From 65dcb5348e333226ba1d76910ca4851e1c8527e0 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Fri, 11 Jun 2021 08:29:15 +0200 Subject: [PATCH 001/226] hacked build changes, api applies cleanly --- Spigot-API-Patches/0001-POM-changes.patch | 4 +- Spigot-API-Patches/0005-Adventure.patch | 12 +- .../0008-Entity-Origin-API.patch | 4 +- .../0059-Entity-fromMobSpawner.patch | 4 +- ...low-plugins-to-use-SLF4J-for-logging.patch | 4 +- ...ld.spawnParticle-API-and-add-Builder.patch | 6 +- .../0118-Entity-getChunk-API.patch | 4 +- .../0153-Material-API-additions.patch | 6 +- .../0172-Entity-getEntitySpawnReason.patch | 4 +- .../0213-Add-entity-liquid-API.patch | 4 +- ...-translation-keys-for-blocks-entitie.patch | 10 +- .../0227-Entity-isTicking.patch | 4 +- ...docs-for-Entity.getEntitySpawnReason.patch | 4 +- .../0263-Added-Vanilla-Entity-Tags.patch | 4 +- ...Cache-the-result-of-Material-isBlock.patch | 8 +- Spigot-API-Patches/0282-Item-Rarity-API.patch | 6 +- ...309-Attributes-API-for-item-defaults.patch | 4 +- .../0002-Paper-config-files.patch | 2 +- Spigot-Server-Patches/0003-MC-Dev-fixes.patch | 2 +- Spigot-Server-Patches/0004-MC-Utils.patch | 6 +- .../0005-Paper-Metrics.patch | 2 +- Spigot-Server-Patches/0010-Adventure.patch | 406 +- ...013-Configurable-fishing-time-ranges.patch | 2 +- ...d-mobs-to-jump-and-take-water-damage.patch | 2 +- ...ck-and-tnt-entities-at-the-specified.patch | 2 +- ...ient-crashes-server-lists-and-Mojang.patch | 4 +- .../0021-Player-affects-spawning-API.patch | 2 +- ...nfigurable-top-of-nether-void-damage.patch | 2 +- .../0033-Optimize-explosions.patch | 2 +- .../0034-Disable-explosion-knockback.patch | 2 +- .../0035-Disable-thunder.patch | 2 +- .../0036-Disable-ice-and-snow.patch | 2 +- .../0041-Use-UserCache-for-player-heads.patch | 2 +- .../0043-Add-PlayerInitialSpawnEvent.patch | 4 +- ...e-informative-in-maxHealth-exception.patch | 2 +- .../0049-Player-Tab-List-and-Title-APIs.patch | 41 +- .../0053-Add-velocity-warnings.patch | 2 +- ...working-with-arrows-stuck-in-living-.patch | 2 +- ...ading-permissions.yml-before-plugins.patch | 2 +- ...064-Handle-Item-Meta-Inconsistencies.patch | 2 +- ...urable-Non-Player-Arrow-Despawn-Rate.patch | 2 +- .../0066-Add-World-Util-Methods.patch | 4 +- ...7-Custom-replacement-for-eaten-items.patch | 2 +- ...th-absorb-values-and-repair-bad-data.patch | 2 +- ...069-Use-a-Shared-Random-for-Entities.patch | 2 +- ...le-spawn-chances-for-skeleton-horses.patch | 2 +- ...ckPhysicsEvent-if-a-plugin-has-a-lis.patch | 4 +- ...Entity-AddTo-RemoveFrom-World-Events.patch | 2 +- ...dDebugInfo-not-initialized-on-client.patch | 2 +- ...g-BlockPlaceEvent-triggering-physics.patch | 2 +- ...nilla-per-world-scoreboard-coloring-.patch | 2 +- ...ityRegainHealthEvent-isFastRegen-API.patch | 2 +- ...-possibility-for-getServer-singleton.patch | 2 +- ...item-frames-performance-and-bug-fixe.patch | 2 +- ...-API-Replenishable-Lootables-Feature.patch | 2 +- ...tem-property-for-disabling-watchdoge.patch | 2 +- .../0099-Optimize-UserCache-Thread-Safe.patch | 2 +- .../0103-Add-server-name-parameter.patch | 2 +- .../0105-Fix-Double-World-Add-issues.patch | 2 +- ...11-Configurable-flying-kick-messages.patch | 2 +- .../0112-Chunk-registration-fixes.patch | 2 +- ...ok-reference-on-Craft-Entity-removal.patch | 2 +- .../0116-Add-EntityZapEvent.patch | 2 +- ...2-Don-t-let-fishinghooks-use-portals.patch | 2 +- .../0128-Optimize-ItemStack.isEmpty.patch | 2 +- ...to-control-if-armour-stands-can-move.patch | 2 +- .../0131-String-based-Action-Bar-API.patch | 2 +- .../0132-Firework-API-s.patch | 2 +- ...rovide-E-TE-Chunk-count-stat-methods.patch | 2 +- .../0135-Enforce-Sync-Player-Saves.patch | 2 +- ...PI-for-Reason-Source-Triggering-play.patch | 12 +- .../0138-Cap-Entity-Collisions.patch | 4 +- ...more-aggressive-in-the-chunk-unload-.patch | 2 +- .../0141-Do-not-let-armorstands-drown.patch | 2 +- ...le-async-calls-to-restart-the-server.patch | 2 +- ...property-to-disable-book-size-limits.patch | 2 +- ...urable-option-to-disable-creeper-lin.patch | 2 +- .../0148-Item-canEntityPickup.patch | 2 +- ...player-logins-during-server-shutdown.patch | 2 +- .../0160-ProfileWhitelistVerifyEvent.patch | 2 +- .../0161-Fix-this-stupid-bullshit.patch | 2 +- .../0166-LivingEntity-setKiller.patch | 2 +- ...n-prefixes-using-Log4J-configuration.patch | 2 +- .../0169-Add-PlayerJumpEvent.patch | 2 +- ...nt-protocol-version-and-virtual-host.patch | 4 +- ...rt-serverside-behavior-of-keepalives.patch | 2 +- .../0175-Add-PlayerArmorChangeEvent.patch | 2 +- .../0185-PreCreatureSpawnEvent.patch | 2 +- ...nt-extended-PaperServerListPingEvent.patch | 2 +- ...plement-EntityKnockbackByEntityEvent.patch | 4 +- ...239-Use-asynchronous-Log4j-2-loggers.patch | 2 +- ...ies-option-to-debug-dupe-uuid-issues.patch | 2 +- ...7-Vanished-players-don-t-have-rights.patch | 2 +- ...dd-some-Debug-to-Chunk-Entity-slices.patch | 2 +- ...ead-Entities-in-entityList-iteration.patch | 2 +- ...nd-make-tab-spam-limits-configurable.patch | 2 +- ...-ray-tracing-methods-to-LivingEntity.patch | 2 +- ...ble-connection-throttle-kick-message.patch | 2 +- .../0294-Add-sun-related-API.patch | 2 +- ...tator-target-events-and-improve-impl.patch | 2 +- ...event-players-from-moving-into-unloa.patch | 2 +- ...er-Thread-Pool-and-Thread-Priorities.patch | 2 +- .../0306-Optimize-World-Time-Updates.patch | 2 +- .../0311-Book-Size-Limits.patch | 2 +- .../0317-Add-PlayerConnectionCloseEvent.patch | 2 +- .../0340-Server-Tick-Events.patch | 2 +- ...l-to-changed-postToMainThread-method.patch | 2 +- .../0356-Chunk-debug-command.patch | 2 +- .../0361-incremental-chunk-saving.patch | 4 +- Spigot-Server-Patches/0362-Anti-Xray.patch | 2 +- ...-being-ticked-when-notifying-navigat.patch | 2 +- ...etChunkIfLoadedImmediately-in-places.patch | 4 +- .../0370-Reduce-sync-loads.patch | 4 +- ...if-we-have-a-custom-Bukkit-generator.patch | 2 +- ...ement-optional-per-player-mob-spawns.patch | 2 +- ...revent-consuming-the-wrong-itemstack.patch | 2 +- .../0388-Optimize-Hoppers.patch | 2 +- ...timise-IEntityAccess-getPlayerByUUID.patch | 2 +- .../0395-Lag-compensate-eating.patch | 2 +- .../0400-Entity-Activation-Range-2.0.patch | 2 +- ...e-getChunkAt-calls-for-loaded-chunks.patch | 2 +- ...ow-overriding-the-java-version-check.patch | 2 +- .../0406-Optimise-random-block-ticking.patch | 2 +- .../0409-Make-the-GUI-graph-fancier.patch | 2 +- ...imise-TickListServer-by-rewriting-it.patch | 4 +- ...re-Entity-is-never-double-registered.patch | 4 +- ...ering-entities-from-unloading-chunks.patch | 2 +- ...-PlayerChunkMap-adds-crashing-server.patch | 2 +- ...ptimize-Collision-to-not-load-chunks.patch | 2 +- .../0427-Increase-Light-Queue-Size.patch | 2 +- ...-Add-tick-times-API-and-mspt-command.patch | 2 +- ...ions-until-after-entity-ticking-is-d.patch | 2 +- .../0436-Improved-Watchdog-Support.patch | 4 +- ...-entity-collision-code-if-not-needed.patch | 2 +- ...oviderServer-s-chunk-level-checking-.patch | 2 +- ...Load-Chunks-for-Login-Asynchronously.patch | 8 +- ...PlayerAttackEntityCooldownResetEvent.patch | 2 +- .../0458-Implement-Brigadier-Mojang-API.patch | 2 +- .../0459-Villager-Restocks-API.patch | 2 +- ...PickItem-Packet-and-kick-for-invalid.patch | 2 +- .../0461-Expose-game-version.patch | 2 +- ...-per-thread-native-byte-buffer-cache.patch | 2 +- ...tance-map-to-optimise-entity-tracker.patch | 4 +- .../0469-Add-villager-reputation-API.patch | 2 +- ...1-Fix-PotionEffect-ignores-icon-flag.patch | 2 +- ...Wait-for-Async-Tasks-during-shutdown.patch | 2 +- ...k-Priority-Urgency-System-for-Chunks.patch | 2 +- ...ookup-for-Treasure-Maps-Fixes-lag-fr.patch | 2 +- ...-desync-in-playerconnection-causing-.patch | 2 +- ...05-Add-permission-for-command-blocks.patch | 2 +- ...WorldBorder-collision-checks-and-air.patch | 2 +- ...ld-Difficulty-Remembering-Difficulty.patch | 4 +- .../0519-Add-entity-liquid-API.patch | 2 +- ...k-for-portal-on-world-gen-entity-add.patch | 2 +- ...ix-Concurrency-issue-in-WeightedList.patch | 44 +- .../0538-Incremental-player-saving.patch | 2 +- ...geEvent-not-firing-for-all-use-cases.patch | 2 +- .../0557-Buffer-joins-to-world.patch | 2 +- ...rs-not-working-in-some-kick-messages.patch | 4 +- .../0565-Cache-block-data-strings.patch | 2 +- ...ortation-and-cancel-velocity-if-tele.patch | 2 +- ...p-capture-to-capture-all-items-added.patch | 2 +- ...-non-whitelisted-player-when-white-l.patch | 2 +- ...r-large-move-vectors-crashing-server.patch | 2 +- .../0590-Add-ignore-discounts-API.patch | 2 +- .../0595-Add-API-for-quit-reason.patch | 2 +- ...602-Add-LivingEntity-clearActiveItem.patch | 2 +- ...-should-not-bypass-cramming-gamerule.patch | 2 +- ...g-for-servers-not-running-on-Java-16.patch | 2 +- ...ing-zombie-villager-discount-exploit.patch | 2 +- .../0619-added-PlayerTradeEvent.patch | 2 +- ...4-Added-ServerResourcesReloadedEvent.patch | 2 +- ...pty-commands-shall-not-be-dispatched.patch | 2 +- .../0643-Remove-stale-POIs.patch | 2 +- ...n-for-requiring-a-player-participant.patch | 2 +- ...0652-Configurable-max-leash-distance.patch | 2 +- ...Leash-variable-to-EntityUnleashEvent.patch | 2 +- ...ce-map-update-when-spawning-disabled.patch | 2 +- .../0664-EntityMoveEvent.patch | 2 +- ...-entity-allow-attribute-registration.patch | 2 +- .../0672-misc-debugging-dumps.patch | 2 +- .../0675-Expose-Tracked-Players.patch | 2 +- ...Fix-Wither-hostility-towards-players.patch | 2 +- ...0682-fix-converting-txt-to-json-file.patch | 2 +- ...telist-use-configurable-kick-message.patch | 2 +- ...ignore-result-of-PlayerEditBookEvent.patch | 2 +- ...ent-suggestion-tooltips-in-AsyncTabC.patch | 2 +- ...ItemConsumeEvent-cancelling-properly.patch | 2 +- .../0703-Add-bypass-host-check.patch | 2 +- .../0714-More-World-API.patch | 2 +- ...s-to-convert-between-Component-and-B.patch | 2 +- ...eacon-activation-deactivation-events.patch | 2 +- ...-address-to-AsyncPlayerPreLoginEvent.patch | 2 +- ...-option-to-load-extra-plugin-jars-no.patch | 4 +- ...x-and-optimise-world-force-upgrading.patch | 2 +- .../0739-Add-Mob-lookAt-API.patch | 2 +- .../0740-Add-Unix-domain-socket-support.patch | 2 +- .../0746-Add-PlayerKickEvent-causes.patch | 2 +- bukkit-e3c5450d-combined.csrg | 5198 +++++++++++++++++ .../0049-Player-Tab-List-and-Title-APIs.patch | 31 + scripts/remap.sh | 38 +- work/BuildData | 2 +- work/Bukkit | 2 +- work/CraftBukkit | 2 +- work/Spigot | 2 +- 205 files changed, 5721 insertions(+), 547 deletions(-) create mode 100644 bukkit-e3c5450d-combined.csrg create mode 100644 removed/1.17/0049-Player-Tab-List-and-Title-APIs.patch diff --git a/Spigot-API-Patches/0001-POM-changes.patch b/Spigot-API-Patches/0001-POM-changes.patch index 2cd563eafa..b6c98e0a08 100644 --- a/Spigot-API-Patches/0001-POM-changes.patch +++ b/Spigot-API-Patches/0001-POM-changes.patch @@ -5,7 +5,7 @@ Subject: [PATCH] POM changes diff --git a/pom.xml b/pom.xml -index 0223e94c1243a58955f858c8bf6d5df4ca8cf0ec..fd663f5471516c3ebbab07c27197e5df48c481e6 100644 +index debe5bd7adb1f41e8a6878a8545de4bfcad1a590..d7cf64f05d0a2f5b186ca13b2b88e390abe84226 100644 --- a/pom.xml +++ b/pom.xml @@ -2,33 +2,34 @@ @@ -22,7 +22,7 @@ index 0223e94c1243a58955f858c8bf6d5df4ca8cf0ec..fd663f5471516c3ebbab07c27197e5df - spigot-api + com.destroystokyo.paper + paper-api - 1.16.5-R0.1-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar - Spigot-API diff --git a/Spigot-API-Patches/0005-Adventure.patch b/Spigot-API-Patches/0005-Adventure.patch index 4e1baf14fe..bbfafdf464 100644 --- a/Spigot-API-Patches/0005-Adventure.patch +++ b/Spigot-API-Patches/0005-Adventure.patch @@ -7,7 +7,7 @@ Co-authored-by: zml Co-authored-by: Jake Potrebic diff --git a/pom.xml b/pom.xml -index 9aafdcc49ed83b403abb96891008103e6d6a69fa..1ced7a212684cee8faf07fa9a083adcd47be7fcb 100644 +index 1ebc4c096638128194cea9c2a4131f901e7d6896..cae43ce5c1287a4cd117fd069d34ebc1b64b7fdb 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,7 @@ @@ -1328,7 +1328,7 @@ index a6b9e4f158583e5932bf8ca210d531857e9f5360..7abdbf43e2f52e8e9e0f7bd7c7a58baf throw new UnsupportedOperationException("Not supported yet."); } diff --git a/src/main/java/org/bukkit/Sound.java b/src/main/java/org/bukkit/Sound.java -index 768f35c19c4557236bded5f4a85f48a2b2b2a9e6..d0ce64412276512cde133937a85a3340a70eea6d 100644 +index 2c8cc0c2af4741df9ae594ab9c436dea5347167c..445b6bf18e6ee26fe6cafca8cf5f1775bcd72d1e 100644 --- a/src/main/java/org/bukkit/Sound.java +++ b/src/main/java/org/bukkit/Sound.java @@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; @@ -1340,7 +1340,7 @@ index 768f35c19c4557236bded5f4a85f48a2b2b2a9e6..d0ce64412276512cde133937a85a3340 AMBIENT_BASALT_DELTAS_ADDITIONS("ambient.basalt_deltas.additions"), AMBIENT_BASALT_DELTAS_LOOP("ambient.basalt_deltas.loop"), -@@ -1016,4 +1016,12 @@ public enum Sound implements Keyed { +@@ -1214,4 +1214,12 @@ public enum Sound implements Keyed { public NamespacedKey getKey() { return key; } @@ -1412,7 +1412,7 @@ index bc4417d8ffa92a78f690bfa5705d3e42cdc11fd2..d3519fa5b99e2888a194c63824155377 * Returns a list of entities within a bounding box centered around a * Location. diff --git a/src/main/java/org/bukkit/block/Sign.java b/src/main/java/org/bukkit/block/Sign.java -index 7e3cf00e49c66023bf46c298ef46c00e8c3c2caf..6ea9b54d95d80070c01a612c0ce2ab37f0b4ad41 100644 +index a52dff9ef1c1cd7d3705e66510dfa2c91119539c..cdcf02ff9e80f5908a8fa22e82701445d5e2d298 100644 --- a/src/main/java/org/bukkit/block/Sign.java +++ b/src/main/java/org/bukkit/block/Sign.java @@ -7,13 +7,48 @@ import org.jetbrains.annotations.NotNull; @@ -1651,7 +1651,7 @@ index 9566e4306ada5e82dede0f002aa06da12c44996b..4d5f0837bd0e02a30c943d8969fb6b13 + // Paper end } diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index b71530e94569f8ade829e655e3a89ec70215ea39..b21fe6c631d5a6cd52f133786270c8f5ad0dafc4 100644 +index 0831f2519a32cf1c5c7d5b72864bcb1c22c52eda..03e12de470f983e89a473c4e42c21941085b1d37 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java @@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable; @@ -1663,7 +1663,7 @@ index b71530e94569f8ade829e655e3a89ec70215ea39..b21fe6c631d5a6cd52f133786270c8f5 /** * Gets the entity's current position -@@ -602,4 +602,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent +@@ -648,4 +648,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent @Override Spigot spigot(); // Spigot end diff --git a/Spigot-API-Patches/0008-Entity-Origin-API.patch b/Spigot-API-Patches/0008-Entity-Origin-API.patch index b26d5933f8..626916f4f7 100644 --- a/Spigot-API-Patches/0008-Entity-Origin-API.patch +++ b/Spigot-API-Patches/0008-Entity-Origin-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Entity Origin API diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 41a1bc45cc5eb7f19374115ade7f5328c7fc1dae..e9d0d507b47b0347b975b1a83f5ae70dca5587b8 100644 +index 03e12de470f983e89a473c4e42c21941085b1d37..fdce246aecac775c3ff4a028c307b09762505258 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -609,5 +609,15 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent +@@ -655,5 +655,15 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.customName()))); } diff --git a/Spigot-API-Patches/0059-Entity-fromMobSpawner.patch b/Spigot-API-Patches/0059-Entity-fromMobSpawner.patch index 6912236f76..73b4016c92 100644 --- a/Spigot-API-Patches/0059-Entity-fromMobSpawner.patch +++ b/Spigot-API-Patches/0059-Entity-fromMobSpawner.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Entity#fromMobSpawner() diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index e9d0d507b47b0347b975b1a83f5ae70dca5587b8..feb9507a972bf797144a01adeeaac83ec2bd165a 100644 +index fdce246aecac775c3ff4a028c307b09762505258..fdc95c87a6020bdcaee5b0b8ab5a996c0e241b33 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -619,5 +619,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent +@@ -665,5 +665,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent */ @Nullable Location getOrigin(); diff --git a/Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch b/Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch index 1f987148b3..58225ea7be 100644 --- a/Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch +++ b/Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch @@ -14,11 +14,11 @@ it without having to shade it in the plugin and going through several layers of logging abstraction. diff --git a/pom.xml b/pom.xml -index 7ec7e6047193a6b390d24f6d2722e35d1d36830d..6b71d9a397dd5b72320402a47b8e7197d24e061c 100644 +index 2c757ffb2253748c6a81f9b373290108209b6ff2..8cf6e1f78d4c1ae388bb478700d5dceaab65c4e7 100644 --- a/pom.xml +++ b/pom.xml @@ -144,6 +144,13 @@ - 20.1.0 + 21.0.1 provided + diff --git a/Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch b/Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch index ee5d06483d..da01d6d5c3 100644 --- a/Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch +++ b/Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch @@ -493,10 +493,10 @@ index 0000000000000000000000000000000000000000..06f1602f5b327705f726d0a99dd6b95e + } +} diff --git a/src/main/java/org/bukkit/Particle.java b/src/main/java/org/bukkit/Particle.java -index b32de827cf8d1780861c271b4215276fdaab7165..1020002ff7127877db2d7e096f2c521751bf13a7 100644 +index c5315ee1ed435c39a3ae298e248b67c5dc291497..687a62707c8021f87e03d6bc358b3b4e6da331e7 100644 --- a/src/main/java/org/bukkit/Particle.java +++ b/src/main/java/org/bukkit/Particle.java -@@ -106,6 +106,17 @@ public enum Particle { +@@ -123,6 +123,17 @@ public enum Particle { return dataType; } @@ -515,7 +515,7 @@ index b32de827cf8d1780861c271b4215276fdaab7165..1020002ff7127877db2d7e096f2c5217 * Options which can be applied to redstone dust particles - a particle * color and size. diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 27bbddac946879149ec43d428417c4707f6a9a8c..fe125ae7bbd7c9dde9db7838169e4819416e148d 100644 +index 6cc9c7fc913f229c4869a976e73253acb74fcda3..ca2b1cbff153c53ec9182e44a1979350bacd695b 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -2592,7 +2592,57 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad diff --git a/Spigot-API-Patches/0118-Entity-getChunk-API.patch b/Spigot-API-Patches/0118-Entity-getChunk-API.patch index 8eaf47d2a6..1a598ac537 100644 --- a/Spigot-API-Patches/0118-Entity-getChunk-API.patch +++ b/Spigot-API-Patches/0118-Entity-getChunk-API.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Entity#getChunk API Get the chunk the entity is currently registered to diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index feb9507a972bf797144a01adeeaac83ec2bd165a..9b8823279524d1c1566176c589aa5794eb8aafbc 100644 +index fdc95c87a6020bdcaee5b0b8ab5a996c0e241b33..76c20d84fee011af4f1850d0cab8ac00a69f2b34 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java @@ -3,6 +3,7 @@ package org.bukkit.entity; @@ -17,7 +17,7 @@ index feb9507a972bf797144a01adeeaac83ec2bd165a..9b8823279524d1c1566176c589aa5794 import org.bukkit.EntityEffect; import org.bukkit.Location; import org.bukkit.Nameable; -@@ -626,5 +627,13 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent +@@ -672,5 +673,13 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent * @return True if entity spawned from a mob spawner */ boolean fromMobSpawner(); diff --git a/Spigot-API-Patches/0153-Material-API-additions.patch b/Spigot-API-Patches/0153-Material-API-additions.patch index d19f497e71..629bed4425 100644 --- a/Spigot-API-Patches/0153-Material-API-additions.patch +++ b/Spigot-API-Patches/0153-Material-API-additions.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Material API additions diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index e4d0dc26fb2f2c4435e11b3460d8c93d6a6fc47f..2b53e68e96ea346a6f2b5cadcf9f81b2c231c408 100644 +index a9769ae0bad61d200c70331eba0b655da4ba03b2..9c28351c7c3f60c6a3b4020329344f91efeedae1 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java -@@ -87,6 +87,7 @@ import org.jetbrains.annotations.Nullable; +@@ -98,6 +98,7 @@ import org.jetbrains.annotations.Nullable; /** * An enum of all material IDs accepted by the official server and client */ @@ -16,7 +16,7 @@ index e4d0dc26fb2f2c4435e11b3460d8c93d6a6fc47f..2b53e68e96ea346a6f2b5cadcf9f81b2 public enum Material implements Keyed { // AIR(9648, 0), -@@ -3563,6 +3564,22 @@ public enum Material implements Keyed { +@@ -3976,6 +3977,22 @@ public enum Material implements Keyed { } } diff --git a/Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch b/Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch index cf940ce2fe..080a5c3186 100644 --- a/Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch +++ b/Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch @@ -10,10 +10,10 @@ persistenting Living Entity, SPAWNER for spawners, or DEFAULT since data was not stored. diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index c137199ed0537874010f1abf311a9cbee56831ac..2622a2f5c9e2cb43aff7ef9eac2dcdb3fd8fad04 100644 +index 4b1f9b0ad5dc9ad6f33fddafc376b6f983a556ef..5b382091b1466b25ad42325d5808785a8e948552 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -662,5 +662,11 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent +@@ -708,5 +708,11 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent */ @NotNull Chunk getChunk(); diff --git a/Spigot-API-Patches/0213-Add-entity-liquid-API.patch b/Spigot-API-Patches/0213-Add-entity-liquid-API.patch index c13d4c2cb3..c38113b716 100644 --- a/Spigot-API-Patches/0213-Add-entity-liquid-API.patch +++ b/Spigot-API-Patches/0213-Add-entity-liquid-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add entity liquid API diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 2622a2f5c9e2cb43aff7ef9eac2dcdb3fd8fad04..75cebfca7b436ef30b718bba7e0566d047e5c61a 100644 +index 5b382091b1466b25ad42325d5808785a8e948552..ecb5595332ab493224d06a75904e142ab541aad9 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -668,5 +668,35 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent +@@ -714,5 +714,35 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent */ @NotNull org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason(); diff --git a/Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch index b6751c5ef8..bfa151e84b 100644 --- a/Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch +++ b/Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add a way to get translation keys for blocks, entities and diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 2b53e68e96ea346a6f2b5cadcf9f81b2c231c408..e453e5eb7245aad3ecbb19652ebb34abe030c0a9 100644 +index 9c28351c7c3f60c6a3b4020329344f91efeedae1..69c85c3a1f45476f7de0a9399852d82eeb4f9c86 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java -@@ -3578,6 +3578,16 @@ public enum Material implements Keyed { +@@ -3991,6 +3991,16 @@ public enum Material implements Keyed { } return false; } @@ -84,10 +84,10 @@ index e1cc36fbe808973227c0e8ca7166453235c90279..e6647c45f65bae916759cd899256f813 // Paper end } diff --git a/src/main/java/org/bukkit/entity/EntityType.java b/src/main/java/org/bukkit/entity/EntityType.java -index 774363a8186b3861f10c0452ac63726cae365169..692b75eb78405874077c850bfc72e247ccc80860 100644 +index 9be5371c7f398d0ec8241403661415ff40661067..f415b61b0d4b57e1557aaf240a0f2ad5915035fc 100644 --- a/src/main/java/org/bukkit/entity/EntityType.java +++ b/src/main/java/org/bukkit/entity/EntityType.java -@@ -414,4 +414,15 @@ public enum EntityType implements Keyed { +@@ -419,4 +419,15 @@ public enum EntityType implements Keyed { public boolean isAlive() { return living; } @@ -104,7 +104,7 @@ index 774363a8186b3861f10c0452ac63726cae365169..692b75eb78405874077c850bfc72e247 + } } diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 15b48ad1ba5bcf7394fb3f52ce2cc6baa6632f66..c236cb81b7ec7993b63da929c0492564e75581ee 100644 +index 9a878e4fde31c015e2f3fdf365d5d16c30198685..bd96c06aca1fc18807e65c34f399ce2ebe891816 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -851,5 +851,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor diff --git a/Spigot-API-Patches/0227-Entity-isTicking.patch b/Spigot-API-Patches/0227-Entity-isTicking.patch index 3856ba234e..315c89bf3b 100644 --- a/Spigot-API-Patches/0227-Entity-isTicking.patch +++ b/Spigot-API-Patches/0227-Entity-isTicking.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Entity#isTicking diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 75cebfca7b436ef30b718bba7e0566d047e5c61a..2cc501b74741bdbdc40d1b135725f18c4d36dc2b 100644 +index ecb5595332ab493224d06a75904e142ab541aad9..4ed8c74f874dbd1017764d7592acfdafbc5d5fe1 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -698,5 +698,10 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent +@@ -744,5 +744,10 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent * Check if entity is in lava */ public boolean isInLava(); diff --git a/Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch b/Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch index 7798b89d21..2947f78299 100644 --- a/Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch +++ b/Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Clarify the Javadocs for Entity.getEntitySpawnReason() diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 2cc501b74741bdbdc40d1b135725f18c4d36dc2b..428daeb04d0a35a443467e2f657d2356bcfdd7d7 100644 +index 4ed8c74f874dbd1017764d7592acfdafbc5d5fe1..14470b23f7b4102cf2dca777bc832ebcbcd5edc6 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -664,7 +664,7 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent +@@ -710,7 +710,7 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent Chunk getChunk(); /** diff --git a/Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch b/Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch index 9916b1726b..53c933017b 100644 --- a/Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch +++ b/Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Added Vanilla Entity Tags diff --git a/src/main/java/org/bukkit/Tag.java b/src/main/java/org/bukkit/Tag.java -index 3c2a6a2167eab43097f5d6ccf1550e12795fc0b6..c1ec099448d57f2a5f973ac5b4e4a25b79ea2112 100644 +index 88ea8b6c5c2c4d2116f646341de62590718bc28c..a2da2cbef6c09b9defbdf97e79cfb3efd742d439 100644 --- a/src/main/java/org/bukkit/Tag.java +++ b/src/main/java/org/bukkit/Tag.java -@@ -425,6 +425,32 @@ public interface Tag extends Keyed { +@@ -589,6 +589,32 @@ public interface Tag extends Keyed { * Vanilla fluid tag representing water and flowing water. */ Tag FLUIDS_WATER = Bukkit.getTag(REGISTRY_FLUIDS, NamespacedKey.minecraft("water"), Fluid.class); diff --git a/Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch b/Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch index eaa498baea..7eca03bdf5 100644 --- a/Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch +++ b/Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Cache the result of Material#isBlock diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index e453e5eb7245aad3ecbb19652ebb34abe030c0a9..112c3f035ec7e7a7cae939264e0af4c6f4450abd 100644 +index 69c85c3a1f45476f7de0a9399852d82eeb4f9c86..0f081835c0484e15fca4fadaa27e90cadd394276 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java -@@ -3522,6 +3522,7 @@ public enum Material implements Keyed { +@@ -3935,6 +3935,7 @@ public enum Material implements Keyed { public final Class data; private final boolean legacy; private final NamespacedKey key; @@ -16,7 +16,7 @@ index e453e5eb7245aad3ecbb19652ebb34abe030c0a9..112c3f035ec7e7a7cae939264e0af4c6 private Material(final int id) { this(id, 64); -@@ -3719,6 +3720,11 @@ public enum Material implements Keyed { +@@ -4132,6 +4133,11 @@ public enum Material implements Keyed { * @return true if this material is a block */ public boolean isBlock() { @@ -28,7 +28,7 @@ index e453e5eb7245aad3ecbb19652ebb34abe030c0a9..112c3f035ec7e7a7cae939264e0af4c6 switch (this) { // case ACACIA_BUTTON: -@@ -4664,6 +4670,7 @@ public enum Material implements Keyed { +@@ -5213,6 +5219,7 @@ public enum Material implements Keyed { static { for (Material material : values()) { BY_NAME.put(material.name(), material); diff --git a/Spigot-API-Patches/0282-Item-Rarity-API.patch b/Spigot-API-Patches/0282-Item-Rarity-API.patch index 1d73fff91a..8f0f4fc977 100644 --- a/Spigot-API-Patches/0282-Item-Rarity-API.patch +++ b/Spigot-API-Patches/0282-Item-Rarity-API.patch @@ -39,10 +39,10 @@ index 0000000000000000000000000000000000000000..74ef8395cc040ce488c2acaa416db202 + } +} diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 112c3f035ec7e7a7cae939264e0af4c6f4450abd..9b1c9e60dba9ea3ef8d8e164f13dd76daf57db8e 100644 +index 0f081835c0484e15fca4fadaa27e90cadd394276..07b8b913434bb575df8670230d693b2d4cec2571 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java -@@ -3589,6 +3589,17 @@ public enum Material implements Keyed { +@@ -4002,6 +4002,17 @@ public enum Material implements Keyed { public String getTranslationKey() { return Bukkit.getUnsafe().getTranslationKey(this); } @@ -88,7 +88,7 @@ index 84eda68281c6c6968d95b1313a33696c3a9980d4..bcd10b2c9255d778b678310febf19373 // Paper end } diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index c236cb81b7ec7993b63da929c0492564e75581ee..7929a00a3e93e0b6a4df99013e0da5bcfecd678b 100644 +index bd96c06aca1fc18807e65c34f399ce2ebe891816..f72d3d62d61755bbaf1950ebcb228ce95d1faf58 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -863,5 +863,15 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor diff --git a/Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch b/Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch index 2ca00f5783..fa1b8ce93a 100644 --- a/Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch +++ b/Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Attributes API for item defaults diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 9b1c9e60dba9ea3ef8d8e164f13dd76daf57db8e..e2b3470e3c9a97671723f5a67f722fb86fb07fbf 100644 +index 07b8b913434bb575df8670230d693b2d4cec2571..397591da25fbb0e4d3012431df70d661d9bc9188 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java -@@ -3600,6 +3600,19 @@ public enum Material implements Keyed { +@@ -4013,6 +4013,19 @@ public enum Material implements Keyed { public io.papermc.paper.inventory.ItemRarity getItemRarity() { return Bukkit.getUnsafe().getItemRarity(this); } diff --git a/Spigot-Server-Patches/0002-Paper-config-files.patch b/Spigot-Server-Patches/0002-Paper-config-files.patch index 674e55cfdd..59424f2288 100644 --- a/Spigot-Server-Patches/0002-Paper-config-files.patch +++ b/Spigot-Server-Patches/0002-Paper-config-files.patch @@ -753,7 +753,7 @@ index f03d83440291a329f5a1922c8710ed975025fdbb..82f5b3387f9e71ae258111b719698662 + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index c6417a0594ffe2d3650ec54d44e575e347a1f724..3b48799d084f14722f815cb35cbd48b618380fca 100644 +index 46a16e31775b28c44f95a8ac5545ebcb656c74b6..05aedca561919a12ced1925c5cc9af585bb04523 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -129,6 +129,14 @@ public class Main { diff --git a/Spigot-Server-Patches/0003-MC-Dev-fixes.patch b/Spigot-Server-Patches/0003-MC-Dev-fixes.patch index b8a1a2f446..1f1f3bab60 100644 --- a/Spigot-Server-Patches/0003-MC-Dev-fixes.patch +++ b/Spigot-Server-Patches/0003-MC-Dev-fixes.patch @@ -236,7 +236,7 @@ index ab08336043d4f558434ed1f38d25cc555ace1ac0..a892521db1197369bf6363bd2f5da24b }); this.b = Lists.newArrayList(); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index a95c52035177cb86c7e3a580d5c26a5dd20a17e2..81cff54c93bc04d19e3cc0f5307799c62d139ab2 100644 +index 6977255868dbc0a96973095fff2eb935ecf4f4fc..6d843bb69b1848ae77098dc3f45d85f405fc24cd 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1675,9 +1675,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant clazz, Object instance) { diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index f08110a22646716bcdf6a8d25ec44df8d78e85a4..23c1ba33903f8913a33332d06b2fd1aa3c90f1a1 100644 +index c04d912adf0da8f7a5b75dd2f58739a11ca31601..3c93a497a790b8d800852db2ac48feca41f45cef 100644 --- a/src/main/java/org/spigotmc/SpigotConfig.java +++ b/src/main/java/org/spigotmc/SpigotConfig.java @@ -83,6 +83,7 @@ public class SpigotConfig diff --git a/Spigot-Server-Patches/0010-Adventure.patch b/Spigot-Server-Patches/0010-Adventure.patch index d871f43df4..51208a5517 100644 --- a/Spigot-Server-Patches/0010-Adventure.patch +++ b/Spigot-Server-Patches/0010-Adventure.patch @@ -945,7 +945,7 @@ index 75e38f05c10713f773a8763100dfc0777521dba6..cd93f99e939438c572a4258d299a6038 @@ -61,6 +61,7 @@ public enum EnumChatFormat { return !this.A && this != EnumChatFormat.RESET; } - + + @Nullable public Integer getHexValue() { return this.e(); } // Paper - OBFHELPER @Nullable public Integer e() { @@ -953,7 +953,7 @@ index 75e38f05c10713f773a8763100dfc0777521dba6..cd93f99e939438c572a4258d299a6038 @@ -84,6 +85,18 @@ public enum EnumChatFormat { return s == null ? null : (EnumChatFormat) EnumChatFormat.w.get(c(s)); } - + + // Paper start + @Nullable public static EnumChatFormat getByHexValue(int i) { + for (EnumChatFormat value : values()) { @@ -976,7 +976,7 @@ index e26ef49d9dde8ed0fb4267b48cb597563967f313..0e41fdb6ba711fbd2240d62e2030b3a1 @@ -43,6 +43,7 @@ public class NBTTagString implements NBTBase { this.data = s; } - + + public static NBTTagString create(final String value) { return a(value); } // Paper - OBFHELPER public static NBTTagString a(String s) { return s.isEmpty() ? NBTTagString.b : new NBTTagString(s); @@ -995,16 +995,16 @@ index 5413bf93f7f0f4491fca1f07c47a925fdace7751..5f1c5dd7902f6cff5acae05e8c6bf58a import java.io.IOException; @@ -44,6 +45,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit public class PacketDataSerializer extends ByteBuf { - + private final ByteBuf a; + public java.util.Locale adventure$locale; // Paper - + public PacketDataSerializer(ByteBuf bytebuf) { this.a = bytebuf; @@ -165,8 +167,15 @@ public class PacketDataSerializer extends ByteBuf { return IChatBaseComponent.ChatSerializer.a(this.e(262144)); } - + + // Paper start + public PacketDataSerializer writeComponent(final net.kyori.adventure.text.Component component) { + return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); @@ -1016,16 +1016,16 @@ index 5413bf93f7f0f4491fca1f07c47a925fdace7751..5f1c5dd7902f6cff5acae05e8c6bf58a + //return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); // Paper - comment + return this.writeUtf(PaperAdventure.asJsonString(ichatbasecomponent, this.adventure$locale), 262144); // Paper } - + public > T a(Class oclass) { @@ -349,6 +358,7 @@ public class PacketDataSerializer extends ByteBuf { return this.a(s, 32767); } - + + public PacketDataSerializer writeUtf(final String string, final int maxLength) { return this.a(string, maxLength); } // Paper - OBFHELPER public PacketDataSerializer a(String s, int i) { byte[] abyte = s.getBytes(StandardCharsets.UTF_8); - + diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java index dc8cc8d6c00176c8562086282f726dc1b24b2c65..2f6da89d6b25ba5144ec15b1bf0e8ed13278e85e 100644 --- a/src/main/java/net/minecraft/network/PacketEncoder.java @@ -1043,23 +1043,23 @@ index dc8cc8d6c00176c8562086282f726dc1b24b2c65..2f6da89d6b25ba5144ec15b1bf0e8ed1 } else { PacketDataSerializer packetdataserializer = new PacketDataSerializer(bytebuf); + packetdataserializer.adventure$locale = channelhandlercontext.channel().attr(PaperAdventure.LOCALE_ATTRIBUTE).get(); // Paper - + packetdataserializer.d(integer); - + diff --git a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java index 85140d961722e86abfe7006a0ad752751e73c721..e96fa348a37a39c381b6659f612232933686c2a7 100644 --- a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java +++ b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java @@ -1,5 +1,6 @@ package net.minecraft.network.chat; - + +import io.papermc.paper.adventure.AdventureComponent; // Paper import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; @@ -111,6 +112,7 @@ public interface IChatBaseComponent extends Message, IChatFormatted, Iterable { - + private IChatBaseComponent a; + public net.kyori.adventure.text.Component adventure$message; // Paper public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot private ChatMessageType b; private UUID c; @@ -32,6 +33,11 @@ public class PacketPlayOutChat implements Packet { - + @Override public void b(PacketDataSerializer packetdataserializer) throws IOException { + // Paper start @@ -1123,18 +1123,18 @@ index 0268b8e6595ee919bcd55a74ba872a2b7d2a17d8..4ff73a4fc5e8a8739e57d2bac6507681 --- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java +++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java @@ -9,6 +9,10 @@ public class PacketPlayOutPlayerListHeaderFooter implements Packet { - - private PacketPlayOutTitle.EnumTitleAction a; - private IChatBaseComponent b; -+ public net.kyori.adventure.text.Component adventure$text; // Paper - private int c; - private int d; - private int e; -@@ -51,6 +52,11 @@ public class PacketPlayOutTitle implements Packet { - public void b(PacketDataSerializer packetdataserializer) throws IOException { - packetdataserializer.a((Enum) this.a); - if (this.a == PacketPlayOutTitle.EnumTitleAction.TITLE || this.a == PacketPlayOutTitle.EnumTitleAction.SUBTITLE || this.a == PacketPlayOutTitle.EnumTitleAction.ACTIONBAR) { -+ // Paper start -+ if (this.adventure$text != null) { -+ packetdataserializer.writeComponent(this.adventure$text); -+ } else -+ // Paper end - packetdataserializer.a(this.b); - } - diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java index 3fa2e077912949f6ca7b14da93c2206215ebcc7e..5ef8b66cf266488df75ce7399596f75273b90761 100644 --- a/src/main/java/net/minecraft/server/level/EntityPlayer.java @@ -1184,7 +1160,7 @@ index 3fa2e077912949f6ca7b14da93c2206215ebcc7e..5ef8b66cf266488df75ce7399596f752 import org.bukkit.GameMode; import org.bukkit.Location; @@ -212,6 +213,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - + // CraftBukkit start public String displayName; + public net.kyori.adventure.text.Component adventure$displayName; // Paper @@ -1192,7 +1168,7 @@ index 3fa2e077912949f6ca7b14da93c2206215ebcc7e..5ef8b66cf266488df75ce7399596f752 public org.bukkit.Location compassTarget; public int newExp = 0; @@ -242,6 +244,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - + // CraftBukkit start this.displayName = this.getName(); + this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getName()); // Paper @@ -1200,21 +1176,21 @@ index 3fa2e077912949f6ca7b14da93c2206215ebcc7e..5ef8b66cf266488df75ce7399596f752 this.maxHealthCache = this.getMaxHealth(); } @@ -695,23 +698,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - + IChatBaseComponent defaultMessage = this.getCombatTracker().getDeathMessage(); - + - String deathmessage = defaultMessage.getString(); - org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, deathmessage, keepInventory); + org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure - + // SPIGOT-943 - only call if they have an inventory open if (this.activeContainer != this.defaultContainer) { this.closeInventory(); } - + - String deathMessage = event.getDeathMessage(); + net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure - + - if (deathMessage != null && deathMessage.length() > 0 && flag) { // TODO: allow plugins to override? - IChatBaseComponent ichatbasecomponent; - if (deathMessage.equals(deathmessage)) { @@ -1224,20 +1200,20 @@ index 3fa2e077912949f6ca7b14da93c2206215ebcc7e..5ef8b66cf266488df75ce7399596f752 - } + if (deathMessage != null && deathMessage != net.kyori.adventure.text.Component.empty() && flag) { // Paper - Adventure // TODO: allow plugins to override? + IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(deathMessage); // Paper - Adventure - + this.playerConnection.a((Packet) (new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, ichatbasecomponent)), (future) -> { if (!future.isSuccess()) { @@ -1669,6 +1666,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.a(ichatbasecomponent, ChatMessageType.SYSTEM, uuid); } - + + public void sendMessage(final IChatBaseComponent message, final ChatMessageType type, final UUID sender) { this.a(message, type, sender); } // Paper - OBFHELPER public void a(IChatBaseComponent ichatbasecomponent, ChatMessageType chatmessagetype, UUID uuid) { this.playerConnection.a((Packet) (new PacketPlayOutChat(ichatbasecomponent, chatmessagetype, uuid)), (future) -> { if (!future.isSuccess() && (chatmessagetype == ChatMessageType.GAME_INFO || chatmessagetype == ChatMessageType.SYSTEM)) { @@ -1691,6 +1689,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } - + public String locale = "en_us"; // CraftBukkit - add, lowercase + public java.util.Locale adventure$locale = java.util.Locale.US; // Paper public void a(PacketPlayInSettings packetplayinsettings) { @@ -1259,7 +1235,7 @@ index 16275208954bfc008115aa169c5bfc149f6a4eeb..49a0aefc7f9544b36175fdf3161b255e --- a/src/main/java/net/minecraft/server/network/LoginListener.java +++ b/src/main/java/net/minecraft/server/network/LoginListener.java @@ -37,6 +37,7 @@ import org.apache.logging.log4j.Logger; - + // CraftBukkit start import net.minecraft.network.chat.ChatComponentText; +import io.papermc.paper.adventure.PaperAdventure; // Paper @@ -1276,7 +1252,7 @@ index 16275208954bfc008115aa169c5bfc149f6a4eeb..49a0aefc7f9544b36175fdf3161b255e Waitable waitable = new Waitable() { @Override @@ -312,12 +313,12 @@ public class LoginListener implements PacketLoginInListener { - + LoginListener.this.server.processQueue.add(waitable); if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { - disconnect(event.getKickMessage()); @@ -1296,12 +1272,12 @@ index 2a96564c1656d42a74c331a6178e511cd5347a66..d219eda271a71f786808a6958b829fca +++ b/src/main/java/net/minecraft/server/network/PacketStatusListener.java @@ -56,7 +56,7 @@ public class PacketStatusListener implements PacketStatusInListener { CraftIconCache icon = minecraftServer.server.getServerIcon(); - + ServerListPingEvent() { - super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.getMotd(), minecraftServer.getPlayerList().getMaxPlayers()); + super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.server.motd(), minecraftServer.getPlayerList().getMaxPlayers()); // Paper - Adventure } - + @Override diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java index 536a351e1879fcb8066546d1179ad1af034b95da..5db09e60c2ac1f4cb0da3190e57896ccae7c58a3 100644 @@ -1309,7 +1285,7 @@ index 536a351e1879fcb8066546d1179ad1af034b95da..5db09e60c2ac1f4cb0da3190e57896cc +++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java @@ -159,6 +159,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; - + // CraftBukkit start +import io.papermc.paper.adventure.ChatProcessor; // Paper +import io.papermc.paper.adventure.PaperAdventure; // Paper @@ -1319,7 +1295,7 @@ index 536a351e1879fcb8066546d1179ad1af034b95da..5db09e60c2ac1f4cb0da3190e57896cc @@ -390,21 +392,24 @@ public class PlayerConnection implements PacketListenerPlayIn { return this.minecraftServer.a(this.player.getProfile()); } - + - // CraftBukkit start - @Deprecated - public void disconnect(IChatBaseComponent ichatbasecomponent) { @@ -1329,7 +1305,7 @@ index 536a351e1879fcb8066546d1179ad1af034b95da..5db09e60c2ac1f4cb0da3190e57896cc + this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); } - // CraftBukkit end - + - public void disconnect(String s) { + public void disconnect(final IChatBaseComponent reason) { + this.disconnect(PaperAdventure.asAdventure(reason)); @@ -1343,10 +1319,10 @@ index 536a351e1879fcb8066546d1179ad1af034b95da..5db09e60c2ac1f4cb0da3190e57896cc } - String leaveMessage = EnumChatFormat.YELLOW + this.player.getName() + " left the game."; + net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure - + - PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), s, leaveMessage); + PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure - + if (this.server.getServer().isRunning()) { this.server.getPluginManager().callEvent(event); @@ -415,8 +420,7 @@ public class PlayerConnection implements PacketListenerPlayIn { @@ -1357,11 +1333,11 @@ index 536a351e1879fcb8066546d1179ad1af034b95da..5db09e60c2ac1f4cb0da3190e57896cc - final IChatBaseComponent ichatbasecomponent = CraftChatMessage.fromString(s, true)[0]; + final IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure // CraftBukkit end - + this.networkManager.sendPacket(new PacketPlayOutKickDisconnect(ichatbasecomponent), (future) -> { @@ -1633,9 +1637,11 @@ public class PlayerConnection implements PacketListenerPlayIn { */ - + this.player.p(); - String quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); - if ((quitMessage != null) && (quitMessage.length() > 0)) { @@ -1389,11 +1365,11 @@ index 536a351e1879fcb8066546d1179ad1af034b95da..5db09e60c2ac1f4cb0da3190e57896cc + Player player = this.getPlayer(); // Paper AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(minecraftServer)); this.server.getPluginManager().callEvent(event); - + @@ -2670,21 +2681,20 @@ public class PlayerConnection implements PacketListenerPlayIn { return; } - + - // CraftBukkit start - Player player = this.server.getPlayer(this.player); - int x = packetplayinupdatesign.b().getX(); @@ -1402,7 +1378,7 @@ index 536a351e1879fcb8066546d1179ad1af034b95da..5db09e60c2ac1f4cb0da3190e57896cc - String[] lines = new String[4]; + // CraftBukkit start // Paper start - Adventure + List lines = new java.util.ArrayList<>(); - + for (int i = 0; i < list.size(); ++i) { - lines[i] = EnumChatFormat.a(new ChatComponentText(EnumChatFormat.a((String) list.get(i))).getString()); + lines.add(net.kyori.adventure.text.Component.text(list.get(i))); @@ -1410,7 +1386,7 @@ index 536a351e1879fcb8066546d1179ad1af034b95da..5db09e60c2ac1f4cb0da3190e57896cc - SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.server.getPlayer(this.player), lines); + SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); this.server.getPluginManager().callEvent(event); - + if (!event.isCancelled()) { - System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.lines, 0, 4); + for (int i = 0; i < 4; i++) { @@ -1434,36 +1410,36 @@ index c601a5c577e438a3fa8dd4c5f36dbe9494b03d52..6ebd4ec781aa215c2b941261250c15c8 import java.text.SimpleDateFormat; @@ -92,6 +93,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; - + // CraftBukkit start +import io.papermc.paper.adventure.PaperAdventure; // Paper import com.google.common.base.Predicate; import com.google.common.collect.Iterables; - + @@ -255,7 +257,7 @@ public abstract class PlayerList { } // CraftBukkit start chatmessage.a(EnumChatFormat.YELLOW); - String joinMessage = CraftChatMessage.fromComponent(chatmessage); + IChatBaseComponent joinMessage = chatmessage; // Paper - Adventure - + playerconnection.a(entityplayer.locX(), entityplayer.locY(), entityplayer.locZ(), entityplayer.yaw, entityplayer.pitch); this.players.add(entityplayer); @@ -264,19 +266,18 @@ public abstract class PlayerList { // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below - + // CraftBukkit start - PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(cserver.getPlayer(entityplayer), joinMessage); + PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure cserver.getPluginManager().callEvent(playerJoinEvent); - + if (!entityplayer.playerConnection.networkManager.isConnected()) { return; } - + - joinMessage = playerJoinEvent.getJoinMessage(); + final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); - + - if (joinMessage != null && joinMessage.length() > 0) { - for (IChatBaseComponent line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { - server.getPlayerList().sendAll(new PacketPlayOutChat(line, ChatMessageType.SYSTEM, SystemUtils.b)); @@ -1473,37 +1449,37 @@ index c601a5c577e438a3fa8dd4c5f36dbe9494b03d52..6ebd4ec781aa215c2b941261250c15c8 + server.getPlayerList().sendAll(new PacketPlayOutChat(joinMessage, ChatMessageType.SYSTEM, SystemUtils.b)); // Paper - Adventure } // CraftBukkit end - + @@ -473,7 +474,7 @@ public abstract class PlayerList { - + } - + - public String disconnect(EntityPlayer entityplayer) { // CraftBukkit - return string + public net.kyori.adventure.text.Component disconnect(EntityPlayer entityplayer) { // Paper - return Component WorldServer worldserver = entityplayer.getWorldServer(); - + entityplayer.a(StatisticList.LEAVE_GAME); @@ -484,7 +485,7 @@ public abstract class PlayerList { entityplayer.closeInventory(); } - + - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getName() + " left the game"); + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); cserver.getPluginManager().callEvent(playerQuitEvent); entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - + @@ -545,7 +546,7 @@ public abstract class PlayerList { cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); // CraftBukkit end - + - return playerQuitEvent.getQuitMessage(); // CraftBukkit + return playerQuitEvent.quitMessage(); // Paper - Adventure } - + // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer @@ -591,10 +592,10 @@ public abstract class PlayerList { } - + // return chatmessage; - if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); // Spigot + if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure @@ -1513,10 +1489,10 @@ index c601a5c577e438a3fa8dd4c5f36dbe9494b03d52..6ebd4ec781aa215c2b941261250c15c8 + event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { IpBanEntry ipbanentry = this.l.get(socketaddress); - + @@ -604,17 +605,17 @@ public abstract class PlayerList { } - + // return chatmessage; - event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); + event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure @@ -1527,7 +1503,7 @@ index c601a5c577e438a3fa8dd4c5f36dbe9494b03d52..6ebd4ec781aa215c2b941261250c15c8 + event.disallow(PlayerLoginEvent.Result.KICK_FULL, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure } } - + cserver.getPluginManager().callEvent(event); if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { - loginlistener.disconnect(event.getKickMessage()); @@ -1543,14 +1519,14 @@ index c601a5c577e438a3fa8dd4c5f36dbe9494b03d52..6ebd4ec781aa215c2b941261250c15c8 + player.playerConnection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure } // CraftBukkit end - + diff --git a/src/main/java/net/minecraft/world/BossBattle.java b/src/main/java/net/minecraft/world/BossBattle.java index f9154b306379c45f15fe55406aaa00351b0471e8..1fb9fea7683075f427edfa411c7747d60928d537 100644 --- a/src/main/java/net/minecraft/world/BossBattle.java +++ b/src/main/java/net/minecraft/world/BossBattle.java @@ -1,5 +1,6 @@ package net.minecraft.world; - + +import io.papermc.paper.adventure.PaperAdventure; import java.util.UUID; import net.minecraft.EnumChatFormat; @@ -1560,85 +1536,85 @@ index f9154b306379c45f15fe55406aaa00351b0471e8..1fb9fea7683075f427edfa411c7747d6 protected boolean f; protected boolean g; + public net.kyori.adventure.bossbar.BossBar adventure; // Paper - + public BossBattle(UUID uuid, IChatBaseComponent ichatbasecomponent, BossBattle.BarColor bossbattle_barcolor, BossBattle.BarStyle bossbattle_barstyle) { this.h = uuid; @@ -28,61 +30,75 @@ public abstract class BossBattle { } - + public IChatBaseComponent j() { + if(this.adventure != null) return PaperAdventure.asVanilla(this.adventure.name()); // Paper return this.title; } - + public void a(IChatBaseComponent ichatbasecomponent) { + if (this.adventure != null) this.adventure.name(PaperAdventure.asAdventure(ichatbasecomponent)); // Paper this.title = ichatbasecomponent; } - + public float getProgress() { + if (this.adventure != null) return this.adventure.progress(); // Paper return this.b; } - + public void a(float f) { + if (this.adventure != null) this.adventure.progress(f); // Paper this.b = f; } - + public BossBattle.BarColor l() { + if (this.adventure != null) return PaperAdventure.asVanilla(this.adventure.color()); // Paper return this.color; } - + public void a(BossBattle.BarColor bossbattle_barcolor) { + if(this.adventure != null) this.adventure.color(PaperAdventure.asAdventure(bossbattle_barcolor)); // Paper this.color = bossbattle_barcolor; } - + public BossBattle.BarStyle m() { + if(this.adventure != null) return PaperAdventure.asVanilla(this.adventure.overlay()); // Paper return this.style; } - + public void a(BossBattle.BarStyle bossbattle_barstyle) { + if(this.adventure != null) this.adventure.overlay(PaperAdventure.asAdventure(bossbattle_barstyle)); // Paper this.style = bossbattle_barstyle; } - + public boolean isDarkenSky() { + if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.DARKEN_SCREEN); // Paper return this.e; } - + public BossBattle a(boolean flag) { + if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.DARKEN_SCREEN, flag); // Paper this.e = flag; return this; } - + public boolean isPlayMusic() { + if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.PLAY_BOSS_MUSIC); // Paper return this.f; } - + public BossBattle b(boolean flag) { + if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.PLAY_BOSS_MUSIC, flag); // Paper this.f = flag; return this; } - + public BossBattle c(boolean flag) { + if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.CREATE_WORLD_FOG, flag); // Paper this.g = flag; return this; } - + public boolean isCreateFog() { + if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.CREATE_WORLD_FOG); // Paper return this.g; } - + diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java index 4010152dccc93019f2e7f284d80b92bae0d91c34..f1a780768e3f4bdb43a7ca6d7850befefb71bf57 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java @@ -1646,11 +1622,11 @@ index 4010152dccc93019f2e7f284d80b92bae0d91c34..f1a780768e3f4bdb43a7ca6d7850befe @@ -867,6 +867,7 @@ public final class ItemStack { } // CraftBukkit end - + + public IChatBaseComponent displayName() { return this.C(); } // Paper - OBFHELPER public IChatBaseComponent C() { IChatMutableComponent ichatmutablecomponent = (new ChatComponentText("")).addSibling(this.getName()); - + diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java index 0134bbda9e6fc900b7eefa05442e25539bab3431..b76ef55145336cc8dc4857b79767f5a738ad5144 100644 --- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java @@ -1658,39 +1634,39 @@ index 0134bbda9e6fc900b7eefa05442e25539bab3431..b76ef55145336cc8dc4857b79767f5a7 @@ -94,6 +94,7 @@ public abstract class Enchantment { return this.f(); } - + + public final IChatBaseComponent getTranslationComponentForLevel(int level) { return this.d(level); } // Paper - OBFHELPER public IChatBaseComponent d(int i) { ChatMessage chatmessage = new ChatMessage(this.g()); - + diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java index 7ec93ddd7e7c9dc54e3e4dcfe0d1654c0b0a8536..3f057f0bd23bc1c693c8f04ee8acd6626c620008 100644 --- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java +++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java @@ -32,6 +32,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; - + // CraftBukkit start +import io.papermc.paper.adventure.PaperAdventure; // Paper import java.util.UUID; - + import org.bukkit.craftbukkit.CraftServer; @@ -473,7 +474,7 @@ public class WorldMap extends PersistentBase { for ( org.bukkit.map.MapCursor cursor : render.cursors) { - + if (cursor.isVisible()) { - icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); + icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure } } - + diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 0c1e12b0b43f949d4ace600b2ccdffe52faab1e6..2ad09749f3005c3eff143d83580e25910341aa6b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -562,8 +562,10 @@ public final class CraftServer implements Server { } - + @Override + @Deprecated // Paper start public int broadcastMessage(String message) { @@ -1698,12 +1674,12 @@ index 0c1e12b0b43f949d4ace600b2ccdffe52faab1e6..2ad09749f3005c3eff143d83580e2591 + return this.broadcast(message, BROADCAST_CHANNEL_USERS); + // Paper end } - + public Player getPlayer(final EntityPlayer entity) { @@ -1307,7 +1309,15 @@ public final class CraftServer implements Server { return configuration.getInt("settings.spawn-radius", -1); } - + + // Paper start @Override + public net.kyori.adventure.text.Component shutdownMessage() { @@ -1718,7 +1694,7 @@ index 0c1e12b0b43f949d4ace600b2ccdffe52faab1e6..2ad09749f3005c3eff143d83580e2591 } @@ -1423,7 +1433,20 @@ public final class CraftServer implements Server { } - + @Override + @Deprecated // Paper public int broadcast(String message, String permission) { @@ -1740,24 +1716,24 @@ index 0c1e12b0b43f949d4ace600b2ccdffe52faab1e6..2ad09749f3005c3eff143d83580e2591 @@ -1431,14 +1454,14 @@ public final class CraftServer implements Server { } } - + - BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); + BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); // Paper - Adventure getPluginManager().callEvent(broadcastMessageEvent); - + if (broadcastMessageEvent.isCancelled()) { return 0; } - + - message = broadcastMessageEvent.getMessage(); + message = broadcastMessageEvent.message(); // Paper - Adventure - + for (CommandSender recipient : recipients) { recipient.sendMessage(message); @@ -1664,6 +1687,14 @@ public final class CraftServer implements Server { return CraftInventoryCreator.INSTANCE.createInventory(owner, type); } - + + // Paper start + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { @@ -1772,7 +1748,7 @@ index 0c1e12b0b43f949d4ace600b2ccdffe52faab1e6..2ad09749f3005c3eff143d83580e2591 @@ -1676,13 +1707,28 @@ public final class CraftServer implements Server { return CraftInventoryCreator.INSTANCE.createInventory(owner, size); } - + + // Paper start + @Override + public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) throws IllegalArgumentException { @@ -1786,7 +1762,7 @@ index 0c1e12b0b43f949d4ace600b2ccdffe52faab1e6..2ad09749f3005c3eff143d83580e2591 Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); } - + + // Paper start + @Override + public Merchant createMerchant(net.kyori.adventure.text.Component title) { @@ -1801,7 +1777,7 @@ index 0c1e12b0b43f949d4ace600b2ccdffe52faab1e6..2ad09749f3005c3eff143d83580e2591 @@ -1726,6 +1772,12 @@ public final class CraftServer implements Server { return Thread.currentThread().equals(console.serverThread) || console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog) } - + + // Paper start + @Override + public net.kyori.adventure.text.Component motd() { @@ -1828,12 +1804,12 @@ index 0c1e12b0b43f949d4ace600b2ccdffe52faab1e6..2ad09749f3005c3eff143d83580e2591 // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 3b48799d084f14722f815cb35cbd48b618380fca..cf6d350e6afc46bb58678192fe0b24b7d923412e 100644 +index 05aedca561919a12ced1925c5cc9af585bb04523..ce9f10f890a5866ab6208c7253b15b09fe323a81 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -19,6 +19,12 @@ public class Main { public static boolean useConsole = true; - + public static void main(String[] args) { + // Paper start + final String warnWhenLegacyFormattingDetected = String.join(".", "net", "kyori", "adventure", "text", "warnWhenLegacyFormattingDetected"); @@ -1851,7 +1827,7 @@ index ae735836accc6bf6f0831f72ff882720b69df792..d3ae5cadd88f9012203d2c04cbe38af9 @@ -70,6 +70,19 @@ public class CraftBeacon extends CraftBlockEntityState impleme this.getSnapshot().secondaryEffect = (effect != null) ? MobEffectList.fromId(effect.getId()) : null; } - + + // Paper start + @Override + public net.kyori.adventure.text.Component customName() { @@ -1875,7 +1851,7 @@ index e8ce890c551c9b809e8ba3f7449dc33f3a3a6b80..c99a59573653ee5d14e780137c769116 @@ -32,6 +32,19 @@ public abstract class CraftContainer extends Craf this.getSnapshot().chestLock = (key == null) ? ChestLock.a : new ChestLock(key); } - + + // Paper start + @Override + public net.kyori.adventure.text.Component customName() { @@ -1899,7 +1875,7 @@ index a559a77aae870988f4dd5e6f5f1f08feb3fad054..75ee5cc96c0e54f99e2ce820289bb74f @@ -16,6 +16,19 @@ public class CraftEnchantingTable extends CraftBlockEntityState implements Sign { - + // Lazily initialized only if requested: - private String[] originalLines = null; - private String[] lines = null; @@ -1930,13 +1906,13 @@ index 50d3f9ea1e905522096ef930c144589a1f0d539e..f4b601277ef75e5bc39d541a0d13c6ee + private java.util.ArrayList originalLines = null; // ArrayList for RandomAccess + private java.util.ArrayList lines = null; // ArrayList for RandomAccess + // Paper end - + public CraftSign(final Block block) { super(block, TileEntitySign.class); @@ -24,27 +26,52 @@ public class CraftSign extends CraftBlockEntityState implements super(material, te); } - + + // Paper start @Override - public String[] getLines() { @@ -1981,25 +1957,25 @@ index 50d3f9ea1e905522096ef930c144589a1f0d539e..f4b601277ef75e5bc39d541a0d13c6ee + this.loadLines(); + return this.lines.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).toArray(String[]::new); // Paper } - + @Override public String getLine(int index) throws IndexOutOfBoundsException { - return getLines()[index]; + this.loadLines(); + return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(this.lines.get(index)); // Paper } - + @Override public void setLine(int index, String line) throws IndexOutOfBoundsException { - getLines()[index] = line; + this.loadLines(); + this.lines.set(index, line != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(line) : net.kyori.adventure.text.Component.empty()); // Paper } - + @Override @@ -72,16 +99,32 @@ public class CraftSign extends CraftBlockEntityState implements super.applyTo(sign); - + if (lines != null) { - for (int i = 0; i < lines.length; i++) { - String line = (lines[i] == null) ? "" : lines[i]; @@ -2017,7 +1993,7 @@ index 50d3f9ea1e905522096ef930c144589a1f0d539e..f4b601277ef75e5bc39d541a0d13c6ee + // Paper end } } - + + // Paper start + public static IChatBaseComponent[] sanitizeLines(java.util.List lines) { + IChatBaseComponent[] components = new IChatBaseComponent[4]; @@ -2033,7 +2009,7 @@ index 50d3f9ea1e905522096ef930c144589a1f0d539e..f4b601277ef75e5bc39d541a0d13c6ee + // Paper end public static IChatBaseComponent[] sanitizeLines(String[] lines) { IChatBaseComponent[] components = new IChatBaseComponent[4]; - + diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java index 089fe4a3458ed3106fa214f89a7004a5d3c6bb95..af986adfdb547cb61fbd52f0f89858f1a9e52cc3 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java @@ -2064,7 +2040,7 @@ index 8f694de2fb3827b9be0dd768ad90eb72c7d708e4..5a14430f63894bbe9daa42900cf5a651 + return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); + } + // Paper end - + public net.minecraft.world.item.enchantment.Enchantment getHandle() { return target; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -2074,7 +2050,7 @@ index eea242af23825ad29ada6e997205e87edffb6bb9..3cf81734c8580f4d88ea97b6ac737a37 @@ -768,6 +768,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return getHandle().getVehicle().getBukkitEntity(); } - + + // Paper start + @Override + public net.kyori.adventure.text.Component customName() { @@ -2098,12 +2074,12 @@ index 816f2cbebe849a9d9533f985298bcd5d36f660eb..24e856473a0050c0b097c17977635037 @@ -318,9 +318,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { container = CraftEventFactory.callInventoryOpenEvent(player, container); if (container == null) return; - + - String title = container.getBukkitView().getTitle(); + //String title = container.getBukkitView().getTitle(); // Paper - comment + net.kyori.adventure.text.Component adventure$title = container.getBukkitView().title(); // Paper + if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper - + - player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); + //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment + player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper @@ -2111,7 +2087,7 @@ index 816f2cbebe849a9d9533f985298bcd5d36f660eb..24e856473a0050c0b097c17977635037 getHandle().activeContainer.addSlotListener(player); } @@ -389,8 +392,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - + // Now open the window Containers windowType = CraftContainer.getNotchInventoryType(inventory.getTopInventory()); - String title = inventory.getTitle(); @@ -2130,19 +2106,19 @@ index b51a874e4665f977a154792e6216e03e04525f39..6ab14bccb1fcd108931bf7ec331e60f6 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -240,14 +240,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - + @Override public String getDisplayName() { + if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper return getHandle().displayName; } - + @Override public void setDisplayName(final String name) { + this.getHandle().adventure$displayName = name != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(name) : net.kyori.adventure.text.Component.text(this.getName()); // Paper getHandle().displayName = name == null ? getName() : name; } - + + // Paper start + @Override + public void playerListName(net.kyori.adventure.text.Component name) { @@ -2172,38 +2148,38 @@ index b51a874e4665f977a154792e6216e03e04525f39..6ab14bccb1fcd108931bf7ec331e60f6 @@ -266,35 +291,35 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } } - + - private IChatBaseComponent playerListHeader; - private IChatBaseComponent playerListFooter; + private net.kyori.adventure.text.Component playerListHeader; // Paper - Adventure + private net.kyori.adventure.text.Component playerListFooter; // Paper - Adventure - + @Override public String getPlayerListHeader() { - return (playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader); + return (playerListHeader == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListHeader); // Paper - Adventure } - + @Override public String getPlayerListFooter() { - return (playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter); + return (playerListFooter == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListFooter); // Paper - Adventure } - + @Override public void setPlayerListHeader(String header) { - this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); + this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure updatePlayerListHeaderFooter(); } - + @Override public void setPlayerListFooter(String footer) { - this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); + this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure updatePlayerListHeaderFooter(); } - + @Override public void setPlayerListHeaderFooter(String header, String footer) { - this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); @@ -2212,10 +2188,10 @@ index b51a874e4665f977a154792e6216e03e04525f39..6ab14bccb1fcd108931bf7ec331e60f6 + this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure updatePlayerListHeaderFooter(); } - + @@ -302,8 +327,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (getHandle().playerConnection == null) return; - + PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); - packet.header = (this.playerListHeader == null) ? new ChatComponentText("") : this.playerListHeader; - packet.footer = (this.playerListFooter == null) ? new ChatComponentText("") : this.playerListFooter; @@ -2223,11 +2199,11 @@ index b51a874e4665f977a154792e6216e03e04525f39..6ab14bccb1fcd108931bf7ec331e60f6 + packet.footer = (this.playerListFooter == null) ? new ChatComponentText("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListFooter); // Paper - Adventure getHandle().playerConnection.sendPacket(packet); } - + @@ -335,6 +360,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { getHandle().playerConnection.disconnect(message == null ? "" : message); } - + + // Paper start + @Override + public void kick(final net.kyori.adventure.text.Component message) { @@ -2245,7 +2221,7 @@ index b51a874e4665f977a154792e6216e03e04525f39..6ab14bccb1fcd108931bf7ec331e60f6 @@ -561,6 +597,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { getHandle().playerConnection.sendPacket(packet); } - + + // Paper start + @Override + public void sendSignChange(Location loc, List lines) { @@ -2282,24 +2258,24 @@ index b51a874e4665f977a154792e6216e03e04525f39..6ab14bccb1fcd108931bf7ec331e60f6 sendSignChange(loc, lines, DyeColor.BLACK); @@ -583,12 +650,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } - + IChatBaseComponent[] components = CraftSign.sanitizeLines(lines); - TileEntitySign sign = new TileEntitySign(); + /*TileEntitySign sign = new TileEntitySign(); // Paper sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); - + - getHandle().playerConnection.sendPacket(sign.getUpdatePacket()); + getHandle().playerConnection.sendPacket(sign.getUpdatePacket());*/ // Paper + this.sendSignChange0(components, loc, dyeColor); // Paper } - + @Override @@ -1688,6 +1756,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return (getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : getHandle().clientViewDistance; } - + + // Paper start + @Override + public java.util.Locale locale() { @@ -2312,7 +2288,7 @@ index b51a874e4665f977a154792e6216e03e04525f39..6ab14bccb1fcd108931bf7ec331e60f6 @@ -1716,6 +1790,138 @@ public class CraftPlayer extends CraftHumanEntity implements Player { getInventory().setItemInMainHand(hand); } - + + // Paper start + @Override + public net.kyori.adventure.text.Component displayName() { @@ -2455,7 +2431,7 @@ index 5df71cbc9d5b7a481fd087623a0d02c98e5fefc4..8a7511fc1876dc6761826dd2636bce19 @@ -788,9 +788,9 @@ public class CraftEventFactory { return event; } - + - public static PlayerDeathEvent callPlayerDeathEvent(EntityPlayer victim, List drops, String deathMessage, boolean keepInventory) { + public static PlayerDeathEvent callPlayerDeathEvent(EntityPlayer victim, List drops, net.kyori.adventure.text.Component deathMessage, String stringDeathMessage, boolean keepInventory) { // Paper - Adventure CraftPlayer entity = victim.getBukkitEntity(); @@ -2478,7 +2454,7 @@ index 384520dd734449d4e4f5243fbaad5f666b0c965c..614ab2d73db2293116f2272f6cd5c16d --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java @@ -39,6 +39,7 @@ public class CraftContainer extends Container { - + private final InventoryView view; private InventoryType cachedType; + private net.kyori.adventure.text.Component adventure$title; // Paper @@ -2499,7 +2475,7 @@ index 384520dd734449d4e4f5243fbaad5f666b0c965c..614ab2d73db2293116f2272f6cd5c16d @@ -77,6 +80,13 @@ public class CraftContainer extends Container { return inventory.getType(); } - + + // Paper start + @Override + public net.kyori.adventure.text.Component title() { @@ -2511,7 +2487,7 @@ index 384520dd734449d4e4f5243fbaad5f666b0c965c..614ab2d73db2293116f2272f6cd5c16d public String getTitle() { return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).getTitle() : inventory.getType().getDefaultTitle(); @@ -95,7 +105,8 @@ public class CraftContainer extends Container { - + @Override public boolean c(EntityHuman entityhuman) { - if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { @@ -2548,7 +2524,7 @@ index a537cc4ac5d052168f96a1ae73b6b17a380436ab..21347cf02cc01c90a81e7dd8264ef119 @@ -19,6 +19,12 @@ public class CraftInventoryCustom extends CraftInventory { super(new MinecraftInventory(owner, type)); } - + + // Paper start + public CraftInventoryCustom(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { + super(new MinecraftInventory(owner, type, title)); @@ -2561,7 +2537,7 @@ index a537cc4ac5d052168f96a1ae73b6b17a380436ab..21347cf02cc01c90a81e7dd8264ef119 @@ -27,6 +33,12 @@ public class CraftInventoryCustom extends CraftInventory { super(new MinecraftInventory(owner, size)); } - + + // Paper start + public CraftInventoryCustom(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { + super(new MinecraftInventory(owner, size, title)); @@ -2578,7 +2554,7 @@ index a537cc4ac5d052168f96a1ae73b6b17a380436ab..21347cf02cc01c90a81e7dd8264ef119 + private final net.kyori.adventure.text.Component adventure$title; // Paper private InventoryType type; private final InventoryHolder owner; - + + // Paper start + public MinecraftInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { + this(owner, type.getDefaultSize(), title); @@ -2598,7 +2574,7 @@ index a537cc4ac5d052168f96a1ae73b6b17a380436ab..21347cf02cc01c90a81e7dd8264ef119 this.owner = owner; this.type = InventoryType.CHEST; } - + + // Paper start + public MinecraftInventory(final InventoryHolder owner, final int size, final net.kyori.adventure.text.Component title) { + Validate.notNull(title, "Title cannot be null"); @@ -2617,7 +2593,7 @@ index a537cc4ac5d052168f96a1ae73b6b17a380436ab..21347cf02cc01c90a81e7dd8264ef119 @@ -183,6 +216,12 @@ public class CraftInventoryCustom extends CraftInventory { return null; } - + + // Paper start + public net.kyori.adventure.text.Component title() { + return this.adventure$title; @@ -2634,7 +2610,7 @@ index 04073ed45f8068d80e58d3927b5ebc3160c6a8c6..9949bb8cac73b2f1f02b51079c0e244f @@ -64,6 +64,13 @@ public class CraftInventoryView extends InventoryView { return CraftItemStack.asCraftMirror(container.getSlot(slot).getItem()); } - + + // Paper start + @Override + public net.kyori.adventure.text.Component title() { @@ -2672,9 +2648,9 @@ index ef10c7ab1d615cdba182eca63eb14309339a5314..206c133ebc6c44038585236b0628543b --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java @@ -14,10 +14,17 @@ import org.apache.commons.lang.Validate; - + public class CraftMerchantCustom extends CraftMerchant { - + + @Deprecated // Paper - Adventure public CraftMerchantCustom(String title) { super(new MinecraftMerchant(title)); @@ -2686,13 +2662,13 @@ index ef10c7ab1d615cdba182eca63eb14309339a5314..206c133ebc6c44038585236b0628543b + getMerchant().craftMerchant = this; + } + // Paper end - + @Override public String toString() { @@ -37,10 +44,17 @@ public class CraftMerchantCustom extends CraftMerchant { private World tradingWorld; protected CraftMerchant craftMerchant; - + + @Deprecated // Paper - Adventure public MinecraftMerchant(String title) { Validate.notNull(title, "Title cannot be null"); @@ -2704,7 +2680,7 @@ index ef10c7ab1d615cdba182eca63eb14309339a5314..206c133ebc6c44038585236b0628543b + this.title = io.papermc.paper.adventure.PaperAdventure.asVanilla(title); + } + // Paper end - + @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 @@ -2713,7 +2689,7 @@ index 4cdc504df4cad6f7725f6d18482e88433523943a..65b6d32e3e1130a64df33082f3292cb1 +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java @@ -1,8 +1,9 @@ package org.bukkit.craftbukkit.inventory; - + import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap.Builder; import com.google.common.collect.Lists; @@ -2727,13 +2703,13 @@ index 4cdc504df4cad6f7725f6d18482e88433523943a..65b6d32e3e1130a64df33082f3292cb1 import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.BookMeta.Generation; +import org.checkerframework.checker.nullness.qual.NonNull; - + // Spigot start import static org.spigotmc.ValidateUtils.*; @@ -269,6 +271,141 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { this.generation = (generation == null) ? null : generation.ordinal(); } - + + // Paper start + @Override + public net.kyori.adventure.text.Component title() { @@ -2874,12 +2850,12 @@ index 4cdc504df4cad6f7725f6d18482e88433523943a..65b6d32e3e1130a64df33082f3292cb1 Validate.isTrue(isValidPage(page), "Invalid page number"); @@ -413,7 +550,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { } - + @Override - Builder serialize(Builder builder) { + ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { super.serialize(builder); - + if (hasTitle()) { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java index 0835541f51e643ae824c197be7100d5849b5e92a..0d58ec9834797ad7b9acaae6353dcf0385c53fd4 100644 @@ -2887,7 +2863,7 @@ index 0835541f51e643ae824c197be7100d5849b5e92a..0d58ec9834797ad7b9acaae6353dcf03 +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java @@ -1,6 +1,6 @@ package org.bukkit.craftbukkit.inventory; - + -import com.google.common.collect.ImmutableMap.Builder; +import com.google.common.collect.ImmutableMap; // Paper import java.util.Map; @@ -2895,7 +2871,7 @@ index 0835541f51e643ae824c197be7100d5849b5e92a..0d58ec9834797ad7b9acaae6353dcf03 import org.bukkit.Material; @@ -84,7 +84,7 @@ class CraftMetaBookSigned extends CraftMetaBook implements BookMeta { } - + @Override - Builder serialize(Builder builder) { + ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { @@ -2909,7 +2885,7 @@ index 928328c292a1322cab478bc748761baf8608e4b0..7a11b2ddfa4244459253c918315aaab7 @@ -745,6 +745,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); } - + + // Paper start + @Override + public net.kyori.adventure.text.Component displayName() { @@ -2928,7 +2904,7 @@ index 928328c292a1322cab478bc748761baf8608e4b0..7a11b2ddfa4244459253c918315aaab7 @@ -780,6 +792,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { return this.lore != null && !this.lore.isEmpty(); } - + + // Paper start + @Override + public List lore() { @@ -2951,7 +2927,7 @@ index ed4415f6dd588c08c922efd5beebb3b124beb9d6..78a7ac47f20e84ccd67ff44d0bc7a2f2 @@ -12,6 +12,13 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve return new CraftInventoryCustom(holder, type); } - + + // Paper start + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { @@ -2965,7 +2941,7 @@ index ed4415f6dd588c08c922efd5beebb3b124beb9d6..78a7ac47f20e84ccd67ff44d0bc7a2f2 @@ -21,6 +28,12 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve return new CraftInventoryCustom(owner, size); } - + + // Paper start + public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { + return new CraftInventoryCustom(owner, size, title); @@ -2982,7 +2958,7 @@ index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b @@ -43,6 +43,17 @@ public final class CraftInventoryCreator { return converterMap.get(type).createInventory(holder, type); } - + + // Paper start + public Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title) { + // Paper start @@ -3000,7 +2976,7 @@ index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b @@ -51,6 +62,12 @@ public final class CraftInventoryCreator { return DEFAULT_CONVERTER.createInventory(holder, size); } - + + // Paper start + public Inventory createInventory(InventoryHolder holder, int size, net.kyori.adventure.text.Component title) { + return DEFAULT_CONVERTER.createInventory(holder, size, title); @@ -3011,9 +2987,9 @@ index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b return DEFAULT_CONVERTER.createInventory(holder, size, title); } @@ -59,6 +76,10 @@ public final class CraftInventoryCreator { - + Inventory createInventory(InventoryHolder holder, InventoryType type); - + + // Paper start + Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title); + // Paper end @@ -3028,7 +3004,7 @@ index f35e66dab9ff63ca05d7e303c71106c0e9971309..2bd4e644ffbde2e1133b25824a2829bc @@ -31,6 +31,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat return getInventory(getTileEntity()); } - + + // Paper start + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { @@ -3047,7 +3023,7 @@ index f35e66dab9ff63ca05d7e303c71106c0e9971309..2bd4e644ffbde2e1133b25824a2829bc @@ -54,6 +66,15 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat return furnace; } - + + // Paper start + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { @@ -3063,7 +3039,7 @@ index f35e66dab9ff63ca05d7e303c71106c0e9971309..2bd4e644ffbde2e1133b25824a2829bc @@ -74,6 +95,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat return new TileEntityBrewingStand(); } - + + // Paper start + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { @@ -3086,7 +3062,7 @@ index 8fedca656af0783f3d97a7ccde3a113f97911084..df3deee12b11508b76c5f8f927fac8db @@ -31,6 +31,21 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective return objective.getName(); } - + + // Paper start + @Override + public net.kyori.adventure.text.Component displayName() throws IllegalStateException { @@ -3134,11 +3110,11 @@ index 954389b818de93cf0ab046edc5dc032fceea391b..6ea491f6308317059c4bc6735abbdce3 + return new CraftObjective(this, objective); + } + // Paper end - + @Override public CraftObjective registerNewObjective(String name, String criteria, String displayName) throws IllegalArgumentException { @@ -36,7 +57,7 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - + @Override public CraftObjective registerNewObjective(String name, String criteria, String displayName, RenderType renderType) throws IllegalArgumentException { - Validate.notNull(name, "Objective name cannot be null"); @@ -3147,21 +3123,21 @@ index 954389b818de93cf0ab046edc5dc032fceea391b..6ea491f6308317059c4bc6735abbdce3 Validate.notNull(displayName, "Display name cannot be null"); Validate.notNull(renderType, "RenderType cannot be null"); @@ -46,7 +67,8 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - + CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); - return new CraftObjective(this, objective); + return new CraftObjective(this, objective);*/ // Paper + return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper } - + @Override diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java index a213c2e3b2680c6d1bd38853580cbdb52ae7779e..c631934fe9d205a06956c900d5b58a1d8a781c19 100644 --- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java @@ -29,6 +29,55 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { - + return team.getName(); } + // Paper start @@ -3213,7 +3189,7 @@ index a213c2e3b2680c6d1bd38853580cbdb52ae7779e..c631934fe9d205a06956c900d5b58a1d + team.setColor(io.papermc.paper.adventure.PaperAdventure.asVanilla(color)); + } + // Paper end - + @Override public String getDisplayName() throws IllegalStateException { diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java @@ -3221,21 +3197,21 @@ index 6a0b4cd36ac54df41642e8499c50e59f2b347b48..666af6cc91bd12ba5d5a846d663a5aab --- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java @@ -290,6 +290,7 @@ public final class CraftChatMessage { - + public static String fromComponent(IChatBaseComponent component) { if (component == null) return ""; + if (component instanceof io.papermc.paper.adventure.AdventureComponent) component = ((io.papermc.paper.adventure.AdventureComponent) component).deepConverted(); StringBuilder out = new StringBuilder(); - + 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 65131f0977fa55c4761c34ce52720170feb61a72..8f737f63f280c00c1276bd1dc3ecf60448732ca8 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -59,6 +59,33 @@ public final class CraftMagicNumbers implements UnsafeValues { - + private CraftMagicNumbers() {} - + + // Paper start + @Override + public net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener() { @@ -3273,10 +3249,10 @@ index f194cf2663919ea18309a0501ddfab5e2ed639dd..4b110d6c6f22ff7c2fa0fd4b45982079 @@ -80,7 +80,7 @@ public abstract class LazyHashSet implements Set { return this.reference = makeReference(); } - + - abstract Set makeReference(); + protected abstract Set makeReference(); // Paper - protected - + public boolean isLazy() { return reference == null; diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java @@ -3285,7 +3261,7 @@ index e7b9250ebdd0d9034ef18a96a6cacc83e6db69c2..20ee8468bcf305139a51da61f5f90267 +++ b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java @@ -15,10 +15,15 @@ public class LazyPlayerSet extends LazyHashSet { } - + @Override - HashSet makeReference() { + protected HashSet makeReference() { // Paper - protected diff --git a/Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch b/Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch index 7d7162311a..b516f276ef 100644 --- a/Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch +++ b/Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch @@ -22,7 +22,7 @@ index 796c17e0941922a9716212c6eae91643d8360418..78948c42b13194005bdbbbc69c2b7ae0 + } } diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 2b75eab985b0f39e1624e5f4cab7e5b5bde6ae14..bcc411107d531529dbce9d1d43896a3c70e63012 100644 +index 382b40a2a030993e1e98f34bc91befdd45c16895..7402e3b305d9bb7b27b97ff2078c26dd578232a1 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java @@ -85,6 +85,10 @@ public class EntityFishingHook extends IProjectile { diff --git a/Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch index cbf2e1e52c..3c4047985e 100644 --- a/Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch +++ b/Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch @@ -19,7 +19,7 @@ index 78948c42b13194005bdbbbc69c2b7ae0732a78c5..b41e7922dd96c3358eb849ab39982a75 + } } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index db8970539f7f69c9087abe43286bca008cb4594d..0b86c697541e3ee6083b3c10ab3618ef740b1904 100644 +index 306f6c0db2333cce5dfc4bf1c09bfef05119a28b..f823763a2f7f40d0be8d058a1bd61386bcd951e6 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1105,6 +1105,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne diff --git a/Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch b/Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch index 26dfa439bc..ec9ba5059c 100644 --- a/Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch +++ b/Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch @@ -25,7 +25,7 @@ index 89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75..d16ae924bcbe31c964f7fb448757c748 + } } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0b86c697541e3ee6083b3c10ab3618ef740b1904..d7dfb89faa47817c51257bb124cfb3806c5e27da 100644 +index f823763a2f7f40d0be8d058a1bd61386bcd951e6..20e4ff812960a54872f2fea8fe6baf7bb1ef077d 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1850,6 +1850,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne diff --git a/Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch index d217c0a5b8..6ff3ad51f7 100644 --- a/Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch +++ b/Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch @@ -32,7 +32,7 @@ index 85c96e3f70a3ffecb6195a1d83053412eb180d78..c21790b4de698aa6f7fc4dadab64d791 public CrashReport b(CrashReport crashreport) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 2c2e87d96f61e7ef88847df70e1c6153bca9fcd3..a9449a62f678ec6dc5e923c64e89140bb96fb697 100644 +index 2ad09749f3005c3eff143d83580e25910341aa6b..462633df2af43959fddf5b7a8ec43063abf7b14b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -225,7 +225,7 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; @@ -45,7 +45,7 @@ index 2c2e87d96f61e7ef88847df70e1c6153bca9fcd3..a9449a62f678ec6dc5e923c64e89140b private final String bukkitVersion = Versioning.getBukkitVersion(); private final Logger logger = Logger.getLogger("Minecraft"); diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index cf6d350e6afc46bb58678192fe0b24b7d923412e..2819c734fb6b8ed82df143e90c24316f3e8c551e 100644 +index ce9f10f890a5866ab6208c7253b15b09fe323a81..e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -206,12 +206,25 @@ public class Main { diff --git a/Spigot-Server-Patches/0021-Player-affects-spawning-API.patch b/Spigot-Server-Patches/0021-Player-affects-spawning-API.patch index aaedffd843..0ccd83d4e5 100644 --- a/Spigot-Server-Patches/0021-Player-affects-spawning-API.patch +++ b/Spigot-Server-Patches/0021-Player-affects-spawning-API.patch @@ -17,7 +17,7 @@ index 20e4ff812960a54872f2fea8fe6baf7bb1ef077d..cae9da158f54438d2a397665c7ce964f double d3 = this.locX() - d0; double d4 = this.locY() - d1; diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index f93af56f68d5fd27eca38d333ca429ce22fc397b..0631cd531647239858b2a7298f58cc770720f69a 100644 +index 6e30fc88fa7a3ff00c9b4b78842c3a533649bd50..31bb5df7bc63c993230bf595bd9b66bfaadb4d50 100644 --- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java +++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java @@ -756,7 +756,7 @@ public abstract class EntityInsentient extends EntityLiving { diff --git a/Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch b/Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch index 69c1692940..a06ff56c4c 100644 --- a/Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch +++ b/Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch @@ -29,7 +29,7 @@ index d16ae924bcbe31c964f7fb448757c748e5c4418c..4bba6977a0287837b8927718c040ac61 + } } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index dce47ec1fc186d12ffa30bfd3d71870aecb95d40..cf92de7c138ef9cbbc1263bee29b9d0017b45827 100644 +index f6f0d551e22ff085935c1543bf84392de0368214..df2582c3b00977d799b189214d7d4f30ded5b66d 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -500,9 +500,16 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne diff --git a/Spigot-Server-Patches/0033-Optimize-explosions.patch b/Spigot-Server-Patches/0033-Optimize-explosions.patch index 78ab387974..d539442720 100644 --- a/Spigot-Server-Patches/0033-Optimize-explosions.patch +++ b/Spigot-Server-Patches/0033-Optimize-explosions.patch @@ -25,7 +25,7 @@ index e6e18f309dc09ea9416ea37dcc697ddc2b571a96..4881b03d470646843bad1bc343eb6a6a + } } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index add4f149fd31d1420d825b646b3e088808e5896b..06071e15851d5d27f1c9a0d60a764a6214e0ba0f 100644 +index fb0d985b5c977a7c63701484678b75928d9ee382..ed71de473d461528d74ca5b95c33b97e98128aff 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1326,6 +1326,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { - } - - } -+ // Paper start -+ public net.md_5.bungee.api.chat.BaseComponent[] components; -+ -+ public PacketPlayOutTitle(EnumTitleAction action, net.md_5.bungee.api.chat.BaseComponent[] components, int fadeIn, int stay, int fadeOut) { -+ this.a = action; -+ this.components = components; -+ this.c = fadeIn; -+ this.d = stay; -+ this.e = fadeOut; -+ } -+ // Paper end - - @Override - public void b(PacketDataSerializer packetdataserializer) throws IOException { -@@ -55,6 +66,8 @@ public class PacketPlayOutTitle implements Packet { - // Paper start - if (this.adventure$text != null) { - packetdataserializer.writeComponent(this.adventure$text); -+ } else if (this.components != null) { -+ packetdataserializer.writeComponent(this.components); - } else - // Paper end - packetdataserializer.a(this.b); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 62f8d96f996ece87b7ab8d5d05d1dc214d10dbfa..9837f7364f3efd0aa22d33058bec369c41cd03ef 100644 +index fb792de46ff80a6bad77a47954861cddfd17f2d9..1ad5863dc12b2288a38efed71b7fa4b84296d96d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1,5 +1,6 @@ package org.bukkit.craftbukkit.entity; - + +import com.destroystokyo.paper.Title; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; @@ -77,7 +46,7 @@ index 62f8d96f996ece87b7ab8d5d05d1dc214d10dbfa..9837f7364f3efd0aa22d33058bec369c @@ -238,6 +239,96 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } } - + + // Paper start + @Override + public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { diff --git a/Spigot-Server-Patches/0053-Add-velocity-warnings.patch b/Spigot-Server-Patches/0053-Add-velocity-warnings.patch index 16e9a27479..41c25af3bd 100644 --- a/Spigot-Server-Patches/0053-Add-velocity-warnings.patch +++ b/Spigot-Server-Patches/0053-Add-velocity-warnings.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add velocity warnings diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index bfd78c41757c73736371811aab97ca05a01667c9..c952b193618c58335172117dfe475047a1178ac5 100644 +index f78f5e4f2c04b64dff1d2229a137c600f18e7051..22b4dec4944b7f823996645af95fbef2d1d8a83b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -261,6 +261,7 @@ public final class CraftServer implements Server { diff --git a/Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch index a2f353ae12..6885002825 100644 --- a/Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ b/Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add methods for working with arrows stuck in living entities diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 9f7334ae769438cdd77508000e7721f57b30e225..a81afaf47214dcb4452642a7e8f295eb94ca6501 100644 +index d863fc9fa6b932b76a89871a09378a9c0697c108..c654026587bc9bf77b39f59a0c89991ac581da1e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -689,4 +689,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { diff --git a/Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch b/Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch index 61421fdb49..6ae4874a0a 100644 --- a/Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch +++ b/Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch @@ -30,7 +30,7 @@ index 429b74474ced04d8dd8f038b8590b8dfe178bf4d..716f285e67019b8a62922d09c15883c9 + } } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c952b193618c58335172117dfe475047a1178ac5..ac10067e924cfbfe0a528cad62293686c0c24562 100644 +index 22b4dec4944b7f823996645af95fbef2d1d8a83b..6eec60b5739edb8f7278608e525b38bdac15bba8 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -398,6 +398,7 @@ public final class CraftServer implements Server { diff --git a/Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch b/Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch index e87ee15fe2..777dfb5014 100644 --- a/Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch +++ b/Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch @@ -18,7 +18,7 @@ For consistency, the old API methods now forward to use the ItemMeta API equivalents, and should deprecate the old API's. diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 4010152dccc93019f2e7f284d80b92bae0d91c34..d7c5065457d910f3e5481fda046d368d5f66f67b 100644 +index f1a780768e3f4bdb43a7ca6d7850befefb71bf57..201ba7250b298f4a91bc45f5954f54ae557305f2 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java @@ -9,6 +9,8 @@ import com.mojang.serialization.Codec; diff --git a/Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch index 0cc21d37c3..1aea311bfb 100644 --- a/Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch +++ b/Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch @@ -30,7 +30,7 @@ index 3ac2ac3db9b1c271b3c21930bb13716669ff64d3..3c78d3234054ce2dc46ef77decb6adb0 + } } diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index a05ee898bd360f49ea2807d06f93e27ada11ef63..9bd4a283a99f86c9a26f73e0bad0c3414d66ad55 100644 +index 04af85e0ccb7a98e0796afcdcce33f8595b1db8c..7868259a94766a6100d7b278c4296dde0a7f9397 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java @@ -283,7 +283,7 @@ public abstract class EntityArrow extends IProjectile { diff --git a/Spigot-Server-Patches/0066-Add-World-Util-Methods.patch b/Spigot-Server-Patches/0066-Add-World-Util-Methods.patch index e8f87bb7d5..ff0b627ecc 100644 --- a/Spigot-Server-Patches/0066-Add-World-Util-Methods.patch +++ b/Spigot-Server-Patches/0066-Add-World-Util-Methods.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Add World Util Methods Methods that can be used for other patches to help improve logic. diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index eddfbd25953e8ef410f1617a1edecbc7d07696c0..b04a6cd626fceed26aec6121e20fb1b6dd1c716d 100644 +index a1769df6a3f6150d322f145199caba3839871dff..3ea4ec748c229031a5f0d973988bb20e55679971 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java +++ b/src/main/java/net/minecraft/server/level/WorldServer.java @@ -197,7 +197,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { @@ -19,7 +19,7 @@ index eddfbd25953e8ef410f1617a1edecbc7d07696c0..b04a6cd626fceed26aec6121e20fb1b6 } diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index b0ad55f35285cc1bc339859a8deae65e930082b8..067f5e46ad2f28ab119db77b19c4897bed9b3d80 100644 +index 01cb0c8dd9875986e0c08371e876f0dba3f0cf5a..a570998e4ef6c3ff83403881bf1d24c8cbcfcf67 100644 --- a/src/main/java/net/minecraft/world/level/World.java +++ b/src/main/java/net/minecraft/world/level/World.java @@ -297,11 +297,27 @@ public abstract class World implements GeneratorAccess, AutoCloseable { diff --git a/Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch b/Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch index defeebd3fc..bf2af97bfc 100644 --- a/Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch +++ b/Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Custom replacement for eaten items diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 318c96ee92fc8c6f5926aeadaa597d32ad590974..9b12e15a6c377ae90193596a35114dd452cf6e0c 100644 +index 70211129e6ab2f7cdb975adcb532be595bc3834f..759592fc6a4654c0760ff8a1d7f3b87c364b045a 100644 --- a/src/main/java/net/minecraft/world/entity/EntityLiving.java +++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java @@ -3205,9 +3205,10 @@ public abstract class EntityLiving extends Entity { diff --git a/Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch index 7560b34679..a64c157fce 100644 --- a/Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch +++ b/Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch @@ -5,7 +5,7 @@ Subject: [PATCH] handle NaN health/absorb values and repair bad data diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 082a3efb8c03e6a0a35411107f3cf3776dee14bf..c7b40800343edb2c2a68786afb828c9dc3e3627f 100644 +index 759592fc6a4654c0760ff8a1d7f3b87c364b045a..375284b7e321cb03a7a30aedea165ca7a2fd1091 100644 --- a/src/main/java/net/minecraft/world/entity/EntityLiving.java +++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java @@ -702,7 +702,13 @@ public abstract class EntityLiving extends Entity { diff --git a/Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch b/Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch index 1579a0057c..23a114a451 100644 --- a/Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch +++ b/Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Use a Shared Random for Entities Reduces memory usage and provides ensures more randomness, Especially since a lot of garbage entity objects get created. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b7df4d8eb3ccb9e8dc85898352f41c5c20abcb34..6cbb797cb0de4b26d8ddd7f0bf567f49bd36f9c0 100644 +index bfced192c1e8fd3fa0250a0f93adfc061d7e71e5..415935739716df3b8b3319aac19519d29aaa5776 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -143,6 +143,21 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne diff --git a/Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch b/Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch index a0c1e7b121..768d4bc95d 100644 --- a/Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch +++ b/Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch @@ -22,7 +22,7 @@ index 3c78d3234054ce2dc46ef77decb6adb0cbd10620..cd64fb9d0c6d123e1c86cb33f12cd9ce + } } diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 045183ab75bac68b1da5e0899a15fa34cd9e956f..a5ee8bf7904444ff6fd82260a66a81c9af479f9e 100644 +index 3ea4ec748c229031a5f0d973988bb20e55679971..5cd864e58b85fa163489557437f5c2eec9f008b7 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java +++ b/src/main/java/net/minecraft/server/level/WorldServer.java @@ -590,7 +590,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { diff --git a/Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch index 357ba81b53..b10153a490 100644 --- a/Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch +++ b/Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Only process BlockPhysicsEvent if a plugin has a listener Saves on some object allocation and processing when no plugin listens to this diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 06071e15851d5d27f1c9a0d60a764a6214e0ba0f..33139f9dc6a9c6030f565b01c9b6fd411cafa710 100644 +index ed71de473d461528d74ca5b95c33b97e98128aff..b141c744b8ffbc37b09cb4347c4051a77bb7049e 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1292,6 +1292,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { return worldserver + " " + worldserver.getDimensionKey().a(); diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index a5ee8bf7904444ff6fd82260a66a81c9af479f9e..c5baf9c448761f24c4fd49d7c4bade7dee43edf4 100644 +index 5cd864e58b85fa163489557437f5c2eec9f008b7..a82affb9ffd0b2a513dcbf29402e99b49ed95d63 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java +++ b/src/main/java/net/minecraft/server/level/WorldServer.java @@ -196,6 +196,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { diff --git a/Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch b/Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch index e910aa110a..61e53caa2c 100644 --- a/Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch +++ b/Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Entity AddTo/RemoveFrom World Events diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index c5baf9c448761f24c4fd49d7c4bade7dee43edf4..b40089319329a0843c4d74ebd6189fc4089e319a 100644 +index a82affb9ffd0b2a513dcbf29402e99b49ed95d63..24a45e5ac9b17feb528e9a047d1ad1761569ebfa 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java +++ b/src/main/java/net/minecraft/server/level/WorldServer.java @@ -1214,7 +1214,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { diff --git a/Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch b/Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch index 063b7e7b45..c5364da582 100644 --- a/Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch +++ b/Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix reducedDebugInfo not initialized on client diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index cfd0af520dd3dcf364a3ffd03a74e3b9ee6045af..152aa38788a21638aab7cfe2dc187671f1143bde 100644 +index 46c516b9ff089a3c885d635244942fd5a6ecf132..9d327f1255dd9d6b11840f7bb8ffc302bc33dbcf 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -246,6 +246,7 @@ public abstract class PlayerList { diff --git a/Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch index d3f898437e..d855eabdf8 100644 --- a/Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch +++ b/Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix Cancelling BlockPlaceEvent triggering physics diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 70db5312ac556ea53247efdbc7759910ba0c9a95..7611481db980a230d42b3cec1d81fae2622ca634 100644 +index 9236e480d21340d4295caa16dae34363e182f483..8da8141c2320c0c1a9b95826a9be2dbe22e11c14 100644 --- a/src/main/java/net/minecraft/world/level/World.java +++ b/src/main/java/net/minecraft/world/level/World.java @@ -518,6 +518,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { diff --git a/Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch index 1d55264b24..1cdc8fed9c 100644 --- a/Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch +++ b/Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch @@ -26,7 +26,7 @@ index db2dddd12f54e6d15916c4cee623676541de37fb..1942f5224aaebb18adb591d6f70a419c + } } diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -index f4d0c4ed270769de7a9ed35643a6cc649c482ed5..294b8ac155c77ae84732c7aeeef9ee6269ff85b1 100644 +index 909968952a7ae2aa0196f12d1b3177cade380db2..1fcb01abc93c3c6ad172f209f55421d8b98629d5 100644 --- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java @@ -17,7 +17,11 @@ import net.kyori.adventure.text.event.ClickEvent; diff --git a/Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch b/Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch index 99e9b4058c..43f4080f06 100644 --- a/Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch +++ b/Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch @@ -6,7 +6,7 @@ Subject: [PATCH] EntityRegainHealthEvent isFastRegen API Don't even get me started diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index acbd10432b09172f7541b2f4081d1aa9812194ac..ecb07130be80b484e0f2241a368db967775148e8 100644 +index 375284b7e321cb03a7a30aedea165ca7a2fd1091..db5c0d2da9ed9993ee83adccfa74e77f4e364f2a 100644 --- a/src/main/java/net/minecraft/world/entity/EntityLiving.java +++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java @@ -1130,10 +1130,16 @@ public abstract class EntityLiving extends Entity { diff --git a/Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch b/Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch index f215104b52..a59d0ec3f4 100644 --- a/Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch +++ b/Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch @@ -6,7 +6,7 @@ Subject: [PATCH] remove null possibility for getServer singleton to stop IDE complaining about potential NPE diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 026ddfba26439a00685f3962084aa6194086c9b7..f990f242a8d812a93b454b065a17fd4e8170355a 100644 +index 8df60cedc1198916dfce8fcea7ca4a49f98429ba..ed00ee8e56e6ca38a1ac689458c4675eff6e3eea 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -180,6 +180,7 @@ import org.spigotmc.SlackActivityAccountant; // Spigot diff --git a/Spigot-Server-Patches/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch b/Spigot-Server-Patches/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch index 73619accb6..583690ace0 100644 --- a/Spigot-Server-Patches/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch +++ b/Spigot-Server-Patches/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch @@ -13,7 +13,7 @@ custom renderers are in use, defaulting to the much simpler Vanilla system. Additionally, numerous issues to player position tracking on maps has been fixed. diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 2412c2fa22abe171254f7fe49d319bcd6cc533ff..c4bbc4e97ee1871ed6e4364c1fe9204b0dd2fdae 100644 +index 75424a5dd6db57dded3b6d895e6b5b102e91c77e..c7652d6bff7630e2eefbb4c3b0deb6e17b9c98d0 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java +++ b/src/main/java/net/minecraft/server/level/WorldServer.java @@ -1170,6 +1170,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { diff --git a/Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch b/Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch index 7d27f20665..52eb70b9df 100644 --- a/Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch +++ b/Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch @@ -518,7 +518,7 @@ index 0000000000000000000000000000000000000000..9dae34370d014a291f025f83b55e18bf + } +} diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 6cbb797cb0de4b26d8ddd7f0bf567f49bd36f9c0..2b1b46bda48c0b137fe914c47a387e6e72a1be40 100644 +index 415935739716df3b8b3319aac19519d29aaa5776..092ee75f9527af25a48ab052659e3304986b50e0 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -158,6 +158,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne diff --git a/Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch b/Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch index e05a8f8155..1cbedf26ca 100644 --- a/Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch +++ b/Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch @@ -5,7 +5,7 @@ Subject: [PATCH] System property for disabling watchdoge diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 0cb3028872041ce9f75e57fdd84b79636d8809f3..882cd398ee6babc3088ea0bb442d61fb46d8bf08 100644 +index 69e5054886b5858664fed333aca8c25a76e5cb11..4e0291be4bd5876bb5b5f62ebfa156635d4c758f 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java @@ -61,7 +61,7 @@ public class WatchdogThread extends Thread diff --git a/Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch b/Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch index 3f1918cdd8..a7c61c2859 100644 --- a/Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch +++ b/Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch @@ -10,7 +10,7 @@ Additionally, move Saving of the User cache to be done async, incase the user never changed the default setting for Spigot's save on stop only. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f990f242a8d812a93b454b065a17fd4e8170355a..283c1111d99b6ae09b6db0c0079eeb0f1cbb7b2b 100644 +index ed00ee8e56e6ca38a1ac689458c4675eff6e3eea..20dffd9dc4cb3868638151b70535f353a3bf1a44 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -907,7 +907,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 256, < 0, is tr Keep them consistent diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index e008ef98d6902f5e1000da99870b12ae9d61bddb..6137a88e1dc8d19a4e35ad97500dabeddba008a8 100644 +index 811e80ebb65715b7cdd1443aa33186c3ce2ec70c..744ec6f09a1b3ccdf0d74fe50f1e1c913ee2df86 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java +++ b/src/main/java/net/minecraft/server/level/WorldServer.java @@ -847,7 +847,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { diff --git a/Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch index ece37f9326..ea0d507b64 100644 --- a/Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch +++ b/Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Remove FishingHook reference on Craft Entity removal diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -index f8e897f0bc4e5d0a432d20983fd37998bb00ae0f..b480ca876687991685b5e070181721da8192a5b6 100644 +index 4dd3deaabfdb383ded92920e1a313b61a1b9262b..4805bce05f2856289608f45df4fca322de161b31 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java @@ -119,4 +119,14 @@ public class CraftFishHook extends CraftProjectile implements FishHook { diff --git a/Spigot-Server-Patches/0116-Add-EntityZapEvent.patch b/Spigot-Server-Patches/0116-Add-EntityZapEvent.patch index 732e5f79ab..40404fd392 100644 --- a/Spigot-Server-Patches/0116-Add-EntityZapEvent.patch +++ b/Spigot-Server-Patches/0116-Add-EntityZapEvent.patch @@ -21,7 +21,7 @@ index cc31c8f31a385f3a8bfe334e75c3553689397750..d6e1697f64e60f2a567288c604a16901 if (CraftEventFactory.callPigZapEvent(this, entitylightning, entitypigzombie).isCancelled()) { return; diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 651ee45431c22b944fac640f936608ae587c055d..6df58fe8084d866de1697ef3fdbfe6648fe42b5f 100644 +index ef838bbcc23145ebd5203963923030a8f971cd6e..72ed4de72c87e9c241507838ddb42eaa4c05ef32 100644 --- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java @@ -787,6 +787,12 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation diff --git a/Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch b/Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch index 304934ac47..34efb26a3c 100644 --- a/Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch +++ b/Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Don't let fishinghooks use portals diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index bcc411107d531529dbce9d1d43896a3c70e63012..57e7b9c7f7f43666d442648120cda3b4b3e5bfb2 100644 +index 7402e3b305d9bb7b27b97ff2078c26dd578232a1..2067af9b13c7ce28cd8ad6c785e2d0a7ff013430 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java @@ -240,6 +240,11 @@ public class EntityFishingHook extends IProjectile { diff --git a/Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch b/Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch index 61881f07d2..011e094dc5 100644 --- a/Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch +++ b/Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Optimize ItemStack.isEmpty() Remove hashMap lookup every check, simplify code to remove ternary diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index d7c5065457d910f3e5481fda046d368d5f66f67b..58045d500a6fbb7eb568f48c7d8ce7730d357577 100644 +index 201ba7250b298f4a91bc45f5954f54ae557305f2..cac92ccacc9d5ff17c70ee266cf12bacce6242ea 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java @@ -208,7 +208,7 @@ public final class ItemStack { diff --git a/Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch b/Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch index 6b9000b823..8d198833bc 100644 --- a/Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch +++ b/Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add API methods to control if armour stands can move diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0631cd531647239858b2a7298f58cc770720f69a..6ee5e1b0bb34ba490a130fbcbdb7a2706c5ecf86 100644 +index 31bb5df7bc63c993230bf595bd9b66bfaadb4d50..ccdfc8068a8205d6e66ab9458764b1440f8c4b97 100644 --- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java +++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java @@ -38,6 +38,7 @@ import net.minecraft.world.entity.ai.control.ControllerLook; diff --git a/Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch b/Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch index 20f702475a..08c66ad7f1 100644 --- a/Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch +++ b/Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch @@ -18,7 +18,7 @@ index c8bb06a31242089ad950713bd5f94abbfe12adc8..68ce7605bd63ea280b96db8230463d2a public static Collector, ?, Map> a() { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 6d7f1dee9ae2fb0b9620d85969de86eee09020cc..c3058d6fca2fd58aea5001e4310592aa8bd20640 100644 +index 5698ef90bfeceec37eaf7f23361246ef125b3cd1..3ab71629699f4978cd2dab36ec7e3b32a1681f91 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -244,6 +244,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/Spigot-Server-Patches/0132-Firework-API-s.patch b/Spigot-Server-Patches/0132-Firework-API-s.patch index e42242de5c..c220b785aa 100644 --- a/Spigot-Server-Patches/0132-Firework-API-s.patch +++ b/Spigot-Server-Patches/0132-Firework-API-s.patch @@ -17,7 +17,7 @@ index bf4826e90976fed2ae95e84cadc7f29433af1ddf..d5508deff819309034554abc7b36aac4 NBTBase nbtbase = this.get(s); diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java -index 2df84b56ef35a18648e74a134ac7ab97c518e481..9cc59439ae2c4e758c44b2a92b78bc328efdfa1b 100644 +index 6ca5c8a4308c56d35bddbabc0be724325a8a73e3..ca7a10c4b04766d7eb55be9252e96ef939e76df3 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java +++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java @@ -38,7 +38,8 @@ public class EntityFireworks extends IProjectile { diff --git a/Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch b/Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch index 6618bb4dd0..753735ecac 100644 --- a/Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch +++ b/Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch @@ -7,7 +7,7 @@ Provides counts without the ineffeciency of using .getEntities().size() which creates copy of the collections. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 5c488c8a40c648c5c432d38d95d3e00fde2cdb75..642efd930dc6cfad1d9436df97f151ea69b24b0c 100644 +index b50ed67714fea93fc6708f2680ae909f403deb00..29f5311260d0d5ee321db94031ffc3ed528d6b02 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -282,6 +282,48 @@ public class CraftWorld implements World { diff --git a/Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch b/Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch index cde18f2475..92ee3f9334 100644 --- a/Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch +++ b/Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch @@ -7,7 +7,7 @@ Saving players async is extremely dangerous. This will force it to main the same way we handle async chunk loads. diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 95ff827b1d5704d279d258bdfb43fd33ec7a9187..d7cf89f4603779ce9a2e9a6f837a81684f209826 100644 +index 49f1aed92fd5fa46b74a979f317a2eb0672991e9..f0928684f2bb56b490bea7cd80eb9300d2647f0c 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -1047,11 +1047,13 @@ public abstract class PlayerList { diff --git a/Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch index 1bdda8112e..1fd6d1e437 100644 --- a/Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch +++ b/Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch @@ -101,7 +101,7 @@ index a17812943b5402684c68ddeac5408dc939e42cf6..f4da22b33c704e675510b4b1a3aa7c18 @Override diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index dc715a0275b148c3c66610d6fb873626180c82d5..b66b340fdef9423ad8dce290065e028a0c135ea8 100644 +index db5c0d2da9ed9993ee83adccfa74e77f4e364f2a..f26f02856e7cca0ca62325adf992619dd15b3885 100644 --- a/src/main/java/net/minecraft/world/entity/EntityLiving.java +++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java @@ -1594,7 +1594,8 @@ public abstract class EntityLiving extends Entity { @@ -115,7 +115,7 @@ index dc715a0275b148c3c66610d6fb873626180c82d5..b66b340fdef9423ad8dce290065e028a this.expToDrop = 0; } diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java -index 8d0c7469999bb6d75debf427ff4d7fa5d2d5c505..28dd42921961c6a47f2d85a5f93b8298f2c228d3 100644 +index b9a681c2f7435c38dda074fbabbf53974ebbc705..4de0a733819d408e8b9a55b604f455281d7732c5 100644 --- a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java +++ b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java @@ -262,7 +262,7 @@ public abstract class EntityAnimal extends EntityAgeable { @@ -128,7 +128,7 @@ index 8d0c7469999bb6d75debf427ff4d7fa5d2d5c505..28dd42921961c6a47f2d85a5f93b8298 // CraftBukkit end } diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -index 7941a083353bb1d9ba81c41d7a566b72bdc955d9..459b7727e946679989477f4a7e99c5ca47ac0b30 100644 +index c1e3b90098605cf809aa2ecfb5edc0ad78f2257c..77de0706aaa32b565cb1e14754e93a1c4a6e15bd 100644 --- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java @@ -1306,7 +1306,7 @@ public class EntityFox extends EntityAnimal { @@ -167,7 +167,7 @@ index 74802de01dba30e38e09f6fc1f61e7bb64cf5f09..97ef4c65c8cc569a99d9697f56bd44d3 } diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 3604fffb9ba13a019e98e0a1a0ef7ba81c8dc329..adce6f17a5dd33004f8a67cd55d195de029e0263 100644 +index 72ed4de72c87e9c241507838ddb42eaa4c05ef32..881bca30d2271560e2f2063f7d50753ec67a23f6 100644 --- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java @@ -600,7 +600,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation @@ -193,7 +193,7 @@ index 46da22aeef6132a96e413301935c4fef7a96e0ee..4f81a97b1451fec0bb5fd1479acad978 } diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 57e7b9c7f7f43666d442648120cda3b4b3e5bfb2..d40b056b2ff14033113bd7108a3295f8783b8bdf 100644 +index 2067af9b13c7ce28cd8ad6c785e2d0a7ff013430..38bcc5a4435c4018b3233cc5e4c9142259e4396d 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java @@ -503,7 +503,7 @@ public class EntityFishingHook extends IProjectile { @@ -278,7 +278,7 @@ index 9744d51a52c5eb99c4cf9e36d9380c49674dd136..deaa4c136c23dc6c258cc1ce68523b3c } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index ccd110c4bfaa263e04154dcc2a5bdbff1f3a7ec2..2513e9a5b66598337f5d380a036ee10fdbab38c3 100644 +index 29f5311260d0d5ee321db94031ffc3ed528d6b02..d7d58a0feac2d0b4303c625b7952103613e8c33e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -1835,7 +1835,7 @@ public class CraftWorld implements World { diff --git a/Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch b/Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch index 5f443dacfc..d620a07721 100644 --- a/Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch +++ b/Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch @@ -27,7 +27,7 @@ index 2dc58b9f769ea43b737804456aafab47ecc143b8..c611b5a63498f5ad1f50a75ccd5d7299 + } } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 49da1525cfc46743013bbac0528ec58501cab6eb..b798190628c1d83b5bf9e5497b515ef1e9f26707 100644 +index 00e79363b3f961111595c50758332f6c1c1b31bb..dcaf5c107bb77b63333f924a33961f9e5cad7082 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -268,6 +268,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne @@ -39,7 +39,7 @@ index 49da1525cfc46743013bbac0528ec58501cab6eb..b798190628c1d83b5bf9e5497b515ef1 // Spigot end diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 6fa269cec002fcffd6d02125c20efa9314148243..2eee92f74a7c82ec7df05db6df79743b4345cc86 100644 +index f26f02856e7cca0ca62325adf992619dd15b3885..dd9c51b28e32389429887e9c9cef0a554eff8a40 100644 --- a/src/main/java/net/minecraft/world/entity/EntityLiving.java +++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java @@ -2903,8 +2903,11 @@ public abstract class EntityLiving extends Entity { diff --git a/Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch index a382dd4190..3d1bc3912d 100644 --- a/Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch +++ b/Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index e8150c456efe72a561d6a6a7647eca05fbc8bd94..56f83a930c3dad1a1de366bff530131d92b4893c 100644 +index 2511fbe7aa5ff1ace71b513d2938975e388295c6..1d71a19a7bbe463f537861531113dd1ed3e5b977 100644 --- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java @@ -121,7 +121,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { diff --git a/Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch b/Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch index 31754281aa..4141d9b9b2 100644 --- a/Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch +++ b/Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Do not let armorstands drown diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 2eee92f74a7c82ec7df05db6df79743b4345cc86..3d6b8fd09c07e78c0d786dff9658eb0089f853cf 100644 +index dd9c51b28e32389429887e9c9cef0a554eff8a40..036577b0237e9c8a7ab22ede7477eefa1abecf96 100644 --- a/src/main/java/net/minecraft/world/entity/EntityLiving.java +++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java @@ -338,6 +338,7 @@ public abstract class EntityLiving extends Entity { diff --git a/Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch b/Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch index 4db53e8336..108fec7080 100644 --- a/Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch +++ b/Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch @@ -30,7 +30,7 @@ will have plugins and worlds saving to the disk has a high potential to result in corruption/dataloss. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 283c1111d99b6ae09b6db0c0079eeb0f1cbb7b2b..d92ca78e483b3f085e3bad1d1250cac2f9031fa7 100644 +index 20dffd9dc4cb3868638151b70535f353a3bf1a44..fae7e4a7adcc930a7252634dc535339b5a5bd3b9 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -201,6 +201,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 100) { // Spigot diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index f2d48659fdb9f030dbeec12ed820062d4d066e48..5122afbd51c87c27efa82d7d9393f252efa848d4 100644 +index 34b68443ff300f8626e9f7a8335cff75580bebfc..8c497da1a4bde904e234a8fa00bf04a12787c7ed 100644 --- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java @@ -557,6 +557,15 @@ public class ChunkProviderServer extends IChunkProvider { diff --git a/Spigot-Server-Patches/0362-Anti-Xray.patch b/Spigot-Server-Patches/0362-Anti-Xray.patch index ff640d6ee9..ddd0aa5463 100644 --- a/Spigot-Server-Patches/0362-Anti-Xray.patch +++ b/Spigot-Server-Patches/0362-Anti-Xray.patch @@ -1173,7 +1173,7 @@ index d86b1e528b53db809ac993aa2f1d2799d4f1a574..fbd8a6985a261396789c87e4b687140b public void a(BlockPosition blockposition, PacketPlayInBlockDig.EnumPlayerDigType packetplayinblockdig_enumplayerdigtype, String s) { diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index d7fe6f00b352dad9e9f579f9af86cb8b90ef83ae..e2c0d30c5b25f9c44025f0619ba254c89402d9f9 100644 +index 12e34e1514f060ffef96cdd3ac57d0495dd37321..024e0bf39b73076fba5c4187c4ff5066e663cf7e 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java +++ b/src/main/java/net/minecraft/server/level/WorldServer.java @@ -210,7 +210,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { diff --git a/Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch b/Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch index ff018b9221..63ff602a83 100644 --- a/Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch +++ b/Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Mark entities as being ticked when notifying navigation diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index e2c0d30c5b25f9c44025f0619ba254c89402d9f9..9012c837c2f284e9f2f11462e6dc7e2f6e190939 100644 +index 024e0bf39b73076fba5c4187c4ff5066e663cf7e..3eb337d42f0292ed7b85a5fdbf6b450bc446b81a 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java +++ b/src/main/java/net/minecraft/server/level/WorldServer.java @@ -1475,6 +1475,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { diff --git a/Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch b/Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch index 797e054aa8..7b764afb8b 100644 --- a/Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch +++ b/Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch @@ -8,7 +8,7 @@ ticket level 33 (yes getChunkIfLoaded will actually perform a chunk load in that case). diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index bb6c59237702bf82d2c344c864f233c606fd429f..96723cac5723ea97780dd3b8697c4ba598788afc 100644 +index 52d22da115212eae6c380bb5012398e3df92f5f3..13c99bdb8894d08f297f84ee1f98f50c811f7f4b 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java +++ b/src/main/java/net/minecraft/server/level/WorldServer.java @@ -207,7 +207,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { @@ -21,7 +21,7 @@ index bb6c59237702bf82d2c344c864f233c606fd429f..96723cac5723ea97780dd3b8697c4ba5 // Paper start - Asynchronous IO diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index fa0b7edf42243d53d9dc897903b9b9e902b33cf7..eee5b3e4645ae41f63aba8898c58f43402d31b73 100644 +index d74d6abfff647c148e524905cd733c4b7fc6591f..24dfdb3807dbf6e9acc59d35d7c76f7ac0185219 100644 --- a/src/main/java/net/minecraft/server/network/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java @@ -1244,7 +1244,7 @@ public class PlayerConnection implements PacketListenerPlayIn { diff --git a/Spigot-Server-Patches/0370-Reduce-sync-loads.patch b/Spigot-Server-Patches/0370-Reduce-sync-loads.patch index 5bdc3d95e4..7b195978a9 100644 --- a/Spigot-Server-Patches/0370-Reduce-sync-loads.patch +++ b/Spigot-Server-Patches/0370-Reduce-sync-loads.patch @@ -281,7 +281,7 @@ index 0000000000000000000000000000000000000000..d381f91cf105bfc01846ada90da8971a + } +} diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 1e74299bb3a368dcbc813408804d25cf58a75b0b..662d7f418e8acc9503ebf43e09410e7bd50f6bb3 100644 +index 2a5df37a94b4b609a2d1b045f8e6a7f08d3f8eaa..24201665f8e7fb635839334308a1bad8fc4ac7b9 100644 --- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java @@ -494,6 +494,7 @@ public class ChunkProviderServer extends IChunkProvider { @@ -293,7 +293,7 @@ index 1e74299bb3a368dcbc813408804d25cf58a75b0b..662d7f418e8acc9503ebf43e09410e7b this.serverThreadQueue.awaitTasks(completablefuture::isDone); com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 96723cac5723ea97780dd3b8697c4ba598788afc..02a64a132502fff19a41d4fa5ffafd61992865a4 100644 +index 13c99bdb8894d08f297f84ee1f98f50c811f7f4b..fbb550cce96e7e5539c69bae1459326090d0c508 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java +++ b/src/main/java/net/minecraft/server/level/WorldServer.java @@ -282,6 +282,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { diff --git a/Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch index be87abbafa..4968b9eb2f 100644 --- a/Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch +++ b/Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch @@ -7,7 +7,7 @@ If the Bukkit generator already has a spawn, use it immediately instead of spending time generating one that we won't use diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index ef13e310a8a452d2ba1d9c8bac72f9baf2693de0..a118187e86238fd4019ba5c25269d5ee80fc56f2 100644 +index e6e8ab0b39a11b0aed247b9b80a6c1f97505546b..eb134ccb68dc135ab6db4c5a1d29edb321cf3f59 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -630,12 +630,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant entitytypes = entity.getEntityType(); int i = entitytypes.getChunkRange() * 16; diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index a71531d6d329b11b9ad535786d26c4c2327bcbb9..8159baec6e862580dc340d8fd7c16013ec8f0e66 100644 +index 2e45f9006eba3b52916d2fccf8f2bebe7b8b8a9c..35fc51ac93a62f6dc4b141dc94a3cda0399f0ce1 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java +++ b/src/main/java/net/minecraft/server/level/WorldServer.java @@ -1531,7 +1531,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { diff --git a/Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch b/Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch index b289eb0159..c69af5d666 100644 --- a/Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch +++ b/Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch @@ -42,7 +42,7 @@ index 9af1d81475d2def60a682ed23e88f1afbbc4c7e6..0a99ee6221c46043ecdf9e9df7a064aa entityplayer1.setPosition(entityplayer1.locX(), entityplayer1.locY() + 1.0D, entityplayer1.locZ()); } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f95aa9b4cc53c1e3258b7b32249ec1c3ef4ae2f1..7bce3722fb00194f5a913c0b9866b73cfc74611d 100644 +index a9d8baef5db0655742e85482604db6f6208eb9b6..6c368921f76fb6eb99dd20dd49d6ba5ac80cdfad 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -169,6 +169,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne diff --git a/Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch b/Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch index 4590de9317..2b28126ee7 100644 --- a/Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch +++ b/Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch @@ -28,7 +28,7 @@ index 6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1..cd248eb6be663e8be33f2c3c6b06b77b + } } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index c86c3cdea77369e3297548c8d5f10674c1100f76..54738ef346b1fe4c45ea95db2f236d10f8525a20 100644 +index b4e058794c3f8a827f3aabab5b98239a4c79c42c..34c273178e711466ec6638f24e0371554e26e134 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -777,7 +777,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant UNKNOWN = a("unknown", Comparator.comparingLong(ChunkCoordIntPair::pair), 1); public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 09ceac61f873ee0cb689c66a403c42677961011d..06e2b48ed6d6d52d0eb17301254ed07fb69cb8af 100644 +index 2e995103fba15c21dbe89321896c7df03ae5e67b..ef2aa000932c222e358789fcd2629dd8a46cfe80 100644 --- a/src/main/java/net/minecraft/server/network/LoginListener.java +++ b/src/main/java/net/minecraft/server/network/LoginListener.java @@ -88,7 +88,7 @@ public class LoginListener implements PacketLoginInListener { @@ -93,7 +93,7 @@ index 09ceac61f873ee0cb689c66a403c42677961011d..06e2b48ed6d6d52d0eb17301254ed07f if (entityplayer != null) { this.g = LoginListener.EnumProtocolState.DELAY_ACCEPT; diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index f02ddd53df4674a2b5e0bb142db756d1f153d69b..443247b03b8352c4dd453270dccdbd7eb5f0944b 100644 +index 8a8f75acdd55e00ac2e7b5c621d1f522208df2c2..7c1d25feab71c325ce2379afa6c61732eebd74f9 100644 --- a/src/main/java/net/minecraft/server/network/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java @@ -222,6 +222,7 @@ public class PlayerConnection implements PacketListenerPlayIn { @@ -292,7 +292,7 @@ index 66c1a9ca392b29fe2191577d32c70b214fa7293d..c7e78d0626fa0dd18021c1a0827a10c0 Iterator iterator = list.iterator(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 7bce3722fb00194f5a913c0b9866b73cfc74611d..8ca7012264528f17ac2e4f15ced96c774fa566d7 100644 +index 6c368921f76fb6eb99dd20dd49d6ba5ac80cdfad..896b4d016de78e98276d7cdf9328d8951572e3be 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1372,7 +1372,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne diff --git a/Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch b/Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch index 325aa1c5a1..c5cfc7c622 100644 --- a/Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch +++ b/Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add PlayerAttackEntityCooldownResetEvent diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index dc9e12c38d1682f6c4558ca07b781de2226c0621..850225509a5398ddcc9335bf88e99bde662bfc91 100644 +index 40fb7e96af7bbbe6c5586fa4d2a629b5a8f7b07a..13896da2194cab683782504291ede6f135ca7279 100644 --- a/src/main/java/net/minecraft/world/entity/EntityLiving.java +++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java @@ -1931,7 +1931,16 @@ public abstract class EntityLiving extends Entity { diff --git a/Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch b/Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch index a9be98b326..16614706f6 100644 --- a/Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch +++ b/Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch @@ -69,7 +69,7 @@ index eb2c9d2248a8647beee9960c5016a83f35aa1247..b5ee789c8dfb7f413ab60902ff3d2ef0 public boolean hasPermission(int i) { // CraftBukkit start diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 443247b03b8352c4dd453270dccdbd7eb5f0944b..b6d326ea30a806240e4a87c277b3cd73a04c805c 100644 +index 7c1d25feab71c325ce2379afa6c61732eebd74f9..358d1acf7ca9ce510325fedf31e18a27c3a784d5 100644 --- a/src/main/java/net/minecraft/server/network/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java @@ -770,8 +770,12 @@ public class PlayerConnection implements PacketListenerPlayIn { diff --git a/Spigot-Server-Patches/0459-Villager-Restocks-API.patch b/Spigot-Server-Patches/0459-Villager-Restocks-API.patch index d136893c45..55095b2a01 100644 --- a/Spigot-Server-Patches/0459-Villager-Restocks-API.patch +++ b/Spigot-Server-Patches/0459-Villager-Restocks-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Villager Restocks API diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index d7e152f7147bb599ce21dc605ebbd76e82eced26..d2850b003f8672122e70da0d52da1de59b2b01dd 100644 +index 596450d3cdb3be4abca3e75bed743abd071fb0b0..fb97325e8df33c0edabb81053877ad4a326a3d34 100644 --- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java @@ -113,7 +113,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation diff --git a/Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch b/Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch index 37c6dde53b..2c474587ad 100644 --- a/Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch +++ b/Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Validate PickItem Packet and kick for invalid diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index b6d326ea30a806240e4a87c277b3cd73a04c805c..6db70005ebc99b19185b8efca550a0783ea05cad 100644 +index 358d1acf7ca9ce510325fedf31e18a27c3a784d5..b491a3563bf457bcb631e05cf41b661712134966 100644 --- a/src/main/java/net/minecraft/server/network/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java @@ -883,7 +883,14 @@ public class PlayerConnection implements PacketListenerPlayIn { diff --git a/Spigot-Server-Patches/0461-Expose-game-version.patch b/Spigot-Server-Patches/0461-Expose-game-version.patch index 9bfccda9ba..24b6d2653e 100644 --- a/Spigot-Server-Patches/0461-Expose-game-version.patch +++ b/Spigot-Server-Patches/0461-Expose-game-version.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Expose game version diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 1ec08b8d1f8104dcdfa00bc0c53c26b7796c514d..7d19942373523f18eb9420d0873f2309895b34d7 100644 +index 63f89916d9982caa99525e01bd0e3f153af74d0f..f6e2e54b5a1b8c2df41a0593fa15112c5195c49c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -515,6 +515,13 @@ public final class CraftServer implements Server { diff --git a/Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch index 8676a856f7..52eb1dbcaa 100644 --- a/Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch +++ b/Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch @@ -17,7 +17,7 @@ keeping long lived large direct buffers in cache. Set system properly at server startup if not set already to help protect from this. diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 777116a0a0be6a5a00b1443204d6c53803af8051..6cae7454f3cf5b246300bac489b38ea65e2185c9 100644 +index 5c54ecf6b1cf5531e51ae4d0a318aa64b837b574..6459ec144fa54a1e6ad1f0c40776321e95b41197 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -28,6 +28,7 @@ public class Main { diff --git a/Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch b/Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch index 3af6a3cc25..0eecb7f13e 100644 --- a/Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch +++ b/Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Use distance map to optimise entity tracker Use the distance map to find candidate players for tracking. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 11a412b1df98dea2826330b0b246655844a4f4ea..1d77d6254b024c286781be8dc74680bc1e8f1238 100644 +index 7f67773686a2d55153f7b2bfbe24df84fe1198be..1eb1da61ee2aa2cc5d28a46fd364a182cd16983b 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1654,6 +1654,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant> e = new WeightedList<>(); + private final WeightedList> e = new WeightedList<>(false); // Paper - don't use a clone - + public BehaviorGate(Map, MemoryStatus> map, Set> set, BehaviorGate.Order behaviorgate_order, BehaviorGate.Execution behaviorgate_execution, List, Integer>> list) { super(map); @@ -65,10 +65,9 @@ public class BehaviorGate extends Behavior { @@ -25,25 +25,25 @@ index dc926f7e59fa350902d4a24aefc3df3eac7d75db..2d4345de154fb2d31f34695672ebdb4d }); - Set set = this.b; BehaviorController behaviorcontroller = e0.getBehaviorController(); - + - set.forEach(behaviorcontroller::removeMemory); + this.b.forEach(behaviorcontroller::removeMemory); // Paper - decomp fix } - + @Override @@ -115,7 +114,7 @@ public class BehaviorGate extends Behavior { - + private final Consumer> c; - + - private Order(Consumer consumer) { + private Order(Consumer> consumer) { // Paper - decomp fix this.c = consumer; } - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java + +diff --git a/src/main/java/net/minecraft/util/random/WeightedRandomList.java b/src/main/java/net/minecraft/util/random/WeightedRandomList.java index f6f8c68ff3642e28901094e8b501fcf8ec2cecd7..1ca9b0595ae9d914d23590ec0b0c2e857c39b250 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java +--- a/src/main/java/net/minecraft/util/random/WeightedRandomList.java ++++ b/src/main/java/net/minecraft/util/random/WeightedRandomList.java @@ -6,7 +6,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.Dynamic; @@ -54,14 +54,14 @@ index f6f8c68ff3642e28901094e8b501fcf8ec2cecd7..1ca9b0595ae9d914d23590ec0b0c2e85 import java.util.List; import java.util.Random; @@ -14,26 +14,32 @@ import java.util.stream.Stream; - + public class WeightedList { - + - protected final List> a; + protected final List> list; // Paper - decompile conflict private final Random b; + private final boolean isUnsafe; // Paper - + - public WeightedList() { - this(Lists.newArrayList()); + // Paper start - add useClone option @@ -69,7 +69,7 @@ index f6f8c68ff3642e28901094e8b501fcf8ec2cecd7..1ca9b0595ae9d914d23590ec0b0c2e85 + public WeightedList(boolean isUnsafe) { + this(Lists.newArrayList(), isUnsafe); } - + - private WeightedList(List> list) { + private WeightedList(List> list) { this(list, true); } + private WeightedList(List> list, boolean isUnsafe) { @@ -79,7 +79,7 @@ index f6f8c68ff3642e28901094e8b501fcf8ec2cecd7..1ca9b0595ae9d914d23590ec0b0c2e85 - this.a = Lists.newArrayList(list); + this.list = Lists.newArrayList(list); // Paper - decompile conflict } - + public static Codec> a(Codec codec) { - return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { - return weightedlist.a; @@ -87,16 +87,16 @@ index f6f8c68ff3642e28901094e8b501fcf8ec2cecd7..1ca9b0595ae9d914d23590ec0b0c2e85 + return weightedlist.list; // Paper - decompile conflict }); } - + public WeightedList a(U u0, int i) { - this.a.add(new WeightedList.a<>(u0, i)); + this.list.add(new WeightedList.a<>(u0, i)); // Paper - decompile conflict return this; } - + @@ -42,21 +48,20 @@ public class WeightedList { } - + public WeightedList a(Random random) { - this.a.forEach((weightedlist_a) -> { - weightedlist_a.a(random.nextFloat()); @@ -112,26 +112,26 @@ index f6f8c68ff3642e28901094e8b501fcf8ec2cecd7..1ca9b0595ae9d914d23590ec0b0c2e85 + return isUnsafe ? new WeightedList<>(list, isUnsafe) : this; + // Paper end } - + public boolean b() { - return this.a.isEmpty(); + return this.list.isEmpty(); // Paper - decompile conflict } - + public Stream c() { - return this.a.stream().map(WeightedList.a::a); + return this.list.stream().map(WeightedList.a::a); // Paper - decompile conflict } - + public U b(Random random) { @@ -64,7 +69,7 @@ public class WeightedList { } - + public String toString() { - return "WeightedList[" + this.a + "]"; + return "WeightedList[" + this.list + "]"; // Paper - decompile conflict } - + public static class a { @@ -98,11 +103,7 @@ public class WeightedList { return new Codec>() { diff --git a/Spigot-Server-Patches/0538-Incremental-player-saving.patch b/Spigot-Server-Patches/0538-Incremental-player-saving.patch index 34068fff0e..a7deadb443 100644 --- a/Spigot-Server-Patches/0538-Incremental-player-saving.patch +++ b/Spigot-Server-Patches/0538-Incremental-player-saving.patch @@ -25,7 +25,7 @@ index b67ba8f75e4a3358d7c2462918b85b0bf9b5a922..fdbd8b89bb8bf3b61f60b812b90483c9 + } } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f26a17228f724906bfcaeba5a28daf7d9cc3d2b0..f2b1d15479bf1a0e510c3416a4d520149d439085 100644 +index afdbbe62eba7b4f0ad63c5126c6d21488c4e9a7a..5acc6cfa96084728f45cfbec0ff9571e5dd0b844 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1349,9 +1349,15 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 6.0F) { double d0 = (entity.locX() - this.locX()) / (double) f; diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index ff482e3774f580d8ba7028f6c5141888d3bd907a..a246edd09854dabf095da75c9d200f5cf26e7138 100644 +index 969e5fa3080a98850f03ba64c5662c32a8d501a6..5c7fafeb7fab584eded30ebe415584132f4ab8af 100644 --- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java +++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java @@ -88,6 +88,7 @@ import org.bukkit.event.entity.EntityTargetEvent; diff --git a/Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch b/Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch index dc18792789..091e48b00a 100644 --- a/Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch +++ b/Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Skip distance map update when spawning disabled. diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 326c52f9f2cc729fd52162aeae18ec9dae3a4eaf..c5e54c519e1f686761faa53b5e9579c514a65332 100644 +index 6770307d69c6b3934bfa804fd713cade22f0fb5c..4a71f9a8a57ed123b31c725a8bd5f94ab0e2174d 100644 --- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java @@ -825,7 +825,7 @@ public class ChunkProviderServer extends IChunkProvider { diff --git a/Spigot-Server-Patches/0664-EntityMoveEvent.patch b/Spigot-Server-Patches/0664-EntityMoveEvent.patch index 4cca37da25..27ba6bd593 100644 --- a/Spigot-Server-Patches/0664-EntityMoveEvent.patch +++ b/Spigot-Server-Patches/0664-EntityMoveEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] EntityMoveEvent diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index c2a2a14164d2431413c773fb5944ad68a8f6ad6b..f8446fd716a891a0b71675ccee6a6eac55fba87c 100644 +index fe02a46df9c652acf4a4bc0ed194522f400cda34..454bc4c7b2e54a75dd0510263165e41cf26b1751 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -13,6 +13,7 @@ import io.netty.buffer.ByteBuf; diff --git a/Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch b/Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch index 73c28af9be..d30fda385f 100644 --- a/Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch +++ b/Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch @@ -50,7 +50,7 @@ index 673948947bd918c1dbb6c4c99486b4200e3c09fe..2e83b8855070077e90e5ab2c4beae819 return IRegistry.ATTRIBUTE.get(CraftNamespacedKey.toMinecraft(attribute.getKey())); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index e574e2453c7bc848168ff24372d6772bd423b672..3d497f69f89455b88fba423de8effb3db83e7af4 100644 +index 278a1c886f15b75e62bfe4c872fc779eda83c988..9865eee8ec5e43f291968bfb2c4473260e5baf7c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -675,6 +675,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { diff --git a/Spigot-Server-Patches/0672-misc-debugging-dumps.patch b/Spigot-Server-Patches/0672-misc-debugging-dumps.patch index 5ba0cb2fae..da0840fc4c 100644 --- a/Spigot-Server-Patches/0672-misc-debugging-dumps.patch +++ b/Spigot-Server-Patches/0672-misc-debugging-dumps.patch @@ -29,7 +29,7 @@ index 0000000000000000000000000000000000000000..2d5494d2813b773e60ddba6790b750a9 + } +} diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f8446fd716a891a0b71675ccee6a6eac55fba87c..176a17582cb3b29a2ed430914ba8c0582bffe541 100644 +index 454bc4c7b2e54a75dd0510263165e41cf26b1751..879074df54e56a9275957a83c92b467094e95cd4 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -14,6 +14,7 @@ import io.netty.buffer.ByteBufOutputStream; diff --git a/Spigot-Server-Patches/0675-Expose-Tracked-Players.patch b/Spigot-Server-Patches/0675-Expose-Tracked-Players.patch index 5bb7b3c9ef..2ee6abd643 100644 --- a/Spigot-Server-Patches/0675-Expose-Tracked-Players.patch +++ b/Spigot-Server-Patches/0675-Expose-Tracked-Players.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Expose Tracked Players diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f7223f214f911dd25abcf3a52745588ec630241d..7abeeefeb579a43bc9ee85fd4150afacfb11c802 100644 +index 881db84a1afe2da5d30732c282f36b294c721c41..d62179765f93738e8444b507238b4fd79a1e9443 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -172,7 +172,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne diff --git a/Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch b/Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch index 68805931e4..78875ff589 100644 --- a/Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch +++ b/Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch @@ -20,7 +20,7 @@ index f1d384d2e235c52a00f4b6d5643ef3c1d163e94b..7ddeecc6496926350d59d9b8725a4b16 + } } diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 891905712903bf3ba241187791cfa995375430d5..229eabe0510e6c3660236ed0fb3e80d41074642c 100644 +index 170b085c76e092f6d7b14095c66c84fa9a96a1fc..635b1493eeb6c13cc5ef489bd747ac557bc131d8 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java @@ -104,6 +104,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { diff --git a/Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch b/Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch index 8ef92016d7..ef2fcdd893 100644 --- a/Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch +++ b/Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch @@ -21,7 +21,7 @@ index b13e6f9923a9c5703f4eaeab2d0c112e4726b496..a762cf4c4a52bcbc8dbfd60b3ad7fef5 this.w(); this.x(); diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index c4df472050622eb2469b2ddb4d2ed917994f6e95..52bb528e75eb43156ee2bf19877bc051a35bb6e3 100644 +index a5b1f33473e8c82511fdd0c218f4fe744f584de8..cac3df2ca054b3b2fb5b6437ab2950afc3ace8fb 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -198,6 +198,12 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer diff --git a/Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch b/Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch index 76154e688b..70f01cbb40 100644 --- a/Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch +++ b/Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch @@ -5,7 +5,7 @@ Subject: [PATCH] forced whitelist: use configurable kick message diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 176a17582cb3b29a2ed430914ba8c0582bffe541..d9ea784758fe52782042ce4b61faa915f895b3f8 100644 +index 879074df54e56a9275957a83c92b467094e95cd4..b3ebf5cd59c827b7426069eda0cb3d47b4386792 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -2042,7 +2042,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { + } + + } ++ // Paper start ++ public net.md_5.bungee.api.chat.BaseComponent[] components; ++ ++ public PacketPlayOutTitle(EnumTitleAction action, net.md_5.bungee.api.chat.BaseComponent[] components, int fadeIn, int stay, int fadeOut) { ++ this.a = action; ++ this.components = components; ++ this.c = fadeIn; ++ this.d = stay; ++ this.e = fadeOut; ++ } ++ // Paper end + + @Override + public void b(PacketDataSerializer packetdataserializer) throws IOException { +@@ -55,6 +66,8 @@ public class PacketPlayOutTitle implements Packet { + // Paper start + if (this.adventure$text != null) { + packetdataserializer.writeComponent(this.adventure$text); ++ } else if (this.components != null) { ++ packetdataserializer.writeComponent(this.components); + } else + // Paper end + packetdataserializer.a(this.b); diff --git a/scripts/remap.sh b/scripts/remap.sh index 7458070127..e47992e17b 100755 --- a/scripts/remap.sh +++ b/scripts/remap.sh @@ -11,7 +11,7 @@ minecrafthash=$(cat "${workdir}/BuildData/info.json" | grep minecraftHash | cut accesstransforms="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep accessTransforms | cut -d '"' -f 4) classmappings="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep classMappings | cut -d '"' -f 4) membermappings="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep memberMappings | cut -d '"' -f 4) -packagemappings="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep packageMappings | cut -d '"' -f 4) +#packagemappings="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep packageMappings | cut -d '"' -f 4) decompiledir="$workdir/Minecraft/$minecraftversion" jarpath="$decompiledir/$minecraftversion" mkdir -p "$decompiledir" @@ -26,22 +26,22 @@ if [ ! -f "$jarpath.jar" ]; then fi # OS X & FreeBSD don't have md5sum, just md5 -r -command -v md5sum >/dev/null 2>&1 || { - command -v md5 >/dev/null 2>&1 && { - shopt -s expand_aliases - alias md5sum='md5 -r' - echo "md5sum command not found, using an alias instead" - } || { - echo >&2 "No md5sum or md5 command found" - exit 1 - } -} - -checksum=$(md5sum "$jarpath.jar" | cut -d ' ' -f 1) -if [ "$checksum" != "$minecrafthash" ]; then - echo "The MD5 checksum of the downloaded server jar does not match the BuildData hash." - exit 1 -fi +#command -v md5sum >/dev/null 2>&1 || { +# command -v md5 >/dev/null 2>&1 && { +# shopt -s expand_aliases +# alias md5sum='md5 -r' +# echo "md5sum command not found, using an alias instead" +# } || { +# echo >&2 "No md5sum or md5 command found" +# exit 1 +# } +#} +# +#checksum=$(md5sum "$jarpath.jar" | cut -d ' ' -f 1) +#if [ "$checksum" != "$minecrafthash" ]; then +# echo "The MD5 checksum of the downloaded server jar does not match the BuildData hash." +# exit 1 +#fi # These specialsource commands are from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/builddata/browse/info.json echo "Applying class mappings..." @@ -55,7 +55,7 @@ fi echo "Applying member mappings..." if [ ! -f "$jarpath-m.jar" ]; then - java -jar "$workdir/BuildData/bin/SpecialSource-2.jar" map --only . --only net/minecraft --only com/mojang/math --auto-member LOGGER --auto-member TOKENS -i "$jarpath-cl.jar" -m "$membermappings" -o "$jarpath-m.jar" 1>/dev/null + java -jar "$workdir/BuildData/bin/SpecialSource-2.jar" map --only . --only com/mojang/math --only net/minecraft --auto-member TOKENS -i "$jarpath-cl.jar" -m "$membermappings" -o "$jarpath-m.jar" 1>/dev/null if [ "$?" != "0" ]; then echo "Failed to apply member mappings." exit 1 @@ -64,7 +64,7 @@ fi echo "Creating remapped jar..." if [ ! -f "$jarpath-mapped.jar" ]; then - java -jar "$workdir/BuildData/bin/SpecialSource.jar" --only . --only net/minecraft --only com/mojang/math -i "$jarpath-m.jar" --access-transformer "$accesstransforms" -m "$packagemappings" -o "$jarpath-mapped.jar" 1>/dev/null + java -jar "$workdir/BuildData/bin/SpecialSource.jar" --only . --only com/mojang/math --only net/minecraft -i "$jarpath-m.jar" --access-transformer "$accesstransforms" -m "/home/martin/Projects/Paper/bukkit-e3c5450d-fields.csrg" -o "$jarpath-mapped.jar" 1>/dev/null if [ "$?" != "0" ]; then echo "Failed to create remapped jar." exit 1 diff --git a/work/BuildData b/work/BuildData index f0a5ed1aef..3cec511b16 160000 --- a/work/BuildData +++ b/work/BuildData @@ -1 +1 @@ -Subproject commit f0a5ed1aeff8156ba4afa504e190c838dd1af50c +Subproject commit 3cec511b16ffa31cb414997a14be313716882e12 diff --git a/work/Bukkit b/work/Bukkit index 7e29f76544..5b94881a0b 160000 --- a/work/Bukkit +++ b/work/Bukkit @@ -1 +1 @@ -Subproject commit 7e29f7654411f0a17ebbcc2c3f6a7dfe93bff39e +Subproject commit 5b94881a0b4383f901c1c65db10767e42446760e diff --git a/work/CraftBukkit b/work/CraftBukkit index 296df56673..e2f5ea34e9 160000 --- a/work/CraftBukkit +++ b/work/CraftBukkit @@ -1 +1 @@ -Subproject commit 296df56673771692593156995684ab8041925d9d +Subproject commit e2f5ea34e9c7f9eb3eb2be422b169679922b2770 diff --git a/work/Spigot b/work/Spigot index 9fb885e86d..c9cea60004 160000 --- a/work/Spigot +++ b/work/Spigot @@ -1 +1 @@ -Subproject commit 9fb885e86def1d9d86e25233c9b5a4de45b7a09d +Subproject commit c9cea600043b1dc6fa306b4baee307d064c65eac From 211b20ffa5c7b9c751278d29d8e676d3459f2503 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Fri, 11 Jun 2021 09:45:34 +0200 Subject: [PATCH 002/226] Did anyone say gradle? and paperweight? potentially even mojmap?! --- .gitignore | 2 + .../additional-spigot-member-mappings.csrg | 24 +++ .../BehaviorWorkComposter.patch.patch | 17 ++ .../ChunkProviderServer.patch.patch | 40 ++++ build-data/library-imports.txt | 5 + build-data/mappings-patch.tiny | 76 +++++++ build.gradle.kts | 83 ++++++++ gradle.properties | 3 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 185 ++++++++++++++++++ gradlew.bat | 89 +++++++++ settings.gradle.kts | 11 ++ 13 files changed, 540 insertions(+) create mode 100644 build-data/additional-spigot-member-mappings.csrg create mode 100644 build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch create mode 100644 build-data/craftbukkit-patch-patches/ChunkProviderServer.patch.patch create mode 100644 build-data/library-imports.txt create mode 100644 build-data/mappings-patch.tiny create mode 100644 build.gradle.kts create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle.kts diff --git a/.gitignore b/.gitignore index b1e563f223..be158334f4 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,5 @@ Paperclip.jar paperclip.jar paperclip-*.jar paperclip.properties + +!gradle/wrapper/gradle-wrapper.jar diff --git a/build-data/additional-spigot-member-mappings.csrg b/build-data/additional-spigot-member-mappings.csrg new file mode 100644 index 0000000000..199b5419bf --- /dev/null +++ b/build-data/additional-spigot-member-mappings.csrg @@ -0,0 +1,24 @@ +# CraftBukkit maps all of (mojmap names): +# Merchant.getLevel() +# Hopper.getLevel() +# Entity.getCommandSenderWorld() +# to getWorld(), which confuses our ability to map this method properly. This patch disambiguates it +net/minecraft/world/level/block/entity/IHopper v ()Lnet/minecraft/world/level/World; getLevel +net/minecraft/world/entity/vehicle/EntityMinecartHopper v ()Lnet/minecraft/world/level/World; getLevel +net/minecraft/world/item/trading/IMerchant eV ()Lnet/minecraft/world/level/World; getLevel +net/minecraft/world/entity/npc/EntityVillagerAbstract eV ()Lnet/minecraft/world/level/World; getLevel + +# CraftBukkit mappings sometimes have mappings for child classes and not parent classes +# We handle this fine for deobf but this breaks reobf. These Patches fix those cases + +# BossBattle -> BossBattleServer +net/minecraft/world/BossBattle a (F)V setProgress +net/minecraft/world/BossBattle c (Z)Lnet/minecraft/world/BossBattle; setCreateFog +net/minecraft/world/BossBattle a (Z)Lnet/minecraft/world/BossBattle; setDarkenSky +net/minecraft/world/BossBattle b (Z)Lnet/minecraft/world/BossBattle; setPlayMusic + +# IChunkProvider -> ChunkProviderServer +net/minecraft/world/level/chunk/IChunkProvider b (II)Z isLoaded + +# BehaviorWorkComposter -> BehaviorWork +net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter a (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/npc/EntityVillager;)V doWork diff --git a/build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch b/build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch new file mode 100644 index 0000000000..a35b59fd5d --- /dev/null +++ b/build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.patch ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.patch +@@ -1,14 +1,5 @@ + --- a/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.java + +++ b/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.java +-@@ -24,7 +24,7 @@ +- public BehaviorWorkComposter() {} +- +- @Override +-- protected void a(WorldServer worldserver, EntityVillager entityvillager) { +-+ protected void doWork(WorldServer worldserver, EntityVillager entityvillager) { // PAIL +- Optional optional = entityvillager.getBehaviorController().getMemory(MemoryModuleType.JOB_SITE); +- +- if (optional.isPresent()) { + @@ -43,7 +43,7 @@ + BlockPosition blockposition = globalpos.getBlockPosition(); + diff --git a/build-data/craftbukkit-patch-patches/ChunkProviderServer.patch.patch b/build-data/craftbukkit-patch-patches/ChunkProviderServer.patch.patch new file mode 100644 index 0000000000..0372012c03 --- /dev/null +++ b/build-data/craftbukkit-patch-patches/ChunkProviderServer.patch.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/server/level/ChunkProviderServer.patch ++++ b/net/minecraft/server/level/ChunkProviderServer.patch +@@ -74,8 +74,8 @@ + + return playerchunk == null || playerchunk.oldTicketLevel > i; // CraftBukkit using oldTicketLevel for isLoaded checks + } + +- public boolean isLoaded(int i, int j) { +-@@ -282,19 +308,19 @@ ++ @Override ++@@ -283,19 +309,19 @@ + public boolean a(Entity entity) { + long i = ChunkCoordIntPair.pair(MathHelper.floor(entity.locX()) >> 4, MathHelper.floor(entity.locZ()) >> 4); + +@@ -98,7 +98,7 @@ + } + + private boolean a(long i, Function>> function) { +-@@ -316,11 +342,31 @@ ++@@ -317,11 +343,31 @@ + + @Override + public void close() throws IOException { +@@ -131,7 +131,7 @@ + public void tick(BooleanSupplier booleansupplier) { + this.world.getMethodProfiler().enter("purge"); + this.chunkMapDistance.purgeTickets(); +-@@ -340,12 +386,12 @@ ++@@ -341,12 +387,12 @@ + this.lastTickTime = i; + WorldData worlddata = this.world.getWorldData(); + boolean flag = this.world.isDebugWorld(); +@@ -146,7 +146,7 @@ + + this.world.getMethodProfiler().enter("naturalSpawnCount"); + int l = this.chunkMapDistance.b(); +-@@ -532,12 +578,18 @@ ++@@ -533,12 +579,18 @@ + + @Override + protected boolean executeNext() { diff --git a/build-data/library-imports.txt b/build-data/library-imports.txt new file mode 100644 index 0000000000..68b9b8022c --- /dev/null +++ b/build-data/library-imports.txt @@ -0,0 +1,5 @@ +authlib com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java +datafixerupper com/mojang/datafixers/DataFixerBuilder.java +datafixerupper com/mojang/datafixers/util/Either.java +datafixerupper com/mojang/serialization/codecs/KeyDispatchCodec.java +datafixerupper com/mojang/serialization Dynamic.java diff --git a/build-data/mappings-patch.tiny b/build-data/mappings-patch.tiny new file mode 100644 index 0000000000..0833ee00b0 --- /dev/null +++ b/build-data/mappings-patch.tiny @@ -0,0 +1,76 @@ +tiny 2 0 spigot mojang+yarn + +# Originally DistanceManager, which also implements DistanceManager, so clashes since the implemented class +# is imported and not fully qualified. Easiest fix is to just change the name +c net/minecraft/server/level/PlayerChunkMap$a net/minecraft/server/level/ChunkMap$ChunkDistanceManager + +# CraftBukkit adds the getServer() method, clashes with a Mojang method +c net/minecraft/world/level/World net/minecraft/world/level/Level + m ()Lorg/bukkit/craftbukkit/CraftServer; getServer getCraftServer + +# CraftBukkit adds the server field, clashes with a Mojang field +c net/minecraft/server/network/PlayerConnection net/minecraft/server/network/ServerGamePacketListenerImpl + f Lorg/bukkit/craftbukkit/CraftServer; server craftServer + +# CraftBukkit adds the player field, clashes with a Mojang field +c net/minecraft/world/inventory/ContainerWorkbench net/minecraft/world/inventory/CraftingMenu + f Lnet/minecraft/world/entity/player/PlayerInventory; player playerInventory + +# CraftBukkit adds the getType() method, clashes with a Mojang method +c net/minecraft/world/entity/EntityAreaEffectCloud net/minecraft/world/entity/AreaEffectCloud + m ()Ljava/lang/String; getType getTypeCb + +# CraftBukkit adds the getType() method, clashes with a Mojang method +c net/minecraft/world/entity/projectile/EntityTippedArrow net/minecraft/world/entity/projectile/Arrow + m ()Ljava/lang/String; getType getTypeCb + +# CraftBukkit adds the getLevel() method, clashes with original method +c net/minecraft/world/level/block/entity/TileEntityBeacon net/minecraft/world/level/block/entity/BeaconBlockEntity + m ()I getLevel getLevelCb + +# CraftBukkit adds the getLootTable() method, clashes with original method +c net/minecraft/world/entity/EntityInsentient net/minecraft/world/entity/Mob + m ()Lnet/minecraft/resources/MinecraftKey; getLootTable getLootTableCb + +# CraftBukkit adds the canCollideWith() method, clashes with original method +c net/minecraft/world/entity/Entity net/minecraft/world/entity/Entity + m (Lnet/minecraft/world/entity/Entity;)Z canCollideWith canCollideWithCb + +# CraftBukkit adds a new `a` method which allows passing the Entity parameter +# It uses `a` to match the original method (with just 1 param), so this patch makes them match +c net/minecraft/server/level/WorldServer net/minecraft/server/level/ServerLevel + m (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/Entity;)V a makeObsidianPlatform + +# CraftBukkit adds `getMinecraftWorld()` to `GeneratorAccess`, which matches `WorldAccess.getMinecraftWorld()` +# But that method in `WorldAccess` is called `getLevel()` in Mojang mappings +c net/minecraft/world/level/GeneratorAccess net/minecraft/world/level/LevelAccessor + m ()Lnet/minecraft/server/level/WorldServer; getMinecraftWorld getLevel + +# SpecialSource2 automatically maps methods to the name of synthetic methods that point to it in an attempt to +# normalize method names with what is expected by the super class. This is _extremely_ stupid and flawed however +# because synthetic methods by definition have different descriptors than the base method, which means method +# signature clashes become possible, which is what happens here. +# +# LootEntryAbstract$Serializer has a synthetic method pointing to the base serialize() method with the following descriptor: +# +# (JsonObject,Object,JsonSerializationContext)V <-- ProGuard names this method `a` +# +# and this synthetic method points to another method with the specialized descriptor: +# +# (JsonObject,LootEntryAbstract,JsonSerializationContext)V <-- ProGuard names this method `b` +# +# SpecialSource2 automatically maps the second method name to the name of the first method, in this case `a`. +# +# LootEntryAbstract$Serializer also has another method with the same descriptor as serialize(), which Spigot calls +# serializeCustom(). Of course ProGuard strips the names and since this method is the first time it's seen this +# descriptor, it renamed that method also to `a`. +# +# This is allowed because the synthetic method for serialize() has a different descriptor, using Object as the second +# parameter. This breaks when SpecialSource2 does it's "magic" of course. This patch manually fixes this case by adding +# both correct mappings +c net/minecraft/world/level/storage/loot/entries/LootEntryAbstract$Serializer net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer$Serializer + m (Lcom/google/gson/JsonObject;Lnet/minecraft/world/level/storage/loot/entries/LootEntryAbstract;Lcom/google/gson/JsonSerializationContext;)V a serialize + p 0 json + p 1 entry + p 2 context + m (Lcom/google/gson/JsonObject;Lnet/minecraft/world/level/storage/loot/entries/LootEntryAbstract;Lcom/google/gson/JsonSerializationContext;)V serializeType serializeCustom diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000000..42b4fa89ba --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,83 @@ +plugins { + java + id("com.github.johnrengelman.shadow") version "7.0.0" apply false + id("io.papermc.paperweight") version "1.0.0-SNAPSHOT" +} + +group = "com.destroystokyo.paper" +version = providers.gradleProperty("projectVersion").forUseAtConfigurationTime().get() + +val mcVersion = providers.gradleProperty("mcVersion") +val packageVersion = providers.gradleProperty("packageVersion") + +allprojects { + apply(plugin = "java") + + java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(11)) + } + } +} + +subprojects { + tasks.withType().configureEach { + options.encoding = "UTF-8" + options.release.set(16) + } + + if (name == "Paper-MojangAPI") { + return@subprojects + } + + repositories { + mavenCentral() + maven("https://repo1.maven.org/maven2/") + maven("https://oss.sonatype.org/content/groups/public/") + maven("https://papermc.io/repo/repository/maven-public/") + maven("https://ci.emc.gs/nexus/content/groups/aikar/") + maven("https://repo.md-5.net/content/repositories/releases/") + maven("https://hub.spigotmc.org/nexus/content/groups/public/") + } +} + +repositories { + mavenLocal() + + maven("https://wav.jfrog.io/artifactory/repo/") { + content { + onlyForConfigurations("paperclip") + } + } + maven("https://maven.quiltmc.org/repository/release/") { + content { + onlyForConfigurations("paramMappings", "remapper") + } + } + maven("https://files.minecraftforge.net/maven/") { + content { + onlyForConfigurations("decompiler") + } + } +} + +dependencies { + paramMappings("org.quiltmc:yarn:1.16.5+build.6:mergedv2") + remapper("org.quiltmc:tiny-remapper:0.3.2:fat@jar") + decompiler("net.minecraftforge:forgeflower:1.5.498.5@jar") + paperclip("io.papermc:paperclip:2.0.0-SNAPSHOT@jar") +} + +paperweight { + minecraftVersion.set(mcVersion) + versionPackage.set(packageVersion) + serverProject.set(project(":Paper-Server")) + + paper { + mappingsPatch.set(file("build-data/mappings-patch.tiny")) + + additionalSpigotMemberMappings.set(file("build-data/additional-spigot-member-mappings.csrg")) + + craftBukkitPatchPatchesDir.set(file("build-data/craftbukkit-patch-patches")) + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000000..70f5bef212 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,3 @@ +mcVersion = 1.16 +projectVersion = 1.17-R0.1-SNAPSHOT +packageVersion = 1_17_R1 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f GIT binary patch literal 59203 zcma&O1CT9Y(k9%tZQHhO+qUh#ZQHhO+qmuS+qP|E@9xZO?0h@l{(r>DQ>P;GjjD{w zH}lENr;dU&FbEU?00aa80D$0M0RRB{U*7-#kbjS|qAG&4l5%47zyJ#WrfA#1$1Ctx zf&Z_d{GW=lf^w2#qRJ|CvSJUi(^E3iv~=^Z(zH}F)3Z%V3`@+rNB7gTVU{Bb~90p|f+0(v;nz01EG7yDMX9@S~__vVgv%rS$+?IH+oZ03D5zYrv|^ zC1J)SruYHmCki$jLBlTaE5&dFG9-kq3!^i>^UQL`%gn6)jz54$WDmeYdsBE9;PqZ_ zoGd=P4+|(-u4U1dbAVQrFWoNgNd;0nrghPFbQrJctO>nwDdI`Q^i0XJDUYm|T|RWc zZ3^Qgo_Qk$%Fvjj-G}1NB#ZJqIkh;kX%V{THPqOyiq)d)0+(r9o(qKlSp*hmK#iIY zA^)Vr$-Hz<#SF=0@tL@;dCQsm`V9s1vYNq}K1B)!XSK?=I1)tX+bUV52$YQu*0%fnWEukW>mxkz+%3-S!oguE8u#MGzST8_Dy^#U?fA@S#K$S@9msUiX!gd_ow>08w5)nX{-KxqMOo7d?k2&?Vf z&diGDtZr(0cwPe9z9FAUSD9KC)7(n^lMWuayCfxzy8EZsns%OEblHFSzP=cL6}?J| z0U$H!4S_TVjj<`6dy^2j`V`)mC;cB%* z8{>_%E1^FH!*{>4a7*C1v>~1*@TMcLK{7nEQ!_igZC}ikJ$*<$yHy>7)oy79A~#xE zWavoJOIOC$5b6*q*F_qN1>2#MY)AXVyr$6x4b=$x^*aqF*L?vmj>Mgv+|ITnw_BoW zO?jwHvNy^prH{9$rrik1#fhyU^MpFqF2fYEt(;4`Q&XWOGDH8k6M=%@fics4ajI;st# zCU^r1CK&|jzUhRMv;+W~6N;u<;#DI6cCw-otsc@IsN3MoSD^O`eNflIoR~l4*&-%RBYk@gb^|-JXs&~KuSEmMxB}xSb z@K76cXD=Y|=I&SNC2E+>Zg?R6E%DGCH5J1nU!A|@eX9oS(WPaMm==k2s_ueCqdZw| z&hqHp)47`c{BgwgvY2{xz%OIkY1xDwkw!<0veB#yF4ZKJyabhyyVS`gZepcFIk%e2 zTcrmt2@-8`7i-@5Nz>oQWFuMC_KlroCl(PLSodswHqJ3fn<;gxg9=}~3x_L3P`9Sn zChIf}8vCHvTriz~T2~FamRi?rh?>3bX1j}%bLH+uFX+p&+^aXbOK7clZxdU~6Uxgy z8R=obwO4dL%pmVo*Ktf=lH6hnlz_5k3cG;m8lgaPp~?eD!Yn2kf)tU6PF{kLyn|oI@eQ`F z3IF7~Blqg8-uwUuWZScRKn%c2_}dXB6Dx_&xR*n9M9LXasJhtZdr$vBY!rP{c@=)& z#!?L$2UrkvClwQO>U*fSMs67oSj2mxiJ$t;E|>q%Kh_GzzWWO&3;ufU%2z%ucBU8H z3WIwr$n)cfCXR&>tyB7BcSInK>=ByZA%;cVEJhcg<#6N{aZC4>K41XF>ZgjG`z_u& zGY?;Ad?-sgiOnI`oppF1o1Gurqbi*;#x2>+SSV6|1^G@ooVy@fg?wyf@0Y!UZ4!}nGuLeC^l)6pwkh|oRY`s1Pm$>zZ3u-83T|9 zGaKJIV3_x+u1>cRibsaJpJqhcm%?0-L;2 zitBrdRxNmb0OO2J%Y&Ym(6*`_P3&&5Bw157{o7LFguvxC$4&zTy#U=W*l&(Q2MNO} zfaUwYm{XtILD$3864IA_nn34oVa_g^FRuHL5wdUd)+W-p-iWCKe8m_cMHk+=? zeKX)M?Dt(|{r5t7IenkAXo%&EXIb-i^w+0CX0D=xApC=|Xy(`xy+QG^UyFe z+#J6h_&T5i#sV)hj3D4WN%z;2+jJcZxcI3*CHXGmOF3^)JD5j&wfX)e?-|V0GPuA+ zQFot%aEqGNJJHn$!_}#PaAvQ^{3-Ye7b}rWwrUmX53(|~i0v{}G_sI9uDch_brX&6 zWl5Ndj-AYg(W9CGfQf<6!YmY>Ey)+uYd_JNXH=>|`OH-CDCmcH(0%iD_aLlNHKH z7bcW-^5+QV$jK?R*)wZ>r9t}loM@XN&M-Pw=F#xn(;u3!(3SXXY^@=aoj70;_=QE9 zGghsG3ekq#N||u{4We_25U=y#T*S{4I{++Ku)> zQ!DZW;pVcn>b;&g2;YE#+V`v*Bl&Y-i@X6D*OpNA{G@JAXho&aOk(_j^weW{#3X5Y z%$q_wpb07EYPdmyH(1^09i$ca{O<}7) zRWncXdSPgBE%BM#by!E>tdnc$8RwUJg1*x($6$}ae$e9Knj8gvVZe#bLi!<+&BkFj zg@nOpDneyc+hU9P-;jmOSMN|*H#>^Ez#?;%C3hg_65leSUm;iz)UkW)jX#p)e&S&M z1|a?wDzV5NVnlhRBCd_;F87wp>6c<&nkgvC+!@KGiIqWY4l}=&1w7|r6{oBN8xyzh zG$b#2=RJp_iq6)#t5%yLkKx(0@D=C3w+oiXtSuaQ%I1WIb-eiE$d~!)b@|4XLy!CZ z9p=t=%3ad@Ep+<9003D2KZ5VyP~_n$=;~r&YUg5UZ0KVD&tR1DHy9x)qWtKJp#Kq# zP*8p#W(8JJ_*h_3W}FlvRam?<4Z+-H77^$Lvi+#vmhL9J zJ<1SV45xi;SrO2f=-OB(7#iNA5)x1uNC-yNxUw|!00vcW2PufRm>e~toH;M0Q85MQLWd?3O{i8H+5VkR@l9Dg-ma ze2fZ%>G(u5(k9EHj2L6!;(KZ8%8|*-1V|B#EagbF(rc+5iL_5;Eu)L4Z-V;0HfK4d z*{utLse_rvHZeQ>V5H=f78M3Ntg1BPxFCVD{HbNA6?9*^YIq;B-DJd{Ca2L#)qWP? zvX^NhFmX?CTWw&Ns}lgs;r3i+Bq@y}Ul+U%pzOS0Fcv9~aB(0!>GT0)NO?p=25LjN z2bh>6RhgqD7bQj#k-KOm@JLgMa6>%-ok1WpOe)FS^XOU{c?d5shG(lIn3GiVBxmg`u%-j=)^v&pX1JecJics3&jvPI)mDut52? z3jEA)DM%}BYbxxKrizVYwq?(P&19EXlwD9^-6J+4!}9{ywR9Gk42jjAURAF&EO|~N z)?s>$Da@ikI4|^z0e{r`J8zIs>SpM~Vn^{3fArRu;?+43>lD+^XtUcY1HidJwnR6+ z!;oG2=B6Z_=M%*{z-RaHc(n|1RTKQdNjjV!Pn9lFt^4w|AeN06*j}ZyhqZ^!-=cyGP_ShV1rGxkx8t zB;8`h!S{LD%ot``700d0@Grql(DTt4Awgmi+Yr0@#jbe=2#UkK%rv=OLqF)9D7D1j z!~McAwMYkeaL$~kI~90)5vBhBzWYc3Cj1WI0RS`z000R8-@ET0dA~*r(gSiCJmQMN&4%1D zyVNf0?}sBH8zNbBLn>~(W{d3%@kL_eQ6jEcR{l>C|JK z(R-fA!z|TTRG40|zv}7E@PqCAXP3n`;%|SCQ|ZS%ym$I{`}t3KPL&^l5`3>yah4*6 zifO#{VNz3)?ZL$be;NEaAk9b#{tV?V7 zP|wf5YA*1;s<)9A4~l3BHzG&HH`1xNr#%){4xZ!jq%o=7nN*wMuXlFV{HaiQLJ`5G zBhDi#D(m`Q1pLh@Tq+L;OwuC52RdW7b8}~60WCOK5iYMUad9}7aWBuILb({5=z~YF zt?*Jr5NG+WadM{mDL>GyiByCuR)hd zA=HM?J6l1Xv0Dl+LW@w$OTcEoOda^nFCw*Sy^I@$sSuneMl{4ys)|RY#9&NxW4S)9 zq|%83IpslTLoz~&vTo!Ga@?rj_kw{|k{nv+w&Ku?fyk4Ki4I?);M|5Axm)t+BaE)D zm(`AQ#k^DWrjbuXoJf2{Aj^KT zFb1zMSqxq|vceV+Mf-)$oPflsO$@*A0n0Z!R{&(xh8s}=;t(lIy zv$S8x>m;vQNHuRzoaOo?eiWFe{0;$s`Bc+Osz~}Van${u;g(su`3lJ^TEfo~nERfP z)?aFzpDgnLYiERsKPu|0tq4l2wT)Atr6Qb%m-AUn6HnCue*yWICp7TjW$@sO zm5rm4aTcPQ(rfi7a`xP7cKCFrJD}*&_~xgLyr^-bmsL}y;A5P|al8J3WUoBSjqu%v zxC;mK!g(7r6RRJ852Z~feoC&sD3(6}^5-uLK8o)9{8L_%%rItZK9C){UxB|;G>JbP zsRRtS4-3B*5c+K2kvmgZK8472%l>3cntWUOVHxB|{Ay~aOg5RN;{PJgeVD*H%ac+y!h#wi%o2bF2Ca8IyMyH{>4#{E_8u^@+l-+n=V}Sq?$O z{091@v%Bd*3pk0^2UtiF9Z+(a@wy6 zUdw8J*ze$K#=$48IBi1U%;hmhO>lu!uU;+RS}p&6@rQila7WftH->*A4=5W|Fmtze z)7E}jh@cbmr9iup^i%*(uF%LG&!+Fyl@LFA-}Ca#bxRfDJAiR2dt6644TaYw1Ma79 zt8&DYj31j^5WPNf5P&{)J?WlCe@<3u^78wnd(Ja4^a>{^Tw}W>|Cjt^If|7l^l)^Q zbz|7~CF(k_9~n|h;ysZ+jHzkXf(*O*@5m zLzUmbHp=x!Q|!9NVXyipZ3)^GuIG$k;D)EK!a5=8MFLI_lpf`HPKl=-Ww%z8H_0$j ztJ||IfFG1lE9nmQ0+jPQy zCBdKkjArH@K7jVcMNz);Q(Q^R{d5G?-kk;Uu_IXSyWB)~KGIizZL(^&qF;|1PI7!E zTP`%l)gpX|OFn&)M%txpQ2F!hdA~hX1Cm5)IrdljqzRg!f{mN%G~H1&oqe`5eJCIF zHdD7O;AX-{XEV(a`gBFJ9ews#CVS2y!&>Cm_dm3C8*n3MA*e67(WC?uP@8TXuMroq z{#w$%z@CBIkRM7?}Xib+>hRjy?%G!fiw8! z8(gB+8J~KOU}yO7UGm&1g_MDJ$IXS!`+*b*QW2x)9>K~Y*E&bYMnjl6h!{17_8d!%&9D`a7r&LKZjC<&XOvTRaKJ1 zUY@hl5^R&kZl3lU3njk`3dPzxj$2foOL26r(9zsVF3n_F#v)s5vv3@dgs|lP#eylq62{<-vczqP!RpVBTgI>@O6&sU>W|do17+#OzQ7o5A$ICH z?GqwqnK^n2%LR;$^oZM;)+>$X3s2n}2jZ7CdWIW0lnGK-b#EG01)P@aU`pg}th&J-TrU`tIpb5t((0eu|!u zQz+3ZiOQ^?RxxK4;zs=l8q!-n7X{@jSwK(iqNFiRColuEOg}!7cyZi`iBX4g1pNBj zAPzL?P^Ljhn;1$r8?bc=#n|Ed7wB&oHcw()&*k#SS#h}jO?ZB246EGItsz*;^&tzp zu^YJ0=lwsi`eP_pU8}6JA7MS;9pfD;DsSsLo~ogzMNP70@@;Fm8f0^;>$Z>~}GWRw!W5J3tNX*^2+1f3hz{~rIzJo z6W%J(H!g-eI_J1>0juX$X4Cl6i+3wbc~k146UIX&G22}WE>0ga#WLsn9tY(&29zBvH1$`iWtTe zG2jYl@P!P)eb<5DsR72BdI7-zP&cZNI{7q3e@?N8IKc4DE#UVr->|-ryuJXk^u^>4 z$3wE~=q390;XuOQP~TNoDR?#|NSPJ%sTMInA6*rJ%go|=YjGe!B>z6u$IhgQSwoV* zjy3F2#I>uK{42{&IqP59)Y(1*Z>>#W8rCf4_eVsH)`v!P#^;BgzKDR`ARGEZzkNX+ zJUQu=*-ol=Xqqt5=`=pA@BIn@6a9G8C{c&`i^(i+BxQO9?YZ3iu%$$da&Kb?2kCCo zo7t$UpSFWqmydXf@l3bVJ=%K?SSw)|?srhJ-1ZdFu*5QhL$~-IQS!K1s@XzAtv6*Y zl8@(5BlWYLt1yAWy?rMD&bwze8bC3-GfNH=p zynNFCdxyX?K&G(ZZ)afguQ2|r;XoV^=^(;Cku#qYn4Lus`UeKt6rAlFo_rU`|Rq z&G?~iWMBio<78of-2X(ZYHx~=U0Vz4btyXkctMKdc9UM!vYr~B-(>)(Hc|D zMzkN4!PBg%tZoh+=Gba!0++d193gbMk2&krfDgcbx0jI92cq?FFESVg0D$>F+bil} zY~$)|>1HZsX=5sAZ2WgPB5P=8X#TI+NQ(M~GqyVB53c6IdX=k>Wu@A0Svf5#?uHaF zsYn|koIi3$(%GZ2+G+7Fv^lHTb#5b8sAHSTnL^qWZLM<(1|9|QFw9pnRU{svj}_Al zL)b9>fN{QiA($8peNEJyy`(a{&uh-T4_kdZFIVsKKVM(?05}76EEz?#W za^fiZOAd14IJ4zLX-n7Lq0qlQ^lW8Cvz4UKkV9~P}>sq0?xD3vg+$4vLm~C(+ zM{-3Z#qnZ09bJ>}j?6ry^h+@PfaD7*jZxBEY4)UG&daWb??6)TP+|3#Z&?GL?1i+280CFsE|vIXQbm| zM}Pk!U`U5NsNbyKzkrul-DzwB{X?n3E6?TUHr{M&+R*2%yOiXdW-_2Yd6?38M9Vy^ z*lE%gA{wwoSR~vN0=no}tP2Ul5Gk5M(Xq`$nw#ndFk`tcpd5A=Idue`XZ!FS>Q zG^0w#>P4pPG+*NC9gLP4x2m=cKP}YuS!l^?sHSFftZy{4CoQrb_ z^20(NnG`wAhMI=eq)SsIE~&Gp9Ne0nD4%Xiu|0Fj1UFk?6avDqjdXz{O1nKao*46y zT8~iA%Exu=G#{x=KD;_C&M+Zx4+n`sHT>^>=-1YM;H<72k>$py1?F3#T1*ef9mLZw z5naLQr?n7K;2l+{_uIw*_1nsTn~I|kkCgrn;|G~##hM;9l7Jy$yJfmk+&}W@JeKcF zx@@Woiz8qdi|D%aH3XTx5*wDlbs?dC1_nrFpm^QbG@wM=i2?Zg;$VK!c^Dp8<}BTI zyRhAq@#%2pGV49*Y5_mV4+OICP|%I(dQ7x=6Ob}>EjnB_-_18*xrY?b%-yEDT(wrO z9RY2QT0`_OpGfMObKHV;QLVnrK%mc?$WAdIT`kJQT^n%GuzE7|9@k3ci5fYOh(287 zuIbg!GB3xLg$YN=n)^pHGB0jH+_iIiC=nUcD;G6LuJsjn2VI1cyZx=a?ShCsF==QK z;q~*m&}L<-cb+mDDXzvvrRsybcgQ;Vg21P(uLv5I+eGc7o7tc6`;OA9{soHFOz zT~2?>Ts}gprIX$wRBb4yE>ot<8+*Bv`qbSDv*VtRi|cyWS>)Fjs>fkNOH-+PX&4(~ z&)T8Zam2L6puQl?;5zg9h<}k4#|yH9czHw;1jw-pwBM*O2hUR6yvHATrI%^mvs9q_ z&ccT0>f#eDG<^WG^q@oVqlJrhxH)dcq2cty@l3~|5#UDdExyXUmLQ}f4#;6fI{f^t zDCsgIJ~0`af%YR%Ma5VQq-p21k`vaBu6WE?66+5=XUd%Ay%D$irN>5LhluRWt7 zov-=f>QbMk*G##&DTQyou$s7UqjjW@k6=!I@!k+S{pP8R(2=e@io;N8E`EOB;OGoI zw6Q+{X1_I{OO0HPpBz!X!@`5YQ2)t{+!?M_iH25X(d~-Zx~cXnS9z>u?+If|iNJbx zyFU2d1!ITX64D|lE0Z{dLRqL1Ajj=CCMfC4lD3&mYR_R_VZ>_7_~|<^o*%_&jevU+ zQ4|qzci=0}Jydw|LXLCrOl1_P6Xf@c0$ieK2^7@A9UbF{@V_0p%lqW|L?5k>bVM8|p5v&2g;~r>B8uo<4N+`B zH{J)h;SYiIVx@#jI&p-v3dwL5QNV1oxPr8J%ooezTnLW>i*3Isb49%5i!&ac_dEXv zvXmVUck^QHmyrF8>CGXijC_R-y(Qr{3Zt~EmW)-nC!tiH`wlw5D*W7Pip;T?&j%kX z6DkZX4&}iw>hE(boLyjOoupf6JpvBG8}jIh!!VhnD0>}KSMMo{1#uU6kiFcA04~|7 zVO8eI&x1`g4CZ<2cYUI(n#wz2MtVFHx47yE5eL~8bot~>EHbevSt}LLMQX?odD{Ux zJMnam{d)W4da{l7&y-JrgiU~qY3$~}_F#G7|MxT)e;G{U`In&?`j<5D->}cb{}{T(4DF0BOk-=1195KB-E*o@c?`>y#4=dMtYtSY=&L{!TAjFVcq0y@AH`vH! z$41+u!Ld&}F^COPgL(EE{0X7LY&%D7-(?!kjFF7=qw<;`V{nwWBq<)1QiGJgUc^Vz ztMUlq1bZqKn17|6x6iAHbWc~l1HcmAxr%$Puv!znW)!JiukwIrqQ00|H$Z)OmGG@= zv%A8*4cq}(?qn4rN6o`$Y))(MyXr8R<2S^J+v(wmFmtac!%VOfN?&(8Nr!T@kV`N; z*Q33V3t`^rN&aBiHet)18wy{*wi1=W!B%B-Q6}SCrUl$~Hl{@!95ydml@FK8P=u4s z4e*7gV2s=YxEvskw2Ju!2%{8h01rx-3`NCPc(O zH&J0VH5etNB2KY6k4R@2Wvl^Ck$MoR3=)|SEclT2ccJ!RI9Nuter7u9@;sWf-%um;GfI!=eEIQ2l2p_YWUd{|6EG ze{yO6;lMc>;2tPrsNdi@&1K6(1;|$xe8vLgiouj%QD%gYk`4p{Ktv9|j+!OF-P?@p z;}SV|oIK)iwlBs+`ROXkhd&NK zzo__r!B>tOXpBJMDcv!Mq54P+n4(@dijL^EpO1wdg~q+!DT3lB<>9AANSe!T1XgC=J^)IP0XEZ()_vpu!!3HQyJhwh?r`Ae%Yr~b% zO*NY9t9#qWa@GCPYOF9aron7thfWT`eujS4`t2uG6)~JRTI;f(ZuoRQwjZjp5Pg34 z)rp$)Kr?R+KdJ;IO;pM{$6|2y=k_siqvp%)2||cHTe|b5Ht8&A{wazGNca zX$Ol?H)E_R@SDi~4{d-|8nGFhZPW;Cts1;08TwUvLLv&_2$O6Vt=M)X;g%HUr$&06 zISZb(6)Q3%?;3r~*3~USIg=HcJhFtHhIV(siOwV&QkQe#J%H9&E21!C*d@ln3E@J* zVqRO^<)V^ky-R|%{(9`l-(JXq9J)1r$`uQ8a}$vr9E^nNiI*thK8=&UZ0dsFN_eSl z(q~lnD?EymWLsNa3|1{CRPW60>DSkY9YQ;$4o3W7Ms&@&lv9eH!tk~N&dhqX&>K@} zi1g~GqglxkZ5pEFkllJ)Ta1I^c&Bt6#r(QLQ02yHTaJB~- zCcE=5tmi`UA>@P=1LBfBiqk)HB4t8D?02;9eXj~kVPwv?m{5&!&TFYhu>3=_ zsGmYZ^mo*-j69-42y&Jj0cBLLEulNRZ9vXE)8~mt9C#;tZs;=#M=1*hebkS;7(aGf zcs7zH(I8Eui9UU4L--))yy`&d&$In&VA2?DAEss4LAPCLd>-$i?lpXvn!gu^JJ$(DoUlc6wE98VLZ*z`QGQov5l4Fm_h?V-;mHLYDVOwKz7>e4+%AzeO>P6v}ndPW| zM>m#6Tnp7K?0mbK=>gV}=@k*0Mr_PVAgGMu$j+pWxzq4MAa&jpCDU&-5eH27Iz>m^ zax1?*HhG%pJ((tkR(V(O(L%7v7L%!_X->IjS3H5kuXQT2!ow(;%FDE>16&3r){!ex zhf==oJ!}YU89C9@mfDq!P3S4yx$aGB?rbtVH?sHpg?J5C->!_FHM%Hl3#D4eplxzQ zRA+<@LD%LKSkTk2NyWCg7u=$%F#;SIL44~S_OGR}JqX}X+=bc@swpiClB`Zbz|f!4 z7Ysah7OkR8liXfI`}IIwtEoL}(URrGe;IM8%{>b1SsqXh)~w}P>yiFRaE>}rEnNkT z!HXZUtxUp1NmFm)Dm@-{FI^aRQqpSkz}ZSyKR%Y}YHNzBk)ZIp} zMtS=aMvkgWKm9&oTcU0?S|L~CDqA+sHpOxwnswF-fEG)cXCzUR?ps@tZa$=O)=L+5 zf%m58cq8g_o}3?Bhh+c!w4(7AjxwQ3>WnVi<{{38g7yFboo>q|+7qs<$8CPXUFAN< zG&}BHbbyQ5n|qqSr?U~GY{@GJ{(Jny{bMaOG{|IkUj7tj^9pa9|FB_<+KHLxSxR;@ zHpS$4V)PP+tx}22fWx(Ku9y+}Ap;VZqD0AZW4gCDTPCG=zgJmF{|x;(rvdM|2|9a}cex6xrMkERnkE;}jvU-kmzd%_J50$M`lIPCKf+^*zL=@LW`1SaEc%=m zQ+lT06Gw+wVwvQ9fZ~#qd430v2HndFsBa9WjD0P}K(rZYdAt^5WQIvb%D^Q|pkVE^ zte$&#~zmULFACGfS#g=2OLOnIf2Of-k!(BIHjs77nr!5Q1*I9 z1%?=~#Oss!rV~?-6Gm~BWJiA4mJ5TY&iPm_$)H1_rTltuU1F3I(qTQ^U$S>%$l z)Wx1}R?ij0idp@8w-p!Oz{&*W;v*IA;JFHA9%nUvVDy7Q8woheC#|8QuDZb-L_5@R zOqHwrh|mVL9b=+$nJxM`3eE{O$sCt$UK^2@L$R(r^-_+z?lOo+me-VW=Zw z-Bn>$4ovfWd%SPY`ab-u9{INc*k2h+yH%toDHIyqQ zO68=u`N}RIIs7lsn1D){)~%>ByF<>i@qFb<-axvu(Z+6t7v<^z&gm9McRB~BIaDn$ z#xSGT!rzgad8o>~kyj#h1?7g96tOcCJniQ+*#=b7wPio>|6a1Z?_(TS{)KrPe}(8j z!#&A=k(&Pj^F;r)CI=Z{LVu>uj!_W1q4b`N1}E(i%;BWjbEcnD=mv$FL$l?zS6bW!{$7j1GR5ocn94P2u{ z70tAAcpqtQo<@cXw~@i-@6B23;317|l~S>CB?hR5qJ%J3EFgyBdJd^fHZu7AzHF(BQ!tyAz^L0`X z23S4Fe{2X$W0$zu9gm%rg~A>ijaE#GlYlrF9$ds^QtaszE#4M(OLVP2O-;XdT(XIC zatwzF*)1c+t~c{L=fMG8Z=k5lv>U0;C{caN1NItnuSMp)6G3mbahu>E#sj&oy94KC zpH}8oEw{G@N3pvHhp{^-YaZeH;K+T_1AUv;IKD<=mv^&Ueegrb!yf`4VlRl$M?wsl zZyFol(2|_QM`e_2lYSABpKR{{NlxlDSYQNkS;J66aT#MSiTx~;tUmvs-b*CrR4w=f z8+0;*th6kfZ3|5!Icx3RV11sp=?`0Jy3Fs0N4GZQMN=8HmT6%x9@{Dza)k}UwL6JT zHRDh;%!XwXr6yuuy`4;Xsn0zlR$k%r%9abS1;_v?`HX_hI|+EibVnlyE@3aL5vhQq zlIG?tN^w@0(v9M*&L+{_+RQZw=o|&BRPGB>e5=ys7H`nc8nx)|-g;s7mRc7hg{GJC zAe^vCIJhajmm7C6g! zL&!WAQ~5d_5)00?w_*|*H>3$loHrvFbitw#WvLB!JASO?#5Ig5$Ys10n>e4|3d;tS zELJ0|R4n3Az(Fl3-r^QiV_C;)lQ1_CW{5bKS15U|E9?ZgLec@%kXr84>5jV2a5v=w z?pB1GPdxD$IQL4)G||B_lI+A=08MUFFR4MxfGOu07vfIm+j=z9tp~5i_6jb`tR>qV z$#`=BQ*jpCjm$F0+F)L%xRlnS%#&gro6PiRfu^l!EVan|r3y}AHJQOORGx4~ z&<)3=K-tx518DZyp%|!EqpU!+X3Et7n2AaC5(AtrkW>_57i}$eqs$rupubg0a1+WO zGHZKLN2L0D;ab%{_S1Plm|hx8R?O14*w*f&2&bB050n!R2by zw!@XOQx$SqZ5I<(Qu$V6g>o#A!JVwErWv#(Pjx=KeS0@hxr4?13zj#oWwPS(7Ro|v z>Mp@Kmxo79q|}!5qtX2-O@U&&@6s~!I&)1WQIl?lTnh6UdKT_1R640S4~f=_xoN3- zI+O)$R@RjV$F=>Ti7BlnG1-cFKCC(t|Qjm{SalS~V-tX#+2ekRhwmN zZr`8{QF6y~Z!D|{=1*2D-JUa<(1Z=;!Ei!KiRNH?o{p5o3crFF=_pX9O-YyJchr$~ zRC`+G+8kx~fD2k*ZIiiIGR<8r&M@3H?%JVOfE>)})7ScOd&?OjgAGT@WVNSCZ8N(p zuQG~76GE3%(%h1*vUXg$vH{ua0b`sQ4f0*y=u~lgyb^!#CcPJa2mkSEHGLsnO^kb$ zru5_l#nu=Y{rSMWiYx?nO{8I!gH+?wEj~UM?IrG}E|bRIBUM>UlY<`T1EHpRr36vv zBi&dG8oxS|J$!zoaq{+JpJy+O^W(nt*|#g32bd&K^w-t>!Vu9N!k9eA8r!Xc{utY> zg9aZ(D2E0gL#W0MdjwES-7~Wa8iubPrd?8-$C4BP?*wok&O8+ykOx{P=Izx+G~hM8 z*9?BYz!T8~dzcZr#ux8kS7u7r@A#DogBH8km8Ry4slyie^n|GrTbO|cLhpqgMdsjX zJ_LdmM#I&4LqqsOUIXK8gW;V0B(7^$y#h3h>J0k^WJfAMeYek%Y-Dcb_+0zPJez!GM zAmJ1u;*rK=FNM0Nf}Y!!P9c4)HIkMnq^b;JFd!S3?_Qi2G#LIQ)TF|iHl~WKK6JmK zbv7rPE6VkYr_%_BT}CK8h=?%pk@3cz(UrZ{@h40%XgThP*-Oeo`T0eq9 zA8BnWZKzCy5e&&_GEsU4*;_k}(8l_&al5K-V*BFM=O~;MgRkYsOs%9eOY6s6AtE*<7GQAR2ulC3RAJrG_P1iQK5Z~&B z&f8X<>yJV6)oDGIlS$Y*D^Rj(cszTy5c81a5IwBr`BtnC6_e`ArI8CaTX_%rx7;cn zR-0?J_LFg*?(#n~G8cXut(1nVF0Oka$A$1FGcERU<^ggx;p@CZc?3UB41RY+wLS`LWFNSs~YP zuw1@DNN3lTd|jDL7gjBsd9}wIw}4xT2+8dBQzI00m<@?c2L%>}QLfK5%r!a-iII`p zX@`VEUH)uj^$;7jVUYdADQ2k*!1O3WdfgF?OMtUXNpQ1}QINamBTKDuv19^{$`8A1 zeq%q*O0mi@(%sZU>Xdb0Ru96CFqk9-L3pzLVsMQ`Xpa~N6CR{9Rm2)A|CI21L(%GW zh&)Y$BNHa=FD+=mBw3{qTgw)j0b!Eahs!rZnpu)z!!E$*eXE~##yaXz`KE5(nQM`s zD!$vW9XH)iMxu9R>r$VlLk9oIR%HxpUiW=BK@4U)|1WNQ=mz9a z^!KkO=>GaJ!GBXm{KJj^;kh-MkUlEQ%lza`-G&}C5y1>La1sR6hT=d*NeCnuK%_LV zOXt$}iP6(YJKc9j-Fxq~*ItVUqljQ8?oaysB-EYtFQp9oxZ|5m0^Hq(qV!S+hq#g( z?|i*H2MIr^Kxgz+3vIljQ*Feejy6S4v~jKEPTF~Qhq!(ms5>NGtRgO5vfPPc4Z^AM zTj!`5xEreIN)vaNxa|q6qWdg>+T`Ol0Uz)ckXBXEGvPNEL3R8hB3=C5`@=SYgAju1 z!)UBr{2~=~xa{b8>x2@C7weRAEuatC)3pkRhT#pMPTpSbA|tan%U7NGMvzmF?c!V8 z=pEWxbdXbTAGtWTyI?Fml%lEr-^AE}w#l(<7OIw;ctw}imYax&vR4UYNJZK6P7ZOd zP87XfhnUHxCUHhM@b*NbTi#(-8|wcv%3BGNs#zRCVV(W?1Qj6^PPQa<{yaBwZ`+<`w|;rqUY_C z&AeyKwwf*q#OW-F()lir=T^<^wjK65Lif$puuU5+tk$;e_EJ;Lu+pH>=-8=PDhkBg z8cWt%@$Sc#C6F$Vd+0507;{OOyT7Hs%nKS88q-W!$f~9*WGBpHGgNp}=C*7!RiZ5s zn1L_DbKF@B8kwhDiLKRB@lsXVVLK|ph=w%_`#owlf@s@V(pa`GY$8h%;-#h@TsO|Y8V=n@*!Rog7<7Cid%apR|x zOjhHCyfbIt%+*PCveTEcuiDi%Wx;O;+K=W?OFUV%)%~6;gl?<0%)?snDDqIvkHF{ zyI02)+lI9ov42^hL>ZRrh*HhjF9B$A@=H94iaBESBF=eC_KT$8A@uB^6$~o?3Wm5t1OIaqF^~><2?4e3c&)@wKn9bD? zoeCs;H>b8DL^F&>Xw-xjZEUFFTv>JD^O#1E#)CMBaG4DX9bD(Wtc8Rzq}9soQ8`jf zeSnHOL}<+WVSKp4kkq&?SbETjq6yr@4%SAqOG=9E(3YeLG9dtV+8vmzq+6PFPk{L; z(&d++iu=^F%b+ea$i2UeTC{R*0Isk;vFK!no<;L+(`y`3&H-~VTdKROkdyowo1iqR zbVW(3`+(PQ2>TKY>N!jGmGo7oeoB8O|P_!Ic@ zZ^;3dnuXo;WJ?S+)%P>{Hcg!Jz#2SI(s&dY4QAy_vRlmOh)QHvs_7c&zkJCmJGVvV zX;Mtb>QE+xp`KyciG$Cn*0?AK%-a|=o!+7x&&yzHQOS>8=B*R=niSnta^Pxp1`=md z#;$pS$4WCT?mbiCYU?FcHGZ#)kHVJTTBt^%XE(Q};aaO=Zik0UgLcc0I(tUpt(>|& zcxB_|fxCF7>&~5eJ=Dpn&5Aj{A^cV^^}(7w#p;HG&Q)EaN~~EqrE1qKrMAc&WXIE;>@<&)5;gD2?={Xf@Mvn@OJKw=8Mgn z!JUFMwD+s==JpjhroT&d{$kQAy%+d`a*XxDEVxy3`NHzmITrE`o!;5ClXNPb4t*8P zzAivdr{j_v!=9!^?T3y?gzmqDWX6mkzhIzJ-3S{T5bcCFMr&RPDryMcdwbBuZbsgN zGrp@^i?rcfN7v0NKGzDPGE#4yszxu=I_`MI%Z|10nFjU-UjQXXA?k8Pk|OE<(?ae) zE%vG#eZAlj*E7_3dx#Zz4kMLj>H^;}33UAankJiDy5ZvEhrjr`!9eMD8COp}U*hP+ zF}KIYx@pkccIgyxFm#LNw~G&`;o&5)2`5aogs`1~7cMZQ7zj!%L4E`2yzlQN6REX20&O<9 zKV6fyr)TScJPPzNTC2gL+0x#=u>(({{D7j)c-%tvqls3#Y?Z1m zV5WUE)zdJ{$p>yX;^P!UcXP?UD~YM;IRa#Rs5~l+*$&nO(;Ers`G=0D!twR(0GF@c zHl9E5DQI}Oz74n zfKP>&$q0($T4y$6w(p=ERAFh+>n%iaeRA%!T%<^+pg?M)@ucY<&59$x9M#n+V&>}=nO9wCV{O~lg&v#+jcUj(tQ z`0u1YH)-`U$15a{pBkGyPL0THv1P|4e@pf@3IBZS4dVJPo#H>pWq%Lr0YS-SeWash z8R7=jb28KPMI|_lo#GEO|5B?N_e``H*23{~a!AmUJ+fb4HX-%QI@lSEUxKlGV7z7Q zSKw@-TR>@1RL%w{x}dW#k1NgW+q4yt2Xf1J62Bx*O^WG8OJ|FqI4&@d3_o8Id@*)4 zYrk=>@!wv~mh7YWv*bZhxqSmFh2Xq)o=m;%n$I?GSz49l1$xRpPu_^N(vZ>*>Z<04 z2+rP70oM=NDysd!@fQdM2OcyT?3T^Eb@lIC-UG=Bw{BjQ&P`KCv$AcJ;?`vdZ4){d z&gkoUK{$!$$K`3*O-jyM1~p-7T*qb)Ys>Myt^;#1&a%O@x8A+E>! zY8=eD`ZG)LVagDLBeHg>=atOG?Kr%h4B%E6m@J^C+U|y)XX@f z8oyJDW|9g=<#f<{JRr{y#~euMnv)`7j=%cHWLc}ngjq~7k**6%4u>Px&W%4D94(r* z+akunK}O0DC2A%Xo9jyF;DobX?!1I(7%}@7F>i%&nk*LMO)bMGg2N+1iqtg+r(70q zF5{Msgsm5GS7DT`kBsjMvOrkx&|EU!{{~gL4d2MWrAT=KBQ-^zQCUq{5PD1orxlIL zq;CvlWx#f1NWvh`hg011I%?T_s!e38l*lWVt|~z-PO4~~1g)SrJ|>*tXh=QfXT)%( z+ex+inPvD&O4Ur;JGz>$sUOnWdpSLcm1X%aQDw4{dB!cnj`^muI$CJ2%p&-kULVCE z>$eMR36kN$wCPR+OFDM3-U(VOrp9k3)lI&YVFqd;Kpz~K)@Fa&FRw}L(SoD z9B4a+hQzZT-BnVltst&=kq6Y(f^S4hIGNKYBgMxGJ^;2yrO}P3;r)(-I-CZ)26Y6? z&rzHI_1GCvGkgy-t1E;r^3Le30|%$ebDRu2+gdLG)r=A~Qz`}~&L@aGJ{}vVs_GE* zVUjFnzHiXfKQbpv&bR&}l2bzIjAooB)=-XNcYmrGmBh(&iu@o!^hn0^#}m2yZZUK8 zufVm7Gq0y`Mj;9b>`c?&PZkU0j4>IL=UL&-Lp3j&47B5pAW4JceG{!XCA)kT<%2nqCxj<)uy6XR_uws~>_MEKPOpAQ!H zkn>FKh)<9DwwS*|Y(q?$^N!6(51O0 z^JM~Ax{AI1Oj$fs-S5d4T7Z_i1?{%0SsIuQ&r8#(JA=2iLcTN+?>wOL532%&dMYkT z*T5xepC+V6zxhS@vNbMoi|i)=rpli@R9~P!39tWbSSb904ekv7D#quKbgFEMTb48P zuq(VJ+&L8aWU(_FCD$3^uD!YM%O^K(dvy~Wm2hUuh6bD|#(I39Xt>N1Y{ZqXL`Fg6 zKQ?T2htHN!(Bx;tV2bfTtIj7e)liN-29s1kew>v(D^@)#v;}C4-G=7x#;-dM4yRWm zyY`cS21ulzMK{PoaQ6xChEZ}o_#}X-o}<&0)$1#3we?+QeLt;aVCjeA)hn!}UaKt< zat1fHEx13y-rXNMvpUUmCVzocPmN~-Y4(YJvQ#db)4|%B!rBsgAe+*yor~}FrNH08 z3V!97S}D7d$zbSD{$z;@IYMxM6aHdypIuS*pr_U6;#Y!_?0i|&yU*@16l z*dcMqDQgfNBf}?quiu4e>H)yTVfsp#f+Du0@=Kc41QockXkCkvu>FBd6Q+@FL!(Yx z2`YuX#eMEiLEDhp+9uFqME_E^faV&~9qjBHJkIp~%$x^bN=N)K@kvSVEMdDuzA0sn z88CBG?`RX1@#hQNd`o^V{37)!w|nA)QfiYBE^m=yQKv-fQF+UCMcuEe1d4BH7$?>b zJl-r9@0^Ie=)guO1vOd=i$_4sz>y3x^R7n4ED!5oXL3@5**h(xr%Hv)_gILarO46q+MaDOF%ChaymKoI6JU5Pg;7#2n9-18|S1;AK+ zgsn6;k6-%!QD>D?cFy}8F;r@z8H9xN1jsOBw2vQONVqBVEbkiNUqgw~*!^##ht>w0 zUOykwH=$LwX2j&nLy=@{hr)2O&-wm-NyjW7n~Zs9UlH;P7iP3 zI}S(r0YFVYacnKH(+{*)Tbw)@;6>%=&Th=+Z6NHo_tR|JCI8TJiXv2N7ei7M^Q+RM z?9o`meH$5Yi;@9XaNR#jIK^&{N|DYNNbtdb)XW1Lv2k{E>;?F`#Pq|&_;gm~&~Zc9 zf+6ZE%{x4|{YdtE?a^gKyzr}dA>OxQv+pq|@IXL%WS0CiX!V zm$fCePA%lU{%pTKD7|5NJHeXg=I0jL@$tOF@K*MI$)f?om)D63K*M|r`gb9edD1~Y zc|w7N)Y%do7=0{RC|AziW7#am$)9jciRJ?IWl9PE{G3U+$%FcyKs_0Cgq`=K3@ttV z9g;M!3z~f_?P%y3-ph%vBMeS@p7P&Ea8M@97+%XEj*(1E6vHj==d zjsoviB>j^$_^OI_DEPvFkVo(BGRo%cJeD){6Uckei=~1}>sp299|IRjhXe)%?uP0I zF5+>?0#Ye}T^Y$u_rc4=lPcq4K^D(TZG-w30-YiEM=dcK+4#o*>lJ8&JLi+3UcpZk z!^?95S^C0ja^jwP`|{<+3cBVog$(mRdQmadS+Vh~z zS@|P}=|z3P6uS+&@QsMp0no9Od&27O&14zHXGAOEy zh~OKpymK5C%;LLb467@KgIiVwYbYd6wFxI{0-~MOGfTq$nBTB!{SrWmL9Hs}C&l&l#m?s*{tA?BHS4mVKHAVMqm63H<|c5n0~k)-kbg zXidai&9ZUy0~WFYYKT;oe~rytRk?)r8bptITsWj(@HLI;@=v5|XUnSls7$uaxFRL+ zRVMGuL3w}NbV1`^=Pw*0?>bm8+xfeY(1PikW*PB>>Tq(FR`91N0c2&>lL2sZo5=VD zQY{>7dh_TX98L2)n{2OV=T10~*YzX27i2Q7W86M4$?gZIXZaBq#sA*{PH8){|GUi;oM>e?ua7eF4WFuFYZSG| zze?srg|5Ti8Og{O zeFxuw9!U+zhyk?@w zjsA6(oKD=Ka;A>Ca)oPORxK+kxH#O@zhC!!XS4@=swnuMk>t+JmLmFiE^1aX3f<)D@`%K0FGK^gg1a1j>zi z2KhV>sjU7AX3F$SEqrXSC}fRx64GDoc%!u2Yag68Lw@w9v;xOONf@o)Lc|Uh3<21ctTYu-mFZuHk*+R{GjXHIGq3p)tFtQp%TYqD=j1&y)>@zxoxUJ!G@ zgI0XKmP6MNzw>nRxK$-Gbzs}dyfFzt>#5;f6oR27ql!%+{tr+(`(>%51|k`ML} zY4eE)Lxq|JMas(;JibNQds1bUB&r}ydMQXBY4x(^&fY_&LlQC)3hylc$~8&~|06-D z#T+%66rYbHX%^KuqJED_wuGB+=h`nWA!>1n0)3wZrBG3%`b^Ozv6__dNa@%V14|!D zQ?o$z5u0^8`giv%qE!BzZ!3j;BlDlJDk)h@9{nSQeEk!z9RGW) z${RSF3phEM*ce*>Xdp}585vj$|40=&S{S-GTiE?Op*vY&Lvr9}BO$XWy80IF+6@%n z5*2ueT_g@ofP#u5pxb7n*fv^Xtt7&?SRc{*2Ka-*!BuOpf}neHGCiHy$@Ka1^Dint z;DkmIL$-e)rj4o2WQV%Gy;Xg(_Bh#qeOsTM2f@KEe~4kJ8kNLQ+;(!j^bgJMcNhvklP5Z6I+9Fq@c&D~8Fb-4rmDT!MB5QC{Dsb;BharP*O;SF4& zc$wj-7Oep7#$WZN!1nznc@Vb<_Dn%ga-O#J(l=OGB`dy=Sy&$(5-n3zzu%d7E#^8`T@}V+5B;PP8J14#4cCPw-SQTdGa2gWL0*zKM z#DfSXs_iWOMt)0*+Y>Lkd=LlyoHjublNLefhKBv@JoC>P7N1_#> zv=mLWe96%EY;!ZGSQDbZWb#;tzqAGgx~uk+-$+2_8U`!ypbwXl z^2E-FkM1?lY@yt8=J3%QK+xaZ6ok=-y%=KXCD^0r!5vUneW>95PzCkOPO*t}p$;-> ze5j-BLT_;)cZQzR2CEsm@rU7GZfFtdp*a|g4wDr%8?2QkIGasRfDWT-Dvy*U{?IHT z*}wGnzdlSptl#ZF^sf)KT|BJs&kLG91^A6ls{CzFprZ6-Y!V0Xysh%9p%iMd7HLsS zN+^Un$tDV)T@i!v?3o0Fsx2qI(AX_$dDkBzQ@fRM%n zRXk6hb9Py#JXUs+7)w@eo;g%QQ95Yq!K_d=z{0dGS+pToEI6=Bo8+{k$7&Z zo4>PH(`ce8E-Ps&uv`NQ;U$%t;w~|@E3WVOCi~R4oj5wP?%<*1C%}Jq%a^q~T7u>K zML5AKfQDv6>PuT`{SrKHRAF+^&edg6+5R_#H?Lz3iGoWo#PCEd0DS;)2U({{X#zU^ zw_xv{4x7|t!S)>44J;KfA|DC?;uQ($l+5Vp7oeqf7{GBF9356nx|&B~gs+@N^gSdd zvb*>&W)|u#F{Z_b`f#GVtQ`pYv3#||N{xj1NgB<#=Odt6{eB%#9RLt5v zIi|0u70`#ai}9fJjKv7dE!9ZrOIX!3{$z_K5FBd-Kp-&e4(J$LD-)NMTp^_pB`RT; zftVVlK2g@+1Ahv2$D){@Y#cL#dUj9*&%#6 zd2m9{1NYp>)6=oAvqdCn5#cx{AJ%S8skUgMglu2*IAtd+z1>B&`MuEAS(D(<6X#Lj z?f4CFx$)M&$=7*>9v1ER4b6!SIz-m0e{o0BfkySREchp?WdVPpQCh!q$t>?rL!&Jg zd#heM;&~A}VEm8Dvy&P|J*eAV&w!&Nx6HFV&B8jJFVTmgLaswn!cx$&%JbTsloz!3 zMEz1d`k==`Ueub_JAy_&`!ogbwx27^ZXgFNAbx=g_I~5nO^r)}&myw~+yY*cJl4$I znNJ32M&K=0(2Dj_>@39`3=FX!v3nZHno_@q^!y}%(yw0PqOo=);6Y@&ylVe>nMOZ~ zd>j#QQSBn3oaWd;qy$&5(5H$Ayi)0haAYO6TH>FR?rhqHmNOO+(})NB zLI@B@v0)eq!ug`>G<@htRlp3n!EpU|n+G+AvXFrWSUsLMBfL*ZB`CRsIVHNTR&b?K zxBgsN0BjfB>UVcJ|x%=-zb%OV7lmZc& zxiupadZVF7)6QuhoY;;FK2b*qL0J-Rn-8!X4ZY$-ZSUXV5DFd7`T41c(#lAeLMoeT z4%g655v@7AqT!i@)Edt5JMbN(=Q-6{=L4iG8RA%}w;&pKmtWvI4?G9pVRp|RTw`g0 zD5c12B&A2&P6Ng~8WM2eIW=wxd?r7A*N+&!Be7PX3s|7~z=APxm=A?5 zt>xB4WG|*Td@VX{Rs)PV0|yK`oI3^xn(4c_j&vgxk_Y3o(-`_5o`V zRTghg6%l@(qodXN;dB#+OKJEEvhfcnc#BeO2|E(5df-!fKDZ!%9!^BJ_4)9P+9Dq5 zK1=(v?KmIp34r?z{NEWnLB3Px{XYwy-akun4F7xTRr2^zeYW{gcK9)>aJDdU5;w5@ zak=<+-PLH-|04pelTb%ULpuuuJC7DgyT@D|p{!V!0v3KpDnRjANN12q6SUR3mb9<- z>2r~IApQGhstZ!3*?5V z8#)hJ0TdZg0M-BK#nGFP>$i=qk82DO z7h;Ft!D5E15OgW)&%lej*?^1~2=*Z5$2VX>V{x8SC+{i10BbtUk9@I#Vi&hX)q
Q!LwySI{Bnv%Sm)yh{^sSVJ8&h_D-BJ_YZe5eCaAWU9b$O2c z$T|{vWVRtOL!xC0DTc(Qbe`ItNtt5hr<)VijD0{U;T#bUEp381_y`%ZIav?kuYG{iyYdEBPW=*xNSc;Rlt6~F4M`5G+VtOjc z*0qGzCb@gME5udTjJA-9O<&TWd~}ysBd(eVT1-H82-doyH9RST)|+Pb{o*;$j9Tjs zhU!IlsPsj8=(x3bAKJTopW3^6AKROHR^7wZ185wJGVhA~hEc|LP;k7NEz-@4p5o}F z`AD6naG3(n=NF9HTH81=F+Q|JOz$7wm9I<+#BSmB@o_cLt2GkW9|?7mM;r!JZp89l zbo!Hp8=n!XH1{GwaDU+k)pGp`C|cXkCU5%vcH)+v@0eK>%7gWxmuMu9YLlChA|_D@ zi#5zovN_!a-0?~pUV-Rj*1P)KwdU-LguR>YM&*Nen+ln8Q$?WFCJg%DY%K}2!!1FE zDv-A%Cbwo^p(lzac&_TZ-l#9kq`mhLcY3h9ZTUVCM(Ad&=EriQY5{jJv<5K&g|*Lk zgV%ILnf1%8V2B0E&;Sp4sYbYOvvMebLwYwzkRQ#F8GpTQq#uv=J`uaSJ34OWITeSGo6+-8Xw znCk*n{kdDEi)Hi&u^)~cs@iyCkFWB2SWZU|Uc%^43ZIZQ-vWNExCCtDWjqHs;;tWf$v{}0{p0Rvxkq``)*>+Akq%|Na zA`@~-Vfe|+(AIlqru+7Ceh4nsVmO9p9jc8}HX^W&ViBDXT+uXbT#R#idPn&L>+#b6 zflC-4C5-X;kUnR~L>PSLh*gvL68}RBsu#2l`s_9KjUWRhiqF`j)`y`2`YU(>3bdBj z?>iyjEhe-~$^I5!nn%B6Wh+I`FvLNvauve~eX<+Ipl&04 zT}};W&1a3%W?dJ2=N#0t?e+aK+%t}5q%jSLvp3jZ%?&F}nOOWr>+{GFIa%wO_2`et z=JzoRR~}iKuuR+azPI8;Gf9)z3kyA4EIOSl!sRR$DlW}0>&?GbgPojmjmnln;cTqCt=ADbE zZ8GAnoM+S1(5$i8^O4t`ue;vO4i}z0wz-QEIVe5_u03;}-!G1NyY8;h^}y;tzY}i5 zqQr#Ur3Fy8sSa$Q0ys+f`!`+>9WbvU_I`Sj;$4{S>O3?#inLHCrtLy~!s#WXV=oVP zeE93*Nc`PBi4q@%Ao$x4lw9vLHM!6mn3-b_cebF|n-2vt-zYVF_&sDE--J-P;2WHo z+@n2areE0o$LjvjlV2X7ZU@j+`{*8zq`JR3gKF#EW|#+{nMyo-a>nFFTg&vhyT=b} zDa8+v0(Dgx0yRL@ZXOYIlVSZ0|MFizy0VPW8;AfA5|pe!#j zX}Py^8fl5SyS4g1WSKKtnyP+_PoOwMMwu`(i@Z)diJp~U54*-miOchy7Z35eL>^M z4p<-aIxH4VUZgS783@H%M7P9hX>t{|RU7$n4T(brCG#h9e9p! z+o`i;EGGq3&pF;~5V~eBD}lC)>if$w%Vf}AFxGqO88|ApfHf&Bvu+xdG)@vuF}Yvk z)o;~k-%+0K0g+L`Wala!$=ZV|z$e%>f0%XoLib%)!R^RoS+{!#X?h-6uu zF&&KxORdZU&EwQFITIRLo(7TA3W}y6X{?Y%y2j0It!ekU#<)$qghZtpcS>L3uh`Uj z7GY;6f$9qKynP#oS3$$a{p^{D+0oJQ71`1?OAn_m8)UGZmj3l*ZI)`V-a>MKGGFG< z&^jg#Ok%(hhm>hSrZ5;Qga4u(?^i>GiW_j9%_7M>j(^|Om$#{k+^*ULnEgzW_1gCICtAD^WpC`A z{9&DXkG#01Xo)U$OC(L5Y$DQ|Q4C6CjUKk1UkPj$nXH##J{c8e#K|&{mA*;b$r0E4 zUNo0jthwA(c&N1l=PEe8Rw_8cEl|-eya9z&H3#n`B$t#+aJ03RFMzrV@gowbe8v(c zIFM60^0&lCFO10NU4w@|61xiZ4CVXeaKjd;d?sv52XM*lS8XiVjgWpRB;&U_C0g+`6B5V&w|O6B*_q zsATxL!M}+$He)1eOWECce#eS@2n^xhlB4<_Nn?yCVEQWDs(r`|@2GqLe<#(|&P0U? z$7V5IgpWf09uIf_RazRwC?qEqRaHyL?iiS05UiGesJy%^>-C{{ypTBI&B0-iUYhk> zIk<5xpsuV@g|z(AZD+C-;A!fTG=df1=<%nxy(a(IS+U{ME4ZbDEBtcD_3V=icT6*_ z)>|J?>&6%nvHhZERBtjK+s4xnut*@>GAmA5m*OTp$!^CHTr}vM4n(X1Q*;{e-Rd2BCF-u@1ZGm z!S8hJ6L=Gl4T_SDa7Xx|-{4mxveJg=ctf`BJ*fy!yF6Dz&?w(Q_6B}WQVtNI!BVBC zKfX<>7vd6C96}XAQmF-Jd?1Q4eTfRB3q7hCh0f!(JkdWT5<{iAE#dKy*Jxq&3a1@~ z8C||Dn2mFNyrUV|<-)C^_y7@8c2Fz+2jrae9deBDu;U}tJ{^xAdxCD248(k;dCJ%o z`y3sADe>U%suxwwv~8A1+R$VB=Q?%U?4joI$um;aH+eCrBqpn- z%79D_7rb;R-;-9RTrwi9dPlg8&@tfWhhZ(Vx&1PQ+6(huX`;M9x~LrW~~#3{j0Bh2kDU$}@!fFQej4VGkJv?M4rU^x!RU zEwhu$!CA_iDjFjrJa`aocySDX16?~;+wgav;}Zut6Mg%C4>}8FL?8)Kgwc(Qlj{@#2Pt0?G`$h7P#M+qoXtlV@d}%c&OzO+QYKK`kyXaK{U(O^2DyIXCZlNQjt0^8~8JzNGrIxhj}}M z&~QZlbx%t;MJ(Vux;2tgNKGlAqphLq%pd}JG9uoVHUo?|hN{pLQ6Em%r*+7t^<);X zm~6=qChlNAVXNN*Sow->*4;}T;l;D1I-5T{Bif@4_}=>l`tK;qqDdt5zvisCKhMAH z#r}`)7VW?LZqfdmXQ%zo5bJ00{Xb9^YKrk0Nf|oIW*K@(=`o2Vndz}ZDyk{!u}PVx zzd--+_WC*U{~DH3{?GI64IB+@On&@9X>EUAo&L+G{L^dozaI4C3G#2wr~hseW@K&g zKWs{uHu-9Je!3;4pE>eBltKUXb^*hG8I&413)$J&{D4N%7PcloU6bn%jPxJyQL?g* z9g+YFFEDiE`8rW^laCNzQmi7CTnPfwyg3VDHRAl>h=In6jeaVOP@!-CP60j3+#vpL zEYmh_oP0{-gTe7Or`L6x)6w?77QVi~jD8lWN@3RHcm80iV%M1A!+Y6iHM)05iC64tb$X2lV_%Txk@0l^hZqi^%Z?#- zE;LE0uFx)R08_S-#(wC=dS&}vj6P4>5ZWjhthP=*Hht&TdLtKDR;rXEX4*z0h74FA zMCINqrh3Vq;s%3MC1YL`{WjIAPkVL#3rj^9Pj9Ss7>7duy!9H0vYF%>1jh)EPqvlr6h%R%CxDsk| z!BACz7E%j?bm=pH6Eaw{+suniuY7C9Ut~1cWfOX9KW9=H><&kQlinPV3h9R>3nJvK z4L9(DRM=x;R&d#a@oFY7mB|m8h4692U5eYfcw|QKwqRsshN(q^v$4$)HgPpAJDJ`I zkqjq(8Cd!K!+wCd=d@w%~e$=gdUgD&wj$LQ1r>-E=O@c ze+Z$x{>6(JA-fNVr)X;*)40Eym1TtUZI1Pwwx1hUi+G1Jlk~vCYeXMNYtr)1?qwyg zsX_e*$h?380O00ou?0R@7-Fc59o$UvyVs4cUbujHUA>sH!}L54>`e` zHUx#Q+Hn&Og#YVOuo*niy*GU3rH;%f``nk#NN5-xrZ34NeH$l`4@t);4(+0|Z#I>Y z)~Kzs#exIAaf--65L0UHT_SvV8O2WYeD>Mq^Y6L!Xu8%vnpofG@w!}R7M28?i1*T&zp3X4^OMCY6(Dg<-! zXmcGQrRgHXGYre7GfTJ)rhl|rs%abKT_Nt24_Q``XH{88NVPW+`x4ZdrMuO0iZ0g` z%p}y};~T5gbb9SeL8BSc`SO#ixC$@QhXxZ=B}L`tP}&k?1oSPS=4%{UOHe0<_XWln zwbl5cn(j-qK`)vGHY5B5C|QZd5)W7c@{bNVXqJ!!n$^ufc?N9C-BF2QK1(kv++h!>$QbAjq)_b$$PcJdV+F7hz0Hu@ zqj+}m0qn{t^tD3DfBb~0B36|Q`bs*xs|$i^G4uNUEBl4g;op-;Wl~iThgga?+dL7s zUP(8lMO?g{GcYpDS{NM!UA8Hco?#}eNEioRBHy4`mq!Pd-9@-97|k$hpEX>xoX+dY zDr$wfm^P&}Wu{!%?)U_(%Mn79$(ywvu*kJ9r4u|MyYLI_67U7%6Gd_vb##Nerf@>& z8W11z$$~xEZt$dPG}+*IZky+os5Ju2eRi;1=rUEeIn>t-AzC_IGM-IXWK3^6QNU+2pe=MBn4I*R@A%-iLDCOHTE-O^wo$sL_h{dcPl=^muAQb`_BRm};=cy{qSkui;`WSsj9%c^+bIDQ z0`_?KX0<-=o!t{u(Ln)v>%VGL z0pC=GB7*AQ?N7N{ut*a%MH-tdtNmNC+Yf$|KS)BW(gQJ*z$d{+{j?(e&hgTy^2|AR9vx1Xre2fagGv0YXWqtNkg*v%40v?BJBt|f9wX5 z{QTlCM}b-0{mV?IG>TW_BdviUKhtosrBqdfq&Frdz>cF~yK{P@(w{Vr7z2qKFwLhc zQuogKO@~YwyS9%+d-zD7mJG~@?EFJLSn!a&mhE5$_4xBl&6QHMzL?CdzEnC~C3$X@ zvY!{_GR06ep5;<#cKCSJ%srxX=+pn?ywDwtJ2{TV;0DKBO2t++B(tIO4)Wh`rD13P z4fE$#%zkd=UzOB74gi=-*CuID&Z3zI^-`4U^S?dHxK8fP*;fE|a(KYMgMUo`THIS1f!*6dOI2 zFjC3O=-AL`6=9pp;`CYPTdVX z8(*?V&%QoipuH0>WKlL8A*zTKckD!paN@~hh zmXzm~qZhMGVdQGd=AG8&20HW0RGV8X{$9LldFZYm zE?}`Q3i?xJRz43S?VFMmqRyvWaS#(~Lempg9nTM$EFDP(Gzx#$r)W&lpFKqcAoJh-AxEw$-bjW>`_+gEi z2w`99#UbFZGiQjS8kj~@PGqpsPX`T{YOj`CaEqTFag;$jY z8_{Wzz>HXx&G*Dx<5skhpETxIdhKH?DtY@b9l8$l?UkM#J-Snmts7bd7xayKTFJ(u zyAT&@6cAYcs{PBfpqZa%sxhJ5nSZBPji?Zlf&}#L?t)vC4X5VLp%~fz2Sx<*oN<7` z?ge=k<=X7r<~F7Tvp9#HB{!mA!QWBOf%EiSJ6KIF8QZNjg&x~-%e*tflL(ji_S^sO ztmib1rp09uon}RcsFi#k)oLs@$?vs(i>5k3YN%$T(5Or(TZ5JW9mA6mIMD08=749$ z!d+l*iu{Il7^Yu}H;lgw=En1sJpCKPSqTCHy4(f&NPelr31^*l%KHq^QE>z>Ks_bH zjbD?({~8Din7IvZeJ>8Ey=e;I?thpzD=zE5UHeO|neioJwG;IyLk?xOz(yO&0DTU~ z^#)xcs|s>Flgmp;SmYJ4g(|HMu3v7#;c*Aa8iF#UZo7CvDq4>8#qLJ|YdZ!AsH%^_7N1IQjCro

K7UpUK$>l@ zw`1S}(D?mUXu_C{wupRS-jiX~w=Uqqhf|Vb3Cm9L=T+w91Cu^ z*&Ty%sN?x*h~mJc4g~k{xD4ZmF%FXZNC;oVDwLZ_WvrnzY|{v8hc1nmx4^}Z;yriXsAf+Lp+OFLbR!&Ox?xABwl zu8w&|5pCxmu#$?Cv2_-Vghl2LZ6m7}VLEfR5o2Ou$x02uA-%QB2$c(c1rH3R9hesc zfpn#oqpbKuVsdfV#cv@5pV4^f_!WS+F>SV6N0JQ9E!T90EX((_{bSSFv9ld%I0&}9 zH&Jd4MEX1e0iqDtq~h?DBrxQX1iI0lIs<|kB$Yrh&cpeK0-^K%=FBsCBT46@h#yi!AyDq1V(#V}^;{{V*@T4WJ&U-NTq43w=|K>z8%pr_nC>%C(Wa_l78Ufib$r8Od)IIN=u>417 z`Hl{9A$mI5A(;+-Q&$F&h-@;NR>Z<2U;Y21>>Z;s@0V@SbkMQQj%_;~+qTuQ?c|AV zcWm3XZQHhP&R%QWarS%mJ!9R^&!_)*s(v+VR@I#QrAT}`17Y+l<`b-nvmDNW`De%y zrwTZ9EJrj1AFA>B`1jYDow}~*dfPs}IZMO3=a{Fy#IOILc8F0;JS4x(k-NSpbN@qM z`@aE_e}5{!$v3+qVs7u?sOV(y@1Os*Fgu`fCW9=G@F_#VQ%xf$hj0~wnnP0$hFI+@ zkQj~v#V>xn)u??YutKsX>pxKCl^p!C-o?+9;!Nug^ z{rP!|+KsP5%uF;ZCa5F;O^9TGac=M|=V z_H(PfkV1rz4jl?gJ(ArXMyWT4y(86d3`$iI4^l9`vLdZkzpznSd5Ikfrs8qcSy&>z zTIZgWZGXw0n9ibQxYWE@gI0(3#KA-dAdPcsL_|hg2@~C!VZDM}5;v_Nykfq!*@*Zf zE_wVgx82GMDryKO{U{D>vSzSc%B~|cjDQrt5BN=Ugpsf8H8f1lR4SGo#hCuXPL;QQ z#~b?C4MoepT3X`qdW2dNn& zo8)K}%Lpu>0tQei+{>*VGErz|qjbK#9 zvtd8rcHplw%YyQCKR{kyo6fgg!)6tHUYT(L>B7er5)41iG`j$qe*kSh$fY!PehLcD zWeKZHn<492B34*JUQh=CY1R~jT9Jt=k=jCU2=SL&&y5QI2uAG2?L8qd2U(^AW#{(x zThSy=C#>k+QMo^7caQcpU?Qn}j-`s?1vXuzG#j8(A+RUAY})F@=r&F(8nI&HspAy4 z4>(M>hI9c7?DCW8rw6|23?qQMSq?*Vx?v30U%luBo)B-k2mkL)Ljk5xUha3pK>EEj z@(;tH|M@xkuN?gsz;*bygizwYR!6=(Xgcg^>WlGtRYCozY<rFX2E>kaZo)O<^J7a`MX8Pf`gBd4vrtD|qKn&B)C&wp0O-x*@-|m*0egT=-t@%dD zgP2D+#WPptnc;_ugD6%zN}Z+X4=c61XNLb7L1gWd8;NHrBXwJ7s0ce#lWnnFUMTR& z1_R9Fin4!d17d4jpKcfh?MKRxxQk$@)*hradH2$3)nyXep5Z;B z?yX+-Bd=TqO2!11?MDtG0n(*T^!CIiF@ZQymqq1wPM_X$Iu9-P=^}v7npvvPBu!d$ z7K?@CsA8H38+zjA@{;{kG)#AHME>Ix<711_iQ@WWMObXyVO)a&^qE1GqpP47Q|_AG zP`(AD&r!V^MXQ^e+*n5~Lp9!B+#y3#f8J^5!iC@3Y@P`;FoUH{G*pj*q7MVV)29+j z>BC`a|1@U_v%%o9VH_HsSnM`jZ-&CDvbiqDg)tQEnV>b%Ptm)T|1?TrpIl)Y$LnG_ zzKi5j2Fx^K^PG1=*?GhK;$(UCF-tM~^=Z*+Wp{FSuy7iHt9#4n(sUuHK??@v+6*|10Csdnyg9hAsC5_OrSL;jVkLlf zHXIPukLqbhs~-*oa^gqgvtpgTk_7GypwH><53riYYL*M=Q@F-yEPLqQ&1Sc zZB%w}T~RO|#jFjMWcKMZccxm-SL)s_ig?OC?y_~gLFj{n8D$J_Kw%{r0oB8?@dWzn zB528d-wUBQzrrSSLq?fR!K%59Zv9J4yCQhhDGwhptpA5O5U?Hjqt>8nOD zi{)0CI|&Gu%zunGI*XFZh(ix)q${jT8wnnzbBMPYVJc4HX*9d^mz|21$=R$J$(y7V zo0dxdbX3N#=F$zjstTf*t8vL)2*{XH!+<2IJ1VVFa67|{?LP&P41h$2i2;?N~RA30LV`BsUcj zfO9#Pg1$t}7zpv#&)8`mis3~o+P(DxOMgz-V*(?wWaxi?R=NhtW}<#^Z?(BhSwyar zG|A#Q7wh4OfK<|DAcl9THc-W4*>J4nTevsD%dkj`U~wSUCh15?_N@uMdF^Kw+{agk zJ`im^wDqj`Ev)W3k3stasP`88-M0ZBs7;B6{-tSm3>I@_e-QfT?7|n0D~0RRqDb^G zyHb=is;IwuQ&ITzL4KsP@Z`b$d%B0Wuhioo1CWttW8yhsER1ZUZzA{F*K=wmi-sb#Ju+j z-l@In^IKnb{bQG}Ps>+Vu_W#grNKNGto+yjA)?>0?~X`4I3T@5G1)RqGUZuP^NJCq&^HykuYtMDD8qq+l8RcZNJsvN(10{ zQ1$XcGt}QH-U^WU!-wRR1d--{B$%vY{JLWIV%P4-KQuxxDeJaF#{eu&&r!3Qu{w}0f--8^H|KwE>)ORrcR+2Qf zb})DRcH>k0zWK8@{RX}NYvTF;E~phK{+F;MkIP$)T$93Ba2R2TvKc>`D??#mv9wg$ zd~|-`Qx5LwwsZ2hb*Rt4S9dsF%Cny5<1fscy~)d;0m2r$f=83<->c~!GNyb!U)PA; zq^!`@@)UaG)Ew(9V?5ZBq#c%dCWZrplmuM`o~TyHjAIMh0*#1{B>K4po-dx$Tk-Cq z=WZDkP5x2W&Os`N8KiYHRH#UY*n|nvd(U>yO=MFI-2BEp?x@=N<~CbLJBf6P)}vLS?xJXYJ2^<3KJUdrwKnJnTp{ zjIi|R=L7rn9b*D#Xxr4*R<3T5AuOS+#U8hNlfo&^9JO{VbH!v9^JbK=TCGR-5EWR@ zN8T-_I|&@A}(hKeL4_*eb!1G8p~&_Im8|wc>Cdir+gg90n1dw?QaXcx6Op_W1r=axRw>4;rM*UOpT#Eb9xU1IiWo@h?|5uP zka>-XW0Ikp@dIe;MN8B01a7+5V@h3WN{J=HJ*pe0uwQ3S&MyWFni47X32Q7SyCTNQ z+sR!_9IZa5!>f&V$`q!%H8ci!a|RMx5}5MA_kr+bhtQy{-^)(hCVa@I!^TV4RBi zAFa!Nsi3y37I5EK;0cqu|9MRj<^r&h1lF}u0KpKQD^5Y+LvFEwM zLU@@v4_Na#Axy6tn3P%sD^5P#<7F;sd$f4a7LBMk zGU^RZHBcxSA%kCx*eH&wgA?Qwazm8>9SCSz_!;MqY-QX<1@p$*T8lc?@`ikEqJ>#w zcG``^CoFMAhdEXT9qt47g0IZkaU)4R7wkGs^Ax}usqJ5HfDYAV$!=6?>J6+Ha1I<5 z|6=9soU4>E))tW$<#>F ziZ$6>KJf0bPfbx_)7-}tMINlc=}|H+$uX)mhC6-Hz+XZxsKd^b?RFB6et}O#+>Wmw9Ec9) z{q}XFWp{3@qmyK*Jvzpyqv57LIR;hPXKsrh{G?&dRjF%Zt5&m20Ll?OyfUYC3WRn{cgQ?^V~UAv+5 z&_m#&nIwffgX1*Z2#5^Kl4DbE#NrD&Hi4|7SPqZ}(>_+JMz=s|k77aEL}<=0Zfb)a z%F(*L3zCA<=xO)2U3B|pcTqDbBoFp>QyAEU(jMu8(jLA61-H!ucI804+B!$E^cQQa z)_ERrW3g!B9iLb3nn3dlkvD7KsY?sRvls3QC0qPi>o<)GHx%4Xb$5a3GBTJ(k@`e@ z$RUa^%S15^1oLEmA=sayrP5;9qtf!Z1*?e$ORVPsXpL{jL<6E)0sj&swP3}NPmR%FM?O>SQgN5XfHE< zo(4#Cv11(%Nnw_{_Ro}r6=gKd{k?NebJ~<~Kv0r(r0qe4n3LFx$5%x(BKvrz$m?LG zjLIc;hbj0FMdb9aH9Lpsof#yG$(0sG2%RL;d(n>;#jb!R_+dad+K;Ccw!|RY?uS(a zj~?=&M!4C(5LnlH6k%aYvz@7?xRa^2gml%vn&eKl$R_lJ+e|xsNfXzr#xuh(>`}9g zLHSyiFwK^-p!;p$yt7$F|3*IfO3Mlu9e>Dpx8O`37?fA`cj`C0B-m9uRhJjs^mRp# zWB;Aj6|G^1V6`jg7#7V9UFvnB4((nIwG?k%c7h`?0tS8J3Bn0t#pb#SA}N-|45$-j z$R>%7cc2ebAClXc(&0UtHX<>pd)akR3Kx_cK+n<}FhzmTx!8e9^u2e4%x{>T6pQ`6 zO182bh$-W5A3^wos0SV_TgPmF4WUP-+D25KjbC{y_6W_9I2_vNKwU(^qSdn&>^=*t z&uvp*@c8#2*paD!ZMCi3;K{Na;I4Q35zw$YrW5U@Kk~)&rw;G?d7Q&c9|x<Hg|CNMsxovmfth*|E*GHezPTWa^Hd^F4!B3sF;)? z(NaPyAhocu1jUe(!5Cy|dh|W2=!@fNmuNOzxi^tE_jAtzNJ0JR-avc_H|ve#KO}#S z#a(8secu|^Tx553d4r@3#6^MHbH)vmiBpn0X^29xEv!Vuh1n(Sr5I0V&`jA2;WS|Y zbf0e}X|)wA-Pf5gBZ>r4YX3Mav1kKY(ulAJ0Q*jB)YhviHK)w!TJsi3^dMa$L@^{` z_De`fF4;M87vM3Ph9SzCoCi$#Fsd38u!^0#*sPful^p5oI(xGU?yeYjn;Hq1!wzFk zG&2w}W3`AX4bxoVm03y>ts{KaDf!}b&7$(P4KAMP=vK5?1In^-YYNtx1f#}+2QK@h zeSeAI@E6Z8a?)>sZ`fbq9_snl6LCu6g>o)rO;ijp3|$vig+4t} zylEo7$SEW<_U+qgVcaVhk+4k+C9THI5V10qV*dOV6pPtAI$)QN{!JRBKh-D zk2^{j@bZ}yqW?<#VVuI_27*cI-V~sJiqQv&m07+10XF+#ZnIJdr8t`9s_EE;T2V;B z4UnQUH9EdX%zwh-5&wflY#ve!IWt0UE-My3?L#^Bh%kcgP1q{&26eXLn zTkjJ*w+(|_>Pq0v8{%nX$QZbf)tbJaLY$03;MO=Ic-uqYUmUCuXD>J>o6BCRF=xa% z3R4SK9#t1!K4I_d>tZgE>&+kZ?Q}1qo4&h%U$GfY058s%*=!kac{0Z+4Hwm!)pFLR zJ+5*OpgWUrm0FPI2ib4NPJ+Sk07j(`diti^i#kh&f}i>P4~|d?RFb#!JN)~D@)beox}bw?4VCf^y*`2{4`-@%SFTry2h z>9VBc9#JxEs1+0i2^LR@B1J`B9Ac=#FW=(?2;5;#U$0E0UNag_!jY$&2diQk_n)bT zl5Me_SUvqUjwCqmVcyb`igygB_4YUB*m$h5oeKv3uIF0sk}~es!{D>4r%PC*F~FN3owq5e0|YeUTSG#Vq%&Gk7uwW z0lDo#_wvflqHeRm*}l?}o;EILszBt|EW*zNPmq#?4A+&i0xx^?9obLyY4xx=Y9&^G;xYXYPxG)DOpPg!i_Ccl#3L}6xAAZzNhPK1XaC_~ z!A|mlo?Be*8Nn=a+FhgpOj@G7yYs(Qk(8&|h@_>w8Y^r&5nCqe0V60rRz?b5%J;GYeBqSAjo|K692GxD4` zRZyM2FdI+-jK2}WAZTZ()w_)V{n5tEb@>+JYluDozCb$fA4H)$bzg(Ux{*hXurjO^ zwAxc+UXu=&JV*E59}h3kzQPG4M)X8E*}#_&}w*KEgtX)cU{vm9b$atHa;s>| z+L6&cn8xUL*OSjx4YGjf6{Eq+Q3{!ZyhrL&^6Vz@jGbI%cAM9GkmFlamTbcQGvOlL zmJ?(FI)c86=JEs|*;?h~o)88>12nXlpMR4@yh%qdwFNpct;vMlc=;{FSo*apJ;p}! zAX~t;3tb~VuP|ZW;z$=IHf->F@Ml)&-&Bnb{iQyE#;GZ@C$PzEf6~q}4D>9jic@mTO5x76ulDz@+XAcm35!VSu zT*Gs>;f0b2TNpjU_BjHZ&S6Sqk6V1370+!eppV2H+FY!q*n=GHQ!9Rn6MjY!Jc77A zG7Y!lFp8?TIHN!LXO?gCnsYM-gQxsm=Ek**VmZu7vnuufD7K~GIxfxbsQ@qv2T zPa`tvHB$fFCyZl>3oYg?_wW)C>^_iDOc^B7klnTOoytQH18WkOk)L2BSD0r%xgRSW zQS9elF^?O=_@|58zKLK;(f77l-Zzu}4{fXed2saq!5k#UZAoDBqYQS{sn@j@Vtp|$ zG%gnZ$U|9@u#w1@11Sjl8ze^Co=)7yS(}=;68a3~g;NDe_X^}yJj;~s8xq9ahQ5_r zxAlTMnep*)w1e(TG%tWsjo3RR;yVGPEO4V{Zp?=a_0R#=V^ioQu4YL=BO4r0$$XTX zZfnw#_$V}sDAIDrezGQ+h?q24St0QNug_?{s-pI(^jg`#JRxM1YBV;a@@JQvH8*>> zIJvku74E0NlXkYe_624>znU0J@L<-c=G#F3k4A_)*;ky!C(^uZfj%WB3-*{*B$?9+ zDm$WFp=0(xnt6`vDQV3Jl5f&R(Mp};;q8d3I%Kn>Kx=^;uSVCw0L=gw53%Bp==8Sw zxtx=cs!^-_+i{2OK`Q;913+AXc_&Z5$@z3<)So0CU3;JAv=H?@Zpi~riQ{z-zLtVL z!oF<}@IgJp)Iyz1zVJ42!SPHSkjYNS4%ulVVIXdRuiZ@5Mx8LJS}J#qD^Zi_xQ@>DKDr-_e#>5h3dtje*NcwH_h;i{Sx7}dkdpuW z(yUCjckQsagv*QGMSi9u1`Z|V^}Wjf7B@q%j2DQXyd0nOyqg%m{CK_lAoKlJ7#8M} z%IvR?Vh$6aDWK2W!=i?*<77q&B8O&3?zP(Cs@kapc)&p7En?J;t-TX9abGT#H?TW? ztO5(lPKRuC7fs}zwcUKbRh=7E8wzTsa#Z{a`WR}?UZ%!HohN}d&xJ=JQhpO1PI#>X zHkb>pW04pU%Bj_mf~U}1F1=wxdBZu1790>3Dm44bQ#F=T4V3&HlOLsGH)+AK$cHk6 zia$=$kog?)07HCL*PI6}DRhpM^*%I*kHM<#1Se+AQ!!xyhcy6j7`iDX7Z-2i73_n# zas*?7LkxS-XSqv;YBa zW_n*32D(HTYQ0$feV_Fru1ZxW0g&iwqixPX3=9t4o)o|kOo79V$?$uh?#8Q8e>4e)V6;_(x&ViUVxma+i25qea;d-oK7ouuDsB^ab{ zu1qjQ%`n56VtxBE#0qAzb7lph`Eb-}TYpXB!H-}3Ykqyp`otprp7{VEuW*^IR2n$Fb99*nAtqT&oOFIf z@w*6>YvOGw@Ja?Pp1=whZqydzx@9X4n^2!n83C5{C?G@|E?&$?p*g68)kNvUTJ)I6 z1Q|(#UuP6pj78GUxq11m-GSszc+)X{C2eo-?8ud9sB=3(D47v?`JAa{V(IF zPZQ_0AY*9M97>Jf<o%#O_%Wq}8>YM=q0|tGY+hlXcpE=Z4Od z`NT7Hu2hnvRoqOw@g1f=bv`+nba{GwA$Ak0INlqI1k<9!x_!sL()h?hEWoWrdU3w` zZ%%)VR+Bc@_v!C#koM1p-3v_^L6)_Ktj4HE>aUh%2XZE@JFMOn)J~c`_7VWNb9c-N z2b|SZMR4Z@E7j&q&9(6H3yjEu6HV7{2!1t0lgizD;mZ9$r(r7W5G$ky@w(T_dFnOD z*p#+z$@pKE+>o@%eT(2-p_C}wbQ5s(%Sn_{$HDN@MB+Ev?t@3dPy`%TZ!z}AThZSu zN<1i$siJhXFdjV zP*y|V<`V8t=h#XTRUR~5`c`Z9^-`*BZf?WAehGdg)E2Je)hqFa!k{V(u+(hTf^Yq& zoruUh2(^3pe)2{bvt4&4Y9CY3js)PUHtd4rVG57}uFJL)D(JfSIo^{P=7liFXG zq5yqgof0V8paQcP!gy+;^pp-DA5pj=gbMN0eW=-eY+N8~y+G>t+x}oa!5r>tW$xhI zPQSv=pi;~653Gvf6~*JcQ%t1xOrH2l3Zy@8AoJ+wz@daW@m7?%LXkr!bw9GY@ns3e zSfuWF_gkWnesv?s3I`@}NgE2xwgs&rj?kH-FEy82=O8`+szN ziHch`vvS`zNfap14!&#i9H@wF7}yIPm=UB%(o(}F{wsZ(wA0nJ2aD^@B41>>o-_U6 zUqD~vdo48S8~FTb^+%#zcbQiiYoDKYcj&$#^;Smmb+Ljp(L=1Kt_J!;0s%1|JK}Wi z;={~oL!foo5n8=}rs6MmUW~R&;SIJO3TL4Ky?kh+b2rT9B1Jl4>#Uh-Bec z`Hsp<==#UEW6pGPhNk8H!!DUQR~#F9jEMI6T*OWfN^Ze&X(4nV$wa8QUJ>oTkruH# zm~O<`J7Wxseo@FqaZMl#Y(mrFW9AHM9Kb|XBMqaZ2a)DvJgYipkDD_VUF_PKd~dT7 z#02}bBfPn9a!X!O#83=lbJSK#E}K&yx-HI#T6ua)6o0{|={*HFusCkHzs|Fn&|C3H zBck1cmfcWVUN&i>X$YU^Sn6k2H;r3zuXbJFz)r5~3$d$tUj(l1?o={MM){kjgqXRO zc5R*#{;V7AQh|G|)jLM@wGAK&rm2~@{Pewv#06pHbKn#wL0P6F1!^qw9g&cW3Z=9} zj)POhOlwsh@eF=>z?#sIs*C-Nl(yU!#DaiaxhEs#iJqQ8w%(?+6lU02MYSeDkr!B- zPjMv+on6OLXgGnAtl(ao>|X2Y8*Hb}GRW5}-IzXnoo-d0!m4Vy$GS!XOLy>3_+UGs z2D|YcQx@M#M|}TDOetGi{9lGo9m-=0-^+nKE^*?$^uHkxZh}I{#UTQd;X!L+W@jm( zDg@N4+lUqI92o_rNk{3P>1gxAL=&O;x)ZT=q1mk0kLlE$WeWuY_$0`0jY-Kkt zP*|m3AF}Ubd=`<>(Xg0har*_@x2YH}bn0Wk*OZz3*e5;Zc;2uBdnl8?&XjupbkOeNZsNh6pvsq_ydmJI+*z**{I{0K)-;p1~k8cpJXL$^t!-`E}=*4G^-E8>H!LjTPxSx zcF+cS`ommfKMhNSbas^@YbTpH1*RFrBuATUR zt{oFWSk^$xU&kbFQ;MCX22RAN5F6eq9UfR$ut`Jw--p2YX)A*J69m^!oYfj2y7NYcH6&r+0~_sH^c^nzeN1AU4Ga7=FlR{S|Mm~MpzY0$Z+p2W(a={b-pR9EO1Rs zB%KY|@wLcAA@)KXi!d2_BxrkhDn`DT1=Dec}V!okd{$+wK z4E{n8R*xKyci1(CnNdhf$Dp2(Jpof0-0%-38X=Dd9PQgT+w%Lshx9+loPS~MOm%ZT zt%2B2iL_KU_ita%N>xjB!#71_3=3c}o zgeW~^U_ZTJQ2!PqXulQd=3b=XOQhwATK$y(9$#1jOQ4}4?~l#&nek)H(04f(Sr=s| zWv7Lu1=%WGk4FSw^;;!8&YPM)pQDCY9DhU`hMty1@sq1=Tj7bFsOOBZOFlpR`W>-J$-(kezWJj;`?x-v>ev{*8V z8p|KXJPV$HyQr1A(9LVrM47u-XpcrIyO`yWvx1pVYc&?154aneRpLqgx)EMvRaa#|9?Wwqs2+W8n5~79G z(}iCiLk;?enn}ew`HzhG+tu+Ru@T+K5juvZN)wY;x6HjvqD!&!)$$;1VAh~7fg0K| zEha#aN=Yv|3^~YFH}cc38ovVb%L|g@9W6fo(JtT6$fa?zf@Ct88e}m?i)b*Jgc{fl zExfdvw-BYDmH6>(4QMt#p0;FUIQqkhD}aH?a7)_%JtA~soqj{ppP_82yi9kaxuK>~ ze_)Zt>1?q=ZH*kF{1iq9sr*tVuy=u>Zev}!gEZx@O6-fjyu9X00gpIl-fS_pzjpqJ z1yqBmf9NF!jaF<+YxgH6oXBdK)sH(>VZ)1siyA$P<#KDt;8NT*l_0{xit~5j1P)FN zI8hhYKhQ)i z37^aP13B~u65?sg+_@2Kr^iWHN=U;EDSZ@2W2!5ALhGNWXnFBY%7W?1 z=HI9JzQ-pLKZDYTv<0-lt|6c-RwhxZ)mU2Os{bsX_i^@*fKUj8*aDO5pks=qn3Dv6 zwggpKLuyRCTVPwmw1r}B#AS}?X7b837UlXwp~E2|PJw2SGVueL7){Y&z!jL!XN=0i zU^Eig`S2`{+gU$68aRdWx?BZ{sU_f=8sn~>s~M?GU~`fH5kCc; z8ICp+INM3(3{#k32RZdv6b9MQYdZXNuk7ed8;G?S2nT+NZBG=Tar^KFl2SvhW$bGW#kdWL-I)s_IqVnCDDM9fm8g;P;8 z7t4yZn3^*NQfx7SwmkzP$=fwdC}bafQSEF@pd&P8@H#`swGy_rz;Z?Ty5mkS%>m#% zp_!m9e<()sfKiY(nF<1zBz&&`ZlJf6QLvLhl`_``%RW&{+O>Xhp;lwSsyRqGf=RWd zpftiR`={2(siiPAS|p}@q=NhVc0ELprt%=fMXO3B)4ryC2LT(o=sLM7hJC!}T1@)E zA3^J$3&1*M6Xq>03FX`R&w*NkrZE?FwU+Muut;>qNhj@bX17ZJxnOlPSZ=Zeiz~T_ zOu#yc3t6ONHB;?|r4w+pI)~KGN;HOGC)txxiUN8#mexj+W(cz%9a4sx|IRG=}ia zuEBuba3AHsV2feqw-3MvuL`I+2|`Ud4~7ZkN=JZ;L20|Oxna5vx1qbIh#k2O4$RQF zo`tL()zxaqibg^GbB+BS5#U{@K;WWQj~GcB1zb}zJkPwH|5hZ9iH2308!>_;%msji zJHSL~s)YHBR=Koa1mLEOHos*`gp=s8KA-C zu0aE+W!#iJ*0xqKm3A`fUGy#O+X+5W36myS>Uh2!R*s$aCU^`K&KKLCCDkejX2p=5 z%o7-fl03x`gaSNyr?3_JLv?2RLS3F*8ub>Jd@^Cc17)v8vYEK4aqo?OS@W9mt%ITJ z9=S2%R8M){CugT@k~~0x`}Vl!svYqX=E)c_oU6o}#Hb^%G1l3BudxA{F*tbjG;W_>=xV73pKY53v%>I)@D36I_@&p$h|Aw zonQS`07z_F#@T-%@-Tb|)7;;anoD_WH>9ewFy(ZcEOM$#Y)8>qi7rCnsH9GO-_7zF zu*C87{Df1P4TEOsnzZ@H%&lvV(3V@;Q!%+OYRp`g05PjY^gL$^$-t0Y>H*CDDs?FZly*oZ&dxvsxaUWF!{em4{A>n@vpXg$dwvt@_rgmHF z-MER`ABa8R-t_H*kv>}CzOpz;!>p^^9ztHMsHL|SRnS<-y5Z*r(_}c4=fXF`l^-i}>e7v!qs_jv zqvWhX^F=2sDNWA9c@P0?lUlr6ecrTKM%pNQ^?*Lq?p-0~?_j50xV%^(+H>sMul#Tw zeciF*1=?a7cI(}352%>LO96pD+?9!fNyl^9v3^v&Y4L)mNGK0FN43&Xf8jUlxW1Bw zyiu2;qW-aGNhs=zbuoxnxiwZ3{PFZM#Kw)9H@(hgX23h(`Wm~m4&TvoZoYp{plb^> z_#?vXcxd>r7K+1HKJvhed>gtK`TAbJUazUWQY6T~t2af%#<+Veyr%7-#*A#@&*;@g58{i|E%6yC_InGXCOd{L0;$)z#?n7M`re zh!kO{6=>7I?*}czyF7_frt#)s1CFJ_XE&VrDA?Dp3XbvF{qsEJgb&OLSNz_5g?HpK z9)8rsr4JN!Af3G9!#Qn(6zaUDqLN(g2g8*M)Djap?WMK9NKlkC)E2|-g|#-rp%!Gz zAHd%`iq|81efi93m3yTBw3g0j#;Yb2X{mhRAI?&KDmbGqou(2xiRNb^sV}%%Wu0?< z?($L>(#BO*)^)rSgyNRni$i`R4v;GhlCZ8$@e^ROX(p=2_v6Y!%^As zu022)fHdv_-~Yu_H6WVPLpHQx!W%^6j)cBhS`O3QBW#x(eX54d&I22op(N59b*&$v zFiSRY6rOc^(dgSV1>a7-5C;(5S5MvKcM2Jm-LD9TGqDpP097%52V+0>Xqq!! zq4e3vj53SE6i8J`XcQB|MZPP8j;PAOnpGnllH6#Ku~vS42xP*Nz@~y%db7Xi8s09P z1)e%8ys6&M8D=Dt6&t`iKG_4X=!kgRQoh%Z`dc&mlOUqXk-k`jKv9@(a^2-Upw>?< zt5*^DV~6Zedbec4NVl($2T{&b)zA@b#dUyd>`2JC0=xa_fIm8{5um zr-!ApXZhC8@=vC2WyxO|!@0Km)h8ep*`^he92$@YwP>VcdoS5OC^s38e#7RPsg4j+ zbVGG}WRSET&ZfrcR(x~k8n1rTP%CnfUNKUonD$P?FtNFF#cn!wEIab-;jU=B1dHK@ z(;(yAQJ`O$sMn>h;pf^8{JISW%d+@v6@CnXh9n5TXGC}?FI9i-D0OMaIg&mAg=0Kn zNJ7oz5*ReJukD55fUsMuaP+H4tDN&V9zfqF@ zr=#ecUk9wu{0;!+gl;3Bw=Vn^)z$ahVhhw)io!na&9}LmWurLb0zubxK=UEnU*{5P z+SP}&*(iBKSO4{alBHaY^)5Q=mZ+2OwIooJ7*Q5XJ+2|q`9#f?6myq!&oz?klihLq z4C)$XP!BNS0G_Z1&TM>?Jk{S~{F3n83ioli=IO6f%wkvCl(RFFw~j0tb{GvXTx>*sB0McY0s&SNvj4+^h`9nJ_wM>F!Uc>X}9PifQekn0sKI2SAJP!a4h z5cyGTuCj3ZBM^&{dRelIlT^9zcfaAuL5Y~bl!ppSf`wZbK$z#6U~rdclk``e+!qhe z6Qspo*%<)eu6?C;Bp<^VuW6JI|Ncvyn+LlSl;Mp22Bl7ARQ0Xc24%29(ZrdsIPw&-=yHQ7_Vle|5h>AST0 zUGX2Zk34vp?U~IHT|;$U86T+UUHl_NE4m|}>E~6q``7hccCaT^#y+?wD##Q%HwPd8 zV3x4L4|qqu`B$4(LXqDJngNy-{&@aFBvVsywt@X^}iH7P%>bR?ciC$I^U-4Foa`YKI^qDyGK7k%E%c_P=yzAi`YnxGA%DeNd++j3*h^ z=rn>oBd0|~lZ<6YvmkKY*ZJlJ;Im0tqgWu&E92eqt;+NYdxx`eS(4Hw_Jb5|yVvBg z*tbdY^!AN;luEyN4VRhS@-_DC{({ziH{&Z}iGElSV~qvT>L-8G%+yEL zX#MFOhj{InyKG=mvW-<1B@c-}x$vA(nU?>S>0*eN#!SLzQ)Ex7fvQ)S4D<8|I#N$3 zT5Ei`Z?cxBODHX8(Xp73v`IsAYC@9b;t}z0wxVuQSY1J^GRwDPN@qbM-ZF48T$GZ< z8WU+;Pqo?{ghI-KZ-i*ydXu`Ep0Xw^McH_KE9J0S7G;x8Fe`DVG?j3Pv=0YzJ}yZR z%2=oqHiUjvuk0~Ca>Kol4CFi0_xQT~;_F?=u+!kIDl-9g`#ZNZ9HCy17Ga1v^Jv9# z{T4Kb1-AzUxq*MutfOWWZgD*HnFfyYg0&e9f(5tZ>krPF6{VikNeHoc{linPPt#Si z&*g>(c54V8rT_AX!J&bNm-!umPvOR}vDai#`CX___J#=zeB*{4<&2WpaDncZsOkp* zsg<%@@rbrMkR_ux9?LsQxzoBa1s%$BBn6vk#{&&zUwcfzeCBJUwFYSF$08qDsB;gWQN*g!p8pxjofWbqNSZOEKOaTx@+* zwdt5*Q47@EOZ~EZL9s?1o?A%9TJT=Ob_13yyugvPg*e&ZU(r6^k4=2+D-@n=Hv5vu zSXG|hM(>h9^zn=eQ=$6`JO&70&2|%V5Lsx>)(%#;pcOfu>*nk_3HB_BNaH$`jM<^S zcSftDU1?nL;jy)+sfonQN}(}gUW?d_ikr*3=^{G)=tjBtEPe>TO|0ddVB zTklrSHiW+!#26frPXQQ(YN8DG$PZo?(po(QUCCf_OJC`pw*uey00%gmH!`WJkrKXj2!#6?`T25mTu9OJp2L8z3! z=arrL$ZqxuE{%yV)14Kd>k}j7pxZ6#$Dz8$@WV5p8kTqN<-7W)Q7Gt2{KoOPK_tZ| zf2WG~O5@{qPI+W<4f_;reuFVdO^5`ADC1!JQE|N`s3cq@(0WB!n0uh@*c{=LAd;~} zyGK@hbF-Oo+!nN)@i*O(`@FA#u?o=~e{`4O#5}z&=UkU*50fOrzi11D^&FOqe>wii z?*k+2|EcUs;Gx{!@KBT~>PAwLrIDT7Th=Utu?~?np@t^gFs?zgX=D${RwOY^WGh-+ z+#4$066ISh8eYW#FXWp~S`<*%O^ZuItL1Tyqt8#tZ zY120E;^VG`!lZn&3sPd$RkdHpU#|w+bYV)pJC|SH9g%|5IkxVTQcBA4CL0}$&}ef@ zW^Vtj%M;;_1xxP9x#ex17&4N*{ksO*_4O}xYu(p*JkL#yr}@7b)t5X?%CY<+s5_MJ zuiqt+N_;A(_)%lumoyRFixWa-M7qK_9s6<1X?JDa9fP!+_6u~~M$5L=ipB=7(j#f< zZ34J%=bs549%~_mA(|={uZNs_0?o7;-LBP(ZRnkd{-^|2|=4vUTmtByHL8 zEph`(LSEzQj68a+`d$V<45J7cyv^#|^|%fD#si1Nx!4NW*`l*{->HEWNh6-|g>-=r zXmQ|-i}Ku$ndUeHQ^&ieT!Lf}vf6GaqW9$DJ2NWrqwPY%%4nip$@vK$nRp*_C-v<| zuKz~ZyN&<%!NS26&x?jhy+@awJipMQ-8(X4#Ae5??U<1QMt1l9R=w9fAnEF}NYu$2 z>6}Vkc zIb*A?G*z8^IvibmBKn_u^5&T_1oey0gZS2~obf(#xk=erZGTEdQnt3DMGM+0oPwss zj5zXD;(oWhB_T@~Ig#9@v)AKtXu3>Inmgf@A|-lD-1U>cNyl3h?ADD9)GG4}zUGPk zZzaXe!~Kf?<~@$G?Uql3t8jy9{2!doq4=J}j9ktTxss{p6!9UdjyDERlA*xZ!=Q)KDs5O)phz>Vq3BNGoM(H|=1*Q4$^2fTZw z(%nq1P|5Rt81}SYJpEEzMPl5VJsV5&4e)ZWKDyoZ>1EwpkHx-AQVQc8%JMz;{H~p{=FXV>jIxvm4X*qv52e?Y-f%DJ zxEA165GikEASQ^fH6K#d!Tpu2HP{sFs%E=e$gYd$aj$+xue6N+Wc(rAz~wUsk2`(b z8Kvmyz%bKQxpP}~baG-rwYcYCvkHOi zlkR<=>ZBTU*8RF_d#Bl@zZsRIhx<%~Z@Z=ik z>adw3!DK(8R|q$vy{FTxw%#xliD~6qXmY^7_9kthVPTF~Xy1CfBqbU~?1QmxmU=+k z(ggxvEuA;0e&+ci-zQR{-f7aO{O(Pz_OsEjLh_K>MbvoZ4nxtk5u{g@nPv)cgW_R} z9}EA4K4@z0?7ue}Z(o~R(X&FjejUI2g~08PH1E4w>9o{)S(?1>Z0XMvTb|;&EuyOE zGvWNpYX)Nv<8|a^;1>bh#&znEcl-r!T#pn= z4$?Yudha6F%4b>*8@=BdtXXY4N+`U4Dmx$}>HeVJk-QdTG@t!tVT#0(LeV0gvqyyw z2sEp^9eY0N`u10Tm4n8No&A=)IeEC|gnmEXoNSzu!1<4R<%-9kY_8~5Ej?zRegMn78wuMs#;i&eUA0Zk_RXQ3b&TT} z;SCI=7-FUB@*&;8|n>(_g^HGf3@QODE3LpmX~ELnymQm{Sx9xrKS zK29p~?v@R$0=v6Dr5aW>-!{+h@?Q58|Kz8{{W`%J+lDAdb&M5VHrX_mDY;1-JLnf)ezmPau$)1;=`-FU=-r-83tX=C`S#}GZufju zQ>sXNT0Ny=k@nc%cFnvA_i4SC)?_ORXHq8B4D%el1uPX`c~uG#S1M7C+*MMqLw78E zhY2dI8@+N^qrMI1+;TUda(vGqGSRyU{Fnm`aqrr7bz42c5xsOO-~oZpkzorD1g}Y<6rk&3>PsSGy}W?MtqFky@A(X# zIuNZK0cK?^=;PUAu>j0#HtjbHCV*6?jzA&OoE$*Jlga*}LF`SF?WLhv1O|zqC<>*> zYB;#lsYKx0&kH@BFpW8n*yDcc6?;_zaJs<-jPSkCsSX-!aV=P5kUgF@Nu<{a%#K*F z134Q{9|YX7X(v$62_cY3^G%t~rD>Q0z@)1|zs)vjJ6Jq9;7#Ki`w+eS**En?7;n&7 zu==V3T&eFboN3ZiMx3D8qYc;VjFUk_H-WWCau(VFXSQf~viH0L$gwD$UfFHqNcgN`x}M+YQ6RnN<+@t>JUp#)9YOkqst-Ga?{FsDpEeX0(5v{0J~SEbWiL zXC2}M4?UH@u&|;%0y`eb33ldo4~z-x8zY!oVmV=c+f$m?RfDC35mdQ2E>Pze7KWP- z>!Bh<&57I+O_^s}9Tg^k)h7{xx@0a0IA~GAOt2yy!X%Q$1rt~LbTB6@Du!_0%HV>N zlf)QI1&gvERKwso23mJ!Ou6ZS#zCS5W`gxE5T>C#E|{i<1D35C222I33?Njaz`On7 zi<+VWFP6D{e-{yiN#M|Jgk<44u1TiMI78S5W`Sdb5f+{zu34s{CfWN7a3Cf^@L%!& zN$?|!!9j2c)j$~+R6n#891w-z8(!oBpL2K=+%a$r2|~8-(vQj5_XT`<0Ksf;oP+tz z9CObS!0m)Tgg`K#xBM8B(|Z)Wb&DYL{WTYv`;A=q6~Nnx2+!lTIXtj8J7dZE!P_{z z#f8w6F}^!?^KE#+ZDv+xd5O&3EmomZzsv?>E-~ygGum45fk!SBN&|eo1rKw^?aZJ4 E2O(~oYXATM literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..0f80bbf516 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000000..4f906e0c81 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000000..ac1b06f938 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000000..5e07a69a83 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,11 @@ +pluginManagement { + repositories { + gradlePluginPortal() + maven("https://wav.jfrog.io/artifactory/repo/") + mavenLocal() + } +} + +rootProject.name = "Paper" + +include("Paper-API", "Paper-Server", "Paper-MojangAPI") From 604ebc2caccf4848b0f3de060bc01390ebbe41c5 Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Fri, 11 Jun 2021 06:23:18 -0500 Subject: [PATCH 003/226] Update paperweight & build config for Spigot changes --- .giattributes | 7 + .gitignore | 3 + .../additional-spigot-member-mappings.csrg | 18 +- .../BehaviorWorkComposter.patch.patch | 17 - .../ChunkProviderServer.patch.patch | 40 - build-data/mappings-patch.tiny | 42 +- build.gradle.kts | 8 +- bukkit-e3c5450d-combined.csrg | 5198 ----------------- gradle.properties | 2 +- paper | 258 - pom.xml | 55 - settings.gradle.kts | 3 +- 12 files changed, 44 insertions(+), 5607 deletions(-) create mode 100644 .giattributes delete mode 100644 build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch delete mode 100644 build-data/craftbukkit-patch-patches/ChunkProviderServer.patch.patch delete mode 100644 bukkit-e3c5450d-combined.csrg delete mode 100755 paper delete mode 100644 pom.xml diff --git a/.giattributes b/.giattributes new file mode 100644 index 0000000000..2fb638f44b --- /dev/null +++ b/.giattributes @@ -0,0 +1,7 @@ +* text=auto + +*.sh text eol=lf +gradlew text eol=lf +*.bat text eol=crlf + +*.jar binary diff --git a/.gitignore b/.gitignore index be158334f4..5c7e1f2db7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +.gradle/ +build/ + # Eclipse stuff .classpath .project diff --git a/build-data/additional-spigot-member-mappings.csrg b/build-data/additional-spigot-member-mappings.csrg index 199b5419bf..9528baf294 100644 --- a/build-data/additional-spigot-member-mappings.csrg +++ b/build-data/additional-spigot-member-mappings.csrg @@ -3,22 +3,20 @@ # Hopper.getLevel() # Entity.getCommandSenderWorld() # to getWorld(), which confuses our ability to map this method properly. This patch disambiguates it -net/minecraft/world/level/block/entity/IHopper v ()Lnet/minecraft/world/level/World; getLevel -net/minecraft/world/entity/vehicle/EntityMinecartHopper v ()Lnet/minecraft/world/level/World; getLevel -net/minecraft/world/item/trading/IMerchant eV ()Lnet/minecraft/world/level/World; getLevel -net/minecraft/world/entity/npc/EntityVillagerAbstract eV ()Lnet/minecraft/world/level/World; getLevel +net/minecraft/world/item/trading/IMerchant fD ()Lnet/minecraft/world/level/World; getLevel +net/minecraft/world/entity/npc/EntityVillagerAbstract fD ()Lnet/minecraft/world/level/World; getLevel # CraftBukkit mappings sometimes have mappings for child classes and not parent classes # We handle this fine for deobf but this breaks reobf. These Patches fix those cases # BossBattle -> BossBattleServer -net/minecraft/world/BossBattle a (F)V setProgress -net/minecraft/world/BossBattle c (Z)Lnet/minecraft/world/BossBattle; setCreateFog -net/minecraft/world/BossBattle a (Z)Lnet/minecraft/world/BossBattle; setDarkenSky -net/minecraft/world/BossBattle b (Z)Lnet/minecraft/world/BossBattle; setPlayMusic +# net/minecraft/world/BossBattle a (F)V setProgress +# net/minecraft/world/BossBattle c (Z)Lnet/minecraft/world/BossBattle; setCreateFog +# net/minecraft/world/BossBattle a (Z)Lnet/minecraft/world/BossBattle; setDarkenSky +# net/minecraft/world/BossBattle b (Z)Lnet/minecraft/world/BossBattle; setPlayMusic # IChunkProvider -> ChunkProviderServer -net/minecraft/world/level/chunk/IChunkProvider b (II)Z isLoaded +# net/minecraft/world/level/chunk/IChunkProvider b (II)Z isLoaded # BehaviorWorkComposter -> BehaviorWork -net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter a (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/npc/EntityVillager;)V doWork +# net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter a (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/npc/EntityVillager;)V doWork diff --git a/build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch b/build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch deleted file mode 100644 index a35b59fd5d..0000000000 --- a/build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- a/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.patch -+++ b/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.patch -@@ -1,14 +1,5 @@ - --- a/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.java - +++ b/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.java --@@ -24,7 +24,7 @@ -- public BehaviorWorkComposter() {} -- -- @Override --- protected void a(WorldServer worldserver, EntityVillager entityvillager) { --+ protected void doWork(WorldServer worldserver, EntityVillager entityvillager) { // PAIL -- Optional optional = entityvillager.getBehaviorController().getMemory(MemoryModuleType.JOB_SITE); -- -- if (optional.isPresent()) { - @@ -43,7 +43,7 @@ - BlockPosition blockposition = globalpos.getBlockPosition(); - diff --git a/build-data/craftbukkit-patch-patches/ChunkProviderServer.patch.patch b/build-data/craftbukkit-patch-patches/ChunkProviderServer.patch.patch deleted file mode 100644 index 0372012c03..0000000000 --- a/build-data/craftbukkit-patch-patches/ChunkProviderServer.patch.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- a/net/minecraft/server/level/ChunkProviderServer.patch -+++ b/net/minecraft/server/level/ChunkProviderServer.patch -@@ -74,8 +74,8 @@ - + return playerchunk == null || playerchunk.oldTicketLevel > i; // CraftBukkit using oldTicketLevel for isLoaded checks - } - -- public boolean isLoaded(int i, int j) { --@@ -282,19 +308,19 @@ -+ @Override -+@@ -283,19 +309,19 @@ - public boolean a(Entity entity) { - long i = ChunkCoordIntPair.pair(MathHelper.floor(entity.locX()) >> 4, MathHelper.floor(entity.locZ()) >> 4); - -@@ -98,7 +98,7 @@ - } - - private boolean a(long i, Function>> function) { --@@ -316,11 +342,31 @@ -+@@ -317,11 +343,31 @@ - - @Override - public void close() throws IOException { -@@ -131,7 +131,7 @@ - public void tick(BooleanSupplier booleansupplier) { - this.world.getMethodProfiler().enter("purge"); - this.chunkMapDistance.purgeTickets(); --@@ -340,12 +386,12 @@ -+@@ -341,12 +387,12 @@ - this.lastTickTime = i; - WorldData worlddata = this.world.getWorldData(); - boolean flag = this.world.isDebugWorld(); -@@ -146,7 +146,7 @@ - - this.world.getMethodProfiler().enter("naturalSpawnCount"); - int l = this.chunkMapDistance.b(); --@@ -532,12 +578,18 @@ -+@@ -533,12 +579,18 @@ - - @Override - protected boolean executeNext() { diff --git a/build-data/mappings-patch.tiny b/build-data/mappings-patch.tiny index 0833ee00b0..73cc8abcdf 100644 --- a/build-data/mappings-patch.tiny +++ b/build-data/mappings-patch.tiny @@ -10,41 +10,41 @@ c net/minecraft/world/level/World net/minecraft/world/level/Level # CraftBukkit adds the server field, clashes with a Mojang field c net/minecraft/server/network/PlayerConnection net/minecraft/server/network/ServerGamePacketListenerImpl - f Lorg/bukkit/craftbukkit/CraftServer; server craftServer + m ()Lorg/bukkit/craftbukkit/entity/CraftPlayer; getPlayer getCraftPlayer # CraftBukkit adds the player field, clashes with a Mojang field -c net/minecraft/world/inventory/ContainerWorkbench net/minecraft/world/inventory/CraftingMenu - f Lnet/minecraft/world/entity/player/PlayerInventory; player playerInventory +#c net/minecraft/world/inventory/ContainerWorkbench net/minecraft/world/inventory/CraftingMenu +# f Lnet/minecraft/world/entity/player/PlayerInventory; player playerInventory # CraftBukkit adds the getType() method, clashes with a Mojang method c net/minecraft/world/entity/EntityAreaEffectCloud net/minecraft/world/entity/AreaEffectCloud - m ()Ljava/lang/String; getType getTypeCb + m ()Ljava/lang/String; getType getPotionType # CraftBukkit adds the getType() method, clashes with a Mojang method c net/minecraft/world/entity/projectile/EntityTippedArrow net/minecraft/world/entity/projectile/Arrow - m ()Ljava/lang/String; getType getTypeCb + m ()Ljava/lang/String; getType getPotionType # CraftBukkit adds the getLevel() method, clashes with original method -c net/minecraft/world/level/block/entity/TileEntityBeacon net/minecraft/world/level/block/entity/BeaconBlockEntity - m ()I getLevel getLevelCb +#c net/minecraft/world/level/block/entity/TileEntityBeacon net/minecraft/world/level/block/entity/BeaconBlockEntity +# m ()I getLevel getLevelCb # CraftBukkit adds the getLootTable() method, clashes with original method -c net/minecraft/world/entity/EntityInsentient net/minecraft/world/entity/Mob - m ()Lnet/minecraft/resources/MinecraftKey; getLootTable getLootTableCb +#c net/minecraft/world/entity/EntityInsentient net/minecraft/world/entity/Mob +# m ()Lnet/minecraft/resources/MinecraftKey; getLootTable getLootTableCb # CraftBukkit adds the canCollideWith() method, clashes with original method -c net/minecraft/world/entity/Entity net/minecraft/world/entity/Entity - m (Lnet/minecraft/world/entity/Entity;)Z canCollideWith canCollideWithCb +#c net/minecraft/world/entity/Entity net/minecraft/world/entity/Entity +# m (Lnet/minecraft/world/entity/Entity;)Z canCollideWith canCollideWithCb # CraftBukkit adds a new `a` method which allows passing the Entity parameter # It uses `a` to match the original method (with just 1 param), so this patch makes them match -c net/minecraft/server/level/WorldServer net/minecraft/server/level/ServerLevel - m (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/Entity;)V a makeObsidianPlatform +#c net/minecraft/server/level/WorldServer net/minecraft/server/level/ServerLevel +# m (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/Entity;)V a makeObsidianPlatform # CraftBukkit adds `getMinecraftWorld()` to `GeneratorAccess`, which matches `WorldAccess.getMinecraftWorld()` # But that method in `WorldAccess` is called `getLevel()` in Mojang mappings -c net/minecraft/world/level/GeneratorAccess net/minecraft/world/level/LevelAccessor - m ()Lnet/minecraft/server/level/WorldServer; getMinecraftWorld getLevel +#c net/minecraft/world/level/GeneratorAccess net/minecraft/world/level/LevelAccessor +# m ()Lnet/minecraft/server/level/WorldServer; getMinecraftWorld getLevel # SpecialSource2 automatically maps methods to the name of synthetic methods that point to it in an attempt to # normalize method names with what is expected by the super class. This is _extremely_ stupid and flawed however @@ -68,9 +68,9 @@ c net/minecraft/world/level/GeneratorAccess net/minecraft/world/level/LevelAcces # This is allowed because the synthetic method for serialize() has a different descriptor, using Object as the second # parameter. This breaks when SpecialSource2 does it's "magic" of course. This patch manually fixes this case by adding # both correct mappings -c net/minecraft/world/level/storage/loot/entries/LootEntryAbstract$Serializer net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer$Serializer - m (Lcom/google/gson/JsonObject;Lnet/minecraft/world/level/storage/loot/entries/LootEntryAbstract;Lcom/google/gson/JsonSerializationContext;)V a serialize - p 0 json - p 1 entry - p 2 context - m (Lcom/google/gson/JsonObject;Lnet/minecraft/world/level/storage/loot/entries/LootEntryAbstract;Lcom/google/gson/JsonSerializationContext;)V serializeType serializeCustom +#c net/minecraft/world/level/storage/loot/entries/LootEntryAbstract$Serializer net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer$Serializer +# m (Lcom/google/gson/JsonObject;Lnet/minecraft/world/level/storage/loot/entries/LootEntryAbstract;Lcom/google/gson/JsonSerializationContext;)V a serialize +# p 0 json +# p 1 entry +# p 2 context +# m (Lcom/google/gson/JsonObject;Lnet/minecraft/world/level/storage/loot/entries/LootEntryAbstract;Lcom/google/gson/JsonSerializationContext;)V serializeType serializeCustom diff --git a/build.gradle.kts b/build.gradle.kts index 42b4fa89ba..0de5a09f47 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight") version "1.0.0-SNAPSHOT" + id("io.papermc.paperweight.core") version "1.0.0-SNAPSHOT" } group = "com.destroystokyo.paper" @@ -15,7 +15,7 @@ allprojects { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(11)) + languageVersion.set(JavaLanguageVersion.of(16)) } } } @@ -62,7 +62,7 @@ repositories { } dependencies { - paramMappings("org.quiltmc:yarn:1.16.5+build.6:mergedv2") + paramMappings("org.quiltmc:yarn:1.17+build.2:mergedv2") remapper("org.quiltmc:tiny-remapper:0.3.2:fat@jar") decompiler("net.minecraftforge:forgeflower:1.5.498.5@jar") paperclip("io.papermc:paperclip:2.0.0-SNAPSHOT@jar") @@ -77,7 +77,5 @@ paperweight { mappingsPatch.set(file("build-data/mappings-patch.tiny")) additionalSpigotMemberMappings.set(file("build-data/additional-spigot-member-mappings.csrg")) - - craftBukkitPatchPatchesDir.set(file("build-data/craftbukkit-patch-patches")) } } diff --git a/bukkit-e3c5450d-combined.csrg b/bukkit-e3c5450d-combined.csrg deleted file mode 100644 index d6c04f21fc..0000000000 --- a/bukkit-e3c5450d-combined.csrg +++ /dev/null @@ -1,5198 +0,0 @@ -# (c) 2021 SpigotMC Pty. Ltd. -aa net/minecraft/ResourceKeyInvalidException -aaa net/minecraft/server/commands/CommandTeam -aab net/minecraft/server/commands/CommandTeamMsg -aac net/minecraft/server/commands/CommandTeleport -aad net/minecraft/server/commands/CommandTellRaw -aae net/minecraft/server/commands/CommandTime -aaf net/minecraft/server/commands/CommandTitle -aag net/minecraft/server/commands/CommandTrigger -aah net/minecraft/server/commands/CommandWeather -aai net/minecraft/server/commands/CommandWhitelist -aaj net/minecraft/server/commands/CommandWorldBorder -aak net/minecraft/server/commands/data/CommandDataAccessorTile -aal net/minecraft/server/commands/data/CommandDataAccessor -aam net/minecraft/server/commands/data/CommandData -aan net/minecraft/server/commands/data/CommandDataAccessorEntity -aao net/minecraft/server/commands/data/CommandDataStorage -aar net/minecraft/server/dedicated/DedicatedPlayerList -aas net/minecraft/server/dedicated/DedicatedServer -aat net/minecraft/server/dedicated/DedicatedServerProperties -aau net/minecraft/server/dedicated/DedicatedServerSettings -aav net/minecraft/server/dedicated/ThreadWatchdog -aaw net/minecraft/server/dedicated/PropertyManager -aaw$a net/minecraft/server/dedicated/PropertyManager$EditableProperty -aay net/minecraft/server/gui/ServerGUI -aaz net/minecraft/server/gui/PlayerListBox -ab net/minecraft/SharedConstants -aba net/minecraft/server/gui/GuiStatsComponent -abd net/minecraft/server/level/PlayerChunk -abd$a net/minecraft/server/level/PlayerChunk$Failure -abd$c net/minecraft/server/level/PlayerChunk$State -abe net/minecraft/server/level/PlayerChunkMap -abe$b net/minecraft/server/level/PlayerChunkMap$EntityTracker -abf net/minecraft/server/level/ChunkTaskQueue -abg net/minecraft/server/level/ChunkTaskQueueSorter -abh net/minecraft/server/level/ChunkMap -abi net/minecraft/server/level/BlockPosition2D -abj net/minecraft/server/level/DemoPlayerInteractManager -abk net/minecraft/server/level/ChunkMapDistance -abl net/minecraft/server/level/PlayerMap -abm net/minecraft/server/level/WorldProviderNormal -abn net/minecraft/server/level/LightEngineGraphSection -abo net/minecraft/server/level/BossBattleServer -abp net/minecraft/server/level/ChunkProviderServer -abq net/minecraft/server/level/EntityTrackerEntry -abr net/minecraft/server/level/WorldServer -abs net/minecraft/server/level/EntityPlayer -abt net/minecraft/server/level/PlayerInteractManager -abu net/minecraft/server/level/LightEngineThreaded -abu$a net/minecraft/server/level/LightEngineThreaded$Update -abv net/minecraft/server/level/Ticket -abw net/minecraft/server/level/TicketType -abx net/minecraft/server/level/RegionLimitedWorldAccess -aby net/minecraft/server/level/TickListWorldGen -ac net/minecraft/SystemReport -aca net/minecraft/server/level/progress/WorldLoadListener -acb net/minecraft/server/level/progress/WorldLoadListenerFactory -acc net/minecraft/server/level/progress/WorldLoadListenerLogger -acg net/minecraft/server/network/LegacyPingHandler -ach net/minecraft/server/network/MemoryServerHandshakePacketListenerImpl -aci net/minecraft/server/network/ServerConnection -aci$a net/minecraft/server/network/ServerConnection$LatencySimulator -aci$a$a net/minecraft/server/network/ServerConnection$LatencySimulator$DelayedMessage -acj net/minecraft/server/network/PlayerConnection -ack net/minecraft/server/network/HandshakeListener -acl net/minecraft/server/network/LoginListener -acl$a net/minecraft/server/network/LoginListener$EnumProtocolState -acm net/minecraft/server/network/ServerPlayerConnection -acn net/minecraft/server/network/PacketStatusListener -aco net/minecraft/server/network/ITextFilter -acp net/minecraft/server/network/TextFilter -acs net/minecraft/server/packs/ResourcePackAbstract -act net/minecraft/server/packs/ResourcePackFile -acu net/minecraft/server/packs/ResourcePackFolder -acv net/minecraft/server/packs/IResourcePack -acw net/minecraft/server/packs/EnumResourcePackType -acx net/minecraft/server/packs/ResourceNotFoundException -acy net/minecraft/server/packs/ResourcePackVanilla -acz net/minecraft/server/packs/metadata/ResourcePackMetaParser -ad net/minecraft/SystemUtils -ad$a net/minecraft/SystemUtils$IdentityHashingStrategy -ad$b net/minecraft/SystemUtils$OS -ada net/minecraft/server/packs/metadata/pack/ResourcePackInfo -adb net/minecraft/server/packs/metadata/pack/ResourcePackInfoDeserializer -adf net/minecraft/server/packs/repository/ResourcePackSourceFolder -adg net/minecraft/server/packs/repository/ResourcePackLoader -adg$b net/minecraft/server/packs/repository/ResourcePackLoader$Position -adh net/minecraft/server/packs/repository/EnumResourcePackVersion -adi net/minecraft/server/packs/repository/ResourcePackRepository -adj net/minecraft/server/packs/repository/PackSource -adk net/minecraft/server/packs/repository/ResourcePackSource -adl net/minecraft/server/packs/repository/ResourcePackSourceVanilla -adn net/minecraft/server/packs/resources/ResourceManagerFallback -ado net/minecraft/server/packs/resources/IReloadListener -adp net/minecraft/server/packs/resources/ReloadableProfiled -adq net/minecraft/server/packs/resources/IReloadable -adr net/minecraft/server/packs/resources/IReloadableResourceManager -ads net/minecraft/server/packs/resources/IResource -adt net/minecraft/server/packs/resources/IResourceManager -adt$a net/minecraft/server/packs/resources/IResourceManager$Empty -adv net/minecraft/server/packs/resources/ResourceProvider -adw net/minecraft/server/packs/resources/ResourceDataJson -adx net/minecraft/server/packs/resources/ResourceDataAbstract -ady net/minecraft/server/packs/resources/Reloadable -adz net/minecraft/server/packs/resources/ResourceManager -ae net/minecraft/advancements/Advancement -ae$a net/minecraft/advancements/Advancement$SerializedAdvancement -aea net/minecraft/server/packs/resources/Resource -aec net/minecraft/server/players/ExpirableListEntry -aed net/minecraft/server/players/UserCache -aed$a net/minecraft/server/players/UserCache$UserCacheEntry -aee net/minecraft/server/players/IpBanList -aef net/minecraft/server/players/IpBanEntry -aeg net/minecraft/server/players/NameReferencingFileConverter -aeg$a net/minecraft/server/players/NameReferencingFileConverter$FileConversionException -aeh net/minecraft/server/players/PlayerList -aei net/minecraft/server/players/OpList -aej net/minecraft/server/players/OpListEntry -aek net/minecraft/server/players/SleepStatus -ael net/minecraft/server/players/JsonListEntry -aem net/minecraft/server/players/JsonList -aen net/minecraft/server/players/GameProfileBanList -aeo net/minecraft/server/players/GameProfileBanEntry -aep net/minecraft/server/players/WhiteList -aeq net/minecraft/server/players/WhiteListEntry -aes net/minecraft/server/rcon/RemoteStatusReply -aet net/minecraft/server/rcon/StatusChallengeUtils -aeu net/minecraft/server/rcon/RemoteControlCommandListener -aew net/minecraft/server/rcon/thread/RemoteConnectionThread -aex net/minecraft/server/rcon/thread/RemoteStatusListener -aex$a net/minecraft/server/rcon/thread/RemoteStatusListener$RemoteStatusChallenge -aey net/minecraft/server/rcon/thread/RemoteControlSession -aez net/minecraft/server/rcon/thread/RemoteControlListener -af net/minecraft/advancements/Advancements -afb net/minecraft/sounds/Music -afc net/minecraft/sounds/Musics -afd net/minecraft/sounds/SoundEffect -afe net/minecraft/sounds/SoundEffects -aff net/minecraft/sounds/SoundCategory -afh net/minecraft/stats/RecipeBook -afi net/minecraft/stats/RecipeBookSettings -afj net/minecraft/stats/RecipeBookServer -afk net/minecraft/stats/ServerStatisticManager -afl net/minecraft/stats/Statistic -afm net/minecraft/stats/Counter -afn net/minecraft/stats/StatisticWrapper -afo net/minecraft/stats/StatisticList -afp net/minecraft/stats/StatisticManager -afr net/minecraft/tags/TagsBlock -afs net/minecraft/tags/TagsEntity -aft net/minecraft/tags/TagsFluid -afu net/minecraft/tags/GameEventTags -afv net/minecraft/tags/TagsItem -afw net/minecraft/tags/TagsInstance -afx net/minecraft/tags/TagSet -afy net/minecraft/tags/TagUtil -afz net/minecraft/tags/TagStatic -ag net/minecraft/advancements/AdvancementProgress -aga net/minecraft/tags/Tag -agb net/minecraft/tags/Tags -agc net/minecraft/tags/ITagRegistry -agd net/minecraft/tags/TagDataPack -age net/minecraft/tags/TagRegistry -agg net/minecraft/util/DataBits -agh net/minecraft/util/EntitySlice -agi net/minecraft/util/RegistryID -agj net/minecraft/util/MinecraftEncryption -agk net/minecraft/util/CryptographyException -agl net/minecraft/util/CSVWriter -agm net/minecraft/util/DebugBuffer -agn net/minecraft/util/SessionLock -agn$a net/minecraft/util/SessionLock$ExceptionWorldConflict -ago net/minecraft/util/ExceptionSuppressor -agp net/minecraft/util/ExtraCodecs -agq net/minecraft/util/ColorUtil -agr net/minecraft/util/FileZipper -ags net/minecraft/util/FormattedString -agt net/minecraft/util/FormattedStringEmpty -agu net/minecraft/util/CircularTimer -agv net/minecraft/util/ChatDeserializer -agw net/minecraft/util/HttpUtilities -agx net/minecraft/util/LazyInitVar -agy net/minecraft/util/LinearCongruentialGenerator -agz net/minecraft/util/ChatTypeAdapterFactory -ah net/minecraft/advancements/AdvancementRewards -aha net/minecraft/util/MathHelper -ahb net/minecraft/util/ParticleUtils -ahc net/minecraft/util/IProgressUpdate -ahd net/minecraft/util/StreamAccumulator -ahf net/minecraft/util/ArraySetSorted -ahg net/minecraft/util/StringDecomposer -ahh net/minecraft/util/INamable -ahi net/minecraft/util/UtilColor -ahj net/minecraft/util/ThreadingDetector -ahk net/minecraft/util/TimeRange -ahl net/minecraft/util/Tuple -ahm net/minecraft/util/Unit -ahn net/minecraft/util/VisibleForDebug -aho net/minecraft/util/WeightedRandom -aho$a net/minecraft/util/WeightedRandom$WeightedRandomChoice -ahp net/minecraft/util/datafix/DataFixTypes -ahq net/minecraft/util/datafix/DataConverterRegistry -ahr net/minecraft/util/datafix/DataBitsPacked -ahs net/minecraft/util/datafix/fixes/AbstractArrowPickupFix -aht net/minecraft/util/datafix/fixes/DataConverterUUIDBase -ahu net/minecraft/util/datafix/fixes/DataConverterAddChoices -ahv net/minecraft/util/datafix/fixes/DataConverterAdvancement -ahw net/minecraft/util/datafix/fixes/DataConverterAdvancementBase -ahx net/minecraft/util/datafix/fixes/DataConverterAttributes -ahy net/minecraft/util/datafix/fixes/DataConverterBedBlock -ahz net/minecraft/util/datafix/fixes/DataConverterBedItem -ai net/minecraft/advancements/CriterionTriggers -aia net/minecraft/util/datafix/fixes/DataConverterBeehive -aib net/minecraft/util/datafix/fixes/DataConverterBiome -aic net/minecraft/util/datafix/fixes/DataConverterBitStorageAlign -aid net/minecraft/util/datafix/fixes/DataConverterBannerColour -aie net/minecraft/util/datafix/fixes/DataConverterPiston -aif net/minecraft/util/datafix/fixes/DataConverterCustomNameTile -aig net/minecraft/util/datafix/fixes/DataConverterTileEntity -aih net/minecraft/util/datafix/fixes/DataConverterJukeBox -aii net/minecraft/util/datafix/fixes/DataConverterBlockEntityKeepPacked -aij net/minecraft/util/datafix/fixes/DataConverterShulkerBoxBlock -aik net/minecraft/util/datafix/fixes/DataConverterSignText -ail net/minecraft/util/datafix/fixes/DataConverterBlockEntityUUID -aim net/minecraft/util/datafix/fixes/DataConverterBlockName -ain net/minecraft/util/datafix/fixes/DataConverterBlockRename -aio net/minecraft/util/datafix/fixes/BlockRenameFixWithJigsaw -aip net/minecraft/util/datafix/fixes/DataConverterFlattenData -aiq net/minecraft/util/datafix/fixes/DataConverterFlattenState -air net/minecraft/util/datafix/fixes/DataConverterCatType -ais net/minecraft/util/datafix/fixes/CauldronRenameFix -ait net/minecraft/util/datafix/fixes/DataConverterLeavesBiome -aiu net/minecraft/util/datafix/fixes/DataConverterChunkLightRemove -aiv net/minecraft/util/datafix/fixes/ChunkConverterPalette -aiv$b net/minecraft/util/datafix/fixes/ChunkConverterPalette$Direction -aiv$b$a net/minecraft/util/datafix/fixes/ChunkConverterPalette$Direction$Axis -aiv$b$b net/minecraft/util/datafix/fixes/ChunkConverterPalette$Direction$AxisDirection -aiw net/minecraft/util/datafix/fixes/DataConverterChunkStatus -aix net/minecraft/util/datafix/fixes/DataConverterChunkStatus2 -aiy net/minecraft/util/datafix/fixes/DataConverterChunkStructuresTemplateRename -aiz net/minecraft/util/datafix/fixes/DataConverterProtoChunk -aj net/minecraft/advancements/Criterion -aja net/minecraft/util/datafix/fixes/DataConverterColorlessShulkerEntity -ajb net/minecraft/util/datafix/fixes/DataConverterDye -ajc net/minecraft/util/datafix/fixes/DataConverterArmorStand -ajd net/minecraft/util/datafix/fixes/DataConverterEntityBlockState -aje net/minecraft/util/datafix/fixes/DataConverterEntityCatSplit -ajf net/minecraft/util/datafix/fixes/DataConverterEntityCodSalmon -ajg net/minecraft/util/datafix/fixes/DataConverterCustomNameEntity -ajh net/minecraft/util/datafix/fixes/DataConverterGuardian -aji net/minecraft/util/datafix/fixes/DataConverterEquipment -ajj net/minecraft/util/datafix/fixes/DataConverterHealth -ajk net/minecraft/util/datafix/fixes/DataConverterSaddle -ajl net/minecraft/util/datafix/fixes/DataConverterHorse -ajm net/minecraft/util/datafix/fixes/DataConverterEntity -ajn net/minecraft/util/datafix/fixes/DataConverterItemFrame -ajo net/minecraft/util/datafix/fixes/DataConverterMinecart -ajp net/minecraft/util/datafix/fixes/DataConverterHanging -ajq net/minecraft/util/datafix/fixes/DataConverterPainting -ajr net/minecraft/util/datafix/fixes/DataConverterEntityProjectileOwner -ajs net/minecraft/util/datafix/fixes/DataConverterEntityPufferfish -ajt net/minecraft/util/datafix/fixes/DataConverterEntityRavagerRename -aju net/minecraft/util/datafix/fixes/DataConverterDropChances -ajv net/minecraft/util/datafix/fixes/DataConverterEntityName -ajw net/minecraft/util/datafix/fixes/DataConverterRiding -ajx net/minecraft/util/datafix/fixes/DataConverterShulker -ajy net/minecraft/util/datafix/fixes/DataConverterEntityShulkerRotation -ajz net/minecraft/util/datafix/fixes/DataConverterSkeleton -ak net/minecraft/advancements/CriterionProgress -aka net/minecraft/util/datafix/fixes/DataConverterUUID -akb net/minecraft/util/datafix/fixes/DataConverterEntityRename -akc net/minecraft/util/datafix/fixes/DataConverterEntityTippedArrow -akd net/minecraft/util/datafix/fixes/DataConverterEntityUUID -ake net/minecraft/util/datafix/fixes/DataConverterWolf -akf net/minecraft/util/datafix/fixes/DataConverterZombieType -akg net/minecraft/util/datafix/fixes/DataConverterZombie -akh net/minecraft/util/datafix/fixes/DataConverterEntityZombifiedPiglinRename -aki net/minecraft/util/datafix/fixes/DataConverterPOIRebuild -akj net/minecraft/util/datafix/fixes/DataConverterFurnaceRecipesUsed -akk net/minecraft/util/datafix/fixes/DataConverterGossip -akl net/minecraft/util/datafix/fixes/DataConverterHeightmapRenaming -akm net/minecraft/util/datafix/fixes/DataConverterIglooMetadataRemoval -akn net/minecraft/util/datafix/fixes/DataConverterBanner -ako net/minecraft/util/datafix/fixes/DataConverterCustomNameItem -akp net/minecraft/util/datafix/fixes/DataConverterMaterialId -akq net/minecraft/util/datafix/fixes/DataConverterItemLoreComponentize -akr net/minecraft/util/datafix/fixes/DataConverterPotionId -aks net/minecraft/util/datafix/fixes/DataConverterItemName -akt net/minecraft/util/datafix/fixes/DataConverterShulkerBoxItem -aku net/minecraft/util/datafix/fixes/DataConverterSpawnEgg -akv net/minecraft/util/datafix/fixes/DataConverterItemStackEnchantment -akw net/minecraft/util/datafix/fixes/DataConverterMap -akx net/minecraft/util/datafix/fixes/DataConverterFlattenSpawnEgg -aky net/minecraft/util/datafix/fixes/DataConverterFlatten -akz net/minecraft/util/datafix/fixes/DataConverterItemStackUUID -al net/minecraft/advancements/CriterionTrigger -ala net/minecraft/util/datafix/fixes/DataConverterPotionWater -alb net/minecraft/util/datafix/fixes/DataConverterBook -alc net/minecraft/util/datafix/fixes/DataConverterJigsawProperties -ald net/minecraft/util/datafix/fixes/DataConverterJigsawRotation -ale net/minecraft/util/datafix/fixes/DataConverterLeaves -alf net/minecraft/util/datafix/fixes/DataConverterLevelDataGeneratorOptions -alg net/minecraft/util/datafix/fixes/DataConverterWorldGenSettings -alh net/minecraft/util/datafix/fixes/DataConverterMiscUUID -ali net/minecraft/util/datafix/fixes/DataConverterMapId -alj net/minecraft/util/datafix/fixes/DataConverterMemoryExpiry -alk net/minecraft/util/datafix/fixes/DataConverterMissingDimension -all net/minecraft/util/datafix/fixes/DataConverterMobSpawner -alm net/minecraft/util/datafix/fixes/DataConverterNamedEntity -aln net/minecraft/util/datafix/fixes/DataConverterNewVillage -alo net/minecraft/util/datafix/fixes/DataConverterObjectiveDisplayName -alp net/minecraft/util/datafix/fixes/DataConverterObjectiveRenderType -alq net/minecraft/util/datafix/fixes/DataConverterOminousBannerBlockEntityRename -alr net/minecraft/util/datafix/fixes/DataConverterOminousBannerRename -als net/minecraft/util/datafix/fixes/DataConverterOptionsAddTextBackground -alt net/minecraft/util/datafix/fixes/DataConverterVBO -alu net/minecraft/util/datafix/fixes/DataConverterKeybind -alv net/minecraft/util/datafix/fixes/DataConverterKeybind2 -alw net/minecraft/util/datafix/fixes/DataConverterLang -alx net/minecraft/util/datafix/fixes/DataConverterSettingRename -aly net/minecraft/util/datafix/fixes/DataConverterPlayerUUID -alz net/minecraft/util/datafix/fixes/DataConverterPOIRename -am net/minecraft/advancements/CriterionInstance -ama net/minecraft/util/datafix/fixes/DataConverterRecipes -amb net/minecraft/util/datafix/fixes/DataConverterRecipeBase -amc net/minecraft/util/datafix/fixes/DataConverterRecipeRename -amd net/minecraft/util/datafix/fixes/DataConverterRedstoneConnections -ame net/minecraft/util/datafix/fixes/DataConverterTypes -amf net/minecraft/util/datafix/fixes/DataConverterRemoveGolemGossip -amg net/minecraft/util/datafix/fixes/DataConverterBiomeBase -amh net/minecraft/util/datafix/fixes/DataConverterCoralFan -ami net/minecraft/util/datafix/fixes/DataConverterCoral -amj net/minecraft/util/datafix/fixes/DataConverterPOI -amk net/minecraft/util/datafix/fixes/SavedDataFeaturePoolElementFix -aml net/minecraft/util/datafix/fixes/DataConverterSavedDataUUID -amm net/minecraft/util/datafix/fixes/DataConverterVillage -amn net/minecraft/util/datafix/fixes/DataConverterEntityNameAbstract -amo net/minecraft/util/datafix/fixes/DataConverterEntityRenameAbstract -amp net/minecraft/util/datafix/fixes/DataConverterStatistic -amq net/minecraft/util/datafix/fixes/StatsRenameFix -amr net/minecraft/util/datafix/fixes/DataConverterStriderGravity -ams net/minecraft/util/datafix/fixes/DataConverterStructureReference -amt net/minecraft/util/datafix/fixes/DataConverterTeamDisplayName -amu net/minecraft/util/datafix/fixes/DataConverterTrappedChest -amv net/minecraft/util/datafix/fixes/DataConverterVillagerProfession -amw net/minecraft/util/datafix/fixes/DataConverterVillagerFollowRange -amx net/minecraft/util/datafix/fixes/DataConverterVillagerLevelXp -amy net/minecraft/util/datafix/fixes/DataConverterVillagerTrade -amz net/minecraft/util/datafix/fixes/DataConverterWallProperty -an net/minecraft/advancements/AdvancementDisplay -ana net/minecraft/util/datafix/fixes/DataConverterWorldGenSettingsBuilding -anb net/minecraft/util/datafix/fixes/DataConverterShoulderEntity -anc net/minecraft/util/datafix/fixes/DataConverterZombieVillagerLevelXp -anf net/minecraft/util/datafix/schemas/DataConverterSchemaNamed -ang net/minecraft/util/datafix/schemas/DataConverterSchemaV100 -anh net/minecraft/util/datafix/schemas/DataConverterSchemaV102 -ani net/minecraft/util/datafix/schemas/DataConverterSchemaV1022 -anj net/minecraft/util/datafix/schemas/DataConverterSchemaV106 -ank net/minecraft/util/datafix/schemas/DataConverterSchemaV107 -anl net/minecraft/util/datafix/schemas/DataConverterSchemaV1125 -anm net/minecraft/util/datafix/schemas/DataConverterSchemaV135 -ann net/minecraft/util/datafix/schemas/DataConverterSchemaV143 -ano net/minecraft/util/datafix/schemas/DataConverterSchemaV1451 -anp net/minecraft/util/datafix/schemas/DataConverterSchemaV1451_1 -anq net/minecraft/util/datafix/schemas/DataConverterSchemaV1451_2 -anr net/minecraft/util/datafix/schemas/DataConverterSchemaV1451_3 -ans net/minecraft/util/datafix/schemas/DataConverterSchemaV1451_4 -ant net/minecraft/util/datafix/schemas/DataConverterSchemaV1451_5 -anu net/minecraft/util/datafix/schemas/DataConverterSchemaV1451_6 -anv net/minecraft/util/datafix/schemas/DataConverterSchemaV1451_7 -anw net/minecraft/util/datafix/schemas/DataConverterSchemaV1460 -anx net/minecraft/util/datafix/schemas/DataConverterSchemaV1466 -any net/minecraft/util/datafix/schemas/DataConverterSchemaV1470 -anz net/minecraft/util/datafix/schemas/DataConverterSchemaV1481 -ao net/minecraft/advancements/AdvancementFrameType -aoa net/minecraft/util/datafix/schemas/DataConverterSchemaV1483 -aob net/minecraft/util/datafix/schemas/DataConverterSchemaV1486 -aoc net/minecraft/util/datafix/schemas/DataConverterSchemaV1510 -aod net/minecraft/util/datafix/schemas/DataConverterSchemaV1800 -aoe net/minecraft/util/datafix/schemas/DataConverterSchemaV1801 -aof net/minecraft/util/datafix/schemas/DataConverterSchemaV1904 -aog net/minecraft/util/datafix/schemas/DataConverterSchemaV1906 -aoh net/minecraft/util/datafix/schemas/DataConverterSchemaV1909 -aoi net/minecraft/util/datafix/schemas/DataConverterSchemaV1920 -aoj net/minecraft/util/datafix/schemas/DataConverterSchemaV1928 -aok net/minecraft/util/datafix/schemas/DataConverterSchemaV1929 -aol net/minecraft/util/datafix/schemas/DataConverterSchemaV1931 -aom net/minecraft/util/datafix/schemas/DataConverterSchemaV2100 -aon net/minecraft/util/datafix/schemas/DataConverterSchemaV2501 -aoo net/minecraft/util/datafix/schemas/DataConverterSchemaV2502 -aop net/minecraft/util/datafix/schemas/DataConverterSchemaV2505 -aoq net/minecraft/util/datafix/schemas/DataConverterSchemaV2509 -aor net/minecraft/util/datafix/schemas/DataConverterSchemaV2519 -aos net/minecraft/util/datafix/schemas/DataConverterSchemaV2522 -aot net/minecraft/util/datafix/schemas/DataConverterSchemaV2551 -aou net/minecraft/util/datafix/schemas/DataConverterSchemaV2568 -aov net/minecraft/util/datafix/schemas/V2571 -aow net/minecraft/util/datafix/schemas/V2684 -aox net/minecraft/util/datafix/schemas/V2686 -aoy net/minecraft/util/datafix/schemas/V2688 -aoz net/minecraft/util/datafix/schemas/V2704 -ap net/minecraft/advancements/AdvancementRequirements -apa net/minecraft/util/datafix/schemas/V2707 -apb net/minecraft/util/datafix/schemas/DataConverterSchemaV501 -apc net/minecraft/util/datafix/schemas/DataConverterSchemaV700 -apd net/minecraft/util/datafix/schemas/DataConverterSchemaV701 -ape net/minecraft/util/datafix/schemas/DataConverterSchemaV702 -apf net/minecraft/util/datafix/schemas/DataConverterSchemaV703 -apg net/minecraft/util/datafix/schemas/DataConverterSchemaV704 -aph net/minecraft/util/datafix/schemas/DataConverterSchemaV705 -api net/minecraft/util/datafix/schemas/DataConverterSchemaV808 -apj net/minecraft/util/datafix/schemas/DataConverterSchemaV99 -apl net/minecraft/util/monitoring/jmx/MinecraftServerBeans -apn net/minecraft/util/profiling/MethodProfiler -apo net/minecraft/util/profiling/GameProfilerSwitcher -app net/minecraft/util/profiling/MethodProfilerResultsEmpty -apq net/minecraft/util/profiling/MethodProfilerResultsFilled -apr net/minecraft/util/profiling/GameProfilerDisabled -aps net/minecraft/util/profiling/GameProfilerFillerActive -apt net/minecraft/util/profiling/MethodProfilerResults -apu net/minecraft/util/profiling/GameProfilerFiller -apv net/minecraft/util/profiling/MethodProfilerResult -apw net/minecraft/util/profiling/MethodProfilerResultsField -apx net/minecraft/util/profiling/GameProfilerTick -apy net/minecraft/util/profiling/metrics/MetricCategory -apz net/minecraft/util/profiling/metrics/MetricSampler -aq net/minecraft/advancements/AdvancementTree -aqa net/minecraft/util/profiling/metrics/MetricsRegistry -aqb net/minecraft/util/profiling/metrics/MetricsSamplerProvider -aqc net/minecraft/util/profiling/metrics/ProfilerMeasured -aqe net/minecraft/util/profiling/metrics/profiling/ActiveMetricsRecorder -aqf net/minecraft/util/profiling/metrics/profiling/InactiveMetricsRecorder -aqg net/minecraft/util/profiling/metrics/profiling/MetricsRecorder -aqh net/minecraft/util/profiling/metrics/profiling/ProfilerSamplerAdapter -aqi net/minecraft/util/profiling/metrics/profiling/ServerMetricsSamplersProvider -aqk net/minecraft/util/profiling/metrics/storage/MetricsPersister -aql net/minecraft/util/profiling/metrics/storage/RecordedDeviation -aqo net/minecraft/util/random/SimpleWeightedRandomList -aqp net/minecraft/util/random/Weight -aqq net/minecraft/util/random/WeightedEntry -aqr net/minecraft/util/random/WeightedRandom2 -aqs net/minecraft/util/random/WeightedRandomList -aqu net/minecraft/util/thread/IAsyncTaskHandler -aqw net/minecraft/util/thread/Mailbox -aqx net/minecraft/util/thread/ThreadedMailbox -aqy net/minecraft/util/thread/IAsyncTaskHandlerReentrant -aqz net/minecraft/util/thread/PairedQueue -ar net/minecraft/advancements/critereon/CriterionInstanceAbstract -arb net/minecraft/util/valueproviders/BiasedToBottomInt -arc net/minecraft/util/valueproviders/ClampedInt -ard net/minecraft/util/valueproviders/ClampedNormalFloat -are net/minecraft/util/valueproviders/ConstantFloat -arf net/minecraft/util/valueproviders/ConstantInt -arg net/minecraft/util/valueproviders/FloatProvider -arh net/minecraft/util/valueproviders/FloatProviderType -ari net/minecraft/util/valueproviders/IntProvider -arj net/minecraft/util/valueproviders/IntProviderType -ark net/minecraft/util/valueproviders/TrapezoidFloat -arl net/minecraft/util/valueproviders/UniformFloat -arm net/minecraft/util/valueproviders/UniformInt -aro net/minecraft/util/worldupdate/WorldUpgrader -arq net/minecraft/world/BossBattle -arq$a net/minecraft/world/BossBattle$BarColor -arq$b net/minecraft/world/BossBattle$BarStyle -arr net/minecraft/world/Clearable -ars net/minecraft/world/InventoryLargeChest -art net/minecraft/world/IInventory -aru net/minecraft/world/ContainerUtil -arv net/minecraft/world/IInventoryListener -arw net/minecraft/world/InventoryUtils -arx net/minecraft/world/EnumDifficulty -ary net/minecraft/world/DifficultyDamageScaler -arz net/minecraft/world/EnumHand -as net/minecraft/advancements/critereon/CriterionTriggerBeeNestDestroyed -asa net/minecraft/world/EnumInteractionResult -asb net/minecraft/world/InteractionResultWrapper -asc net/minecraft/world/ChestLock -asd net/minecraft/world/ITileInventory -ase net/minecraft/world/INamableTileEntity -asf net/minecraft/world/InventorySubcontainer -asg net/minecraft/world/TileInventory -ash net/minecraft/world/MojangStatisticsGenerator -asi net/minecraft/world/IMojangStatistics -asj net/minecraft/world/IWorldInventory -ask net/minecraft/world/IInventoryHolder -asl net/minecraft/world/damagesource/DamageSourceNetherBed -asm net/minecraft/world/damagesource/CombatEntry -asn net/minecraft/world/damagesource/CombatMath -aso net/minecraft/world/damagesource/CombatTracker -asp net/minecraft/world/damagesource/DamageSource -asq net/minecraft/world/damagesource/EntityDamageSource -asr net/minecraft/world/damagesource/EntityDamageSourceIndirect -ast net/minecraft/world/effect/MobEffectAbsorption -asu net/minecraft/world/effect/MobEffectAttackDamage -asv net/minecraft/world/effect/MobEffectHealthBoost -asw net/minecraft/world/effect/InstantMobEffect -asx net/minecraft/world/effect/MobEffectList -asy net/minecraft/world/effect/MobEffectInfo -asz net/minecraft/world/effect/MobEffect -at net/minecraft/advancements/critereon/CriterionConditionBlock -ata net/minecraft/world/effect/MobEffectUtil -atb net/minecraft/world/effect/MobEffects -atd net/minecraft/world/entity/EntityAgeable -ate net/minecraft/world/entity/EntityAreaEffectCloud -atf net/minecraft/world/entity/Entity -atf$a net/minecraft/world/entity/Entity$MoveFunction -atf$b net/minecraft/world/entity/Entity$MovementEmission -atf$c net/minecraft/world/entity/Entity$RemovalReason -atg net/minecraft/world/entity/EntitySize -ati net/minecraft/world/entity/IEntitySelector -ati$a net/minecraft/world/entity/IEntitySelector$EntitySelectorEquipable -atj net/minecraft/world/entity/EntityTypes -atj$a net/minecraft/world/entity/EntityTypes$Builder -atk net/minecraft/world/entity/EnumItemSlot -atk$a net/minecraft/world/entity/EnumItemSlot$Function -atl net/minecraft/world/entity/EntityExperienceOrb -atm net/minecraft/world/entity/EntityFlying -atn net/minecraft/world/entity/GlowSquid -ato net/minecraft/world/entity/EnumMainHand -atp net/minecraft/world/entity/SaddleStorage -atq net/minecraft/world/entity/ISteerable -atr net/minecraft/world/entity/LerpingModel -ats net/minecraft/world/entity/EntityLightning -att net/minecraft/world/entity/EntityLiving -atu net/minecraft/world/entity/Marker -atv net/minecraft/world/entity/EntityInsentient -atw net/minecraft/world/entity/EnumCreatureType -atx net/minecraft/world/entity/EnumMobSpawn -aty net/minecraft/world/entity/EnumMonsterType -atz net/minecraft/world/entity/EnumMoveType -au net/minecraft/advancements/critereon/CriterionTriggerBredAnimals -aua net/minecraft/world/entity/IEntityAngerable -aub net/minecraft/world/entity/OwnableEntity -auc net/minecraft/world/entity/EntityCreature -aud net/minecraft/world/entity/PlayerRideable -aue net/minecraft/world/entity/IJumpable -auf net/minecraft/world/entity/EntityPose -aug net/minecraft/world/entity/PowerableMob -auh net/minecraft/world/entity/ReputationHandler -aui net/minecraft/world/entity/ISaddleable -auj net/minecraft/world/entity/IShearable -auk net/minecraft/world/entity/SlotAccess -aul net/minecraft/world/entity/GroupDataEntity -aum net/minecraft/world/entity/EntityPositionTypes -aum$c net/minecraft/world/entity/EntityPositionTypes$Surface -aun net/minecraft/world/entity/EntityTameableAnimal -auo net/minecraft/world/entity/ai/BehaviorController -aup net/minecraft/world/entity/ai/attributes/AttributeBase -auq net/minecraft/world/entity/ai/attributes/AttributeModifiable -aur net/minecraft/world/entity/ai/attributes/AttributeMapBase -aus net/minecraft/world/entity/ai/attributes/AttributeModifier -aus$a net/minecraft/world/entity/ai/attributes/AttributeModifier$Operation -aut net/minecraft/world/entity/ai/attributes/AttributeProvider -aut$a net/minecraft/world/entity/ai/attributes/AttributeProvider$Builder -auu net/minecraft/world/entity/ai/attributes/GenericAttributes -auv net/minecraft/world/entity/ai/attributes/AttributeDefaults -auw net/minecraft/world/entity/ai/attributes/AttributeRanged -auz net/minecraft/world/entity/ai/behavior/BehaviorFindPosition -av net/minecraft/advancements/critereon/CriterionTriggerBrewedPotion -ava net/minecraft/world/entity/ai/behavior/BehaviorMakeLoveAnimal -avb net/minecraft/world/entity/ai/behavior/AnimalPanic -avc net/minecraft/world/entity/ai/behavior/BehaviorCareer -avd net/minecraft/world/entity/ai/behavior/BehaviorFollowAdult -ave net/minecraft/world/entity/ai/behavior/BehaviorRetreat -avf net/minecraft/world/entity/ai/behavior/BehaviorPacify -avg net/minecraft/world/entity/ai/behavior/Behavior -avg$a net/minecraft/world/entity/ai/behavior/Behavior$Status -avh net/minecraft/world/entity/ai/behavior/BehaviorUtil -avi net/minecraft/world/entity/ai/behavior/BehaviorTarget -avj net/minecraft/world/entity/ai/behavior/BehaviorCelebrate -avk net/minecraft/world/entity/ai/behavior/BehaviorExpirableMemory -avl net/minecraft/world/entity/ai/behavior/CountDownCooldownTicks -avm net/minecraft/world/entity/ai/behavior/BehaviorCrossbowAttack -avm$a net/minecraft/world/entity/ai/behavior/BehaviorCrossbowAttack$BowState -avn net/minecraft/world/entity/ai/behavior/BehaviorStopRiding -avo net/minecraft/world/entity/ai/behavior/BehaviorNop -avp net/minecraft/world/entity/ai/behavior/BehaviorPositionEntity -avq net/minecraft/world/entity/ai/behavior/BehaviorRemoveMemory -avr net/minecraft/world/entity/ai/behavior/FollowTemptation -avs net/minecraft/world/entity/ai/behavior/BehaviorGate -avs$a net/minecraft/world/entity/ai/behavior/BehaviorGate$Order -avs$b net/minecraft/world/entity/ai/behavior/BehaviorGate$Execution -avt net/minecraft/world/entity/ai/behavior/BehaviorVillageHeroGift -avu net/minecraft/world/entity/ai/behavior/BehaviorOutsideCelebrate -avv net/minecraft/world/entity/ai/behavior/BehaviorCelebrateLocation -avw net/minecraft/world/entity/ai/behavior/BehaviorNearestVillage -avx net/minecraft/world/entity/ai/behavior/BehaviorPotentialJobSite -avy net/minecraft/world/entity/ai/behavior/BehaviorFindAdmirableItem -avz net/minecraft/world/entity/ai/behavior/BehaviorFarm -aw net/minecraft/advancements/critereon/CriterionTriggerChangedDimension -awa net/minecraft/world/entity/ai/behavior/BehaviorStrollInside -awb net/minecraft/world/entity/ai/behavior/BehaviorInteract -awc net/minecraft/world/entity/ai/behavior/BehaviorInteractDoor -awd net/minecraft/world/entity/ai/behavior/BehaviorBedJump -awe net/minecraft/world/entity/ai/behavior/BehaviorHome -awf net/minecraft/world/entity/ai/behavior/BehaviorHomeRaid -awg net/minecraft/world/entity/ai/behavior/LongJumpMidJump -awh net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos -awi net/minecraft/world/entity/ai/behavior/BehaviorInteractPlayer -awj net/minecraft/world/entity/ai/behavior/BehaviorLook -awk net/minecraft/world/entity/ai/behavior/BehaviorAttack -awl net/minecraft/world/entity/ai/behavior/BehaviorStartRiding -awm net/minecraft/world/entity/ai/behavior/BehaviorOutside -awn net/minecraft/world/entity/ai/behavior/BehavorMove -awo net/minecraft/world/entity/ai/behavior/BehaviorPlay -awp net/minecraft/world/entity/ai/behavior/BehaviorBetterJob -awq net/minecraft/world/entity/ai/behavior/BehaviorPosition -awr net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget -aws net/minecraft/world/entity/ai/behavior/RamTarget -awt net/minecraft/world/entity/ai/behavior/BehaviorStrollRandomUnconstrained -awu net/minecraft/world/entity/ai/behavior/RandomSwim -awv net/minecraft/world/entity/ai/behavior/BehaviorBellAlert -aww net/minecraft/world/entity/ai/behavior/BehaviorProfession -awx net/minecraft/world/entity/ai/behavior/BehaviorRaidReset -awy net/minecraft/world/entity/ai/behavior/BehaviorBellRing -awz net/minecraft/world/entity/ai/behavior/BehaviorRunIf -ax net/minecraft/advancements/critereon/CriterionTriggerChanneledLightning -axa net/minecraft/world/entity/ai/behavior/BehaviorGateSingle -axb net/minecraft/world/entity/ai/behavior/BehaviorRunSometimes -axc net/minecraft/world/entity/ai/behavior/BehaviorWalkHome -axd net/minecraft/world/entity/ai/behavior/BehaviorLookTarget -axe net/minecraft/world/entity/ai/behavior/BehaviorHide -axf net/minecraft/world/entity/ai/behavior/BehaviorLookInteract -axg net/minecraft/world/entity/ai/behavior/BehaviorRaid -axh net/minecraft/world/entity/ai/behavior/BehaviorWalkAway -axi net/minecraft/world/entity/ai/behavior/BehaviorWalkAwayOutOfRange -axj net/minecraft/world/entity/ai/behavior/BehaviorWalkAwayBlock -axk net/minecraft/world/entity/ai/behavior/BehaviorLookWalk -axl net/minecraft/world/entity/ai/behavior/BehaviorTradePlayer -axm net/minecraft/world/entity/ai/behavior/ShufflingList -axn net/minecraft/world/entity/ai/behavior/BehaviorSleep -axo net/minecraft/world/entity/ai/behavior/BehaviorBell -axp net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetSet -axq net/minecraft/world/entity/ai/behavior/BehaviorCelebrateDeath -axr net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget -axs net/minecraft/world/entity/ai/behavior/BehaviorForgetAnger -axt net/minecraft/world/entity/ai/behavior/BehaviorStrollPosition -axu net/minecraft/world/entity/ai/behavior/BehaviorStrollPlace -axv net/minecraft/world/entity/ai/behavior/BehaviorStrollPlaceList -axw net/minecraft/world/entity/ai/behavior/BehaviorSwim -axx net/minecraft/world/entity/ai/behavior/BehaviorTradeVillager -axy net/minecraft/world/entity/ai/behavior/TryFindWater -axz net/minecraft/world/entity/ai/behavior/BehaviorSchedule -ay net/minecraft/advancements/critereon/CriterionTriggerConstructBeacon -aya net/minecraft/world/entity/ai/behavior/BehaviorBonemeal -ayb net/minecraft/world/entity/ai/behavior/BehaviorPositionValidate -ayc net/minecraft/world/entity/ai/behavior/BehaviorVictory -ayd net/minecraft/world/entity/ai/behavior/BehaviorStrollRandom -aye net/minecraft/world/entity/ai/behavior/BehaviorCooldown -ayf net/minecraft/world/entity/ai/behavior/Behaviors -ayg net/minecraft/world/entity/ai/behavior/BehaviorMakeLove -ayh net/minecraft/world/entity/ai/behavior/BehaviorPanic -ayi net/minecraft/world/entity/ai/behavior/BehaviorWake -ayj net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter -ayk net/minecraft/world/entity/ai/behavior/BehaviorWork -ayl net/minecraft/world/entity/ai/behavior/BehaviorLeaveJob -ayn net/minecraft/world/entity/ai/control/EntityAIBodyControl -ayo net/minecraft/world/entity/ai/control/Control -ayp net/minecraft/world/entity/ai/control/ControllerMoveFlying -ayq net/minecraft/world/entity/ai/control/ControllerJump -ayr net/minecraft/world/entity/ai/control/ControllerLook -ays net/minecraft/world/entity/ai/control/ControllerMove -ays$a net/minecraft/world/entity/ai/control/ControllerMove$Operation -ayt net/minecraft/world/entity/ai/control/SmoothSwimmingLookControl -ayu net/minecraft/world/entity/ai/control/SmoothSwimmingMoveControl -ayw net/minecraft/world/entity/ai/goal/PathfinderGoalAvoidTarget -ayx net/minecraft/world/entity/ai/goal/PathfinderGoalBeg -ayy net/minecraft/world/entity/ai/goal/PathfinderGoalBoat -ayz net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor -az net/minecraft/advancements/critereon/CriterionTriggerConsumeItem -aza net/minecraft/world/entity/ai/goal/PathfinderGoalBreath -azb net/minecraft/world/entity/ai/goal/PathfinderGoalBreed -azc net/minecraft/world/entity/ai/goal/PathfinderGoalCatSitOnBed -azd net/minecraft/world/entity/ai/goal/PathfinderGoalJumpOnBlock -aze net/minecraft/world/entity/ai/goal/PathfinderGoalWaterJump -azf net/minecraft/world/entity/ai/goal/PathfinderGoalDoorInteract -azg net/minecraft/world/entity/ai/goal/PathfinderGoalEatTile -azh net/minecraft/world/entity/ai/goal/PathfinderGoalFleeSun -azi net/minecraft/world/entity/ai/goal/PathfinderGoalFloat -azj net/minecraft/world/entity/ai/goal/PathfinderGoalFollowBoat -azk net/minecraft/world/entity/ai/goal/PathfinderGoalFishSchool -azl net/minecraft/world/entity/ai/goal/PathfinderGoalFollowEntity -azm net/minecraft/world/entity/ai/goal/PathfinderGoalFollowOwner -azn net/minecraft/world/entity/ai/goal/PathfinderGoalFollowParent -azo net/minecraft/world/entity/ai/goal/PathfinderGoal -azo$a net/minecraft/world/entity/ai/goal/PathfinderGoal$Type -azp net/minecraft/world/entity/ai/goal/PathfinderGoalSelector -azq net/minecraft/world/entity/ai/goal/PathfinderGoalStrollVillageGolem -azr net/minecraft/world/entity/ai/goal/PathfinderGoalInteract -azs net/minecraft/world/entity/ai/goal/PathfinderGoalWaterJumpAbstract -azt net/minecraft/world/entity/ai/goal/PathfinderGoalPerch -azu net/minecraft/world/entity/ai/goal/PathfinderGoalLeapAtTarget -azv net/minecraft/world/entity/ai/goal/PathfinderGoalLlamaFollow -azw net/minecraft/world/entity/ai/goal/PathfinderGoalLookAtPlayer -azx net/minecraft/world/entity/ai/goal/PathfinderGoalLookAtTradingPlayer -azy net/minecraft/world/entity/ai/goal/PathfinderGoalMeleeAttack -azz net/minecraft/world/entity/ai/goal/PathfinderGoalStrollVillage -ba net/minecraft/advancements/critereon/CriterionTriggerCuredZombieVillager -baa net/minecraft/world/entity/ai/goal/PathfinderGoalMoveThroughVillage -bab net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget -bac net/minecraft/world/entity/ai/goal/PathfinderGoalMoveTowardsRestriction -bad net/minecraft/world/entity/ai/goal/PathfinderGoalMoveTowardsTarget -bae net/minecraft/world/entity/ai/goal/PathfinderGoalOcelotAttack -baf net/minecraft/world/entity/ai/goal/PathfinderGoalOfferFlower -bag net/minecraft/world/entity/ai/goal/PathfinderGoalDoorOpen -bah net/minecraft/world/entity/ai/goal/PathfinderGoalPanic -bai net/minecraft/world/entity/ai/goal/PathfinderGoalRaid -baj net/minecraft/world/entity/ai/goal/PathfinderGoalRandomLookaround -bak net/minecraft/world/entity/ai/goal/PathfinderGoalRandomStroll -bal net/minecraft/world/entity/ai/goal/PathfinderGoalRandomSwim -bam net/minecraft/world/entity/ai/goal/PathfinderGoalArrowAttack -ban net/minecraft/world/entity/ai/goal/PathfinderGoalBowShoot -bao net/minecraft/world/entity/ai/goal/PathfinderGoalCrossbowAttack -bao$a net/minecraft/world/entity/ai/goal/PathfinderGoalCrossbowAttack$State -bap net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock -baq net/minecraft/world/entity/ai/goal/PathfinderGoalRestrictSun -bar net/minecraft/world/entity/ai/goal/PathfinderGoalTame -bas net/minecraft/world/entity/ai/goal/PathfinderGoalSit -bat net/minecraft/world/entity/ai/goal/PathfinderGoalNearestVillage -bau net/minecraft/world/entity/ai/goal/PathfinderGoalSwell -bav net/minecraft/world/entity/ai/goal/PathfinderGoalTempt -baw net/minecraft/world/entity/ai/goal/PathfinderGoalTradeWithPlayer -bax net/minecraft/world/entity/ai/goal/PathfinderGoalWater -bay net/minecraft/world/entity/ai/goal/PathfinderGoalUseItem -baz net/minecraft/world/entity/ai/goal/PathfinderGoalRandomFly -bb net/minecraft/advancements/critereon/CriterionConditionDamage -bba net/minecraft/world/entity/ai/goal/PathfinderGoalRandomStrollLand -bbb net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped -bbc net/minecraft/world/entity/ai/goal/PathfinderGoalZombieAttack -bbe net/minecraft/world/entity/ai/goal/target/PathfinderGoalDefendVillage -bbf net/minecraft/world/entity/ai/goal/target/PathfinderGoalHurtByTarget -bbg net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget -bbh net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTargetWitch -bbi net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestHealableRaider -bbj net/minecraft/world/entity/ai/goal/target/PathfinderGoalRandomTargetNonTamed -bbk net/minecraft/world/entity/ai/goal/target/PathfinderGoalOwnerHurtByTarget -bbl net/minecraft/world/entity/ai/goal/target/PathfinderGoalOwnerHurtTarget -bbm net/minecraft/world/entity/ai/goal/target/PathfinderGoalUniversalAngerReset -bbn net/minecraft/world/entity/ai/goal/target/PathfinderGoalTarget -bbp net/minecraft/world/entity/ai/gossip/Reputation -bbq net/minecraft/world/entity/ai/gossip/ReputationType -bbs net/minecraft/world/entity/ai/memory/ExpirableMemory -bbt net/minecraft/world/entity/ai/memory/MemoryModuleType -bbu net/minecraft/world/entity/ai/memory/MemoryStatus -bbv net/minecraft/world/entity/ai/memory/MemoryTarget -bbx net/minecraft/world/entity/ai/navigation/NavigationFlying -bby net/minecraft/world/entity/ai/navigation/Navigation -bbz net/minecraft/world/entity/ai/navigation/NavigationAbstract -bc net/minecraft/advancements/critereon/CriterionConditionDamageSource -bca net/minecraft/world/entity/ai/navigation/NavigationSpider -bcb net/minecraft/world/entity/ai/navigation/NavigationGuardian -bce net/minecraft/world/entity/ai/sensing/SensorAdult -bcf net/minecraft/world/entity/ai/sensing/AxolotlAttackablesSensor -bcg net/minecraft/world/entity/ai/sensing/SensorDummy -bch net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen -bci net/minecraft/world/entity/ai/sensing/SensorHoglinSpecific -bcj net/minecraft/world/entity/ai/sensing/SensorHurtBy -bck net/minecraft/world/entity/ai/sensing/SensorNearestBed -bcl net/minecraft/world/entity/ai/sensing/SensorNearestItems -bcm net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities -bcn net/minecraft/world/entity/ai/sensing/NearestVisibleLivingEntitySensor -bco net/minecraft/world/entity/ai/sensing/SensorPiglinBruteSpecific -bcp net/minecraft/world/entity/ai/sensing/SensorPiglinSpecific -bcq net/minecraft/world/entity/ai/sensing/SensorNearestPlayers -bcr net/minecraft/world/entity/ai/sensing/SensorSecondaryPlaces -bcs net/minecraft/world/entity/ai/sensing/EntitySenses -bct net/minecraft/world/entity/ai/sensing/Sensor -bcu net/minecraft/world/entity/ai/sensing/SensorType -bcv net/minecraft/world/entity/ai/sensing/TemptingSensor -bcw net/minecraft/world/entity/ai/sensing/SensorVillagerBabies -bcx net/minecraft/world/entity/ai/sensing/SensorVillagerHostiles -bcz net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition -bd net/minecraft/advancements/critereon/LootDeserializationContext -bdb net/minecraft/world/entity/ai/util/AirAndWaterRandomPos -bdc net/minecraft/world/entity/ai/util/AirRandomPos -bdd net/minecraft/world/entity/ai/util/DefaultRandomPos -bde net/minecraft/world/entity/ai/util/PathfinderGoalUtil -bdf net/minecraft/world/entity/ai/util/HoverRandomPos -bdg net/minecraft/world/entity/ai/util/LandRandomPos -bdh net/minecraft/world/entity/ai/util/RandomPositionGenerator -bdj net/minecraft/world/entity/ai/village/ReputationEvent -bdk net/minecraft/world/entity/ai/village/VillageSiege -bdk$a net/minecraft/world/entity/ai/village/VillageSiege$State -bdm net/minecraft/world/entity/ai/village/poi/VillagePlace -bdm$b net/minecraft/world/entity/ai/village/poi/VillagePlace$Occupancy -bdn net/minecraft/world/entity/ai/village/poi/VillagePlaceRecord -bdo net/minecraft/world/entity/ai/village/poi/VillagePlaceSection -bdp net/minecraft/world/entity/ai/village/poi/VillagePlaceType -bdr net/minecraft/world/entity/ambient/EntityAmbient -bds net/minecraft/world/entity/ambient/EntityBat -bdu net/minecraft/world/entity/animal/EntityFish -bdv net/minecraft/world/entity/animal/EntityGolem -bdw net/minecraft/world/entity/animal/EntityFishSchool -bdx net/minecraft/world/entity/animal/EntityAnimal -bdy net/minecraft/world/entity/animal/EntityBee -bdz net/minecraft/world/entity/animal/Bucketable -be net/minecraft/advancements/critereon/CriterionConditionDistance -bea net/minecraft/world/entity/animal/EntityCat -bea$c net/minecraft/world/entity/animal/EntityCat$PathfinderGoalTemptChance -beb net/minecraft/world/entity/animal/EntityChicken -bec net/minecraft/world/entity/animal/EntityCod -bed net/minecraft/world/entity/animal/EntityCow -bee net/minecraft/world/entity/animal/EntityDolphin -bef net/minecraft/world/entity/animal/EntityBird -beg net/minecraft/world/entity/animal/EntityFox -beg$v net/minecraft/world/entity/animal/EntityFox$Type -beh net/minecraft/world/entity/animal/EntityIronGolem -beh$a net/minecraft/world/entity/animal/EntityIronGolem$CrackLevel -bei net/minecraft/world/entity/animal/EntityMushroomCow -bei$a net/minecraft/world/entity/animal/EntityMushroomCow$Type -bej net/minecraft/world/entity/animal/EntityOcelot -bek net/minecraft/world/entity/animal/EntityPanda -bek$a net/minecraft/world/entity/animal/EntityPanda$Gene -bel net/minecraft/world/entity/animal/EntityParrot -bem net/minecraft/world/entity/animal/EntityPig -ben net/minecraft/world/entity/animal/EntityPolarBear -beo net/minecraft/world/entity/animal/EntityPufferFish -bep net/minecraft/world/entity/animal/EntityRabbit -bep$a net/minecraft/world/entity/animal/EntityRabbit$PathfinderGoalKillerRabbitMeleeAttack -bep$b net/minecraft/world/entity/animal/EntityRabbit$PathfinderGoalRabbitAvoidTarget -bep$c net/minecraft/world/entity/animal/EntityRabbit$GroupDataRabbit -bep$d net/minecraft/world/entity/animal/EntityRabbit$ControllerJumpRabbit -bep$e net/minecraft/world/entity/animal/EntityRabbit$ControllerMoveRabbit -bep$f net/minecraft/world/entity/animal/EntityRabbit$PathfinderGoalRabbitPanic -bep$g net/minecraft/world/entity/animal/EntityRabbit$PathfinderGoalEatCarrots -beq net/minecraft/world/entity/animal/EntitySalmon -ber net/minecraft/world/entity/animal/EntitySheep -bes net/minecraft/world/entity/animal/EntityPerchable -bet net/minecraft/world/entity/animal/EntitySnowman -beu net/minecraft/world/entity/animal/EntitySquid -beu$b net/minecraft/world/entity/animal/EntitySquid$PathfinderGoalSquid -bev net/minecraft/world/entity/animal/EntityTropicalFish -bev$a net/minecraft/world/entity/animal/EntityTropicalFish$Variant -bew net/minecraft/world/entity/animal/EntityTurtle -bex net/minecraft/world/entity/animal/EntityWaterAnimal -bey net/minecraft/world/entity/animal/EntityWolf -bez net/minecraft/world/entity/animal/axolotl/Axolotl -bez$e net/minecraft/world/entity/animal/axolotl/Axolotl$Variant -bf net/minecraft/advancements/critereon/CriterionTriggerEffectsChanged -bfa net/minecraft/world/entity/animal/axolotl/AxolotlAi -bfb net/minecraft/world/entity/animal/axolotl/PlayDead -bfc net/minecraft/world/entity/animal/axolotl/ValidatePlayDead -bfe net/minecraft/world/entity/animal/goat/Goat -bff net/minecraft/world/entity/animal/goat/GoatAi -bfh net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract -bfi net/minecraft/world/entity/animal/horse/EntityHorseAbstract -bfj net/minecraft/world/entity/animal/horse/EntityHorseDonkey -bfk net/minecraft/world/entity/animal/horse/EntityHorse -bfl net/minecraft/world/entity/animal/horse/EntityLlama -bfm net/minecraft/world/entity/animal/horse/HorseStyle -bfn net/minecraft/world/entity/animal/horse/EntityHorseMule -bfo net/minecraft/world/entity/animal/horse/EntityHorseSkeleton -bfp net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap -bfq net/minecraft/world/entity/animal/horse/EntityLlamaTrader -bfr net/minecraft/world/entity/animal/horse/HorseColor -bfs net/minecraft/world/entity/animal/horse/EntityHorseZombie -bfv net/minecraft/world/entity/boss/EntityComplexPart -bfw net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal -bfx net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon -bfz net/minecraft/world/entity/boss/enderdragon/phases/AbstractDragonController -bg net/minecraft/advancements/critereon/CriterionTriggerEnchantedItem -bga net/minecraft/world/entity/boss/enderdragon/phases/AbstractDragonControllerLanded -bgb net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerCharge -bgc net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerDying -bgd net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerHold -bge net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerHover -bgf net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandingFly -bgg net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLanding -bgh net/minecraft/world/entity/boss/enderdragon/phases/IDragonController -bgi net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedAttack -bgj net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame -bgk net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedSearch -bgl net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe -bgm net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerFly -bgn net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerPhase -bgo net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerManager -bgr net/minecraft/world/entity/boss/wither/EntityWither -bgt net/minecraft/world/entity/decoration/EntityArmorStand -bgu net/minecraft/world/entity/decoration/GlowItemFrame -bgv net/minecraft/world/entity/decoration/EntityHanging -bgw net/minecraft/world/entity/decoration/EntityItemFrame -bgx net/minecraft/world/entity/decoration/EntityLeash -bgy net/minecraft/world/entity/decoration/Paintings -bgz net/minecraft/world/entity/decoration/EntityPainting -bh net/minecraft/advancements/critereon/CriterionConditionEnchantments -bhb net/minecraft/world/entity/item/EntityFallingBlock -bhc net/minecraft/world/entity/item/EntityItem -bhd net/minecraft/world/entity/item/EntityTNTPrimed -bhf net/minecraft/world/entity/monster/EntityIllagerAbstract -bhg net/minecraft/world/entity/monster/EntitySkeletonAbstract -bhh net/minecraft/world/entity/monster/EntityBlaze -bhh$a net/minecraft/world/entity/monster/EntityBlaze$PathfinderGoalBlazeFireball -bhi net/minecraft/world/entity/monster/EntityCaveSpider -bhj net/minecraft/world/entity/monster/EntityCreeper -bhk net/minecraft/world/entity/monster/ICrossbow -bhl net/minecraft/world/entity/monster/EntityDrowned -bhm net/minecraft/world/entity/monster/EntityGuardianElder -bhn net/minecraft/world/entity/monster/EntityEnderman -bhn$b net/minecraft/world/entity/monster/EntityEnderman$PathfinderGoalEndermanPlaceBlock -bhn$c net/minecraft/world/entity/monster/EntityEnderman$PathfinderGoalPlayerWhoLookedAtTarget -bhn$d net/minecraft/world/entity/monster/EntityEnderman$PathfinderGoalEndermanPickupBlock -bho net/minecraft/world/entity/monster/EntityEndermite -bhp net/minecraft/world/entity/monster/IMonster -bhq net/minecraft/world/entity/monster/EntityEvoker -bhr net/minecraft/world/entity/monster/EntityGhast -bhr$a net/minecraft/world/entity/monster/EntityGhast$PathfinderGoalGhastMoveTowardsTarget -bhr$b net/minecraft/world/entity/monster/EntityGhast$ControllerGhast -bhr$c net/minecraft/world/entity/monster/EntityGhast$PathfinderGoalGhastAttackTarget -bhr$d net/minecraft/world/entity/monster/EntityGhast$PathfinderGoalGhastIdleMove -bhs net/minecraft/world/entity/monster/EntityGiantZombie -bht net/minecraft/world/entity/monster/EntityGuardian -bht$a net/minecraft/world/entity/monster/EntityGuardian$PathfinderGoalGuardianAttack -bht$b net/minecraft/world/entity/monster/EntityGuardian$EntitySelectorGuardianTargetHumanSquid -bht$c net/minecraft/world/entity/monster/EntityGuardian$ControllerMoveGuardian -bhu net/minecraft/world/entity/monster/EntityZombieHusk -bhv net/minecraft/world/entity/monster/EntityIllagerIllusioner -bhw net/minecraft/world/entity/monster/EntityMagmaCube -bhx net/minecraft/world/entity/monster/EntityMonster -bhy net/minecraft/world/entity/monster/EntityMonsterPatrolling -bhz net/minecraft/world/entity/monster/EntityPhantom -bhz$a net/minecraft/world/entity/monster/EntityPhantom$AttackPhase -bi net/minecraft/advancements/critereon/CriterionTriggerEnterBlock -bia net/minecraft/world/entity/monster/EntityPillager -bib net/minecraft/world/entity/monster/IRangedEntity -bic net/minecraft/world/entity/monster/EntityRavager -bid net/minecraft/world/entity/monster/EntityShulker -bie net/minecraft/world/entity/monster/EntitySilverfish -bie$a net/minecraft/world/entity/monster/EntitySilverfish$PathfinderGoalSilverfishHideInBlock -bie$b net/minecraft/world/entity/monster/EntitySilverfish$PathfinderGoalSilverfishWakeOthers -bif net/minecraft/world/entity/monster/EntitySkeleton -big net/minecraft/world/entity/monster/EntitySlime -big$a net/minecraft/world/entity/monster/EntitySlime$PathfinderGoalSlimeNearestPlayer -big$b net/minecraft/world/entity/monster/EntitySlime$PathfinderGoalSlimeRandomJump -big$c net/minecraft/world/entity/monster/EntitySlime$PathfinderGoalSlimeIdle -big$d net/minecraft/world/entity/monster/EntitySlime$ControllerMoveSlime -big$e net/minecraft/world/entity/monster/EntitySlime$PathfinderGoalSlimeRandomDirection -bih net/minecraft/world/entity/monster/EntityIllagerWizard -bih$a net/minecraft/world/entity/monster/EntityIllagerWizard$Spell -bih$c net/minecraft/world/entity/monster/EntityIllagerWizard$PathfinderGoalCastSpell -bii net/minecraft/world/entity/monster/EntitySpider -bii$a net/minecraft/world/entity/monster/EntitySpider$PathfinderGoalSpiderMeleeAttack -bii$b net/minecraft/world/entity/monster/EntitySpider$GroupDataSpider -bii$c net/minecraft/world/entity/monster/EntitySpider$PathfinderGoalSpiderNearestAttackableTarget -bij net/minecraft/world/entity/monster/EntitySkeletonStray -bik net/minecraft/world/entity/monster/EntityStrider -bil net/minecraft/world/entity/monster/EntityVex -bim net/minecraft/world/entity/monster/EntityVindicator -bin net/minecraft/world/entity/monster/EntityWitch -bio net/minecraft/world/entity/monster/EntitySkeletonWither -bip net/minecraft/world/entity/monster/EntityZoglin -biq net/minecraft/world/entity/monster/EntityZombie -biq$b net/minecraft/world/entity/monster/EntityZombie$GroupDataZombie -bir net/minecraft/world/entity/monster/EntityZombieVillager -bis net/minecraft/world/entity/monster/EntityPigZombie -bit net/minecraft/world/entity/monster/hoglin/EntityHoglin -biu net/minecraft/world/entity/monster/hoglin/HoglinAI -biv net/minecraft/world/entity/monster/hoglin/IOglin -biy net/minecraft/world/entity/monster/piglin/EntityPiglinAbstract -biz net/minecraft/world/entity/monster/piglin/EntityPiglin -bj net/minecraft/advancements/critereon/CriterionConditionEntityEquipment -bja net/minecraft/world/entity/monster/piglin/PiglinAI -bjb net/minecraft/world/entity/monster/piglin/EntityPiglinArmPose -bjc net/minecraft/world/entity/monster/piglin/EntityPiglinBrute -bjd net/minecraft/world/entity/monster/piglin/PiglinBruteAI -bje net/minecraft/world/entity/monster/piglin/BehaviorRememberHuntedHoglin -bjf net/minecraft/world/entity/monster/piglin/BehaviorStartAdmiringItem -bjg net/minecraft/world/entity/monster/piglin/BehaviorHuntHoglin -bjh net/minecraft/world/entity/monster/piglin/BehaviorStopAdmiringItem -bji net/minecraft/world/entity/monster/piglin/BehaviorAdmireTimeout -bjj net/minecraft/world/entity/monster/piglin/BehaviorStopAdmiring -bjl net/minecraft/world/entity/npc/EntityVillagerAbstract -bjm net/minecraft/world/entity/npc/MobSpawnerCat -bjn net/minecraft/world/entity/npc/MerchantWrapper -bjo net/minecraft/world/entity/npc/InventoryCarrier -bjp net/minecraft/world/entity/npc/NPC -bjq net/minecraft/world/entity/npc/EntityVillager -bjr net/minecraft/world/entity/npc/VillagerData -bjs net/minecraft/world/entity/npc/VillagerDataHolder -bjt net/minecraft/world/entity/npc/VillagerProfession -bju net/minecraft/world/entity/npc/VillagerTrades -bju$f net/minecraft/world/entity/npc/VillagerTrades$IMerchantRecipeOption -bjv net/minecraft/world/entity/npc/VillagerType -bjw net/minecraft/world/entity/npc/EntityVillagerTrader -bjx net/minecraft/world/entity/npc/MobSpawnerTrader -bk net/minecraft/advancements/critereon/CriterionConditionEntityFlags -bka net/minecraft/world/entity/player/PlayerAbilities -bkb net/minecraft/world/entity/player/EnumChatVisibility -bkc net/minecraft/world/entity/player/PlayerInventory -bkd net/minecraft/world/entity/player/EntityHuman -bkd$a net/minecraft/world/entity/player/EntityHuman$EnumBedResult -bke net/minecraft/world/entity/player/PlayerModelPart -bkf net/minecraft/world/entity/player/AutoRecipeStackManager -bkh net/minecraft/world/entity/projectile/EntityArrow -bkh$a net/minecraft/world/entity/projectile/EntityArrow$PickupStatus -bki net/minecraft/world/entity/projectile/EntityFireball -bkj net/minecraft/world/entity/projectile/EntityTippedArrow -bkk net/minecraft/world/entity/projectile/EntityDragonFireball -bkl net/minecraft/world/entity/projectile/EntityEvokerFangs -bkm net/minecraft/world/entity/projectile/EntityEnderSignal -bkn net/minecraft/world/entity/projectile/EntityFireballFireball -bko net/minecraft/world/entity/projectile/EntityFireworks -bkp net/minecraft/world/entity/projectile/EntityFishingHook -bkp$a net/minecraft/world/entity/projectile/EntityFishingHook$HookState -bkp$b net/minecraft/world/entity/projectile/EntityFishingHook$WaterPosition -bkq net/minecraft/world/entity/projectile/ItemSupplier -bkr net/minecraft/world/entity/projectile/EntityLargeFireball -bks net/minecraft/world/entity/projectile/EntityLlamaSpit -bkt net/minecraft/world/entity/projectile/IProjectile -bku net/minecraft/world/entity/projectile/ProjectileHelper -bkv net/minecraft/world/entity/projectile/EntityShulkerBullet -bkw net/minecraft/world/entity/projectile/EntitySmallFireball -bkx net/minecraft/world/entity/projectile/EntitySnowball -bky net/minecraft/world/entity/projectile/EntitySpectralArrow -bkz net/minecraft/world/entity/projectile/EntityProjectileThrowable -bl net/minecraft/advancements/critereon/CriterionTriggerEntityHurtPlayer -bla net/minecraft/world/entity/projectile/EntityProjectile -blb net/minecraft/world/entity/projectile/EntityEgg -blc net/minecraft/world/entity/projectile/EntityEnderPearl -bld net/minecraft/world/entity/projectile/EntityThrownExpBottle -ble net/minecraft/world/entity/projectile/EntityPotion -blf net/minecraft/world/entity/projectile/EntityThrownTrident -blg net/minecraft/world/entity/projectile/EntityWitherSkull -bli net/minecraft/world/entity/raid/Raid -bli$a net/minecraft/world/entity/raid/Raid$Status -bli$b net/minecraft/world/entity/raid/Raid$Wave -blj net/minecraft/world/entity/raid/EntityRaider -blk net/minecraft/world/entity/raid/PersistentRaid -blm net/minecraft/world/entity/schedule/Activity -bln net/minecraft/world/entity/schedule/ActivityFrame -blo net/minecraft/world/entity/schedule/Schedule -blp net/minecraft/world/entity/schedule/ScheduleBuilder -blq net/minecraft/world/entity/schedule/ScheduleActivity -bls net/minecraft/world/entity/vehicle/EntityMinecartAbstract -bls$a net/minecraft/world/entity/vehicle/EntityMinecartAbstract$EnumMinecartType -blt net/minecraft/world/entity/vehicle/EntityMinecartContainer -blu net/minecraft/world/entity/vehicle/EntityBoat -blu$a net/minecraft/world/entity/vehicle/EntityBoat$EnumStatus -blu$b net/minecraft/world/entity/vehicle/EntityBoat$EnumBoatType -blv net/minecraft/world/entity/vehicle/DismountUtil -blw net/minecraft/world/entity/vehicle/EntityMinecartRideable -blx net/minecraft/world/entity/vehicle/EntityMinecartChest -bly net/minecraft/world/entity/vehicle/EntityMinecartCommandBlock -blz net/minecraft/world/entity/vehicle/EntityMinecartFurnace -bm net/minecraft/advancements/critereon/CriterionConditionEntity -bma net/minecraft/world/entity/vehicle/EntityMinecartHopper -bmb net/minecraft/world/entity/vehicle/EntityMinecartMobSpawner -bmc net/minecraft/world/entity/vehicle/EntityMinecartTNT -bmf net/minecraft/world/food/FoodMetaData -bmg net/minecraft/world/food/FoodInfo -bmh net/minecraft/world/food/Foods -bmj net/minecraft/world/inventory/Container -bmk net/minecraft/world/inventory/ContainerFurnace -bml net/minecraft/world/inventory/ContainerAnvil -bmm net/minecraft/world/inventory/ContainerBeacon -bmm$a net/minecraft/world/inventory/ContainerBeacon$SlotBeacon -bmn net/minecraft/world/inventory/ContainerBlastFurnace -bmo net/minecraft/world/inventory/ContainerBrewingStand -bmo$b net/minecraft/world/inventory/ContainerBrewingStand$SlotBrewing -bmo$c net/minecraft/world/inventory/ContainerBrewingStand$SlotPotionBottle -bmp net/minecraft/world/inventory/ContainerCartography -bmq net/minecraft/world/inventory/ContainerChest -bmr net/minecraft/world/inventory/ClickAction -bms net/minecraft/world/inventory/InventoryClickType -bmt net/minecraft/world/inventory/IContainerProperties -bmu net/minecraft/world/inventory/ContainerAccess -bmv net/minecraft/world/inventory/ICrafting -bmw net/minecraft/world/inventory/ContainerSynchronizer -bmx net/minecraft/world/inventory/InventoryCrafting -bmy net/minecraft/world/inventory/ContainerWorkbench -bmz net/minecraft/world/inventory/ContainerProperty -bn net/minecraft/advancements/critereon/CriterionConditionEntityType -bna net/minecraft/world/inventory/ContainerDispenser -bnb net/minecraft/world/inventory/ContainerEnchantTable -bnc net/minecraft/world/inventory/SlotFurnaceFuel -bnd net/minecraft/world/inventory/ContainerFurnaceFurnace -bne net/minecraft/world/inventory/SlotFurnaceResult -bnf net/minecraft/world/inventory/ContainerGrindstone -bng net/minecraft/world/inventory/ContainerHopper -bnh net/minecraft/world/inventory/ContainerHorse -bni net/minecraft/world/inventory/ContainerPlayer -bnj net/minecraft/world/inventory/ContainerAnvilAbstract -bnk net/minecraft/world/inventory/ContainerLectern -bnl net/minecraft/world/inventory/ContainerLoom -bnm net/minecraft/world/inventory/ITileEntityContainer -bnn net/minecraft/world/inventory/Containers -bnn$a net/minecraft/world/inventory/Containers$Supplier -bno net/minecraft/world/inventory/InventoryMerchant -bnp net/minecraft/world/inventory/ContainerMerchant -bnq net/minecraft/world/inventory/SlotMerchantResult -bnr net/minecraft/world/inventory/InventoryEnderChest -bns net/minecraft/world/inventory/ContainerRecipeBook -bnt net/minecraft/world/inventory/RecipeBookType -bnu net/minecraft/world/inventory/RecipeHolder -bnv net/minecraft/world/inventory/InventoryCraftResult -bnw net/minecraft/world/inventory/SlotResult -bnx net/minecraft/world/inventory/ContainerShulkerBox -bny net/minecraft/world/inventory/SlotShulkerBox -bnz net/minecraft/world/inventory/ContainerProperties -bo net/minecraft/advancements/critereon/CriterionTriggerFilledBucket -boa net/minecraft/world/inventory/Slot -bob net/minecraft/world/inventory/ContainerSmithing -boc net/minecraft/world/inventory/ContainerSmoker -bod net/minecraft/world/inventory/AutoRecipeOutput -boe net/minecraft/world/inventory/ContainerStonecutter -bog net/minecraft/world/inventory/tooltip/BundleTooltip -boh net/minecraft/world/inventory/tooltip/TooltipComponent -boj net/minecraft/world/item/ItemAir -bok net/minecraft/world/item/ItemArmor -bol net/minecraft/world/item/ArmorMaterial -bom net/minecraft/world/item/EnumArmorMaterial -bon net/minecraft/world/item/ItemArmorStand -boo net/minecraft/world/item/ItemArrow -bop net/minecraft/world/item/ItemAxe -boq net/minecraft/world/item/ItemBanner -bor net/minecraft/world/item/ItemBannerPattern -bos net/minecraft/world/item/ItemBed -bot net/minecraft/world/item/ItemBlock -bou net/minecraft/world/item/ItemBoat -bov net/minecraft/world/item/ItemBoneMeal -bow net/minecraft/world/item/ItemBook -box net/minecraft/world/item/ItemGlassBottle -boy net/minecraft/world/item/ItemBow -boz net/minecraft/world/item/ItemSoup -bp net/minecraft/advancements/critereon/CriterionConditionInOpenWater -bpa net/minecraft/world/item/ItemBucket -bpb net/minecraft/world/item/BundleItem -bpc net/minecraft/world/item/ItemChorusFruit -bpd net/minecraft/world/item/ItemCompass -bpe net/minecraft/world/item/ItemWorldMapBase -bpf net/minecraft/world/item/CreativeModeTab -bpg net/minecraft/world/item/ItemCrossbow -bph net/minecraft/world/item/ItemDebugStick -bpi net/minecraft/world/item/ItemTool -bpj net/minecraft/world/item/DispensibleContainerItem -bpk net/minecraft/world/item/ItemBisected -bpl net/minecraft/world/item/EnumColor -bpm net/minecraft/world/item/ItemDye -bpn net/minecraft/world/item/ItemArmorColorable -bpo net/minecraft/world/item/ItemHorseArmorDyeable -bpp net/minecraft/world/item/IDyeable -bpq net/minecraft/world/item/ItemEgg -bpr net/minecraft/world/item/ItemElytra -bps net/minecraft/world/item/ItemMapEmpty -bpt net/minecraft/world/item/ItemEnchantedBook -bpu net/minecraft/world/item/ItemGoldenAppleEnchanted -bpv net/minecraft/world/item/ItemEndCrystal -bpw net/minecraft/world/item/ItemEnderEye -bpx net/minecraft/world/item/ItemEnderPearl -bpy net/minecraft/world/item/ItemExpBottle -bpz net/minecraft/world/item/ItemFireball -bq net/minecraft/advancements/critereon/CriterionTriggerFishingRodHooked -bqa net/minecraft/world/item/ItemFireworks -bqa$a net/minecraft/world/item/ItemFireworks$EffectType -bqb net/minecraft/world/item/ItemFireworksCharge -bqc net/minecraft/world/item/ItemFishingRod -bqd net/minecraft/world/item/ItemFlintAndSteel -bqe net/minecraft/world/item/ItemCarrotStick -bqf net/minecraft/world/item/ItemRestricted -bqg net/minecraft/world/item/ItemHanging -bqh net/minecraft/world/item/ItemHoe -bqi net/minecraft/world/item/ItemHoneyBottle -bqj net/minecraft/world/item/HoneycombItem -bqk net/minecraft/world/item/ItemHorseArmor -bql net/minecraft/world/item/Item -bql$a net/minecraft/world/item/Item$Info -bqm net/minecraft/world/item/ItemCooldown -bqm$a net/minecraft/world/item/ItemCooldown$Info -bqn net/minecraft/world/item/ItemItemFrame -bqo net/minecraft/world/item/ItemNamedBlock -bqp net/minecraft/world/item/ItemStack -bqp$a net/minecraft/world/item/ItemStack$HideFlags -bqq net/minecraft/world/item/ItemLiquidUtil -bqr net/minecraft/world/item/Items -bqs net/minecraft/world/item/ItemKnowledgeBook -bqt net/minecraft/world/item/ItemLeash -bqu net/minecraft/world/item/ItemLingeringPotion -bqv net/minecraft/world/item/ItemWorldMap -bqw net/minecraft/world/item/ItemMilkBucket -bqx net/minecraft/world/item/ItemMinecart -bqy net/minecraft/world/item/MobBucketItem -bqz net/minecraft/world/item/ItemNameTag -br net/minecraft/advancements/critereon/CriterionConditionFluid -bra net/minecraft/world/item/ItemPickaxe -brb net/minecraft/world/item/ItemSkullPlayer -brc net/minecraft/world/item/ItemPotion -brd net/minecraft/world/item/ItemProjectileWeapon -bre net/minecraft/world/item/EnumItemRarity -brf net/minecraft/world/item/ItemRecord -brg net/minecraft/world/item/ItemSaddle -brh net/minecraft/world/item/ItemScaffolding -bri net/minecraft/world/item/ItemCooldownPlayer -brj net/minecraft/world/item/ItemShears -brk net/minecraft/world/item/ItemShield -brl net/minecraft/world/item/ItemSpade -brm net/minecraft/world/item/ItemSign -brn net/minecraft/world/item/ItemNetherStar -bro net/minecraft/world/item/ItemSnowball -brp net/minecraft/world/item/SolidBucketItem -brq net/minecraft/world/item/ItemMonsterEgg -brr net/minecraft/world/item/ItemSpectralArrow -brs net/minecraft/world/item/ItemSplashPotion -brt net/minecraft/world/item/SpyglassItem -bru net/minecraft/world/item/ItemBlockWallable -brv net/minecraft/world/item/ItemSuspiciousStew -brw net/minecraft/world/item/ItemSword -brx net/minecraft/world/item/ItemPotionThrowable -bry net/minecraft/world/item/ToolMaterial -brz net/minecraft/world/item/ItemToolMaterial -bs net/minecraft/advancements/critereon/CriterionTriggerImpossible -bsa net/minecraft/world/item/EnumToolMaterial -bsb net/minecraft/world/item/ItemTippedArrow -bsc net/minecraft/world/item/TooltipFlag -bsd net/minecraft/world/item/ItemTrident -bse net/minecraft/world/item/EnumAnimation -bsf net/minecraft/world/item/ItemVanishable -bsg net/minecraft/world/item/ItemWaterLily -bsh net/minecraft/world/item/ItemWearable -bsi net/minecraft/world/item/ItemBookAndQuill -bsj net/minecraft/world/item/ItemWrittenBook -bsk net/minecraft/world/item/alchemy/PotionRegistry -bsl net/minecraft/world/item/alchemy/PotionBrewer -bsl$a net/minecraft/world/item/alchemy/PotionBrewer$PredicatedCombination -bsm net/minecraft/world/item/alchemy/PotionUtil -bsn net/minecraft/world/item/alchemy/Potions -bsp net/minecraft/world/item/context/BlockActionContext -bsq net/minecraft/world/item/context/BlockActionContextDirectional -bsr net/minecraft/world/item/context/ItemActionContext -bst net/minecraft/world/item/crafting/RecipeCooking -bsu net/minecraft/world/item/crafting/RecipeArmorDye -bsv net/minecraft/world/item/crafting/RecipeBannerDuplicate -bsw net/minecraft/world/item/crafting/RecipeBlasting -bsx net/minecraft/world/item/crafting/RecipeBookClone -bsy net/minecraft/world/item/crafting/RecipeCampfire -bsz net/minecraft/world/item/crafting/RecipeCrafting -bt net/minecraft/advancements/critereon/CriterionTriggerInventoryChanged -bta net/minecraft/world/item/crafting/IRecipeComplex -btb net/minecraft/world/item/crafting/RecipeFireworks -btc net/minecraft/world/item/crafting/RecipeFireworksFade -btd net/minecraft/world/item/crafting/RecipeFireworksStar -bte net/minecraft/world/item/crafting/RecipeItemStack -bte$a net/minecraft/world/item/crafting/RecipeItemStack$StackProvider -bte$c net/minecraft/world/item/crafting/RecipeItemStack$Provider -btf net/minecraft/world/item/crafting/RecipeMapClone -btg net/minecraft/world/item/crafting/RecipeMapExtend -bth net/minecraft/world/item/crafting/IRecipe -bti net/minecraft/world/item/crafting/CraftingManager -btj net/minecraft/world/item/crafting/RecipeSerializer -btk net/minecraft/world/item/crafting/Recipes -btl net/minecraft/world/item/crafting/RecipeRepair -btm net/minecraft/world/item/crafting/ShapedRecipes -btn net/minecraft/world/item/crafting/ShapelessRecipes -bto net/minecraft/world/item/crafting/RecipiesShield -btp net/minecraft/world/item/crafting/RecipeShulkerBox -btq net/minecraft/world/item/crafting/RecipeSerializerCooking -btr net/minecraft/world/item/crafting/RecipeSerializerComplex -bts net/minecraft/world/item/crafting/RecipeSingleItem -btt net/minecraft/world/item/crafting/FurnaceRecipe -btu net/minecraft/world/item/crafting/RecipeSmoking -btv net/minecraft/world/item/crafting/RecipeStonecutting -btw net/minecraft/world/item/crafting/RecipeSuspiciousStew -btx net/minecraft/world/item/crafting/RecipeTippedArrow -bty net/minecraft/world/item/crafting/RecipeSmithing -bu net/minecraft/advancements/critereon/CriterionTriggerItemDurabilityChanged -bua net/minecraft/world/item/enchantment/EnchantmentArrowDamage -bub net/minecraft/world/item/enchantment/EnchantmentFlameArrows -buc net/minecraft/world/item/enchantment/EnchantmentInfiniteArrows -bud net/minecraft/world/item/enchantment/EnchantmentArrowKnockback -bue net/minecraft/world/item/enchantment/EnchantmentPiercing -buf net/minecraft/world/item/enchantment/EnchantmentBinding -bug net/minecraft/world/item/enchantment/EnchantmentWeaponDamage -buh net/minecraft/world/item/enchantment/EnchantmentDurability -bui net/minecraft/world/item/enchantment/EnchantmentDigging -buj net/minecraft/world/item/enchantment/Enchantment -buj$a net/minecraft/world/item/enchantment/Enchantment$Rarity -buk net/minecraft/world/item/enchantment/EnchantmentSlotType -bul net/minecraft/world/item/enchantment/EnchantmentManager -bum net/minecraft/world/item/enchantment/WeightedRandomEnchant -bun net/minecraft/world/item/enchantment/Enchantments -buo net/minecraft/world/item/enchantment/EnchantmentFire -bup net/minecraft/world/item/enchantment/EnchantmentLure -buq net/minecraft/world/item/enchantment/EnchantmentFrostWalker -bur net/minecraft/world/item/enchantment/EnchantmentKnockback -bus net/minecraft/world/item/enchantment/EnchantmentLootBonus -but net/minecraft/world/item/enchantment/EnchantmentMending -buu net/minecraft/world/item/enchantment/EnchantmentMultishot -buv net/minecraft/world/item/enchantment/EnchantmentOxygen -buw net/minecraft/world/item/enchantment/EnchantmentProtection -buw$a net/minecraft/world/item/enchantment/EnchantmentProtection$DamageType -bux net/minecraft/world/item/enchantment/EnchantmentQuickCharge -buy net/minecraft/world/item/enchantment/EnchantmentSoulSpeed -buz net/minecraft/world/item/enchantment/EnchantmentSweeping -bv net/minecraft/advancements/critereon/CriterionTriggerThrownItemPickedUpByEntity -bva net/minecraft/world/item/enchantment/EnchantmentThorns -bvb net/minecraft/world/item/enchantment/EnchantmentTridentChanneling -bvc net/minecraft/world/item/enchantment/EnchantmentTridentImpaling -bvd net/minecraft/world/item/enchantment/EnchantmentTridentLoyalty -bve net/minecraft/world/item/enchantment/EnchantmentTridentRiptide -bvf net/minecraft/world/item/enchantment/EnchantmentSilkTouch -bvg net/minecraft/world/item/enchantment/EnchantmentVanishing -bvh net/minecraft/world/item/enchantment/EnchantmentDepthStrider -bvi net/minecraft/world/item/enchantment/EnchantmentWaterWorker -bvl net/minecraft/world/item/trading/IMerchant -bvm net/minecraft/world/item/trading/MerchantRecipe -bvn net/minecraft/world/item/trading/MerchantRecipeList -bvp net/minecraft/world/level/CommandBlockListenerAbstract -bvq net/minecraft/world/level/MobSpawnerAbstract -bvr net/minecraft/world/level/IBlockLightAccess -bvs net/minecraft/world/level/BlockActionData -bvt net/minecraft/world/level/IBlockAccess -bvu net/minecraft/world/level/ChunkCoordIntPair -bvv net/minecraft/world/level/TickListChunk -bvw net/minecraft/world/level/ClipBlockStateContext -bvx net/minecraft/world/level/RayTrace -bvx$a net/minecraft/world/level/RayTrace$BlockCollisionOption -bvx$b net/minecraft/world/level/RayTrace$FluidCollisionOption -bvy net/minecraft/world/level/ICollisionAccess -bvz net/minecraft/world/level/VoxelShapeSpliterator -bw net/minecraft/advancements/critereon/CriterionConditionItem -bwa net/minecraft/world/level/ICombinedAccess -bwb net/minecraft/world/level/MobSpawner -bwc net/minecraft/world/level/DataPackConfiguration -bwd net/minecraft/world/level/BlockAccessAir -bwe net/minecraft/world/level/TickListEmpty -bwf net/minecraft/world/level/ExplosionDamageCalculatorEntity -bwg net/minecraft/world/level/IEntityAccess -bwh net/minecraft/world/level/Explosion -bwh$a net/minecraft/world/level/Explosion$Effect -bwi net/minecraft/world/level/ExplosionDamageCalculator -bwj net/minecraft/world/level/FoliageColor -bwk net/minecraft/world/level/ForcedChunk -bwl net/minecraft/world/level/GameRules -bwl$a net/minecraft/world/level/GameRules$GameRuleBoolean -bwl$b net/minecraft/world/level/GameRules$GameRuleCategory -bwl$c net/minecraft/world/level/GameRules$GameRuleVisitor -bwl$d net/minecraft/world/level/GameRules$GameRuleInt -bwl$e net/minecraft/world/level/GameRules$GameRuleKey -bwl$f net/minecraft/world/level/GameRules$GameRuleDefinition -bwl$g net/minecraft/world/level/GameRules$GameRuleValue -bwm net/minecraft/world/level/EnumGamemode -bwn net/minecraft/world/level/GrassColor -bwo net/minecraft/world/level/IMaterial -bwp net/minecraft/world/level/World -bwq net/minecraft/world/level/GeneratorAccess -bwr net/minecraft/world/level/LevelHeightAccessor -bws net/minecraft/world/level/IWorldReader -bwt net/minecraft/world/level/WorldSettings -bwu net/minecraft/world/level/VirtualLevelWritable -bwv net/minecraft/world/level/VirtualLevelReadable -bww net/minecraft/world/level/IWorldTime -bwx net/minecraft/world/level/IWorldWriter -bwy net/minecraft/world/level/EnumSkyBlock -bwz net/minecraft/world/level/SpawnerCreature -bx net/minecraft/advancements/critereon/CriterionTriggerInteractBlock -bxa net/minecraft/world/level/BlockColumn -bxb net/minecraft/world/level/ChunkCache -bxc net/minecraft/world/level/SpawnerCreatureProbabilities -bxd net/minecraft/world/level/WorldAccess -bxe net/minecraft/world/level/TickListServer -bxf net/minecraft/world/level/MobSpawnerData -bxg net/minecraft/world/level/StructureManager -bxh net/minecraft/world/level/TickList -bxi net/minecraft/world/level/NextTickListEntry -bxj net/minecraft/world/level/TickListPriority -bxk net/minecraft/world/level/GeneratorAccessSeed -bxl net/minecraft/world/level/biome/CaveSound -bxm net/minecraft/world/level/biome/CaveSoundSettings -bxn net/minecraft/world/level/biome/BiomeParticles -bxo net/minecraft/world/level/biome/BiomeBase -bxo$b net/minecraft/world/level/biome/BiomeBase$Geography -bxo$e net/minecraft/world/level/biome/BiomeBase$Precipitation -bxo$f net/minecraft/world/level/biome/BiomeBase$TemperatureModifier -bxp net/minecraft/world/level/biome/BiomeSettingsGeneration -bxq net/minecraft/world/level/biome/BiomeManager -bxq$a net/minecraft/world/level/biome/BiomeManager$Provider -bxr net/minecraft/world/level/biome/WorldChunkManager -bxs net/minecraft/world/level/biome/BiomeFog -bxs$b net/minecraft/world/level/biome/BiomeFog$GrassColor -bxt net/minecraft/world/level/biome/GenLayerZoomer -bxu net/minecraft/world/level/biome/Biomes -bxv net/minecraft/world/level/biome/WorldChunkManagerCheckerBoard -bxw net/minecraft/world/level/biome/WorldChunkManagerHell -bxx net/minecraft/world/level/biome/GenLayerZoomVoronoi -bxy net/minecraft/world/level/biome/GenLayerZoomVoronoiFixed -bxz net/minecraft/world/level/biome/BiomeSettingsMobs -by net/minecraft/advancements/critereon/CriterionTriggerKilledByCrossbow -bya net/minecraft/world/level/biome/WorldChunkManagerMultiNoise -byb net/minecraft/world/level/biome/GenLayerZoomerBiome -byc net/minecraft/world/level/biome/WorldChunkManagerOverworld -byd net/minecraft/world/level/biome/WorldChunkManagerTheEnd -byf net/minecraft/world/level/block/BlockBannerAbstract -byg net/minecraft/world/level/block/AbstractCandleBlock -byh net/minecraft/world/level/block/AbstractCauldronBlock -byi net/minecraft/world/level/block/BlockChestAbstract -byj net/minecraft/world/level/block/BlockFurnace -byk net/minecraft/world/level/block/BlockGlassAbstract -byl net/minecraft/world/level/block/BlockSkullAbstract -bym net/minecraft/world/level/block/BlockAir -byn net/minecraft/world/level/block/AmethystBlock -byo net/minecraft/world/level/block/AmethystClusterBlock -byp net/minecraft/world/level/block/BlockAnvil -byq net/minecraft/world/level/block/BlockStemAttached -byr net/minecraft/world/level/block/AzaleaBlock -bys net/minecraft/world/level/block/BlockBamboo -byt net/minecraft/world/level/block/BlockBambooSapling -byu net/minecraft/world/level/block/BlockBanner -byv net/minecraft/world/level/block/BlockBarrel -byw net/minecraft/world/level/block/BlockBarrier -byx net/minecraft/world/level/block/BlockCoralFanAbstract -byy net/minecraft/world/level/block/BlockCoralDead -byz net/minecraft/world/level/block/BlockCoralBase -bz net/minecraft/advancements/critereon/CriterionTriggerKilled -bza net/minecraft/world/level/block/BlockCoralFanWallAbstract -bzb net/minecraft/world/level/block/BlockTileEntity -bzc net/minecraft/world/level/block/BlockFireAbstract -bzd net/minecraft/world/level/block/BlockPressurePlateAbstract -bze net/minecraft/world/level/block/BlockMinecartTrackAbstract -bzf net/minecraft/world/level/block/IBeaconBeam -bzg net/minecraft/world/level/block/BlockBeacon -bzh net/minecraft/world/level/block/BlockBed -bzi net/minecraft/world/level/block/BlockBeehive -bzj net/minecraft/world/level/block/BlockBeetroot -bzk net/minecraft/world/level/block/BlockBell -bzl net/minecraft/world/level/block/BigDripleafBlock -bzm net/minecraft/world/level/block/BigDripleafStemBlock -bzn net/minecraft/world/level/block/BlockBlastFurnace -bzo net/minecraft/world/level/block/Block -bzp net/minecraft/world/level/block/Blocks -bzq net/minecraft/world/level/block/IBlockFragilePlantElement -bzr net/minecraft/world/level/block/BlockBrewingStand -bzs net/minecraft/world/level/block/BlockBubbleColumn -bzt net/minecraft/world/level/block/IFluidSource -bzu net/minecraft/world/level/block/BuddingAmethystBlock -bzv net/minecraft/world/level/block/BlockPlant -bzw net/minecraft/world/level/block/BlockButtonAbstract -bzx net/minecraft/world/level/block/BlockCactus -bzy net/minecraft/world/level/block/BlockCake -bzz net/minecraft/world/level/block/BlockCampfire -c com/mojang/math/Matrix3f -ca net/minecraft/advancements/critereon/CriterionTriggerLevitation -caa net/minecraft/world/level/block/CandleBlock -cab net/minecraft/world/level/block/CandleCakeBlock -cac net/minecraft/world/level/block/CarpetBlock -cad net/minecraft/world/level/block/BlockCarrots -cae net/minecraft/world/level/block/BlockCartographyTable -caf net/minecraft/world/level/block/BlockPumpkinCarved -cag net/minecraft/world/level/block/BlockCauldron -cah net/minecraft/world/level/block/CaveVines -cai net/minecraft/world/level/block/CaveVinesBlock -caj net/minecraft/world/level/block/CaveVinesPlantBlock -cak net/minecraft/world/level/block/BlockChain -cal net/minecraft/world/level/block/ChangeOverTimeBlock -cam net/minecraft/world/level/block/BlockChest -can net/minecraft/world/level/block/BlockChorusFlower -cao net/minecraft/world/level/block/BlockChorusFruit -cap net/minecraft/world/level/block/BlockCocoa -caq net/minecraft/world/level/block/BlockCommand -car net/minecraft/world/level/block/BlockRedstoneComparator -cas net/minecraft/world/level/block/BlockComposter -cas$a net/minecraft/world/level/block/BlockComposter$ContainerEmpty -cas$b net/minecraft/world/level/block/BlockComposter$ContainerInput -cas$c net/minecraft/world/level/block/BlockComposter$ContainerOutput -cat net/minecraft/world/level/block/BlockConcretePowder -cau net/minecraft/world/level/block/BlockConduit -cav net/minecraft/world/level/block/BlockCoral -caw net/minecraft/world/level/block/BlockCoralFan -cax net/minecraft/world/level/block/BlockCoralPlant -cay net/minecraft/world/level/block/BlockCoralFanWall -caz net/minecraft/world/level/block/BlockWorkbench -cb net/minecraft/advancements/critereon/CriterionConditionLight -cba net/minecraft/world/level/block/BlockCrops -cbb net/minecraft/world/level/block/BlockTall -cbc net/minecraft/world/level/block/BlockCryingObsidian -cbd net/minecraft/world/level/block/BlockDaylightDetector -cbe net/minecraft/world/level/block/BlockDeadBush -cbf net/minecraft/world/level/block/BlockMinecartDetector -cbg net/minecraft/world/level/block/BlockDiodeAbstract -cbh net/minecraft/world/level/block/BlockDirectional -cbi net/minecraft/world/level/block/BlockGrassPath -cbj net/minecraft/world/level/block/BlockDispenser -cbk net/minecraft/world/level/block/BlockDoor -cbl net/minecraft/world/level/block/DoubleBlockFinder -cbl$a net/minecraft/world/level/block/DoubleBlockFinder$BlockType -cbl$b net/minecraft/world/level/block/DoubleBlockFinder$Combiner -cbl$c net/minecraft/world/level/block/DoubleBlockFinder$Result -cbl$c$a net/minecraft/world/level/block/DoubleBlockFinder$Result$Double -cbl$c$b net/minecraft/world/level/block/DoubleBlockFinder$Result$Single -cbm net/minecraft/world/level/block/BlockTallPlant -cbn net/minecraft/world/level/block/BlockDragonEgg -cbo net/minecraft/world/level/block/BlockDropper -cbp net/minecraft/world/level/block/BlockEnchantmentTable -cbq net/minecraft/world/level/block/BlockEndGateway -cbr net/minecraft/world/level/block/BlockEnderPortal -cbs net/minecraft/world/level/block/BlockEnderPortalFrame -cbt net/minecraft/world/level/block/BlockEndRod -cbu net/minecraft/world/level/block/BlockEnderChest -cbv net/minecraft/world/level/block/ITileEntity -cbw net/minecraft/world/level/block/BlockAttachable -cbx net/minecraft/world/level/block/Fallable -cby net/minecraft/world/level/block/BlockFalling -cbz net/minecraft/world/level/block/BlockSoil -cc net/minecraft/advancements/critereon/LighthingBoltPredicate -cca net/minecraft/world/level/block/BlockFence -ccb net/minecraft/world/level/block/BlockFenceGate -ccc net/minecraft/world/level/block/BlockFire -ccd net/minecraft/world/level/block/BlockFletchingTable -cce net/minecraft/world/level/block/BlockFlowers -ccf net/minecraft/world/level/block/BlockFlowerPot -ccg net/minecraft/world/level/block/BlockIceFrost -cch net/minecraft/world/level/block/BlockFungi -cci net/minecraft/world/level/block/BlockFurnaceFurace -ccj net/minecraft/world/level/block/GameMasterBlock -cck net/minecraft/world/level/block/BlockGlass -ccl net/minecraft/world/level/block/BlockGlazedTerracotta -ccm net/minecraft/world/level/block/GlowLichenBlock -ccn net/minecraft/world/level/block/BlockGrass -cco net/minecraft/world/level/block/BlockGravel -ccp net/minecraft/world/level/block/BlockGrindstone -ccq net/minecraft/world/level/block/BlockGrowingAbstract -ccr net/minecraft/world/level/block/BlockGrowingStem -ccs net/minecraft/world/level/block/BlockGrowingTop -cct net/minecraft/world/level/block/BlockHalfTransparent -ccu net/minecraft/world/level/block/HangingRootsBlock -ccv net/minecraft/world/level/block/BlockHay -ccw net/minecraft/world/level/block/BlockHoney -ccx net/minecraft/world/level/block/BlockHopper -ccy net/minecraft/world/level/block/BlockFacingHorizontal -ccz net/minecraft/world/level/block/BlockHugeMushroom -cd net/minecraft/advancements/critereon/LightningStrikeTrigger -cda net/minecraft/world/level/block/BlockIce -cdb net/minecraft/world/level/block/BlockMonsterEggs -cdc net/minecraft/world/level/block/InfestedRotatedPillarBlock -cdd net/minecraft/world/level/block/BlockIronBars -cde net/minecraft/world/level/block/BlockJigsaw -cdf net/minecraft/world/level/block/BlockJukeBox -cdg net/minecraft/world/level/block/BlockKelp -cdh net/minecraft/world/level/block/BlockKelpPlant -cdi net/minecraft/world/level/block/BlockLadder -cdj net/minecraft/world/level/block/BlockLantern -cdk net/minecraft/world/level/block/LavaCauldronBlock -cdl net/minecraft/world/level/block/LayeredCauldronBlock -cdm net/minecraft/world/level/block/BlockLeaves -cdn net/minecraft/world/level/block/BlockLectern -cdp net/minecraft/world/level/block/BlockLever -cdq net/minecraft/world/level/block/LightBlock -cdr net/minecraft/world/level/block/LightningRodBlock -cds net/minecraft/world/level/block/BlockFluids -cdt net/minecraft/world/level/block/IFluidContainer -cdu net/minecraft/world/level/block/BlockLoom -cdv net/minecraft/world/level/block/BlockMagma -cdw net/minecraft/world/level/block/BlockMelon -cdx net/minecraft/world/level/block/EnumBlockMirror -cdy net/minecraft/world/level/block/MossBlock -cdz net/minecraft/world/level/block/MultifaceBlock -ce net/minecraft/advancements/critereon/CriterionConditionLocation -cea net/minecraft/world/level/block/BlockMushroom -ceb net/minecraft/world/level/block/BlockMycel -cec net/minecraft/world/level/block/BlockPortal -ced net/minecraft/world/level/block/BlockNetherSprouts -cee net/minecraft/world/level/block/BlockNetherVinesUtil -cef net/minecraft/world/level/block/BlockNetherWart -ceg net/minecraft/world/level/block/BlockNetherrack -ceh net/minecraft/world/level/block/BlockNote -cei net/minecraft/world/level/block/BlockNylium -cej net/minecraft/world/level/block/BlockObserver -cek net/minecraft/world/level/block/BlockOre -cel net/minecraft/world/level/block/BlockSprawling -cem net/minecraft/world/level/block/BlockSkullPlayer -cen net/minecraft/world/level/block/BlockSkullPlayerWall -ceo net/minecraft/world/level/block/PointedDripstoneBlock -cep net/minecraft/world/level/block/BlockPotatoes -ceq net/minecraft/world/level/block/PowderSnowBlock -cer net/minecraft/world/level/block/PowderSnowCauldronBlock -ces net/minecraft/world/level/block/BlockPowered -cet net/minecraft/world/level/block/BlockPoweredRail -ceu net/minecraft/world/level/block/BlockPressurePlateBinary -ceu$a net/minecraft/world/level/block/BlockPressurePlateBinary$EnumMobType -cev net/minecraft/world/level/block/BlockPumpkin -cew net/minecraft/world/level/block/BlockMinecartTrack -cex net/minecraft/world/level/block/MinecartTrackLogic -cey net/minecraft/world/level/block/BlockRedstoneOre -cez net/minecraft/world/level/block/BlockRedstoneWire -cf net/minecraft/advancements/critereon/CriterionTriggerLocation -cfa net/minecraft/world/level/block/BlockRedstoneLamp -cfb net/minecraft/world/level/block/BlockRedstoneTorch -cfb$a net/minecraft/world/level/block/BlockRedstoneTorch$RedstoneUpdateInfo -cfc net/minecraft/world/level/block/BlockRedstoneTorchWall -cfd net/minecraft/world/level/block/EnumRenderType -cfe net/minecraft/world/level/block/BlockRepeater -cff net/minecraft/world/level/block/BlockRespawnAnchor -cfg net/minecraft/world/level/block/RodBlock -cfh net/minecraft/world/level/block/RootedDirtBlock -cfi net/minecraft/world/level/block/BlockRoots -cfj net/minecraft/world/level/block/BlockRotatable -cfk net/minecraft/world/level/block/EnumBlockRotation -cfl net/minecraft/world/level/block/BlockSand -cfm net/minecraft/world/level/block/BlockSapling -cfn net/minecraft/world/level/block/BlockScaffolding -cfo net/minecraft/world/level/block/SculkSensorBlock -cfp net/minecraft/world/level/block/BlockSeaPickle -cfq net/minecraft/world/level/block/SeagrassBlock -cfr net/minecraft/world/level/block/BlockShulkerBox -cfs net/minecraft/world/level/block/BlockSign -cft net/minecraft/world/level/block/IBlockWaterlogged -cfu net/minecraft/world/level/block/BlockSkull -cfu$b net/minecraft/world/level/block/BlockSkull$Type -cfv net/minecraft/world/level/block/BlockStepAbstract -cfw net/minecraft/world/level/block/BlockSlime -cfx net/minecraft/world/level/block/SmallDripleafBlock -cfy net/minecraft/world/level/block/BlockSmithingTable -cfz net/minecraft/world/level/block/BlockSmoker -cg net/minecraft/advancements/critereon/CriterionTriggerPlayerGeneratesContainerLoot -cga net/minecraft/world/level/block/BlockSnow -cgb net/minecraft/world/level/block/BlockDirtSnow -cgc net/minecraft/world/level/block/BlockSoulFire -cgd net/minecraft/world/level/block/BlockSlowSand -cge net/minecraft/world/level/block/SoundEffectType -cgf net/minecraft/world/level/block/BlockMobSpawner -cgg net/minecraft/world/level/block/BlockSponge -cgh net/minecraft/world/level/block/SporeBlossomBlock -cgi net/minecraft/world/level/block/BlockDirtSnowSpreadable -cgj net/minecraft/world/level/block/BlockStainedGlass -cgk net/minecraft/world/level/block/BlockStainedGlassPane -cgl net/minecraft/world/level/block/BlockStairs -cgm net/minecraft/world/level/block/BlockFloorSign -cgn net/minecraft/world/level/block/BlockStem -cgo net/minecraft/world/level/block/BlockStemmed -cgp net/minecraft/world/level/block/BlockStoneButton -cgq net/minecraft/world/level/block/BlockStonecutter -cgr net/minecraft/world/level/block/BlockStructure -cgs net/minecraft/world/level/block/BlockStructureVoid -cgt net/minecraft/world/level/block/BlockReed -cgu net/minecraft/world/level/block/EnumBlockSupport -cgv net/minecraft/world/level/block/BlockSweetBerryBush -cgw net/minecraft/world/level/block/BlockTallPlantFlower -cgx net/minecraft/world/level/block/BlockLongGrass -cgy net/minecraft/world/level/block/TallSeagrassBlock -cgz net/minecraft/world/level/block/BlockTarget -ch net/minecraft/advancements/critereon/CriterionConditionValue -ch$c net/minecraft/advancements/critereon/CriterionConditionValue$DoubleRange -ch$d net/minecraft/advancements/critereon/CriterionConditionValue$IntegerRange -cha net/minecraft/world/level/block/TintedGlassBlock -chb net/minecraft/world/level/block/BlockTNT -chc net/minecraft/world/level/block/BlockTorch -chd net/minecraft/world/level/block/BlockTrapdoor -che net/minecraft/world/level/block/BlockChestTrapped -chf net/minecraft/world/level/block/BlockTripwire -chg net/minecraft/world/level/block/BlockTripwireHook -chh net/minecraft/world/level/block/BlockTurtleEgg -chi net/minecraft/world/level/block/BlockTwistingVines -chj net/minecraft/world/level/block/BlockTwistingVinesPlant -chk net/minecraft/world/level/block/BlockVine -chl net/minecraft/world/level/block/BlockBannerWall -chm net/minecraft/world/level/block/BlockCobbleWall -chn net/minecraft/world/level/block/BlockWallSign -cho net/minecraft/world/level/block/BlockSkullWall -chp net/minecraft/world/level/block/BlockTorchWall -chq net/minecraft/world/level/block/BlockWaterLily -chr net/minecraft/world/level/block/WeatheringCopper -chs net/minecraft/world/level/block/WeatheringCopperFullBlock -cht net/minecraft/world/level/block/WeatheringCopperSlabBlock -chu net/minecraft/world/level/block/WeatheringCopperStairBlock -chv net/minecraft/world/level/block/BlockWeb -chw net/minecraft/world/level/block/BlockWeepingVines -chx net/minecraft/world/level/block/BlockWeepingVinesPlant -chy net/minecraft/world/level/block/BlockPressurePlateWeighted -chz net/minecraft/world/level/block/BlockWetSponge -ci net/minecraft/advancements/critereon/CriterionConditionMobEffect -cia net/minecraft/world/level/block/BlockWitherRose -cib net/minecraft/world/level/block/BlockWitherSkull -cic net/minecraft/world/level/block/BlockWitherSkullWall -cid net/minecraft/world/level/block/BlockWoodButton -cie net/minecraft/world/level/block/BlockCarpet -cif net/minecraft/world/level/block/entity/TileEntityFurnace -cig net/minecraft/world/level/block/entity/TileEntityBanner -cih net/minecraft/world/level/block/entity/EnumBannerPatternType -cii net/minecraft/world/level/block/entity/TileEntityBarrel -cij net/minecraft/world/level/block/entity/TileEntityContainer -cik net/minecraft/world/level/block/entity/TileEntityBeacon -cik$a net/minecraft/world/level/block/entity/TileEntityBeacon$BeaconColorTracker -cil net/minecraft/world/level/block/entity/TileEntityBed -cim net/minecraft/world/level/block/entity/TileEntityBeehive -cim$a net/minecraft/world/level/block/entity/TileEntityBeehive$HiveBee -cim$b net/minecraft/world/level/block/entity/TileEntityBeehive$ReleaseStatus -cin net/minecraft/world/level/block/entity/TileEntityBell -cio net/minecraft/world/level/block/entity/TileEntityBlastFurnace -cip net/minecraft/world/level/block/entity/TileEntity -ciq net/minecraft/world/level/block/entity/BlockEntityTicker -cir net/minecraft/world/level/block/entity/TileEntityTypes -cis net/minecraft/world/level/block/entity/TileEntityBrewingStand -cit net/minecraft/world/level/block/entity/TileEntityCampfire -ciu net/minecraft/world/level/block/entity/TileEntityChest -civ net/minecraft/world/level/block/entity/ChestLidController -ciw net/minecraft/world/level/block/entity/TileEntityCommand -ciw$a net/minecraft/world/level/block/entity/TileEntityCommand$Type -cix net/minecraft/world/level/block/entity/TileEntityComparator -ciy net/minecraft/world/level/block/entity/TileEntityConduit -ciz net/minecraft/world/level/block/entity/ContainerOpenersCounter -cj net/minecraft/advancements/critereon/CriterionConditionNBT -cja net/minecraft/world/level/block/entity/TileEntityLightDetector -cjb net/minecraft/world/level/block/entity/TileEntityDispenser -cjc net/minecraft/world/level/block/entity/TileEntityDropper -cjd net/minecraft/world/level/block/entity/TileEntityEnchantTable -cje net/minecraft/world/level/block/entity/TileEntityEnderChest -cjf net/minecraft/world/level/block/entity/TileEntityFurnaceFurnace -cjg net/minecraft/world/level/block/entity/IHopper -cjh net/minecraft/world/level/block/entity/TileEntityHopper -cji net/minecraft/world/level/block/entity/TileEntityJigsaw -cji$a net/minecraft/world/level/block/entity/TileEntityJigsaw$JointType -cjj net/minecraft/world/level/block/entity/TileEntityJukeBox -cjk net/minecraft/world/level/block/entity/TileEntityLectern -cjl net/minecraft/world/level/block/entity/LidBlockEntity -cjm net/minecraft/world/level/block/entity/TileEntityLootable -cjn net/minecraft/world/level/block/entity/SculkSensorBlockEntity -cjo net/minecraft/world/level/block/entity/TileEntityShulkerBox -cjo$a net/minecraft/world/level/block/entity/TileEntityShulkerBox$AnimationPhase -cjp net/minecraft/world/level/block/entity/TileEntitySign -cjq net/minecraft/world/level/block/entity/TileEntitySkull -cjr net/minecraft/world/level/block/entity/TileEntitySmoker -cjs net/minecraft/world/level/block/entity/TileEntityMobSpawner -cjt net/minecraft/world/level/block/entity/TileEntityStructure -cjt$a net/minecraft/world/level/block/entity/TileEntityStructure$UpdateType -cju net/minecraft/world/level/block/entity/TileEntityEndGateway -cjv net/minecraft/world/level/block/entity/TileEntityEnderPortal -cjw net/minecraft/world/level/block/entity/TickingBlockEntity -cjx net/minecraft/world/level/block/entity/TileEntityChestTrapped -cjz net/minecraft/world/level/block/grower/WorldGenMegaTreeProvider -ck net/minecraft/advancements/critereon/CriterionTriggerNetherTravel -cka net/minecraft/world/level/block/grower/WorldGenTreeProvider -ckb net/minecraft/world/level/block/grower/WorldGenTreeProviderAcacia -ckc net/minecraft/world/level/block/grower/AzaleaTreeGrower -ckd net/minecraft/world/level/block/grower/WorldGenTreeProviderBirch -cke net/minecraft/world/level/block/grower/WorldGenMegaTreeProviderDarkOak -ckf net/minecraft/world/level/block/grower/WorldGenMegaTreeProviderJungle -ckg net/minecraft/world/level/block/grower/WorldGenTreeProviderOak -ckh net/minecraft/world/level/block/grower/WorldGenTreeProviderSpruce -ckk net/minecraft/world/level/block/piston/BlockPistonMoving -ckl net/minecraft/world/level/block/piston/BlockPiston -ckm net/minecraft/world/level/block/piston/BlockPistonExtension -ckn net/minecraft/world/level/block/piston/PistonUtil -cko net/minecraft/world/level/block/piston/TileEntityPiston -ckp net/minecraft/world/level/block/piston/PistonExtendsChecker -ckr net/minecraft/world/level/block/state/BlockBase -ckr$a net/minecraft/world/level/block/state/BlockBase$BlockData -ckr$a$a net/minecraft/world/level/block/state/BlockBase$BlockData$Cache -ckr$b net/minecraft/world/level/block/state/BlockBase$EnumRandomOffset -ckr$c net/minecraft/world/level/block/state/BlockBase$Info -cks net/minecraft/world/level/block/state/IBlockData -ckt net/minecraft/world/level/block/state/BlockStateList -cku net/minecraft/world/level/block/state/IBlockDataHolder -ckw net/minecraft/world/level/block/state/pattern/ShapeDetectorBlock -ckx net/minecraft/world/level/block/state/pattern/ShapeDetector -ckx$a net/minecraft/world/level/block/state/pattern/ShapeDetector$BlockLoader -ckx$b net/minecraft/world/level/block/state/pattern/ShapeDetector$ShapeDetectorCollection -cky net/minecraft/world/level/block/state/pattern/ShapeDetectorBuilder -cl net/minecraft/advancements/critereon/CriterionTriggerPlacedBlock -cla net/minecraft/world/level/block/state/predicate/MaterialPredicate -clb net/minecraft/world/level/block/state/predicate/BlockPredicate -clc net/minecraft/world/level/block/state/predicate/BlockStatePredicate -cle net/minecraft/world/level/block/state/properties/BlockPropertyAttachPosition -clf net/minecraft/world/level/block/state/properties/BlockPropertyBambooSize -clg net/minecraft/world/level/block/state/properties/BlockPropertyBedPart -clh net/minecraft/world/level/block/state/properties/BlockPropertyBellAttach -cli net/minecraft/world/level/block/state/properties/BlockProperties -clj net/minecraft/world/level/block/state/properties/BlockStateBoolean -clk net/minecraft/world/level/block/state/properties/BlockPropertyChestType -cll net/minecraft/world/level/block/state/properties/BlockPropertyComparatorMode -clm net/minecraft/world/level/block/state/properties/BlockStateDirection -cln net/minecraft/world/level/block/state/properties/BlockPropertyDoorHinge -clo net/minecraft/world/level/block/state/properties/BlockPropertyDoubleBlockHalf -clp net/minecraft/world/level/block/state/properties/DripstoneThickness -clq net/minecraft/world/level/block/state/properties/BlockStateEnum -clr net/minecraft/world/level/block/state/properties/BlockPropertyHalf -cls net/minecraft/world/level/block/state/properties/BlockStateInteger -clt net/minecraft/world/level/block/state/properties/BlockPropertyInstrument -clu net/minecraft/world/level/block/state/properties/BlockPropertyPistonType -clv net/minecraft/world/level/block/state/properties/IBlockState -clw net/minecraft/world/level/block/state/properties/BlockPropertyTrackPosition -clx net/minecraft/world/level/block/state/properties/BlockPropertyRedstoneSide -cly net/minecraft/world/level/block/state/properties/SculkSensorPhase -clz net/minecraft/world/level/block/state/properties/BlockPropertySlabType -cm net/minecraft/advancements/critereon/CriterionTriggerPlayerHurtEntity -cma net/minecraft/world/level/block/state/properties/BlockPropertyStairsShape -cmb net/minecraft/world/level/block/state/properties/BlockPropertyStructureMode -cmc net/minecraft/world/level/block/state/properties/Tilt -cmd net/minecraft/world/level/block/state/properties/BlockPropertyWallHeight -cme net/minecraft/world/level/block/state/properties/BlockPropertyWood -cmg net/minecraft/world/level/border/IWorldBorderListener -cmh net/minecraft/world/level/border/BorderStatus -cmi net/minecraft/world/level/border/WorldBorder -cmk net/minecraft/world/level/chunk/BulkSectionAccess -cml net/minecraft/world/level/chunk/IChunkAccess -cmm net/minecraft/world/level/chunk/BiomeStorage -cmn net/minecraft/world/level/chunk/ChunkGenerator -cmo net/minecraft/world/level/chunk/IChunkProvider -cmp net/minecraft/world/level/chunk/ChunkStatus -cmp$a net/minecraft/world/level/chunk/ChunkStatus$Type -cmq net/minecraft/world/level/chunk/NibbleArray -cmr net/minecraft/world/level/chunk/ChunkEmpty -cms net/minecraft/world/level/chunk/IStructureAccess -cmt net/minecraft/world/level/chunk/DataPaletteGlobal -cmu net/minecraft/world/level/chunk/DataPaletteHash -cmv net/minecraft/world/level/chunk/ProtoChunkExtension -cmw net/minecraft/world/level/chunk/Chunk -cmw$b net/minecraft/world/level/chunk/Chunk$EnumTileEntityState -cmx net/minecraft/world/level/chunk/ChunkSection -cmy net/minecraft/world/level/chunk/ILightAccess -cmz net/minecraft/world/level/chunk/DataPaletteLinear -cn net/minecraft/advancements/critereon/CriterionTriggerPlayerInteractedWithEntity -cna net/minecraft/world/level/chunk/OldNibbleArray -cnb net/minecraft/world/level/chunk/DataPalette -cnc net/minecraft/world/level/chunk/DataPaletteExpandable -cnd net/minecraft/world/level/chunk/DataPaletteBlock -cne net/minecraft/world/level/chunk/ProtoChunk -cnf net/minecraft/world/level/chunk/ProtoChunkTickList -cng net/minecraft/world/level/chunk/ChunkConverter -cng$b net/minecraft/world/level/chunk/ChunkConverter$Type -cni net/minecraft/world/level/chunk/storage/ChunkRegionLoader -cnj net/minecraft/world/level/chunk/storage/IChunkLoader -cnk net/minecraft/world/level/chunk/storage/EntityStorage -cnl net/minecraft/world/level/chunk/storage/IOWorker -cnl$b net/minecraft/world/level/chunk/storage/IOWorker$Priority -cnm net/minecraft/world/level/chunk/storage/OldChunkLoader -cnm$a net/minecraft/world/level/chunk/storage/OldChunkLoader$OldChunk -cnn net/minecraft/world/level/chunk/storage/RegionFileBitSet -cno net/minecraft/world/level/chunk/storage/RegionFile -cno$a net/minecraft/world/level/chunk/storage/RegionFile$ChunkBuffer -cnp net/minecraft/world/level/chunk/storage/RegionFileCache -cnq net/minecraft/world/level/chunk/storage/RegionFileCompression -cnr net/minecraft/world/level/chunk/storage/RegionFileSection -cnu net/minecraft/world/level/dimension/DimensionManager -cnv net/minecraft/world/level/dimension/WorldDimension -cnw net/minecraft/world/level/dimension/end/EnumDragonRespawn -cnx net/minecraft/world/level/dimension/end/EnderDragonBattle -co net/minecraft/advancements/critereon/CriterionConditionPlayer -coa net/minecraft/world/level/entity/ChunkEntities -cob net/minecraft/world/level/entity/ChunkStatusUpdateListener -coc net/minecraft/world/level/entity/EntityAccess -cod net/minecraft/world/level/entity/EntityInLevelCallback -coe net/minecraft/world/level/entity/EntityLookup -cof net/minecraft/world/level/entity/EntityPersistentStorage -cog net/minecraft/world/level/entity/EntitySection -coh net/minecraft/world/level/entity/EntitySectionStorage -coi net/minecraft/world/level/entity/EntityTickList -coj net/minecraft/world/level/entity/EntityTypeTest -cok net/minecraft/world/level/entity/LevelCallback -col net/minecraft/world/level/entity/LevelEntityGetter -com net/minecraft/world/level/entity/LevelEntityGetterAdapter -coo net/minecraft/world/level/entity/PersistentEntitySectionManager -coq net/minecraft/world/level/entity/Visibility -cos net/minecraft/world/level/gameevent/BlockPositionSource -cot net/minecraft/world/level/gameevent/EntityPositionSource -cou net/minecraft/world/level/gameevent/EuclideanGameEventDispatcher -cov net/minecraft/world/level/gameevent/GameEvent -cow net/minecraft/world/level/gameevent/GameEventDispatcher -cox net/minecraft/world/level/gameevent/GameEventListener -coy net/minecraft/world/level/gameevent/GameEventListenerRegistrar -coz net/minecraft/world/level/gameevent/PositionSource -cp net/minecraft/advancements/critereon/CriterionTriggerRecipeUnlocked -cpa net/minecraft/world/level/gameevent/PositionSourceType -cpc net/minecraft/world/level/gameevent/vibrations/VibrationListener -cpd net/minecraft/world/level/gameevent/vibrations/VibrationPath -cpf net/minecraft/world/level/levelgen/Aquifer -cpg net/minecraft/world/level/levelgen/BaseStoneSource -cph net/minecraft/world/level/levelgen/Beardifier -cpi net/minecraft/world/level/levelgen/Cavifier -cpj net/minecraft/world/level/levelgen/Column -cpk net/minecraft/world/level/levelgen/ChunkProviderDebug -cpl net/minecraft/world/level/levelgen/IDecoratable -cpm net/minecraft/world/level/levelgen/DepthBasedReplacingBaseStoneSource -cpn net/minecraft/world/level/levelgen/ChunkProviderFlat -cpo net/minecraft/world/level/levelgen/WorldGenStage -cpo$a net/minecraft/world/level/levelgen/WorldGenStage$Features -cpo$b net/minecraft/world/level/levelgen/WorldGenStage$Decoration -cpp net/minecraft/world/level/levelgen/GeodeBlockSettings -cpq net/minecraft/world/level/levelgen/GeodeCrackSettings -cpr net/minecraft/world/level/levelgen/GeodeLayerSettings -cps net/minecraft/world/level/levelgen/HeightMap -cps$a net/minecraft/world/level/levelgen/HeightMap$Type -cps$b net/minecraft/world/level/levelgen/HeightMap$Use -cpt net/minecraft/world/level/levelgen/ChunkGeneratorAbstract -cpu net/minecraft/world/level/levelgen/GeneratorSettingBase -cpv net/minecraft/world/level/levelgen/NoiseInterpolator -cpw net/minecraft/world/level/levelgen/NoiseModifier -cpx net/minecraft/world/level/levelgen/NoiseSampler -cpy net/minecraft/world/level/levelgen/NoiseSamplingSettings -cpz net/minecraft/world/level/levelgen/NoiseSettings -cq net/minecraft/advancements/critereon/LootSerializationContext -cqa net/minecraft/world/level/levelgen/NoiseSlideSettings -cqb net/minecraft/world/level/levelgen/NoodleCavifier -cqc net/minecraft/world/level/levelgen/OreVeinifier -cqd net/minecraft/world/level/levelgen/MobSpawnerPatrol -cqe net/minecraft/world/level/levelgen/MobSpawnerPhantom -cqf net/minecraft/world/level/levelgen/RandomSource -cqg net/minecraft/world/level/levelgen/SimpleRandomSource -cqh net/minecraft/world/level/levelgen/SingleBaseStoneSource -cqi net/minecraft/world/level/levelgen/StructureSettings -cqj net/minecraft/world/level/levelgen/VerticalAnchor -cqk net/minecraft/world/level/levelgen/GeneratorSettings -cql net/minecraft/world/level/levelgen/WorldGenerationContext -cqm net/minecraft/world/level/levelgen/SeededRandom -cqn net/minecraft/world/level/levelgen/carver/CanyonCarverConfiguration -cqo net/minecraft/world/level/levelgen/carver/WorldGenCanyon -cqp net/minecraft/world/level/levelgen/carver/WorldGenCarverConfiguration -cqq net/minecraft/world/level/levelgen/carver/CarverDebugSettings -cqr net/minecraft/world/level/levelgen/carver/CarvingContext -cqs net/minecraft/world/level/levelgen/carver/CaveCarverConfiguration -cqt net/minecraft/world/level/levelgen/carver/WorldGenCaves -cqu net/minecraft/world/level/levelgen/carver/WorldGenCarverWrapper -cqv net/minecraft/world/level/levelgen/carver/WorldGenCavesHell -cqw net/minecraft/world/level/levelgen/carver/WorldGenCanyonOcean -cqx net/minecraft/world/level/levelgen/carver/WorldGenCavesOcean -cqy net/minecraft/world/level/levelgen/carver/WorldGenCarverAbstract -cr net/minecraft/advancements/critereon/CriterionTriggerShotCrossbow -cra net/minecraft/world/level/levelgen/feature/WorldGenFlowers -crb net/minecraft/world/level/levelgen/feature/WorldGenMushrooms -crc net/minecraft/world/level/levelgen/feature/WorldGenFeatureBamboo -crd net/minecraft/world/level/levelgen/feature/WorldGenFeatureBasaltColumns -cre net/minecraft/world/level/levelgen/feature/WorldGenFeatureBasaltPillar -crf net/minecraft/world/level/levelgen/feature/WorldGenFeatureDisk -crg net/minecraft/world/level/levelgen/feature/WorldGenFeatureBastionRemnant -crh net/minecraft/world/level/levelgen/feature/WorldGenTaigaStructure -cri net/minecraft/world/level/levelgen/feature/WorldGenFeatureBlockPile -crj net/minecraft/world/level/levelgen/feature/WorldGenFeatureBlueIce -crk net/minecraft/world/level/levelgen/feature/WorldGenBonusChest -crl net/minecraft/world/level/levelgen/feature/WorldGenBuriedTreasure -crm net/minecraft/world/level/levelgen/feature/WorldGenFeatureChorusPlant -crn net/minecraft/world/level/levelgen/feature/WorldGenFeatureConfigured -cro net/minecraft/world/level/levelgen/feature/StructureFeature -crp net/minecraft/world/level/levelgen/feature/WorldGenFeatureCoralClaw -crq net/minecraft/world/level/levelgen/feature/WorldGenFeatureCoral -crr net/minecraft/world/level/levelgen/feature/WorldGenFeatureCoralMushroom -crs net/minecraft/world/level/levelgen/feature/WorldGenFeatureCoralTree -crt net/minecraft/world/level/levelgen/feature/WorldGenFeatureComposite -cru net/minecraft/world/level/levelgen/feature/WorldGenFeatureFlower -crv net/minecraft/world/level/levelgen/feature/WorldGenFeatureDelta -crw net/minecraft/world/level/levelgen/feature/WorldGenFeatureDesertPyramid -crx net/minecraft/world/level/levelgen/feature/WorldGenDesertWell -cry net/minecraft/world/level/levelgen/feature/WorldGenFeatureCircle -crz net/minecraft/world/level/levelgen/feature/DripstoneClusterFeature -cs net/minecraft/advancements/critereon/CriterionTriggerAbstract -csa net/minecraft/world/level/levelgen/feature/DripstoneUtils -csb net/minecraft/world/level/levelgen/feature/WorldGenEndCity -csc net/minecraft/world/level/levelgen/feature/WorldGenEndGateway -csd net/minecraft/world/level/levelgen/feature/WorldGenEndIsland -cse net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy -csf net/minecraft/world/level/levelgen/feature/WorldGenerator -csg net/minecraft/world/level/levelgen/feature/FeaturePlaceContext -csh net/minecraft/world/level/levelgen/feature/WorldGenFeatureFill -csi net/minecraft/world/level/levelgen/feature/WorldGenFossils -csj net/minecraft/world/level/levelgen/feature/FossilFeatureConfiguration -csk net/minecraft/world/level/levelgen/feature/GeodeFeature -csl net/minecraft/world/level/levelgen/feature/GlowLichenFeature -csm net/minecraft/world/level/levelgen/feature/WorldGenLightStone1 -csn net/minecraft/world/level/levelgen/feature/GrowingPlantFeature -cso net/minecraft/world/level/levelgen/feature/WorldGenHugeMushroomBrown -csp net/minecraft/world/level/levelgen/feature/WorldGenFeatureHugeFungiConfiguration -csq net/minecraft/world/level/levelgen/feature/WorldGenFeatureHugeFungi -csr net/minecraft/world/level/levelgen/feature/WorldGenHugeMushroomRed -css net/minecraft/world/level/levelgen/feature/WorldGenPackedIce1 -cst net/minecraft/world/level/levelgen/feature/WorldGenPackedIce2 -csu net/minecraft/world/level/levelgen/feature/WorldGenFeatureIceburg -csv net/minecraft/world/level/levelgen/feature/WorldGenFeatureIgloo -csw net/minecraft/world/level/levelgen/feature/WorldGenFeatureJigsaw -csx net/minecraft/world/level/levelgen/feature/WorldGenFeatureJunglePyramid -csy net/minecraft/world/level/levelgen/feature/WorldGenFeatureKelp -csz net/minecraft/world/level/levelgen/feature/WorldGenLakes -ct net/minecraft/advancements/critereon/CriterionSlideDownBlock -cta net/minecraft/world/level/levelgen/feature/LargeDripstoneFeature -ctb net/minecraft/world/level/levelgen/feature/WorldGenMineshaft -ctb$b net/minecraft/world/level/levelgen/feature/WorldGenMineshaft$Type -ctc net/minecraft/world/level/levelgen/feature/WorldGenDungeons -ctd net/minecraft/world/level/levelgen/feature/WorldGenFeatureNetherForestVegetation -cte net/minecraft/world/level/levelgen/feature/WorldGenNether -ctf net/minecraft/world/level/levelgen/feature/WorldGenFeatureEmpty -ctg net/minecraft/world/level/levelgen/feature/NoiseEffect -cth net/minecraft/world/level/levelgen/feature/WorldGenMonument -cti net/minecraft/world/level/levelgen/feature/WorldGenMinable -ctj net/minecraft/world/level/levelgen/feature/WorldGenFeaturePillagerOutpost -ctk net/minecraft/world/level/levelgen/feature/WorldGenFeatureChoice -ctl net/minecraft/world/level/levelgen/feature/WorldGenFeatureRandomPatch -ctm net/minecraft/world/level/levelgen/feature/WorldGenFeatureRandomChoice -ctn net/minecraft/world/level/levelgen/feature/WorldGenFeatureNetherrackReplaceBlobs -cto net/minecraft/world/level/levelgen/feature/WorldGenFeatureReplaceBlock -ctp net/minecraft/world/level/levelgen/feature/RootSystemFeature -ctq net/minecraft/world/level/levelgen/feature/WorldGenFeatureRuinedPortal -ctq$b net/minecraft/world/level/levelgen/feature/WorldGenFeatureRuinedPortal$Type -ctr net/minecraft/world/level/levelgen/feature/ScatteredOreFeature -cts net/minecraft/world/level/levelgen/feature/WorldGenFeatureSeaPickel -ctt net/minecraft/world/level/levelgen/feature/WorldGenFeatureSeaGrass -ctu net/minecraft/world/level/levelgen/feature/WorldGenFeatureShipwreck -ctv net/minecraft/world/level/levelgen/feature/WorldGenFeatureBlock -ctw net/minecraft/world/level/levelgen/feature/WorldGenFeatureRandom2Configuration -ctx net/minecraft/world/level/levelgen/feature/SmallDripstoneFeature -cty net/minecraft/world/level/levelgen/feature/WorldGenFeatureIceSnow -ctz net/minecraft/world/level/levelgen/feature/WorldGenEnder -ctz$a net/minecraft/world/level/levelgen/feature/WorldGenEnder$Spike -cu net/minecraft/advancements/critereon/StartRidingTrigger -cua net/minecraft/world/level/levelgen/feature/WorldGenLiquids -cub net/minecraft/world/level/levelgen/feature/WorldGenStronghold -cuc net/minecraft/world/level/levelgen/feature/StructureGenerator -cud net/minecraft/world/level/levelgen/feature/WorldGenFeatureStructurePieceType -cue net/minecraft/world/level/levelgen/feature/WorldGenFeatureSwampHut -cuf net/minecraft/world/level/levelgen/feature/WorldGenTrees -cug net/minecraft/world/level/levelgen/feature/WorldGenFeatureTwistingVines -cuh net/minecraft/world/level/levelgen/feature/UnderwaterMagmaFeature -cui net/minecraft/world/level/levelgen/feature/VegetationPatchFeature -cuj net/minecraft/world/level/levelgen/feature/WorldGenVillage -cuk net/minecraft/world/level/levelgen/feature/WorldGenVines -cul net/minecraft/world/level/levelgen/feature/WorldGenFeatureEndPlatform -cum net/minecraft/world/level/levelgen/feature/WaterloggedVegetationPatchFeature -cun net/minecraft/world/level/levelgen/feature/WorldGenFeatureWeepingVines -cuo net/minecraft/world/level/levelgen/feature/WorldGenFeatureRandomChoiceConfigurationWeight -cup net/minecraft/world/level/levelgen/feature/WorldGenWoodlandMansion -cuq net/minecraft/world/level/levelgen/feature/blockplacers/WorldGenBlockPlacer -cur net/minecraft/world/level/levelgen/feature/blockplacers/WorldGenBlockPlacers -cus net/minecraft/world/level/levelgen/feature/blockplacers/WorldGenBlockPlacerColumn -cut net/minecraft/world/level/levelgen/feature/blockplacers/WorldGenBlockPlacerDoublePlant -cuu net/minecraft/world/level/levelgen/feature/blockplacers/WorldGenBlockPlacerSimple -cuw net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureBlockPileConfiguration -cux net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureLakeConfiguration -cuy net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureBasaltColumnsConfiguration -cuz net/minecraft/world/level/levelgen/feature/configurations/WorldGenDecoratorFrequencyConfiguration -cv net/minecraft/advancements/critereon/CriterionTriggerProperties -cva net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureCompositeConfiguration -cvb net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureDecoratorConfiguration -cvc net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureDeltaConfiguration -cvd net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureCircleConfiguration -cve net/minecraft/world/level/levelgen/feature/configurations/DripstoneClusterConfiguration -cvf net/minecraft/world/level/levelgen/feature/configurations/WorldGenEndGatewayConfiguration -cvg net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureConfiguration -cvh net/minecraft/world/level/levelgen/feature/configurations/GeodeConfiguration -cvi net/minecraft/world/level/levelgen/feature/configurations/GlowLichenConfiguration -cvj net/minecraft/world/level/levelgen/feature/configurations/GrowingPlantConfiguration -cvk net/minecraft/world/level/levelgen/feature/configurations/HeightmapConfiguration -cvl net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureMushroomConfiguration -cvm net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureVillageConfiguration -cvn net/minecraft/world/level/levelgen/feature/configurations/LargeDripstoneConfiguration -cvo net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureFillConfiguration -cvp net/minecraft/world/level/levelgen/feature/configurations/WorldGenMineshaftConfiguration -cvq net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureDecoratorNoiseConfiguration -cvr net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureEmptyConfiguration2 -cvs net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureEmptyConfiguration -cvt net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureOceanRuinConfiguration -cvu net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureOreConfiguration -cvu$a net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureOreConfiguration$Target -cvv net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureConfigurationChance -cvw net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureChoiceConfiguration -cvx net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureRandomChoiceConfiguration -cvy net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureRandomPatchConfiguration -cvz net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureChanceDecoratorRangeConfiguration -cw net/minecraft/advancements/critereon/CriterionTriggerSummonedEntity -cwa net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureReplaceBlockConfiguration -cwb net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureRadiusConfiguration -cwc net/minecraft/world/level/levelgen/feature/configurations/RootSystemConfiguration -cwd net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureRuinedPortalConfiguration -cwe net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureShipwreckConfiguration -cwf net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureBlockConfiguration -cwg net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureRandom2 -cwh net/minecraft/world/level/levelgen/feature/configurations/SmallDripstoneConfiguration -cwi net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureEndSpikeConfiguration -cwj net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureHellFlowingLavaConfiguration -cwk net/minecraft/world/level/levelgen/feature/configurations/StructureSettingsStronghold -cwl net/minecraft/world/level/levelgen/feature/configurations/StructureSettingsFeature -cwm net/minecraft/world/level/levelgen/feature/configurations/WorldGenFeatureTreeConfiguration -cwn net/minecraft/world/level/levelgen/feature/configurations/UnderwaterMagmaConfiguration -cwo net/minecraft/world/level/levelgen/feature/configurations/VegetationPatchConfiguration -cwq net/minecraft/world/level/levelgen/feature/featuresize/FeatureSize -cwr net/minecraft/world/level/levelgen/feature/featuresize/FeatureSizeType -cws net/minecraft/world/level/levelgen/feature/featuresize/FeatureSizeThreeLayers -cwt net/minecraft/world/level/levelgen/feature/featuresize/FeatureSizeTwoLayers -cwv net/minecraft/world/level/levelgen/feature/foliageplacers/WorldGenFoilagePlacerAcacia -cww net/minecraft/world/level/levelgen/feature/foliageplacers/WorldGenFoilagePlacerBlob -cwx net/minecraft/world/level/levelgen/feature/foliageplacers/WorldGenFoilagePlacerBush -cwy net/minecraft/world/level/levelgen/feature/foliageplacers/WorldGenFoilagePlacerDarkOak -cwz net/minecraft/world/level/levelgen/feature/foliageplacers/WorldGenFoilagePlacerFancy -cx net/minecraft/advancements/critereon/CriterionTriggerTamedAnimal -cxa net/minecraft/world/level/levelgen/feature/foliageplacers/WorldGenFoilagePlacer -cxb net/minecraft/world/level/levelgen/feature/foliageplacers/WorldGenFoilagePlacers -cxc net/minecraft/world/level/levelgen/feature/foliageplacers/WorldGenFoilagePlacerJungle -cxd net/minecraft/world/level/levelgen/feature/foliageplacers/WorldGenFoilagePlacerMegaPine -cxe net/minecraft/world/level/levelgen/feature/foliageplacers/WorldGenFoilagePlacerPine -cxf net/minecraft/world/level/levelgen/feature/foliageplacers/RandomSpreadFoliagePlacer -cxg net/minecraft/world/level/levelgen/feature/foliageplacers/WorldGenFoilagePlacerSpruce -cxj net/minecraft/world/level/levelgen/feature/stateproviders/WorldGenFeatureStateProvider -cxk net/minecraft/world/level/levelgen/feature/stateproviders/WorldGenFeatureStateProviders -cxl net/minecraft/world/level/levelgen/feature/stateproviders/WorldGenFeatureStateProviderForestFlower -cxm net/minecraft/world/level/levelgen/feature/stateproviders/WorldGenFeatureStateProviderPlainFlower -cxn net/minecraft/world/level/levelgen/feature/stateproviders/RandomizedIntStateProvider -cxo net/minecraft/world/level/levelgen/feature/stateproviders/WorldGenFeatureStateProviderRotatedBlock -cxp net/minecraft/world/level/levelgen/feature/stateproviders/WorldGenFeatureStateProviderSimpl -cxq net/minecraft/world/level/levelgen/feature/stateproviders/WorldGenFeatureStateProviderWeighted -cxs net/minecraft/world/level/levelgen/feature/structures/WorldGenFeatureDefinedStructurePoolEmpty -cxt net/minecraft/world/level/levelgen/feature/structures/WorldGenFeatureDefinedStructurePoolFeature -cxu net/minecraft/world/level/levelgen/feature/structures/WorldGenFeatureDefinedStructureJigsawJunction -cxv net/minecraft/world/level/levelgen/feature/structures/WorldGenFeatureDefinedStructureJigsawPlacement -cxw net/minecraft/world/level/levelgen/feature/structures/WorldGenFeatureDefinedStructurePoolLegacySingle -cxx net/minecraft/world/level/levelgen/feature/structures/WorldGenFeatureDefinedStructurePoolList -cxy net/minecraft/world/level/levelgen/feature/structures/WorldGenFeatureDefinedStructurePoolSingle -cxz net/minecraft/world/level/levelgen/feature/structures/WorldGenFeatureDefinedStructurePoolStructure -cy net/minecraft/advancements/critereon/CriterionTriggerTargetHit -cya net/minecraft/world/level/levelgen/feature/structures/WorldGenFeatureDefinedStructurePools -cyb net/minecraft/world/level/levelgen/feature/structures/WorldGenFeatureDefinedStructurePoolTemplate -cyb$a net/minecraft/world/level/levelgen/feature/structures/WorldGenFeatureDefinedStructurePoolTemplate$Matching -cyd net/minecraft/world/level/levelgen/feature/treedecorators/WorldGenFeatureTreeAlterGround -cye net/minecraft/world/level/levelgen/feature/treedecorators/WorldGenFeatureTreeBeehive -cyf net/minecraft/world/level/levelgen/feature/treedecorators/WorldGenFeatureTreeCocoa -cyg net/minecraft/world/level/levelgen/feature/treedecorators/WorldGenFeatureTreeVineLeaves -cyh net/minecraft/world/level/levelgen/feature/treedecorators/WorldGenFeatureTree -cyi net/minecraft/world/level/levelgen/feature/treedecorators/WorldGenFeatureTrees -cyj net/minecraft/world/level/levelgen/feature/treedecorators/WorldGenFeatureTreeVineTrunk -cyl net/minecraft/world/level/levelgen/feature/trunkplacers/BendingTrunkPlacer -cym net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacerDarkOak -cyn net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacerFancy -cyo net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacerForking -cyp net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacerGiant -cyq net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacerMegaJungle -cyr net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacerStraight -cys net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacer -cyt net/minecraft/world/level/levelgen/feature/trunkplacers/TrunkPlacers -cyv net/minecraft/world/level/levelgen/flat/WorldGenFlatLayerInfo -cyw net/minecraft/world/level/levelgen/flat/GeneratorSettingsFlat -cyy net/minecraft/world/level/levelgen/heightproviders/BiasedToBottomHeight -cyz net/minecraft/world/level/levelgen/heightproviders/ConstantHeight -cz net/minecraft/advancements/critereon/CriterionTriggerTick -cza net/minecraft/world/level/levelgen/heightproviders/HeightProvider -czb net/minecraft/world/level/levelgen/heightproviders/HeightProviderType -czc net/minecraft/world/level/levelgen/heightproviders/TrapezoidHeight -czd net/minecraft/world/level/levelgen/heightproviders/UniformHeight -cze net/minecraft/world/level/levelgen/heightproviders/VeryBiasedToBottomHeight -czh net/minecraft/world/level/levelgen/placement/WorldGenDecoratorCarveMask -czi net/minecraft/world/level/levelgen/placement/WorldGenDecoratorCarveMaskConfiguration -czj net/minecraft/world/level/levelgen/placement/CaveDecoratorConfiguration -czk net/minecraft/world/level/levelgen/placement/CaveSurface -czl net/minecraft/world/level/levelgen/placement/CaveSurfaceDecorator -czm net/minecraft/world/level/levelgen/placement/WorldGenDecoratorChance -czn net/minecraft/world/level/levelgen/placement/WorldGenDecoratorDungeonConfiguration -czo net/minecraft/world/level/levelgen/placement/WorldGenDecoratorConfigured -czp net/minecraft/world/level/levelgen/placement/WorldGenDecoratorCount -czq net/minecraft/world/level/levelgen/placement/WorldGenDecoratorCountNoise -czr net/minecraft/world/level/levelgen/placement/WorldGenDecoratorCountExtra -czs net/minecraft/world/level/levelgen/placement/WorldGenDecoratorRoofedTree -czt net/minecraft/world/level/levelgen/placement/WorldGenDecoratorDecorated -czu net/minecraft/world/level/levelgen/placement/WorldGenDecoratorDecpratedConfiguration -czv net/minecraft/world/level/levelgen/placement/WorldGenDecoratorContext -czw net/minecraft/world/level/levelgen/placement/WorldGenDecoratorEndGateway -czx net/minecraft/world/level/levelgen/placement/WorldGenDecorator -czy net/minecraft/world/level/levelgen/placement/WorldGenDecoratorFrequencyExtraChanceConfiguration -czz net/minecraft/world/level/levelgen/placement/WorldGenDecoratorHeightmap -d com/mojang/math/Matrix4f -da net/minecraft/advancements/critereon/CriterionTriggerVillagerTrade -daa net/minecraft/world/level/levelgen/placement/WorldGenDecoratorHeightmapSpreadDouble -dab net/minecraft/world/level/levelgen/placement/WorldGenDecoratorIceburg -dac net/minecraft/world/level/levelgen/placement/WorldGenDecoratorLakeLava -dad net/minecraft/world/level/levelgen/placement/WorldGenDecoratorCountNoiseBiased -dae net/minecraft/world/level/levelgen/placement/WorldGenDecoratorNoiseConfiguration -daf net/minecraft/world/level/levelgen/placement/WorldGenDecoratorEmpty -dag net/minecraft/world/level/levelgen/placement/WorldGenDecoratorRange -dah net/minecraft/world/level/levelgen/placement/RepeatingDecorator -dai net/minecraft/world/level/levelgen/placement/WorldGenDecoratorSpread32Above -daj net/minecraft/world/level/levelgen/placement/WorldGenDecoratorSquare -dak net/minecraft/world/level/levelgen/placement/VerticalDecorator -dal net/minecraft/world/level/levelgen/placement/WaterDepthThresholdConfiguration -dam net/minecraft/world/level/levelgen/placement/WaterDepthThresholdDecorator -dan net/minecraft/world/level/levelgen/placement/nether/WorldGenDecoratorCountMultilayer -daq net/minecraft/world/level/levelgen/structure/StructureBoundingBox -dar net/minecraft/world/level/levelgen/structure/WorldGenBuriedTreasurePieces -das net/minecraft/world/level/levelgen/structure/WorldGenDesertPyramidPiece -dat net/minecraft/world/level/levelgen/structure/WorldGenEndCityPieces -dat$a net/minecraft/world/level/levelgen/structure/WorldGenEndCityPieces$Piece -dat$b net/minecraft/world/level/levelgen/structure/WorldGenEndCityPieces$PieceGenerator -dau net/minecraft/world/level/levelgen/structure/WorldGenIglooPiece -dav net/minecraft/world/level/levelgen/structure/WorldGenJunglePyramidPiece -daw net/minecraft/world/level/levelgen/structure/PersistentStructureLegacy -dax net/minecraft/world/level/levelgen/structure/WorldGenMineshaftPieces -dax$a net/minecraft/world/level/levelgen/structure/WorldGenMineshaftPieces$WorldGenMineshaftCorridor -dax$b net/minecraft/world/level/levelgen/structure/WorldGenMineshaftPieces$WorldGenMineshaftCross -dax$d net/minecraft/world/level/levelgen/structure/WorldGenMineshaftPieces$WorldGenMineshaftRoom -dax$e net/minecraft/world/level/levelgen/structure/WorldGenMineshaftPieces$WorldGenMineshaftStairs -day net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces -day$a net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece1 -day$b net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece2 -day$c net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece3 -day$d net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece4 -day$e net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece5 -day$f net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece6 -day$g net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece7 -day$h net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece8 -day$i net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece9 -day$j net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece10 -day$k net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece11 -day$l net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece12 -day$m net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece -day$n net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPieceWeight -day$o net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece13 -day$p net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece14 -day$q net/minecraft/world/level/levelgen/structure/WorldGenNetherPieces$WorldGenNetherPiece15 -daz net/minecraft/world/level/levelgen/structure/WorldGenFeatureNetherFossil -db net/minecraft/advancements/critereon/CriterionTriggerUsedEnderEye -dba net/minecraft/world/level/levelgen/structure/WorldGenNetherFossil -dbb net/minecraft/world/level/levelgen/structure/NoiseAffectingStructureStart -dbc net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces -dbc$a net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPieceSelector7 -dbc$b net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPieceSelector6 -dbc$c net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPieceSelector5 -dbc$d net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPieceSelector4 -dbc$e net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPieceSelector3 -dbc$f net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPieceSelector2 -dbc$g net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPieceSelector1 -dbc$h net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPiece1 -dbc$i net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$IWorldGenMonumentPieceSelector -dbc$j net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPiece2 -dbc$k net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPiece3 -dbc$l net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPiece4 -dbc$m net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPiece5 -dbc$n net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPiece6 -dbc$o net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPiece7 -dbc$p net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPieceEntry -dbc$q net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPiecePenthouse -dbc$r net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPiece -dbc$s net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPieceSimple -dbc$t net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPieceSimpleT -dbc$u net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentPiece8 -dbc$v net/minecraft/world/level/levelgen/structure/WorldGenMonumentPieces$WorldGenMonumentStateTracker -dbd net/minecraft/world/level/levelgen/structure/WorldGenFeatureOceanRuin -dbd$b net/minecraft/world/level/levelgen/structure/WorldGenFeatureOceanRuin$Temperature -dbe net/minecraft/world/level/levelgen/structure/WorldGenFeatureOceanRuinPieces -dbf net/minecraft/world/level/levelgen/structure/WorldGenFeaturePillagerOutpostPoolPiece -dbg net/minecraft/world/level/levelgen/structure/WorldGenFeatureRuinedPortalPieces -dbg$b net/minecraft/world/level/levelgen/structure/WorldGenFeatureRuinedPortalPieces$Position -dbh net/minecraft/world/level/levelgen/structure/WorldGenScatteredPiece -dbi net/minecraft/world/level/levelgen/structure/WorldGenShipwreck -dbj net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces -dbj$a net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdChestCorridor -dbj$b net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdCorridor -dbj$c net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdCrossing -dbj$d net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdLeftTurn -dbj$e net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdLibrary -dbj$f net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdPieceWeight -dbj$g net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdPortalRoom -dbj$h net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdPrison -dbj$i net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdRightTurn -dbj$j net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdRoomCrossing -dbj$k net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdStones -dbj$l net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdStairs2 -dbj$m net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdStart -dbj$n net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdStairs -dbj$o net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdStairsStraight -dbj$p net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdPiece -dbj$p$a net/minecraft/world/level/levelgen/structure/WorldGenStrongholdPieces$WorldGenStrongholdPiece$WorldGenStrongholdDoorType -dbk net/minecraft/world/level/levelgen/structure/PersistentIndexed -dbl net/minecraft/world/level/levelgen/structure/StructurePiece -dbl$a net/minecraft/world/level/levelgen/structure/StructurePiece$StructurePieceBlockSelector -dbm net/minecraft/world/level/levelgen/structure/StructurePieceAccessor -dbn net/minecraft/world/level/levelgen/structure/StructureStart -dbo net/minecraft/world/level/levelgen/structure/WorldGenWitchHut -dbp net/minecraft/world/level/levelgen/structure/DefinedStructurePiece -dbq net/minecraft/world/level/levelgen/structure/WorldGenWoodlandMansionPieces -dbs net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureTestTrue -dbt net/minecraft/world/level/levelgen/structure/templatesystem/PosRuleTestAxisAlignedLinear -dbu net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureProcessorBlackstoneReplace -dbv net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureProcessorBlockAge -dbw net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureProcessorBlockIgnore -dbx net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureTestBlock -dby net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureProcessorRotation -dbz net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureTestBlockState -dc net/minecraft/advancements/critereon/CriterionTriggerUsedTotem -dca net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureProcessorGravity -dcb net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureProcessorJigsawReplacement -dcc net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureProcessorLavaSubmergedBlock -dcd net/minecraft/world/level/levelgen/structure/templatesystem/PosRuleTestLinear -dce net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureProcessorNop -dcf net/minecraft/world/level/levelgen/structure/templatesystem/PosRuleTestTrue -dcg net/minecraft/world/level/levelgen/structure/templatesystem/PosRuleTest -dch net/minecraft/world/level/levelgen/structure/templatesystem/PosRuleTestType -dci net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureProcessorPredicates -dcj net/minecraft/world/level/levelgen/structure/templatesystem/ProtectedBlockProcessor -dck net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureTestRandomBlock -dcl net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureTestRandomBlockState -dcm net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureProcessorRule -dcn net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureRuleTest -dco net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureRuleTestType -dcp net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureManager -dcq net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureInfo -dcr net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureProcessor -dcs net/minecraft/world/level/levelgen/structure/templatesystem/ProcessorList -dct net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureStructureProcessorType -dcu net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure -dcu$c net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure$BlockInfo -dcu$d net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure$EntityInfo -dcv net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureTestTag -dcx net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceMesa -dcy net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceBasaltDeltas -dcz net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceComposite -dd net/minecraft/advancements/critereon/UsingItemTrigger -dda net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceDefaultBlock -ddb net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceMesaBryce -ddc net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceFrozenOcean -ddd net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceTaigaMega -dde net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceExtremeHillMutated -ddf net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceExtremeHills -ddg net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract -ddh net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest -ddi net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether -ddj net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceEmpty -ddk net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceSavannaMutated -ddl net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceSoulSandValley -ddm net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurface -ddn net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceConfigurationBase -ddo net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceConfiguration -ddp net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceSwamp -ddq net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceMesaForest -dds net/minecraft/world/level/levelgen/synth/BlendedNoise -ddt net/minecraft/world/level/levelgen/synth/NoiseGeneratorPerlin -ddu net/minecraft/world/level/levelgen/synth/NoiseUtils -ddv net/minecraft/world/level/levelgen/synth/NoiseGeneratorNormal -ddw net/minecraft/world/level/levelgen/synth/NoiseGeneratorOctaves -ddx net/minecraft/world/level/levelgen/synth/NoiseGenerator3 -ddy net/minecraft/world/level/levelgen/synth/NoiseGenerator3Handler -ddz net/minecraft/world/level/levelgen/synth/NoiseGenerator -de net/minecraft/advancements/critereon/CriterionConditionRange -deb net/minecraft/world/level/lighting/LightEngineBlock -dec net/minecraft/world/level/lighting/LightEngineStorageBlock -ded net/minecraft/world/level/lighting/LightEngineStorageArray -dee net/minecraft/world/level/lighting/LightEngineGraph -def net/minecraft/world/level/lighting/NibbleArrayFlat -deg net/minecraft/world/level/lighting/LightEngineLayer -deh net/minecraft/world/level/lighting/LightEngineLayerEventListener -deh$a net/minecraft/world/level/lighting/LightEngineLayerEventListener$Void -dei net/minecraft/world/level/lighting/LightEngineStorage -dej net/minecraft/world/level/lighting/LightEngine -dek net/minecraft/world/level/lighting/ILightEngine -del net/minecraft/world/level/lighting/LightEngineSky -dem net/minecraft/world/level/lighting/LightEngineStorageSky -dep net/minecraft/world/level/material/FluidTypeEmpty -deq net/minecraft/world/level/material/FluidTypeFlowing -der net/minecraft/world/level/material/FluidType -des net/minecraft/world/level/material/Fluid -det net/minecraft/world/level/material/FluidTypes -dev net/minecraft/world/level/material/FluidTypeLava -dew net/minecraft/world/level/material/Material -dex net/minecraft/world/level/material/MaterialMapColor -dey net/minecraft/world/level/material/EnumPistonReaction -dez net/minecraft/world/level/material/FluidTypeWater -dfb net/minecraft/world/level/newbiome/area/Area -dfc net/minecraft/world/level/newbiome/area/AreaFactory -dfd net/minecraft/world/level/newbiome/area/AreaLazy -dff net/minecraft/world/level/newbiome/context/AreaContextTransformed -dfg net/minecraft/world/level/newbiome/context/WorldGenContext -dfh net/minecraft/world/level/newbiome/context/WorldGenContextArea -dfj net/minecraft/world/level/newbiome/layer/GenLayerDeepOcean -dfk net/minecraft/world/level/newbiome/layer/GenLayerSpecial -dfk$a net/minecraft/world/level/newbiome/layer/GenLayerSpecial$Special1 -dfk$b net/minecraft/world/level/newbiome/layer/GenLayerSpecial$Special2 -dfk$c net/minecraft/world/level/newbiome/layer/GenLayerSpecial$Special3 -dfl net/minecraft/world/level/newbiome/layer/GenLayerIsland -dfm net/minecraft/world/level/newbiome/layer/GenLayerMushroomIsland -dfn net/minecraft/world/level/newbiome/layer/GenLayerTopSoil -dfo net/minecraft/world/level/newbiome/layer/GenLayerDesert -dfp net/minecraft/world/level/newbiome/layer/GenLayerBiome -dfq net/minecraft/world/level/newbiome/layer/LayerIsland -dfr net/minecraft/world/level/newbiome/layer/GenLayer -dfs net/minecraft/world/level/newbiome/layer/LayerBiomes -dft net/minecraft/world/level/newbiome/layer/GenLayers -dft$a net/minecraft/world/level/newbiome/layer/GenLayers$Type -dfu net/minecraft/world/level/newbiome/layer/GenLayerOceanEdge -dfv net/minecraft/world/level/newbiome/layer/GenLayerOcean -dfw net/minecraft/world/level/newbiome/layer/GenLayerJungle -dfx net/minecraft/world/level/newbiome/layer/GenLayerPlains -dfy net/minecraft/world/level/newbiome/layer/GenLayerRegionHills -dfz net/minecraft/world/level/newbiome/layer/GenLayerIcePlains -dga net/minecraft/world/level/newbiome/layer/GenLayerCleaner -dgb net/minecraft/world/level/newbiome/layer/GenLayerRiver -dgc net/minecraft/world/level/newbiome/layer/GenLayerRiverMix -dgd net/minecraft/world/level/newbiome/layer/GenLayerMushroomShore -dge net/minecraft/world/level/newbiome/layer/GenLayerSmooth -dgf net/minecraft/world/level/newbiome/layer/GenLayerZoom -dgh net/minecraft/world/level/newbiome/layer/traits/AreaTransformer1 -dgi net/minecraft/world/level/newbiome/layer/traits/AreaTransformer2 -dgj net/minecraft/world/level/newbiome/layer/traits/AreaTransformer3 -dgk net/minecraft/world/level/newbiome/layer/traits/AreaTransformer4 -dgl net/minecraft/world/level/newbiome/layer/traits/AreaTransformer5 -dgm net/minecraft/world/level/newbiome/layer/traits/AreaTransformer6 -dgn net/minecraft/world/level/newbiome/layer/traits/AreaTransformer7 -dgo net/minecraft/world/level/newbiome/layer/traits/AreaTransformerIdentity -dgp net/minecraft/world/level/newbiome/layer/traits/AreaTransformerOffset1 -dgq net/minecraft/world/level/newbiome/layer/traits/AreaTransformer -dgr net/minecraft/world/level/newbiome/layer/traits/AreaTransformer8 -dgu net/minecraft/world/level/pathfinder/AmphibiousNodeEvaluator -dgv net/minecraft/world/level/pathfinder/Path -dgw net/minecraft/world/level/pathfinder/PathType -dgx net/minecraft/world/level/pathfinder/PathfinderFlying -dgy net/minecraft/world/level/pathfinder/PathPoint -dgz net/minecraft/world/level/pathfinder/PathfinderAbstract -dh net/minecraft/commands/CommandExceptionProvider -dha net/minecraft/world/level/pathfinder/PathEntity -dhb net/minecraft/world/level/pathfinder/PathMode -dhc net/minecraft/world/level/pathfinder/Pathfinder -dhd net/minecraft/world/level/pathfinder/PathfinderWater -dhe net/minecraft/world/level/pathfinder/PathDestination -dhf net/minecraft/world/level/pathfinder/PathfinderNormal -dhh net/minecraft/world/level/portal/PortalTravelAgent -dhi net/minecraft/world/level/portal/ShapeDetectorShape -dhj net/minecraft/world/level/portal/BlockPortalShape -dhn net/minecraft/world/level/saveddata/PersistentBase -dho net/minecraft/world/level/saveddata/maps/MapIconBanner -dhp net/minecraft/world/level/saveddata/maps/MapIcon -dhp$a net/minecraft/world/level/saveddata/maps/MapIcon$Type -dhq net/minecraft/world/level/saveddata/maps/WorldMapFrame -dhr net/minecraft/world/level/saveddata/maps/PersistentIdCounts -dhs net/minecraft/world/level/saveddata/maps/WorldMap -dhs$a net/minecraft/world/level/saveddata/maps/WorldMap$WorldMapHumanTracker -dhv net/minecraft/world/level/storage/PersistentCommandStorage -dhw net/minecraft/world/level/storage/SecondaryWorldData -dhx net/minecraft/world/level/storage/WorldPersistentData -dhy net/minecraft/world/level/storage/WorldData -dhz net/minecraft/world/level/storage/SavedFile -di net/minecraft/commands/CustomFunction -dia net/minecraft/world/level/storage/LevelStorageException -dib net/minecraft/world/level/storage/Convertable -dib$a net/minecraft/world/level/storage/Convertable$ConversionSession -dic net/minecraft/world/level/storage/WorldInfo -did net/minecraft/world/level/storage/LevelVersion -die net/minecraft/world/level/storage/WorldUpgraderIterator -dif net/minecraft/world/level/storage/WorldNBTStorage -dig net/minecraft/world/level/storage/WorldDataServer -dih net/minecraft/world/level/storage/IWorldDataServer -dii net/minecraft/world/level/storage/SaveData -dij net/minecraft/world/level/storage/WorldDataMutable -dik net/minecraft/world/level/storage/loot/LootTables -dil net/minecraft/world/level/storage/loot/LootSerialization -dim net/minecraft/world/level/storage/loot/JsonRegistry -din net/minecraft/world/level/storage/loot/IntRange -dio net/minecraft/world/level/storage/loot/ItemModifierManager -dip net/minecraft/world/level/storage/loot/LootTableInfo -dip$a net/minecraft/world/level/storage/loot/LootTableInfo$Builder -dip$c net/minecraft/world/level/storage/loot/LootTableInfo$EntityTarget -diq net/minecraft/world/level/storage/loot/LootItemUser -dir net/minecraft/world/level/storage/loot/LootSelector -dis net/minecraft/world/level/storage/loot/LootTable -dit net/minecraft/world/level/storage/loot/LootTableRegistry -diu net/minecraft/world/level/storage/loot/LootPredicateManager -div net/minecraft/world/level/storage/loot/LootSerializer -diw net/minecraft/world/level/storage/loot/LootSerializerType -dix net/minecraft/world/level/storage/loot/LootCollector -diy net/minecraft/world/level/storage/loot/entries/LootEntryAlternatives -diz net/minecraft/world/level/storage/loot/entries/LootEntryChildren -dj net/minecraft/commands/CommandException -dja net/minecraft/world/level/storage/loot/entries/LootEntryChildrenAbstract -djb net/minecraft/world/level/storage/loot/entries/LootSelectorDynamic -djc net/minecraft/world/level/storage/loot/entries/LootSelectorEmpty -djd net/minecraft/world/level/storage/loot/entries/LootEntryGroup -dje net/minecraft/world/level/storage/loot/entries/LootItem -djf net/minecraft/world/level/storage/loot/entries/LootEntries -djg net/minecraft/world/level/storage/loot/entries/LootEntry -djh net/minecraft/world/level/storage/loot/entries/LootEntryAbstract -djh$b net/minecraft/world/level/storage/loot/entries/LootEntryAbstract$Serializer -dji net/minecraft/world/level/storage/loot/entries/LootEntryType -djj net/minecraft/world/level/storage/loot/entries/LootSelectorEntry -djk net/minecraft/world/level/storage/loot/entries/LootSelectorLootTable -djl net/minecraft/world/level/storage/loot/entries/LootEntrySequence -djm net/minecraft/world/level/storage/loot/entries/LootSelectorTag -djo net/minecraft/world/level/storage/loot/functions/LootItemFunctionApplyBonus -djp net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplosionDecay -djq net/minecraft/world/level/storage/loot/functions/LootItemFunctionCopyState -djr net/minecraft/world/level/storage/loot/functions/LootItemFunctionCopyName -djr$a net/minecraft/world/level/storage/loot/functions/LootItemFunctionCopyName$Source -djs net/minecraft/world/level/storage/loot/functions/LootItemFunctionCopyNBT -djs$c net/minecraft/world/level/storage/loot/functions/LootItemFunctionCopyNBT$Action -djt net/minecraft/world/level/storage/loot/functions/LootItemFunctionEnchant -dju net/minecraft/world/level/storage/loot/functions/LootEnchantLevel -djv net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap -djw net/minecraft/world/level/storage/loot/functions/LootItemFunctionFillPlayerHead -djx net/minecraft/world/level/storage/loot/functions/LootItemFunctionUser -djy net/minecraft/world/level/storage/loot/functions/LootItemFunctionLimitCount -djz net/minecraft/world/level/storage/loot/functions/LootItemFunctionConditional -dk net/minecraft/commands/ICommandListener -dka net/minecraft/world/level/storage/loot/functions/LootItemFunction -dkb net/minecraft/world/level/storage/loot/functions/LootItemFunctionType -dkc net/minecraft/world/level/storage/loot/functions/LootItemFunctions -dkd net/minecraft/world/level/storage/loot/functions/LootEnchantFunction -dke net/minecraft/world/level/storage/loot/functions/LootItemFunctionSetAttribute -dkf net/minecraft/world/level/storage/loot/functions/SetBannerPatternFunction -dkg net/minecraft/world/level/storage/loot/functions/LootItemFunctionSetContents -dkh net/minecraft/world/level/storage/loot/functions/LootItemFunctionSetTable -dki net/minecraft/world/level/storage/loot/functions/SetEnchantmentsFunction -dkj net/minecraft/world/level/storage/loot/functions/LootItemFunctionSetCount -dkk net/minecraft/world/level/storage/loot/functions/LootItemFunctionSetDamage -dkl net/minecraft/world/level/storage/loot/functions/LootItemFunctionSetLore -dkm net/minecraft/world/level/storage/loot/functions/LootItemFunctionSetName -dkn net/minecraft/world/level/storage/loot/functions/LootItemFunctionSetTag -dko net/minecraft/world/level/storage/loot/functions/LootItemFunctionSetStewEffect -dkp net/minecraft/world/level/storage/loot/functions/LootItemFunctionSmelt -dks net/minecraft/world/level/storage/loot/parameters/LootContextParameter -dkt net/minecraft/world/level/storage/loot/parameters/LootContextParameterSet -dkt$a net/minecraft/world/level/storage/loot/parameters/LootContextParameterSet$Builder -dku net/minecraft/world/level/storage/loot/parameters/LootContextParameterSets -dkv net/minecraft/world/level/storage/loot/parameters/LootContextParameters -dkx net/minecraft/world/level/storage/loot/predicates/LootItemConditionAlternative -dky net/minecraft/world/level/storage/loot/predicates/LootItemConditionTableBonus -dkz net/minecraft/world/level/storage/loot/predicates/LootItemConditionReference -dl net/minecraft/commands/CommandListenerWrapper -dla net/minecraft/world/level/storage/loot/predicates/LootItemConditionUser -dlb net/minecraft/world/level/storage/loot/predicates/LootItemConditionDamageSourceProperties -dlc net/minecraft/world/level/storage/loot/predicates/LootItemConditionEntityScore -dld net/minecraft/world/level/storage/loot/predicates/LootItemConditionSurvivesExplosion -dle net/minecraft/world/level/storage/loot/predicates/LootItemConditionInverted -dlf net/minecraft/world/level/storage/loot/predicates/LootItemConditionLocationCheck -dlg net/minecraft/world/level/storage/loot/predicates/LootItemConditionBlockStateProperty -dlh net/minecraft/world/level/storage/loot/predicates/LootItemCondition -dli net/minecraft/world/level/storage/loot/predicates/LootItemConditionType -dlj net/minecraft/world/level/storage/loot/predicates/LootItemConditions -dlk net/minecraft/world/level/storage/loot/predicates/LootItemConditionEntityProperty -dll net/minecraft/world/level/storage/loot/predicates/LootItemConditionKilledByPlayer -dlm net/minecraft/world/level/storage/loot/predicates/LootItemConditionRandomChance -dln net/minecraft/world/level/storage/loot/predicates/LootItemConditionRandomChanceWithLooting -dlo net/minecraft/world/level/storage/loot/predicates/LootItemConditionMatchTool -dlp net/minecraft/world/level/storage/loot/predicates/LootItemConditionTimeCheck -dlq net/minecraft/world/level/storage/loot/predicates/ValueCheckCondition -dlr net/minecraft/world/level/storage/loot/predicates/LootItemConditionWeatherCheck -dlt net/minecraft/world/level/storage/loot/providers/nbt/ContextNbtProvider -dlu net/minecraft/world/level/storage/loot/providers/nbt/LootNbtProviderType -dlv net/minecraft/world/level/storage/loot/providers/nbt/NbtProvider -dlw net/minecraft/world/level/storage/loot/providers/nbt/NbtProviders -dlx net/minecraft/world/level/storage/loot/providers/nbt/StorageNbtProvider -dlz net/minecraft/world/level/storage/loot/providers/number/BinomialDistributionGenerator -dm net/minecraft/commands/CommandDispatcher -dm$a net/minecraft/commands/CommandDispatcher$ServerType -dma net/minecraft/world/level/storage/loot/providers/number/ConstantValue -dmb net/minecraft/world/level/storage/loot/providers/number/LootNumberProviderType -dmc net/minecraft/world/level/storage/loot/providers/number/NumberProvider -dmd net/minecraft/world/level/storage/loot/providers/number/NumberProviders -dme net/minecraft/world/level/storage/loot/providers/number/ScoreboardValue -dmf net/minecraft/world/level/storage/loot/providers/number/UniformGenerator -dmh net/minecraft/world/level/storage/loot/providers/score/ContextScoreboardNameProvider -dmi net/minecraft/world/level/storage/loot/providers/score/FixedScoreboardNameProvider -dmj net/minecraft/world/level/storage/loot/providers/score/LootScoreProviderType -dmk net/minecraft/world/level/storage/loot/providers/score/ScoreboardNameProvider -dml net/minecraft/world/level/storage/loot/providers/score/ScoreboardNameProviders -dmo net/minecraft/world/level/timers/CustomFunctionCallback -dmp net/minecraft/world/level/timers/CustomFunctionCallbackTag -dmq net/minecraft/world/level/timers/CustomFunctionCallbackTimer -dmr net/minecraft/world/level/timers/CustomFunctionCallbackTimers -dms net/minecraft/world/level/timers/CustomFunctionCallbackTimerQueue -dmv net/minecraft/world/phys/AxisAlignedBB -dmw net/minecraft/world/phys/MovingObjectPositionBlock -dmx net/minecraft/world/phys/MovingObjectPositionEntity -dmy net/minecraft/world/phys/MovingObjectPosition -dmy$a net/minecraft/world/phys/MovingObjectPosition$EnumMovingObjectType -dmz net/minecraft/world/phys/Vec2F -dn net/minecraft/commands/ICompletionProvider -dna net/minecraft/world/phys/Vec3D -dnc net/minecraft/world/phys/shapes/VoxelShapeArray -dnd net/minecraft/world/phys/shapes/VoxelShapeBitSet -dne net/minecraft/world/phys/shapes/OperatorBoolean -dnf net/minecraft/world/phys/shapes/VoxelShapeCollision -dng net/minecraft/world/phys/shapes/VoxelShapeCubePoint -dnh net/minecraft/world/phys/shapes/VoxelShapeCube -dni net/minecraft/world/phys/shapes/VoxelShapeCubeMerger -dnj net/minecraft/world/phys/shapes/VoxelShapeDiscrete -dnk net/minecraft/world/phys/shapes/VoxelShapeCollisionEntity -dnl net/minecraft/world/phys/shapes/VoxelShapeMergerIdentical -dnm net/minecraft/world/phys/shapes/VoxelShapeMerger -dnn net/minecraft/world/phys/shapes/VoxelShapeMergerList -dno net/minecraft/world/phys/shapes/VoxelShapeMergerDisjoint -dnp net/minecraft/world/phys/shapes/DoubleListOffset -dnq net/minecraft/world/phys/shapes/VoxelShapes -dnr net/minecraft/world/phys/shapes/VoxelShapeSlice -dns net/minecraft/world/phys/shapes/VoxelShapeDiscreteSlice -dnt net/minecraft/world/phys/shapes/VoxelShape -dnv net/minecraft/world/scores/ScoreboardObjective -dnw net/minecraft/world/scores/ScoreboardTeam -dnx net/minecraft/world/scores/ScoreboardScore -dny net/minecraft/world/scores/Scoreboard -dnz net/minecraft/world/scores/PersistentScoreboard -doa net/minecraft/world/scores/ScoreboardTeamBase -doa$a net/minecraft/world/scores/ScoreboardTeamBase$EnumTeamPush -doa$b net/minecraft/world/scores/ScoreboardTeamBase$EnumNameTagVisibility -dob net/minecraft/world/scores/criteria/IScoreboardCriteria -dob$a net/minecraft/world/scores/criteria/IScoreboardCriteria$EnumScoreboardHealthDisplay -dp net/minecraft/commands/arguments/ArgumentAngle -dq net/minecraft/commands/arguments/ArgumentChatFormat -dr net/minecraft/commands/arguments/ArgumentChatComponent -ds net/minecraft/commands/arguments/ArgumentNBTTag -dt net/minecraft/commands/arguments/ArgumentDimension -du net/minecraft/commands/arguments/ArgumentAnchor -du$a net/minecraft/commands/arguments/ArgumentAnchor$Anchor -dv net/minecraft/commands/arguments/ArgumentEntity -dw net/minecraft/commands/arguments/ArgumentEntitySummon -dx net/minecraft/commands/arguments/ArgumentProfile -dy net/minecraft/commands/arguments/ArgumentEnchantment -dz net/minecraft/commands/arguments/ArgumentChat -ea net/minecraft/commands/arguments/ArgumentMobEffect -eb net/minecraft/commands/arguments/ArgumentNBTKey -ec net/minecraft/commands/arguments/ArgumentNBTBase -ed net/minecraft/commands/arguments/ArgumentScoreboardObjective -ee net/minecraft/commands/arguments/ArgumentScoreboardCriteria -ef net/minecraft/commands/arguments/ArgumentMathOperation -eg net/minecraft/commands/arguments/ArgumentParticle -eh net/minecraft/commands/arguments/ArgumentCriterionValue -ei net/minecraft/commands/arguments/ArgumentMinecraftKeyRegistered -ej net/minecraft/commands/arguments/ArgumentScoreholder -ek net/minecraft/commands/arguments/ArgumentScoreboardSlot -el net/minecraft/commands/arguments/ArgumentInventorySlot -em net/minecraft/commands/arguments/ArgumentScoreboardTeam -en net/minecraft/commands/arguments/ArgumentTime -eo net/minecraft/commands/arguments/ArgumentUUID -ep net/minecraft/commands/arguments/blocks/ArgumentTileLocation -eq net/minecraft/commands/arguments/blocks/ArgumentBlockPredicate -er net/minecraft/commands/arguments/blocks/ArgumentTile -es net/minecraft/commands/arguments/blocks/ArgumentBlock -eu net/minecraft/commands/arguments/coordinates/ArgumentPosition -ev net/minecraft/commands/arguments/coordinates/ArgumentVec2I -ew net/minecraft/commands/arguments/coordinates/IVectorPosition -ex net/minecraft/commands/arguments/coordinates/ArgumentVectorPosition -ey net/minecraft/commands/arguments/coordinates/ArgumentRotation -ez net/minecraft/commands/arguments/coordinates/ArgumentRotationAxis -f com/mojang/math/PointGroupO -fa net/minecraft/commands/arguments/coordinates/ArgumentVec2 -fb net/minecraft/commands/arguments/coordinates/ArgumentVec3 -fc net/minecraft/commands/arguments/coordinates/ArgumentParserPosition -fd net/minecraft/commands/arguments/coordinates/VectorPosition -ff net/minecraft/commands/arguments/item/ArgumentTag -fg net/minecraft/commands/arguments/item/ArgumentItemStack -fh net/minecraft/commands/arguments/item/ArgumentPredicateItemStack -fi net/minecraft/commands/arguments/item/ArgumentParserItemStack -fj net/minecraft/commands/arguments/item/ArgumentItemPredicate -fm net/minecraft/commands/arguments/selector/EntitySelector -fn net/minecraft/commands/arguments/selector/ArgumentParserSelector -fo net/minecraft/commands/arguments/selector/options/PlayerSelector -fs net/minecraft/commands/synchronization/ArgumentSerializer -ft net/minecraft/commands/synchronization/ArgumentRegistry -fu net/minecraft/commands/synchronization/ArgumentSerializerVoid -fv net/minecraft/commands/synchronization/CompletionProviders -fw net/minecraft/commands/synchronization/brigadier/ArgumentSerializers -fx net/minecraft/commands/synchronization/brigadier/ArgumentSerializerDouble -fy net/minecraft/commands/synchronization/brigadier/ArgumentSerializerFloat -fz net/minecraft/commands/synchronization/brigadier/ArgumentSerializerInteger -g com/mojang/math/Quaternion -ga net/minecraft/commands/synchronization/brigadier/ArgumentSerializerLong -gb net/minecraft/commands/synchronization/brigadier/ArgumentSerializerString -ge net/minecraft/core/EnumAxisCycle -gg net/minecraft/core/BlockPosition -gg$a net/minecraft/core/BlockPosition$MutableBlockPosition -gh net/minecraft/core/ISourceBlock -gi net/minecraft/core/SourceBlock -gj net/minecraft/core/CursorPosition -gk net/minecraft/core/RegistryBlocks -gl net/minecraft/core/EnumDirection -gl$a net/minecraft/core/EnumDirection$EnumAxis -gl$b net/minecraft/core/EnumDirection$EnumAxisDirection -gl$c net/minecraft/core/EnumDirection$EnumDirectionLimit -gm net/minecraft/core/EnumDirection8 -gn net/minecraft/core/BlockPropertyJigsawOrientation -go net/minecraft/core/GlobalPos -gp net/minecraft/core/Registry -gq net/minecraft/core/RegistryBlockID -gr net/minecraft/core/RegistryMaterials -gs net/minecraft/core/NonNullList -gt net/minecraft/core/IPosition -gu net/minecraft/core/Position -gv net/minecraft/core/QuartPos -gw net/minecraft/core/IRegistry -gx net/minecraft/core/IRegistryCustom -gx$b net/minecraft/core/IRegistryCustom$Dimension -gy net/minecraft/core/Vector3f -gz net/minecraft/core/SectionPosition -h com/mojang/math/PointGroupS -ha net/minecraft/core/MinecraftSerializableUUID -hb net/minecraft/core/BaseBlockPosition -hc net/minecraft/core/IRegistryWritable -hd net/minecraft/core/cauldron/CauldronInteraction -he net/minecraft/core/dispenser/DispenseBehaviorProjectile -hf net/minecraft/core/dispenser/DispenseBehaviorBoat -hg net/minecraft/core/dispenser/DispenseBehaviorItem -hh net/minecraft/core/dispenser/IDispenseBehavior -hi net/minecraft/core/dispenser/DispenseBehaviorMaybe -hj net/minecraft/core/dispenser/DispenseBehaviorShears -hk net/minecraft/core/dispenser/DispenseBehaviorShulkerBox -hn net/minecraft/core/particles/ParticleParamBlock -ho net/minecraft/core/particles/DustColorTransitionOptions -hp net/minecraft/core/particles/ParticleParamRedstone -hq net/minecraft/core/particles/DustParticleOptionsBase -hr net/minecraft/core/particles/ParticleParamItem -ht net/minecraft/core/particles/ParticleParam -hu net/minecraft/core/particles/Particle -hv net/minecraft/core/particles/Particles -hw net/minecraft/core/particles/ParticleType -hx net/minecraft/core/particles/VibrationParticleOption -ib net/minecraft/data/RegistryGeneration -ic net/minecraft/data/DebugReportGenerator -id net/minecraft/data/DebugReportProvider -ie net/minecraft/data/HashCache -k com/mojang/math/Vector3fa -kg net/minecraft/data/structures/DebugReportNBT -kh net/minecraft/data/structures/SnbtToNbt -ki net/minecraft/data/structures/StructureUpdater -kr net/minecraft/data/worldgen/WorldGenFeatureBastionBridge -ks net/minecraft/data/worldgen/WorldGenFeatureBastionHoglinStable -kt net/minecraft/data/worldgen/WorldGenFeatureBastionUnits -ku net/minecraft/data/worldgen/WorldGenFeatureBastionPieces -kv net/minecraft/data/worldgen/WorldGenFeatureBastionExtra -kw net/minecraft/data/worldgen/WorldGenFeatureBastionTreasure -kx net/minecraft/data/worldgen/BiomeSettings -ky net/minecraft/data/worldgen/WorldGenCarvers -kz net/minecraft/data/worldgen/WorldGenFeatureDesertVillage -l com/mojang/math/Vector4f -la net/minecraft/data/worldgen/BiomeDecoratorGroups -lb net/minecraft/data/worldgen/WorldGenFeaturePillagerOutpostPieces -lc net/minecraft/data/worldgen/WorldGenFeatureVillagePlain -ld net/minecraft/data/worldgen/WorldGenFeaturePieces -le net/minecraft/data/worldgen/ProcessorLists -lf net/minecraft/data/worldgen/WorldGenFeatureVillageSavanna -lg net/minecraft/data/worldgen/WorldGenFeatureVillageSnowy -lh net/minecraft/data/worldgen/StructureFeatures -li net/minecraft/data/worldgen/WorldGenSurfaceComposites -lj net/minecraft/data/worldgen/WorldGenFeatureVillageTaiga -lk net/minecraft/data/worldgen/WorldGenFeatureVillages -lm net/minecraft/data/worldgen/biome/BiomeRegistry -ln net/minecraft/data/worldgen/biome/BiomesSettingsDefault -lp net/minecraft/gametest/framework/AfterBatch -lq net/minecraft/gametest/framework/BeforeBatch -lr net/minecraft/gametest/framework/ExhaustedAttemptsException -ls net/minecraft/gametest/framework/GameTest -lt net/minecraft/gametest/framework/GameTestHarnessAssertion -lu net/minecraft/gametest/framework/GameTestHarnessAssertionPosition -lv net/minecraft/gametest/framework/GameTestHarnessBatch -lw net/minecraft/gametest/framework/GameTestHarnessBatchRunner -lx net/minecraft/gametest/framework/GameTestHarnessEvent -ly net/minecraft/gametest/framework/GameTestGenerator -lz net/minecraft/gametest/framework/GameTestHarnessHelper -ma net/minecraft/gametest/framework/GameTestHarnessInfo -mb net/minecraft/gametest/framework/GameTestHarnessListener -mc net/minecraft/gametest/framework/GameTestHarnessRegistry -md net/minecraft/gametest/framework/GameTestHarnessRunner -me net/minecraft/gametest/framework/GameTestHarnessSequence -mg net/minecraft/gametest/framework/GameTestHarnessTicker -mh net/minecraft/gametest/framework/GameTestHarnessTimeout -mi net/minecraft/gametest/framework/GlobalTestReporter -mk net/minecraft/gametest/framework/GameTestHarnessLogger -ml net/minecraft/gametest/framework/GameTestHarnessCollector -mm net/minecraft/gametest/framework/ReportGameListener -mn net/minecraft/gametest/framework/GameTestHarnessStructures -mp net/minecraft/gametest/framework/GameTestHarnessTestClassArgument -mq net/minecraft/gametest/framework/GameTestHarnessTestCommand -mr net/minecraft/gametest/framework/GameTestHarnessTestFunction -ms net/minecraft/gametest/framework/GameTestHarnessTestFunctionArgument -mt net/minecraft/gametest/framework/GameTestHarnessITestReporter -mv net/minecraft/locale/LocaleLanguage -mx net/minecraft/nbt/NBTTagByteArray -my net/minecraft/nbt/NBTTagByte -mz net/minecraft/nbt/NBTList -n net/minecraft/BlockUtil -n$a net/minecraft/BlockUtil$Rectangle -n$b net/minecraft/BlockUtil$IntBounds -na net/minecraft/nbt/NBTTagCompound -nb net/minecraft/nbt/NBTTagDouble -nc net/minecraft/nbt/NBTTagEnd -nd net/minecraft/nbt/NBTTagFloat -ne net/minecraft/nbt/NBTTagIntArray -net/minecraft/server/Main net/minecraft/server/Main -net/minecraft/server/MinecraftServer net/minecraft/server/MinecraftServer -nf net/minecraft/nbt/NBTTagInt -ng net/minecraft/nbt/NBTTagList -nh net/minecraft/nbt/NBTTagLongArray -ni net/minecraft/nbt/NBTTagLong -nj net/minecraft/nbt/NBTReadLimiter -nk net/minecraft/nbt/NBTCompressedStreamTools -nl net/minecraft/nbt/DynamicOpsNBT -nm net/minecraft/nbt/GameProfileSerializer -nn net/minecraft/nbt/NBTNumber -no net/minecraft/nbt/NBTTagShort -np net/minecraft/nbt/SnbtPrinterTagVisitor -nq net/minecraft/nbt/NBTTagString -nr net/minecraft/nbt/StringTagVisitor -ns net/minecraft/nbt/NBTBase -nt net/minecraft/nbt/MojangsonParser -nu net/minecraft/nbt/NBTTagType -nv net/minecraft/nbt/NBTTagTypes -nw net/minecraft/nbt/TagVisitor -nx net/minecraft/nbt/TextComponentTagVisitor -nz net/minecraft/network/PacketEncryptionHandler -o net/minecraft/CharPredicate -oa net/minecraft/network/PacketDecrypter -ob net/minecraft/network/PacketEncrypter -oc net/minecraft/network/PacketDecompressor -od net/minecraft/network/PacketCompressor -oe net/minecraft/network/NetworkManager -oe$a net/minecraft/network/NetworkManager$QueuedPacket -of net/minecraft/network/EnumProtocol -og net/minecraft/network/PacketDataSerializer -oh net/minecraft/network/PacketDecoder -oi net/minecraft/network/PacketEncoder -oj net/minecraft/network/PacketListener -ok net/minecraft/network/NetworkManagerServer -ol net/minecraft/network/SkipEncodeException -om net/minecraft/network/PacketSplitter -on net/minecraft/network/PacketPrepender -oo net/minecraft/network/chat/ChatBaseComponent -op net/minecraft/network/chat/ChatMessageType -oq net/minecraft/network/chat/ChatClickable -oq$a net/minecraft/network/chat/ChatClickable$EnumClickAction -os net/minecraft/network/chat/IChatBaseComponent -os$a net/minecraft/network/chat/IChatBaseComponent$ChatSerializer -ot net/minecraft/network/chat/ChatComponentUtils -ou net/minecraft/network/chat/ChatComponentContextual -ov net/minecraft/network/chat/IChatFormatted -ow net/minecraft/network/chat/ChatHoverable -ow$a net/minecraft/network/chat/ChatHoverable$EnumHoverAction -ox net/minecraft/network/chat/ChatComponentKeybind -oy net/minecraft/network/chat/IChatMutableComponent -oz net/minecraft/network/chat/ChatComponentNBT -p net/minecraft/EnumChatFormat -pa net/minecraft/network/chat/ChatComponentScore -pb net/minecraft/network/chat/ChatComponentSelector -pc net/minecraft/network/chat/ChatModifier -pc$a net/minecraft/network/chat/ChatModifier$ChatModifierSerializer -pe net/minecraft/network/chat/ChatHexColor -pf net/minecraft/network/chat/ChatComponentText -pg net/minecraft/network/chat/ChatMessage -ph net/minecraft/network/chat/ChatMessageException -pk net/minecraft/network/protocol/Packet -pl net/minecraft/network/protocol/EnumProtocolDirection -pm net/minecraft/network/protocol/PlayerConnectionUtils -pn net/minecraft/network/protocol/game/PacketListenerPlayOut -po net/minecraft/network/protocol/game/PacketPlayOutSpawnEntity -pp net/minecraft/network/protocol/game/PacketPlayOutSpawnEntityExperienceOrb -pq net/minecraft/network/protocol/game/PacketPlayOutSpawnEntityLiving -pr net/minecraft/network/protocol/game/PacketPlayOutSpawnEntityPainting -ps net/minecraft/network/protocol/game/PacketPlayOutNamedEntitySpawn -pt net/minecraft/network/protocol/game/ClientboundAddVibrationSignalPacket -pu net/minecraft/network/protocol/game/PacketPlayOutAnimation -pv net/minecraft/network/protocol/game/PacketPlayOutStatistic -pw net/minecraft/network/protocol/game/PacketPlayOutBlockBreak -px net/minecraft/network/protocol/game/PacketPlayOutBlockBreakAnimation -py net/minecraft/network/protocol/game/PacketPlayOutTileEntityData -pz net/minecraft/network/protocol/game/PacketPlayOutBlockAction -q net/minecraft/CrashReport -qa net/minecraft/network/protocol/game/PacketPlayOutBlockChange -qb net/minecraft/network/protocol/game/PacketPlayOutBoss -qb$c net/minecraft/network/protocol/game/PacketPlayOutBoss$Action -qc net/minecraft/network/protocol/game/PacketPlayOutServerDifficulty -qd net/minecraft/network/protocol/game/PacketPlayOutChat -qe net/minecraft/network/protocol/game/ClientboundClearTitlesPacket -qf net/minecraft/network/protocol/game/PacketPlayOutTabComplete -qg net/minecraft/network/protocol/game/PacketPlayOutCommands -qh net/minecraft/network/protocol/game/PacketPlayOutCloseWindow -qi net/minecraft/network/protocol/game/PacketPlayOutWindowItems -qj net/minecraft/network/protocol/game/PacketPlayOutWindowData -qk net/minecraft/network/protocol/game/PacketPlayOutSetSlot -ql net/minecraft/network/protocol/game/PacketPlayOutSetCooldown -qm net/minecraft/network/protocol/game/PacketPlayOutCustomPayload -qn net/minecraft/network/protocol/game/PacketPlayOutCustomSoundEffect -qo net/minecraft/network/protocol/game/PacketPlayOutKickDisconnect -qp net/minecraft/network/protocol/game/PacketPlayOutEntityStatus -qq net/minecraft/network/protocol/game/PacketPlayOutExplosion -qr net/minecraft/network/protocol/game/PacketPlayOutUnloadChunk -qs net/minecraft/network/protocol/game/PacketPlayOutGameStateChange -qt net/minecraft/network/protocol/game/PacketPlayOutOpenWindowHorse -qu net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket -qv net/minecraft/network/protocol/game/PacketPlayOutKeepAlive -qw net/minecraft/network/protocol/game/PacketPlayOutMapChunk -qx net/minecraft/network/protocol/game/PacketPlayOutWorldEvent -qy net/minecraft/network/protocol/game/PacketPlayOutWorldParticles -qz net/minecraft/network/protocol/game/PacketPlayOutLightUpdate -r net/minecraft/CrashReportSystemDetails -r$a net/minecraft/CrashReportSystemDetails$CrashReportDetail -ra net/minecraft/network/protocol/game/PacketPlayOutLogin -rb net/minecraft/network/protocol/game/PacketPlayOutMap -rc net/minecraft/network/protocol/game/PacketPlayOutOpenWindowMerchant -rd net/minecraft/network/protocol/game/PacketPlayOutEntity -rd$a net/minecraft/network/protocol/game/PacketPlayOutEntity$PacketPlayOutRelEntityMove -rd$b net/minecraft/network/protocol/game/PacketPlayOutEntity$PacketPlayOutRelEntityMoveLook -rd$c net/minecraft/network/protocol/game/PacketPlayOutEntity$PacketPlayOutEntityLook -re net/minecraft/network/protocol/game/PacketPlayOutVehicleMove -rf net/minecraft/network/protocol/game/PacketPlayOutOpenBook -rg net/minecraft/network/protocol/game/PacketPlayOutOpenWindow -rh net/minecraft/network/protocol/game/PacketPlayOutOpenSignEditor -ri net/minecraft/network/protocol/game/ClientboundPingPacket -rj net/minecraft/network/protocol/game/PacketPlayOutAutoRecipe -rk net/minecraft/network/protocol/game/PacketPlayOutAbilities -rl net/minecraft/network/protocol/game/ClientboundPlayerCombatEndPacket -rm net/minecraft/network/protocol/game/ClientboundPlayerCombatEnterPacket -rn net/minecraft/network/protocol/game/ClientboundPlayerCombatKillPacket -ro net/minecraft/network/protocol/game/PacketPlayOutPlayerInfo -ro$a net/minecraft/network/protocol/game/PacketPlayOutPlayerInfo$EnumPlayerInfoAction -ro$b net/minecraft/network/protocol/game/PacketPlayOutPlayerInfo$PlayerInfoData -rp net/minecraft/network/protocol/game/PacketPlayOutLookAt -rq net/minecraft/network/protocol/game/PacketPlayOutPosition -rq$a net/minecraft/network/protocol/game/PacketPlayOutPosition$EnumPlayerTeleportFlags -rr net/minecraft/network/protocol/game/PacketPlayOutRecipes -rr$a net/minecraft/network/protocol/game/PacketPlayOutRecipes$Action -rs net/minecraft/network/protocol/game/PacketPlayOutEntityDestroy -rt net/minecraft/network/protocol/game/PacketPlayOutRemoveEntityEffect -ru net/minecraft/network/protocol/game/PacketPlayOutResourcePackSend -rv net/minecraft/network/protocol/game/PacketPlayOutRespawn -rw net/minecraft/network/protocol/game/PacketPlayOutEntityHeadRotation -rx net/minecraft/network/protocol/game/PacketPlayOutMultiBlockChange -ry net/minecraft/network/protocol/game/PacketPlayOutSelectAdvancementTab -rz net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket -s net/minecraft/CrashReportCallable -sa net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket -sb net/minecraft/network/protocol/game/ClientboundSetBorderLerpSizePacket -sc net/minecraft/network/protocol/game/ClientboundSetBorderSizePacket -sd net/minecraft/network/protocol/game/ClientboundSetBorderWarningDelayPacket -se net/minecraft/network/protocol/game/ClientboundSetBorderWarningDistancePacket -sf net/minecraft/network/protocol/game/PacketPlayOutCamera -sg net/minecraft/network/protocol/game/PacketPlayOutHeldItemSlot -sh net/minecraft/network/protocol/game/PacketPlayOutViewCentre -si net/minecraft/network/protocol/game/PacketPlayOutViewDistance -sj net/minecraft/network/protocol/game/PacketPlayOutSpawnPosition -sk net/minecraft/network/protocol/game/PacketPlayOutScoreboardDisplayObjective -sl net/minecraft/network/protocol/game/PacketPlayOutEntityMetadata -sm net/minecraft/network/protocol/game/PacketPlayOutAttachEntity -sn net/minecraft/network/protocol/game/PacketPlayOutEntityVelocity -so net/minecraft/network/protocol/game/PacketPlayOutEntityEquipment -sp net/minecraft/network/protocol/game/PacketPlayOutExperience -sq net/minecraft/network/protocol/game/PacketPlayOutUpdateHealth -sr net/minecraft/network/protocol/game/PacketPlayOutScoreboardObjective -ss net/minecraft/network/protocol/game/PacketPlayOutMount -st net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam -su net/minecraft/network/protocol/game/PacketPlayOutScoreboardScore -sv net/minecraft/network/protocol/game/ClientboundSetSubtitleTextPacket -sw net/minecraft/network/protocol/game/PacketPlayOutUpdateTime -sx net/minecraft/network/protocol/game/ClientboundSetTitleTextPacket -sy net/minecraft/network/protocol/game/ClientboundSetTitlesAnimationPacket -sz net/minecraft/network/protocol/game/PacketPlayOutEntitySound -t net/minecraft/DefaultUncaughtExceptionHandler -ta net/minecraft/network/protocol/game/PacketPlayOutNamedSoundEffect -tb net/minecraft/network/protocol/game/PacketPlayOutStopSound -tc net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter -td net/minecraft/network/protocol/game/PacketPlayOutNBTQuery -te net/minecraft/network/protocol/game/PacketPlayOutCollect -tf net/minecraft/network/protocol/game/PacketPlayOutEntityTeleport -tg net/minecraft/network/protocol/game/PacketPlayOutAdvancements -th net/minecraft/network/protocol/game/PacketPlayOutUpdateAttributes -th$a net/minecraft/network/protocol/game/PacketPlayOutUpdateAttributes$AttributeSnapshot -ti net/minecraft/network/protocol/game/PacketPlayOutEntityEffect -tj net/minecraft/network/protocol/game/PacketPlayOutRecipeUpdate -tk net/minecraft/network/protocol/game/PacketPlayOutTags -tl net/minecraft/network/protocol/game/DebugEntityNameGenerator -tm net/minecraft/network/protocol/game/PacketDebug -tn net/minecraft/network/protocol/game/PacketListenerPlayIn -to net/minecraft/network/protocol/game/PacketPlayInTeleportAccept -tp net/minecraft/network/protocol/game/PacketPlayInTileNBTQuery -tq net/minecraft/network/protocol/game/PacketPlayInDifficultyChange -tr net/minecraft/network/protocol/game/PacketPlayInChat -ts net/minecraft/network/protocol/game/PacketPlayInClientCommand -ts$a net/minecraft/network/protocol/game/PacketPlayInClientCommand$EnumClientCommand -tt net/minecraft/network/protocol/game/PacketPlayInSettings -tu net/minecraft/network/protocol/game/PacketPlayInTabComplete -tv net/minecraft/network/protocol/game/PacketPlayInEnchantItem -tw net/minecraft/network/protocol/game/PacketPlayInWindowClick -tx net/minecraft/network/protocol/game/PacketPlayInCloseWindow -ty net/minecraft/network/protocol/game/PacketPlayInCustomPayload -tz net/minecraft/network/protocol/game/PacketPlayInBEdit -u net/minecraft/ThreadNamedUncaughtExceptionHandler -ua net/minecraft/network/protocol/game/PacketPlayInEntityNBTQuery -ub net/minecraft/network/protocol/game/PacketPlayInUseEntity -ub$a net/minecraft/network/protocol/game/PacketPlayInUseEntity$EnumEntityUseAction -uc net/minecraft/network/protocol/game/PacketPlayInJigsawGenerate -ud net/minecraft/network/protocol/game/PacketPlayInKeepAlive -ue net/minecraft/network/protocol/game/PacketPlayInDifficultyLock -uf net/minecraft/network/protocol/game/PacketPlayInFlying -uf$a net/minecraft/network/protocol/game/PacketPlayInFlying$PacketPlayInPosition -uf$b net/minecraft/network/protocol/game/PacketPlayInFlying$PacketPlayInPositionLook -uf$c net/minecraft/network/protocol/game/PacketPlayInFlying$PacketPlayInLook -ug net/minecraft/network/protocol/game/PacketPlayInVehicleMove -uh net/minecraft/network/protocol/game/PacketPlayInBoatMove -ui net/minecraft/network/protocol/game/PacketPlayInPickItem -uj net/minecraft/network/protocol/game/PacketPlayInAutoRecipe -uk net/minecraft/network/protocol/game/PacketPlayInAbilities -ul net/minecraft/network/protocol/game/PacketPlayInBlockDig -ul$a net/minecraft/network/protocol/game/PacketPlayInBlockDig$EnumPlayerDigType -um net/minecraft/network/protocol/game/PacketPlayInEntityAction -um$a net/minecraft/network/protocol/game/PacketPlayInEntityAction$EnumPlayerAction -un net/minecraft/network/protocol/game/PacketPlayInSteerVehicle -uo net/minecraft/network/protocol/game/ServerboundPongPacket -up net/minecraft/network/protocol/game/PacketPlayInRecipeSettings -uq net/minecraft/network/protocol/game/PacketPlayInRecipeDisplayed -ur net/minecraft/network/protocol/game/PacketPlayInItemName -us net/minecraft/network/protocol/game/PacketPlayInResourcePackStatus -us$a net/minecraft/network/protocol/game/PacketPlayInResourcePackStatus$EnumResourcePackStatus -ut net/minecraft/network/protocol/game/PacketPlayInAdvancements -ut$a net/minecraft/network/protocol/game/PacketPlayInAdvancements$Status -uu net/minecraft/network/protocol/game/PacketPlayInTrSel -uv net/minecraft/network/protocol/game/PacketPlayInBeacon -uw net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot -ux net/minecraft/network/protocol/game/PacketPlayInSetCommandBlock -uy net/minecraft/network/protocol/game/PacketPlayInSetCommandMinecart -uz net/minecraft/network/protocol/game/PacketPlayInSetCreativeSlot -v net/minecraft/MinecraftVersion -va net/minecraft/network/protocol/game/PacketPlayInSetJigsaw -vb net/minecraft/network/protocol/game/PacketPlayInStruct -vc net/minecraft/network/protocol/game/PacketPlayInUpdateSign -vd net/minecraft/network/protocol/game/PacketPlayInArmAnimation -ve net/minecraft/network/protocol/game/PacketPlayInSpectate -vf net/minecraft/network/protocol/game/PacketPlayInUseItem -vg net/minecraft/network/protocol/game/PacketPlayInBlockPlace -vi net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol -vj net/minecraft/network/protocol/handshake/PacketHandshakingInListener -vl net/minecraft/network/protocol/login/PacketLoginOutListener -vm net/minecraft/network/protocol/login/PacketLoginOutCustomPayload -vn net/minecraft/network/protocol/login/PacketLoginOutSuccess -vo net/minecraft/network/protocol/login/PacketLoginOutEncryptionBegin -vp net/minecraft/network/protocol/login/PacketLoginOutSetCompression -vq net/minecraft/network/protocol/login/PacketLoginOutDisconnect -vr net/minecraft/network/protocol/login/PacketLoginInListener -vs net/minecraft/network/protocol/login/PacketLoginInCustomPayload -vt net/minecraft/network/protocol/login/PacketLoginInStart -vu net/minecraft/network/protocol/login/PacketLoginInEncryptionBegin -vx net/minecraft/network/protocol/status/PacketStatusOutListener -vy net/minecraft/network/protocol/status/PacketStatusOutPong -vz net/minecraft/network/protocol/status/PacketStatusOutServerInfo -wa net/minecraft/network/protocol/status/ServerPing -wa$a net/minecraft/network/protocol/status/ServerPing$ServerPingPlayerSample -wa$a$a net/minecraft/network/protocol/status/ServerPing$ServerPingPlayerSample$Serializer -wa$b net/minecraft/network/protocol/status/ServerPing$Serializer -wa$c net/minecraft/network/protocol/status/ServerPing$ServerData -wa$c$a net/minecraft/network/protocol/status/ServerPing$ServerData$Serializer -wb net/minecraft/network/protocol/status/PacketStatusInListener -wc net/minecraft/network/protocol/status/PacketStatusInPing -wd net/minecraft/network/protocol/status/PacketStatusInStart -wf net/minecraft/network/syncher/DataWatcherObject -wg net/minecraft/network/syncher/DataWatcherSerializer -wh net/minecraft/network/syncher/DataWatcherRegistry -wi net/minecraft/network/syncher/DataWatcher -wi$a net/minecraft/network/syncher/DataWatcher$Item -wm net/minecraft/recipebook/AutoRecipeAbstract -wn net/minecraft/recipebook/AutoRecipe -wp net/minecraft/resources/DynamicOpsWrapper -wq net/minecraft/resources/RegistryDataPackCodec -wr net/minecraft/resources/RegistryFileCodec -ws net/minecraft/resources/RegistryLookupCodec -wt net/minecraft/resources/RegistryReadOps -wu net/minecraft/resources/RegistryWriteOps -wv net/minecraft/resources/ResourceKey -ww net/minecraft/resources/MinecraftKey -wy net/minecraft/server/DispenserRegistry -x net/minecraft/FileUtils -xa net/minecraft/server/ServerCommand -xb net/minecraft/server/DebugOutputStream -xc net/minecraft/server/EULA -xd net/minecraft/server/RedirectStream -xe net/minecraft/server/AdvancementDataPlayer -xf net/minecraft/server/CancelledPacketHandleException -xg net/minecraft/server/AdvancementDataWorld -xh net/minecraft/server/CustomFunctionManager -xi net/minecraft/server/CustomFunctionData -xj net/minecraft/server/IMinecraftServer -xk net/minecraft/server/DataPackResources -xl net/minecraft/server/ScoreboardServer -xl$a net/minecraft/server/ScoreboardServer$Action -xm net/minecraft/server/TickTask -xn net/minecraft/server/bossevents/BossBattleCustom -xo net/minecraft/server/bossevents/BossBattleCustomData -xq net/minecraft/server/commands/CommandAdvancement -xq$a net/minecraft/server/commands/CommandAdvancement$Action -xq$b net/minecraft/server/commands/CommandAdvancement$Filter -xr net/minecraft/server/commands/CommandAttribute -xs net/minecraft/server/commands/CommandBanIp -xt net/minecraft/server/commands/CommandBanList -xu net/minecraft/server/commands/CommandBan -xv net/minecraft/server/commands/CommandBossBar -xw net/minecraft/server/commands/CommandClear -xx net/minecraft/server/commands/CommandClone -xx$a net/minecraft/server/commands/CommandClone$CommandCloneStoredTileEntity -xx$b net/minecraft/server/commands/CommandClone$Mode -xy net/minecraft/server/commands/CommandDatapack -xz net/minecraft/server/commands/CommandDeop -ya net/minecraft/server/commands/CommandDebug -yd net/minecraft/server/commands/CommandGamemodeDefault -ye net/minecraft/server/commands/CommandDifficulty -yf net/minecraft/server/commands/CommandEffect -yg net/minecraft/server/commands/CommandMe -yh net/minecraft/server/commands/CommandEnchant -yi net/minecraft/server/commands/CommandExecute -yj net/minecraft/server/commands/CommandXp -yj$a net/minecraft/server/commands/CommandXp$Unit -yk net/minecraft/server/commands/CommandFill -yk$a net/minecraft/server/commands/CommandFill$Mode -yl net/minecraft/server/commands/CommandForceload -ym net/minecraft/server/commands/CommandFunction -yn net/minecraft/server/commands/CommandGamemode -yo net/minecraft/server/commands/CommandGamerule -yp net/minecraft/server/commands/CommandGive -yq net/minecraft/server/commands/CommandHelp -yr net/minecraft/server/commands/ItemCommands -ys net/minecraft/server/commands/CommandKick -yt net/minecraft/server/commands/CommandKill -yu net/minecraft/server/commands/CommandList -yv net/minecraft/server/commands/CommandLocateBiome -yw net/minecraft/server/commands/CommandLocate -yx net/minecraft/server/commands/CommandLoot -yy net/minecraft/server/commands/CommandTell -yz net/minecraft/server/commands/CommandOp -z net/minecraft/ReportedException -za net/minecraft/server/commands/CommandPardon -zb net/minecraft/server/commands/CommandPardonIP -zc net/minecraft/server/commands/CommandParticle -zd net/minecraft/server/commands/PerfCommand -ze net/minecraft/server/commands/CommandPlaySound -zf net/minecraft/server/commands/CommandPublish -zh net/minecraft/server/commands/CommandRecipe -zi net/minecraft/server/commands/CommandReload -zj net/minecraft/server/commands/CommandSaveAll -zk net/minecraft/server/commands/CommandSaveOff -zl net/minecraft/server/commands/CommandSaveOn -zm net/minecraft/server/commands/CommandSay -zn net/minecraft/server/commands/CommandSchedule -zo net/minecraft/server/commands/CommandScoreboard -zp net/minecraft/server/commands/CommandSeed -zq net/minecraft/server/commands/CommandSetBlock -zq$a net/minecraft/server/commands/CommandSetBlock$Filter -zq$b net/minecraft/server/commands/CommandSetBlock$Mode -zr net/minecraft/server/commands/CommandIdleTimeout -zs net/minecraft/server/commands/CommandSpawnpoint -zt net/minecraft/server/commands/CommandSetWorldSpawn -zu net/minecraft/server/commands/CommandSpectate -zv net/minecraft/server/commands/CommandSpreadPlayers -zw net/minecraft/server/commands/CommandStop -zx net/minecraft/server/commands/CommandStopSound -zy net/minecraft/server/commands/CommandSummon -zz net/minecraft/server/commands/CommandTag -p c ()Z isFormat -ab a (C)Z isAllowedChatCharacter -ab b ()Lcom/mojang/bridge/game/GameVersion; getGameVersion -ad b ()J getMonotonicMillis -ad c ()J getMonotonicNanos -ad d ()J getTimeMillis -ae f ()Ljava/util/Map; getCriteria -ae h ()Lww; getName -ag a ()Z isDone -ag c (Ljava/lang/String;)Lak; getCriterionProgress -ag e ()Ljava/lang/Iterable; getRemainingCriteria -ag f ()Ljava/lang/Iterable; getAwardedCriteria -ak d ()Ljava/util/Date; getDate -dl a (Los;)V sendFailureMessage -dl a (Los;Z)V sendMessage -dl b ()Los; getScoreboardDisplayName -dl b (Los;)V sendAdminMessage -dl c ()Ljava/lang/String; getName -dl d ()Ldna; getPosition -dl e ()Labr; getWorld -dl f ()Latf; getEntity -dl j ()Lnet/minecraft/server/MinecraftServer; getServer -dk E_ ()Z shouldBroadcastCommands -dk a (Los;Ljava/util/UUID;)V sendMessage -dk h_ ()Z shouldSendSuccess -dk i_ ()Z shouldSendFailure -dn c (I)Z hasPermission -dv b ()Ldv; multipleEntities -es a ()Ljava/util/Map; getStateMap -es b ()Lcks; getBlockData -fn b ()V parseSelector -fn t ()Lfm; parse -fm b (Ldl;)Ljava/util/List; getEntities -hb a (DDDZ)D distanceSquared -hb b (Lgl;)Lhb; shift -hb b (Lgl;I)Lhb; shift -hb i (I)Lhb; east -hb j ()Lhb; east -hb j (I)Lhb; west -hb k ()Lhb; west -hb k (I)Lhb; south -hb l ()Lhb; south -hb l (I)Lhb; north -hb m ()Lhb; north -hb m (I)Lhb; down -hb n ()Lhb; down -hb n (I)Lhb; up -hb o ()Lhb; up -hb u ()I getX -hb v ()I getY -hb w ()I getZ -gg a ()J asLong -gg d (J)Lgg; fromLong -gg h ()Lgg; immutableCopy -gl a (D)Lgl; fromAngle -gl a (I)Lgl; fromType1 -gl b (I)Lgl; fromType2 -gl d ()I get2DRotationValue -gl f ()Lgl; opposite -gl i ()I getAdjacentX -gl j ()I getAdjacentY -gl k ()I getAdjacentZ -go a ()Lwv; getDimensionManager -go a (Lwv;Lgg;)Lgo; create -go b ()Lgg; getBlockPosition -gt a ()D getX -gt b ()D getY -gt c ()D getZ -gw a (Lww;)Ljava/lang/Object; get -gw b (Ljava/lang/Object;)Lww; getKey -gw b (Lww;)Ljava/util/Optional; getOptional -gw c ()Ljava/util/Set; keySet -gh d ()Lgg; getBlockPosition -gh e ()Lcks; getBlockData -gh f ()Lcip; getTileEntity -gh g ()Labr; getWorld -gp a (I)Ljava/lang/Object; fromId -gp a (Ljava/lang/Object;)I getId -gy b ()F getX -gy c ()F getY -gy d ()F getZ -he b ()F getPower -ht b ()Lhu; getParticle -nm a (Lna;)Lcom/mojang/authlib/GameProfile; deserialize -nm a (Lna;Lcom/mojang/authlib/GameProfile;)Lna; serialize -nt a (Ljava/lang/String;)Lna; parse -nt b (Ljava/lang/String;)Lns; parseLiteral -nt h ()Lns; parseArray -ns a ()B getTypeId -ns a (Ljava/io/DataOutput;)V write -ns c ()Lns; clone -ns d_ ()Ljava/lang/String; asString -mz d (ILns;)Lns; set -nn e ()J asLong -nn f ()I asInt -nn g ()S asShort -nn h ()B asByte -nn i ()D asDouble -nn j ()F asFloat -mx d ()[B getBytes -na a (Ljava/lang/String;B)V setByte -na a (Ljava/lang/String;D)V setDouble -na a (Ljava/lang/String;F)V setFloat -na a (Ljava/lang/String;I)V setInt -na a (Ljava/lang/String;J)V setLong -na a (Ljava/lang/String;Ljava/lang/String;)V setString -na a (Ljava/lang/String;Lns;)Lns; set -na a (Ljava/lang/String;S)V setShort -na a (Ljava/lang/String;Z)V setBoolean -na a (Ljava/lang/String;[B)V setByteArray -na a (Ljava/lang/String;[I)V setIntArray -na b (Ljava/lang/String;I)Z hasKeyOfType -na c (Ljava/lang/String;)Lns; get -na c (Ljava/lang/String;I)Lng; getList -na d ()Ljava/util/Set; getKeys -na e (Ljava/lang/String;)Z hasKey -na f ()Z isEmpty -na f (Ljava/lang/String;)B getByte -na g ()Lna; clone -na g (Ljava/lang/String;)S getShort -na h (Ljava/lang/String;)I getInt -na i (Ljava/lang/String;)J getLong -na j (Ljava/lang/String;)F getFloat -na k (Ljava/lang/String;)D getDouble -na l (Ljava/lang/String;)Ljava/lang/String; getString -na m (Ljava/lang/String;)[B getByteArray -na n (Ljava/lang/String;)[I getIntArray -na o (Ljava/lang/String;)[J getLongArray -na p (Ljava/lang/String;)Lna; getCompound -na q (Ljava/lang/String;)Z getBoolean -na r (Ljava/lang/String;)V remove -ne f ()[I getInts -ng a (I)Lna; getCompound -ng c (I)Lns; remove -ng j (I)Ljava/lang/String; getString -nh f ()[J getLongs -oe a (I)V setCompressionLevel -oe a (Lof;)V setProtocol -oe a (Loj;)V setPacketListener -oe a (Los;)V close -oe a (Lpk;)V sendPacket -oe a (Lpk;Lio/netty/util/concurrent/GenericFutureListener;)V sendPacket -oe c ()Ljava/net/SocketAddress; getSocketAddress -oe d ()Z isLocal -oe h ()Z isConnected -oe l ()V stopReading -oe m ()V handleDisconnection -ot a (Ldl;Los;Latf;I)Loy; filterForDisplay -pg i ()Ljava/lang/String; getKey -pg j ()[Ljava/lang/Object; getArgs -pc a ()Lpe; getColor -pc a (Ljava/lang/Boolean;)Lpc; setBold -pc a (Ljava/lang/String;)Lpc; setInsertion -pc a (Lp;)Lpc; setColor -pc a (Loq;)Lpc; setChatClickable -pc a (Lpe;)Lpc; setColor -pc a (Low;)Lpc; setChatHoverable -pc a (Lpc;)Lpc; setChatModifier -pc b ()Z isBold -pc b (Ljava/lang/Boolean;)Lpc; setItalic -pc c ()Z isItalic -pc c (Ljava/lang/Boolean;)Lpc; setUnderline -pc d ()Z isStrikethrough -pc d (Ljava/lang/Boolean;)Lpc; setStrikethrough -pc e ()Z isUnderlined -pc e (Ljava/lang/Boolean;)Lpc; setRandom -pc f ()Z isRandom -pc h ()Loq; getClickEvent -pc i ()Low; getHoverEvent -pc j ()Ljava/lang/String; getInsertion -pc k ()Lww; getFont -os a ()Ljava/lang/String; getText -os b ()Ljava/util/List; getSiblings -os c ()Lpc; getChatModifier -os e ()Loy; mutableCopy -oy a (Ljava/util/function/UnaryOperator;)Loy; format -oy a (Lpc;)Loy; setChatModifier -oy a (Los;)Loy; addSibling -pm a (Lpk;Loj;Labr;)V ensureMainThread -pm a (Lpk;Loj;Laqu;)V ensureMainThread -uk b ()Z isFlying -uz c ()Lbqp; getItemStack -tt g ()Lato; getMainHand -ug b ()D getX -ug c ()D getY -ug d ()D getZ -ug e ()F getYaw -ug f ()F getPitch -qb a (Ljava/util/UUID;)Lqb; createRemovePacket -qb a (Larq;)Lqb; createAddPacket -qb b (Larq;)Lqb; createUpdateProgressPacket -qb c (Larq;)Lqb; createUpdateNamePacket -qb d (Larq;)Lqb; createUpdateStylePacket -qb e (Larq;)Lqb; createUpdatePropertiesPacket -vu a (Ljava/security/PrivateKey;)Ljavax/crypto/SecretKey; a -wa a (Ljava/lang/String;)V setFavicon -wa a (Los;)V setMOTD -wa a (Lwa$c;)V setServerInfo -wa a (Lwa$a;)V setPlayerSample -wa c ()Lwa$c; getServerData -wa$c b ()I getProtocolVersion -wi a (Lwf;)Ljava/lang/Object; get -wi a (Lwf;Ljava/lang/Object;)V register -wi b (Lwf;Ljava/lang/Object;)V set -wi c ()Ljava/util/List; getAll -wi c (Lwf;Ljava/lang/Object;)V registerObject -ww a ()Ljava/lang/String; getKey -ww b ()Ljava/lang/String; getNamespace -xe a (Lae;Ljava/lang/String;)Z grantCriteria -xe b (Lae;)Lag; getProgress -xe b (Lae;Ljava/lang/String;)Z revokeCritera -xg a ()Ljava/util/Collection; getAdvancements -xi b ()Lcom/mojang/brigadier/CommandDispatcher; getCommandDispatcher -xi c ()V tick -wy a ()V init -xj I ()Ljava/lang/String; getVersion -xj J ()I getPlayerCount -xj K ()I getMaxPlayers -xj L ()[Ljava/lang/String; getPlayers -xj a ()Laat; getDedicatedServerProperties -xj a (Ljava/lang/String;)Ljava/lang/String; executeRemoteCommand -xj s ()Ljava/lang/String; getWorld -xj t ()Ljava/lang/String; getPlugins -net/minecraft/server/Main a (Ldib$a;Lcom/mojang/datafixers/DataFixer;ZLjava/util/function/BooleanSupplier;Lcom/google/common/collect/ImmutableSet;)V convertWorld -net/minecraft/server/MinecraftServer D ()Z getAllowNether -net/minecraft/server/MinecraftServer H ()Ljava/lang/Iterable; getWorlds -net/minecraft/server/MinecraftServer I ()Ljava/lang/String; getVersion -net/minecraft/server/MinecraftServer J ()I getPlayerCount -net/minecraft/server/MinecraftServer K ()I getMaxPlayers -net/minecraft/server/MinecraftServer L ()[Ljava/lang/String; getPlayers -net/minecraft/server/MinecraftServer M ()Ljava/security/KeyPair; getKeyPair -net/minecraft/server/MinecraftServer N ()I getPort -net/minecraft/server/MinecraftServer O ()Ljava/lang/String; getSinglePlayerName -net/minecraft/server/MinecraftServer P ()Z isEmbeddedServer -net/minecraft/server/MinecraftServer R ()Z getSpawnMonsters -net/minecraft/server/MinecraftServer S ()Z isDemoMode -net/minecraft/server/MinecraftServer T ()Ljava/lang/String; getResourcePack -net/minecraft/server/MinecraftServer U ()Ljava/lang/String; getResourcePackHash -net/minecraft/server/MinecraftServer W ()Z getOnlineMode -net/minecraft/server/MinecraftServer Y ()Z getSpawnAnimals -net/minecraft/server/MinecraftServer Z ()Z getSpawnNPCs -net/minecraft/server/MinecraftServer a (I)V setPort -net/minecraft/server/MinecraftServer a (Ljava/lang/String;Ljava/lang/String;)V setResourcePack -net/minecraft/server/MinecraftServer a (Lwv;)Labr; getWorldServer -net/minecraft/server/MinecraftServer a (Ldib$a;)V convertWorld -net/minecraft/server/MinecraftServer a (Ldhx;)V initializeScoreboards -net/minecraft/server/MinecraftServer a (Z)V safeShutdown -net/minecraft/server/MinecraftServer a (ZZZ)Z saveChunks -net/minecraft/server/MinecraftServer aA ()Lxi; getFunctionData -net/minecraft/server/MinecraftServer aB ()Ladi; getResourcePackRepository -net/minecraft/server/MinecraftServer aC ()Ldm; getCommandDispatcher -net/minecraft/server/MinecraftServer aD ()Ldl; getServerCommandListener -net/minecraft/server/MinecraftServer aE ()Lbti; getCraftingManager -net/minecraft/server/MinecraftServer aF ()Lagc; getTagRegistry -net/minecraft/server/MinecraftServer aG ()Lxl; getScoreboard -net/minecraft/server/MinecraftServer aI ()Ldit; getLootTableRegistry -net/minecraft/server/MinecraftServer aJ ()Ldiu; getLootPredicateManager -net/minecraft/server/MinecraftServer aL ()Lbwl; getGameRules -net/minecraft/server/MinecraftServer aM ()Lxo; getBossBattleCustomData -net/minecraft/server/MinecraftServer aQ ()Lapu; getMethodProfiler -net/minecraft/server/MinecraftServer aU ()Z isSyncChunkWrites -net/minecraft/server/MinecraftServer aV ()Ldcp; getDefinedStructureManager -net/minecraft/server/MinecraftServer aW ()Ldii; getSaveData -net/minecraft/server/MinecraftServer aX ()Lgx; getCustomRegistry -net/minecraft/server/MinecraftServer aa ()Z getPVP -net/minecraft/server/MinecraftServer ab ()Z getAllowFlight -net/minecraft/server/MinecraftServer ac ()Ljava/lang/String; getMotd -net/minecraft/server/MinecraftServer ad ()Z isStopped -net/minecraft/server/MinecraftServer ae ()Laeh; getPlayerList -net/minecraft/server/MinecraftServer af ()Laci; getServerConnection -net/minecraft/server/MinecraftServer ak ()I getSpawnProtection -net/minecraft/server/MinecraftServer an ()I getIdleTimeout -net/minecraft/server/MinecraftServer ao ()Lcom/mojang/authlib/minecraft/MinecraftSessionService; getMinecraftSessionService -net/minecraft/server/MinecraftServer ap ()Lcom/mojang/authlib/GameProfileRepository; getGameProfileRepository -net/minecraft/server/MinecraftServer aq ()Laed; getUserCache -net/minecraft/server/MinecraftServer ar ()Lwa; getServerPing -net/minecraft/server/MinecraftServer as ()V invalidatePingSample -net/minecraft/server/MinecraftServer ay ()Lcom/mojang/datafixers/DataFixer; getDataFixer -net/minecraft/server/MinecraftServer az ()Lxg; getAdvancementData -net/minecraft/server/MinecraftServer b (Laca;)V loadSpawn -net/minecraft/server/MinecraftServer bf ()Z canSleepForTick -net/minecraft/server/MinecraftServer bh ()V updateSpawnFlags -net/minecraft/server/MinecraftServer c (I)V setIdleTimeout -net/minecraft/server/MinecraftServer d (Lxm;)Z canExecute -net/minecraft/server/MinecraftServer d (Z)V setOnlineMode -net/minecraft/server/MinecraftServer e ()Z init -net/minecraft/server/MinecraftServer e (Ljava/lang/String;)V setMotd -net/minecraft/server/MinecraftServer e_ ()V loadWorld -net/minecraft/server/MinecraftServer f ()V exit -net/minecraft/server/MinecraftServer f (Z)V setPVP -net/minecraft/server/MinecraftServer f_ ()V loadResourcesZip -net/minecraft/server/MinecraftServer g ()Z isHardcore -net/minecraft/server/MinecraftServer g (Z)V setAllowFlight -net/minecraft/server/MinecraftServer g_ ()Lbwm; getGamemode -net/minecraft/server/MinecraftServer n ()Z getEnableCommandBlock -net/minecraft/server/MinecraftServer p ()Ljava/util/Optional; getModded -net/minecraft/server/MinecraftServer r ()V updateWorldSettings -net/minecraft/server/MinecraftServer u ()V stop -net/minecraft/server/MinecraftServer v ()Ljava/lang/String; getServerIp -net/minecraft/server/MinecraftServer w ()Z isRunning -net/minecraft/server/MinecraftServer y ()V sleepForTick -xl d (Ldnv;)Ljava/util/List; getScoreboardScorePacketsForObjective -xn a ()Lww; getKey -xo a (Lna;)V load -xo a (Lww;Los;)Lxn; register -xo a (Lxn;)V remove -xo b ()Ljava/util/Collection; getBattles -xo c ()Lna; save -aar b ()Laas; getServer -aas a (Ljava/lang/String;Ldl;)V issueCommand -aas bg ()V handleCommandQueue -aas bj ()Z convertNames -aas bk ()J getMaxTickTime -aas i (Z)V setHasWhitelist -aat a (Ljava/nio/file/Path;)Laat; load -aau a ()Laat; getProperties -aau a (Ljava/util/function/UnaryOperator;)Laau; setProperty -aau b ()V save -aaw a (Ljava/lang/String;I)I getInt -aaw a (Ljava/lang/String;J)J getLong -aaw a (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; getString -aaw a (Ljava/lang/String;Z)Z getBoolean -aaw b (Ljava/nio/file/Path;)Ljava/util/Properties; loadPropertiesFile -aaw b (Lgx;Ljava/util/Properties;)Laaw; reload -aaw c (Ljava/nio/file/Path;)V savePropertiesFile -aaw$a a (Lgx;Ljava/lang/Object;)Laaw; set -aaz a ()V tick -abo a (Ljava/util/function/Function;)V sendUpdate -abo a (Labs;)V addPlayer -abo b (Labs;)V removePlayer -abo d (Z)V setVisible -abo h ()Ljava/util/Collection; getPlayers -abh b (JIZ)V update -abk a ()V purgeTickets -abk a (JLabv;)V addTicket -abk a (Lahf;)I getLowestTicketLevel -abk b (JLabv;)V removeTicket -abk c (Labw;Lbvu;ILjava/lang/Object;)V addTicket -abk d (Labw;Lbvu;ILjava/lang/Object;)V removeTicket -abp a (I)V setViewDistance -abp a (Lgg;)V flagDirty -abp a (Labs;)V movePlayer -abp a (Labw;Lbvu;ILjava/lang/Object;)V addTicket -abp a (Latf;)V removeEntity -abp a (Latf;Lpk;)V broadcastIncludingSelf -abp a (Z)V save -abp b (J)Labd; getChunk -abp b (Labw;Lbvu;ILjava/lang/Object;)V removeTicket -abp b (Latf;)V addEntity -abp b (Latf;Lpk;)V broadcast -abp c (IILcmp;Z)Ljava/util/concurrent/CompletableFuture; getChunkFutureMainThread -abp d ()Z runTasks -abp g ()Lcmn; getChunkGenerator -abp i ()Ldhx; getWorldPersistentData -abp n ()V clearCache -abp o ()Z tickDistanceManager -abp p ()V tickChunks -abs A ()Lafk; getStatisticManager -abs B ()Lafj; getRecipeBook -abs D ()Latf; getSpecatorTarget -abs G ()Los; getPlayerListName -abs J ()Lxe; getAdvancementData -abs K ()Lgg; getSpawn -abs L ()F getSpawnAngle -abs M ()Lwv; getSpawnDimension -abs N ()Z isSpawnForced -abs a (Ljava/lang/String;Ljava/lang/String;ZLos;)V setResourcePack -abs a (Lwv;Lgg;FZZ)V setRespawnPosition -abs a (Labs;Z)V copyFrom -abs a (Lbmj;)V initMenu -abs c (Labr;)V spawnIn -abs c (Latf;)V setSpectatorTarget -abs e (Labr;)V triggerDimensionAdvancements -abs fI ()Z canPvP -abs fJ ()V nextContainerCounter -abs g ()V syncInventory -abs l ()V playerTick -abs r ()V triggerHealthUpdate -abs u ()Labr; getWorldServer -abs x ()Lbkb; getChatFlags -abs z ()V resetIdleTimer -abq a (Lpk;)V broadcastIncludingSelf -abu a ()V queueUpdate -abd a (Lcmp;)Ljava/util/concurrent/CompletableFuture; getStatusFutureUnchecked -abd b (I)Lcmp; getChunkStatus -abd c (I)Labd$c; getChunkState -abd d ()Lcmw; getChunk -abd g ()Ljava/util/concurrent/CompletableFuture; getChunkSave -abd j ()I getTicketLevel -abd l ()Z hasBeenLoaded -abd$c a (Labd$c;)Z isAtLeast -abe a (I)V setViewDistance -abe a (J)Labd; getUpdatingChunk -abe a (Ljava/util/function/BooleanSupplier;)V unloadChunks -abe a (Labs;)V movePlayer -abe a (Labs;Lbvu;[Lpk;ZZ)V sendChunk -abe a (Latf;)V addEntity -abe a (Latf;Lpk;)V broadcast -abe a (Lcml;)Z saveChunk -abe a (Z)V save -abe b (J)Labd; getVisibleChunk -abe b (Latf;)V removeEntity -abe b (Latf;Lpk;)V broadcastIncludingSelf -abe d (Lbvu;)Z isOutsideOfRange -abe i (Lbvu;)Lna; readChunkData -abe$b a (Ljava/util/List;)V track -abe$b a (Lpk;)V broadcast -abe$b a (Labs;)V clear -abe$b b (Lpk;)V broadcastIncludingSelf -abe$b b (Labs;)V updatePlayer -abt a (Lgg;)Z breakBlock -abt a (Lbwm;)Z setGameMode -abt b ()Lbwm; getGameMode -abt e ()Z isCreative -abv a ()Labw; getTicketType -abr B ()Lblk; getPersistentRaid -abr D ()Z isFlatWorld -abr F ()Lcnx; getDragonBattle -abr a ()Lbxg; getStructureManager -abr a (IIZ)Z setForceLoaded -abr a (J)V setDayTime -abr a (Ljava/util/UUID;)Latf; getEntity -abr a (Ljava/util/function/BooleanSupplier;)V doTick -abr a (Labs;)V addPlayerCommand -abr a (Lahc;ZZ)V save -abr a (Latf;)V entityJoinedWorld -abr a (Lcmw;)V unloadChunk -abr a (ZZ)V doMobSpawning -abr am ()V wakeupPlayers -abr ao ()V clearWeather -abr b (Labs;)V addPlayerPortal -abr c (Labs;)V addPlayerJoin -abr c (Latf;)Z addEntitySerialized -abr d (Labs;)V addPlayerRespawn -abr d (Latf;)V addEntityTeleport -abr e ()V everyoneSleeping -abr e (Labs;)V addPlayer0 -abr e (Latf;)Z addAllEntitiesSafely -abr g ()V resetEmptyTime -abr j (Latf;)Z addEntity0 -abr o ()Ldhh; getTravelAgent -abr u ()Ldhx; getWorldPersistentData -abr w ()Lgg; getSpawn -abr y ()Lit/unimi/dsi/fastutil/longs/LongSet; getForceLoadedChunks -acl b ()V tick -acl b (Los;)V disconnect -acj a (Ljava/lang/String;)V handleCommand -acj b ()V tick -acj b (Los;)V disconnect -acj c ()V syncPosition -acj e ()Z isExemptPlayer -acm a (Lpk;)V sendPacket -aec a ()Ljava/util/Date; getCreated -aec b ()Ljava/lang/String; getSource -aec c ()Ljava/util/Date; getExpires -aec d ()Ljava/lang/String; getReason -aen a (Lcom/mojang/authlib/GameProfile;)Z isBanned -aee a (Ljava/net/SocketAddress;)Z isBanned -aee b (Ljava/net/SocketAddress;)Laef; get -aem a ()[Ljava/lang/String; getEntries -aem a (Lael;)V add -aem b (Ljava/lang/Object;)Lael; get -aem c ()Z isEmpty -aem c (Ljava/lang/Object;)V remove -aem e ()V save -aem f ()V load -ael f ()Z hasExpired -ael g ()Ljava/lang/Object; getKey -aeg g (Lnet/minecraft/server/MinecraftServer;)Ljava/io/File; getPlayersFolder -aei a (Lcom/mojang/authlib/GameProfile;)Z canBypassPlayerLimit -aeh a ()V reloadWhitelist -aeh a (Lcom/mojang/authlib/GameProfile;)V addOp -aeh a (Ljava/lang/String;)Labs; getPlayer -aeh a (Ljava/net/SocketAddress;Lcom/mojang/authlib/GameProfile;)Los; attemptLogin -aeh a (Ljava/util/UUID;)Labs; getPlayer -aeh a (Los;Lop;Ljava/util/UUID;)V sendMessage -aeh a (Lpk;)V sendAll -aeh a (Lxl;Labs;)V sendScoreboard -aeh a (Labs;Z)Labs; moveToWorld -aeh a (Labr;)V setPlayerFileData -aeh a (Lbkd;)Lafk; getStatisticManager -aeh a (Lbkd;DDDDLwv;Lpk;)V sendPacketNearby -aeh a (Z)V setHasWhitelist -aeh b (Lcom/mojang/authlib/GameProfile;)V removeOp -aeh b (Labs;)V savePlayerFile -aeh c ()Lnet/minecraft/server/MinecraftServer; getServer -aeh c (Lcom/mojang/authlib/GameProfile;)Z isWhitelisted -aeh c (Labs;)V disconnect -aeh d ()V tick -aeh e (Lcom/mojang/authlib/GameProfile;)Labs; processLogin -aeh e (Labs;)V updateClient -aeh f ()Laen; getProfileBans -aeh f (Lcom/mojang/authlib/GameProfile;)Z isOp -aeh g ()Laee; getIPBans -aeh h ()V savePlayers -aeh i ()Laep; getWhitelist -aeh j ()[Ljava/lang/String; getWhitelisted -aeh k ()Laei; getOPs -aeh m ()I getPlayerCount -aeh n ()I getMaxPlayers -aeh o ()Z getHasWhitelist -aeh p ()I getViewDistance -aeh q ()Lna; save -aeh r ()V shutdown -aeh s ()Ljava/util/List; getPlayers -aeh t ()V reload -aed a (Ljava/lang/String;)Lcom/mojang/authlib/GameProfile; getProfile -aed a (Ljava/util/UUID;)Lcom/mojang/authlib/GameProfile; getProfile -aep a (Lcom/mojang/authlib/GameProfile;)Z isWhitelisted -aeu e ()V clearMessages -aeu f ()Ljava/lang/String; getMessages -aeu g ()Ldl; getWrapper -afh b (Lww;)Z hasDiscoveredRecipe -afj b ()Lna; save -afk a ()V save -afl a ()Lafn; getWrapper -afp a (Lafl;)I getStatisticValue -afp a (Lbkd;Lafl;I)V setStatistic -afn a ()Lgw; getRegistry -agc a ()V bind -aga a (Ljava/lang/Object;)Z isTagged -aga b ()Ljava/util/List; getTagged -ahh c ()Ljava/lang/String; getName -aha a (F)F sin -aha a (III)I clamp -aha a (Ljava/util/Random;II)I nextInt -aha b (D)I floor -aha b (F)F cos -agj a (ILjava/lang/String;Ljava/security/Key;)Ljavax/crypto/Cipher; a -agj a (ILjava/security/Key;)Ljavax/crypto/Cipher; a -agj a (Ljava/lang/String;Ljava/security/PublicKey;Ljavax/crypto/SecretKey;)[B a -agj a (Ljava/security/PrivateKey;[B)Ljavax/crypto/SecretKey; a -aip a (ILjava/lang/String;[Ljava/lang/String;)V map -apu a (Ljava/lang/String;)V enter -apu b (Ljava/lang/String;)V exitEnter -apu c ()V exit -aqu a (Ljava/lang/Runnable;)Ljava/util/concurrent/CompletableFuture; executeFuture -aqu au ()Z isNotMainThread -aqu av ()Ljava/lang/Thread; getThread -aqu bm ()Z isMainThread -aqu bq ()V executeAll -aqu c (Ljava/lang/Runnable;)V executeTask -aqu c (Ljava/util/function/BooleanSupplier;)V awaitTasks -aqu d (Ljava/lang/Runnable;)Z canExecute -aqu e (Ljava/lang/Runnable;)Ljava/lang/Runnable; postToMainThread -aqu g (Ljava/lang/Runnable;)V executeSync -aqu z ()Z executeNext -aqy bs ()Z isEntered -arq a (F)V setProgress -arq a (Z)Larq; setDarkenSky -arq b (Z)Larq; setPlayMusic -arq c (Z)Larq; setCreateFog -arq k ()F getProgress -arq n ()Z isDarkenSky -arq o ()Z isPlayMusic -arq p ()Z isCreateFog -arr a ()V clear -arx a (I)Larx; getById -art L_ ()I getMaxStackSize -art a (I)Lbqp; getItem -art a (II)Lbqp; splitStack -art a (ILbqp;)V setItem -art b ()I getSize -art b (I)Lbqp; splitWithoutUpdate -art b_ (Lbkd;)V startOpen -art c ()Z isEmpty -art c_ (Lbkd;)V closeContainer -art e ()V update -ase B_ ()Los; getScoreboardDisplayName -ase S ()Los; getDisplayName -ase T ()Z hasCustomName -ase U ()Los; getCustomName -asd B_ ()Los; getScoreboardDisplayName -asj a (ILbqp;Lgl;)Z canPlaceItemThroughFace -asj a (Lgl;)[I getSlotsForFace -asj b (ILbqp;Lgl;)Z canTakeItemThroughFace -asb a (Ljava/lang/Object;)Lasb; success -asb b (Ljava/lang/Object;)Lasb; consume -asb c (Ljava/lang/Object;)Lasb; pass -asb d (Ljava/lang/Object;)Lasb; fail -arw a (Lbwp;DDDLart;)V dropInventory -arw a (Lbwp;DDDLbqp;)V dropItem -arw a (Lbwp;Lgg;Lart;)V dropInventory -arw a (Lbwp;Latf;Lart;)V dropEntity -aso a (Lasp;FF)V trackDamage -aso b ()Los; getDeathMessage -asp a (Latt;)Los; getLocalizedDeathMessage -asp a (Lbkd;)Lasp; playerAttack -asp a (Lbkh;Latf;)Lasp; arrow -asp a (Lbkn;Latf;)Lasp; fireball -asp a (Lbwh;)Lasp; explosion -asp b (Latf;Latf;)Lasp; projectile -asp c (Latt;)Lasp; mobAttack -asp d ()Z isExplosion -asp e ()Lasp; setExplosion -asp f ()Z ignoresArmor -asp h ()F getExhaustionCost -asp i ()Z ignoresInvulnerability -asp j ()Z isStarvation -asp l ()Latf; getEntity -asp m ()Lasp; setIgnoreArmor -asp o ()Lasp; setIgnoresInvulnerability -asp p ()Lasp; setStarvation -asp q ()Lasp; setFire -asp s ()Z isFire -asp x ()Z isMagic -asp y ()Lasp; setMagic -asz a ()Lasx; getMobEffect -asz a (Latt;Ljava/lang/Runnable;)Z tick -asz b ()I getDuration -asz c ()I getAmplifier -asz d ()Z isAmbient -asz e ()Z isShowParticles -asz f ()Z isShowIcon -asx a ()Z isInstant -asx a (I)Lasx; fromId -asx a (Lasx;)I getId -asx a (Latf;Latf;Latt;ID)V applyInstantEffect -asx a (Latt;I)V tick -asx f ()I getColor -atf A_ ()Z isSpectator -atf P ()Lpk; getPacket -atf W ()V decouple -atf Y ()Latj; getEntityType -atf a (DDDFF)V setLocation -atf a (FF)V setYawPitch -atf a (Ljava/lang/String;)Z addScoreboardTag -atf a (Lr;)V appendEntityCrashDetails -atf a (Lgg;FF)V setPositionRotation -atf a (Lna;)V loadData -atf a (Los;)V setCustomName -atf a (Labr;Lgg;Z)Ljava/util/Optional; findOrCreatePortal -atf a (Labr;Lats;)V onLightningStrike -atf a (Lafd;FF)V playSound -atf a (Lasp;F)Z damageEntity -atf a (Lauf;Latg;)F getHeadHeight -atf a (Latk;Lbqp;)V setSlot -atf a (Latz;Ldna;)V move -atf a ([D)Lng; newDoubleList -atf a ([F)Lng; newFloatList -atf aA ()Lafd; getSoundSwim -atf aB ()Lafd; getSoundSplash -atf aC ()Lafd; getSoundSplashHighSpeed -atf aD ()V checkBlockCollisions -atf aG ()Z isSilent -atf aH ()Z isNoGravity -atf aK ()Z isFireProof -atf aL ()Z isInWater -atf aM ()Z isInWaterOrRain -atf a_ ()V initDatawatcher -atf aa ()Ljava/util/Set; getScoreboardTags -atf ab ()V killEntity -atf ac ()V die -atf ad ()Lwi; getDataWatcher -atf af ()Lauf; getPose -atf ai ()V entityBaseTick -atf ak ()V resetPortalCooldown -atf an ()V burnFromLava -atf ao ()I getFireTicks -atf ap ()V extinguish -atf ar ()Z isOnGround -atf aw ()F getBlockJumpFactor -atf ax ()F getBlockSpeedFactor -atf b (DDD)V enderTeleportTo -atf b (DDDFF)V setPositionRotation -atf b (IZ)V setFlag -atf b (Ljava/lang/String;)Z removeScoreboardTag -atf b (Lna;)V saveData -atf b (Lasp;)Z isInvulnerable -atf b (Lauf;)V setPose -atf b (Lbkd;)V pickup -atf bA ()Z isPassenger -atf bB ()Z isVehicle -atf bD ()Z isSneaking -atf bI ()Z isCrouching -atf bJ ()Z isSprinting -atf bK ()Z isSwimming -atf bN ()Z hasGlowingTag -atf bO ()Z isCurrentlyGlowing -atf bP ()Z isInvisible -atf bR ()Ldoa; getScoreboardTeam -atf bT ()I getAirTicks -atf bU ()I getTicksFrozen -atf bW ()Z isFullyFrozen -atf bX ()I getTicksRequiredToFreeze -atf bZ ()F getHeadRotation -atf ba ()V velocityChanged -atf bc ()Z isInteractable -atf bd ()Z isCollidable -atf bf ()Ljava/lang/String; getSaveID -atf bg ()Z isAlive -atf bh ()Z inBlock -atf bj ()V passengerTick -atf bn ()V ejectPassengers -atf bq ()Ldna; getLookDirection -atf bt ()V doPortalTick -atf bu ()I getDefaultPortalCooldown -atf bx ()Ljava/lang/Iterable; getArmorItems -atf bz ()Z isBurning -atf c (DDD)V teleportAndSync -atf c (Z)V setOnGround -atf cA ()Ljava/util/List; getPassengers -atf cE ()Ljava/lang/Iterable; getAllPassengers -atf cF ()Z hasSinglePlayerPassenger -atf cG ()Latf; getRootVehicle -atf cI ()Latf; getVehicle -atf cJ ()Laff; getSoundCategory -atf cK ()I getMaxFireTicks -atf cL ()Ldl; getCommandListener -atf cO ()F getWidth -atf cP ()F getHeight -atf cQ ()Ldna; getPositionVector -atf cV ()Ldna; getMot -atf cX ()D locX -atf cZ ()D locY -atf cb ()Z isInvulnerable -atf cd ()Z canPortal -atf cf ()Z isIgnoreBlockTrigger -atf ci ()Ljava/lang/String; getUniqueIDString -atf cj ()Ljava/lang/String; getName -atf cm ()Z getCustomNameVisible -atf co ()Lgl; getDirection -atf cp ()Lgl; getAdjustedDirection -atf ct ()F getHeadHeight -atf cv ()Lbwp; getWorld -atf cw ()Lnet/minecraft/server/MinecraftServer; getMinecraftServer -atf cz ()Latf; getRidingPassenger -atf d (Z)V setSilent -atf db ()D getHeadY -atf dd ()D locZ -atf de ()V checkDespawn -atf dh ()F getYRot -atf di ()F getXRot -atf dj ()Z isRemoved -atf dk ()Latf$c; getRemovalReason -atf dl ()V unsetRemoved -atf e (DDD)V setPosition -atf e (Z)V setNoGravity -atf f (I)V setOnFire -atf f (Lna;)Lna; save -atf f (Ldna;)V setMot -atf f (Z)V setSneaking -atf g (I)V setFireTicks -atf g (Lna;)V load -atf g (Latf;)V collide -atf g (Z)V setSprinting -atf h (I)Z getFlag -atf h (Z)V setSwimming -atf i ()Z isInRain -atf i (I)V setAirTicks -atf i (Z)V setGlowingTag -atf j (I)V setTicksFrozen -atf j (Z)V setInvisible -atf k ()V tick -atf k (Latf;)Z startRiding -atf l (F)V setHeadRotation -atf m ()V stopRiding -atf m (DDD)V enderTeleportAndLoad -atf m (Latf;)V addPassenger -atf m (Z)V setInvulnerable -atf n (DDD)V setMot -atf n (Latf;)V removePassenger -atf n (Z)V setCustomNameVisible -atf o (DDD)V setPositionRaw -atf o (F)V setYRot -atf p (F)V setXRot -atf v (Latf;)Z isSameVehicle -atf x_ ()V updateSize -atf y_ ()Ldey; getPushReaction -atd a (IZ)V setAge -atd a (Labr;Latd;)Latd; createChild -atd a_ (I)V setAge -atd b_ (I)V setAgeRaw -atd g ()Z canBreed -atd j ()I getAge -ate a (F)V setRadius -ate a (I)V setColor -ate a (Lht;)V setParticle -ate a (Lasz;)V addEffect -ate a (Latt;)V setSource -ate b (F)V setRadiusOnUse -ate b (I)V setDuration -ate c (F)V setRadiusPerTick -ate d (I)V setWaitTime -ate h ()F getRadius -ate i ()I getColor -ate j ()Lht; getParticle -ate n ()I getDuration -ate s ()Latt; getSource -atl a (I)I getOrbValue -atv A ()Layr; getControllerLook -atv B ()Lays; getControllerMove -atv D ()Layq; getControllerJump -atv F ()Lbbz; getNavigation -atv G ()Lbcs; getEntitySenses -atv H ()Latt; getGoalTarget -atv I ()V blockEaten -atv L ()V doSpawnEffect -atv N ()Lww; getDefaultLootTable -atv O ()Z isSpecialPersistence -atv a (Lbxd;Lary;Latx;Laul;Lna;)Laul; prepare -atv a (Z)V setBaby -atv a (ZZ)V unleash -atv b (Latf;Z)V setLeashHolder -atv eX ()V mobTick -atv fb ()I getMaxSpawnGroup -atv fd ()V setPersistent -atv fe ()Z canPickupLoot -atv ff ()Z isPersistent -atv fm ()Z isLeashed -atv fn ()Latf; getLeashHolder -atv fo ()Z isNoAI -atv fp ()Z isLeftHanded -atv fq ()Z isAggressive -atv h (D)Z isTypeNotPersistent -atv h (Latt;)V setGoalTarget -atv k (Lbqp;)Z canPickup -atv q ()Lafd; getSoundAmbient -atv r (Z)V setCanPickupLoot -atv s (Z)V setNoAI -atv t (Z)V setLeftHanded -atv u (Z)V setAggressive -atv v ()V initPathfinder -ats a (Z)V setEffect -att B (Latf;)Z hasLineOfSight -att a (Larz;)V swingHand -att a (Larz;Z)V swingHand -att a (Lasp;)V die -att a (Lasp;IZ)V dropDeathLoot -att a (Lasx;)Z hasEffect -att a (Latf;I)V receive -att a (Latt;)V setLastDamager -att a (Laup;)Lauq; getAttributeInstance -att b (F)V heal -att b (Lgg;)V entitySleep -att b (Lasp;F)V damageArmor -att b (Lasz;)Z addEffect -att b (Lasz;Latf;)Z addEffect -att b (Lasx;)Lasz; getEffect -att b (Latk;)Lbqp; getEquipment -att b_ ()Z isClimbing -att c (F)V setHealth -att c (Lasp;)Lafd; getSoundHurt -att c (Lasp;F)V damageHelmet -att c (Latk;)V broadcastItemBreak -att c (Lbqp;)V playEquipSound -att d (Larz;)V broadcastItemBreak -att d (Lasp;F)F applyArmorModifier -att d (Lasx;)Z removeEffect -att d (Latt;)V shieldBlock -att d (Lbkd;)I getExpValue -att dC ()Z isDropExperience -att dE ()Z alwaysGivesExp -att dF ()Ljava/util/Random; getRandom -att dG ()Latt; getLastDamager -att dM ()V tickPotionEffects -att dQ ()Z removeAllEffects -att dR ()Ljava/util/Collection; getEffects -att dU ()F getHealth -att dX ()V dropInventory -att dY ()V dropExperience -att do ()Lauo; getBehaviorController -att e (Lasp;)Z applyBlockingModifier -att e (Lasp;F)F applyMagicModifier -att eA ()Z doAITick -att eB ()F getAbsorptionHearts -att eD ()Lato; getMainHand -att eE ()Z isHandRaised -att eF ()Larz; getRaisedHand -att eG ()Lbqp; getActiveItem -att eJ ()V releaseActiveItem -att eK ()V clearActiveItem -att eL ()Z isBlocking -att eN ()Z isGliding -att eS ()Ljava/util/Optional; getBedPosition -att eU ()Z isSleeping -att eV ()V entityWakeup -att eb ()V playBlockStepSound -att ec ()I getArmorStrength -att ed ()Laso; getCombatTracker -att ee ()Latt; getKillingEntity -att ef ()F getMaxHealth -att eg ()I getArrowCount -att ej ()Laur; getAttributeMap -att ek ()Laty; getMonsterType -att el ()Lbqp; getItemInMainHand -att em ()Lbqp; getItemInOffHand -att eo ()F getSoundVolume -att eq ()Z isFrozen -att es ()V jump -att ex ()V doTick -att ey ()V collideNearby -att ez ()Z isRiptiding -att f (Lasp;F)V damageEntity0 -att h ()V enterCombat -att i ()V exitCombat -att i (Lbqp;)Latk; getEquipmentSlotForItem -att p (I)Lafd; getSoundFall -att q (F)V damageShield -att q (I)V setArrowCount -att q (Z)V setJumping -att t (F)V setAbsorptionHearts -att u_ ()V movementTick -att v_ ()Lafd; getSoundDeath -att w_ ()Z isBaby -att x ()V updateEquipment -att z (Latf;)Z attackEntity -aun b (Ljava/util/UUID;)V setOwnerUUID -aun f (Lbkd;)V tame -aun fv ()Z isSitting -aun fx ()Z isWillSit -aun p ()Z isTamed -aun w (Z)V setTamed -aun x (Z)V setSitting -aun y (Z)V setWillSit -atj a (Labr;Lna;Los;Lbkd;Lgg;Latx;ZZ)Latf; spawnCreature -atj a (Labr;Lbqp;Lbkd;Lgg;Latx;ZZ)Latf; spawnCreature -atj a (Latj;)Lww; getName -atj b (Labr;Lna;Los;Lbkd;Lgg;Latx;ZZ)Latf; createCreature -atj n ()I getChunkRange -atj o ()I getUpdateInterval -atj p ()Z isDeltaTracking -atj$a a (I)Latj$a; trackingRange -atj$a b (I)Latj$a; updateInterval -atk a (Ljava/lang/String;)Latk; fromName -atk c ()I getSlotFlag -atk d ()Ljava/lang/String; getSlotName -atn b (I)V setDarkTicksRemaining -atn t ()I getDarkTicksRemaining -aua F_ ()V pacify -aua G_ ()Z isAngry -aua H ()Latt; getGoalTarget -aua a ()I getAnger -aua a (I)V setAnger -aua a (Ljava/util/UUID;)V setAngerTarget -aua a (Latt;)V setLastDamager -aua b ()Ljava/util/UUID; getAngerTarget -aua c ()V anger -aua dG ()Latt; getLastDamager -aua h (Latt;)V setGoalTarget -aui a (Laff;)V saddle -aui c ()Z canSaddle -aui d ()Z hasSaddle -auj a ()Z canShear -auj a (Laff;)V shear -aub d ()Ljava/util/UUID; getOwnerUUID -aub e ()Latf; getOwner -aug a ()Z isPowered -atp a (Z)V setSaddle -atp b ()Z hasSaddle -auo a (Lbbt;)Z hasMemory -auo a (Lbbt;Ljava/lang/Object;)V setMemory -auo a (Lbbt;Ljava/util/Optional;)V setMemory -auo a (Lblo;)V setSchedule -auo b ()Lblo; getSchedule -auo b (Lbbt;)V removeMemory -auo c (Lbbt;)Ljava/util/Optional; getMemory -aup a ()D getDefault -aup c ()Ljava/lang/String; getName -aur a ()Ljava/util/Set; getAttributes -auq a ()Laup; getAttribute -auq a (D)V setValue -auq b ()D getBaseValue -auq c ()Ljava/util/Set; getModifiers -auq c (Laus;)V addModifier -auq d (Laus;)V removeModifier -auq f ()D getValue -aus a ()Ljava/util/UUID; getUniqueId -aus b ()Ljava/lang/String; getName -aus c ()Laus$a; getOperation -aus d ()D getAmount -aus e ()Lna; save -ayk a (Labr;Lbjq;)V doWork -ayq a ()V jump -bak a (I)V setTimeBetweenMovement -azp b ()V doTick -bbt a ()Ljava/util/Optional; getSerializer -bds p ()Z isAsleep -bds v (Z)V setAsleep -bdz b ()Lbqp; getBucketItem -bdz m (Lbqp;)V setBucketName -bdz p ()Z isFromBucket -bdz v (Z)V setFromBucket -bdx a (Lbdx;)Z mate -bdx fA ()Labs; getBreedCause -bdx fB ()Z isInLove -bdx fC ()V resetLove -bdx t (I)V setLoveTicks -bdy fD ()Z hasHivePos -bdy fE ()Lgg; getHivePos -bdy fG ()Z hasNectar -bdy fH ()Z hasStung -bdy fL ()Z canPollinate -bdy fP ()I getNumCropsGrownSincePollination -bdy g (Lgg;)V setFlowerPos -bdy p ()Lgg; getFlowerPos -bdy t ()Z hasFlowerPos -bdy u (I)V setCannotEnterHiveTicks -bdy v (Z)V setHasNectar -bdy w (Z)V setHasStung -bea a (Lbpl;)V setCollarColor -bea fE ()I getCatType -bea fH ()Lbpl; getCollarColor -bea u (I)V setCatType -beb t ()Z isChickenJockey -beb v (Z)V setChickenJockey -bee b (I)V setMoistness -bee g (Lgg;)V setTreasurePos -bee n ()Lgg; getTreasurePos -bee p ()Z gotFish -bee t ()I getMoistness -bee v (Z)V setGotFish -bdu fw ()Lafd; getSoundFlop -beg B (Z)V setSleeping -beg a (Lbeg$v;)V setFoxType -beg fG ()V initializePathFinderGoals -beg fv ()Z isSitting -beg t ()Lbeg$v; getFoxType -beg v (Z)V setSitting -beg x (Z)V setCrouching -beh fw ()Z isPlayerCreated -beh w (Z)V setPlayerCreated -bei a (Lbei$a;)V setVariant -bei t ()Lbei$a; getVariant -bej fv ()Z isTrusting -bej v (Z)V setTrusting -bek a (Lbek$a;)V setMainGene -bek b (Lbek$a;)V setHiddenGene -bek fE ()Lbek$a; getMainGene -bek fF ()Lbek$a; getHiddenGene -bek fI ()Lbek$a; getActiveGene -bek fJ ()Z isLazy -bek fK ()Z isWorried -bek fL ()Z isPlayful -bek fN ()Z isWeak -bek$a c ()Z isRecessive -bel fF ()I getVariant -bel u (I)V setVariant -beo b (I)V setPuffState -beo fx ()I getPuffState -bep fv ()Lafd; getSoundJump -bep fw ()I getRabbitType -bep u (I)V setRabbitType -ber b (Lbpl;)V setColor -ber fv ()Z isSheared -ber t ()Lbpl; getColor -ber v (Z)V setSheared -bet p ()Z hasPumpkin -bet v (Z)V setHasPumpkin -bev fE ()I getVariant -bev w (I)V setVariant -bew fw ()Lgg; getHomePos -bew fx ()Lgg; getTravelPos -bew g (Lgg;)V setHomePos -bew h (Lgg;)V setTravelPos -bew p ()Z hasEgg -bew v (Z)V setHasEgg -bey a (Lbpl;)V setCollarColor -bey fG ()Lbpl; getCollarColor -bez a (Lbez$e;)V setVariant -bez fD ()Z isPlayingDead -bez fx ()Lbez$e; getVariant -bez w (Z)V setPlayingDead -bfe fv ()Z isScreamingGoat -bfe v (Z)V setScreamingGoat -bfk a (Lbfr;Lbfm;)V setVariant -bfk fD ()I getVariantRaw -bfk fv ()Lbfr; getColor -bfk fx ()Lbfm; getStyle -bfk x (I)V setVariantRaw -bfi A (Z)V setStanding -bfi b (Ljava/util/UUID;)V setOwnerUUID -bfi fF ()Z isTamed -bfi fG ()Ljava/util/UUID; getOwnerUUID -bfi fK ()Z hasReproduced -bfi fL ()I getTemper -bfi fM ()V loadChest -bfi fO ()D getJumpStrength -bfi fQ ()Lafd; getSoundAngry -bfi fS ()I getMaxDomestication -bfi fw ()I getChestSlots -bfi v (I)V setTemper -bfi w (Z)V setTamed -bfh fv ()Z isCarryingChest -bfh v (Z)V setCarryingChest -bfl ge ()I getStrength -bfl gg ()I getVariant -bfl x (I)V setVariant -bfl y (I)V setStrength -bfw a (Lgg;)V setBeamTarget -bfw a (Z)V setShowingBottom -bfw h ()Lgg; getBeamTarget -bfw i ()Z isShowingBottom -bfx ft ()Lbgo; getDragonControllerManager -bfx fu ()Lcnx; getEnderDragonBattle -bfx g (Lasp;F)Z dealDamage -bgo a (Lbgn;)V setControllerPhase -bgn a (I)Lbgn; getById -bgh i ()Lbgn; getControllerPhase -bgr a (II)V setHeadTarget -bgr n ()V beginSpawnSequence -bgr t ()I getInvul -bgr t (I)V setInvul -bgr u (I)I getHeadTarget -bgt a (Lgy;)V setHeadPose -bgt a (Z)V setSmall -bgt b (Lgy;)V setBodyPose -bgt c (Lgy;)V setLeftArmPose -bgt d (Lgy;)V setRightArmPose -bgt e (Lgy;)V setLeftLegPose -bgt f (Lgy;)V setRightLegPose -bgt n ()Z isSmall -bgt p ()Z hasArms -bgt q ()Z hasBasePlate -bgt r (Z)V setArms -bgt s (Z)V setBasePlate -bgt t ()Z isMarker -bgt t (Z)V setMarker -bgv a (Lgl;)V setDirection -bgv p ()V updateBoundingBox -bgv q ()Z survives -bgv r ()I getHangingWidth -bgv s ()I getHangingHeight -bgv t ()V playPlaceSound -bgv v ()Lgg; getBlockPosition -bgw a (I)V setRotation -bgw a (IZ)V setRotation -bgw a (Lbqp;)V setItem -bgw a (Lbqp;Z)V setItem -bgw w ()Lbqp; getItem -bgw x ()I getRotation -bgy a ()I getWidth -bgy b ()I getHeight -bhb j ()Lcks; getBlock -bhc a (I)V setPickupDelay -bhc a (Lbqp;)V setItemStack -bhc b (Ljava/util/UUID;)V setOwner -bhc c (Ljava/util/UUID;)V setThrower -bhc h ()Lbqp; getItemStack -bhc i ()Ljava/util/UUID; getOwner -bhc j ()Ljava/util/UUID; getThrower -bhc n ()V defaultPickupDelay -bhc z ()V mergeNearby -bhd a (I)V setFuseTicks -bhd h ()Latt; getSource -bhd i ()I getFuseTicks -bhd j ()V explode -bhj fB ()V createEffectCloud -bhj fv ()V ignite -bhj fw ()Z canCauseHeadDrop -bhj fx ()V setCausedHeadDrop -bhj fy ()V explode -bhj t ()Z isIgnited -bhn c (Lcks;)V setCarried -bhn fv ()Lcks; getCarried -bhr p ()I getPower -bht t ()Lafd; getSoundFlop -bih a (Lbih$a;)V setSpell -bih fG ()Lbih$a; getSpell -bih fv ()Lafd; getSoundCastSpell -bih$c l ()Lbih$a; getCastSpell -bhy fB ()Z isPatrolLeader -bhy fE ()Z isPatrolling -bhy fx ()Lgg; getPatrolTarget -bhy g (Lgg;)V setPatrolTarget -bhy v (Z)V setPatrolLeader -bhz a (I)V setSize -bhz n ()I getSize -bid a (I)V setPeek -bid a (Lgl;)V setAttachFace -bid fB ()I getPeek -bid t ()Lgl; getAttachFace -big a (IZ)V setSize -big fw ()Lafd; getSoundSquish -big fx ()Lafd; getSoundJump -big fy ()I getSize -bik p ()Z isShivering -bik v (Z)V setShivering -bil fv ()Z isCharging -bil v (Z)V setCharging -biq a (I)V startDrownedConversion -biq fC ()Z isDrownConverting -biq t ()Lafd; getSoundStep -bir a (Ljava/util/UUID;I)V startConversion -bir c (Lna;)V setOffers -bir fF ()Z isConverting -bir fI ()I getConversionProgress -bhk H ()Latt; getGoalTarget -bit fD ()Z isImmuneToZombification -bit fw ()Z isConverting -bit v (Z)V setImmuneToZombification -biy p ()Z isImmuneToZombification -biy t ()Z isConverting -biy v (Z)V setImmuneToZombification -bjq fR ()Z canPlant -bjq gd ()V populateTrades -bjq v (I)V setExperience -bjw fG ()I getDespawnDelay -bjw v (I)V setDespawnDelay -bjo fF ()Lart; getInventory -bjr a ()Lbjv; getType -bjr a (I)Lbjr; withLevel -bjr a (Lbjt;)Lbjr; withProfession -bjr a (Lbjv;)Lbjr; withType -bjr b ()Lbjt; getProfession -bjr c ()I getLevel -bjs a (Lbjr;)V setVillagerData -bjs fG ()Lbjr; getVillagerData -bkd a (ILbvn;IIZZ)V openTrade -bkd a (Ljava/util/Collection;)I discoverRecipes -bkd a (Lgg;)Lcom/mojang/datafixers/util/Either; sleep -bkd a (Labr;Lgg;FZZ)Ljava/util/Optional; getBed -bkd a (Lasd;)Ljava/util/OptionalInt; openContainer -bkd a (Lbfi;Lart;)V openHorseInventory -bkd a (Lbqp;I)V enchantDone -bkd a (Lbqp;Larz;)V openBook -bkd a (Lbqp;Z)Lbhc; drop -bkd a (Lcjp;)V openSign -bkd a (Z)Z dropItem -bkd a (ZZ)V wakeup -bkd b (Ljava/util/Collection;)I undiscoverRecipes -bkd c (I)V levelDown -bkd c (Ljava/lang/String;)Ljava/util/UUID; getOfflineUUID -bkd d (I)V giveExp -bkd d (Latf;)V attack -bkd d (Lcks;)Z hasBlock -bkd f ()Z isCreative -bkd fA ()Lna; getShoulderEntityRight -bkd fC ()V resetAttackCooldown -bkd fD ()Lbqm; getCooldownTracker -bkd fF ()Z isCreativeAndOp -bkd fd ()I getScore -bkd fe ()V removeCursedItems -bkd fi ()Lcom/mojang/authlib/GameProfile; getProfile -bkd fj ()Lbkc; getInventory -bkd fk ()Lbka; getAbilities -bkd fl ()Z isDeeplySleeping -bkd fo ()V startGliding -bkd fp ()V stopGliding -bkd fr ()I getExpToLevel -bkd fs ()Lbmf; getFoodData -bkd fv ()Lbnr; getEnderChest -bkd fw ()V releaseShoulderEntities -bkd fx ()Ldny; getScoreboard -bkd fz ()Lna; getShoulderEntityLeft -bkd i (Lna;)V setShoulderEntityLeft -bkd j (Lna;)V setShoulderEntityRight -bkd k (Lna;)V spawnEntityFromShoulder -bkd n ()V closeInventory -bkd q (DDD)V checkMovement -bkd t ()V updateAbilities -bkd t (I)V setScore -bkd u (F)V applyExhaustion -bkd u (I)V addScore -bkd v (F)F getAttackCooldown -bkc a (Lbqp;Lbqp;)Z isSimilarAndNotFull -bkc d (Lbqp;)I firstPartial -bkc e (Lbqp;)Z pickup -bkc f ()Lbqp; getItemInHand -bkc g ()I getHotbarSize -bkc h ()I getFirstEmptySlotIndex -bkc k ()V dropContents -bkh a (I)V setKnockbackStrength -bkh a (Z)V setCritical -bkh b (B)V setPierceLevel -bkh h (D)V setDamage -bkh j ()Lafd; getSoundHit -bkh l ()Lbqp; getItemStack -bkh n ()D getDamage -bkh p ()Z isCritical -bkh q ()Z isShotFromCrossbow -bkh q (Z)V setShotFromCrossbow -bkh r ()B getPierceLevel -bkm a (Lbqp;)V setItem -bkl h ()Latt; getOwner -bkn a (Lbqp;)V setItem -bkn l ()Lbqp; getItem -bko i ()Z isShotAtAngle -bko j ()V explode -bko l ()Z hasExplosions -bkp c (Latf;)V reel -bkp h ()Z isInOpenWater -bkp i ()Lbkd; getOwner -bkp j ()Latf; getHooked -bkp x (Latf;)V updateHookedEntity -ble n ()V splash -ble o ()Z isLingering -bkz a (Lbqp;)V setItem -bkz i ()Lbql; getDefaultItem -bkz j ()Lbqp; getItem -bkj a (Lasz;)V addEffect -bkj c (I)V setColor -bkj v ()I getColor -blg a (Z)V setCharged -blg l ()Z isCharged -bkt b (Latf;)V setShooter -bkt c (DDDFF)V shoot -bkt w ()Latf; getShooter -bkq h ()Lbqp; getSuppliedItem -blj fI ()Z isCanJoinRaid -blj y (Z)V setCanJoinRaid -blk a (Lgg;I)Lbli; getNearbyRaid -bli d ()Z isStopped -bli e ()Z isVictory -bli f ()Z isLoss -bli i ()Lbwp; getWorld -bli j ()Z isStarted -bli k ()I getGroupsSpawned -bli l ()I getMaxBadOmenLevel -bli m ()I getBadOmenLevel -bli n ()V stop -bli p ()V updateProgress -bli q ()F sumMobHealth -bli t ()Lgg; getCenter -bli u ()I getId -blu a (F)V setDamage -blu a (Lblu$b;)V setType -blu n ()F getDamage -blu q ()Lblu$b; getType -bls a (F)V setDamage -bls b (Lcks;)V setDisplayBlock -bls h ()D getMaxSpeed -bls j ()V decelerate -bls l ()F getDamage -bls m (I)V setDisplayBlockOffset -bls n ()I getType -bls p ()Lbls$a; getMinecartType -bls q ()Lcks; getDisplayBlock -bls s ()I getDisplayBlockOffset -bly w ()Lbvp; getCommandBlock -blt a (Lww;J)V setLootTable -bma n (I)V setCooldown -bma p (Z)V setEnabled -bma w ()Z isEnabled -bmg a ()I getNutrition -bmg b ()F getSaturationModifier -bmf a ()I getFoodLevel -bmf a (IF)V eat -bmf e ()F getSaturationLevel -bmj a ()Lbnn; getType -bmj a (I)Lboa; getSlot -bmj a (II)V setContainerData -bmj a (Lbkd;)Z canUse -bmj a (Lbmv;)V addSlotListener -bmj b ()V updateInventory -bmj b (ILbqp;)V setItem -bmj b (Lbkd;I)Lbqp; shiftClick -bmj b (Lbqp;)V setCarried -bmj f ()Lbqp; getCarried -bmu a (Lbwp;Lgg;)Lbmu; at -bmz a (I)V set -bmz b ()I get -bmw a (Lbmj;II)V sendDataChange -bmw a (Lbmj;ILbqp;)V sendSlotChange -bmw a (Lbmj;Lgs;Lbqp;[I)V sendInitialData -bmw a (Lbmj;Lbqp;)V sendCarriedChange -bmt a (I)I getProperty -bmt a (II)V setProperty -bmv a (Lbmj;II)V setContainerData -bno g ()Lbvm; getRecipe -bnu a (Lbth;)V setRecipeUsed -bnu a (Lbwp;Labs;Lbth;)Z setRecipeUsed -bnu b (Lbkd;)V awardUsedRecipes -bnu d ()Lbth; getRecipeUsed -boa a ()I getMaxStackSize -boa a (Lbkd;)Z isAllowed -boa a (Lbqp;)Z isAllowed -boa a_ (Lbqp;)I getMaxStackSize -boa d (Lbqp;)V set -boa e ()Lbqp; getItem -boa f ()Z hasItem -bpl a ()I getColorIndex -bpl a (I)Lbpl; fromColorIndex -bpl d ()[F getColor -bpl f ()I getFireworksColor -bql N_ ()Lbqp; createItemStack -bql a ()Ljava/lang/String; getName -bql a (Lbql;)I getId -bql a (Lbqp;Lcks;)F getDestroySpeed -bql a (Lbzo;)Lbql; getItemOf -bql a_ (Lcks;)Z canDestroySpecialBlock -bql b (I)Lbql; getById -bql l ()I getMaxStackSize -bql m ()I getMaxDurability -bql n ()Z usesDurability -bql r ()Lbql; getCraftingRemainingItem -bql u ()Z isFood -bql v ()Lbmg; getFoodInfo -bot d ()Z isCheckCollisions -bot e ()Lbzo; getBlock -bqm a (Lbql;)Z hasCooldown -bqm a (Lbql;I)V setCooldown -bqp A ()Z canEnchant -bqp B ()Z hasEnchantments -bqp F ()I getRepairCost -bqp I ()I getCount -bqp N ()V checkEmpty -bqp a (I)Lbqp; cloneAndSubtract -bqp a (ILjava/util/Random;Labs;)Z isDamaged -bqp a (ILatt;Ljava/util/function/Consumer;)V damage -bqp a (Lbqp;)Z doMaterialsMatch -bqp a (Lbqp;Lbqp;)Z equals -bqp a (Lbsr;)Lasa; placeItem -bqp a (Lbuj;I)V addEnchantment -bqp b ()Z isEmpty -bqp b (I)V setDamage -bqp b (Lna;)Lna; save -bqp b (Lbqp;Lbqp;)Z matches -bqp b (Lcks;)Z canDestroySpecialBlock -bqp c ()Lbql; getItem -bqp c (I)V setRepairCost -bqp c (Ljava/lang/String;)V removeTag -bqp c (Lna;)V setTag -bqp d ()I getMaxStackSize -bqp e ()Z isStackable -bqp e (I)V setCount -bqp f (I)V add -bqp g (I)V subtract -bqp h ()I getDamage -bqp m ()Lbqp; cloneItemStack -bqp r ()Z hasTag -bqp s ()Lna; getTag -bqp t ()Lna; getOrCreateTag -bqp u ()Lng; getEnchantments -bqp v ()Los; getName -bqp x ()Z hasName -bqv a (Labr;Lbqp;)V applySepiaFilter -bqv a (Lbqp;Lbwp;)Ldhs; getSavedMap -bqv a (Lbwp;IIBZZ)Lbqp; createFilledMapView -bsm a (Lbqp;)Ljava/util/List; getEffects -bsr a ()Lgg; getClickPosition -bsr h ()Z isSneaking -bsr k ()Lgl; getClickedFace -bsr l ()Ldna; getPos -bsr n ()Lbqp; getItemStack -bsr o ()Lbkd; getEntity -bsr p ()Larz; getHand -bsr q ()Lbwp; getWorld -bti a (Lww;)Ljava/util/Optional; getRecipe -bti a (Lbtk;Lart;Lbwp;)Ljava/util/Optional; craft -bth Q_ ()Z isComplex -bth R_ ()Lbtj; getRecipeSerializer -bth c ()Lbqp; getResult -bth f ()Lww; getKey -bst b ()F getExperience -bst e ()I getCookingTime -bte f ()V buildChoices -buj a ()I getMaxLevel -buj a (Lbqp;)Z canEnchant -buj b ()Z isTreasure -buj b (Lbuj;)Z isCompatible -buj e ()I getStartLevel -bul a (Lbuj;Lbqp;)I getEnchantmentLevel -bul c (Latt;)I getFireAspectEnchantmentLevel -bul d (Latt;)I getOxygenEnchantmentLevel -bul e (Lbqp;)Z shouldNotDrop -bul f (Latt;)I getDigSpeedEnchantmentLevel -buk a (Lbql;)Z canEnchant -bvl a (Lbkd;Los;I)V openTrade -bvl f (Lbkd;)V setTradingPlayer -bvl fD ()Lbwp; getWorld -bvl fv ()Lbkd; getTrader -bvl fx ()Lbvn; getOffers -bvl fy ()Z isRegularVillager -bvl fz ()Lafd; getTradeSound -bvl t ()I getExperience -bvl u (I)V setForcedExperience -bvm a (I)V increaseSpecialPrice -bvm b ()Lbqp; getBuyItem1 -bvm b (I)V setSpecialPrice -bvm c ()Lbqp; getBuyItem2 -bvm d ()Lbqp; getSellingItem -bvm g ()I getUses -bvm h ()V resetUses -bvm i ()I getMaxUses -bvm j ()V increaseUses -bvm k ()I getDemand -bvm l ()V setSpecialPrice -bvm m ()I getSpecialPrice -bvm n ()F getPriceMultiplier -bvm o ()I getXp -bvm p ()Z isFullyUsed -bvm s ()Z isRewardExp -bvu a ()J pair -bvu a (II)J pair -bvu a (J)I getX -bvu b (J)I getZ -bvu h ()I getRegionX -bvu i ()I getRegionZ -bvp a (Ljava/lang/String;)V setCommand -bvp a (Los;)V setName -bvp i ()Ldl; getWrapper -bvp l ()Ljava/lang/String; getCommand -bvp m ()Los; getName -bwm a ()I getId -bwm a (I)Lbwm; getById -bwm f ()Z isCreative -bwh d ()Latt; getSource -bwh e ()V clearBlocks -bwh f ()Ljava/util/List; getBlocks -bwl a (Lbwl$e;)Lbwl$g; get -bwl b (Lbwl$e;)Z getBoolean -bwl c (Lbwl$e;)I getInt -bwl$f a ()Lbwl$g; getValue -bwl$g a (Ljava/lang/String;)V setValue -bwl$g a (Lnet/minecraft/server/MinecraftServer;)V onChange -bwl$g b ()Ljava/lang/String; getValue -bwl$g c ()I getIntValue -bwq L ()Lcmo; getChunkProvider -bwq M ()Lbxh; getFluidTickList -bwq N ()Lbxh; getBlockTickList -bwq a (Lgg;Lbzo;)V update -bwq a (Lht;DDDDDD)V addParticle -bwq a (Lbkd;Lgg;Lafd;Laff;FF)V playSound -bwq af ()Larx; getDifficulty -bwq c (ILgg;I)V triggerEffect -bwq d_ (Lgg;)Lary; getDamageScaler -bwq j ()I getLogicalHeight -bwq m_ ()Ldhy; getWorldData -bwq n ()Lnet/minecraft/server/MinecraftServer; getMinecraftServer -bwq q_ ()Ljava/util/Random; getRandom -bxk E ()J getSeed -bvt a (Lbvx;)Ldmw; rayTrace -bvt a (Ldna;Ldna;Lgg;Ldnt;Lcks;)Ldmw; rayTrace -bvt a_ (Lgg;)Lcks; getType -bvt b_ (Lgg;)Ldes; getFluid -bvt c_ (Lgg;)Lcip; getTileEntity -bvr a (Lbwy;Lgg;)I getBrightness -bvr b (Lgg;I)I getLightLevel -bvy a (Latf;Ldmv;)Z getCubes -bvy g (Latf;)Z getCubes -bvy o_ ()Lcmi; getWorldBorder -bwg a (DDDD)Z isPlayerNearby -bwg a (Latf;D)Lbkd; findNearbyPlayer -bwg a (Latf;Ldmv;Ljava/util/function/Predicate;)Ljava/util/List; getEntities -bwg a_ (Latf;Ldmv;)Ljava/util/List; getEntities -bwg z ()Ljava/util/List; getPlayers -bwo k ()Lbql; getItem -bws C (Lgg;)I getLightLevel -bws D (Lgg;)Z isLoaded -bws a (II)Lcml; getChunkAt -bws a (IIIIII)Z isAreaLoaded -bws a (IILcmp;)Lcml; getChunkAt -bws a (IILcmp;Z)Lcml; getChunkAt -bws a (Lgg;Lgg;)Z areChunksLoadedBetween -bws a (Lcps$a;Lgg;)Lgg; getHighestBlockYAt -bws b (II)Z isChunkLoaded -bws d (Ldmv;)Z containsLiquid -bws j_ ()Z isClientSide -bws l_ ()I getSeaLevel -bws p_ ()Lcnu; getDimensionManager -bws w (Lgg;)Lbxo; getBiome -bws x (Lgg;)Z isEmpty -bwx a (Lgg;Lcks;I)Z setTypeAndData -bwx b (Latf;)Z addEntity -bwr ag ()I getMaxBuildHeight -bwr ah ()I getSectionsCount -bwr ai ()I getMinSection -bwr aj ()I getMaxSection -bwr e (I)I getSectionIndex -bwr f (I)I getSectionIndexFromSectionY -bwr g (I)I getSectionYFromSectionIndex -bwr s_ ()I getMinBuildHeight -bwr t_ ()I getHeight -bwr v (Lgg;)Z isOutsideWorld -bvq a (Latj;)V setMobName -bvq a (Lbwp;Lgg;Lbxf;)V setSpawnData -bvq b (Lbwp;Lgg;)Lww; getMobName -bxf c ()Lna; getEntity -bwz a (Lbwp;Lcmw;)Lgg; getRandomPosition -bwv a (Lcps$a;Lgg;)Lgg; getHighestBlockYAt -bwp I ()Lcol; getEntities -bwp K ()Ldny; getScoreboard -bwp P ()Z isDay -bwp Q ()Z isNight -bwp R ()V tickBlockEntities -bwp V ()J getTime -bwp W ()J getDayTime -bwp X ()Lbwl; getGameRules -bwp Z ()Z isRaining -bwp a (I)Latf; getEntity -bwp a (Lgg;Lgl;)Z isBlockFacePowered -bwp a (Lgg;Lbzo;II)V playBlockAction -bwp a (Lgg;Lcks;Lcks;I)V notify -bwp a (Latf;B)V broadcastEntityEffect -bwp a (Latf;DDDFLbwh$a;)Lbwh; explode -bwp a (Latf;DDDFZLbwh$a;)Lbwh; createExplosion -bwp a (Latf;Lasp;Lbwi;DDDFZLbwh$a;)Lbwh; createExplosion -bwp a (Lbkd;DDDLafd;Laff;FF)V playSound -bwp a (Lbkd;Latf;Lafd;Laff;FF)V playSound -bwp a (Lcip;)V setTileEntity -bwp aa ()Lwv; getDimensionKey -bwp ab ()Lapu; getMethodProfiler -bwp ac ()Ljava/util/function/Supplier; getMethodProfilerSupplier -bwp ad ()Z isDebugWorld -bwp b (Lgg;Lgl;)I getBlockFacePower -bwp b (Lgg;Lbzo;)V applyPhysics -bwp b (Lgg;Lcks;)Z setTypeUpdate -bwp b (ZZ)V setSpawnFlags -bwp c (Lgg;Lbzo;)V updateAdjacentComparators -bwp k (Lgg;)Z isValidLocation -bwp m (Lgg;)Lcmw; getChunkAtWorldCoords -bwp n (Lgg;)V removeTileEntity -bwp q ()Lbti; getCraftingManager -bwp q (Lgg;)I getBlockPower -bwp r (Lgg;)Z isBlockIndirectlyPowered -bwp s ()Z isSavingDisabled -bwp t (Lgg;)Z isRainingAt -bwp v ()I getWorldMapCount -bxd G ()Labr; getLevel -bxd h (Latf;)V addAllEntities -bwt a ()Ljava/lang/String; getLevelName -bwt b ()Lbwm; getGameType -bwt c ()Z isHardcore -bwt d ()Larx; getDifficulty -bwt f ()Lbwl; getGameRules -bxo a (Lgg;)F getAdjustedTemperature -bxo i ()F getHumidity -bxq$a b (III)Lbxo; getBiome -bzo a (I)Lcks; getByCombinedId -bzo a (Labr;Lgg;I)V dropExperience -bzo a (Lbql;)Lbzo; asBlock -bzo a (Lbsp;)Lcks; getPlacedState -bzo a (Lbwq;Lgg;Lcks;)V postBreak -bzo a (Lbwp;Lgg;Lbwh;)V wasExploded -bzo a (Lbwp;Lgg;Lcks;Latf;)V stepOn -bzo a (Lbwp;Lgg;Lcks;Latt;Lbqp;)V postPlace -bzo a (Lbwp;Lcks;Lgg;Latf;F)V fallOn -bzo a (Lcks;Labr;Lgg;Lcip;Latf;Lbqp;)Ljava/util/List; getDrops -bzo a (Lcks;Lbwp;Lgg;Lcip;Latf;Lbqp;)V dropItems -bzo e_ (Lcks;)Z isTicking -bzo f ()F getDurability -bzo i ()F getFrictionFactor -bzo i (Lcks;)I getCombinedId -bzo j ()F getSpeedFactor -bzo l ()F getJumpFactor -bzo m ()Lckt; getStates -bzo m (Lcks;)Lcge; getStepSound -bzo n ()Lcks; getBlockData -byf b ()Lbpl; getColor -cam a (Lcam;Lcks;Lbwp;Lgg;Z)Lart; getInventory -cat b (Lbvt;Lgg;Lcks;)Z canHarden -cba b (I)Lcks; setAge -cba h (Lcks;)Z isRipe -cbg n (Lcks;)Z isDiode -cbj a (Labr;Lgg;)V dispense -cbk a (Latf;Lbwp;Lcks;Lgg;Z)V setDoor -cby h (Lcks;)Z canFallThrough -ccc a (Lbwp;Lgg;ILjava/util/Random;I)V trySpread -ccc b (Lbvt;Lgg;)Lcks; getPlacedState -ccc d (Lbvt;Lgg;)Z canBurn -ccc n (Lcks;)I getBurnChance -ccc o (Lcks;)I getFlameChance -cds a (Lbwq;Lgg;)V fizz -cda d (Lcks;Lbwp;Lgg;)V melt -cdf a (Lbwp;Lgg;)V dropRecord -cdn a (Lbwp;Lgg;Lcks;Z)V setHasBook -ceh a (Lbwp;Lgg;)V play -bzd g (Lcks;)I getPower -caf q ()Lckx; getSnowmanShape -caf v ()Lckx; getIronGolemShape -cey a (Lbwp;Lgg;)V playEffect -cey d (Lcks;Lbwp;Lgg;)V interact -cfm a (Labr;Lgg;Lcks;Ljava/util/Random;)V grow -cbz d (Lcks;Lbwp;Lgg;)V fade -chk a (Lgl;)Lclj; getDirection -chk p (Lcks;)Z canSpread -cah a_ (Lcks;Lbwp;Lgg;)Lasa; harvest -cdt a (Lbwq;Lgg;Lcks;Ldes;)Z place -cdt a (Lbvt;Lgg;Lcks;Lder;)Z canPlace -bzt c (Lbwq;Lgg;Lcks;)Lbqp; removeFluid -cbv a (Lgg;Lcks;)Lcip; createTile -cge a ()F getVolume -cge b ()F getPitch -cge d ()Lafd; getStepSound -cge e ()Lafd; getPlaceSound -cge g ()Lafd; getFallSound -ciz a ()I getOpenerCount -cjn f ()I getLastVibrationFrequency -cip Y_ ()Lpy; getUpdatePacket -cip a (Lgg;Lcks;Lna;)Lcip; create -cip a (Lna;)V load -cip a (Lbwp;)V setWorld -cip a_ (II)Z setProperty -cip b (Lna;)Lna; save -cip e ()V update -cip k ()Lbwp; getWorld -cip l ()Z hasWorld -cip m ()Lgg; getPosition -cip n ()Lcks; getBlock -cip o ()Z isRemoved -cip q ()Z isFilteredNBT -cip r ()Lcir; getTileType -cii a (Lcks;Lafd;)V playOpenSound -cii a (Lcks;Z)V setOpenFlag -cik a (Los;)V setCustomName -cik a (Lbwp;Lgg;ILasx;Lasx;)V applyEffects -cim a (Latf;Z)V addBee -cim a (Lbwp;Lgg;Lcks;Lcim$a;Ljava/util/List;Lcim$b;Lgg;)Z releaseBee -cim a (Lcks;Lcim$b;)Ljava/util/List; releaseBees -cim f ()Z isEmpty -cim g ()Z isFull -cim h ()I getBeeCount -cim i ()Z isSedated -cit d ()Lgs; getItems -ciu a (Lbwp;Lgg;Lcks;Lafd;)V playOpenSound -ciw d ()Lbvp; getCommandBlock -cij a (ILbkc;)Lbmj; createContainer -cij a (Los;)V setCustomName -cij g ()Los; getContainerName -cjb a (Lbqp;)I addItem -cjd a (Los;)V setCustomName -cif a (Lbqp;)I fuelTime -cif a (Lbth;Lgs;I)Z canBurn -cif a (Lbwp;Lbtk;Lart;)I getRecipeCookingTime -cif b (Lbqp;)Z isFuel -cif b (Lbth;Lgs;I)Z burn -cif h ()Z isBurning -cjh a (Lart;Lart;Lbqp;Lgl;)Lbqp; addItem -cjh c (I)V setCooldown -cjj a (Lbqp;)V setRecord -cjj d ()Lbqp; getRecord -cjk a (I)V setPage -cjk a (Lbqp;)V setBook -cjk f ()Lbqp; getBook -cjk g ()Z hasBook -cjk h ()I getPage -cjm a (Lww;J)V setLootTable -cjs d ()Lbvq; getSpawner -cjp a (Lbpl;)Z setColor -cjp b (Z)Z setHasGlowingText -cjp g ()Lbpl; getColor -cjp h ()Z hasGlowingText -cjq a (Lcom/mojang/authlib/GameProfile;)V setGameProfile -cjt a (Ljava/lang/String;)V setStructureName -cjt a (Latt;)V setAuthor -cjt a (Lcmb;)V setUsageMode -cjt d ()Ljava/lang/String; getStructureName -cjt u ()Lcmb; getUsageMode -cir a (Lcks;)Z isValidBlock -ckp c ()Ljava/util/List; getMovedBlocks -ckp d ()Ljava/util/List; getBrokenBlocks -ckr a (Lcks;Lgl;Lcks;Lbwq;Lgg;Lgg;)Lcks; updateState -ckr a (Lcks;Labr;Lgg;Ljava/util/Random;)V tickAlways -ckr a (Lcks;Labr;Lgg;Lbqp;)V dropNaturally -ckr a (Lcks;Lbkd;Lbvt;Lgg;)F getDamage -ckr a (Lcks;Lbws;Lgg;)Z canPlace -ckr a (Lcks;Lbwp;Lgg;Lbkd;)V attack -ckr a (Lcks;Lbwp;Lgg;Lbkd;Larz;Ldmw;)Lasa; interact -ckr a (Lcks;Lbwp;Lgg;Lbzo;Lgg;Z)V doPhysics -ckr a (Lcks;Lbwp;Lgg;Lcks;Z)V remove -ckr b (Lcks;Labr;Lgg;Ljava/util/Random;)V tick -ckr b (Lcks;Lbwp;Lgg;)Lasd; getInventory -ckr b (Lcks;Lbwp;Lgg;Lcks;Z)V onPlace -ckr d (Lcks;)Ldey; getPushReaction -ckr d_ (Lcks;)Z isComplexRedstone -ckr f_ (Lcks;)Z isPowerSource -ckr k ()Lbql; getItem -ckr$a a (Lgl;Lcks;Lbwq;Lgg;Lgg;)Lcks; updateState -ckr$a a (Labr;Lgg;Lbqp;)V dropNaturally -ckr$a a (Lbkd;Lbvt;Lgg;)F getDamage -ckr$a a (Lbws;Lgg;)Z canPlace -ckr$a a (Lbwp;Lgg;Lbkd;)V attack -ckr$a a (Lbwp;Lgg;Lbzo;Lgg;Z)V doPhysics -ckr$a a (Lbwp;Lgg;Lcks;Z)V onPlace -ckr$a a (Lbwp;Lbkd;Larz;Ldmw;)Lasa; interact -ckr$a b ()Lbzo; getBlock -ckr$a b (Lbwp;Lgg;Lcks;Z)V remove -ckr$a c ()Ldew; getMaterial -ckr$a g ()Z isAir -ckr$a g (Lbvt;Lgg;)Z isOccluding -ckr$a i ()Z isPowerSource -ckr$a j ()Z isComplexRedstone -ckr$a j (Lbvt;Lgg;)Ldnt; getShape -ckr$a k ()Ldey; getPushReaction -ckr$a k (Lbvt;Lgg;)Ldnt; getCollisionShape -ckr$a m ()Z isTileEntity -ckr$a n ()Ldes; getFluid -ckr$a o ()Z isTicking -ckr$a p ()Lcge; getStepSound -ckr$a r ()Z isRequiresSpecialTool -ckt b ()Lcku; getBlockData -ckt c ()Ljava/lang/Object; getBlock -cku a (Lclv;Ljava/lang/Comparable;)Ljava/lang/Object; set -cku c (Lclv;)Ljava/lang/Comparable; get -cku t ()Lcom/google/common/collect/ImmutableMap; getStateMap -ckx$b b ()Lgl; getFacing -ckw d ()Lgg; getPosition -clj a (Ljava/lang/String;)Lclj; of -clm a (Ljava/lang/String;)Lclm; of -clq a (Ljava/lang/String;Ljava/lang/Class;)Lclq; of -clq a (Ljava/lang/String;Ljava/lang/Class;[Ljava/lang/Enum;)Lclq; of -cls a (Ljava/lang/String;II)Lcls; of -clv a ()Ljava/util/Collection; getValues -clv f ()Ljava/lang/String; getName -clv g ()Ljava/lang/Class; getType -cmi a ()D getCenterX -cmi a (D)V setSize -cmi a (DDJ)V transitionSizeBetween -cmi a (Lbvu;)Z isInBounds -cmi b ()D getCenterZ -cmi b (D)V setDamageBuffer -cmi b (I)V setWarningTime -cmi c (D)V setDamageAmount -cmi c (DD)V setCenter -cmi c (I)V setWarningDistance -cmi i ()D getSize -cmi n ()D getDamageBuffer -cmi o ()D getDamageAmount -cmi q ()I getWarningTime -cmi r ()I getWarningDistance -cmw c (Z)V setLoaded -cmw t ()V markDirty -cmw u ()Z isEmpty -cmw v ()Labd$c; getState -cmw x ()V addEntities -cmw y ()Lbwp; getWorld -cmw z ()Ljava/util/Map; getTileEntities -cmn a (IILbwr;)Lbxa; getBaseColumn -cmn a (IILcps$a;Lbwr;)I getBaseHeight -cmn a (J)Lcmn; withSeed -cmn a (JLbxq;Lcml;Lcpo$a;)V doCarving -cmn a (Ljava/util/concurrent/Executor;Lbxg;Lcml;)Ljava/util/concurrent/CompletableFuture; buildNoise -cmn a (Lgw;Lcml;)V createBiomes -cmn a (Lgx;Lbxg;Lcml;Ldcp;J)V createStructures -cmn a (Labx;)V addMobs -cmn a (Labx;Lbxg;)V addDecorations -cmn a (Labx;Lcml;)V buildBase -cmn a (Labr;Lcuc;Lgg;IZ)Lgg; findNearestMapFeature -cmn a (Lbxk;Lbxg;Lcml;)V storeStructures -cmn a (Lbwr;)I getSpawnHeight -cmn a (Lbxo;Lbxg;Latw;Lgg;)Laqs; getMobsFor -cmn b ()Lcqi; getSettings -cmn c ()Lbxr; getWorldChunkManager -cmn d ()I getGenerationDepth -cmn e ()I getSeaLevel -cmn f ()I getMinY -cmx a (III)Lcks; getType -cmx a (IIILcks;)Lcks; setType -cmx a (IIILcks;Z)Lcks; setType -cmx e ()Z shouldTick -cmx g ()I getYPosition -cmx h ()V recalcBlockCounts -cmx i ()Lcnd; getBlocks -cmp g ()Lcmp$a; getType -cnd a (IIILjava/lang/Object;)Ljava/lang/Object; setBlock -cnd a (Ljava/util/function/Predicate;)Z contains -cnd b (ILjava/lang/Object;)V setBlockIndex -cml a (J)V setInhabitedTime -cml a (Lgg;Lcks;Z)Lcks; setType -cml a (Lcip;)V setTileEntity -cml a (Lcps$a;II)I getHighestBlock -cml a (Z)V setNeedsSaving -cml d ()[Lcmx; getSections -cml d (Lgg;)V removeTileEntity -cml f ()Lbvu; getPos -cml h ()Lcmm; getBiomeIndex -cml i ()Z isNeedsSaving -cml j ()Lcmp; getChunkStatus -cml r ()J getInhabitedTime -cmo a (IILcmp;Z)Lcml; getChunkAt -cmo a (IIZ)Lcmw; getChunkAt -cmo a (Ljava/util/function/BooleanSupplier;)V tick -cmo b (II)Z isLoaded -cmo e ()Ljava/lang/String; getName -cmo l ()Ldej; getLightEngine -cmy m ()Lbvt; getWorld -cmq a ()[B asBytes -cni a (Labr;Lna;Lcmw;)V loadEntities -cni a (Labr;Lcml;)Lna; saveChunk -cni a (Labr;Ldcp;Lbdm;Lbvu;Lna;)Lcne; loadChunk -cnj a (Lwv;Ljava/util/function/Supplier;Lna;)Lna; getChunkData -cnj e (Lbvu;)Lna; read -cno e (Lbvu;)Z chunkExists -cno g (Lbvu;)I getOffset -cnp a (Lbvu;)Lna; read -cnp a (Lbvu;Lna;)V write -cnp b (Lbvu;)Lcno; getFile -cnu a ()Ljava/lang/String; getSuffix -cnu b ()Z hasSkyLight -cnu c ()Z hasCeiling -cnu d ()Z isNether -cnu e ()Z isNatural -cnu f ()D getCoordinateScale -cnu g ()Z isPiglinSafe -cnu h ()Z isBedWorks -cnu i ()Z isRespawnAnchorWorks -cnu j ()Z hasRaids -cnu k ()I getMinY -cnu l ()I getHeight -cnu m ()I getLogicalHeight -cnu n ()Z isCreateDragonBattle -cnu o ()Lbxt; getGenLayerZoomer -cnu p ()Z isFixedTime -cnx a (Lcnw;)V setRespawnPhase -cnx a (Z)V generateExitPortal -cnx d ()Z isPreviouslyKilled -cnx e ()V initiateRespawn -cnx f ()V resetCrystals -cnx j ()Lckx$b; getExitPortalShape -coc Z ()I getId -coc b (Latf$c;)V setRemoved -coc cC ()Ljava/util/stream/Stream; recursiveStream -coc cR ()Lgg; getChunkCoordinates -coc ch ()Ljava/util/UUID; getUniqueID -coc cr ()Ldmv; getBoundingBox -cqk a ()J getSeed -cqk b ()Z shouldGenerateMapFeatures -cqk e ()Lcmn; getChunkGenerator -cqk g ()Z isDebugWorld -cqk h ()Z isFlatWorld -cuc a (Lbws;Lbxg;Lgg;IZJLcwl;)Lgg; getNearestGeneratedFeature -csf a (Lcsg;)Z generate -des a ()Lder; getType -des a (Lbvt;Lgg;)F getHeight -des b ()Z isSource -des c ()Z isEmpty -des g ()Lcks; getBlockData -dew a ()Z isLiquid -dew b ()Z isBuildable -dew c ()Z isSolid -dew d ()Z isBurnable -dew e ()Z isReplaceable -dew g ()Ldey; getPushReaction -dhj b ()V createPortal -dhh a (Lgg;Lgl$a;)Ljava/util/Optional; createPortal -dhh a (Lgg;Z)Ljava/util/Optional; findPortal -dhp a ()B getIconType -dhp b ()Ldhp$a; getType -dhp c ()B getX -dhp d ()B getY -dhp e ()B getRotation -dhp g ()Los; getName -dhs a (II)V flagDirty -dhs a (Lbqp;Lgg;Ljava/lang/String;Ldhp$a;)V decorateMap -dhs g ()V flagDecorationsDirty -dib$a a ()Ljava/lang/String; getLevelName -dib$a a (Lahc;)Z convert -dib$a a (Ldhz;)Ljava/nio/file/Path; getWorldFolder -dib$a c ()Z isConvertable -dib$a i ()V checkSession -dih a (I)V setClearWeatherTime -dih a (J)V setTime -dih a (Lbwm;)V setGameType -dih a (Z)V setThundering -dih b (J)V setDayTime -dih e (I)V setThunderDuration -dih f (I)V setWeatherDuration -dih g ()Ljava/lang/String; getName -dih h ()I getClearWeatherTime -dih j ()I getThunderDuration -dih l ()I getWeatherDuration -dih m ()Lbwm; getGameType -dii A ()Lcqk; getGeneratorSettings -dii E ()Lna; getCustomBossEvents -dii a (Larx;)V setDifficulty -dii a (Lbwm;)V setGameType -dii b (Lna;)V setCustomBossEvents -dii g ()Ljava/lang/String; getName -dii m ()Lbwm; getGameType -dii n ()Z isHardcore -dii s ()Larx; getDifficulty -dii t ()Z isDifficultyLocked -dhy b (Z)V setStorm -dhy e ()J getTime -dhy f ()J getDayTime -dhy i ()Z isThundering -dhy k ()Z hasStorm -dhy n ()Z isHardcore -dhy s ()Larx; getDifficulty -dhy t ()Z isDifficultyLocked -dij a (Lgg;F)V setSpawn -dif a ()[Ljava/lang/String; getSeenPlayers -dif a (Lbkd;)V save -dif b (Lbkd;)Lna; load -dis a ()Ldkt; getLootContextParameterSet -dis a (Lart;Ldip;)V fillInventory -dis a (Ldip;)Ljava/util/List; populateLoot -dis a (Ldip;Ljava/util/function/Consumer;)V populateLootDirect -dis b (Ldip;Ljava/util/function/Consumer;)V populateLoot -dip a (Ldks;)Z hasContextParameter -dip b ()F getLuck -dip c ()Labr; getWorld -dip c (Ldks;)Ljava/lang/Object; getContextParameter -dip$a a (Ldks;Ljava/lang/Object;)Ldip$a; set -dip$a a (Ldkt;)Ldip; build -dip$a b (Ldks;Ljava/lang/Object;)Ldip$a; setOptional -dit a (Lww;)Ldis; getLootTable -djh$b a (Lcom/google/gson/JsonObject;Ldjh;Lcom/google/gson/JsonSerializationContext;)V serializeType -djh$b b (Lcom/google/gson/JsonObject;Lcom/google/gson/JsonDeserializationContext;[Ldlh;)Ldjh; deserializeType -dkt a ()Ljava/util/Set; getRequired -dkt b ()Ljava/util/Set; getOptional -dkt$a a ()Ldkt; build -dkt$a a (Ldks;)Ldkt$a; addRequired -dkt$a b (Ldks;)Ldkt$a; addOptional -dmv c (DDD)Ldmv; grow -dmv h (D)Ldmv; shrink -dmy c ()Ldmy$a; getType -dmy e ()Ldna; getPos -dmw a ()Lgg; getBlockPosition -dmw b ()Lgl; getDirection -dmx a ()Latf; getEntity -dna b (DDD)Ldna; add -dna g (Ldna;)D distanceSquared -dnt a ()Ldmv; getBoundingBox -dnt a (Ldna;Ldna;Lgg;)Ldmw; rayTrace -dnt b ()Z isEmpty -dnq a (DDDDDD)Ldnt; create -dny a (I)Ldnv; getObjectiveForSlot -dny a (ILdnv;)V setDisplaySlot -dny a (Ljava/lang/String;)V handlePlayerRemoved -dny a (Ljava/lang/String;Ldnw;)Z addPlayerToTeam -dny a (Ljava/lang/String;Ldob;Los;Ldob$a;)Ldnv; registerObjective -dny a (Ldnv;)V handleObjectiveAdded -dny a (Ldnx;)V handleScoreChanged -dny a (Ldnw;)V handleTeamAdded -dny a (Ldob;Ljava/lang/String;Ljava/util/function/Consumer;)V getObjectivesForCriteria -dny b (I)Ljava/lang/String; getSlotName -dny b (Ljava/lang/String;Ldnw;)V removePlayerFromTeam -dny b (Ldnv;)V handleObjectiveChanged -dny b (Ldnw;)V handleTeamChanged -dny c ()Ljava/util/Collection; getObjectives -dny c (Ljava/lang/String;Ldnv;)Ldnx; getPlayerScoreForObjective -dny c (Ldnv;)V handleObjectiveRemoved -dny c (Ldnw;)V handleTeamRemoved -dny d (Ljava/lang/String;)Ldnv; getObjective -dny d (Ljava/lang/String;Ldnv;)V resetPlayerScores -dny d (Ldnw;)V removeTeam -dny e ()Ljava/util/Collection; getPlayers -dny e (Ljava/lang/String;)Ljava/util/Map; getPlayerObjectives -dny f (Ljava/lang/String;)Ldnw; getTeam -dny g ()Ljava/util/Collection; getTeams -dny g (Ljava/lang/String;)Ldnw; createTeam -dny h (Ljava/lang/String;)Z removePlayerFromTeam -dny i (Ljava/lang/String;)Ldnw; getPlayerTeam -dny i (Ldnv;)Ljava/util/Collection; getScoresForObjective -dny j (Ljava/lang/String;)I getSlotForName -dny j (Ldnv;)V unregisterObjective -dnv a (Los;)V setDisplayName -dnv a (Ldob$a;)V setRenderType -dnv b ()Ljava/lang/String; getName -dnv c ()Ldob; getCriteria -dnv d ()Los; getDisplayName -dnv f ()Ldob$a; getRenderType -dnx a ()V incrementScore -dnx a (I)V addScore -dnx b ()I getScore -dnx b (I)V setScore -dnx d ()Ldnv; getObjective -dnx e ()Ljava/lang/String; getPlayerName -dnw a (Lp;)V setColor -dnw a (Los;)V setDisplayName -dnw a (Ldoa$b;)V setNameTagVisibility -dnw a (Ldoa$a;)V setCollisionRule -dnw a (Z)V setAllowFriendlyFire -dnw b (Los;)V setPrefix -dnw b (Ldoa$b;)V setDeathMessageVisibility -dnw b (Z)V setCanSeeFriendlyInvisibles -dnw c ()Los; getDisplayName -dnw c (Los;)V setSuffix -dnw e ()Los; getPrefix -dnw f ()Los; getSuffix -dnw m ()I packOptionData -doa a (Ldoa;)Z isAlly -doa b ()Ljava/lang/String; getName -doa d (Los;)Loy; getFormattedName -doa g ()Ljava/util/Collection; getPlayerNameSet -doa h ()Z allowFriendlyFire -doa i ()Z canSeeFriendlyInvisibles -doa j ()Ldoa$b; getNameTagVisibility -doa k ()Ldoa$b; getDeathMessageVisibility -doa l ()Ldoa$a; getCollisionRule -doa n ()Lp; getColor -dob d ()Ljava/lang/String; getName -dob e ()Z isReadOnly diff --git a/gradle.properties b/gradle.properties index 70f5bef212..b26ff13432 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -mcVersion = 1.16 +mcVersion = 1.17 projectVersion = 1.17-R0.1-SNAPSHOT packageVersion = 1_17_R1 diff --git a/paper b/paper deleted file mode 100755 index a397d2786b..0000000000 --- a/paper +++ /dev/null @@ -1,258 +0,0 @@ -#!/usr/bin/env bash - -# resolve shell-specifics -case "$(echo "$SHELL" | sed -E 's|/usr(/local)?||g')" in - "/bin/zsh") - RCPATH="$HOME/.zshrc" - SOURCE="${BASH_SOURCE[0]:-${(%):-%N}}" - ;; - *) - RCPATH="$HOME/.bashrc" - if [[ -f "$HOME/.bash_aliases" ]]; then - RCPATH="$HOME/.bash_aliases" - fi - SOURCE="${BASH_SOURCE[0]}" - ;; -esac - -# get base dir regardless of execution location -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -SOURCE=$([[ "$SOURCE" = /* ]] && echo "$SOURCE" || echo "$PWD/${SOURCE#./}") -basedir=$(dirname "$SOURCE") -gitcmd="git -c commit.gpgsign=false" - -source "$basedir/scripts/functions.sh" - -"$basedir"/scripts/requireDeps.sh || exit 1 - -failed=0 -case "$1" in - "rb" | "rbp" | "rebuild") - ( - set -e - cd "$basedir" - scripts/rebuildPatches.sh "$basedir" $2 || exit 1 - ) || failed=1 - ;; - "rbf" | "rbfull") - ( - set -e - cd "$basedir" - scripts/rebuildPatches.sh "$basedir" "nofilter" || exit 1 - ) || failed=1 - ;; - "p" | "patch") - ( - set -e - cd "$basedir" - scripts/build.sh "$basedir" || exit 1 - ) || failed=1 - ;; - "j" | "jar") - ( - set -e - cd "$basedir" - scripts/build.sh "$basedir" "--jar" || exit 1 - ) || failed=1 - ;; - "b" | "build") - ( - set -e - cd "$basedir" - scripts/build.sh "$basedir" || exit 1 - (cd Paper-API ; mvn clean install) || exit 1 - (cd Paper-MojangAPI ; mvn clean install) || exit 1 - (cd Paper-Server ; mvn clean package) || exit 1 - echo "Paper jar successfully built" - ls -la Paper-Server/target/paper*.jar - ) || failed=1 - ;; - "i" | "install") - ( - set -e - cd "$basedir" - scripts/build.sh "$basedir" || exit 1 - mvn clean install || exit 1 - echo "Paper jar successfully built and installed to local repo" - ) || failed=1 - ;; - "pc" | "paperclip") - ( - set -e - cd "$basedir" - scripts/paperclip.sh "$basedir" || exit 1 - ) || failed=1 - ;; - "make") - ( - if [[ "$2" = "bacon" ]] ; then - set -e - cd "$basedir" - scripts/build.sh "$basedir" "--jar" - fi - ) - ;; - "m" | "mcdev") - ( - set -e - cd "$basedir" - scripts/makemcdevsrc.sh "$basedir" - ) - ;; - "t" | "test" | "testserver") - ( - cd "$basedir" - shift - scripts/testServer.sh "$basedir" "$@" - ) - ;; - "td" | "testdir") - cd "${PAPER_TEST_DIR:-$basedir/work/test-server}" - ;; - "u" | "up" | "upstream") - ( - cd "$basedir" - scripts/upstreamMerge.sh "$basedir" "$2" - ) - ;; - "cu" | "commitup" | "commitupstream" | "upc" | "upcommit" | "upstreamcommit") - ( - cd "$basedir" - shift - scripts/upstreamCommit.sh "$@" - ) - ;; - "r" | "root") - cd "$basedir" - ;; - "a" | "api") - cd "$basedir/Paper-API" - ;; - "s" | "server") - cd "$basedir/Paper-Server" - ;; - "c" | "clean") - rm -rf Paper-API - rm -rf Paper-Server - rm -rf work - echo "Cleaned build files" - ;; - "con" | "continue") - if [ -d ".git/rebase-apply" ]; then - git -c commit.gpgsign=false am --continue - elif [ -d ".git/rebase-merge" ]; then - git -c commit.gpgsign=false rebase --continue - fi - ;; - "e" | "edit") - case "$2" in - "s" | "server") - mkdir -p "$basedir/work/Temp" - echo "$basedir/Paper-Server" > "$basedir/work/Temp/PAPER_LAST_EDIT" - cd "$basedir/Paper-Server" - ( - set -e - - paperstash - $gitcmd rebase -i upstream/upstream - paperunstash - ) - ;; - "a" | "api") - mkdir -p "$basedir/work/Temp" - echo "$basedir/Paper-API" > "$basedir/work/Temp/PAPER_LAST_EDIT" - cd "$basedir/Paper-API" - ( - set -e - - paperstash - $gitcmd rebase -i upstream/upstream - paperunstash - ) - ;; - "c" | "continue") - cd "$( < "$basedir/work/Temp/PAPER_LAST_EDIT")" - rm -f "$basedir/work/Temp/PAPER_LAST_EDIT" - ( - set -e - - $gitcmd add . - $gitcmd commit --amend - $gitcmd rebase --continue - - cd "$basedir" - scripts/rebuildPatches.sh "$basedir" - ) - ;; - *) - echo "You must edit either the api or server." - ;; - esac - ;; - "setup") - if [[ -f "$RCPATH" ]] ; then - NAME="paper" - if [[ ! -z "${2+x}" ]] ; then - NAME="$2" - fi - (grep "alias $NAME=" "$RCPATH" > /dev/null) && (sed -i "s|alias $NAME=.*|alias $NAME='. $SOURCE'|g" "$RCPATH") || (echo "alias $NAME='. $SOURCE'" >> "$RCPATH") - alias "$NAME=. $SOURCE" - echo "You can now just type '$NAME' at any time to access the paper tool." - else - echo "We were unable to setup the paper build tool alias: $RCPATH is missing" - fi - ;; - *) - echo "PaperMC build tool command. This provides a variety of commands to build and manage the PaperMC build" - echo "environment. For all of the functionality of this command to be available, you must first run the" - echo "'setup' command. View below for details. For essential building and patching, you do not need to do the setup." - echo "" - echo " Normal commands:" - echo " * rb, rebuild | Rebuild patches, can be called from anywhere." - echo " * p, patch | Apply all patches to the project without building it. Can be run from anywhere." - echo " * j, jar | Apply all patches and build the project, paperclip.jar will be output. Can be run from anywhere." - echo " * i, install | Build and install paper into the local repo. Can be run from anywhere." - echo " * m, mcdev | Setup decompiled sources for non-modified NMS files to be imported into an IDE. Can be run from anywhere." - echo " * u, up, upstream | Updates the submodules used by Paper to their latest upstream versions." - echo " * upc, upstreamcommit | Creates the correctly-formatted upstream commit after updating upstream." - echo " * c, clean | Removes all generated files, Paper-API, Paper-Server, and work." - echo " * t, testserver | Run the test server with the set of plugins Paper uses as a basis for server tests." - echo " * con, continue | Shortcut command for running git am --continue, or git rebase --continue." - echo "" - echo " These commands require the setup command before use:" - echo " * r, root | Change directory to the root of the project." - echo " * a. api | Move to the Paper-API directory." - echo " * s, server | Move to the Paper-Server directory." - echo " * td, testdirectory | Move to the test-server directory." - echo " * e, edit | Use to edit a specific patch, give it the argument \"server\" or \"api\"" - echo " | respectively to edit the correct project. Use the argument \"continue\" after" - echo " | the changes have been made to finish and rebuild patches. Can be called from anywhere." - echo "" - echo " * setup | Add an alias to $RCPATH to allow full functionality of this script. Run as:" - echo " | . ./paper setup" - echo " | After you run this command you'll be able to just run 'paper' from anywhere." - echo " | The default name for the resulting alias is 'paper', you can give an argument to override" - echo " | this default, such as:" - echo " | . ./paper setup example" - echo " | Which will allow you to run 'example' instead." - ;; -esac - -unset RCPATH -unset SOURCE -unset basedir -unset -f color -unset -f colorend -unset -f paperstash -unset -f paperunstash -if [[ "$failed" == "1" ]]; then - unset failed - false -else - unset failed - true -fi diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 4ddd1eb648..0000000000 --- a/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - 4.0.0 - - - com.destroystokyo.paper - paper-parent - dev-SNAPSHOT - pom - - Paper-Parent - Parent project for all Paper modules. - https://github.com/PaperMC/Paper - - - Paper-API - Paper-MojangAPI - Paper-Server - - - - clean install - - - - UTF-8 - - - - - md_5-releases - https://repo.md-5.net/content/repositories/releases/ - - - aikar - https://repo.aikar.co/content/groups/aikar/ - - - destroystokyo-repo - https://papermc.io/repo/repository/maven-public/ - - - - - - papermc-releases - https://papermc.io/repo/repository/maven-releases/ - - - papermc-snapshots - https://papermc.io/repo/repository/maven-snapshots/ - - - diff --git a/settings.gradle.kts b/settings.gradle.kts index 5e07a69a83..54bb957497 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,10 +2,9 @@ pluginManagement { repositories { gradlePluginPortal() maven("https://wav.jfrog.io/artifactory/repo/") - mavenLocal() } } rootProject.name = "Paper" -include("Paper-API", "Paper-Server", "Paper-MojangAPI") +include("Paper-API", "Paper-Server") From fc52b39f3f5fffc5404062d2f52518250192a307 Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Fri, 11 Jun 2021 06:35:46 -0500 Subject: [PATCH 004/226] Move patches --- .../0001-POM-changes.patch | 0 .../0002-Add-FastUtil-to-Bukkit.patch | 0 .../0003-Paper-Utils.patch | 0 .../0004-Timings-v2.patch | 0 .../0005-Adventure.patch | 0 .../0006-Player-affects-spawning-API.patch | 0 .../0007-Add-getTPS-method.patch | 0 .../0008-Entity-Origin-API.patch | 0 .../0009-Version-Command-2.0.patch | 0 .../0010-Add-PlayerLocaleChangeEvent.patch | 0 .../0011-Add-player-view-distance-API.patch | 0 .../0012-Add-BeaconEffectEvent.patch | 0 .../0013-Add-PlayerInitialSpawnEvent.patch | 0 .../0014-Automatically-disable-plugins-that-fail-to-load.patch | 0 .../0015-Expose-server-CommandMap.patch | 0 ...0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch | 0 .../0017-Player-Tab-List-and-Title-APIs.patch | 0 .../0018-Add-exception-reporting-event.patch | 0 .../0019-Fix-ServerListPingEvent-flagging-as-Async.patch | 0 ...020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch | 0 ...021-Add-methods-for-working-with-arrows-stuck-in-living-.patch | 0 .../0022-Complete-resource-pack-API.patch | 0 .../0023-Use-ASM-for-event-executors.patch | 0 .../0024-Add-a-call-helper-to-Event.patch | 0 .../0025-Add-sender-name-to-commands.yml-replacement.patch | 0 ...026-Add-command-to-reload-permissions.yml-and-require-co.patch | 0 .../0027-Custom-replacement-for-eaten-items.patch | 0 .../0028-Entity-AddTo-RemoveFrom-World-Events.patch | 0 .../0029-EntityPathfindEvent.patch | 0 .../0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch | 0 .../0031-Add-MetadataStoreBase.removeAll-Plugin.patch | 0 .../0032-Add-PlayerUseUnknownEntityEvent.patch | 0 ...033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch | 0 .../0034-Arrow-pickup-rule-API.patch | 0 .../0035-EntityRegainHealthEvent-isFastRegen-API.patch | 0 .../0036-LootTable-API.patch | 0 .../0037-Add-EntityZapEvent.patch | 0 .../0038-Misc-Utils.patch | 0 .../0039-Allow-Reloading-of-Command-Aliases.patch | 0 .../0040-Add-source-to-PlayerExpChangeEvent.patch | 0 .../0041-Add-ProjectileCollideEvent.patch | 0 .../0042-Add-String-based-Action-Bar-API.patch | 0 ...043-Add-API-methods-to-control-if-armour-stands-can-move.patch | 0 .../0044-IllegalPacketEvent.patch | 0 .../0045-Fireworks-API-s.patch | 0 .../0046-PlayerTeleportEndGatewayEvent.patch | 0 .../0047-Provide-E-TE-Chunk-count-stat-methods.patch | 0 ...048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch | 0 .../0049-Expose-WorldBorder-isInBounds-Location-check.patch | 0 ...050-Add-configuration-option-to-prevent-player-names-fro.patch | 0 .../0051-Fix-upstream-javadoc-warnings-and-errors.patch | 0 .../0052-Item-canEntityPickup.patch | 0 .../0053-PlayerPickupItemEvent-setFlyAtPlayer.patch | 0 .../0054-PlayerAttemptPickupItemEvent.patch | 0 .../0055-Add-UnknownCommandEvent.patch | 0 .../0056-Basic-PlayerProfile-API.patch | 0 .../0057-Shoulder-Entities-Release-API.patch | 0 .../0058-Profile-Lookup-Events.patch | 0 .../0059-Entity-fromMobSpawner.patch | 0 .../0060-Improve-the-Saddle-API-for-Horses.patch | 0 .../0061-ensureServerConversions-API.patch | 0 .../0062-Add-getI18NDisplayName-API.patch | 0 .../0063-ProfileWhitelistVerifyEvent.patch | 0 .../0064-Make-plugins-list-alphabetical.patch | 0 .../0065-LivingEntity-setKiller.patch | 0 ...066-Handle-plugin-prefixes-in-implementation-logging-con.patch | 0 .../0067-Allow-plugins-to-use-SLF4J-for-logging.patch | 0 ...068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch | 0 .../0069-Add-PlayerJumpEvent.patch | 0 .../0070-Expose-client-protocol-version-and-virtual-host.patch | 0 .../0071-Add-PlayerArmorChangeEvent.patch | 0 .../0072-API-to-get-a-BlockState-without-a-snapshot.patch | 0 .../0073-AsyncTabCompleteEvent.patch | 0 .../0074-Display-warning-on-deprecated-recipe-API.patch | 0 .../0075-PlayerPickupExperienceEvent.patch | 0 .../0076-ExperienceOrbMergeEvent.patch | 0 .../0077-Ability-to-apply-mending-to-XP-API.patch | 0 .../0078-PreCreatureSpawnEvent.patch | 0 .../0079-PlayerNaturallySpawnCreaturesEvent.patch | 0 .../0080-Add-setPlayerProfile-API-for-Skulls.patch | 0 .../0081-Fill-Profile-Property-Events.patch | 0 .../0082-PlayerAdvancementCriterionGrantEvent.patch | 0 .../0083-Add-ArmorStand-Item-Meta.patch | 0 .../0084-Optimize-Hoppers.patch | 0 .../0085-Tameable-getOwnerUniqueId-API.patch | 0 ...086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch | 0 .../0087-Add-extended-PaperServerListPingEvent.patch | 0 .../0088-Player.setPlayerProfile-API.patch | 0 .../0089-getPlayerUniqueId-API.patch | 0 ...0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch | 0 .../0091-Add-method-to-open-already-placed-sign.patch | 0 .../0092-Add-Ban-Methods-to-Player-Objects.patch | 0 .../0093-EndermanEscapeEvent.patch | 0 .../0094-Enderman.teleportRandomly.patch | 0 .../0095-Additional-world.getNearbyEntities-API-s.patch | 0 .../0096-Location.isChunkLoaded-API.patch | 0 .../0097-Expand-World.spawnParticle-API-and-add-Builder.patch | 0 .../0098-EndermanAttackPlayerEvent.patch | 0 .../0099-Close-Plugin-Class-Loaders-on-Disable.patch | 0 .../0100-WitchConsumePotionEvent.patch | 0 .../0101-WitchThrowPotionEvent.patch | 0 .../0102-Location.toBlockLocation-toCenterLocation.patch | 0 .../0103-PotionEffect-clone-methods.patch | 0 .../0104-WitchReadyPotionEvent.patch | 0 .../0105-ItemStack-getMaxItemUseDuration.patch | 0 .../0106-Add-EntityTeleportEndGatewayEvent.patch | 0 .../0107-Make-shield-blocking-delay-configurable.patch | 0 ...108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch | 0 .../0109-Add-getNearbyXXX-methods-to-Location.patch | 0 .../0110-PlayerReadyArrowEvent.patch | 0 .../0111-Add-EntityKnockbackByEntityEvent.patch | 0 .../0112-Expand-Explosions-API.patch | 0 .../0113-ItemStack-API-additions-for-quantity-flags-lore.patch | 0 .../0114-LivingEntity-Hand-Raised-Item-Use-API.patch | 0 .../0115-RangedEntity-API.patch | 0 .../0116-Add-World.getEntity-UUID-API.patch | 0 .../0117-InventoryCloseEvent-Reason-API.patch | 0 .../0118-Entity-getChunk-API.patch | 0 .../0119-Add-an-asterisk-to-legacy-API-plugins.patch | 0 .../0120-EnderDragon-Events.patch | 0 .../0121-PlayerLaunchProjectileEvent.patch | 0 .../0122-PlayerElytraBoostEvent.patch | 0 .../0123-EntityTransformedEvent.patch | 0 .../0124-Allow-disabling-armour-stand-ticking.patch | 0 .../0125-SkeletonHorse-Additions.patch | 0 .../0126-Expand-Location-Manipulation-API.patch | 0 .../0127-Expand-ArmorStand-API.patch | 0 .../0128-AnvilDamageEvent.patch | 0 .../0129-Remove-deadlock-risk-in-firing-async-events.patch | 0 .../0130-Add-hand-to-bucket-events.patch | 0 .../0131-Add-TNTPrimeEvent.patch | 0 .../0132-Provide-Chunk-Coordinates-as-a-Long-API.patch | 0 .../0133-Async-Chunks-API.patch | 0 .../0134-Make-EnderDragon-extend-Mob.patch | 0 ...135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch | 0 ...0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch | 0 .../0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch | 0 .../0138-Slime-Pathfinder-Events.patch | 0 .../0139-isChunkGenerated-API.patch | 0 .../0140-Add-More-Creeper-API.patch | 0 .../0141-Add-PhantomPreSpawnEvent.patch | 0 .../0142-Add-source-block-to-BlockPhysicsEvent.patch | 0 .../0143-Inventory-removeItemAnySlot.patch | 0 .../0144-Add-ray-tracing-methods-to-LivingEntity.patch | 0 .../0145-Improve-death-events.patch | 0 .../0146-Mob-Pathfinding-API.patch | 0 .../0147-Expose-attack-cooldown-methods-for-Player.patch | 0 ...0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch | 0 ...0149-Performance-Concurrency-Improvements-to-Permissions.patch | 0 .../0150-Add-ItemStackRecipeChoice-Draft-API.patch | 0 .../0151-Implement-furnace-cook-speed-multiplier-API.patch | 0 .../0152-PreSpawnerSpawnEvent.patch | 0 .../0153-Material-API-additions.patch | 0 .../0154-Add-Material-Tags.patch | 0 .../0155-Allow-setting-the-vex-s-summoner.patch | 0 .../0156-Add-LivingEntity-getTargetEntity.patch | 0 .../0157-Add-sun-related-API.patch | 0 .../0158-Here-s-Johnny.patch | 0 .../0159-Turtle-API.patch | 0 .../0160-Add-spectator-target-events.patch | 0 .../0161-Add-more-Witch-API.patch | 0 .../0162-Make-the-default-permission-message-configurable.patch | 0 ...163-Support-cancellation-supression-of-EntityDismount-Ve.patch | 0 .../0164-Add-more-Zombie-API.patch | 0 .../0165-Change-the-reserved-channel-check-to-be-sensible.patch | 0 .../0166-Add-PlayerConnectionCloseEvent.patch | 0 .../0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch | 0 .../0168-BlockDestroyEvent.patch | 0 .../0169-Add-ItemStack-Recipe-API-helper-methods.patch | 0 .../0170-Add-WhitelistToggleEvent.patch | 0 .../0171-Annotation-Test-changes.patch | 0 .../0172-Entity-getEntitySpawnReason.patch | 0 .../0173-Add-GS4-Query-event.patch | 0 .../0174-Add-PlayerPostRespawnEvent.patch | 0 ...175-Ignore-package-private-methods-for-nullability-annot.patch | 0 .../0176-Flip-some-Spigot-API-null-annotations.patch | 0 .../0177-Server-Tick-Events.patch | 0 .../0178-PlayerDeathEvent-getItemsToKeep.patch | 0 .../0179-Add-Heightmap-API.patch | 0 .../0180-Mob-Spawner-API-Enhancements.patch | 0 .../0181-Add-BlockSoundGroup-interface.patch | 0 ...182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch | 0 .../0183-Increase-custom-payload-channel-message-size.patch | 0 .../0184-Expose-the-internal-current-tick.patch | 0 .../0185-PlayerDeathEvent-shouldDropExperience.patch | 0 .../0186-Add-effect-to-block-break-naturally.patch | 0 .../0187-Add-ThrownEggHatchEvent.patch | 0 .../0188-Entity-Jump-API.patch | 0 .../0189-add-hand-to-BlockMultiPlaceEvent.patch | 0 .../0190-Add-tick-times-API.patch | 0 .../0191-Expose-MinecraftServer-isRunning.patch | 0 ...192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch | 0 .../0193-Make-JavaPluginLoader-thread-safe.patch | 0 .../0194-Add-Player-Client-Options-API.patch | 0 .../0195-Add-PlayerAttackEntityCooldownResetEvent.patch | 0 ...196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch | 0 .../0197-Villager-Restocks-API.patch | 0 .../0198-Expose-game-version.patch | 0 .../0199-Add-item-slot-convenience-methods.patch | 0 .../0200-Add-Mob-Goal-API.patch | 0 .../0201-World-view-distance-api.patch | 0 .../0202-Add-villager-reputation-API.patch | 0 .../0203-Spawn-Reason-API.patch | 0 .../0204-Potential-bed-API.patch | 0 .../0205-Prioritise-own-classes-where-possible.patch | 0 .../0206-Add-Raw-Byte-ItemStack-Serialization.patch | 0 .../0207-Provide-a-useful-PluginClassLoader-toString.patch | 0 .../0208-Inventory-getHolder-method-without-block-snapshot.patch | 0 .../0209-Expose-Arrow-getItemStack.patch | 0 .../0210-Add-and-implement-PlayerRecipeBookClickEvent.patch | 0 .../0211-Support-components-in-ItemMeta.patch | 0 .../0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch | 0 .../0213-Add-entity-liquid-API.patch | 0 .../0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch | 0 .../0215-Allow-delegation-to-vanilla-chunk-gen.patch | 0 .../0216-Support-hex-colors-in-getLastColors.patch | 0 .../0217-Add-setMaxPlayers-API.patch | 0 .../0218-Add-moon-phase-API.patch | 0 .../0219-Add-playPickupItemAnimation-to-LivingEntity.patch | 0 .../0220-Add-BellRingEvent.patch | 0 .../0221-Brand-support.patch | 0 .../0222-Add-more-Evoker-API.patch | 0 ...223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch | 0 .../0224-Create-HoverEvent-from-ItemStack-Entity.patch | 0 .../0225-Add-additional-open-container-api-to-HumanEntity.patch | 0 ...226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch | 0 .../0227-Entity-isTicking.patch | 0 ...228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch | 0 .../0229-Villager-resetOffers.patch | 0 .../0230-Player-elytra-boost-API.patch | 0 .../0231-Add-getOfflinePlayerIfCached-String.patch | 0 .../0232-Add-ignore-discounts-API.patch | 0 .../0233-Item-no-age-no-player-pickup.patch | 0 .../0234-Beacon-API-custom-effect-ranges.patch | 0 .../0235-Add-API-for-quit-reason.patch | 0 .../0236-Add-Destroy-Speed-API.patch | 0 .../0237-Add-LivingEntity-clearActiveItem.patch | 0 .../0238-Add-PlayerItemCooldownEvent.patch | 0 .../0239-More-lightning-API.patch | 0 .../0240-Add-PlayerShearBlockEvent.patch | 0 .../0241-Enable-multi-release-plugin-jars.patch | 0 .../0242-Player-Chunk-Load-Unload-Events.patch | 0 .../0243-Expose-LivingEntity-hurt-direction.patch | 0 .../0244-Added-PlayerTradeEvent.patch | 0 .../0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch | 0 .../0246-Add-TargetHitEvent-API.patch | 0 .../0247-Additional-Block-Material-API-s.patch | 0 .../0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch | 0 .../0249-Add-PlayerFlowerPotManipulateEvent.patch | 0 .../0250-Zombie-API-breaking-doors.patch | 0 .../0251-Add-EntityLoadCrossbowEvent.patch | 0 .../0252-Added-WorldGameRuleChangeEvent.patch | 0 .../0253-Added-ServerResourcesReloadedEvent.patch | 0 .../0254-Add-BlockFailedDispenseEvent.patch | 0 .../0255-Added-PlayerLecternPageChangeEvent.patch | 0 .../0256-Added-PlayerLoomPatternSelectEvent.patch | 0 .../0257-Better-AnnotationTest-printout.patch | 0 ...258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch | 0 .../0259-Add-sendOpLevel-API.patch | 0 .../0260-Add-StructureLocateEvent.patch | 0 ...261-Return-chat-component-with-empty-text-instead-of-thr.patch | 0 .../0262-Add-BlockPreDispenseEvent.patch | 0 .../0263-Added-Vanilla-Entity-Tags.patch | 0 .../0264-added-Wither-API.patch | 0 .../0265-Added-PlayerChangeBeaconEffectEvent.patch | 0 .../0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch | 0 .../0267-Added-PlayerStonecutterRecipeSelectEvent.patch | 0 .../0268-EntityMoveEvent.patch | 0 .../0269-add-DragonEggFormEvent.patch | 0 .../0270-Allow-adding-items-to-BlockDropItemEvent.patch | 0 .../0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch | 0 .../0272-living-entity-allow-attribute-registration.patch | 0 .../0273-Add-missing-effects.patch | 0 .../0274-Expose-Tracked-Players.patch | 0 .../0275-Cache-the-result-of-Material-isBlock.patch | 0 .../0276-Add-worldborder-events.patch | 0 .../0277-added-PlayerNameEntityEvent.patch | 0 .../0278-Add-recipe-to-cook-events.patch | 0 .../0279-Add-Block-isValidTool.patch | 0 .../0280-Implement-Keyed-on-World.patch | 0 .../0281-fix-Inventory-getContents-null-annotations.patch | 0 .../0282-Item-Rarity-API.patch | 0 .../0283-Expose-protocol-version.patch | 0 .../0284-add-isDeeplySleeping-to-HumanEntity.patch | 0 .../0285-add-consumeFuel-to-FurnaceBurnEvent.patch | 0 .../0286-add-get-set-drop-chance-to-EntityEquipment.patch | 0 .../0287-Added-PlayerDeepSleepEvent.patch | 0 .../0288-More-World-API.patch | 0 .../0289-Added-PlayerBedFailEnterEvent.patch | 0 .../0290-Introduce-beacon-activation-deactivation-events.patch | 0 .../0291-PlayerMoveEvent-Improvements.patch | 0 .../0292-add-RespawnFlags-to-PlayerRespawnEvent.patch | 0 .../0293-Add-more-WanderingTrader-API.patch | 0 ...294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch | 0 .../0295-Add-EntityBlockStorage-clearEntities.patch | 0 ...0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch | 0 .../0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch | 0 .../0298-Inventory-close.patch | 0 ...299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch | 0 .../0300-Add-basic-Datapack-API.patch | 0 .../0301-additions-to-PlayerGameModeChangeEvent.patch | 0 .../0302-ItemStack-repair-check-API.patch | 0 .../0303-More-Enchantment-API.patch | 0 ...304-Add-command-line-option-to-load-extra-plugin-jars-no.patch | 0 .../0305-List-all-missing-hard-depends-not-just-first.patch | 0 .../0306-Add-Mob-lookAt-API.patch | 0 .../0307-ItemStack-editMeta.patch | 0 .../0308-Add-EntityInsideBlockEvent.patch | 0 .../0309-Attributes-API-for-item-defaults.patch | 0 .../0310-Add-cause-to-Weather-ThunderChangeEvents.patch | 0 .../0311-More-Lidded-Block-API.patch | 0 .../0312-Add-PlayerKickEvent-causes.patch | 0 .../0313-Add-PufferFishStateChangeEvent.patch | 0 .../0314-Add-BellRevealRaiderEvent.patch | 0 .../0315-Add-ElderGuardianAppearanceEvent.patch | 0 .../0316-Add-more-line-of-sight-methods.patch | 0 .../0001-POM-Changes.patch | 0 .../0002-Paper-config-files.patch | 0 .../0003-MC-Dev-fixes.patch | 0 .../0004-MC-Utils.patch | 0 .../0005-Paper-Metrics.patch | 0 .../0006-Add-MinecraftKey-Information-to-Objects.patch | 0 ...007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch | 0 .../0008-Store-counts-for-each-Entity-Block-Entity-Type.patch | 0 .../0009-Timings-v2.patch | 0 .../0010-Adventure.patch | 0 .../0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch | 0 .../0012-Configurable-baby-zombie-movement-speed.patch | 0 .../0013-Configurable-fishing-time-ranges.patch | 0 .../0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch | 0 ...015-Add-configurable-despawn-distances-for-living-entiti.patch | 0 .../0016-Allow-for-toggling-of-spawn-chunks.patch | 0 ...017-Drop-falling-block-and-tnt-entities-at-the-specified.patch | 0 ...018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch | 0 .../0019-Implement-Paper-VersionChecker.patch | 0 .../0020-Add-version-history-to-version-command.patch | 0 .../0021-Player-affects-spawning-API.patch | 0 .../0022-Remove-invalid-mob-spawner-tile-entities.patch | 0 .../0023-Optimize-TileEntity-Ticking.patch | 0 .../0024-Further-improve-server-tick-loop.patch | 0 .../0025-Only-refresh-abilities-if-needed.patch | 0 .../0026-Entity-Origin-API.patch | 0 .../0027-Prevent-tile-entity-and-entity-crashes.patch | 0 .../0028-Configurable-top-of-nether-void-damage.patch | 0 ...029-Check-online-mode-before-converting-and-renaming-pla.patch | 0 .../0030-Always-tick-falling-blocks.patch | 0 .../0031-Configurable-end-credits.patch | 0 .../0032-Fix-lag-from-explosions-processing-dead-entities.patch | 0 .../0033-Optimize-explosions.patch | 0 .../0034-Disable-explosion-knockback.patch | 0 .../0035-Disable-thunder.patch | 0 .../0036-Disable-ice-and-snow.patch | 0 .../0037-Configurable-mob-spawner-tick-rate.patch | 0 ...038-Send-absolute-position-the-first-time-an-entity-is-s.patch | 0 .../0039-Add-BeaconEffectEvent.patch | 0 .../0040-Configurable-container-update-tick-rate.patch | 0 .../0041-Use-UserCache-for-player-heads.patch | 0 .../0042-Disable-spigot-tick-limiters.patch | 0 .../0043-Add-PlayerInitialSpawnEvent.patch | 0 .../0044-Configurable-Disabling-Cat-Chest-Detection.patch | 0 .../0045-Ensure-commands-are-not-ran-async.patch | 0 .../0046-All-chunks-are-slime-spawn-chunks-toggle.patch | 0 .../0047-Expose-server-CommandMap.patch | 0 .../0048-Be-a-bit-more-informative-in-maxHealth-exception.patch | 0 .../0049-Player-Tab-List-and-Title-APIs.patch | 0 .../0050-Ensure-inv-drag-is-in-bounds.patch | 0 .../0051-Change-implementation-of-tile-entity-removal-list.patch | 0 .../0052-Add-configurable-portal-search-radius.patch | 0 .../0053-Add-velocity-warnings.patch | 0 .../0054-Configurable-inter-world-teleportation-safety.patch | 0 .../0055-Add-exception-reporting-event.patch | 0 ...056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch | 0 .../0057-Disable-Scoreboards-for-non-players-by-default.patch | 0 ...058-Add-methods-for-working-with-arrows-stuck-in-living-.patch | 0 .../0059-Complete-resource-pack-API.patch | 0 .../0060-Chunk-Save-Reattempt.patch | 0 .../0061-Default-loading-permissions.yml-before-plugins.patch | 0 .../0062-Allow-Reloading-of-Custom-Permissions.patch | 0 .../0063-Remove-Metadata-on-reload.patch | 0 .../0064-Handle-Item-Meta-Inconsistencies.patch | 0 .../0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch | 0 .../0066-Add-World-Util-Methods.patch | 0 .../0067-Custom-replacement-for-eaten-items.patch | 0 ...0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch | 0 .../0069-Use-a-Shared-Random-for-Entities.patch | 0 .../0070-Configurable-spawn-chances-for-skeleton-horses.patch | 0 ...071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch | 0 ...072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch | 0 .../0073-Entity-AddTo-RemoveFrom-World-Events.patch | 0 .../0074-Configurable-Chunk-Inhabited-Time.patch | 0 .../0075-EntityPathfindEvent.patch | 0 .../0076-Sanitise-RegionFileCache-and-make-configurable.patch | 0 .../0077-Do-not-load-chunks-for-Pathfinding.patch | 0 .../0078-Add-PlayerUseUnknownEntityEvent.patch | 0 .../0079-Fix-reducedDebugInfo-not-initialized-on-client.patch | 0 .../0080-Configurable-Grass-Spread-Tick-Rate.patch | 0 .../0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch | 0 .../0082-Optimize-DataBits.patch | 0 ...083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch | 0 .../0084-Workaround-for-setting-passengers-on-players.patch | 0 .../0085-Remove-unused-World-Tile-Entity-List.patch | 0 .../0086-Don-t-tick-Skulls-unused-code.patch | 0 .../0087-Configurable-Player-Collision.patch | 0 ...088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch | 0 .../0089-Configurable-RCON-IP-address.patch | 0 .../0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch | 0 .../0091-Implement-PlayerLocaleChangeEvent.patch | 0 .../0092-EntityRegainHealthEvent-isFastRegen-API.patch | 0 .../0093-Add-ability-to-configure-frosted_ice-properties.patch | 0 .../0094-remove-null-possibility-for-getServer-singleton.patch | 0 ...095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch | 0 .../0096-LootTable-API-Replenishable-Lootables-Feature.patch | 0 ...0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch | 0 .../0098-System-property-for-disabling-watchdoge.patch | 0 .../0099-Optimize-UserCache-Thread-Safe.patch | 0 .../0100-Avoid-blocking-on-Network-Manager-creation.patch | 0 .../0101-Optional-TNT-doesn-t-move-in-water.patch | 0 .../0102-Faster-redstone-torch-rapid-clock-removal.patch | 0 .../0103-Add-server-name-parameter.patch | 0 .../0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch | 0 .../0105-Fix-Double-World-Add-issues.patch | 0 .../0106-Fix-Old-Sign-Conversion.patch | 0 ...107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch | 0 .../0108-Add-setting-for-proxy-online-mode-status.patch | 0 .../0109-Optimise-BlockState-s-hashCode-equals.patch | 0 .../0110-Configurable-packet-in-spam-threshold.patch | 0 .../0111-Configurable-flying-kick-messages.patch | 0 .../0112-Chunk-registration-fixes.patch | 0 ...113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch | 0 .../0114-Auto-fix-bad-Y-levels-on-player-login.patch | 0 .../0115-Option-to-remove-corrupt-tile-entities.patch | 0 .../0116-Add-EntityZapEvent.patch | 0 .../0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch | 0 .../0118-Cache-user-authenticator-threads.patch | 0 .../0119-Optimise-removeQueue.patch | 0 .../0120-Allow-Reloading-of-Command-Aliases.patch | 0 .../0121-Add-source-to-PlayerExpChangeEvent.patch | 0 .../0122-Don-t-let-fishinghooks-use-portals.patch | 0 .../0123-Add-ProjectileCollideEvent.patch | 0 .../0124-Prevent-Pathfinding-out-of-World-Border.patch | 0 .../0125-Optimize-World.isLoaded-BlockPosition-Z.patch | 0 .../0126-Bound-Treasure-Maps-to-World-Border.patch | 0 .../0127-Configurable-Cartographer-Treasure-Maps.patch | 0 .../0128-Optimize-ItemStack.isEmpty.patch | 0 ...129-Add-API-methods-to-control-if-armour-stands-can-move.patch | 0 .../0130-Properly-fix-item-duplication-bug.patch | 0 .../0131-String-based-Action-Bar-API.patch | 0 .../0132-Firework-API-s.patch | 0 .../0133-PlayerTeleportEndGatewayEvent.patch | 0 .../0134-Provide-E-TE-Chunk-count-stat-methods.patch | 0 .../0135-Enforce-Sync-Player-Saves.patch | 0 .../0136-Don-t-allow-entities-to-ride-themselves-572.patch | 0 ...137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch | 0 .../0138-Cap-Entity-Collisions.patch | 0 .../0139-Remove-CraftScheduler-Async-Task-Debugger.patch | 0 ...140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch | 0 .../0141-Do-not-let-armorstands-drown.patch | 0 .../0142-Properly-handle-async-calls-to-restart-the-server.patch | 0 .../0143-Add-system-property-to-disable-book-size-limits.patch | 0 ...144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch | 0 ...145-Add-configuration-option-to-prevent-player-names-fro.patch | 0 ...146-Use-TerminalConsoleAppender-for-console-improvements.patch | 0 ...147-provide-a-configurable-option-to-disable-creeper-lin.patch | 0 .../0148-Item-canEntityPickup.patch | 0 .../0149-PlayerPickupItemEvent-setFlyAtPlayer.patch | 0 .../0150-PlayerAttemptPickupItemEvent.patch | 0 .../0151-Add-UnknownCommandEvent.patch | 0 .../0152-Basic-PlayerProfile-API.patch | 0 .../0153-Shoulder-Entities-Release-API.patch | 0 .../0154-Profile-Lookup-Events.patch | 0 .../0155-Block-player-logins-during-server-shutdown.patch | 0 .../0156-Entity-fromMobSpawner.patch | 0 .../0157-Improve-the-Saddle-API-for-Horses.patch | 0 .../0158-Implement-ensureServerConversions-API.patch | 0 .../0159-Implement-getI18NDisplayName.patch | 0 .../0160-ProfileWhitelistVerifyEvent.patch | 0 .../0161-Fix-this-stupid-bullshit.patch | 0 .../0162-Ocelot-despawns-should-honor-nametags-and-leash.patch | 0 ...0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch | 0 .../0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch | 0 ...165-Allow-specifying-a-custom-authentication-servers-dow.patch | 0 .../0166-LivingEntity-setKiller.patch | 0 .../0167-Handle-plugin-prefixes-using-Log4J-configuration.patch | 0 .../0168-Improve-Log4J-Configuration-Plugin-Loggers.patch | 0 .../0169-Add-PlayerJumpEvent.patch | 0 .../0170-handle-PacketPlayInKeepAlive-async.patch | 0 .../0171-Expose-client-protocol-version-and-virtual-host.patch | 0 .../0172-revert-serverside-behavior-of-keepalives.patch | 0 ...173-Send-attack-SoundEffects-only-to-players-who-can-see.patch | 0 .../0174-Option-for-maximum-exp-value-when-merging-orbs.patch | 0 .../0175-Add-PlayerArmorChangeEvent.patch | 0 ...176-Prevent-logins-from-being-processed-when-the-player-.patch | 0 ...177-use-CB-BlockState-implementations-for-captured-block.patch | 0 .../0178-API-to-get-a-BlockState-without-a-snapshot.patch | 0 .../0179-AsyncTabCompleteEvent.patch | 0 .../0180-Avoid-NPE-in-PathfinderGoalTempt.patch | 0 .../0181-PlayerPickupExperienceEvent.patch | 0 .../0182-ExperienceOrbMergeEvent.patch | 0 .../0183-Ability-to-apply-mending-to-XP-API.patch | 0 .../0184-Make-max-squid-spawn-height-configurable.patch | 0 .../0185-PreCreatureSpawnEvent.patch | 0 .../0186-PlayerNaturallySpawnCreaturesEvent.patch | 0 .../0187-Add-setPlayerProfile-API-for-Skulls.patch | 0 .../0188-Fill-Profile-Property-Events.patch | 0 .../0189-PlayerAdvancementCriterionGrantEvent.patch | 0 .../0190-Add-ArmorStand-Item-Meta.patch | 0 .../0191-Extend-Player-Interact-cancellation.patch | 0 .../0192-Tameable-getOwnerUniqueId-API.patch | 0 ...193-Toggleable-player-crits-helps-mitigate-hacked-client.patch | 0 .../0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch | 0 .../0195-Disable-Explicit-Network-Manager-Flushing.patch | 0 .../0196-Implement-extended-PaperServerListPingEvent.patch | 0 .../0197-Improved-Async-Task-Scheduler.patch | 0 ...198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch | 0 .../0199-Player.setPlayerProfile-API.patch | 0 .../0200-Fix-Dragon-Server-Crashes.patch | 0 .../0201-getPlayerUniqueId-API.patch | 0 .../0202-Make-player-data-saving-configurable.patch | 0 .../0203-Make-legacy-ping-handler-more-reliable.patch | 0 .../0204-Call-PaperServerListPingEvent-for-legacy-pings.patch | 0 .../0205-Flag-to-disable-the-channel-limit.patch | 0 .../0206-Add-method-to-open-already-placed-sign.patch | 0 .../0207-Configurable-sprint-interruption-on-attack.patch | 0 ...208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch | 0 .../0209-EndermanEscapeEvent.patch | 0 .../0210-Enderman.teleportRandomly.patch | 0 .../0211-Block-Enderpearl-Travel-Exploit.patch | 0 .../0212-Expand-World.spawnParticle-API-and-add-Builder.patch | 0 .../0213-EndermanAttackPlayerEvent.patch | 0 .../0214-WitchConsumePotionEvent.patch | 0 .../0215-WitchThrowPotionEvent.patch | 0 ...0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch | 0 .../0217-WitchReadyPotionEvent.patch | 0 .../0218-ItemStack-getMaxItemUseDuration.patch | 0 .../0219-Implement-EntityTeleportEndGatewayEvent.patch | 0 .../0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch | 0 .../0221-Fix-CraftEntity-hashCode.patch | 0 .../0222-Configurable-Alternative-LootPool-Luck-Formula.patch | 0 ...223-Print-Error-details-when-failing-to-save-player-data.patch | 0 .../0224-Make-shield-blocking-delay-configurable.patch | 0 .../0225-Improve-EntityShootBowEvent.patch | 0 .../0226-PlayerReadyArrowEvent.patch | 0 .../0227-Implement-EntityKnockbackByEntityEvent.patch | 0 .../0228-Expand-Explosions-API.patch | 0 .../0229-LivingEntity-Hand-Raised-Item-Use-API.patch | 0 .../0230-RangedEntity-API.patch | 0 .../0231-Add-config-to-disable-ender-dragon-legacy-check.patch | 0 .../0232-Implement-World.getEntity-UUID-API.patch | 0 .../0233-InventoryCloseEvent-Reason-API.patch | 0 .../0234-Vex-getSummoner-API.patch | 0 ...235-Refresh-player-inventory-when-cancelling-PlayerInter.patch | 0 .../0236-Don-t-change-the-Entity-Random-seed-for-squids.patch | 0 .../0237-Re-add-vanilla-entity-warnings-for-duplicates.patch | 0 ...0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch | 0 .../0239-Use-asynchronous-Log4j-2-loggers.patch | 0 .../0240-add-more-information-to-Entity.toString.patch | 0 ...0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch | 0 .../0242-EnderDragon-Events.patch | 0 .../0243-PlayerElytraBoostEvent.patch | 0 .../0244-Improve-BlockPosition-inlining.patch | 0 .../0245-Optimize-RegistryID.c.patch | 0 ...246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch | 0 .../0247-Vanished-players-don-t-have-rights.patch | 0 ...248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch | 0 .../0249-Add-some-Debug-to-Chunk-Entity-slices.patch | 0 .../0250-SkeletonHorse-Additions.patch | 0 .../0251-Prevent-Saving-Bad-entities-to-chunks.patch | 0 .../0252-Don-t-call-getItemMeta-on-hasItemMeta.patch | 0 .../0253-Ignore-Dead-Entities-in-entityList-iteration.patch | 0 .../0254-Implement-Expanded-ArmorStand-API.patch | 0 .../0255-AnvilDamageEvent.patch | 0 .../0256-Add-TNTPrimeEvent.patch | 0 .../0257-Break-up-and-make-tab-spam-limits-configurable.patch | 0 .../0258-Add-hand-to-bucket-events.patch | 0 .../0259-MC-135506-Experience-should-save-as-Integers.patch | 0 .../0260-Fix-client-rendering-skulls-from-same-user.patch | 0 .../0261-Add-Early-Warning-Feature-to-WatchDog.patch | 0 .../0262-Make-EnderDragon-implement-Mob.patch | 0 .../0263-Use-ConcurrentHashMap-in-JsonList.patch | 0 .../0264-Use-a-Queue-for-Queueing-Commands.patch | 0 ...265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch | 0 .../0266-Allow-disabling-armour-stand-ticking.patch | 0 .../0267-Optimize-BlockPosition-helper-methods.patch | 0 ...268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch | 0 .../0269-Slime-Pathfinder-Events.patch | 0 .../0270-Configurable-speed-for-water-flowing-over-lava.patch | 0 .../0271-Optimize-CraftBlockData-Creation.patch | 0 .../0272-Optimize-RegistryMaterials.patch | 0 .../0273-Add-PhantomPreSpawnEvent.patch | 0 .../0274-Add-More-Creeper-API.patch | 0 .../0275-Inventory-removeItemAnySlot.patch | 0 ...276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch | 0 .../0277-Add-ray-tracing-methods-to-LivingEntity.patch | 0 .../0278-Expose-attack-cooldown-methods-for-Player.patch | 0 .../0279-Improve-death-events.patch | 0 .../0280-Allow-chests-to-be-placed-with-NBT-data.patch | 0 .../0281-Mob-Pathfinding-API.patch | 0 .../0282-Prevent-chunk-loading-from-Fluid-Flowing.patch | 0 ...283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch | 0 .../0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch | 0 ...0285-Prevent-mob-spawning-from-loading-generating-chunks.patch | 0 .../0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch | 0 .../0287-Implement-furnace-cook-speed-multiplier-API.patch | 0 .../0288-PreSpawnerSpawnEvent.patch | 0 .../0289-Catch-JsonParseException-in-Entity-and-TE-names.patch | 0 .../0290-Honor-EntityAgeable.ageLock.patch | 0 .../0291-Configurable-connection-throttle-kick-message.patch | 0 .../0292-Hook-into-CB-plugin-rewrites.patch | 0 .../0293-Allow-setting-the-vex-s-summoner.patch | 0 .../0294-Add-sun-related-API.patch | 0 .../0295-Turtle-API.patch | 0 ...296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch | 0 ...297-Call-player-spectator-target-events-and-improve-impl.patch | 0 .../0298-Add-Velocity-IP-Forwarding-Support.patch | 0 .../0299-Add-more-Witch-API.patch | 0 .../0300-Check-Drowned-for-Villager-Aggression-Config.patch | 0 .../0301-Here-s-Johnny.patch | 0 ...302-Add-option-to-prevent-players-from-moving-into-unloa.patch | 0 .../0303-Reset-players-airTicks-on-respawn.patch | 0 .../0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch | 0 .../0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch | 0 .../0306-Optimize-World-Time-Updates.patch | 0 .../0307-Restore-custom-InventoryHolder-support.patch | 0 .../0308-Use-Vanilla-Minecart-Speeds.patch | 0 .../0309-Fix-SpongeAbsortEvent-handling.patch | 0 .../0310-Don-t-allow-digging-into-unloaded-chunks.patch | 0 .../0311-Book-Size-Limits.patch | 0 .../0312-Make-the-default-permission-message-configurable.patch | 0 .../0313-Prevent-rayTrace-from-loading-chunks.patch | 0 .../0314-Handle-Large-Packets-disconnecting-client.patch | 0 .../0315-force-entity-dismount-during-teleportation.patch | 0 .../0316-Add-more-Zombie-API.patch | 0 .../0317-Add-PlayerConnectionCloseEvent.patch | 0 .../0318-Prevent-Enderman-from-loading-chunks.patch | 0 .../0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch | 0 ...0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch | 0 .../0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch | 0 .../0322-Block-Entity-remove-from-being-called-on-Players.patch | 0 .../0323-BlockDestroyEvent.patch | 0 .../0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch | 0 .../0325-Fix-sign-edit-memory-leak.patch | 0 .../0326-Limit-Client-Sign-length-more.patch | 0 .../0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch | 0 ...328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch | 0 .../0329-Handle-Oversized-Tile-Entities-in-chunks.patch | 0 .../0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch | 0 .../0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch | 0 .../0332-Allow-Saving-of-Oversized-Chunks.patch | 0 ...0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch | 0 .../0334-Add-LivingEntity-getTargetEntity.patch | 0 ...335-Use-proper-max-length-when-serialising-BungeeCord-te.patch | 0 .../0336-Entity-getEntitySpawnReason.patch | 0 .../0337-Update-entity-Metadata-for-all-tracked-players.patch | 0 .../0338-Implement-PlayerPostRespawnEvent.patch | 0 ...339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch | 0 .../0340-Server-Tick-Events.patch | 0 .../0341-PlayerDeathEvent-getItemsToKeep.patch | 0 .../0342-Optimize-Captured-TileEntity-Lookup.patch | 0 .../0343-Add-Heightmap-API.patch | 0 .../0344-Mob-Spawner-API-Enhancements.patch | 0 .../0345-Per-Player-View-Distance-API-placeholders.patch | 0 .../0346-Fix-CB-call-to-changed-postToMainThread-method.patch | 0 .../0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch | 0 ...348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch | 0 .../0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch | 0 .../0350-Duplicate-UUID-Resolve-Option.patch | 0 .../0351-improve-CraftWorld-isChunkLoaded.patch | 0 .../0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch | 0 ...353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch | 0 .../0354-ChunkMapDistance-CME.patch | 0 .../0355-Implement-CraftBlockSoundGroup.patch | 0 .../0356-Chunk-debug-command.patch | 0 .../0357-Catch-exceptions-from-dispenser-entity-spawns.patch | 0 .../0358-Fix-World-isChunkGenerated-calls.patch | 0 .../0359-Show-blockstate-location-if-we-failed-to-read-it.patch | 0 ...360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch | 0 .../0361-incremental-chunk-saving.patch | 0 .../0362-Anti-Xray.patch | 0 ...363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch | 0 .../0364-Configurable-projectile-relative-velocity.patch | 0 ...365-Mark-entities-as-being-ticked-when-notifying-navigat.patch | 0 .../0366-offset-item-frame-ticking.patch | 0 .../0367-Avoid-hopper-searches-if-there-are-no-items.patch | 0 .../0368-Asynchronous-chunk-IO-and-loading.patch | 0 .../0369-Use-getChunkIfLoadedImmediately-in-places.patch | 0 .../0370-Reduce-sync-loads.patch | 0 .../0371-Implement-alternative-item-despawn-rate.patch | 0 .../0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch | 0 .../0373-Fix-MC-158900.patch | 0 .../0374-implement-optional-per-player-mob-spawns.patch | 0 .../0375-Prevent-consuming-the-wrong-itemstack.patch | 0 .../0376-Generator-Settings.patch | 0 .../0377-Fix-MC-161754.patch | 0 .../0378-Performance-improvement-for-Chunk.getEntities.patch | 0 ...379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch | 0 .../0380-Expose-the-internal-current-tick.patch | 0 .../0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch | 0 .../0382-Add-option-to-disable-pillager-patrols.patch | 0 ...383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch | 0 .../0384-PlayerLaunchProjectileEvent.patch | 0 .../0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch | 0 ...386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch | 0 .../0387-MC-145656-Fix-Follow-Range-Initial-Target.patch | 0 .../0388-Optimize-Hoppers.patch | 0 .../0389-PlayerDeathEvent-shouldDropExperience.patch | 0 .../0390-Prevent-bees-loading-chunks-checking-hive-position.patch | 0 .../0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch | 0 ...392-Guard-against-serializing-mismatching-chunk-coordina.patch | 0 .../0393-Optimise-IEntityAccess-getPlayerByUUID.patch | 0 .../0394-Fix-items-not-falling-correctly.patch | 0 .../0395-Lag-compensate-eating.patch | 0 .../0396-Optimize-call-to-getFluid-for-explosions.patch | 0 ...397-Fix-last-firework-in-stack-not-having-effects-when-d.patch | 0 .../0398-Add-effect-to-block-break-naturally.patch | 0 .../0399-Tracking-Range-Improvements.patch | 0 .../0400-Entity-Activation-Range-2.0.patch | 0 .../0401-Fix-items-vanishing-through-end-portal.patch | 0 .../0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch | 0 .../0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch | 0 .../0404-Allow-overriding-the-java-version-check.patch | 0 .../0405-Add-ThrownEggHatchEvent.patch | 0 .../0406-Optimise-random-block-ticking.patch | 0 .../0407-Entity-Jump-API.patch | 0 .../0408-Add-option-to-nerf-pigmen-from-nether-portals.patch | 0 .../0409-Make-the-GUI-graph-fancier.patch | 0 .../0410-add-hand-to-BlockMultiPlaceEvent.patch | 0 .../0411-Prevent-teleporting-dead-entities.patch | 0 .../0412-Validate-tripwire-hook-placement-before-update.patch | 0 .../0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch | 0 .../0414-Configurable-chance-of-villager-zombie-infection.patch | 0 .../0415-Optimise-Chunk-getFluid.patch | 0 .../0416-Optimise-TickListServer-by-rewriting-it.patch | 0 ...417-Pillager-patrol-spawn-settings-and-per-player-option.patch | 0 .../0418-Ensure-Entity-is-never-double-registered.patch | 0 .../0419-Fix-unregistering-entities-from-unloading-chunks.patch | 0 .../0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch | 0 .../0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch | 0 .../0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch | 0 .../0423-Optimize-Collision-to-not-load-chunks.patch | 0 .../0424-Don-t-tick-dead-players.patch | 0 .../0425-Dead-Player-s-shouldn-t-be-able-to-move.patch | 0 ...426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch | 0 .../0427-Increase-Light-Queue-Size.patch | 0 ...428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch | 0 .../0429-Don-t-move-existing-players-to-world-spawn.patch | 0 .../0430-Add-tick-times-API-and-mspt-command.patch | 0 .../0431-Expose-MinecraftServer-isRunning.patch | 0 .../0432-Add-Raw-Byte-ItemStack-Serialization.patch | 0 .../0433-Remove-streams-from-Mob-AI-System.patch | 0 ...434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch | 0 .../0435-Async-command-map-building.patch | 0 .../0436-Improved-Watchdog-Support.patch | 0 .../0437-Optimize-Pathfinding.patch | 0 .../0438-Reduce-Either-Optional-allocation.patch | 0 .../0439-Remove-streams-from-PairedQueue.patch | 0 .../0440-Reduce-memory-footprint-of-NBTTagCompound.patch | 0 .../0441-Prevent-opening-inventories-when-frozen.patch | 0 .../0442-Optimise-ArraySetSorted-removeIf.patch | 0 .../0443-Don-t-run-entity-collision-code-if-not-needed.patch | 0 ...444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch | 0 ...445-Restrict-vanilla-teleport-command-to-valid-locations.patch | 0 .../0446-Implement-Player-Client-Options-API.patch | 0 .../0447-Fix-Chunk-Post-Processing-deadlock-risk.patch | 0 ...448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch | 0 .../0449-Broadcast-join-message-to-console.patch | 0 ...0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch | 0 .../0451-Load-Chunks-for-Login-Asynchronously.patch | 0 ...452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch | 0 .../0453-Add-PlayerAttackEntityCooldownResetEvent.patch | 0 ...454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch | 0 .../0455-Don-t-fire-BlockFade-on-worldgen-threads.patch | 0 .../0456-Add-phantom-creative-and-insomniac-controls.patch | 0 ...457-Fix-numerous-item-duplication-issues-and-teleport-is.patch | 0 .../0458-Implement-Brigadier-Mojang-API.patch | 0 .../0459-Villager-Restocks-API.patch | 0 .../0460-Validate-PickItem-Packet-and-kick-for-invalid.patch | 0 .../0461-Expose-game-version.patch | 0 .../0462-Optimize-Voxel-Shape-Merging.patch | 0 .../0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch | 0 .../0464-Implement-Mob-Goal-API.patch | 0 .../0465-Use-distance-map-to-optimise-entity-tracker.patch | 0 .../0466-Optimize-isOutsideRange-to-use-distance-maps.patch | 0 ...467-Stop-copy-on-write-operations-for-updating-light-dat.patch | 0 .../0468-No-Tick-view-distance-implementation.patch | 0 .../0469-Add-villager-reputation-API.patch | 0 .../0470-Fix-Light-Command.patch | 0 .../0471-Fix-PotionEffect-ignores-icon-flag.patch | 0 .../0472-Optimize-brigadier-child-sorting-performance.patch | 0 .../0473-Potential-bed-API.patch | 0 .../0474-Wait-for-Async-Tasks-during-shutdown.patch | 0 ...475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch | 0 ...476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch | 0 .../0477-Optimize-NibbleArray-to-use-pooled-buffers.patch | 0 .../0478-Reduce-MutableInt-allocations-from-light-engine.patch | 0 .../0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch | 0 .../0480-Ensure-safe-gateway-teleport.patch | 0 .../0481-Add-option-for-console-having-all-permissions.patch | 0 .../0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch | 0 .../0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch | 0 .../0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch | 0 ...485-Optimize-sending-packets-to-nearby-locations-sounds-.patch | 0 .../0486-Improve-Chunk-Status-Transition-Speed.patch | 0 .../0487-Fix-villager-trading-demand-MC-163962.patch | 0 .../0488-Maps-shouldn-t-load-chunks.patch | 0 ...489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch | 0 .../0490-Optimize-Bit-Operations-by-inlining.patch | 0 .../0491-Optimize-Light-Engine.patch | 0 .../0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch | 0 .../0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch | 0 .../0494-Fix-missing-chunks-due-to-integer-overflow.patch | 0 ...495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch | 0 .../0496-Fix-piston-physics-inconsistency-MC-188840.patch | 0 .../0497-Fix-sand-duping.patch | 0 ...498-Prevent-position-desync-in-playerconnection-causing-.patch | 0 .../0499-Fix-enderdragon-exp-dupe.patch | 0 .../0500-Inventory-getHolder-method-without-block-snapshot.patch | 0 .../0501-Expose-Arrow-getItemStack.patch | 0 .../0502-Add-and-implement-PlayerRecipeBookClickEvent.patch | 0 .../0503-Hide-sync-chunk-writes-behind-flag.patch | 0 .../0504-Limit-lightning-strike-effect-distance.patch | 0 .../0505-Add-permission-for-command-blocks.patch | 0 .../0506-Ensure-Entity-AABB-s-are-never-invalid.patch | 0 .../0507-Optimize-WorldBorder-collision-checks-and-air.patch | 0 .../0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch | 0 .../0509-Paper-dumpitem-command.patch | 0 .../0510-Don-t-allow-null-UUID-s-for-chat.patch | 0 .../0511-Improve-Legacy-Component-serialization-size.patch | 0 .../0512-Support-old-UUID-format-for-NBT.patch | 0 .../0513-Clean-up-duplicated-GameProfile-Properties.patch | 0 .../0514-Convert-legacy-attributes-in-Item-Meta.patch | 0 .../0515-Remove-some-streams-from-structures.patch | 0 ...0516-Remove-streams-from-classes-related-villager-gossip.patch | 0 .../0517-Support-components-in-ItemMeta.patch | 0 ...0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch | 0 .../0519-Add-entity-liquid-API.patch | 0 .../0520-Update-itemstack-legacy-name-and-lore.patch | 0 .../0521-Spawn-player-in-correct-world-on-login.patch | 0 .../0522-Add-PrepareResultEvent.patch | 0 .../0523-Allow-delegation-to-vanilla-chunk-gen.patch | 0 ...524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch | 0 .../0525-Optimize-NetworkManager-Exception-Handling.patch | 0 .../0526-Fix-Concurrency-issue-in-WeightedList.patch | 0 ...527-Optimize-the-advancement-data-player-iteration-to-be.patch | 0 .../0528-Fix-arrows-never-despawning-MC-125757.patch | 0 .../0529-Thread-Safe-Vanilla-Command-permission-checking.patch | 0 .../0530-Move-range-check-for-block-placing-up.patch | 0 .../0531-Fix-SPIGOT-5989.patch | 0 .../0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch | 0 .../0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch | 0 ...534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch | 0 ...535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch | 0 .../0536-Fix-some-rails-connecting-improperly.patch | 0 ...537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch | 0 .../0538-Incremental-player-saving.patch | 0 .../0539-Import-fastutil-classes.patch | 0 .../0540-Don-t-mark-null-chunk-sections-for-block-updates.patch | 0 .../0541-Remove-armour-stand-double-add-to-world.patch | 0 .../0542-Fix-MC-187716-Use-configured-height.patch | 0 .../0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch | 0 ...544-Do-not-let-the-server-load-chunks-from-newer-version.patch | 0 .../0545-Brand-support.patch | 0 ...546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch | 0 .../0547-Fix-MC-197271.patch | 0 .../0548-MC-197883-Bandaid-decode-issue.patch | 0 .../0549-Add-setMaxPlayers-API.patch | 0 .../0550-Add-playPickupItemAnimation-to-LivingEntity.patch | 0 .../0551-Don-t-require-FACING-data.patch | 0 .../0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch | 0 .../0553-Add-moon-phase-API.patch | 0 .../0554-Prevent-headless-pistons-from-being-created.patch | 0 .../0555-Add-BellRingEvent.patch | 0 .../0556-Add-zombie-targets-turtle-egg-config.patch | 0 .../0557-Buffer-joins-to-world.patch | 0 .../0558-Optimize-redstone-algorithm.patch | 0 .../0559-Fix-hex-colors-not-working-in-some-kick-messages.patch | 0 .../0560-PortalCreateEvent-needs-to-know-its-entity.patch | 0 .../0561-Fix-CraftTeam-null-check.patch | 0 .../0562-Add-more-Evoker-API.patch | 0 ...563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch | 0 .../0564-Create-HoverEvent-from-ItemStack-Entity.patch | 0 .../0565-Cache-block-data-strings.patch | 0 ...566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch | 0 .../0567-Add-additional-open-container-api-to-HumanEntity.patch | 0 .../0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch | 0 ...569-Extend-block-drop-capture-to-capture-all-items-added.patch | 0 .../0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch | 0 ...571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch | 0 .../0572-Lazily-track-plugin-scoreboards-by-default.patch | 0 .../0573-Entity-isTicking.patch | 0 ...574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch | 0 .../0575-Fix-Not-a-string-Map-Conversion-spam.patch | 0 ...0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch | 0 ...577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch | 0 .../0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch | 0 .../0579-Fix-for-large-move-vectors-crashing-server.patch | 0 .../0580-Optimise-getType-calls.patch | 0 .../0581-Villager-resetOffers.patch | 0 .../0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch | 0 ...0583-Retain-block-place-order-when-capturing-blockstates.patch | 0 .../0584-Reduce-blockpos-allocation-from-pathfinding.patch | 0 .../0585-Fix-item-locations-dropped-from-campfires.patch | 0 .../0586-Player-elytra-boost-API.patch | 0 .../0587-Fixed-TileEntityBell-memory-leak.patch | 0 ...588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch | 0 .../0589-Add-getOfflinePlayerIfCached-String.patch | 0 .../0590-Add-ignore-discounts-API.patch | 0 .../0591-Toggle-for-removing-existing-dragon.patch | 0 .../0592-Fix-client-lag-on-advancement-loading.patch | 0 .../0593-Item-no-age-no-player-pickup.patch | 0 .../0594-Beacon-API-custom-effect-ranges.patch | 0 .../0595-Add-API-for-quit-reason.patch | 0 .../0596-Seed-based-feature-search.patch | 0 .../0597-Add-Wandering-Trader-spawn-rate-config-options.patch | 0 ...598-Significantly-improve-performance-of-the-end-generat.patch | 0 .../0599-Expose-world-spawn-angle.patch | 0 .../0600-Add-Destroy-Speed-API.patch | 0 .../0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch | 0 .../0602-Add-LivingEntity-clearActiveItem.patch | 0 .../0603-Add-PlayerItemCooldownEvent.patch | 0 .../0604-More-lightning-API.patch | 0 .../0605-Climbing-should-not-bypass-cramming-gamerule.patch | 0 .../0606-Added-missing-default-perms-for-commands.patch | 0 .../0607-Add-PlayerShearBlockEvent.patch | 0 .../0608-Add-warning-for-servers-not-running-on-Java-16.patch | 0 .../0609-Set-spigots-verbose-world-setting-to-false-by-def.patch | 0 .../0610-Fix-curing-zombie-villager-discount-exploit.patch | 0 .../0611-Limit-recipe-packets.patch | 0 .../0612-Fix-CraftSound-backwards-compatibility.patch | 0 .../0613-MC-4-Fix-item-position-desync.patch | 0 .../0614-Player-Chunk-Load-Unload-Events.patch | 0 .../0615-Optimize-Dynamic-get-Missing-Keys.patch | 0 .../0616-Expose-LivingEntity-hurt-direction.patch | 0 .../0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch | 0 ...618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch | 0 .../0619-added-PlayerTradeEvent.patch | 0 .../0620-Implement-TargetHitEvent.patch | 0 .../0621-Additional-Block-Material-API-s.patch | 0 .../0622-Fix-harming-potion-dupe.patch | 0 ...623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch | 0 .../0624-Optimized-tick-ready-check.patch | 0 .../0625-Cache-burn-durations.patch | 0 ...626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch | 0 .../0627-Implement-PlayerFlowerPotManipulateEvent.patch | 0 .../0628-Fix-interact-event-not-being-called-in-adventure.patch | 0 .../0629-Zombie-API-breaking-doors.patch | 0 .../0630-Fix-nerfed-slime-when-splitting.patch | 0 .../0631-Add-EntityLoadCrossbowEvent.patch | 0 .../0632-Guardian-beam-workaround.patch | 0 .../0633-Added-WorldGameRuleChangeEvent.patch | 0 .../0634-Added-ServerResourcesReloadedEvent.patch | 0 .../0635-Added-world-settings-for-mobs-picking-up-loot.patch | 0 .../0636-Implemented-BlockFailedDispenseEvent.patch | 0 .../0637-Added-PlayerLecternPageChangeEvent.patch | 0 .../0638-Fire-event-on-GS4-query.patch | 0 .../0639-Added-PlayerLoomPatternSelectEvent.patch | 0 .../0640-Configurable-door-breaking-difficulty.patch | 0 .../0641-Empty-commands-shall-not-be-dispatched.patch | 0 .../0642-Implement-API-to-expose-exact-interaction-point.patch | 0 .../0643-Remove-stale-POIs.patch | 0 .../0644-Fix-villager-boat-exploit.patch | 0 .../0645-Entity-load-save-limit-per-chunk.patch | 0 .../0646-Add-sendOpLevel-API.patch | 0 .../0647-Add-StructureLocateEvent.patch | 0 ...0648-Collision-option-for-requiring-a-player-participant.patch | 0 .../0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch | 0 ...650-Return-chat-component-with-empty-text-instead-of-thr.patch | 0 .../0651-Make-schedule-command-per-world.patch | 0 .../0652-Configurable-max-leash-distance.patch | 0 .../0653-Implement-BlockPreDispenseEvent.patch | 0 .../0654-Added-Vanilla-Entity-Tags.patch | 0 .../0655-added-Wither-API.patch | 0 .../0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch | 0 .../0657-Fix-console-spam-when-removing-chests-in-water.patch | 0 .../0658-Add-toggle-for-always-placing-the-dragon-egg.patch | 0 .../0659-Added-PlayerStonecutterRecipeSelectEvent.patch | 0 .../0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch | 0 .../0661-Skip-distance-map-update-when-spawning-disabled.patch | 0 .../0662-Reset-shield-blocking-on-dimension-change.patch | 0 .../0663-add-DragonEggFormEvent.patch | 0 .../0664-EntityMoveEvent.patch | 0 ...665-added-option-to-disable-pathfinding-updates-on-block.patch | 0 .../0666-Inline-shift-direction-fields.patch | 0 .../0667-Allow-adding-items-to-BlockDropItemEvent.patch | 0 .../0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch | 0 .../0669-living-entity-allow-attribute-registration.patch | 0 .../0670-fix-dead-slime-setSize-invincibility.patch | 0 ...0671-Merchant-getRecipes-should-return-an-immutable-list.patch | 0 .../0672-misc-debugging-dumps.patch | 0 .../0673-Add-support-for-hex-color-codes-in-console.patch | 0 .../0674-Clear-SyncLoadInfo.patch | 0 .../0675-Expose-Tracked-Players.patch | 0 .../0676-Remove-streams-from-SensorNearest.patch | 0 .../0677-do-not-create-unnecessary-copies-of-passenger-list.patch | 0 .../0678-MC-29274-Fix-Wither-hostility-towards-players.patch | 0 .../0679-Throw-proper-exception-on-empty-JsonList-file.patch | 0 .../0680-Improve-ServerGUI.patch | 0 ...681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch | 0 .../0682-fix-converting-txt-to-json-file.patch | 0 .../0683-Add-worldborder-events.patch | 0 .../0684-added-PlayerNameEntityEvent.patch | 0 .../0685-Prevent-grindstones-from-overstacking-items.patch | 0 .../0686-Add-recipe-to-cook-events.patch | 0 .../0687-Add-Block-isValidTool.patch | 0 .../0688-Allow-using-signs-inside-spawn-protection.patch | 0 .../0689-Implement-Keyed-on-World.patch | 0 .../0690-Add-fast-alternative-constructor-for-Vector3f.patch | 0 .../0691-Item-Rarity-API.patch | 0 ...692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch | 0 .../0693-copy-TESign-isEditable-from-snapshots.patch | 0 .../0694-Drop-carried-item-when-player-has-disconnected.patch | 0 .../0695-forced-whitelist-use-configurable-kick-message.patch | 0 .../0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch | 0 .../0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch | 0 .../0698-fix-cancelling-block-falling-causing-client-desync.patch | 0 .../0699-Expose-protocol-version.patch | 0 ...700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch | 0 ...701-Enhance-console-tab-completions-for-brigadier-comman.patch | 0 .../0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch | 0 .../0703-Add-bypass-host-check.patch | 0 .../0704-don-t-throw-when-loading-invalid-TEs.patch | 0 .../0705-Set-area-affect-cloud-rotation.patch | 0 .../0706-add-isDeeplySleeping-to-HumanEntity.patch | 0 .../0707-Fix-duplicating-give-items-on-item-drop-cancel.patch | 0 .../0708-add-consumeFuel-to-FurnaceBurnEvent.patch | 0 .../0709-add-get-set-drop-chance-to-EntityEquipment.patch | 0 .../0710-fix-PigZombieAngerEvent-cancellation.patch | 0 .../0711-Fix-checkReach-check-for-Shulker-boxes.patch | 0 .../0712-fix-PlayerItemHeldEvent-firing-twice.patch | 0 .../0713-Added-PlayerDeepSleepEvent.patch | 0 .../0714-More-World-API.patch | 0 .../0715-Added-PlayerBedFailEnterEvent.patch | 0 ...716-Implement-methods-to-convert-between-Component-and-B.patch | 0 ...717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch | 0 .../0718-add-RespawnFlags-to-PlayerRespawnEvent.patch | 0 .../0719-Introduce-beacon-activation-deactivation-events.patch | 0 .../0720-Add-Channel-initialization-listeners.patch | 0 .../0721-Send-empty-commands-if-tab-completion-is-disabled.patch | 0 .../0722-Add-more-WanderingTrader-API.patch | 0 .../0723-Add-EntityBlockStorage-clearEntities.patch | 0 ...0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch | 0 .../0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch | 0 .../0726-Inventory-close.patch | 0 .../0727-call-PortalCreateEvent-players-and-end-platform.patch | 0 ...728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch | 0 .../0729-Fix-CraftPotionBrewer-cache.patch | 0 .../0730-Add-basic-Datapack-API.patch | 0 .../0731-Add-environment-variable-to-disable-server-gui.patch | 0 .../0732-additions-to-PlayerGameModeChangeEvent.patch | 0 .../0733-ItemStack-repair-check-API.patch | 0 .../0734-More-Enchantment-API.patch | 0 ...735-Add-command-line-option-to-load-extra-plugin-jars-no.patch | 0 ...736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch | 0 ...737-Fix-MC-148809-Increase-structure-block-data-length-t.patch | 0 .../0738-Fix-and-optimise-world-force-upgrading.patch | 0 .../0739-Add-Mob-lookAt-API.patch | 0 .../0740-Add-Unix-domain-socket-support.patch | 0 .../0741-Add-EntityInsideBlockEvent.patch | 0 .../0742-Attributes-API-for-item-defaults.patch | 0 .../0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch | 0 .../0744-Add-cause-to-Weather-ThunderChangeEvents.patch | 0 .../0745-More-Lidded-Block-API.patch | 0 .../0746-Add-PlayerKickEvent-causes.patch | 0 .../0747-Limit-item-frame-cursors-on-maps.patch | 0 .../0748-Add-PufferFishStateChangeEvent.patch | 0 .../0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch | 0 .../0750-Add-option-to-fix-items-merging-through-walls.patch | 0 .../0751-Add-BellRevealRaiderEvent.patch | 0 .../0752-Fix-invulnerable-end-crystals.patch | 0 .../0753-Add-ElderGuardianAppearanceEvent.patch | 0 .../0754-Reset-villager-inventory-on-cancelled-pickup-event.patch | 0 .../0755-Fix-dangerous-end-portal-logic.patch | 0 .../0756-Make-item-validations-configurable.patch | 0 .../0757-Add-more-line-of-sight-methods.patch | 0 .../0758-add-per-world-spawn-limits.patch | 0 .../0759-Fix-PotionSplashEvent-for-water-splash-potions.patch | 0 1075 files changed, 0 insertions(+), 0 deletions(-) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0001-POM-changes.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0002-Add-FastUtil-to-Bukkit.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0003-Paper-Utils.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0004-Timings-v2.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0005-Adventure.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0006-Player-affects-spawning-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0007-Add-getTPS-method.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0008-Entity-Origin-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0009-Version-Command-2.0.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0010-Add-PlayerLocaleChangeEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0011-Add-player-view-distance-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0012-Add-BeaconEffectEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0013-Add-PlayerInitialSpawnEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0014-Automatically-disable-plugins-that-fail-to-load.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0015-Expose-server-CommandMap.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0017-Player-Tab-List-and-Title-APIs.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0018-Add-exception-reporting-event.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0019-Fix-ServerListPingEvent-flagging-as-Async.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0022-Complete-resource-pack-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0023-Use-ASM-for-event-executors.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0024-Add-a-call-helper-to-Event.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0025-Add-sender-name-to-commands.yml-replacement.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0026-Add-command-to-reload-permissions.yml-and-require-co.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0027-Custom-replacement-for-eaten-items.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0028-Entity-AddTo-RemoveFrom-World-Events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0029-EntityPathfindEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0031-Add-MetadataStoreBase.removeAll-Plugin.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0032-Add-PlayerUseUnknownEntityEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0034-Arrow-pickup-rule-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0035-EntityRegainHealthEvent-isFastRegen-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0036-LootTable-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0037-Add-EntityZapEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0038-Misc-Utils.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0039-Allow-Reloading-of-Command-Aliases.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0040-Add-source-to-PlayerExpChangeEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0041-Add-ProjectileCollideEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0042-Add-String-based-Action-Bar-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0044-IllegalPacketEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0045-Fireworks-API-s.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0046-PlayerTeleportEndGatewayEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0047-Provide-E-TE-Chunk-count-stat-methods.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0049-Expose-WorldBorder-isInBounds-Location-check.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0050-Add-configuration-option-to-prevent-player-names-fro.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0051-Fix-upstream-javadoc-warnings-and-errors.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0052-Item-canEntityPickup.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0054-PlayerAttemptPickupItemEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0055-Add-UnknownCommandEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0056-Basic-PlayerProfile-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0057-Shoulder-Entities-Release-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0058-Profile-Lookup-Events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0059-Entity-fromMobSpawner.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0060-Improve-the-Saddle-API-for-Horses.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0061-ensureServerConversions-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0062-Add-getI18NDisplayName-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0063-ProfileWhitelistVerifyEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0064-Make-plugins-list-alphabetical.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0065-LivingEntity-setKiller.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0067-Allow-plugins-to-use-SLF4J-for-logging.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0069-Add-PlayerJumpEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0070-Expose-client-protocol-version-and-virtual-host.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0071-Add-PlayerArmorChangeEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0072-API-to-get-a-BlockState-without-a-snapshot.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0073-AsyncTabCompleteEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0074-Display-warning-on-deprecated-recipe-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0075-PlayerPickupExperienceEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0076-ExperienceOrbMergeEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0077-Ability-to-apply-mending-to-XP-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0078-PreCreatureSpawnEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0079-PlayerNaturallySpawnCreaturesEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0080-Add-setPlayerProfile-API-for-Skulls.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0081-Fill-Profile-Property-Events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0082-PlayerAdvancementCriterionGrantEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0083-Add-ArmorStand-Item-Meta.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0084-Optimize-Hoppers.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0085-Tameable-getOwnerUniqueId-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0087-Add-extended-PaperServerListPingEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0088-Player.setPlayerProfile-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0089-getPlayerUniqueId-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0091-Add-method-to-open-already-placed-sign.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0092-Add-Ban-Methods-to-Player-Objects.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0093-EndermanEscapeEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0094-Enderman.teleportRandomly.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0095-Additional-world.getNearbyEntities-API-s.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0096-Location.isChunkLoaded-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0097-Expand-World.spawnParticle-API-and-add-Builder.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0098-EndermanAttackPlayerEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0099-Close-Plugin-Class-Loaders-on-Disable.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0100-WitchConsumePotionEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0101-WitchThrowPotionEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0102-Location.toBlockLocation-toCenterLocation.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0103-PotionEffect-clone-methods.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0104-WitchReadyPotionEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0105-ItemStack-getMaxItemUseDuration.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0106-Add-EntityTeleportEndGatewayEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0107-Make-shield-blocking-delay-configurable.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0109-Add-getNearbyXXX-methods-to-Location.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0110-PlayerReadyArrowEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0111-Add-EntityKnockbackByEntityEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0112-Expand-Explosions-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0113-ItemStack-API-additions-for-quantity-flags-lore.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0114-LivingEntity-Hand-Raised-Item-Use-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0115-RangedEntity-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0116-Add-World.getEntity-UUID-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0117-InventoryCloseEvent-Reason-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0118-Entity-getChunk-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0119-Add-an-asterisk-to-legacy-API-plugins.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0120-EnderDragon-Events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0121-PlayerLaunchProjectileEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0122-PlayerElytraBoostEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0123-EntityTransformedEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0124-Allow-disabling-armour-stand-ticking.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0125-SkeletonHorse-Additions.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0126-Expand-Location-Manipulation-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0127-Expand-ArmorStand-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0128-AnvilDamageEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0129-Remove-deadlock-risk-in-firing-async-events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0130-Add-hand-to-bucket-events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0131-Add-TNTPrimeEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0133-Async-Chunks-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0134-Make-EnderDragon-extend-Mob.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0138-Slime-Pathfinder-Events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0139-isChunkGenerated-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0140-Add-More-Creeper-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0141-Add-PhantomPreSpawnEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0142-Add-source-block-to-BlockPhysicsEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0143-Inventory-removeItemAnySlot.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0144-Add-ray-tracing-methods-to-LivingEntity.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0145-Improve-death-events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0146-Mob-Pathfinding-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0147-Expose-attack-cooldown-methods-for-Player.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0149-Performance-Concurrency-Improvements-to-Permissions.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0150-Add-ItemStackRecipeChoice-Draft-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0151-Implement-furnace-cook-speed-multiplier-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0152-PreSpawnerSpawnEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0153-Material-API-additions.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0154-Add-Material-Tags.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0155-Allow-setting-the-vex-s-summoner.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0156-Add-LivingEntity-getTargetEntity.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0157-Add-sun-related-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0158-Here-s-Johnny.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0159-Turtle-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0160-Add-spectator-target-events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0161-Add-more-Witch-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0162-Make-the-default-permission-message-configurable.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0164-Add-more-Zombie-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0165-Change-the-reserved-channel-check-to-be-sensible.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0166-Add-PlayerConnectionCloseEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0168-BlockDestroyEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0169-Add-ItemStack-Recipe-API-helper-methods.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0170-Add-WhitelistToggleEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0171-Annotation-Test-changes.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0172-Entity-getEntitySpawnReason.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0173-Add-GS4-Query-event.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0174-Add-PlayerPostRespawnEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0175-Ignore-package-private-methods-for-nullability-annot.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0176-Flip-some-Spigot-API-null-annotations.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0177-Server-Tick-Events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0178-PlayerDeathEvent-getItemsToKeep.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0179-Add-Heightmap-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0180-Mob-Spawner-API-Enhancements.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0181-Add-BlockSoundGroup-interface.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0183-Increase-custom-payload-channel-message-size.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0184-Expose-the-internal-current-tick.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0185-PlayerDeathEvent-shouldDropExperience.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0186-Add-effect-to-block-break-naturally.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0187-Add-ThrownEggHatchEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0188-Entity-Jump-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0189-add-hand-to-BlockMultiPlaceEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0190-Add-tick-times-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0191-Expose-MinecraftServer-isRunning.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0193-Make-JavaPluginLoader-thread-safe.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0194-Add-Player-Client-Options-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0195-Add-PlayerAttackEntityCooldownResetEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0197-Villager-Restocks-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0198-Expose-game-version.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0199-Add-item-slot-convenience-methods.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0200-Add-Mob-Goal-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0201-World-view-distance-api.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0202-Add-villager-reputation-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0203-Spawn-Reason-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0204-Potential-bed-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0205-Prioritise-own-classes-where-possible.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0206-Add-Raw-Byte-ItemStack-Serialization.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0207-Provide-a-useful-PluginClassLoader-toString.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0208-Inventory-getHolder-method-without-block-snapshot.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0209-Expose-Arrow-getItemStack.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0211-Support-components-in-ItemMeta.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0213-Add-entity-liquid-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0215-Allow-delegation-to-vanilla-chunk-gen.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0216-Support-hex-colors-in-getLastColors.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0217-Add-setMaxPlayers-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0218-Add-moon-phase-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0219-Add-playPickupItemAnimation-to-LivingEntity.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0220-Add-BellRingEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0221-Brand-support.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0222-Add-more-Evoker-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0224-Create-HoverEvent-from-ItemStack-Entity.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0225-Add-additional-open-container-api-to-HumanEntity.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0227-Entity-isTicking.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0229-Villager-resetOffers.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0230-Player-elytra-boost-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0231-Add-getOfflinePlayerIfCached-String.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0232-Add-ignore-discounts-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0233-Item-no-age-no-player-pickup.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0234-Beacon-API-custom-effect-ranges.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0235-Add-API-for-quit-reason.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0236-Add-Destroy-Speed-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0237-Add-LivingEntity-clearActiveItem.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0238-Add-PlayerItemCooldownEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0239-More-lightning-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0240-Add-PlayerShearBlockEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0241-Enable-multi-release-plugin-jars.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0242-Player-Chunk-Load-Unload-Events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0243-Expose-LivingEntity-hurt-direction.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0244-Added-PlayerTradeEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0246-Add-TargetHitEvent-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0247-Additional-Block-Material-API-s.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0249-Add-PlayerFlowerPotManipulateEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0250-Zombie-API-breaking-doors.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0251-Add-EntityLoadCrossbowEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0252-Added-WorldGameRuleChangeEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0253-Added-ServerResourcesReloadedEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0254-Add-BlockFailedDispenseEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0255-Added-PlayerLecternPageChangeEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0256-Added-PlayerLoomPatternSelectEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0257-Better-AnnotationTest-printout.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0259-Add-sendOpLevel-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0260-Add-StructureLocateEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0261-Return-chat-component-with-empty-text-instead-of-thr.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0262-Add-BlockPreDispenseEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0263-Added-Vanilla-Entity-Tags.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0264-added-Wither-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0265-Added-PlayerChangeBeaconEffectEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0267-Added-PlayerStonecutterRecipeSelectEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0268-EntityMoveEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0269-add-DragonEggFormEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0270-Allow-adding-items-to-BlockDropItemEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0272-living-entity-allow-attribute-registration.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0273-Add-missing-effects.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0274-Expose-Tracked-Players.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0275-Cache-the-result-of-Material-isBlock.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0276-Add-worldborder-events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0277-added-PlayerNameEntityEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0278-Add-recipe-to-cook-events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0279-Add-Block-isValidTool.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0280-Implement-Keyed-on-World.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0281-fix-Inventory-getContents-null-annotations.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0282-Item-Rarity-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0283-Expose-protocol-version.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0284-add-isDeeplySleeping-to-HumanEntity.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0285-add-consumeFuel-to-FurnaceBurnEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0286-add-get-set-drop-chance-to-EntityEquipment.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0287-Added-PlayerDeepSleepEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0288-More-World-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0289-Added-PlayerBedFailEnterEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0290-Introduce-beacon-activation-deactivation-events.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0291-PlayerMoveEvent-Improvements.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0293-Add-more-WanderingTrader-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0295-Add-EntityBlockStorage-clearEntities.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0298-Inventory-close.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0300-Add-basic-Datapack-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0301-additions-to-PlayerGameModeChangeEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0302-ItemStack-repair-check-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0303-More-Enchantment-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0305-List-all-missing-hard-depends-not-just-first.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0306-Add-Mob-lookAt-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0307-ItemStack-editMeta.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0308-Add-EntityInsideBlockEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0309-Attributes-API-for-item-defaults.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0310-Add-cause-to-Weather-ThunderChangeEvents.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0311-More-Lidded-Block-API.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0312-Add-PlayerKickEvent-causes.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0313-Add-PufferFishStateChangeEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0314-Add-BellRevealRaiderEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0315-Add-ElderGuardianAppearanceEvent.patch (100%) rename {Spigot-API-Patches => Unmapped-Spigot-API-Patches}/0316-Add-more-line-of-sight-methods.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0001-POM-Changes.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0002-Paper-config-files.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0003-MC-Dev-fixes.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0004-MC-Utils.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0005-Paper-Metrics.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0006-Add-MinecraftKey-Information-to-Objects.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0009-Timings-v2.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0010-Adventure.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0012-Configurable-baby-zombie-movement-speed.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0013-Configurable-fishing-time-ranges.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0015-Add-configurable-despawn-distances-for-living-entiti.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0016-Allow-for-toggling-of-spawn-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0019-Implement-Paper-VersionChecker.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0020-Add-version-history-to-version-command.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0021-Player-affects-spawning-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0022-Remove-invalid-mob-spawner-tile-entities.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0023-Optimize-TileEntity-Ticking.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0024-Further-improve-server-tick-loop.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0025-Only-refresh-abilities-if-needed.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0026-Entity-Origin-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0027-Prevent-tile-entity-and-entity-crashes.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0028-Configurable-top-of-nether-void-damage.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0029-Check-online-mode-before-converting-and-renaming-pla.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0030-Always-tick-falling-blocks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0031-Configurable-end-credits.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0032-Fix-lag-from-explosions-processing-dead-entities.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0033-Optimize-explosions.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0034-Disable-explosion-knockback.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0035-Disable-thunder.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0036-Disable-ice-and-snow.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0037-Configurable-mob-spawner-tick-rate.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0039-Add-BeaconEffectEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0040-Configurable-container-update-tick-rate.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0041-Use-UserCache-for-player-heads.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0042-Disable-spigot-tick-limiters.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0043-Add-PlayerInitialSpawnEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0044-Configurable-Disabling-Cat-Chest-Detection.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0045-Ensure-commands-are-not-ran-async.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0046-All-chunks-are-slime-spawn-chunks-toggle.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0047-Expose-server-CommandMap.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0049-Player-Tab-List-and-Title-APIs.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0050-Ensure-inv-drag-is-in-bounds.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0051-Change-implementation-of-tile-entity-removal-list.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0052-Add-configurable-portal-search-radius.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0053-Add-velocity-warnings.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0054-Configurable-inter-world-teleportation-safety.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0055-Add-exception-reporting-event.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0057-Disable-Scoreboards-for-non-players-by-default.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0059-Complete-resource-pack-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0060-Chunk-Save-Reattempt.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0061-Default-loading-permissions.yml-before-plugins.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0062-Allow-Reloading-of-Custom-Permissions.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0063-Remove-Metadata-on-reload.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0064-Handle-Item-Meta-Inconsistencies.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0066-Add-World-Util-Methods.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0067-Custom-replacement-for-eaten-items.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0069-Use-a-Shared-Random-for-Entities.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0070-Configurable-spawn-chances-for-skeleton-horses.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0073-Entity-AddTo-RemoveFrom-World-Events.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0074-Configurable-Chunk-Inhabited-Time.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0075-EntityPathfindEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0076-Sanitise-RegionFileCache-and-make-configurable.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0077-Do-not-load-chunks-for-Pathfinding.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0078-Add-PlayerUseUnknownEntityEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0080-Configurable-Grass-Spread-Tick-Rate.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0082-Optimize-DataBits.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0084-Workaround-for-setting-passengers-on-players.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0085-Remove-unused-World-Tile-Entity-List.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0086-Don-t-tick-Skulls-unused-code.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0087-Configurable-Player-Collision.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0089-Configurable-RCON-IP-address.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0091-Implement-PlayerLocaleChangeEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0092-EntityRegainHealthEvent-isFastRegen-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0093-Add-ability-to-configure-frosted_ice-properties.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0094-remove-null-possibility-for-getServer-singleton.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0096-LootTable-API-Replenishable-Lootables-Feature.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0098-System-property-for-disabling-watchdoge.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0099-Optimize-UserCache-Thread-Safe.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0100-Avoid-blocking-on-Network-Manager-creation.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0101-Optional-TNT-doesn-t-move-in-water.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0102-Faster-redstone-torch-rapid-clock-removal.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0103-Add-server-name-parameter.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0105-Fix-Double-World-Add-issues.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0106-Fix-Old-Sign-Conversion.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0108-Add-setting-for-proxy-online-mode-status.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0109-Optimise-BlockState-s-hashCode-equals.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0110-Configurable-packet-in-spam-threshold.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0111-Configurable-flying-kick-messages.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0112-Chunk-registration-fixes.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0114-Auto-fix-bad-Y-levels-on-player-login.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0115-Option-to-remove-corrupt-tile-entities.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0116-Add-EntityZapEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0118-Cache-user-authenticator-threads.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0119-Optimise-removeQueue.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0120-Allow-Reloading-of-Command-Aliases.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0121-Add-source-to-PlayerExpChangeEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0122-Don-t-let-fishinghooks-use-portals.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0123-Add-ProjectileCollideEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0124-Prevent-Pathfinding-out-of-World-Border.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0125-Optimize-World.isLoaded-BlockPosition-Z.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0126-Bound-Treasure-Maps-to-World-Border.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0127-Configurable-Cartographer-Treasure-Maps.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0128-Optimize-ItemStack.isEmpty.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0130-Properly-fix-item-duplication-bug.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0131-String-based-Action-Bar-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0132-Firework-API-s.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0133-PlayerTeleportEndGatewayEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0134-Provide-E-TE-Chunk-count-stat-methods.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0135-Enforce-Sync-Player-Saves.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0136-Don-t-allow-entities-to-ride-themselves-572.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0138-Cap-Entity-Collisions.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0139-Remove-CraftScheduler-Async-Task-Debugger.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0141-Do-not-let-armorstands-drown.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0142-Properly-handle-async-calls-to-restart-the-server.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0143-Add-system-property-to-disable-book-size-limits.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0145-Add-configuration-option-to-prevent-player-names-fro.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0146-Use-TerminalConsoleAppender-for-console-improvements.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0147-provide-a-configurable-option-to-disable-creeper-lin.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0148-Item-canEntityPickup.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0150-PlayerAttemptPickupItemEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0151-Add-UnknownCommandEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0152-Basic-PlayerProfile-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0153-Shoulder-Entities-Release-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0154-Profile-Lookup-Events.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0155-Block-player-logins-during-server-shutdown.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0156-Entity-fromMobSpawner.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0157-Improve-the-Saddle-API-for-Horses.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0158-Implement-ensureServerConversions-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0159-Implement-getI18NDisplayName.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0160-ProfileWhitelistVerifyEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0161-Fix-this-stupid-bullshit.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0165-Allow-specifying-a-custom-authentication-servers-dow.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0166-LivingEntity-setKiller.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0169-Add-PlayerJumpEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0170-handle-PacketPlayInKeepAlive-async.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0171-Expose-client-protocol-version-and-virtual-host.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0172-revert-serverside-behavior-of-keepalives.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0174-Option-for-maximum-exp-value-when-merging-orbs.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0175-Add-PlayerArmorChangeEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0176-Prevent-logins-from-being-processed-when-the-player-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0177-use-CB-BlockState-implementations-for-captured-block.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0178-API-to-get-a-BlockState-without-a-snapshot.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0179-AsyncTabCompleteEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0180-Avoid-NPE-in-PathfinderGoalTempt.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0181-PlayerPickupExperienceEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0182-ExperienceOrbMergeEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0183-Ability-to-apply-mending-to-XP-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0184-Make-max-squid-spawn-height-configurable.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0185-PreCreatureSpawnEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0186-PlayerNaturallySpawnCreaturesEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0187-Add-setPlayerProfile-API-for-Skulls.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0188-Fill-Profile-Property-Events.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0189-PlayerAdvancementCriterionGrantEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0190-Add-ArmorStand-Item-Meta.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0191-Extend-Player-Interact-cancellation.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0192-Tameable-getOwnerUniqueId-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0195-Disable-Explicit-Network-Manager-Flushing.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0196-Implement-extended-PaperServerListPingEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0197-Improved-Async-Task-Scheduler.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0199-Player.setPlayerProfile-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0200-Fix-Dragon-Server-Crashes.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0201-getPlayerUniqueId-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0202-Make-player-data-saving-configurable.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0203-Make-legacy-ping-handler-more-reliable.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0205-Flag-to-disable-the-channel-limit.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0206-Add-method-to-open-already-placed-sign.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0207-Configurable-sprint-interruption-on-attack.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0209-EndermanEscapeEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0210-Enderman.teleportRandomly.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0211-Block-Enderpearl-Travel-Exploit.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0212-Expand-World.spawnParticle-API-and-add-Builder.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0213-EndermanAttackPlayerEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0214-WitchConsumePotionEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0215-WitchThrowPotionEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0217-WitchReadyPotionEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0218-ItemStack-getMaxItemUseDuration.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0219-Implement-EntityTeleportEndGatewayEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0221-Fix-CraftEntity-hashCode.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0222-Configurable-Alternative-LootPool-Luck-Formula.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0223-Print-Error-details-when-failing-to-save-player-data.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0224-Make-shield-blocking-delay-configurable.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0225-Improve-EntityShootBowEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0226-PlayerReadyArrowEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0227-Implement-EntityKnockbackByEntityEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0228-Expand-Explosions-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0229-LivingEntity-Hand-Raised-Item-Use-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0230-RangedEntity-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0231-Add-config-to-disable-ender-dragon-legacy-check.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0232-Implement-World.getEntity-UUID-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0233-InventoryCloseEvent-Reason-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0234-Vex-getSummoner-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0239-Use-asynchronous-Log4j-2-loggers.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0240-add-more-information-to-Entity.toString.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0242-EnderDragon-Events.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0243-PlayerElytraBoostEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0244-Improve-BlockPosition-inlining.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0245-Optimize-RegistryID.c.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0247-Vanished-players-don-t-have-rights.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0249-Add-some-Debug-to-Chunk-Entity-slices.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0250-SkeletonHorse-Additions.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0251-Prevent-Saving-Bad-entities-to-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0253-Ignore-Dead-Entities-in-entityList-iteration.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0254-Implement-Expanded-ArmorStand-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0255-AnvilDamageEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0256-Add-TNTPrimeEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0257-Break-up-and-make-tab-spam-limits-configurable.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0258-Add-hand-to-bucket-events.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0259-MC-135506-Experience-should-save-as-Integers.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0260-Fix-client-rendering-skulls-from-same-user.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0261-Add-Early-Warning-Feature-to-WatchDog.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0262-Make-EnderDragon-implement-Mob.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0263-Use-ConcurrentHashMap-in-JsonList.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0264-Use-a-Queue-for-Queueing-Commands.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0266-Allow-disabling-armour-stand-ticking.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0267-Optimize-BlockPosition-helper-methods.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0269-Slime-Pathfinder-Events.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0270-Configurable-speed-for-water-flowing-over-lava.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0271-Optimize-CraftBlockData-Creation.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0272-Optimize-RegistryMaterials.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0273-Add-PhantomPreSpawnEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0274-Add-More-Creeper-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0275-Inventory-removeItemAnySlot.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0277-Add-ray-tracing-methods-to-LivingEntity.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0278-Expose-attack-cooldown-methods-for-Player.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0279-Improve-death-events.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0280-Allow-chests-to-be-placed-with-NBT-data.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0281-Mob-Pathfinding-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0287-Implement-furnace-cook-speed-multiplier-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0288-PreSpawnerSpawnEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0290-Honor-EntityAgeable.ageLock.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0291-Configurable-connection-throttle-kick-message.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0292-Hook-into-CB-plugin-rewrites.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0293-Allow-setting-the-vex-s-summoner.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0294-Add-sun-related-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0295-Turtle-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0297-Call-player-spectator-target-events-and-improve-impl.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0298-Add-Velocity-IP-Forwarding-Support.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0299-Add-more-Witch-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0300-Check-Drowned-for-Villager-Aggression-Config.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0301-Here-s-Johnny.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0303-Reset-players-airTicks-on-respawn.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0306-Optimize-World-Time-Updates.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0307-Restore-custom-InventoryHolder-support.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0308-Use-Vanilla-Minecart-Speeds.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0309-Fix-SpongeAbsortEvent-handling.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0310-Don-t-allow-digging-into-unloaded-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0311-Book-Size-Limits.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0312-Make-the-default-permission-message-configurable.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0313-Prevent-rayTrace-from-loading-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0314-Handle-Large-Packets-disconnecting-client.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0315-force-entity-dismount-during-teleportation.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0316-Add-more-Zombie-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0317-Add-PlayerConnectionCloseEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0318-Prevent-Enderman-from-loading-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0322-Block-Entity-remove-from-being-called-on-Players.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0323-BlockDestroyEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0325-Fix-sign-edit-memory-leak.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0326-Limit-Client-Sign-length-more.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0329-Handle-Oversized-Tile-Entities-in-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0332-Allow-Saving-of-Oversized-Chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0334-Add-LivingEntity-getTargetEntity.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0336-Entity-getEntitySpawnReason.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0337-Update-entity-Metadata-for-all-tracked-players.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0338-Implement-PlayerPostRespawnEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0340-Server-Tick-Events.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0341-PlayerDeathEvent-getItemsToKeep.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0342-Optimize-Captured-TileEntity-Lookup.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0343-Add-Heightmap-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0344-Mob-Spawner-API-Enhancements.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0345-Per-Player-View-Distance-API-placeholders.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0346-Fix-CB-call-to-changed-postToMainThread-method.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0350-Duplicate-UUID-Resolve-Option.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0351-improve-CraftWorld-isChunkLoaded.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0354-ChunkMapDistance-CME.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0355-Implement-CraftBlockSoundGroup.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0356-Chunk-debug-command.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0357-Catch-exceptions-from-dispenser-entity-spawns.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0358-Fix-World-isChunkGenerated-calls.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0359-Show-blockstate-location-if-we-failed-to-read-it.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0361-incremental-chunk-saving.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0362-Anti-Xray.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0364-Configurable-projectile-relative-velocity.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0366-offset-item-frame-ticking.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0367-Avoid-hopper-searches-if-there-are-no-items.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0368-Asynchronous-chunk-IO-and-loading.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0369-Use-getChunkIfLoadedImmediately-in-places.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0370-Reduce-sync-loads.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0371-Implement-alternative-item-despawn-rate.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0373-Fix-MC-158900.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0374-implement-optional-per-player-mob-spawns.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0375-Prevent-consuming-the-wrong-itemstack.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0376-Generator-Settings.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0377-Fix-MC-161754.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0378-Performance-improvement-for-Chunk.getEntities.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0380-Expose-the-internal-current-tick.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0382-Add-option-to-disable-pillager-patrols.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0384-PlayerLaunchProjectileEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0388-Optimize-Hoppers.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0389-PlayerDeathEvent-shouldDropExperience.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0390-Prevent-bees-loading-chunks-checking-hive-position.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0392-Guard-against-serializing-mismatching-chunk-coordina.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0393-Optimise-IEntityAccess-getPlayerByUUID.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0394-Fix-items-not-falling-correctly.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0395-Lag-compensate-eating.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0396-Optimize-call-to-getFluid-for-explosions.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0398-Add-effect-to-block-break-naturally.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0399-Tracking-Range-Improvements.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0400-Entity-Activation-Range-2.0.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0401-Fix-items-vanishing-through-end-portal.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0404-Allow-overriding-the-java-version-check.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0405-Add-ThrownEggHatchEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0406-Optimise-random-block-ticking.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0407-Entity-Jump-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0409-Make-the-GUI-graph-fancier.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0410-add-hand-to-BlockMultiPlaceEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0411-Prevent-teleporting-dead-entities.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0412-Validate-tripwire-hook-placement-before-update.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0414-Configurable-chance-of-villager-zombie-infection.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0415-Optimise-Chunk-getFluid.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0416-Optimise-TickListServer-by-rewriting-it.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0418-Ensure-Entity-is-never-double-registered.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0419-Fix-unregistering-entities-from-unloading-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0423-Optimize-Collision-to-not-load-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0424-Don-t-tick-dead-players.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0427-Increase-Light-Queue-Size.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0429-Don-t-move-existing-players-to-world-spawn.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0430-Add-tick-times-API-and-mspt-command.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0431-Expose-MinecraftServer-isRunning.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0432-Add-Raw-Byte-ItemStack-Serialization.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0433-Remove-streams-from-Mob-AI-System.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0435-Async-command-map-building.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0436-Improved-Watchdog-Support.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0437-Optimize-Pathfinding.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0438-Reduce-Either-Optional-allocation.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0439-Remove-streams-from-PairedQueue.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0440-Reduce-memory-footprint-of-NBTTagCompound.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0441-Prevent-opening-inventories-when-frozen.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0442-Optimise-ArraySetSorted-removeIf.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0443-Don-t-run-entity-collision-code-if-not-needed.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0446-Implement-Player-Client-Options-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0449-Broadcast-join-message-to-console.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0451-Load-Chunks-for-Login-Asynchronously.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0453-Add-PlayerAttackEntityCooldownResetEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0456-Add-phantom-creative-and-insomniac-controls.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0458-Implement-Brigadier-Mojang-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0459-Villager-Restocks-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0461-Expose-game-version.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0462-Optimize-Voxel-Shape-Merging.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0464-Implement-Mob-Goal-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0465-Use-distance-map-to-optimise-entity-tracker.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0466-Optimize-isOutsideRange-to-use-distance-maps.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0468-No-Tick-view-distance-implementation.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0469-Add-villager-reputation-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0470-Fix-Light-Command.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0471-Fix-PotionEffect-ignores-icon-flag.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0472-Optimize-brigadier-child-sorting-performance.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0473-Potential-bed-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0474-Wait-for-Async-Tasks-during-shutdown.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0478-Reduce-MutableInt-allocations-from-light-engine.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0480-Ensure-safe-gateway-teleport.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0481-Add-option-for-console-having-all-permissions.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0486-Improve-Chunk-Status-Transition-Speed.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0487-Fix-villager-trading-demand-MC-163962.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0488-Maps-shouldn-t-load-chunks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0490-Optimize-Bit-Operations-by-inlining.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0491-Optimize-Light-Engine.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0494-Fix-missing-chunks-due-to-integer-overflow.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0496-Fix-piston-physics-inconsistency-MC-188840.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0497-Fix-sand-duping.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0498-Prevent-position-desync-in-playerconnection-causing-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0499-Fix-enderdragon-exp-dupe.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0500-Inventory-getHolder-method-without-block-snapshot.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0501-Expose-Arrow-getItemStack.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0503-Hide-sync-chunk-writes-behind-flag.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0504-Limit-lightning-strike-effect-distance.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0505-Add-permission-for-command-blocks.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0506-Ensure-Entity-AABB-s-are-never-invalid.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0507-Optimize-WorldBorder-collision-checks-and-air.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0509-Paper-dumpitem-command.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0510-Don-t-allow-null-UUID-s-for-chat.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0511-Improve-Legacy-Component-serialization-size.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0512-Support-old-UUID-format-for-NBT.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0513-Clean-up-duplicated-GameProfile-Properties.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0514-Convert-legacy-attributes-in-Item-Meta.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0515-Remove-some-streams-from-structures.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0516-Remove-streams-from-classes-related-villager-gossip.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0517-Support-components-in-ItemMeta.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0519-Add-entity-liquid-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0520-Update-itemstack-legacy-name-and-lore.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0521-Spawn-player-in-correct-world-on-login.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0522-Add-PrepareResultEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0523-Allow-delegation-to-vanilla-chunk-gen.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0525-Optimize-NetworkManager-Exception-Handling.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0526-Fix-Concurrency-issue-in-WeightedList.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0527-Optimize-the-advancement-data-player-iteration-to-be.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0528-Fix-arrows-never-despawning-MC-125757.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0529-Thread-Safe-Vanilla-Command-permission-checking.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0530-Move-range-check-for-block-placing-up.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0531-Fix-SPIGOT-5989.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0536-Fix-some-rails-connecting-improperly.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0538-Incremental-player-saving.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0539-Import-fastutil-classes.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0541-Remove-armour-stand-double-add-to-world.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0542-Fix-MC-187716-Use-configured-height.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0545-Brand-support.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0547-Fix-MC-197271.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0548-MC-197883-Bandaid-decode-issue.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0549-Add-setMaxPlayers-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0550-Add-playPickupItemAnimation-to-LivingEntity.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0551-Don-t-require-FACING-data.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0553-Add-moon-phase-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0554-Prevent-headless-pistons-from-being-created.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0555-Add-BellRingEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0556-Add-zombie-targets-turtle-egg-config.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0557-Buffer-joins-to-world.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0558-Optimize-redstone-algorithm.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0560-PortalCreateEvent-needs-to-know-its-entity.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0561-Fix-CraftTeam-null-check.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0562-Add-more-Evoker-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0564-Create-HoverEvent-from-ItemStack-Entity.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0565-Cache-block-data-strings.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0567-Add-additional-open-container-api-to-HumanEntity.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0569-Extend-block-drop-capture-to-capture-all-items-added.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0572-Lazily-track-plugin-scoreboards-by-default.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0573-Entity-isTicking.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0575-Fix-Not-a-string-Map-Conversion-spam.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0579-Fix-for-large-move-vectors-crashing-server.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0580-Optimise-getType-calls.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0581-Villager-resetOffers.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0583-Retain-block-place-order-when-capturing-blockstates.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0584-Reduce-blockpos-allocation-from-pathfinding.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0585-Fix-item-locations-dropped-from-campfires.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0586-Player-elytra-boost-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0587-Fixed-TileEntityBell-memory-leak.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0589-Add-getOfflinePlayerIfCached-String.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0590-Add-ignore-discounts-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0591-Toggle-for-removing-existing-dragon.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0592-Fix-client-lag-on-advancement-loading.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0593-Item-no-age-no-player-pickup.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0594-Beacon-API-custom-effect-ranges.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0595-Add-API-for-quit-reason.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0596-Seed-based-feature-search.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0597-Add-Wandering-Trader-spawn-rate-config-options.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0598-Significantly-improve-performance-of-the-end-generat.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0599-Expose-world-spawn-angle.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0600-Add-Destroy-Speed-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0602-Add-LivingEntity-clearActiveItem.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0603-Add-PlayerItemCooldownEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0604-More-lightning-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0605-Climbing-should-not-bypass-cramming-gamerule.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0606-Added-missing-default-perms-for-commands.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0607-Add-PlayerShearBlockEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0608-Add-warning-for-servers-not-running-on-Java-16.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0609-Set-spigots-verbose-world-setting-to-false-by-def.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0610-Fix-curing-zombie-villager-discount-exploit.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0611-Limit-recipe-packets.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0612-Fix-CraftSound-backwards-compatibility.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0613-MC-4-Fix-item-position-desync.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0614-Player-Chunk-Load-Unload-Events.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0615-Optimize-Dynamic-get-Missing-Keys.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0616-Expose-LivingEntity-hurt-direction.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0619-added-PlayerTradeEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0620-Implement-TargetHitEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0621-Additional-Block-Material-API-s.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0622-Fix-harming-potion-dupe.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0624-Optimized-tick-ready-check.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0625-Cache-burn-durations.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0627-Implement-PlayerFlowerPotManipulateEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0628-Fix-interact-event-not-being-called-in-adventure.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0629-Zombie-API-breaking-doors.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0630-Fix-nerfed-slime-when-splitting.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0631-Add-EntityLoadCrossbowEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0632-Guardian-beam-workaround.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0633-Added-WorldGameRuleChangeEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0634-Added-ServerResourcesReloadedEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0635-Added-world-settings-for-mobs-picking-up-loot.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0636-Implemented-BlockFailedDispenseEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0637-Added-PlayerLecternPageChangeEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0638-Fire-event-on-GS4-query.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0639-Added-PlayerLoomPatternSelectEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0640-Configurable-door-breaking-difficulty.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0641-Empty-commands-shall-not-be-dispatched.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0642-Implement-API-to-expose-exact-interaction-point.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0643-Remove-stale-POIs.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0644-Fix-villager-boat-exploit.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0645-Entity-load-save-limit-per-chunk.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0646-Add-sendOpLevel-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0647-Add-StructureLocateEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0648-Collision-option-for-requiring-a-player-participant.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0650-Return-chat-component-with-empty-text-instead-of-thr.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0651-Make-schedule-command-per-world.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0652-Configurable-max-leash-distance.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0653-Implement-BlockPreDispenseEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0654-Added-Vanilla-Entity-Tags.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0655-added-Wither-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0657-Fix-console-spam-when-removing-chests-in-water.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0658-Add-toggle-for-always-placing-the-dragon-egg.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0659-Added-PlayerStonecutterRecipeSelectEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0661-Skip-distance-map-update-when-spawning-disabled.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0662-Reset-shield-blocking-on-dimension-change.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0663-add-DragonEggFormEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0664-EntityMoveEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0665-added-option-to-disable-pathfinding-updates-on-block.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0666-Inline-shift-direction-fields.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0667-Allow-adding-items-to-BlockDropItemEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0669-living-entity-allow-attribute-registration.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0670-fix-dead-slime-setSize-invincibility.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0671-Merchant-getRecipes-should-return-an-immutable-list.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0672-misc-debugging-dumps.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0673-Add-support-for-hex-color-codes-in-console.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0674-Clear-SyncLoadInfo.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0675-Expose-Tracked-Players.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0676-Remove-streams-from-SensorNearest.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0677-do-not-create-unnecessary-copies-of-passenger-list.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0678-MC-29274-Fix-Wither-hostility-towards-players.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0679-Throw-proper-exception-on-empty-JsonList-file.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0680-Improve-ServerGUI.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0682-fix-converting-txt-to-json-file.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0683-Add-worldborder-events.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0684-added-PlayerNameEntityEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0685-Prevent-grindstones-from-overstacking-items.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0686-Add-recipe-to-cook-events.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0687-Add-Block-isValidTool.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0688-Allow-using-signs-inside-spawn-protection.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0689-Implement-Keyed-on-World.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0690-Add-fast-alternative-constructor-for-Vector3f.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0691-Item-Rarity-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0693-copy-TESign-isEditable-from-snapshots.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0694-Drop-carried-item-when-player-has-disconnected.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0695-forced-whitelist-use-configurable-kick-message.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0698-fix-cancelling-block-falling-causing-client-desync.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0699-Expose-protocol-version.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0701-Enhance-console-tab-completions-for-brigadier-comman.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0703-Add-bypass-host-check.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0704-don-t-throw-when-loading-invalid-TEs.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0705-Set-area-affect-cloud-rotation.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0706-add-isDeeplySleeping-to-HumanEntity.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0708-add-consumeFuel-to-FurnaceBurnEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0709-add-get-set-drop-chance-to-EntityEquipment.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0710-fix-PigZombieAngerEvent-cancellation.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0711-Fix-checkReach-check-for-Shulker-boxes.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0712-fix-PlayerItemHeldEvent-firing-twice.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0713-Added-PlayerDeepSleepEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0714-More-World-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0715-Added-PlayerBedFailEnterEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0716-Implement-methods-to-convert-between-Component-and-B.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0719-Introduce-beacon-activation-deactivation-events.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0720-Add-Channel-initialization-listeners.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0721-Send-empty-commands-if-tab-completion-is-disabled.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0722-Add-more-WanderingTrader-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0723-Add-EntityBlockStorage-clearEntities.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0726-Inventory-close.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0727-call-PortalCreateEvent-players-and-end-platform.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0729-Fix-CraftPotionBrewer-cache.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0730-Add-basic-Datapack-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0731-Add-environment-variable-to-disable-server-gui.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0732-additions-to-PlayerGameModeChangeEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0733-ItemStack-repair-check-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0734-More-Enchantment-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0738-Fix-and-optimise-world-force-upgrading.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0739-Add-Mob-lookAt-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0740-Add-Unix-domain-socket-support.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0741-Add-EntityInsideBlockEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0742-Attributes-API-for-item-defaults.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0744-Add-cause-to-Weather-ThunderChangeEvents.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0745-More-Lidded-Block-API.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0746-Add-PlayerKickEvent-causes.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0747-Limit-item-frame-cursors-on-maps.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0748-Add-PufferFishStateChangeEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0750-Add-option-to-fix-items-merging-through-walls.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0751-Add-BellRevealRaiderEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0752-Fix-invulnerable-end-crystals.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0753-Add-ElderGuardianAppearanceEvent.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0755-Fix-dangerous-end-portal-logic.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0756-Make-item-validations-configurable.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0757-Add-more-line-of-sight-methods.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0758-add-per-world-spawn-limits.patch (100%) rename {Spigot-Server-Patches => Unmapped-Spigot-Server-Patches}/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch (100%) diff --git a/Spigot-API-Patches/0001-POM-changes.patch b/Unmapped-Spigot-API-Patches/0001-POM-changes.patch similarity index 100% rename from Spigot-API-Patches/0001-POM-changes.patch rename to Unmapped-Spigot-API-Patches/0001-POM-changes.patch diff --git a/Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch b/Unmapped-Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch similarity index 100% rename from Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch rename to Unmapped-Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch diff --git a/Spigot-API-Patches/0003-Paper-Utils.patch b/Unmapped-Spigot-API-Patches/0003-Paper-Utils.patch similarity index 100% rename from Spigot-API-Patches/0003-Paper-Utils.patch rename to Unmapped-Spigot-API-Patches/0003-Paper-Utils.patch diff --git a/Spigot-API-Patches/0004-Timings-v2.patch b/Unmapped-Spigot-API-Patches/0004-Timings-v2.patch similarity index 100% rename from Spigot-API-Patches/0004-Timings-v2.patch rename to Unmapped-Spigot-API-Patches/0004-Timings-v2.patch diff --git a/Spigot-API-Patches/0005-Adventure.patch b/Unmapped-Spigot-API-Patches/0005-Adventure.patch similarity index 100% rename from Spigot-API-Patches/0005-Adventure.patch rename to Unmapped-Spigot-API-Patches/0005-Adventure.patch diff --git a/Spigot-API-Patches/0006-Player-affects-spawning-API.patch b/Unmapped-Spigot-API-Patches/0006-Player-affects-spawning-API.patch similarity index 100% rename from Spigot-API-Patches/0006-Player-affects-spawning-API.patch rename to Unmapped-Spigot-API-Patches/0006-Player-affects-spawning-API.patch diff --git a/Spigot-API-Patches/0007-Add-getTPS-method.patch b/Unmapped-Spigot-API-Patches/0007-Add-getTPS-method.patch similarity index 100% rename from Spigot-API-Patches/0007-Add-getTPS-method.patch rename to Unmapped-Spigot-API-Patches/0007-Add-getTPS-method.patch diff --git a/Spigot-API-Patches/0008-Entity-Origin-API.patch b/Unmapped-Spigot-API-Patches/0008-Entity-Origin-API.patch similarity index 100% rename from Spigot-API-Patches/0008-Entity-Origin-API.patch rename to Unmapped-Spigot-API-Patches/0008-Entity-Origin-API.patch diff --git a/Spigot-API-Patches/0009-Version-Command-2.0.patch b/Unmapped-Spigot-API-Patches/0009-Version-Command-2.0.patch similarity index 100% rename from Spigot-API-Patches/0009-Version-Command-2.0.patch rename to Unmapped-Spigot-API-Patches/0009-Version-Command-2.0.patch diff --git a/Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch b/Unmapped-Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch diff --git a/Spigot-API-Patches/0011-Add-player-view-distance-API.patch b/Unmapped-Spigot-API-Patches/0011-Add-player-view-distance-API.patch similarity index 100% rename from Spigot-API-Patches/0011-Add-player-view-distance-API.patch rename to Unmapped-Spigot-API-Patches/0011-Add-player-view-distance-API.patch diff --git a/Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch b/Unmapped-Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch similarity index 100% rename from Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch rename to Unmapped-Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch diff --git a/Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch b/Unmapped-Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch similarity index 100% rename from Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch rename to Unmapped-Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch diff --git a/Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch b/Unmapped-Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch similarity index 100% rename from Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch rename to Unmapped-Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch diff --git a/Spigot-API-Patches/0015-Expose-server-CommandMap.patch b/Unmapped-Spigot-API-Patches/0015-Expose-server-CommandMap.patch similarity index 100% rename from Spigot-API-Patches/0015-Expose-server-CommandMap.patch rename to Unmapped-Spigot-API-Patches/0015-Expose-server-CommandMap.patch diff --git a/Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch b/Unmapped-Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch similarity index 100% rename from Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch rename to Unmapped-Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch diff --git a/Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch b/Unmapped-Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch similarity index 100% rename from Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch rename to Unmapped-Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch diff --git a/Spigot-API-Patches/0018-Add-exception-reporting-event.patch b/Unmapped-Spigot-API-Patches/0018-Add-exception-reporting-event.patch similarity index 100% rename from Spigot-API-Patches/0018-Add-exception-reporting-event.patch rename to Unmapped-Spigot-API-Patches/0018-Add-exception-reporting-event.patch diff --git a/Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch b/Unmapped-Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch similarity index 100% rename from Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch rename to Unmapped-Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch diff --git a/Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch b/Unmapped-Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch similarity index 100% rename from Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch rename to Unmapped-Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch diff --git a/Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Unmapped-Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch similarity index 100% rename from Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch rename to Unmapped-Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch diff --git a/Spigot-API-Patches/0022-Complete-resource-pack-API.patch b/Unmapped-Spigot-API-Patches/0022-Complete-resource-pack-API.patch similarity index 100% rename from Spigot-API-Patches/0022-Complete-resource-pack-API.patch rename to Unmapped-Spigot-API-Patches/0022-Complete-resource-pack-API.patch diff --git a/Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch b/Unmapped-Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch similarity index 100% rename from Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch rename to Unmapped-Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch diff --git a/Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch b/Unmapped-Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch similarity index 100% rename from Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch rename to Unmapped-Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch diff --git a/Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch b/Unmapped-Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch similarity index 100% rename from Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch rename to Unmapped-Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch diff --git a/Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch b/Unmapped-Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch similarity index 100% rename from Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch rename to Unmapped-Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch diff --git a/Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch b/Unmapped-Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch similarity index 100% rename from Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch rename to Unmapped-Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch diff --git a/Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch b/Unmapped-Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch similarity index 100% rename from Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch rename to Unmapped-Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch diff --git a/Spigot-API-Patches/0029-EntityPathfindEvent.patch b/Unmapped-Spigot-API-Patches/0029-EntityPathfindEvent.patch similarity index 100% rename from Spigot-API-Patches/0029-EntityPathfindEvent.patch rename to Unmapped-Spigot-API-Patches/0029-EntityPathfindEvent.patch diff --git a/Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch b/Unmapped-Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch similarity index 100% rename from Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch rename to Unmapped-Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch diff --git a/Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch b/Unmapped-Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch similarity index 100% rename from Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch rename to Unmapped-Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch diff --git a/Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch b/Unmapped-Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch similarity index 100% rename from Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch rename to Unmapped-Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch diff --git a/Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Unmapped-Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch similarity index 100% rename from Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch rename to Unmapped-Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch diff --git a/Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch b/Unmapped-Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch similarity index 100% rename from Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch rename to Unmapped-Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch diff --git a/Spigot-API-Patches/0035-EntityRegainHealthEvent-isFastRegen-API.patch b/Unmapped-Spigot-API-Patches/0035-EntityRegainHealthEvent-isFastRegen-API.patch similarity index 100% rename from Spigot-API-Patches/0035-EntityRegainHealthEvent-isFastRegen-API.patch rename to Unmapped-Spigot-API-Patches/0035-EntityRegainHealthEvent-isFastRegen-API.patch diff --git a/Spigot-API-Patches/0036-LootTable-API.patch b/Unmapped-Spigot-API-Patches/0036-LootTable-API.patch similarity index 100% rename from Spigot-API-Patches/0036-LootTable-API.patch rename to Unmapped-Spigot-API-Patches/0036-LootTable-API.patch diff --git a/Spigot-API-Patches/0037-Add-EntityZapEvent.patch b/Unmapped-Spigot-API-Patches/0037-Add-EntityZapEvent.patch similarity index 100% rename from Spigot-API-Patches/0037-Add-EntityZapEvent.patch rename to Unmapped-Spigot-API-Patches/0037-Add-EntityZapEvent.patch diff --git a/Spigot-API-Patches/0038-Misc-Utils.patch b/Unmapped-Spigot-API-Patches/0038-Misc-Utils.patch similarity index 100% rename from Spigot-API-Patches/0038-Misc-Utils.patch rename to Unmapped-Spigot-API-Patches/0038-Misc-Utils.patch diff --git a/Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch b/Unmapped-Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch similarity index 100% rename from Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch rename to Unmapped-Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch diff --git a/Spigot-API-Patches/0040-Add-source-to-PlayerExpChangeEvent.patch b/Unmapped-Spigot-API-Patches/0040-Add-source-to-PlayerExpChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/0040-Add-source-to-PlayerExpChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0040-Add-source-to-PlayerExpChangeEvent.patch diff --git a/Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch b/Unmapped-Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch similarity index 100% rename from Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch rename to Unmapped-Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch diff --git a/Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch b/Unmapped-Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch similarity index 100% rename from Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch rename to Unmapped-Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch diff --git a/Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch b/Unmapped-Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch similarity index 100% rename from Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch rename to Unmapped-Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch diff --git a/Spigot-API-Patches/0044-IllegalPacketEvent.patch b/Unmapped-Spigot-API-Patches/0044-IllegalPacketEvent.patch similarity index 100% rename from Spigot-API-Patches/0044-IllegalPacketEvent.patch rename to Unmapped-Spigot-API-Patches/0044-IllegalPacketEvent.patch diff --git a/Spigot-API-Patches/0045-Fireworks-API-s.patch b/Unmapped-Spigot-API-Patches/0045-Fireworks-API-s.patch similarity index 100% rename from Spigot-API-Patches/0045-Fireworks-API-s.patch rename to Unmapped-Spigot-API-Patches/0045-Fireworks-API-s.patch diff --git a/Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch b/Unmapped-Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch similarity index 100% rename from Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch rename to Unmapped-Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch diff --git a/Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch b/Unmapped-Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch similarity index 100% rename from Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch rename to Unmapped-Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch diff --git a/Spigot-API-Patches/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/Unmapped-Spigot-API-Patches/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch similarity index 100% rename from Spigot-API-Patches/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch rename to Unmapped-Spigot-API-Patches/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch diff --git a/Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch b/Unmapped-Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch similarity index 100% rename from Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch rename to Unmapped-Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch diff --git a/Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch b/Unmapped-Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch similarity index 100% rename from Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch rename to Unmapped-Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch diff --git a/Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch b/Unmapped-Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch similarity index 100% rename from Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch rename to Unmapped-Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch diff --git a/Spigot-API-Patches/0052-Item-canEntityPickup.patch b/Unmapped-Spigot-API-Patches/0052-Item-canEntityPickup.patch similarity index 100% rename from Spigot-API-Patches/0052-Item-canEntityPickup.patch rename to Unmapped-Spigot-API-Patches/0052-Item-canEntityPickup.patch diff --git a/Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch b/Unmapped-Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch similarity index 100% rename from Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch rename to Unmapped-Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch diff --git a/Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch b/Unmapped-Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch similarity index 100% rename from Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch rename to Unmapped-Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch diff --git a/Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch b/Unmapped-Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch similarity index 100% rename from Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch rename to Unmapped-Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch diff --git a/Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch b/Unmapped-Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch similarity index 100% rename from Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch rename to Unmapped-Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch diff --git a/Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch b/Unmapped-Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch similarity index 100% rename from Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch rename to Unmapped-Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch diff --git a/Spigot-API-Patches/0058-Profile-Lookup-Events.patch b/Unmapped-Spigot-API-Patches/0058-Profile-Lookup-Events.patch similarity index 100% rename from Spigot-API-Patches/0058-Profile-Lookup-Events.patch rename to Unmapped-Spigot-API-Patches/0058-Profile-Lookup-Events.patch diff --git a/Spigot-API-Patches/0059-Entity-fromMobSpawner.patch b/Unmapped-Spigot-API-Patches/0059-Entity-fromMobSpawner.patch similarity index 100% rename from Spigot-API-Patches/0059-Entity-fromMobSpawner.patch rename to Unmapped-Spigot-API-Patches/0059-Entity-fromMobSpawner.patch diff --git a/Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch b/Unmapped-Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch similarity index 100% rename from Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch rename to Unmapped-Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch diff --git a/Spigot-API-Patches/0061-ensureServerConversions-API.patch b/Unmapped-Spigot-API-Patches/0061-ensureServerConversions-API.patch similarity index 100% rename from Spigot-API-Patches/0061-ensureServerConversions-API.patch rename to Unmapped-Spigot-API-Patches/0061-ensureServerConversions-API.patch diff --git a/Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch b/Unmapped-Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch similarity index 100% rename from Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch rename to Unmapped-Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch diff --git a/Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch b/Unmapped-Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch similarity index 100% rename from Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch rename to Unmapped-Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch diff --git a/Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch b/Unmapped-Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch similarity index 100% rename from Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch rename to Unmapped-Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch diff --git a/Spigot-API-Patches/0065-LivingEntity-setKiller.patch b/Unmapped-Spigot-API-Patches/0065-LivingEntity-setKiller.patch similarity index 100% rename from Spigot-API-Patches/0065-LivingEntity-setKiller.patch rename to Unmapped-Spigot-API-Patches/0065-LivingEntity-setKiller.patch diff --git a/Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch b/Unmapped-Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch similarity index 100% rename from Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch rename to Unmapped-Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch diff --git a/Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch b/Unmapped-Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch similarity index 100% rename from Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch rename to Unmapped-Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch diff --git a/Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/Unmapped-Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch similarity index 100% rename from Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch rename to Unmapped-Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch diff --git a/Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch b/Unmapped-Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch similarity index 100% rename from Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch rename to Unmapped-Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch diff --git a/Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch b/Unmapped-Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch similarity index 100% rename from Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch rename to Unmapped-Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch diff --git a/Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch b/Unmapped-Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch diff --git a/Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch b/Unmapped-Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch similarity index 100% rename from Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch rename to Unmapped-Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch diff --git a/Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch b/Unmapped-Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch similarity index 100% rename from Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch rename to Unmapped-Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch diff --git a/Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch b/Unmapped-Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch similarity index 100% rename from Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch rename to Unmapped-Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch diff --git a/Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch b/Unmapped-Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch similarity index 100% rename from Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch rename to Unmapped-Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch diff --git a/Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch b/Unmapped-Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch similarity index 100% rename from Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch rename to Unmapped-Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch diff --git a/Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch b/Unmapped-Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch similarity index 100% rename from Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch rename to Unmapped-Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch diff --git a/Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch b/Unmapped-Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch similarity index 100% rename from Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch rename to Unmapped-Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch diff --git a/Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch b/Unmapped-Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch similarity index 100% rename from Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch rename to Unmapped-Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch diff --git a/Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch b/Unmapped-Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch similarity index 100% rename from Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch rename to Unmapped-Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch diff --git a/Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch b/Unmapped-Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch similarity index 100% rename from Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch rename to Unmapped-Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch diff --git a/Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch b/Unmapped-Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch similarity index 100% rename from Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch rename to Unmapped-Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch diff --git a/Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch b/Unmapped-Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch similarity index 100% rename from Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch rename to Unmapped-Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch diff --git a/Spigot-API-Patches/0084-Optimize-Hoppers.patch b/Unmapped-Spigot-API-Patches/0084-Optimize-Hoppers.patch similarity index 100% rename from Spigot-API-Patches/0084-Optimize-Hoppers.patch rename to Unmapped-Spigot-API-Patches/0084-Optimize-Hoppers.patch diff --git a/Spigot-API-Patches/0085-Tameable-getOwnerUniqueId-API.patch b/Unmapped-Spigot-API-Patches/0085-Tameable-getOwnerUniqueId-API.patch similarity index 100% rename from Spigot-API-Patches/0085-Tameable-getOwnerUniqueId-API.patch rename to Unmapped-Spigot-API-Patches/0085-Tameable-getOwnerUniqueId-API.patch diff --git a/Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/Unmapped-Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch similarity index 100% rename from Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch rename to Unmapped-Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch diff --git a/Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch b/Unmapped-Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch similarity index 100% rename from Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch rename to Unmapped-Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch diff --git a/Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch b/Unmapped-Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch similarity index 100% rename from Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch rename to Unmapped-Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch diff --git a/Spigot-API-Patches/0089-getPlayerUniqueId-API.patch b/Unmapped-Spigot-API-Patches/0089-getPlayerUniqueId-API.patch similarity index 100% rename from Spigot-API-Patches/0089-getPlayerUniqueId-API.patch rename to Unmapped-Spigot-API-Patches/0089-getPlayerUniqueId-API.patch diff --git a/Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch b/Unmapped-Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch similarity index 100% rename from Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch rename to Unmapped-Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch diff --git a/Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch b/Unmapped-Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch similarity index 100% rename from Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch rename to Unmapped-Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch diff --git a/Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch b/Unmapped-Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch similarity index 100% rename from Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch rename to Unmapped-Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch diff --git a/Spigot-API-Patches/0093-EndermanEscapeEvent.patch b/Unmapped-Spigot-API-Patches/0093-EndermanEscapeEvent.patch similarity index 100% rename from Spigot-API-Patches/0093-EndermanEscapeEvent.patch rename to Unmapped-Spigot-API-Patches/0093-EndermanEscapeEvent.patch diff --git a/Spigot-API-Patches/0094-Enderman.teleportRandomly.patch b/Unmapped-Spigot-API-Patches/0094-Enderman.teleportRandomly.patch similarity index 100% rename from Spigot-API-Patches/0094-Enderman.teleportRandomly.patch rename to Unmapped-Spigot-API-Patches/0094-Enderman.teleportRandomly.patch diff --git a/Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch b/Unmapped-Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch similarity index 100% rename from Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch rename to Unmapped-Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch diff --git a/Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch b/Unmapped-Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch similarity index 100% rename from Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch rename to Unmapped-Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch diff --git a/Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch b/Unmapped-Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch similarity index 100% rename from Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch rename to Unmapped-Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch diff --git a/Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch b/Unmapped-Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch similarity index 100% rename from Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch rename to Unmapped-Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch diff --git a/Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch b/Unmapped-Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch similarity index 100% rename from Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch rename to Unmapped-Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch diff --git a/Spigot-API-Patches/0100-WitchConsumePotionEvent.patch b/Unmapped-Spigot-API-Patches/0100-WitchConsumePotionEvent.patch similarity index 100% rename from Spigot-API-Patches/0100-WitchConsumePotionEvent.patch rename to Unmapped-Spigot-API-Patches/0100-WitchConsumePotionEvent.patch diff --git a/Spigot-API-Patches/0101-WitchThrowPotionEvent.patch b/Unmapped-Spigot-API-Patches/0101-WitchThrowPotionEvent.patch similarity index 100% rename from Spigot-API-Patches/0101-WitchThrowPotionEvent.patch rename to Unmapped-Spigot-API-Patches/0101-WitchThrowPotionEvent.patch diff --git a/Spigot-API-Patches/0102-Location.toBlockLocation-toCenterLocation.patch b/Unmapped-Spigot-API-Patches/0102-Location.toBlockLocation-toCenterLocation.patch similarity index 100% rename from Spigot-API-Patches/0102-Location.toBlockLocation-toCenterLocation.patch rename to Unmapped-Spigot-API-Patches/0102-Location.toBlockLocation-toCenterLocation.patch diff --git a/Spigot-API-Patches/0103-PotionEffect-clone-methods.patch b/Unmapped-Spigot-API-Patches/0103-PotionEffect-clone-methods.patch similarity index 100% rename from Spigot-API-Patches/0103-PotionEffect-clone-methods.patch rename to Unmapped-Spigot-API-Patches/0103-PotionEffect-clone-methods.patch diff --git a/Spigot-API-Patches/0104-WitchReadyPotionEvent.patch b/Unmapped-Spigot-API-Patches/0104-WitchReadyPotionEvent.patch similarity index 100% rename from Spigot-API-Patches/0104-WitchReadyPotionEvent.patch rename to Unmapped-Spigot-API-Patches/0104-WitchReadyPotionEvent.patch diff --git a/Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch b/Unmapped-Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch similarity index 100% rename from Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch rename to Unmapped-Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch diff --git a/Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch b/Unmapped-Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch similarity index 100% rename from Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch rename to Unmapped-Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch diff --git a/Spigot-API-Patches/0107-Make-shield-blocking-delay-configurable.patch b/Unmapped-Spigot-API-Patches/0107-Make-shield-blocking-delay-configurable.patch similarity index 100% rename from Spigot-API-Patches/0107-Make-shield-blocking-delay-configurable.patch rename to Unmapped-Spigot-API-Patches/0107-Make-shield-blocking-delay-configurable.patch diff --git a/Spigot-API-Patches/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch b/Unmapped-Spigot-API-Patches/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch similarity index 100% rename from Spigot-API-Patches/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch rename to Unmapped-Spigot-API-Patches/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch diff --git a/Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch b/Unmapped-Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch similarity index 100% rename from Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch rename to Unmapped-Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch diff --git a/Spigot-API-Patches/0110-PlayerReadyArrowEvent.patch b/Unmapped-Spigot-API-Patches/0110-PlayerReadyArrowEvent.patch similarity index 100% rename from Spigot-API-Patches/0110-PlayerReadyArrowEvent.patch rename to Unmapped-Spigot-API-Patches/0110-PlayerReadyArrowEvent.patch diff --git a/Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch b/Unmapped-Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch similarity index 100% rename from Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch rename to Unmapped-Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch diff --git a/Spigot-API-Patches/0112-Expand-Explosions-API.patch b/Unmapped-Spigot-API-Patches/0112-Expand-Explosions-API.patch similarity index 100% rename from Spigot-API-Patches/0112-Expand-Explosions-API.patch rename to Unmapped-Spigot-API-Patches/0112-Expand-Explosions-API.patch diff --git a/Spigot-API-Patches/0113-ItemStack-API-additions-for-quantity-flags-lore.patch b/Unmapped-Spigot-API-Patches/0113-ItemStack-API-additions-for-quantity-flags-lore.patch similarity index 100% rename from Spigot-API-Patches/0113-ItemStack-API-additions-for-quantity-flags-lore.patch rename to Unmapped-Spigot-API-Patches/0113-ItemStack-API-additions-for-quantity-flags-lore.patch diff --git a/Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch b/Unmapped-Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch similarity index 100% rename from Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch rename to Unmapped-Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch diff --git a/Spigot-API-Patches/0115-RangedEntity-API.patch b/Unmapped-Spigot-API-Patches/0115-RangedEntity-API.patch similarity index 100% rename from Spigot-API-Patches/0115-RangedEntity-API.patch rename to Unmapped-Spigot-API-Patches/0115-RangedEntity-API.patch diff --git a/Spigot-API-Patches/0116-Add-World.getEntity-UUID-API.patch b/Unmapped-Spigot-API-Patches/0116-Add-World.getEntity-UUID-API.patch similarity index 100% rename from Spigot-API-Patches/0116-Add-World.getEntity-UUID-API.patch rename to Unmapped-Spigot-API-Patches/0116-Add-World.getEntity-UUID-API.patch diff --git a/Spigot-API-Patches/0117-InventoryCloseEvent-Reason-API.patch b/Unmapped-Spigot-API-Patches/0117-InventoryCloseEvent-Reason-API.patch similarity index 100% rename from Spigot-API-Patches/0117-InventoryCloseEvent-Reason-API.patch rename to Unmapped-Spigot-API-Patches/0117-InventoryCloseEvent-Reason-API.patch diff --git a/Spigot-API-Patches/0118-Entity-getChunk-API.patch b/Unmapped-Spigot-API-Patches/0118-Entity-getChunk-API.patch similarity index 100% rename from Spigot-API-Patches/0118-Entity-getChunk-API.patch rename to Unmapped-Spigot-API-Patches/0118-Entity-getChunk-API.patch diff --git a/Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch b/Unmapped-Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch similarity index 100% rename from Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch rename to Unmapped-Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch diff --git a/Spigot-API-Patches/0120-EnderDragon-Events.patch b/Unmapped-Spigot-API-Patches/0120-EnderDragon-Events.patch similarity index 100% rename from Spigot-API-Patches/0120-EnderDragon-Events.patch rename to Unmapped-Spigot-API-Patches/0120-EnderDragon-Events.patch diff --git a/Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch b/Unmapped-Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch similarity index 100% rename from Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch rename to Unmapped-Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch diff --git a/Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch b/Unmapped-Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch similarity index 100% rename from Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch rename to Unmapped-Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch diff --git a/Spigot-API-Patches/0123-EntityTransformedEvent.patch b/Unmapped-Spigot-API-Patches/0123-EntityTransformedEvent.patch similarity index 100% rename from Spigot-API-Patches/0123-EntityTransformedEvent.patch rename to Unmapped-Spigot-API-Patches/0123-EntityTransformedEvent.patch diff --git a/Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch b/Unmapped-Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch similarity index 100% rename from Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch rename to Unmapped-Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch diff --git a/Spigot-API-Patches/0125-SkeletonHorse-Additions.patch b/Unmapped-Spigot-API-Patches/0125-SkeletonHorse-Additions.patch similarity index 100% rename from Spigot-API-Patches/0125-SkeletonHorse-Additions.patch rename to Unmapped-Spigot-API-Patches/0125-SkeletonHorse-Additions.patch diff --git a/Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch b/Unmapped-Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch similarity index 100% rename from Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch rename to Unmapped-Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch diff --git a/Spigot-API-Patches/0127-Expand-ArmorStand-API.patch b/Unmapped-Spigot-API-Patches/0127-Expand-ArmorStand-API.patch similarity index 100% rename from Spigot-API-Patches/0127-Expand-ArmorStand-API.patch rename to Unmapped-Spigot-API-Patches/0127-Expand-ArmorStand-API.patch diff --git a/Spigot-API-Patches/0128-AnvilDamageEvent.patch b/Unmapped-Spigot-API-Patches/0128-AnvilDamageEvent.patch similarity index 100% rename from Spigot-API-Patches/0128-AnvilDamageEvent.patch rename to Unmapped-Spigot-API-Patches/0128-AnvilDamageEvent.patch diff --git a/Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch b/Unmapped-Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch similarity index 100% rename from Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch rename to Unmapped-Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch diff --git a/Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch b/Unmapped-Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch similarity index 100% rename from Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch rename to Unmapped-Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch diff --git a/Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch b/Unmapped-Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch similarity index 100% rename from Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch rename to Unmapped-Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch diff --git a/Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch b/Unmapped-Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch similarity index 100% rename from Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch rename to Unmapped-Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch diff --git a/Spigot-API-Patches/0133-Async-Chunks-API.patch b/Unmapped-Spigot-API-Patches/0133-Async-Chunks-API.patch similarity index 100% rename from Spigot-API-Patches/0133-Async-Chunks-API.patch rename to Unmapped-Spigot-API-Patches/0133-Async-Chunks-API.patch diff --git a/Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch b/Unmapped-Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch similarity index 100% rename from Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch rename to Unmapped-Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch diff --git a/Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/Unmapped-Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch similarity index 100% rename from Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch rename to Unmapped-Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch diff --git a/Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch b/Unmapped-Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch similarity index 100% rename from Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch rename to Unmapped-Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch diff --git a/Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch b/Unmapped-Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch similarity index 100% rename from Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch rename to Unmapped-Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch diff --git a/Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch b/Unmapped-Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch similarity index 100% rename from Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch rename to Unmapped-Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch diff --git a/Spigot-API-Patches/0139-isChunkGenerated-API.patch b/Unmapped-Spigot-API-Patches/0139-isChunkGenerated-API.patch similarity index 100% rename from Spigot-API-Patches/0139-isChunkGenerated-API.patch rename to Unmapped-Spigot-API-Patches/0139-isChunkGenerated-API.patch diff --git a/Spigot-API-Patches/0140-Add-More-Creeper-API.patch b/Unmapped-Spigot-API-Patches/0140-Add-More-Creeper-API.patch similarity index 100% rename from Spigot-API-Patches/0140-Add-More-Creeper-API.patch rename to Unmapped-Spigot-API-Patches/0140-Add-More-Creeper-API.patch diff --git a/Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch b/Unmapped-Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch similarity index 100% rename from Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch rename to Unmapped-Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch diff --git a/Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch b/Unmapped-Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch similarity index 100% rename from Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch rename to Unmapped-Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch diff --git a/Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch b/Unmapped-Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch similarity index 100% rename from Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch rename to Unmapped-Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch diff --git a/Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch b/Unmapped-Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch similarity index 100% rename from Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch rename to Unmapped-Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch diff --git a/Spigot-API-Patches/0145-Improve-death-events.patch b/Unmapped-Spigot-API-Patches/0145-Improve-death-events.patch similarity index 100% rename from Spigot-API-Patches/0145-Improve-death-events.patch rename to Unmapped-Spigot-API-Patches/0145-Improve-death-events.patch diff --git a/Spigot-API-Patches/0146-Mob-Pathfinding-API.patch b/Unmapped-Spigot-API-Patches/0146-Mob-Pathfinding-API.patch similarity index 100% rename from Spigot-API-Patches/0146-Mob-Pathfinding-API.patch rename to Unmapped-Spigot-API-Patches/0146-Mob-Pathfinding-API.patch diff --git a/Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch b/Unmapped-Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch similarity index 100% rename from Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch rename to Unmapped-Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch diff --git a/Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/Unmapped-Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch similarity index 100% rename from Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch rename to Unmapped-Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch diff --git a/Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch b/Unmapped-Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch similarity index 100% rename from Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch rename to Unmapped-Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch diff --git a/Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch b/Unmapped-Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch similarity index 100% rename from Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch rename to Unmapped-Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch diff --git a/Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch b/Unmapped-Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch similarity index 100% rename from Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch rename to Unmapped-Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch diff --git a/Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch b/Unmapped-Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch similarity index 100% rename from Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch rename to Unmapped-Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch diff --git a/Spigot-API-Patches/0153-Material-API-additions.patch b/Unmapped-Spigot-API-Patches/0153-Material-API-additions.patch similarity index 100% rename from Spigot-API-Patches/0153-Material-API-additions.patch rename to Unmapped-Spigot-API-Patches/0153-Material-API-additions.patch diff --git a/Spigot-API-Patches/0154-Add-Material-Tags.patch b/Unmapped-Spigot-API-Patches/0154-Add-Material-Tags.patch similarity index 100% rename from Spigot-API-Patches/0154-Add-Material-Tags.patch rename to Unmapped-Spigot-API-Patches/0154-Add-Material-Tags.patch diff --git a/Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch b/Unmapped-Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch similarity index 100% rename from Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch rename to Unmapped-Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch diff --git a/Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch b/Unmapped-Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch similarity index 100% rename from Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch rename to Unmapped-Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch diff --git a/Spigot-API-Patches/0157-Add-sun-related-API.patch b/Unmapped-Spigot-API-Patches/0157-Add-sun-related-API.patch similarity index 100% rename from Spigot-API-Patches/0157-Add-sun-related-API.patch rename to Unmapped-Spigot-API-Patches/0157-Add-sun-related-API.patch diff --git a/Spigot-API-Patches/0158-Here-s-Johnny.patch b/Unmapped-Spigot-API-Patches/0158-Here-s-Johnny.patch similarity index 100% rename from Spigot-API-Patches/0158-Here-s-Johnny.patch rename to Unmapped-Spigot-API-Patches/0158-Here-s-Johnny.patch diff --git a/Spigot-API-Patches/0159-Turtle-API.patch b/Unmapped-Spigot-API-Patches/0159-Turtle-API.patch similarity index 100% rename from Spigot-API-Patches/0159-Turtle-API.patch rename to Unmapped-Spigot-API-Patches/0159-Turtle-API.patch diff --git a/Spigot-API-Patches/0160-Add-spectator-target-events.patch b/Unmapped-Spigot-API-Patches/0160-Add-spectator-target-events.patch similarity index 100% rename from Spigot-API-Patches/0160-Add-spectator-target-events.patch rename to Unmapped-Spigot-API-Patches/0160-Add-spectator-target-events.patch diff --git a/Spigot-API-Patches/0161-Add-more-Witch-API.patch b/Unmapped-Spigot-API-Patches/0161-Add-more-Witch-API.patch similarity index 100% rename from Spigot-API-Patches/0161-Add-more-Witch-API.patch rename to Unmapped-Spigot-API-Patches/0161-Add-more-Witch-API.patch diff --git a/Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch b/Unmapped-Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch similarity index 100% rename from Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch rename to Unmapped-Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch diff --git a/Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch b/Unmapped-Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch similarity index 100% rename from Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch rename to Unmapped-Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch diff --git a/Spigot-API-Patches/0164-Add-more-Zombie-API.patch b/Unmapped-Spigot-API-Patches/0164-Add-more-Zombie-API.patch similarity index 100% rename from Spigot-API-Patches/0164-Add-more-Zombie-API.patch rename to Unmapped-Spigot-API-Patches/0164-Add-more-Zombie-API.patch diff --git a/Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch b/Unmapped-Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch similarity index 100% rename from Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch rename to Unmapped-Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch diff --git a/Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch b/Unmapped-Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch similarity index 100% rename from Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch rename to Unmapped-Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch diff --git a/Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/Unmapped-Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 100% rename from Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to Unmapped-Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch diff --git a/Spigot-API-Patches/0168-BlockDestroyEvent.patch b/Unmapped-Spigot-API-Patches/0168-BlockDestroyEvent.patch similarity index 100% rename from Spigot-API-Patches/0168-BlockDestroyEvent.patch rename to Unmapped-Spigot-API-Patches/0168-BlockDestroyEvent.patch diff --git a/Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch b/Unmapped-Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch similarity index 100% rename from Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch rename to Unmapped-Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch diff --git a/Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch b/Unmapped-Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch similarity index 100% rename from Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch rename to Unmapped-Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch diff --git a/Spigot-API-Patches/0171-Annotation-Test-changes.patch b/Unmapped-Spigot-API-Patches/0171-Annotation-Test-changes.patch similarity index 100% rename from Spigot-API-Patches/0171-Annotation-Test-changes.patch rename to Unmapped-Spigot-API-Patches/0171-Annotation-Test-changes.patch diff --git a/Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch b/Unmapped-Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch similarity index 100% rename from Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch rename to Unmapped-Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch diff --git a/Spigot-API-Patches/0173-Add-GS4-Query-event.patch b/Unmapped-Spigot-API-Patches/0173-Add-GS4-Query-event.patch similarity index 100% rename from Spigot-API-Patches/0173-Add-GS4-Query-event.patch rename to Unmapped-Spigot-API-Patches/0173-Add-GS4-Query-event.patch diff --git a/Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch b/Unmapped-Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch similarity index 100% rename from Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch rename to Unmapped-Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch diff --git a/Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch b/Unmapped-Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch similarity index 100% rename from Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch rename to Unmapped-Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch diff --git a/Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch b/Unmapped-Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch similarity index 100% rename from Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch rename to Unmapped-Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch diff --git a/Spigot-API-Patches/0177-Server-Tick-Events.patch b/Unmapped-Spigot-API-Patches/0177-Server-Tick-Events.patch similarity index 100% rename from Spigot-API-Patches/0177-Server-Tick-Events.patch rename to Unmapped-Spigot-API-Patches/0177-Server-Tick-Events.patch diff --git a/Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch b/Unmapped-Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch similarity index 100% rename from Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch rename to Unmapped-Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch diff --git a/Spigot-API-Patches/0179-Add-Heightmap-API.patch b/Unmapped-Spigot-API-Patches/0179-Add-Heightmap-API.patch similarity index 100% rename from Spigot-API-Patches/0179-Add-Heightmap-API.patch rename to Unmapped-Spigot-API-Patches/0179-Add-Heightmap-API.patch diff --git a/Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch b/Unmapped-Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch similarity index 100% rename from Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch rename to Unmapped-Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch diff --git a/Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch b/Unmapped-Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch similarity index 100% rename from Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch rename to Unmapped-Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch diff --git a/Spigot-API-Patches/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch b/Unmapped-Spigot-API-Patches/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch similarity index 100% rename from Spigot-API-Patches/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch rename to Unmapped-Spigot-API-Patches/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch diff --git a/Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch b/Unmapped-Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch similarity index 100% rename from Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch rename to Unmapped-Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch diff --git a/Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch b/Unmapped-Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch similarity index 100% rename from Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch rename to Unmapped-Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch diff --git a/Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch b/Unmapped-Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch similarity index 100% rename from Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch rename to Unmapped-Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch diff --git a/Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch b/Unmapped-Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch similarity index 100% rename from Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch rename to Unmapped-Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch diff --git a/Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch b/Unmapped-Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch similarity index 100% rename from Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch rename to Unmapped-Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch diff --git a/Spigot-API-Patches/0188-Entity-Jump-API.patch b/Unmapped-Spigot-API-Patches/0188-Entity-Jump-API.patch similarity index 100% rename from Spigot-API-Patches/0188-Entity-Jump-API.patch rename to Unmapped-Spigot-API-Patches/0188-Entity-Jump-API.patch diff --git a/Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch b/Unmapped-Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch rename to Unmapped-Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/Spigot-API-Patches/0190-Add-tick-times-API.patch b/Unmapped-Spigot-API-Patches/0190-Add-tick-times-API.patch similarity index 100% rename from Spigot-API-Patches/0190-Add-tick-times-API.patch rename to Unmapped-Spigot-API-Patches/0190-Add-tick-times-API.patch diff --git a/Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch b/Unmapped-Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch similarity index 100% rename from Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch rename to Unmapped-Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch diff --git a/Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch b/Unmapped-Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch similarity index 100% rename from Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch rename to Unmapped-Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch diff --git a/Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch b/Unmapped-Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch similarity index 100% rename from Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch rename to Unmapped-Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch diff --git a/Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch b/Unmapped-Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch similarity index 100% rename from Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch rename to Unmapped-Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch diff --git a/Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch b/Unmapped-Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch rename to Unmapped-Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch b/Unmapped-Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch similarity index 100% rename from Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch rename to Unmapped-Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch diff --git a/Spigot-API-Patches/0197-Villager-Restocks-API.patch b/Unmapped-Spigot-API-Patches/0197-Villager-Restocks-API.patch similarity index 100% rename from Spigot-API-Patches/0197-Villager-Restocks-API.patch rename to Unmapped-Spigot-API-Patches/0197-Villager-Restocks-API.patch diff --git a/Spigot-API-Patches/0198-Expose-game-version.patch b/Unmapped-Spigot-API-Patches/0198-Expose-game-version.patch similarity index 100% rename from Spigot-API-Patches/0198-Expose-game-version.patch rename to Unmapped-Spigot-API-Patches/0198-Expose-game-version.patch diff --git a/Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch b/Unmapped-Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch similarity index 100% rename from Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch rename to Unmapped-Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch diff --git a/Spigot-API-Patches/0200-Add-Mob-Goal-API.patch b/Unmapped-Spigot-API-Patches/0200-Add-Mob-Goal-API.patch similarity index 100% rename from Spigot-API-Patches/0200-Add-Mob-Goal-API.patch rename to Unmapped-Spigot-API-Patches/0200-Add-Mob-Goal-API.patch diff --git a/Spigot-API-Patches/0201-World-view-distance-api.patch b/Unmapped-Spigot-API-Patches/0201-World-view-distance-api.patch similarity index 100% rename from Spigot-API-Patches/0201-World-view-distance-api.patch rename to Unmapped-Spigot-API-Patches/0201-World-view-distance-api.patch diff --git a/Spigot-API-Patches/0202-Add-villager-reputation-API.patch b/Unmapped-Spigot-API-Patches/0202-Add-villager-reputation-API.patch similarity index 100% rename from Spigot-API-Patches/0202-Add-villager-reputation-API.patch rename to Unmapped-Spigot-API-Patches/0202-Add-villager-reputation-API.patch diff --git a/Spigot-API-Patches/0203-Spawn-Reason-API.patch b/Unmapped-Spigot-API-Patches/0203-Spawn-Reason-API.patch similarity index 100% rename from Spigot-API-Patches/0203-Spawn-Reason-API.patch rename to Unmapped-Spigot-API-Patches/0203-Spawn-Reason-API.patch diff --git a/Spigot-API-Patches/0204-Potential-bed-API.patch b/Unmapped-Spigot-API-Patches/0204-Potential-bed-API.patch similarity index 100% rename from Spigot-API-Patches/0204-Potential-bed-API.patch rename to Unmapped-Spigot-API-Patches/0204-Potential-bed-API.patch diff --git a/Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch b/Unmapped-Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch similarity index 100% rename from Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch rename to Unmapped-Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch diff --git a/Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch b/Unmapped-Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 100% rename from Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch rename to Unmapped-Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch diff --git a/Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch b/Unmapped-Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch similarity index 100% rename from Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch rename to Unmapped-Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch diff --git a/Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch b/Unmapped-Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch similarity index 100% rename from Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch rename to Unmapped-Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch diff --git a/Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch b/Unmapped-Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch similarity index 100% rename from Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch rename to Unmapped-Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch diff --git a/Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch b/Unmapped-Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch similarity index 100% rename from Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch rename to Unmapped-Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch diff --git a/Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch b/Unmapped-Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch similarity index 100% rename from Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch rename to Unmapped-Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch diff --git a/Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch b/Unmapped-Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch similarity index 100% rename from Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch rename to Unmapped-Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch diff --git a/Spigot-API-Patches/0213-Add-entity-liquid-API.patch b/Unmapped-Spigot-API-Patches/0213-Add-entity-liquid-API.patch similarity index 100% rename from Spigot-API-Patches/0213-Add-entity-liquid-API.patch rename to Unmapped-Spigot-API-Patches/0213-Add-entity-liquid-API.patch diff --git a/Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch b/Unmapped-Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch similarity index 100% rename from Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch rename to Unmapped-Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch diff --git a/Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch b/Unmapped-Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 100% rename from Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch rename to Unmapped-Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch diff --git a/Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch b/Unmapped-Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch similarity index 100% rename from Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch rename to Unmapped-Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch diff --git a/Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch b/Unmapped-Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch similarity index 100% rename from Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch rename to Unmapped-Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch diff --git a/Spigot-API-Patches/0218-Add-moon-phase-API.patch b/Unmapped-Spigot-API-Patches/0218-Add-moon-phase-API.patch similarity index 100% rename from Spigot-API-Patches/0218-Add-moon-phase-API.patch rename to Unmapped-Spigot-API-Patches/0218-Add-moon-phase-API.patch diff --git a/Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch b/Unmapped-Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch rename to Unmapped-Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/Spigot-API-Patches/0220-Add-BellRingEvent.patch b/Unmapped-Spigot-API-Patches/0220-Add-BellRingEvent.patch similarity index 100% rename from Spigot-API-Patches/0220-Add-BellRingEvent.patch rename to Unmapped-Spigot-API-Patches/0220-Add-BellRingEvent.patch diff --git a/Spigot-API-Patches/0221-Brand-support.patch b/Unmapped-Spigot-API-Patches/0221-Brand-support.patch similarity index 100% rename from Spigot-API-Patches/0221-Brand-support.patch rename to Unmapped-Spigot-API-Patches/0221-Brand-support.patch diff --git a/Spigot-API-Patches/0222-Add-more-Evoker-API.patch b/Unmapped-Spigot-API-Patches/0222-Add-more-Evoker-API.patch similarity index 100% rename from Spigot-API-Patches/0222-Add-more-Evoker-API.patch rename to Unmapped-Spigot-API-Patches/0222-Add-more-Evoker-API.patch diff --git a/Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/Unmapped-Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 100% rename from Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to Unmapped-Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch diff --git a/Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch b/Unmapped-Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 100% rename from Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch rename to Unmapped-Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch diff --git a/Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch b/Unmapped-Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch similarity index 100% rename from Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch rename to Unmapped-Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch diff --git a/Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/Unmapped-Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 100% rename from Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to Unmapped-Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch diff --git a/Spigot-API-Patches/0227-Entity-isTicking.patch b/Unmapped-Spigot-API-Patches/0227-Entity-isTicking.patch similarity index 100% rename from Spigot-API-Patches/0227-Entity-isTicking.patch rename to Unmapped-Spigot-API-Patches/0227-Entity-isTicking.patch diff --git a/Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch b/Unmapped-Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch similarity index 100% rename from Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch rename to Unmapped-Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch diff --git a/Spigot-API-Patches/0229-Villager-resetOffers.patch b/Unmapped-Spigot-API-Patches/0229-Villager-resetOffers.patch similarity index 100% rename from Spigot-API-Patches/0229-Villager-resetOffers.patch rename to Unmapped-Spigot-API-Patches/0229-Villager-resetOffers.patch diff --git a/Spigot-API-Patches/0230-Player-elytra-boost-API.patch b/Unmapped-Spigot-API-Patches/0230-Player-elytra-boost-API.patch similarity index 100% rename from Spigot-API-Patches/0230-Player-elytra-boost-API.patch rename to Unmapped-Spigot-API-Patches/0230-Player-elytra-boost-API.patch diff --git a/Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch b/Unmapped-Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch rename to Unmapped-Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch diff --git a/Spigot-API-Patches/0232-Add-ignore-discounts-API.patch b/Unmapped-Spigot-API-Patches/0232-Add-ignore-discounts-API.patch similarity index 100% rename from Spigot-API-Patches/0232-Add-ignore-discounts-API.patch rename to Unmapped-Spigot-API-Patches/0232-Add-ignore-discounts-API.patch diff --git a/Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch b/Unmapped-Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch similarity index 100% rename from Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch rename to Unmapped-Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch diff --git a/Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch b/Unmapped-Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch rename to Unmapped-Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch diff --git a/Spigot-API-Patches/0235-Add-API-for-quit-reason.patch b/Unmapped-Spigot-API-Patches/0235-Add-API-for-quit-reason.patch similarity index 100% rename from Spigot-API-Patches/0235-Add-API-for-quit-reason.patch rename to Unmapped-Spigot-API-Patches/0235-Add-API-for-quit-reason.patch diff --git a/Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch b/Unmapped-Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch similarity index 100% rename from Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch rename to Unmapped-Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch diff --git a/Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch b/Unmapped-Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch rename to Unmapped-Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch diff --git a/Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch b/Unmapped-Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch rename to Unmapped-Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch diff --git a/Spigot-API-Patches/0239-More-lightning-API.patch b/Unmapped-Spigot-API-Patches/0239-More-lightning-API.patch similarity index 100% rename from Spigot-API-Patches/0239-More-lightning-API.patch rename to Unmapped-Spigot-API-Patches/0239-More-lightning-API.patch diff --git a/Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch b/Unmapped-Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch similarity index 100% rename from Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch rename to Unmapped-Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch diff --git a/Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch b/Unmapped-Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch similarity index 100% rename from Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch rename to Unmapped-Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch diff --git a/Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch b/Unmapped-Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch rename to Unmapped-Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch diff --git a/Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch b/Unmapped-Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch rename to Unmapped-Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch diff --git a/Spigot-API-Patches/0244-Added-PlayerTradeEvent.patch b/Unmapped-Spigot-API-Patches/0244-Added-PlayerTradeEvent.patch similarity index 100% rename from Spigot-API-Patches/0244-Added-PlayerTradeEvent.patch rename to Unmapped-Spigot-API-Patches/0244-Added-PlayerTradeEvent.patch diff --git a/Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/Unmapped-Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to Unmapped-Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch b/Unmapped-Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch similarity index 100% rename from Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch rename to Unmapped-Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch diff --git a/Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch b/Unmapped-Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch similarity index 100% rename from Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch rename to Unmapped-Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch diff --git a/Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch b/Unmapped-Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch similarity index 100% rename from Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch rename to Unmapped-Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch diff --git a/Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch b/Unmapped-Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch rename to Unmapped-Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch diff --git a/Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch b/Unmapped-Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch similarity index 100% rename from Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch rename to Unmapped-Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch diff --git a/Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch b/Unmapped-Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch rename to Unmapped-Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch diff --git a/Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch b/Unmapped-Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch diff --git a/Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch b/Unmapped-Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch rename to Unmapped-Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch diff --git a/Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch b/Unmapped-Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch similarity index 100% rename from Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch rename to Unmapped-Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch diff --git a/Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch b/Unmapped-Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch diff --git a/Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch b/Unmapped-Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch rename to Unmapped-Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch diff --git a/Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch b/Unmapped-Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch similarity index 100% rename from Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch rename to Unmapped-Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch diff --git a/Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch b/Unmapped-Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch similarity index 100% rename from Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch rename to Unmapped-Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch diff --git a/Spigot-API-Patches/0259-Add-sendOpLevel-API.patch b/Unmapped-Spigot-API-Patches/0259-Add-sendOpLevel-API.patch similarity index 100% rename from Spigot-API-Patches/0259-Add-sendOpLevel-API.patch rename to Unmapped-Spigot-API-Patches/0259-Add-sendOpLevel-API.patch diff --git a/Spigot-API-Patches/0260-Add-StructureLocateEvent.patch b/Unmapped-Spigot-API-Patches/0260-Add-StructureLocateEvent.patch similarity index 100% rename from Spigot-API-Patches/0260-Add-StructureLocateEvent.patch rename to Unmapped-Spigot-API-Patches/0260-Add-StructureLocateEvent.patch diff --git a/Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch b/Unmapped-Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch rename to Unmapped-Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch b/Unmapped-Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch similarity index 100% rename from Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch rename to Unmapped-Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch diff --git a/Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch b/Unmapped-Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch rename to Unmapped-Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch diff --git a/Spigot-API-Patches/0264-added-Wither-API.patch b/Unmapped-Spigot-API-Patches/0264-added-Wither-API.patch similarity index 100% rename from Spigot-API-Patches/0264-added-Wither-API.patch rename to Unmapped-Spigot-API-Patches/0264-added-Wither-API.patch diff --git a/Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch b/Unmapped-Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch rename to Unmapped-Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch diff --git a/Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/Unmapped-Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to Unmapped-Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch b/Unmapped-Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch rename to Unmapped-Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/Spigot-API-Patches/0268-EntityMoveEvent.patch b/Unmapped-Spigot-API-Patches/0268-EntityMoveEvent.patch similarity index 100% rename from Spigot-API-Patches/0268-EntityMoveEvent.patch rename to Unmapped-Spigot-API-Patches/0268-EntityMoveEvent.patch diff --git a/Spigot-API-Patches/0269-add-DragonEggFormEvent.patch b/Unmapped-Spigot-API-Patches/0269-add-DragonEggFormEvent.patch similarity index 100% rename from Spigot-API-Patches/0269-add-DragonEggFormEvent.patch rename to Unmapped-Spigot-API-Patches/0269-add-DragonEggFormEvent.patch diff --git a/Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch b/Unmapped-Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch rename to Unmapped-Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/Unmapped-Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to Unmapped-Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/Spigot-API-Patches/0272-living-entity-allow-attribute-registration.patch b/Unmapped-Spigot-API-Patches/0272-living-entity-allow-attribute-registration.patch similarity index 100% rename from Spigot-API-Patches/0272-living-entity-allow-attribute-registration.patch rename to Unmapped-Spigot-API-Patches/0272-living-entity-allow-attribute-registration.patch diff --git a/Spigot-API-Patches/0273-Add-missing-effects.patch b/Unmapped-Spigot-API-Patches/0273-Add-missing-effects.patch similarity index 100% rename from Spigot-API-Patches/0273-Add-missing-effects.patch rename to Unmapped-Spigot-API-Patches/0273-Add-missing-effects.patch diff --git a/Spigot-API-Patches/0274-Expose-Tracked-Players.patch b/Unmapped-Spigot-API-Patches/0274-Expose-Tracked-Players.patch similarity index 100% rename from Spigot-API-Patches/0274-Expose-Tracked-Players.patch rename to Unmapped-Spigot-API-Patches/0274-Expose-Tracked-Players.patch diff --git a/Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch b/Unmapped-Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch similarity index 100% rename from Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch rename to Unmapped-Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch diff --git a/Spigot-API-Patches/0276-Add-worldborder-events.patch b/Unmapped-Spigot-API-Patches/0276-Add-worldborder-events.patch similarity index 100% rename from Spigot-API-Patches/0276-Add-worldborder-events.patch rename to Unmapped-Spigot-API-Patches/0276-Add-worldborder-events.patch diff --git a/Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch b/Unmapped-Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch similarity index 100% rename from Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch rename to Unmapped-Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch diff --git a/Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch b/Unmapped-Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch similarity index 100% rename from Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch rename to Unmapped-Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch diff --git a/Spigot-API-Patches/0279-Add-Block-isValidTool.patch b/Unmapped-Spigot-API-Patches/0279-Add-Block-isValidTool.patch similarity index 100% rename from Spigot-API-Patches/0279-Add-Block-isValidTool.patch rename to Unmapped-Spigot-API-Patches/0279-Add-Block-isValidTool.patch diff --git a/Spigot-API-Patches/0280-Implement-Keyed-on-World.patch b/Unmapped-Spigot-API-Patches/0280-Implement-Keyed-on-World.patch similarity index 100% rename from Spigot-API-Patches/0280-Implement-Keyed-on-World.patch rename to Unmapped-Spigot-API-Patches/0280-Implement-Keyed-on-World.patch diff --git a/Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch b/Unmapped-Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch similarity index 100% rename from Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch rename to Unmapped-Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch diff --git a/Spigot-API-Patches/0282-Item-Rarity-API.patch b/Unmapped-Spigot-API-Patches/0282-Item-Rarity-API.patch similarity index 100% rename from Spigot-API-Patches/0282-Item-Rarity-API.patch rename to Unmapped-Spigot-API-Patches/0282-Item-Rarity-API.patch diff --git a/Spigot-API-Patches/0283-Expose-protocol-version.patch b/Unmapped-Spigot-API-Patches/0283-Expose-protocol-version.patch similarity index 100% rename from Spigot-API-Patches/0283-Expose-protocol-version.patch rename to Unmapped-Spigot-API-Patches/0283-Expose-protocol-version.patch diff --git a/Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch b/Unmapped-Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch rename to Unmapped-Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch diff --git a/Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch b/Unmapped-Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch rename to Unmapped-Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch b/Unmapped-Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch rename to Unmapped-Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch b/Unmapped-Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch rename to Unmapped-Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch diff --git a/Spigot-API-Patches/0288-More-World-API.patch b/Unmapped-Spigot-API-Patches/0288-More-World-API.patch similarity index 100% rename from Spigot-API-Patches/0288-More-World-API.patch rename to Unmapped-Spigot-API-Patches/0288-More-World-API.patch diff --git a/Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch b/Unmapped-Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch rename to Unmapped-Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch diff --git a/Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch b/Unmapped-Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch rename to Unmapped-Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch diff --git a/Spigot-API-Patches/0291-PlayerMoveEvent-Improvements.patch b/Unmapped-Spigot-API-Patches/0291-PlayerMoveEvent-Improvements.patch similarity index 100% rename from Spigot-API-Patches/0291-PlayerMoveEvent-Improvements.patch rename to Unmapped-Spigot-API-Patches/0291-PlayerMoveEvent-Improvements.patch diff --git a/Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch b/Unmapped-Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to Unmapped-Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/Spigot-API-Patches/0293-Add-more-WanderingTrader-API.patch b/Unmapped-Spigot-API-Patches/0293-Add-more-WanderingTrader-API.patch similarity index 100% rename from Spigot-API-Patches/0293-Add-more-WanderingTrader-API.patch rename to Unmapped-Spigot-API-Patches/0293-Add-more-WanderingTrader-API.patch diff --git a/Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/Unmapped-Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 100% rename from Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to Unmapped-Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch diff --git a/Spigot-API-Patches/0295-Add-EntityBlockStorage-clearEntities.patch b/Unmapped-Spigot-API-Patches/0295-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from Spigot-API-Patches/0295-Add-EntityBlockStorage-clearEntities.patch rename to Unmapped-Spigot-API-Patches/0295-Add-EntityBlockStorage-clearEntities.patch diff --git a/Spigot-API-Patches/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/Unmapped-Spigot-API-Patches/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from Spigot-API-Patches/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to Unmapped-Spigot-API-Patches/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/Unmapped-Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to Unmapped-Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/Spigot-API-Patches/0298-Inventory-close.patch b/Unmapped-Spigot-API-Patches/0298-Inventory-close.patch similarity index 100% rename from Spigot-API-Patches/0298-Inventory-close.patch rename to Unmapped-Spigot-API-Patches/0298-Inventory-close.patch diff --git a/Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/Unmapped-Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 100% rename from Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to Unmapped-Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch diff --git a/Spigot-API-Patches/0300-Add-basic-Datapack-API.patch b/Unmapped-Spigot-API-Patches/0300-Add-basic-Datapack-API.patch similarity index 100% rename from Spigot-API-Patches/0300-Add-basic-Datapack-API.patch rename to Unmapped-Spigot-API-Patches/0300-Add-basic-Datapack-API.patch diff --git a/Spigot-API-Patches/0301-additions-to-PlayerGameModeChangeEvent.patch b/Unmapped-Spigot-API-Patches/0301-additions-to-PlayerGameModeChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/0301-additions-to-PlayerGameModeChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0301-additions-to-PlayerGameModeChangeEvent.patch diff --git a/Spigot-API-Patches/0302-ItemStack-repair-check-API.patch b/Unmapped-Spigot-API-Patches/0302-ItemStack-repair-check-API.patch similarity index 100% rename from Spigot-API-Patches/0302-ItemStack-repair-check-API.patch rename to Unmapped-Spigot-API-Patches/0302-ItemStack-repair-check-API.patch diff --git a/Spigot-API-Patches/0303-More-Enchantment-API.patch b/Unmapped-Spigot-API-Patches/0303-More-Enchantment-API.patch similarity index 100% rename from Spigot-API-Patches/0303-More-Enchantment-API.patch rename to Unmapped-Spigot-API-Patches/0303-More-Enchantment-API.patch diff --git a/Spigot-API-Patches/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/Unmapped-Spigot-API-Patches/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 100% rename from Spigot-API-Patches/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to Unmapped-Spigot-API-Patches/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch diff --git a/Spigot-API-Patches/0305-List-all-missing-hard-depends-not-just-first.patch b/Unmapped-Spigot-API-Patches/0305-List-all-missing-hard-depends-not-just-first.patch similarity index 100% rename from Spigot-API-Patches/0305-List-all-missing-hard-depends-not-just-first.patch rename to Unmapped-Spigot-API-Patches/0305-List-all-missing-hard-depends-not-just-first.patch diff --git a/Spigot-API-Patches/0306-Add-Mob-lookAt-API.patch b/Unmapped-Spigot-API-Patches/0306-Add-Mob-lookAt-API.patch similarity index 100% rename from Spigot-API-Patches/0306-Add-Mob-lookAt-API.patch rename to Unmapped-Spigot-API-Patches/0306-Add-Mob-lookAt-API.patch diff --git a/Spigot-API-Patches/0307-ItemStack-editMeta.patch b/Unmapped-Spigot-API-Patches/0307-ItemStack-editMeta.patch similarity index 100% rename from Spigot-API-Patches/0307-ItemStack-editMeta.patch rename to Unmapped-Spigot-API-Patches/0307-ItemStack-editMeta.patch diff --git a/Spigot-API-Patches/0308-Add-EntityInsideBlockEvent.patch b/Unmapped-Spigot-API-Patches/0308-Add-EntityInsideBlockEvent.patch similarity index 100% rename from Spigot-API-Patches/0308-Add-EntityInsideBlockEvent.patch rename to Unmapped-Spigot-API-Patches/0308-Add-EntityInsideBlockEvent.patch diff --git a/Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch b/Unmapped-Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch similarity index 100% rename from Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch rename to Unmapped-Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch diff --git a/Spigot-API-Patches/0310-Add-cause-to-Weather-ThunderChangeEvents.patch b/Unmapped-Spigot-API-Patches/0310-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from Spigot-API-Patches/0310-Add-cause-to-Weather-ThunderChangeEvents.patch rename to Unmapped-Spigot-API-Patches/0310-Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/Spigot-API-Patches/0311-More-Lidded-Block-API.patch b/Unmapped-Spigot-API-Patches/0311-More-Lidded-Block-API.patch similarity index 100% rename from Spigot-API-Patches/0311-More-Lidded-Block-API.patch rename to Unmapped-Spigot-API-Patches/0311-More-Lidded-Block-API.patch diff --git a/Spigot-API-Patches/0312-Add-PlayerKickEvent-causes.patch b/Unmapped-Spigot-API-Patches/0312-Add-PlayerKickEvent-causes.patch similarity index 100% rename from Spigot-API-Patches/0312-Add-PlayerKickEvent-causes.patch rename to Unmapped-Spigot-API-Patches/0312-Add-PlayerKickEvent-causes.patch diff --git a/Spigot-API-Patches/0313-Add-PufferFishStateChangeEvent.patch b/Unmapped-Spigot-API-Patches/0313-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/0313-Add-PufferFishStateChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0313-Add-PufferFishStateChangeEvent.patch diff --git a/Spigot-API-Patches/0314-Add-BellRevealRaiderEvent.patch b/Unmapped-Spigot-API-Patches/0314-Add-BellRevealRaiderEvent.patch similarity index 100% rename from Spigot-API-Patches/0314-Add-BellRevealRaiderEvent.patch rename to Unmapped-Spigot-API-Patches/0314-Add-BellRevealRaiderEvent.patch diff --git a/Spigot-API-Patches/0315-Add-ElderGuardianAppearanceEvent.patch b/Unmapped-Spigot-API-Patches/0315-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from Spigot-API-Patches/0315-Add-ElderGuardianAppearanceEvent.patch rename to Unmapped-Spigot-API-Patches/0315-Add-ElderGuardianAppearanceEvent.patch diff --git a/Spigot-API-Patches/0316-Add-more-line-of-sight-methods.patch b/Unmapped-Spigot-API-Patches/0316-Add-more-line-of-sight-methods.patch similarity index 100% rename from Spigot-API-Patches/0316-Add-more-line-of-sight-methods.patch rename to Unmapped-Spigot-API-Patches/0316-Add-more-line-of-sight-methods.patch diff --git a/Spigot-Server-Patches/0001-POM-Changes.patch b/Unmapped-Spigot-Server-Patches/0001-POM-Changes.patch similarity index 100% rename from Spigot-Server-Patches/0001-POM-Changes.patch rename to Unmapped-Spigot-Server-Patches/0001-POM-Changes.patch diff --git a/Spigot-Server-Patches/0002-Paper-config-files.patch b/Unmapped-Spigot-Server-Patches/0002-Paper-config-files.patch similarity index 100% rename from Spigot-Server-Patches/0002-Paper-config-files.patch rename to Unmapped-Spigot-Server-Patches/0002-Paper-config-files.patch diff --git a/Spigot-Server-Patches/0003-MC-Dev-fixes.patch b/Unmapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch similarity index 100% rename from Spigot-Server-Patches/0003-MC-Dev-fixes.patch rename to Unmapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch diff --git a/Spigot-Server-Patches/0004-MC-Utils.patch b/Unmapped-Spigot-Server-Patches/0004-MC-Utils.patch similarity index 100% rename from Spigot-Server-Patches/0004-MC-Utils.patch rename to Unmapped-Spigot-Server-Patches/0004-MC-Utils.patch diff --git a/Spigot-Server-Patches/0005-Paper-Metrics.patch b/Unmapped-Spigot-Server-Patches/0005-Paper-Metrics.patch similarity index 100% rename from Spigot-Server-Patches/0005-Paper-Metrics.patch rename to Unmapped-Spigot-Server-Patches/0005-Paper-Metrics.patch diff --git a/Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch b/Unmapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch similarity index 100% rename from Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch rename to Unmapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch diff --git a/Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch b/Unmapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch similarity index 100% rename from Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch rename to Unmapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch diff --git a/Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch b/Unmapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch similarity index 100% rename from Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch rename to Unmapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch diff --git a/Spigot-Server-Patches/0009-Timings-v2.patch b/Unmapped-Spigot-Server-Patches/0009-Timings-v2.patch similarity index 100% rename from Spigot-Server-Patches/0009-Timings-v2.patch rename to Unmapped-Spigot-Server-Patches/0009-Timings-v2.patch diff --git a/Spigot-Server-Patches/0010-Adventure.patch b/Unmapped-Spigot-Server-Patches/0010-Adventure.patch similarity index 100% rename from Spigot-Server-Patches/0010-Adventure.patch rename to Unmapped-Spigot-Server-Patches/0010-Adventure.patch diff --git a/Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch b/Unmapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch similarity index 100% rename from Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch rename to Unmapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch diff --git a/Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch b/Unmapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch similarity index 100% rename from Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch rename to Unmapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch diff --git a/Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch b/Unmapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch similarity index 100% rename from Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch rename to Unmapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch diff --git a/Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/Unmapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch similarity index 100% rename from Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch rename to Unmapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch diff --git a/Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch b/Unmapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch similarity index 100% rename from Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch rename to Unmapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch diff --git a/Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch b/Unmapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch rename to Unmapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch diff --git a/Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch b/Unmapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch similarity index 100% rename from Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch rename to Unmapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch diff --git a/Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/Unmapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch similarity index 100% rename from Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch rename to Unmapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch diff --git a/Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch b/Unmapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch similarity index 100% rename from Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch rename to Unmapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch diff --git a/Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch b/Unmapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch similarity index 100% rename from Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch rename to Unmapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch diff --git a/Spigot-Server-Patches/0021-Player-affects-spawning-API.patch b/Unmapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch similarity index 100% rename from Spigot-Server-Patches/0021-Player-affects-spawning-API.patch rename to Unmapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch diff --git a/Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch b/Unmapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch similarity index 100% rename from Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch rename to Unmapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch diff --git a/Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch b/Unmapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch similarity index 100% rename from Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch rename to Unmapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch diff --git a/Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch b/Unmapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch similarity index 100% rename from Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch rename to Unmapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch diff --git a/Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch b/Unmapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch similarity index 100% rename from Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch rename to Unmapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch diff --git a/Spigot-Server-Patches/0026-Entity-Origin-API.patch b/Unmapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch similarity index 100% rename from Spigot-Server-Patches/0026-Entity-Origin-API.patch rename to Unmapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch diff --git a/Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch b/Unmapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch similarity index 100% rename from Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch rename to Unmapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch diff --git a/Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch b/Unmapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch similarity index 100% rename from Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch rename to Unmapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch diff --git a/Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch b/Unmapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch similarity index 100% rename from Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch rename to Unmapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch diff --git a/Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch b/Unmapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch similarity index 100% rename from Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch rename to Unmapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch diff --git a/Spigot-Server-Patches/0031-Configurable-end-credits.patch b/Unmapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch similarity index 100% rename from Spigot-Server-Patches/0031-Configurable-end-credits.patch rename to Unmapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch diff --git a/Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch b/Unmapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch similarity index 100% rename from Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch rename to Unmapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch diff --git a/Spigot-Server-Patches/0033-Optimize-explosions.patch b/Unmapped-Spigot-Server-Patches/0033-Optimize-explosions.patch similarity index 100% rename from Spigot-Server-Patches/0033-Optimize-explosions.patch rename to Unmapped-Spigot-Server-Patches/0033-Optimize-explosions.patch diff --git a/Spigot-Server-Patches/0034-Disable-explosion-knockback.patch b/Unmapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch similarity index 100% rename from Spigot-Server-Patches/0034-Disable-explosion-knockback.patch rename to Unmapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch diff --git a/Spigot-Server-Patches/0035-Disable-thunder.patch b/Unmapped-Spigot-Server-Patches/0035-Disable-thunder.patch similarity index 100% rename from Spigot-Server-Patches/0035-Disable-thunder.patch rename to Unmapped-Spigot-Server-Patches/0035-Disable-thunder.patch diff --git a/Spigot-Server-Patches/0036-Disable-ice-and-snow.patch b/Unmapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch similarity index 100% rename from Spigot-Server-Patches/0036-Disable-ice-and-snow.patch rename to Unmapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch diff --git a/Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch b/Unmapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch similarity index 100% rename from Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch rename to Unmapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch diff --git a/Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch b/Unmapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch similarity index 100% rename from Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch rename to Unmapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch diff --git a/Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch b/Unmapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch similarity index 100% rename from Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch rename to Unmapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch diff --git a/Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch b/Unmapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch similarity index 100% rename from Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch rename to Unmapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch diff --git a/Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch b/Unmapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch similarity index 100% rename from Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch rename to Unmapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch diff --git a/Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch b/Unmapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch similarity index 100% rename from Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch rename to Unmapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch diff --git a/Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch b/Unmapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch similarity index 100% rename from Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch rename to Unmapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch diff --git a/Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch b/Unmapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch similarity index 100% rename from Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch rename to Unmapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch diff --git a/Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch b/Unmapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch similarity index 100% rename from Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch rename to Unmapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch diff --git a/Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch b/Unmapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch similarity index 100% rename from Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch rename to Unmapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch diff --git a/Spigot-Server-Patches/0047-Expose-server-CommandMap.patch b/Unmapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch similarity index 100% rename from Spigot-Server-Patches/0047-Expose-server-CommandMap.patch rename to Unmapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch diff --git a/Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch b/Unmapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch similarity index 100% rename from Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch rename to Unmapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch diff --git a/Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch b/Unmapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch similarity index 100% rename from Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch rename to Unmapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch diff --git a/Spigot-Server-Patches/0050-Ensure-inv-drag-is-in-bounds.patch b/Unmapped-Spigot-Server-Patches/0050-Ensure-inv-drag-is-in-bounds.patch similarity index 100% rename from Spigot-Server-Patches/0050-Ensure-inv-drag-is-in-bounds.patch rename to Unmapped-Spigot-Server-Patches/0050-Ensure-inv-drag-is-in-bounds.patch diff --git a/Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch b/Unmapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch similarity index 100% rename from Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch rename to Unmapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch diff --git a/Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch b/Unmapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch similarity index 100% rename from Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch rename to Unmapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch diff --git a/Spigot-Server-Patches/0053-Add-velocity-warnings.patch b/Unmapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch similarity index 100% rename from Spigot-Server-Patches/0053-Add-velocity-warnings.patch rename to Unmapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch diff --git a/Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch b/Unmapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch similarity index 100% rename from Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch rename to Unmapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch diff --git a/Spigot-Server-Patches/0055-Add-exception-reporting-event.patch b/Unmapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch similarity index 100% rename from Spigot-Server-Patches/0055-Add-exception-reporting-event.patch rename to Unmapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch diff --git a/Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/Unmapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch similarity index 100% rename from Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch rename to Unmapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch diff --git a/Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch b/Unmapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch similarity index 100% rename from Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch rename to Unmapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch diff --git a/Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Unmapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch similarity index 100% rename from Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch rename to Unmapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch diff --git a/Spigot-Server-Patches/0059-Complete-resource-pack-API.patch b/Unmapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch similarity index 100% rename from Spigot-Server-Patches/0059-Complete-resource-pack-API.patch rename to Unmapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch diff --git a/Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch b/Unmapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch similarity index 100% rename from Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch rename to Unmapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch diff --git a/Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch b/Unmapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch similarity index 100% rename from Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch rename to Unmapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch diff --git a/Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch b/Unmapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch similarity index 100% rename from Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch rename to Unmapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch diff --git a/Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch b/Unmapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch similarity index 100% rename from Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch rename to Unmapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch diff --git a/Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch b/Unmapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch similarity index 100% rename from Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch rename to Unmapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch diff --git a/Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/Unmapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch similarity index 100% rename from Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch rename to Unmapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch diff --git a/Spigot-Server-Patches/0066-Add-World-Util-Methods.patch b/Unmapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch similarity index 100% rename from Spigot-Server-Patches/0066-Add-World-Util-Methods.patch rename to Unmapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch diff --git a/Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch b/Unmapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch similarity index 100% rename from Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch rename to Unmapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch diff --git a/Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/Unmapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch similarity index 100% rename from Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch rename to Unmapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch diff --git a/Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch b/Unmapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch similarity index 100% rename from Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch rename to Unmapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch diff --git a/Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch b/Unmapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch similarity index 100% rename from Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch rename to Unmapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch diff --git a/Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/Unmapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch similarity index 100% rename from Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch rename to Unmapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch diff --git a/Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/Unmapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch similarity index 100% rename from Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch rename to Unmapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch diff --git a/Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch b/Unmapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch similarity index 100% rename from Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch rename to Unmapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch diff --git a/Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch b/Unmapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch similarity index 100% rename from Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch rename to Unmapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch diff --git a/Spigot-Server-Patches/0075-EntityPathfindEvent.patch b/Unmapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch similarity index 100% rename from Spigot-Server-Patches/0075-EntityPathfindEvent.patch rename to Unmapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch diff --git a/Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch b/Unmapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch similarity index 100% rename from Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch rename to Unmapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch diff --git a/Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch b/Unmapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch similarity index 100% rename from Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch rename to Unmapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch diff --git a/Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch b/Unmapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch similarity index 100% rename from Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch rename to Unmapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch diff --git a/Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch b/Unmapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch similarity index 100% rename from Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch rename to Unmapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch diff --git a/Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch b/Unmapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch similarity index 100% rename from Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch rename to Unmapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch diff --git a/Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/Unmapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch similarity index 100% rename from Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch rename to Unmapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch diff --git a/Spigot-Server-Patches/0082-Optimize-DataBits.patch b/Unmapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch similarity index 100% rename from Spigot-Server-Patches/0082-Optimize-DataBits.patch rename to Unmapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch diff --git a/Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/Unmapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch similarity index 100% rename from Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch rename to Unmapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch diff --git a/Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch b/Unmapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch similarity index 100% rename from Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch rename to Unmapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch diff --git a/Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch b/Unmapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch similarity index 100% rename from Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch rename to Unmapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch diff --git a/Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch b/Unmapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch similarity index 100% rename from Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch rename to Unmapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch diff --git a/Spigot-Server-Patches/0087-Configurable-Player-Collision.patch b/Unmapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch similarity index 100% rename from Spigot-Server-Patches/0087-Configurable-Player-Collision.patch rename to Unmapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch diff --git a/Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Unmapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch similarity index 100% rename from Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch rename to Unmapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch diff --git a/Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch b/Unmapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch similarity index 100% rename from Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch rename to Unmapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch diff --git a/Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch b/Unmapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch similarity index 100% rename from Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch rename to Unmapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch diff --git a/Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch similarity index 100% rename from Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch rename to Unmapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch diff --git a/Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch b/Unmapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch similarity index 100% rename from Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch rename to Unmapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch diff --git a/Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch b/Unmapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch similarity index 100% rename from Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch rename to Unmapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch diff --git a/Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch b/Unmapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch similarity index 100% rename from Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch rename to Unmapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch diff --git a/Spigot-Server-Patches/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch b/Unmapped-Spigot-Server-Patches/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch similarity index 100% rename from Spigot-Server-Patches/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch rename to Unmapped-Spigot-Server-Patches/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch diff --git a/Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch b/Unmapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch similarity index 100% rename from Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch rename to Unmapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch diff --git a/Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/Unmapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch similarity index 100% rename from Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch rename to Unmapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch diff --git a/Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch b/Unmapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch similarity index 100% rename from Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch rename to Unmapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch diff --git a/Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch b/Unmapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch similarity index 100% rename from Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch rename to Unmapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch diff --git a/Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch b/Unmapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch similarity index 100% rename from Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch rename to Unmapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch diff --git a/Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch b/Unmapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch similarity index 100% rename from Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch rename to Unmapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch diff --git a/Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch b/Unmapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch similarity index 100% rename from Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch rename to Unmapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch diff --git a/Spigot-Server-Patches/0103-Add-server-name-parameter.patch b/Unmapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch similarity index 100% rename from Spigot-Server-Patches/0103-Add-server-name-parameter.patch rename to Unmapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch diff --git a/Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/Unmapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch similarity index 100% rename from Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch rename to Unmapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch diff --git a/Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch b/Unmapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch similarity index 100% rename from Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch rename to Unmapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch diff --git a/Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch b/Unmapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch similarity index 100% rename from Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch rename to Unmapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch diff --git a/Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/Unmapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch similarity index 100% rename from Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch rename to Unmapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch diff --git a/Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch b/Unmapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch similarity index 100% rename from Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch rename to Unmapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch diff --git a/Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch b/Unmapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch similarity index 100% rename from Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch rename to Unmapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch diff --git a/Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch b/Unmapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch similarity index 100% rename from Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch rename to Unmapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch diff --git a/Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch b/Unmapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch similarity index 100% rename from Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch rename to Unmapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch diff --git a/Spigot-Server-Patches/0112-Chunk-registration-fixes.patch b/Unmapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch similarity index 100% rename from Spigot-Server-Patches/0112-Chunk-registration-fixes.patch rename to Unmapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch diff --git a/Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/Unmapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch similarity index 100% rename from Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch rename to Unmapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch diff --git a/Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch b/Unmapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch similarity index 100% rename from Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch rename to Unmapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch diff --git a/Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch b/Unmapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch similarity index 100% rename from Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch rename to Unmapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch diff --git a/Spigot-Server-Patches/0116-Add-EntityZapEvent.patch b/Unmapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch similarity index 100% rename from Spigot-Server-Patches/0116-Add-EntityZapEvent.patch rename to Unmapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch diff --git a/Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/Unmapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch similarity index 100% rename from Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch rename to Unmapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch diff --git a/Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch b/Unmapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch similarity index 100% rename from Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch rename to Unmapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch diff --git a/Spigot-Server-Patches/0119-Optimise-removeQueue.patch b/Unmapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch similarity index 100% rename from Spigot-Server-Patches/0119-Optimise-removeQueue.patch rename to Unmapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch diff --git a/Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch b/Unmapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch similarity index 100% rename from Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch rename to Unmapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch diff --git a/Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch similarity index 100% rename from Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch rename to Unmapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch diff --git a/Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch b/Unmapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch similarity index 100% rename from Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch rename to Unmapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch diff --git a/Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch b/Unmapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch similarity index 100% rename from Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch rename to Unmapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch diff --git a/Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch b/Unmapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch similarity index 100% rename from Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch rename to Unmapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch diff --git a/Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch b/Unmapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch similarity index 100% rename from Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch rename to Unmapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch diff --git a/Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch b/Unmapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch similarity index 100% rename from Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch rename to Unmapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch diff --git a/Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch b/Unmapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch similarity index 100% rename from Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch rename to Unmapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch diff --git a/Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch b/Unmapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch similarity index 100% rename from Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch rename to Unmapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch diff --git a/Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch b/Unmapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch similarity index 100% rename from Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch rename to Unmapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch diff --git a/Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch b/Unmapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch similarity index 100% rename from Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch rename to Unmapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch diff --git a/Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch b/Unmapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch similarity index 100% rename from Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch rename to Unmapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch diff --git a/Spigot-Server-Patches/0132-Firework-API-s.patch b/Unmapped-Spigot-Server-Patches/0132-Firework-API-s.patch similarity index 100% rename from Spigot-Server-Patches/0132-Firework-API-s.patch rename to Unmapped-Spigot-Server-Patches/0132-Firework-API-s.patch diff --git a/Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch b/Unmapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch similarity index 100% rename from Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch rename to Unmapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch diff --git a/Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch b/Unmapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch similarity index 100% rename from Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch rename to Unmapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch diff --git a/Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch b/Unmapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch similarity index 100% rename from Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch rename to Unmapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch diff --git a/Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch b/Unmapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch similarity index 100% rename from Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch rename to Unmapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch diff --git a/Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/Unmapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch similarity index 100% rename from Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch rename to Unmapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch diff --git a/Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch b/Unmapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch similarity index 100% rename from Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch rename to Unmapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch diff --git a/Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch b/Unmapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch similarity index 100% rename from Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch rename to Unmapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch diff --git a/Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/Unmapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch similarity index 100% rename from Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch rename to Unmapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch diff --git a/Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch b/Unmapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch similarity index 100% rename from Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch rename to Unmapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch diff --git a/Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch b/Unmapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch similarity index 100% rename from Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch rename to Unmapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch diff --git a/Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch b/Unmapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch similarity index 100% rename from Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch rename to Unmapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch diff --git a/Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/Unmapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch similarity index 100% rename from Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch rename to Unmapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch diff --git a/Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch b/Unmapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch similarity index 100% rename from Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch rename to Unmapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch diff --git a/Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch b/Unmapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch similarity index 100% rename from Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch rename to Unmapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch diff --git a/Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch b/Unmapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch similarity index 100% rename from Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch rename to Unmapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch diff --git a/Spigot-Server-Patches/0148-Item-canEntityPickup.patch b/Unmapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch similarity index 100% rename from Spigot-Server-Patches/0148-Item-canEntityPickup.patch rename to Unmapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch diff --git a/Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch b/Unmapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch similarity index 100% rename from Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch rename to Unmapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch diff --git a/Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch b/Unmapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch similarity index 100% rename from Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch rename to Unmapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch diff --git a/Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch b/Unmapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch similarity index 100% rename from Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch rename to Unmapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch diff --git a/Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch b/Unmapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch similarity index 100% rename from Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch rename to Unmapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch diff --git a/Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch b/Unmapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch similarity index 100% rename from Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch rename to Unmapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch diff --git a/Spigot-Server-Patches/0154-Profile-Lookup-Events.patch b/Unmapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch similarity index 100% rename from Spigot-Server-Patches/0154-Profile-Lookup-Events.patch rename to Unmapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch diff --git a/Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch b/Unmapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch similarity index 100% rename from Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch rename to Unmapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch diff --git a/Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch b/Unmapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch similarity index 100% rename from Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch rename to Unmapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch diff --git a/Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch b/Unmapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch similarity index 100% rename from Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch rename to Unmapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch diff --git a/Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch b/Unmapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch similarity index 100% rename from Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch rename to Unmapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch diff --git a/Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch b/Unmapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch similarity index 100% rename from Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch rename to Unmapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch diff --git a/Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch b/Unmapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch similarity index 100% rename from Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch rename to Unmapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch diff --git a/Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch b/Unmapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch similarity index 100% rename from Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch rename to Unmapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch diff --git a/Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch b/Unmapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch similarity index 100% rename from Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch rename to Unmapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch diff --git a/Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/Unmapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch similarity index 100% rename from Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch rename to Unmapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch diff --git a/Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/Unmapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch similarity index 100% rename from Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch rename to Unmapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch diff --git a/Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch b/Unmapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch similarity index 100% rename from Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch rename to Unmapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch diff --git a/Spigot-Server-Patches/0166-LivingEntity-setKiller.patch b/Unmapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch similarity index 100% rename from Spigot-Server-Patches/0166-LivingEntity-setKiller.patch rename to Unmapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch diff --git a/Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch b/Unmapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch similarity index 100% rename from Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch rename to Unmapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch diff --git a/Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch b/Unmapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch similarity index 100% rename from Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch rename to Unmapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch diff --git a/Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch b/Unmapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch similarity index 100% rename from Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch rename to Unmapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch diff --git a/Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch b/Unmapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch similarity index 100% rename from Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch rename to Unmapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch diff --git a/Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch b/Unmapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch similarity index 100% rename from Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch rename to Unmapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch diff --git a/Spigot-Server-Patches/0172-revert-serverside-behavior-of-keepalives.patch b/Unmapped-Spigot-Server-Patches/0172-revert-serverside-behavior-of-keepalives.patch similarity index 100% rename from Spigot-Server-Patches/0172-revert-serverside-behavior-of-keepalives.patch rename to Unmapped-Spigot-Server-Patches/0172-revert-serverside-behavior-of-keepalives.patch diff --git a/Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch b/Unmapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch similarity index 100% rename from Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch rename to Unmapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch diff --git a/Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch b/Unmapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch similarity index 100% rename from Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch rename to Unmapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch diff --git a/Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch similarity index 100% rename from Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch rename to Unmapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch diff --git a/Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch b/Unmapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch similarity index 100% rename from Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch rename to Unmapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch diff --git a/Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch b/Unmapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch similarity index 100% rename from Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch rename to Unmapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch diff --git a/Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch b/Unmapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch similarity index 100% rename from Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch rename to Unmapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch diff --git a/Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch b/Unmapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch similarity index 100% rename from Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch rename to Unmapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch diff --git a/Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch b/Unmapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch similarity index 100% rename from Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch rename to Unmapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch diff --git a/Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch b/Unmapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch similarity index 100% rename from Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch rename to Unmapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch diff --git a/Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch b/Unmapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch similarity index 100% rename from Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch rename to Unmapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch diff --git a/Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch b/Unmapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch similarity index 100% rename from Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch rename to Unmapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch diff --git a/Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch b/Unmapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch similarity index 100% rename from Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch rename to Unmapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch diff --git a/Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch b/Unmapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch similarity index 100% rename from Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch rename to Unmapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch diff --git a/Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch b/Unmapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch similarity index 100% rename from Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch rename to Unmapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch diff --git a/Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch b/Unmapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch similarity index 100% rename from Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch rename to Unmapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch diff --git a/Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch b/Unmapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch similarity index 100% rename from Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch rename to Unmapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch diff --git a/Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch b/Unmapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch similarity index 100% rename from Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch rename to Unmapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch diff --git a/Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch b/Unmapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch similarity index 100% rename from Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch rename to Unmapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch diff --git a/Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch b/Unmapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch similarity index 100% rename from Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch rename to Unmapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch diff --git a/Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch b/Unmapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch similarity index 100% rename from Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch rename to Unmapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch diff --git a/Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch b/Unmapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch similarity index 100% rename from Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch rename to Unmapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch diff --git a/Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/Unmapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch rename to Unmapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch diff --git a/Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch b/Unmapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch similarity index 100% rename from Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch rename to Unmapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch diff --git a/Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch b/Unmapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch similarity index 100% rename from Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch rename to Unmapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch diff --git a/Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch b/Unmapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch similarity index 100% rename from Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch rename to Unmapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch diff --git a/Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/Unmapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch similarity index 100% rename from Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch rename to Unmapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch diff --git a/Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch b/Unmapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch similarity index 100% rename from Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch rename to Unmapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch diff --git a/Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch b/Unmapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch similarity index 100% rename from Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch rename to Unmapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch diff --git a/Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch b/Unmapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch similarity index 100% rename from Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch rename to Unmapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch diff --git a/Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch b/Unmapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch similarity index 100% rename from Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch rename to Unmapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch diff --git a/Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch b/Unmapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch similarity index 100% rename from Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch rename to Unmapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch diff --git a/Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch b/Unmapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch similarity index 100% rename from Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch rename to Unmapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch diff --git a/Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch b/Unmapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch similarity index 100% rename from Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch rename to Unmapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch diff --git a/Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch b/Unmapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch similarity index 100% rename from Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch rename to Unmapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch diff --git a/Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch b/Unmapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch similarity index 100% rename from Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch rename to Unmapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch diff --git a/Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/Unmapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch similarity index 100% rename from Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch rename to Unmapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch diff --git a/Spigot-Server-Patches/0209-EndermanEscapeEvent.patch b/Unmapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch similarity index 100% rename from Spigot-Server-Patches/0209-EndermanEscapeEvent.patch rename to Unmapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch diff --git a/Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch b/Unmapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch similarity index 100% rename from Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch rename to Unmapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch diff --git a/Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch b/Unmapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch similarity index 100% rename from Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch rename to Unmapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch diff --git a/Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch b/Unmapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch similarity index 100% rename from Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch rename to Unmapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch diff --git a/Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch b/Unmapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch similarity index 100% rename from Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch rename to Unmapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch diff --git a/Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch b/Unmapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch similarity index 100% rename from Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch rename to Unmapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch diff --git a/Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch b/Unmapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch similarity index 100% rename from Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch rename to Unmapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch diff --git a/Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/Unmapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch similarity index 100% rename from Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch rename to Unmapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch diff --git a/Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch b/Unmapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch similarity index 100% rename from Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch rename to Unmapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch diff --git a/Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch b/Unmapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch similarity index 100% rename from Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch rename to Unmapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch diff --git a/Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch b/Unmapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch similarity index 100% rename from Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch rename to Unmapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch diff --git a/Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/Unmapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch similarity index 100% rename from Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch rename to Unmapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch diff --git a/Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch b/Unmapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch similarity index 100% rename from Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch rename to Unmapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch diff --git a/Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch b/Unmapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch similarity index 100% rename from Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch rename to Unmapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch diff --git a/Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch b/Unmapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch similarity index 100% rename from Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch rename to Unmapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch diff --git a/Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch b/Unmapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch similarity index 100% rename from Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch rename to Unmapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch diff --git a/Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch b/Unmapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch similarity index 100% rename from Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch rename to Unmapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch diff --git a/Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch b/Unmapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch similarity index 100% rename from Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch rename to Unmapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch diff --git a/Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch b/Unmapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch similarity index 100% rename from Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch rename to Unmapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch diff --git a/Spigot-Server-Patches/0228-Expand-Explosions-API.patch b/Unmapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch similarity index 100% rename from Spigot-Server-Patches/0228-Expand-Explosions-API.patch rename to Unmapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch diff --git a/Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch b/Unmapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch similarity index 100% rename from Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch rename to Unmapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch diff --git a/Spigot-Server-Patches/0230-RangedEntity-API.patch b/Unmapped-Spigot-Server-Patches/0230-RangedEntity-API.patch similarity index 100% rename from Spigot-Server-Patches/0230-RangedEntity-API.patch rename to Unmapped-Spigot-Server-Patches/0230-RangedEntity-API.patch diff --git a/Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch b/Unmapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch similarity index 100% rename from Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch rename to Unmapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch diff --git a/Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch b/Unmapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch similarity index 100% rename from Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch rename to Unmapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch diff --git a/Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch b/Unmapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch similarity index 100% rename from Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch rename to Unmapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch diff --git a/Spigot-Server-Patches/0234-Vex-getSummoner-API.patch b/Unmapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch similarity index 100% rename from Spigot-Server-Patches/0234-Vex-getSummoner-API.patch rename to Unmapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch diff --git a/Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/Unmapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch similarity index 100% rename from Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch rename to Unmapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch diff --git a/Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch b/Unmapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch similarity index 100% rename from Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch rename to Unmapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch diff --git a/Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch b/Unmapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch similarity index 100% rename from Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch rename to Unmapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch diff --git a/Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch b/Unmapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch similarity index 100% rename from Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch rename to Unmapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch diff --git a/Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch b/Unmapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch similarity index 100% rename from Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch rename to Unmapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch diff --git a/Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch b/Unmapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch similarity index 100% rename from Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch rename to Unmapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch diff --git a/Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/Unmapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch similarity index 100% rename from Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch rename to Unmapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch diff --git a/Spigot-Server-Patches/0242-EnderDragon-Events.patch b/Unmapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch similarity index 100% rename from Spigot-Server-Patches/0242-EnderDragon-Events.patch rename to Unmapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch diff --git a/Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch b/Unmapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch similarity index 100% rename from Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch rename to Unmapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch diff --git a/Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch b/Unmapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch similarity index 100% rename from Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch rename to Unmapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch diff --git a/Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch b/Unmapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch similarity index 100% rename from Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch rename to Unmapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch diff --git a/Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/Unmapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch similarity index 100% rename from Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch rename to Unmapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch diff --git a/Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch b/Unmapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch similarity index 100% rename from Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch rename to Unmapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch diff --git a/Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch b/Unmapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch similarity index 100% rename from Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch rename to Unmapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch diff --git a/Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch b/Unmapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch similarity index 100% rename from Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch rename to Unmapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch diff --git a/Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch b/Unmapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch similarity index 100% rename from Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch rename to Unmapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch diff --git a/Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch b/Unmapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch rename to Unmapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch diff --git a/Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch b/Unmapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch similarity index 100% rename from Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch rename to Unmapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch diff --git a/Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch b/Unmapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch similarity index 100% rename from Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch rename to Unmapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch diff --git a/Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch b/Unmapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch similarity index 100% rename from Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch rename to Unmapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch diff --git a/Spigot-Server-Patches/0255-AnvilDamageEvent.patch b/Unmapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch similarity index 100% rename from Spigot-Server-Patches/0255-AnvilDamageEvent.patch rename to Unmapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch diff --git a/Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch b/Unmapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch similarity index 100% rename from Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch rename to Unmapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch diff --git a/Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch b/Unmapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch similarity index 100% rename from Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch rename to Unmapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch diff --git a/Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch b/Unmapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch similarity index 100% rename from Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch rename to Unmapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch diff --git a/Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch b/Unmapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch similarity index 100% rename from Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch rename to Unmapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch diff --git a/Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch b/Unmapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch similarity index 100% rename from Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch rename to Unmapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch diff --git a/Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch b/Unmapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch similarity index 100% rename from Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch rename to Unmapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch diff --git a/Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch b/Unmapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch similarity index 100% rename from Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch rename to Unmapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch diff --git a/Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch b/Unmapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch similarity index 100% rename from Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch rename to Unmapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch diff --git a/Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch b/Unmapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch similarity index 100% rename from Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch rename to Unmapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch diff --git a/Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/Unmapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch similarity index 100% rename from Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch rename to Unmapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch diff --git a/Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch b/Unmapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch similarity index 100% rename from Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch rename to Unmapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch diff --git a/Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch b/Unmapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch similarity index 100% rename from Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch rename to Unmapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch diff --git a/Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/Unmapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch similarity index 100% rename from Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch rename to Unmapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch diff --git a/Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch b/Unmapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch similarity index 100% rename from Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch rename to Unmapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch diff --git a/Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch b/Unmapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch similarity index 100% rename from Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch rename to Unmapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch diff --git a/Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch b/Unmapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch similarity index 100% rename from Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch rename to Unmapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch diff --git a/Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch b/Unmapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch similarity index 100% rename from Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch rename to Unmapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch diff --git a/Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch b/Unmapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch similarity index 100% rename from Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch rename to Unmapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch diff --git a/Spigot-Server-Patches/0274-Add-More-Creeper-API.patch b/Unmapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch similarity index 100% rename from Spigot-Server-Patches/0274-Add-More-Creeper-API.patch rename to Unmapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch diff --git a/Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch b/Unmapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch similarity index 100% rename from Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch rename to Unmapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch diff --git a/Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/Unmapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch similarity index 100% rename from Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch rename to Unmapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch diff --git a/Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch b/Unmapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch similarity index 100% rename from Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch rename to Unmapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch diff --git a/Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch b/Unmapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch similarity index 100% rename from Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch rename to Unmapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch diff --git a/Spigot-Server-Patches/0279-Improve-death-events.patch b/Unmapped-Spigot-Server-Patches/0279-Improve-death-events.patch similarity index 100% rename from Spigot-Server-Patches/0279-Improve-death-events.patch rename to Unmapped-Spigot-Server-Patches/0279-Improve-death-events.patch diff --git a/Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch b/Unmapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch similarity index 100% rename from Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch rename to Unmapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch diff --git a/Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch b/Unmapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch similarity index 100% rename from Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch rename to Unmapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch diff --git a/Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch b/Unmapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch similarity index 100% rename from Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch rename to Unmapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch diff --git a/Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/Unmapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch similarity index 100% rename from Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch rename to Unmapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch diff --git a/Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/Unmapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch similarity index 100% rename from Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch rename to Unmapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch diff --git a/Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch b/Unmapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch rename to Unmapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch diff --git a/Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/Unmapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch similarity index 100% rename from Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch rename to Unmapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch diff --git a/Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch b/Unmapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch similarity index 100% rename from Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch rename to Unmapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch diff --git a/Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch b/Unmapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch similarity index 100% rename from Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch rename to Unmapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch diff --git a/Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch b/Unmapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch similarity index 100% rename from Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch rename to Unmapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch diff --git a/Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch b/Unmapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch similarity index 100% rename from Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch rename to Unmapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch diff --git a/Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch b/Unmapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch similarity index 100% rename from Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch rename to Unmapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch diff --git a/Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch b/Unmapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch similarity index 100% rename from Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch rename to Unmapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch diff --git a/Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch b/Unmapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch similarity index 100% rename from Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch rename to Unmapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch diff --git a/Spigot-Server-Patches/0294-Add-sun-related-API.patch b/Unmapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch similarity index 100% rename from Spigot-Server-Patches/0294-Add-sun-related-API.patch rename to Unmapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch diff --git a/Spigot-Server-Patches/0295-Turtle-API.patch b/Unmapped-Spigot-Server-Patches/0295-Turtle-API.patch similarity index 100% rename from Spigot-Server-Patches/0295-Turtle-API.patch rename to Unmapped-Spigot-Server-Patches/0295-Turtle-API.patch diff --git a/Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/Unmapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch similarity index 100% rename from Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch rename to Unmapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch diff --git a/Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch b/Unmapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch similarity index 100% rename from Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch rename to Unmapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch diff --git a/Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch b/Unmapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch similarity index 100% rename from Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch rename to Unmapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch diff --git a/Spigot-Server-Patches/0299-Add-more-Witch-API.patch b/Unmapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch similarity index 100% rename from Spigot-Server-Patches/0299-Add-more-Witch-API.patch rename to Unmapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch diff --git a/Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch b/Unmapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch similarity index 100% rename from Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch rename to Unmapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch diff --git a/Spigot-Server-Patches/0301-Here-s-Johnny.patch b/Unmapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch similarity index 100% rename from Spigot-Server-Patches/0301-Here-s-Johnny.patch rename to Unmapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch diff --git a/Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch b/Unmapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch similarity index 100% rename from Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch rename to Unmapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch diff --git a/Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch b/Unmapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch similarity index 100% rename from Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch rename to Unmapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch diff --git a/Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch b/Unmapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch similarity index 100% rename from Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch rename to Unmapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch diff --git a/Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/Unmapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch similarity index 100% rename from Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch rename to Unmapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch diff --git a/Spigot-Server-Patches/0306-Optimize-World-Time-Updates.patch b/Unmapped-Spigot-Server-Patches/0306-Optimize-World-Time-Updates.patch similarity index 100% rename from Spigot-Server-Patches/0306-Optimize-World-Time-Updates.patch rename to Unmapped-Spigot-Server-Patches/0306-Optimize-World-Time-Updates.patch diff --git a/Spigot-Server-Patches/0307-Restore-custom-InventoryHolder-support.patch b/Unmapped-Spigot-Server-Patches/0307-Restore-custom-InventoryHolder-support.patch similarity index 100% rename from Spigot-Server-Patches/0307-Restore-custom-InventoryHolder-support.patch rename to Unmapped-Spigot-Server-Patches/0307-Restore-custom-InventoryHolder-support.patch diff --git a/Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch b/Unmapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch similarity index 100% rename from Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch rename to Unmapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch diff --git a/Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch b/Unmapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch similarity index 100% rename from Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch rename to Unmapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch diff --git a/Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch b/Unmapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch rename to Unmapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch diff --git a/Spigot-Server-Patches/0311-Book-Size-Limits.patch b/Unmapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch similarity index 100% rename from Spigot-Server-Patches/0311-Book-Size-Limits.patch rename to Unmapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch diff --git a/Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch b/Unmapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch similarity index 100% rename from Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch rename to Unmapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch diff --git a/Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch b/Unmapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch rename to Unmapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch diff --git a/Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch b/Unmapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch similarity index 100% rename from Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch rename to Unmapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch diff --git a/Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch b/Unmapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch similarity index 100% rename from Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch rename to Unmapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch diff --git a/Spigot-Server-Patches/0316-Add-more-Zombie-API.patch b/Unmapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch similarity index 100% rename from Spigot-Server-Patches/0316-Add-more-Zombie-API.patch rename to Unmapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch diff --git a/Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch b/Unmapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch similarity index 100% rename from Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch rename to Unmapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch diff --git a/Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch b/Unmapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch rename to Unmapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch diff --git a/Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/Unmapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 100% rename from Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to Unmapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch diff --git a/Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/Unmapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch similarity index 100% rename from Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch rename to Unmapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch diff --git a/Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/Unmapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch similarity index 100% rename from Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch rename to Unmapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch diff --git a/Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch b/Unmapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch similarity index 100% rename from Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch rename to Unmapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch diff --git a/Spigot-Server-Patches/0323-BlockDestroyEvent.patch b/Unmapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch similarity index 100% rename from Spigot-Server-Patches/0323-BlockDestroyEvent.patch rename to Unmapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch diff --git a/Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/Unmapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch similarity index 100% rename from Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch rename to Unmapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch diff --git a/Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch b/Unmapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch similarity index 100% rename from Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch rename to Unmapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch diff --git a/Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch b/Unmapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch similarity index 100% rename from Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch rename to Unmapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch diff --git a/Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/Unmapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch similarity index 100% rename from Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch rename to Unmapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch diff --git a/Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/Unmapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch similarity index 100% rename from Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch rename to Unmapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch diff --git a/Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch b/Unmapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch rename to Unmapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch diff --git a/Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/Unmapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch similarity index 100% rename from Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch rename to Unmapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch diff --git a/Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/Unmapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch similarity index 100% rename from Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch rename to Unmapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch diff --git a/Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch b/Unmapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch similarity index 100% rename from Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch rename to Unmapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch diff --git a/Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/Unmapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch similarity index 100% rename from Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch rename to Unmapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch diff --git a/Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch b/Unmapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch similarity index 100% rename from Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch rename to Unmapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch diff --git a/Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/Unmapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch similarity index 100% rename from Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch rename to Unmapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch diff --git a/Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch b/Unmapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch similarity index 100% rename from Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch rename to Unmapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch diff --git a/Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch b/Unmapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch similarity index 100% rename from Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch rename to Unmapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch diff --git a/Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch b/Unmapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch similarity index 100% rename from Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch rename to Unmapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch diff --git a/Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/Unmapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch similarity index 100% rename from Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch rename to Unmapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch diff --git a/Spigot-Server-Patches/0340-Server-Tick-Events.patch b/Unmapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch similarity index 100% rename from Spigot-Server-Patches/0340-Server-Tick-Events.patch rename to Unmapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch diff --git a/Spigot-Server-Patches/0341-PlayerDeathEvent-getItemsToKeep.patch b/Unmapped-Spigot-Server-Patches/0341-PlayerDeathEvent-getItemsToKeep.patch similarity index 100% rename from Spigot-Server-Patches/0341-PlayerDeathEvent-getItemsToKeep.patch rename to Unmapped-Spigot-Server-Patches/0341-PlayerDeathEvent-getItemsToKeep.patch diff --git a/Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch b/Unmapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch similarity index 100% rename from Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch rename to Unmapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch diff --git a/Spigot-Server-Patches/0343-Add-Heightmap-API.patch b/Unmapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch similarity index 100% rename from Spigot-Server-Patches/0343-Add-Heightmap-API.patch rename to Unmapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch diff --git a/Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch b/Unmapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch similarity index 100% rename from Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch rename to Unmapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch diff --git a/Spigot-Server-Patches/0345-Per-Player-View-Distance-API-placeholders.patch b/Unmapped-Spigot-Server-Patches/0345-Per-Player-View-Distance-API-placeholders.patch similarity index 100% rename from Spigot-Server-Patches/0345-Per-Player-View-Distance-API-placeholders.patch rename to Unmapped-Spigot-Server-Patches/0345-Per-Player-View-Distance-API-placeholders.patch diff --git a/Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch b/Unmapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch similarity index 100% rename from Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch rename to Unmapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch diff --git a/Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/Unmapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch similarity index 100% rename from Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch rename to Unmapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch diff --git a/Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/Unmapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch similarity index 100% rename from Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch rename to Unmapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch diff --git a/Spigot-Server-Patches/0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch b/Unmapped-Spigot-Server-Patches/0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch rename to Unmapped-Spigot-Server-Patches/0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch diff --git a/Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch b/Unmapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch similarity index 100% rename from Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch rename to Unmapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch diff --git a/Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch b/Unmapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch similarity index 100% rename from Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch rename to Unmapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch diff --git a/Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/Unmapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch similarity index 100% rename from Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch rename to Unmapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch diff --git a/Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch b/Unmapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch similarity index 100% rename from Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch rename to Unmapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch diff --git a/Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch b/Unmapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch similarity index 100% rename from Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch rename to Unmapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch diff --git a/Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch b/Unmapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch similarity index 100% rename from Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch rename to Unmapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch diff --git a/Spigot-Server-Patches/0356-Chunk-debug-command.patch b/Unmapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch similarity index 100% rename from Spigot-Server-Patches/0356-Chunk-debug-command.patch rename to Unmapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch diff --git a/Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch b/Unmapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch similarity index 100% rename from Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch rename to Unmapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch diff --git a/Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch b/Unmapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch similarity index 100% rename from Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch rename to Unmapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch diff --git a/Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch b/Unmapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch similarity index 100% rename from Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch rename to Unmapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch diff --git a/Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch b/Unmapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch similarity index 100% rename from Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch rename to Unmapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch diff --git a/Spigot-Server-Patches/0361-incremental-chunk-saving.patch b/Unmapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch similarity index 100% rename from Spigot-Server-Patches/0361-incremental-chunk-saving.patch rename to Unmapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch diff --git a/Spigot-Server-Patches/0362-Anti-Xray.patch b/Unmapped-Spigot-Server-Patches/0362-Anti-Xray.patch similarity index 100% rename from Spigot-Server-Patches/0362-Anti-Xray.patch rename to Unmapped-Spigot-Server-Patches/0362-Anti-Xray.patch diff --git a/Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/Unmapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch similarity index 100% rename from Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch rename to Unmapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch diff --git a/Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch b/Unmapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch similarity index 100% rename from Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch rename to Unmapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch diff --git a/Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch b/Unmapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch similarity index 100% rename from Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch rename to Unmapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch diff --git a/Spigot-Server-Patches/0366-offset-item-frame-ticking.patch b/Unmapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch similarity index 100% rename from Spigot-Server-Patches/0366-offset-item-frame-ticking.patch rename to Unmapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch diff --git a/Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch b/Unmapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch similarity index 100% rename from Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch rename to Unmapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch diff --git a/Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch b/Unmapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch similarity index 100% rename from Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch rename to Unmapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch diff --git a/Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch b/Unmapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch similarity index 100% rename from Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch rename to Unmapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch diff --git a/Spigot-Server-Patches/0370-Reduce-sync-loads.patch b/Unmapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch similarity index 100% rename from Spigot-Server-Patches/0370-Reduce-sync-loads.patch rename to Unmapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch diff --git a/Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch b/Unmapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch similarity index 100% rename from Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch rename to Unmapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch diff --git a/Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/Unmapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch similarity index 100% rename from Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch rename to Unmapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch diff --git a/Spigot-Server-Patches/0373-Fix-MC-158900.patch b/Unmapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch similarity index 100% rename from Spigot-Server-Patches/0373-Fix-MC-158900.patch rename to Unmapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch diff --git a/Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch b/Unmapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch similarity index 100% rename from Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch rename to Unmapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch diff --git a/Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch b/Unmapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch similarity index 100% rename from Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch rename to Unmapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch diff --git a/Spigot-Server-Patches/0376-Generator-Settings.patch b/Unmapped-Spigot-Server-Patches/0376-Generator-Settings.patch similarity index 100% rename from Spigot-Server-Patches/0376-Generator-Settings.patch rename to Unmapped-Spigot-Server-Patches/0376-Generator-Settings.patch diff --git a/Spigot-Server-Patches/0377-Fix-MC-161754.patch b/Unmapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch similarity index 100% rename from Spigot-Server-Patches/0377-Fix-MC-161754.patch rename to Unmapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch diff --git a/Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch b/Unmapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch similarity index 100% rename from Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch rename to Unmapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch diff --git a/Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/Unmapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch similarity index 100% rename from Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch rename to Unmapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch diff --git a/Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch b/Unmapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch similarity index 100% rename from Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch rename to Unmapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch diff --git a/Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/Unmapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch similarity index 100% rename from Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch rename to Unmapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch diff --git a/Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch b/Unmapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch similarity index 100% rename from Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch rename to Unmapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch diff --git a/Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/Unmapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch similarity index 100% rename from Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch rename to Unmapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch diff --git a/Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch b/Unmapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch similarity index 100% rename from Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch rename to Unmapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch diff --git a/Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch b/Unmapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch similarity index 100% rename from Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch rename to Unmapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch diff --git a/Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/Unmapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch similarity index 100% rename from Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch rename to Unmapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch diff --git a/Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch b/Unmapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch similarity index 100% rename from Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch rename to Unmapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch diff --git a/Spigot-Server-Patches/0388-Optimize-Hoppers.patch b/Unmapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch similarity index 100% rename from Spigot-Server-Patches/0388-Optimize-Hoppers.patch rename to Unmapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch diff --git a/Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch b/Unmapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch similarity index 100% rename from Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch rename to Unmapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch diff --git a/Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch b/Unmapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch similarity index 100% rename from Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch rename to Unmapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch diff --git a/Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/Unmapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch similarity index 100% rename from Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch rename to Unmapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch diff --git a/Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch b/Unmapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch similarity index 100% rename from Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch rename to Unmapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch diff --git a/Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch b/Unmapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch similarity index 100% rename from Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch rename to Unmapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch diff --git a/Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch b/Unmapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch similarity index 100% rename from Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch rename to Unmapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch diff --git a/Spigot-Server-Patches/0395-Lag-compensate-eating.patch b/Unmapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch similarity index 100% rename from Spigot-Server-Patches/0395-Lag-compensate-eating.patch rename to Unmapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch diff --git a/Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch b/Unmapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch similarity index 100% rename from Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch rename to Unmapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch diff --git a/Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch b/Unmapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch similarity index 100% rename from Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch rename to Unmapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch diff --git a/Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch b/Unmapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch similarity index 100% rename from Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch rename to Unmapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch diff --git a/Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch b/Unmapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch similarity index 100% rename from Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch rename to Unmapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch diff --git a/Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch b/Unmapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch similarity index 100% rename from Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch rename to Unmapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch diff --git a/Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch b/Unmapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch similarity index 100% rename from Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch rename to Unmapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch diff --git a/Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/Unmapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch similarity index 100% rename from Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch rename to Unmapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch diff --git a/Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/Unmapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch rename to Unmapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch diff --git a/Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch b/Unmapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch similarity index 100% rename from Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch rename to Unmapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch diff --git a/Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch b/Unmapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch similarity index 100% rename from Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch rename to Unmapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch diff --git a/Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch b/Unmapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch similarity index 100% rename from Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch rename to Unmapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch diff --git a/Spigot-Server-Patches/0407-Entity-Jump-API.patch b/Unmapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch similarity index 100% rename from Spigot-Server-Patches/0407-Entity-Jump-API.patch rename to Unmapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch diff --git a/Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch b/Unmapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch similarity index 100% rename from Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch rename to Unmapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch diff --git a/Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch b/Unmapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch similarity index 100% rename from Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch rename to Unmapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch diff --git a/Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch b/Unmapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch rename to Unmapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch b/Unmapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch similarity index 100% rename from Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch rename to Unmapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch diff --git a/Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch b/Unmapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch similarity index 100% rename from Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch rename to Unmapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch diff --git a/Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/Unmapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch similarity index 100% rename from Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch rename to Unmapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch diff --git a/Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch b/Unmapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch similarity index 100% rename from Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch rename to Unmapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch diff --git a/Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch b/Unmapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch similarity index 100% rename from Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch rename to Unmapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch diff --git a/Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch b/Unmapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch similarity index 100% rename from Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch rename to Unmapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch diff --git a/Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch b/Unmapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch similarity index 100% rename from Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch rename to Unmapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch diff --git a/Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch b/Unmapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch similarity index 100% rename from Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch rename to Unmapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch diff --git a/Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch b/Unmapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch rename to Unmapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch diff --git a/Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/Unmapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch similarity index 100% rename from Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch rename to Unmapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch diff --git a/Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/Unmapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch similarity index 100% rename from Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch rename to Unmapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch diff --git a/Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/Unmapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch similarity index 100% rename from Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch rename to Unmapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch diff --git a/Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch b/Unmapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch rename to Unmapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch diff --git a/Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch b/Unmapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch similarity index 100% rename from Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch rename to Unmapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch diff --git a/Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch b/Unmapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch similarity index 100% rename from Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch rename to Unmapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch diff --git a/Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/Unmapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch similarity index 100% rename from Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch rename to Unmapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch diff --git a/Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch b/Unmapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch similarity index 100% rename from Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch rename to Unmapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch diff --git a/Spigot-Server-Patches/0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/Unmapped-Spigot-Server-Patches/0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch similarity index 100% rename from Spigot-Server-Patches/0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch rename to Unmapped-Spigot-Server-Patches/0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch diff --git a/Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch b/Unmapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch similarity index 100% rename from Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch rename to Unmapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch diff --git a/Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch b/Unmapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch similarity index 100% rename from Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch rename to Unmapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch diff --git a/Spigot-Server-Patches/0431-Expose-MinecraftServer-isRunning.patch b/Unmapped-Spigot-Server-Patches/0431-Expose-MinecraftServer-isRunning.patch similarity index 100% rename from Spigot-Server-Patches/0431-Expose-MinecraftServer-isRunning.patch rename to Unmapped-Spigot-Server-Patches/0431-Expose-MinecraftServer-isRunning.patch diff --git a/Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch b/Unmapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 100% rename from Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch rename to Unmapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch diff --git a/Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch b/Unmapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch similarity index 100% rename from Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch rename to Unmapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch diff --git a/Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch b/Unmapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch similarity index 100% rename from Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch rename to Unmapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch diff --git a/Spigot-Server-Patches/0435-Async-command-map-building.patch b/Unmapped-Spigot-Server-Patches/0435-Async-command-map-building.patch similarity index 100% rename from Spigot-Server-Patches/0435-Async-command-map-building.patch rename to Unmapped-Spigot-Server-Patches/0435-Async-command-map-building.patch diff --git a/Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch b/Unmapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch similarity index 100% rename from Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch rename to Unmapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch diff --git a/Spigot-Server-Patches/0437-Optimize-Pathfinding.patch b/Unmapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch similarity index 100% rename from Spigot-Server-Patches/0437-Optimize-Pathfinding.patch rename to Unmapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch diff --git a/Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch b/Unmapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch similarity index 100% rename from Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch rename to Unmapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch diff --git a/Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch b/Unmapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch similarity index 100% rename from Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch rename to Unmapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch diff --git a/Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch b/Unmapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch similarity index 100% rename from Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch rename to Unmapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch diff --git a/Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch b/Unmapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch similarity index 100% rename from Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch rename to Unmapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch diff --git a/Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch b/Unmapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch similarity index 100% rename from Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch rename to Unmapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch diff --git a/Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch b/Unmapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch similarity index 100% rename from Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch rename to Unmapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch diff --git a/Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch b/Unmapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch similarity index 100% rename from Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch rename to Unmapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch diff --git a/Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch b/Unmapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch similarity index 100% rename from Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch rename to Unmapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch diff --git a/Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch b/Unmapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch similarity index 100% rename from Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch rename to Unmapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch diff --git a/Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch b/Unmapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch similarity index 100% rename from Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch rename to Unmapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch diff --git a/Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/Unmapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch similarity index 100% rename from Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch rename to Unmapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch diff --git a/Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch b/Unmapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch similarity index 100% rename from Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch rename to Unmapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch diff --git a/Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/Unmapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch similarity index 100% rename from Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch rename to Unmapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch diff --git a/Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch b/Unmapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch similarity index 100% rename from Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch rename to Unmapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch diff --git a/Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/Unmapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch similarity index 100% rename from Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch rename to Unmapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch diff --git a/Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch b/Unmapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch rename to Unmapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/Unmapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch similarity index 100% rename from Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch rename to Unmapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch diff --git a/Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch b/Unmapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch similarity index 100% rename from Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch rename to Unmapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch diff --git a/Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch b/Unmapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch similarity index 100% rename from Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch rename to Unmapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch diff --git a/Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/Unmapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch similarity index 100% rename from Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch rename to Unmapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch diff --git a/Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch b/Unmapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch similarity index 100% rename from Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch rename to Unmapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch diff --git a/Spigot-Server-Patches/0459-Villager-Restocks-API.patch b/Unmapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch similarity index 100% rename from Spigot-Server-Patches/0459-Villager-Restocks-API.patch rename to Unmapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch diff --git a/Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch b/Unmapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch similarity index 100% rename from Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch rename to Unmapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch diff --git a/Spigot-Server-Patches/0461-Expose-game-version.patch b/Unmapped-Spigot-Server-Patches/0461-Expose-game-version.patch similarity index 100% rename from Spigot-Server-Patches/0461-Expose-game-version.patch rename to Unmapped-Spigot-Server-Patches/0461-Expose-game-version.patch diff --git a/Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch b/Unmapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch similarity index 100% rename from Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch rename to Unmapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch diff --git a/Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/Unmapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch similarity index 100% rename from Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch rename to Unmapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch diff --git a/Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch b/Unmapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch similarity index 100% rename from Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch rename to Unmapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch diff --git a/Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch b/Unmapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch similarity index 100% rename from Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch rename to Unmapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch diff --git a/Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch b/Unmapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch similarity index 100% rename from Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch rename to Unmapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch diff --git a/Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch b/Unmapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch similarity index 100% rename from Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch rename to Unmapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch diff --git a/Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch b/Unmapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch similarity index 100% rename from Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch rename to Unmapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch diff --git a/Spigot-Server-Patches/0469-Add-villager-reputation-API.patch b/Unmapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch similarity index 100% rename from Spigot-Server-Patches/0469-Add-villager-reputation-API.patch rename to Unmapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch diff --git a/Spigot-Server-Patches/0470-Fix-Light-Command.patch b/Unmapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch similarity index 100% rename from Spigot-Server-Patches/0470-Fix-Light-Command.patch rename to Unmapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch diff --git a/Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch b/Unmapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch similarity index 100% rename from Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch rename to Unmapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch diff --git a/Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch b/Unmapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch similarity index 100% rename from Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch rename to Unmapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch diff --git a/Spigot-Server-Patches/0473-Potential-bed-API.patch b/Unmapped-Spigot-Server-Patches/0473-Potential-bed-API.patch similarity index 100% rename from Spigot-Server-Patches/0473-Potential-bed-API.patch rename to Unmapped-Spigot-Server-Patches/0473-Potential-bed-API.patch diff --git a/Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch b/Unmapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch similarity index 100% rename from Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch rename to Unmapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch diff --git a/Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/Unmapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch similarity index 100% rename from Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch rename to Unmapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch diff --git a/Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/Unmapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch similarity index 100% rename from Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch rename to Unmapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch diff --git a/Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch b/Unmapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch similarity index 100% rename from Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch rename to Unmapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch diff --git a/Spigot-Server-Patches/0478-Reduce-MutableInt-allocations-from-light-engine.patch b/Unmapped-Spigot-Server-Patches/0478-Reduce-MutableInt-allocations-from-light-engine.patch similarity index 100% rename from Spigot-Server-Patches/0478-Reduce-MutableInt-allocations-from-light-engine.patch rename to Unmapped-Spigot-Server-Patches/0478-Reduce-MutableInt-allocations-from-light-engine.patch diff --git a/Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/Unmapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch similarity index 100% rename from Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch rename to Unmapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch diff --git a/Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch b/Unmapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch similarity index 100% rename from Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch rename to Unmapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch diff --git a/Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch b/Unmapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch similarity index 100% rename from Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch rename to Unmapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch diff --git a/Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/Unmapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch similarity index 100% rename from Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch rename to Unmapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch diff --git a/Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch b/Unmapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch similarity index 100% rename from Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch rename to Unmapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch diff --git a/Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/Unmapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch similarity index 100% rename from Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch rename to Unmapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch diff --git a/Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/Unmapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch similarity index 100% rename from Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch rename to Unmapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch diff --git a/Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch b/Unmapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch similarity index 100% rename from Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch rename to Unmapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch diff --git a/Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch b/Unmapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch similarity index 100% rename from Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch rename to Unmapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch diff --git a/Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch b/Unmapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch similarity index 100% rename from Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch rename to Unmapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch diff --git a/Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/Unmapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch similarity index 100% rename from Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch rename to Unmapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch diff --git a/Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch b/Unmapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch similarity index 100% rename from Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch rename to Unmapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch diff --git a/Spigot-Server-Patches/0491-Optimize-Light-Engine.patch b/Unmapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch similarity index 100% rename from Spigot-Server-Patches/0491-Optimize-Light-Engine.patch rename to Unmapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch diff --git a/Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/Unmapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch similarity index 100% rename from Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch rename to Unmapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch diff --git a/Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/Unmapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch similarity index 100% rename from Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch rename to Unmapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch diff --git a/Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch b/Unmapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch similarity index 100% rename from Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch rename to Unmapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch diff --git a/Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/Unmapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch similarity index 100% rename from Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch rename to Unmapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch diff --git a/Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch b/Unmapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch similarity index 100% rename from Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch rename to Unmapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch diff --git a/Spigot-Server-Patches/0497-Fix-sand-duping.patch b/Unmapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch similarity index 100% rename from Spigot-Server-Patches/0497-Fix-sand-duping.patch rename to Unmapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch diff --git a/Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch b/Unmapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch similarity index 100% rename from Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch rename to Unmapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch diff --git a/Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch b/Unmapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch similarity index 100% rename from Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch rename to Unmapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch diff --git a/Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch b/Unmapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch similarity index 100% rename from Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch rename to Unmapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch diff --git a/Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch b/Unmapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch similarity index 100% rename from Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch rename to Unmapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch diff --git a/Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch b/Unmapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch similarity index 100% rename from Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch rename to Unmapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch diff --git a/Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch b/Unmapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch similarity index 100% rename from Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch rename to Unmapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch diff --git a/Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch b/Unmapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch similarity index 100% rename from Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch rename to Unmapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch diff --git a/Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch b/Unmapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch similarity index 100% rename from Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch rename to Unmapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch diff --git a/Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch b/Unmapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch similarity index 100% rename from Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch rename to Unmapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch diff --git a/Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch b/Unmapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch similarity index 100% rename from Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch rename to Unmapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch diff --git a/Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/Unmapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch similarity index 100% rename from Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch rename to Unmapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch diff --git a/Spigot-Server-Patches/0509-Paper-dumpitem-command.patch b/Unmapped-Spigot-Server-Patches/0509-Paper-dumpitem-command.patch similarity index 100% rename from Spigot-Server-Patches/0509-Paper-dumpitem-command.patch rename to Unmapped-Spigot-Server-Patches/0509-Paper-dumpitem-command.patch diff --git a/Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch b/Unmapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch similarity index 100% rename from Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch rename to Unmapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch diff --git a/Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch b/Unmapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch similarity index 100% rename from Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch rename to Unmapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch diff --git a/Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch b/Unmapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch similarity index 100% rename from Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch rename to Unmapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch diff --git a/Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch b/Unmapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch similarity index 100% rename from Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch rename to Unmapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch diff --git a/Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch b/Unmapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch similarity index 100% rename from Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch rename to Unmapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch diff --git a/Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch b/Unmapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch similarity index 100% rename from Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch rename to Unmapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch diff --git a/Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch b/Unmapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch similarity index 100% rename from Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch rename to Unmapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch diff --git a/Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch b/Unmapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch similarity index 100% rename from Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch rename to Unmapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch diff --git a/Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/Unmapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch similarity index 100% rename from Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch rename to Unmapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch diff --git a/Spigot-Server-Patches/0519-Add-entity-liquid-API.patch b/Unmapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch similarity index 100% rename from Spigot-Server-Patches/0519-Add-entity-liquid-API.patch rename to Unmapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch diff --git a/Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch b/Unmapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch similarity index 100% rename from Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch rename to Unmapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch diff --git a/Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch b/Unmapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch similarity index 100% rename from Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch rename to Unmapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch diff --git a/Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch b/Unmapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch similarity index 100% rename from Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch rename to Unmapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch diff --git a/Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch b/Unmapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 100% rename from Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch rename to Unmapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch diff --git a/Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/Unmapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch similarity index 100% rename from Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch rename to Unmapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch diff --git a/Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch b/Unmapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch similarity index 100% rename from Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch rename to Unmapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch diff --git a/Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch b/Unmapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch similarity index 100% rename from Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch rename to Unmapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch diff --git a/Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch b/Unmapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch similarity index 100% rename from Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch rename to Unmapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch diff --git a/Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch b/Unmapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch similarity index 100% rename from Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch rename to Unmapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch diff --git a/Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch b/Unmapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch similarity index 100% rename from Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch rename to Unmapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch diff --git a/Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch b/Unmapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch similarity index 100% rename from Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch rename to Unmapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch diff --git a/Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch b/Unmapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch similarity index 100% rename from Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch rename to Unmapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch diff --git a/Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/Unmapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch similarity index 100% rename from Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch rename to Unmapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch diff --git a/Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/Unmapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch similarity index 100% rename from Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch rename to Unmapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch diff --git a/Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/Unmapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch similarity index 100% rename from Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch rename to Unmapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch diff --git a/Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/Unmapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch similarity index 100% rename from Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch rename to Unmapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch diff --git a/Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch b/Unmapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch similarity index 100% rename from Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch rename to Unmapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch diff --git a/Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/Unmapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch similarity index 100% rename from Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch rename to Unmapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch diff --git a/Spigot-Server-Patches/0538-Incremental-player-saving.patch b/Unmapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch similarity index 100% rename from Spigot-Server-Patches/0538-Incremental-player-saving.patch rename to Unmapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch diff --git a/Spigot-Server-Patches/0539-Import-fastutil-classes.patch b/Unmapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch similarity index 100% rename from Spigot-Server-Patches/0539-Import-fastutil-classes.patch rename to Unmapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch diff --git a/Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch b/Unmapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch similarity index 100% rename from Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch rename to Unmapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch diff --git a/Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch b/Unmapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch similarity index 100% rename from Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch rename to Unmapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch diff --git a/Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch b/Unmapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch similarity index 100% rename from Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch rename to Unmapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch diff --git a/Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/Unmapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch similarity index 100% rename from Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch rename to Unmapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch diff --git a/Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch b/Unmapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch similarity index 100% rename from Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch rename to Unmapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch diff --git a/Spigot-Server-Patches/0545-Brand-support.patch b/Unmapped-Spigot-Server-Patches/0545-Brand-support.patch similarity index 100% rename from Spigot-Server-Patches/0545-Brand-support.patch rename to Unmapped-Spigot-Server-Patches/0545-Brand-support.patch diff --git a/Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch b/Unmapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch similarity index 100% rename from Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch rename to Unmapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch diff --git a/Spigot-Server-Patches/0547-Fix-MC-197271.patch b/Unmapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch similarity index 100% rename from Spigot-Server-Patches/0547-Fix-MC-197271.patch rename to Unmapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch diff --git a/Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch b/Unmapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch similarity index 100% rename from Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch rename to Unmapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch diff --git a/Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch b/Unmapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch similarity index 100% rename from Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch rename to Unmapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch diff --git a/Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch b/Unmapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch rename to Unmapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch b/Unmapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch similarity index 100% rename from Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch rename to Unmapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch diff --git a/Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/Unmapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch similarity index 100% rename from Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch rename to Unmapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch diff --git a/Spigot-Server-Patches/0553-Add-moon-phase-API.patch b/Unmapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch similarity index 100% rename from Spigot-Server-Patches/0553-Add-moon-phase-API.patch rename to Unmapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch diff --git a/Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch b/Unmapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch similarity index 100% rename from Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch rename to Unmapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch diff --git a/Spigot-Server-Patches/0555-Add-BellRingEvent.patch b/Unmapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch similarity index 100% rename from Spigot-Server-Patches/0555-Add-BellRingEvent.patch rename to Unmapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch diff --git a/Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch b/Unmapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch similarity index 100% rename from Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch rename to Unmapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch diff --git a/Spigot-Server-Patches/0557-Buffer-joins-to-world.patch b/Unmapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch similarity index 100% rename from Spigot-Server-Patches/0557-Buffer-joins-to-world.patch rename to Unmapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch diff --git a/Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch b/Unmapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch similarity index 100% rename from Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch rename to Unmapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch diff --git a/Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch b/Unmapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch similarity index 100% rename from Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch rename to Unmapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch diff --git a/Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch b/Unmapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch similarity index 100% rename from Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch rename to Unmapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch diff --git a/Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch b/Unmapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch similarity index 100% rename from Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch rename to Unmapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch diff --git a/Spigot-Server-Patches/0562-Add-more-Evoker-API.patch b/Unmapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch similarity index 100% rename from Spigot-Server-Patches/0562-Add-more-Evoker-API.patch rename to Unmapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch diff --git a/Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/Unmapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 100% rename from Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to Unmapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch diff --git a/Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch b/Unmapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 100% rename from Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch rename to Unmapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch diff --git a/Spigot-Server-Patches/0565-Cache-block-data-strings.patch b/Unmapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch similarity index 100% rename from Spigot-Server-Patches/0565-Cache-block-data-strings.patch rename to Unmapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch diff --git a/Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/Unmapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch similarity index 100% rename from Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch rename to Unmapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch diff --git a/Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch b/Unmapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch similarity index 100% rename from Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch rename to Unmapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch diff --git a/Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/Unmapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch similarity index 100% rename from Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch rename to Unmapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch diff --git a/Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch b/Unmapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch similarity index 100% rename from Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch rename to Unmapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch diff --git a/Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/Unmapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch similarity index 100% rename from Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch rename to Unmapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch diff --git a/Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/Unmapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 100% rename from Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to Unmapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch diff --git a/Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch b/Unmapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch similarity index 100% rename from Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch rename to Unmapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch diff --git a/Spigot-Server-Patches/0573-Entity-isTicking.patch b/Unmapped-Spigot-Server-Patches/0573-Entity-isTicking.patch similarity index 100% rename from Spigot-Server-Patches/0573-Entity-isTicking.patch rename to Unmapped-Spigot-Server-Patches/0573-Entity-isTicking.patch diff --git a/Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/Unmapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch similarity index 100% rename from Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch rename to Unmapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch diff --git a/Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch b/Unmapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch similarity index 100% rename from Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch rename to Unmapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch diff --git a/Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/Unmapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch similarity index 100% rename from Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch rename to Unmapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch diff --git a/Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch b/Unmapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch similarity index 100% rename from Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch rename to Unmapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch diff --git a/Spigot-Server-Patches/0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch b/Unmapped-Spigot-Server-Patches/0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch similarity index 100% rename from Spigot-Server-Patches/0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch rename to Unmapped-Spigot-Server-Patches/0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch diff --git a/Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch b/Unmapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch similarity index 100% rename from Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch rename to Unmapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch diff --git a/Spigot-Server-Patches/0580-Optimise-getType-calls.patch b/Unmapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch similarity index 100% rename from Spigot-Server-Patches/0580-Optimise-getType-calls.patch rename to Unmapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch diff --git a/Spigot-Server-Patches/0581-Villager-resetOffers.patch b/Unmapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch similarity index 100% rename from Spigot-Server-Patches/0581-Villager-resetOffers.patch rename to Unmapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch diff --git a/Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/Unmapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch similarity index 100% rename from Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch rename to Unmapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch diff --git a/Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch b/Unmapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch similarity index 100% rename from Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch rename to Unmapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch diff --git a/Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch b/Unmapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch similarity index 100% rename from Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch rename to Unmapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch diff --git a/Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch b/Unmapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch similarity index 100% rename from Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch rename to Unmapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch diff --git a/Spigot-Server-Patches/0586-Player-elytra-boost-API.patch b/Unmapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch similarity index 100% rename from Spigot-Server-Patches/0586-Player-elytra-boost-API.patch rename to Unmapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch diff --git a/Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch b/Unmapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch similarity index 100% rename from Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch rename to Unmapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch diff --git a/Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/Unmapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch similarity index 100% rename from Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch rename to Unmapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch diff --git a/Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch b/Unmapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch rename to Unmapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch diff --git a/Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch b/Unmapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch similarity index 100% rename from Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch rename to Unmapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch diff --git a/Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch b/Unmapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch similarity index 100% rename from Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch rename to Unmapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch diff --git a/Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch b/Unmapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch similarity index 100% rename from Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch rename to Unmapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch diff --git a/Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch b/Unmapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch similarity index 100% rename from Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch rename to Unmapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch diff --git a/Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch b/Unmapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch rename to Unmapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch diff --git a/Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch b/Unmapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch similarity index 100% rename from Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch rename to Unmapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch diff --git a/Spigot-Server-Patches/0596-Seed-based-feature-search.patch b/Unmapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch similarity index 100% rename from Spigot-Server-Patches/0596-Seed-based-feature-search.patch rename to Unmapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch diff --git a/Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch b/Unmapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch similarity index 100% rename from Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch rename to Unmapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch diff --git a/Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch b/Unmapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch similarity index 100% rename from Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch rename to Unmapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch diff --git a/Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch b/Unmapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch similarity index 100% rename from Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch rename to Unmapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch diff --git a/Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch b/Unmapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch similarity index 100% rename from Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch rename to Unmapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch diff --git a/Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/Unmapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch similarity index 100% rename from Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch rename to Unmapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch diff --git a/Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch b/Unmapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch rename to Unmapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch diff --git a/Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch b/Unmapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch rename to Unmapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch diff --git a/Spigot-Server-Patches/0604-More-lightning-API.patch b/Unmapped-Spigot-Server-Patches/0604-More-lightning-API.patch similarity index 100% rename from Spigot-Server-Patches/0604-More-lightning-API.patch rename to Unmapped-Spigot-Server-Patches/0604-More-lightning-API.patch diff --git a/Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch b/Unmapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch similarity index 100% rename from Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch rename to Unmapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch diff --git a/Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch b/Unmapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch similarity index 100% rename from Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch rename to Unmapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch diff --git a/Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch b/Unmapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch similarity index 100% rename from Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch rename to Unmapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch diff --git a/Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch b/Unmapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch similarity index 100% rename from Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch rename to Unmapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch diff --git a/Spigot-Server-Patches/0609-Set-spigots-verbose-world-setting-to-false-by-def.patch b/Unmapped-Spigot-Server-Patches/0609-Set-spigots-verbose-world-setting-to-false-by-def.patch similarity index 100% rename from Spigot-Server-Patches/0609-Set-spigots-verbose-world-setting-to-false-by-def.patch rename to Unmapped-Spigot-Server-Patches/0609-Set-spigots-verbose-world-setting-to-false-by-def.patch diff --git a/Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch b/Unmapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch similarity index 100% rename from Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch rename to Unmapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch diff --git a/Spigot-Server-Patches/0611-Limit-recipe-packets.patch b/Unmapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch similarity index 100% rename from Spigot-Server-Patches/0611-Limit-recipe-packets.patch rename to Unmapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch diff --git a/Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch b/Unmapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch similarity index 100% rename from Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch rename to Unmapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch diff --git a/Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch b/Unmapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch similarity index 100% rename from Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch rename to Unmapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch diff --git a/Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch b/Unmapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch rename to Unmapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch diff --git a/Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch b/Unmapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch similarity index 100% rename from Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch rename to Unmapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch diff --git a/Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch b/Unmapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch rename to Unmapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch diff --git a/Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/Unmapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to Unmapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/Unmapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch similarity index 100% rename from Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch rename to Unmapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch diff --git a/Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch b/Unmapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch similarity index 100% rename from Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch rename to Unmapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch diff --git a/Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch b/Unmapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch similarity index 100% rename from Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch rename to Unmapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch diff --git a/Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch b/Unmapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch similarity index 100% rename from Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch rename to Unmapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch diff --git a/Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch b/Unmapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch similarity index 100% rename from Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch rename to Unmapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch diff --git a/Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/Unmapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch similarity index 100% rename from Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch rename to Unmapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch diff --git a/Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch b/Unmapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch similarity index 100% rename from Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch rename to Unmapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch diff --git a/Spigot-Server-Patches/0625-Cache-burn-durations.patch b/Unmapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch similarity index 100% rename from Spigot-Server-Patches/0625-Cache-burn-durations.patch rename to Unmapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch diff --git a/Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/Unmapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch similarity index 100% rename from Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch rename to Unmapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch diff --git a/Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch b/Unmapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch rename to Unmapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch diff --git a/Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch b/Unmapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch similarity index 100% rename from Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch rename to Unmapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch diff --git a/Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch b/Unmapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch similarity index 100% rename from Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch rename to Unmapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch diff --git a/Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch b/Unmapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch similarity index 100% rename from Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch rename to Unmapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch diff --git a/Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch b/Unmapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch rename to Unmapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch diff --git a/Spigot-Server-Patches/0632-Guardian-beam-workaround.patch b/Unmapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch similarity index 100% rename from Spigot-Server-Patches/0632-Guardian-beam-workaround.patch rename to Unmapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch diff --git a/Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch rename to Unmapped-Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch diff --git a/Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch b/Unmapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch rename to Unmapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch diff --git a/Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch b/Unmapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch similarity index 100% rename from Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch rename to Unmapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch diff --git a/Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch b/Unmapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch similarity index 100% rename from Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch rename to Unmapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch diff --git a/Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch rename to Unmapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch diff --git a/Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch b/Unmapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch similarity index 100% rename from Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch rename to Unmapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch diff --git a/Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch b/Unmapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch rename to Unmapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch diff --git a/Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch b/Unmapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch similarity index 100% rename from Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch rename to Unmapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch diff --git a/Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch b/Unmapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch similarity index 100% rename from Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch rename to Unmapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch diff --git a/Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch b/Unmapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch similarity index 100% rename from Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch rename to Unmapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch diff --git a/Spigot-Server-Patches/0643-Remove-stale-POIs.patch b/Unmapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch similarity index 100% rename from Spigot-Server-Patches/0643-Remove-stale-POIs.patch rename to Unmapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch diff --git a/Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch b/Unmapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch similarity index 100% rename from Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch rename to Unmapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch diff --git a/Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch b/Unmapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch similarity index 100% rename from Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch rename to Unmapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch diff --git a/Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch b/Unmapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch similarity index 100% rename from Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch rename to Unmapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch diff --git a/Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch b/Unmapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch similarity index 100% rename from Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch rename to Unmapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch diff --git a/Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch b/Unmapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch similarity index 100% rename from Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch rename to Unmapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch diff --git a/Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/Unmapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch similarity index 100% rename from Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch rename to Unmapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch diff --git a/Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch b/Unmapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch rename to Unmapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch b/Unmapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch similarity index 100% rename from Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch rename to Unmapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch diff --git a/Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch b/Unmapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch similarity index 100% rename from Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch rename to Unmapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch diff --git a/Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch b/Unmapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch similarity index 100% rename from Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch rename to Unmapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch diff --git a/Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch b/Unmapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch rename to Unmapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch diff --git a/Spigot-Server-Patches/0655-added-Wither-API.patch b/Unmapped-Spigot-Server-Patches/0655-added-Wither-API.patch similarity index 100% rename from Spigot-Server-Patches/0655-added-Wither-API.patch rename to Unmapped-Spigot-Server-Patches/0655-added-Wither-API.patch diff --git a/Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/Unmapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch rename to Unmapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch diff --git a/Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch b/Unmapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch similarity index 100% rename from Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch rename to Unmapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch diff --git a/Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch b/Unmapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch similarity index 100% rename from Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch rename to Unmapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch diff --git a/Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch b/Unmapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch rename to Unmapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/Unmapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to Unmapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch b/Unmapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch similarity index 100% rename from Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch rename to Unmapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch diff --git a/Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch b/Unmapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch similarity index 100% rename from Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch rename to Unmapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch diff --git a/Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch b/Unmapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch similarity index 100% rename from Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch rename to Unmapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch diff --git a/Spigot-Server-Patches/0664-EntityMoveEvent.patch b/Unmapped-Spigot-Server-Patches/0664-EntityMoveEvent.patch similarity index 100% rename from Spigot-Server-Patches/0664-EntityMoveEvent.patch rename to Unmapped-Spigot-Server-Patches/0664-EntityMoveEvent.patch diff --git a/Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch b/Unmapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch similarity index 100% rename from Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch rename to Unmapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch diff --git a/Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch b/Unmapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch similarity index 100% rename from Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch rename to Unmapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch diff --git a/Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch b/Unmapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch rename to Unmapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/Unmapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to Unmapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch b/Unmapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch similarity index 100% rename from Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch rename to Unmapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch diff --git a/Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch b/Unmapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch similarity index 100% rename from Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch rename to Unmapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch diff --git a/Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch b/Unmapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch similarity index 100% rename from Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch rename to Unmapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch diff --git a/Spigot-Server-Patches/0672-misc-debugging-dumps.patch b/Unmapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch similarity index 100% rename from Spigot-Server-Patches/0672-misc-debugging-dumps.patch rename to Unmapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch diff --git a/Spigot-Server-Patches/0673-Add-support-for-hex-color-codes-in-console.patch b/Unmapped-Spigot-Server-Patches/0673-Add-support-for-hex-color-codes-in-console.patch similarity index 100% rename from Spigot-Server-Patches/0673-Add-support-for-hex-color-codes-in-console.patch rename to Unmapped-Spigot-Server-Patches/0673-Add-support-for-hex-color-codes-in-console.patch diff --git a/Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch b/Unmapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch similarity index 100% rename from Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch rename to Unmapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch diff --git a/Spigot-Server-Patches/0675-Expose-Tracked-Players.patch b/Unmapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch similarity index 100% rename from Spigot-Server-Patches/0675-Expose-Tracked-Players.patch rename to Unmapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch diff --git a/Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch b/Unmapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch similarity index 100% rename from Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch rename to Unmapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch diff --git a/Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch b/Unmapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch similarity index 100% rename from Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch rename to Unmapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch diff --git a/Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch b/Unmapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch similarity index 100% rename from Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch rename to Unmapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch diff --git a/Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch b/Unmapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch similarity index 100% rename from Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch rename to Unmapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch diff --git a/Spigot-Server-Patches/0680-Improve-ServerGUI.patch b/Unmapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch similarity index 100% rename from Spigot-Server-Patches/0680-Improve-ServerGUI.patch rename to Unmapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch diff --git a/Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/Unmapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch similarity index 100% rename from Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch rename to Unmapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch diff --git a/Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch b/Unmapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch similarity index 100% rename from Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch rename to Unmapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch diff --git a/Spigot-Server-Patches/0683-Add-worldborder-events.patch b/Unmapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch similarity index 100% rename from Spigot-Server-Patches/0683-Add-worldborder-events.patch rename to Unmapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch diff --git a/Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch b/Unmapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch similarity index 100% rename from Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch rename to Unmapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch diff --git a/Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch b/Unmapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch similarity index 100% rename from Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch rename to Unmapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch diff --git a/Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch b/Unmapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch similarity index 100% rename from Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch rename to Unmapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch diff --git a/Spigot-Server-Patches/0687-Add-Block-isValidTool.patch b/Unmapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch similarity index 100% rename from Spigot-Server-Patches/0687-Add-Block-isValidTool.patch rename to Unmapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch diff --git a/Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch b/Unmapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch similarity index 100% rename from Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch rename to Unmapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch diff --git a/Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch b/Unmapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch similarity index 100% rename from Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch rename to Unmapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch diff --git a/Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch b/Unmapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch similarity index 100% rename from Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch rename to Unmapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch diff --git a/Spigot-Server-Patches/0691-Item-Rarity-API.patch b/Unmapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch similarity index 100% rename from Spigot-Server-Patches/0691-Item-Rarity-API.patch rename to Unmapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch diff --git a/Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/Unmapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch similarity index 100% rename from Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch rename to Unmapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch diff --git a/Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch b/Unmapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch similarity index 100% rename from Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch rename to Unmapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch diff --git a/Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch b/Unmapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch similarity index 100% rename from Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch rename to Unmapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch diff --git a/Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch b/Unmapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch similarity index 100% rename from Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch rename to Unmapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch diff --git a/Spigot-Server-Patches/0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch b/Unmapped-Spigot-Server-Patches/0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch similarity index 100% rename from Spigot-Server-Patches/0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch rename to Unmapped-Spigot-Server-Patches/0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch diff --git a/Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/Unmapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch similarity index 100% rename from Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch rename to Unmapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch diff --git a/Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch b/Unmapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch similarity index 100% rename from Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch rename to Unmapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch diff --git a/Spigot-Server-Patches/0699-Expose-protocol-version.patch b/Unmapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch similarity index 100% rename from Spigot-Server-Patches/0699-Expose-protocol-version.patch rename to Unmapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch diff --git a/Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/Unmapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 100% rename from Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to Unmapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch diff --git a/Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch b/Unmapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch similarity index 100% rename from Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch rename to Unmapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch diff --git a/Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/Unmapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch similarity index 100% rename from Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch rename to Unmapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch diff --git a/Spigot-Server-Patches/0703-Add-bypass-host-check.patch b/Unmapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch similarity index 100% rename from Spigot-Server-Patches/0703-Add-bypass-host-check.patch rename to Unmapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch diff --git a/Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch b/Unmapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch similarity index 100% rename from Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch rename to Unmapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch diff --git a/Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch b/Unmapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch similarity index 100% rename from Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch rename to Unmapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch diff --git a/Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch b/Unmapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch rename to Unmapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch diff --git a/Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch b/Unmapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch similarity index 100% rename from Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch rename to Unmapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch diff --git a/Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch b/Unmapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch rename to Unmapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch b/Unmapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch rename to Unmapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch b/Unmapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch similarity index 100% rename from Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch rename to Unmapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch diff --git a/Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch b/Unmapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch similarity index 100% rename from Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch rename to Unmapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch diff --git a/Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch b/Unmapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch similarity index 100% rename from Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch rename to Unmapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch diff --git a/Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch b/Unmapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch rename to Unmapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch diff --git a/Spigot-Server-Patches/0714-More-World-API.patch b/Unmapped-Spigot-Server-Patches/0714-More-World-API.patch similarity index 100% rename from Spigot-Server-Patches/0714-More-World-API.patch rename to Unmapped-Spigot-Server-Patches/0714-More-World-API.patch diff --git a/Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch b/Unmapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch rename to Unmapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch diff --git a/Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch b/Unmapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch similarity index 100% rename from Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch rename to Unmapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch diff --git a/Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/Unmapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch similarity index 100% rename from Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch rename to Unmapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch diff --git a/Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch b/Unmapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to Unmapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch b/Unmapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch rename to Unmapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch diff --git a/Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch b/Unmapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch similarity index 100% rename from Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch rename to Unmapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch diff --git a/Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch b/Unmapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch similarity index 100% rename from Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch rename to Unmapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch diff --git a/Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch b/Unmapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch similarity index 100% rename from Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch rename to Unmapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch diff --git a/Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch b/Unmapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch rename to Unmapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch diff --git a/Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/Unmapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to Unmapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/Unmapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to Unmapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/Spigot-Server-Patches/0726-Inventory-close.patch b/Unmapped-Spigot-Server-Patches/0726-Inventory-close.patch similarity index 100% rename from Spigot-Server-Patches/0726-Inventory-close.patch rename to Unmapped-Spigot-Server-Patches/0726-Inventory-close.patch diff --git a/Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch b/Unmapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch similarity index 100% rename from Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch rename to Unmapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch diff --git a/Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/Unmapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 100% rename from Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to Unmapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch diff --git a/Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch b/Unmapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch similarity index 100% rename from Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch rename to Unmapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch diff --git a/Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch b/Unmapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch similarity index 100% rename from Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch rename to Unmapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch diff --git a/Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch b/Unmapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch similarity index 100% rename from Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch rename to Unmapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch diff --git a/Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch similarity index 100% rename from Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch rename to Unmapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch diff --git a/Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch b/Unmapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch similarity index 100% rename from Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch rename to Unmapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch diff --git a/Spigot-Server-Patches/0734-More-Enchantment-API.patch b/Unmapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch similarity index 100% rename from Spigot-Server-Patches/0734-More-Enchantment-API.patch rename to Unmapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch diff --git a/Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/Unmapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 100% rename from Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to Unmapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch diff --git a/Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/Unmapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch similarity index 100% rename from Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch rename to Unmapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch diff --git a/Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch b/Unmapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch similarity index 100% rename from Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch rename to Unmapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch diff --git a/Spigot-Server-Patches/0738-Fix-and-optimise-world-force-upgrading.patch b/Unmapped-Spigot-Server-Patches/0738-Fix-and-optimise-world-force-upgrading.patch similarity index 100% rename from Spigot-Server-Patches/0738-Fix-and-optimise-world-force-upgrading.patch rename to Unmapped-Spigot-Server-Patches/0738-Fix-and-optimise-world-force-upgrading.patch diff --git a/Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch b/Unmapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch similarity index 100% rename from Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch rename to Unmapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch diff --git a/Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch b/Unmapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch similarity index 100% rename from Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch rename to Unmapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch diff --git a/Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch b/Unmapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch similarity index 100% rename from Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch rename to Unmapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch diff --git a/Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch b/Unmapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch similarity index 100% rename from Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch rename to Unmapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch diff --git a/Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/Unmapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch similarity index 100% rename from Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch rename to Unmapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch diff --git a/Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch b/Unmapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch rename to Unmapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/Spigot-Server-Patches/0745-More-Lidded-Block-API.patch b/Unmapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch similarity index 100% rename from Spigot-Server-Patches/0745-More-Lidded-Block-API.patch rename to Unmapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch diff --git a/Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch b/Unmapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch similarity index 100% rename from Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch rename to Unmapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch diff --git a/Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch b/Unmapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch similarity index 100% rename from Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch rename to Unmapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch diff --git a/Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch rename to Unmapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch diff --git a/Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/Unmapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch similarity index 100% rename from Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch rename to Unmapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch diff --git a/Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch b/Unmapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch similarity index 100% rename from Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch rename to Unmapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch diff --git a/Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch b/Unmapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch similarity index 100% rename from Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch rename to Unmapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch diff --git a/Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch b/Unmapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch similarity index 100% rename from Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch rename to Unmapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch diff --git a/Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch b/Unmapped-Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch rename to Unmapped-Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch diff --git a/Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch b/Unmapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch similarity index 100% rename from Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch rename to Unmapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch diff --git a/Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch b/Unmapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch similarity index 100% rename from Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch rename to Unmapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch diff --git a/Spigot-Server-Patches/0756-Make-item-validations-configurable.patch b/Unmapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch similarity index 100% rename from Spigot-Server-Patches/0756-Make-item-validations-configurable.patch rename to Unmapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch diff --git a/Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch b/Unmapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch similarity index 100% rename from Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch rename to Unmapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch diff --git a/Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch b/Unmapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch similarity index 100% rename from Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch rename to Unmapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch diff --git a/Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch b/Unmapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch similarity index 100% rename from Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch rename to Unmapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch From c1aacf62b5b7dadb583bb8bec3aedf0a9b9f91b8 Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Fri, 11 Jun 2021 06:43:40 -0500 Subject: [PATCH 005/226] Initial Spigot remap patches --- .../0001-Convert-project-to-Gradle.patch | 76 +++++++++++++++ .../0001-Setup-Gradle-project.patch | 95 +++++++++++++++++++ .../0002-Decompile-fixes.patch | 77 +++++++++++++++ 3 files changed, 248 insertions(+) create mode 100644 Spigot-API-Patches/0001-Convert-project-to-Gradle.patch create mode 100644 Spigot-Server-Patches/0001-Setup-Gradle-project.patch create mode 100644 Spigot-Server-Patches/0002-Decompile-fixes.patch diff --git a/Spigot-API-Patches/0001-Convert-project-to-Gradle.patch b/Spigot-API-Patches/0001-Convert-project-to-Gradle.patch new file mode 100644 index 0000000000..d34ab3ef3c --- /dev/null +++ b/Spigot-API-Patches/0001-Convert-project-to-Gradle.patch @@ -0,0 +1,76 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Thu, 10 Dec 2020 20:50:33 -0800 +Subject: [PATCH] Convert project to Gradle + + +diff --git a/.gitignore b/.gitignore +index e431e3435737e28394d81b56568a08b3c3148b9b..c484aff2c192bf42059b5689327909e4af654401 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -1,3 +1,5 @@ ++.gradle/ ++ + # Eclipse stuff + /.classpath + /.project +diff --git a/build.gradle.kts b/build.gradle.kts +new file mode 100644 +index 0000000000000000000000000000000000000000..a0f1c1d1ac63fdcce942922ffe68a8d44c712513 +--- /dev/null ++++ b/build.gradle.kts +@@ -0,0 +1,54 @@ ++plugins { ++ `java-library` ++ checkstyle ++} ++ ++java { ++ withSourcesJar() ++ withJavadocJar() ++} ++ ++dependencies { ++ // api dependencies are listed transitively to API consumers ++ api("commons-lang:commons-lang:2.6") ++ api("com.google.guava:guava:21.0") ++ api("com.google.code.gson:gson:2.8.0") ++ api("net.md-5:bungeecord-chat:1.16-R0.4") ++ api("org.yaml:snakeyaml:1.29") ++ ++ compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") ++ compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") ++ compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") ++ ++ val annotations = "org.jetbrains:annotations-java5:21.0.1" ++ compileOnly(annotations) ++ testCompileOnly(annotations) ++ ++ testImplementation("junit:junit:4.13.1") ++ testImplementation("org.hamcrest:hamcrest-library:1.3") ++ testImplementation("org.ow2.asm:asm-tree:9.1") ++ ++ checkstyle("com.puppycrawl.tools:checkstyle:8.39") ++} ++ ++tasks.jar { ++ manifest { ++ attributes += mapOf( ++ "Automatic-Module-Name" to "org.bukkit" ++ ) ++ } ++} ++ ++tasks.withType().configureEach { ++ (options as StandardJavadocDocletOptions).links( ++ "https://guava.dev/releases/21.0/api/docs/", ++ "https://javadoc.io/doc/org.yaml/snakeyaml/1.27/", ++ "https://javadoc.io/doc/org.jetbrains/annotations-java5/20.1.0/", ++ "https://javadoc.io/doc/net.md-5/bungeecord-chat/1.16-R0.4/" ++ ) ++} ++ ++checkstyle { ++ configFile = file("checkstyle.xml") ++ sourceSets = listOf(project.sourceSets.main.get(), project.sourceSets.test.get()) ++} diff --git a/Spigot-Server-Patches/0001-Setup-Gradle-project.patch b/Spigot-Server-Patches/0001-Setup-Gradle-project.patch new file mode 100644 index 0000000000..9e12bf0e6d --- /dev/null +++ b/Spigot-Server-Patches/0001-Setup-Gradle-project.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Thu, 10 Dec 2020 20:54:19 -0800 +Subject: [PATCH] Setup Gradle project + + +diff --git a/.gitignore b/.gitignore +index 67fb370cad6924895a6b27052dbd5c1767e3f0c9..3e05459f27c4c5697ae65da504d67a6a2f617b57 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -1,3 +1,6 @@ ++.gradle/ ++build/ ++ + # Eclipse stuff + /.classpath + /.project +diff --git a/build.gradle.kts b/build.gradle.kts +new file mode 100644 +index 0000000000000000000000000000000000000000..fddf2f440356425d948f40dcf9d9853a374ddc8e +--- /dev/null ++++ b/build.gradle.kts +@@ -0,0 +1,72 @@ ++import com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer ++import java.time.Instant ++ ++plugins { ++ java ++ id("com.github.johnrengelman.shadow") ++} ++ ++val packageVersion = providers.gradleProperty("packageVersion").forUseAtConfigurationTime().get() ++ ++repositories { ++ maven("https://libraries.minecraft.net/") ++} ++ ++dependencies { ++ implementation(project(":Paper-API")) ++ implementation("jline:jline:2.12.1") ++ implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") { ++ exclude(group = "org.apache.logging.log4j", module = "log4j-api") ++ } ++ implementation("org.ow2.asm:asm:9.1") ++ implementation("com.googlecode.json-simple:json-simple:1.1.1") { ++ // This includes junit transitively for whatever reason ++ isTransitive = false ++ } ++ runtimeOnly("org.xerial:sqlite-jdbc:3.34.0") ++ runtimeOnly("mysql:mysql-connector-java:5.1.49") ++ ++ runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.1") ++ runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") ++ runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") ++ ++ testImplementation("junit:junit:4.13.1") ++ testImplementation("org.hamcrest:hamcrest-library:1.3") ++} ++ ++tasks.jar { ++ manifest { ++ attributes(mapOf( ++ "Main-Class" to "org.bukkit.craftbukkit.Main", ++ "Implementation-Title" to "CraftBukkit", ++ "Implementation-Vendor" to Instant.now().epochSecond, ++ "Specification-Title" to "Bukkit", ++ "Specification-Version" to project.version, ++ "Specification-Vendor" to "Bukkit Team" ++ )) ++ for (tld in listOf("net", "com", "org")) { ++ attributes(mapOf( ++ "Sealed" to "true" ++ ), "$tld/bukkit") ++ } ++ } ++} ++ ++tasks.shadowJar { ++ listOf( ++ "jline", "it.unimi", "org.apache.commons.codec", "org.apache.commons.io", ++ "org.apache.commons.lang3", "org.objectweb.asm" ++ ).forEach { pack -> ++ relocate(pack, "org.bukkit.craftbukkit.libs.$pack") ++ } ++ relocate("org.bukkit.craftbukkit", "org.bukkit.craftbukkit.v$packageVersion") { ++ exclude("org.bukkit.craftbukkit.Main*") ++ } ++ transform(AppendingTransformer::class.java) { ++ resource = "META-INF/services/java.sql.Driver" ++ } ++} ++ ++tasks.test { ++ exclude("org/bukkit/craftbukkit/inventory/ItemStack*Test.class") ++} diff --git a/Spigot-Server-Patches/0002-Decompile-fixes.patch b/Spigot-Server-Patches/0002-Decompile-fixes.patch new file mode 100644 index 0000000000..ce714be18b --- /dev/null +++ b/Spigot-Server-Patches/0002-Decompile-fixes.patch @@ -0,0 +1,77 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Fri, 11 Jun 2021 05:25:03 -0500 +Subject: [PATCH] Decompile fixes + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 3aecce56bdac0a316742a55e340c522bea737321..6b4d84faba50d9f3f87e48251cf1294479d4a3a0 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1138,7 +1138,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +- entity1.moveTo(pos.x, pos.y, pos.z, entity1.getYRot(), entity1.getXRot()); +- return entity1; ++ Entity entity1 = EntityType.loadEntityRecursive(nbttagcompound1, worldserver, (loadedEntity) -> { // Paper - decomp fix ++ loadedEntity.moveTo(pos.x, pos.y, pos.z, loadedEntity.getYRot(), loadedEntity.getXRot()); // Paper - decomp fix ++ return loadedEntity; // Paper - decomp fix + }); + + if (entity1 == null) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java +index 88a8c2bc4aa30f478122a05fd119486a0107db82..5f00e3f4c86196db47bf1007973445d40866afdd 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java +@@ -169,8 +169,8 @@ public class BehaviorUtils { + + return optional.map((uuid) -> { + return ((ServerLevel) entity.level).getEntity(uuid); +- }).map((entity) -> { +- return entity instanceof LivingEntity ? (LivingEntity) entity : null; ++ }).map((entity2) -> { // Paper - decomp fix ++ return entity2 instanceof LivingEntity ? (LivingEntity) entity2 : null; // Paper - decomp fix + }); + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index c88dc823ca0c2f83bc10886208d498ea77523d68..dcfd0b107ac7bd1633f3b681cd5f5e26ce87bd63 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -522,7 +522,7 @@ public class Phantom extends FlyingMob implements Enemy { + List list = Phantom.this.level.getNearbyPlayers(this.attackTargeting, (LivingEntity) Phantom.this, Phantom.this.getBoundingBox().inflate(16.0D, 64.0D, 16.0D)); + + if (!list.isEmpty()) { +- list.sort(Comparator.comparing(Entity::getY).reversed()); ++ list.sort(Comparator.comparing(Entity::getY).reversed()); // Paper - decomp fix + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +index b4a5709b03e400d00504f33a9b34019d2b7bf115..2d79d4014770081fcd58a929e5fe0a26ac1b8023 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java ++++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +@@ -172,7 +172,7 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { + Map, Object2ObjectLinkedOpenHashMap>> map = Maps.newHashMap(); // CraftBukkit + + recipes.forEach((irecipe) -> { +- Map> map1 = (Map) map.computeIfAbsent(irecipe.getType(), (recipes) -> { ++ Map> map1 = (Map) map.computeIfAbsent(irecipe.getType(), (recipes_) -> { // Paper - decomp fix + return new Object2ObjectLinkedOpenHashMap<>(); // CraftBukkit + }); + Recipe irecipe1 = (Recipe) map1.put(irecipe.getId(), irecipe); From 73bcb74f232c5f060ecdb59a11d8a8689e2648b9 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Fri, 11 Jun 2021 13:56:17 +0200 Subject: [PATCH 006/226] Inital remap of patches --- .../0001-POM-Changes.patch | 291 + .../0002-Paper-config-files.patch | 820 +++ .../0003-MC-Dev-fixes.patch | 929 ++++ .../0004-MC-Utils.patch | 4859 +++++++++++++++++ .../0005-Paper-Metrics.patch | 735 +++ ...-MinecraftKey-Information-to-Objects.patch | 144 + ...to-current-Chunk-for-Entity-and-Bloc.patch | 171 + ...ts-for-each-Entity-Block-Entity-Type.patch | 55 + .../0009-Timings-v2.patch | 2330 ++++++++ .../0010-Adventure.patch | 3238 +++++++++++ ...actus-bamboo-and-reed-growth-heights.patch | 114 + ...figurable-baby-zombie-movement-speed.patch | 51 + ...013-Configurable-fishing-time-ranges.patch | 38 + ...d-mobs-to-jump-and-take-water-damage.patch | 105 + ...-despawn-distances-for-living-entiti.patch | 55 + ...6-Allow-for-toggling-of-spawn-chunks.patch | 33 + ...ck-and-tnt-entities-at-the-specified.patch | 94 + ...ient-crashes-server-lists-and-Mojang.patch | 117 + .../0019-Implement-Paper-VersionChecker.patch | 150 + ...d-version-history-to-version-command.patch | 215 + .../0021-Player-affects-spawning-API.patch | 157 + ...ve-invalid-mob-spawner-tile-entities.patch | 31 + .../0023-Optimize-TileEntity-Ticking.patch | 279 + ...024-Further-improve-server-tick-loop.patch | 208 + ...025-Only-refresh-abilities-if-needed.patch | 25 + .../0026-Entity-Origin-API.patch | 140 + ...event-tile-entity-and-entity-crashes.patch | 65 + ...nfigurable-top-of-nether-void-damage.patch | 93 + ...e-before-converting-and-renaming-pla.patch | 19 + .../0030-Always-tick-falling-blocks.patch | 18 + .../0031-Configurable-end-credits.patch | 42 + ...-explosions-processing-dead-entities.patch | 19 + .../0033-Optimize-explosions.patch | 148 + .../0034-Disable-explosion-knockback.patch | 69 + .../0035-Disable-thunder.patch | 33 + .../0036-Disable-ice-and-snow.patch | 33 + ...7-Configurable-mob-spawner-tick-rate.patch | 65 + ...sition-the-first-time-an-entity-is-s.patch | 108 + .../0039-Add-BeaconEffectEvent.patch | 103 + ...figurable-container-update-tick-rate.patch | 46 + .../0041-Use-UserCache-for-player-heads.patch | 25 + .../0042-Disable-spigot-tick-limiters.patch | 21 + .../0043-Add-PlayerInitialSpawnEvent.patch | 48 + ...urable-Disabling-Cat-Chest-Detection.patch | 37 + ...45-Ensure-commands-are-not-ran-async.patch | 119 + ...chunks-are-slime-spawn-chunks-toggle.patch | 33 + .../0047-Expose-server-CommandMap.patch | 18 + ...e-informative-in-maxHealth-exception.patch | 22 + .../0049-Player-Tab-List-and-Title-APIs.patch | 173 + .../0050-Ensure-inv-drag-is-in-bounds.patch | 19 + ...entation-of-tile-entity-removal-list.patch | 48 + ...dd-configurable-portal-search-radius.patch | 56 + .../0053-Add-velocity-warnings.patch | 89 + ...ble-inter-world-teleportation-safety.patch | 44 + .../0055-Add-exception-reporting-event.patch | 264 + ...-don-t-need-to-when-cerealising-text.patch | 27 + ...oreboards-for-non-players-by-default.patch | 50 + ...working-with-arrows-stuck-in-living-.patch | 27 + .../0059-Complete-resource-pack-API.patch | 71 + .../0060-Chunk-Save-Reattempt.patch | 59 + ...ading-permissions.yml-before-plugins.patch | 52 + ...llow-Reloading-of-Custom-Permissions.patch | 35 + .../0063-Remove-Metadata-on-reload.patch | 31 + ...064-Handle-Item-Meta-Inconsistencies.patch | 339 ++ ...urable-Non-Player-Arrow-Despawn-Rate.patch | 44 + .../0066-Add-World-Util-Methods.patch | 65 + ...7-Custom-replacement-for-eaten-items.patch | 48 + ...th-absorb-values-and-repair-bad-data.patch | 57 + ...069-Use-a-Shared-Random-for-Entities.patch | 42 + ...le-spawn-chances-for-skeleton-horses.patch | 36 + ...Location-getType-and-getBlockData-fo.patch | 206 + ...ckPhysicsEvent-if-a-plugin-has-a-lis.patch | 95 + ...Entity-AddTo-RemoveFrom-World-Events.patch | 27 + ...74-Configurable-Chunk-Inhabited-Time.patch | 44 + .../0075-EntityPathfindEvent.patch | 125 + ...egionFileCache-and-make-configurable.patch | 39 + ...7-Do-not-load-chunks-for-Pathfinding.patch | 68 + ...0078-Add-PlayerUseUnknownEntityEvent.patch | 40 + ...dDebugInfo-not-initialized-on-client.patch | 18 + ...-Configurable-Grass-Spread-Tick-Rate.patch | 41 + ...g-BlockPlaceEvent-triggering-physics.patch | 18 + .../0082-Optimize-DataBits.patch | 84 + ...nilla-per-world-scoreboard-coloring-.patch | 66 + ...nd-for-setting-passengers-on-players.patch | 29 + ...Remove-unused-World-Tile-Entity-List.patch | 90 + .../0086-Don-t-tick-Skulls-unused-code.patch | 28 + .../0087-Configurable-Player-Collision.patch | 131 + ...ent-to-allow-plugins-to-handle-clien.patch | 57 + .../0089-Configurable-RCON-IP-address.patch | 59 + ...e-from-loading-chunks-wrongly-spread.patch | 82 + ...91-Implement-PlayerLocaleChangeEvent.patch | 48 + ...ityRegainHealthEvent-isFastRegen-API.patch | 42 + ...-to-configure-frosted_ice-properties.patch | 52 + ...-possibility-for-getServer-singleton.patch | 36 + ...item-frames-performance-and-bug-fixe.patch | 144 + ...-API-Replenishable-Lootables-Feature.patch | 739 +++ ...y-scoreboard-teams-to-scoreboard.dat.patch | 32 + ...tem-property-for-disabling-watchdoge.patch | 19 + .../0099-Optimize-UserCache-Thread-Safe.patch | 117 + ...blocking-on-Network-Manager-creation.patch | 45 + ...1-Optional-TNT-doesn-t-move-in-water.patch | 121 + ...r-redstone-torch-rapid-clock-removal.patch | 98 + .../0103-Add-server-name-parameter.patch | 25 + ...on-Wither-Death-sounds-to-same-world.patch | 47 + .../0105-Fix-Double-World-Add-issues.patch | 21 + .../0106-Fix-Old-Sign-Conversion.patch | 59 + ...e-profiles-that-have-no-UUID-and-no-.patch | 19 + ...setting-for-proxy-online-mode-status.patch | 81 + ...ptimise-BlockState-s-hashCode-equals.patch | 84 + ...onfigurable-packet-in-spam-threshold.patch | 45 + ...11-Configurable-flying-kick-messages.patch | 44 + .../0112-Chunk-registration-fixes.patch | 22 + ...ok-reference-on-Craft-Entity-removal.patch | 25 + ...uto-fix-bad-Y-levels-on-player-login.patch | 19 + ...tion-to-remove-corrupt-tile-entities.patch | 37 + .../0116-Add-EntityZapEvent.patch | 58 + ...a-from-ArmorStand-and-SpawnEgg-items.patch | 49 + ...118-Cache-user-authenticator-threads.patch | 102 + .../0119-Optimise-removeQueue.patch | 67 + ...0-Allow-Reloading-of-Command-Aliases.patch | 36 + ...1-Add-source-to-PlayerExpChangeEvent.patch | 49 + ...2-Don-t-let-fishinghooks-use-portals.patch | 22 + .../0123-Add-ProjectileCollideEvent.patch | 109 + ...vent-Pathfinding-out-of-World-Border.patch | 20 + ...imize-World.isLoaded-BlockPosition-Z.patch | 22 + ...-Bound-Treasure-Maps-to-World-Border.patch | 47 + ...figurable-Cartographer-Treasure-Maps.patch | 65 + .../0128-Optimize-ItemStack.isEmpty.patch | 20 + ...to-control-if-armour-stands-can-move.patch | 106 + ...30-Properly-fix-item-duplication-bug.patch | 35 + .../0131-String-based-Action-Bar-API.patch | 48 + .../0132-Firework-API-s.patch | 124 + .../0133-PlayerTeleportEndGatewayEvent.patch | 28 + ...rovide-E-TE-Chunk-count-stat-methods.patch | 61 + .../0135-Enforce-Sync-Player-Saves.patch | 27 + ...llow-entities-to-ride-themselves-572.patch | 18 + ...PI-for-Reason-Source-Triggering-play.patch | 332 ++ .../0138-Cap-Entity-Collisions.patch | 57 + ...e-CraftScheduler-Async-Task-Debugger.patch | 48 + ...more-aggressive-in-the-chunk-unload-.patch | 47 + .../0141-Do-not-let-armorstands-drown.patch | 42 + ...le-async-calls-to-restart-the-server.patch | 307 ++ ...property-to-disable-book-size-limits.patch | 51 + ...ke-parrots-stay-on-shoulders-despite.patch | 58 + ...n-option-to-prevent-player-names-fro.patch | 36 + ...oleAppender-for-console-improvements.patch | 558 ++ ...urable-option-to-disable-creeper-lin.patch | 35 + .../0148-Item-canEntityPickup.patch | 55 + ...PlayerPickupItemEvent-setFlyAtPlayer.patch | 46 + .../0150-PlayerAttemptPickupItemEvent.patch | 41 + .../0151-Add-UnknownCommandEvent.patch | 25 + .../0152-Basic-PlayerProfile-API.patch | 577 ++ .../0153-Shoulder-Entities-Release-API.patch | 96 + .../0154-Profile-Lookup-Events.patch | 81 + ...player-logins-during-server-shutdown.patch | 23 + .../0156-Entity-fromMobSpawner.patch | 65 + ...57-Improve-the-Saddle-API-for-Horses.patch | 59 + ...mplement-ensureServerConversions-API.patch | 24 + .../0159-Implement-getI18NDisplayName.patch | 58 + .../0160-ProfileWhitelistVerifyEvent.patch | 50 + .../0161-Fix-this-stupid-bullshit.patch | 30 + ...awns-should-honor-nametags-and-leash.patch | 19 + ...imer-when-spawner-event-is-cancelled.patch | 27 + ...64-Fix-MC-117075-TE-Unload-Lag-Spike.patch | 23 + ...-a-custom-authentication-servers-dow.patch | 43 + .../0166-LivingEntity-setKiller.patch | 48 + ...n-prefixes-using-Log4J-configuration.patch | 71 + ...e-Log4J-Configuration-Plugin-Loggers.patch | 47 + .../0169-Add-PlayerJumpEvent.patch | 46 + ...0-handle-PacketPlayInKeepAlive-async.patch | 40 + ...nt-protocol-version-and-virtual-host.patch | 128 + ...rt-serverside-behavior-of-keepalives.patch | 75 + ...dEffects-only-to-players-who-can-see.patch | 80 + ...-maximum-exp-value-when-merging-orbs.patch | 61 + .../0175-Add-PlayerArmorChangeEvent.patch | 43 + ...rom-being-processed-when-the-player-.patch | 24 + ...e-implementations-for-captured-block.patch | 60 + ...-get-a-BlockState-without-a-snapshot.patch | 147 + .../0179-AsyncTabCompleteEvent.patch | 130 + ...180-Avoid-NPE-in-PathfinderGoalTempt.patch | 19 + .../0181-PlayerPickupExperienceEvent.patch | 28 + .../0182-ExperienceOrbMergeEvent.patch | 22 + ...3-Ability-to-apply-mending-to-XP-API.patch | 101 + ...-max-squid-spawn-height-configurable.patch | 36 + .../0185-PreCreatureSpawnEvent.patch | 215 + ...6-PlayerNaturallySpawnCreaturesEvent.patch | 79 + ...-Add-setPlayerProfile-API-for-Skulls.patch | 109 + .../0188-Fill-Profile-Property-Events.patch | 42 + ...PlayerAdvancementCriterionGrantEvent.patch | 23 + .../0190-Add-ArmorStand-Item-Meta.patch | 296 + ...-Extend-Player-Interact-cancellation.patch | 60 + .../0192-Tameable-getOwnerUniqueId-API.patch | 36 + ...r-crits-helps-mitigate-hacked-client.patch | 34 + ...sted-Ice-from-loading-holding-chunks.patch | 31 + ...le-Explicit-Network-Manager-Flushing.patch | 34 + ...nt-extended-PaperServerListPingEvent.patch | 378 ++ .../0197-Improved-Async-Task-Scheduler.patch | 370 ++ ...e-PlayerProfile-in-AsyncPreLoginEven.patch | 45 + .../0199-Player.setPlayerProfile-API.patch | 142 + .../0200-Fix-Dragon-Server-Crashes.patch | 21 + .../0201-getPlayerUniqueId-API.patch | 40 + ...Make-player-data-saving-configurable.patch | 27 + ...ke-legacy-ping-handler-more-reliable.patch | 181 + ...ServerListPingEvent-for-legacy-pings.patch | 154 + ...05-Flag-to-disable-the-channel-limit.patch | 31 + ...d-method-to-open-already-placed-sign.patch | 36 + ...urable-sprint-interruption-on-attack.patch | 38 + ...-allowed-colored-signs-to-be-created.patch | 31 + .../0209-EndermanEscapeEvent.patch | 82 + .../0210-Enderman.teleportRandomly.patch | 31 + ...0211-Block-Enderpearl-Travel-Exploit.patch | 40 + ...ld.spawnParticle-API-and-add-Builder.patch | 67 + .../0213-EndermanAttackPlayerEvent.patch | 46 + .../0214-WitchConsumePotionEvent.patch | 24 + .../0215-WitchThrowPotionEvent.patch | 30 + ...Item-entities-with-World.spawnEntity.patch | 24 + .../0217-WitchReadyPotionEvent.patch | 23 + ...0218-ItemStack-getMaxItemUseDuration.patch | 37 + ...lement-EntityTeleportEndGatewayEvent.patch | 32 + ...ed-flag-on-cancel-of-Explosion-Event.patch | 28 + .../0221-Fix-CraftEntity-hashCode.patch | 46 + ...le-Alternative-LootPool-Luck-Formula.patch | 118 + ...ils-when-failing-to-save-player-data.patch | 19 + ...e-shield-blocking-delay-configurable.patch | 69 + .../0225-Improve-EntityShootBowEvent.patch | 44 + .../0226-PlayerReadyArrowEvent.patch | 39 + ...plement-EntityKnockbackByEntityEvent.patch | 93 + .../0228-Expand-Explosions-API.patch | 23 + ...ivingEntity-Hand-Raised-Item-Use-API.patch | 68 + .../0230-RangedEntity-API.patch | 171 + ...to-disable-ender-dragon-legacy-check.patch | 33 + ...2-Implement-World.getEntity-UUID-API.patch | 26 + .../0233-InventoryCloseEvent-Reason-API.patch | 228 + .../0234-Vex-getSummoner-API.patch | 37 + ...nventory-when-cancelling-PlayerInter.patch | 29 + ...ge-the-Entity-Random-seed-for-squids.patch | 19 + ...nilla-entity-warnings-for-duplicates.patch | 22 + ...e-if-stack-size-above-max-stack-size.patch | 21 + ...239-Use-asynchronous-Log4j-2-loggers.patch | 55 + ...-more-information-to-Entity.toString.patch | 20 + ...ies-option-to-debug-dupe-uuid-issues.patch | 131 + .../0242-EnderDragon-Events.patch | 62 + .../0243-PlayerElytraBoostEvent.patch | 31 + .../0244-Improve-BlockPosition-inlining.patch | 75 + .../0245-Optimize-RegistryID.c.patch | 67 + ...t-armor-stands-from-doing-entity-loo.patch | 58 + ...7-Vanished-players-don-t-have-rights.patch | 194 + ...-anytime-entities-change-to-guarante.patch | 27 + ...dd-some-Debug-to-Chunk-Entity-slices.patch | 99 + .../0250-SkeletonHorse-Additions.patch | 152 + ...revent-Saving-Bad-entities-to-chunks.patch | 127 + ...on-t-call-getItemMeta-on-hasItemMeta.patch | 64 + ...ead-Entities-in-entityList-iteration.patch | 120 + ...54-Implement-Expanded-ArmorStand-API.patch | 104 + .../0255-AnvilDamageEvent.patch | 28 + .../0256-Add-TNTPrimeEvent.patch | 148 + ...nd-make-tab-spam-limits-configurable.patch | 75 + .../0258-Add-hand-to-bucket-events.patch | 341 ++ ...6-Experience-should-save-as-Integers.patch | 28 + ...ient-rendering-skulls-from-same-user.patch | 147 + ...dd-Early-Warning-Feature-to-WatchDog.patch | 184 + .../0262-Make-EnderDragon-implement-Mob.patch | 33 + ...63-Use-ConcurrentHashMap-in-JsonList.patch | 147 + ...64-Use-a-Queue-for-Queueing-Commands.patch | 39 + ...ile-Entities-from-a-chunk-without-sn.patch | 73 + ...Allow-disabling-armour-stand-ticking.patch | 159 + ...ptimize-BlockPosition-helper-methods.patch | 100 + ...efault-mob-spawn-range-and-water-ani.patch | 33 + .../0269-Slime-Pathfinder-Events.patch | 229 + ...le-speed-for-water-flowing-over-lava.patch | 72 + ...271-Optimize-CraftBlockData-Creation.patch | 49 + .../0272-Optimize-RegistryMaterials.patch | 96 + .../0273-Add-PhantomPreSpawnEvent.patch | 96 + .../0274-Add-More-Creeper-API.patch | 49 + .../0275-Inventory-removeItemAnySlot.patch | 58 + ...loadChunk-int-int-false-load-unconve.patch | 20 + ...-ray-tracing-methods-to-LivingEntity.patch | 99 + ...e-attack-cooldown-methods-for-Player.patch | 41 + .../0279-Improve-death-events.patch | 458 ++ ...ow-chests-to-be-placed-with-NBT-data.patch | 31 + .../0281-Mob-Pathfinding-API.patch | 290 + ...ent-chunk-loading-from-Fluid-Flowing.patch | 75 + ...-for-CanPlaceOn-and-CanDestroy-NBT-v.patch | 446 ++ ...ent-Mob-AI-Rules-from-Loading-Chunks.patch | 83 + ...wning-from-loading-generating-chunks.patch | 32 + ...e-Biome-Mob-Lookups-for-Mob-Spawning.patch | 97 + ...nt-furnace-cook-speed-multiplier-API.patch | 102 + .../0288-PreSpawnerSpawnEvent.patch | 29 + ...arseException-in-Entity-and-TE-names.patch | 110 + .../0290-Honor-EntityAgeable.ageLock.patch | 18 + ...ble-connection-throttle-kick-message.patch | 35 + .../0292-Hook-into-CB-plugin-rewrites.patch | 184 + ...293-Allow-setting-the-vex-s-summoner.patch | 33 + .../0294-Add-sun-related-API.patch | 52 + .../0295-Turtle-API.patch | 150 + ...ther-worlds-for-shooter-of-projectil.patch | 36 + ...tator-target-events-and-improve-impl.patch | 99 + ...8-Add-Velocity-IP-Forwarding-Support.patch | 303 + .../0299-Add-more-Witch-API.patch | 150 + ...owned-for-Villager-Aggression-Config.patch | 19 + .../0301-Here-s-Johnny.patch | 38 + ...event-players-from-moving-into-unloa.patch | 64 + ...03-Reset-players-airTicks-on-respawn.patch | 30 + ...-after-profile-lookups-if-not-needed.patch | 33 + ...er-Thread-Pool-and-Thread-Priorities.patch | 121 + .../0306-Optimize-World-Time-Updates.patch | 42 + ...store-custom-InventoryHolder-support.patch | 46 + .../0308-Use-Vanilla-Minecart-Speeds.patch | 24 + .../0309-Fix-SpongeAbsortEvent-handling.patch | 37 + ...t-allow-digging-into-unloaded-chunks.patch | 68 + .../0311-Book-Size-Limits.patch | 80 + ...ault-permission-message-configurable.patch | 46 + ...Prevent-rayTrace-from-loading-chunks.patch | 29 + ...e-Large-Packets-disconnecting-client.patch | 130 + ...entity-dismount-during-teleportation.patch | 134 + .../0316-Add-more-Zombie-API.patch | 117 + .../0317-Add-PlayerConnectionCloseEvent.patch | 82 + ...Prevent-Enderman-from-loading-chunks.patch | 30 + ...-replace-OfflinePlayer-getLastPlayed.patch | 164 + ...vehicle-tracking-issue-on-disconnect.patch | 24 + ...onRetractEvent-for-all-empty-pistons.patch | 47 + ...-remove-from-being-called-on-Players.patch | 33 + .../0323-BlockDestroyEvent.patch | 46 + ...om-Shapeless-Custom-Crafting-Recipes.patch | 68 + .../0325-Fix-sign-edit-memory-leak.patch | 44 + .../0326-Limit-Client-Sign-length-more.patch | 54 + ...ConvertSigns-boolean-every-sign-save.patch | 29 + ...-Manager-and-add-advanced-packet-sup.patch | 394 ++ ...le-Oversized-Tile-Entities-in-chunks.patch | 54 + ...0-Fix-Whitelist-On-Off-inconsistency.patch | 45 + ...st-tick-at-start-of-drowning-process.patch | 19 + ...332-Allow-Saving-of-Oversized-Chunks.patch | 271 + ...oggleEvent-when-whitelist-is-toggled.patch | 18 + ...334-Add-LivingEntity-getTargetEntity.patch | 187 + ...ength-when-serialising-BungeeCord-te.patch | 32 + .../0336-Entity-getEntitySpawnReason.patch | 121 + ...ity-Metadata-for-all-tracked-players.patch | 43 + ...338-Implement-PlayerPostRespawnEvent.patch | 48 + ...-for-pickupDelay-breaks-picking-up-i.patch | 27 + .../0340-Server-Tick-Events.patch | 32 + ...0341-PlayerDeathEvent-getItemsToKeep.patch | 74 + ...-Optimize-Captured-TileEntity-Lookup.patch | 32 + .../0343-Add-Heightmap-API.patch | 55 + .../0344-Mob-Spawner-API-Enhancements.patch | 139 + ...layer-View-Distance-API-placeholders.patch | 70 + ...l-to-changed-postToMainThread-method.patch | 19 + ...n-item-frames-are-modified-MC-123450.patch | 20 + ...isPrimaryThread-and-MinecraftServer-.patch | 43 + ...h-entity-loss-due-to-unloaded-chunks.patch | 53 + .../0350-Duplicate-UUID-Resolve-Option.patch | 249 + ...351-improve-CraftWorld-isChunkLoaded.patch | 30 + ...le-Keep-Spawn-Loaded-range-per-world.patch | 260 + ...tityAreaEffectCloud-from-going-negat.patch | 24 + .../0354-ChunkMapDistance-CME.patch | 93 + .../0355-Implement-CraftBlockSoundGroup.patch | 83 + .../0356-Chunk-debug-command.patch | 490 ++ ...eptions-from-dispenser-entity-spawns.patch | 33 + ...358-Fix-World-isChunkGenerated-calls.patch | 390 ++ ...ate-location-if-we-failed-to-read-it.patch | 34 + ...PaletteBlock-instead-of-ReentrantLoc.patch | 117 + .../0361-incremental-chunk-saving.patch | 317 ++ .../0362-Anti-Xray.patch | 1624 ++++++ ...al-Spawned-mobs-towards-natural-spaw.patch | 57 + ...gurable-projectile-relative-velocity.patch | 53 + ...-being-ticked-when-notifying-navigat.patch | 26 + .../0366-offset-item-frame-ticking.patch | 19 + ...opper-searches-if-there-are-no-items.patch | 127 + ...68-Asynchronous-chunk-IO-and-loading.patch | 4410 +++++++++++++++ ...etChunkIfLoadedImmediately-in-places.patch | 119 + .../0370-Reduce-sync-loads.patch | 350 ++ ...lement-alternative-item-despawn-rate.patch | 127 + ...if-we-have-a-custom-Bukkit-generator.patch | 42 + .../0373-Fix-MC-158900.patch | 25 + ...ement-optional-per-player-mob-spawns.patch | 924 ++++ ...revent-consuming-the-wrong-itemstack.patch | 52 + .../0376-Generator-Settings.patch | 89 + .../0377-Fix-MC-161754.patch | 23 + ...ce-improvement-for-Chunk.getEntities.patch | 35 + ...hanging-entities-that-are-not-ItemFr.patch | 25 + ...380-Expose-the-internal-current-tick.patch | 21 + ...-sneak-when-changing-worlds-MC-10657.patch | 32 + ...d-option-to-disable-pillager-patrols.patch | 32 + ...or-when-player-hand-set-to-empty-typ.patch | 35 + .../0384-PlayerLaunchProjectileEvent.patch | 351 ++ ...ftMagicNumbers.isSupportedApiVersion.patch | 22 + ...nk-loads-when-villagers-try-to-find-.patch | 20 + ...5656-Fix-Follow-Range-Initial-Target.patch | 73 + .../0388-Optimize-Hoppers.patch | 605 ++ ...layerDeathEvent-shouldDropExperience.patch | 19 + ...oading-chunks-checking-hive-position.patch | 18 + ...Chunks-from-Hoppers-and-other-things.patch | 32 + ...rializing-mismatching-chunk-coordina.patch | 62 + ...timise-IEntityAccess-getPlayerByUUID.patch | 44 + ...0394-Fix-items-not-falling-correctly.patch | 29 + .../0395-Lag-compensate-eating.patch | 83 + ...mize-call-to-getFluid-for-explosions.patch | 19 + ...k-in-stack-not-having-effects-when-d.patch | 23 + ...-Add-effect-to-block-break-naturally.patch | 32 + .../0399-Tracking-Range-Improvements.patch | 75 + .../0400-Entity-Activation-Range-2.0.patch | 908 +++ ...x-items-vanishing-through-end-portal.patch | 28 + ...get-gravity-in-void.-Fixes-MC-167279.patch | 55 + ...e-getChunkAt-calls-for-loaded-chunks.patch | 66 + ...ow-overriding-the-java-version-check.patch | 20 + .../0405-Add-ThrownEggHatchEvent.patch | 29 + .../0406-Optimise-random-block-ticking.patch | 407 ++ .../0407-Entity-Jump-API.patch | 59 + ...n-to-nerf-pigmen-from-nether-portals.patch | 71 + .../0409-Make-the-GUI-graph-fancier.patch | 439 ++ ...410-add-hand-to-BlockMultiPlaceEvent.patch | 30 + ...11-Prevent-teleporting-dead-entities.patch | 21 + ...ripwire-hook-placement-before-update.patch | 18 + ...to-allow-iron-golems-to-spawn-in-air.patch | 35 + ...-chance-of-villager-zombie-infection.patch | 44 + .../0415-Optimise-Chunk-getFluid.patch | 67 + ...imise-TickListServer-by-rewriting-it.patch | 1301 +++++ ...spawn-settings-and-per-player-option.patch | 155 + ...re-Entity-is-never-double-registered.patch | 79 + ...ering-entities-from-unloading-chunks.patch | 32 + ...nnections-shouldn-t-hold-up-shutdown.patch | 25 + ...low-bees-to-load-chunks-for-beehives.patch | 42 + ...-PlayerChunkMap-adds-crashing-server.patch | 48 + ...ptimize-Collision-to-not-load-chunks.patch | 185 + .../0424-Don-t-tick-dead-players.patch | 21 + ...d-Player-s-shouldn-t-be-able-to-move.patch | 21 + ...hunkMap-memory-use-for-visibleChunks.patch | 294 + .../0427-Increase-Light-Queue-Size.patch | 42 + ...asks-Speed-up-processing-of-chunk-lo.patch | 271 + ...move-existing-players-to-world-spawn.patch | 54 + ...-Add-tick-times-API-and-mspt-command.patch | 169 + ...431-Expose-MinecraftServer-isRunning.patch | 22 + ...Add-Raw-Byte-ItemStack-Serialization.patch | 102 + ...33-Remove-streams-from-Mob-AI-System.patch | 253 + ...ions-until-after-entity-ticking-is-d.patch | 45 + .../0435-Async-command-map-building.patch | 72 + .../0436-Improved-Watchdog-Support.patch | 608 +++ .../0437-Optimize-Pathfinding.patch | 61 + ...38-Reduce-Either-Optional-allocation.patch | 48 + ...0439-Remove-streams-from-PairedQueue.patch | 79 + ...e-memory-footprint-of-NBTTagCompound.patch | 59 + ...vent-opening-inventories-when-frozen.patch | 59 + ...442-Optimise-ArraySetSorted-removeIf.patch | 65 + ...-entity-collision-code-if-not-needed.patch | 30 + ...oviderServer-s-chunk-level-checking-.patch | 59 + ...-teleport-command-to-valid-locations.patch | 24 + ...-Implement-Player-Client-Options-API.patch | 188 + ...-Chunk-Post-Processing-deadlock-risk.patch | 60 + ...layer-is-attempted-to-be-removed-fro.patch | 23 + ...49-Broadcast-join-message-to-console.patch | 21 + ...g-Broken-behavior-of-PlayerJoinEvent.patch | 149 + ...Load-Chunks-for-Login-Asynchronously.patch | 416 ++ ...pawn-point-if-spawn-in-unloaded-worl.patch | 27 + ...PlayerAttackEntityCooldownResetEvent.patch | 28 + ...allbacks-to-schedule-for-Callback-Ex.patch | 58 + ...t-fire-BlockFade-on-worldgen-threads.patch | 28 + ...ntom-creative-and-insomniac-controls.patch | 74 + ...m-duplication-issues-and-teleport-is.patch | 117 + .../0458-Implement-Brigadier-Mojang-API.patch | 139 + .../0459-Villager-Restocks-API.patch | 42 + ...PickItem-Packet-and-kick-for-invalid.patch | 26 + .../0461-Expose-game-version.patch | 24 + .../0462-Optimize-Voxel-Shape-Merging.patch | 175 + ...-per-thread-native-byte-buffer-cache.patch | 30 + .../0464-Implement-Mob-Goal-API.patch | 1104 ++++ ...tance-map-to-optimise-entity-tracker.patch | 413 ++ ...-isOutsideRange-to-use-distance-maps.patch | 384 ++ ...te-operations-for-updating-light-dat.patch | 320 ++ ...No-Tick-view-distance-implementation.patch | 819 +++ .../0469-Add-villager-reputation-API.patch | 155 + .../0470-Fix-Light-Command.patch | 182 + ...1-Fix-PotionEffect-ignores-icon-flag.patch | 19 + ...-brigadier-child-sorting-performance.patch | 29 + .../0473-Potential-bed-API.patch | 44 + ...Wait-for-Async-Tasks-during-shutdown.patch | 63 + ...der-respects-game-and-entity-rules-f.patch | 28 + ...and-End-Portal-Frames-from-being-des.patch | 173 + ...ze-NibbleArray-to-use-pooled-buffers.patch | 394 ++ ...bleInt-allocations-from-light-engine.patch | 50 + ...llocation-of-Vec3D-by-entity-tracker.patch | 69 + .../0480-Ensure-safe-gateway-teleport.patch | 27 + ...n-for-console-having-all-permissions.patch | 74 + ...on-Full-Status-Chunk-NBT-Memory-Leak.patch | 99 + ...ound-for-Client-Lag-Spikes-MC-162253.patch | 137 + ...k-Priority-Urgency-System-for-Chunks.patch | 1352 +++++ ...-packets-to-nearby-locations-sounds-.patch | 63 + ...mprove-Chunk-Status-Transition-Speed.patch | 99 + ...ix-villager-trading-demand-MC-163962.patch | 20 + .../0488-Maps-shouldn-t-load-chunks.patch | 32 + ...ookup-for-Treasure-Maps-Fixes-lag-fr.patch | 35 + ...-Optimize-Bit-Operations-by-inlining.patch | 220 + .../0491-Optimize-Light-Engine.patch | 1464 +++++ ...unk-Unloads-based-on-Player-Movement.patch | 107 + ...-Plugin-Tickets-to-API-Chunk-Methods.patch | 129 + ...ssing-chunks-due-to-integer-overflow.patch | 29 + ...er-runTaskTimerAsynchronously-Plugin.patch | 21 + ...ston-physics-inconsistency-MC-188840.patch | 93 + .../0497-Fix-sand-duping.patch | 37 + ...-desync-in-playerconnection-causing-.patch | 31 + .../0499-Fix-enderdragon-exp-dupe.patch | 28 + ...Holder-method-without-block-snapshot.patch | 50 + .../0501-Expose-Arrow-getItemStack.patch | 36 + ...implement-PlayerRecipeBookClickEvent.patch | 29 + ...3-Hide-sync-chunk-writes-behind-flag.patch | 23 + ...mit-lightning-strike-effect-distance.patch | 76 + ...05-Add-permission-for-command-blocks.patch | 79 + ...sure-Entity-AABB-s-are-never-invalid.patch | 48 + ...WorldBorder-collision-checks-and-air.patch | 71 + ...ld-Difficulty-Remembering-Difficulty.patch | 86 + .../0509-Paper-dumpitem-command.patch | 80 + ...510-Don-t-allow-null-UUID-s-for-chat.patch | 27 + ...-Legacy-Component-serialization-size.patch | 56 + ...0512-Support-old-UUID-format-for-NBT.patch | 64 + ...up-duplicated-GameProfile-Properties.patch | 68 + ...nvert-legacy-attributes-in-Item-Meta.patch | 44 + ...-Remove-some-streams-from-structures.patch | 143 + ...from-classes-related-villager-gossip.patch | 100 + .../0517-Support-components-in-ItemMeta.patch | 83 + ...argetLivingEntityEvent-for-1.16-mobs.patch | 62 + .../0519-Add-entity-liquid-API.patch | 75 + ...pdate-itemstack-legacy-name-and-lore.patch | 79 + ...awn-player-in-correct-world-on-login.patch | 30 + .../0522-Add-PrepareResultEvent.patch | 164 + ...llow-delegation-to-vanilla-chunk-gen.patch | 104 + ...k-for-portal-on-world-gen-entity-add.patch | 19 + ...ze-NetworkManager-Exception-Handling.patch | 117 + ...ix-Concurrency-issue-in-WeightedList.patch | 153 + ...ancement-data-player-iteration-to-be.patch | 54 + ...ix-arrows-never-despawning-MC-125757.patch | 30 + ...-Vanilla-Command-permission-checking.patch | 53 + ...ove-range-check-for-block-placing-up.patch | 35 + .../0531-Fix-SPIGOT-5989.patch | 69 + ...4-Bukkit-world-container-is-not-used.patch | 33 + ...-5885-Unable-to-disable-advancements.patch | 18 + ...ataPlayer-leak-due-from-quitting-ear.patch | 94 + ...keLighting-call-to-World-spigot-stri.patch | 19 + ...Fix-some-rails-connecting-improperly.patch | 95 + ...der-Remove-Streams-Optimized-collect.patch | 159 + .../0538-Incremental-player-saving.patch | 95 + .../0539-Import-fastutil-classes.patch | 27 + ...ull-chunk-sections-for-block-updates.patch | 18 + ...ove-armour-stand-double-add-to-world.patch | 28 + ...-Fix-MC-187716-Use-configured-height.patch | 45 + ...istake-in-CB-NBT-int-deserialization.patch | 27 + ...erver-load-chunks-from-newer-version.patch | 39 + .../0545-Brand-support.patch | 92 + ...her-Boss-Bar-doesn-t-update-until-in.patch | 22 + .../0547-Fix-MC-197271.patch | 51 + .../0548-MC-197883-Bandaid-decode-issue.patch | 28 + .../0549-Add-setMaxPlayers-API.patch | 37 + ...yPickupItemAnimation-to-LivingEntity.patch | 21 + .../0551-Don-t-require-FACING-data.patch | 35 + ...geEvent-not-firing-for-all-use-cases.patch | 46 + .../0553-Add-moon-phase-API.patch | 22 + ...-headless-pistons-from-being-created.patch | 74 + .../0555-Add-BellRingEvent.patch | 58 + ...Add-zombie-targets-turtle-egg-config.patch | 33 + .../0557-Buffer-joins-to-world.patch | 71 + .../0558-Optimize-redstone-algorithm.patch | 1157 ++++ ...rs-not-working-in-some-kick-messages.patch | 64 + ...CreateEvent-needs-to-know-its-entity.patch | 147 + .../0561-Fix-CraftTeam-null-check.patch | 19 + .../0562-Add-more-Evoker-API.patch | 57 + ...-translation-keys-for-blocks-entitie.patch | 126 + ...ate-HoverEvent-from-ItemStack-Entity.patch | 51 + .../0565-Cache-block-data-strings.patch | 70 + ...ortation-and-cancel-velocity-if-tele.patch | 83 + ...al-open-container-api-to-HumanEntity.patch | 81 + ...taFixerUpper-Rewrite-Rules-on-demand.patch | 54 + ...p-capture-to-capture-all-items-added.patch | 60 + ...rty-in-invalid-locations-SPIGOT-6086.patch | 18 + ...y-Counter-to-allow-plugins-to-use-va.patch | 37 + ...-track-plugin-scoreboards-by-default.patch | 102 + .../0573-Entity-isTicking.patch | 42 + ...-non-whitelisted-player-when-white-l.patch | 19 + ...Fix-Not-a-string-Map-Conversion-spam.patch | 52 + ...ng-a-passenger-in-CreatureSpawnEvent.patch | 19 + ...tems-that-are-extra-from-a-crafting-.patch | 24 + ...Reset-Ender-Crystals-on-Dragon-Spawn.patch | 24 + ...r-large-move-vectors-crashing-server.patch | 66 + .../0580-Optimise-getType-calls.patch | 96 + .../0581-Villager-resetOffers.patch | 48 + ...inig-for-some-hot-IBlockData-methods.patch | 101 + ...ace-order-when-capturing-blockstates.patch | 24 + ...blockpos-allocation-from-pathfinding.patch | 28 + ...tem-locations-dropped-from-campfires.patch | 32 + .../0586-Player-elytra-boost-API.patch | 39 + ...587-Fixed-TileEntityBell-memory-leak.patch | 56 + ...ling-up-when-item-stack-is-empty-in-.patch | 46 + ...-Add-getOfflinePlayerIfCached-String.patch | 39 + .../0590-Add-ignore-discounts-API.patch | 143 + ...-Toggle-for-removing-existing-dragon.patch | 36 + ...ix-client-lag-on-advancement-loading.patch | 55 + .../0593-Item-no-age-no-player-pickup.patch | 50 + ...0594-Beacon-API-custom-effect-ranges.patch | 90 + .../0595-Add-API-for-quit-reason.patch | 63 + .../0596-Seed-based-feature-search.patch | 115 + ...ing-Trader-spawn-rate-config-options.patch | 120 + ...prove-performance-of-the-end-generat.patch | 77 + .../0599-Expose-world-spawn-angle.patch | 44 + .../0600-Add-Destroy-Speed-API.patch | 35 + ...r-spawnParticle-x-y-z-precision-loss.patch | 19 + ...602-Add-LivingEntity-clearActiveItem.patch | 24 + .../0603-Add-PlayerItemCooldownEvent.patch | 39 + .../0604-More-lightning-API.patch | 68 + ...-should-not-bypass-cramming-gamerule.patch | 179 + ...d-missing-default-perms-for-commands.patch | 70 + .../0607-Add-PlayerShearBlockEvent.patch | 116 + ...g-for-servers-not-running-on-Java-16.patch | 80 + ...erbose-world-setting-to-false-by-def.patch | 19 + ...ing-zombie-villager-discount-exploit.patch | 55 + .../0611-Limit-recipe-packets.patch | 74 + ...x-CraftSound-backwards-compatibility.patch | 21 + .../0613-MC-4-Fix-item-position-desync.patch | 84 + ...0614-Player-Chunk-Load-Unload-Events.patch | 41 + ...15-Optimize-Dynamic-get-Missing-Keys.patch | 34 + ...6-Expose-LivingEntity-hurt-direction.patch | 39 + ...-OBSTRUCTED-reason-to-BedEnterResult.patch | 21 + ...m-invalid-ingredient-lists-in-Villag.patch | 24 + .../0619-added-PlayerTradeEvent.patch | 75 + .../0620-Implement-TargetHitEvent.patch | 58 + ...0621-Additional-Block-Material-API-s.patch | 40 + .../0622-Fix-harming-potion-dupe.patch | 59 + ...-get-Material-from-Boats-and-Minecar.patch | 100 + .../0624-Optimized-tick-ready-check.patch | 51 + .../0625-Cache-burn-durations.patch | 63 + ...mob-spawner-spawn-egg-transformation.patch | 33 + ...ement-PlayerFlowerPotManipulateEvent.patch | 46 + ...-event-not-being-called-in-adventure.patch | 29 + .../0629-Zombie-API-breaking-doors.patch | 44 + ...0630-Fix-nerfed-slime-when-splitting.patch | 18 + .../0631-Add-EntityLoadCrossbowEvent.patch | 60 + .../0632-Guardian-beam-workaround.patch | 30 + .../0633-Added-WorldGameRuleChangeEvent.patch | 110 + ...4-Added-ServerResourcesReloadedEvent.patch | 90 + ...ld-settings-for-mobs-picking-up-loot.patch | 51 + ...Implemented-BlockFailedDispenseEvent.patch | 63 + ...7-Added-PlayerLecternPageChangeEvent.patch | 66 + .../0638-Fire-event-on-GS4-query.patch | 265 + ...9-Added-PlayerLoomPatternSelectEvent.patch | 63 + ...onfigurable-door-breaking-difficulty.patch | 100 + ...pty-commands-shall-not-be-dispatched.patch | 18 + ...PI-to-expose-exact-interaction-point.patch | 59 + .../0643-Remove-stale-POIs.patch | 50 + .../0644-Fix-villager-boat-exploit.patch | 34 + ...645-Entity-load-save-limit-per-chunk.patch | 90 + .../0646-Add-sendOpLevel-API.patch | 65 + .../0647-Add-StructureLocateEvent.patch | 41 + ...n-for-requiring-a-player-participant.patch | 81 + ...ileHitEvent-call-when-fireballs-dead.patch | 21 + ...onent-with-empty-text-instead-of-thr.patch | 33 + ...0651-Make-schedule-command-per-world.patch | 37 + ...0652-Configurable-max-leash-distance.patch | 45 + ...0653-Implement-BlockPreDispenseEvent.patch | 42 + .../0654-Added-Vanilla-Entity-Tags.patch | 93 + .../0655-added-Wither-API.patch | 75 + ...ing-of-PlayerChangeBeaconEffectEvent.patch | 39 + ...e-spam-when-removing-chests-in-water.patch | 19 + ...le-for-always-placing-the-dragon-egg.patch | 33 + ...d-PlayerStonecutterRecipeSelectEvent.patch | 109 + ...Leash-variable-to-EntityUnleashEvent.patch | 156 + ...ce-map-update-when-spawning-disabled.patch | 19 + ...-shield-blocking-on-dimension-change.patch | 22 + .../0663-add-DragonEggFormEvent.patch | 117 + .../0664-EntityMoveEvent.patch | 71 + ...disable-pathfinding-updates-on-block.patch | 40 + .../0666-Inline-shift-direction-fields.patch | 55 + ...w-adding-items-to-BlockDropItemEvent.patch | 44 + ...ainThreadExecutor-to-BukkitScheduler.patch | 26 + ...-entity-allow-attribute-registration.patch | 69 + ...fix-dead-slime-setSize-invincibility.patch | 19 + ...ipes-should-return-an-immutable-list.patch | 19 + .../0672-misc-debugging-dumps.patch | 87 + ...pport-for-hex-color-codes-in-console.patch | 221 + .../0674-Clear-SyncLoadInfo.patch | 40 + .../0675-Expose-Tracked-Players.patch | 53 + ...76-Remove-streams-from-SensorNearest.patch | 120 + ...unnecessary-copies-of-passenger-list.patch | 239 + ...Fix-Wither-hostility-towards-players.patch | 33 + ...per-exception-on-empty-JsonList-file.patch | 18 + .../0680-Improve-ServerGUI.patch | 400 ++ ...sure-plate-EntityInteractEvent-for-i.patch | 19 + ...0682-fix-converting-txt-to-json-file.patch | 74 + .../0683-Add-worldborder-events.patch | 122 + .../0684-added-PlayerNameEntityEvent.patch | 41 + ...-grindstones-from-overstacking-items.patch | 26 + .../0686-Add-recipe-to-cook-events.patch | 44 + .../0687-Add-Block-isValidTool.patch | 20 + ...-using-signs-inside-spawn-protection.patch | 41 + .../0689-Implement-Keyed-on-World.patch | 110 + ...alternative-constructor-for-Vector3f.patch | 30 + .../0691-Item-Rarity-API.patch | 52 + ...Timer-for-Wandering-Traders-spawned-.patch | 58 + ...opy-TESign-isEditable-from-snapshots.patch | 18 + ...ed-item-when-player-has-disconnected.patch | 35 + ...telist-use-configurable-kick-message.patch | 27 + ...-to-remove-correct-TE-during-TE-tick.patch | 45 + ...ignore-result-of-PlayerEditBookEvent.patch | 19 + ...-block-falling-causing-client-desync.patch | 59 + .../0699-Expose-protocol-version.patch | 22 + ...ent-suggestion-tooltips-in-AsyncTabC.patch | 132 + ...tab-completions-for-brigadier-comman.patch | 316 ++ ...ItemConsumeEvent-cancelling-properly.patch | 22 + .../0703-Add-bypass-host-check.patch | 30 + ...don-t-throw-when-loading-invalid-TEs.patch | 33 + .../0705-Set-area-affect-cloud-rotation.patch | 18 + ...-add-isDeeplySleeping-to-HumanEntity.patch | 24 + ...ating-give-items-on-item-drop-cancel.patch | 113 + ...-add-consumeFuel-to-FurnaceBurnEvent.patch | 19 + ...t-set-drop-chance-to-EntityEquipment.patch | 48 + ...fix-PigZombieAngerEvent-cancellation.patch | 47 + ...x-checkReach-check-for-Shulker-boxes.patch | 18 + ...fix-PlayerItemHeldEvent-firing-twice.patch | 30 + .../0713-Added-PlayerDeepSleepEvent.patch | 22 + .../0714-More-World-API.patch | 146 + .../0715-Added-PlayerBedFailEnterEvent.patch | 57 + ...s-to-convert-between-Component-and-B.patch | 55 + ...wn-acting-as-a-bed-respawn-from-the-.patch | 36 + ...d-RespawnFlags-to-PlayerRespawnEvent.patch | 46 + ...eacon-activation-deactivation-events.patch | 37 + ...Add-Channel-initialization-listeners.patch | 119 + ...mmands-if-tab-completion-is-disabled.patch | 24 + .../0722-Add-more-WanderingTrader-API.patch | 65 + ...Add-EntityBlockStorage-clearEntities.patch | 37 + ...essage-to-PlayerAdvancementDoneEvent.patch | 89 + ...-address-to-AsyncPlayerPreLoginEvent.patch | 25 + .../0726-Inventory-close.patch | 25 + ...CreateEvent-players-and-end-platform.patch | 45 + ...n-in-sunlight-API-for-Phantoms-and-S.patch | 126 + .../0729-Fix-CraftPotionBrewer-cache.patch | 44 + .../0730-Add-basic-Datapack-API.patch | 174 + ...nment-variable-to-disable-server-gui.patch | 18 + ...ditions-to-PlayerGameModeChangeEvent.patch | 138 + .../0733-ItemStack-repair-check-API.patch | 91 + .../0734-More-Enchantment-API.patch | 211 + ...-option-to-load-extra-plugin-jars-no.patch | 64 + ...atus-dataconverter-for-pre-1.13-chun.patch | 91 + ...crease-structure-block-data-length-t.patch | 19 + ...x-and-optimise-world-force-upgrading.patch | 411 ++ .../0739-Add-Mob-lookAt-API.patch | 127 + .../0740-Add-Unix-domain-socket-support.patch | 141 + .../0741-Add-EntityInsideBlockEvent.patch | 222 + ...742-Attributes-API-for-item-defaults.patch | 42 + ...chantCustom-emit-PlayerPurchaseEvent.patch | 59 + ...cause-to-Weather-ThunderChangeEvents.patch | 136 + .../0745-More-Lidded-Block-API.patch | 127 + .../0746-Add-PlayerKickEvent-causes.patch | 393 ++ ...747-Limit-item-frame-cursors-on-maps.patch | 37 + .../0748-Add-PufferFishStateChangeEvent.patch | 50 + ...yerBucketEmptyEvent-result-itemstack.patch | 43 + ...n-to-fix-items-merging-through-walls.patch | 39 + .../0751-Add-BellRevealRaiderEvent.patch | 26 + .../0752-Fix-invulnerable-end-crystals.patch | 105 + ...753-Add-ElderGuardianAppearanceEvent.patch | 23 + ...-inventory-on-cancelled-pickup-event.patch | 62 + .../0755-Fix-dangerous-end-portal-logic.patch | 107 + ...6-Make-item-validations-configurable.patch | 83 + .../0757-Add-more-line-of-sight-methods.patch | 62 + .../0758-add-per-world-spawn-limits.patch | 49 + ...SplashEvent-for-water-splash-potions.patch | 63 + 759 files changed, 87847 insertions(+) create mode 100644 Remapped-Spigot-Server-Patches/0001-POM-Changes.patch create mode 100644 Remapped-Spigot-Server-Patches/0002-Paper-config-files.patch create mode 100644 Remapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch create mode 100644 Remapped-Spigot-Server-Patches/0004-MC-Utils.patch create mode 100644 Remapped-Spigot-Server-Patches/0005-Paper-Metrics.patch create mode 100644 Remapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch create mode 100644 Remapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch create mode 100644 Remapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch create mode 100644 Remapped-Spigot-Server-Patches/0009-Timings-v2.patch create mode 100644 Remapped-Spigot-Server-Patches/0010-Adventure.patch create mode 100644 Remapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch create mode 100644 Remapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch create mode 100644 Remapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch create mode 100644 Remapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch create mode 100644 Remapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch create mode 100644 Remapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch create mode 100644 Remapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch create mode 100644 Remapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch create mode 100644 Remapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch create mode 100644 Remapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch create mode 100644 Remapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch create mode 100644 Remapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch create mode 100644 Remapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch create mode 100644 Remapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch create mode 100644 Remapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch create mode 100644 Remapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch create mode 100644 Remapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch create mode 100644 Remapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch create mode 100644 Remapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch create mode 100644 Remapped-Spigot-Server-Patches/0033-Optimize-explosions.patch create mode 100644 Remapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch create mode 100644 Remapped-Spigot-Server-Patches/0035-Disable-thunder.patch create mode 100644 Remapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch create mode 100644 Remapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch create mode 100644 Remapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch create mode 100644 Remapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch create mode 100644 Remapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch create mode 100644 Remapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch create mode 100644 Remapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch create mode 100644 Remapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch create mode 100644 Remapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch create mode 100644 Remapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch create mode 100644 Remapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch create mode 100644 Remapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch create mode 100644 Remapped-Spigot-Server-Patches/0050-Ensure-inv-drag-is-in-bounds.patch create mode 100644 Remapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch create mode 100644 Remapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch create mode 100644 Remapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch create mode 100644 Remapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch create mode 100644 Remapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch create mode 100644 Remapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch create mode 100644 Remapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch create mode 100644 Remapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch create mode 100644 Remapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch create mode 100644 Remapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch create mode 100644 Remapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch create mode 100644 Remapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch create mode 100644 Remapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch create mode 100644 Remapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch create mode 100644 Remapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch create mode 100644 Remapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch create mode 100644 Remapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch create mode 100644 Remapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch create mode 100644 Remapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch create mode 100644 Remapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch create mode 100644 Remapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch create mode 100644 Remapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch create mode 100644 Remapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch create mode 100644 Remapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch create mode 100644 Remapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch create mode 100644 Remapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch create mode 100644 Remapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch create mode 100644 Remapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch create mode 100644 Remapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch create mode 100644 Remapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch create mode 100644 Remapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch create mode 100644 Remapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch create mode 100644 Remapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch create mode 100644 Remapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch create mode 100644 Remapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch create mode 100644 Remapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch create mode 100644 Remapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch create mode 100644 Remapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch create mode 100644 Remapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch create mode 100644 Remapped-Spigot-Server-Patches/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch create mode 100644 Remapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch create mode 100644 Remapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch create mode 100644 Remapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch create mode 100644 Remapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch create mode 100644 Remapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch create mode 100644 Remapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch create mode 100644 Remapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch create mode 100644 Remapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch create mode 100644 Remapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch create mode 100644 Remapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch create mode 100644 Remapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch create mode 100644 Remapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch create mode 100644 Remapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch create mode 100644 Remapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch create mode 100644 Remapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch create mode 100644 Remapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch create mode 100644 Remapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch create mode 100644 Remapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch create mode 100644 Remapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch create mode 100644 Remapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch create mode 100644 Remapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch create mode 100644 Remapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch create mode 100644 Remapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch create mode 100644 Remapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch create mode 100644 Remapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch create mode 100644 Remapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch create mode 100644 Remapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch create mode 100644 Remapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch create mode 100644 Remapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch create mode 100644 Remapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch create mode 100644 Remapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch create mode 100644 Remapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch create mode 100644 Remapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0132-Firework-API-s.patch create mode 100644 Remapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch create mode 100644 Remapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch create mode 100644 Remapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch create mode 100644 Remapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch create mode 100644 Remapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch create mode 100644 Remapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch create mode 100644 Remapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch create mode 100644 Remapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch create mode 100644 Remapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch create mode 100644 Remapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch create mode 100644 Remapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch create mode 100644 Remapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch create mode 100644 Remapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch create mode 100644 Remapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch create mode 100644 Remapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch create mode 100644 Remapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch create mode 100644 Remapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch create mode 100644 Remapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch create mode 100644 Remapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch create mode 100644 Remapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch create mode 100644 Remapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch create mode 100644 Remapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch create mode 100644 Remapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch create mode 100644 Remapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch create mode 100644 Remapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch create mode 100644 Remapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch create mode 100644 Remapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch create mode 100644 Remapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch create mode 100644 Remapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch create mode 100644 Remapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch create mode 100644 Remapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch create mode 100644 Remapped-Spigot-Server-Patches/0172-revert-serverside-behavior-of-keepalives.patch create mode 100644 Remapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch create mode 100644 Remapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch create mode 100644 Remapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch create mode 100644 Remapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch create mode 100644 Remapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch create mode 100644 Remapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch create mode 100644 Remapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch create mode 100644 Remapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch create mode 100644 Remapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch create mode 100644 Remapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch create mode 100644 Remapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch create mode 100644 Remapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch create mode 100644 Remapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch create mode 100644 Remapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch create mode 100644 Remapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch create mode 100644 Remapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch create mode 100644 Remapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch create mode 100644 Remapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch create mode 100644 Remapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch create mode 100644 Remapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch create mode 100644 Remapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch create mode 100644 Remapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch create mode 100644 Remapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch create mode 100644 Remapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch create mode 100644 Remapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch create mode 100644 Remapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch create mode 100644 Remapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch create mode 100644 Remapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch create mode 100644 Remapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch create mode 100644 Remapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch create mode 100644 Remapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch create mode 100644 Remapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch create mode 100644 Remapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch create mode 100644 Remapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0230-RangedEntity-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch create mode 100644 Remapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch create mode 100644 Remapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch create mode 100644 Remapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch create mode 100644 Remapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch create mode 100644 Remapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch create mode 100644 Remapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch create mode 100644 Remapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch create mode 100644 Remapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch create mode 100644 Remapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch create mode 100644 Remapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch create mode 100644 Remapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch create mode 100644 Remapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch create mode 100644 Remapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch create mode 100644 Remapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch create mode 100644 Remapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch create mode 100644 Remapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch create mode 100644 Remapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch create mode 100644 Remapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch create mode 100644 Remapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch create mode 100644 Remapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch create mode 100644 Remapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch create mode 100644 Remapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch create mode 100644 Remapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch create mode 100644 Remapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch create mode 100644 Remapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch create mode 100644 Remapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch create mode 100644 Remapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch create mode 100644 Remapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch create mode 100644 Remapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch create mode 100644 Remapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch create mode 100644 Remapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch create mode 100644 Remapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch create mode 100644 Remapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch create mode 100644 Remapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch create mode 100644 Remapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch create mode 100644 Remapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch create mode 100644 Remapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch create mode 100644 Remapped-Spigot-Server-Patches/0279-Improve-death-events.patch create mode 100644 Remapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch create mode 100644 Remapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch create mode 100644 Remapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch create mode 100644 Remapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch create mode 100644 Remapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch create mode 100644 Remapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch create mode 100644 Remapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch create mode 100644 Remapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch create mode 100644 Remapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch create mode 100644 Remapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0295-Turtle-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch create mode 100644 Remapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch create mode 100644 Remapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch create mode 100644 Remapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch create mode 100644 Remapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch create mode 100644 Remapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch create mode 100644 Remapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch create mode 100644 Remapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch create mode 100644 Remapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch create mode 100644 Remapped-Spigot-Server-Patches/0306-Optimize-World-Time-Updates.patch create mode 100644 Remapped-Spigot-Server-Patches/0307-Restore-custom-InventoryHolder-support.patch create mode 100644 Remapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch create mode 100644 Remapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch create mode 100644 Remapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch create mode 100644 Remapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch create mode 100644 Remapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch create mode 100644 Remapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch create mode 100644 Remapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch create mode 100644 Remapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch create mode 100644 Remapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch create mode 100644 Remapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch create mode 100644 Remapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch create mode 100644 Remapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch create mode 100644 Remapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch create mode 100644 Remapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch create mode 100644 Remapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch create mode 100644 Remapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch create mode 100644 Remapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch create mode 100644 Remapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch create mode 100644 Remapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch create mode 100644 Remapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch create mode 100644 Remapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch create mode 100644 Remapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch create mode 100644 Remapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch create mode 100644 Remapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch create mode 100644 Remapped-Spigot-Server-Patches/0341-PlayerDeathEvent-getItemsToKeep.patch create mode 100644 Remapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch create mode 100644 Remapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch create mode 100644 Remapped-Spigot-Server-Patches/0345-Per-Player-View-Distance-API-placeholders.patch create mode 100644 Remapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch create mode 100644 Remapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch create mode 100644 Remapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch create mode 100644 Remapped-Spigot-Server-Patches/0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch create mode 100644 Remapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch create mode 100644 Remapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch create mode 100644 Remapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch create mode 100644 Remapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch create mode 100644 Remapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch create mode 100644 Remapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch create mode 100644 Remapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch create mode 100644 Remapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch create mode 100644 Remapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch create mode 100644 Remapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch create mode 100644 Remapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch create mode 100644 Remapped-Spigot-Server-Patches/0362-Anti-Xray.patch create mode 100644 Remapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch create mode 100644 Remapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch create mode 100644 Remapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch create mode 100644 Remapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch create mode 100644 Remapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch create mode 100644 Remapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch create mode 100644 Remapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch create mode 100644 Remapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch create mode 100644 Remapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch create mode 100644 Remapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch create mode 100644 Remapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch create mode 100644 Remapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch create mode 100644 Remapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch create mode 100644 Remapped-Spigot-Server-Patches/0376-Generator-Settings.patch create mode 100644 Remapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch create mode 100644 Remapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch create mode 100644 Remapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch create mode 100644 Remapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch create mode 100644 Remapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch create mode 100644 Remapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch create mode 100644 Remapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch create mode 100644 Remapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch create mode 100644 Remapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch create mode 100644 Remapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch create mode 100644 Remapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch create mode 100644 Remapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch create mode 100644 Remapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch create mode 100644 Remapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch create mode 100644 Remapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch create mode 100644 Remapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch create mode 100644 Remapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch create mode 100644 Remapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch create mode 100644 Remapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch create mode 100644 Remapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch create mode 100644 Remapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch create mode 100644 Remapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch create mode 100644 Remapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch create mode 100644 Remapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch create mode 100644 Remapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch create mode 100644 Remapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch create mode 100644 Remapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch create mode 100644 Remapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch create mode 100644 Remapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch create mode 100644 Remapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch create mode 100644 Remapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch create mode 100644 Remapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch create mode 100644 Remapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch create mode 100644 Remapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch create mode 100644 Remapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch create mode 100644 Remapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch create mode 100644 Remapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch create mode 100644 Remapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch create mode 100644 Remapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch create mode 100644 Remapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch create mode 100644 Remapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch create mode 100644 Remapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch create mode 100644 Remapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch create mode 100644 Remapped-Spigot-Server-Patches/0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch create mode 100644 Remapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch create mode 100644 Remapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch create mode 100644 Remapped-Spigot-Server-Patches/0431-Expose-MinecraftServer-isRunning.patch create mode 100644 Remapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch create mode 100644 Remapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch create mode 100644 Remapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch create mode 100644 Remapped-Spigot-Server-Patches/0435-Async-command-map-building.patch create mode 100644 Remapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch create mode 100644 Remapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch create mode 100644 Remapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch create mode 100644 Remapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch create mode 100644 Remapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch create mode 100644 Remapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch create mode 100644 Remapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch create mode 100644 Remapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch create mode 100644 Remapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch create mode 100644 Remapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch create mode 100644 Remapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch create mode 100644 Remapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch create mode 100644 Remapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch create mode 100644 Remapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch create mode 100644 Remapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch create mode 100644 Remapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch create mode 100644 Remapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch create mode 100644 Remapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch create mode 100644 Remapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch create mode 100644 Remapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch create mode 100644 Remapped-Spigot-Server-Patches/0461-Expose-game-version.patch create mode 100644 Remapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch create mode 100644 Remapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch create mode 100644 Remapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch create mode 100644 Remapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch create mode 100644 Remapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch create mode 100644 Remapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch create mode 100644 Remapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch create mode 100644 Remapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch create mode 100644 Remapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch create mode 100644 Remapped-Spigot-Server-Patches/0473-Potential-bed-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch create mode 100644 Remapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch create mode 100644 Remapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch create mode 100644 Remapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch create mode 100644 Remapped-Spigot-Server-Patches/0478-Reduce-MutableInt-allocations-from-light-engine.patch create mode 100644 Remapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch create mode 100644 Remapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch create mode 100644 Remapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch create mode 100644 Remapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch create mode 100644 Remapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch create mode 100644 Remapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch create mode 100644 Remapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch create mode 100644 Remapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch create mode 100644 Remapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch create mode 100644 Remapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch create mode 100644 Remapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch create mode 100644 Remapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch create mode 100644 Remapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch create mode 100644 Remapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch create mode 100644 Remapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch create mode 100644 Remapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch create mode 100644 Remapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch create mode 100644 Remapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch create mode 100644 Remapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch create mode 100644 Remapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch create mode 100644 Remapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch create mode 100644 Remapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch create mode 100644 Remapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch create mode 100644 Remapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch create mode 100644 Remapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch create mode 100644 Remapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch create mode 100644 Remapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch create mode 100644 Remapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch create mode 100644 Remapped-Spigot-Server-Patches/0509-Paper-dumpitem-command.patch create mode 100644 Remapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch create mode 100644 Remapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch create mode 100644 Remapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch create mode 100644 Remapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch create mode 100644 Remapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch create mode 100644 Remapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch create mode 100644 Remapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch create mode 100644 Remapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch create mode 100644 Remapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch create mode 100644 Remapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch create mode 100644 Remapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch create mode 100644 Remapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch create mode 100644 Remapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch create mode 100644 Remapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch create mode 100644 Remapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch create mode 100644 Remapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch create mode 100644 Remapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch create mode 100644 Remapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch create mode 100644 Remapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch create mode 100644 Remapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch create mode 100644 Remapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch create mode 100644 Remapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch create mode 100644 Remapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch create mode 100644 Remapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch create mode 100644 Remapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch create mode 100644 Remapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch create mode 100644 Remapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch create mode 100644 Remapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch create mode 100644 Remapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch create mode 100644 Remapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch create mode 100644 Remapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch create mode 100644 Remapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch create mode 100644 Remapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch create mode 100644 Remapped-Spigot-Server-Patches/0545-Brand-support.patch create mode 100644 Remapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch create mode 100644 Remapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch create mode 100644 Remapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch create mode 100644 Remapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch create mode 100644 Remapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch create mode 100644 Remapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch create mode 100644 Remapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch create mode 100644 Remapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch create mode 100644 Remapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch create mode 100644 Remapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch create mode 100644 Remapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch create mode 100644 Remapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch create mode 100644 Remapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch create mode 100644 Remapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch create mode 100644 Remapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch create mode 100644 Remapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch create mode 100644 Remapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch create mode 100644 Remapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch create mode 100644 Remapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch create mode 100644 Remapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch create mode 100644 Remapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch create mode 100644 Remapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch create mode 100644 Remapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch create mode 100644 Remapped-Spigot-Server-Patches/0573-Entity-isTicking.patch create mode 100644 Remapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch create mode 100644 Remapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch create mode 100644 Remapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch create mode 100644 Remapped-Spigot-Server-Patches/0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch create mode 100644 Remapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch create mode 100644 Remapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch create mode 100644 Remapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch create mode 100644 Remapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch create mode 100644 Remapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch create mode 100644 Remapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch create mode 100644 Remapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch create mode 100644 Remapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch create mode 100644 Remapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch create mode 100644 Remapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch create mode 100644 Remapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch create mode 100644 Remapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch create mode 100644 Remapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch create mode 100644 Remapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch create mode 100644 Remapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch create mode 100644 Remapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch create mode 100644 Remapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch create mode 100644 Remapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch create mode 100644 Remapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch create mode 100644 Remapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch create mode 100644 Remapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch create mode 100644 Remapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0604-More-lightning-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch create mode 100644 Remapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch create mode 100644 Remapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch create mode 100644 Remapped-Spigot-Server-Patches/0609-Set-spigots-verbose-world-setting-to-false-by-def.patch create mode 100644 Remapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch create mode 100644 Remapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch create mode 100644 Remapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch create mode 100644 Remapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch create mode 100644 Remapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch create mode 100644 Remapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch create mode 100644 Remapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch create mode 100644 Remapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch create mode 100644 Remapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch create mode 100644 Remapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch create mode 100644 Remapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch create mode 100644 Remapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch create mode 100644 Remapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch create mode 100644 Remapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch create mode 100644 Remapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch create mode 100644 Remapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch create mode 100644 Remapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch create mode 100644 Remapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch create mode 100644 Remapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch create mode 100644 Remapped-Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch create mode 100644 Remapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch create mode 100644 Remapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch create mode 100644 Remapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch create mode 100644 Remapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch create mode 100644 Remapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch create mode 100644 Remapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch create mode 100644 Remapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch create mode 100644 Remapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch create mode 100644 Remapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch create mode 100644 Remapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch create mode 100644 Remapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch create mode 100644 Remapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch create mode 100644 Remapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch create mode 100644 Remapped-Spigot-Server-Patches/0655-added-Wither-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch create mode 100644 Remapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch create mode 100644 Remapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch create mode 100644 Remapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch create mode 100644 Remapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0664-EntityMoveEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch create mode 100644 Remapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch create mode 100644 Remapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch create mode 100644 Remapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch create mode 100644 Remapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch create mode 100644 Remapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch create mode 100644 Remapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch create mode 100644 Remapped-Spigot-Server-Patches/0673-Add-support-for-hex-color-codes-in-console.patch create mode 100644 Remapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch create mode 100644 Remapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch create mode 100644 Remapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch create mode 100644 Remapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch create mode 100644 Remapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch create mode 100644 Remapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch create mode 100644 Remapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch create mode 100644 Remapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch create mode 100644 Remapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch create mode 100644 Remapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch create mode 100644 Remapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch create mode 100644 Remapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch create mode 100644 Remapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch create mode 100644 Remapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch create mode 100644 Remapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch create mode 100644 Remapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch create mode 100644 Remapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch create mode 100644 Remapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch create mode 100644 Remapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch create mode 100644 Remapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch create mode 100644 Remapped-Spigot-Server-Patches/0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch create mode 100644 Remapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch create mode 100644 Remapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch create mode 100644 Remapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch create mode 100644 Remapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch create mode 100644 Remapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch create mode 100644 Remapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch create mode 100644 Remapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch create mode 100644 Remapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch create mode 100644 Remapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch create mode 100644 Remapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch create mode 100644 Remapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch create mode 100644 Remapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch create mode 100644 Remapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch create mode 100644 Remapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch create mode 100644 Remapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0714-More-World-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch create mode 100644 Remapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch create mode 100644 Remapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch create mode 100644 Remapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch create mode 100644 Remapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch create mode 100644 Remapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch create mode 100644 Remapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0726-Inventory-close.patch create mode 100644 Remapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch create mode 100644 Remapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch create mode 100644 Remapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch create mode 100644 Remapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch create mode 100644 Remapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch create mode 100644 Remapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch create mode 100644 Remapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch create mode 100644 Remapped-Spigot-Server-Patches/0738-Fix-and-optimise-world-force-upgrading.patch create mode 100644 Remapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch create mode 100644 Remapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch create mode 100644 Remapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch create mode 100644 Remapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch create mode 100644 Remapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch create mode 100644 Remapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch create mode 100644 Remapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch create mode 100644 Remapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch create mode 100644 Remapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch create mode 100644 Remapped-Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch create mode 100644 Remapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch create mode 100644 Remapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch create mode 100644 Remapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch create mode 100644 Remapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch create mode 100644 Remapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch create mode 100644 Remapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch diff --git a/Remapped-Spigot-Server-Patches/0001-POM-Changes.patch b/Remapped-Spigot-Server-Patches/0001-POM-Changes.patch new file mode 100644 index 0000000000..8d0da0d549 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0001-POM-Changes.patch @@ -0,0 +1,291 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 29 Feb 2016 20:40:33 -0600 +Subject: [PATCH] POM Changes + + +diff --git a/pom.xml b/pom.xml +index 3fc047371e8f8a626e69697fad549d689c5dce89..a5d87d22cb1588d15e08da3b37e51c5e261c7799 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -1,15 +1,14 @@ + + 4.0.0 +- org.spigotmc +- spigot ++ paper + jar + 1.16.5-R0.1-SNAPSHOT +- Spigot +- https://www.spigotmc.org/ ++ Paper ++ https://papermc.io + + +- true ++ + UTF-8 + unknown + git +@@ -20,21 +19,39 @@ + + + +- org.spigotmc +- spigot-parent ++ com.destroystokyo.paper ++ paper-parent + dev-SNAPSHOT + ../pom.xml + + ++ ++ ++ ++ org.apache.logging.log4j ++ log4j-bom ++ 2.11.2 ++ pom ++ import ++ ++ ++ ++ + + +- org.spigotmc +- spigot-api ++ com.destroystokyo.paper ++ paper-api ++ ${project.version} ++ compile ++ ++ ++ com.destroystokyo.paper ++ paper-mojangapi + ${project.version} + compile + + +- org.spigotmc ++ io.papermc + minecraft-server + ${minecraft.version}-SNAPSHOT + compile +@@ -45,18 +62,15 @@ + 2.12.1 + compile + ++ ++ org.apache.logging.log4j ++ log4j-api ++ compile ++ + + org.apache.logging.log4j + log4j-iostreams +- 2.8.1 + compile +- +- +- +- org.apache.logging.log4j +- log4j-api +- +- + + + org.ow2.asm +@@ -64,12 +78,23 @@ + 9.1 + compile + ++ ++ ++ co.aikar ++ cleaner ++ 1.0-SNAPSHOT ++ ++ ++ io.netty ++ netty-all ++ 4.1.50.Final ++ + + + com.googlecode.json-simple + json-simple + 1.1.1 +- runtime ++ compile + + + org.xerial +@@ -80,7 +105,7 @@ + + mysql + mysql-connector-java +- 5.1.49 ++ 8.0.23 + runtime + + +@@ -105,7 +130,7 @@ + + org.apache.logging.log4j + log4j-slf4j-impl +- 2.8.1 ++ + runtime + + +@@ -132,34 +157,22 @@ + + + ++ paper-${minecraft.version} ++ clean install + + +- net.md-5 +- scriptus +- 0.4.1 ++ com.lukegb.mojo ++ gitdescribe-maven-plugin ++ 1.3 ++ ++ git-Paper- ++ .. ++ + + +- ex-spigot +- +- ${bt.name}-Spigot-%s +- ../ +- spigot.desc +- +- initialize +- +- describe +- +- +- +- ex-craftbukkit +- +- -%s +- ../../CraftBukkit +- craftbukkit.desc +- +- initialize ++ compile + +- describe ++ gitdescribe + + + +@@ -169,6 +182,7 @@ + maven-jar-plugin + 3.2.0 + ++ true + + + false +@@ -176,11 +190,13 @@ + + org.bukkit.craftbukkit.Main + CraftBukkit +- ${spigot.desc}${craftbukkit.desc} +- ${project.build.outputTimestamp} ++ ++ ${describe} ++ ${maven.build.timestamp} + Bukkit + ${api.version} + Bukkit Team ++ true + + + +@@ -216,14 +232,24 @@ + shade + + ++ ${project.build.directory}/dependency-reduced-pom.xml + ${shadeSourcesJar} + + +- org.spigotmc:minecraft-server ++ io.papermc:minecraft-server + + com/google/common/** + com/google/gson/** + com/google/thirdparty/** ++ ++ io/netty/** ++ META-INF/native/libnetty* ++ com/mojang/brigadier/** ++ META-INF/MANIFEST.MF ++ com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.class ++ com/mojang/datafixers/util/Either* ++ org/apache/logging/log4j/** ++ META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat + + + +@@ -245,10 +271,11 @@ + jline + org.bukkit.craftbukkit.libs.jline + +- +- it.unimi +- org.bukkit.craftbukkit.libs.it.unimi +- ++ ++ ++ ++ ++ + + org.apache.commons.codec + org.bukkit.craftbukkit.libs.org.apache.commons.codec +@@ -316,10 +343,6 @@ + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 +- +- +- eclipse +- + + + org.codehaus.plexus +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 4452427d0a8298d119ca29ef397b7a94f19eec28..46a16e31775b28c44f95a8ac5545ebcb656c74b6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -186,7 +186,7 @@ public class Main { + } + + if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { +- Date buildDate = new Date(Integer.parseInt(Main.class.getPackage().getImplementationVendor()) * 1000L); ++ Date buildDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(Main.class.getPackage().getImplementationVendor()); // Paper + + Calendar deadline = Calendar.getInstance(); + deadline.add(Calendar.DAY_OF_YEAR, -28); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +index 93046379d0cefd5d3236fc59e698809acdc18f80..674096cab190d62622f9947853b056f57d43a2a5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +@@ -11,7 +11,7 @@ public final class Versioning { + public static String getBukkitVersion() { + String result = "Unknown-Version"; + +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties"); ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.destroystokyo.paper/paper-api/pom.properties"); + Properties properties = new Properties(); + + if (stream != null) { diff --git a/Remapped-Spigot-Server-Patches/0002-Paper-config-files.patch b/Remapped-Spigot-Server-Patches/0002-Paper-config-files.patch new file mode 100644 index 0000000000..363f09b241 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0002-Paper-config-files.patch @@ -0,0 +1,820 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 29 Feb 2016 21:02:09 -0600 +Subject: [PATCH] Paper config files + +Loads each yml file for early init too so it can be used for early options + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d05eeaa711a09bb121b530654821894e795ff4ea +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -0,0 +1,286 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Functions; ++import com.google.common.base.Joiner; ++import com.google.common.collect.ImmutableSet; ++import com.google.common.collect.Iterables; ++import com.google.common.collect.Lists; ++import com.google.common.collect.Maps; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.level.ChunkPos; ++import org.apache.commons.lang3.tuple.MutablePair; ++import org.apache.commons.lang3.tuple.Pair; ++import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; ++import org.bukkit.Location; ++import org.bukkit.World; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.entity.Player; ++ ++import java.io.File; ++import java.time.LocalDateTime; ++import java.time.format.DateTimeFormatter; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collection; ++import java.util.Collections; ++import java.util.Iterator; ++import java.util.List; ++import java.util.Locale; ++import java.util.Map; ++import java.util.Set; ++import java.util.stream.Collectors; ++ ++public class PaperCommand extends Command { ++ private static final String BASE_PERM = "bukkit.command.paper."; ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); ++ ++ public PaperCommand(String name) { ++ super(name); ++ this.description = "Paper related commands"; ++ this.usageMessage = "/paper [" + Joiner.on(" | ").join(SUBCOMMANDS) + "]"; ++ this.setPermission("bukkit.command.paper;" + Joiner.on(';').join(SUBCOMMANDS.stream().map(s -> BASE_PERM + s).collect(Collectors.toSet()))); ++ } ++ ++ private static boolean testPermission(CommandSender commandSender, String permission) { ++ if (commandSender.hasPermission(BASE_PERM + permission) || commandSender.hasPermission("bukkit.command.paper")) return true; ++ commandSender.sendMessage(Bukkit.getPermissionMessage()); ++ return false; ++ } ++ ++ @Override ++ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { ++ if (args.length <= 1) ++ return getListMatchingLast(sender, args, SUBCOMMANDS); ++ ++ switch (args[0].toLowerCase(Locale.ENGLISH)) ++ { ++ case "entity": ++ if (args.length == 2) ++ return getListMatchingLast(sender, args, "help", "list"); ++ if (args.length == 3) ++ return getListMatchingLast(sender, args, EntityType.getEntityNameList().stream().map(ResourceLocation::toString).sorted().toArray(String[]::new)); ++ break; ++ } ++ return Collections.emptyList(); ++ } ++ ++ // Code from Mojang - copyright them ++ public static List getListMatchingLast(CommandSender sender, String[] args, String... matches) { ++ return getListMatchingLast(sender, args, (Collection) Arrays.asList(matches)); ++ } ++ ++ public static boolean matches(String s, String s1) { ++ return s1.regionMatches(true, 0, s, 0, s.length()); ++ } ++ ++ public static List getListMatchingLast(CommandSender sender, String[] strings, Collection collection) { ++ String last = strings[strings.length - 1]; ++ ArrayList results = Lists.newArrayList(); ++ ++ if (!collection.isEmpty()) { ++ Iterator iterator = Iterables.transform(collection, Functions.toStringFunction()).iterator(); ++ ++ while (iterator.hasNext()) { ++ String s1 = (String) iterator.next(); ++ ++ if (matches(last, s1) && (sender.hasPermission(BASE_PERM + s1) || sender.hasPermission("bukkit.command.paper"))) { ++ results.add(s1); ++ } ++ } ++ ++ if (results.isEmpty()) { ++ iterator = collection.iterator(); ++ ++ while (iterator.hasNext()) { ++ Object object = iterator.next(); ++ ++ if (object instanceof ResourceLocation && matches(last, ((ResourceLocation) object).getPath())) { ++ results.add(String.valueOf(object)); ++ } ++ } ++ } ++ } ++ ++ return results; ++ } ++ // end copy stuff ++ ++ @Override ++ public boolean execute(CommandSender sender, String commandLabel, String[] args) { ++ if (!testPermission(sender)) return true; ++ ++ if (args.length == 0) { ++ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); ++ return false; ++ } ++ if (SUBCOMMANDS.contains(args[0].toLowerCase(Locale.ENGLISH))) { ++ if (!testPermission(sender, args[0].toLowerCase(Locale.ENGLISH))) return true; ++ } ++ switch (args[0].toLowerCase(Locale.ENGLISH)) { ++ case "heap": ++ dumpHeap(sender); ++ break; ++ case "entity": ++ listEntities(sender, args); ++ break; ++ case "reload": ++ doReload(sender); ++ break; ++ case "ver": ++ if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) ++ case "version": ++ Command ver = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version"); ++ if (ver != null) { ++ ver.execute(sender, commandLabel, new String[0]); ++ break; ++ } ++ // else - fall through to default ++ default: ++ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); ++ return false; ++ } ++ ++ return true; ++ } ++ ++ /* ++ * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 ++ */ ++ private void listEntities(CommandSender sender, String[] args) { ++ if (args.length < 2 || args[1].toLowerCase(Locale.ENGLISH).equals("help")) { ++ sender.sendMessage(ChatColor.RED + "Use /paper entity [list] help for more information on a specific command."); ++ return; ++ } ++ ++ switch (args[1].toLowerCase(Locale.ENGLISH)) { ++ case "list": ++ String filter = "*"; ++ if (args.length > 2) { ++ if (args[2].toLowerCase(Locale.ENGLISH).equals("help")) { ++ sender.sendMessage(ChatColor.RED + "Use /paper entity list [filter] [worldName] to get entity info that matches the optional filter."); ++ return; ++ } ++ filter = args[2]; ++ } ++ final String cleanfilter = filter.replace("?", ".?").replace("*", ".*?"); ++ Set names = EntityType.getEntityNameList().stream() ++ .filter(n -> n.toString().matches(cleanfilter)) ++ .collect(Collectors.toSet()); ++ ++ if (names.isEmpty()) { ++ sender.sendMessage(ChatColor.RED + "Invalid filter, does not match any entities. Use /paper entity list for a proper list"); ++ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); ++ return; ++ } ++ ++ String worldName; ++ if (args.length > 3) { ++ worldName = args[3]; ++ } else if (sender instanceof Player) { ++ worldName = ((Player) sender).getWorld().getName(); ++ } else { ++ sender.sendMessage(ChatColor.RED + "Please specify the name of a world"); ++ sender.sendMessage(ChatColor.RED + "To do so without a filter, specify '*' as the filter"); ++ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); ++ return; ++ } ++ ++ Map>> list = Maps.newHashMap(); ++ World bukkitWorld = Bukkit.getWorld(worldName); ++ if (bukkitWorld == null) { ++ sender.sendMessage(ChatColor.RED + "Could not load world for " + worldName + ". Please select a valid world."); ++ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); ++ return; ++ } ++ ServerLevel world = ((CraftWorld) Bukkit.getWorld(worldName)).getHandle(); ++ ++ Map nonEntityTicking = Maps.newHashMap(); ++ ServerChunkCache chunkProviderServer = world.getChunkSource(); ++ ++ Collection entities = world.entitiesById.values(); ++ entities.forEach(e -> { ++ ResourceLocation key = new ResourceLocation(""); // TODO: update in next patch ++ ++ MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); ++ ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); ++ info.left++; ++ info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1); ++ if (!chunkProviderServer.isInEntityTickingChunk(e)) { ++ nonEntityTicking.merge(key, Integer.valueOf(1), Integer::sum); ++ } ++ }); ++ ++ if (names.size() == 1) { ++ ResourceLocation name = names.iterator().next(); ++ Pair> info = list.get(name); ++ int nonTicking = nonEntityTicking.getOrDefault(name, Integer.valueOf(0)).intValue(); ++ if (info == null) { ++ sender.sendMessage(ChatColor.RED + "No entities found."); ++ return; ++ } ++ sender.sendMessage("Entity: " + name + " Total Ticking: " + (info.getLeft() - nonTicking) + ", Total Non-Ticking: " + nonTicking); ++ info.getRight().entrySet().stream() ++ .sorted((a, b) -> !a.getValue().equals(b.getValue()) ? b.getValue() - a.getValue() : a.getKey().toString().compareTo(b.getKey().toString())) ++ .limit(10).forEach(e -> sender.sendMessage(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z + (chunkProviderServer.isEntityTickingChunk(e.getKey()) ? " (Ticking)" : " (Non-Ticking)"))); ++ } else { ++ List> info = list.entrySet().stream() ++ .filter(e -> names.contains(e.getKey())) ++ .map(e -> Pair.of(e.getKey(), e.getValue().left)) ++ .sorted((a, b) -> !a.getRight().equals(b.getRight()) ? b.getRight() - a.getRight() : a.getKey().toString().compareTo(b.getKey().toString())) ++ .collect(Collectors.toList()); ++ ++ if (info == null || info.size() == 0) { ++ sender.sendMessage(ChatColor.RED + "No entities found."); ++ return; ++ } ++ ++ int count = info.stream().mapToInt(Pair::getRight).sum(); ++ int nonTickingCount = nonEntityTicking.values().stream().mapToInt(Integer::intValue).sum(); ++ sender.sendMessage("Total Ticking: " + (count - nonTickingCount) + ", Total Non-Ticking: " + nonTickingCount); ++ info.forEach(e -> { ++ int nonTicking = nonEntityTicking.getOrDefault(e.getKey(), Integer.valueOf(0)).intValue(); ++ sender.sendMessage(" " + (e.getValue() - nonTicking) + " (" + nonTicking + ") " + ": " + e.getKey()); ++ }); ++ sender.sendMessage("* First number is ticking entities, second number is non-ticking entities"); ++ } ++ break; ++ } ++ } ++ ++ private void dumpHeap(CommandSender sender) { ++ java.nio.file.Path dir = java.nio.file.Paths.get("./dumps"); ++ String name = "heap-dump-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()); ++ ++ Command.broadcastCommandMessage(sender, ChatColor.YELLOW + "Writing JVM heap data..."); ++ ++ java.nio.file.Path file = CraftServer.dumpHeap(dir, name); ++ if (file != null) { ++ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Heap dump saved to " + file); ++ } else { ++ Command.broadcastCommandMessage(sender, ChatColor.RED + "Failed to write heap dump, see sever log for details"); ++ } ++ } ++ ++ private void doReload(CommandSender sender) { ++ Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues."); ++ Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); ++ ++ MinecraftServer console = MinecraftServer.getServer(); ++ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); ++ for (ServerLevel world : console.getAllLevels()) { ++ world.paperConfig.init(); ++ } ++ console.server.reloadCount++; ++ ++ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete."); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2c0514892d3993bef57ecf677cf8bb0fbe0216e4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -0,0 +1,185 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Throwables; ++ ++import java.io.File; ++import java.io.IOException; ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.TimeUnit; ++import java.util.logging.Level; ++import java.util.regex.Pattern; ++ ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++import org.bukkit.command.Command; ++import org.bukkit.configuration.ConfigurationSection; ++import org.bukkit.configuration.InvalidConfigurationException; ++import org.bukkit.configuration.file.YamlConfiguration; ++ ++public class PaperConfig { ++ ++ private static File CONFIG_FILE; ++ private static final String HEADER = "This is the main configuration file for Paper.\n" ++ + "As you can see, there's tons to configure. Some options may impact gameplay, so use\n" ++ + "with caution, and make sure you know what each option does before configuring.\n" ++ + "\n" ++ + "If you need help with the configuration or have any questions related to Paper,\n" ++ + "join us in our Discord or IRC channel.\n" ++ + "\n" ++ + "Discord: https://discord.gg/papermc\n" ++ + "IRC: #paper @ irc.esper.net ( https://webchat.esper.net/?channels=paper ) \n" ++ + "Website: https://papermc.io/ \n" ++ + "Docs: https://paper.readthedocs.org/ \n"; ++ /*========================================================================*/ ++ public static YamlConfiguration config; ++ static int version; ++ static Map commands; ++ private static boolean verbose; ++ private static boolean fatalError; ++ /*========================================================================*/ ++ ++ public static void init(File configFile) { ++ CONFIG_FILE = configFile; ++ config = new YamlConfiguration(); ++ try { ++ config.load(CONFIG_FILE); ++ } catch (IOException ex) { ++ } catch (InvalidConfigurationException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not load paper.yml, please correct your syntax errors", ex); ++ throw Throwables.propagate(ex); ++ } ++ config.options().header(HEADER); ++ config.options().copyDefaults(true); ++ verbose = getBoolean("verbose", false); ++ ++ commands = new HashMap(); ++ commands.put("paper", new PaperCommand("paper")); ++ ++ version = getInt("config-version", 20); ++ set("config-version", 20); ++ readConfig(PaperConfig.class, null); ++ } ++ ++ protected static void logError(String s) { ++ Bukkit.getLogger().severe(s); ++ } ++ ++ protected static void fatal(String s) { ++ fatalError = true; ++ throw new RuntimeException("Fatal paper.yml config error: " + s); ++ } ++ ++ protected static void log(String s) { ++ if (verbose) { ++ Bukkit.getLogger().info(s); ++ } ++ } ++ ++ public static void registerCommands() { ++ for (Map.Entry entry : commands.entrySet()) { ++ MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); ++ } ++ } ++ ++ static void readConfig(Class clazz, Object instance) { ++ for (Method method : clazz.getDeclaredMethods()) { ++ if (Modifier.isPrivate(method.getModifiers())) { ++ if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) { ++ try { ++ method.setAccessible(true); ++ method.invoke(instance); ++ } catch (InvocationTargetException ex) { ++ throw Throwables.propagate(ex.getCause()); ++ } catch (Exception ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex); ++ } ++ } ++ } ++ } ++ ++ try { ++ config.save(CONFIG_FILE); ++ } catch (IOException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex); ++ } ++ } ++ ++ private static final Pattern SPACE = Pattern.compile(" "); ++ private static final Pattern NOT_NUMERIC = Pattern.compile("[^-\\d.]"); ++ public static int getSeconds(String str) { ++ str = SPACE.matcher(str).replaceAll(""); ++ final char unit = str.charAt(str.length() - 1); ++ str = NOT_NUMERIC.matcher(str).replaceAll(""); ++ double num; ++ try { ++ num = Double.parseDouble(str); ++ } catch (Exception e) { ++ num = 0D; ++ } ++ switch (unit) { ++ case 'd': num *= (double) 60*60*24; break; ++ case 'h': num *= (double) 60*60; break; ++ case 'm': num *= (double) 60; break; ++ default: case 's': break; ++ } ++ return (int) num; ++ } ++ ++ protected static String timeSummary(int seconds) { ++ String time = ""; ++ ++ if (seconds > 60 * 60 * 24) { ++ time += TimeUnit.SECONDS.toDays(seconds) + "d"; ++ seconds %= 60 * 60 * 24; ++ } ++ ++ if (seconds > 60 * 60) { ++ time += TimeUnit.SECONDS.toHours(seconds) + "h"; ++ seconds %= 60 * 60; ++ } ++ ++ if (seconds > 0) { ++ time += TimeUnit.SECONDS.toMinutes(seconds) + "m"; ++ } ++ return time; ++ } ++ ++ private static void set(String path, Object val) { ++ config.set(path, val); ++ } ++ ++ private static boolean getBoolean(String path, boolean def) { ++ config.addDefault(path, def); ++ return config.getBoolean(path, config.getBoolean(path)); ++ } ++ ++ private static double getDouble(String path, double def) { ++ config.addDefault(path, def); ++ return config.getDouble(path, config.getDouble(path)); ++ } ++ ++ private static float getFloat(String path, float def) { ++ // TODO: Figure out why getFloat() always returns the default value. ++ return (float) getDouble(path, (double) def); ++ } ++ ++ private static int getInt(String path, int def) { ++ config.addDefault(path, def); ++ return config.getInt(path, config.getInt(path)); ++ } ++ ++ private static List getList(String path, T def) { ++ config.addDefault(path, def); ++ return (List) config.getList(path, config.getList(path)); ++ } ++ ++ private static String getString(String path, String def) { ++ config.addDefault(path, def); ++ return config.getString(path, config.getString(path)); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b31109d2dadd29e8852468c19265066b773d2be0 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -0,0 +1,68 @@ ++package com.destroystokyo.paper; ++ ++import java.util.List; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.configuration.file.YamlConfiguration; ++import org.spigotmc.SpigotWorldConfig; ++ ++import static com.destroystokyo.paper.PaperConfig.log; ++import static com.destroystokyo.paper.PaperConfig.logError; ++ ++public class PaperWorldConfig { ++ ++ private final String worldName; ++ private final SpigotWorldConfig spigotConfig; ++ private YamlConfiguration config; ++ private boolean verbose; ++ ++ public PaperWorldConfig(String worldName, SpigotWorldConfig spigotConfig) { ++ this.worldName = worldName; ++ this.spigotConfig = spigotConfig; ++ this.config = PaperConfig.config; ++ init(); ++ } ++ ++ public void init() { ++ this.config = PaperConfig.config; // grab updated reference ++ log("-------- World Settings For [" + worldName + "] --------"); ++ PaperConfig.readConfig(PaperWorldConfig.class, this); ++ } ++ ++ private void set(String path, Object val) { ++ config.set("world-settings.default." + path, val); ++ if (config.get("world-settings." + worldName + "." + path) != null) { ++ config.set("world-settings." + worldName + "." + path, val); ++ } ++ } ++ ++ private boolean getBoolean(String path, boolean def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path)); ++ } ++ ++ private double getDouble(String path, double def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getDouble("world-settings." + worldName + "." + path, config.getDouble("world-settings.default." + path)); ++ } ++ ++ private int getInt(String path, int def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getInt("world-settings." + worldName + "." + path, config.getInt("world-settings.default." + path)); ++ } ++ ++ private float getFloat(String path, float def) { ++ // TODO: Figure out why getFloat() always returns the default value. ++ return (float) getDouble(path, (double) def); ++ } ++ ++ private List getList(String path, List def) { ++ config.addDefault("world-settings.default." + path, def); ++ return (List) config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)); ++ } ++ ++ private String getString(String path, String def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 9366b5551047e87e455fafbf45be5fb145aa875b..5d83a8d4c69144219219877c521c364d912d2452 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -95,6 +95,12 @@ public class Main { + DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(iregistrycustom_dimension, optionset); // CraftBukkit - CLI argument support + + dedicatedserversettings.forceSave(); ++ // Paper start - load config files for access below if needed ++ org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = loadConfigFile((File) optionset.valueOf("bukkit-settings")); ++ org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = loadConfigFile((File) optionset.valueOf("spigot-settings")); ++ org.bukkit.configuration.file.YamlConfiguration paperConfiguration = loadConfigFile((File) optionset.valueOf("paper-settings")); ++ // Paper end ++ + java.nio.file.Path java_nio_file_path1 = Paths.get("eula.txt"); + Eula eula = new Eula(java_nio_file_path1); + +@@ -236,6 +242,20 @@ public class Main { + + } + ++ // Paper start - load config files ++ private static org.bukkit.configuration.file.YamlConfiguration loadConfigFile(File configFile) throws Exception { ++ org.bukkit.configuration.file.YamlConfiguration config = new org.bukkit.configuration.file.YamlConfiguration(); ++ if (configFile.exists()) { ++ try { ++ config.load(configFile); ++ } catch (Exception ex) { ++ throw new Exception("Failed to load configuration file: " + configFile.getName(), ex); ++ } ++ } ++ return config; ++ } ++ // Paper end ++ + public static void forceUpgrade(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, boolean eraseCache, BooleanSupplier booleansupplier, ImmutableSet> worlds) { // CraftBukkit + Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit + WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, worlds, eraseCache); +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 2228f83f251851aa683f739ac5ce2ec98f059f3f..23d6f803eafa78fd51ea4cdc4ca25c78661bc80b 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -184,6 +184,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); + org.spigotmc.SpigotConfig.registerCommands(); + // Spigot end ++ // Paper start ++ try { ++ com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); ++ } catch (Exception e) { ++ DedicatedServer.LOGGER.error("Unable to load server configuration", e); ++ return false; ++ } ++ com.destroystokyo.paper.PaperConfig.registerCommands(); ++ // Paper end + + this.setPvpAllowed(dedicatedserverproperties.pvp); + this.setFlightAllowed(dedicatedserverproperties.allowFlight); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index aa7bf54e4b93a9b6085aa943500f5dec5f60a117..7cc5070f70a4f740add9d971385ceaa4d44275a2 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -307,15 +307,15 @@ public class ServerChunkCache extends ChunkSource { + } + } + +- @Override +- public boolean isEntityTickingChunk(Entity entity) { ++ public final boolean isInEntityTickingChunk(Entity entity) { return this.isEntityTickingChunk(entity); } // Paper - OBFHELPER ++ @Override public boolean isEntityTickingChunk(Entity entity) { + long i = ChunkPos.asLong(Mth.floor(entity.getX()) >> 4, Mth.floor(entity.getZ()) >> 4); + + return this.checkChunkFuture(i, (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error + } + +- @Override +- public boolean isEntityTickingChunk(ChunkPos pos) { ++ public final boolean isEntityTickingChunk(ChunkPos chunkcoordintpair) { return this.isEntityTickingChunk(chunkcoordintpair); } // Paper - OBFHELPER ++ @Override public boolean isEntityTickingChunk(ChunkPos pos) { + return this.checkChunkFuture(pos.toLong(), (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error + } + +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index f82fd4a50921c3c4791be18a43778e6fd216f557..ff482d0349c18d0d1ba902ea0d10611b1ca4e588 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -2,6 +2,7 @@ package net.minecraft.world.entity; + + import com.google.common.collect.ImmutableSet; + import java.util.Optional; ++import java.util.Set; // Paper + import java.util.UUID; + import java.util.function.Function; + import java.util.stream.Stream; +@@ -599,4 +600,10 @@ public class EntityType { + return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval); + } + } ++ ++ // Paper start ++ public static Set getEntityNameList() { ++ return Registry.ENTITY_TYPE.keySet(); ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index b7c64fcf49ea50fa38a121d906ec6df20a1be31b..f08de81dcc4acd5a3e44407b431ce827a19b2e9c 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -129,6 +129,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean populating; + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + ++ public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper ++ + public final SpigotTimings.WorldTimingsHandler timings; // Spigot + public static BlockPos lastPhysicsProblem; // Spigot + private org.spigotmc.TickLimiter entityLimiter; +@@ -149,6 +151,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot ++ this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper + this.generator = gen; + this.world = new CraftWorld((ServerLevel) this, gen, env); + this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns(); // CraftBukkit +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 761ad2d7e538d1e299d3050446274addcde7d772..328d1e2b128b62f24917719c79823c9fb64a0dcf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -806,6 +806,7 @@ public final class CraftServer implements Server { + } + + org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot ++ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper + for (ServerLevel world : console.getAllLevels()) { + world.worldDataServer.setDifficulty(config.difficulty); + world.setSpawnSettings(config.spawnMonsters, config.spawnAnimals); +@@ -839,6 +840,7 @@ public final class CraftServer implements Server { + world.ticksPerAmbientSpawns = this.getTicksPerAmbientSpawns(); + } + world.spigotConfig.init(); // Spigot ++ world.paperConfig.init(); // Paper + } + + pluginManager.clearPlugins(); +@@ -846,6 +848,7 @@ public final class CraftServer implements Server { + resetRecipes(); + reloadData(); + org.spigotmc.SpigotConfig.registerCommands(); // Spigot ++ com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper + overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); + ignoreVanillaPermissions = commandsConfiguration.getBoolean("ignore-vanilla-permissions"); + +@@ -2101,4 +2104,35 @@ public final class CraftServer implements Server { + return spigot; + } + // Spigot end ++ ++ // Paper start ++ @SuppressWarnings({"rawtypes", "unchecked"}) ++ public static java.nio.file.Path dumpHeap(java.nio.file.Path dir, String name) { ++ try { ++ java.nio.file.Files.createDirectories(dir); ++ ++ javax.management.MBeanServer server = java.lang.management.ManagementFactory.getPlatformMBeanServer(); ++ java.nio.file.Path file; ++ ++ try { ++ Class clazz = Class.forName("openj9.lang.management.OpenJ9DiagnosticsMXBean"); ++ Object openj9Mbean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "openj9.lang.management:type=OpenJ9Diagnostics", clazz); ++ java.lang.reflect.Method m = clazz.getMethod("triggerDumpToFile", String.class, String.class); ++ file = dir.resolve(name + ".phd"); ++ m.invoke(openj9Mbean, "heap", file.toString()); ++ } catch (ClassNotFoundException e) { ++ Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean"); ++ Object hotspotMBean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", clazz); ++ java.lang.reflect.Method m = clazz.getMethod("dumpHeap", String.class, boolean.class); ++ file = dir.resolve(name + ".hprof"); ++ m.invoke(hotspotMBean, file.toString(), true); ++ } ++ ++ return file; ++ } catch (Throwable t) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not write heap", t); ++ return null; ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 46a16e31775b28c44f95a8ac5545ebcb656c74b6..05aedca561919a12ced1925c5cc9af585bb04523 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -129,6 +129,14 @@ public class Main { + .defaultsTo(new File("spigot.yml")) + .describedAs("Yml file"); + // Spigot End ++ ++ // Paper Start ++ acceptsAll(asList("paper", "paper-settings"), "File for paper settings") ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File("paper.yml")) ++ .describedAs("Yml file"); ++ // Paper end + } + }; + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 83d83ff7ceffbb77723da721b869dfd0091e496d..0efcbab8f8806aeb8dd8bd6384e5a7cee375d100 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -39,36 +39,36 @@ public class SpigotWorldConfig + config.set( "world-settings.default." + path, val ); + } + +- private boolean getBoolean(String path, boolean def) ++ public boolean getBoolean(String path, boolean def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return config.getBoolean( "world-settings." + worldName + "." + path, config.getBoolean( "world-settings.default." + path ) ); + } + +- private double getDouble(String path, double def) ++ public double getDouble(String path, double def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return config.getDouble( "world-settings." + worldName + "." + path, config.getDouble( "world-settings.default." + path ) ); + } + +- private int getInt(String path) ++ public int getInt(String path) // Paper - private -> public + { + return config.getInt( "world-settings." + worldName + "." + path ); + } + +- private int getInt(String path, int def) ++ public int getInt(String path, int def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return config.getInt( "world-settings." + worldName + "." + path, config.getInt( "world-settings.default." + path ) ); + } + +- private List getList(String path, T def) ++ public List getList(String path, T def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return (List) config.getList( "world-settings." + worldName + "." + path, config.getList( "world-settings.default." + path ) ); + } + +- private String getString(String path, String def) ++ public String getString(String path, String def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return config.getString( "world-settings." + worldName + "." + path, config.getString( "world-settings.default." + path ) ); diff --git a/Remapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch b/Remapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch new file mode 100644 index 0000000000..10c424b9a6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch @@ -0,0 +1,929 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 30 Mar 2016 19:36:20 -0400 +Subject: [PATCH] MC Dev fixes + + +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index 16220ce9a7db722c8b351f8016fd1df066ffcb98..8c378d3f3138953b3b22b289fecdb6b40a09ab63 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -65,8 +65,8 @@ public class Util { + return Collectors.toMap(Entry::getKey, Entry::getValue); + } + +- public static > String getPropertyName(Property iblockstate, Object object) { +- return iblockstate.value((Comparable) object); ++ public static > String a(Property iblockstate, T object) { // Paper - decompile fix ++ return iblockstate.getName(object); // Paper - decompile fix + } + + public static String makeDescriptionId(String type, @Nullable ResourceLocation id) { +@@ -234,8 +234,8 @@ public class Util { + public static T findPreviousInIterable(Iterable iterable, @Nullable T t0) { + Iterator iterator = iterable.iterator(); + +- Object object; +- Object object1; ++ T object; // Paper - decompile fix ++ T object1; // Paper - decompile fix + + for (object1 = null; iterator.hasNext(); object1 = object) { + object = iterator.next(); +@@ -260,7 +260,7 @@ public class Util { + } + + public static Strategy identityStrategy() { +- return Util.IdentityStrategy.INSTANCE; ++ return (Strategy) Util.IdentityStrategy.INSTANCE; // Paper - decompile fix + } + + public static CompletableFuture> sequence(List> futures) { +@@ -271,7 +271,7 @@ public class Util { + futures.forEach((completablefuture1) -> { + int i = list1.size(); + +- list1.add((Object) null); ++ list1.add(null); // Paper - decompile fix + acompletablefuture[i] = completablefuture1.whenComplete((object, throwable) -> { + if (throwable != null) { + completablefuture.completeExceptionally(throwable); +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index aa35d67cc27a4f982575eab3be46f4187f29d3fe..88147a1f25cf2fd549412b653b8f0eb5c60bb55d 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -241,8 +241,8 @@ public class BlockPos extends Vec3i { + }; + } + +- public static Iterable withinManhattan(BlockPos center, int xRange, int yRange, int zRange) { +- int l = xRange + yRange + zRange; ++ public static Iterable withinManhattan(BlockPos center, int xRange, int yRange, int zRange) { // Paper - decompile issues - variable name conflicts to inner class field refs ++ int l_decompiled = xRange + yRange + zRange; // Paper - decompile issues + int i1 = center.getX(); + int j1 = center.getY(); + int k1 = center.getZ(); +@@ -270,15 +270,15 @@ public class BlockPos extends Vec3i { + ++this.x; + if (this.x > this.maxX) { + ++this.currentDepth; +- if (this.currentDepth > x) { ++ if (this.currentDepth > l_decompiled) { // Paper - use proper l above (first line of this method) + return (BlockPos) this.endOfData(); + } + +- this.maxX = Math.min(currentDepth, this.currentDepth); ++ this.maxX = Math.min(xRange, this.currentDepth); // Paper - decompile issues + this.x = -this.maxX; + } + +- this.maxY = Math.min(maxX, this.currentDepth - Math.abs(this.x)); ++ this.maxY = Math.min(yRange, this.currentDepth - Math.abs(this.x)); // Paper - decompile issues + this.y = -this.maxY; + } + +@@ -286,7 +286,7 @@ public class BlockPos extends Vec3i { + int i2 = this.y; + int j2 = this.currentDepth - Math.abs(l1) - Math.abs(i2); + +- if (j2 <= maxY) { ++ if (j2 <= zRange) { // Paper - decompile issues + this.zMirror = j2 != 0; + blockposition_mutableblockposition = this.cursor.set(i1 + l1, j1 + i2, k1 + j2); + } +@@ -355,13 +355,13 @@ public class BlockPos extends Vec3i { + }; + } + +- public static Iterable spiralAround(BlockPos blockposition, int i, Direction enumdirection, Direction enumdirection1) { ++ public static Iterable spiralAround(BlockPos blockposition, int I, Direction enumdirection, Direction enumdirection1) { // Paper - decompile fix + Validate.validState(enumdirection.getAxis() != enumdirection1.getAxis(), "The two directions cannot be on the same axis", new Object[0]); + return () -> { + return new AbstractIterator() { + private final Direction[] directions = new Direction[]{enumdirection, enumdirection1, enumdirection.getOpposite(), enumdirection1.getOpposite()}; + private final BlockPos.MutableBlockPos cursor = blockposition.mutable().move(enumdirection1); +- private final int legs = 4 * legSize; ++ private final int legs = 4 * I; + private int leg = -1; + private int legSize; + private int legIndex; +diff --git a/src/main/java/net/minecraft/core/IdMapper.java b/src/main/java/net/minecraft/core/IdMapper.java +index 71c591487853bec3cecf5777c09ddc05bd658b64..424c6cacc2e7c7b1c9d0b92fe198237033a3fcbd 100644 +--- a/src/main/java/net/minecraft/core/IdMapper.java ++++ b/src/main/java/net/minecraft/core/IdMapper.java +@@ -27,7 +27,7 @@ public class IdMapper implements IdMap { + this.tToId.put(value, id); + + while (this.idToT.size() <= id) { +- this.idToT.add((Object) null); ++ this.idToT.add(null); // Paper - decompile fix + } + + this.idToT.set(id, value); +@@ -41,6 +41,13 @@ public class IdMapper implements IdMap { + this.addMapping(value, this.nextId); + } + ++ // Paper start - decompile fix ++ @Override ++ public int a(T t) { ++ return getId(t); ++ } ++ // Paper end ++ + public int getId(T entry) { + Integer integer = (Integer) this.tToId.get(entry); + +diff --git a/src/main/java/net/minecraft/nbt/ListTag.java b/src/main/java/net/minecraft/nbt/ListTag.java +index efc632a8ac13f77aaf2229a09e84416c09c86255..084340dc73acb3d972e0717b48da820c027a5137 100644 +--- a/src/main/java/net/minecraft/nbt/ListTag.java ++++ b/src/main/java/net/minecraft/nbt/ListTag.java +@@ -53,7 +53,7 @@ public class ListTag extends CollectionTag { + return "TAG_List"; + } + }; +- private static final ByteSet INLINE_ELEMENT_TYPES = new ByteOpenHashSet(Arrays.asList(1, 2, 3, 4, 5, 6)); ++ private static final ByteSet INLINE_ELEMENT_TYPES = new ByteOpenHashSet(Arrays.asList((byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6)); // Paper - decompiler fix + private final List list; + private byte type; + +diff --git a/src/main/java/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java +index 5494db9e8e04d976aa1b005a108b452cd481d0bb..c4fbc0bc8b80d16f09d3c6642acc7476a0817868 100644 +--- a/src/main/java/net/minecraft/nbt/NbtIo.java ++++ b/src/main/java/net/minecraft/nbt/NbtIo.java +@@ -18,6 +18,7 @@ import java.util.zip.GZIPOutputStream; + import net.minecraft.CrashReport; + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; ++import io.netty.buffer.ByteBufInputStream; // Paper + + public class NbtIo { + +@@ -137,7 +138,7 @@ public class NbtIo { + + public static CompoundTag read(DataInput input, NbtAccounter tracker) throws IOException { + // Spigot start +- if ( input instanceof io.netty.buffer.ByteBufInputStream ) ++ if ( input instanceof ByteBufInputStream) // Paper + { + input = new DataInputStream(new org.spigotmc.LimitStream((InputStream) input, tracker)); + } +diff --git a/src/main/java/net/minecraft/nbt/Tag.java b/src/main/java/net/minecraft/nbt/Tag.java +index 483c33e9b2d64c1a003d3bb543486b8a545bc96a..85e9c5f4620fcf48cb3655fbb2db58b3fb31aa74 100644 +--- a/src/main/java/net/minecraft/nbt/Tag.java ++++ b/src/main/java/net/minecraft/nbt/Tag.java +@@ -20,7 +20,7 @@ public interface Tag { + + TagType getType(); + +- Tag copy(); ++ public Tag copy(); // Paper - decompile fix + + default String getAsString() { + return this.toString(); +diff --git a/src/main/java/net/minecraft/network/ConnectionProtocol.java b/src/main/java/net/minecraft/network/ConnectionProtocol.java +index a12d169edf4e087b18fedf7199d6eb7ee58f0305..fca778d131aa10e88d5f7ed8d57eda6803318184 100644 +--- a/src/main/java/net/minecraft/network/ConnectionProtocol.java ++++ b/src/main/java/net/minecraft/network/ConnectionProtocol.java +@@ -14,23 +14,29 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketFlow; + import net.minecraft.network.protocol.game.*; + import net.minecraft.network.protocol.handshake.ClientIntentionPacket; ++import net.minecraft.network.protocol.handshake.ServerHandshakePacketListener; ++import net.minecraft.network.protocol.login.ClientLoginPacketListener; + import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; + import net.minecraft.network.protocol.login.ClientboundGameProfilePacket; + import net.minecraft.network.protocol.login.ClientboundHelloPacket; + import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; + import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; ++import net.minecraft.network.protocol.login.ServerLoginPacketListener; + import net.minecraft.network.protocol.login.ServerboundCustomQueryPacket; + import net.minecraft.network.protocol.login.ServerboundHelloPacket; + import net.minecraft.network.protocol.login.ServerboundKeyPacket; ++import net.minecraft.network.protocol.status.ClientStatusPacketListener; + import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; + import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; ++import net.minecraft.network.protocol.status.ServerStatusPacketListener; + import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; + import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; + import org.apache.logging.log4j.LogManager; + + public enum ConnectionProtocol { + +- HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))), PLAY(0, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new).a(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new).a(ClientboundAddMobPacket.class, ClientboundAddMobPacket::new).a(ClientboundAddPaintingPacket.class, ClientboundAddPaintingPacket::new).a(ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new).a(ClientboundAnimatePacket.class, ClientboundAnimatePacket::new).a(ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new).a(ClientboundBlockBreakAckPacket.class, ClientboundBlockBreakAckPacket::new).a(ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new).a(ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new).a(ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new).a(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new).a(ClientboundBossEventPacket.class, ClientboundBossEventPacket::new).a(ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new).a(ClientboundChatPacket.class, ClientboundChatPacket::new).a(ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new).a(ClientboundCommandsPacket.class, ClientboundCommandsPacket::new).a(ClientboundContainerAckPacket.class, ClientboundContainerAckPacket::new).a(ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new).a(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new).a(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new).a(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new).a(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new).a(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new).a(ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new).a(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new).a(ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new).a(ClientboundExplodePacket.class, ClientboundExplodePacket::new).a(ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new).a(ClientboundGameEventPacket.class, ClientboundGameEventPacket::new).a(ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new).a(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new).a(ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new).a(ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new).a(ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new).a(ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new).a(ClientboundLoginPacket.class, ClientboundLoginPacket::new).a(ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new).a(ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new).a(ClientboundMoveEntityPacket.Pos.class, ClientboundMoveEntityPacket.Pos::new).a(ClientboundMoveEntityPacket.PosRot.class, ClientboundMoveEntityPacket.PosRot::new).a(ClientboundMoveEntityPacket.Rot.class, ClientboundMoveEntityPacket.Rot::new).a(ClientboundMoveEntityPacket.class, ClientboundMoveEntityPacket::new).a(ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new).a(ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new).a(ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new).a(ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new).a(ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new).a(ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new).a(ClientboundPlayerCombatPacket.class, ClientboundPlayerCombatPacket::new).a(ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new).a(ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new).a(ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new).a(ClientboundRecipePacket.class, ClientboundRecipePacket::new).a(ClientboundRemoveEntitiesPacket.class, ClientboundRemoveEntitiesPacket::new).a(ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new).a(ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new).a(ClientboundRespawnPacket.class, ClientboundRespawnPacket::new).a(ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new).a(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new).a(ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new).a(ClientboundSetBorderPacket.class, ClientboundSetBorderPacket::new).a(ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new).a(ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new).a(ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new).a(ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new).a(ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new).a(ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new).a(ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new).a(ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new).a(ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new).a(ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new).a(ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new).a(ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new).a(ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new).a(ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new).a(ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new).a(ClientboundSetScorePacket.class, ClientboundSetScorePacket::new).a(ClientboundSetTimePacket.class, ClientboundSetTimePacket::new).a(ClientboundSetTitlesPacket.class, ClientboundSetTitlesPacket::new).a(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new).a(ClientboundSoundPacket.class, ClientboundSoundPacket::new).a(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new).a(ClientboundTabListPacket.class, ClientboundTabListPacket::new).a(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new).a(ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new).a(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new).a(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new).a(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new).a(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new).a(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new).a(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new)).a(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new).a(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new).a(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new).a(ServerboundChatPacket.class, ServerboundChatPacket::new).a(ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new).a(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new).a(ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new).a(ServerboundContainerAckPacket.class, ServerboundContainerAckPacket::new).a(ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new).a(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new).a(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new).a(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new).a(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new).a(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new).a(ServerboundInteractPacket.class, ServerboundInteractPacket::new).a(ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new).a(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new).a(ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new).a(ServerboundMovePlayerPacket.Pos.class, ServerboundMovePlayerPacket.Pos::new).a(ServerboundMovePlayerPacket.PosRot.class, ServerboundMovePlayerPacket.PosRot::new).a(ServerboundMovePlayerPacket.Rot.class, ServerboundMovePlayerPacket.Rot::new).a(ServerboundMovePlayerPacket.class, ServerboundMovePlayerPacket::new).a(ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new).a(ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new).a(ServerboundPickItemPacket.class, ServerboundPickItemPacket::new).a(ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new).a(ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new).a(ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new).a(ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new).a(ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new).a(ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new).a(ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new).a(ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new).a(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new).a(ServerboundSeenAdvancementsPacket.class, ServerboundSeenAdvancementsPacket::new).a(ServerboundSelectTradePacket.class, ServerboundSelectTradePacket::new).a(ServerboundSetBeaconPacket.class, ServerboundSetBeaconPacket::new).a(ServerboundSetCarriedItemPacket.class, ServerboundSetCarriedItemPacket::new).a(ServerboundSetCommandBlockPacket.class, ServerboundSetCommandBlockPacket::new).a(ServerboundSetCommandMinecartPacket.class, ServerboundSetCommandMinecartPacket::new).a(ServerboundSetCreativeModeSlotPacket.class, ServerboundSetCreativeModeSlotPacket::new).a(ServerboundSetJigsawBlockPacket.class, ServerboundSetJigsawBlockPacket::new).a(ServerboundSetStructureBlockPacket.class, ServerboundSetStructureBlockPacket::new).a(ServerboundSignUpdatePacket.class, ServerboundSignUpdatePacket::new).a(ServerboundSwingPacket.class, ServerboundSwingPacket::new).a(ServerboundTeleportToEntityPacket.class, ServerboundTeleportToEntityPacket::new).a(ServerboundUseItemOnPacket.class, ServerboundUseItemOnPacket::new).a(ServerboundUseItemPacket.class, ServerboundUseItemPacket::new))), STATUS(1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new).a(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)).a(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new).a(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new))), LOGIN(2, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new).a(ClientboundHelloPacket.class, ClientboundHelloPacket::new).a(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new).a(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new).a(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new)).a(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new).a(ServerboundKeyPacket.class, ServerboundKeyPacket::new).a(ServerboundCustomQueryPacket.class, ServerboundCustomQueryPacket::new))); ++ // Paper - fix decompile error - add generic names to < > like PacketListenerPlayOut ++ HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))), PLAY(0, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new).addPacket(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new).addPacket(ClientboundAddMobPacket.class, ClientboundAddMobPacket::new).addPacket(ClientboundAddPaintingPacket.class, ClientboundAddPaintingPacket::new).addPacket(ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new).addPacket(ClientboundAnimatePacket.class, ClientboundAnimatePacket::new).addPacket(ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new).addPacket(ClientboundBlockBreakAckPacket.class, ClientboundBlockBreakAckPacket::new).addPacket(ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new).addPacket(ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new).addPacket(ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new).addPacket(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new).addPacket(ClientboundBossEventPacket.class, ClientboundBossEventPacket::new).addPacket(ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new).addPacket(ClientboundChatPacket.class, ClientboundChatPacket::new).addPacket(ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new).addPacket(ClientboundCommandsPacket.class, ClientboundCommandsPacket::new).addPacket(ClientboundContainerAckPacket.class, ClientboundContainerAckPacket::new).addPacket(ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new).addPacket(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new).addPacket(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new).addPacket(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new).addPacket(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new).addPacket(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new).addPacket(ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new).addPacket(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new).addPacket(ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new).addPacket(ClientboundExplodePacket.class, ClientboundExplodePacket::new).addPacket(ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new).addPacket(ClientboundGameEventPacket.class, ClientboundGameEventPacket::new).addPacket(ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new).addPacket(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new).addPacket(ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new).addPacket(ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new).addPacket(ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new).addPacket(ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new).addPacket(ClientboundLoginPacket.class, ClientboundLoginPacket::new).addPacket(ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new).addPacket(ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new).addPacket(ClientboundMoveEntityPacket.Pos.class, ClientboundMoveEntityPacket.Pos::new).addPacket(ClientboundMoveEntityPacket.PosRot.class, ClientboundMoveEntityPacket.PosRot::new).addPacket(ClientboundMoveEntityPacket.Rot.class, ClientboundMoveEntityPacket.Rot::new).addPacket(ClientboundMoveEntityPacket.class, ClientboundMoveEntityPacket::new).addPacket(ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new).addPacket(ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new).addPacket(ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new).addPacket(ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new).addPacket(ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new).addPacket(ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new).addPacket(ClientboundPlayerCombatPacket.class, ClientboundPlayerCombatPacket::new).addPacket(ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new).addPacket(ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new).addPacket(ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new).addPacket(ClientboundRecipePacket.class, ClientboundRecipePacket::new).addPacket(ClientboundRemoveEntitiesPacket.class, ClientboundRemoveEntitiesPacket::new).addPacket(ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new).addPacket(ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new).addPacket(ClientboundRespawnPacket.class, ClientboundRespawnPacket::new).addPacket(ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new).addPacket(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new).addPacket(ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new).addPacket(ClientboundSetBorderPacket.class, ClientboundSetBorderPacket::new).addPacket(ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new).addPacket(ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new).addPacket(ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new).addPacket(ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new).addPacket(ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new).addPacket(ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new).addPacket(ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new).addPacket(ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new).addPacket(ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new).addPacket(ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new).addPacket(ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new).addPacket(ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new).addPacket(ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new).addPacket(ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new).addPacket(ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new).addPacket(ClientboundSetScorePacket.class, ClientboundSetScorePacket::new).addPacket(ClientboundSetTimePacket.class, ClientboundSetTimePacket::new).addPacket(ClientboundSetTitlesPacket.class, ClientboundSetTitlesPacket::new).addPacket(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new).addPacket(ClientboundSoundPacket.class, ClientboundSoundPacket::new).addPacket(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new).addPacket(ClientboundTabListPacket.class, ClientboundTabListPacket::new).addPacket(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new).addPacket(ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new).addPacket(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new).addPacket(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new).addPacket(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new).addPacket(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new).addPacket(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new).addPacket(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new).addPacket(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new).addPacket(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new).addPacket(ServerboundChatPacket.class, ServerboundChatPacket::new).addPacket(ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new).addPacket(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new).addPacket(ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new).addPacket(ServerboundContainerAckPacket.class, ServerboundContainerAckPacket::new).addPacket(ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new).addPacket(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new).addPacket(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new).addPacket(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new).addPacket(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new).addPacket(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new).addPacket(ServerboundInteractPacket.class, ServerboundInteractPacket::new).addPacket(ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new).addPacket(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new).addPacket(ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new).addPacket(ServerboundMovePlayerPacket.Pos.class, ServerboundMovePlayerPacket.Pos::new).addPacket(ServerboundMovePlayerPacket.PosRot.class, ServerboundMovePlayerPacket.PosRot::new).addPacket(ServerboundMovePlayerPacket.Rot.class, ServerboundMovePlayerPacket.Rot::new).addPacket(ServerboundMovePlayerPacket.class, ServerboundMovePlayerPacket::new).addPacket(ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new).addPacket(ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new).addPacket(ServerboundPickItemPacket.class, ServerboundPickItemPacket::new).addPacket(ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new).addPacket(ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new).addPacket(ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new).addPacket(ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new).addPacket(ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new).addPacket(ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new).addPacket(ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new).addPacket(ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new).addPacket(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new).addPacket(ServerboundSeenAdvancementsPacket.class, ServerboundSeenAdvancementsPacket::new).addPacket(ServerboundSelectTradePacket.class, ServerboundSelectTradePacket::new).addPacket(ServerboundSetBeaconPacket.class, ServerboundSetBeaconPacket::new).addPacket(ServerboundSetCarriedItemPacket.class, ServerboundSetCarriedItemPacket::new).addPacket(ServerboundSetCommandBlockPacket.class, ServerboundSetCommandBlockPacket::new).addPacket(ServerboundSetCommandMinecartPacket.class, ServerboundSetCommandMinecartPacket::new).addPacket(ServerboundSetCreativeModeSlotPacket.class, ServerboundSetCreativeModeSlotPacket::new).addPacket(ServerboundSetJigsawBlockPacket.class, ServerboundSetJigsawBlockPacket::new).addPacket(ServerboundSetStructureBlockPacket.class, ServerboundSetStructureBlockPacket::new).addPacket(ServerboundSignUpdatePacket.class, ServerboundSignUpdatePacket::new).addPacket(ServerboundSwingPacket.class, ServerboundSwingPacket::new).addPacket(ServerboundTeleportToEntityPacket.class, ServerboundTeleportToEntityPacket::new).addPacket(ServerboundUseItemOnPacket.class, ServerboundUseItemOnPacket::new).addPacket(ServerboundUseItemPacket.class, ServerboundUseItemPacket::new))), STATUS(1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new).addPacket(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)).addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new).addPacket(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new))), LOGIN(2, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new).addPacket(ClientboundHelloPacket.class, ClientboundHelloPacket::new).addPacket(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new).addPacket(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new).addPacket(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new).addPacket(ServerboundKeyPacket.class, ServerboundKeyPacket::new).addPacket(ServerboundCustomQueryPacket.class, ServerboundCustomQueryPacket::new))); + + private static final ConnectionProtocol[] LOOKUP = new ConnectionProtocol[4]; + private static final Map>, ConnectionProtocol> PROTOCOL_BY_PACKET = Maps.newHashMap(); +@@ -115,7 +121,7 @@ public enum ConnectionProtocol { + private final List>> idToConstructor; + + private PacketSet() { +- this.classToId = (Object2IntMap) Util.make((Object) (new Object2IntOpenHashMap()), (object2intopenhashmap) -> { ++ this.classToId = (Object2IntMap) Util.make(new Object2IntOpenHashMap(), (object2intopenhashmap) -> { // Paper - fix decompile error + object2intopenhashmap.defaultReturnValue(-1); + }); + this.idToConstructor = Lists.newArrayList(); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 21f461ce884bc547dbe81c5430be530423c1605c..37a51dee4cd37844e80fdd5c9853947201151dfc 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1673,9 +1673,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoopmap(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error + }, this).thenCompose((immutablelist) -> { +- return ServerResources.loadResources(immutablelist, this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this); ++ return ServerResources.loadResources(immutablelist, this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this); // Paper - decompile error + }).thenAcceptAsync((datapackresources) -> { + this.resources.close(); + this.resources = datapackresources; +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 37e938b258ee4eb5f5bab56145e83b640d80bcc7..23506a8903ce64fbfe849bb94e589bdbb6e61a74 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1913,7 +1913,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + // CraftBukkit - decompile error +- return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(it.unimi.dsi.fastutil.objects.Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { ++ return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { // Paper - decompile fix + return it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey() + ":" + it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue(); + }).collect(Collectors.joining(",")); + } catch (Exception exception) { +diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java +index ad8a9d14e17b5e40b2cc3a83154931734d6c73d7..cc4190b3a8904d1eaae0f542a3b3090583f5ff82 100644 +--- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java ++++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java +@@ -179,9 +179,9 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl + + public void tryScheduleUpdate() { + if ((!this.lightTasks.isEmpty() || super.hasLightWork()) && this.scheduled.compareAndSet(false, true)) { +- this.taskMailbox.tell((Object) (() -> { +- this.b(); +- this.g.set(false); ++ this.taskMailbox.tell((() -> { // Paper - decompile error ++ this.runUpdate(); ++ this.scheduled.set(false); + })); + } + +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index 90df41ec5081fe4ef2bc507e7289b18e0fea6e53..0c118d482e304c567fe7fe778c6ff386f960bdde 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -23,7 +23,7 @@ public final class Ticket implements Comparable> { + } else { + int j = Integer.compare(System.identityHashCode(this.type), System.identityHashCode(ticket.type)); + +- return j != 0 ? j : this.type.getComparator().compare(this.key, ticket.key); ++ return j != 0 ? j : this.type.getComparator().compare(this.key, (T)ticket.key); // Paper - decompile fix + } + } + +diff --git a/src/main/java/net/minecraft/stats/ServerStatsCounter.java b/src/main/java/net/minecraft/stats/ServerStatsCounter.java +index d624c390f8550c6aa44ca5920d127c901903ce27..7d435998680a363ad06c2e08139010c2573f7fb3 100644 +--- a/src/main/java/net/minecraft/stats/ServerStatsCounter.java ++++ b/src/main/java/net/minecraft/stats/ServerStatsCounter.java +@@ -203,7 +203,7 @@ public class ServerStatsCounter extends StatsCounter { + ObjectIterator objectiterator = this.stats.object2IntEntrySet().iterator(); + + while (objectiterator.hasNext()) { +- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); ++ Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix + Stat statistic = (Stat) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); + + ((JsonObject) map.computeIfAbsent(statistic.getType(), (statisticwrapper) -> { +diff --git a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java +index 74eb1ed6b3fafeaca7e65a88a982d759d6836853..66ad412e4368a8615cc66a97ac442c572813a3dd 100644 +--- a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java ++++ b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java +@@ -18,11 +18,18 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + + public CrudeIncrementalIntIdentityHashBiMap(int size) { + size = (int) ((float) size / 0.8F); +- this.keys = (Object[]) (new Object[size]); ++ this.keys = (K[]) (new Object[size]); // Paper - decompile fix + this.values = new int[size]; +- this.byId = (Object[]) (new Object[size]); ++ this.byId = (K[]) (new Object[size]); // Paper - decompile fix + } + ++ // Paper start - decompile fix ++ @Override ++ public int a(K k) { ++ return getId(k); ++ } ++ // Paper end ++ + public int getId(@Nullable K entry) { + return this.getValue(this.indexOf(entry, this.hash(entry))); + } +@@ -56,9 +63,9 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + K[] ak = this.keys; + int[] aint = this.values; + +- this.keys = (Object[]) (new Object[newSize]); ++ this.keys = (K[]) (new Object[newSize]); // Paper - decompile fix + this.values = new int[newSize]; +- this.byId = (Object[]) (new Object[newSize]); ++ this.byId = (K[]) (new Object[newSize]); // Paper - decompile fix + this.nextId = 0; + this.size = 0; + +diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java +index be40fc388c501c311d661927025f1c572f3b3493..93813a508be1e1e600a8211f9822f2087328de70 100644 +--- a/src/main/java/net/minecraft/util/SortedArraySet.java ++++ b/src/main/java/net/minecraft/util/SortedArraySet.java +@@ -23,11 +23,11 @@ public class SortedArraySet extends AbstractSet { + } + + public static > SortedArraySet create(int initialCapacity) { +- return new SortedArraySet<>(initialCapacity, Comparator.naturalOrder()); ++ return new SortedArraySet<>(initialCapacity, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix + } + + private static T[] castRawArray(Object[] array) { +- return (Object[]) array; ++ return (T[])array; // Paper - decompile fix + } + + private int findIndex(T object) { +@@ -101,7 +101,7 @@ public class SortedArraySet extends AbstractSet { + } + + public boolean remove(Object object) { +- int i = this.findIndex(object); ++ int i = this.findIndex((T)object); // Paper - decompile fix + + if (i >= 0) { + this.removeInternal(i); +@@ -116,7 +116,7 @@ public class SortedArraySet extends AbstractSet { + } + + public boolean contains(Object object) { +- int i = this.findIndex(object); ++ int i = this.findIndex((T)object); // Paper - decompile fix + + return i >= 0; + } +@@ -135,7 +135,7 @@ public class SortedArraySet extends AbstractSet { + + public U[] toArray(U[] au) { + if (au.length < this.size) { +- return (Object[]) Arrays.copyOf(this.contents, this.size, au.getClass()); ++ return (U[])Arrays.copyOf(this.contents, this.size, au.getClass()); // Paper - decompile fix + } else { + System.arraycopy(this.contents, 0, au, 0, this.size); + if (au.length > this.size) { +diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +index d9375f83de6d069f603f8a48cc5b02194e940052..03831adce7905916423d8c3834c42c90f3a1ca8f 100644 +--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java ++++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +@@ -55,7 +55,7 @@ public abstract class BlockableEventLoop implements Processo + return this.submitAsync(task); + } else { + task.run(); +- return CompletableFuture.completedFuture((Object) null); ++ return CompletableFuture.completedFuture(null); // Paper - decompile fix + } + } + +@@ -90,14 +90,14 @@ public abstract class BlockableEventLoop implements Processo + } + + protected boolean pollTask() { +- R r0 = (Runnable) this.pendingRunnables.peek(); ++ R r0 = this.pendingRunnables.peek(); // Paper - decompile fix + + if (r0 == null) { + return false; + } else if (this.blockingCount == 0 && !this.shouldRun(r0)) { + return false; + } else { +- this.doRunTask((Runnable) this.pendingRunnables.remove()); ++ this.doRunTask(this.pendingRunnables.remove()); // Paper - decompile fix + return true; + } + } +diff --git a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java +index cc77767947e458e7205e616dce3bea8da09ca0cf..c763aa0c0cf49dd844af94a820103258b49021ae 100644 +--- a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java ++++ b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java +@@ -100,7 +100,7 @@ public class ProcessorMailbox implements ProcessorHandle, AutoCloseable, R + + public void run() { + try { +- this.pollUntil((i) -> { ++ this.pollUntil((int i) -> { // Paper - decompile fix + return i == 0; + }); + } finally { +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +index 8f686f8608771d0a444dfd51dd4eabc90c6b2262..33a8604fa6c6431ccc5f61e484c163e09f1625a0 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +@@ -191,9 +191,9 @@ public class PoiManager extends SectionStorage { + } + + private static boolean mayHavePoi(LevelChunkSection chunksection) { +- Set set = PoiType.ALL_STATES; ++ Set set = PoiType.ALL_STATES; // Paper - decompile error + +- set.getClass(); ++ //set.getClass(); // Paper - decompile error + return chunksection.maybeHas(set::contains); + } + +@@ -211,7 +211,7 @@ public class PoiManager extends SectionStorage { + SectionPos.aroundChunk(new ChunkPos(pos), Math.floorDiv(radius, 16)).map((sectionposition) -> { + return Pair.of(sectionposition, this.getOrLoad(sectionposition.asLong())); + }).filter((pair) -> { +- return !(Boolean) ((Optional) pair.getSecond()).map(PoiSection::a).orElse(false); ++ return !(Boolean) (pair.getSecond()).map(PoiSection::isValid).orElse(false); // Paper - decompile fix + }).map((pair) -> { + return ((SectionPos) pair.getFirst()).chunk(); + }).filter((chunkcoordintpair) -> { +@@ -257,13 +257,13 @@ public class PoiManager extends SectionStorage { + + public static enum Occupancy { + +- HAS_SPACE(PoiRecord::d), IS_OCCUPIED(PoiRecord::e), ANY((villageplacerecord) -> { ++ HAS_SPACE(PoiRecord::hasSpace), IS_OCCUPIED(PoiRecord::isOccupied), ANY((villageplacerecord) -> { + return true; + }); + + private final Predicate test; + +- private Occupancy(Predicate predicate) { ++ private Occupancy(Predicate predicate) { // Paper - decompile fix + this.test = predicate; + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +index 97317517a729877e307407ca9fab5fa58657fe38..a41f61daf6cbbb13d0b86cdbad8a4cae00368653 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +@@ -65,7 +65,7 @@ public class Vindicator extends AbstractIllager { + this.goalSelector.addGoal(2, new AbstractIllager.RaiderOpenDoorGoal(this)); + this.goalSelector.addGoal(3, new Raider.HoldGroundAttackGoal(this, 10.0F)); + this.goalSelector.addGoal(4, new Vindicator.VindicatorMeleeAttackGoal(this)); +- this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).canUse()); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers(new Class[0])); // Paper - decompile fix + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); +diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +index ad4e181b24829980dc12f46807ec1c5226bd8e0c..fd1b84baae5f333c58dbbdcbfaa9198328f0961d 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java ++++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +@@ -47,12 +47,12 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + + public class VillagerTrades { + +- public static final Map> TRADES = (Map) Util.make((Object) Maps.newHashMap(), (hashmap) -> { ++ public static final Map> TRADES = Util.make(Maps.newHashMap(), (hashmap) -> { // Paper - decompile fix + hashmap.put(VillagerProfession.FARMER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WHEAT, 20, 16, 2), new VillagerTrades.EmeraldForItems(Items.POTATO, 26, 16, 2), new VillagerTrades.EmeraldForItems(Items.CARROT, 22, 16, 2), new VillagerTrades.EmeraldForItems(Items.BEETROOT, 15, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.BREAD, 1, 6, 16, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Blocks.PUMPKIN, 6, 12, 10), new VillagerTrades.ItemsForEmeralds(Items.PUMPKIN_PIE, 1, 4, 5), new VillagerTrades.ItemsForEmeralds(Items.APPLE, 1, 4, 16, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.COOKIE, 3, 18, 10), new VillagerTrades.EmeraldForItems(Blocks.MELON, 4, 12, 20)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Blocks.CAKE, 1, 1, 12, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.NIGHT_VISION, 100, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.JUMP, 160, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.WEAKNESS, 140, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.BLINDNESS, 120, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.POISON, 280, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.SATURATION, 7, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.GOLDEN_CARROT, 3, 3, 30), new VillagerTrades.ItemsForEmeralds(Items.GLISTERING_MELON_SLICE, 4, 3, 30)}))); +- hashmap.put(VillagerProfession.FISHERMAN, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STRING, 20, 16, 2), new VillagerTrades.EmeraldForItems(Items.COAL, 10, 16, 2), new VillagerTrades.ItemsAndEmeraldsToItems(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.ItemsForEmeralds(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COD, 15, 16, 10), new VillagerTrades.ItemsAndEmeraldsToItems(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.ItemsForEmeralds(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.SALMON, 13, 16, 20), new VillagerTrades.EnchantedItemForEmeralds(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.EmeraldsForVillagerTypeItem(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); ++ hashmap.put(VillagerProfession.FISHERMAN, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STRING, 20, 16, 2), new VillagerTrades.EmeraldForItems(Items.COAL, 10, 16, 2), new VillagerTrades.ItemsAndEmeraldsToItems(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.ItemsForEmeralds(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COD, 15, 16, 10), new VillagerTrades.ItemsAndEmeraldsToItems(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.ItemsForEmeralds(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.SALMON, 13, 16, 20), new VillagerTrades.EnchantedItemForEmeralds(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.EmeraldsForVillagerTypeItem(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); // Paper - add to ImmutableMap..builder() + hashmap.put(VillagerProfession.SHEPHERD, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Blocks.WHITE_WOOL, 18, 16, 2), new VillagerTrades.EmeraldForItems(Blocks.BROWN_WOOL, 18, 16, 2), new VillagerTrades.EmeraldForItems(Blocks.BLACK_WOOL, 18, 16, 2), new VillagerTrades.EmeraldForItems(Blocks.GRAY_WOOL, 18, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.SHEARS, 2, 1, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WHITE_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.GRAY_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.BLACK_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.LIGHT_BLUE_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.LIME_DYE, 12, 16, 10), new VillagerTrades.ItemsForEmeralds(Blocks.WHITE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.ORANGE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.MAGENTA_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.YELLOW_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIME_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PINK_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.CYAN_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PURPLE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BROWN_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GREEN_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.RED_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLACK_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.WHITE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.ORANGE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.MAGENTA_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.YELLOW_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIME_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PINK_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.CYAN_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PURPLE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BROWN_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GREEN_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.RED_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLACK_CARPET, 1, 4, 16, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.YELLOW_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.LIGHT_GRAY_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.ORANGE_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.RED_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.PINK_DYE, 12, 16, 20), new VillagerTrades.ItemsForEmeralds(Blocks.WHITE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.YELLOW_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.RED_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.BLACK_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.BLUE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.BROWN_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.CYAN_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.GRAY_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.GREEN_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_BLUE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_GRAY_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.LIME_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.MAGENTA_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.ORANGE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.PINK_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.PURPLE_BED, 3, 1, 12, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.BROWN_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.PURPLE_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.BLUE_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.GREEN_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.MAGENTA_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.CYAN_DYE, 12, 16, 30), new VillagerTrades.ItemsForEmeralds(Items.WHITE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.RED_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.PINK_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.GREEN_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.LIME_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.GRAY_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.BLACK_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.PURPLE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.MAGENTA_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.CYAN_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.BROWN_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.YELLOW_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.ORANGE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_GRAY_BANNER, 3, 1, 12, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.PAINTING, 2, 3, 30)}))); + hashmap.put(VillagerProfession.FLETCHER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STICK, 32, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.ARROW, 1, 16, 1), new VillagerTrades.ItemsAndEmeraldsToItems(Blocks.GRAVEL, 10, Items.FLINT, 10, 12, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.FLINT, 26, 12, 10), new VillagerTrades.ItemsForEmeralds(Items.BOW, 2, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STRING, 14, 16, 20), new VillagerTrades.ItemsForEmeralds(Items.CROSSBOW, 3, 1, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.FEATHER, 24, 16, 30), new VillagerTrades.EnchantedItemForEmeralds(Items.BOW, 2, 3, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.es, 8, 12, 30), new VillagerTrades.EnchantedItemForEmeralds(Items.CROSSBOW, 3, 3, 15), new VillagerTrades.TippedArrowForItemsAndEmeralds(Items.ARROW, 5, Items.TIPPED_ARROW, 5, 2, 12, 30)}))); +- hashmap.put(VillagerProfession.LIBRARIAN, toIntMap(ImmutableMap.builder().put(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PAPER, 24, 16, 2), new VillagerTrades.EnchantBookForEmeralds(1), new VillagerTrades.ItemsForEmeralds(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.BOOK, 4, 12, 10), new VillagerTrades.EnchantBookForEmeralds(5), new VillagerTrades.ItemsForEmeralds(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.INK_SAC, 5, 12, 20), new VillagerTrades.EnchantBookForEmeralds(10), new VillagerTrades.ItemsForEmeralds(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.EnchantBookForEmeralds(15), new VillagerTrades.ItemsForEmeralds(Items.CLOCK, 5, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.NAME_TAG, 20, 1, 30)}).build())); ++ hashmap.put(VillagerProfession.LIBRARIAN, toIntMap(ImmutableMap.builder().put(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PAPER, 24, 16, 2), new VillagerTrades.EnchantBookForEmeralds(1), new VillagerTrades.ItemsForEmeralds(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.BOOK, 4, 12, 10), new VillagerTrades.EnchantBookForEmeralds(5), new VillagerTrades.ItemsForEmeralds(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.INK_SAC, 5, 12, 20), new VillagerTrades.EnchantBookForEmeralds(10), new VillagerTrades.ItemsForEmeralds(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.EnchantBookForEmeralds(15), new VillagerTrades.ItemsForEmeralds(Items.CLOCK, 5, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.NAME_TAG, 20, 1, 30)}).build())); // Paper - add to ImmutableMap..builder() + hashmap.put(VillagerProfession.CARTOGRAPHER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PAPER, 24, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.MAP, 7, 1, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.dP, 11, 16, 10), new VillagerTrades.TreasureMapForEmeralds(13, StructureFeature.OCEAN_MONUMENT, MapDecoration.Type.MONUMENT, 12, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COMPASS, 1, 12, 20), new VillagerTrades.TreasureMapForEmeralds(14, StructureFeature.WOODLAND_MANSION, MapDecoration.Type.MANSION, 12, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.ITEM_FRAME, 7, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.WHITE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.BLUE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_BLUE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.RED_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.PINK_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.GREEN_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.LIME_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.GRAY_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.BLACK_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.PURPLE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.MAGENTA_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.CYAN_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.BROWN_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.YELLOW_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.ORANGE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_GRAY_BANNER, 3, 1, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.GLOBE_BANNER_PATTERN, 8, 1, 30)}))); + hashmap.put(VillagerProfession.CLERIC, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.ROTTEN_FLESH, 32, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.REDSTONE, 1, 2, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.GOLD_INGOT, 3, 12, 10), new VillagerTrades.ItemsForEmeralds(Items.LAPIS_LAZULI, 1, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.RABBIT_FOOT, 2, 12, 20), new VillagerTrades.ItemsForEmeralds(Blocks.GLOWSTONE, 4, 1, 12, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.SCUTE, 4, 12, 30), new VillagerTrades.EmeraldForItems(Items.GLASS_BOTTLE, 9, 12, 30), new VillagerTrades.ItemsForEmeralds(Items.ENDER_PEARL, 5, 1, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.NETHER_WART, 22, 12, 30), new VillagerTrades.ItemsForEmeralds(Items.EXPERIENCE_BOTTLE, 3, 1, 30)}))); + hashmap.put(VillagerProfession.ARMORER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COAL, 15, 16, 2), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_LEGGINGS), 7, 1, 12, 1, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_BOOTS), 4, 1, 12, 1, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_HELMET), 5, 1, 12, 1, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_CHESTPLATE), 9, 1, 12, 1, 0.2F)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.IRON_INGOT, 4, 12, 10), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.rj), 36, 1, 12, 5, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_BOOTS), 1, 1, 12, 5, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_LEGGINGS), 3, 1, 12, 5, 0.2F)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.LAVA_BUCKET, 1, 12, 20), new VillagerTrades.EmeraldForItems(Items.DIAMOND, 1, 12, 20), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_HELMET), 1, 1, 12, 10, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_CHESTPLATE), 4, 1, 12, 10, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.SHIELD), 5, 1, 12, 10, 0.2F)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_LEGGINGS, 14, 3, 15, 0.2F), new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_BOOTS, 8, 3, 15, 0.2F)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_HELMET, 8, 3, 30, 0.2F), new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_CHESTPLATE, 16, 3, 30, 0.2F)}))); +diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +index 86d7af20fad04405f95c71e078d41070abdc43ad..c4777997cfff364818fbaee70afd7c79099213fb 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java ++++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +@@ -75,7 +75,7 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { + } + + this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { +- return (entry1.getValue()); // CraftBukkit ++ return entry1.getValue(); // CraftBukkit // Paper - decompile fix - *shrugs internally* + })); + RecipeManager.LOGGER.info("Loaded {} recipes", map1.size()); + } +diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java +index 1276769b22ae21f0ff4271ecc72d4aa39ddff23f..7e7a58b9a9ececdcc37fc33b33703428eb1d5faf 100644 +--- a/src/main/java/net/minecraft/world/level/EntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/EntityGetter.java +@@ -167,22 +167,22 @@ public interface EntityGetter { + + @Nullable + default T getNearestEntity(Class entityClass, TargetingConditions targetPredicate, @Nullable LivingEntity entity, double x, double y, double z, AABB box) { +- return this.getNearestEntity(this.getEntitiesOfClass(entityClass, box, (Predicate) null), targetPredicate, entity, x, y, z); ++ return this.getNearestEntity(this.getEntitiesOfClass(entityClass, box, null), targetPredicate, entity, x, y, z); // Paper - decompile fix + } + + @Nullable + default T getNearestLoadedEntity(Class entityClass, TargetingConditions targetPredicate, @Nullable LivingEntity entity, double x, double y, double z, AABB box) { +- return this.getNearestEntity(this.getLoadedEntitiesOfClass(entityClass, box, (Predicate) null), targetPredicate, entity, x, y, z); ++ return this.getNearestEntity(this.getLoadedEntitiesOfClass(entityClass, box, null), targetPredicate, entity, x, y, z); // Paper - decompile fix + } + + @Nullable + default T getNearestEntity(List entityList, TargetingConditions targetPredicate, @Nullable LivingEntity entity, double x, double y, double z) { + double d3 = -1.0D; + T t0 = null; +- Iterator iterator = entityList.iterator(); ++ Iterator iterator = entityList.iterator(); // Paper - decompile fix + + while (iterator.hasNext()) { +- T t1 = (LivingEntity) iterator.next(); ++ T t1 = iterator.next(); // Paper - decompile fix + + if (targetPredicate.test(entity, t1)) { + double d4 = t1.distanceToSqr(x, y, z); +@@ -215,10 +215,10 @@ public interface EntityGetter { + default List getNearbyEntities(Class entityClass, TargetingConditions targetPredicate, LivingEntity targetingEntity, AABB box) { + List list = this.getEntitiesOfClass(entityClass, box, (Predicate) null); + List list1 = Lists.newArrayList(); +- Iterator iterator = list.iterator(); ++ Iterator iterator = list.iterator(); // Paper - decompile fix + + while (iterator.hasNext()) { +- T t0 = (LivingEntity) iterator.next(); ++ T t0 = iterator.next(); // Paper - decompile fix + + if (targetPredicate.test(targetingEntity, t0)) { + list1.add(t0); +diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java +index c6e64c5182d564664464e26df27e6b5f7da418e6..d97e266b83bb331fcd4031046a5843d29ce53164 100644 +--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java ++++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java +@@ -38,13 +38,13 @@ public class TickNextTickData { + return this.pos.hashCode(); + } + +- public static Comparator> createTimeComparator() { ++ public static Comparator createTimeComparator() { // Paper - decompile fix + return Comparator.comparingLong((nextticklistentry) -> { +- return nextticklistentry.b; ++ return ((TickNextTickData) nextticklistentry).triggerTick; // Paper - decompile fix + }).thenComparing((nextticklistentry) -> { +- return nextticklistentry.c; ++ return ((TickNextTickData) nextticklistentry).priority; // Paper - decompile fix + }).thenComparingLong((nextticklistentry) -> { +- return nextticklistentry.f; ++ return ((TickNextTickData) nextticklistentry).c; // Paper - decompile fix + }); + } + +diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java +index 79be56c26b66351bcfcd96c9967f0ce91e40d5ce..ed83335175bb882741dfaef251ab30ce1590f74c 100644 +--- a/src/main/java/net/minecraft/world/level/biome/Biome.java ++++ b/src/main/java/net/minecraft/world/level/biome/Biome.java +@@ -49,36 +49,43 @@ import org.apache.logging.log4j.Logger; + public final class Biome { + + public static final Logger LOGGER = LogManager.getLogger(); ++ // Paper start ++ private static class dProxy extends Biome.ClimateSettings { ++ private dProxy(Precipitation precipitation, float temperature, TemperatureModifier temperatureModifier, float downfall) { ++ super(precipitation, temperature, temperatureModifier, downfall); ++ } ++ }; ++ // Paper end + public static final Codec DIRECT_CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { +- return biomebase.j; ++ return instance.group(dProxy.CODEC.forGetter((biomebase) -> { // Paper ++ return biomebase.climateSettings; + }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biomebase) -> { +- return biomebase.o; ++ return biomebase.biomeCategory; + }), Codec.FLOAT.fieldOf("depth").forGetter((biomebase) -> { +- return biomebase.m; ++ return biomebase.depth; + }), Codec.FLOAT.fieldOf("scale").forGetter((biomebase) -> { +- return biomebase.n; ++ return biomebase.scale; + }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biomebase) -> { +- return biomebase.p; ++ return biomebase.specialEffects; + }), BiomeGenerationSettings.CODEC.forGetter((biomebase) -> { +- return biomebase.k; ++ return biomebase.generationSettings; + }), MobSpawnSettings.CODEC.forGetter((biomebase) -> { +- return biomebase.l; ++ return biomebase.mobSettings; + })).apply(instance, Biome::new); + }); + public static final Codec NETWORK_CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { +- return biomebase.j; ++ return instance.group(dProxy.CODEC.forGetter((biomebase) -> { // Paper ++ return biomebase.climateSettings; + }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biomebase) -> { +- return biomebase.o; ++ return biomebase.biomeCategory; + }), Codec.FLOAT.fieldOf("depth").forGetter((biomebase) -> { +- return biomebase.m; ++ return biomebase.depth; + }), Codec.FLOAT.fieldOf("scale").forGetter((biomebase) -> { +- return biomebase.n; ++ return biomebase.scale; + }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biomebase) -> { +- return biomebase.p; ++ return biomebase.specialEffects; + })).apply(instance, (biomebase_d, biomebase_geography, ofloat, ofloat1, biomefog) -> { +- return new BiomeBase(biomebase_d, biomebase_geography, ofloat, ofloat1, biomefog, BiomeSettingsGeneration.b, BiomeSettingsMobs.b); ++ return new Biome(biomebase_d, biomebase_geography, ofloat, ofloat1, biomefog, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY); + }); + }); + public static final Codec> CODEC = RegistryFileCodec.a(Registry.BIOME_REGISTRY, Biome.DIRECT_CODEC); +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +index 94a02cb23a210ee0cc789db15853b6672ec673f4..73888713746e7ddd72ba9ac9d33d8e616eb3bd25 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +@@ -160,7 +160,7 @@ public class PistonMovingBlockEntity extends BlockEntity implements TickableBloc + private static void moveEntityByPiston(Direction enumdirection, Entity entity, double d0, Direction enumdirection1) { + PistonMovingBlockEntity.NOCLIP.set(enumdirection); + entity.move(MoverType.PISTON, new Vec3(d0 * (double) enumdirection1.getStepX(), d0 * (double) enumdirection1.getStepY(), d0 * (double) enumdirection1.getStepZ())); +- PistonMovingBlockEntity.NOCLIP.set((Object) null); ++ PistonMovingBlockEntity.NOCLIP.set(null); // Paper - decompile fix + } + + private void moveStuckEntities(float f) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java +index 95ad396fc46a587d08b87943aa05dd72d35efd3a..60ce75c7f94c995d3753c40bc8d1ec09b4d37b1a 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java ++++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java +@@ -28,12 +28,12 @@ public abstract class StateHolder { + } else { + Property iblockstate = (Property) entry.getKey(); + +- return iblockstate.getName() + "=" + this.getName(iblockstate, (Comparable) entry.getValue()); ++ return iblockstate.getName() + "=" + this.getName((Property) iblockstate, (Comparable) entry.getValue()); // Paper - decompile fix + } + } + +- private > String getName(Property property, Comparable value) { +- return property.value(value); ++ private > String getName(Property property, T value) { // Paper - decompile error ++ return property.getName(value); + } + }; + protected final O owner; +@@ -48,11 +48,11 @@ public abstract class StateHolder { + } + + public > S cycle(Property property) { +- return this.setValue(property, (Comparable) findNextInCollection(property.getPossibleValues(), (Object) this.getValue(property))); ++ return this.setValue(property, findNextInCollection(property.getPossibleValues(), this.getValue(property))); // Paper - decompile error + } + + protected static T findNextInCollection(Collection values, T value) { +- Iterator iterator = values.iterator(); ++ Iterator iterator = values.iterator(); // Paper + + do { + if (!iterator.hasNext()) { +@@ -94,7 +94,7 @@ public abstract class StateHolder { + if (comparable == null) { + throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner); + } else { +- return (Comparable) property.getValueClass().cast(comparable); ++ return property.getValueClass().cast(comparable); // Paper - decompile error + } + } + +@@ -110,7 +110,7 @@ public abstract class StateHolder { + if (comparable == null) { + throw new IllegalArgumentException("Cannot set property " + property + " as it does not exist in " + this.owner); + } else if (comparable == value) { +- return this; ++ return (S) this; // Paper - decompile error + } else { + S s0 = this.neighbours.get(property, value); + +@@ -162,7 +162,7 @@ public abstract class StateHolder { + return codec.dispatch("Name", (iblockdataholder) -> { + return iblockdataholder.owner; + }, (object) -> { +- S s0 = (StateHolder) ownerToStateFunction.apply(object); ++ S s0 = ownerToStateFunction.apply(object); // Paper - decompile error + + return s0.getValues().isEmpty() ? Codec.unit(s0) : s0.propertiesCodec.fieldOf("Properties").codec(); + }); +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +index 9e0724c4bf06d207898e477e35412c09f3aa0f74..b5817645727f2af2785e0987ba824f431d4e9e32 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +@@ -21,10 +21,10 @@ public class EnumProperty & StringRepresentable> extends Prope + protected EnumProperty(String name, Class type, Collection values) { + super(name, type); + this.values = ImmutableSet.copyOf(values); +- Iterator iterator = values.iterator(); ++ Iterator iterator = values.iterator(); // Paper - decompile fix + + while (iterator.hasNext()) { +- T t0 = (Enum) iterator.next(); ++ T t0 = iterator.next(); // Paper - Decompile fix + String s1 = ((StringRepresentable) t0).getSerializedName(); + + if (this.names.containsKey(s1)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java +index 5a16a0079bc297fb4572d2e6e9b07a9d1a53c906..8cc07c70fde81e44679f3ea7d9a4c6b2447885d4 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java +@@ -17,12 +17,10 @@ public abstract class Property> { + private final Codec> valueCodec; + + protected Property(String name, Class type) { +- this.codec = Codec.STRING.comapFlatMap((s1) -> { +- return (DataResult) this.getValue(s1).map(DataResult::success).orElseGet(() -> { +- return DataResult.error("Unable to read property: " + this + " with value: " + s1); +- }); +- }, this::getName); +- this.valueCodec = this.codec.xmap(this::b, Property.clazz::b); ++ this.codec = Codec.STRING.comapFlatMap((s1) -> this.getValue(s1).map(DataResult::success).orElseGet(() -> { // Paper - decompile error ++ return DataResult.error("Unable to read property: " + this + " with value: " + s1); ++ }), this::getName); ++ this.valueCodec = this.codec.xmap(this::value, (Property.Value param) -> param.value()); // Paper - decompile fix + this.clazz = type; + this.name = name; + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +index 977ac6db5fbdd001c306ee6aa396bb395384dd8f..7de765786b3504dcffab98bb0d9dac64b30b3325 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +@@ -89,7 +89,7 @@ public class IOWorker implements AutoCloseable { + return this.submitTask(() -> { + try { + this.storage.flush(); +- return Either.left((Object) null); ++ return Either.left(null); // Paper - decompile error + } catch (Exception exception) { + IOWorker.LOGGER.warn("Failed to synchronized chunks", exception); + return Either.right(exception); +@@ -123,13 +123,13 @@ public class IOWorker implements AutoCloseable { + } + + private void tellStorePending() { +- this.mailbox.tell((Object) (new StrictQueue.IntRunnable(IOWorker.Priority.LOW.ordinal(), this::storePendingChunk))); ++ this.mailbox.tell((new StrictQueue.IntRunnable(IOWorker.Priority.LOW.ordinal(), this::storePendingChunk))); // Paper - decompile error + } + + private void runStore(ChunkPos pos, IOWorker.PendingStore ioworker_a) { + try { + this.storage.write(pos, ioworker_a.data); +- ioworker_a.result.complete((Object) null); ++ ioworker_a.result.complete(null); // Paper - decompile fix + } catch (Exception exception) { + IOWorker.LOGGER.error("Failed to store chunk {}", pos, exception); + ioworker_a.result.completeExceptionally(exception); +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 217065b88178342159154490ffabe0fe7d32d7bf..2386ffeec60851ba192b89bc6fd7ffff9c56aff5 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -430,7 +430,7 @@ public class EndDragonFight { + } + } + +- worldgenendtrophy.configured((FeatureConfiguration) FeatureConfiguration.NONE).a(this.level, this.level.getChunkSource().getGenerator(), new Random(), this.portalLocation); ++ worldgenendtrophy.configured(FeatureConfiguration.NONE).place(this.level, this.level.getChunkSource().getGenerator(), new Random(), this.portalLocation); // Paper - decompile fix + } + + private EnderDragon createNewDragon() { +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +index 418abfdc85de157d23807059670a2dfc964cbd5f..9f60abfe0a37e30c5528a1ca0546295b00598798 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +@@ -71,13 +71,13 @@ public abstract class StructureFeature { + public static final StructureFeature BASTION_REMNANT = register("Bastion_Remnant", new BastionFeature(JigsawConfiguration.CODEC), GenerationStep.Decoration.SURFACE_STRUCTURES); + public static final List> NOISE_AFFECTING_FEATURES = ImmutableList.of(StructureFeature.PILLAGER_OUTPOST, StructureFeature.VILLAGE, StructureFeature.NETHER_FOSSIL); + private static final ResourceLocation JIGSAW_RENAME = new ResourceLocation("jigsaw"); +- private static final Map RENAMES = ImmutableMap.builder().put(new ResourceLocation("nvi"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("pcp"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("bastionremnant"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("runtime"), StructureFeature.JIGSAW_RENAME).build(); ++ private static final Map RENAMES = ImmutableMap.builder().put(new ResourceLocation("nvi"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("pcp"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("bastionremnant"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("runtime"), StructureFeature.JIGSAW_RENAME).build(); // Paper - decompile fix + private final Codec>> y; + + private static > F register(String name, F structureFeature, GenerationStep.Decoration step) { + StructureFeature.STRUCTURES_REGISTRY.put(name.toLowerCase(Locale.ROOT), structureFeature); + StructureFeature.STEP.put(structureFeature, step); +- return (StructureFeature) Registry.registerDefaulted(Registry.STRUCTURE_FEATURE, name.toLowerCase(Locale.ROOT), (Object) structureFeature); ++ return (F) Registry.>register(Registry.STRUCTURE_FEATURE, name.toLowerCase(Locale.ROOT), structureFeature); // Paper - decomp fix + } + + public StructureFeature(Codec codec) { +diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +index cd2efdd5802605de5d3d636ce1b4a796e0c13310..c304637ae8f80c65b58e8ba8a27609b532bb1184 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +@@ -34,10 +34,10 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage= l) { +diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +index b106f2458361fc2a9168bbef8c9e5b35d8e359fb..60b7fdf9c092e8105d41f4af02a08651624f3eb9 100644 +--- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +@@ -44,7 +44,7 @@ public class DimensionDataStorage { + if (t0 != null) { + return t0; + } else { +- T t1 = (SavedData) factory.get(); ++ T t1 = factory.get(); // Paper - decompile fix + + this.set(t1); + return t1; +@@ -53,7 +53,7 @@ public class DimensionDataStorage { + + @Nullable + public T get(Supplier factory, String id) { +- SavedData persistentbase = (SavedData) this.cache.get(id); ++ T persistentbase = (T) this.cache.get(id); // Paper - decompile fix + + if (persistentbase == null && !this.cache.containsKey(id)) { + persistentbase = this.readSavedData(factory, id); +@@ -69,7 +69,7 @@ public class DimensionDataStorage { + File file = this.getDataFile(id); + + if (file.exists()) { +- T t0 = (SavedData) factory.get(); ++ T t0 = factory.get(); // Paper - decompile fix + CompoundTag nbttagcompound = this.readTagFromDisk(id, SharedConstants.getCurrentVersion().getWorldVersion()); + + t0.load(nbttagcompound.getCompound("data")); +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java +index 4093a4a1f924ac722d60599be9688a88d26a5c1a..802eb7fe690adae03c80db3fc0f72ea2788a3b2c 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java +@@ -42,7 +42,7 @@ public abstract class LootPoolEntryContainer implements ComposableEntryContainer + + // CraftBukkit start + @Override +- public final void serialize(JsonObject json, T entry, JsonSerializationContext context) { ++ public void serialize(JsonObject json, T entry, JsonSerializationContext context) { // Paper - remove final + if (!org.apache.commons.lang3.ArrayUtils.isEmpty(entry.conditions)) { + json.add("conditions", context.serialize(entry.conditions)); + } +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java +index c942459e0a492dd9fab296ef60d272651d13f049..ceb5e5405ed20c8de954847bbb269109107a43fc 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java +@@ -132,7 +132,7 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer + @Override + public T b(LootItemFunction.Builder lootitemfunction_a) { + this.functions.add(lootitemfunction_a.b()); +- return (LootPoolSingletonContainer.Builder) this.getThis(); ++ return this.getThis(); // Paper - decompile fix + } + + protected LootItemFunction[] getFunctions() { +@@ -141,12 +141,12 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer + + public T setWeight(int weight) { + this.weight = weight; +- return (LootPoolSingletonContainer.Builder) this.getThis(); ++ return this.getThis(); // Paper - decompile fix + } + + public T setQuality(int quality) { + this.quality = quality; +- return (LootPoolSingletonContainer.Builder) this.getThis(); ++ return this.getThis(); // Paper - decompile fix + } + } + +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java +index b77c921548ff55bab62bf37fa411ad1fd8d38f82..a3ce120b0da62f9be938c58c3414ce997f5d30ea 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java +@@ -89,7 +89,7 @@ public class ExplorationMapFunction extends LootItemConditionalFunction { + public Serializer() {} + + public void serialize(JsonObject json, ExplorationMapFunction object, JsonSerializationContext context) { +- super.serialize(json, (LootItemConditionalFunction) object, context); ++ super.serialize(json, object, context); // Paper - decompile fix + if (!object.destination.equals(ExplorationMapFunction.DEFAULT_FEATURE)) { + json.add("destination", context.serialize(object.destination.getFeatureName())); + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java +index bc1798f130184d6b107d7a9ba972cab686534439..f0e74daa5bb9e88c028225e7c71deb04c481a7ac 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java +@@ -38,7 +38,7 @@ public final class IndirectMerger implements IndexMerger { + double d1 = flag4 ? first.getDouble(i++) : second.getDouble(j++); + + if ((i != 0 && flag2 || flag4 || includeSecondOnly) && (j != 0 && flag3 || !flag4 || includeFirstOnly)) { +- if (d0 < d1 - 1.0E-7D) { ++ if (!(d0 >= d1 - 1.0E-7D)) { // Paper - decompile error - welcome to hell + this.firstIndices.add(i - 1); + this.secondIndices.add(j - 1); + this.result.add(d1); diff --git a/Remapped-Spigot-Server-Patches/0004-MC-Utils.patch b/Remapped-Spigot-Server-Patches/0004-MC-Utils.patch new file mode 100644 index 0000000000..cccd5824cd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0004-MC-Utils.patch @@ -0,0 +1,4859 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 20:55:47 -0400 +Subject: [PATCH] MC Utils + + +diff --git a/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4029dc68cf35d63aa70c4a76c35bf65a7fc6358f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java +@@ -0,0 +1,68 @@ ++package com.destroystokyo.paper.util.concurrent; ++ ++import java.util.concurrent.atomic.AtomicLong; ++ ++/** ++ * copied from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/lock/WeakSeqLock.java ++ * @author Spottedleaf ++ */ ++public final class WeakSeqLock { ++ // TODO when the switch to J11 is made, nuke this class from orbit ++ ++ protected final AtomicLong lock = new AtomicLong(); ++ ++ public WeakSeqLock() { ++ //VarHandle.storeStoreFence(); // warn: usages must be checked to ensure this behaviour isn't needed ++ } ++ ++ public void acquireWrite() { ++ // must be release-type write ++ this.lock.lazySet(this.lock.get() + 1); ++ } ++ ++ public boolean canRead(final long read) { ++ return (read & 1) == 0; ++ } ++ ++ public boolean tryAcquireWrite() { ++ this.acquireWrite(); ++ return true; ++ } ++ ++ public void releaseWrite() { ++ // must be acquire-type write ++ final long lock = this.lock.get(); // volatile here acts as store-store ++ this.lock.lazySet(lock + 1); ++ } ++ ++ public void abortWrite() { ++ // must be acquire-type write ++ final long lock = this.lock.get(); // volatile here acts as store-store ++ this.lock.lazySet(lock ^ 1); ++ } ++ ++ public long acquireRead() { ++ int failures = 0; ++ long curr; ++ ++ for (curr = this.lock.get(); !this.canRead(curr); curr = this.lock.get()) { ++ // without j11, our only backoff is the yield() call... ++ ++ if (++failures > 5_000) { /* TODO determine a threshold */ ++ Thread.yield(); ++ } ++ /* Better waiting is beyond the scope of this lock; if it is needed the lock is being misused */ ++ } ++ ++ //VarHandle.loadLoadFence(); // volatile acts as the load-load barrier ++ return curr; ++ } ++ ++ public boolean tryReleaseRead(final long read) { ++ return this.lock.get() == read; // volatile acts as the load-load barrier ++ } ++ ++ public long getSequentialCounter() { ++ return this.lock.get(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java +new file mode 100644 +index 0000000000000000000000000000000000000000..59868f37d14bbc0ece0836095cdad148778995e6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java +@@ -0,0 +1,162 @@ ++package com.destroystokyo.paper.util.map; ++ ++import com.destroystokyo.paper.util.concurrent.WeakSeqLock; ++import it.unimi.dsi.fastutil.longs.Long2IntMap; ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; ++import it.unimi.dsi.fastutil.longs.LongIterator; ++import it.unimi.dsi.fastutil.longs.LongOpenHashSet; ++import it.unimi.dsi.fastutil.objects.ObjectIterator; ++ ++/** ++ * @author Spottedleaf ++ */ ++public class QueuedChangesMapLong2Int { ++ ++ protected final Long2IntOpenHashMap updatingMap; ++ protected final Long2IntOpenHashMap visibleMap; ++ protected final Long2IntOpenHashMap queuedPuts; ++ protected final LongOpenHashSet queuedRemove; ++ ++ protected int queuedDefaultReturnValue; ++ ++ // we use a seqlock as writes are not common. ++ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); ++ ++ public QueuedChangesMapLong2Int() { ++ this(16, 0.75f); ++ } ++ ++ public QueuedChangesMapLong2Int(final int capacity, final float loadFactor) { ++ this.updatingMap = new Long2IntOpenHashMap(capacity, loadFactor); ++ this.visibleMap = new Long2IntOpenHashMap(capacity, loadFactor); ++ this.queuedPuts = new Long2IntOpenHashMap(); ++ this.queuedRemove = new LongOpenHashSet(); ++ } ++ ++ public void queueDefaultReturnValue(final int dfl) { ++ this.queuedDefaultReturnValue = dfl; ++ this.updatingMap.defaultReturnValue(dfl); ++ } ++ ++ public int queueUpdate(final long k, final int v) { ++ this.queuedRemove.remove(k); ++ this.queuedPuts.put(k, v); ++ ++ return this.updatingMap.put(k, v); ++ } ++ ++ public int queueRemove(final long k) { ++ this.queuedPuts.remove(k); ++ this.queuedRemove.add(k); ++ ++ return this.updatingMap.remove(k); ++ } ++ ++ public int getUpdating(final long k) { ++ return this.updatingMap.get(k); ++ } ++ ++ public int getVisible(final long k) { ++ return this.visibleMap.get(k); ++ } ++ ++ public int getVisibleAsync(final long k) { ++ long readlock; ++ int ret = 0; ++ ++ do { ++ readlock = this.updatingMapSeqLock.acquireRead(); ++ try { ++ ret = this.visibleMap.get(k); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ // ignore... ++ continue; ++ } ++ ++ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ ++ public boolean performUpdates() { ++ this.updatingMapSeqLock.acquireWrite(); ++ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); ++ this.updatingMapSeqLock.releaseWrite(); ++ ++ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { ++ return false; ++ } ++ ++ // update puts ++ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); ++ while (iterator0.hasNext()) { ++ final Long2IntMap.Entry entry = iterator0.next(); ++ final long key = entry.getLongKey(); ++ final int val = entry.getIntValue(); ++ ++ this.updatingMapSeqLock.acquireWrite(); ++ try { ++ this.visibleMap.put(key, val); ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ } ++ ++ this.queuedPuts.clear(); ++ ++ final LongIterator iterator1 = this.queuedRemove.iterator(); ++ while (iterator1.hasNext()) { ++ final long key = iterator1.nextLong(); ++ ++ this.updatingMapSeqLock.acquireWrite(); ++ try { ++ this.visibleMap.remove(key); ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ } ++ ++ this.queuedRemove.clear(); ++ ++ return true; ++ } ++ ++ public boolean performUpdatesLockMap() { ++ this.updatingMapSeqLock.acquireWrite(); ++ try { ++ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); ++ ++ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { ++ return false; ++ } ++ ++ // update puts ++ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); ++ while (iterator0.hasNext()) { ++ final Long2IntMap.Entry entry = iterator0.next(); ++ final long key = entry.getLongKey(); ++ final int val = entry.getIntValue(); ++ ++ this.visibleMap.put(key, val); ++ } ++ ++ this.queuedPuts.clear(); ++ ++ final LongIterator iterator1 = this.queuedRemove.iterator(); ++ while (iterator1.hasNext()) { ++ final long key = iterator1.nextLong(); ++ ++ this.visibleMap.remove(key); ++ } ++ ++ this.queuedRemove.clear(); ++ ++ return true; ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7bab31a312463cc963d9621cdc543a281459bd32 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java +@@ -0,0 +1,202 @@ ++package com.destroystokyo.paper.util.map; ++ ++import com.destroystokyo.paper.util.concurrent.WeakSeqLock; ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectMap; ++import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator; ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.List; ++ ++/** ++ * @author Spottedleaf ++ */ ++public class QueuedChangesMapLong2Object { ++ ++ protected static final Object REMOVED = new Object(); ++ ++ protected final Long2ObjectLinkedOpenHashMap updatingMap; ++ protected final Long2ObjectLinkedOpenHashMap visibleMap; ++ protected final Long2ObjectLinkedOpenHashMap queuedChanges; ++ ++ // we use a seqlock as writes are not common. ++ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); ++ ++ public QueuedChangesMapLong2Object() { ++ this(16, 0.75f); // dfl for fastutil ++ } ++ ++ public QueuedChangesMapLong2Object(final int capacity, final float loadFactor) { ++ this.updatingMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); ++ this.visibleMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); ++ this.queuedChanges = new Long2ObjectLinkedOpenHashMap<>(); ++ } ++ ++ public V queueUpdate(final long k, final V value) { ++ this.queuedChanges.put(k, value); ++ return this.updatingMap.put(k, value); ++ } ++ ++ public V queueRemove(final long k) { ++ this.queuedChanges.put(k, REMOVED); ++ return this.updatingMap.remove(k); ++ } ++ ++ public V getUpdating(final long k) { ++ return this.updatingMap.get(k); ++ } ++ ++ public boolean updatingContainsKey(final long k) { ++ return this.updatingMap.containsKey(k); ++ } ++ ++ public V getVisible(final long k) { ++ return this.visibleMap.get(k); ++ } ++ ++ public boolean visibleContainsKey(final long k) { ++ return this.visibleMap.containsKey(k); ++ } ++ ++ public V getVisibleAsync(final long k) { ++ long readlock; ++ V ret = null; ++ ++ do { ++ readlock = this.updatingMapSeqLock.acquireRead(); ++ ++ try { ++ ret = this.visibleMap.get(k); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ // ignore... ++ continue; ++ } ++ ++ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ ++ public boolean visibleContainsKeyAsync(final long k) { ++ long readlock; ++ boolean ret = false; ++ ++ do { ++ readlock = this.updatingMapSeqLock.acquireRead(); ++ ++ try { ++ ret = this.visibleMap.containsKey(k); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ // ignore... ++ continue; ++ } ++ ++ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ ++ public Long2ObjectLinkedOpenHashMap getVisibleMap() { ++ return this.visibleMap; ++ } ++ ++ public Long2ObjectLinkedOpenHashMap getUpdatingMap() { ++ return this.updatingMap; ++ } ++ ++ public int getVisibleSize() { ++ return this.visibleMap.size(); ++ } ++ ++ public int getVisibleSizeAsync() { ++ long readlock; ++ int ret; ++ ++ do { ++ readlock = this.updatingMapSeqLock.acquireRead(); ++ ret = this.visibleMap.size(); ++ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ ++ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map ++ public Collection getUpdatingValues() { ++ return this.updatingMap.values(); ++ } ++ ++ public List getUpdatingValuesCopy() { ++ return new ArrayList<>(this.updatingMap.values()); ++ } ++ ++ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map ++ public Collection getVisibleValues() { ++ return this.visibleMap.values(); ++ } ++ ++ public List getVisibleValuesCopy() { ++ return new ArrayList<>(this.visibleMap.values()); ++ } ++ ++ public boolean performUpdates() { ++ if (this.queuedChanges.isEmpty()) { ++ return false; ++ } ++ ++ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); ++ while (iterator.hasNext()) { ++ final Long2ObjectMap.Entry entry = iterator.next(); ++ final long key = entry.getLongKey(); ++ final Object val = entry.getValue(); ++ ++ this.updatingMapSeqLock.acquireWrite(); ++ try { ++ if (val == REMOVED) { ++ this.visibleMap.remove(key); ++ } else { ++ this.visibleMap.put(key, (V)val); ++ } ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ } ++ ++ this.queuedChanges.clear(); ++ return true; ++ } ++ ++ public boolean performUpdatesLockMap() { ++ if (this.queuedChanges.isEmpty()) { ++ return false; ++ } ++ ++ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); ++ ++ try { ++ this.updatingMapSeqLock.acquireWrite(); ++ ++ while (iterator.hasNext()) { ++ final Long2ObjectMap.Entry entry = iterator.next(); ++ final long key = entry.getLongKey(); ++ final Object val = entry.getValue(); ++ ++ if (val == REMOVED) { ++ this.visibleMap.remove(key); ++ } else { ++ this.visibleMap.put(key, (V)val); ++ } ++ } ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ ++ this.queuedChanges.clear(); ++ return true; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..554f4d4e63c1431721989e6f502a32ccc53a8807 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java +@@ -0,0 +1,128 @@ ++package com.destroystokyo.paper.util.maplist; ++ ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; ++import java.util.Arrays; ++import java.util.Iterator; ++import java.util.NoSuchElementException; ++import net.minecraft.world.level.chunk.LevelChunk; ++ ++// list with O(1) remove & contains ++/** ++ * @author Spottedleaf ++ */ ++public final class ChunkList implements Iterable { ++ ++ protected final Long2IntOpenHashMap chunkToIndex = new Long2IntOpenHashMap(2, 0.8f); ++ { ++ this.chunkToIndex.defaultReturnValue(Integer.MIN_VALUE); ++ } ++ ++ protected static final LevelChunk[] EMPTY_LIST = new LevelChunk[0]; ++ ++ protected LevelChunk[] chunks = EMPTY_LIST; ++ protected int count; ++ ++ public int size() { ++ return this.count; ++ } ++ ++ public boolean contains(final LevelChunk chunk) { ++ return this.chunkToIndex.containsKey(chunk.coordinateKey); ++ } ++ ++ public boolean remove(final LevelChunk chunk) { ++ final int index = this.chunkToIndex.remove(chunk.coordinateKey); ++ if (index == Integer.MIN_VALUE) { ++ return false; ++ } ++ ++ // move the entity at the end to this index ++ final int endIndex = --this.count; ++ final LevelChunk end = this.chunks[endIndex]; ++ if (index != endIndex) { ++ // not empty after this call ++ this.chunkToIndex.put(end.coordinateKey, index); // update index ++ } ++ this.chunks[index] = end; ++ this.chunks[endIndex] = null; ++ ++ return true; ++ } ++ ++ public boolean add(final LevelChunk chunk) { ++ final int count = this.count; ++ final int currIndex = this.chunkToIndex.putIfAbsent(chunk.coordinateKey, count); ++ ++ if (currIndex != Integer.MIN_VALUE) { ++ return false; // already in this list ++ } ++ ++ LevelChunk[] list = this.chunks; ++ ++ if (list.length == count) { ++ // resize required ++ list = this.chunks = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative ++ } ++ ++ list[count] = chunk; ++ this.count = count + 1; ++ ++ return true; ++ } ++ ++ public LevelChunk getChecked(final int index) { ++ if (index < 0 || index >= this.count) { ++ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); ++ } ++ return this.chunks[index]; ++ } ++ ++ public LevelChunk getUnchecked(final int index) { ++ return this.chunks[index]; ++ } ++ ++ public LevelChunk[] getRawData() { ++ return this.chunks; ++ } ++ ++ public void clear() { ++ this.chunkToIndex.clear(); ++ Arrays.fill(this.chunks, 0, this.count, null); ++ this.count = 0; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return new Iterator() { ++ ++ LevelChunk lastRet; ++ int current; ++ ++ @Override ++ public boolean hasNext() { ++ return this.current < ChunkList.this.count; ++ } ++ ++ @Override ++ public LevelChunk next() { ++ if (this.current >= ChunkList.this.count) { ++ throw new NoSuchElementException(); ++ } ++ return this.lastRet = ChunkList.this.chunks[this.current++]; ++ } ++ ++ @Override ++ public void remove() { ++ final LevelChunk lastRet = this.lastRet; ++ ++ if (lastRet == null) { ++ throw new IllegalStateException(); ++ } ++ this.lastRet = null; ++ ++ ChunkList.this.remove(lastRet); ++ --this.current; ++ } ++ }; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0133ea6feb1ab88f021f66855669f58367e7420b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java +@@ -0,0 +1,128 @@ ++package com.destroystokyo.paper.util.maplist; ++ ++import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; ++import net.minecraft.world.entity.Entity; ++import java.util.Arrays; ++import java.util.Iterator; ++import java.util.NoSuchElementException; ++ ++// list with O(1) remove & contains ++/** ++ * @author Spottedleaf ++ */ ++public final class EntityList implements Iterable { ++ ++ protected final Int2IntOpenHashMap entityToIndex = new Int2IntOpenHashMap(2, 0.8f); ++ { ++ this.entityToIndex.defaultReturnValue(Integer.MIN_VALUE); ++ } ++ ++ protected static final Entity[] EMPTY_LIST = new Entity[0]; ++ ++ protected Entity[] entities = EMPTY_LIST; ++ protected int count; ++ ++ public int size() { ++ return this.count; ++ } ++ ++ public boolean contains(final Entity entity) { ++ return this.entityToIndex.containsKey(entity.getId()); ++ } ++ ++ public boolean remove(final Entity entity) { ++ final int index = this.entityToIndex.remove(entity.getId()); ++ if (index == Integer.MIN_VALUE) { ++ return false; ++ } ++ ++ // move the entity at the end to this index ++ final int endIndex = --this.count; ++ final Entity end = this.entities[endIndex]; ++ if (index != endIndex) { ++ // not empty after this call ++ this.entityToIndex.put(end.getId(), index); // update index ++ } ++ this.entities[index] = end; ++ this.entities[endIndex] = null; ++ ++ return true; ++ } ++ ++ public boolean add(final Entity entity) { ++ final int count = this.count; ++ final int currIndex = this.entityToIndex.putIfAbsent(entity.getId(), count); ++ ++ if (currIndex != Integer.MIN_VALUE) { ++ return false; // already in this list ++ } ++ ++ Entity[] list = this.entities; ++ ++ if (list.length == count) { ++ // resize required ++ list = this.entities = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative ++ } ++ ++ list[count] = entity; ++ this.count = count + 1; ++ ++ return true; ++ } ++ ++ public Entity getChecked(final int index) { ++ if (index < 0 || index >= this.count) { ++ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); ++ } ++ return this.entities[index]; ++ } ++ ++ public Entity getUnchecked(final int index) { ++ return this.entities[index]; ++ } ++ ++ public Entity[] getRawData() { ++ return this.entities; ++ } ++ ++ public void clear() { ++ this.entityToIndex.clear(); ++ Arrays.fill(this.entities, 0, this.count, null); ++ this.count = 0; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return new Iterator() { ++ ++ Entity lastRet; ++ int current; ++ ++ @Override ++ public boolean hasNext() { ++ return this.current < EntityList.this.count; ++ } ++ ++ @Override ++ public Entity next() { ++ if (this.current >= EntityList.this.count) { ++ throw new NoSuchElementException(); ++ } ++ return this.lastRet = EntityList.this.entities[this.current++]; ++ } ++ ++ @Override ++ public void remove() { ++ final Entity lastRet = this.lastRet; ++ ++ if (lastRet == null) { ++ throw new IllegalStateException(); ++ } ++ this.lastRet = null; ++ ++ EntityList.this.remove(lastRet); ++ --this.current; ++ } ++ }; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..abe7f2f13ab713bf1cb0343059377ab7e1b48b6e +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java +@@ -0,0 +1,128 @@ ++package com.destroystokyo.paper.util.maplist; ++ ++import it.unimi.dsi.fastutil.longs.LongIterator; ++import it.unimi.dsi.fastutil.shorts.Short2LongOpenHashMap; ++import java.util.Arrays; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.GlobalPalette; ++import net.minecraft.world.level.chunk.LevelChunkSection; ++ ++/** ++ * @author Spottedleaf ++ */ ++public final class IBlockDataList { ++ ++ static final GlobalPalette GLOBAL_PALETTE = (GlobalPalette) LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE; ++ ++ // map of location -> (index | (location << 16) | (palette id << 32)) ++ private final Short2LongOpenHashMap map = new Short2LongOpenHashMap(2, 0.8f); ++ { ++ this.map.defaultReturnValue(Long.MAX_VALUE); ++ } ++ ++ private static final long[] EMPTY_LIST = new long[0]; ++ ++ private long[] byIndex = EMPTY_LIST; ++ private int size; ++ ++ public static int getLocationKey(final int x, final int y, final int z) { ++ return (x & 15) | (((z & 15) << 4)) | ((y & 255) << (4 + 4)); ++ } ++ ++ public static BlockState getBlockDataFromRaw(final long raw) { ++ return GLOBAL_PALETTE.getObject((int)(raw >>> 32)); ++ } ++ ++ public static int getIndexFromRaw(final long raw) { ++ return (int)(raw & 0xFFFF); ++ } ++ ++ public static int getLocationFromRaw(final long raw) { ++ return (int)((raw >>> 16) & 0xFFFF); ++ } ++ ++ public static long getRawFromValues(final int index, final int location, final BlockState data) { ++ return (long)index | ((long)location << 16) | (((long)GLOBAL_PALETTE.getOrCreateIdFor(data)) << 32); ++ } ++ ++ public static long setIndexRawValues(final long value, final int index) { ++ return value & ~(0xFFFF) | (index); ++ } ++ ++ public long add(final int x, final int y, final int z, final BlockState data) { ++ return this.add(getLocationKey(x, y, z), data); ++ } ++ ++ public long add(final int location, final BlockState data) { ++ final long curr = this.map.get((short)location); ++ ++ if (curr == Long.MAX_VALUE) { ++ final int index = this.size++; ++ final long raw = getRawFromValues(index, location, data); ++ this.map.put((short)location, raw); ++ ++ if (index >= this.byIndex.length) { ++ this.byIndex = Arrays.copyOf(this.byIndex, (int)Math.max(4L, this.byIndex.length * 2L)); ++ } ++ ++ this.byIndex[index] = raw; ++ return raw; ++ } else { ++ final int index = getIndexFromRaw(curr); ++ final long raw = this.byIndex[index] = getRawFromValues(index, location, data); ++ ++ this.map.put((short)location, raw); ++ ++ return raw; ++ } ++ } ++ ++ public long remove(final int x, final int y, final int z) { ++ return this.remove(getLocationKey(x, y, z)); ++ } ++ ++ public long remove(final int location) { ++ final long ret = this.map.remove((short)location); ++ final int index = getIndexFromRaw(ret); ++ if (ret == Long.MAX_VALUE) { ++ return ret; ++ } ++ ++ // move the entry at the end to this index ++ final int endIndex = --this.size; ++ final long end = this.byIndex[endIndex]; ++ if (index != endIndex) { ++ // not empty after this call ++ this.map.put((short)getLocationFromRaw(end), setIndexRawValues(end, index)); ++ } ++ this.byIndex[index] = end; ++ this.byIndex[endIndex] = 0L; ++ ++ return ret; ++ } ++ ++ public int size() { ++ return this.size; ++ } ++ ++ public long getRaw(final int index) { ++ return this.byIndex[index]; ++ } ++ ++ public int getLocation(final int index) { ++ return getLocationFromRaw(this.getRaw(index)); ++ } ++ ++ public BlockState getData(final int index) { ++ return getBlockDataFromRaw(this.getRaw(index)); ++ } ++ ++ public void clear() { ++ this.size = 0; ++ this.map.clear(); ++ } ++ ++ public LongIterator getRawIterator() { ++ return this.map.values().iterator(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c3b936f54b3fff418c265639ef223292ccc89356 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java +@@ -0,0 +1,230 @@ ++package com.destroystokyo.paper.util.math; ++ ++/** ++ * @author Spottedleaf ++ */ ++public final class IntegerUtil { ++ ++ public static final int HIGH_BIT_U32 = Integer.MIN_VALUE; ++ public static final long HIGH_BIT_U64 = Long.MIN_VALUE; ++ ++ public static int ceilLog2(final int value) { ++ return Integer.SIZE - Integer.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros ++ } ++ ++ public static long ceilLog2(final long value) { ++ return Long.SIZE - Long.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros ++ } ++ ++ public static int floorLog2(final int value) { ++ // xor is optimized subtract for 2^n -1 ++ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) ++ return (Integer.SIZE - 1) ^ Integer.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros ++ } ++ ++ public static int floorLog2(final long value) { ++ // xor is optimized subtract for 2^n -1 ++ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) ++ return (Long.SIZE - 1) ^ Long.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros ++ } ++ ++ public static int roundCeilLog2(final int value) { ++ // optimized variant of 1 << (32 - leading(val - 1)) ++ // given ++ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) ++ // 1 << (32 - leading(val - 1)) = HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) ++ // HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) ++ // HIGH_BIT_32 >>> (31 - 32 + leading(val - 1)) ++ // HIGH_BIT_32 >>> (-1 + leading(val - 1)) ++ return HIGH_BIT_U32 >>> (Integer.numberOfLeadingZeros(value - 1) - 1); ++ } ++ ++ public static long roundCeilLog2(final long value) { ++ // see logic documented above ++ return HIGH_BIT_U64 >>> (Long.numberOfLeadingZeros(value - 1) - 1); ++ } ++ ++ public static int roundFloorLog2(final int value) { ++ // optimized variant of 1 << (31 - leading(val)) ++ // given ++ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) ++ // 1 << (31 - leading(val)) = HIGH_BIT_32 >> (31 - (31 - leading(val))) ++ // HIGH_BIT_32 >> (31 - (31 - leading(val))) ++ // HIGH_BIT_32 >> (31 - 31 + leading(val)) ++ return HIGH_BIT_U32 >>> Integer.numberOfLeadingZeros(value); ++ } ++ ++ public static long roundFloorLog2(final long value) { ++ // see logic documented above ++ return HIGH_BIT_U64 >>> Long.numberOfLeadingZeros(value); ++ } ++ ++ public static boolean isPowerOfTwo(final int n) { ++ // 2^n has one bit ++ // note: this rets true for 0 still ++ return IntegerUtil.getTrailingBit(n) == n; ++ } ++ ++ public static boolean isPowerOfTwo(final long n) { ++ // 2^n has one bit ++ // note: this rets true for 0 still ++ return IntegerUtil.getTrailingBit(n) == n; ++ } ++ ++ ++ public static int getTrailingBit(final int n) { ++ return -n & n; ++ } ++ ++ public static long getTrailingBit(final long n) { ++ return -n & n; ++ } ++ ++ public static int trailingZeros(final int n) { ++ return Integer.numberOfTrailingZeros(n); ++ } ++ ++ public static long trailingZeros(final long n) { ++ return Long.numberOfTrailingZeros(n); ++ } ++ ++ // from hacker's delight (signed division magic value) ++ public static int getDivisorMultiple(final long numbers) { ++ return (int)(numbers >>> 32); ++ } ++ ++ // from hacker's delight (signed division magic value) ++ public static int getDivisorShift(final long numbers) { ++ return (int)numbers; ++ } ++ ++ // copied from hacker's delight (signed division magic value) ++ // http://www.hackersdelight.org/hdcodetxt/magic.c.txt ++ public static long getDivisorNumbers(final int d) { ++ final int ad = IntegerUtil.branchlessAbs(d); ++ ++ if (ad < 2) { ++ throw new IllegalArgumentException("|number| must be in [2, 2^31 -1], not: " + d); ++ } ++ ++ final int two31 = 0x80000000; ++ final long mask = 0xFFFFFFFFL; // mask for enforcing unsigned behaviour ++ ++ int p = 31; ++ ++ // all these variables are UNSIGNED! ++ int t = two31 + (d >>> 31); ++ int anc = t - 1 - t%ad; ++ int q1 = (int)((two31 & mask)/(anc & mask)); ++ int r1 = two31 - q1*anc; ++ int q2 = (int)((two31 & mask)/(ad & mask)); ++ int r2 = two31 - q2*ad; ++ int delta; ++ ++ do { ++ p = p + 1; ++ q1 = 2*q1; // Update q1 = 2**p/|nc|. ++ r1 = 2*r1; // Update r1 = rem(2**p, |nc|). ++ if ((r1 & mask) >= (anc & mask)) {// (Must be an unsigned comparison here) ++ q1 = q1 + 1; ++ r1 = r1 - anc; ++ } ++ q2 = 2*q2; // Update q2 = 2**p/|d|. ++ r2 = 2*r2; // Update r2 = rem(2**p, |d|). ++ if ((r2 & mask) >= (ad & mask)) {// (Must be an unsigned comparison here) ++ q2 = q2 + 1; ++ r2 = r2 - ad; ++ } ++ delta = ad - r2; ++ } while ((q1 & mask) < (delta & mask) || (q1 == delta && r1 == 0)); ++ ++ int magicNum = q2 + 1; ++ if (d < 0) { ++ magicNum = -magicNum; ++ } ++ int shift = p - 32; ++ return ((long)magicNum << 32) | shift; ++ } ++ ++ public static int branchlessAbs(final int val) { ++ // -n = -1 ^ n + 1 ++ final int mask = val >> (Integer.SIZE - 1); // -1 if < 0, 0 if >= 0 ++ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 ++ } ++ ++ public static long branchlessAbs(final long val) { ++ // -n = -1 ^ n + 1 ++ final long mask = val >> (Long.SIZE - 1); // -1 if < 0, 0 if >= 0 ++ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 ++ } ++ ++ //https://github.com/skeeto/hash-prospector for hash functions ++ ++ //score = ~590.47984224483832 ++ public static int hash0(int x) { ++ x *= 0x36935555; ++ x ^= x >>> 16; ++ return x; ++ } ++ ++ //score = ~310.01596637036749 ++ public static int hash1(int x) { ++ x ^= x >>> 15; ++ x *= 0x356aaaad; ++ x ^= x >>> 17; ++ return x; ++ } ++ ++ public static int hash2(int x) { ++ x ^= x >>> 16; ++ x *= 0x7feb352d; ++ x ^= x >>> 15; ++ x *= 0x846ca68b; ++ x ^= x >>> 16; ++ return x; ++ } ++ ++ public static int hash3(int x) { ++ x ^= x >>> 17; ++ x *= 0xed5ad4bb; ++ x ^= x >>> 11; ++ x *= 0xac4c1b51; ++ x ^= x >>> 15; ++ x *= 0x31848bab; ++ x ^= x >>> 14; ++ return x; ++ } ++ ++ //score = ~365.79959673201887 ++ public static long hash1(long x) { ++ x ^= x >>> 27; ++ x *= 0xb24924b71d2d354bL; ++ x ^= x >>> 28; ++ return x; ++ } ++ ++ //h2 hash ++ public static long hash2(long x) { ++ x ^= x >>> 32; ++ x *= 0xd6e8feb86659fd93L; ++ x ^= x >>> 32; ++ x *= 0xd6e8feb86659fd93L; ++ x ^= x >>> 32; ++ return x; ++ } ++ ++ public static long hash3(long x) { ++ x ^= x >>> 45; ++ x *= 0xc161abe5704b6c79L; ++ x ^= x >>> 41; ++ x *= 0xe3e5389aedbc90f7L; ++ x ^= x >>> 56; ++ x *= 0x1f9aba75a52db073L; ++ x ^= x >>> 53; ++ return x; ++ } ++ ++ private IntegerUtil() { ++ throw new RuntimeException(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c601f04b9c6dff76606763ea6f4a9a89b7e83203 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java +@@ -0,0 +1,453 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import com.destroystokyo.paper.util.math.IntegerUtil; ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.world.level.ChunkPos; ++import javax.annotation.Nullable; ++import java.util.Iterator; ++ ++/** @author Spottedleaf */ ++public abstract class AreaMap { ++ ++ /* Tested via https://gist.github.com/Spottedleaf/520419c6f41ef348fe9926ce674b7217 */ ++ ++ protected final Object2LongOpenHashMap objectToLastCoordinate = new Object2LongOpenHashMap<>(); ++ protected final Object2IntOpenHashMap objectToViewDistance = new Object2IntOpenHashMap<>(); ++ ++ { ++ this.objectToViewDistance.defaultReturnValue(-1); ++ this.objectToLastCoordinate.defaultReturnValue(Long.MIN_VALUE); ++ } ++ ++ // we use linked for better iteration. ++ // map of: coordinate to set of objects in coordinate ++ protected final Long2ObjectOpenHashMap> areaMap = new Long2ObjectOpenHashMap<>(1024, 0.7f); ++ protected final PooledLinkedHashSets pooledHashSets; ++ ++ protected final ChangeCallback addCallback; ++ protected final ChangeCallback removeCallback; ++ protected final ChangeSourceCallback changeSourceCallback; ++ ++ public AreaMap() { ++ this(new PooledLinkedHashSets<>()); ++ } ++ ++ // let users define a "global" or "shared" pooled sets if they wish ++ public AreaMap(final PooledLinkedHashSets pooledHashSets) { ++ this(pooledHashSets, null, null); ++ } ++ ++ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback) { ++ this(pooledHashSets, addCallback, removeCallback, null); ++ } ++ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { ++ this.pooledHashSets = pooledHashSets; ++ this.addCallback = addCallback; ++ this.removeCallback = removeCallback; ++ this.changeSourceCallback = changeSourceCallback; ++ } ++ ++ @Nullable ++ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final long key) { ++ return this.areaMap.get(key); ++ } ++ ++ @Nullable ++ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final ChunkPos chunkPos) { ++ return this.areaMap.get(MCUtil.getCoordinateKey(chunkPos)); ++ } ++ ++ @Nullable ++ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final int chunkX, final int chunkZ) { ++ return this.areaMap.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); ++ } ++ ++ // Long.MIN_VALUE indicates the object is not mapped ++ public final long getLastCoordinate(final E object) { ++ return this.objectToLastCoordinate.getOrDefault(object, Long.MIN_VALUE); ++ } ++ ++ // -1 indicates the object is not mapped ++ public final int getLastViewDistance(final E object) { ++ return this.objectToViewDistance.getOrDefault(object, -1); ++ } ++ ++ // returns the total number of mapped chunks ++ public final int size() { ++ return this.areaMap.size(); ++ } ++ ++ public final void addOrUpdate(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int oldViewDistance = this.objectToViewDistance.put(object, viewDistance); ++ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final long oldPos = this.objectToLastCoordinate.put(object, newPos); ++ ++ if (oldViewDistance == -1) { ++ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); ++ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); ++ } else { ++ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); ++ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); ++ } ++ //this.validate(object, viewDistance); ++ } ++ ++ public final boolean update(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int oldViewDistance = this.objectToViewDistance.replace(object, viewDistance); ++ if (oldViewDistance == -1) { ++ return false; ++ } else { ++ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final long oldPos = this.objectToLastCoordinate.put(object, newPos); ++ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); ++ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); ++ } ++ //this.validate(object, viewDistance); ++ return true; ++ } ++ ++ // called after the distance map updates ++ protected void updateObjectCallback(final E Object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { ++ if (newPosition != oldPosition && this.changeSourceCallback != null) { ++ this.changeSourceCallback.accept(Object, oldPosition, newPosition); ++ } ++ } ++ ++ public final boolean add(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int oldViewDistance = this.objectToViewDistance.putIfAbsent(object, viewDistance); ++ if (oldViewDistance != -1) { ++ return false; ++ } ++ ++ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ this.objectToLastCoordinate.put(object, newPos); ++ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); ++ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); ++ ++ //this.validate(object, viewDistance); ++ ++ return true; ++ } ++ ++ // called after the distance map updates ++ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} ++ ++ public final boolean remove(final E object) { ++ final long position = this.objectToLastCoordinate.removeLong(object); ++ final int viewDistance = this.objectToViewDistance.removeInt(object); ++ ++ if (viewDistance == -1) { ++ return false; ++ } ++ ++ final int currentX = MCUtil.getCoordinateX(position); ++ final int currentZ = MCUtil.getCoordinateZ(position); ++ ++ this.removeObject(object, currentX, currentZ, currentX, currentZ, viewDistance); ++ this.removeObjectCallback(object, currentX, currentZ, viewDistance); ++ //this.validate(object, -1); ++ return true; ++ } ++ ++ // called after the distance map updates ++ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} ++ ++ protected abstract PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final E object); ++ ++ // expensive op, only for debug ++ protected void validate(final E object, final int viewDistance) { ++ int entiesGot = 0; ++ int expectedEntries = (2 * viewDistance + 1); ++ expectedEntries *= expectedEntries; ++ if (viewDistance < 0) { ++ expectedEntries = 0; ++ } ++ ++ final long currPosition = this.objectToLastCoordinate.getLong(object); ++ ++ final int centerX = MCUtil.getCoordinateX(currPosition); ++ final int centerZ = MCUtil.getCoordinateZ(currPosition); ++ ++ for (Iterator>> iterator = this.areaMap.long2ObjectEntrySet().fastIterator(); ++ iterator.hasNext();) { ++ ++ final Long2ObjectLinkedOpenHashMap.Entry> entry = iterator.next(); ++ final long key = entry.getLongKey(); ++ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); ++ ++ if (map.referenceCount == 0) { ++ throw new IllegalStateException("Invalid map"); ++ } ++ ++ if (map.contains(object)) { ++ ++entiesGot; ++ ++ final int chunkX = MCUtil.getCoordinateX(key); ++ final int chunkZ = MCUtil.getCoordinateZ(key); ++ ++ final int dist = Math.max(IntegerUtil.branchlessAbs(chunkX - centerX), IntegerUtil.branchlessAbs(chunkZ - centerZ)); ++ ++ if (dist > viewDistance) { ++ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); ++ } ++ } ++ } ++ ++ if (entiesGot != expectedEntries) { ++ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); ++ } ++ } ++ ++ private void addObjectTo(final E object, final int chunkX, final int chunkZ, final int currChunkX, ++ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { ++ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet empty = this.getEmptySetFor(object); ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.putIfAbsent(key, empty); ++ ++ if (current != null) { ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWith(current, object); ++ if (next == current) { ++ throw new IllegalStateException("Expected different map: got " + next.toString()); ++ } ++ this.areaMap.put(key, next); ++ ++ current = next; ++ // fall through to callback ++ } else { ++ current = empty; ++ } ++ ++ if (this.addCallback != null) { ++ try { ++ this.addCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, current); ++ } catch (final Throwable ex) { ++ if (ex instanceof ThreadDeath) { ++ throw (ThreadDeath)ex; ++ } ++ MinecraftServer.LOGGER.error("Add callback for map threw exception ", ex); ++ } ++ } ++ } ++ ++ private void removeObjectFrom(final E object, final int chunkX, final int chunkZ, final int currChunkX, ++ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { ++ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.get(key); ++ ++ if (current == null) { ++ throw new IllegalStateException("Current map may not be null for " + object + ", (" + chunkX + "," + chunkZ + ")"); ++ } ++ ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWithout(current, object); ++ ++ if (next == current) { ++ throw new IllegalStateException("Current map [" + next.toString() + "] should have contained " + object + ", (" + chunkX + "," + chunkZ + ")"); ++ } ++ ++ if (next != null) { ++ this.areaMap.put(key, next); ++ } else { ++ this.areaMap.remove(key); ++ } ++ ++ if (this.removeCallback != null) { ++ try { ++ this.removeCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, next); ++ } catch (final Throwable ex) { ++ if (ex instanceof ThreadDeath) { ++ throw (ThreadDeath)ex; ++ } ++ MinecraftServer.LOGGER.error("Remove callback for map threw exception ", ex); ++ } ++ } ++ } ++ ++ private void addObject(final E object, final int chunkX, final int chunkZ, final int prevChunkX, final int prevChunkZ, final int viewDistance) { ++ final int maxX = chunkX + viewDistance; ++ final int maxZ = chunkZ + viewDistance; ++ final int minX = chunkX - viewDistance; ++ final int minZ = chunkZ - viewDistance; ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ this.addObjectTo(object, x, z, chunkX, chunkZ, prevChunkX, prevChunkZ); ++ } ++ } ++ } ++ ++ private void removeObject(final E object, final int chunkX, final int chunkZ, final int currentChunkX, final int currentChunkZ, final int viewDistance) { ++ final int maxX = chunkX + viewDistance; ++ final int maxZ = chunkZ + viewDistance; ++ final int minX = chunkX - viewDistance; ++ final int minZ = chunkZ - viewDistance; ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ this.removeObjectFrom(object, x, z, currentChunkX, currentChunkZ, chunkX, chunkZ); ++ } ++ } ++ } ++ ++ /* math sign function except 0 returns 1 */ ++ protected static int sign(int val) { ++ return 1 | (val >> (Integer.SIZE - 1)); ++ } ++ ++ private void updateObject(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { ++ final int toX = MCUtil.getCoordinateX(newPosition); ++ final int toZ = MCUtil.getCoordinateZ(newPosition); ++ final int fromX = MCUtil.getCoordinateX(oldPosition); ++ final int fromZ = MCUtil.getCoordinateZ(oldPosition); ++ ++ final int dx = toX - fromX; ++ final int dz = toZ - fromZ; ++ ++ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); ++ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); ++ ++ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { ++ // teleported? ++ this.removeObject(object, fromX, fromZ, fromX, fromZ, oldViewDistance); ++ this.addObject(object, toX, toZ, fromX, fromZ, newViewDistance); ++ return; ++ } ++ ++ if (oldViewDistance != newViewDistance) { ++ // remove loop ++ ++ final int oldMinX = fromX - oldViewDistance; ++ final int oldMinZ = fromZ - oldViewDistance; ++ final int oldMaxX = fromX + oldViewDistance; ++ final int oldMaxZ = fromZ + oldViewDistance; ++ for (int currX = oldMinX; currX <= oldMaxX; ++currX) { ++ for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) { ++ ++ // only remove if we're outside the new view distance... ++ if (Math.max(IntegerUtil.branchlessAbs(currX - toX), IntegerUtil.branchlessAbs(currZ - toZ)) > newViewDistance) { ++ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ // add loop ++ ++ final int newMinX = toX - newViewDistance; ++ final int newMinZ = toZ - newViewDistance; ++ final int newMaxX = toX + newViewDistance; ++ final int newMaxZ = toZ + newViewDistance; ++ for (int currX = newMinX; currX <= newMaxX; ++currX) { ++ for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) { ++ ++ // only add if we're outside the old view distance... ++ if (Math.max(IntegerUtil.branchlessAbs(currX - fromX), IntegerUtil.branchlessAbs(currZ - fromZ)) > oldViewDistance) { ++ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ return; ++ } ++ ++ // x axis is width ++ // z axis is height ++ // right refers to the x axis of where we moved ++ // top refers to the z axis of where we moved ++ ++ // same view distance ++ ++ // used for relative positioning ++ final int up = sign(dz); // 1 if dz >= 0, -1 otherwise ++ final int right = sign(dx); // 1 if dx >= 0, -1 otherwise ++ ++ // The area excluded by overlapping the two view distance squares creates four rectangles: ++ // Two on the left, and two on the right. The ones on the left we consider the "removed" section ++ // and on the right the "added" section. ++ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually ++ // exclusive to the regions they surround. ++ ++ // 4 points of the rectangle ++ int maxX; // exclusive ++ int minX; // inclusive ++ int maxZ; // exclusive ++ int minZ; // inclusive ++ ++ if (dx != 0) { ++ // handle right addition ++ ++ maxX = toX + (oldViewDistance * right) + right; // exclusive ++ minX = fromX + (oldViewDistance * right) + right; // inclusive ++ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive ++ minZ = toZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ if (dz != 0) { ++ // handle up addition ++ ++ maxX = toX + (oldViewDistance * right) + right; // exclusive ++ minX = toX - (oldViewDistance * right); // inclusive ++ maxZ = toZ + (oldViewDistance * up) + up; // exclusive ++ minZ = fromZ + (oldViewDistance * up) + up; // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ if (dx != 0) { ++ // handle left removal ++ ++ maxX = toX - (oldViewDistance * right); // exclusive ++ minX = fromX - (oldViewDistance * right); // inclusive ++ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive ++ minZ = toZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ if (dz != 0) { ++ // handle down removal ++ ++ maxX = fromX + (oldViewDistance * right) + right; // exclusive ++ minX = fromX - (oldViewDistance * right); // inclusive ++ maxZ = toZ - (oldViewDistance * up); // exclusive ++ minZ = fromZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ } ++ ++ @FunctionalInterface ++ public static interface ChangeCallback { ++ ++ // if there is no previous position, then prevPos = Integer.MIN_VALUE ++ void accept(final E object, final int rangeX, final int rangeZ, final int currPosX, final int currPosZ, final int prevPosX, final int prevPosZ, ++ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState); ++ ++ } ++ ++ @FunctionalInterface ++ public static interface ChangeSourceCallback { ++ void accept(final E object, final long prevPos, final long newPos); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9b8cb361767fbcf5f592db32a12186f0bd6373bd +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java +@@ -0,0 +1,175 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import com.destroystokyo.paper.util.math.IntegerUtil; ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; ++import net.minecraft.server.MCUtil; ++import net.minecraft.world.level.ChunkPos; ++ ++/** @author Spottedleaf */ ++public abstract class DistanceTrackingAreaMap extends AreaMap { ++ ++ // use this map only if you need distance tracking, the tracking here is obviously going to hit harder. ++ ++ protected final Long2IntOpenHashMap chunkToNearestDistance = new Long2IntOpenHashMap(1024, 0.7f); ++ { ++ this.chunkToNearestDistance.defaultReturnValue(-1); ++ } ++ ++ protected final DistanceChangeCallback distanceChangeCallback; ++ ++ public DistanceTrackingAreaMap() { ++ this(new PooledLinkedHashSets<>()); ++ } ++ ++ // let users define a "global" or "shared" pooled sets if they wish ++ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { ++ this(pooledHashSets, null, null, null); ++ } ++ ++ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, ++ final DistanceChangeCallback distanceChangeCallback) { ++ super(pooledHashSets, addCallback, removeCallback); ++ this.distanceChangeCallback = distanceChangeCallback; ++ } ++ ++ // ret -1 if there is nothing mapped ++ public final int getNearestObjectDistance(final long key) { ++ return this.chunkToNearestDistance.get(key); ++ } ++ ++ // ret -1 if there is nothing mapped ++ public final int getNearestObjectDistance(final ChunkPos chunkPos) { ++ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkPos)); ++ } ++ ++ // ret -1 if there is nothing mapped ++ public final int getNearestObjectDistance(final int chunkX, final int chunkZ) { ++ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); ++ } ++ ++ protected final void recalculateDistance(final int chunkX, final int chunkZ) { ++ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state = this.areaMap.get(key); ++ if (state == null) { ++ final int oldDistance = this.chunkToNearestDistance.remove(key); ++ // nothing here. ++ if (oldDistance == -1) { ++ // nothing was here previously ++ return; ++ } ++ if (this.distanceChangeCallback != null) { ++ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, -1, null); ++ } ++ return; ++ } ++ ++ int newDistance = Integer.MAX_VALUE; ++ ++ final Object[] rawData = state.getBackingSet(); ++ for (int i = 0, len = rawData.length; i < len; ++i) { ++ final Object raw = rawData[i]; ++ ++ if (raw == null) { ++ continue; ++ } ++ ++ final E object = (E)raw; ++ final long location = this.objectToLastCoordinate.getLong(object); ++ ++ final int distance = Math.max(IntegerUtil.branchlessAbs(chunkX - MCUtil.getCoordinateX(location)), IntegerUtil.branchlessAbs(chunkZ - MCUtil.getCoordinateZ(location))); ++ ++ if (distance < newDistance) { ++ newDistance = distance; ++ } ++ } ++ ++ final int oldDistance = this.chunkToNearestDistance.put(key, newDistance); ++ ++ if (oldDistance != newDistance) { ++ if (this.distanceChangeCallback != null) { ++ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, newDistance, state); ++ } ++ } ++ } ++ ++ @Override ++ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int maxX = chunkX + viewDistance; ++ final int maxZ = chunkZ + viewDistance; ++ final int minX = chunkX - viewDistance; ++ final int minZ = chunkZ - viewDistance; ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ this.recalculateDistance(x, z); ++ } ++ } ++ } ++ ++ @Override ++ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int maxX = chunkX + viewDistance; ++ final int maxZ = chunkZ + viewDistance; ++ final int minX = chunkX - viewDistance; ++ final int minZ = chunkZ - viewDistance; ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ this.recalculateDistance(x, z); ++ } ++ } ++ } ++ ++ @Override ++ protected void updateObjectCallback(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { ++ if (oldPosition == newPosition && newViewDistance == oldViewDistance) { ++ return; ++ } ++ ++ final int toX = MCUtil.getCoordinateX(newPosition); ++ final int toZ = MCUtil.getCoordinateZ(newPosition); ++ final int fromX = MCUtil.getCoordinateX(oldPosition); ++ final int fromZ = MCUtil.getCoordinateZ(oldPosition); ++ ++ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); ++ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); ++ ++ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { ++ // teleported? ++ this.removeObjectCallback(object, fromX, fromZ, oldViewDistance); ++ this.addObjectCallback(object, toX, toZ, newViewDistance); ++ return; ++ } ++ ++ final int minX = Math.min(fromX - oldViewDistance, toX - newViewDistance); ++ final int maxX = Math.max(fromX + oldViewDistance, toX + newViewDistance); ++ final int minZ = Math.min(fromZ - oldViewDistance, toZ - newViewDistance); ++ final int maxZ = Math.max(fromZ + oldViewDistance, toZ + newViewDistance); ++ ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ final int distXOld = IntegerUtil.branchlessAbs(x - fromX); ++ final int distZOld = IntegerUtil.branchlessAbs(z - fromZ); ++ ++ if (Math.max(distXOld, distZOld) <= oldViewDistance) { ++ this.recalculateDistance(x, z); ++ continue; ++ } ++ ++ final int distXNew = IntegerUtil.branchlessAbs(x - toX); ++ final int distZNew = IntegerUtil.branchlessAbs(z - toZ); ++ ++ if (Math.max(distXNew, distZNew) <= newViewDistance) { ++ this.recalculateDistance(x, z); ++ continue; ++ } ++ } ++ } ++ } ++ ++ @FunctionalInterface ++ public static interface DistanceChangeCallback { ++ ++ void accept(final int posX, final int posZ, final int oldNearestDistance, final int newNearestDistance, ++ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state); ++ ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..46954db7ecd35ac4018fdf476df7c8020d7ce6c8 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java +@@ -0,0 +1,32 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import net.minecraft.server.level.ServerPlayer; ++ ++/** ++ * @author Spottedleaf ++ */ ++public final class PlayerAreaMap extends AreaMap { ++ ++ public PlayerAreaMap() { ++ super(); ++ } ++ ++ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets) { ++ super(pooledHashSets); ++ } ++ ++ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, ++ final ChangeCallback removeCallback) { ++ this(pooledHashSets, addCallback, removeCallback, null); ++ } ++ ++ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, ++ final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { ++ super(pooledHashSets, addCallback, removeCallback, changeSourceCallback); ++ } ++ ++ @Override ++ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final ServerPlayer player) { ++ return player.cachedSingleHashSet; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d05dcea15f7047b58736c7c0e07920a04d6c5abe +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java +@@ -0,0 +1,24 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import net.minecraft.server.level.ServerPlayer; ++ ++public class PlayerDistanceTrackingAreaMap extends DistanceTrackingAreaMap { ++ ++ public PlayerDistanceTrackingAreaMap() { ++ super(); ++ } ++ ++ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { ++ super(pooledHashSets); ++ } ++ ++ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, ++ final ChangeCallback removeCallback, final DistanceChangeCallback distanceChangeCallback) { ++ super(pooledHashSets, addCallback, removeCallback, distanceChangeCallback); ++ } ++ ++ @Override ++ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final ServerPlayer player) { ++ return player.cachedSingleHashSet; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e51104e65a07b6ea7bbbcbb6afb066ef6401cc5b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java +@@ -0,0 +1,287 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; ++import java.lang.ref.WeakReference; ++ ++/** @author Spottedleaf */ ++public class PooledLinkedHashSets { ++ ++ /* Tested via https://gist.github.com/Spottedleaf/a93bb7a8993d6ce142d3efc5932bf573 */ ++ ++ // we really want to avoid that equals() check as much as possible... ++ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(128, 0.25f); ++ ++ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { ++ if (current.referenceCount == 0) { ++ throw new IllegalStateException("Cannot decrement reference count for " + current); ++ } ++ if (current.referenceCount == -1 || --current.referenceCount > 0) { ++ return; ++ } ++ ++ this.mapPool.remove(current); ++ return; ++ } ++ ++ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { ++ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); ++ ++ if (cached != null) { ++ decrementReferenceCount(current); ++ ++ if (cached.referenceCount == 0) { ++ // bring the map back from the dead ++ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); ++ if (contending != null) { ++ // a map already exists with the elements we want ++ if (contending.referenceCount != -1) { ++ ++contending.referenceCount; ++ } ++ current.updateAddCache(object, contending); ++ return contending; ++ } ++ ++ cached.referenceCount = 1; ++ } else if (cached.referenceCount != -1) { ++ ++cached.referenceCount; ++ } ++ ++ return cached; ++ } ++ ++ if (!current.add(object)) { ++ return current; ++ } ++ ++ // we use get/put since we use a different key on put ++ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); ++ ++ if (ret == null) { ++ ret = new PooledObjectLinkedOpenHashSet<>(current); ++ current.remove(object); ++ this.mapPool.put(ret, ret); ++ ret.referenceCount = 1; ++ } else { ++ if (ret.referenceCount != -1) { ++ ++ret.referenceCount; ++ } ++ current.remove(object); ++ } ++ ++ current.updateAddCache(object, ret); ++ ++ decrementReferenceCount(current); ++ return ret; ++ } ++ ++ // rets null if current.size() == 1 ++ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { ++ if (current.set.size() == 1) { ++ decrementReferenceCount(current); ++ return null; ++ } ++ ++ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); ++ ++ if (cached != null) { ++ decrementReferenceCount(current); ++ ++ if (cached.referenceCount == 0) { ++ // bring the map back from the dead ++ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); ++ if (contending != null) { ++ // a map already exists with the elements we want ++ if (contending.referenceCount != -1) { ++ ++contending.referenceCount; ++ } ++ current.updateRemoveCache(object, contending); ++ return contending; ++ } ++ ++ cached.referenceCount = 1; ++ } else if (cached.referenceCount != -1) { ++ ++cached.referenceCount; ++ } ++ ++ return cached; ++ } ++ ++ if (!current.remove(object)) { ++ return current; ++ } ++ ++ // we use get/put since we use a different key on put ++ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); ++ ++ if (ret == null) { ++ ret = new PooledObjectLinkedOpenHashSet<>(current); ++ current.add(object); ++ this.mapPool.put(ret, ret); ++ ret.referenceCount = 1; ++ } else { ++ if (ret.referenceCount != -1) { ++ ++ret.referenceCount; ++ } ++ current.add(object); ++ } ++ ++ current.updateRemoveCache(object, ret); ++ ++ decrementReferenceCount(current); ++ return ret; ++ } ++ ++ static final class RawSetObjectLinkedOpenHashSet extends ObjectOpenHashSet { ++ ++ public RawSetObjectLinkedOpenHashSet() { ++ super(); ++ } ++ ++ public RawSetObjectLinkedOpenHashSet(final int capacity) { ++ super(capacity); ++ } ++ ++ public RawSetObjectLinkedOpenHashSet(final int capacity, final float loadFactor) { ++ super(capacity, loadFactor); ++ } ++ ++ @Override ++ public RawSetObjectLinkedOpenHashSet clone() { ++ return (RawSetObjectLinkedOpenHashSet)super.clone(); ++ } ++ ++ public E[] getRawSet() { ++ return this.key; ++ } ++ } ++ ++ public static final class PooledObjectLinkedOpenHashSet { ++ ++ private static final WeakReference NULL_REFERENCE = new WeakReference<>(null); ++ ++ final RawSetObjectLinkedOpenHashSet set; ++ int referenceCount; // -1 if special ++ int hash; // optimize hashcode ++ ++ // add cache ++ WeakReference lastAddObject = NULL_REFERENCE; ++ WeakReference> lastAddMap = NULL_REFERENCE; ++ ++ // remove cache ++ WeakReference lastRemoveObject = NULL_REFERENCE; ++ WeakReference> lastRemoveMap = NULL_REFERENCE; ++ ++ public PooledObjectLinkedOpenHashSet(final PooledLinkedHashSets pooledSets) { ++ this.set = new RawSetObjectLinkedOpenHashSet<>(2, 0.8f); ++ } ++ ++ public PooledObjectLinkedOpenHashSet(final E single) { ++ this((PooledLinkedHashSets)null); ++ this.referenceCount = -1; ++ this.add(single); ++ } ++ ++ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { ++ this.set = other.set.clone(); ++ this.hash = other.hash; ++ } ++ ++ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java ++ // generated by https://github.com/skeeto/hash-prospector ++ private static int hash0(int x) { ++ x *= 0x36935555; ++ x ^= x >>> 16; ++ return x; ++ } ++ ++ PooledObjectLinkedOpenHashSet getAddCache(final E element) { ++ final E currentAdd = this.lastAddObject.get(); ++ ++ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { ++ return null; ++ } ++ ++ return this.lastAddMap.get(); ++ } ++ ++ PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { ++ final E currentRemove = this.lastRemoveObject.get(); ++ ++ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { ++ return null; ++ } ++ ++ return this.lastRemoveMap.get(); ++ } ++ ++ void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { ++ this.lastAddObject = new WeakReference<>(element); ++ this.lastAddMap = new WeakReference<>(map); ++ } ++ ++ void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { ++ this.lastRemoveObject = new WeakReference<>(element); ++ this.lastRemoveMap = new WeakReference<>(map); ++ } ++ ++ boolean add(final E element) { ++ boolean added = this.set.add(element); ++ ++ if (added) { ++ this.hash += hash0(element.hashCode()); ++ } ++ ++ return added; ++ } ++ ++ boolean remove(Object element) { ++ boolean removed = this.set.remove(element); ++ ++ if (removed) { ++ this.hash -= hash0(element.hashCode()); ++ } ++ ++ return removed; ++ } ++ ++ public boolean contains(final Object element) { ++ return this.set.contains(element); ++ } ++ ++ public E[] getBackingSet() { ++ return this.set.getRawSet(); ++ } ++ ++ public int size() { ++ return this.set.size(); ++ } ++ ++ @Override ++ public int hashCode() { ++ return this.hash; ++ } ++ ++ @Override ++ public boolean equals(final Object other) { ++ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { ++ return false; ++ } ++ if (this.referenceCount == 0) { ++ return other == this; ++ } else { ++ if (other == this) { ++ // Unfortunately we are never equal to our own instance while in use! ++ return false; ++ } ++ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); ++ } ++ } ++ ++ @Override ++ public String toString() { ++ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + ++ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d0c77068e9a53d1b8bbad0f3f6b420d6bc85f8c8 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java +@@ -0,0 +1,85 @@ ++package com.destroystokyo.paper.util.pooled; ++ ++import net.minecraft.server.MCUtil; ++import org.apache.commons.lang3.mutable.MutableInt; ++ ++import java.util.ArrayDeque; ++import java.util.function.Consumer; ++import java.util.function.Supplier; ++ ++public final class PooledObjects { ++ ++ /** ++ * Wrapper for an object that will be have a cleaner registered for it, and may be automatically returned to pool. ++ */ ++ public class AutoReleased { ++ private final E object; ++ private final Runnable cleaner; ++ ++ public AutoReleased(E object, Runnable cleaner) { ++ this.object = object; ++ this.cleaner = cleaner; ++ } ++ ++ public final E getObject() { ++ return object; ++ } ++ ++ public final Runnable getCleaner() { ++ return cleaner; ++ } ++ } ++ ++ public static final PooledObjects POOLED_MUTABLE_INTEGERS = new PooledObjects<>(MutableInt::new, 1024); ++ ++ private final Supplier creator; ++ private final Consumer releaser; ++ private final int maxPoolSize; ++ private final ArrayDeque queue; ++ ++ public PooledObjects(final Supplier creator, int maxPoolSize) { ++ this(creator, maxPoolSize, null); ++ } ++ public PooledObjects(final Supplier creator, int maxPoolSize, Consumer releaser) { ++ if (creator == null) { ++ throw new NullPointerException("Creator must not be null"); ++ } ++ if (maxPoolSize <= 0) { ++ throw new IllegalArgumentException("Max pool size must be greater-than 0"); ++ } ++ ++ this.queue = new ArrayDeque<>(maxPoolSize); ++ this.maxPoolSize = maxPoolSize; ++ this.creator = creator; ++ this.releaser = releaser; ++ } ++ ++ public AutoReleased acquireCleaner(Object holder) { ++ return acquireCleaner(holder, this::release); ++ } ++ ++ public AutoReleased acquireCleaner(Object holder, Consumer releaser) { ++ E resource = acquire(); ++ Runnable cleaner = MCUtil.registerCleaner(holder, resource, releaser); ++ return new AutoReleased(resource, cleaner); ++ } ++ ++ public final E acquire() { ++ E value; ++ synchronized (queue) { ++ value = this.queue.pollLast(); ++ } ++ return value != null ? value : this.creator.get(); ++ } ++ ++ public final void release(final E value) { ++ if (this.releaser != null) { ++ this.releaser.accept(value); ++ } ++ synchronized (this.queue) { ++ if (queue.size() < this.maxPoolSize) { ++ this.queue.addLast(value); ++ } ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java +@@ -0,0 +1,67 @@ ++package com.destroystokyo.paper.util.set; ++ ++import java.util.Collection; ++ ++/** ++ * @author Spottedleaf ++ */ ++public final class OptimizedSmallEnumSet> { ++ ++ private final Class enumClass; ++ private long backingSet; ++ ++ public OptimizedSmallEnumSet(final Class clazz) { ++ if (clazz == null) { ++ throw new IllegalArgumentException("Null class"); ++ } ++ if (!clazz.isEnum()) { ++ throw new IllegalArgumentException("Class must be enum, not " + clazz.getCanonicalName()); ++ } ++ this.enumClass = clazz; ++ } ++ ++ public boolean addUnchecked(final E element) { ++ final int ordinal = element.ordinal(); ++ final long key = 1L << ordinal; ++ ++ final long prev = this.backingSet; ++ this.backingSet = prev | key; ++ ++ return (prev & key) == 0; ++ } ++ ++ public boolean removeUnchecked(final E element) { ++ final int ordinal = element.ordinal(); ++ final long key = 1L << ordinal; ++ ++ final long prev = this.backingSet; ++ this.backingSet = prev & ~key; ++ ++ return (prev & key) != 0; ++ } ++ ++ public void clear() { ++ this.backingSet = 0L; ++ } ++ ++ public int size() { ++ return Long.bitCount(this.backingSet); ++ } ++ ++ public void addAllUnchecked(final Collection enums) { ++ for (final E element : enums) { ++ if (element == null) { ++ throw new NullPointerException("Null element"); ++ } ++ this.backingSet |= (1L << element.ordinal()); ++ } ++ } ++ ++ public long getBackingSet() { ++ return this.backingSet; ++ } ++ ++ public boolean hasCommonElements(final OptimizedSmallEnumSet other) { ++ return (other.backingSet & this.backingSet) != 0; ++ } ++} +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index 8c378d3f3138953b3b22b289fecdb6b40a09ab63..67fa685f4b8de3eae1431c0de399c246678b542a 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -78,7 +78,7 @@ public class Util { + } + + public static long getNanos() { +- return Util.timeSource.getAsLong(); ++ return System.nanoTime(); // Paper + } + + public static long getEpochMillis() { +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 88147a1f25cf2fd549412b653b8f0eb5c60bb55d..6a58059a05e16d96894b67a544c2f595d9546c78 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -105,6 +105,7 @@ public class BlockPos extends Vec3i { + return x == 0.0D && y == 0.0D && z == 0.0D ? this : new BlockPos((double) this.getX() + x, (double) this.getY() + y, (double) this.getZ() + z); + } + ++ public final BlockPos add(int i, int j, int k) {return offset(i, j, k);} // Paper - OBFHELPER + public BlockPos offset(int x, int y, int z) { + return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.getX() + x, this.getY() + y, this.getZ() + z); + } +@@ -436,6 +437,7 @@ public class BlockPos extends Vec3i { + return super.rotate(rotation).immutable(); + } + ++ public final BlockPos.MutableBlockPos setValues(int i, int j, int k) { return set(i, j, k);} // Paper - OBFHELPER + public BlockPos.MutableBlockPos set(int x, int y, int z) { + this.setX(x); + this.setY(y); +@@ -443,6 +445,7 @@ public class BlockPos extends Vec3i { + return this; + } + ++ public final BlockPos.MutableBlockPos setValues(double d0, double d1, double d2) { return set(d0, d1, d2);} // Paper - OBFHELPER + public BlockPos.MutableBlockPos set(double x, double y, double z) { + return this.set(Mth.floor(x), Mth.floor(y), Mth.floor(z)); + } +@@ -496,20 +499,21 @@ public class BlockPos extends Vec3i { + } + } + ++ /* // Paper start - comment out useless overrides @Override + @Override +- public void setX(int x) { +- super.setX(x); ++ public void o(int i) { ++ super.o(i); + } + + @Override +- public void setY(int y) { +- super.setY(y); ++ public void p(int i) { ++ super.p(i); + } + +- @Override +- public void setZ(int z) { +- super.setZ(z); ++ public void q(int i) { ++ super.q(i); + } ++ */ // Paper end + + @Override + public BlockPos immutable() { +diff --git a/src/main/java/net/minecraft/core/IdMapper.java b/src/main/java/net/minecraft/core/IdMapper.java +index 424c6cacc2e7c7b1c9d0b92fe198237033a3fcbd..e7358721e9d78bc9cbbfc3e71ce927ea4b82ce7c 100644 +--- a/src/main/java/net/minecraft/core/IdMapper.java ++++ b/src/main/java/net/minecraft/core/IdMapper.java +@@ -64,6 +64,7 @@ public class IdMapper implements IdMap { + return Iterators.filter(this.idToT.iterator(), Predicates.notNull()); + } + ++ public int size() { return this.size(); } // Paper - OBFHELPER + public int size() { + return this.tToId.size(); + } +diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java +index 9bd2120bdcfe204184eb9a9e1daa5e3338665e51..3e79b274b8e0406a3cbdd94c7cec091b583109ca 100644 +--- a/src/main/java/net/minecraft/core/Vec3i.java ++++ b/src/main/java/net/minecraft/core/Vec3i.java +@@ -18,9 +18,9 @@ public class Vec3i implements Comparable { + return IntStream.of(new int[]{baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()}); + }); + public static final Vec3i ZERO = new Vec3i(0, 0, 0); +- private int x; +- private int y; +- private int z; ++ private int x;public final void setX(final int x) { this.x = x; } // Paper - OBFHELPER ++ private int y;public final void setY(final int y) { this.y = y; } // Paper - OBFHELPER ++ private int z;public final void setZ(final int z) { this.z = z; } // Paper - OBFHELPER + + public Vec3i(int x, int y, int z) { + this.x = x; +@@ -64,15 +64,15 @@ public class Vec3i implements Comparable { + return this.z; + } + +- protected void setX(int x) { ++ public void setX(int x) { // Paper - protected -> public + this.x = x; + } + +- protected void setY(int y) { ++ public void setY(int y) { // Paper - protected -> public + this.y = y; + } + +- protected void setZ(int z) { ++ public void setZ(int z) { // Paper - protected -> public + this.z = z; + } + +@@ -108,6 +108,7 @@ public class Vec3i implements Comparable { + return this.distSqr(pos.x(), pos.y(), pos.z(), true) < distance * distance; + } + ++ public final double distanceSquared(Vec3i baseblockposition) { return distSqr(baseblockposition); } // Paper - OBFHELPER + public double distSqr(Vec3i vec) { + return this.distSqr((double) vec.getX(), (double) vec.getY(), (double) vec.getZ(), true); + } +diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java +index 077383bd9af79851351eba50e7d7ea31cc106cad..4c8f249e45e5deb7628997d4dbd9dab613ac5241 100644 +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -76,7 +76,7 @@ public class CompoundTag implements Tag { + return "TAG_Compound"; + } + }; +- private final Map tags; ++ public final Map tags; // Paper + + protected CompoundTag(Map tags) { + this.tags = tags; +@@ -139,10 +139,16 @@ public class CompoundTag implements Tag { + this.tags.put(key, LongTag.valueOf(value)); + } + ++ public void setUUID(String prefix, UUID uuid) { putUUID(prefix, uuid); } // Paper - OBFHELPER + public void putUUID(String key, UUID value) { + this.tags.put(key, NbtUtils.createUUID(value)); + } + ++ ++ /** ++ * You must use {@link #hasUUID(String)} before or else it will throw an NPE. ++ */ ++ public UUID getUUID(String prefix) { return getUUID(prefix); } // Paper - OBFHELPER + public UUID getUUID(String key) { + return NbtUtils.loadUUID(this.get(key)); + } +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 8ce3a74821a0e540423a2e8e67be640b8b876035..92c5c5bbcfe364475578b6a0eddfaa85858ace8a 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -168,6 +168,7 @@ public class Connection extends SimpleChannelInboundHandler> { + + } + ++ private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.sendPacket(packet, genericFutureListener); } // Paper - OBFHELPER + private void sendPacket(Packet packet, @Nullable GenericFutureListener> callback) { + ConnectionProtocol enumprotocol = ConnectionProtocol.getProtocolForPacket(packet); + ConnectionProtocol enumprotocol1 = (ConnectionProtocol) this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).get(); +@@ -208,6 +209,7 @@ public class Connection extends SimpleChannelInboundHandler> { + + } + ++ private void sendPacketQueue() { this.flushQueue(); } // Paper - OBFHELPER + private void flushQueue() { + if (this.channel != null && this.channel.isOpen()) { + Queue queue = this.queue; +@@ -344,9 +346,9 @@ public class Connection extends SimpleChannelInboundHandler> { + + static class PacketHolder { + +- private final Packet packet; ++ private final Packet packet; private final Packet getPacket() { return this.packet; } // Paper - OBFHELPER + @Nullable +- private final GenericFutureListener> listener; ++ private final GenericFutureListener> listener; private final GenericFutureListener> getGenericFutureListener() { return this.listener; } // Paper - OBFHELPER + + public PacketHolder(Packet packet, @Nullable GenericFutureListener> callback) { + this.packet = packet; +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index e0dc41a8f408b7fa0b8554833ea4d09e7e604913..50f14acb062c2f90266279dbd1945a3297396f0b 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -48,6 +48,7 @@ public class FriendlyByteBuf extends ByteBuf { + this.source = bytebuf; + } + ++ public static int countBytes(int i) { return FriendlyByteBuf.getVarIntSize(i); } // Paper - OBFHELPER + public static int getVarIntSize(int i) { + for (int j = 1; j < 5; ++j) { + if ((i & -1 << j * 7) == 0) { +diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java +index 7af36e5a889d04f6e80c80f7335bf149a4b5d224..14fa1371e52b9af5a7550a9aa144fa406b754046 100644 +--- a/src/main/java/net/minecraft/network/PacketEncoder.java ++++ b/src/main/java/net/minecraft/network/PacketEncoder.java +@@ -44,6 +44,7 @@ public class PacketEncoder extends MessageToByteEncoder> { + packet.write(packetdataserializer); + } catch (Throwable throwable) { + PacketEncoder.LOGGER.error(throwable); ++ throwable.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? + if (packet.isSkippable()) { + throw new SkipPacketException(throwable); + } else { +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index bda189ab2b3b934e6bf9fd11da5d95bd9b37ba70..e5d4363edb8c494d2db69d2e0223a2db1519f64b 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -28,7 +28,7 @@ public class ClientboundLevelChunkPacket implements Packet blockEntitiesTags; + private boolean fullChunk; + +@@ -140,6 +140,7 @@ public class ClientboundLevelChunkPacket implements Packet { + +- private ItemStack book; ++ private ItemStack book; public ItemStack getBook() { return book; } // Paper - OBFHELPER + private boolean signing; + private int slot; + +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d29fe67b7d39e368a873368a6be16042429e9209 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -0,0 +1,510 @@ ++package net.minecraft.server; ++ ++import com.destroystokyo.paper.block.TargetBlockInfo; ++import com.google.common.util.concurrent.ThreadFactoryBuilder; ++import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.ClipContext; ++import net.minecraft.world.level.Level; ++import org.apache.commons.lang.exception.ExceptionUtils; ++import org.bukkit.Location; ++import org.bukkit.block.BlockFace; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.spigotmc.AsyncCatcher; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++import java.util.List; ++import java.util.Queue; ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.ExecutionException; ++import java.util.concurrent.LinkedBlockingQueue; ++import java.util.concurrent.ThreadPoolExecutor; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++import java.util.concurrent.atomic.AtomicBoolean; ++import java.util.function.BiConsumer; ++import java.util.function.Consumer; ++import java.util.function.Supplier; ++ ++public final class MCUtil { ++ public static final ThreadPoolExecutor asyncExecutor = new ThreadPoolExecutor( ++ 0, 2, 60L, TimeUnit.SECONDS, ++ new LinkedBlockingQueue(), ++ new ThreadFactoryBuilder().setNameFormat("Paper Async Task Handler Thread - %1$d").build() ++ ); ++ public static final ThreadPoolExecutor cleanerExecutor = new ThreadPoolExecutor( ++ 1, 1, 0L, TimeUnit.SECONDS, ++ new LinkedBlockingQueue(), ++ new ThreadFactoryBuilder().setNameFormat("Paper Object Cleaner").build() ++ ); ++ ++ public static final long INVALID_CHUNK_KEY = getCoordinateKey(Integer.MAX_VALUE, Integer.MAX_VALUE); ++ ++ ++ public static Runnable once(Runnable run) { ++ AtomicBoolean ran = new AtomicBoolean(false); ++ return () -> { ++ if (ran.compareAndSet(false, true)) { ++ run.run(); ++ } ++ }; ++ } ++ ++ public static Runnable once(List list, Consumer cb) { ++ return once(() -> { ++ list.forEach(cb); ++ }); ++ } ++ ++ private static Runnable makeCleanerCallback(Runnable run) { ++ return once(() -> cleanerExecutor.execute(run)); ++ } ++ ++ /** ++ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! ++ * @param obj ++ * @param run ++ * @return ++ */ ++ public static Runnable registerCleaner(Object obj, Runnable run) { ++ // Wrap callback in its own method above or the lambda will leak object ++ Runnable cleaner = makeCleanerCallback(run); ++ co.aikar.cleaner.Cleaner.register(obj, cleaner); ++ return cleaner; ++ } ++ ++ /** ++ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! ++ * @param obj ++ * @param list ++ * @param cleaner ++ * @param ++ * @return ++ */ ++ public static Runnable registerListCleaner(Object obj, List list, Consumer cleaner) { ++ return registerCleaner(obj, () -> { ++ list.forEach(cleaner); ++ list.clear(); ++ }); ++ } ++ ++ /** ++ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! ++ * @param obj ++ * @param resource ++ * @param cleaner ++ * @param ++ * @return ++ */ ++ public static Runnable registerCleaner(Object obj, T resource, java.util.function.Consumer cleaner) { ++ return registerCleaner(obj, () -> cleaner.accept(resource)); ++ } ++ ++ public static List getSpiralOutChunks(BlockPos blockposition, int radius) { ++ List list = com.google.common.collect.Lists.newArrayList(); ++ ++ list.add(new ChunkPos(blockposition.getX() >> 4, blockposition.getZ() >> 4)); ++ for (int r = 1; r <= radius; r++) { ++ int x = -r; ++ int z = r; ++ ++ // Iterates the edge of half of the box; then negates for other half. ++ while (x <= r && z > -r) { ++ list.add(new ChunkPos((blockposition.getX() + (x << 4)) >> 4, (blockposition.getZ() + (z << 4)) >> 4)); ++ list.add(new ChunkPos((blockposition.getX() - (x << 4)) >> 4, (blockposition.getZ() - (z << 4)) >> 4)); ++ ++ if (x < r) { ++ x++; ++ } else { ++ z--; ++ } ++ } ++ } ++ return list; ++ } ++ ++ public static int fastFloor(double x) { ++ int truncated = (int)x; ++ return x < (double)truncated ? truncated - 1 : truncated; ++ } ++ ++ public static int fastFloor(float x) { ++ int truncated = (int)x; ++ return x < (double)truncated ? truncated - 1 : truncated; ++ } ++ ++ public static float normalizeYaw(float f) { ++ float f1 = f % 360.0F; ++ ++ if (f1 >= 180.0F) { ++ f1 -= 360.0F; ++ } ++ ++ if (f1 < -180.0F) { ++ f1 += 360.0F; ++ } ++ ++ return f1; ++ } ++ ++ /** ++ * Quickly generate a stack trace for current location ++ * ++ * @return Stacktrace ++ */ ++ public static String stack() { ++ return ExceptionUtils.getFullStackTrace(new Throwable()); ++ } ++ ++ /** ++ * Quickly generate a stack trace for current location with message ++ * ++ * @param str ++ * @return Stacktrace ++ */ ++ public static String stack(String str) { ++ return ExceptionUtils.getFullStackTrace(new Throwable(str)); ++ } ++ ++ public static long getCoordinateKey(final BlockPos blockPos) { ++ return ((long)(blockPos.getZ() >> 4) << 32) | ((blockPos.getX() >> 4) & 0xFFFFFFFFL); ++ } ++ ++ public static long getCoordinateKey(final Entity entity) { ++ return ((long)(MCUtil.fastFloor(entity.getZ()) >> 4) << 32) | ((MCUtil.fastFloor(entity.getX()) >> 4) & 0xFFFFFFFFL); ++ } ++ ++ public static long getCoordinateKey(final ChunkPos pair) { ++ return ((long)pair.z << 32) | (pair.x & 0xFFFFFFFFL); ++ } ++ ++ public static long getCoordinateKey(final int x, final int z) { ++ return ((long)z << 32) | (x & 0xFFFFFFFFL); ++ } ++ ++ public static int getCoordinateX(final long key) { ++ return (int)key; ++ } ++ ++ public static int getCoordinateZ(final long key) { ++ return (int)(key >>> 32); ++ } ++ ++ public static int getChunkCoordinate(final double coordinate) { ++ return MCUtil.fastFloor(coordinate) >> 4; ++ } ++ ++ public static int getBlockCoordinate(final double coordinate) { ++ return MCUtil.fastFloor(coordinate); ++ } ++ ++ public static long getBlockKey(final int x, final int y, final int z) { ++ return ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54); ++ } ++ ++ public static long getBlockKey(final BlockPos pos) { ++ return ((long)pos.getX() & 0x7FFFFFF) | (((long)pos.getZ() & 0x7FFFFFF) << 27) | ((long)pos.getY() << 54); ++ } ++ ++ public static long getBlockKey(final Entity entity) { ++ return getBlockKey(getBlockCoordinate(entity.getX()), getBlockCoordinate(entity.getY()), getBlockCoordinate(entity.getZ())); ++ } ++ ++ // assumes the sets have the same comparator, and if this comparator is null then assume T is Comparable ++ public static void mergeSortedSets(final java.util.function.Consumer consumer, final java.util.Comparator comparator, final java.util.SortedSet...sets) { ++ final ObjectRBTreeSet all = new ObjectRBTreeSet<>(comparator); ++ // note: this is done in log(n!) ~ nlogn time. It could be improved if it were to mimic what mergesort does. ++ for (java.util.SortedSet set : sets) { ++ if (set != null) { ++ all.addAll(set); ++ } ++ } ++ all.forEach(consumer); ++ } ++ ++ private MCUtil() {} ++ ++ public static final java.util.concurrent.Executor MAIN_EXECUTOR = (run) -> { ++ if (!isMainThread()) { ++ MinecraftServer.getServer().execute(run); ++ } else { ++ run.run(); ++ } ++ }; ++ ++ public static CompletableFuture ensureMain(CompletableFuture future) { ++ return future.thenApplyAsync(r -> r, MAIN_EXECUTOR); ++ } ++ ++ public static void thenOnMain(CompletableFuture future, Consumer consumer) { ++ future.thenAcceptAsync(consumer, MAIN_EXECUTOR); ++ } ++ public static void thenOnMain(CompletableFuture future, BiConsumer consumer) { ++ future.whenCompleteAsync(consumer, MAIN_EXECUTOR); ++ } ++ ++ public static boolean isMainThread() { ++ return MinecraftServer.getServer().isSameThread(); ++ } ++ ++ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable) { ++ return scheduleTask(ticks, runnable, null); ++ } ++ ++ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable, String taskName) { ++ return MinecraftServer.getServer().server.getScheduler().scheduleInternalTask(runnable, ticks, taskName); ++ } ++ ++ public static void processQueue() { ++ Runnable runnable; ++ Queue processQueue = getProcessQueue(); ++ while ((runnable = processQueue.poll()) != null) { ++ try { ++ runnable.run(); ++ } catch (Exception e) { ++ MinecraftServer.LOGGER.error("Error executing task", e); ++ } ++ } ++ } ++ public static T processQueueWhileWaiting(CompletableFuture future) { ++ try { ++ if (isMainThread()) { ++ while (!future.isDone()) { ++ try { ++ return future.get(1, TimeUnit.MILLISECONDS); ++ } catch (TimeoutException ignored) { ++ processQueue(); ++ } ++ } ++ } ++ return future.get(); ++ } catch (Exception e) { ++ throw new RuntimeException(e); ++ } ++ } ++ ++ public static void ensureMain(Runnable run) { ++ ensureMain(null, run); ++ } ++ /** ++ * Ensures the target code is running on the main thread ++ * @param reason ++ * @param run ++ * @return ++ */ ++ public static void ensureMain(String reason, Runnable run) { ++ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { ++ if (reason != null) { ++ new IllegalStateException("Asynchronous " + reason + "!").printStackTrace(); ++ } ++ getProcessQueue().add(run); ++ return; ++ } ++ run.run(); ++ } ++ ++ private static Queue getProcessQueue() { ++ return MinecraftServer.getServer().processQueue; ++ } ++ ++ public static T ensureMain(Supplier run) { ++ return ensureMain(null, run); ++ } ++ /** ++ * Ensures the target code is running on the main thread ++ * @param reason ++ * @param run ++ * @param ++ * @return ++ */ ++ public static T ensureMain(String reason, Supplier run) { ++ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { ++ if (reason != null) { ++ new IllegalStateException("Asynchronous " + reason + "! Blocking thread until it returns ").printStackTrace(); ++ } ++ Waitable wait = new Waitable() { ++ @Override ++ protected T evaluate() { ++ return run.get(); ++ } ++ }; ++ getProcessQueue().add(wait); ++ try { ++ return wait.get(); ++ } catch (InterruptedException | ExecutionException e) { ++ e.printStackTrace(); ++ } ++ return null; ++ } ++ return run.get(); ++ } ++ ++ /** ++ * Calculates distance between 2 entities ++ * @param e1 ++ * @param e2 ++ * @return ++ */ ++ public static double distance(Entity e1, Entity e2) { ++ return Math.sqrt(distanceSq(e1, e2)); ++ } ++ ++ ++ /** ++ * Calculates distance between 2 block positions ++ * @param e1 ++ * @param e2 ++ * @return ++ */ ++ public static double distance(BlockPos e1, BlockPos e2) { ++ return Math.sqrt(distanceSq(e1, e2)); ++ } ++ ++ /** ++ * Gets the distance between 2 positions ++ * @param x1 ++ * @param y1 ++ * @param z1 ++ * @param x2 ++ * @param y2 ++ * @param z2 ++ * @return ++ */ ++ public static double distance(double x1, double y1, double z1, double x2, double y2, double z2) { ++ return Math.sqrt(distanceSq(x1, y1, z1, x2, y2, z2)); ++ } ++ ++ /** ++ * Get's the distance squared between 2 entities ++ * @param e1 ++ * @param e2 ++ * @return ++ */ ++ public static double distanceSq(Entity e1, Entity e2) { ++ return distanceSq(e1.getX(),e1.getY(),e1.getZ(), e2.getX(),e2.getY(),e2.getZ()); ++ } ++ ++ /** ++ * Gets the distance sqaured between 2 block positions ++ * @param pos1 ++ * @param pos2 ++ * @return ++ */ ++ public static double distanceSq(BlockPos pos1, BlockPos pos2) { ++ return distanceSq(pos1.getX(), pos1.getY(), pos1.getZ(), pos2.getX(), pos2.getY(), pos2.getZ()); ++ } ++ ++ /** ++ * Gets the distance squared between 2 positions ++ * @param x1 ++ * @param y1 ++ * @param z1 ++ * @param x2 ++ * @param y2 ++ * @param z2 ++ * @return ++ */ ++ public static double distanceSq(double x1, double y1, double z1, double x2, double y2, double z2) { ++ return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2); ++ } ++ ++ /** ++ * Converts a NMS World/BlockPosition to Bukkit Location ++ * @param world ++ * @param x ++ * @param y ++ * @param z ++ * @return ++ */ ++ public static Location toLocation(Level world, double x, double y, double z) { ++ return new Location(world.getWorld(), x, y, z); ++ } ++ ++ /** ++ * Converts a NMS World/BlockPosition to Bukkit Location ++ * @param world ++ * @param pos ++ * @return ++ */ ++ public static Location toLocation(Level world, BlockPos pos) { ++ return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()); ++ } ++ ++ /** ++ * Converts an NMS entity's current location to a Bukkit Location ++ * @param entity ++ * @return ++ */ ++ public static Location toLocation(Entity entity) { ++ return new Location(entity.getCommandSenderWorld().getWorld(), entity.getX(), entity.getY(), entity.getZ()); ++ } ++ ++ public static org.bukkit.block.Block toBukkitBlock(Level world, BlockPos pos) { ++ return world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ } ++ ++ public static BlockPos toBlockPosition(Location loc) { ++ return new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); ++ } ++ ++ public static boolean isEdgeOfChunk(BlockPos pos) { ++ final int modX = pos.getX() & 15; ++ final int modZ = pos.getZ() & 15; ++ return (modX == 0 || modX == 15 || modZ == 0 || modZ == 15); ++ } ++ ++ /** ++ * Posts a task to be executed asynchronously ++ * @param run ++ */ ++ public static void scheduleAsyncTask(Runnable run) { ++ asyncExecutor.execute(run); ++ } ++ ++ @Nonnull ++ public static ServerLevel getNMSWorld(@Nonnull org.bukkit.World world) { ++ return ((CraftWorld) world).getHandle(); ++ } ++ ++ public static ServerLevel getNMSWorld(@Nonnull org.bukkit.entity.Entity entity) { ++ return getNMSWorld(entity.getWorld()); ++ } ++ ++ public static ClipContext.Fluid getNMSFluidCollisionOption(TargetBlockInfo.FluidMode fluidMode) { ++ if (fluidMode == TargetBlockInfo.FluidMode.NEVER) { ++ return ClipContext.Fluid.NONE; ++ } ++ if (fluidMode == TargetBlockInfo.FluidMode.SOURCE_ONLY) { ++ return ClipContext.Fluid.SOURCE_ONLY; ++ } ++ if (fluidMode == TargetBlockInfo.FluidMode.ALWAYS) { ++ return ClipContext.Fluid.ANY; ++ } ++ return null; ++ } ++ ++ public static BlockFace toBukkitBlockFace(Direction enumDirection) { ++ switch (enumDirection) { ++ case DOWN: ++ return BlockFace.DOWN; ++ case UP: ++ return BlockFace.UP; ++ case NORTH: ++ return BlockFace.NORTH; ++ case SOUTH: ++ return BlockFace.SOUTH; ++ case WEST: ++ return BlockFace.WEST; ++ case EAST: ++ return BlockFace.EAST; ++ default: ++ return null; ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 37a51dee4cd37844e80fdd5c9853947201151dfc..2406879e76a110e96a4753e66366432a4bc52d9b 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -882,6 +882,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop CHUNK_STATUSES = ChunkStatus.getStatusList(); + private static final ChunkHolder.FullChunkStatus[] FULL_CHUNK_STATUSES = ChunkHolder.FullChunkStatus.values(); + private final AtomicReferenceArray>> futures; +- private volatile CompletableFuture> fullChunkFuture; +- private volatile CompletableFuture> tickingChunkFuture; +- private volatile CompletableFuture> entityTickingChunkFuture; ++ private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage ++ private volatile CompletableFuture> tickingChunkFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage ++ private volatile CompletableFuture> entityTickingChunkFuture; private volatile boolean isEntityTickingReady; // Paper - cache chunk ticking stage + private CompletableFuture chunkToSave; + public int oldTicketLevel; + private int ticketLevel; +@@ -63,6 +63,8 @@ public class ChunkHolder { + private boolean wasAccessibleSinceLastSave; + private boolean resendLight; + ++ private final ChunkMap chunkMap; // Paper ++ + public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +@@ -78,10 +80,49 @@ public class ChunkHolder { + this.ticketLevel = this.oldTicketLevel; + this.queueLevel = this.oldTicketLevel; + this.setTicketLevel(level); ++ this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper ++ } ++ ++ // Paper start ++ @Nullable ++ public final LevelChunk getEntityTickingChunk() { ++ CompletableFuture> completablefuture = this.entityTickingChunkFuture; ++ Either either = completablefuture.getNow(null); ++ ++ return either == null ? null : either.left().orElse(null); ++ } ++ ++ @Nullable ++ public final LevelChunk getTickingChunk() { ++ CompletableFuture> completablefuture = this.tickingChunkFuture; ++ Either either = completablefuture.getNow(null); ++ ++ return either == null ? null : either.left().orElse(null); ++ } ++ ++ @Nullable ++ public final LevelChunk getFullReadyChunk() { ++ CompletableFuture> completablefuture = this.fullChunkFuture; ++ Either either = completablefuture.getNow(null); ++ ++ return either == null ? null : either.left().orElse(null); ++ } ++ ++ public final boolean isEntityTickingReady() { ++ return this.isEntityTickingReady; ++ } ++ ++ public final boolean isTickingReady() { ++ return this.isTickingReady; ++ } ++ ++ public final boolean isFullChunkReady() { ++ return this.isFullChunkReady; + } ++ // Paper end + + // CraftBukkit start +- public LevelChunk getFullChunk() { ++ public final LevelChunk getFullChunk() { // Paper - final for inline + if (!getFullChunkStatus(this.oldTicketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) return null; // note: using oldTicketLevel for isLoaded checks + return this.getFullChunkUnchecked(); + } +@@ -92,6 +133,14 @@ public class ChunkHolder { + return (either == null) ? null : (LevelChunk) either.left().orElse(null); + } + // CraftBukkit end ++ // Paper start - "real" get full chunk immediately ++ public final LevelChunk getFullChunkIfCached() { ++ // Note: Copied from above without ticket level check ++ CompletableFuture> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL); ++ Either either = (Either) statusFuture.getNow(null); ++ return either == null ? null : (LevelChunk) either.left().orElse(null); ++ } ++ // Paper end + + public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { + CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(leastStatus.getIndex()); +@@ -103,20 +152,23 @@ public class ChunkHolder { + return getStatus(this.ticketLevel).isOrAfter(leastStatus) ? this.getFutureIfPresentUnchecked(leastStatus) : ChunkHolder.UNLOADED_CHUNK_FUTURE; + } + +- public CompletableFuture> getTickingChunkFuture() { ++ public final CompletableFuture> getTickingFuture() { return this.getTickingChunkFuture(); } // Paper - OBFHELPER ++ public final CompletableFuture> getTickingChunkFuture() { // Paper - final for inline + return this.tickingChunkFuture; + } + +- public CompletableFuture> getEntityTickingChunkFuture() { ++ public final CompletableFuture> getEntityTickingFuture() { return this.getEntityTickingChunkFuture(); } // Paper - OBFHELPER ++ public final CompletableFuture> getEntityTickingChunkFuture() { // Paper - final for inline + return this.entityTickingChunkFuture; + } + +- public CompletableFuture> getFullChunkFuture() { ++ public final CompletableFuture> getFullChunkFuture() { return this.getFullChunkFuture(); } // Paper - OBFHELPER ++ public final CompletableFuture> getFullChunkFuture() { // Paper - final for inline + return this.fullChunkFuture; + } + + @Nullable +- public LevelChunk getTickingChunk() { ++ public final LevelChunk getTickingChunk() { // Paper - final for inline + CompletableFuture> completablefuture = this.getTickingChunkFuture(); + Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error + +@@ -141,7 +193,7 @@ public class ChunkHolder { + return null; + } + +- public CompletableFuture getChunkToSave() { ++ public final CompletableFuture getChunkToSave() { // Paper - final for inline + return this.chunkToSave; + } + +@@ -282,11 +334,11 @@ public class ChunkHolder { + }); + } + +- public ChunkPos getPos() { ++ public final ChunkPos getPos() { // Paper - final for inline + return this.pos; + } + +- public int getTicketLevel() { ++ public final int getTicketLevel() { // Paper - final for inline + return this.ticketLevel; + } + +@@ -357,13 +409,27 @@ public class ChunkHolder { + + this.wasAccessibleSinceLastSave |= flag3; + if (!flag2 && flag3) { +- this.fullChunkFuture = chunkStorage.unpackTicks(this); ++ // Paper start - cache ticking ready status ++ int expectCreateCount = ++this.fullChunkCreateCount; ++ this.fullChunkFuture = chunkStorage.unpackTicks(this); this.fullChunkFuture.thenAccept((either) -> { ++ if (either.left().isPresent() && ChunkHolder.this.fullChunkCreateCount == expectCreateCount) { ++ // note: Here is a very good place to add callbacks to logic waiting on this. ++ LevelChunk fullChunk = either.left().get(); ++ ChunkHolder.this.isFullChunkReady = true; ++ fullChunk.playerChunk = ChunkHolder.this; ++ ++ ++ } ++ }); ++ // Paper end + this.updateChunkToSave(this.fullChunkFuture); + } + + if (flag2 && !flag3) { + completablefuture = this.fullChunkFuture; + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; ++ ++this.fullChunkCreateCount; // Paper - cache ticking ready status ++ this.isFullChunkReady = false; // Paper - cache ticking ready status + this.updateChunkToSave(((CompletableFuture>) completablefuture).thenApply((either1) -> { // CraftBukkit - decompile error + chunkStorage.getClass(); + return either1.ifLeft(chunkStorage::packTicks); +@@ -374,12 +440,24 @@ public class ChunkHolder { + boolean flag5 = playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.TICKING); + + if (!flag4 && flag5) { +- this.tickingChunkFuture = chunkStorage.postProcess(this); ++ // Paper start - cache ticking ready status ++ this.tickingChunkFuture = chunkStorage.postProcess(this); this.tickingChunkFuture.thenAccept((either) -> { ++ if (either.left().isPresent()) { ++ // note: Here is a very good place to add callbacks to logic waiting on this. ++ LevelChunk tickingChunk = either.left().get(); ++ ChunkHolder.this.isTickingReady = true; ++ ++ ++ ++ ++ } ++ }); ++ // Paper end + this.updateChunkToSave(this.tickingChunkFuture); + } + + if (flag4 && !flag5) { +- this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); ++ this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); this.isTickingReady = false; // Paper - cache chunk ticking stage + this.tickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + } + +@@ -391,12 +469,24 @@ public class ChunkHolder { + throw (IllegalStateException) Util.pauseInIde((Throwable) (new IllegalStateException())); + } + +- this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); ++ // Paper start - cache ticking ready status ++ this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); this.entityTickingChunkFuture.thenAccept((either) -> { ++ if (either.left().isPresent()) { ++ // note: Here is a very good place to add callbacks to logic waiting on this. ++ LevelChunk entityTickingChunk = either.left().get(); ++ ChunkHolder.this.isEntityTickingReady = true; ++ ++ ++ ++ ++ } ++ }); ++ // Paper end + this.updateChunkToSave(this.entityTickingChunkFuture); + } + + if (flag6 && !flag7) { +- this.entityTickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); ++ this.entityTickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage + this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + } + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index aaa56d121cdb66066e869b7cbdc2c863974d51b0..d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -54,6 +54,7 @@ import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; + import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; + import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; + import net.minecraft.network.protocol.game.DebugPackets; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.progress.ChunkProgressListener; + import net.minecraft.util.CsvOutput; + import net.minecraft.util.Mth; +@@ -144,6 +145,26 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }; + // CraftBukkit end + ++ // Paper start - distance maps ++ private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); ++ ++ void addPlayerToDistanceMaps(ServerPlayer player) { ++ int chunkX = MCUtil.getChunkCoordinate(player.getX()); ++ int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); ++ // Note: players need to be explicitly added to distance maps before they can be updated ++ } ++ ++ void removePlayerFromDistanceMaps(ServerPlayer player) { ++ ++ } ++ ++ void updateMaps(ServerPlayer player) { ++ int chunkX = MCUtil.getChunkCoordinate(player.getX()); ++ int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); ++ // Note: players need to be explicitly added to distance maps before they can be updated ++ } ++ // Paper end ++ + public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier supplier, int i, boolean flag) { + super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag); + this.visibleChunkMap = this.updatingChunkMap.clone(); +@@ -233,6 +254,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }; + } + ++ // Paper start ++ public final int getEffectiveViewDistance() { ++ // TODO this needs to be checked on update ++ // Mojang currently sets it to +1 of the configured view distance. So subtract one to get the one we really want. ++ return this.viewDistance - 1; ++ } ++ // Paper end ++ + private CompletableFuture, ChunkHolder.ChunkLoadingFailure>> getChunkRangeFuture(ChunkPos centerChunk, int margin, IntFunction distanceToStatus) { + List>> list = Lists.newArrayList(); + int j = centerChunk.x; +@@ -951,6 +980,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (!flag1) { + this.distanceManager.addPlayer(SectionPos.of((Entity) player), player); + } ++ this.addPlayerToDistanceMaps(player); // Paper - distance maps + } else { + SectionPos sectionposition = player.getLastSectionPos(); + +@@ -958,6 +988,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (!flag2) { + this.distanceManager.removePlayer(sectionposition, player); + } ++ this.removePlayerFromDistanceMaps(player); // Paper - distance maps + } + + for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { +@@ -1068,6 +1099,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + } + ++ this.updateMaps(player); // Paper - distance maps ++ + } + + @Override +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 7cc5070f70a4f740add9d971385ceaa4d44275a2..ef336645f3bd7a86129ad1dff7e1a15dc93d1e3e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -42,6 +42,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelData; + import net.minecraft.world.level.storage.LevelStorageSource; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper + + public class ServerChunkCache extends ChunkSource { + +@@ -49,7 +50,7 @@ public class ServerChunkCache extends ChunkSource { + private final DistanceManager distanceManager; + public final ChunkGenerator generator; + private final ServerLevel level; +- private final Thread mainThread; ++ public final Thread mainThread; // Paper - private -> public + private final ThreadedLevelLightEngine lightEngine; + private final ServerChunkCache.MainThreadExecutor mainThreadProcessor; + public final ChunkMap chunkMap; +@@ -62,6 +63,158 @@ public class ServerChunkCache extends ChunkSource { + private final ChunkAccess[] lastChunk = new ChunkAccess[4]; + @Nullable + private NaturalSpawner.SpawnState lastSpawnState; ++ // Paper start ++ final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock(); ++ final Long2ObjectOpenHashMap loadedChunkMap = new Long2ObjectOpenHashMap<>(8192, 0.5f); ++ ++ private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4]; ++ ++ private static int getChunkCacheKey(int x, int z) { ++ return x & 3 | ((z & 3) << 2); ++ } ++ ++ public void addLoadedChunk(LevelChunk chunk) { ++ this.loadedChunkMapSeqLock.acquireWrite(); ++ try { ++ this.loadedChunkMap.put(chunk.coordinateKey, chunk); ++ } finally { ++ this.loadedChunkMapSeqLock.releaseWrite(); ++ } ++ ++ // rewrite cache if we have to ++ // we do this since we also cache null chunks ++ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); ++ ++ this.lastLoadedChunks[cacheKey] = chunk; ++ } ++ ++ public void removeLoadedChunk(LevelChunk chunk) { ++ this.loadedChunkMapSeqLock.acquireWrite(); ++ try { ++ this.loadedChunkMap.remove(chunk.coordinateKey); ++ } finally { ++ this.loadedChunkMapSeqLock.releaseWrite(); ++ } ++ ++ // rewrite cache if we have to ++ // we do this since we also cache null chunks ++ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); ++ ++ LevelChunk cachedChunk = this.lastLoadedChunks[cacheKey]; ++ if (cachedChunk != null && cachedChunk.coordinateKey == chunk.coordinateKey) { ++ this.lastLoadedChunks[cacheKey] = null; ++ } ++ } ++ ++ public final LevelChunk getChunkAtIfLoadedMainThread(int x, int z) { ++ int cacheKey = getChunkCacheKey(x, z); ++ ++ LevelChunk cachedChunk = this.lastLoadedChunks[cacheKey]; ++ if (cachedChunk != null && cachedChunk.locX == x & cachedChunk.locZ == z) { ++ return this.lastLoadedChunks[cacheKey]; ++ } ++ ++ long chunkKey = ChunkPos.asLong(x, z); ++ ++ cachedChunk = this.loadedChunkMap.get(chunkKey); ++ // Skipping a null check to avoid extra instructions to improve inline capability ++ this.lastLoadedChunks[cacheKey] = cachedChunk; ++ return cachedChunk; ++ } ++ ++ public final LevelChunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) { ++ return this.loadedChunkMap.get(ChunkPos.asLong(x, z)); ++ } ++ ++ public final LevelChunk getChunkAtMainThread(int x, int z) { ++ LevelChunk ret = this.getChunkAtIfLoadedMainThread(x, z); ++ if (ret != null) { ++ return ret; ++ } ++ return (LevelChunk)this.getChunk(x, z, ChunkStatus.FULL, true); ++ } ++ ++ private long chunkFutureAwaitCounter; ++ ++ public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.mainThread) { ++ this.mainThreadProcessor.execute(() -> { ++ ServerChunkCache.this.getEntityTickingChunkAsync(x, z, onLoad); ++ }); ++ return; ++ } ++ this.getChunkFutureAsynchronously(x, z, 31, ChunkHolder::getEntityTickingFuture, onLoad); ++ } ++ ++ public void getTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.mainThread) { ++ this.mainThreadProcessor.execute(() -> { ++ ServerChunkCache.this.getTickingChunkAsync(x, z, onLoad); ++ }); ++ return; ++ } ++ this.getChunkFutureAsynchronously(x, z, 32, ChunkHolder::getTickingFuture, onLoad); ++ } ++ ++ public void getFullChunkAsync(int x, int z, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.mainThread) { ++ this.mainThreadProcessor.execute(() -> { ++ ServerChunkCache.this.getFullChunkAsync(x, z, onLoad); ++ }); ++ return; ++ } ++ this.getChunkFutureAsynchronously(x, z, 33, ChunkHolder::getFullChunkFuture, onLoad); ++ } ++ ++ private void getChunkFutureAsynchronously(int x, int z, int ticketLevel, Function>> futureGet, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.mainThread) { ++ throw new IllegalStateException(); ++ } ++ ChunkPos chunkPos = new ChunkPos(x, z); ++ Long identifier = this.chunkFutureAwaitCounter++; ++ this.distanceManager.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); ++ this.runDistanceManagerUpdates(); ++ ++ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(chunkPos.toLong()); ++ ++ if (chunk == null) { ++ throw new IllegalStateException("Expected playerchunk " + chunkPos + " in world '" + this.level.getWorld().getName() + "'"); ++ } ++ ++ CompletableFuture> future = futureGet.apply(chunk); ++ ++ future.whenCompleteAsync((either, throwable) -> { ++ try { ++ if (throwable != null) { ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath)throwable; ++ } ++ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", throwable); ++ } else if (either.right().isPresent()) { ++ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "': " + either.right().get().toString()); ++ } ++ ++ try { ++ if (onLoad != null) { ++ chunkMap.callbackExecutor.execute(() -> { ++ onLoad.accept(either == null ? null : either.left().orElse(null)); // indicate failure to the callback. ++ }); ++ } ++ } catch (Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ net.minecraft.server.MinecraftServer.LOGGER.fatal("Load callback for future await failed " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", thr); ++ return; ++ } ++ } finally { ++ // due to odd behaviour with CB unload implementation we need to have these AFTER the load callback. ++ ServerChunkCache.this.distanceManager.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); ++ ServerChunkCache.this.distanceManager.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); ++ } ++ }, this.mainThreadProcessor); ++ } ++ // Paper end + + public ServerChunkCache(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldloadlistener, Supplier supplier) { + this.level = worldserver; +@@ -123,6 +276,49 @@ public class ServerChunkCache extends ChunkSource { + this.lastChunk[0] = chunk; + } + ++ // Paper start - "real" get chunk if loaded ++ // Note: Partially copied from the getChunkAt method below ++ @Nullable ++ public LevelChunk getChunkAtIfCachedImmediately(int x, int z) { ++ long k = ChunkPos.asLong(x, z); ++ ++ // Note: Bypass cache since we need to check ticket level, and to make this MT-Safe ++ ++ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(k); ++ if (playerChunk == null) { ++ return null; ++ } ++ ++ return playerChunk.getFullChunkIfCached(); ++ } ++ ++ @Nullable ++ public LevelChunk getChunkAtIfLoadedImmediately(int x, int z) { ++ long k = ChunkPos.asLong(x, z); ++ ++ if (Thread.currentThread() == this.mainThread) { ++ return this.getChunkAtIfLoadedMainThread(x, z); ++ } ++ ++ LevelChunk ret = null; ++ long readlock; ++ do { ++ readlock = this.loadedChunkMapSeqLock.acquireRead(); ++ try { ++ ret = this.loadedChunkMap.get(k); ++ } catch (Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ // re-try, this means a CME occurred... ++ continue; ++ } ++ } while (!this.loadedChunkMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ // Paper end ++ + @Nullable + @Override + public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) { +@@ -406,10 +602,9 @@ public class ServerChunkCache extends ChunkSource { + + this.lastSpawnState = spawnercreature_d; + this.level.getProfiler().pop(); +- List list = Lists.newArrayList(this.chunkMap.getChunks()); +- +- Collections.shuffle(list); +- list.forEach((playerchunk) -> { ++ //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper ++ //Collections.shuffle(list); // Paper ++ this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + + if (optional.isPresent()) { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 23506a8903ce64fbfe849bb94e589bdbb6e61a74..34ed8f0d348e7bc2339660ebc6490057ba9ef214 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -12,6 +12,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry; + import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.longs.LongSets; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; + import java.io.BufferedWriter; +@@ -163,7 +164,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + private final Map entitiesByUuid = Maps.newHashMap(); + private final Queue toAddAfterTick = Queues.newArrayDeque(); + private final List players = Lists.newArrayList(); +- private final ServerChunkCache chunkSource; ++ public final ServerChunkCache chunkSource; // Paper - public + boolean tickingEntities; + private final MinecraftServer server; + public final PrimaryLevelData worldDataServer; // CraftBukkit - type +@@ -1682,7 +1683,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + ObjectIterator objectiterator = spawnercreature_d.getMobCategoryCounts().object2IntEntrySet().iterator(); + + while (objectiterator.hasNext()) { +- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); ++ Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix + + bufferedwriter.write(String.format("spawn_count.%s: %d\n", ((MobCategory) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey()).getName(), it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue())); + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index d62c74318ac3bb139570fe2b5f12cdb6e900d70d..8d7fa186b0b47688f2822038b46c33b3f32d28ae 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -221,6 +221,8 @@ public class ServerPlayer extends Player implements ContainerListener { + public Integer clientViewDistance; + // CraftBukkit end + ++ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper ++ + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { + super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); + this.respawnDimension = Level.OVERWORLD; +@@ -233,6 +235,8 @@ public class ServerPlayer extends Player implements ContainerListener { + this.fudgeSpawnLocation(world); + this.textFilter = server.createTextFilterForPlayer(this); + ++ this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper ++ + // CraftBukkit start + this.displayName = this.getScoreboardName(); + this.canPickUpLoot = true; +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index 34dd10908101a6709e389bfa1d1c2a6599e8b102..cf3ced15c9a87e7a4dbccba17c57a7b32b77566c 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -25,6 +25,7 @@ public class TicketType { + public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); + public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit + public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit ++ public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper + + public static TicketType create(String name, Comparator comparator) { + return new TicketType<>(name, comparator, 0L); +diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java +index 0a9f76b7aef5c12879a408954384b4e70ac5b484..fdc56d602ef0bf3c50842f3081a3e6523b9765b0 100644 +--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java ++++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java +@@ -141,6 +141,26 @@ public class WorldGenRegion implements WorldGenLevel { + return chunkX >= this.firstPos.x && chunkX <= this.lastPos.x && chunkZ >= this.firstPos.z && chunkZ <= this.lastPos.z; + } + ++ // Paper start - if loaded util ++ @Nullable ++ @Override ++ public ChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ return this.getChunk(x, z, ChunkStatus.FULL, false); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getBlockState(blockposition); ++ } ++ ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getFluidState(blockposition); ++ } ++ // Paper end ++ + @Override + public BlockState getBlockState(BlockPos pos) { + return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4).getBlockState(pos); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 8766e79c1ed7a8557ef5fd91e8f3c65c3467efcd..35f3940cebb00ee29da54b1ee148ee931fa11636 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -218,9 +218,9 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private final MinecraftServer server; + public ServerPlayer player; + private int tickCount; +- private long keepAliveTime; +- private boolean keepAlivePending; +- private long keepAliveChallenge; ++ private long keepAliveTime; private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER ++ private boolean keepAlivePending; private void setPendingPing(boolean isPending) { this.keepAlivePending = isPending;}; private boolean isPendingPing() { return this.keepAlivePending;}; // Paper - OBFHELPER ++ private long keepAliveChallenge; private void setKeepAliveID(long keepAliveID) { this.keepAliveChallenge = keepAliveID;}; private long getKeepAliveID() {return this.keepAliveChallenge; }; // Paper - OBFHELPER + // CraftBukkit start - multithreaded fields + private volatile int chatSpamTickCount; + private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(ServerGamePacketListenerImpl.class, "chatThrottle"); +diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java +index 497e23e4ebf0d8b4e1a90ea3909608cdc066265f..97bde5f8402452e59b0da94edfe1b970cdb86748 100644 +--- a/src/main/java/net/minecraft/util/BitStorage.java ++++ b/src/main/java/net/minecraft/util/BitStorage.java +@@ -84,6 +84,7 @@ public class BitStorage { + return (int) (k >> l & this.mask); + } + ++ public final long[] getDataBits() { return this.getRaw(); } // Paper - OBFHELPER + public long[] getRaw() { + return this.data; + } +diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +index 03831adce7905916423d8c3834c42c90f3a1ca8f..e48fcfe2e4ff151258ae1d84cc0995d2cd54e9a6 100644 +--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java ++++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +@@ -68,6 +68,15 @@ public abstract class BlockableEventLoop implements Processo + + } + ++ // Paper start ++ public void scheduleOnMain(Runnable r0) { ++ // postToMainThread does not work the same as older versions of mc ++ // This method is actually used to create a TickTask, which can then be posted onto main ++ this.addTask(this.wrapRunnable(r0)); ++ } ++ // Paper end ++ ++ public final void addTask(R r0) { tell(r0); }; // Paper - OBFHELPER + public void tell(R r0) { + this.pendingRunnables.add(r0); + LockSupport.unpark(this.getRunningThread()); +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index ff482d0349c18d0d1ba902ea0d10611b1ca4e588..102298d57cf3143092d04ab1d5d0d69b28d696ea 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -3,6 +3,7 @@ package net.minecraft.world.entity; + import com.google.common.collect.ImmutableSet; + import java.util.Optional; + import java.util.Set; // Paper ++import java.util.Map; // Paper + import java.util.UUID; + import java.util.function.Function; + import java.util.stream.Stream; +@@ -441,8 +442,8 @@ public class EntityType { + return this.dimensions.height; + } + +- @Nullable +- public T create(Level world) { ++ public T create(Level world) { return this.create(world); } // Paper - OBFHELPER ++ @Nullable public T create(Level world) { // Paper - OBFHELPER + return this.factory.create(this, world); + } + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 3245c0d7310285dd423c5c1d44c26fb8c3d7bf7f..9e5dde73bd65bf4e51352c628fba024c36e29ef1 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -228,6 +228,7 @@ public abstract class LivingEntity extends Entity { + public boolean collides = true; + public Set collidableExemptions = new HashSet<>(); + public boolean canPickUpLoot; ++ public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper + + @Override + public float getBukkitYaw() { +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index f268b7e6f89068267ea2f07f7505e0dc69968b73..99cb4dc1a1009d4a29e651c94d21babcc61388ed 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -223,6 +223,7 @@ public abstract class Mob extends LivingEntity { + return this.target; + } + ++ public org.bukkit.craftbukkit.entity.CraftMob getBukkitMob() { return (org.bukkit.craftbukkit.entity.CraftMob) super.getBukkitEntity(); } // Paper + public void setTarget(@Nullable LivingEntity target) { + // CraftBukkit start - fire event + setGoalTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true); +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +index d090ffcf08e32a08d4b815b79ed58fc00bc26fd0..920ae9af8985705a0ada7da5b7085a1ed8ca7f27 100644 +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -12,6 +12,8 @@ import org.bukkit.event.entity.EntityUnleashEvent; + + public abstract class PathfinderMob extends Mob { + ++ public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper ++ + protected PathfinderMob(EntityType type, Level world) { + super(type, world); + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Monster.java b/src/main/java/net/minecraft/world/entity/monster/Monster.java +index fa886a89195312acfe53605169216ce95642ba87..407b7168b7e8d4408824039c06d02792d3c7e534 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Monster.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Monster.java +@@ -27,6 +27,7 @@ import net.minecraft.world.level.ServerLevelAccessor; + + public abstract class Monster extends PathfinderMob implements Enemy { + ++ public org.bukkit.craftbukkit.entity.CraftMonster getBukkitMonster() { return (org.bukkit.craftbukkit.entity.CraftMonster) super.getBukkitEntity(); } // Paper + protected Monster(EntityType type, Level world) { + super(type, world); + this.xpReward = 5; +diff --git a/src/main/java/net/minecraft/world/entity/player/Inventory.java b/src/main/java/net/minecraft/world/entity/player/Inventory.java +index c0e0a8deabf3dffcc974f9e5bea2332d0d6e57a5..7d06838c4c8eef7ebff64ae094cd12404b9edd53 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Inventory.java ++++ b/src/main/java/net/minecraft/world/entity/player/Inventory.java +@@ -37,7 +37,7 @@ public class Inventory implements Container, Nameable { + public final NonNullList items; + public final NonNullList armor; + public final NonNullList offhand; +- private final List> compartments; ++ private final List> compartments; public final List> getComponents() { return compartments; } // Paper - OBFHELPER + public int selected; + public final Player player; + private ItemStack carried; +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index da0fabafad0aa6c124abf52f8da68c73b7264fe9..2a6a6e291efbd7cc8fed6532f18321bd141e1306 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -101,7 +101,7 @@ public final class ItemStack { + })).apply(instance, ItemStack::new); + }); + private static final Logger LOGGER = LogManager.getLogger(); +- public static final ItemStack EMPTY = new ItemStack((Item) null); ++ public static final ItemStack EMPTY = new ItemStack((Item) null);public static final ItemStack NULL_ITEM = EMPTY; // Paper - OBFHELPER + public static final DecimalFormat ATTRIBUTE_MODIFIER_FORMAT = (DecimalFormat) Util.make((new DecimalFormat("#.##")), (decimalformat) -> { // CraftBukkit - decompile error + decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); + }); +@@ -658,6 +658,24 @@ public final class ItemStack { + return this.tag != null ? this.tag.getList("Enchantments", 10) : new ListTag(); + } + ++ // Paper start - (this is just a good no conflict location) ++ public org.bukkit.inventory.ItemStack asBukkitMirror() { ++ return CraftItemStack.asCraftMirror(this); ++ } ++ public org.bukkit.inventory.ItemStack asBukkitCopy() { ++ return CraftItemStack.asCraftMirror(this.copy()); ++ } ++ public static ItemStack fromBukkitCopy(org.bukkit.inventory.ItemStack itemstack) { ++ return CraftItemStack.asNMSCopy(itemstack); ++ } ++ private org.bukkit.craftbukkit.inventory.CraftItemStack bukkitStack; ++ public org.bukkit.inventory.ItemStack getBukkitStack() { ++ if (bukkitStack == null || bukkitStack.getHandle() != this) { ++ bukkitStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this); ++ } ++ return bukkitStack; ++ } ++ // Paper end + public void setTag(@Nullable CompoundTag tag) { + this.tag = tag; + if (this.getItem().canBeDepleted()) { +@@ -756,6 +774,7 @@ public final class ItemStack { + return this.tag != null && this.tag.contains("Enchantments", 9) ? !this.tag.getList("Enchantments", 10).isEmpty() : false; + } + ++ public void getOrCreateTagAndSet(String s, Tag nbtbase) { addTagElement(s, nbtbase);} // Paper - OBFHELPER + public void addTagElement(String key, Tag tag) { + this.getOrCreateTag().put(key, tag); + } +@@ -841,6 +860,7 @@ public final class ItemStack { + // CraftBukkit start + @Deprecated + public void setItem(Item item) { ++ this.bukkitStack = null; // Paper + this.item = item; + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java b/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java +index e38c38c7d7679f267283a5ac6245e2261829aa05..2285a0cf6a35d06de77f94ad8a14ae91c1a7929f 100644 +--- a/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java ++++ b/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java +@@ -121,6 +121,7 @@ public class PotionUtils { + return compound == null ? Potions.EMPTY : Potion.byName(compound.getString("Potion")); + } + ++ public static ItemStack addPotionToItemStack(ItemStack itemstack, Potion potionregistry) { return setPotion(itemstack, potionregistry); } // Paper - OBFHELPER + public static ItemStack setPotion(ItemStack stack, Potion potion) { + ResourceLocation minecraftkey = Registry.POTION.getKey(potion); + +diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java +index 3bbee667743d9a249c1513ea426e7a51d9185c4c..2feb187f62be5cf5d354a1e806087417cc189ab1 100644 +--- a/src/main/java/net/minecraft/world/level/BlockGetter.java ++++ b/src/main/java/net/minecraft/world/level/BlockGetter.java +@@ -8,9 +8,11 @@ import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.util.Mth; ++import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.material.FluidState; ++import net.minecraft.world.level.material.Material; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; +@@ -22,6 +24,19 @@ public interface BlockGetter { + BlockEntity getBlockEntity(BlockPos pos); + + BlockState getBlockState(BlockPos pos); ++ // Paper start - if loaded util ++ BlockState getTypeIfLoaded(BlockPos blockposition); ++ default Material getMaterialIfLoaded(BlockPos blockposition) { ++ BlockState type = this.getTypeIfLoaded(blockposition); ++ return type == null ? null : type.getMaterial(); ++ } ++ ++ default Block getBlockIfLoaded(BlockPos blockposition) { ++ BlockState type = this.getTypeIfLoaded(blockposition); ++ return type == null ? null : type.getBlock(); ++ } ++ FluidState getFluidIfLoaded(BlockPos blockposition); ++ // Paper end + + FluidState getFluidState(BlockPos pos); + +diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java +index 0caf067f9d888f9769db1503284d444e97c60c9c..7ccf830146c252cff8e22553d293e02d4b53dad8 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkPos.java ++++ b/src/main/java/net/minecraft/world/level/ChunkPos.java +@@ -12,27 +12,32 @@ public class ChunkPos { + public static final long INVALID_CHUNK_POS = asLong(1875016, 1875016); + public final int x; + public final int z; ++ public final long longKey; // Paper + + public ChunkPos(int x, int z) { + this.x = x; + this.z = z; ++ this.longKey = asLong(this.x, this.z); // Paper + } + + public ChunkPos(BlockPos pos) { + this.x = pos.getX() >> 4; + this.z = pos.getZ() >> 4; ++ this.longKey = asLong(this.x, this.z); // Paper + } + + public ChunkPos(long pos) { + this.x = (int) pos; + this.z = (int) (pos >> 32); ++ this.longKey = asLong(this.x, this.z); // Paper + } + + public long toLong() { +- return asLong(this.x, this.z); ++ return longKey; // Paper + } + +- public static long asLong(int chunkX, int chunkZ) { ++ public static long pair(final BlockPos pos) { return asLong(pos.getX() >> 4, pos.getZ() >> 4); } // Paper - OBFHELPER ++ public static long asLong(int chunkX, int chunkZ) { + return (long) chunkX & 4294967295L | ((long) chunkZ & 4294967295L) << 32; + } + +diff --git a/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java b/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java +index 82c14e1ac66792137ab9e647c868a698c1ec9929..2b4f9849d668dede4d1f7d10f3a6ec9ef7a6d828 100644 +--- a/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java ++++ b/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java +@@ -20,6 +20,18 @@ public enum EmptyBlockGetter implements BlockGetter { + return null; + } + ++ // Paper start - If loaded util ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ return this.getFluidState(blockposition); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ return this.getBlockState(blockposition); ++ } ++ // Paper end ++ + @Override + public BlockState getBlockState(BlockPos pos) { + return Blocks.AIR.defaultBlockState(); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index f08de81dcc4acd5a3e44407b431ce827a19b2e9c..5cc4c2668df72f83fb1526f4586b71d2ae0103dc 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -74,6 +74,7 @@ import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.block.CapturedBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockState; + import org.bukkit.craftbukkit.block.data.CraftBlockData; + import org.bukkit.event.block.BlockPhysicsEvent; + // CraftBukkit end +@@ -255,17 +256,50 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return y < 0 || y >= 256; + } + +- public LevelChunk getChunkAt(BlockPos pos) { ++ public final LevelChunk getChunkAt(BlockPos pos) { // Paper - help inline + return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); + } + + @Override +- public LevelChunk getChunk(int chunkX, int chunkZ) { +- return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL); ++ public final LevelChunk getChunk(int chunkX, int chunkZ) { // Paper - final to help inline ++ return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true); // Paper - avoid a method jump ++ } ++ ++ // Paper start - if loaded ++ @Nullable ++ @Override ++ public final ChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ return ((ServerLevel)this).chunkSource.getChunkAtIfLoadedImmediately(x, z); + } + + @Override +- public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { ++ public final BlockState getTypeIfLoaded(BlockPos blockposition) { ++ // CraftBukkit start - tree generation ++ if (captureTreeGeneration) { ++ CraftBlockState previous = capturedBlockStates.get(blockposition); ++ if (previous != null) { ++ return previous.getHandle(); ++ } ++ } ++ // CraftBukkit end ++ if (!isInWorldBounds(blockposition)) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ ++ return chunk == null ? null : chunk.getBlockState(blockposition); ++ } ++ ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ ++ return chunk == null ? null : chunk.getFluidState(blockposition); ++ } ++ // Paper end ++ ++ @Override ++ public final ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { // Paper - final for inline + ChunkAccess ichunkaccess = this.getChunkSource().getChunk(chunkX, chunkZ, leastStatus, create); + + if (ichunkaccess == null && create) { +@@ -276,7 +310,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + + @Override +- public boolean setBlock(BlockPos pos, BlockState state, int flags) { ++ public final boolean setBlock(BlockPos pos, BlockState state, int flags) { // Paper - final for inline + return this.setBlock(pos, state, flags, 512); + } + +@@ -422,8 +456,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + public void onBlockStateChange(BlockPos pos, BlockState oldBlock, BlockState newBlock) {} + +- @Override +- public boolean removeBlock(BlockPos pos, boolean move) { ++ public boolean setAir(BlockPos blockposition) { return this.removeBlock(blockposition, false); } // Paper - OBFHELPER ++ public boolean setAir(BlockPos blockposition, boolean moved) { return this.removeBlock(blockposition, moved); } // Paper - OBFHELPER ++ @Override public boolean removeBlock(BlockPos pos, boolean move) { // Paper - OBFHELPER + FluidState fluid = this.getFluidState(pos); + + return this.setBlock(pos, fluid.createLegacyBlock(), 3 | (move ? 64 : 0)); +@@ -569,7 +604,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + if (isOutsideBuildHeight(pos)) { + return Blocks.VOID_AIR.defaultBlockState(); + } else { +- LevelChunk chunk = this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); ++ LevelChunk chunk = (LevelChunk) this.getChunkSource().getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, true); // Paper - manually inline to reduce hops and avoid unnecessary null check to reduce total byte code size, this should never return null and if it does we will see it the next line but the real stack trace will matter in the chunk engine + + return chunk.getBlockState(pos); + } +diff --git a/src/main/java/net/minecraft/world/level/LevelReader.java b/src/main/java/net/minecraft/world/level/LevelReader.java +index b6877b78bf6ecf2069e59028f8910826c8b4eafe..6e4a53291ee87fac6d81d4ab9746906b6ae1b453 100644 +--- a/src/main/java/net/minecraft/world/level/LevelReader.java ++++ b/src/main/java/net/minecraft/world/level/LevelReader.java +@@ -18,6 +18,7 @@ import net.minecraft.world.phys.AABB; + + public interface LevelReader extends BlockAndTintGetter, CollisionGetter, BiomeManager.NoiseBiomeSource { + ++ @Nullable ChunkAccess getChunkIfLoadedImmediately(int x, int z); // Paper - ifLoaded api (we need this since current impl blocks if the chunk is loading) + @Nullable + ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create); + +diff --git a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java b/src/main/java/net/minecraft/world/level/PathNavigationRegion.java +index f1d759d87291f469bde3b433031a6e7c6a19fbf2..6db3f4efa6ea4a09aad7684a3b7cc7479fad2f5c 100644 +--- a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java ++++ b/src/main/java/net/minecraft/world/level/PathNavigationRegion.java +@@ -4,6 +4,7 @@ import java.util.function.Predicate; + import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntity; +@@ -23,7 +24,7 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { + protected final int centerZ; + protected final ChunkAccess[][] chunks; + protected boolean allEmpty; +- protected final Level level; ++ protected final Level level; protected final Level getWorld() { return level; } // Paper - OBFHELPER + + public PathNavigationRegion(Level world, BlockPos minPos, BlockPos maxPos) { + this.level = world; +@@ -42,7 +43,7 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { + + for (k = this.centerX; k <= i; ++k) { + for (l = this.centerZ; l <= j; ++l) { +- this.chunks[k - this.centerX][l - this.centerZ] = ichunkprovider.getChunkNow(k, l); ++ this.chunks[k - this.centerX][l - this.centerZ] = ((ServerLevel)world).getChunkSource().getChunkAtIfLoadedMainThreadNoCache(k, l); // Paper + } + } + +@@ -67,7 +68,7 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { + int k = i - this.centerX; + int l = j - this.centerZ; + +- if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { ++ if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { // Paper - if this changes, update getChunkIfLoaded below + ChunkAccess ichunkaccess = this.chunks[k][l]; + + return (ChunkAccess) (ichunkaccess != null ? ichunkaccess : new EmptyLevelChunk(this.level, new ChunkPos(i, j))); +@@ -86,6 +87,29 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { + return this.getChunk(chunkX, chunkZ); + } + ++ // Paper start - if loaded util ++ private ChunkAccess getChunkIfLoaded(int x, int z) { ++ int k = x - this.centerX; ++ int l = z - this.centerZ; ++ ++ if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { ++ return this.chunks[k][l]; ++ } ++ return null; ++ } ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getFluidState(blockposition); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getBlockState(blockposition); ++ } ++ // Paper end ++ + @Nullable + @Override + public BlockEntity getBlockEntity(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index c9713d1ab6498c09790503f673b31b5ef30ce4f3..e6928557a79f51302975f2832ec911c2692eaaeb 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -687,6 +687,7 @@ public abstract class BlockBehaviour { + return this.cache != null ? this.cache.isCollisionShapeFullBlock : Block.isShapeFullBlock(this.getCollisionShape(world, pos)); + } + ++ public final BlockState getBlockData() { return asState(); } // Paper - OBFHELPER + protected abstract BlockState asState(); + + public boolean requiresCorrectToolForDrops() { +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index fe1c10e5eeb434cd24e94b3247abbf5f73fce9cc..31f17956b3b031d1a47bda4d282554c8a7853097 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -47,6 +47,7 @@ public class WorldBorder { + return this.getDistanceToBorder(entity.getX(), entity.getZ()); + } + ++ public final VoxelShape asVoxelShape(){ return getCollisionShape();} // Paper - OBFHELPER + public VoxelShape getCollisionShape() { + return this.extent.getCollisionShape(); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 5a91d74f0acf393dbf098719b0924a4c00cf7128..e2c5a17aa72d1a5412d76881187d4d9ad1763297 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -59,7 +59,7 @@ public class LevelChunk implements ChunkAccess { + + private static final Logger LOGGER = LogManager.getLogger(); + @Nullable +- public static final LevelChunkSection EMPTY_SECTION = null; ++ public static final LevelChunkSection EMPTY_SECTION = null; public static final LevelChunkSection EMPTY_CHUNK_SECTION = EMPTY_SECTION; // Paper - OBFHELPER + private final LevelChunkSection[] sections; + private ChunkBiomeContainer biomes; + private final Map pendingBlockEntities; +@@ -82,7 +82,7 @@ public class LevelChunk implements ChunkAccess { + private Supplier fullStatus; + @Nullable + private Consumer postLoad; +- private final ChunkPos chunkPos; ++ private final ChunkPos chunkPos; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key + private volatile boolean isLightCorrect; + + public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes) { +@@ -99,7 +99,8 @@ public class LevelChunk implements ChunkAccess { + this.postProcessing = new ShortList[16]; + this.entitySlices = (List[]) (new List[16]); // Spigot + this.world = (ServerLevel) world; // CraftBukkit - type +- this.chunkPos = pos; ++ this.locX = pos.x; this.locZ = pos.z; // Paper - reduce need for field look ups ++ this.chunkPos = pos; this.coordinateKey = ChunkPos.asLong(locX, locZ); // Paper - cache long key + this.upgradeData = upgradeData; + Heightmap.Types[] aheightmap_type = Heightmap.Types.values(); + int j = aheightmap_type.length; +@@ -145,6 +146,110 @@ public class LevelChunk implements ChunkAccess { + public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY); + // CraftBukkit end + ++ // Paper start ++ public final com.destroystokyo.paper.util.maplist.EntityList entities = new com.destroystokyo.paper.util.maplist.EntityList(); ++ public ChunkHolder playerChunk; ++ ++ static final int NEIGHBOUR_CACHE_RADIUS = 3; ++ public static int getNeighbourCacheRadius() { ++ return NEIGHBOUR_CACHE_RADIUS; ++ } ++ ++ boolean loadedTicketLevel; ++ private long neighbourChunksLoadedBitset; ++ private final LevelChunk[] loadedNeighbourChunks = new LevelChunk[(NEIGHBOUR_CACHE_RADIUS * 2 + 1) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)]; ++ ++ private static int getNeighbourIndex(final int relativeX, final int relativeZ) { ++ // index = (relativeX + NEIGHBOUR_CACHE_RADIUS) + (relativeZ + NEIGHBOUR_CACHE_RADIUS) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1) ++ // optimised variant of the above by moving some of the ops to compile time ++ return relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))); ++ } ++ ++ public final LevelChunk getRelativeNeighbourIfLoaded(final int relativeX, final int relativeZ) { ++ return this.loadedNeighbourChunks[getNeighbourIndex(relativeX, relativeZ)]; ++ } ++ ++ public final boolean isNeighbourLoaded(final int relativeX, final int relativeZ) { ++ return (this.neighbourChunksLoadedBitset & (1L << getNeighbourIndex(relativeX, relativeZ))) != 0; ++ } ++ ++ public final void setNeighbourLoaded(final int relativeX, final int relativeZ, final LevelChunk chunk) { ++ if (chunk == null) { ++ throw new IllegalArgumentException("Chunk must be non-null, neighbour: (" + relativeX + "," + relativeZ + "), chunk: " + this.chunkPos); ++ } ++ final long before = this.neighbourChunksLoadedBitset; ++ final int index = getNeighbourIndex(relativeX, relativeZ); ++ this.loadedNeighbourChunks[index] = chunk; ++ this.neighbourChunksLoadedBitset |= (1L << index); ++ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); ++ } ++ ++ public final void setNeighbourUnloaded(final int relativeX, final int relativeZ) { ++ final long before = this.neighbourChunksLoadedBitset; ++ final int index = getNeighbourIndex(relativeX, relativeZ); ++ this.loadedNeighbourChunks[index] = null; ++ this.neighbourChunksLoadedBitset &= ~(1L << index); ++ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); ++ } ++ ++ public final void resetNeighbours() { ++ final long before = this.neighbourChunksLoadedBitset; ++ this.neighbourChunksLoadedBitset = 0L; ++ java.util.Arrays.fill(this.loadedNeighbourChunks, null); ++ this.onNeighbourChange(before, 0L); ++ } ++ ++ protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { ++ ++ } ++ ++ public final boolean isAnyNeighborsLoaded() { ++ return neighbourChunksLoadedBitset != 0; ++ } ++ public final boolean areNeighboursLoaded(final int radius) { ++ return LevelChunk.areNeighboursLoaded(this.neighbourChunksLoadedBitset, radius); ++ } ++ ++ public static boolean areNeighboursLoaded(final long bitset, final int radius) { ++ // index = relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))) ++ switch (radius) { ++ case 0: { ++ return (bitset & (1L << getNeighbourIndex(0, 0))) != 0; ++ } ++ case 1: { ++ long mask = 0L; ++ for (int dx = -1; dx <= 1; ++dx) { ++ for (int dz = -1; dz <= 1; ++dz) { ++ mask |= (1L << getNeighbourIndex(dx, dz)); ++ } ++ } ++ return (bitset & mask) == mask; ++ } ++ case 2: { ++ long mask = 0L; ++ for (int dx = -2; dx <= 2; ++dx) { ++ for (int dz = -2; dz <= 2; ++dz) { ++ mask |= (1L << getNeighbourIndex(dx, dz)); ++ } ++ } ++ return (bitset & mask) == mask; ++ } ++ case 3: { ++ long mask = 0L; ++ for (int dx = -3; dx <= 3; ++dx) { ++ for (int dz = -3; dz <= 3; ++dz) { ++ mask |= (1L << getNeighbourIndex(dx, dz)); ++ } ++ } ++ return (bitset & mask) == mask; ++ } ++ ++ default: ++ throw new IllegalArgumentException("Radius not recognized: " + radius); ++ } ++ } ++ // Paper end ++ + public LevelChunk(Level world, ProtoChunk protoChunk) { + this(world, protoChunk.getPos(), protoChunk.getBiomes(), protoChunk.getUpgradeData(), protoChunk.getBlockTicks(), protoChunk.getLiquidTicks(), protoChunk.getInhabitedTime(), protoChunk.getSections(), (Consumer) null); + Iterator iterator = protoChunk.getEntities().iterator(); +@@ -250,6 +355,18 @@ public class LevelChunk implements ChunkAccess { + } + } + ++ // Paper start - If loaded util ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ return this.getFluidState(blockposition); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ return this.getBlockState(blockposition); ++ } ++ // Paper end ++ + @Override + public FluidState getFluidState(BlockPos pos) { + return this.getFluidState(pos.getX(), pos.getY(), pos.getZ()); +@@ -390,6 +507,7 @@ public class LevelChunk implements ChunkAccess { + entity.xChunk = this.chunkPos.x; + entity.yChunk = k; + entity.zChunk = this.chunkPos.z; ++ this.entities.add(entity); // Paper - per chunk entity list + this.entitySlices[k].add(entity); + } + +@@ -413,6 +531,7 @@ public class LevelChunk implements ChunkAccess { + } + + this.entitySlices[section].remove(entity); ++ this.entities.remove(entity); // Paper + } + + @Override +@@ -434,6 +553,7 @@ public class LevelChunk implements ChunkAccess { + return this.getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); + } + ++ @Nullable public final BlockEntity getTileEntityImmediately(BlockPos pos) { return this.getBlockEntity(pos, EntityCreationType.IMMEDIATE); } // Paper - OBFHELPER + @Nullable + public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType) { + // CraftBukkit start +@@ -545,7 +665,25 @@ public class LevelChunk implements ChunkAccess { + + // CraftBukkit start + public void loadCallback() { ++ // Paper start - neighbour cache ++ int chunkX = this.chunkPos.x; ++ int chunkZ = this.chunkPos.z; ++ ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); ++ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { ++ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { ++ LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); ++ if (neighbour != null) { ++ neighbour.setNeighbourLoaded(-dx, -dz, this); ++ // should be in cached already ++ this.setNeighbourLoaded(dx, dz, neighbour); ++ } ++ } ++ } ++ this.setNeighbourLoaded(0, 0, this); ++ this.loadedTicketLevel = true; ++ // Paper end - neighbour cache + org.bukkit.Server server = this.world.getCraftServer(); ++ ((ServerLevel)this.world).getChunkSource().addLoadedChunk(this); // Paper + if (server != null) { + /* + * If it's a new world, the first few chunks are generated inside +@@ -584,6 +722,22 @@ public class LevelChunk implements ChunkAccess { + server.getPluginManager().callEvent(unloadEvent); + // note: saving can be prevented, but not forced if no saving is actually required + this.mustNotSave = !unloadEvent.isSaveChunk(); ++ ((ServerLevel)this.world).getChunkSource().removeLoadedChunk(this); // Paper ++ // Paper start - neighbour cache ++ int chunkX = this.chunkPos.x; ++ int chunkZ = this.chunkPos.z; ++ ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); ++ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { ++ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { ++ LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); ++ if (neighbour != null) { ++ neighbour.setNeighbourUnloaded(-dx, -dz); ++ } ++ } ++ } ++ this.loadedTicketLevel = false; ++ this.resetNeighbours(); ++ // Paper end + } + // CraftBukkit end + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index 8a4fca9f4882e65b831dd3f82f242e1113859fe0..b54d82e0f41a03c91e0de8df8249a91da3c04d0e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -139,6 +139,7 @@ public class LevelChunkSection { + return this.states; + } + ++ public void writeChunkSection(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER + public void write(FriendlyByteBuf packetdataserializer) { + packetdataserializer.writeShort(this.nonEmptyBlockCount); + this.states.write(packetdataserializer); +diff --git a/src/main/java/net/minecraft/world/level/chunk/Palette.java b/src/main/java/net/minecraft/world/level/chunk/Palette.java +index dcc030f4801b4c6e1fe5b8c2718ddfd7ba6bb248..78c56e1e2af50e923fb0b07c6ddd860c4aa77195 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Palette.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Palette.java +@@ -7,10 +7,12 @@ import net.minecraft.network.FriendlyByteBuf; + + public interface Palette { + ++ default int getOrCreateIdFor(T object) { return this.idFor(object); } // Paper - OBFHELPER + int idFor(T object); + + boolean maybeHas(Predicate predicate); + ++ @Nullable default T getObject(int dataBits) { return this.valueFor(dataBits); } // Paper - OBFHELPER + @Nullable + T valueFor(int index); + +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index f14f89f8916c832feaa3887bd28a5cf6b2f6ff1d..d4db27421736f665739436c1ac4d3c6d5cae95cd 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -19,7 +19,7 @@ import net.minecraft.util.Mth; + + public class PalettedContainer implements PaletteResize { + +- private final Palette globalPalette; ++ private final Palette globalPalette; private final Palette getDataPaletteGlobal() { return this.globalPalette; } // Paper - OBFHELPER + private final PaletteResize dummyPaletteResize = (i, object) -> { + return 0; + }; +@@ -27,9 +27,9 @@ public class PalettedContainer implements PaletteResize { + private final Function reader; + private final Function writer; + private final T defaultValue; +- protected BitStorage storage; +- private Palette palette; +- private int bits; ++ protected BitStorage storage; public final BitStorage getDataBits() { return this.storage; } // Paper - OBFHELPER ++ private Palette palette; private Palette getDataPalette() { return this.palette; } // Paper - OBFHELPER ++ private int bits; private int getBitsPerObject() { return this.bits; } // Paper - OBFHELPER + private final ReentrantLock lock = new ReentrantLock(); + + public void acquire() { +@@ -64,6 +64,7 @@ public class PalettedContainer implements PaletteResize { + return y << 8 | z << 4 | x; + } + ++ private void initialize(int bitsPerObject) { this.setBits(bitsPerObject); } // Paper - OBFHELPER + private void setBits(int size) { + if (size != this.bits) { + this.bits = size; +@@ -141,6 +142,7 @@ public class PalettedContainer implements PaletteResize { + return t0 == null ? this.defaultValue : t0; + } + ++ public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER + public void write(FriendlyByteBuf buf) { + this.acquire(); + buf.writeByte(this.bits); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index cecf8a68f215d85e84fba157930f6987ffd21e50..7cd3f89004b0a64772fc3dfbdd132ba5a850b63e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -99,6 +99,18 @@ public class ProtoChunk implements ChunkAccess { + + } + ++ // Paper start - If loaded util ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ return this.getFluidState(blockposition); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ return this.getBlockState(blockposition); ++ } ++ // Paper end ++ + @Override + public BlockState getBlockState(BlockPos pos) { + int i = pos.getY(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +index 7de765786b3504dcffab98bb0d9dac64b30b3325..5bd34b136f2892f541ba686debca19e0a4eef0be 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +@@ -27,7 +27,7 @@ public class IOWorker implements AutoCloseable { + private static final Logger LOGGER = LogManager.getLogger(); + private final AtomicBoolean shutdownRequested = new AtomicBoolean(); + private final ProcessorMailbox mailbox; +- private final RegionFileStorage storage; ++ private final RegionFileStorage storage;public RegionFileStorage getRegionFileCache() { return storage; } // Paper - OBFHELPER + private final Map pendingWrites = Maps.newLinkedHashMap(); + + protected IOWorker(File file, boolean flag, String s) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index aa3d6db08e4d744cc94de71d0f8dceb99948e2ab..60f410a4f838048bbfd2cde52caa7c4c9434b0ba 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -112,6 +112,7 @@ public class RegionFile implements AutoCloseable { + return this.externalFileDir.resolve(s); + } + ++ @Nullable public synchronized DataInputStream getReadStream(ChunkPos chunkCoordIntPair) throws IOException { return getChunkDataInputStream(chunkCoordIntPair);} // Paper - OBFHELPER + @Nullable + public synchronized DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException { + int i = this.getOffset(pos); +diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java +index 022fafff8b476f8bc1830bf5494760b0fef65297..983d0495ec35128ca3ef68566ada065bc4b21efc 100644 +--- a/src/main/java/net/minecraft/world/phys/AABB.java ++++ b/src/main/java/net/minecraft/world/phys/AABB.java +@@ -194,10 +194,12 @@ public class AABB { + return this.move(vec3d.x, vec3d.y, vec3d.z); + } + ++ public final boolean intersects(AABB axisalignedbb) { return this.intersects(axisalignedbb); } // Paper - OBFHELPER + public boolean intersects(AABB box) { + return this.intersects(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ); + } + ++ public final boolean intersects(double d0, double d1, double d2, double d3, double d4, double d5) { return intersects(d0, d1, d2, d3, d4, d5); } // Paper - OBFHELPER + public boolean intersects(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { + return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ; + } +@@ -210,6 +212,7 @@ public class AABB { + return x >= this.minX && x < this.maxX && y >= this.minY && y < this.maxY && z >= this.minZ && z < this.maxZ; + } + ++ public final double getAverageSideLength(){return getSize();} // Paper - OBFHELPER + public double getSize() { + double d0 = this.getXsize(); + double d1 = this.getYsize(); +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index eb07309be171ccadcae21f4096c44d2b700d22b3..2371b52b450e2b43fa9b9549a91f853c702a9dc0 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -31,10 +31,12 @@ public final class Shapes { + public static final VoxelShape INFINITY = box(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); + private static final VoxelShape EMPTY = new ArrayVoxelShape(new BitSetDiscreteVoxelShape(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); + ++ public static final VoxelShape empty() {return empty();} // Paper - OBFHELPER + public static VoxelShape empty() { + return Shapes.EMPTY; + } + ++ public static final VoxelShape fullCube() {return block();} // Paper - OBFHELPER + public static VoxelShape block() { + return Shapes.BLOCK; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index c34f63eaf3deca4623ca4dfbee863771014847ba..01df5263d77771a296ca091a0feec620e6e37229 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -85,6 +85,7 @@ public final class CraftItemStack extends ItemStack { + } + + net.minecraft.world.item.ItemStack handle; ++ public net.minecraft.world.item.ItemStack getHandle() { return handle; } // Paper + + /** + * Mirror +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 9ad17c560c8d99a396543ab9f97c34de648f6544..4bf48f77f3f7cd62a91590543f5af441c8268029 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -43,6 +43,7 @@ import org.bukkit.scheduler.BukkitWorker; + */ + public class CraftScheduler implements BukkitScheduler { + ++ static Plugin MINECRAFT = new MinecraftInternalPlugin(); + /** + * Counter for IDs. Order doesn't matter, only uniqueness. + */ +@@ -177,6 +178,11 @@ public class CraftScheduler implements BukkitScheduler { + runTaskTimer(plugin, (Object) task, delay, period); + } + ++ public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { ++ final CraftTask task = new CraftTask(run, nextId(), taskName); ++ return handle(task, delay); ++ } ++ + public BukkitTask runTaskTimer(Plugin plugin, Object runnable, long delay, long period) { + validate(plugin, runnable); + if (delay < 0L) { +@@ -400,13 +406,20 @@ public class CraftScheduler implements BukkitScheduler { + task.run(); + task.timings.stopTiming(); // Spigot + } catch (final Throwable throwable) { +- task.getOwner().getLogger().log( ++ // Paper start ++ String msg = String.format( ++ "Task #%s for %s generated an exception", ++ task.getTaskId(), ++ task.getOwner().getDescription().getFullName()); ++ if (task.getOwner() == MINECRAFT) { ++ net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable); ++ } else { ++ task.getOwner().getLogger().log( + Level.WARNING, +- String.format( +- "Task #%s for %s generated an exception", +- task.getTaskId(), +- task.getOwner().getDescription().getFullName()), ++ msg, + throwable); ++ } ++ // Paper end + } finally { + currentTask = null; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +index 3c7066192ea4c05c101404bb56cbc839771f4200..09aa6809c5400ce8548ac902908b750ce7c964ec 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +@@ -39,6 +39,21 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + CraftTask(final Object task) { + this(null, task, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); + } ++ // Paper start ++ public String taskName = null; ++ boolean internal = false; ++ CraftTask(final Object task, int id, String taskName) { ++ this.rTask = (Runnable) task; ++ this.cTask = null; ++ this.plugin = CraftScheduler.MINECRAFT; ++ this.taskName = taskName; ++ this.internal = true; ++ this.id = id; ++ this.period = CraftTask.NO_REPEATING; ++ this.taskName = taskName; ++ this.timings = null; // Will be changed in later patch ++ } ++ // Paper end + + CraftTask(final Plugin plugin, final Object task, final int id, final long period) { + this.plugin = plugin; +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java +new file mode 100644 +index 0000000000000000000000000000000000000000..49dc0c441b9dd7e7745cf15ced67f383ebee1f99 +--- /dev/null ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java +@@ -0,0 +1,132 @@ ++package org.bukkit.craftbukkit.scheduler; ++ ++ ++import org.bukkit.Server; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.bukkit.configuration.file.FileConfiguration; ++import org.bukkit.generator.ChunkGenerator; ++import org.bukkit.plugin.PluginBase; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.bukkit.plugin.PluginLoader; ++import org.bukkit.plugin.PluginLogger; ++ ++import java.io.File; ++import java.io.InputStream; ++import java.util.List; ++ ++public class MinecraftInternalPlugin extends PluginBase { ++ private boolean enabled = true; ++ ++ private final String pluginName; ++ private PluginDescriptionFile pdf; ++ ++ public MinecraftInternalPlugin() { ++ this.pluginName = "Minecraft"; ++ pdf = new PluginDescriptionFile(pluginName, "1.0", "nms"); ++ } ++ ++ public void setEnabled(boolean enabled) { ++ this.enabled = enabled; ++ } ++ ++ @Override ++ public File getDataFolder() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginDescriptionFile getDescription() { ++ return pdf; ++ } ++ ++ @Override ++ public FileConfiguration getConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public InputStream getResource(String filename) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void saveConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void saveDefaultConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void saveResource(String resourcePath, boolean replace) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void reloadConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginLogger getLogger() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginLoader getPluginLoader() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public Server getServer() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public boolean isEnabled() { ++ return enabled; ++ } ++ ++ @Override ++ public void onDisable() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void onLoad() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void onEnable() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public boolean isNaggable() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void setNaggable(boolean canNag) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java +index 33cd17c415ae19bc9028934257b396907995cb9a..40a2ad3e180cc50a755f44a8ff6d8261734bf733 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java +@@ -168,7 +168,23 @@ public class DummyGeneratorAccess implements LevelAccessor { + public FluidState getFluidState(BlockPos pos) { + throw new UnsupportedOperationException("Not supported yet."); + } ++ // Paper start - if loaded util ++ @javax.annotation.Nullable ++ @Override ++ public ChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } + ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // Paper end + @Override + public WorldBorder getWorldBorder() { + throw new UnsupportedOperationException("Not supported yet."); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java +index 1aec70a1f1a9d8fd2cd06bde4033e19e769ab331..f72c13bedaa6fa45e26f5dcad564835bdd4af61f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java +@@ -17,7 +17,7 @@ import java.util.RandomAccess; + public class UnsafeList extends AbstractList implements List, RandomAccess, Cloneable, Serializable { + private static final long serialVersionUID = 8683452581112892191L; + +- private transient Object[] data; ++ private transient Object[] data; public final Object[] getRawDataArray() { return this.data; } // Paper - expose for raw get + private int size; + private int initialCapacity; + +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 8d6f4d76d6f04a322a98faecaca6b1b69c5f49d6..dc11dab14624ca25e78bf0b919ecf461e0be430d 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -118,7 +118,11 @@ public class SpigotConfig + } + } + } +- ++ // Paper start ++ SpigotConfig.save(); ++ } ++ public static void save() { ++ // Paper end + try + { + config.save( CONFIG_FILE ); diff --git a/Remapped-Spigot-Server-Patches/0005-Paper-Metrics.patch b/Remapped-Spigot-Server-Patches/0005-Paper-Metrics.patch new file mode 100644 index 0000000000..82a9c9a2d4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0005-Paper-Metrics.patch @@ -0,0 +1,735 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 24 Mar 2017 23:56:01 -0500 +Subject: [PATCH] Paper Metrics + +Removes Spigot's mcstats metrics in favor of a system using bStats + +To disable for privacy or other reasons go to the bStats folder in your plugins folder +and edit the config.yml file present there. + +Please keep in mind the data collected is anonymous and collection should have no +tangible effect on server performance. The data is used to allow the authors of +PaperMC to track version and platform usage so that we can make better management +decisions on behalf of the project. + +diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0b9e689d57705965721b5c55bc45d36657f360e4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/Metrics.java +@@ -0,0 +1,670 @@ ++package com.destroystokyo.paper; ++ ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++import org.bukkit.configuration.file.YamlConfiguration; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.plugin.Plugin; ++ ++import org.json.simple.JSONArray; ++import org.json.simple.JSONObject; ++ ++import javax.net.ssl.HttpsURLConnection; ++import java.io.ByteArrayOutputStream; ++import java.io.DataOutputStream; ++import java.io.File; ++import java.io.IOException; ++import java.net.URL; ++import java.util.*; ++import java.util.concurrent.Callable; ++import java.util.concurrent.Executors; ++import java.util.concurrent.ScheduledExecutorService; ++import java.util.concurrent.TimeUnit; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++import java.util.zip.GZIPOutputStream; ++ ++/** ++ * bStats collects some data for plugin authors. ++ * ++ * Check out https://bStats.org/ to learn more about bStats! ++ */ ++public class Metrics { ++ ++ // Executor service for requests ++ // We use an executor service because the Bukkit scheduler is affected by server lags ++ private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); ++ ++ // The version of this bStats class ++ public static final int B_STATS_VERSION = 1; ++ ++ // The url to which the data is sent ++ private static final String URL = "https://bStats.org/submitData/server-implementation"; ++ ++ // Should failed requests be logged? ++ private static boolean logFailedRequests = false; ++ ++ // The logger for the failed requests ++ private static Logger logger = Logger.getLogger("bStats"); ++ ++ // The name of the server software ++ private final String name; ++ ++ // The uuid of the server ++ private final String serverUUID; ++ ++ // A list with all custom charts ++ private final List charts = new ArrayList<>(); ++ ++ /** ++ * Class constructor. ++ * ++ * @param name The name of the server software. ++ * @param serverUUID The uuid of the server. ++ * @param logFailedRequests Whether failed requests should be logged or not. ++ * @param logger The logger for the failed requests. ++ */ ++ public Metrics(String name, String serverUUID, boolean logFailedRequests, Logger logger) { ++ this.name = name; ++ this.serverUUID = serverUUID; ++ Metrics.logFailedRequests = logFailedRequests; ++ Metrics.logger = logger; ++ ++ // Start submitting the data ++ startSubmitting(); ++ } ++ ++ /** ++ * Adds a custom chart. ++ * ++ * @param chart The chart to add. ++ */ ++ public void addCustomChart(CustomChart chart) { ++ if (chart == null) { ++ throw new IllegalArgumentException("Chart cannot be null!"); ++ } ++ charts.add(chart); ++ } ++ ++ /** ++ * Starts the Scheduler which submits our data every 30 minutes. ++ */ ++ private void startSubmitting() { ++ final Runnable submitTask = this::submitData; ++ ++ // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the ++ // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. ++ // WARNING: You must not modify any part of this Metrics class, including the submit delay or frequency! ++ // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! ++ long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); ++ long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); ++ scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); ++ scheduler.scheduleAtFixedRate(submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); ++ } ++ ++ /** ++ * Gets the plugin specific data. ++ * ++ * @return The plugin specific data. ++ */ ++ private JSONObject getPluginData() { ++ JSONObject data = new JSONObject(); ++ ++ data.put("pluginName", name); // Append the name of the server software ++ JSONArray customCharts = new JSONArray(); ++ for (CustomChart customChart : charts) { ++ // Add the data of the custom charts ++ JSONObject chart = customChart.getRequestJsonObject(); ++ if (chart == null) { // If the chart is null, we skip it ++ continue; ++ } ++ customCharts.add(chart); ++ } ++ data.put("customCharts", customCharts); ++ ++ return data; ++ } ++ ++ /** ++ * Gets the server specific data. ++ * ++ * @return The server specific data. ++ */ ++ private JSONObject getServerData() { ++ // OS specific data ++ String osName = System.getProperty("os.name"); ++ String osArch = System.getProperty("os.arch"); ++ String osVersion = System.getProperty("os.version"); ++ int coreCount = Runtime.getRuntime().availableProcessors(); ++ ++ JSONObject data = new JSONObject(); ++ ++ data.put("serverUUID", serverUUID); ++ ++ data.put("osName", osName); ++ data.put("osArch", osArch); ++ data.put("osVersion", osVersion); ++ data.put("coreCount", coreCount); ++ ++ return data; ++ } ++ ++ /** ++ * Collects the data and sends it afterwards. ++ */ ++ private void submitData() { ++ final JSONObject data = getServerData(); ++ ++ JSONArray pluginData = new JSONArray(); ++ pluginData.add(getPluginData()); ++ data.put("plugins", pluginData); ++ ++ try { ++ // We are still in the Thread of the timer, so nothing get blocked :) ++ sendData(data); ++ } catch (Exception e) { ++ // Something went wrong! :( ++ if (logFailedRequests) { ++ logger.log(Level.WARNING, "Could not submit stats of " + name, e); ++ } ++ } ++ } ++ ++ /** ++ * Sends the data to the bStats server. ++ * ++ * @param data The data to send. ++ * @throws Exception If the request failed. ++ */ ++ private static void sendData(JSONObject data) throws Exception { ++ if (data == null) { ++ throw new IllegalArgumentException("Data cannot be null!"); ++ } ++ HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); ++ ++ // Compress the data to save bandwidth ++ byte[] compressedData = compress(data.toString()); ++ ++ // Add headers ++ connection.setRequestMethod("POST"); ++ connection.addRequestProperty("Accept", "application/json"); ++ connection.addRequestProperty("Connection", "close"); ++ connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request ++ connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); ++ connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format ++ connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); ++ ++ // Send data ++ connection.setDoOutput(true); ++ DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); ++ outputStream.write(compressedData); ++ outputStream.flush(); ++ outputStream.close(); ++ ++ connection.getInputStream().close(); // We don't care about the response - Just send our data :) ++ } ++ ++ /** ++ * Gzips the given String. ++ * ++ * @param str The string to gzip. ++ * @return The gzipped String. ++ * @throws IOException If the compression failed. ++ */ ++ private static byte[] compress(final String str) throws IOException { ++ if (str == null) { ++ return null; ++ } ++ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ++ GZIPOutputStream gzip = new GZIPOutputStream(outputStream); ++ gzip.write(str.getBytes("UTF-8")); ++ gzip.close(); ++ return outputStream.toByteArray(); ++ } ++ ++ /** ++ * Represents a custom chart. ++ */ ++ public static abstract class CustomChart { ++ ++ // The id of the chart ++ final String chartId; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ */ ++ CustomChart(String chartId) { ++ if (chartId == null || chartId.isEmpty()) { ++ throw new IllegalArgumentException("ChartId cannot be null or empty!"); ++ } ++ this.chartId = chartId; ++ } ++ ++ private JSONObject getRequestJsonObject() { ++ JSONObject chart = new JSONObject(); ++ chart.put("chartId", chartId); ++ try { ++ JSONObject data = getChartData(); ++ if (data == null) { ++ // If the data is null we don't send the chart. ++ return null; ++ } ++ chart.put("data", data); ++ } catch (Throwable t) { ++ if (logFailedRequests) { ++ logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t); ++ } ++ return null; ++ } ++ return chart; ++ } ++ ++ protected abstract JSONObject getChartData() throws Exception; ++ ++ } ++ ++ /** ++ * Represents a custom simple pie. ++ */ ++ public static class SimplePie extends CustomChart { ++ ++ private final Callable callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public SimplePie(String chartId, Callable callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ String value = callable.call(); ++ if (value == null || value.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("value", value); ++ return data; ++ } ++ } ++ ++ /** ++ * Represents a custom advanced pie. ++ */ ++ public static class AdvancedPie extends CustomChart { ++ ++ private final Callable> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public AdvancedPie(String chartId, Callable> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ boolean allSkipped = true; ++ for (Map.Entry entry : map.entrySet()) { ++ if (entry.getValue() == 0) { ++ continue; // Skip this invalid ++ } ++ allSkipped = false; ++ values.put(entry.getKey(), entry.getValue()); ++ } ++ if (allSkipped) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("values", values); ++ return data; ++ } ++ } ++ ++ /** ++ * Represents a custom drilldown pie. ++ */ ++ public static class DrilldownPie extends CustomChart { ++ ++ private final Callable>> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public DrilldownPie(String chartId, Callable>> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ public JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map> map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ boolean reallyAllSkipped = true; ++ for (Map.Entry> entryValues : map.entrySet()) { ++ JSONObject value = new JSONObject(); ++ boolean allSkipped = true; ++ for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { ++ value.put(valueEntry.getKey(), valueEntry.getValue()); ++ allSkipped = false; ++ } ++ if (!allSkipped) { ++ reallyAllSkipped = false; ++ values.put(entryValues.getKey(), value); ++ } ++ } ++ if (reallyAllSkipped) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("values", values); ++ return data; ++ } ++ } ++ ++ /** ++ * Represents a custom single line chart. ++ */ ++ public static class SingleLineChart extends CustomChart { ++ ++ private final Callable callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public SingleLineChart(String chartId, Callable callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ int value = callable.call(); ++ if (value == 0) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("value", value); ++ return data; ++ } ++ ++ } ++ ++ /** ++ * Represents a custom multi line chart. ++ */ ++ public static class MultiLineChart extends CustomChart { ++ ++ private final Callable> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public MultiLineChart(String chartId, Callable> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ boolean allSkipped = true; ++ for (Map.Entry entry : map.entrySet()) { ++ if (entry.getValue() == 0) { ++ continue; // Skip this invalid ++ } ++ allSkipped = false; ++ values.put(entry.getKey(), entry.getValue()); ++ } ++ if (allSkipped) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("values", values); ++ return data; ++ } ++ ++ } ++ ++ /** ++ * Represents a custom simple bar chart. ++ */ ++ public static class SimpleBarChart extends CustomChart { ++ ++ private final Callable> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public SimpleBarChart(String chartId, Callable> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ for (Map.Entry entry : map.entrySet()) { ++ JSONArray categoryValues = new JSONArray(); ++ categoryValues.add(entry.getValue()); ++ values.put(entry.getKey(), categoryValues); ++ } ++ data.put("values", values); ++ return data; ++ } ++ ++ } ++ ++ /** ++ * Represents a custom advanced bar chart. ++ */ ++ public static class AdvancedBarChart extends CustomChart { ++ ++ private final Callable> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public AdvancedBarChart(String chartId, Callable> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ boolean allSkipped = true; ++ for (Map.Entry entry : map.entrySet()) { ++ if (entry.getValue().length == 0) { ++ continue; // Skip this invalid ++ } ++ allSkipped = false; ++ JSONArray categoryValues = new JSONArray(); ++ for (int categoryValue : entry.getValue()) { ++ categoryValues.add(categoryValue); ++ } ++ values.put(entry.getKey(), categoryValues); ++ } ++ if (allSkipped) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("values", values); ++ return data; ++ } ++ ++ } ++ ++ static class PaperMetrics { ++ static void startMetrics() { ++ // Get the config file ++ File configFile = new File(new File((File) MinecraftServer.getServer().options.valueOf("plugins"), "bStats"), "config.yml"); ++ YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); ++ ++ // Check if the config file exists ++ if (!config.isSet("serverUuid")) { ++ ++ // Add default values ++ config.addDefault("enabled", true); ++ // Every server gets it's unique random id. ++ config.addDefault("serverUuid", UUID.randomUUID().toString()); ++ // Should failed request be logged? ++ config.addDefault("logFailedRequests", false); ++ ++ // Inform the server owners about bStats ++ config.options().header( ++ "bStats collects some data for plugin authors like how many servers are using their plugins.\n" + ++ "To honor their work, you should not disable it.\n" + ++ "This has nearly no effect on the server performance!\n" + ++ "Check out https://bStats.org/ to learn more :)" ++ ).copyDefaults(true); ++ try { ++ config.save(configFile); ++ } catch (IOException ignored) { ++ } ++ } ++ // Load the data ++ String serverUUID = config.getString("serverUuid"); ++ boolean logFailedRequests = config.getBoolean("logFailedRequests", false); ++ // Only start Metrics, if it's enabled in the config ++ if (config.getBoolean("enabled", true)) { ++ Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger()); ++ ++ metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { ++ String minecraftVersion = Bukkit.getVersion(); ++ minecraftVersion = minecraftVersion.substring(minecraftVersion.indexOf("MC: ") + 4, minecraftVersion.length() - 1); ++ return minecraftVersion; ++ })); ++ ++ metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); ++ metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() || PaperConfig.isProxyOnlineMode() ? "online" : "offline")); ++ metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); ++ ++ metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { ++ Map> map = new HashMap<>(); ++ String javaVersion = System.getProperty("java.version"); ++ Map entry = new HashMap<>(); ++ entry.put(javaVersion, 1); ++ ++ // http://openjdk.java.net/jeps/223 ++ // Java decided to change their versioning scheme and in doing so modified the java.version system ++ // property to return $major[.$minor][.$secuity][-ea], as opposed to 1.$major.0_$identifier ++ // we can handle pre-9 by checking if the "major" is equal to "1", otherwise, 9+ ++ String majorVersion = javaVersion.split("\\.")[0]; ++ String release; ++ ++ int indexOf = javaVersion.lastIndexOf('.'); ++ ++ if (majorVersion.equals("1")) { ++ release = "Java " + javaVersion.substring(0, indexOf); ++ } else { ++ // of course, it really wouldn't be all that simple if they didn't add a quirk, now would it ++ // valid strings for the major may potentially include values such as -ea to deannotate a pre release ++ Matcher versionMatcher = Pattern.compile("\\d+").matcher(majorVersion); ++ if (versionMatcher.find()) { ++ majorVersion = versionMatcher.group(0); ++ } ++ release = "Java " + majorVersion; ++ } ++ map.put(release, entry); ++ ++ return map; ++ })); ++ ++ metrics.addCustomChart(new Metrics.DrilldownPie("legacy_plugins", () -> { ++ Map> map = new HashMap<>(); ++ ++ // count legacy plugins ++ int legacy = 0; ++ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { ++ if (CraftMagicNumbers.isLegacy(plugin.getDescription())) { ++ legacy++; ++ } ++ } ++ ++ // insert real value as lower dimension ++ Map entry = new HashMap<>(); ++ entry.put(String.valueOf(legacy), 1); ++ ++ // create buckets as higher dimension ++ if (legacy == 0) { ++ map.put("0 \uD83D\uDE0E", entry); // :sunglasses: ++ } else if (legacy <= 5) { ++ map.put("1-5", entry); ++ } else if (legacy <= 10) { ++ map.put("6-10", entry); ++ } else if (legacy <= 25) { ++ map.put("11-25", entry); ++ } else if (legacy <= 50) { ++ map.put("26-50", entry); ++ } else { ++ map.put("50+ \uD83D\uDE2D", entry); // :cry: ++ } ++ ++ return map; ++ })); ++ } ++ ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 2c0514892d3993bef57ecf677cf8bb0fbe0216e4..da922f395f0fff0881ead893c900c5b2623f48f0 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -42,6 +42,7 @@ public class PaperConfig { + private static boolean verbose; + private static boolean fatalError; + /*========================================================================*/ ++ private static boolean metricsStarted; + + public static void init(File configFile) { + CONFIG_FILE = configFile; +@@ -84,6 +85,11 @@ public class PaperConfig { + for (Map.Entry entry : commands.entrySet()) { + MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); + } ++ ++ if (!metricsStarted) { ++ Metrics.PaperMetrics.startMetrics(); ++ metricsStarted = true; ++ } + } + + static void readConfig(Class clazz, Object instance) { +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index dc11dab14624ca25e78bf0b919ecf461e0be430d..0083f979933d4a9035efb992ab0a2f250a56a979 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -83,6 +83,7 @@ public class SpigotConfig + MinecraftServer.getServer().server.getCommandMap().register( entry.getKey(), "Spigot", entry.getValue() ); + } + ++ /* // Paper - Replace with our own + if ( metrics == null ) + { + try +@@ -94,6 +95,7 @@ public class SpigotConfig + Bukkit.getServer().getLogger().log( Level.SEVERE, "Could not start metrics service", ex ); + } + } ++ */ // Paper end + } + + static void readConfig(Class clazz, Object instance) diff --git a/Remapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch b/Remapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch new file mode 100644 index 0000000000..91f564fb1b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch @@ -0,0 +1,144 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 01:40:13 -0400 +Subject: [PATCH] Add MinecraftKey Information to Objects + +Stores the reference to the objects respective MinecraftKey + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index d05eeaa711a09bb121b530654821894e795ff4ea..e95b91cefb0374bd5bb57cc090f5ecd566d7a618 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -208,7 +208,7 @@ public class PaperCommand extends Command { + + Collection entities = world.entitiesById.values(); + entities.forEach(e -> { +- ResourceLocation key = new ResourceLocation(""); // TODO: update in next patch ++ ResourceLocation key = e.getMinecraftKey(); + + MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); + ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); +diff --git a/src/main/java/net/minecraft/server/KeyedObject.java b/src/main/java/net/minecraft/server/KeyedObject.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3c9933050ca0a7453ba7950cb3cf4cc8b5b7081d +--- /dev/null ++++ b/src/main/java/net/minecraft/server/KeyedObject.java +@@ -0,0 +1,11 @@ ++package net.minecraft.server; ++ ++import net.minecraft.resources.ResourceLocation; ++ ++public interface KeyedObject { ++ ResourceLocation getMinecraftKey(); ++ default String getMinecraftKeyString() { ++ ResourceLocation key = getMinecraftKey(); ++ return key != null ? key.toString() : null; ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index c7008fcbd4d805fe0e743f1d4ad948dcd86ceae3..48c9d2b7d56832ebd13749a394b8b715f0b1704d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -135,7 +135,7 @@ import org.bukkit.event.player.PlayerTeleportEvent; + import org.bukkit.plugin.PluginManager; + // CraftBukkit end + +-public abstract class Entity implements Nameable, CommandSource { ++public abstract class Entity implements Nameable, CommandSource, net.minecraft.server.KeyedObject { // Paper + + // CraftBukkit start + private static final int CURRENT_LEVEL = 2; +@@ -1761,12 +1761,31 @@ public abstract class Entity implements Nameable, CommandSource { + return true; + } + ++ // Paper start ++ private ResourceLocation entityKey; ++ private String entityKeyString; ++ ++ @Override ++ public ResourceLocation getMinecraftKey() { ++ if (entityKey == null) { ++ this.entityKey = EntityType.getKey(this.getType()); ++ this.entityKeyString = this.entityKey != null ? this.entityKey.toString() : null; ++ } ++ return entityKey; ++ } ++ ++ @Override ++ public String getMinecraftKeyString() { ++ getMinecraftKey(); // Try to load if it doesn't exists. see: https://github.com/PaperMC/Paper/issues/1280 ++ return entityKeyString; ++ } + @Nullable + public final String getEncodeId() { + EntityType entitytypes = this.getType(); + ResourceLocation minecraftkey = EntityType.getKey(entitytypes); + +- return entitytypes.canSerialize() && minecraftkey != null ? minecraftkey.toString() : null; ++ return entitytypes != null && entitytypes.isPersistable() ? getMinecraftKeyString() : null; ++ // Paper end + } + + protected abstract void readAdditionalSaveData(CompoundTag tag); +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index 102298d57cf3143092d04ab1d5d0d69b28d696ea..2cb86de4bfc87a709f0cfa2c4e550d8e7928a3f0 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -384,6 +384,7 @@ public class EntityType { + } + } + ++ public boolean isPersistable() { return canSerialize(); } // Paper - OBFHELPER + public boolean canSerialize() { + return this.serialize; + } +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 8928a1ae51d24fd15aaae93bc8ea573548f2b012..846fc0f36377337630b2ec2a5f7a5a54c39c2965 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -23,7 +23,7 @@ import org.bukkit.inventory.InventoryHolder; + + import org.spigotmc.CustomTimingsHandler; // Spigot + +-public abstract class BlockEntity { ++public abstract class BlockEntity implements net.minecraft.server.KeyedObject { // Paper + + public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot + // CraftBukkit start - data containers +@@ -31,7 +31,7 @@ public abstract class BlockEntity { + public CraftPersistentDataContainer persistentDataContainer; + // CraftBukkit end + private static final Logger LOGGER = LogManager.getLogger(); +- private final BlockEntityType type; ++ private final BlockEntityType type; public BlockEntityType getTileEntityType() { return type; } // Paper - OBFHELPER + @Nullable + protected Level level; + protected BlockPos worldPosition; +@@ -45,6 +45,26 @@ public abstract class BlockEntity { + this.type = type; + } + ++ // Paper start ++ private String tileEntityKeyString = null; ++ private ResourceLocation tileEntityKey = null; ++ ++ @Override ++ public ResourceLocation getMinecraftKey() { ++ if (tileEntityKey == null) { ++ tileEntityKey = BlockEntityType.getKey(this.getTileEntityType()); ++ tileEntityKeyString = tileEntityKey != null ? tileEntityKey.toString() : null; ++ } ++ return tileEntityKey; ++ } ++ ++ @Override ++ public String getMinecraftKeyString() { ++ getMinecraftKey(); // Try to load if it doesn't exists. ++ return tileEntityKeyString; ++ } ++ // Paper end ++ + @Nullable + public Level getLevel() { + return this.level; diff --git a/Remapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch b/Remapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch new file mode 100644 index 0000000000..11ed8248cc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch @@ -0,0 +1,171 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 02:10:36 -0400 +Subject: [PATCH] Store reference to current Chunk for Entity and Block + Entities + +This enables us a fast reference to the entities current chunk instead +of having to look it up by hashmap lookups. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 48c9d2b7d56832ebd13749a394b8b715f0b1704d..b633f6b3a36b793e6dbc1b8b554bfba74c719570 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -260,7 +260,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean isChunkLoaded() { +- return level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); ++ return getCurrentChunk() != null; + } + // CraftBukkit end + +@@ -1762,6 +1762,23 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + // Paper start ++ public java.lang.ref.WeakReference currentChunk = null; ++ ++ public void setCurrentChunk(net.minecraft.world.level.chunk.LevelChunk chunk) { ++ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; ++ } ++ /** ++ * Returns the entities current registered chunk. If the entity is not added to a chunk yet, it will return null ++ */ ++ public net.minecraft.world.level.chunk.LevelChunk getCurrentChunk() { ++ final net.minecraft.world.level.chunk.LevelChunk chunk = currentChunk != null ? currentChunk.get() : null; ++ if (chunk != null && chunk.loaded) { ++ return chunk; ++ } ++ ++ return !inChunk ? null : ((ServerLevel)level).getChunkSource().getChunkAtIfLoadedMainThreadNoCache(xChunk, zChunk); ++ } ++ + private ResourceLocation entityKey; + private String entityKeyString; + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 846fc0f36377337630b2ec2a5f7a5a54c39c2965..bb60c9da9f3ba0d5c5bad22512675ccb841a60e5 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -11,6 +11,7 @@ import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; + import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.LevelChunk; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import org.apache.logging.log4j.util.Supplier; +@@ -63,6 +64,15 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + getMinecraftKey(); // Try to load if it doesn't exists. + return tileEntityKeyString; + } ++ ++ private java.lang.ref.WeakReference currentChunk = null; ++ public LevelChunk getCurrentChunk() { ++ final LevelChunk chunk = currentChunk != null ? currentChunk.get() : null; ++ return chunk != null && chunk.loaded ? chunk : null; ++ } ++ public void setCurrentChunk(LevelChunk chunk) { ++ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; ++ } + // Paper end + + @Nullable +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index e2c5a17aa72d1a5412d76881187d4d9ad1763297..ae08fcce66d50d7f61bc3bd4a0e2547d56f53e82 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -89,11 +89,36 @@ public class LevelChunk implements ChunkAccess { + this(world, pos, biomes, UpgradeData.EMPTY, EmptyTickList.empty(), EmptyTickList.empty(), 0L, (LevelChunkSection[]) null, (Consumer) null); + } + ++ // Paper start ++ private class TileEntityHashMap extends java.util.HashMap { ++ @Override ++ public BlockEntity put(BlockPos key, BlockEntity value) { ++ BlockEntity replaced = super.put(key, value); ++ if (replaced != null) { ++ replaced.setCurrentChunk(null); ++ } ++ if (value != null) { ++ value.setCurrentChunk(LevelChunk.this); ++ } ++ return replaced; ++ } ++ ++ @Override ++ public BlockEntity remove(Object key) { ++ BlockEntity removed = super.remove(key); ++ if (removed != null) { ++ removed.setCurrentChunk(null); ++ } ++ return removed; ++ } ++ } ++ // Paper end ++ + public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes, UpgradeData upgradeData, TickList blockTickScheduler, TickList fluidTickScheduler, long inhabitedTime, @Nullable LevelChunkSection[] sections, @Nullable Consumer loadToWorldConsumer) { + this.sections = new LevelChunkSection[16]; + this.pendingBlockEntities = Maps.newHashMap(); + this.heightmaps = Maps.newEnumMap(Heightmap.Types.class); +- this.blockEntities = Maps.newHashMap(); ++ this.blockEntities = new TileEntityHashMap(); // Paper + this.structureStarts = Maps.newHashMap(); + this.structuresRefences = Maps.newHashMap(); + this.postProcessing = new ShortList[16]; +@@ -504,6 +529,7 @@ public class LevelChunk implements ChunkAccess { + } + + entity.inChunk = true; ++ entity.setCurrentChunk(this); // Paper + entity.xChunk = this.chunkPos.x; + entity.yChunk = k; + entity.zChunk = this.chunkPos.z; +@@ -516,6 +542,7 @@ public class LevelChunk implements ChunkAccess { + ((Heightmap) this.heightmaps.get(type)).setRawData(heightmap); + } + ++ public final void removeEntity(Entity entity) { this.removeEntity(entity); } // Paper - OBFHELPER + public void removeEntity(Entity entity) { + this.removeEntity(entity, entity.yChunk); + } +@@ -530,7 +557,12 @@ public class LevelChunk implements ChunkAccess { + section = this.entitySlices.length - 1; + } + +- this.entitySlices[section].remove(entity); ++ // Paper start ++ if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); ++ if (!this.entitySlices[section].remove(entity)) { ++ return; ++ } ++ // Paper end + this.entities.remove(entity); // Paper + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 080d3292e03c5a179b9eb89da1550718d263f817..eb61c803cf74c5ca2c51d5027a02ed3db6b53096 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -145,6 +145,7 @@ import net.minecraft.world.entity.vehicle.MinecartHopper; + import net.minecraft.world.entity.vehicle.MinecartSpawner; + import net.minecraft.world.entity.vehicle.MinecartTNT; + import net.minecraft.world.phys.AABB; ++import org.bukkit.Chunk; // Paper + import org.bukkit.EntityEffect; + import org.bukkit.Location; + import org.bukkit.Server; +@@ -186,6 +187,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + this.entity = entity; + } + ++ @Override ++ public Chunk getChunk() { ++ net.minecraft.world.level.chunk.LevelChunk currentChunk = entity.getCurrentChunk(); ++ return currentChunk != null ? currentChunk.bukkitChunk : getLocation().getChunk(); ++ } ++ + public static CraftEntity getEntity(CraftServer server, Entity entity) { + /* + * Order is *EXTREMELY* important -- keep it right! =D diff --git a/Remapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch b/Remapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch new file mode 100644 index 0000000000..ca1271ce76 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 02:13:59 -0400 +Subject: [PATCH] Store counts for each Entity/Block Entity Type + +Opens door for future patches to optimize performance + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index ae08fcce66d50d7f61bc3bd4a0e2547d56f53e82..00ce55c17980da87a3834f952475a766543506b0 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -90,15 +90,19 @@ public class LevelChunk implements ChunkAccess { + } + + // Paper start ++ public final co.aikar.util.Counter entityCounts = new co.aikar.util.Counter<>(); ++ public final co.aikar.util.Counter tileEntityCounts = new co.aikar.util.Counter<>(); + private class TileEntityHashMap extends java.util.HashMap { + @Override + public BlockEntity put(BlockPos key, BlockEntity value) { + BlockEntity replaced = super.put(key, value); + if (replaced != null) { + replaced.setCurrentChunk(null); ++ tileEntityCounts.decrement(replaced.getMinecraftKeyString()); + } + if (value != null) { + value.setCurrentChunk(LevelChunk.this); ++ tileEntityCounts.increment(value.getMinecraftKeyString()); + } + return replaced; + } +@@ -108,6 +112,7 @@ public class LevelChunk implements ChunkAccess { + BlockEntity removed = super.remove(key); + if (removed != null) { + removed.setCurrentChunk(null); ++ tileEntityCounts.decrement(removed.getMinecraftKeyString()); + } + return removed; + } +@@ -528,6 +533,7 @@ public class LevelChunk implements ChunkAccess { + k = this.entitySlices.length - 1; + } + ++ if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper + entity.inChunk = true; + entity.setCurrentChunk(this); // Paper + entity.xChunk = this.chunkPos.x; +@@ -562,6 +568,7 @@ public class LevelChunk implements ChunkAccess { + if (!this.entitySlices[section].remove(entity)) { + return; + } ++ entityCounts.decrement(entity.getMinecraftKeyString()); + // Paper end + this.entities.remove(entity); // Paper + } diff --git a/Remapped-Spigot-Server-Patches/0009-Timings-v2.patch b/Remapped-Spigot-Server-Patches/0009-Timings-v2.patch new file mode 100644 index 0000000000..dc683eaeec --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0009-Timings-v2.patch @@ -0,0 +1,2330 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 04:00:11 -0600 +Subject: [PATCH] Timings v2 + + +diff --git a/src/main/java/SpigotTimings.java b/src/main/java/SpigotTimings.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 +diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java +new file mode 100644 +index 0000000000000000000000000000000000000000..be3a62f543a5fec4739c14821fe5a443c1fa3f5b +--- /dev/null ++++ b/src/main/java/co/aikar/timings/MinecraftTimings.java +@@ -0,0 +1,152 @@ ++package co.aikar.timings; ++ ++import Timing; ++import com.google.common.collect.MapMaker; ++import net.minecraft.commands.CommandFunction; ++import net.minecraft.network.protocol.Packet; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.entity.BlockEntity; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.scheduler.BukkitTask; ++ ++import org.bukkit.craftbukkit.scheduler.CraftTask; ++ ++import java.util.Map; ++ ++// TODO: Re-implement missing timers ++public final class MinecraftTimings { ++ ++ public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); ++ public static final Timing playerListTimer = Timings.ofSafe("Player List"); ++ public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); ++ public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); ++ public static final Timing tickablesTimer = Timings.ofSafe("Tickables"); ++ public static final Timing minecraftSchedulerTimer = Timings.ofSafe("Minecraft Scheduler"); ++ public static final Timing bukkitSchedulerTimer = Timings.ofSafe("Bukkit Scheduler"); ++ public static final Timing bukkitSchedulerPendingTimer = Timings.ofSafe("Bukkit Scheduler - Pending"); ++ public static final Timing bukkitSchedulerFinishTimer = Timings.ofSafe("Bukkit Scheduler - Finishing"); ++ public static final Timing chunkIOTickTimer = Timings.ofSafe("ChunkIOTick"); ++ public static final Timing timeUpdateTimer = Timings.ofSafe("Time Update"); ++ public static final Timing serverCommandTimer = Timings.ofSafe("Server Command"); ++ public static final Timing savePlayers = Timings.ofSafe("Save Players"); ++ ++ public static final Timing tickEntityTimer = Timings.ofSafe("## tickEntity"); ++ public static final Timing tickTileEntityTimer = Timings.ofSafe("## tickTileEntity"); ++ public static final Timing packetProcessTimer = Timings.ofSafe("## Packet Processing"); ++ public static final Timing scheduledBlocksTimer = Timings.ofSafe("## Scheduled Blocks"); ++ public static final Timing structureGenerationTimer = Timings.ofSafe("Structure Generation"); ++ ++ public static final Timing processQueueTimer = Timings.ofSafe("processQueue"); ++ public static final Timing processTasksTimer = Timings.ofSafe("processTasks"); ++ ++ public static final Timing playerCommandTimer = Timings.ofSafe("playerCommand"); ++ ++ public static final Timing entityActivationCheckTimer = Timings.ofSafe("entityActivationCheck"); ++ ++ public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update"); ++ public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate"); ++ ++ private static final Map, String> taskNameCache = new MapMaker().weakKeys().makeMap(); ++ ++ private MinecraftTimings() {} ++ ++ public static Timing getInternalTaskName(String taskName) { ++ return Timings.ofSafe(taskName); ++ } ++ ++ /** ++ * Gets a timer associated with a plugins tasks. ++ * @param bukkitTask ++ * @param period ++ * @return ++ */ ++ public static Timing getPluginTaskTimings(BukkitTask bukkitTask, long period) { ++ if (!bukkitTask.isSync()) { ++ return NullTimingHandler.NULL; ++ } ++ Plugin plugin; ++ ++ CraftTask craftTask = (CraftTask) bukkitTask; ++ ++ final Class taskClass = craftTask.getTaskClass(); ++ if (bukkitTask.getOwner() != null) { ++ plugin = bukkitTask.getOwner(); ++ } else { ++ plugin = TimingsManager.getPluginByClassloader(taskClass); ++ } ++ ++ final String taskname = taskNameCache.computeIfAbsent(taskClass, clazz -> { ++ try { ++ String clsName = !clazz.isMemberClass() ++ ? clazz.getName() ++ : clazz.getCanonicalName(); ++ if (clsName != null && clsName.contains("$Lambda$")) { ++ clsName = clsName.replaceAll("(Lambda\\$.*?)/.*", "$1"); ++ } ++ return clsName != null ? clsName : "UnknownTask"; ++ } catch (Throwable ex) { ++ new Exception("Error occurred detecting class name", ex).printStackTrace(); ++ return "MangledClassFile"; ++ } ++ }); ++ ++ StringBuilder name = new StringBuilder(64); ++ name.append("Task: ").append(taskname); ++ if (period > 0) { ++ name.append(" (interval:").append(period).append(")"); ++ } else { ++ name.append(" (Single)"); ++ } ++ ++ if (plugin == null) { ++ return Timings.ofSafe(null, name.toString()); ++ } ++ ++ return Timings.ofSafe(plugin, name.toString()); ++ } ++ ++ /** ++ * Get a named timer for the specified entity type to track type specific timings. ++ * @param entityType ++ * @return ++ */ ++ public static Timing getEntityTimings(String entityType, String type) { ++ return Timings.ofSafe("Minecraft", "## tickEntity - " + entityType + " - " + type, tickEntityTimer); ++ } ++ ++ /** ++ * Get a named timer for the specified tile entity type to track type specific timings. ++ * @param entity ++ * @return ++ */ ++ public static Timing getTileEntityTimings(BlockEntity entity) { ++ String entityType = entity.getClass().getName(); ++ return Timings.ofSafe("Minecraft", "## tickTileEntity - " + entityType, tickTileEntityTimer); ++ } ++ public static Timing getCancelTasksTimer() { ++ return Timings.ofSafe("Cancel Tasks"); ++ } ++ public static Timing getCancelTasksTimer(Plugin plugin) { ++ return Timings.ofSafe(plugin, "Cancel Tasks"); ++ } ++ ++ public static void stopServer() { ++ TimingsManager.stopServer(); ++ } ++ ++ public static Timing getBlockTiming(Block block) { ++ return Timings.ofSafe("## Scheduled Block: " + block.toString(), scheduledBlocksTimer); ++ } ++/* ++ public static Timing getStructureTiming(StructureGenerator structureGenerator) { ++ return Timings.ofSafe("Structure Generator - " + structureGenerator.getName(), structureGenerationTimer); ++ }*/ ++ ++ public static Timing getPacketTiming(Packet packet) { ++ return Timings.ofSafe("## Packet - " + packet.getClass().getName(), packetProcessTimer); ++ } ++ ++ public static Timing getCommandFunctionTiming(CommandFunction function) { ++ return Timings.ofSafe("Command Function - " + function.getMinecraftKey().toString()); ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java +new file mode 100644 +index 0000000000000000000000000000000000000000..94adf0275a2e7093c152cc3b8b0a5747b3a13a86 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingsExport.java +@@ -0,0 +1,380 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import com.google.common.collect.Sets; ++import net.minecraft.server.MinecraftServer; ++import org.apache.commons.lang.StringUtils; ++import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; ++import org.bukkit.Material; ++import org.bukkit.configuration.ConfigurationSection; ++import org.bukkit.configuration.MemorySection; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.entity.EntityType; ++import org.json.simple.JSONObject; ++import org.json.simple.JSONValue; ++ ++import java.io.ByteArrayOutputStream; ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.OutputStream; ++import java.lang.management.ManagementFactory; ++import java.lang.management.OperatingSystemMXBean; ++import java.lang.management.RuntimeMXBean; ++import java.net.HttpURLConnection; ++import java.net.InetAddress; ++import java.net.URL; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import java.util.logging.Level; ++import java.util.zip.GZIPOutputStream; ++ ++import static co.aikar.timings.TimingsManager.HISTORY; ++import static co.aikar.util.JSONUtil.appendObjectData; ++import static co.aikar.util.JSONUtil.createObject; ++import static co.aikar.util.JSONUtil.pair; ++import static co.aikar.util.JSONUtil.toArray; ++import static co.aikar.util.JSONUtil.toArrayMapper; ++import static co.aikar.util.JSONUtil.toObjectMapper; ++ ++import TimingHistory; ++import TimingsReportListener; ++ ++@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) ++public class TimingsExport extends Thread { ++ ++ private final TimingsReportListener listeners; ++ private final Map out; ++ private final TimingHistory[] history; ++ private static long lastReport = 0; ++ ++ private TimingsExport(TimingsReportListener listeners, Map out, TimingHistory[] history) { ++ super("Timings paste thread"); ++ this.listeners = listeners; ++ this.out = out; ++ this.history = history; ++ } ++ ++ /** ++ * Checks if any pending reports are being requested, and builds one if needed. ++ */ ++ public static void reportTimings() { ++ if (Timings.requestingReport.isEmpty()) { ++ return; ++ } ++ TimingsReportListener listeners = new TimingsReportListener(Timings.requestingReport); ++ listeners.addConsoleIfNeeded(); ++ ++ Timings.requestingReport.clear(); ++ long now = System.currentTimeMillis(); ++ final long lastReportDiff = now - lastReport; ++ if (lastReportDiff < 60000) { ++ listeners.sendMessage(ChatColor.RED + "Please wait at least 1 minute in between Timings reports. (" + (int)((60000 - lastReportDiff) / 1000) + " seconds)"); ++ listeners.done(); ++ return; ++ } ++ final long lastStartDiff = now - TimingsManager.timingStart; ++ if (lastStartDiff < 180000) { ++ listeners.sendMessage(ChatColor.RED + "Please wait at least 3 minutes before generating a Timings report. Unlike Timings v1, v2 benefits from longer timings and is not as useful with short timings. (" + (int)((180000 - lastStartDiff) / 1000) + " seconds)"); ++ listeners.done(); ++ return; ++ } ++ listeners.sendMessage(ChatColor.GREEN + "Preparing Timings Report..."); ++ lastReport = now; ++ Map parent = createObject( ++ // Get some basic system details about the server ++ pair("version", Bukkit.getVersion()), ++ pair("maxplayers", Bukkit.getMaxPlayers()), ++ pair("start", TimingsManager.timingStart / 1000), ++ pair("end", System.currentTimeMillis() / 1000), ++ pair("online-mode", Bukkit.getServer().getOnlineMode()), ++ pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), ++ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedIds(), pack -> { ++ // Don't feel like obf helper'ing these, non fatal if its temp missed. ++ return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); ++ })) ++ ); ++ if (!TimingsManager.privacy) { ++ appendObjectData(parent, ++ pair("server", Bukkit.getUnsafe().getTimingsServerName()), ++ pair("motd", Bukkit.getServer().getMotd()), ++ pair("icon", Bukkit.getServer().getServerIcon().getData()) ++ ); ++ } ++ ++ final Runtime runtime = Runtime.getRuntime(); ++ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); ++ ++ OperatingSystemMXBean osInfo = ManagementFactory.getOperatingSystemMXBean(); ++ ++ parent.put("system", createObject( ++ pair("timingcost", getCost()), ++ pair("loadavg", osInfo.getSystemLoadAverage()), ++ pair("name", System.getProperty("os.name")), ++ pair("version", System.getProperty("os.version")), ++ pair("jvmversion", System.getProperty("java.version")), ++ pair("arch", System.getProperty("os.arch")), ++ pair("maxmem", runtime.maxMemory()), ++ pair("memory", createObject( ++ pair("heap", ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().toString()), ++ pair("nonheap", ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().toString()), ++ pair("finalizing", ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount()) ++ )), ++ pair("cpu", runtime.availableProcessors()), ++ pair("runtime", runtimeBean.getUptime()), ++ pair("flags", StringUtils.join(runtimeBean.getInputArguments(), " ")), ++ pair("gc", toObjectMapper(ManagementFactory.getGarbageCollectorMXBeans(), input -> pair(input.getName(), toArray(input.getCollectionCount(), input.getCollectionTime())))) ++ ) ++ ); ++ ++ parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getAllLevels(), world -> { ++ if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; ++ return pair(world.getWorldData().getName(), createObject( ++ pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { ++ return pair(rule, world.getWorld().getGameRuleValue(rule)); ++ })), ++ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) ++ )); ++ })); ++ ++ Set tileEntityTypeSet = Sets.newHashSet(); ++ Set entityTypeSet = Sets.newHashSet(); ++ ++ int size = HISTORY.size(); ++ TimingHistory[] history = new TimingHistory[size + 1]; ++ int i = 0; ++ for (TimingHistory timingHistory : HISTORY) { ++ tileEntityTypeSet.addAll(timingHistory.tileEntityTypeSet); ++ entityTypeSet.addAll(timingHistory.entityTypeSet); ++ history[i++] = timingHistory; ++ } ++ ++ history[i] = new TimingHistory(); // Current snapshot ++ tileEntityTypeSet.addAll(history[i].tileEntityTypeSet); ++ entityTypeSet.addAll(history[i].entityTypeSet); ++ ++ ++ Map handlers = createObject(); ++ Map groupData; ++ synchronized (TimingIdentifier.GROUP_MAP) { ++ for (TimingIdentifier.TimingGroup group : TimingIdentifier.GROUP_MAP.values()) { ++ synchronized (group.handlers) { ++ for (TimingHandler id : group.handlers) { ++ ++ if (!id.isTimed() && !id.isSpecial()) { ++ continue; ++ } ++ ++ String name = id.identifier.name; ++ if (name.startsWith("##")) { ++ name = name.substring(3); ++ } ++ handlers.put(id.id, toArray( ++ group.id, ++ name ++ )); ++ } ++ } ++ } ++ ++ groupData = toObjectMapper( ++ TimingIdentifier.GROUP_MAP.values(), group -> pair(group.id, group.name)); ++ } ++ ++ parent.put("idmap", createObject( ++ pair("groups", groupData), ++ pair("handlers", handlers), ++ pair("worlds", toObjectMapper(TimingHistory.worldMap.entrySet(), input -> pair(input.getValue(), input.getKey()))), ++ pair("tileentity", ++ toObjectMapper(tileEntityTypeSet, input -> pair(input.ordinal(), input.name()))), ++ pair("entity", ++ toObjectMapper(entityTypeSet, input -> pair(input.ordinal(), input.name()))) ++ )); ++ ++ // Information about loaded plugins ++ ++ parent.put("plugins", toObjectMapper(Bukkit.getPluginManager().getPlugins(), ++ plugin -> pair(plugin.getName(), createObject( ++ pair("version", plugin.getDescription().getVersion()), ++ pair("description", String.valueOf(plugin.getDescription().getDescription()).trim()), ++ pair("website", plugin.getDescription().getWebsite()), ++ pair("authors", StringUtils.join(plugin.getDescription().getAuthors(), ", ")) ++ )))); ++ ++ ++ ++ // Information on the users Config ++ ++ parent.put("config", createObject( ++ pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), ++ pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), ++ pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) ++ )); ++ ++ new TimingsExport(listeners, parent, history).start(); ++ } ++ ++ static long getCost() { ++ // Benchmark the users System.nanotime() for cost basis ++ int passes = 100; ++ TimingHandler SAMPLER1 = Timings.ofSafe("Timings Sampler 1"); ++ TimingHandler SAMPLER2 = Timings.ofSafe("Timings Sampler 2"); ++ TimingHandler SAMPLER3 = Timings.ofSafe("Timings Sampler 3"); ++ TimingHandler SAMPLER4 = Timings.ofSafe("Timings Sampler 4"); ++ TimingHandler SAMPLER5 = Timings.ofSafe("Timings Sampler 5"); ++ TimingHandler SAMPLER6 = Timings.ofSafe("Timings Sampler 6"); ++ ++ long start = System.nanoTime(); ++ for (int i = 0; i < passes; i++) { ++ SAMPLER1.startTiming(); ++ SAMPLER2.startTiming(); ++ SAMPLER3.startTiming(); ++ SAMPLER3.stopTiming(); ++ SAMPLER4.startTiming(); ++ SAMPLER5.startTiming(); ++ SAMPLER6.startTiming(); ++ SAMPLER6.stopTiming(); ++ SAMPLER5.stopTiming(); ++ SAMPLER4.stopTiming(); ++ SAMPLER2.stopTiming(); ++ SAMPLER1.stopTiming(); ++ } ++ long timingsCost = (System.nanoTime() - start) / passes / 6; ++ SAMPLER1.reset(true); ++ SAMPLER2.reset(true); ++ SAMPLER3.reset(true); ++ SAMPLER4.reset(true); ++ SAMPLER5.reset(true); ++ SAMPLER6.reset(true); ++ return timingsCost; ++ } ++ ++ private static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) { ++ ++ JSONObject object = new JSONObject(); ++ for (String key : config.getKeys(false)) { ++ String fullKey = (parentKey != null ? parentKey + "." + key : key); ++ if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld")) { ++ continue; ++ } ++ final Object val = config.get(key); ++ ++ object.put(key, valAsJSON(val, fullKey)); ++ } ++ return object; ++ } ++ ++ private static Object valAsJSON(Object val, final String parentKey) { ++ if (!(val instanceof MemorySection)) { ++ if (val instanceof List) { ++ Iterable v = (Iterable) val; ++ return toArrayMapper(v, input -> valAsJSON(input, parentKey)); ++ } else { ++ return String.valueOf(val); ++ } ++ } else { ++ return mapAsJSON((ConfigurationSection) val, parentKey); ++ } ++ } ++ ++ @Override ++ public void run() { ++ out.put("data", toArrayMapper(history, TimingHistory::export)); ++ ++ ++ String response = null; ++ String timingsURL = null; ++ try { ++ HttpURLConnection con = (HttpURLConnection) new URL("http://timings.aikar.co/post").openConnection(); ++ con.setDoOutput(true); ++ String hostName = "BrokenHost"; ++ try { ++ hostName = InetAddress.getLocalHost().getHostName(); ++ } catch (Exception ignored) {} ++ con.setRequestProperty("User-Agent", "Paper/" + Bukkit.getUnsafe().getTimingsServerName() + "/" + hostName); ++ con.setRequestMethod("POST"); ++ con.setInstanceFollowRedirects(false); ++ ++ OutputStream request = new GZIPOutputStream(con.getOutputStream()) {{ ++ this.def.setLevel(7); ++ }}; ++ ++ request.write(JSONValue.toJSONString(out).getBytes("UTF-8")); ++ request.close(); ++ ++ response = getResponse(con); ++ ++ if (con.getResponseCode() != 302) { ++ listeners.sendMessage( ++ ChatColor.RED + "Upload Error: " + con.getResponseCode() + ": " + con.getResponseMessage()); ++ listeners.sendMessage(ChatColor.RED + "Check your logs for more information"); ++ if (response != null) { ++ Bukkit.getLogger().log(Level.SEVERE, response); ++ } ++ return; ++ } ++ ++ timingsURL = con.getHeaderField("Location"); ++ listeners.sendMessage(ChatColor.GREEN + "View Timings Report: " + timingsURL); ++ ++ if (response != null && !response.isEmpty()) { ++ Bukkit.getLogger().log(Level.INFO, "Timing Response: " + response); ++ } ++ } catch (IOException ex) { ++ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); ++ if (response != null) { ++ Bukkit.getLogger().log(Level.SEVERE, response); ++ } ++ Bukkit.getLogger().log(Level.SEVERE, "Could not paste timings", ex); ++ } finally { ++ this.listeners.done(timingsURL); ++ } ++ } ++ ++ private String getResponse(HttpURLConnection con) throws IOException { ++ InputStream is = null; ++ try { ++ is = con.getInputStream(); ++ ByteArrayOutputStream bos = new ByteArrayOutputStream(); ++ ++ byte[] b = new byte[1024]; ++ int bytesRead; ++ while ((bytesRead = is.read(b)) != -1) { ++ bos.write(b, 0, bytesRead); ++ } ++ return bos.toString(); ++ ++ } catch (IOException ex) { ++ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); ++ Bukkit.getLogger().log(Level.WARNING, con.getResponseMessage(), ex); ++ return null; ++ } finally { ++ if (is != null) { ++ is.close(); ++ } ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..79ede25e4fe7a648b1d29c49d876482a2158f892 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +@@ -0,0 +1,120 @@ ++package co.aikar.timings; ++ ++import Timing; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.storage.PrimaryLevelData; ++ ++/** ++ * Set of timers per world, to track world specific timings. ++ */ ++// TODO: Re-implement missing timers ++public class WorldTimingsHandler { ++ public final Timing mobSpawn; ++ public final Timing doChunkUnload; ++ public final Timing doPortalForcer; ++ public final Timing scheduledBlocks; ++ public final Timing scheduledBlocksCleanup; ++ public final Timing scheduledBlocksTicking; ++ public final Timing chunkTicks; ++ public final Timing lightChunk; ++ public final Timing chunkTicksBlocks; ++ public final Timing doVillages; ++ public final Timing doChunkMap; ++ public final Timing doChunkMapUpdate; ++ public final Timing doChunkMapToUpdate; ++ public final Timing doChunkMapSortMissing; ++ public final Timing doChunkMapSortSendToPlayers; ++ public final Timing doChunkMapPlayersNeedingChunks; ++ public final Timing doChunkMapPendingSendToPlayers; ++ public final Timing doChunkMapUnloadChunks; ++ public final Timing doChunkGC; ++ public final Timing doSounds; ++ public final Timing entityRemoval; ++ public final Timing entityTick; ++ public final Timing tileEntityTick; ++ public final Timing tileEntityPending; ++ public final Timing tracker1; ++ public final Timing tracker2; ++ public final Timing doTick; ++ public final Timing tickEntities; ++ public final Timing chunks; ++ public final Timing newEntities; ++ public final Timing raids; ++ public final Timing chunkProviderTick; ++ public final Timing broadcastChunkUpdates; ++ public final Timing countNaturalMobs; ++ ++ public final Timing chunkLoad; ++ public final Timing chunkLoadPopulate; ++ public final Timing syncChunkLoad; ++ public final Timing chunkLoadLevelTimer; ++ public final Timing chunkIO; ++ public final Timing chunkPostLoad; ++ public final Timing worldSave; ++ public final Timing worldSaveChunks; ++ public final Timing worldSaveLevel; ++ public final Timing chunkSaveData; ++ ++ ++ public final Timing miscMobSpawning; ++ ++ public WorldTimingsHandler(Level server) { ++ String name = ((PrimaryLevelData) server.getLevelData()).getLevelName() + " - "; ++ ++ mobSpawn = Timings.ofSafe(name + "mobSpawn"); ++ doChunkUnload = Timings.ofSafe(name + "doChunkUnload"); ++ scheduledBlocks = Timings.ofSafe(name + "Scheduled Blocks"); ++ scheduledBlocksCleanup = Timings.ofSafe(name + "Scheduled Blocks - Cleanup"); ++ scheduledBlocksTicking = Timings.ofSafe(name + "Scheduled Blocks - Ticking"); ++ chunkTicks = Timings.ofSafe(name + "Chunk Ticks"); ++ lightChunk = Timings.ofSafe(name + "Light Chunk"); ++ chunkTicksBlocks = Timings.ofSafe(name + "Chunk Ticks - Blocks"); ++ doVillages = Timings.ofSafe(name + "doVillages"); ++ doChunkMap = Timings.ofSafe(name + "doChunkMap"); ++ doChunkMapUpdate = Timings.ofSafe(name + "doChunkMap - Update"); ++ doChunkMapToUpdate = Timings.ofSafe(name + "doChunkMap - To Update"); ++ doChunkMapSortMissing = Timings.ofSafe(name + "doChunkMap - Sort Missing"); ++ doChunkMapSortSendToPlayers = Timings.ofSafe(name + "doChunkMap - Sort Send To Players"); ++ doChunkMapPlayersNeedingChunks = Timings.ofSafe(name + "doChunkMap - Players Needing Chunks"); ++ doChunkMapPendingSendToPlayers = Timings.ofSafe(name + "doChunkMap - Pending Send To Players"); ++ doChunkMapUnloadChunks = Timings.ofSafe(name + "doChunkMap - Unload Chunks"); ++ doSounds = Timings.ofSafe(name + "doSounds"); ++ doChunkGC = Timings.ofSafe(name + "doChunkGC"); ++ doPortalForcer = Timings.ofSafe(name + "doPortalForcer"); ++ entityTick = Timings.ofSafe(name + "entityTick"); ++ entityRemoval = Timings.ofSafe(name + "entityRemoval"); ++ tileEntityTick = Timings.ofSafe(name + "tileEntityTick"); ++ tileEntityPending = Timings.ofSafe(name + "tileEntityPending"); ++ ++ chunkLoad = Timings.ofSafe(name + "Chunk Load"); ++ chunkLoadPopulate = Timings.ofSafe(name + "Chunk Load - Populate"); ++ syncChunkLoad = Timings.ofSafe(name + "Sync Chunk Load"); ++ chunkLoadLevelTimer = Timings.ofSafe(name + "Chunk Load - Load Level"); ++ chunkIO = Timings.ofSafe(name + "Chunk Load - DiskIO"); ++ chunkPostLoad = Timings.ofSafe(name + "Chunk Load - Post Load"); ++ worldSave = Timings.ofSafe(name + "World Save"); ++ worldSaveLevel = Timings.ofSafe(name + "World Save - Level"); ++ worldSaveChunks = Timings.ofSafe(name + "World Save - Chunks"); ++ chunkSaveData = Timings.ofSafe(name + "Chunk Save - Data"); ++ ++ tracker1 = Timings.ofSafe(name + "tracker stage 1"); ++ tracker2 = Timings.ofSafe(name + "tracker stage 2"); ++ doTick = Timings.ofSafe(name + "doTick"); ++ tickEntities = Timings.ofSafe(name + "tickEntities"); ++ ++ chunks = Timings.ofSafe(name + "Chunks"); ++ newEntities = Timings.ofSafe(name + "New entity registration"); ++ raids = Timings.ofSafe(name + "Raids"); ++ chunkProviderTick = Timings.ofSafe(name + "Chunk provider tick"); ++ broadcastChunkUpdates = Timings.ofSafe(name + "Broadcast chunk updates"); ++ countNaturalMobs = Timings.ofSafe(name + "Count natural mobs"); ++ ++ ++ miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); ++ } ++ ++ public static Timing getTickList(ServerLevel worldserver, String timingsType) { ++ return Timings.ofSafe(((PrimaryLevelData) worldserver.getLevelData()).getLevelName() + " - Scheduled " + timingsType); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index da922f395f0fff0881ead893c900c5b2623f48f0..1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -14,12 +14,15 @@ import java.util.concurrent.TimeUnit; + import java.util.logging.Level; + import java.util.regex.Pattern; + ++import com.google.common.collect.Lists; + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; + import org.bukkit.command.Command; + import org.bukkit.configuration.ConfigurationSection; + import org.bukkit.configuration.InvalidConfigurationException; + import org.bukkit.configuration.file.YamlConfiguration; ++import co.aikar.timings.Timings; ++import co.aikar.timings.TimingsManager; + + public class PaperConfig { + +@@ -188,4 +191,30 @@ public class PaperConfig { + config.addDefault(path, def); + return config.getString(path, config.getString(path)); + } ++ ++ public static String timingsServerName; ++ private static void timings() { ++ boolean timings = getBoolean("timings.enabled", true); ++ boolean verboseTimings = getBoolean("timings.verbose", true); ++ TimingsManager.privacy = getBoolean("timings.server-name-privacy", false); ++ TimingsManager.hiddenConfigs = getList("timings.hidden-config-entries", Lists.newArrayList("database", "settings.bungeecord-addresses", "settings.velocity-support.secret")); ++ if (!TimingsManager.hiddenConfigs.contains("settings.velocity-support.secret")) { ++ TimingsManager.hiddenConfigs.add("settings.velocity-support.secret"); ++ } ++ int timingHistoryInterval = getInt("timings.history-interval", 300); ++ int timingHistoryLength = getInt("timings.history-length", 3600); ++ timingsServerName = getString("timings.server-name", "Unknown Server"); ++ ++ ++ Timings.setVerboseTimingsEnabled(verboseTimings); ++ Timings.setTimingsEnabled(timings); ++ Timings.setHistoryInterval(timingHistoryInterval * 20); ++ Timings.setHistoryLength(timingHistoryLength * 20); ++ ++ log("Timings: " + timings + ++ " - Verbose: " + verboseTimings + ++ " - Interval: " + timeSummary(Timings.getHistoryInterval() / 20) + ++ " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + ++ " - Server Name: " + timingsServerName); ++ } + } +diff --git a/src/main/java/net/minecraft/commands/CommandFunction.java b/src/main/java/net/minecraft/commands/CommandFunction.java +index cf57de0e791a9362fe95b65134d9fe4f4e95adf4..07b891075191161a8a903876b02caa75d4db1366 100644 +--- a/src/main/java/net/minecraft/commands/CommandFunction.java ++++ b/src/main/java/net/minecraft/commands/CommandFunction.java +@@ -15,12 +15,22 @@ public class CommandFunction { + + private final CommandFunction.Entry[] entries; + private final ResourceLocation id; ++ // Paper start ++ public co.aikar.timings.Timing timing; ++ public co.aikar.timings.Timing getTiming() { ++ if (timing == null) { ++ timing = co.aikar.timings.MinecraftTimings.getCommandFunctionTiming(this); ++ } ++ return timing; ++ } ++ // Paper end + + public CommandFunction(ResourceLocation id, CommandFunction.Entry[] elements) { + this.id = id; + this.entries = elements; + } + ++ public final ResourceLocation getMinecraftKey() { return this.getId(); } // Paper - OBFHELPER + public ResourceLocation getId() { + return this.id; + } +diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java +index 23ccd095ad99fe90a6f2a16bcca368804b16101a..4ae8201d7dcffeb3298a4e593f978e15ffc5ac15 100644 +--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java ++++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java +@@ -3,6 +3,8 @@ package net.minecraft.network.protocol; + import net.minecraft.network.PacketListener; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import co.aikar.timings.MinecraftTimings; // Paper ++import co.aikar.timings.Timing; // Paper + + // CraftBukkit start + import net.minecraft.server.MinecraftServer; +@@ -21,10 +23,13 @@ public class PacketUtils { + + public static void ensureRunningOnSameThread(Packet packet, T listener, BlockableEventLoop engine) throws RunningOnDifferentThreadException { + if (!engine.isSameThread()) { ++ Timing timing = MinecraftTimings.getPacketTiming(packet); // Paper - timings + engine.execute(() -> { + if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerGamePacketListenerImpl && ((ServerGamePacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590 + if (listener.a().isConnected()) { ++ try (Timing ignored = timing.startTiming()) { // Paper - timings + packet.handle(listener); ++ } // Paper - timings + } else { + PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 2406879e76a110e96a4753e66366432a4bc52d9b..a456b9cbf0e5eea4e888e0e3d07ed17558650371 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -172,7 +172,7 @@ import org.bukkit.craftbukkit.Main; + import org.bukkit.event.server.ServerLoadEvent; + // CraftBukkit end + +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper + import org.spigotmc.SlackActivityAccountant; // Spigot + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { +@@ -226,8 +226,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +- return !this.haveTime(); ++ return !this.canSleepForTickNoOversleep(); // Paper - move oversleep into full server tick + }); + } + +@@ -1120,10 +1133,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { ++ return !this.canOversleep(); ++ }); ++ isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); ++ // Paper end ++ + ++this.tickCount; + this.tickChildren(shouldKeepTicking); + if (i - this.lastServerStatus >= 5000000000L) { +@@ -1141,14 +1162,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % autosavePeriod == 0) { // CraftBukkit +- SpigotTimings.worldSaveTimer.startTiming(); // Spigot + MinecraftServer.LOGGER.debug("Autosave started"); + this.profiler.push("save"); + this.playerList.saveAll(); + this.saveAllChunks(true, false, false); + this.profiler.pop(); + MinecraftServer.LOGGER.debug("Autosave finished"); +- SpigotTimings.worldSaveTimer.stopTiming(); // Spigot + } + + this.profiler.push("snooper"); +@@ -1161,6 +1180,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { + // CraftBukkit start - fire RemoteServerCommandEvent +@@ -677,10 +679,39 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + if (event.isCancelled()) { + return; + } ++ // Paper start ++ if (command.toLowerCase().startsWith("timings") && command.toLowerCase().matches("timings (report|paste|get|merged|seperate)")) { ++ org.bukkit.command.BufferedCommandSender sender = new org.bukkit.command.BufferedCommandSender(); ++ Waitable waitable = new Waitable() { ++ @Override ++ protected String evaluate() { ++ return sender.getBuffer(); ++ } ++ }; ++ waitableArray[0] = waitable; ++ co.aikar.timings.Timings.generateReport(new co.aikar.timings.TimingsReportListener(sender, waitable)); ++ } else { ++ // Paper end + ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), rconConsoleSource.createCommandSourceStack()); + server.dispatchServerCommand(remoteConsole, serverCommand); ++ } // Paper + // CraftBukkit end + }); ++ // Paper start ++ if (waitableArray[0] != null) { ++ //noinspection unchecked ++ Waitable waitable = waitableArray[0]; ++ try { ++ return waitable.get(); ++ } catch (java.util.concurrent.ExecutionException e) { ++ throw new RuntimeException("Exception processing rcon command " + command, e.getCause()); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // Maintain interrupted state ++ throw new RuntimeException("Interrupted processing rcon command " + command, e); ++ } ++ ++ } ++ // Paper end + return this.rconConsoleSource.getCommandResponse(); + } + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465..59a5f82c9f57d760ba4959a040ce8cbf0f49e4aa 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1,7 +1,9 @@ + package net.minecraft.server.level; + ++import co.aikar.timings.Timing; // Paper + import com.google.common.collect.ImmutableList; + import com.google.common.collect.Iterables; ++import com.google.common.collect.ComparisonChain; // Paper + import com.google.common.collect.Lists; + import com.google.common.collect.Queues; + import com.google.common.collect.Sets; +@@ -552,11 +554,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + private CompletableFuture> scheduleChunkLoad(ChunkPos pos) { + return CompletableFuture.supplyAsync(() -> { +- try { ++ try (Timing ignored = this.level.timings.chunkLoad.startTimingIfSync()) { // Paper + this.level.getProfiler().incrementCounter("chunkLoad"); +- CompoundTag nbttagcompound = this.readChunk(pos); ++ CompoundTag nbttagcompound; // Paper ++ try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings ++ nbttagcompound = this.readChunk(pos); ++ } // Paper end + +- if (nbttagcompound != null) { ++ if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings + boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8); + + if (flag) { +@@ -568,7 +573,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + ChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", pos); +- } ++ }} // Paper + } catch (ReportedException reportedexception) { + Throwable throwable = reportedexception.getCause(); + +@@ -605,7 +610,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return "chunkGenerate " + requiredStatus.getName(); + }); + return completablefuture.thenComposeAsync((either) -> { +- return (CompletableFuture) either.map((list) -> { ++ return either.map((list) -> { // Paper - Shut up. + try { + CompletableFuture> completablefuture1 = requiredStatus.generate(this.level, this.generator, this.structureManager, this.lightEngine, (ichunkaccess) -> { + return this.protoChunkToFullChunk(holder); +@@ -658,6 +663,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkStatus chunkstatus = ChunkHolder.getStatus(playerchunk.getTicketLevel()); + + return !chunkstatus.isOrAfter(ChunkStatus.FULL) ? ChunkHolder.UNLOADED_CHUNK : either.mapLeft((ichunkaccess) -> { ++ try (Timing ignored = level.timings.chunkPostLoad.startTimingIfSync()) { // Paper + ChunkPos chunkcoordintpair = playerchunk.getPos(); + LevelChunk chunk; + +@@ -717,6 +723,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + return chunk; ++ } // Paper + }); + }, (runnable) -> { + ProcessorHandle mailbox = this.mainThreadMailbox; +@@ -1175,6 +1182,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + ChunkMap.TrackedEntity playerchunkmap_entitytracker; + ObjectIterator objectiterator; ++ level.timings.tracker1.startTiming(); // Paper + + for (objectiterator = this.entityMap.values().iterator(); objectiterator.hasNext(); playerchunkmap_entitytracker.serverEntity.sendChanges()) { + playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); +@@ -1192,16 +1200,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + playerchunkmap_entitytracker.lastSectionPos = sectionposition1; + } + } ++ level.timings.tracker1.stopTiming(); // Paper + + if (!list.isEmpty()) { + objectiterator = this.entityMap.values().iterator(); + ++ level.timings.tracker2.startTiming(); // Paper + while (objectiterator.hasNext()) { + playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); + playerchunkmap_entitytracker.updatePlayers(list); + } ++ level.timings.tracker2.stopTiming(); // Paper + } + ++ + } + + protected void broadcast(Entity entity, Packet packet) { +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index ef336645f3bd7a86129ad1dff7e1a15dc93d1e3e..d0b0fdaf5451bcc7f7ac7dab28aa59ef77e6dd97 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -344,11 +344,13 @@ public class ServerChunkCache extends ChunkSource { + } + + gameprofilerfiller.incrementCounter("getChunkCacheMiss"); +- level.timings.syncChunkLoadTimer.startTiming(); // Spigot + CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); + ++ if (!completablefuture.isDone()) { // Paper ++ this.level.timings.syncChunkLoad.startTiming(); // Paper + this.mainThreadProcessor.managedBlock(completablefuture::isDone); +- level.timings.syncChunkLoadTimer.stopTiming(); // Spigot ++ this.level.timings.syncChunkLoad.stopTiming(); // Paper ++ } // Paper + ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { + return ichunkaccess1; + }, (playerchunk_failure) -> { +@@ -536,7 +538,9 @@ public class ServerChunkCache extends ChunkSource { + + public void save(boolean flush) { + this.runDistanceManagerUpdates(); ++ try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings + this.chunkMap.saveAllChunks(flush); ++ } // Paper - Timings + } + + @Override +@@ -573,7 +577,9 @@ public class ServerChunkCache extends ChunkSource { + this.runDistanceManagerUpdates(); + this.level.timings.doChunkMap.stopTiming(); // Spigot + this.level.getProfiler().popPush("chunks"); ++ this.level.timings.chunks.startTiming(); // Paper - timings + this.tickChunks(); ++ this.level.timings.chunks.stopTiming(); // Paper - timings + this.level.timings.doChunkUnload.startTiming(); // Spigot + this.level.getProfiler().popPush("unload"); + this.chunkMap.tick(shouldKeepTicking); +@@ -597,19 +603,24 @@ public class ServerChunkCache extends ChunkSource { + boolean flag2 = level.ticksPerAnimalSpawns != 0L && worlddata.getGameTime() % level.ticksPerAnimalSpawns == 0L; // CraftBukkit + + this.level.getProfiler().push("naturalSpawnCount"); ++ this.level.timings.countNaturalMobs.startTiming(); // Paper - timings + int l = this.distanceManager.getNaturalSpawnChunkCount(); + NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk); ++ this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings + + this.lastSpawnState = spawnercreature_d; + this.level.getProfiler().pop(); + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper ++ this.level.timings.chunkTicks.startTiming(); // Paper + this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + + if (optional.isPresent()) { + this.level.getProfiler().push("broadcast"); ++ this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timings + playerchunk.broadcastChanges((LevelChunk) optional.get()); ++ this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings + this.level.getProfiler().pop(); + Optional optional1 = ((Either) playerchunk.getEntityTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + +@@ -623,25 +634,26 @@ public class ServerChunkCache extends ChunkSource { + NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); + } + +- this.level.timings.doTickTiles.startTiming(); // Spigot ++ //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper + this.level.tickChunk(chunk, k); +- this.level.timings.doTickTiles.stopTiming(); // Spigot ++ //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper + } + } + } + }); ++ this.level.timings.chunkTicks.stopTiming(); // Paper + this.level.getProfiler().push("customSpawners"); + if (flag1) { ++ try (co.aikar.timings.Timing ignored = this.level.timings.miscMobSpawning.startTiming()) { // Paper - timings + this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); ++ } // Paper - timings + } + + this.level.getProfiler().pop(); + this.level.getProfiler().pop(); + } + +- this.level.timings.tracker.startTiming(); // Spigot + this.chunkMap.tick(); +- this.level.timings.tracker.stopTiming(); // Spigot + } + + private void getFullChunk(long pos, Consumer chunkConsumer) { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 34ed8f0d348e7bc2339660ebc6490057ba9ef214..0cc86ca4ea4a2e1b5acc3c0507397eef85dec0c1 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -2,6 +2,8 @@ package net.minecraft.server.level; + + import com.google.common.annotations.VisibleForTesting; + import com.google.common.collect.Iterables; ++import co.aikar.timings.TimingHistory; // Paper ++import co.aikar.timings.Timings; // Paper + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Queues; +@@ -147,7 +149,6 @@ import org.apache.logging.log4j.Logger; + import java.util.logging.Level; + import org.bukkit.Bukkit; + import org.bukkit.WeatherType; +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.event.CraftEventFactory; + import org.bukkit.craftbukkit.util.WorldUUID; + import org.bukkit.event.entity.CreatureSpawnEvent; +@@ -203,10 +204,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // CraftBukkit end + this.blockTicks = new ServerTickList<>(this, (block) -> { + return block == null || block.defaultBlockState().isAir(); +- }, Registry.BLOCK::getKey, this::tickBlock); ++ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings + this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { + return fluidtype == null || fluidtype == Fluids.EMPTY; +- }, Registry.FLUID::getKey, this::tickLiquid); ++ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings + this.navigations = Sets.newHashSet(); + this.blockEvents = new ObjectLinkedOpenHashSet(); + this.tickTime = flag1; +@@ -436,17 +437,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.updateSkyBrightness(); + this.tickTime(); + gameprofilerfiller.popPush("chunkSource"); ++ this.timings.chunkProviderTick.startTiming(); // Paper - timings + this.getChunkSource().tick(shouldKeepTicking); ++ this.timings.chunkProviderTick.stopTiming(); // Paper - timings + gameprofilerfiller.popPush("tickPending"); +- timings.doTickPending.startTiming(); // Spigot ++ timings.scheduledBlocks.startTiming(); // Paper + if (!this.isDebug()) { + this.blockTicks.tick(); + this.liquidTicks.tick(); + } +- timings.doTickPending.stopTiming(); // Spigot ++ timings.scheduledBlocks.stopTiming(); // Paper + + gameprofilerfiller.popPush("raid"); ++ this.timings.raids.startTiming(); // Paper - timings + this.raids.tick(); ++ this.timings.raids.stopTiming(); // Paper - timings + gameprofilerfiller.popPush("blockEvents"); + timings.doSounds.startTiming(); // Spigot + this.runBlockEvents(); +@@ -618,6 +623,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + gameprofilerfiller.popPush("tickBlocks"); ++ timings.chunkTicksBlocks.startTiming(); // Paper + if (randomTickSpeed > 0) { + LevelChunkSection[] achunksection = chunk.getSections(); + int l = achunksection.length; +@@ -649,7 +655,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + } + } +- ++ timings.chunkTicksBlocks.stopTiming(); // Paper + gameprofilerfiller.pop(); + } + +@@ -747,14 +753,22 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (!(entity instanceof Player) && !this.getChunkSource().isEntityTickingChunk(entity)) { + this.updateChunkPos(entity); + } else { ++ ++TimingHistory.entityTicks; // Paper - timings + // Spigot start ++ co.aikar.timings.Timing timer; // Paper + if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { + entity.tickCount++; ++ timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings + entity.inactiveTick(); ++ } finally { timer.stopTiming(); } // Paper + return; + } + // Spigot end +- entity.tickTimer.startTiming(); // Spigot ++ // Paper start- timings ++ TimingHistory.activatedEntityTicks++; ++ timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); ++ try { ++ // Paper end - timings + entity.setPosAndOldPos(entity.getX(), entity.getY(), entity.getZ()); + entity.yRotO = entity.yRot; + entity.xRotO = entity.xRot; +@@ -781,7 +795,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.tickPassenger(entity, entity1); + } + } +- entity.tickTimer.stopTiming(); // Spigot ++ } finally { timer.stopTiming(); } // Paper - timings + + } + } +@@ -859,6 +873,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + if (!flag1) { + org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit ++ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper + if (progressListener != null) { + progressListener.progressStartNoAbort(new TranslatableComponent("menu.savingLevel")); + } +@@ -868,7 +883,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + progressListener.progressStage(new TranslatableComponent("menu.savingChunks")); + } + ++ timings.worldSaveChunks.startTiming(); // Paper + chunkproviderserver.save(flush); ++ timings.worldSaveChunks.stopTiming(); // Paper ++ } // Paper + } + + // CraftBukkit start - moved from MinecraftServer.saveChunks +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 35f3940cebb00ee29da54b1ee148ee931fa11636..466c4322803bedf1fa61be281b954bf94fb8ff02 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -209,6 +209,7 @@ import org.bukkit.inventory.EquipmentSlot; + import org.bukkit.inventory.InventoryView; + import org.bukkit.inventory.SmithingInventory; + import org.bukkit.util.NumberConversions; ++import co.aikar.timings.MinecraftTimings; // Paper + // CraftBukkit end + + public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -291,7 +292,6 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit end + + public void tick() { +- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.startTiming(); // Spigot + this.resetPosition(); + this.player.xo = this.player.getX(); + this.player.yo = this.player.getY(); +@@ -367,7 +367,6 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 + this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling")); + } +- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.stopTiming(); // Spigot + + } + +@@ -1915,7 +1914,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit end + + private void handleCommand(String input) { +- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot ++ MinecraftTimings.playerCommandTimer.startTiming(); // Paper + // CraftBukkit start - whole method + if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot + this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + input); +@@ -1926,7 +1925,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.craftServer.getPluginManager().callEvent(event); + + if (event.isCancelled()) { +- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot ++ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper + return; + } + +@@ -1939,7 +1938,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); + return; + } finally { +- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot ++ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper + } + // this.minecraftServer.getCommandDispatcher().a(this.player.getCommandListener(), s); + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 28121e2fee9d862057042261d25360f0d4ee4530..88af57699d7f9e45ad1366243049e4f3565703ff 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1,5 +1,6 @@ + package net.minecraft.server.players; + ++import co.aikar.timings.MinecraftTimings; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; +@@ -1018,10 +1019,11 @@ public abstract class PlayerList { + } + + public void saveAll() { ++ MinecraftTimings.savePlayers.startTiming(); // Paper + for (int i = 0; i < this.players.size(); ++i) { + this.save((ServerPlayer) this.players.get(i)); + } +- ++ MinecraftTimings.savePlayers.stopTiming(); // Paper + } + + public UserWhiteList getWhiteList() { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index b633f6b3a36b793e6dbc1b8b554bfba74c719570..2a7f587e19fcdd6d01b360d6b47d9eadd9df92cc 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -115,7 +115,6 @@ import org.bukkit.craftbukkit.event.CraftPortalEvent; + import org.bukkit.entity.Hanging; + import org.bukkit.entity.LivingEntity; + import org.bukkit.entity.Vehicle; +-import org.spigotmc.CustomTimingsHandler; // Spigot + import org.bukkit.event.entity.EntityCombustByEntityEvent; + import org.bukkit.event.hanging.HangingBreakByEntityEvent; + import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; +@@ -247,7 +246,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only + public boolean forceExplosionKnockback; // SPIGOT-949 + public boolean persistentInvisibility = false; +- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot + // Spigot start + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; +@@ -616,7 +614,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public void move(MoverType type, Vec3 movement) { +- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot + if (this.noPhysics) { + this.setBoundingBox(this.getBoundingBox().move(movement)); + this.setLocationFromBoundingbox(); +@@ -752,7 +749,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + this.level.getProfiler().pop(); + } +- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot + } + + protected BlockPos getOnPos() { +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index 2cb86de4bfc87a709f0cfa2c4e550d8e7928a3f0..e3d92d1d35911b2960a7ca82bd4f324d285d0533 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -281,17 +281,27 @@ public class EntityType { + return Registry.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(id)); + } + +- public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet immutableset, EntityDimensions entitysize, int i, int j) { +- this.factory = factory; +- this.category = spawnGroup; +- this.canSpawnFarFromPlayer = spawnableFarFromPlayer; +- this.serialize = saveable; +- this.summon = summonable; +- this.fireImmune = fireImmune; ++ public final String id; ++ public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet immutableset, EntityDimensions entitysize, int i, int j) { this(factory, spawnGroup, saveable, summonable, fireImmune, spawnableFarFromPlayer, immutableset, entitysize, i, j, "custom"); } // Paper - old signature ++ public EntityType(EntityType.EntityFactory entitytypes_b, MobCategory enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntityDimensions entitysize, int i, int j, String id) { // Paper - add id ++ this.factory = entitytypes_b; ++ this.category = enumcreaturetype; ++ this.canSpawnFarFromPlayer = flag3; ++ this.serialize = flag; ++ this.summon = flag1; ++ this.fireImmune = flag2; + this.immuneTo = immutableset; + this.dimensions = entitysize; + this.clientTrackingRange = i; + this.updateInterval = j; ++ ++ // Paper start - timings ++ this.id = id; ++ this.tickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "tick"); ++ this.inactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "inactiveTick"); ++ this.passengerTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerTick"); ++ this.passengerInactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerInactiveTick"); ++ // Paper end + } + + @Nullable +@@ -512,6 +522,12 @@ public class EntityType { + return this.updateInterval; + } + ++ // Paper start - timings ++ public final co.aikar.timings.Timing tickTimer; ++ public final co.aikar.timings.Timing inactiveTickTimer; ++ public final co.aikar.timings.Timing passengerTickTimer; ++ public final co.aikar.timings.Timing passengerInactiveTickTimer; ++ // Paper end + public boolean trackDeltas() { + return this != EntityType.PLAYER && this != EntityType.LLAMA_SPIT && this != EntityType.WITHER && this != EntityType.BAT && this != EntityType.ITEM_FRAME && this != EntityType.LEASH_KNOT && this != EntityType.PAINTING && this != EntityType.END_CRYSTAL && this != EntityType.EVOKER_FANGS; + } +@@ -599,7 +615,7 @@ public class EntityType { + Util.fetchChoiceType(References.ENTITY_TREE, id); + } + +- return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval); ++ return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval, id); // Paper - add id + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 9e5dde73bd65bf4e51352c628fba024c36e29ef1..e5f8cee6726ea9a90c540bb10fd8594a35bb5e40 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -132,7 +132,7 @@ import org.bukkit.event.entity.EntityTeleportEvent; + import org.bukkit.event.player.PlayerItemConsumeEvent; + // CraftBukkit end + +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper + + public abstract class LivingEntity extends Entity { + +@@ -2455,7 +2455,6 @@ public abstract class LivingEntity extends Entity { + + @Override + public void tick() { +- SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot + super.tick(); + this.updatingUsingItem(); + this.updateSwimAmount(); +@@ -2504,9 +2503,7 @@ public abstract class LivingEntity extends Entity { + } + } + +- SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot + this.aiStep(); +- SpigotTimings.timerEntityTickRest.startTiming(); // Spigot + double d0 = this.getX() - this.xo; + double d1 = this.getZ() - this.zo; + float f = (float) (d0 * d0 + d1 * d1); +@@ -2586,8 +2583,6 @@ public abstract class LivingEntity extends Entity { + if (this.isSleeping()) { + this.xRot = 0.0F; + } +- +- SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot + } + + public void detectEquipmentUpdates() { +@@ -2769,7 +2764,6 @@ public abstract class LivingEntity extends Entity { + + this.setDeltaMovement(d4, d5, d6); + this.level.getProfiler().push("ai"); +- SpigotTimings.timerEntityAI.startTiming(); // Spigot + if (this.isImmobile()) { + this.jumping = false; + this.xxa = 0.0F; +@@ -2779,7 +2773,6 @@ public abstract class LivingEntity extends Entity { + this.serverAiStep(); + this.level.getProfiler().pop(); + } +- SpigotTimings.timerEntityAI.stopTiming(); // Spigot + + this.level.getProfiler().pop(); + this.level.getProfiler().push("jump"); +@@ -2814,9 +2807,9 @@ public abstract class LivingEntity extends Entity { + this.updateFallFlying(); + AABB axisalignedbb = this.getBoundingBox(); + +- SpigotTimings.timerEntityAIMove.startTiming(); // Spigot ++ // SpigotTimings.timerEntityAIMove.startTiming(); // Spigot // Paper + this.travel(new Vec3((double) this.xxa, (double) this.yya, (double) this.zza)); +- SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot ++ // SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot // Paper + this.level.getProfiler().pop(); + this.level.getProfiler().push("push"); + if (this.autoSpinAttackTicks > 0) { +@@ -2824,9 +2817,7 @@ public abstract class LivingEntity extends Entity { + this.checkAutoSpinAttack(axisalignedbb, this.getBoundingBox()); + } + +- SpigotTimings.timerEntityAICollision.startTiming(); // Spigot + this.pushEntities(); +- SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot + this.level.getProfiler().pop(); + if (!this.level.isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { + this.hurt(DamageSource.DROWN, 1.0F); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 5cc4c2668df72f83fb1526f4586b71d2ae0103dc..c153df1f4dea3dc0ae744bde01e334b3bd3b50af 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -70,7 +70,6 @@ import org.apache.logging.log4j.Logger; + import java.util.HashMap; + import java.util.Map; + import org.bukkit.Bukkit; +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.block.CapturedBlockState; +@@ -132,7 +131,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper + +- public final SpigotTimings.WorldTimingsHandler timings; // Spigot ++ public final co.aikar.timings.WorldTimingsHandler timings; // Paper + public static BlockPos lastPhysicsProblem; // Spigot + private org.spigotmc.TickLimiter entityLimiter; + private org.spigotmc.TickLimiter tileLimiter; +@@ -217,7 +216,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) {} + }); + // CraftBukkit end +- timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings ++ timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings + this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + } +@@ -797,15 +796,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + + timings.tileEntityPending.stopTiming(); // Spigot ++ co.aikar.timings.TimingHistory.tileEntityTicks += this.tickableBlockEntities.size(); // Paper + gameprofilerfiller.pop(); + spigotConfig.currentPrimedTnt = 0; // Spigot + } + + public void guardEntityTick(Consumer tickConsumer, Entity entity) { + try { +- SpigotTimings.tickEntityTimer.startTiming(); // Spigot + tickConsumer.accept(entity); +- SpigotTimings.tickEntityTimer.stopTiming(); // Spigot + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); +diff --git a/src/main/java/net/minecraft/world/level/ServerTickList.java b/src/main/java/net/minecraft/world/level/ServerTickList.java +index 0519d5adf392dd46b4a93c5c1b977c8355163c2e..10ac1ba0a3d192486f22c2127d5bc30353f0edb6 100644 +--- a/src/main/java/net/minecraft/world/level/ServerTickList.java ++++ b/src/main/java/net/minecraft/world/level/ServerTickList.java +@@ -38,12 +38,17 @@ public class ServerTickList implements TickList { + private final List> alreadyTicked = Lists.newArrayList(); + private final Consumer> ticker; + +- public ServerTickList(ServerLevel world, Predicate invalidObjPredicate, Function idToName, Consumer> consumer) { +- this.ignore = invalidObjPredicate; +- this.toId = idToName; +- this.level = world; ++ public ServerTickList(ServerLevel worldserver, Predicate predicate, Function function, Consumer> consumer, String timingsType) { // Paper ++ this.ignore = predicate; ++ this.toId = function; ++ this.level = worldserver; + this.ticker = consumer; ++ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Cleanup"); ++ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Ticking"); + } ++ private final co.aikar.timings.Timing timingCleanup; // Paper ++ private final co.aikar.timings.Timing timingTicking; // Paper ++ // Paper end + + public void tick() { + int i = this.tickNextTickList.size(); +@@ -66,6 +71,7 @@ public class ServerTickList implements TickList { + + this.level.getProfiler().push("cleaning"); + ++ this.timingCleanup.startTiming(); // Paper + TickNextTickData nextticklistentry; + + while (i > 0 && iterator.hasNext()) { +@@ -81,7 +87,9 @@ public class ServerTickList implements TickList { + --i; + } + } ++ this.timingCleanup.stopTiming(); // Paper + ++ this.timingTicking.startTiming(); // Paper + this.level.getProfiler().popPush("ticking"); + + while ((nextticklistentry = (TickNextTickData) this.currentlyTicking.poll()) != null) { +@@ -101,6 +109,7 @@ public class ServerTickList implements TickList { + } + } + ++ this.timingTicking.stopTiming(); // Paper + this.level.getProfiler().pop(); + this.alreadyTicked.clear(); + this.currentlyTicking.clear(); +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 73a271a1fccd6f82dac8d33c0d378f0d84ceb5e5..2ae786b8fc6da19ca2a40252b0606f9e06d31ded 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -61,6 +61,15 @@ public class Block extends BlockBehaviour implements ItemLike { + }); + protected final StateDefinition stateDefinition; + private BlockState defaultBlockState; ++ // Paper start ++ public co.aikar.timings.Timing timing; ++ public co.aikar.timings.Timing getTiming() { ++ if (timing == null) { ++ timing = co.aikar.timings.MinecraftTimings.getBlockTiming(this); ++ } ++ return timing; ++ } ++ // Paper end + @Nullable + private String descriptionId; + @Nullable +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index bb60c9da9f3ba0d5c5bad22512675ccb841a60e5..d445a1b7b7605eed66923789c5d8e2199c31c5ac 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -23,10 +23,12 @@ import org.bukkit.inventory.InventoryHolder; + // CraftBukkit end + + import org.spigotmc.CustomTimingsHandler; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper ++import co.aikar.timings.Timing; // Paper + + public abstract class BlockEntity implements net.minecraft.server.KeyedObject { // Paper + +- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot ++ public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper + // CraftBukkit start - data containers + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); + public CraftPersistentDataContainer persistentDataContainer; +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 00ce55c17980da87a3834f952475a766543506b0..f30793b81dfd9018b4879d655c7c18a9f9c25267 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -732,6 +732,7 @@ public class LevelChunk implements ChunkAccess { + server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(this.bukkitChunk, this.needsDecoration)); + + if (this.needsDecoration) { ++ try (co.aikar.timings.Timing ignored = this.world.timings.chunkLoadPopulate.startTiming()) { // Paper + this.needsDecoration = false; + java.util.Random random = new java.util.Random(); + random.setSeed(world.getSeed()); +@@ -751,6 +752,7 @@ public class LevelChunk implements ChunkAccess { + } + } + server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); ++ } // Paper + } + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 7e13a438bd80ab5452eacf107d418c42c2e5c727..0efaf4d0f58bcf38b427e76bf09b96e354294159 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.chunk.storage; + ++import co.aikar.timings.Timings; + import com.google.common.collect.Maps; + import it.unimi.dsi.fastutil.longs.LongOpenHashSet; + import it.unimi.dsi.fastutil.longs.LongSet; +@@ -446,7 +447,6 @@ public class ChunkSerializer { + private static void postLoadChunk(CompoundTag tag, LevelChunk chunk) { + ListTag nbttaglist = tag.getList("Entities", 10); + Level world = chunk.getLevel(); +- world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot + + for (int i = 0; i < nbttaglist.size(); ++i) { + CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); +@@ -458,8 +458,6 @@ public class ChunkSerializer { + chunk.setLastSaveHadEntities(true); + } + +- world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot +- world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot + ListTag nbttaglist1 = tag.getList("TileEntities", 10); + + for (int j = 0; j < nbttaglist1.size(); ++j) { +@@ -477,8 +475,6 @@ public class ChunkSerializer { + } + } + } +- world.timings.syncChunkLoadTileEntitiesTimer.stopTiming(); // Spigot +- + } + + private static CompoundTag packStructureData(ChunkPos pos, Map, StructureStart> structureStarts, Map, LongSet> structureReferences) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 328d1e2b128b62f24917719c79823c9fb64a0dcf..c4cf1394fe4c2782b1fea8b3653a817157d857eb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2073,12 +2073,31 @@ public final class CraftServer implements Server { + private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() + { + ++ @Deprecated + @Override + public YamlConfiguration getConfig() + { + return org.spigotmc.SpigotConfig.config; + } + ++ @Override ++ public YamlConfiguration getBukkitConfig() ++ { ++ return configuration; ++ } ++ ++ @Override ++ public YamlConfiguration getSpigotConfig() ++ { ++ return org.spigotmc.SpigotConfig.config; ++ } ++ ++ @Override ++ public YamlConfiguration getPaperConfig() ++ { ++ return com.destroystokyo.paper.PaperConfig.config; ++ } ++ + @Override + public void restart() { + org.spigotmc.RestartCommand.restart(); +diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +deleted file mode 100644 +index 56b644e272ddad0e5410061e0a202daaebb734b8..0000000000000000000000000000000000000000 +--- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java ++++ /dev/null +@@ -1,163 +0,0 @@ +-package org.bukkit.craftbukkit; +- +-import java.util.HashMap; +-import net.minecraft.world.entity.Entity; +-import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.storage.PrimaryLevelData; +-import org.bukkit.craftbukkit.scheduler.CraftTask; +-import org.bukkit.plugin.java.JavaPluginLoader; +-import org.bukkit.scheduler.BukkitTask; +-import org.spigotmc.CustomTimingsHandler; +- +-public class SpigotTimings { +- +- public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); +- public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); +- public static final CustomTimingsHandler commandFunctionsTimer = new CustomTimingsHandler("Command Functions"); +- public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler"); +- public static final CustomTimingsHandler playerConnectionTimer = new CustomTimingsHandler("** PlayerConnection"); +- public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); +- public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); +- public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update"); +- public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command"); +- public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save"); +- +- public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); +- public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); +- public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); +- public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); +- +- public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); +- public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); +- public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); +- public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); +- public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); +- +- public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue"); +- public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer); +- +- public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); +- +- public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); +- public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); +- +- public static final HashMap entityTypeTimingMap = new HashMap(); +- public static final HashMap tileEntityTypeTimingMap = new HashMap(); +- public static final HashMap pluginTaskTimingMap = new HashMap(); +- +- /** +- * Gets a timer associated with a plugins tasks. +- * @param task +- * @param period +- * @return +- */ +- public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { +- if (!task.isSync()) { +- return null; +- } +- String plugin; +- final CraftTask ctask = (CraftTask) task; +- +- if (task.getOwner() != null) { +- plugin = task.getOwner().getDescription().getFullName(); +- } else { +- plugin = "Unknown"; +- } +- String taskname = ctask.getTaskName(); +- +- String name = "Task: " + plugin + " Runnable: " + taskname; +- if (period > 0) { +- name += "(interval:" + period + ")"; +- } else { +- name += "(Single)"; +- } +- CustomTimingsHandler result = pluginTaskTimingMap.get(name); +- if (result == null) { +- result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); +- pluginTaskTimingMap.put(name, result); +- } +- return result; +- } +- +- /** +- * Get a named timer for the specified entity type to track type specific timings. +- * @param entity +- * @return +- */ +- public static CustomTimingsHandler getEntityTimings(Entity entity) { +- String entityType = entity.getClass().getName(); +- CustomTimingsHandler result = entityTypeTimingMap.get(entityType); +- if (result == null) { +- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), activatedEntityTimer); +- entityTypeTimingMap.put(entityType, result); +- } +- return result; +- } +- +- /** +- * Get a named timer for the specified tile entity type to track type specific timings. +- * @param entity +- * @return +- */ +- public static CustomTimingsHandler getTileEntityTimings(BlockEntity entity) { +- String entityType = entity.getClass().getName(); +- CustomTimingsHandler result = tileEntityTypeTimingMap.get(entityType); +- if (result == null) { +- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), tickTileEntityTimer); +- tileEntityTypeTimingMap.put(entityType, result); +- } +- return result; +- } +- +- /** +- * Set of timers per world, to track world specific timings. +- */ +- public static class WorldTimingsHandler { +- public final CustomTimingsHandler mobSpawn; +- public final CustomTimingsHandler doChunkUnload; +- public final CustomTimingsHandler doTickPending; +- public final CustomTimingsHandler doTickTiles; +- public final CustomTimingsHandler doChunkMap; +- public final CustomTimingsHandler doSounds; +- public final CustomTimingsHandler entityTick; +- public final CustomTimingsHandler tileEntityTick; +- public final CustomTimingsHandler tileEntityPending; +- public final CustomTimingsHandler tracker; +- public final CustomTimingsHandler doTick; +- public final CustomTimingsHandler tickEntities; +- +- public final CustomTimingsHandler syncChunkLoadTimer; +- public final CustomTimingsHandler syncChunkLoadStructuresTimer; +- public final CustomTimingsHandler syncChunkLoadEntitiesTimer; +- public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer; +- public final CustomTimingsHandler syncChunkLoadTileTicksTimer; +- public final CustomTimingsHandler syncChunkLoadPostTimer; +- +- public WorldTimingsHandler(Level server) { +- String name = ((PrimaryLevelData) server.levelData).getLevelName() + " - "; +- +- mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); +- doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); +- doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); +- doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); +- doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); +- doSounds = new CustomTimingsHandler("** " + name + "doSounds"); +- entityTick = new CustomTimingsHandler("** " + name + "entityTick"); +- tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); +- tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending"); +- +- syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); +- syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); +- syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); +- syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); +- syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); +- syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); +- +- +- tracker = new CustomTimingsHandler(name + "tracker"); +- doTick = new CustomTimingsHandler(name + "doTick"); +- tickEntities = new CustomTimingsHandler(name + "tickEntities"); +- } +- } +-} +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 8fbf6c56d8820f3fa86e70a2636c0b58043232c3..61e2d92471d1498eb97d42dc642605a2e00e6089 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1806,6 +1806,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + packet.components = components; + getHandle().connection.send(packet); + } ++ ++ // Paper start ++ @Override ++ public int getPing() ++ { ++ return getHandle().latency; ++ } ++ // Paper end + }; + + public Player.Spigot spigot() +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 4bf48f77f3f7cd62a91590543f5af441c8268029..ffe9cc1011226d604dc5499e7692e9a9a5132b72 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.scheduler; + ++import co.aikar.timings.MinecraftTimings; // Paper + import com.google.common.util.concurrent.ThreadFactoryBuilder; + import java.util.ArrayList; + import java.util.Comparator; +@@ -179,7 +180,8 @@ public class CraftScheduler implements BukkitScheduler { + } + + public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { +- final CraftTask task = new CraftTask(run, nextId(), taskName); ++ final CraftTask task = new CraftTask(run, nextId(), "Internal - " + (taskName != null ? taskName : "Unknown")); ++ task.internal = true; + return handle(task, delay); + } + +@@ -260,7 +262,7 @@ public class CraftScheduler implements BukkitScheduler { + } + return false; + } +- }); ++ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer();}}; // Paper + handle(task, 0L); + for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { + if (taskPending == task) { +@@ -295,7 +297,7 @@ public class CraftScheduler implements BukkitScheduler { + } + } + } +- }); ++ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer(plugin);}}; // Paper + handle(task, 0L); + for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { + if (taskPending == task) { +@@ -402,9 +404,7 @@ public class CraftScheduler implements BukkitScheduler { + if (task.isSync()) { + currentTask = task; + try { +- task.timings.startTiming(); // Spigot + task.run(); +- task.timings.stopTiming(); // Spigot + } catch (final Throwable throwable) { + // Paper start + String msg = String.format( +@@ -438,8 +438,10 @@ public class CraftScheduler implements BukkitScheduler { + runners.remove(task.getTaskId()); + } + } ++ MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); + pending.addAll(temp); + temp.clear(); ++ MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); + debugHead = debugHead.getNextHead(currentTick); + } + +@@ -472,6 +474,7 @@ public class CraftScheduler implements BukkitScheduler { + } + + private void parsePending() { ++ MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); + CraftTask head = this.head; + CraftTask task = head.getNext(); + CraftTask lastTask = head; +@@ -490,6 +493,7 @@ public class CraftScheduler implements BukkitScheduler { + task.setNext(null); + } + this.head = lastTask; ++ MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); + } + + private boolean isReady(final int currentTick) { +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +index 09aa6809c5400ce8548ac902908b750ce7c964ec..3c96807e97657502849093e4371e9fef3584a346 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +@@ -1,12 +1,15 @@ + package org.bukkit.craftbukkit.scheduler; + + import java.util.function.Consumer; ++ ++import co.aikar.timings.NullTimingHandler; + import org.bukkit.Bukkit; + import org.bukkit.plugin.Plugin; + import org.bukkit.scheduler.BukkitTask; + +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.spigotmc.CustomTimingsHandler; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper ++import co.aikar.timings.Timing; // Paper + + public class CraftTask implements BukkitTask, Runnable { // Spigot + +@@ -26,12 +29,12 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + */ + private volatile long period; + private long nextRun; +- private final Runnable rTask; +- private final Consumer cTask; ++ public final Runnable rTask; // Paper ++ public final Consumer cTask; // Paper ++ public Timing timings; // Paper + private final Plugin plugin; + private final int id; + +- final CustomTimingsHandler timings; // Spigot + CraftTask() { + this(null, null, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); + } +@@ -51,7 +54,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + this.id = id; + this.period = CraftTask.NO_REPEATING; + this.taskName = taskName; +- this.timings = null; // Will be changed in later patch ++ this.timings = MinecraftTimings.getInternalTaskName(taskName); + } + // Paper end + +@@ -72,7 +75,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + } + this.id = id; + this.period = period; +- this.timings = this.isSync() ? SpigotTimings.getPluginTaskTimings(this, period) : null; // Spigot ++ timings = task != null ? MinecraftTimings.getPluginTaskTimings(this, period) : NullTimingHandler.NULL; // Paper + } + + @Override +@@ -92,11 +95,13 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + + @Override + public void run() { ++ try (Timing ignored = timings.startTiming()) { // Paper + if (rTask != null) { + rTask.run(); + } else { + cTask.accept(this); + } ++ } // Paper + } + + long getPeriod() { +@@ -123,7 +128,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + this.next = next; + } + +- Class getTaskClass() { ++ public Class getTaskClass() { + return (rTask != null) ? rTask.getClass() : ((cTask != null) ? cTask.getClass() : null); + } + +@@ -147,9 +152,4 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + return true; + } + +- // Spigot start +- public String getTaskName() { +- return (getTaskClass() == null) ? "Unknown" : getTaskClass().getName(); +- } +- // Spigot end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java +index e52ef47b783785dc214746b678e7b549aea9a274..3d90b3426873a3528af14f7f1ab0adae0027da2e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java +@@ -5,6 +5,7 @@ import org.bukkit.util.CachedServerIcon; + public class CraftIconCache implements CachedServerIcon { + public final String value; + ++ public String getData() { return value; } // Paper + public CraftIconCache(final String value) { + this.value = value; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index ec3d663886eb134eb9ecc87e7517a73bcfb9ec02..ef7715774fbdc4c42b217d8192784e09a43fe66f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -156,6 +156,12 @@ public final class CraftMagicNumbers implements UnsafeValues { + return CraftNamespacedKey.toMinecraft(mat.getKey()); + } + // ======================================================================== ++ // Paper start ++ @Override ++ public void reportTimings() { ++ co.aikar.timings.TimingsExport.reportTimings(); ++ } ++ // Paper end + + public static byte toLegacyData(BlockState data) { + return CraftLegacy.toLegacyData(data); +@@ -330,6 +336,13 @@ public final class CraftMagicNumbers implements UnsafeValues { + return clazz; + } + ++ // Paper start ++ @Override ++ public String getTimingsServerName() { ++ return com.destroystokyo.paper.PaperConfig.timingsServerName; ++ } ++ // Paper end ++ + /** + * This helper class represents the different NBT Tags. + *

+diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index ac6fc546931f7884952058b42e7e3fab3ce42998..9bb35ec64e1538aabec9ff7831706c4717239449 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -29,7 +29,7 @@ import net.minecraft.world.entity.raid.Raider; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.phys.AABB; +-import org.bukkit.craftbukkit.SpigotTimings; ++import co.aikar.timings.MinecraftTimings; + + public class ActivationRange + { +@@ -73,8 +73,8 @@ public class ActivationRange + /** + * These entities are excluded from Activation range checks. + * +- * @param entity +- * @param config ++ * @param entity Entity to initialize ++ * @param config Spigot config to determine ranges + * @return boolean If it should always tick. + */ + public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) +@@ -109,7 +109,7 @@ public class ActivationRange + */ + public static void activateEntities(Level world) + { +- SpigotTimings.entityActivationCheckTimer.startTiming(); ++ MinecraftTimings.entityActivationCheckTimer.startTiming(); + final int miscActivationRange = world.spigotConfig.miscActivationRange; + final int raiderActivationRange = world.spigotConfig.raiderActivationRange; + final int animalActivationRange = world.spigotConfig.animalActivationRange; +@@ -146,7 +146,7 @@ public class ActivationRange + } + } + } +- SpigotTimings.entityActivationCheckTimer.stopTiming(); ++ MinecraftTimings.entityActivationCheckTimer.stopTiming(); + } + + /** +@@ -243,10 +243,8 @@ public class ActivationRange + */ + public static boolean checkIfActive(Entity entity) + { +- SpigotTimings.checkIfActiveTimer.startTiming(); + // Never safe to skip fireworks or entities not yet added to chunk + if ( !entity.inChunk || entity instanceof FireworkRocketEntity ) { +- SpigotTimings.checkIfActiveTimer.stopTiming(); + return true; + } + +@@ -270,7 +268,6 @@ public class ActivationRange + { + isActive = false; + } +- SpigotTimings.checkIfActiveTimer.stopTiming(); + return isActive; + } + } diff --git a/Remapped-Spigot-Server-Patches/0010-Adventure.patch b/Remapped-Spigot-Server-Patches/0010-Adventure.patch new file mode 100644 index 0000000000..4ad53cc5f6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0010-Adventure.patch @@ -0,0 +1,3238 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Riley Park +Date: Fri, 29 Jan 2021 17:54:03 +0100 +Subject: [PATCH] Adventure + +Co-authored-by: zml +Co-authored-by: Jake Potrebic + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7..429b74474ced04d8dd8f038b8590b8dfe178bf4d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -217,4 +217,9 @@ public class PaperConfig { + " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + + " - Server Name: " + timingsServerName); + } ++ ++ public static boolean useDisplayNameInQuit = false; ++ private static void useDisplayNameInQuit() { ++ useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); ++ } + } +diff --git a/src/main/java/io/papermc/paper/adventure/AdventureComponent.java b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4b4cec054ad0146773b722c7e3708f988aeeb76d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java +@@ -0,0 +1,76 @@ ++package io.papermc.paper.adventure; ++ ++import com.google.gson.JsonElement; ++import com.google.gson.JsonSerializationContext; ++import com.google.gson.JsonSerializer; ++import java.lang.reflect.Type; ++import java.util.List; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.TextComponent; ++import net.minecraft.network.chat.MutableComponent; ++import net.minecraft.network.chat.Style; ++import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++ ++public final class AdventureComponent implements net.minecraft.network.chat.Component { ++ final Component wrapped; ++ private @MonotonicNonNull net.minecraft.network.chat.Component converted; ++ ++ public AdventureComponent(final Component wrapped) { ++ this.wrapped = wrapped; ++ } ++ ++ public net.minecraft.network.chat.Component deepConverted() { ++ net.minecraft.network.chat.Component converted = this.converted; ++ if (converted == null) { ++ converted = PaperAdventure.WRAPPER_AWARE_SERIALIZER.serialize(this.wrapped); ++ this.converted = converted; ++ } ++ return converted; ++ } ++ ++ public @Nullable net.minecraft.network.chat.Component deepConvertedIfPresent() { ++ return this.converted; ++ } ++ ++ @Override ++ public Style getStyle() { ++ return this.deepConverted().getStyle(); ++ } ++ ++ @Override ++ public String getContents() { ++ if (this.wrapped instanceof TextComponent) { ++ return ((TextComponent) this.wrapped).content(); ++ } else { ++ return this.deepConverted().getContents(); ++ } ++ } ++ ++ @Override ++ public String getString() { ++ return PaperAdventure.PLAIN.serialize(this.wrapped); ++ } ++ ++ @Override ++ public List getSiblings() { ++ return this.deepConverted().getSiblings(); ++ } ++ ++ @Override ++ public MutableComponent plainCopy() { ++ return this.deepConverted().plainCopy(); ++ } ++ ++ @Override ++ public MutableComponent copy() { ++ return this.deepConverted().copy(); ++ } ++ ++ public static class Serializer implements JsonSerializer { ++ @Override ++ public JsonElement serialize(final AdventureComponent src, final Type type, final JsonSerializationContext context) { ++ return PaperAdventure.GSON.serializer().toJsonTree(src.wrapped, Component.class); ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a29b6aaafd529e56a83dd96c32211f21e4aad348 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +@@ -0,0 +1,214 @@ ++package io.papermc.paper.adventure; ++ ++import io.papermc.paper.chat.ChatRenderer; ++import io.papermc.paper.event.player.AbstractChatEvent; ++import io.papermc.paper.event.player.AsyncChatEvent; ++import io.papermc.paper.event.player.ChatEvent; ++import java.util.Set; ++import java.util.concurrent.ExecutionException; ++import java.util.function.Consumer; ++import java.util.regex.Pattern; ++ ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.audience.MessageType; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.TextReplacementConfig; ++import net.kyori.adventure.text.event.ClickEvent; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.LazyPlayerSet; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.AsyncPlayerChatEvent; ++import org.bukkit.event.player.PlayerChatEvent; ++ ++public final class ChatProcessor { ++ // <-- copied from adventure-text-serializer-legacy ++ private static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?"); ++ private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("^[a-z][a-z0-9+\\-.]*:"); ++ private static final TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder() ++ .match(DEFAULT_URL_PATTERN) ++ .replacement(url -> { ++ String clickUrl = url.content(); ++ if (!URL_SCHEME_PATTERN.matcher(clickUrl).find()) { ++ clickUrl = "http://" + clickUrl; ++ } ++ return url.clickEvent(ClickEvent.openUrl(clickUrl)); ++ }) ++ .build(); ++ // copied from adventure-text-serializer-legacy --> ++ final MinecraftServer server; ++ final ServerPlayer player; ++ final String message; ++ final boolean async; ++ final Component originalMessage; ++ ++ public ChatProcessor(final MinecraftServer server, final ServerPlayer player, final String message, final boolean async) { ++ this.server = server; ++ this.player = player; ++ this.message = message; ++ this.async = async; ++ this.originalMessage = Component.text(message); ++ } ++ ++ @SuppressWarnings({"CodeBlock2Expr", "deprecated"}) ++ public void process() { ++ this.processingLegacyFirst( ++ // continuing from AsyncPlayerChatEvent (without PlayerChatEvent) ++ event -> { ++ this.processModern( ++ legacyRenderer(event.getFormat()), ++ event.getRecipients(), ++ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), ++ event.isCancelled() ++ ); ++ }, ++ // continuing from AsyncPlayerChatEvent and PlayerChatEvent ++ event -> { ++ this.processModern( ++ legacyRenderer(event.getFormat()), ++ event.getRecipients(), ++ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), ++ event.isCancelled() ++ ); ++ }, ++ // no legacy events called, all nice and fresh! ++ () -> { ++ this.processModern( ++ ChatRenderer.defaultRenderer(), ++ new LazyPlayerSet(this.server), ++ Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG), ++ false ++ ); ++ } ++ ); ++ } ++ ++ @SuppressWarnings("deprecation") ++ private void processingLegacyFirst( ++ final Consumer continueAfterAsync, ++ final Consumer continueAfterAsyncAndSync, ++ final Runnable modernOnly ++ ) { ++ final boolean listenersOnAsyncEvent = anyListeners(AsyncPlayerChatEvent.getHandlerList()); ++ final boolean listenersOnSyncEvent = anyListeners(PlayerChatEvent.getHandlerList()); ++ if (listenersOnAsyncEvent || listenersOnSyncEvent) { ++ final CraftPlayer player = this.player.getBukkitEntity(); ++ final AsyncPlayerChatEvent ae = new AsyncPlayerChatEvent(this.async, player, this.message, new LazyPlayerSet(this.server)); ++ post(ae); ++ if (listenersOnSyncEvent) { ++ final PlayerChatEvent se = new PlayerChatEvent(player, ae.getMessage(), ae.getFormat(), ae.getRecipients()); ++ se.setCancelled(ae.isCancelled()); // propagate cancelled state ++ this.queueIfAsyncOrRunImmediately(new Waitable() { ++ @Override ++ protected Void evaluate() { ++ post(se); ++ return null; ++ } ++ }); ++ continueAfterAsyncAndSync.accept(se); ++ } else { ++ continueAfterAsync.accept(ae); ++ } ++ } else { ++ modernOnly.run(); ++ } ++ } ++ ++ private void processModern(final ChatRenderer renderer, final Set recipients, final Component message, final boolean cancelled) { ++ final AsyncChatEvent ae = this.createAsync(renderer, recipients, new LazyChatAudienceSet(), message); ++ ae.setCancelled(cancelled); // propagate cancelled state ++ post(ae); ++ final boolean listenersOnSyncEvent = anyListeners(ChatEvent.getHandlerList()); ++ if (listenersOnSyncEvent) { ++ this.continueWithSyncFromWhereAsyncLeftOff(ae); ++ } else { ++ this.complete(ae); ++ } ++ } ++ ++ private void continueWithSyncFromWhereAsyncLeftOff(final AsyncChatEvent ae) { ++ this.queueIfAsyncOrRunImmediately(new Waitable() { ++ @Override ++ protected Void evaluate() { ++ final ChatEvent se = ChatProcessor.this.createSync(ae.renderer(), ae.recipients(), ae.viewers(), ae.message()); ++ se.setCancelled(ae.isCancelled()); // propagate cancelled state ++ post(se); ++ ChatProcessor.this.complete(se); ++ return null; ++ } ++ }); ++ } ++ ++ private void complete(final AbstractChatEvent event) { ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ final CraftPlayer player = this.player.getBukkitEntity(); ++ final Component displayName = displayName(player); ++ final Component message = event.message(); ++ final ChatRenderer renderer = event.renderer(); ++ ++ final Set viewers = event.viewers(); ++ final Set recipients = event.recipients(); ++ if (viewers instanceof LazyChatAudienceSet && recipients instanceof LazyPlayerSet && ++ (!((LazyChatAudienceSet) viewers).isLazy() || ((LazyPlayerSet) recipients).isLazy())) { ++ for (final Audience viewer : viewers) { ++ viewer.sendMessage(player, renderer.render(player, displayName, message, viewer), MessageType.CHAT); ++ } ++ } else { ++ this.server.console.sendMessage(player, renderer.render(player, displayName, message, this.server.console), MessageType.CHAT); ++ for (final Player recipient : recipients) { ++ recipient.sendMessage(player, renderer.render(player, displayName, message, recipient), MessageType.CHAT); ++ } ++ } ++ } ++ ++ private AsyncChatEvent createAsync(final ChatRenderer renderer, final Set recipients, final Set viewers, final Component message) { ++ return new AsyncChatEvent(this.async, this.player.getBukkitEntity(), recipients, viewers, renderer, message, this.originalMessage); ++ } ++ ++ private ChatEvent createSync(final ChatRenderer renderer, final Set recipients, final Set viewers, final Component message) { ++ return new ChatEvent(this.player.getBukkitEntity(), recipients, viewers, renderer, message, this.originalMessage); ++ } ++ ++ private static String legacyDisplayName(final CraftPlayer player) { ++ return player.getDisplayName(); ++ } ++ ++ private static Component displayName(final CraftPlayer player) { ++ return player.displayName(); ++ } ++ ++ private static ChatRenderer legacyRenderer(final String format) { ++ return (player, displayName, message, recipient) -> PaperAdventure.LEGACY_SECTION_UXRC.deserialize(String.format(format, legacyDisplayName((CraftPlayer) player), PaperAdventure.LEGACY_SECTION_UXRC.serialize(message))).replaceText(URL_REPLACEMENT_CONFIG); ++ } ++ ++ private void queueIfAsyncOrRunImmediately(final Waitable waitable) { ++ if (this.async) { ++ this.server.processQueue.add(waitable); ++ } else { ++ waitable.run(); ++ } ++ try { ++ waitable.get(); ++ } catch (final InterruptedException e) { ++ Thread.currentThread().interrupt(); // tag, you're it ++ } catch (final ExecutionException e) { ++ throw new RuntimeException("Exception processing chat", e.getCause()); ++ } ++ } ++ ++ private static void post(final Event event) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ ++ private static boolean anyListeners(final HandlerList handlers) { ++ return handlers.getRegisteredListeners().length > 0; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/DisplayNames.java b/src/main/java/io/papermc/paper/adventure/DisplayNames.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bfaf5d3c5aae8a587c2b11d90089c588b2a2aba0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/DisplayNames.java +@@ -0,0 +1,22 @@ ++package io.papermc.paper.adventure; ++ ++import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.ChatColor; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++ ++public final class DisplayNames { ++ private DisplayNames() { ++ } ++ ++ public static String getLegacy(final CraftPlayer player) { ++ return getLegacy(player.getHandle()); ++ } ++ ++ public static String getLegacy(final ServerPlayer player) { ++ final String legacy = player.displayName; ++ if (legacy != null) { ++ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName) + ChatColor.getLastColors(player.displayName); ++ } ++ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..10f08e2b73610ab06928d1f63348920fef8e91fa +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java +@@ -0,0 +1,21 @@ ++package io.papermc.paper.adventure; ++ ++import net.kyori.adventure.audience.Audience; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.util.LazyHashSet; ++import org.bukkit.craftbukkit.util.LazyPlayerSet; ++import org.bukkit.entity.Player; ++ ++import java.util.HashSet; ++import java.util.Set; ++ ++final class LazyChatAudienceSet extends LazyHashSet { ++ @Override ++ protected Set makeReference() { ++ final Set playerSet = LazyPlayerSet.makePlayerSet(MinecraftServer.getServer()); ++ final HashSet audiences = new HashSet<>(playerSet); ++ audiences.add(Bukkit.getConsoleSender()); ++ return audiences; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..eeedc30a45d9637d68f04f185b3dd90dd711b9e0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java +@@ -0,0 +1,88 @@ ++package io.papermc.paper.adventure; ++ ++import com.mojang.brigadier.exceptions.CommandSyntaxException; ++import java.io.IOException; ++import java.util.UUID; ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.nbt.api.BinaryTagHolder; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.event.HoverEvent; ++import net.kyori.adventure.text.serializer.gson.LegacyHoverEventSerializer; ++import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; ++import net.kyori.adventure.util.Codec; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.nbt.TagParser; ++ ++final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer { ++ public static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer(); ++ private static final Codec SNBT_CODEC = Codec.of(TagParser::parseTag, Tag::toString); ++ ++ static final String ITEM_TYPE = "id"; ++ static final String ITEM_COUNT = "Count"; ++ static final String ITEM_TAG = "tag"; ++ ++ static final String ENTITY_NAME = "name"; ++ static final String ENTITY_TYPE = "type"; ++ static final String ENTITY_ID = "id"; ++ ++ NBTLegacyHoverEventSerializer() { ++ } ++ ++ @Override ++ public HoverEvent.ShowItem deserializeShowItem(final Component input) throws IOException { ++ final String raw = PlainComponentSerializer.plain().serialize(input); ++ try { ++ final CompoundTag contents = SNBT_CODEC.decode(raw); ++ final CompoundTag tag = contents.getCompound(ITEM_TAG); ++ return HoverEvent.ShowItem.of( ++ Key.key(contents.getString(ITEM_TYPE)), ++ contents.contains(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1, ++ tag.isEmpty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC) ++ ); ++ } catch (final CommandSyntaxException ex) { ++ throw new IOException(ex); ++ } ++ } ++ ++ @Override ++ public HoverEvent.ShowEntity deserializeShowEntity(final Component input, final Codec.Decoder componentCodec) throws IOException { ++ final String raw = PlainComponentSerializer.plain().serialize(input); ++ try { ++ final CompoundTag contents = SNBT_CODEC.decode(raw); ++ return HoverEvent.ShowEntity.of( ++ Key.key(contents.getString(ENTITY_TYPE)), ++ UUID.fromString(contents.getString(ENTITY_ID)), ++ componentCodec.decode(contents.getString(ENTITY_NAME)) ++ ); ++ } catch (final CommandSyntaxException ex) { ++ throw new IOException(ex); ++ } ++ } ++ ++ @Override ++ public Component serializeShowItem(final HoverEvent.ShowItem input) throws IOException { ++ final CompoundTag tag = new CompoundTag(); ++ tag.putString(ITEM_TYPE, input.item().asString()); ++ tag.putByte(ITEM_COUNT, (byte) input.count()); ++ if (input.nbt() != null) { ++ try { ++ tag.put(ITEM_TAG, input.nbt().get(SNBT_CODEC)); ++ } catch (final CommandSyntaxException ex) { ++ throw new IOException(ex); ++ } ++ } ++ return Component.text(SNBT_CODEC.encode(tag)); ++ } ++ ++ @Override ++ public Component serializeShowEntity(final HoverEvent.ShowEntity input, final Codec.Encoder componentCodec) throws IOException { ++ final CompoundTag tag = new CompoundTag(); ++ tag.putString(ENTITY_ID, input.id().toString()); ++ tag.putString(ENTITY_TYPE, input.type().asString()); ++ if (input.name() != null) { ++ tag.putString(ENTITY_NAME, componentCodec.encode(input.name())); ++ } ++ return Component.text(SNBT_CODEC.encode(tag)); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java +new file mode 100644 +index 0000000000000000000000000000000000000000..696b7ad89af4e379d7b8f1961d1ab0cba1c3313f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java +@@ -0,0 +1,342 @@ ++package io.papermc.paper.adventure; ++ ++import com.mojang.brigadier.exceptions.CommandSyntaxException; ++import io.netty.util.AttributeKey; ++import java.io.IOException; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Locale; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++import net.kyori.adventure.bossbar.BossBar; ++import net.kyori.adventure.inventory.Book; ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.nbt.api.BinaryTagHolder; ++import net.kyori.adventure.sound.Sound; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.TranslatableComponent; ++import net.kyori.adventure.text.flattener.ComponentFlattener; ++import net.kyori.adventure.text.format.TextColor; ++import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; ++import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; ++import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; ++import net.kyori.adventure.translation.GlobalTranslator; ++import net.kyori.adventure.util.Codec; ++import net.minecraft.ChatFormatting; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.StringTag; ++import net.minecraft.nbt.TagParser; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.world.BossEvent; ++import net.minecraft.world.item.ItemStack; ++import org.bukkit.ChatColor; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++ ++public final class PaperAdventure { ++ public static final AttributeKey LOCALE_ATTRIBUTE = AttributeKey.valueOf("adventure:locale"); ++ private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s"); ++ public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder() ++ .complexMapper(TranslatableComponent.class, (translatable, consumer) -> { ++ final @NonNull String translated = LocaleLanguage.a().a(translatable.key()); ++ ++ final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated); ++ final List args = translatable.args(); ++ int argPosition = 0; ++ int lastIdx = 0; ++ while (matcher.find()) { ++ // append prior ++ if (lastIdx < matcher.start()) { ++ consumer.accept(Component.text(translated.substring(lastIdx, matcher.start()))); ++ } ++ lastIdx = matcher.end(); ++ ++ final @Nullable String argIdx = matcher.group(1); ++ // calculate argument position ++ if (argIdx != null) { ++ try { ++ final int idx = Integer.parseInt(argIdx) - 1; ++ if (idx < args.size()) { ++ consumer.accept(args.get(idx)); ++ } ++ } catch (final NumberFormatException ex) { ++ // ignore, drop the format placeholder ++ } ++ } else { ++ final int idx = argPosition++; ++ if (idx < args.size()) { ++ consumer.accept(args.get(idx)); ++ } ++ } ++ } ++ ++ // append tail ++ if (lastIdx < translated.length()) { ++ consumer.accept(Component.text(translated.substring(lastIdx))); ++ } ++ }) ++ .build(); ++ public static final LegacyComponentSerializer LEGACY_SECTION_UXRC = LegacyComponentSerializer.builder().flattener(FLATTENER).hexColors().useUnusualXRepeatedCharacterHexFormat().build(); ++ public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build(); ++ public static final GsonComponentSerializer GSON = GsonComponentSerializer.builder() ++ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) ++ .build(); ++ public static final GsonComponentSerializer COLOR_DOWNSAMPLING_GSON = GsonComponentSerializer.builder() ++ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) ++ .downsampleColors() ++ .build(); ++ private static final Codec NBT_CODEC = new Codec() { ++ @Override ++ public @NonNull CompoundTag decode(final @NonNull String encoded) throws IOException { ++ try { ++ return TagParser.parseTag(encoded); ++ } catch (final CommandSyntaxException e) { ++ throw new IOException(e); ++ } ++ } ++ ++ @Override ++ public @NonNull String encode(final @NonNull CompoundTag decoded) { ++ return decoded.toString(); ++ } ++ }; ++ static final WrapperAwareSerializer WRAPPER_AWARE_SERIALIZER = new WrapperAwareSerializer(); ++ ++ private PaperAdventure() { ++ } ++ ++ // Key ++ ++ public static ResourceLocation asVanilla(final Key key) { ++ return new ResourceLocation(key.namespace(), key.value()); ++ } ++ ++ public static ResourceLocation asVanillaNullable(final Key key) { ++ if (key == null) { ++ return null; ++ } ++ return new ResourceLocation(key.namespace(), key.value()); ++ } ++ ++ // Component ++ ++ public static Component asAdventure(final net.minecraft.network.chat.Component component) { ++ return component == null ? Component.empty() : GSON.serializer().fromJson(net.minecraft.network.chat.Component.Serializer.toJsonTree(component), Component.class); ++ } ++ ++ public static ArrayList asAdventure(final List vanillas) { ++ final ArrayList adventures = new ArrayList<>(vanillas.size()); ++ for (final net.minecraft.network.chat.Component vanilla : vanillas) { ++ adventures.add(asAdventure(vanilla)); ++ } ++ return adventures; ++ } ++ ++ public static ArrayList asAdventureFromJson(final List jsonStrings) { ++ final ArrayList adventures = new ArrayList<>(jsonStrings.size()); ++ for (final String json : jsonStrings) { ++ adventures.add(GsonComponentSerializer.gson().deserialize(json)); ++ } ++ return adventures; ++ } ++ ++ public static List asJson(final List adventures) { ++ final List jsons = new ArrayList<>(adventures.size()); ++ for (final Component component : adventures) { ++ jsons.add(GsonComponentSerializer.gson().serialize(component)); ++ } ++ return jsons; ++ } ++ ++ public static net.minecraft.network.chat.Component asVanilla(final Component component) { ++ if (true) return new AdventureComponent(component); ++ return net.minecraft.network.chat.Component.Serializer.fromJsonTree(GSON.serializer().toJsonTree(component)); ++ } ++ ++ public static List asVanilla(final List adventures) { ++ final List vanillas = new ArrayList<>(adventures.size()); ++ for (final Component adventure : adventures) { ++ vanillas.add(asVanilla(adventure)); ++ } ++ return vanillas; ++ } ++ ++ public static String asJsonString(final Component component, final Locale locale) { ++ return GSON.serialize( ++ GlobalTranslator.render( ++ component, ++ // play it safe ++ locale != null ++ ? locale ++ : Locale.US ++ ) ++ ); ++ } ++ ++ public static String asJsonString(final net.minecraft.network.chat.Component component, final Locale locale) { ++ if (component instanceof AdventureComponent) { ++ return asJsonString(((AdventureComponent) component).wrapped, locale); ++ } ++ return net.minecraft.network.chat.Component.Serializer.componentToJson(component); ++ } ++ ++ // thank you for being worse than wet socks, Bukkit ++ public static String superHackyLegacyRepresentationOfComponent(final Component component, final String string) { ++ return LEGACY_SECTION_UXRC.serialize(component) + ChatColor.getLastColors(string); ++ } ++ ++ // BossBar ++ ++ public static BossEvent.BossBarColor asVanilla(final BossBar.Color color) { ++ if (color == BossBar.Color.PINK) { ++ return BossEvent.BossBarColor.PINK; ++ } else if (color == BossBar.Color.BLUE) { ++ return BossEvent.BossBarColor.BLUE; ++ } else if (color == BossBar.Color.RED) { ++ return BossEvent.BossBarColor.RED; ++ } else if (color == BossBar.Color.GREEN) { ++ return BossEvent.BossBarColor.GREEN; ++ } else if (color == BossBar.Color.YELLOW) { ++ return BossEvent.BossBarColor.YELLOW; ++ } else if (color == BossBar.Color.PURPLE) { ++ return BossEvent.BossBarColor.PURPLE; ++ } else if (color == BossBar.Color.WHITE) { ++ return BossEvent.BossBarColor.WHITE; ++ } ++ throw new IllegalArgumentException(color.name()); ++ } ++ ++ public static BossBar.Color asAdventure(final BossEvent.BossBarColor color) { ++ if(color == BossEvent.BossBarColor.PINK) { ++ return BossBar.Color.PINK; ++ } else if(color == BossEvent.BossBarColor.BLUE) { ++ return BossBar.Color.BLUE; ++ } else if(color == BossEvent.BossBarColor.RED) { ++ return BossBar.Color.RED; ++ } else if(color == BossEvent.BossBarColor.GREEN) { ++ return BossBar.Color.GREEN; ++ } else if(color == BossEvent.BossBarColor.YELLOW) { ++ return BossBar.Color.YELLOW; ++ } else if(color == BossEvent.BossBarColor.PURPLE) { ++ return BossBar.Color.PURPLE; ++ } else if(color == BossEvent.BossBarColor.WHITE) { ++ return BossBar.Color.WHITE; ++ } ++ throw new IllegalArgumentException(color.name()); ++ } ++ ++ public static BossEvent.BossBarOverlay asVanilla(final BossBar.Overlay overlay) { ++ if (overlay == BossBar.Overlay.PROGRESS) { ++ return BossEvent.BossBarOverlay.PROGRESS; ++ } else if (overlay == BossBar.Overlay.NOTCHED_6) { ++ return BossEvent.BossBarOverlay.NOTCHED_6; ++ } else if (overlay == BossBar.Overlay.NOTCHED_10) { ++ return BossEvent.BossBarOverlay.NOTCHED_10; ++ } else if (overlay == BossBar.Overlay.NOTCHED_12) { ++ return BossEvent.BossBarOverlay.NOTCHED_12; ++ } else if (overlay == BossBar.Overlay.NOTCHED_20) { ++ return BossEvent.BossBarOverlay.NOTCHED_20; ++ } ++ throw new IllegalArgumentException(overlay.name()); ++ } ++ ++ public static BossBar.Overlay asAdventure(final BossEvent.BossBarOverlay overlay) { ++ if (overlay == BossEvent.BossBarOverlay.PROGRESS) { ++ return BossBar.Overlay.PROGRESS; ++ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_6) { ++ return BossBar.Overlay.NOTCHED_6; ++ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_10) { ++ return BossBar.Overlay.NOTCHED_10; ++ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_12) { ++ return BossBar.Overlay.NOTCHED_12; ++ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_20) { ++ return BossBar.Overlay.NOTCHED_20; ++ } ++ throw new IllegalArgumentException(overlay.name()); ++ } ++ ++ public static void setFlag(final BossBar bar, final BossBar.Flag flag, final boolean value) { ++ if (value) { ++ bar.addFlag(flag); ++ } else { ++ bar.removeFlag(flag); ++ } ++ } ++ ++ // Book ++ ++ public static ItemStack asItemStack(final Book book, final Locale locale) { ++ final ItemStack item = new ItemStack(net.minecraft.world.item.Items.WRITTEN_BOOK, 1); ++ final CompoundTag tag = item.getOrCreateTag(); ++ tag.putString("title", asJsonString(book.title(), locale)); ++ tag.putString("author", asJsonString(book.author(), locale)); ++ final ListTag pages = new ListTag(); ++ for (final Component page : book.pages()) { ++ pages.add(StringTag.create(asJsonString(page, locale))); ++ } ++ tag.put("pages", pages); ++ return item; ++ } ++ ++ // Sounds ++ ++ public static SoundSource asVanilla(final Sound.Source source) { ++ if (source == Sound.Source.MASTER) { ++ return SoundSource.MASTER; ++ } else if (source == Sound.Source.MUSIC) { ++ return SoundSource.MUSIC; ++ } else if (source == Sound.Source.RECORD) { ++ return SoundSource.RECORDS; ++ } else if (source == Sound.Source.WEATHER) { ++ return SoundSource.WEATHER; ++ } else if (source == Sound.Source.BLOCK) { ++ return SoundSource.BLOCKS; ++ } else if (source == Sound.Source.HOSTILE) { ++ return SoundSource.HOSTILE; ++ } else if (source == Sound.Source.NEUTRAL) { ++ return SoundSource.NEUTRAL; ++ } else if (source == Sound.Source.PLAYER) { ++ return SoundSource.PLAYERS; ++ } else if (source == Sound.Source.AMBIENT) { ++ return SoundSource.AMBIENT; ++ } else if (source == Sound.Source.VOICE) { ++ return SoundSource.VOICE; ++ } ++ throw new IllegalArgumentException(source.name()); ++ } ++ ++ public static @Nullable SoundSource asVanillaNullable(final Sound.@Nullable Source source) { ++ if (source == null) { ++ return null; ++ } ++ return asVanilla(source); ++ } ++ ++ // NBT ++ ++ public static @Nullable BinaryTagHolder asBinaryTagHolder(final @Nullable CompoundTag tag) { ++ if (tag == null) { ++ return null; ++ } ++ try { ++ return BinaryTagHolder.encode(tag, NBT_CODEC); ++ } catch (final IOException e) { ++ return null; ++ } ++ } ++ ++ // Colors ++ ++ public static @NonNull TextColor asAdventure(ChatFormatting minecraftColor) { ++ if (minecraftColor.getColor() == null) { ++ throw new IllegalArgumentException("Not a valid color"); ++ } ++ return TextColor.color(minecraftColor.getColor()); ++ } ++ ++ public static @Nullable ChatFormatting asVanilla(TextColor color) { ++ return ChatFormatting.getByHexValue(color.value()); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ee6d9d5c072d68cace63068a8e2ed603ad475378 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java +@@ -0,0 +1,41 @@ ++package io.papermc.paper.adventure; ++ ++import java.util.Set; ++import java.util.function.Consumer; ++import net.kyori.adventure.bossbar.BossBar; ++import net.kyori.adventure.text.Component; ++import net.minecraft.network.protocol.game.ClientboundBossEventPacket; ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++public final class VanillaBossBarListener implements BossBar.Listener { ++ private final Consumer action; ++ ++ public VanillaBossBarListener(final Consumer action) { ++ this.action = action; ++ } ++ ++ @Override ++ public void bossBarNameChanged(final @NonNull BossBar bar, final @NonNull Component oldName, final @NonNull Component newName) { ++ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_NAME); ++ } ++ ++ @Override ++ public void bossBarProgressChanged(final @NonNull BossBar bar, final float oldProgress, final float newProgress) { ++ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_PCT); ++ } ++ ++ @Override ++ public void bossBarColorChanged(final @NonNull BossBar bar, final BossBar.@NonNull Color oldColor, final BossBar.@NonNull Color newColor) { ++ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_STYLE); ++ } ++ ++ @Override ++ public void bossBarOverlayChanged(final @NonNull BossBar bar, final BossBar.@NonNull Overlay oldOverlay, final BossBar.@NonNull Overlay newOverlay) { ++ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_STYLE); ++ } ++ ++ @Override ++ public void bossBarFlagsChanged(final @NonNull BossBar bar, final @NonNull Set flagsAdded, final @NonNull Set flagsRemoved) { ++ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_PROPERTIES); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2e93ac0eb74a89c020f3356f77320cf6459727fd +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java +@@ -0,0 +1,19 @@ ++package io.papermc.paper.adventure; ++ ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.serializer.ComponentSerializer; ++ ++final class WrapperAwareSerializer implements ComponentSerializer { ++ @Override ++ public Component deserialize(final net.minecraft.network.chat.Component input) { ++ if (input instanceof AdventureComponent) { ++ return ((AdventureComponent) input).wrapped; ++ } ++ return PaperAdventure.GSON.serializer().fromJson(net.minecraft.network.chat.Component.Serializer.toJsonTree(input), Component.class); ++ } ++ ++ @Override ++ public net.minecraft.network.chat.Component serialize(final Component component) { ++ return net.minecraft.network.chat.Component.Serializer.fromJsonTree(PaperAdventure.GSON.serializer().toJsonTree(component)); ++ } ++} +diff --git a/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2dc92d8d2764d3e9b621d5c7d5e30c30367b3117 +--- /dev/null ++++ b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java +@@ -0,0 +1,36 @@ ++package net.kyori.adventure.bossbar; ++ ++import io.papermc.paper.adventure.PaperAdventure; ++import io.papermc.paper.adventure.VanillaBossBarListener; ++import net.minecraft.server.level.ServerBossEvent; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++ ++public abstract class HackyBossBarPlatformBridge { ++ public ServerBossEvent vanilla$bar; ++ private VanillaBossBarListener vanilla$listener; ++ ++ public final void paper$playerShow(final CraftPlayer player) { ++ if (this.vanilla$bar == null) { ++ final BossBar $this = (BossBar) this; ++ this.vanilla$bar = new ServerBossEvent( ++ PaperAdventure.asVanilla($this.name()), ++ PaperAdventure.asVanilla($this.color()), ++ PaperAdventure.asVanilla($this.overlay()) ++ ); ++ this.vanilla$bar.adventure = $this; ++ this.vanilla$listener = new VanillaBossBarListener(this.vanilla$bar::broadcast); ++ $this.addListener(this.vanilla$listener); ++ } ++ this.vanilla$bar.addPlayer(player.getHandle()); ++ } ++ ++ public final void paper$playerHide(final CraftPlayer player) { ++ if (this.vanilla$bar != null) { ++ this.vanilla$bar.removePlayer(player.getHandle()); ++ if (this.vanilla$bar.getPlayers().isEmpty()) { ++ ((BossBar) this).removeListener(this.vanilla$listener); ++ this.vanilla$bar = null; ++ } ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/ChatFormatting.java b/src/main/java/net/minecraft/ChatFormatting.java +index e888a90226c30757b190a3b89a56c1a312f32850..1720eba650c959810c6e4a3522979e75e10a1bb8 100644 +--- a/src/main/java/net/minecraft/ChatFormatting.java ++++ b/src/main/java/net/minecraft/ChatFormatting.java +@@ -61,6 +61,7 @@ public enum ChatFormatting { + return !this.isFormat && this != ChatFormatting.RESET; + } + ++ @Nullable public Integer getHexValue() { return this.getColor(); } // Paper - OBFHELPER + @Nullable + public Integer getColor() { + return this.color; +@@ -84,6 +85,18 @@ public enum ChatFormatting { + return name == null ? null : (ChatFormatting) ChatFormatting.FORMATTING_BY_NAME.get(cleanName(name)); + } + ++ // Paper start ++ @Nullable public static ChatFormatting getByHexValue(int i) { ++ for (ChatFormatting value : values()) { ++ if (value.getHexValue() != null && value.getHexValue() == i) { ++ return value; ++ } ++ } ++ ++ return null; ++ } ++ // Paper end ++ + @Nullable + public static ChatFormatting getById(int colorIndex) { + if (colorIndex < 0) { +diff --git a/src/main/java/net/minecraft/nbt/StringTag.java b/src/main/java/net/minecraft/nbt/StringTag.java +index 620e10b5ba9e57ff4d0d7967bf4240fafadb2be7..dab8983fa65b97ecf0fe20fdc06cc8ec60d8fe95 100644 +--- a/src/main/java/net/minecraft/nbt/StringTag.java ++++ b/src/main/java/net/minecraft/nbt/StringTag.java +@@ -43,6 +43,7 @@ public class StringTag implements Tag { + this.data = value; + } + ++ public static StringTag create(final String value) { return valueOf(value); } // Paper - OBFHELPER + public static StringTag valueOf(String value) { + return value.isEmpty() ? StringTag.EMPTY : new StringTag(value); + } +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index 50f14acb062c2f90266279dbd1945a3297396f0b..59788eaef0dae5ee01ceba1bf45e85cb07f88e53 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -10,6 +10,7 @@ import io.netty.buffer.ByteBufOutputStream; + import io.netty.handler.codec.DecoderException; + import io.netty.handler.codec.EncoderException; + import io.netty.util.ByteProcessor; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.io.DataInput; + import java.io.DataOutput; + import java.io.IOException; +@@ -43,6 +44,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit + public class FriendlyByteBuf extends ByteBuf { + + private final ByteBuf source; ++ public java.util.Locale adventure$locale; // Paper + + public FriendlyByteBuf(ByteBuf bytebuf) { + this.source = bytebuf; +@@ -164,8 +166,15 @@ public class FriendlyByteBuf extends ByteBuf { + return Component.Serializer.fromJson(this.readUtf(262144)); + } + ++ // Paper start ++ public FriendlyByteBuf writeComponent(final net.kyori.adventure.text.Component component) { ++ return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); ++ } ++ // Paper end ++ + public FriendlyByteBuf writeComponent(Component text) { +- return this.writeUtf(Component.Serializer.toJson(text), 262144); ++ //return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); // Paper - comment ++ return this.writeUtf(PaperAdventure.asJsonString(text, this.adventure$locale), 262144); // Paper + } + + public > T readEnum(Class oclass) { +@@ -348,6 +357,7 @@ public class FriendlyByteBuf extends ByteBuf { + return this.writeUtf(s, 32767); + } + ++ public FriendlyByteBuf writeUtf(final String string, final int maxLength) { return this.writeUtf(string, maxLength); } // Paper - OBFHELPER + public FriendlyByteBuf writeUtf(String s, int i) { + byte[] abyte = s.getBytes(StandardCharsets.UTF_8); + +diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java +index 14fa1371e52b9af5a7550a9aa144fa406b754046..d36d0424bcd4811af892f5f76fdcefda2af1ad33 100644 +--- a/src/main/java/net/minecraft/network/PacketEncoder.java ++++ b/src/main/java/net/minecraft/network/PacketEncoder.java +@@ -3,6 +3,7 @@ package net.minecraft.network; + import io.netty.buffer.ByteBuf; + import io.netty.channel.ChannelHandlerContext; + import io.netty.handler.codec.MessageToByteEncoder; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.io.IOException; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketFlow; +@@ -37,6 +38,7 @@ public class PacketEncoder extends MessageToByteEncoder> { + throw new IOException("Can't serialize unregistered packet"); + } else { + FriendlyByteBuf packetdataserializer = new FriendlyByteBuf(bytebuf); ++ packetdataserializer.adventure$locale = channelhandlercontext.channel().attr(PaperAdventure.LOCALE_ATTRIBUTE).get(); // Paper + + packetdataserializer.writeVarInt(integer); + +diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java +index 819ea90ea116dea396c225539fc0fbebd6176ba5..54d186a195aca6d0a4c412ed609d8c86dcc76072 100644 +--- a/src/main/java/net/minecraft/network/chat/Component.java ++++ b/src/main/java/net/minecraft/network/chat/Component.java +@@ -1,5 +1,6 @@ + package net.minecraft.network.chat; + ++import io.papermc.paper.adventure.AdventureComponent; // Paper + import com.google.gson.Gson; + import com.google.gson.GsonBuilder; + import com.google.gson.JsonArray; +@@ -110,6 +111,7 @@ public interface Component extends Message, FormattedText, Iterable { + GsonBuilder gsonbuilder = new GsonBuilder(); + + gsonbuilder.disableHtmlEscaping(); ++ gsonbuilder.registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()); // Paper + gsonbuilder.registerTypeHierarchyAdapter(Component.class, new Component.Serializer()); + gsonbuilder.registerTypeHierarchyAdapter(Style.class, new Style.Serializer()); + gsonbuilder.registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()); +@@ -262,6 +264,7 @@ public interface Component extends Message, FormattedText, Iterable { + } + + public JsonElement serialize(Component ichatbasecomponent, Type type, JsonSerializationContext jsonserializationcontext) { ++ if (ichatbasecomponent instanceof AdventureComponent) return jsonserializationcontext.serialize(ichatbasecomponent); // Paper + JsonObject jsonobject = new JsonObject(); + + if (!ichatbasecomponent.getStyle().isEmpty()) { +@@ -350,10 +353,12 @@ public interface Component extends Message, FormattedText, Iterable { + return jsonobject; + } + ++ public static String componentToJson(final Component component) { return toJson(component); } // Paper - OBFHELPER + public static String toJson(Component text) { + return Component.Serializer.GSON.toJson(text); + } + ++ public static JsonElement toJsonTree(final Component component) { return toJsonTree(component); } // Paper - OBFHELPER + public static JsonElement toJsonTree(Component text) { + return Component.Serializer.GSON.toJsonTree(text); + } +@@ -363,6 +368,7 @@ public interface Component extends Message, FormattedText, Iterable { + return (MutableComponent) GsonHelper.fromJson(Component.Serializer.GSON, json, MutableComponent.class, false); + } + ++ public static @Nullable Component fromJsonTree(final JsonElement json) { return fromJson(json); } // Paper - OBFHELPER + @Nullable + public static MutableComponent fromJson(JsonElement json) { + return (MutableComponent) Component.Serializer.GSON.fromJson(json, MutableComponent.class); +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +index ce64931b5c363352f03baddbc747246469d56a84..e47102cadb40ed8a9c011386445f15fd30de7596 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +@@ -11,6 +11,7 @@ import net.minecraft.network.protocol.Packet; + public class ClientboundChatPacket implements Packet { + + private Component message; ++ public net.kyori.adventure.text.Component adventure$message; // Paper + public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot + private ChatType type; + private UUID sender; +@@ -32,6 +33,11 @@ public class ClientboundChatPacket implements Packet { + + @Override + public void write(FriendlyByteBuf buf) throws IOException { ++ // Paper start ++ if (this.adventure$message != null) { ++ buf.writeComponent(this.adventure$message); ++ } else ++ // Paper end + // Spigot start + if (components != null) { + buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(components)); +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java +index 915120cc505c70153f7b70f07d8d42c13eb77ea7..69ff8df7340e60c476803256750a48f0b43414d3 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java +@@ -10,6 +10,7 @@ public class ClientboundSetTitlesPacket implements Packet 0 && flag) { // TODO: allow plugins to override? +- Component ichatbasecomponent; +- if (deathMessage.equals(deathmessage)) { +- ichatbasecomponent = this.getCombatTracker().getDeathMessage(); +- } else { +- ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage); +- } ++ if (deathMessage != null && deathMessage != net.kyori.adventure.text.Component.empty() && flag) { // Paper - Adventure // TODO: allow plugins to override? ++ Component ichatbasecomponent = PaperAdventure.asVanilla(deathMessage); // Paper - Adventure + + this.connection.send((Packet) (new ClientboundPlayerCombatPacket(this.getCombatTracker(), ClientboundPlayerCombatPacket.Event.ENTITY_DIED, ichatbasecomponent)), (future) -> { + if (!future.isSuccess()) { +@@ -1666,6 +1663,7 @@ public class ServerPlayer extends Player implements ContainerListener { + this.sendMessage(message, ChatType.SYSTEM, senderUuid); + } + ++ public void sendMessage(final Component message, final ChatType type, final UUID sender) { this.sendMessage(message, type, sender); } // Paper - OBFHELPER + public void sendMessage(Component message, ChatType type, UUID senderUuid) { + this.connection.send((Packet) (new ClientboundChatPacket(message, type, senderUuid)), (future) -> { + if (!future.isSuccess() && (type == ChatType.GAME_INFO || type == ChatType.SYSTEM)) { +@@ -1688,6 +1686,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + + public String locale = "en_us"; // CraftBukkit - add, lowercase ++ public java.util.Locale adventure$locale = java.util.Locale.US; // Paper + public void updateOptions(ServerboundClientInformationPacket packet) { + // CraftBukkit start + if (getMainArm() != packet.getMainHand()) { +@@ -1699,6 +1698,10 @@ public class ServerPlayer extends Player implements ContainerListener { + this.server.server.getPluginManager().callEvent(event); + } + this.locale = packet.language; ++ // Paper start ++ this.adventure$locale = net.kyori.adventure.translation.Translator.parseLocale(this.locale); ++ this.connection.connection.channel.attr(PaperAdventure.LOCALE_ATTRIBUTE).set(this.adventure$locale); ++ // Paper end + this.clientViewDistance = packet.viewDistance; + // CraftBukkit end + this.chatVisibility = packet.getChatVisibility(); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 466c4322803bedf1fa61be281b954bf94fb8ff02..016e91a6ca1c8457e3e367ac0597b73e81919b68 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -168,6 +168,8 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + // CraftBukkit start ++import io.papermc.paper.adventure.ChatProcessor; // Paper ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.util.concurrent.ExecutionException; + import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + import org.bukkit.Location; +@@ -388,21 +390,24 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + return this.server.isSingleplayerOwner(this.player.getGameProfile()); + } + +- // CraftBukkit start +- @Deprecated +- public void disconnect(Component reason) { +- disconnect(CraftChatMessage.fromComponent(reason)); ++ public void disconnect(String s) { ++ // Paper start ++ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); + } +- // CraftBukkit end + +- public void disconnect(String s) { ++ public void disconnect(final Component reason) { ++ this.disconnect(PaperAdventure.asAdventure(reason)); ++ } ++ ++ public void disconnect(net.kyori.adventure.text.Component reason) { ++ // Paper end + // CraftBukkit start - fire PlayerKickEvent + if (this.processedDisconnect) { + return; + } +- String leaveMessage = ChatFormatting.YELLOW + this.player.getScoreboardName() + " left the game."; ++ net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure + +- PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), s, leaveMessage); ++ PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure + + if (this.craftServer.getServer().isRunning()) { + this.craftServer.getPluginManager().callEvent(event); +@@ -413,8 +418,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + return; + } + // Send the possibly modified leave message +- s = event.getReason(); +- final Component ichatbasecomponent = CraftChatMessage.fromString(s, true)[0]; ++ final Component ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure + // CraftBukkit end + + this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> { +@@ -1631,9 +1635,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + */ + + this.player.disconnect(); +- String quitMessage = this.server.getPlayerList().disconnect(this.player); +- if ((quitMessage != null) && (quitMessage.length() > 0)) { +- this.server.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); ++ // Paper start - Adventure ++ net.kyori.adventure.text.Component quitMessage = this.server.getPlayerList().disconnect(this.player); ++ if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) { ++ this.server.getPlayerList().sendMessage(PaperAdventure.asVanilla(quitMessage)); ++ // Paper end + } + // CraftBukkit end + TextFilter itextfilter = this.player.getTextFilter(); +@@ -1849,8 +1855,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.handleCommand(s); + } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { + // Do nothing, this is coming from a plugin +- } else { +- Player player = this.getPlayer(); ++ // Paper start ++ } else if (true) { ++ final ChatProcessor cp = new ChatProcessor(this.server, this.player, s, async); ++ cp.process(); ++ // Paper end ++ } else if (false) { // Paper ++ Player player = this.getPlayer(); // Paper + AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(server)); + this.craftServer.getPluginManager().callEvent(event); + +@@ -2668,21 +2679,20 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + return; + } + +- // CraftBukkit start +- Player player = this.craftServer.getPlayer(this.player); +- int x = packetplayinupdatesign.getPos().getX(); +- int y = packetplayinupdatesign.getPos().getY(); +- int z = packetplayinupdatesign.getPos().getZ(); +- String[] lines = new String[4]; ++ // CraftBukkit start // Paper start - Adventure ++ List lines = new java.util.ArrayList<>(); + + for (int i = 0; i < list.size(); ++i) { +- lines[i] = ChatFormatting.stripFormatting(new TextComponent(ChatFormatting.stripFormatting((String) list.get(i))).getString()); ++ lines.add(net.kyori.adventure.text.Component.text(list.get(i))); + } +- SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.craftServer.getPlayer(this.player), lines); ++ SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); + this.craftServer.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { +- System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.messages, 0, 4); ++ for (int i = 0; i < 4; i++) { ++ tileentitysign.setMessage(i, PaperAdventure.asVanilla(event.line(i))); ++ } ++ // Paper end + tileentitysign.isEditable = false; + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index a1dd76f49c59ed0a0b7f2b68fbd1a9a70a89128b..9dbb3bb79ae2de6635f71e5ee5bebeb5e57b624e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -35,6 +35,7 @@ import net.minecraft.world.entity.player.Player; + import org.apache.commons.lang3.Validate; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import org.bukkit.craftbukkit.util.Waitable; + import org.bukkit.event.player.AsyncPlayerPreLoginEvent; + import org.bukkit.event.player.PlayerPreLoginEvent; +@@ -299,7 +300,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { + final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); + if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { +- event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); ++ event.disallow(asyncEvent.getResult(), asyncEvent.kickMessage()); // Paper - Adventure + } + Waitable waitable = new Waitable() { + @Override +@@ -310,12 +311,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + + ServerLoginPacketListenerImpl.this.server.processQueue.add(waitable); + if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { +- disconnect(event.getKickMessage()); ++ disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure + return; + } + } else { + if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { +- disconnect(asyncEvent.getKickMessage()); ++ disconnect(PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure + return; + } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +index de19aa66e7b6ddde17e9acf65643b4a71573d759..223df8d27c2ff1cbff634bca3dbde5cc24de7f98 100644 +--- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +@@ -55,7 +55,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + CraftIconCache icon = server.server.getServerIcon(); + + ServerListPingEvent() { +- super(((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.getMotd(), server.getPlayerList().getMaxPlayers()); ++ super(((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.server.motd(), server.getPlayerList().getMaxPlayers()); // Paper - Adventure + } + + @Override +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 88af57699d7f9e45ad1366243049e4f3565703ff..8cdecaf2f63c78196e0c5046fe2431b40e072c8a 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -8,6 +8,7 @@ import com.mojang.authlib.GameProfile; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import io.netty.buffer.Unpooled; ++import io.papermc.paper.adventure.PaperAdventure; + import java.io.File; + import java.net.SocketAddress; + import java.text.SimpleDateFormat; +@@ -83,6 +84,7 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + // CraftBukkit start ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import com.google.common.base.Predicate; + import com.google.common.collect.Iterables; + import net.minecraft.server.dedicated.DedicatedServer; +@@ -251,7 +253,7 @@ public abstract class PlayerList { + } + // CraftBukkit start + chatmessage.withStyle(ChatFormatting.YELLOW); +- String joinMessage = CraftChatMessage.fromComponent(chatmessage); ++ Component joinMessage = chatmessage; // Paper - Adventure + + playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.yRot, player.xRot); + this.players.add(player); +@@ -260,19 +262,18 @@ public abstract class PlayerList { + // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below + + // CraftBukkit start +- PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(cserver.getPlayer(player), joinMessage); ++ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + cserver.getPluginManager().callEvent(playerJoinEvent); + + if (!player.connection.connection.isConnected()) { + return; + } + +- joinMessage = playerJoinEvent.getJoinMessage(); ++ final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); + +- if (joinMessage != null && joinMessage.length() > 0) { +- for (Component line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { +- server.getPlayerList().broadcastAll(new ClientboundChatPacket(line, ChatType.SYSTEM, Util.NIL_UUID)); +- } ++ if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure ++ joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure ++ server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure + } + // CraftBukkit end + +@@ -469,7 +470,7 @@ public abstract class PlayerList { + + } + +- public String disconnect(ServerPlayer entityplayer) { // CraftBukkit - return string ++ public net.kyori.adventure.text.Component disconnect(ServerPlayer entityplayer) { // Paper - return Component + ServerLevel worldserver = entityplayer.getLevel(); + + entityplayer.awardStat(Stats.LEAVE_GAME); +@@ -480,7 +481,7 @@ public abstract class PlayerList { + entityplayer.closeContainer(); + } + +- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getScoreboardName() + " left the game"); ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); + cserver.getPluginManager().callEvent(playerQuitEvent); + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + +@@ -541,7 +542,7 @@ public abstract class PlayerList { + cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); + // CraftBukkit end + +- return playerQuitEvent.getQuitMessage(); // CraftBukkit ++ return playerQuitEvent.quitMessage(); // Paper - Adventure + } + + // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer +@@ -587,10 +588,10 @@ public abstract class PlayerList { + } + + // return chatmessage; +- if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); // Spigot ++ if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure + } else if (!this.isWhiteListed(gameprofile)) { + chatmessage = new TranslatableComponent("multiplayer.disconnect.not_whitelisted"); +- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot ++ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure + } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { + IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); + +@@ -600,17 +601,17 @@ public abstract class PlayerList { + } + + // return chatmessage; +- event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); ++ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + } else { + // return this.players.size() >= this.maxPlayers && !this.f(gameprofile) ? new ChatMessage("multiplayer.disconnect.server_full") : null; + if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) { +- event.disallow(PlayerLoginEvent.Result.KICK_FULL, org.spigotmc.SpigotConfig.serverFullMessage); // Spigot ++ event.disallow(PlayerLoginEvent.Result.KICK_FULL, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure + } + } + + cserver.getPluginManager().callEvent(event); + if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { +- loginlistener.disconnect(event.getKickMessage()); ++ loginlistener.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure + return null; + } + return entity; +@@ -1131,7 +1132,7 @@ public abstract class PlayerList { + public void removeAll() { + // CraftBukkit start - disconnect safely + for (ServerPlayer player : this.players) { +- player.connection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message ++ player.connection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure + } + // CraftBukkit end + +diff --git a/src/main/java/net/minecraft/world/BossEvent.java b/src/main/java/net/minecraft/world/BossEvent.java +index 8718449abc08ed7795ac70c2bef12d15b94d4127..adb7c8db8e173801a83e5ff1f4cad0dda2abeb82 100644 +--- a/src/main/java/net/minecraft/world/BossEvent.java ++++ b/src/main/java/net/minecraft/world/BossEvent.java +@@ -1,5 +1,6 @@ + package net.minecraft.world; + ++import io.papermc.paper.adventure.PaperAdventure; + import java.util.UUID; + import net.minecraft.ChatFormatting; + import net.minecraft.network.chat.Component; +@@ -14,6 +15,7 @@ public abstract class BossEvent { + protected boolean darkenScreen; + protected boolean playBossMusic; + protected boolean createWorldFog; ++ public net.kyori.adventure.bossbar.BossBar adventure; // Paper + + public BossEvent(UUID uuid, Component name, BossEvent.BossBarColor color, BossEvent.BossBarOverlay style) { + this.id = uuid; +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 2a6a6e291efbd7cc8fed6532f18321bd141e1306..3faf52e7ac5e7e22d09cfb73cfda6b9f622137d4 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -865,6 +865,7 @@ public final class ItemStack { + } + // CraftBukkit end + ++ public Component displayName() { return this.getDisplayName(); } // Paper - OBFHELPER + public Component getDisplayName() { + MutableComponent ichatmutablecomponent = (new TextComponent("")).append(this.getHoverName()); + +diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +index 72367311f79e3ef2868c05b38bae98c5a9fb129c..c23ec1b31950471905c65e46273ae105de853d9b 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +@@ -94,6 +94,7 @@ public abstract class Enchantment { + return this.getOrCreateDescriptionId(); + } + ++ public final Component getTranslationComponentForLevel(int level) { return this.getFullname(level); } // Paper - OBFHELPER + public Component getFullname(int level) { + TranslatableComponent chatmessage = new TranslatableComponent(this.getDescriptionId()); + +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +index 2cccec66fbc7114c65336769e354fe6f756c9fca..d44505b3ee2a35422568e9bce0d868191e348fc0 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -32,6 +32,7 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + // CraftBukkit start ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.util.UUID; + + import org.bukkit.craftbukkit.CraftServer; +@@ -473,7 +474,7 @@ public class MapItemSavedData extends SavedData { + for ( org.bukkit.map.MapCursor cursor : render.cursors) { + + if (cursor.isVisible()) { +- icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); ++ icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure + } + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index c4cf1394fe4c2782b1fea8b3653a817157d857eb..f7f5457d20586e0ba72368e64ff6025f6755e61e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -561,8 +561,10 @@ public final class CraftServer implements Server { + } + + @Override ++ @Deprecated // Paper start + public int broadcastMessage(String message) { +- return broadcast(message, BROADCAST_CHANNEL_USERS); ++ return this.broadcast(message, BROADCAST_CHANNEL_USERS); ++ // Paper end + } + + public Player getPlayer(final ServerPlayer entity) { +@@ -1306,7 +1308,15 @@ public final class CraftServer implements Server { + return configuration.getInt("settings.spawn-radius", -1); + } + ++ // Paper start + @Override ++ public net.kyori.adventure.text.Component shutdownMessage() { ++ String msg = getShutdownMessage(); ++ return msg != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(msg) : null; ++ } ++ // Paper end ++ @Override ++ @Deprecated // Paper + public String getShutdownMessage() { + return configuration.getString("settings.shutdown-message"); + } +@@ -1422,7 +1432,20 @@ public final class CraftServer implements Server { + } + + @Override ++ @Deprecated // Paper + public int broadcast(String message, String permission) { ++ // Paper start - Adventure ++ return this.broadcast(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(message), permission); ++ } ++ ++ @Override ++ public int broadcast(net.kyori.adventure.text.Component message) { ++ return this.broadcast(message, BROADCAST_CHANNEL_USERS); ++ } ++ ++ @Override ++ public int broadcast(net.kyori.adventure.text.Component message, String permission) { ++ // Paper end + Set recipients = new HashSet<>(); + for (Permissible permissible : getPluginManager().getPermissionSubscriptions(permission)) { + if (permissible instanceof CommandSender && permissible.hasPermission(permission)) { +@@ -1430,14 +1453,14 @@ public final class CraftServer implements Server { + } + } + +- BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); ++ BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); // Paper - Adventure + getPluginManager().callEvent(broadcastMessageEvent); + + if (broadcastMessageEvent.isCancelled()) { + return 0; + } + +- message = broadcastMessageEvent.getMessage(); ++ message = broadcastMessageEvent.message(); // Paper - Adventure + + for (CommandSender recipient : recipients) { + recipient.sendMessage(message); +@@ -1663,6 +1686,14 @@ public final class CraftServer implements Server { + return CraftInventoryCreator.INSTANCE.createInventory(owner, type); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); ++ return CraftInventoryCreator.INSTANCE.createInventory(owner, type, title); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { + Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); +@@ -1675,13 +1706,28 @@ public final class CraftServer implements Server { + return CraftInventoryCreator.INSTANCE.createInventory(owner, size); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) throws IllegalArgumentException { ++ Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); ++ return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder owner, int size, String title) throws IllegalArgumentException { + Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); + return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); + } + ++ // Paper start ++ @Override ++ public Merchant createMerchant(net.kyori.adventure.text.Component title) { ++ return new org.bukkit.craftbukkit.inventory.CraftMerchantCustom(title == null ? InventoryType.MERCHANT.defaultTitle() : title); ++ } ++ // Paper end + @Override ++ @Deprecated // Paper + public Merchant createMerchant(String title) { + return new CraftMerchantCustom(title == null ? InventoryType.MERCHANT.getDefaultTitle() : title); + } +@@ -1725,6 +1771,12 @@ public final class CraftServer implements Server { + return Thread.currentThread().equals(console.serverThread) || console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog) + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component motd() { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(new net.minecraft.network.chat.TextComponent(console.getMotd())); ++ } ++ // Paper end + @Override + public String getMotd() { + return console.getMotd(); +@@ -2153,5 +2205,15 @@ public final class CraftServer implements Server { + return null; + } + } ++ ++ // Paper start ++ private Iterable adventure$audiences; ++ @Override ++ public Iterable audiences() { ++ if (this.adventure$audiences == null) { ++ this.adventure$audiences = com.google.common.collect.Iterables.concat(java.util.Collections.singleton(this.getConsoleSender()), this.getOnlinePlayers()); ++ } ++ return this.adventure$audiences; ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 05aedca561919a12ced1925c5cc9af585bb04523..ce9f10f890a5866ab6208c7253b15b09fe323a81 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -19,6 +19,12 @@ public class Main { + public static boolean useConsole = true; + + public static void main(String[] args) { ++ // Paper start ++ final String warnWhenLegacyFormattingDetected = String.join(".", "net", "kyori", "adventure", "text", "warnWhenLegacyFormattingDetected"); ++ if (false && System.getProperty(warnWhenLegacyFormattingDetected) == null) { ++ System.setProperty(warnWhenLegacyFormattingDetected, String.valueOf(true)); ++ } ++ // Paper end + // Todo: Installation script + OptionParser parser = new OptionParser() { + { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +index 639577ab8b6467302a243c99ba5a4eede3aed655..940fef58f14e06213c7f305f67dcb8918976c03d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +@@ -70,6 +70,19 @@ public class CraftBeacon extends CraftBlockEntityState implem + this.getSnapshot().secondaryPower = (effect != null) ? MobEffect.byId(effect.getId()) : null; + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component customName() { ++ final BeaconBlockEntity be = this.getSnapshot(); ++ return be.name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.name) : null; ++ } ++ ++ @Override ++ public void customName(final net.kyori.adventure.text.Component customName) { ++ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); ++ } ++ // Paper end ++ + @Override + public String getCustomName() { + BeaconBlockEntity beacon = this.getSnapshot(); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java +index 16a0f6e390a7415635e3573c1f79f7d78e5ef859..b1edc96d7e0444e72b79f190982de1d1bb5987f3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java +@@ -32,6 +32,19 @@ public abstract class CraftContainer extends + this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component customName() { ++ final T be = this.getSnapshot(); ++ return be.hasCustomName() ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.getCustomName()) : null; ++ } ++ ++ @Override ++ public void customName(final net.kyori.adventure.text.Component customName) { ++ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); ++ } ++ // Paper end ++ + @Override + public String getCustomName() { + T container = this.getSnapshot(); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java +index add5b68d5fbd887e3fc2d226eff9ab00ed01ce73..2c3d6ba06d876df168aae4cc09b7b4400e2fa33d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java +@@ -16,6 +16,19 @@ public class CraftEnchantingTable extends CraftBlockEntityState implements Sign { + + // Lazily initialized only if requested: +- private String[] originalLines = null; +- private String[] lines = null; ++ // Paper start ++ private java.util.ArrayList originalLines = null; // ArrayList for RandomAccess ++ private java.util.ArrayList lines = null; // ArrayList for RandomAccess ++ // Paper end + + public CraftSign(final Block block) { + super(block, SignBlockEntity.class); +@@ -23,27 +25,52 @@ public class CraftSign extends CraftBlockEntityState implements + super(material, te); + } + ++ // Paper start + @Override +- public String[] getLines() { +- if (lines == null) { +- // Lazy initialization: +- SignBlockEntity sign = this.getSnapshot(); +- lines = new String[sign.messages.length]; +- System.arraycopy(revertComponents(sign.messages), 0, lines, 0, lines.length); +- originalLines = new String[lines.length]; +- System.arraycopy(lines, 0, originalLines, 0, originalLines.length); ++ public java.util.List lines() { ++ this.loadLines(); ++ return this.lines; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.Component line(int index) { ++ this.loadLines(); ++ return this.lines.get(index); ++ } ++ ++ @Override ++ public void line(int index, net.kyori.adventure.text.Component line) { ++ this.loadLines(); ++ this.lines.set(index, line); ++ } ++ ++ private void loadLines() { ++ if (lines != null) { ++ return; + } +- return lines; ++ ++ // Lazy initialization: ++ SignBlockEntity sign = this.getSnapshot(); ++ lines = io.papermc.paper.adventure.PaperAdventure.asAdventure(com.google.common.collect.Lists.newArrayList(sign.messages)); ++ originalLines = new java.util.ArrayList<>(lines); ++ } ++ // Paper end ++ @Override ++ public String[] getLines() { ++ this.loadLines(); ++ return this.lines.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).toArray(String[]::new); // Paper + } + + @Override + public String getLine(int index) throws IndexOutOfBoundsException { +- return getLines()[index]; ++ this.loadLines(); ++ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(this.lines.get(index)); // Paper + } + + @Override + public void setLine(int index, String line) throws IndexOutOfBoundsException { +- getLines()[index] = line; ++ this.loadLines(); ++ this.lines.set(index, line != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(line) : net.kyori.adventure.text.Component.empty()); // Paper + } + + @Override +@@ -71,16 +98,32 @@ public class CraftSign extends CraftBlockEntityState implements + super.applyTo(sign); + + if (lines != null) { +- for (int i = 0; i < lines.length; i++) { +- String line = (lines[i] == null) ? "" : lines[i]; +- if (line.equals(originalLines[i])) { ++ // Paper start ++ for (int i = 0; i < this.lines.size(); ++i) { ++ net.kyori.adventure.text.Component component = this.lines.get(i); ++ net.kyori.adventure.text.Component origComp = this.originalLines.get(i); ++ if (component.equals(origComp)) { + continue; // The line contents are still the same, skip. + } +- sign.messages[i] = CraftChatMessage.fromString(line)[0]; ++ sign.messages[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(component); + } ++ // Paper end + } + } + ++ // Paper start ++ public static Component[] sanitizeLines(java.util.List lines) { ++ Component[] components = new Component[4]; ++ for (int i = 0; i < 4; i++) { ++ if (i < lines.size() && lines.get(i) != null) { ++ components[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(lines.get(i)); ++ } else { ++ components[i] = new TextComponent(""); ++ } ++ } ++ return components; ++ } ++ // Paper end + public static Component[] sanitizeLines(String[] lines) { + Component[] components = new Component[4]; + +diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +index 089fe4a3458ed3106fa214f89a7004a5d3c6bb95..af986adfdb547cb61fbd52f0f89858f1a9e52cc3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +@@ -80,4 +80,11 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co + public boolean isConversing() { + return conversationTracker.isConversing(); + } ++ ++ // Paper start ++ @Override ++ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { ++ this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); ++ } ++ // 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 fd473d213f4050f420bd7d729fe0df757d5398bc..b1ffe6c7a5915f00a476e88f3a38349b740b4910 100644 +--- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java ++++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +@@ -187,6 +187,12 @@ public class CraftEnchantment extends Enchantment { + CraftEnchantment ench = (CraftEnchantment) other; + return !target.isCompatibleWith(ench.target); + } ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName(int level) { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); ++ } ++ // Paper end + + public net.minecraft.world.item.enchantment.Enchantment getHandle() { + return target; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index eb61c803cf74c5ca2c51d5027a02ed3db6b53096..53c231925ef1b17e48c5863570e3c54124874621 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -768,6 +768,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return getHandle().getVehicle().getBukkitEntity(); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component customName() { ++ final Component name = this.getHandle().getCustomName(); ++ return name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(name) : null; ++ } ++ ++ @Override ++ public void customName(final net.kyori.adventure.text.Component customName) { ++ this.getHandle().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); ++ } ++ // Paper end ++ + @Override + public void setCustomName(String name) { + // sane limit for name length +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index 7c200e43bdc170ecf8b8fbfadd7bb38c66133443..b5c0f3d91cf451a972f0cf293db03a306073c493 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -317,9 +317,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + container = CraftEventFactory.callInventoryOpenEvent(player, container); + if (container == null) return; + +- String title = container.getBukkitView().getTitle(); ++ //String title = container.getBukkitView().getTitle(); // Paper - comment ++ net.kyori.adventure.text.Component adventure$title = container.getBukkitView().title(); // Paper ++ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper + +- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); ++ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment ++ player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + getHandle().containerMenu = container; + getHandle().containerMenu.addSlotListener(player); + } +@@ -388,8 +391,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + + // Now open the window + MenuType windowType = CraftContainer.getNotchInventoryType(inventory.getTopInventory()); +- String title = inventory.getTitle(); +- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); ++ ++ //String title = inventory.getTitle(); // Paper - comment ++ net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper ++ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper ++ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment ++ player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + player.containerMenu = container; + player.containerMenu.addSlotListener(player); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05b891167b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -238,14 +238,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + @Override + public String getDisplayName() { ++ if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper + return getHandle().displayName; + } + + @Override + public void setDisplayName(final String name) { ++ this.getHandle().adventure$displayName = name != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(name) : net.kyori.adventure.text.Component.text(this.getName()); // Paper + getHandle().displayName = name == null ? getName() : name; + } + ++ // Paper start ++ @Override ++ public void playerListName(net.kyori.adventure.text.Component name) { ++ getHandle().listName = name == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(name); ++ for (ServerPlayer player : server.getHandle().players) { ++ if (player.getBukkitEntity().canSee(this)) { ++ player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME, getHandle())); ++ } ++ } ++ } ++ @Override ++ public net.kyori.adventure.text.Component playerListName() { ++ return getHandle().listName == null ? net.kyori.adventure.text.Component.text(getName()) : io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().listName); ++ } ++ @Override ++ public net.kyori.adventure.text.Component playerListHeader() { ++ return playerListHeader; ++ } ++ @Override ++ public net.kyori.adventure.text.Component playerListFooter() { ++ return playerListFooter; ++ } ++ // Paper end + @Override + public String getPlayerListName() { + return getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(getHandle().listName); +@@ -264,35 +289,35 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + } + +- private Component playerListHeader; +- private Component playerListFooter; ++ private net.kyori.adventure.text.Component playerListHeader; // Paper - Adventure ++ private net.kyori.adventure.text.Component playerListFooter; // Paper - Adventure + + @Override + public String getPlayerListHeader() { +- return (playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader); ++ return (playerListHeader == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListHeader); // Paper - Adventure + } + + @Override + public String getPlayerListFooter() { +- return (playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter); ++ return (playerListFooter == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListFooter); // Paper - Adventure + } + + @Override + public void setPlayerListHeader(String header) { +- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); ++ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure + updatePlayerListHeaderFooter(); + } + + @Override + public void setPlayerListFooter(String footer) { +- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); ++ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure + updatePlayerListHeaderFooter(); + } + + @Override + public void setPlayerListHeaderFooter(String header, String footer) { +- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); +- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); ++ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure ++ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure + updatePlayerListHeaderFooter(); + } + +@@ -300,8 +325,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + if (getHandle().connection == null) return; + + ClientboundTabListPacket packet = new ClientboundTabListPacket(); +- packet.header = (this.playerListHeader == null) ? new TextComponent("") : this.playerListHeader; +- packet.footer = (this.playerListFooter == null) ? new TextComponent("") : this.playerListFooter; ++ packet.header = (this.playerListHeader == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListHeader); // Paper - Adventure ++ packet.footer = (this.playerListFooter == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListFooter); // Paper - Adventure + getHandle().connection.send(packet); + } + +@@ -333,6 +358,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + getHandle().connection.disconnect(message == null ? "" : message); + } + ++ // Paper start ++ @Override ++ public void kick(final net.kyori.adventure.text.Component message) { ++ org.spigotmc.AsyncCatcher.catchOp("player kick"); ++ final ServerGamePacketListenerImpl connection = this.getHandle().connection; ++ if (connection != null) { ++ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); ++ } ++ } ++ // Paper end ++ + @Override + public void setCompassTarget(Location loc) { + if (getHandle().connection == null) return; +@@ -559,6 +595,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + getHandle().connection.send(packet); + } + ++ // Paper start ++ @Override ++ public void sendSignChange(Location loc, List lines) { ++ this.sendSignChange(loc, lines, org.bukkit.DyeColor.BLACK); ++ } ++ @Override ++ public void sendSignChange(Location loc, List lines, DyeColor dyeColor) { ++ if (getHandle().connection == null) { ++ return; ++ } ++ if (lines == null) { ++ lines = new java.util.ArrayList<>(4); ++ } ++ Validate.notNull(loc, "Location cannot be null"); ++ Validate.notNull(dyeColor, "DyeColor cannot be null"); ++ if (lines.size() < 4) { ++ throw new IllegalArgumentException("Must have at least 4 lines"); ++ } ++ Component[] components = CraftSign.sanitizeLines(lines); ++ this.sendSignChange0(components, loc, dyeColor); ++ } ++ ++ private void sendSignChange0(Component[] components, Location loc, DyeColor dyeColor) { ++ SignBlockEntity sign = new SignBlockEntity(); ++ sign.setPosition(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); ++ sign.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData())); ++ System.arraycopy(components, 0, sign.messages, 0, sign.messages.length); ++ ++ getHandle().connection.send(sign.getUpdatePacket()); ++ } ++ // Paper end + @Override + public void sendSignChange(Location loc, String[] lines) { + sendSignChange(loc, lines, DyeColor.BLACK); +@@ -581,12 +648,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + Component[] components = CraftSign.sanitizeLines(lines); +- SignBlockEntity sign = new SignBlockEntity(); +- sign.setPosition(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); +- sign.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData())); +- System.arraycopy(components, 0, sign.messages, 0, sign.messages.length); ++ /*TileEntitySign sign = new TileEntitySign(); // Paper ++ sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); ++ sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); ++ System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); + +- getHandle().connection.send(sign.getUpdatePacket()); ++ getHandle().playerConnection.sendPacket(sign.getUpdatePacket());*/ // Paper ++ this.sendSignChange0(components, loc, dyeColor); // Paper + } + + @Override +@@ -1686,6 +1754,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return (getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : getHandle().clientViewDistance; + } + ++ // Paper start ++ @Override ++ public java.util.Locale locale() { ++ return getHandle().adventure$locale; ++ } ++ // Paper end + @Override + public int getPing() { + return getHandle().latency; +@@ -1714,6 +1788,138 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + getInventory().setItemInMainHand(hand); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() { ++ return this.getHandle().adventure$displayName; ++ } ++ ++ @Override ++ public void displayName(final net.kyori.adventure.text.Component displayName) { ++ this.getHandle().adventure$displayName = displayName != null ? displayName : net.kyori.adventure.text.Component.text(this.getName()); ++ this.getHandle().displayName = null; ++ } ++ ++ @Override ++ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { ++ final ClientboundChatPacket packet = new ClientboundChatPacket(null, type == net.kyori.adventure.audience.MessageType.CHAT ? net.minecraft.network.chat.ChatType.CHAT : net.minecraft.network.chat.ChatType.SYSTEM, identity.uuid()); ++ packet.adventure$message = message; ++ this.getHandle().connection.send(packet); ++ } ++ ++ @Override ++ public void sendActionBar(final net.kyori.adventure.text.Component message) { ++ final ClientboundSetTitlesPacket packet = new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.ACTIONBAR, null); ++ packet.adventure$text = message; ++ this.getHandle().connection.send(packet); ++ } ++ ++ @Override ++ public void sendPlayerListHeader(final net.kyori.adventure.text.Component header) { ++ this.playerListHeader = header; ++ this.adventure$sendPlayerListHeaderAndFooter(); ++ } ++ ++ @Override ++ public void sendPlayerListFooter(final net.kyori.adventure.text.Component footer) { ++ this.playerListFooter = footer; ++ this.adventure$sendPlayerListHeaderAndFooter(); ++ } ++ ++ @Override ++ public void sendPlayerListHeaderAndFooter(final net.kyori.adventure.text.Component header, final net.kyori.adventure.text.Component footer) { ++ this.playerListHeader = header; ++ this.playerListFooter = footer; ++ this.adventure$sendPlayerListHeaderAndFooter(); ++ } ++ ++ private void adventure$sendPlayerListHeaderAndFooter() { ++ final ServerGamePacketListenerImpl connection = this.getHandle().connection; ++ if (connection == null) return; ++ final ClientboundTabListPacket packet = new ClientboundTabListPacket(); ++ packet.adventure$header = (this.playerListHeader == null) ? net.kyori.adventure.text.Component.empty() : this.playerListHeader; ++ packet.adventure$footer = (this.playerListFooter == null) ? net.kyori.adventure.text.Component.empty() : this.playerListFooter; ++ connection.send(packet); ++ } ++ ++ @Override ++ public void showTitle(final net.kyori.adventure.title.Title title) { ++ final ServerGamePacketListenerImpl connection = this.getHandle().connection; ++ final net.kyori.adventure.title.Title.Times times = title.times(); ++ if (times != null) { ++ connection.send(new ClientboundSetTitlesPacket(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut()))); ++ } ++ final ClientboundSetTitlesPacket sp = new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.SUBTITLE, null); ++ sp.adventure$text = title.subtitle(); ++ connection.send(sp); ++ final ClientboundSetTitlesPacket tp = new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.TITLE, null); ++ tp.adventure$text = title.title(); ++ connection.send(tp); ++ } ++ ++ private static int ticks(final java.time.Duration duration) { ++ if (duration == null) { ++ return -1; ++ } ++ return (int) (duration.toMillis() / 50L); ++ } ++ ++ @Override ++ public void clearTitle() { ++ this.getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.CLEAR, null)); ++ } ++ ++ // resetTitle implemented above ++ ++ @Override ++ public void showBossBar(final net.kyori.adventure.bossbar.BossBar bar) { ++ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerShow(this); ++ } ++ ++ @Override ++ public void hideBossBar(final net.kyori.adventure.bossbar.BossBar bar) { ++ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerHide(this); ++ } ++ ++ @Override ++ public void playSound(final net.kyori.adventure.sound.Sound sound) { ++ final Vec3 pos = this.getHandle().position(); ++ this.playSound(sound, pos.x, pos.y, pos.z); ++ } ++ ++ @Override ++ public void playSound(final net.kyori.adventure.sound.Sound sound, final double x, final double y, final double z) { ++ final ResourceLocation name = io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.name()); ++ final java.util.Optional event = net.minecraft.core.Registry.SOUND_EVENT.getOptional(name); ++ if (event.isPresent()) { ++ this.getHandle().connection.send(new ClientboundSoundPacket(event.get(), io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), x, y, z, sound.volume(), sound.pitch())); ++ } else { ++ this.getHandle().connection.send(new ClientboundCustomSoundPacket(name, io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), new Vec3(x, y, z), sound.volume(), sound.pitch())); ++ } ++ } ++ ++ @Override ++ public void stopSound(final net.kyori.adventure.sound.SoundStop stop) { ++ this.getHandle().connection.send(new ClientboundStopSoundPacket( ++ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.sound()), ++ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.source()) ++ )); ++ } ++ ++ @Override ++ public void openBook(final net.kyori.adventure.inventory.Book book) { ++ final java.util.Locale locale = this.getHandle().adventure$locale; ++ final net.minecraft.world.item.ItemStack item = io.papermc.paper.adventure.PaperAdventure.asItemStack(book, locale); ++ final ServerPlayer player = this.getHandle(); ++ final ServerGamePacketListenerImpl connection = player.connection; ++ final net.minecraft.world.entity.player.Inventory inventory = player.inventory; ++ final int slot = inventory.items.size() + inventory.selected; ++ connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, item)); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND)); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, inventory.getSelected())); ++ } ++ // Paper end ++ + // Spigot start + private final Player.Spigot spigot = new Player.Spigot() + { +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index abd65693aca1964b65d091e633a36c97513c1d69..7fde1bb7587e567270e3f936381c6d361870211f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -776,9 +776,9 @@ public class CraftEventFactory { + return event; + } + +- public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, List drops, String deathMessage, boolean keepInventory) { ++ public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, List drops, net.kyori.adventure.text.Component deathMessage, String stringDeathMessage, boolean keepInventory) { // Paper - Adventure + CraftPlayer entity = victim.getBukkitEntity(); +- PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage); ++ PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure + event.setKeepInventory(keepInventory); + org.bukkit.World world = entity.getWorld(); + Bukkit.getServer().getPluginManager().callEvent(event); +@@ -802,7 +802,7 @@ public class CraftEventFactory { + * Server methods + */ + public static ServerListPingEvent callServerListPingEvent(Server craftServer, InetAddress address, String motd, int numPlayers, int maxPlayers) { +- ServerListPingEvent event = new ServerListPingEvent(address, motd, numPlayers, maxPlayers); ++ ServerListPingEvent event = new ServerListPingEvent(address, craftServer.motd(), numPlayers, maxPlayers); // Paper - Adventure + craftServer.getPluginManager().callEvent(event); + return event; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +index a393bdae6ef588289c8814a1896146a993c92e71..680c7818a7097355158eb76662ecebbae6dd6637 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +@@ -1,6 +1,5 @@ + package org.bukkit.craftbukkit.inventory; + +-import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; + import net.minecraft.world.Container; + import net.minecraft.world.entity.player.Player; +@@ -38,6 +37,7 @@ public class CraftContainer extends AbstractContainerMenu { + + private final InventoryView view; + private InventoryType cachedType; ++ private net.kyori.adventure.text.Component adventure$title; // Paper + private String cachedTitle; + private AbstractContainerMenu delegate; + private final int cachedSize; +@@ -49,7 +49,9 @@ public class CraftContainer extends AbstractContainerMenu { + Container top = ((CraftInventory) view.getTopInventory()).getInventory(); + net.minecraft.world.entity.player.Inventory bottom = (net.minecraft.world.entity.player.Inventory) ((CraftInventory) view.getBottomInventory()).getInventory(); + cachedType = view.getType(); +- cachedTitle = view.getTitle(); ++ this.adventure$title = view.title(); // Paper ++ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper ++ //cachedTitle = view.getTitle(); // Paper - comment + cachedSize = getSize(); + setupSlots(top, bottom, player); + } +@@ -76,6 +78,13 @@ public class CraftContainer extends AbstractContainerMenu { + return inventory.getType(); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component title() { ++ return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).title() : net.kyori.adventure.text.Component.text(inventory.getType().getDefaultTitle()); ++ } ++ // Paper end ++ + @Override + public String getTitle() { + return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).getTitle() : inventory.getType().getDefaultTitle(); +@@ -94,7 +103,8 @@ public class CraftContainer extends AbstractContainerMenu { + + @Override + public boolean isSynched(Player player) { +- if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { ++ if (cachedType == view.getType() && cachedSize == getSize() && this.adventure$title.equals(view.title())) { // Paper ++ //if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { // Paper - comment + return true; + } + // If the window type has changed for some reason, update the player +@@ -102,7 +112,9 @@ public class CraftContainer extends AbstractContainerMenu { + // as good a place as any to put something like this. + boolean typeChanged = (cachedType != view.getType()); + cachedType = view.getType(); +- cachedTitle = view.getTitle(); ++ this.adventure$title = view.title(); // Paper ++ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper ++ //cachedTitle = view.getTitle(); // Paper - comment + if (view.getPlayer() instanceof CraftPlayer) { + CraftPlayer player1 = (CraftPlayer) view.getPlayer(); + MenuType type = getNotchInventoryType(view.getTopInventory()); +@@ -114,7 +126,8 @@ public class CraftContainer extends AbstractContainerMenu { + setupSlots(top, bottom, player1.getHandle()); + } + int size = getSize(); +- player1.getHandle().connection.send(new ClientboundOpenScreenPacket(this.containerId, type, new TextComponent(cachedTitle))); ++ player1.getHandle().connection.send(new ClientboundOpenScreenPacket(this.containerId, type, io.papermc.paper.adventure.PaperAdventure.asVanilla(this.adventure$title))); // Paper ++ //player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, new ChatComponentText(cachedTitle))); // Paper - comment + player1.updateInventory(); + } + return true; +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java +index 397cd9651381a8a0ddb4ca173690e9b80428b182..46805a25c0273b76c19a3bbd40078d78c5379f43 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java +@@ -19,6 +19,12 @@ public class CraftInventoryCustom extends CraftInventory { + super(new MinecraftInventory(owner, type)); + } + ++ // Paper start ++ public CraftInventoryCustom(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ super(new MinecraftInventory(owner, type, title)); ++ } ++ // Paper end ++ + public CraftInventoryCustom(InventoryHolder owner, InventoryType type, String title) { + super(new MinecraftInventory(owner, type, title)); + } +@@ -27,6 +33,12 @@ public class CraftInventoryCustom extends CraftInventory { + super(new MinecraftInventory(owner, size)); + } + ++ // Paper start ++ public CraftInventoryCustom(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { ++ super(new MinecraftInventory(owner, size, title)); ++ } ++ // Paper end ++ + public CraftInventoryCustom(InventoryHolder owner, int size, String title) { + super(new MinecraftInventory(owner, size, title)); + } +@@ -36,9 +48,17 @@ public class CraftInventoryCustom extends CraftInventory { + private int maxStack = MAX_STACK; + private final List viewers; + private final String title; ++ private final net.kyori.adventure.text.Component adventure$title; // Paper + private InventoryType type; + private final InventoryHolder owner; + ++ // Paper start ++ public MinecraftInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ this(owner, type.getDefaultSize(), title); ++ this.type = type; ++ } ++ // Paper end ++ + public MinecraftInventory(InventoryHolder owner, InventoryType type) { + this(owner, type.getDefaultSize(), type.getDefaultTitle()); + this.type = type; +@@ -57,11 +77,24 @@ public class CraftInventoryCustom extends CraftInventory { + Validate.notNull(title, "Title cannot be null"); + this.items = NonNullList.a(size, ItemStack.EMPTY); + this.title = title; ++ this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(title); + this.viewers = new ArrayList(); + this.owner = owner; + this.type = InventoryType.CHEST; + } + ++ // Paper start ++ public MinecraftInventory(final InventoryHolder owner, final int size, final net.kyori.adventure.text.Component title) { ++ Validate.notNull(title, "Title cannot be null"); ++ this.items = NonNullList.a(size, ItemStack.EMPTY); ++ this.title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); ++ this.adventure$title = title; ++ this.viewers = new ArrayList(); ++ this.owner = owner; ++ this.type = InventoryType.CHEST; ++ } ++ // Paper end ++ + @Override + public int getContainerSize() { + return items.size(); +@@ -183,6 +216,12 @@ public class CraftInventoryCustom extends CraftInventory { + return null; + } + ++ // Paper start ++ public net.kyori.adventure.text.Component title() { ++ return this.adventure$title; ++ } ++ // Paper end ++ + public String getTitle() { + return title; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java +index 326e8eb49e67ccfbf8f9b23bd6f03ea3576b9d35..945a80ca026c12e16a7ac5bebe56f846a437f847 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java +@@ -64,6 +64,13 @@ public class CraftInventoryView extends InventoryView { + return CraftItemStack.asCraftMirror(container.getSlot(slot).getItem()); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component title() { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.container.getTitle()); ++ } ++ // Paper end ++ + @Override + public String getTitle() { + return CraftChatMessage.fromComponent(container.getTitle()); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index 89a3617068421bb86baf4e8bfd9df2d0626adff7..32fa5ca0df07466e40817341d85d359b282f3078 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -334,4 +334,17 @@ public final class CraftItemFactory implements ItemFactory { + public Material updateMaterial(ItemMeta meta, Material material) throws IllegalArgumentException { + return ((CraftMetaItem) meta).updateMaterial(material); + } ++ ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final ItemStack item, final java.util.function.UnaryOperator op) { ++ final net.minecraft.nbt.CompoundTag tag = CraftItemStack.asNMSCopy(item).getTag(); ++ return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowItem.of(item.getType().getKey(), item.getAmount(), io.papermc.paper.adventure.PaperAdventure.asBinaryTagHolder(tag)))); ++ } ++ ++ @Override ++ public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +index 71136bb009d6c8c92595f957ee7680a771ea9a63..306c6483708ae1b41bd16f122d36beec1916a776 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +@@ -14,10 +14,17 @@ import org.apache.commons.lang.Validate; + + public class CraftMerchantCustom extends CraftMerchant { + ++ @Deprecated // Paper - Adventure + public CraftMerchantCustom(String title) { + super(new MinecraftMerchant(title)); + getMerchant().craftMerchant = this; + } ++ // Paper start ++ public CraftMerchantCustom(net.kyori.adventure.text.Component title) { ++ super(new MinecraftMerchant(title)); ++ getMerchant().craftMerchant = this; ++ } ++ // Paper end + + @Override + public String toString() { +@@ -37,10 +44,17 @@ public class CraftMerchantCustom extends CraftMerchant { + private Level tradingWorld; + protected CraftMerchant craftMerchant; + ++ @Deprecated // Paper - Adventure + public MinecraftMerchant(String title) { + Validate.notNull(title, "Title cannot be null"); + this.title = new TextComponent(title); + } ++ // Paper start ++ public MinecraftMerchant(net.kyori.adventure.text.Component title) { ++ Validate.notNull(title, "Title cannot be null"); ++ this.title = io.papermc.paper.adventure.PaperAdventure.asVanilla(title); ++ } ++ // Paper end + + @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 6dba12c4f58a462c8d466461eb8b804dd045766d..a592d4a286a775a61192dde2a4d21a0681090415 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +@@ -1,8 +1,9 @@ + package org.bukkit.craftbukkit.inventory; + + import com.google.common.collect.ImmutableList; +-import com.google.common.collect.ImmutableMap.Builder; + import com.google.common.collect.Lists; ++ ++import com.google.common.collect.ImmutableMap; // Paper + import java.util.ArrayList; + import java.util.Arrays; + import java.util.List; +@@ -17,9 +18,12 @@ import org.bukkit.craftbukkit.util.CraftChatMessage; + import org.bukkit.craftbukkit.util.CraftMagicNumbers; + import org.bukkit.inventory.meta.BookMeta; + import org.bukkit.inventory.meta.BookMeta.Generation; ++import org.checkerframework.checker.nullness.qual.NonNull; + + // Spigot start + import static org.spigotmc.ValidateUtils.*; ++ ++import BookMetaBuilder; + import java.util.AbstractList; + import net.md_5.bungee.api.chat.BaseComponent; + import net.md_5.bungee.chat.ComponentSerializer; +@@ -269,6 +273,141 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + this.generation = (generation == null) ? null : generation.ordinal(); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component title() { ++ return this.title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.title); ++ } ++ ++ @Override ++ public org.bukkit.inventory.meta.BookMeta title(net.kyori.adventure.text.Component title) { ++ this.setTitle(title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title)); ++ return this; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.Component author() { ++ return this.author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.author); ++ } ++ ++ @Override ++ public org.bukkit.inventory.meta.BookMeta author(net.kyori.adventure.text.Component author) { ++ this.setAuthor(author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author)); ++ return this; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.Component page(final int page) { ++ Validate.isTrue(isValidPage(page), "Invalid page number"); ++ return this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(pages.get(page - 1)) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(pages.get(page - 1)); ++ } ++ ++ @Override ++ public void page(final int page, net.kyori.adventure.text.Component data) { ++ if (!isValidPage(page)) { ++ throw new IllegalArgumentException("Invalid page number " + page + "/" + pages.size()); ++ } ++ if (data == null) { ++ data = net.kyori.adventure.text.Component.empty(); ++ } ++ pages.set(page - 1, this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(data) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(data)); ++ } ++ ++ @Override ++ public List pages() { ++ if (this.pages == null) return ImmutableList.of(); ++ if (this instanceof CraftMetaBookSigned) ++ return pages.stream().map(net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson()::deserialize).collect(ImmutableList.toImmutableList()); ++ else ++ return pages.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::deserialize).collect(ImmutableList.toImmutableList()); ++ } ++ ++ @Override ++ public BookMeta pages(List pages) { ++ if (this.pages != null) this.pages.clear(); ++ for (net.kyori.adventure.text.Component page : pages) { ++ addPages(page); ++ } ++ return this; ++ } ++ ++ @Override ++ public BookMeta pages(net.kyori.adventure.text.Component... pages) { ++ if (this.pages != null) this.pages.clear(); ++ addPages(pages); ++ return this; ++ } ++ ++ @Override ++ public void addPages(net.kyori.adventure.text.Component... pages) { ++ if (this.pages == null) this.pages = new ArrayList<>(); ++ for (net.kyori.adventure.text.Component page : pages) { ++ if (this.pages.size() >= MAX_PAGES) { ++ return; ++ } ++ ++ if (page == null) { ++ page = net.kyori.adventure.text.Component.empty(); ++ } ++ ++ this.pages.add(this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(page) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(page)); ++ } ++ } ++ ++ private CraftMetaBook(net.kyori.adventure.text.Component title, net.kyori.adventure.text.Component author, List pages) { ++ super((org.bukkit.craftbukkit.inventory.CraftMetaItem) org.bukkit.Bukkit.getItemFactory().getItemMeta(org.bukkit.Material.WRITABLE_BOOK)); ++ this.title = title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); ++ this.author = author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author); ++ this.pages = pages.subList(0, Math.min(MAX_PAGES, pages.size())).stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).collect(java.util.stream.Collectors.toList()); ++ } ++ ++ static final class CraftMetaBookBuilder implements BookMetaBuilder { ++ private net.kyori.adventure.text.Component title = null; ++ private net.kyori.adventure.text.Component author = null; ++ private final List pages = new java.util.ArrayList<>(); ++ ++ @Override ++ public BookMetaBuilder title(net.kyori.adventure.text.Component title) { ++ this.title = title; ++ return this; ++ } ++ ++ @Override ++ public BookMetaBuilder author(net.kyori.adventure.text.Component author) { ++ this.author = author; ++ return this; ++ } ++ ++ @Override ++ public BookMetaBuilder addPage(net.kyori.adventure.text.Component page) { ++ this.pages.add(page); ++ return this; ++ } ++ ++ @Override ++ public BookMetaBuilder pages(net.kyori.adventure.text.Component... pages) { ++ java.util.Collections.addAll(this.pages, pages); ++ return this; ++ } ++ ++ @Override ++ public BookMetaBuilder pages(java.util.Collection pages) { ++ this.pages.addAll(pages); ++ return this; ++ } ++ ++ @Override ++ public BookMeta build() { ++ return new CraftMetaBook(title, author, pages); ++ } ++ } ++ ++ @Override ++ public BookMetaBuilder toBuilder() { ++ return new CraftMetaBookBuilder(); ++ } ++ ++ // Paper end + @Override + public String getPage(final int page) { + Validate.isTrue(isValidPage(page), "Invalid page number"); +@@ -413,7 +552,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + } + + @Override +- Builder serialize(Builder builder) { ++ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { + super.serialize(builder); + + if (hasTitle()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java +index 00445fc7373c70f4cecc4114f9bcfb4b6f27c0e8..0cf60eb9b6ba1a79c9b603c4349debd478101f9a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java +@@ -1,6 +1,6 @@ + package org.bukkit.craftbukkit.inventory; + +-import com.google.common.collect.ImmutableMap.Builder; ++import com.google.common.collect.ImmutableMap; // Paper + import java.util.Map; + import net.minecraft.nbt.CompoundTag; + import org.bukkit.Material; +@@ -84,7 +84,7 @@ class CraftMetaBookSigned extends CraftMetaBook implements BookMeta { + } + + @Override +- Builder serialize(Builder builder) { ++ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { + super.serialize(builder); + return builder; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 2e819849e83967d751f7b0612a7cf4edb5a7264b..cca04daf84e506382365c0ba945cb024bd4d4475 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -744,6 +744,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() { ++ return displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(displayName); ++ } ++ ++ @Override ++ public void displayName(final net.kyori.adventure.text.Component displayName) { ++ this.displayName = displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(displayName); ++ } ++ // Paper end ++ + @Override + public String getDisplayName() { + return CraftChatMessage.fromJSONComponent(displayName); +@@ -779,6 +791,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return this.lore != null && !this.lore.isEmpty(); + } + ++ // Paper start ++ @Override ++ public List lore() { ++ return this.lore != null ? io.papermc.paper.adventure.PaperAdventure.asAdventureFromJson(this.lore) : null; ++ } ++ ++ @Override ++ public void lore(final List lore) { ++ this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asJson(lore) : null; ++ } ++ // Paper end ++ + @Override + public boolean hasRepairCost() { + return repairCost > 0; +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java +index ed4415f6dd588c08c922efd5beebb3b124beb9d6..78a7ac47f20e84ccd67ff44d0bc7a2f2faa0d476 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java +@@ -12,6 +12,13 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve + return new CraftInventoryCustom(holder, type); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ return new CraftInventoryCustom(owner, type, title); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { + return new CraftInventoryCustom(owner, type, title); +@@ -21,6 +28,12 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve + return new CraftInventoryCustom(owner, size); + } + ++ // Paper start ++ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { ++ return new CraftInventoryCustom(owner, size, title); ++ } ++ // Paper end ++ + public Inventory createInventory(InventoryHolder owner, int size, String title) { + return new CraftInventoryCustom(owner, size, title); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b833806a0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +@@ -43,6 +43,17 @@ public final class CraftInventoryCreator { + return converterMap.get(type).createInventory(holder, type); + } + ++ // Paper start ++ public Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title) { ++ // Paper start ++ if (holder != null) { ++ return DEFAULT_CONVERTER.createInventory(holder, type, title); ++ } ++ //noinspection ConstantConditions // Paper end ++ return converterMap.get(type).createInventory(holder, type, title); ++ } ++ // Paper end ++ + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { + return converterMap.get(type).createInventory(holder, type, title); + } +@@ -51,6 +62,12 @@ public final class CraftInventoryCreator { + return DEFAULT_CONVERTER.createInventory(holder, size); + } + ++ // Paper start ++ public Inventory createInventory(InventoryHolder holder, int size, net.kyori.adventure.text.Component title) { ++ return DEFAULT_CONVERTER.createInventory(holder, size, title); ++ } ++ // Paper end ++ + public Inventory createInventory(InventoryHolder holder, int size, String title) { + return DEFAULT_CONVERTER.createInventory(holder, size, title); + } +@@ -59,6 +76,10 @@ public final class CraftInventoryCreator { + + Inventory createInventory(InventoryHolder holder, InventoryType type); + ++ // Paper start ++ Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title); ++ // Paper end ++ + Inventory createInventory(InventoryHolder holder, InventoryType type, String title); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java +index 0395a6235d62126540e370d6ef77e6966c50ca1d..3ef9742a68084d159ea8ed5709298f9863e04a67 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java +@@ -31,6 +31,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat + return getInventory(getTileEntity()); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ Container te = getTileEntity(); ++ if (te instanceof RandomizableContainerBlockEntity) { ++ ((RandomizableContainerBlockEntity) te).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); ++ } ++ ++ return getInventory(te); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { + Container te = getTileEntity(); +@@ -54,6 +66,15 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat + return furnace; + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ Container tileEntity = getTileEntity(); ++ ((AbstractFurnaceBlockEntity) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); ++ return getInventory(tileEntity); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { + Container tileEntity = getTileEntity(); +@@ -74,6 +95,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat + return new BrewingStandBlockEntity(); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ // BrewingStand does not extend TileEntityLootable ++ Container tileEntity = getTileEntity(); ++ if (tileEntity instanceof BrewingStandBlockEntity) { ++ ((BrewingStandBlockEntity) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); ++ } ++ return getInventory(tileEntity); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { + // BrewingStand does not extend TileEntityLootable +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java +index d5ebb11447a8effa41138a13874fd3e5246dfe71..96ba508c87336d012c1ed5aa982588f55782a2fe 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java +@@ -30,6 +30,21 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective + return objective.getName(); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(objective.getDisplayName()); ++ } ++ @Override ++ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { ++ if (displayName == null) { ++ displayName = net.kyori.adventure.text.Component.empty(); ++ } ++ CraftScoreboard scoreboard = checkState(); ++ objective.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); ++ } ++ // Paper end + @Override + public String getDisplayName() throws IllegalStateException { + CraftScoreboard scoreboard = checkState(); +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +index af160d3bdb82f07c6c836a438b8ab37b803c29e2..4c93be31fd95d731327479519ecb34a08785c1ca 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +@@ -27,6 +27,27 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + public CraftObjective registerNewObjective(String name, String criteria) throws IllegalArgumentException { + return registerNewObjective(name, criteria, name); + } ++ // Paper start ++ @Override ++ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName) { ++ return registerNewObjective(name, criteria, displayName, org.bukkit.scoreboard.RenderType.INTEGER); ++ } ++ @Override ++ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName, RenderType renderType) { ++ if (displayName == null) { ++ displayName = net.kyori.adventure.text.Component.empty(); ++ } ++ Validate.notNull(name, "Objective name cannot be null"); ++ Validate.notNull(criteria, "Criteria cannot be null"); ++ Validate.notNull(displayName, "Display name cannot be null"); ++ Validate.notNull(renderType, "RenderType cannot be null"); ++ Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); ++ Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); ++ CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); ++ net.minecraft.world.scores.Objective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); ++ return new CraftObjective(this, objective); ++ } ++ // Paper end + + @Override + public CraftObjective registerNewObjective(String name, String criteria, String displayName) throws IllegalArgumentException { +@@ -35,7 +56,7 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + + @Override + public CraftObjective registerNewObjective(String name, String criteria, String displayName, RenderType renderType) throws IllegalArgumentException { +- Validate.notNull(name, "Objective name cannot be null"); ++ /*Validate.notNull(name, "Objective name cannot be null"); // Paper + Validate.notNull(criteria, "Criteria cannot be null"); + Validate.notNull(displayName, "Display name cannot be null"); + Validate.notNull(renderType, "RenderType cannot be null"); +@@ -44,8 +65,9 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); + + CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); +- net.minecraft.world.scores.Objective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); +- return new CraftObjective(this, objective); ++ ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); ++ return new CraftObjective(this, objective);*/ // Paper ++ return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +index f5237ff19d8b26be0b762659ad0ea6887205b3f9..7ebcba4ada42f5599d56cfdeb75dbf62f2a09b78 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +@@ -28,6 +28,55 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { + + return team.getName(); + } ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getDisplayName()); ++ } ++ @Override ++ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { ++ if (displayName == null) displayName = net.kyori.adventure.text.Component.empty(); ++ CraftScoreboard scoreboard = checkState(); ++ team.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); ++ } ++ @Override ++ public net.kyori.adventure.text.Component prefix() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPlayerPrefix()); ++ } ++ @Override ++ public void prefix(net.kyori.adventure.text.Component prefix) throws IllegalStateException, IllegalArgumentException { ++ if (prefix == null) prefix = net.kyori.adventure.text.Component.empty(); ++ CraftScoreboard scoreboard = checkState(); ++ team.setPlayerPrefix(io.papermc.paper.adventure.PaperAdventure.asVanilla(prefix)); ++ } ++ @Override ++ public net.kyori.adventure.text.Component suffix() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPlayerSuffix()); ++ } ++ @Override ++ public void suffix(net.kyori.adventure.text.Component suffix) throws IllegalStateException, IllegalArgumentException { ++ if (suffix == null) suffix = net.kyori.adventure.text.Component.empty(); ++ CraftScoreboard scoreboard = checkState(); ++ team.setPlayerSuffix(io.papermc.paper.adventure.PaperAdventure.asVanilla(suffix)); ++ } ++ @Override ++ public net.kyori.adventure.text.format.TextColor color() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ if (team.getColor().getHexValue() == null) throw new IllegalStateException("Team colors must have hex values"); ++ net.kyori.adventure.text.format.TextColor color = net.kyori.adventure.text.format.TextColor.color(team.getColor().getHexValue()); ++ if (!(color instanceof net.kyori.adventure.text.format.NamedTextColor)) throw new IllegalStateException("Team doesn't have a NamedTextColor"); ++ return (net.kyori.adventure.text.format.NamedTextColor) color; ++ } ++ @Override ++ public void color(net.kyori.adventure.text.format.NamedTextColor color) { ++ if (color == null) color = net.kyori.adventure.text.format.NamedTextColor.WHITE; ++ CraftScoreboard scoreboard = checkState(); ++ team.setColor(io.papermc.paper.adventure.PaperAdventure.asVanilla(color)); ++ } ++ // Paper end + + @Override + public String getDisplayName() throws IllegalStateException { +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +index 35e6ce5f33b3d6b86c3654e6a207e26aa44badb5..b27af66795d902a2e95d692fa0ff18eccbef8a75 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +@@ -290,6 +290,7 @@ public final class CraftChatMessage { + + public static String fromComponent(Component component) { + if (component == null) return ""; ++ if (component instanceof io.papermc.paper.adventure.AdventureComponent) component = ((io.papermc.paper.adventure.AdventureComponent) component).deepConverted(); + StringBuilder out = new StringBuilder(); + + 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 ef7715774fbdc4c42b217d8192784e09a43fe66f..2d4faef5a2b9c4fe8b65ff4f1346b8375e0e02c8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -57,6 +57,33 @@ public final class CraftMagicNumbers implements UnsafeValues { + + private CraftMagicNumbers() {} + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener() { ++ return io.papermc.paper.adventure.PaperAdventure.FLATTENER; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer() { ++ return io.papermc.paper.adventure.PaperAdventure.COLOR_DOWNSAMPLING_GSON; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer() { ++ return io.papermc.paper.adventure.PaperAdventure.GSON; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer() { ++ return io.papermc.paper.adventure.PaperAdventure.PLAIN; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer() { ++ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC; ++ } ++ // Paper end ++ + public static BlockState getBlock(MaterialData material) { + return getBlock(material.getItemType(), material.getData()); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java +index f194cf2663919ea18309a0501ddfab5e2ed639dd..4b110d6c6f22ff7c2fa0fd4b459820797066199d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java +@@ -80,7 +80,7 @@ public abstract class LazyHashSet implements Set { + return this.reference = makeReference(); + } + +- abstract Set makeReference(); ++ protected abstract Set makeReference(); // Paper - protected + + public boolean isLazy() { + return reference == null; +diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java +index 103c1407b2946e9cae2271646178e5f243c8abb1..b22b7603f3f66e1b64f413106e7989b30475110b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java +@@ -15,10 +15,15 @@ public class LazyPlayerSet extends LazyHashSet { + } + + @Override +- HashSet makeReference() { ++ protected HashSet makeReference() { // Paper - protected + if (reference != null) { + throw new IllegalStateException("Reference already created!"); + } ++ // Paper start ++ return makePlayerSet(this.server); ++ } ++ public static HashSet makePlayerSet(final MinecraftServer server) { ++ // Paper end + List players = server.getPlayerList().players; + HashSet reference = new HashSet(players.size()); + for (ServerPlayer player : players) { diff --git a/Remapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch b/Remapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch new file mode 100644 index 0000000000..2bef4fada9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch @@ -0,0 +1,114 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 13:02:51 -0600 +Subject: [PATCH] Configurable cactus bamboo and reed growth heights + +Bamboo - Both the minimum fully-grown heights and the maximum are configurable +- Machine_Maker + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index b31109d2dadd29e8852468c19265066b773d2be0..3618cc017feb60e257a28f67cbddca3f792a9833 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -65,4 +65,17 @@ public class PaperWorldConfig { + config.addDefault("world-settings.default." + path, def); + return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); + } ++ ++ public int cactusMaxHeight; ++ public int reedMaxHeight; ++ public int bambooMaxHeight; ++ public int bambooMinHeight; ++ private void blockGrowthHeight() { ++ cactusMaxHeight = getInt("max-growth-height.cactus", 3); ++ reedMaxHeight = getInt("max-growth-height.reeds", 3); ++ bambooMaxHeight = getInt("max-growth-height.bamboo.max", 16); ++ bambooMinHeight = getInt("max-growth-height.bamboo.min", 11); ++ log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); ++ ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/BambooBlock.java b/src/main/java/net/minecraft/world/level/block/BambooBlock.java +index 8f423ae6261434a670bb94aa70b6bc1694f1fc45..36583c189aa5e55de7f5eba362285e57c8279176 100644 +--- a/src/main/java/net/minecraft/world/level/block/BambooBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BambooBlock.java +@@ -124,7 +124,7 @@ public class BambooBlock extends Block implements BonemealableBlock { + if (random.nextInt(Math.max(1, (int) (100.0F / world.spigotConfig.bambooModifier) * 3)) == 0 && world.isEmptyBlock(pos.above()) && world.getRawBrightness(pos.above(), 0) >= 9) { // Spigot + int i = this.getHeightBelowUpToMax(world, pos) + 1; + +- if (i < 16) { ++ if (i < world.paperConfig.bambooMaxHeight) { // Paper + this.growBamboo(state, (Level) world, pos, random, i); + } + } +@@ -155,7 +155,7 @@ public class BambooBlock extends Block implements BonemealableBlock { + int i = this.getHeightAboveUpToMax(world, pos); + int j = this.getHeightBelowUpToMax(world, pos); + +- return i + j + 1 < 16 && (Integer) world.getBlockState(pos.above(i)).getValue(BambooBlock.STAGE) != 1; ++ return i + j + 1 < ((Level) world).paperConfig.bambooMaxHeight && (Integer) world.getBlockState(pos.above(i)).getValue(BambooBlock.STAGE) != 1; // Paper + } + + @Override +@@ -174,7 +174,7 @@ public class BambooBlock extends Block implements BonemealableBlock { + BlockPos blockposition1 = pos.above(i); + BlockState iblockdata1 = world.getBlockState(blockposition1); + +- if (k >= 16 || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here ++ if (k >= world.paperConfig.bambooMaxHeight || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here // Paper - Configurable cactus bamboo and reed growth heights + return; + } + +@@ -215,7 +215,7 @@ public class BambooBlock extends Block implements BonemealableBlock { + } + + int j = (Integer) state.getValue(BambooBlock.AGE) != 1 && !iblockdata2.is(Blocks.BAMBOO) ? 0 : 1; +- int k = (height < 11 || random.nextFloat() >= 0.25F) && height != 15 ? 0 : 1; ++ int k = (height < world.paperConfig.bambooMinHeight || random.nextFloat() >= 0.25F) && height != (world.paperConfig.bambooMaxHeight - 1) ? 0 : 1; // Paper + + // CraftBukkit start + if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, pos.above(), (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(BambooBlock.AGE, j)).setValue(BambooBlock.LEAVES, blockpropertybamboosize)).setValue(BambooBlock.STAGE, k), 3)) { +@@ -230,7 +230,7 @@ public class BambooBlock extends Block implements BonemealableBlock { + protected int getHeightAboveUpToMax(BlockGetter world, BlockPos pos) { + int i; + +- for (i = 0; i < 16 && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { ++ for (i = 0; i < ((Level) world).paperConfig.bambooMaxHeight && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper + ; + } + +@@ -240,7 +240,7 @@ public class BambooBlock extends Block implements BonemealableBlock { + protected int getHeightBelowUpToMax(BlockGetter world, BlockPos pos) { + int i; + +- for (i = 0; i < 16 && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { ++ for (i = 0; i < ((Level) world).paperConfig.bambooMaxHeight && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper + ; + } + +diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java +index d07fd9c1f726b1d45992352408499034c12683e6..de61393e3f702554817d81ff10693ec3fb63d492 100644 +--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java +@@ -54,7 +54,7 @@ public class CactusBlock extends Block { + ; + } + +- if (i < 3) { ++ if (i < world.paperConfig.cactusMaxHeight) { // Paper - Configurable growth height + int j = (Integer) state.getValue(CactusBlock.AGE); + + if (j >= (byte) range(3, ((100.0F / world.spigotConfig.cactusModifier) * 15) + 0.5F, 15)) { // Spigot +diff --git a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java +index 25f634ee93fa4678eaf09694d98783f2aef9d0f0..a795732af122204b88a01311e73892658132da25 100644 +--- a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java +@@ -51,7 +51,7 @@ public class SugarCaneBlock extends Block { + ; + } + +- if (i < 3) { ++ if (i < world.paperConfig.reedMaxHeight) { // Paper - Configurable growth height + int j = (Integer) state.getValue(SugarCaneBlock.AGE); + + if (j >= (byte) range(3, ((100.0F / world.spigotConfig.caneModifier) * 15) + 0.5F, 15)) { // Spigot diff --git a/Remapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch b/Remapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch new file mode 100644 index 0000000000..1b143bb4a0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 13:09:16 -0600 +Subject: [PATCH] Configurable baby zombie movement speed + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3618cc017feb60e257a28f67cbddca3f792a9833..796c17e0941922a9716212c6eae91643d8360418 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -78,4 +78,15 @@ public class PaperWorldConfig { + log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); + + } ++ ++ public double babyZombieMovementModifier; ++ private void babyZombieMovementModifier() { ++ babyZombieMovementModifier = getDouble("baby-zombie-movement-modifier", 0.5D); ++ if (PaperConfig.version < 20) { ++ babyZombieMovementModifier = getDouble("baby-zombie-movement-speed", 0.5D); ++ set("baby-zombie-movement-modifier", babyZombieMovementModifier); ++ } ++ ++ log("Baby zombies will move at the speed of " + babyZombieMovementModifier); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 992c9646c274350b30c1abb75e0469adc471397f..94e2a8f74e74d68d4a9b82b667fbff24b7e9e629 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -79,7 +79,7 @@ import org.bukkit.event.entity.EntityTransformEvent; + public class Zombie extends Monster { + + private static final UUID SPEED_MODIFIER_BABY_UUID = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836"); +- private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); ++ private final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); private final AttributeModifier babyModifier = this.SPEED_MODIFIER_BABY; // Paper - remove static - Make baby speed configurable + private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT); + public static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); +@@ -182,9 +182,9 @@ public class Zombie extends Monster { + if (this.level != null && !this.level.isClientSide) { + AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- attributemodifiable.removeModifier(Zombie.SPEED_MODIFIER_BABY); ++ attributemodifiable.removeModifier(this.babyModifier); // Paper + if (baby) { +- attributemodifiable.addTransientModifier(Zombie.SPEED_MODIFIER_BABY); ++ attributemodifiable.addTransientModifier(this.babyModifier); // Paper + } + } + diff --git a/Remapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch b/Remapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch new file mode 100644 index 0000000000..33edff1ef7 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 13:14:11 -0600 +Subject: [PATCH] Configurable fishing time ranges + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 796c17e0941922a9716212c6eae91643d8360418..78948c42b13194005bdbbbc69c2b7ae0732a78c5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -89,4 +89,12 @@ public class PaperWorldConfig { + + log("Baby zombies will move at the speed of " + babyZombieMovementModifier); + } ++ ++ public int fishingMinTicks; ++ public int fishingMaxTicks; ++ private void fishingTickRange() { ++ fishingMinTicks = getInt("fishing-time-range.MinimumTicks", 100); ++ fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); ++ log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +index d74dae6d7bd78c082b39a4e38da640a57c40b341..2f67c2065ef29f17f12190b25bd1ea53e1fb55b4 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +@@ -82,6 +82,10 @@ public class FishingHook extends Projectile { + owner.fishing = this; + this.luck = Math.max(0, lureLevel); + this.lureSpeed = Math.max(0, luckOfTheSeaLevel); ++ // Paper start ++ minWaitTime = world.paperConfig.fishingMinTicks; ++ maxWaitTime = world.paperConfig.fishingMaxTicks; ++ // paper end + } + + public FishingHook(net.minecraft.world.entity.player.Player thrower, Level world, int lureLevel, int luckOfTheSeaLevel) { diff --git a/Remapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/Remapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch new file mode 100644 index 0000000000..6f5fd676df --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch @@ -0,0 +1,105 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 13:24:16 -0600 +Subject: [PATCH] Allow nerfed mobs to jump and take water damage + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 78948c42b13194005bdbbbc69c2b7ae0732a78c5..b41e7922dd96c3358eb849ab39982a75736e3476 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -97,4 +97,9 @@ public class PaperWorldConfig { + fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); + log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); + } ++ ++ public boolean nerfedMobsShouldJump; ++ private void nerfedMobsShouldJump() { ++ nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 2a7f587e19fcdd6d01b360d6b47d9eadd9df92cc..584e83441a9fef88eb1b0a29bec8bda29d6a0c9c 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1104,6 +1104,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.isInWater() || this.isInRain(); + } + ++ public final boolean isInWaterOrRainOrBubble() { return isInWaterRainOrBubble(); } // Paper - OBFHELPER + public boolean isInWaterRainOrBubble() { + return this.isInWater() || this.isInRain() || this.isInBubbleColumn(); + } +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 99cb4dc1a1009d4a29e651c94d21babcc61388ed..151ebcffc1f2ae02fa55ab83d2ae7d8a0057f29d 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.entity; + ++import PathfinderGoalFloat; + import com.google.common.collect.Maps; + import java.util.Arrays; + import java.util.Iterator; +@@ -96,6 +97,7 @@ public abstract class Mob extends LivingEntity { + private final BodyRotationControl bodyRotationControl; + protected PathNavigation navigation; + public GoalSelector goalSelector; ++ @Nullable public PathfinderGoalFloat goalFloat; // Paper + public GoalSelector targetSelector; + private LivingEntity target; + private final Sensing sensing; +@@ -782,7 +784,17 @@ public abstract class Mob extends LivingEntity { + @Override + protected final void serverAiStep() { + ++this.noActionTime; +- if (!this.aware) return; // CraftBukkit ++ if (!this.aware) { // Paper start - Allow nerfed mobs to jump, float and take water damage ++ if (goalFloat != null) { ++ if (goalFloat.validConditions()) goalFloat.update(); ++ this.getJumpControl().jumpIfSet(); ++ } ++ if ((this instanceof EntityBlaze || this instanceof EntityEnderman) && isInWaterOrRainOrBubble()) { ++ hurt(DamageSource.DROWN, 1.0F); ++ } ++ return; ++ } ++ // Paper end + this.level.getProfiler().push("sensing"); + this.sensing.tick(); + this.level.getProfiler().pop(); +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java b/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java +index 5f7ad2b57d8d8f0f6a7d880f55e08b52f017cf51..09d1cda50ce9076e9236d124aa7766a26a50dae1 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java +@@ -15,6 +15,7 @@ public class JumpControl { + this.jump = true; + } + ++ public final void jumpIfSet() { this.tick(); } // Paper - OBFHELPER + public void tick() { + this.mob.setJumping(this.jump); + this.jump = false; +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java +index 7ea5cb5a92ff3b66859ebcd53031aa06689bd329..790b5646683247ef757095a0763dc52701afe97b 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java +@@ -11,15 +11,18 @@ public class FloatGoal extends Goal { + + public FloatGoal(Mob mob) { + this.mob = mob; ++ if (mob.getCommandSenderWorld().paperConfig.nerfedMobsShouldJump) mob.goalFloat = this; // Paper + this.setFlags(EnumSet.of(Goal.Flag.JUMP)); + mob.getNavigation().setCanFloat(true); + } + ++ public final boolean validConditions() { return this.canUse(); } // Paper - OBFHELPER + @Override + public boolean canUse() { + return this.mob.isInWater() && this.mob.getFluidHeight((Tag) FluidTags.WATER) > this.mob.getFluidJumpThreshold() || this.mob.isInLava(); + } + ++ public void update() { this.tick(); } // Paper - OBFHELPER + @Override + public void tick() { + if (this.mob.getRandom().nextFloat() < 0.8F) { diff --git a/Remapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch b/Remapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch new file mode 100644 index 0000000000..4a3d5d60ea --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Suddenly +Date: Tue, 1 Mar 2016 13:51:54 -0600 +Subject: [PATCH] Add configurable despawn distances for living entities + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index b41e7922dd96c3358eb849ab39982a75736e3476..2f0d582baf0eb2bb477944d0cb1369db6ca33956 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -102,4 +102,20 @@ public class PaperWorldConfig { + private void nerfedMobsShouldJump() { + nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); + } ++ ++ public int softDespawnDistance; ++ public int hardDespawnDistance; ++ private void despawnDistances() { ++ softDespawnDistance = getInt("despawn-ranges.soft", 32); // 32^2 = 1024, Minecraft Default ++ hardDespawnDistance = getInt("despawn-ranges.hard", 128); // 128^2 = 16384, Minecraft Default ++ ++ if (softDespawnDistance > hardDespawnDistance) { ++ softDespawnDistance = hardDespawnDistance; ++ } ++ ++ log("Living Entity Despawn Ranges: Soft: " + softDespawnDistance + " Hard: " + hardDespawnDistance); ++ ++ softDespawnDistance = softDespawnDistance*softDespawnDistance; ++ hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 151ebcffc1f2ae02fa55ab83d2ae7d8a0057f29d..4d3000067ae3d46b7ed4dda6146a21993199c6d9 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -762,16 +762,16 @@ public abstract class Mob extends LivingEntity { + int i = this.getType().getCategory().getDespawnDistance(); + int j = i * i; + +- if (d0 > (double) j) { // CraftBukkit - remove isTypeNotPersistent() check ++ if (d0 > (double) level.paperConfig.hardDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances + this.remove(); + } + + int k = this.getType().getCategory().getNoDespawnDistance(); + int l = k * k; + +- if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > (double) l) { // CraftBukkit - remove isTypeNotPersistent() check ++ if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > level.paperConfig.softDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances + this.remove(); +- } else if (d0 < (double) l) { ++ } else if (d0 < level.paperConfig.softDespawnDistance) { // Paper - custom despawn distances + this.noActionTime = 0; + } + } diff --git a/Remapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch b/Remapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch new file mode 100644 index 0000000000..91cd6d02b8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 3 Mar 2016 03:53:43 -0600 +Subject: [PATCH] Allow for toggling of spawn chunks + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2f0d582baf0eb2bb477944d0cb1369db6ca33956..89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -118,4 +118,10 @@ public class PaperWorldConfig { + softDespawnDistance = softDespawnDistance*softDespawnDistance; + hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; + } ++ ++ public boolean keepSpawnInMemory; ++ private void keepSpawnInMemory() { ++ keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); ++ log("Keep spawn chunk loaded: " + keepSpawnInMemory); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index c153df1f4dea3dc0ae744bde01e334b3bd3b50af..832abf73bdab2488c5814ea6e57888aac1b26154 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -217,6 +217,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + }); + // CraftBukkit end + timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings ++ this.keepSpawnInMemory = this.paperConfig.keepSpawnInMemory; // Paper + this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + } diff --git a/Remapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch b/Remapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch new file mode 100644 index 0000000000..91e53448a3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Tue, 1 Mar 2016 14:14:15 -0600 +Subject: [PATCH] Drop falling block and tnt entities at the specified height + +* Dec 2, 2020 Added tnt nerf for tnt minecarts - Machine_Maker + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75..d16ae924bcbe31c964f7fb448757c748e5c4418c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -124,4 +124,14 @@ public class PaperWorldConfig { + keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); + log("Keep spawn chunk loaded: " + keepSpawnInMemory); + } ++ ++ public int fallingBlockHeightNerf; ++ public int entityTNTHeightNerf; ++ private void heightNerfs() { ++ fallingBlockHeightNerf = getInt("falling-block-height-nerf", 0); ++ entityTNTHeightNerf = getInt("tnt-entity-height-nerf", 0); ++ ++ if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); ++ if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 584e83441a9fef88eb1b0a29bec8bda29d6a0c9c..706417f44c1eebc7cc5e8e7053fa0ab21f4caeba 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1849,6 +1849,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.spawnAtLocation(stack, 0.0F); + } + ++ @Nullable public final ItemEntity dropItem(ItemStack itemstack, float offset) { return this.spawnAtLocation(itemstack, offset); } // Paper - OBFHELPER + @Nullable + public ItemEntity spawnAtLocation(ItemStack stack, float yOffset) { + if (stack.isEmpty()) { +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 8a9e2316b9f5756503dc06e27981525d2cd7d1a5..5394bc6336cb84025c1c748fb5b3d38e0648a590 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -122,6 +122,17 @@ public class FallingBlockEntity extends Entity { + } + + this.move(MoverType.SELF, this.getDeltaMovement()); ++ ++ // Paper start - Configurable EntityFallingBlock height nerf ++ if (this.level.paperConfig.fallingBlockHeightNerf != 0 && this.getY() > this.level.paperConfig.fallingBlockHeightNerf) { ++ if (this.dropItem && this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { ++ this.spawnAtLocation(block); ++ } ++ ++ this.remove(); ++ return; ++ } ++ // Paper end + if (!this.level.isClientSide) { + blockposition = this.blockPosition(); + boolean flag = this.blockState.getBlock() instanceof ConcretePowderBlock; +diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +index ff15a372b7cad5fa88b7ef6de1f3441d93f9c67e..4c4262b8f0cb44b8cea8cb46194a6e70d4ce56f4 100644 +--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +@@ -69,6 +69,12 @@ public class PrimedTnt extends Entity { + } + + this.move(MoverType.SELF, this.getDeltaMovement()); ++ // Paper start - Configurable TNT entity height nerf ++ if (this.level.paperConfig.entityTNTHeightNerf != 0 && this.getY() > this.level.paperConfig.entityTNTHeightNerf) { ++ this.remove(); ++ return; ++ } ++ // Paper end + this.setDeltaMovement(this.getDeltaMovement().scale(0.98D)); + if (this.onGround) { + this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D)); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java +index c2ed3ba42d29a50386c94b109fdd3b2f2f1b433b..3b5e96f2325e14a94de0fb2d6da86812cecc7395 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java +@@ -47,6 +47,12 @@ public class MinecartTNT extends AbstractMinecart { + public void tick() { + super.tick(); + if (this.fuse > 0) { ++ // Paper start - Configurable TNT entity height nerf ++ if (this.level.paperConfig.entityTNTHeightNerf != 0 && this.getY() > this.level.paperConfig.entityTNTHeightNerf) { ++ this.remove(); ++ return; ++ } ++ // Paper end + --this.fuse; + this.level.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D); + } else if (this.fuse == 0) { diff --git a/Remapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/Remapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch new file mode 100644 index 0000000000..e00adead2f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 14:32:43 -0600 +Subject: [PATCH] Show 'Paper' in client crashes, server lists, and Mojang + stats + + +diff --git a/src/main/java/net/minecraft/server/Eula.java b/src/main/java/net/minecraft/server/Eula.java +index 6934b0fdfe11ef673a3e4ae7564d04acee169252..9f104b1bd05d9f344579f086b2b9c00af1750690 100644 +--- a/src/main/java/net/minecraft/server/Eula.java ++++ b/src/main/java/net/minecraft/server/Eula.java +@@ -72,7 +72,7 @@ public class Eula { + Properties properties = new Properties(); + + properties.setProperty("eula", "false"); +- properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula)."); ++ properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\nYou also agree that tacos are tasty, and the best food in the world."); // Paper - fix lag; + } catch (Throwable throwable1) { + throwable = throwable1; + throw throwable1; +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index a456b9cbf0e5eea4e888e0e3d07ed17558650371..fa29790600021809f31092a90e1a3a9b84d5e0c4 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1340,7 +1340,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop // CraftBukkit - cb > vanilla! ++ return "Paper"; //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! + } + + public CrashReport fillReport(CrashReport report) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index f7f5457d20586e0ba72368e64ff6025f6755e61e..f81def94a1a7ab3a24b74a8bbd5f3e8ebae2c0d5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -224,7 +224,7 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; + import net.md_5.bungee.api.chat.BaseComponent; // Spigot + + public final class CraftServer implements Server { +- private final String serverName = "CraftBukkit"; ++ private final String serverName = "Paper"; // Paper + private final String serverVersion; + private final String bukkitVersion = Versioning.getBukkitVersion(); + private final Logger logger = Logger.getLogger("Minecraft"); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index ce9f10f890a5866ab6208c7253b15b09fe323a81..e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -206,12 +206,25 @@ public class Main { + deadline.add(Calendar.DAY_OF_YEAR, -28); + 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 ***"); ++ System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper + System.err.println("*** Server will start in 20 seconds ***"); + Thread.sleep(TimeUnit.SECONDS.toMillis(20)); + } + } + ++ // Paper start - Log Java and OS versioning to help with debugging plugin issues ++ java.lang.management.RuntimeMXBean runtimeMX = java.lang.management.ManagementFactory.getRuntimeMXBean(); ++ java.lang.management.OperatingSystemMXBean osMX = java.lang.management.ManagementFactory.getOperatingSystemMXBean(); ++ if (runtimeMX != null && osMX != null) { ++ String javaInfo = "Java " + runtimeMX.getSpecVersion() + " (" + runtimeMX.getVmName() + " " + runtimeMX.getVmVersion() + ")"; ++ String osInfo = "Host: " + osMX.getName() + " " + osMX.getVersion() + " (" + osMX.getArch() + ")"; ++ ++ System.out.println("System Info: " + javaInfo + " " + osInfo); ++ } else { ++ System.out.println("Unable to read system info"); ++ } ++ // Paper end ++ + System.out.println("Loading libraries, please wait..."); + net.minecraft.server.Main.main(options); + } catch (Throwable t) { +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 9a695b80ef57d677fbdee1bfc59f0f9125a7ebd4..21d7b483920841456707fe3f08b180c1f072b7f7 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -19,7 +19,7 @@ public class WatchdogThread extends Thread + + private WatchdogThread(long timeoutTime, boolean restart) + { +- super( "Spigot Watchdog Thread" ); ++ super( "Paper Watchdog Thread" ); + this.timeoutTime = timeoutTime; + this.restart = restart; + } +@@ -65,14 +65,14 @@ public class WatchdogThread extends Thread + { + Logger log = Bukkit.getServer().getLogger(); + log.log( Level.SEVERE, "------------------------------" ); +- log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Spigot bug." ); ++ log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper + log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); + log.log( Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring" ); + log.log( Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once" ); + log.log( Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes" ); +- log.log( Level.SEVERE, "If you are unsure or still think this is a Spigot bug, please report to https://www.spigotmc.org/" ); ++ log.log( Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues" ); + log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); +- log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() ); ++ log.log( Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion() ); + // + if ( net.minecraft.world.level.Level.lastPhysicsProblem != null ) + { +@@ -82,7 +82,7 @@ public class WatchdogThread extends Thread + } + // + log.log( Level.SEVERE, "------------------------------" ); +- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" ); ++ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // diff --git a/Remapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch b/Remapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch new file mode 100644 index 0000000000..66c45ee1f0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 27 May 2019 03:40:05 -0500 +Subject: [PATCH] Implement Paper VersionChecker + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1a1b50e475b9ede544b2f6d0d36632b24b68898c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +@@ -0,0 +1,122 @@ ++package com.destroystokyo.paper; ++ ++import com.destroystokyo.paper.util.VersionFetcher; ++import com.google.common.base.Charsets; ++import com.google.common.io.Resources; ++import com.google.gson.*; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.format.NamedTextColor; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++import java.io.*; ++import java.net.HttpURLConnection; ++import java.net.URL; ++import java.util.stream.StreamSupport; ++ ++public class PaperVersionFetcher implements VersionFetcher { ++ private static final java.util.regex.Pattern VER_PATTERN = java.util.regex.Pattern.compile("^([0-9\\.]*)\\-.*R"); // R is an anchor, will always give '-R' at end ++ private static final String GITHUB_BRANCH_NAME = "master"; ++ private static @Nullable String mcVer; ++ ++ @Override ++ public long getCacheTime() { ++ return 720000; ++ } ++ ++ @Nonnull ++ @Override ++ public Component getVersionMessage(@Nonnull String serverVersion) { ++ String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); ++ return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); ++ } ++ ++ private static @Nullable String getMinecraftVersion() { ++ if (mcVer == null) { ++ java.util.regex.Matcher matcher = VER_PATTERN.matcher(org.bukkit.Bukkit.getBukkitVersion()); ++ if (matcher.find()) { ++ String result = matcher.group(); ++ mcVer = result.substring(0, result.length() - 2); // strip 'R' anchor and trailing '-' ++ } else { ++ org.bukkit.Bukkit.getLogger().warning("Unable to match version to pattern! Report to PaperMC!"); ++ org.bukkit.Bukkit.getLogger().warning("Pattern: " + VER_PATTERN.toString()); ++ org.bukkit.Bukkit.getLogger().warning("Version: " + org.bukkit.Bukkit.getBukkitVersion()); ++ } ++ } ++ ++ return mcVer; ++ } ++ ++ private static Component getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) { ++ int distance; ++ try { ++ int jenkinsBuild = Integer.parseInt(versionInfo); ++ distance = fetchDistanceFromSiteApi(jenkinsBuild, getMinecraftVersion()); ++ } catch (NumberFormatException ignored) { ++ versionInfo = versionInfo.replace("\"", ""); ++ distance = fetchDistanceFromGitHub(repo, branch, versionInfo); ++ } ++ ++ switch (distance) { ++ case -1: ++ return Component.text("Error obtaining version information", NamedTextColor.YELLOW); ++ case 0: ++ return Component.text("You are running the latest version", NamedTextColor.GREEN); ++ case -2: ++ return Component.text("Unknown version", NamedTextColor.YELLOW); ++ default: ++ return Component.text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW); ++ } ++ } ++ ++ private static int fetchDistanceFromSiteApi(int jenkinsBuild, @Nullable String siteApiVersion) { ++ if (siteApiVersion == null) { return -1; } ++ try { ++ try (BufferedReader reader = Resources.asCharSource( ++ new URL("https://papermc.io/api/v2/projects/paper/versions/" + siteApiVersion), ++ Charsets.UTF_8 ++ ).openBufferedStream()) { ++ JsonObject json = new Gson().fromJson(reader, JsonObject.class); ++ JsonArray builds = json.getAsJsonArray("builds"); ++ int latest = StreamSupport.stream(builds.spliterator(), false) ++ .mapToInt(e -> e.getAsInt()) ++ .max() ++ .getAsInt(); ++ return latest - jenkinsBuild; ++ } catch (JsonSyntaxException ex) { ++ ex.printStackTrace(); ++ return -1; ++ } ++ } catch (IOException e) { ++ e.printStackTrace(); ++ return -1; ++ } ++ } ++ ++ // Contributed by Techcable in GH-65 ++ private static int fetchDistanceFromGitHub(@Nonnull String repo, @Nonnull String branch, @Nonnull String hash) { ++ try { ++ HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + repo + "/compare/" + branch + "..." + hash).openConnection(); ++ connection.connect(); ++ if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return -2; // Unknown commit ++ try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) { ++ JsonObject obj = new Gson().fromJson(reader, JsonObject.class); ++ String status = obj.get("status").getAsString(); ++ switch (status) { ++ case "identical": ++ return 0; ++ case "behind": ++ return obj.get("behind_by").getAsInt(); ++ default: ++ return -1; ++ } ++ } catch (JsonSyntaxException | NumberFormatException e) { ++ e.printStackTrace(); ++ return -1; ++ } ++ } catch (IOException e) { ++ e.printStackTrace(); ++ return -1; ++ } ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 2d4faef5a2b9c4fe8b65ff4f1346b8375e0e02c8..21052d0e88351b075733331d71e07b086354b820 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -368,6 +368,11 @@ public final class CraftMagicNumbers implements UnsafeValues { + public String getTimingsServerName() { + return com.destroystokyo.paper.PaperConfig.timingsServerName; + } ++ ++ @Override ++ public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { ++ return new com.destroystokyo.paper.PaperVersionFetcher(); ++ } + // Paper end + + /** diff --git a/Remapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch b/Remapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch new file mode 100644 index 0000000000..4985c3e747 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch @@ -0,0 +1,215 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Thu, 1 Mar 2018 19:37:52 -0600 +Subject: [PATCH] Add version history to version command + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +index 1a1b50e475b9ede544b2f6d0d36632b24b68898c..580bae0d414d371a07a6bfeefc41fdd989dc0083 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java ++++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +@@ -5,7 +5,9 @@ import com.google.common.base.Charsets; + import com.google.common.io.Resources; + import com.google.gson.*; + import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.TextComponent; + import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.format.TextDecoration; + + import javax.annotation.Nonnull; + import javax.annotation.Nullable; +@@ -28,7 +30,10 @@ public class PaperVersionFetcher implements VersionFetcher { + @Override + public Component getVersionMessage(@Nonnull String serverVersion) { + String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); +- return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); ++ final Component updateMessage = getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); ++ final Component history = getHistory(); ++ ++ return history != null ? TextComponent.ofChildren(updateMessage, Component.newline(), history) : updateMessage; + } + + private static @Nullable String getMinecraftVersion() { +@@ -119,4 +124,19 @@ public class PaperVersionFetcher implements VersionFetcher { + return -1; + } + } ++ ++ @Nullable ++ private Component getHistory() { ++ final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); ++ if (data == null) { ++ return null; ++ } ++ ++ final String oldVersion = data.getOldVersion(); ++ if (oldVersion == null) { ++ return null; ++ } ++ ++ return Component.text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC); ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..aac3f66cb23d260729c2a48d8710a9de2346aa22 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java +@@ -0,0 +1,145 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.MoreObjects; ++import com.google.gson.Gson; ++import com.google.gson.JsonSyntaxException; ++import java.io.BufferedReader; ++import java.io.BufferedWriter; ++import java.io.IOException; ++import java.nio.charset.StandardCharsets; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.nio.file.Paths; ++import java.nio.file.StandardOpenOption; ++import java.util.Objects; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++import org.bukkit.Bukkit; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++ ++public enum VersionHistoryManager { ++ INSTANCE; ++ ++ private final Gson gson = new Gson(); ++ ++ private final Logger logger = Bukkit.getLogger(); ++ ++ private VersionData currentData = null; ++ ++ VersionHistoryManager() { ++ final Path path = Paths.get("version_history.json"); ++ ++ if (Files.exists(path)) { ++ // Basic file santiy checks ++ if (!Files.isRegularFile(path)) { ++ if (Files.isDirectory(path)) { ++ logger.severe(path + " is a directory, cannot be used for version history"); ++ } else { ++ logger.severe(path + " is not a regular file, cannot be used for version history"); ++ } ++ // We can't continue ++ return; ++ } ++ ++ try (final BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { ++ currentData = gson.fromJson(reader, VersionData.class); ++ } catch (final IOException e) { ++ logger.log(Level.SEVERE, "Failed to read version history file '" + path + "'", e); ++ return; ++ } catch (final JsonSyntaxException e) { ++ logger.log(Level.SEVERE, "Invalid json syntax for file '" + path + "'", e); ++ return; ++ } ++ ++ final String version = Bukkit.getVersion(); ++ if (version == null) { ++ logger.severe("Failed to retrieve current version"); ++ return; ++ } ++ ++ if (!version.equals(currentData.getCurrentVersion())) { ++ // The version appears to have changed ++ currentData.setOldVersion(currentData.getCurrentVersion()); ++ currentData.setCurrentVersion(version); ++ writeFile(path); ++ } ++ } else { ++ // File doesn't exist, start fresh ++ currentData = new VersionData(); ++ // oldVersion is null ++ currentData.setCurrentVersion(Bukkit.getVersion()); ++ writeFile(path); ++ } ++ } ++ ++ private void writeFile(@Nonnull final Path path) { ++ try (final BufferedWriter writer = Files.newBufferedWriter( ++ path, ++ StandardCharsets.UTF_8, ++ StandardOpenOption.WRITE, ++ StandardOpenOption.CREATE, ++ StandardOpenOption.TRUNCATE_EXISTING ++ )) { ++ gson.toJson(currentData, writer); ++ } catch (final IOException e) { ++ logger.log(Level.SEVERE, "Failed to write to version history file", e); ++ } ++ } ++ ++ @Nullable ++ public VersionData getVersionData() { ++ return currentData; ++ } ++ ++ public static class VersionData { ++ private String oldVersion; ++ ++ private String currentVersion; ++ ++ @Nullable ++ public String getOldVersion() { ++ return oldVersion; ++ } ++ ++ public void setOldVersion(@Nullable String oldVersion) { ++ this.oldVersion = oldVersion; ++ } ++ ++ @Nullable ++ public String getCurrentVersion() { ++ return currentVersion; ++ } ++ ++ public void setCurrentVersion(@Nullable String currentVersion) { ++ this.currentVersion = currentVersion; ++ } ++ ++ @Override ++ public String toString() { ++ return MoreObjects.toStringHelper(this) ++ .add("oldVersion", oldVersion) ++ .add("currentVersion", currentVersion) ++ .toString(); ++ } ++ ++ @Override ++ public boolean equals(@Nullable Object o) { ++ if (this == o) { ++ return true; ++ } ++ if (o == null || getClass() != o.getClass()) { ++ return false; ++ } ++ final VersionData versionData = (VersionData) o; ++ return Objects.equals(oldVersion, versionData.oldVersion) && ++ Objects.equals(currentVersion, versionData.currentVersion); ++ } ++ ++ @Override ++ public int hashCode() { ++ return Objects.hash(oldVersion, currentVersion); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 40fe03c844c8bf6a9c4c5ae028b259f01a81eead..c7655883262f122b373ac30a33ddb4c06cd9aebe 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -193,6 +193,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + return false; + } + com.destroystokyo.paper.PaperConfig.registerCommands(); ++ com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now + // Paper end + + this.setPvpAllowed(dedicatedserverproperties.pvp); diff --git a/Remapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch b/Remapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch new file mode 100644 index 0000000000..08d7ac1c4a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch @@ -0,0 +1,157 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Tue, 1 Mar 2016 14:47:52 -0600 +Subject: [PATCH] Player affects spawning API + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 706417f44c1eebc7cc5e8e7053fa0ab21f4caeba..392f2f2d67b688d5b37f77c8e4b3036348472d77 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1353,6 +1353,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return Mth.sqrt(f * f + f1 * f1 + f2 * f2); + } + ++ public double getDistanceSquared(double x, double y, double z) { return distanceToSqr(x, y, z); } // Paper - OBFHELPER + public double distanceToSqr(double x, double y, double z) { + double d3 = this.getX() - x; + double d4 = this.getY() - y; +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index f8c13881f59ccaccf8d8e5496d2f8f49ba7d7343..a3bad391a719363077740aa810c9412df34b4ae5 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -29,6 +29,12 @@ public final class EntitySelector { + return !entity.isSpectator(); + }; + ++ // Paper start ++ public static final Predicate affectsSpawning = (entity) -> { ++ return !entity.isSpectator() && entity.isAlive() && (entity instanceof EntityPlayer) && ((EntityPlayer) entity).affectsSpawning; ++ }; ++ // Paper end ++ + public static Predicate withinDistance(double x, double y, double z, double d3) { + double d4 = d3 * d3; + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 4d3000067ae3d46b7ed4dda6146a21993199c6d9..09d39b73e8a3987e58a502bd914a6451b807421b 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -755,7 +755,7 @@ public abstract class Mob extends LivingEntity { + if (this.level.getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) { + this.remove(); + } else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) { +- Player entityhuman = this.level.getNearestPlayer(this, -1.0D); ++ Player entityhuman = this.level.findNearbyPlayer(this, -1.0D, EntitySelector.affectsSpawning); // Paper + + if (entityhuman != null) { + double d0 = entityhuman.distanceToSqr((Entity) this); // CraftBukkit - decompile error +diff --git a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java +index 4ce9e37d7334ba0557c397c0ebd2cb7928c7c564..cfdbaec1de6add7a189c26eb66701dfa5f40fe4f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java +@@ -122,7 +122,7 @@ public class Silverfish extends Monster { + if (checkAnyLightMonsterSpawnRules(type, world, spawnReason, pos, random)) { + Player entityhuman = world.getNearestPlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0D, true); + +- return entityhuman == null; ++ return !(entityhuman != null && !entityhuman.affectsSpawning) && entityhuman == null; // Paper - Affects Spawning API + } else { + return 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 91f605c803c021c8743de87b67dcb0fb9fc807e9..3b451e75a7f49ea6b543aee9f0a51c0be3c4dfba 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -161,6 +161,9 @@ public abstract class Player extends LivingEntity { + private final ItemCooldowns cooldowns; + @Nullable + public FishingHook fishing; ++ // Paper start ++ public boolean affectsSpawning = true; ++ // Paper end + + // CraftBukkit start + public boolean fauxSleeping; +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 98f85d59bc48451ef6381a47fe341f77b9920981..10058d3c3565382faa893b79119c5caf845bf29a 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -66,7 +66,7 @@ public abstract class BaseSpawner { + private boolean isNearPlayer() { + BlockPos blockposition = this.getPos(); + +- return this.getLevel().hasNearbyAlivePlayer((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); ++ return this.getLevel().isAffectsSpawningPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper + } + + public void tick() { +diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java +index 7e7a58b9a9ececdcc37fc33b33703428eb1d5faf..66681b9f0e2531d3da25629e44180417b32b4d66 100644 +--- a/src/main/java/net/minecraft/world/level/EntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/EntityGetter.java +@@ -92,8 +92,9 @@ public interface EntityGetter { + } + } + +- @Nullable +- default Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate targetPredicate) { ++ default Player findNearbyPlayer(Entity entity, double d0, @Nullable Predicate predicate) { return this.findNearbyPlayer(entity.getX(), entity.getY(), entity.getZ(), d0, predicate); } // Paper ++ @Nullable default Player findNearbyPlayer(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { return getNearestPlayer(d0, d1, d2, d3, predicate); } // Paper - OBFHELPER ++ @Nullable default Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate targetPredicate) { // Paper + double d4 = -1.0D; + Player entityhuman = null; + Iterator iterator = this.players().iterator(); +@@ -126,6 +127,27 @@ public interface EntityGetter { + return this.getNearestPlayer(x, y, z, maxDistance, predicate); + } + ++ // Paper end ++ default boolean isAffectsSpawningPlayerNearby(double d0, double d1, double d2, double d3) { ++ Iterator iterator = this.players().iterator(); ++ double d4; ++ do { ++ Player entityhuman; ++ do { ++ if (!iterator.hasNext()) { ++ return false; ++ } ++ ++ entityhuman = (Player) iterator.next(); ++ } while (!EntitySelector.affectsSpawning.test(entityhuman)); ++ ++ d4 = entityhuman.getDistanceSquared(d0, d1, d2); ++ } while (d3 >= 0.0D && d4 >= d3 * d3); ++ ++ return true; ++ } ++ // Paper end ++ + default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) { + Iterator iterator = this.players().iterator(); + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 50d11611702e3d1f0e980fb8f2280b05b891167b..e6c39c822c6a910f63e9b4899d53b7d75e1b77cf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1768,8 +1768,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + @Override + public String getLocale() { + return getHandle().locale; ++ ++ } ++ ++ // Paper start ++ public void setAffectsSpawning(boolean affects) { ++ this.getHandle().affectsSpawning = affects; + } + ++ @Override ++ public boolean getAffectsSpawning() { ++ return this.getHandle().affectsSpawning; ++ } ++ // Paper end ++ + @Override + public void updateCommands() { + if (getHandle().connection == null) return; diff --git a/Remapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch b/Remapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch new file mode 100644 index 0000000000..23323c9803 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Tue, 1 Mar 2016 15:08:03 -0600 +Subject: [PATCH] Remove invalid mob spawner tile entities + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index f30793b81dfd9018b4879d655c7c18a9f9c25267..300749822d52f9f973e71c6ec9c8bf29d6a6938e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -41,7 +41,9 @@ import net.minecraft.world.level.TickList; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EntityBlock; ++import net.minecraft.world.level.block.SpawnerBlock; + import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.entity.SpawnerBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.levelgen.DebugLevelSource; + import net.minecraft.world.level.levelgen.Heightmap; +@@ -647,6 +649,10 @@ public class LevelChunk implements ChunkAccess { + } + + // CraftBukkit start ++ // Paper start - Remove invalid mob spawner tile entities ++ } else if (blockEntity instanceof SpawnerBlockEntity && !(getBlockData(pos.getX(), pos.getY(), pos.getZ()).getBlock() instanceof SpawnerBlock)) { ++ this.blockEntities.remove(pos); ++ // Paper end + } else { + System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() + + " (" + getBlockState(pos) + ") where there was no entity tile!"); diff --git a/Remapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch b/Remapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch new file mode 100644 index 0000000000..db2d2e1d05 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch @@ -0,0 +1,279 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 8 Mar 2015 22:55:25 -0600 +Subject: [PATCH] Optimize TileEntity Ticking + + +diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java +index 94adf0275a2e7093c152cc3b8b0a5747b3a13a86..5bcf9cefc29eb20e2cfbfb49e2b2662ec394a87e 100644 +--- a/src/main/java/co/aikar/timings/TimingsExport.java ++++ b/src/main/java/co/aikar/timings/TimingsExport.java +@@ -112,7 +112,7 @@ public class TimingsExport extends Thread { + pair("end", System.currentTimeMillis() / 1000), + pair("online-mode", Bukkit.getServer().getOnlineMode()), + pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), +- pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedIds(), pack -> { ++ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedPacks(), pack -> { + // Don't feel like obf helper'ing these, non fatal if its temp missed. + return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); + })) +@@ -151,8 +151,8 @@ public class TimingsExport extends Thread { + ); + + parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getAllLevels(), world -> { +- if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; +- return pair(world.getWorldData().getName(), createObject( ++ if (world.getWorld().getName().equals("worldeditregentempworld")) return null; ++ return pair(world.getWorld().getName(), createObject( + pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { + return pair(rule, world.getWorld().getGameRuleValue(rule)); + })), +diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +index 56656bf34db07bc717ace8ae9c1b60f9bfd7ff05..1bda9a158eb4372b9ab7cf3097732e64810aefc6 100644 +--- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +@@ -54,8 +54,8 @@ import net.minecraft.world.phys.shapes.VoxelShape; + public class ChestBlock extends AbstractChestBlock implements SimpleWaterloggedBlock { + + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; +- public static final EnumProperty TYPE = BlockStateProperties.CHEST_TYPE; +- public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; ++ public static final EnumProperty TYPE = BlockStateProperties.CHEST_TYPE; public static final EnumProperty CHEST_TYPE_PROPERTY = TYPE; // Paper - OBFHELPER ++ public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; public static final BooleanProperty waterlogged() { return WATERLOGGED; } // Paper OBFHELPER + protected static final VoxelShape NORTH_AABB = Block.box(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D); + protected static final VoxelShape SOUTH_AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D); + protected static final VoxelShape WEST_AABB = Block.box(0.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java +index 7b08ee35d2d8dc3fe783d773bf6686a5197006b8..17289d28b6d0023279a573715ee3d182988dd651 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java +@@ -8,6 +8,7 @@ import net.minecraft.core.NonNullList; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; +@@ -32,7 +33,7 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.entity.HumanEntity; + // CraftBukkit end + +-public class ChestBlockEntity extends RandomizableContainerBlockEntity implements TickableBlockEntity { ++public class ChestBlockEntity extends RandomizableContainerBlockEntity { // Paper - Remove ITickable + + private NonNullList items; + protected float openness; +@@ -110,14 +111,20 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + return tag; + } + +- @Override + public void tick() { + int i = this.worldPosition.getX(); + int j = this.worldPosition.getY(); + int k = this.worldPosition.getZ(); + + ++this.tickInterval; +- this.openCount = getOpenCount(this.level, this, this.tickInterval, i, j, k, this.openCount); ++ } ++ ++ public void doOpenLogic() { ++ int i = this.worldPosition.getX(); ++ int j = this.worldPosition.getY(); ++ int k = this.worldPosition.getZ(); ++ ++ //this.viewingCount = a(this.world, this, this.j, i, j, k, this.viewingCount); // Paper - check is faulty given our logic is called before active container set + this.oOpenness = this.openness; + float f = 0.1F; + +@@ -131,25 +138,31 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + if (this.openCount > 0 && this.openness == 0.0F) { + this.playSound(SoundEvents.CHEST_OPEN); + } ++ } + +- if (this.openCount == 0 && this.openness > 0.0F || this.openCount > 0 && this.openness < 1.0F) { +- float f1 = this.openness; ++ public void doCloseLogic() { ++ if (this.openCount == 0 /* && this.a > 0.0F || this.viewingCount > 0 && this.a < 1.0F */) { // Paper - disable all but player count check ++ /* // Paper - disable animation stuff ++ float f1 = this.a; + +- if (this.openCount > 0) { +- this.openness += 0.1F; ++ if (this.viewingCount > 0) { ++ this.a += 0.1F; + } else { +- this.openness -= 0.1F; ++ this.a -= 0.1F; + } + +- if (this.openness > 1.0F) { +- this.openness = 1.0F; ++ if (this.a > 1.0F) { ++ this.a = 1.0F; + } + + float f2 = 0.5F; + +- if (this.openness < 0.5F && f1 >= 0.5F) { ++ if (this.a < 0.5F && f1 >= 0.5F) { ++ */ ++ MCUtil.scheduleTask(10, () -> { + this.playSound(SoundEvents.CHEST_CLOSE); +- } ++ }, "Chest Sounds"); ++ //} // Paper end + + if (this.openness < 0.0F) { + this.openness = 0.0F; +@@ -188,6 +201,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + } + + public void playSound(SoundEvent soundeffect) { ++ if (!this.getBlockState().contains(ChestBlock.CHEST_TYPE_PROPERTY)) { return; } // Paper - this can be delayed, double check exists - Fixes GH-2074 + ChestType blockpropertychesttype = (ChestType) this.getBlockState().getValue(ChestBlock.TYPE); + + if (blockpropertychesttype != ChestType.LEFT) { +@@ -226,6 +240,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + + ++this.openCount; + if (this.level == null) return; // CraftBukkit ++ doOpenLogic(); // Paper + + // CraftBukkit start - Call redstone event + if (this.getBlockState().getBlock() == Blocks.TRAPPED_CHEST) { +@@ -248,6 +263,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + --this.openCount; + + // CraftBukkit start - Call redstone event ++ doCloseLogic(); // Paper + if (this.getBlockState().getBlock() == Blocks.TRAPPED_CHEST) { + int newPower = Math.max(0, Math.min(15, this.openCount)); + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java +index b26337770e13c20f57a4e74282710ce697ac0d41..8f0477d9620ef71e10855bbca07f9b6984d5d794 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java +@@ -1,11 +1,12 @@ + package net.minecraft.world.level.block.entity; + ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.block.Blocks; + +-public class EnderChestBlockEntity extends BlockEntity implements TickableBlockEntity { ++public class EnderChestBlockEntity extends BlockEntity { // Paper - Remove ITickable + + public float openness; + public float oOpenness; +@@ -16,18 +17,28 @@ public class EnderChestBlockEntity extends BlockEntity implements TickableBlockE + super(BlockEntityType.ENDER_CHEST); + } + +- @Override + public void tick() { + if (++this.tickInterval % 20 * 4 == 0) { + this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); + } + + this.oOpenness = this.openness; ++ /* // Paper ++ int i = this.position.getX(); ++ int j = this.position.getY(); ++ int k = this.position.getZ(); ++ float f = 0.1F; ++ double d0; ++ // Paper start ++ */ ++ } ++ ++ private void doOpenLogic() { + int i = this.worldPosition.getX(); + int j = this.worldPosition.getY(); + int k = this.worldPosition.getZ(); +- float f = 0.1F; + double d0; ++ // Paper end + + if (this.openCount > 0 && this.openness == 0.0F) { + double d1 = (double) i + 0.5D; +@@ -35,28 +46,40 @@ public class EnderChestBlockEntity extends BlockEntity implements TickableBlockE + d0 = (double) k + 0.5D; + this.level.playSound((Player) null, d1, (double) j + 0.5D, d0, SoundEvents.ENDER_CHEST_OPEN, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); + } ++ // Paper start ++ } + +- if (this.openCount == 0 && this.openness > 0.0F || this.openCount > 0 && this.openness < 1.0F) { +- float f1 = this.openness; ++ private void doCloseLogic() { ++ int i = this.worldPosition.getX(); ++ int j = this.worldPosition.getY(); ++ int k = this.worldPosition.getZ(); ++ double d0; ++ ++ if (this.openCount == 0) { /* && this.a > 0.0F || this.c > 0 && this.a < 1.0F) { ++ // Paper end ++ float f1 = this.a; + +- if (this.openCount > 0) { +- this.openness += 0.1F; ++ if (this.c > 0) { ++ this.a += 0.1F; + } else { +- this.openness -= 0.1F; ++ this.a -= 0.1F; + } + +- if (this.openness > 1.0F) { +- this.openness = 1.0F; ++ if (this.a > 1.0F) { ++ this.a = 1.0F; + } + + float f2 = 0.5F; + +- if (this.openness < 0.5F && f1 >= 0.5F) { ++ if (this.a < 0.5F && f1 >= 0.5F) { ++ // Paper start ++ */ + d0 = (double) i + 0.5D; + double d2 = (double) k + 0.5D; + ++ MCUtil.scheduleTask(10, () -> { + this.level.playSound((Player) null, d0, (double) j + 0.5D, d2, SoundEvents.ENDER_CHEST_CLOSE, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); +- } ++ }, "Chest Sounds"); + + if (this.openness < 0.0F) { + this.openness = 0.0F; +@@ -84,11 +107,13 @@ public class EnderChestBlockEntity extends BlockEntity implements TickableBlockE + public void startOpen() { + ++this.openCount; + this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); ++ doOpenLogic(); // Paper + } + + public void stopOpen() { + --this.openCount; + this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); ++ doCloseLogic(); // Paper + } + + public boolean stillValid(Player entityhuman) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java +index 60ce75c7f94c995d3753c40bc8d1ec09b4d37b1a..ac10fb9cd4701f0f6477a86bec73cb5ac6496725 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java ++++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java +@@ -84,6 +84,7 @@ public abstract class StateHolder { + return Collections.unmodifiableCollection(this.values.keySet()); + } + ++ public > boolean contains(Property iblockstate) { return this.hasProperty(iblockstate); } // Paper - OBFHELPER + public > boolean hasProperty(Property property) { + return this.values.containsKey(property); + } diff --git a/Remapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch b/Remapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch new file mode 100644 index 0000000000..ee0ab66ab5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch @@ -0,0 +1,208 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 1 Mar 2016 23:09:29 -0600 +Subject: [PATCH] Further improve server tick loop + +Improves how the catchup buffer is handled, allowing it to roll both ways +increasing the effeciency of the thread sleep so it only will sleep once. + +Also increases the buffer of the catchup to ensure server stays at 20 TPS unless extreme conditions + +Previous implementation did not calculate TPS correctly. +Switch to a realistic rolling average and factor in std deviation as an extra reporting variable + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index fa29790600021809f31092a90e1a3a9b84d5e0c4..526d6c0fa45bfba92a3f964f72e4965fd5c841c1 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -251,7 +251,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; + public Commands vanillaCommandDispatcher; +@@ -260,7 +260,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 5000L && this.nextTickTime - this.lastOverloadWarning >= 30000L) { // CraftBukkit + long j = i / 50L; + + if (server.getWarnOnOverload()) // CraftBukkit +- MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); ++ MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); + this.nextTickTime += j * 50L; + this.lastOverloadWarning = this.nextTickTime; + } + +- if ( tickCount++ % SAMPLE_INTERVAL == 0 ) ++ if ( ++MinecraftServer.currentTick % SAMPLE_INTERVAL == 0 ) + { +- double currentTps = 1E3 / ( curTime - tickSection ) * SAMPLE_INTERVAL; +- recentTps[0] = calcTps( recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min) +- recentTps[1] = calcTps( recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min) +- recentTps[2] = calcTps( recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min) ++ final long diff = curTime - tickSection; ++ java.math.BigDecimal currentTps = TPS_BASE.divide(new java.math.BigDecimal(diff), 30, java.math.RoundingMode.HALF_UP); ++ tps1.add(currentTps, diff); ++ tps5.add(currentTps, diff); ++ tps15.add(currentTps, diff); ++ // Backwards compat with bad plugins ++ recentTps[0] = tps1.getAverage(); ++ recentTps[1] = tps5.getAverage(); ++ recentTps[2] = tps15.getAverage(); ++ // Paper end + tickSection = curTime; + } + // Spigot end + +- MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit ++ //MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit // Paper - don't overwrite current tick time ++ lastTick = curTime; + this.nextTickTime += 50L; + SingleTickProfiler gameprofilertick = SingleTickProfiler.createTickProfiler("Server"); + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index f81def94a1a7ab3a24b74a8bbd5f3e8ebae2c0d5..6fa31ca31128b1094eebd5f848c5b506dfeedeeb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2121,6 +2121,17 @@ public final class CraftServer implements Server { + return CraftMagicNumbers.INSTANCE; + } + ++ // Paper - Add getTPS API - Further improve tick loop ++ @Override ++ public double[] getTPS() { ++ return new double[] { ++ net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(), ++ net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(), ++ net.minecraft.server.MinecraftServer.getServer().tps15.getAverage() ++ }; ++ } ++ // Paper end ++ + // Spigot start + private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() + { +diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java +index f5b6dec1cbe7501ce2ee9125920e810bc94670cc..e62890433ffbe0b4e48942fe6c38b599a19e58fd 100644 +--- a/src/main/java/org/spigotmc/TicksPerSecondCommand.java ++++ b/src/main/java/org/spigotmc/TicksPerSecondCommand.java +@@ -24,22 +24,30 @@ public class TicksPerSecondCommand extends Command + return true; + } + +- StringBuilder sb = new StringBuilder( ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " ); +- for ( double tps : MinecraftServer.getServer().recentTps ) +- { +- sb.append( format( tps ) ); +- sb.append( ", " ); ++ // Paper start - Further improve tick handling ++ double[] tps = org.bukkit.Bukkit.getTPS(); ++ String[] tpsAvg = new String[tps.length]; ++ ++ for ( int i = 0; i < tps.length; i++) { ++ tpsAvg[i] = format( tps[i] ); ++ } ++ sender.sendMessage(ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " + org.apache.commons.lang.StringUtils.join(tpsAvg, ", ")); ++ if (args.length > 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) { ++ sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); ++ if (!hasShownMemoryWarning) { ++ sender.sendMessage(ChatColor.RED + "Warning: " + ChatColor.GOLD + " Memory usage on modern garbage collectors is not a stable value and it is perfectly normal to see it reach max. Please do not pay it much attention."); ++ hasShownMemoryWarning = true; ++ } + } +- sender.sendMessage( sb.substring( 0, sb.length() - 2 ) ); +- sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " +- + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); ++ // Paper end + + return true; + } + +- private String format(double tps) ++ private boolean hasShownMemoryWarning; // Paper ++ private static String format(double tps) // Paper - Made static + { + return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString() +- + ( ( tps > 20.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); ++ + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise + } + } diff --git a/Remapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch b/Remapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch new file mode 100644 index 0000000000..b310cdcaa1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 23:12:03 -0600 +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 e6c39c822c6a910f63e9b4899d53b7d75e1b77cf..2920ba3d8eeb62670897ea19b50aaf395ab84c5a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1437,12 +1437,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + @Override + public void setFlying(boolean value) { ++ boolean needsUpdate = getHandle().abilities.flying != value; // Paper - Only refresh abilities if needed + if (!getAllowFlight() && value) { + throw new IllegalArgumentException("Cannot make player fly if getAllowFlight() is false"); + } + + getHandle().abilities.flying = value; +- getHandle().onUpdateAbilities(); ++ if (needsUpdate) getHandle().onUpdateAbilities(); // Paper - Only refresh abilities if needed + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch b/Remapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch new file mode 100644 index 0000000000..cc2e7adc4a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch @@ -0,0 +1,140 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Tue, 1 Mar 2016 23:45:08 -0600 +Subject: [PATCH] Entity Origin API + + +diff --git a/src/main/java/net/minecraft/nbt/ListTag.java b/src/main/java/net/minecraft/nbt/ListTag.java +index 084340dc73acb3d972e0717b48da820c027a5137..7927ebac41eb1f257738238500cfe0c06031fcaf 100644 +--- a/src/main/java/net/minecraft/nbt/ListTag.java ++++ b/src/main/java/net/minecraft/nbt/ListTag.java +@@ -190,6 +190,7 @@ public class ListTag extends CollectionTag { + return new int[0]; + } + ++ public final double getDoubleAt(int i) { return this.getDouble(i); } // Paper - OBFHELPER + public double getDouble(int index) { + if (index >= 0 && index < this.list.size()) { + Tag nbtbase = (Tag) this.list.get(index); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0cc86ca4ea4a2e1b5acc3c0507397eef85dec0c1..d2bb9385fbc21cdef6cef06680fac685d3da3570 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1240,6 +1240,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.navigations.add(((Mob) entity).getNavigation()); + } + entity.valid = true; // CraftBukkit ++ // Paper start - Set origin location when the entity is being added to the world ++ if (entity.origin == null) { ++ entity.origin = entity.getBukkitEntity().getLocation(); ++ } ++ // Paper end + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 392f2f2d67b688d5b37f77c8e4b3036348472d77..fd5b41ceb97dc8aa975f1c0ae05b58d0b09f2cd6 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -246,6 +246,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only + public boolean forceExplosionKnockback; // SPIGOT-949 + public boolean persistentInvisibility = false; ++ public org.bukkit.Location origin; // Paper + // Spigot start + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; +@@ -1624,6 +1625,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.bukkitEntity.storeBukkitValues(tag); + } + // CraftBukkit end ++ // Paper start - Save the entity's origin location ++ if (this.origin != null) { ++ tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); ++ tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); ++ } ++ // Paper end + return tag; + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); +@@ -1746,6 +1753,17 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + // CraftBukkit end + ++ // Paper start - Restore the entity's origin location ++ ListTag originTag = tag.getList("Paper.Origin", 6); ++ if (!originTag.isEmpty()) { ++ org.bukkit.World originWorld = level.getWorld(); ++ if (tag.contains("Paper.OriginWorld")) { ++ originWorld = Bukkit.getWorld(tag.getUUID("Paper.OriginWorld")); ++ } ++ origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); ++ } ++ // Paper end ++ + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded"); +@@ -1807,6 +1825,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + protected abstract void addAdditionalSaveData(CompoundTag tag); + ++ protected final ListTag createList(double... adouble) { return newDoubleList(adouble); } // Paper - OBFHELPER + protected ListTag newDoubleList(double... values) { + ListTag nbttaglist = new ListTag(); + double[] adouble1 = values; +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 5394bc6336cb84025c1c748fb5b3d38e0648a590..1d87717cc9002ea202ee2ca614aaa8a4c7ea3cb2 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -291,6 +291,14 @@ public class FallingBlockEntity extends Entity { + this.blockState = Blocks.SAND.defaultBlockState(); + } + ++ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility ++ if (tag.contains("SourceLoc_x")) { ++ int srcX = tag.getInt("SourceLoc_x"); ++ int srcY = tag.getInt("SourceLoc_y"); ++ int srcZ = tag.getInt("SourceLoc_z"); ++ origin = new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ); ++ } ++ // Paper end + } + + public void setHurtsEntities(boolean hurtEntities) { +diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +index 4c4262b8f0cb44b8cea8cb46194a6e70d4ce56f4..661848084fd986321ef782317934dac19ed4dce3 100644 +--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +@@ -119,6 +119,14 @@ public class PrimedTnt extends Entity { + @Override + protected void readAdditionalSaveData(CompoundTag tag) { + this.setFuse(tag.getShort("Fuse")); ++ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility ++ if (tag.contains("SourceLoc_x")) { ++ int srcX = tag.getInt("SourceLoc_x"); ++ int srcY = tag.getInt("SourceLoc_y"); ++ int srcZ = tag.getInt("SourceLoc_z"); ++ origin = new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ); ++ } ++ // Paper end + } + + @Nullable +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 53c231925ef1b17e48c5863570e3c54124874621..e7a59a8e0424a0839dfa73fc65f44c5b04bd3dec 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1062,4 +1062,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return spigot; + } + // Spigot end ++ ++ // Paper start ++ @Override ++ public Location getOrigin() { ++ Location origin = getHandle().origin; ++ return origin == null ? null : origin.clone(); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch b/Remapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch new file mode 100644 index 0000000000..cf3cf1beaa --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 1 Mar 2016 23:52:34 -0600 +Subject: [PATCH] Prevent tile entity and entity crashes + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 832abf73bdab2488c5814ea6e57888aac1b26154..870843254d1c1fc49bc101a49cdf9d300ae3ca1b 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -737,11 +737,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + gameprofilerfiller.pop(); + } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking block entity"); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block entity being ticked"); +- +- tileentity.fillCrashReportCategory(crashreportsystemdetails); +- throw new ReportedException(crashreport); ++ // Paper start - Prevent tile entity and entity crashes ++ System.err.println("TileEntity threw exception at " + tileentity.level.getWorld().getName() + ":" + tileentity.worldPosition.getX() + "," + tileentity.worldPosition.getY() + "," + tileentity.worldPosition.getZ()); ++ throwable.printStackTrace(); ++ tilesThisCycle--; ++ this.tickableBlockEntities.remove(tileTickPosition--); ++ continue; ++ // Paper end + // Spigot start + } finally { + tileentity.tickTimer.stopTiming(); +@@ -806,11 +808,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + try { + tickConsumer.accept(entity); + } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); +- +- entity.fillCrashReportCategory(crashreportsystemdetails); +- throw new ReportedException(crashreport); ++ // Paper start - Prevent tile entity and entity crashes ++ System.err.println("Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ()); ++ throwable.printStackTrace(); ++ entity.removed = true; ++ return; ++ // Paper end + } + } + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index d445a1b7b7605eed66923789c5d8e2199c31c5ac..13115d1b28dfa2d87b45a50bd0feaa7f57769122 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -208,7 +208,12 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + return Registry.BLOCK_ENTITY_TYPE.getKey(this.getType()) + " // " + this.getClass().getCanonicalName(); + }); + if (this.level != null) { +- CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.worldPosition, this.getBlockState()); ++ // Paper start - Prevent TileEntity and Entity crashes ++ BlockState block = this.getBlockState(); ++ if (block != null) { ++ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.worldPosition, block); ++ } ++ // Paper end + CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.worldPosition, this.level.getBlockState(this.worldPosition)); + } + } diff --git a/Remapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch b/Remapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch new file mode 100644 index 0000000000..805929cc33 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 23:58:50 -0600 +Subject: [PATCH] Configurable top of nether void damage + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index d16ae924bcbe31c964f7fb448757c748e5c4418c..4bba6977a0287837b8927718c040ac61463f0469 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -134,4 +134,19 @@ public class PaperWorldConfig { + if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); + if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); + } ++ ++ public int netherVoidTopDamageHeight; ++ public boolean doNetherTopVoidDamage() { return netherVoidTopDamageHeight > 0; } ++ private void netherVoidTopDamageHeight() { ++ netherVoidTopDamageHeight = getInt("nether-ceiling-void-damage-height", 0); ++ log("Top of the nether void damage height: " + netherVoidTopDamageHeight); ++ ++ if (PaperConfig.version < 18) { ++ boolean legacy = getBoolean("nether-ceiling-void-damage", false); ++ if (legacy) { ++ netherVoidTopDamageHeight = 128; ++ set("nether-ceiling-void-damage-height", netherVoidTopDamageHeight); ++ } ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index fd5b41ceb97dc8aa975f1c0ae05b58d0b09f2cd6..f3f48c268639937874dd39eea9bd8e119eebdce7 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -499,9 +499,16 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.fallDistance *= 0.5F; + } + +- if (this.getY() < -64.0D) { +- this.outOfWorld(); ++ // Paper start - Configurable nether ceiling damage ++ ++ // Extracted to own function ++ /* ++ if (this.locY() < -64.0D) { ++ this.an(); + } ++ */ ++ this.performVoidDamage(); ++ // Paper end + + if (!this.level.isClientSide) { + this.setSharedFlag(0, this.remainingFireTicks > 0); +@@ -594,6 +601,17 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.setRemainingFireTicks(0); + } + ++ // Paper start ++ protected void performVoidDamage() { ++ if (this.getY() < -64.0D || (this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER ++ && level.paperConfig.doNetherTopVoidDamage() ++ && this.getY() >= level.paperConfig.netherVoidTopDamageHeight)) { ++ this.doVoidDamage(); ++ } ++ } ++ // Paper end ++ ++ protected final void doVoidDamage() { this.outOfWorld(); } // Paper - OBFHELPER + protected void outOfWorld() { + this.remove(); + } +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 9503376895d90e8db0d4f7b164e2d813dd1a4a3a..7ba74b0a9319e29077b5afe3019a463ed3004813 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -329,9 +329,15 @@ public abstract class AbstractMinecart extends Entity { + this.setDamage(this.getDamage() - 1.0F); + } + +- if (this.getY() < -64.0D) { +- this.outOfWorld(); ++ // Paper start - Configurable nether ceiling damage ++ // Extracted to own function ++ /* ++ if (this.locY() < -64.0D) { ++ this.an(); + } ++ */ ++ this.performVoidDamage(); ++ // Paper end + + // this.doPortalTick(); // CraftBukkit - handled in postTick + if (this.level.isClientSide) { diff --git a/Remapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch b/Remapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch new file mode 100644 index 0000000000..56a96d8cfe --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Mar 2016 00:03:55 -0600 +Subject: [PATCH] Check online mode before converting and renaming player data + + +diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +index 067c5acd4aad346ac9ccf6d1b5aa6691b0ccd348..60fe01e824e4657d2601797d7858d5de339ab255 100644 +--- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +@@ -56,7 +56,7 @@ public class PlayerDataStorage { + File file = new File(this.playerDir, entityhuman.getStringUUID() + ".dat"); + // Spigot Start + boolean usingWrongFile = false; +- if ( !file.exists() ) ++ if ( org.bukkit.Bukkit.getOnlineMode() && !file.exists() ) // Paper - Check online mode first + { + file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + entityhuman.getScoreboardName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); + if ( file.exists() ) diff --git a/Remapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch b/Remapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch new file mode 100644 index 0000000000..29eba4b28a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Mar 2016 00:32:25 -0600 +Subject: [PATCH] Always tick falling blocks + + +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 9bb35ec64e1538aabec9ff7831706c4717239449..0a9bd85e0308e962df3b24a74bd5aac919744d6d 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -91,6 +91,7 @@ public class ActivationRange + || entity instanceof AbstractHurtingProjectile + || entity instanceof LightningBolt + || entity instanceof PrimedTnt ++ || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks + || entity instanceof EndCrystal + || entity instanceof FireworkRocketEntity + || entity instanceof ThrownTrident ) diff --git a/Remapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch b/Remapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch new file mode 100644 index 0000000000..201a2e7284 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DoctorDark +Date: Wed, 16 Mar 2016 02:21:39 -0500 +Subject: [PATCH] Configurable end credits + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4bba6977a0287837b8927718c040ac61463f0469..e6e18f309dc09ea9416ea37dcc697ddc2b571a96 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -149,4 +149,10 @@ public class PaperWorldConfig { + } + } + } ++ ++ public boolean disableEndCredits; ++ private void disableEndCredits() { ++ disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); ++ log("End credits disabled: " + disableEndCredits); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index ca647b3afbe8da5847dc8fa890ae9ca5c18e03d9..f3797bd761c2c6782cce3fca25bc9ef37e5c4978 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -188,7 +188,7 @@ public class ServerPlayer extends Player implements ContainerListener { + private long lastActionTime = Util.getMillis(); + private Entity camera; + public boolean isChangingDimension; +- private boolean seenCredits; ++ private boolean seenCredits; private void setHasSeenCredits(boolean has) { this.seenCredits = has; } // Paper - OBFHELPER + private final ServerRecipeBook recipeBook = new ServerRecipeBook(); + private Vec3 levitationStartPos; + private int levitationStartTime; +@@ -893,6 +893,7 @@ public class ServerPlayer extends Player implements ContainerListener { + this.unRide(); + this.getLevel().removePlayerImmediately(this); + if (!this.wonGame) { ++ if (level.paperConfig.disableEndCredits) this.setHasSeenCredits(true); // Paper - Toggle to always disable end credits + this.wonGame = true; + this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.WIN_GAME, this.seenCredits ? 0.0F : 1.0F)); + this.seenCredits = true; diff --git a/Remapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch b/Remapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch new file mode 100644 index 0000000000..a9fb2be3bd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Iceee +Date: Wed, 2 Mar 2016 01:39:52 -0600 +Subject: [PATCH] Fix lag from explosions processing dead entities + + +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 54c3bfead8497f64c183f5612676803d91fc557b..8d6cd2a5b16d99cb8e754ce04b2d12fee7ffb4d0 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -180,7 +180,7 @@ public class Explosion { + int i1 = Mth.floor(this.y + (double) f2 + 1.0D); + int j1 = Mth.floor(this.z - (double) f2 - 1.0D); + int k1 = Mth.floor(this.z + (double) f2 + 1.0D); +- List list = this.level.getEntities(this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1)); ++ List list = this.level.getEntities(this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1), (com.google.common.base.Predicate) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities + Vec3 vec3d = new Vec3(this.x, this.y, this.z); + + for (int l1 = 0; l1 < list.size(); ++l1) { diff --git a/Remapped-Spigot-Server-Patches/0033-Optimize-explosions.patch b/Remapped-Spigot-Server-Patches/0033-Optimize-explosions.patch new file mode 100644 index 0000000000..ec1e34fc38 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0033-Optimize-explosions.patch @@ -0,0 +1,148 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 2 Mar 2016 11:59:48 -0600 +Subject: [PATCH] Optimize explosions + +The process of determining an entity's exposure from explosions can be +expensive when there are hundreds or more entities in range. + +This patch adds a per-tick cache that is used for storing and retrieving +an entity's exposure during an explosion. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e6e18f309dc09ea9416ea37dcc697ddc2b571a96..4881b03d470646843bad1bc343eb6a6ab9072d8e 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -155,4 +155,10 @@ public class PaperWorldConfig { + disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); + log("End credits disabled: " + disableEndCredits); + } ++ ++ public boolean optimizeExplosions; ++ private void optimizeExplosions() { ++ optimizeExplosions = getBoolean("optimize-explosions", false); ++ log("Optimize explosions: " + optimizeExplosions); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 526d6c0fa45bfba92a3f964f72e4965fd5c841c1..901d5497667706c049718dc4fca37a1bc489c465 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1324,6 +1324,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop>> 32)); ++ temp = Double.doubleToLongBits(posY); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(posZ); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(minX); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(minY); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(minZ); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(maxX); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(maxY); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(maxZ); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ return result; ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 870843254d1c1fc49bc101a49cdf9d300ae3ca1b..f71b56fa079e2c7b2123061a8e1a7cb41935bab6 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -136,6 +136,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + private org.spigotmc.TickLimiter entityLimiter; + private org.spigotmc.TickLimiter tileLimiter; + private int tileTickPosition; ++ public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions + + public CraftWorld getWorld() { + return this.world; diff --git a/Remapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch b/Remapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch new file mode 100644 index 0000000000..d9f4ff9678 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 14:48:03 -0600 +Subject: [PATCH] Disable explosion knockback + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4881b03d470646843bad1bc343eb6a6ab9072d8e..2222c1bb5f8625eee4d88946e4bfdfa2fe598977 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -161,4 +161,9 @@ public class PaperWorldConfig { + optimizeExplosions = getBoolean("optimize-explosions", false); + log("Optimize explosions: " + optimizeExplosions); + } ++ ++ public boolean disableExplosionKnockback; ++ private void disableExplosionKnockback(){ ++ disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index e5f8cee6726ea9a90c540bb10fd8594a35bb5e40..afd114e1ce00db72534d470fed12101bb237f266 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1280,6 +1280,7 @@ public abstract class LivingEntity extends Entity { + } + } + ++ boolean knockbackCancelled = level.paperConfig.disableExplosionKnockback && source.isExplosion() && this instanceof net.minecraft.world.entity.player.Player; // Paper - Disable explosion knockback + if (flag1) { + if (flag) { + this.level.broadcastEntityEvent(this, (byte) 29); +@@ -1298,6 +1299,7 @@ public abstract class LivingEntity extends Entity { + b0 = 2; + } + ++ if (!knockbackCancelled) // Paper - Disable explosion knockback + this.level.broadcastEntityEvent(this, b0); + } + +@@ -1321,6 +1323,7 @@ public abstract class LivingEntity extends Entity { + } + } + ++ if (knockbackCancelled) this.level.broadcastEntityEvent(this, (byte) 2); // Paper - Disable explosion knockback + if (this.isDeadOrDying()) { + if (!this.checkTotemDeathProtection(source)) { + SoundEvent soundeffect = this.getDeathSound(); +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index db46caaa5ad5f129d313c65c5006cb24853768be..45a75f7be308678336e192828becf6cf5c9047bc 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -215,14 +215,14 @@ public class Explosion { + double d14 = d13; + + if (entity instanceof LivingEntity) { +- d14 = ProtectionEnchantment.getExplosionKnockbackAfterDampener((LivingEntity) entity, d13); ++ d14 = entity instanceof Player && level.paperConfig.disableExplosionKnockback ? 0 : ProtectionEnchantment.getExplosionKnockbackAfterDampener((LivingEntity) entity, d13); // Paper - Disable explosion knockback + } + + entity.setDeltaMovement(entity.getDeltaMovement().add(d8 * d14, d9 * d14, d10 * d14)); + if (entity instanceof Player) { + Player entityhuman = (Player) entity; + +- if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.flying)) { ++ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.flying) && !level.paperConfig.disableExplosionKnockback) { // Paper - Disable explosion knockback + this.hitPlayers.put(entityhuman, new Vec3(d8 * d13, d9 * d13, d10 * d13)); + } + } diff --git a/Remapped-Spigot-Server-Patches/0035-Disable-thunder.patch b/Remapped-Spigot-Server-Patches/0035-Disable-thunder.patch new file mode 100644 index 0000000000..d5971380bb --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0035-Disable-thunder.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 14:52:43 -0600 +Subject: [PATCH] Disable thunder + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2222c1bb5f8625eee4d88946e4bfdfa2fe598977..083e421f8496b5336af473b108498ed28b984774 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -166,4 +166,9 @@ public class PaperWorldConfig { + private void disableExplosionKnockback(){ + disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); + } ++ ++ public boolean disableThunder; ++ private void disableThunder() { ++ disableThunder = getBoolean("disable-thunder", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index d2bb9385fbc21cdef6cef06680fac685d3da3570..3fc8fb197400c63bc85f57ff484803659619f775 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -580,7 +580,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + gameprofilerfiller.push("thunder"); + BlockPos blockposition; + +- if (flag && this.isThundering() && this.random.nextInt(100000) == 0) { ++ if (!this.paperConfig.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder + blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); + if (this.isRainingAt(blockposition)) { + DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); diff --git a/Remapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch b/Remapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch new file mode 100644 index 0000000000..9d2d87a6b0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 14:57:24 -0600 +Subject: [PATCH] Disable ice and snow + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 083e421f8496b5336af473b108498ed28b984774..2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -171,4 +171,9 @@ public class PaperWorldConfig { + private void disableThunder() { + disableThunder = getBoolean("disable-thunder", false); + } ++ ++ public boolean disableIceAndSnow; ++ private void disableIceAndSnow(){ ++ disableIceAndSnow = getBoolean("disable-ice-and-snow", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 3fc8fb197400c63bc85f57ff484803659619f775..6c6098731752d61b5241710b075d4ffe3826daac 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -604,7 +604,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + gameprofilerfiller.popPush("iceandsnow"); +- if (this.random.nextInt(16) == 0) { ++ if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow + blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.getBlockRandomPos(j, 0, k, 15)); + BlockPos blockposition1 = blockposition.below(); + Biome biomebase = this.getBiome(blockposition); diff --git a/Remapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch b/Remapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch new file mode 100644 index 0000000000..454050d2c3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 15:03:53 -0600 +Subject: [PATCH] Configurable mob spawner tick rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2..4de86b09c6bc3c1974ce61b550ccb73d37f6f170 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -176,4 +176,9 @@ public class PaperWorldConfig { + private void disableIceAndSnow(){ + disableIceAndSnow = getBoolean("disable-ice-and-snow", false); + } ++ ++ public int mobSpawnerTickRate; ++ private void mobSpawnerTickRate() { ++ mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 10058d3c3565382faa893b79119c5caf845bf29a..ed631d5bfba5d2543e8eed017a7c484ad3ddb453 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -41,6 +41,7 @@ public abstract class BaseSpawner { + public int maxNearbyEntities = 6; + public int requiredPlayerRange = 16; + public int spawnRange = 4; ++ private int tickDelay = 0; // Paper + + public BaseSpawner() {} + +@@ -70,6 +71,10 @@ public abstract class BaseSpawner { + } + + public void tick() { ++ // Paper start - Configurable mob spawner tick rate ++ if (spawnDelay > 0 && --tickDelay > 0) return; ++ tickDelay = this.getLevel().paperConfig.mobSpawnerTickRate; ++ // Paper end + if (!this.isNearPlayer()) { + this.oSpin = this.spin; + } else { +@@ -84,18 +89,18 @@ public abstract class BaseSpawner { + world.addParticle(ParticleTypes.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + world.addParticle(ParticleTypes.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D); + if (this.spawnDelay > 0) { +- --this.spawnDelay; ++ this.spawnDelay -= tickDelay; // Paper + } + + this.oSpin = this.spin; + this.spin = (this.spin + (double) (1000.0F / ((float) this.spawnDelay + 200.0F))) % 360.0D; + } else { +- if (this.spawnDelay == -1) { ++ if (this.spawnDelay < -tickDelay) { // Paper + this.delay(); + } + + if (this.spawnDelay > 0) { +- --this.spawnDelay; ++ this.spawnDelay -= tickDelay; // Paper + return; + } + diff --git a/Remapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch b/Remapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch new file mode 100644 index 0000000000..c77faa1999 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Wed, 2 Mar 2016 23:13:07 -0600 +Subject: [PATCH] Send absolute position the first time an entity is seen + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 59a5f82c9f57d760ba4959a040ce8cbf0f49e4aa..d1bc927c8b429f43de2cdad98f8b329ff4c8b4db 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1301,10 +1301,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private final Entity entity; + private final int range; + private SectionPos lastSectionPos; +- public final Set seenBy = Sets.newHashSet(); ++ // Paper start ++ // Replace trackedPlayers Set with a Map. The value is true until the player receives ++ // their first update (which is forced to have absolute coordinates), false afterward. ++ public java.util.Map trackedPlayerMap = new java.util.HashMap<>(); ++ public Set seenBy = trackedPlayerMap.keySet(); + + public TrackedEntity(Entity entity, int i, int j, boolean flag) { +- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, seenBy); // CraftBukkit ++ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, trackedPlayerMap); // CraftBukkit // Paper + this.entity = entity; + this.range = i; + this.lastSectionPos = SectionPos.of(entity); +@@ -1386,7 +1390,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + player.entitiesToRemove.remove(Integer.valueOf(this.entity.getId())); + // CraftBukkit end + +- if (flag1 && this.seenBy.add(player)) { ++ if (flag1 && this.trackedPlayerMap.putIfAbsent(player, true) == null) { // Paper + this.serverEntity.addPairing(player); + } + } else if (this.seenBy.remove(player)) { +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index 3d386627b6d3d33da76372e4a14d0c5000eb8ffc..fa6893055fa5617742bfb4b7eff60c8139395cb6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -4,6 +4,7 @@ import com.google.common.collect.Lists; + import com.mojang.datafixers.util.Pair; + import java.util.Collection; + import java.util.Collections; ++import java.util.HashSet; + import java.util.Iterator; + import java.util.List; + import java.util.Set; +@@ -51,7 +52,7 @@ public class ServerEntity { + private final Entity entity; + private final int updateInterval; + private final boolean trackDelta; +- private final Consumer> broadcast; ++ private final Consumer> broadcast; private Consumer> getPacketConsumer() { return broadcast; } // Paper - OBFHELPER + private long xp; + private long yp; + private long zp; +@@ -66,8 +67,23 @@ public class ServerEntity { + private boolean wasOnGround; + // CraftBukkit start + private final Set trackedPlayers; ++ // Paper start ++ private java.util.Map trackedPlayerMap = null; ++ ++ /** ++ * Requested in https://github.com/PaperMC/Paper/issues/1537 to allow intercepting packets ++ */ ++ public void sendPlayerPacket(ServerPlayer player, Packet packet) { ++ player.connection.send(packet); ++ } ++ ++ public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, java.util.Map trackedPlayers) { ++ this(worldserver, entity, i, flag, consumer, trackedPlayers.keySet()); ++ trackedPlayerMap = trackedPlayers; ++ } + + public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { ++ // Paper end + this.trackedPlayers = trackedPlayers; + // CraftBukkit end + this.ap = Vec3.ZERO; +@@ -188,7 +204,25 @@ public class ServerEntity { + } + + if (packet1 != null) { +- this.broadcast.accept(packet1); ++ // paper start ++ if (trackedPlayerMap == null || packet1 instanceof ClientboundTeleportEntityPacket) { ++ this.broadcast.accept((packet1)); ++ } else { ++ ClientboundTeleportEntityPacket teleportPacket = null; ++ ++ for (java.util.Map.Entry viewer : trackedPlayerMap.entrySet()) { ++ if (viewer.getValue()) { ++ viewer.setValue(false); ++ if (teleportPacket == null) { ++ teleportPacket = new ClientboundTeleportEntityPacket(this.entity); ++ } ++ sendPlayerPacket(viewer.getKey(), teleportPacket); ++ } else { ++ sendPlayerPacket(viewer.getKey(), packet1); ++ } ++ } ++ } ++ // Paper end + } + + this.sendDirtyEntityData(); diff --git a/Remapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch b/Remapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch new file mode 100644 index 0000000000..d61c3cadc2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 2 Mar 2016 23:30:53 -0600 +Subject: [PATCH] Add BeaconEffectEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +index c91f7bcfab2da6a23114a3cff63ca31dab443393..5f75c6d653a31f65fcf9c0e280d796e15d059c00 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -25,7 +25,6 @@ import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.inventory.BeaconMenu; + import net.minecraft.world.inventory.ContainerData; +@@ -41,6 +40,11 @@ import net.minecraft.world.phys.AABB; + import org.bukkit.craftbukkit.potion.CraftPotionUtil; + import org.bukkit.potion.PotionEffect; + // CraftBukkit end ++// Paper start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.Player; ++import com.destroystokyo.paper.event.block.BeaconEffectEvent; ++// Paper end + + public class BeaconBlockEntity extends BlockEntity implements MenuProvider, TickableBlockEntity { + +@@ -260,21 +264,37 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + double d0 = (double) (this.levels * 10 + 10); + + AABB axisalignedbb = (new AABB(this.worldPosition)).inflate(d0).expandTowards(0.0D, (double) this.level.getMaxBuildHeight(), 0.0D); +- List list = this.level.getEntitiesOfClass(Player.class, axisalignedbb); ++ List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.player.Player.class, axisalignedbb); + + return list; + } + } + + private void applyEffect(List list, MobEffect effects, int i, int b0) { ++ // Paper - BeaconEffectEvent ++ applyEffect(list, effects, i, b0, true); ++ } ++ ++ private void applyEffect(List list, MobEffect effects, int i, int b0, boolean isPrimary) { ++ // Paper - BeaconEffectEvent + { + Iterator iterator = list.iterator(); + +- Player entityhuman; ++ net.minecraft.world.entity.player.Player entityhuman; ++ ++ // Paper start - BeaconEffectEvent ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ PotionEffect effect = CraftPotionUtil.toBukkit(new MobEffectInstance(effects, i, b0, true, true)); ++ // Paper end + + while (iterator.hasNext()) { +- entityhuman = (Player) iterator.next(); +- entityhuman.addEffect(new MobEffectInstance(effects, i, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); ++ entityhuman = (net.minecraft.world.entity.player.Player) iterator.next(); ++ ++ // Paper start - BeaconEffectEvent ++ BeaconEffectEvent event = new BeaconEffectEvent(block, effect, (Player) entityhuman.getBukkitEntity(), isPrimary); ++ if (CraftEventFactory.callEvent(event).isCancelled()) continue; ++ entityhuman.addEffect(new MobEffectInstance(CraftPotionUtil.fromBukkit(event.getEffect())), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); ++ // Paper end + } + } + } +@@ -297,10 +317,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + int i = getLevelCb(); + List list = getHumansInRange(); + +- applyEffect(list, this.primaryPower, i, b0); ++ applyEffect(list, this.primaryPower, i, b0, true); // Paper - BeaconEffectEvent + + if (hasSecondaryEffect()) { +- applyEffect(list, this.secondaryPower, i, 0); ++ applyEffect(list, this.secondaryPower, i, 0, false); // Paper - BeaconEffectEvent + } + } + +@@ -308,7 +328,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + // CraftBukkit end + + public void playSound(SoundEvent soundeffect) { +- this.level.playSound((Player) null, this.worldPosition, soundeffect, SoundSource.BLOCKS, 1.0F, 1.0F); ++ this.level.playSound((net.minecraft.world.entity.player.Player) null, this.worldPosition, soundeffect, SoundSource.BLOCKS, 1.0F, 1.0F); + } + + public int getLevels() { +@@ -368,7 +388,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + + @Nullable + @Override +- public AbstractContainerMenu createMenu(int syncId, Inventory inv, Player player) { ++ public AbstractContainerMenu createMenu(int syncId, Inventory inv, net.minecraft.world.entity.player.Player player) { + return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName()) ? new BeaconMenu(syncId, inv, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; + } + diff --git a/Remapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch b/Remapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch new file mode 100644 index 0000000000..3344a83459 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 23:34:44 -0600 +Subject: [PATCH] Configurable container update tick rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4de86b09c6bc3c1974ce61b550ccb73d37f6f170..5a4c3a8c511f22c8c3240c9c7cd83a65119c1054 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -181,4 +181,9 @@ public class PaperWorldConfig { + private void mobSpawnerTickRate() { + mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); + } ++ ++ public int containerUpdateTickRate; ++ private void containerUpdateTickRate() { ++ containerUpdateTickRate = getInt("container-update-tick-rate", 1); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index f3797bd761c2c6782cce3fca25bc9ef37e5c4978..ffad931c72e52855a3f139354f5e85c460e2a80b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -207,6 +207,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public boolean ignoreSlotUpdateHack; + public int latency; + public boolean wonGame; ++ private int containerUpdateDelay; // Paper + + // CraftBukkit start + public String displayName; +@@ -531,7 +532,12 @@ public class ServerPlayer extends Player implements ContainerListener { + --this.invulnerableTime; + } + +- this.containerMenu.broadcastChanges(); ++ // Paper start - Configurable container update tick rate ++ if (--containerUpdateDelay <= 0) { ++ this.containerMenu.broadcastChanges(); ++ containerUpdateDelay = level.paperConfig.containerUpdateTickRate; ++ } ++ // Paper end + if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { + this.closeContainer(); + this.containerMenu = this.inventoryMenu; diff --git a/Remapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch b/Remapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch new file mode 100644 index 0000000000..1c9a8dab7e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Wed, 2 Mar 2016 23:42:37 -0600 +Subject: [PATCH] Use UserCache for player heads + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +index 11baf6fd5f7e408a570d5a48ae6b2fc05cd7e243..313ddd6b64e395a8caab77b3da005e52006ab2d7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +@@ -166,7 +166,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + if (name == null) { + setProfile(null); + } else { +- setProfile(new GameProfile(null, name)); ++ // Paper start - Use Online Players Skull ++ GameProfile newProfile = null; ++ net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); ++ if (player != null) newProfile = player.getProfile(); ++ if (newProfile == null) newProfile = new GameProfile(null, name); ++ setProfile(newProfile); ++ // Paper end + } + + return true; diff --git a/Remapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch b/Remapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch new file mode 100644 index 0000000000..703b1b0774 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Mar 2016 23:45:17 -0600 +Subject: [PATCH] Disable spigot tick limiters + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index f71b56fa079e2c7b2123061a8e1a7cb41935bab6..e25666328dbf433b8358f2637d93b4128034bbaa 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -707,9 +707,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Spigot start + // Iterator iterator = this.tileEntityListTick.iterator(); + int tilesThisCycle = 0; +- for (tileLimiter.initTick(); +- tilesThisCycle < tickableBlockEntities.size() && (tilesThisCycle % 10 != 0 || tileLimiter.shouldContinue()); +- tileTickPosition++, tilesThisCycle++) { ++ for (tileTickPosition = 0; tileTickPosition < tickableBlockEntities.size(); tileTickPosition++) { // Paper - Disable tick limiters + tileTickPosition = (tileTickPosition < tickableBlockEntities.size()) ? tileTickPosition : 0; + BlockEntity tileentity = (BlockEntity) this.tickableBlockEntities.get(tileTickPosition); + // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch b/Remapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch new file mode 100644 index 0000000000..7e6b238460 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Steve Anton +Date: Thu, 3 Mar 2016 00:09:38 -0600 +Subject: [PATCH] Add PlayerInitialSpawnEvent + +For modifying a player's initial spawn location as they join the server + +This is a duplicate API from spigot, so use our duplicate subclass and +improve setPosition to use raw + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 8cdecaf2f63c78196e0c5046fe2431b40e072c8a..a63babe123fad398b07685ec57cd88756435457c 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -209,7 +209,7 @@ public abstract class PlayerList { + + // Spigot start - spawn location event + Player bukkitPlayer = player.getBukkitEntity(); +- org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(bukkitPlayer, bukkitPlayer.getLocation()); ++ org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(bukkitPlayer, bukkitPlayer.getLocation()); // Paper use our duplicate event + cserver.getPluginManager().callEvent(ev); + + Location loc = ev.getSpawnLocation(); +@@ -217,7 +217,10 @@ public abstract class PlayerList { + + player.setLevel(worldserver1); + player.gameMode.setLevel((ServerLevel) player.level); +- player.absMoveTo(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); ++ // Paper start - set raw so we aren't fully joined to the world (not added to chunk or world) ++ player.setPosRaw(loc.getX(), loc.getY(), loc.getZ()); ++ player.setRot(loc.getYaw(), loc.getPitch()); ++ // Paper end + // Spigot end + + // CraftBukkit - Moved message to after join +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index f3f48c268639937874dd39eea9bd8e119eebdce7..72eb40f748c33572c2828f48ebd1ca7d5d5712c8 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -397,7 +397,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return d1 * d1 + d2 * d2 + d3 * d3 < radius * radius; + } + +- protected void setRot(float yaw, float pitch) { ++ public void setRot(float yaw, float pitch) { // Paper - protected -> public + // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 + if (Float.isNaN(yaw)) { + yaw = 0; diff --git a/Remapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch b/Remapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch new file mode 100644 index 0000000000..88836aa6a1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 01:13:45 -0600 +Subject: [PATCH] Configurable Disabling Cat Chest Detection + +Offers a gameplay feature to stop cats from blocking chests + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5a4c3a8c511f22c8c3240c9c7cd83a65119c1054..70e074cdf2087e638af8e0f3878d0ef8eb7305cc 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -186,4 +186,9 @@ public class PaperWorldConfig { + private void containerUpdateTickRate() { + containerUpdateTickRate = getInt("container-update-tick-rate", 1); + } ++ ++ public boolean disableChestCatDetection; ++ private void disableChestCatDetection() { ++ disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +index 1bda9a158eb4372b9ab7cf3097732e64810aefc6..6b95cd2e2af66eef324dfcc8f7642da2f9e39d4e 100644 +--- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +@@ -312,6 +312,11 @@ public class ChestBlock extends AbstractChestBlock implements + } + + private static boolean isCatSittingOnChest(LevelAccessor world, BlockPos pos) { ++ // Paper start - Option to disable chest cat detection ++ if (((Level) world).paperConfig.disableChestCatDetection) { ++ return false; ++ } ++ // Paper end + List list = world.getEntitiesOfClass(Cat.class, new AABB((double) pos.getX(), (double) (pos.getY() + 1), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 2), (double) (pos.getZ() + 1))); + + if (!list.isEmpty()) { diff --git a/Remapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch b/Remapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch new file mode 100644 index 0000000000..b0605d0e7a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 01:17:12 -0600 +Subject: [PATCH] Ensure commands are not ran async + +Plugins calling Player.chat("/foo") or Server.dispatchCommand() could +trigger the server to execute a command while on another thread. + +These commands would then process EXPECTING to be on the main thread, leaving to +very hard to trace concurrency issues. + +This change will synchronize the command execution back to the main thread, causing a +big slowdown in execution but throwing an exception at same time to raise awareness +that it is happening so that plugin authors can fix their code to stop executing commands async. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 016e91a6ca1c8457e3e367ac0597b73e81919b68..00689dc07625a02781052c5df2e466e8abe85708 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1852,6 +1852,29 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + + if (!async && s.startsWith("/")) { ++ // Paper Start ++ if (!org.spigotmc.AsyncCatcher.shuttingDown && !org.bukkit.Bukkit.isPrimaryThread()) { ++ final String fCommandLine = s; ++ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Command Dispatched Async: " + fCommandLine); ++ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); ++ Waitable wait = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ chat(fCommandLine, false); ++ return null; ++ } ++ }; ++ server.processQueue.add(wait); ++ try { ++ wait.get(); ++ return; ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! ++ } catch (Exception e) { ++ throw new RuntimeException("Exception processing chat command", e.getCause()); ++ } ++ } ++ // Paper End + this.handleCommand(s); + } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { + // Do nothing, this is coming from a plugin +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 6fa31ca31128b1094eebd5f848c5b506dfeedeeb..783da25e189c0264ebf31e244677a6b653ff7b26 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -759,6 +759,29 @@ public final class CraftServer implements Server { + Validate.notNull(commandLine, "CommandLine cannot be null"); + org.spigotmc.AsyncCatcher.catchOp("command dispatch"); // Spigot + ++ // Paper Start ++ if (!org.spigotmc.AsyncCatcher.shuttingDown && !Bukkit.isPrimaryThread()) { ++ final CommandSender fSender = sender; ++ final String fCommandLine = commandLine; ++ Bukkit.getLogger().log(Level.SEVERE, "Command Dispatched Async: " + commandLine); ++ Bukkit.getLogger().log(Level.SEVERE, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); ++ org.bukkit.craftbukkit.util.Waitable wait = new org.bukkit.craftbukkit.util.Waitable() { ++ @Override ++ protected Boolean evaluate() { ++ return dispatchCommand(fSender, fCommandLine); ++ } ++ }; ++ net.minecraft.server.MinecraftServer.getServer().processQueue.add(wait); ++ try { ++ return wait.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! ++ } catch (Exception e) { ++ throw new RuntimeException("Exception processing dispatch command", e.getCause()); ++ } ++ } ++ // Paper End ++ + if (commandMap.dispatch(sender, commandLine)) { + return true; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +index ddef523ea8762c927f37f7d16d581e43367e8c6b..70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +@@ -13,6 +13,7 @@ public class ServerShutdownThread extends Thread { + public void run() { + try { + org.spigotmc.AsyncCatcher.enabled = false; // Spigot ++ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper + server.close(); + } finally { + try { +diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java +index aeed7697254af17ffefe8e578353ad216e15f9f3..9f7d2ef932ab41cef5d3d0736d20a7c7e4a2c888 100644 +--- a/src/main/java/org/spigotmc/AsyncCatcher.java ++++ b/src/main/java/org/spigotmc/AsyncCatcher.java +@@ -6,6 +6,7 @@ public class AsyncCatcher + { + + public static boolean enabled = true; ++ public static boolean shuttingDown = false; // Paper + + public static void catchOp(String reason) + { +diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java +index a4223094802a7e996cc57c617df92d23bc48f5b5..04ae5fec376af006ec828d1ae568338af5cfe6ce 100644 +--- a/src/main/java/org/spigotmc/RestartCommand.java ++++ b/src/main/java/org/spigotmc/RestartCommand.java +@@ -43,6 +43,7 @@ public class RestartCommand extends Command + private static void restart(final String restartScript) + { + AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us ++ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper + try + { + String[] split = restartScript.split( " " ); diff --git a/Remapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch b/Remapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch new file mode 100644 index 0000000000..cee1933ce4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: vemacs +Date: Thu, 3 Mar 2016 01:19:22 -0600 +Subject: [PATCH] All chunks are slime spawn chunks toggle + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 70e074cdf2087e638af8e0f3878d0ef8eb7305cc..416a6760883cb40367535c7c5acd779742bb8af5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -191,4 +191,9 @@ public class PaperWorldConfig { + private void disableChestCatDetection() { + disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); + } ++ ++ public boolean allChunksAreSlimeChunks; ++ private void allChunksAreSlimeChunks() { ++ allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java +index 8ff8c19f0b258623b9f0a3cfd0ad5595a92f5899..fc8f26e988f1e4826dcfdcf071293bb356163e62 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java +@@ -323,7 +323,7 @@ public class Slime extends Mob implements Enemy { + } + + ChunkPos chunkcoordintpair = new ChunkPos(pos); +- boolean flag = WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getLevel().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot ++ boolean flag = world.getLevel().paperConfig.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getLevel().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper + + if (random.nextInt(10) == 0 && flag && pos.getY() < 40) { + return checkMobSpawnRules(type, world, spawnReason, pos, random); diff --git a/Remapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch b/Remapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch new file mode 100644 index 0000000000..c633af2298 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Thu, 3 Mar 2016 02:15:57 -0600 +Subject: [PATCH] Expose server CommandMap + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 783da25e189c0264ebf31e244677a6b653ff7b26..95d32f37db663a37f8fde927bdf9d3d4802ba1b4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1760,6 +1760,7 @@ public final class CraftServer implements Server { + return helpMap; + } + ++ @Override // Paper - add override + public SimpleCommandMap getCommandMap() { + return commandMap; + } diff --git a/Remapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch b/Remapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch new file mode 100644 index 0000000000..b47fa12664 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Thu, 3 Mar 2016 02:18:39 -0600 +Subject: [PATCH] Be a bit more informative in maxHealth exception + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index d8bfb0953f0b23c64f4e27fc84a6c5f3eb0cc8b8..3afdcb3013263a7e06876821d7d889fa48404041 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -99,7 +99,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setHealth(double health) { + health = (float) health; + if ((health < 0) || (health > getMaxHealth())) { +- throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + "(" + health + ")"); ++ // Paper - Be more informative ++ throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + ", but was " + health ++ + ". (attribute base value: " + this.getHandle().getAttribute(Attributes.MAX_HEALTH).getBaseValue() ++ + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); + } + + getHandle().setHealth((float) health); diff --git a/Remapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch b/Remapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch new file mode 100644 index 0000000000..c26e87ac6e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch @@ -0,0 +1,173 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Thu, 3 Mar 2016 02:32:10 -0600 +Subject: [PATCH] Player Tab List and Title APIs + + +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index 59788eaef0dae5ee01ceba1bf45e85cb07f88e53..b4542ce6a8c37ab31e6ecaeb4cbad4742cca0f9b 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -170,6 +170,11 @@ public class FriendlyByteBuf extends ByteBuf { + public FriendlyByteBuf writeComponent(final net.kyori.adventure.text.Component component) { + return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); + } ++ ++ @Deprecated ++ public FriendlyByteBuf writeComponent(final net.md_5.bungee.api.chat.BaseComponent[] component) { ++ return this.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(component), 262144); ++ } + // Paper end + + public FriendlyByteBuf writeComponent(Component text) { +diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java +index 54d186a195aca6d0a4c412ed609d8c86dcc76072..06e9246f05e130be6a63ebb0c9def10c6c9675b7 100644 +--- a/src/main/java/net/minecraft/network/chat/Component.java ++++ b/src/main/java/net/minecraft/network/chat/Component.java +@@ -363,6 +363,7 @@ public interface Component extends Message, FormattedText, Iterable { + return Component.Serializer.GSON.toJsonTree(text); + } + ++ @Nullable public static Component jsonToComponent(String json) { return fromJson(json);} // Paper - OBFHELPER + @Nullable + public static MutableComponent fromJson(String json) { + return (MutableComponent) GsonHelper.fromJson(Component.Serializer.GSON, json, MutableComponent.class, false); +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java +index 69ff8df7340e60c476803256750a48f0b43414d3..df444daeb181ff78170f7b92bd02f1f1862dfa2e 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java +@@ -47,6 +47,17 @@ public class ClientboundSetTitlesPacket implements Packet +Date: Thu, 3 Mar 2016 02:33:53 -0600 +Subject: [PATCH] Ensure inv drag is in bounds + + +diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index c377a425dc3274b8aa25f94ce8f76efda2652def..72b0cfcc5aab03e14e63440c734436e9c1432111 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -238,7 +238,7 @@ public abstract class AbstractContainerMenu { + this.resetQuickCraft(); + } + } else if (this.quickcraftStatus == 1) { +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = i < this.slots.size() ? this.slots.get(i) : null; // Paper - Ensure drag in bounds + + itemstack1 = playerinventory.getCarried(); + if (slot != null && canItemQuickReplace(slot, itemstack1, true) && slot.isAllowed(itemstack1) && (this.quickcraftType == 2 || itemstack1.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) { diff --git a/Remapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch b/Remapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch new file mode 100644 index 0000000000..6e0641f0dd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joseph Hirschfeld +Date: Thu, 3 Mar 2016 02:39:54 -0600 +Subject: [PATCH] Change implementation of (tile)entity removal list + +use sets for faster removal + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 6c6098731752d61b5241710b075d4ffe3826daac..89472b6e8f38921db50440d0213e40ac893892f1 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1122,7 +1122,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + } + // Spigot End +- this.blockEntitiesToUnload.addAll(chunk.getBlockEntities().values()); ++ this.tileEntityListUnload.addAll(chunk.getBlockEntities().values()); + List[] aentityslice = chunk.getEntitySlices(); // Spigot + int i = aentityslice.length; + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index e25666328dbf433b8358f2637d93b4128034bbaa..7b4475807cca0e92ea9ae6ea49a82a8634cc0ff5 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -89,7 +89,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public final List blockEntityList = Lists.newArrayList(); + public final List tickableBlockEntities = Lists.newArrayList(); + protected final List pendingBlockEntities = Lists.newArrayList(); +- protected final List blockEntitiesToUnload = Lists.newArrayList(); ++ protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); + public final Thread thread; + private final boolean isDebug; + private int skyDarken; +@@ -697,10 +697,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + gameprofilerfiller.push("blockEntities"); + timings.tileEntityTick.startTiming(); // Spigot +- if (!this.blockEntitiesToUnload.isEmpty()) { +- this.tickableBlockEntities.removeAll(this.blockEntitiesToUnload); +- this.blockEntityList.removeAll(this.blockEntitiesToUnload); +- this.blockEntitiesToUnload.clear(); ++ if (!this.tileEntityListUnload.isEmpty()) { ++ this.tickableBlockEntities.removeAll(this.tileEntityListUnload); ++ this.blockEntityList.removeAll(this.tileEntityListUnload); ++ this.tileEntityListUnload.clear(); + } + + this.updatingBlockEntities = true; diff --git a/Remapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch b/Remapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch new file mode 100644 index 0000000000..8bbb23e407 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joseph Hirschfeld +Date: Thu, 3 Mar 2016 02:46:17 -0600 +Subject: [PATCH] Add configurable portal search radius + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 416a6760883cb40367535c7c5acd779742bb8af5..670efbe53241a0ae32d618c83da601ccc1f26e37 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -196,4 +196,13 @@ public class PaperWorldConfig { + private void allChunksAreSlimeChunks() { + allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); + } ++ ++ public int portalSearchRadius; ++ public int portalCreateRadius; ++ public boolean portalSearchVanillaDimensionScaling; ++ private void portalSearchRadius() { ++ portalSearchRadius = getInt("portal-search-radius", 128); ++ portalCreateRadius = getInt("portal-create-radius", 16); ++ portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 72eb40f748c33572c2828f48ebd1ca7d5d5712c8..a6f2e671cc9b2ef086dfa3d127a7b33272acbd56 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2617,7 +2617,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + double d4 = DimensionType.getTeleportationScale(this.level.dimensionType(), destination.dimensionType()); + BlockPos blockposition = new BlockPos(Mth.clamp(this.getX() * d4, d0, d2), this.getY(), Mth.clamp(this.getZ() * d4, d1, d3)); + // CraftBukkit start +- CraftPortalEvent event = callPortalEvent(this, destination, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); ++ // Paper start ++ int portalSearchRadius = destination.paperConfig.portalSearchRadius; ++ if (level.paperConfig.portalSearchVanillaDimensionScaling && flag2) { // == THE_NETHER ++ portalSearchRadius = (int) (portalSearchRadius / destination.dimensionType().coordinateScale()); ++ } ++ // Paper end ++ CraftPortalEvent event = callPortalEvent(this, destination, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, portalSearchRadius, destination.paperConfig.portalCreateRadius); // Paper start - configurable portal radius + if (event == null) { + return null; + } +diff --git a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java +index 948d031627435bfce442b1fe7d3eff4addc85bc4..21c01302635d23bc21e6bb373cbe277ea1eb6a56 100644 +--- a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java ++++ b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java +@@ -30,7 +30,7 @@ public class PortalForcer { + + public Optional findPortalAround(BlockPos blockposition, boolean flag) { + // CraftBukkit start +- return findPortalAround(blockposition, flag ? 16 : 128); // Search Radius ++ return findPortalAround(blockposition, flag ? level.paperConfig.portalCreateRadius : level.paperConfig.portalSearchRadius); // Paper - search Radius + } + + public Optional findPortal(BlockPos blockposition, int i) { diff --git a/Remapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch b/Remapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch new file mode 100644 index 0000000000..3a11078735 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joseph Hirschfeld +Date: Thu, 3 Mar 2016 02:48:12 -0600 +Subject: [PATCH] Add velocity warnings + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 95d32f37db663a37f8fde927bdf9d3d4802ba1b4..35d3df7ded4904414a9a61895950b56be530d244 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -260,6 +260,7 @@ public final class CraftServer implements Server { + public boolean ignoreVanillaPermissions = false; + private final List playerView; + public int reloadCount; ++ public static Exception excessiveVelEx; // Paper - Velocity warnings + + static { + ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index e7a59a8e0424a0839dfa73fc65f44c5b04bd3dec..b028946de7c8f52091635fe154c816453f1ddc93 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -424,10 +424,41 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public void setVelocity(Vector velocity) { + Preconditions.checkArgument(velocity != null, "velocity"); + velocity.checkFinite(); ++ // Paper start - Warn server owners when plugins try to set super high velocities ++ if (!(this instanceof org.bukkit.entity.Projectile) && isUnsafeVelocity(velocity)) { ++ CraftServer.excessiveVelEx = new Exception("Excessive velocity set detected: tried to set velocity of entity " + entity.getScoreboardName() + " id #" + getEntityId() + " to (" + velocity.getX() + "," + velocity.getY() + "," + velocity.getZ() + ")."); ++ } ++ // Paper end ++ + entity.setDeltaMovement(CraftVector.toNMS(velocity)); + entity.hurtMarked = true; + } + ++ // Paper start ++ /** ++ * Checks if the given velocity is not necessarily safe in all situations. ++ * This function returning true does not mean the velocity is dangerous or to be avoided, only that it may be ++ * a detriment to performance on the server. ++ * ++ * It is not to be used as a hard rule of any sort. ++ * Paper only uses it to warn server owners in watchdog crashes. ++ * ++ * @param vel incoming velocity to check ++ * @return if the velocity has the potential to be a performance detriment ++ */ ++ private static boolean isUnsafeVelocity(Vector vel) { ++ final double x = vel.getX(); ++ final double y = vel.getY(); ++ final double z = vel.getZ(); ++ ++ if (x > 4 || x < -4 || y > 4 || y < -4 || z > 4 || z < -4) { ++ return true; ++ } ++ ++ return false; ++ } ++ // Paper end ++ + @Override + public double getHeight() { + return getHandle().getBbHeight(); +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 21d7b483920841456707fe3f08b180c1f072b7f7..0ed95268364ea7f6a92a39b726a1e03bc815be07 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -80,7 +80,19 @@ public class WatchdogThread extends Thread + log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" ); + log.log( Level.SEVERE, "near " + net.minecraft.world.level.Level.lastPhysicsProblem ); + } +- // ++ // Paper start - Warn in watchdog if an excessive velocity was ever set ++ if ( org.bukkit.craftbukkit.CraftServer.excessiveVelEx != null ) ++ { ++ log.log( Level.SEVERE, "------------------------------" ); ++ log.log( Level.SEVERE, "During the run of the server, a plugin set an excessive velocity on an entity" ); ++ log.log( Level.SEVERE, "This may be the cause of the issue, or it may be entirely unrelated" ); ++ log.log( Level.SEVERE, org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getMessage()); ++ for ( StackTraceElement stack : org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getStackTrace() ) ++ { ++ log.log( Level.SEVERE, "\t\t" + stack ); ++ } ++ } ++ // Paper end + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); diff --git a/Remapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch b/Remapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch new file mode 100644 index 0000000000..c0826d9b39 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Thu, 3 Mar 2016 02:50:31 -0600 +Subject: [PATCH] Configurable inter-world teleportation safety + +People are able to abuse the way Bukkit handles teleportation across worlds since it provides a built in teleportation +safety check. + +To abuse the safety check, players are required to get into a location deemed unsafe by Bukkit e.g. be within a chest +or door block. While they are in this block, they accept a teleport request from a player within a different world. Once +the player teleports, Minecraft will recursively search upwards for a safe location, this could eventually land within a +player's skybase. + +Example setup to perform the glitch: http://puu.sh/ng3PC/cf072dcbdb.png +The wanted destination was on top of the emerald block however the player ended on top of the diamond block. +This only is the case if the player is teleporting between worlds. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 670efbe53241a0ae32d618c83da601ccc1f26e37..abbbe1786eb68af02f9d39650aad730ac44aac8a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -205,4 +205,9 @@ public class PaperWorldConfig { + portalCreateRadius = getInt("portal-create-radius", 16); + portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); + } ++ ++ public boolean disableTeleportationSuffocationCheck; ++ private void disableTeleportationSuffocationCheck() { ++ disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 63933bd455ad72a772d4db160e946600b84a1791..3b9d61b524441f65646edf7d403b6c5b5345b1e5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -861,7 +861,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + if (fromWorld == toWorld) { + entity.connection.teleport(to); + } else { +- server.getHandle().moveToWorld(entity, toWorld, true, to, true); ++ server.getHandle().moveToWorld(entity, toWorld, true, to, !toWorld.paperConfig.disableTeleportationSuffocationCheck); // Paper + } + return true; + } diff --git a/Remapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch b/Remapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch new file mode 100644 index 0000000000..7b87e0d39f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch @@ -0,0 +1,264 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joseph Hirschfeld +Date: Thu, 3 Mar 2016 03:15:41 -0600 +Subject: [PATCH] Add exception reporting event + + +diff --git a/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f699ce18ca044f813e194ef2786b7ea853ea86e7 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java +@@ -0,0 +1,38 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Preconditions; ++import org.bukkit.craftbukkit.scheduler.CraftTask; ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerSchedulerException; ++ ++/** ++ * Reporting wrapper to catch exceptions not natively ++ */ ++public class ServerSchedulerReportingWrapper implements Runnable { ++ ++ private final CraftTask internalTask; ++ ++ public ServerSchedulerReportingWrapper(CraftTask internalTask) { ++ this.internalTask = Preconditions.checkNotNull(internalTask, "internalTask"); ++ } ++ ++ @Override ++ public void run() { ++ try { ++ internalTask.run(); ++ } catch (RuntimeException e) { ++ internalTask.getOwner().getServer().getPluginManager().callEvent( ++ new ServerExceptionEvent(new ServerSchedulerException(e, internalTask)) ++ ); ++ throw e; ++ } catch (Throwable t) { ++ internalTask.getOwner().getServer().getPluginManager().callEvent( ++ new ServerExceptionEvent(new ServerSchedulerException(t, internalTask)) ++ ); //Do not rethrow, since it is not permitted with Runnable#run ++ } ++ } ++ ++ public CraftTask getInternalTask() { ++ return internalTask; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index d1bc927c8b429f43de2cdad98f8b329ff4c8b4db..0597c0c3e881dd43cf91bd3088ed30dfecfe8098 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -813,6 +813,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return true; + } catch (Exception exception) { + ChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception); ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper + return false; + } + } +diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java +index c167d2fd99a7a352e69e2930551678bd9c9def83..09c5fa2dbcbed05da51ef2d63e6d6112d22d7877 100644 +--- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java ++++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java +@@ -1,5 +1,6 @@ + package net.minecraft.server.players; + ++import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.io.Files; +@@ -360,6 +361,7 @@ public class OldUsersConverter { + root = NbtIo.readCompressed(new java.io.FileInputStream(file5)); + } catch (Exception exception) { + exception.printStackTrace(); ++ ServerInternalException.reportInternalException(exception); // Paper + } + + if (root != null) { +@@ -373,6 +375,7 @@ public class OldUsersConverter { + NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2)); + } catch (Exception exception) { + exception.printStackTrace(); ++ ServerInternalException.reportInternalException(exception); // Paper + } + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java +index 78cea15142f9fd7988f5df397061b90625070eef..f50774f022c78813982bfe08f764b54bde779e04 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.entity.ai.village; + ++import com.destroystokyo.paper.exception.ServerInternalException; ++ + import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -119,6 +121,7 @@ public class VillageSiege implements CustomSpawner { + entityzombie.finalizeSpawn(world, world.getCurrentDifficultyAt(entityzombie.blockPosition()), MobSpawnType.EVENT, (SpawnGroupData) null, (CompoundTag) null); + } catch (Exception exception) { + VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception); ++ ServerInternalException.reportInternalException(exception); // Paper + return; + } + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 7b4475807cca0e92ea9ae6ea49a82a8634cc0ff5..94e268a05b4601c29b6d2845f0fc2311643a161f 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -1,5 +1,10 @@ + package net.minecraft.world.level; + ++import co.aikar.timings.Timing; ++import co.aikar.timings.Timings; ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerInternalException; ++import com.google.common.base.MoreObjects; + import com.google.common.collect.Lists; + import com.mojang.serialization.Codec; + import java.io.IOException; +@@ -737,8 +742,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + gameprofilerfiller.pop(); + } catch (Throwable throwable) { + // Paper start - Prevent tile entity and entity crashes +- System.err.println("TileEntity threw exception at " + tileentity.level.getWorld().getName() + ":" + tileentity.worldPosition.getX() + "," + tileentity.worldPosition.getY() + "," + tileentity.worldPosition.getZ()); ++ String msg = "TileEntity threw exception at " + tileentity.getLevel().getWorld().getName() + ":" + tileentity.getBlockPos().getX() + "," + tileentity.getBlockPos().getY() + "," + tileentity.getBlockPos().getZ(); ++ System.err.println(msg); + throwable.printStackTrace(); ++ getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); ++ // Paper end + tilesThisCycle--; + this.tickableBlockEntities.remove(tileTickPosition--); + continue; +@@ -808,8 +816,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + tickConsumer.accept(entity); + } catch (Throwable throwable) { + // Paper start - Prevent tile entity and entity crashes +- System.err.println("Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ()); ++ String msg = "Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ(); ++ System.err.println(msg); + throwable.printStackTrace(); ++ getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); + entity.removed = true; + return; + // Paper end +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index fc134b916e95231af8478a4f97bf11a0f37f7f0b..a19ac1cb7e4d8d478648a048b2bfa0daf85a80c9 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -299,6 +299,7 @@ public final class NaturalSpawner { + } + } catch (Exception exception) { + NaturalSpawner.LOGGER.warn("Failed to create mob", exception); ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper + return null; + } + } +@@ -405,6 +406,7 @@ public final class NaturalSpawner { + entity = biomesettingsmobs_c.type.create((Level) worldaccess.getLevel()); + } catch (Exception exception) { + NaturalSpawner.LOGGER.warn("Failed to create mob", exception); ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper + continue; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 300749822d52f9f973e71c6ec9c8bf29d6a6938e..9ca05aa06696883adc8b67a68ca6d2d850e95d25 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.chunk; + ++import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; + import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +@@ -654,10 +655,15 @@ public class LevelChunk implements ChunkAccess { + this.blockEntities.remove(pos); + // Paper end + } else { +- System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() +- + " (" + getBlockState(pos) + ") where there was no entity tile!"); +- System.out.println("Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); +- new Exception().printStackTrace(); ++ // Paper start ++ ServerInternalException e = new ServerInternalException( ++ "Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," ++ + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() ++ + " (" + getBlockState(pos) + ") where there was no entity tile!\n" + ++ "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); ++ e.printStackTrace(); ++ ServerInternalException.reportInternalException(e); ++ // Paper end + // CraftBukkit end + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 60f410a4f838048bbfd2cde52caa7c4c9434b0ba..1598da3449ee1c559cf503e1b20a0daaf6a033dd 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -265,6 +265,7 @@ public class RegionFile implements AutoCloseable { + return true; + } + } catch (IOException ioexception) { ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper + return false; + } + } +@@ -337,6 +338,7 @@ public class RegionFile implements AutoCloseable { + filechannel.write(bytebuffer); + } catch (Throwable throwable1) { + throwable = throwable1; ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper + throw throwable1; + } finally { + if (filechannel != null) { +diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +index 60b7fdf9c092e8105d41f4af02a08651624f3eb9..99cfd693ea705d45a5eab181cb80c354a2d1159f 100644 +--- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +@@ -150,6 +150,7 @@ public class DimensionDataStorage { + } + } catch (Throwable throwable6) { + throwable = throwable6; ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper + throw throwable6; + } finally { + if (fileinputstream != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index ffe9cc1011226d604dc5499e7692e9a9a5132b72..9b6d9373abb59a30c2835ca891282d07559281f5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -16,6 +16,9 @@ import java.util.concurrent.atomic.AtomicInteger; + import java.util.concurrent.atomic.AtomicReference; + import java.util.function.Consumer; + import java.util.logging.Level; ++import com.destroystokyo.paper.ServerSchedulerReportingWrapper; ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerSchedulerException; + import org.apache.commons.lang.Validate; + import org.bukkit.plugin.IllegalPluginAccessException; + import org.bukkit.plugin.Plugin; +@@ -419,6 +422,8 @@ public class CraftScheduler implements BukkitScheduler { + msg, + throwable); + } ++ org.bukkit.Bukkit.getServer().getPluginManager().callEvent( ++ new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task))); + // Paper end + } finally { + currentTask = null; +@@ -426,7 +431,7 @@ public class CraftScheduler implements BukkitScheduler { + parsePending(); + } else { + debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); +- executor.execute(task); ++ executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper + // We don't need to parse pending + // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) + } diff --git a/Remapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/Remapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch new file mode 100644 index 0000000000..f1642d7a3b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Tue, 8 Mar 2016 18:28:43 -0800 +Subject: [PATCH] Don't nest if we don't need to when cerealising text + components + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +index e47102cadb40ed8a9c011386445f15fd30de7596..f13da9e7d014bc00fbabf0a495b548bba2f59468 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +@@ -40,7 +40,14 @@ public class ClientboundChatPacket implements Packet { + // Paper end + // Spigot start + if (components != null) { +- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(components)); ++ //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below ++ // Paper start - don't nest if we don't need to so that we can preserve formatting ++ if (this.components.length == 1) { ++ buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); ++ } else { ++ buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); ++ } ++ // Paper end + } else { + buf.writeComponent(this.message); + } diff --git a/Remapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch b/Remapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch new file mode 100644 index 0000000000..d1cae6e603 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 8 Mar 2016 23:25:45 -0500 +Subject: [PATCH] Disable Scoreboards for non players by default + +Entities collision is checking for scoreboards setting. +This is very heavy to do map lookups for every collision to check +this setting. + +So avoid looking up scoreboards and short circuit to the "not on a team" +logic which is most likely to be true. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index abbbe1786eb68af02f9d39650aad730ac44aac8a..3ac2ac3db9b1c271b3c21930bb13716669ff64d3 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -210,4 +210,9 @@ public class PaperWorldConfig { + private void disableTeleportationSuffocationCheck() { + disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); + } ++ ++ public boolean nonPlayerEntitiesOnScoreboards = false; ++ private void nonPlayerEntitiesOnScoreboards() { ++ nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a6f2e671cc9b2ef086dfa3d127a7b33272acbd56..93d3408231a177cf6d2086594756adffe3efa702 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2288,6 +2288,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + @Nullable + public Team getTeam() { ++ if (!this.level.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof Player)) { return null; } // Paper + return this.level.getScoreboard().getPlayerTeam(this.getScoreboardName()); + } + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index afd114e1ce00db72534d470fed12101bb237f266..d483d552092c901fec262c43e488784d9cd8acb9 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -738,6 +738,7 @@ public abstract class LivingEntity extends Entity { + if (tag.contains("Team", 8)) { + String s = tag.getString("Team"); + PlayerTeam scoreboardteam = this.level.getScoreboard().getTeam(s); ++ if (!level.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof net.minecraft.world.entity.player.Player)) { scoreboardteam = null; } // Paper + boolean flag = scoreboardteam != null && this.level.getScoreboard().addPlayerToTeam(this.getStringUUID(), scoreboardteam); + + if (!flag) { diff --git a/Remapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Remapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch new file mode 100644 index 0000000000..e0d5759239 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: mrapple +Date: Sun, 25 Nov 2012 13:43:39 -0600 +Subject: [PATCH] Add methods for working with arrows stuck in living entities + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 3afdcb3013263a7e06876821d7d889fa48404041..d8cd88d62f9abfc7960c187dd74239f61267ca57 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -677,4 +677,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + getHandle().persistentInvisibility = invisible; + getHandle().setSharedFlag(5, invisible); + } ++ ++ // Paper start ++ @Override ++ public int getArrowsStuck() { ++ return getHandle().getArrowCount(); ++ } ++ ++ @Override ++ public void setArrowsStuck(int arrows) { ++ getHandle().setArrowCount(arrows); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch b/Remapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch new file mode 100644 index 0000000000..6be95196f1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 4 Apr 2015 23:17:52 -0400 +Subject: [PATCH] Complete resource pack API + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 00689dc07625a02781052c5df2e466e8abe85708..73683ba59d0aff3a61f555b4ae15753e9e4e6141 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1603,7 +1603,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit start + public void handleResourcePackResponse(ServerboundResourcePackPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); +- this.craftServer.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()])); ++ // Paper start ++ PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()]; ++ player.getBukkitEntity().setResourcePackStatus(packStatus); ++ this.craftServer.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), packStatus)); ++ // Paper end + } + // CraftBukkit end + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 3b9d61b524441f65646edf7d403b6c5b5345b1e5..dd29038778d73fae84df360515f3c670915f1d48 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -136,6 +136,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + private double health = 20; + private boolean scaledHealth = false; + private double healthScale = 20; ++ // Paper start ++ private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; ++ private String resourcePackHash; ++ // Paper end + + public CraftPlayer(CraftServer server, ServerPlayer entity) { + super(server, entity); +@@ -1872,6 +1876,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public boolean getAffectsSpawning() { + return this.getHandle().affectsSpawning; + } ++ ++ @Override ++ public void setResourcePack(String url, String hash) { ++ Validate.notNull(url, "Resource pack URL cannot be null"); ++ Validate.notNull(hash, "Hash cannot be null"); ++ this.getHandle().sendTexturePack(url, hash); ++ } ++ ++ @Override ++ public org.bukkit.event.player.PlayerResourcePackStatusEvent.Status getResourcePackStatus() { ++ return this.resourcePackStatus; ++ } ++ ++ @Override ++ public String getResourcePackHash() { ++ return this.resourcePackHash; ++ } ++ ++ @Override ++ public boolean hasResourcePack() { ++ return this.resourcePackStatus == org.bukkit.event.player.PlayerResourcePackStatusEvent.Status.SUCCESSFULLY_LOADED; ++ } ++ ++ public void setResourcePackStatus(org.bukkit.event.player.PlayerResourcePackStatusEvent.Status status) { ++ this.resourcePackStatus = status; ++ } + // Paper end + + @Override diff --git a/Remapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch b/Remapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch new file mode 100644 index 0000000000..db35b14461 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 4 Mar 2013 23:46:10 -0500 +Subject: [PATCH] Chunk Save Reattempt + +We commonly have "Stream Closed" errors on chunk saving, so this code should re-try to save the chunk in the event of failure and hopefully prevent rollbacks. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 1598da3449ee1c559cf503e1b20a0daaf6a033dd..1aa4d342b97f8be71c108194a6f1e0e2828aa364 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -265,7 +265,7 @@ public class RegionFile implements AutoCloseable { + return true; + } + } catch (IOException ioexception) { +- com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioexception); // Paper - we want the upper try/catch to retry this + return false; + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index 1e49d17b54704e1b99c3ded458c4bc6842bd32bd..97a58da9d64d812942ceb71426d35b490bbbe817 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -11,6 +11,7 @@ import java.io.IOException; + import javax.annotation.Nullable; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtIo; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.util.ExceptionCollector; + import net.minecraft.world.level.ChunkPos; + +@@ -92,6 +93,7 @@ public final class RegionFileStorage implements AutoCloseable { + + protected void write(ChunkPos pos, CompoundTag tag) throws IOException { + RegionFile regionfile = this.getFile(pos, false); // CraftBukkit ++ int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper + DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(pos); + Throwable throwable = null; + +@@ -115,6 +117,18 @@ public final class RegionFileStorage implements AutoCloseable { + + } + ++ // Paper start ++ return; ++ } catch (Exception ex) { ++ laste = ex; ++ } ++ } ++ ++ if (laste != null) { ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(laste); ++ MinecraftServer.LOGGER.error("Failed to save chunk", laste); ++ } ++ // Paper end + } + + public void close() throws IOException { diff --git a/Remapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch b/Remapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch new file mode 100644 index 0000000000..3df2a1e2a2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 13:17:38 -0400 +Subject: [PATCH] Default loading permissions.yml before plugins + +Under previous behavior, plugins were not able to check if a player had a permission +if it was defined in permissions.yml. there is no clean way for a plugin to fix that either. + +This will change the order so that by default, permissions.yml loads BEFORE plugins instead of after. + +This gives plugins expected permission checks. + +It also helps improve the expected logic, as servers should set the initial defaults, and then let plugins +modify that. Under the previous logic, plugins were unable (cleanly) override permissions.yml. + +A config option has been added for those who depend on the previous behavior, but I don't expect that. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 429b74474ced04d8dd8f038b8590b8dfe178bf4d..716f285e67019b8a62922d09c15883c99f9421aa 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -222,4 +222,9 @@ public class PaperConfig { + private static void useDisplayNameInQuit() { + useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); + } ++ ++ public static boolean loadPermsBeforePlugins = true; ++ private static void loadPermsBeforePlugins() { ++ loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 35d3df7ded4904414a9a61895950b56be530d244..662fc88e2e118a57a6c35a8981d4622188adec3b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -397,6 +397,7 @@ public final class CraftServer implements Server { + if (type == PluginLoadOrder.STARTUP) { + helpMap.clear(); + helpMap.initializeGeneralTopics(); ++ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper + } + + Plugin[] plugins = pluginManager.getPlugins(); +@@ -416,7 +417,7 @@ public final class CraftServer implements Server { + commandMap.registerServerAliases(); + DefaultPermissions.registerCorePermissions(); + CraftDefaultPermissions.registerCorePermissions(); +- loadCustomPermissions(); ++ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper + helpMap.initializeCommands(); + syncCommands(); + } diff --git a/Remapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch b/Remapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch new file mode 100644 index 0000000000..e43351be69 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William +Date: Fri, 18 Mar 2016 03:30:17 -0400 +Subject: [PATCH] Allow Reloading of Custom Permissions + +https://github.com/PaperMC/Paper/issues/49 + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 662fc88e2e118a57a6c35a8981d4622188adec3b..50da8e292c131176c263f0bc140ff4f6d890c737 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2252,5 +2252,23 @@ public final class CraftServer implements Server { + } + return this.adventure$audiences; + } ++ ++ @Override ++ public void reloadPermissions() { ++ pluginManager.clearPermissions(); ++ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); ++ for (Plugin plugin : pluginManager.getPlugins()) { ++ for (Permission perm : plugin.getDescription().getPermissions()) { ++ try { ++ pluginManager.addPermission(perm); ++ } catch (IllegalArgumentException ex) { ++ getLogger().log(Level.WARNING, "Plugin " + plugin.getDescription().getFullName() + " tried to register permission '" + perm.getName() + "' but it's already registered", ex); ++ } ++ } ++ } ++ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); ++ DefaultPermissions.registerCorePermissions(); ++ CraftDefaultPermissions.registerCorePermissions(); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch b/Remapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch new file mode 100644 index 0000000000..bad86d108d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 13:50:14 -0400 +Subject: [PATCH] Remove Metadata on reload + +Metadata is not meant to persist reload as things break badly with non primitive types +This will remove metadata on reload so it does not crash everything if a plugin uses it. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 50da8e292c131176c263f0bc140ff4f6d890c737..2828936fe294d9d6750a8838da49ec8398835214 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -870,8 +870,18 @@ public final class CraftServer implements Server { + world.paperConfig.init(); // Paper + } + ++ Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper + pluginManager.clearPlugins(); + commandMap.clearCommands(); ++ ++ // Paper start ++ for (Plugin plugin : pluginClone) { ++ entityMetadata.removeAll(plugin); ++ worldMetadata.removeAll(plugin); ++ playerMetadata.removeAll(plugin); ++ } ++ // Paper end ++ + resetRecipes(); + reloadData(); + org.spigotmc.SpigotConfig.registerCommands(); // Spigot diff --git a/Remapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch b/Remapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch new file mode 100644 index 0000000000..32698665bc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch @@ -0,0 +1,339 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 28 May 2015 23:00:19 -0400 +Subject: [PATCH] Handle Item Meta Inconsistencies + +First, Enchantment order would blow away seeing 2 items as the same, +however the Client forces enchantment list in a certain order, as well +as does the /enchant command. Anvils can insert it into forced order, +causing 2 same items to be considered different. + +This change makes unhandled NBT Tags and Enchantments use a sorted tree map, +so they will always be in a consistent order. + +Additionally, the old enchantment API was never updated when ItemMeta +was added, resulting in 2 different ways to modify an items enchantments. + +For consistency, the old API methods now forward to use the +ItemMeta API equivalents, and should deprecate the old API's. + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 3faf52e7ac5e7e22d09cfb73cfda6b9f622137d4..123025c6dc9a2eea56c7db5cb508cdfd7c6cc97b 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -9,6 +9,8 @@ import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; + import java.text.DecimalFormat; + import java.text.DecimalFormatSymbols; ++import java.util.Collections; ++import java.util.Comparator; + import java.util.Locale; + import java.util.Objects; + import java.util.Optional; +@@ -118,6 +120,23 @@ public final class ItemStack { + private BlockInWorld cachedPlaceBlock; + private boolean cachedPlaceBlockResult; + ++ // Paper start ++ private static final java.util.Comparator enchantSorter = java.util.Comparator.comparing(o -> o.getString("id")); ++ private void processEnchantOrder(CompoundTag tag) { ++ if (tag == null || !tag.contains("Enchantments", 9)) { ++ return; ++ } ++ ListTag list = tag.getList("Enchantments", 10); ++ if (list.size() < 2) { ++ return; ++ } ++ try { ++ //noinspection unchecked ++ list.sort((Comparator) enchantSorter); // Paper ++ } catch (Exception ignored) {} ++ } ++ // Paper end ++ + public ItemStack(ItemLike item) { + this(item, 1); + } +@@ -160,6 +179,7 @@ public final class ItemStack { + if (nbttagcompound.contains("tag", 10)) { + // CraftBukkit start - make defensive copy as this data may be coming from the save thread + this.tag = (CompoundTag) nbttagcompound.getCompound("tag").copy(); ++ processEnchantOrder(this.tag); // Paper + this.getItem().verifyTagAfterLoad(this.tag); + // CraftBukkit end + } +@@ -678,6 +698,7 @@ public final class ItemStack { + // Paper end + public void setTag(@Nullable CompoundTag tag) { + this.tag = tag; ++ processEnchantOrder(this.tag); // Paper + if (this.getItem().canBeDepleted()) { + this.setDamageValue(this.getDamageValue()); + } +@@ -768,6 +789,7 @@ public final class ItemStack { + nbttagcompound.putString("id", String.valueOf(Registry.ENCHANTMENT.getKey(enchantment))); + nbttagcompound.putShort("lvl", (short) ((byte) level)); + nbttaglist.add(nbttagcompound); ++ processEnchantOrder(nbttagcompound); // Paper + } + + public boolean isEnchanted() { +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index 01df5263d77771a296ca091a0feec620e6e37229..5f0ccdeb8565505278caa591f7390047eab49cf4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -6,7 +6,6 @@ import java.util.Map; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.world.item.Item; +-import net.minecraft.world.item.enchantment.EnchantmentHelper; + import org.apache.commons.lang.Validate; + import org.bukkit.Material; + import org.bukkit.configuration.serialization.DelegateDeserialization; +@@ -178,28 +177,11 @@ public final class CraftItemStack extends ItemStack { + public void addUnsafeEnchantment(Enchantment ench, int level) { + Validate.notNull(ench, "Cannot add null enchantment"); + +- if (!makeTag(handle)) { +- return; +- } +- ListTag list = getEnchantmentList(handle); +- if (list == null) { +- list = new ListTag(); +- handle.getTag().put(ENCHANTMENTS.NBT, list); +- } +- int size = list.size(); +- +- for (int i = 0; i < size; i++) { +- CompoundTag tag = (CompoundTag) list.get(i); +- String id = tag.getString(ENCHANTMENTS_ID.NBT); +- if (id.equals(ench.getKey().toString())) { +- tag.putShort(ENCHANTMENTS_LVL.NBT, (short) level); +- return; +- } +- } +- CompoundTag tag = new CompoundTag(); +- tag.putString(ENCHANTMENTS_ID.NBT, ench.getKey().toString()); +- tag.putShort(ENCHANTMENTS_LVL.NBT, (short) level); +- list.add(tag); ++ // Paper start - Replace whole method ++ final ItemMeta itemMeta = getItemMeta(); ++ itemMeta.addEnchant(ench, level, true); ++ setItemMeta(itemMeta); ++ // Paper end + } + + static boolean makeTag(net.minecraft.world.item.ItemStack item) { +@@ -216,66 +198,33 @@ public final class CraftItemStack extends ItemStack { + + @Override + public boolean containsEnchantment(Enchantment ench) { +- return getEnchantmentLevel(ench) > 0; ++ return hasItemMeta() && getItemMeta().hasEnchant(ench); // Paper - use meta + } + + @Override + public int getEnchantmentLevel(Enchantment ench) { +- Validate.notNull(ench, "Cannot find null enchantment"); +- if (handle == null) { +- return 0; +- } +- return EnchantmentHelper.getItemEnchantmentLevel(CraftEnchantment.getRaw(ench), handle); ++ return hasItemMeta() ? getItemMeta().getEnchantLevel(ench) : 0; // Paper - replace entire method with meta + } + + @Override + public int removeEnchantment(Enchantment ench) { + Validate.notNull(ench, "Cannot remove null enchantment"); + +- ListTag list = getEnchantmentList(handle), listCopy; +- if (list == null) { +- return 0; +- } +- int index = Integer.MIN_VALUE; +- int level = Integer.MIN_VALUE; +- int size = list.size(); +- +- for (int i = 0; i < size; i++) { +- CompoundTag enchantment = (CompoundTag) list.get(i); +- String id = enchantment.getString(ENCHANTMENTS_ID.NBT); +- if (id.equals(ench.getKey().toString())) { +- index = i; +- level = 0xffff & enchantment.getShort(ENCHANTMENTS_LVL.NBT); +- break; +- } +- } +- +- if (index == Integer.MIN_VALUE) { +- return 0; +- } +- if (size == 1) { +- handle.getTag().remove(ENCHANTMENTS.NBT); +- if (handle.getTag().isEmpty()) { +- handle.setTag(null); +- } +- return level; +- } +- +- // This is workaround for not having an index removal +- listCopy = new ListTag(); +- for (int i = 0; i < size; i++) { +- if (i != index) { +- listCopy.add(list.get(i)); +- } ++ // Paper start - replace entire method ++ final ItemMeta itemMeta = getItemMeta(); ++ int level = itemMeta.getEnchantLevel(ench); ++ if (level > 0) { ++ itemMeta.removeEnchant(ench); ++ setItemMeta(itemMeta); + } +- handle.getTag().put(ENCHANTMENTS.NBT, listCopy); ++ // Paper end + + return level; + } + + @Override + public Map getEnchantments() { +- return getEnchantments(handle); ++ return hasItemMeta() ? getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta + } + + 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 cca04daf84e506382365c0ba945cb024bd4d4475..521699615778c4b724d10edfee1d3915e036eb2e 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; + import com.google.common.collect.ImmutableMap; + import com.google.common.collect.ImmutableMultimap; + import com.google.common.collect.LinkedHashMultimap; ++import com.google.common.collect.ImmutableSortedMap; // Paper + import com.google.common.collect.Lists; + import com.google.common.collect.Multimap; + import com.google.common.collect.SetMultimap; +@@ -22,6 +23,7 @@ import java.lang.reflect.InvocationTargetException; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collection; ++import java.util.Comparator; // Paper + import java.util.EnumSet; + import java.util.HashMap; + import java.util.Iterator; +@@ -32,6 +34,7 @@ import java.util.Map; + import java.util.NoSuchElementException; + import java.util.Objects; + import java.util.Set; ++import java.util.TreeMap; // Paper + import java.util.logging.Level; + import java.util.logging.Logger; + import javax.annotation.Nonnull; +@@ -270,7 +273,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + private List lore; // null and empty are two different states internally + private Integer customModelData; + private CompoundTag blockData; +- private Map enchantments; ++ private EnchantmentMap enchantments; // Paper + private Multimap attributeModifiers; + private int repairCost; + private int hideFlag; +@@ -281,7 +284,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); + + private CompoundTag internalTag; +- private final Map unhandledTags = new HashMap(); ++ private final Map unhandledTags = new TreeMap<>(); // Paper + private CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); + + private int version = CraftMagicNumbers.INSTANCE.getDataVersion(); // Internal use only +@@ -302,7 +305,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + this.blockData = meta.blockData; + + if (meta.enchantments != null) { // Spigot +- this.enchantments = new LinkedHashMap(meta.enchantments); ++ this.enchantments = new EnchantmentMap(meta.enchantments); // Paper + } + + if (meta.hasAttributeModifiers()) { +@@ -385,13 +388,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + } + +- static Map buildEnchantments(CompoundTag tag, ItemMetaKey key) { ++ static EnchantmentMap buildEnchantments(CompoundTag tag, ItemMetaKey key) { // Paper + if (!tag.contains(key.NBT)) { + return null; + } + + ListTag ench = tag.getList(key.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); +- Map enchantments = new LinkedHashMap(ench.size()); ++ EnchantmentMap enchantments = new EnchantmentMap(); // Paper + + for (int i = 0; i < ench.size(); i++) { + String id = ((CompoundTag) ench.get(i)).getString(ENCHANTMENTS_ID.NBT); +@@ -544,13 +547,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + } + +- static Map buildEnchantments(Map map, ItemMetaKey key) { ++ static EnchantmentMap buildEnchantments(Map map, ItemMetaKey key) { // Paper + Map ench = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); + if (ench == null) { + return null; + } + +- Map enchantments = new LinkedHashMap(ench.size()); ++ EnchantmentMap enchantments = new EnchantmentMap(); // Paper + for (Map.Entry entry : ench.entrySet()) { + // Doctor older enchants + String enchantKey = entry.getKey().toString(); +@@ -826,14 +829,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + + @Override + public Map getEnchants() { +- return hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); ++ return hasEnchants() ? ImmutableSortedMap.copyOfSorted(enchantments) : ImmutableMap.of(); // Paper + } + + @Override + public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { + Validate.notNull(ench, "Enchantment cannot be null"); + if (enchantments == null) { +- enchantments = new LinkedHashMap(4); ++ enchantments = new EnchantmentMap(); // Paper + } + + if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { +@@ -1214,7 +1217,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + clone.customModelData = this.customModelData; + clone.blockData = this.blockData; + if (this.enchantments != null) { +- clone.enchantments = new LinkedHashMap(this.enchantments); ++ clone.enchantments = new EnchantmentMap(this.enchantments); // Paper + } + if (this.hasAttributeModifiers()) { + clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); +@@ -1446,4 +1449,22 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return HANDLED_TAGS; + } + } ++ ++ // Paper start ++ private static class EnchantmentMap extends TreeMap { ++ private EnchantmentMap(Map enchantments) { ++ this(); ++ putAll(enchantments); ++ } ++ ++ private EnchantmentMap() { ++ super(Comparator.comparing(o -> o.getKey().toString())); ++ } ++ ++ public EnchantmentMap clone() { ++ return (EnchantmentMap) super.clone(); ++ } ++ } ++ // Paper end ++ + } diff --git a/Remapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/Remapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch new file mode 100644 index 0000000000..a940748e3b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 15:12:22 -0400 +Subject: [PATCH] Configurable Non Player Arrow Despawn Rate + +Can set a much shorter despawn rate for arrows that players can not pick up. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3ac2ac3db9b1c271b3c21930bb13716669ff64d3..3c78d3234054ce2dc46ef77decb6adb0cbd10620 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -215,4 +215,19 @@ public class PaperWorldConfig { + private void nonPlayerEntitiesOnScoreboards() { + nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); + } ++ ++ public int nonPlayerArrowDespawnRate = -1; ++ public int creativeArrowDespawnRate = -1; ++ private void nonPlayerArrowDespawnRate() { ++ nonPlayerArrowDespawnRate = getInt("non-player-arrow-despawn-rate", -1); ++ if (nonPlayerArrowDespawnRate == -1) { ++ nonPlayerArrowDespawnRate = spigotConfig.arrowDespawnRate; ++ } ++ creativeArrowDespawnRate = getInt("creative-arrow-despawn-rate", -1); ++ if (creativeArrowDespawnRate == -1) { ++ creativeArrowDespawnRate = spigotConfig.arrowDespawnRate; ++ } ++ log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); ++ log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); ++ } + } +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 371fdcbf1f9c01f6a356393f6c3767511f230930..0dc5792d542658107c9c22c1f920986decd13920 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -281,7 +281,7 @@ public abstract class AbstractArrow extends Projectile { + + protected void tickDespawn() { + ++this.life; +- if (this.life >= ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)) { // Spigot ++ if (this.life >= (pickup == Pickup.CREATIVE_ONLY ? level.paperConfig.creativeArrowDespawnRate : (pickup == Pickup.DISALLOWED ? level.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? + this.remove(); + } + diff --git a/Remapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch b/Remapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch new file mode 100644 index 0000000000..83f43bb54a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 20:16:03 -0400 +Subject: [PATCH] Add World Util Methods + +Methods that can be used for other patches to help improve logic. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 89472b6e8f38921db50440d0213e40ac893892f1..e1f9a12c7fb4818a785b9a4819f94fccde02b6a2 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -191,7 +191,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; + +- public LevelChunk getChunkIfLoaded(int x, int z) { ++ @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkSource.getChunk(x, z, false); + } + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 94e268a05b4601c29b6d2845f0fc2311643a161f..799721ac63f0c08dd03a788b87eafa9a8cc976cc 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -297,11 +297,27 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + + @Override +- public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ public final FluidState getFluidIfLoaded(BlockPos blockposition) { + ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); + + return chunk == null ? null : chunk.getFluidState(blockposition); + } ++ ++ public final boolean isLoadedAndInBounds(BlockPos blockposition) { // Paper - final for inline ++ return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; ++ } ++ ++ public LevelChunk getChunkIfLoaded(int x, int z) { // Overridden in WorldServer for ABI compat which has final ++ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(x, z); ++ } ++ public final LevelChunk getChunkIfLoaded(BlockPos blockposition) { ++ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ } ++ ++ // reduces need to do isLoaded before getType ++ public final BlockState getTypeIfLoadedAndInBounds(BlockPos blockposition) { ++ return getWorldBorder().isInBounds(blockposition) ? getTypeIfLoaded(blockposition) : null; ++ } + // Paper end + + @Override +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index 31f17956b3b031d1a47bda4d282554c8a7853097..0846f649dca3422dbab3bb0a4826e27430cc8186 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -31,6 +31,7 @@ public class WorldBorder { + + public WorldBorder() {} + ++ public final boolean isInBounds(BlockPos blockposition) { return this.isWithinBounds(blockposition); } // Paper - OBFHELPER + public boolean isWithinBounds(BlockPos pos) { + return (double) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ(); + } diff --git a/Remapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch b/Remapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch new file mode 100644 index 0000000000..2e91f18d2b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sun, 21 Jun 2015 15:07:20 -0400 +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 d483d552092c901fec262c43e488784d9cd8acb9..3c707ca6b56e89b671db6316d4db90a2903f33b4 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3202,9 +3202,10 @@ public abstract class LivingEntity extends Entity { + this.triggerItemUseEffects(this.useItem, 16); + // CraftBukkit start - fire PlayerItemConsumeEvent + ItemStack itemstack; ++ PlayerItemConsumeEvent event = null; // Paper + if (this instanceof ServerPlayer) { + org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.useItem); +- PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); ++ event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); // Paper + level.getCraftServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { +@@ -3218,6 +3219,13 @@ public abstract class LivingEntity extends Entity { + } else { + itemstack = this.useItem.finishUsingItem(this.level, this); + } ++ ++ // Paper start - save the default replacement item and change it if necessary ++ final ItemStack defaultReplacement = itemstack; ++ if (event != null && event.getReplacement() != null) { ++ itemstack = CraftItemStack.asNMSCopy(event.getReplacement()); ++ } ++ // Paper end + // CraftBukkit end + + if (itemstack != this.useItem) { +@@ -3225,6 +3233,11 @@ public abstract class LivingEntity extends Entity { + } + + this.stopUsingItem(); ++ // Paper start - if the replacement is anything but the default, update the client inventory ++ if (this instanceof ServerPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { ++ ((ServerPlayer) this).getBukkitEntity().updateInventory(); ++ } ++ // Paper end + } + + } diff --git a/Remapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/Remapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch new file mode 100644 index 0000000000..0d5d5d19aa --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 27 Sep 2015 01:18:02 -0400 +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 3c707ca6b56e89b671db6316d4db90a2903f33b4..a326e5b4ac055f2f8a95c6eaccd8d0a97762da1f 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -699,7 +699,13 @@ public abstract class LivingEntity extends Entity { + + @Override + public void readAdditionalSaveData(CompoundTag tag) { +- this.setAbsorptionAmount(tag.getFloat("AbsorptionAmount")); ++ // Paper start - jvm keeps optimizing the setter ++ float absorptionAmount = tag.getFloat("AbsorptionAmount"); ++ if (Float.isNaN(absorptionAmount)) { ++ absorptionAmount = 0; ++ } ++ this.setAbsorptionAmount(absorptionAmount); ++ // Paper end + if (tag.contains("Attributes", 9) && this.level != null && !this.level.isClientSide) { + this.getAttributes().load(tag.getList("Attributes", 10)); + } +@@ -1148,6 +1154,10 @@ public abstract class LivingEntity extends Entity { + } + + public void setHealth(float health) { ++ // Paper start ++ if (Float.isNaN(health)) { health = getMaxHealth(); if (this.valid) { ++ System.err.println("[NAN-HEALTH] " + getScoreboardName() + " had NaN health set"); ++ } } // Paper end + // CraftBukkit start - Handle scaled health + if (this instanceof ServerPlayer) { + org.bukkit.craftbukkit.entity.CraftPlayer player = ((ServerPlayer) this).getBukkitEntity(); +@@ -3042,7 +3052,7 @@ public abstract class LivingEntity extends Entity { + } + + public void setAbsorptionAmount(float amount) { +- if (amount < 0.0F) { ++ if (amount < 0.0F || Float.isNaN(amount)) { // Paper + amount = 0.0F; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index dd29038778d73fae84df360515f3c670915f1d48..b7d5a718375083a4162df4bb41de3acd57b297fb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1678,6 +1678,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void setRealHealth(double health) { ++ if (Double.isNaN(health)) {return;} // Paper + this.health = health; + } + diff --git a/Remapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch b/Remapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch new file mode 100644 index 0000000000..ddca7a2d46 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 22 Mar 2016 00:33:47 -0400 +Subject: [PATCH] Use a Shared Random for Entities + +Reduces memory usage and provides ensures more randomness, Especially since a lot of garbage entity objects get created. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 93d3408231a177cf6d2086594756adffe3efa702..61048140cf0adca03bfb57193ada0adaee73b1bb 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -142,6 +142,21 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; + } + ++ // Paper start ++ public static Random SHARED_RANDOM = new Random() { ++ private boolean locked = false; ++ @Override ++ public synchronized void setSeed(long seed) { ++ if (locked) { ++ LogManager.getLogger().error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable()); ++ } else { ++ super.setSeed(seed); ++ locked = true; ++ } ++ } ++ }; ++ // Paper end ++ + private CraftEntity bukkitEntity; + + public CraftEntity getBukkitEntity() { +@@ -271,7 +286,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.stuckSpeedMultiplier = Vec3.ZERO; + this.nextStep = 1.0F; + this.nextFlap = 1.0F; +- this.random = new Random(); ++ this.random = SHARED_RANDOM; // Paper + this.remainingFireTicks = -this.getFireImmuneTicks(); + this.fluidHeight = new Object2DoubleArrayMap(2); + this.firstTick = true; diff --git a/Remapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch b/Remapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch new file mode 100644 index 0000000000..59b6c7f72a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 22 Mar 2016 12:04:28 -0500 +Subject: [PATCH] Configurable spawn chances for skeleton horses + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3c78d3234054ce2dc46ef77decb6adb0cbd10620..cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -230,4 +230,12 @@ public class PaperWorldConfig { + log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); + log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); + } ++ ++ public double skeleHorseSpawnChance; ++ private void skeleHorseSpawnChance() { ++ skeleHorseSpawnChance = getDouble("skeleton-horse-thunder-spawn-chance", 0.01D); ++ if (skeleHorseSpawnChance < 0) { ++ skeleHorseSpawnChance = 0.01D; // Vanilla value ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index e1f9a12c7fb4818a785b9a4819f94fccde02b6a2..22c687e3db79bcfbc512ce3993d6e8a6db062360 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -584,7 +584,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); + if (this.isRainingAt(blockposition)) { + DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); +- boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * 0.01D; ++ boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance; // Paper + + if (flag1) { + SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create((net.minecraft.world.level.Level) this); diff --git a/Remapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/Remapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch new file mode 100644 index 0000000000..2c0ed8f7cd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch @@ -0,0 +1,206 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 02:07:55 -0600 +Subject: [PATCH] Optimize isValidLocation, getType and getBlockData for + inlining + +Hot methods, so reduce # of instructions for the method. + +Move is valid location test to the BlockPosition class so that it can access local variables. + +Replace all calls to the new place to the unnecessary forward. + +Optimize getType and getBlockData to manually inline and optimize the calls + +diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java +index 3e79b274b8e0406a3cbdd94c7cec091b583109ca..c22de593be404c4e921724bba6a69c13759a95fd 100644 +--- a/src/main/java/net/minecraft/core/Vec3i.java ++++ b/src/main/java/net/minecraft/core/Vec3i.java +@@ -22,6 +22,15 @@ public class Vec3i implements Comparable { + private int y;public final void setY(final int y) { this.y = y; } // Paper - OBFHELPER + private int z;public final void setZ(final int z) { this.z = z; } // Paper - OBFHELPER + ++ // Paper start ++ public boolean isValidLocation() { ++ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && getY() >= 0 && getY() < 256; ++ } ++ public boolean isInvalidYLocation() { ++ return y < 0 || y >= 256; ++ } ++ // Paper end ++ + public Vec3i(int x, int y, int z) { + this.x = x; + this.y = y; +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 799721ac63f0c08dd03a788b87eafa9a8cc976cc..24a6429059f58f51c97386ca2823ca0910288dec 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -239,7 +239,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + + public static boolean isInWorldBounds(BlockPos pos) { +- return !isOutsideBuildHeight(pos) && isInWorldBoundsHorizontal(pos); ++ return pos.isValidLocation(); // Paper - use better/optimized check + } + + public static boolean isInSpawnableBounds(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index 3ca6289ba4952b5036367451b50cd90a78c0f938..e6303cdb433ee2b6782e2a0bd6b03e4f6ecb18ba 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -25,6 +25,7 @@ import org.apache.logging.log4j.LogManager; + + public interface ChunkAccess extends BlockGetter, FeatureAccess { + ++ BlockState getType(final int x, final int y, final int z); // Paper + @Nullable + BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); + +diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +index a26de06252207cf333ea4a8d73f0af6ddc239103..e369730ac6909ff5343468bd685c9ea2b6b3cfed 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +@@ -23,7 +23,7 @@ import net.minecraft.world.phys.AABB; + + public class EmptyLevelChunk extends LevelChunk { + +- private static final Biome[] BIOMES = (Biome[]) Util.make((Object) (new Biome[ChunkBiomeContainer.BIOMES_SIZE]), (abiomebase) -> { ++ private static final Biome[] BIOMES = Util.make((new Biome[ChunkBiomeContainer.BIOMES_SIZE]), (abiomebase) -> { // Paper - decompile error + Arrays.fill(abiomebase, Biomes.PLAINS); + }); + +@@ -31,6 +31,11 @@ public class EmptyLevelChunk extends LevelChunk { + super(world, pos, new ChunkBiomeContainer(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), EmptyLevelChunk.BIOMES)); + } + ++ // Paper start ++ @Override public BlockState getType(int x, int y, int z) { ++ return Blocks.VOID_AIR.defaultBlockState(); ++ } ++ // Paper end + @Override + public BlockState getBlockState(BlockPos pos) { + return Blocks.VOID_AIR.defaultBlockState(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +index 04940ab2814cf39157d234dc4615646d7c760460..17fa8b23d1000ae53f2b4f1a6e8817c1005c1c81 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +@@ -42,6 +42,11 @@ public class ImposterProtoChunk extends ProtoChunk { + public BlockState getBlockState(BlockPos pos) { + return this.wrapped.getBlockState(pos); + } ++ // Paper start ++ public final BlockState getType(final int x, final int y, final int z) { ++ return this.wrapped.getBlockData(x, y, z); ++ } ++ // Paper end + + @Override + public FluidState getFluidState(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 9ca05aa06696883adc8b67a68ca6d2d850e95d25..546fb2f42e6bf333582b504d0a29991698505df3 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -347,12 +347,27 @@ public class LevelChunk implements ChunkAccess { + return this.sections; + } + +- @Override ++ // Paper start - Optimize getBlockData to reduce instructions ++ public final BlockState getBlockData(BlockPos pos) { return getBlockData(pos.getX(), pos.getY(), pos.getZ()); } // Paper + public BlockState getBlockState(BlockPos pos) { +- int i = pos.getX(); +- int j = pos.getY(); +- int k = pos.getZ(); ++ return this.getBlockData(pos.getX(), pos.getY(), pos.getZ()); ++ } + ++ public BlockState getType(final int x, final int y, final int z) { ++ return getBlockData(x, y, z); ++ } ++ public final BlockState getBlockData(final int x, final int y, final int z) { ++ // Method body / logic copied from below ++ final int i = y >> 4; ++ if (y < 0 || i >= this.sections.length || this.sections[i] == null || this.sections[i].nonEmptyBlockCount == 0) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) ++ return this.sections[i].states.get((y & 15) << 8 | (z & 15) << 4 | x & 15); ++ } ++ ++ public BlockState getBlockData_unused(int i, int j, int k) { ++ // Paper end + if (this.world.isDebug()) { + BlockState iblockdata = null; + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index b54d82e0f41a03c91e0de8df8249a91da3c04d0e..f5db97fb0dac78e1d9aa68d0417aa13f39914f52 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -13,10 +13,10 @@ public class LevelChunkSection { + + public static final Palette GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState()); + private final int bottomBlockY; +- private short nonEmptyBlockCount; ++ short nonEmptyBlockCount; // Paper - package-private + private short tickingBlockCount; + private short tickingFluidCount; +- private final PalettedContainer states; ++ final PalettedContainer states; // Paper - package-private + + public LevelChunkSection(int yOffset) { + this(yOffset, (short) 0, (short) 0, (short) 0); +@@ -30,8 +30,8 @@ public class LevelChunkSection { + this.states = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); + } + +- public BlockState getBlockState(int x, int y, int z) { +- return (BlockState) this.states.get(x, y, z); ++ public final BlockState getBlockState(int x, int y, int z) { // Paper ++ return this.states.get(y << 8 | z << 4 | x); // Paper - inline + } + + public FluidState getFluidState(int x, int y, int z) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index d4db27421736f665739436c1ac4d3c6d5cae95cd..6d3dcd19ce1abc9d502903b8008949b5174a13c3 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -133,7 +133,7 @@ public class PalettedContainer implements PaletteResize { + } + + public T get(int x, int y, int z) { +- return this.get(getIndex(x, y, z)); ++ return this.get(y << 8 | z << 4 | x); // Paper - inline + } + + protected T get(int index) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index 7cd3f89004b0a64772fc3dfbdd132ba5a850b63e..d8b7b210484079c9ca2c34831c84102cba6692f5 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -113,16 +113,18 @@ public class ProtoChunk implements ChunkAccess { + + @Override + public BlockState getBlockState(BlockPos pos) { +- int i = pos.getY(); +- +- if (Level.isOutsideBuildHeight(i)) { ++ return getType(pos.getX(), pos.getY(), pos.getZ()); ++ } ++ // Paper start ++ public BlockState getType(final int x, final int y, final int z) { ++ if (y < 0 || y >= 256) { + return Blocks.VOID_AIR.defaultBlockState(); + } else { +- LevelChunkSection chunksection = this.getSections()[i >> 4]; +- +- return LevelChunkSection.isEmpty(chunksection) ? Blocks.AIR.defaultBlockState() : chunksection.getBlockState(pos.getX() & 15, i & 15, pos.getZ() & 15); ++ LevelChunkSection chunksection = this.getSections()[y >> 4]; ++ return chunksection == LevelChunk.EMPTY_CHUNK_SECTION || chunksection.isEmpty() ? Blocks.AIR.defaultBlockState() : chunksection.getBlockState(x & 15, y & 15, z & 15); + } + } ++ // Paper end + + @Override + public FluidState getFluidState(BlockPos pos) { diff --git a/Remapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/Remapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch new file mode 100644 index 0000000000..1bc2cb3b6f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 19:55:45 -0400 +Subject: [PATCH] Only process BlockPhysicsEvent if a plugin has a listener + +Saves on some object allocation and processing when no plugin listens to this + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 901d5497667706c049718dc4fca37a1bc489c465..f7763a773bce4d8d947c8c859fe84d8a601034c5 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1290,6 +1290,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper + + this.profiler.push(() -> { + return worldserver + " " + worldserver.dimension().location(); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 22c687e3db79bcfbc512ce3993d6e8a6db062360..8b0a384caa09848d61b3a6259dd56590cd52d0a0 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -190,6 +190,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + private int tickPosition; + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; ++ public boolean hasPhysicsEvent = true; // Paper + + @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkSource.getChunk(x, z, false); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 24a6429059f58f51c97386ca2823ca0910288dec..d47ed15382f98aabd509e32a3c202a91088adf6b 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -458,7 +458,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // CraftBukkit start + iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam + CraftWorld world = ((ServerLevel) this).getWorld(); +- if (world != null) { ++ if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper + BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); + this.getCraftServer().getPluginManager().callEvent(event); + +@@ -560,7 +560,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + try { + // CraftBukkit start + CraftWorld world = ((ServerLevel) this).getWorld(); +- if (world != null) { ++ if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper + BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(sourcePos.getX(), sourcePos.getY(), sourcePos.getZ()), CraftBlockData.fromData(iblockdata), world.getBlockAt(neighborPos.getX(), neighborPos.getY(), neighborPos.getZ())); + this.getCraftServer().getPluginManager().callEvent(event); + +diff --git a/src/main/java/net/minecraft/world/level/block/BushBlock.java b/src/main/java/net/minecraft/world/level/block/BushBlock.java +index d6cb341d4d8e20b77979a241dd2e4346455796d7..42635b6115187abeffb290ca040350fd97cf89f7 100644 +--- a/src/main/java/net/minecraft/world/level/block/BushBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BushBlock.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; + + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; +@@ -23,7 +24,7 @@ public class BushBlock extends Block { + public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { + // CraftBukkit start + if (!state.canSurvive(world, pos)) { +- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { ++ if (!(world instanceof ServerLevel && ((ServerLevel) world).hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper + return Blocks.AIR.defaultBlockState(); + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java +index db444689092f537dd736dc73c532bd540fadcf86..86c5025d1b21dc35782124eca66288c63626147a 100644 +--- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java +@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +@@ -83,7 +84,7 @@ public class DoublePlantBlock extends BushBlock { + + protected static void preventCreativeDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) { + // CraftBukkit start +- if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { ++ if (((ServerLevel)world).hasPhysicsEvent && org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper + return; + } + // CraftBukkit end diff --git a/Remapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch b/Remapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch new file mode 100644 index 0000000000..0b9b2867e9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 20:32:58 -0400 +Subject: [PATCH] Entity AddTo/RemoveFrom World Events + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 8b0a384caa09848d61b3a6259dd56590cd52d0a0..f7eddb39985072afeb79ec0cbfc084d7e84638e6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1208,7 +1208,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (entity instanceof Mob) { + this.navigations.remove(((Mob) entity).getNavigation()); + } +- ++ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + entity.valid = false; // CraftBukkit + } + +@@ -1246,6 +1246,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + entity.origin = entity.getBukkitEntity().getLocation(); + } + // Paper end ++ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + } + + } diff --git a/Remapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch b/Remapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch new file mode 100644 index 0000000000..126102b49a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 20:46:14 -0400 +Subject: [PATCH] Configurable Chunk Inhabited Time + +Vanilla stores how long a chunk has been active on a server, and dynamically scales some +aspects of vanilla gameplay to this factor. + +For people who want all chunks to be treated equally, you can chose a fixed value. + +This allows to fine-tune vanilla gameplay. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0..74ba5dbb83c13ce1721619b755036a7864a1fb90 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -238,4 +238,14 @@ public class PaperWorldConfig { + skeleHorseSpawnChance = 0.01D; // Vanilla value + } + } ++ ++ public int fixedInhabitedTime; ++ private void fixedInhabitedTime() { ++ if (PaperConfig.version < 16) { ++ if (!config.getBoolean("world-settings.default.use-chunk-inhabited-timer", true)) config.set("world-settings.default.fixed-chunk-inhabited-time", 0); ++ if (!config.getBoolean("world-settings." + worldName + ".use-chunk-inhabited-timer", true)) config.set("world-settings." + worldName + ".fixed-chunk-inhabited-time", 0); ++ set("use-chunk-inhabited-timer", null); ++ } ++ fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 546fb2f42e6bf333582b504d0a29991698505df3..70f5b025c2b803df3de8a51cbcfafbe915866f42 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -1021,7 +1021,7 @@ public class LevelChunk implements ChunkAccess { + + @Override + public long getInhabitedTime() { +- return this.inhabitedTime; ++ return world.paperConfig.fixedInhabitedTime < 0 ? this.inhabitedTime : world.paperConfig.fixedInhabitedTime; // Paper + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch b/Remapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch new file mode 100644 index 0000000000..e784dacc5f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch @@ -0,0 +1,125 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 21:22:26 -0400 +Subject: [PATCH] EntityPathfindEvent + +Fires when an Entity decides to start moving to a location. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java +index 0af2c5dde41043a6fb2fcd07db96288c7f96e0c7..5e7e678c4469e34c7ae39656f547243fbcf1d0da 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java +@@ -37,7 +37,7 @@ public class FlyingPathNavigation extends PathNavigation { + + @Override + public Path createPath(Entity entity, int distance) { +- return this.createPath(entity.blockPosition(), distance); ++ return this.a(entity.blockPosition(), entity, distance); // Paper - Forward target entity + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java +index cd7cb7cbe55a36282de394efc95f4ba7cc6a75cf..01be1de9d9ca0a86d69b2e82693bd0fea61a969f 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java +@@ -75,7 +75,7 @@ public class GroundPathNavigation extends PathNavigation { + + @Override + public Path createPath(Entity entity, int distance) { +- return this.createPath(entity.blockPosition(), distance); ++ return this.a(entity.blockPosition(), entity, distance); // Paper - Forward target entity + } + + private int getSurfaceY() { +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index 3cfd913e31236e35e7225ba19d292cacb8b4134a..ae8d430382b20ddd837c47e39515c7995f25312a 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -10,6 +10,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Position; + import net.minecraft.core.Vec3i; + import net.minecraft.network.protocol.game.DebugPackets; ++import net.minecraft.server.MCUtil; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.Mob; +@@ -28,7 +29,7 @@ import net.minecraft.world.phys.Vec3; + + public abstract class PathNavigation { + +- protected final Mob mob; ++ protected final Mob mob; public Entity getEntity() { return mob; } // Paper - OBFHELPER + protected final Level level; + @Nullable + protected Path path; +@@ -115,36 +116,63 @@ public abstract class PathNavigation { + + @Nullable + public Path createPath(BlockPos target, int distance) { +- return this.createPath(ImmutableSet.of(target), 8, false, distance); ++ // Paper start - add target parameter ++ return this.a(target, null, distance); ++ } ++ @Nullable public Path a(BlockPos blockposition, Entity target, int i) { ++ return this.a(ImmutableSet.of(blockposition), target, 8, false, i); ++ // Paper end + } + + @Nullable + public Path createPath(Entity entity, int distance) { +- return this.createPath(ImmutableSet.of(entity.blockPosition()), 16, true, distance); ++ return this.a(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper + } + + @Nullable ++ // Paper start - Add target + protected Path createPath(Set positions, int range, boolean flag, int distance) { +- if (positions.isEmpty()) { ++ return this.a(positions, null, range, flag, distance); ++ } ++ @Nullable protected Path a(Set set, Entity target, int i, boolean flag, int j) { ++ // Paper end ++ if (set.isEmpty()) { + return null; + } else if (this.mob.getY() < 0.0D) { + return null; + } else if (!this.canUpdatePath()) { + return null; +- } else if (this.path != null && !this.path.isDone() && positions.contains(this.targetPos)) { ++ } else if (this.path != null && !this.path.isDone() && set.contains(this.targetPos)) { + return this.path; + } else { ++ // Paper start - Pathfind event ++ boolean copiedSet = false; ++ for (BlockPos possibleTarget : set) { ++ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), ++ MCUtil.toLocation(getEntity().level, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { ++ if (!copiedSet) { ++ copiedSet = true; ++ set = new java.util.HashSet<>(set); ++ } ++ // note: since we copy the set this remove call is safe, since we're iterating over the old copy ++ set.remove(possibleTarget); ++ if (set.isEmpty()) { ++ return null; ++ } ++ } ++ } ++ // Paper end + this.level.getProfiler().push("pathfind"); + float f = (float) this.mob.getAttributeValue(Attributes.FOLLOW_RANGE); + BlockPos blockposition = flag ? this.mob.blockPosition().above() : this.mob.blockPosition(); +- int k = (int) (f + (float) range); ++ int k = (int) (f + (float) i); + PathNavigationRegion chunkcache = new PathNavigationRegion(this.level, blockposition.offset(-k, -k, -k), blockposition.offset(k, k, k)); +- Path pathentity = this.pathFinder.findPath(chunkcache, this.mob, positions, f, distance, this.maxVisitedNodesMultiplier); ++ Path pathentity = this.pathFinder.findPath(chunkcache, this.mob, set, f, j, this.maxVisitedNodesMultiplier); + + this.level.getProfiler().pop(); + if (pathentity != null && pathentity.getTarget() != null) { + this.targetPos = pathentity.getTarget(); +- this.reachRange = distance; ++ this.reachRange = j; + this.resetStuckTimeout(); + } + diff --git a/Remapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch b/Remapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch new file mode 100644 index 0000000000..95fc3262c8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Antony Riley +Date: Tue, 29 Mar 2016 08:22:55 +0300 +Subject: [PATCH] Sanitise RegionFileCache and make configurable. + +RegionFileCache prior to this patch would close every single open region +file upon reaching a size of 256. +This patch modifies that behaviour so it closes the the least recently +used RegionFile. +The implementation uses a LinkedHashMap as an LRU cache (modified from HashMap). +The maximum size of the RegionFileCache is also made configurable. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 716f285e67019b8a62922d09c15883c99f9421aa..439dcc6effdc91830d2b7ede9063982998b37120 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -227,4 +227,9 @@ public class PaperConfig { + private static void loadPermsBeforePlugins() { + loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); + } ++ ++ public static int regionFileCacheSize = 256; ++ private static void regionFileCacheSize() { ++ regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index 97a58da9d64d812942ceb71426d35b490bbbe817..f33a5fc725d1d5e895f8878d82ebc4172237ad29 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -33,7 +33,7 @@ public final class RegionFileStorage implements AutoCloseable { + if (regionfile != null) { + return regionfile; + } else { +- if (this.regionCache.size() >= 256) { ++ if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable + ((RegionFile) this.regionCache.removeLast()).close(); + } + diff --git a/Remapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch b/Remapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch new file mode 100644 index 0000000000..dcc5c72d1e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 31 Mar 2016 19:17:58 -0400 +Subject: [PATCH] Do not load chunks for Pathfinding + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index ae8d430382b20ddd837c47e39515c7995f25312a..25bc3adfad956157cef0953e6e632b7b7e352f3a 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -48,7 +48,7 @@ public abstract class PathNavigation { + private BlockPos targetPos; + private int reachRange; + private float maxVisitedNodesMultiplier; +- private final PathFinder pathFinder; ++ private final PathFinder pathFinder; public PathFinder getPathfinder() { return this.pathFinder; } // Paper - OBFHELPER + private boolean isStuck; + + public PathNavigation(Mob mob, Level world) { +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +index 99f3f0b895295229b75d93e98141c0cd75789b69..ba8ee93032aabe7ec4ecf52d452e1a580d6ebc20 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +@@ -20,7 +20,7 @@ public class PathFinder { + + private final Node[] neighbors = new Node[32]; + private final int maxVisitedNodes; +- private final NodeEvaluator nodeEvaluator; ++ private final NodeEvaluator nodeEvaluator; public NodeEvaluator getPathfinder() { return this.nodeEvaluator; } // Paper - OBFHELPER + private final BinaryHeap openSet = new BinaryHeap(); + + public PathFinder(NodeEvaluator pathNodeMaker, int range) { +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +index 0b378348cb9e9576e2a209e651264e2caccfd182..7ae24381b91c282745b7fe5f6897865e74bc0acf 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +@@ -479,7 +479,12 @@ public class WalkNodeEvaluator extends NodeEvaluator { + for (int j1 = -1; j1 <= 1; ++j1) { + if (l != 0 || j1 != 0) { + blockposition_mutableblockposition.set(i + l, j + i1, k + j1); +- BlockState iblockdata = iblockaccess.getBlockState(blockposition_mutableblockposition); ++ // Paper start ++ BlockState iblockdata = iblockaccess.getTypeIfLoaded(blockposition_mutableblockposition); ++ if (iblockdata == null) { ++ pathtype = BlockPathTypes.BLOCKED; ++ } else { ++ // Paper end + + if (iblockdata.is(Blocks.CACTUS)) { + return BlockPathTypes.DANGER_CACTUS; +@@ -496,6 +501,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { + if (iblockaccess.getFluidState(blockposition_mutableblockposition).is((Tag) FluidTags.WATER)) { + return BlockPathTypes.WATER_BORDER; + } ++ } // Paper + } + } + } +@@ -505,7 +511,8 @@ public class WalkNodeEvaluator extends NodeEvaluator { + } + + protected static BlockPathTypes getBlockPathTypeRaw(BlockGetter iblockaccess, BlockPos blockposition) { +- BlockState iblockdata = iblockaccess.getBlockState(blockposition); ++ BlockState iblockdata = iblockaccess.getTypeIfLoaded(blockposition); // Paper ++ if (iblockdata == null) return BlockPathTypes.BLOCKED; // Paper + Block block = iblockdata.getBlock(); + Material material = iblockdata.getMaterial(); + diff --git a/Remapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch b/Remapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch new file mode 100644 index 0000000000..c91bb4d9ec --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 2 Apr 2016 05:09:16 -0400 +Subject: [PATCH] Add PlayerUseUnknownEntityEvent + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java +index 9ff5b938f97da5ca1f13fd2bcbf3d13e8b8f760c..e1d219550006d22b0a8e949e820488c6ed96dc58 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java +@@ -11,7 +11,7 @@ import net.minecraft.world.phys.Vec3; + + public class ServerboundInteractPacket implements Packet { + +- private int entityId; ++ private int entityId; public int getEntityId() { return this.entityId; } // Paper - add accessor + private ServerboundInteractPacket.Action action; + private Vec3 location; + private InteractionHand hand; +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 73683ba59d0aff3a61f555b4ae15753e9e4e6141..e2bfe8e916c9e59af81627ea0ee449970527034d 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2198,6 +2198,16 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + } + } ++ // Paper start - fire event ++ else { ++ this.craftServer.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( ++ this.getPlayer(), ++ packet.getEntityId(), ++ packet.getAction() == ServerboundInteractPacket.Action.ATTACK, ++ packet.getHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND ++ )); ++ } ++ // Paper end + + } + diff --git a/Remapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch b/Remapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch new file mode 100644 index 0000000000..d10d109cb2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 2 Apr 2016 20:37:03 -0400 +Subject: [PATCH] Fix reducedDebugInfo not initialized on client + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index a63babe123fad398b07685ec57cd88756435457c..aa440a6341a6d30aba8fd5f6bcd122bd5d8760cd 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -242,6 +242,7 @@ public abstract class PlayerList { + playerconnection.send(new ClientboundSetCarriedItemPacket(player.inventory.selected)); + playerconnection.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); + playerconnection.send(new ClientboundUpdateTagsPacket(this.server.getTags())); ++ playerconnection.send(new ClientboundEntityEventPacket(player, (byte) (worldserver1.getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23))); // Paper - fix this rule not being initialized on the client + this.sendPlayerPermissionLevel(player); + player.getStats().markAllDirty(); + player.getRecipeBook().sendInitialRecipeBook(player); diff --git a/Remapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch b/Remapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch new file mode 100644 index 0000000000..8481cb94a1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 Apr 2016 16:28:17 -0400 +Subject: [PATCH] Configurable Grass Spread Tick Rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 74ba5dbb83c13ce1721619b755036a7864a1fb90..db2dddd12f54e6d15916c4cee623676541de37fb 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -248,4 +248,10 @@ public class PaperWorldConfig { + } + fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); + } ++ ++ public int grassUpdateRate = 1; ++ private void grassUpdateRate() { ++ grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); ++ log("Grass Spread Tick Rate: " + grassUpdateRate); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java +index d54f097afc455a01486d7f7459b0cfc4ab4f3970..813a5b0598eca28aa173cd6e34bc16381f313604 100644 +--- a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java +@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; + import java.util.Random; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.FluidTags; + import net.minecraft.tags.Tag; +@@ -41,6 +42,7 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock { + + @Override + public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) { ++ if (this instanceof GrassBlock && world.paperConfig.grassUpdateRate != 1 && (world.paperConfig.grassUpdateRate < 1 || (MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig.grassUpdateRate != 0)) { return; } // Paper + if (!canBeGrass(state, (LevelReader) world, pos)) { + // CraftBukkit start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { diff --git a/Remapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/Remapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch new file mode 100644 index 0000000000..5d706f6263 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 Apr 2016 17:48:50 -0400 +Subject: [PATCH] Fix Cancelling BlockPlaceEvent triggering physics + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index d47ed15382f98aabd509e32a3c202a91088adf6b..89a6a0b4235cfcc1d3ad68ff59a21fa60df4508f 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -518,6 +518,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public void setBlocksDirty(BlockPos pos, BlockState old, BlockState updated) {} + + public void updateNeighborsAt(BlockPos pos, Block block) { ++ if (captureBlockStates) { return; } // Paper - Cancel all physics during placement + this.neighborChanged(pos.west(), block, pos); + this.neighborChanged(pos.east(), block, pos); + this.neighborChanged(pos.below(), block, pos); diff --git a/Remapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch b/Remapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch new file mode 100644 index 0000000000..7b5057a4e9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Apr 2016 21:38:58 -0400 +Subject: [PATCH] Optimize DataBits + +Remove Debug checks as these are super hot and causing noticeable hits + +Before: http://i.imgur.com/nQsMzAE.png +After: http://i.imgur.com/nJ46crB.png + +Optimize redundant converting of static fields into an unsigned long each call by precomputing it in ctor + +diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java +index 97bde5f8402452e59b0da94edfe1b970cdb86748..dd84984f28484cf7129c294222696784e128221a 100644 +--- a/src/main/java/net/minecraft/util/BitStorage.java ++++ b/src/main/java/net/minecraft/util/BitStorage.java +@@ -13,8 +13,8 @@ public class BitStorage { + private final long mask; + private final int size; + private final int valuesPerLong; +- private final int divideMul; +- private final int divideAdd; ++ private final int divideMul;private final long g_unsigned; // Paper - referenced in b(int) with 2 Integer.toUnsignedLong calls ++ private final int divideAdd;private final long h_unsigned; // Paper + private final int divideShift; + + public BitStorage(int elementBits, int size) { +@@ -29,8 +29,8 @@ public class BitStorage { + this.valuesPerLong = (char) (64 / elementBits); + int k = 3 * (this.valuesPerLong - 1); + +- this.divideMul = BitStorage.MAGIC[k + 0]; +- this.divideAdd = BitStorage.MAGIC[k + 1]; ++ this.divideMul = BitStorage.MAGIC[k + 0]; this.g_unsigned = Integer.toUnsignedLong(this.divideMul); // Paper ++ this.divideAdd = BitStorage.MAGIC[k + 1]; this.h_unsigned = Integer.toUnsignedLong(this.divideAdd); // Paper + this.divideShift = BitStorage.MAGIC[k + 2]; + int l = (size + this.valuesPerLong - 1) / this.valuesPerLong; + +@@ -47,15 +47,15 @@ public class BitStorage { + } + + private int cellIndex(int i) { +- long j = Integer.toUnsignedLong(this.divideMul); +- long k = Integer.toUnsignedLong(this.divideAdd); ++ //long j = Integer.toUnsignedLong(this.g); // Paper ++ //long k = Integer.toUnsignedLong(this.h); // Paper + +- return (int) ((long) i * j + k >> 32 >> this.divideShift); ++ return (int) ((long) i * this.g_unsigned + this.h_unsigned >> 32 >> this.divideShift); // Paper + } + +- public int getAndSet(int index, int value) { +- Validate.inclusiveBetween(0L, (long) (this.size - 1), (long) index); +- Validate.inclusiveBetween(0L, this.mask, (long) value); ++ public final int getAndSet(int index, int value) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper ++ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper + int k = this.cellIndex(index); + long l = this.data[k]; + int i1 = (index - k * this.valuesPerLong) * this.bits; +@@ -65,9 +65,9 @@ public class BitStorage { + return j1; + } + +- public void set(int index, int value) { +- Validate.inclusiveBetween(0L, (long) (this.size - 1), (long) index); +- Validate.inclusiveBetween(0L, this.mask, (long) value); ++ public final void set(int index, int value) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper ++ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper + int k = this.cellIndex(index); + long l = this.data[k]; + int i1 = (index - k * this.valuesPerLong) * this.bits; +@@ -75,8 +75,8 @@ public class BitStorage { + this.data[k] = l & ~(this.mask << i1) | ((long) value & this.mask) << i1; + } + +- public int get(int index) { +- Validate.inclusiveBetween(0L, (long) (this.size - 1), (long) index); ++ public final int get(int index) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper + int j = this.cellIndex(index); + long k = this.data[j]; + int l = (index - j * this.valuesPerLong) * this.bits; diff --git a/Remapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/Remapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch new file mode 100644 index 0000000000..ac90c24b3a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 6 Apr 2016 01:04:23 -0500 +Subject: [PATCH] Option to use vanilla per-world scoreboard coloring on names + +This change is basically a bandaid to fix CB's complete and utter lack +of support for vanilla scoreboard name modifications. + +In the future, finding a way to merge the vanilla expectations in with +bukkit's concept of a display name would be preferable. There was a PR +for this on CB at one point but I can't find it. We may need to do this +ourselves at some point in the future. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index db2dddd12f54e6d15916c4cee623676541de37fb..1942f5224aaebb18adb591d6f70a419cfc1a7bdd 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -254,4 +254,9 @@ public class PaperWorldConfig { + grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); + log("Grass Spread Tick Rate: " + grassUpdateRate); + } ++ ++ public boolean useVanillaScoreboardColoring; ++ private void useVanillaScoreboardColoring() { ++ useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); ++ } + } +diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +index a29b6aaafd529e56a83dd96c32211f21e4aad348..2039f83a718427d0969a1a2e2200f7922097449e 100644 +--- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java ++++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +@@ -16,7 +16,11 @@ import net.kyori.adventure.text.TextReplacementConfig; + import net.kyori.adventure.text.event.ClickEvent; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.scores.PlayerTeam; ++import net.minecraft.world.scores.Team; + import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; ++import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.entity.CraftPlayer; + import org.bukkit.craftbukkit.util.LazyPlayerSet; + import org.bukkit.craftbukkit.util.Waitable; +@@ -178,10 +182,22 @@ public final class ChatProcessor { + } + + private static String legacyDisplayName(final CraftPlayer player) { ++ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { ++ final ServerPlayer ep = player.getHandle(); ++ net.minecraft.network.chat.Component name = ep.getName(); ++ final Team team = ep.getTeam(); ++ if (team != null) { ++ name = team.getFormattedName(name); ++ } ++ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(PaperAdventure.asAdventure(name)) + ChatColor.RESET; ++ } + return player.getDisplayName(); + } + + private static Component displayName(final CraftPlayer player) { ++ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { ++ return PaperAdventure.asAdventure(PlayerTeam.formatNameForTeam(player.getHandle().getTeam(), player.getHandle().getName())); ++ } + return player.displayName(); + } + diff --git a/Remapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch b/Remapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch new file mode 100644 index 0000000000..c2fdc7667a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 10 Apr 2016 03:23:32 -0500 +Subject: [PATCH] Workaround for setting passengers on players + +SPIGOT-1915 & GH-114 + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index b7d5a718375083a4162df4bb41de3acd57b297fb..b264cbe5f91da9e31c5fd00ee285735a19aaad35 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -870,6 +870,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return true; + } + ++ // Paper start - Ugly workaround for SPIGOT-1915 & GH-114 ++ @Override ++ public boolean setPassenger(org.bukkit.entity.Entity passenger) { ++ boolean wasSet = super.setPassenger(passenger); ++ if (wasSet) { ++ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSetPassengersPacket(this.getHandle())); ++ } ++ return wasSet; ++ } ++ // Paper end ++ + @Override + public void setSneaking(boolean sneak) { + getHandle().setShiftKeyDown(sneak); diff --git a/Remapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch b/Remapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch new file mode 100644 index 0000000000..d96a9f686a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 13 Apr 2016 00:25:28 -0400 +Subject: [PATCH] Remove unused World Tile Entity List + +Massive hit to performance and it is completely unnecessary. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index f7eddb39985072afeb79ec0cbfc084d7e84638e6..bb99d9fe5e274318d8480a6de2c45b0a57351f77 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1715,7 +1715,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + bufferedwriter.write(String.format("entities: %d\n", this.entitiesById.size())); +- bufferedwriter.write(String.format("block_entities: %d\n", this.blockEntityList.size())); ++ bufferedwriter.write(String.format("block_entities: %d\n", this.tickableBlockEntities.size())); // Paper - remove unused list + bufferedwriter.write(String.format("block_ticks: %d\n", this.getBlockTicks().size())); + bufferedwriter.write(String.format("fluid_ticks: %d\n", this.getLiquidTicks().size())); + bufferedwriter.write("distance_manager: " + playerchunkmap.getDistanceManager().getDebugStatus() + "\n"); +@@ -1854,7 +1854,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + private void dumpBlockEntities(Writer writer) throws IOException { + CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("type").build(writer); +- Iterator iterator = this.blockEntityList.iterator(); ++ Iterator iterator = this.tickableBlockEntities.iterator(); // Paper - remove unused list + + while (iterator.hasNext()) { + BlockEntity tileentity = (BlockEntity) iterator.next(); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 89a6a0b4235cfcc1d3ad68ff59a21fa60df4508f..8f0fec38b482465285057d3fd27d456cf036f2fd 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -91,7 +91,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public static final ResourceKey NETHER = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation("the_nether")); + public static final ResourceKey END = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation("the_end")); + private static final Direction[] DIRECTIONS = Direction.values(); +- public final List blockEntityList = Lists.newArrayList(); ++ //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list + public final List tickableBlockEntities = Lists.newArrayList(); + protected final List pendingBlockEntities = Lists.newArrayList(); + protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); +@@ -683,9 +683,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + }, blockEntity::getBlockPos}); + } + +- boolean flag = this.blockEntityList.add(blockEntity); ++ boolean flag = true; // Paper - remove unused list + +- if (flag && blockEntity instanceof TickableBlockEntity) { ++ if (flag && blockEntity instanceof TickableBlockEntity && !this.tickableBlockEntities.contains(blockEntity)) { // Paper + this.tickableBlockEntities.add(blockEntity); + } + +@@ -721,7 +721,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + timings.tileEntityTick.startTiming(); // Spigot + if (!this.tileEntityListUnload.isEmpty()) { + this.tickableBlockEntities.removeAll(this.tileEntityListUnload); +- this.blockEntityList.removeAll(this.tileEntityListUnload); ++ //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list + this.tileEntityListUnload.clear(); + } + +@@ -781,7 +781,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + tilesThisCycle--; + this.tickableBlockEntities.remove(tileTickPosition--); + // Spigot end +- this.blockEntityList.remove(tileentity); ++ //this.tileEntityList.remove(tileentity); // Paper - remove unused list + if (this.hasChunkAt(tileentity.getBlockPos())) { + this.getChunkAt(tileentity.getBlockPos()).removeBlockEntity(tileentity.getBlockPos()); + } +@@ -811,7 +811,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.sendBlockUpdated(tileentity1.getBlockPos(), iblockdata, iblockdata, 3); + // CraftBukkit start + // From above, don't screw this up - SPIGOT-1746 +- if (!this.blockEntityList.contains(tileentity1)) { ++ if (true) { // Paper - remove unused list + this.addBlockEntity(tileentity1); + } + // CraftBukkit end +@@ -957,7 +957,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } else { + if (tileentity != null) { + this.pendingBlockEntities.remove(tileentity); +- this.blockEntityList.remove(tileentity); ++ //this.tileEntityList.remove(tileentity); // Paper - remove unused list + this.tickableBlockEntities.remove(tileentity); + } + diff --git a/Remapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch b/Remapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch new file mode 100644 index 0000000000..42e534b702 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 13 Apr 2016 00:30:10 -0400 +Subject: [PATCH] Don't tick Skulls - unused code + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java +index 6a46517e4026971d8c050c685c710883b5976fa3..eebaeaccc3ba1a9ec089d84b8de6c9d36034868f 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java +@@ -31,7 +31,7 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.server.players.GameProfileCache; + import net.minecraft.util.StringUtil; + +-public class SkullBlockEntity extends BlockEntity implements TickableBlockEntity { ++public class SkullBlockEntity extends BlockEntity /*implements ITickable*/ { // Paper - remove tickable + + @Nullable + private static GameProfileCache profileCache; +@@ -134,7 +134,7 @@ public class SkullBlockEntity extends BlockEntity implements TickableBlockEntity + + } + +- @Override ++ // Paper - remove override + public void tick() { + BlockState iblockdata = this.getBlockState(); + diff --git a/Remapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch b/Remapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch new file mode 100644 index 0000000000..3ed6659147 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch @@ -0,0 +1,131 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 13 Apr 2016 02:10:49 -0400 +Subject: [PATCH] Configurable Player Collision + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 439dcc6effdc91830d2b7ede9063982998b37120..504efea7b6f50a0d17f4f353781953dfb18bdeca 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -232,4 +232,9 @@ public class PaperConfig { + private static void regionFileCacheSize() { + regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); + } ++ ++ public static boolean enablePlayerCollisions = true; ++ private static void enablePlayerCollisions() { ++ enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); ++ } + } +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java +index 53f284b720d97ba8ce8fac90bc26e7930dcec6b2..d70e7079ea2c84edbc2a8501f115194e2a4ef2e4 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java +@@ -112,7 +112,7 @@ public class ClientboundSetPlayerTeamPacket implements Packet toRemove = scoreboard.getTeams().stream().filter(team -> team.getName().startsWith("collideRule_")).map(PlayerTeam::getName).collect(java.util.stream.Collectors.toList()); ++ for (String teamName : toRemove) { ++ scoreboard.removeTeam(scoreboard.getTeam(teamName)); // Clean up after ourselves ++ } ++ ++ if (!com.destroystokyo.paper.PaperConfig.enablePlayerCollisions) { ++ this.getPlayerList().collideRuleTeamName = org.apache.commons.lang3.StringUtils.left("collideRule_" + java.util.concurrent.ThreadLocalRandom.current().nextInt(), 16); ++ PlayerTeam collideTeam = scoreboard.createTeam(this.getPlayerList().collideRuleTeamName); ++ collideTeam.setSeeFriendlyInvisibles(false); // Because we want to mimic them not being on a team at all ++ } ++ // Paper end ++ + this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); + this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); + this.connection.acceptConnections(); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index aa440a6341a6d30aba8fd5f6bcd122bd5d8760cd..59fb19cfebe4f488fd02f02db31029d44b65e408 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -79,6 +79,7 @@ import net.minecraft.world.level.storage.PlayerDataStorage; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.Objective; + import net.minecraft.world.scores.PlayerTeam; ++import net.minecraft.world.scores.Scoreboard; + import net.minecraft.world.scores.Team; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -141,6 +142,7 @@ public abstract class PlayerList { + // CraftBukkit start + private CraftServer cserver; + private final Map playersByName = new java.util.HashMap<>(); ++ public @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule + + public PlayerList(MinecraftServer server, RegistryAccess.RegistryHolder registryManager, PlayerDataStorage saveHandler, int maxPlayers) { + this.cserver = server.server = new CraftServer((DedicatedServer) server, this); +@@ -372,6 +374,13 @@ public abstract class PlayerList { + } + + player.initMenu(); ++ // Paper start - Add to collideRule team if needed ++ final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); ++ final PlayerTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName); ++ if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) { ++ scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); ++ } ++ // Paper end + // CraftBukkit - Moved from above, added world + PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.worldDataServer.getLevelName(), player.getX(), player.getY(), player.getZ()); + } +@@ -492,6 +501,16 @@ public abstract class PlayerList { + entityplayer.doTick(); // SPIGOT-924 + // CraftBukkit end + ++ // Paper start - Remove from collideRule team if needed ++ if (this.collideRuleTeamName != null) { ++ final Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard(); ++ final PlayerTeam team = scoreBoard.getTeam(this.collideRuleTeamName); ++ if (entityplayer.getTeam() == team && team != null) { ++ scoreBoard.removePlayerFromTeam(entityplayer.getScoreboardName(), team); ++ } ++ } ++ // Paper end ++ + this.save(entityplayer); + if (entityplayer.isPassenger()) { + Entity entity = entityplayer.getRootVehicle(); +@@ -1140,6 +1159,13 @@ public abstract class PlayerList { + } + // CraftBukkit end + ++ // Paper start - Remove collideRule team if it exists ++ if (this.collideRuleTeamName != null) { ++ final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); ++ final PlayerTeam team = scoreboard.getTeam(this.collideRuleTeamName); ++ if (team != null) scoreboard.removeTeam(team); ++ } ++ // Paper end + } + + // CraftBukkit start diff --git a/Remapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Remapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch new file mode 100644 index 0000000000..56a3be043d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 13 Apr 2016 20:21:38 -0700 +Subject: [PATCH] Add handshake event to allow plugins to handle client + handshaking logic themselves + + +diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 55b6412bb978abb6f8eaff83a7dd40fbc1ed8b9a..e56ab94ce65e81bb0383a1626a1790c43bd6920e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -29,7 +29,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + // CraftBukkit end + private static final Component IGNORE_STATUS_REASON = new TextComponent("Ignoring status request"); + private final MinecraftServer server; +- private final Connection connection; ++ private final Connection connection; final Connection getNetworkManager() { return this.connection; } // Paper - OBFHELPER + + public ServerHandshakePacketListenerImpl(MinecraftServer server, Connection connection) { + this.server = server; +@@ -88,8 +88,35 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + this.connection.disconnect(chatmessage); + } else { + this.connection.setListener(new ServerLoginPacketListenerImpl(this.server, this.connection)); ++ // Paper start - handshake event ++ boolean proxyLogicEnabled = org.spigotmc.SpigotConfig.bungee; ++ boolean handledByEvent = false; ++ // Try and handle the handshake through the event ++ if (com.destroystokyo.paper.event.player.PlayerHandshakeEvent.getHandlerList().getRegisteredListeners().length != 0) { // Hello? Can you hear me? ++ java.net.SocketAddress socketAddress = this.getNetworkManager().address; ++ String hostnameOfRemote = socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getHostString() : InetAddress.getLoopbackAddress().getHostAddress(); ++ com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packet.hostName, hostnameOfRemote, !proxyLogicEnabled); ++ if (event.callEvent()) { ++ // If we've failed somehow, let the client know so and go no further. ++ if (event.isFailed()) { ++ chatmessage = new TranslatableComponent(event.getFailMessage()); ++ this.getNetworkManager().send(new ClientboundLoginDisconnectPacket(chatmessage)); ++ this.getNetworkManager().disconnect(chatmessage); ++ return; ++ } ++ ++ if (event.getServerHostname() != null) packet.hostName = event.getServerHostname(); ++ if (event.getSocketAddressHostname() != null) this.getNetworkManager().address = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); ++ this.getNetworkManager().spoofedUUID = event.getUniqueId(); ++ this.getNetworkManager().spoofedProfile = gson.fromJson(event.getPropertiesJson(), com.mojang.authlib.properties.Property[].class); ++ handledByEvent = true; // Hooray, we did it! ++ } ++ } ++ // Don't try and handle default logic if it's been handled by the event. ++ if (!handledByEvent && proxyLogicEnabled) { ++ // Paper end + // Spigot Start +- if (org.spigotmc.SpigotConfig.bungee) { ++ //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! + String[] split = packet.hostName.split("\00"); + if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { + packet.hostName = split[0]; diff --git a/Remapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch b/Remapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch new file mode 100644 index 0000000000..4bc15f3f2f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 16 Apr 2016 00:39:33 -0400 +Subject: [PATCH] Configurable RCON IP address + +For servers with multiple IP's, ability to bind to a specific interface. + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +index d10f2e5a13a9e86c32ef5dd8c6732ad8b51ed6a0..545096d9ba403396b6aaa7bb6d912f2de08a967e 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +@@ -64,6 +64,8 @@ public class DedicatedServerProperties extends Settings.MutableValue whiteList; + public final WorldGenSettings worldGenSettings; + ++ public final String rconIp; // Paper - Add rcon ip ++ + // CraftBukkit start + public DedicatedServerProperties(Properties properties, RegistryAccess iregistrycustom, OptionSet optionset) { + super(properties, optionset); +@@ -115,6 +117,10 @@ public class DedicatedServerProperties extends Settings> { + }; + } + +- @Nullable +- private String getStringRaw(String key) { ++ @Nullable String getSettingIfExists(final String path) { return this.getStringRaw(path); } // Paper - OBFHELPER ++ @Nullable private String getStringRaw(String key) { // Paper - OBFHELPER + return (String) getOverride(key, this.properties.getProperty(key)); // CraftBukkit + } + +diff --git a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java b/src/main/java/net/minecraft/server/rcon/thread/RconThread.java +index f2a94e9d9b57ece16873972bc5292f7cf3928848..ef9f659ae5f53a8effa807ecb955ef47d53aacd2 100644 +--- a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java ++++ b/src/main/java/net/minecraft/server/rcon/thread/RconThread.java +@@ -62,7 +62,7 @@ public class RconThread extends GenericThread { + @Nullable + public static RconThread create(ServerInterface server) { + DedicatedServerProperties dedicatedserverproperties = server.getProperties(); +- String s = server.getServerIp(); ++ String s = dedicatedserverproperties.rconIp; // Paper - Configurable rcon ip + + if (s.isEmpty()) { + s = "0.0.0.0"; diff --git a/Remapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch b/Remapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch new file mode 100644 index 0000000000..04b43eed1b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 17 Apr 2016 17:27:09 -0400 +Subject: [PATCH] Prevent Fire from loading chunks & wrongly spread + +This causes the nether to spam unload/reload chunks, plus overall +bad behavior. + +This also stops fire from spreading to illegal locations. + +diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java +index 700078c2fd536cc22351eadf51503efb9acd9df9..85170008de6e77cfb8e4f55ae440a8428d868af4 100644 +--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java +@@ -134,7 +134,7 @@ public class FireBlock extends BaseFireBlock { + BooleanProperty blockstateboolean = (BooleanProperty) FireBlock.PROPERTY_BY_DIRECTION.get(enumdirection); + + if (blockstateboolean != null) { +- iblockdata1 = (BlockState) iblockdata1.setValue(blockstateboolean, this.canBurn(world.getBlockState(pos.relative(enumdirection)))); ++ iblockdata1 = (BlockState) iblockdata1.setValue(blockstateboolean, this.canBurn(world.getTypeIfLoaded(pos.relative(enumdirection)))); // Paper - prevent chunk loads + } + } + +@@ -214,6 +214,7 @@ public class FireBlock extends BaseFireBlock { + } + + blockposition_mutableblockposition.setWithOffset((Vec3i) pos, l, j1, i1); ++ if (blockposition_mutableblockposition.isInvalidYLocation() || !world.hasChunkAt(blockposition_mutableblockposition)) continue; // Paper + int l1 = this.getFireOdds((LevelReader) world, (BlockPos) blockposition_mutableblockposition); + + if (l1 > 0) { +@@ -259,10 +260,16 @@ public class FireBlock extends BaseFireBlock { + } + + private void trySpread(Level world, BlockPos blockposition, int i, Random random, int j, BlockPos sourceposition) { // CraftBukkit add sourceposition +- int k = this.getBurnOdd(world.getBlockState(blockposition)); ++ // Paper start ++ final BlockState iblockdata = world.getTypeIfLoaded(blockposition); ++ if (iblockdata == null) { ++ return; ++ } ++ int k = this.getBurnOdd(iblockdata); ++ // Paper end + + if (random.nextInt(i) < k) { +- BlockState iblockdata = world.getBlockState(blockposition); ++ //IBlockData iblockdata = world.getType(blockposition); // Paper + + // CraftBukkit start + org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); +@@ -308,7 +315,7 @@ public class FireBlock extends BaseFireBlock { + for (int j = 0; j < i; ++j) { + Direction enumdirection = aenumdirection[j]; + +- if (this.canBurn(world.getBlockState(pos.relative(enumdirection)))) { ++ if (this.canBurn(world.getTypeIfLoaded(pos.relative(enumdirection)))) { // Paper - prevent chunk loads + return true; + } + } +@@ -326,7 +333,12 @@ public class FireBlock extends BaseFireBlock { + + for (int k = 0; k < j; ++k) { + Direction enumdirection = aenumdirection[k]; +- BlockState iblockdata = iworldreader.getBlockState(pos.relative(enumdirection)); ++ // Paper start ++ BlockState iblockdata = iworldreader.getTypeIfLoaded(pos.relative(enumdirection)); ++ if (iblockdata == null) { ++ continue; ++ } ++ // Paper end + + i = Math.max(this.getFlameOdds(iblockdata), i); + } +@@ -337,7 +349,7 @@ public class FireBlock extends BaseFireBlock { + + @Override + protected boolean canBurn(BlockState state) { +- return this.getFlameOdds(state) > 0; ++ return state != null && this.getFlameOdds(state) > 0; // Paper - iblockdata can be nullable if chunk is unloaded now + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch b/Remapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch new file mode 100644 index 0000000000..c52d99a313 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Isaac Moore +Date: Tue, 19 Apr 2016 14:09:31 -0500 +Subject: [PATCH] Implement PlayerLocaleChangeEvent + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index ffad931c72e52855a3f139354f5e85c460e2a80b..bd3d9182dfb2c0ae1d8c3b9aa360f94c33252592 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1692,7 +1692,7 @@ public class ServerPlayer extends Player implements ContainerListener { + return s; + } + +- public String locale = "en_us"; // CraftBukkit - add, lowercase ++ public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null + public java.util.Locale adventure$locale = java.util.Locale.US; // Paper + public void updateOptions(ServerboundClientInformationPacket packet) { + // CraftBukkit start +@@ -1700,9 +1700,10 @@ public class ServerPlayer extends Player implements ContainerListener { + PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); + this.server.server.getPluginManager().callEvent(event); + } +- if (!this.locale.equals(packet.language)) { ++ if (this.locale == null || !this.locale.equals(packet.language)) { // Paper - check for null + PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), packet.language); + this.server.server.getPluginManager().callEvent(event); ++ new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.locale, packet.language).callEvent(); // Paper + } + this.locale = packet.language; + // Paper start +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index b264cbe5f91da9e31c5fd00ee285735a19aaad35..fc19b4cacd223b928fbdf922b828beaed630bf2e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1875,8 +1875,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + @Override + public String getLocale() { +- return getHandle().locale; +- ++ // Paper start - Locale change event ++ final String locale = getHandle().locale; ++ return locale != null ? locale : "en_us"; ++ // Paper end + } + + // Paper start diff --git a/Remapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch b/Remapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch new file mode 100644 index 0000000000..386b74cf50 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 22 Apr 2016 01:43:11 -0500 +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 a326e5b4ac055f2f8a95c6eaccd8d0a97762da1f..1131d86080b3100437aa18a00c6277fcea4b7ea8 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1127,10 +1127,16 @@ public abstract class LivingEntity extends Entity { + } + + public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { ++ // Paper start - Forward ++ heal(f, regainReason, false); ++ } ++ ++ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason, boolean isFastRegen) { ++ // Paper end + float f1 = this.getHealth(); + + if (f1 > 0.0F) { +- EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason, isFastRegen); // Paper + // Suppress during worldgen + if (this.valid) { + this.level.getCraftServer().getPluginManager().callEvent(event); +diff --git a/src/main/java/net/minecraft/world/food/FoodData.java b/src/main/java/net/minecraft/world/food/FoodData.java +index 269392592f5271b1bb8c37661fbe685e76e32b74..d18b7d2c22312fc6ec3977ce38a1f04e0b5c8ad4 100644 +--- a/src/main/java/net/minecraft/world/food/FoodData.java ++++ b/src/main/java/net/minecraft/world/food/FoodData.java +@@ -84,7 +84,7 @@ public class FoodData { + if (this.tickTimer >= this.saturatedRegenRate) { // CraftBukkit + float f = Math.min(this.saturationLevel, 6.0F); + +- player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED, true); // CraftBukkit - added RegainReason // Paper - This is fast regen + // this.a(f); CraftBukkit - EntityExhaustionEvent + player.applyExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; diff --git a/Remapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch b/Remapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch new file mode 100644 index 0000000000..e5bee625dc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Thu, 21 Apr 2016 23:51:55 -0700 +Subject: [PATCH] Add ability to configure frosted_ice properties + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1942f5224aaebb18adb591d6f70a419cfc1a7bdd..5baccb8d50c135ab20c38ffd0690f585514ce5af 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -259,4 +259,14 @@ public class PaperWorldConfig { + private void useVanillaScoreboardColoring() { + useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); + } ++ ++ public boolean frostedIceEnabled = true; ++ public int frostedIceDelayMin = 20; ++ public int frostedIceDelayMax = 40; ++ private void frostedIce() { ++ this.frostedIceEnabled = this.getBoolean("frosted-ice.enabled", this.frostedIceEnabled); ++ this.frostedIceDelayMin = this.getInt("frosted-ice.delay.min", this.frostedIceDelayMin); ++ this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); ++ log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +index 0727cc36c99cb5ca5019c71f4540de76b78c7a80..ae2f5acd008d5d7163b56cb4a2d29354299959ca 100644 +--- a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +@@ -30,6 +30,7 @@ public class FrostedIceBlock extends IceBlock { + + @Override + public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) { ++ if (!world.paperConfig.frostedIceEnabled) return; // Paper - add ability to disable frosted ice + if ((random.nextInt(3) == 0 || this.fewerNeigboursThan(world, pos, 4)) && world.getMaxLocalRawBrightness(pos) > 11 - (Integer) state.getValue(FrostedIceBlock.AGE) - state.getLightBlock((BlockGetter) world, pos) && this.slightlyMelt(state, (Level) world, pos)) { + BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + Direction[] aenumdirection = Direction.values(); +@@ -42,12 +43,12 @@ public class FrostedIceBlock extends IceBlock { + BlockState iblockdata1 = world.getBlockState(blockposition_mutableblockposition); + + if (iblockdata1.is((Block) this) && !this.slightlyMelt(iblockdata1, (Level) world, blockposition_mutableblockposition)) { +- world.getBlockTicks().scheduleTick(blockposition_mutableblockposition, this, Mth.nextInt(random, 20, 40)); ++ world.getBlockTicks().scheduleTick(blockposition_mutableblockposition, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay + } + } + + } else { +- world.getBlockTicks().scheduleTick(pos, this, Mth.nextInt(random, 20, 40)); ++ world.getBlockTicks().scheduleTick(pos, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay + } + } + diff --git a/Remapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch b/Remapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch new file mode 100644 index 0000000000..2a17e8f4af --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 28 Apr 2016 00:57:27 -0400 +Subject: [PATCH] remove null possibility for getServer singleton + +to stop IDE complaining about potential NPE + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index d639ead95c36985fa0f5a9c51898c4237e373f0e..4e468cb7ccf683b8fc9e04a48cfc25779775e25f 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -178,6 +178,7 @@ import org.spigotmc.SlackActivityAccountant; // Spigot + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { + ++ private static MinecraftServer SERVER; // Paper + public static final Logger LOGGER = LogManager.getLogger(); + public static final File USERID_CACHE_FILE = new File("usercache.json"); + public static final LevelSettings DEMO_SETTINGS = new LevelSettings("Demo World", GameType.SURVIVAL, false, Difficulty.NORMAL, false, new GameRules(), DataPackConfig.DEFAULT); +@@ -284,6 +285,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Fri, 29 Apr 2016 20:02:00 -0400 +Subject: [PATCH] Improve Maps (in item frames) performance and bug fixes + +Maps used a modified version of rendering to support plugin controlled +imaging on maps. The Craft Map Renderer is much slower than Vanilla, +causing maps in item frames to cause a noticeable hit on server performance. + +This updates the map system to not use the Craft system if we detect that no +custom renderers are in use, defaulting to the much simpler Vanilla system. + +Additionally, numerous issues to player position tracking on maps has been fixed. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index bb99d9fe5e274318d8480a6de2c45b0a57351f77..0a613f94d1c796267636e1a343aeee65a49ffed5 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1164,6 +1164,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + { + if ( iter.next().player == entity ) + { ++ map.decorations.remove(entity.getName().getString()); // Paper + iter.remove(); + } + } +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 3b451e75a7f49ea6b543aee9f0a51c0be3c4dfba..c11d5aa115d10e3c12863cf9d42c60194d63b690 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -85,6 +85,7 @@ import net.minecraft.world.item.ElytraItem; + import net.minecraft.world.item.ItemCooldowns; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; ++import net.minecraft.world.item.MapItem; + import net.minecraft.world.item.ProjectileWeaponItem; + import net.minecraft.world.item.SwordItem; + import net.minecraft.world.item.crafting.Recipe; +@@ -104,6 +105,7 @@ import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.entity.StructureBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.block.state.pattern.BlockInWorld; ++import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.PlayerTeam; +@@ -686,6 +688,12 @@ public abstract class Player extends LivingEntity { + return null; + } + // CraftBukkit end ++ // Paper start - remove player from map on drop ++ if (stack.getItem() == Items.FILLED_MAP) { ++ MapItemSavedData worldmap = MapItem.getOrCreateSavedData(stack, this.level); ++ worldmap.updateSeenPlayers(this, stack); ++ } ++ // Paper end + + return entityitem; + } +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +index d44505b3ee2a35422568e9bce0d868191e348fc0..7582c7cd4235d212a0cf66a4c59ce0cedaa360ad 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -57,6 +57,7 @@ public class MapItemSavedData extends SavedData { + private final Map bannerMarkers = Maps.newHashMap(); + public final Map decorations = Maps.newLinkedHashMap(); + private final Map frameMarkers = Maps.newHashMap(); ++ private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper + + // CraftBukkit start + public final CraftMapView mapView; +@@ -69,6 +70,7 @@ public class MapItemSavedData extends SavedData { + // CraftBukkit start + mapView = new CraftMapView(this); + server = (CraftServer) org.bukkit.Bukkit.getServer(); ++ vanillaRender.buffer = colors; // Paper + // CraftBukkit end + } + +@@ -136,6 +138,7 @@ public class MapItemSavedData extends SavedData { + this.bannerMarkers.put(mapiconbanner.getId(), mapiconbanner); + this.addDecoration(mapiconbanner.getDecoration(), (LevelAccessor) null, mapiconbanner.getId(), (double) mapiconbanner.getPos().getX(), (double) mapiconbanner.getPos().getZ(), 180.0D, mapiconbanner.getName()); + } ++ this.vanillaRender.buffer = colors; // Paper + + ListTag nbttaglist1 = tag.getList("frames", 10); + +@@ -216,6 +219,7 @@ public class MapItemSavedData extends SavedData { + this.setDirty(); + } + ++ public void updateSeenPlayers(Player entityhuman, ItemStack itemstack) { this.tickCarriedBy(entityhuman, itemstack); } // Paper - OBFHELPER + public void tickCarriedBy(Player player, ItemStack stack) { + if (!this.carriedByPlayers.containsKey(player)) { + MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = new MapItemSavedData.HoldingPlayer(player); +@@ -451,6 +455,21 @@ public class MapItemSavedData extends SavedData { + + public class HoldingPlayer { + ++ // Paper start ++ private void addSeenPlayers(java.util.Collection icons) { ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) player.getBukkitEntity(); ++ MapItemSavedData.this.decorations.forEach((name, mapIcon) -> { ++ // If this cursor is for a player check visibility with vanish system ++ org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayerExact(name); // Spigot ++ if (other == null || player.canSee(other)) { ++ icons.add(mapIcon); ++ } ++ }); ++ } ++ private boolean shouldUseVanillaMap() { ++ return mapView.getRenderers().size() == 1 && mapView.getRenderers().get(0).getClass() == org.bukkit.craftbukkit.map.CraftMapRenderer.class; ++ } ++ // Paper end + public final Player player; + private boolean dirtyData = true; + private int minDirtyX; +@@ -467,9 +486,12 @@ public class MapItemSavedData extends SavedData { + @Nullable + public Packet nextUpdatePacket(ItemStack stack) { + // CraftBukkit start +- org.bukkit.craftbukkit.map.RenderData render = MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit ++ if (!this.dirtyData && this.tick % 5 != 0) { this.tick++; return null; } // Paper - this won't end up sending, so don't render it! ++ boolean vanillaMaps = shouldUseVanillaMap(); // Paper ++ org.bukkit.craftbukkit.map.RenderData render = !vanillaMaps ? MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()) : MapItemSavedData.this.vanillaRender; // CraftBukkit // Paper + + java.util.Collection icons = new java.util.ArrayList(); ++ if (vanillaMaps) addSeenPlayers(icons); // Paper + + for ( org.bukkit.map.MapCursor cursor : render.cursors) { + +diff --git a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java +index 256a131781721c86dd6cdbc329335964570cbe8c..5768cd512ec166f1e8d1f4a28792015347297c3f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java ++++ b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java +@@ -5,7 +5,7 @@ import org.bukkit.map.MapCursor; + + public class RenderData { + +- public final byte[] buffer; ++ public byte[] buffer; // Paper + public final ArrayList cursors; + + public RenderData() { diff --git a/Remapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch b/Remapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch new file mode 100644 index 0000000000..4e9c15788b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch @@ -0,0 +1,739 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 1 May 2016 21:19:14 -0400 +Subject: [PATCH] LootTable API & Replenishable Lootables Feature + +Provides an API to control the loot table for an object. +Also provides a feature that any Lootable Inventory (Chests in Structures) +can automatically replenish after a given time. + +This feature is good for long term worlds so that newer players +do not suffer with "Every chest has been looted" + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5baccb8d50c135ab20c38ffd0690f585514ce5af..eb04fdb172a50ec1f5b7fe78fa0e7655246abd60 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -269,4 +269,26 @@ public class PaperWorldConfig { + this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); + log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); + } ++ ++ public boolean autoReplenishLootables; ++ public boolean restrictPlayerReloot; ++ public boolean changeLootTableSeedOnFill; ++ public int maxLootableRefills; ++ public int lootableRegenMin; ++ public int lootableRegenMax; ++ private void enhancedLootables() { ++ autoReplenishLootables = getBoolean("lootables.auto-replenish", false); ++ restrictPlayerReloot = getBoolean("lootables.restrict-player-reloot", true); ++ changeLootTableSeedOnFill = getBoolean("lootables.reset-seed-on-fill", true); ++ maxLootableRefills = getInt("lootables.max-refills", -1); ++ lootableRegenMin = PaperConfig.getSeconds(getString("lootables.refresh-min", "12h")); ++ lootableRegenMax = PaperConfig.getSeconds(getString("lootables.refresh-max", "2d")); ++ if (autoReplenishLootables) { ++ log("Lootables: Replenishing every " + ++ PaperConfig.timeSummary(lootableRegenMin) + " to " + ++ PaperConfig.timeSummary(lootableRegenMax) + ++ (restrictPlayerReloot ? " (restricting reloot)" : "") ++ ); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fda64b8860cb696e209eedcfb200e7193d216732 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java +@@ -0,0 +1,34 @@ ++package com.destroystokyo.paper.loottable; ++ ++import LootableInventory; ++import net.minecraft.core.BlockPos; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; ++import org.bukkit.Chunk; ++import org.bukkit.block.Block; ++ ++public interface PaperLootableBlockInventory extends LootableBlockInventory, PaperLootableInventory { ++ ++ RandomizableContainerBlockEntity getTileEntity(); ++ ++ @Override ++ default LootableInventory getAPILootableInventory() { ++ return this; ++ } ++ ++ @Override ++ default Level getNMSWorld() { ++ return getTileEntity().getLevel(); ++ } ++ ++ default Block getBlock() { ++ final BlockPos position = getTileEntity().getBlockPos(); ++ final Chunk bukkitChunk = getTileEntity().getLevel().getChunkAt(position).bukkitChunk; ++ return bukkitChunk.getBlock(position.getX(), position.getY(), position.getZ()); ++ } ++ ++ @Override ++ default PaperLootableInventoryData getLootableData() { ++ return getTileEntity().lootableData; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..292d5ef8a1c428893af729b298eecd32b4c4659a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java +@@ -0,0 +1,29 @@ ++package com.destroystokyo.paper.loottable; ++ ++import LootableInventory; ++import net.minecraft.world.level.Level; ++import org.bukkit.entity.Entity; ++ ++public interface PaperLootableEntityInventory extends LootableEntityInventory, PaperLootableInventory { ++ ++ net.minecraft.world.entity.Entity getHandle(); ++ ++ @Override ++ default LootableInventory getAPILootableInventory() { ++ return this; ++ } ++ ++ default Entity getEntity() { ++ return getHandle().getBukkitEntity(); ++ } ++ ++ @Override ++ default Level getNMSWorld() { ++ return getHandle().getCommandSenderWorld(); ++ } ++ ++ @Override ++ default PaperLootableInventoryData getLootableData() { ++ return getHandle().lootableData; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b3def19a50081cfa758b6e25707b2fc6fed8d3ca +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java +@@ -0,0 +1,71 @@ ++package com.destroystokyo.paper.loottable; ++ ++import org.bukkit.loot.Lootable; ++import LootableInventory; ++import java.util.UUID; ++import net.minecraft.world.level.Level; ++ ++public interface PaperLootableInventory extends LootableInventory, Lootable { ++ ++ PaperLootableInventoryData getLootableData(); ++ LootableInventory getAPILootableInventory(); ++ ++ Level getNMSWorld(); ++ ++ default org.bukkit.World getBukkitWorld() { ++ return getNMSWorld().getWorld(); ++ } ++ ++ @Override ++ default boolean isRefillEnabled() { ++ return getNMSWorld().paperConfig.autoReplenishLootables; ++ } ++ ++ @Override ++ default boolean hasBeenFilled() { ++ return getLastFilled() != -1; ++ } ++ ++ @Override ++ default boolean hasPlayerLooted(UUID player) { ++ return getLootableData().hasPlayerLooted(player); ++ } ++ ++ @Override ++ default Long getLastLooted(UUID player) { ++ return getLootableData().getLastLooted(player); ++ } ++ ++ @Override ++ default boolean setHasPlayerLooted(UUID player, boolean looted) { ++ final boolean hasLooted = hasPlayerLooted(player); ++ if (hasLooted != looted) { ++ getLootableData().setPlayerLootedState(player, looted); ++ } ++ return hasLooted; ++ } ++ ++ @Override ++ default boolean hasPendingRefill() { ++ long nextRefill = getLootableData().getNextRefill(); ++ return nextRefill != -1 && nextRefill > getLootableData().getLastFill(); ++ } ++ ++ @Override ++ default long getLastFilled() { ++ return getLootableData().getLastFill(); ++ } ++ ++ @Override ++ default long getNextRefill() { ++ return getLootableData().getNextRefill(); ++ } ++ ++ @Override ++ default long setNextRefill(long refillAt) { ++ if (refillAt < -1) { ++ refillAt = -1; ++ } ++ return getLootableData().setNextRefill(refillAt); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java +new file mode 100644 +index 0000000000000000000000000000000000000000..88542462d34ba24e8590294bd896d7e73932ef9c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java +@@ -0,0 +1,180 @@ ++package com.destroystokyo.paper.loottable; ++ ++import com.destroystokyo.paper.PaperWorldConfig; ++import org.bukkit.entity.Player; ++import org.bukkit.loot.LootTable; ++ ++import javax.annotation.Nullable; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import java.util.HashMap; ++import java.util.Map; ++import java.util.Random; ++import java.util.UUID; ++ ++public class PaperLootableInventoryData { ++ ++ private static final Random RANDOM = new Random(); ++ ++ private long lastFill = -1; ++ private long nextRefill = -1; ++ private int numRefills = 0; ++ private Map lootedPlayers; ++ private final PaperLootableInventory lootable; ++ ++ public PaperLootableInventoryData(PaperLootableInventory lootable) { ++ this.lootable = lootable; ++ } ++ ++ long getLastFill() { ++ return this.lastFill; ++ } ++ ++ long getNextRefill() { ++ return this.nextRefill; ++ } ++ ++ long setNextRefill(long nextRefill) { ++ long prev = this.nextRefill; ++ this.nextRefill = nextRefill; ++ return prev; ++ } ++ ++ public boolean shouldReplenish(@Nullable net.minecraft.world.entity.player.Player player) { ++ LootTable table = this.lootable.getLootTable(); ++ ++ // No Loot Table associated ++ if (table == null) { ++ return false; ++ } ++ ++ // ALWAYS process the first fill or if the feature is disabled ++ if (this.lastFill == -1 || !this.lootable.getNMSWorld().paperConfig.autoReplenishLootables) { ++ return true; ++ } ++ ++ // Only process refills when a player is set ++ if (player == null) { ++ return false; ++ } ++ ++ // Chest is not scheduled for refill ++ if (this.nextRefill == -1) { ++ return false; ++ } ++ ++ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; ++ ++ // Check if max refills has been hit ++ if (paperConfig.maxLootableRefills != -1 && this.numRefills >= paperConfig.maxLootableRefills) { ++ return false; ++ } ++ ++ // Refill has not been reached ++ if (this.nextRefill > System.currentTimeMillis()) { ++ return false; ++ } ++ ++ ++ final Player bukkitPlayer = (Player) player.getBukkitEntity(); ++ LootableInventoryReplenishEvent event = new LootableInventoryReplenishEvent(bukkitPlayer, lootable.getAPILootableInventory()); ++ if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUUID())) { ++ event.setCancelled(true); ++ } ++ return event.callEvent(); ++ } ++ public void processRefill(@Nullable net.minecraft.world.entity.player.Player player) { ++ this.lastFill = System.currentTimeMillis(); ++ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; ++ if (paperConfig.autoReplenishLootables) { ++ int min = paperConfig.lootableRegenMin; ++ int max = paperConfig.lootableRegenMax; ++ this.nextRefill = this.lastFill + (min + RANDOM.nextInt(max - min + 1)) * 1000L; ++ this.numRefills++; ++ if (paperConfig.changeLootTableSeedOnFill) { ++ this.lootable.setSeed(0); ++ } ++ if (player != null) { // This means that numRefills can be incremented without a player being in the lootedPlayers list - Seems to be EntityMinecartChest specific ++ this.setPlayerLootedState(player.getUUID(), true); ++ } ++ } else { ++ this.lootable.clearLootTable(); ++ } ++ } ++ ++ ++ public void loadNbt(CompoundTag base) { ++ if (!base.contains("Paper.LootableData", 10)) { // 10 = compound ++ return; ++ } ++ CompoundTag comp = base.getCompound("Paper.LootableData"); ++ if (comp.contains("lastFill")) { ++ this.lastFill = comp.getLong("lastFill"); ++ } ++ if (comp.contains("nextRefill")) { ++ this.nextRefill = comp.getLong("nextRefill"); ++ } ++ ++ if (comp.contains("numRefills")) { ++ this.numRefills = comp.getInt("numRefills"); ++ } ++ if (comp.contains("lootedPlayers", 9)) { // 9 = list ++ ListTag list = comp.getList("lootedPlayers", 10); // 10 = compound ++ final int size = list.size(); ++ if (size > 0) { ++ this.lootedPlayers = new HashMap<>(list.size()); ++ } ++ for (int i = 0; i < size; i++) { ++ final CompoundTag cmp = list.getCompound(i); ++ lootedPlayers.put(cmp.getUUID("UUID"), cmp.getLong("Time")); ++ } ++ } ++ } ++ public void saveNbt(CompoundTag base) { ++ CompoundTag comp = new CompoundTag(); ++ if (this.nextRefill != -1) { ++ comp.putLong("nextRefill", this.nextRefill); ++ } ++ if (this.lastFill != -1) { ++ comp.putLong("lastFill", this.lastFill); ++ } ++ if (this.numRefills != 0) { ++ comp.putInt("numRefills", this.numRefills); ++ } ++ if (this.lootedPlayers != null && !this.lootedPlayers.isEmpty()) { ++ ListTag list = new ListTag(); ++ for (Map.Entry entry : this.lootedPlayers.entrySet()) { ++ CompoundTag cmp = new CompoundTag(); ++ cmp.setUUID("UUID", entry.getKey()); ++ cmp.putLong("Time", entry.getValue()); ++ list.add(cmp); ++ } ++ comp.put("lootedPlayers", list); ++ } ++ ++ if (!comp.isEmpty()) { ++ base.put("Paper.LootableData", comp); ++ } ++ } ++ ++ void setPlayerLootedState(UUID player, boolean looted) { ++ if (looted && this.lootedPlayers == null) { ++ this.lootedPlayers = new HashMap<>(); ++ } ++ if (looted) { ++ if (!this.lootedPlayers.containsKey(player)) { ++ this.lootedPlayers.put(player, System.currentTimeMillis()); ++ } ++ } else if (this.lootedPlayers != null) { ++ this.lootedPlayers.remove(player); ++ } ++ } ++ ++ boolean hasPlayerLooted(UUID player) { ++ return this.lootedPlayers != null && this.lootedPlayers.containsKey(player); ++ } ++ ++ Long getLastLooted(UUID player) { ++ return lootedPlayers != null ? lootedPlayers.get(player) : null; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d9b31c8a21fdffb33d1f75b1a16606f218145b39 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java +@@ -0,0 +1,63 @@ ++package com.destroystokyo.paper.loottable; ++ ++import LootableInventory; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; ++import net.minecraft.world.level.Level; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++ ++public class PaperMinecartLootableInventory implements PaperLootableEntityInventory { ++ ++ private AbstractMinecartContainer entity; ++ ++ public PaperMinecartLootableInventory(AbstractMinecartContainer entity) { ++ this.entity = entity; ++ } ++ ++ @Override ++ public org.bukkit.loot.LootTable getLootTable() { ++ return entity.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.lootTable)) : null; ++ } ++ ++ @Override ++ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { ++ setLootTable(table); ++ setSeed(seed); ++ } ++ ++ @Override ++ public void setSeed(long seed) { ++ entity.lootTableSeed = seed; ++ } ++ ++ @Override ++ public long getSeed() { ++ return entity.lootTableSeed; ++ } ++ ++ @Override ++ public void setLootTable(org.bukkit.loot.LootTable table) { ++ entity.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); ++ } ++ ++ @Override ++ public PaperLootableInventoryData getLootableData() { ++ return entity.lootableData; ++ } ++ ++ @Override ++ public Entity getHandle() { ++ return entity; ++ } ++ ++ @Override ++ public LootableInventory getAPILootableInventory() { ++ return (LootableInventory) entity.getBukkitEntity(); ++ } ++ ++ @Override ++ public Level getNMSWorld() { ++ return entity.level; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6bc899ec4dc03b09cc978bc7a763a9755a3d2dc4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java +@@ -0,0 +1,66 @@ ++package com.destroystokyo.paper.loottable; ++ ++import LootableInventory; ++import net.minecraft.server.MCUtil; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++ ++public class PaperTileEntityLootableInventory implements PaperLootableBlockInventory { ++ private RandomizableContainerBlockEntity tileEntityLootable; ++ ++ public PaperTileEntityLootableInventory(RandomizableContainerBlockEntity tileEntityLootable) { ++ this.tileEntityLootable = tileEntityLootable; ++ } ++ ++ @Override ++ public org.bukkit.loot.LootTable getLootTable() { ++ return tileEntityLootable.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null; ++ } ++ ++ @Override ++ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { ++ setLootTable(table); ++ setSeed(seed); ++ } ++ ++ @Override ++ public void setLootTable(org.bukkit.loot.LootTable table) { ++ tileEntityLootable.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); ++ } ++ ++ @Override ++ public void setSeed(long seed) { ++ tileEntityLootable.lootTableSeed = seed; ++ } ++ ++ @Override ++ public long getSeed() { ++ return tileEntityLootable.lootTableSeed; ++ } ++ ++ @Override ++ public PaperLootableInventoryData getLootableData() { ++ return tileEntityLootable.lootableData; ++ } ++ ++ @Override ++ public RandomizableContainerBlockEntity getTileEntity() { ++ return tileEntityLootable; ++ } ++ ++ @Override ++ public LootableInventory getAPILootableInventory() { ++ Level world = tileEntityLootable.getLevel(); ++ if (world == null) { ++ return null; ++ } ++ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, tileEntityLootable.getBlockPos())).getState(); ++ } ++ ++ @Override ++ public Level getNMSWorld() { ++ return tileEntityLootable.getLevel(); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 61048140cf0adca03bfb57193ada0adaee73b1bb..171697e88f5a4d8c0be2a47b67b865bbdc4dfe8c 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -157,6 +157,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + }; + // Paper end + ++ public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper + private CraftEntity bukkitEntity; + + public CraftEntity getBukkitEntity() { +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +index f4758251e58fbb36526cea5c4825561d62c9665a..5b96b1e7428a43c8c5f4a96ea37d5189f0d84f56 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +@@ -45,6 +45,7 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme + public long lootTableSeed; + + // CraftBukkit start ++ { this.lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperMinecartLootableInventory(this)); } // Paper + public List transaction = new java.util.ArrayList(); + private int maxStack = MAX_STACK; + +@@ -202,12 +203,13 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme + @Override + protected void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); ++ this.lootableData.saveNbt(tag); // Paper + if (this.lootTable != null) { + tag.putString("LootTable", this.lootTable.toString()); + if (this.lootTableSeed != 0L) { + tag.putLong("LootTableSeed", this.lootTableSeed); + } +- } else { ++ } if (true) { // Paper - Always save the items, Table may stick around + ContainerHelper.saveAllItems(tag, this.itemStacks); + } + +@@ -216,11 +218,12 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme + @Override + protected void readAdditionalSaveData(CompoundTag tag) { + super.readAdditionalSaveData(tag); ++ this.lootableData.loadNbt(tag); // Paper + this.itemStacks = NonNullList.a(this.getContainerSize(), ItemStack.EMPTY); + if (tag.contains("LootTable", 8)) { + this.lootTable = new ResourceLocation(tag.getString("LootTable")); + this.lootTableSeed = tag.getLong("LootTableSeed"); +- } else { ++ } if (true) { // Paper - always load the items, table may still remain + ContainerHelper.loadAllItems(tag, this.itemStacks); + } + +@@ -251,14 +254,15 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme + } + + public void unpackLootTable(@Nullable Player player) { +- if (this.lootTable != null && this.level.getServer() != null) { ++ if (this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper + LootTable loottable = this.level.getServer().getLootTables().get(this.lootTable); + + if (player instanceof ServerPlayer) { + CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer) player, this.lootTable); + } + +- this.lootTable = null; ++ //this.lootTable = null; // Paper ++ this.lootableData.processRefill(player); // Paper + LootContext.Builder loottableinfo_builder = (new LootContext.Builder((ServerLevel) this.level)).withParameter(LootContextParams.ORIGIN, this.position()).withOptionalRandomSeed(this.lootTableSeed); + + if (player != null) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +index 9d33bc31c8088bfba66be1aecbf20e7ee86e4f83..5ad419941ff1113ef29b9a4593f44d8f35ba8424 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +@@ -27,6 +27,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + @Nullable + public ResourceLocation lootTable; + public long lootTableSeed; ++ public final com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperTileEntityLootableInventory(this)); // Paper + + protected RandomizableContainerBlockEntity(BlockEntityType type) { + super(type); +@@ -42,16 +43,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + } + + protected boolean tryLoadLootTable(CompoundTag nbttagcompound) { ++ this.lootableData.loadNbt(nbttagcompound); // Paper + if (nbttagcompound.contains("LootTable", 8)) { + this.lootTable = new ResourceLocation(nbttagcompound.getString("LootTable")); ++ try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate + this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); +- return true; ++ return false; // Paper - always load the items, table may still remain + } else { + return false; + } + } + + protected boolean trySaveLootTable(CompoundTag nbttagcompound) { ++ this.lootableData.saveNbt(nbttagcompound); // Paper + if (this.lootTable == null) { + return false; + } else { +@@ -60,19 +64,20 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + nbttagcompound.putLong("LootTableSeed", this.lootTableSeed); + } + +- return true; ++ return false; // Paper - always save the items, table may still remain + } + } + + public void unpackLootTable(@Nullable Player player) { +- if (this.lootTable != null && this.level.getServer() != null) { ++ if (this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper + LootTable loottable = this.level.getServer().getLootTables().get(this.lootTable); + + if (player instanceof ServerPlayer) { + CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer) player, this.lootTable); + } + +- this.lootTable = null; ++ //this.lootTable = null; // Paper ++ this.lootableData.processRefill(player); // Paper + LootContext.Builder loottableinfo_builder = (new LootContext.Builder((ServerLevel) this.level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf((Vec3i) this.worldPosition)).withOptionalRandomSeed(this.lootTableSeed); + + if (player != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +index 1e2e94b0cd2ede8fb7ae5902dcd0b639bd8dcf52..e89a93082fe07fdb14df8ffef5beca5bd52d7866 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +@@ -64,7 +64,7 @@ public class CraftBlockEntityState extends CraftBlockStat + } + + // gets the wrapped TileEntity +- protected T getTileEntity() { ++ public T getTileEntity() { // Paper - protected -> public + return tileEntity; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +index 20d9a192ff102e04687a8aa3eff1ba36a69b6c03..a821df3e13e2ddc479dc5f55540671f43563cdac 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +@@ -12,8 +12,9 @@ import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.inventory.CraftInventory; + import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest; + import org.bukkit.inventory.Inventory; ++import com.destroystokyo.paper.loottable.PaperLootableBlockInventory; // Paper + +-public class CraftChest extends CraftLootable implements Chest { ++public class CraftChest extends CraftLootable implements Chest, PaperLootableBlockInventory { // Paper + + public CraftChest(final Block block) { + super(block, ChestBlockEntity.class); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java +index 309650aad43d8b6ce4bb13f8c172028f3feab299..5babbcfcacb89e62f00f8184af2ceea227f9ff69 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java +@@ -10,7 +10,7 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; + import org.bukkit.loot.LootTable; + import org.bukkit.loot.Lootable; + +-public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable { ++public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable, com.destroystokyo.paper.loottable.PaperLootableBlockInventory { // Paper + + public CraftLootable(Block block, Class tileEntityClass) { + super(block, tileEntityClass); +@@ -54,7 +54,7 @@ public abstract class CraftLootable + setLootTable(getLootTable(), seed); + } + +- private void setLootTable(LootTable table, long seed) { ++ public void setLootTable(LootTable table, long seed) { // Paper - public + ResourceLocation key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); + getSnapshot().setLootTable(key, seed); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java +index f0a30acb0199e396d6863a473db433cbe112d8a5..293b222565d8e0592f9f355a2ee8cdfbc868a08e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java +@@ -8,7 +8,7 @@ import org.bukkit.entity.minecart.StorageMinecart; + import org.bukkit.inventory.Inventory; + + @SuppressWarnings("deprecation") +-public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart { ++public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper + private final CraftInventory inventory; + + public CraftMinecartChest(CraftServer server, MinecartChest entity) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java +index 12044062cb746bd5c77abacf8acddc67e08e78ce..ce14bc4791bd282d16af0ee91fc431acefa3b909 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java +@@ -47,7 +47,7 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo + return getHandle().lootTableSeed; + } + +- private void setLootTable(LootTable table, long seed) { ++ public void setLootTable(LootTable table, long seed) { // Paper + ResourceLocation newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); + getHandle().setLootTable(newKey, seed); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +index c1af739369715d8c628c466b269fdde99a2f6286..c8c5f60b6b32248696363d9b63bbbe43810743d3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +@@ -7,7 +7,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.minecart.HopperMinecart; + import org.bukkit.inventory.Inventory; + +-public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart { ++public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper + private final CraftInventory inventory; + + public CraftMinecartHopper(CraftServer server, MinecartHopper entity) { diff --git a/Remapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/Remapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch new file mode 100644 index 0000000000..f9fbbc4e75 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 May 2016 23:33:08 -0400 +Subject: [PATCH] Don't save empty scoreboard teams to scoreboard.dat + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 504efea7b6f50a0d17f4f353781953dfb18bdeca..1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -237,4 +237,9 @@ public class PaperConfig { + private static void enablePlayerCollisions() { + enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); + } ++ ++ public static boolean saveEmptyScoreboardTeams = false; ++ private static void saveEmptyScoreboardTeams() { ++ saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java +index 36a922029687b9fa3ca3a986ae42a373ced87a0e..b9e14d1c54b690f0b975bda5733c4cb4f6449f77 100644 +--- a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java ++++ b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java +@@ -182,6 +182,7 @@ public class ScoreboardSaveData extends SavedData { + + while (iterator.hasNext()) { + PlayerTeam scoreboardteam = (PlayerTeam) iterator.next(); ++ if (!com.destroystokyo.paper.PaperConfig.saveEmptyScoreboardTeams && scoreboardteam.getPlayers().isEmpty()) continue; // Paper + CompoundTag nbttagcompound = new CompoundTag(); + + nbttagcompound.putString("Name", scoreboardteam.getName()); diff --git a/Remapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch b/Remapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch new file mode 100644 index 0000000000..d8a22a7f5f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 12 May 2016 23:02:58 -0500 +Subject: [PATCH] System property for disabling watchdoge + + +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 0ed95268364ea7f6a92a39b726a1e03bc815be07..ee0cca25ef458f2f0f7e450a2edea2b2adb7e846 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -61,7 +61,7 @@ public class WatchdogThread extends Thread + while ( !stopping ) + { + // +- if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime ) ++ if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable + { + Logger log = Bukkit.getServer().getLogger(); + log.log( Level.SEVERE, "------------------------------" ); diff --git a/Remapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch b/Remapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch new file mode 100644 index 0000000000..4b08a22748 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 16 May 2016 20:47:41 -0400 +Subject: [PATCH] Optimize UserCache / Thread Safe + +Because Techable keeps complaining about how this isn't thread safe, +easier to do this than replace the entire thing. + +Additionally, move Saving of the User cache to be done async, incase +the user never changed the default setting for Spigot's save on stop only. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 4e468cb7ccf683b8fc9e04a48cfc25779775e25f..211251fe7cd08074c040df2f4642f37d5f90d856 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -905,7 +905,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Paper + + try { + BufferedWriter bufferedwriter = Files.newWriter(this.file, StandardCharsets.UTF_8); +@@ -268,6 +270,14 @@ public class GameProfileCache { + } catch (IOException ioexception) { + ; + } ++ // Paper start ++ }; ++ if (asyncSave) { ++ MCUtil.scheduleAsyncTask(save); ++ } else { ++ save.run(); ++ } ++ // Paper end + + } + diff --git a/Remapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch b/Remapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch new file mode 100644 index 0000000000..ba69589d2f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 16 May 2016 23:19:16 -0400 +Subject: [PATCH] Avoid blocking on Network Manager creation + +Per Paper issue 294 + +diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +index 9680b0b3879c72776d6225a6a5a89fdfa3520598..6cb51a4fe3c11f53fbb556ce6b0d64b735254d51 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +@@ -52,6 +52,15 @@ public class ServerConnectionListener { + public volatile boolean running; + private final List channels = Collections.synchronizedList(Lists.newArrayList()); + private final List connections = Collections.synchronizedList(Lists.newArrayList()); ++ // Paper start - prevent blocking on adding a new network manager while the server is ticking ++ private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ private void addPending() { ++ Connection manager = null; ++ while ((manager = pending.poll()) != null) { ++ connections.add(manager); ++ } ++ } ++ // Paper end + + public ServerConnectionListener(MinecraftServer server) { + this.server = server; +@@ -87,7 +96,8 @@ public class ServerConnectionListener { + int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); + Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); + +- ServerConnectionListener.this.connections.add((Connection) object); // CraftBukkit - decompile error ++ //ServerConnection.this.connectedChannels.add((NetworkManager) object); // CraftBukkit - decompile error ++ pending.add((Connection) object); // Paper + channel.pipeline().addLast("packet_handler", (ChannelHandler) object); + ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); + } +@@ -126,6 +136,7 @@ public class ServerConnectionListener { + + synchronized (this.connections) { + // Spigot Start ++ this.addPending(); // Paper + // This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order + if ( org.spigotmc.SpigotConfig.playerShuffle > 0 && MinecraftServer.currentTick % org.spigotmc.SpigotConfig.playerShuffle == 0 ) + { diff --git a/Remapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch b/Remapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch new file mode 100644 index 0000000000..cd8e56460f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 22 May 2016 20:20:55 -0500 +Subject: [PATCH] Optional TNT doesn't move in water + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index eb04fdb172a50ec1f5b7fe78fa0e7655246abd60..6eca3f300020006f02dd36253b522db442e3cc33 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -2,7 +2,6 @@ package com.destroystokyo.paper; + + import java.util.List; + +-import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; + +@@ -291,4 +290,14 @@ public class PaperWorldConfig { + ); + } + } ++ ++ public boolean preventTntFromMovingInWater; ++ private void preventTntFromMovingInWater() { ++ if (PaperConfig.version < 13) { ++ boolean oldVal = getBoolean("enable-old-tnt-cannon-behaviors", false); ++ set("prevent-tnt-from-moving-in-water", oldVal); ++ } ++ preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); ++ log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index fa6893055fa5617742bfb4b7eff60c8139395cb6..49c71b21b6b88bc41ca6ddf4c76186ce522ee456 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -66,7 +66,7 @@ public class ServerEntity { + private boolean wasRiding; + private boolean wasOnGround; + // CraftBukkit start +- private final Set trackedPlayers; ++ final Set trackedPlayers; // Paper - private -> package + // Paper start + private java.util.Map trackedPlayerMap = null; + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 171697e88f5a4d8c0be2a47b67b865bbdc4dfe8c..c3aece8e5001828edea304b2a8377e9a28b34cfe 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2770,6 +2770,11 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean isPushedByFluid() { ++ // Paper start ++ return this.pushedByWater(); ++ } ++ public boolean pushedByWater() { ++ // Paper end + return true; + } + +diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +index 661848084fd986321ef782317934dac19ed4dce3..347ac17643de8bcb0c8496c2ea5eb18c2e4d856b 100644 +--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +@@ -5,9 +5,13 @@ import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; ++import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; ++import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; +@@ -95,7 +99,27 @@ public class PrimedTnt extends Entity { + this.level.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D); + } + } +- ++ // Paper start - Optional prevent TNT from moving in water ++ if (!this.removed && this.wasTouchingWater && this.level.paperConfig.preventTntFromMovingInWater) { ++ /* ++ * Author: Jedediah Smith ++ */ ++ // Send position and velocity updates to nearby players on every tick while the TNT is in water. ++ // This does pretty well at keeping their clients in sync with the server. ++ ChunkMap.TrackedEntity ete = ((ServerLevel)this.level).getChunkSource().chunkMap.entityMap.get(this.getId()); ++ if (ete != null) { ++ ClientboundSetEntityMotionPacket velocityPacket = new ClientboundSetEntityMotionPacket(this); ++ ClientboundTeleportEntityPacket positionPacket = new ClientboundTeleportEntityPacket(this); ++ ++ ete.seenBy.stream() ++ .filter(viewer -> (viewer.getX() - this.getX()) * (viewer.getY() - this.getY()) * (viewer.getZ() - this.getZ()) < 16 * 16) ++ .forEach(viewer -> { ++ viewer.connection.send(velocityPacket); ++ viewer.connection.send(positionPacket); ++ }); ++ } ++ } ++ // Paper end + } + + private void explode() { +@@ -164,4 +188,11 @@ public class PrimedTnt extends Entity { + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this); + } ++ ++ // Paper start - Optional prevent TNT from moving in water ++ @Override ++ public boolean pushedByWater() { ++ return !level.paperConfig.preventTntFromMovingInWater && super.pushedByWater(); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch b/Remapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch new file mode 100644 index 0000000000..cc437e7353 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch @@ -0,0 +1,98 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Panzer +Date: Mon, 23 May 2016 12:12:37 +0200 +Subject: [PATCH] Faster redstone torch rapid clock removal + +Only resize the the redstone torch list once, since resizing arrays / lists is costly + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 8f0fec38b482465285057d3fd27d456cf036f2fd..5f3d17cb247156fc8aaa7a763e402c2bbb42a7ec 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -48,6 +48,7 @@ import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.RedstoneTorchBlock; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.TickableBlockEntity; +@@ -142,6 +143,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + private org.spigotmc.TickLimiter tileLimiter; + private int tileTickPosition; + public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions ++ public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here + + public CraftWorld getWorld() { + return this.world; +diff --git a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java +index 7d71c99c2268174fbea4297f028b75a3a0f43c11..dd4391086aff05bdea81e62b950b88cfab5ac6b8 100644 +--- a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java +@@ -21,7 +21,7 @@ import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + public class RedstoneTorchBlock extends TorchBlock { + + public static final BooleanProperty LIT = BlockStateProperties.LIT; +- private static final Map> RECENT_TOGGLES = new WeakHashMap(); ++ // Paper - Move the mapped list to World + + protected RedstoneTorchBlock(BlockBehaviour.Properties settings) { + super(settings, DustParticleOptions.REDSTONE); +@@ -68,11 +68,15 @@ public class RedstoneTorchBlock extends TorchBlock { + @Override + public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) { + boolean flag = this.hasNeighborSignal((Level) world, pos, state); +- List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.get(world); +- +- while (list != null && !list.isEmpty() && world.getGameTime() - ((RedstoneTorchBlock.Toggle) list.get(0)).when > 60L) { +- list.remove(0); ++ // Paper start ++ java.util.ArrayDeque redstoneUpdateInfos = world.redstoneUpdateInfos; ++ if (redstoneUpdateInfos != null) { ++ RedstoneTorchBlock.Toggle curr; ++ while ((curr = redstoneUpdateInfos.peek()) != null && world.getGameTime() - curr.getTime() > 60L) { ++ redstoneUpdateInfos.poll(); ++ } + } ++ // Paper end + + // CraftBukkit start + org.bukkit.plugin.PluginManager manager = world.getCraftServer().getPluginManager(); +@@ -137,9 +141,12 @@ public class RedstoneTorchBlock extends TorchBlock { + } + + private static boolean isToggledTooFrequently(Level world, BlockPos pos, boolean addNew) { +- List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.computeIfAbsent(world, (iblockaccess) -> { +- return Lists.newArrayList(); +- }); ++ // Paper start ++ java.util.ArrayDeque list = world.redstoneUpdateInfos; ++ if (list == null) { ++ list = world.redstoneUpdateInfos = new java.util.ArrayDeque<>(); ++ } ++ + + if (addNew) { + list.add(new RedstoneTorchBlock.Toggle(pos.immutable(), world.getGameTime())); +@@ -147,9 +154,9 @@ public class RedstoneTorchBlock extends TorchBlock { + + int i = 0; + +- for (int j = 0; j < list.size(); ++j) { +- RedstoneTorchBlock.Toggle blockredstonetorch_redstoneupdateinfo = (RedstoneTorchBlock.Toggle) list.get(j); +- ++ for (java.util.Iterator iterator = list.iterator(); iterator.hasNext();) { ++ RedstoneTorchBlock.Toggle blockredstonetorch_redstoneupdateinfo = iterator.next(); ++ // Paper end + if (blockredstonetorch_redstoneupdateinfo.pos.equals(pos)) { + ++i; + if (i >= 8) { +@@ -164,7 +171,7 @@ public class RedstoneTorchBlock extends TorchBlock { + public static class Toggle { + + private final BlockPos pos; +- private final long when; ++ private final long when; final long getTime() { return this.when; } // Paper - OBFHELPER + + public Toggle(BlockPos pos, long time) { + this.pos = pos; diff --git a/Remapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch b/Remapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch new file mode 100644 index 0000000000..50ec621547 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Panzer +Date: Sat, 28 May 2016 16:54:03 +0200 +Subject: [PATCH] Add server-name parameter + + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2..b849b2afd009da433fe6cea5837b3ee9bb5c52b4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -143,6 +143,14 @@ public class Main { + .defaultsTo(new File("paper.yml")) + .describedAs("Yml file"); + // Paper end ++ ++ // Paper start ++ acceptsAll(asList("server-name"), "Name of the server") ++ .withRequiredArg() ++ .ofType(String.class) ++ .defaultsTo("Unknown Server") ++ .describedAs("Name"); ++ // Paper end + } + }; + diff --git a/Remapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/Remapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch new file mode 100644 index 0000000000..e84fc6a07e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 31 May 2016 22:53:50 -0400 +Subject: [PATCH] Only send Dragon/Wither Death sounds to same world + +Also fix view distance lookup + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index 8d1b3cbb21fe798c27ad2d39bccffa9cc983cf96..39298b69918da890c3faa516f80d1a69adb88fe2 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -619,8 +619,9 @@ public class EnderDragon extends Mob implements Enemy { + if (this.dragonDeathTime == 1 && !this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1028, this.getChunkCoordinates(), 0); +- int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; +- for (net.minecraft.server.level.ServerPlayer player : this.level.getServer().getPlayerList().players) { ++ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ for (net.minecraft.server.level.ServerPlayer player : (List) ((ServerLevel)level).players()) { ++ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch + double deltaX = this.getX() - player.getX(); + double deltaZ = this.getZ() - player.getZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +index 61c982ead18334a29438ef8e024d97ead178a2c8..3a80869dc3c16cb81ac87100f28d63eee722067f 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -46,7 +46,6 @@ import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerBossEvent; +-import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; +@@ -256,8 +255,9 @@ public class WitherBoss extends Monster implements RangedAttackMob { + if (!this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1023, new BlockPosition(this), 0); +- int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; +- for (ServerPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { ++ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ for (ServerPlayer player : (List)this.level.players()) { ++ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch + double deltaX = this.getX() - player.getX(); + double deltaZ = this.getZ() - player.getZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; diff --git a/Remapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch b/Remapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch new file mode 100644 index 0000000000..b412753ddd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 21 Jun 2016 22:54:34 -0400 +Subject: [PATCH] Fix Double World Add issues + +Vanilla will double add Spider Jockeys to the world, so ignore already added. + +Also add debug if something else tries to, and abort before world gets bad state + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0a613f94d1c796267636e1a343aeee65a49ffed5..335928d60dbfc07644ffeab366900c5e77e99d56 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1032,6 +1032,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // CraftBukkit start + private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot ++ if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper + if (entity.removed) { + // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit + return false; diff --git a/Remapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch b/Remapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch new file mode 100644 index 0000000000..d08b9cb8ca --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 17 Jun 2016 20:50:11 -0400 +Subject: [PATCH] Fix Old Sign Conversion + +1) Sign loading code was trying to parse the JSON before the check for oldSign. + That code could then skip the old sign converting code if it triggers a JSON parse exception. +2) New Mojang Schematic system has Tile Entities in the new converted format, but missing the Bukkit.isConverted flag + This causes Igloos and such to render broken signs. We fix this by ignoring sign conversion for Defined Structures + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 13115d1b28dfa2d87b45a50bd0feaa7f57769122..d08ed44884726ca2ba4578226b8aa6244778f4c7 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -34,6 +34,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + public CraftPersistentDataContainer persistentDataContainer; + // CraftBukkit end + private static final Logger LOGGER = LogManager.getLogger(); ++ public boolean isLoadingStructure = false; // Paper + private final BlockEntityType type; public BlockEntityType getTileEntityType() { return type; } // Paper - OBFHELPER + @Nullable + protected Level level; +diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +index e747f729326fb3bacfb3f983ac7701c0fb0f0e6a..e4eab82855649fec654c60b2e94ba7b71c2ac5a2 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -78,13 +78,14 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + } + + try { +- MutableComponent ichatmutablecomponent = Component.Serializer.fromJson(s.isEmpty() ? "\"\"" : s); ++ //IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); // Paper - move down - the old format might throw a json error + +- if (oldSign) { ++ if (oldSign && !isLoadingStructure) { // Paper - saved structures will be in the new format, but will not have isConverted + messages[i] = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s)[0]; + continue; + } + // CraftBukkit end ++ MutableComponent ichatmutablecomponent = Component.Serializer.fromJson(s.isEmpty() ? "\"\"" : s); // Paper - after old sign + + if (this.level instanceof ServerLevel) { + try { +diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java +index 8da00ee410e3f8f09b8ac273095a3d22d6c4d92b..d4cf5d3bdbe629081f6ec9d4ea94004560c93ebc 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java +@@ -278,9 +278,11 @@ public class StructureTemplate { + definedstructure_blockinfo.nbt.putLong("LootTableSeed", random.nextLong()); + } + ++ tileentity.isLoadingStructure = true; // Paper + tileentity.load(definedstructure_blockinfo.state, definedstructure_blockinfo.nbt); + tileentity.mirror(placementData.getMirror()); + tileentity.rotate(placementData.getRotation()); ++ tileentity.isLoadingStructure = false; // Paper + } + } + diff --git a/Remapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/Remapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch new file mode 100644 index 0000000000..51ddf3745d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 16 Jul 2016 19:11:17 -0500 +Subject: [PATCH] Don't lookup game profiles that have no UUID and no name + + +diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java +index 9342fa6b28e805743b8e3a13007605934244d6cd..f3e05fac1b5248ca4ee2cac03263e96c166ed343 100644 +--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java ++++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +@@ -92,7 +92,7 @@ public class GameProfileCache { + repository.findProfilesByNames(new String[]{name}, Agent.MINECRAFT, profilelookupcallback); + GameProfile gameprofile = (GameProfile) atomicreference.get(); + +- if (!usesAuthentication() && gameprofile == null) { ++ if (!usesAuthentication() && gameprofile == null && !org.apache.commons.lang3.StringUtils.isBlank(name)) { // Paper - Don't lookup a profile with a blank name + UUID uuid = Player.createPlayerUUID(new GameProfile((UUID) null, name)); + + gameprofile = new GameProfile(uuid, name); diff --git a/Remapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch b/Remapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch new file mode 100644 index 0000000000..067e04850c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gabriele C +Date: Fri, 5 Aug 2016 01:03:08 +0200 +Subject: [PATCH] Add setting for proxy online mode status + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2..c52dc0346f93527965ef29a0ccdc4bf3debe302e 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -23,6 +23,7 @@ import org.bukkit.configuration.InvalidConfigurationException; + import org.bukkit.configuration.file.YamlConfiguration; + import co.aikar.timings.Timings; + import co.aikar.timings.TimingsManager; ++import org.spigotmc.SpigotConfig; + + public class PaperConfig { + +@@ -242,4 +243,13 @@ public class PaperConfig { + private static void saveEmptyScoreboardTeams() { + saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); + } ++ ++ public static boolean bungeeOnlineMode = true; ++ private static void bungeeOnlineMode() { ++ bungeeOnlineMode = getBoolean("settings.bungee-online-mode", true); ++ } ++ ++ public static boolean isProxyOnlineMode() { ++ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); ++ } + } +diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java +index f3e05fac1b5248ca4ee2cac03263e96c166ed343..e8af352f813a5015d216fc590190ae8fdb03f77d 100644 +--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java ++++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +@@ -89,6 +89,7 @@ public class GameProfileCache { + } + }; + ++ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) // Paper - only run in online mode - 100 COL + repository.findProfilesByNames(new String[]{name}, Agent.MINECRAFT, profilelookupcallback); + GameProfile gameprofile = (GameProfile) atomicreference.get(); + +@@ -106,7 +107,7 @@ public class GameProfileCache { + } + + private static boolean usesAuthentication() { +- return GameProfileCache.usesAuthentication; ++ return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper + } + + public synchronized void add(GameProfile gameprofile) { // Paper - synchronize +diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java +index 09c5fa2dbcbed05da51ef2d63e6d6112d22d7877..e6a26c274616947329a6164e4648486452819b0c 100644 +--- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java ++++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java +@@ -63,7 +63,8 @@ public class OldUsersConverter { + return new String[i]; + }); + +- if (server.usesAuthentication() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. ++ if (server.usesAuthentication() ++ || (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode())) { // Spigot: bungee = online mode, for now. // Paper - Handle via setting + server.getProfileRepository().findProfilesByNames(astring, Agent.MINECRAFT, callback); + } else { + String[] astring1 = astring; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 2828936fe294d9d6750a8838da49ec8398835214..bbe0978f56d23b7defce765d381d4a7c20acd75c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1515,7 +1515,8 @@ public final class CraftServer implements Server { + // Spigot Start + GameProfile profile = null; + // Only fetch an online UUID in online mode +- if ( getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) ++ if ( getOnlineMode() ++ || com.destroystokyo.paper.PaperConfig.isProxyOnlineMode() ) // Paper - Handle via setting + { + profile = console.getProfileCache().get( name ); + } diff --git a/Remapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch b/Remapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch new file mode 100644 index 0000000000..6e9e140dc2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Fri, 19 Aug 2016 01:52:56 +0100 +Subject: [PATCH] Optimise BlockState's hashCode/equals + +These are singleton "single instance" objects. We can rely on +object identity checks safely. + +Use a simpler optimized hashcode + +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java +index c5af36a0279d1e1c951e6f9b34857b0aa934f940..62f11a02e3f5c07e838f425cffb0a28b6d2bc138 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java +@@ -30,8 +30,7 @@ public class BooleanProperty extends Property { + return value.toString(); + } + +- @Override +- public boolean equals(Object object) { ++ public boolean equals_unused(Object object) { // Paper + if (this == object) { + return true; + } else if (object instanceof BooleanProperty && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +index b5817645727f2af2785e0987ba824f431d4e9e32..2fdfd7d2470ee9f1a96eda7418b104c960df8460 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +@@ -50,8 +50,7 @@ public class EnumProperty & StringRepresentable> extends Prope + return ((StringRepresentable) value).getSerializedName(); + } + +- @Override +- public boolean equals(Object object) { ++ public boolean equals_unused(Object object) { // Paper + if (this == object) { + return true; + } else if (object instanceof EnumProperty && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java +index c3ec7f91794d802e5b9ddac3fffccce378dace68..72f508321ebffcca31240fbdd068b4d185454cbc 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java +@@ -38,8 +38,7 @@ public class IntegerProperty extends Property { + return this.values; + } + +- @Override +- public boolean equals(Object object) { ++ public boolean equals_unused(Object object) { // Paper + if (this == object) { + return true; + } else if (object instanceof IntegerProperty && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java +index 8cc07c70fde81e44679f3ea7d9a4c6b2447885d4..80f8966ac56e8af4a6c7aa86b2d8dd0f319c7b5d 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java +@@ -60,23 +60,17 @@ public abstract class Property> { + } + + public boolean equals(Object object) { +- if (this == object) { +- return true; +- } else if (!(object instanceof Property)) { +- return false; +- } else { +- Property iblockstate = (Property) object; +- +- return this.clazz.equals(iblockstate.clazz) && this.name.equals(iblockstate.name); +- } ++ return this == object; // Paper - only one instance per configuration + } + ++ private static final java.util.concurrent.atomic.AtomicInteger hashId = new java.util.concurrent.atomic.AtomicInteger(1); // Paper - only one instance per configuration ++ private final int hashCode = 92821 * hashId.getAndIncrement(); // Paper - only one instance per configuration + public final int hashCode() { + if (this.hashCode == null) { + this.hashCode = this.generateHashCode(); + } + +- return this.hashCode; ++ return this.hashCode; // Paper - only one instance per configuration + } + + public int generateHashCode() { diff --git a/Remapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch b/Remapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch new file mode 100644 index 0000000000..bce5b61b0d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 11 Sep 2016 14:30:57 -0500 +Subject: [PATCH] Configurable packet in spam threshold + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index c52dc0346f93527965ef29a0ccdc4bf3debe302e..64d7c9058ee757a6d3cf3b648596092a810e105c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -252,4 +252,13 @@ public class PaperConfig { + public static boolean isProxyOnlineMode() { + return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); + } ++ ++ public static int packetInSpamThreshold = 300; ++ private static void packetInSpamThreshold() { ++ if (version < 11) { ++ int oldValue = getInt("settings.play-in-use-item-spam-threshold", 300); ++ set("settings.incoming-packet-spam-threshold", oldValue); ++ } ++ packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index e2bfe8e916c9e59af81627ea0ee449970527034d..d6f4ccf06c919410e13409433bdfc3aa88a21c30 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1463,13 +1463,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // Spigot start - limit place/interactions + private int limitedPackets; + private long lastLimitedPacket = -1; ++ private static final int THRESHOLD = com.destroystokyo.paper.PaperConfig.packetInSpamThreshold; // Paper - Configurable threshold + + private boolean checkLimit(long timestamp) { +- if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < 30 && limitedPackets++ >= 4) { ++ if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < THRESHOLD && limitedPackets++ >= 8) { // Paper - Use threshold, raise packet limit to 8 + return false; + } + +- if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= 30) { ++ if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= THRESHOLD) { // Paper + lastLimitedPacket = timestamp; + limitedPackets = 0; + return true; diff --git a/Remapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch b/Remapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch new file mode 100644 index 0000000000..fc05cbc991 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Tue, 20 Sep 2016 00:58:01 +0000 +Subject: [PATCH] Configurable flying kick messages + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 64d7c9058ee757a6d3cf3b648596092a810e105c..4e2f243faa209925dcb7c3ef89df3ed875c5ff78 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -261,4 +261,11 @@ public class PaperConfig { + } + packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); + } ++ ++ public static String flyingKickPlayerMessage = "Flying is not enabled on this server"; ++ public static String flyingKickVehicleMessage = "Flying is not enabled on this server"; ++ private static void flyingKickMessages() { ++ flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); ++ flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index d6f4ccf06c919410e13409433bdfc3aa88a21c30..1b92c669bbe69bcc07a554b7b43ee99bfebc1af4 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -305,7 +305,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + if (this.clientIsFloating && !this.player.isSleeping()) { + if (++this.aboveGroundTickCount > 80) { + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.flying")); ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message + return; + } + } else { +@@ -324,7 +324,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) { + if (++this.aboveGroundVehicleTickCount > 80) { + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.flying")); ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message + return; + } + } else { diff --git a/Remapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch b/Remapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch new file mode 100644 index 0000000000..4d2da1cd83 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Sep 2016 22:54:28 -0400 +Subject: [PATCH] Chunk registration fixes + +World checks and the Chunk Add logic are inconsistent on how Y > 256, < 0, is treated + +Keep them consistent + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 335928d60dbfc07644ffeab366900c5e77e99d56..20650bfd10abfa010e71cfeede06c461d50d19a3 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -841,7 +841,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (entity.checkAndResetUpdateChunkPos()) { + this.getProfiler().push("chunkCheck"); + int i = Mth.floor(entity.getX() / 16.0D); +- int j = Mth.floor(entity.getY() / 16.0D); ++ int j = Math.min(15, Math.max(0, Mth.floor(entity.getY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior + int k = Mth.floor(entity.getZ() / 16.0D); + + if (!entity.inChunk || entity.xChunk != i || entity.yChunk != j || entity.zChunk != k) { diff --git a/Remapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/Remapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch new file mode 100644 index 0000000000..0d1bb6c9bb --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 16 Jun 2016 00:17:23 -0400 +Subject: [PATCH] Remove FishingHook reference on Craft Entity removal + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java +index 5668facc5bf5c56581c3ebd268f832d77ce5c05b..50322cfc07a7d93c32461faeb5e22e35ceead323 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java +@@ -119,4 +119,14 @@ public class CraftFishHook extends CraftProjectile implements FishHook { + public HookState getState() { + return HookState.values()[getHandle().currentState.ordinal()]; + } ++ ++ // Paper start ++ @Override ++ public void remove() { ++ super.remove(); ++ if (getHandle().getPlayerOwner() != null) { ++ getHandle().getPlayerOwner().fishing = null; ++ } ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch b/Remapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch new file mode 100644 index 0000000000..a6a274fc00 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Sep 2016 23:48:39 -0400 +Subject: [PATCH] Auto fix bad Y levels on player login + +Bring down to a saner Y level if super high, as this can cause the server to crash + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index bd3d9182dfb2c0ae1d8c3b9aa360f94c33252592..3a2356b3e00098d100a179a05316f402390d4e9b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -337,6 +337,7 @@ public class ServerPlayer extends Player implements ContainerListener { + @Override + public void readAdditionalSaveData(CompoundTag tag) { + super.readAdditionalSaveData(tag); ++ if (this.getY() > 300) this.setPosRaw(getX(), 257, getZ()); // Paper - bring down to a saner Y level if out of world + if (tag.contains("playerGameType", 99)) { + if (this.getServer().getForceGameType()) { + this.gameMode.setGameModeForPlayer(this.getServer().getDefaultGameType(), GameType.NOT_SET); diff --git a/Remapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch b/Remapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch new file mode 100644 index 0000000000..d6b80297c0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 5 Oct 2016 16:27:36 -0500 +Subject: [PATCH] Option to remove corrupt tile entities + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6eca3f300020006f02dd36253b522db442e3cc33..622affa0dc3cc1eadaed400511f2ca2cde3fca2a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -300,4 +300,9 @@ public class PaperWorldConfig { + preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); + log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); + } ++ ++ public boolean removeCorruptTEs = false; ++ private void removeCorruptTEs() { ++ removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 70f5b025c2b803df3de8a51cbcfafbe915866f42..d69ccb1f31f31ebeee477df20ce1410f9e485eb7 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -678,6 +678,12 @@ public class LevelChunk implements ChunkAccess { + "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); + e.printStackTrace(); + ServerInternalException.reportInternalException(e); ++ ++ if (this.world.paperConfig.removeCorruptTEs) { ++ this.removeBlockEntity(blockEntity.getBlockPos()); ++ this.markUnsaved(); ++ org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); ++ } + // Paper end + // CraftBukkit end + } diff --git a/Remapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch b/Remapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch new file mode 100644 index 0000000000..20a798bf8d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaBlend +Date: Sun, 16 Oct 2016 23:19:30 -0700 +Subject: [PATCH] Add EntityZapEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.java +index 6ecf7afe5fd7c4c95a17eaed1445d034aa2d5f18..e512a38ccbba93266f0234e3b2fcf7f62693039b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Pig.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java +@@ -254,6 +254,11 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { + } + + entitypigzombie.setPersistenceRequired(); ++ // Paper start ++ if (CraftEventFactory.callEntityZapEvent(this, lightning, entitypigzombie).isCancelled()) { ++ return; ++ } ++ // Paper end + // CraftBukkit start + if (CraftEventFactory.callPigZapEvent(this, lightning, entitypigzombie).isCancelled()) { + return; +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 2f99bdaabe1c1a6a4e1a7e2bd533a63b12818be1..5648a4a4d8511ac8c46c61245a7ff83753a3e51f 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -786,6 +786,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); + Witch entitywitch = (Witch) EntityType.WITCH.create((Level) world); + ++ // Paper start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, lightning, entitywitch).isCancelled()) { ++ return; ++ } ++ // Paper end ++ + entitywitch.moveTo(this.getX(), this.getY(), this.getZ(), this.yRot, this.xRot); + entitywitch.finalizeSpawn(world, world.getCurrentDifficultyAt(entitywitch.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null, (CompoundTag) 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 7fde1bb7587e567270e3f936381c6d361870211f..81af3e2e0964b6e179f92a342efdae943be18b75 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1086,6 +1086,14 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start ++ public static com.destroystokyo.paper.event.entity.EntityZapEvent callEntityZapEvent (Entity entity, Entity lightning, Entity changedEntity) { ++ com.destroystokyo.paper.event.entity.EntityZapEvent event = new com.destroystokyo.paper.event.entity.EntityZapEvent(entity.getBukkitEntity(), (LightningStrike) lightning.getBukkitEntity(), changedEntity.getBukkitEntity()); ++ entity.getBukkitEntity().getServer().getPluginManager().callEvent(event); ++ return event; ++ } ++ // Paper end ++ + public static HorseJumpEvent callHorseJumpEvent(Entity horse, float power) { + HorseJumpEvent event = new HorseJumpEvent((AbstractHorse) horse.getBukkitEntity(), power); + horse.getBukkitEntity().getServer().getPluginManager().callEvent(event); diff --git a/Remapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/Remapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch new file mode 100644 index 0000000000..782f93006e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 12 Nov 2016 23:25:22 -0600 +Subject: [PATCH] Filter bad data from ArmorStand and SpawnEgg items + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 622affa0dc3cc1eadaed400511f2ca2cde3fca2a..e83216be5a00d5b927d8c2fc364551bd3077c974 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -2,6 +2,7 @@ package com.destroystokyo.paper; + + import java.util.List; + ++import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; + +@@ -305,4 +306,12 @@ public class PaperWorldConfig { + private void removeCorruptTEs() { + removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); + } ++ ++ public boolean filterNBTFromSpawnEgg = true; ++ private void fitlerNBTFromSpawnEgg() { ++ filterNBTFromSpawnEgg = getBoolean("filter-nbt-data-from-spawn-eggs-and-related", true); ++ if (!filterNBTFromSpawnEgg) { ++ Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 1d87717cc9002ea202ee2ca614aaa8a4c7ea3cb2..ff8f7e4569a889ead1512b7c9908f9c5cad9eed5 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -270,6 +270,13 @@ public class FallingBlockEntity extends Entity { + @Override + protected void readAdditionalSaveData(CompoundTag tag) { + this.blockState = NbtUtils.readBlockState(tag.getCompound("BlockState")); ++ // Paper start - Block FallingBlocks with Command Blocks ++ // Check mappings on update - dc = "repeating_command_block" - dd = "chain_command_block" ++ final Block b = this.blockState.getBlock(); ++ if (this.level.paperConfig.filterNBTFromSpawnEgg && (b == Blocks.COMMAND_BLOCK || b == Blocks.REPEATING_COMMAND_BLOCK || b == Blocks.CHAIN_COMMAND_BLOCK)) { ++ this.blockState = Blocks.STONE.defaultBlockState(); ++ } ++ // Paper end + this.time = tag.getInt("Time"); + if (tag.contains("HurtEntities", 99)) { + this.hurtEntities = tag.getBoolean("HurtEntities"); diff --git a/Remapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch b/Remapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch new file mode 100644 index 0000000000..be4de8cb23 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: vemacs +Date: Wed, 23 Nov 2016 08:31:45 -0500 +Subject: [PATCH] Cache user authenticator threads + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0597c0c3e881dd43cf91bd3088ed30dfecfe8098..175bf535066afc42de8a3f0d11c46af66f3e3e52 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1388,7 +1388,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + } + +- player.entitiesToRemove.remove(Integer.valueOf(this.entity.getId())); ++ player.removeQueue.remove(Integer.valueOf(this.entity.getId())); + // CraftBukkit end + + if (flag1 && this.trackedPlayerMap.putIfAbsent(player, true) == null) { // Paper +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 3a2356b3e00098d100a179a05316f402390d4e9b..3cde25c2479adcc4ce3014e5ac2ec0710bffeea9 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -4,7 +4,9 @@ import com.google.common.collect.Lists; + import com.mojang.authlib.GameProfile; + import com.mojang.datafixers.util.Either; + import com.mojang.serialization.DataResult; ++import java.util.ArrayDeque; // Paper + import java.util.Collection; ++import java.util.Deque; // Paper + import java.util.Iterator; + import java.util.List; + import java.util.Optional; +@@ -169,7 +171,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public ServerGamePacketListenerImpl connection; + public final MinecraftServer server; + public final ServerPlayerGameMode gameMode; +- public final List entitiesToRemove = Lists.newLinkedList(); ++ public final Deque removeQueue = new ArrayDeque<>(); // Paper + private final PlayerAdvancements advancements; + private final ServerStatsCounter stats; + private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE; +@@ -544,16 +546,23 @@ public class ServerPlayer extends Player implements ContainerListener { + this.containerMenu = this.inventoryMenu; + } + +- while (!this.entitiesToRemove.isEmpty()) { +- int i = Math.min(this.entitiesToRemove.size(), Integer.MAX_VALUE); ++ while (!this.removeQueue.isEmpty()) { ++ int i = Math.min(this.removeQueue.size(), Integer.MAX_VALUE); + int[] aint = new int[i]; +- Iterator iterator = this.entitiesToRemove.iterator(); ++ //Iterator iterator = this.removeQueue.iterator(); // Paper + int j = 0; + +- while (iterator.hasNext() && j < i) { ++ // Paper start ++ /* while (iterator.hasNext() && j < i) { + aint[j++] = (Integer) iterator.next(); + iterator.remove(); ++ } */ ++ ++ Integer integer; ++ while (j < i && (integer = this.removeQueue.poll()) != null) { ++ aint[j++] = integer.intValue(); + } ++ // Paper end + + this.connection.send(new ClientboundRemoveEntitiesPacket(aint)); + } +@@ -1558,7 +1567,14 @@ public class ServerPlayer extends Player implements ContainerListener { + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; + // this.recipeBook.a((RecipeBook) entityplayer.recipeBook); // CraftBukkit +- this.entitiesToRemove.addAll(oldPlayer.entitiesToRemove); ++ // Paper start - Optimize remove queue - vanilla copies player objects, but CB doesn't. This method currently only ++ // Applies to the same player, so we need to not duplicate our removal queue. The rest of this method does "resetting" ++ // type logic so it does need to be called, maybe? This is silly. ++ // this.removeQueue.addAll(entityplayer.removeQueue); ++ if (this.removeQueue != oldPlayer.removeQueue) { ++ this.removeQueue.addAll(oldPlayer.removeQueue); ++ } ++ // Paper end + this.seenCredits = oldPlayer.seenCredits; + this.enteredNetherPosition = oldPlayer.enteredNetherPosition; + this.setShoulderEntityLeft(oldPlayer.getShoulderEntityLeft()); +@@ -1748,13 +1764,13 @@ public class ServerPlayer extends Player implements ContainerListener { + if (entity instanceof Player) { + this.connection.send(new ClientboundRemoveEntitiesPacket(new int[]{entity.getId()})); + } else { +- this.entitiesToRemove.add((Integer) entity.getId()); // CraftBukkit - decompile error ++ this.removeQueue.add((Integer) entity.getId()); // CraftBukkit - decompile error + } + + } + + public void cancelRemoveEntity(Entity entity) { +- this.entitiesToRemove.remove((Integer) entity.getId()); // CraftBukkit - decompile error ++ this.removeQueue.remove((Integer) entity.getId()); // CraftBukkit - decompile error + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch b/Remapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch new file mode 100644 index 0000000000..f3b8068513 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Fri, 25 Nov 2016 13:22:40 +0000 +Subject: [PATCH] Optimise removeQueue + + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 9dbb3bb79ae2de6635f71e5ee5bebeb5e57b624e..e3c1460c580ea348ee6d436018244441a5a1206e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -114,6 +114,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + + } + ++ // Paper start - Cache authenticator threads ++ private static final AtomicInteger threadId = new AtomicInteger(0); ++ private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool( ++ r -> new Thread(r, "User Authenticator #" + threadId.incrementAndGet()) ++ ); ++ // Paper end + // Spigot start + public void initUUID() + { +@@ -193,8 +199,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce)); + } else { + // Spigot start +- new Thread("User Authenticator #" + ServerLoginPacketListenerImpl.UNIQUE_THREAD_ID.incrementAndGet()) { +- ++ // Paper start - Cache authenticator threads ++ authenticatorPool.execute(new Runnable() { + @Override + public void run() { + try { +@@ -205,7 +211,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + gameProfile.getName(), ex); + } + } +- }.start(); ++ }); ++ // Paper end + // Spigot end + } + +@@ -234,7 +241,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + throw new IllegalStateException("Protocol error", cryptographyexception); + } + +- Thread thread = new Thread("User Authenticator #" + ServerLoginPacketListenerImpl.UNIQUE_THREAD_ID.incrementAndGet()) { ++ // Paper start - Cache authenticator threads ++ authenticatorPool.execute(new Runnable() { + public void run() { + GameProfile gameprofile = ServerLoginPacketListenerImpl.this.gameProfile; + +@@ -279,10 +287,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + + return ServerLoginPacketListenerImpl.this.server.getPreventProxyConnections() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; + } +- }; +- +- thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(ServerLoginPacketListenerImpl.LOGGER)); +- thread.start(); ++ }); ++ // Paper end + } + + // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch b/Remapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch new file mode 100644 index 0000000000..360a4a34cc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: willies952002 +Date: Mon, 28 Nov 2016 10:21:52 -0500 +Subject: [PATCH] Allow Reloading of Command Aliases + +Reload the aliases stored in commands.yml + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index bbe0978f56d23b7defce765d381d4a7c20acd75c..9365fd2bcf74755c90c4ae9b550969e97a22c639 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2281,5 +2281,24 @@ public final class CraftServer implements Server { + DefaultPermissions.registerCorePermissions(); + CraftDefaultPermissions.registerCorePermissions(); + } ++ ++ @Override ++ public boolean reloadCommandAliases() { ++ Set removals = getCommandAliases().keySet().stream() ++ .map(key -> key.toLowerCase(java.util.Locale.ENGLISH)) ++ .collect(java.util.stream.Collectors.toSet()); ++ getCommandMap().getKnownCommands().keySet().removeIf(removals::contains); ++ File file = getCommandsConfigFile(); ++ try { ++ commandsConfiguration.load(file); ++ } catch (FileNotFoundException ex) { ++ return false; ++ } catch (IOException | org.bukkit.configuration.InvalidConfigurationException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex); ++ return false; ++ } ++ commandMap.registerServerAliases(); ++ return true; ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch b/Remapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch new file mode 100644 index 0000000000..0ab2cb875a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaBlend +Date: Thu, 8 Sep 2016 08:48:33 -0700 +Subject: [PATCH] Add source to PlayerExpChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index a4a1e836767d0b2b71c3277a28eb72418fa76210..f932fc4f8240b48f8e518af05d1521bc8ff9cbee 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -202,7 +202,7 @@ public class ExperienceOrb extends Entity { + } + + if (this.value > 0) { +- player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, this.value).getAmount()); // CraftBukkit - this.value -> event.getAmount() ++ player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object + } + + this.remove(); +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 81af3e2e0964b6e179f92a342efdae943be18b75..c85fcad33e17c8ae2e4ee5cb873dbd4166fcc7f5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -109,6 +109,7 @@ import org.bukkit.entity.ThrownPotion; + import org.bukkit.entity.Vehicle; + import org.bukkit.entity.Villager; + import org.bukkit.entity.Villager.Profession; ++import org.bukkit.entity.ExperienceOrb; // Paper + import org.bukkit.event.Cancellable; + import org.bukkit.event.Event; + import org.bukkit.event.Event.Result; +@@ -1045,6 +1046,17 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start - Add orb ++ public static PlayerExpChangeEvent callPlayerExpChangeEvent(net.minecraft.world.entity.player.Player entity, net.minecraft.world.entity.ExperienceOrb entityOrb) { ++ Player player = (Player) entity.getBukkitEntity(); ++ ExperienceOrb source = (ExperienceOrb) entityOrb.getBukkitEntity(); ++ int expAmount = source.getExperience(); ++ PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, source, expAmount); ++ Bukkit.getPluginManager().callEvent(event); ++ return event; ++ } ++ // Paper end ++ + public static boolean handleBlockGrowEvent(Level world, BlockPos pos, net.minecraft.world.level.block.state.BlockState block) { + return handleBlockGrowEvent(world, pos, block, 3); + } diff --git a/Remapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch b/Remapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch new file mode 100644 index 0000000000..6845784927 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 16 Dec 2016 16:03:19 -0600 +Subject: [PATCH] Don't let fishinghooks use portals + + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +index 2f67c2065ef29f17f12190b25bd1ea53e1fb55b4..fa078167dd9e0cae80516549eef0e554c13938a3 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +@@ -237,6 +237,11 @@ public class FishingHook extends Projectile { + + this.setDeltaMovement(this.getDeltaMovement().scale(0.92D)); + this.reapplyPosition(); ++ // Paper start - These shouldn't be going through portals ++ if (this.isInsidePortal) { ++ this.remove(); ++ } ++ // Paper end + } + } + diff --git a/Remapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch b/Remapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch new file mode 100644 index 0000000000..0f4f99f50a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Fri, 16 Dec 2016 21:25:39 -0600 +Subject: [PATCH] Add ProjectileCollideEvent + + +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 0dc5792d542658107c9c22c1f920986decd13920..3ce431c1fdf1f5bd62b49f26cca188e939e98efa 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -196,6 +196,17 @@ public abstract class AbstractArrow extends Projectile { + } + } + ++ // Paper start - Call ProjectileCollideEvent ++ // TODO: flag - noclip - call cancelled? ++ if (object instanceof EntityHitResult) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)object); ++ if (event.isCancelled()) { ++ object = null; ++ movingobjectpositionentity = null; ++ } ++ } ++ // Paper end ++ + if (object != null && !flag) { + this.preOnHit((HitResult) object); // CraftBukkit - projectile hit event + this.hasImpulse = true; +diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +index bdff1c57f64d1bf29f2050f06c8b585d395b2c5c..872ff430547276e2a41a48aa07ae63b87ab39e5d 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +@@ -12,6 +12,7 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.level.Level; ++import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit +@@ -71,7 +72,16 @@ public abstract class AbstractHurtingProjectile extends Projectile { + + HitResult movingobjectposition = ProjectileUtil.getHitResult((Entity) this, this::canHitEntity); + +- if (movingobjectposition.getType() != HitResult.Type.MISS) { ++ // Paper start - Call ProjectileCollideEvent ++ if (movingobjectposition instanceof EntityHitResult) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)movingobjectposition); ++ if (event.isCancelled()) { ++ movingobjectposition = null; ++ } ++ } ++ // Paper end ++ ++ if (movingobjectposition != null && movingobjectposition.getType() != HitResult.Type.MISS) { // Paper - add null check in case cancelled + this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + + // CraftBukkit start - Fire ProjectileHitEvent +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java +index 23f255bfa63cd16e2930fc932a2f4df8e522f2dc..becb07cda7388bcf2e987f06557894ae50d70dbf 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java +@@ -13,6 +13,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.BlockHitResult; ++import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + +@@ -57,7 +58,17 @@ public abstract class ThrowableProjectile extends Projectile { + } + + if (movingobjectposition.getType() != HitResult.Type.MISS && !flag) { ++ // Paper start - Call ProjectileCollideEvent ++ if (movingobjectposition instanceof EntityHitResult) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)movingobjectposition); ++ if (event.isCancelled()) { ++ movingobjectposition = null; ++ } ++ } ++ if (movingobjectposition != null) { ++ // Paper end + this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event ++ } // Paper + } + + this.checkInsideBlocks(); +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index c85fcad33e17c8ae2e4ee5cb873dbd4166fcc7f5..3f082b7fd50752728917a7da28cba4cb396a9fdf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1190,6 +1190,16 @@ public class CraftEventFactory { + return CraftItemStack.asNMSCopy(bitem); + } + ++ // Paper start ++ public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, EntityHitResult position) { ++ 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); ++ Bukkit.getPluginManager().callEvent(event); ++ return event; ++ } ++ // Paper end ++ + public static ProjectileLaunchEvent callProjectileLaunchEvent(Entity entity) { + Projectile bukkitEntity = (Projectile) entity.getBukkitEntity(); + ProjectileLaunchEvent event = new ProjectileLaunchEvent(bukkitEntity); diff --git a/Remapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch b/Remapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch new file mode 100644 index 0000000000..f8a0e7b1ea --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 19 Dec 2016 23:07:42 -0500 +Subject: [PATCH] Prevent Pathfinding out of World Border + +This prevents Entities from trying to run outside of the World Border + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index 25bc3adfad956157cef0953e6e632b7b7e352f3a..c3082f5dd64413a47421cb01538bec846bf21d2c 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -148,7 +148,7 @@ public abstract class PathNavigation { + // Paper start - Pathfind event + boolean copiedSet = false; + for (BlockPos possibleTarget : set) { +- if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), ++ if (!getEntity().getCommandSenderWorld().getWorldBorder().isInBounds(possibleTarget) || !new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), // Paper - don't path out of world border + MCUtil.toLocation(getEntity().level, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { + if (!copiedSet) { + copiedSet = true; diff --git a/Remapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch b/Remapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch new file mode 100644 index 0000000000..6a3d81e0fe --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 2 Dec 2016 00:11:43 -0500 +Subject: [PATCH] Optimize World.isLoaded(BlockPosition)Z + +Reduce method invocations for World.isLoaded(BlockPosition)Z + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 5f3d17cb247156fc8aaa7a763e402c2bbb42a7ec..ecb6378a285dff4b34170410387ebb7a8510a6dc 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -305,6 +305,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return chunk == null ? null : chunk.getFluidState(blockposition); + } + ++ public final boolean hasChunkAt(BlockPos pos) { ++ return getChunkIfLoaded(pos.getX() >> 4, pos.getZ() >> 4) != null; // Paper ++ } ++ + public final boolean isLoadedAndInBounds(BlockPos blockposition) { // Paper - final for inline + return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; + } diff --git a/Remapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch b/Remapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch new file mode 100644 index 0000000000..b839110284 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 20 Dec 2016 15:15:11 -0500 +Subject: [PATCH] Bound Treasure Maps to World Border + +Make it so a Treasure Map does not target a structure outside of the +World Border, where players are not even able to reach. + +This also would help the case where a players close to the border, and one +that is outside happens to be closer, but unreachable, yet another reachable +one is in border that would of been missed. + +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index 0846f649dca3422dbab3bb0a4826e27430cc8186..7a728ca96ee2eaf776c391ba8351196a526e18ec 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -36,6 +36,18 @@ public class WorldBorder { + return (double) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ(); + } + ++ // Paper start ++ private final BlockPos.MutableBlockPos mutPos = new BlockPos.MutableBlockPos(); ++ public boolean isBlockInBounds(int chunkX, int chunkZ) { ++ this.mutPos.setValues(chunkX, 64, chunkZ); ++ return this.isInBounds(this.mutPos); ++ } ++ public boolean isChunkInBounds(int chunkX, int chunkZ) { ++ this.mutPos.setValues(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15); ++ return this.isInBounds(this.mutPos); ++ } ++ // Paper end ++ + public boolean isWithinBounds(ChunkPos pos) { + return (double) pos.getMaxBlockX() > this.getMinX() && (double) pos.getMinBlockX() < this.getMaxX() && (double) pos.getMaxBlockZ() > this.getMinZ() && (double) pos.getMinBlockZ() < this.getMaxZ(); + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +index 9f60abfe0a37e30c5528a1ca0546295b00598798..0624b8270bc28c83c5479cd51fa4633ed5c36f44 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +@@ -175,6 +175,7 @@ public abstract class StructureFeature { + int i2 = l + k * k1; + int j2 = i1 + k * l1; + ChunkPos chunkcoordintpair = this.getPotentialFeatureChunk(config, worldSeed, seededrandom, i2, j2); ++ if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper + ChunkAccess ichunkaccess = world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); + StructureStart structurestart = structureAccessor.getStartForFeature(SectionPos.of(ichunkaccess.getPos(), 0), this, ichunkaccess); + diff --git a/Remapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch b/Remapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch new file mode 100644 index 0000000000..2eabafdf57 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 20 Dec 2016 15:26:27 -0500 +Subject: [PATCH] Configurable Cartographer Treasure Maps + +Allow configuring for cartographers to return the same map location + +Also allow turning off treasure maps all together as they can eat up Map ID's +which are limited in quantity. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e83216be5a00d5b927d8c2fc364551bd3077c974..2dc58b9f769ea43b737804456aafab47ecc143b8 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -314,4 +314,14 @@ public class PaperWorldConfig { + Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); + } + } ++ ++ public boolean enableTreasureMaps = true; ++ public boolean treasureMapsAlreadyDiscovered = false; ++ private void treasureMapsAlreadyDiscovered() { ++ enableTreasureMaps = getBoolean("enable-treasure-maps", true); ++ treasureMapsAlreadyDiscovered = getBoolean("treasure-maps-return-already-discovered", false); ++ if (treasureMapsAlreadyDiscovered) { ++ log("Treasure Maps will return already discovered locations"); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +index fd1b84baae5f333c58dbbdcbfaa9198328f0961d..7d490e1be772be22c3ab75c7e356465183a5c6b1 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java ++++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +@@ -124,7 +124,8 @@ public class VillagerTrades { + return null; + } else { + ServerLevel worldserver = (ServerLevel) entity.level; +- BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, entity.blockPosition(), 100, true); ++ if (!worldserver.paperConfig.enableTreasureMaps) return null; // Paper ++ BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, entity.blockPosition(), 100, !worldserver.paperConfig.treasureMapsAlreadyDiscovered); // Paper + + if (blockposition != null) { + ItemStack itemstack = MapItem.create(worldserver, blockposition.getX(), blockposition.getZ(), (byte) 2, true, true); +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java +index a3ce120b0da62f9be938c58c3414ce997f5d30ea..81a8331bfdf30da6ea69952ae42d3c77a2103bfd 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java +@@ -64,7 +64,16 @@ public class ExplorationMapFunction extends LootItemConditionalFunction { + + if (vec3d != null) { + ServerLevel worldserver = context.getLevel(); +- BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, new BlockPos(vec3d), this.searchRadius, this.skipKnownStructures); ++ // Paper start ++ if (!worldserver.paperConfig.enableTreasureMaps) { ++ /* ++ * NOTE: I fear users will just get a plain map as their "treasure" ++ * This is preferable to disrespecting the config. ++ */ ++ return stack; ++ } ++ // Paper end ++ BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, new BlockPos(vec3d), this.searchRadius, !worldserver.paperConfig.treasureMapsAlreadyDiscovered && this.skipKnownStructures); // Paper + + if (blockposition != null) { + ItemStack itemstack1 = MapItem.create(worldserver, blockposition.getX(), blockposition.getZ(), this.zoom, true, true); diff --git a/Remapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch b/Remapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch new file mode 100644 index 0000000000..329afa7401 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Dec 2016 03:48:29 -0500 +Subject: [PATCH] Optimize ItemStack.isEmpty() + +Remove hashMap lookup every check, simplify code to remove ternary + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 123025c6dc9a2eea56c7db5cb508cdfd7c6cc97b..a0815c0d7f68f345dc48c73b8253de637c7a3e0f 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -206,7 +206,7 @@ public final class ItemStack { + } + + public boolean isEmpty() { +- return this == ItemStack.EMPTY ? true : (this.getItem() != null && this.getItem() != Items.AIR ? this.count <= 0 : true); ++ return this == ItemStack.NULL_ITEM || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper + } + + public ItemStack split(int amount) { diff --git a/Remapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch b/Remapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch new file mode 100644 index 0000000000..970e858ba4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 21 Dec 2016 11:47:25 -0600 +Subject: [PATCH] Add API methods to control if armour stands can move + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 09d39b73e8a3987e58a502bd914a6451b807421b..46f0ebfc99352ec8b64bdff2c6bb8d17ecfeb619 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -1,6 +1,5 @@ + package net.minecraft.world.entity; + +-import PathfinderGoalFloat; + import com.google.common.collect.Maps; + import java.util.Arrays; + import java.util.Iterator; +@@ -39,6 +38,7 @@ import net.minecraft.world.entity.ai.control.BodyRotationControl; + import net.minecraft.world.entity.ai.control.JumpControl; + import net.minecraft.world.entity.ai.control.LookControl; + import net.minecraft.world.entity.ai.control.MoveControl; ++import net.minecraft.world.entity.ai.goal.FloatGoal; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.goal.GoalSelector; + import net.minecraft.world.entity.ai.navigation.GroundPathNavigation; +@@ -47,6 +47,8 @@ import net.minecraft.world.entity.ai.sensing.Sensing; + import net.minecraft.world.entity.decoration.HangingEntity; + import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; + import net.minecraft.world.entity.item.ItemEntity; ++import net.minecraft.world.entity.monster.Blaze; ++import net.minecraft.world.entity.monster.EnderMan; + import net.minecraft.world.entity.monster.Enemy; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.Boat; +@@ -97,7 +99,7 @@ public abstract class Mob extends LivingEntity { + private final BodyRotationControl bodyRotationControl; + protected PathNavigation navigation; + public GoalSelector goalSelector; +- @Nullable public PathfinderGoalFloat goalFloat; // Paper ++ @Nullable public FloatGoal goalFloat; // Paper + public GoalSelector targetSelector; + private LivingEntity target; + private final Sensing sensing; +@@ -789,7 +791,7 @@ public abstract class Mob extends LivingEntity { + if (goalFloat.validConditions()) goalFloat.update(); + this.getJumpControl().jumpIfSet(); + } +- if ((this instanceof EntityBlaze || this instanceof EntityEnderman) && isInWaterOrRainOrBubble()) { ++ if ((this instanceof Blaze || this instanceof EnderMan) && isInWaterOrRainOrBubble()) { + hurt(DamageSource.DROWN, 1.0F); + } + return; +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 438dd75e3adffc395960b34b8bb26cbc07a4291e..8b6ec9ddf0d47bf4369b247e764f75893ab15781 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -26,6 +26,7 @@ import net.minecraft.world.entity.HumanoidArm; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.entity.vehicle.AbstractMinecart; +@@ -75,6 +76,7 @@ public class ArmorStand extends LivingEntity { + public Rotations rightArmPose; + public Rotations leftLegPose; + public Rotations rightLegPose; ++ public boolean canMove = true; // Paper + + public ArmorStand(EntityType type, Level world) { + super(type, world); +@@ -858,4 +860,13 @@ public class ArmorStand extends LivingEntity { + private EntityDimensions getDimensionsMarker(boolean flag) { + return flag ? ArmorStand.MARKER_DIMENSIONS : (this.isBaby() ? ArmorStand.BABY_DIMENSIONS : this.getType().getDimensions()); + } ++ ++ // Paper start ++ @Override ++ public void move(MoverType type, Vec3 movement) { ++ if (this.canMove) { ++ super.move(type, movement); ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +index 6b292162fb8c6416b1637b7b83e5113f6a35dbac..16f996d505b96da8a40c7709214ebbd2a0d0d9f3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +@@ -228,4 +228,15 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public boolean hasEquipmentLock(EquipmentSlot equipmentSlot, LockType lockType) { + return (getHandle().disabledSlots & (1 << CraftEquipmentSlot.getNMS(equipmentSlot).getFilterFlag() + lockType.ordinal() * 8)) != 0; + } ++ // Paper start ++ @Override ++ public boolean canMove() { ++ return getHandle().canMove; ++ } ++ ++ @Override ++ public void setCanMove(boolean move) { ++ getHandle().canMove = move; ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch b/Remapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch new file mode 100644 index 0000000000..aa2398aa87 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Tue, 27 Dec 2016 01:57:57 +0000 +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 3cde25c2479adcc4ce3014e5ac2ec0710bffeea9..4ff66138fa43cf932b95d6d3dc050a9cd7b28ad4 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -2066,8 +2066,8 @@ public class ServerPlayer extends Player implements ContainerListener { + } + + @Override +- public boolean isImmobile() { +- return super.isImmobile() || !getBukkitEntity().isOnline(); ++ protected boolean isImmobile() { ++ return super.isImmobile() || (this.connection != null && this.connection.isDisconnected()); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 1b92c669bbe69bcc07a554b7b43ee99bfebc1af4..ecc393ad94332ec2a59d29f30bd60bade4e1f18e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2818,7 +2818,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + + public final boolean isDisconnected() { +- return !this.player.joining && !this.connection.isConnected(); ++ return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper + } + // CraftBukkit end + diff --git a/Remapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch b/Remapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch new file mode 100644 index 0000000000..416d50b18b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 27 Dec 2016 15:02:42 -0500 +Subject: [PATCH] String based Action Bar API + + +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index 67fa685f4b8de3eae1431c0de399c246678b542a..7b36274718b7cce24ac00530697f145648d52590 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -58,7 +58,7 @@ public class Util { + private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main"); + private static final ExecutorService IO_POOL = makeIoExecutor(); + public static LongSupplier timeSource = System::nanoTime; +- public static final UUID NIL_UUID = new UUID(0L, 0L); ++ public static final UUID NIL_UUID = new UUID(0L, 0L); public static final UUID getNullUUID() {return NIL_UUID;} // Paper OBFHELPER + private static final Logger LOGGER = LogManager.getLogger(); + + public static Collector, ?, Map> toMap() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index fc19b4cacd223b928fbdf922b828beaed630bf2e..d6d4e5ab7551f802dc2d3ab055d340d471ed0bc2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -242,6 +242,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + // Paper start ++ @Override ++ public void sendActionBar(BaseComponent[] message) { ++ if (getHandle().connection == null) return; ++ getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.ACTIONBAR, message, -1, -1, -1)); ++ } ++ ++ @Override ++ public void sendActionBar(String message) { ++ if (getHandle().connection == null || message == null || message.isEmpty()) return; ++ getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.ACTIONBAR, CraftChatMessage.fromStringOrNull(message))); ++ } ++ ++ @Override ++ public void sendActionBar(char alternateChar, String message) { ++ if (message == null || message.isEmpty()) return; ++ sendActionBar(org.bukkit.ChatColor.translateAlternateColorCodes(alternateChar, message)); ++ } ++ + @Override + public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { + if (header != null) { diff --git a/Remapped-Spigot-Server-Patches/0132-Firework-API-s.patch b/Remapped-Spigot-Server-Patches/0132-Firework-API-s.patch new file mode 100644 index 0000000000..e3dc3d3182 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0132-Firework-API-s.patch @@ -0,0 +1,124 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 28 Dec 2016 07:18:33 +0100 +Subject: [PATCH] Firework API's + + +diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java +index 4c8f249e45e5deb7628997d4dbd9dab613ac5241..a91bf94ed9f2f353a685194fc91c4b101ccc1232 100644 +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -153,6 +153,7 @@ public class CompoundTag implements Tag { + return NbtUtils.loadUUID(this.get(key)); + } + ++ public final boolean hasUUID(String s) { return this.hasUUID(s); } // Paper - OBFHELPER + public boolean hasUUID(String key) { + Tag nbtbase = this.get(key); + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +index 28a2c6a0fbc8b4c38f3899698504d8ca0d7ba3af..5669be107b580075fdffbcbb490513593a57fc9f 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +@@ -37,7 +37,8 @@ public class FireworkRocketEntity extends Projectile { + public static final EntityDataAccessor DATA_SHOT_AT_ANGLE = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.BOOLEAN); + private int life; + public int lifetime; +- private LivingEntity attachedToEntity; ++ public LivingEntity attachedToEntity; // Paper - public ++ public java.util.UUID spawningEntity; // Paper + + public FireworkRocketEntity(EntityType type, Level world) { + super(type, world); +@@ -284,6 +285,11 @@ public class FireworkRocketEntity extends Projectile { + } + + tag.putBoolean("ShotAtAngle", (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE)); ++ // Paper start ++ if (this.spawningEntity != null) { ++ tag.setUUID("SpawningEntity", this.spawningEntity); ++ } ++ // Paper end + } + + @Override +@@ -300,7 +306,11 @@ public class FireworkRocketEntity extends Projectile { + if (tag.contains("ShotAtAngle")) { + this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, tag.getBoolean("ShotAtAngle")); + } +- ++ // Paper start ++ if (tag.hasUUID("SpawningEntity")) { ++ this.spawningEntity = tag.getUUID("SpawningEntity"); ++ } ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java +index 8a358872d3c8357775451e7dffe267cf9121f211..e1e58b7035e6dbafdad0a04cc5333464fc4febb8 100644 +--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java ++++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java +@@ -205,6 +205,7 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + + if (flag1) { + object = new FireworkRocketEntity(world, projectile, shooter, shooter.getX(), shooter.getEyeY() - 0.15000000596046448D, shooter.getZ(), true); ++ ((FireworkRocketEntity) object).spawningEntity = shooter.getUUID(); // Paper + } else { + object = getArrow(world, shooter, crossbow, projectile); + if (creative || simulated != 0.0F) { +diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index d3a045fc99ef77fa0905aac7c73a2e84772c73cf..dba52063d402eb2371441fa244b730a3313444fc 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -27,6 +27,7 @@ public class FireworkRocketItem extends Item { + Vec3 vec3d = context.getClickLocation(); + Direction enumdirection = context.getClickedFace(); + FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, context.getPlayer(), vec3d.x + (double) enumdirection.getStepX() * 0.15D, vec3d.y + (double) enumdirection.getStepY() * 0.15D, vec3d.z + (double) enumdirection.getStepZ() * 0.15D, itemstack); ++ entityfireworks.spawningEntity = context.getPlayer().getUUID(); // Paper + + world.addFreshEntity(entityfireworks); + itemstack.shrink(1); +@@ -41,7 +42,11 @@ public class FireworkRocketItem extends Item { + ItemStack itemstack = user.getItemInHand(hand); + + if (!world.isClientSide) { +- world.addFreshEntity(new FireworkRocketEntity(world, itemstack, user)); ++ // Paper start ++ final FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, itemstack, user); ++ entityfireworks.spawningEntity = user.getUUID(); ++ world.addFreshEntity(entityfireworks); ++ // Paper end + if (!user.abilities.instabuild) { + itemstack.shrink(1); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +index 5901a53b25449430ed02a80b022f83755f83a440..0fbbdd6e3fda3f834d0b0d68d868dbff1aebb673 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +@@ -1,6 +1,7 @@ + package org.bukkit.craftbukkit.entity; + + import java.util.Random; ++import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.projectile.FireworkRocketEntity; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -78,4 +79,17 @@ public class CraftFirework extends CraftProjectile implements Firework { + public void setShotAtAngle(boolean shotAtAngle) { + getHandle().getEntityData().set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, shotAtAngle); + } ++ ++ // Paper start ++ @Override ++ public java.util.UUID getSpawningEntity() { ++ return getHandle().spawningEntity; ++ } ++ ++ @Override ++ public org.bukkit.entity.LivingEntity getBoostedEntity() { ++ LivingEntity boostedEntity = getHandle().attachedToEntity; ++ return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null; ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch b/Remapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch new file mode 100644 index 0000000000..98fb21f40b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 31 Dec 2016 21:44:50 -0500 +Subject: [PATCH] PlayerTeleportEndGatewayEvent + +Allows you to access the Gateway being used in a teleport event + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +index 07d89af8111673087b0534ca9fac043d3e89662b..2c974f9801d209907733bed8e6c4c9ef46e2b610 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -10,6 +10,7 @@ import net.minecraft.data.worldgen.Features; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; +@@ -177,7 +178,7 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements + location.setPitch(player.getLocation().getPitch()); + location.setYaw(player.getLocation().getYaw()); + +- PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); ++ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(level, this.getBlockPos()).getBlock())); // Paper + Bukkit.getPluginManager().callEvent(teleEvent); + if (teleEvent.isCancelled()) { + return; diff --git a/Remapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch b/Remapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch new file mode 100644 index 0000000000..7b2dc85ab1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 Jan 2017 15:24:46 -0500 +Subject: [PATCH] Provide E/TE/Chunk count stat methods + +Provides counts without the ineffeciency of using .getEntities().size() +which creates copy of the collections. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index ca189e5d160d2655175c9fab9366ff93bded2fee..6782888f7df4eea4e6378ee850424e14c5136afd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -264,6 +264,48 @@ public class CraftWorld implements World { + private int waterAmbientSpawn = -1; + private int ambientSpawn = -1; + ++ // Paper start - Provide fast information methods ++ public int getEntityCount() { ++ int ret = 0; ++ for (net.minecraft.world.entity.Entity entity : world.entitiesById.values()) { ++ if (entity.isChunkLoaded()) { ++ ++ret; ++ } ++ } ++ return ret; ++ } ++ public int getTileEntityCount() { ++ // We don't use the full world tile entity list, so we must iterate chunks ++ Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; ++ int size = 0; ++ for (ChunkHolder playerchunk : chunks.values()) { ++ net.minecraft.world.level.chunk.LevelChunk chunk = playerchunk.getTickingChunk(); ++ if (chunk == null) { ++ continue; ++ } ++ size += chunk.blockEntities.size(); ++ } ++ return size; ++ } ++ public int getTickableTileEntityCount() { ++ return world.tickableBlockEntities.size(); ++ } ++ public int getChunkCount() { ++ int ret = 0; ++ ++ for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { ++ if (chunkHolder.getTickingChunk() != null) { ++ ++ret; ++ } ++ } ++ ++ return ret; ++ } ++ public int getPlayerCount() { ++ return world.players.size(); ++ } ++ // Paper end ++ + private static final Random rand = new Random(); + + public CraftWorld(ServerLevel world, ChunkGenerator gen, Environment env) { diff --git a/Remapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch b/Remapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch new file mode 100644 index 0000000000..09ab2be15a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 Jan 2017 15:41:58 -0500 +Subject: [PATCH] Enforce Sync Player Saves + +Saving players async is extremely dangerous. This will force it to main +the same way we handle async chunk loads. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 59fb19cfebe4f488fd02f02db31029d44b65e408..cebf536e9d16d44c4b2a91b5b4be053cd7f44045 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1043,11 +1043,13 @@ public abstract class PlayerList { + } + + public void saveAll() { ++ MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main + MinecraftTimings.savePlayers.startTiming(); // Paper + for (int i = 0; i < this.players.size(); ++i) { +- this.save((ServerPlayer) this.players.get(i)); ++ this.savePlayerFile((EntityPlayer) this.players.get(i)); + } + MinecraftTimings.savePlayers.stopTiming(); // Paper ++ return null; }); // Paper - ensure main + } + + public UserWhiteList getWhiteList() { diff --git a/Remapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch b/Remapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch new file mode 100644 index 0000000000..da9f57d585 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Sun, 8 Jan 2017 04:31:36 +0000 +Subject: [PATCH] Don't allow entities to ride themselves - #572 + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index c3aece8e5001828edea304b2a8377e9a28b34cfe..a9ed1c3ce6361a86dd58501f5b0ce5d6bbfb8adf 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2045,6 +2045,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + protected boolean addPassenger(Entity entity) { // CraftBukkit ++ if (entity == this) throw new IllegalArgumentException("Entities cannot become a passenger of themselves"); // Paper - issue 572 + if (entity.getVehicle() != this) { + throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)"); + } else { diff --git a/Remapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/Remapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch new file mode 100644 index 0000000000..44aa5bf7e5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch @@ -0,0 +1,332 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 16:31:46 -0500 +Subject: [PATCH] ExperienceOrbs API for Reason/Source/Triggering player + +Adds lots of information about why this orb exists. + +Replaces isFromBottle() with logic that persists entity reloads too. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index ed4309d5e567b20fd4aa025e7c82d8943bf1d8e1..26ce794cb8d089c03fab5dd0a0c910783d10b72e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -409,7 +409,7 @@ public class ServerPlayerGameMode { + + // Drop event experience + if (flag && event != null) { +- iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop()); ++ iblockdata.getBlock().dropExperience(this.level, pos, event.getExpToDrop(), this.player); // Paper + } + + return true; +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index f932fc4f8240b48f8e518af05d1521bc8ff9cbee..3ddb0a9f15c920c9a2080f76edfda0504c1e287a 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -30,13 +30,63 @@ public class ExperienceOrb extends Entity { + public int value; + private Player followingPlayer; + private int followingTime; ++ // Paper start ++ public java.util.UUID sourceEntityId; ++ public java.util.UUID triggerEntityId; ++ public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; ++ ++ private void loadPaperNBT(CompoundTag nbttagcompound) { ++ if (!nbttagcompound.contains("Paper.ExpData", 10)) { // 10 = compound ++ return; ++ } ++ CompoundTag comp = nbttagcompound.getCompound("Paper.ExpData"); ++ if (comp.hasUUID("source")) { ++ this.sourceEntityId = comp.getUUID("source"); ++ } ++ if (comp.hasUUID("trigger")) { ++ this.triggerEntityId = comp.getUUID("trigger"); ++ } ++ if (comp.contains("reason")) { ++ String reason = comp.getString("reason"); ++ try { ++ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason); ++ } catch (Exception e) { ++ this.level.getCraftServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason); ++ } ++ } ++ } ++ private void savePaperNBT(CompoundTag nbttagcompound) { ++ CompoundTag comp = new CompoundTag(); ++ if (this.sourceEntityId != null) { ++ comp.setUUID("source", this.sourceEntityId); ++ } ++ if (this.triggerEntityId != null) { ++ comp.setUUID("trigger", triggerEntityId); ++ } ++ if (this.spawnReason != null && this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) { ++ comp.putString("reason", this.spawnReason.name()); ++ } ++ nbttagcompound.put("Paper.ExpData", comp); ++ } + + public ExperienceOrb(Level world, double x, double y, double z, int amount) { ++ this(world, x, y, z, amount, null, null); ++ } ++ ++ public EntityExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { ++ this(world, d0, d1, d2, i, reason, triggerId, null); ++ } ++ ++ public EntityExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { + this(EntityType.EXPERIENCE_ORB, world); +- this.setPos(x, y, z); ++ this.sourceEntityId = sourceId != null ? sourceId.getUUID() : null; ++ this.triggerEntityId = triggerId != null ? triggerId.getUUID() : null; ++ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; ++ // Paper end ++ this.setPos(d0, d1, d2); + this.yRot = (float) (this.random.nextDouble() * 360.0D); + this.setDeltaMovement((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D); +- this.value = amount; ++ this.value = i; + } + + public ExperienceOrb(EntityType type, Level world) { +@@ -167,6 +217,7 @@ public class ExperienceOrb extends Entity { + tag.putShort("Health", (short) this.health); + tag.putShort("Age", (short) this.age); + tag.putShort("Value", (short) this.value); ++ this.savePaperNBT(tag); // Paper + } + + @Override +@@ -174,6 +225,7 @@ public class ExperienceOrb extends Entity { + this.health = tag.getShort("Health"); + this.age = tag.getShort("Age"); + this.value = tag.getShort("Value"); ++ this.loadPaperNBT(tag); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 1131d86080b3100437aa18a00c6277fcea4b7ea8..c6aa5328907f85cd210b1c20ff407e60d9b03349 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1591,7 +1591,8 @@ public abstract class LivingEntity extends Entity { + int j = ExperienceOrb.getExperienceValue(i); + + i -= j; +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); ++ LivingEntity attacker = lastHurtByPlayer != null ? lastHurtByPlayer : lastHurtByMob; // Paper ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this)); // Paper + } + this.expToDrop = 0; + } +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 ab2a19554aa1541e924104a70364f957ff8b33f9..e0f2a70870ff97ae2e8f216a202787bbcba6c6a9 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Animal.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java +@@ -260,7 +260,7 @@ public abstract class Animal extends AgableMob { + if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + // CraftBukkit start - use event experience + if (experience > 0) { +- worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience)); ++ worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper + } + // CraftBukkit end + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java +index 83fcfd888a335e3c054174e1f55e92fea878f7ab..c2d98222f575d7383e4c040730f6d531bdb0d7b6 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java +@@ -1306,7 +1306,7 @@ public class Fox extends Animal { + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + // CraftBukkit start - use event experience + if (experience > 0) { +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityfox)); // Paper + } + // CraftBukkit end + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +index 2ae59200ed67ab68645b569ba03839e8cedc9aa8..c54f4b83b9f2fdb15ddb363be0a179a05eb3693b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +@@ -561,7 +561,7 @@ public class Turtle extends Animal { + Random random = this.animal.getRandom(); + + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), random.nextInt(7) + 1)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), random.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper; + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index 39298b69918da890c3faa516f80d1a69adb88fe2..ae3cf71f14526e1f356216dfaa899c8f5083d46d 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -661,7 +661,7 @@ public class EnderDragon extends Mob implements Enemy { + int j = ExperienceOrb.getExperienceValue(amount); + + amount -= j; +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this)); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 5648a4a4d8511ac8c46c61245a7ff83753a3e51f..a66fab2e04a5d87ced139ed15d2434c5ffcec695 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -599,7 +599,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + } + + if (offer.shouldRewardExp()) { +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTradingPlayer(), this)); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +index 15570b9ba2443ce8c6f48dfbc13cdf45de8b45ac..69d92590d265abe8a04d8bf48bbe9a6ae606ae50 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -188,7 +188,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + if (offer.shouldRewardExp()) { + int i = 3 + this.random.nextInt(4); + +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTradingPlayer(), this)); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +index fa078167dd9e0cae80516549eef0e554c13938a3..7bff012f3cd4458673ee02e5f5f830fc0ef983a3 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +@@ -500,7 +500,7 @@ public class FishingHook extends Projectile { + this.level.addFreshEntity(entityitem); + // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() + if (playerFishEvent.getExpToDrop() > 0) { +- entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop())); ++ entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper + } + // CraftBukkit end + if (itemstack1.getItem().is((Tag) ItemTags.FISHES)) { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java +index 85b8f8f52c5035054ad9f665fce735260a54c270..42c7371355b6e36e31daf055317f015240761b8b 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java +@@ -54,7 +54,7 @@ public class ThrownExperienceBottle extends ThrowableItemProjectile { + int j = ExperienceOrb.getExperienceValue(i); + + i -= j; +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, getOwner(), this)); // Paper + } + + this.remove(); +diff --git a/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java b/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java +index ea6e1a96bd1fa9fbb87f65a169aa1e5af0589f34..5b9111d502bc12ab9e5c37e4d66c21aa37007b53 100644 +--- a/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java ++++ b/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java +@@ -7,7 +7,7 @@ import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; + + public class FurnaceResultSlot extends Slot { + +- private final Player player; ++ private final Player player; public final Player getPlayer() { return this.player; } // Paper OBFHELPER + private int removeCount; + + public FurnaceResultSlot(Player player, Container inventory, int index, int x, int y) { +diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +index e8bc37e1f7aebd192f048d7b056a41c50ceef9f5..e9e830117fe3e4e02a51eef8671a3d3b48c2858e 100644 +--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -93,7 +93,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { + int k = ExperienceOrb.getExperienceValue(j); + + j -= k; +- world.addFreshEntity(new ExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k)); ++ world.addFreshEntity(new ExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k, org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player)); // Paper + } + + world.levelEvent(1042, blockposition, 0); +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 2ae786b8fc6da19ca2a40252b0606f9e06d31ded..9d2e4adddae481735053c64eec0ee7259c61f1a4 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -267,13 +267,13 @@ public class Block extends BlockBehaviour implements ItemLike { + } + } + +- public void popExperience(ServerLevel world, BlockPos pos, int size) { +- if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { +- while (size > 0) { +- int j = ExperienceOrb.getExperienceValue(size); ++ public void dropExperience(ServerLevel worldserver, BlockPos blockposition, int i, net.minecraft.server.level.ServerPlayer player) { // Paper ++ if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { ++ while (i > 0) { ++ int j = ExperienceOrb.getExperienceValue(i); + +- size -= j; +- world.addFreshEntity(new ExperienceOrb(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, j)); ++ i -= j; ++ worldserver.addFreshEntity(new ExperienceOrb(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player)); // Paper + } + } + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 7a2554c5cd18e0c5e482ba8ba68a098d533b6a4f..8c55c1d88ef2e20e82bcdae0b9b3d381e562051f 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -601,7 +601,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + int k = ExperienceOrb.getExperienceValue(j); + + j -= k; +- world.addFreshEntity(new ExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k)); ++ world.addFreshEntity(new ExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman)); // Paper + } + + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 6782888f7df4eea4e6378ee850424e14c5136afd..88658d4deacc29128c537e2e02fdc8f684090a2c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1817,7 +1817,7 @@ public class CraftWorld implements World { + } else if (TNTPrimed.class.isAssignableFrom(clazz)) { + entity = new PrimedTnt(world, x, y, z, null); + } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { +- entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0); ++ entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper + } else if (LightningStrike.class.isAssignableFrom(clazz)) { + entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(world); + } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +index 3b450d97302bab30cdb975c8332b81318470503e..d5b8fd76ec3bd7d2621231480eb3e694a90aa037 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import SpawnReason; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.ExperienceOrb; +@@ -19,6 +20,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { + getHandle().value = value; + } + ++ // Paper start ++ public java.util.UUID getTriggerEntityId() { ++ return getHandle().triggerEntityId; ++ } ++ public java.util.UUID getSourceEntityId() { ++ return getHandle().sourceEntityId; ++ } ++ public SpawnReason getSpawnReason() { ++ return getHandle().spawnReason; ++ } ++ // Paper end ++ + @Override + public net.minecraft.world.entity.ExperienceOrb getHandle() { + return (net.minecraft.world.entity.ExperienceOrb) entity; diff --git a/Remapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch b/Remapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch new file mode 100644 index 0000000000..7b28bfe328 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 22 Jan 2017 18:07:56 -0500 +Subject: [PATCH] Cap Entity Collisions + +Limit a single entity to colliding a max of configurable times per tick. +This will alleviate issues where living entities are hoarded in 1x1 pens + +This is not tied to the maxEntityCramming rule. Cramming will still apply +just as it does in Vanilla, but entity pushing logic will be capped. + +You can set this to 0 to disable collisions. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2dc58b9f769ea43b737804456aafab47ecc143b8..c611b5a63498f5ad1f50a75ccd5d7299e27df7e3 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -324,4 +324,10 @@ public class PaperWorldConfig { + log("Treasure Maps will return already discovered locations"); + } + } ++ ++ public int maxCollisionsPerEntity; ++ private void maxEntityCollision() { ++ maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); ++ log( "Max Entity Collisions: " + maxCollisionsPerEntity ); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a9ed1c3ce6361a86dd58501f5b0ce5d6bbfb8adf..a017fa55002d6674124befa3f6e81eb70c9ce8f7 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -267,6 +267,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; + public long activatedTick = Integer.MIN_VALUE; ++ protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index c6aa5328907f85cd210b1c20ff407e60d9b03349..3908f54e2216c635d47f8256bac455e7207a5bc6 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -2900,8 +2900,11 @@ public abstract class LivingEntity extends Entity { + } + } + +- for (j = 0; j < list.size(); ++j) { ++ numCollisions = Math.max(0, numCollisions - level.paperConfig.maxCollisionsPerEntity); // Paper ++ for (j = 0; j < list.size() && numCollisions < level.paperConfig.maxCollisionsPerEntity; ++j) { // Paper + Entity entity = (Entity) list.get(j); ++ entity.numCollisions++; // Paper ++ numCollisions++; // Paper + + this.doPush(entity); + } diff --git a/Remapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch b/Remapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch new file mode 100644 index 0000000000..db58842a96 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 5 Feb 2017 00:04:04 -0500 +Subject: [PATCH] Remove CraftScheduler Async Task Debugger + +I have not once ever seen this system help debug a crash. +One report of a suspected memory leak with the system. + +This adds additional overhead to asynchronous task dispatching + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 9b6d9373abb59a30c2835ca891282d07559281f5..0e0f361c3af363539d5d1d865603114bdb84fd67 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -430,7 +430,7 @@ public class CraftScheduler implements BukkitScheduler { + } + parsePending(); + } else { +- debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); ++ //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper + executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper + // We don't need to parse pending + // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) +@@ -447,7 +447,7 @@ public class CraftScheduler implements BukkitScheduler { + pending.addAll(temp); + temp.clear(); + MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); +- debugHead = debugHead.getNextHead(currentTick); ++ //debugHead = debugHead.getNextHead(currentTick); // Paper + } + + private void addTask(final CraftTask task) { +@@ -507,10 +507,15 @@ public class CraftScheduler implements BukkitScheduler { + + @Override + public String toString() { ++ // Paper start ++ return ""; ++ /* + int debugTick = currentTick; + StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - RECENT_TICKS).append('-').append(debugTick).append('{'); + debugHead.debugTo(string); + return string.append('}').toString(); ++ */ ++ // Paper end + } + + @Deprecated diff --git a/Remapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/Remapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch new file mode 100644 index 0000000000..740c39b430 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Tue, 7 Feb 2017 16:55:35 -0600 +Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 175bf535066afc42de8a3f0d11c46af66f3e3e52..3b6f35b695117bd2b0c71b994efc55fa1084eddc 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -119,7 +119,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private final PlayerMap playerMap; + public final Int2ObjectMap entityMap; + private final Long2ByteMap chunkTypeCache; +- private final Queue unloadQueue; ++ private final Queue unloadQueue; private final Queue getUnloadQueueTasks() { return this.unloadQueue; } // Paper - OBFHELPER + private int viewDistance; + + // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() +@@ -177,7 +177,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerMap = new PlayerMap(); + this.entityMap = new Int2ObjectOpenHashMap(); + this.chunkTypeCache = new Long2ByteOpenHashMap(); +- this.unloadQueue = Queues.newConcurrentLinkedQueue(); ++ this.unloadQueue = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size() + this.structureManager = definedstructuremanager; + this.storageFolder = convertable_conversionsession.getDimensionPath(worldserver.dimension()); + this.level = worldserver; +@@ -435,7 +435,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Spigot start + org.spigotmc.SlackActivityAccountant activityAccountant = this.level.getServer().slackActivityAccountant; + activityAccountant.startActivity(0.5); +- int targetSize = (int) (this.toDrop.size() * UNLOAD_QUEUE_RESIZE_FACTOR); ++ int targetSize = Math.min(this.toDrop.size() - 100, (int) (this.toDrop.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive + // Spigot end + while (longiterator.hasNext()) { // Spigot + long j = longiterator.nextLong(); +@@ -457,7 +457,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + Runnable runnable; + +- while ((shouldKeepTicking.getAsBoolean() || this.unloadQueue.size() > 2000) && (runnable = (Runnable) this.unloadQueue.poll()) != null) { ++ int queueTarget = Math.min(this.getUnloadQueueTasks().size() - 100, (int) (this.getUnloadQueueTasks().size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well ++ while ((shouldKeepTicking.getAsBoolean() || this.getUnloadQueueTasks().size() > queueTarget) && (runnable = (Runnable)this.getUnloadQueueTasks().poll()) != null) { // Paper - Target this queue as well + runnable.run(); + } + diff --git a/Remapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch b/Remapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch new file mode 100644 index 0000000000..d8f5fab54d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 18 Feb 2017 19:29:58 -0600 +Subject: [PATCH] Do not let armorstands drown + + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 3908f54e2216c635d47f8256bac455e7207a5bc6..c1786fcabeaee5732e9197db04268c5c4e164339 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -335,6 +335,7 @@ public abstract class LivingEntity extends Entity { + super.checkFallDamage(heightDifference, onGround, landedState, landedPosition); + } + ++ public boolean canBreatheUnderwater() { return this.canBreatheUnderwater(); } // Paper - OBFHELPER + public boolean canBreatheUnderwater() { + return this.getMobType() == MobType.UNDEAD; + } +@@ -378,7 +379,7 @@ public abstract class LivingEntity extends Entity { + + if (this.isAlive()) { + if (this.isEyeInFluid((Tag) FluidTags.WATER) && !this.level.getBlockState(new BlockPos(this.getX(), this.getEyeY(), this.getZ())).is(Blocks.BUBBLE_COLUMN)) { +- if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { ++ if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { // Paper - use OBFHELPER so it can be overridden + this.setAirSupply(this.decreaseAirSupply(this.getAirSupply())); + if (this.getAirSupply() == -20) { + this.setAirSupply(0); +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 8b6ec9ddf0d47bf4369b247e764f75893ab15781..59239e202e8e99870ce3be515d2f040ad9786892 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -868,5 +868,10 @@ public class ArmorStand extends LivingEntity { + super.move(type, movement); + } + } ++ ++ @Override ++ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization ++ return true; ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch b/Remapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch new file mode 100644 index 0000000000..761e1f8b83 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch @@ -0,0 +1,307 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 12 May 2017 23:34:11 -0500 +Subject: [PATCH] Properly handle async calls to restart the server + +The watchdog thread calls the server restart function asynchronously. Prior to +this change, it attempted to do several non-safe operations from the watchdog +thread, rather than the main. Specifically, because of a separate upstream change, +it causes player entities to be ticked asynchronously, among other things. + +This is dangerous. + +This patch moves the old handling into a synchronous variant, for calls from the +restart command, and adds separate handling for async calls, such as those from +the watchdog thread. + +When calling from the watchdog thread, we cannot assume the main thread is in a +tickable state; it may be completely deadlocked. In order to handle this, we mark +the server as stopping, in order to account for situations where the server should +complete a tick reasonbly soon, i.e. 99% of cases. + +Should the server not enter a state where it is stopping within 10 seconds, We +will assume that the server has in fact deadlocked and will proceed to force +kill the server. + +This modification does not force restart the server should we actually enter a +deadlocked state where the server is stopping, whereas this will in most cases +exit within a reasonable amount of time, to put a fixed limit on a process that +will have plugins and worlds saving to the disk has a high potential to result +in corruption/dataloss. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 211251fe7cd08074c040df2f4642f37d5f90d856..f41d79c6630fd8daae28476ffc854f7e65d841e6 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -199,6 +199,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop, ServerLevel> levels; + private PlayerList playerList; + private volatile boolean running; ++ private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart + private boolean stopped; + private int tickCount; + protected final Proxy proxy; +@@ -858,7 +859,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && new File( split[0] ).isFile() ) ++ // Paper - extract method and cleanup ++ boolean isRestarting = addShutdownHook( restartScript ); ++ if ( isRestarting ) + { +- System.out.println( "Attempting to restart with " + restartScript ); ++ System.out.println( "Attempting to restart with " + SpigotConfig.restartScript ); ++ } else ++ { ++ System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); ++ } ++ // Stop the watchdog ++ WatchdogThread.doStop(); + +- // Disable Watchdog +- WatchdogThread.doStop(); ++ shutdownServer( isRestarting ); ++ // Paper end ++ } catch ( Exception ex ) ++ { ++ ex.printStackTrace(); ++ } ++ } + +- // Kick all players +- for ( ServerPlayer p : (List) MinecraftServer.getServer().getPlayerList().players ) +- { +- p.connection.disconnect(SpigotConfig.restartMessage); +- } +- // Give the socket a chance to send the packets +- try +- { +- Thread.sleep( 100 ); +- } catch ( InterruptedException ex ) +- { +- } +- // Close the socket so we can rebind with the new process +- MinecraftServer.getServer().getConnection().stop(); ++ // Paper start - sync copied from above with minor changes, async added ++ private static void shutdownServer(boolean isRestarting) ++ { ++ if ( MinecraftServer.getServer().isSameThread() ) ++ { ++ // Kick all players ++ for ( ServerPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) ++ { ++ p.connection.disconnect(SpigotConfig.restartMessage); ++ } ++ // Give the socket a chance to send the packets ++ try ++ { ++ Thread.sleep( 100 ); ++ } catch ( InterruptedException ex ) ++ { ++ } + +- // Give time for it to kick in +- try +- { +- Thread.sleep( 100 ); +- } catch ( InterruptedException ex ) +- { +- } ++ closeSocket(); + +- // Actually shutdown +- try +- { +- MinecraftServer.getServer().close(); +- } catch ( Throwable t ) +- { +- } ++ // Actually shutdown ++ try ++ { ++ MinecraftServer.getServer().close(); // calls stop() ++ } catch ( Throwable t ) ++ { ++ } ++ ++ // Actually stop the JVM ++ System.exit( 0 ); + +- // This will be done AFTER the server has completely halted +- Thread shutdownHook = new Thread() ++ } else ++ { ++ // Mark the server to shutdown at the end of the tick ++ MinecraftServer.getServer().safeShutdown( false, isRestarting ); ++ ++ // wait 10 seconds to see if we're actually going to try shutdown ++ try ++ { ++ Thread.sleep( 10000 ); ++ } ++ catch (InterruptedException ignored) ++ { ++ } ++ ++ // Check if we've actually hit a state where the server is going to safely shutdown ++ // if we have, let the server stop as usual ++ if (MinecraftServer.getServer().isStopped()) return; ++ ++ // If the server hasn't stopped by now, assume worse case and kill ++ closeSocket(); ++ System.exit( 0 ); ++ } ++ } ++ // Paper end ++ ++ // Paper - Split from moved code ++ private static void closeSocket() ++ { ++ // Close the socket so we can rebind with the new process ++ MinecraftServer.getServer().getConnection().stop(); ++ ++ // Give time for it to kick in ++ try ++ { ++ Thread.sleep( 100 ); ++ } catch ( InterruptedException ex ) ++ { ++ } ++ } ++ // Paper end ++ ++ // Paper start - copied from above and modified to return if the hook registered ++ private static boolean addShutdownHook(String restartScript) ++ { ++ String[] split = restartScript.split( " " ); ++ if ( split.length > 0 && new File( split[0] ).isFile() ) ++ { ++ Thread shutdownHook = new Thread() ++ { ++ @Override ++ public void run() + { +- @Override +- public void run() ++ try + { +- try ++ String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); ++ if ( os.contains( "win" ) ) + { +- String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); +- if ( os.contains( "win" ) ) +- { +- Runtime.getRuntime().exec( "cmd /c start " + restartScript ); +- } else +- { +- Runtime.getRuntime().exec( "sh " + restartScript ); +- } +- } catch ( Exception e ) ++ Runtime.getRuntime().exec( "cmd /c start " + restartScript ); ++ } else + { +- e.printStackTrace(); ++ Runtime.getRuntime().exec( "sh " + restartScript ); + } ++ } catch ( Exception e ) ++ { ++ e.printStackTrace(); + } +- }; +- +- shutdownHook.setDaemon( true ); +- Runtime.getRuntime().addShutdownHook( shutdownHook ); +- } else +- { +- System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); +- +- // Actually shutdown +- try +- { +- MinecraftServer.getServer().close(); +- } catch ( Throwable t ) +- { + } +- } +- System.exit( 0 ); +- } catch ( Exception ex ) ++ }; ++ ++ shutdownHook.setDaemon( true ); ++ Runtime.getRuntime().addShutdownHook( shutdownHook ); ++ return true; ++ } else + { +- ex.printStackTrace(); ++ return false; + } + } ++ // Paper end ++ + } diff --git a/Remapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch b/Remapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch new file mode 100644 index 0000000000..ebfc39ca77 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 13 May 2017 20:11:21 -0500 +Subject: [PATCH] Add system property to disable book size limits + +If anyone comes in with a watchdog crash related to books after this patch +you will not only be publicly shamed but also made an example of. + +Disables the security limits on books entirely, allowing plugins AND players +to make books with as much data as they want. Do not use this without +limiting incoming data from packets in some other way. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +index a592d4a286a775a61192dde2a4d21a0681090415..80397e223990f11c9aa413f3f4ebd7c1b8ce1cff 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +@@ -43,6 +43,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + static final int MAX_PAGES = 100; + static final int MAX_PAGE_LENGTH = 320; // 256 limit + 64 characters to allow for psuedo colour codes + static final int MAX_TITLE_LENGTH = 32; ++ private static final boolean OVERRIDE_CHECKS = Boolean.getBoolean("disable.book-limits"); // Paper - Add override + + protected String title; + protected String author; +@@ -245,7 +246,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + if (title == null) { + this.title = null; + return true; +- } else if (title.length() > MAX_TITLE_LENGTH) { ++ } else if (title.length() > MAX_TITLE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override + return false; + } + +@@ -442,7 +443,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + String validatePage(String page) { + if (page == null) { + page = ""; +- } else if (page.length() > MAX_PAGE_LENGTH) { ++ } else if (page.length() > MAX_PAGE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override + page = page.substring(0, MAX_PAGE_LENGTH); + } + return page; +@@ -452,7 +453,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + // asserted: page != null + if (this.pages == null) { + this.pages = new ArrayList(); +- } else if (this.pages.size() >= MAX_PAGES) { ++ } else if (this.pages.size() >= MAX_PAGES && !OVERRIDE_CHECKS) {// Paper - Add override + return; + } + this.pages.add(page); diff --git a/Remapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/Remapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch new file mode 100644 index 0000000000..0e3605cc72 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 16 May 2017 21:29:08 -0500 +Subject: [PATCH] Add option to make parrots stay on shoulders despite movement + +Makes parrots not fall off whenever the player changes height, or touches water, or gets hit by a passing leaf. +Instead, switches the behavior so that players have to sneak to make the birds leave. + +I suspect Mojang may switch to this behavior before full release. + +To be converted into a Paper-API event at some point in the future? + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index c611b5a63498f5ad1f50a75ccd5d7299e27df7e3..9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -330,4 +330,10 @@ public class PaperWorldConfig { + maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); + log( "Max Entity Collisions: " + maxCollisionsPerEntity ); + } ++ ++ public boolean parrotsHangOnBetter; ++ private void parrotsHangOnBetter() { ++ parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); ++ log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index ecc393ad94332ec2a59d29f30bd60bade4e1f18e..6a922e3522ac99a8e317a5f5f51fbb597baaf63e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2051,6 +2051,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + switch (packet.getAction()) { + case PRESS_SHIFT_KEY: + this.player.setShiftKeyDown(true); ++ ++ // Paper start - Hang on! ++ if (this.player.level.paperConfig.parrotsHangOnBetter) { ++ this.player.removeEntitiesOnShoulder(); ++ } ++ // Paper end ++ + break; + 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 c11d5aa115d10e3c12863cf9d42c60194d63b690..ae10c531ae69eaf6b78a342dcedb89c39fd8dbcc 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -529,7 +529,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.removeEntitiesOnShoulder(); ++ if (!this.level.paperConfig.parrotsHangOnBetter) this.removeEntitiesOnShoulder(); // Paper - Hang on! + } + + } diff --git a/Remapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch b/Remapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch new file mode 100644 index 0000000000..2f0b8509ca --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Fri, 9 Jun 2017 07:24:34 -0700 +Subject: [PATCH] Add configuration option to prevent player names from being + suggested + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 4e2f243faa209925dcb7c3ef89df3ed875c5ff78..48319aaf1c525c6fb7bdee5c2f570a0d056d4eae 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -268,4 +268,9 @@ public class PaperConfig { + flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); + flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); + } ++ ++ public static boolean suggestPlayersWhenNullTabCompletions = true; ++ private static void suggestPlayersWhenNull() { ++ suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 9365fd2bcf74755c90c4ae9b550969e97a22c639..d198dad80e0fb41a5bde66944d0e41509a9c1c43 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2300,5 +2300,10 @@ public final class CraftServer implements Server { + commandMap.registerServerAliases(); + return true; + } ++ ++ @Override ++ public boolean suggestPlayerNamesWhenNullTabCompletions() { ++ return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch b/Remapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch new file mode 100644 index 0000000000..d43b61bcff --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch @@ -0,0 +1,558 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Fri, 9 Jun 2017 19:03:43 +0200 +Subject: [PATCH] Use TerminalConsoleAppender for console improvements + +Rewrite console improvements (console colors, tab completion, +persistent input line, ...) using JLine 3.x and TerminalConsoleAppender. + +New features: + - Support console colors for Vanilla commands + - Add console colors for warnings and errors + - Server can now be turned off safely using CTRL + C. JLine catches + the signal and the implementation shuts down the server cleanly. + - Support console colors and persistent input line when running in + IntelliJ IDEA + +Other changes: + - Server starts 1-2 seconds faster thanks to optimizations in Log4j + configuration + +diff --git a/pom.xml b/pom.xml +index a5d87d22cb1588d15e08da3b37e51c5e261c7799..3841fe3630c090f8a468333d43caeb2b5841329d 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -57,10 +57,26 @@ + compile + + +- jline +- jline +- 2.12.1 +- compile ++ net.minecrell ++ terminalconsoleappender ++ 1.2.0 ++ ++ ++ org.jline ++ jline-terminal-jansi ++ 3.12.1 ++ runtime ++ ++ ++ ++ org.apache.logging.log4j ++ log4j-core ++ runtime + + + org.apache.logging.log4j +@@ -334,10 +350,18 @@ + + META-INF/services/java.sql.Driver + ++ + + + + ++ ++ ++ com.github.edwgiz ++ maven-shade-plugin.log4j2-cachefile-transformer ++ 2.13.1 ++ ++ + + + org.apache.maven.plugins +diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a4070b59e261f0f1ac4beec47b11492f4724bf27 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.console; ++ ++import net.minecraft.server.dedicated.DedicatedServer; ++import net.minecrell.terminalconsole.SimpleTerminalConsole; ++import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; ++import org.jline.reader.LineReader; ++import org.jline.reader.LineReaderBuilder; ++ ++public final class PaperConsole extends SimpleTerminalConsole { ++ ++ private final DedicatedServer server; ++ ++ public PaperConsole(DedicatedServer server) { ++ this.server = server; ++ } ++ ++ @Override ++ protected LineReader buildReader(LineReaderBuilder builder) { ++ return super.buildReader(builder ++ .appName("Paper") ++ .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) ++ .completer(new ConsoleCommandCompleter(this.server)) ++ ); ++ } ++ ++ @Override ++ protected boolean isRunning() { ++ return !this.server.isStopped() && this.server.isRunning(); ++ } ++ ++ @Override ++ protected void runCommand(String command) { ++ this.server.handleConsoleInput(command, this.server.createCommandSourceStack()); ++ } ++ ++ @Override ++ protected void shutdown() { ++ this.server.halt(false); ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java +new file mode 100644 +index 0000000000000000000000000000000000000000..685deaa0e5d1ddc13e3a7c0471b1cfcf1710c869 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.console; ++ ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++import org.bukkit.craftbukkit.command.CraftConsoleCommandSender; ++ ++public class TerminalConsoleCommandSender extends CraftConsoleCommandSender { ++ ++ private static final Logger LOGGER = LogManager.getRootLogger(); ++ ++ @Override ++ public void sendRawMessage(String message) { ++ // TerminalConsoleAppender supports color codes directly in log messages ++ LOGGER.info(message); ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index f41d79c6630fd8daae28476ffc854f7e65d841e6..4b3341877629c7065496fb0f0b4d509f5a48db6d 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -12,6 +12,7 @@ import com.mojang.datafixers.DataFixer; + import io.netty.buffer.ByteBuf; + import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import it.unimi.dsi.fastutil.longs.LongIterator; + import java.awt.image.BufferedImage; + import java.io.BufferedWriter; +@@ -161,7 +162,7 @@ import org.apache.logging.log4j.Logger; + import com.mojang.serialization.DynamicOps; + import com.mojang.serialization.Lifecycle; + import com.google.common.collect.ImmutableSet; +-import jline.console.ConsoleReader; ++// import jline.console.ConsoleReader; // Paper + import joptsimple.OptionSet; + import net.minecraft.resources.RegistryReadOps; + import net.minecraft.server.bossevents.CustomBossEvents; +@@ -253,7 +254,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; +@@ -322,7 +323,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { // Trim to filter lines which are just spaces +- DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack()); ++ DedicatedServer.this.issueCommand(s, DedicatedServer.this.getServerCommandListener()); + } + // CraftBukkit end + } +@@ -138,6 +141,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + DedicatedServer.LOGGER.error("Exception handling console input", ioexception); + } + ++ */ ++ // Paper end + } + }; + +@@ -149,6 +154,9 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } + global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler()); + ++ // Paper start - Not needed with TerminalConsoleAppender ++ final org.apache.logging.log4j.Logger logger = LogManager.getRootLogger(); ++ /* + final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()); + for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) { + if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) { +@@ -157,6 +165,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } + + new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start(); ++ */ ++ // Paper end + + System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream()); + System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream()); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index d750bef20312cc97e3446bbb2d2dc03f90d47f1c..7d6256f65d369fcbcfe1fffe7ac264788a38540b 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -146,8 +146,7 @@ public abstract class PlayerList { + + public PlayerList(MinecraftServer server, RegistryAccess.RegistryHolder registryManager, PlayerDataStorage saveHandler, int maxPlayers) { + this.cserver = server.server = new CraftServer((DedicatedServer) server, this); +- server.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance(); +- server.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(server.server)); ++ server.console = new com.destroystokyo.paper.console.TerminalConsoleCommandSender(); // Paper + // CraftBukkit end + + this.bans = new UserBanList(PlayerList.USERBANLIST_FILE); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index d198dad80e0fb41a5bde66944d0e41509a9c1c43..7b2ece40c09ba336a0c2a84321401619801c64c8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -46,7 +46,6 @@ import java.util.function.Consumer; + import java.util.logging.Level; + import java.util.logging.Logger; + import javax.imageio.ImageIO; +-import jline.console.ConsoleReader; + import net.minecraft.advancements.Advancement; + import net.minecraft.commands.CommandSourceStack; + import net.minecraft.commands.Commands; +@@ -60,6 +59,7 @@ import net.minecraft.resources.RegistryReadOps; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.ConsoleInput; ++//import jline.console.ConsoleReader; // Paper + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.bossevents.CustomBossEvent; + import net.minecraft.server.commands.ReloadCommand; +@@ -1204,9 +1204,13 @@ public final class CraftServer implements Server { + return logger; + } + ++ // Paper start - JLine update ++ /* + public ConsoleReader getReader() { + return console.reader; + } ++ */ ++ // Paper end + + @Override + public PluginCommand getPluginCommand(String name) { +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index b849b2afd009da433fe6cea5837b3ee9bb5c52b4..60d9980ccca6f1ac55b70f7684b917ddceac380a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -12,7 +12,7 @@ import java.util.logging.Level; + import java.util.logging.Logger; + import joptsimple.OptionParser; + import joptsimple.OptionSet; +-import org.fusesource.jansi.AnsiConsole; ++import net.minecrell.terminalconsole.TerminalConsoleAppender; // Paper + + public class Main { + public static boolean useJline = true; +@@ -185,6 +185,8 @@ public class Main { + } + + try { ++ // Paper start - Handled by TerminalConsoleAppender ++ /* + // This trick bypasses Maven Shade's clever rewriting of our getProperty call when using String literals + String jline_UnsupportedTerminal = new String(new char[]{'j', 'l', 'i', 'n', 'e', '.', 'U', 'n', 's', 'u', 'p', 'p', 'o', 'r', 't', 'e', 'd', 'T', 'e', 'r', 'm', 'i', 'n', 'a', 'l'}); + String jline_terminal = new String(new char[]{'j', 'l', 'i', 'n', 'e', '.', 't', 'e', 'r', 'm', 'i', 'n', 'a', 'l'}); +@@ -202,9 +204,18 @@ public class Main { + // This ensures the terminal literal will always match the jline implementation + System.setProperty(jline.TerminalFactory.JLINE_TERMINAL, jline.UnsupportedTerminal.class.getName()); + } ++ */ ++ ++ if (options.has("nojline")) { ++ System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); ++ useJline = false; ++ } ++ // Paper end + + if (options.has("noconsole")) { + useConsole = false; ++ useJline = false; // Paper ++ System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper + } + + if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { +@@ -232,7 +243,7 @@ public class Main { + System.out.println("Unable to read system info"); + } + // Paper end +- ++ System.setProperty( "library.jansi.version", "Paper" ); // Paper - set meaningless jansi version to prevent git builds from crashing on Windows + System.out.println("Loading libraries, please wait..."); + net.minecraft.server.Main.main(options); + } catch (Throwable t) { +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java b/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java +index 4580642e0ee79e6d9c9bef0344e643bbc551205c..829c62b6d55cb5706be3ce6bdc758d6b204844ee 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java +@@ -5,15 +5,13 @@ import java.util.EnumMap; + import java.util.Map; + import java.util.regex.Matcher; + import java.util.regex.Pattern; +-import jline.Terminal; ++//import jline.Terminal; + import org.bukkit.Bukkit; + import org.bukkit.ChatColor; + import org.bukkit.command.ConsoleCommandSender; + import org.bukkit.craftbukkit.CraftServer; +-import org.fusesource.jansi.Ansi; +-import org.fusesource.jansi.Ansi.Attribute; + +-public class ColouredConsoleSender extends CraftConsoleCommandSender { ++public class ColouredConsoleSender /*extends CraftConsoleCommandSender */{/* // Paper - disable + private final Terminal terminal; + private final Map replacements = new EnumMap(ChatColor.class); + private final ChatColor[] colors = ChatColor.values(); +@@ -93,5 +91,5 @@ public class ColouredConsoleSender extends CraftConsoleCommandSender { + } else { + return new ColouredConsoleSender(); + } +- } ++ }*/ // Paper + } +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index befcc19f9b56df9096b98a23b0020f1db793ea5b..a957695457cf3252848ce6ef37069692841b8e28 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -4,20 +4,31 @@ import java.util.Collections; + import java.util.List; + import java.util.concurrent.ExecutionException; + import java.util.logging.Level; +-import jline.console.completer.Completer; ++import net.minecraft.server.dedicated.DedicatedServer; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.util.Waitable; ++ ++// Paper start - JLine update ++import org.jline.reader.Candidate; ++import org.jline.reader.Completer; ++import org.jline.reader.LineReader; ++import org.jline.reader.ParsedLine; ++// Paper end + import org.bukkit.event.server.TabCompleteEvent; + + public class ConsoleCommandCompleter implements Completer { +- private final CraftServer server; ++ private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer + +- public ConsoleCommandCompleter(CraftServer server) { ++ public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer + this.server = server; + } + ++ // Paper start - Change method signature for JLine update + @Override +- public int complete(final String buffer, final int cursor, final List candidates) { ++ public void complete(LineReader reader, ParsedLine line, List candidates) { ++ final CraftServer server = this.server.server; ++ final String buffer = line.line(); ++ // Paper end + Waitable> waitable = new Waitable>() { + @Override + protected List evaluate() { +@@ -29,25 +40,37 @@ public class ConsoleCommandCompleter implements Completer { + return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); + } + }; +- this.server.getServer().processQueue.add(waitable); ++ server.getServer().processQueue.add(waitable); // Paper - Remove "this." + try { + List offers = waitable.get(); + if (offers == null) { +- return cursor; ++ return; // Paper - Method returns void ++ } ++ ++ // Paper start - JLine update ++ for (String completion : offers) { ++ if (completion.isEmpty()) { ++ continue; ++ } ++ ++ candidates.add(new Candidate(completion)); + } +- candidates.addAll(offers); ++ // Paper end + ++ // Paper start - JLine handles cursor now ++ /* + final int lastSpace = buffer.lastIndexOf(' '); + if (lastSpace == -1) { + return cursor - buffer.length(); + } else { + return cursor - (buffer.length() - lastSpace - 1); + } ++ */ ++ // Paper end + } catch (ExecutionException e) { +- this.server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); ++ server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); // Paper - Remove "this." + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } +- return cursor; + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +index 70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe..449e99d1b673870ed6892f6ab2c715a2db35c35d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +@@ -17,7 +17,7 @@ public class ServerShutdownThread extends Thread { + server.close(); + } finally { + try { +- server.reader.getTerminal().restore(); ++ net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender + } catch (Exception e) { + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java +index 99564fed7ce77e29dbdc591bcfe656af741acf8a..9a2da548b8860b496e396564b2c8f6383f020193 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java +@@ -5,12 +5,12 @@ import java.io.IOException; + import java.io.OutputStream; + import java.util.logging.Level; + import java.util.logging.Logger; +-import jline.console.ConsoleReader; ++//import jline.console.ConsoleReader; + import org.bukkit.craftbukkit.Main; +-import org.fusesource.jansi.Ansi; +-import org.fusesource.jansi.Ansi.Erase; ++//import org.fusesource.jansi.Ansi; ++//import org.fusesource.jansi.Ansi.Erase; + +-public class TerminalConsoleWriterThread extends Thread { ++public class TerminalConsoleWriterThread /*extends Thread*/ {/* // Paper - disable + private final ConsoleReader reader; + private final OutputStream output; + +@@ -54,5 +54,5 @@ public class TerminalConsoleWriterThread extends Thread { + Logger.getLogger(TerminalConsoleWriterThread.class.getName()).log(Level.SEVERE, null, ex); + } + } +- } ++ }*/ + } +diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties +new file mode 100644 +index 0000000000000000000000000000000000000000..0694b21465fb9e4164e71862ff24b62241b191f2 +--- /dev/null ++++ b/src/main/resources/log4j2.component.properties +@@ -0,0 +1 @@ ++log4j.skipJansi=true +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 722ca84968cbbbdeffd09939abff0cccd0a84010..620b9490e5f159080e50289d127404a1b56adbef 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -1,17 +1,14 @@ + + + +- +- +- + + + +- +- +- ++ ++ ++ + +- ++ + + + +@@ -24,10 +21,9 @@ + + + +- + +- + ++ + + + diff --git a/Remapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch b/Remapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch new file mode 100644 index 0000000000..a511c4d919 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 11 Jun 2017 21:01:18 +0100 +Subject: [PATCH] provide a configurable option to disable creeper lingering + effect spawns + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1..90ca51dfdbb3045dd528450225cba96f5834166e 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -336,4 +336,10 @@ public class PaperWorldConfig { + parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); + log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); + } ++ ++ public boolean disableCreeperLingeringEffect; ++ private void setDisableCreeperLingeringEffect() { ++ disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); ++ log("Creeper lingering effect: " + disableCreeperLingeringEffect); ++ } + } +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 bb3226310158139c9fcfe204554caffcbb62798c..8f8d0a23d011936150854a0606be3d63b18c57af 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +@@ -261,7 +261,7 @@ public class Creeper extends Monster { + private void spawnLingeringCloud() { + Collection collection = this.getActiveEffects(); + +- if (!collection.isEmpty()) { ++ if (!collection.isEmpty() && !level.paperConfig.disableCreeperLingeringEffect) { // Paper + AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level, this.getX(), this.getY(), this.getZ()); + + entityareaeffectcloud.setOwner(this); // CraftBukkit diff --git a/Remapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch b/Remapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch new file mode 100644 index 0000000000..569a928f31 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 5 May 2017 03:57:17 -0500 +Subject: [PATCH] Item#canEntityPickup + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 46f0ebfc99352ec8b64bdff2c6bb8d17ecfeb619..eb35c69bb777ba8d83b2304ff9f862512643e745 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -605,6 +605,11 @@ public abstract class Mob extends LivingEntity { + ItemEntity entityitem = (ItemEntity) iterator.next(); + + if (!entityitem.removed && !entityitem.getItem().isEmpty() && !entityitem.hasPickUpDelay() && this.wantsToPickUp(entityitem.getItem())) { ++ // Paper Start ++ if (!entityitem.canMobPickup) { ++ continue; ++ } ++ // Paper End + this.pickUpItem(entityitem); + } + } +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 78dc5ac986afaba04176f64afbb035442cd41d38..7aba507e171f34e213b3c034e345e7397a44d2b5 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -46,6 +46,7 @@ public class ItemEntity extends Entity { + private UUID owner; + public final float bobOffs; + private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit ++ public boolean canMobPickup = true; // Paper + + public ItemEntity(EntityType type, Level world) { + super(type, world); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +index 6e394ce6ea4177e1758e27074a4fd54d716edc3d..9a410f557988d737c3b930a79ef2ccb2b5c8b406 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +@@ -49,6 +49,16 @@ public class CraftItem extends CraftEntity implements Item { + item.age = value; + } + ++ // Paper Start ++ public boolean canMobPickup() { ++ return item.canMobPickup; ++ } ++ ++ public void setCanMobPickup(boolean canMobPickup) { ++ item.canMobPickup = canMobPickup; ++ } ++ // Paper End ++ + @Override + public void setOwner(UUID uuid) { + item.setOwner(uuid); diff --git a/Remapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch b/Remapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch new file mode 100644 index 0000000000..a5081735fc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 7 May 2017 06:26:09 -0500 +Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer + + +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 7aba507e171f34e213b3c034e345e7397a44d2b5..72d1e83ac5e4ae3c943ca5ec1058f0d7ad2903cd 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -362,6 +362,7 @@ public class ItemEntity extends Entity { + // CraftBukkit start - fire PlayerPickupItemEvent + int canHold = player.inventory.canHold(itemstack); + int remaining = i - canHold; ++ boolean flyAtPlayer = false; // Paper + + if (this.pickupDelay <= 0 && canHold > 0) { + itemstack.setCount(canHold); +@@ -369,8 +370,14 @@ public class ItemEntity extends Entity { + PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); + playerEvent.setCancelled(!player.canPickUpLoot); + this.level.getCraftServer().getPluginManager().callEvent(playerEvent); ++ flyAtPlayer = playerEvent.getFlyAtPlayer(); // Paper + if (playerEvent.isCancelled()) { + itemstack.setCount(i); // SPIGOT-5294 - restore count ++ // Paper Start ++ if (flyAtPlayer) { ++ player.take(this, i); ++ } ++ // Paper End + return; + } + +@@ -400,7 +407,11 @@ public class ItemEntity extends Entity { + // CraftBukkit end + + if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(player.getUUID())) && player.inventory.add(itemstack)) { +- player.take(this, i); ++ // Paper Start ++ if (flyAtPlayer) { ++ player.take(this, i); ++ } ++ // Paper End + if (itemstack.isEmpty()) { + this.remove(); + itemstack.setCount(i); diff --git a/Remapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch b/Remapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch new file mode 100644 index 0000000000..1c5b10dcee --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 11 Jun 2017 16:30:30 -0500 +Subject: [PATCH] PlayerAttemptPickupItemEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 72d1e83ac5e4ae3c943ca5ec1058f0d7ad2903cd..de69f7c3c0ee1e74682b0db91bdaae09175690e9 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -35,6 +35,7 @@ import net.minecraft.stats.Stats; + import org.bukkit.event.entity.EntityPickupItemEvent; + import org.bukkit.event.player.PlayerPickupItemEvent; + // CraftBukkit end ++import org.bukkit.event.player.PlayerAttemptPickupItemEvent; // Paper + + public class ItemEntity extends Entity { + +@@ -364,6 +365,22 @@ public class ItemEntity extends Entity { + int remaining = i - canHold; + boolean flyAtPlayer = false; // Paper + ++ // Paper start ++ if (this.pickupDelay <= 0) { ++ PlayerAttemptPickupItemEvent attemptEvent = new PlayerAttemptPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ this.level.getCraftServer().getPluginManager().callEvent(attemptEvent); ++ ++ flyAtPlayer = attemptEvent.getFlyAtPlayer(); ++ if (attemptEvent.isCancelled()) { ++ if (flyAtPlayer) { ++ player.take(this, i); ++ } ++ ++ return; ++ } ++ } ++ // Paper end ++ + if (this.pickupDelay <= 0 && canHold > 0) { + itemstack.setCount(canHold); + // Call legacy event diff --git a/Remapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch b/Remapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch new file mode 100644 index 0000000000..9979b7ace2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sweepyoface +Date: Sat, 17 Jun 2017 18:48:21 -0400 +Subject: [PATCH] Add UnknownCommandEvent + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 7b2ece40c09ba336a0c2a84321401619801c64c8..b9e39a4c0aea3de96d1774ae0d0d23ff82162c7e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -790,7 +790,13 @@ public final class CraftServer implements Server { + + // Spigot start + if (!org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty()) { +- sender.sendMessage(org.spigotmc.SpigotConfig.unknownCommandMessage); ++ // Paper start ++ org.bukkit.event.command.UnknownCommandEvent event = new org.bukkit.event.command.UnknownCommandEvent(sender, commandLine, org.spigotmc.SpigotConfig.unknownCommandMessage); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.message() != null) { ++ sender.sendMessage(event.message()); ++ } ++ // Paper end + } + // Spigot end + diff --git a/Remapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch b/Remapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch new file mode 100644 index 0000000000..ce8cf66ee0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch @@ -0,0 +1,577 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 15 Jan 2018 22:11:48 -0500 +Subject: [PATCH] Basic PlayerProfile API + +Establishes base extension of profile systems for future edits too + +diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8f559897e408eee8617af0bb77fa4635e07ccdce +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java +@@ -0,0 +1,303 @@ ++package com.destroystokyo.paper.profile; ++ ++import PlayerProfile; ++import ProfileProperty; ++import com.destroystokyo.paper.PaperConfig; ++import com.google.common.base.Charsets; ++import com.mojang.authlib.GameProfile; ++import com.mojang.authlib.properties.Property; ++import com.mojang.authlib.properties.PropertyMap; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.players.GameProfileCache; ++import org.apache.commons.lang3.Validate; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.spigotmc.SpigotConfig; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++import java.util.AbstractSet; ++import java.util.Collection; ++import java.util.Iterator; ++import java.util.Objects; ++import java.util.Set; ++import java.util.UUID; ++ ++public class CraftPlayerProfile implements PlayerProfile { ++ ++ private GameProfile profile; ++ private final PropertySet properties = new PropertySet(); ++ ++ public CraftPlayerProfile(CraftPlayer player) { ++ this.profile = player.getHandle().getGameProfile(); ++ } ++ ++ public CraftPlayerProfile(UUID id, String name) { ++ this.profile = new GameProfile(id, name); ++ } ++ ++ public CraftPlayerProfile(GameProfile profile) { ++ Validate.notNull(profile, "GameProfile cannot be null!"); ++ this.profile = profile; ++ } ++ ++ @Override ++ public boolean hasProperty(String property) { ++ return profile.getProperties().containsKey(property); ++ } ++ ++ @Override ++ public void setProperty(ProfileProperty property) { ++ String name = property.getName(); ++ PropertyMap properties = profile.getProperties(); ++ properties.removeAll(name); ++ properties.put(name, new Property(name, property.getValue(), property.getSignature())); ++ } ++ ++ public GameProfile getGameProfile() { ++ return profile; ++ } ++ ++ @Nullable ++ @Override ++ public UUID getId() { ++ return profile.getId(); ++ } ++ ++ @Override ++ public UUID setId(@Nullable UUID uuid) { ++ GameProfile prev = this.profile; ++ this.profile = new GameProfile(uuid, prev.getName()); ++ copyProfileProperties(prev, this.profile); ++ return prev.getId(); ++ } ++ ++ @Nullable ++ @Override ++ public String getName() { ++ return profile.getName(); ++ } ++ ++ @Override ++ public String setName(@Nullable String name) { ++ GameProfile prev = this.profile; ++ this.profile = new GameProfile(prev.getId(), name); ++ copyProfileProperties(prev, this.profile); ++ return prev.getName(); ++ } ++ ++ @Nonnull ++ @Override ++ public Set getProperties() { ++ return properties; ++ } ++ ++ @Override ++ public void setProperties(Collection properties) { ++ properties.forEach(this::setProperty); ++ } ++ ++ @Override ++ public void clearProperties() { ++ profile.getProperties().clear(); ++ } ++ ++ @Override ++ public boolean removeProperty(String property) { ++ return !profile.getProperties().removeAll(property).isEmpty(); ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ CraftPlayerProfile that = (CraftPlayerProfile) o; ++ return Objects.equals(profile, that.profile); ++ } ++ ++ @Override ++ public int hashCode() { ++ return profile.hashCode(); ++ } ++ ++ @Override ++ public String toString() { ++ return profile.toString(); ++ } ++ ++ @Override ++ public CraftPlayerProfile clone() { ++ CraftPlayerProfile clone = new CraftPlayerProfile(this.getId(), this.getName()); ++ clone.setProperties(getProperties()); ++ return clone; ++ } ++ ++ @Override ++ public boolean isComplete() { ++ return profile.isComplete(); ++ } ++ ++ @Override ++ public boolean completeFromCache() { ++ MinecraftServer server = MinecraftServer.getServer(); ++ return completeFromCache(false, PaperConfig.isProxyOnlineMode()); ++ } ++ ++ public boolean completeFromCache(boolean onlineMode) { ++ return completeFromCache(false, onlineMode); ++ } ++ ++ public boolean completeFromCache(boolean lookupUUID, boolean onlineMode) { ++ MinecraftServer server = MinecraftServer.getServer(); ++ String name = profile.getName(); ++ GameProfileCache userCache = server.getProfileCache(); ++ if (profile.getId() == null) { ++ final GameProfile profile; ++ if (onlineMode) { ++ profile = lookupUUID ? userCache.get(name) : userCache.getProfileIfCached(name); ++ } else { ++ // Make an OfflinePlayer using an offline mode UUID since the name has no profile ++ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); ++ } ++ if (profile != null) { ++ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't ++ copyProfileProperties(this.profile, profile); ++ this.profile = profile; ++ } ++ } ++ ++ if ((profile.getName() == null || !hasTextures()) && profile.getId() != null) { ++ GameProfile profile = userCache.get(this.profile.getId()); ++ if (profile != null) { ++ if (this.profile.getName() == null) { ++ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't ++ copyProfileProperties(this.profile, profile); ++ this.profile = profile; ++ } else { ++ copyProfileProperties(profile, this.profile); ++ } ++ } ++ } ++ return this.profile.isComplete(); ++ } ++ ++ public boolean complete(boolean textures) { ++ MinecraftServer server = MinecraftServer.getServer(); ++ return complete(textures, PaperConfig.isProxyOnlineMode()); ++ } ++ public boolean complete(boolean textures, boolean onlineMode) { ++ MinecraftServer server = MinecraftServer.getServer(); ++ ++ boolean isCompleteFromCache = this.completeFromCache(true, onlineMode); ++ if (onlineMode && (!isCompleteFromCache || textures && !hasTextures())) { ++ GameProfile result = server.getSessionService().fillProfileProperties(profile, true); ++ if (result != null) { ++ copyProfileProperties(result, this.profile, true); ++ } ++ if (this.profile.isComplete()) { ++ server.getProfileCache().saveProfile(this.profile); ++ } ++ } ++ return profile.isComplete() && (!onlineMode || !textures || hasTextures()); ++ } ++ ++ private static void copyProfileProperties(GameProfile source, GameProfile target) { ++ copyProfileProperties(source, target, false); ++ } ++ ++ private static void copyProfileProperties(GameProfile source, GameProfile target, boolean clearTarget) { ++ PropertyMap sourceProperties = source.getProperties(); ++ PropertyMap targetProperties = target.getProperties(); ++ if (clearTarget) targetProperties.clear(); ++ if (sourceProperties.isEmpty()) { ++ return; ++ } ++ ++ for (Property property : sourceProperties.values()) { ++ targetProperties.removeAll(property.getName()); ++ targetProperties.put(property.getName(), property); ++ } ++ } ++ ++ private static ProfileProperty toBukkit(Property property) { ++ return new ProfileProperty(property.getName(), property.getValue(), property.getSignature()); ++ } ++ ++ public static PlayerProfile asBukkitCopy(GameProfile gameProfile) { ++ CraftPlayerProfile profile = new CraftPlayerProfile(gameProfile.getId(), gameProfile.getName()); ++ copyProfileProperties(gameProfile, profile.profile); ++ return profile; ++ } ++ ++ public static PlayerProfile asBukkitMirror(GameProfile profile) { ++ return new CraftPlayerProfile(profile); ++ } ++ ++ public static Property asAuthlib(ProfileProperty property) { ++ return new Property(property.getName(), property.getValue(), property.getSignature()); ++ } ++ ++ public static GameProfile asAuthlibCopy(PlayerProfile profile) { ++ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); ++ return asAuthlib(craft.clone()); ++ } ++ ++ public static GameProfile asAuthlib(PlayerProfile profile) { ++ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); ++ return craft.getGameProfile(); ++ } ++ ++ private class PropertySet extends AbstractSet { ++ ++ @Override ++ @Nonnull ++ public Iterator iterator() { ++ return new ProfilePropertyIterator(profile.getProperties().values().iterator()); ++ } ++ ++ @Override ++ public int size() { ++ return profile.getProperties().size(); ++ } ++ ++ @Override ++ public boolean add(ProfileProperty property) { ++ setProperty(property); ++ return true; ++ } ++ ++ @Override ++ public boolean addAll(Collection c) { ++ //noinspection unchecked ++ setProperties((Collection) c); ++ return true; ++ } ++ ++ @Override ++ public boolean contains(Object o) { ++ return o instanceof ProfileProperty && profile.getProperties().containsKey(((ProfileProperty) o).getName()); ++ } ++ ++ private class ProfilePropertyIterator implements Iterator { ++ private final Iterator iterator; ++ ++ ProfilePropertyIterator(Iterator iterator) { ++ this.iterator = iterator; ++ } ++ ++ @Override ++ public boolean hasNext() { ++ return iterator.hasNext(); ++ } ++ ++ @Override ++ public ProfileProperty next() { ++ return toBukkit(iterator.next()); ++ } ++ ++ @Override ++ public void remove() { ++ iterator.remove(); ++ } ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d64d45eb01c65864fca1077982d89bc05e0f811b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java +@@ -0,0 +1,31 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.mojang.authlib.*; ++import com.mojang.authlib.minecraft.MinecraftSessionService; ++import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; ++import com.mojang.authlib.yggdrasil.YggdrasilEnvironment; ++ ++import java.net.Proxy; ++ ++public class PaperAuthenticationService extends YggdrasilAuthenticationService { ++ private final Environment environment; ++ public PaperAuthenticationService(Proxy proxy) { ++ super(proxy); ++ this.environment = (Environment)EnvironmentParser.getEnvironmentFromProperties().orElse(YggdrasilEnvironment.PROD);; ++ } ++ ++ @Override ++ public UserAuthentication createUserAuthentication(Agent agent) { ++ return new PaperUserAuthentication(this, agent); ++ } ++ ++ @Override ++ public MinecraftSessionService createMinecraftSessionService() { ++ return new PaperMinecraftSessionService(this, this.environment); ++ } ++ ++ @Override ++ public GameProfileRepository createProfileRepository() { ++ return new PaperGameProfileRepository(this, this.environment); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java +new file mode 100644 +index 0000000000000000000000000000000000000000..582c169c85ac66f1f9430f79042e4655f776c157 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java +@@ -0,0 +1,18 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.mojang.authlib.Agent; ++import com.mojang.authlib.Environment; ++import com.mojang.authlib.ProfileLookupCallback; ++import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; ++import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; ++ ++public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { ++ public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { ++ super(authenticationService, environment); ++ } ++ ++ @Override ++ public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { ++ super.findProfilesByNames(names, agent, callback); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java +new file mode 100644 +index 0000000000000000000000000000000000000000..93d73c27340645c7502acafdc0b2cfbc1a759dd8 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java +@@ -0,0 +1,30 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.mojang.authlib.Environment; ++import com.mojang.authlib.GameProfile; ++import com.mojang.authlib.minecraft.MinecraftProfileTexture; ++import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; ++import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; ++ ++import java.util.Map; ++ ++public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionService { ++ protected PaperMinecraftSessionService(YggdrasilAuthenticationService authenticationService, Environment environment) { ++ super(authenticationService, environment); ++ } ++ ++ @Override ++ public Map getTextures(GameProfile profile, boolean requireSecure) { ++ return super.getTextures(profile, requireSecure); ++ } ++ ++ @Override ++ public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { ++ return super.fillProfileProperties(profile, requireSecure); ++ } ++ ++ @Override ++ protected GameProfile fillGameProfile(GameProfile profile, boolean requireSecure) { ++ return super.fillGameProfile(profile, requireSecure); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3cdd06d3af7ff94f1fe1a11b9a9275e17c695a38 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java +@@ -0,0 +1,12 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.mojang.authlib.Agent; ++import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; ++import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; ++import java.util.UUID; ++ ++public class PaperUserAuthentication extends YggdrasilUserAuthentication { ++ public PaperUserAuthentication(YggdrasilAuthenticationService authenticationService, Agent agent) { ++ super(authenticationService, UUID.randomUUID().toString(), agent); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index d29fe67b7d39e368a873368a6be16042429e9209..68c3f069f8f832ab3d146748348aded69b5ad823 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -1,6 +1,8 @@ + package net.minecraft.server; + + import com.destroystokyo.paper.block.TargetBlockInfo; ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; + import com.google.common.util.concurrent.ThreadFactoryBuilder; + import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; + import net.minecraft.core.BlockPos; +@@ -11,6 +13,7 @@ import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.Level; + import org.apache.commons.lang.exception.ExceptionUtils; ++import com.mojang.authlib.GameProfile; + import org.bukkit.Location; + import org.bukkit.block.BlockFace; + import org.bukkit.craftbukkit.CraftWorld; +@@ -345,6 +348,10 @@ public final class MCUtil { + return run.get(); + } + ++ public static PlayerProfile toBukkit(GameProfile profile) { ++ return CraftPlayerProfile.asBukkitMirror(profile); ++ } ++ + /** + * Calculates distance between 2 entities + * @param e1 +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 5d83a8d4c69144219219877c521c364d912d2452..2bfc54941ec34c75c2d59bda748c75730b9951f7 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -124,7 +124,7 @@ public class Main { + } + + File file = (File) optionset.valueOf("universe"); // CraftBukkit +- YggdrasilAuthenticationService yggdrasilauthenticationservice = new YggdrasilAuthenticationService(Proxy.NO_PROXY); ++ YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper + MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); + GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); + GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName())); +diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java +index e8af352f813a5015d216fc590190ae8fdb03f77d..941b7e356c377fd8ad4e27409cd74c0046878396 100644 +--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java ++++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +@@ -45,7 +45,7 @@ public class GameProfileCache { + + private static final Logger LOGGER = LogManager.getLogger(); + private static boolean usesAuthentication; +- private final Map profilesByName = Maps.newConcurrentMap(); ++ private final Map profilesByName = Maps.newConcurrentMap();private final Map nameCache = profilesByName; // Paper - OBFHELPER // Paper + private final Map profilesByUUID = Maps.newConcurrentMap(); + private final GameProfileRepository profileRepository; + private final Gson gson = (new GsonBuilder()).create(); +@@ -110,6 +110,7 @@ public class GameProfileCache { + return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper + } + ++ public void saveProfile(GameProfile gameprofile) { add(gameprofile); } // Paper - OBFHELPER + public synchronized void add(GameProfile gameprofile) { // Paper - synchronize + Calendar calendar = Calendar.getInstance(); + +@@ -159,6 +160,13 @@ public class GameProfileCache { + return gameprofile; + } + ++ // Paper start ++ @Nullable public GameProfile getProfileIfCached(String name) { ++ GameProfileCache.GameProfileInfo entry = this.nameCache.get(name.toLowerCase(Locale.ROOT)); ++ return entry == null ? null : entry.getProfile(); ++ } ++ // Paper end ++ + @Nullable + public GameProfile get(UUID uuid) { + GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); +@@ -341,7 +349,7 @@ public class GameProfileCache { + + static class GameProfileInfo { + +- private final GameProfile profile; ++ private final GameProfile profile;public GameProfile getProfile() { return profile; } // Paper - OBFHELPER + private final Date expirationDate; + private volatile long lastAccess; + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index b9e39a4c0aea3de96d1774ae0d0d23ff82162c7e..df68599520189e2699c8521d6c6ab7235612af33 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -223,6 +223,9 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; + + import net.md_5.bungee.api.chat.BaseComponent; // Spigot + ++import javax.annotation.Nullable; // Paper ++import javax.annotation.Nonnull; // Paper ++ + public final class CraftServer implements Server { + private final String serverName = "Paper"; // Paper + private final String serverVersion; +@@ -2315,5 +2318,24 @@ public final class CraftServer implements Server { + public boolean suggestPlayerNamesWhenNullTabCompletions() { + return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; + } ++ ++ @Override ++ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { ++ return createProfile(uuid, null); ++ } ++ ++ @Override ++ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull String name) { ++ return createProfile(null, name); ++ } ++ ++ @Override ++ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { ++ Player player = uuid != null ? Bukkit.getPlayer(uuid) : (name != null ? Bukkit.getPlayerExact(name) : null); ++ if (player != null) { ++ return new com.destroystokyo.paper.profile.CraftPlayerProfile((CraftPlayer)player); ++ } ++ return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +index 313ddd6b64e395a8caab77b3da005e52006ab2d7..750661540f55d3c59119dcc909e706e571a2123b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +@@ -80,6 +80,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + } + + private void setProfile(GameProfile profile) { ++ // Paper start ++ if (profile != null) { ++ com.destroystokyo.paper.profile.CraftPlayerProfile paperProfile = new com.destroystokyo.paper.profile.CraftPlayerProfile(profile); ++ paperProfile.completeFromCache(false, true); ++ profile = paperProfile.getGameProfile(); ++ } ++ // Paper end + this.profile = profile; + this.serializedProfile = (profile == null) ? null : NbtUtils.writeGameProfile(new CompoundTag(), profile); + } diff --git a/Remapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch b/Remapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch new file mode 100644 index 0000000000..e71eeed527 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 17 Jun 2017 15:18:30 -0400 +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 ae10c531ae69eaf6b78a342dcedb89c39fd8dbcc..3205bc2fb6c9031be68ff46dfca927e681163fa8 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1877,20 +1877,44 @@ public abstract class Player extends LivingEntity { + + } + ++ // Paper start ++ public Entity releaseLeftShoulderEntity() { ++ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityLeft()); ++ if (entity != null) { ++ this.setShoulderEntityLeft(new CompoundTag()); ++ } ++ return entity; ++ } ++ ++ public Entity releaseRightShoulderEntity() { ++ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityRight()); ++ if (entity != null) { ++ this.setShoulderEntityRight(new CompoundTag()); ++ } ++ return entity; ++ } ++ // Paper - maintain old signature + private boolean spawnEntityFromShoulder(CompoundTag nbttagcompound) { // CraftBukkit void->boolean +- if (!this.level.isClientSide && !nbttagcompound.isEmpty()) { ++ return spawnEntityFromShoulder0(nbttagcompound) != null; ++ } ++ ++ // Paper - return entity ++ private Entity spawnEntityFromShoulder0(@Nullable CompoundTag nbttagcompound) { ++ if (!this.level.isClientSide && nbttagcompound != null && !nbttagcompound.isEmpty()) { + return EntityType.create(nbttagcompound, this.level).map((entity) -> { // CraftBukkit + if (entity instanceof TamableAnimal) { + ((TamableAnimal) entity).setOwnerUUID(this.uuid); + } + + entity.setPos(this.getX(), this.getY() + 0.699999988079071D, this.getZ()); +- return ((ServerLevel) this.level).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit +- }).orElse(true); // CraftBukkit ++ boolean addedToWorld = ((ServerLevel) this.level).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit ++ return addedToWorld ? entity : null; ++ }).orElse(null); // CraftBukkit // Paper - false -> null + } + +- return true; // CraftBukkit ++ return null; // Paper - return null + } ++ // Paper end + + @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 b5c0f3d91cf451a972f0cf293db03a306073c493..c62d01719f21762aa10294815ab88e450e4dce3f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -494,6 +494,32 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + getHandle().getCooldowns().addCooldown(CraftMagicNumbers.getItem(material), ticks); + } + ++ // Paper start ++ @Override ++ public org.bukkit.entity.Entity releaseLeftShoulderEntity() { ++ if (!getHandle().getShoulderEntityLeft().isEmpty()) { ++ Entity entity = getHandle().releaseLeftShoulderEntity(); ++ if (entity != null) { ++ return entity.getBukkitEntity(); ++ } ++ } ++ ++ return null; ++ } ++ ++ @Override ++ public org.bukkit.entity.Entity releaseRightShoulderEntity() { ++ if (!getHandle().getShoulderEntityRight().isEmpty()) { ++ Entity entity = getHandle().releaseRightShoulderEntity(); ++ if (entity != null) { ++ return entity.getBukkitEntity(); ++ } ++ } ++ ++ return null; ++ } ++ // Paper end ++ + @Override + public boolean discoverRecipe(NamespacedKey recipe) { + return discoverRecipes(Arrays.asList(recipe)) != 0; diff --git a/Remapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch b/Remapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch new file mode 100644 index 0000000000..a9a4210f19 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 17 Jun 2017 17:00:32 -0400 +Subject: [PATCH] Profile Lookup Events + +Adds a Pre Lookup Event and a Post Lookup Event so that plugins may prefill in profile data, and cache the responses from +profiles that had to be looked up. + +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java +index 582c169c85ac66f1f9430f79042e4655f776c157..08fdb681a68e8be6e4062af0630957ce3e524806 100644 +--- a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java +@@ -1,11 +1,16 @@ + package com.destroystokyo.paper.profile; + ++import com.destroystokyo.paper.event.profile.LookupProfileEvent; ++import com.destroystokyo.paper.event.profile.PreLookupProfileEvent; ++import com.google.common.collect.Sets; + import com.mojang.authlib.Agent; + import com.mojang.authlib.Environment; ++import com.mojang.authlib.GameProfile; + import com.mojang.authlib.ProfileLookupCallback; + import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; + import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; + ++import java.util.Set; + public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { + public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { + super(authenticationService, environment); +@@ -13,6 +18,50 @@ public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { + + @Override + public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { +- super.findProfilesByNames(names, agent, callback); ++ Set unfoundNames = Sets.newHashSet(); ++ for (String name : names) { ++ PreLookupProfileEvent event = new PreLookupProfileEvent(name); ++ event.callEvent(); ++ if (event.getUUID() != null) { ++ // Plugin provided UUI, we can skip network call. ++ GameProfile gameprofile = new GameProfile(event.getUUID(), name); ++ // We might even have properties! ++ Set profileProperties = event.getProfileProperties(); ++ if (!profileProperties.isEmpty()) { ++ for (ProfileProperty property : profileProperties) { ++ gameprofile.getProperties().put(property.getName(), CraftPlayerProfile.asAuthlib(property)); ++ } ++ } ++ callback.onProfileLookupSucceeded(gameprofile); ++ } else { ++ unfoundNames.add(name); ++ } ++ } ++ ++ // Some things were not found.... Proceed to look up. ++ if (!unfoundNames.isEmpty()) { ++ String[] namesArr = unfoundNames.toArray(new String[unfoundNames.size()]); ++ super.findProfilesByNames(namesArr, agent, new PreProfileLookupCallback(callback)); ++ } ++ } ++ ++ private static class PreProfileLookupCallback implements ProfileLookupCallback { ++ private final ProfileLookupCallback callback; ++ ++ PreProfileLookupCallback(ProfileLookupCallback callback) { ++ this.callback = callback; ++ } ++ ++ @Override ++ public void onProfileLookupSucceeded(GameProfile gameProfile) { ++ PlayerProfile from = CraftPlayerProfile.asBukkitMirror(gameProfile); ++ new LookupProfileEvent(from).callEvent(); ++ callback.onProfileLookupSucceeded(gameProfile); ++ } ++ ++ @Override ++ public void onProfileLookupFailed(GameProfile gameProfile, Exception e) { ++ callback.onProfileLookupFailed(gameProfile, e); ++ } + } + } diff --git a/Remapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch b/Remapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch new file mode 100644 index 0000000000..f43b561da9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 2 Jul 2017 21:35:56 -0500 +Subject: [PATCH] Block player logins during server shutdown + + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index e3c1460c580ea348ee6d436018244441a5a1206e..fca291c34c67d552590320c6e6e9c08e21d19fa8 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -66,6 +66,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + + public void tick() { ++ // Paper start - Do not allow logins while the server is shutting down ++ if (!MinecraftServer.getServer().isRunning()) { ++ this.disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(org.spigotmc.SpigotConfig.restartMessage)[0]); ++ return; ++ } ++ // Paper end + if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) { + this.handleAcceptedLogin(); + } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { diff --git a/Remapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch b/Remapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch new file mode 100644 index 0000000000..10fa81134b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 18 Jun 2017 18:17:05 -0500 +Subject: [PATCH] Entity#fromMobSpawner() + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a017fa55002d6674124befa3f6e81eb70c9ce8f7..7e70bae5bc54ad17980789fa965fd539a7f193ea 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -267,6 +267,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; + public long activatedTick = Integer.MIN_VALUE; ++ public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one + protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end +@@ -1665,6 +1666,10 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); + tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); + } ++ // Save entity's from mob spawner status ++ if (spawnedViaMobSpawner) { ++ tag.putBoolean("Paper.FromMobSpawner", true); ++ } + // Paper end + return tag; + } catch (Throwable throwable) { +@@ -1797,6 +1802,8 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); + } ++ ++ spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status + // Paper end + + } catch (Throwable throwable) { +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index ed631d5bfba5d2543e8eed017a7c484ad3ddb453..7541155048744a9af2017ec039cf99a246addb0b 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -160,6 +160,7 @@ public abstract class BaseSpawner { + } + // Spigot End + } ++ entity.spawnedViaMobSpawner = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { + Entity vehicle = entity.getVehicle(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index b028946de7c8f52091635fe154c816453f1ddc93..ecb5f5ca547930f91602d539e541964cd9f10287 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1100,5 +1100,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + Location origin = getHandle().origin; + return origin == null ? null : origin.clone(); + } ++ ++ @Override ++ public boolean fromMobSpawner() { ++ return getHandle().spawnedViaMobSpawner; ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch b/Remapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch new file mode 100644 index 0000000000..85d5e4f330 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 10 Dec 2016 16:24:06 -0500 +Subject: [PATCH] Improve the Saddle API for Horses + +Not all horses with Saddles have armor. This lets us break up the horses with saddles +and access their saddle state separately from an interface shared with Armor. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +index 116553ea587ab5ff3bc8a1530f51cd6efb7ae8ca..6136b3322a340d506ce744bcd15f71a158e46ad1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +@@ -5,6 +5,7 @@ import net.minecraft.world.entity.ai.attributes.Attributes; + import org.apache.commons.lang.Validate; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.inventory.CraftInventoryAbstractHorse; ++import org.bukkit.craftbukkit.inventory.CraftSaddledInventory; + import org.bukkit.entity.AbstractHorse; + import org.bukkit.entity.AnimalTamer; + import org.bukkit.entity.Horse; +@@ -98,6 +99,6 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac + + @Override + public AbstractHorseInventory getInventory() { +- return new CraftInventoryAbstractHorse(getHandle().inventory); ++ return new CraftSaddledInventory(getHandle().inventory); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java +index 7013059856c2471dc34112a1a2068b96b809dd96..b72b4260fc1c0e9928d70f97589d8db00849b9e8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java +@@ -4,7 +4,7 @@ import net.minecraft.world.Container; + import org.bukkit.inventory.HorseInventory; + import org.bukkit.inventory.ItemStack; + +-public class CraftInventoryHorse extends CraftInventoryAbstractHorse implements HorseInventory { ++public class CraftInventoryHorse extends CraftSaddledInventory implements HorseInventory { + + public CraftInventoryHorse(Container inventory) { + super(inventory); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3a617c07d445bacf5a13e0e3ff6481823cfc8477 +--- /dev/null ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java +@@ -0,0 +1,12 @@ ++package org.bukkit.craftbukkit.inventory; ++ ++import net.minecraft.world.Container; ++import org.bukkit.inventory.SaddledHorseInventory; ++ ++public class CraftSaddledInventory extends CraftInventoryAbstractHorse implements SaddledHorseInventory { ++ ++ public CraftSaddledInventory(Container inventory) { ++ super(inventory); ++ } ++ ++} diff --git a/Remapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch b/Remapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch new file mode 100644 index 0000000000..bc3d68abd4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 May 2016 22:43:12 -0400 +Subject: [PATCH] Implement ensureServerConversions API + +This will take a Bukkit ItemStack and run it through any conversions a server process would perform on it, +to ensure it meets latest minecraft expectations. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index 32fa5ca0df07466e40817341d85d359b282f3078..41c8bbf93039add43695a52d2bfc0c2cef88463d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -346,5 +346,11 @@ public final class CraftItemFactory implements ItemFactory { + public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { + return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); + } ++ ++ // Paper start ++ @Override ++ public ItemStack ensureServerConversions(ItemStack item) { ++ return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch b/Remapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch new file mode 100644 index 0000000000..c27fb916c9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 May 2016 23:59:38 -0400 +Subject: [PATCH] Implement getI18NDisplayName + +Gets the Display name as seen in the Client. +Currently the server only supports the English language. To override this, +You must replace the language file embedded in the server jar. + +diff --git a/src/main/java/net/minecraft/locale/Language.java b/src/main/java/net/minecraft/locale/Language.java +index 8a0d2e510aee160ec3a817fd72c23bc9dfeb6287..756b78a7dc3d3e76dc0a37375b304db0b6ecf684 100644 +--- a/src/main/java/net/minecraft/locale/Language.java ++++ b/src/main/java/net/minecraft/locale/Language.java +@@ -30,7 +30,7 @@ public abstract class Language { + + private static Language loadDefault() { + Builder builder = ImmutableMap.builder(); +- BiConsumer biconsumer = builder::put; ++ BiConsumer biconsumer = builder::put; // Paper - decompile fix + + try { + InputStream inputstream = Language.class.getResourceAsStream("/assets/minecraft/lang/en_us.json"); +@@ -87,10 +87,12 @@ public abstract class Language { + + } + ++ public static Language getInstance() { return getInstance(); } // Paper - OBFHELPER + public static Language getInstance() { + return Language.instance; + } + ++ public String translateKey(String key) { return getOrDefault(key); } // Paper - OBFHELPER + public abstract String getOrDefault(String key); + + public abstract boolean has(String key); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index 41c8bbf93039add43695a52d2bfc0c2cef88463d..746755f76ae177b2eeccf66f8cd95e6ffd5acad9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -352,5 +352,18 @@ public final class CraftItemFactory implements ItemFactory { + public ItemStack ensureServerConversions(ItemStack item) { + return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); + } ++ ++ @Override ++ public String getI18NDisplayName(ItemStack item) { ++ net.minecraft.world.item.ItemStack nms = null; ++ if (item instanceof CraftItemStack) { ++ nms = ((CraftItemStack) item).handle; ++ } ++ if (nms == null) { ++ nms = CraftItemStack.asNMSCopy(item); ++ } ++ ++ return nms != null ? net.minecraft.locale.Language.getInstance().translateKey(nms.getItem().getDescriptionId()) : null; ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch b/Remapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch new file mode 100644 index 0000000000..5051a6a195 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 3 Jul 2017 18:11:10 -0500 +Subject: [PATCH] ProfileWhitelistVerifyEvent + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7d6256f65d369fcbcfe1fffe7ac264788a38540b..ae60b233c4d56a4964b388f96e9cc66410774e8d 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -611,9 +611,9 @@ public abstract class PlayerList { + + // return chatmessage; + if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure +- } else if (!this.isWhiteListed(gameprofile)) { +- chatmessage = new TranslatableComponent("multiplayer.disconnect.not_whitelisted"); +- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure ++ } else if (!this.isWhitelisted(gameprofile, event)) { // Paper ++ //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper ++ //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted + } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { + IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); + +@@ -1005,9 +1005,25 @@ public abstract class PlayerList { + this.server.getCommands().sendCommands(player); + } + ++ // Paper start + public boolean isWhiteListed(GameProfile profile) { +- return !this.doWhiteList || this.ops.contains(profile) || this.whitelist.contains(profile); ++ return isWhitelisted(profile, null); + } ++ public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { ++ boolean isOp = this.ops.contains(gameprofile); ++ boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile); ++ final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; ++ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); ++ event.callEvent(); ++ if (!event.isWhitelisted()) { ++ if (loginEvent != null) { ++ loginEvent.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getKickMessage() == null ? org.spigotmc.SpigotConfig.whitelistMessage : event.getKickMessage())); ++ } ++ return false; ++ } ++ return true; ++ } ++ // Paper end + + public boolean isOp(GameProfile profile) { + return this.ops.contains(profile) || this.server.isSingleplayerOwner(profile) && this.server.getWorldData().getAllowCommands() || this.allowCheatsForAllPlayers; diff --git a/Remapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch b/Remapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch new file mode 100644 index 0000000000..8eacc81f8c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DemonWav +Date: Sun, 6 Aug 2017 17:17:53 -0500 +Subject: [PATCH] Fix this stupid bullshit + +Disable the 15 second sleep when the server jar hasn't been rebuilt within a period of time. + +modified in order to prevent merge conflicts when Spigot changes/disables the warning, +and to provide some level of hint without being disruptive. + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 60d9980ccca6f1ac55b70f7684b917ddceac380a..808a7688ed81bdfef623ee0a151ff8f94df2a3d7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -224,10 +224,12 @@ public class Main { + Calendar deadline = Calendar.getInstance(); + deadline.add(Calendar.DAY_OF_YEAR, -28); + if (buildDate.before(deadline.getTime())) { +- System.err.println("*** Error, this build is outdated ***"); ++ // Paper start - This is some stupid bullshit ++ System.err.println("*** Warning, you've not updated in a while! ***"); + System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper +- System.err.println("*** Server will start in 20 seconds ***"); +- Thread.sleep(TimeUnit.SECONDS.toMillis(20)); ++ //System.err.println("*** Server will start in 20 seconds ***"); ++ //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); ++ // Paper End + } + } + diff --git a/Remapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch b/Remapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch new file mode 100644 index 0000000000..07571c80e4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 31 Jul 2017 01:54:40 -0500 +Subject: [PATCH] Ocelot despawns should honor nametags and leash + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java +index 1b820ca48845cbe4a668cc31582c2ddf6d50c96a..142025cfb75b24dc6df8160f4922086404efa6a7 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java +@@ -128,7 +128,7 @@ public class Ocelot extends Animal { + + @Override + public boolean removeWhenFarAway(double distanceSquared) { +- return !this.isTrusting() /*&& this.ticksLived > 2400*/; // CraftBukkit ++ return !this.isTrusting() && !this.hasCustomName() && !this.isLeashed() /*&& this.ticksLived > 2400*/; // CraftBukkit // Paper - honor name and leash + } + + public static AttributeSupplier.Builder createAttributes() { diff --git a/Remapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/Remapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch new file mode 100644 index 0000000000..3476f2d837 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 31 Jul 2017 01:45:19 -0500 +Subject: [PATCH] Reset spawner timer when spawner event is cancelled + + +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 7541155048744a9af2017ec039cf99a246addb0b..4582fc1bb767214241568fbc22b0ee2cbf3322e0 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -161,6 +161,7 @@ public abstract class BaseSpawner { + // Spigot End + } + entity.spawnedViaMobSpawner = true; // Paper ++ flag = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { + Entity vehicle = entity.getVehicle(); +@@ -184,7 +185,7 @@ public abstract class BaseSpawner { + ((Mob) entity).spawnAnim(); + } + +- flag = true; ++ /*flag = true;*/ // Paper - moved up above cancellable event + } + } + } diff --git a/Remapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/Remapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch new file mode 100644 index 0000000000..01e55f74f0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: mezz +Date: Wed, 9 Aug 2017 17:51:22 -0500 +Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index ecb6378a285dff4b34170410387ebb7a8510a6dc..81713c97f35263f4ab8d14f8b707aac3d6afea11 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -726,7 +726,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + gameprofilerfiller.push("blockEntities"); + timings.tileEntityTick.startTiming(); // Spigot + if (!this.tileEntityListUnload.isEmpty()) { +- this.tickableBlockEntities.removeAll(this.tileEntityListUnload); ++ // Paper start - Use alternate implementation with faster contains ++ java.util.Set toRemove = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); ++ toRemove.addAll(tileEntityListUnload); ++ this.tickableBlockEntities.removeAll(toRemove); ++ // Paper end + //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list + this.tileEntityListUnload.clear(); + } diff --git a/Remapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch b/Remapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch new file mode 100644 index 0000000000..766b536512 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Thu, 17 Aug 2017 16:08:20 -0700 +Subject: [PATCH] Allow specifying a custom "authentication servers down" kick + message + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 48319aaf1c525c6fb7bdee5c2f570a0d056d4eae..52954fc3bf932cfc9d5ce63e3d3cace351305790 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -1,5 +1,6 @@ + package com.destroystokyo.paper; + ++import com.google.common.base.Strings; + import com.google.common.base.Throwables; + + import java.io.File; +@@ -273,4 +274,9 @@ public class PaperConfig { + private static void suggestPlayersWhenNull() { + suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); + } ++ ++ public static String authenticationServersDownKickMessage = ""; // empty = use translatable message ++ private static void authenticationServersDownKickMessage() { ++ authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index fca291c34c67d552590320c6e6e9c08e21d19fa8..4b91699ddfa2ee298af5ba25447a85751facf4a4 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -275,6 +275,10 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + ServerLoginPacketListenerImpl.this.gameProfile = ServerLoginPacketListenerImpl.this.createFakeProfile(gameprofile); + ServerLoginPacketListenerImpl.this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT; + } else { ++ // Paper start ++ if (com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage != null) { ++ ServerLoginPacketListenerImpl.this.disconnect(new TextComponent(com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage)); ++ } else // Paper end + ServerLoginPacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.authservers_down")); + ServerLoginPacketListenerImpl.LOGGER.error("Couldn't verify username because servers are unavailable"); + } diff --git a/Remapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch b/Remapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch new file mode 100644 index 0000000000..fdb6acae74 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 31 Jul 2017 01:49:48 -0500 +Subject: [PATCH] LivingEntity#setKiller + + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index c1786fcabeaee5732e9197db04268c5c4e164339..d6b4fabd232958ae1fd5405c7129551951cd7765 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -177,7 +177,7 @@ public abstract class LivingEntity extends Entity { + public float flyingSpeed; + @Nullable + public net.minecraft.world.entity.player.Player lastHurtByPlayer; +- protected int lastHurtByPlayerTime; ++ public int lastHurtByPlayerTime; // Paper - protected -> public + protected boolean dead; + protected int noActionTime; + protected float oRun; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index d8cd88d62f9abfc7960c187dd74239f61267ca57..006f4c71bbcda61b55815e7ceab91731ab062da0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -8,6 +8,7 @@ import java.util.Iterator; + import java.util.List; + import java.util.Set; + import java.util.UUID; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.InteractionHand; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffect; +@@ -332,6 +333,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return getHandle().lastHurtByPlayer == null ? null : (Player) getHandle().lastHurtByPlayer.getBukkitEntity(); + } + ++ // Paper start ++ @Override ++ public void setKiller(Player killer) { ++ ServerPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle(); ++ getHandle().lastHurtByPlayer = entityPlayer; ++ getHandle().lastHurtByMob = entityPlayer; ++ getHandle().lastHurtByPlayerTime = entityPlayer == null ? 0 : 100; // 100 value taken from EntityLiving#damageEntity ++ } ++ // Paper end ++ + @Override + public boolean addPotionEffect(PotionEffect effect) { + return addPotionEffect(effect, false); diff --git a/Remapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch b/Remapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch new file mode 100644 index 0000000000..8c91986ef3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Thu, 21 Sep 2017 16:14:55 +0200 +Subject: [PATCH] Handle plugin prefixes using Log4J configuration + +Display logger name in the console for all loggers except the +root logger, Bukkit's logger ("Minecraft") and Minecraft loggers. +Since plugins now use the plugin name as logger name this will +restore the plugin prefixes without having to prepend them manually +to the log messages. + +Logger prefixes are shown by default for all loggers except for +the root logger, the Minecraft/Mojang loggers and the Bukkit loggers. +This may cause additional prefixes to be disabled for plugins bypassing +the plugin logger. + +diff --git a/pom.xml b/pom.xml +index 3841fe3630c090f8a468333d43caeb2b5841329d..f5429f2f1979542fd93956d2f436d20d0e3a66b8 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -76,7 +76,7 @@ + + org.apache.logging.log4j + log4j-core +- runtime ++ compile + + + org.apache.logging.log4j +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0083f979933d4a9035efb992ab0a2f250a56a979..3981ba5957fdc2929d54515f2b98bb7a4611e938 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -290,7 +290,7 @@ public class SpigotConfig + private static void playerSample() + { + playerSample = getInt( "settings.sample-count", 12 ); +- System.out.println( "Server Ping Player Sample Count: " + playerSample ); ++ Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger + } + + public static int playerShuffle; +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 620b9490e5f159080e50289d127404a1b56adbef..a8bdaaeaa1a9316848416f0533739b9b083ca151 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -5,10 +5,22 @@ + + + +- ++ ++ ++ ++ ++ ++ + + +- ++ ++ ++ ++ ++ ++ + + + diff --git a/Remapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch b/Remapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch new file mode 100644 index 0000000000..5afb9562c0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Sat, 23 Sep 2017 21:07:20 +0200 +Subject: [PATCH] Improve Log4J Configuration / Plugin Loggers + +Add full exceptions to log4j to not truncate stack traces + +Disable logger prefix for various plugins bypassing the plugin logger + +Some plugins bypass the plugin logger and add the plugin prefix +manually to the log message. Since they use other logger names +(e.g. qualified class names) these would now also appear in the +log. Disable the logger prefix for these plugins so the messages +show up correctly. + +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index a8bdaaeaa1a9316848416f0533739b9b083ca151..476f4a5cbe664ddd05474cb88553018bd334a5b8 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -6,19 +6,21 @@ + + + +- ++ + +- ++ ++ + + + + + +- ++ + +- ++ ++ + + + diff --git a/Remapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch b/Remapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch new file mode 100644 index 0000000000..9abed7291f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 28 Sep 2017 17:21:44 -0400 +Subject: [PATCH] Add PlayerJumpEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 6a922e3522ac99a8e317a5f5f51fbb597baaf63e..f35a976de39f16d100bcbe411b64de357832c5df 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1166,7 +1166,34 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + boolean flag = d8 > 0.0D; + + if (this.player.isOnGround() && !packet.isOnGround() && flag) { +- this.player.jumpFromGround(); ++ // Paper start - Add player jump event ++ Player player = this.getPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ if (packet.hasPos) { ++ to.setX(packet.x); ++ to.setY(packet.y); ++ to.setZ(packet.z); ++ } ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ if (packet.hasRot) { ++ to.setYaw(packet.yRot); ++ to.setPitch(packet.xRot); ++ } ++ ++ com.destroystokyo.paper.event.player.PlayerJumpEvent event = new com.destroystokyo.paper.event.player.PlayerJumpEvent(player, from, to); ++ ++ if (event.callEvent()) { ++ this.player.jumpFromGround(); ++ } else { ++ from = event.getFrom(); ++ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet()); ++ return; ++ } ++ // Paper end + } + + this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9)); diff --git a/Remapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch b/Remapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch new file mode 100644 index 0000000000..1a0b7f3089 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 5 Oct 2017 01:54:07 +0100 +Subject: [PATCH] handle PacketPlayInKeepAlive async + +In 1.12.2, Mojang moved the processing of PacketPlayInKeepAlive off the main +thread, while entirely correct for the server, this causes issues with +plugins which are expecting the PlayerQuitEvent on the main thread. + +In order to counteract some bad behavior, we will post handling of the +disconnection to the main thread, but leave the actual processing of the packet +off the main thread. + +also adding some additional logging in order to help work out what is causing +random disconnections for clients. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index f35a976de39f16d100bcbe411b64de357832c5df..f0aab8639c7d8440e4d70dd096200313d7958780 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2777,14 +2777,18 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + @Override + public void handleKeepAlive(ServerboundKeepAlivePacket packet) { +- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); // CraftBukkit ++ //PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit // Paper - This shouldn't be on the main thread + if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) { + int i = (int) (Util.getMillis() - this.keepAliveTime); + + this.player.latency = (this.player.latency * 3 + i) / 4; + this.keepAlivePending = false; + } else if (!this.isSingleplayerOwner()) { ++ // Paper start - This needs to be handled on the main thread for plugins ++ server.scheduleOnMain(() -> { + this.disconnect(new TranslatableComponent("disconnect.timeout")); ++ }); ++ // Paper end + } + + } diff --git a/Remapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch b/Remapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch new file mode 100644 index 0000000000..c18295ef08 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch @@ -0,0 +1,128 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Tue, 10 Oct 2017 18:45:20 +0200 +Subject: [PATCH] Expose client protocol version and virtual host + + +diff --git a/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a5a7624f1f372a26b982836cd31cff15e2589e9b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java +@@ -0,0 +1,49 @@ ++package com.destroystokyo.paper.network; ++ ++import java.net.InetSocketAddress; ++ ++import javax.annotation.Nullable; ++import net.minecraft.network.Connection; ++ ++public class PaperNetworkClient implements NetworkClient { ++ ++ private final Connection networkManager; ++ ++ PaperNetworkClient(Connection networkManager) { ++ this.networkManager = networkManager; ++ } ++ ++ @Override ++ public InetSocketAddress getAddress() { ++ return (InetSocketAddress) this.networkManager.getRemoteAddress(); ++ } ++ ++ @Override ++ public int getProtocolVersion() { ++ return this.networkManager.protocolVersion; ++ } ++ ++ @Nullable ++ @Override ++ public InetSocketAddress getVirtualHost() { ++ return this.networkManager.virtualHost; ++ } ++ ++ public static InetSocketAddress prepareVirtualHost(String host, int port) { ++ int len = host.length(); ++ ++ // FML appends a marker to the host to recognize FML clients (\0FML\0) ++ int pos = host.indexOf('\0'); ++ if (pos >= 0) { ++ len = pos; ++ } ++ ++ // When clients connect with a SRV record, their host contains a trailing '.' ++ if (len > 0 && host.charAt(len - 1) == '.') { ++ len--; ++ } ++ ++ return InetSocketAddress.createUnresolved(host.substring(0, len), port); ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 92c5c5bbcfe364475578b6a0eddfaa85858ace8a..3429c813a5b471cdfa561bd20849a303e5aacead 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -70,6 +70,10 @@ public class Connection extends SimpleChannelInboundHandler> { + private float averageSentPackets; + private int tickCount; + private boolean handlingFault; ++ // Paper start - NetworkClient implementation ++ public int protocolVersion; ++ public java.net.InetSocketAddress virtualHost; ++ // Paper end + + public Connection(PacketFlow side) { + this.receiving = side; +diff --git a/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java b/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java +index 1eae2999ecc57f68ac9cd1d745191cba617b0de2..9ad400b15a2eb2d80bc763de28d648e22432b8f2 100644 +--- a/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java +@@ -39,6 +39,7 @@ public class ClientIntentionPacket implements Packet +Date: Sun, 15 Oct 2017 00:29:07 +0100 +Subject: [PATCH] revert serverside behavior of keepalives + +This patch intends to bump up the time that a client has to reply to the +server back to 30 seconds as per pre 1.12.2, which allowed clients +more than enough time to reply potentially allowing them to be less +tempermental due to lag spikes on the network thread, e.g. that caused +by plugins that are interacting with netty. + +We also add a system property to allow people to tweak how long the server +will wait for a reply. There is a compromise here between lower and higher +values, lower values will mean that dead connections can be closed sooner, +whereas higher values will make this less sensitive to issues such as spikes +from networking or during connections flood of chunk packets on slower clients, + at the cost of dead connections being kept open for longer. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index f0aab8639c7d8440e4d70dd096200313d7958780..525728268f56470fdc24c4fd2f19d66943447778 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -221,7 +221,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private final MinecraftServer server; + public ServerPlayer player; + private int tickCount; +- private long keepAliveTime; private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER ++ private long keepAliveTime = Util.getMillis(); private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER + private boolean keepAlivePending; private void setPendingPing(boolean isPending) { this.keepAlivePending = isPending;}; private boolean isPendingPing() { return this.keepAlivePending;}; // Paper - OBFHELPER + private long keepAliveChallenge; private void setKeepAliveID(long keepAliveID) { this.keepAliveChallenge = keepAliveID;}; private long getKeepAliveID() {return this.keepAliveChallenge; }; // Paper - OBFHELPER + // CraftBukkit start - multithreaded fields +@@ -252,6 +252,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private int aboveGroundVehicleTickCount; + private int receivedMovePacketCount; + private int knownMovePacketCount; ++ private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit + + public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { + this.server = server; +@@ -338,18 +339,25 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + + this.server.getProfiler().push("keepAlive"); +- long i = Util.getMillis(); +- +- if (i - this.keepAliveTime >= 25000L) { // CraftBukkit +- if (this.keepAlivePending) { +- this.disconnect(new TranslatableComponent("disconnect.timeout")); +- } else { +- this.keepAlivePending = true; +- this.keepAliveTime = i; +- this.keepAliveChallenge = i; +- this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge)); ++ // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings ++ // This should effectively place the keepalive handling back to "as it was" before 1.12.2 ++ long currentTime = Util.getMillis(); ++ long elapsedTime = currentTime - this.getLastPing(); ++ ++ if (this.isPendingPing()) { ++ if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected ++ ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info ++ this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0])); ++ } ++ } else { ++ if (elapsedTime >= 15000L) { // 15 seconds ++ this.setPendingPing(true); ++ this.setLastPing(currentTime); ++ this.setKeepAliveID(currentTime); ++ this.send(new ClientboundKeepAlivePacket(this.getKeepAliveID())); + } + } ++ // Paper end + + this.server.getProfiler().pop(); + // CraftBukkit start diff --git a/Remapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch b/Remapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch new file mode 100644 index 0000000000..d30ac6d736 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Tue, 31 Oct 2017 03:26:18 +0100 +Subject: [PATCH] Send attack SoundEffects only to players who can see the + attacker + + +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 3205bc2fb6c9031be68ff46dfca927e681163fa8..43868c1e2d2c858a4f02119c3238f615f9b1ee72 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -28,6 +28,7 @@ import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; ++import net.minecraft.network.protocol.game.ClientboundSoundPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; +@@ -1123,7 +1124,7 @@ public abstract class Player extends LivingEntity { + int i = b0 + EnchantmentHelper.getKnockbackBonus((LivingEntity) this); + + if (this.isSprinting() && flag) { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + ++i; + flag1 = true; + } +@@ -1198,7 +1199,7 @@ public abstract class Player extends LivingEntity { + } + } + +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + this.sweepAttack(); + } + +@@ -1226,15 +1227,15 @@ public abstract class Player extends LivingEntity { + } + + if (flag2) { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + this.crit(target); + } + + if (!flag2 && !flag3) { + if (flag) { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + } else { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + } + } + +@@ -1286,7 +1287,7 @@ public abstract class Player extends LivingEntity { + + this.applyExhaustion(level.spigotConfig.combatExhaustion, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value + } else { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + if (flag4) { + target.clearFire(); + } +@@ -1721,6 +1722,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); + } ++ // Paper start - send SoundEffect to everyone who can see fromEntity ++ private static void sendSoundEffect(Player fromEntity, double x, double y, double z, SoundEvent soundEffect, SoundSource soundCategory, float volume, float pitch) { ++ fromEntity.level.playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself ++ if (fromEntity instanceof ServerPlayer) { ++ ((ServerPlayer) fromEntity).connection.send(new ClientboundSoundPacket(soundEffect, soundCategory, x, y, z, volume, pitch)); ++ } ++ } ++ // Paper end + + // CraftBukkit start + public void causeFoodExhaustion(float exhaustion) { diff --git a/Remapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch b/Remapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch new file mode 100644 index 0000000000..c2626fdee4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 10 Nov 2017 23:03:12 -0500 +Subject: [PATCH] Option for maximum exp value when merging orbs + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 90ca51dfdbb3045dd528450225cba96f5834166e..6c692e58cde22003ecbf6dc5695799147c39905a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -342,4 +342,10 @@ public class PaperWorldConfig { + disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); + log("Creeper lingering effect: " + disableCreeperLingeringEffect); + } ++ ++ public int expMergeMaxValue; ++ private void expMergeMaxValue() { ++ expMergeMaxValue = getInt("experience-merge-max-value", -1); ++ log("Experience Merge Max Value: " + expMergeMaxValue); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 3f082b7fd50752728917a7da28cba4cb396a9fdf..7d6834796259e364196280ffa468b5bf999ec7b9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -587,16 +587,32 @@ public class CraftEventFactory { + net.minecraft.world.entity.ExperienceOrb xp = (net.minecraft.world.entity.ExperienceOrb) entity; + double radius = world.spigotConfig.expMerge; + if (radius > 0) { ++ // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics ++ final int maxValue = world.paperConfig.expMergeMaxValue; ++ final boolean mergeUnconditionally = world.paperConfig.expMergeMaxValue <= 0; ++ if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary ++ + List entities = world.getEntities(entity, entity.getBoundingBox().inflate(radius, radius, radius)); + for (Entity e : entities) { + if (e instanceof net.minecraft.world.entity.ExperienceOrb) { + net.minecraft.world.entity.ExperienceOrb loopItem = (net.minecraft.world.entity.ExperienceOrb) e; +- if (!loopItem.removed) { +- xp.value += loopItem.value; +- loopItem.remove(); ++ // Paper start ++ if (!loopItem.removed && !(maxValue > 0 && loopItem.value >= maxValue)) { ++ long newTotal = (long)xp.value + (long)loopItem.value; ++ if ((int) newTotal < 0) continue; // Overflow ++ if (maxValue > 0 && newTotal > (long)maxValue) { ++ loopItem.value = (int) (newTotal - maxValue); ++ xp.value = maxValue; ++ } else { ++ xp.value += loopItem.value; ++ loopItem.remove(); ++ } ++ // Paper end + } + } + } ++ ++ } // Paper end - End iteration skip check - All tweaking ends here + } + // Spigot end + } else if (!(entity instanceof ServerPlayer)) { diff --git a/Remapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch b/Remapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch new file mode 100644 index 0000000000..ae78b560ac --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: pkt77 +Date: Fri, 10 Nov 2017 23:46:34 -0500 +Subject: [PATCH] Add PlayerArmorChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/EquipmentSlot.java b/src/main/java/net/minecraft/world/entity/EquipmentSlot.java +index b686b7a2faa4fbce37dcc3598b3c956661b91aaa..17cd5f525a45058ce34c66c87f9c133033bb8f4b 100644 +--- a/src/main/java/net/minecraft/world/entity/EquipmentSlot.java ++++ b/src/main/java/net/minecraft/world/entity/EquipmentSlot.java +@@ -16,6 +16,7 @@ public enum EquipmentSlot { + this.name = s; + } + ++ public EquipmentSlot.Type getType() { return this.getType(); } // Paper - OBFHELPER + public EquipmentSlot.Type getType() { + return this.type; + } +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index d6b4fabd232958ae1fd5405c7129551951cd7765..8b0d1f4fbc43a6f37a5f9c453b5dd142a4f69745 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.entity; + ++import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; // Paper + import com.google.common.base.Objects; + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableMap; +@@ -2643,6 +2644,13 @@ public abstract class LivingEntity extends Entity { + ItemStack itemstack1 = this.getItemBySlot(enumitemslot); + + if (!ItemStack.matches(itemstack1, itemstack)) { ++ // Paper start - PlayerArmorChangeEvent ++ if (this instanceof ServerPlayer && enumitemslot.getType() == EquipmentSlot.Type.ARMOR) { ++ final org.bukkit.inventory.ItemStack oldItem = CraftItemStack.asBukkitCopy(itemstack); ++ final org.bukkit.inventory.ItemStack newItem = CraftItemStack.asBukkitCopy(itemstack1); ++ new PlayerArmorChangeEvent((Player) this.getBukkitEntity(), PlayerArmorChangeEvent.SlotType.valueOf(enumitemslot.name()), oldItem, newItem).callEvent(); ++ } ++ // Paper end + if (map == null) { + map = Maps.newEnumMap(EquipmentSlot.class); + } diff --git a/Remapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch b/Remapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch new file mode 100644 index 0000000000..c04d5e61cf --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: killme +Date: Sun, 12 Nov 2017 19:40:01 +0100 +Subject: [PATCH] Prevent logins from being processed when the player has + disconnected + + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 4b91699ddfa2ee298af5ba25447a85751facf4a4..ff83fb15d0d0adb62c630fc7aafc134972bf15fc 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -73,7 +73,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + // Paper end + if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) { +- this.handleAcceptedLogin(); ++ // Paper start - prevent logins to be processed even though disconnect was called ++ if (connection.isConnected()) { ++ this.handleAcceptedLogin(); ++ } ++ // Paper end + } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { + ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); + diff --git a/Remapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch b/Remapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch new file mode 100644 index 0000000000..939a2fed54 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 16 Nov 2017 12:12:41 +0000 +Subject: [PATCH] use CB BlockState implementations for captured blocks + +When modifying the world, CB will store a copy of the affected +blocks in order to restore their state in the case that the event +is cancelled. This change only modifies the collection of blocks +in the world by normal means, e.g. not during tree population, +as the potentially marginal overheads would serve no advantage. + +CB was using a CraftBlockState for all blocks, which causes issues +should any block that uses information beyond a data ID would suffer +from missing information, e.g. Skulls. + +By using CBs CraftBlock#getState(), we will maintain a proper copy of +the blockstate that will be valid for restoration, as opposed to dropping +information on restoration when the event is cancelled. + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 81713c97f35263f4ab8d14f8b707aac3d6afea11..b4248d46ccb1a95e21601bca1198512287edcabf 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -124,7 +124,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + public boolean captureBlockStates = false; + public boolean captureTreeGeneration = false; +- public Map capturedBlockStates = new java.util.LinkedHashMap<>(); ++ public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper + public Map capturedTileEntities = new HashMap<>(); + public List captureDrops; + public long ticksPerAnimalSpawns; +@@ -346,7 +346,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { + // CraftBukkit start - tree generation + if (this.captureTreeGeneration) { +- CapturedBlockState blockstate = capturedBlockStates.get(pos); ++ CraftBlockState blockstate = capturedBlockStates.get(pos); + if (blockstate == null) { + blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); + this.capturedBlockStates.put(pos.immutable(), blockstate); +@@ -366,7 +366,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // CraftBukkit start - capture blockstates + boolean captured = false; + if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) { +- CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, pos, flags); ++ CraftBlockState blockstate = (CraftBlockState) world.getBlockAt(pos.getX(), pos.getY(), pos.getZ()).getState(); // Paper - use CB getState to get a suitable snapshot ++ blockstate.setFlag(flags); // Paper - set flag + this.capturedBlockStates.put(pos.immutable(), blockstate); + captured = true; + } +@@ -624,7 +625,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public BlockState getBlockState(BlockPos pos) { + // CraftBukkit start - tree generation + if (captureTreeGeneration) { +- CapturedBlockState previous = capturedBlockStates.get(pos); ++ CraftBlockState previous = capturedBlockStates.get(pos); // Paper + if (previous != null) { + return previous.getHandle(); + } diff --git a/Remapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch b/Remapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch new file mode 100644 index 0000000000..d3837145f0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 6 Nov 2017 21:08:22 -0500 +Subject: [PATCH] API to get a BlockState without a snapshot + +This allows you to get a BlockState without creating a snapshot, operating +on the real tile entity. + +This is useful for where performance is needed + +also Avoid NPE during CraftBlockEntityState load if could not get TE + +If Tile Entity was null, correct Sign to return empty lines instead of null + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index d08ed44884726ca2ba4578226b8aa6244778f4c7..84012c2d12817e657b046bc168cc8eddebcd3831 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -47,6 +47,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + public BlockEntity(BlockEntityType type) { + this.worldPosition = BlockPos.ZERO; + this.type = type; ++ persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init + } + + // Paper start +@@ -95,7 +96,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + public void load(BlockState state, CompoundTag tag) { + this.worldPosition = new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); + // CraftBukkit start - read container +- this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ this.persistentDataContainer.clear(); // Paper - clear instead of reinit + + net.minecraft.nbt.Tag persistentDataTag = tag.get("PublicBukkitValues"); + if (persistentDataTag instanceof CompoundTag) { +@@ -245,7 +246,12 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + } + + // CraftBukkit start - add method ++ // Paper start + public InventoryHolder getOwner() { ++ return getOwner(true); ++ } ++ public InventoryHolder getOwner(boolean useSnapshot) { ++ // Paper end + if (level == null) return null; + // Spigot start + org.bukkit.block.Block block = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); +@@ -254,7 +260,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + return null; + } + // Spigot end +- org.bukkit.block.BlockState state = block.getState(); ++ org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper + if (state instanceof InventoryHolder) return (InventoryHolder) state; + return null; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 9d5b3801205e2800b0bcf238c5656321e3654f03..d73086970db19531db66c2e8af52da91d0b1ea28 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -313,6 +313,20 @@ public class CraftBlock implements Block { + + @Override + public BlockState getState() { ++ // Paper start - allow disabling the use of snapshots ++ return getState(true); ++ } ++ public BlockState getState(boolean useSnapshot) { ++ boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT; ++ CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot; ++ try { ++ return getState0(); ++ } finally { ++ CraftBlockEntityState.DISABLE_SNAPSHOT = prev; ++ } ++ } ++ public BlockState getState0() { ++ // Paper end + Material material = getType(); + + switch (material) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +index e89a93082fe07fdb14df8ffef5beca5bd52d7866..730fda7f0bf02400d349959e9cc2aafaed000b21 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +@@ -26,20 +26,40 @@ public class CraftBlockEntityState extends CraftBlockStat + this.tileEntity = tileEntityClass.cast(world.getHandle().getBlockEntity(this.getPosition())); + Preconditions.checkState(this.tileEntity != null, "Tile is null, asynchronous access? %s", block); + ++ // Paper start ++ this.snapshotDisabled = DISABLE_SNAPSHOT; ++ if (DISABLE_SNAPSHOT) { ++ this.snapshot = this.tileEntity; ++ } else { ++ this.snapshot = this.createSnapshot(this.tileEntity); ++ } + // copy tile entity data: +- this.snapshot = this.createSnapshot(tileEntity); +- this.load(snapshot); ++ if(this.snapshot != null) { ++ this.load(this.snapshot); ++ } ++ // Paper end + } + ++ public final boolean snapshotDisabled; // Paper ++ public static boolean DISABLE_SNAPSHOT = false; // Paper ++ + public CraftBlockEntityState(Material material, T tileEntity) { + super(material); + + this.tileEntityClass = (Class) tileEntity.getClass(); + this.tileEntity = tileEntity; +- ++ // Paper start ++ this.snapshotDisabled = DISABLE_SNAPSHOT; ++ if (DISABLE_SNAPSHOT) { ++ this.snapshot = this.tileEntity; ++ } else { ++ this.snapshot = this.createSnapshot(this.tileEntity); ++ } + // copy tile entity data: +- this.snapshot = this.createSnapshot(tileEntity); +- this.load(snapshot); ++ if(this.snapshot != null) { ++ this.load(this.snapshot); ++ } ++ // Paper end + } + + private T createSnapshot(T tileEntity) { +diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java +index e3664110bef9315cfde5b61dde98dce77016600e..10ba8b810c1759adc439f753d36108e30cf70140 100644 +--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java ++++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java +@@ -155,4 +155,10 @@ public final class CraftPersistentDataContainer implements PersistentDataContain + public Map serialize() { + return (Map) CraftNBTTagConfigSerializer.serialize(toTagCompound()); + } ++ ++ // Paper start ++ public void clear() { ++ this.customDataTags.clear(); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch b/Remapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch new file mode 100644 index 0000000000..1bd4fdfc05 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 26 Nov 2017 13:19:58 -0500 +Subject: [PATCH] AsyncTabCompleteEvent + +Let plugins be able to control tab completion of commands and chat async. + +This will be useful for frameworks like ACF so we can define async safe completion handlers, +and avoid going to main for tab completions. + +Especially useful if you need to query a database in order to obtain the results for tab +completion, such as offline players. + +Also adds isCommand and getLocation to the sync TabCompleteEvent + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 525728268f56470fdc24c4fd2f19d66943447778..8d0c44b6c2c99d5161c5d4b79209b79ff6db75e4 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -711,10 +711,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + @Override + public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { +- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); ++ // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async + // CraftBukkit start + if (chatSpamField.addAndGet(this, 1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { +- this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0])); ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper + return; + } + // CraftBukkit end +@@ -724,12 +724,35 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + stringreader.skip(); + } + +- ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); ++ // Paper start - async tab completion ++ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; ++ java.util.List completions = new java.util.ArrayList<>(); ++ String buffer = packet.getCommand(); ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, ++ buffer, true, null); ++ event.callEvent(); ++ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); ++ // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server ++ if (!event.isHandled()) { ++ if (!event.isCancelled()) { + +- this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { +- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer +- this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); +- }); ++ this.server.scheduleOnMain(() -> { // Paper - This needs to be on main ++ ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); ++ ++ this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { ++ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer ++ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); ++ }); ++ }); ++ } ++ } else if (!completions.isEmpty()) { ++ com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); ++ ++ builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); ++ completions.forEach(builder::suggest); ++ player.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), builder.buildFuture().join())); ++ } ++ // Paper end - async tab completion + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index df68599520189e2699c8521d6c6ab7235612af33..10addb128a357e7719854bf4f9d75f5def32b27d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1850,7 +1850,7 @@ public final class CraftServer implements Server { + offers = tabCompleteChat(player, message); + } + +- TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers); ++ TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? net.minecraft.server.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), new BlockPos(pos)) : null); // Paper + getPluginManager().callEvent(tabEvent); + + return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index a957695457cf3252848ce6ef37069692841b8e28..c5e00bd9e2790992202aadf8eec2002fc88c78f1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -28,6 +28,39 @@ public class ConsoleCommandCompleter implements Completer { + public void complete(LineReader reader, ParsedLine line, List candidates) { + final CraftServer server = this.server.server; + final String buffer = line.line(); ++ // Async Tab Complete ++ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; ++ java.util.List completions = new java.util.ArrayList<>(); ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, ++ buffer, true, null); ++ event.callEvent(); ++ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); ++ ++ if (event.isCancelled() || event.isHandled()) { ++ // Still fire sync event with the provided completions, if someone is listening ++ if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { ++ List finalCompletions = completions; ++ Waitable> syncCompletions = new Waitable>() { ++ @Override ++ protected List evaluate() { ++ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); ++ return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); ++ } ++ }; ++ server.getServer().processQueue.add(syncCompletions); ++ try { ++ completions = syncCompletions.get(); ++ } catch (InterruptedException | ExecutionException e1) { ++ e1.printStackTrace(); ++ } ++ } ++ ++ if (!completions.isEmpty()) { ++ candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); ++ } ++ return; ++ } ++ + // Paper end + Waitable> waitable = new Waitable>() { + @Override diff --git a/Remapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch b/Remapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch new file mode 100644 index 0000000000..5d0147c515 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 29 Nov 2017 22:18:54 -0500 +Subject: [PATCH] Avoid NPE in PathfinderGoalTempt + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java +index 186025458e923d153e9e47c2be147a9bb53db517..11ca6a752bac4ba4bc683bef844d204b739fab63 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java +@@ -63,7 +63,7 @@ public class TemptGoal extends Goal { + } + this.target = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle(); + } +- return tempt; ++ return tempt && this.target != null; // Paper - must have target - plugin might of cancelled + // CraftBukkit end + } + } diff --git a/Remapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch b/Remapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch new file mode 100644 index 0000000000..fe7129d330 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 22:02:53 -0500 +Subject: [PATCH] PlayerPickupExperienceEvent + +Allows plugins to cancel a player picking up an experience orb + +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 3ddb0a9f15c920c9a2080f76edfda0504c1e287a..885c5a920204a31b24c7d360390eaf4177c30698 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -5,6 +5,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.FluidTags; + import net.minecraft.tags.Tag; +@@ -231,7 +232,7 @@ public class ExperienceOrb extends Entity { + @Override + public void playerTouch(Player player) { + if (!this.level.isClientSide) { +- if (this.throwTime == 0 && player.takeXpDelay == 0) { ++ if (this.throwTime == 0 && player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((ServerPlayer) player).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper + player.takeXpDelay = 2; + player.take(this, 1); + Entry entry = EnchantmentHelper.getRandomItemWith(Enchantments.MENDING, (LivingEntity) player, ItemStack::isDamaged); diff --git a/Remapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch b/Remapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch new file mode 100644 index 0000000000..28b23c94bd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 22:57:26 -0500 +Subject: [PATCH] ExperienceOrbMergeEvent + +Fired when the server is about to merge 2 experience orbs +Plugins can cancel this if they want to ensure experience orbs do not lose important +metadata such as spawn reason, or conditionally move data from source to target. + +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 7d6834796259e364196280ffa468b5bf999ec7b9..5e8ff18f98b03741ccbb927f87499ae36d775a86 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -597,7 +597,7 @@ public class CraftEventFactory { + if (e instanceof net.minecraft.world.entity.ExperienceOrb) { + net.minecraft.world.entity.ExperienceOrb loopItem = (net.minecraft.world.entity.ExperienceOrb) e; + // Paper start +- if (!loopItem.removed && !(maxValue > 0 && loopItem.value >= maxValue)) { ++ if (!loopItem.removed && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper + long newTotal = (long)xp.value + (long)loopItem.value; + if ((int) newTotal < 0) continue; // Overflow + if (maxValue > 0 && newTotal > (long)maxValue) { diff --git a/Remapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch b/Remapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch new file mode 100644 index 0000000000..24cf0a602e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 20 Dec 2017 17:36:49 -0500 +Subject: [PATCH] Ability to apply mending to XP API + +This allows plugins that give players the ability to apply the experience +points to the Item Mending formula, which will repair an item instead +of giving the player experience points. + +Both an API To standalone mend, and apply mending logic to .giveExp has been added. + +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 885c5a920204a31b24c7d360390eaf4177c30698..52b90ef3a145325209d3d903a2b7c9a44c332cbe 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -264,10 +264,12 @@ public class ExperienceOrb extends Entity { + } + } + ++ public final int durToXp(int i) { return durabilityToXp(i); } // Paper OBFHELPER + private int durabilityToXp(int repairAmount) { + return repairAmount / 2; + } + ++ public final int xpToDur(int i) { return xpToDurability(i); } // Paper OBFHELPER + private int xpToDurability(int experienceAmount) { + return experienceAmount * 2; + } +diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java +index 045f937f0b7acd73469b65897bea2ca9036acf22..c82e1b6e3ec98530099fd6452fdaaefebfd99b33 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java +@@ -269,8 +269,8 @@ public class EnchantmentHelper { + return getItemEnchantmentLevel(Enchantments.CHANNELING, stack) > 0; + } + +- @Nullable +- public static Entry getRandomItemWith(Enchantment enchantment, LivingEntity entity) { ++ public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, LivingEntity entityliving) { Entry entry = getRandomItemWith(enchantment, entityliving); return entry != null ? entry.getValue() : ItemStack.NULL_ITEM; } // Paper - OBFHELPER ++ @Nullable public static Entry getRandomItemWith(Enchantment enchantment, LivingEntity entity) { + return getRandomItemWith(enchantment, entity, (itemstack) -> { + 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 8a5bf0b83c1e65f07e14da0e053a64c34976b91a..efdcb8dac8db15c4bbaed84a7861ce98339e516a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -58,11 +58,14 @@ import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.network.ServerGamePacketListenerImpl; + import net.minecraft.server.players.UserWhiteListEntry; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeMap; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.inventory.AbstractContainerMenu; ++import net.minecraft.world.item.enchantment.EnchantmentHelper; ++import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.GameType; + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.saveddata.maps.MapDecoration; +@@ -1176,8 +1179,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return GameMode.getByValue(getHandle().gameMode.getGameModeForPlayer().getId()); + } + ++ // Paper start + @Override +- public void giveExp(int exp) { ++ public int applyMending(int amount) { ++ ServerPlayer handle = getHandle(); ++ // Logic copied from EntityExperienceOrb and remapped to unobfuscated methods/properties ++ net.minecraft.world.item.ItemStack itemstack = EnchantmentHelper.getRandomEquippedItemWithEnchant(Enchantments.MENDING, handle); ++ if (!itemstack.isEmpty() && itemstack.getItem().canBeDepleted()) { ++ ++ ExperienceOrb orb = net.minecraft.world.entity.EntityType.EXPERIENCE_ORB.create(handle.level); ++ orb.value = amount; ++ orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM; ++ orb.setPosRaw(handle.getX(), handle.getY(), handle.getZ()); ++ ++ int i = Math.min(orb.xpToDur(amount), itemstack.getDamageValue()); ++ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, i); ++ i = event.getRepairAmount(); ++ orb.removed = true; ++ if (!event.isCancelled()) { ++ amount -= orb.durToXp(i); ++ itemstack.setDamageValue(itemstack.getDamageValue() - i); ++ } ++ } ++ return amount; ++ } ++ ++ @Override ++ public void giveExp(int exp, boolean applyMending) { ++ if (applyMending) { ++ exp = this.applyMending(exp); ++ } ++ // Paper end + getHandle().giveExperiencePoints(exp); + } + diff --git a/Remapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch b/Remapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch new file mode 100644 index 0000000000..94fb614365 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 11 Jan 2018 16:47:28 -0600 +Subject: [PATCH] Make max squid spawn height configurable + +I don't know why upstream made only the minimum height configurable but +whatever + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6c692e58cde22003ecbf6dc5695799147c39905a..3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -348,4 +348,9 @@ public class PaperWorldConfig { + expMergeMaxValue = getInt("experience-merge-max-value", -1); + log("Experience Merge Max Value: " + expMergeMaxValue); + } ++ ++ public double squidMaxSpawnHeight; ++ private void squidMaxSpawnHeight() { ++ squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java +index 0b782c77f6d93002c35b123044b5a3eb03e63672..5a7582fd4f8e883d2f08a0227932c17d7576b957 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java +@@ -196,7 +196,8 @@ public class Squid extends WaterAnimal { + } + + public static boolean checkSquidSpawnRules(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) { +- return pos.getY() > world.getLevel().spigotConfig.squidSpawnRangeMin && pos.getY() < world.getSeaLevel(); // Spigot ++ final double maxHeight = world.getLevel().paperConfig.squidMaxSpawnHeight > 0 ? world.getLevel().paperConfig.squidMaxSpawnHeight : world.getSeaLevel(); // Paper ++ return pos.getY() > world.getLevel().spigotConfig.squidSpawnRangeMin && pos.getY() < maxHeight; // Spigot // Paper + } + + public void setMovementVector(float x, float y, float z) { diff --git a/Remapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch b/Remapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch new file mode 100644 index 0000000000..341927c26e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch @@ -0,0 +1,215 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 14 Jan 2018 17:01:31 -0500 +Subject: [PATCH] PreCreatureSpawnEvent + +Adds an event to fire before an Entity is created, so that plugins that need to cancel +CreatureSpawnEvent can do so from this event instead. + +Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste +as it's done after the Entity object has been fully created. + +Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event +instead and save a lot of server resources. + +See: https://github.com/PaperMC/Paper/issues/917 + +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index e3d92d1d35911b2960a7ca82bd4f324d285d0533..e39d950783599b01271bdb7e67fe68b46af0c49c 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -17,6 +17,7 @@ import net.minecraft.nbt.ListTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.BlockTags; +@@ -317,6 +318,20 @@ public class EntityType { + + @Nullable + public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // Paper start - Call PreCreatureSpawnEvent ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath()); ++ if (type != null) { ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ MCUtil.toLocation(worldserver, blockposition), ++ type, ++ spawnReason ++ ); ++ if (!event.callEvent()) { ++ return null; ++ } ++ } ++ // Paper end + T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); + + if (t0 != null) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java +index f3a7807a20b279056d5640ab02aa77f7b1dabc2a..880d69bad933294a2cfdea9adb3e648e29eb42be 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java +@@ -33,8 +33,8 @@ public class GolemSensor extends Sensor { + Optional> optional = entityliving.getBrain().getMemory(MemoryModuleType.MOBS); + + if (optional.isPresent()) { +- boolean flag = ((List) optional.get()).stream().anyMatch((entityliving1) -> { +- return entityliving1.getEntityType().equals(EntityType.IRON_GOLEM); ++ boolean flag = optional.get().stream().anyMatch((entityliving1) -> { // Paper - decompile fixes ++ return entityliving1.getType().equals(EntityType.IRON_GOLEM); + }); + + if (flag) { +@@ -44,6 +44,7 @@ public class GolemSensor extends Sensor { + } + } + ++ public static void setDetectedRecently(LivingEntity entityLiving) { golemDetected(entityLiving); } // Paper - OBFHELPER + public static void golemDetected(LivingEntity entityliving) { + entityliving.getBrain().setMemoryWithExpiry(MemoryModuleType.GOLEM_DETECTED_RECENTLY, true, 600L); + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index a66fab2e04a5d87ced139ed15d2434c5ffcec695..eed6265dc8275921a18fc5f4970ba131ba782132 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.DebugPackets; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvent; +@@ -942,6 +943,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + BlockPos blockposition1 = this.findSpawnPositionForGolemInColumn(blockposition, d0, d1); + + if (blockposition1 != null) { ++ // Paper start - Call PreCreatureSpawnEvent ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ MCUtil.toLocation(level, blockposition1), ++ org.bukkit.entity.EntityType.IRON_GOLEM, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE ++ ); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ GolemSensor.golemDetected(this); // Set Golem Last Seen to stop it from spawning another one ++ return null; ++ } ++ break; ++ } ++ // Paper end + IronGolem entityirongolem = (IronGolem) EntityType.IRON_GOLEM.create(world, (CompoundTag) null, (Component) null, (Player) null, blockposition1, MobSpawnType.MOB_SUMMONED, false, false); + + if (entityirongolem != null) { +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 4582fc1bb767214241568fbc22b0ee2cbf3322e0..ac572eba10a7239d71dfae060f623b076d4252ce 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -12,6 +12,7 @@ import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.StringUtil; + import net.minecraft.util.WeighedRandom; +@@ -125,6 +126,27 @@ public abstract class BaseSpawner { + ServerLevel worldserver = (ServerLevel) world; + + if (SpawnPlacements.checkSpawnRules((EntityType) optional.get(), worldserver, MobSpawnType.SPAWNER, new BlockPos(d3, d4, d5), world.getRandom())) { ++ // Paper start ++ EntityType entityType = optional.get(); ++ String key = EntityType.getKey(entityType).getPath(); ++ ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); ++ if (type != null) { ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ MCUtil.toLocation(world, d3, d4, d5), ++ type, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER ++ ); ++ if (!event.callEvent()) { ++ flag = true; ++ if (event.shouldAbortSpawn()) { ++ break; ++ } ++ continue; ++ } ++ } ++ // Paper end + Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> { + entity1.moveTo(d3, d4, d5, entity1.yRot, entity1.xRot); + return entity1; +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index a19ac1cb7e4d8d478648a048b2bfa0daf85a80c9..8a71eaf2855be0d415d1f7b18dbec98353fe5b47 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -15,6 +15,7 @@ import net.minecraft.core.Direction; + import net.minecraft.core.Position; + import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.FluidTags; +@@ -214,9 +215,16 @@ public final class NaturalSpawner { + j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); + } + +- if (isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ // Paper start ++ Boolean doSpawning = a(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); ++ if (doSpawning == null) { ++ return; ++ } ++ if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ // Paper end + Mob entityinsentient = getMobForSpawn(world, biomesettingsmobs_c.type); + ++ + if (entityinsentient == null) { + return; + } +@@ -269,17 +277,33 @@ public final class NaturalSpawner { + } + } + +- private static boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { +- EntityType entitytypes = spawnEntry.type; ++ private static Boolean a(ServerLevel worldserver, MobCategory enumcreaturetype, StructureFeatureManager structuremanager, ChunkGenerator chunkgenerator, MobSpawnSettings.SpawnerData biomesettingsmobs_c, BlockPos.MutableBlockPos blockposition_mutableblockposition, double d0) { // Paper ++ EntityType entitytypes = biomesettingsmobs_c.type; ++ // Paper start ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(entitytypes).getPath()); ++ if (type != null) { ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ MCUtil.toLocation(worldserver, blockposition_mutableblockposition), ++ type, SpawnReason.NATURAL ++ ); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ return null; ++ } ++ return false; ++ } ++ } ++ // Paper end + + if (entitytypes.getCategory() == MobCategory.MISC) { + return false; +- } else if (!entitytypes.canSpawnFarFromPlayer() && squaredDistance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { ++ } else if (!entitytypes.canSpawnFarFromPlayer() && d0 > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { + return false; +- } else if (entitytypes.canSummon() && canSpawnMobAt(world, structureAccessor, chunkGenerator, group, spawnEntry, (BlockPos) pos)) { ++ } else if (entitytypes.canSummon() && canSpawnMobAt(worldserver, structuremanager, chunkgenerator, enumcreaturetype, biomesettingsmobs_c, (BlockPos) blockposition_mutableblockposition)) { + SpawnPlacements.Type entitypositiontypes_surface = SpawnPlacements.getPlacementType(entitytypes); + +- return !isSpawnPositionOk(entitypositiontypes_surface, (LevelReader) world, pos, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, world, MobSpawnType.NATURAL, pos, world.random) ? false : world.noCollision(entitytypes.getAABB((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D))); ++ return !isSpawnPositionOk(entitypositiontypes_surface, (LevelReader) worldserver, blockposition_mutableblockposition, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, worldserver, MobSpawnType.NATURAL, blockposition_mutableblockposition, worldserver.random) ? false : worldserver.noCollision(entitytypes.getAABB((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D))); + } else { + return false; + } diff --git a/Remapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch b/Remapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch new file mode 100644 index 0000000000..0b2a988e3b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 14 Jan 2018 17:36:02 -0500 +Subject: [PATCH] PlayerNaturallySpawnCreaturesEvent + +This event can be used for when you want to exclude a certain player +from triggering monster spawns on a server. + +Also a highly more effecient way to blanket block spawns in a world + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 3b6f35b695117bd2b0c71b994efc55fa1084eddc..97d5437df10a6d0124e944404e88650547b7d8a8 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -964,12 +964,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; + chunkRange = (chunkRange > 8) ? 8 : chunkRange; + +- double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; ++ final int finalChunkRange = chunkRange; // Paper for lambda below ++ //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event + // Spigot end + long i = chunkcoordintpair.toLong(); + + return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { +- return !entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot ++ // Paper start - ++ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; ++ double blockRange = 16384.0D; ++ if (reducedRange) { ++ event = entityplayer.playerNaturallySpawnedEvent; ++ if (event == null || event.isCancelled()) return false; ++ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); ++ } ++ ++ return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot ++ // Paper end + }); + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index d0b0fdaf5451bcc7f7ac7dab28aa59ef77e6dd97..a7122a0411f4a8656efd4facde3403c8093bc8a6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -612,6 +612,15 @@ public class ServerChunkCache extends ChunkSource { + this.level.getProfiler().pop(); + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper ++ //Paper start - call player naturally spawn event ++ int chunkRange = level.spigotConfig.mobSpawnRange; ++ chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; ++ chunkRange = Math.min(chunkRange, 8); ++ for (ServerPlayer entityPlayer : this.level.players()) { ++ entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); ++ entityPlayer.playerNaturallySpawnedEvent.callEvent(); ++ }; ++ // Paper end + this.level.timings.chunkTicks.startTiming(); // Paper + this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 4ff66138fa43cf932b95d6d3dc050a9cd7b28ad4..0fa977a31cf945b74f3a046b6be302b10f494ad1 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1,5 +1,6 @@ + package net.minecraft.server.level; + ++import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent; + import com.google.common.collect.Lists; + import com.mojang.authlib.GameProfile; + import com.mojang.datafixers.util.Either; +@@ -225,6 +226,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public boolean sentListPacket = false; + public Integer clientViewDistance; + // CraftBukkit end ++ public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper + + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + diff --git a/Remapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch b/Remapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch new file mode 100644 index 0000000000..746bff56a9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 19 Jan 2018 00:36:25 -0500 +Subject: [PATCH] Add setPlayerProfile API for Skulls + +This allows you to create already filled textures on Skulls to avoid texture lookups +which commonly cause rate limit issues with Mojang API + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java +index 2047ea32489d03051783d18a0dbaf456bfdbb2a1..a06c51a56846750ce59a70e9698c2b57c3517aad 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java +@@ -1,5 +1,7 @@ + package org.bukkit.craftbukkit.block; + ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; + import com.google.common.base.Preconditions; + import com.mojang.authlib.GameProfile; + import net.minecraft.server.MinecraftServer; +@@ -15,6 +17,7 @@ import org.bukkit.block.data.BlockData; + import org.bukkit.block.data.Directional; + import org.bukkit.block.data.Rotatable; + import org.bukkit.craftbukkit.entity.CraftPlayer; ++import javax.annotation.Nullable; + + public class CraftSkull extends CraftBlockEntityState implements Skull { + +@@ -105,6 +108,20 @@ public class CraftSkull extends CraftBlockEntityState implemen + } + } + ++ // Paper start ++ @Override ++ public void setPlayerProfile(PlayerProfile profile) { ++ Preconditions.checkNotNull(profile, "profile"); ++ this.profile = CraftPlayerProfile.asAuthlibCopy(profile); ++ } ++ ++ @Nullable ++ @Override ++ public PlayerProfile getPlayerProfile() { ++ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; ++ } ++ // Paper end ++ + @Override + public BlockFace getRotation() { + BlockData blockData = getBlockData(); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +index 750661540f55d3c59119dcc909e706e571a2123b..aa64ffc23d8941ff05ea7791ddd628c3c6be90e4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +@@ -4,10 +4,8 @@ import com.google.common.collect.ImmutableMap.Builder; + import com.mojang.authlib.GameProfile; + import java.util.Map; + import java.util.UUID; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.nbt.NbtUtils; +-import net.minecraft.nbt.Tag; +-import net.minecraft.world.level.block.entity.SkullBlockEntity; ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; + import org.bukkit.Bukkit; + import org.bukkit.Material; + import org.bukkit.OfflinePlayer; +@@ -18,6 +16,11 @@ import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta; + import org.bukkit.craftbukkit.util.CraftMagicNumbers; + import org.bukkit.inventory.meta.SkullMeta; + ++import javax.annotation.Nullable; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtUtils; ++import net.minecraft.nbt.Tag; ++import net.minecraft.world.level.block.entity.SkullBlockEntity; + @DelegateDeserialization(SerializableMeta.class) + class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + +@@ -149,6 +152,19 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + return hasOwner() ? profile.getName() : null; + } + ++ // Paper start ++ @Override ++ public void setPlayerProfile(@Nullable PlayerProfile profile) { ++ setProfile((profile == null) ? null : CraftPlayerProfile.asAuthlibCopy(profile)); ++ } ++ ++ @Nullable ++ @Override ++ public PlayerProfile getPlayerProfile() { ++ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; ++ } ++ // Paper end ++ + @Override + public OfflinePlayer getOwningPlayer() { + if (hasOwner()) { +@@ -175,8 +191,8 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + } else { + // Paper start - Use Online Players Skull + GameProfile newProfile = null; +- net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); +- if (player != null) newProfile = player.getProfile(); ++ net.minecraft.server.level.ServerPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); ++ if (player != null) newProfile = player.getGameProfile(); + if (newProfile == null) newProfile = new GameProfile(null, name); + setProfile(newProfile); + // Paper end diff --git a/Remapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch b/Remapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch new file mode 100644 index 0000000000..30643d081c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 2 Jan 2018 00:31:26 -0500 +Subject: [PATCH] Fill Profile Property Events + +Allows plugins to populate profile properties from local sources to avoid calls out to Mojang API +to fill in textures for example. + +If Mojang API does need to be hit, event fire so you can get the results. + +This is useful for implementing a ProfileCache for Player Skulls + +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java +index 93d73c27340645c7502acafdc0b2cfbc1a759dd8..5c7d2ee19243d0911a3a00af3ae42078a2ccba94 100644 +--- a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java +@@ -1,6 +1,8 @@ + package com.destroystokyo.paper.profile; + + import com.mojang.authlib.Environment; ++import com.destroystokyo.paper.event.profile.FillProfileEvent; ++import com.destroystokyo.paper.event.profile.PreFillProfileEvent; + import com.mojang.authlib.GameProfile; + import com.mojang.authlib.minecraft.MinecraftProfileTexture; + import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; +@@ -20,7 +22,15 @@ public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionServi + + @Override + public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { +- return super.fillProfileProperties(profile, requireSecure); ++ CraftPlayerProfile playerProfile = (CraftPlayerProfile) CraftPlayerProfile.asBukkitMirror(profile); ++ new PreFillProfileEvent(playerProfile).callEvent(); ++ profile = playerProfile.getGameProfile(); ++ if (profile.isComplete() && profile.getProperties().containsKey("textures")) { ++ return profile; ++ } ++ GameProfile gameProfile = super.fillProfileProperties(profile, requireSecure); ++ new FillProfileEvent(CraftPlayerProfile.asBukkitMirror(gameProfile)).callEvent(); ++ return gameProfile; + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch b/Remapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch new file mode 100644 index 0000000000..6190b30a26 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 19 Jan 2018 08:15:29 -0600 +Subject: [PATCH] PlayerAdvancementCriterionGrantEvent + + +diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index 8df1803754817707a5ad292f65276871dacc4508..5ab62fc74085bbbb0c81b2f4d16a35c9345cd1f1 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -297,6 +297,12 @@ public class PlayerAdvancements { + boolean flag1 = advancementprogress.isDone(); + + if (advancementprogress.a(criterionName)) { ++ // Paper start ++ if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.bukkit, criterionName).callEvent()) { ++ advancementprogress.b(criterionName); ++ return false; ++ } ++ // Paper end + this.unregisterListeners(advancement); + this.progressChanged.add(advancement); + flag = true; diff --git a/Remapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch b/Remapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch new file mode 100644 index 0000000000..14798cca5e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch @@ -0,0 +1,296 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 27 Jan 2018 17:04:14 -0500 +Subject: [PATCH] Add ArmorStand Item Meta + +This is adds basic item meta for armor stands. It does not add all +possible metadata however. + +There are armor, hand, and equipment types, as well as position data +that can also be added here. This initial addition should serve a +starting point for future additions in this area. + +Fixes GH-559 + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java +index 783b9c7283492fb71776b61f9820c21a39868c47..6521f4f6f660885f59f024640239609fb67d691f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java +@@ -9,9 +9,22 @@ import org.bukkit.configuration.serialization.DelegateDeserialization; + import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey; + + @DelegateDeserialization(CraftMetaItem.SerializableMeta.class) +-public class CraftMetaArmorStand extends CraftMetaItem { ++public class CraftMetaArmorStand extends CraftMetaItem implements com.destroystokyo.paper.inventory.meta.ArmorStandMeta { // Paper + + static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag"); ++ // Paper start ++ static final ItemMetaKey INVISIBLE = new ItemMetaKey("Invisible", "invisible"); ++ static final ItemMetaKey NO_BASE_PLATE = new ItemMetaKey("NoBasePlate", "no-base-plate"); ++ static final ItemMetaKey SHOW_ARMS = new ItemMetaKey("ShowArms", "show-arms"); ++ static final ItemMetaKey SMALL = new ItemMetaKey("Small", "small"); ++ static final ItemMetaKey MARKER = new ItemMetaKey("Marker", "marker"); ++ ++ private boolean invisible; ++ private boolean noBasePlate; ++ private boolean showArms; ++ private boolean small; ++ private boolean marker; ++ // Paper end + CompoundTag entityTag; + + CraftMetaArmorStand(CraftMetaItem meta) { +@@ -22,6 +35,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { + } + + CraftMetaArmorStand armorStand = (CraftMetaArmorStand) meta; ++ // Paper start ++ this.invisible = armorStand.invisible; ++ this.noBasePlate = armorStand.noBasePlate; ++ this.showArms = armorStand.showArms; ++ this.small = armorStand.small; ++ this.marker = armorStand.marker; ++ // Paper end + this.entityTag = armorStand.entityTag; + } + +@@ -30,11 +50,47 @@ public class CraftMetaArmorStand extends CraftMetaItem { + + if (tag.contains(ENTITY_TAG.NBT)) { + entityTag = tag.getCompound(ENTITY_TAG.NBT); ++ ++ // Paper start ++ if (entityTag.contains(INVISIBLE.NBT)) { ++ invisible = entityTag.getBoolean(INVISIBLE.NBT); ++ } ++ ++ if (entityTag.contains(NO_BASE_PLATE.NBT)) { ++ noBasePlate = entityTag.getBoolean(NO_BASE_PLATE.NBT); ++ } ++ ++ if (entityTag.contains(SHOW_ARMS.NBT)) { ++ showArms = entityTag.getBoolean(SHOW_ARMS.NBT); ++ } ++ ++ if (entityTag.contains(SMALL.NBT)) { ++ small = entityTag.getBoolean(SMALL.NBT); ++ } ++ ++ if (entityTag.contains(MARKER.NBT)) { ++ marker = entityTag.getBoolean(MARKER.NBT); ++ } ++ // Paper end + } + } + + CraftMetaArmorStand(Map map) { + super(map); ++ ++ // Paper start ++ boolean invis = SerializableMeta.getBoolean(map, INVISIBLE.BUKKIT); ++ boolean noBase = SerializableMeta.getBoolean(map, NO_BASE_PLATE.BUKKIT); ++ boolean showArms = SerializableMeta.getBoolean(map, SHOW_ARMS.BUKKIT); ++ boolean small = SerializableMeta.getBoolean(map, SMALL.BUKKIT); ++ boolean marker = SerializableMeta.getBoolean(map, MARKER.BUKKIT); ++ ++ this.invisible = invis; ++ this.noBasePlate = noBase; ++ this.showArms = showArms; ++ this.small = small; ++ this.marker = marker; ++ // Paper end + } + + @Override +@@ -57,6 +113,32 @@ public class CraftMetaArmorStand extends CraftMetaItem { + void applyToItem(CompoundTag tag) { + super.applyToItem(tag); + ++ // Paper start ++ if (!isArmorStandEmpty() && entityTag == null) { ++ entityTag = new CompoundTag(); ++ } ++ ++ if (isInvisible()) { ++ entityTag.putBoolean(INVISIBLE.NBT, invisible); ++ } ++ ++ if (hasNoBasePlate()) { ++ entityTag.putBoolean(NO_BASE_PLATE.NBT, noBasePlate); ++ } ++ ++ if (shouldShowArms()) { ++ entityTag.putBoolean(SHOW_ARMS.NBT, showArms); ++ } ++ ++ if (isSmall()) { ++ entityTag.putBoolean(SMALL.NBT, small); ++ } ++ ++ if (isMarker()) { ++ entityTag.putBoolean(MARKER.NBT, marker); ++ } ++ // Paper end ++ + if (entityTag != null) { + tag.put(ENTITY_TAG.NBT, entityTag); + } +@@ -78,7 +160,7 @@ public class CraftMetaArmorStand extends CraftMetaItem { + } + + boolean isArmorStandEmpty() { +- return !(entityTag != null); ++ return !(isInvisible() || hasNoBasePlate() || shouldShowArms() || isSmall() || isMarker() || entityTag != null); + } + + @Override +@@ -89,7 +171,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { + if (meta instanceof CraftMetaArmorStand) { + CraftMetaArmorStand that = (CraftMetaArmorStand) meta; + +- return entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : entityTag == null; ++ // Paper start ++ return invisible == that.invisible && ++ noBasePlate == that.noBasePlate && ++ showArms == that.showArms && ++ small == that.small && ++ marker == that.marker; ++ // Paper end + } + return true; + } +@@ -104,9 +192,14 @@ public class CraftMetaArmorStand extends CraftMetaItem { + final int original; + int hash = original = super.applyHash(); + +- if (entityTag != null) { +- hash = 73 * hash + entityTag.hashCode(); +- } ++ // Paper start ++ hash += entityTag != null ? 73 * hash + entityTag.hashCode() : 0; ++ hash += isInvisible() ? 61 * hash + 1231 : 0; ++ hash += hasNoBasePlate() ? 61 * hash + 1231 : 0; ++ hash += shouldShowArms() ? 61 * hash + 1231 : 0; ++ hash += isSmall() ? 61 * hash + 1231 : 0; ++ hash += isMarker() ? 61 * hash + 1231 : 0; ++ // Paper end + + return original != hash ? CraftMetaArmorStand.class.hashCode() ^ hash : hash; + } +@@ -115,6 +208,28 @@ public class CraftMetaArmorStand extends CraftMetaItem { + Builder serialize(Builder builder) { + super.serialize(builder); + ++ // Paper start ++ if (isInvisible()) { ++ builder.put(INVISIBLE.BUKKIT, invisible); ++ } ++ ++ if (hasNoBasePlate()) { ++ builder.put(NO_BASE_PLATE.BUKKIT, noBasePlate); ++ } ++ ++ if (shouldShowArms()) { ++ builder.put(SHOW_ARMS.BUKKIT, showArms); ++ } ++ ++ if (isSmall()) { ++ builder.put(SMALL.BUKKIT, small); ++ } ++ ++ if (isMarker()) { ++ builder.put(MARKER.BUKKIT, marker); ++ } ++ // Paper end ++ + return builder; + } + +@@ -128,4 +243,56 @@ public class CraftMetaArmorStand extends CraftMetaItem { + + return clone; + } ++ ++ // Paper start ++ @Override ++ public boolean isInvisible() { ++ return invisible; ++ } ++ ++ @Override ++ public boolean hasNoBasePlate() { ++ return noBasePlate; ++ } ++ ++ @Override ++ public boolean shouldShowArms() { ++ return showArms; ++ } ++ ++ @Override ++ public boolean isSmall() { ++ return small; ++ } ++ ++ @Override ++ public boolean isMarker() { ++ return marker; ++ } ++ ++ @Override ++ public void setInvisible(boolean invisible) { ++ this.invisible = invisible; ++ } ++ ++ @Override ++ public void setNoBasePlate(boolean noBasePlate) { ++ this.noBasePlate = noBasePlate; ++ } ++ ++ @Override ++ public void setShowArms(boolean showArms) { ++ this.showArms = showArms; ++ } ++ ++ @Override ++ public void setSmall(boolean small) { ++ this.small = small; ++ } ++ ++ @Override ++ public void setMarker(boolean marker) { ++ this.marker = marker; ++ } ++ // 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 521699615778c4b724d10edfee1d3915e036eb2e..64f166fa93e998a58a895d785ff8c9e62dacb1bb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -1441,6 +1441,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + CraftMetaCrossbow.CHARGED.NBT, + CraftMetaCrossbow.CHARGED_PROJECTILES.NBT, + CraftMetaSuspiciousStew.EFFECTS.NBT, ++ // Paper start ++ CraftMetaArmorStand.ENTITY_TAG.NBT, ++ CraftMetaArmorStand.INVISIBLE.NBT, ++ CraftMetaArmorStand.NO_BASE_PLATE.NBT, ++ CraftMetaArmorStand.SHOW_ARMS.NBT, ++ CraftMetaArmorStand.SMALL.NBT, ++ CraftMetaArmorStand.MARKER.NBT, ++ // Paper end + CraftMetaCompass.LODESTONE_DIMENSION.NBT, + CraftMetaCompass.LODESTONE_POS.NBT, + CraftMetaCompass.LODESTONE_TRACKED.NBT +diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +index 9a351c137776ac622f4df7353bb353142b3a6ccc..42f577ed3508ba5a380648461e149f16ce97c9bd 100644 +--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java ++++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +@@ -313,6 +313,7 @@ public class ItemMetaTest extends AbstractTestingBase { + final CraftMetaArmorStand meta = (CraftMetaArmorStand) cleanStack.getItemMeta(); + meta.entityTag = new NBTTagCompound(); + meta.entityTag.setBoolean("Small", true); ++ meta.setInvisible(true); // Paper + cleanStack.setItemMeta(meta); + return cleanStack; + } diff --git a/Remapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch b/Remapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch new file mode 100644 index 0000000000..826fede56c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 11 Feb 2018 10:43:46 +0000 +Subject: [PATCH] Extend Player Interact cancellation + +GUIs are opened on the client, meaning that the server cannot block them from opening, +However, it is possible to close these GUIs from the server. + +Flower pots are also not updated on the client when interaction is cancelled, this patch +also resolves this. + +Update adjacent blocks of doors, double plants, pistons and beds +when cancelling interaction. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 26ce794cb8d089c03fab5dd0a0c910783d10b72e..b1a53093eb5b5f359eedb6c252cf6d0d1ae8e409 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -23,6 +23,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.network.protocol.game.ClientboundBlockBreakAckPacket; + import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; ++import net.minecraft.network.protocol.game.ClientboundContainerClosePacket; + import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket; + import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; + import net.minecraft.server.MinecraftServer; +@@ -180,6 +181,11 @@ public class ServerPlayerGameMode { + PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, direction, this.player.inventory.getSelected(), InteractionHand.MAIN_HAND); + if (event.isCancelled()) { + // Let the client know the block still exists ++ // Paper start - brute force neighbor blocks for any attached blocks ++ for (Direction dir : Direction.values()) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(level, pos.relative(dir))); ++ } ++ // Paper end + this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); + // Update any tile entity data for this block + BlockEntity tileentity = this.level.getBlockEntity(pos); +@@ -484,6 +490,7 @@ public class ServerPlayerGameMode { + interactItemStack = stack.copy(); + + if (event.useInteractedBlock() == Event.Result.DENY) { ++ + // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. + if (iblockdata.getBlock() instanceof DoorBlock) { + boolean bottom = iblockdata.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER; +@@ -496,7 +503,13 @@ public class ServerPlayerGameMode { + + // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) + player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.above())); ++ // Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method ++ } else if (iblockdata.getBlock() instanceof StructureBlock) { ++ player.connection.send(new ClientboundContainerClosePacket()); ++ } else if (iblockdata.getBlock() instanceof CommandBlock) { ++ player.connection.send(new ClientboundContainerClosePacket()); + } ++ // Paper end - extend Player Interact cancellation + player.getBukkitEntity().updateInventory(); // SPIGOT-2867 + enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS; + } else if (this.gameModeForPlayer == GameType.SPECTATOR) { diff --git a/Remapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch b/Remapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch new file mode 100644 index 0000000000..643044c740 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 24 Feb 2018 01:14:55 -0500 +Subject: [PATCH] Tameable#getOwnerUniqueId API + +This is faster if all you need is the UUID, as .getOwner() will cause +an OfflinePlayer to be loaded from disk. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +index 6136b3322a340d506ce744bcd15f71a158e46ad1..04b0b2449f20220c74892788080d40e3693151c5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +@@ -89,6 +89,9 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac + } + } + ++ public UUID getOwnerUniqueId() { ++ return getOwnerUUID(); ++ } + public UUID getOwnerUUID() { + return getHandle().getOwnerUUID(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java +index 35587fd6d90dfd1da2075c3268692eac7a2eaa25..85fe4f07d35c514f2a7c7920ec416fb651434c83 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java +@@ -17,6 +17,9 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat + return (TamableAnimal) super.getHandle(); + } + ++ public UUID getOwnerUniqueId() { ++ return getOwnerUUID(); ++ } + public UUID getOwnerUUID() { + try { + return getHandle().getOwnerUUID(); diff --git a/Remapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch b/Remapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch new file mode 100644 index 0000000000..671d7965cc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Sat, 10 Mar 2018 00:50:24 +0100 +Subject: [PATCH] Toggleable player crits, helps mitigate hacked clients. + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2..48f0385c7203c7955de5a015f3dc42be2ab7b681 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -192,6 +192,11 @@ public class PaperWorldConfig { + disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); + } + ++ public boolean disablePlayerCrits; ++ private void disablePlayerCrits() { ++ disablePlayerCrits = getBoolean("game-mechanics.disable-player-crits", false); ++ } ++ + public boolean allChunksAreSlimeChunks; + private void allChunksAreSlimeChunks() { + allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", 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 43868c1e2d2c858a4f02119c3238f615f9b1ee72..63871a3a1981b2e8c7ad74214196e35684acb584 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1131,6 +1131,7 @@ public abstract class Player extends LivingEntity { + + boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; + ++ flag2 = flag2 && !level.paperConfig.disablePlayerCrits; // Paper + flag2 = flag2 && !this.isSprinting(); + if (flag2) { + f *= 1.5F; diff --git a/Remapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/Remapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch new file mode 100644 index 0000000000..4b912daff9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 10 Mar 2018 16:33:15 -0500 +Subject: [PATCH] Prevent Frosted Ice from loading/holding chunks + + +diff --git a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +index ae2f5acd008d5d7163b56cb4a2d29354299959ca..99843f1ca4737d40ae0626fce931c97bbf5ab81d 100644 +--- a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +@@ -40,7 +40,8 @@ public class FrostedIceBlock extends IceBlock { + Direction enumdirection = aenumdirection[j]; + + blockposition_mutableblockposition.setWithOffset((Vec3i) pos, enumdirection); +- BlockState iblockdata1 = world.getBlockState(blockposition_mutableblockposition); ++ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper ++ if (iblockdata1 == null) { continue; } // Paper + + if (iblockdata1.is((Block) this) && !this.slightlyMelt(iblockdata1, (Level) world, blockposition_mutableblockposition)) { + world.getBlockTicks().scheduleTick(blockposition_mutableblockposition, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay +@@ -83,7 +84,9 @@ public class FrostedIceBlock extends IceBlock { + Direction enumdirection = aenumdirection[l]; + + blockposition_mutableblockposition.setWithOffset((Vec3i) pos, enumdirection); +- if (world.getBlockState(blockposition_mutableblockposition).is((Block) this)) { ++ // Paper start ++ BlockState type = world.getTypeIfLoaded(blockposition_mutableblockposition); ++ if (type != null && type.is((Block) this)) { // Paper end + ++j; + if (j >= maxNeighbors) { + return false; diff --git a/Remapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch b/Remapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch new file mode 100644 index 0000000000..45eef88da2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 11 Mar 2018 14:13:33 -0400 +Subject: [PATCH] Disable Explicit Network Manager Flushing + +This seems completely pointless, as packet dispatch uses .writeAndFlush. + +Things seem to work fine without explicit flushing, but incase issues arise, +provide a System property to re-enable it using improved logic of doing the +flushing on the netty event loop, so it won't do the flush on the main thread. + +Renable flushing by passing -Dpaper.explicit-flush=true + +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 3429c813a5b471cdfa561bd20849a303e5aacead..7f4681910751047a26fdfc6b59bc460449c02001 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -73,6 +73,7 @@ public class Connection extends SimpleChannelInboundHandler> { + // Paper start - NetworkClient implementation + public int protocolVersion; + public java.net.InetSocketAddress virtualHost; ++ private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); + // Paper end + + public Connection(PacketFlow side) { +@@ -240,7 +241,7 @@ public class Connection extends SimpleChannelInboundHandler> { + } + + if (this.channel != null) { +- this.channel.flush(); ++ if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version + } + + if (this.tickCount++ % 20 == 0) { diff --git a/Remapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch b/Remapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch new file mode 100644 index 0000000000..762c35c3ad --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch @@ -0,0 +1,378 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Wed, 11 Oct 2017 15:56:26 +0200 +Subject: [PATCH] Implement extended PaperServerListPingEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4ecd0c5bbea55f68549c85aa27e80e2c7e6265d4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java +@@ -0,0 +1,31 @@ ++package com.destroystokyo.paper.network; ++ ++import com.destroystokyo.paper.event.server.PaperServerListPingEvent; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.entity.Player; ++import org.bukkit.util.CachedServerIcon; ++ ++import javax.annotation.Nullable; ++ ++class PaperServerListPingEventImpl extends PaperServerListPingEvent { ++ ++ private final MinecraftServer server; ++ ++ PaperServerListPingEventImpl(MinecraftServer server, StatusClient client, int protocolVersion, @Nullable CachedServerIcon icon) { ++ super(client, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers(), ++ server.getServerModName() + ' ' + server.getServerVersion(), protocolVersion, icon); ++ this.server = server; ++ } ++ ++ @Override ++ protected final Object[] getOnlinePlayers() { ++ return this.server.getPlayerList().players.toArray(); ++ } ++ ++ @Override ++ protected final Player getBukkitPlayer(Object player) { ++ return ((ServerPlayer) player).getBukkitEntity(); ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d926ad804355ee2fdc5910b2505e8671602acdab +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java +@@ -0,0 +1,11 @@ ++package com.destroystokyo.paper.network; ++ ++import net.minecraft.network.Connection; ++ ++class PaperStatusClient extends PaperNetworkClient implements StatusClient { ++ ++ PaperStatusClient(Connection networkManager) { ++ super(networkManager); ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4c2351b03b58511b80017b58ee9b20ab5193adc9 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java +@@ -0,0 +1,110 @@ ++package com.destroystokyo.paper.network; ++ ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; ++import com.google.common.base.MoreObjects; ++import com.google.common.base.Strings; ++import com.mojang.authlib.GameProfile; ++import io.papermc.paper.adventure.AdventureComponent; ++import java.util.List; ++import java.util.UUID; ++import javax.annotation.Nonnull; ++import net.minecraft.network.Connection; ++import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; ++import net.minecraft.network.protocol.status.ServerStatus; ++import net.minecraft.server.MinecraftServer; ++ ++public final class StandardPaperServerListPingEventImpl extends PaperServerListPingEventImpl { ++ ++ private static final GameProfile[] EMPTY_PROFILES = new GameProfile[0]; ++ private static final UUID FAKE_UUID = new UUID(0, 0); ++ ++ private GameProfile[] originalSample; ++ ++ private StandardPaperServerListPingEventImpl(MinecraftServer server, Connection networkManager, ServerStatus ping) { ++ super(server, new PaperStatusClient(networkManager), ping.getVersion() != null ? ping.getVersion().getProtocol() : -1, server.server.getServerIcon()); ++ this.originalSample = ping.getPlayers() == null ? null : ping.getPlayers().getSample(); // GH-1473 - pre-tick race condition NPE ++ } ++ ++ @Nonnull ++ @Override ++ public List getPlayerSample() { ++ List sample = super.getPlayerSample(); ++ ++ if (this.originalSample != null) { ++ for (GameProfile profile : this.originalSample) { ++ sample.add(CraftPlayerProfile.asBukkitCopy(profile)); ++ } ++ this.originalSample = null; ++ } ++ ++ return sample; ++ } ++ ++ private GameProfile[] getPlayerSampleHandle() { ++ if (this.originalSample != null) { ++ return this.originalSample; ++ } ++ ++ List entries = super.getPlayerSample(); ++ if (entries.isEmpty()) { ++ return EMPTY_PROFILES; ++ } ++ ++ GameProfile[] profiles = new GameProfile[entries.size()]; ++ for (int i = 0; i < profiles.length; i++) { ++ /* ++ * Avoid null UUIDs/names since that will make the response invalid ++ * on the client. ++ * Instead, fall back to a fake/empty UUID and an empty string as name. ++ * This can be used to create custom lines in the player list that do not ++ * refer to a specific player. ++ */ ++ ++ PlayerProfile profile = entries.get(i); ++ if (profile.getId() != null && profile.getName() != null) { ++ profiles[i] = CraftPlayerProfile.asAuthlib(profile); ++ } else { ++ profiles[i] = new GameProfile(MoreObjects.firstNonNull(profile.getId(), FAKE_UUID), Strings.nullToEmpty(profile.getName())); ++ } ++ } ++ ++ return profiles; ++ } ++ ++ @SuppressWarnings("deprecation") ++ public static void processRequest(MinecraftServer server, Connection networkManager) { ++ StandardPaperServerListPingEventImpl event = new StandardPaperServerListPingEventImpl(server, networkManager, server.getStatus()); ++ server.server.getPluginManager().callEvent(event); ++ ++ // Close connection immediately if event is cancelled ++ if (event.isCancelled()) { ++ networkManager.disconnect(null); ++ return; ++ } ++ ++ // Setup response ++ ServerStatus ping = new ServerStatus(); ++ ++ // Description ++ ping.setDescription(new AdventureComponent(event.motd())); ++ ++ // Players ++ if (!event.shouldHidePlayers()) { ++ ping.setPlayers(new ServerStatus.Players(event.getMaxPlayers(), event.getNumPlayers())); ++ ping.getPlayers().setSample(event.getPlayerSampleHandle()); ++ } ++ ++ // Version ++ ping.setVersion(new ServerStatus.Version(event.getVersion(), event.getProtocolVersion())); ++ ++ // Favicon ++ if (event.getServerIcon() != null) { ++ ping.setFavicon(event.getServerIcon().getData()); ++ } ++ ++ // Send response ++ networkManager.send(new ClientboundStatusResponsePacket(ping)); ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java +index b985d238eadf857602636ba5e5c277d4b1992d35..5b2081f920304244df96de78b2c66cf8a49a5b85 100644 +--- a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java ++++ b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java +@@ -2,6 +2,7 @@ package net.minecraft.network.protocol.status; + + import com.google.gson.Gson; + import com.google.gson.GsonBuilder; ++import io.papermc.paper.adventure.AdventureComponent; // Paper + import java.io.IOException; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.chat.Component; +@@ -12,7 +13,9 @@ import net.minecraft.util.LowerCaseEnumTypeAdapterFactory; + + public class ClientboundStatusResponsePacket implements Packet { + +- private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()).create(); ++ private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()) ++ .registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()) ++ .create(); + private ServerStatus status; + + public ClientboundStatusResponsePacket() {} +diff --git a/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java b/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java +index d6be3dd6cfed3f65325398fc33663cb251f87ac7..31d45cd635eae2ff406cb0441f2cd2aee833b945 100644 +--- a/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java ++++ b/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java +@@ -31,6 +31,7 @@ public class ServerStatus { + this.description = description; + } + ++ public Players getPlayers() { return getPlayers(); } // Paper - OBFHELPER + public ServerStatus.Players getPlayers() { + return this.players; + } +@@ -162,10 +163,12 @@ public class ServerStatus { + return this.numPlayers; + } + ++ public GameProfile[] getSample() { return getSample(); } // Paper - OBFHELPER + public GameProfile[] getSample() { + return this.sample; + } + ++ public void setSample(GameProfile[] sample) { setSample(sample); } // Paper - OBFHELPER + public void setSample(GameProfile[] sample) { + this.sample = sample; + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 4b3341877629c7065496fb0f0b4d509f5a48db6d..d34da1eb172a7dcda564680afecf3dc145bf09f3 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2,6 +2,9 @@ package net.minecraft.server; + + import com.google.common.base.Splitter; + import com.google.common.collect.ImmutableList; ++import co.aikar.timings.Timings; ++import com.destroystokyo.paper.event.server.PaperServerListPingEvent; ++import com.google.common.base.Stopwatch; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; +@@ -1238,7 +1241,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= 5000000000L) { + this.lastServerStatus = i; + this.status.setPlayers(new ServerStatus.Players(this.getMaxPlayers(), this.getPlayerCount())); +- GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), 12)]; ++ GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), org.spigotmc.SpigotConfig.playerSample)]; // Paper + int j = Mth.nextInt(this.random, 0, this.getPlayerCount() - agameprofile.length); + + for (int k = 0; k < agameprofile.length; ++k) { +diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +index 223df8d27c2ff1cbff634bca3dbde5cc24de7f98..f74e3cbdff8c2d83809f04f42717501d7b1a1ed2 100644 +--- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +@@ -1,7 +1,7 @@ + package net.minecraft.server.network; + + import net.minecraft.server.MinecraftServer; +-import net.minecraft.server.level.ServerPlayer; ++ + // CraftBukkit start + import com.mojang.authlib.GameProfile; + import java.net.InetSocketAddress; +@@ -11,8 +11,6 @@ import net.minecraft.network.Connection; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; +-import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; +-import net.minecraft.network.protocol.status.ServerStatus; + import net.minecraft.network.protocol.status.ServerStatusPacketListener; + import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; + import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; +@@ -47,15 +45,17 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON); + } else { + this.hasRequestedStatus = true; ++ // Paper start - Replace everything ++ /* + // CraftBukkit start + // this.networkManager.sendPacket(new PacketStatusOutServerInfo(this.minecraftServer.getServerPing())); +- final Object[] players = server.getPlayerList().players.toArray(); ++ final Object[] players = minecraftServer.getPlayerList().players.toArray(); + class ServerListPingEvent extends org.bukkit.event.server.ServerListPingEvent { + +- CraftIconCache icon = server.server.getServerIcon(); ++ CraftIconCache icon = minecraftServer.server.getServerIcon(); + + ServerListPingEvent() { +- super(((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.server.motd(), server.getPlayerList().getMaxPlayers()); // Paper - Adventure ++ super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.server.motd(), minecraftServer.getPlayerList().getMaxPlayers()); // Paper - Adventure + } + + @Override +@@ -71,7 +71,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + return new Iterator() { + int i; + int ret = Integer.MIN_VALUE; +- ServerPlayer player; ++ EntityPlayer player; + + @Override + public boolean hasNext() { +@@ -80,7 +80,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + } + final Object[] currentPlayers = players; + for (int length = currentPlayers.length, i = this.i; i < length; i++) { +- final ServerPlayer player = (ServerPlayer) currentPlayers[i]; ++ final EntityPlayer player = (EntityPlayer) currentPlayers[i]; + if (player != null) { + this.i = i + 1; + this.player = player; +@@ -95,7 +95,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + if (!hasNext()) { + throw new java.util.NoSuchElementException(); + } +- final ServerPlayer player = this.player; ++ final EntityPlayer player = this.player; + this.player = null; + this.ret = this.i - 1; + return player.getBukkitEntity(); +@@ -115,16 +115,16 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + } + + ServerListPingEvent event = new ServerListPingEvent(); +- this.server.server.getPluginManager().callEvent(event); ++ this.minecraftServer.server.getPluginManager().callEvent(event); + + java.util.List profiles = new java.util.ArrayList(players.length); + for (Object player : players) { + if (player != null) { +- profiles.add(((ServerPlayer) player).getGameProfile()); ++ profiles.add(((EntityPlayer) player).getProfile()); + } + } + +- ServerStatus.Players playerSample = new ServerStatus.Players(event.getMaxPlayers(), profiles.size()); ++ ServerPing.ServerPingPlayerSample playerSample = new ServerPing.ServerPingPlayerSample(event.getMaxPlayers(), profiles.size()); + // Spigot Start + if ( !profiles.isEmpty() ) + { +@@ -132,16 +132,19 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + profiles = profiles.subList( 0, Math.min( profiles.size(), org.spigotmc.SpigotConfig.playerSample ) ); // Cap the sample to n (or less) displayed players, ie: Vanilla behaviour + } + // Spigot End +- playerSample.setSample(profiles.toArray(new GameProfile[profiles.size()])); ++ playerSample.a(profiles.toArray(new GameProfile[profiles.size()])); + +- ServerStatus ping = new ServerStatus(); ++ ServerPing ping = new ServerPing(); + ping.setFavicon(event.icon.value); +- ping.setDescription(CraftChatMessage.fromString(event.getMotd(), true)[0]); +- ping.setPlayers(playerSample); +- int version = SharedConstants.getCurrentVersion().getProtocolVersion(); +- ping.setVersion(new ServerStatus.Version(server.getServerModName() + " " + server.getServerVersion(), version)); +- +- this.connection.send(new ClientboundStatusResponsePacket(ping)); ++ ping.setMOTD(CraftChatMessage.fromString(event.getMotd(), true)[0]); ++ ping.setPlayerSample(playerSample); ++ int version = SharedConstants.getGameVersion().getProtocolVersion(); ++ ping.setServerInfo(new ServerPing.ServerData(minecraftServer.getServerModName() + " " + minecraftServer.getVersion(), version)); ++ ++ this.networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); ++ */ ++ com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.server, this.connection); ++ // Paper end + } + // CraftBukkit end + } +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 3981ba5957fdc2929d54515f2b98bb7a4611e938..652b820a4c0bbf7b6bbb8200927a663665583606 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -289,7 +289,7 @@ public class SpigotConfig + public static int playerSample; + private static void playerSample() + { +- playerSample = getInt( "settings.sample-count", 12 ); ++ playerSample = Math.max( getInt( "settings.sample-count", 12 ), 0 ); // Paper - Avoid negative counts + Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger + } + diff --git a/Remapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch b/Remapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch new file mode 100644 index 0000000000..b0ae823221 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch @@ -0,0 +1,370 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 16 Mar 2018 22:59:43 -0400 +Subject: [PATCH] Improved Async Task Scheduler + +The Craft Scheduler still uses the primary thread for task scheduling. +This results in the main thread still having to do work as part of the +dispatching of async tasks. + +If plugins make use of lots of async tasks, such as particle emitters +that want to keep the logic off the main thread, the main thread still +receives quite a bit of load from processing all of these queued tasks. + +Additionally, resizing and managing the pending entries for all of +these asynchronous tasks takes up time on the main thread too. + +This commit replaces the implementation of the scheduler when working +with asynchronous tasks, by forwarding calls to the new scheduler. + +The Async Scheduler uses a single thread executor for "management" tasks. +The Management Thread is responsible for all adding and dispatching of +scheduled tasks. + +The mainThreadHeartbeat will send a heartbeat task to the management thread +with the currentTick value, so that it can find which tasks to execute. + +Scheduling of an async tasks also dispatches a management task, ensuring +that any Queue resizing operation occurs off of the main thread. + +The async queue uses a complete separate PriorityQueue, ensuring that resize +operations are decoupled from the sync tasks queue. + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3c1992e212a6d6f1db4d5b807b38d71913619fc0 +--- /dev/null ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java +@@ -0,0 +1,122 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package org.bukkit.craftbukkit.scheduler; ++ ++import com.destroystokyo.paper.ServerSchedulerReportingWrapper; ++import com.google.common.util.concurrent.ThreadFactoryBuilder; ++import org.bukkit.plugin.Plugin; ++ ++import java.util.ArrayList; ++import java.util.Iterator; ++import java.util.List; ++import java.util.concurrent.Executor; ++import java.util.concurrent.Executors; ++import java.util.concurrent.SynchronousQueue; ++import java.util.concurrent.ThreadPoolExecutor; ++import java.util.concurrent.TimeUnit; ++ ++public class CraftAsyncScheduler extends CraftScheduler { ++ ++ private final ThreadPoolExecutor executor = new ThreadPoolExecutor( ++ 4, Integer.MAX_VALUE,30L, TimeUnit.SECONDS, new SynchronousQueue<>(), ++ new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").build()); ++ private final Executor management = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder() ++ .setNameFormat("Craft Async Scheduler Management Thread").build()); ++ private final List temp = new ArrayList<>(); ++ ++ CraftAsyncScheduler() { ++ super(true); ++ executor.allowCoreThreadTimeOut(true); ++ executor.prestartAllCoreThreads(); ++ } ++ ++ @Override ++ public void cancelTask(int taskId) { ++ this.management.execute(() -> this.removeTask(taskId)); ++ } ++ ++ private synchronized void removeTask(int taskId) { ++ parsePending(); ++ this.pending.removeIf((task) -> { ++ if (task.getTaskId() == taskId) { ++ task.cancel0(); ++ return true; ++ } ++ return false; ++ }); ++ } ++ ++ @Override ++ public void mainThreadHeartbeat(int currentTick) { ++ this.currentTick = currentTick; ++ this.management.execute(() -> this.runTasks(currentTick)); ++ } ++ ++ private synchronized void runTasks(int currentTick) { ++ parsePending(); ++ while (!this.pending.isEmpty() && this.pending.peek().getNextRun() <= currentTick) { ++ CraftTask task = this.pending.remove(); ++ if (executeTask(task)) { ++ final long period = task.getPeriod(); ++ if (period > 0) { ++ task.setNextRun(currentTick + period); ++ temp.add(task); ++ } ++ } ++ parsePending(); ++ } ++ this.pending.addAll(temp); ++ temp.clear(); ++ } ++ ++ private boolean executeTask(CraftTask task) { ++ if (isValid(task)) { ++ this.runners.put(task.getTaskId(), task); ++ this.executor.execute(new ServerSchedulerReportingWrapper(task)); ++ return true; ++ } ++ return false; ++ } ++ ++ @Override ++ public synchronized void cancelTasks(Plugin plugin) { ++ parsePending(); ++ for (Iterator iterator = this.pending.iterator(); iterator.hasNext(); ) { ++ CraftTask task = iterator.next(); ++ if (task.getTaskId() != -1 && (plugin == null || task.getOwner().equals(plugin))) { ++ task.cancel0(); ++ iterator.remove(); ++ } ++ } ++ } ++ ++ /** ++ * Task is not cancelled ++ * @param runningTask ++ * @return ++ */ ++ static boolean isValid(CraftTask runningTask) { ++ return runningTask.getPeriod() >= CraftTask.NO_REPEATING; ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483ca3c7c2a8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -63,7 +63,7 @@ public class CraftScheduler implements BukkitScheduler { + /** + * Main thread logic only + */ +- private final PriorityQueue pending = new PriorityQueue(10, ++ final PriorityQueue pending = new PriorityQueue(10, // Paper + new Comparator() { + @Override + public int compare(final CraftTask o1, final CraftTask o2) { +@@ -80,12 +80,13 @@ public class CraftScheduler implements BukkitScheduler { + /** + * These are tasks that are currently active. It's provided for 'viewing' the current state. + */ +- private final ConcurrentHashMap runners = new ConcurrentHashMap(); ++ final ConcurrentHashMap runners = new ConcurrentHashMap(); // Paper + /** + * The sync task that is currently running on the main thread. + */ + private volatile CraftTask currentTask = null; +- private volatile int currentTick = -1; ++ // Paper start - Improved Async Task Scheduler ++ volatile int currentTick = -1;/* + private final Executor executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %d").build()); + private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) { + @Override +@@ -94,12 +95,31 @@ public class CraftScheduler implements BukkitScheduler { + } + }; + private CraftAsyncDebugger debugTail = debugHead; ++ ++ */ // Paper end + private static final int RECENT_TICKS; + + static { + RECENT_TICKS = 30; + } + ++ ++ // Paper start ++ private final CraftScheduler asyncScheduler; ++ private final boolean isAsyncScheduler; ++ public CraftScheduler() { ++ this(false); ++ } ++ ++ public CraftScheduler(boolean isAsync) { ++ this.isAsyncScheduler = isAsync; ++ if (isAsync) { ++ this.asyncScheduler = this; ++ } else { ++ this.asyncScheduler = new CraftAsyncScheduler(); ++ } ++ } ++ // Paper end + @Override + public int scheduleSyncDelayedTask(final Plugin plugin, final Runnable task) { + return this.scheduleSyncDelayedTask(plugin, task, 0L); +@@ -222,7 +242,7 @@ public class CraftScheduler implements BukkitScheduler { + } else if (period < CraftTask.NO_REPEATING) { + period = CraftTask.NO_REPEATING; + } +- return handle(new CraftAsyncTask(runners, plugin, runnable, nextId(), period), delay); ++ return handle(new CraftAsyncTask(this.asyncScheduler.runners, plugin, runnable, nextId(), period), delay); // Paper + } + + @Override +@@ -238,6 +258,11 @@ public class CraftScheduler implements BukkitScheduler { + if (taskId <= 0) { + return; + } ++ // Paper start ++ if (!this.isAsyncScheduler) { ++ this.asyncScheduler.cancelTask(taskId); ++ } ++ // Paper end + CraftTask task = runners.get(taskId); + if (task != null) { + task.cancel0(); +@@ -280,6 +305,11 @@ public class CraftScheduler implements BukkitScheduler { + @Override + public void cancelTasks(final Plugin plugin) { + Validate.notNull(plugin, "Cannot cancel tasks of null plugin"); ++ // Paper start ++ if (!this.isAsyncScheduler) { ++ this.asyncScheduler.cancelTasks(plugin); ++ } ++ // Paper end + final CraftTask task = new CraftTask( + new Runnable() { + @Override +@@ -319,6 +349,13 @@ public class CraftScheduler implements BukkitScheduler { + + @Override + public boolean isCurrentlyRunning(final int taskId) { ++ // Paper start ++ if (!isAsyncScheduler) { ++ if (this.asyncScheduler.isCurrentlyRunning(taskId)) { ++ return true; ++ } ++ } ++ // Paper end + final CraftTask task = runners.get(taskId); + if (task == null) { + return false; +@@ -337,6 +374,11 @@ public class CraftScheduler implements BukkitScheduler { + if (taskId <= 0) { + return false; + } ++ // Paper start ++ if (!this.isAsyncScheduler && this.asyncScheduler.isQueued(taskId)) { ++ return true; ++ } ++ // Paper end + for (CraftTask task = head.getNext(); task != null; task = task.getNext()) { + if (task.getTaskId() == taskId) { + return task.getPeriod() >= CraftTask.NO_REPEATING; // The task will run +@@ -348,6 +390,12 @@ public class CraftScheduler implements BukkitScheduler { + + @Override + public List getActiveWorkers() { ++ // Paper start ++ if (!isAsyncScheduler) { ++ //noinspection TailRecursion ++ return this.asyncScheduler.getActiveWorkers(); ++ } ++ // Paper end + final ArrayList workers = new ArrayList(); + for (final CraftTask taskObj : runners.values()) { + // Iterator will be a best-effort (may fail to grab very new values) if called from an async thread +@@ -385,6 +433,11 @@ public class CraftScheduler implements BukkitScheduler { + pending.add(task); + } + } ++ // Paper start ++ if (!this.isAsyncScheduler) { ++ pending.addAll(this.asyncScheduler.getPendingTasks()); ++ } ++ // Paper end + return pending; + } + +@@ -392,6 +445,11 @@ public class CraftScheduler implements BukkitScheduler { + * This method is designed to never block or wait for locks; an immediate execution of all current tasks. + */ + public void mainThreadHeartbeat(final int currentTick) { ++ // Paper start ++ if (!this.isAsyncScheduler) { ++ this.asyncScheduler.mainThreadHeartbeat(currentTick); ++ } ++ // Paper end + this.currentTick = currentTick; + final List temp = this.temp; + parsePending(); +@@ -431,7 +489,7 @@ public class CraftScheduler implements BukkitScheduler { + parsePending(); + } else { + //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper +- executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper ++ task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Paper"); // Paper + // We don't need to parse pending + // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) + } +@@ -450,7 +508,7 @@ public class CraftScheduler implements BukkitScheduler { + //debugHead = debugHead.getNextHead(currentTick); // Paper + } + +- private void addTask(final CraftTask task) { ++ protected void addTask(final CraftTask task) { + final AtomicReference tail = this.tail; + CraftTask tailTask = tail.get(); + while (!tail.compareAndSet(tailTask, task)) { +@@ -459,7 +517,13 @@ public class CraftScheduler implements BukkitScheduler { + tailTask.setNext(task); + } + +- private CraftTask handle(final CraftTask task, final long delay) { ++ protected CraftTask handle(final CraftTask task, final long delay) { // Paper ++ // Paper start ++ if (!this.isAsyncScheduler && !task.isSync()) { ++ this.asyncScheduler.handle(task, delay); ++ return task; ++ } ++ // Paper end + task.setNextRun(currentTick + delay); + addTask(task); + return task; +@@ -478,8 +542,8 @@ public class CraftScheduler implements BukkitScheduler { + return ids.incrementAndGet(); + } + +- private void parsePending() { +- MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); ++ void parsePending() { // Paper ++ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); // Paper + CraftTask head = this.head; + CraftTask task = head.getNext(); + CraftTask lastTask = head; +@@ -498,7 +562,7 @@ public class CraftScheduler implements BukkitScheduler { + task.setNext(null); + } + this.head = lastTask; +- MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); ++ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); // Paper + } + + private boolean isReady(final int currentTick) { diff --git a/Remapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/Remapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch new file mode 100644 index 0000000000..f400637138 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 18 Mar 2018 11:45:57 -0400 +Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent + +This will allow you to change the players name or skin on login. + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index ff83fb15d0d0adb62c630fc7aafc134972bf15fc..e5be45ac86907c1f8cc154bd38fd624a2320180f 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -1,5 +1,7 @@ + package net.minecraft.server.network; + ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; + import com.mojang.authlib.GameProfile; + import com.mojang.authlib.exceptions.AuthenticationUnavailableException; + import java.math.BigInteger; +@@ -36,6 +38,7 @@ import org.apache.commons.lang3.Validate; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import io.papermc.paper.adventure.PaperAdventure; // Paper ++import org.bukkit.Bukkit; + import org.bukkit.craftbukkit.util.Waitable; + import org.bukkit.event.player.AsyncPlayerPreLoginEvent; + import org.bukkit.event.player.PlayerPreLoginEvent; +@@ -314,8 +317,16 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + java.util.UUID uniqueId = gameProfile.getId(); + final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; + +- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); ++ // Paper start ++ PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); ++ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); + server.getPluginManager().callEvent(asyncEvent); ++ profile = asyncEvent.getPlayerProfile(); ++ profile.complete(); ++ gameProfile = CraftPlayerProfile.asAuthlibCopy(profile); ++ playerName = gameProfile.getName(); ++ uniqueId = gameProfile.getId(); ++ // Paper end + + if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { + final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); diff --git a/Remapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch b/Remapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch new file mode 100644 index 0000000000..f35f170d57 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch @@ -0,0 +1,142 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 18 Mar 2018 12:29:48 -0400 +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/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index e5be45ac86907c1f8cc154bd38fd624a2320180f..0aa3a154d68f00edcc09b947a24b2b59b1e135e6 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -54,7 +54,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + public final Connection connection; + private ServerLoginPacketListenerImpl.State state; + private int tick; +- private GameProfile gameProfile; ++ private GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } private GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER + private final String serverId; + private SecretKey secretKey; + private ServerPlayer delayedAcceptPlayer; +@@ -318,12 +318,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; + + // Paper start +- PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); ++ PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); + AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); + server.getPluginManager().callEvent(asyncEvent); + profile = asyncEvent.getPlayerProfile(); +- profile.complete(); +- gameProfile = CraftPlayerProfile.asAuthlibCopy(profile); ++ profile.complete(true); ++ setGameProfile(CraftPlayerProfile.asAuthlib(profile)); + playerName = gameProfile.getName(); + uniqueId = gameProfile.getId(); + // Paper end +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 63871a3a1981b2e8c7ad74214196e35684acb584..c4aa824d03de952fe6b306e539baa47af979add1 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -159,7 +159,7 @@ public abstract class Player extends LivingEntity { + protected int enchantmentSeed; + protected final float defaultFlySpeed = 0.02F; + private int lastLevelUpTime; +- private final GameProfile gameProfile; ++ private GameProfile gameProfile; public final void setProfile(final GameProfile profile) { this.gameProfile = profile; } // Paper - OBFHELPER + private ItemStack lastItemInMainHand; + private final ItemCooldowns cooldowns; + @Nullable +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index efdcb8dac8db15c4bbaed84a7861ce98339e516a..9d853733ff9054cc48925e22c8bb3c8d9b898808 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -67,6 +67,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.GameType; ++import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.saveddata.maps.MapDecoration; + import net.minecraft.world.phys.Vec3; +@@ -1307,8 +1308,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + hiddenPlayers.put(player.getUniqueId(), hidingPlugins); + + // Remove this player from the hidden player's EntityTrackerEntry +- ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; ++ // Paper start + ServerPlayer other = ((CraftPlayer) player).getHandle(); ++ unregisterPlayer(other); ++ } ++ private void unregisterPlayer(ServerPlayer other) { ++ ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; ++ // Paper end + ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId()); + if (entry != null) { + entry.removePlayer(getHandle()); +@@ -1349,8 +1355,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + hiddenPlayers.remove(player.getUniqueId()); + +- ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; ++ // Paper start + ServerPlayer other = ((CraftPlayer) player).getHandle(); ++ registerPlayer(other); ++ } ++ private void registerPlayer(ServerPlayer other) { ++ ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; ++ // Paper end + + getHandle().connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, other)); + +@@ -1359,6 +1370,50 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + entry.updatePlayer(getHandle()); + } + } ++ // Paper start ++ private void reregisterPlayer(ServerPlayer player) { ++ if (!hiddenPlayers.containsKey(player.getUUID())) { ++ unregisterPlayer(player); ++ registerPlayer(player); ++ } ++ } ++ public void setPlayerProfile(com.destroystokyo.paper.profile.PlayerProfile profile) { ++ ServerPlayer self = getHandle(); ++ self.setProfile(com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile)); ++ if (!self.sentListPacket) { ++ return; ++ } ++ List players = server.getServer().getPlayerList().players; ++ for (ServerPlayer player : players) { ++ player.getBukkitEntity().reregisterPlayer(self); ++ } ++ refreshPlayer(); ++ } ++ public com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile() { ++ return new com.destroystokyo.paper.profile.CraftPlayerProfile(this).clone(); ++ } ++ ++ private void refreshPlayer() { ++ ServerPlayer handle = getHandle(); ++ ++ Location loc = getLocation(); ++ ++ ServerGamePacketListenerImpl connection = handle.connection; ++ reregisterPlayer(handle); ++ ++ //Respawn the player then update their position and selected slot ++ ServerLevel worldserver = handle.getLevel(); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundRespawnPacket(worldserver.dimensionType(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), handle.gameMode.getGameModeForPlayer(), handle.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), true)); ++ handle.onUpdateAbilities(); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), new HashSet<>(), 0)); ++ net.minecraft.server.MinecraftServer.getServer().getPlayerList().sendAllPlayerInfo(handle); ++ ++ if (this.isOp()) { ++ this.setOp(false); ++ this.setOp(true); ++ } ++ } ++ // Paper end + + public void removeDisconnectingPlayer(Player player) { + hiddenPlayers.remove(player.getUniqueId()); diff --git a/Remapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch b/Remapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch new file mode 100644 index 0000000000..334aa02f71 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Mar 2018 20:52:07 -0400 +Subject: [PATCH] Fix Dragon Server Crashes + +If the dragon tries to find "ground" and hits a hole, or off edge, +it will infinitely keep looking for non air and eventually crash. + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java +index 5e701b02e464889fe433b08018d13e63b24506eb..0c2a5f5c4d7d7516793eba20205b5703fe1450d5 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java +@@ -63,7 +63,7 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { + double d3 = d2; + BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(d0, d2, d1); + +- while (this.dragon.level.isEmptyBlock(blockposition_mutableblockposition)) { ++ while (this.dragon.level.isEmptyBlock(blockposition_mutableblockposition ) && d2 > 0) { // Paper + --d3; + if (d3 < 0.0D) { + d3 = d2; diff --git a/Remapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch b/Remapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch new file mode 100644 index 0000000000..64d63b916e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 22 Mar 2018 01:40:24 -0400 +Subject: [PATCH] getPlayerUniqueId API + +Gets the unique ID of the player currently known as the specified player name +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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 10addb128a357e7719854bf4f9d75f5def32b27d..20915e40fbcf28faed603d449a99bf2157fcf972 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1517,6 +1517,25 @@ public final class CraftServer implements Server { + return recipients.size(); + } + ++ // Paper start ++ @Nullable ++ public UUID getPlayerUniqueId(String name) { ++ Player player = Bukkit.getPlayerExact(name); ++ if (player != null) { ++ return player.getUniqueId(); ++ } ++ GameProfile profile; ++ // Only fetch an online UUID in online mode ++ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) { ++ profile = console.getProfileCache().get( name ); ++ } else { ++ // Make an OfflinePlayer using an offline mode UUID since the name has no profile ++ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); ++ } ++ return profile != null ? profile.getId() : null; ++ } ++ // Paper end ++ + @Override + @Deprecated + public OfflinePlayer getOfflinePlayer(String name) { diff --git a/Remapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch b/Remapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch new file mode 100644 index 0000000000..7a7b4d1993 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Mon, 26 Mar 2018 18:30:53 +0300 +Subject: [PATCH] Make player data saving configurable + +Upstream has added a patch which negates the need for this patch, +however, we should still migrate our configuration back upstream, +to prevent unexpected situations + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 52954fc3bf932cfc9d5ce63e3d3cace351305790..05a5abb951abe37f30a719cb75376d2d43c0d252 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -279,4 +279,13 @@ public class PaperConfig { + private static void authenticationServersDownKickMessage() { + authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); + } ++ ++ private static void savePlayerData() { ++ Object val = config.get("settings.save-player-data"); ++ if (val instanceof Boolean) { ++ SpigotConfig.disablePlayerDataSaving = !(Boolean) val; ++ SpigotConfig.config.set("players.disable-saving", SpigotConfig.disableAdvancementSaving); ++ SpigotConfig.save(); ++ } ++ } + } diff --git a/Remapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch b/Remapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch new file mode 100644 index 0000000000..72dfa9fd8e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch @@ -0,0 +1,181 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Wed, 11 Oct 2017 18:22:50 +0200 +Subject: [PATCH] Make legacy ping handler more reliable + +The Minecraft server often fails to respond to old ("legacy") pings +from old Minecraft versions using the protocol used before the switch +to Netty in Minecraft 1.7. + +Due to packet fragmentation[1], we might not have all needed bytes +available when the LegacyPingHandler is called. In this case, it will +run into an error, remove the handler and continue using the modern +protocol. + +This is unlikely to happen for the first two revisions of the legacy +ping protocol (used in Minecraft 1.5.x and older) since the request +consists of only one or two bytes, but happens frequently for the +last/third revision introduced in Minecraft 1.6. + +It has much larger, variable packet sizes due to the inclusion of +the virtual host (the hostname/port used to connect to the server). + +The solution[2] is simple: If we find more than two matching bytes, +we buffer the remaining bytes until we have enough to fully read and +respond to the request. + +[1]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h3-11 +[2]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h4-13 + +diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java +index e2867a3de87a778a897b4963212fa4aab566a643..1d11802876c1a94ecf991cd8249bd6a911c0ac20 100644 +--- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java ++++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java +@@ -15,6 +15,7 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + + private static final Logger LOGGER = LogManager.getLogger(); + private final ServerConnectionListener serverConnectionListener; ++ private ByteBuf buf; // Paper + + public LegacyQueryHandler(ServerConnectionListener networkIo) { + this.serverConnectionListener = networkIo; +@@ -23,6 +24,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) throws Exception { + ByteBuf bytebuf = (ByteBuf) object; + ++ // Paper start - Make legacy ping handler more reliable ++ if (this.buf != null) { ++ try { ++ readLegacy1_6(channelhandlercontext, bytebuf); ++ } finally { ++ bytebuf.release(); ++ } ++ return; ++ } ++ // Paper end + bytebuf.markReaderIndex(); + boolean flag = true; + +@@ -53,6 +64,10 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); + break; + default: ++ // Paper start - Replace with improved version below ++ if (bytebuf.readUnsignedByte() != 0x01 || bytebuf.readUnsignedByte() != 0xFA) return; ++ readLegacy1_6(channelhandlercontext, bytebuf); ++ /* + boolean flag1 = bytebuf.readUnsignedByte() == 1; + + flag1 &= bytebuf.readUnsignedByte() == 250; +@@ -67,15 +82,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + return; + } + +- LegacyQueryHandler.LOGGER.debug("Ping: (1.6) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); +- String s1 = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit +- ByteBuf bytebuf1 = this.createReply(s1); ++ LegacyPingHandler.LOGGER.debug("Ping: (1.6) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); ++ String s1 = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit ++ ByteBuf bytebuf1 = this.a(s1); + + try { +- this.sendFlushAndClose(channelhandlercontext, bytebuf1); ++ this.a(channelhandlercontext, bytebuf1); + } finally { + bytebuf1.release(); + } ++ */ // Paper end - Replace with improved version below + } + + bytebuf.release(); +@@ -93,6 +109,90 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + + } + ++ // Paper start ++ private static String readLegacyString(ByteBuf buf) { ++ int size = buf.readShort() * Character.BYTES; ++ if (!buf.isReadable(size)) { ++ return null; ++ } ++ ++ String result = buf.toString(buf.readerIndex(), size, StandardCharsets.UTF_16BE); ++ buf.skipBytes(size); // toString doesn't increase readerIndex automatically ++ return result; ++ } ++ ++ private void readLegacy1_6(ChannelHandlerContext ctx, ByteBuf part) { ++ ByteBuf buf = this.buf; ++ ++ if (buf == null) { ++ this.buf = buf = ctx.alloc().buffer(); ++ buf.markReaderIndex(); ++ } else { ++ buf.resetReaderIndex(); ++ } ++ ++ buf.writeBytes(part); ++ ++ if (!buf.isReadable(Short.BYTES + Short.BYTES + Byte.BYTES + Short.BYTES + Integer.BYTES)) { ++ return; ++ } ++ ++ String s = readLegacyString(buf); ++ if (s == null) { ++ return; ++ } ++ ++ if (!s.equals("MC|PingHost")) { ++ removeHandler(ctx); ++ return; ++ } ++ ++ if (!buf.isReadable(Short.BYTES) || !buf.isReadable(buf.readShort())) { ++ return; ++ } ++ ++ MinecraftServer server = this.serverConnectionListener.getServer(); ++ int protocolVersion = buf.readByte(); ++ String host = readLegacyString(buf); ++ if (host == null) { ++ removeHandler(ctx); ++ return; ++ } ++ int port = buf.readInt(); ++ ++ if (buf.isReadable()) { ++ removeHandler(ctx); ++ return; ++ } ++ ++ buf.release(); ++ this.buf = null; ++ ++ LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); ++ ++ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", ++ Byte.MAX_VALUE, server.getServerVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); ++ this.sendFlushAndClose(ctx, this.createReply(response)); ++ } ++ ++ private void removeHandler(ChannelHandlerContext ctx) { ++ ByteBuf buf = this.buf; ++ this.buf = null; ++ ++ buf.resetReaderIndex(); ++ ctx.pipeline().remove(this); ++ ctx.fireChannelRead(buf); ++ } ++ ++ @Override ++ public void handlerRemoved(ChannelHandlerContext ctx) { ++ if (this.buf != null) { ++ this.buf.release(); ++ this.buf = null; ++ } ++ } ++ // Paper end ++ + private void sendFlushAndClose(ChannelHandlerContext ctx, ByteBuf buf) { + ctx.pipeline().firstContext().writeAndFlush(buf).addListener(ChannelFutureListener.CLOSE); + } diff --git a/Remapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch b/Remapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch new file mode 100644 index 0000000000..90d915afd6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch @@ -0,0 +1,154 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Wed, 11 Oct 2017 19:30:51 +0200 +Subject: [PATCH] Call PaperServerListPingEvent for legacy pings + + +diff --git a/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java +new file mode 100644 +index 0000000000000000000000000000000000000000..74c012fd40491f1d870fbc1aa8c318a2197eb106 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java +@@ -0,0 +1,73 @@ ++package com.destroystokyo.paper.network; ++ ++import com.destroystokyo.paper.event.server.PaperServerListPingEvent; ++import net.minecraft.server.MinecraftServer; ++import org.apache.commons.lang3.StringUtils; ++import org.bukkit.ChatColor; ++ ++import java.net.InetSocketAddress; ++ ++import javax.annotation.Nullable; ++ ++public final class PaperLegacyStatusClient implements StatusClient { ++ ++ private final InetSocketAddress address; ++ private final int protocolVersion; ++ @Nullable private final InetSocketAddress virtualHost; ++ ++ private PaperLegacyStatusClient(InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { ++ this.address = address; ++ this.protocolVersion = protocolVersion; ++ this.virtualHost = virtualHost; ++ } ++ ++ @Override ++ public InetSocketAddress getAddress() { ++ return this.address; ++ } ++ ++ @Override ++ public int getProtocolVersion() { ++ return this.protocolVersion; ++ } ++ ++ @Nullable ++ @Override ++ public InetSocketAddress getVirtualHost() { ++ return this.virtualHost; ++ } ++ ++ @Override ++ public boolean isLegacy() { ++ return true; ++ } ++ ++ public static PaperServerListPingEvent processRequest(MinecraftServer server, ++ InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { ++ ++ PaperServerListPingEvent event = new PaperServerListPingEventImpl(server, ++ new PaperLegacyStatusClient(address, protocolVersion, virtualHost), Byte.MAX_VALUE, null); ++ server.server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return null; ++ } ++ ++ return event; ++ } ++ ++ public static String getMotd(PaperServerListPingEvent event) { ++ return getFirstLine(event.getMotd()); ++ } ++ ++ public static String getUnformattedMotd(PaperServerListPingEvent event) { ++ // Strip color codes and all other occurrences of the color char (because it's used as delimiter) ++ return getFirstLine(StringUtils.remove(ChatColor.stripColor(event.getMotd()), ChatColor.COLOR_CHAR)); ++ } ++ ++ private static String getFirstLine(String s) { ++ int pos = s.indexOf('\n'); ++ return pos >= 0 ? s.substring(0, pos) : s; ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java +index 1d11802876c1a94ecf991cd8249bd6a911c0ac20..dfe2cd46f2432dca2028b7436c4108e3f190787f 100644 +--- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java ++++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java +@@ -1,5 +1,7 @@ + package net.minecraft.server.network; + ++import com.destroystokyo.paper.network.PaperLegacyStatusClient; ++ + import io.netty.buffer.ByteBuf; + import io.netty.buffer.Unpooled; + import io.netty.channel.ChannelFutureListener; +@@ -46,12 +48,19 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + MinecraftServer minecraftserver = this.serverConnectionListener.getServer(); + int i = bytebuf.readableBytes(); + String s; +- org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit ++ //org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit // Paper ++ com.destroystokyo.paper.event.server.PaperServerListPingEvent event; // Paper + + switch (i) { + case 0: + LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); +- s = String.format("%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit ++ // Paper start - Call PaperServerListPingEvent and use results ++ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 39, null); ++ if (event == null) { ++ channelhandlercontext.close(); ++ break; ++ } ++ s = String.format("%s\u00a7%d\u00a7%d", PaperLegacyStatusClient.getUnformattedMotd(event), event.getNumPlayers(), event.getMaxPlayers()); + this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); + break; + case 1: +@@ -60,7 +69,14 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + } + + LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); +- s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit ++ // Paper start - Call PaperServerListPingEvent and use results ++ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 127, null); // Paper ++ if (event == null) { ++ channelhandlercontext.close(); ++ break; ++ } ++ s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", new Object[] { event.getProtocolVersion(), minecraftserver.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()}); // CraftBukkit ++ // Paper end + this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); + break; + default: +@@ -170,8 +186,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + + LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); + +- String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", +- Byte.MAX_VALUE, server.getServerVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); ++ InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port); ++ com.destroystokyo.paper.event.server.PaperServerListPingEvent event = PaperLegacyStatusClient.processRequest( ++ server, (InetSocketAddress) ctx.channel().remoteAddress(), protocolVersion, virtualHost); ++ if (event == null) { ++ ctx.close(); ++ return; ++ } ++ ++ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", event.getProtocolVersion(), event.getVersion(), ++ PaperLegacyStatusClient.getMotd(event), event.getNumPlayers(), event.getMaxPlayers()); + this.sendFlushAndClose(ctx, this.createReply(response)); + } + diff --git a/Remapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch b/Remapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch new file mode 100644 index 0000000000..467dda42a9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 31 Mar 2018 17:04:26 +0100 +Subject: [PATCH] Flag to disable the channel limit + +In some enviroments, the channel limit set by spigot can cause issues, +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 9d853733ff9054cc48925e22c8bb3c8d9b898808..46338fe5693003698de9c7b37a860c3481e06233 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -143,6 +143,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + // Paper start + private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; + private String resourcePackHash; ++ private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit + // Paper end + + public CraftPlayer(CraftServer server, ServerPlayer entity) { +@@ -1576,7 +1577,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void addChannel(String channel) { +- Preconditions.checkState(channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); ++ Preconditions.checkState(DISABLE_CHANNEL_LIMIT || channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); // Paper - flag to disable channel limit + channel = StandardMessenger.validateAndCorrectChannel(channel); + if (channels.add(channel)) { + server.getPluginManager().callEvent(new PlayerRegisterChannelEvent(this, channel)); diff --git a/Remapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch b/Remapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch new file mode 100644 index 0000000000..9a923369d1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 1 Apr 2018 02:29:37 +0300 +Subject: [PATCH] Add method to open already placed sign + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index c62d01719f21762aa10294815ab88e450e4dce3f..4aec1c2b26d48cb5bea3dfb9e183526763bdb98f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -28,6 +28,7 @@ import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CraftingTableBlock; + import net.minecraft.world.level.block.EnchantmentTableBlock; + import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import org.bukkit.GameMode; + import org.bukkit.Location; +@@ -604,6 +605,17 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + } + } + ++ // Paper start - Add method to open already placed sign ++ @Override ++ public void openSign(org.bukkit.block.Sign sign) { ++ org.apache.commons.lang.Validate.isTrue(sign.getWorld().equals(this.getWorld()), "Sign must be in the same world as player is in"); ++ org.bukkit.craftbukkit.block.CraftSign craftSign = (org.bukkit.craftbukkit.block.CraftSign) sign; ++ SignBlockEntity teSign = craftSign.getTileEntity(); ++ // Make sign editable temporarily, will be set back to false in PlayerConnection later ++ teSign.isEditable = true; ++ getHandle().openTextEdit(teSign); ++ } ++ // Paper end + @Override + public boolean dropItem(boolean dropAll) { + return getHandle().drop(dropAll); diff --git a/Remapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch b/Remapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch new file mode 100644 index 0000000000..dfe307fc2f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Sat, 14 Apr 2018 20:20:46 +0200 +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/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 48f0385c7203c7955de5a015f3dc42be2ab7b681..cebf1a623a9bec72d60fdd23dda01868ef6431d4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -358,4 +358,9 @@ public class PaperWorldConfig { + private void squidMaxSpawnHeight() { + squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); + } ++ ++ public boolean disableSprintInterruptionOnAttack; ++ private void disableSprintInterruptionOnAttack() { ++ disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", 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 c4aa824d03de952fe6b306e539baa47af979add1..552920f59aae9de2cad3edcdc8c48a91dff49093 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1180,7 +1180,11 @@ public abstract class Player extends LivingEntity { + } + + this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); +- this.setSprinting(false); ++ // Paper start - Configuration option to disable automatic sprint interruption ++ if (!level.paperConfig.disableSprintInterruptionOnAttack) { ++ this.setSprinting(false); ++ } ++ // Paper end + } + + if (flag3) { diff --git a/Remapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/Remapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch new file mode 100644 index 0000000000..68cdac63bd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 0x22 <0x22@futureclient.net> +Date: Thu, 26 Apr 2018 04:41:11 -0400 +Subject: [PATCH] Fix exploit that allowed colored signs to be created + + +diff --git a/src/main/java/net/minecraft/SharedConstants.java b/src/main/java/net/minecraft/SharedConstants.java +index a70c3d25930e7414fc9e897de8d2e0c12f11c0e4..04b8783417bbcd826d6d1c302551fbad9c48bd01 100644 +--- a/src/main/java/net/minecraft/SharedConstants.java ++++ b/src/main/java/net/minecraft/SharedConstants.java +@@ -20,6 +20,7 @@ public class SharedConstants { + return chr != 167 && chr >= ' ' && chr != 127; + } + ++ public static String filterAllowedChatCharacters(String input) { return filterText(input); } // Paper - OBFHELPER + public static String filterText(String s) { + StringBuilder stringbuilder = new StringBuilder(); + char[] achar = s.toCharArray(); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 8d0c44b6c2c99d5161c5d4b79209b79ff6db75e4..fb36aa08cd2fbe3f7262dccb8cf0f7cae55aea9c 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2786,7 +2786,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + List lines = new java.util.ArrayList<>(); + + for (int i = 0; i < list.size(); ++i) { +- lines.add(net.kyori.adventure.text.Component.text(list.get(i))); ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. + } + SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); + this.craftServer.getPluginManager().callEvent(event); diff --git a/Remapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch b/Remapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch new file mode 100644 index 0000000000..038bdea2df --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 13:15:55 -0400 +Subject: [PATCH] EndermanEscapeEvent + +Fires an event anytime an enderman intends to teleport away from the player + +You may cancel this, enabling ranged attacks to damage the enderman for example. + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index 1c2998c89fd660d6b26b7ff48cddd1862b9b1828..1b9c77666204765a3ed5648b0f8eaa820f578e58 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster; + + import java.util.EnumSet; + import java.util.Optional; ++import com.destroystokyo.paper.event.entity.EndermanEscapeEvent; // Paper + import java.util.Random; + import java.util.UUID; + import java.util.function.Predicate; +@@ -109,6 +110,12 @@ public class EnderMan extends Monster implements NeutralMob { + setGoalTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, true); + } + ++ // Paper start ++ private boolean tryEscape(EndermanEscapeEvent.Reason reason) { ++ return new EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent(); ++ } ++ // Paper end ++ + @Override + public boolean setGoalTarget(LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { + if (!super.setGoalTarget(entityliving, reason, fireEvent)) { +@@ -262,7 +269,7 @@ public class EnderMan extends Monster implements NeutralMob { + if (this.level.isDay() && this.tickCount >= this.targetChangeTime + 600) { + float f = this.getBrightness(); + +- if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) { ++ if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper + this.setTarget((LivingEntity) null); + this.teleport(); + } +@@ -360,17 +367,19 @@ public class EnderMan extends Monster implements NeutralMob { + if (this.isInvulnerableTo(source)) { + return false; + } else if (source instanceof IndirectEntityDamageSource) { ++ if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start + for (int i = 0; i < 64; ++i) { + if (this.teleport()) { + return true; + } + } ++ } // Paper end + + return false; + } else { + boolean flag = super.hurt(source, amount); + +- if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) { ++ if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0 && this.tryEscape(source == DamageSource.DROWN ? EndermanEscapeEvent.Reason.DROWN : EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - use to be critical hits as else, but mojang removed critical hits in 1.16.2 due to MC-185684 + this.teleport(); + } + +@@ -515,7 +524,7 @@ public class EnderMan extends Monster implements NeutralMob { + + static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal { + +- private final EnderMan enderman; ++ private final EnderMan enderman; public final EnderMan getEnderman() { return this.enderman; } // Paper - OBFHELPER + private Player pendingTarget; + private int aggroTime; + private int teleportTime; +@@ -578,7 +587,7 @@ public class EnderMan extends Monster implements NeutralMob { + } else { + if (this.target != null && !this.enderman.isPassenger()) { + if (this.enderman.isLookingAtMe((Player) this.target)) { +- if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D) { ++ if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D && this.getEnderman().tryEscape(EndermanEscapeEvent.Reason.STARE)) { // Paper + this.enderman.teleport(); + } + diff --git a/Remapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch b/Remapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch new file mode 100644 index 0000000000..f76f4023f9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 13:29:44 -0400 +Subject: [PATCH] Enderman.teleportRandomly() + +Ability to trigger the vanilla "teleport randomly" mechanic of an enderman. + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index 1b9c77666204765a3ed5648b0f8eaa820f578e58..1981c08af85b16d45531ffae4fe790bb31edec04 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -278,6 +278,7 @@ public class EnderMan extends Monster implements NeutralMob { + super.customServerAiStep(); + } + ++ public final boolean teleportRandomly() { return this.teleport(); } // Paper - OBFHELPER + protected boolean teleport() { + if (!this.level.isClientSide() && this.isAlive()) { + double d0 = this.getX() + (this.random.nextDouble() - 0.5D) * 64.0D; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java +index d17ed71e800ebcd12b69745f239fa7dbc8a0c808..1edb45490b35b6517201acc8551da8d3c5a489de 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java +@@ -16,6 +16,7 @@ public class CraftEnderman extends CraftMonster implements Enderman { + super(server, entity); + } + ++ @Override public boolean teleportRandomly() { return getHandle().teleportRandomly(); } // Paper + @Override + public MaterialData getCarriedMaterial() { + BlockState blockData = getHandle().getCarriedBlock(); diff --git a/Remapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch b/Remapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch new file mode 100644 index 0000000000..47a535288c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 17:15:26 -0400 +Subject: [PATCH] Block Enderpearl Travel Exploit + +Players are able to use alt accounts and enderpearls to travel +long distances utilizing the pearls in unloaded chunks and loading +the chunk later when convenient. + +This disables that by not saving the thrower when the chunk is unloaded. + +This is mainly useful for survival servers that do not allow freeform teleporting. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index cebf1a623a9bec72d60fdd23dda01868ef6431d4..e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -363,4 +363,10 @@ public class PaperWorldConfig { + private void disableSprintInterruptionOnAttack() { + disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); + } ++ ++ public boolean disableEnderpearlExploit = true; ++ private void disableEnderpearlExploit() { ++ disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); ++ log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index 14ed4f212a9c9c3128c4ddbef7b2e243c925b509..16b554675a276471851846d4f2bea06fdcc166d9 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -62,6 +62,7 @@ public abstract class Projectile extends Entity { + protected void readAdditionalSaveData(CompoundTag tag) { + if (tag.hasUUID("Owner")) { + this.ownerUUID = tag.getUUID("Owner"); ++ if (this instanceof ThrownEnderpearl && this.level != null && this.level.paperConfig.disableEnderpearlExploit) { this.ownerUUID = null; } // Paper - Don't store shooter name for pearls to block enderpearl travel exploit + } + + this.leftOwner = tag.getBoolean("LeftOwner"); diff --git a/Remapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch b/Remapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch new file mode 100644 index 0000000000..e2c16b5648 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 15 Aug 2017 22:29:12 -0400 +Subject: [PATCH] Expand World.spawnParticle API and add Builder + +Adds ability to control who receives it and who is the source/sender (vanish API) +the standard API is to send the packet to everyone in the world, which is ineffecient. +Adds an option to control the force mode of the particle. + +This adds a new Builder API which is much friendlier to use. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 20650bfd10abfa010e71cfeede06c461d50d19a3..5110f2c70d96284e8e7592b3d89266b867b9a466 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -164,7 +164,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final Int2ObjectMap entitiesById = new Int2ObjectLinkedOpenHashMap(); + private final Map entitiesByUuid = Maps.newHashMap(); + private final Queue toAddAfterTick = Queues.newArrayDeque(); +- private final List players = Lists.newArrayList(); ++ public final List players = Lists.newArrayList(); // Paper - private -> public + public final ServerChunkCache chunkSource; // Paper - public + boolean tickingEntities; + private final MinecraftServer server; +@@ -1472,12 +1472,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + public int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { ++ // Paper start - Particle API Expansion ++ return sendParticles(players, sender, t0, d0, d1, d2, i, d3, d4, d5, d6, force); ++ } ++ public int sendParticles(List receivers, ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { ++ // Paper end + ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); + // CraftBukkit end + int j = 0; + +- for (int k = 0; k < this.players.size(); ++k) { +- ServerPlayer entityplayer = (ServerPlayer) this.players.get(k); ++ for (Player entityhuman : receivers) { // Paper - Particle API Expansion ++ ServerPlayer entityplayer = (ServerPlayer) entityhuman; // Paper - Particle API Expansion + if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit + + if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 88658d4deacc29128c537e2e02fdc8f684090a2c..beb7219312be5143a50b0841c25efea5dbcc1267 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2334,11 +2334,17 @@ public class CraftWorld implements World { + + @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) { ++ // Paper start - Particle API Expansion ++ spawnParticle(particle, null, null, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, force); ++ } ++ public void spawnParticle(Particle particle, List receivers, Player sender, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) { ++ // Paper end + if (data != null && !particle.getDataType().isInstance(data)) { + throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); + } + getHandle().sendParticles( +- null, // Sender ++ receivers == null ? getHandle().players : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API Expansion ++ sender != null ? ((CraftPlayer) sender).getHandle() : null, // Sender // Paper - Particle API Expansion + CraftParticle.toNMS(particle, data), // Particle + x, y, z, // Position + count, // Count diff --git a/Remapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch b/Remapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch new file mode 100644 index 0000000000..3341055b48 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 1 May 2018 20:18:54 -0400 +Subject: [PATCH] EndermanAttackPlayerEvent + +Allow control over whether or not an enderman aggros a player. + +This allows you to override/extend the pumpkin/stare logic. + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index 1981c08af85b16d45531ffae4fe790bb31edec04..d190b58bea310f4006ea3deaf0d42c502d441284 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -221,20 +221,28 @@ public class EnderMan extends Monster implements NeutralMob { + this.readPersistentAngerSaveData((ServerLevel) this.level, tag); + } + ++ // Paper start - OBFHELPER - ok not really, but verify this on updates + private boolean isLookingAtMe(Player player) { +- ItemStack itemstack = (ItemStack) player.inventory.armor.get(3); ++ boolean shouldAttack = g_real(player); ++ com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) player.getBukkitEntity()); ++ event.setCancelled(!shouldAttack); ++ return event.callEvent(); ++ } ++ private boolean g_real(Player entityhuman) { ++ // Paper end ++ ItemStack itemstack = (ItemStack) entityhuman.inventory.armor.get(3); + + if (itemstack.getItem() == Blocks.CARVED_PUMPKIN.asItem()) { + return false; + } else { +- Vec3 vec3d = player.getViewVector(1.0F).normalize(); +- Vec3 vec3d1 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ()); ++ Vec3 vec3d = entityhuman.getViewVector(1.0F).normalize(); ++ Vec3 vec3d1 = new Vec3(this.getX() - entityhuman.getX(), this.getEyeY() - entityhuman.getEyeY(), this.getZ() - entityhuman.getZ()); + double d0 = vec3d1.length(); + + vec3d1 = vec3d1.normalize(); + double d1 = vec3d.dot(vec3d1); + +- return d1 > 1.0D - 0.025D / d0 ? player.canSee(this) : false; ++ return d1 > 1.0D - 0.025D / d0 ? entityhuman.canSee(this) : false; + } + } + diff --git a/Remapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch b/Remapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch new file mode 100644 index 0000000000..b17791b352 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 16 May 2018 20:35:16 -0400 +Subject: [PATCH] WitchConsumePotionEvent + +Fires when a witch consumes the potion in their hand + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java +index 9b0269bdd25123f5c0662187de49a869ead3ee81..dd5976d81ff57e8691ba60f425af37572edd26e7 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java +@@ -124,7 +124,11 @@ public class Witch extends Raider implements RangedAttackMob { + + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + if (itemstack.getItem() == Items.POTION) { +- List list = PotionUtils.getMobEffects(itemstack); ++ // Paper start ++ com.destroystokyo.paper.event.entity.WitchConsumePotionEvent event = new com.destroystokyo.paper.event.entity.WitchConsumePotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); ++ ++ List list = event.callEvent() ? PotionUtils.getMobEffects(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion())) : null; ++ // Paper end + + if (list != null) { + Iterator iterator = list.iterator(); diff --git a/Remapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch b/Remapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch new file mode 100644 index 0000000000..0630f7d920 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 16 May 2018 20:44:58 -0400 +Subject: [PATCH] WitchThrowPotionEvent + +Fired when a witch throws a potion at a player + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java +index dd5976d81ff57e8691ba60f425af37572edd26e7..7cefabfb0d8a264cae24f23c06f1c5f552ff0158 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java +@@ -224,9 +224,16 @@ public class Witch extends Raider implements RangedAttackMob { + potionregistry = Potions.WEAKNESS; + } + ++ // Paper start ++ ItemStack potion = PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potionregistry); ++ com.destroystokyo.paper.event.entity.WitchThrowPotionEvent event = new com.destroystokyo.paper.event.entity.WitchThrowPotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), (org.bukkit.entity.LivingEntity) target.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++ if (!event.callEvent()) { ++ return; ++ } ++ potion = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion()); + ThrownPotion entitypotion = new ThrownPotion(this.level, this); +- +- entitypotion.setItem(PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potionregistry)); ++ entitypotion.setItem(potion); ++ // Paper end + entitypotion.xRot -= -20.0F; + entitypotion.shoot(d0, d1 + (double) (f1 * 0.2F), d2, 0.75F, 8.0F); + if (!this.isSilent()) { diff --git a/Remapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/Remapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch new file mode 100644 index 0000000000..7e80925cf5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 4 Jun 2018 20:39:20 -0400 +Subject: [PATCH] Allow spawning Item entities with World.spawnEntity + +This API has more capabilities than .dropItem with the Consumer function + +Item can be set inside of the Consumer pre spawn function. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index beb7219312be5143a50b0841c25efea5dbcc1267..2dc9daaeea600fff1f2efddf74b6849fd745a28c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1497,6 +1497,10 @@ public class CraftWorld implements World { + if (Boat.class.isAssignableFrom(clazz)) { + entity = new net.minecraft.world.entity.vehicle.Boat(world, x, y, z); + entity.moveTo(x, y, z, yaw, pitch); ++ // Paper start ++ } else if (org.bukkit.entity.Item.class.isAssignableFrom(clazz)) { ++ entity = new ItemEntity(world, x, y, z, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Item.byBlock(net.minecraft.world.level.block.Blocks.DIRT))); ++ // Paper end + } else if (FallingBlock.class.isAssignableFrom(clazz)) { + entity = new FallingBlockEntity(world, x, y, z, world.getBlockState(new BlockPos(x, y, z))); + } else if (Projectile.class.isAssignableFrom(clazz)) { diff --git a/Remapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch b/Remapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch new file mode 100644 index 0000000000..2177cecc8f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Jun 2018 22:47:26 -0400 +Subject: [PATCH] WitchReadyPotionEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java +index 7cefabfb0d8a264cae24f23c06f1c5f552ff0158..a37ee32b46aa87be6e3eeca2892b4e7294fd1aef 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java +@@ -157,7 +157,11 @@ public class Witch extends Raider implements RangedAttackMob { + } + + if (potionregistry != null) { +- this.setItemSlot(EquipmentSlot.MAINHAND, PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry)); ++ // Paper start ++ ItemStack potion = PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry); ++ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++ this.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++ // Paper end + this.usingTime = this.getMainHandItem().getUseDuration(); + this.setUsingItem(true); + if (!this.isSilent()) { diff --git a/Remapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch b/Remapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch new file mode 100644 index 0000000000..2b415bf929 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Jun 2018 23:00:29 -0400 +Subject: [PATCH] ItemStack#getMaxItemUseDuration + +Allows you to determine how long it takes to use a usable/consumable item + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index a0815c0d7f68f345dc48c73b8253de637c7a3e0f..34187197efd5ceff0503682dc6ce313220ca916f 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -604,6 +604,7 @@ public final class ItemStack { + this.getItem().onCraftedBy(this, world, player); + } + ++ public int getItemUseMaxDuration() { return getUseDuration(); } // Paper - OBFHELPER + public int getUseDuration() { + return this.getItem().getUseDuration(this); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index 5f0ccdeb8565505278caa591f7390047eab49cf4..44caf00330e4f4f74745973dbe709980f0b61269 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -173,6 +173,13 @@ public final class CraftItemStack extends ItemStack { + return (handle == null) ? Material.AIR.getMaxStackSize() : handle.getItem().getMaxStackSize(); + } + ++ // Paper start ++ @Override ++ public int getMaxItemUseDuration() { ++ return handle == null ? 0 : handle.getItemUseMaxDuration(); ++ } ++ // Paper end ++ + @Override + public void addUnsafeEnchantment(Enchantment ench, int level) { + Validate.notNull(ench, "Cannot add null enchantment"); diff --git a/Remapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch b/Remapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch new file mode 100644 index 0000000000..007bf52a29 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 9 Jun 2018 14:08:39 +0200 +Subject: [PATCH] Implement EntityTeleportEndGatewayEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +index 2c974f9801d209907733bed8e6c4c9ef46e2b610..b70e0633435a272ae1e9fbd12d7f18862de0b951 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -191,9 +191,20 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements + + } + // CraftBukkit end ++ // Paper start - EntityTeleportEndGatewayEvent - replicated from above ++ org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity = entity.getBukkitEntity(); ++ org.bukkit.Location location = new Location(level.getWorld(), (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); ++ location.setPitch(bukkitEntity.getLocation().getPitch()); ++ location.setYaw(bukkitEntity.getLocation().getYaw()); ++ ++ com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent event = new com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent(bukkitEntity, bukkitEntity.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(level, this.getBlockPos()).getBlock())); ++ if (!event.callEvent()) { ++ return; ++ } ++ // Paper end + + entity1.setPortalCooldown(); +- entity1.teleportToWithTicket((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D); ++ entity1.teleportToWithTicket(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); // Paper + } + + this.triggerCooldown(); diff --git a/Remapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/Remapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch new file mode 100644 index 0000000000..1bda08648d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 Jun 2018 01:18:49 -0400 +Subject: [PATCH] Unset Ignited flag on cancel of Explosion Event + +Otherwise the creeper infinite explodes + +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 8f8d0a23d011936150854a0606be3d63b18c57af..d9b5cf8ac01289801ded01d928fa7ead96551be5 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +@@ -47,7 +47,7 @@ public class Creeper extends Monster { + + private static final EntityDataAccessor DATA_SWELL_DIR = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_IS_POWERED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); +- private static final EntityDataAccessor DATA_IS_IGNITED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); ++ private static final EntityDataAccessor DATA_IS_IGNITED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); private static final EntityDataAccessor isIgnitedDW = DATA_IS_IGNITED; // Paper OBFHELPER + private int oldSwell; + public int swell; // PAIL + public int maxSwell = 30; +@@ -252,6 +252,7 @@ public class Creeper extends Monster { + this.spawnLingeringCloud(); + } else { + swell = 0; ++ this.entityData.set(isIgnitedDW, Boolean.valueOf(false)); // Paper + } + // CraftBukkit end + } diff --git a/Remapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch b/Remapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch new file mode 100644 index 0000000000..dbc0942196 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 Jun 2018 20:20:15 -0400 +Subject: [PATCH] Fix CraftEntity hashCode + +hashCodes are not allowed to change, however bukkit used a value +that does change, the entityId. + +When an entity is teleported dimensions, the entity reference is +replaced with a new one with a new entity ID. + +For hashCode, we can simply use the UUID's hashCode to keep +the hashCode from changing. + +equals() is ok to use getEntityId() because equals() should only +be true if both the left and right are the same reference. + +Since entity ids can not duplicate during runtime, this +check is essentially the same as this.getHandle() == other.getHandle() + +However, replaced it too to make it clearer of intent. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index ecb5f5ca547930f91602d539e541964cd9f10287..e1bbaf620f3ed2a6cb9ce8007a78c4cee47b653e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -745,14 +745,15 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return false; + } + final CraftEntity other = (CraftEntity) obj; +- return (this.getEntityId() == other.getEntityId()); ++ return (this.getHandle() == other.getHandle()); // Paper - while logically the same, this is clearer + } + ++ // Paper - Fix hashCode. entity ID's are not static. ++ // A CraftEntity can change reference to a new entity with a new ID, and hash codes should never change + @Override + public int hashCode() { +- int hash = 7; +- hash = 29 * hash + this.getEntityId(); +- return hash; ++ return getUniqueId().hashCode(); ++ // Paper end + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch b/Remapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch new file mode 100644 index 0000000000..5a10f8c4d8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch @@ -0,0 +1,118 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 15 Jun 2018 00:30:32 -0400 +Subject: [PATCH] Configurable Alternative LootPool Luck Formula + +Rewrites the Vanilla luck application formula so that luck can be +applied to items that do not have any quality defined. + +See: https://luckformula.emc.gs for data and details +----------- + +The rough summary is: +My goal was that in a pool, when luck was applied, the pool +rebalances so the percentages for bigger items is +lowered and smaller items is boosted. + +Do this by boosting and then reducing the weight value, +so that larger numbers are penalized more than smaller numbers. +resulting in a larger reduction of entries for more common +items than the reduction on small weights, +giving smaller weights more of a chance + +----------- + +This work kind of obsoletes quality, but quality would be useful +for 2 items with same weight that you want luck to impact +in varying directions. + +Fishing still falls into that as the weights are closer, so luck +will invalidate junk more. + +This change will result in some major changes to fishing formulas. + +----------- + +I would love to see this change in Vanilla, so Mojang please pull :) + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 05a5abb951abe37f30a719cb75376d2d43c0d252..77a03abd59db4a43f6f2d59d4c7ef176e782f205 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -288,4 +288,12 @@ public class PaperConfig { + SpigotConfig.save(); + } + } ++ ++ public static boolean useAlternativeLuckFormula = false; ++ private static void useAlternativeLuckFormula() { ++ useAlternativeLuckFormula = getBoolean("settings.use-alternative-luck-formula", false); ++ if (useAlternativeLuckFormula) { ++ Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java +index ceb5e5405ed20c8de954847bbb269109107a43fc..d99bc0b8a1e9c4749b176a823b879ced9efdd7d6 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java +@@ -8,7 +8,6 @@ import java.util.List; + import java.util.function.BiFunction; + import java.util.function.Consumer; + import net.minecraft.util.GsonHelper; +-import net.minecraft.util.Mth; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.storage.loot.LootContext; + import net.minecraft.world.level.storage.loot.ValidationContext; +@@ -20,8 +19,8 @@ import org.apache.commons.lang3.ArrayUtils; + + public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer { + +- protected final int weight; +- protected final int quality; ++ protected final int weight; public int getWeight() { return weight; } // Paper - OBFHELPER ++ protected final int quality; public int getQuality() { return quality; } // Paper - OBFHELPER + protected final LootItemFunction[] functions; + private final BiFunction compositeFunction; + private final LootPoolEntry entry = new LootPoolSingletonContainer.EntryBase() { +@@ -152,11 +151,38 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer + + public abstract class EntryBase implements LootPoolEntry { + +- protected EntryBase() {} ++ protected EntryBase() { ++ } + + @Override + public int getWeight(float luck) { +- return Math.max(Mth.floor((float) LootPoolSingletonContainer.this.weight + (float) LootPoolSingletonContainer.this.quality * luck), 0); ++ // Paper start - Offer an alternative loot formula to refactor how luck bonus applies ++ // SEE: https://luckformula.emc.gs for details and data ++ if (lastLuck != null && lastLuck == luck) { ++ return lastWeight; ++ } ++ // This is vanilla ++ float qualityModifer = (float) getQuality() * luck; ++ double baseWeight = (getWeight() + qualityModifer); ++ if (com.destroystokyo.paper.PaperConfig.useAlternativeLuckFormula) { ++ // Random boost to avoid losing precision in the final int cast on return ++ final int weightBoost = 100; ++ baseWeight *= weightBoost; ++ // If we have vanilla 1, bump that down to 0 so nothing is is impacted ++ // vanilla 3 = 300, 200 basis = impact 2% ++ // =($B2*(($B2-100)/100/100)) ++ double impacted = baseWeight * ((baseWeight - weightBoost) / weightBoost / 100); ++ // =($B$7/100) ++ float luckModifier = Math.min(100, luck * 10) / 100; ++ // =B2 - (C2 *($B$7/100)) ++ baseWeight = Math.ceil(baseWeight - (impacted * luckModifier)); ++ } ++ lastLuck = luck; ++ lastWeight = (int) Math.max(0, Math.floor(baseWeight)); ++ return lastWeight; + } + } ++ private Float lastLuck = null; ++ private int lastWeight = 0; ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch b/Remapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch new file mode 100644 index 0000000000..368773ef81 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 15 Jun 2018 20:37:03 -0400 +Subject: [PATCH] Print Error details when failing to save player data + + +diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +index 60fe01e824e4657d2601797d7858d5de339ab255..5b2a558d4d357d0de033ec2d7a9b4686f202c903 100644 +--- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +@@ -43,7 +43,7 @@ public class PlayerDataStorage { + + Util.safeReplaceFile(file1, file, file2); + } catch (Exception exception) { +- PlayerDataStorage.LOGGER.warn("Failed to save player data for {}", entityhuman.getName().getString()); ++ PlayerDataStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getScoreboardName(), exception); // Paper + } + + } diff --git a/Remapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch b/Remapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch new file mode 100644 index 0000000000..9472536ee6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 16 Jun 2018 01:18:16 -0500 +Subject: [PATCH] Make shield blocking delay configurable + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec..3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -369,4 +369,9 @@ public class PaperWorldConfig { + disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); + log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); + } ++ ++ public int shieldBlockingDelay = 5; ++ private void shieldBlockingDelay() { ++ shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 8b0d1f4fbc43a6f37a5f9c453b5dd142a4f69745..af2e81137d9c686f8d94a1d0d7241619fa1f352c 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3308,7 +3308,7 @@ public abstract class LivingEntity extends Entity { + if (this.isUsingItem() && !this.useItem.isEmpty()) { + Item item = this.useItem.getItem(); + +- return item.getUseAnimation(this.useItem) != UseAnim.BLOCK ? false : item.getUseDuration(this.useItem) - this.useItemRemaining >= 5; ++ return item.getUseAnimation(this.useItem) != UseAnim.BLOCK ? false : item.getUseDuration(this.useItem) - this.useItemRemaining >= getShieldBlockingDelay(); // Paper - shieldBlockingDelay + } else { + return false; + } +@@ -3587,4 +3587,15 @@ public abstract class LivingEntity extends Entity { + public void broadcastBreakEvent(InteractionHand hand) { + this.broadcastBreakEvent(hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); + } ++ // Paper start ++ public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; ++ ++ public int getShieldBlockingDelay() { ++ return shieldBlockingDelay; ++ } ++ ++ public void setShieldBlockingDelay(int shieldBlockingDelay) { ++ this.shieldBlockingDelay = shieldBlockingDelay; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 006f4c71bbcda61b55815e7ceab91731ab062da0..663887d9aecc2823fe7d02a9b108a291cd27102c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -699,5 +699,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setArrowsStuck(int arrows) { + getHandle().setArrowCount(arrows); + } ++ ++ @Override ++ public int getShieldBlockingDelay() { ++ return getHandle().getShieldBlockingDelay(); ++ } ++ ++ @Override ++ public void setShieldBlockingDelay(int delay) { ++ getHandle().setShieldBlockingDelay(delay); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch b/Remapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch new file mode 100644 index 0000000000..4fc5ab999a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 15 Jun 2013 19:51:17 -0400 +Subject: [PATCH] Improve EntityShootBowEvent + +Adds missing call to Illagers and also adds Arrow ItemStack to skeltons + +diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +index e8ad820b11dd1b89e442bb057d5761c90c4b1923..76027a7c9615495af64102744e264d7ba7c9b87e 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -197,7 +197,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + + entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level.getDifficulty().getId() * 4)); + // CraftBukkit start +- org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), null, entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getOriginalItemStack(), entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper + if (event.isCancelled()) { + event.getProjectile().remove(); + return; +diff --git a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +index ab8c41e72c15ee9e5256eba2ba2681a33ce8a8d9..2d07e9cf4c84bc32a7624f65173c4e8a6dc07165 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +@@ -171,8 +171,18 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { + double d3 = (double) Mth.sqrt(d0 * d0 + d2 * d2); + + entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level.getDifficulty().getId() * 4)); ++ // Paper start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getOriginalItemStack(), entityarrow, target.getUsedItemHand(), 0.8F, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ this.level.addFreshEntity(entityarrow); ++ } + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level.addFreshEntity(entityarrow); ++ // Paper end + } + + class IllusionerBlindnessSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { diff --git a/Remapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch b/Remapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch new file mode 100644 index 0000000000..1250005dcb --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 18 Jun 2018 01:12:53 -0400 +Subject: [PATCH] PlayerReadyArrowEvent + +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 552920f59aae9de2cad3edcdc8c48a91dff49093..b88d8f2c377322290002e84e217f3f2f6e4e71e8 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -2139,6 +2139,17 @@ public abstract class Player extends LivingEntity { + return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING); + } + ++ // Paper start ++ protected boolean tryReadyArrow(ItemStack bow, ItemStack itemstack) { ++ return !(this instanceof ServerPlayer) || ++ new com.destroystokyo.paper.event.player.PlayerReadyArrowEvent( ++ ((ServerPlayer) this).getBukkitEntity(), ++ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(bow), ++ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack) ++ ).callEvent(); ++ // Paper end ++ } ++ + @Override + public ItemStack getProjectile(ItemStack stack) { + if (!(stack.getItem() instanceof ProjectileWeaponItem)) { +@@ -2155,7 +2166,7 @@ public abstract class Player extends LivingEntity { + for (int i = 0; i < this.inventory.getContainerSize(); ++i) { + ItemStack itemstack2 = this.inventory.getItem(i); + +- if (predicate.test(itemstack2)) { ++ if (predicate.test(itemstack2) && tryReadyArrow(stack, itemstack2)) { // Paper + return itemstack2; + } + } diff --git a/Remapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch b/Remapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch new file mode 100644 index 0000000000..79e858a274 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Mon, 18 Jun 2018 15:46:23 +0200 +Subject: [PATCH] Implement EntityKnockbackByEntityEvent + +This event is called when an entity receives knockback by another entity. + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index af2e81137d9c686f8d94a1d0d7241619fa1f352c..04489a915d11ba970a5188a5a913432ab4ef9faa 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1336,7 +1336,7 @@ public abstract class LivingEntity extends Entity { + } + + this.hurtDir = (float) (Mth.atan2(d1, d0) * 57.2957763671875D - (double) this.yRot); +- this.knockback(0.4F, d0, d1); ++ this.doKnockback(0.4F, d0, d1, entity1); // Paper + } else { + this.hurtDir = (float) ((int) (Math.random() * 2.0D) * 180); + } +@@ -1384,7 +1384,7 @@ public abstract class LivingEntity extends Entity { + } + + protected void blockedByShield(LivingEntity target) { +- target.knockback(0.5F, target.getX() - this.getX(), target.getZ() - this.getZ()); ++ target.doKnockback(0.5F, target.getX() - this.getX(), target.getZ() - this.getZ(), this); // Paper + } + + private boolean checkTotemDeathProtection(DamageSource source) { +@@ -1627,6 +1627,11 @@ public abstract class LivingEntity extends Entity { + } + + public void knockback(float f, double d0, double d1) { ++ // Paper start - add knockbacking entity parameter ++ this.doKnockback(f, d0, d1, null); ++ } ++ public void doKnockback(float f, double d0, double d1, Entity knockingBackEntity) { ++ // Paper end - add knockbacking entity parameter + f = (float) ((double) f * (1.0D - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE))); + if (f > 0.0F) { + this.hasImpulse = true; +@@ -1634,6 +1639,16 @@ public abstract class LivingEntity extends Entity { + Vec3 vec3d1 = (new Vec3(d0, 0.0D, d1)).normalize().scale((double) f); + + this.setDeltaMovement(vec3d.x / 2.0D - vec3d1.x, this.onGround ? Math.min(0.4D, vec3d.y / 2.0D + (double) f) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); ++ ++ // Paper start - call EntityKnockbackByEntityEvent ++ Vec3 currentMot = this.getDeltaMovement(); ++ org.bukkit.util.Vector delta = new org.bukkit.util.Vector(currentMot.x - vec3d.x, currentMot.y - vec3d.y, currentMot.z - vec3d.z); ++ // Restore old velocity to be able to access it in the event ++ this.setDeltaMovement(vec3d); ++ if (knockingBackEntity == null || new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent((org.bukkit.entity.LivingEntity) getBukkitEntity(), knockingBackEntity.getBukkitEntity(), f, delta).callEvent()) { ++ this.setDeltaMovement(vec3d.x + delta.getX(), vec3d.y + delta.getY(), vec3d.z + delta.getZ()); ++ } ++ // Paper end + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index eb35c69bb777ba8d83b2304ff9f862512643e745..f3690ea49cf90c816b8b3554b47d6f2d9dfbe016 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -1566,7 +1566,7 @@ public abstract class Mob extends LivingEntity { + + if (flag) { + if (f1 > 0.0F && target instanceof LivingEntity) { +- ((LivingEntity) target).knockback(f1 * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F))); ++ ((LivingEntity) target).doKnockback(f1 * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)), this); // Paper + this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); + } + +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 b88d8f2c377322290002e84e217f3f2f6e4e71e8..5e6a86b0b8999a5c47d2f9bdd9857ab5f0772033 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1174,7 +1174,7 @@ public abstract class Player extends LivingEntity { + if (flag5) { + if (i > 0) { + if (target instanceof LivingEntity) { +- ((LivingEntity) target).knockback((float) i * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F))); ++ ((LivingEntity) target).doKnockback((float) i * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)), this); // Paper + } else { + target.push((double) (-Mth.sin(this.yRot * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.yRot * 0.017453292F) * (float) i * 0.5F)); + } +@@ -1198,7 +1198,7 @@ public abstract class Player extends LivingEntity { + if (entityliving != this && entityliving != target && !this.isAlliedTo(entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) { + // CraftBukkit start - Only apply knockback if the damage hits + if (entityliving.hurt(DamageSource.playerAttack(this).sweep(), f4)) { +- entityliving.knockback(0.4F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F))); ++ entityliving.doKnockback(0.4F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)), this); // Paper + } + // CraftBukkit end + } diff --git a/Remapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch b/Remapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch new file mode 100644 index 0000000000..01be1df09c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 20 Jun 2018 23:17:24 -0400 +Subject: [PATCH] Expand Explosions API + +Add Entity as a Source capability, and add more API choices, and on Location. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 2dc9daaeea600fff1f2efddf74b6849fd745a28c..9b5a1c3ab8ffde524e194fdeaa8eaef6b286b57b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -871,6 +871,11 @@ public class CraftWorld implements World { + public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) { + return !world.explode(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; + } ++ // Paper start ++ public boolean createExplosion(Entity source, Location loc, float power, boolean setFire, boolean breakBlocks) { ++ return !world.explode(source != null ? ((org.bukkit.craftbukkit.entity.CraftEntity) source).getHandle() : null, loc.getX(), loc.getY(), loc.getZ(), power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; ++ } ++ // Paper end + + @Override + public boolean createExplosion(Location loc, float power) { diff --git a/Remapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch b/Remapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch new file mode 100644 index 0000000000..181103a79c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 Jun 2018 00:21:28 -0400 +Subject: [PATCH] LivingEntity Hand Raised/Item Use API + +How long an entity has raised hands to charge an attack or use an item + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 04489a915d11ba970a5188a5a913432ab4ef9faa..205c639d26652befebae925fc6e40976c370710f 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -209,7 +209,7 @@ public abstract class LivingEntity extends Entity { + private float speed; + private int noJumpDelay; + private float absorptionAmount; +- protected ItemStack useItem; ++ public ItemStack useItem; // Paper - public + protected int useItemRemaining; + protected int fallFlyTicks; + private BlockPos lastPos; +@@ -3291,10 +3291,12 @@ public abstract class LivingEntity extends Entity { + return this.useItem; + } + ++ public int getItemUseRemainingTime() { return this.getUseItemRemainingTicks(); } // Paper - OBFHELPER + public int getUseItemRemainingTicks() { + return this.useItemRemaining; + } + ++ public int getHandRaisedTime() { return this.getTicksUsingItem(); } // Paper - OBFHELPER + public int getTicksUsingItem() { + return this.isUsingItem() ? this.useItem.getUseDuration() - this.getUseItemRemainingTicks() : 0; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 663887d9aecc2823fe7d02a9b108a291cd27102c..6dd7a722e10a2727f68318b880f2726bb816f198 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -709,5 +709,30 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setShieldBlockingDelay(int delay) { + getHandle().setShieldBlockingDelay(delay); + } ++ ++ @Override ++ public ItemStack getActiveItem() { ++ return getHandle().useItem.asBukkitMirror(); ++ } ++ ++ @Override ++ public int getItemUseRemainingTime() { ++ return getHandle().getItemUseRemainingTime(); ++ } ++ ++ @Override ++ public int getHandRaisedTime() { ++ return getHandle().getHandRaisedTime(); ++ } ++ ++ @Override ++ public boolean isHandRaised() { ++ return getHandle().isUsingItem(); ++ } ++ ++ @Override ++ public org.bukkit.inventory.EquipmentSlot getHandRaised() { ++ return getHandle().getUsedItemHand() == net.minecraft.world.InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0230-RangedEntity-API.patch b/Remapped-Spigot-Server-Patches/0230-RangedEntity-API.patch new file mode 100644 index 0000000000..40db6f9590 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0230-RangedEntity-API.patch @@ -0,0 +1,171 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 26 Jun 2018 22:00:49 -0400 +Subject: [PATCH] RangedEntity API + +Allows you to determine if an entity is capable of ranged attacks, +and to perform an attack. + +diff --git a/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e75e1d0d833c96af139fd955b2585ec24281b294 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java +@@ -0,0 +1,19 @@ ++package com.destroystokyo.paper.entity; ++ ++import net.minecraft.world.entity.monster.RangedAttackMob; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.LivingEntity; ++ ++public interface CraftRangedEntity extends RangedEntity { ++ T getHandle(); ++ ++ @Override ++ default void rangedAttack(LivingEntity target, float charge) { ++ getHandle().rangedAttack(((CraftLivingEntity) target).getHandle(), charge); ++ } ++ ++ @Override ++ default void setChargingAttack(boolean raiseHands) { ++ getHandle().setChargingAttack(raiseHands); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java b/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java +index b3ad4d54eeb1b894c24a5a76e8b12b8d9568cd56..ae10f3933fe78f74995952a6a8acf09ef4e99823 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java ++++ b/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java +@@ -4,5 +4,8 @@ import net.minecraft.world.entity.LivingEntity; + + public interface RangedAttackMob { + +- void performRangedAttack(LivingEntity target, float pullProgress); ++ void performRangedAttack(LivingEntity target, float pullProgress); default void rangedAttack(LivingEntity entityliving, float f) { performRangedAttack(entityliving, f); } // Paper - OBFHELPER ++ ++ // - see EntitySkeletonAbstract melee goal ++ void setAggressive(boolean flag); default void setChargingAttack(boolean charging) { setAggressive(charging); }; // Paper + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java +index 34cb8062168258bfd168826ceeb2fde669f6d1a8..03e2acd4829da449a471b0fa1a311e74aee114d3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java +@@ -4,7 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.Drowned; + import org.bukkit.entity.EntityType; + +-public class CraftDrowned extends CraftZombie implements Drowned { ++public class CraftDrowned extends CraftZombie implements Drowned, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftDrowned(CraftServer server, net.minecraft.world.entity.monster.Drowned entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java +index 59b866e54e0d7e1dd8815ffa85275e36271113da..bbf7189a0fc9921e7a6007494f91229d9fba0846 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java +@@ -4,7 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Illusioner; + +-public class CraftIllusioner extends CraftSpellcaster implements Illusioner { ++public class CraftIllusioner extends CraftSpellcaster implements Illusioner, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftIllusioner(CraftServer server, net.minecraft.world.entity.monster.Illusioner entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java +index 04f716af67939b2dc34875f722816dd1ffdc4966..ed3b8fcc221d6c0789eb92eb4716d640ba0fec9f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import com.destroystokyo.paper.entity.CraftRangedEntity; + import com.google.common.base.Preconditions; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.inventory.CraftInventoryLlama; +@@ -9,7 +10,7 @@ import org.bukkit.entity.Llama; + import org.bukkit.entity.Llama.Color; + import org.bukkit.inventory.LlamaInventory; + +-public class CraftLlama extends CraftChestedHorse implements Llama { ++public class CraftLlama extends CraftChestedHorse implements Llama, CraftRangedEntity { // Paper + + public CraftLlama(CraftServer server, net.minecraft.world.entity.animal.horse.Llama entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java +index 12bce49fcb164b6311a81024d1749a582ab1be25..c06fea6e0eaf58b8e7441ccf8595d6ca8417526a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java +@@ -13,7 +13,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.Piglin; + import org.bukkit.inventory.Inventory; + +-public class CraftPiglin extends CraftPiglinAbstract implements Piglin { ++public class CraftPiglin extends CraftPiglinAbstract implements Piglin, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftPiglin(CraftServer server, net.minecraft.world.entity.monster.piglin.Piglin entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java +index fc86b8ecc349ed59c9eb6de03086d4027cb4e08d..949260d6750e71f148229955c94bcbaad9d54a2d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java +@@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.Pillager; + import org.bukkit.inventory.Inventory; + +-public class CraftPillager extends CraftIllager implements Pillager { ++public class CraftPillager extends CraftIllager implements Pillager, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftPillager(CraftServer server, net.minecraft.world.entity.monster.Pillager entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +index 4cd3dfd3466f384aab06dacd388e8053b045b046..b2d3244cca4d9d108159f3537d8a9aace3f8e77f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +@@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.Skeleton; + import org.bukkit.entity.Skeleton.SkeletonType; + +-public class CraftSkeleton extends CraftMonster implements Skeleton { ++public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftSkeleton(CraftServer server, AbstractSkeleton entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java +index fcce4aa391d0c448531815e99e0e32c84203c1b8..a7164a921f479c928049d4e812eab50567e96fc2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java +@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Snowman; + +-public class CraftSnowman extends CraftGolem implements Snowman { ++public class CraftSnowman extends CraftGolem implements Snowman, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftSnowman(CraftServer server, SnowGolem entity) { + super(server, entity); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +index 60e00e539d214eb8854a53364c92c3cf55ca1062..d4eeb071dbbfca3ecea256228853bcb5c11f49ee 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +@@ -4,7 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Witch; + +-public class CraftWitch extends CraftRaider implements Witch { ++public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftWitch(CraftServer server, net.minecraft.world.entity.monster.Witch entity) { + super(server, entity); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +index 728a8c0f5781f33bdb096aefb569e9509dda8c89..fdcd680b972da54f9cdb41dff5563e42bd12d8e3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +@@ -7,7 +7,7 @@ import org.bukkit.craftbukkit.boss.CraftBossBar; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Wither; + +-public class CraftWither extends CraftMonster implements Wither { ++public class CraftWither extends CraftMonster implements Wither, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + private BossBar bossBar; + diff --git a/Remapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch b/Remapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch new file mode 100644 index 0000000000..1ba8695871 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 22 Jun 2018 10:38:31 -0500 +Subject: [PATCH] Add config to disable ender dragon legacy check + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77..4813f62d1e382d5ac6971b2244df3f13c80d1950 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -374,4 +374,9 @@ public class PaperWorldConfig { + private void shieldBlockingDelay() { + shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); + } ++ ++ public boolean scanForLegacyEnderDragon = true; ++ private void scanForLegacyEnderDragon() { ++ scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 2386ffeec60851ba192b89bc6fd7ffff9c56aff5..4b18931225ef60dbcffd7fcc20d0e9ce62348a07 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -73,7 +73,7 @@ public class EndDragonFight { + private boolean dragonKilled; + private boolean previouslyKilled; + public UUID dragonUUID; +- private boolean needsStateScanning; ++ private boolean needsStateScanning; private void setScanForLegacyFight(boolean scanForLegacyFight) { this.needsStateScanning = scanForLegacyFight; } private boolean scanForLegacyFight() { return this.needsStateScanning; } // Paper - OBFHELPER + public BlockPos portalLocation; + public DragonRespawnAnimation respawnStage; + private int respawnTime; diff --git a/Remapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch b/Remapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch new file mode 100644 index 0000000000..6bcd99431d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Tue, 3 Jul 2018 16:08:14 +0200 +Subject: [PATCH] Implement World.getEntity(UUID) API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 9b5a1c3ab8ffde524e194fdeaa8eaef6b286b57b..3a3466cd9bbd34dbc0b79567f5579e84a81d6009 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1286,6 +1286,15 @@ public class CraftWorld implements World { + return list; + } + ++ // Paper start - getEntity by UUID API ++ @Override ++ public Entity getEntity(UUID uuid) { ++ Validate.notNull(uuid, "UUID cannot be null"); ++ net.minecraft.world.entity.Entity entity = world.getEntity(uuid); ++ return entity == null ? null : entity.getBukkitEntity(); ++ } ++ // Paper end ++ + @Override + public void save() { + org.spigotmc.AsyncCatcher.catchOp("world save"); // Spigot diff --git a/Remapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch b/Remapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch new file mode 100644 index 0000000000..c1daa66bf3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch @@ -0,0 +1,228 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 3 Jul 2018 21:56:23 -0400 +Subject: [PATCH] InventoryCloseEvent Reason API + +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/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 5110f2c70d96284e8e7592b3d89266b867b9a466..ea1b15495481157912140bf5de9bf4a949c16910 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1119,7 +1119,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + for (BlockEntity tileentity : chunk.getBlockEntities().values()) { + if (tileentity instanceof net.minecraft.world.Container) { + for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((net.minecraft.world.Container) tileentity).getViewers())) { +- h.closeInventory(); ++ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper + } + } + } +@@ -1177,7 +1177,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // Spigot Start + if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder) { + for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) { +- h.closeInventory(); ++ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper + } + } + // 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 0fa977a31cf945b74f3a046b6be302b10f494ad1..1441a461e749dbfa303095f6b51d655c45f68ce0 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -544,7 +544,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + // Paper end + if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.containerMenu = this.inventoryMenu; + } + +@@ -717,7 +717,7 @@ public class ServerPlayer extends Player implements ContainerListener { + + // SPIGOT-943 - only call if they have an inventory open + if (this.containerMenu != this.inventoryMenu) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DEATH); // Paper + } + + net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure +@@ -1290,7 +1290,7 @@ public class ServerPlayer extends Player implements ContainerListener { + return OptionalInt.empty(); + } else { + if (this.containerMenu != this.inventoryMenu) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + this.nextContainerCounter(); +@@ -1350,7 +1350,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + // CraftBukkit end + if (this.containerMenu != this.inventoryMenu) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + // this.nextContainerCounter(); // CraftBukkit - moved up +@@ -1414,7 +1414,12 @@ public class ServerPlayer extends Player implements ContainerListener { + + @Override + public void closeContainer() { +- CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit ++ // Paper start ++ closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); ++ } ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit ++ // Paper end + this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); + this.doCloseContainer(); + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index fb36aa08cd2fbe3f7262dccb8cf0f7cae55aea9c..d322e99170b3cb6594efc824a879ab9a538ea1eb 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -188,6 +188,7 @@ import org.bukkit.event.inventory.ClickType; + import org.bukkit.event.inventory.CraftItemEvent; + import org.bukkit.event.inventory.InventoryAction; + import org.bukkit.event.inventory.InventoryClickEvent; ++import org.bukkit.event.inventory.InventoryCloseEvent; // Paper + import org.bukkit.event.inventory.InventoryCreativeEvent; + import org.bukkit.event.inventory.InventoryType.SlotType; + import org.bukkit.event.inventory.SmithItemEvent; +@@ -2309,10 +2310,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + @Override + public void handleContainerClose(ServerboundContainerClosePacket packet) { +- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); ++ // Paper start ++ handleContainerClose(packet, InventoryCloseEvent.Reason.PLAYER); ++ } ++ public void handleContainerClose(ServerboundContainerClosePacket packetplayinclosewindow, InventoryCloseEvent.Reason reason) { ++ // Paper end ++ PacketUtils.ensureRunningOnSameThread(packetplayinclosewindow, this, this.player.getLevel()); + + if (this.player.isImmobile()) return; // CraftBukkit +- CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit ++ CraftEventFactory.handleInventoryCloseEvent(this.player, reason); // CraftBukkit // Paper + + this.player.doCloseContainer(); + } +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index ae60b233c4d56a4964b388f96e9cc66410774e8d..51b1ce465d23b971f7e08a3175319a33183d0398 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -490,7 +490,7 @@ public abstract class PlayerList { + // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it + // See SPIGOT-5799, SPIGOT-6145 + if (entityplayer.containerMenu != entityplayer.inventoryMenu) { +- entityplayer.closeContainer(); ++ entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper + } + + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); +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 5e6a86b0b8999a5c47d2f9bdd9857ab5f0772033..709e930eef7bae5694238ed8c4d0ef59316bb715 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -249,7 +249,7 @@ public abstract class Player extends LivingEntity { + this.updateIsUnderwater(); + super.tick(); + if (!this.level.isClientSide && this.containerMenu != null && !this.containerMenu.stillValid(this)) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.containerMenu = this.inventoryMenu; + } + +@@ -444,6 +444,13 @@ public abstract class Player extends LivingEntity { + return 20; + } + ++ // Paper start - unused code, but to keep signatures aligned ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ closeContainer(); ++ this.containerMenu = this.inventoryMenu; ++ } ++ // Paper end ++ + public void closeContainer() { + 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 4aec1c2b26d48cb5bea3dfb9e183526763bdb98f..a73c6ddd6bf66cc21ae5b25daacdece8cbfeeeac 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -374,7 +374,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + if (((ServerPlayer) getHandle()).connection == null) return; + if (getHandle().containerMenu != getHandle().inventoryMenu) { + // fire INVENTORY_CLOSE if one already open +- ((ServerPlayer) getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(getHandle().containerMenu.containerId)); ++ ((ServerPlayer) getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(getHandle().containerMenu.containerId), org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + ServerPlayer player = (ServerPlayer) getHandle(); + AbstractContainerMenu container; +@@ -444,8 +444,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + + @Override + public void closeInventory() { +- getHandle().closeContainer(); ++ // Paper start ++ getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); + } ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ getHandle().closeContainer(reason); ++ } ++ // Paper end + + @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 46338fe5693003698de9c7b37a860c3481e06233..c7f66dddf0a0850ca4048dd47cd2ded114caa07e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -895,7 +895,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + // Close any foreign inventory + if (getHandle().containerMenu != getHandle().inventoryMenu) { +- getHandle().closeContainer(); ++ getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper + } + + // 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 5e8ff18f98b03741ccbb927f87499ae36d775a86..c2f58b95db41b2205fbf2728c6a99419c6a63dfa 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1175,7 +1175,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 +- player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId)); ++ player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + CraftServer server = player.level.getCraftServer(); +@@ -1341,8 +1341,18 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start ++ /** ++ * Incase plugins hooked into this or Spigot adds a new inventory close event. Prefer to pass a reason ++ * @param human ++ */ ++ @Deprecated + public static void handleInventoryCloseEvent(net.minecraft.world.entity.player.Player human) { +- InventoryCloseEvent event = new InventoryCloseEvent(human.containerMenu.getBukkitView()); ++ handleInventoryCloseEvent(human, org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); ++ } ++ public static void handleInventoryCloseEvent(net.minecraft.world.entity.player.Player human, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ // Paper end ++ InventoryCloseEvent event = new InventoryCloseEvent(human.containerMenu.getBukkitView(), reason); // Paper + human.level.getCraftServer().getPluginManager().callEvent(event); + human.containerMenu.transferTo(human.inventoryMenu, human.getBukkitEntity()); + } diff --git a/Remapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch b/Remapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch new file mode 100644 index 0000000000..0689023cf1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 15:30:22 -0400 +Subject: [PATCH] Vex#getSummoner API + +Get's the NPC that summoned this Vex + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java +index 3204ae9a9243818727bedfa060c07bc34d3b4c66..ec4f6d96360e759ffc19de838fdbf3027164a424 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vex.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java +@@ -124,6 +124,7 @@ public class Vex extends Monster { + + } + ++ public Mob getOwner() { return getOwner(); } // Paper - OBFHELPER + public Mob getOwner() { + return this.owner; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +index 2b4e9ddca5c6429c01d780d65a64ef6a59446c69..56bec4350f36a94d4dfa71a234872a795c2dcb3f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +@@ -15,6 +15,13 @@ public class CraftVex extends CraftMonster implements Vex { + return (net.minecraft.world.entity.monster.Vex) super.getHandle(); + } + ++ // Paper start ++ public org.bukkit.entity.Mob getSummoner() { ++ net.minecraft.world.entity.Mob owner = getHandle().getOwner(); ++ return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; ++ } ++ // Paper end ++ + @Override + public String toString() { + return "CraftVex"; diff --git a/Remapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/Remapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch new file mode 100644 index 0000000000..5cab7fe140 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Fri, 13 Jul 2018 14:54:43 +0200 +Subject: [PATCH] Refresh player inventory when cancelling + PlayerInteractEntityEvent + +When interacting with entities with an item, the client will assume +the interaction is successful, and update the held item on the +client. However, if the interaction is cancelled on the server side, +the client will still mistakenly remove/replace the item in hand. + +Examples for this are milking cows with a bucket or dyeing sheep. +The bucket is replaced with milk and the dye removed from inventory. + +Refresh the player inventory when PlayerInteractEntityEvent is +cancelled to avoid this problem. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index d322e99170b3cb6594efc824a879ab9a538ea1eb..645f7b7c862acf77d70ca0b05308945424bc4d32 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2222,6 +2222,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + + if (event.isCancelled()) { ++ this.player.refreshContainer(this.player.containerMenu); // Paper - Refresh player inventory + return; + } + // CraftBukkit end diff --git a/Remapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch b/Remapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch new file mode 100644 index 0000000000..4887c3dd7e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 19 Jul 2018 01:05:00 -0400 +Subject: [PATCH] Don't change the Entity Random seed for squids + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java +index 5a7582fd4f8e883d2f08a0227932c17d7576b957..2e5a35565b6b7c4d3f7fdab45095f789c33f8937 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java +@@ -48,7 +48,7 @@ public class Squid extends WaterAnimal { + + public Squid(EntityType type, Level world) { + super(type, world); +- this.random.setSeed((long) this.getId()); ++ //this.random.setSeed((long) this.getId()); // Paper + this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; + } + diff --git a/Remapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch b/Remapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch new file mode 100644 index 0000000000..4deb8f2bc2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 19 Jul 2018 01:08:05 -0400 +Subject: [PATCH] Re-add vanilla entity warnings for duplicates + +These are a critical sign that somethin went wrong, and you've lost some data.... + +We should kind of know about these things you know. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index ea1b15495481157912140bf5de9bf4a949c16910..914241a57c304fde220bc546261d6e959445772a 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1071,7 +1071,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (entity1 == null) { + return false; + } else { +- // WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit ++ ServerLevel.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityType.getKey(entity1.getType()), entity1.getId(), EntityType.getKey(entity.getType()), entity.getId()); // CraftBukkit // Paper + return true; + } + } diff --git a/Remapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch b/Remapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch new file mode 100644 index 0000000000..b47c9efed4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Mon, 16 Jul 2018 12:42:20 +0200 +Subject: [PATCH] Avoid item merge if stack size above max stack size + + +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index de69f7c3c0ee1e74682b0db91bdaae09175690e9..70f719ba3c68c8e9414e6b4bc68002f7c962e2b9 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -208,6 +208,10 @@ public class ItemEntity extends Entity { + + private void mergeWithNeighbours() { + if (this.isMergable()) { ++ // Paper start - avoid item merge if stack size above max stack size ++ ItemStack stack = getItem(); ++ if (stack.getCount() >= stack.getMaxStackSize()) return; ++ // Paper end + // Spigot start + double radius = level.spigotConfig.itemMerge; + List list = this.level.getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(radius, radius, radius), (entityitem) -> { diff --git a/Remapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch b/Remapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch new file mode 100644 index 0000000000..fd4a4b705a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Tue, 17 Jul 2018 16:42:17 +0200 +Subject: [PATCH] Use asynchronous Log4j 2 loggers + + +diff --git a/pom.xml b/pom.xml +index f5429f2f1979542fd93956d2f436d20d0e3a66b8..4c8a057e790c96b0ab5123549d0566371acacb46 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -88,6 +88,13 @@ + log4j-iostreams + compile + ++ ++ ++ com.lmax ++ disruptor ++ 3.4.2 ++ runtime ++ + + org.ow2.asm + asm +diff --git a/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java +new file mode 100644 +index 0000000000000000000000000000000000000000..db652a1f7abc80bc751fd94925abaec58ab1a563 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.log; ++ ++import org.apache.logging.log4j.Level; ++import org.apache.logging.log4j.core.async.AsyncQueueFullPolicy; ++import org.apache.logging.log4j.core.async.EventRoute; ++ ++public final class LogFullPolicy implements AsyncQueueFullPolicy { ++ ++ /* ++ * Prevents log calls being logged out of order when the log queue is full. ++ */ ++ ++ @Override ++ public EventRoute getRoute(final long backgroundThreadId, final Level level) { ++ return EventRoute.ENQUEUE; ++ } ++} +diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties +index 0694b21465fb9e4164e71862ff24b62241b191f2..30efeb5faf8e7faccf1b252fa0ed6a9fc31c40a7 100644 +--- a/src/main/resources/log4j2.component.properties ++++ b/src/main/resources/log4j2.component.properties +@@ -1 +1,3 @@ ++Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector ++log4j2.AsyncQueueFullPolicy="com.destroystokyo.paper.log.LogFullPolicy" + log4j.skipJansi=true diff --git a/Remapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch b/Remapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch new file mode 100644 index 0000000000..b0de783dec --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 19 Jul 2018 01:13:28 -0400 +Subject: [PATCH] add more information to Entity.toString() + +UUID, ticks lived, valid, dead + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 7e70bae5bc54ad17980789fa965fd539a7f193ea..e49fe2de6a53bdd16f0cd09b691f01f1866ffb4f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2526,7 +2526,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public String toString() { +- return String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getName().getString(), this.id, this.level == null ? "~NULL~" : this.level.toString(), this.getX(), this.getY(), this.getZ()); ++ return String.format(Locale.ROOT, "%s['%s'/%d, uuid='%s', l='%s', x=%.2f, y=%.2f, z=%.2f, cx=%d, cz=%d, tl=%d, v=%b, d=%b]", new Object[] { this.getClass().getSimpleName(), this.getName().getString(), Integer.valueOf(this.id), this.uuid.toString(), this.level == null ? "~NULL~" : this.level.toString(), Double.valueOf(this.getX()), Double.valueOf(this.getY()), Double.valueOf(this.getZ()), xChunk, zChunk, this.tickCount, this.valid, this.removed}); // Paper - add more information + } + + public boolean isInvulnerableTo(DamageSource damageSource) { diff --git a/Remapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/Remapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch new file mode 100644 index 0000000000..be88eeb2df --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch @@ -0,0 +1,131 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 21 Jul 2018 08:25:40 -0400 +Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues + +Add -Ddebug.entities=true to your JVM flags to gain more information + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 97d5437df10a6d0124e944404e88650547b7d8a8..083db6c1899b5391231b6d5d5044a334212f148c 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1145,6 +1145,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } else { + ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas()); + ++ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker + this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); + playerchunkmap_entitytracker.updatePlayers(this.level.players()); + if (entity instanceof ServerPlayer) { +@@ -1186,7 +1187,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (playerchunkmap_entitytracker1 != null) { + playerchunkmap_entitytracker1.broadcastRemoved(); + } +- ++ entity.tracker = null; // Paper - We're no longer tracked + } + + protected void tick() { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 914241a57c304fde220bc546261d6e959445772a..a5d7781b13a6d61238d026f064512f7162e1e868 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -191,6 +191,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper ++ private static Throwable getAddToWorldStackTrace(Entity entity) { ++ return new Throwable(entity + " Added to world at " + new java.util.Date()); ++ } + + @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkSource.getChunk(x, z, false); +@@ -1032,8 +1035,28 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // CraftBukkit start + private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot +- if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper ++ // Paper start ++ if (entity.valid) { ++ MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); ++ ++ if (DEBUG_ENTITIES) { ++ Throwable thr = entity.addedToWorldStack; ++ if (thr == null) { ++ MinecraftServer.LOGGER.error("Double add entity has no add stacktrace"); ++ } else { ++ MinecraftServer.LOGGER.error("Double add stacktrace: ", thr); ++ } ++ } ++ return true; ++ } ++ // Paper end + if (entity.removed) { ++ // Paper start ++ if (DEBUG_ENTITIES) { ++ new Throwable("Tried to add entity " + entity + " but it was marked as removed already").printStackTrace(); // CraftBukkit ++ getAddToWorldStackTrace(entity).printStackTrace(); ++ } ++ // Paper end + // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit + return false; + } else if (this.isUUIDUsed(entity)) { +@@ -1231,7 +1254,24 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + } + +- this.entitiesByUuid.put(entity.getUUID(), entity); ++ if (DEBUG_ENTITIES) { ++ entity.addedToWorldStack = getAddToWorldStackTrace(entity); ++ } ++ ++ Entity old = this.entitiesByUuid.put(entity.getUUID(), entity); ++ if (old != null && old.getId() != entity.getId() && old.valid) { ++ Logger logger = LogManager.getLogger(); ++ logger.error("Overwrote an existing entity " + old + " with " + entity); ++ if (DEBUG_ENTITIES) { ++ if (old.addedToWorldStack != null) { ++ old.addedToWorldStack.printStackTrace(); ++ } else { ++ logger.error("Oddly, the old entity was not added to the world in the normal way. Plugins?"); ++ } ++ entity.addedToWorldStack.printStackTrace(); ++ } ++ } ++ + this.getChunkSource().addEntity(entity); + // CraftBukkit start - SPIGOT-5278 + if (entity instanceof Drowned) { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index e49fe2de6a53bdd16f0cd09b691f01f1866ffb4f..9d8682d367522bd85894947ad2f2a53cf0aa123a 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -47,6 +47,7 @@ import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.level.TicketType; +@@ -160,6 +161,8 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper + private CraftEntity bukkitEntity; + ++ ChunkMap.TrackedEntity tracker; // Paper ++ public Throwable addedToWorldStack; // Paper - entity debug + public CraftEntity getBukkitEntity() { + if (bukkitEntity == null) { + bukkitEntity = CraftEntity.getEntity(level.getCraftServer(), this); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index b4248d46ccb1a95e21601bca1198512287edcabf..0c6c3b211b05eda8f9ab47ef0a01cc520ae28201 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -121,6 +121,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean pvpMode; + public boolean keepSpawnInMemory = true; + public org.bukkit.generator.ChunkGenerator generator; ++ public static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper + + public boolean captureBlockStates = false; + public boolean captureTreeGeneration = false; diff --git a/Remapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch b/Remapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch new file mode 100644 index 0000000000..14fc4f84c6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 01:51:27 -0500 +Subject: [PATCH] EnderDragon Events + + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java +index 0c2a5f5c4d7d7516793eba20205b5703fe1450d5..6b28cfb1e79903c43702f6e78e226dc78e3ccec2 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java +@@ -80,7 +80,11 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { + this.flame.setDuration(200); + this.flame.setParticle(ParticleTypes.DRAGON_BREATH); + this.flame.addEffect(new MobEffectInstance(MobEffects.HARM)); ++ if (new com.destroystokyo.paper.event.entity.EnderDragonFlameEvent((org.bukkit.entity.EnderDragon) this.dragon.getBukkitEntity(), (org.bukkit.entity.AreaEffectCloud) this.flame.getBukkitEntity()).callEvent()) { // Paper + this.dragon.level.addFreshEntity(this.flame); ++ } else { ++ this.removeAreaEffect(); ++ } + } + + } +@@ -91,8 +95,8 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { + ++this.flameCount; + } + +- @Override +- public void end() { ++ public final void removeAreaEffect() { this.end(); } // Paper - OBFHELPER ++ @Override public void end() { + if (this.flame != null) { + this.flame.remove(); + this.flame = null; +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java +index 01442af7b0c7340f0ece2fa0faa0f783b1b81c48..a43ef94f8a5c7a9d1581667beb4516cc26f30a0d 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java +@@ -81,7 +81,9 @@ public class DragonStrafePlayerPhase extends AbstractDragonPhaseInstance { + DragonFireball entitydragonfireball = new DragonFireball(this.dragon.level, this.dragon, d9, d10, d11); + + entitydragonfireball.moveTo(d6, d7, d8, 0.0F, 0.0F); ++ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) dragon.getBukkitEntity(), (org.bukkit.entity.DragonFireball) entitydragonfireball.getBukkitEntity()).callEvent()) // Paper + this.dragon.level.addFreshEntity(entitydragonfireball); ++ else entitydragonfireball.remove(); // Paper + this.fireballCharge = 0; + if (this.currentPath != null) { + while (!this.currentPath.isDone()) { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java +index 76dc15e07ce9ef01ad7908e289a0d695b65b2fc9..1629e409a83b11b76e1627247a838c9ebd11a648 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java +@@ -58,8 +58,10 @@ public class DragonFireball extends AbstractHurtingProjectile { + } + } + ++ if (new com.destroystokyo.paper.event.entity.EnderDragonFireballHitEvent((org.bukkit.entity.DragonFireball) this.getBukkitEntity(), list.stream().map(LivingEntity::getBukkitLivingEntity).collect(java.util.stream.Collectors.toList()), (org.bukkit.entity.AreaEffectCloud) entityareaeffectcloud.getBukkitEntity()).callEvent()) { // Paper + this.level.levelEvent(2006, this.blockPosition(), this.isSilent() ? -1 : 1); + this.level.addFreshEntity(entityareaeffectcloud); ++ } else entityareaeffectcloud.remove(); // Paper + this.remove(); + } + diff --git a/Remapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch b/Remapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch new file mode 100644 index 0000000000..be2454e01e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 01:59:59 -0500 +Subject: [PATCH] PlayerElytraBoostEvent + + +diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index dba52063d402eb2371441fa244b730a3313444fc..28cffbe299acccc59c34d5dbd2cf458704be5ee5 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -45,11 +45,16 @@ public class FireworkRocketItem extends Item { + // Paper start + final FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, itemstack, user); + entityfireworks.spawningEntity = user.getUUID(); +- world.addFreshEntity(entityfireworks); +- // Paper end +- if (!user.abilities.instabuild) { +- itemstack.shrink(1); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entityfireworks)) { ++ if (event.shouldConsume() && !user.abilities.instabuild) { ++ itemstack.shrink(1); ++ } else ((EntityPlayer) user).getBukkitEntity().updateInventory(); ++ } else if (user instanceof EntityPlayer) { ++ ((EntityPlayer) user).getBukkitEntity().updateInventory(); + } ++ // Paper end + } + + return InteractionResultHolder.sidedSuccess(user.getItemInHand(hand), world.isClientSide()); diff --git a/Remapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch b/Remapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch new file mode 100644 index 0000000000..675f0c0360 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Wed, 30 Nov 2016 20:56:58 -0600 +Subject: [PATCH] Improve BlockPosition inlining + +Normally the JVM can inline virtual getters by having two sets of code, one is the 'optimized' code and the other is the 'deoptimized' code. +If a single type is used 99% of the time, then its worth it to inline, and to revert to 'deoptimized' the 1% of the time we encounter other types. +But if two types are encountered commonly, then the JVM can't inline them both, and the call overhead remains. + +This scenario also occurs with BlockPos and MutableBlockPos. +The variables in BlockPos are final, so MutableBlockPos can't modify them. +MutableBlockPos fixes this by adding custom mutable variables, and overriding the getters to access them. + +This approach with utility methods that operate on MutableBlockPos and BlockPos. +Specific examples are BlockPosition.up(), and World.isValidLocation(). +It makes these simple methods much slower than they need to be. + +This should result in an across the board speedup in anything that accesses blocks or does logic with positions. + +This is based upon conclusions drawn from inspecting the assenmbly generated bythe JIT compiler on my microbenchmarks. +They had 'callq' (invoke) instead of 'mov' (get from memory) instructions. + +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 6a58059a05e16d96894b67a544c2f595d9546c78..c5089b0da33a68e7cadbc4841b07f9d772d224a0 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -88,6 +88,7 @@ public class BlockPos extends Vec3i { + return asLong(this.getX(), this.getY(), this.getZ()); + } + ++ public static long asLong(int x, int y, int z) { return asLong(x, y, z); } // Paper - OBFHELPER + public static long asLong(int x, int y, int z) { + long l = 0L; + +diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java +index c22de593be404c4e921724bba6a69c13759a95fd..fc4e652ada7b228cb99a3c8fb372ae9af5ddfba4 100644 +--- a/src/main/java/net/minecraft/core/Vec3i.java ++++ b/src/main/java/net/minecraft/core/Vec3i.java +@@ -41,7 +41,7 @@ public class Vec3i implements Comparable { + this(Mth.floor(x), Mth.floor(y), Mth.floor(z)); + } + +- public boolean equals(Object object) { ++ public final boolean equals(Object object) { // Paper + if (this == object) { + return true; + } else if (!(object instanceof Vec3i)) { +@@ -53,7 +53,7 @@ public class Vec3i implements Comparable { + } + } + +- public int hashCode() { ++ public final int hashCode() { // Paper + return (this.getY() + this.getZ() * 31) * 31 + this.getX(); + } + +@@ -61,15 +61,15 @@ public class Vec3i implements Comparable { + return this.getY() == baseblockposition.getY() ? (this.getZ() == baseblockposition.getZ() ? this.getX() - baseblockposition.getX() : this.getZ() - baseblockposition.getZ()) : this.getY() - baseblockposition.getY(); + } + +- public int getX() { ++ public final int getX() { // Paper + return this.x; + } + +- public int getY() { ++ public final int getY() { // Paper + return this.y; + } + +- public int getZ() { ++ public final int getZ() { // Paper + return this.z; + } + diff --git a/Remapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch b/Remapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch new file mode 100644 index 0000000000..e8d895a808 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Mon, 23 Jul 2018 13:08:19 -0400 +Subject: [PATCH] Optimize RegistryID.c() + +This is a frequent hotspot for world loading/saving. + +diff --git a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java +index 66ad412e4368a8615cc66a97ac442c572813a3dd..fa4a2d29b3b4c20d7396e973801d69c4acadddda 100644 +--- a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java ++++ b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java +@@ -15,12 +15,14 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + private K[] byId; + private int nextId; + private int size; ++ private java.util.BitSet usedIds; // Paper + + public CrudeIncrementalIntIdentityHashBiMap(int size) { + size = (int) ((float) size / 0.8F); + this.keys = (K[]) (new Object[size]); // Paper - decompile fix + this.values = new int[size]; + this.byId = (K[]) (new Object[size]); // Paper - decompile fix ++ this.usedIds = new java.util.BitSet(); // Paper + } + + // Paper start - decompile fix +@@ -52,9 +54,14 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + } + + private int nextId() { +- while (this.nextId < this.byId.length && this.byId[this.nextId] != null) { +- ++this.nextId; ++ // Paper start ++ /* ++ while (this.e < this.d.length && this.d[this.e] != null) { ++ ++this.e; + } ++ */ ++ this.nextId = this.usedIds.nextClearBit(0); ++ // Paper end + + return this.nextId; + } +@@ -68,6 +75,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + this.byId = (K[]) (new Object[newSize]); // Paper - decompile fix + this.nextId = 0; + this.size = 0; ++ this.usedIds.clear(); // Paper + + for (int j = 0; j < ak.length; ++j) { + if (ak[j] != null) { +@@ -93,6 +101,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + this.keys[k] = value; + this.values[k] = id; + this.byId[id] = value; ++ this.usedIds.set(id); // Paper + ++this.size; + if (id == this.nextId) { + ++this.nextId; +@@ -157,6 +166,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + Arrays.fill(this.byId, (Object) null); + this.nextId = 0; + this.size = 0; ++ this.usedIds.clear(); // Paper + } + + public int size() { diff --git a/Remapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/Remapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch new file mode 100644 index 0000000000..f39334e396 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Mon, 23 Jul 2018 12:57:39 +0200 +Subject: [PATCH] Option to prevent armor stands from doing entity lookups + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4813f62d1e382d5ac6971b2244df3f13c80d1950..3562950df4868b1393790b1a1ff1fe0dc589c155 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -379,4 +379,9 @@ public class PaperWorldConfig { + private void scanForLegacyEnderDragon() { + scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); + } ++ ++ public boolean armorStandEntityLookups = true; ++ private void armorStandEntityLookups() { ++ armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 59239e202e8e99870ce3be515d2f040ad9786892..7fc69adc8afa971ee3cf815c6002628ae2149a5b 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -352,6 +352,7 @@ public class ArmorStand extends LivingEntity { + + @Override + protected void pushEntities() { ++ if (!level.paperConfig.armorStandEntityLookups) return; // Paper + List list = this.level.getEntities(this, this.getBoundingBox(), ArmorStand.RIDABLE_MINECARTS); + + for (int i = 0; i < list.size(); ++i) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0c6c3b211b05eda8f9ab47ef0a01cc520ae28201..7b135a3951bc168ccebdbb4e3acdc07397a820d3 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -39,6 +39,7 @@ import net.minecraft.world.DifficultyInstance; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.decoration.ArmorStand; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +@@ -854,6 +855,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Paper end + } + } ++ // Paper start - Prevent armor stands from doing entity lookups ++ @Override ++ public boolean noCollision(@Nullable Entity entity, AABB box) { ++ if (entity instanceof ArmorStand && !entity.level.paperConfig.armorStandEntityLookups) return false; ++ return LevelAccessor.super.noCollision(entity, box); ++ } ++ // Paper end + + public Explosion explode(@Nullable Entity entity, double x, double y, double z, float power, Explosion.BlockInteraction destructionType) { + return this.explode(entity, (DamageSource) null, (ExplosionDamageCalculator) null, x, y, z, power, false, destructionType); diff --git a/Remapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch b/Remapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch new file mode 100644 index 0000000000..f0b596c503 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch @@ -0,0 +1,194 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Mon, 23 Jul 2018 14:22:26 +0200 +Subject: [PATCH] Vanished players don't have rights + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 9d8682d367522bd85894947ad2f2a53cf0aa123a..a2cc3e58d59ed3d9f443b77c44d8200cc09b4da9 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -183,7 +183,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + private static double viewScale = 1.0D; + private final EntityType type; + private int id; +- public boolean blocksBuilding; ++ public boolean blocksBuilding; public final boolean blocksEntitySpawning() { return this.blocksBuilding; } // Paper - OBFHELPER + public final List passengers; + protected int boardingCooldown; + @Nullable +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index 16b554675a276471851846d4f2bea06fdcc166d9..d1dd173c11d751b15c3afd4309e386931fd9cf8d 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -5,6 +5,7 @@ import java.util.UUID; + import javax.annotation.Nullable; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -157,8 +158,14 @@ public abstract class Projectile extends Entity { + protected boolean canHitEntity(Entity entity) { + if (!entity.isSpectator() && entity.isAlive() && entity.isPickable()) { + Entity entity1 = this.getOwner(); +- ++ // Paper start - Cancel hit for vanished players ++ if (entity1 instanceof ServerPlayer && entity instanceof ServerPlayer) { ++ org.bukkit.entity.Player collided = (org.bukkit.entity.Player) entity.getBukkitEntity(); ++ org.bukkit.entity.Player shooter = (org.bukkit.entity.Player) entity1.getBukkitEntity(); ++ if (!shooter.canSee(collided)) return false; ++ } + return entity1 == null || this.leftOwner || !entity1.isPassengerOfSameVehicle(entity); ++ // Paper end + } else { + return false; + } +diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java +index 1ba89fa106dc24abf68d5d13c39a8d80f5582f1f..59522e367327224e5fe0fe2307858077ed812ba6 100644 +--- a/src/main/java/net/minecraft/world/item/BlockItem.java ++++ b/src/main/java/net/minecraft/world/item/BlockItem.java +@@ -174,7 +174,8 @@ public class BlockItem extends Item { + Player entityhuman = context.getPlayer(); + CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of((Entity) entityhuman); + // CraftBukkit start - store default return +- boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision); ++ Level world = context.getLevel(); // Paper ++ boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && world.checkEntityCollision(state, entityhuman, voxelshapecollision, context.getClickedPos(), true); // Paper + org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; + + BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 7b135a3951bc168ccebdbb4e3acdc07397a820d3..7a9ccd203885b9b369767d1fb8c53783201d0f0f 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -30,6 +30,7 @@ import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.TagContainer; +@@ -69,6 +70,10 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + import net.minecraft.world.level.storage.LevelData; + import net.minecraft.world.level.storage.WritableLevelData; + import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.shapes.BooleanOp; ++import net.minecraft.world.phys.shapes.CollisionContext; ++import net.minecraft.world.phys.shapes.Shapes; ++import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.scores.Scoreboard; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -232,6 +237,46 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + } + ++ // Paper start ++ // ret true if no collision ++ public final boolean checkEntityCollision(BlockState data, Entity source, CollisionContext voxelshapedcollision, ++ BlockPos position, boolean checkCanSee) { ++ // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape) ++ VoxelShape voxelshape = data.getCollisionShape(this, position, voxelshapedcollision); ++ if (voxelshape.isEmpty()) { ++ return true; ++ } ++ ++ voxelshape = voxelshape.offset((double) position.getX(), (double) position.getY(), (double) position.getZ()); ++ if (voxelshape.isEmpty()) { ++ return true; ++ } ++ ++ List entities = this.getEntities(null, voxelshape.bounds()); ++ for (int i = 0, len = entities.size(); i < len; ++i) { ++ Entity entity = entities.get(i); ++ ++ if (checkCanSee && source instanceof ServerPlayer && entity instanceof ServerPlayer ++ && !((ServerPlayer) source).getBukkitEntity().canSee(((ServerPlayer) entity).getBukkitEntity())) { ++ continue; ++ } ++ ++ // !entity1.dead && entity1.i && (entity == null || !entity1.x(entity)); ++ // elide the last check since vanilla calls with entity = null ++ // only we care about the source for the canSee check ++ if (entity.removed || !entity.blocksEntitySpawning()) { ++ continue; ++ } ++ ++ if (Shapes.applyOperation(voxelshape, Shapes.of(entity.getBoundingBox()), BooleanOp.AND)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ // Paper end ++ + @Override + public boolean isClientSide() { + return this.isClientSide; +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index e6928557a79f51302975f2832ec911c2692eaaeb..5d7794c9533bd37193f196bda616adaaace2bbde 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -504,6 +504,7 @@ public abstract class BlockBehaviour { + return this.cache != null ? this.cache.collisionShape : this.getCollisionShape(world, pos, CollisionContext.empty()); + } + ++ public final VoxelShape getCollisionShape(BlockGetter iblockaccess, BlockPos blockposition, CollisionContext voxelshapecollision) { return this.getCollisionShape(iblockaccess, blockposition, voxelshapecollision); } // Paper - OBFHELPER + public VoxelShape getCollisionShape(BlockGetter world, BlockPos pos, CollisionContext context) { + return this.getBlock().getCollisionShape(this.asState(), world, pos, context); + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index 2371b52b450e2b43fa9b9549a91f853c702a9dc0..fa2942d0b0424390daee2121f8959034c5352e0b 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -45,6 +45,7 @@ public final class Shapes { + return create(new AABB(xMin, yMin, zMin, xMax, yMax, zMax)); + } + ++ public static final VoxelShape of(AABB axisAlignedbb) { return Shapes.create(axisAlignedbb); } // Paper - OBFHELPER + public static VoxelShape create(AABB box) { + int i = findBits(box.minX, box.maxX); + int j = findBits(box.minY, box.maxY); +@@ -139,6 +140,7 @@ public final class Shapes { + } + } + ++ public static final boolean applyOperation(VoxelShape voxelshape, VoxelShape voxelshape1, BooleanOp operatorboolean) { return Shapes.joinIsNotEmpty(voxelshape, voxelshape1, operatorboolean); } // Paper - OBFHELPER + public static boolean joinIsNotEmpty(VoxelShape shape1, VoxelShape shape2, BooleanOp predicate) { + if (predicate.apply(false, false)) { + throw (IllegalArgumentException) Util.pauseInIde((Throwable) (new IllegalArgumentException())); +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +index 026759567c58b5e7687ed1eec26fb4ffc60f9fa7..67ecdaada9f87304a9ae83d7917c7aca4676d195 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +@@ -54,6 +54,7 @@ public abstract class VoxelShape { + return this.shape.isEmpty(); + } + ++ public final VoxelShape offset(double x, double y, double z) { return this.move(x, y, z); } // Paper - OBFHELPER + public VoxelShape move(double x, double y, double z) { + return (VoxelShape) (this.isEmpty() ? Shapes.empty() : new ArrayVoxelShape(this.shape, new OffsetDoubleList(this.getCoords(Direction.Axis.X), x), new OffsetDoubleList(this.getCoords(Direction.Axis.Y), y), new OffsetDoubleList(this.getCoords(Direction.Axis.Z), z))); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index c2f58b95db41b2205fbf2728c6a99419c6a63dfa..4cd08821305590e21a01cc4dda05370c2b721ac2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1211,6 +1211,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); ++ ++ if (projectile.getShooter() instanceof Player && collided instanceof Player) { ++ if (!((Player) projectile.getShooter()).canSee((Player) collided)) { ++ event.setCancelled(true); ++ return event; ++ } ++ } ++ + Bukkit.getPluginManager().callEvent(event); + return event; + } diff --git a/Remapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch b/Remapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch new file mode 100644 index 0000000000..a8a2ab7437 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 23 Jul 2018 22:18:31 -0400 +Subject: [PATCH] Mark chunk dirty anytime entities change to guarantee it + saves + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index d69ccb1f31f31ebeee477df20ce1410f9e485eb7..bd9b19d988ecf72e099efeff6ec3483a352174ec 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -559,6 +559,7 @@ public class LevelChunk implements ChunkAccess { + entity.zChunk = this.chunkPos.z; + this.entities.add(entity); // Paper - per chunk entity list + this.entitySlices[k].add(entity); ++ this.markUnsaved(); // Paper + } + + @Override +@@ -587,6 +588,7 @@ public class LevelChunk implements ChunkAccess { + return; + } + entityCounts.decrement(entity.getMinecraftKeyString()); ++ this.markUnsaved(); // Paper + // Paper end + this.entities.remove(entity); // Paper + } diff --git a/Remapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch b/Remapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch new file mode 100644 index 0000000000..1978f629cd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 23 Jul 2018 22:44:23 -0400 +Subject: [PATCH] Add some Debug to Chunk Entity slices + +If we detect unexpected state, log and try to recover + +This should hopefully avoid duplicate entities ever being created +if the entity was to end up in 2 different chunk slices + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a2cc3e58d59ed3d9f443b77c44d8200cc09b4da9..7847078c54154e28ab066ea8a329f929df1e1a37 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -156,6 +156,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + } + }; ++ public List entitySlice = null; + // Paper end + + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index bd9b19d988ecf72e099efeff6ec3483a352174ec..09aa608bd303b618ae2c0ebd237bcbdba60a37a8 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -26,7 +26,9 @@ import net.minecraft.ReportedException; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; +@@ -550,6 +552,25 @@ public class LevelChunk implements ChunkAccess { + if (k >= this.entitySlices.length) { + k = this.entitySlices.length - 1; + } ++ // Paper - remove from any old list if its in one ++ List nextSlice = this.entitySlices[k]; // the next list to be added to ++ List currentSlice = entity.entitySlice; ++ if (nextSlice == currentSlice) { ++ if (Level.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity was already in this chunk!" + entity, new Throwable()); ++ return; // ??? silly plugins ++ } ++ if (currentSlice != null && currentSlice.contains(entity)) { ++ // Still in an old chunk... ++ if (Level.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity is still in another chunk!" + entity, new Throwable()); ++ LevelChunk chunk = entity.getCurrentChunk(); ++ if (chunk != null) { ++ chunk.removeEntity(entity); ++ } else { ++ removeEntity(entity); ++ } ++ currentSlice.remove(entity); // Just incase the above did not remove from the previous slice ++ } ++ // Paper end + + if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper + entity.inChunk = true; +@@ -559,6 +580,7 @@ public class LevelChunk implements ChunkAccess { + entity.zChunk = this.chunkPos.z; + this.entities.add(entity); // Paper - per chunk entity list + this.entitySlices[k].add(entity); ++ entity.entitySlice = this.entitySlices[k]; // Paper + this.markUnsaved(); // Paper + } + +@@ -584,6 +606,10 @@ public class LevelChunk implements ChunkAccess { + + // Paper start + if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); ++ if (entitySlices[section] == entity.entitySlice) { ++ entity.entitySlice = null; ++ entity.inChunk = false; ++ } + if (!this.entitySlices[section].remove(entity)) { + return; + } +@@ -742,7 +768,7 @@ public class LevelChunk implements ChunkAccess { + // Paper start - neighbour cache + int chunkX = this.chunkPos.x; + int chunkZ = this.chunkPos.z; +- ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); ++ ServerChunkCache chunkProvider = ((ServerLevel)this.world).getChunkSource(); + for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { + for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { + LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); +@@ -802,7 +828,7 @@ public class LevelChunk implements ChunkAccess { + // Paper start - neighbour cache + int chunkX = this.chunkPos.x; + int chunkZ = this.chunkPos.z; +- ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); ++ ServerChunkCache chunkProvider = ((ServerLevel)this.world).getChunkSource(); + for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { + for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { + LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); diff --git a/Remapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch b/Remapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch new file mode 100644 index 0000000000..6599e06859 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch @@ -0,0 +1,152 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 27 Jul 2018 22:36:31 -0500 +Subject: [PATCH] SkeletonHorse Additions + + +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index a3bad391a719363077740aa810c9412df34b4ae5..e92a8c4c49c452e1f3f0c06398f2a74e3432262f 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -25,6 +25,7 @@ public final class EntitySelector { + public static final Predicate ATTACK_ALLOWED = (entity) -> { + return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative() && entity.level.getDifficulty() != Difficulty.PEACEFUL; + }; ++ public static Predicate notSpectator() { return NO_SPECTATORS; } // Paper - OBFHELPER + public static final Predicate NO_SPECTATORS = (entity) -> { + return !entity.isSpectator(); + }; +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java +index 7ef99acaa24525c68b1528bd3232738baab8e1c6..eaab482ae341ddda0754e726357cd845121fb043 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java +@@ -26,7 +26,7 @@ public class SkeletonHorse extends AbstractHorse { + + private final SkeletonTrapGoal skeletonTrapGoal = new SkeletonTrapGoal(this); + private boolean isTrap; +- private int trapTime; ++ private int trapTime; public int getTrapTime() { return this.trapTime; } // Paper - OBFHELPER + + public SkeletonHorse(EntityType type, Level world) { + super(type, world); +@@ -145,10 +145,12 @@ public class SkeletonHorse extends AbstractHorse { + return 0.96F; + } + ++ public boolean isTrap() { return this.isTrap(); } // Paper - OBFHELPER + public boolean isTrap() { + return this.isTrap; + } + ++ public void setTrap(boolean trap) { this.setTrap(trap); } // Paper - OBFHELPER + public void setTrap(boolean trapped) { + if (trapped != this.isTrap) { + this.isTrap = trapped; +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java +index 6c2cbaae2afe076c8b7bc53ffa91fe37e423d120..7f5fb28a7deabe1b62ed21e5ed1ea1ecca0d15b8 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java +@@ -14,10 +14,14 @@ import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.level.Level; ++import org.bukkit.entity.HumanEntity; ++ ++import java.util.List; + + public class SkeletonTrapGoal extends Goal { + + private final SkeletonHorse horse; ++ private List eligiblePlayers; // Paper + + public SkeletonTrapGoal(SkeletonHorse skeletonHorse) { + this.horse = skeletonHorse; +@@ -25,12 +29,13 @@ public class SkeletonTrapGoal extends Goal { + + @Override + public boolean canUse() { +- return this.horse.level.hasNearbyAlivePlayer(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D); ++ return !(eligiblePlayers = this.horse.level.findNearbyBukkitPlayers(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D, false)).isEmpty(); // Paper + } + + @Override + public void tick() { + ServerLevel worldserver = (ServerLevel) this.horse.level; ++ if (!new com.destroystokyo.paper.event.entity.SkeletonHorseTrapEvent((org.bukkit.entity.SkeletonHorse) this.horse.getBukkitEntity(), eligiblePlayers).callEvent()) return; // Paper + DifficultyInstance difficultydamagescaler = worldserver.getCurrentDifficultyAt(this.horse.blockPosition()); + + this.horse.setTrap(false); +diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java +index 66681b9f0e2531d3da25629e44180417b32b4d66..6a5430fe54a5c8ad119a0f3842961825a54d8d7a 100644 +--- a/src/main/java/net/minecraft/world/level/EntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/EntityGetter.java +@@ -1,6 +1,9 @@ + package net.minecraft.world.level; + ++import com.google.common.collect.ImmutableList; + import com.google.common.collect.Lists; ++import org.bukkit.entity.HumanEntity; ++ + import java.util.Iterator; + import java.util.List; + import java.util.UUID; +@@ -115,6 +118,28 @@ public interface EntityGetter { + return entityhuman; + } + ++ // Paper start ++ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, boolean notSpectator) { ++ return findNearbyBukkitPlayers(x, y, z, radius, notSpectator ? EntitySelector.notSpectator() : EntitySelector.canAITarget()); ++ } ++ ++ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate predicate) { ++ ImmutableList.Builder builder = ImmutableList.builder(); ++ ++ for (Player human : this.players()) { ++ if (predicate == null || predicate.test(human)) { ++ double distanceSquared = human.getDistanceSquared(x, y, z); ++ ++ if (radius < 0.0D || distanceSquared < radius * radius) { ++ builder.add(human.getBukkitEntity()); ++ } ++ } ++ } ++ ++ return builder.build(); ++ } ++ // Paper end ++ + @Nullable + default Player getNearestPlayer(Entity entity, double maxDistance) { + return this.getNearestPlayer(entity.getX(), entity.getY(), entity.getZ(), maxDistance, false); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java +index b52ca4a612e30542ef4029cb1340f616bc4c36e6..7f984639fc2697cad9d0393467b0cb896d1e55a4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java +@@ -25,4 +25,26 @@ public class CraftSkeletonHorse extends CraftAbstractHorse implements SkeletonHo + public Variant getVariant() { + return Variant.SKELETON_HORSE; + } ++ ++ // Paper start ++ @Override ++ public net.minecraft.world.entity.animal.horse.SkeletonHorse getHandle() { ++ return (net.minecraft.world.entity.animal.horse.SkeletonHorse) super.getHandle(); ++ } ++ ++ @Override ++ public int getTrapTime() { ++ return getHandle().getTrapTime(); ++ } ++ ++ @Override ++ public boolean isTrap() { ++ return getHandle().isTrap(); ++ } ++ ++ @Override ++ public void setTrap(boolean trap) { ++ getHandle().setTrap(trap); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch b/Remapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch new file mode 100644 index 0000000000..946c608327 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 26 Jul 2018 00:11:12 -0400 +Subject: [PATCH] Prevent Saving Bad entities to chunks + +See https://github.com/PaperMC/Paper/issues/1223 + +Minecraft is saving invalid entities to the chunk files. + +Avoid saving bad data, and also make improvements to handle +loading these chunks. Any invalid entity will be instant killed, +so lets avoid adding it to the world... + +This lets us be safer about the dupe UUID resolver too, as now +we can ignore instant killed entities and avoid risk of duplicating +an invalid entity. + +This should reduce log occurrences of dupe uuid messages. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index a5d7781b13a6d61238d026f064512f7162e1e868..8e8e5f30c512ed7d8ee987550c22d3e9df845043 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1151,6 +1151,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + List[] aentityslice = chunk.getEntitySlices(); // Spigot + int i = aentityslice.length; + ++ java.util.List toMoveChunks = new java.util.ArrayList<>(); // Paper + for (int j = 0; j < i; ++j) { + List entityslice = aentityslice[j]; // Spigot + Iterator iterator = entityslice.iterator(); +@@ -1163,11 +1164,25 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + throw (IllegalStateException) Util.pauseInIde((Throwable) (new IllegalStateException("Removing entity while ticking!"))); + } + ++ // Paper start - move out entities that shouldn't be in this chunk before it unloads ++ if (!entity.removed && (int) Math.floor(entity.getX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk.getPos().z) { ++ toMoveChunks.add(entity); ++ continue; ++ } ++ // Paper end ++ + this.entitiesById.remove(entity.getId()); + this.onEntityRemoved(entity); ++ ++ if (entity.removed) iterator.remove(); // Paper - don't save dead entities during unload + } + } + } ++ // Paper start - move out entities that shouldn't be in this chunk before it unloads ++ for (Entity entity : toMoveChunks) { ++ this.updateChunkPos(entity); ++ } ++ // Paper end + + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 0efaf4d0f58bcf38b427e76bf09b96e354294159..542d6f322df5f44ad9f504c8e14c88e3fa540657 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -27,6 +27,7 @@ import net.minecraft.nbt.LongArrayTag; + import net.minecraft.nbt.ShortTag; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.level.ThreadedLevelLightEngine; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -349,6 +350,7 @@ public class ChunkSerializer { + nbttagcompound1.put("TileEntities", nbttaglist1); + ListTag nbttaglist2 = new ListTag(); + ++ java.util.List toUpdate = new java.util.ArrayList<>(); // Paper + if (chunk.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { + LevelChunk chunk1 = (LevelChunk) chunk; + +@@ -366,13 +368,28 @@ public class ChunkSerializer { + while (iterator1.hasNext()) { + Entity entity = (Entity) iterator1.next(); + CompoundTag nbttagcompound4 = new CompoundTag(); +- ++ // Paper start ++ if ((int) Math.floor(entity.getX()) >> 4 != chunk1.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk1.getPos().z) { ++ toUpdate.add(entity); ++ continue; ++ } ++ if (entity.removed || hasPlayerPassenger(entity)) { ++ continue; ++ } ++ // Paper end + if (entity.save(nbttagcompound4)) { + chunk1.setLastSaveHadEntities(true); + nbttaglist2.add(nbttagcompound4); + } + } + } ++ ++ // Paper start - move entities to the correct chunk ++ for (Entity entity : toUpdate) { ++ world.updateChunkPos(entity); ++ } ++ // Paper end ++ + } else { + ProtoChunk protochunk = (ProtoChunk) chunk; + +@@ -431,6 +448,19 @@ public class ChunkSerializer { + nbttagcompound1.put("Structures", packStructureData(chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences())); + return nbttagcompound; + } ++ // Paper start - this is saved with the player ++ private static boolean hasPlayerPassenger(Entity entity) { ++ for (Entity passenger : entity.passengers) { ++ if (passenger instanceof ServerPlayer) { ++ return true; ++ } ++ if (hasPlayerPassenger(passenger)) { ++ return true; ++ } ++ } ++ return false; ++ } ++ // Paper end + + public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag tag) { + if (tag != null) { diff --git a/Remapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch b/Remapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch new file mode 100644 index 0000000000..0133184a69 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Thu, 26 Jul 2018 14:10:23 +0200 +Subject: [PATCH] Don't call getItemMeta on hasItemMeta + +Spigot 1.13 checks if any field (which are manually copied from the ItemStack's "tag" NBT tag) on the ItemMeta class of an ItemStack is set. + +We could just check if the "tag" NBT tag is empty, albeit that would break some plugins. The only general tag added on 1.13 is "Damage", and we can just check if the "tag" NBT tag contains any other tag that's not "Damage" (https://minecraft.gamepedia.com/Player.dat_format#Item_structure) making the `hasItemStack` method behave as before. + +Returns true if getDamage() == 0 or has damage tag or other tag is set. +Check the `ItemMetaTest#testTaggedButNotMeta` method to see how this method behaves. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index 44caf00330e4f4f74745973dbe709980f0b61269..9e06912b0c13c3d61bc95e526acaa28f96b46fb9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -569,7 +569,7 @@ public final class CraftItemStack extends ItemStack { + + @Override + public boolean hasItemMeta() { +- return hasItemMeta(handle) && !CraftItemFactory.instance().equals(getItemMeta(), null); ++ return hasItemMeta(handle) && (handle.getDamageValue() != 0 || (handle.getTag() != null && handle.getTag().tags.size() >= (handle.getTag().contains(CraftMetaItem.DAMAGE.NBT) ? 2 : 1))); // Paper - keep 1.12 CraftBukkit behavior without calling getItemMeta + } + + static boolean hasItemMeta(net.minecraft.world.item.ItemStack item) { +diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +index 42f577ed3508ba5a380648461e149f16ce97c9bd..b85a0a4c4f134dd6012d9141244ecf97b4300b65 100644 +--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java ++++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +@@ -96,6 +96,34 @@ public class ItemMetaTest extends AbstractTestingBase { + assertThat(itemMeta.hasConflictingEnchant(null), is(false)); + } + ++ // Paper start ++ private void testItemMeta(ItemStack stack) { ++ assertThat("Should not have ItemMeta", stack.hasItemMeta(), is(false)); ++ ++ stack.setDurability((short) 0); ++ assertThat("ItemStack with zero durability should not have ItemMeta", stack.hasItemMeta(), is(false)); ++ ++ stack.setDurability((short) 2); ++ assertThat("ItemStack with non-zero durability should have ItemMeta", stack.hasItemMeta(), is(true)); ++ ++ stack.setLore(java.util.Collections.singletonList("Lore")); ++ assertThat("ItemStack with lore and durability should have ItemMeta", stack.hasItemMeta(), is(true)); ++ ++ stack.setDurability((short) 0); ++ assertThat("ItemStack with lore should have ItemMeta", stack.hasItemMeta(), is(true)); ++ ++ stack.setLore(null); ++ } ++ ++ @Test ++ public void testHasItemMeta() { ++ ItemStack itemStack = new ItemStack(Material.SHEARS); ++ ++ testItemMeta(itemStack); ++ testItemMeta(CraftItemStack.asCraftCopy(itemStack)); ++ } ++ // Paper end ++ + @Test + public void testConflictingStoredEnchantment() { + EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) Bukkit.getItemFactory().getItemMeta(Material.ENCHANTED_BOOK); diff --git a/Remapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch b/Remapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch new file mode 100644 index 0000000000..ae6ea8935e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 28 Jul 2018 12:18:27 -0400 +Subject: [PATCH] Ignore Dead Entities in entityList iteration + +A spigot change delays removal of entities from the entity list. +This causes a change in behavior from Vanilla where getEntities type +methods will return dead entities that they shouldn't otherwise be doing. + +This will ensure that dead entities are skipped from iteration since +they shouldn't of been in the list in the first place. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index e95b91cefb0374bd5bb57cc090f5ecd566d7a618..8fd716bf2e1402694798b8be03fd85821153be44 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -209,6 +209,7 @@ public class PaperCommand extends Command { + Collection entities = world.entitiesById.values(); + entities.forEach(e -> { + ResourceLocation key = e.getMinecraftKey(); ++ if (e.shouldBeRemoved) return; // Paper + + MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); + ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 8e8e5f30c512ed7d8ee987550c22d3e9df845043..84b2cd661697545186677ab7966556d9288c650b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1303,6 +1303,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + entity.origin = entity.getBukkitEntity().getLocation(); + } + // Paper end ++ entity.shouldBeRemoved = false; // Paper - shouldn't be removed after being re-added + new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + } + +@@ -1315,6 +1316,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.removeFromChunk(entity); + this.entitiesById.remove(entity.getId()); + this.onEntityRemoved(entity); ++ entity.shouldBeRemoved = true; // Paper + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 7847078c54154e28ab066ea8a329f929df1e1a37..5bf6bc6a01ccde8a4d67b49293bb326cb09248d8 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -275,6 +275,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end ++ public boolean shouldBeRemoved; // Paper + + public float getBukkitYaw() { + return this.yRot; +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 09aa608bd303b618ae2c0ebd237bcbdba60a37a8..db28bfe95c885cdefa855c7aaa3bcf92bc52df26 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -862,6 +862,7 @@ public class LevelChunk implements ChunkAccess { + + for (int i1 = 0; i1 < l; ++i1) { + Entity entity1 = (Entity) list1.get(i1); ++ if (entity1.shouldBeRemoved) continue; // Paper + + if (entity1.getBoundingBox().intersects(box) && entity1 != except) { + if (predicate == null || predicate.test(entity1)) { +@@ -899,6 +900,7 @@ public class LevelChunk implements ChunkAccess { + + while (iterator.hasNext()) { + T entity = (T) iterator.next(); // CraftBukkit - decompile error ++ if (entity.shouldBeRemoved) continue; // Paper + + if ((type == null || entity.getType() == type) && entity.getBoundingBox().intersects(box) && predicate.test(entity)) { + result.add(entity); +@@ -921,6 +923,7 @@ public class LevelChunk implements ChunkAccess { + + while (iterator.hasNext()) { + T t0 = (T) iterator.next(); // CraftBukkit - decompile error ++ if (t0.shouldBeRemoved) continue; // Paper + + if (entityClass.isInstance(t0) && t0.getBoundingBox().intersects(box) && (predicate == null || predicate.test(t0))) { // Spigot - instance check + result.add(t0); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 3a3466cd9bbd34dbc0b79567f5579e84a81d6009..9807612aed6c4393cbe1f4b6078e45bf1ba3deb2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1022,6 +1022,7 @@ public class CraftWorld implements World { + for (Object o : world.entitiesById.values()) { + if (o instanceof net.minecraft.world.entity.Entity) { + net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; ++ if (mcEnt.shouldBeRemoved) continue; // Paper + Entity bukkitEntity = mcEnt.getBukkitEntity(); + + // Assuming that bukkitEntity isn't null +@@ -1041,6 +1042,7 @@ public class CraftWorld implements World { + for (Object o : world.entitiesById.values()) { + if (o instanceof net.minecraft.world.entity.Entity) { + net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; ++ if (mcEnt.shouldBeRemoved) continue; // Paper + Entity bukkitEntity = mcEnt.getBukkitEntity(); + + // Assuming that bukkitEntity isn't null +@@ -1067,6 +1069,7 @@ public class CraftWorld implements World { + + for (Object entity: world.entitiesById.values()) { + if (entity instanceof net.minecraft.world.entity.Entity) { ++ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper + Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); + + if (bukkitEntity == null) { +@@ -1090,6 +1093,7 @@ public class CraftWorld implements World { + + for (Object entity: world.entitiesById.values()) { + if (entity instanceof net.minecraft.world.entity.Entity) { ++ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper + Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); + + if (bukkitEntity == null) { diff --git a/Remapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch b/Remapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch new file mode 100644 index 0000000000..4909987c8f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch @@ -0,0 +1,104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: willies952002 +Date: Thu, 26 Jul 2018 02:25:46 -0400 +Subject: [PATCH] Implement Expanded ArmorStand API + +Add the following: +- Add proper methods for getting and setting items in both hands. Deprecates old methods +- Enable/Disable slot interactions + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 7fc69adc8afa971ee3cf815c6002628ae2149a5b..06e52a0c5decf717e35c605d6bcb46c3c7b29656 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -426,6 +426,7 @@ public class ArmorStand extends LivingEntity { + return enumitemslot; + } + ++ public final boolean isSlotDisabled(net.minecraft.world.entity.EquipmentSlot slot) { return this.isDisabled(slot); } // Paper - OBFHELPER + private boolean isDisabled(net.minecraft.world.entity.EquipmentSlot slot) { + return (this.disabledSlots & 1 << slot.getFilterFlag()) != 0 || slot.getType() == net.minecraft.world.entity.EquipmentSlot.Type.HAND && !this.isShowArms(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +index 16f996d505b96da8a40c7709214ebbd2a0d0d9f3..d4da5214a39b718671dcaf687cb0ff8668ce9728 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +@@ -238,5 +238,78 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public void setCanMove(boolean move) { + getHandle().canMove = move; + } ++ ++ @Override ++ public ItemStack getItem(org.bukkit.inventory.EquipmentSlot slot) { ++ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); ++ return getHandle().getItemBySlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)).asBukkitMirror(); ++ } ++ ++ @Override ++ public void setItem(org.bukkit.inventory.EquipmentSlot slot, ItemStack item) { ++ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); ++ switch (slot) { ++ case HAND: ++ getEquipment().setItemInMainHand(item); ++ return; ++ case OFF_HAND: ++ getEquipment().setItemInOffHand(item); ++ return; ++ case FEET: ++ setBoots(item); ++ return; ++ case LEGS: ++ setLeggings(item); ++ return; ++ case CHEST: ++ setChestplate(item); ++ return; ++ case HEAD: ++ setHelmet(item); ++ return; ++ } ++ throw new UnsupportedOperationException(slot.name()); ++ } ++ ++ @Override ++ public java.util.Set getDisabledSlots() { ++ java.util.Set disabled = new java.util.HashSet<>(); ++ for (org.bukkit.inventory.EquipmentSlot slot : org.bukkit.inventory.EquipmentSlot.values()) { ++ if (this.isSlotDisabled(slot)) { ++ disabled.add(slot); ++ } ++ } ++ return disabled; ++ } ++ ++ @Override ++ public void setDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { ++ int disabled = 0; ++ for (org.bukkit.inventory.EquipmentSlot slot : slots) { ++ if (slot == org.bukkit.inventory.EquipmentSlot.OFF_HAND) continue; ++ net.minecraft.world.entity.EquipmentSlot nmsSlot = org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot); ++ disabled += (1 << nmsSlot.getFilterFlag()) + (1 << (nmsSlot.getFilterFlag() + 8)) + (1 << (nmsSlot.getFilterFlag() + 16)); ++ } ++ getHandle().disabledSlots = disabled; ++ } ++ ++ @Override ++ public void addDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { ++ java.util.Set disabled = getDisabledSlots(); ++ java.util.Collections.addAll(disabled, slots); ++ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); ++ } ++ ++ @Override ++ public void removeDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { ++ java.util.Set disabled = getDisabledSlots(); ++ for (final org.bukkit.inventory.EquipmentSlot slot : slots) disabled.remove(slot); ++ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); ++ } ++ ++ @Override ++ public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { ++ return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch b/Remapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch new file mode 100644 index 0000000000..8e4a474184 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 20 Jul 2018 23:37:03 -0500 +Subject: [PATCH] AnvilDamageEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +index aa4b03dc9a0d6b3f387f081a1887672b90c60ef9..3d53edae7e3d5bb00913384ad0eb67551a65750e 100644 +--- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +@@ -80,7 +80,16 @@ public class AnvilMenu extends ItemCombinerMenu { + + if (!player.abilities.instabuild && iblockdata.is((Tag) BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { + BlockState iblockdata1 = AnvilBlock.damage(iblockdata); +- ++ // Paper start ++ com.destroystokyo.paper.event.block.AnvilDamagedEvent event = new com.destroystokyo.paper.event.block.AnvilDamagedEvent(getBukkitView(), iblockdata1 != null ? org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(iblockdata1) : null); ++ if (!event.callEvent()) { ++ return; ++ } else if (event.getDamageState() == com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState.BROKEN) { ++ iblockdata1 = null; ++ } else { ++ iblockdata1 = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getDamageState().getMaterial().createBlockData()).getState().setValue(AnvilBlock.FACING, iblockdata.getValue(AnvilBlock.FACING)); ++ } ++ // Paper end + if (iblockdata1 == null) { + world.removeBlock(blockposition, false); + world.levelEvent(1029, blockposition, 0); diff --git a/Remapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch b/Remapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch new file mode 100644 index 0000000000..812624262a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch @@ -0,0 +1,148 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Mon, 16 Jul 2018 00:05:05 +0300 +Subject: [PATCH] Add TNTPrimeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index ae3cf71f14526e1f356216dfaa899c8f5083d46d..37a9e9df7f7f816c214c37e545288bf9329626ed 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -61,6 +61,7 @@ import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.event.entity.EntityExplodeEvent; + import org.bukkit.event.entity.EntityRegainHealthEvent; + // CraftBukkit end ++import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent + + public class EnderDragon extends Mob implements Enemy { + +@@ -515,6 +516,11 @@ public class EnderDragon extends Mob implements Enemy { + }); + craftBlock.getNMS().spawnAfterBreak((ServerLevel) level, blockposition, ItemStack.EMPTY); + } ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = level.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, explosionSource.getSourceMob().getBukkitEntity()).callEvent()) ++ continue; ++ // Paper end + nmsBlock.wasExploded(level, blockposition, explosionSource); + + this.level.removeBlock(blockposition, false); +diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java +index 85170008de6e77cfb8e4f55ae440a8428d868af4..31b6c1333c7d0af28385e804e94348cef398748b 100644 +--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java +@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; + import com.google.common.collect.ImmutableMap; + import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent + import java.util.Map; + import java.util.Random; + import java.util.function.Function; +@@ -11,6 +12,7 @@ import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.Vec3i; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.BlockGetter; +@@ -288,7 +290,7 @@ public class FireBlock extends BaseFireBlock { + + world.setBlock(blockposition, this.getStateWithAge(world, blockposition, l), 3); + } else { +- world.removeBlock(blockposition, false); ++ if(iblockdata.getBlock() != Blocks.TNT) world.removeBlock(blockposition, false); // Paper - TNTPrimeEvent - We might be cancelling it below, move the setAir down + } + + Block block = iblockdata.getBlock(); +@@ -296,6 +298,13 @@ public class FireBlock extends BaseFireBlock { + if (block instanceof TntBlock) { + TntBlock blocktnt = (TntBlock) block; + ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = MCUtil.toBukkitBlock(world, blockposition); ++ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.FIRE, null).callEvent()) { ++ return; ++ } ++ world.setAir(blockposition, false); ++ // Paper end + TntBlock.explode(world, blockposition); + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/TntBlock.java b/src/main/java/net/minecraft/world/level/block/TntBlock.java +index 5c06e2f69f6c0a03f12fab6accc5f9a79ae37118..76665be4b3f2e2821c35d3d6d6407c4da4f224e7 100644 +--- a/src/main/java/net/minecraft/world/level/block/TntBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TntBlock.java +@@ -22,6 +22,7 @@ import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.phys.BlockHitResult; ++import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent + + public class TntBlock extends Block { + +@@ -36,6 +37,11 @@ public class TntBlock extends Block { + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + if (!oldState.is(state.getBlock())) { + if (world.hasNeighborSignal(pos)) { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos);; ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) ++ return; ++ // Paper end + explode(world, pos); + world.removeBlock(pos, false); + } +@@ -46,6 +52,11 @@ public class TntBlock extends Block { + @Override + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { + if (world.hasNeighborSignal(pos)) { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos);; ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) ++ return; ++ // Paper end + explode(world, pos); + world.removeBlock(pos, false); + } +@@ -64,6 +75,12 @@ public class TntBlock extends Block { + @Override + public void wasExploded(Level world, BlockPos pos, Explosion explosion) { + if (!world.isClientSide) { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos); ++ org.bukkit.entity.Entity source = explosion.source != null ? explosion.source.getBukkitEntity() : null; ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) ++ return; ++ // Paper end + PrimedTnt entitytntprimed = new PrimedTnt(world, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, explosion.getSourceMob()); + + entitytntprimed.setFuse((short) (world.random.nextInt(entitytntprimed.getLife() / 4) + entitytntprimed.getLife() / 8)); +@@ -92,6 +109,11 @@ public class TntBlock extends Block { + if (item != Items.FLINT_AND_STEEL && item != Items.FIRE_CHARGE) { + return super.use(state, world, pos, player, hand, hit); + } else { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos); ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.ITEM, player.getBukkitEntity()).callEvent()) ++ return InteractionResult.FAIL; ++ // Paper end + explode(world, pos, (LivingEntity) player); + world.setBlock(pos, Blocks.AIR.defaultBlockState(), 11); + if (!player.isCreative()) { +@@ -121,6 +143,13 @@ public class TntBlock extends Block { + } + // CraftBukkit end + ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); ++ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.PROJECTILE, projectile.getBukkitEntity()).callEvent()) { ++ return; ++ } ++ // Paper end ++ + explode(world, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null); + world.removeBlock(blockposition, false); + } diff --git a/Remapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch b/Remapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch new file mode 100644 index 0000000000..a6f013522a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 29 Jul 2018 05:02:15 +0100 +Subject: [PATCH] Break up and make tab spam limits configurable + +Due to the changes in 1.13, clients will send a tab completion request +for all bukkit commands in order to factor in the lack of support for +brigadier and provide backwards support in the API. + +Craftbukkit, however; has moved the chat spam limiter to also interact +with the tab completion request, which while good for avoiding abuse, +causes 1.13 clients to easilly be kicked from a server in bukkit due +to this. Removing the spam limit could cause issues for servers, however, +there is no way for servers to manipulate this without blindly cancelling +kick events, which only causes additional complications. This also causes +issues in that the tab spam limit and chat share the same field but different +limits, meaning that a player having typed a long command may be kicked from +the server. + +Splitting the field up and making it configurable allows for server owners +to take the burden of this into their own hand without having to rely on +plugins doing unsafe things. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 77a03abd59db4a43f6f2d59d4c7ef176e782f205..bd508025b771424c942fd856c31d520b6f548082 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -296,4 +296,18 @@ public class PaperConfig { + Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); + } + } ++ ++ public static int tabSpamIncrement = 1; ++ public static int tabSpamLimit = 500; ++ private static void tabSpamLimiters() { ++ tabSpamIncrement = getInt("settings.spam-limiter.tab-spam-increment", tabSpamIncrement); ++ // Older versions used a smaller limit, which is too low for 1.13, we'll bump this up if default ++ if (version < 14) { ++ if (tabSpamIncrement == 10) { ++ set("settings.spam-limiter.tab-spam-increment", 2); ++ tabSpamIncrement = 2; ++ } ++ } ++ tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 645f7b7c862acf77d70ca0b05308945424bc4d32..900c9b1106a153bc386f6c3d9c11226f8ac69f86 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -228,6 +228,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit start - multithreaded fields + private volatile int chatSpamTickCount; + private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(ServerGamePacketListenerImpl.class, "chatThrottle"); ++ private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits + // CraftBukkit end + private int dropSpamTickCount; + private final Int2ShortMap expectedAcks = new Int2ShortOpenHashMap(); +@@ -363,6 +364,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.server.getProfiler().pop(); + // CraftBukkit start + for (int spam; (spam = this.chatSpamTickCount) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; ++ if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable + /* Use thread-safe field access instead + if (this.chatThrottle > 0) { + --this.chatThrottle; +@@ -714,7 +716,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { + // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async + // CraftBukkit start +- if (chatSpamField.addAndGet(this, 1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable + server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper + return; + } diff --git a/Remapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch b/Remapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch new file mode 100644 index 0000000000..80b6896fe7 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch @@ -0,0 +1,341 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Thu, 2 Aug 2018 08:44:35 -0500 +Subject: [PATCH] Add hand to bucket events + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index d34da1eb172a7dcda564680afecf3dc145bf09f3..125a75576442eaa4f1ff6dd153bdb31097497a3f 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -724,7 +724,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop cachedSingleHashSet; // Paper + + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { +- super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); ++ super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); + this.respawnDimension = Level.OVERWORLD; + interactionManager.player = this; + this.gameMode = interactionManager; +@@ -254,7 +254,7 @@ public class ServerPlayer extends Player implements ContainerListener { + // Yes, this doesn't match Vanilla, but it's the best we can do for now. + // If this is an issue, PRs are welcome + public final BlockPos getSpawnPoint(ServerLevel worldserver) { +- BlockPos blockposition = worldserver.getSharedSpawnPos(); ++ BlockPos blockposition = worldserver.getSpawn(); + + if (worldserver.dimensionType().hasSkyLight() && worldserver.worldDataServer.getGameType() != GameType.ADVENTURE) { + int i = Math.max(0, this.server.getSpawnRadius(worldserver)); +@@ -291,7 +291,7 @@ public class ServerPlayer extends Player implements ContainerListener { + // CraftBukkit end + + private void fudgeSpawnLocation(ServerLevel world) { +- BlockPos blockposition = world.getSharedSpawnPos(); ++ BlockPos blockposition = world.getSpawn(); + + if (world.dimensionType().hasSkyLight() && world.worldDataServer.getGameType() != GameType.ADVENTURE) { // CraftBukkit + int i = Math.max(0, this.server.getSpawnRadius(world)); +@@ -464,7 +464,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + if (world == null || position == null) { + world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(); +- position = Vec3.atCenterOf(((ServerLevel) world).getSharedSpawnPos()); ++ position = Vec3.atCenterOf(((ServerLevel) world).getSpawn()); + } + this.level = world; + this.setPos(position.x(), position.y(), position.z()); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 51b1ce465d23b971f7e08a3175319a33183d0398..0bb397407b55bd1c464ac603ec4c189045aabbb2 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -808,7 +808,7 @@ public abstract class PlayerList { + entityplayer1.setShiftKeyDown(false); + + // entityplayer1.playerConnection.a(entityplayer1.locX(), entityplayer1.locY(), entityplayer1.locZ(), entityplayer1.yaw, entityplayer1.pitch); +- entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSharedSpawnPos(), worldserver1.getSharedSpawnAngle())); ++ entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSpawn(), worldserver1.getSharedSpawnAngle())); + entityplayer1.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); + entityplayer1.connection.send(new ClientboundSetExperiencePacket(entityplayer1.experienceProgress, entityplayer1.totalExperience, entityplayer1.experienceLevel)); + this.sendLevelInfo(entityplayer1, worldserver1); +@@ -1090,7 +1090,7 @@ public abstract class PlayerList { + + player.connection.send(new ClientboundSetBorderPacket(worldborder, ClientboundSetBorderPacket.Type.INITIALIZE)); + player.connection.send(new ClientboundSetTimePacket(world.getGameTime(), world.getDayTime(), world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); +- player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(world.getSharedSpawnPos(), world.getSharedSpawnAngle())); ++ player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(world.getSpawn(), world.getSharedSpawnAngle())); + if (world.isRaining()) { + // CraftBukkit start - handle player weather + // entityplayer.playerConnection.sendPacket(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.b, 0.0F)); +diff --git a/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java b/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java +index c283ea9528493fb95088870c84c6d6e3963aabb7..2633aca30601682a53b0236b94a12f0f18a87fc2 100644 +--- a/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java ++++ b/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java +@@ -33,7 +33,7 @@ public class RconConsoleSource implements CommandSource { + public CommandSourceStack createCommandSourceStack() { + ServerLevel worldserver = this.server.overworld(); + +- return new CommandSourceStack(this, Vec3.atLowerCornerOf((Vec3i) worldserver.getSharedSpawnPos()), Vec2.ZERO, worldserver, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null); ++ return new CommandSourceStack(this, Vec3.atLowerCornerOf((Vec3i) worldserver.getSpawn()), Vec2.ZERO, worldserver, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null); + } + + // CraftBukkit start - Send a String +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 5bf6bc6a01ccde8a4d67b49293bb326cb09248d8..4503bd65b3454bad94bb7b869f4e72e3121d8a3d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2688,7 +2688,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + if (flag1) { + blockposition1 = ServerLevel.END_SPAWN_POINT; + } else { +- blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos()); ++ blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSpawn()); + } + // CraftBukkit start + CraftPortalEvent event = callPortalEvent(this, destination, blockposition1, PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); +diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java +index 90393bb196c0895f387259c2dccbb29e2ca11c87..9c67b603d4d0ee5cb7f86b25ed8754afaf9cf7b3 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Cow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Cow.java +@@ -87,7 +87,7 @@ public class Cow extends Animal { + + if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) { + // CraftBukkit start - Got milk? +- org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET); ++ org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); // Paper - add enumHand + + if (event.isCancelled()) { + return InteractionResult.PASS; +diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java +index b426e155d13a1b2eb5ddb24a2d83cd7d1e92026b..d0e847e58483695d2af1c1410826bb25231cd6f6 100644 +--- a/src/main/java/net/minecraft/world/item/BucketItem.java ++++ b/src/main/java/net/minecraft/world/item/BucketItem.java +@@ -69,7 +69,7 @@ public class BucketItem extends Item { + if (iblockdata.getBlock() instanceof BucketPickup) { + // CraftBukkit start + Fluid dummyFluid = ((BucketPickup) iblockdata.getBlock()).takeLiquid(DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); +- PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getBucket()); ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getBucket(), hand); // Paper - add enumhand + + if (event.isCancelled()) { + ((ServerPlayer) user).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) +@@ -97,7 +97,7 @@ public class BucketItem extends Item { + iblockdata = world.getBlockState(blockposition); + BlockPos blockposition2 = iblockdata.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockposition : blockposition1; + +- if (this.a(user, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack)) { // CraftBukkit ++ if (this.a(user, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack, hand)) { // CraftBukkit // Paper - add enumhand + this.checkExtraContent(world, itemstack, blockposition2); + if (user instanceof ServerPlayer) { + CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) user, blockposition2, itemstack); +@@ -122,10 +122,12 @@ public class BucketItem extends Item { + public void checkExtraContent(Level world, ItemStack stack, BlockPos pos) {} + + public boolean emptyBucket(@Nullable Player player, Level world, BlockPos pos, @Nullable BlockHitResult movingobjectpositionblock) { +- return a(player, world, pos, movingobjectpositionblock, null, null, null); ++ // Paper start - add enumHand ++ return a(player, world, pos, movingobjectpositionblock, null, null, null, null); + } + +- public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack) { ++ public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, InteractionHand enumhand) { ++ // Paper end + // CraftBukkit end + if (!(this.content instanceof FlowingFluid)) { + return false; +@@ -138,7 +140,7 @@ public class BucketItem extends Item { + + // CraftBukkit start + if (flag1 && entityhuman != null) { +- PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack); ++ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); // Paper - add enumhand + if (event.isCancelled()) { + ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity + ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 +@@ -147,7 +149,7 @@ public class BucketItem extends Item { + } + // CraftBukkit end + if (!flag1) { +- return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack); // CraftBukkit ++ return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit // Paper - add enumhand + } else if (world.dimensionType().ultraWarm() && this.content.is((Tag) FluidTags.WATER)) { + int i = blockposition.getX(); + int j = blockposition.getY(); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 7a9ccd203885b9b369767d1fb8c53783201d0f0f..b75ffafb6840b6acab6e5b0ef5e222c4fa130977 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -277,6 +277,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + // Paper end + ++ // Paper start - moved up from WorldServer ++ public BlockPos getSpawn() { ++ BlockPos blockposition = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn()); ++ ++ if (!this.getWorldBorder().isWithinBounds(blockposition)) { ++ blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, new BlockPos(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); ++ } ++ ++ return blockposition; ++ } ++ // Paper end + @Override + public boolean isClientSide() { + return this.isClientSide; +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index 8a71eaf2855be0d415d1f7b18dbec98353fe5b47..b90a275a0dc2913809ce16659eed445501e486de 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -268,7 +268,7 @@ public final class NaturalSpawner { + private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) { + if (squaredDistance <= 576.0D) { + return false; +- } else if (world.getSharedSpawnPos().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D)) { ++ } else if (world.getSpawn().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D)) { + return false; + } else { + ChunkPos chunkcoordintpair = new ChunkPos(pos); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 9807612aed6c4393cbe1f4b6078e45bf1ba3deb2..159c32d6678e83f2d98ea6a1ad48346c9de017e1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -327,7 +327,7 @@ public class CraftWorld implements World { + + @Override + public Location getSpawnLocation() { +- BlockPos spawn = world.getSharedSpawnPos(); ++ BlockPos spawn = world.getSpawn(); + return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); + } + +@@ -1926,7 +1926,7 @@ public class CraftWorld implements World { + public void setKeepSpawnInMemory(boolean keepLoaded) { + world.keepSpawnInMemory = keepLoaded; + // Grab the worlds spawn chunk +- BlockPos chunkcoordinates = this.world.getSharedSpawnPos(); ++ BlockPos chunkcoordinates = this.world.getSpawn(); + if (keepLoaded) { + world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); + } else { +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 4cd08821305590e21a01cc4dda05370c2b721ac2..1877267344df1ff5b4de6a4e0c239f488cd52c1f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -222,7 +222,7 @@ public class CraftEventFactory { + public static Entity entityDamage; // For use in EntityDamageByEntityEvent + + // helper methods +- private static boolean canBuild(ServerLevel world, Player player, int x, int z) { ++ private static boolean canBuild(Level world, Player player, int x, int z) { + int spawnSize = Bukkit.getServer().getSpawnRadius(); + + if (world.dimension() != Level.OVERWORLD) return true; +@@ -230,7 +230,7 @@ public class CraftEventFactory { + if (((CraftServer) Bukkit.getServer()).getHandle().getOps().isEmpty()) return true; + if (player.isOp()) return true; + +- BlockPos chunkcoordinates = world.getSharedSpawnPos(); ++ BlockPos chunkcoordinates = world.getSpawn(); + + int distanceFromSpawn = Math.max(Math.abs(x - chunkcoordinates.getX()), Math.abs(z - chunkcoordinates.getZ())); + return distanceFromSpawn > spawnSize; +@@ -412,6 +412,20 @@ public class CraftEventFactory { + } + + private static PlayerEvent getPlayerBucketEvent(boolean isFilling, ServerLevel world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item) { ++ // Paper start - add enumHand ++ return getPlayerBucketEvent(isFilling, world, who, changed, clicked, clickedFace, itemstack, item, null); ++ } ++ ++ public static PlayerBucketEmptyEvent callPlayerBucketEmptyEvent(Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, InteractionHand enumHand) { ++ return (PlayerBucketEmptyEvent) getPlayerBucketEvent(false, world, who, changed, clicked, clickedFace, itemstack, Items.BUCKET, enumHand); ++ } ++ ++ public static PlayerBucketFillEvent callPlayerBucketFillEvent(Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemInHand, net.minecraft.world.item.Item bucket, InteractionHand enumHand) { ++ return (PlayerBucketFillEvent) getPlayerBucketEvent(true, world, who, clicked, changed, clickedFace, itemInHand, bucket, enumHand); ++ } ++ ++ private static PlayerEvent getPlayerBucketEvent(boolean isFilling, Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item, InteractionHand enumHand) { ++ // Paper end + Player player = (Player) who.getBukkitEntity(); + CraftItemStack itemInHand = CraftItemStack.asNewCraftStack(item); + Material bucket = CraftMagicNumbers.getMaterial(itemstack.getItem()); +@@ -424,10 +438,10 @@ public class CraftEventFactory { + + PlayerEvent event; + if (isFilling) { +- event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand); ++ event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand + ((PlayerBucketFillEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); + } else { +- event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand); ++ event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand + ((PlayerBucketEmptyEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); + } + diff --git a/Remapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch b/Remapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch new file mode 100644 index 0000000000..07dc1c1b3f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 3 Aug 2018 00:04:54 -0400 +Subject: [PATCH] MC-135506: Experience should save as Integers + + +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 52b90ef3a145325209d3d903a2b7c9a44c332cbe..37758cff3c4a8406c2f1496ae827ecdc953cf9f4 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -217,7 +217,7 @@ public class ExperienceOrb extends Entity { + public void addAdditionalSaveData(CompoundTag tag) { + tag.putShort("Health", (short) this.health); + tag.putShort("Age", (short) this.age); +- tag.putShort("Value", (short) this.value); ++ tag.putInt("Value", this.value); // Paper - save as Integer + this.savePaperNBT(tag); // Paper + } + +@@ -225,7 +225,7 @@ public class ExperienceOrb extends Entity { + public void readAdditionalSaveData(CompoundTag tag) { + this.health = tag.getShort("Health"); + this.age = tag.getShort("Age"); +- this.value = tag.getShort("Value"); ++ this.value = tag.getInt("Value"); // Paper - load as Integer + this.loadPaperNBT(tag); // Paper + } + diff --git a/Remapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch b/Remapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch new file mode 100644 index 0000000000..057731ba61 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 22 Nov 2016 00:40:42 -0500 +Subject: [PATCH] Fix client rendering skulls from same user + +See: https://github.com/PaperMC/Paper/issues/1304 + +Changes the UUID sent to client to be based on either +the texture payload, or random. + +This allows the client to render multiple skull textures from the same user, +for when different skins were used when skull was made. + +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index b4542ce6a8c37ab31e6ecaeb4cbad4742cca0f9b..10f1e3d761af83507bf71a00092641e22d0c8049 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -37,6 +37,7 @@ import net.minecraft.network.chat.Component; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.block.entity.SkullBlockEntity; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit +@@ -310,9 +311,18 @@ public class FriendlyByteBuf extends ByteBuf { + if (item.canBeDepleted() || item.shouldOverrideMultiplayerNbt()) { + // Spigot start - filter + itemstack = itemstack.copy(); +- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ //CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported + // Spigot end + nbttagcompound = itemstack.getTag(); ++ // Paper start ++ if (nbttagcompound != null && nbttagcompound.contains("SkullOwner", 10)) { ++ CompoundTag owner = nbttagcompound.getCompound("SkullOwner"); ++ if (owner.hasUUID("Id")) { ++ nbttagcompound.setUUID("SkullOwnerOrig", owner.getUUID("Id")); ++ SkullBlockEntity.sanitizeUUID(owner); ++ } ++ } ++ // Paper end + } + + this.writeNbt(nbttagcompound); +@@ -332,7 +342,16 @@ public class FriendlyByteBuf extends ByteBuf { + itemstack.setTag(this.readNbt()); + // CraftBukkit start + if (itemstack.getTag() != null) { +- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ // Paper start - Fix skulls of same owner - restore orig ID since we changed it on send to client ++ if (itemstack.tag.contains("SkullOwnerOrig")) { ++ CompoundTag owner = itemstack.tag.getCompound("SkullOwner"); ++ if (itemstack.tag.contains("SkullOwnerOrig")) { ++ owner.tags.put("Id", itemstack.tag.tags.get("SkullOwnerOrig")); ++ itemstack.tag.remove("SkullOwnerOrig"); ++ } ++ } ++ // Paper end ++ // CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported + } + // CraftBukkit end + return itemstack; +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index e5d4363edb8c494d2db69d2e0223a2db1519f64b..4fe15aa331ca18319ca46d1b426f0d6fd24341f0 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -15,6 +15,7 @@ import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.entity.SkullBlockEntity; + import net.minecraft.world.level.chunk.ChunkBiomeContainer; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.chunk.LevelChunkSection; +@@ -69,6 +70,7 @@ public class ClientboundLevelChunkPacket implements Packet public + private boolean emptyCacheFlag; + private Entity entityRepresentation; + private BlockInWorld cachedBreakBlock; +diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java +index eebaeaccc3ba1a9ec089d84b8de6c9d36034868f..6a1289424421083876d1808b7328cd3f01063a7e 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java +@@ -25,6 +25,7 @@ import java.util.concurrent.Executors; + import java.util.concurrent.Future; + import java.util.concurrent.TimeUnit; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; + import net.minecraft.server.MinecraftServer; +@@ -152,9 +153,37 @@ public class SkullBlockEntity extends BlockEntity /*implements ITickable*/ { // + @Nullable + @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { +- return new ClientboundBlockEntityDataPacket(this.worldPosition, 4, this.getUpdateTag()); ++ return new ClientboundBlockEntityDataPacket(this.worldPosition, 4, sanitizeTileEntityUUID(this.getUpdateTag())); // Paper + } + ++ // Paper start ++ public static CompoundTag sanitizeTileEntityUUID(CompoundTag cmp) { ++ CompoundTag owner = cmp.getCompound("Owner"); ++ if (!owner.isEmpty()) { ++ sanitizeUUID(owner); ++ } ++ return cmp; ++ } ++ ++ public static void sanitizeUUID(CompoundTag owner) { ++ CompoundTag properties = owner.getCompound("Properties"); ++ ListTag list = null; ++ if (!properties.isEmpty()) { ++ list = properties.getList("textures", 10); ++ } ++ ++ if (list != null && !list.isEmpty()) { ++ String textures = ((CompoundTag)list.get(0)).getString("Value"); ++ if (textures != null && textures.length() > 3) { ++ UUID uuid = UUID.nameUUIDFromBytes(textures.getBytes()); ++ owner.setUUID("Id", uuid); ++ return; ++ } ++ } ++ owner.setUUID("Id", UUID.randomUUID()); ++ } ++ // Paper end ++ + @Override + public CompoundTag getUpdateTag() { + return this.save(new CompoundTag()); diff --git a/Remapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch b/Remapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch new file mode 100644 index 0000000000..4f9ee3cc3e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch @@ -0,0 +1,184 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: miclebrick +Date: Wed, 8 Aug 2018 15:30:52 -0400 +Subject: [PATCH] Add Early Warning Feature to WatchDog + +Detect when the server has been hung for a long duration, and start printing +thread dumps at an interval until the point of crash. + +This will help diagnose what was going on in that time before the crash. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index bd508025b771424c942fd856c31d520b6f548082..62621562137cba4804f0465c58d25ca2786328e5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -25,6 +25,7 @@ import org.bukkit.configuration.file.YamlConfiguration; + import co.aikar.timings.Timings; + import co.aikar.timings.TimingsManager; + import org.spigotmc.SpigotConfig; ++import org.spigotmc.WatchdogThread; + + public class PaperConfig { + +@@ -297,6 +298,14 @@ public class PaperConfig { + } + } + ++ public static int watchdogPrintEarlyWarningEvery = 5000; ++ public static int watchdogPrintEarlyWarningDelay = 10000; ++ private static void watchdogEarlyWarning() { ++ watchdogPrintEarlyWarningEvery = getInt("settings.watchdog.early-warning-every", 5000); ++ watchdogPrintEarlyWarningDelay = getInt("settings.watchdog.early-warning-delay", 10000); ++ WatchdogThread.doStart(SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash ); ++ } ++ + public static int tabSpamIncrement = 1; + public static int tabSpamLimit = 500; + private static void tabSpamLimiters() { +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 125a75576442eaa4f1ff6dd153bdb31097497a3f..5a76ca77b974ff6fe862c9e05a88b507a34b44be 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1017,6 +1017,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable ++ // Paper start ++ Logger log = Bukkit.getServer().getLogger(); ++ long currentTime = monotonicMillis(); ++ if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) + { +- Logger log = Bukkit.getServer().getLogger(); ++ boolean isLongTimeout = currentTime > lastTick + timeoutTime; ++ // Don't spam early warning dumps ++ if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; ++ if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... ++ lastEarlyWarning = currentTime; ++ if (isLongTimeout) { ++ // Paper end + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper + log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); +@@ -93,29 +108,46 @@ public class WatchdogThread extends Thread + } + } + // Paper end ++ } else ++ { ++ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); ++ log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump"); ++ } ++ // Paper end - Different message for short timeout + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // ++ // Paper start - Only print full dump on long timeouts ++ if ( isLongTimeout ) ++ { + log.log( Level.SEVERE, "Entire Thread Dump:" ); + ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); + for ( ThreadInfo thread : threads ) + { + dumpThread( thread, log ); + } ++ } else { ++ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---"); ++ } ++ ++ + log.log( Level.SEVERE, "------------------------------" ); + ++ if ( isLongTimeout ) ++ { + if ( restart && !MinecraftServer.getServer().hasStopped() ) + { + RestartCommand.restart(); + } + break; ++ } // Paper end + } + + try + { +- sleep( 10000 ); ++ sleep( 1000 ); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout + } catch ( InterruptedException ex ) + { + interrupt(); diff --git a/Remapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch b/Remapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch new file mode 100644 index 0000000000..8392dc7bad --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 10 Aug 2018 22:11:49 -0400 +Subject: [PATCH] Make EnderDragon implement Mob + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java +index bba2e3152ee7073b75ecce1a4792178db20344db..aea39a6cb778d2ef88f66b632aebd824aaef2ea6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java +@@ -1,17 +1,17 @@ + package org.bukkit.craftbukkit.entity; + +-import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.Mob; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.ComplexLivingEntity; + +-public abstract class CraftComplexLivingEntity extends CraftLivingEntity implements ComplexLivingEntity { +- public CraftComplexLivingEntity(CraftServer server, LivingEntity entity) { ++public abstract class CraftComplexLivingEntity extends CraftMob implements ComplexLivingEntity { // Paper ++ public CraftComplexLivingEntity(CraftServer server, Mob entity) { // Paper + super(server, entity); + } + + @Override +- public LivingEntity getHandle() { +- return (LivingEntity) entity; ++ public Mob getHandle() { // Paper ++ return (Mob) entity; // Paper + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch b/Remapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch new file mode 100644 index 0000000000..b981b8b044 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: egg82 +Date: Tue, 7 Aug 2018 01:24:23 -0600 +Subject: [PATCH] Use ConcurrentHashMap in JsonList + +This is specifically aimed at fixing #471 + +Using a ConcurrentHashMap because thread safety +The performance benefit of Map over ConcurrentMap is negligabe at best in this scenaio, as most operations will be get and not add or remove +Even without considering the use-case the benefits are still negligable + +Original ideas for the system included an expiration policy and/or handler +The simpler solution was to use a computeIfPresent in the get method +This will simultaneously have an O(1) lookup time and automatically expire any values +Since the get method (nor other similar methods) don't seem to have a critical need to flush the map to disk at any of these points further processing is simply wasteful +Meaning the original function expired values unrelated to the current value without actually having any explicit need to + +The h method was heavily modified to be much more efficient in its processing +Also instead of being called on every get, it's now called just before a save +This will eliminate stale values being flushed to disk + +Modified isEmpty to use the isEmpty() method instead of the slightly confusing size() < 1 +The point of this is readability, but does have a side-benefit of a small microptimization + +Finally, added a couple obfhelpers for the modified code + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 0bb397407b55bd1c464ac603ec4c189045aabbb2..7c307a16ca3962db65be09a0ddd058a4ce81c7be 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -614,7 +614,7 @@ public abstract class PlayerList { + } else if (!this.isWhitelisted(gameprofile, event)) { // Paper + //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper + //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted +- } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { ++ } else if (getIpBans().isBanned(socketaddress) && getIpBans().get(socketaddress) != null && !getIpBans().get(socketaddress).hasExpired()) { // Paper - fix NPE with temp ip bans + IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); + + chatmessage = new TranslatableComponent("multiplayer.disconnect.banned_ip.reason", new Object[]{ipbanentry.getReason()}); +diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java +index 2cb235d695c244863a37454df22d5d94a291524d..e2982a8ac5448110378bc92247952332bdffe12c 100644 +--- a/src/main/java/net/minecraft/server/players/StoredUserList.java ++++ b/src/main/java/net/minecraft/server/players/StoredUserList.java +@@ -12,6 +12,8 @@ import java.io.BufferedReader; + import java.io.BufferedWriter; + import java.io.File; + import java.io.IOException; ++import java.lang.reflect.ParameterizedType; // Paper ++import java.lang.reflect.Type; // Paper + import java.nio.charset.StandardCharsets; + import java.util.Collection; + import java.util.Iterator; +@@ -28,7 +30,22 @@ public abstract class StoredUserList> { + protected static final Logger LOGGER = LogManager.getLogger(); + private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create(); + private final File file; +- private final Map map = Maps.newHashMap(); ++ // Paper - replace HashMap is ConcurrentHashMap ++ private final Map map = Maps.newConcurrentMap(); private final Map getBackingMap() { return this.map; } // Paper - OBFHELPER ++ private boolean e = true; ++ private static final ParameterizedType f = new ParameterizedType() { ++ public Type[] getActualTypeArguments() { ++ return new Type[]{StoredUserEntry.class}; ++ } ++ ++ public Type getRawType() { ++ return List.class; ++ } ++ ++ public Type getOwnerType() { ++ return null; ++ } ++ }; + + public StoredUserList(File file) { + this.file = file; +@@ -51,8 +68,13 @@ public abstract class StoredUserList> { + + @Nullable + public V get(K key) { +- this.removeExpired(); +- return (V) this.map.get(this.getKeyForUser(key)); // CraftBukkit - fix decompile error ++ // Paper start ++ // this.g(); ++ // return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error ++ return (V) this.getBackingMap().computeIfPresent(this.getMappingKey(key), (k, v) -> { ++ return v.hasExpired() ? null : v; ++ }); ++ // Paper end + } + + public void remove(K key) { +@@ -81,9 +103,11 @@ public abstract class StoredUserList> { + // CraftBukkit end + + public boolean isEmpty() { +- return this.map.size() < 1; ++ // return this.d.size() < 1; // Paper ++ return this.getBackingMap().isEmpty(); // Paper - readability is the goal. As an aside, isEmpty() uses only sumCount() and a comparison. size() uses sumCount(), casts, and boolean logic + } + ++ protected final String getMappingKey(K k0) { return getKeyForUser(k0); } // Paper - OBFHELPER + protected String getKeyForUser(K profile) { + return profile.toString(); + } +@@ -92,15 +116,16 @@ public abstract class StoredUserList> { + return this.map.containsKey(this.getKeyForUser(k0)); + } + ++ private void removeStaleEntries() { removeExpired(); } // Paper - OBFHELPER + private void removeExpired() { +- List list = Lists.newArrayList(); +- Iterator iterator = this.map.values().iterator(); ++ /*List list = Lists.newArrayList(); ++ Iterator iterator = this.d.values().iterator(); + + while (iterator.hasNext()) { + V v0 = (V) iterator.next(); // CraftBukkit - decompile error + + if (v0.hasExpired()) { +- list.add(v0.getUser()); ++ list.add(v0.getKey()); + } + } + +@@ -109,9 +134,11 @@ public abstract class StoredUserList> { + while (iterator.hasNext()) { + K k0 = (K) iterator.next(); // CraftBukkit - decompile error + +- this.map.remove(this.getKeyForUser(k0)); +- } ++ this.d.remove(this.a(k0)); ++ }*/ + ++ this.getBackingMap().values().removeIf(StoredUserEntry::hasExpired); ++ // Paper end + } + + protected abstract StoredUserEntry createEntry(JsonObject json); +@@ -121,6 +148,7 @@ public abstract class StoredUserList> { + } + + public void save() throws IOException { ++ this.removeStaleEntries(); // Paper - remove expired values before saving + JsonArray jsonarray = new JsonArray(); + + this.map.values().stream().map((jsonlistentry) -> { diff --git a/Remapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch b/Remapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch new file mode 100644 index 0000000000..b220fa4eb9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 12 Aug 2018 02:33:39 -0400 +Subject: [PATCH] Use a Queue for Queueing Commands + +Lists are bad as Queues mmmkay. + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 9143fe99e43236bf65e6f098a30d522302ad78b7..4862a9519d4ba5f05b634a0335837bea9812edee 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -72,7 +72,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + + private static final Logger LOGGER = LogManager.getLogger(); + private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$"); +- private final List consoleInput = Collections.synchronizedList(Lists.newArrayList()); ++ private final java.util.Queue serverCommandQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Paper - use a proper queue + private QueryThreadGs4 queryThreadGs4; + public final RconConsoleSource rconConsoleSource; + private RconThread rconThread; +@@ -426,13 +426,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } + + public void handleConsoleInput(String command, CommandSourceStack commandSource) { +- this.consoleInput.add(new ConsoleInput(command, commandSource)); ++ this.serverCommandQueue.add(new ConsoleInput(command, commandSource)); + } + + public void handleConsoleInputs() { + MinecraftTimings.serverCommandTimer.startTiming(); // Spigot +- while (!this.consoleInput.isEmpty()) { +- ConsoleInput servercommand = (ConsoleInput) this.consoleInput.remove(0); ++ // Paper start - use proper queue ++ ConsoleInput servercommand; ++ while ((servercommand = this.serverCommandQueue.poll()) != null) { ++ // Paper end + + // CraftBukkit start - ServerCommand for preprocessing + ServerCommandEvent event = new ServerCommandEvent(console, servercommand.msg); diff --git a/Remapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/Remapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch new file mode 100644 index 0000000000..52dbc8ee7e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 15 Aug 2018 01:16:34 -0400 +Subject: [PATCH] Ability to get Tile Entities from a chunk without snapshots + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +index 93b9e9d5932764f7e946dd3f8ab8191189c5d38f..423594177fe78600755d913f169f28dd1bfa2b37 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +@@ -3,8 +3,10 @@ package org.bukkit.craftbukkit; + import com.google.common.base.Preconditions; + import com.google.common.base.Predicates; + import java.lang.ref.WeakReference; ++import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collection; ++import java.util.List; + import java.util.function.Predicate; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Registry; +@@ -129,9 +131,16 @@ public class CraftChunk implements Chunk { + + @Override + public BlockState[] getTileEntities() { ++ // Paper start ++ return getTileEntities(true); ++ } ++ ++ @Override ++ public BlockState[] getTileEntities(boolean useSnapshot) { + if (!isLoaded()) { + getWorld().getChunkAt(x, z); // Transient load for this tick + } ++ // Paper end + int index = 0; + net.minecraft.world.level.chunk.LevelChunk chunk = getHandle(); + +@@ -143,11 +152,33 @@ public class CraftChunk implements Chunk { + } + + BlockPos position = (BlockPos) obj; +- entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(); ++ entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(useSnapshot); // Paper ++ } ++ ++ return entities; ++ } ++ ++ // Paper start ++ @Override ++ public Collection getTileEntities(Predicate blockPredicate, boolean useSnapshot) { ++ Preconditions.checkNotNull(blockPredicate, "blockPredicate"); ++ if (!isLoaded()) { ++ getWorld().getChunkAt(x, z); // Transient load for this tick ++ } ++ net.minecraft.world.level.chunk.LevelChunk chunk = getHandle(); ++ ++ List entities = new ArrayList<>(); ++ ++ for (BlockPos position : chunk.blockEntities.keySet()) { ++ Block block = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); ++ if (blockPredicate.test(block)) { ++ entities.add(block.getState(useSnapshot)); ++ } + } + + return entities; + } ++ // Paper end + + @Override + public boolean isLoaded() { diff --git a/Remapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch b/Remapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch new file mode 100644 index 0000000000..b471e98ef0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch @@ -0,0 +1,159 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 15 Aug 2018 01:26:09 -0700 +Subject: [PATCH] Allow disabling armour stand ticking + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3562950df4868b1393790b1a1ff1fe0dc589c155..5ab0e7183e48134b7a0f736462516b1a8a333b04 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -384,4 +384,10 @@ public class PaperWorldConfig { + private void armorStandEntityLookups() { + armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); + } ++ ++ public boolean armorStandTick = true; ++ private void armorStandTick() { ++ this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); ++ log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 06e52a0c5decf717e35c605d6bcb46c3c7b29656..2994eee1d381af2c9ff3649dd48a2ae14c38c9d7 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -77,9 +77,16 @@ public class ArmorStand extends LivingEntity { + public Rotations leftLegPose; + public Rotations rightLegPose; + public boolean canMove = true; // Paper ++ // Paper start - Allow ArmorStands not to tick ++ public boolean canTick = true; ++ public boolean canTickSetByAPI = false; ++ private boolean noTickPoseDirty = false; ++ private boolean noTickEquipmentDirty = false; ++ // Paper end + + public ArmorStand(EntityType type, Level world) { + super(type, world); ++ if (world != null) this.canTick = world.paperConfig.armorStandTick; // Paper - armour stand ticking + this.handItems = NonNullList.a(2, ItemStack.EMPTY); + this.armorItems = NonNullList.a(4, ItemStack.EMPTY); + this.headPose = ArmorStand.DEFAULT_HEAD_POSE; +@@ -175,6 +182,7 @@ public class ArmorStand extends LivingEntity { + this.armorItems.set(enumitemslot.getIndex(), itemstack); + } + ++ this.noTickEquipmentDirty = true; // Paper - Allow equipment to be updated even when tick disabled + } + + @Override +@@ -255,6 +263,7 @@ public class ArmorStand extends LivingEntity { + } + + tag.put("Pose", this.writePose()); ++ if (this.canTickSetByAPI) tag.putBoolean("Paper.CanTickOverride", this.canTick); // Paper - persist no tick setting + } + + @Override +@@ -286,6 +295,12 @@ public class ArmorStand extends LivingEntity { + this.setNoBasePlate(tag.getBoolean("NoBasePlate")); + this.setMarker(tag.getBoolean("Marker")); + this.noPhysics = !this.hasPhysics(); ++ // Paper start - persist no tick ++ if (tag.contains("Paper.CanTickOverride")) { ++ this.canTick = tag.getBoolean("Paper.CanTickOverride"); ++ this.canTickSetByAPI = true; ++ } ++ // Paper end + CompoundTag nbttagcompound1 = tag.getCompound("Pose"); + + this.readPose(nbttagcompound1); +@@ -641,7 +656,29 @@ public class ArmorStand extends LivingEntity { + + @Override + public void tick() { ++ // Paper start ++ if (!this.canTick) { ++ if (this.noTickPoseDirty) { ++ this.noTickPoseDirty = false; ++ this.updatePose(); ++ } ++ ++ if (this.noTickEquipmentDirty) { ++ this.noTickEquipmentDirty = false; ++ this.detectEquipmentUpdates(); ++ } ++ ++ return; ++ } ++ // Paper end ++ + super.tick(); ++ // Paper start - Split into separate method ++ updatePose(); ++ } ++ ++ public void updatePose() { ++ // Paper end + Rotations vector3f = (Rotations) this.entityData.get(ArmorStand.DATA_HEAD_POSE); + + if (!this.headPose.equals(vector3f)) { +@@ -764,29 +801,36 @@ public class ArmorStand extends LivingEntity { + public void setHeadPose(Rotations vector3f) { + this.headPose = vector3f; + this.entityData.set(ArmorStand.DATA_HEAD_POSE, vector3f); ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + } + + public void setBodyPose(Rotations vector3f) { + this.bodyPose = vector3f; + this.entityData.set(ArmorStand.DATA_BODY_POSE, vector3f); ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + } + + public void setLeftArmPose(Rotations vector3f) { + this.leftArmPose = vector3f; + this.entityData.set(ArmorStand.DATA_LEFT_ARM_POSE, vector3f); ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + } + + public void setRightArmPose(Rotations vector3f) { + this.rightArmPose = vector3f; + this.entityData.set(ArmorStand.DATA_RIGHT_ARM_POSE, vector3f); ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + } + + public void setLeftLegPose(Rotations vector3f) { ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + this.leftLegPose = vector3f; + this.entityData.set(ArmorStand.DATA_LEFT_LEG_POSE, vector3f); ++ + } + + public void setRightLegPose(Rotations vector3f) { ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + this.rightLegPose = vector3f; + this.entityData.set(ArmorStand.DATA_RIGHT_LEG_POSE, vector3f); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +index d4da5214a39b718671dcaf687cb0ff8668ce9728..8363b1b2267da30cda2fb8ea4e844598e20e1422 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +@@ -311,5 +311,16 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { + return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); + } ++ ++ @Override ++ public boolean canTick() { ++ return this.getHandle().canTick; ++ } ++ ++ @Override ++ public void setCanTick(final boolean tick) { ++ this.getHandle().canTick = tick; ++ this.getHandle().canTickSetByAPI = true; ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch b/Remapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch new file mode 100644 index 0000000000..fa154eb153 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Aug 2018 12:05:12 -0700 +Subject: [PATCH] Optimize BlockPosition helper methods + +Resolves #1338 + +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index c5089b0da33a68e7cadbc4841b07f9d772d224a0..b13e5d05d862ea8c6031b8071f525f00bc48f7e7 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -121,58 +121,75 @@ public class BlockPos extends Vec3i { + + @Override + public BlockPos above() { +- return this.relative(Direction.UP); ++ return new BlockPos(this.getX(), this.getY() + 1, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos above(int distance) { +- return this.relative(Direction.UP, distance); ++ return distance == 0 ? this : new BlockPos(this.getX(), this.getY() + distance, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos below() { +- return this.relative(Direction.DOWN); ++ return new BlockPos(this.getX(), this.getY() - 1, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos below(int distance) { +- return this.relative(Direction.DOWN, distance); ++ return distance == 0 ? this : new BlockPos(this.getX(), this.getY() - distance, this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPos north() { +- return this.relative(Direction.NORTH); ++ return new BlockPos(this.getX(), this.getY(), this.getZ() - 1); // Paper - Optimize BlockPosition + } + + public BlockPos north(int distance) { +- return this.relative(Direction.NORTH, distance); ++ return distance == 0 ? this : new BlockPos(this.getX(), this.getY(), this.getZ() - distance); // Paper - Optimize BlockPosition + } + + public BlockPos south() { +- return this.relative(Direction.SOUTH); ++ return new BlockPos(this.getX(), this.getY(), this.getZ() + 1); // Paper - Optimize BlockPosition + } + + public BlockPos south(int distance) { +- return this.relative(Direction.SOUTH, distance); ++ return distance == 0 ? this : new BlockPos(this.getX(), this.getY(), this.getZ() + distance); // Paper - Optimize BlockPosition + } + + public BlockPos west() { +- return this.relative(Direction.WEST); ++ return new BlockPos(this.getX() - 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPos west(int distance) { +- return this.relative(Direction.WEST, distance); ++ return distance == 0 ? this : new BlockPos(this.getX() - distance, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPos east() { +- return this.relative(Direction.EAST); ++ return new BlockPos(this.getX() + 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPos east(int distance) { +- return this.relative(Direction.EAST, distance); ++ return distance == 0 ? this : new BlockPos(this.getX() + distance, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPos relative(Direction direction) { +- return new BlockPos(this.getX() + direction.getStepX(), this.getY() + direction.getStepY(), this.getZ() + direction.getStepZ()); ++ // Paper Start - Optimize BlockPosition ++ switch(direction) { ++ case UP: ++ return new BlockPos(this.getX(), this.getY() + 1, this.getZ()); ++ case DOWN: ++ return new BlockPos(this.getX(), this.getY() - 1, this.getZ()); ++ case NORTH: ++ return new BlockPos(this.getX(), this.getY(), this.getZ() - 1); ++ case SOUTH: ++ return new BlockPos(this.getX(), this.getY(), this.getZ() + 1); ++ case WEST: ++ return new BlockPos(this.getX() - 1, this.getY(), this.getZ()); ++ case EAST: ++ return new BlockPos(this.getX() + 1, this.getY(), this.getZ()); ++ default: ++ return new BlockPos(this.getX() + direction.getStepX(), this.getY() + direction.getStepY(), this.getZ() + direction.getStepZ()); ++ } ++ // Paper End + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/Remapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch new file mode 100644 index 0000000000..50cfc368af --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 18 Aug 2018 12:43:16 -0400 +Subject: [PATCH] Restore vanlla default mob-spawn-range and water animals + limit + + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0efcbab8f8806aeb8dd8bd6384e5a7cee375d100..34ee684901906fc2ef5f0d09680d2686b813e52b 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -165,7 +165,7 @@ public class SpigotWorldConfig + public byte mobSpawnRange; + private void mobSpawnRange() + { +- mobSpawnRange = (byte) getInt( "mob-spawn-range", 6 ); ++ mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla + log( "Mob Spawn Range: " + mobSpawnRange ); + } + +diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml +index 6474a7fb738e1238cc272afc5ff14b645947e688..6d71bd0db752e6f523364ca5351579b6bcb434c8 100644 +--- a/src/main/resources/configurations/bukkit.yml ++++ b/src/main/resources/configurations/bukkit.yml +@@ -26,7 +26,7 @@ settings: + spawn-limits: + monsters: 70 + animals: 10 +- water-animals: 15 ++ water-animals: 5 + water-ambient: 20 + ambient: 15 + chunk-gc: diff --git a/Remapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch b/Remapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch new file mode 100644 index 0000000000..1156074828 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch @@ -0,0 +1,229 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 24 Aug 2018 08:18:42 -0500 +Subject: [PATCH] Slime Pathfinder Events + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java +index fc8f26e988f1e4826dcfdcf071293bb356163e62..120ceb28ee3aee8a09cf67b45ac95d3d6613c133 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java +@@ -24,7 +24,6 @@ import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.Pose; +@@ -43,6 +42,13 @@ import net.minecraft.world.level.WorldGenLevel; + import net.minecraft.world.level.biome.Biomes; + import net.minecraft.world.level.levelgen.WorldgenRandom; + import net.minecraft.world.phys.Vec3; ++// Paper start ++import com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent; ++import com.destroystokyo.paper.event.entity.SlimeSwimEvent; ++import com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent; ++import com.destroystokyo.paper.event.entity.SlimeWanderEvent; ++import org.bukkit.entity.LivingEntity; ++// Paper end + // CraftBukkit start + import java.util.ArrayList; + import java.util.List; +@@ -103,6 +109,7 @@ public class Slime extends Mob implements Enemy { + @Override + public void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); ++ tag.putBoolean("Paper.canWander", this.canWander); // Paper + tag.putInt("Size", this.getSize() - 1); + tag.putBoolean("wasOnGround", this.wasOnGround); + } +@@ -117,6 +124,11 @@ public class Slime extends Mob implements Enemy { + + this.setSize(i + 1, false); + super.readAdditionalSaveData(tag); ++ // Paper start - check exists before loading or this will be loaded as false ++ if (tag.contains("Paper.canWander")) { ++ this.canWander = tag.getBoolean("Paper.canWander"); ++ } ++ // Paper end + this.wasOnGround = tag.getBoolean("wasOnGround"); + } + +@@ -218,7 +230,7 @@ public class Slime extends Mob implements Enemy { + super.remove(); + return; + } +- List slimes = new ArrayList<>(j); ++ List slimes = new ArrayList<>(j); + // CraftBukkit end + + for (int l = 0; l < k; ++l) { +@@ -242,7 +254,7 @@ public class Slime extends Mob implements Enemy { + if (CraftEventFactory.callEntityTransformEvent(this, slimes, EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { + return; + } +- for (LivingEntity living : slimes) { ++ for (net.minecraft.world.entity.LivingEntity living : slimes) { + this.level.addEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason + } + // CraftBukkit end +@@ -255,7 +267,7 @@ public class Slime extends Mob implements Enemy { + public void push(Entity entity) { + super.push(entity); + if (entity instanceof IronGolem && this.isDealsDamage()) { +- this.dealDamage((LivingEntity) entity); ++ this.dealDamage((net.minecraft.world.entity.LivingEntity) entity); + } + + } +@@ -263,18 +275,18 @@ public class Slime extends Mob implements Enemy { + @Override + public void playerTouch(Player player) { + if (this.isDealsDamage()) { +- this.dealDamage((LivingEntity) player); ++ this.dealDamage((net.minecraft.world.entity.LivingEntity) player); + } + + } + +- protected void dealDamage(LivingEntity target) { ++ protected void dealDamage(net.minecraft.world.entity.LivingEntity target) { + if (this.isAlive()) { + int i = this.getSize(); + + if (this.distanceToSqr((Entity) target) < 0.6D * (double) i * 0.6D * (double) i && this.canSee(target) && target.hurt(DamageSource.mobAttack(this), this.getAttackDamage())) { + this.playSound(SoundEvents.SLIME_ATTACK, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); +- this.doEnchantDamageEffects((LivingEntity) this, (Entity) target); ++ this.doEnchantDamageEffects((net.minecraft.world.entity.LivingEntity) this, (Entity) target); + } + } + +@@ -396,7 +408,7 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- return !this.slime.isPassenger(); ++ return !this.slime.isPassenger() && this.slime.canWander && new SlimeWanderEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper + } + + @Override +@@ -417,7 +429,7 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; ++ return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new SlimeSwimEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper + } + + @Override +@@ -443,14 +455,18 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- return this.slime.getTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; ++ return this.slime.getTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander; // Paper - add canWander + } + + @Override + public void tick() { + if (--this.nextRandomizeTime <= 0) { + this.nextRandomizeTime = 40 + this.slime.getRandom().nextInt(60); +- this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); ++ // Paper start ++ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (float) this.slime.getRandom().nextInt(360)); ++ if (!this.slime.canWander || !event.callEvent()) return; ++ this.chosenDegrees = event.getNewYaw(); ++ // Paper end + } + + ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.chosenDegrees, false); +@@ -469,9 +485,17 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- LivingEntity entityliving = this.slime.getTarget(); ++ net.minecraft.world.entity.LivingEntity entityliving = this.slime.getTarget(); + +- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable ? false : this.slime.getMoveControl() instanceof Slime.SlimeMoveControl)); ++ // Paper start ++ if (entityliving == null || !entityliving.isAlive()) { ++ return false; ++ } ++ if (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable) { ++ return false; ++ } ++ return this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); ++ // Paper end + } + + @Override +@@ -482,9 +506,17 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canContinueToUse() { +- LivingEntity entityliving = this.slime.getTarget(); ++ net.minecraft.world.entity.LivingEntity entityliving = this.slime.getTarget(); + +- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable ? false : --this.growTiredTimer > 0)); ++ // Paper start ++ if (entityliving == null || !entityliving.isAlive()) { ++ return false; ++ } ++ if (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable) { ++ return false; ++ } ++ return --this.growTiredTimer > 0 && this.slime.canWander && new SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); ++ // Paper end + } + + @Override +@@ -492,6 +524,13 @@ public class Slime extends Mob implements Enemy { + this.slime.lookAt((Entity) this.slime.getTarget(), 10.0F, 10.0F); + ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.slime.yRot, this.slime.isDealsDamage()); + } ++ ++ // Paper start - clear timer and target when goal resets ++ public void stop() { ++ this.growTiredTimer = 0; ++ this.slime.setTarget(null); ++ } ++ // Paper end + } + + static class SlimeMoveControl extends MoveControl { +@@ -550,4 +589,15 @@ public class Slime extends Mob implements Enemy { + } + } + } ++ ++ // Paper start ++ private boolean canWander = true; ++ public boolean canWander() { ++ return canWander; ++ } ++ ++ public void setWander(boolean canWander) { ++ this.canWander = canWander; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +index 93af0fd9e15954d7d9f28d7dc29ee18055908348..340036135588d06e43cbd229dd3a6613b04bb9ab 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +@@ -34,4 +34,14 @@ public class CraftSlime extends CraftMob implements Slime { + public EntityType getType() { + return EntityType.SLIME; + } ++ ++ // Paper start ++ public boolean canWander() { ++ return getHandle().canWander(); ++ } ++ ++ public void setWander(boolean canWander) { ++ getHandle().setWander(canWander); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch b/Remapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch new file mode 100644 index 0000000000..c8fef8a86f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 8 Aug 2018 16:33:21 -0600 +Subject: [PATCH] Configurable speed for water flowing over lava + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5ab0e7183e48134b7a0f736462516b1a8a333b04..f280dbff4a09bc611a9ca565c6d697d08801f53b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -390,4 +390,10 @@ public class PaperWorldConfig { + this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); + log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); + } ++ ++ public int waterOverLavaFlowSpeed; ++ private void waterOverLavaFlowSpeed() { ++ waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); ++ log("Water over lava flow speed: " + waterOverLavaFlowSpeed); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java +index f99b90e4b3210747077f2bf3adbcf7b5fb9821ec..97f2d9082e49010fb8780c5fdd8957f71b31e43e 100644 +--- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java +@@ -23,6 +23,7 @@ import net.minecraft.world.level.material.FlowingFluid; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; ++import net.minecraft.world.level.material.Material; + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.level.storage.loot.LootContext; + import net.minecraft.world.phys.shapes.CollisionContext; +@@ -100,11 +101,28 @@ public class LiquidBlock extends Block implements BucketPickup { + @Override + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + if (this.shouldSpreadLiquid(world, pos, state)) { +- world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); ++ world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper + } + + } + ++ // Paper start - Get flow speed. Throttle if its water and flowing adjacent to lava ++ public int getFlowSpeed(Level world, BlockPos blockposition) { ++ if (this.material == Material.WATER) { ++ if ( ++ world.getMaterialIfLoaded(blockposition.north(1)) == Material.LAVA || ++ world.getMaterialIfLoaded(blockposition.south(1)) == Material.LAVA || ++ world.getMaterialIfLoaded(blockposition.west(1)) == Material.LAVA || ++ world.getMaterialIfLoaded(blockposition.east(1)) == Material.LAVA ++ ) { ++ return world.paperConfig.waterOverLavaFlowSpeed; ++ } ++ } ++ return this.fluid.getTickDelay(world); ++ } ++ // Paper end ++ ++ + @Override + public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { + if (state.getFluidState().isSource() || newState.getFluidState().isSource()) { +@@ -117,7 +135,7 @@ public class LiquidBlock extends Block implements BucketPickup { + @Override + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { + if (this.shouldSpreadLiquid(world, pos, state)) { +- world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); ++ world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper + } + + } diff --git a/Remapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch b/Remapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch new file mode 100644 index 0000000000..b9e1c45f8f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: miclebrick +Date: Thu, 23 Aug 2018 11:45:32 -0400 +Subject: [PATCH] Optimize CraftBlockData Creation + +Avoids a hashmap lookup by cacheing a reference to the CraftBlockData +and cloning it when one is needed. + +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index 5d7794c9533bd37193f196bda616adaaace2bbde..57eedaeedaa24bd274fb55c6e4521f1305382645 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -374,6 +374,14 @@ public abstract class BlockBehaviour { + this.hasPostProcess = blockbase_info.hasPostProcess; + this.emissiveRendering = blockbase_info.emissiveRendering; + } ++ // Paper start - impl cached craft block data, lazy load to fix issue with loading at the wrong time ++ private org.bukkit.craftbukkit.block.data.CraftBlockData cachedCraftBlockData; ++ ++ public org.bukkit.craftbukkit.block.data.CraftBlockData createCraftBlockData() { ++ if (cachedCraftBlockData == null) cachedCraftBlockData = org.bukkit.craftbukkit.block.data.CraftBlockData.createData(getBlockData()); ++ return (org.bukkit.craftbukkit.block.data.CraftBlockData) cachedCraftBlockData.clone(); ++ } ++ // Paper end + + public void initCache() { + if (!this.getBlock().hasDynamicShape()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +index 3a90b504ebbe86350f5fee5baa818e40d884d24f..0b6c6dfc380cea87bd88c3eb8a199e072dcbf56c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +@@ -509,7 +509,17 @@ public class CraftBlockData implements BlockData { + return craft; + } + ++ // Paper start - optimize creating BlockData to not need a map lookup ++ static { ++ // Initialize cached data for all IBlockData instances after registration ++ Block.BLOCK_STATE_REGISTRY.iterator().forEachRemaining(BlockState::createCraftBlockData); ++ } + public static CraftBlockData fromData(BlockState data) { ++ return data.createCraftBlockData(); ++ } ++ ++ public static CraftBlockData createData(BlockState data) { ++ // Paper end + return MAP.getOrDefault(data.getBlock().getClass(), CraftBlockData::new).apply(data); + } + diff --git a/Remapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch b/Remapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch new file mode 100644 index 0000000000..9ee9585d10 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 26 Aug 2018 20:49:50 -0400 +Subject: [PATCH] Optimize RegistryMaterials + +Use larger initial sizes to increase bucket capacity on the BiMap + +BiMap.get was seen to be using a good bit of CPU time. + +diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java +index 928d4b980a1f703915454ffb304dc329fa4223df..da3733db4a5817673703f6c0cf37b5ee3bf91a99 100644 +--- a/src/main/java/net/minecraft/core/MappedRegistry.java ++++ b/src/main/java/net/minecraft/core/MappedRegistry.java +@@ -30,6 +30,7 @@ import net.minecraft.Util; + import net.minecraft.resources.RegistryDataPackCodec; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; ++import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; // Paper + import org.apache.commons.lang3.Validate; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -38,7 +39,7 @@ public class MappedRegistry extends WritableRegistry { + + protected static final Logger LOGGER = LogManager.getLogger(); + private final ObjectList byId = new ObjectArrayList(256); +- private final Object2IntMap toId = new Object2IntOpenCustomHashMap(Util.identityStrategy()); ++ private final Reference2IntOpenHashMap bg = new Reference2IntOpenHashMap(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map + private final BiMap storage; + private final BiMap, T> keyStorage; + private final Map lifecycles; +@@ -48,10 +49,10 @@ public class MappedRegistry extends WritableRegistry { + + public MappedRegistry(ResourceKey> key, Lifecycle lifecycle) { + super(key, lifecycle); +- this.toId.defaultReturnValue(-1); +- this.storage = HashBiMap.create(); +- this.keyStorage = HashBiMap.create(); +- this.lifecycles = Maps.newIdentityHashMap(); ++ this.bg.defaultReturnValue(-1); ++ this.storage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions ++ this.keyStorage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions ++ this.lifecycles = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions + this.elementsLifecycle = lifecycle; + } + +@@ -77,7 +78,7 @@ public class MappedRegistry extends WritableRegistry { + Validate.notNull(entry); + this.byId.size(Math.max(this.byId.size(), rawId + 1)); + this.byId.set(rawId, entry); +- this.toId.put(entry, rawId); ++ this.bg.put(entry, rawId); + this.randomCache = null; + if (checkDuplicateKeys && this.keyStorage.containsKey(key)) { + MappedRegistry.LOGGER.debug("Adding duplicate key '{}' to registry", key); +@@ -113,12 +114,12 @@ public class MappedRegistry extends WritableRegistry { + if (t0 == null) { + i = rawId.isPresent() ? rawId.getAsInt() : this.nextId; + } else { +- i = this.toId.getInt(t0); ++ i = this.bg.getInt(t0); + if (rawId.isPresent() && rawId.getAsInt() != i) { + throw new IllegalStateException("ID mismatch"); + } + +- this.toId.removeInt(t0); ++ this.bg.removeInt(t0); + this.lifecycles.remove(t0); + } + +@@ -138,7 +139,7 @@ public class MappedRegistry extends WritableRegistry { + + @Override + public int getId(@Nullable T entry) { +- return this.toId.getInt(entry); ++ return this.bg.getInt(entry); + } + + @Nullable +@@ -195,7 +196,7 @@ public class MappedRegistry extends WritableRegistry { + this.randomCache = collection.toArray(new Object[collection.size()]); + } + +- return Util.getRandom(this.randomCache, random); ++ return (T) Util.getRandom(this.randomCache, random); // Paper - Decompile fix + } + + public static Codec> networkCodec(ResourceKey> resourcekey, Lifecycle lifecycle, Codec entryCodec) { +@@ -215,7 +216,7 @@ public class MappedRegistry extends WritableRegistry { + Iterator iterator = registrymaterials.iterator(); + + while (iterator.hasNext()) { +- T t0 = iterator.next(); ++ T t0 = (T) iterator.next(); // Paper - Decompile fix + + builder.add(new MappedRegistry.RegistryEntry<>((ResourceKey) registrymaterials.getResourceKey(t0).get(), registrymaterials.getId(t0), t0)); + } diff --git a/Remapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch b/Remapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch new file mode 100644 index 0000000000..a3b507be83 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 25 Aug 2018 19:56:51 -0500 +Subject: [PATCH] Add PhantomPreSpawnEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index 4a2fecdfbda34d6360d50e2ac017907a62b4a043..e37137a2890330b92e05d6f76c46ffc99a527803 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -161,6 +161,11 @@ public class Phantom extends FlyingMob implements Enemy { + } + + this.setPhantomSize(tag.getInt("Size")); ++ // Paper start ++ if (tag.hasUUID("Paper.SpawningEntity")) { ++ this.spawningEntity = tag.getUUID("Paper.SpawningEntity"); ++ } ++ // Paper end + } + + @Override +@@ -170,6 +175,11 @@ public class Phantom extends FlyingMob implements Enemy { + tag.putInt("AY", this.anchorPoint.getY()); + tag.putInt("AZ", this.anchorPoint.getZ()); + tag.putInt("Size", this.getPhantomSize()); ++ // Paper start ++ if (this.spawningEntity != null) { ++ tag.setUUID("Paper.SpawningEntity", this.spawningEntity); ++ } ++ // Paper end + } + + @Override +@@ -216,6 +226,15 @@ public class Phantom extends FlyingMob implements Enemy { + return entitysize.scale(f); + } + ++ // Paper start ++ java.util.UUID spawningEntity; ++ ++ public java.util.UUID getSpawningEntity() { ++ return spawningEntity; ++ } ++ public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } ++ // Paper end ++ + class PhantomAttackPlayerTargetGoal extends Goal { + + private final TargetingConditions attackTargeting; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +index ee18e2826f6390ef5a29557b733fd00db5bc409f..42effcbd3ca7c38a4e8b1aa835543ad243112a33 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +@@ -4,6 +4,7 @@ import java.util.Iterator; + import java.util.Random; + import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.stats.ServerStatsCounter; +@@ -73,8 +74,17 @@ public class PhantomSpawner implements CustomSpawner { + int k = 1 + random.nextInt(difficultydamagescaler.getDifficulty().getId() + 1); + + for (int l = 0; l < k; ++l) { ++ // Paper start ++ com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(MCUtil.toLocation(world, blockposition1), ((ServerPlayer) entityhuman).getBukkitEntity(), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ break; ++ } ++ continue; ++ } ++ // Paper end + Phantom entityphantom = (Phantom) EntityType.PHANTOM.create((Level) world); +- ++ entityphantom.setSpawningEntity(entityhuman.getUUID()); // Paper + entityphantom.moveTo(blockposition1, 0.0F, 0.0F); + groupdataentity = entityphantom.finalizeSpawn(world, difficultydamagescaler, MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); + world.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +index 15eb09595dad996314c169f9dd7d381e43f77be9..92162fa22f5e98b7837bde5830bd47c31b8b52d8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +@@ -34,4 +34,10 @@ public class CraftPhantom extends CraftFlying implements Phantom { + public EntityType getType() { + return EntityType.PHANTOM; + } ++ ++ // Paper start ++ public java.util.UUID getSpawningEntity() { ++ return getHandle().getSpawningEntity(); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch b/Remapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch new file mode 100644 index 0000000000..3a4091fe8d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 24 Aug 2018 11:50:26 -0500 +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 d9b5cf8ac01289801ded01d928fa7ead96551be5..336736fae0b49a05e48c1c70a225da316bb73e66 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +@@ -289,7 +289,18 @@ public class Creeper extends Monster { + } + + public void ignite() { +- this.entityData.set(Creeper.DATA_IS_IGNITED, true); ++ // Paper start ++ setIgnited(true); ++ } ++ ++ public void setIgnited(boolean ignited) { ++ if (isIgnited() != ignited) { ++ com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited); ++ if (event.callEvent()) { ++ this.entityData.set(Creeper.DATA_IS_IGNITED, event.isIgnited()); ++ } ++ } ++ // Paper end + } + + 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 ded0b7c1619aada95492e7ec25c0e0f3d008d0ad..9f68beb8c79ed1c429ee9f9efab8b8604258293b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java +@@ -100,4 +100,14 @@ public class CraftCreeper extends CraftMonster implements Creeper { + public EntityType getType() { + return EntityType.CREEPER; + } ++ ++ // Paper start ++ public void setIgnited(boolean ignited) { ++ getHandle().setIgnited(ignited); ++ } ++ ++ public boolean isIgnited() { ++ return getHandle().isIgnited(); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch b/Remapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch new file mode 100644 index 0000000000..b542a82e8a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 28 Aug 2018 23:04:15 -0400 +Subject: [PATCH] Inventory#removeItemAnySlot + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +index 9d70ef8c3967596491a804e4d66f2ec1b13992c9..ef2d18d19a86b3701855aa1ac126462e663f8fcd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +@@ -222,10 +222,16 @@ public class CraftInventory implements Inventory { + } + + private int first(ItemStack item, boolean withAmount) { ++ // Paper start ++ return first(item, withAmount, getStorageContents()); ++ } ++ ++ private int first(ItemStack item, boolean withAmount, ItemStack[] inventory) { ++ // Paper end + if (item == null) { + return -1; + } +- ItemStack[] inventory = getStorageContents(); ++ //ItemStack[] inventory = getStorageContents(); // Paper - let param deal + for (int i = 0; i < inventory.length; i++) { + if (inventory[i] == null) continue; + +@@ -348,6 +354,17 @@ public class CraftInventory implements Inventory { + + @Override + public HashMap removeItem(ItemStack... items) { ++ // Paper start ++ return removeItem(false, items); ++ } ++ ++ @Override ++ public HashMap removeItemAnySlot(ItemStack... items) { ++ return removeItem(true, items); ++ } ++ ++ private HashMap removeItem(boolean searchEntire, ItemStack... items) { ++ // Paper end + Validate.notNull(items, "Items cannot be null"); + HashMap leftover = new HashMap(); + +@@ -358,7 +375,10 @@ public class CraftInventory implements Inventory { + int toDelete = item.getAmount(); + + while (true) { +- int first = first(item, false); ++ // Paper start - Allow searching entire contents ++ ItemStack[] toSearch = searchEntire ? getContents() : getStorageContents(); ++ int first = first(item, false, toSearch); ++ // Paper end + + // Drat! we don't have this type in the inventory + if (first == -1) { diff --git a/Remapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/Remapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch new file mode 100644 index 0000000000..3b436ea5af --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 2 Sep 2018 19:34:33 -0700 +Subject: [PATCH] Make CraftWorld#loadChunk(int, int, false) load unconverted + chunks + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 159c32d6678e83f2d98ea6a1ad48346c9de017e1..57a2af56b53567371fdb6d0a55866e1e4e37cf3b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -490,7 +490,7 @@ public class CraftWorld implements World { + @Override + public boolean loadChunk(int x, int z, boolean generate) { + org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot +- ChunkAccess chunk = world.getChunkSource().getChunk(x, z, generate ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); ++ ChunkAccess chunk = world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper + + // If generate = false, but the chunk already exists, we will get this back. + if (chunk instanceof ImposterProtoChunk) { diff --git a/Remapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch b/Remapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch new file mode 100644 index 0000000000..f1edc62517 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 3 Sep 2018 18:20:03 -0500 +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 205c639d26652befebae925fc6e40976c370710f..2e25cb2a04d150d3154bf0d7f0eccb97e65ff53e 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3605,6 +3605,23 @@ public abstract class LivingEntity extends Entity { + this.broadcastBreakEvent(hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); + } + // Paper start ++ public HitResult getRayTrace(int maxDistance) { ++ return getRayTrace(maxDistance, ClipContext.Fluid.NONE); ++ } ++ ++ public HitResult getRayTrace(int maxDistance, ClipContext.Fluid fluidCollisionOption) { ++ if (maxDistance < 1 || maxDistance > 120) { ++ throw new IllegalArgumentException("maxDistance must be between 1-120"); ++ } ++ ++ Vec3 start = new Vec3(getX(), getY() + getEyeHeight(), getZ()); ++ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance); ++ Vec3 end = new Vec3(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ()); ++ ClipContext raytrace = new ClipContext(start, end, ClipContext.Block.OUTLINE, fluidCollisionOption, this); ++ ++ return level.clip(raytrace); ++ } ++ + public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; + + public int getShieldBlockingDelay() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 6dd7a722e10a2727f68318b880f2726bb816f198..7e3a215f1592bed9f35e22076d9e35a5a49a430e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import com.destroystokyo.paper.block.TargetBlockInfo; + import com.google.common.base.Preconditions; + import com.google.common.collect.Sets; + import java.util.ArrayList; +@@ -8,6 +9,7 @@ import java.util.Iterator; + import java.util.List; + import java.util.Set; + import java.util.UUID; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.InteractionHand; + import net.minecraft.world.damagesource.DamageSource; +@@ -28,6 +30,8 @@ import net.minecraft.world.entity.projectile.ThrownEgg; + import net.minecraft.world.entity.projectile.ThrownEnderpearl; + import net.minecraft.world.entity.projectile.ThrownExperienceBottle; + import net.minecraft.world.entity.projectile.ThrownTrident; ++import net.minecraft.world.phys.BlockHitResult; ++import net.minecraft.world.phys.HitResult; + import org.apache.commons.lang.Validate; + import org.bukkit.FluidCollisionMode; + import org.bukkit.Location; +@@ -37,6 +41,7 @@ import org.bukkit.attribute.AttributeInstance; + import org.bukkit.block.Block; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.entity.memory.CraftMemoryKey; + import org.bukkit.craftbukkit.entity.memory.CraftMemoryMapper; + import org.bukkit.craftbukkit.inventory.CraftEntityEquipment; +@@ -190,6 +195,28 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return blocks.get(0); + } + ++ // Paper start ++ @Override ++ public Block getTargetBlock(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { ++ HitResult rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof BlockHitResult) ? null : CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()); ++ } ++ ++ @Override ++ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { ++ HitResult rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof BlockHitResult) ? null : MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection()); ++ } ++ ++ @Override ++ public TargetBlockInfo getTargetBlockInfo(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { ++ HitResult rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof BlockHitResult) ? null : ++ new TargetBlockInfo(CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()), ++ MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection())); ++ } ++ // Paper end ++ + @Override + public List getLastTwoTargetBlocks(Set transparent, int maxDistance) { + return getLineOfSight(transparent, maxDistance, 2); diff --git a/Remapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch b/Remapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch new file mode 100644 index 0000000000..bfe6717c67 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 4 Sep 2018 15:02:00 -0500 +Subject: [PATCH] Expose attack cooldown methods for Player + + +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 709e930eef7bae5694238ed8c4d0ef59316bb715..14d5acff198338c68162e33d4a90f74be77cb15f 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -2100,6 +2100,7 @@ public abstract class Player extends LivingEntity { + this.entityData.set(Player.DATA_SHOULDER_RIGHT, entityTag); + } + ++ public float getCooldownPeriod() { return this.getCurrentItemAttackStrengthDelay(); } // Paper - OBFHELPER + public float getCurrentItemAttackStrengthDelay() { + return (float) (1.0D / this.getAttributeValue(Attributes.ATTACK_SPEED) * 20.0D); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index c7f66dddf0a0850ca4048dd47cd2ded114caa07e..ee823c4ed5b9fcfaa900b470c582435f0b909ebc 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2186,6 +2186,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND)); + connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, inventory.getSelected())); + } ++ ++ public float getCooldownPeriod() { ++ return getHandle().getCooldownPeriod(); ++ } ++ ++ public float getCooledAttackStrength(float adjustTicks) { ++ return getHandle().getAttackStrengthScale(adjustTicks); ++ } ++ ++ public void resetCooldown() { ++ getHandle().resetAttackStrengthTicker(); ++ } + // Paper end + + // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0279-Improve-death-events.patch b/Remapped-Spigot-Server-Patches/0279-Improve-death-events.patch new file mode 100644 index 0000000000..15db46e30d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0279-Improve-death-events.patch @@ -0,0 +1,458 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Tue, 21 Aug 2018 01:39:35 +0100 +Subject: [PATCH] Improve death events + +This adds the ability to cancel the death events and to modify the sound +an entity makes when dying. (In cases were no sound should it will be +called with shouldPlaySound set to false allowing unsilencing of silent +entities) + +It makes handling of entity deaths a lot nicer as you no longer need +to listen on the damage event and calculate if the entity dies yourself +to cancel the death which has the benefit of also receiving the dropped +items and experience which is otherwise only properly possible by using +internal code. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 5664e292046d4fcdb81340df8cee8d04aa27ca55..75419c866641ab654349cde6ca3fbdef701dd8d9 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -211,6 +211,10 @@ public class ServerPlayer extends Player implements ContainerListener { + public int latency; + public boolean wonGame; + private int containerUpdateDelay; // Paper ++ // Paper start - cancellable death event ++ public boolean queueHealthUpdatePacket = false; ++ public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; ++ // Paper end + + // CraftBukkit start + public String displayName; +@@ -714,6 +718,15 @@ public class ServerPlayer extends Player implements ContainerListener { + Component defaultMessage = this.getCombatTracker().getDeathMessage(); + + org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure ++ // Paper start - cancellable death event ++ if (event.isCancelled()) { ++ // make compatible with plugins that might have already set the health in an event listener ++ if (this.getHealth() <= 0) { ++ this.setHealth((float) event.getReviveHealth()); ++ } ++ return; ++ } ++ // Paper end + + // SPIGOT-943 - only call if they have an inventory open + if (this.containerMenu != this.inventoryMenu) { +@@ -860,8 +873,17 @@ public class ServerPlayer extends Player implements ContainerListener { + } + } + } +- +- return super.hurt(source, amount); ++ // Paper start - cancellable death events ++ //return super.damageEntity(damagesource, f); ++ this.queueHealthUpdatePacket = true; ++ boolean damaged = super.hurt(source, amount); ++ this.queueHealthUpdatePacket = false; ++ if (this.queuedHealthUpdatePacket != null) { ++ this.connection.send(this.queuedHealthUpdatePacket); ++ this.queuedHealthUpdatePacket = null; ++ } ++ return damaged; ++ // Paper end + } + } + } +diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java +index 8a0863a695bb33698fb3fe6e06599f6f6f47011f..36e665009418d5177016a744eb920fbf99f534fc 100644 +--- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java ++++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java +@@ -203,6 +203,7 @@ public class CombatTracker { + this.nextLocation = null; + } + ++ public final void reset() { this.recheckStatus(); } // Paper - OBFHELPER + public void recheckStatus() { + int i = this.inCombat ? 300 : 100; + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 4503bd65b3454bad94bb7b869f4e72e3121d8a3d..e7fed1f8bb8ffb164ddcdab51f41c369d6e3103d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1537,6 +1537,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + // CraftBukkit end + ++ public final void runKillTrigger(Entity entity, int kills, DamageSource damageSource) { this.awardKillScore(entity, kills, damageSource); } // Paper - OBFHELPER + public void awardKillScore(Entity killer, int score, DamageSource damageSource) { + if (killer instanceof ServerPlayer) { + CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer) killer, this, damageSource); +@@ -2441,6 +2442,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.fallDistance = 0.0F; + } + ++ public final void onKill(ServerLevel worldserver, net.minecraft.world.entity.LivingEntity entityLiving) { this.killed(worldserver, entityLiving); } // Paper - OBFHELPER + public void killed(ServerLevel worldserver, net.minecraft.world.entity.LivingEntity entityliving) {} + + protected void moveTowardsClosestSpace(double x, double y, double z) { +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 2e25cb2a04d150d3154bf0d7f0eccb97e65ff53e..7a2292e6907a2ae2026bd7243e864bd8300ecafa 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -186,7 +186,7 @@ public abstract class LivingEntity extends Entity { + protected float animStep; + protected float animStepO; + protected float rotOffs; +- protected int deathScore; ++ protected int deathScore;protected int getKillCount() { return this.deathScore; } // Paper - OBFHELPER + public float lastHurt; + protected boolean jumping; + public float xxa; +@@ -230,6 +230,7 @@ public abstract class LivingEntity extends Entity { + public Set collidableExemptions = new HashSet<>(); + public boolean canPickUpLoot; + public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper ++ public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event + + @Override + public float getBukkitYaw() { +@@ -1345,13 +1346,17 @@ public abstract class LivingEntity extends Entity { + if (knockbackCancelled) this.level.broadcastEntityEvent(this, (byte) 2); // Paper - Disable explosion knockback + if (this.isDeadOrDying()) { + if (!this.checkTotemDeathProtection(source)) { +- SoundEvent soundeffect = this.getDeathSound(); ++ // Paper start - moved into CraftEventFactory event caller for cancellable death event ++ //SoundEffect soundeffect = this.getSoundDeath(); + +- if (flag1 && soundeffect != null) { +- this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); +- } ++// if (flag1 && soundeffect != null) { ++// this.playSound(soundeffect, this.getSoundVolume(), this.dH()); ++// } ++ this.silentDeath = !flag1; // mark entity as dying silently ++ // Paper end + + this.die(source); ++ this.silentDeath = false; // Paper - cancellable death event - reset to default + } + } else if (flag1) { + this.playHurtSound(source); +@@ -1490,27 +1495,48 @@ public abstract class LivingEntity extends Entity { + Entity entity = source.getEntity(); + LivingEntity entityliving = this.getKillCredit(); + +- if (this.deathScore >= 0 && entityliving != null) { +- entityliving.awardKillScore(this, this.deathScore, source); ++ /* // Paper - move down to make death event cancellable - this is the runKillTrigger below ++ if (this.aO >= 0 && entityliving != null) { ++ entityliving.a(this, this.aO, damagesource); + } + + if (this.isSleeping()) { +- this.stopSleeping(); ++ this.entityWakeup(); + } ++ */ // Paper + + this.dead = true; +- this.getCombatTracker().recheckStatus(); ++ // this.getCombatTracker().g(); // Paper - moved into if below as .reset() + if (this.level instanceof ServerLevel) { + if (entity != null) { +- entity.killed((ServerLevel) this.level, this); ++ // entity.a((WorldServer) this.world, this); // Paper - move below into if for onKill + } + +- this.dropAllDeathLoot(source); ++ // Paper start ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.d(source); ++ if (deathEvent == null || !deathEvent.isCancelled()) { ++ if (this.getKillCount() >= 0 && entityliving != null) { ++ entityliving.runKillTrigger(this, this.getKillCount(), source); ++ } ++ if (this.isSleeping()) { ++ this.stopSleeping(); ++ } ++ this.getCombatTracker().reset(); ++ if (entity != null) { ++ entity.onKill((ServerLevel) this.level, this); ++ } ++ } else { ++ this.dead = false; ++ this.setHealth((float) deathEvent.getReviveHealth()); ++ } ++ // Paper end + this.createWitherRose(entityliving); + } + ++ if (this.dead) { // Paper + this.level.broadcastEntityEvent(this, (byte) 3); + this.setPose(Pose.DYING); ++ } // Paper + } + } + +@@ -1518,7 +1544,7 @@ public abstract class LivingEntity extends Entity { + if (!this.level.isClientSide) { + boolean flag = false; + +- if (adversary instanceof WitherBoss) { ++ if (this.dead && adversary instanceof WitherBoss) { // Paper + if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + BlockPos blockposition = this.blockPosition(); + BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState(); +@@ -1546,8 +1572,9 @@ public abstract class LivingEntity extends Entity { + } + } + +- protected void dropAllDeathLoot(DamageSource source) { +- Entity entity = source.getEntity(); ++ protected org.bukkit.event.entity.EntityDeathEvent processDeath(DamageSource damagesource) { return d(damagesource); } // Paper - OBFHELPER ++ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper ++ Entity entity = damagesource.getEntity(); + int i; + + if (entity instanceof net.minecraft.world.entity.player.Player) { +@@ -1560,19 +1587,22 @@ public abstract class LivingEntity extends Entity { + + this.dropEquipment(); // CraftBukkit - from below + if (this.shouldDropLoot() && this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.dropFromLootTable(source, flag); +- this.dropCustomDeathLoot(source, i, flag); ++ this.dropFromLootTable(damagesource, flag); ++ this.dropCustomDeathLoot(damagesource, i, flag); + } + // CraftBukkit start - Call death event +- CraftEventFactory.callEntityDeathEvent(this, this.drops); ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper ++ this.postDeathDropItems(deathEvent); // Paper + this.drops = new ArrayList<>(); + // CraftBukkit end + + // this.dropInventory();// CraftBukkit - moved up + this.dropExperience(); ++ return deathEvent; // Paper + } + + protected void dropEquipment() {} ++ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled + + // CraftBukkit start + public int getExpReward() { +@@ -1657,6 +1687,7 @@ public abstract class LivingEntity extends Entity { + return SoundEvents.GENERIC_HURT; + } + ++ public final SoundEvent getDeathSoundEffect() { return this.getDeathSound(); } // Paper - OBFHELPER + @Nullable + protected SoundEvent getDeathSound() { + return SoundEvents.GENERIC_DEATH; +@@ -2193,10 +2224,12 @@ public abstract class LivingEntity extends Entity { + + } + ++ public final float getDeathSoundVolume() { return this.getSoundVolume(); } // Paper - OBFHELPER + protected float getSoundVolume() { + return 1.0F; + } + ++ public float getSoundPitch() { return getVoicePitch();} // Paper - OBFHELPER + protected float getVoicePitch() { + return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.5F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java +index c2d98222f575d7383e4c040730f6d531bdb0d7b6..46792914f574800c893eb197fa7b3b87ce7e500b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java +@@ -647,15 +647,25 @@ public class Fox extends Animal { + } + + @Override +- protected void dropAllDeathLoot(DamageSource source) { +- ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND); ++ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND).copy(); // Paper ++ ++ // Paper start - Cancellable death event ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.d(damagesource); ++ ++ // Below is code to drop ++ ++ if (deathEvent == null || deathEvent.isCancelled()) { ++ return deathEvent; ++ } ++ // Paper end + + if (!itemstack.isEmpty()) { + this.spawnAtLocation(itemstack); + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + } + +- super.dropAllDeathLoot(source); ++ return deathEvent; // Paper + } + + public static boolean isPathClear(Fox fox, LivingEntity chasedEntity) { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java +index 34a9843267ef739e5889791fb4899fabe1f864bc..63723044ae6c607e6d36bc0b0c6b525037df34b2 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java +@@ -68,11 +68,19 @@ public abstract class AbstractChestedHorse extends AbstractHorse { + this.spawnAtLocation((ItemLike) Blocks.CHEST); + } + +- this.setChest(false); ++ //this.setCarryingChest(false); // Paper - moved to post death logic + } + + } + ++ // Paper start ++ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) { ++ if (this.hasChest() && (event == null || !event.isCancelled())) { ++ this.setChest(false); ++ } ++ } ++ // Paper end ++ + @Override + public void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 2994eee1d381af2c9ff3649dd48a2ae14c38c9d7..33d51852ed6fe3f5adcdecf8f405a23689f4265a 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -610,7 +610,7 @@ public class ArmorStand extends LivingEntity { + this.armorItems.set(i, ItemStack.EMPTY); + } + } +- this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above ++ this.d(damageSource); // CraftBukkit - moved from above + + } + +@@ -742,7 +742,8 @@ public class ArmorStand extends LivingEntity { + + @Override + public void kill() { +- org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event ++ org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event // Paper - make cancellable ++ if (event.isCancelled()) return; // Paper - make cancellable + this.remove(); + } + +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 14d5acff198338c68162e33d4a90f74be77cb15f..3aadc4ab5fe7b2ee9e20e0789ddcfe750599972f 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -581,7 +581,7 @@ public abstract class Player extends LivingEntity { + super.die(source); + this.reapplyPosition(); + if (!this.isSpectator()) { +- this.dropAllDeathLoot(source); ++ this.d(source); + } + + if (source != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index ee823c4ed5b9fcfaa900b470c582435f0b909ebc..a3e65028d3e0c09a65cd9c28b037fe01a2ed1d76 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1836,7 +1836,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void sendHealthUpdate() { +- getHandle().connection.send(new ClientboundSetHealthPacket(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); ++ // Paper start - cancellable death event ++ //getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); ++ ClientboundSetHealthPacket packet = new ClientboundSetHealthPacket(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel()); ++ if (this.getHandle().queueHealthUpdatePacket) { ++ this.getHandle().queuedHealthUpdatePacket = packet; ++ } else { ++ this.getHandle().connection.send(packet); ++ } ++ // Paper end + } + + 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 1877267344df1ff5b4de6a4e0c239f488cd52c1f..e696d2e52532df25d74a1f559e2c9ca0f3d5058d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -18,6 +18,8 @@ import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundSource; + import net.minecraft.util.Unit; + import net.minecraft.world.Container; + import net.minecraft.world.InteractionHand; +@@ -793,9 +795,16 @@ public class CraftEventFactory { + public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, List drops) { + CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); + EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward()); ++ populateFields(victim, event); // Paper - make cancellable + CraftWorld world = (CraftWorld) entity.getWorld(); + Bukkit.getServer().getPluginManager().callEvent(event); + ++ // Paper start - make cancellable ++ if (event.isCancelled()) { ++ return event; ++ } ++ playDeathSound(victim, event); ++ // Paper end + victim.expToDrop = event.getDroppedExp(); + + for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { +@@ -811,8 +820,15 @@ public class CraftEventFactory { + CraftPlayer entity = victim.getBukkitEntity(); + PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure + event.setKeepInventory(keepInventory); ++ populateFields(victim, event); // Paper - make cancellable + org.bukkit.World world = entity.getWorld(); + Bukkit.getServer().getPluginManager().callEvent(event); ++ // Paper start - make cancellable ++ if (event.isCancelled()) { ++ return event; ++ } ++ playDeathSound(victim, event); ++ // Paper end + + victim.keepLevel = event.getKeepLevel(); + victim.newLevel = event.getNewLevel(); +@@ -829,6 +845,31 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start - helper methods for making death event cancellable ++ // Add information to death event ++ private static void populateFields(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) { ++ event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue()); ++ event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent()); ++ SoundEvent soundEffect = victim.getDeathSoundEffect(); ++ event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null); ++ event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundSource().name())); ++ event.setDeathSoundVolume(victim.getDeathSoundVolume()); ++ event.setDeathSoundPitch(victim.getSoundPitch()); ++ } ++ ++ // Play death sound manually ++ private static void playDeathSound(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) { ++ if (event.shouldPlayDeathSound() && event.getDeathSound() != null && event.getDeathSoundCategory() != null) { ++ net.minecraft.world.entity.player.Player source = victim instanceof net.minecraft.world.entity.player.Player ? (net.minecraft.world.entity.player.Player) victim : null; ++ double x = event.getEntity().getLocation().getX(); ++ double y = event.getEntity().getLocation().getY(); ++ double z = event.getEntity().getLocation().getZ(); ++ SoundEvent soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound()); ++ SoundSource soundCategory = SoundSource.valueOf(event.getDeathSoundCategory().name()); ++ victim.level.playSound(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch()); ++ } ++ } ++ // Paper end + /** + * Server methods + */ diff --git a/Remapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch b/Remapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch new file mode 100644 index 0000000000..59c2f88e09 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 8 Sep 2018 18:43:31 -0500 +Subject: [PATCH] Allow chests to be placed with NBT data + + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 79a7c37f15840dbd97510874ac12437d2b854999..02bfa4fb8055e60a84e878ffbf18303c0ee25b1d 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -296,6 +296,7 @@ public final class ItemStack { + enuminteractionresult = InteractionResult.FAIL; // cancel placement + // PAIL: Remove this when MC-99075 fixed + placeEvent.getPlayer().updateInventory(); ++ world.capturedTileEntities.clear(); // Paper - clear out tile entities as chests and such will pop loot + // revert back all captured blocks + for (BlockState blockstate : blocks) { + blockstate.update(true, false); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java +index 17289d28b6d0023279a573715ee3d182988dd651..ab11c7a5a397047a35245b149d77bf035e718a0c 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java +@@ -326,7 +326,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity { // Pape + // CraftBukkit start + @Override + public boolean onlyOpCanSetNbt() { +- return true; ++ return false; // Paper + } + // CraftBukkit end + } diff --git a/Remapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch b/Remapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch new file mode 100644 index 0000000000..8ae73987bc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch @@ -0,0 +1,290 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 9 Sep 2018 13:30:00 -0400 +Subject: [PATCH] Mob Pathfinding API + +Implements Pathfinding API for mobs + +diff --git a/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3e7971b7ca5be0442378c9e7482775e05918d0ac +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java +@@ -0,0 +1,141 @@ ++package com.destroystokyo.paper.entity; ++ ++import org.apache.commons.lang.Validate; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Mob; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++import net.minecraft.world.level.pathfinder.Node; ++import net.minecraft.world.level.pathfinder.Path; ++import PathResult; ++import java.util.ArrayList; ++import java.util.List; ++ ++public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder { ++ ++ private final net.minecraft.world.entity.Mob entity; ++ ++ public PaperPathfinder(net.minecraft.world.entity.Mob entity) { ++ this.entity = entity; ++ } ++ ++ @Override ++ public Mob getEntity() { ++ return entity.getBukkitMob(); ++ } ++ ++ @Override ++ public void stopPathfinding() { ++ entity.getNavigation().stopPathfinding(); ++ } ++ ++ @Override ++ public boolean hasPath() { ++ return entity.getNavigation().getPathEntity() != null; ++ } ++ ++ @Nullable ++ @Override ++ public PathResult getCurrentPath() { ++ Path path = entity.getNavigation().getPathEntity(); ++ return path != null ? new PaperPathResult(path) : null; ++ } ++ ++ @Nullable ++ @Override ++ public PathResult findPath(Location loc) { ++ Validate.notNull(loc, "Location can not be null"); ++ Path path = entity.getNavigation().calculateDestination(loc.getX(), loc.getY(), loc.getZ()); ++ return path != null ? new PaperPathResult(path) : null; ++ } ++ ++ @Nullable ++ @Override ++ public PathResult findPath(LivingEntity target) { ++ Validate.notNull(target, "Target can not be null"); ++ Path path = entity.getNavigation().calculateDestination(((CraftLivingEntity) target).getHandle()); ++ return path != null ? new PaperPathResult(path) : null; ++ } ++ ++ @Override ++ public boolean moveTo(@Nonnull PathResult path, double speed) { ++ Validate.notNull(path, "PathResult can not be null"); ++ Path pathEntity = ((PaperPathResult) path).path; ++ return entity.getNavigation().setDestination(pathEntity, speed); ++ } ++ ++ @Override ++ public boolean canOpenDoors() { ++ return entity.getNavigation().getPathfinder().getPathfinder().shouldOpenDoors(); ++ } ++ ++ @Override ++ public void setCanOpenDoors(boolean canOpenDoors) { ++ entity.getNavigation().getPathfinder().getPathfinder().setShouldOpenDoors(canOpenDoors); ++ } ++ ++ @Override ++ public boolean canPassDoors() { ++ return entity.getNavigation().getPathfinder().getPathfinder().shouldPassDoors(); ++ } ++ ++ @Override ++ public void setCanPassDoors(boolean canPassDoors) { ++ entity.getNavigation().getPathfinder().getPathfinder().setShouldPassDoors(canPassDoors); ++ } ++ ++ @Override ++ public boolean canFloat() { ++ return entity.getNavigation().getPathfinder().getPathfinder().shouldFloat(); ++ } ++ ++ @Override ++ public void setCanFloat(boolean canFloat) { ++ entity.getNavigation().getPathfinder().getPathfinder().setShouldFloat(canFloat); ++ } ++ ++ public class PaperPathResult implements com.destroystokyo.paper.entity.PaperPathfinder.PathResult { ++ ++ private final Path path; ++ PaperPathResult(Path path) { ++ this.path = path; ++ } ++ ++ @Nullable ++ @Override ++ public Location getFinalPoint() { ++ Node point = path.getFinalPoint(); ++ return point != null ? toLoc(point) : null; ++ } ++ ++ @Override ++ public List getPoints() { ++ List points = new ArrayList<>(); ++ for (Node point : path.getPoints()) { ++ points.add(toLoc(point)); ++ } ++ return points; ++ } ++ ++ @Override ++ public int getNextPointIndex() { ++ return path.getNextIndex(); ++ } ++ ++ @Nullable ++ @Override ++ public Location getNextPoint() { ++ if (!path.hasNext()) { ++ return null; ++ } ++ return toLoc(path.getPoints().get(path.getNextIndex())); ++ } ++ } ++ ++ private Location toLoc(Node point) { ++ return new Location(entity.level.getWorld(), point.getX(), point.getY(), point.getZ()); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index c3082f5dd64413a47421cb01538bec846bf21d2c..a362506f38e8d30543b6cd6d215db561290dac76 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -100,7 +100,7 @@ public abstract class PathNavigation { + } + + @Nullable +- public final Path createPath(double x, double y, double z, int distance) { ++ public final Path calculateDestination(double d0, double d1, double d2) { return createPath(d0, d1, d2, 0); } public final Path createPath(double x, double y, double z, int distance) { // Paper - OBFHELPER + return this.createPath(new BlockPos(x, y, z), distance); + } + +@@ -125,7 +125,7 @@ public abstract class PathNavigation { + } + + @Nullable +- public Path createPath(Entity entity, int distance) { ++ public final Path calculateDestination(Entity entity) { return createPath(entity, 0); } public Path createPath(Entity entity, int distance) { + return this.a(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper + } + +@@ -190,6 +190,7 @@ public abstract class PathNavigation { + return pathentity != null && this.moveTo(pathentity, speed); + } + ++ public boolean setDestination(@Nullable Path pathentity, double speed) { return moveTo(pathentity, speed); } // Paper - OBFHELPER + public boolean moveTo(@Nullable Path path, double speed) { + if (path == null) { + this.path = null; +@@ -217,7 +218,7 @@ public abstract class PathNavigation { + } + } + +- @Nullable ++ @Nullable public Path getPathEntity() { return getPath(); } @Nullable // Paper - OBFHELPER + public Path getPath() { + return this.path; + } +@@ -341,6 +342,7 @@ public abstract class PathNavigation { + return !this.isDone(); + } + ++ public void stopPathfinding() { stop(); } // Paper - OBFHELPER + public void stop() { + this.path = null; + } +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Node.java b/src/main/java/net/minecraft/world/level/pathfinder/Node.java +index c1ac95d784935f5d3d827e2e390162f594991d2c..27b5d3d02d1f3aa048fefc3ef2222c8031e7661f 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/Node.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/Node.java +@@ -5,9 +5,9 @@ import net.minecraft.util.Mth; + + public class Node { + +- public final int x; +- public final int y; +- public final int z; ++ public final int x; public final int getX() { return x; } // Paper - OBFHELPER ++ public final int y; public final int getY() { return y; } // Paper - OBFHELPER ++ public final int z; public final int getZ() { return z; } // Paper - OBFHELPER + private final int hash; + public int heapIdx = -1; + public float g; +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java +index 0941bd177f65abfed3991267448df7df259d7f04..ddc9a9ececf44ce5524fd98a872e8a53cd7cc4f5 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java +@@ -16,9 +16,9 @@ public abstract class NodeEvaluator { + protected int entityWidth; + protected int entityHeight; + protected int entityDepth; +- protected boolean canPassDoors; +- protected boolean canOpenDoors; +- protected boolean canFloat; ++ protected boolean canPassDoors; public boolean shouldPassDoors() { return canPassDoors; } public void setShouldPassDoors(boolean b) { canPassDoors = b; } // Paper - obfhelper ++ protected boolean canOpenDoors; public boolean shouldOpenDoors() { return canOpenDoors; } public void setShouldOpenDoors(boolean b) { canOpenDoors = b; } // Paper - obfhelper ++ protected boolean canFloat; public boolean shouldFloat() { return canFloat; } public void setShouldFloat(boolean b) { canFloat = b; } // Paper - obfhelper + + public NodeEvaluator() {} + +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Path.java b/src/main/java/net/minecraft/world/level/pathfinder/Path.java +index 7bc0787634e3c5a6f76181b166793fb7591767e4..fd5b369b59669b893aaaec17aef1a526fd23d8c0 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/Path.java +@@ -8,13 +8,14 @@ import net.minecraft.world.phys.Vec3; + + public class Path { + +- private final List nodes; ++ private final List nodes; public List getPoints() { return nodes; } // Paper - OBFHELPER + private Node[] openSet = new Node[0]; + private Node[] closedSet = new Node[0]; +- private int nextNodeIndex; ++ private int nextNodeIndex; public int getNextIndex() { return this.nextNodeIndex; } // Paper - OBFHELPER + private final BlockPos target; + private final float distToTarget; + private final boolean reached; ++ public boolean hasNext() { return getNextIndex() < getPoints().size(); } // Paper + + public Path(List nodes, BlockPos target, boolean reachesTarget) { + this.nodes = nodes; +@@ -36,7 +37,7 @@ public class Path { + } + + @Nullable +- public Node getEndNode() { ++ public Node getFinalPoint() { return getEndNode(); } @Nullable public Node getEndNode() { // Paper - OBFHELPER + return !this.nodes.isEmpty() ? (Node) this.nodes.get(this.nodes.size() - 1) : null; + } + +@@ -84,7 +85,7 @@ public class Path { + return this.getEntityPosAtNode(entity, this.nextNodeIndex); + } + +- public BlockPos getNextNodePos() { ++ public BlockPos getNext() { return getNextNodePos(); } public BlockPos getNextNodePos() { // Paper - OBFHELPER + return ((Node) this.nodes.get(this.nextNodeIndex)).asBlockPos(); + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +index fd2c5a4e245647f51c1191991dc315b773ff73d4..b5fe55a77c8558cf2ea32689ff57911530df75f9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +@@ -11,8 +11,11 @@ import org.bukkit.loot.LootTable; + public abstract class CraftMob extends CraftLivingEntity implements Mob { + public CraftMob(CraftServer server, net.minecraft.world.entity.Mob entity) { + super(server, entity); ++ paperPathfinder = new com.destroystokyo.paper.entity.PaperPathfinder(entity); // Paper + } + ++ private final com.destroystokyo.paper.entity.PaperPathfinder paperPathfinder; // Paper ++ @Override public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { return paperPathfinder; } // Paper + @Override + public void setTarget(LivingEntity target) { + net.minecraft.world.entity.Mob entity = getHandle(); diff --git a/Remapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch b/Remapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch new file mode 100644 index 0000000000..9234ee7b61 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 10 Sep 2018 23:36:16 -0400 +Subject: [PATCH] Prevent chunk loading from Fluid Flowing + + +diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java +index 967123992ee86f13f4ca6e336eaf8cebed086a1a..7544bf227b1dded0f854cc1b30d246d120f65b20 100644 +--- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java ++++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java +@@ -175,7 +175,8 @@ public abstract class FlowingFluid extends Fluid { + Direction enumdirection = (Direction) entry.getKey(); + FluidState fluid1 = (FluidState) entry.getValue(); + BlockPos blockposition1 = pos.relative(enumdirection); +- BlockState iblockdata1 = world.getBlockState(blockposition1); ++ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); // Paper ++ if (iblockdata1 == null) continue; // Paper + + if (this.canSpreadTo(world, pos, blockState, enumdirection, blockposition1, iblockdata1, world.getFluidState(blockposition1), fluid1.getType())) { + // CraftBukkit start +@@ -202,7 +203,8 @@ public abstract class FlowingFluid extends Fluid { + while (iterator.hasNext()) { + Direction enumdirection = (Direction) iterator.next(); + BlockPos blockposition1 = pos.relative(enumdirection); +- BlockState iblockdata1 = world.getBlockState(blockposition1); ++ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); // Paper ++ if (iblockdata1 == null) continue; // Paper + FluidState fluid = iblockdata1.getFluidState(); + + if (fluid.getType().isSame((Fluid) this) && this.canPassThroughWall(enumdirection, (BlockGetter) world, pos, state, blockposition1, iblockdata1)) { +@@ -319,11 +321,18 @@ public abstract class FlowingFluid extends Fluid { + if (enumdirection1 != enumdirection) { + BlockPos blockposition2 = blockposition.relative(enumdirection1); + short short0 = getCacheKey(blockposition1, blockposition2); +- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (k) -> { +- BlockState iblockdata1 = world.getBlockState(blockposition2); ++ // Paper start - avoid loading chunks ++ Pair pair = short2objectmap.get(short0); ++ if (pair == null) { ++ BlockState iblockdatax = world.getTypeIfLoaded(blockposition2); ++ if (iblockdatax == null) { ++ continue; ++ } + +- return Pair.of(iblockdata1, iblockdata1.getFluidState()); +- }); ++ pair = Pair.of(iblockdatax, iblockdatax.getFluidState()); ++ short2objectmap.put(short0, pair); ++ } ++ // Paper end + BlockState iblockdata1 = (BlockState) pair.getFirst(); + FluidState fluid = (FluidState) pair.getSecond(); + +@@ -395,11 +404,16 @@ public abstract class FlowingFluid extends Fluid { + Direction enumdirection = (Direction) iterator.next(); + BlockPos blockposition1 = pos.relative(enumdirection); + short short0 = getCacheKey(pos, blockposition1); +- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (j) -> { +- BlockState iblockdata1 = world.getBlockState(blockposition1); +- +- return Pair.of(iblockdata1, iblockdata1.getFluidState()); +- }); ++ // Paper start ++ Pair pair = (Pair) short2objectmap.get(short0); ++ if (pair == null) { ++ BlockState iblockdatax = world.getTypeIfLoaded(blockposition1); ++ if (iblockdatax == null) continue; ++ ++ pair = Pair.of(iblockdatax, iblockdatax.getFluidState()); ++ short2objectmap.put(short0, pair); ++ } ++ // Paper end + BlockState iblockdata1 = (BlockState) pair.getFirst(); + FluidState fluid = (FluidState) pair.getSecond(); + FluidState fluid1 = this.getNewLiquid(world, blockposition1, iblockdata1); diff --git a/Remapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/Remapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch new file mode 100644 index 0000000000..30b7b72f6c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch @@ -0,0 +1,446 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Wed, 12 Sep 2018 18:53:55 +0300 +Subject: [PATCH] Implement an API for CanPlaceOn and CanDestroy NBT values + + +diff --git a/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java b/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java +index 9175c74c2119e7052d744db77badcae6be05f3b4..52f8ad848a22ddca856f6f256276ea59416f9664 100644 +--- a/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java ++++ b/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java +@@ -57,7 +57,7 @@ public class BlockStateParser { + private final boolean forTesting; + private final Map, Comparable> properties = Maps.newLinkedHashMap(); // CraftBukkit - stable + private final Map vagueProperties = Maps.newHashMap(); +- private ResourceLocation id = new ResourceLocation(""); ++ private ResourceLocation id = new ResourceLocation(""); public final ResourceLocation getBlockKey() { return this.id; } // Paper - OBFHELPER + private StateDefinition definition; + private BlockState state; + @Nullable +@@ -86,11 +86,13 @@ public class BlockStateParser { + return this.nbt; + } + ++ public final @Nullable ResourceLocation getTagKey() { return getTag(); } // Paper - OBFHELPER + @Nullable + public ResourceLocation getTag() { + return this.tag; + } + ++ public final BlockStateParser parse(boolean parseTile) throws CommandSyntaxException { return this.parse(parseTile); } // Paper - OBFHELPER + public BlockStateParser parse(boolean allowNbt) throws CommandSyntaxException { + this.suggestions = this::suggestBlockIdOrTag; + if (this.reader.canRead() && this.reader.peek() == '#') { +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba918f044e51 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -39,12 +39,14 @@ import java.util.logging.Level; + import java.util.logging.Logger; + import javax.annotation.Nonnull; + import javax.annotation.Nullable; ++import net.minecraft.commands.arguments.blocks.BlockStateParser; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtIo; + import net.minecraft.nbt.StringTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.TextComponent; ++import net.minecraft.resources.ResourceLocation; + import net.minecraft.world.item.BlockItem; + import org.apache.commons.codec.binary.Base64; + import org.apache.commons.lang.Validate; +@@ -83,6 +85,12 @@ import org.bukkit.persistence.PersistentDataContainer; + import static org.spigotmc.ValidateUtils.*; + // Spigot end + ++// Paper start ++import com.destroystokyo.paper.Namespaced; ++import com.destroystokyo.paper.NamespacedTag; ++import java.util.Collections; ++// Paper end ++ + /** + * Children must include the following: + * +@@ -266,6 +274,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + @Specific(Specific.To.NBT) + static final ItemMetaKey BLOCK_DATA = new ItemMetaKey("BlockStateTag"); + static final ItemMetaKey BUKKIT_CUSTOM_TAG = new ItemMetaKey("PublicBukkitValues"); ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ static final ItemMetaKey CAN_DESTROY = new ItemMetaKey("CanDestroy"); ++ static final ItemMetaKey CAN_PLACE_ON = new ItemMetaKey("CanPlaceOn"); ++ // Paper end + + // We store the raw original JSON representation of all text data. See SPIGOT-5063, SPIGOT-5656, SPIGOT-5304 + private String displayName; +@@ -279,6 +291,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + private int hideFlag; + private boolean unbreakable; + private int damage; ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ private Set placeableKeys = Sets.newHashSet(); ++ private Set destroyableKeys = Sets.newHashSet(); ++ // Paper end + + private static final Set HANDLED_TAGS = Sets.newHashSet(); + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); +@@ -316,6 +332,15 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + this.hideFlag = meta.hideFlag; + this.unbreakable = meta.unbreakable; + this.damage = meta.damage; ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (meta.hasPlaceableKeys()) { ++ this.placeableKeys = new java.util.HashSet<>(meta.placeableKeys); ++ } ++ ++ if (meta.hasDestroyableKeys()) { ++ this.destroyableKeys = new java.util.HashSet<>(meta.destroyableKeys); ++ } ++ // Paper end + this.unhandledTags.putAll(meta.unhandledTags); + this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw()); + +@@ -379,6 +404,31 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + persistentDataContainer.put(key, compound.get(key)); + } + } ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (tag.contains(CAN_DESTROY.NBT)) { ++ ListTag list = tag.getList(CAN_DESTROY.NBT, CraftMagicNumbers.NBT.TAG_STRING); ++ for (int i = 0; i < list.size(); i++) { ++ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); ++ if (namespaced == null) { ++ continue; ++ } ++ ++ this.destroyableKeys.add(namespaced); ++ } ++ } ++ ++ if (tag.contains(CAN_PLACE_ON.NBT)) { ++ ListTag list = tag.getList(CAN_PLACE_ON.NBT, CraftMagicNumbers.NBT.TAG_STRING); ++ for (int i = 0; i < list.size(); i++) { ++ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); ++ if (namespaced == null) { ++ continue; ++ } ++ ++ this.placeableKeys.add(namespaced); ++ } ++ } ++ // Paper end + + Set keys = tag.getAllKeys(); + for (String key : keys) { +@@ -517,6 +567,34 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + setDamage(damage); + } + ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ Iterable canPlaceOnSerialized = SerializableMeta.getObject(Iterable.class, map, CAN_PLACE_ON.BUKKIT, true); ++ if (canPlaceOnSerialized != null) { ++ for (Object canPlaceOnElement : canPlaceOnSerialized) { ++ String canPlaceOnRaw = (String) canPlaceOnElement; ++ Namespaced value = this.deserializeNamespaced(canPlaceOnRaw); ++ if (value == null) { ++ continue; ++ } ++ ++ this.placeableKeys.add(value); ++ } ++ } ++ ++ Iterable canDestroySerialized = SerializableMeta.getObject(Iterable.class, map, CAN_DESTROY.BUKKIT, true); ++ if (canDestroySerialized != null) { ++ for (Object canDestroyElement : canDestroySerialized) { ++ String canDestroyRaw = (String) canDestroyElement; ++ Namespaced value = this.deserializeNamespaced(canDestroyRaw); ++ if (value == null) { ++ continue; ++ } ++ ++ this.destroyableKeys.add(value); ++ } ++ } ++ // Paper end ++ + String internal = SerializableMeta.getString(map, "internal", true); + if (internal != null) { + ByteArrayInputStream buf = new ByteArrayInputStream(Base64.decodeBase64(internal)); +@@ -645,6 +723,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + if (hasDamage()) { + itemTag.putInt(DAMAGE.NBT, damage); + } ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (hasPlaceableKeys()) { ++ List items = this.placeableKeys.stream() ++ .map(this::serializeNamespaced) ++ .collect(java.util.stream.Collectors.toList()); ++ ++ itemTag.put(CAN_PLACE_ON.NBT, createNonComponentStringList(items)); ++ } ++ ++ if (hasDestroyableKeys()) { ++ List items = this.destroyableKeys.stream() ++ .map(this::serializeNamespaced) ++ .collect(java.util.stream.Collectors.toList()); ++ ++ itemTag.put(CAN_DESTROY.NBT, createNonComponentStringList(items)); ++ } ++ // Paper end + + for (Map.Entry e : unhandledTags.entrySet()) { + itemTag.put(e.getKey(), e.getValue()); +@@ -661,6 +756,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + } + ++ // Paper start ++ static ListTag createNonComponentStringList(List list) { ++ if (list == null || list.isEmpty()) { ++ return null; ++ } ++ ++ ListTag tagList = new ListTag(); ++ for (String value : list) { ++ tagList.add(StringTag.valueOf(value)); // Paper - NBTTagString.of(String str) ++ } ++ ++ return tagList; ++ } ++ // Paper end ++ + ListTag createStringList(List list) { + if (list == null) { + return null; +@@ -744,7 +854,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + + @Overridden + boolean isEmpty() { +- return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); ++ return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers() || hasPlaceableKeys() || hasDestroyableKeys()); // Paper - Implement an API for CanPlaceOn and CanDestroy NBT values + } + + // Paper start +@@ -1168,7 +1278,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + && (this.hideFlag == that.hideFlag) + && (this.isUnbreakable() == that.isUnbreakable()) + && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) +- && (this.version == that.version); ++ && (this.version == that.version) ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ && (this.hasPlaceableKeys() ? that.hasPlaceableKeys() && this.placeableKeys.equals(that.placeableKeys) : !that.hasPlaceableKeys()) ++ && (this.hasDestroyableKeys() ? that.hasDestroyableKeys() && this.destroyableKeys.equals(that.destroyableKeys) : !that.hasDestroyableKeys()); ++ // Paper end + } + + /** +@@ -1203,6 +1317,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + hash = 61 * hash + (hasDamage() ? this.damage : 0); + hash = 61 * hash + (hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); + hash = 61 * hash + version; ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ hash = 61 * hash + (hasPlaceableKeys() ? this.placeableKeys.hashCode() : 0); ++ hash = 61 * hash + (hasDestroyableKeys() ? this.destroyableKeys.hashCode() : 0); ++ // Paper end + return hash; + } + +@@ -1227,6 +1345,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + clone.unbreakable = this.unbreakable; + clone.damage = this.damage; + clone.version = this.version; ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (this.placeableKeys != null) { ++ clone.placeableKeys = Sets.newHashSet(this.placeableKeys); ++ } ++ if (this.destroyableKeys != null) { ++ clone.destroyableKeys = Sets.newHashSet(this.destroyableKeys); ++ } ++ // Paper end + return clone; + } catch (CloneNotSupportedException e) { + throw new Error(e); +@@ -1284,6 +1410,24 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + builder.put(DAMAGE.BUKKIT, damage); + } + ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (hasPlaceableKeys()) { ++ List cerealPlaceable = this.placeableKeys.stream() ++ .map(this::serializeNamespaced) ++ .collect(java.util.stream.Collectors.toList()); ++ ++ builder.put(CAN_PLACE_ON.BUKKIT, cerealPlaceable); ++ } ++ ++ if (hasDestroyableKeys()) { ++ List cerealDestroyable = this.destroyableKeys.stream() ++ .map(this::serializeNamespaced) ++ .collect(java.util.stream.Collectors.toList()); ++ ++ builder.put(CAN_DESTROY.BUKKIT, cerealDestroyable); ++ } ++ // Paper end ++ + final Map internalTags = new HashMap(unhandledTags); + serializeInternal(internalTags); + if (!internalTags.isEmpty()) { +@@ -1448,6 +1592,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + CraftMetaArmorStand.SHOW_ARMS.NBT, + CraftMetaArmorStand.SMALL.NBT, + CraftMetaArmorStand.MARKER.NBT, ++ CAN_DESTROY.NBT, ++ CAN_PLACE_ON.NBT, + // Paper end + CraftMetaCompass.LODESTONE_DIMENSION.NBT, + CraftMetaCompass.LODESTONE_POS.NBT, +@@ -1475,4 +1621,147 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + // Paper end + ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ @Override ++ @SuppressWarnings("deprecation") ++ public Set getCanDestroy() { ++ return !hasDestroyableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.destroyableKeys); ++ } ++ ++ @Override ++ @SuppressWarnings("deprecation") ++ public void setCanDestroy(Set canDestroy) { ++ Validate.notNull(canDestroy, "Cannot replace with null set!"); ++ legacyClearAndReplaceKeys(this.destroyableKeys, canDestroy); ++ } ++ ++ @Override ++ @SuppressWarnings("deprecation") ++ public Set getCanPlaceOn() { ++ return !hasPlaceableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.placeableKeys); ++ } ++ ++ @Override ++ @SuppressWarnings("deprecation") ++ public void setCanPlaceOn(Set canPlaceOn) { ++ Validate.notNull(canPlaceOn, "Cannot replace with null set!"); ++ legacyClearAndReplaceKeys(this.placeableKeys, canPlaceOn); ++ } ++ ++ @Override ++ public Set getDestroyableKeys() { ++ return !hasDestroyableKeys() ? Collections.emptySet() : Sets.newHashSet(this.destroyableKeys); ++ } ++ ++ @Override ++ public void setDestroyableKeys(Collection canDestroy) { ++ Validate.notNull(canDestroy, "Cannot replace with null collection!"); ++ Validate.isTrue(ofAcceptableType(canDestroy), "Can only use NamespacedKey or NamespacedTag objects!"); ++ this.destroyableKeys.clear(); ++ this.destroyableKeys.addAll(canDestroy); ++ } ++ ++ @Override ++ public Set getPlaceableKeys() { ++ return !hasPlaceableKeys() ? Collections.emptySet() : Sets.newHashSet(this.placeableKeys); ++ } ++ ++ @Override ++ public void setPlaceableKeys(Collection canPlaceOn) { ++ Validate.notNull(canPlaceOn, "Cannot replace with null collection!"); ++ Validate.isTrue(ofAcceptableType(canPlaceOn), "Can only use NamespacedKey or NamespacedTag objects!"); ++ this.placeableKeys.clear(); ++ this.placeableKeys.addAll(canPlaceOn); ++ } ++ ++ @Override ++ public boolean hasPlaceableKeys() { ++ return this.placeableKeys != null && !this.placeableKeys.isEmpty(); ++ } ++ ++ @Override ++ public boolean hasDestroyableKeys() { ++ return this.destroyableKeys != null && !this.destroyableKeys.isEmpty(); ++ } ++ ++ @Deprecated ++ private void legacyClearAndReplaceKeys(Collection toUpdate, Collection beingSet) { ++ if (beingSet.stream().anyMatch(Material::isLegacy)) { ++ throw new IllegalArgumentException("Set must not contain any legacy materials!"); ++ } ++ ++ toUpdate.clear(); ++ toUpdate.addAll(beingSet.stream().map(Material::getKey).collect(java.util.stream.Collectors.toSet())); ++ } ++ ++ @Deprecated ++ private Set legacyGetMatsFromKeys(Collection names) { ++ Set mats = Sets.newHashSet(); ++ for (Namespaced key : names) { ++ if (!(key instanceof org.bukkit.NamespacedKey)) { ++ continue; ++ } ++ ++ Material material = Material.matchMaterial(key.toString(), false); ++ if (material != null) { ++ mats.add(material); ++ } ++ } ++ ++ return mats; ++ } ++ ++ private @Nullable Namespaced deserializeNamespaced(String raw) { ++ boolean isTag = raw.length() > 0 && raw.codePointAt(0) == '#'; ++ BlockStateParser blockParser = new BlockStateParser(new com.mojang.brigadier.StringReader(raw), true); ++ try { ++ blockParser = blockParser.parse(false); ++ } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) { ++ e.printStackTrace(); ++ return null; ++ } ++ ++ ResourceLocation key; ++ if (isTag) { ++ key = blockParser.getTagKey(); ++ } else { ++ key = blockParser.getBlockKey(); ++ } ++ ++ if (key == null) { ++ return null; ++ } ++ ++ // don't DC the player if something slips through somehow ++ Namespaced resource = null; ++ try { ++ if (isTag) { ++ resource = new NamespacedTag(key.getNamespace(), key.getPath()); ++ } else { ++ resource = CraftNamespacedKey.fromMinecraft(key); ++ } ++ } catch (IllegalArgumentException ex) { ++ org.bukkit.Bukkit.getLogger().warning("Namespaced resource does not validate: " + key.toString()); ++ ex.printStackTrace(); ++ } ++ ++ return resource; ++ } ++ ++ private @Nonnull String serializeNamespaced(Namespaced resource) { ++ return resource.toString(); ++ } ++ ++ // not a fan of this ++ private boolean ofAcceptableType(Collection namespacedResources) { ++ ++ for (Namespaced resource : namespacedResources) { ++ if (!(resource instanceof org.bukkit.NamespacedKey || resource instanceof com.destroystokyo.paper.NamespacedTag)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/Remapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch new file mode 100644 index 0000000000..dff6bf782c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 10 Sep 2018 23:56:36 -0400 +Subject: [PATCH] Prevent Mob AI Rules from Loading Chunks + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +index 415661c61eb85ac57dd2ba81fb62f8d9df54153f..c9825bc1894904fab34bec8223adf8e343bb6623 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +@@ -29,11 +29,13 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + private final Block blockToRemove; + private final Mob removerMob; + private int ticksSinceReachedGoal; ++ private Level world; // Paper + + public RemoveBlockGoal(Block targetBlock, PathfinderMob mob, double speed, int maxYDifference) { + super(mob, speed, 24, maxYDifference); + this.blockToRemove = targetBlock; + this.removerMob = mob; ++ this.world = mob.level; // Paper + } + + @Override +@@ -131,7 +133,9 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + + @Nullable + private BlockPos getPosWithBlock(BlockPos pos, BlockGetter world) { +- if (world.getBlockState(pos).is(this.blockToRemove)) { ++ Block block = world.getBlockIfLoaded(pos); // Paper ++ if (block == null) return null; // Paper ++ if (block.is(this.blockToRemove)) { // Paper + return pos; + } else { + BlockPos[] ablockposition = new BlockPos[]{pos.below(), pos.west(), pos.east(), pos.north(), pos.south(), pos.below().below()}; +@@ -141,7 +145,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + for (int j = 0; j < i; ++j) { + BlockPos blockposition1 = ablockposition1[j]; + +- if (world.getBlockState(blockposition1).is(this.blockToRemove)) { ++ if (world.getBlockIfLoaded(blockposition1).is(this.blockToRemove)) { // Paper + return blockposition1; + } + } +@@ -152,7 +156,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + + @Override + protected boolean isValidTarget(LevelReader world, BlockPos pos) { +- ChunkAccess ichunkaccess = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, false); ++ ChunkAccess ichunkaccess = world.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4); // Paper + + return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).is(this.blockToRemove) && ichunkaccess.getBlockState(pos.above()).isAir() && ichunkaccess.getBlockState(pos.above(2)).isAir(); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java b/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java +index 246cbddb23781e323d022db2fbeef72c9eeaad2b..55d484fd4774cfad8f8ba3263b387243540e31b1 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java ++++ b/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java +@@ -13,6 +13,7 @@ import net.minecraft.util.Mth; + import net.minecraft.world.entity.PathfinderMob; + import net.minecraft.world.entity.ai.navigation.PathNavigation; + import net.minecraft.world.level.BlockGetter; ++import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; + import net.minecraft.world.phys.Vec3; +@@ -128,6 +129,7 @@ public class RandomPos { + } + + blockposition2 = new BlockPos((double) k1 + mob.getX(), (double) l1 + mob.getY(), (double) i2 + mob.getZ()); ++ if (!mob.level.hasChunkAt(blockposition2)) continue; // Paper + if (blockposition2.getY() >= 0 && blockposition2.getY() <= mob.level.getMaxBuildHeight() && (!flag3 || mob.isWithinRestriction(blockposition2)) && (!validPositionsOnly || navigationabstract.isStableDestination(blockposition2))) { + if (aboveGround) { + blockposition2 = moveUpToAboveSolid(blockposition2, random.nextInt(distanceAboveGroundRange + 1) + minDistanceAboveGround, mob.level.getMaxBuildHeight(), (blockposition3) -> { +@@ -135,7 +137,8 @@ public class RandomPos { + }); + } + +- if (notInWater || !mob.level.getFluidState(blockposition2).is((Tag) FluidTags.WATER)) { ++ FluidState fluid = mob.level.getFluidIfLoaded(blockposition2); // Paper ++ if (notInWater || (fluid != null && !fluid.is((Tag) FluidTags.WATER))) { // Paper + BlockPathTypes pathtype = WalkNodeEvaluator.getBlockPathTypeStatic((BlockGetter) mob.level, blockposition2.mutable()); + + if (mob.getPathfindingMalus(pathtype) == 0.0F) { diff --git a/Remapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch b/Remapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch new file mode 100644 index 0000000000..759560db06 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 12 Sep 2018 21:12:57 -0400 +Subject: [PATCH] Prevent mob spawning from loading/generating chunks + +also prevents if out of world border bounds + +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index b90a275a0dc2913809ce16659eed445501e486de..e23875ae07c23fed1161ea070e63bbc3a30168a0 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -174,9 +174,9 @@ public final class NaturalSpawner { + StructureFeatureManager structuremanager = world.structureFeatureManager(); + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); + int i = pos.getY(); +- BlockState iblockdata = chunk.getBlockState(pos); ++ BlockState iblockdata = world.getTypeIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn + +- if (!iblockdata.isRedstoneConductor(chunk, pos)) { ++ if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn + BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + int j = 0; + int k = 0; +@@ -205,7 +205,7 @@ public final class NaturalSpawner { + if (entityhuman != null) { + double d2 = entityhuman.distanceToSqr(d0, (double) i, d1); + +- if (isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2)) { ++ if (isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2) && world.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn + if (biomesettingsmobs_c == null) { + biomesettingsmobs_c = getRandomSpawnMobAt(world, structuremanager, chunkgenerator, group, world.random, (BlockPos) blockposition_mutableblockposition); + if (biomesettingsmobs_c == null) { diff --git a/Remapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/Remapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch new file mode 100644 index 0000000000..db7b1e6312 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch @@ -0,0 +1,97 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 12 Sep 2018 21:47:01 -0400 +Subject: [PATCH] Optimize Biome Mob Lookups for Mob Spawning + +Uses an EnumMap as well as a Set paired List for O(1) contains calls. + +diff --git a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java +index 58ee27a994b4cd845b8bb28e80cc2102c860f097..528f42c63a1186b8827bfe7cf6193e14da938cb3 100644 +--- a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java ++++ b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java +@@ -30,19 +30,28 @@ public class MobSpawnSettings { + }, (enumcreaturetype) -> { + return ImmutableList.of(); + })), ImmutableMap.of(), false); ++ // Paper start- decompile error workaround ++ private static class bProxy extends MobSpawnSettings.MobSpawnCost { ++ private bProxy(double gravityLimit, double mass) { ++ super(gravityLimit, mass); ++ } ++ } ++ private static class cProxy extends MobSpawnSettings.SpawnerData { ++ public cProxy(EntityType type, int weight, int minGroupSize, int maxGroupSize) { ++ super(type, weight, minGroupSize, maxGroupSize); ++ } ++ }; ++ // Paper end + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { +- return biomesettingsmobs.d; ++ RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { // Paper - add type to builder ++ return biomesettingsmobs.creatureGenerationProbability; + }); +- Codec codec = MobCategory.CODEC; +- Codec codec1 = BiomeSettingsMobs.c.b.listOf(); +- Logger logger = MobSpawnSettings.LOGGER; +- +- logger.getClass(); +- return instance.group(recordcodecbuilder, Codec.simpleMap(codec, codec1.promotePartial(Util.prefix("Spawn data: ", logger::error)), StringRepresentable.keys(MobCategory.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { +- return biomesettingsmobs.e; +- }), Codec.simpleMap(Registry.ENTITY_TYPE, BiomeSettingsMobs.b.a, Registry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { +- return biomesettingsmobs.f; ++ // Paper - remove unused vars ++ ++ return instance.group(recordcodecbuilder, Codec.simpleMap(MobCategory.CODEC, cProxy.CODEC.listOf().promotePartial(Util.prefix("Spawn data: ", MobSpawnSettings.LOGGER::error)), StringRepresentable.keys(MobCategory.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { // Paper - inline codec, cProxy, LOGGER ++ return biomesettingsmobs.spawners; ++ }), Codec.simpleMap(Registry.ENTITY_TYPE, bProxy.CODEC, Registry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { // Paper - decompile error - bProxy ++ return biomesettingsmobs.mobSpawnCosts; + }), Codec.BOOL.fieldOf("player_spawn_friendly").orElse(false).forGetter(MobSpawnSettings::playerSpawnFriendly)).apply(instance, MobSpawnSettings::new); + }); + private final float creatureGenerationProbability; +@@ -76,11 +85,43 @@ public class MobSpawnSettings { + + public static class Builder { + +- private final Map> spawners = (Map) Stream.of(MobCategory.values()).collect(ImmutableMap.toImmutableMap((enumcreaturetype) -> { ++ // Paper start - keep track of data in a pair set to give O(1) contains calls - we have to hook removals incase plugins mess with it ++ public static class MobList extends java.util.ArrayList { ++ java.util.Set biomes = new java.util.HashSet<>(); ++ ++ @Override ++ public boolean contains(Object o) { ++ return biomes.contains(o); ++ } ++ ++ @Override ++ public boolean add(MobSpawnSettings.SpawnerData BiomeSettingsMobs) { ++ biomes.add(BiomeSettingsMobs); ++ return super.add(BiomeSettingsMobs); ++ } ++ ++ @Override ++ public MobSpawnSettings.SpawnerData remove(int index) { ++ MobSpawnSettings.SpawnerData removed = super.remove(index); ++ if (removed != null) { ++ biomes.remove(removed); ++ } ++ return removed; ++ } ++ ++ @Override ++ public void clear() { ++ biomes.clear(); ++ super.clear(); ++ } ++ } ++ // use toImmutableEnumMap collector ++ private final Map> spawners = (Map) Stream.of(MobCategory.values()).collect(Maps.toImmutableEnumMap((enumcreaturetype) -> { + return enumcreaturetype; + }, (enumcreaturetype) -> { +- return Lists.newArrayList(); ++ return new MobList(); // Use MobList instead of ArrayList + })); ++ // Paper end + private final Map, MobSpawnSettings.MobSpawnCost> mobSpawnCosts = Maps.newLinkedHashMap(); + private float creatureGenerationProbability = 0.1F; + private boolean playerCanSpawn; diff --git a/Remapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch b/Remapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch new file mode 100644 index 0000000000..4b104b38ec --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tassu +Date: Thu, 13 Sep 2018 08:45:21 +0300 +Subject: [PATCH] Implement furnace cook speed multiplier API + +Signed-off-by: Tassu + +Fixed an issue where a furnace's cook-speed multiplier rounds down +to the nearest Integer when updating its current cook time. + +Modified by: Eric Su + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 8c55c1d88ef2e20e82bcdae0b9b3d381e562051f..4126a36dbc7750108a883f0be14dcb0d2e6d7ae8 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -38,6 +38,7 @@ import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.Vec3; + // CraftBukkit start ++import java.util.List; + import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.craftbukkit.inventory.CraftItemStack; +@@ -56,6 +57,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + protected NonNullList items; + public int litTime; + private int litDuration; ++ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API + public int cookingProgress; + public int cookingTotalTime; + protected final ContainerData dataAccess; +@@ -256,6 +258,11 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + this.recipesUsed.put(new ResourceLocation(s), nbttagcompound1.getInt(s)); + } + ++ // Paper start - cook speed API ++ if (tag.contains("Paper.CookSpeedMultiplier")) { ++ this.cookSpeedMultiplier = tag.getDouble("Paper.CookSpeedMultiplier"); ++ } ++ // Paper end + } + + @Override +@@ -264,6 +271,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + tag.putShort("BurnTime", (short) this.litTime); + tag.putShort("CookTime", (short) this.cookingProgress); + tag.putShort("CookTimeTotal", (short) this.cookingTotalTime); ++ tag.putDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API + ContainerHelper.saveAllItems(tag, this.items); + CompoundTag nbttagcompound1 = new CompoundTag(); + +@@ -324,7 +332,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + + if (this.isLit() && this.canBurn(irecipe)) { + ++this.cookingProgress; +- if (this.cookingProgress == this.cookingTotalTime) { ++ if (this.cookingProgress >= this.cookingTotalTime) { // Paper - cook speed multiplier API + this.cookingProgress = 0; + this.cookingTotalTime = this.getTotalCookTime(); + this.burn(irecipe); +@@ -424,9 +432,13 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + } + } + +- protected int getTotalCookTime() { +- return (this.hasLevel()) ? (Integer) this.level.getRecipeManager().getRecipeFor((RecipeType) this.recipeType, this, this.level).map(AbstractCookingRecipe::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail ++ // Paper begin - Expose this function so CraftFurnace can correctly scale the total cooking time to a new multiplier ++ public int getTotalCookTime() { ++ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */ ++ int cookTime = (this.hasLevel()) ? (Integer) this.level.getRecipeManager().getRecipeFor((RecipeType) this.recipeType, this, this.level).map(AbstractCookingRecipe::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail ++ return (int) Math.ceil (cookTime / this.cookSpeedMultiplier); + } ++ // Paper end + + public static boolean isFuel(ItemStack stack) { + return getFuel().containsKey(stack.getItem()); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java +index 5028a6388f95a14df8d1590cddd7414d8de5bf78..a69785c331c6cee34ba4e93f47865ab8e29ec9b8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java +@@ -63,4 +63,20 @@ public abstract class CraftFurnace extends + public void setCookTimeTotal(int cookTimeTotal) { + this.getSnapshot().cookingTotalTime = cookTimeTotal; + } ++ ++ // Paper start - cook speed multiplier API ++ @Override ++ public double getCookSpeedMultiplier() { ++ return this.getSnapshot().cookSpeedMultiplier; ++ } ++ ++ @Override ++ public void setCookSpeedMultiplier(double multiplier) { ++ com.google.common.base.Preconditions.checkArgument(multiplier >= 0, "Furnace speed multiplier cannot be negative"); ++ com.google.common.base.Preconditions.checkArgument(multiplier <= 200, "Furnace speed multiplier cannot more than 200"); ++ T snapshot = this.getSnapshot(); ++ snapshot.cookSpeedMultiplier = multiplier; ++ snapshot.cookingTotalTime = snapshot.getTotalCookTime(); // Update the snapshot's current total cook time to scale with the newly set multiplier ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch b/Remapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch new file mode 100644 index 0000000000..cb777e4c22 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Tue, 18 Sep 2018 23:53:23 +0100 +Subject: [PATCH] PreSpawnerSpawnEvent + +This adds a separate event before an entity is spawned by a spawner +which contains the location of the spawner too similarly to how the +SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for +spawners. + +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index ac572eba10a7239d71dfae060f623b076d4252ce..1ce675d0d24ceb5724f5ac2d8f671e38f2735f74 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -132,11 +132,11 @@ public abstract class BaseSpawner { + + org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); + if (type != null) { +- com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; +- event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent( + MCUtil.toLocation(world, d3, d4, d5), + type, +- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER ++ MCUtil.toLocation(world, blockposition) + ); + if (!event.callEvent()) { + flag = true; diff --git a/Remapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch b/Remapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch new file mode 100644 index 0000000000..a418dc54d3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 22 Sep 2018 15:56:59 -0400 +Subject: [PATCH] Catch JsonParseException in Entity and TE names + +As a result, data that no longer parses correctly will not crash the server +instead just logging the exception and continuing (and in most cases should +fix the data) + +Player data is fixed pretty much immediately but some block data (like +Shulkers) may need to be changed in order for it to re-save properly + +No more crashing though. + +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 68c3f069f8f832ab3d146748348aded69b5ad823..1fecc81b25109592907623741225a6222a8c5ccc 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -7,6 +7,8 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; + import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.chat.Component; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkPos; +@@ -514,4 +516,19 @@ public final class MCUtil { + return null; + } + } ++ ++ @Nullable ++ public static Component getBaseComponentFromNbt(String key, CompoundTag compound) { ++ if (!compound.contains(key)) { ++ return null; ++ } ++ String string = compound.getString(key); ++ try { ++ return Component.Serializer.jsonToComponent(string); ++ } catch (com.google.gson.JsonParseException e) { ++ org.bukkit.Bukkit.getLogger().warning("Unable to parse " + key + " from " + compound +": " + e.getMessage()); ++ } ++ ++ return null; ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +index 9ad077259563a3d960d32a59d4b6fc3cfbe3440c..00dc4cd436023b946d7005f17a7ba983a4bbdfb6 100644 +--- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java ++++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +@@ -12,6 +12,7 @@ import net.minecraft.commands.CommandSourceStack; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TextComponent; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.StringUtil; +@@ -72,7 +73,7 @@ public abstract class BaseCommandBlock implements CommandSource { + this.command = tag.getString("Command"); + this.successCount = tag.getInt("SuccessCount"); + if (tag.contains("CustomName", 8)) { +- this.setName(Component.Serializer.fromJson(tag.getString("CustomName"))); ++ this.setName(MCUtil.getBaseComponentFromNbt("CustomName", tag)); // Paper - Catch ParseException + } + + if (tag.contains("TrackOutput", 1)) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java +index 2e3ec85e7bd1c375db0662dba2617d8924dbd2a6..2c885be67b9c992b96f5caf78130d46abb455ceb 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java +@@ -9,6 +9,7 @@ import net.minecraft.nbt.ListTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; ++import net.minecraft.server.MCUtil; + import net.minecraft.world.Nameable; + import net.minecraft.world.item.DyeColor; + import net.minecraft.world.item.ItemStack; +@@ -70,7 +71,7 @@ public class BannerBlockEntity extends BlockEntity implements Nameable { + public void load(BlockState state, CompoundTag tag) { + super.load(state, tag); + if (tag.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(tag.getString("CustomName")); ++ this.name = MCUtil.getBaseComponentFromNbt("CustomName", tag); // Paper - Catch ParseException + } + + if (this.hasLevel()) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +index a7358274fe367a113b304a5ce332b8dcf721b7af..2b420109e9bed184aaa4ffbcee666b4c325c5a28 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +@@ -4,6 +4,7 @@ import javax.annotation.Nullable; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.Container; +@@ -30,7 +31,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co + super.load(state, tag); + this.lockKey = LockCode.fromTag(tag); + if (tag.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(tag.getString("CustomName")); ++ this.name = MCUtil.getBaseComponentFromNbt("CustomName", tag); // Paper - Catch ParseException + } + + } diff --git a/Remapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch b/Remapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch new file mode 100644 index 0000000000..a2b0c4fa76 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Sep 2018 20:59:53 -0500 +Subject: [PATCH] Honor EntityAgeable.ageLock + + +diff --git a/src/main/java/net/minecraft/world/entity/AgableMob.java b/src/main/java/net/minecraft/world/entity/AgableMob.java +index d7c19e5607bcf92c874b3656c2742f4c84dceb12..354311dc541588212a2eacba38e60c7e34aa4c2b 100644 +--- a/src/main/java/net/minecraft/world/entity/AgableMob.java ++++ b/src/main/java/net/minecraft/world/entity/AgableMob.java +@@ -82,6 +82,7 @@ public abstract class AgableMob extends PathfinderMob { + } + + public void ageUp(int age, boolean overGrow) { ++ if (ageLocked) return; // Paper - GH-1459 + int j = this.getAge(); + int k = j; + diff --git a/Remapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch b/Remapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch new file mode 100644 index 0000000000..354aa4e66c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 2 Oct 2018 09:57:50 +0100 +Subject: [PATCH] Configurable connection throttle kick message + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 62621562137cba4804f0465c58d25ca2786328e5..7178b37f7978c7e9031a22726005c5099fd78fe0 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -281,6 +281,11 @@ public class PaperConfig { + authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); + } + ++ public static String connectionThrottleKickMessage = "Connection throttled! Please wait before reconnecting."; ++ private static void connectionThrottleKickMessage() { ++ connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); ++ } ++ + private static void savePlayerData() { + Object val = config.get("settings.save-player-data"); + if (val instanceof Boolean) { +diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 45c9dc9c2a580a5cd57fd4e891fbaa2b1336f5c5..6f98be2b9b00f71dd041e7511c70166fdecf0749 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -50,7 +50,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + synchronized (throttleTracker) { + if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { + throttleTracker.put(address, currentTime); +- TranslatableComponent chatmessage = new TranslatableComponent("Connection throttled! Please wait before reconnecting."); ++ TranslatableComponent chatmessage = new TranslatableComponent(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message + this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); + this.connection.disconnect(chatmessage); + return; diff --git a/Remapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch b/Remapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch new file mode 100644 index 0000000000..06025aa8c5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch @@ -0,0 +1,184 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 3 Oct 2018 20:09:18 -0400 +Subject: [PATCH] Hook into CB plugin rewrites + +Allows us to do fun stuff like rewrite the OBC util fastutil location to +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 45cbdcfc131bbc0e2bf23cc30a572df72eecd51c..49e5a86c223f1b28ce7da6ced276b2f880777856 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java +@@ -6,7 +6,9 @@ import java.io.FileOutputStream; + import java.io.InputStream; + import java.util.Arrays; + import java.util.Enumeration; ++import java.util.HashMap; + import java.util.HashSet; ++import java.util.Map; + import java.util.Set; + import java.util.jar.JarEntry; + import java.util.jar.JarFile; +@@ -20,10 +22,15 @@ import org.bukkit.plugin.AuthorNagException; + import org.objectweb.asm.ClassReader; + import org.objectweb.asm.ClassVisitor; + import org.objectweb.asm.ClassWriter; ++import org.objectweb.asm.FieldVisitor; ++import org.objectweb.asm.Handle; ++import org.objectweb.asm.Label; + import org.objectweb.asm.MethodVisitor; + import org.objectweb.asm.Opcodes; + import org.objectweb.asm.Type; + ++import javax.annotation.Nonnull; ++ + /** + * This file is imported from Commodore. + * +@@ -46,6 +53,42 @@ public class Commodore + "org/bukkit/inventory/ItemStack (I)V setTypeId" + ) ); + ++ // Paper start - Plugin rewrites ++ private static final Map SEARCH_AND_REMOVE = initReplacementsMap(); ++ private static Map initReplacementsMap() ++ { ++ Map getAndRemove = new HashMap<>(); ++ // Be wary of maven shade's relocations ++ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/libs/it/unimi/dsi/fastutil/" ), "org/bukkit/".concat( "craftbukkit/libs/" ) ); // Remap fastutil to our location ++ ++ if ( Boolean.getBoolean( "debug.rewriteForIde" ) ) ++ { ++ // unversion incoming calls for pre-relocate debug work ++ final String NMS_REVISION_PACKAGE = "v1_16_R3/"; ++ ++ getAndRemove.put( "net/minecraft/".concat( "server/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); ++ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); ++ } ++ ++ return getAndRemove; ++ } ++ ++ @Nonnull ++ private static String getOriginalOrRewrite(@Nonnull String original) ++ { ++ String rewrite = null; ++ for ( Map.Entry entry : SEARCH_AND_REMOVE.entrySet() ) ++ { ++ if ( original.contains( entry.getKey() ) ) ++ { ++ rewrite = original.replace( entry.getValue(), "" ); ++ } ++ } ++ ++ return rewrite != null ? rewrite : original; ++ } ++ // Paper end ++ + public static void main(String[] args) + { + OptionParser parser = new OptionParser(); +@@ -130,15 +173,86 @@ public class Commodore + + cr.accept( new ClassVisitor( Opcodes.ASM9, cw ) + { ++ // Paper start - Rewrite plugins ++ @Override ++ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) ++ { ++ desc = getOriginalOrRewrite( desc ); ++ if ( signature != null ) { ++ signature = getOriginalOrRewrite( signature ); ++ } ++ ++ return super.visitField( access, name, desc, signature, value) ; ++ } ++ // Paper end ++ + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) + { + return new MethodVisitor( api, super.visitMethod( access, name, desc, signature, exceptions ) ) + { ++ // Paper start - Plugin rewrites ++ @Override ++ public void visitInvokeDynamicInsn(String name, String desc, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) ++ { ++ // Paper start - Rewrite plugins ++ name = getOriginalOrRewrite( name ); ++ if ( desc != null ) ++ { ++ desc = getOriginalOrRewrite( desc ); ++ } ++ // Paper end ++ ++ super.visitInvokeDynamicInsn( name, desc, bootstrapMethodHandle, bootstrapMethodArguments ); ++ } ++ ++ @Override ++ public void visitTypeInsn(int opcode, String type) ++ { ++ type = getOriginalOrRewrite( type ); ++ ++ super.visitTypeInsn( opcode, type ); ++ } ++ ++ @Override ++ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { ++ for ( int i = 0; i < local.length; i++ ) ++ { ++ if ( !( local[i] instanceof String ) ) { continue; } ++ ++ local[i] = getOriginalOrRewrite( (String) local[i] ); ++ } ++ ++ for ( int i = 0; i < stack.length; i++ ) ++ { ++ if ( !( stack[i] instanceof String ) ) { continue; } ++ ++ stack[i] = getOriginalOrRewrite( (String) stack[i] ); ++ } ++ ++ super.visitFrame( type, nLocal, local, nStack, stack ); ++ } ++ ++ @Override ++ public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) ++ { ++ descriptor = getOriginalOrRewrite( descriptor ); ++ ++ super.visitLocalVariable( name, descriptor, signature, start, end, index ); ++ } ++ // Paper end + + @Override + public void visitFieldInsn(int opcode, String owner, String name, String desc) + { ++ // Paper start - Rewrite plugins ++ owner = getOriginalOrRewrite( owner ); ++ if ( desc != null ) ++ { ++ desc = getOriginalOrRewrite( desc ); ++ } ++ // Paper end ++ + if ( owner.equals( "org/bukkit/block/Biome" ) ) + { + switch ( name ) +@@ -270,6 +384,14 @@ public class Commodore + return; + } + ++ // Paper start - Rewrite plugins ++ owner = getOriginalOrRewrite( owner) ; ++ if (desc != null) ++ { ++ desc = getOriginalOrRewrite(desc); ++ } ++ // Paper end ++ + if ( modern ) + { + if ( owner.equals( "org/bukkit/Material" ) ) diff --git a/Remapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch b/Remapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch new file mode 100644 index 0000000000..ee472ab644 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 6 Oct 2018 21:47:44 -0500 +Subject: [PATCH] Allow setting the vex's summoner + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java +index ec4f6d96360e759ffc19de838fdbf3027164a424..a4be2bddc5f51601d419647a280c89f7101371f2 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vex.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java +@@ -165,6 +165,7 @@ public class Vex extends Monster { + this.setVexFlag(1, charging); + } + ++ public void setOwner(Mob entityinsentient) { setOwner(entityinsentient); } // Paper - OBFHELPER + public void setOwner(Mob owner) { + this.owner = owner; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +index 56bec4350f36a94d4dfa71a234872a795c2dcb3f..07c470f8b049bea930337abc1cc87f4669d2f11a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +@@ -20,6 +20,10 @@ public class CraftVex extends CraftMonster implements Vex { + net.minecraft.world.entity.Mob owner = getHandle().getOwner(); + return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; + } ++ ++ public void setSummoner(org.bukkit.entity.Mob summoner) { ++ getHandle().setOwner(summoner == null ? null : ((CraftMob) summoner).getHandle()); ++ } + // Paper end + + @Override diff --git a/Remapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch b/Remapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch new file mode 100644 index 0000000000..32037c620c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 7 Oct 2018 00:54:21 -0500 +Subject: [PATCH] Add sun related API + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index f3690ea49cf90c816b8b3554b47d6f2d9dfbe016..29a2eeee9f2011ed6fcc44f19041f616decfdb38 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -1595,6 +1595,7 @@ public abstract class Mob extends LivingEntity { + + } + ++ public boolean isInDaylight() { return this.isSunBurnTick(); } // Paper - OBFHELPER + protected boolean isSunBurnTick() { + if (this.level.isDay() && !this.level.isClientSide) { + float f = this.getBrightness(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 57a2af56b53567371fdb6d0a55866e1e4e37cf3b..7b5abccac9793811bd56340c8f9d23806e832365 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -847,6 +847,13 @@ public class CraftWorld implements World { + } + } + ++ // Paper start ++ @Override ++ public boolean isDayTime() { ++ return getHandle().isDay(); ++ } ++ // Paper end ++ + @Override + public long getGameTime() { + return world.levelData.getGameTime(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +index b5fe55a77c8558cf2ea32689ff57911530df75f9..1e3a0851c75d8067d2699f00bb3f6621d1d739d8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +@@ -77,4 +77,11 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { + public long getSeed() { + return getHandle().lootTableSeed; + } ++ ++ // Paper start ++ @Override ++ public boolean isInDaylight() { ++ return getHandle().isInDaylight(); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0295-Turtle-API.patch b/Remapped-Spigot-Server-Patches/0295-Turtle-API.patch new file mode 100644 index 0000000000..042449088a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0295-Turtle-API.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 29 Sep 2018 16:08:23 -0500 +Subject: [PATCH] Turtle API + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +index 4584fad16a65f06e77e97a0804d88dbe83f7c5c1..c8680e795deeb68e0662eac7c760a103d1c767b4 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +@@ -14,7 +14,7 @@ public abstract class MoveToBlockGoal extends Goal { + protected int nextStartTick; + protected int tryTicks; + private int maxStayTicks; +- protected BlockPos blockPos; ++ protected BlockPos blockPos;public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER + private boolean reachedTarget; + private final int searchRange; + private final int verticalSearchRange; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +index c54f4b83b9f2fdb15ddb363be0a179a05eb3693b..42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +@@ -14,6 +14,7 @@ import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; +@@ -93,7 +94,7 @@ public class Turtle extends Animal { + this.entityData.set(Turtle.HOME_POS, pos); + } + +- private BlockPos getHomePos() { ++ public BlockPos getHomePos() { // Paper - public + return (BlockPos) this.entityData.get(Turtle.HOME_POS); + } + +@@ -109,31 +110,37 @@ public class Turtle extends Animal { + return (Boolean) this.entityData.get(Turtle.HAS_EGG); + } + +- private void setHasEgg(boolean hasEgg) { ++ public void setHasEgg(boolean hasEgg) { // Paper + this.entityData.set(Turtle.HAS_EGG, hasEgg); + } + ++ public final boolean isDigging() { return this.isLayingEgg(); } // Paper - OBFHELPER + public boolean isLayingEgg() { + return (Boolean) this.entityData.get(Turtle.LAYING_EGG); + } + ++ public final void setDigging(boolean digging) { this.setLayingEgg(digging); } // Paper - OBFHELPER + private void setLayingEgg(boolean diggingSand) { + this.layEggCounter = diggingSand ? 1 : 0; + this.entityData.set(Turtle.LAYING_EGG, diggingSand); + } + ++ public final boolean isGoingHome() { return this.isGoingHome(); } // Paper - OBFHELPER + private boolean isGoingHome() { + return (Boolean) this.entityData.get(Turtle.GOING_HOME); + } + ++ public final void setGoingHome(boolean goingHome) { this.setGoingHome(goingHome); } // Paper - OBFHELPER + private void setGoingHome(boolean landBound) { + this.entityData.set(Turtle.GOING_HOME, landBound); + } + ++ public final boolean isTravelling() { return this.isTravelling(); } // Paper - OBFHELPER + private boolean isTravelling() { + return (Boolean) this.entityData.get(Turtle.TRAVELLING); + } + ++ public final void setTravelling(boolean travelling) { this.setTravelling(travelling); } // Paper - OBFHELPER + private void setTravelling(boolean travelling) { + this.entityData.set(Turtle.TRAVELLING, travelling); + } +@@ -500,14 +507,17 @@ public class Turtle extends Animal { + + if (!this.turtle.isInWater() && this.isReachedTarget()) { + if (this.turtle.layEggCounter < 1) { +- this.turtle.setLayingEgg(true); ++ this.turtle.setDigging(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), MCUtil.toLocation(this.turtle.level, this.getTargetPosition())).callEvent()); // Paper + } else if (this.turtle.layEggCounter > 200) { + Level world = this.turtle.level; + + // CraftBukkit start +- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1)).isCancelled()) { ++ // Paper start ++ int eggCount = this.turtle.random.nextInt(4) + 1; ++ com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), MCUtil.toLocation(this.turtle.level, this.blockPos.above()), eggCount); ++ if (layEggEvent.callEvent() && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount())).isCancelled()) { + world.playSound((Player) null, blockposition, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); +- world.setBlock(this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1), 3); ++ world.setBlock(this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()), 3); + } + // CraftBukkit end + this.turtle.setHasEgg(false); +@@ -636,7 +646,7 @@ public class Turtle extends Animal { + + @Override + public boolean canUse() { +- return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(700) != 0 ? false : !this.turtle.getHomePos().closerThan((Position) this.turtle.position(), 64.0D))); ++ return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(700) != 0 ? false : !this.turtle.getHomePos().closerThan((Position) this.turtle.position(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity()).callEvent(); // Paper + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java +index ed08089f21c8958fc9fc7e6e73a2b6ff9108242c..e50f6051baf34981707adce56ab2d3e1f341fb4c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java +@@ -24,4 +24,36 @@ public class CraftTurtle extends CraftAnimals implements Turtle { + public EntityType getType() { + return EntityType.TURTLE; + } ++ ++ // Paper start ++ @Override ++ public org.bukkit.Location getHome() { ++ return net.minecraft.server.MCUtil.toLocation(getHandle().level, getHandle().getHomePos()); ++ } ++ ++ @Override ++ public void setHome(org.bukkit.Location location) { ++ getHandle().setHomePos(net.minecraft.server.MCUtil.toBlockPosition(location)); ++ } ++ ++ @Override ++ public boolean isGoingHome() { ++ return getHandle().isGoingHome(); ++ } ++ ++ @Override ++ public boolean isDigging() { ++ return getHandle().isDigging(); ++ } ++ ++ @Override ++ public boolean hasEgg() { ++ return getHandle().hasEgg(); ++ } ++ ++ @Override ++ public void setHasEgg(boolean hasEgg) { ++ getHandle().setHasEgg(hasEgg); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/Remapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch new file mode 100644 index 0000000000..685d458bbb --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 17 Oct 2018 19:17:27 -0400 +Subject: [PATCH] MC-50319: Check other worlds for shooter of projectiles + +Say a player shoots an arrow through a nether portal, the game +would lose the shooter for determining things such as Player Kills, +because the entity is in another world. + +If the projectile fails to find the shooter in the current world, check +other worlds. + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index d1dd173c11d751b15c3afd4309e386931fd9cf8d..d385fb6eee5000951c350b6ced5669dc3dcce725 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -44,7 +44,18 @@ public abstract class Projectile extends Entity { + + @Nullable + public Entity getOwner() { +- return this.ownerUUID != null && this.level instanceof ServerLevel ? ((ServerLevel) this.level).getEntity(this.ownerUUID) : (this.ownerNetworkId != 0 ? this.level.getEntity(this.ownerNetworkId) : null); ++ // Paper start - MC-50319 - shooter might be in another world (arrows through portals) ++ Entity entity = this.ownerUUID != null && this.level instanceof ServerLevel ? ((ServerLevel) this.level).getEntity(this.ownerUUID) : (this.ownerNetworkId != 0 ? this.level.getEntity(this.ownerNetworkId) : null); ++ if (entity == null) { ++ for (ServerLevel world : level.getServer().getAllLevels()) { ++ entity = world.getEntity(this.ownerUUID); ++ if (entity != null) { ++ break; ++ } ++ } ++ } ++ return entity; ++ // Paper end + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch b/Remapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch new file mode 100644 index 0000000000..4b6ccafcaa --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Caleb Bassham +Date: Fri, 28 Sep 2018 02:32:19 -0500 +Subject: [PATCH] Call player spectator target events and improve + implementation + +Use a proper teleport for teleporting to entities in different +worlds. + +Implementation improvements authored by Spottedleaf +Validate that the target entity is valid and deny spectate +requests from frozen players. + +Also, make sure the entity is spawned to the client before +sending the camera packet. If the entity isn't spawned clientside +when it receives the camera packet, then the client will not +spectate the target entity. + +Co-authored-by: Spottedleaf + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 75419c866641ab654349cde6ca3fbdef701dd8d9..92139b271eb6c305787662ef8c7d221fb42296f7 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1818,14 +1818,58 @@ public class ServerPlayer extends Player implements ContainerListener { + } + + public void setCamera(Entity entity) { ++ // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event and improve implementation + Entity entity1 = this.getCamera(); + +- this.camera = (Entity) (entity == null ? this : entity); +- if (entity1 != this.camera) { +- this.connection.send(new ClientboundSetCameraPacket(this.camera)); +- this.connection.a(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.yRot, this.xRot, TeleportCause.SPECTATE); // CraftBukkit ++ if (entity == null) { ++ entity = this; + } + ++ if (entity1 == entity) return; // new spec target is the current spec target ++ ++ if (entity == this) { ++ com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent playerStopSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity()); ++ ++ if (!playerStopSpectatingEntityEvent.callEvent()) { ++ return; ++ } ++ } else { ++ com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent playerStartSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity(), entity.getBukkitEntity()); ++ ++ if (!playerStartSpectatingEntityEvent.callEvent()) { ++ return; ++ } ++ } ++ // Validate ++ if (entity != this) { ++ if (entity.removed || entity.shouldBeRemoved || !entity.valid || entity.level == null) { ++ MinecraftServer.LOGGER.info("Blocking player " + this.toString() + " from spectating invalid entity " + entity.toString()); ++ return; ++ } ++ if (this.isImmobile()) { ++ // use debug: clients might maliciously spam this ++ MinecraftServer.LOGGER.debug("Blocking frozen player " + this.toString() + " from spectating entity " + entity.toString()); ++ return; ++ } ++ } ++ ++ this.camera = entity; // only set after validating state ++ ++ if (entity != this) { ++ // Make sure we're in the right place ++ this.ejectPassengers(); // teleport can fail if we have passengers... ++ this.getBukkitEntity().teleport(new Location(entity.getCommandSenderWorld().getWorld(), entity.getX(), entity.getY(), entity.getZ(), this.yRot, this.xRot), TeleportCause.SPECTATE); // Correctly handle cross-world entities from api calls by using CB teleport ++ ++ // Make sure we're tracking the entity before sending ++ ChunkMap.TrackedEntity tracker = ((ServerLevel)entity.level).getChunkSource().chunkMap.entityMap.get(entity.getId()); ++ if (tracker != null) { // dumb plugins... ++ tracker.updatePlayer(this); ++ } ++ } else { ++ this.connection.teleport(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.yRot, this.xRot, TeleportCause.SPECTATE); // CraftBukkit ++ } ++ this.connection.send(new ClientboundSetCameraPacket(entity)); ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 900c9b1106a153bc386f6c3d9c11226f8ac69f86..4fd8d775790c037e82f9b0d29ed0eccf03c2dc66 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1353,6 +1353,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + + // CraftBukkit start - Delegate to teleport(Location) ++ public final void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { this.a(d0, d1, d2, f, f1, cause); } // Paper - OBFHELPER + public void a(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { + this.a(d0, d1, d2, f, f1, Collections.emptySet(), cause); + } diff --git a/Remapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch b/Remapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch new file mode 100644 index 0000000000..f1b44575c0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch @@ -0,0 +1,303 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Mon, 8 Oct 2018 14:36:14 -0400 +Subject: [PATCH] Add Velocity IP Forwarding Support + +While Velocity supports BungeeCord-style IP forwarding, it is not secure. Users +have a lot of problems setting up firewalls or setting up plugins like IPWhitelist. +Further, the BungeeCord IP forwarding protocol still retains essentially its original +form, when there is brand new support for custom login plugin messages in 1.13. + +Velocity's modern IP forwarding uses an HMAC-SHA256 code to ensure authenticity +of messages, is packed into a binary format that is smaller than BungeeCord's +forwarding, and is integrated into the Minecraft login process by using the 1.13 +login plugin message packet. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 7178b37f7978c7e9031a22726005c5099fd78fe0..3139c194f9b1bc3510d51a81f13ae43d00a3dc29 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -8,6 +8,7 @@ import java.io.IOException; + import java.lang.reflect.InvocationTargetException; + import java.lang.reflect.Method; + import java.lang.reflect.Modifier; ++import java.nio.charset.StandardCharsets; + import java.util.HashMap; + import java.util.List; + import java.util.Map; +@@ -252,7 +253,7 @@ public class PaperConfig { + } + + public static boolean isProxyOnlineMode() { +- return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); ++ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode) || (velocitySupport && velocityOnlineMode); + } + + public static int packetInSpamThreshold = 300; +@@ -324,4 +325,18 @@ public class PaperConfig { + } + tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); + } ++ ++ public static boolean velocitySupport; ++ public static boolean velocityOnlineMode; ++ public static byte[] velocitySecretKey; ++ private static void velocitySupport() { ++ velocitySupport = getBoolean("settings.velocity-support.enabled", false); ++ velocityOnlineMode = getBoolean("settings.velocity-support.online-mode", false); ++ String secret = getString("settings.velocity-support.secret", ""); ++ if (velocitySupport && secret.isEmpty()) { ++ fatal("Velocity support is enabled, but no secret key was specified. A secret key is required!"); ++ } else { ++ velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5490ddb9f2ff1fc3e6088e703c246a06594076bc +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java +@@ -0,0 +1,66 @@ ++package com.destroystokyo.paper.proxy; ++ ++import com.destroystokyo.paper.PaperConfig; ++import com.google.common.net.InetAddresses; ++import com.mojang.authlib.GameProfile; ++import com.mojang.authlib.properties.Property; ++import java.net.InetAddress; ++import java.security.InvalidKeyException; ++import java.security.MessageDigest; ++import java.security.NoSuchAlgorithmException; ++ ++import javax.crypto.Mac; ++import javax.crypto.spec.SecretKeySpec; ++import net.minecraft.network.FriendlyByteBuf; ++import net.minecraft.resources.ResourceLocation; ++ ++public class VelocityProxy { ++ private static final int SUPPORTED_FORWARDING_VERSION = 1; ++ public static final ResourceLocation PLAYER_INFO_CHANNEL = new ResourceLocation("velocity", "player_info"); ++ ++ public static boolean checkIntegrity(final FriendlyByteBuf buf) { ++ final byte[] signature = new byte[32]; ++ buf.readBytes(signature); ++ ++ final byte[] data = new byte[buf.readableBytes()]; ++ buf.getBytes(buf.readerIndex(), data); ++ ++ try { ++ final Mac mac = Mac.getInstance("HmacSHA256"); ++ mac.init(new SecretKeySpec(PaperConfig.velocitySecretKey, "HmacSHA256")); ++ final byte[] mySignature = mac.doFinal(data); ++ if (!MessageDigest.isEqual(signature, mySignature)) { ++ return false; ++ } ++ } catch (final InvalidKeyException | NoSuchAlgorithmException e) { ++ throw new AssertionError(e); ++ } ++ ++ int version = buf.readVarInt(); ++ if (version != SUPPORTED_FORWARDING_VERSION) { ++ throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted " + SUPPORTED_FORWARDING_VERSION); ++ } ++ ++ return true; ++ } ++ ++ public static InetAddress readAddress(final FriendlyByteBuf buf) { ++ return InetAddresses.forString(buf.readUTF(Short.MAX_VALUE)); ++ } ++ ++ public static GameProfile createProfile(final FriendlyByteBuf buf) { ++ final GameProfile profile = new GameProfile(buf.readUUID(), buf.readUTF(16)); ++ readProperties(buf, profile); ++ return profile; ++ } ++ ++ private static void readProperties(final FriendlyByteBuf buf, final GameProfile profile) { ++ final int properties = buf.readVarInt(); ++ for (int i1 = 0; i1 < properties; i1++) { ++ final String name = buf.readUTF(Short.MAX_VALUE); ++ final String value = buf.readUTF(Short.MAX_VALUE); ++ final String signature = buf.readBoolean() ? buf.readUTF(Short.MAX_VALUE) : null; ++ profile.getProperties().put(name, new Property(name, value, signature)); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index 10f1e3d761af83507bf71a00092641e22d0c8049..a295845409824b930992426451ef26856d6e7c36 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -191,6 +191,7 @@ public class FriendlyByteBuf extends ByteBuf { + return this.writeVarInt(oenum.ordinal()); + } + ++ public int readVarInt() { return readVarInt(); } // Paper - OBFHELPER + public int readVarInt() { + int i = 0; + int j = 0; +@@ -231,6 +232,7 @@ public class FriendlyByteBuf extends ByteBuf { + return this; + } + ++ public UUID readUUID() { return readUUID(); } // Paper - OBFHELPER + public UUID readUUID() { + return new UUID(this.readLong(), this.readLong()); + } +@@ -358,6 +360,7 @@ public class FriendlyByteBuf extends ByteBuf { + } + } + ++ public String readUTF(int maxLength) { return this.readUtf(maxLength); } // Paper - OBFHELPER + public String readUtf(int i) { + int j = this.readVarInt(); + +diff --git a/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java b/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java +index 8a0301cc4a411c4f9384331d68794ca73b797f5f..88a63635d73983afe58406c66f4ea81cd823c627 100644 +--- a/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java +@@ -13,6 +13,14 @@ public class ClientboundCustomQueryPacket implements Packet { + +- private int transactionId; +- private FriendlyByteBuf data; ++ private int transactionId; public int getId() { return transactionId; } // Paper - OBFHELPER ++ private FriendlyByteBuf data; public FriendlyByteBuf getBuf() { return data; } // Paper - OBFHELPER + + public ServerboundCustomQueryPacket() {} + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 0aa3a154d68f00edcc09b947a24b2b59b1e135e6..22d6f41001977917ec75046252cbf7157b92396d 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -18,9 +18,11 @@ import javax.crypto.Cipher; + import javax.crypto.SecretKey; + import net.minecraft.DefaultUncaughtExceptionHandler; + import net.minecraft.network.Connection; ++import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.chat.TranslatableComponent; ++import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; + import net.minecraft.network.protocol.login.ClientboundGameProfilePacket; + import net.minecraft.network.protocol.login.ClientboundHelloPacket; + import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; +@@ -43,6 +45,7 @@ import org.bukkit.craftbukkit.util.Waitable; + import org.bukkit.event.player.AsyncPlayerPreLoginEvent; + import org.bukkit.event.player.PlayerPreLoginEvent; + // CraftBukkit end ++import io.netty.buffer.Unpooled; // Paper + + public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener { + +@@ -59,6 +62,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + private SecretKey secretKey; + private ServerPlayer delayedAcceptPlayer; + public String hostname = ""; // CraftBukkit - add field ++ private int velocityLoginMessageId = -1; // Paper - Velocity support + + public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection) { + this.state = ServerLoginPacketListenerImpl.State.HELLO; +@@ -211,6 +215,14 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + this.state = ServerLoginPacketListenerImpl.State.KEY; + this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce)); + } else { ++ // Paper start - Velocity support ++ if (com.destroystokyo.paper.PaperConfig.velocitySupport) { ++ this.velocityLoginMessageId = java.util.concurrent.ThreadLocalRandom.current().nextInt(); ++ ClientboundCustomQueryPacket packet1 = new ClientboundCustomQueryPacket(this.velocityLoginMessageId, com.destroystokyo.paper.proxy.VelocityProxy.PLAYER_INFO_CHANNEL, new FriendlyByteBuf(Unpooled.EMPTY_BUFFER)); ++ this.connection.send(packet1); ++ return; ++ } ++ // Paper end + // Spigot start + // Paper start - Cache authenticator threads + authenticatorPool.execute(new Runnable() { +@@ -312,6 +324,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + public class LoginHandler { + + public void fireEvents() throws Exception { ++ // Paper start - Velocity support ++ if (ServerLoginPacketListenerImpl.this.velocityLoginMessageId == -1 && com.destroystokyo.paper.PaperConfig.velocitySupport) { ++ disconnect("This server requires you to connect with Velocity."); ++ return; ++ } ++ // Paper end + String playerName = gameProfile.getName(); + java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); + java.util.UUID uniqueId = gameProfile.getId(); +@@ -359,6 +377,40 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + // Spigot end + + public void handleCustomQueryPacket(ServerboundCustomQueryPacket packet) { ++ // Paper start - Velocity support ++ if (com.destroystokyo.paper.PaperConfig.velocitySupport && packet.getId() == this.velocityLoginMessageId) { ++ FriendlyByteBuf buf = packet.getBuf(); ++ if (buf == null) { ++ this.disconnect("This server requires you to connect with Velocity."); ++ return; ++ } ++ ++ if (!com.destroystokyo.paper.proxy.VelocityProxy.checkIntegrity(buf)) { ++ this.disconnect("Unable to verify player details"); ++ return; ++ } ++ ++ java.net.SocketAddress listening = this.connection.getRemoteAddress(); ++ int port = 0; ++ if (listening instanceof java.net.InetSocketAddress) { ++ port = ((java.net.InetSocketAddress) listening).getPort(); ++ } ++ this.connection.address = new java.net.InetSocketAddress(com.destroystokyo.paper.proxy.VelocityProxy.readAddress(buf), port); ++ ++ this.setGameProfile(com.destroystokyo.paper.proxy.VelocityProxy.createProfile(buf)); ++ ++ // Proceed with login ++ authenticatorPool.execute(() -> { ++ try { ++ new LoginHandler().fireEvents(); ++ } catch (Exception ex) { ++ disconnect("Failed to verify username!"); ++ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + gameProfile.getName(), ex); ++ } ++ }); ++ return; ++ } ++ // Paper end + this.disconnect(new TranslatableComponent("multiplayer.disconnect.unexpected_query_response")); + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 5e36d705c56384f507fd85f704eae634379a27f1..c06b35f114a8d243198b66c44ef57d8c2b201361 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -680,7 +680,7 @@ public final class CraftServer implements Server { + @Override + public long getConnectionThrottle() { + // Spigot Start - Automatically set connection throttle for bungee configurations +- if (org.spigotmc.SpigotConfig.bungee) { ++ if (org.spigotmc.SpigotConfig.bungee || com.destroystokyo.paper.PaperConfig.velocitySupport) { // Paper - Velocity support + return -1; + } else { + return this.configuration.getInt("settings.connection-throttle"); diff --git a/Remapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch b/Remapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch new file mode 100644 index 0000000000..099a0f9cff --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 12 Oct 2018 14:10:46 -0500 +Subject: [PATCH] Add more Witch API + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java +index a37ee32b46aa87be6e3eeca2892b4e7294fd1aef..bc9380782c2afba359852542837e7154c4c6cf8b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java +@@ -1,5 +1,8 @@ + package net.minecraft.world.entity.monster; + ++// Paper start ++import com.destroystokyo.paper.event.entity.WitchReadyPotionEvent; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; + import java.util.Iterator; + import java.util.List; + import java.util.UUID; +@@ -49,7 +52,7 @@ public class Witch extends Raider implements RangedAttackMob { + private static final UUID SPEED_MODIFIER_DRINKING_UUID = UUID.fromString("5CD17E52-A79A-43D3-A529-90FDE04B181E"); + private static final AttributeModifier SPEED_MODIFIER_DRINKING = new AttributeModifier(Witch.SPEED_MODIFIER_DRINKING_UUID, "Drinking speed penalty", -0.25D, AttributeModifier.Operation.ADDITION); + private static final EntityDataAccessor DATA_USING_ITEM = SynchedEntityData.defineId(Witch.class, EntityDataSerializers.BOOLEAN); +- private int usingTime; ++ private int usingTime; public int getPotionUseTimeLeft() { return usingTime; } public void setPotionUseTimeLeft(int timeLeft) { usingTime = timeLeft; } // Paper - OBFHELPER + private NearestHealableRaiderTargetGoal healRaidersGoal; + private NearestAttackableWitchTargetGoal attackPlayersGoal; + +@@ -95,10 +98,12 @@ public class Witch extends Raider implements RangedAttackMob { + return SoundEvents.WITCH_DEATH; + } + ++ public void setDrinkingPotion(boolean drinkingPotion) { setUsingItem(drinkingPotion); } // Paper - OBFHELPER + public void setUsingItem(boolean drinking) { + this.getEntityData().set(Witch.DATA_USING_ITEM, drinking); + } + ++ public boolean isDrinkingPotion() { return isDrinkingPotion(); } // Paper - OBFHELPER + public boolean isDrinkingPotion() { + return (Boolean) this.getEntityData().get(Witch.DATA_USING_ITEM); + } +@@ -157,21 +162,24 @@ public class Witch extends Raider implements RangedAttackMob { + } + + if (potionregistry != null) { +- // Paper start + ItemStack potion = PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry); +- org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); +- this.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++ // Paper start - logic moved into setDrinkingPotion, copy exact impl into the method and then comment out ++ this.setDrinkingPotion(potion); ++// org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++// this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++// // Paper end ++// this.bq = this.getItemInMainHand().k(); ++// this.v(true); ++// if (!this.isSilent()) { ++// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); ++// } ++// ++// AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); ++// ++// attributemodifiable.removeModifier(EntityWitch.bo); ++// attributemodifiable.b(EntityWitch.bo); + // Paper end +- this.usingTime = this.getMainHandItem().getUseDuration(); +- this.setUsingItem(true); +- if (!this.isSilent()) { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); +- } +- +- AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING); +- attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); + } + } + +@@ -183,6 +191,24 @@ public class Witch extends Raider implements RangedAttackMob { + super.aiStep(); + } + ++ // Paper start - moved to its own method ++ public void setDrinkingPotion(ItemStack potion) { ++ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++ this.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++ // Paper end ++ this.usingTime = this.getMainHandItem().getUseDuration(); ++ this.setUsingItem(true); ++ if (!this.isSilent()) { ++ this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); ++ } ++ ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING); ++ attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); ++ } ++ // Paper end ++ + @Override + public SoundEvent getCelebrateSound() { + return SoundEvents.WITCH_CELEBRATE; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +index d4eeb071dbbfca3ecea256228853bcb5c11f49ee..bb40b5af0f2a6a971f78350394099e3a48d5d04a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +@@ -3,6 +3,13 @@ package org.bukkit.craftbukkit.entity; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Witch; ++// Paper start ++import com.destroystokyo.paper.entity.CraftRangedEntity; ++import com.google.common.base.Preconditions; ++import org.bukkit.Material; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.inventory.ItemStack; ++// Paper end + + public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftWitch(CraftServer server, net.minecraft.world.entity.monster.Witch entity) { +@@ -23,4 +30,28 @@ public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo. + public EntityType getType() { + return EntityType.WITCH; + } ++ ++ // Paper start ++ public boolean isDrinkingPotion() { ++ return getHandle().isDrinkingPotion(); ++ } ++ ++ public int getPotionUseTimeLeft() { ++ return getHandle().getPotionUseTimeLeft(); ++ } ++ ++ @Override ++ public void setPotionUseTimeLeft(int ticks) { ++ getHandle().setPotionUseTimeLeft(ticks); ++ } ++ ++ public ItemStack getDrinkingPotion() { ++ return CraftItemStack.asCraftMirror(getHandle().getMainHandItem()); ++ } ++ ++ public void setDrinkingPotion(ItemStack potion) { ++ Preconditions.checkArgument(potion == null || potion.getType().isEmpty() || potion.getType() == Material.POTION, "must be potion, air, or null"); ++ getHandle().setDrinkingPotion(CraftItemStack.asNMSCopy(potion)); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch b/Remapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch new file mode 100644 index 0000000000..cbace85cba --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Wed, 10 Oct 2018 21:22:44 -0500 +Subject: [PATCH] Check Drowned for Villager Aggression Config + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java +index cc9cd34f77e1f568572f312655fb2fe8e83bd733..0addfd6a1421fc99840d9229bad3ba04e524317b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java +@@ -82,7 +82,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D)); + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Drowned.class})).setAlertOthers(ZombifiedPiglin.class)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::okTarget)); +- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); ++ if ( level.spigotConfig.zombieAggressiveTowardsVillager ) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Paper + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); + this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); + } diff --git a/Remapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch b/Remapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch new file mode 100644 index 0000000000..e6a6846d1e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 12 Oct 2018 01:37:22 -0500 +Subject: [PATCH] Here's Johnny! + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +index a41f61daf6cbbb13d0b86cdbad8a4cae00368653..623de661f3b56062792e3a7dbc508637aa58aca5 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +@@ -51,7 +51,7 @@ public class Vindicator extends AbstractIllager { + private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { + return enumdifficulty == Difficulty.NORMAL || enumdifficulty == Difficulty.HARD; + }; +- private boolean isJohnny; ++ private boolean isJohnny; public boolean isJohnny() { return isJohnny; } public void setJohnny(boolean johnny) { isJohnny = johnny; } // Paper - OBFHELPER + + public Vindicator(EntityType type, Level world) { + super(type, world); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java +index 3c5994e9862e5caa257ee6a21f8fba2df39c98c5..6c1569340317f7bed39eaf6e858d602234993eb3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java +@@ -24,4 +24,14 @@ public class CraftVindicator extends CraftIllager implements Vindicator { + public EntityType getType() { + return EntityType.VINDICATOR; + } ++ ++ // Paper start ++ public boolean isJohnny() { ++ return getHandle().isJohnny(); ++ } ++ ++ public void setJohnny(boolean johnny) { ++ getHandle().setJohnny(johnny); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch b/Remapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch new file mode 100644 index 0000000000..565724bd30 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gabriele C +Date: Mon, 22 Oct 2018 17:34:10 +0200 +Subject: [PATCH] Add option to prevent players from moving into unloaded + chunks #1551 + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index f280dbff4a09bc611a9ca565c6d697d08801f53b..fbf3ccfb347a5ba6e895339e9576629d940d1aa4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -396,4 +396,9 @@ public class PaperWorldConfig { + waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); + log("Water over lava flow speed: " + waterOverLavaFlowSpeed); + } ++ ++ public boolean preventMovingIntoUnloadedChunks = false; ++ private void preventMovingIntoUnloadedChunks() { ++ preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 4fd8d775790c037e82f9b0d29ed0eccf03c2dc66..b5593300516fad767f603084aca4abcda4424db3 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -541,6 +541,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + speed *= 2f; // TODO: Get the speed of the vehicle instead of the player + ++ // Paper start - Prevent moving into unloaded chunks ++ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && worldserver.getChunkIfLoadedImmediately((int) Math.floor(packet.getX()) >> 4, (int) Math.floor(packet.getZ()) >> 4) == null) { ++ this.connection.send(new ClientboundMoveVehiclePacket(entity)); ++ return; ++ } ++ // Paper end ++ + if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { + // CraftBukkit end + ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getName().getString(), this.player.getName().getString(), d6, d7, d8); +@@ -1139,9 +1146,9 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + double d1 = this.player.getY(); + double d2 = this.player.getZ(); + double d3 = this.player.getY(); +- double d4 = packet.getX(this.player.getX()); ++ double d4 = packet.getX(this.player.getX());double toX = d4; // Paper - OBFHELPER + double d5 = packet.getY(this.player.getY()); +- double d6 = packet.getZ(this.player.getZ()); ++ double d6 = packet.getZ(this.player.getZ());double toZ = d6; // Paper - OBFHELPER + float f = packet.getYRot(this.player.yRot); + float f1 = packet.getXRot(this.player.xRot); + double d7 = d4 - this.firstGoodX; +@@ -1180,6 +1187,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } else { + speed = player.abilities.walkingSpeed * 10f; + } ++ // Paper start - Prevent moving into unloaded chunks ++ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.hasChunk((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { ++ this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.yRot, this.player.xRot, Collections.emptySet()); ++ return; ++ } ++ // Paper end + + if (!this.player.isChangingDimension() && (!this.player.getLevel().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying())) { + float f2 = this.player.isFallFlying() ? 300.0F : 100.0F; diff --git a/Remapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch b/Remapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch new file mode 100644 index 0000000000..b3525e04cd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: GreenMeanie +Date: Sat, 20 Oct 2018 22:34:02 -0400 +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 92139b271eb6c305787662ef8c7d221fb42296f7..b68acf219fc61e2ea811d0c732393824fa44db2d 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -2159,6 +2159,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + + this.setHealth(this.getMaxHealth()); ++ this.setAirSupply(this.getMaxAirTicks()); // Paper + this.remainingFireTicks = 0; + this.fallDistance = 0; + this.foodData = new FoodData(this); +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index e7fed1f8bb8ffb164ddcdab51f41c369d6e3103d..460c6fd61bb45247715d99445821e15e98e4c465 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2354,6 +2354,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + } + ++ public final int getMaxAirTicks() { return getMaxAirSupply(); } // Paper - OBFHELPER + public int getMaxAirSupply() { + return 300; + } diff --git a/Remapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch b/Remapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch new file mode 100644 index 0000000000..01be147e24 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 23 Oct 2018 20:25:05 -0400 +Subject: [PATCH] Don't sleep after profile lookups if not needed + +Mojang was sleeping even if we had no more requests to go after +the current one finished, resulting in 100ms lost per profile lookup + +diff --git a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java +index a3ab666b5fa89aad7ee167d9aeff2f62019a4a78..8e182fdd69dba6e1c52e2f6a893534d77fb3bfaa 100644 +--- a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java ++++ b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java +@@ -43,6 +43,7 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { + } + + final int page = 0; ++ boolean hasRequested = false; // Paper + + for (final List request : Iterables.partition(criteria, ENTRIES_PER_PAGE)) { + int failCount = 0; +@@ -68,6 +69,12 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { + LOGGER.debug("Couldn't find profile {}", name); + callback.onProfileLookupFailed(new GameProfile(null, name), new ProfileNotFoundException("Server did not find the requested profile")); + } ++ // Paper start ++ if (!hasRequested) { ++ hasRequested = true; ++ continue; ++ } ++ // Paper end + + try { + Thread.sleep(DELAY_BETWEEN_PAGES); diff --git a/Remapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/Remapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch new file mode 100644 index 0000000000..04594148fc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 23 Oct 2018 23:14:38 -0400 +Subject: [PATCH] Improve Server Thread Pool and Thread Priorities + +Use a simple executor since Fork join is a much more complex pool +type and we are not using its capabilities. + +Set thread priorities so main thread has above normal priority over +server threads + +Allow usage of a single thread executor by not using ForkJoin so single core CPU's. + +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index 7b36274718b7cce24ac00530697f145648d52590..cec5ad5052c8cf6059e9b117117846bdb217748f 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -45,7 +45,7 @@ import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.Bootstrap; +-import net.minecraft.util.Mth; ++import net.minecraft.server.ServerWorkerThread; + import net.minecraft.util.datafix.DataFixers; + import net.minecraft.world.level.block.state.properties.Property; + import org.apache.logging.log4j.LogManager; +@@ -54,8 +54,8 @@ import org.apache.logging.log4j.Logger; + public class Util { + + private static final AtomicInteger WORKER_COUNT = new AtomicInteger(1); +- private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap"); +- private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main"); ++ private static final ExecutorService BOOTSTRAP_EXECUTOR = a("Bootstrap", -2); // Paper - add -2 priority ++ private static final ExecutorService BACKGROUND_EXECUTOR = a("Main", -1); // Paper - add -1 priority + private static final ExecutorService IO_POOL = makeIoExecutor(); + public static LongSupplier timeSource = System::nanoTime; + public static final UUID NIL_UUID = new UUID(0L, 0L); public static final UUID getNullUUID() {return NIL_UUID;} // Paper OBFHELPER +@@ -85,30 +85,34 @@ public class Util { + return Instant.now().toEpochMilli(); + } + +- private static ExecutorService makeExecutor(String name) { +- int i = Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, 7); +- Object object; ++ private static ExecutorService a(String s, int priorityModifier) { // Paper - add priority ++ // Paper start - use simpler thread pool that allows 1 thread ++ int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1)); ++ i = Integer.getInteger("Paper.WorkerThreadCount", i); ++ ExecutorService object; + + if (i <= 0) { + object = MoreExecutors.newDirectExecutorService(); + } else { +- object = new ForkJoinPool(i, (forkjoinpool) -> { +- ForkJoinWorkerThread forkjoinworkerthread = new ForkJoinWorkerThread(forkjoinpool) { ++ object = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue(), target -> new ServerWorkerThread(target, s, priorityModifier)); ++ } ++ /* + protected void onTermination(Throwable throwable) { + if (throwable != null) { +- Util.LOGGER.warn("{} died", this.getName(), throwable); ++ SystemUtils.LOGGER.warn("{} died", this.getName(), throwable); + } else { +- Util.LOGGER.debug("{} shutdown", this.getName()); ++ SystemUtils.LOGGER.debug("{} shutdown", this.getName()); + } + + super.onTermination(throwable); + } + }; + +- forkjoinworkerthread.setName("Worker-" + name + "-" + Util.WORKER_COUNT.getAndIncrement()); ++ forkjoinworkerthread.setName("Worker-" + s + "-" + SystemUtils.c.getAndIncrement()); + return forkjoinworkerthread; +- }, Util::onThreadException, true); ++ }, SystemUtils::a, true); + } ++ }*/ // Paper end + + return (ExecutorService) object; + } +@@ -157,6 +161,7 @@ public class Util { + }); + } + ++ public static void onThreadError(Thread thread, Throwable throwable) { onThreadException(thread, throwable); } // Paper - OBFHELPER + private static void onThreadException(Thread thread, Throwable throwable) { + pauseInIde(throwable); + if (throwable instanceof CompletionException) { +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 5a76ca77b974ff6fe862c9e05a88b507a34b44be..5faa8f3cc251b6687e33e40009db98d2aee48f2c 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -284,6 +284,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Fri, 2 Nov 2018 23:11:51 -0400 +Subject: [PATCH] Optimize World Time Updates + +Splits time updates into incremental updates as well as does +the updates per world, so that we can re-use the same packet +object for every player unless they have per-player time enabled. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 5faa8f3cc251b6687e33e40009db98d2aee48f2c..6ccc0be795e3ac7689de0eff6f9142d13161a29c 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1314,12 +1314,24 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Mon, 5 Nov 2018 04:23:51 +0000 +Subject: [PATCH] Restore custom InventoryHolder support + +Upstream removed the ability to consistently use a custom InventoryHolder, +However, the implementation does not use an InventoryHolder in any form +outside of custom inventories. + +We can take that knowledge and apply some expected behavior, if we're given +an inventory holder, we should use it and return a custom inventory with the +holder, otherwise, create an inventory backed by the intended inventory, as +per upstream behavior. + +This provides a "best of both worlds" scenario: plugins with InventoryHolder's +will always work as intended in the past, those without will create implementation +based inventories. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +index 94d807c5d09f165c6eedd0a1c4026c2b833806a0..3e56de295be0d03dddd3e54fcd7b05d4b9c74dc4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +@@ -40,6 +40,11 @@ public final class CraftInventoryCreator { + } + + public Inventory createInventory(InventoryHolder holder, InventoryType type) { ++ // Paper start ++ if (holder != null) { ++ return DEFAULT_CONVERTER.createInventory(holder, type); ++ } ++ //noinspection ConstantConditions // Paper end + return converterMap.get(type).createInventory(holder, type); + } + +@@ -55,6 +60,11 @@ public final class CraftInventoryCreator { + // Paper end + + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { ++ // Paper start ++ if (holder != null) { ++ return DEFAULT_CONVERTER.createInventory(holder, type, title); ++ } ++ //noinspection ConstantConditions // Paper end + return converterMap.get(type).createInventory(holder, type, title); + } + diff --git a/Remapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch b/Remapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch new file mode 100644 index 0000000000..1eeb5272ca --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 8 Nov 2018 21:33:09 -0500 +Subject: [PATCH] Use Vanilla Minecart Speeds + +CraftBukkit changed the values on flying speed, restore back to vanilla + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 7ba74b0a9319e29077b5afe3019a463ed3004813..1257a740a4ab79870fe89057782e8ffc6c658c14 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -99,9 +99,9 @@ public abstract class AbstractMinecart extends Entity { + private double derailedX = 0.5; + private double derailedY = 0.5; + private double derailedZ = 0.5; +- private double flyingX = 0.95; +- private double flyingY = 0.95; +- private double flyingZ = 0.95; ++ private double flyingX = 0.949999988079071D; // Paper - restore vanilla precision ++ private double flyingY = 0.949999988079071D; // Paper - restore vanilla precision ++ private double flyingZ = 0.949999988079071D; // Paper - restore vanilla precision + public double maxSpeed = 0.4D; + // CraftBukkit end + diff --git a/Remapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch b/Remapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch new file mode 100644 index 0000000000..169c739faa --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 10 Nov 2018 05:15:21 +0000 +Subject: [PATCH] Fix SpongeAbsortEvent handling + +Only process drops when the block is actually going to be removed + +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 9d2e4adddae481735053c64eec0ee7259c61f1a4..fca5d175cbef24fb0ee2d0bbedc8d1c0af3eb528 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -228,6 +228,7 @@ public class Block extends BlockBehaviour implements ItemLike { + + } + ++ public static void dropNaturally(BlockState iblockdata, LevelAccessor generatoraccess, BlockPos blockposition, @Nullable BlockEntity tileentity) { dropResources(iblockdata, generatoraccess, blockposition, tileentity); } + public static void dropResources(BlockState state, LevelAccessor world, BlockPos pos, @Nullable BlockEntity blockEntity) { + if (world instanceof ServerLevel) { + getDrops(state, (ServerLevel) world, pos, blockEntity).forEach((itemstack) -> { +diff --git a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java +index c453963ec90cd4eeec845fd0c2137e60dfdd6225..1895c75deee8da40624ba3abbd08ba7cd4f0f503 100644 +--- a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java +@@ -128,8 +128,11 @@ public class SpongeBlock extends Block { + // NOP + } else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) { + BlockEntity tileentity = iblockdata.getBlock().isEntityBlock() ? world.getBlockEntity(blockposition2) : null; +- +- dropResources(iblockdata, world, blockposition2, tileentity); ++ // Paper start ++ if (block.getHandle().getMaterial() == Material.AIR) { ++ dropNaturally(iblockdata, world, blockposition2, tileentity); ++ } ++ // Paper end + } + } + world.setBlock(blockposition2, block.getHandle(), block.getFlag()); diff --git a/Remapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch b/Remapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch new file mode 100644 index 0000000000..f5420a15fd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 11 Nov 2018 21:01:09 +0000 +Subject: [PATCH] Don't allow digging into unloaded chunks + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index b1a53093eb5b5f359eedb6c252cf6d0d1ae8e409..d97607f2ded4977b253d3afa3bafcbe6d7f98837 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -113,8 +113,8 @@ public class ServerPlayerGameMode { + BlockState iblockdata; + + if (this.hasDelayedDestroy) { +- iblockdata = this.level.getBlockState(this.delayedDestroyPos); +- if (iblockdata.isAir()) { ++ iblockdata = this.level.getTypeIfLoaded(this.delayedDestroyPos); // Paper ++ if (iblockdata == null || iblockdata.isAir()) { // Paper + this.hasDelayedDestroy = false; + } else { + float f = this.incrementDestroyProgress(iblockdata, this.delayedDestroyPos, this.delayedTickStart); +@@ -125,7 +125,13 @@ public class ServerPlayerGameMode { + } + } + } else if (this.isDestroyingBlock) { +- iblockdata = this.level.getBlockState(this.destroyPos); ++ // Paper start - don't want to do same logic as above, return instead ++ iblockdata = this.level.getTypeIfLoaded(this.destroyPos); ++ if (iblockdata == null) { ++ this.isDestroyingBlock = false; ++ return; ++ } ++ // Paper end + if (iblockdata.isAir()) { + this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); + this.lastSentState = -1; +@@ -289,10 +295,12 @@ public class ServerPlayerGameMode { + this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, "stopped destroying")); + } else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) { + this.isDestroyingBlock = false; +- if (!Objects.equals(this.destroyPos, pos)) { ++ if (!Objects.equals(this.destroyPos, pos) && !BlockPos.ZERO.equals(this.destroyPos)) { + ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: " + this.destroyPos + " " + pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled +- this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); +- this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, this.level.getBlockState(this.destroyPos), action, true, "aborted mismatched destroying")); ++ BlockState type = this.level.getTypeIfLoaded(this.destroyPos); // Paper - don't load unloaded chunks for stale records here ++ if (type != null) this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); // Paper ++ if (type != null) this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, type, action, true, "aborted mismatched destroying")); // Paper ++ this.destroyPos = BlockPos.ZERO; // Paper + } + + this.level.destroyBlockProgress(this.player.getId(), pos, -1); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index b5593300516fad767f603084aca4abcda4424db3..a6ad7747396f94def688b4d2783137180dc2bb84 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1518,6 +1518,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + case START_DESTROY_BLOCK: + case ABORT_DESTROY_BLOCK: + case STOP_DESTROY_BLOCK: ++ // Paper start - Don't allow digging in unloaded chunks ++ if (this.player.level.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { ++ return; ++ } ++ // Paper end - Don't allow digging in unloaded chunks + this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packet.getDirection(), this.server.getMaxBuildHeight()); + return; + default: diff --git a/Remapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch b/Remapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch new file mode 100644 index 0000000000..ef45bdd8d0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 16 Nov 2018 23:08:50 -0500 +Subject: [PATCH] Book Size Limits + +Puts some limits on the size of books. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 3139c194f9b1bc3510d51a81f13ae43d00a3dc29..13edb435b3fa65b4980bd7472aa5a5196f4d5b2b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -339,4 +339,11 @@ public class PaperConfig { + velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); + } + } ++ ++ public static int maxBookPageSize = 2560; ++ public static double maxBookTotalSizeMultiplier = 0.98D; ++ private static void maxBookSize() { ++ maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); ++ maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index a6ad7747396f94def688b4d2783137180dc2bb84..b1c505d3fdcc2fb3496f80bee85e4895b9069dcb 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -999,6 +999,52 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + @Override + public void handleEditBook(ServerboundEditBookPacket packet) { ++ // Paper start ++ ItemStack testStack = packet.getBook(); ++ if (!craftServer.isPrimaryThread() && !testStack.isEmpty() && testStack.getTag() != null) { ++ ListTag pageList = testStack.getTag().getList("pages", 8); ++ if (pageList.size() > 100) { ++ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with too many pages"); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ return; ++ } ++ long byteTotal = 0; ++ int maxBookPageSize = com.destroystokyo.paper.PaperConfig.maxBookPageSize; ++ double multiplier = Math.max(0.3D, Math.min(1D, com.destroystokyo.paper.PaperConfig.maxBookTotalSizeMultiplier)); ++ long byteAllowed = maxBookPageSize; ++ for (int i = 0; i < pageList.size(); ++i) { ++ String testString = pageList.getString(i); ++ int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; ++ if (byteLength > 256 * 4) { ++ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!"); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ return; ++ } ++ byteTotal += byteLength; ++ int length = testString.length(); ++ int multibytes = 0; ++ if (byteLength != length) { ++ for (char c : testString.toCharArray()) { ++ if (c > 127) { ++ multibytes++; ++ } ++ } ++ } ++ byteAllowed += (maxBookPageSize * Math.min(1, Math.max(0.1D, (double) length / 255D))) * multiplier; ++ ++ if (multibytes > 1) { ++ // penalize MB ++ byteAllowed -= multibytes; ++ } ++ } ++ ++ if (byteTotal > byteAllowed) { ++ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ return; ++ } ++ } ++ // Paper end + // CraftBukkit start + if (this.lastBookTick + 20 > MinecraftServer.currentTick) { + this.disconnect("Book edited too quickly!"); diff --git a/Remapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch b/Remapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch new file mode 100644 index 0000000000..8d9bfec2a6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 18 Nov 2018 19:49:56 +0000 +Subject: [PATCH] Make the default permission message configurable + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 13edb435b3fa65b4980bd7472aa5a5196f4d5b2b..469f78775b03cf363d88e35c69c0dc185c22547c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -19,6 +19,7 @@ import java.util.regex.Pattern; + import com.google.common.collect.Lists; + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; + import org.bukkit.command.Command; + import org.bukkit.configuration.ConfigurationSection; + import org.bukkit.configuration.InvalidConfigurationException; +@@ -287,6 +288,11 @@ public class PaperConfig { + connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); + } + ++ public static String noPermissionMessage = "&cI'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error."; ++ private static void noPermissionMessage() { ++ noPermissionMessage = ChatColor.translateAlternateColorCodes('&', getString("messages.no-permission", noPermissionMessage)); ++ } ++ + private static void savePlayerData() { + Object val = config.get("settings.save-player-data"); + if (val instanceof Boolean) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index c06b35f114a8d243198b66c44ef57d8c2b201361..590687d5941cbed3a330bcd749f8d52cd4b5e3ae 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2340,6 +2340,11 @@ public final class CraftServer implements Server { + return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; + } + ++ @Override ++ public String getPermissionMessage() { ++ return com.destroystokyo.paper.PaperConfig.noPermissionMessage; ++ } ++ + @Override + public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { + return createProfile(uuid, null); diff --git a/Remapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch b/Remapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch new file mode 100644 index 0000000000..d300ff7c9e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 26 Nov 2018 19:21:58 -0500 +Subject: [PATCH] Prevent rayTrace from loading chunks + +ray tracing into an unloaded chunk should be treated as a miss +this saves a ton of lag for when AI tries to raytrace near unloaded chunks. + +diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java +index 2feb187f62be5cf5d354a1e806087417cc189ab1..07fe8e72a7ff01d872dd5b04ccbc435e82ebe990 100644 +--- a/src/main/java/net/minecraft/world/level/BlockGetter.java ++++ b/src/main/java/net/minecraft/world/level/BlockGetter.java +@@ -58,7 +58,15 @@ public interface BlockGetter { + + // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace + default BlockHitResult rayTraceBlock(ClipContext raytrace1, BlockPos blockposition) { +- BlockState iblockdata = this.getBlockState(blockposition); ++ // Paper start - Prevent raytrace from loading chunks ++ BlockState iblockdata = this.getTypeIfLoaded(blockposition); ++ if (iblockdata == null) { ++ // copied the last function parameter (listed below) ++ Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo()); ++ ++ return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), new BlockPos(raytrace1.getTo())); ++ } ++ // Paper end + FluidState fluid = this.getFluidState(blockposition); + Vec3 vec3d = raytrace1.getFrom(); + Vec3 vec3d1 = raytrace1.getTo(); diff --git a/Remapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch b/Remapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch new file mode 100644 index 0000000000..3b9703f204 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 27 Nov 2018 21:18:06 -0500 +Subject: [PATCH] Handle Large Packets disconnecting client + +If a players inventory is too big to send in a single packet, +split the inventory set into multiple packets instead. + +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 7f4681910751047a26fdfc6b59bc460449c02001..35191d968fd30db16213540ef7121f4dede68e68 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -12,6 +12,7 @@ import io.netty.channel.epoll.EpollEventLoopGroup; + import io.netty.channel.local.LocalChannel; + import io.netty.channel.local.LocalServerChannel; + import io.netty.channel.nio.NioEventLoopGroup; ++import io.netty.handler.codec.EncoderException; // Paper + import io.netty.handler.timeout.TimeoutException; + import io.netty.util.AttributeKey; + import io.netty.util.concurrent.Future; +@@ -107,6 +108,15 @@ public class Connection extends SimpleChannelInboundHandler> { + } + + public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { ++ // Paper start ++ if (throwable instanceof EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) { ++ if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) { ++ return; ++ } else { ++ throwable = throwable.getCause(); ++ } ++ } ++ // Paper end + if (throwable instanceof SkipPacketException) { + Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause()); + } else { +diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java +index d36d0424bcd4811af892f5f76fdcefda2af1ad33..a58c4fa8be7193b8acae5ea18a9780866312d768 100644 +--- a/src/main/java/net/minecraft/network/PacketEncoder.java ++++ b/src/main/java/net/minecraft/network/PacketEncoder.java +@@ -53,7 +53,31 @@ public class PacketEncoder extends MessageToByteEncoder> { + throw throwable; + } + } ++ ++ // Paper start ++ int packetLength = bytebuf.readableBytes(); ++ if (packetLength > MAX_PACKET_SIZE) { ++ throw new PacketTooLargeException(packet, packetLength); ++ } ++ // Paper end + } + } + } ++ ++ // Paper start ++ private static int MAX_PACKET_SIZE = 2097152; ++ ++ public static class PacketTooLargeException extends RuntimeException { ++ private final Packet packet; ++ ++ PacketTooLargeException(Packet packet, int packetLength) { ++ super("PacketTooLarge - " + packet.getClass().getSimpleName() + " is " + packetLength + ". Max is " + MAX_PACKET_SIZE); ++ this.packet = packet; ++ } ++ ++ public Packet getPacket() { ++ return packet; ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java +index 29f10af7feabe2765f576586db4e3dba320dceda..9914a82ba0ec146ab13fe94c4dbf0ebf64926536 100644 +--- a/src/main/java/net/minecraft/network/protocol/Packet.java ++++ b/src/main/java/net/minecraft/network/protocol/Packet.java +@@ -12,6 +12,12 @@ public interface Packet { + + void handle(T listener); + ++ // Paper start ++ default boolean packetTooLarge(NetworkManager manager) { ++ return false; ++ } ++ // Paper end ++ + default boolean isSkippable() { + return false; + } +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java +index 70684318c562a9c3ce566b16cd0e68cfe95cbd50..64a15dcaef40c4e16458ab71d648f9fff169a3b2 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java +@@ -4,6 +4,7 @@ import java.io.IOException; + import java.util.Iterator; + import java.util.List; + import net.minecraft.core.NonNullList; ++import net.minecraft.network.Connection; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; + import net.minecraft.world.item.ItemStack; +@@ -13,6 +14,15 @@ public class ClientboundContainerSetContentPacket implements Packet items; + ++ //Paper start ++ @Override ++ public boolean packetTooLarge(Connection manager) { ++ for (int i = 0 ; i < this.items.size() ; i++) { ++ manager.send(new ClientboundContainerSetSlotPacket(this.containerId, i, this.items.get(i))); ++ } ++ return true; ++ } ++ // Paper end + public ClientboundContainerSetContentPacket() {} + + public ClientboundContainerSetContentPacket(int syncId, NonNullList contents) { +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index 4fe15aa331ca18319ca46d1b426f0d6fd24341f0..b7d303b5f51a35504888933efef74564fa01e59d 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -91,7 +91,7 @@ public class ClientboundLevelChunkPacket implements Packet 2097152) { ++ if (i > 2097152) { // Paper - if this changes, update PacketEncoder + throw new RuntimeException("Chunk Packet trying to allocate too much memory on read."); + } else { + this.buffer = new byte[i]; diff --git a/Remapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch b/Remapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch new file mode 100644 index 0000000000..abee5b71e8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch @@ -0,0 +1,134 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 15 Nov 2018 13:38:37 +0000 +Subject: [PATCH] force entity dismount during teleportation + +Entities must be dismounted before teleportation in order to avoid +multiple issues in the server with regards to teleportation, shamefully, +too many plugins rely on the events firing, which means that not firing +these events caues more issues than it solves; + +In order to counteract this, Entity dismount/exit vehicle events have +been modified to supress cancellation (and has a method to allow plugins +to check if this has been set), noting that cancellation will be silently +surpressed given that plugins are not expecting this event to not be cancellable. + +This is a far from ideal scenario, however: given the current state of this +event and other alternatives causing issues elsewhere, I believe that +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 b68acf219fc61e2ea811d0c732393824fa44db2d..416c21f0a6be8d71a654e18f7ea0fa074f8fc5ff 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1258,11 +1258,13 @@ public class ServerPlayer extends Player implements ContainerListener { + } + } + +- @Override +- public void stopRiding() { ++ // Paper start ++ @Override public void stopRiding() { stopRiding(false); } ++ @Override public void stopRiding(boolean suppressCancellation) { ++ // paper end + Entity entity = this.getVehicle(); + +- super.stopRiding(); ++ super.stopRiding(suppressCancellation); // Paper + Entity entity1 = this.getVehicle(); + + if (entity1 != entity && this.connection != null) { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 460c6fd61bb45247715d99445821e15e98e4c465..c5d6235a132818dfc78105e9d03d0687f697bb00 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2044,12 +2044,15 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + } + +- public void removeVehicle() { ++ // Paper start ++ public void removeVehicle() { stopRiding(false); } ++ public void stopRiding(boolean suppressCancellation) { ++ // Paper end + if (this.vehicle != null) { + Entity entity = this.vehicle; + + this.vehicle = null; +- if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit ++ if (!entity.removePassenger(this, suppressCancellation)) this.vehicle = entity; // CraftBukkit // Paper + } + + } +@@ -2104,7 +2107,10 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return true; // CraftBukkit + } + +- protected boolean removePassenger(Entity entity) { // CraftBukkit ++ // Paper start ++ protected boolean removePassenger(Entity entity) { return removePassenger(entity, false);} ++ protected boolean removePassenger(Entity entity, boolean suppressCancellation) { // CraftBukkit ++ // Paper end + if (entity.getVehicle() == this) { + throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); + } else { +@@ -2114,7 +2120,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { + VehicleExitEvent event = new VehicleExitEvent( + (Vehicle) getBukkitEntity(), +- (LivingEntity) entity.getBukkitEntity() ++ (LivingEntity) entity.getBukkitEntity(), !suppressCancellation // Paper + ); + // Suppress during worldgen + if (this.valid) { +@@ -2128,7 +2134,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + // CraftBukkit end + // Spigot start +- org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity()); ++ org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity(), !suppressCancellation); // Paper + // Suppress during worldgen + 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 7a2292e6907a2ae2026bd7243e864bd8300ecafa..29d4ed42e5d763639a50d849ef274c4d848bc9c9 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3012,11 +3012,13 @@ public abstract class LivingEntity extends Entity { + return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 4) != 0; + } + +- @Override +- public void stopRiding() { ++ // Paper start ++ @Override public void stopRiding() { stopRiding(false); } ++ @Override public void stopRiding(boolean suppressCancellation) { ++ // Paper end + Entity entity = this.getVehicle(); + +- super.stopRiding(); ++ super.stopRiding(suppressCancellation); // Paper - suppress + if (entity != null && entity != this.getVehicle() && !this.level.isClientSide) { + this.dismountVehicle(entity); + } +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 3aadc4ab5fe7b2ee9e20e0789ddcfe750599972f..0685920073a6a2b2c6a80018d0c9009b2ef860c4 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1036,9 +1036,11 @@ public abstract class Player extends LivingEntity { + return -0.35D; + } + +- @Override +- public void removeVehicle() { +- super.removeVehicle(); ++ // Paper start ++ @Override public void removeVehicle() { stopRiding(false); } ++ @Override public void stopRiding(boolean suppressCancellation) { ++ // Paper end ++ super.stopRiding(suppressCancellation); // Paper - suppress + this.boardingCooldown = 0; + } + diff --git a/Remapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch b/Remapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch new file mode 100644 index 0000000000..324b101062 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 7 Oct 2018 04:29:59 -0500 +Subject: [PATCH] Add more Zombie API + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 94e2a8f74e74d68d4a9b82b667fbff24b7e9e629..ad4eeb15771750193a28116117992270c72a3644 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -91,6 +91,7 @@ public class Zombie extends Monster { + private int inWaterTime; + public int conversionTime; + private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field ++ private boolean shouldBurnInDay = true; // Paper + + public Zombie(EntityType type, Level world) { + super(type, world); +@@ -259,6 +260,12 @@ public class Zombie extends Monster { + super.aiStep(); + } + ++ // Paper start ++ public void stopDrowning() { ++ this.conversionTime = -1; ++ this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, false); ++ } ++ // Paper end + public void startUnderWaterConversion(int ticksUntilWaterConversion) { + this.lastTick = MinecraftServer.currentTick; // CraftBukkit + this.conversionTime = ticksUntilWaterConversion; +@@ -287,9 +294,16 @@ public class Zombie extends Monster { + + } + ++ public boolean shouldBurnInDay() { return isSunSensitive(); } // Paper - OBFHELPER + protected boolean isSunSensitive() { +- return true; ++ return this.shouldBurnInDay; // Paper - use api value instead ++ } ++ ++ // Paper start ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { ++ this.shouldBurnInDay = shouldBurnInDay; + } ++ // Paper end + + @Override + public boolean hurt(DamageSource source, float amount) { +@@ -410,6 +424,7 @@ public class Zombie extends Monster { + tag.putBoolean("CanBreakDoors", this.canBreakDoors()); + tag.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1); + tag.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1); ++ tag.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); // Paper + } + + @Override +@@ -421,7 +436,11 @@ public class Zombie extends Monster { + if (tag.contains("DrownedConversionTime", 99) && tag.getInt("DrownedConversionTime") > -1) { + this.startUnderWaterConversion(tag.getInt("DrownedConversionTime")); + } +- ++ // Paper start ++ if (tag.contains("Paper.ShouldBurnInDay")) { ++ shouldBurnInDay = tag.getBoolean("Paper.ShouldBurnInDay"); ++ } ++ // Paper end + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +index 038793987338c2e4b73784a10836f85c7061175a..86f65c07806a118c49e900c59be86c2bd2eb124c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +@@ -93,6 +93,42 @@ public class CraftZombie extends CraftMonster implements Zombie { + @Override + public void setAgeLock(boolean b) { + } ++ // Paper start ++ @Override ++ public boolean isDrowning() { ++ return getHandle().isUnderWaterConverting(); ++ } ++ ++ @Override ++ public void startDrowning(int drownedConversionTime) { ++ getHandle().startUnderWaterConversion(drownedConversionTime); ++ } ++ ++ @Override ++ public void stopDrowning() { ++ getHandle().stopDrowning(); ++ } ++ ++ @Override ++ public boolean shouldBurnInDay() { ++ return getHandle().shouldBurnInDay(); ++ } ++ ++ @Override ++ public boolean isArmsRaised() { ++ return getHandle().isAggressive(); ++ } ++ ++ @Override ++ public void setArmsRaised(final boolean raised) { ++ getHandle().setAggressive(raised); ++ } ++ ++ @Override ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { ++ getHandle().setShouldBurnInDay(shouldBurnInDay); ++ } ++ // Paper end + + @Override + public boolean getAgeLock() { diff --git a/Remapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch b/Remapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch new file mode 100644 index 0000000000..12d0a9084e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 7 Oct 2018 12:05:28 -0700 +Subject: [PATCH] Add PlayerConnectionCloseEvent + +This event is invoked when a player has disconnected. It is guaranteed that, +if the server is in online-mode, that the provided uuid and username have been +validated. + +The event is invoked for players who have not yet logged into the world, whereas +PlayerQuitEvent is only invoked on players who have logged into the world. + +The event is invoked for players who have already logged into the world, +although whether or not the player exists in the world at the time of +firing is undefined. (That is, whether the plugin can retrieve a Player object +using the event parameters is undefined). However, it is guaranteed that this +event is invoked AFTER PlayerQuitEvent, if the player has already logged into +the world. + +This event is guaranteed to never fire unless AsyncPlayerPreLoginEvent has +been called beforehand, and this event may not be called in parallel with +AsyncPlayerPreLoginEvent for the same connection. + +Cancelling the AsyncPlayerPreLoginEvent guarantees the corresponding +PlayerConnectionCloseEvent is never called. + +The event may be invoked asynchronously or synchronously. As it stands, +it is never invoked asynchronously. However, plugins should check +Event#isAsynchronous to be future-proof. + +On purpose, the deprecated PlayerPreLoginEvent event is left out of the +API spec for this event. Plugins should not be using that event, and +how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent +is undefined. + +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 35191d968fd30db16213540ef7121f4dede68e68..3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -350,6 +350,26 @@ public class Connection extends SimpleChannelInboundHandler> { + this.getPacketListener().a(new TranslatableComponent("multiplayer.disconnect.generic")); + } + this.queue.clear(); // Free up packet queue. ++ // Paper start - Add PlayerConnectionCloseEvent ++ final PacketListener packetListener = this.getPacketListener(); ++ if (packetListener instanceof ServerGamePacketListenerImpl) { ++ /* Player was logged in */ ++ final ServerGamePacketListenerImpl playerConnection = (ServerGamePacketListenerImpl) packetListener; ++ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(playerConnection.player.getUUID(), ++ playerConnection.player.getScoreboardName(), ((java.net.InetSocketAddress)address).getAddress(), false).callEvent(); ++ } else if (packetListener instanceof ServerLoginPacketListenerImpl) { ++ /* Player is login stage */ ++ final ServerLoginPacketListenerImpl loginListener = (ServerLoginPacketListenerImpl) packetListener; ++ switch (loginListener.getLoginState()) { ++ case READY_TO_ACCEPT: ++ case DELAY_ACCEPT: ++ case ACCEPTED: ++ final com.mojang.authlib.GameProfile profile = loginListener.getGameProfile(); /* Should be non-null at this stage */ ++ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(profile.getId(), profile.getName(), ++ ((java.net.InetSocketAddress)address).getAddress(), false).callEvent(); ++ } ++ } ++ // Paper end + } + + } +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 22d6f41001977917ec75046252cbf7157b92396d..9631fa93b821c7f6bc6dc707c2c82cce2ae8291e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -55,9 +55,9 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + private final byte[] nonce = new byte[4]; + private final MinecraftServer server; + public final Connection connection; +- private ServerLoginPacketListenerImpl.State state; ++ private ServerLoginPacketListenerImpl.State state; public final ServerLoginPacketListenerImpl.State getLoginState() { return this.state; }; // Paper - OBFHELPER + private int tick; +- private GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } private GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER ++ private GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } public GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER + private final String serverId; + private SecretKey secretKey; + private ServerPlayer delayedAcceptPlayer; diff --git a/Remapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch b/Remapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch new file mode 100644 index 0000000000..b1074d223b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 18 Dec 2018 02:15:08 +0000 +Subject: [PATCH] Prevent Enderman from loading chunks + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index d190b58bea310f4006ea3deaf0d42c502d441284..dae35d3f758e40c1edf31b11c6e11f1b7bb2dfae 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -434,7 +434,8 @@ public class EnderMan extends Monster implements NeutralMob { + int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 3.0D); + int k = Mth.floor(this.enderman.getZ() - 2.0D + random.nextDouble() * 4.0D); + BlockPos blockposition = new BlockPos(i, j, k); +- BlockState iblockdata = world.getBlockState(blockposition); ++ BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper ++ if (iblockdata == null) return; // Paper + Block block = iblockdata.getBlock(); + Vec3 vec3d = new Vec3((double) Mth.floor(this.enderman.getX()) + 0.5D, (double) j + 0.5D, (double) Mth.floor(this.enderman.getZ()) + 0.5D); + Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); +@@ -474,7 +475,8 @@ public class EnderMan extends Monster implements NeutralMob { + int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 2.0D); + int k = Mth.floor(this.enderman.getZ() - 1.0D + random.nextDouble() * 2.0D); + BlockPos blockposition = new BlockPos(i, j, k); +- BlockState iblockdata = world.getBlockState(blockposition); ++ BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper ++ if (iblockdata == null) return; // Paper + BlockPos blockposition1 = blockposition.below(); + BlockState iblockdata1 = world.getBlockState(blockposition1); + BlockState iblockdata2 = this.enderman.getCarriedBlock(); diff --git a/Remapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/Remapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch new file mode 100644 index 0000000000..491b5bd0f8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch @@ -0,0 +1,164 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Jan 2019 00:35:43 -0600 +Subject: [PATCH] Add APIs to replace OfflinePlayer#getLastPlayed + +Currently OfflinePlayer#getLastPlayed could more accurately be described +as "OfflinePlayer#getLastTimeTheirDataWasSaved". + +The API doc says it should return the last time the server "witnessed" +the player, whilst also saying it should return the last time they +logged in. The current implementation does neither. + +Given this interesting contradiction in the API documentation and the +current defacto implementation, I've elected to deprecate (with no +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 416c21f0a6be8d71a654e18f7ea0fa074f8fc5ff..1fa4f58658ff98396eb5abfc27e19e5832d56f5a 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -211,6 +211,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public int latency; + public boolean wonGame; + private int containerUpdateDelay; // Paper ++ public long loginTime; // Paper + // Paper start - cancellable death event + public boolean queueHealthUpdatePacket = false; + public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7c307a16ca3962db65be09a0ddd058a4ce81c7be..5b71b487836cdd2ddc75b2039f4dc0177719d345 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -164,6 +164,7 @@ public abstract class PlayerList { + } + + public void placeNewPlayer(Connection connection, ServerPlayer player) { ++ player.loginTime = System.currentTimeMillis(); // Paper + GameProfile gameprofile = player.getGameProfile(); + GameProfileCache usercache = this.server.getProfileCache(); + GameProfile gameprofile1 = usercache.get(gameprofile.getId()); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +index 1eeb1d1fe54eba68652be8dba52dce8ca91d948d..19aee8c6d0989bcf263e27adab42b3e6e411b66f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +@@ -244,6 +244,61 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa + return getData() != null; + } + ++ // Paper start ++ @Override ++ public long getLastLogin() { ++ Player player = getPlayer(); ++ if (player != null) return player.getLastLogin(); ++ ++ CompoundTag data = getPaperData(); ++ ++ if (data != null) { ++ if (data.contains("LastLogin")) { ++ return data.getLong("LastLogin"); ++ } else { ++ // if the player file cannot provide accurate data, this is probably the closest we can approximate ++ File file = getDataFile(); ++ return file.lastModified(); ++ } ++ } else { ++ return 0; ++ } ++ } ++ ++ @Override ++ public long getLastSeen() { ++ Player player = getPlayer(); ++ if (player != null) return player.getLastSeen(); ++ ++ CompoundTag data = getPaperData(); ++ ++ if (data != null) { ++ if (data.contains("LastSeen")) { ++ return data.getLong("LastSeen"); ++ } else { ++ // if the player file cannot provide accurate data, this is probably the closest we can approximate ++ File file = getDataFile(); ++ return file.lastModified(); ++ } ++ } else { ++ return 0; ++ } ++ } ++ ++ private CompoundTag getPaperData() { ++ CompoundTag result = getData(); ++ ++ if (result != null) { ++ if (!result.contains("Paper")) { ++ result.put("Paper", new CompoundTag()); ++ } ++ result = result.getCompound("Paper"); ++ } ++ ++ return result; ++ } ++ // Paper end ++ + @Override + public Location getBedSpawnLocation() { + CompoundTag data = getData(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index a3e65028d3e0c09a65cd9c28b037fe01a2ed1d76..ba03a1cdac68dc08ed878e311adeebc531e8f2f1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -144,6 +144,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; + private String resourcePackHash; + private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit ++ private long lastSaveTime; + // Paper end + + public CraftPlayer(CraftServer server, ServerPlayer entity) { +@@ -1480,6 +1481,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + this.firstPlayed = firstPlayed; + } + ++ // Paper start ++ @Override ++ public long getLastLogin() { ++ return getHandle().loginTime; ++ } ++ ++ @Override ++ public long getLastSeen() { ++ return isOnline() ? System.currentTimeMillis() : this.lastSaveTime; ++ } ++ // Paper end ++ + public void readExtraData(CompoundTag nbttagcompound) { + hasPlayedBefore = true; + if (nbttagcompound.contains("bukkit")) { +@@ -1502,6 +1515,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void setExtraData(CompoundTag nbttagcompound) { ++ this.lastSaveTime = System.currentTimeMillis(); // Paper ++ + if (!nbttagcompound.contains("bukkit")) { + nbttagcompound.put("bukkit", new CompoundTag()); + } +@@ -1516,6 +1531,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + data.putLong("firstPlayed", getFirstPlayed()); + data.putLong("lastPlayed", System.currentTimeMillis()); + data.putString("lastKnownName", handle.getScoreboardName()); ++ ++ // Paper start - persist for use in offline save data ++ if (!nbttagcompound.contains("Paper")) { ++ nbttagcompound.put("Paper", new CompoundTag()); ++ } ++ ++ CompoundTag paper = nbttagcompound.getCompound("Paper"); ++ paper.putLong("LastLogin", handle.loginTime); ++ paper.putLong("LastSeen", System.currentTimeMillis()); ++ // Paper end + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/Remapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch new file mode 100644 index 0000000000..4645205240 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: connorhartley +Date: Mon, 7 Jan 2019 14:43:48 -0600 +Subject: [PATCH] Workaround for vehicle tracking issue on disconnect + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 1fa4f58658ff98396eb5abfc27e19e5832d56f5a..fd2717a00a85f91ee23a1c0f929f856972892a9b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1524,6 +1524,13 @@ public class ServerPlayer extends Player implements ContainerListener { + public void disconnect() { + this.disconnected = true; + this.ejectPassengers(); ++ ++ // Paper start - Workaround an issue where the vehicle doesn't track the passenger disconnection dismount. ++ if (this.isPassenger() && this.getVehicle() instanceof ServerPlayer) { ++ this.stopRiding(); ++ } ++ // Paper end ++ + if (this.isSleeping()) { + this.stopSleepInBed(true, false); + } diff --git a/Remapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/Remapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch new file mode 100644 index 0000000000..7b22e86252 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 31 Jan 2019 16:33:36 -0500 +Subject: [PATCH] Fire BlockPistonRetractEvent for all empty pistons + +There is an explicit check in the handling code for empty pistons that +prevents sticky pistons from firing the event. However when we look back +at the history we see that this check was originally added so that ONLY +sticky pistons would fire the retract event. I'm not sure why. +https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1092acbddf07edfa4100bc6824504ac75088e913 + +Over the course of several updates, the meaning of that field appears to +have changed from "is NOT sticky" to "is sticky". So now its having the +opposite effect. Only normal pistons fire the retraction event. And like +all things in CB, it's just been carried around since. + +If we are to believe the history, the correct fix for this issue is to +flip it so it only fires for sticky pistons, but that puts us in a +bind. It's already firing for non-sticky pistons, changing it now would +likely result in breakage. Furthermore, there is little documentation as +to WHY that was ever intended to be the case. + +Instead we opt to remove the check entirely so that the event fires for +all piston types. + +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +index 878cec21b52fb62369310c2f85001e859a270dd8..dc9584a30c18d964afd9cc118c81c24a80beba63 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -140,7 +140,7 @@ public class PistonBaseBlock extends DirectionalBlock { + } + + // CraftBukkit start +- if (!this.isSticky) { ++ //if (!this.sticky) { // Paper - Prevents empty sticky pistons from firing retract - history behind is odd + org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); + BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); + world.getCraftServer().getPluginManager().callEvent(event); +@@ -148,7 +148,7 @@ public class PistonBaseBlock extends DirectionalBlock { + if (event.isCancelled()) { + return; + } +- } ++ //} // Paper + // PAIL: checkME - what happened to setTypeAndData? + // CraftBukkit end + world.blockEvent(pos, this, b0, enumdirection.get3DDataValue()); diff --git a/Remapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch b/Remapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch new file mode 100644 index 0000000000..8ac3978e9f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 4 Feb 2019 23:33:24 -0500 +Subject: [PATCH] Block Entity#remove from being called on Players + +This doesn't result in the same behavior as other entities and causes +several problems. Anyone ever complain about the "Cannot send chat +message" thing? That's one of the issues this causes, among others. + +If a plugin developer can come up with a valid reason to call this on a +Player we will look at limiting the scope of this change. It appears to +be unintentional in the few cases we've seen so far. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index ba03a1cdac68dc08ed878e311adeebc531e8f2f1..c2c6eb54096ef85b01c0b700cbe6a8054b62729f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2231,6 +2231,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public void resetCooldown() { + getHandle().resetAttackStrengthTicker(); + } ++ ++ @Override ++ public void remove() { ++ if (this.getHandle().getClass().equals(ServerPlayer.class)) { // special case for NMS plugins inheriting ++ throw new UnsupportedOperationException("Calling Entity#remove on players produces undefined (bad) behavior"); ++ } else { ++ super.remove(); ++ } ++ } + // Paper end + + // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch b/Remapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch new file mode 100644 index 0000000000..497abbdeb1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 Feb 2019 00:20:33 -0500 +Subject: [PATCH] BlockDestroyEvent + +Adds an event for when the server is going to destroy a current block, +potentially causing it to drop. This event can be cancelled to avoid +the block destruction, such as preventing signs from popping when +floating in the air. + +This can replace many uses of BlockPhysicsEvent + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index b75ffafb6840b6acab6e5b0ef5e222c4fa130977..c8542636e89748699d608eb29569cacb6321d334 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -27,6 +27,7 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundSetBorderPacket; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerLevel; +@@ -559,8 +560,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return false; + } else { + FluidState fluid = this.getFluidState(pos); ++ // Paper start - while the above setAir method is named same and looks very similar ++ // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent, ++ // it doesn't imply destruction of a block that plays a sound effect / drops an item. ++ boolean playEffect = true; ++ if (com.destroystokyo.paper.event.block.BlockDestroyEvent.getHandlerList().getRegisteredListeners().length > 0) { ++ com.destroystokyo.paper.event.block.BlockDestroyEvent event = new com.destroystokyo.paper.event.block.BlockDestroyEvent(MCUtil.toBukkitBlock(this, pos), fluid.createLegacyBlock().createCraftBlockData(), drop); ++ if (!event.callEvent()) { ++ return false; ++ } ++ playEffect = event.playEffect(); ++ } ++ // Paper end + +- if (!(iblockdata.getBlock() instanceof BaseFireBlock)) { ++ if (playEffect && !(iblockdata.getBlock() instanceof BaseFireBlock)) { // Paper + this.levelEvent(2001, pos, Block.getId(iblockdata)); + } + diff --git a/Remapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/Remapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch new file mode 100644 index 0000000000..941fce8c3e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Jan 2019 00:08:15 -0500 +Subject: [PATCH] Fix Custom Shapeless Custom Crafting Recipes + +Mojang implemented Shapeless different than Shaped + +This made the Bukkit RecipeChoice API not work for Shapeless. + +This reimplements vanilla logic using the same test logic as Shaped + +diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java +index 7bd62f598f3fff7520c276bdc45e538bd3260bc9..a8d0a90d36d58515bb6f6128de1ef15b72c20c17 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java ++++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java +@@ -71,16 +71,49 @@ public class ShapelessRecipe implements CraftingRecipe { + StackedContents autorecipestackmanager = new StackedContents(); + int i = 0; + ++ // Paper start ++ java.util.List providedItems = new java.util.ArrayList<>(); ++ co.aikar.util.Counter matchedProvided = new co.aikar.util.Counter<>(); ++ co.aikar.util.Counter matchedIngredients = new co.aikar.util.Counter<>(); ++ // Paper end + for (int j = 0; j < inv.getContainerSize(); ++j) { + ItemStack itemstack = inv.getItem(j); + + if (!itemstack.isEmpty()) { +- ++i; +- autorecipestackmanager.accountStack(itemstack, 1); ++ // Paper start ++ itemstack = itemstack.copy(); ++ providedItems.add(itemstack); ++ for (Ingredient ingredient : ingredients) { ++ if (ingredient.test(itemstack)) { ++ matchedProvided.increment(itemstack); ++ matchedIngredients.increment(ingredient); ++ } ++ } ++ // Paper end + } + } + +- return i == this.ingredients.size() && autorecipestackmanager.canCraft(this, (IntList) null); ++ // Paper start ++ if (matchedProvided.isEmpty() || matchedIngredients.isEmpty()) { ++ return false; ++ } ++ java.util.List ingredients = new java.util.ArrayList<>(this.ingredients); ++ providedItems.sort(java.util.Comparator.comparingInt((ItemStack c) -> (int) matchedProvided.getCount(c)).reversed()); ++ ingredients.sort(java.util.Comparator.comparingInt((Ingredient c) -> (int) matchedIngredients.getCount(c))); ++ ++ PROVIDED: ++ for (ItemStack provided : providedItems) { ++ for (Iterator itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) { ++ Ingredient ingredient = itIngredient.next(); ++ if (ingredient.test(provided)) { ++ itIngredient.remove(); ++ continue PROVIDED; ++ } ++ } ++ return false; ++ } ++ return ingredients.isEmpty(); ++ // Paper end + } + + public ItemStack assemble(CraftingContainer inv) { diff --git a/Remapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch b/Remapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch new file mode 100644 index 0000000000..cdc4ad71f6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 28 Feb 2019 00:15:28 -0500 +Subject: [PATCH] Fix sign edit memory leak + +when a player edits a sign, a reference to their Entity is never cleand up. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index b1c505d3fdcc2fb3496f80bee85e4895b9069dcb..276773e17149f57038cd21485fd9d9061670ff2d 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2850,7 +2850,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; + +- if (!tileentitysign.isEditable() || tileentitysign.getPlayerWhoMayEdit() != this.player) { ++ if (!tileentitysign.isEditable() || tileentitysign.signEditor == null || !tileentitysign.signEditor.equals(this.player.getUUID())) { + ServerGamePacketListenerImpl.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getName().getString()); + this.send(tileentity.getUpdatePacket()); // CraftBukkit + return; +diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +index e4eab82855649fec654c60b2e94ba7b71c2ac5a2..0b26d3ab2db66d6baaa95d1d5f6c756595d31495 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -30,6 +30,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + private Player playerWhoMayEdit; + private final FormattedCharSequence[] renderMessages; + private DyeColor color; ++ public java.util.UUID signEditor; // Paper + + public SignBlockEntity() { + super(BlockEntityType.SIGN); +@@ -131,7 +132,10 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + } + + public void setAllowedPlayerEditor(Player player) { +- this.playerWhoMayEdit = player; ++ // Paper start ++ //this.c = entityhuman; ++ signEditor = player != null ? player.getUUID() : null; ++ // Paper end + } + + public Player getPlayerWhoMayEdit() { diff --git a/Remapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch b/Remapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch new file mode 100644 index 0000000000..da033509aa --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 27 Feb 2019 22:18:40 -0500 +Subject: [PATCH] Limit Client Sign length more + +modified clients can send more data from the client +to the server and it would get stored on the sign as sent. + +Mojang has a limit of 384 which is much higher than reasonable. + +the client can barely render around 16 characters as-is, but formatting +codes can get it to be more than 16 actual length. + +Set a limit of 80 which should give an average of 16 characters 2 +sets of legacy formatting codes which should be plenty for all uses. + +This does not strip any existing data from the NBT as plugins +may use this for storing data out of the rendered area. + +it only impacts data sent from the client. + +Set -DPaper.maxSignLength=XX to change limit or -1 to disable + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 276773e17149f57038cd21485fd9d9061670ff2d..d6d8d83bc16572474d56a278dd119eacc2c52476 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -254,6 +254,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private int aboveGroundVehicleTickCount; + private int receivedMovePacketCount; + private int knownMovePacketCount; ++ private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); + private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit + + public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { +@@ -2860,7 +2861,17 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + List lines = new java.util.ArrayList<>(); + + for (int i = 0; i < list.size(); ++i) { +- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. ++ // Paper start - cap line length - modified clients can send longer data than normal ++ String currentLine = list.get(i); ++ if (MAX_SIGN_LINE_LENGTH > 0 && currentLine.length() > MAX_SIGN_LINE_LENGTH) { ++ // This handles multibyte characters as 1 ++ int offset = currentLine.codePoints().limit(MAX_SIGN_LINE_LENGTH).map(Character::charCount).sum(); ++ if (offset < currentLine.length()) { ++ list.set(i, currentLine = currentLine.substring(0, offset)); ++ } ++ } ++ // Paper end ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(currentLine))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. + } + SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); + this.craftServer.getPluginManager().callEvent(event); diff --git a/Remapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/Remapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch new file mode 100644 index 0000000000..e847f69596 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 2 Mar 2019 11:11:29 -0500 +Subject: [PATCH] Don't check ConvertSigns boolean every sign save + +property lookups arent super cheap. they synchronize, validate +and check security managers. + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +index 0b26d3ab2db66d6baaa95d1d5f6c756595d31495..8d619e0bf8bcf7d6d4e7f23f11d648ccfb65cac4 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -31,6 +31,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + private final FormattedCharSequence[] renderMessages; + private DyeColor color; + public java.util.UUID signEditor; // Paper ++ private static final boolean CONVERT_LEGACY_SIGNS = Boolean.getBoolean("convertLegacySigns"); // Paper + + public SignBlockEntity() { + super(BlockEntityType.SIGN); +@@ -51,7 +52,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + } + + // CraftBukkit start +- if (Boolean.getBoolean("convertLegacySigns")) { ++ if (CONVERT_LEGACY_SIGNS) { // Paper + tag.putBoolean("Bukkit.isConverted", true); + } + // CraftBukkit end diff --git a/Remapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/Remapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch new file mode 100644 index 0000000000..0dc4b2e085 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch @@ -0,0 +1,394 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 May 2020 04:53:35 -0400 +Subject: [PATCH] Optimize Network Manager and add advanced packet support + +Adds ability for 1 packet to bundle other packets to follow it +Adds ability for a packet to delay sending more packets until a state is ready. + +Removes synchronization from sending packets +Removes processing packet queue off of main thread + - for the few cases where it is allowed, order is not necessary nor + should it even be happening concurrently in first place (handshaking/login/status) + +Ensures packets sent asynchronously are dispatched on main thread + +This helps ensure safety for ProtocolLib as packet listeners +are commonly accessing world state. This will allow you to schedule +a packet to be sent async, but itll be dispatched sync for packet +listeners to process. + +This should solve some deadlock risks + +Also adds Netty Channel Flush Consolidation to reduce the amount of flushing + +Also avoids spamming closed channel exception by rechecking closed state in dispatch +and then catch exceptions and close if they fire. + +Part of this commit was authored by: Spottedleaf + +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed0b562c1b 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -25,8 +25,15 @@ import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketFlow; ++import net.minecraft.network.protocol.game.ClientboundBossEventPacket; ++import net.minecraft.network.protocol.game.ClientboundChatPacket; ++import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket; + import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; ++import net.minecraft.network.protocol.game.ClientboundKeepAlivePacket; ++import net.minecraft.network.protocol.game.ClientboundSetTitlesPacket; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.RunningOnDifferentThreadException; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.network.ServerGamePacketListenerImpl; + import net.minecraft.server.network.ServerLoginPacketListenerImpl; + import net.minecraft.util.LazyLoadedValue; +@@ -75,6 +82,10 @@ public class Connection extends SimpleChannelInboundHandler> { + public int protocolVersion; + public java.net.InetSocketAddress virtualHost; + private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); ++ // Optimize network ++ public boolean isPending = true; ++ public boolean queueImmunity = false; ++ public ConnectionProtocol protocol; + // Paper end + + public Connection(PacketFlow side) { +@@ -98,6 +109,7 @@ public class Connection extends SimpleChannelInboundHandler> { + } + + public void setProtocol(ConnectionProtocol state) { ++ protocol = state; // Paper + this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).set(state); + this.channel.config().setAutoRead(true); + Connection.LOGGER.debug("Enabled auto read"); +@@ -168,19 +180,84 @@ public class Connection extends SimpleChannelInboundHandler> { + Validate.notNull(listener, "packetListener", new Object[0]); + this.packetListener = listener; + } ++ // Paper start ++ public ServerPlayer getPlayer() { ++ if (packetListener instanceof ServerGamePacketListenerImpl) { ++ return ((ServerGamePacketListenerImpl) packetListener).player; ++ } else { ++ return null; ++ } ++ } ++ private static class InnerUtil { // Attempt to hide these methods from ProtocolLib so it doesn't accidently pick them up. ++ private static java.util.List buildExtraPackets(Packet packet) { ++ java.util.List extra = packet.getExtraPackets(); ++ if (extra == null || extra.isEmpty()) { ++ return null; ++ } ++ java.util.List ret = new java.util.ArrayList<>(1 + extra.size()); ++ buildExtraPackets0(extra, ret); ++ return ret; ++ } ++ ++ private static void buildExtraPackets0(java.util.List extraPackets, java.util.List into) { ++ for (Packet extra : extraPackets) { ++ into.add(extra); ++ java.util.List extraExtra = extra.getExtraPackets(); ++ if (extraExtra != null && !extraExtra.isEmpty()) { ++ buildExtraPackets0(extraExtra, into); ++ } ++ } ++ } ++ // Paper start ++ private static boolean canSendImmediate(Connection networkManager, Packet packet) { ++ return networkManager.isPending || networkManager.protocol != ConnectionProtocol.PLAY || ++ packet instanceof ClientboundKeepAlivePacket || ++ packet instanceof ClientboundChatPacket || ++ packet instanceof ClientboundCommandSuggestionsPacket || ++ packet instanceof ClientboundSetTitlesPacket || ++ packet instanceof ClientboundBossEventPacket; ++ } ++ // Paper end ++ } ++ // Paper end + + public void send(Packet packet) { + this.send(packet, (GenericFutureListener) null); + } + + public void send(Packet packet, @Nullable GenericFutureListener> callback) { +- if (this.isConnected()) { +- this.flushQueue(); +- this.sendPacket(packet, callback); +- } else { +- this.queue.add(new Connection.PacketHolder(packet, callback)); ++ // Paper start - handle oversized packets better ++ boolean connected = this.isConnected(); ++ if (!connected && !preparing) { ++ return; // Do nothing ++ } ++ packet.onPacketDispatch(getPlayer()); ++ if (connected && (InnerUtil.canSendImmediate(this, packet) || ( ++ MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() && ++ (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) ++ ))) { ++ this.dispatchPacket(packet, callback); ++ return; + } ++ // write the packets to the queue, then flush - antixray hooks there already ++ java.util.List extraPackets = InnerUtil.buildExtraPackets(packet); ++ boolean hasExtraPackets = extraPackets != null && !extraPackets.isEmpty(); ++ if (!hasExtraPackets) { ++ this.queue.add(new Connection.PacketHolder(packet, callback)); ++ } else { ++ java.util.List packets = new java.util.ArrayList<>(1 + extraPackets.size()); ++ packets.add(new Connection.PacketHolder(packet, null)); // delay the future listener until the end of the extra packets ++ ++ for (int i = 0, len = extraPackets.size(); i < len;) { ++ Packet extra = extraPackets.get(i); ++ boolean end = ++i == len; ++ packets.add(new Connection.PacketHolder(extra, end ? callback : null)); // append listener to the end ++ } + ++ this.queue.addAll(packets); // atomic ++ } ++ this.sendPacketQueue(); ++ // Paper end + } + + private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.sendPacket(packet, genericFutureListener); } // Paper - OBFHELPER +@@ -194,54 +271,119 @@ public class Connection extends SimpleChannelInboundHandler> { + this.channel.config().setAutoRead(false); + } + ++ ServerPlayer player = getPlayer(); // Paper + if (this.channel.eventLoop().inEventLoop()) { + if (enumprotocol != enumprotocol1) { + this.setProtocol(enumprotocol); + } ++ // Paper start ++ if (!isConnected()) { ++ packet.onPacketDispatchFinish(player, null); ++ return; ++ } ++ try { ++ // Paper end + + ChannelFuture channelfuture = this.channel.writeAndFlush(packet); + + if (callback != null) { + channelfuture.addListener(callback); + } ++ // Paper start ++ if (packet.hasFinishListener()) { ++ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); ++ } ++ // Paper end + + channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); ++ // Paper start ++ } catch (Exception e) { ++ LOGGER.error("NetworkException: " + player, e); ++ disconnect(new TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; ++ packet.onPacketDispatchFinish(player, null); ++ } ++ // Paper end + } else { + this.channel.eventLoop().execute(() -> { + if (enumprotocol != enumprotocol1) { + this.setProtocol(enumprotocol); + } + ++ // Paper start ++ if (!isConnected()) { ++ packet.onPacketDispatchFinish(player, null); ++ return; ++ } ++ try { ++ // Paper end + ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet); + ++ + if (callback != null) { + channelfuture1.addListener(callback); + } ++ // Paper start ++ if (packet.hasFinishListener()) { ++ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); ++ } ++ // Paper end + + channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); ++ // Paper start ++ } catch (Exception e) { ++ LOGGER.error("NetworkException: " + player, e); ++ disconnect(new TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; ++ packet.onPacketDispatchFinish(player, null); ++ } ++ // Paper end + }); + } + + } + +- private void sendPacketQueue() { this.flushQueue(); } // Paper - OBFHELPER +- private void flushQueue() { +- if (this.channel != null && this.channel.isOpen()) { +- Queue queue = this.queue; +- ++ // Paper start - rewrite this to be safer if ran off main thread ++ private boolean sendPacketQueue() { return this.p(); } // OBFHELPER // void -> boolean ++ private boolean p() { // void -> boolean ++ if (!isConnected()) { ++ return true; ++ } ++ if (MCUtil.isMainThread()) { ++ return processQueue(); ++ } else if (isPending) { ++ // Should only happen during login/status stages + synchronized (this.queue) { +- Connection.PacketHolder networkmanager_queuedpacket; +- +- while ((networkmanager_queuedpacket = (Connection.PacketHolder) this.queue.poll()) != null) { +- this.sendPacket(networkmanager_queuedpacket.packet, networkmanager_queuedpacket.listener); +- } ++ return this.processQueue(); ++ } ++ } ++ return false; ++ } ++ private boolean processQueue() { ++ if (this.queue.isEmpty()) return true; ++ // If we are on main, we are safe here in that nothing else should be processing queue off main anymore ++ // But if we are not on main due to login/status, the parent is synchronized on packetQueue ++ java.util.Iterator iterator = this.queue.iterator(); ++ while (iterator.hasNext()) { ++ Connection.PacketHolder queued = iterator.next(); // poll -> peek ++ ++ // Fix NPE (Spigot bug caused by handleDisconnection()) ++ if (queued == null) { ++ return true; ++ } + ++ Packet packet = queued.getPacket(); ++ if (!packet.isReady()) { ++ return false; ++ } else { ++ iterator.remove(); ++ this.dispatchPacket(packet, queued.getGenericFutureListener()); + } + } ++ return true; + } ++ // Paper end + + public void tick() { +- this.flushQueue(); ++ this.p(); + if (this.packetListener instanceof ServerLoginPacketListenerImpl) { + ((ServerLoginPacketListenerImpl) this.packetListener).tick(); + } +@@ -271,9 +413,21 @@ public class Connection extends SimpleChannelInboundHandler> { + return this.address; + } + ++ // Paper start ++ public void clearPacketQueue() { ++ ServerPlayer player = getPlayer(); ++ queue.forEach(queuedPacket -> { ++ Packet packet = queuedPacket.getPacket(); ++ if (packet.hasFinishListener()) { ++ packet.onPacketDispatchFinish(player, null); ++ } ++ }); ++ queue.clear(); ++ } // Paper end + public void disconnect(Component disconnectReason) { + // Spigot Start + this.preparing = false; ++ clearPacketQueue(); // Paper + // Spigot End + if (this.channel.isOpen()) { + this.channel.close(); // We can't wait as this may be called from an event loop. +@@ -341,7 +495,7 @@ public class Connection extends SimpleChannelInboundHandler> { + public void handleDisconnection() { + if (this.channel != null && !this.channel.isOpen()) { + if (this.disconnectionHandled) { +- Connection.LOGGER.warn("handleDisconnection() called twice"); ++ //NetworkManager.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message + } else { + this.disconnectionHandled = true; + if (this.getDisconnectedReason() != null) { +@@ -349,7 +503,7 @@ public class Connection extends SimpleChannelInboundHandler> { + } else if (this.getPacketListener() != null) { + this.getPacketListener().a(new TranslatableComponent("multiplayer.disconnect.generic")); + } +- this.queue.clear(); // Free up packet queue. ++ clearPacketQueue(); // Paper + // Paper start - Add PlayerConnectionCloseEvent + final PacketListener packetListener = this.getPacketListener(); + if (packetListener instanceof ServerGamePacketListenerImpl) { +diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java +index 9914a82ba0ec146ab13fe94c4dbf0ebf64926536..22db5d0d2cc33498ca40162c66aa3b5fbf2f569f 100644 +--- a/src/main/java/net/minecraft/network/protocol/Packet.java ++++ b/src/main/java/net/minecraft/network/protocol/Packet.java +@@ -1,5 +1,6 @@ + package net.minecraft.network.protocol; + ++import io.netty.channel.ChannelFuture; // Paper + import java.io.IOException; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.PacketListener; +@@ -13,6 +14,20 @@ public interface Packet { + void handle(T listener); + + // Paper start ++ ++ /** ++ * @param player Null if not at PLAY stage yet ++ */ ++ default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} ++ ++ /** ++ * @param player Null if not at PLAY stage yet ++ * @param future Can be null if packet was cancelled ++ */ ++ default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} ++ default boolean hasFinishListener() { return false; } ++ default boolean isReady() { return true; } ++ default java.util.List getExtraPackets() { return null; } + default boolean packetTooLarge(NetworkManager manager) { + return false; + } +diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +index 6cb51a4fe3c11f53fbb556ce6b0d64b735254d51..d46910cfdc0aef046a0c79731a85d381953c328a 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +@@ -16,6 +16,7 @@ import io.netty.channel.epoll.EpollServerSocketChannel; + import io.netty.channel.nio.NioEventLoopGroup; + import io.netty.channel.socket.ServerSocketChannel; + import io.netty.channel.socket.nio.NioServerSocketChannel; ++import io.netty.handler.flush.FlushConsolidationHandler; // Paper + import io.netty.handler.timeout.ReadTimeoutHandler; + import java.io.IOException; + import java.net.InetAddress; +@@ -54,10 +55,12 @@ public class ServerConnectionListener { + private final List connections = Collections.synchronizedList(Lists.newArrayList()); + // Paper start - prevent blocking on adding a new network manager while the server is ticking + private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ private static final boolean disableFlushConsolidation = Boolean.getBoolean("Paper.disableFlushConsolidate"); // Paper + private void addPending() { + Connection manager = null; + while ((manager = pending.poll()) != null) { + connections.add(manager); ++ manager.isPending = false; + } + } + // Paper end +@@ -92,6 +95,7 @@ public class ServerConnectionListener { + ; + } + ++ if (!disableFlushConsolidation) channel.pipeline().addFirst(new FlushConsolidationHandler()); // Paper + channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyQueryHandler(ServerConnectionListener.this)).addLast("splitter", new Varint21FrameDecoder()).addLast("decoder", new PacketDecoder(PacketFlow.SERVERBOUND)).addLast("prepender", new Varint21LengthFieldPrepender()).addLast("encoder", new PacketEncoder(PacketFlow.CLIENTBOUND)); + int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); + Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); diff --git a/Remapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch b/Remapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch new file mode 100644 index 0000000000..83303e9b30 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 May 2020 05:00:57 -0400 +Subject: [PATCH] Handle Oversized Tile Entities in chunks + +Splits out Extra Packets if too many TE's are encountered to prevent +creating too large of a packet to sed. + +Co authored by Spottedleaf + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index b7d303b5f51a35504888933efef74564fa01e59d..b587f774c8f88f2a1c3ea489f7e4fe0bbdeb5a41 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -34,7 +34,15 @@ public class ClientboundLevelChunkPacket implements Packet extraPackets = new java.util.ArrayList<>(); ++ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); + ++ @Override ++ public java.util.List getExtraPackets() { ++ return extraPackets; ++ } ++ // Paper end + public ClientboundLevelChunkPacket(LevelChunk chunk, int includedSectionsMask) { + ChunkPos chunkcoordintpair = chunk.getPos(); + +@@ -61,6 +69,7 @@ public class ClientboundLevelChunkPacket implements Packet> 4; + + if (this.isFullChunk() || (includedSectionsMask & 1 << j) != 0) { ++ // Paper start - improve oversized chunk data packet handling ++ if (++totalTileEntities > TE_LIMIT) { ++ ClientboundBlockEntityDataPacket updatePacket = tileentity.getUpdatePacket(); ++ if (updatePacket != null) { ++ this.extraPackets.add(updatePacket); ++ continue; ++ } ++ } ++ // Paper end + CompoundTag nbttagcompound = tileentity.getUpdateTag(); + if (tileentity instanceof SkullBlockEntity) { SkullBlockEntity.sanitizeTileEntityUUID(nbttagcompound); } // Paper + diff --git a/Remapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/Remapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch new file mode 100644 index 0000000000..1209aa99ea --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 2 Mar 2019 16:12:35 -0500 +Subject: [PATCH] MC-145260: Fix Whitelist On/Off inconsistency + +mojang stored whitelist state in 2 places (Whitelist Object, PlayerList) + +some things checked PlayerList, some checked object. This moves +everything to the Whitelist object. + +https://github.com/PaperMC/Paper/issues/1880 + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 5b71b487836cdd2ddc75b2039f4dc0177719d345..8d133d3c825f7747081de99ee67d4556e5c19cdd 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -55,6 +55,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.PlayerAdvancements; + import net.minecraft.server.ServerScoreboard; +@@ -1012,9 +1013,9 @@ public abstract class PlayerList { + } + public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { + boolean isOp = this.ops.contains(gameprofile); +- boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile); ++ boolean isWhitelisted = !this.isUsingWhitelist() || isOp || this.whitelist.contains(gameprofile); + final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; +- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); ++ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.isUsingWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); + event.callEvent(); + if (!event.isWhitelisted()) { + if (loginEvent != null) { +@@ -1062,7 +1063,7 @@ public abstract class PlayerList { + MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main + MinecraftTimings.savePlayers.startTiming(); // Paper + for (int i = 0; i < this.players.size(); ++i) { +- this.savePlayerFile((EntityPlayer) this.players.get(i)); ++ this.save((ServerPlayer) this.players.get(i)); + } + MinecraftTimings.savePlayers.stopTiming(); // Paper + return null; }); // Paper - ensure main diff --git a/Remapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/Remapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch new file mode 100644 index 0000000000..eb4f5ff56c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 4 Mar 2019 02:23:28 -0500 +Subject: [PATCH] Set Zombie last tick at start of drowning process + +Fixes GH-1887 + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index ad4eeb15771750193a28116117992270c72a3644..6fecf4188fc0247143edc688c03e645376960687 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -220,6 +220,7 @@ public class Zombie extends Monster { + ++this.inWaterTime; + if (this.inWaterTime >= 600) { + this.startUnderWaterConversion(300); ++ this.lastTick = MinecraftServer.currentTick; // Paper - Make sure this is set at start of process - GH-1887 + } + } else { + this.inWaterTime = -1; diff --git a/Remapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch b/Remapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch new file mode 100644 index 0000000000..c23cb450e8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch @@ -0,0 +1,271 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 15 Feb 2019 01:08:19 -0500 +Subject: [PATCH] Allow Saving of Oversized Chunks + +The Minecraft World Region File format has a hard cap of 1MB per chunk. +This is due to the fact that the header of the file format only allocates +a single byte for sector count, meaning a maximum of 256 sectors, at 4k per sector. + +This limit can be reached fairly easily with books, resulting in the chunk being unable +to save to the world. Worse off, is that nothing printed when this occured, and silently +performed a chunk rollback on next load. + +This leads to security risk with duplication and is being actively exploited. + +This patch catches the too large scenario, falls back and moves any large Entity +or Tile Entity into a new compound, and this compound is saved into a different file. + +On Chunk Load, we check for oversized status, and if so, we load the extra file and +merge the Entities and Tile Entities from the oversized chunk back into the level to +then be loaded as normal. + +Once a chunk is returned back to normal size, the oversized flag will clear, and no +extra data file will exist. + +This fix maintains compatability with all existing Anvil Region Format tools as it +does not alter the save format. They will just not know about the extra entities. + +This fix also maintains compatability if someone switches server jars to one without +this fix, as the data will remain in the oversized file. Once the server returns +to a jar with this fix, the data will be restored. + +diff --git a/src/main/java/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java +index c4fbc0bc8b80d16f09d3c6642acc7476a0817868..b3838e709c1581c25da7738c9a03a827761845b1 100644 +--- a/src/main/java/net/minecraft/nbt/NbtIo.java ++++ b/src/main/java/net/minecraft/nbt/NbtIo.java +@@ -132,6 +132,7 @@ public class NbtIo { + + } + ++ public static CompoundTag readNBT(DataInput datainput) throws IOException { return read(datainput); } // Paper - OBFHELPER + public static CompoundTag read(DataInput input) throws IOException { + return read(input, NbtAccounter.UNLIMITED); + } +@@ -152,6 +153,7 @@ public class NbtIo { + } + } + ++ public static void writeNBT(CompoundTag nbttagcompound, DataOutput dataoutput) throws IOException { write(nbttagcompound, dataoutput); } // Paper - OBFHELPER + public static void write(CompoundTag tag, DataOutput output) throws IOException { + writeUnnamedTag((Tag) tag, output); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 1aa4d342b97f8be71c108194a6f1e0e2828aa364..424628c9588c02454558bc7e7c5bad3a3e75ec9f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -20,8 +20,12 @@ import java.nio.file.LinkOption; + import java.nio.file.Path; + import java.nio.file.StandardCopyOption; + import java.nio.file.StandardOpenOption; ++import java.util.zip.InflaterInputStream; // Paper ++ + import javax.annotation.Nullable; + import net.minecraft.Util; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtIo; + import net.minecraft.world.level.ChunkPos; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -38,6 +42,7 @@ public class RegionFile implements AutoCloseable { + private final IntBuffer timestamps; + @VisibleForTesting + protected final RegionBitmap usedSectors; ++ public final File file; // Paper + + public RegionFile(File file, File directory, boolean dsync) throws IOException { + this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); +@@ -45,6 +50,8 @@ public class RegionFile implements AutoCloseable { + + public RegionFile(Path file, Path directory, RegionFileVersion outputChunkStreamVersion, boolean dsync) throws IOException { + this.header = ByteBuffer.allocateDirect(8192); ++ this.file = file.toFile(); // Paper ++ initOversizedState(); // Paper + this.usedSectors = new RegionBitmap(); + this.version = outputChunkStreamVersion; + if (!Files.isDirectory(directory, new LinkOption[0])) { +@@ -408,6 +415,74 @@ public class RegionFile implements AutoCloseable { + void run() throws IOException; + } + ++ // Paper start ++ private final byte[] oversized = new byte[1024]; ++ private int oversizedCount = 0; ++ ++ private synchronized void initOversizedState() throws IOException { ++ File metaFile = getOversizedMetaFile(); ++ if (metaFile.exists()) { ++ final byte[] read = java.nio.file.Files.readAllBytes(metaFile.toPath()); ++ System.arraycopy(read, 0, oversized, 0, oversized.length); ++ for (byte temp : oversized) { ++ oversizedCount += temp; ++ } ++ } ++ } ++ ++ private static int getChunkIndex(int x, int z) { ++ return (x & 31) + (z & 31) * 32; ++ } ++ synchronized boolean isOversized(int x, int z) { ++ return this.oversized[getChunkIndex(x, z)] == 1; ++ } ++ synchronized void setOversized(int x, int z, boolean oversized) throws IOException { ++ final int offset = getChunkIndex(x, z); ++ boolean previous = this.oversized[offset] == 1; ++ this.oversized[offset] = (byte) (oversized ? 1 : 0); ++ if (!previous && oversized) { ++ oversizedCount++; ++ } else if (!oversized && previous) { ++ oversizedCount--; ++ } ++ if (previous && !oversized) { ++ File oversizedFile = getOversizedFile(x, z); ++ if (oversizedFile.exists()) { ++ oversizedFile.delete(); ++ } ++ } ++ if (oversizedCount > 0) { ++ if (previous != oversized) { ++ writeOversizedMeta(); ++ } ++ } else if (previous) { ++ File oversizedMetaFile = getOversizedMetaFile(); ++ if (oversizedMetaFile.exists()) { ++ oversizedMetaFile.delete(); ++ } ++ } ++ } ++ ++ private void writeOversizedMeta() throws IOException { ++ java.nio.file.Files.write(getOversizedMetaFile().toPath(), oversized); ++ } ++ ++ private File getOversizedMetaFile() { ++ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + ".oversized.nbt"); ++ } ++ ++ private File getOversizedFile(int x, int z) { ++ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); ++ } ++ ++ synchronized CompoundTag getOversizedData(int x, int z) throws IOException { ++ File file = getOversizedFile(x, z); ++ try (DataInputStream out = new DataInputStream(new BufferedInputStream(new InflaterInputStream(new java.io.FileInputStream(file))))) { ++ return NbtIo.readNBT((java.io.DataInput) out); ++ } ++ ++ } ++ // Paper end + class ChunkBuffer extends ByteArrayOutputStream { + + private final ChunkPos pos; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index f33a5fc725d1d5e895f8878d82ebc4172237ad29..6d3e1bb20d1ab8ce5c9ea613322042d80550761a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -10,7 +10,9 @@ import java.io.File; + import java.io.IOException; + import javax.annotation.Nullable; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtIo; ++import net.minecraft.nbt.Tag; + import net.minecraft.server.MinecraftServer; + import net.minecraft.util.ExceptionCollector; + import net.minecraft.world.level.ChunkPos; +@@ -50,6 +52,74 @@ public final class RegionFileStorage implements AutoCloseable { + } + } + ++ // Paper start ++ private static void printOversizedLog(String msg, File file, int x, int z) { ++ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); ++ } ++ ++ private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 8; ++ private static final int OVERZEALOUS_TOTAL_THRESHOLD = 1024 * 64; ++ private static final int OVERZEALOUS_THRESHOLD = 1024; ++ private static int SIZE_THRESHOLD = DEFAULT_SIZE_THRESHOLD; ++ private static void resetFilterThresholds() { ++ SIZE_THRESHOLD = Math.max(1024 * 4, Integer.getInteger("Paper.FilterThreshhold", DEFAULT_SIZE_THRESHOLD)); ++ } ++ static { ++ resetFilterThresholds(); ++ } ++ ++ static boolean isOverzealous() { ++ return SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD; ++ } ++ ++ ++ private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException { ++ synchronized (regionfile) { ++ try (DataInputStream datainputstream = regionfile.getReadStream(chunkCoordinate)) { ++ CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); ++ CompoundTag chunk = NbtIo.readNBT((DataInput) datainputstream); ++ if (oversizedData == null) { ++ return chunk; ++ } ++ CompoundTag oversizedLevel = oversizedData.getCompound("Level"); ++ CompoundTag level = chunk.getCompound("Level"); ++ ++ mergeChunkList(level, oversizedLevel, "Entities"); ++ mergeChunkList(level, oversizedLevel, "TileEntities"); ++ ++ chunk.put("Level", level); ++ ++ return chunk; ++ } catch (Throwable throwable) { ++ throwable.printStackTrace(); ++ throw throwable; ++ } ++ } ++ } ++ ++ private static void mergeChunkList(CompoundTag level, CompoundTag oversizedLevel, String key) { ++ ListTag levelList = level.getList(key, 10); ++ ListTag oversizedList = oversizedLevel.getList(key, 10); ++ ++ if (!oversizedList.isEmpty()) { ++ levelList.addAll(oversizedList); ++ level.put(key, levelList); ++ } ++ } ++ ++ private static int getNBTSize(Tag nbtBase) { ++ DataOutputStream test = new DataOutputStream(new org.apache.commons.io.output.NullOutputStream()); ++ try { ++ nbtBase.write(test); ++ return test.size(); ++ } catch (IOException e) { ++ e.printStackTrace(); ++ return 0; ++ } ++ } ++ ++ // Paper End ++ + @Nullable + public CompoundTag read(ChunkPos pos) throws IOException { + // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing +@@ -59,6 +129,12 @@ public final class RegionFileStorage implements AutoCloseable { + } + // CraftBukkit end + DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); ++ // Paper start ++ if (regionfile.isOversized(pos.x, pos.z)) { ++ printOversizedLog("Loading Oversized Chunk!", regionfile.file, pos.x, pos.z); ++ return readOversizedChunk(regionfile, pos); ++ } ++ // Paper end + Throwable throwable = null; + + CompoundTag nbttagcompound; +@@ -99,6 +175,7 @@ public final class RegionFileStorage implements AutoCloseable { + + try { + NbtIo.write(tag, (DataOutput) dataoutputstream); ++ regionfile.setOversized(pos.x, pos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone + } catch (Throwable throwable1) { + throwable = throwable1; + throw throwable1; diff --git a/Remapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/Remapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch new file mode 100644 index 0000000000..5fcbc4df8c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Wed, 13 Mar 2019 20:08:09 +0200 +Subject: [PATCH] Call WhitelistToggleEvent when whitelist is toggled + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 8d133d3c825f7747081de99ee67d4556e5c19cdd..728eaadd3dc619e414ec30feb38c7d4a84b2e539 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1131,6 +1131,7 @@ public abstract class PlayerList { + } + + public void setUsingWhiteList(boolean whitelistEnabled) { ++ new com.destroystokyo.paper.event.server.WhitelistToggleEvent(whitelistEnabled).callEvent(); + this.doWhiteList = whitelistEnabled; + } + diff --git a/Remapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch b/Remapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch new file mode 100644 index 0000000000..d02aab104b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch @@ -0,0 +1,187 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 22 Sep 2018 00:33:08 -0500 +Subject: [PATCH] Add LivingEntity#getTargetEntity + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index c5d6235a132818dfc78105e9d03d0687f697bb00..d106118dbf4fb270f8526e40a767dd4c563a333f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1503,6 +1503,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.calculateViewVector(pitch - 90.0F, yaw); + } + ++ public final Vec3 getEyePosition(float partialTicks) { return getEyePosition(partialTicks); } // Paper - OBFHELPER + public final Vec3 getEyePosition(float tickDelta) { + if (tickDelta == 1.0F) { + return new Vec3(this.getX(), this.getEyeY(), this.getZ()); +@@ -2153,6 +2154,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.getPassengers().size() < 1; + } + ++ public final float getCollisionBorderSize() { return getPickRadius(); } // Paper - OBFHELPER + public float getPickRadius() { + return 0.0F; + } +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index e92a8c4c49c452e1f3f0c06398f2a74e3432262f..d3640975c5a33b4911428760691215905b987385 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -22,6 +22,7 @@ public final class EntitySelector { + public static final Predicate NO_CREATIVE_OR_SPECTATOR = (entity) -> { + return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative(); + }; ++ public static Predicate canAITarget() { return ATTACK_ALLOWED; } // Paper - OBFHELPER + public static final Predicate ATTACK_ALLOWED = (entity) -> { + return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative() && entity.level.getDifficulty() != Difficulty.PEACEFUL; + }; +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 29d4ed42e5d763639a50d849ef274c4d848bc9c9..046a05925739005080af35c4be984303b575bf68 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -108,6 +108,7 @@ import net.minecraft.world.level.storage.loot.LootTable; + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.PlayerTeam; +@@ -3657,6 +3658,37 @@ public abstract class LivingEntity extends Entity { + return level.clip(raytrace); + } + ++ public EntityHitResult getTargetEntity(int maxDistance) { ++ if (maxDistance < 1 || maxDistance > 120) { ++ throw new IllegalArgumentException("maxDistance must be between 1-120"); ++ } ++ ++ Vec3 start = this.getEyePosition(1.0F); ++ Vec3 direction = this.getLookAngle(); ++ Vec3 end = start.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance); ++ ++ List entityList = level.getEntities(this, getBoundingBox().expand(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance).inflate(1.0D, 1.0D, 1.0D), EntitySelector.canAITarget().and(Entity::isPickable)); ++ ++ double distance = 0.0D; ++ EntityHitResult result = null; ++ ++ for (Entity entity : entityList) { ++ AABB aabb = entity.getBoundingBox().grow((double) entity.getCollisionBorderSize()); ++ Optional rayTraceResult = aabb.calculateIntercept(start, end); ++ ++ if (rayTraceResult.isPresent()) { ++ Vec3 rayTrace = rayTraceResult.get(); ++ double distanceTo = start.distanceToSqr(rayTrace); ++ if (distanceTo < distance || distance == 0.0D) { ++ result = new EntityHitResult(entity, rayTrace); ++ distance = distanceTo; ++ } ++ } ++ } ++ ++ return result; ++ } ++ + public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; + + public int getShieldBlockingDelay() { +diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java +index 983d0495ec35128ca3ef68566ada065bc4b21efc..143a160a7577e9e34d34a9f3b900db03d3f297af 100644 +--- a/src/main/java/net/minecraft/world/phys/AABB.java ++++ b/src/main/java/net/minecraft/world/phys/AABB.java +@@ -116,6 +116,7 @@ public class AABB { + return this.expandTowards(scale.x, scale.y, scale.z); + } + ++ public final AABB expand(double x, double y, double z) { return expandTowards(x, y, z); } // Paper - OBFHELPER + public AABB expandTowards(double x, double y, double z) { + double d3 = this.minX; + double d4 = this.minY; +@@ -145,6 +146,12 @@ public class AABB { + return new AABB(d3, d4, d5, d6, d7, d8); + } + ++ // Paper start ++ public AABB grow(double d0) { ++ return inflate(d0, d0, d0); ++ } ++ // Paper end ++ + public AABB inflate(double x, double y, double z) { + double d3 = this.minX - x; + double d4 = this.minY - y; +@@ -204,6 +211,7 @@ public class AABB { + return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ; + } + ++ public final boolean contains(Vec3 vec3d) { return contains(vec3d); } // Paper - OBFHELPER + public boolean contains(Vec3 vec) { + return this.contains(vec.x, vec.y, vec.z); + } +@@ -237,6 +245,7 @@ public class AABB { + return this.inflate(-value); + } + ++ public final Optional calculateIntercept(Vec3 vec3d, Vec3 vec3d1) { return clip(vec3d, vec3d1); } // Paper - OBFHELPER + public Optional clip(Vec3 min, Vec3 max) { + double[] adouble = new double[]{1.0D}; + double d0 = max.x - min.x; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 7e3a215f1592bed9f35e22076d9e35a5a49a430e..a01bd035846df0e2e28dc55e2ef2f5f35b83f905 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -1,6 +1,7 @@ + package org.bukkit.craftbukkit.entity; + + import com.destroystokyo.paper.block.TargetBlockInfo; ++import com.destroystokyo.paper.entity.TargetEntityInfo; + import com.google.common.base.Preconditions; + import com.google.common.collect.Sets; + import java.util.ArrayList; +@@ -30,8 +31,11 @@ import net.minecraft.world.entity.projectile.ThrownEgg; + import net.minecraft.world.entity.projectile.ThrownEnderpearl; + import net.minecraft.world.entity.projectile.ThrownExperienceBottle; + import net.minecraft.world.entity.projectile.ThrownTrident; ++import net.minecraft.world.level.ClipContext; + import net.minecraft.world.phys.BlockHitResult; ++import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang.Validate; + import org.bukkit.FluidCollisionMode; + import org.bukkit.Location; +@@ -215,6 +219,33 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + new TargetBlockInfo(CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()), + MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection())); + } ++ ++ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks) { ++ EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); ++ return rayTrace == null ? null : rayTrace.getEntity().getBukkitEntity(); ++ } ++ ++ public TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks) { ++ EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); ++ return rayTrace == null ? null : new TargetEntityInfo(rayTrace.getEntity().getBukkitEntity(), new org.bukkit.util.Vector(rayTrace.getLocation().x, rayTrace.getLocation().y, rayTrace.getLocation().z)); ++ } ++ ++ public EntityHitResult rayTraceEntity(int maxDistance, boolean ignoreBlocks) { ++ EntityHitResult rayTrace = getHandle().getTargetEntity(maxDistance); ++ if (rayTrace == null) { ++ return null; ++ } ++ if (!ignoreBlocks) { ++ HitResult rayTraceBlocks = getHandle().getRayTrace(maxDistance, ClipContext.Fluid.NONE); ++ if (rayTraceBlocks != null) { ++ Vec3 eye = getHandle().getEyePosition(1.0F); ++ if (eye.distanceToSqr(rayTraceBlocks.getLocation()) <= eye.distanceToSqr(rayTrace.getLocation())) { ++ return null; ++ } ++ } ++ } ++ return rayTrace; ++ } + // Paper end + + @Override diff --git a/Remapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/Remapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch new file mode 100644 index 0000000000..c6e42c264d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 20 Mar 2019 21:19:29 -0700 +Subject: [PATCH] Use proper max length when serialising BungeeCord text + component + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +index f13da9e7d014bc00fbabf0a495b548bba2f59468..002a6c7933f64405707d7d34d3e5c17584539623 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +@@ -9,7 +9,7 @@ import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.Packet; + + public class ClientboundChatPacket implements Packet { +- ++ private static final int MAX_LENGTH = Short.MAX_VALUE * 8 + 8; // Paper + private Component message; + public net.kyori.adventure.text.Component adventure$message; // Paper + public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot +@@ -43,9 +43,9 @@ public class ClientboundChatPacket implements Packet { + //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below + // Paper start - don't nest if we don't need to so that we can preserve formatting + if (this.components.length == 1) { +- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); ++ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]), MAX_LENGTH); // Paper - use proper max length + } else { +- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); ++ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components), MAX_LENGTH); // Paper - use proper max length + } + // Paper end + } else { diff --git a/Remapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch b/Remapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch new file mode 100644 index 0000000000..18095e343f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Mar 2019 00:24:52 -0400 +Subject: [PATCH] Entity#getEntitySpawnReason + +Allows you to return the SpawnReason for why an Entity Spawned + +Pre existing entities will return NATURAL if it was a non +persistenting Living Entity, SPAWNER for spawners, +or DEFAULT since data was not stored. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 2ab221e5315dde4e556ee49a6962ae0091ccf616..d03b4f97102dfb88927a94ee5a5d397ac493eaa1 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1035,6 +1035,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // CraftBukkit start + private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot ++ if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper + // Paper start + if (entity.valid) { + MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 728eaadd3dc619e414ec30feb38c7d4a84b2e539..4d813b6556030354f51c1ee5f18eac2166b44576 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -331,7 +331,7 @@ public abstract class PlayerList { + // CraftBukkit start + ServerLevel finalWorldServer = worldserver1; + Entity entity = EntityType.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { +- return !finalWorldServer.addWithUUID(entity1) ? null : entity1; ++ return !finalWorldServer.addEntitySerialized(entity1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity1; // Paper + // CraftBukkit end + }); + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f311e197f6e 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -63,6 +63,8 @@ import net.minecraft.world.InteractionHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.Nameable; + import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.animal.AbstractFish; ++import net.minecraft.world.entity.animal.Animal; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.Boat; +@@ -157,6 +159,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + }; + public List entitySlice = null; ++ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; + // Paper end + + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper +@@ -1673,6 +1676,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); + tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); + } ++ if (spawnReason != null) { ++ tag.putString("Paper.SpawnReason", spawnReason.name()); ++ } + // Save entity's from mob spawner status + if (spawnedViaMobSpawner) { + tag.putBoolean("Paper.FromMobSpawner", true); +@@ -1811,6 +1817,26 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ if (tag.contains("Paper.SpawnReason")) { ++ String spawnReasonName = tag.getString("Paper.SpawnReason"); ++ try { ++ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName); ++ } catch (Exception ignored) { ++ LogManager.getLogger().error("Unknown SpawnReason " + spawnReasonName + " for " + this); ++ } ++ } ++ if (spawnReason == null) { ++ if (spawnedViaMobSpawner) { ++ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; ++ } else if (this instanceof Mob && (this instanceof Animal || this instanceof AbstractFish) && !((Mob) this).removeWhenFarAway(0.0)) { ++ if (!tag.getBoolean("PersistenceRequired")) { ++ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL; ++ } ++ } ++ } ++ if (spawnReason == null) { ++ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; ++ } + // Paper end + + } catch (Throwable throwable) { +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 1ce675d0d24ceb5724f5ac2d8f671e38f2735f74..3a7aec9bd2f3fd1b4a1981fb6a8c64b69e4875f8 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -183,6 +183,7 @@ public abstract class BaseSpawner { + // Spigot End + } + entity.spawnedViaMobSpawner = true; // Paper ++ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper + flag = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index e1bbaf620f3ed2a6cb9ce8007a78c4cee47b653e..7ad4fb57af32cc1b8278688381e1b058ed8437db 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1106,5 +1106,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public boolean fromMobSpawner() { + return getHandle().spawnedViaMobSpawner; + } ++ ++ @Override ++ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { ++ return getHandle().spawnReason; ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch b/Remapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch new file mode 100644 index 0000000000..8f0ddb740c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AgentTroll +Date: Fri, 22 Mar 2019 22:24:03 -0700 +Subject: [PATCH] Update entity Metadata for all tracked players + + +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index 49c71b21b6b88bc41ca6ddf4c76186ce522ee456..1609ab94c86e964421f996d4d46aef30f8b8e696 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -420,6 +420,12 @@ public class ServerEntity { + return ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp); + } + ++ // Paper start - Add broadcast method ++ void broadcast(Packet packet) { ++ this.getPacketConsumer().accept(packet); ++ } ++ // Paper end ++ + private void broadcastAndSend(Packet packet) { + this.broadcast.accept(packet); + if (this.entity instanceof ServerPlayer) { +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index d6d8d83bc16572474d56a278dd119eacc2c52476..ed4129a51351aff16455960d71a0add1b8209c02 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2286,7 +2286,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + if (event.isCancelled() || this.player.inventory.getSelected() == null || this.player.inventory.getSelected().getItem() != origItem) { + // Refresh the current entity metadata +- this.send(new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true)); ++ // Paper start - update entity for all players ++ ClientboundSetEntityDataPacket packet1 = new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true); ++ if (entity.tracker != null) { ++ entity.tracker.broadcast(packet1); ++ } else { ++ this.send(packet1); ++ } ++ // Paper end + } + + if (event.isCancelled()) { diff --git a/Remapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch b/Remapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch new file mode 100644 index 0000000000..dbfcbf2e3f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MisterVector +Date: Fri, 26 Oct 2018 21:31:00 -0700 +Subject: [PATCH] Implement PlayerPostRespawnEvent + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 4d813b6556030354f51c1ee5f18eac2166b44576..7412765020854caabd32fb6f4fffcf7f4bf6dba7 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -737,9 +737,14 @@ public abstract class PlayerList { + // this.a(entityplayer1, entityplayer, worldserver1); // CraftBukkit - removed + boolean flag2 = false; + ++ // Paper start ++ boolean isBedSpawn = false; ++ boolean isRespawn = false; ++ // Paper end ++ + // CraftBukkit start - fire PlayerRespawnEvent + if (location == null) { +- boolean isBedSpawn = false; ++ // boolean isBedSpawn = false; // Paper - moved up + ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); + if (worldserver1 != null) { + Optional optional; +@@ -790,6 +795,7 @@ public abstract class PlayerList { + + location = respawnEvent.getRespawnLocation(); + if (!flag) entityplayer.reset(); // SPIGOT-4785 ++ isRespawn = true; // Paper + } else { + location.setWorld(worldserver.getWorld()); + } +@@ -847,6 +853,13 @@ public abstract class PlayerList { + if (entityplayer.connection.isDisconnected()) { + this.save(entityplayer); + } ++ ++ // Paper start ++ if (isRespawn) { ++ cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(entityplayer.getBukkitEntity(), location, isBedSpawn)); ++ } ++ // Paper end ++ + // CraftBukkit end + return entityplayer1; + } diff --git a/Remapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/Remapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch new file mode 100644 index 0000000000..df8e4e2e9a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Mar 2019 18:09:20 -0400 +Subject: [PATCH] don't go below 0 for pickupDelay, breaks picking up items + +vanilla checks for == 0 + +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 70f719ba3c68c8e9414e6b4bc68002f7c962e2b9..281f5646980afc70890bdafd358ff9b20d32420d 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -86,6 +86,7 @@ public class ItemEntity extends Entity { + // CraftBukkit start - Use wall time for pickup and despawn timers + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; ++ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 + if (this.age != -32768) this.age += elapsedTicks; + this.lastTick = MinecraftServer.currentTick; + // CraftBukkit end +@@ -178,6 +179,7 @@ public class ItemEntity extends Entity { + // CraftBukkit start - Use wall time for pickup and despawn timers + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; ++ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 + if (this.age != -32768) this.age += elapsedTicks; + this.lastTick = MinecraftServer.currentTick; + // CraftBukkit end diff --git a/Remapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch b/Remapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch new file mode 100644 index 0000000000..9fb3057ffc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 27 Mar 2019 22:48:45 -0400 +Subject: [PATCH] Server Tick Events + +Fires event at start and end of a server tick + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 6ccc0be795e3ac7689de0eff6f9142d13161a29c..35984c7e994570a909ed4ffaabe64ae941b15e71 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1237,6 +1237,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Wed, 27 Mar 2019 23:01:33 -0400 +Subject: [PATCH] PlayerDeathEvent#getItemsToKeep + +Exposes a mutable array on items a player should keep on death + +Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4 + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index fd2717a00a85f91ee23a1c0f929f856972892a9b..d6cfe68be1a944ff5d5780666467f5fd8e2794e3 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -692,6 +692,46 @@ public class ServerPlayer extends Player implements ContainerListener { + }); + } + ++ // Paper start - process inventory ++ private static void processKeep(org.bukkit.event.entity.PlayerDeathEvent event, NonNullList inv) { ++ List itemsToKeep = event.getItemsToKeep(); ++ if (inv == null) { ++ // remainder of items left in toKeep - plugin added stuff on death that wasn't in the initial loot? ++ if (!itemsToKeep.isEmpty()) { ++ for (org.bukkit.inventory.ItemStack itemStack : itemsToKeep) { ++ event.getEntity().getInventory().addItem(itemStack); ++ } ++ } ++ ++ return; ++ } ++ ++ for (int i = 0; i < inv.size(); ++i) { ++ ItemStack item = inv.get(i); ++ if (EnchantmentHelper.hasVanishingCurse(item) || itemsToKeep.isEmpty() || item.isEmpty()) { ++ inv.set(i, ItemStack.NULL_ITEM); ++ continue; ++ } ++ ++ final org.bukkit.inventory.ItemStack bukkitStack = item.getBukkitStack(); ++ boolean keep = false; ++ final Iterator iterator = itemsToKeep.iterator(); ++ while (iterator.hasNext()) { ++ final org.bukkit.inventory.ItemStack itemStack = iterator.next(); ++ if (bukkitStack.equals(itemStack)) { ++ iterator.remove(); ++ keep = true; ++ break; ++ } ++ } ++ ++ if (!keep) { ++ inv.set(i, ItemStack.NULL_ITEM); ++ } ++ } ++ } ++ // Paper end ++ + @Override + public void die(DamageSource source) { + boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); +@@ -775,7 +815,12 @@ public class ServerPlayer extends Player implements ContainerListener { + this.dropExperience(); + // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. + if (!event.getKeepInventory()) { +- this.inventory.clearContent(); ++ // Paper start - replace logic ++ for (NonNullList inv : this.inventory.getComponents()) { ++ processKeep(event, inv); ++ } ++ processKeep(event, null); ++ // Paper end + } + + this.setCamera(this); // Remove spectated target diff --git a/Remapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch b/Remapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch new file mode 100644 index 0000000000..5c22ff496a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 6 Apr 2019 10:16:48 -0400 +Subject: [PATCH] Optimize Captured TileEntity Lookup + +upstream was doing a containsKey/get pattern, and always doing it at that. +that scenario is only even valid if were in the middle of a block place. + +Optimize to check if the captured list even has values in it, and also to +just do a get call since the value can never be null. + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index c8542636e89748699d608eb29569cacb6321d334..5193271bc257248e0d2bc9d9a477e999a97deada 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -968,12 +968,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return null; + } else { + // CraftBukkit start +- if (capturedTileEntities.containsKey(blockposition)) { +- return capturedTileEntities.get(blockposition); ++ BlockEntity tileentity = null; // Paper ++ if (!capturedTileEntities.isEmpty() && (tileentity = capturedTileEntities.get(blockposition)) != null) { // Paper ++ return tileentity; // Paper + } + // CraftBukkit end + +- BlockEntity tileentity = null; ++ //TileEntity tileentity = null; // Paper - move up + + if (this.updatingBlockEntities) { + tileentity = this.getPendingBlockEntityAt(blockposition); diff --git a/Remapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch b/Remapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch new file mode 100644 index 0000000000..2926bb8ee6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 1 Jan 2019 02:22:01 -0800 +Subject: [PATCH] Add Heightmap API + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 5193271bc257248e0d2bc9d9a477e999a97deada..eb88d830fb45a6b8c990e8bdc1943d80f63c8b93 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -670,8 +670,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + } + +- @Override +- public int getHeight(Heightmap.Types heightmap, int x, int z) { ++ public final int getHighestBlockY(final Heightmap.Types heightmap, final int x, final int z) { return this.getHeight(heightmap, x, z); } // Paper - OBFHELPER ++ @Override public int getHeight(Heightmap.Types heightmap, int x, int z) { // Paper - OBFHELPER + int k; + + if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 7b5abccac9793811bd56340c8f9d23806e832365..a4231e1c3d468355c0b55ac9d2c239f1b4c54594 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -325,6 +325,29 @@ public class CraftWorld implements World { + return getHighestBlockYAt(x, z, org.bukkit.HeightMap.MOTION_BLOCKING); + } + ++ // Paper start - Implement heightmap api ++ @Override ++ public int getHighestBlockYAt(final int x, final int z, final com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { ++ this.getChunkAt(x >> 4, z >> 4); // heightmap will ret 0 on unloaded areas ++ ++ switch (heightmap) { ++ case LIGHT_BLOCKING: ++ throw new UnsupportedOperationException(); // TODO ++ //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z); ++ case ANY: ++ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE, x, z); ++ case SOLID: ++ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR, x, z); ++ case SOLID_OR_LIQUID: ++ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING, x, z); ++ case SOLID_OR_LIQUID_NO_LEAVES: ++ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z); ++ default: ++ throw new UnsupportedOperationException(); ++ } ++ } ++ // Paper end ++ + @Override + public Location getSpawnLocation() { + BlockPos spawn = world.getSpawn(); diff --git a/Remapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch b/Remapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch new file mode 100644 index 0000000000..b3ee864737 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch @@ -0,0 +1,139 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 19 Apr 2019 12:41:13 -0500 +Subject: [PATCH] Mob Spawner API Enhancements + + +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 3a7aec9bd2f3fd1b4a1981fb6a8c64b69e4875f8..6ca378ec7868b855d46c749910c656f82ddb009f 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -65,6 +65,7 @@ public abstract class BaseSpawner { + this.spawnPotentials.clear(); // CraftBukkit - SPIGOT-3496, MC-92282 + } + ++ public boolean isActivated() { return isNearPlayer(); } // Paper - OBFHELPER + private boolean isNearPlayer() { + BlockPos blockposition = this.getPos(); + +@@ -221,6 +222,7 @@ public abstract class BaseSpawner { + } + } + ++ public void resetTimer() { delay(); } // Paper - OBFHELPER + private void delay() { + if (this.maxSpawnDelay <= this.minSpawnDelay) { + this.spawnDelay = this.minSpawnDelay; +@@ -238,7 +240,13 @@ public abstract class BaseSpawner { + } + + public void load(CompoundTag tag) { ++ // Paper start - use larger int if set ++ if (tag.contains("Paper.Delay")) { ++ this.spawnDelay = tag.getInt("Paper.Delay"); ++ } else { + this.spawnDelay = tag.getShort("Delay"); ++ } ++ // Paper end + this.spawnPotentials.clear(); + if (tag.contains("SpawnPotentials", 9)) { + ListTag nbttaglist = tag.getList("SpawnPotentials", 10); +@@ -253,10 +261,15 @@ public abstract class BaseSpawner { + } else if (!this.spawnPotentials.isEmpty()) { + this.setNextSpawnData((SpawnData) WeighedRandom.getRandomItem(this.getLevel().random, this.spawnPotentials)); + } +- ++ // Paper start - use ints if set ++ if (tag.contains("Paper.MinSpawnDelay", 99)) { ++ this.minSpawnDelay = tag.getInt("Paper.MinSpawnDelay"); ++ this.maxSpawnDelay = tag.getInt("Paper.MaxSpawnDelay"); ++ this.spawnCount = tag.getShort("SpawnCount"); ++ } else // Paper end + if (tag.contains("MinSpawnDelay", 99)) { +- this.minSpawnDelay = tag.getShort("MinSpawnDelay"); +- this.maxSpawnDelay = tag.getShort("MaxSpawnDelay"); ++ this.minSpawnDelay = tag.getInt("MinSpawnDelay"); ++ this.maxSpawnDelay = tag.getInt("MaxSpawnDelay"); + this.spawnCount = tag.getShort("SpawnCount"); + } + +@@ -281,9 +294,20 @@ public abstract class BaseSpawner { + if (minecraftkey == null) { + return tag; + } else { +- tag.putShort("Delay", (short) this.spawnDelay); +- tag.putShort("MinSpawnDelay", (short) this.minSpawnDelay); +- tag.putShort("MaxSpawnDelay", (short) this.maxSpawnDelay); ++ // Paper start ++ if (spawnDelay > Short.MAX_VALUE) { ++ tag.putInt("Paper.Delay", this.spawnDelay); ++ } ++ tag.putShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay)); ++ ++ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) { ++ tag.putInt("Paper.MinSpawnDelay", this.minSpawnDelay); ++ tag.putInt("Paper.MaxSpawnDelay", this.maxSpawnDelay); ++ } ++ ++ tag.putShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay)); ++ tag.putShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay)); ++ // Paper end + tag.putShort("SpawnCount", (short) this.spawnCount); + tag.putShort("MaxNearbyEntities", (short) this.maxNearbyEntities); + tag.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 daaf861041cf7c8f59c85535ecb99e402ab4f658..a5b88b545e08eaabf894305a9bee31c55c5b1b87 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java +@@ -1,12 +1,20 @@ + package org.bukkit.craftbukkit.block; + + import com.google.common.base.Preconditions; ++import net.minecraft.core.Registry; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.world.level.SpawnData; + import net.minecraft.world.level.block.entity.SpawnerBlockEntity; + import org.bukkit.Material; + import org.bukkit.block.Block; + import org.bukkit.block.CreatureSpawner; + import org.bukkit.entity.EntityType; ++// Paper start ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.inventory.ItemStack; ++// Paper end + + public class CraftCreatureSpawner extends CraftBlockEntityState implements CreatureSpawner { + +@@ -120,4 +128,30 @@ public class CraftCreatureSpawner extends CraftBlockEntityState +Date: Mon, 6 May 2019 01:29:25 -0400 +Subject: [PATCH] Per-Player View Distance API placeholders + +I hope to look at this more in-depth soon. It appears doable. +However this should not block the update. + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index 37a9e9df7f7f816c214c37e545288bf9329626ed..ec9436005a3a6fdfb4783d1092bb361224eb6414 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -625,9 +625,10 @@ public class EnderDragon extends Mob implements Enemy { + if (this.dragonDeathTime == 1 && !this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1028, this.getChunkCoordinates(), 0); +- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API + for (net.minecraft.server.level.ServerPlayer player : (List) ((ServerLevel)level).players()) { +- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch ++ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch ++ // Paper end + double deltaX = this.getX() - player.getX(); + double deltaZ = this.getZ() - player.getZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +index 3a80869dc3c16cb81ac87100f28d63eee722067f..edd231568b75330d0cffbecb03a7e9dbc55d5f94 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -46,6 +46,7 @@ import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerBossEvent; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; +@@ -255,9 +256,9 @@ public class WitherBoss extends Monster implements RangedAttackMob { + if (!this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1023, new BlockPosition(this), 0); +- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API + for (ServerPlayer player : (List)this.level.players()) { +- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch ++ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch + double deltaX = this.getX() - player.getX(); + double deltaZ = this.getZ() - player.getZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index c2c6eb54096ef85b01c0b700cbe6a8054b62729f..20de8e358789d05bb5ac15e4cdd7dda85b61b7f8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2240,6 +2240,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + super.remove(); + } + } ++ ++ @Override ++ public int getViewDistance() { ++ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO ++ } ++ ++ @Override ++ public void setViewDistance(int viewDistance) { ++ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO ++ } + // Paper end + + // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch b/Remapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch new file mode 100644 index 0000000000..5853bd79ee --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Fri, 10 May 2019 18:38:19 +0100 +Subject: [PATCH] Fix CB call to changed postToMainThread method + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index ed4129a51351aff16455960d71a0add1b8209c02..4f99c3d06e3b994708c699395adf481a6828e097 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -443,7 +443,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + this.connection.getClass(); + // CraftBukkit - Don't wait +- minecraftserver.wrapRunnable(networkmanager::handleDisconnection); ++ minecraftserver.scheduleOnMain(networkmanager::handleDisconnection); // Paper + } + + private void filterTextPacket(T text, Consumer consumer, BiFunction>> backingFilterer) { diff --git a/Remapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/Remapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch new file mode 100644 index 0000000000..262820c228 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Sat, 27 Apr 2019 20:00:43 +0100 +Subject: [PATCH] Fix sounds when item frames are modified (MC-123450) + +This also fixes the adding sound playing when the item frame direction is changed. + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java +index d6e6846a12a889222ced67937c09d184a64c60b9..429d8a50a35f07bfc16dbedf28560fa6df817644 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java +@@ -277,7 +277,7 @@ public class ItemFrame extends HangingEntity { + } + + this.getEntityData().set(ItemFrame.DATA_ITEM, itemstack); +- if (!itemstack.isEmpty() && playSound) { // CraftBukkit ++ if (!itemstack.isEmpty() && flag && playSound) { // CraftBukkit // Paper - only play sound when update flag is set + this.playSound(SoundEvents.ITEM_FRAME_ADD_ITEM, 1.0F, 1.0F); + } + diff --git a/Remapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/Remapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch new file mode 100644 index 0000000000..367d2e18c9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 13 May 2019 21:10:59 -0700 +Subject: [PATCH] Fix CraftServer#isPrimaryThread and MinecraftServer + isMainThread + +md_5 changed it so he could shut down the server asynchronously +from watchdog, although we have patches that prevent that type +of behavior for this exact reason. + +md_5 also placed code in PlayerConnectionUtils that would have +solved https://bugs.mojang.com/browse/MC-142590, making the change +to MinecraftServer#isMainThread irrelevant. +By reverting his change to MinecraftServer#isMainThread packet +handling that should have been handled synchronously will be handled +synchronously when the server gets shut down. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 35984c7e994570a909ed4ffaabe64ae941b15e71..9beda5e429b5c520a41d9c7f536dc48dbb6f6f9e 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2190,7 +2190,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Fri, 28 Sep 2018 21:49:53 -0400 +Subject: [PATCH] Fix issues with entity loss due to unloaded chunks + +Vanilla has risk of losing entities by causing them to be +removed from all chunks if they try to move into an unloaded chunk. + +This pretty much means high chance this entity will be lost in this +scenario. + +There is another case that adding an entity to the world can fail if +the chunk isn't loaded. + +Lots of the server is designed around addEntity never expecting to fail +for these reasons, nor is it really logical. + +This change ensures the chunks are always loaded when entities are +added to the world, or a valid entity moves between chunks. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index d03b4f97102dfb88927a94ee5a5d397ac493eaa1..99883c83c126405fc93becefed8a1d0727b94aa7 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -848,11 +848,18 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + int k = Mth.floor(entity.getZ() / 16.0D); + + if (!entity.inChunk || entity.xChunk != i || entity.yChunk != j || entity.zChunk != k) { ++ // Paper start - remove entity if its in a chunk more correctly. ++ LevelChunk currentChunk = entity.getCurrentChunk(); ++ if (currentChunk != null) { ++ currentChunk.removeEntity(entity); ++ } ++ // Paper end ++ + if (entity.inChunk && this.hasChunk(entity.xChunk, entity.zChunk)) { + this.getChunk(entity.xChunk, entity.zChunk).removeEntity(entity, entity.yChunk); + } + +- if (!entity.checkAndResetForcedChunkAdditionFlag() && !this.hasChunk(i, k)) { ++ if (!entity.valid && !entity.checkAndResetForcedChunkAdditionFlag() && !this.hasChunk(i, k)) { // Paper - always load chunks to register valid entities location + if (entity.inChunk) { + ServerLevel.LOGGER.warn("Entity {} left loaded chunk area", entity); + } +@@ -1067,7 +1074,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return false; + } + // CraftBukkit end +- ChunkAccess ichunkaccess = this.getChunk(Mth.floor(entity.getX() / 16.0D), Mth.floor(entity.getZ() / 16.0D), ChunkStatus.FULL, entity.forcedLoading); ++ ChunkAccess ichunkaccess = this.getChunk(Mth.floor(entity.getX() / 16.0D), Mth.floor(entity.getZ() / 16.0D), ChunkStatus.FULL, true); // Paper - always load chunks for entity adds + + if (!(ichunkaccess instanceof LevelChunk)) { + return false; diff --git a/Remapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch b/Remapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch new file mode 100644 index 0000000000..29914b85b0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch @@ -0,0 +1,249 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 21 Jul 2018 14:27:34 -0400 +Subject: [PATCH] Duplicate UUID Resolve Option + +Due to a bug in https://github.com/PaperMC/Paper/commit/2e29af3df05ec0a383f48be549d1c03200756d24 +which was added all the way back in March of 2016, it was unknown (potentially not at the time) +that an entity might actually change the seed of the random object. + +At some point, EntitySquid did start setting the seed. Due to this shared random, this caused +every entity to use a Random object with a predictable seed. + +This has caused entities to potentially generate with the same UUID.... + +Over the years, servers have had entities disappear, but no sign of trouble +because CraftBukkit removed the log lines indicating that something was wrong. + +We have fixed the root issue causing duplicate UUID's, however we now have chunk +files full of entities that have the same UUID as another entity! + +When these chunks load, the 2nd entity will not be added to the world correctly. + +If that chunk loads in a different order in the future, then it will reverse and the +missing one is now the one added to the world and not the other. This results in very +inconsistent entity behavior. + +This change allows you to recover any duplicate entity by generating a new UUID for it. +This also lets you delete them instead if you don't want to risk having new entities added to +the world that you previously did not see. + +But for those who are ok with leaving this inconsistent behavior, you may use WARN or NOTHING options. + +It is recommended you regenerate the entities, as these were legit entities, and deserve your love. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index fbf3ccfb347a5ba6e895339e9576629d940d1aa4..38d25a12c6a52d8a83214e2a0f43a218cf15ceac 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -401,4 +401,43 @@ public class PaperWorldConfig { + private void preventMovingIntoUnloadedChunks() { + preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); + } ++ ++ public enum DuplicateUUIDMode { ++ SAFE_REGEN, DELETE, NOTHING, WARN ++ } ++ public DuplicateUUIDMode duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; ++ public int duplicateUUIDDeleteRange = 32; ++ private void repairDuplicateUUID() { ++ String desiredMode = getString("duplicate-uuid-resolver", "saferegen").toLowerCase().trim(); ++ duplicateUUIDDeleteRange = getInt("duplicate-uuid-saferegen-delete-range", duplicateUUIDDeleteRange); ++ switch (desiredMode.toLowerCase()) { ++ case "regen": ++ case "regenerate": ++ case "saferegen": ++ case "saferegenerate": ++ duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; ++ log("Duplicate UUID Resolve: Regenerate New UUID if distant (Delete likely duplicates within " + duplicateUUIDDeleteRange + " blocks)"); ++ break; ++ case "remove": ++ case "delete": ++ duplicateUUIDMode = DuplicateUUIDMode.DELETE; ++ log("Duplicate UUID Resolve: Delete Entity"); ++ break; ++ case "silent": ++ case "nothing": ++ duplicateUUIDMode = DuplicateUUIDMode.NOTHING; ++ logError("Duplicate UUID Resolve: Do Nothing (no logs) - Warning, may lose indication of bad things happening"); ++ break; ++ case "log": ++ case "warn": ++ duplicateUUIDMode = DuplicateUUIDMode.WARN; ++ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); ++ break; ++ default: ++ duplicateUUIDMode = DuplicateUUIDMode.WARN; ++ logError("Warning: Invalid duplicate-uuid-resolver config " + desiredMode + " - must be one of: regen, delete, nothing, warn"); ++ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); ++ break; ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 083db6c1899b5391231b6d5d5044a334212f148c..5d87a282042d7112415b7d7175031f734219f2c9 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1,6 +1,7 @@ + package net.minecraft.server.level; + + import co.aikar.timings.Timing; // Paper ++import com.destroystokyo.paper.PaperWorldConfig; // Paper + import com.google.common.collect.ImmutableList; + import com.google.common.collect.Iterables; + import com.google.common.collect.ComparisonChain; // Paper +@@ -23,14 +24,17 @@ import it.unimi.dsi.fastutil.objects.ObjectIterator; + import java.io.File; + import java.io.IOException; + import java.io.Writer; ++import java.util.HashMap; // Paper + import java.util.Collection; + import java.util.Iterator; + import java.util.List; ++import java.util.Map; // Paper + import java.util.Objects; + import java.util.Optional; + import java.util.Queue; + import java.util.Set; + import java.util.concurrent.CancellationException; ++import java.util.UUID; // Paper + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.CompletionException; + import java.util.concurrent.Executor; +@@ -71,6 +75,7 @@ import net.minecraft.world.entity.ai.village.poi.PoiManager; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.GameRules; ++import net.minecraft.world.level.Level; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.ChunkStatus; +@@ -697,18 +702,18 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (chunk.needsDecoration) { + net.minecraft.server.dedicated.DedicatedServer server = this.level.getCraftServer().getServer(); + if (!server.areNpcsEnabled() && entity instanceof net.minecraft.world.entity.npc.Npc) { +- entity.remove(); ++ entity.removed = true; // Paper + needsRemoval = true; + } + + if (!server.isSpawningAnimals() && (entity instanceof net.minecraft.world.entity.animal.Animal || entity instanceof net.minecraft.world.entity.animal.WaterAnimal)) { +- entity.remove(); ++ entity.removed = true; // Paper + needsRemoval = true; + } + } +- +- if (!(entity instanceof net.minecraft.world.entity.player.Player) && (needsRemoval || !this.level.loadFromChunk(entity))) { +- // CraftBukkit end ++ // CraftBukkit end ++ checkDupeUUID(entity); // Paper ++ if (!(entity instanceof net.minecraft.world.entity.player.Player) && (entity.removed || !this.level.loadFromChunk(entity))) { // Paper + if (list == null) { + list = Lists.newArrayList(new Entity[]{entity}); + } else { +@@ -735,6 +740,44 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }); + } + ++ // Paper start ++ private void checkDupeUUID(Entity entity) { ++ PaperWorldConfig.DuplicateUUIDMode mode = level.paperConfig.duplicateUUIDMode; ++ if (mode != PaperWorldConfig.DuplicateUUIDMode.WARN ++ && mode != PaperWorldConfig.DuplicateUUIDMode.DELETE ++ && mode != PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN) { ++ return; ++ } ++ Entity other = level.getEntity(entity.getUUID()); ++ ++ if (mode == PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN && other != null && !other.removed ++ && Objects.equals(other.getEncodeId(), entity.getEncodeId()) ++ && entity.getBukkitEntity().getLocation().distance(other.getBukkitEntity().getLocation()) < level.paperConfig.duplicateUUIDDeleteRange ++ ) { ++ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + " because it was near the duplicate and likely an actual duplicate. See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ entity.removed = true; ++ return; ++ } ++ if (other != null && !other.removed) { ++ switch (mode) { ++ case SAFE_REGEN: { ++ entity.setUUID(UUID.randomUUID()); ++ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", regenerated UUID for " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ break; ++ } ++ case DELETE: { ++ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ entity.removed = true; ++ break; ++ } ++ default: ++ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", doing nothing to " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ break; ++ } ++ } ++ } ++ // Paper end ++ + public CompletableFuture> postProcess(ChunkHolder holder) { + ChunkPos chunkcoordintpair = holder.getPos(); + CompletableFuture, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkRangeFuture(chunkcoordintpair, 1, (i) -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 99883c83c126405fc93becefed8a1d0727b94aa7..20b74fc8e1273fcd07ea4417eaedc8bd9aba93b3 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -4,6 +4,8 @@ import com.google.common.annotations.VisibleForTesting; + import com.google.common.collect.Iterables; + import co.aikar.timings.TimingHistory; // Paper + import co.aikar.timings.Timings; // Paper ++ ++import com.destroystokyo.paper.PaperWorldConfig; // Paper + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Queues; +@@ -1102,7 +1104,22 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (entity1 == null) { + return false; + } else { ++ // Paper start ++ if (entity1.removed) { ++ onEntityRemoved(entity1); // remove the existing entity ++ return false; ++ } ++ // Paper end + ServerLevel.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityType.getKey(entity1.getType()), entity1.getId(), EntityType.getKey(entity.getType()), entity.getId()); // CraftBukkit // Paper ++ // Paper start ++ if (DEBUG_ENTITIES && entity.level.paperConfig.duplicateUUIDMode != PaperWorldConfig.DuplicateUUIDMode.NOTHING) { ++ if (entity1.addedToWorldStack != null) { ++ entity1.addedToWorldStack.printStackTrace(); ++ } ++ ++ getAddToWorldStackTrace(entity).printStackTrace(); ++ } ++ // Paper end + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 6faac8773136412ca129dfa884178f311e197f6e..af86c370c6f834514115a8e40659f5e1aaabec75 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2803,6 +2803,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + }); + } + ++ public final void setUUID(UUID uuid) { setUUID(uuid); } // Paper - OBFHELPER + public void setUUID(UUID uuid) { + this.uuid = uuid; + this.stringUUID = this.uuid.toString(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index db28bfe95c885cdefa855c7aaa3bcf92bc52df26..55872a17060a35b727a597bc414fecec3ada3515 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -541,6 +541,7 @@ public class LevelChunk implements ChunkAccess { + if (i != this.chunkPos.x || j != this.chunkPos.z) { + LevelChunk.LOGGER.warn("Wrong location! ({}, {}) should be ({}, {}), {}", i, j, this.chunkPos.x, this.chunkPos.z, entity); + entity.removed = true; ++ return; // Paper + } + + int k = Mth.floor(entity.getY() / 16.0D); diff --git a/Remapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch b/Remapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch new file mode 100644 index 0000000000..40d4c9c49d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 21 May 2019 02:34:04 +0100 +Subject: [PATCH] improve CraftWorld#isChunkLoaded + +getChunkAt will request the chunk using vanillas chunk loading system, +which while we're not going to load the chunk, does involve the server +waiting for the execution queue to get to our request; We can just query +the chunk status and get a response now, vs having to wait + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index a4231e1c3d468355c0b55ac9d2c239f1b4c54594..6e9e2149d854f26826d030ee6e655ca8fa7b5141 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -396,13 +396,13 @@ public class CraftWorld implements World { + + @Override + public boolean isChunkLoaded(int x, int z) { +- return world.getChunkSource().isChunkLoaded(x, z); ++ return world.getChunkSource().getChunkAtIfLoadedImmediately(x, z) != null; // Paper + } + + @Override + public boolean isChunkGenerated(int x, int z) { + try { +- return isChunkLoaded(x, z) || world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; ++ return world.getChunkSource().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; // Paper (TODO check if the first part can be removed) + } catch (IOException ex) { + throw new RuntimeException(ex); + } diff --git a/Remapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/Remapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch new file mode 100644 index 0000000000..ad03456870 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -0,0 +1,260 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 13 Sep 2014 23:14:43 -0400 +Subject: [PATCH] Configurable Keep Spawn Loaded range per world + +This lets you disable it for some worlds and lower it for others. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 38d25a12c6a52d8a83214e2a0f43a218cf15ceac..ffe9b1a63d78925e1d77b9e730aef42fed6d58fa 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -440,4 +440,10 @@ public class PaperWorldConfig { + break; + } + } ++ ++ public short keepLoadedRange; ++ private void keepLoadedRange() { ++ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); ++ log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 9beda5e429b5c520a41d9c7f536dc48dbb6f6f9e..0efe7024493f96bb54e7d8c1ea7b233a1b481a04 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -716,35 +716,36 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> 4).forEach(pair -> { ++ getChunkSource().getChunkAtMainThread(pair.x, pair.z); ++ }); ++ } ++ public void removeTicketsForSpawn(int radiusInBlocks, BlockPos spawn) { ++ // In order to respect vanilla behavior, which is ensuring everything but the spawn border can tick, we added tickets ++ // with level 31 for the non-border spawn chunks ++ ServerChunkCache chunkproviderserver = this.getChunkSource(); ++ int tickRadius = radiusInBlocks - 16; ++ ++ // remove ticking chunks ++ for (int x = -tickRadius; x <= tickRadius; x += 16) { ++ for (int z = -tickRadius; z <= tickRadius; z += 16) { ++ // radius of 2 will have the current chunk be level 31 ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(x, 0, z)), 2, Unit.INSTANCE); ++ } ++ } ++ ++ // remove border chunks ++ ++ // remove border along x axis (including corner chunks) ++ for (int x = -radiusInBlocks; x <= radiusInBlocks; x += 16) { ++ // top ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32 ++ // bottom ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(x, 0, -radiusInBlocks)), 1, Unit.INSTANCE); // level 32 ++ } ++ ++ // remove border along z axis (excluding corner chunks) ++ for (int z = -radiusInBlocks + 16; z < radiusInBlocks; z += 16) { ++ // right ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 ++ // left ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 ++ } ++ } ++ // Paper end ++ + public void setDefaultSpawnPos(BlockPos pos, float angle) { +- ChunkPos chunkcoordintpair = new ChunkPos(new BlockPos(this.levelData.getXSpawn(), 0, this.levelData.getZSpawn())); ++ // Paper - configurable spawn radius ++ BlockPos prevSpawn = this.getSpawn(); ++ //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); + + this.levelData.setSpawn(pos, angle); +- this.getChunkSource().removeRegionTicket(TicketType.START, chunkcoordintpair, 11, Unit.INSTANCE); +- this.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(pos), 11, Unit.INSTANCE); ++ if (this.keepSpawnInMemory) { ++ // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add ++ this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); ++ this.addTicketsForSpawn(this.paperConfig.keepLoadedRange, pos); ++ } + this.getServer().getPlayerList().broadcastAll(new ClientboundSetDefaultSpawnPositionPacket(pos, angle)); + } + +diff --git a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java +index 2860a16c80e56edb333115f6f64f65d0e56feb11..85863211a666b299cae8a3791c182ae5094b94d9 100644 +--- a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java ++++ b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java +@@ -11,4 +11,6 @@ public interface ChunkProgressListener { + void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status); + + void stop(); ++ ++ void setChunkRadius(int radius); // Paper - allow changing chunk radius + } +diff --git a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java +index 4a541f0b2582430abda6e5ff8f492e37fc903483..e810843fae13d3e83e8f509810b781859217c48b 100644 +--- a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java ++++ b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java +@@ -12,16 +12,24 @@ import org.apache.logging.log4j.Logger; + public class LoggerChunkProgressListener implements ChunkProgressListener { + + private static final Logger LOGGER = LogManager.getLogger(); +- private final int maxCount; ++ private int maxCount; // Paper - remove final + private int count; + private long startTime; + private long nextTickTime = Long.MAX_VALUE; + + public LoggerChunkProgressListener(int radius) { ++ // Paper start - Allow changing radius later for configurable spawn patch ++ this.setChunkRadius(radius); // Move to method ++ } ++ ++ @Override ++ public void setChunkRadius(int radius) { ++ // Paper - copied from above + int j = radius * 2 + 1; + + this.maxCount = j * j; + } ++ // Paper end + + @Override + public void updateSpawnPos(ChunkPos spawnPos) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 6e9e2149d854f26826d030ee6e655ca8fa7b5141..0cb0021fac211996c5bdbb2cfc8f54addc3b49f6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1954,15 +1954,21 @@ public class CraftWorld implements World { + + @Override + public void setKeepSpawnInMemory(boolean keepLoaded) { ++ // Paper start - Configurable spawn radius ++ if (keepLoaded == world.keepSpawnInMemory) { ++ // do nothing, nothing has changed ++ return; ++ } + world.keepSpawnInMemory = keepLoaded; + // Grab the worlds spawn chunk +- BlockPos chunkcoordinates = this.world.getSpawn(); ++ BlockPos prevSpawn = this.world.getSpawn(); + if (keepLoaded) { +- world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); ++ world.addTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); + } else { +- // TODO: doesn't work well if spawn changed.... +- world.getChunkSource().removeRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); ++ // TODO: doesn't work well if spawn changed.... // paper - resolved ++ world.removeTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); + } ++ // Paper end + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch b/Remapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch new file mode 100644 index 0000000000..3475c01271 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Mon, 27 May 2019 17:35:39 -0500 +Subject: [PATCH] MC-114618 - Fix EntityAreaEffectCloud from going negative + size + + +diff --git a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java +index 949553229a55f8c8b9a5c0141409d1520eff22c7..fe4312a58b0b2ffd63db14068d99c5391e0eb0a0 100644 +--- a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java ++++ b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java +@@ -194,6 +194,12 @@ public class AreaEffectCloud extends Entity { + super.tick(); + boolean flag = this.isWaiting(); + float f = this.getRadius(); ++ // Paper start - fix MC-114618 ++ if (f < 0.0F) { ++ this.remove(); ++ return; ++ } ++ // Paper end + + if (this.level.isClientSide) { + ParticleOptions particleparam = this.getParticle(); diff --git a/Remapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch b/Remapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch new file mode 100644 index 0000000000..09a7ae7ee7 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Wed, 29 May 2019 04:01:22 +0100 +Subject: [PATCH] ChunkMapDistance CME + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 0b8cbf75ff01b9825141be00d63679f7bcc58a9f..89e90806b78d94d5c1d781113da420dafa47930a 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -44,6 +44,7 @@ public class ChunkHolder { + private static final CompletableFuture> UNLOADED_LEVEL_CHUNK_FUTURE = CompletableFuture.completedFuture(ChunkHolder.UNLOADED_LEVEL_CHUNK); + private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); + private static final ChunkHolder.FullChunkStatus[] FULL_CHUNK_STATUSES = ChunkHolder.FullChunkStatus.values(); ++ boolean isUpdateQueued = false; // Paper + private final AtomicReferenceArray>> futures; + private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage + private volatile CompletableFuture> tickingChunkFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 8f993f15ae02c2e4af9cc732cd1b040cce0a67e8..71a51cc99e26579e765f88340588e23956888929 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -39,7 +39,16 @@ public abstract class DistanceManager { + private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); + private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); + private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); +- private final Set chunksToUpdateFutures = Sets.newHashSet(); ++ // Paper start use a queue, but still keep unique requirement ++ public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { ++ @Override ++ public boolean add(ChunkHolder o) { ++ if (o.isUpdateQueued) return true; ++ o.isUpdateQueued = true; ++ return super.add(o); ++ } ++ }; ++ // Paper end + private final ChunkTaskPriorityQueueSorter ticketThrottler; + private final ProcessorHandle> ticketThrottlerInput; + private final ProcessorHandle ticketThrottlerReleaser; +@@ -100,26 +109,14 @@ public abstract class DistanceManager { + ; + } + +- if (!this.chunksToUpdateFutures.isEmpty()) { +- // CraftBukkit start +- // Iterate pending chunk updates with protection against concurrent modification exceptions +- java.util.Iterator iter = this.chunksToUpdateFutures.iterator(); +- int expectedSize = this.chunksToUpdateFutures.size(); +- do { +- ChunkHolder playerchunk = iter.next(); +- iter.remove(); +- expectedSize--; +- +- playerchunk.updateFutures(chunkStorage); +- +- // Reset iterator if set was modified using add() +- if (this.chunksToUpdateFutures.size() != expectedSize) { +- expectedSize = this.chunksToUpdateFutures.size(); +- iter = this.chunksToUpdateFutures.iterator(); +- } +- } while (iter.hasNext()); +- // CraftBukkit end +- ++ // Paper start ++ if (!this.pendingChunkUpdates.isEmpty()) { ++ while(!this.pendingChunkUpdates.isEmpty()) { ++ ChunkHolder remove = this.pendingChunkUpdates.remove(); ++ remove.isUpdateQueued = false; ++ remove.updateFutures(chunkStorage); ++ } ++ // Paper end + return true; + } else { + if (!this.ticketsToRelease.isEmpty()) { +@@ -342,7 +339,7 @@ public abstract class DistanceManager { + if (k != level) { + playerchunk = DistanceManager.this.updateChunkScheduling(id, level, playerchunk, k); + if (playerchunk != null) { +- DistanceManager.this.chunksToUpdateFutures.add(playerchunk); ++ DistanceManager.this.pendingChunkUpdates.add(playerchunk); + } + + } +@@ -373,7 +370,7 @@ public abstract class DistanceManager { + ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); + + while (objectiterator.hasNext()) { +- it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); ++ Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix + byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); + long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); + diff --git a/Remapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch b/Remapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch new file mode 100644 index 0000000000..0fd2f20b1d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: simpleauthority +Date: Tue, 28 May 2019 03:48:51 -0700 +Subject: [PATCH] Implement CraftBlockSoundGroup + + +diff --git a/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9a516520d975f52169e346adc4ec6d9db843db2f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java +@@ -0,0 +1,38 @@ ++package com.destroystokyo.paper.block; ++ ++import net.minecraft.world.level.block.SoundType; ++import org.bukkit.Sound; ++import org.bukkit.craftbukkit.CraftSound; ++ ++public class CraftBlockSoundGroup implements BlockSoundGroup { ++ private final SoundType soundEffectType; ++ ++ public CraftBlockSoundGroup(SoundType soundEffectType) { ++ this.soundEffectType = soundEffectType; ++ } ++ ++ @Override ++ public Sound getBreakSound() { ++ return CraftSound.getBukkit(soundEffectType.getBreakSound()); ++ } ++ ++ @Override ++ public Sound getStepSound() { ++ return CraftSound.getBukkit(soundEffectType.getStepSound()); ++ } ++ ++ @Override ++ public Sound getPlaceSound() { ++ return CraftSound.getBukkit(soundEffectType.getPlaceSound()); ++ } ++ ++ @Override ++ public Sound getHitSound() { ++ return CraftSound.getBukkit(soundEffectType.getHitSound()); ++ } ++ ++ @Override ++ public Sound getFallSound() { ++ return CraftSound.getBukkit(soundEffectType.getFallSound()); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/level/block/SoundType.java b/src/main/java/net/minecraft/world/level/block/SoundType.java +index 1d3acbbc80a38998fb38e0ce37af52103f677721..44394adbe60b5e9c4654ee2f437d465bef5909a8 100644 +--- a/src/main/java/net/minecraft/world/level/block/SoundType.java ++++ b/src/main/java/net/minecraft/world/level/block/SoundType.java +@@ -54,10 +54,10 @@ public class SoundType { + public static final SoundType GILDED_BLACKSTONE = new SoundType(1.0F, 1.0F, SoundEvents.GILDED_BLACKSTONE_BREAK, SoundEvents.GILDED_BLACKSTONE_STEP, SoundEvents.GILDED_BLACKSTONE_PLACE, SoundEvents.GILDED_BLACKSTONE_HIT, SoundEvents.GILDED_BLACKSTONE_FALL); + public final float volume; + public final float pitch; +- public final SoundEvent breakSound; ++ public final SoundEvent breakSound; public final SoundEvent getBreakSound() { return this.breakSound; } // Paper - OBFHELPER // PAIL private -> public, rename breakSound + private final SoundEvent stepSound; + private final SoundEvent placeSound; +- public final SoundEvent hitSound; ++ public final SoundEvent hitSound; public final SoundEvent getHitSound() { return this.hitSound; } // Paper - OBFHELPER // PAIL private -> public, rename hitSound + private final SoundEvent fallSound; + + public SoundType(float volume, float pitch, SoundEvent breakSound, SoundEvent stepSound, SoundEvent placeSound, SoundEvent hitSound, SoundEvent fallSound) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index d73086970db19531db66c2e8af52da91d0b1ea28..5bff313dbbb3049105874846d995883e827fbc00 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -747,4 +747,11 @@ public class CraftBlock implements Block { + AABB aabb = shape.bounds(); + return new BoundingBox(getX() + aabb.minX, getY() + aabb.minY, getZ() + aabb.minZ, getX() + aabb.maxX, getY() + aabb.maxY, getZ() + aabb.maxZ); + } ++ ++ // Paper start ++ @Override ++ public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { ++ return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().defaultBlockState().getSoundType()); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch b/Remapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch new file mode 100644 index 0000000000..a8a34d2b86 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch @@ -0,0 +1,490 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 1 Jun 2019 13:00:55 -0700 +Subject: [PATCH] Chunk debug command + +Prints all chunk information to a text file into the debug +folder in the root server folder. The format is in JSON, and +the data format is described in MCUtil#dumpChunks(File) + +The command will output server version and all online players to the +file as well. We do not log anything but the location, world and +username of the player. + +Also logs the value of these config values (note not all are paper's): +- keep spawn loaded value +- spawn radius +- view distance + +Each chunk has the following logged: +- Coordinate +- Ticket level & its corresponding state +- Whether it is queued for unload +- Chunk status (may be unloaded) +- All tickets on the chunk + +Example log: +https://gist.githubusercontent.com/Spottedleaf/0131e7710ffd5d531e5fd246c3367380/raw/169ae1b2e240485f99bc7a6bd8e78d90e3af7397/chunks-2019-06-01_19.57.05.txt + +For references on certain keywords (ticket, status, etc), please see: + +https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528273&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528273 +https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528577&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528577 + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 8fd716bf2e1402694798b8be03fd85821153be44..53dd6c18de8e80378852bbb141016d9574d42162 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -6,13 +6,15 @@ import com.google.common.collect.ImmutableSet; + import com.google.common.collect.Iterables; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; +-import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import org.apache.commons.lang3.tuple.MutablePair; + import org.apache.commons.lang3.tuple.Pair; + import org.bukkit.Bukkit; +@@ -41,7 +43,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); + + public PaperCommand(String name) { + super(name); +@@ -69,6 +71,21 @@ public class PaperCommand extends Command { + if (args.length == 3) + return getListMatchingLast(sender, args, EntityType.getEntityNameList().stream().map(ResourceLocation::toString).sorted().toArray(String[]::new)); + break; ++ case "debug": ++ if (args.length == 2) { ++ return getListMatchingLast(sender, args, "help", "chunks"); ++ } ++ break; ++ case "chunkinfo": ++ List worldNames = new ArrayList<>(); ++ worldNames.add("*"); ++ for (org.bukkit.World world : Bukkit.getWorlds()) { ++ worldNames.add(world.getName()); ++ } ++ if (args.length == 2) { ++ return getListMatchingLast(sender, args, worldNames); ++ } ++ break; + } + return Collections.emptyList(); + } +@@ -135,6 +152,12 @@ public class PaperCommand extends Command { + case "reload": + doReload(sender); + break; ++ case "debug": ++ doDebug(sender, args); ++ break; ++ case "chunkinfo": ++ doChunkInfo(sender, args); ++ break; + case "ver": + if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) + case "version": +@@ -152,6 +175,114 @@ public class PaperCommand extends Command { + return true; + } + ++ private void doChunkInfo(CommandSender sender, String[] args) { ++ List worlds; ++ if (args.length < 2 || args[1].equals("*")) { ++ worlds = Bukkit.getWorlds(); ++ } else { ++ worlds = new ArrayList<>(args.length - 1); ++ for (int i = 1; i < args.length; ++i) { ++ org.bukkit.World world = Bukkit.getWorld(args[i]); ++ if (world == null) { ++ sender.sendMessage(ChatColor.RED + "World '" + args[i] + "' is invalid"); ++ return; ++ } ++ worlds.add(world); ++ } ++ } ++ ++ int accumulatedTotal = 0; ++ int accumulatedInactive = 0; ++ int accumulatedBorder = 0; ++ int accumulatedTicking = 0; ++ int accumulatedEntityTicking = 0; ++ ++ for (org.bukkit.World bukkitWorld : worlds) { ++ ServerLevel world = ((CraftWorld)bukkitWorld).getHandle(); ++ ++ int total = 0; ++ int inactive = 0; ++ int border = 0; ++ int ticking = 0; ++ int entityTicking = 0; ++ ++ for (ChunkHolder chunk : world.getChunkSource().chunkMap.updatingChunkMap.values()) { ++ if (chunk.getFullChunkIfCached() == null) { ++ continue; ++ } ++ ++ ++total; ++ ++ ChunkHolder.FullChunkStatus state = ChunkHolder.getFullChunkStatus(chunk.getTicketLevel()); ++ ++ switch (state) { ++ case INACCESSIBLE: ++ ++inactive; ++ continue; ++ case BORDER: ++ ++border; ++ continue; ++ case TICKING: ++ ++ticking; ++ continue; ++ case ENTITY_TICKING: ++ ++entityTicking; ++ continue; ++ } ++ } ++ ++ accumulatedTotal += total; ++ accumulatedInactive += inactive; ++ accumulatedBorder += border; ++ accumulatedTicking += ticking; ++ accumulatedEntityTicking += entityTicking; ++ ++ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + bukkitWorld.getName() + ChatColor.DARK_AQUA + ":"); ++ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + total + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA ++ + inactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + border + ChatColor.BLUE + " Ticking: " ++ + ChatColor.DARK_AQUA + ticking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + entityTicking); ++ } ++ if (worlds.size() > 1) { ++ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + "all listed worlds" + ChatColor.DARK_AQUA + ":"); ++ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + accumulatedTotal + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA ++ + accumulatedInactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + accumulatedBorder + ChatColor.BLUE + " Ticking: " ++ + ChatColor.DARK_AQUA + accumulatedTicking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + accumulatedEntityTicking); ++ } ++ } ++ ++ private void doDebug(CommandSender sender, String[] args) { ++ if (args.length < 2) { ++ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); ++ return; ++ } ++ ++ String debugType = args[1].toLowerCase(Locale.ENGLISH); ++ switch (debugType) { ++ case "chunks": ++ if (args.length >= 3 && args[2].toLowerCase(Locale.ENGLISH).equals("help")) { ++ sender.sendMessage(ChatColor.RED + "Use /paper debug chunks to dump loaded chunk information to a file"); ++ break; ++ } ++ File file = new File(new File(new File("."), "debug"), ++ "chunks-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); ++ sender.sendMessage(ChatColor.GREEN + "Writing chunk information dump to " + file.toString()); ++ try { ++ MCUtil.dumpChunks(file); ++ sender.sendMessage(ChatColor.GREEN + "Successfully written chunk information!"); ++ } catch (Throwable thr) { ++ MinecraftServer.LOGGER.warn("Failed to dump chunk information to file " + file.toString(), thr); ++ sender.sendMessage(ChatColor.RED + "Failed to dump chunk information, see console"); ++ } ++ ++ break; ++ case "help": ++ // fall through to default ++ default: ++ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); ++ return; ++ } ++ } ++ + /* + * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 + */ +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 1fecc81b25109592907623741225a6222a8c5ccc..a16551c81a444685f6337a65b6d7862b8c0dc684 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -9,13 +9,27 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; ++import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.DistanceManager; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.Ticket; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.Level; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.ChunkStatus; + import org.apache.commons.lang.exception.ExceptionUtils; ++import com.google.gson.JsonArray; ++import com.google.gson.JsonObject; ++import com.google.gson.internal.Streams; ++import com.google.gson.stream.JsonWriter; + import com.mojang.authlib.GameProfile; ++import com.mojang.datafixers.util.Either; ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; + import org.bukkit.Location; + import org.bukkit.block.BlockFace; + import org.bukkit.craftbukkit.CraftWorld; +@@ -24,8 +38,11 @@ import org.spigotmc.AsyncCatcher; + + import javax.annotation.Nonnull; + import javax.annotation.Nullable; ++import java.io.*; ++import java.util.ArrayList; + import java.util.List; + import java.util.Queue; ++import java.util.Set; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.ExecutionException; + import java.util.concurrent.LinkedBlockingQueue; +@@ -531,4 +548,170 @@ public final class MCUtil { + + return null; + } ++ ++ public static ChunkStatus getChunkStatus(ChunkHolder chunk) { ++ List statuses = ServerChunkCache.getPossibleChunkStatuses(); ++ for (int i = statuses.size() - 1; i >= 0; --i) { ++ ChunkStatus curr = statuses.get(i); ++ CompletableFuture> future = chunk.getFutureIfPresentUnchecked(curr); ++ if (future != ChunkHolder.UNLOADED_CHUNK_FUTURE) { ++ return curr; ++ } ++ } ++ return null; // unloaded ++ } ++ ++ public static void dumpChunks(File file) throws IOException { ++ file.getParentFile().mkdirs(); ++ file.createNewFile(); ++ /* ++ * Json format: ++ * ++ * Main data format: ++ * -server-version: ++ * -data-version: ++ * -worlds: ++ * -name: ++ * -view-distance: ++ * -keep-spawn-loaded: ++ * -keep-spawn-loaded-range: ++ * -visible-chunk-count: ++ * -loaded-chunk-count: ++ * -verified-fully-loaded-chunks: ++ * -players: ++ * -chunk-data: ++ * ++ * Player format: ++ * -name: ++ * -x: ++ * -y: ++ * -z: ++ * ++ * Chunk Format: ++ * -x: ++ * -z: ++ * -ticket-level: ++ * -state: ++ * -queued-for-unload: ++ * -status: ++ * -tickets: ++ * ++ * ++ * Ticket format: ++ * -ticket-type: ++ * -ticket-level: ++ * -add-tick: ++ * -object-reason: // This depends on the type of ticket. ie POST_TELEPORT -> entity id ++ */ ++ List worlds = org.bukkit.Bukkit.getWorlds(); ++ JsonObject data = new JsonObject(); ++ ++ data.addProperty("server-version", org.bukkit.Bukkit.getVersion()); ++ data.addProperty("data-version", 0); ++ ++ JsonArray worldsData = new JsonArray(); ++ ++ for (org.bukkit.World bukkitWorld : worlds) { ++ JsonObject worldData = new JsonObject(); ++ ++ ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); ++ ChunkMap chunkMap = world.getChunkSource().chunkMap; ++ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunkMap; ++ DistanceManager chunkMapDistance = chunkMap.distanceManager; ++ List allChunks = new ArrayList<>(visibleChunks.values()); ++ List players = world.players; ++ ++ int fullLoadedChunks = 0; ++ ++ for (ChunkHolder chunk : allChunks) { ++ if (chunk.getFullChunkIfCached() != null) { ++ ++fullLoadedChunks; ++ } ++ } ++ ++ // sorting by coordinate makes the log easier to read ++ allChunks.sort((ChunkHolder v1, ChunkHolder v2) -> { ++ if (v1.location.x != v2.location.x) { ++ return Integer.compare(v1.location.x, v2.location.x); ++ } ++ return Integer.compare(v1.location.z, v2.location.z); ++ }); ++ ++ worldData.addProperty("name", world.getWorld().getName()); ++ worldData.addProperty("view-distance", world.spigotConfig.viewDistance); ++ worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); ++ worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); ++ worldData.addProperty("visible-chunk-count", visibleChunks.size()); ++ worldData.addProperty("loaded-chunk-count", chunkMap.entitiesInLevel.size()); ++ worldData.addProperty("verified-fully-loaded-chunks", fullLoadedChunks); ++ ++ JsonArray playersData = new JsonArray(); ++ ++ for (ServerPlayer player : players) { ++ JsonObject playerData = new JsonObject(); ++ ++ playerData.addProperty("name", player.getScoreboardName()); ++ playerData.addProperty("x", player.getX()); ++ playerData.addProperty("y", player.getY()); ++ playerData.addProperty("z", player.getZ()); ++ ++ playersData.add(playerData); ++ ++ } ++ ++ worldData.add("players", playersData); ++ ++ JsonArray chunksData = new JsonArray(); ++ ++ for (ChunkHolder playerChunk : allChunks) { ++ JsonObject chunkData = new JsonObject(); ++ ++ Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.pair()); ++ ChunkStatus status = getChunkStatus(playerChunk); ++ ++ chunkData.addProperty("x", playerChunk.location.x); ++ chunkData.addProperty("z", playerChunk.location.z); ++ chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); ++ chunkData.addProperty("state", ChunkHolder.getFullChunkStatus(playerChunk.getTicketLevel()).toString()); ++ chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.pair())); ++ chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); ++ ++ JsonArray ticketsData = new JsonArray(); ++ ++ if (tickets != null) { ++ for (Ticket ticket : tickets) { ++ JsonObject ticketData = new JsonObject(); ++ ++ ticketData.addProperty("ticket-type", ticket.getType().toString()); ++ ticketData.addProperty("ticket-level", ticket.getTicketLevel()); ++ ticketData.addProperty("object-reason", String.valueOf(ticket.getObjectReason())); ++ ticketData.addProperty("add-tick", ticket.getCreationTick()); ++ ++ ticketsData.add(ticketData); ++ } ++ } ++ ++ chunkData.add("tickets", ticketsData); ++ chunksData.add(chunkData); ++ } ++ ++ ++ worldData.add("chunk-data", chunksData); ++ worldsData.add(worldData); ++ } ++ ++ data.add("worlds", worldsData); ++ ++ StringWriter stringWriter = new StringWriter(); ++ JsonWriter jsonWriter = new JsonWriter(stringWriter); ++ jsonWriter.setIndent(" "); ++ jsonWriter.setLenient(false); ++ Streams.write(data, jsonWriter); ++ ++ String fileData = stringWriter.toString(); ++ ++ try (PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) { ++ out.print(fileData); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 89e90806b78d94d5c1d781113da420dafa47930a..a89b9dab043ad4536014141d5a942670b4152a95 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -53,7 +53,7 @@ public class ChunkHolder { + public int oldTicketLevel; + private int ticketLevel; + private int queueLevel; +- private final ChunkPos pos; ++ final ChunkPos pos; // Paper - private -> package + private boolean hasChangedSections; + private final ShortSet[] changedBlocksPerSection; + private int blockChangedLightSectionFilter; +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 5d87a282042d7112415b7d7175031f734219f2c9..7585b6f87b72f53deccbcb8627a13503921fc682 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -104,7 +104,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); + public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; + private final Long2ObjectLinkedOpenHashMap pendingUnloads; +- private final LongSet entitiesInLevel; ++ public final LongSet entitiesInLevel; // Paper - private -> public + public final ServerLevel level; + private final ThreadedLevelLightEngine lightEngine; + private final BlockableEventLoop mainThreadExecutor; +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index a7122a0411f4a8656efd4facde3403c8093bc8a6..6d33c1ee44bc732b58d18a8f6b0fd4bbdcb2dcd6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -46,7 +46,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper + + public class ServerChunkCache extends ChunkSource { + +- private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); ++ private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); public static final List getPossibleChunkStatuses() { return ServerChunkCache.CHUNK_STATUSES; } // Paper - OBFHELPER + private final DistanceManager distanceManager; + public final ChunkGenerator generator; + private final ServerLevel level; +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index 0c118d482e304c567fe7fe778c6ff386f960bdde..c6b5f32153b63ac92df9c4b31b8de168481f79f2 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -6,8 +6,8 @@ public final class Ticket implements Comparable> { + + private final TicketType type; + private final int ticketLevel; +- public final T key; +- private long createdTick; ++ public final T key; public final T getObjectReason() { return this.key; } // Paper - OBFHELPER ++ private long createdTick; public final long getCreationTick() { return this.createdTick; } // Paper - OBFHELPER + + protected Ticket(TicketType type, int level, T argument) { + this.type = type; +@@ -51,6 +51,7 @@ public final class Ticket implements Comparable> { + return this.type; + } + ++ public final int getTicketLevel() { return this.getTicketLevel(); } // Paper - OBFHELPER + public int getTicketLevel() { + return this.ticketLevel; + } diff --git a/Remapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch b/Remapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch new file mode 100644 index 0000000000..0a15b5e432 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Mon, 10 Jun 2019 09:36:40 +0100 +Subject: [PATCH] Catch exceptions from dispenser entity spawns + + +diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +index dccf689d17bb5a77abf97779663413d01e840c23..67a894a185a3d4a53b3c7f90174b2604dff18257 100644 +--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +@@ -8,6 +8,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.BlockSource; + import net.minecraft.core.Direction; + import net.minecraft.core.Position; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; +@@ -235,7 +236,14 @@ public interface DispenseItemBehavior { + } + } + ++ try { // Paper + entitytypes.spawn(pointer.getLevel(), stack, (Player) null, pointer.getPos().relative(enumdirection), MobSpawnType.DISPENSER, enumdirection != Direction.UP, false); ++ // Paper start ++ } catch (Exception ex){ ++ MinecraftServer.LOGGER.warn("An exception occurred dispensing entity at {}[{}]", worldserver.getWorld().getName(), pointer.getPos(), ex); ++ } ++ // Paper end ++ + // itemstack.subtract(1); // Handled during event processing + // CraftBukkit end + return stack; diff --git a/Remapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch b/Remapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch new file mode 100644 index 0000000000..6f00b2b7ac --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch @@ -0,0 +1,390 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 15 Jun 2019 08:54:33 -0700 +Subject: [PATCH] Fix World#isChunkGenerated calls + +Optimize World#loadChunk() too +This patch also adds a chunk status cache on region files (note that +its only purpose is to cache the status on DISK) + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index a89b9dab043ad4536014141d5a942670b4152a95..7010e0a970462d2b2e1b5696a1a49dba9ea60935 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -141,6 +141,19 @@ public class ChunkHolder { + Either either = (Either) statusFuture.getNow(null); + return either == null ? null : (LevelChunk) either.left().orElse(null); + } ++ ++ public ChunkAccess getAvailableChunkNow() { ++ // TODO can we just getStatusFuture(EMPTY)? ++ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) { ++ CompletableFuture> future = this.getFutureIfPresentUnchecked(curr); ++ Either either = future.getNow(null); ++ if (either == null || !either.left().isPresent()) { ++ continue; ++ } ++ return either.left().get(); ++ } ++ return null; ++ } + // Paper end + + public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 7585b6f87b72f53deccbcb8627a13503921fc682..0aac29de933c84c34cb24e204e8fcc7010060d8f 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -991,12 +991,61 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + @Nullable +- private CompoundTag readChunk(ChunkPos pos) throws IOException { ++ public CompoundTag readChunk(ChunkPos pos) throws IOException { // Paper - private -> public + CompoundTag nbttagcompound = this.read(pos); ++ // Paper start - Cache chunk status on disk ++ if (nbttagcompound == null) { ++ return null; ++ } ++ ++ nbttagcompound = this.getChunkData(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, pos, level); // CraftBukkit ++ if (nbttagcompound == null) { ++ return null; ++ } ++ ++ this.updateChunkStatusOnDisk(pos, nbttagcompound); ++ ++ return nbttagcompound; ++ // Paper end ++ } ++ ++ // Paper start - chunk status cache "api" ++ public ChunkStatus getChunkStatusOnDiskIfCached(ChunkPos chunkPos) { ++ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); ++ ++ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ } ++ ++ public ChunkStatus getChunkStatusOnDisk(ChunkPos chunkPos) throws IOException { ++ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); ++ ++ if (regionFile == null || !regionFile.chunkExists(chunkPos)) { ++ return null; ++ } ++ ++ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ ++ if (status != null) { ++ return status; ++ } ++ ++ this.readChunk(chunkPos); + +- return nbttagcompound == null ? null : this.getChunkData(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, pos, level); // CraftBukkit ++ return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); + } + ++ public void updateChunkStatusOnDisk(ChunkPos chunkPos, @Nullable CompoundTag compound) throws IOException { ++ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); ++ ++ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); ++ } ++ ++ public ChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { ++ ChunkHolder chunkHolder = this.pendingUnloads.get(ChunkPos.asLong(chunkX, chunkZ)); ++ return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow(); ++ } ++ // Paper end ++ + boolean noPlayersCloseForSpawning(ChunkPos chunkcoordintpair) { + // Spigot start + return isOutsideOfRange(chunkcoordintpair, false); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 6d33c1ee44bc732b58d18a8f6b0fd4bbdcb2dcd6..1e8ac0110badbf2d1c2336168c3e11991667c782 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -52,7 +52,7 @@ public class ServerChunkCache extends ChunkSource { + private final ServerLevel level; + public final Thread mainThread; // Paper - private -> public + private final ThreadedLevelLightEngine lightEngine; +- private final ServerChunkCache.MainThreadExecutor mainThreadProcessor; ++ public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; // Paper private -> public + public final ChunkMap chunkMap; + private final DimensionDataStorage dataStorage; + private long lastInhabitedUpdate; +@@ -317,6 +317,21 @@ public class ServerChunkCache extends ChunkSource { + + return ret; + } ++ ++ @Nullable ++ public ChunkAccess getChunkAtImmediately(int x, int z) { ++ long k = ChunkPos.asLong(x, z); ++ ++ // Note: Bypass cache to make this MT-Safe ++ ++ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(k); ++ if (playerChunk == null) { ++ return null; ++ } ++ ++ return playerChunk.getAvailableChunkNow(); ++ ++ } + // Paper end + + @Nullable +@@ -771,7 +786,7 @@ public class ServerChunkCache extends ChunkSource { + return this.lastSpawnState; + } + +- final class MainThreadExecutor extends BlockableEventLoop { ++ public final class MainThreadExecutor extends BlockableEventLoop { // Paper - package -> public + + private MainThreadExecutor(Level world) { + super("Chunk source main thread executor for " + world.dimension().location()); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +index ae84dc310c076e3212d3cdbca77a1ab06a11d479..46d5a24332c1fd3c164b760ec2a2d5bf859b1ab6 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +@@ -193,6 +193,7 @@ public class ChunkStatus { + return this.name; + } + ++ public ChunkStatus getPreviousStatus() { return this.getParent(); } // Paper - OBFHELPER + public ChunkStatus getParent() { + return this.parent; + } +@@ -213,6 +214,17 @@ public class ChunkStatus { + return this.chunkType; + } + ++ // Paper start ++ public static ChunkStatus getStatus(String name) { ++ try { ++ // We need this otherwise we return EMPTY for invalid names ++ ResourceLocation key = new ResourceLocation(name); ++ return Registry.CHUNK_STATUS.getOptional(key).orElse(null); ++ } catch (Exception ex) { ++ return null; // invalid name ++ } ++ } ++ // Paper end + public static ChunkStatus byName(String id) { + return (ChunkStatus) Registry.CHUNK_STATUS.get(ResourceLocation.tryParse(id)); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 542d6f322df5f44ad9f504c8e14c88e3fa540657..969130442b529eaac6f708107ff129f89cc0af90 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -462,6 +462,17 @@ public class ChunkSerializer { + } + // Paper end + ++ // Paper start ++ public static ChunkStatus getStatus(CompoundTag compound) { ++ if (compound == null) { ++ return null; ++ } ++ ++ // Note: Copied from below ++ return ChunkStatus.getStatus(compound.getCompound("Level").getString("Status")); ++ } ++ // Paper end ++ + public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag tag) { + if (tag != null) { + ChunkStatus chunkstatus = ChunkStatus.byName(tag.getCompound("Level").getString("Status")); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +index 637274532b01bb7b4cdb7d7b1b58181b98ac7e98..9cffef2098fbfba89ddd88a45bde33c07660497a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -21,7 +21,7 @@ import net.minecraft.world.level.storage.DimensionDataStorage; + + public class ChunkStorage implements AutoCloseable { + +- private final IOWorker worker; ++ private final IOWorker worker; public IOWorker getIOWorker() { return worker; } // Paper - OBFHELPER + protected final DataFixer fixerUpper; + @Nullable + private LegacyStructureDataHandler legacyStructureHandler; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 424628c9588c02454558bc7e7c5bad3a3e75ec9f..4d96e5ed28c910387c0a4238c9036c7a12458f57 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -27,6 +27,7 @@ import net.minecraft.Util; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtIo; + import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.chunk.ChunkStatus; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +@@ -44,6 +45,30 @@ public class RegionFile implements AutoCloseable { + protected final RegionBitmap usedSectors; + public final File file; // Paper + ++ // Paper start - Cache chunk status ++ private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; ++ ++ private boolean closed; ++ ++ // invoked on write/read ++ public void setStatus(int x, int z, ChunkStatus status) { ++ if (this.closed) { ++ // We've used an invalid region file. ++ throw new IllegalStateException("RegionFile is closed"); ++ } ++ this.statuses[getChunkLocation(x, z)] = status; ++ } ++ ++ public ChunkStatus getStatusIfCached(int x, int z) { ++ if (this.closed) { ++ // We've used an invalid region file. ++ throw new IllegalStateException("RegionFile is closed"); ++ } ++ final int location = getChunkLocation(x, z); ++ return this.statuses[location]; ++ } ++ // Paper end ++ + public RegionFile(File file, File directory, boolean dsync) throws IOException { + this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); + } +@@ -380,11 +405,13 @@ public class RegionFile implements AutoCloseable { + return this.getOffset(pos) != 0; + } + ++ private static int getChunkLocation(int x, int z) { return (x & 31) + (z & 31) * 32; } // Paper - OBFHELPER - sort of, mirror of logic below + private static int getOffsetIndex(ChunkPos pos) { + return pos.getRegionLocalX() + pos.getRegionLocalZ() * 32; + } + + public void close() throws IOException { ++ this.closed = true; // Paper + try { + this.padToFullSector(); + } finally { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index 6d3e1bb20d1ab8ce5c9ea613322042d80550761a..6f1c96e4325caf6b4762700ad2286d9ea41515c9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -28,7 +28,14 @@ public final class RegionFileStorage implements AutoCloseable { + this.sync = dsync; + } + +- private RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit ++ ++ // Paper start ++ public RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { ++ return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); ++ } ++ ++ // Paper end ++ public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public + long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); + RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); + +@@ -175,6 +182,7 @@ public final class RegionFileStorage implements AutoCloseable { + + try { + NbtIo.write(tag, (DataOutput) dataoutputstream); ++ regionfile.setStatus(pos.x, pos.z, ChunkSerializer.getStatus(tag)); // Paper - cache status on disk + regionfile.setOversized(pos.x, pos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone + } catch (Throwable throwable1) { + throwable = throwable1; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 0cb0021fac211996c5bdbb2cfc8f54addc3b49f6..a0615e4ba015cca4fe074de63b87d0bff84b1a14 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -19,6 +19,7 @@ import java.util.Objects; + import java.util.Random; + import java.util.Set; + import java.util.UUID; ++import java.util.concurrent.CompletableFuture; + import java.util.function.Predicate; + import java.util.stream.Collectors; + import net.minecraft.core.BlockPos; +@@ -401,8 +402,22 @@ public class CraftWorld implements World { + + @Override + public boolean isChunkGenerated(int x, int z) { ++ // Paper start - Fix this method ++ if (!Bukkit.isPrimaryThread()) { ++ return CompletableFuture.supplyAsync(() -> { ++ return CraftWorld.this.isChunkGenerated(x, z); ++ }, world.getChunkSource().mainThreadProcessor).join(); ++ } ++ ChunkAccess chunk = world.getChunkSource().getChunkAtImmediately(x, z); ++ if (chunk == null) { ++ chunk = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); ++ } ++ if (chunk != null) { ++ return chunk instanceof ImposterProtoChunk || chunk instanceof net.minecraft.world.level.chunk.LevelChunk; ++ } + try { +- return world.getChunkSource().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; // Paper (TODO check if the first part can be removed) ++ return world.getChunkSource().chunkMap.getChunkStatusOnDisk(new ChunkPos(x, z)) == ChunkStatus.FULL; ++ // Paper end + } catch (IOException ex) { + throw new RuntimeException(ex); + } +@@ -513,20 +528,48 @@ public class CraftWorld implements World { + @Override + public boolean loadChunk(int x, int z, boolean generate) { + org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot +- ChunkAccess chunk = world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper ++ // Paper start - Optimize this method ++ ChunkPos chunkPos = new ChunkPos(x, z); + +- // If generate = false, but the chunk already exists, we will get this back. +- if (chunk instanceof ImposterProtoChunk) { +- // We then cycle through again to get the full chunk immediately, rather than after the ticket addition +- chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); +- } ++ if (!generate) { ++ ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z); ++ if (immediate == null) { ++ immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); ++ } ++ if (immediate != null) { ++ if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) { ++ return false; // not full status ++ } ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunk(x, z); // make sure we're at ticket level 32 or lower ++ return true; ++ } + +- if (chunk instanceof net.minecraft.world.level.chunk.LevelChunk) { +- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); +- return true; ++ net.minecraft.world.level.chunk.storage.RegionFile file; ++ try { ++ file = world.getChunkSource().chunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); ++ } catch (IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ ChunkStatus status = file.getStatusIfCached(x, z); ++ if (!file.hasChunk(chunkPos) || (status != null && status != ChunkStatus.FULL)) { ++ return false; ++ } ++ ++ ChunkAccess chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.EMPTY, true); ++ if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof net.minecraft.world.level.chunk.LevelChunk)) { ++ return false; ++ } ++ ++ // fall through to load ++ // we do this so we do not re-read the chunk data on disk + } + +- return false; ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); ++ return true; ++ // Paper end + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch b/Remapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch new file mode 100644 index 0000000000..873d34715d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 15 Jun 2019 10:28:25 -0700 +Subject: [PATCH] Show blockstate location if we failed to read it + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +index 730fda7f0bf02400d349959e9cc2aafaed000b21..66aee7635cd9260d97ae9dd2e9a2a0590fe3c433 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +@@ -19,6 +19,8 @@ public class CraftBlockEntityState extends CraftBlockStat + public CraftBlockEntityState(Block block, Class tileEntityClass) { + super(block); + ++ try {// Paper - show location on failure ++ + this.tileEntityClass = tileEntityClass; + + // get tile entity from block: +@@ -38,6 +40,14 @@ public class CraftBlockEntityState extends CraftBlockStat + this.load(this.snapshot); + } + // Paper end ++ // Paper start - show location on failure ++ } catch (Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ throw new RuntimeException("Failed to read BlockState at: world: " + block.getWorld().getName() + " location: (" + block.getX() + ", " + block.getY() + ", " + block.getZ() + ")", thr); ++ } ++ // Paper end + } + + public final boolean snapshotDisabled; // Paper diff --git a/Remapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch b/Remapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch new file mode 100644 index 0000000000..9769725fb1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 May 2020 20:29:02 -0400 +Subject: [PATCH] Synchronize DataPaletteBlock instead of ReentrantLock + +Mojang has flaws in their logic about chunks being concurrently +wrote to. So we constantly see crashes around multiple threads writing. + +Additionally, java has optimized synchronization so well that its +in many times faster than trying to manage read wrote locks for low +contention situations. + +And this is extremely a low contention situation. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index 6d3dcd19ce1abc9d502903b8008949b5174a13c3..917b0a64083ebbe24321089b784b91f3af4918b9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -8,7 +8,6 @@ import java.util.function.Function; + import java.util.function.Predicate; + import java.util.stream.Collectors; + import net.minecraft.CrashReport; +-import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; + import net.minecraft.core.IdMapper; + import net.minecraft.nbt.CompoundTag; +@@ -32,23 +31,23 @@ public class PalettedContainer implements PaletteResize { + private int bits; private int getBitsPerObject() { return this.bits; } // Paper - OBFHELPER + private final ReentrantLock lock = new ReentrantLock(); + +- public void acquire() { +- if (this.lock.isLocked() && !this.lock.isHeldByCurrentThread()) { ++ public void acquire() { /* // Paper start - disable this - use proper synchronization ++ if (this.j.isLocked() && !this.j.isHeldByCurrentThread()) { + String s = (String) Thread.getAllStackTraces().keySet().stream().filter(Objects::nonNull).map((thread) -> { + return thread.getName() + ": \n\tat " + (String) Arrays.stream(thread.getStackTrace()).map(Object::toString).collect(Collectors.joining("\n\tat ")); + }).collect(Collectors.joining("\n")); + CrashReport crashreport = new CrashReport("Writing into PalettedContainer from multiple threads", new IllegalStateException()); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Thread dumps"); ++ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Thread dumps"); + +- crashreportsystemdetails.setDetail("Thread dumps", (Object) s); ++ crashreportsystemdetails.a("Thread dumps", (Object) s); + throw new ReportedException(crashreport); + } else { +- this.lock.lock(); +- } ++ this.j.lock(); ++ } */ // Paper end + } + + public void release() { +- this.lock.unlock(); ++ //this.j.unlock(); // Paper - disable this + } + + public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { +@@ -84,7 +83,7 @@ public class PalettedContainer implements PaletteResize { + } + + @Override +- public int onResize(int newSize, T objectAdded) { ++ public synchronized int onResize(int newSize, T objectAdded) { // Paper - synchronize + this.acquire(); + BitStorage databits = this.storage; + Palette datapalette = this.palette; +@@ -107,18 +106,18 @@ public class PalettedContainer implements PaletteResize { + } + + public T getAndSet(int x, int y, int z, T value) { +- this.acquire(); +- T t1 = this.getAndSet(getIndex(x, y, z), value); ++ //this.a(); // Paper - remove to reduce ops - synchronize handled below ++ return this.getAndSet(getIndex(x, y, z), value); // Paper + +- this.release(); +- return t1; ++ //this.b(); // Paper ++ //return t1; // PAper + } + + public T getAndSetUnchecked(int x, int y, int z, T value) { + return this.getAndSet(getIndex(x, y, z), value); + } + +- protected T getAndSet(int index, T value) { ++ protected synchronized T getAndSet(int index, T value) { // Paper - synchronize - writes + int j = this.palette.idFor(value); + int k = this.storage.getAndSet(index, j); + T t1 = this.palette.valueFor(k); +@@ -143,7 +142,7 @@ public class PalettedContainer implements PaletteResize { + } + + public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER +- public void write(FriendlyByteBuf buf) { ++ public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize + this.acquire(); + buf.writeByte(this.bits); + this.palette.write(buf); +@@ -151,7 +150,7 @@ public class PalettedContainer implements PaletteResize { + this.release(); + } + +- public void read(ListTag paletteTag, long[] data) { ++ public synchronized void read(ListTag paletteTag, long[] data) { // Paper - synchronize + this.acquire(); + int i = Math.max(4, Mth.ceillog2(paletteTag.size())); + +@@ -184,7 +183,7 @@ public class PalettedContainer implements PaletteResize { + this.release(); + } + +- public void write(CompoundTag nbttagcompound, String s, String s1) { ++ public synchronized void write(CompoundTag nbttagcompound, String s, String s1) { // Paper - synchronize + this.acquire(); + HashMapPalette datapalettehash = new HashMapPalette<>(this.registry, this.bits, this.dummyPaletteResize, this.reader, this.writer); + T t0 = this.defaultValue; diff --git a/Remapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch b/Remapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch new file mode 100644 index 0000000000..1600ad9506 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch @@ -0,0 +1,317 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 9 Jun 2019 03:53:22 +0100 +Subject: [PATCH] incremental chunk saving + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index ffe9b1a63d78925e1d77b9e730aef42fed6d58fa..1278d09f70c1e97607ef20d87a178dc252c7f723 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -446,4 +446,19 @@ public class PaperWorldConfig { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); + log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); + } ++ ++ public int autoSavePeriod = -1; ++ private void autoSavePeriod() { ++ autoSavePeriod = getInt("auto-save-interval", -1); ++ if (autoSavePeriod > 0) { ++ log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)"); ++ } else if (autoSavePeriod < 0) { ++ autoSavePeriod = net.minecraft.server.MinecraftServer.getServer().autosavePeriod; ++ } ++ } ++ ++ public int maxAutoSaveChunksPerTick = 24; ++ private void maxAutoSaveChunksPerTick() { ++ maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0efe7024493f96bb54e7d8c1ea7b233a1b481a04..aab1a055c065d1f1a92461e4442ec2cdd8e0b347 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -261,6 +261,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; ++ public boolean serverAutoSave = false; // Paper + public Commands vanillaCommandDispatcher; + private boolean forceTicks; + // CraftBukkit end +@@ -1256,14 +1257,24 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % autosavePeriod == 0) { // CraftBukkit +- MinecraftServer.LOGGER.debug("Autosave started"); ++ //if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down ++ //MinecraftServer.LOGGER.debug("Autosave started"); // Paper ++ serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper + this.profiler.push("save"); ++ if (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0) { // Paper + this.playerList.saveAll(); +- this.saveAllChunks(true, false, false); ++ }// Paper ++ // Paper start ++ for (ServerLevel world : getAllLevels()) { ++ if (world.paperConfig.autoSavePeriod > 0) { ++ world.saveIncrementally(serverAutoSave); ++ } ++ } ++ // Paper end ++ + this.profiler.pop(); +- MinecraftServer.LOGGER.debug("Autosave finished"); +- } ++ //MinecraftServer.LOGGER.debug("Autosave finished"); // Paper ++ //} // Paper + + this.profiler.push("snooper"); + if (((DedicatedServer) this).getProperties().snooperEnabled && !this.snooper.isStarted() && this.tickCount > 100) { // Spigot +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 7010e0a970462d2b2e1b5696a1a49dba9ea60935..491a9e78fdcec8c211499e8f48cceb829f1e5c8b 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -66,6 +66,9 @@ public class ChunkHolder { + + private final ChunkMap chunkMap; // Paper + ++ long lastAutoSaveTime; // Paper - incremental autosave ++ long inactiveTimeStart; // Paper - incremental autosave ++ + public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +@@ -421,7 +424,19 @@ public class ChunkHolder { + boolean flag2 = playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER); + boolean flag3 = playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER); + ++ boolean prevHasBeenLoaded = this.wasAccessibleSinceLastSave; // Paper + this.wasAccessibleSinceLastSave |= flag3; ++ // Paper start - incremental autosave ++ if (this.wasAccessibleSinceLastSave & !prevHasBeenLoaded) { ++ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; ++ if (timeSinceAutoSave < 0) { ++ // safest bet is to assume autosave is needed here ++ timeSinceAutoSave = this.chunkMap.level.paperConfig.autoSavePeriod; ++ } ++ this.lastAutoSaveTime = this.chunkMap.level.getGameTime() - timeSinceAutoSave; ++ this.chunkMap.autoSaveQueue.add(this); ++ } ++ // Paper end + if (!flag2 && flag3) { + // Paper start - cache ticking ready status + int expectCreateCount = ++this.fullChunkCreateCount; +@@ -541,8 +556,32 @@ public class ChunkHolder { + } + + public void refreshAccessibility() { ++ boolean prev = this.wasAccessibleSinceLastSave; // Paper ++ this.wasAccessibleSinceLastSave = getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER); ++ // Paper start - incremental autosave ++ if (prev != this.wasAccessibleSinceLastSave) { ++ if (this.wasAccessibleSinceLastSave) { ++ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; ++ if (timeSinceAutoSave < 0) { ++ // safest bet is to assume autosave is needed here ++ timeSinceAutoSave = this.chunkMap.level.paperConfig.autoSavePeriod; ++ } ++ this.lastAutoSaveTime = this.chunkMap.level.getGameTime() - timeSinceAutoSave; ++ this.chunkMap.autoSaveQueue.add(this); ++ } else { ++ this.inactiveTimeStart = this.chunkMap.level.getGameTime(); ++ this.chunkMap.autoSaveQueue.remove(this); ++ } ++ } ++ // Paper end ++ } ++ ++ // Paper start - incremental autosave ++ public boolean setHasBeenLoaded() { + this.wasAccessibleSinceLastSave = getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER); ++ return this.wasAccessibleSinceLastSave; + } ++ // Paper end + + public void replaceProtoChunk(ImposterProtoChunk protochunkextension) { + for (int i = 0; i < this.futures.length(); ++i) { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0aac29de933c84c34cb24e204e8fcc7010060d8f..cfec04e12dfaeb8852dc129a6a7e68c61dac54b6 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -91,6 +91,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelStorageSource; + import net.minecraft.world.phys.Vec3; ++import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper + import org.apache.commons.lang3.mutable.MutableBoolean; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -378,6 +379,64 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + } + ++ // Paper start - incremental autosave ++ final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((playerchunk1, playerchunk2) -> { ++ int timeCompare = Long.compare(playerchunk1.lastAutoSaveTime, playerchunk2.lastAutoSaveTime); ++ if (timeCompare != 0) { ++ return timeCompare; ++ } ++ ++ return Long.compare(MCUtil.getCoordinateKey(playerchunk1.pos), MCUtil.getCoordinateKey(playerchunk2.pos)); ++ }); ++ ++ protected void saveIncrementally() { ++ int savedThisTick = 0; ++ // optimized since we search far less chunks to hit ones that need to be saved ++ List reschedule = new java.util.ArrayList<>(this.level.paperConfig.maxAutoSaveChunksPerTick); ++ long currentTick = this.level.getGameTime(); ++ long maxSaveTime = currentTick - this.level.paperConfig.autoSavePeriod; ++ ++ for (Iterator iterator = this.autoSaveQueue.iterator(); iterator.hasNext();) { ++ ChunkHolder playerchunk = iterator.next(); ++ if (playerchunk.lastAutoSaveTime > maxSaveTime) { ++ break; ++ } ++ ++ iterator.remove(); ++ ++ ChunkAccess ichunkaccess = playerchunk.getChunkToSave().getNow(null); ++ if (ichunkaccess instanceof LevelChunk) { ++ boolean shouldSave = ((LevelChunk)ichunkaccess).lastSaveTime <= maxSaveTime; ++ ++ if (shouldSave && this.save(ichunkaccess)) { ++ ++savedThisTick; ++ ++ if (!playerchunk.setHasBeenLoaded()) { ++ // do not fall through to reschedule logic ++ playerchunk.inactiveTimeStart = currentTick; ++ if (savedThisTick >= this.level.paperConfig.maxAutoSaveChunksPerTick) { ++ break; ++ } ++ continue; ++ } ++ } ++ } ++ ++ reschedule.add(playerchunk); ++ ++ if (savedThisTick >= this.level.paperConfig.maxAutoSaveChunksPerTick) { ++ break; ++ } ++ } ++ ++ for (int i = 0, len = reschedule.size(); i < len; ++i) { ++ ChunkHolder playerchunk = reschedule.get(i); ++ playerchunk.lastAutoSaveTime = this.level.getGameTime(); ++ this.autoSaveQueue.add(playerchunk); ++ } ++ } ++ // Paper end ++ + protected void saveAllChunks(boolean flush) { + if (flush) { + List list = (List) this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); +@@ -488,6 +547,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + this.level.unload(chunk); + } ++ this.autoSaveQueue.remove(playerchunk); // Paper + + this.lightEngine.updateChunkStatus(ichunkaccess.getPos()); + this.lightEngine.tryScheduleUpdate(); +@@ -680,6 +740,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + playerchunk.replaceProtoChunk(new ImposterProtoChunk(chunk)); + } + ++ chunk.setLastSaveTime(this.level.getGameTime() - 1); // Paper - avoid autosaving newly generated/loaded chunks ++ + chunk.setFullStatus(() -> { + return ChunkHolder.getFullChunkStatus(playerchunk.getTicketLevel()); + }); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 1e8ac0110badbf2d1c2336168c3e11991667c782..c1aa40c01a80a8870478193b8cd7354b0d71045c 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -558,6 +558,15 @@ public class ServerChunkCache extends ChunkSource { + } // Paper - Timings + } + ++ // Paper start - duplicate save, but call incremental ++ public void saveIncrementally() { ++ this.runDistanceManagerUpdates(); ++ try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings ++ this.chunkMap.saveIncrementally(); ++ } // Paper - Timings ++ } ++ // Paper end ++ + @Override + public void close() throws IOException { + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index b2ddf145ae9f581ec6820deb9cb6a98be87658d7..fd7ee4badb383ffb4347d62c00ea2dfa3d76fd12 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -882,6 +882,38 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos); + } + ++ // Paper start - derived from below ++ public void saveIncrementally(boolean doFull) { ++ ServerChunkCache chunkproviderserver = this.getChunkSource(); ++ ++ if (doFull) { ++ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); ++ } ++ ++ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { ++ if (doFull) { ++ this.saveData(); ++ } ++ ++ timings.worldSaveChunks.startTiming(); // Paper ++ if (!this.noSave()) chunkproviderserver.saveIncrementally(); ++ timings.worldSaveChunks.stopTiming(); // Paper ++ ++ ++ // Copied from save() ++ // CraftBukkit start - moved from MinecraftServer.saveChunks ++ if (doFull) { // Paper ++ ServerLevel worldserver1 = this; ++ ++ worldDataServer.setWorldBorder(worldserver1.getWorldBorder().createSettings()); ++ worldDataServer.setCustomBossEvents(this.server.getCustomBossEvents().save()); ++ convertable.saveDataTag(this.server.registryHolder, this.worldDataServer, this.server.getPlayerList().getSingleplayerData()); ++ } ++ // CraftBukkit end ++ } ++ } ++ // Paper end ++ + public void save(@Nullable ProgressListener progressListener, boolean flush, boolean flag1) { + ServerChunkCache chunkproviderserver = this.getChunkSource(); + +@@ -912,6 +944,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // CraftBukkit end + } + ++ private void saveData() { this.saveLevelData(); } // Paper - OBFHELPER + private void saveLevelData() { + if (this.dragonFight != null) { + this.worldDataServer.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 55872a17060a35b727a597bc414fecec3ada3515..419b4bf0549d798d52d73fbbd9de59313fc05eb1 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -80,7 +80,7 @@ public class LevelChunk implements ChunkAccess { + private TickList blockTicks; + private TickList liquidTicks; + private boolean lastSaveHadEntities; +- private long lastSaveTime; ++ public long lastSaveTime; // Paper + private volatile boolean unsaved; + private long inhabitedTime; + @Nullable diff --git a/Remapped-Spigot-Server-Patches/0362-Anti-Xray.patch b/Remapped-Spigot-Server-Patches/0362-Anti-Xray.patch new file mode 100644 index 0000000000..95ed9fdc2a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0362-Anti-Xray.patch @@ -0,0 +1,1624 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: stonar96 +Date: Mon, 20 Aug 2018 03:03:58 +0200 +Subject: [PATCH] Anti-Xray + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1278d09f70c1e97607ef20d87a178dc252c7f723..c45493e88bf7e8811be2759ff9ac19e3fe9d938a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -1,7 +1,9 @@ + package com.destroystokyo.paper; + ++import java.util.Arrays; + import java.util.List; + ++import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; + import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; +@@ -461,4 +463,38 @@ public class PaperWorldConfig { + private void maxAutoSaveChunksPerTick() { + maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); + } ++ ++ public boolean antiXray; ++ public EngineMode engineMode; ++ public int maxChunkSectionIndex; ++ public int updateRadius; ++ public boolean lavaObscures; ++ public boolean usePermission; ++ public List hiddenBlocks; ++ public List replacementBlocks; ++ private void antiXray() { ++ antiXray = getBoolean("anti-xray.enabled", false); ++ engineMode = EngineMode.getById(getInt("anti-xray.engine-mode", EngineMode.HIDE.getId())); ++ engineMode = engineMode == null ? EngineMode.HIDE : engineMode; ++ maxChunkSectionIndex = getInt("anti-xray.max-chunk-section-index", 3); ++ maxChunkSectionIndex = maxChunkSectionIndex > 15 ? 15 : maxChunkSectionIndex; ++ updateRadius = getInt("anti-xray.update-radius", 2); ++ lavaObscures = getBoolean("anti-xray.lava-obscures", false); ++ usePermission = getBoolean("anti-xray.use-permission", false); ++ hiddenBlocks = getList("anti-xray.hidden-blocks", Arrays.asList("gold_ore", "iron_ore", "coal_ore", "lapis_ore", "mossy_cobblestone", "obsidian", "chest", "diamond_ore", "redstone_ore", "clay", "emerald_ore", "ender_chest")); ++ replacementBlocks = getList("anti-xray.replacement-blocks", Arrays.asList("stone", "oak_planks")); ++ if (PaperConfig.version < 19) { ++ hiddenBlocks.remove("lit_redstone_ore"); ++ int index = replacementBlocks.indexOf("planks"); ++ if (index != -1) { ++ replacementBlocks.set(index, "oak_planks"); ++ } ++ set("anti-xray.hidden-blocks", hiddenBlocks); ++ set("anti-xray.replacement-blocks", replacementBlocks); ++ } ++ log("Anti-Xray: " + (antiXray ? "enabled" : "disabled") + " / Engine Mode: " + engineMode.getDescription() + " / Up to " + ((maxChunkSectionIndex + 1) * 16) + " blocks / Update Radius: " + updateRadius); ++ if (antiXray && usePermission) { ++ Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8fb63441fbf9afb6f11e1185a9f29528e1950546 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java +@@ -0,0 +1,45 @@ ++package com.destroystokyo.paper.antixray; ++ ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.ServerPlayerGameMode; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.LevelChunkSection; ++ ++public class ChunkPacketBlockController { ++ ++ public static final ChunkPacketBlockController NO_OPERATION_INSTANCE = new ChunkPacketBlockController(); ++ ++ protected ChunkPacketBlockController() { ++ ++ } ++ ++ public BlockState[] getPredefinedBlockData(Level world, ChunkAccess chunk, LevelChunkSection chunkSection, boolean initializeBlocks) { ++ return null; ++ } ++ ++ public boolean shouldModify(ServerPlayer entityPlayer, LevelChunk chunk, int chunkSectionSelector) { ++ return false; ++ } ++ ++ public ChunkPacketInfo getChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector) { ++ return null; ++ } ++ ++ public void modifyBlocks(ClientboundLevelChunkPacket packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { ++ packetPlayOutMapChunk.setReady(true); ++ } ++ ++ public void onBlockChange(Level world, BlockPos blockPosition, BlockState newBlockData, BlockState oldBlockData, int flag) { ++ ++ } ++ ++ public void onPlayerLeftClickBlock(ServerPlayerGameMode playerInteractManager, BlockPos blockPosition, Direction enumDirection) { ++ ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6d41628444e880dea5c96ad5caf557f4c56dea46 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java +@@ -0,0 +1,649 @@ ++package com.destroystokyo.paper.antixray; ++ ++import java.util.ArrayList; ++import java.util.LinkedHashSet; ++import java.util.LinkedList; ++import java.util.List; ++import java.util.Set; ++import java.util.concurrent.Executor; ++import java.util.concurrent.ThreadLocalRandom; ++import java.util.function.IntSupplier; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.core.Registry; ++import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.ServerPlayerGameMode; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.EmptyLevelChunk; ++import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.LevelChunkSection; ++import net.minecraft.world.level.chunk.Palette; ++import org.bukkit.Bukkit; ++import org.bukkit.World.Environment; ++ ++import com.destroystokyo.paper.PaperWorldConfig; ++ ++public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockController { ++ ++ private final Executor executor; ++ private final EngineMode engineMode; ++ private final int maxChunkSectionIndex; ++ private final int updateRadius; ++ private final boolean usePermission; ++ private final BlockState[] predefinedBlockData; ++ private final BlockState[] predefinedBlockDataFull; ++ private final BlockState[] predefinedBlockDataStone; ++ private final BlockState[] predefinedBlockDataNetherrack; ++ private final BlockState[] predefinedBlockDataEndStone; ++ private final int[] predefinedBlockDataBitsGlobal; ++ private final int[] predefinedBlockDataBitsStoneGlobal; ++ private final int[] predefinedBlockDataBitsNetherrackGlobal; ++ private final int[] predefinedBlockDataBitsEndStoneGlobal; ++ private final boolean[] solidGlobal = new boolean[Block.BLOCK_STATE_REGISTRY.size()]; ++ private final boolean[] obfuscateGlobal = new boolean[Block.BLOCK_STATE_REGISTRY.size()]; ++ private final LevelChunkSection[] emptyNearbyChunkSections = {LevelChunk.EMPTY_CHUNK_SECTION, LevelChunk.EMPTY_CHUNK_SECTION, LevelChunk.EMPTY_CHUNK_SECTION, LevelChunk.EMPTY_CHUNK_SECTION}; ++ private final int maxBlockYUpdatePosition; ++ ++ public ChunkPacketBlockControllerAntiXray(Level world, Executor executor) { ++ PaperWorldConfig paperWorldConfig = world.paperConfig; ++ engineMode = paperWorldConfig.engineMode; ++ maxChunkSectionIndex = paperWorldConfig.maxChunkSectionIndex; ++ updateRadius = paperWorldConfig.updateRadius; ++ usePermission = paperWorldConfig.usePermission; ++ ++ this.executor = executor; ++ ++ List toObfuscate; ++ ++ if (engineMode == EngineMode.HIDE) { ++ toObfuscate = paperWorldConfig.hiddenBlocks; ++ predefinedBlockData = null; ++ predefinedBlockDataFull = null; ++ predefinedBlockDataStone = new BlockState[] {Blocks.STONE.defaultBlockState()}; ++ predefinedBlockDataNetherrack = new BlockState[] {Blocks.NETHERRACK.defaultBlockState()}; ++ predefinedBlockDataEndStone = new BlockState[] {Blocks.END_STONE.defaultBlockState()}; ++ predefinedBlockDataBitsGlobal = null; ++ predefinedBlockDataBitsStoneGlobal = new int[] {LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(Blocks.STONE.defaultBlockState())}; ++ predefinedBlockDataBitsNetherrackGlobal = new int[] {LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(Blocks.NETHERRACK.defaultBlockState())}; ++ predefinedBlockDataBitsEndStoneGlobal = new int[] {LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(Blocks.END_STONE.defaultBlockState())}; ++ } else { ++ toObfuscate = new ArrayList<>(paperWorldConfig.replacementBlocks); ++ List predefinedBlockDataList = new LinkedList(); ++ ++ for (String id : paperWorldConfig.hiddenBlocks) { ++ Block block = Registry.BLOCK.getOptional(new ResourceLocation(id)).orElse(null); ++ ++ if (block != null && !block.isEntityBlock()) { ++ toObfuscate.add(id); ++ predefinedBlockDataList.add(block.defaultBlockState()); ++ } ++ } ++ ++ // The doc of the LinkedHashSet(Collection c) constructor doesn't specify that the insertion order is the predictable iteration order of the specified Collection, although it is in the implementation ++ Set predefinedBlockDataSet = new LinkedHashSet(); ++ // Therefore addAll(Collection c) is used, which guarantees this order in the doc ++ predefinedBlockDataSet.addAll(predefinedBlockDataList); ++ predefinedBlockData = predefinedBlockDataSet.size() == 0 ? new BlockState[] {Blocks.DIAMOND_ORE.defaultBlockState()} : predefinedBlockDataSet.toArray(new BlockState[0]); ++ predefinedBlockDataFull = predefinedBlockDataSet.size() == 0 ? new BlockState[] {Blocks.DIAMOND_ORE.defaultBlockState()} : predefinedBlockDataList.toArray(new BlockState[0]); ++ predefinedBlockDataStone = null; ++ predefinedBlockDataNetherrack = null; ++ predefinedBlockDataEndStone = null; ++ predefinedBlockDataBitsGlobal = new int[predefinedBlockDataFull.length]; ++ ++ for (int i = 0; i < predefinedBlockDataFull.length; i++) { ++ predefinedBlockDataBitsGlobal[i] = LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(predefinedBlockDataFull[i]); ++ } ++ ++ predefinedBlockDataBitsStoneGlobal = null; ++ predefinedBlockDataBitsNetherrackGlobal = null; ++ predefinedBlockDataBitsEndStoneGlobal = null; ++ } ++ ++ for (String id : toObfuscate) { ++ Block block = Registry.BLOCK.getOptional(new ResourceLocation(id)).orElse(null); ++ ++ // Don't obfuscate air because air causes unnecessary block updates and causes block updates to fail in the void ++ if (block != null && !block.defaultBlockState().isAir()) { ++ // Replace all block states of a specified block ++ // No OBFHELPER for nms.BlockStateList#a() due to too many decompile errors ++ // The OBFHELPER should be getBlockDataList() ++ for (BlockState blockData : block.getStateDefinition().getPossibleStates()) { ++ obfuscateGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(blockData)] = true; ++ } ++ } ++ } ++ ++ EmptyLevelChunk emptyChunk = new EmptyLevelChunk(world, new ChunkPos(0, 0)); ++ BlockPos zeroPos = new BlockPos(0, 0, 0); ++ ++ for (int i = 0; i < solidGlobal.length; i++) { ++ BlockState blockData = LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getObject(i); ++ ++ if (blockData != null) { ++ solidGlobal[i] = blockData.isRedstoneConductor(emptyChunk, zeroPos) ++ && blockData.getBlock() != Blocks.SPAWNER && blockData.getBlock() != Blocks.BARRIER && blockData.getBlock() != Blocks.SHULKER_BOX && blockData.getBlock() != Blocks.SLIME_BLOCK || paperWorldConfig.lavaObscures && blockData == Blocks.LAVA.defaultBlockState(); ++ // Comparing blockData == Blocks.LAVA.getBlockData() instead of blockData.getBlock() == Blocks.LAVA ensures that only "stationary lava" is used ++ // shulker box checks TE. ++ } ++ } ++ ++ this.maxBlockYUpdatePosition = (maxChunkSectionIndex + 1) * 16 + updateRadius - 1; ++ } ++ ++ private int getPredefinedBlockDataFullLength() { ++ return engineMode == EngineMode.HIDE ? 1 : predefinedBlockDataFull.length; ++ } ++ ++ @Override ++ public BlockState[] getPredefinedBlockData(Level world, ChunkAccess chunk, LevelChunkSection chunkSection, boolean initializeBlocks) { ++ // Return the block data which should be added to the data palettes so that they can be used for the obfuscation ++ if (chunkSection.bottomBlockY() >> 4 <= maxChunkSectionIndex) { ++ switch (engineMode) { ++ case HIDE: ++ switch (world.getWorld().getEnvironment()) { ++ case NETHER: ++ return predefinedBlockDataNetherrack; ++ case THE_END: ++ return predefinedBlockDataEndStone; ++ default: ++ return predefinedBlockDataStone; ++ } ++ default: ++ return predefinedBlockData; ++ } ++ } ++ ++ return null; ++ } ++ ++ @Override ++ public boolean shouldModify(ServerPlayer entityPlayer, LevelChunk chunk, int chunkSectionSelector) { ++ return !usePermission || !entityPlayer.getBukkitEntity().hasPermission("paper.antixray.bypass"); ++ } ++ ++ @Override ++ public ChunkPacketInfoAntiXray getChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector) { ++ // Return a new instance to collect data and objects in the right state while creating the chunk packet for thread safe access later ++ // Note: As of 1.14 this has to be moved later due to the chunk system. ++ ChunkPacketInfoAntiXray chunkPacketInfoAntiXray = new ChunkPacketInfoAntiXray(packetPlayOutMapChunk, chunk, chunkSectionSelector, this); ++ return chunkPacketInfoAntiXray; ++ } ++ ++ @Override ++ public void modifyBlocks(ClientboundLevelChunkPacket packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { ++ if (chunkPacketInfo == null) { ++ packetPlayOutMapChunk.setReady(true); ++ return; ++ } ++ ++ if (!Bukkit.isPrimaryThread()) { ++ // plugins? ++ MinecraftServer.getServer().scheduleOnMain(() -> { ++ this.modifyBlocks(packetPlayOutMapChunk, chunkPacketInfo); ++ }); ++ return; ++ } ++ ++ LevelChunk chunk = chunkPacketInfo.getChunk(); ++ int x = chunk.getPos().x; ++ int z = chunk.getPos().z; ++ ServerLevel world = (ServerLevel)chunk.world; ++ ((ChunkPacketInfoAntiXray) chunkPacketInfo).setNearbyChunks( ++ (LevelChunk) world.getChunkIfLoadedImmediately(x - 1, z), ++ (LevelChunk) world.getChunkIfLoadedImmediately(x + 1, z), ++ (LevelChunk) world.getChunkIfLoadedImmediately(x, z - 1), ++ (LevelChunk) world.getChunkIfLoadedImmediately(x, z + 1)); ++ ++ executor.execute((ChunkPacketInfoAntiXray) chunkPacketInfo); ++ } ++ ++ // Actually these fields should be variables inside the obfuscate method but in sync mode or with SingleThreadExecutor in async mode it's okay (even without ThreadLocal) ++ // If an ExecutorService with multiple threads is used, ThreadLocal must be used here ++ private final ThreadLocal predefinedBlockDataBits = ThreadLocal.withInitial(() -> new int[getPredefinedBlockDataFullLength()]); ++ private static final ThreadLocal solid = ThreadLocal.withInitial(() -> new boolean[Block.BLOCK_STATE_REGISTRY.size()]); ++ private static final ThreadLocal obfuscate = ThreadLocal.withInitial(() -> new boolean[Block.BLOCK_STATE_REGISTRY.size()]); ++ // These boolean arrays represent chunk layers, true means don't obfuscate, false means obfuscate ++ private static final ThreadLocal current = ThreadLocal.withInitial(() -> new boolean[16][16]); ++ private static final ThreadLocal next = ThreadLocal.withInitial(() -> new boolean[16][16]); ++ private static final ThreadLocal nextNext = ThreadLocal.withInitial(() -> new boolean[16][16]); ++ ++ public void obfuscate(ChunkPacketInfoAntiXray chunkPacketInfoAntiXray) { ++ int[] predefinedBlockDataBits = this.predefinedBlockDataBits.get(); ++ boolean[] solid = this.solid.get(); ++ boolean[] obfuscate = this.obfuscate.get(); ++ boolean[][] current = this.current.get(); ++ boolean[][] next = this.next.get(); ++ boolean[][] nextNext = this.nextNext.get(); ++ // dataBitsReader, dataBitsWriter and nearbyChunkSections could also be reused (with ThreadLocal if necessary) but it's not worth it ++ DataBitsReader dataBitsReader = new DataBitsReader(); ++ DataBitsWriter dataBitsWriter = new DataBitsWriter(); ++ LevelChunkSection[] nearbyChunkSections = new LevelChunkSection[4]; ++ boolean[] solidTemp = null; ++ boolean[] obfuscateTemp = null; ++ dataBitsReader.setDataBits(chunkPacketInfoAntiXray.getData()); ++ dataBitsWriter.setDataBits(chunkPacketInfoAntiXray.getData()); ++ int numberOfBlocks = predefinedBlockDataBits.length; ++ // Keep the lambda expressions as simple as possible. They are used very frequently. ++ IntSupplier random = numberOfBlocks == 1 ? (() -> 0) : new IntSupplier() { ++ private int state; ++ ++ { ++ while ((state = ThreadLocalRandom.current().nextInt()) == 0); ++ } ++ ++ @Override ++ public int getAsInt() { ++ // https://en.wikipedia.org/wiki/Xorshift ++ state ^= state << 13; ++ state ^= state >>> 17; ++ state ^= state << 5; ++ // https://www.pcg-random.org/posts/bounded-rands.html ++ return (int) ((Integer.toUnsignedLong(state) * numberOfBlocks) >>> 32); ++ } ++ }; ++ ++ for (int chunkSectionIndex = 0; chunkSectionIndex <= maxChunkSectionIndex; chunkSectionIndex++) { ++ if (chunkPacketInfoAntiXray.isWritten(chunkSectionIndex) && chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) != null) { ++ int[] predefinedBlockDataBitsTemp; ++ ++ if (chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex) == LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE) { ++ predefinedBlockDataBitsTemp = engineMode == EngineMode.HIDE ? chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.NETHER ? predefinedBlockDataBitsNetherrackGlobal : chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.THE_END ? predefinedBlockDataBitsEndStoneGlobal : predefinedBlockDataBitsStoneGlobal : predefinedBlockDataBitsGlobal; ++ } else { ++ // If it's this.predefinedBlockData, use this.predefinedBlockDataFull instead ++ BlockState[] predefinedBlockDataFull = chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) == predefinedBlockData ? this.predefinedBlockDataFull : chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex); ++ predefinedBlockDataBitsTemp = predefinedBlockDataBits; ++ ++ for (int i = 0; i < predefinedBlockDataBitsTemp.length; i++) { ++ predefinedBlockDataBitsTemp[i] = chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex).getOrCreateIdFor(predefinedBlockDataFull[i]); ++ } ++ } ++ ++ dataBitsWriter.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); ++ ++ // Check if the chunk section below was not obfuscated ++ if (chunkSectionIndex == 0 || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex - 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex - 1) == null) { ++ // If so, initialize some stuff ++ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); ++ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); ++ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), solid, solidGlobal); ++ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), obfuscate, obfuscateGlobal); ++ // Read the blocks of the upper layer of the chunk section below if it exists ++ LevelChunkSection belowChunkSection = null; ++ boolean skipFirstLayer = chunkSectionIndex == 0 || (belowChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex - 1]) == LevelChunk.EMPTY_CHUNK_SECTION; ++ ++ for (int z = 0; z < 16; z++) { ++ for (int x = 0; x < 16; x++) { ++ current[z][x] = true; ++ next[z][x] = skipFirstLayer || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(belowChunkSection.getBlockState(x, 15, z))]; ++ } ++ } ++ ++ // Abuse the obfuscateLayer method to read the blocks of the first layer of the current chunk section ++ dataBitsWriter.setBitsPerObject(0); ++ obfuscateLayer(-1, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, emptyNearbyChunkSections, random); ++ } ++ ++ dataBitsWriter.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); ++ nearbyChunkSections[0] = chunkPacketInfoAntiXray.getNearbyChunks()[0] == null ? LevelChunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[0].getSections()[chunkSectionIndex]; ++ nearbyChunkSections[1] = chunkPacketInfoAntiXray.getNearbyChunks()[1] == null ? LevelChunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[1].getSections()[chunkSectionIndex]; ++ nearbyChunkSections[2] = chunkPacketInfoAntiXray.getNearbyChunks()[2] == null ? LevelChunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[2].getSections()[chunkSectionIndex]; ++ nearbyChunkSections[3] = chunkPacketInfoAntiXray.getNearbyChunks()[3] == null ? LevelChunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[3].getSections()[chunkSectionIndex]; ++ ++ // Obfuscate all layers of the current chunk section except the upper one ++ for (int y = 0; y < 15; y++) { ++ boolean[][] temp = current; ++ current = next; ++ next = nextNext; ++ nextNext = temp; ++ obfuscateLayer(y, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); ++ } ++ ++ // Check if the chunk section above doesn't need obfuscation ++ if (chunkSectionIndex == maxChunkSectionIndex || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex + 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex + 1) == null) { ++ // If so, obfuscate the upper layer of the current chunk section by reading blocks of the first layer from the chunk section above if it exists ++ LevelChunkSection aboveChunkSection; ++ ++ if (chunkSectionIndex != 15 && (aboveChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex + 1]) != LevelChunk.EMPTY_CHUNK_SECTION) { ++ boolean[][] temp = current; ++ current = next; ++ next = nextNext; ++ nextNext = temp; ++ ++ for (int z = 0; z < 16; z++) { ++ for (int x = 0; x < 16; x++) { ++ if (!solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(aboveChunkSection.getBlockState(x, 0, z))]) { ++ current[z][x] = true; ++ } ++ } ++ } ++ ++ // There is nothing to read anymore ++ dataBitsReader.setBitsPerObject(0); ++ solid[0] = true; ++ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solid, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); ++ } ++ } else { ++ // If not, initialize the reader and other stuff for the chunk section above to obfuscate the upper layer of the current chunk section ++ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex + 1)); ++ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex + 1)); ++ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), solid, solidGlobal); ++ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), obfuscate, obfuscateGlobal); ++ boolean[][] temp = current; ++ current = next; ++ next = nextNext; ++ nextNext = temp; ++ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); ++ } ++ ++ dataBitsWriter.finish(); ++ } ++ } ++ ++ chunkPacketInfoAntiXray.getPacketPlayOutMapChunk().setReady(true); ++ } ++ ++ private void obfuscateLayer(int y, DataBitsReader dataBitsReader, DataBitsWriter dataBitsWriter, boolean[] solid, boolean[] obfuscate, int[] predefinedBlockDataBits, boolean[][] current, boolean[][] next, boolean[][] nextNext, LevelChunkSection[] nearbyChunkSections, IntSupplier random) { ++ // First block of first line ++ int dataBits = dataBitsReader.read(); ++ ++ if (nextNext[0][0] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[0][1] = true; ++ next[1][0] = true; ++ } else { ++ if (nearbyChunkSections[2] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getBlockState(0, y, 15))] || nearbyChunkSections[0] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getBlockState(15, y, 0))] || current[0][0]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[0][0] = true; ++ } ++ ++ // First line ++ for (int x = 1; x < 15; x++) { ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[0][x] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[0][x - 1] = true; ++ next[0][x + 1] = true; ++ next[1][x] = true; ++ } else { ++ if (nearbyChunkSections[2] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getBlockState(x, y, 15))] || current[0][x]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[0][x] = true; ++ } ++ } ++ ++ // Last block of first line ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[0][15] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[0][14] = true; ++ next[1][15] = true; ++ } else { ++ if (nearbyChunkSections[2] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getBlockState(15, y, 15))] || nearbyChunkSections[1] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getBlockState(0, y, 0))] || current[0][15]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[0][15] = true; ++ } ++ ++ // All inner lines ++ for (int z = 1; z < 15; z++) { ++ // First block ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[z][0] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[z][1] = true; ++ next[z - 1][0] = true; ++ next[z + 1][0] = true; ++ } else { ++ if (nearbyChunkSections[0] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getBlockState(15, y, z))] || current[z][0]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[z][0] = true; ++ } ++ ++ // All inner blocks ++ for (int x = 1; x < 15; x++) { ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[z][x] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[z][x - 1] = true; ++ next[z][x + 1] = true; ++ next[z - 1][x] = true; ++ next[z + 1][x] = true; ++ } else { ++ if (current[z][x]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[z][x] = true; ++ } ++ } ++ ++ // Last block ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[z][15] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[z][14] = true; ++ next[z - 1][15] = true; ++ next[z + 1][15] = true; ++ } else { ++ if (nearbyChunkSections[1] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getBlockState(0, y, z))] || current[z][15]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[z][15] = true; ++ } ++ } ++ ++ // First block of last line ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[15][0] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[15][1] = true; ++ next[14][0] = true; ++ } else { ++ if (nearbyChunkSections[3] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getBlockState(0, y, 0))] || nearbyChunkSections[0] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getBlockState(15, y, 15))] || current[15][0]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[15][0] = true; ++ } ++ ++ // Last line ++ for (int x = 1; x < 15; x++) { ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[15][x] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[15][x - 1] = true; ++ next[15][x + 1] = true; ++ next[14][x] = true; ++ } else { ++ if (nearbyChunkSections[3] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getBlockState(x, y, 0))] || current[15][x]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[15][x] = true; ++ } ++ } ++ ++ // Last block of last line ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[15][15] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[15][14] = true; ++ next[14][15] = true; ++ } else { ++ if (nearbyChunkSections[3] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getBlockState(15, y, 0))] || nearbyChunkSections[1] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getBlockState(0, y, 15))] || current[15][15]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[15][15] = true; ++ } ++ } ++ ++ private boolean[] readDataPalette(Palette dataPalette, boolean[] temp, boolean[] global) { ++ if (dataPalette == LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE) { ++ return global; ++ } ++ ++ BlockState blockData; ++ ++ for (int i = 0; (blockData = dataPalette.getObject(i)) != null; i++) { ++ temp[i] = global[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(blockData)]; ++ } ++ ++ return temp; ++ } ++ ++ @Override ++ public void onBlockChange(Level world, BlockPos blockPosition, BlockState newBlockData, BlockState oldBlockData, int flag) { ++ if (oldBlockData != null && solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(oldBlockData)] && !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(newBlockData)] && blockPosition.getY() <= maxBlockYUpdatePosition) { ++ updateNearbyBlocks(world, blockPosition); ++ } ++ } ++ ++ @Override ++ public void onPlayerLeftClickBlock(ServerPlayerGameMode playerInteractManager, BlockPos blockPosition, Direction enumDirection) { ++ if (blockPosition.getY() <= maxBlockYUpdatePosition) { ++ updateNearbyBlocks(playerInteractManager.level, blockPosition); ++ } ++ } ++ ++ private void updateNearbyBlocks(Level world, BlockPos blockPosition) { ++ if (updateRadius >= 2) { ++ BlockPos temp = blockPosition.west(); ++ updateBlock(world, temp); ++ updateBlock(world, temp.west()); ++ updateBlock(world, temp.below()); ++ updateBlock(world, temp.above()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.east()); ++ updateBlock(world, temp.east()); ++ updateBlock(world, temp.below()); ++ updateBlock(world, temp.above()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.below()); ++ updateBlock(world, temp.below()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.above()); ++ updateBlock(world, temp.above()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.north()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp = blockPosition.south()); ++ updateBlock(world, temp.south()); ++ } else if (updateRadius == 1) { ++ updateBlock(world, blockPosition.west()); ++ updateBlock(world, blockPosition.east()); ++ updateBlock(world, blockPosition.below()); ++ updateBlock(world, blockPosition.above()); ++ updateBlock(world, blockPosition.north()); ++ updateBlock(world, blockPosition.south()); ++ } else { ++ // Do nothing if updateRadius <= 0 (test mode) ++ } ++ } ++ ++ private void updateBlock(Level world, BlockPos blockPosition) { ++ BlockState blockData = world.getTypeIfLoaded(blockPosition); ++ ++ if (blockData != null && obfuscateGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(blockData)]) { ++ // world.notify(blockPosition, blockData, blockData, 3); ++ ((ServerLevel)world).getChunkSource().blockChanged(blockPosition); // We only need to re-send to client ++ } ++ } ++ ++ public enum EngineMode { ++ ++ HIDE(1, "hide ores"), ++ OBFUSCATE(2, "obfuscate"); ++ ++ private final int id; ++ private final String description; ++ ++ EngineMode(int id, String description) { ++ this.id = id; ++ this.description = description; ++ } ++ ++ public static EngineMode getById(int id) { ++ for (EngineMode engineMode : values()) { ++ if (engineMode.id == id) { ++ return engineMode; ++ } ++ } ++ ++ return null; ++ } ++ ++ public int getId() { ++ return id; ++ } ++ ++ public String getDescription() { ++ return description; ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java +new file mode 100644 +index 0000000000000000000000000000000000000000..dc04ffc76e11ab63cd98a84cf95c58dc5cd1efdb +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java +@@ -0,0 +1,81 @@ ++package com.destroystokyo.paper.antixray; ++ ++import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; ++import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.Palette; ++ ++public class ChunkPacketInfo { ++ ++ private final ClientboundLevelChunkPacket packetPlayOutMapChunk; ++ private final LevelChunk chunk; ++ private final int chunkSectionSelector; ++ private byte[] data; ++ private final int[] bitsPerObject = new int[16]; ++ private final Object[] dataPalettes = new Object[16]; ++ private final int[] dataBitsIndexes = new int[16]; ++ private final Object[][] predefinedObjects = new Object[16][]; ++ ++ public ChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector) { ++ this.packetPlayOutMapChunk = packetPlayOutMapChunk; ++ this.chunk = chunk; ++ this.chunkSectionSelector = chunkSectionSelector; ++ } ++ ++ public ClientboundLevelChunkPacket getPacketPlayOutMapChunk() { ++ return packetPlayOutMapChunk; ++ } ++ ++ public LevelChunk getChunk() { ++ return chunk; ++ } ++ ++ public int getChunkSectionSelector() { ++ return chunkSectionSelector; ++ } ++ ++ public byte[] getData() { ++ return data; ++ } ++ ++ public void setData(byte[] data) { ++ this.data = data; ++ } ++ ++ public int getBitsPerObject(int chunkSectionIndex) { ++ return bitsPerObject[chunkSectionIndex]; ++ } ++ ++ public void setBitsPerObject(int chunkSectionIndex, int bitsPerObject) { ++ this.bitsPerObject[chunkSectionIndex] = bitsPerObject; ++ } ++ ++ @SuppressWarnings("unchecked") ++ public Palette getDataPalette(int chunkSectionIndex) { ++ return (Palette) dataPalettes[chunkSectionIndex]; ++ } ++ ++ public void setDataPalette(int chunkSectionIndex, Palette dataPalette) { ++ dataPalettes[chunkSectionIndex] = dataPalette; ++ } ++ ++ public int getDataBitsIndex(int chunkSectionIndex) { ++ return dataBitsIndexes[chunkSectionIndex]; ++ } ++ ++ public void setDataBitsIndex(int chunkSectionIndex, int dataBitsIndex) { ++ dataBitsIndexes[chunkSectionIndex] = dataBitsIndex; ++ } ++ ++ @SuppressWarnings("unchecked") ++ public T[] getPredefinedObjects(int chunkSectionIndex) { ++ return (T[]) predefinedObjects[chunkSectionIndex]; ++ } ++ ++ public void setPredefinedObjects(int chunkSectionIndex, T[] predefinedObjects) { ++ this.predefinedObjects[chunkSectionIndex] = predefinedObjects; ++ } ++ ++ public boolean isWritten(int chunkSectionIndex) { ++ return bitsPerObject[chunkSectionIndex] != 0; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7345f1dc7c5c05f2e1ee09b94f4ebf56dd59bc55 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java +@@ -0,0 +1,30 @@ ++package com.destroystokyo.paper.antixray; ++ ++import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.LevelChunk; ++ ++public final class ChunkPacketInfoAntiXray extends ChunkPacketInfo implements Runnable { ++ ++ private LevelChunk[] nearbyChunks; ++ private final ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray; ++ ++ public ChunkPacketInfoAntiXray(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector, ++ ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray) { ++ super(packetPlayOutMapChunk, chunk, chunkSectionSelector); ++ this.chunkPacketBlockControllerAntiXray = chunkPacketBlockControllerAntiXray; ++ } ++ ++ public LevelChunk[] getNearbyChunks() { ++ return nearbyChunks; ++ } ++ ++ public void setNearbyChunks(LevelChunk... nearbyChunks) { ++ this.nearbyChunks = nearbyChunks; ++ } ++ ++ @Override ++ public void run() { ++ chunkPacketBlockControllerAntiXray.obfuscate(this); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..298ea423084dbcc1b61f991bcd82b8ae51bf0977 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java +@@ -0,0 +1,51 @@ ++package com.destroystokyo.paper.antixray; ++ ++public final class DataBitsReader { ++ ++ private byte[] dataBits; ++ private int bitsPerObject; ++ private int mask; ++ private int longInDataBitsIndex; ++ private int bitInLongIndex; ++ private long current; ++ ++ public void setDataBits(byte[] dataBits) { ++ this.dataBits = dataBits; ++ } ++ ++ public void setBitsPerObject(int bitsPerObject) { ++ this.bitsPerObject = bitsPerObject; ++ mask = (1 << bitsPerObject) - 1; ++ } ++ ++ public void setIndex(int index) { ++ this.longInDataBitsIndex = index; ++ bitInLongIndex = 0; ++ init(); ++ } ++ ++ private void init() { ++ if (dataBits.length > longInDataBitsIndex + 7) { ++ current = ((((long) dataBits[longInDataBitsIndex]) << 56) ++ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) ++ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) ++ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) ++ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) ++ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) ++ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) ++ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); ++ } ++ } ++ ++ public int read() { ++ if (bitInLongIndex + bitsPerObject > 64) { ++ bitInLongIndex = 0; ++ longInDataBitsIndex += 8; ++ init(); ++ } ++ ++ int value = (int) (current >>> bitInLongIndex) & mask; ++ bitInLongIndex += bitsPerObject; ++ return value; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..333763936897befda5bb6c077944d2667f922799 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java +@@ -0,0 +1,79 @@ ++package com.destroystokyo.paper.antixray; ++ ++public final class DataBitsWriter { ++ ++ private byte[] dataBits; ++ private int bitsPerObject; ++ private long mask; ++ private int longInDataBitsIndex; ++ private int bitInLongIndex; ++ private long current; ++ private boolean dirty; ++ ++ public void setDataBits(byte[] dataBits) { ++ this.dataBits = dataBits; ++ } ++ ++ public void setBitsPerObject(int bitsPerObject) { ++ this.bitsPerObject = bitsPerObject; ++ mask = (1 << bitsPerObject) - 1; ++ } ++ ++ public void setIndex(int index) { ++ this.longInDataBitsIndex = index; ++ bitInLongIndex = 0; ++ init(); ++ } ++ ++ private void init() { ++ if (dataBits.length > longInDataBitsIndex + 7) { ++ current = ((((long) dataBits[longInDataBitsIndex]) << 56) ++ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) ++ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) ++ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) ++ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) ++ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) ++ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) ++ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); ++ } ++ ++ dirty = false; ++ } ++ ++ public void finish() { ++ if (dirty && dataBits.length > longInDataBitsIndex + 7) { ++ dataBits[longInDataBitsIndex] = (byte) (current >> 56 & 0xff); ++ dataBits[longInDataBitsIndex + 1] = (byte) (current >> 48 & 0xff); ++ dataBits[longInDataBitsIndex + 2] = (byte) (current >> 40 & 0xff); ++ dataBits[longInDataBitsIndex + 3] = (byte) (current >> 32 & 0xff); ++ dataBits[longInDataBitsIndex + 4] = (byte) (current >> 24 & 0xff); ++ dataBits[longInDataBitsIndex + 5] = (byte) (current >> 16 & 0xff); ++ dataBits[longInDataBitsIndex + 6] = (byte) (current >> 8 & 0xff); ++ dataBits[longInDataBitsIndex + 7] = (byte) (current & 0xff); ++ } ++ } ++ ++ public void write(int value) { ++ if (bitInLongIndex + bitsPerObject > 64) { ++ finish(); ++ bitInLongIndex = 0; ++ longInDataBitsIndex += 8; ++ init(); ++ } ++ ++ current = current & ~(mask << bitInLongIndex) | (value & mask) << bitInLongIndex; ++ dirty = true; ++ bitInLongIndex += bitsPerObject; ++ } ++ ++ public void skip() { ++ bitInLongIndex += bitsPerObject; ++ ++ if (bitInLongIndex > 64) { ++ finish(); ++ bitInLongIndex = bitsPerObject; ++ longInDataBitsIndex += 8; ++ init(); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index b587f774c8f88f2a1c3ea489f7e4fe0bbdeb5a41..10dd582b0fff4df27f1113e41c8ee3e274c6fb65 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -1,5 +1,6 @@ + package net.minecraft.network.protocol.game; + ++import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info + import com.google.common.collect.Lists; + import io.netty.buffer.ByteBuf; + import io.netty.buffer.Unpooled; +@@ -16,6 +17,7 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.SkullBlockEntity; ++import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.chunk.ChunkBiomeContainer; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.chunk.LevelChunkSection; +@@ -33,7 +35,13 @@ public class ClientboundLevelChunkPacket implements Packet blockEntitiesTags; + private boolean fullChunk; + +- public ClientboundLevelChunkPacket() {} ++ // Paper start - Async-Anti-Xray - Set the ready flag to true ++ private volatile boolean ready; // Paper - Async-Anti-Xray - Ready flag for the network manager ++ public ClientboundLevelChunkPacket() { ++ this.ready = true; ++ } ++ // Paper end ++ + // Paper start + private final java.util.List extraPackets = new java.util.ArrayList<>(); + private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); +@@ -43,12 +51,16 @@ public class ClientboundLevelChunkPacket implements Packet chunkPacketInfo = modifyBlocks ? chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i) : null; ++ // Paper end + ChunkPos chunkcoordintpair = chunk.getPos(); + + this.x = chunkcoordintpair.x; + this.z = chunkcoordintpair.z; +- this.fullChunk = includedSectionsMask == 65535; ++ this.fullChunk = i == 65535; + this.heightmaps = new CompoundTag(); + Iterator iterator = chunk.getHeightmaps().iterator(); + +@@ -65,8 +77,13 @@ public class ClientboundLevelChunkPacket implements Packet> 4; + +- if (this.isFullChunk() || (includedSectionsMask & 1 << j) != 0) { ++ if (this.isFullChunk() || (i & 1 << j) != 0) { + // Paper start - improve oversized chunk data packet handling + if (++totalTileEntities > TE_LIMIT) { + ClientboundBlockEntityDataPacket updatePacket = tileentity.getUpdatePacket(); +@@ -93,8 +110,19 @@ public class ClientboundLevelChunkPacket implements Packet chunkPacketInfo) { return this.a(packetDataSerializer, chunk, chunkSectionSelector, chunkPacketInfo); } // OBFHELPER ++ public int a(FriendlyByteBuf packetdataserializer, LevelChunk chunk, int i, ChunkPacketInfo chunkPacketInfo) { ++ // Paper end + int j = 0; + LevelChunkSection[] achunksection = chunk.getSections(); + int k = 0; +@@ -169,9 +201,9 @@ public class ClientboundLevelChunkPacket implements Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER + private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { + if (packets[0] == null) { +- packets[0] = new ClientboundLevelChunkPacket(chunk, 65535); ++ packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass + packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, true); + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index fd7ee4badb383ffb4347d62c00ea2dfa3d76fd12..7a09bc921827958f58290bd3d6f19984bb34a8f6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -204,7 +204,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + // Add env and gen to constructor, WorldData -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { +- super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env); ++ super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor + this.pvpMode = minecraftserver.isPvpAllowed(); + convertable = convertable_conversionsession; + uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile()); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index d97607f2ded4977b253d3afa3bafcbe6d7f98837..af048ab682612233c01f7087d7b8afbf7e58945b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -308,6 +308,8 @@ public class ServerPlayerGameMode { + } + + } ++ ++ this.level.chunkPacketBlockController.onPlayerLeftClickBlock(this, pos, direction); // Paper - Anti-Xray + } + + public void destroyAndAck(BlockPos pos, ServerboundPlayerActionPacket.Action action, String reason) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index eb88d830fb45a6b8c990e8bdc1943d80f63c8b93..1377465e3dc062f34be25cac10aa018776fb22e7 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -2,6 +2,8 @@ package net.minecraft.world.level; + + import co.aikar.timings.Timing; + import co.aikar.timings.Timings; ++import com.destroystokyo.paper.antixray.ChunkPacketBlockController; // Paper - Anti-Xray ++import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray; // Paper - Anti-Xray + import com.destroystokyo.paper.event.server.ServerExceptionEvent; + import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.base.MoreObjects; +@@ -144,6 +146,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + + public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper ++ public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray + + public final co.aikar.timings.WorldTimingsHandler timings; // Paper + public static BlockPos lastPhysicsProblem; // Spigot +@@ -165,9 +168,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return typeKey; + } + +- protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { ++ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot + this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper ++ this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray + this.generator = gen; + this.world = new CraftWorld((ServerLevel) this, gen, env); + this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns(); // CraftBukkit +@@ -433,6 +437,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // CraftBukkit end + + BlockState iblockdata1 = chunk.setType(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag ++ this.chunkPacketBlockController.onBlockChange(this, pos, state, iblockdata1, flags); // Paper - Anti-Xray + + if (iblockdata1 == null) { + // CraftBukkit start - remove blockstate if failed (or the same) +diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +index e369730ac6909ff5343468bd685c9ea2b6b3cfed..2c19d147710a3bbe2e980114161f1cdf81760947 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +@@ -8,6 +8,7 @@ import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Registry; + import net.minecraft.data.worldgen.biome.Biomes; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkPos; +@@ -28,7 +29,7 @@ public class EmptyLevelChunk extends LevelChunk { + }); + + public EmptyLevelChunk(Level world, ChunkPos pos) { +- super(world, pos, new ChunkBiomeContainer(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), EmptyLevelChunk.BIOMES)); ++ super(world, pos, new ChunkBiomeContainer(MinecraftServer.getServer().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), EmptyLevelChunk.BIOMES)); // Paper - world isnt ready yet for anti xray use here, use server singleton for registry + } + + // Paper start +diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +index 17fa8b23d1000ae53f2b4f1a6e8817c1005c1c81..56ab660e29a0dc7d22eeaa41cc8f50e8a96717ef 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +@@ -27,7 +27,7 @@ public class ImposterProtoChunk extends ProtoChunk { + private final LevelChunk wrapped; + + public ImposterProtoChunk(LevelChunk wrapped) { +- super(wrapped.getPos(), UpgradeData.EMPTY); ++ super(wrapped.getPos(), UpgradeData.EMPTY, wrapped.world); // Paper - Anti-Xray - Add parameter + this.wrapped = wrapped; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 419b4bf0549d798d52d73fbbd9de59313fc05eb1..85861545ec4620a6cfd06876dad091637bd29b0b 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -464,7 +464,7 @@ public class LevelChunk implements ChunkAccess { + return null; + } + +- chunksection = new LevelChunkSection(j >> 4 << 4); ++ chunksection = new LevelChunkSection(j >> 4 << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters + this.sections[j >> 4] = chunksection; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index f5db97fb0dac78e1d9aa68d0417aa13f39914f52..38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -1,9 +1,11 @@ + package net.minecraft.world.level.chunk; + + import java.util.function.Predicate; ++import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info + import javax.annotation.Nullable; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.network.FriendlyByteBuf; ++import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; +@@ -18,16 +20,22 @@ public class LevelChunkSection { + private short tickingFluidCount; + final PalettedContainer states; // Paper - package-private + +- public LevelChunkSection(int yOffset) { +- this(yOffset, (short) 0, (short) 0, (short) 0); ++ // Paper start - Anti-Xray - Add parameters ++ @Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public LevelChunkSection(int i, ChunkAccess chunk, Level world, boolean initializeBlocks) { ++ this(i, (short) 0, (short) 0, (short) 0, chunk, world, initializeBlocks); ++ // Paper end + } + +- public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount) { +- this.bottomBlockY = yOffset; +- this.nonEmptyBlockCount = nonEmptyBlockCount; +- this.tickingBlockCount = randomTickableBlockCount; +- this.tickingFluidCount = nonEmptyFluidCount; +- this.states = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); ++ // Paper start - Anti-Xray - Add parameters ++ @Deprecated public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount) { this(yOffset, nonEmptyBlockCount, randomTickableBlockCount, nonEmptyFluidCount, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public LevelChunkSection(int i, short short0, short short1, short short2, ChunkAccess chunk, Level world, boolean initializeBlocks) { ++ // Paper end ++ this.bottomBlockY = i; ++ this.nonEmptyBlockCount = short0; ++ this.tickingBlockCount = short1; ++ this.tickingFluidCount = short2; ++ this.states = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState(), world == null ? null : world.chunkPacketBlockController.getPredefinedBlockData(world, chunk, this, initializeBlocks), initializeBlocks); // Paper - Anti-Xray - Add predefined block data + } + + public final BlockState getBlockState(int x, int y, int z) { // Paper +@@ -139,10 +147,14 @@ public class LevelChunkSection { + return this.states; + } + +- public void writeChunkSection(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER +- public void write(FriendlyByteBuf packetdataserializer) { ++ // Paper start - Anti-Xray - Add chunk packet info ++ @Deprecated public final void writeChunkSection(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere ++ @Deprecated public final void write(FriendlyByteBuf packetdataserializer) { this.writeChunkSection(packetdataserializer, null); } // Notice for updates: Please make sure this method isn't used anywhere ++ public final void writeChunkSection(FriendlyByteBuf packetDataSerializer, ChunkPacketInfo chunkPacketInfo) { this.b(packetDataSerializer, chunkPacketInfo); } // OBFHELPER ++ public void b(FriendlyByteBuf packetdataserializer, ChunkPacketInfo chunkPacketInfo) { ++ // Paper end + packetdataserializer.writeShort(this.nonEmptyBlockCount); +- this.states.write(packetdataserializer); ++ this.states.writeDataPaletteBlock(packetdataserializer, chunkPacketInfo, this.bottomBlockY >> 4); // Paper - Anti-Xray - Add chunk packet info + } + + public int getSerializedSize() { +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index 917b0a64083ebbe24321089b784b91f3af4918b9..dd252372e1e380674b1191e9ea265cbb10de437b 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.chunk; + + import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; ++import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info + import java.util.Arrays; + import java.util.Objects; + import java.util.concurrent.locks.ReentrantLock; +@@ -26,6 +27,7 @@ public class PalettedContainer implements PaletteResize { + private final Function reader; + private final Function writer; + private final T defaultValue; ++ private final T[] predefinedObjects; // Paper - Anti-Xray - Add predefined objects + protected BitStorage storage; public final BitStorage getDataBits() { return this.storage; } // Paper - OBFHELPER + private Palette palette; private Palette getDataPalette() { return this.palette; } // Paper - OBFHELPER + private int bits; private int getBitsPerObject() { return this.bits; } // Paper - OBFHELPER +@@ -50,14 +52,47 @@ public class PalettedContainer implements PaletteResize { + //this.j.unlock(); // Paper - disable this + } + +- public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { +- this.globalPalette = fallbackPalette; +- this.registry = idList; +- this.reader = elementDeserializer; +- this.writer = elementSerializer; +- this.defaultValue = defaultElement; +- this.setBits(4); ++ // Paper start - Anti-Xray - Add predefined objects ++ @Deprecated public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { this(fallbackPalette, idList, elementDeserializer, elementSerializer, defaultElement, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public PalettedContainer(Palette datapalette, IdMapper registryblockid, Function function, Function function1, T t0, T[] predefinedObjects, boolean initialize) { ++ // Paper end ++ this.globalPalette = datapalette; ++ this.registry = registryblockid; ++ this.reader = function; ++ this.writer = function1; ++ this.defaultValue = t0; ++ // Paper start - Anti-Xray - Add predefined objects ++ this.predefinedObjects = predefinedObjects; ++ ++ if (initialize) { ++ if (predefinedObjects == null) { ++ // Default ++ this.initialize(4); ++ } else { ++ // MathHelper.d() is trailingBits(roundCeilPow2(n)), alternatively; (int)ceil(log2(n)); however it's trash, use numberOfLeadingZeros instead ++ // Count the bits of the maximum array index to initialize a data palette with enough space from the beginning ++ // The length of the array is used because air is also added to the data palette from the beginning ++ // Start with at least 4 ++ int maxIndex = predefinedObjects.length >> 4; ++ int bitCount = (32 - Integer.numberOfLeadingZeros(Math.max(16, maxIndex) - 1)); ++ ++ // Initialize with at least 15 free indixes ++ this.initialize((1 << bitCount) - predefinedObjects.length < 16 ? bitCount + 1 : bitCount); ++ this.addPredefinedObjects(); ++ } ++ } ++ // Paper end ++ } ++ ++ // Paper start - Anti-Xray - Add predefined objects ++ private void addPredefinedObjects() { ++ if (this.predefinedObjects != null && this.getDataPalette() != this.getDataPaletteGlobal()) { ++ for (int i = 0; i < this.predefinedObjects.length; i++) { ++ this.getDataPalette().getOrCreateIdFor(this.predefinedObjects[i]); ++ } ++ } + } ++ // Paper end + + private static int getIndex(int x, int y, int z) { + return y << 8 | z << 4 | x; +@@ -92,6 +127,7 @@ public class PalettedContainer implements PaletteResize { + + int j; + ++ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects + for (j = 0; j < databits.getSize(); ++j) { + T t1 = datapalette.valueFor(databits.get(j)); + +@@ -141,24 +177,38 @@ public class PalettedContainer implements PaletteResize { + return t0 == null ? this.defaultValue : t0; + } + +- public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER +- public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize ++ // Paper start - Anti-Xray - Add chunk packet info ++ @Deprecated public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere ++ @Deprecated public void write(FriendlyByteBuf buf) { this.writeDataPaletteBlock(buf, null, 0); } // Notice for updates: Please make sure this method isn't used anywhere ++ public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { this.b(packetDataSerializer, chunkPacketInfo, chunkSectionIndex); } // OBFHELPER ++ public synchronized void b(FriendlyByteBuf packetdataserializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { // Paper - synchronize ++ // Paper end + this.acquire(); +- buf.writeByte(this.bits); +- this.palette.write(buf); +- buf.writeLongArray(this.storage.getRaw()); ++ packetdataserializer.writeByte(this.bits); ++ this.palette.write(packetdataserializer); ++ // Paper start - Anti-Xray - Add chunk packet info ++ if (chunkPacketInfo != null) { ++ chunkPacketInfo.setBitsPerObject(chunkSectionIndex, this.getBitsPerObject()); ++ chunkPacketInfo.setDataPalette(chunkSectionIndex, this.getDataPalette()); ++ chunkPacketInfo.setDataBitsIndex(chunkSectionIndex, packetdataserializer.writerIndex() + FriendlyByteBuf.countBytes(this.getDataBits().getDataBits().length)); ++ chunkPacketInfo.setPredefinedObjects(chunkSectionIndex, this.predefinedObjects); ++ } ++ // Paper end ++ packetdataserializer.writeLongArray(this.storage.getRaw()); + this.release(); + } + + public synchronized void read(ListTag paletteTag, long[] data) { // Paper - synchronize + this.acquire(); +- int i = Math.max(4, Mth.ceillog2(paletteTag.size())); ++ // Paper - Anti-Xray - TODO: Should this.predefinedObjects.length just be added here (faster) or should the contents be compared to calculate the size (less RAM)? ++ int i = Math.max(4, Mth.ceillog2(paletteTag.size() + (this.predefinedObjects == null ? 0 : this.predefinedObjects.length))); // Paper - Anti-Xray - Calculate the size with predefined objects + +- if (i != this.bits) { ++ if (true || i != this.bits) { // Paper - Anti-Xray - Not initialized yet + this.setBits(i); + } + + this.palette.read(paletteTag); ++ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects + int j = data.length * 64 / 4096; + + if (this.palette == this.globalPalette) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index d8b7b210484079c9ca2c34831c84102cba6692f5..87fd585141ad9818fca0b697cb4c87248fe7ce11 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -64,16 +64,24 @@ public class ProtoChunk implements ChunkAccess { + private long inhabitedTime; + private final Map carvingMasks; + private volatile boolean isLightCorrect; ++ private final Level world; // Paper - Anti-Xray - Add world + +- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { +- this(pos, upgradeData, (LevelChunkSection[]) null, new ProtoTickList<>((block) -> { ++ // Paper start - Anti-Xray - Add world ++ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { this(pos, upgradeData, null); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public ProtoChunk(ChunkPos chunkcoordintpair, UpgradeData chunkconverter, Level world) { ++ // Paper end ++ this(chunkcoordintpair, chunkconverter, (LevelChunkSection[]) null, new ProtoTickList<>((block) -> { + return block == null || block.defaultBlockState().isAir(); +- }, pos), new ProtoTickList<>((fluidtype) -> { ++ }, chunkcoordintpair), new ProtoTickList<>((fluidtype) -> { + return fluidtype == null || fluidtype == Fluids.EMPTY; +- }, pos)); ++ }, chunkcoordintpair), world); // Paper - Anti-Xray - Add world + } + +- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] sections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler) { ++ // Paper start - Anti-Xray - Add world ++ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] sections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler) { this(pos, upgradeData, sections, blockTickScheduler, fluidTickScheduler, null); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public ProtoChunk(ChunkPos chunkcoordintpair, UpgradeData chunkconverter, @Nullable LevelChunkSection[] achunksection, ProtoTickList protochunkticklist, ProtoTickList protochunkticklist1, Level world) { ++ this.world = world; ++ // Paper end + this.heightmaps = Maps.newEnumMap(Heightmap.Types.class); + this.status = ChunkStatus.EMPTY; + this.blockEntities = Maps.newHashMap(); +@@ -85,15 +93,15 @@ public class ProtoChunk implements ChunkAccess { + this.structureStarts = Maps.newHashMap(); + this.structuresRefences = Maps.newHashMap(); + this.carvingMasks = new Object2ObjectArrayMap(); +- this.chunkPos = pos; +- this.upgradeData = upgradeData; +- this.blockTicks = blockTickScheduler; +- this.liquidTicks = fluidTickScheduler; +- if (sections != null) { +- if (this.sections.length == sections.length) { +- System.arraycopy(sections, 0, this.sections, 0, this.sections.length); ++ this.chunkPos = chunkcoordintpair; ++ this.upgradeData = chunkconverter; ++ this.blockTicks = protochunkticklist; ++ this.liquidTicks = protochunkticklist1; ++ if (achunksection != null) { ++ if (this.sections.length == achunksection.length) { ++ System.arraycopy(achunksection, 0, this.sections, 0, this.sections.length); + } else { +- ProtoChunk.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", sections.length, this.sections.length); ++ ProtoChunk.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", achunksection.length, this.sections.length); + } + } + +@@ -228,7 +236,7 @@ public class ProtoChunk implements ChunkAccess { + + public LevelChunkSection getOrCreateSection(int y) { + if (this.sections[y] == LevelChunk.EMPTY_SECTION) { +- this.sections[y] = new LevelChunkSection(y << 4); ++ this.sections[y] = new LevelChunkSection(y << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters + } + + return this.sections[y]; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 969130442b529eaac6f708107ff129f89cc0af90..8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -101,7 +101,7 @@ public class ChunkSerializer { + byte b0 = nbttagcompound2.getByte("Y"); + + if (nbttagcompound2.contains("Palette", 9) && nbttagcompound2.contains("BlockStates", 12)) { +- LevelChunkSection chunksection = new LevelChunkSection(b0 << 4); ++ LevelChunkSection chunksection = new LevelChunkSection(b0 << 4, null, world, false); // Paper - Anti-Xray - Add parameters + + chunksection.getStates().read(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); + chunksection.recalcBlockCounts(); +@@ -165,7 +165,7 @@ public class ChunkSerializer { + // CraftBukkit end + }); + } else { +- ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1); ++ ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world); // Paper - Anti-Xray - Add parameter + + protochunk.setBiomes(biomestorage); + object = protochunk; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +index 423594177fe78600755d913f169f28dd1bfa2b37..74bad15034d9d55fb70931f38868f812160c6305 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +@@ -43,7 +43,7 @@ public class CraftChunk implements Chunk { + private final ServerLevel worldServer; + private final int x; + private final int z; +- private static final PalettedContainer emptyBlockIDs = new LevelChunkSection(0).getStates(); ++ private static final PalettedContainer emptyBlockIDs = new LevelChunkSection(0, null, null, true).getStates(); // Paper - Anti-Xray - Add parameters + private static final byte[] emptyLight = new byte[2048]; + + public CraftChunk(net.minecraft.world.level.chunk.LevelChunk chunk) { +@@ -287,7 +287,7 @@ public class CraftChunk implements Chunk { + CompoundTag data = new CompoundTag(); + cs[i].getStates().write(data, "Palette", "BlockStates"); + +- PalettedContainer blockids = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, net.minecraft.world.level.block.Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); // TODO: snapshot whole ChunkSection ++ PalettedContainer blockids = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, net.minecraft.world.level.block.Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState(), null, false); // TODO: snapshot whole ChunkSection // Paper - Anti-Xray - Add no predefined block data and don't initialize because it's done in the line below internally + blockids.read(data.getList("Palette", CraftMagicNumbers.NBT.TAG_COMPOUND), data.getLongArray("BlockStates")); + + sectionBlockIDs[i] = blockids; +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +index a94c65f4d63a06be099fd67b0b7756c5b45b84a0..8d72cd6a44cf462cfe3adac9bf99a16883a587df 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +@@ -21,9 +21,11 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + private final int maxHeight; + private final LevelChunkSection[] sections; + private Set tiles; ++ private World world; // Paper - Anti-Xray - Add world + + public CraftChunkData(World world) { + this(world.getMaxHeight()); ++ this.world = world; // Paper - Anti-Xray - Add world + } + + /* pp for tests */ CraftChunkData(int maxHeight) { +@@ -157,7 +159,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + private LevelChunkSection getChunkSection(int y, boolean create) { + LevelChunkSection section = sections[y >> 4]; + if (create && section == null) { +- sections[y >> 4] = section = new LevelChunkSection(y >> 4 << 4); ++ sections[y >> 4] = section = new LevelChunkSection(y >> 4 << 4, null, world instanceof org.bukkit.craftbukkit.CraftWorld ? ((org.bukkit.craftbukkit.CraftWorld) world).getHandle() : null, true); // Paper - Anti-Xray - Add parameters + } + return section; + } diff --git a/Remapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/Remapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch new file mode 100644 index 0000000000..0d019759ff --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Mar 2019 01:01:32 -0400 +Subject: [PATCH] Only count Natural Spawned mobs towards natural spawn mob + limit + +This resolves the super common complaint about mobs not spawning. + +This was ultimately a flaw in the vanilla count algorithim that allows +spawners and other misc mobs to count against the mob limit, which are +not bounded, and can prevent the entire world from spawning new. + +I believe Bukkits changes around persistence may of actually made it +worse than vanilla. + +This should fully solve all of the issues around it so that only natural +influences natural spawns. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index c45493e88bf7e8811be2759ff9ac19e3fe9d938a..384cb363eed794551bee6b0ec11ba1be92a3d7ac 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -464,6 +464,16 @@ public class PaperWorldConfig { + maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); + } + ++ public boolean countAllMobsForSpawning = false; ++ private void countAllMobsForSpawning() { ++ countAllMobsForSpawning = getBoolean("count-all-mobs-for-spawning", false); ++ if (countAllMobsForSpawning) { ++ log("Counting all mobs for spawning. Mob farms may reduce natural spawns elsewhere in world."); ++ } else { ++ log("Using improved mob spawn limits (Only Natural Spawns impact spawn limits for more natural spawns)"); ++ } ++ } ++ + public boolean antiXray; + public EngineMode engineMode; + public int maxChunkSectionIndex; +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index e23875ae07c23fed1161ea070e63bbc3a30168a0..0fb69f9194078e5e05e36ed909eb48424b6465b4 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -79,6 +79,13 @@ public final class NaturalSpawner { + MobCategory enumcreaturetype = entity.getType().getCategory(); + + if (enumcreaturetype != MobCategory.MISC) { ++ // Paper start - Only count natural spawns ++ if (!entity.level.paperConfig.countAllMobsForSpawning && ++ !(entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL || ++ entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { ++ continue; ++ } ++ // Paper end + BlockPos blockposition = entity.blockPosition(); + long j = ChunkPos.asLong(blockposition.getX() >> 4, blockposition.getZ() >> 4); + diff --git a/Remapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch b/Remapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch new file mode 100644 index 0000000000..111827bdd8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lucavon +Date: Tue, 23 Jul 2019 20:29:20 -0500 +Subject: [PATCH] Configurable projectile relative velocity + +This patch adds an option "disable relative projectile velocity", which, when +nabled, will cause projectiles to ignore the shooter's current velocity, +like they did in Minecraft 1.8 and prior. +If a player is falling, for example, their shooting range will be drastically +reduced, as a downwards velocity is applied to the projectile. This prevents +players from saving themselves from falling off floating islands, for example, +as a thrown ender pearl will not make it back to the island, while it would +have in 1.8. + +While this could easily be done with plugins, too, there are multiple problems: +P1) If multiple plugins cancel the velocity by subtracting the shooter's velocity +from the projectile's velocity, the projectile's velocity would be different. +As there's no way to detect whether the projectile's velocity has already been +adjusted to ignore the player's velocity, plugins can't not do it if it's not +necessary. +P2) I've noticed some inconsistencies, e.g. weird velocity when shooting while +using an elytra. Checking for those inconsistencies is possible, but not as +efficient as just not applying the velocity in the first place. +P3) Solutions for 1) and especially 2) might not be future-proof, while this +server-internal fix makes this change future-proof. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 384cb363eed794551bee6b0ec11ba1be92a3d7ac..1ee2cced100626e48eb36ee14f84b9257c79a2f8 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -507,4 +507,9 @@ public class PaperWorldConfig { + Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); + } + } ++ ++ public boolean disableRelativeProjectileVelocity; ++ private void disableRelativeProjectileVelocity() { ++ disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index d385fb6eee5000951c350b6ced5669dc3dcce725..ca3d936433cd47caa4e0335e41246b1c4ce0eb99 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -129,7 +129,7 @@ public abstract class Projectile extends Entity { + this.shoot((double) f5, (double) f6, (double) f7, modifierZ, modifierXYZ); + Vec3 vec3d = user.getDeltaMovement(); + +- this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, user.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); ++ if (!user.level.paperConfig.disableRelativeProjectileVelocity) this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, user.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); // Paper - allow disabling relative velocity + } + + // CraftBukkit start - call projectile hit event diff --git a/Remapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch b/Remapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch new file mode 100644 index 0000000000..17630cf486 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 28 Jul 2019 00:51:11 +0100 +Subject: [PATCH] Mark entities as being ticked when notifying navigation + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 7a09bc921827958f58290bd3d6f19984bb34a8f6..a811ced17721b70bb51837f47e466c2261db2466 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1469,6 +1469,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + VoxelShape voxelshape1 = newState.getCollisionShape(this, pos); + + if (Shapes.joinIsNotEmpty(voxelshape, voxelshape1, BooleanOp.NOT_SAME)) { ++ boolean wasTicking = this.tickingEntities; this.tickingEntities = true; // Paper + Iterator iterator = this.navigations.iterator(); + + while (iterator.hasNext()) { +@@ -1490,6 +1491,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + } + ++ this.tickingEntities = wasTicking; // Paper + } + } + diff --git a/Remapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch b/Remapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch new file mode 100644 index 0000000000..32966f397f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Tue, 30 Jul 2019 03:17:16 +0500 +Subject: [PATCH] offset item frame ticking + + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java +index e0bf8c6c838b18a0c55b6f3317033e892b631f5c..3277a56bcf3831f8d3c9fa9168c608b369eed7e4 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java +@@ -35,7 +35,7 @@ public abstract class HangingEntity extends Entity { + protected static final Predicate HANGING_ENTITY = (entity) -> { + return entity instanceof HangingEntity; + }; +- private int checkInterval; ++ private int checkInterval; { this.checkInterval = this.getId() % this.level.spigotConfig.hangingTickFrequency; } // Paper + public BlockPos pos; + protected Direction direction; + diff --git a/Remapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch b/Remapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch new file mode 100644 index 0000000000..ee50904042 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: CullanP +Date: Thu, 3 Mar 2016 02:13:38 -0600 +Subject: [PATCH] Avoid hopper searches if there are no items + +Hoppers searching for items and minecarts is the most expensive part of hopper ticking. +We keep track of the number of minecarts and items in a chunk. +If there are no items in the chunk, we skip searching for items. +If there are no minecarts in the chunk, we skip searching for them. + +Usually hoppers aren't near items, so we can skip most item searches. +And since minecart hoppers are used _very_ rarely near we can avoid alot of searching there. + +Combined, this adds up a lot. + +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index d3640975c5a33b4911428760691215905b987385..e7facd849e3511c64b4ae44b34382f4a4985f2a4 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -16,6 +16,7 @@ public final class EntitySelector { + public static final Predicate ENTITY_NOT_BEING_RIDDEN = (entity) -> { + return entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); + }; ++ public static final Predicate isInventory() { return CONTAINER_ENTITY_SELECTOR; } // Paper - OBFHELPER + public static final Predicate CONTAINER_ENTITY_SELECTOR = (entity) -> { + return entity instanceof Container && entity.isAlive(); + }; +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 85861545ec4620a6cfd06876dad091637bd29b0b..4fef3abe4b416cbebe1b456468b5c3e162de18f1 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -31,10 +31,13 @@ import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.Mth; ++import net.minecraft.world.Container; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.ChunkTickList; + import net.minecraft.world.level.EmptyTickList; +@@ -122,6 +125,10 @@ public class LevelChunk implements ChunkAccess { + return removed; + } + } ++ // Track the number of minecarts and items ++ // Keep this synced with entitySlices.add() and entitySlices.remove() ++ private final int[] itemCounts = new int[16]; ++ private final int[] inventoryEntityCounts = new int[16]; + // Paper end + + public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes, UpgradeData upgradeData, TickList blockTickScheduler, TickList fluidTickScheduler, long inhabitedTime, @Nullable LevelChunkSection[] sections, @Nullable Consumer loadToWorldConsumer) { +@@ -581,6 +588,13 @@ public class LevelChunk implements ChunkAccess { + entity.zChunk = this.chunkPos.z; + this.entities.add(entity); // Paper - per chunk entity list + this.entitySlices[k].add(entity); ++ // Paper start ++ if (entity instanceof ItemEntity) { ++ itemCounts[k]++; ++ } else if (entity instanceof Container) { ++ inventoryEntityCounts[k]++; ++ } ++ // Paper end + entity.entitySlice = this.entitySlices[k]; // Paper + this.markUnsaved(); // Paper + } +@@ -614,6 +628,11 @@ public class LevelChunk implements ChunkAccess { + if (!this.entitySlices[section].remove(entity)) { + return; + } ++ if (entity instanceof ItemEntity) { ++ itemCounts[section]--; ++ } else if (entity instanceof Container) { ++ inventoryEntityCounts[section]--; ++ } + entityCounts.decrement(entity.getMinecraftKeyString()); + this.markUnsaved(); // Paper + // Paper end +@@ -899,6 +918,14 @@ public class LevelChunk implements ChunkAccess { + for (int k = i; k <= j; ++k) { + Iterator iterator = this.entitySlices[k].iterator(); // Spigot + ++ // Paper start - Don't search for inventories if we have none, and that is all we want ++ /* ++ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` ++ * ++ * Make sure the inventory selector stays in sync. ++ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` ++ */ ++ if (predicate == EntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; + while (iterator.hasNext()) { + T entity = (T) iterator.next(); // CraftBukkit - decompile error + if (entity.shouldBeRemoved) continue; // Paper +@@ -919,9 +946,29 @@ public class LevelChunk implements ChunkAccess { + i = Mth.clamp(i, 0, this.entitySlices.length - 1); + j = Mth.clamp(j, 0, this.entitySlices.length - 1); + ++ // Paper start ++ int[] counts; ++ if (ItemEntity.class.isAssignableFrom(entityClass)) { ++ counts = itemCounts; ++ } else if (Container.class.isAssignableFrom(entityClass)) { ++ counts = inventoryEntityCounts; ++ } else { ++ counts = null; ++ } ++ // Paper end + for (int k = i; k <= j; ++k) { ++ if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for + Iterator iterator = this.entitySlices[k].iterator(); // Spigot + ++ // Paper start - Don't search for inventories if we have none, and that is all we want ++ /* ++ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` ++ * ++ * Make sure the inventory selector stays in sync. ++ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` ++ */ ++ if (predicate == EntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; ++ // Paper end + while (iterator.hasNext()) { + T t0 = (T) iterator.next(); // CraftBukkit - decompile error + if (t0.shouldBeRemoved) continue; // Paper diff --git a/Remapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch b/Remapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch new file mode 100644 index 0000000000..c4fd709325 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch @@ -0,0 +1,4410 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 13 Jul 2019 09:23:10 -0700 +Subject: [PATCH] Asynchronous chunk IO and loading + +This patch re-adds a file IO thread as well as shoving de-serializing +chunk NBT data onto worker threads. This patch also will shove +chunk data serialization onto the same worker threads when the chunk +is unloaded - this cannot be done for regular saves since that's unsafe. + +The file IO Thread + +Unlike 1.13 and below, the file IO thread is prioritized - IO tasks can +be reoredered, however they are "stuck" to a world & coordinate. + +Scheduling IO tasks works as follows, given a world & coordinate - location: + +The IO thread has been designed to ensure that reads and writes appear to +occur synchronously for a given location, however the implementation also +has the unfortunate side-effect of making every write appear as if +they occur without failure. + +The IO thread has also been designed to accomodate Mojang's decision to +store chunk data and POI data separately. It can independently schedule +tasks for each. + +However threads can wait for writes to complete and check if: + - The write was overwriten by another scheduler + - The write failed (however it does not indicate whether it was overwritten by another scheduler) + +Scheduling reads: + + - If a write task is in progress, the task is not scheduled and returns the in-progress write data + This means that readers cannot modify the NBTTagCompound returned and must clone if it they wish to write + - If a write task is not in progress but a read task is in progress, then the read task is simply chained + This means that again, readers cannot modify the NBTTagCompound returned + +Scheduling writes: + + - If a read task is in progress, ignore the read task and schedule the write + We cannot complete the read task since we assume it wants old data - not current + - If a write task is pending, overwrite the write data + The file IO thread does correctly handle cases where the data is overwritten when it + is writing data (before completing a task it will check if the data was overwritten and + will retry). + +When the file IO thread executes a task for a location, the it will +execute the read task first (if it exists), then it will execute the +write task. This ensures that, even when scheduling at different +priorities, that reads/writes for a location act synchronously. + +The downside of the file IO thread is that write failure can only be +indicated to the scheduling thread if: + +- No other thread decides to schedule another write for the location +concurrently +- The scheduling thread blocks on the write to complete (however the +current implementation can be modified to indicate success +asynchronously) + +The file io thread can be modified easily to provide indications +of write failure and write overwriting if needed. + +The upside of the file IO thread is that if a write failures, then +chunk data is not lost until server restart. This leaves more room +for spurious failure. + +Finally, the io thread will indicate to the console when reads +or writes fail - with relevant detail. + +Asynchronous chunk data serialization for unloading chunks + +When chunks unload they make a call to PlayerChunkMap#saveChunk(IChunkAccess). +Even if I make the IO asynchronous for this call, the data serialization +still hits pretty hard. And given that now the chunk system will +aggressively unload chunks more often (queued immediately at +ticket level 45 or higher), unloads occur more often, and +combined with our changes to the unload queue to make it +significantly more aggresive - chunk unloads can hit pretty hard. +Especially players running around with elytras and fireworks. + +For serializing chunk data off main, there are some tasks which cannot be +done asynchronously. Lighting data must be saved beforehand as well as +potentially some tick lists. These are completed before scheduling the +asynchronous save. + +However serializing chunk data off of the main thread is still risky. +Even though this patch schedules the save to occur after ALL references +of the chunk are removed from the world, plugins can still technically +access entities inside the chunks. For this, if the serialization task +fails for any reason, it will be re-scheduled to be serialized on the +main thread - with the hopes that the reason it failed was due to a plugin +and not an error with the save code itself. Like vanilla code - if the +serialization fails, the chunk data is lost. + +Asynchronous chunk io/loading + +Mojang's current implementation for loading chunk data off disk is +to return a CompletableFuture that will be completed by scheduling a +task to be executed on the world's chunk queue (which is only drained +on the main thread). This task will read the IO off disk and it will +apply data conversions & deserialization synchronously. Obviously +all 3 of these operations are expensive however all can be completed +asynchronously instead. + +The solution this patch uses is as follows: + +0. If an asynchronous chunk save is in progress (see above), wait +for that task to complete. It will use the serialized NBTTagCompound +created by the task. If the task fails to complete, then we would continue +with step 1. If it does not, we skip step 1. (Note: We actually load +POI data no matter what in this case). +1. Schedule an IO task to read chunk & poi data off disk. +2. The IO task will schedule a chunk load task. +3. The chunk load task executes on the async chunk loader threads +and will apply datafixers & de-serialize the chunk into a ProtoChunk +or ProtoChunkExtension. +4. The in progress chunk is then passed on to the world's chunk queue +to complete the ComletableFuture and execute any of the synchronous +tasks required to be executed by the chunk load task (i.e lighting +and some poi tasks). + +diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +index 79ede25e4fe7a648b1d29c49d876482a2158f892..24eac9400fbf971742e89bbf47b0ba52b587c4eb 100644 +--- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java ++++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +@@ -59,6 +59,17 @@ public class WorldTimingsHandler { + + public final Timing miscMobSpawning; + ++ public final Timing poiUnload; ++ public final Timing chunkUnload; ++ public final Timing poiSaveDataSerialization; ++ public final Timing chunkSave; ++ public final Timing chunkSaveOverwriteCheck; ++ public final Timing chunkSaveDataSerialization; ++ public final Timing chunkSaveIOWait; ++ public final Timing chunkUnloadPrepareSave; ++ public final Timing chunkUnloadPOISerialization; ++ public final Timing chunkUnloadDataSave; ++ + public WorldTimingsHandler(Level server) { + String name = ((PrimaryLevelData) server.getLevelData()).getLevelName() + " - "; + +@@ -112,6 +123,17 @@ public class WorldTimingsHandler { + + + miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); ++ ++ poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); ++ chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); ++ poiSaveDataSerialization = Timings.ofSafe(name + "Chunk save - POI Data serialization"); ++ chunkSave = Timings.ofSafe(name + "Chunk save - Chunk"); ++ chunkSaveOverwriteCheck = Timings.ofSafe(name + "Chunk save - Chunk Overwrite Check"); ++ chunkSaveDataSerialization = Timings.ofSafe(name + "Chunk save - Chunk Data serialization"); ++ chunkSaveIOWait = Timings.ofSafe(name + "Chunk save - Chunk IO Wait"); ++ chunkUnloadPrepareSave = Timings.ofSafe(name + "Chunk unload - Async Save Prepare"); ++ chunkUnloadPOISerialization = Timings.ofSafe(name + "Chunk unload - POI Data Serialization"); ++ chunkUnloadDataSave = Timings.ofSafe(name + "Chunk unload - Data Serialization"); + } + + public static Timing getTickList(ServerLevel worldserver, String timingsType) { +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 53dd6c18de8e80378852bbb141016d9574d42162..62711d95db62221a2e4e6423c518afe13a6c7dbe 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -1,5 +1,6 @@ + package com.destroystokyo.paper; + ++import com.destroystokyo.paper.io.chunk.ChunkTaskManager; + import com.google.common.base.Functions; + import com.google.common.base.Joiner; + import com.google.common.collect.ImmutableSet; +@@ -43,7 +44,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); + + public PaperCommand(String name) { + super(name); +@@ -155,6 +156,9 @@ public class PaperCommand extends Command { + case "debug": + doDebug(sender, args); + break; ++ case "dumpwaiting": ++ ChunkTaskManager.dumpAllChunkLoadInfo(); ++ break; + case "chunkinfo": + doChunkInfo(sender, args); + break; +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 469f78775b03cf363d88e35c69c0dc185c22547c..8bf4d2b8c38c02d6a5b2fea37113689a252f1571 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -1,5 +1,6 @@ + package com.destroystokyo.paper; + ++import com.destroystokyo.paper.io.chunk.ChunkTaskManager; + import com.google.common.base.Strings; + import com.google.common.base.Throwables; + +@@ -352,4 +353,54 @@ public class PaperConfig { + maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); + maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); + } ++ ++ public static boolean asyncChunks = false; ++ private static void asyncChunks() { ++ ConfigurationSection section; ++ if (version < 15) { ++ section = config.createSection("settings.async-chunks"); ++ section.set("threads", -1); ++ } else { ++ section = config.getConfigurationSection("settings.async-chunks"); ++ if (section == null) { ++ section = config.createSection("settings.async-chunks"); ++ } ++ } ++ // Clean up old configs ++ if (section.contains("load-threads")) { ++ if (!section.contains("threads")) { ++ section.set("threads", section.get("load-threads")); ++ } ++ section.set("load-threads", null); ++ } ++ section.set("generation", null); ++ section.set("enabled", null); ++ section.set("thread-per-world-generation", null); ++ ++ int threads = getInt("settings.async-chunks.threads", -1); ++ int cpus = Runtime.getRuntime().availableProcessors(); ++ if (threads <= 0) { ++ threads = (int) Math.min(Integer.getInteger("paper.maxChunkThreads", 8), Math.max(1, cpus - 1)); ++ } ++ if (cpus == 1 && !Boolean.getBoolean("Paper.allowAsyncChunksSingleCore")) { ++ asyncChunks = false; ++ } else { ++ asyncChunks = true; ++ } ++ ++ // Let Shared Host set some limits ++ String sharedHostThreads = System.getenv("PAPER_ASYNC_CHUNKS_SHARED_HOST_THREADS"); ++ if (sharedHostThreads != null) { ++ try { ++ threads = Math.max(1, Math.min(threads, Integer.parseInt(sharedHostThreads))); ++ } catch (NumberFormatException ignored) {} ++ } ++ ++ if (!asyncChunks) { ++ log("Async Chunks: Disabled - Chunks will be managed synchronously, and will cause tremendous lag."); ++ } else { ++ ChunkTaskManager.initGlobalLoadThreads(threads); ++ log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/io/IOUtil.java b/src/main/java/com/destroystokyo/paper/io/IOUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5af0ac3d9e87c06053e65433060f15779c156c2a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/IOUtil.java +@@ -0,0 +1,62 @@ ++package com.destroystokyo.paper.io; ++ ++import org.bukkit.Bukkit; ++ ++public final class IOUtil { ++ ++ /* Copied from concrete or concurrentutil */ ++ ++ public static long getCoordinateKey(final int x, final int z) { ++ return ((long)z << 32) | (x & 0xFFFFFFFFL); ++ } ++ ++ public static int getCoordinateX(final long key) { ++ return (int)key; ++ } ++ ++ public static int getCoordinateZ(final long key) { ++ return (int)(key >>> 32); ++ } ++ ++ public static int getRegionCoordinate(final int chunkCoordinate) { ++ return chunkCoordinate >> 5; ++ } ++ ++ public static int getChunkInRegion(final int chunkCoordinate) { ++ return chunkCoordinate & 31; ++ } ++ ++ public static String genericToString(final Object object) { ++ return object == null ? "null" : object.getClass().getName() + ":" + object.toString(); ++ } ++ ++ public static T notNull(final T obj) { ++ if (obj == null) { ++ throw new NullPointerException(); ++ } ++ return obj; ++ } ++ ++ public static T notNull(final T obj, final String msgIfNull) { ++ if (obj == null) { ++ throw new NullPointerException(msgIfNull); ++ } ++ return obj; ++ } ++ ++ public static void arrayBounds(final int off, final int len, final int arrayLength, final String msgPrefix) { ++ if (off < 0 || len < 0 || (arrayLength - off) < len) { ++ throw new ArrayIndexOutOfBoundsException(msgPrefix + ": off: " + off + ", len: " + len + ", array length: " + arrayLength); ++ } ++ } ++ ++ public static int getPriorityForCurrentThread() { ++ return Bukkit.isPrimaryThread() ? PrioritizedTaskQueue.HIGHEST_PRIORITY : PrioritizedTaskQueue.NORMAL_PRIORITY; ++ } ++ ++ @SuppressWarnings("unchecked") ++ public static void rethrow(final Throwable throwable) throws T { ++ throw (T)throwable; ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a630a84b60b4517e3bc330d4983b914bd064efa4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java +@@ -0,0 +1,606 @@ ++package com.destroystokyo.paper.io; ++ ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.chunk.storage.RegionFile; ++import org.apache.logging.log4j.Logger; ++ ++import java.io.IOException; ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.atomic.AtomicLong; ++import java.util.function.Consumer; ++import java.util.function.Function; ++ ++/** ++ * Prioritized singleton thread responsible for all chunk IO that occurs in a minecraft server. ++ * ++ *

++ * Singleton access: {@link Holder#INSTANCE} ++ *

++ * ++ *

++ * All functions provided are MT-Safe, however certain ordering constraints are (but not enforced): ++ *

  • ++ * Chunk saves may not occur for unloaded chunks. ++ *
  • ++ *
  • ++ * Tasks must be scheduled on the main thread. ++ *
  • ++ *

    ++ * ++ * @see Holder#INSTANCE ++ * @see #scheduleSave(ServerLevel, int, int, CompoundTag, CompoundTag, int) ++ * @see #loadChunkDataAsync(ServerLevel, int, int, int, Consumer, boolean, boolean, boolean) ++ */ ++public final class PaperFileIOThread extends QueueExecutorThread { ++ ++ public static final Logger LOGGER = MinecraftServer.LOGGER; ++ public static final CompoundTag FAILURE_VALUE = new CompoundTag(); ++ ++ public static final class Holder { ++ ++ public static final PaperFileIOThread INSTANCE = new PaperFileIOThread(); ++ ++ static { ++ INSTANCE.start(); ++ } ++ } ++ ++ private final AtomicLong writeCounter = new AtomicLong(); ++ ++ private PaperFileIOThread() { ++ super(new PrioritizedTaskQueue<>(), (int)(1.0e6)); // 1.0ms spinwait time ++ this.setName("Paper RegionFile IO Thread"); ++ this.setPriority(Thread.NORM_PRIORITY - 1); // we keep priority close to normal because threads can wait on us ++ this.setUncaughtExceptionHandler((final Thread unused, final Throwable thr) -> { ++ LOGGER.fatal("Uncaught exception thrown from IO thread, report this!", thr); ++ }); ++ } ++ ++ /* run() is implemented by superclass */ ++ ++ /* ++ * ++ * IO thread will perform reads before writes ++ * ++ * How reads/writes are scheduled: ++ * ++ * If read in progress while scheduling write, ignore read and schedule write ++ * If read in progress while scheduling read (no write in progress), chain the read task ++ * ++ * ++ * If write in progress while scheduling read, use the pending write data and ret immediately ++ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data ++ * ++ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however ++ * it fails to properly propagate write failures. When writes fail the data is kept so future reads will actually ++ * read the failed write data. This should hopefully act as a way to prevent data loss for spurious fails for writing data. ++ * ++ */ ++ ++ /** ++ * Attempts to bump the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. ++ * @param world Chunk's world ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority level to try to bump to ++ */ ++ public void bumpPriority(final ServerLevel world, final int chunkX, final int chunkZ, final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority: " + priority); ++ } ++ ++ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); ++ ++ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); ++ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); ++ ++ if (poiTask != null) { ++ poiTask.raisePriority(priority); ++ } ++ if (chunkTask != null) { ++ chunkTask.raisePriority(priority); ++ } ++ } ++ ++ public CompoundTag getPendingWrite(final ServerLevel world, final int chunkX, final int chunkZ, final boolean poiData) { ++ final ChunkDataController taskController = poiData ? world.poiDataController : world.chunkDataController; ++ ++ final ChunkDataTask dataTask = taskController.tasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); ++ ++ if (dataTask == null) { ++ return null; ++ } ++ ++ final ChunkDataController.InProgressWrite write = dataTask.inProgressWrite; ++ ++ if (write == null) { ++ return null; ++ } ++ ++ return write.data; ++ } ++ ++ /** ++ * Sets the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. ++ * @param world Chunk's world ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority level to set to ++ */ ++ public void setPriority(final ServerLevel world, final int chunkX, final int chunkZ, final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority: " + priority); ++ } ++ ++ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); ++ ++ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); ++ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); ++ ++ if (poiTask != null) { ++ poiTask.updatePriority(priority); ++ } ++ if (chunkTask != null) { ++ chunkTask.updatePriority(priority); ++ } ++ } ++ ++ /** ++ * Schedules the chunk data to be written asynchronously. ++ *

    ++ * Impl notes: ++ *

    ++ *
  • ++ * This function presumes a chunk load for the coordinates is not called during this function (anytime after is OK). This means ++ * saves must be scheduled before a chunk is unloaded. ++ *
  • ++ *
  • ++ * Writes may be called concurrently, although only the "later" write will go through. ++ *
  • ++ * @param world Chunk's world ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param poiData Chunk point of interest data. If {@code null}, then no poi data is saved. ++ * @param chunkData Chunk data. If {@code null}, then no chunk data is saved. ++ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} ++ * @throws IllegalArgumentException If both {@code poiData} and {@code chunkData} are {@code null}. ++ * @throws IllegalStateException If the file io thread has shutdown. ++ */ ++ public void scheduleSave(final ServerLevel world, final int chunkX, final int chunkZ, ++ final CompoundTag poiData, final CompoundTag chunkData, ++ final int priority) throws IllegalArgumentException { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority: " + priority); ++ } ++ ++ final long writeCounter = this.writeCounter.getAndIncrement(); ++ ++ if (poiData != null) { ++ this.scheduleWrite(world.poiDataController, world, chunkX, chunkZ, poiData, priority, writeCounter); ++ } ++ if (chunkData != null) { ++ this.scheduleWrite(world.chunkDataController, world, chunkX, chunkZ, chunkData, priority, writeCounter); ++ } ++ } ++ ++ private void scheduleWrite(final ChunkDataController dataController, final ServerLevel world, ++ final int chunkX, final int chunkZ, final CompoundTag data, final int priority, final long writeCounter) { ++ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask taskRunning) -> { ++ if (taskRunning == null) { ++ // no task is scheduled ++ ++ // create task ++ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); ++ newTask.inProgressWrite = new ChunkDataController.InProgressWrite(); ++ newTask.inProgressWrite.writeCounter = writeCounter; ++ newTask.inProgressWrite.data = data; ++ ++ PaperFileIOThread.this.queueTask(newTask); // schedule ++ return newTask; ++ } ++ ++ taskRunning.raisePriority(priority); ++ ++ if (taskRunning.inProgressWrite == null) { ++ taskRunning.inProgressWrite = new ChunkDataController.InProgressWrite(); ++ } ++ ++ boolean reschedule = taskRunning.inProgressWrite.writeCounter == -1L; ++ ++ // synchronize for readers ++ //noinspection SynchronizationOnLocalVariableOrMethodParameter ++ synchronized (taskRunning) { ++ taskRunning.inProgressWrite.data = data; ++ taskRunning.inProgressWrite.writeCounter = writeCounter; ++ } ++ ++ if (reschedule) { ++ // We need to reschedule this task since the previous one is not currently scheduled since it failed ++ taskRunning.reschedule(priority); ++ } ++ ++ return taskRunning; ++ }); ++ } ++ ++ /** ++ * Same as {@link #loadChunkDataAsync(ServerLevel, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns ++ * a {@link CompletableFuture} which is potentially completed ASYNCHRONOUSLY ON THE FILE IO THREAD when the load task ++ * has completed. ++ *

    ++ * Note that if the chunk fails to load the returned future is completed with {@code null}. ++ *

    ++ */ ++ public CompletableFuture loadChunkDataAsyncFuture(final ServerLevel world, final int chunkX, final int chunkZ, ++ final int priority, final boolean readPoiData, final boolean readChunkData, ++ final boolean intendingToBlock) { ++ final CompletableFuture future = new CompletableFuture<>(); ++ this.loadChunkDataAsync(world, chunkX, chunkZ, priority, future::complete, readPoiData, readChunkData, intendingToBlock); ++ return future; ++ } ++ ++ /** ++ * Schedules a load to be executed asynchronously. ++ *

    ++ * Impl notes: ++ *

    ++ *
  • ++ * If a chunk fails to load, the {@code onComplete} parameter is completed with {@code null}. ++ *
  • ++ *
  • ++ * It is possible for the {@code onComplete} parameter to be given {@link ChunkData} containing data ++ * this call did not request. ++ *
  • ++ *
  • ++ * The {@code onComplete} parameter may be completed during the execution of this function synchronously or it may ++ * be completed asynchronously on this file io thread. Interacting with the file IO thread in the completion of ++ * data is undefined behaviour, and can cause deadlock. ++ *
  • ++ * @param world Chunk's world ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} ++ * @param onComplete Consumer to execute once this task has completed ++ * @param readPoiData Whether to read point of interest data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. ++ * @param readChunkData Whether to read chunk data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. ++ * @return The {@link PrioritizedTaskQueue.PrioritizedTask} associated with this task. Note that this task does not support ++ * cancellation. ++ */ ++ public void loadChunkDataAsync(final ServerLevel world, final int chunkX, final int chunkZ, ++ final int priority, final Consumer onComplete, ++ final boolean readPoiData, final boolean readChunkData, ++ final boolean intendingToBlock) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority: " + priority); ++ } ++ ++ if (!(readPoiData | readChunkData)) { ++ throw new IllegalArgumentException("Must read chunk data or poi data"); ++ } ++ ++ final ChunkData complete = new ChunkData(); ++ final boolean[] requireCompletion = new boolean[] { readPoiData, readChunkData }; ++ ++ if (readPoiData) { ++ this.scheduleRead(world.poiDataController, world, chunkX, chunkZ, (final CompoundTag poiData) -> { ++ complete.poiData = poiData; ++ ++ final boolean finished; ++ ++ // avoid a race condition where the file io thread completes and we complete synchronously ++ // Note: Synchronization can be elided if both of the accesses are volatile ++ synchronized (requireCompletion) { ++ requireCompletion[0] = false; // 0 -> poi data ++ finished = !requireCompletion[1]; // 1 -> chunk data ++ } ++ ++ if (finished) { ++ onComplete.accept(complete); ++ } ++ }, priority, intendingToBlock); ++ } ++ ++ if (readChunkData) { ++ this.scheduleRead(world.chunkDataController, world, chunkX, chunkZ, (final CompoundTag chunkData) -> { ++ complete.chunkData = chunkData; ++ ++ final boolean finished; ++ ++ // avoid a race condition where the file io thread completes and we complete synchronously ++ // Note: Synchronization can be elided if both of the accesses are volatile ++ synchronized (requireCompletion) { ++ requireCompletion[1] = false; // 1 -> chunk data ++ finished = !requireCompletion[0]; // 0 -> poi data ++ } ++ ++ if (finished) { ++ onComplete.accept(complete); ++ } ++ }, priority, intendingToBlock); ++ } ++ ++ } ++ ++ // Note: the onComplete may be called asynchronously or synchronously here. ++ private void scheduleRead(final ChunkDataController dataController, final ServerLevel world, ++ final int chunkX, final int chunkZ, final Consumer onComplete, final int priority, ++ final boolean intendingToBlock) { ++ ++ Function tryLoadFunction = (final RegionFile file) -> { ++ if (file == null) { ++ return Boolean.TRUE; ++ } ++ return Boolean.valueOf(file.hasChunk(new ChunkPos(chunkX, chunkZ))); ++ }; ++ ++ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask running) -> { ++ if (running == null) { ++ // not scheduled ++ ++ final Boolean shouldSchedule = intendingToBlock ? dataController.computeForRegionFile(chunkX, chunkZ, tryLoadFunction) : ++ dataController.computeForRegionFileIfLoaded(chunkX, chunkZ, tryLoadFunction); ++ ++ if (shouldSchedule == Boolean.FALSE) { ++ // not on disk ++ onComplete.accept(null); ++ return null; ++ } ++ ++ // set up task ++ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); ++ newTask.inProgressRead = new ChunkDataController.InProgressRead(); ++ newTask.inProgressRead.readFuture.thenAccept(onComplete); ++ ++ PaperFileIOThread.this.queueTask(newTask); // schedule task ++ return newTask; ++ } ++ ++ running.raisePriority(priority); ++ ++ if (running.inProgressWrite == null) { ++ // chain to the read future ++ running.inProgressRead.readFuture.thenAccept(onComplete); ++ return running; ++ } ++ ++ // at this stage we have to use the in progress write's data to avoid an order issue ++ // we don't synchronize since all writes to data occur in the compute() call ++ onComplete.accept(running.inProgressWrite.data); ++ return running; ++ }); ++ } ++ ++ /** ++ * Same as {@link #loadChunkDataAsync(ServerLevel, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns ++ * the {@link ChunkData} associated with the specified chunk when the task is complete. ++ * @return The chunk data, or {@code null} if the chunk failed to load. ++ */ ++ public ChunkData loadChunkData(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, ++ final boolean readPoiData, final boolean readChunkData) { ++ return this.loadChunkDataAsyncFuture(world, chunkX, chunkZ, priority, readPoiData, readChunkData, true).join(); ++ } ++ ++ /** ++ * Schedules the given task at the specified priority to be executed on the IO thread. ++ *

    ++ * Internal api. Do not use. ++ *

    ++ */ ++ public void runTask(final int priority, final Runnable runnable) { ++ this.queueTask(new GeneralTask(priority, runnable)); ++ } ++ ++ static final class GeneralTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { ++ ++ private final Runnable run; ++ ++ public GeneralTask(final int priority, final Runnable run) { ++ super(priority); ++ this.run = IOUtil.notNull(run, "Task may not be null"); ++ } ++ ++ @Override ++ public void run() { ++ try { ++ this.run.run(); ++ } catch (final Throwable throwable) { ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath)throwable; ++ } ++ LOGGER.fatal("Failed to execute general task on IO thread " + IOUtil.genericToString(this.run), throwable); ++ } ++ } ++ } ++ ++ public static final class ChunkData { ++ ++ public CompoundTag poiData; ++ public CompoundTag chunkData; ++ ++ public ChunkData() {} ++ ++ public ChunkData(final CompoundTag poiData, final CompoundTag chunkData) { ++ this.poiData = poiData; ++ this.chunkData = chunkData; ++ } ++ } ++ ++ public static abstract class ChunkDataController { ++ ++ // ConcurrentHashMap synchronizes per chain, so reduce the chance of task's hashes colliding. ++ public final ConcurrentHashMap tasks = new ConcurrentHashMap<>(64, 0.5f); ++ ++ public abstract void writeData(final int x, final int z, final CompoundTag compound) throws IOException; ++ public abstract CompoundTag readData(final int x, final int z) throws IOException; ++ ++ public abstract T computeForRegionFile(final int chunkX, final int chunkZ, final Function function); ++ public abstract T computeForRegionFileIfLoaded(final int chunkX, final int chunkZ, final Function function); ++ ++ public static final class InProgressWrite { ++ public long writeCounter; ++ public CompoundTag data; ++ } ++ ++ public static final class InProgressRead { ++ public final CompletableFuture readFuture = new CompletableFuture<>(); ++ } ++ } ++ ++ public static final class ChunkDataTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { ++ ++ public ChunkDataController.InProgressWrite inProgressWrite; ++ public ChunkDataController.InProgressRead inProgressRead; ++ ++ private final ServerLevel world; ++ private final int x; ++ private final int z; ++ private final ChunkDataController taskController; ++ ++ public ChunkDataTask(final int priority, final ServerLevel world, final int x, final int z, final ChunkDataController taskController) { ++ super(priority); ++ this.world = world; ++ this.x = x; ++ this.z = z; ++ this.taskController = taskController; ++ } ++ ++ @Override ++ public String toString() { ++ return "Task for world: '" + this.world.getWorld().getName() + "' at " + this.x + "," + this.z + ++ " poi: " + (this.taskController == this.world.poiDataController) + ", hash: " + this.hashCode(); ++ } ++ ++ /* ++ * ++ * IO thread will perform reads before writes ++ * ++ * How reads/writes are scheduled: ++ * ++ * If read in progress while scheduling write, ignore read and schedule write ++ * If read in progress while scheduling read (no write in progress), chain the read task ++ * ++ * ++ * If write in progress while scheduling read, use the pending write data and ret immediately ++ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data ++ * ++ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however ++ * it fails to properly propagate write failures ++ * ++ */ ++ ++ void reschedule(final int priority) { ++ // priority is checked before this stage // TODO what ++ this.queue.lazySet(null); ++ this.priority.lazySet(priority); ++ PaperFileIOThread.Holder.INSTANCE.queueTask(this); ++ } ++ ++ @Override ++ public void run() { ++ ChunkDataController.InProgressRead read = this.inProgressRead; ++ if (read != null) { ++ CompoundTag compound = PaperFileIOThread.FAILURE_VALUE; ++ try { ++ compound = this.taskController.readData(this.x, this.z); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ LOGGER.fatal("Failed to read chunk data for task: " + this.toString(), thr); ++ // fall through to complete with null data ++ } ++ read.readFuture.complete(compound); ++ } ++ ++ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(this.x, this.z)); ++ ++ ChunkDataController.InProgressWrite write = this.inProgressWrite; ++ ++ if (write == null) { ++ // IntelliJ warns this is invalid, however it does not consider that writes to the task map & the inProgress field can occur concurrently. ++ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { ++ if (valueInMap == null) { ++ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); ++ } ++ if (valueInMap != ChunkDataTask.this) { ++ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); ++ } ++ return valueInMap.inProgressWrite == null ? null : valueInMap; ++ }); ++ ++ if (inMap == null) { ++ return; // set the task value to null, indicating we're done ++ } ++ ++ // not null, which means there was a concurrent write ++ write = this.inProgressWrite; ++ } ++ ++ // check if another process is writing ++ /*try { TODO: Can we restore this? ++ ((WorldServer)this.world).checkSession(); ++ } catch (final Exception ex) { ++ LOGGER.fatal("Couldn't save chunk; already in use by another instance of Minecraft?", ex); ++ // we don't need to set the write counter to -1 as we know at this stage there's no point in re-scheduling ++ // writes since they'll fail anyways. ++ return; ++ } ++*/ ++ for (;;) { ++ final long writeCounter; ++ final CompoundTag data; ++ ++ //noinspection SynchronizationOnLocalVariableOrMethodParameter ++ synchronized (write) { ++ writeCounter = write.writeCounter; ++ data = write.data; ++ } ++ ++ boolean failedWrite = false; ++ ++ try { ++ this.taskController.writeData(this.x, this.z, data); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ LOGGER.fatal("Failed to write chunk data for task: " + this.toString(), thr); ++ failedWrite = true; ++ } ++ ++ boolean finalFailWrite = failedWrite; ++ ++ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { ++ if (valueInMap == null) { ++ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); ++ } ++ if (valueInMap != ChunkDataTask.this) { ++ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); ++ } ++ if (valueInMap.inProgressWrite.writeCounter == writeCounter) { ++ if (finalFailWrite) { ++ valueInMap.inProgressWrite.writeCounter = -1L; ++ } ++ ++ return null; ++ } ++ return valueInMap; ++ // Hack end ++ }); ++ ++ if (inMap == null) { ++ // write counter matched, so we wrote the most up-to-date pending data, we're done here ++ // or we failed to write and successfully set the write counter to -1 ++ return; // we're done here ++ } ++ ++ // fetch & write new data ++ continue; ++ } ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java +new file mode 100644 +index 0000000000000000000000000000000000000000..97f2e433c483f1ebd7500ae142269e144ef5fda4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java +@@ -0,0 +1,277 @@ ++package com.destroystokyo.paper.io; ++ ++import java.util.concurrent.ConcurrentLinkedQueue; ++import java.util.concurrent.atomic.AtomicBoolean; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.concurrent.atomic.AtomicReference; ++ ++public class PrioritizedTaskQueue { ++ ++ // lower numbers are a higher priority (except < 0) ++ // higher priorities are always executed before lower priorities ++ ++ /** ++ * Priority value indicating the task has completed or is being completed. ++ */ ++ public static final int COMPLETING_PRIORITY = -1; ++ ++ /** ++ * Highest priority, should only be used for main thread tasks or tasks that are blocking the main thread. ++ */ ++ public static final int HIGHEST_PRIORITY = 0; ++ ++ /** ++ * Should be only used in an IO task so that chunk loads do not wait on other IO tasks. ++ * This only exists because IO tasks are scheduled before chunk load tasks to decrease IO waiting times. ++ */ ++ public static final int HIGHER_PRIORITY = 1; ++ ++ /** ++ * Should be used for scheduling chunk loads/generation that would increase response times to users. ++ */ ++ public static final int HIGH_PRIORITY = 2; ++ ++ /** ++ * Default priority. ++ */ ++ public static final int NORMAL_PRIORITY = 3; ++ ++ /** ++ * Use for tasks not at all critical and can potentially be delayed. ++ */ ++ public static final int LOW_PRIORITY = 4; ++ ++ /** ++ * Use for tasks that should "eventually" execute. ++ */ ++ public static final int LOWEST_PRIORITY = 5; ++ ++ private static final int TOTAL_PRIORITIES = 6; ++ ++ final ConcurrentLinkedQueue[] queues = (ConcurrentLinkedQueue[])new ConcurrentLinkedQueue[TOTAL_PRIORITIES]; ++ ++ private final AtomicBoolean shutdown = new AtomicBoolean(); ++ ++ { ++ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { ++ this.queues[i] = new ConcurrentLinkedQueue<>(); ++ } ++ } ++ ++ /** ++ * Returns whether the specified priority is valid ++ */ ++ public static boolean validPriority(final int priority) { ++ return priority >= 0 && priority < TOTAL_PRIORITIES; ++ } ++ ++ /** ++ * Queues a task. ++ * @throws IllegalStateException If the task has already been queued. Use {@link PrioritizedTask#raisePriority(int)} to ++ * raise a task's priority. ++ * This can also be thrown if the queue has shutdown. ++ */ ++ public void add(final T task) throws IllegalStateException { ++ int priority = task.getPriority(); ++ if (priority != COMPLETING_PRIORITY) { ++ task.setQueue(this); ++ this.queues[priority].add(task); ++ } ++ if (this.shutdown.get()) { ++ // note: we're not actually sure at this point if our task will go through ++ throw new IllegalStateException("Queue has shutdown, refusing to execute task " + IOUtil.genericToString(task)); ++ } ++ } ++ ++ /** ++ * Polls the highest priority task currently available. {@code null} if none. ++ */ ++ public T poll() { ++ T task; ++ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { ++ final ConcurrentLinkedQueue queue = this.queues[i]; ++ ++ while ((task = queue.poll()) != null) { ++ final int prevPriority = task.tryComplete(i); ++ if (prevPriority != COMPLETING_PRIORITY && prevPriority <= i) { ++ // if the prev priority was greater-than or equal to our current priority ++ return task; ++ } ++ } ++ } ++ ++ return null; ++ } ++ ++ /** ++ * Returns whether this queue may have tasks queued. ++ *

    ++ * This operation is not atomic, but is MT-Safe. ++ *

    ++ * @return {@code true} if tasks may be queued, {@code false} otherwise ++ */ ++ public boolean hasTasks() { ++ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { ++ final ConcurrentLinkedQueue queue = this.queues[i]; ++ ++ if (queue.peek() != null) { ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ /** ++ * Prevent further additions to this queue. Attempts to add after this call has completed (potentially during) will ++ * result in {@link IllegalStateException} being thrown. ++ *

    ++ * This operation is atomic with respect to other shutdown calls ++ *

    ++ *

    ++ * After this call has completed, regardless of return value, this queue will be shutdown. ++ *

    ++ * @return {@code true} if the queue was shutdown, {@code false} if it has shut down already ++ */ ++ public boolean shutdown() { ++ return this.shutdown.getAndSet(false); ++ } ++ ++ public abstract static class PrioritizedTask { ++ ++ protected final AtomicReference queue = new AtomicReference<>(); ++ ++ protected final AtomicInteger priority; ++ ++ protected PrioritizedTask() { ++ this(PrioritizedTaskQueue.NORMAL_PRIORITY); ++ } ++ ++ protected PrioritizedTask(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority " + priority); ++ } ++ this.priority = new AtomicInteger(priority); ++ } ++ ++ /** ++ * Returns the current priority. Note that {@link PrioritizedTaskQueue#COMPLETING_PRIORITY} will be returned ++ * if this task is completing or has completed. ++ */ ++ public final int getPriority() { ++ return this.priority.get(); ++ } ++ ++ /** ++ * Returns whether this task is scheduled to execute, or has been already executed. ++ */ ++ public boolean isScheduled() { ++ return this.queue.get() != null; ++ } ++ ++ final int tryComplete(final int minPriority) { ++ for (int curr = this.getPriorityVolatile();;) { ++ if (curr == COMPLETING_PRIORITY) { ++ return COMPLETING_PRIORITY; ++ } ++ if (curr > minPriority) { ++ // curr is lower priority ++ return curr; ++ } ++ ++ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, COMPLETING_PRIORITY))) { ++ return curr; ++ } ++ continue; ++ } ++ } ++ ++ /** ++ * Forces this task to be completed. ++ * @return {@code true} if the task was cancelled, {@code false} if the task has already completed or is being completed. ++ */ ++ public boolean cancel() { ++ return this.exchangePriorityVolatile(PrioritizedTaskQueue.COMPLETING_PRIORITY) != PrioritizedTaskQueue.COMPLETING_PRIORITY; ++ } ++ ++ /** ++ * Attempts to raise the priority to the priority level specified. ++ * @param priority Priority specified ++ * @return {@code true} if successful, {@code false} otherwise. ++ */ ++ public boolean raisePriority(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority"); ++ } ++ ++ for (int curr = this.getPriorityVolatile();;) { ++ if (curr == COMPLETING_PRIORITY) { ++ return false; ++ } ++ if (priority >= curr) { ++ return true; ++ } ++ ++ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { ++ PrioritizedTaskQueue queue = this.queue.get(); ++ if (queue != null) { ++ //noinspection unchecked ++ queue.queues[priority].add(this); // silently fail on shutdown ++ } ++ return true; ++ } ++ continue; ++ } ++ } ++ ++ /** ++ * Attempts to set this task's priority level to the level specified. ++ * @param priority Specified priority level. ++ * @return {@code true} if successful, {@code false} if this task is completing or has completed. ++ */ ++ public boolean updatePriority(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority"); ++ } ++ ++ for (int curr = this.getPriorityVolatile();;) { ++ if (curr == COMPLETING_PRIORITY) { ++ return false; ++ } ++ if (curr == priority) { ++ return true; ++ } ++ ++ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { ++ PrioritizedTaskQueue queue = this.queue.get(); ++ if (queue != null) { ++ //noinspection unchecked ++ queue.queues[priority].add(this); // silently fail on shutdown ++ } ++ return true; ++ } ++ continue; ++ } ++ } ++ ++ void setQueue(final PrioritizedTaskQueue queue) { ++ this.queue.set(queue); ++ } ++ ++ /* priority */ ++ ++ protected final int getPriorityVolatile() { ++ return this.priority.get(); ++ } ++ ++ protected final int compareAndExchangePriorityVolatile(final int expect, final int update) { ++ if (this.priority.compareAndSet(expect, update)) { ++ return expect; ++ } ++ return this.priority.get(); ++ } ++ ++ protected final int exchangePriorityVolatile(final int value) { ++ return this.priority.getAndSet(value); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ee906b594b306906c170180a29a8b61997d05168 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java +@@ -0,0 +1,241 @@ ++package com.destroystokyo.paper.io; ++ ++import net.minecraft.server.MinecraftServer; ++import org.apache.logging.log4j.Logger; ++ ++import java.util.concurrent.ConcurrentLinkedQueue; ++import java.util.concurrent.atomic.AtomicBoolean; ++import java.util.concurrent.locks.LockSupport; ++ ++public class QueueExecutorThread extends Thread { ++ ++ private static final Logger LOGGER = MinecraftServer.LOGGER; ++ ++ protected final PrioritizedTaskQueue queue; ++ protected final long spinWaitTime; ++ ++ protected volatile boolean closed; ++ ++ protected final AtomicBoolean parked = new AtomicBoolean(); ++ ++ protected volatile ConcurrentLinkedQueue flushQueue = new ConcurrentLinkedQueue<>(); ++ protected volatile long flushCycles; ++ ++ public QueueExecutorThread(final PrioritizedTaskQueue queue) { ++ this(queue, (int)(1.e6)); // 1.0ms ++ } ++ ++ public QueueExecutorThread(final PrioritizedTaskQueue queue, final long spinWaitTime) { // in ms ++ this.queue = queue; ++ this.spinWaitTime = spinWaitTime; ++ } ++ ++ @Override ++ public void run() { ++ final long spinWaitTime = this.spinWaitTime; ++ main_loop: ++ for (;;) { ++ this.pollTasks(true); ++ ++ // spinwait ++ ++ final long start = System.nanoTime(); ++ ++ for (;;) { ++ // If we are interrpted for any reason, park() will always return immediately. Clear so that we don't needlessly use cpu in such an event. ++ Thread.interrupted(); ++ LockSupport.parkNanos("Spinwaiting on tasks", 1000L); // 1us ++ ++ if (this.pollTasks(true)) { ++ // restart loop, found tasks ++ continue main_loop; ++ } ++ ++ if (this.handleClose()) { ++ return; // we're done ++ } ++ ++ if ((System.nanoTime() - start) >= spinWaitTime) { ++ break; ++ } ++ } ++ ++ if (this.handleClose()) { ++ return; ++ } ++ ++ this.parked.set(true); ++ ++ // We need to parse here to avoid a race condition where a thread queues a task before we set parked to true ++ // (i.e it will not notify us) ++ if (this.pollTasks(true)) { ++ this.parked.set(false); ++ continue; ++ } ++ ++ if (this.handleClose()) { ++ return; ++ } ++ ++ // we don't need to check parked before sleeping, but we do need to check parked in a do-while loop ++ // LockSupport.park() can fail for any reason ++ do { ++ Thread.interrupted(); ++ LockSupport.park("Waiting on tasks"); ++ } while (this.parked.get()); ++ } ++ } ++ ++ protected boolean handleClose() { ++ if (this.closed) { ++ this.pollTasks(true); // this ensures we've emptied the queue ++ this.handleFlushThreads(true); ++ return true; ++ } ++ return false; ++ } ++ ++ protected boolean pollTasks(boolean flushTasks) { ++ Runnable task; ++ boolean ret = false; ++ ++ while ((task = this.queue.poll()) != null) { ++ ret = true; ++ try { ++ task.run(); ++ } catch (final Throwable throwable) { ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath)throwable; ++ } ++ LOGGER.fatal("Exception thrown from prioritized runnable task in thread '" + this.getName() + "': " + IOUtil.genericToString(task), throwable); ++ } ++ } ++ ++ if (flushTasks) { ++ this.handleFlushThreads(false); ++ } ++ ++ return ret; ++ } ++ ++ protected void handleFlushThreads(final boolean shutdown) { ++ Thread parking; ++ ConcurrentLinkedQueue flushQueue = this.flushQueue; ++ do { ++ ++flushCycles; // may be plain read opaque write ++ while ((parking = flushQueue.poll()) != null) { ++ LockSupport.unpark(parking); ++ } ++ } while (this.pollTasks(false)); ++ ++ if (shutdown) { ++ this.flushQueue = null; ++ ++ // defend against a race condition where a flush thread double-checks right before we set to null ++ while ((parking = flushQueue.poll()) != null) { ++ LockSupport.unpark(parking); ++ } ++ } ++ } ++ ++ /** ++ * Notify's this thread that a task has been added to its queue ++ * @return {@code true} if this thread was waiting for tasks, {@code false} if it is executing tasks ++ */ ++ public boolean notifyTasks() { ++ if (this.parked.get() && this.parked.getAndSet(false)) { ++ LockSupport.unpark(this); ++ return true; ++ } ++ return false; ++ } ++ ++ protected void queueTask(final T task) { ++ this.queue.add(task); ++ this.notifyTasks(); ++ } ++ ++ /** ++ * Waits until this thread's queue is empty. ++ * ++ * @throws IllegalStateException If the current thread is {@code this} thread. ++ */ ++ public void flush() { ++ final Thread currentThread = Thread.currentThread(); ++ ++ if (currentThread == this) { ++ // avoid deadlock ++ throw new IllegalStateException("Cannot flush the queue executor thread while on the queue executor thread"); ++ } ++ ++ // order is important ++ ++ int successes = 0; ++ long lastCycle = -1L; ++ ++ do { ++ final ConcurrentLinkedQueue flushQueue = this.flushQueue; ++ if (flushQueue == null) { ++ return; ++ } ++ ++ flushQueue.add(currentThread); ++ ++ // double check flush queue ++ if (this.flushQueue == null) { ++ return; ++ } ++ ++ final long currentCycle = this.flushCycles; // may be opaque read ++ ++ if (currentCycle == lastCycle) { ++ Thread.yield(); ++ continue; ++ } ++ ++ // force response ++ this.parked.set(false); ++ LockSupport.unpark(this); ++ ++ LockSupport.park("flushing queue executor thread"); ++ ++ // returns whether there are tasks queued, does not return whether there are tasks executing ++ // this is why we cycle twice twice through flush (we know a pollTask call is made after a flush cycle) ++ // we really only need to guarantee that the tasks this thread has queued has gone through, and can leave ++ // tasks queued concurrently that are unsychronized with this thread as undefined behavior ++ if (this.queue.hasTasks()) { ++ successes = 0; ++ } else { ++ ++successes; ++ } ++ ++ } while (successes != 2); ++ ++ } ++ ++ /** ++ * Closes this queue executor's queue and optionally waits for it to empty. ++ *

    ++ * If wait is {@code true}, then the queue will be empty by the time this call completes. ++ *

    ++ *

    ++ * This function is MT-Safe. ++ *

    ++ * @param wait If this call is to wait until the queue is empty ++ * @param killQueue Whether to shutdown this thread's queue ++ * @return whether this thread shut down the queue ++ */ ++ public boolean close(final boolean wait, final boolean killQueue) { ++ boolean ret = !killQueue ? false : this.queue.shutdown(); ++ this.closed = true; ++ ++ // force thread to respond to the shutdown ++ this.parked.set(false); ++ LockSupport.unpark(this); ++ ++ if (wait) { ++ this.flush(); ++ } ++ return ret; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java +new file mode 100644 +index 0000000000000000000000000000000000000000..26a5da48c87674f320aa9f7382217cde2c93e08c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java +@@ -0,0 +1,145 @@ ++package com.destroystokyo.paper.io.chunk; ++ ++import co.aikar.timings.Timing; ++import com.destroystokyo.paper.io.PaperFileIOThread; ++import com.destroystokyo.paper.io.IOUtil; ++import java.util.ArrayDeque; ++import java.util.function.Consumer; ++import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.chunk.storage.ChunkSerializer; ++ ++public final class ChunkLoadTask extends ChunkTask { ++ ++ public boolean cancelled; ++ ++ Consumer onComplete; ++ public PaperFileIOThread.ChunkData chunkData; ++ ++ private boolean hasCompleted; ++ ++ public ChunkLoadTask(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, ++ final ChunkTaskManager taskManager, ++ final Consumer onComplete) { ++ super(world, chunkX, chunkZ, priority, taskManager); ++ this.onComplete = onComplete; ++ } ++ ++ private static final ArrayDeque EMPTY_QUEUE = new ArrayDeque<>(); ++ ++ private static ChunkSerializer.InProgressChunkHolder createEmptyHolder() { ++ return new ChunkSerializer.InProgressChunkHolder(null, EMPTY_QUEUE); ++ } ++ ++ @Override ++ public void run() { ++ try { ++ this.executeTask(); ++ } catch (final Throwable ex) { ++ PaperFileIOThread.LOGGER.error("Failed to execute chunk load task: " + this.toString(), ex); ++ if (!this.hasCompleted) { ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ } ++ } ++ } ++ ++ private boolean checkCancelled() { ++ if (this.cancelled) { ++ // IntelliJ does not understand writes may occur to cancelled concurrently. ++ return this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap != ChunkLoadTask.this) { ++ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); ++ } ++ ++ if (valueInMap.cancelled) { ++ return null; ++ } ++ return valueInMap; ++ }) == null; ++ } ++ return false; ++ } ++ ++ public void executeTask() { ++ if (this.checkCancelled()) { ++ return; ++ } ++ ++ // either executed synchronously or asynchronously ++ final PaperFileIOThread.ChunkData chunkData = this.chunkData; ++ ++ if (chunkData.poiData == PaperFileIOThread.FAILURE_VALUE || chunkData.chunkData == PaperFileIOThread.FAILURE_VALUE) { ++ PaperFileIOThread.LOGGER.error("Could not load chunk for task: " + this.toString() + ", file IO thread has dumped the relevant exception above"); ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ return; ++ } ++ ++ if (chunkData.chunkData == null) { ++ // not on disk ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ return; ++ } ++ ++ final ChunkPos chunkPos = new ChunkPos(this.chunkX, this.chunkZ); ++ ++ final ChunkMap chunkManager = this.world.getChunkSource().chunkMap; ++ ++ try (Timing ignored = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { ++ final ChunkSerializer.InProgressChunkHolder chunkHolder; ++ ++ // apply fixes ++ ++ try { ++ chunkData.chunkData = chunkManager.getChunkData(this.world.getTypeKey(), ++ chunkManager.getWorldPersistentDataSupplier(), chunkData.chunkData, chunkPos, this.world); // clone data for safety, file IO thread does not clone ++ } catch (final Throwable ex) { ++ PaperFileIOThread.LOGGER.error("Could not apply datafixers for chunk task: " + this.toString(), ex); ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ } ++ ++ if (this.checkCancelled()) { ++ return; ++ } ++ ++ try { ++ this.world.getChunkSource().chunkMap.updateChunkStatusOnDisk(chunkPos, chunkData.chunkData); ++ } catch (final Throwable ex) { ++ PaperFileIOThread.LOGGER.warn("Failed to update chunk status cache for task: " + this.toString(), ex); ++ // non-fatal, continue ++ } ++ ++ try { ++ chunkHolder = ChunkSerializer.loadChunk(this.world, ++ chunkManager.structureManager, chunkManager.getVillagePlace(), chunkPos, ++ chunkData.chunkData, true); ++ } catch (final Throwable ex) { ++ PaperFileIOThread.LOGGER.error("Could not de-serialize chunk data for task: " + this.toString(), ex); ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ return; ++ } ++ ++ this.complete(chunkHolder); ++ } ++ } ++ ++ private void complete(final ChunkSerializer.InProgressChunkHolder holder) { ++ this.hasCompleted = true; ++ holder.poiData = this.chunkData == null ? null : this.chunkData.poiData; ++ ++ this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap != ChunkLoadTask.this) { ++ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); ++ } ++ if (valueInMap.cancelled) { ++ return null; ++ } ++ try { ++ ChunkLoadTask.this.onComplete.accept(holder); ++ } catch (final Throwable thr) { ++ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); ++ } ++ return null; ++ }); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java +new file mode 100644 +index 0000000000000000000000000000000000000000..69ebbfa171385c46a84d1a0d241d168a8c2af145 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java +@@ -0,0 +1,111 @@ ++package com.destroystokyo.paper.io.chunk; ++ ++import co.aikar.timings.Timing; ++import com.destroystokyo.paper.io.PaperFileIOThread; ++import com.destroystokyo.paper.io.IOUtil; ++import com.destroystokyo.paper.io.PrioritizedTaskQueue; ++ ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.atomic.AtomicInteger; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.storage.ChunkSerializer; ++ ++public final class ChunkSaveTask extends ChunkTask { ++ ++ public final ChunkSerializer.AsyncSaveData asyncSaveData; ++ public final ChunkAccess chunk; ++ public final CompletableFuture onComplete = new CompletableFuture<>(); ++ ++ private final AtomicInteger attemptedPriority; ++ ++ public ChunkSaveTask(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, ++ final ChunkTaskManager taskManager, final ChunkSerializer.AsyncSaveData asyncSaveData, ++ final ChunkAccess chunk) { ++ super(world, chunkX, chunkZ, priority, taskManager); ++ this.chunk = chunk; ++ this.asyncSaveData = asyncSaveData; ++ this.attemptedPriority = new AtomicInteger(priority); ++ } ++ ++ @Override ++ public void run() { ++ // can be executed asynchronously or synchronously ++ final CompoundTag compound; ++ ++ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTimingIfSync()) { ++ compound = ChunkSerializer.saveChunk(this.world, this.chunk, this.asyncSaveData); ++ } catch (final Throwable ex) { ++ // has a plugin modified something it should not have and made us CME? ++ PaperFileIOThread.LOGGER.error("Failed to serialize unloading chunk data for task: " + this.toString() + ", falling back to a synchronous execution", ex); ++ ++ // Note: We add to the server thread queue here since this is what the server will drain tasks from ++ // when waiting for chunks ++ ChunkTaskManager.queueChunkWaitTask(() -> { ++ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTiming()) { ++ CompoundTag data = PaperFileIOThread.FAILURE_VALUE; ++ ++ try { ++ data = ChunkSerializer.saveChunk(this.world, this.chunk, this.asyncSaveData); ++ PaperFileIOThread.LOGGER.info("Successfully serialized chunk data for task: " + this.toString() + " synchronously"); ++ } catch (final Throwable ex1) { ++ PaperFileIOThread.LOGGER.fatal("Failed to synchronously serialize unloading chunk data for task: " + this.toString() + "! Chunk data will be lost", ex1); ++ } ++ ++ ChunkSaveTask.this.complete(data); ++ } ++ }); ++ ++ return; // the main thread will now complete the data ++ } ++ ++ this.complete(compound); ++ } ++ ++ @Override ++ public boolean raisePriority(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalStateException("Invalid priority: " + priority); ++ } ++ ++ // we know priority is valid here ++ for (int curr = this.attemptedPriority.get();;) { ++ if (curr <= priority) { ++ break; // curr is higher/same priority ++ } ++ if (this.attemptedPriority.compareAndSet(curr, priority)) { ++ break; ++ } ++ curr = this.attemptedPriority.get(); ++ } ++ ++ return super.raisePriority(priority); ++ } ++ ++ @Override ++ public boolean updatePriority(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalStateException("Invalid priority: " + priority); ++ } ++ this.attemptedPriority.set(priority); ++ return super.updatePriority(priority); ++ } ++ ++ private void complete(final CompoundTag compound) { ++ try { ++ this.onComplete.complete(compound); ++ } catch (final Throwable thr) { ++ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); ++ } ++ if (compound != PaperFileIOThread.FAILURE_VALUE) { ++ PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, this.chunkX, this.chunkZ, null, compound, this.attemptedPriority.get()); ++ } ++ this.taskManager.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { ++ if (valueInMap != ChunkSaveTask.this) { ++ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", this: " + ChunkSaveTask.this); ++ } ++ return null; ++ }); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java +new file mode 100644 +index 0000000000000000000000000000000000000000..058fb5a41565e6ce2acbd1f4d071a1b8be449f5d +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java +@@ -0,0 +1,40 @@ ++package com.destroystokyo.paper.io.chunk; ++ ++import com.destroystokyo.paper.io.PaperFileIOThread; ++import com.destroystokyo.paper.io.PrioritizedTaskQueue; ++import net.minecraft.server.level.ServerLevel; ++ ++abstract class ChunkTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { ++ ++ public final ServerLevel world; ++ public final int chunkX; ++ public final int chunkZ; ++ public final ChunkTaskManager taskManager; ++ ++ public ChunkTask(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, ++ final ChunkTaskManager taskManager) { ++ super(priority); ++ this.world = world; ++ this.chunkX = chunkX; ++ this.chunkZ = chunkZ; ++ this.taskManager = taskManager; ++ } ++ ++ @Override ++ public String toString() { ++ return "Chunk task: class:" + this.getClass().getName() + ", for world '" + this.world.getWorld().getName() + ++ "', (" + this.chunkX + "," + this.chunkZ + "), hashcode:" + this.hashCode() + ", priority: " + this.getPriority(); ++ } ++ ++ @Override ++ public boolean raisePriority(final int priority) { ++ PaperFileIOThread.Holder.INSTANCE.bumpPriority(this.world, this.chunkX, this.chunkZ, priority); ++ return super.raisePriority(priority); ++ } ++ ++ @Override ++ public boolean updatePriority(final int priority) { ++ PaperFileIOThread.Holder.INSTANCE.setPriority(this.world, this.chunkX, this.chunkZ, priority); ++ return super.updatePriority(priority); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..499aff1f1e1ffc01ba8f9de43ca17899525a306f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +@@ -0,0 +1,513 @@ ++package com.destroystokyo.paper.io.chunk; ++ ++import com.destroystokyo.paper.io.PaperFileIOThread; ++import com.destroystokyo.paper.io.IOUtil; ++import com.destroystokyo.paper.io.PrioritizedTaskQueue; ++import com.destroystokyo.paper.io.QueueExecutorThread; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.util.thread.BlockableEventLoop; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.chunk.storage.ChunkSerializer; ++import org.apache.commons.lang.StringUtils; ++import org.apache.logging.log4j.Level; ++import org.bukkit.Bukkit; ++import org.spigotmc.AsyncCatcher; ++ ++import java.util.ArrayDeque; ++import java.util.HashSet; ++import java.util.Set; ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.ConcurrentLinkedQueue; ++import java.util.function.Consumer; ++ ++public final class ChunkTaskManager { ++ ++ private final QueueExecutorThread[] workers; ++ private final ServerLevel world; ++ ++ private final PrioritizedTaskQueue queue; ++ private final boolean perWorldQueue; ++ ++ final ConcurrentHashMap chunkLoadTasks = new ConcurrentHashMap<>(64, 0.5f); ++ final ConcurrentHashMap chunkSaveTasks = new ConcurrentHashMap<>(64, 0.5f); ++ ++ private final PrioritizedTaskQueue chunkTasks = new PrioritizedTaskQueue<>(); // used if async chunks are disabled in config ++ ++ protected static QueueExecutorThread[] globalWorkers; ++ protected static QueueExecutorThread globalUrgentWorker; ++ protected static PrioritizedTaskQueue globalQueue; ++ protected static PrioritizedTaskQueue globalUrgentQueue; ++ ++ protected static final ConcurrentLinkedQueue CHUNK_WAIT_QUEUE = new ConcurrentLinkedQueue<>(); ++ ++ public static final ArrayDeque WAITING_CHUNKS = new ArrayDeque<>(); // stack ++ ++ private static final class ChunkInfo { ++ ++ public final int chunkX; ++ public final int chunkZ; ++ public final ServerLevel world; ++ ++ public ChunkInfo(final int chunkX, final int chunkZ, final ServerLevel world) { ++ this.chunkX = chunkX; ++ this.chunkZ = chunkZ; ++ this.world = world; ++ } ++ ++ @Override ++ public String toString() { ++ return "[( " + this.chunkX + "," + this.chunkZ + ") in '" + this.world.getWorld().getName() + "']"; ++ } ++ } ++ ++ public static void pushChunkWait(final ServerLevel world, final int chunkX, final int chunkZ) { ++ synchronized (WAITING_CHUNKS) { ++ WAITING_CHUNKS.push(new ChunkInfo(chunkX, chunkZ, world)); ++ } ++ } ++ ++ public static void popChunkWait() { ++ synchronized (WAITING_CHUNKS) { ++ WAITING_CHUNKS.pop(); ++ } ++ } ++ ++ private static ChunkInfo[] getChunkInfos() { ++ ChunkInfo[] chunks; ++ synchronized (WAITING_CHUNKS) { ++ chunks = WAITING_CHUNKS.toArray(new ChunkInfo[0]); ++ } ++ return chunks; ++ } ++ ++ public static void dumpAllChunkLoadInfo() { ++ ChunkInfo[] chunks = getChunkInfos(); ++ if (chunks.length > 0) { ++ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk wait task info below: "); ++ ++ for (final ChunkInfo chunkInfo : chunks) { ++ final long key = IOUtil.getCoordinateKey(chunkInfo.chunkX, chunkInfo.chunkZ); ++ final ChunkLoadTask loadTask = chunkInfo.world.asyncChunkTaskManager.chunkLoadTasks.get(key); ++ final ChunkSaveTask saveTask = chunkInfo.world.asyncChunkTaskManager.chunkSaveTasks.get(key); ++ ++ PaperFileIOThread.LOGGER.log(Level.ERROR, chunkInfo.chunkX + "," + chunkInfo.chunkZ + " in '" + chunkInfo.world.getWorld().getName() + ":"); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, "Load Task - " + (loadTask == null ? "none" : loadTask.toString())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, "Save Task - " + (saveTask == null ? "none" : saveTask.toString())); ++ // log current status of chunk to indicate whether we're waiting on generation or loading ++ ChunkHolder chunkHolder = chunkInfo.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(key); ++ ++ dumpChunkInfo(new HashSet<>(), chunkHolder, chunkInfo.chunkX, chunkInfo.chunkZ); ++ } ++ } ++ } ++ ++ static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z) { ++ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); ++ } ++ ++ static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z, int indent, int maxDepth) { ++ if (seenChunks.contains(chunkHolder)) { ++ return; ++ } ++ if (indent > maxDepth) { ++ return; ++ } ++ seenChunks.add(chunkHolder); ++ String indentStr = StringUtils.repeat(" ", indent); ++ if (chunkHolder == null) { ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - null for (" + x +"," + z +")"); ++ } else { ++ ChunkAccess chunk = chunkHolder.getAvailableChunkNow(); ++ ChunkStatus holderStatus = chunkHolder.getChunkHolderStatus(); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - non-null"); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); ++ } ++ } ++ ++ public static void initGlobalLoadThreads(int threads) { ++ if (threads <= 0 || globalWorkers != null) { ++ return; ++ } ++ ++ globalWorkers = new QueueExecutorThread[threads]; ++ globalQueue = new PrioritizedTaskQueue<>(); ++ globalUrgentQueue = new PrioritizedTaskQueue<>(); ++ ++ for (int i = 0; i < threads; ++i) { ++ globalWorkers[i] = new QueueExecutorThread<>(globalQueue, (long)0.10e6); //0.1ms ++ globalWorkers[i].setName("Paper Async Chunk Task Thread #" + i); ++ globalWorkers[i].setPriority(Thread.NORM_PRIORITY - 1); ++ globalWorkers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { ++ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); ++ }); ++ ++ globalWorkers[i].start(); ++ } ++ ++ globalUrgentWorker = new QueueExecutorThread<>(globalUrgentQueue, (long)0.10e6); //0.1ms ++ globalUrgentWorker.setName("Paper Async Chunk Urgent Task Thread"); ++ globalUrgentWorker.setPriority(Thread.NORM_PRIORITY+1); ++ globalUrgentWorker.setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { ++ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); ++ }); ++ ++ globalUrgentWorker.start(); ++ } ++ ++ /** ++ * Creates this chunk task manager to operate off the specified number of threads. If the specified number of threads is ++ * less-than or equal to 0, then this chunk task manager will operate off of the world's chunk task queue. ++ * @param world Specified world. ++ * @param threads Specified number of threads. ++ * @see ServerChunkCache#mainThreadProcessor ++ */ ++ public ChunkTaskManager(final ServerLevel world, final int threads) { ++ this.world = world; ++ this.workers = threads <= 0 ? null : new QueueExecutorThread[threads]; ++ this.queue = new PrioritizedTaskQueue<>(); ++ this.perWorldQueue = true; ++ ++ for (int i = 0; i < threads; ++i) { ++ this.workers[i] = new QueueExecutorThread<>(this.queue, (long)0.10e6); //0.1ms ++ this.workers[i].setName("Async chunk loader thread #" + i + " for world: " + world.getWorld().getName()); ++ this.workers[i].setPriority(Thread.NORM_PRIORITY - 1); ++ this.workers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { ++ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); ++ }); ++ ++ this.workers[i].start(); ++ } ++ } ++ ++ /** ++ * Creates the chunk task manager to work from the global workers. When {@link #close(boolean)} is invoked, ++ * the global queue is not shutdown. If the global workers is configured to be disabled or use 0 threads, then ++ * this chunk task manager will operate off of the world's chunk task queue. ++ * @param world The world that this task manager is responsible for ++ * @see ServerChunkCache#mainThreadProcessor ++ */ ++ public ChunkTaskManager(final ServerLevel world) { ++ this.world = world; ++ this.workers = globalWorkers; ++ this.queue = globalQueue; ++ this.perWorldQueue = false; ++ } ++ ++ public boolean pollNextChunkTask() { ++ final ChunkTask task = this.chunkTasks.poll(); ++ ++ if (task != null) { ++ task.run(); ++ return true; ++ } ++ return false; ++ } ++ ++ /** ++ * Polls and runs the next available chunk wait queue task. This is to be used when the server is waiting on a chunk queue. ++ * (per-world can cause issues if all the worker threads are blocked waiting for a response from the main thread) ++ */ ++ public static boolean pollChunkWaitQueue() { ++ final Runnable run = CHUNK_WAIT_QUEUE.poll(); ++ if (run != null) { ++ run.run(); ++ return true; ++ } ++ return false; ++ } ++ ++ /** ++ * Queues a chunk wait task. Note that this will execute out of order with respect to tasks scheduled on a world's ++ * chunk task queue, since this is the global chunk wait queue. ++ */ ++ public static void queueChunkWaitTask(final Runnable runnable) { ++ CHUNK_WAIT_QUEUE.add(runnable); ++ } ++ ++ private static void drainChunkWaitQueue() { ++ Runnable run; ++ while ((run = CHUNK_WAIT_QUEUE.poll()) != null) { ++ run.run(); ++ } ++ } ++ ++ /** ++ * The exact same as {@link #scheduleChunkLoad(int, int, int, Consumer, boolean)}, except that the chunk data is provided as ++ * the {@code data} parameter. ++ */ ++ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, ++ final Consumer onComplete, ++ final boolean intendingToBlock, final CompletableFuture dataFuture) { ++ final ServerLevel world = this.world; ++ ++ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap != null) { ++ if (!valueInMap.cancelled) { ++ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); ++ } ++ valueInMap.cancelled = false; ++ valueInMap.onComplete = onComplete; ++ return valueInMap; ++ } ++ ++ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); ++ ++ dataFuture.thenAccept((final CompoundTag data) -> { ++ final boolean failed = data == PaperFileIOThread.FAILURE_VALUE; ++ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { ++ ret.chunkData = chunkData; ++ if (!failed) { ++ chunkData.chunkData = data; ++ } ++ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here ++ }, true, failed, intendingToBlock); // read data off disk if the future fails ++ }); ++ ++ return ret; ++ }); ++ } ++ ++ public void cancelChunkLoad(final int chunkX, final int chunkZ) { ++ this.chunkLoadTasks.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap == null) { ++ return null; ++ } ++ ++ if (valueInMap.cancelled) { ++ PaperFileIOThread.LOGGER.warn("Task " + valueInMap.toString() + " is already cancelled!"); ++ } ++ valueInMap.cancelled = true; ++ if (valueInMap.cancel()) { ++ return null; ++ } ++ ++ return valueInMap; ++ }); ++ } ++ ++ /** ++ * Schedules an asynchronous chunk load for the specified coordinates. The onComplete parameter may be invoked asynchronously ++ * on a worker thread or on the world's chunk executor queue. As such the code that is executed for the parameter should be ++ * carefully chosen. ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority for this task ++ * @param onComplete The consumer to invoke with the {@link ChunkSerializer.InProgressChunkHolder} object once this task is complete ++ * @param intendingToBlock Whether the caller is intending to block on this task completing (this is a performance tune, and has no adverse side-effects) ++ * @return The {@link ChunkLoadTask} associated with ++ */ ++ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, ++ final Consumer onComplete, ++ final boolean intendingToBlock) { ++ final ServerLevel world = this.world; ++ ++ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap != null) { ++ if (!valueInMap.cancelled) { ++ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); ++ } ++ valueInMap.cancelled = false; ++ valueInMap.onComplete = onComplete; ++ return valueInMap; ++ } ++ ++ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); ++ ++ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { ++ ret.chunkData = chunkData; ++ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here ++ }, true, true, intendingToBlock); ++ ++ return ret; ++ }); ++ } ++ ++ /** ++ * Schedules an async save for the specified chunk. The chunk, at the beginning of this call, must be completely unloaded ++ * from the world. ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority for this task ++ * @param asyncSaveData Async save data. See {@link ChunkSerializer#getAsyncSaveData(ServerLevel, ChunkAccess)} ++ * @param chunk Chunk to save ++ * @return The {@link ChunkSaveTask} associated with the save task. ++ */ ++ public ChunkSaveTask scheduleChunkSave(final int chunkX, final int chunkZ, final int priority, ++ final ChunkSerializer.AsyncSaveData asyncSaveData, ++ final ChunkAccess chunk) { ++ AsyncCatcher.catchOp("chunk save schedule"); ++ ++ final ServerLevel world = this.world; ++ ++ return this.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { ++ if (valueInMap != null) { ++ throw new IllegalStateException("Double scheduling chunk save for task: " + valueInMap.toString()); ++ } ++ ++ final ChunkSaveTask ret = new ChunkSaveTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, asyncSaveData, chunk); ++ ++ ChunkTaskManager.this.internalSchedule(ret); ++ ++ return ret; ++ }); ++ } ++ ++ /** ++ * Returns a completable future which will be completed with the un-copied chunk data for an in progress async save. ++ * Returns {@code null} if no save is in progress. ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ */ ++ public CompletableFuture getChunkSaveFuture(final int chunkX, final int chunkZ) { ++ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); ++ if (chunkSaveTask == null) { ++ return null; ++ } ++ return chunkSaveTask.onComplete; ++ } ++ ++ /** ++ * Returns the chunk object being used to serialize data async for an unloaded chunk. Note that modifying this chunk ++ * is not safe to do as another thread is handling its save. The chunk is also not loaded into the world. ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @return Chunk object for an in-progress async save, or {@code null} if no save is in progress ++ */ ++ public ChunkAccess getChunkInSaveProgress(final int chunkX, final int chunkZ) { ++ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); ++ if (chunkSaveTask == null) { ++ return null; ++ } ++ return chunkSaveTask.chunk; ++ } ++ ++ public void flush() { ++ // flush here since we schedule tasks on the IO thread that can schedule tasks here ++ drainChunkWaitQueue(); ++ PaperFileIOThread.Holder.INSTANCE.flush(); ++ drainChunkWaitQueue(); ++ ++ if (this.workers == null) { ++ if (Bukkit.isPrimaryThread() || MinecraftServer.getServer().hasStopped()) { ++ ((BlockableEventLoop)this.world.getChunkSource().mainThreadProcessor).runAllTasks(); ++ } else { ++ CompletableFuture wait = new CompletableFuture<>(); ++ MinecraftServer.getServer().scheduleOnMain(() -> { ++ ((BlockableEventLoop)this.world.getChunkSource().mainThreadProcessor).runAllTasks(); ++ }); ++ wait.join(); ++ } ++ } else { ++ for (final QueueExecutorThread worker : this.workers) { ++ worker.flush(); ++ } ++ } ++ if (globalUrgentWorker != null) globalUrgentWorker.flush(); ++ ++ // flush again since tasks we execute async saves ++ drainChunkWaitQueue(); ++ PaperFileIOThread.Holder.INSTANCE.flush(); ++ } ++ ++ public void close(final boolean wait) { ++ // flush here since we schedule tasks on the IO thread that can schedule tasks to this task manager ++ // we do this regardless of the wait param since after we invoke close no tasks can be queued ++ PaperFileIOThread.Holder.INSTANCE.flush(); ++ ++ if (this.workers == null) { ++ if (wait) { ++ this.flush(); ++ } ++ return; ++ } ++ ++ if (this.workers != globalWorkers) { ++ for (final QueueExecutorThread worker : this.workers) { ++ worker.close(false, this.perWorldQueue); ++ } ++ } ++ ++ if (wait) { ++ this.flush(); ++ } ++ } ++ ++ public void raisePriority(final int chunkX, final int chunkZ, final int priority) { ++ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); ++ ++ ChunkTask chunkSaveTask = this.chunkSaveTasks.get(chunkKey); ++ if (chunkSaveTask != null) { ++ // don't bump save into urgent queue ++ raiseTaskPriority(chunkSaveTask, priority != PrioritizedTaskQueue.HIGHEST_PRIORITY ? priority : PrioritizedTaskQueue.HIGH_PRIORITY); ++ } ++ ++ ChunkLoadTask chunkLoadTask = this.chunkLoadTasks.get(chunkKey); ++ if (chunkLoadTask != null) { ++ raiseTaskPriority(chunkLoadTask, priority); ++ } ++ } ++ ++ private void raiseTaskPriority(ChunkTask task, int priority) { ++ final boolean raised = task.raisePriority(priority); ++ if (task.isScheduled() && raised && this.workers != null) { ++ // only notify if we're in queue to be executed ++ if (priority == PrioritizedTaskQueue.HIGHEST_PRIORITY) { ++ // was in another queue but became urgent later, add to urgent queue and the previous ++ // queue will just have to ignore this task if it has already been started. ++ // Ultimately, we now have 2 potential queues that can pull it out whoever gets it first ++ // but the urgent queue has dedicated thread(s) so it's likely to win.... ++ globalUrgentQueue.add(task); ++ this.internalScheduleNotifyUrgent(); ++ } else { ++ this.internalScheduleNotify(); ++ } ++ } ++ } ++ ++ protected void internalSchedule(final ChunkTask task) { ++ if (this.workers == null) { ++ this.chunkTasks.add(task); ++ return; ++ } ++ ++ // It's important we order the task to be executed before notifying. Avoid a race condition where the worker thread ++ // wakes up and goes to sleep before we actually schedule (or it's just about to sleep) ++ if (task.getPriority() == PrioritizedTaskQueue.HIGHEST_PRIORITY) { ++ globalUrgentQueue.add(task); ++ this.internalScheduleNotifyUrgent(); ++ } else { ++ this.queue.add(task); ++ this.internalScheduleNotify(); ++ } ++ ++ } ++ ++ protected void internalScheduleNotify() { ++ if (this.workers == null) { ++ return; ++ } ++ for (final QueueExecutorThread worker : this.workers) { ++ if (worker.notifyTasks()) { ++ // break here since we only want to wake up one worker for scheduling one task ++ break; ++ } ++ } ++ } ++ ++ ++ protected void internalScheduleNotifyUrgent() { ++ if (globalUrgentWorker == null) { ++ return; ++ } ++ globalUrgentWorker.notifyTasks(); ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java +index 354783f862986bf939639a86a9076ac0f5ed97e3..c171860bc117199ca00085bf37507f867d51fb62 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java +@@ -14,7 +14,7 @@ public class ServerboundCommandSuggestionPacket implements Packet { + DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataFixers.getDataFixer(), minecraftsessionservice, gameprofilerepository, usercache, LoggerChunkProgressListener::new); + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index aab1a055c065d1f1a92461e4442ec2cdd8e0b347..643d75b999c3da006eaaab11f4acd77e807683d4 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -920,7 +920,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> future = this.getFutureIfPresentUnchecked(curr); ++ Either either = future.getNow(null); ++ if (either == null || !either.left().isPresent()) { ++ continue; ++ } ++ return curr; ++ } ++ return null; ++ } + // Paper end + + public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { +@@ -375,7 +387,7 @@ public class ChunkHolder { + ChunkStatus chunkstatus = getStatus(this.oldTicketLevel); + ChunkStatus chunkstatus1 = getStatus(this.ticketLevel); + boolean flag = this.oldTicketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; +- boolean flag1 = this.ticketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; ++ boolean flag1 = this.ticketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; // Paper - diff on change: (flag1 = new ticket level is in loadable range) + ChunkHolder.FullChunkStatus playerchunk_state = getFullChunkStatus(this.oldTicketLevel); + ChunkHolder.FullChunkStatus playerchunk_state1 = getFullChunkStatus(this.ticketLevel); + // CraftBukkit start +@@ -411,6 +423,12 @@ public class ChunkHolder { + } + }); + ++ // Paper start ++ if (!flag1) { ++ chunkStorage.level.asyncChunkTaskManager.cancelChunkLoad(this.pos.x, this.pos.z); ++ } ++ // Paper end ++ + for (int i = flag1 ? chunkstatus1.getIndex() + 1 : 0; i <= chunkstatus.getIndex(); ++i) { + completablefuture = (CompletableFuture) this.futures.get(i); + if (completablefuture != null) { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f327e2113 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -86,6 +86,7 @@ import net.minecraft.world.level.chunk.ProtoChunk; + import net.minecraft.world.level.chunk.UpgradeData; + import net.minecraft.world.level.chunk.storage.ChunkSerializer; + import net.minecraft.world.level.chunk.storage.ChunkStorage; ++import net.minecraft.world.level.chunk.storage.RegionFile; + import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; + import net.minecraft.world.level.storage.DimensionDataStorage; +@@ -110,7 +111,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private final ThreadedLevelLightEngine lightEngine; + private final BlockableEventLoop mainThreadExecutor; + public final ChunkGenerator generator; +- private final Supplier overworldDataStorage; ++ private final Supplier overworldDataStorage; public final Supplier getWorldPersistentDataSupplier() { return this.overworldDataStorage; } // Paper - OBFHELPER + private final PoiManager poiManager; + public final LongSet toDrop; + private boolean modified; +@@ -120,7 +121,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final ChunkProgressListener progressListener; + public final ChunkMap.ChunkDistanceManager distanceManager; + private final AtomicInteger tickingGenerated; +- private final StructureManager structureManager; ++ public final StructureManager structureManager; // Paper - private -> public + private final File storageFolder; + private final PlayerMap playerMap; + public final Int2ObjectMap entityMap; +@@ -203,7 +204,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); + this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); + this.overworldDataStorage = supplier; +- this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag); ++ this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper + this.setViewDistance(i); + } + +@@ -245,12 +246,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + @Nullable +- protected ChunkHolder getUpdatingChunkIfPresent(long pos) { ++ public ChunkHolder getUpdatingChunkIfPresent(long pos) { // Paper + return (ChunkHolder) this.updatingChunkMap.get(pos); + } + + @Nullable +- protected ChunkHolder getVisibleChunkIfPresent(long pos) { ++ public ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public + return (ChunkHolder) this.visibleChunkMap.get(pos); + } + +@@ -372,6 +373,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public void close() throws IOException { + try { + this.queueSorter.close(); ++ this.level.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line + this.poiManager.close(); + } finally { + super.close(); +@@ -463,7 +465,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.processUnloads(() -> { + return true; + }); +- this.flushWorker(); ++ this.level.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour ++// this.i(); // Paper - nuke IOWorker + ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); + } else { + this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { +@@ -479,16 +482,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + } + +- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot ++ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more + + protected void tick(BooleanSupplier shouldKeepTicking) { + ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + ++ try (Timing ignored = this.level.timings.poiUnload.startTiming()) { // Paper + gameprofilerfiller.push("poi"); + this.poiManager.tick(shouldKeepTicking); ++ } // Paper + gameprofilerfiller.popPush("chunk_unload"); + if (!this.level.noSave()) { ++ try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper + this.processUnloads(shouldKeepTicking); ++ }// Paper + } + + gameprofilerfiller.pop(); +@@ -509,12 +516,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (playerchunk != null) { + this.pendingUnloads.put(j, playerchunk); + this.modified = true; ++ this.scheduleUnload(j, playerchunk); // Paper - Move up - don't leak chunks + // Spigot start + if (!shouldKeepTicking.getAsBoolean() && this.toDrop.size() <= targetSize && activityAccountant.activityTimeIsExhausted()) { + break; + } + // Spigot end +- this.scheduleUnload(j, playerchunk); ++ //this.a(j, playerchunk); // Paper - move up because spigot did a dumb + } + } + activityAccountant.endActivity(); // Spigot +@@ -528,6 +536,60 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + } + ++ // Paper start - async chunk save for unload ++ // Note: This is very unsafe to call if the chunk is still in use. ++ // This is also modeled after PlayerChunkMap#saveChunk(IChunkAccess, boolean), with the intentional difference being ++ // serializing the chunk is left to a worker thread. ++ private void asyncSave(ChunkAccess chunk) { ++ ChunkPos chunkPos = chunk.getPos(); ++ CompoundTag poiData; ++ try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) { ++ poiData = this.getVillagePlace().getData(chunk.getPos()); ++ } ++ ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkPos.x, chunkPos.z, ++ poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); ++ ++ if (!chunk.isUnsaved()) { ++ return; ++ } ++ ++ ChunkStatus chunkstatus = chunk.getStatus(); ++ ++ // Copied from PlayerChunkMap#saveChunk(IChunkAccess, boolean) ++ if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { ++ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper ++ // Paper start - Optimize save by using status cache ++ try { ++ ChunkStatus statusOnDisk = this.getChunkStatusOnDisk(chunkPos); ++ if (statusOnDisk != null && statusOnDisk.getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { ++ // Paper end ++ return; ++ } ++ ++ if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::e)) { ++ return; ++ } ++ } catch (IOException ex) { ++ ex.printStackTrace(); ++ return; ++ } ++ } ++ } ++ ++ ChunkSerializer.AsyncSaveData asyncSaveData; ++ try (Timing ignored = this.level.timings.chunkUnloadPrepareSave.startTiming()) { ++ asyncSaveData = ChunkSerializer.getAsyncSaveData(this.level, chunk); ++ } ++ ++ this.level.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY, ++ asyncSaveData, chunk); ++ ++ chunk.setLastSaveTime(this.level.getGameTime()); ++ chunk.setUnsaved(false); ++ } ++ // Paper end ++ + private void scheduleUnload(long pos, ChunkHolder playerchunk) { + CompletableFuture completablefuture = playerchunk.getChunkToSave(); + Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error +@@ -541,7 +603,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ((LevelChunk) ichunkaccess).setLoaded(false); + } + +- this.save(ichunkaccess); ++ //this.saveChunk(ichunkaccess);// Paper - delay + if (this.entitiesInLevel.remove(pos) && ichunkaccess instanceof LevelChunk) { + LevelChunk chunk = (LevelChunk) ichunkaccess; + +@@ -549,6 +611,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + this.autoSaveQueue.remove(playerchunk); // Paper + ++ try { ++ this.asyncSave(ichunkaccess); // Paper - async chunk saving ++ } catch (Throwable ex) { ++ LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex); ++ this.save(ichunkaccess); ++ } ++ + this.lightEngine.updateChunkStatus(ichunkaccess.getPos()); + this.lightEngine.tryScheduleUpdate(); + this.progressListener.onStatusChange(ichunkaccess.getPos(), (ChunkStatus) null); +@@ -619,19 +688,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + private CompletableFuture> scheduleChunkLoad(ChunkPos pos) { +- return CompletableFuture.supplyAsync(() -> { ++ // Paper start - Async chunk io ++ final java.util.function.BiFunction> syncLoadComplete = (chunkHolder, ioThrowable) -> { + try (Timing ignored = this.level.timings.chunkLoad.startTimingIfSync()) { // Paper + this.level.getProfiler().incrementCounter("chunkLoad"); +- CompoundTag nbttagcompound; // Paper +- try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings +- nbttagcompound = this.readChunk(pos); +- } // Paper end ++ // Paper start ++ if (ioThrowable != null) { ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable); ++ } ++ ++ this.getVillagePlace().loadInData(pos, chunkHolder.poiData); ++ chunkHolder.tasks.forEach(Runnable::run); ++ // Paper end + +- if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings +- boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8); ++ if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async + +- if (flag) { +- ProtoChunk protochunk = ChunkSerializer.read(this.level, this.structureManager, this.poiManager, pos, nbttagcompound); ++ if (true) { ++ ProtoChunk protochunk = chunkHolder.protoChunk; + + protochunk.setLastSaveTime(this.level.getGameTime()); + this.markPosition(pos, protochunk.getStatus().getChunkType()); +@@ -655,7 +728,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + this.markPositionReplaceable(pos); + return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level)); // Paper - Anti-Xray - Add parameter +- }, this.mainThreadExecutor); ++ // Paper start - Async chunk io ++ }; ++ CompletableFuture> ret = new CompletableFuture<>(); ++ ++ Consumer chunkHolderConsumer = (ChunkSerializer.InProgressChunkHolder holder) -> { ++ // Go into the chunk load queue and not server task queue so we can be popped out even faster. ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.queueChunkWaitTask(() -> { ++ try { ++ ret.complete(syncLoadComplete.apply(holder, null)); ++ } catch (Exception e) { ++ ret.completeExceptionally(e); ++ } ++ }); ++ }; ++ ++ CompletableFuture chunkSaveFuture = this.level.asyncChunkTaskManager.getChunkSaveFuture(pos.x, pos.z); ++ if (chunkSaveFuture != null) { ++ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, ++ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); ++ this.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); ++ } else { ++ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, ++ com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); ++ } ++ return ret; ++ // Paper end + } + + private void markPositionReplaceable(ChunkPos chunkcoordintpair) { +@@ -890,6 +988,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + public boolean save(ChunkAccess chunk) { ++ try (co.aikar.timings.Timing ignored = this.level.timings.chunkSave.startTiming()) { // Paper + this.poiManager.flush(chunk.getPos()); + if (!chunk.isUnsaved()) { + return false; +@@ -902,6 +1001,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkStatus chunkstatus = chunk.getStatus(); + + if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { ++ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper + if (this.isExistingChunkFull(chunkcoordintpair)) { + return false; + } +@@ -909,12 +1009,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::e)) { + return false; + } ++ } // Paper + } + + this.level.getProfiler().incrementCounter("chunkSave"); +- CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk); ++ CompoundTag nbttagcompound; ++ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper ++ nbttagcompound = ChunkSerializer.write(this.level, chunk); ++ } // Paper + +- this.write(chunkcoordintpair, nbttagcompound); ++ ++ // Paper start - async chunk io ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z, ++ null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); ++ // Paper end - async chunk io + this.markPosition(chunkcoordintpair, chunkstatus.getChunkType()); + return true; + } catch (Exception exception) { +@@ -923,6 +1031,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return false; + } + } ++ } // Paper + } + + private boolean isExistingChunkFull(ChunkPos chunkcoordintpair) { +@@ -1052,6 +1161,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + } + ++ // Paper start - Asynchronous chunk io ++ @Nullable ++ @Override ++ public CompoundTag read(ChunkPos chunkcoordintpair) throws IOException { ++ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { ++ CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .loadChunkDataAsyncFuture(this.level, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), ++ false, true, true).join().chunkData; ++ ++ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { ++ throw new IOException("See logs for further detail"); ++ } ++ return ret; ++ } ++ return super.read(chunkcoordintpair); ++ } ++ ++ @Override ++ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { ++ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( ++ this.level, chunkcoordintpair.x, chunkcoordintpair.z, null, nbttagcompound, ++ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); ++ return; ++ } ++ super.write(chunkcoordintpair, nbttagcompound); ++ } ++ // Paper end ++ + @Nullable + public CompoundTag readChunk(ChunkPos pos) throws IOException { // Paper - private -> public + CompoundTag nbttagcompound = this.read(pos); +@@ -1073,33 +1211,55 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + // Paper start - chunk status cache "api" + public ChunkStatus getChunkStatusOnDiskIfCached(ChunkPos chunkPos) { +- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); ++ synchronized (this) { // Paper ++ RegionFile regionFile = this.regionFileCache.getRegionFileIfLoaded(chunkPos); + + return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ } // Paper + } + + public ChunkStatus getChunkStatusOnDisk(ChunkPos chunkPos) throws IOException { +- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); ++ // Paper start - async chunk save for unload ++ ChunkAccess unloadingChunk = this.level.asyncChunkTaskManager.getChunkInSaveProgress(chunkPos.x, chunkPos.z); ++ if (unloadingChunk != null) { ++ return unloadingChunk.getStatus(); ++ } ++ // Paper end ++ // Paper start - async io ++ CompoundTag inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .getPendingWrite(this.level, chunkPos.x, chunkPos.z, false); + +- if (regionFile == null || !regionFile.chunkExists(chunkPos)) { +- return null; ++ if (inProgressWrite != null) { ++ return ChunkSerializer.getStatus(inProgressWrite); + } ++ // Paper end ++ synchronized (this) { // Paper - async io ++ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, true); ++ ++ if (regionFile == null || !regionFile.hasChunk(chunkPos)) { ++ return null; ++ } + +- ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); + +- if (status != null) { +- return status; ++ if (status != null) { ++ return status; ++ } ++ // Paper start - async io + } + +- this.readChunk(chunkPos); ++ CompoundTag compound = this.readChunk(chunkPos); + +- return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ return ChunkSerializer.getStatus(compound); ++ // Paper end + } + + public void updateChunkStatusOnDisk(ChunkPos chunkPos, @Nullable CompoundTag compound) throws IOException { +- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); ++ synchronized (this) { ++ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, false); + +- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); ++ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); ++ } + } + + public ChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { +@@ -1108,6 +1268,39 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + // Paper end + ++ ++ // Paper start - async io ++ // this function will not load chunk data off disk to check for status ++ // ret null for unknown, empty for empty status on disk or absent from disk ++ public ChunkStatus getStatusOnDiskNoLoad(int x, int z) { ++ // Paper start - async chunk save for unload ++ ChunkAccess unloadingChunk = this.level.asyncChunkTaskManager.getChunkInSaveProgress(x, z); ++ if (unloadingChunk != null) { ++ return unloadingChunk.getStatus(); ++ } ++ // Paper end ++ // Paper start - async io ++ CompoundTag inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .getPendingWrite(this.level, x, z, false); ++ ++ if (inProgressWrite != null) { ++ return ChunkSerializer.getStatus(inProgressWrite); ++ } ++ // Paper end ++ // variant of PlayerChunkMap#getChunkStatusOnDisk that does not load data off disk, but loads the region file ++ ChunkPos chunkPos = new ChunkPos(x, z); ++ synchronized (level.getChunkSource().chunkMap) { ++ RegionFile file; ++ try { ++ file = level.getChunkSource().chunkMap.regionFileCache.getFile(chunkPos, false); ++ } catch (IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return !file.hasChunk(chunkPos) ? ChunkStatus.EMPTY : file.getStatusIfCached(x, z); ++ } ++ } ++ + boolean noPlayersCloseForSpawning(ChunkPos chunkcoordintpair) { + // Spigot start + return isOutsideOfRange(chunkcoordintpair, false); +@@ -1454,6 +1647,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + } + ++ public PoiManager getVillagePlace() { return this.getPoiManager(); } // Paper - OBFHELPER + protected PoiManager getPoiManager() { + return this.poiManager; + } +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index c1aa40c01a80a8870478193b8cd7354b0d71045c..120b604d91643248ab375969f95f62a74cbf6be7 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -37,6 +37,7 @@ import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.ChunkSource; + import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.chunk.ImposterProtoChunk; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; + import net.minecraft.world.level.storage.DimensionDataStorage; +@@ -332,11 +333,138 @@ public class ServerChunkCache extends ChunkSource { + return playerChunk.getAvailableChunkNow(); + + } ++ ++ private long asyncLoadSeqCounter; ++ ++ public CompletableFuture> getChunkAtAsynchronously(int x, int z, boolean gen, boolean isUrgent) { ++ if (Thread.currentThread() != this.mainThread) { ++ CompletableFuture> future = new CompletableFuture>(); ++ this.mainThreadProcessor.execute(() -> { ++ this.getChunkAtAsynchronously(x, z, gen, isUrgent).whenComplete((chunk, ex) -> { ++ if (ex != null) { ++ future.completeExceptionally(ex); ++ } else { ++ future.complete(chunk); ++ } ++ }); ++ }); ++ return future; ++ } ++ ++ if (!com.destroystokyo.paper.PaperConfig.asyncChunks) { ++ level.getWorld().loadChunk(x, z, gen); ++ LevelChunk chunk = getChunkAtIfLoadedMainThread(x, z); ++ return CompletableFuture.completedFuture(chunk != null ? Either.left(chunk) : ChunkHolder.UNLOADED_CHUNK); ++ } ++ ++ long k = ChunkPos.asLong(x, z); ++ ChunkPos chunkPos = new ChunkPos(x, z); ++ ++ ChunkAccess ichunkaccess; ++ ++ // try cache ++ for (int l = 0; l < 4; ++l) { ++ if (k == this.lastChunkPos[l] && ChunkStatus.FULL == this.lastChunkStatus[l]) { ++ ichunkaccess = this.lastChunk[l]; ++ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime ++ ++ // move to first in cache ++ ++ for (int i1 = 3; i1 > 0; --i1) { ++ this.lastChunkPos[i1] = this.lastChunkPos[i1 - 1]; ++ this.lastChunkStatus[i1] = this.lastChunkStatus[i1 - 1]; ++ this.lastChunk[i1] = this.lastChunk[i1 - 1]; ++ } ++ ++ this.lastChunkPos[0] = k; ++ this.lastChunkStatus[0] = ChunkStatus.FULL; ++ this.lastChunk[0] = ichunkaccess; ++ ++ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); ++ } ++ } ++ } ++ ++ if (gen) { ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ } ++ ++ ChunkAccess current = this.getChunkAtImmediately(x, z); // we want to bypass ticket restrictions ++ if (current != null) { ++ if (!(current instanceof ImposterProtoChunk) && !(current instanceof LevelChunk)) { ++ return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); ++ } ++ // we know the chunk is at full status here (either in read-only mode or the real thing) ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ } ++ ++ ChunkStatus status = level.getChunkSource().chunkMap.getStatusOnDiskNoLoad(x, z); ++ ++ if (status != null && status != ChunkStatus.FULL) { ++ // does not exist on disk ++ return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); ++ } ++ ++ if (status == ChunkStatus.FULL) { ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ } ++ ++ // status is null here ++ ++ // here we don't know what status it is and we're not supposed to generate ++ // so we asynchronously load empty status ++ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.EMPTY, isUrgent).thenCompose((either) -> { ++ ChunkAccess chunk = either.left().orElse(null); ++ if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof LevelChunk)) { ++ // the chunk on disk was not a full status chunk ++ return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); ++ } ++ ; // bring to full status if required ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ }); ++ } ++ ++ private CompletableFuture> bringToFullStatusAsync(int x, int z, ChunkPos chunkPos, boolean isUrgent) { ++ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.FULL, isUrgent); ++ } ++ ++ private CompletableFuture> bringToStatusAsync(int x, int z, ChunkPos chunkPos, ChunkStatus status, boolean isUrgent) { ++ CompletableFuture> future = this.getChunkFutureMainThread(x, z, status, true, isUrgent); ++ Long identifier = Long.valueOf(this.asyncLoadSeqCounter++); ++ int ticketLevel = MCUtil.getTicketLevelFor(status); ++ this.addTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); ++ ++ return future.thenComposeAsync((Either either) -> { ++ // either left -> success ++ // either right -> failure ++ ++ this.removeTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); ++ this.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); // allow unloading ++ ++ Optional failure = either.right(); ++ ++ if (failure.isPresent()) { ++ // failure ++ throw new IllegalStateException("Chunk failed to load: " + failure.get().toString()); ++ } ++ ++ return CompletableFuture.completedFuture(either); ++ }, this.mainThreadProcessor); ++ } ++ ++ public void addTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { ++ this.distanceManager.addTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); ++ } ++ ++ public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { ++ this.distanceManager.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); ++ } + // Paper end + + @Nullable + @Override + public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) { ++ final int x1 = x; final int z1 = z; // Paper - conflict on variable change + if (Thread.currentThread() != this.mainThread) { + return (ChunkAccess) CompletableFuture.supplyAsync(() -> { + return this.getChunk(x, z, leastStatus, create); +@@ -359,11 +487,16 @@ public class ServerChunkCache extends ChunkSource { + } + + gameprofilerfiller.incrementCounter("getChunkCacheMiss"); +- CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); ++ CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper + + if (!completablefuture.isDone()) { // Paper ++ // Paper start - async chunk io/loading ++ this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); ++ // Paper end + this.level.timings.syncChunkLoad.startTiming(); // Paper + this.mainThreadProcessor.managedBlock(completablefuture::isDone); ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug + this.level.timings.syncChunkLoad.stopTiming(); // Paper + } // Paper + ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { +@@ -429,9 +562,14 @@ public class ServerChunkCache extends ChunkSource { + } + + private CompletableFuture> getChunkFutureMainThread(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { +- ChunkPos chunkcoordintpair = new ChunkPos(chunkX, chunkZ); ++ // Paper start - add isUrgent - old sig left in place for dirty nms plugins ++ return getChunkFutureMainThread(chunkX, chunkZ, leastStatus, create, false); ++ } ++ private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag, boolean isUrgent) { ++ // Paper end ++ ChunkPos chunkcoordintpair = new ChunkPos(i, j); + long k = chunkcoordintpair.toLong(); +- int l = 33 + ChunkStatus.getDistance(leastStatus); ++ int l = 33 + ChunkStatus.getDistance(chunkstatus); + ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); + + // CraftBukkit start - don't add new ticket for currently unloading chunk +@@ -441,7 +579,7 @@ public class ServerChunkCache extends ChunkSource { + ChunkHolder.FullChunkStatus currentChunkState = ChunkHolder.getFullChunkStatus(playerchunk.getTicketLevel()); + currentlyUnloading = (oldChunkState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !currentChunkState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)); + } +- if (create && !currentlyUnloading) { ++ if (flag && !currentlyUnloading) { + // CraftBukkit end + this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); + if (this.chunkAbsent(playerchunk, l)) { +@@ -457,7 +595,7 @@ public class ServerChunkCache extends ChunkSource { + } + } + +- return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(leastStatus, this.chunkMap); ++ return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkstatus, this.chunkMap); + } + + private boolean chunkAbsent(@Nullable ChunkHolder holder, int maxLevel) { +@@ -831,11 +969,12 @@ public class ServerChunkCache extends ChunkSource { + protected boolean pollTask() { + // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task + try { ++ boolean execChunkTask = com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ServerChunkCache.this.level.asyncChunkTaskManager.pollNextChunkTask(); // Paper + if (ServerChunkCache.this.runDistanceManagerUpdates()) { + return true; + } else { + ServerChunkCache.this.lightEngine.tryScheduleUpdate(); +- return super.pollTask(); ++ return super.pollTask() || execChunkTask; // Paper + } + } finally { + chunkMap.callbackExecutor.run(); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index a811ced17721b70bb51837f47e466c2261db2466..95eff4f6165024d21e5c4268a9ae1b7a4268de4b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -51,6 +51,7 @@ import net.minecraft.core.RegistryAccess; + import net.minecraft.core.SectionPos; + import net.minecraft.core.Vec3i; + import net.minecraft.core.particles.ParticleOptions; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.Packet; +@@ -122,6 +123,7 @@ import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.chunk.LevelChunkSection; ++import net.minecraft.world.level.chunk.storage.RegionFile; + import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.level.dimension.end.EndDragonFight; + import net.minecraft.world.level.levelgen.Heightmap; +@@ -202,6 +204,79 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return this.chunkSource.getChunk(x, z, false); + } + ++ // Paper start - Asynchronous IO ++ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController poiDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { ++ @Override ++ public void writeData(int x, int z, CompoundTag compound) throws java.io.IOException { ++ ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().write(new ChunkPos(x, z), compound); ++ } ++ ++ @Override ++ public CompoundTag readData(int x, int z) throws java.io.IOException { ++ return ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().read(new ChunkPos(x, z)); ++ } ++ ++ @Override ++ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (ServerLevel.this.getChunkSource().chunkMap.getVillagePlace()) { ++ RegionFile file; ++ ++ try { ++ file = ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().getFile(new ChunkPos(chunkX, chunkZ), false); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return function.apply(file); ++ } ++ } ++ ++ @Override ++ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (ServerLevel.this.getChunkSource().chunkMap.getVillagePlace()) { ++ RegionFile file = ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().getRegionFileIfLoaded(new ChunkPos(chunkX, chunkZ)); ++ return function.apply(file); ++ } ++ } ++ }; ++ ++ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController chunkDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { ++ @Override ++ public void writeData(int x, int z, CompoundTag compound) throws java.io.IOException { ++ ServerLevel.this.getChunkSource().chunkMap.write(new ChunkPos(x, z), compound); ++ } ++ ++ @Override ++ public CompoundTag readData(int x, int z) throws java.io.IOException { ++ return ServerLevel.this.getChunkSource().chunkMap.read(new ChunkPos(x, z)); ++ } ++ ++ @Override ++ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (ServerLevel.this.getChunkSource().chunkMap) { ++ RegionFile file; ++ ++ try { ++ file = ServerLevel.this.getChunkSource().chunkMap.regionFileCache.getFile(new ChunkPos(chunkX, chunkZ), false); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return function.apply(file); ++ } ++ } ++ ++ @Override ++ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (ServerLevel.this.getChunkSource().chunkMap) { ++ RegionFile file = ServerLevel.this.getChunkSource().chunkMap.regionFileCache.getRegionFileIfLoaded(new ChunkPos(chunkX, chunkZ)); ++ return function.apply(file); ++ } ++ } ++ }; ++ public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; ++ // Paper end ++ + // Add env and gen to constructor, WorldData -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor +@@ -249,6 +324,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.dragonFight = null; + } + this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit ++ ++ this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper + } + + // CraftBukkit start +@@ -1737,7 +1814,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + MCUtil.getSpiralOutChunks(spawn, radiusInBlocks >> 4).forEach(pair -> { +- getChunkSource().getChunkAtMainThread(pair.x, pair.z); ++ getChunkSource().getChunkAtAsynchronously(pair.x, pair.z, true, false).exceptionally((ex) -> { ++ ex.printStackTrace(); ++ return null; ++ }); + }); + } + public void removeTicketsForSpawn(int radiusInBlocks, BlockPos spawn) { +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index cf3ced15c9a87e7a4dbccba17c57a7b32b77566c..d09e4857b6c40410d134fa81b48e95919a7373bd 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -26,6 +26,7 @@ public class TicketType { + public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit + public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper ++ public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper + + public static TicketType create(String name, Comparator comparator) { + return new TicketType<>(name, comparator, 0L); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 4f99c3d06e3b994708c699395adf481a6828e097..5dd99709d6b0ed15bbcee184fe33a28bc1c19dac 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -728,6 +728,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper + return; + } ++ // Paper start ++ String str = packet.getCommand(); int index = -1; ++ if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ return; ++ } ++ // Paper end + // CraftBukkit end + StringReader stringreader = new StringReader(packet.getCommand()); + +diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +index e48fcfe2e4ff151258ae1d84cc0995d2cd54e9a6..a5ce61be7d6e85ac289730d9671e66a7190529f9 100644 +--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java ++++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +@@ -91,7 +91,7 @@ public abstract class BlockableEventLoop implements Processo + + } + +- protected void runAllTasks() { ++ public void runAllTasks() { // Paper - protected -> public + while (this.pollTask()) { + ; + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +index 33a8604fa6c6431ccc5f61e484c163e09f1625a0..d082af8cf4c0c7ca434598aa370712c62e05bb24 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +@@ -22,7 +22,9 @@ import java.util.stream.Stream; + import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.SectionTracker; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.LevelReader; +@@ -36,8 +38,16 @@ public class PoiManager extends SectionStorage { + private final PoiManager.DistanceTracker distanceTracker = new PoiManager.DistanceTracker(); + private final LongSet loadedChunks = new LongOpenHashSet(); + ++ private final ServerLevel world; // Paper ++ + public PoiManager(File directory, DataFixer datafixer, boolean flag) { +- super(directory, PoiSection::codec, PoiSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); ++ // Paper start - add world parameter ++ this(directory, datafixer, flag, null); ++ } ++ public PoiManager(File file, DataFixer datafixer, boolean flag, ServerLevel world) { ++ super(file, PoiSection::codec, PoiSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); ++ this.world = world; ++ // Paper end - add world parameter + } + + public void add(BlockPos pos, PoiType type) { +@@ -155,7 +165,23 @@ public class PoiManager extends SectionStorage { + + @Override + public void tick(BooleanSupplier shouldKeepTicking) { +- super.tick(shouldKeepTicking); ++ // Paper start - async chunk io ++ if (this.world == null) { ++ super.tick(shouldKeepTicking); ++ } else { ++ //super.a(booleansupplier); // re-implement below ++ while (!((SectionStorage)this).dirty.isEmpty() && shouldKeepTicking.getAsBoolean()) { ++ ChunkPos chunkcoordintpair = SectionPos.of(((SectionStorage)this).dirty.firstLong()).chunk(); ++ ++ CompoundTag data; ++ try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) { ++ data = this.getData(chunkcoordintpair); ++ } ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, ++ chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); ++ } ++ } ++ // Paper end + this.distanceTracker.runAllUpdates(); + } + +@@ -255,6 +281,35 @@ public class PoiManager extends SectionStorage { + } + } + ++ // Paper start - Asynchronous chunk io ++ @javax.annotation.Nullable ++ @Override ++ public CompoundTag read(ChunkPos chunkcoordintpair) throws java.io.IOException { ++ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { ++ CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), ++ true, false, true).join().poiData; ++ ++ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { ++ throw new java.io.IOException("See logs for further detail"); ++ } ++ return ret; ++ } ++ return super.read(chunkcoordintpair); ++ } ++ ++ @Override ++ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws java.io.IOException { ++ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( ++ this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, ++ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); ++ return; ++ } ++ super.write(chunkcoordintpair, nbttagcompound); ++ } ++ // Paper end ++ + public static enum Occupancy { + + HAS_SPACE(PoiRecord::hasSpace), IS_OCCUPIED(PoiRecord::isOccupied), ANY((villageplacerecord) -> { +diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java +index d97e266b83bb331fcd4031046a5843d29ce53164..90833389022d7412bdda8868a356b84f62a00e03 100644 +--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java ++++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java +@@ -5,7 +5,7 @@ import net.minecraft.core.BlockPos; + + public class TickNextTickData { + +- private static long counter; ++ private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading + private final T type; + public final BlockPos pos; + public final long triggerTick; +@@ -17,7 +17,7 @@ public class TickNextTickData { + } + + public TickNextTickData(BlockPos pos, T t, long time, TickPriority priority) { +- this.c = (long) (TickNextTickData.counter++); ++ this.c = (long) (TickNextTickData.COUNTER.getAndIncrement()); // Paper - async chunk loading + this.pos = pos.immutable(); + this.type = t; + this.triggerTick = time; +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +index 46d5a24332c1fd3c164b760ec2a2d5bf859b1ab6..3c85b0d39a3fc5c8ec073d92f48b360c0b0be245 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +@@ -170,6 +170,7 @@ public class ChunkStatus { + return ChunkStatus.STATUS_BY_RANGE.size(); + } + ++ public static int getTicketLevelOffset(ChunkStatus status) { return ChunkStatus.getDistance(status); } // Paper - OBFHELPER + public static int getDistance(ChunkStatus status) { + return ChunkStatus.RANGE_BY_STATUS.getInt(status.getIndex()); + } +@@ -185,6 +186,7 @@ public class ChunkStatus { + this.index = previous == null ? 0 : previous.getIndex() + 1; + } + ++ public final int getStatusIndex() { return getIndex(); } // Paper - OBFHELPER + public int getIndex() { + return this.index; + } +@@ -193,7 +195,7 @@ public class ChunkStatus { + return this.name; + } + +- public ChunkStatus getPreviousStatus() { return this.getParent(); } // Paper - OBFHELPER ++ public final ChunkStatus getPreviousStatus() { return this.getParent(); } // Paper - OBFHELPER + public ChunkStatus getParent() { + return this.parent; + } +@@ -206,6 +208,7 @@ public class ChunkStatus { + return this.loadingTask.doWork(this, world, structureManager, lightingProvider, function, chunk); + } + ++ public final int getNeighborRadius() { return this.getRange(); } // Paper - OBFHELPER + public int getRange() { + return this.range; + } +@@ -233,6 +236,7 @@ public class ChunkStatus { + return this.heightmapsAfter; + } + ++ public final boolean isAtLeastStatus(ChunkStatus chunkstatus) { return isOrAfter(chunkstatus); } // Paper - OBFHELPER + public boolean isOrAfter(ChunkStatus chunk) { + return this.getIndex() >= chunk.getIndex(); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java +index 808f69a10589a4a7d6c238c05f6d3e0f272681d3..2b798f4e556302f6f79d54182a309f4716a84f04 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java +@@ -73,6 +73,7 @@ public class DataLayer { + return this.data; + } + ++ public DataLayer copy() { return this.copy(); } // Paper - OBFHELPER + public DataLayer copy() { + return this.data == null ? new DataLayer() : new DataLayer((byte[]) this.data.clone()); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2..be67dc16bf70e4517efd213ca9002f116f60b57c 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet; + import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.shorts.ShortList; + import it.unimi.dsi.fastutil.shorts.ShortListIterator; ++import java.util.ArrayDeque; // Paper + import java.util.Arrays; + import java.util.BitSet; + import java.util.EnumSet; +@@ -66,34 +67,58 @@ public class ChunkSerializer { + + private static final Logger LOGGER = LogManager.getLogger(); + ++ // Paper start ++ public static final class InProgressChunkHolder { ++ ++ public final ProtoChunk protoChunk; ++ public final ArrayDeque tasks; ++ ++ public CompoundTag poiData; ++ ++ public InProgressChunkHolder(final ProtoChunk protoChunk, final ArrayDeque tasks) { ++ this.protoChunk = protoChunk; ++ this.tasks = tasks; ++ } ++ } ++ + public static ProtoChunk read(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag tag) { +- ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); ++ InProgressChunkHolder holder = loadChunk(world, structureManager, poiStorage, pos, tag, true); ++ holder.tasks.forEach(Runnable::run); ++ return holder.protoChunk; ++ } ++ ++ public static InProgressChunkHolder loadChunk(ServerLevel worldserver, StructureManager definedstructuremanager, PoiManager villageplace, ChunkPos chunkcoordintpair, CompoundTag nbttagcompound, boolean distinguish) { ++ ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); ++ // Paper end ++ ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); + BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); +- CompoundTag nbttagcompound1 = tag.getCompound("Level"); ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); + ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); + +- if (!Objects.equals(pos, chunkcoordintpair1)) { +- ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", pos, pos, chunkcoordintpair1); ++ if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { ++ ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); + } + +- ChunkBiomeContainer biomestorage = new ChunkBiomeContainer(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), pos, worldchunkmanager, nbttagcompound1.contains("Biomes", 11) ? nbttagcompound1.getIntArray("Biomes") : null); ++ ChunkBiomeContainer biomestorage = new ChunkBiomeContainer(worldserver.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunkcoordintpair, worldchunkmanager, nbttagcompound1.contains("Biomes", 11) ? nbttagcompound1.getIntArray("Biomes") : null); + UpgradeData chunkconverter = nbttagcompound1.contains("UpgradeData", 10) ? new UpgradeData(nbttagcompound1.getCompound("UpgradeData")) : UpgradeData.EMPTY; + ProtoTickList protochunkticklist = new ProtoTickList<>((block) -> { + return block == null || block.defaultBlockState().isAir(); +- }, pos, nbttagcompound1.getList("ToBeTicked", 9)); ++ }, chunkcoordintpair, nbttagcompound1.getList("ToBeTicked", 9)); + ProtoTickList protochunkticklist1 = new ProtoTickList<>((fluidtype) -> { + return fluidtype == null || fluidtype == Fluids.EMPTY; +- }, pos, nbttagcompound1.getList("LiquidsToBeTicked", 9)); ++ }, chunkcoordintpair, nbttagcompound1.getList("LiquidsToBeTicked", 9)); + boolean flag = nbttagcompound1.getBoolean("isLightOn"); + ListTag nbttaglist = nbttagcompound1.getList("Sections", 10); + boolean flag1 = true; + LevelChunkSection[] achunksection = new LevelChunkSection[16]; +- boolean flag2 = world.dimensionType().hasSkyLight(); +- ServerChunkCache chunkproviderserver = world.getChunkSource(); ++ boolean flag2 = worldserver.dimensionType().hasSkyLight(); ++ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); + LevelLightEngine lightengine = chunkproviderserver.getLightEngine(); + + if (flag) { +- lightengine.retainData(pos, true); ++ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main ++ lightengine.retainData(chunkcoordintpair, true); ++ }); // Paper - delay this task since we're executing off-main + } + + for (int i = 0; i < nbttaglist.size(); ++i) { +@@ -101,7 +126,7 @@ public class ChunkSerializer { + byte b0 = nbttagcompound2.getByte("Y"); + + if (nbttagcompound2.contains("Palette", 9) && nbttagcompound2.contains("BlockStates", 12)) { +- LevelChunkSection chunksection = new LevelChunkSection(b0 << 4, null, world, false); // Paper - Anti-Xray - Add parameters ++ LevelChunkSection chunksection = new LevelChunkSection(b0 << 4, null, worldserver, false); // Paper - Anti-Xray - Add parameters + + chunksection.getStates().read(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); + chunksection.recalcBlockCounts(); +@@ -109,22 +134,34 @@ public class ChunkSerializer { + achunksection[b0] = chunksection; + } + +- poiStorage.checkConsistencyWithBlocks(pos, chunksection); ++ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main ++ villageplace.checkConsistencyWithBlocks(chunkcoordintpair, chunksection); ++ }); // Paper - delay this task since we're executing off-main + } + + if (flag) { + if (nbttagcompound2.contains("BlockLight", 7)) { +- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("BlockLight")), true); ++ // Paper start - delay this task since we're executing off-main ++ DataLayer blockLight = new DataLayer(nbttagcompound2.getByteArray("BlockLight")); ++ tasksToExecuteOnMain.add(() -> { ++ lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair, b0), blockLight, true); ++ }); ++ // Paper end - delay this task since we're executing off-main + } + + if (flag2 && nbttagcompound2.contains("SkyLight", 7)) { +- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("SkyLight")), true); ++ // Paper start - delay this task since we're executing off-main ++ DataLayer skyLight = new DataLayer(nbttagcompound2.getByteArray("SkyLight")); ++ tasksToExecuteOnMain.add(() -> { ++ lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkcoordintpair, b0), skyLight, true); ++ }); ++ // Paper end - delay this task since we're executing off-main + } + } + } + + long j = nbttagcompound1.getLong("InhabitedTime"); +- ChunkStatus.ChunkType chunkstatus_type = getChunkTypeFromTag(tag); ++ ChunkStatus.ChunkType chunkstatus_type = getChunkTypeFromTag(nbttagcompound); + Object object; + + if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) { +@@ -155,7 +192,7 @@ public class ChunkSerializer { + object2 = protochunkticklist1; + } + +- object = new LevelChunk(world.getLevel(), pos, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { ++ object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { + postLoadChunk(nbttagcompound1, chunk); + // CraftBukkit start - load chunk persistent data from nbt + net.minecraft.nbt.Tag persistentBase = nbttagcompound1.get("ChunkBukkitValues"); +@@ -165,7 +202,7 @@ public class ChunkSerializer { + // CraftBukkit end + }); + } else { +- ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world); // Paper - Anti-Xray - Add parameter ++ ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter + + protochunk.setBiomes(biomestorage); + object = protochunk; +@@ -176,7 +213,7 @@ public class ChunkSerializer { + } + + if (!flag && protochunk.getStatus().isOrAfter(ChunkStatus.LIGHT)) { +- Iterator iterator = BlockPos.betweenClosed(pos.getMinBlockX(), 0, pos.getMinBlockZ(), pos.getMaxBlockX(), 255, pos.getMaxBlockZ()).iterator(); ++ Iterator iterator = BlockPos.betweenClosed(chunkcoordintpair.getMinBlockX(), 0, chunkcoordintpair.getMinBlockZ(), chunkcoordintpair.getMaxBlockX(), 255, chunkcoordintpair.getMaxBlockZ()).iterator(); + + while (iterator.hasNext()) { + BlockPos blockposition = (BlockPos) iterator.next(); +@@ -207,8 +244,8 @@ public class ChunkSerializer { + Heightmap.primeHeightmaps((ChunkAccess) object, enumset); + CompoundTag nbttagcompound4 = nbttagcompound1.getCompound("Structures"); + +- ((ChunkAccess) object).setAllStarts(unpackStructureStart(structureManager, nbttagcompound4, world.getSeed())); +- ((ChunkAccess) object).setAllReferences(unpackStructureReferences(pos, nbttagcompound4)); ++ ((ChunkAccess) object).setAllStarts(unpackStructureStart(definedstructuremanager, nbttagcompound4, worldserver.getSeed())); ++ ((ChunkAccess) object).setAllReferences(unpackStructureReferences(chunkcoordintpair, nbttagcompound4)); + if (nbttagcompound1.getBoolean("shouldSave")) { + ((ChunkAccess) object).setUnsaved(true); + } +@@ -227,7 +264,7 @@ public class ChunkSerializer { + } + + if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) { +- return new ImposterProtoChunk((LevelChunk) object); ++ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading + } else { + ProtoChunk protochunk1 = (ProtoChunk) object; + +@@ -266,12 +303,84 @@ public class ChunkSerializer { + protochunk1.setCarvingMask(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1))); + } + +- return protochunk1; ++ return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading + } + } + ++ // Paper start - async chunk save for unload ++ public static final class AsyncSaveData { ++ public final DataLayer[] blockLight; // null or size of 17 (for indices -1 through 15) ++ public final DataLayer[] skyLight; ++ ++ public final ListTag blockTickList; // non-null if we had to go to the server's tick list ++ public final ListTag fluidTickList; // non-null if we had to go to the server's tick list ++ ++ public final long worldTime; ++ ++ public AsyncSaveData(DataLayer[] blockLight, DataLayer[] skyLight, ListTag blockTickList, ListTag fluidTickList, ++ long worldTime) { ++ this.blockLight = blockLight; ++ this.skyLight = skyLight; ++ this.blockTickList = blockTickList; ++ this.fluidTickList = fluidTickList; ++ this.worldTime = worldTime; ++ } ++ } ++ ++ // must be called sync ++ public static AsyncSaveData getAsyncSaveData(ServerLevel world, ChunkAccess chunk) { ++ org.spigotmc.AsyncCatcher.catchOp("preparation of chunk data for async save"); ++ ChunkPos chunkPos = chunk.getPos(); ++ ++ ThreadedLevelLightEngine lightenginethreaded = world.getChunkSource().getLightEngine(); ++ ++ DataLayer[] blockLight = new DataLayer[17 - (-1)]; ++ DataLayer[] skyLight = new DataLayer[17 - (-1)]; ++ ++ for (int i = -1; i < 17; ++i) { ++ DataLayer blockArray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkPos, i)); ++ DataLayer skyArray = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkPos, i)); ++ ++ // copy data for safety ++ if (blockArray != null) { ++ blockArray = blockArray.copy(); ++ } ++ if (skyArray != null) { ++ skyArray = skyArray.copy(); ++ } ++ ++ // apply offset of 1 for -1 starting index ++ blockLight[i + 1] = blockArray; ++ skyLight[i + 1] = skyArray; ++ } ++ ++ TickList blockTickList = chunk.getBlockTicks(); ++ ++ ListTag blockTickListSerialized; ++ if (blockTickList instanceof ProtoTickList || blockTickList instanceof ChunkTickList) { ++ blockTickListSerialized = null; ++ } else { ++ blockTickListSerialized = world.getBlockTicks().save(chunkPos); ++ } ++ ++ TickList fluidTickList = chunk.getLiquidTicks(); ++ ++ ListTag fluidTickListSerialized; ++ if (fluidTickList instanceof ProtoTickList || fluidTickList instanceof ChunkTickList) { ++ fluidTickListSerialized = null; ++ } else { ++ fluidTickListSerialized = world.getLiquidTicks().save(chunkPos); ++ } ++ ++ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, world.getGameTime()); ++ } ++ + public static CompoundTag write(ServerLevel world, ChunkAccess chunk) { +- ChunkPos chunkcoordintpair = chunk.getPos(); ++ return saveChunk(world, chunk, null); ++ } ++ public static CompoundTag saveChunk(ServerLevel worldserver, ChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { ++ // Paper end ++ ChunkPos chunkcoordintpair = ichunkaccess.getPos(); + CompoundTag nbttagcompound = new CompoundTag(); + CompoundTag nbttagcompound1 = new CompoundTag(); + +@@ -279,30 +388,38 @@ public class ChunkSerializer { + nbttagcompound.put("Level", nbttagcompound1); + nbttagcompound1.putInt("xPos", chunkcoordintpair.x); + nbttagcompound1.putInt("zPos", chunkcoordintpair.z); +- nbttagcompound1.putLong("LastUpdate", world.getGameTime()); +- nbttagcompound1.putLong("InhabitedTime", chunk.getInhabitedTime()); +- nbttagcompound1.putString("Status", chunk.getStatus().getName()); +- UpgradeData chunkconverter = chunk.getUpgradeData(); ++ nbttagcompound1.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getGameTime()); // Paper - async chunk unloading ++ nbttagcompound1.putLong("InhabitedTime", ichunkaccess.getInhabitedTime()); ++ nbttagcompound1.putString("Status", ichunkaccess.getStatus().getName()); ++ UpgradeData chunkconverter = ichunkaccess.getUpgradeData(); + + if (!chunkconverter.isEmpty()) { + nbttagcompound1.put("UpgradeData", chunkconverter.write()); + } + +- LevelChunkSection[] achunksection = chunk.getSections(); ++ LevelChunkSection[] achunksection = ichunkaccess.getSections(); + ListTag nbttaglist = new ListTag(); +- ThreadedLevelLightEngine lightenginethreaded = world.getChunkSource().getLightEngine(); +- boolean flag = chunk.isLightCorrect(); ++ ThreadedLevelLightEngine lightenginethreaded = worldserver.getChunkSource().getLightEngine(); ++ boolean flag = ichunkaccess.isLightCorrect(); + + CompoundTag nbttagcompound2; + +- for (int i = -1; i < 17; ++i) { ++ for (int i = -1; i < 17; ++i) { // Paper - conflict on loop parameter change + int finalI = i; // CraftBukkit - decompile errors + LevelChunkSection chunksection = (LevelChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { + return chunksection1 != null && chunksection1.bottomBlockY() >> 4 == finalI; // CraftBukkit - decompile errors + }).findFirst().orElse(LevelChunk.EMPTY_SECTION); +- DataLayer nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); +- DataLayer nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); +- ++ // Paper start - async chunk save for unload ++ DataLayer nibblearray; // block light ++ DataLayer nibblearray1; // sky light ++ if (asyncsavedata == null) { ++ nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); /// Paper - diff on method change (see getAsyncSaveData) ++ nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); // Paper - diff on method change (see getAsyncSaveData) ++ } else { ++ nibblearray = asyncsavedata.blockLight[i + 1]; // +1 to offset the -1 starting index ++ nibblearray1 = asyncsavedata.skyLight[i + 1]; // +1 to offset the -1 starting index ++ } ++ // Paper end + if (chunksection != LevelChunk.EMPTY_SECTION || nibblearray != null || nibblearray1 != null) { + nbttagcompound2 = new CompoundTag(); + nbttagcompound2.putByte("Y", (byte) (i & 255)); +@@ -327,21 +444,21 @@ public class ChunkSerializer { + nbttagcompound1.putBoolean("isLightOn", true); + } + +- ChunkBiomeContainer biomestorage = chunk.getBiomes(); ++ ChunkBiomeContainer biomestorage = ichunkaccess.getBiomes(); + + if (biomestorage != null) { + nbttagcompound1.putIntArray("Biomes", biomestorage.writeBiomes()); + } + + ListTag nbttaglist1 = new ListTag(); +- Iterator iterator = chunk.getBlockEntitiesPos().iterator(); ++ Iterator iterator = ichunkaccess.getBlockEntitiesPos().iterator(); + + CompoundTag nbttagcompound3; + + while (iterator.hasNext()) { + BlockPos blockposition = (BlockPos) iterator.next(); + +- nbttagcompound3 = chunk.getBlockEntityNbtForSaving(blockposition); ++ nbttagcompound3 = ichunkaccess.getBlockEntityNbtForSaving(blockposition); + if (nbttagcompound3 != null) { + nbttaglist1.add(nbttagcompound3); + } +@@ -351,25 +468,25 @@ public class ChunkSerializer { + ListTag nbttaglist2 = new ListTag(); + + java.util.List toUpdate = new java.util.ArrayList<>(); // Paper +- if (chunk.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { +- LevelChunk chunk1 = (LevelChunk) chunk; ++ if (ichunkaccess.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { ++ LevelChunk chunk = (LevelChunk) ichunkaccess; + + // CraftBukkit start - store chunk persistent data in nbt +- if (!chunk1.persistentDataContainer.isEmpty()) { +- nbttagcompound1.put("ChunkBukkitValues", chunk1.persistentDataContainer.toTagCompound()); ++ if (!chunk.persistentDataContainer.isEmpty()) { ++ nbttagcompound1.put("ChunkBukkitValues", chunk.persistentDataContainer.toTagCompound()); + } + // CraftBukkit end + +- chunk1.setLastSaveHadEntities(false); ++ chunk.setLastSaveHadEntities(false); + +- for (int j = 0; j < chunk1.getEntitySlices().length; ++j) { +- Iterator iterator1 = chunk1.getEntitySlices()[j].iterator(); ++ for (int j = 0; j < chunk.getEntitySlices().length; ++j) { ++ Iterator iterator1 = chunk.getEntitySlices()[j].iterator(); + + while (iterator1.hasNext()) { + Entity entity = (Entity) iterator1.next(); + CompoundTag nbttagcompound4 = new CompoundTag(); + // Paper start +- if ((int) Math.floor(entity.getX()) >> 4 != chunk1.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk1.getPos().z) { ++ if (asyncsavedata == null && !entity.removed && (int) Math.floor(entity.getX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk.getPos().z) { + toUpdate.add(entity); + continue; + } +@@ -378,7 +495,7 @@ public class ChunkSerializer { + } + // Paper end + if (entity.save(nbttagcompound4)) { +- chunk1.setLastSaveHadEntities(true); ++ chunk.setLastSaveHadEntities(true); + nbttaglist2.add(nbttagcompound4); + } + } +@@ -386,12 +503,12 @@ public class ChunkSerializer { + + // Paper start - move entities to the correct chunk + for (Entity entity : toUpdate) { +- world.updateChunkPos(entity); ++ worldserver.updateChunkPos(entity); + } + // Paper end + + } else { +- ProtoChunk protochunk = (ProtoChunk) chunk; ++ ProtoChunk protochunk = (ProtoChunk) ichunkaccess; + + nbttaglist2.addAll(protochunk.getEntities()); + nbttagcompound1.put("Lights", packOffsets(protochunk.getPackedLights())); +@@ -412,40 +529,48 @@ public class ChunkSerializer { + } + + nbttagcompound1.put("Entities", nbttaglist2); +- TickList ticklist = chunk.getBlockTicks(); ++ TickList ticklist = ichunkaccess.getBlockTicks(); // Paper - diff on method change (see getAsyncSaveData) + + if (ticklist instanceof ProtoTickList) { + nbttagcompound1.put("ToBeTicked", ((ProtoTickList) ticklist).save()); + } else if (ticklist instanceof ChunkTickList) { + nbttagcompound1.put("TileTicks", ((ChunkTickList) ticklist).save()); ++ // Paper start - async chunk save for unload ++ } else if (asyncsavedata != null) { ++ nbttagcompound1.put("TileTicks", asyncsavedata.blockTickList); ++ // Paper end + } else { +- nbttagcompound1.put("TileTicks", world.getBlockTicks().save(chunkcoordintpair)); ++ nbttagcompound1.put("TileTicks", worldserver.getBlockTicks().save(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) + } + +- TickList ticklist1 = chunk.getLiquidTicks(); ++ TickList ticklist1 = ichunkaccess.getLiquidTicks(); // Paper - diff on method change (see getAsyncSaveData) + + if (ticklist1 instanceof ProtoTickList) { + nbttagcompound1.put("LiquidsToBeTicked", ((ProtoTickList) ticklist1).save()); + } else if (ticklist1 instanceof ChunkTickList) { + nbttagcompound1.put("LiquidTicks", ((ChunkTickList) ticklist1).save()); ++ // Paper start - async chunk save for unload ++ } else if (asyncsavedata != null) { ++ nbttagcompound1.put("LiquidTicks", asyncsavedata.fluidTickList); ++ // Paper end + } else { +- nbttagcompound1.put("LiquidTicks", world.getLiquidTicks().save(chunkcoordintpair)); ++ nbttagcompound1.put("LiquidTicks", worldserver.getLiquidTicks().save(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) + } + +- nbttagcompound1.put("PostProcessing", packOffsets(chunk.getPostProcessing())); ++ nbttagcompound1.put("PostProcessing", packOffsets(ichunkaccess.getPostProcessing())); + nbttagcompound2 = new CompoundTag(); +- Iterator iterator2 = chunk.getHeightmaps().iterator(); ++ Iterator iterator2 = ichunkaccess.getHeightmaps().iterator(); + + while (iterator2.hasNext()) { + Entry entry = (Entry) iterator2.next(); + +- if (chunk.getStatus().heightmapsAfter().contains(entry.getKey())) { ++ if (ichunkaccess.getStatus().heightmapsAfter().contains(entry.getKey())) { + nbttagcompound2.put(((Heightmap.Types) entry.getKey()).getSerializationKey(), new LongArrayTag(((Heightmap) entry.getValue()).getRawData())); + } + } + + nbttagcompound1.put("Heightmaps", nbttagcompound2); +- nbttagcompound1.put("Structures", packStructureData(chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences())); ++ nbttagcompound1.put("Structures", packStructureData(chunkcoordintpair, ichunkaccess.getAllStarts(), ichunkaccess.getAllReferences())); + return nbttagcompound; + } + // Paper start - this is saved with the player +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +index 9cffef2098fbfba89ddd88a45bde33c07660497a..684442b7175e30b6d4cafb2f7d2d4c10517cc33d 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -3,6 +3,10 @@ package net.minecraft.world.level.chunk.storage; + import com.mojang.datafixers.DataFixer; + import java.io.File; + import java.io.IOException; ++// Paper start ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.CompletionException; ++// Paper end + import java.util.function.Supplier; + import javax.annotation.Nullable; + import net.minecraft.SharedConstants; +@@ -21,32 +25,41 @@ import net.minecraft.world.level.storage.DimensionDataStorage; + + public class ChunkStorage implements AutoCloseable { + +- private final IOWorker worker; public IOWorker getIOWorker() { return worker; } // Paper - OBFHELPER ++ // Paper - OBFHELPER - nuke IOWorker + protected final DataFixer fixerUpper; + @Nullable +- private LegacyStructureDataHandler legacyStructureHandler; ++ private volatile LegacyStructureDataHandler legacyStructureHandler; // Paper - async chunk loading ++ ++ private final Object persistentDataLock = new Object(); // Paper ++ public final RegionFileStorage regionFileCache; + + public ChunkStorage(File file, DataFixer datafixer, boolean flag) { ++ this.regionFileCache = new RegionFileStorage(file, flag); // Paper - nuke IOWorker + this.fixerUpper = datafixer; +- this.worker = new IOWorker(file, flag, "chunk"); ++ // Paper - nuke IOWorker + } + + // CraftBukkit start + private boolean check(ServerChunkCache cps, int x, int z) throws IOException { + ChunkPos pos = new ChunkPos(x, z); + if (cps != null) { +- com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); +- if (cps.hasChunk(x, z)) { ++ //com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe ++ if (cps.getChunkAtIfCachedImmediately(x, z) != null) { // Paper - isLoaded is a ticket level check, not a chunk loaded check! + return true; + } + } + +- CompoundTag nbt = read(pos); +- if (nbt != null) { +- CompoundTag level = nbt.getCompound("Level"); +- if (level.getBoolean("TerrainPopulated")) { +- return true; +- } ++ ++ // Paper start - prioritize ++ CompoundTag nbt = cps == null ? read(pos) : ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.loadChunkData((ServerLevel)cps.getLevel(), x, z, ++ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHER_PRIORITY, false, true).chunkData; ++ // Paper end ++ if (nbt != null) { ++ CompoundTag level = nbt.getCompound("Level"); ++ if (level.getBoolean("TerrainPopulated")) { ++ return true; ++ } + + ChunkStatus status = ChunkStatus.byName(level.getString("Status")); + if (status != null && status.isOrAfter(ChunkStatus.FEATURES)) { +@@ -77,11 +90,13 @@ public class ChunkStorage implements AutoCloseable { + if (i < 1493) { + nbttagcompound = NbtUtils.update(this.fixerUpper, DataFixTypes.CHUNK, nbttagcompound, i, 1493); + if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { ++ synchronized (this.persistentDataLock) { // Paper - Async chunk loading + if (this.legacyStructureHandler == null) { + this.legacyStructureHandler = LegacyStructureDataHandler.getLegacyStructureHandler(resourcekey, (DimensionDataStorage) supplier.get()); + } + + nbttagcompound = this.legacyStructureHandler.updateFromLegacy(nbttagcompound); ++ } // Paper - Async chunk loading + } + } + +@@ -99,22 +114,20 @@ public class ChunkStorage implements AutoCloseable { + + @Nullable + public CompoundTag read(ChunkPos chunkcoordintpair) throws IOException { +- return this.worker.load(chunkcoordintpair); ++ return this.regionFileCache.read(chunkcoordintpair); + } + +- public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) { +- this.worker.store(chunkcoordintpair, nbttagcompound); ++ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER ++ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) ++ this.regionFileCache.write(chunkcoordintpair, nbttagcompound); + if (this.legacyStructureHandler != null) { ++ synchronized (this.persistentDataLock) { // Paper - Async chunk loading + this.legacyStructureHandler.removeIndex(chunkcoordintpair.toLong()); ++ } // Paper - Async chunk loading} + } +- +- } +- +- public void flushWorker() { +- this.worker.synchronize().join(); + } + + public void close() throws IOException { +- this.worker.close(); ++ this.regionFileCache.close(); + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 4d96e5ed28c910387c0a4238c9036c7a12458f57..7ecde2cb15fa0b1b5195fc560c559f2c367e336f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -45,6 +45,8 @@ public class RegionFile implements AutoCloseable { + protected final RegionBitmap usedSectors; + public final File file; // Paper + ++ public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper ++ + // Paper start - Cache chunk status + private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; + +@@ -251,7 +253,7 @@ public class RegionFile implements AutoCloseable { + return (byteCount + 4096 - 1) / 4096; + } + +- public boolean doesChunkExist(ChunkPos pos) { ++ public synchronized boolean doesChunkExist(ChunkPos pos) { // Paper - synchronized + int i = this.getOffset(pos); + + if (i == 0) { +@@ -411,6 +413,11 @@ public class RegionFile implements AutoCloseable { + } + + public void close() throws IOException { ++ // Paper start - Prevent regionfiles from being closed during use ++ this.fileLock.lock(); ++ synchronized (this) { ++ try { ++ // Paper end + this.closed = true; // Paper + try { + this.padToFullSector(); +@@ -421,6 +428,10 @@ public class RegionFile implements AutoCloseable { + this.file.close(); + } + } ++ } finally { // Paper start - Prevent regionfiles from being closed during use ++ this.fileLock.unlock(); ++ } ++ } // Paper end + + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index 6f1c96e4325caf6b4762700ad2286d9ea41515c9..0498982ac14f20145d68dbf64a46bcaacf5516ef 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -17,7 +17,7 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.util.ExceptionCollector; + import net.minecraft.world.level.ChunkPos; + +-public final class RegionFileStorage implements AutoCloseable { ++public class RegionFileStorage implements AutoCloseable { // Paper - no final + + public final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap(); + private final File folder; +@@ -30,16 +30,27 @@ public final class RegionFileStorage implements AutoCloseable { + + + // Paper start +- public RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { ++ public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { // Paper - synchronize for async io + return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); + } + + // Paper end +- public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public ++ public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public, synchronize ++ // Paper start - add lock parameter ++ return this.getFile(chunkcoordintpair, existingOnly, false); ++ } ++ public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly, boolean lock) throws IOException { ++ // Paper end + long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); + RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); + + if (regionfile != null) { ++ // Paper start ++ if (lock) { ++ // must be in this synchronized block ++ regionfile.fileLock.lock(); ++ } ++ // Paper end + return regionfile; + } else { + if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable +@@ -55,6 +66,12 @@ public final class RegionFileStorage implements AutoCloseable { + RegionFile regionfile1 = new RegionFile(file, this.folder, this.sync); + + this.regionCache.putAndMoveToFirst(i, regionfile1); ++ // Paper start ++ if (lock) { ++ // must be in this synchronized block ++ regionfile1.fileLock.lock(); ++ } ++ // Paper end + return regionfile1; + } + } +@@ -130,11 +147,12 @@ public final class RegionFileStorage implements AutoCloseable { + @Nullable + public CompoundTag read(ChunkPos pos) throws IOException { + // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing +- RegionFile regionfile = this.getFile(pos, true); ++ RegionFile regionfile = this.getFile(pos, true, true); // Paper + if (regionfile == null) { + return null; + } + // CraftBukkit end ++ try { // Paper + DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); + // Paper start + if (regionfile.isOversized(pos.x, pos.z)) { +@@ -172,10 +190,14 @@ public final class RegionFileStorage implements AutoCloseable { + } + + return nbttagcompound; ++ } finally { // Paper start ++ regionfile.fileLock.unlock(); ++ } // Paper end + } + + protected void write(ChunkPos pos, CompoundTag tag) throws IOException { +- RegionFile regionfile = this.getFile(pos, false); // CraftBukkit ++ RegionFile regionfile = this.getFile(pos, false, true); // CraftBukkit // Paper ++ try { // Paper + int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper + DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(pos); + Throwable throwable = null; +@@ -214,9 +236,12 @@ public final class RegionFileStorage implements AutoCloseable { + MinecraftServer.LOGGER.error("Failed to save chunk", laste); + } + // Paper end ++ } finally { // Paper start ++ regionfile.fileLock.unlock(); ++ } // Paper end + } + +- public void close() throws IOException { ++ public synchronized void close() throws IOException { // Paper -> synchronized + ExceptionCollector exceptionsuppressor = new ExceptionCollector<>(); + ObjectIterator objectiterator = this.regionCache.values().iterator(); + +@@ -243,4 +268,12 @@ public final class RegionFileStorage implements AutoCloseable { + } + + } ++ ++ // CraftBukkit start ++ public synchronized boolean chunkExists(ChunkPos pos) throws IOException { // Paper - synchronize ++ RegionFile regionfile = getFile(pos, true); ++ ++ return regionfile != null ? regionfile.hasChunk(pos) : false; ++ } ++ // CraftBukkit end + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java +index 059a658aa87d19025daa66d98f78112d5f5be4e3..bb30fb085a6c5edb717ad006c0ab481723ca1b6b 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java +@@ -30,28 +30,29 @@ import net.minecraft.world.level.Level; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +-public class SectionStorage implements AutoCloseable { ++public class SectionStorage extends RegionFileStorage implements AutoCloseable { // Paper - nuke IOWorker + + private static final Logger LOGGER = LogManager.getLogger(); +- private final IOWorker worker; ++ // Paper - nuke IOWorker + private final Long2ObjectMap> storage = new Long2ObjectOpenHashMap(); +- private final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet(); ++ public final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet(); // Paper - private -> public + private final Function> codec; + private final Function factory; + private final DataFixer fixerUpper; + private final DataFixTypes type; + + public SectionStorage(File directory, Function> codecFactory, Function factory, DataFixer datafixer, DataFixTypes datafixtypes, boolean flag) { ++ super(directory, flag); // Paper - nuke IOWorker + this.codec = codecFactory; + this.factory = factory; + this.fixerUpper = datafixer; + this.type = datafixtypes; +- this.worker = new IOWorker(directory, flag, directory.getName()); ++ //this.b = new IOWorker(file, flag, file.getName()); // Paper - nuke IOWorker + } + + protected void tick(BooleanSupplier shouldKeepTicking) { + while (!this.dirty.isEmpty() && shouldKeepTicking.getAsBoolean()) { +- ChunkPos chunkcoordintpair = SectionPos.of(this.dirty.firstLong()).chunk(); ++ ChunkPos chunkcoordintpair = SectionPos.of(this.dirty.firstLong()).chunk(); // Paper - conflict here to avoid obfhelpers + + this.writeColumn(chunkcoordintpair); + } +@@ -105,13 +106,18 @@ public class SectionStorage implements AutoCloseable { + } + + private void readColumn(ChunkPos chunkcoordintpair) { +- this.readColumn(chunkcoordintpair, NbtOps.INSTANCE, this.tryRead(chunkcoordintpair)); ++ // Paper start - load data in function ++ this.loadInData(chunkcoordintpair, this.tryRead(chunkcoordintpair)); ++ } ++ public void loadInData(ChunkPos chunkPos, CompoundTag compound) { ++ this.readColumn(chunkPos, NbtOps.INSTANCE, compound); ++ // Paper end + } + + @Nullable + private CompoundTag tryRead(ChunkPos pos) { + try { +- return this.worker.load(pos); ++ return this.read(pos); // Paper - nuke IOWorker + } catch (IOException ioexception) { + SectionStorage.LOGGER.error("Error reading chunk {} data from disk", pos, ioexception); + return null; +@@ -157,17 +163,31 @@ public class SectionStorage implements AutoCloseable { + } + + private void writeColumn(ChunkPos chunkcoordintpair) { +- Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); ++ Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); // Paper - conflict here to avoid adding obfhelpers :) + Tag nbtbase = (Tag) dynamic.getValue(); + + if (nbtbase instanceof CompoundTag) { +- this.worker.store(chunkcoordintpair, (CompoundTag) nbtbase); ++ try { this.write(chunkcoordintpair, (CompoundTag) nbtbase); } catch (IOException ioexception) { SectionStorage.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker // TODO make this write async + } else { + SectionStorage.LOGGER.error("Expected compound tag, got {}", nbtbase); + } + + } + ++ // Paper start - internal get data function, copied from above ++ private CompoundTag getDataInternal(ChunkPos chunkcoordintpair) { ++ Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); ++ Tag nbtbase = (Tag) dynamic.getValue(); ++ ++ if (nbtbase instanceof CompoundTag) { ++ return (CompoundTag)nbtbase; ++ } else { ++ SectionStorage.LOGGER.error("Expected compound tag, got {}", nbtbase); ++ } ++ return null; ++ } ++ // Paper end ++ + private Dynamic writeColumn(ChunkPos chunkcoordintpair, DynamicOps dynamicops) { + Map map = Maps.newHashMap(); + +@@ -213,9 +233,9 @@ public class SectionStorage implements AutoCloseable { + public void flush(ChunkPos chunkcoordintpair) { + if (!this.dirty.isEmpty()) { + for (int i = 0; i < 16; ++i) { +- long j = SectionPos.of(chunkcoordintpair, i).asLong(); ++ long j = SectionPos.of(chunkcoordintpair, i).asLong(); // Paper - conflict here to avoid obfhelpers + +- if (this.dirty.contains(j)) { ++ if (this.dirty.contains(j)) { // Paper - conflict here to avoid obfhelpers + this.writeColumn(chunkcoordintpair); + return; + } +@@ -224,7 +244,26 @@ public class SectionStorage implements AutoCloseable { + + } + +- public void close() throws IOException { +- this.worker.close(); ++// Paper start - nuke IOWorker ++// public void close() throws IOException { ++// this.b.close(); ++// } ++// Paper end ++ ++ // Paper start - get data function ++ public CompoundTag getData(ChunkPos chunkcoordintpair) { ++ // Note: Copied from above ++ // This is checking if the data exists, then it builds it later in getDataInternal(ChunkCoordIntPair) ++ if (!this.dirty.isEmpty()) { ++ for (int i = 0; i < 16; ++i) { ++ long j = SectionPos.of(chunkcoordintpair, i).asLong(); ++ ++ if (this.dirty.contains(j)) { ++ return this.getDataInternal(chunkcoordintpair); ++ } ++ } ++ } ++ return null; + } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index a0615e4ba015cca4fe074de63b87d0bff84b1a14..52444619a4bae80a12bf296fbe07fa811adf806e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -545,22 +545,23 @@ public class CraftWorld implements World { + return true; + } + +- net.minecraft.world.level.chunk.storage.RegionFile file; +- try { +- file = world.getChunkSource().chunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); +- } catch (IOException ex) { +- throw new RuntimeException(ex); +- } ++ ChunkStatus status = world.getChunkSource().chunkMap.getStatusOnDiskNoLoad(x, z); // Paper - async io - move to own method + +- ChunkStatus status = file.getStatusIfCached(x, z); +- if (!file.hasChunk(chunkPos) || (status != null && status != ChunkStatus.FULL)) { ++ // Paper start - async io ++ if (status == ChunkStatus.EMPTY) { ++ // does not exist on disk + return false; + } + ++ if (status == null) { // at this stage we don't know what it is on disk + ChunkAccess chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.EMPTY, true); + if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof net.minecraft.world.level.chunk.LevelChunk)) { + return false; + } ++ } else if (status != ChunkStatus.FULL) { ++ return false; // not full status on disk ++ } ++ // Paper end + + // fall through to load + // we do this so we do not re-read the chunk data on disk +@@ -2483,6 +2484,34 @@ public class CraftWorld implements World { + public DragonBattle getEnderDragonBattle() { + return (getHandle().dragonFight() == null) ? null : new CraftDragonBattle(getHandle().dragonFight()); + } ++ // Paper start ++ @Override ++ public CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { ++ if (Bukkit.isPrimaryThread()) { ++ net.minecraft.world.level.chunk.LevelChunk immediate = this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); ++ if (immediate != null) { ++ return CompletableFuture.completedFuture(immediate.getBukkitChunk()); ++ } ++ } else { ++ CompletableFuture future = new CompletableFuture(); ++ world.getServer().execute(() -> { ++ getChunkAtAsync(x, z, gen, urgent).whenComplete((chunk, err) -> { ++ if (err != null) { ++ future.completeExceptionally(err); ++ } else { ++ future.complete(chunk); ++ } ++ }); ++ }); ++ return future; ++ } ++ ++ return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { ++ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); ++ return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); ++ }, net.minecraft.server.MinecraftServer.getServer()); ++ } ++ // Paper end + + // Spigot start + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 7ad4fb57af32cc1b8278688381e1b058ed8437db..76d652386806fd11961611486a1d0a12fe9616a4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -11,7 +11,9 @@ import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.Component; ++import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.TicketType; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AreaEffectCloud; + import net.minecraft.world.entity.Entity; +@@ -508,6 +510,28 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + entity.setYHeadRot(yaw); + } + ++ @Override// Paper start ++ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ ChunkMap playerChunkMap = ((CraftWorld) loc.getWorld()).getHandle().getChunkSource().chunkMap; ++ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); ++ ++ loc.getWorld().getChunkAtAsyncUrgently(loc).thenCompose(chunk -> { ++ ChunkCoordIntPair pair = new ChunkCoordIntPair(chunk.getX(), chunk.getZ()); ++ ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().addTicketAtLevel(TicketType.POST_TELEPORT, pair, 31, 0); ++ PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pair.pair()); ++ if (updatingChunk != null) { ++ return updatingChunk.getEntityTickingFuture(); ++ } else { ++ return java.util.concurrent.CompletableFuture.completedFuture(com.mojang.datafixers.util.Either.left(((org.bukkit.craftbukkit.CraftChunk)chunk).getHandle())); ++ } ++ }).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { ++ future.completeExceptionally(ex); ++ return null; ++ }); ++ return future; ++ } ++ // Paper end ++ + @Override + public boolean teleport(Location location) { + return teleport(location, TeleportCause.PLUGIN); +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 16f6163bb53e73aa4ab6e22365342613b6b38118..33a66322d253c7562ae5acbdbc6cc87f7d72a9af 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -6,6 +6,7 @@ import java.lang.management.ThreadInfo; + import java.util.logging.Level; + import java.util.logging.Logger; + import com.destroystokyo.paper.PaperConfig; ++import com.destroystokyo.paper.io.chunk.ChunkTaskManager; // Paper + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; + +@@ -116,6 +117,7 @@ public class WatchdogThread extends Thread + // Paper end - Different message for short timeout + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper ++ ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // diff --git a/Remapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch b/Remapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch new file mode 100644 index 0000000000..3becb4b6e9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 8 Jul 2019 00:13:36 -0700 +Subject: [PATCH] Use getChunkIfLoadedImmediately in places + +This prevents us from hitting chunk loads for chunks at or less-than +ticket level 33 (yes getChunkIfLoaded will actually perform a chunk +load in that case). + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 95eff4f6165024d21e5c4268a9ae1b7a4268de4b..9d4c81a4964317a0726171dc6d490d12bd959cc4 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -201,7 +201,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI +- return this.chunkSource.getChunk(x, z, false); ++ return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper + } + + // Paper start - Asynchronous IO +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 5dd99709d6b0ed15bbcee184fe33a28bc1c19dac..e45690b6197335ed1c07fa04c39b311b401724d7 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1242,7 +1242,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + speed = player.abilities.walkingSpeed * 10f; + } + // Paper start - Prevent moving into unloaded chunks +- if (player.level.paperConfig.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.hasChunk((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { ++ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && worldserver.getChunkIfLoadedImmediately((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4) == null) { // Paper - use getIfLoadedImmediately + this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.yRot, this.player.xRot, Collections.emptySet()); + return; + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +index d082af8cf4c0c7ca434598aa370712c62e05bb24..b9d32e3322c2cce1aca2a90df71b6175a6f8c548 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +@@ -284,10 +284,10 @@ public class PoiManager extends SectionStorage { + // Paper start - Asynchronous chunk io + @javax.annotation.Nullable + @Override +- public CompoundTag read(ChunkPos chunkcoordintpair) throws java.io.IOException { ++ public CompoundTag read(ChunkPos pos) throws java.io.IOException { + if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { + CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE +- .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), ++ .loadChunkDataAsyncFuture(this.world, pos.x, pos.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), + true, false, true).join().poiData; + + if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { +@@ -295,18 +295,18 @@ public class PoiManager extends SectionStorage { + } + return ret; + } +- return super.read(chunkcoordintpair); ++ return super.read(pos); + } + + @Override +- public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws java.io.IOException { ++ public void write(ChunkPos pos, CompoundTag tag) throws java.io.IOException { + if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( +- this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, ++ this.world, pos.x, pos.z, tag, null, + com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); + return; + } +- super.write(chunkcoordintpair, nbttagcompound); ++ super.write(pos, tag); + } + // Paper end + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 1377465e3dc062f34be25cac10aa018776fb22e7..3a1b9f1ba19b28cebdafeb3b2476217d47213862 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -164,6 +164,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return (CraftServer) Bukkit.getServer(); + } + ++ // Paper start ++ @Override ++ public boolean hasChunk(int chunkX, int chunkZ) { ++ return ((ServerLevel)this).getChunkIfLoaded(chunkX, chunkZ) != null; ++ } ++ // Paper end ++ + public ResourceKey getTypeKey() { + return typeKey; + } +@@ -1190,7 +1197,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + for (int i1 = i; i1 < j; ++i1) { + for (int j1 = k; j1 < l; ++j1) { +- LevelChunk chunk = ichunkprovider.getChunkNow(i1, j1); ++ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { + chunk.getEntitiesOfClass(entityClass, box, list, predicate); +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 0a9bd85e0308e962df3b24a74bd5aac919744d6d..61f180a7c95d83bb88c7df4910c498d9bdf6785a 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -140,9 +140,10 @@ public class ActivationRange + { + for ( int j1 = k; j1 <= l; ++j1 ) + { +- if ( world.getWorld().isChunkLoaded( i1, j1 ) ) ++ LevelChunk chunk = (LevelChunk) world.getChunkIfLoadedImmediately( i1, j1 ); ++ if ( chunk != null ) + { +- activateChunkEntities( world.getChunk( i1, j1 ) ); ++ activateChunkEntities( chunk ); + } + } + } diff --git a/Remapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch b/Remapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch new file mode 100644 index 0000000000..5349d43158 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch @@ -0,0 +1,350 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 19 Jul 2019 03:29:14 -0700 +Subject: [PATCH] Reduce sync loads + +This reduces calls to getChunkAt which would load chunks. + +This patch also adds a tool to find calls which are doing this, however +it must be enabled by setting the startup flag -Dpaper.debug-sync-loads=true + +To get a debug log for sync loads, the command is /paper syncloadinfo + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 62711d95db62221a2e4e6423c518afe13a6c7dbe..ff718bc7f521575e6a670e17fcf59a2d30841705 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -1,12 +1,18 @@ + package com.destroystokyo.paper; + + import com.destroystokyo.paper.io.chunk.ChunkTaskManager; ++import com.destroystokyo.paper.io.SyncLoadFinder; + import com.google.common.base.Functions; + import com.google.common.base.Joiner; + import com.google.common.collect.ImmutableSet; + import com.google.common.collect.Iterables; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; ++import com.google.gson.JsonObject; ++import com.google.gson.internal.Streams; ++import com.google.gson.stream.JsonWriter; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerChunkCache; +@@ -14,7 +20,6 @@ import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; +-import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MCUtil; + import org.apache.commons.lang3.tuple.MutablePair; + import org.apache.commons.lang3.tuple.Pair; +@@ -29,6 +34,9 @@ import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.entity.Player; + + import java.io.File; ++import java.io.FileOutputStream; ++import java.io.PrintStream; ++import java.io.StringWriter; + import java.time.LocalDateTime; + import java.time.format.DateTimeFormatter; + import java.util.ArrayList; +@@ -44,7 +52,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); + + public PaperCommand(String name) { + super(name); +@@ -162,6 +170,9 @@ public class PaperCommand extends Command { + case "chunkinfo": + doChunkInfo(sender, args); + break; ++ case "syncloadinfo": ++ this.doSyncLoadInfo(sender, args); ++ break; + case "ver": + if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) + case "version": +@@ -179,6 +190,40 @@ public class PaperCommand extends Command { + return true; + } + ++ private void doSyncLoadInfo(CommandSender sender, String[] args) { ++ if (!SyncLoadFinder.ENABLED) { ++ sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); ++ return; ++ } ++ File file = new File(new File(new File("."), "debug"), ++ "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); ++ file.getParentFile().mkdirs(); ++ sender.sendMessage(ChatColor.GREEN + "Writing sync load info to " + file.toString()); ++ ++ ++ try { ++ final JsonObject data = SyncLoadFinder.serialize(); ++ ++ StringWriter stringWriter = new StringWriter(); ++ JsonWriter jsonWriter = new JsonWriter(stringWriter); ++ jsonWriter.setIndent(" "); ++ jsonWriter.setLenient(false); ++ Streams.write(data, jsonWriter); ++ ++ String fileData = stringWriter.toString(); ++ ++ try ( ++ PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8") ++ ) { ++ out.print(fileData); ++ } ++ sender.sendMessage(ChatColor.GREEN + "Successfully written sync load information!"); ++ } catch (Throwable thr) { ++ sender.sendMessage(ChatColor.RED + "Failed to write sync load information"); ++ thr.printStackTrace(); ++ } ++ } ++ + private void doChunkInfo(CommandSender sender, String[] args) { + List worlds; + if (args.length < 2 || args[1].equals("*")) { +diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..524f33371b9de1d4dd6972fe59ffbe1804d7c5f3 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java +@@ -0,0 +1,171 @@ ++package com.destroystokyo.paper.io; ++ ++import com.google.gson.JsonArray; ++import com.google.gson.JsonObject; ++import com.mojang.datafixers.util.Pair; ++import it.unimi.dsi.fastutil.longs.Long2IntMap; ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++import java.util.WeakHashMap; ++import net.minecraft.world.level.Level; ++ ++public class SyncLoadFinder { ++ ++ public static final boolean ENABLED = Boolean.getBoolean("paper.debug-sync-loads"); ++ ++ private static final WeakHashMap> SYNC_LOADS = new WeakHashMap<>(); ++ ++ private static final class SyncLoadInformation { ++ ++ public int times; ++ ++ public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); ++ } ++ ++ public static void logSyncLoad(final Level world, final int chunkX, final int chunkZ) { ++ if (!ENABLED) { ++ return; ++ } ++ ++ final ThrowableWithEquals stacktrace = new ThrowableWithEquals(Thread.currentThread().getStackTrace()); ++ ++ SYNC_LOADS.compute(world, (final Level keyInMap, Object2ObjectOpenHashMap map) -> { ++ if (map == null) { ++ map = new Object2ObjectOpenHashMap<>(); ++ } ++ ++ map.compute(stacktrace, (ThrowableWithEquals keyInMap0, SyncLoadInformation valueInMap) -> { ++ if (valueInMap == null) { ++ valueInMap = new SyncLoadInformation(); ++ } ++ ++ ++valueInMap.times; ++ ++ valueInMap.coordinateTimes.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (Long keyInMap1, Integer valueInMap1) -> { ++ return valueInMap1 == null ? Integer.valueOf(1) : Integer.valueOf(valueInMap1.intValue() + 1); ++ }); ++ ++ return valueInMap; ++ }); ++ ++ return map; ++ }); ++ } ++ ++ public static JsonObject serialize() { ++ final JsonObject ret = new JsonObject(); ++ ++ final JsonArray worldsData = new JsonArray(); ++ ++ for (final Map.Entry> entry : SYNC_LOADS.entrySet()) { ++ final Level world = entry.getKey(); ++ ++ final JsonObject worldData = new JsonObject(); ++ ++ worldData.addProperty("name", world.getWorld().getName()); ++ ++ final List> data = new ArrayList<>(); ++ ++ entry.getValue().forEach((ThrowableWithEquals stacktrace, SyncLoadInformation times) -> { ++ data.add(new Pair<>(stacktrace, times)); ++ }); ++ ++ data.sort((Pair pair1, Pair pair2) -> { ++ return Integer.compare(pair2.getSecond().times, pair1.getSecond().times); // reverse order ++ }); ++ ++ final JsonArray stacktraces = new JsonArray(); ++ ++ for (Pair pair : data) { ++ final JsonObject stacktrace = new JsonObject(); ++ ++ stacktrace.addProperty("times", pair.getSecond().times); ++ ++ final JsonArray traces = new JsonArray(); ++ ++ for (StackTraceElement element : pair.getFirst().stacktrace) { ++ traces.add(String.valueOf(element)); ++ } ++ ++ stacktrace.add("stacktrace", traces); ++ ++ final JsonArray coordinates = new JsonArray(); ++ ++ for (Long2IntMap.Entry coordinate : pair.getSecond().coordinateTimes.long2IntEntrySet()) { ++ final long key = coordinate.getLongKey(); ++ final int times = coordinate.getIntValue(); ++ coordinates.add("(" + IOUtil.getCoordinateX(key) + "," + IOUtil.getCoordinateZ(key) + "): " + times); ++ } ++ ++ stacktrace.add("coordinates", coordinates); ++ ++ stacktraces.add(stacktrace); ++ } ++ ++ ++ worldData.add("stacktraces", stacktraces); ++ worldsData.add(worldData); ++ } ++ ++ ret.add("worlds", worldsData); ++ ++ return ret; ++ } ++ ++ static final class ThrowableWithEquals { ++ ++ private final StackTraceElement[] stacktrace; ++ private final int hash; ++ ++ public ThrowableWithEquals(final StackTraceElement[] stacktrace) { ++ this.stacktrace = stacktrace; ++ this.hash = ThrowableWithEquals.hash(stacktrace); ++ } ++ ++ public static int hash(final StackTraceElement[] stacktrace) { ++ int hash = 0; ++ ++ for (int i = 0; i < stacktrace.length; ++i) { ++ hash *= 31; ++ hash += stacktrace[i].hashCode(); ++ } ++ ++ return hash; ++ } ++ ++ @Override ++ public int hashCode() { ++ return this.hash; ++ } ++ ++ @Override ++ public boolean equals(final Object obj) { ++ if (obj == null || obj.getClass() != this.getClass()) { ++ return false; ++ } ++ ++ final ThrowableWithEquals other = (ThrowableWithEquals)obj; ++ final StackTraceElement[] otherStackTrace = other.stacktrace; ++ ++ if (this.stacktrace.length != otherStackTrace.length || this.hash != other.hash) { ++ return false; ++ } ++ ++ if (this == obj) { ++ return true; ++ } ++ ++ for (int i = 0; i < this.stacktrace.length; ++i) { ++ if (!this.stacktrace[i].equals(otherStackTrace[i])) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 120b604d91643248ab375969f95f62a74cbf6be7..5e0d55c3821b1769d20514a8a6c5c74477019778 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -494,6 +494,7 @@ public class ServerChunkCache extends ChunkSource { + this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); + // Paper end ++ com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x1, z1); // Paper - sync load info + this.level.timings.syncChunkLoad.startTiming(); // Paper + this.mainThreadProcessor.managedBlock(completablefuture::isDone); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 9d4c81a4964317a0726171dc6d490d12bd959cc4..01f879a8dd0e1ffec380e02072567330152eaceb 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -276,6 +276,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + }; + public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; + // Paper end ++ // Paper start ++ @Override ++ public boolean hasChunk(int chunkX, int chunkZ) { ++ return this.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ) != null; ++ } ++ // Paper end + + // Add env and gen to constructor, WorldData -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 3a1b9f1ba19b28cebdafeb3b2476217d47213862..3e2cd6c7a34c1a792d7346019a8b039d1f4a7c04 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -1130,7 +1130,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + for (int i1 = i; i1 <= j; ++i1) { + for (int j1 = k; j1 <= l; ++j1) { +- LevelChunk chunk = ichunkprovider.getChunk(i1, j1, false); ++ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { + chunk.getEntities(except, box, list, predicate); +@@ -1151,7 +1151,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + for (int i1 = i; i1 < j; ++i1) { + for (int j1 = k; j1 < l; ++j1) { +- LevelChunk chunk = this.getChunkSource().getChunk(i1, j1, false); ++ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { + chunk.getEntities(type, box, list, predicate); +@@ -1174,7 +1174,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + for (int i1 = i; i1 < j; ++i1) { + for (int j1 = k; j1 < l; ++j1) { +- LevelChunk chunk = ichunkprovider.getChunk(i1, j1, false); ++ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { + chunk.getEntitiesOfClass(entityClass, box, list, predicate); diff --git a/Remapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch b/Remapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch new file mode 100644 index 0000000000..21aa2f962b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Mon, 3 Jun 2019 02:02:39 -0400 +Subject: [PATCH] Implement alternative item-despawn-rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1ee2cced100626e48eb36ee14f84b9257c79a2f8..b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -1,10 +1,15 @@ + package com.destroystokyo.paper; + + import java.util.Arrays; ++import java.util.EnumMap; ++import java.util.HashMap; + import java.util.List; ++import java.util.Map; + + import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; + import org.bukkit.Bukkit; ++import org.bukkit.Material; ++import org.bukkit.configuration.ConfigurationSection; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; + +@@ -512,4 +517,52 @@ public class PaperWorldConfig { + private void disableRelativeProjectileVelocity() { + disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); + } ++ ++ public boolean altItemDespawnRateEnabled; ++ public Map altItemDespawnRateMap; ++ private void altItemDespawnRate() { ++ String path = "alt-item-despawn-rate"; ++ ++ altItemDespawnRateEnabled = getBoolean(path + ".enabled", false); ++ ++ Map altItemDespawnRateMapDefault = new EnumMap<>(Material.class); ++ altItemDespawnRateMapDefault.put(Material.COBBLESTONE, 300); ++ for (Material key : altItemDespawnRateMapDefault.keySet()) { ++ config.addDefault("world-settings.default." + path + ".items." + key, altItemDespawnRateMapDefault.get(key)); ++ } ++ ++ Map rawMap = new HashMap<>(); ++ try { ++ ConfigurationSection mapSection = config.getConfigurationSection("world-settings." + worldName + "." + path + ".items"); ++ if (mapSection == null) { ++ mapSection = config.getConfigurationSection("world-settings.default." + path + ".items"); ++ } ++ for (String key : mapSection.getKeys(false)) { ++ int val = mapSection.getInt(key); ++ rawMap.put(key, val); ++ } ++ } ++ catch (Exception e) { ++ logError("alt-item-despawn-rate was malformatted"); ++ altItemDespawnRateEnabled = false; ++ } ++ ++ altItemDespawnRateMap = new EnumMap<>(Material.class); ++ if (!altItemDespawnRateEnabled) { ++ return; ++ } ++ ++ for(String key : rawMap.keySet()) { ++ try { ++ altItemDespawnRateMap.put(Material.valueOf(key), rawMap.get(key)); ++ } catch (Exception e) { ++ logError("Could not add item " + key + " to altItemDespawnRateMap: " + e.getMessage()); ++ } ++ } ++ if(altItemDespawnRateEnabled) { ++ for(Material key : altItemDespawnRateMap.keySet()) { ++ log("Alternative item despawn rate of " + key + ": " + altItemDespawnRateMap.get(key)); ++ } ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 281f5646980afc70890bdafd358ff9b20d32420d..96b8102773cbee2c3fe2711008ba1487084d67b0 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -32,6 +32,7 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.stats.Stats; ++import org.bukkit.Material; // Paper + import org.bukkit.event.entity.EntityPickupItemEvent; + import org.bukkit.event.player.PlayerPickupItemEvent; + // CraftBukkit end +@@ -160,7 +161,7 @@ public class ItemEntity extends Entity { + } + } + +- if (!this.level.isClientSide && this.age >= level.spigotConfig.itemDespawnRate) { // Spigot ++ if (!this.level.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper + // CraftBukkit start - fire ItemDespawnEvent + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { + this.age = 0; +@@ -184,7 +185,7 @@ public class ItemEntity extends Entity { + this.lastTick = MinecraftServer.currentTick; + // CraftBukkit end + +- if (!this.level.isClientSide && this.age >= level.spigotConfig.itemDespawnRate) { // Spigot ++ if (!this.level.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper + // CraftBukkit start - fire ItemDespawnEvent + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { + this.age = 0; +@@ -534,9 +535,16 @@ public class ItemEntity extends Entity { + + public void makeFakeItem() { + this.setNeverPickUp(); +- this.age = level.spigotConfig.itemDespawnRate - 1; // Spigot ++ this.age = this.getDespawnRate() - 1; // Spigot // Paper + } + ++ // Paper start ++ public int getDespawnRate(){ ++ Material material = this.getItem().getBukkitStack().getType(); ++ return level.paperConfig.altItemDespawnRateMap.getOrDefault(material, level.spigotConfig.itemDespawnRate); ++ } ++ // Paper end ++ + @Override + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this); diff --git a/Remapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/Remapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch new file mode 100644 index 0000000000..eab9bd3397 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paul Sauve +Date: Sun, 14 Jul 2019 21:05:03 -0500 +Subject: [PATCH] Do less work if we have a custom Bukkit generator + +If the Bukkit generator already has a spawn, use it immediately instead +of spending time generating one that we won't use + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 643d75b999c3da006eaaab11f4acd77e807683d4..753e6f609189c589514739bea80007bace3c89d2 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -628,12 +628,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +- return biomebase.getMobSettings().playerSpawnFriendly(); +- }, random); +- ChunkPos chunkcoordintpair = blockposition == null ? new ChunkPos(0, 0) : new ChunkPos(blockposition); ++ // Paper start - moved down + // CraftBukkit start + if (world.generator != null) { + Random rand = new Random(world.getSeed()); +@@ -649,6 +644,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { ++ return biomebase.getMobSettings().playerSpawnFriendly(); ++ }, random); ++ ChunkPos chunkcoordintpair = blockposition == null ? new ChunkPos(0, 0) : new ChunkPos(blockposition); ++ // Paper end + + if (blockposition == null) { + MinecraftServer.LOGGER.warn("Unable to find spawn biome"); diff --git a/Remapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch b/Remapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch new file mode 100644 index 0000000000..585e674b4b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 13 Aug 2019 06:35:17 -0700 +Subject: [PATCH] Fix MC-158900 + +The problem was we were checking isExpired() on the entry, but if it +was expired at that point, then it would be null. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7412765020854caabd32fb6f4fffcf7f4bf6dba7..e6eebb8f6f48cc55fc8fb114c959b8fbec4b8472 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -603,8 +603,10 @@ public abstract class PlayerList { + Player player = entity.getBukkitEntity(); + PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.connection.getRawAddress()).getAddress()); + +- if (getBans().isBanned(gameprofile) && !getBans().get(gameprofile).hasExpired()) { +- UserBanListEntry gameprofilebanentry = (UserBanListEntry) this.bans.get(gameprofile); ++ // Paper start - Fix MC-158900 ++ UserBanListEntry gameprofilebanentry; ++ if (getBans().isBanned(gameprofile) && (gameprofilebanentry = getBans().get(gameprofile)) != null) { ++ // Paper end + + chatmessage = new TranslatableComponent("multiplayer.disconnect.banned.reason", new Object[]{gameprofilebanentry.getReason()}); + if (gameprofilebanentry.getExpires() != null) { diff --git a/Remapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch b/Remapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch new file mode 100644 index 0000000000..70bcd1b1bd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch @@ -0,0 +1,924 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Mon, 19 Aug 2019 01:27:58 +0500 +Subject: [PATCH] implement optional per player mob spawns + + +diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +index 24eac9400fbf971742e89bbf47b0ba52b587c4eb..b818a7451d45d2ab7d4678f0065ada9017d8a631 100644 +--- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java ++++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +@@ -58,6 +58,7 @@ public class WorldTimingsHandler { + + + public final Timing miscMobSpawning; ++ public final Timing playerMobDistanceMapUpdate; + + public final Timing poiUnload; + public final Timing chunkUnload; +@@ -123,6 +124,7 @@ public class WorldTimingsHandler { + + + miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); ++ playerMobDistanceMapUpdate = Timings.ofSafe(name + "Per Player Mob Spawning - Distance Map Update"); + + poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); + chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920..6aec502eb529d4090306e12e837117cde7e114eb 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -565,4 +565,9 @@ public class PaperWorldConfig { + } + } + } ++ ++ public boolean perPlayerMobSpawns = false; ++ private void perPlayerMobSpawns() { ++ perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2a87599922d7075a9f888f48a2deb35ed3eb7c54 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java +@@ -0,0 +1,252 @@ ++package com.destroystokyo.paper.util; ++ ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; ++import java.util.List; ++import java.util.Map; ++import net.minecraft.core.SectionPos; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.level.ChunkPos; ++import org.spigotmc.AsyncCatcher; ++import java.util.HashMap; ++ ++/** @author Spottedleaf */ ++public final class PlayerMobDistanceMap { ++ ++ private static final PooledHashSets.PooledObjectLinkedOpenHashSet EMPTY_SET = new PooledHashSets.PooledObjectLinkedOpenHashSet<>(); ++ ++ private final Map players = new HashMap<>(); ++ // we use linked for better iteration. ++ private final Long2ObjectOpenHashMap> playerMap = new Long2ObjectOpenHashMap<>(32, 0.5f); ++ private int viewDistance; ++ ++ private final PooledHashSets pooledHashSets = new PooledHashSets<>(); ++ ++ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final ChunkPos chunkPos) { ++ return this.getPlayersInRange(chunkPos.x, chunkPos.z); ++ } ++ ++ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final int chunkX, final int chunkZ) { ++ return this.playerMap.getOrDefault(ChunkPos.asLong(chunkX, chunkZ), EMPTY_SET); ++ } ++ ++ public void update(final List currentPlayers, final int newViewDistance) { ++ AsyncCatcher.catchOp("Distance map update"); ++ final ObjectLinkedOpenHashSet gone = new ObjectLinkedOpenHashSet<>(this.players.keySet()); ++ ++ final int oldViewDistance = this.viewDistance; ++ this.viewDistance = newViewDistance; ++ ++ for (final ServerPlayer player : currentPlayers) { ++ if (player.isSpectator() || !player.affectsSpawning) { ++ continue; // will be left in 'gone' (or not added at all) ++ } ++ ++ gone.remove(player); ++ ++ final SectionPos newPosition = player.getPlayerMapSection(); ++ final SectionPos oldPosition = this.players.put(player, newPosition); ++ ++ if (oldPosition == null) { ++ this.addNewPlayer(player, newPosition, newViewDistance); ++ } else { ++ this.updatePlayer(player, oldPosition, newPosition, oldViewDistance, newViewDistance); ++ } ++ //this.validatePlayer(player, newViewDistance); // debug only ++ } ++ ++ for (final ServerPlayer player : gone) { ++ final SectionPos oldPosition = this.players.remove(player); ++ if (oldPosition != null) { ++ this.removePlayer(player, oldPosition, oldViewDistance); ++ } ++ } ++ } ++ ++ // expensive op, only for debug ++ private void validatePlayer(final ServerPlayer player, final int viewDistance) { ++ int entiesGot = 0; ++ int expectedEntries = (2 * viewDistance + 1); ++ expectedEntries *= expectedEntries; ++ ++ final SectionPos currPosition = player.getPlayerMapSection(); ++ ++ final int centerX = currPosition.getX(); ++ final int centerZ = currPosition.getZ(); ++ ++ for (final Long2ObjectLinkedOpenHashMap.Entry> entry : this.playerMap.long2ObjectEntrySet()) { ++ final long key = entry.getLongKey(); ++ final PooledHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); ++ ++ if (map.referenceCount == 0) { ++ throw new IllegalStateException("Invalid map"); ++ } ++ ++ if (map.set.contains(player)) { ++ ++entiesGot; ++ ++ final int chunkX = ChunkPos.getX(key); ++ final int chunkZ = ChunkPos.getZ(key); ++ ++ final int dist = Math.max(Math.abs(chunkX - centerX), Math.abs(chunkZ - centerZ)); ++ ++ if (dist > viewDistance) { ++ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); ++ } ++ } ++ } ++ ++ if (entiesGot != expectedEntries) { ++ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); ++ } ++ } ++ ++ private void addPlayerTo(final ServerPlayer player, final int chunkX, final int chunkZ) { ++ this.playerMap.compute(ChunkPos.asLong(chunkX, chunkZ), (final Long key, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { ++ if (players == null) { ++ return player.cachedSingleMobDistanceMap; ++ } else { ++ return PlayerMobDistanceMap.this.pooledHashSets.findMapWith(players, player); ++ } ++ }); ++ } ++ ++ private void removePlayerFrom(final ServerPlayer player, final int chunkX, final int chunkZ) { ++ this.playerMap.compute(ChunkPos.asLong(chunkX, chunkZ), (final Long keyInMap, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { ++ return PlayerMobDistanceMap.this.pooledHashSets.findMapWithout(players, player); // rets null instead of an empty map ++ }); ++ } ++ ++ private void updatePlayer(final ServerPlayer player, final SectionPos oldPosition, final SectionPos newPosition, final int oldViewDistance, final int newViewDistance) { ++ final int toX = newPosition.getX(); ++ final int toZ = newPosition.getZ(); ++ final int fromX = oldPosition.getX(); ++ final int fromZ = oldPosition.getZ(); ++ ++ final int dx = toX - fromX; ++ final int dz = toZ - fromZ; ++ ++ final int totalX = Math.abs(fromX - toX); ++ final int totalZ = Math.abs(fromZ - toZ); ++ ++ if (Math.max(totalX, totalZ) > (2 * oldViewDistance)) { ++ // teleported? ++ this.removePlayer(player, oldPosition, oldViewDistance); ++ this.addNewPlayer(player, newPosition, newViewDistance); ++ return; ++ } ++ ++ // x axis is width ++ // z axis is height ++ // right refers to the x axis of where we moved ++ // top refers to the z axis of where we moved ++ ++ if (oldViewDistance == newViewDistance) { ++ // same view distance ++ ++ // used for relative positioning ++ final int up = 1 | (dz >> (Integer.SIZE - 1)); // 1 if dz >= 0, -1 otherwise ++ final int right = 1 | (dx >> (Integer.SIZE - 1)); // 1 if dx >= 0, -1 otherwise ++ ++ // The area excluded by overlapping the two view distance squares creates four rectangles: ++ // Two on the left, and two on the right. The ones on the left we consider the "removed" section ++ // and on the right the "added" section. ++ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually ++ // exclusive to the regions they surround. ++ ++ // 4 points of the rectangle ++ int maxX; // exclusive ++ int minX; // inclusive ++ int maxZ; // exclusive ++ int minZ; // inclusive ++ ++ if (dx != 0) { ++ // handle right addition ++ ++ maxX = toX + (oldViewDistance * right) + right; // exclusive ++ minX = fromX + (oldViewDistance * right) + right; // inclusive ++ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive ++ minZ = toZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.addPlayerTo(player, currX, currZ); ++ } ++ } ++ } ++ ++ if (dz != 0) { ++ // handle up addition ++ ++ maxX = toX + (oldViewDistance * right) + right; // exclusive ++ minX = toX - (oldViewDistance * right); // inclusive ++ maxZ = toZ + (oldViewDistance * up) + up; // exclusive ++ minZ = fromZ + (oldViewDistance * up) + up; // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.addPlayerTo(player, currX, currZ); ++ } ++ } ++ } ++ ++ if (dx != 0) { ++ // handle left removal ++ ++ maxX = toX - (oldViewDistance * right); // exclusive ++ minX = fromX - (oldViewDistance * right); // inclusive ++ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive ++ minZ = toZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.removePlayerFrom(player, currX, currZ); ++ } ++ } ++ } ++ ++ if (dz != 0) { ++ // handle down removal ++ ++ maxX = fromX + (oldViewDistance * right) + right; // exclusive ++ minX = fromX - (oldViewDistance * right); // inclusive ++ maxZ = toZ - (oldViewDistance * up); // exclusive ++ minZ = fromZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.removePlayerFrom(player, currX, currZ); ++ } ++ } ++ } ++ } else { ++ // different view distance ++ // for now :) ++ this.removePlayer(player, oldPosition, oldViewDistance); ++ this.addNewPlayer(player, newPosition, newViewDistance); ++ } ++ } ++ ++ private void removePlayer(final ServerPlayer player, final SectionPos position, final int viewDistance) { ++ final int x = position.getX(); ++ final int z = position.getZ(); ++ ++ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { ++ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { ++ this.removePlayerFrom(player, x + xoff, z + zoff); ++ } ++ } ++ } ++ ++ private void addNewPlayer(final ServerPlayer player, final SectionPos position, final int viewDistance) { ++ final int x = position.getX(); ++ final int z = position.getZ(); ++ ++ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { ++ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { ++ this.addPlayerTo(player, x + xoff, z + zoff); ++ } ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4f13d3ff8391793a99f067189f854078334499c6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java +@@ -0,0 +1,241 @@ ++package com.destroystokyo.paper.util; ++ ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; ++import java.lang.ref.WeakReference; ++import java.util.Iterator; ++ ++/** @author Spottedleaf */ ++public class PooledHashSets { ++ ++ // we really want to avoid that equals() check as much as possible... ++ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(64, 0.25f); ++ ++ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { ++ if (current.referenceCount == 0) { ++ throw new IllegalStateException("Cannot decrement reference count for " + current); ++ } ++ if (current.referenceCount == -1 || --current.referenceCount > 0) { ++ return; ++ } ++ ++ this.mapPool.remove(current); ++ return; ++ } ++ ++ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { ++ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); ++ ++ if (cached != null) { ++ if (cached.referenceCount != -1) { ++ ++cached.referenceCount; ++ } ++ ++ decrementReferenceCount(current); ++ ++ return cached; ++ } ++ ++ if (!current.add(object)) { ++ return current; ++ } ++ ++ // we use get/put since we use a different key on put ++ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); ++ ++ if (ret == null) { ++ ret = new PooledObjectLinkedOpenHashSet<>(current); ++ current.remove(object); ++ this.mapPool.put(ret, ret); ++ ret.referenceCount = 1; ++ } else { ++ if (ret.referenceCount != -1) { ++ ++ret.referenceCount; ++ } ++ current.remove(object); ++ } ++ ++ current.updateAddCache(object, ret); ++ ++ decrementReferenceCount(current); ++ return ret; ++ } ++ ++ // rets null if current.size() == 1 ++ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { ++ if (current.set.size() == 1) { ++ decrementReferenceCount(current); ++ return null; ++ } ++ ++ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); ++ ++ if (cached != null) { ++ if (cached.referenceCount != -1) { ++ ++cached.referenceCount; ++ } ++ ++ decrementReferenceCount(current); ++ ++ return cached; ++ } ++ ++ if (!current.remove(object)) { ++ return current; ++ } ++ ++ // we use get/put since we use a different key on put ++ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); ++ ++ if (ret == null) { ++ ret = new PooledObjectLinkedOpenHashSet<>(current); ++ current.add(object); ++ this.mapPool.put(ret, ret); ++ ret.referenceCount = 1; ++ } else { ++ if (ret.referenceCount != -1) { ++ ++ret.referenceCount; ++ } ++ current.add(object); ++ } ++ ++ current.updateRemoveCache(object, ret); ++ ++ decrementReferenceCount(current); ++ return ret; ++ } ++ ++ public static final class PooledObjectLinkedOpenHashSet implements Iterable { ++ ++ private static final WeakReference NULL_REFERENCE = new WeakReference(null); ++ ++ final ObjectLinkedOpenHashSet set; ++ int referenceCount; // -1 if special ++ int hash; // optimize hashcode ++ ++ // add cache ++ WeakReference lastAddObject = NULL_REFERENCE; ++ WeakReference> lastAddMap = NULL_REFERENCE; ++ ++ // remove cache ++ WeakReference lastRemoveObject = NULL_REFERENCE; ++ WeakReference> lastRemoveMap = NULL_REFERENCE; ++ ++ public PooledObjectLinkedOpenHashSet() { ++ this.set = new ObjectLinkedOpenHashSet<>(2, 0.6f); ++ } ++ ++ public PooledObjectLinkedOpenHashSet(final E single) { ++ this(); ++ this.referenceCount = -1; ++ this.add(single); ++ } ++ ++ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { ++ this.set = other.set.clone(); ++ this.hash = other.hash; ++ } ++ ++ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java ++ // generated by https://github.com/skeeto/hash-prospector ++ static int hash0(int x) { ++ x *= 0x36935555; ++ x ^= x >>> 16; ++ return x; ++ } ++ ++ public PooledObjectLinkedOpenHashSet getAddCache(final E element) { ++ final E currentAdd = this.lastAddObject.get(); ++ ++ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { ++ return null; ++ } ++ ++ final PooledObjectLinkedOpenHashSet map = this.lastAddMap.get(); ++ if (map == null || map.referenceCount == 0) { ++ // we need to ret null if ref count is zero as calling code will assume the map is in use ++ return null; ++ } ++ ++ return map; ++ } ++ ++ public PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { ++ final E currentRemove = this.lastRemoveObject.get(); ++ ++ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { ++ return null; ++ } ++ ++ final PooledObjectLinkedOpenHashSet map = this.lastRemoveMap.get(); ++ if (map == null || map.referenceCount == 0) { ++ // we need to ret null if ref count is zero as calling code will assume the map is in use ++ return null; ++ } ++ ++ return map; ++ } ++ ++ public void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { ++ this.lastAddObject = new WeakReference<>(element); ++ this.lastAddMap = new WeakReference<>(map); ++ } ++ ++ public void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { ++ this.lastRemoveObject = new WeakReference<>(element); ++ this.lastRemoveMap = new WeakReference<>(map); ++ } ++ ++ boolean add(final E element) { ++ boolean added = this.set.add(element); ++ ++ if (added) { ++ this.hash += hash0(element.hashCode()); ++ } ++ ++ return added; ++ } ++ ++ boolean remove(Object element) { ++ boolean removed = this.set.remove(element); ++ ++ if (removed) { ++ this.hash -= hash0(element.hashCode()); ++ } ++ ++ return removed; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return this.set.iterator(); ++ } ++ ++ @Override ++ public int hashCode() { ++ return this.hash; ++ } ++ ++ @Override ++ public boolean equals(final Object other) { ++ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { ++ return false; ++ } ++ if (this.referenceCount == 0) { ++ return other == this; ++ } else { ++ if (other == this) { ++ // Unfortunately we are never equal to our own instance while in use! ++ return false; ++ } ++ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); ++ } ++ } ++ ++ @Override ++ public String toString() { ++ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + ++ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index c00f7c60ce7b497d697d1abdf230f91f327e2113..190ddd4d9ef3472c33d46c2ead72fa0dc918054a 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -71,6 +71,7 @@ import net.minecraft.util.thread.ProcessorMailbox; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.MobCategory; + import net.minecraft.world.entity.ai.village.poi.PoiManager; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.level.ChunkPos; +@@ -127,7 +128,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final Int2ObjectMap entityMap; + private final Long2ByteMap chunkTypeCache; + private final Queue unloadQueue; private final Queue getUnloadQueueTasks() { return this.unloadQueue; } // Paper - OBFHELPER +- private int viewDistance; ++ int viewDistance; // Paper - private -> package private ++ public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper + + // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() + public final CallbackExecutor callbackExecutor = new CallbackExecutor(); +@@ -206,6 +208,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.overworldDataStorage = supplier; + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper + this.setViewDistance(i); ++ this.playerMobDistanceMap = this.level.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper ++ } ++ ++ public void updatePlayerMobTypeMap(Entity entity) { ++ if (!this.level.paperConfig.perPlayerMobSpawns) { ++ return; ++ } ++ int chunkX = (int)Math.floor(entity.getX()) >> 4; ++ int chunkZ = (int)Math.floor(entity.getZ()) >> 4; ++ int index = entity.getType().getEnumCreatureType().ordinal(); ++ ++ for (ServerPlayer player : this.playerMobDistanceMap.getPlayersInRange(chunkX, chunkZ)) { ++ ++player.mobCounts[index]; ++ } ++ } ++ ++ public int getMobCountNear(ServerPlayer entityPlayer, MobCategory enumCreatureType) { ++ return entityPlayer.mobCounts[enumCreatureType.ordinal()]; + } + + private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 5e0d55c3821b1769d20514a8a6c5c74477019778..eac5e799c4d26e53286a27c54b56899ba0b9ffb2 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -768,7 +768,22 @@ public class ServerChunkCache extends ChunkSource { + this.level.getProfiler().push("naturalSpawnCount"); + this.level.timings.countNaturalMobs.startTiming(); // Paper - timings + int l = this.distanceManager.getNaturalSpawnChunkCount(); +- NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk); ++ // Paper start - per player mob spawning ++ NaturalSpawner.SpawnState spawnercreature_d; // moved down ++ if (this.chunkMap.playerMobDistanceMap != null) { ++ // update distance map ++ this.level.timings.playerMobDistanceMapUpdate.startTiming(); ++ this.chunkMap.playerMobDistanceMap.update(this.level.players, this.chunkMap.viewDistance); ++ this.level.timings.playerMobDistanceMapUpdate.stopTiming(); ++ // re-set mob counts ++ for (ServerPlayer player : this.level.players) { ++ Arrays.fill(player.mobCounts, 0); ++ } ++ spawnercreature_d = NaturalSpawner.countMobs(l, this.level.getAllEntities(), this::getFullChunk, true); ++ } else { ++ spawnercreature_d = NaturalSpawner.countMobs(l, this.level.getAllEntities(), this::getFullChunk, false); ++ } ++ // Paper end + this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings + + this.lastSpawnState = spawnercreature_d; +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index d6cfe68be1a944ff5d5780666467f5fd8e2794e3..b0eed4e18fc183856613c05f378576eb19985c46 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -93,6 +93,7 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.HumanoidArm; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.MobCategory; + import net.minecraft.world.entity.NeutralMob; + import net.minecraft.world.entity.animal.horse.AbstractHorse; + import net.minecraft.world.entity.item.ItemEntity; +@@ -216,6 +217,11 @@ public class ServerPlayer extends Player implements ContainerListener { + public boolean queueHealthUpdatePacket = false; + public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; + // Paper end ++ // Paper start - mob spawning rework ++ public static final int ENUMCREATURETYPE_TOTAL_ENUMS = MobCategory.values().length; ++ public final int[] mobCounts = new int[ENUMCREATURETYPE_TOTAL_ENUMS]; // Paper ++ public final com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet cachedSingleMobDistanceMap; ++ // Paper end + + // CraftBukkit start + public String displayName; +@@ -254,6 +260,7 @@ public class ServerPlayer extends Player implements ContainerListener { + this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper + this.canPickUpLoot = true; + this.maxHealthCache = this.getMaxHealth(); ++ this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper + } + + // Yes, this doesn't match Vanilla, but it's the best we can do for now. +@@ -2058,6 +2065,7 @@ public class ServerPlayer extends Player implements ContainerListener { + + } + ++ public final SectionPos getPlayerMapSection() { return this.getLastSectionPos(); } // Paper - OBFHELPER + public SectionPos getLastSectionPos() { + return this.lastSectionPos; + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index e39d950783599b01271bdb7e67fe68b46af0c49c..ae50030df7512c56c552e800b74ef4c69ec6d6d2 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -426,6 +426,7 @@ public class EntityType { + return this.canSpawnFarFromPlayer; + } + ++ public final MobCategory getEnumCreatureType() { return this.getCategory(); } // Paper - OBFHELPER + public MobCategory getCategory() { + return this.category; + } +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index 0fb69f9194078e5e05e36ed909eb48424b6465b4..df271598f6036c8cab8a8811151a376dda46e44d 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -17,6 +17,7 @@ import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.FluidTags; + import net.minecraft.tags.Tag; +@@ -60,9 +61,14 @@ public final class NaturalSpawner { + }); + + public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkSource) { ++ // Paper start - add countMobs parameter ++ return countMobs(spawningChunkCount, entities, chunkSource, false); ++ } ++ public static NaturalSpawner.SpawnState countMobs(int i, Iterable iterable, NaturalSpawner.ChunkGetter spawnercreature_b, boolean countMobs) { ++ // Paper end - add countMobs parameter + PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator(); + Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); +- Iterator iterator = entities.iterator(); ++ Iterator iterator = iterable.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +@@ -89,7 +95,7 @@ public final class NaturalSpawner { + BlockPos blockposition = entity.blockPosition(); + long j = ChunkPos.asLong(blockposition.getX() >> 4, blockposition.getZ() >> 4); + +- chunkSource.query(j, (chunk) -> { ++ spawnercreature_b.query(j, (chunk) -> { + MobSpawnSettings.MobSpawnCost biomesettingsmobs_b = getRoughBiome(blockposition, chunk).getMobSettings().getMobSpawnCost(entity.getType()); + + if (biomesettingsmobs_b != null) { +@@ -97,11 +103,16 @@ public final class NaturalSpawner { + } + + object2intopenhashmap.addTo(enumcreaturetype, 1); ++ // Paper start ++ if (countMobs) { ++ ((ServerLevel)chunk.world).getChunkSource().chunkMap.updatePlayerMobTypeMap(entity); ++ } ++ // Paper end + }); + } + } + +- return new NaturalSpawner.SpawnState(spawningChunkCount, object2intopenhashmap, spawnercreatureprobabilities); ++ return new NaturalSpawner.SpawnState(i, object2intopenhashmap, spawnercreatureprobabilities); + } + + private static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) { +@@ -155,13 +166,31 @@ public final class NaturalSpawner { + continue; + } + +- if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (shouldSpawnAnimals || !enumcreaturetype.isPersistent()) && info.a(enumcreaturetype, limit)) { ++ // Paper start - only allow spawns upto the limit per chunk and update count afterwards ++ int currEntityCount = info.getEntityCountsByType().getInt(enumcreaturetype); ++ int k1 = limit * info.getSpawnerChunks() / NaturalSpawner.MAGIC_NUMBER; ++ int difference = k1 - currEntityCount; ++ ++ if (world.paperConfig.perPlayerMobSpawns) { ++ int minDiff = Integer.MAX_VALUE; ++ for (ServerPlayer entityplayer : world.getChunkSource().chunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) { ++ minDiff = Math.min(limit - world.getChunkSource().chunkMap.getMobCountNear(entityplayer, enumcreaturetype), minDiff); ++ } ++ difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff; ++ } ++ // Paper end ++ ++ // Paper start - per player mob spawning ++ if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (shouldSpawnAnimals || !enumcreaturetype.isPersistent()) && difference > 0) { + // CraftBukkit end +- spawnCategoryForChunk(enumcreaturetype, world, chunk, (entitytypes, blockposition, ichunkaccess) -> { ++ int spawnCount = spawnMobs(enumcreaturetype, world, chunk, (entitytypes, blockposition, ichunkaccess) -> { + return info.canSpawn(entitytypes, blockposition, ichunkaccess); + }, (entityinsentient, ichunkaccess) -> { + info.afterSpawn(entityinsentient, ichunkaccess); +- }); ++ }, ++ difference, world.paperConfig.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null); ++ info.getEntityCountsByType().mergeInt(enumcreaturetype, spawnCount, Integer::sum); ++ // Paper end - per player mob spawning + } + } + +@@ -170,31 +199,43 @@ public final class NaturalSpawner { + } + + public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { +- BlockPos blockposition = getRandomPosWithin(world, chunk); ++ // Paper start - add parameters and int ret type ++ spawnMobs(group, world, chunk, checker, runner, Integer.MAX_VALUE, null); ++ } ++ public static int spawnMobs(MobCategory enumcreaturetype, ServerLevel worldserver, LevelChunk chunk, NaturalSpawner.SpawnPredicate spawnercreature_c, NaturalSpawner.AfterSpawnCallback spawnercreature_a, int maxSpawns, Consumer trackEntity) { ++ // Paper end - add parameters and int ret type ++ BlockPos blockposition = getRandomPosWithin(worldserver, chunk); + + if (blockposition.getY() >= 1) { +- spawnCategoryForPosition(group, world, (ChunkAccess) chunk, blockposition, checker, runner); ++ return spawnMobsInternal(enumcreaturetype, worldserver, (ChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a, maxSpawns, trackEntity); + } ++ return 0; // Paper + } + + public static void spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { +- StructureFeatureManager structuremanager = world.structureFeatureManager(); +- ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); +- int i = pos.getY(); +- BlockState iblockdata = world.getTypeIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn +- +- if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn ++ // Paper start - add maxSpawns parameter and return spawned mobs ++ spawnMobsInternal(group, world, chunk, pos, checker, runner, Integer.MAX_VALUE, null); ++ } ++ public static int spawnMobsInternal(MobCategory enumcreaturetype, ServerLevel worldserver, ChunkAccess ichunkaccess, BlockPos blockposition, NaturalSpawner.SpawnPredicate spawnercreature_c, NaturalSpawner.AfterSpawnCallback spawnercreature_a, int maxSpawns, Consumer trackEntity) { ++ // Paper end - add maxSpawns parameter and return spawned mobs ++ StructureFeatureManager structuremanager = worldserver.structureFeatureManager(); ++ ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); ++ int i = blockposition.getY(); ++ BlockState iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn ++ int j = 0; // Paper - moved up ++ ++ if (iblockdata != null && !iblockdata.isRedstoneConductor(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn + BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); +- int j = 0; ++ // Paper - moved up + int k = 0; + + while (k < 3) { +- int l = pos.getX(); +- int i1 = pos.getZ(); ++ int l = blockposition.getX(); ++ int i1 = blockposition.getZ(); + boolean flag = true; + MobSpawnSettings.SpawnerData biomesettingsmobs_c = null; + SpawnGroupData groupdataentity = null; +- int j1 = Mth.ceil(world.random.nextFloat() * 4.0F); ++ int j1 = Mth.ceil(worldserver.random.nextFloat() * 4.0F); + int k1 = 0; + int l1 = 0; + +@@ -202,53 +243,58 @@ public final class NaturalSpawner { + if (l1 < j1) { + label53: + { +- l += world.random.nextInt(6) - world.random.nextInt(6); +- i1 += world.random.nextInt(6) - world.random.nextInt(6); ++ l += worldserver.random.nextInt(6) - worldserver.random.nextInt(6); ++ i1 += worldserver.random.nextInt(6) - worldserver.random.nextInt(6); + blockposition_mutableblockposition.set(l, i, i1); + double d0 = (double) l + 0.5D; + double d1 = (double) i1 + 0.5D; +- Player entityhuman = world.getNearestPlayer(d0, (double) i, d1, -1.0D, false); ++ Player entityhuman = worldserver.getNearestPlayer(d0, (double) i, d1, -1.0D, false); + + if (entityhuman != null) { + double d2 = entityhuman.distanceToSqr(d0, (double) i, d1); + +- if (isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2) && world.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn ++ if (isRightDistanceToPlayerAndSpawnPoint(worldserver, ichunkaccess, blockposition_mutableblockposition, d2) && worldserver.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn + if (biomesettingsmobs_c == null) { +- biomesettingsmobs_c = getRandomSpawnMobAt(world, structuremanager, chunkgenerator, group, world.random, (BlockPos) blockposition_mutableblockposition); ++ biomesettingsmobs_c = getRandomSpawnMobAt(worldserver, structuremanager, chunkgenerator, enumcreaturetype, worldserver.random, (BlockPos) blockposition_mutableblockposition); + if (biomesettingsmobs_c == null) { + break label53; + } + +- j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); ++ j1 = biomesettingsmobs_c.minCount + worldserver.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); + } + + // Paper start +- Boolean doSpawning = a(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); ++ Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); + if (doSpawning == null) { +- return; ++ return j; // Paper + } +- if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, ichunkaccess)) { + // Paper end +- Mob entityinsentient = getMobForSpawn(world, biomesettingsmobs_c.type); ++ Mob entityinsentient = getMobForSpawn(worldserver, biomesettingsmobs_c.type); + + + if (entityinsentient == null) { +- return; ++ return j; // Paper + } + +- entityinsentient.moveTo(d0, (double) i, d1, world.random.nextFloat() * 360.0F, 0.0F); +- if (isValidPositionForMob(world, entityinsentient, d2)) { +- groupdataentity = entityinsentient.finalizeSpawn(world, world.getCurrentDifficultyAt(entityinsentient.blockPosition()), MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); ++ entityinsentient.moveTo(d0, (double) i, d1, worldserver.random.nextFloat() * 360.0F, 0.0F); ++ if (isValidPositionForMob(worldserver, entityinsentient, d2)) { ++ groupdataentity = entityinsentient.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(entityinsentient.blockPosition()), MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); + // CraftBukkit start +- world.addAllEntities(entityinsentient, SpawnReason.NATURAL); ++ worldserver.addAllEntities(entityinsentient, SpawnReason.NATURAL); + if (!entityinsentient.removed) { +- ++j; ++ ++j; // Paper - force diff on name change - we expect this to be the total amount spawned + ++k1; +- runner.run(entityinsentient, chunk); ++ spawnercreature_a.run(entityinsentient, ichunkaccess); ++ // Paper start ++ if (trackEntity != null) { ++ trackEntity.accept(entityinsentient); ++ } ++ // Paper end + } + // CraftBukkit end +- if (j >= entityinsentient.getMaxSpawnClusterSize()) { +- return; ++ if (j >= entityinsentient.getMaxSpawnClusterSize() || j >= maxSpawns) { // Paper ++ return j; // Paper + } + + if (entityinsentient.isMaxGroupSizeReached(k1)) { +@@ -270,6 +316,7 @@ public final class NaturalSpawner { + } + + } ++ return j; // Paper + } + + private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) { +@@ -510,8 +557,8 @@ public final class NaturalSpawner { + + public static class SpawnState { + +- private final int spawnableChunkCount; +- private final Object2IntOpenHashMap mobCategoryCounts; ++ private final int spawnableChunkCount; final int getSpawnerChunks() { return this.spawnableChunkCount; } // Paper - OBFHELPER ++ private final Object2IntOpenHashMap mobCategoryCounts; final Object2IntMap getEntityCountsByType() { return this.mobCategoryCounts; } // Paper - OBFHELPER + private final PotentialCalculator spawnPotential; + private final Object2IntMap unmodifiableMobCategoryCounts; + @Nullable +@@ -572,7 +619,7 @@ public final class NaturalSpawner { + + // CraftBukkit start + private boolean a(MobCategory enumcreaturetype, int limit) { +- int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; ++ int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; // Paper - diff on change, needed in the spawn method + // CraftBukkit end + + return this.mobCategoryCounts.getInt(enumcreaturetype) < i; diff --git a/Remapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch b/Remapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch new file mode 100644 index 0000000000..32aa3ddc1d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Mon, 19 Aug 2019 19:42:35 +0500 +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 046a05925739005080af35c4be984303b575bf68..f8917123547615dd624e3e428ec1bf6450c7b7d8 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3198,15 +3198,18 @@ public abstract class LivingEntity extends Entity { + this.entityData.set(LivingEntity.DATA_LIVING_ENTITY_FLAGS, (byte) j); + } + +- public void startUsingItem(InteractionHand hand) { +- ItemStack itemstack = this.getItemInHand(hand); ++ // Paper start -- OBFHELPER and forwarder to method with forceUpdate parameter ++ public void startUsingItem(InteractionHand hand) { this.updateActiveItem(hand, false); } ++ public void updateActiveItem(InteractionHand enumhand, boolean forceUpdate) { ++ // Paper end ++ ItemStack itemstack = this.getItemInHand(enumhand); + +- if (!itemstack.isEmpty() && !this.isUsingItem()) { ++ if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag + this.useItem = itemstack; + this.useItemRemaining = itemstack.getUseDuration(); + if (!this.level.isClientSide) { + this.setLivingEntityFlag(1, true); +- this.setLivingEntityFlag(2, hand == InteractionHand.OFF_HAND); ++ this.setLivingEntityFlag(2, enumhand == InteractionHand.OFF_HAND); + } + + } +@@ -3279,6 +3282,7 @@ public abstract class LivingEntity extends Entity { + this.releaseUsingItem(); + } else { + if (!this.useItem.isEmpty() && this.isUsingItem()) { ++ this.updateActiveItem(this.getUsedItemHand(), true); // Paper + this.triggerItemUseEffects(this.useItem, 16); + // CraftBukkit start - fire PlayerItemConsumeEvent + ItemStack itemstack; +@@ -3313,8 +3317,8 @@ public abstract class LivingEntity extends Entity { + } + + this.stopUsingItem(); +- // Paper start - if the replacement is anything but the default, update the client inventory +- if (this instanceof ServerPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { ++ // Paper start ++ if (this instanceof ServerPlayer) { + ((ServerPlayer) this).getBukkitEntity().updateInventory(); + } + // Paper end diff --git a/Remapped-Spigot-Server-Patches/0376-Generator-Settings.patch b/Remapped-Spigot-Server-Patches/0376-Generator-Settings.patch new file mode 100644 index 0000000000..fe0b780b55 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0376-Generator-Settings.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 2 Mar 2016 02:17:54 -0600 +Subject: [PATCH] Generator Settings + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6aec502eb529d4090306e12e837117cde7e114eb..290e49cf0077909ad7ab8127c01ef93cf7b70b51 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -570,4 +570,9 @@ public class PaperWorldConfig { + private void perPlayerMobSpawns() { + perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); + } ++ ++ public boolean generateFlatBedrock; ++ private void generatorSettings() { ++ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index e6303cdb433ee2b6782e2a0bd6b03e4f6ecb18ba..36c7ab3919d8818af96d50170aeb431051c5aabf 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -25,6 +25,18 @@ import org.apache.logging.log4j.LogManager; + + public interface ChunkAccess extends BlockGetter, FeatureAccess { + ++ // Paper start ++ default boolean generateFlatBedrock() { ++ if (this instanceof ProtoChunk) { ++ return ((ProtoChunk)this).world.paperConfig.generateFlatBedrock; ++ } else if (this instanceof LevelChunk) { ++ return ((LevelChunk)this).world.paperConfig.generateFlatBedrock; ++ } else { ++ return false; ++ } ++ } ++ // Paper end ++ + BlockState getType(final int x, final int y, final int z); // Paper + @Nullable + BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index 87fd585141ad9818fca0b697cb4c87248fe7ce11..5a94464b9628b74eefa1c1d8514cf267f4c8a11d 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -64,7 +64,7 @@ public class ProtoChunk implements ChunkAccess { + private long inhabitedTime; + private final Map carvingMasks; + private volatile boolean isLightCorrect; +- private final Level world; // Paper - Anti-Xray - Add world ++ final Level world; // Paper - Anti-Xray - Add world // Paper - private -> default + + // Paper start - Anti-Xray - Add world + @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { this(pos, upgradeData, null); } // Notice for updates: Please make sure this constructor isn't used anywhere +diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +index b38a9c87fc996bd3107c38f6446a687fd093c617..04adec255e4650ead8d80bee32a681c98686fb95 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +@@ -408,8 +408,8 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + int i = chunk.getPos().getMinBlockX(); + int j = chunk.getPos().getMinBlockZ(); + NoiseGeneratorSettings generatorsettingbase = (NoiseGeneratorSettings) this.settings.get(); +- int k = generatorsettingbase.getBedrockFloorPosition(); +- int l = this.height - 1 - generatorsettingbase.getBedrockRoofPosition(); ++ int k = generatorsettingbase.getBedrockFloorPosition(); final int floorHeight = k; // Paper ++ int l = this.height - 1 - generatorsettingbase.getBedrockRoofPosition(); final int roofHeight = l; // Paper + boolean flag = true; + boolean flag1 = l + 4 >= 0 && l < this.height; + boolean flag2 = k + 4 >= 0 && k < this.height; +@@ -423,7 +423,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + + if (flag1) { + for (i1 = 0; i1 < 5; ++i1) { +- if (i1 <= random.nextInt(5)) { ++ if (i1 <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof + chunk.setBlockState(blockposition_mutableblockposition.set(blockposition.getX(), l - i1, blockposition.getZ()), Blocks.BEDROCK.defaultBlockState(), false); + } + } +@@ -431,7 +431,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + + if (flag2) { + for (i1 = 4; i1 >= 0; --i1) { +- if (i1 <= random.nextInt(5)) { ++ if (i1 <= (chunk.generateFlatBedrock() ? floorHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor + chunk.setBlockState(blockposition_mutableblockposition.set(blockposition.getX(), k + i1, blockposition.getZ()), Blocks.BEDROCK.defaultBlockState(), false); + } + } diff --git a/Remapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch b/Remapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch new file mode 100644 index 0000000000..c50817dd4f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 24 Sep 2019 16:03:00 -0700 +Subject: [PATCH] Fix MC-161754 + +Fixes https://github.com/PaperMC/Paper/issues/2580 + +We can use an entity valid check since this method is invoked for +each inventory iteraction (thanks to CB) and on player tick (vanilla). + +diff --git a/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java b/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java +index 7246b3a84415e303591adb08d81362201deebfce..e0237e821b2c31ba68168fddf1c1a4ebfcf10ca7 100644 +--- a/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java +@@ -85,7 +85,7 @@ public class HorseInventoryMenu extends AbstractContainerMenu { + + @Override + public boolean stillValid(Player player) { +- return this.horseContainer.stillValid(player) && this.horse.isAlive() && this.horse.distanceTo((Entity) player) < 8.0F; ++ return this.horseContainer.stillValid(player) && (this.horse.isAlive() && this.horse.valid) && this.horse.distanceTo((Entity) player) < 8.0F; // Paper - Fix MC-161754 + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch b/Remapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch new file mode 100644 index 0000000000..439bca032a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: wea_ondara +Date: Thu, 10 Oct 2019 11:29:42 +0200 +Subject: [PATCH] Performance improvement for Chunk.getEntities + +This patch aims to reduce performance cost used by collecting the +entities of a chunk. Previously the entitySlices were copied into an +extra array with List.toArray() with is a costly and unneccessary +operation. This patch will reduce the load of plugins which for example +implement custom moblimits and depend on Chunk.getEntities(). + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +index 74bad15034d9d55fb70931f38868f812160c6305..0f45f4b2486e910d11fd94b260bcd68e49eae31e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +@@ -116,14 +116,14 @@ public class CraftChunk implements Chunk { + Entity[] entities = new Entity[count]; + + for (int i = 0; i < 16; i++) { +- +- for (Object obj : chunk.entitySlices[i].toArray()) { +- if (!(obj instanceof net.minecraft.world.entity.Entity)) { ++ // Paper start - speed up (was with chunk.entitySlices[i].toArray() and cast checks which costs a lot of performance if called often) ++ for (net.minecraft.world.entity.Entity entity : chunk.entitySlices[i]) { ++ if (entity == null) { + continue; + } +- +- entities[index++] = ((net.minecraft.world.entity.Entity) obj).getBukkitEntity(); ++ entities[index++] = entity.getBukkitEntity(); + } ++ // Paper end + } + + return entities; diff --git a/Remapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/Remapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch new file mode 100644 index 0000000000..548deb2cdf --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MisterErwin +Date: Wed, 30 Oct 2019 16:57:54 +0100 +Subject: [PATCH] Fix spawning of hanging entities that are not ItemFrames and + can not face UP or DOWN + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 52444619a4bae80a12bf296fbe07fa811adf806e..fb74bdcf4c2935b56e92717cc5a1504fbc853d0a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1868,7 +1868,12 @@ public class CraftWorld implements World { + height = 9; + } + +- BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; ++ // Paper start - In addition to d65a2576e40e58c8e446b330febe6799d13a604f do not check UP/DOWN for non item frames ++ // BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; ++ BlockFace[] faces = (ItemFrame.class.isAssignableFrom(clazz)) ++ ? new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN} ++ : new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH}; ++ // Paper end + final BlockPos pos = new BlockPos(x, y, z); + for (BlockFace dir : faces) { + net.minecraft.world.level.block.state.BlockState nmsBlock = world.getBlockState(pos.relative(CraftBlock.blockFaceToNotch(dir))); diff --git a/Remapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch b/Remapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch new file mode 100644 index 0000000000..9cf110529d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 20 Apr 2019 19:47:34 -0500 +Subject: [PATCH] Expose the internal current tick + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 96a3a4d89df858d4e46a36f110dd9ad3a2061433..3c0ba80bbba19f3725013e118cecdbac5612deec 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2363,5 +2363,10 @@ public final class CraftServer implements Server { + } + return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); + } ++ ++ @Override ++ public int getCurrentTick() { ++ return net.minecraft.server.MinecraftServer.currentTick; ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/Remapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch new file mode 100644 index 0000000000..169ff964a9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 9 Oct 2019 21:51:43 -0500 +Subject: [PATCH] Fix stuck in sneak when changing worlds (MC-10657) + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index b0eed4e18fc183856613c05f378576eb19985c46..2ef273e3b917803f3e2ac3c6a22d92a15b9eb71a 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1070,6 +1070,8 @@ public class ServerPlayer extends Player implements ContainerListener { + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; + ++ setShiftKeyDown(false); // Paper - fix MC-10657 ++ + // CraftBukkit start + PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); + this.level.getCraftServer().getPluginManager().callEvent(changeEvent); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index e6eebb8f6f48cc55fc8fb114c959b8fbec4b8472..dfdde9722bc0d83916779014b7718eef2c01b3db 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -842,6 +842,8 @@ public abstract class PlayerList { + entityplayer.connection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobEffect)); + } + ++ entityplayer.setShiftKeyDown(false); // Paper - fix MC-10657 ++ + // Fire advancement trigger + entityplayer.triggerDimensionChangeTriggers(((CraftWorld) fromWorld).getHandle()); + diff --git a/Remapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch b/Remapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch new file mode 100644 index 0000000000..2e772d88a3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 9 Oct 2019 21:46:15 -0500 +Subject: [PATCH] Add option to disable pillager patrols + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 290e49cf0077909ad7ab8127c01ef93cf7b70b51..e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -575,4 +575,9 @@ public class PaperWorldConfig { + private void generatorSettings() { + generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); + } ++ ++ public boolean disablePillagerPatrols = false; ++ private void pillagerSettings() { ++ disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +index caadd1a0fa6c4c446f84629088890a09e29622d9..48efe133d294bb1b17e8ac8b44eea8a29f15845f 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +@@ -26,6 +26,7 @@ public class PatrolSpawner implements CustomSpawner { + + @Override + public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { ++ if (world.paperConfig.disablePillagerPatrols) return 0; // Paper + if (!spawnMonsters) { + return 0; + } else if (!world.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) { diff --git a/Remapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/Remapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch new file mode 100644 index 0000000000..3d4d87429f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lukasz Derlatka +Date: Mon, 11 Nov 2019 16:08:13 +0100 +Subject: [PATCH] Fix AssertionError when player hand set to empty type + +Fixes an AssertionError when setting the player's item in hand to null or a new ItemStack of Air in PlayerInteractEvent +Fixes GH-2718 + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index e45690b6197335ed1c07fa04c39b311b401724d7..2b79413bb8a592a7b7093e11d3a0cce895286c8f 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1706,6 +1706,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 + return; + } ++ // Paper start ++ itemstack = this.player.getItemInHand(enumhand); ++ if (itemstack.isEmpty()) return; ++ // Paper end + InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); + + if (enuminteractionresult.shouldSwing()) { +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index f8917123547615dd624e3e428ec1bf6450c7b7d8..b49d4772932a58852b3195f5f56ff93dbcabf766 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -2153,6 +2153,7 @@ public abstract class LivingEntity extends Entity { + return predicate.test(this.getMainHandItem().getItem()) || predicate.test(this.getOffhandItem().getItem()); + } + ++ public final ItemStack getItemInHand(InteractionHand enumhand) { return this.getItemInHand(enumhand); } // Paper - OBFHELPER + public ItemStack getItemInHand(InteractionHand hand) { + if (hand == InteractionHand.MAIN_HAND) { + return this.getItemBySlot(EquipmentSlot.MAINHAND); diff --git a/Remapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch b/Remapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch new file mode 100644 index 0000000000..886004a317 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch @@ -0,0 +1,351 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 03:11:03 -0500 +Subject: [PATCH] PlayerLaunchProjectileEvent + + +diff --git a/src/main/java/net/minecraft/world/InteractionResultHolder.java b/src/main/java/net/minecraft/world/InteractionResultHolder.java +index 3bc22b977e00c1901a9025112e354e59fcc08a74..c12e2a65d30ca22db0c522e4b245009bcc38c4f4 100644 +--- a/src/main/java/net/minecraft/world/InteractionResultHolder.java ++++ b/src/main/java/net/minecraft/world/InteractionResultHolder.java +@@ -10,6 +10,7 @@ public class InteractionResultHolder { + this.object = value; + } + ++ public InteractionResult getResult() { return this.getResult(); } // Paper - OBFHELPER + public InteractionResult getResult() { + return this.result; + } +diff --git a/src/main/java/net/minecraft/world/item/EggItem.java b/src/main/java/net/minecraft/world/item/EggItem.java +index d2c4241104343a2d2283c358ab2247e333cf0dbf..5d03dcaf79a14946934a6732c94a195d3d65c56d 100644 +--- a/src/main/java/net/minecraft/world/item/EggItem.java ++++ b/src/main/java/net/minecraft/world/item/EggItem.java +@@ -25,21 +25,35 @@ public class EggItem extends Item { + + entityegg.setItem(itemstack); + entityegg.shootFromRotation(user, user.xRot, user.yRot, 0.0F, 1.5F, 1.0F); +- // CraftBukkit start +- if (!world.addFreshEntity(entityegg)) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityegg.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entityegg)) { ++ if (event.shouldConsume() && !user.abilities.instabuild) { ++ itemstack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ } else { + if (user instanceof net.minecraft.server.level.ServerPlayer) { + ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); + } +- return InteractionResultHolder.fail(itemstack); ++ return new InteractionResultHolder(net.minecraft.world.InteractionResult.FAIL, itemstack); + } +- // CraftBukkit end ++ // Paper end ++ ++ + } + world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (EggItem.random.nextFloat() * 0.4F + 0.8F)); // CraftBukkit - from above + +- user.awardStat(Stats.ITEM_USED.get(this)); +- if (!user.abilities.instabuild) { +- itemstack.shrink(1); ++ /* // Paper start - moved up ++ entityhuman.b(StatisticList.ITEM_USED.b(this)); ++ if (!entityhuman.abilities.canInstantlyBuild) { ++ itemstack.subtract(1); + } ++ */ // Paper end + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/EnderpearlItem.java b/src/main/java/net/minecraft/world/item/EnderpearlItem.java +index 347e95cc393e773de98b74e18cebbe05f612bdf6..a57c59b330766a2c784ddb7431719e9c1cc2fca8 100644 +--- a/src/main/java/net/minecraft/world/item/EnderpearlItem.java ++++ b/src/main/java/net/minecraft/world/item/EnderpearlItem.java +@@ -25,22 +25,37 @@ public class EnderpearlItem extends Item { + + entityenderpearl.setItem(itemstack); + entityenderpearl.shootFromRotation(user, user.xRot, user.yRot, 0.0F, 1.5F, 1.0F); +- if (!world.addFreshEntity(entityenderpearl)) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityenderpearl.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entityenderpearl)) { ++ if (event.shouldConsume() && !user.abilities.instabuild) { ++ itemstack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ user.getCooldowns().addCooldown(this, 20); ++ } else { ++ // Paper end + if (user instanceof net.minecraft.server.level.ServerPlayer) { + ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); + } +- return InteractionResultHolder.fail(itemstack); ++ return new InteractionResultHolder(net.minecraft.world.InteractionResult.FAIL, itemstack); + } + } + +- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (EnderpearlItem.random.nextFloat() * 0.4F + 0.8F)); +- user.getCooldowns().addCooldown(this, 20); +- // CraftBukkit end +- +- user.awardStat(Stats.ITEM_USED.get(this)); +- if (!user.abilities.instabuild) { +- itemstack.shrink(1); +- } ++ // Paper start - moved up ++// world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F)); ++// entityhuman.getCooldownTracker().setCooldown(this, 20); ++// // CraftBukkit end ++// ++// entityhuman.b(StatisticList.ITEM_USED.b(this)); ++// if (!entityhuman.abilities.canInstantlyBuild) { ++// itemstack.subtract(1); ++// } ++ // Paper end - moved up + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java +index 032c476892c58a873242b00ca71fe084c719dcaa..0bd65165eacf6a54cdcc348991cf9adb44077bee 100644 +--- a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java ++++ b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java +@@ -1,10 +1,13 @@ + package net.minecraft.world.item; + ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.world.InteractionHand; ++import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.ThrownExperienceBottle; + import net.minecraft.world.level.Level; +@@ -24,19 +27,38 @@ public class ExperienceBottleItem extends Item { + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { + ItemStack itemstack = user.getItemInHand(hand); + +- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (ExperienceBottleItem.random.nextFloat() * 0.4F + 0.8F)); ++ //world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); // Paper - moved down + if (!world.isClientSide) { + ThrownExperienceBottle entitythrownexpbottle = new ThrownExperienceBottle(world, user); + + entitythrownexpbottle.setItem(itemstack); + entitythrownexpbottle.shootFromRotation(user, user.xRot, user.yRot, -20.0F, 0.7F, 1.0F); +- world.addFreshEntity(entitythrownexpbottle); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitythrownexpbottle.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entitythrownexpbottle)) { ++ if (event.shouldConsume() && !user.abilities.instabuild) { ++ itemstack.shrink(1); ++ } else if (user instanceof ServerPlayer) { ++ ((ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ } else { ++ if (user instanceof ServerPlayer) { ++ ((ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ return new InteractionResultHolder(InteractionResult.FAIL, itemstack); ++ } ++ // Paper end + } + +- user.awardStat(Stats.ITEM_USED.get(this)); +- if (!user.abilities.instabuild) { +- itemstack.shrink(1); ++ /* // Paper start - moved up ++ entityhuman.b(StatisticList.ITEM_USED.b(this)); ++ if (!entityhuman.abilities.canInstantlyBuild) { ++ itemstack.subtract(1); + } ++ */ // Paper end + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index 28cffbe299acccc59c34d5dbd2cf458704be5ee5..4a70582bada607e1efcd826d58d725a0cc95e3c3 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -3,6 +3,7 @@ package net.minecraft.world.item; + import java.util.Arrays; + import java.util.Comparator; + import net.minecraft.core.Direction; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.InteractionHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; +@@ -29,8 +30,12 @@ public class FireworkRocketItem extends Item { + FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, context.getPlayer(), vec3d.x + (double) enumdirection.getStepX() * 0.15D, vec3d.y + (double) enumdirection.getStepY() * 0.15D, vec3d.z + (double) enumdirection.getStepZ() * 0.15D, itemstack); + entityfireworks.spawningEntity = context.getPlayer().getUUID(); // Paper + +- world.addFreshEntity(entityfireworks); +- itemstack.shrink(1); ++ // Paper start - PlayerLaunchProjectileEvent ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) context.getPlayer().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); ++ if (!event.callEvent() || !world.addFreshEntity(entityfireworks)) return InteractionResult.PASS; ++ if (event.shouldConsume() && !context.getPlayer().abilities.instabuild) itemstack.shrink(1); ++ else if (context.getPlayer() instanceof ServerPlayer) ((ServerPlayer) context.getPlayer()).getBukkitEntity().updateInventory(); ++ // Paper end + } + + return InteractionResult.sidedSuccess(world.isClientSide); +@@ -50,9 +55,9 @@ public class FireworkRocketItem extends Item { + if (event.callEvent() && world.addFreshEntity(entityfireworks)) { + if (event.shouldConsume() && !user.abilities.instabuild) { + itemstack.shrink(1); +- } else ((EntityPlayer) user).getBukkitEntity().updateInventory(); +- } else if (user instanceof EntityPlayer) { +- ((EntityPlayer) user).getBukkitEntity().updateInventory(); ++ } else ((ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } else if (user instanceof ServerPlayer) { ++ ((ServerPlayer) user).getBukkitEntity().updateInventory(); + } + // Paper end + } +diff --git a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java +index 813a9c8464e253b9baa15af666111be104b4aa29..1957561f83645a57df5925b4b0b54153ebf4aeef 100644 +--- a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java ++++ b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java +@@ -3,6 +3,7 @@ package net.minecraft.world.item; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.InteractionHand; ++import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; +@@ -15,7 +16,12 @@ public class LingeringPotionItem extends ThrowablePotionItem { + + @Override + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { +- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.LINGERING_POTION_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (LingeringPotionItem.random.nextFloat() * 0.4F + 0.8F)); +- return super.use(world, user, hand); ++ // Paper start ++ InteractionResultHolder wrapper = super.use(world, user, hand); ++ if (wrapper.getResult() != InteractionResult.FAIL) { ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.LINGERING_POTION_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (LingeringPotionItem.random.nextFloat() * 0.4F + 0.8F)); ++ } ++ return wrapper; ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/item/SnowballItem.java b/src/main/java/net/minecraft/world/item/SnowballItem.java +index 50adbfc5d57b2b5f25c0efdc51da1701197c66e6..b053d105a1513a6b138972cdb9d28116fc6b8c81 100644 +--- a/src/main/java/net/minecraft/world/item/SnowballItem.java ++++ b/src/main/java/net/minecraft/world/item/SnowballItem.java +@@ -26,14 +26,20 @@ public class SnowballItem extends Item { + + entitysnowball.setItem(itemstack); + entitysnowball.shootFromRotation(user, user.xRot, user.yRot, 0.0F, 1.5F, 1.0F); +- if (world.addFreshEntity(entitysnowball)) { +- if (!user.abilities.instabuild) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entitysnowball)) { ++ if (event.shouldConsume() && !user.abilities.instabuild) { ++ // Paper end + itemstack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { // Paper ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper + } + + world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (SnowballItem.random.nextFloat() * 0.4F + 0.8F)); +- } else if (user instanceof net.minecraft.server.level.ServerPlayer) { +- ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } else { // Paper ++ if (user instanceof net.minecraft.server.level.ServerPlayer) ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper ++ return new InteractionResultHolder(net.minecraft.world.InteractionResult.FAIL, itemstack); // Paper + } + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/item/SplashPotionItem.java b/src/main/java/net/minecraft/world/item/SplashPotionItem.java +index 9c7547988fe90e9b87868636a1c1a7b4dff32622..6d3ab7fea3b5ebba4c304cdec5dd36dbea31f2c6 100644 +--- a/src/main/java/net/minecraft/world/item/SplashPotionItem.java ++++ b/src/main/java/net/minecraft/world/item/SplashPotionItem.java +@@ -3,6 +3,7 @@ package net.minecraft.world.item; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.InteractionHand; ++import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; +@@ -15,7 +16,12 @@ public class SplashPotionItem extends ThrowablePotionItem { + + @Override + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { ++ // Paper start ++ InteractionResultHolder wrapper = super.use(world, user, hand); ++ if (wrapper.getResult() != InteractionResult.FAIL) { + world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SPLASH_POTION_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (SplashPotionItem.random.nextFloat() * 0.4F + 0.8F)); +- return super.use(world, user, hand); ++ } ++ return wrapper; ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java +index 3615bc9222db4489189537f7f5d7a7d338053d6d..e12c7ebc0a4ff4f132512dc1677db7f79db41b03 100644 +--- a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java ++++ b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java +@@ -1,7 +1,9 @@ + package net.minecraft.world.item; + ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.stats.Stats; + import net.minecraft.world.InteractionHand; ++import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.ThrownPotion; +@@ -22,13 +24,31 @@ public class ThrowablePotionItem extends PotionItem { + + entitypotion.setItem(itemstack); + entitypotion.shootFromRotation(user, user.xRot, user.yRot, -20.0F, 0.5F, 1.0F); +- world.addFreshEntity(entitypotion); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitypotion.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entitypotion)) { ++ if (event.shouldConsume() && !user.abilities.instabuild) { ++ itemstack.shrink(1); ++ } else if (user instanceof ServerPlayer) { ++ ((ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ } else { ++ if (user instanceof ServerPlayer) { ++ ((ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ return new InteractionResultHolder(InteractionResult.FAIL, itemstack); ++ } ++ // Paper end + } + +- user.awardStat(Stats.ITEM_USED.get(this)); +- if (!user.abilities.instabuild) { +- itemstack.shrink(1); ++ /* // Paper start - moved up ++ entityhuman.b(StatisticList.ITEM_USED.b(this)); ++ if (!entityhuman.abilities.canInstantlyBuild) { ++ itemstack.subtract(1); + } ++ */ // Paper end + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } diff --git a/Remapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch b/Remapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch new file mode 100644 index 0000000000..509fc426f4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BlackHole +Date: Sun, 15 Dec 2019 19:12:39 +0100 +Subject: [PATCH] Add CraftMagicNumbers.isSupportedApiVersion() + + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 21052d0e88351b075733331d71e07b086354b820..86b319337fc41a09dd45df466df60cadaed1343f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -373,6 +373,11 @@ public final class CraftMagicNumbers implements UnsafeValues { + public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { + return new com.destroystokyo.paper.PaperVersionFetcher(); + } ++ ++ @Override ++ public boolean isSupportedApiVersion(String apiVersion) { ++ return apiVersion != null && SUPPORTED_API.contains(apiVersion); ++ } + // Paper end + + /** diff --git a/Remapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/Remapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch new file mode 100644 index 0000000000..32b045db49 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Callahan +Date: Mon, 13 Jan 2020 23:47:28 -0600 +Subject: [PATCH] Prevent sync chunk loads when villagers try to find beds + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java +index 5151c794985a135d3bd794bbafdf524ab9f670de..9a582fb4b96b2d0406cc86e473e8bf8c4e488e37 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java +@@ -46,7 +46,8 @@ public class SleepInBed extends Behavior { + } + } + +- BlockState iblockdata = world.getBlockState(globalpos.getBlockPosition()); ++ BlockState iblockdata = world.getTypeIfLoaded(globalpos.getBlockPosition()); // Paper ++ if (iblockdata == null) { return false; } // Paper + + return globalpos.getBlockPosition().a((Position) entity.position(), 2.0D) && iblockdata.getBlock().is((Tag) BlockTags.BEDS) && !(Boolean) iblockdata.getValue(BedBlock.OCCUPIED); + } diff --git a/Remapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch b/Remapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch new file mode 100644 index 0000000000..27d343fa11 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 18 Dec 2019 22:21:35 -0600 +Subject: [PATCH] MC-145656 Fix Follow Range Initial Target + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5..edda2121f8c1046478beaa77030ebb36d403b334 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -580,4 +580,9 @@ public class PaperWorldConfig { + private void pillagerSettings() { + disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); + } ++ ++ public boolean entitiesTargetWithFollowRange = false; ++ private void entitiesTargetWithFollowRange() { ++ entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java +index 7bba2ac71a3cd34a06ec865a3c1828b10decd644..93845edab0e1b0e2ad300cad051b0182cadd46e5 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java +@@ -32,6 +32,7 @@ public class NearestAttackableTargetGoal extends TargetG + this.randomInterval = reciprocalChance; + this.setFlags(EnumSet.of(Goal.Flag.TARGET)); + this.targetConditions = (new TargetingConditions()).range(this.getFollowDistance()).selector(targetPredicate); ++ if (mob.level.paperConfig.entitiesTargetWithFollowRange) this.targetConditions.useFollowRange(); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java +index 1714507fa744b2767e8a66cdb5db7f43c21f5c56..e1a0104a3b52990a83e7732491029d8a20976dc3 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java ++++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java +@@ -4,6 +4,8 @@ import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.ai.attributes.AttributeInstance; ++import net.minecraft.world.entity.ai.attributes.Attributes; + + public class TargetingConditions { + +@@ -82,7 +84,7 @@ public class TargetingConditions { + + if (this.range > 0.0D) { + double d0 = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D; +- double d1 = Math.max(this.range * d0, 2.0D); ++ double d1 = Math.max((useFollowRange ? getFollowRange(baseEntity) : this.range) * d0, 2.0D); // Paper + double d2 = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); + + if (d2 > d1 * d1) { +@@ -98,4 +100,18 @@ public class TargetingConditions { + return true; + } + } ++ ++ // Paper start ++ private boolean useFollowRange = false; ++ ++ public TargetingConditions useFollowRange() { ++ this.useFollowRange = true; ++ return this; ++ } ++ ++ private double getFollowRange(LivingEntity entityliving) { ++ AttributeInstance attributeinstance = entityliving.getAttribute(Attributes.FOLLOW_RANGE); ++ return attributeinstance == null ? 16.0D : attributeinstance.getValue(); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch b/Remapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch new file mode 100644 index 0000000000..5d342ad554 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch @@ -0,0 +1,605 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 27 Apr 2016 22:09:52 -0400 +Subject: [PATCH] Optimize Hoppers + +* Removes unnecessary extra calls to .update() that are very expensive +* Lots of itemstack cloning removed. Only clone if the item is actually moved +* Return true when a plugin cancels inventory move item event instead of false, as false causes pulls to cycle through all items. + However, pushes do not exhibit the same behavior, so this is not something plugins could of been relying on. +* Add option (Default on) to cooldown hoppers when they fail to move an item due to full inventory +* Skip subsequent InventoryMoveItemEvents if a plugin does not use the item after first event fire for an iteration +* Don't check for Entities with Inventories if the block above us is also occluding (not just Inventoried) +* Remove Streams from Item Suck In and restore restore 1.12 AABB checks which is simpler and no voxel allocations (was doing TWO Item Suck ins) + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index edda2121f8c1046478beaa77030ebb36d403b334..7fbd501d70dccf869a4454e2789a5d68f2e15754 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -585,4 +585,13 @@ public class PaperWorldConfig { + private void entitiesTargetWithFollowRange() { + entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); + } ++ ++ public boolean cooldownHopperWhenFull = true; ++ public boolean disableHopperMoveEvents = false; ++ private void hopperOptimizations() { ++ cooldownHopperWhenFull = getBoolean("hopper.cooldown-when-full", cooldownHopperWhenFull); ++ log("Cooldown Hoppers when Full: " + (cooldownHopperWhenFull ? "enabled" : "disabled")); ++ disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); ++ log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 753e6f609189c589514739bea80007bace3c89d2..7038897b8fb4c18ca97b95a3b24c30b40b62b005 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -131,6 +131,7 @@ import net.minecraft.world.level.LevelSettings; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.biome.BiomeSource; + import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.entity.HopperBlockEntity; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.dimension.DimensionType; +@@ -1360,6 +1361,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper ++ HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + + this.profiler.push(() -> { + return worldserver + " " + worldserver.dimension().location(); +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 02bfa4fb8055e60a84e878ffbf18303c0ee25b1d..ac996d581925c8f92832009945c766962e5b51c5 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -538,11 +538,12 @@ public final class ItemStack { + return this.getItem().interactLivingEntity(this, user, entity, hand); + } + +- public ItemStack copy() { +- if (this.isEmpty()) { ++ public ItemStack copy() { return cloneItemStack(false); } // Paper ++ public ItemStack cloneItemStack(boolean origItem) { // Paper ++ if (!origItem && this.isEmpty()) { // Paper + return ItemStack.EMPTY; + } else { +- ItemStack itemstack = new ItemStack(this.getItem(), this.count); ++ ItemStack itemstack = new ItemStack(origItem ? this.item : this.getItem(), this.count); // Paper + + itemstack.setPopTime(this.getPopTime()); + if (this.tag != null) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 3e2cd6c7a34c1a792d7346019a8b039d1f4a7c04..6b79f8cd9258af47afa6efa7b1f97c3780be58b0 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -1162,8 +1162,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return list; + } + +- @Override +- public List getEntitiesOfClass(Class entityClass, AABB box, @Nullable Predicate predicate) { ++ public List getEntities(Class oclass, AABB axisalignedbb, @Nullable Predicate predicate) { return getEntitiesOfClass(oclass, axisalignedbb, predicate); } // Paper - OBFHELPER ++ @Override public List getEntitiesOfClass(Class entityClass, AABB box, @Nullable Predicate predicate) { + this.getProfiler().incrementCounter("getEntities"); + int i = Mth.floor((box.minX - 2.0D) / 16.0D); + int j = Mth.ceil((box.maxX + 2.0D) / 16.0D); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 84012c2d12817e657b046bc168cc8eddebcd3831..05fa76c02ce61e26891ad995fe89e925ea086557 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -77,6 +77,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + public void setCurrentChunk(LevelChunk chunk) { + this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; + } ++ static boolean IGNORE_TILE_UPDATES = false; + // Paper end + + @Nullable +@@ -155,6 +156,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + + public void setChanged() { + if (this.level != null) { ++ if (IGNORE_TILE_UPDATES) return; // Paper + this.blockState = this.level.getBlockState(this.worldPosition); + this.level.blockEntityChanged(this.worldPosition, this); + if (!this.blockState.isAir()) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java +index f8e4a42bed265822666141683e36e6696694925b..fc8bb72f7d677f65db505016ad6a4cd6146de29f 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block.entity; + + import javax.annotation.Nullable; ++import net.minecraft.core.BlockPos; + import net.minecraft.world.Container; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; +@@ -17,12 +18,13 @@ public interface Hopper extends Container { + return Hopper.SUCK; + } + +- @Nullable ++ //@Nullable // Paper - it's annoying + Level getLevel(); ++ default BlockPos getBlockPosition() { return new BlockPos(getX(), getY(), getZ()); } // Paper + +- double getLevelX(); ++ double getLevelX(); default double getX() { return this.getLevelX(); } // Paper - OBFHELPER + +- double getLevelY(); ++ double getLevelY(); default double getY() { return this.getLevelY(); } // Paper - OBFHELPER + +- double getLevelZ(); ++ double getLevelZ(); default double getZ() { return this.getLevelZ(); } // Paper - OBFHELPER + } +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 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f7639dab54b 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 +@@ -193,6 +193,160 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + return false; + } + ++ // Paper start - Optimize Hoppers ++ private static boolean skipPullModeEventFire = false; ++ private static boolean skipPushModeEventFire = false; ++ public static boolean skipHopperEvents = false; ++ ++ private boolean hopperPush(Container iinventory, Direction enumdirection) { ++ skipPushModeEventFire = skipHopperEvents; ++ boolean foundItem = false; ++ for (int i = 0; i < this.getContainerSize(); ++i) { ++ ItemStack item = this.getItem(i); ++ if (!item.isEmpty()) { ++ foundItem = true; ++ ItemStack origItemStack = item; ++ ItemStack itemstack = origItemStack; ++ ++ final int origCount = origItemStack.getCount(); ++ final int moved = Math.min(level.spigotConfig.hopperAmount, origCount); ++ origItemStack.setCount(moved); ++ ++ // We only need to fire the event once to give protection plugins a chance to cancel this event ++ // Because nothing uses getItem, every event call should end up the same result. ++ if (!skipPushModeEventFire) { ++ itemstack = callPushMoveEvent(iinventory, itemstack); ++ if (itemstack == null) { // cancelled ++ origItemStack.setCount(origCount); ++ return false; ++ } ++ } ++ final ItemStack itemstack2 = addItem(this, iinventory, itemstack, enumdirection); ++ final int remaining = itemstack2.getCount(); ++ if (remaining != moved) { ++ origItemStack = origItemStack.cloneItemStack(true); ++ origItemStack.setCount(origCount); ++ if (!origItemStack.isEmpty()) { ++ origItemStack.setCount(origCount - moved + remaining); ++ } ++ this.setItem(i, origItemStack); ++ iinventory.setChanged(); ++ return true; ++ } ++ origItemStack.setCount(origCount); ++ } ++ } ++ if (foundItem && level.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown ++ this.setCooldown(level.spigotConfig.hopperTransfer); ++ } ++ return false; ++ } ++ ++ private static boolean hopperPull(Hopper ihopper, Container iinventory, ItemStack origItemStack, int i) { ++ ItemStack itemstack = origItemStack; ++ final int origCount = origItemStack.getCount(); ++ final Level world = ihopper.getLevel(); ++ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); ++ itemstack.setCount(moved); ++ ++ if (!skipPullModeEventFire) { ++ itemstack = callPullMoveEvent(ihopper, iinventory, itemstack); ++ if (itemstack == null) { // cancelled ++ origItemStack.setCount(origCount); ++ // Drastically improve performance by returning true. ++ // No plugin could of relied on the behavior of false as the other call ++ // site for IMIE did not exhibit the same behavior ++ return true; ++ } ++ } ++ ++ final ItemStack itemstack2 = addItem(iinventory, ihopper, itemstack, null); ++ final int remaining = itemstack2.getCount(); ++ if (remaining != moved) { ++ origItemStack = origItemStack.cloneItemStack(true); ++ origItemStack.setCount(origCount); ++ if (!origItemStack.isEmpty()) { ++ origItemStack.setCount(origCount - moved + remaining); ++ } ++ IGNORE_TILE_UPDATES = true; ++ iinventory.setItem(i, origItemStack); ++ IGNORE_TILE_UPDATES = false; ++ iinventory.setChanged(); ++ return true; ++ } ++ origItemStack.setCount(origCount); ++ ++ if (world.paperConfig.cooldownHopperWhenFull) { ++ cooldownHopper(ihopper); ++ } ++ ++ return false; ++ } ++ ++ private ItemStack callPushMoveEvent(Container iinventory, ItemStack itemstack) { ++ Inventory destinationInventory = getInventory(iinventory); ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner(false).getInventory(), ++ CraftItemStack.asCraftMirror(itemstack), destinationInventory, true); ++ boolean result = event.callEvent(); ++ if (!event.calledGetItem && !event.calledSetItem) { ++ skipPushModeEventFire = true; ++ } ++ if (!result) { ++ cooldownHopper(this); ++ return null; ++ } ++ ++ if (event.calledSetItem) { ++ return CraftItemStack.asNMSCopy(event.getItem()); ++ } else { ++ return itemstack; ++ } ++ } ++ ++ private static ItemStack callPullMoveEvent(Hopper hopper, Container iinventory, ItemStack itemstack) { ++ Inventory sourceInventory = getInventory(iinventory); ++ Inventory destination = getInventory(hopper); ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, ++ // Mirror is safe as we no plugins ever use this item ++ CraftItemStack.asCraftMirror(itemstack), destination, false); ++ boolean result = event.callEvent(); ++ if (!event.calledGetItem && !event.calledSetItem) { ++ skipPullModeEventFire = true; ++ } ++ if (!result) { ++ cooldownHopper(hopper); ++ return null; ++ } ++ ++ if (event.calledSetItem) { ++ return CraftItemStack.asNMSCopy(event.getItem()); ++ } else { ++ return itemstack; ++ } ++ } ++ ++ private static Inventory getInventory(Container iinventory) { ++ Inventory sourceInventory;// Have to special case large chests as they work oddly ++ if (iinventory instanceof CompoundContainer) { ++ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); ++ } else if (iinventory instanceof BlockEntity) { ++ sourceInventory = ((BlockEntity) iinventory).getOwner(false).getInventory(); ++ } else { ++ sourceInventory = iinventory.getOwner().getInventory(); ++ } ++ return sourceInventory; ++ } ++ ++ private static void cooldownHopper(Hopper hopper) { ++ if (hopper instanceof HopperBlockEntity) { ++ ((HopperBlockEntity) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer); ++ } else if (hopper instanceof MinecartHopper) { ++ ((MinecartHopper) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer / 2); ++ } ++ } ++ // Paper end ++ + private boolean ejectItems() { + Container iinventory = this.getAttachedContainer(); + +@@ -204,27 +358,28 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + if (this.isFullContainer(iinventory, enumdirection)) { + return false; + } else { +- for (int i = 0; i < this.getContainerSize(); ++i) { ++ return hopperPush(iinventory, enumdirection); /* // Paper - disable rest ++ for (int i = 0; i < this.getSize(); ++i) { + if (!this.getItem(i).isEmpty()) { +- ItemStack itemstack = this.getItem(i).copy(); ++ ItemStack itemstack = this.getItem(i).cloneItemStack(); + // ItemStack itemstack1 = addItem(this, iinventory, this.splitStack(i, 1), enumdirection); + + // CraftBukkit start - Call event when pushing items into other inventories +- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.removeItem(i, level.spigotConfig.hopperAmount)); // Spigot ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.splitStack(i, world.spigotConfig.hopperAmount)); // Spigot + + Inventory destinationInventory; + // Have to special case large chests as they work oddly +- if (iinventory instanceof CompoundContainer) { +- destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); ++ if (iinventory instanceof InventoryLargeChest) { ++ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); + } else { + destinationInventory = iinventory.getOwner().getInventory(); + } + + InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); +- this.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ this.getWorld().getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.setItem(i, itemstack); +- this.setCooldown(level.spigotConfig.hopperTransfer); // Spigot ++ this.setCooldown(world.spigotConfig.hopperTransfer); // Spigot + return false; + } + int origCount = event.getItem().getAmount(); // Spigot +@@ -232,16 +387,16 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + // CraftBukkit end + + if (itemstack1.isEmpty()) { +- iinventory.setChanged(); ++ iinventory.update(); + return true; + } + +- itemstack.shrink(origCount - itemstack1.getCount()); // Spigot ++ itemstack.subtract(origCount - itemstack1.getCount()); // Spigot + this.setItem(i, itemstack); + } + } + +- return false; ++ return false;*/ // Paper - end commenting out replaced block for Hopper Optimizations + } + } + } +@@ -250,18 +405,54 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + return inventory instanceof WorldlyContainer ? IntStream.of(((WorldlyContainer) inventory).getSlotsForFace(side)) : IntStream.range(0, inventory.getContainerSize()); + } + +- private boolean isFullContainer(Container inv, Direction enumdirection) { +- return getSlots(inv, enumdirection).allMatch((i) -> { +- ItemStack itemstack = inv.getItem(i); ++ private static boolean allMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate test) { ++ if (iinventory instanceof WorldlyContainer) { ++ for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) { ++ if (!test.test(iinventory.getItem(i), i)) { ++ return false; ++ } ++ } ++ } else { ++ int size = iinventory.getContainerSize(); ++ for (int i = 0; i < size; i++) { ++ if (!test.test(iinventory.getItem(i), i)) { ++ return false; ++ } ++ } ++ } ++ return true; ++ } + +- return itemstack.getCount() >= itemstack.getMaxStackSize(); +- }); ++ private static boolean anyMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate test) { ++ if (iinventory instanceof WorldlyContainer) { ++ for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) { ++ if (test.test(iinventory.getItem(i), i)) { ++ return true; ++ } ++ } ++ } else { ++ int size = iinventory.getContainerSize(); ++ for (int i = 0; i < size; i++) { ++ if (test.test(iinventory.getItem(i), i)) { ++ return true; ++ } ++ } ++ } ++ return true; ++ } ++ private static final java.util.function.BiPredicate STACK_SIZE_TEST = (itemstack, i) -> itemstack.getCount() >= itemstack.getMaxStackSize(); ++ private static final java.util.function.BiPredicate IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty(); ++ ++ // Paper end ++ ++ private boolean isFullContainer(Container inv, Direction enumdirection) { ++ // Paper start - no streams ++ return allMatch(inv, enumdirection, STACK_SIZE_TEST); ++ // Paper end + } + + private static boolean isEmptyContainer(Container inv, Direction facing) { +- return getSlots(inv, facing).allMatch((i) -> { +- return inv.getItem(i).isEmpty(); +- }); ++ return allMatch(inv, facing, IS_EMPTY_TEST); + } + + public static boolean suckInItems(Hopper hopper) { +@@ -270,9 +461,17 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + if (iinventory != null) { + Direction enumdirection = Direction.DOWN; + +- return isEmptyContainer(iinventory, enumdirection) ? false : getSlots(iinventory, enumdirection).anyMatch((i) -> { +- return tryTakeInItemFromSlot(hopper, iinventory, i, enumdirection); ++ // Paper start - optimize hoppers and remove streams ++ skipPullModeEventFire = skipHopperEvents; ++ return !isEmptyContainer(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { ++ // Logic copied from below to avoid extra getItem calls ++ if (!item.isEmpty() && canTakeItem(iinventory, item, i, enumdirection)) { ++ return hopperPull(hopper, iinventory, item, i); ++ } else { ++ return false; ++ } + }); ++ // Paper end + } else { + Iterator iterator = getItemsAtAndAbove(hopper).iterator(); + +@@ -290,47 +489,48 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + } + +- private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) { ++ private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) {// Paper - method unused as logic is inlined above + ItemStack itemstack = inventory.getItem(slot); + +- if (!itemstack.isEmpty() && canTakeItemFromContainer(inventory, itemstack, slot, side)) { +- ItemStack itemstack1 = itemstack.copy(); ++ if (!itemstack.isEmpty() && canTakeItemFromContainer(inventory, itemstack, slot, side)) { // If this logic changes, update above. this is left inused incase reflective plugins ++ return hopperPull(hopper, inventory, itemstack, slot); /* // Paper - disable rest ++ ItemStack itemstack1 = itemstack.cloneItemStack(); + // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null); + // CraftBukkit start - Call event on collection of items from inventories into the hopper +- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(inventory.removeItem(slot, hopper.getLevel().spigotConfig.hopperAmount)); // Spigot ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.splitStack(i, ihopper.getWorld().spigotConfig.hopperAmount)); // Spigot + + Inventory sourceInventory; + // Have to special case large chests as they work oddly +- if (inventory instanceof CompoundContainer) { +- sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) inventory); ++ if (iinventory instanceof InventoryLargeChest) { ++ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); + } else { +- sourceInventory = inventory.getOwner().getInventory(); ++ sourceInventory = iinventory.getOwner().getInventory(); + } + +- InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), hopper.getOwner().getInventory(), false); ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), ihopper.getOwner().getInventory(), false); + +- hopper.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ ihopper.getWorld().getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { +- inventory.setItem(slot, itemstack1); ++ iinventory.setItem(i, itemstack1); + +- if (hopper instanceof HopperBlockEntity) { +- ((HopperBlockEntity) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer); // Spigot +- } else if (hopper instanceof MinecartHopper) { +- ((MinecartHopper) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer / 2); // Spigot ++ if (ihopper instanceof TileEntityHopper) { ++ ((TileEntityHopper) ihopper).setCooldown(ihopper.getWorld().spigotConfig.hopperTransfer); // Spigot ++ } else if (ihopper instanceof EntityMinecartHopper) { ++ ((EntityMinecartHopper) ihopper).setCooldown(ihopper.getWorld().spigotConfig.hopperTransfer / 2); // Spigot + } + return false; + } + int origCount = event.getItem().getAmount(); // Spigot +- ItemStack itemstack2 = addItem(inventory, hopper, CraftItemStack.asNMSCopy(event.getItem()), null); ++ ItemStack itemstack2 = addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null); + // CraftBukkit end + + if (itemstack2.isEmpty()) { +- inventory.setChanged(); ++ iinventory.update(); + return true; + } + +- itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot +- inventory.setItem(slot, itemstack1); ++ itemstack1.subtract(origCount - itemstack2.getCount()); // Spigot ++ iinventory.setItem(i, itemstack1);*/ // Paper - end commenting out replaced block for Hopper Optimizations + } + + return false; +@@ -339,7 +539,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + public static boolean addItem(Container inventory, ItemEntity itemEntity) { + boolean flag = false; + // CraftBukkit start +- InventoryPickupItemEvent event = new InventoryPickupItemEvent(inventory.getOwner().getInventory(), (org.bukkit.entity.Item) itemEntity.getBukkitEntity()); ++ InventoryPickupItemEvent event = new InventoryPickupItemEvent(getInventory(inventory), (org.bukkit.entity.Item) itemEntity.getBukkitEntity()); // Paper - use getInventory() to avoid snapshot creation + itemEntity.level.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; +@@ -381,6 +581,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + return !inventory.canPlaceItem(slot, stack) ? false : !(inventory instanceof WorldlyContainer) || ((WorldlyContainer) inventory).canPlaceItemThroughFace(slot, stack, side); + } + ++ private static boolean canTakeItem(Container iinventory, ItemStack itemstack, int i, Direction enumdirection) { return canTakeItemFromContainer(iinventory, itemstack, i, enumdirection); } // Paper - OBFHELPER + private static boolean canTakeItemFromContainer(Container inv, ItemStack stack, int slot, Direction facing) { + return !(inv instanceof WorldlyContainer) || ((WorldlyContainer) inv).canTakeItemThroughFace(slot, stack, facing); + } +@@ -393,7 +594,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + boolean flag1 = to.isEmpty(); + + if (itemstack1.isEmpty()) { ++ IGNORE_TILE_UPDATES = true; // Paper + to.setItem(slot, stack); ++ IGNORE_TILE_UPDATES = false; // Paper + stack = ItemStack.EMPTY; + flag = true; + } else if (canMergeItems(itemstack1, stack)) { +@@ -444,20 +647,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + + public static List getItemsAtAndAbove(Hopper ihopper) { +- return (List) ihopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> { +- return ihopper.getLevel().getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(ihopper.getLevelX() - 0.5D, ihopper.getLevelY() - 0.5D, ihopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream(); +- }).collect(Collectors.toList()); ++ // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?! ++ Level world = ihopper.getLevel(); ++ double d0 = ihopper.getX(); ++ double d1 = ihopper.getY(); ++ double d2 = ihopper.getZ(); ++ AABB bb = new AABB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); ++ return world.getEntities(ItemEntity.class, bb, Entity::isAlive); ++ // Paper end + } + + @Nullable + public static Container getContainerAt(Level world, BlockPos blockposition) { +- return getContainerAt(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); ++ return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, true); // Paper + } + + @Nullable +- public static Container getContainerAt(Level world, double x, double y, double z) { ++ public static Container getContainerAt(Level world, double x, double y, double z) { return a(world, x, y, z, false); } // Paper - overload to default false ++ public static Container a(Level world, double d0, double d1, double d2, boolean optimizeEntities) { // Paper + Object object = null; +- BlockPos blockposition = new BlockPos(x, y, z); ++ BlockPos blockposition = new BlockPos(d0, d1, d2); + if ( !world.hasChunkAt( blockposition ) ) return null; // Spigot + BlockState iblockdata = world.getBlockState(blockposition); + Block block = iblockdata.getBlock(); +@@ -475,8 +684,8 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + } + +- if (object == null) { +- List list = world.getEntities((Entity) null, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); ++ if (object == null && (!optimizeEntities || !org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(block).isOccluding())) { // Paper ++ List list = world.getEntities((Entity) null, new AABB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); + + if (!list.isEmpty()) { + object = (Container) list.get(world.random.nextInt(list.size())); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +index 5ad419941ff1113ef29b9a4593f44d8f35ba8424..4525032232b5a89de13c6a46dc489a07428e3f21 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +@@ -97,12 +97,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + @Override + public boolean isEmpty() { + this.unpackLootTable((Player) null); +- return this.getItems().stream().allMatch(ItemStack::isEmpty); ++ // Paper start ++ for (ItemStack itemStack : this.getItems()) { ++ if (!itemStack.isEmpty()) { ++ return false; ++ } ++ } ++ // Paper end ++ return true; + } + + @Override + public ItemStack getItem(int slot) { +- this.unpackLootTable((Player) null); ++ if (slot == 0) this.unpackLootTable((Player) null); // Paper + return (ItemStack) this.getItems().get(slot); + } + diff --git a/Remapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch b/Remapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch new file mode 100644 index 0000000000..4f453dc689 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 24 Dec 2019 00:35:42 +0000 +Subject: [PATCH] PlayerDeathEvent#shouldDropExperience + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 2ef273e3b917803f3e2ac3c6a22d92a15b9eb71a..7f4e81ee3339e90b8525541dccf6dea187853cf7 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -819,7 +819,7 @@ public class ServerPlayer extends Player implements ContainerListener { + this.tellNeutralMobsThatIDied(); + } + // SPIGOT-5478 must be called manually now +- this.dropExperience(); ++ if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event + // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. + if (!event.getKeepInventory()) { + // Paper start - replace logic diff --git a/Remapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch b/Remapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch new file mode 100644 index 0000000000..9a427d5aa2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 5 Jan 2020 17:24:34 -0600 +Subject: [PATCH] Prevent bees loading chunks checking hive position + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java +index 32ee38142a3053091ab7b3fb3d608d268b07d4e3..edd6d63f715acef1a77eba0cf46ff8267228f4c6 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -442,6 +442,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + if (!this.hasHive()) { + return false; + } else { ++ if (level.getChunkIfLoadedImmediately(hivePos.getX() >> 4, hivePos.getZ() >> 4) == null) return true; // Paper - just assume the hive is still there, no need to load the chunk(s) + BlockEntity tileentity = this.level.getBlockEntity(this.hivePos); + + return tileentity != null && tileentity.getType() == BlockEntityType.BEEHIVE; diff --git a/Remapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/Remapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch new file mode 100644 index 0000000000..f6952f6250 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Nov 2016 20:28:12 -0400 +Subject: [PATCH] Don't load Chunks from Hoppers and other things + +Hoppers call this to I guess "get the primary side" of a double sided chest. + +If the double sided chest crosses chunk lines, it causes the chunk to load. +This will end up causing sync chunk loads, which will unload with Chunk GC, +only to be reloaded again the next tick. + +This of course is undesirable, so just return the loaded side as "primary" +and treat it as a single chest if the other sides are unloaded + +diff --git a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java +index a4f16b2093c867e9fd1c2e07b67c49c3c5ec7506..df20b3616929657d2e8061159ed97f500b33d192 100644 +--- a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java ++++ b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java +@@ -29,7 +29,12 @@ public class DoubleBlockCombiner { + return new DoubleBlockCombiner.NeighborCombineResult.Single<>(s0); + } else { + BlockPos blockposition1 = pos.relative((Direction) function1.apply(state)); +- BlockState iblockdata1 = world.getBlockState(blockposition1); ++ // Paper start ++ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); ++ if (iblockdata1 == null) { ++ return new DoubleBlockCombiner.NeighborCombineResult.Single<>(s0); ++ } ++ // Paper end + + if (iblockdata1.is(state.getBlock())) { + DoubleBlockCombiner.BlockType doubleblockfinder_blocktype1 = (DoubleBlockCombiner.BlockType) typeMapper.apply(iblockdata1); diff --git a/Remapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch b/Remapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch new file mode 100644 index 0000000000..37dc33fc4a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 27 Dec 2019 09:42:26 -0800 +Subject: [PATCH] Guard against serializing mismatching chunk coordinate + +Should help if something dumb happens + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index be67dc16bf70e4517efd213ca9002f116f60b57c..6c28a611b9b79c3322ab07883972c07b3bfc3073 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -67,6 +67,13 @@ public class ChunkSerializer { + + private static final Logger LOGGER = LogManager.getLogger(); + ++ // Paper start - guard against serializing mismatching coordinates ++ // TODO Note: This needs to be re-checked each update ++ public static ChunkPos getChunkCoordinate(CompoundTag chunkData) { ++ CompoundTag levelData = chunkData.getCompound("Level"); ++ return new ChunkPos(levelData.getInt("xPos"), levelData.getInt("zPos")); ++ } ++ // Paper end + // Paper start + public static final class InProgressChunkHolder { + +@@ -92,8 +99,8 @@ public class ChunkSerializer { + // Paper end + ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); + BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); +- CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); +- ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate ++ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate + + if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { + ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +index 684442b7175e30b6d4cafb2f7d2d4c10517cc33d..1af804c5c6fb2b20ea3f020610763c1d7dcee110 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -13,6 +13,7 @@ import net.minecraft.SharedConstants; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.datafix.DataFixTypes; +@@ -119,6 +120,13 @@ public class ChunkStorage implements AutoCloseable { + + public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER + public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) ++ // Paper start ++ if (!chunkcoordintpair.equals(ChunkSerializer.getChunkCoordinate(nbttagcompound))) { ++ String world = (this instanceof ChunkMap) ? ((ChunkMap)this).level.getWorld().getName() : null; ++ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkcoordintpair.toString() ++ + " but compound says coordinate is " + ChunkSerializer.getChunkCoordinate(nbttagcompound).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); ++ } ++ // Paper end + this.regionFileCache.write(chunkcoordintpair, nbttagcompound); + if (this.legacyStructureHandler != null) { + synchronized (this.persistentDataLock) { // Paper - Async chunk loading diff --git a/Remapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch b/Remapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch new file mode 100644 index 0000000000..e478c7d039 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 11 Jan 2020 21:50:56 -0800 +Subject: [PATCH] Optimise IEntityAccess#getPlayerByUUID + +Use the world entity map instead of iterating over all players + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 01f879a8dd0e1ffec380e02072567330152eaceb..40d7dbc4f1deda88d4a539b89d84b595217051b6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -283,6 +283,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + // Paper end + ++ // Paper start - optimise getPlayerByUUID ++ @Nullable ++ @Override ++ public Player getPlayerByUUID(UUID uuid) { ++ Entity player = this.entitiesByUuid.get(uuid); ++ return (player instanceof Player) ? (Player)player : null; ++ } ++ // Paper end ++ + // Add env and gen to constructor, WorldData -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor +diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java +index 6a5430fe54a5c8ad119a0f3842961825a54d8d7a..b9606465ace8b320eafbbad3d60c01b87a859c44 100644 +--- a/src/main/java/net/minecraft/world/level/EntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/EntityGetter.java +@@ -277,6 +277,12 @@ public interface EntityGetter { + + @Nullable + default Player getPlayerByUUID(UUID uuid) { ++ // Paper start - allow WorldServer to override ++ return this.getPlayerByUUID(uuid); ++ } ++ @Nullable ++ default Player getPlayerByUUID(UUID uuid) { ++ // Paper end + for (int i = 0; i < this.players().size(); ++i) { + Player entityhuman = (Player) this.players().get(i); + diff --git a/Remapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch b/Remapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch new file mode 100644 index 0000000000..f1ecdfe628 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AJMFactsheets +Date: Fri, 17 Jan 2020 17:17:54 -0600 +Subject: [PATCH] Fix items not falling correctly + +Since 1.14, Mojang has added an optimization which skips checking if +an item should fall every fourth tick. + +However, Spigot's entity activation range class also has an +optimization which skips ticking active entities every fourth tick. +This can result in a state where an item will never properly fall +due to its move method never being called. + +This patch resolves the conflict by offsetting checking an item's +move method from Spigot's entity activation range check. + +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 96b8102773cbee2c3fe2711008ba1487084d67b0..9311f9f411d09d4460f0be8235957fab9e195b7a 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -115,7 +115,7 @@ public class ItemEntity extends Entity { + } + } + +- if (!this.onGround || getHorizontalDistanceSqr(this.getDeltaMovement()) > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) { ++ if (!this.onGround || getHorizontalDistanceSqr(this.getDeltaMovement()) > 9.999999747378752E-6D || this.tickCount % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check + this.move(MoverType.SELF, this.getDeltaMovement()); + float f1 = 0.98F; + diff --git a/Remapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch b/Remapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch new file mode 100644 index 0000000000..cc90ba9655 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 14 Jan 2020 15:28:28 -0800 +Subject: [PATCH] Lag compensate eating + +When the server is lagging, players will wait longer when eating. +Change to also use a time check instead if it passes. + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index b49d4772932a58852b3195f5f56ff93dbcabf766..016fcc4ae20e1e48728a848be28633e624ae49a7 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -211,7 +211,7 @@ public abstract class LivingEntity extends Entity { + private int noJumpDelay; + private float absorptionAmount; + public ItemStack useItem; // Paper - public +- protected int useItemRemaining; ++ protected int useItemRemaining; protected final int getEatTimeTicks() { return this.useItemRemaining; } protected final void setEatTimeTicks(int value) { this.useItemRemaining = value; } // Paper - OBFHELPER + protected int fallFlyTicks; + private BlockPos lastPos; + private Optional lastClimbablePos; +@@ -3148,6 +3148,11 @@ public abstract class LivingEntity extends Entity { + return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; + } + ++ // Paper start - lag compensate eating ++ protected long eatStartTime; ++ protected int totalEatTimeTicks; ++ // Paper end ++ + private void updatingUsingItem() { + if (this.isUsingItem()) { + if (ItemStack.isSameIgnoreDurability(this.getItemInHand(this.getUsedItemHand()), this.useItem)) { +@@ -3157,7 +3162,12 @@ public abstract class LivingEntity extends Entity { + this.triggerItemUseEffects(this.useItem, 5); + } + +- if (--this.useItemRemaining == 0 && !this.level.isClientSide && !this.useItem.useOnRelease()) { ++ // Paper start - lag compensate eating ++ // we add 1 to the expected time to avoid lag compensating when we should not ++ boolean shouldLagCompensate = this.useItem.getItem().isEdible() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); ++ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level.isClientSide && !this.useItem.useOnRelease()) { ++ this.setEatTimeTicks(0); ++ // Paper end + this.completeUsingItem(); + } + } else { +@@ -3207,7 +3217,10 @@ public abstract class LivingEntity extends Entity { + + if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag + this.useItem = itemstack; +- this.useItemRemaining = itemstack.getUseDuration(); ++ // Paper start - lag compensate eating ++ this.useItemRemaining = this.totalEatTimeTicks = itemstack.getUseDuration(); ++ this.eatStartTime = System.nanoTime(); ++ // Paper end + if (!this.level.isClientSide) { + this.setLivingEntityFlag(1, true); + this.setLivingEntityFlag(2, enumhand == InteractionHand.OFF_HAND); +@@ -3231,7 +3244,10 @@ public abstract class LivingEntity extends Entity { + } + } else if (!this.isUsingItem() && !this.useItem.isEmpty()) { + this.useItem = ItemStack.EMPTY; +- this.useItemRemaining = 0; ++ // Paper start - lag compensate eating ++ this.useItemRemaining = this.totalEatTimeTicks = 0; ++ this.eatStartTime = -1L; ++ // Paper end + } + } + +@@ -3359,7 +3375,10 @@ public abstract class LivingEntity extends Entity { + } + + this.useItem = ItemStack.EMPTY; +- this.useItemRemaining = 0; ++ // Paper start - lag compensate eating ++ this.useItemRemaining = this.totalEatTimeTicks = 0; ++ this.eatStartTime = -1L; ++ // Paper end + } + + public boolean isBlocking() { diff --git a/Remapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch b/Remapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch new file mode 100644 index 0000000000..9e3f2b3479 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BrodyBeckwith +Date: Tue, 14 Jan 2020 17:49:03 -0500 +Subject: [PATCH] Optimize call to getFluid for explosions + + +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 45a75f7be308678336e192828becf6cf5c9047bc..667a6d645034c67639c01b8221591877bcb87b35 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -151,7 +151,7 @@ public class Explosion { + for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { + BlockPos blockposition = new BlockPos(d4, d5, d6); + BlockState iblockdata = this.level.getBlockState(blockposition); +- FluidState fluid = this.level.getFluidState(blockposition); ++ FluidState fluid = iblockdata.getFluidState(); // Paper + Optional optional = this.damageCalculator.a(this, this.level, blockposition, iblockdata, fluid); + + if (optional.isPresent()) { diff --git a/Remapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch b/Remapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch new file mode 100644 index 0000000000..63271d423f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 17 Jan 2020 18:44:55 -0800 +Subject: [PATCH] Fix last firework in stack not having effects when dispensed + - #2871 + +CB used the resulting item in the dispenser rather than the item +dispensed. The resulting item would have size == 0 and therefore +be convertered to air, hence why the effects disappeared. + +diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +index 67a894a185a3d4a53b3c7f90174b2604dff18257..67d140dff483bfc654a0390e0cdcd13aa658a62d 100644 +--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +@@ -425,7 +425,7 @@ public interface DispenseItemBehavior { + } + + itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); +- FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.getLevel(), stack, pointer.x(), pointer.y(), pointer.x(), true); ++ FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.getLevel(), itemstack1, pointer.x(), pointer.y(), pointer.x(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed + + DispenseItemBehavior.setEntityPokingOutOfBlock(pointer, entityfireworks, enumdirection); + entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F); diff --git a/Remapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch b/Remapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch new file mode 100644 index 0000000000..e51ec69f45 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 2 Jan 2020 12:25:07 -0600 +Subject: [PATCH] Add effect to block break naturally + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 5bff313dbbb3049105874846d995883e827fbc00..05f0833f762436bf8f5f5875c7e3cfed1da11e1c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -630,6 +630,13 @@ public class CraftBlock implements Block { + + @Override + public boolean breakNaturally(ItemStack item) { ++ // Paper start ++ return breakNaturally(item, false); ++ } ++ ++ @Override ++ public boolean breakNaturally(ItemStack item, boolean triggerEffect) { ++ // Paper end + // Order matters here, need to drop before setting to air so skulls can get their data + net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS(); + net.minecraft.world.level.block.Block block = iblockdata.getBlock(); +@@ -639,6 +646,7 @@ public class CraftBlock implements Block { + // Modelled off EntityHuman#hasBlock + if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) { + net.minecraft.world.level.block.Block.dropResources(iblockdata, world.getLevel(), position, world.getBlockEntity(position), null, nmsItem); ++ if (triggerEffect) world.levelEvent(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.world.level.block.Block.getId(block.defaultBlockState())); // Paper + result = true; + } + diff --git a/Remapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch b/Remapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch new file mode 100644 index 0000000000..ec1d0a178d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Sat, 21 Dec 2019 15:22:09 -0500 +Subject: [PATCH] Tracking Range Improvements + +Sets tracking range of watermobs to animals instead of misc and simplifies code + +Also ignores Enderdragon, defaulting it to Mojang's setting + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 190ddd4d9ef3472c33d46c2ead72fa0dc918054a..6da406c8403797a1cd9276ac06577c3c080a8a22 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1795,6 +1795,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + int j = entity.getType().clientTrackingRange() * 16; ++ j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper + + if (j > i) { + i = j; +diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java +index 8e3e36a8739a7dea1feb3785e96b7b9f19720446..b03fa9024c7f0238e1379f6ae4486db5300a70e9 100644 +--- a/src/main/java/org/spigotmc/TrackingRange.java ++++ b/src/main/java/org/spigotmc/TrackingRange.java +@@ -6,7 +6,6 @@ import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.decoration.ItemFrame; + import net.minecraft.world.entity.decoration.Painting; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.monster.Ghast; + + public class TrackingRange + { +@@ -25,26 +24,26 @@ public class TrackingRange + if ( entity instanceof ServerPlayer ) + { + return config.playerTrackingRange; +- } else if ( entity.activationType == ActivationRange.ActivationType.MONSTER || entity.activationType == ActivationRange.ActivationType.RAIDER ) +- { +- return config.monsterTrackingRange; +- } else if ( entity instanceof Ghast ) +- { +- if ( config.monsterTrackingRange > config.monsterActivationRange ) +- { ++ // Paper start - Simplify and set water mobs to animal tracking range ++ } ++ switch (entity.activationType) { ++ case RAIDER: ++ case MONSTER: ++ case FLYING_MONSTER: + return config.monsterTrackingRange; +- } else +- { +- return config.monsterActivationRange; +- } +- } else if ( entity.activationType == ActivationRange.ActivationType.ANIMAL ) +- { +- return config.animalTrackingRange; +- } else if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) ++ case WATER: ++ case VILLAGER: ++ case ANIMAL: ++ return config.animalTrackingRange; ++ case MISC: ++ } ++ if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) ++ // Paper end + { + return config.miscTrackingRange; + } else + { ++ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt + return config.otherTrackingRange; + } + } diff --git a/Remapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch b/Remapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch new file mode 100644 index 0000000000..ad4d829921 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch @@ -0,0 +1,908 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 13 May 2016 01:38:06 -0400 +Subject: [PATCH] Entity Activation Range 2.0 + +Optimizes performance of Activation Range + +Adds many new configurations and a new wake up inactive system + +Fixes and adds new Immunities to improve gameplay behavior + +Adds water Mobs to activation range config and nerfs fish +Adds flying monsters to control ghast and phantoms +Adds villagers as separate config + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 40d7dbc4f1deda88d4a539b89d84b595217051b6..bf1bb1530037ebcacc8d5a491789909bddb8b697 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -855,17 +855,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + ++TimingHistory.entityTicks; // Paper - timings + // Spigot start + co.aikar.timings.Timing timer; // Paper +- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { +- entity.tickCount++; +- timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings ++ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below ++ entity.ticksLived++; ++ timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings + entity.inactiveTick(); + } finally { timer.stopTiming(); } // Paper + return; +- } ++ }*/ // Paper - comment out EAR 2 + // Spigot end + // Paper start- timings +- TimingHistory.activatedEntityTicks++; +- timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); ++ timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper + try { + // Paper end - timings + entity.setPosAndOldPos(entity.getX(), entity.getY(), entity.getZ()); +@@ -879,12 +879,16 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return Registry.ENTITY_TYPE.getKey(entity.getType()).toString(); + }); + gameprofilerfiller.incrementCounter("tickNonPassenger"); ++ if (isActive) { // Paper - EAR 2 ++ TimingHistory.activatedEntityTicks++; // Paper + entity.tick(); + entity.postTick(); // CraftBukkit ++ } else { entity.inactiveTick(); } // Paper - EAR 2 + gameprofilerfiller.pop(); + } + + this.updateChunkPos(entity); ++ } finally { timer.stopTiming(); } // Paper - timings + if (entity.inChunk) { + Iterator iterator = entity.getPassengers().iterator(); + +@@ -894,7 +898,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.tickPassenger(entity, entity1); + } + } +- } finally { timer.stopTiming(); } // Paper - timings ++ //} finally { timer.stopTiming(); } // Paper - timings - move up + + } + } +@@ -902,6 +906,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public void tickPassenger(Entity vehicle, Entity passenger) { + if (!passenger.removed && passenger.getVehicle() == vehicle) { + if (passenger instanceof Player || this.getChunkSource().isEntityTickingChunk(passenger)) { ++ // Paper - EAR 2 ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); ++ co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper ++ try { ++ // Paper end + passenger.setPosAndOldPos(passenger.getX(), passenger.getY(), passenger.getZ()); + passenger.yRotO = passenger.yRot; + passenger.xRotO = passenger.xRot; +@@ -913,8 +922,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return Registry.ENTITY_TYPE.getKey(passenger.getType()).toString(); + }); + gameprofilerfiller.incrementCounter("tickPassenger"); ++ // Paper start - EAR 2 ++ if (isActive) { + passenger.rideTick(); + passenger.postTick(); // CraftBukkit ++ } else { ++ passenger.setDeltaMovement(Vec3.ZERO); ++ passenger.inactiveTick(); ++ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary ++ vehicle.syncPositionOf(passenger); ++ } ++ // Paper end - EAR 2 + gameprofilerfiller.pop(); + } + +@@ -927,7 +945,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + this.tickPassenger(passenger, entity2); + } +- } ++ } } finally { timer.stopTiming(); } // Paper - EAR2 timings + + } + } else { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index af86c370c6f834514115a8e40659f5e1aaabec75..c6881a9a5da2caed77dea30e4906d2dd99a624c1 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -67,6 +67,7 @@ import net.minecraft.world.entity.animal.AbstractFish; + import net.minecraft.world.entity.animal.Animal; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; ++import net.minecraft.world.entity.vehicle.AbstractMinecart; + import net.minecraft.world.entity.vehicle.Boat; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.enchantment.EnchantmentHelper; +@@ -250,7 +251,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public boolean noCulling; + public boolean hasImpulse; + public int portalCooldown; +- protected boolean isInsidePortal; ++ public boolean isInsidePortal; // Paper - public + protected int portalTime; + protected BlockPos portalEntrancePos; + private boolean invulnerable; +@@ -274,6 +275,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; + public long activatedTick = Integer.MIN_VALUE; ++ public boolean isTemporarilyActive = false; // Paper + public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one + protected int numCollisions = 0; // Paper + public void inactiveTick() { } +@@ -664,6 +666,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.setLocationFromBoundingbox(); + } else { + if (type == MoverType.PISTON) { ++ this.activatedTick = MinecraftServer.currentTick + 20; // Paper + movement = this.limitPistonMovement(movement); + if (movement.equals(Vec3.ZERO)) { + return; +@@ -676,6 +679,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.stuckSpeedMultiplier = Vec3.ZERO; + this.setDeltaMovement(Vec3.ZERO); + } ++ // Paper start - ignore movement changes while inactive. ++ if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof AbstractMinecart) && movement == getDeltaMovement() && type == MoverType.SELF) { ++ setDeltaMovement(Vec3.ZERO); ++ this.level.getProfiler().pop(); ++ return; ++ } ++ // Paper end + + movement = this.maybeBackOffFromEdge(movement, type); + Vec3 vec3d1 = this.collide(movement); +@@ -2011,6 +2021,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + } + ++ public void syncPositionOf(Entity entity) { positionRider(entity); } // Paper - OBFHELPER + public void positionRider(Entity passenger) { + this.positionRider(passenger, Entity::setPos); + } +@@ -2821,6 +2832,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.stringUUID; + } + ++ public final boolean isPushedByWater() { return this.isPushedByFluid(); } // Paper - OBFHELPER - the below is not an obfhelper, don't use it! + public boolean isPushedByFluid() { + // Paper start + return this.pushedByWater(); +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 016fcc4ae20e1e48728a848be28633e624ae49a7..b84dab1043c56e2deb58aec8639226f98db165d1 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -189,7 +189,7 @@ public abstract class LivingEntity extends Entity { + protected float rotOffs; + protected int deathScore;protected int getKillCount() { return this.deathScore; } // Paper - OBFHELPER + public float lastHurt; +- protected boolean jumping; ++ public boolean jumping; // Paper protected -> public + public float xxa; + public float yya; + public float zza; +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 29a2eeee9f2011ed6fcc44f19041f616decfdb38..40ab66f888f30a5506e3aa96a4b32485452e8978 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -113,7 +113,7 @@ public abstract class Mob extends LivingEntity { + public ResourceLocation lootTable; + public long lootTableSeed; + @Nullable +- private Entity leashHolder; ++ public Entity leashHolder; // Paper - private -> public + private int delayedLeashHolderId; + @Nullable + private CompoundTag leashInfoTag; +@@ -194,6 +194,19 @@ public abstract class Mob extends LivingEntity { + return this.lookControl; + } + ++ // Paper start ++ @Override ++ public void inactiveTick() { ++ super.inactiveTick(); ++ if (this.goalSelector.inactiveTick()) { ++ this.goalSelector.tick(); ++ } ++ if (this.targetSelector.inactiveTick()) { ++ this.targetSelector.tick(); ++ } ++ } ++ // Paper end ++ + public MoveControl getMoveControl() { + if (this.isPassenger() && this.getVehicle() instanceof Mob) { + Mob entityinsentient = (Mob) this.getVehicle(); +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +index 920ae9af8985705a0ada7da5b7085a1ed8ca7f27..7c82d453388a27b69207d051dec316fc14715e2b 100644 +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -13,6 +13,7 @@ import org.bukkit.event.entity.EntityUnleashEvent; + public abstract class PathfinderMob extends Mob { + + public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper ++ public BlockPos movingTarget = null; public BlockPos getMovingTarget() { return movingTarget; } // Paper + + protected PathfinderMob(EntityType type, Level world) { + super(type, world); +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +index d44a5b7f6cf62d5e9acacad25d47cb0d44761cfa..558dd72c47930f6993952467f83b5a54ead95d92 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +@@ -20,7 +20,10 @@ public abstract class Goal { + + public void start() {} + +- public void stop() {} ++ public void stop() { ++ onTaskReset(); // Paper ++ } ++ public void onTaskReset() {} // Paper + + public void tick() {} + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +index 9066db5c9a76cfb9665bef77b36172f1ea6ba931..9bd2ee05a0de6678ad8933a8ffbe0ae66bd073b4 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +@@ -26,10 +26,11 @@ public class GoalSelector { + } + }; + private final Map lockedFlags = new EnumMap(Goal.Flag.class); +- private final Set availableGoals = Sets.newLinkedHashSet(); ++ private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER + private final Supplier profiler; + private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); +- private int newGoalRate = 3; ++ private int newGoalRate = 3;private int getTickRate() { return newGoalRate; } // Paper - OBFHELPER ++ private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO + + public GoalSelector(Supplier profiler) { + this.profiler = profiler; +@@ -39,6 +40,21 @@ public class GoalSelector { + this.availableGoals.add(new WrappedGoal(priority, goal)); + } + ++ // Paper start ++ public boolean inactiveTick() { ++ incRate(); ++ return getCurRate() % getTickRate() == 0; ++ } ++ public boolean hasTasks() { ++ for (WrappedGoal task : getTasks()) { ++ if (task.isRunning()) { ++ return true; ++ } ++ } ++ return false; ++ } ++ // Paper end ++ + public void removeGoal(Goal goal) { + this.availableGoals.stream().filter((pathfindergoalwrapped) -> { + return pathfindergoalwrapped.getGoal() == goal; +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +index c8680e795deeb68e0662eac7c760a103d1c767b4..e83cb412d8549b86d0348a2aa37c79201a5930be 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +@@ -9,12 +9,12 @@ import net.minecraft.world.level.LevelReader; + + public abstract class MoveToBlockGoal extends Goal { + +- protected final PathfinderMob mob; ++ protected final PathfinderMob mob;public PathfinderMob getEntity() { return mob; } // Paper - OBFHELPER + public final double speedModifier; + protected int nextStartTick; + protected int tryTicks; + private int maxStayTicks; +- protected BlockPos blockPos;public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER ++ protected BlockPos blockPos; public final BlockPos getTargetPosition() { return this.blockPos; } public void setTargetPosition(BlockPos pos) { this.blockPos = pos; getEntity().movingTarget = pos != BlockPos.ZERO ? pos : null; } // Paper - OBFHELPER + private boolean reachedTarget; + private final int searchRange; + private final int verticalSearchRange; +@@ -23,6 +23,13 @@ public abstract class MoveToBlockGoal extends Goal { + public MoveToBlockGoal(PathfinderMob mob, double speed, int range) { + this(mob, speed, range, 1); + } ++ // Paper start - activation range improvements ++ @Override ++ public void onTaskReset() { ++ super.onTaskReset(); ++ setTargetPosition(BlockPos.ZERO); ++ } ++ // Paper end + + public MoveToBlockGoal(PathfinderMob mob, double speed, int range, int maxYDifference) { + this.blockPos = BlockPos.ZERO; +@@ -111,6 +118,7 @@ public abstract class MoveToBlockGoal extends Goal { + blockposition_mutableblockposition.setWithOffset((Vec3i) blockposition, i1, k - 1, j1); + if (this.mob.isWithinRestriction((BlockPos) blockposition_mutableblockposition) && this.isValidTarget(this.mob.level, blockposition_mutableblockposition)) { + this.blockPos = blockposition_mutableblockposition; ++ setTargetPosition(blockposition_mutableblockposition.immutable()); // Paper + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +index 9921adf9292e0eff77515841d1b109a07b489367..81b4618a7979ee8dd25e1749c084de9262318ef4 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +@@ -64,6 +64,7 @@ public class WrappedGoal extends Goal { + return this.goal.getFlags(); + } + ++ public boolean isRunning() { return this.isRunning(); } // Paper - OBFHELPER + public boolean isRunning() { + return this.isRunning; + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java +index 5a7310bb48c1b8a72ad3c5d82c44fff8800995a2..a24af0600ad3e7d189581aa06a8e998f6a12e0fc 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java +@@ -454,6 +454,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { + return this.caravanTail != null; + } + ++ public final boolean inCaravan() { return this.inCaravan(); } // Paper - OBFHELPER + public boolean inCaravan() { + return this.caravanHead != null; + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +index ae8f850baa14a4f4277da5b6fdb1e5ccb44c4f35..9eee68a5a84e121698d26bd54212a72c75e16251 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -70,10 +70,12 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan + return super.finalizeSpawn(world, difficulty, spawnReason, (SpawnGroupData) entityData, entityTag); + } + ++ public final int getUnhappy() { return getUnhappyCounter(); } // Paper - OBFHELPER + public int getUnhappyCounter() { + return (Integer) this.entityData.get(AbstractVillager.DATA_UNHAPPY_COUNTER); + } + ++ public final void setUnhappy(int i) { setUnhappyCounter(i); } // Paper - OBFHELPER + public void setUnhappyCounter(int ticks) { + this.entityData.set(AbstractVillager.DATA_UNHAPPY_COUNTER, ticks); + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index eed6265dc8275921a18fc5f4970ba131ba782132..4aa34320ef7d6c62ccb17734bfa61d406190b919 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -212,17 +212,29 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + @Override + public void inactiveTick() { + // SPIGOT-3874, SPIGOT-3894, SPIGOT-3846, SPIGOT-5286 :( +- if (level.spigotConfig.tickInactiveVillagers && this.isEffectiveAi()) { +- this.customServerAiStep(); ++ // Paper start ++ if (this.getUnhappy() > 0) { ++ this.setUnhappy(this.getUnhappy() - 1); + } ++ if (this.isEffectiveAi()) { ++ if (level.spigotConfig.tickInactiveVillagers) { ++ this.customServerAiStep(); ++ } else { ++ this.mobTick(true); ++ } ++ } ++ doReputationTick(); ++ // Paper end ++ + super.inactiveTick(); + } + // Spigot End + + @Override +- protected void customServerAiStep() { ++ protected void customServerAiStep() { mobTick(false); } ++ protected void mobTick(boolean inactive) { + this.level.getProfiler().push("villagerBrain"); +- this.getBrain().tick((ServerLevel) this.level, this); // CraftBukkit - decompile error ++ if (!inactive) this.getBrain().tick((ServerLevel) this.level, this); // CraftBukkit - decompile error // Paper + this.level.getProfiler().pop(); + if (this.assignProfessionWhenSpawned) { + this.assignProfessionWhenSpawned = false; +@@ -246,7 +258,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + this.lastTradedPlayer = null; + } + +- if (!this.isNoAi() && this.random.nextInt(100) == 0) { ++ if (!inactive && !this.isNoAi() && this.random.nextInt(100) == 0) { // Paper + Raid raid = ((ServerLevel) this.level).getRaidAt(this.blockPosition()); + + if (raid != null && raid.isActive() && !raid.isOver()) { +@@ -257,6 +269,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.isTrading()) { + this.stopTrading(); + } ++ if (inactive) return; // Paper + + super.customServerAiStep(); + } +@@ -900,6 +913,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + } + } + ++ private void doReputationTick() { maybeDecayGossip(); } // Paper - OBFHELPER + private void maybeDecayGossip() { + long i = this.level.getGameTime(); + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 6b79f8cd9258af47afa6efa7b1f97c3780be58b0..1d536d77518a70bdc1a23924aea99df1042b3cd5 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -142,6 +142,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public long ticksPerWaterSpawns; + public long ticksPerWaterAmbientSpawns; + public long ticksPerAmbientSpawns; ++ // Paper start ++ public int wakeupInactiveRemainingAnimals; ++ public int wakeupInactiveRemainingFlying; ++ public int wakeupInactiveRemainingMonsters; ++ public int wakeupInactiveRemainingVillagers; ++ // Paper end + public boolean populating; + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3e4ac3eaf 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -1,41 +1,55 @@ + package org.spigotmc; + + import java.util.Collection; ++import net.minecraft.core.BlockPos; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.FlyingMob; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.PathfinderMob; ++import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ambient.AmbientCreature; + import net.minecraft.world.entity.animal.Animal; ++import net.minecraft.world.entity.animal.Bee; + import net.minecraft.world.entity.animal.Sheep; ++import net.minecraft.world.entity.animal.WaterAnimal; ++import net.minecraft.world.entity.animal.horse.Llama; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.entity.boss.enderdragon.EndCrystal; + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; + import net.minecraft.world.entity.boss.wither.WitherBoss; ++import net.minecraft.world.entity.item.FallingBlockEntity; + import net.minecraft.world.entity.item.PrimedTnt; + import net.minecraft.world.entity.monster.Creeper; +-import net.minecraft.world.entity.monster.Monster; +-import net.minecraft.world.entity.monster.Slime; ++import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.Pillager; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; ++import net.minecraft.world.entity.projectile.EyeOfEnder; + import net.minecraft.world.entity.projectile.FireworkRocketEntity; + import net.minecraft.world.entity.projectile.ThrowableProjectile; + import net.minecraft.world.entity.projectile.ThrownTrident; + import net.minecraft.world.entity.raid.Raider; ++import co.aikar.timings.MinecraftTimings; ++import net.minecraft.world.entity.schedule.Activity; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.phys.AABB; +-import co.aikar.timings.MinecraftTimings; + + public class ActivationRange + { + + public enum ActivationType + { ++ WATER, // Paper ++ FLYING_MONSTER, // Paper ++ VILLAGER, // Paper + MONSTER, + ANIMAL, + RAIDER, +@@ -43,6 +57,43 @@ public class ActivationRange + + AABB boundingBox = new AABB( 0, 0, 0, 0, 0, 0 ); + } ++ // Paper start ++ ++ static Activity[] VILLAGER_PANIC_IMMUNITIES = { ++ Activity.HIDE, ++ Activity.PRE_RAID, ++ Activity.RAID, ++ Activity.PANIC ++ }; ++ ++ private static int checkInactiveWakeup(Entity entity) { ++ Level world = entity.level; ++ SpigotWorldConfig config = world.spigotConfig; ++ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; ++ if (entity.activationType == ActivationType.VILLAGER) { ++ if (inactiveFor > config.wakeUpInactiveVillagersEvery && world.wakeupInactiveRemainingVillagers > 0) { ++ world.wakeupInactiveRemainingVillagers--; ++ return config.wakeUpInactiveVillagersFor; ++ } ++ } else if (entity.activationType == ActivationType.ANIMAL) { ++ if (inactiveFor > config.wakeUpInactiveAnimalsEvery && world.wakeupInactiveRemainingAnimals > 0) { ++ world.wakeupInactiveRemainingAnimals--; ++ return config.wakeUpInactiveAnimalsFor; ++ } ++ } else if (entity.activationType == ActivationType.FLYING_MONSTER) { ++ if (inactiveFor > config.wakeUpInactiveFlyingEvery && world.wakeupInactiveRemainingFlying > 0) { ++ world.wakeupInactiveRemainingFlying--; ++ return config.wakeUpInactiveFlyingFor; ++ } ++ } else if (entity.activationType == ActivationType.MONSTER || entity.activationType == ActivationType.RAIDER) { ++ if (inactiveFor > config.wakeUpInactiveMonstersEvery && world.wakeupInactiveRemainingMonsters > 0) { ++ world.wakeupInactiveRemainingMonsters--; ++ return config.wakeUpInactiveMonstersFor; ++ } ++ } ++ return -1; ++ } ++ // Paper end + + static AABB maxBB = new AABB( 0, 0, 0, 0, 0, 0 ); + +@@ -55,10 +106,13 @@ public class ActivationRange + */ + public static ActivationType initializeEntityActivationType(Entity entity) + { ++ if (entity instanceof WaterAnimal) { return ActivationType.WATER; } // Paper ++ else if (entity instanceof Villager) { return ActivationType.VILLAGER; } // Paper ++ else if (entity instanceof FlyingMob && entity instanceof Enemy) { return ActivationType.FLYING_MONSTER; } // Paper - doing & Monster incase Flying no longer includes monster in future + if ( entity instanceof Raider ) + { + return ActivationType.RAIDER; +- } else if ( entity instanceof Monster || entity instanceof Slime ) ++ } else if ( entity instanceof Enemy ) // Paper - correct monster check + { + return ActivationType.MONSTER; + } else if ( entity instanceof PathfinderMob || entity instanceof AmbientCreature ) +@@ -79,10 +133,14 @@ public class ActivationRange + */ + public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) + { +- if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange == 0 ) +- || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange == 0 ) +- || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange == 0 ) +- || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange == 0 ) ++ if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.VILLAGER && config.villagerActivationRange <= 0 ) // Paper ++ || ( entity.activationType == ActivationType.WATER && config.waterActivationRange <= 0 ) // Paper ++ || ( entity.activationType == ActivationType.FLYING_MONSTER && config.flyingMonsterActivationRange <= 0 ) // Paper ++ || entity instanceof EyeOfEnder // Paper + || entity instanceof Player + || entity instanceof ThrowableProjectile + || entity instanceof EnderDragon +@@ -91,7 +149,7 @@ public class ActivationRange + || entity instanceof AbstractHurtingProjectile + || entity instanceof LightningBolt + || entity instanceof PrimedTnt +- || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks ++ || entity instanceof FallingBlockEntity // Paper - Always tick falling blocks + || entity instanceof EndCrystal + || entity instanceof FireworkRocketEntity + || entity instanceof ThrownTrident ) +@@ -115,10 +173,25 @@ public class ActivationRange + final int raiderActivationRange = world.spigotConfig.raiderActivationRange; + final int animalActivationRange = world.spigotConfig.animalActivationRange; + final int monsterActivationRange = world.spigotConfig.monsterActivationRange; ++ // Paper start ++ final int waterActivationRange = world.spigotConfig.waterActivationRange; ++ final int flyingActivationRange = world.spigotConfig.flyingMonsterActivationRange; ++ final int villagerActivationRange = world.spigotConfig.villagerActivationRange; ++ world.wakeupInactiveRemainingAnimals = Math.min(world.wakeupInactiveRemainingAnimals + 1, world.spigotConfig.wakeUpInactiveAnimals); ++ world.wakeupInactiveRemainingVillagers = Math.min(world.wakeupInactiveRemainingVillagers + 1, world.spigotConfig.wakeUpInactiveVillagers); ++ world.wakeupInactiveRemainingMonsters = Math.min(world.wakeupInactiveRemainingMonsters + 1, world.spigotConfig.wakeUpInactiveMonsters); ++ world.wakeupInactiveRemainingFlying = Math.min(world.wakeupInactiveRemainingFlying + 1, world.spigotConfig.wakeUpInactiveFlying); ++ final ServerChunkCache chunkProvider = (ServerChunkCache) world.getChunkSource(); ++ // Paper end + + int maxRange = Math.max( monsterActivationRange, animalActivationRange ); + maxRange = Math.max( maxRange, raiderActivationRange ); + maxRange = Math.max( maxRange, miscActivationRange ); ++ // Paper start ++ maxRange = Math.max( maxRange, flyingActivationRange ); ++ maxRange = Math.max( maxRange, waterActivationRange ); ++ maxRange = Math.max( maxRange, villagerActivationRange ); ++ // Paper end + maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); + + for ( Player player : world.players() ) +@@ -130,6 +203,11 @@ public class ActivationRange + ActivationType.RAIDER.boundingBox = player.getBoundingBox().inflate( raiderActivationRange, 256, raiderActivationRange ); + ActivationType.ANIMAL.boundingBox = player.getBoundingBox().inflate( animalActivationRange, 256, animalActivationRange ); + ActivationType.MONSTER.boundingBox = player.getBoundingBox().inflate( monsterActivationRange, 256, monsterActivationRange ); ++ // Paper start ++ ActivationType.WATER.boundingBox = player.getBoundingBox().inflate( waterActivationRange, 256, waterActivationRange ); ++ ActivationType.FLYING_MONSTER.boundingBox = player.getBoundingBox().inflate( flyingActivationRange, 256, flyingActivationRange ); ++ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().inflate( villagerActivationRange, 256, waterActivationRange ); ++ // Paper end + + int i = Mth.floor( maxBB.minX / 16.0D ); + int j = Mth.floor( maxBB.maxX / 16.0D ); +@@ -140,7 +218,7 @@ public class ActivationRange + { + for ( int j1 = k; j1 <= l; ++j1 ) + { +- LevelChunk chunk = (LevelChunk) world.getChunkIfLoadedImmediately( i1, j1 ); ++ LevelChunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper + if ( chunk != null ) + { + activateChunkEntities( chunk ); +@@ -158,19 +236,15 @@ public class ActivationRange + */ + private static void activateChunkEntities(LevelChunk chunk) + { +- for ( java.util.List slice : chunk.entitySlices ) +- { +- for ( Entity entity : (Collection) slice ) ++ // Paper start ++ Entity[] rawData = chunk.entities.getRawData(); ++ for (int i = 0; i < chunk.entities.size(); i++) { ++ Entity entity = rawData[i]; ++ //for ( Entity entity : (Collection) slice ) ++ // Paper end + { +- if ( MinecraftServer.currentTick > entity.activatedTick ) +- { +- if ( entity.defaultActivationState ) +- { +- entity.activatedTick = MinecraftServer.currentTick; +- continue; +- } +- if ( entity.activationType.boundingBox.intersects( entity.getBoundingBox() ) ) +- { ++ if (MinecraftServer.currentTick > entity.activatedTick) { ++ if (entity.defaultActivationState || entity.activationType.boundingBox.intersects(entity.getBoundingBox())) { // Paper + entity.activatedTick = MinecraftServer.currentTick; + } + } +@@ -185,56 +259,105 @@ public class ActivationRange + * @param entity + * @return + */ +- public static boolean checkEntityImmunities(Entity entity) ++ public static int checkEntityImmunities(Entity entity) // Paper - return # of ticks to get immunity + { ++ // Paper start ++ SpigotWorldConfig config = entity.level.spigotConfig; ++ int inactiveWakeUpImmunity = checkInactiveWakeup(entity); ++ if (inactiveWakeUpImmunity > -1) { ++ return inactiveWakeUpImmunity; ++ } ++ if (entity.remainingFireTicks > 0) { ++ return 2; ++ } ++ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; ++ // Paper end + // quick checks. +- if ( entity.wasTouchingWater || entity.remainingFireTicks > 0 ) ++ if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByWater()) ) // Paper + { +- return true; ++ return 100; // Paper + } + if ( !( entity instanceof AbstractArrow ) ) + { +- if ( !entity.isOnGround() || !entity.passengers.isEmpty() || entity.isPassenger() ) ++ if ( (!entity.isOnGround() && !(entity instanceof FlyingMob)) ) // Paper - remove passengers logic + { +- return true; ++ return 10; // Paper + } + } else if ( !( (AbstractArrow) entity ).inGround ) + { +- return true; ++ return 1; // Paper + } + // special cases. + if ( entity instanceof LivingEntity ) + { + LivingEntity living = (LivingEntity) entity; +- if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTime > 0 || living.activeEffects.size() > 0 ) ++ if ( living.onClimbable() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 ) // Paper + { +- return true; ++ return 1; // Paper + } +- if ( entity instanceof PathfinderMob && ( (PathfinderMob) entity ).getTarget() != null ) ++ if ( entity instanceof Mob && ((Mob) entity ).getTarget() != null) // Paper + { +- return true; ++ return 20; // Paper ++ } ++ // Paper start ++ if (entity instanceof Bee) { ++ Bee bee = (Bee)entity; ++ BlockPos movingTarget = bee.getMovingTarget(); ++ if (bee.isAngry() || ++ (bee.getHivePos() != null && bee.getHivePos().equals(movingTarget)) || ++ (bee.getSavedFlowerPos() != null && bee.getSavedFlowerPos().equals(movingTarget)) ++ ) { ++ return 20; ++ } ++ } ++ if ( entity instanceof Villager ) { ++ Brain behaviorController = ((Villager) entity).getBrain(); ++ ++ if (config.villagersActiveForPanic) { ++ for (Activity activity : VILLAGER_PANIC_IMMUNITIES) { ++ if (behaviorController.isActive(activity)) { ++ return 20*5; ++ } ++ } ++ } ++ ++ if (config.villagersWorkImmunityAfter > 0 && inactiveFor >= config.villagersWorkImmunityAfter) { ++ if (behaviorController.isActive(Activity.WORK)) { ++ return config.villagersWorkImmunityFor; ++ } ++ } + } +- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() ) ++ if ( entity instanceof Llama && ( (Llama) entity ).inCaravan() ) + { +- return true; ++ return 1; + } ++ // Paper end + if ( entity instanceof Animal ) + { + Animal animal = (Animal) entity; + if ( animal.isBaby() || animal.isInLove() ) + { +- return true; ++ return 5; // Paper + } + if ( entity instanceof Sheep && ( (Sheep) entity ).isSheared() ) + { +- return true; ++ return 1; // Paper + } + } + if (entity instanceof Creeper && ((Creeper) entity).isIgnited()) { // isExplosive +- return true; ++ return 20; // Paper + } ++ // Paper start ++ if (entity instanceof Mob && ((Mob) entity).targetSelector.hasTasks() ) { ++ return 0; ++ } ++ if (entity instanceof Pillager) { ++ Pillager pillager = (Pillager) entity; ++ // TODO:? ++ } ++ // Paper end + } +- return false; ++ return -1; // Paper + } + + /** +@@ -249,8 +372,19 @@ public class ActivationRange + if ( !entity.inChunk || entity instanceof FireworkRocketEntity ) { + return true; + } ++ // Paper start - special case always immunities ++ // immunize brand new entities, dead entities, and portal scenarios ++ if (entity.defaultActivationState || entity.tickCount < 20*10 || !entity.isAlive() || entity.isInsidePortal || entity.portalCooldown > 0) { ++ return true; ++ } ++ // immunize leashed entities ++ if (entity instanceof Mob && ((Mob)entity).leashHolder instanceof Player) { ++ return true; ++ } ++ // Paper end + +- boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; ++ boolean isActive = entity.activatedTick >= MinecraftServer.currentTick; ++ entity.isTemporarilyActive = false; // Paper + + // Should this entity tick? + if ( !isActive ) +@@ -258,15 +392,19 @@ public class ActivationRange + if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) + { + // Check immunities every 20 ticks. +- if ( checkEntityImmunities( entity ) ) +- { +- // Triggered some sort of immunity, give 20 full ticks before we check again. +- entity.activatedTick = MinecraftServer.currentTick + 20; ++ // Paper start ++ int immunity = checkEntityImmunities(entity); ++ if (immunity >= 0) { ++ entity.activatedTick = MinecraftServer.currentTick + immunity; ++ } else { ++ entity.isTemporarilyActive = true; + } ++ // Paper end + isActive = true; ++ + } + // Add a little performance juice to active entities. Skip 1/4 if not immune. +- } else if ( !entity.defaultActivationState && entity.tickCount % 4 == 0 && !checkEntityImmunities( entity ) ) ++ } else if (entity.tickCount % 4 == 0 && checkEntityImmunities( entity) < 0 ) // Paper + { + isActive = false; + } +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 34ee684901906fc2ef5f0d09680d2686b813e52b..6b015c1f26facb4e82d75b252164dec05731ca6c 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -180,13 +180,59 @@ public class SpigotWorldConfig + public int monsterActivationRange = 32; + public int raiderActivationRange = 48; + public int miscActivationRange = 16; ++ // Paper start ++ public int flyingMonsterActivationRange = 32; ++ public int waterActivationRange = 16; ++ public int villagerActivationRange = 32; ++ public int wakeUpInactiveAnimals = 4; ++ public int wakeUpInactiveAnimalsEvery = 60*20; ++ public int wakeUpInactiveAnimalsFor = 5*20; ++ public int wakeUpInactiveMonsters = 8; ++ public int wakeUpInactiveMonstersEvery = 20*20; ++ public int wakeUpInactiveMonstersFor = 5*20; ++ public int wakeUpInactiveVillagers = 4; ++ public int wakeUpInactiveVillagersEvery = 30*20; ++ public int wakeUpInactiveVillagersFor = 5*20; ++ public int wakeUpInactiveFlying = 8; ++ public int wakeUpInactiveFlyingEvery = 10*20; ++ public int wakeUpInactiveFlyingFor = 5*20; ++ public int villagersWorkImmunityAfter = 5*20; ++ public int villagersWorkImmunityFor = 20; ++ public boolean villagersActiveForPanic = true; ++ // Paper end + public boolean tickInactiveVillagers = true; + private void activationRange() + { ++ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", animalActivationRange) != animalActivationRange; // Paper + animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange ); + monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange ); + raiderActivationRange = getInt( "entity-activation-range.raiders", raiderActivationRange ); + miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange ); ++ // Paper start ++ waterActivationRange = getInt( "entity-activation-range.water", waterActivationRange ); ++ villagerActivationRange = getInt( "entity-activation-range.villagers", hasAnimalsConfig ? animalActivationRange : villagerActivationRange ); ++ flyingMonsterActivationRange = getInt( "entity-activation-range.flying-monsters", flyingMonsterActivationRange ); ++ ++ wakeUpInactiveAnimals = getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", wakeUpInactiveAnimals); ++ wakeUpInactiveAnimalsEvery = getInt("entity-activation-range.wake-up-inactive.animals-every", wakeUpInactiveAnimalsEvery); ++ wakeUpInactiveAnimalsFor = getInt("entity-activation-range.wake-up-inactive.animals-for", wakeUpInactiveAnimalsFor); ++ ++ wakeUpInactiveMonsters = getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", wakeUpInactiveMonsters); ++ wakeUpInactiveMonstersEvery = getInt("entity-activation-range.wake-up-inactive.monsters-every", wakeUpInactiveMonstersEvery); ++ wakeUpInactiveMonstersFor = getInt("entity-activation-range.wake-up-inactive.monsters-for", wakeUpInactiveMonstersFor); ++ ++ wakeUpInactiveVillagers = getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", wakeUpInactiveVillagers); ++ wakeUpInactiveVillagersEvery = getInt("entity-activation-range.wake-up-inactive.villagers-every", wakeUpInactiveVillagersEvery); ++ wakeUpInactiveVillagersFor = getInt("entity-activation-range.wake-up-inactive.villagers-for", wakeUpInactiveVillagersFor); ++ ++ wakeUpInactiveFlying = getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", wakeUpInactiveFlying); ++ wakeUpInactiveFlyingEvery = getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", wakeUpInactiveFlyingEvery); ++ wakeUpInactiveFlyingFor = getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", wakeUpInactiveFlyingFor); ++ ++ villagersWorkImmunityAfter = getInt( "entity-activation-range.villagers-work-immunity-after", villagersWorkImmunityAfter ); ++ villagersWorkImmunityFor = getInt( "entity-activation-range.villagers-work-immunity-for", villagersWorkImmunityFor ); ++ villagersActiveForPanic = getBoolean( "entity-activation-range.villagers-active-for-panic", villagersActiveForPanic ); ++ // Paper end + tickInactiveVillagers = getBoolean( "entity-activation-range.tick-inactive-villagers", tickInactiveVillagers ); + log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Ra " + raiderActivationRange + " / Mi " + miscActivationRange + " / Tiv " + tickInactiveVillagers ); + } diff --git a/Remapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch b/Remapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch new file mode 100644 index 0000000000..283ad7000c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AJMFactsheets +Date: Wed, 22 Jan 2020 19:52:28 -0600 +Subject: [PATCH] Fix items vanishing through end portal + +If the Paper configuration option "keep-spawn-loaded" is set to false, +items entering the overworld from the end will spawn at Y = 0. + +This is due to logic in the getHighestBlockYAt method in World.java +only searching the heightmap if the chunk is loaded. + +Quickly loading the exact world spawn chunk before searching the +heightmap resolves the issue without having to load all spawn chunks. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index c6881a9a5da2caed77dea30e4906d2dd99a624c1..efc9cb6def2f4ee327329dc090d2918ff60d8e19 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2734,6 +2734,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + BlockPos blockposition1; + + if (flag1) { ++ // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate ++ this.level.getChunkAt(this.level.getSpawn()); ++ // Paper end + blockposition1 = ServerLevel.END_SPAWN_POINT; + } else { + blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSpawn()); diff --git a/Remapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/Remapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch new file mode 100644 index 0000000000..f19be75b52 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 26 Jan 2020 16:30:19 -0600 +Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java +index 2c9e3dd1b9dd7bb8825a2eb9fecc2b2be348d055..868e9cdeb3c7effb398cef6f6f9c1e4fffa2db8c 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java +@@ -16,7 +16,7 @@ public class FlyingMoveControl extends MoveControl { + } + + @Override +- public void tick() { ++ public void tick() { tick(); } public void tick() { // Paper - OBFHELPER + if (this.operation == MoveControl.Operation.MOVE_TO) { + this.operation = MoveControl.Operation.WAIT; + this.mob.setNoGravity(true); +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java +index ab65f0327766463a5e53fdd723e243464319fdbe..f4984d601d14c684e75f887f5f5d2f5a29326b15 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java +@@ -16,7 +16,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; + + public class MoveControl { + +- protected final Mob mob; ++ protected final Mob mob; public final Mob getEntity() { return mob; } // Paper - OBFHELPER + protected double wantedX; + protected double wantedY; + protected double wantedZ; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java +index edd6d63f715acef1a77eba0cf46ff8267228f4c6..9b68809b91910d2bbb82cafe23d1de5dfff4221c 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -111,7 +111,17 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + + public Bee(EntityType type, Level world) { + super(type, world); +- this.moveControl = new FlyingMoveControl(this, 20, true); ++ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 ++ this.moveControl = new FlyingMoveControl(this, 20, true) { ++ @Override ++ public void tick() { ++ if (getEntity().getY() <= 0) { ++ getEntity().setNoGravity(false); ++ } ++ super.tick(); ++ } ++ }; ++ // Paper end + this.lookControl = new Bee.BeeLookControl(this); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); diff --git a/Remapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/Remapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch new file mode 100644 index 0000000000..009a0fad66 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 25 Jan 2020 17:04:35 -0800 +Subject: [PATCH] Optimise getChunkAt calls for loaded chunks + +bypass the need to get a player chunk, then get the either, +then unwrap it... + +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index eac5e799c4d26e53286a27c54b56899ba0b9ffb2..3aeb8426b0461ec572c1499116be80f968bb4104 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -470,6 +470,12 @@ public class ServerChunkCache extends ChunkSource { + return this.getChunk(x, z, leastStatus, create); + }, this.mainThreadProcessor).join(); + } else { ++ // Paper start - optimise for loaded chunks ++ LevelChunk ifLoaded = this.getChunkAtIfLoadedMainThread(x, z); ++ if (ifLoaded != null) { ++ return ifLoaded; ++ } ++ // Paper end + ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + + gameprofilerfiller.incrementCounter("getChunk"); +@@ -520,39 +526,7 @@ public class ServerChunkCache extends ChunkSource { + if (Thread.currentThread() != this.mainThread) { + return null; + } else { +- this.level.getProfiler().incrementCounter("getChunkNow"); +- long k = ChunkPos.asLong(chunkX, chunkZ); +- +- for (int l = 0; l < 4; ++l) { +- if (k == this.lastChunkPos[l] && this.lastChunkStatus[l] == ChunkStatus.FULL) { +- ChunkAccess ichunkaccess = this.lastChunk[l]; +- +- return ichunkaccess instanceof LevelChunk ? (LevelChunk) ichunkaccess : null; +- } +- } +- +- ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); +- +- if (playerchunk == null) { +- return null; +- } else { +- Either either = (Either) playerchunk.getFutureIfPresent(ChunkStatus.FULL).getNow(null); // CraftBukkit - decompile error +- +- if (either == null) { +- return null; +- } else { +- ChunkAccess ichunkaccess1 = (ChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error +- +- if (ichunkaccess1 != null) { +- this.storeInCache(k, ichunkaccess1, ChunkStatus.FULL); +- if (ichunkaccess1 instanceof LevelChunk) { +- return (LevelChunk) ichunkaccess1; +- } +- } +- +- return null; +- } +- } ++ return this.getChunkAtIfLoadedMainThread(chunkX, chunkZ); // Paper - optimise for loaded chunks + } + } + diff --git a/Remapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch b/Remapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch new file mode 100644 index 0000000000..04082e9a36 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 8 Feb 2020 18:02:24 -0600 +Subject: [PATCH] Allow overriding the java version check + +-DPaper.IgnoreJavaVersion=true + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 808a7688ed81bdfef623ee0a151ff8f94df2a3d7..c519ceca6f7788ca7c5d74ad1001dbc09f62681c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -181,7 +181,7 @@ public class Main { + float javaVersion = Float.parseFloat(System.getProperty("java.class.version")); + if (javaVersion > 60.0) { + System.err.println("Unsupported Java detected (" + javaVersion + "). Only up to Java 16 is supported."); +- return; ++ if (!Boolean.getBoolean("Paper.IgnoreJavaVersion")) return; // Paper + } + + try { diff --git a/Remapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch b/Remapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch new file mode 100644 index 0000000000..5bc9d2e683 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 9 Feb 2020 00:19:05 -0600 +Subject: [PATCH] Add ThrownEggHatchEvent + +Adds a new event similar to PlayerEggThrowEvent, but without the Player requirement +(dispensers can throw eggs to hatch them, too). + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java +index f3808a5e9155e1bf6c6219fc494864bb7dc61117..520eace73b569c2c77e76e0dfd18eb9c7188ec30 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java +@@ -63,6 +63,16 @@ public class ThrownEgg extends ThrowableItemProjectile { + hatchingType = event.getHatchingType(); + } + ++ // Paper start ++ com.destroystokyo.paper.event.entity.ThrownEggHatchEvent event = new com.destroystokyo.paper.event.entity.ThrownEggHatchEvent((org.bukkit.entity.Egg) getBukkitEntity(), hatching, b0, hatchingType); ++ event.callEvent(); ++ ++ b0 = event.getNumHatches(); ++ hatching = event.isHatching(); ++ hatchingType = event.getHatchingType(); ++ // Paper end ++ ++ + if (hatching) { + for (int i = 0; i < b0; ++i) { + Entity entity = level.getWorld().createEntity(new org.bukkit.Location(level.getWorld(), this.getX(), this.getY(), this.getZ(), this.yRot, 0.0F), hatchingType.getEntityClass()); diff --git a/Remapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch b/Remapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch new file mode 100644 index 0000000000..881f7be3f4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch @@ -0,0 +1,407 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 27 Jan 2020 21:28:00 -0800 +Subject: [PATCH] Optimise random block ticking + +Massive performance improvement for random block ticking. +The performance increase comes from the fact that the vast +majority of attempted block ticks (~95% in my testing) fail +because the randomly selected block is not tickable. + +Now only tickable blocks are targeted, however this means that +the maximum number of block ticks occurs per chunk. However, +not all chunks are going to be targeted. The percent chance +of a chunk being targeted is based on how many tickable blocks +are in the chunk. +This means that while block ticks are spread out less, the +total number of blocks ticked per world tick remains the same. +Therefore, the chance of a random tickable block being ticked +remains the same. + +diff --git a/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3edc8e52e06a62ce9f8cc734fd7458b37cfaad91 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java +@@ -0,0 +1,46 @@ ++package com.destroystokyo.paper.util.math; ++ ++import java.util.Random; ++ ++public final class ThreadUnsafeRandom extends Random { ++ ++ // See javadoc and internal comments for java.util.Random where these values come from, how they are used, and the author for them. ++ private static final long multiplier = 0x5DEECE66DL; ++ private static final long addend = 0xBL; ++ private static final long mask = (1L << 48) - 1; ++ ++ private static long initialScramble(long seed) { ++ return (seed ^ multiplier) & mask; ++ } ++ ++ private long seed; ++ ++ @Override ++ public void setSeed(long seed) { ++ // note: called by Random constructor ++ this.seed = initialScramble(seed); ++ } ++ ++ @Override ++ protected int next(int bits) { ++ // avoid the expensive CAS logic used by superclass ++ return (int) (((this.seed = this.seed * multiplier + addend) & mask) >>> (48 - bits)); ++ } ++ ++ // Taken from ++ // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ ++ // https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2016/06/25/fastrange.c ++ // Original license is public domain ++ public static int fastRandomBounded(final long randomInteger, final long limit) { ++ // randomInteger must be [0, pow(2, 32)) ++ // limit must be [0, pow(2, 32)) ++ return (int)((randomInteger * limit) >>> 32); ++ } ++ ++ @Override ++ public int nextInt(int bound) { ++ // yes this breaks random's spec ++ // however there's nothing that uses this class that relies on it ++ return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound); ++ } ++} +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index b13e5d05d862ea8c6031b8071f525f00bc48f7e7..3db77d9eda98eacb099135643aff5e94751f4c7c 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -468,6 +468,7 @@ public class BlockPos extends Vec3i { + return this.set(Mth.floor(x), Mth.floor(y), Mth.floor(z)); + } + ++ public final BlockPos.MutableBlockPos setValues(final Vec3i baseblockposition) { return this.set(baseblockposition); } // Paper - OBFHELPER + public BlockPos.MutableBlockPos set(Vec3i pos) { + return this.set(pos.getX(), pos.getY(), pos.getZ()); + } +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027ea23b400b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -669,7 +669,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + }); + } + +- public void tickChunk(LevelChunk chunk, int randomTickSpeed) { ++ // Paper start - optimise random block ticking ++ private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos(); ++ private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom(); ++ // Paper end ++ ++ public void tickChunk(LevelChunk chunk, int randomTickSpeed) { final int randomTickSpeed1 = randomTickSpeed; // Paper + ChunkPos chunkcoordintpair = chunk.getPos(); + boolean flag = this.isRaining(); + int j = chunkcoordintpair.getMinBlockX(); +@@ -677,10 +682,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + ProfilerFiller gameprofilerfiller = this.getProfiler(); + + gameprofilerfiller.push("thunder"); +- BlockPos blockposition; ++ final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change + + if (!this.paperConfig.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder +- blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); ++ blockposition.setValues(this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper + if (this.isRainingAt(blockposition)) { + DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); + boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance; // Paper +@@ -703,59 +708,77 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + gameprofilerfiller.popPush("iceandsnow"); +- if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow +- blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.getBlockRandomPos(j, 0, k, 15)); +- BlockPos blockposition1 = blockposition.below(); ++ if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking ++ // Paper start - optimise chunk ticking ++ this.getRandomBlockPosition(j, 0, k, 15, blockposition); ++ int normalY = chunk.getHighestBlockY(Heightmap.Types.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15); ++ int downY = normalY - 1; ++ blockposition.setY(normalY); ++ // Paper end + Biome biomebase = this.getBiome(blockposition); + +- if (biomebase.shouldFreeze(this, blockposition1)) { +- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.defaultBlockState(), null); // CraftBukkit ++ // Paper start - optimise chunk ticking ++ blockposition.setY(downY); ++ if (biomebase.shouldFreeze(this, blockposition)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.ICE.defaultBlockState(), null); // CraftBukkit ++ // Paper end + } + ++ blockposition.setY(normalY); // Paper + if (flag && biomebase.shouldSnow(this, blockposition)) { + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit + } + +- if (flag && this.getBiome(blockposition1).getPrecipitation() == Biome.Precipitation.RAIN) { +- this.getBlockState(blockposition1).getBlock().handleRain((net.minecraft.world.level.Level) this, blockposition1); ++ // Paper start - optimise chunk ticking ++ blockposition.setY(downY); ++ if (flag && this.getBiome(blockposition).getPrecipitation() == Biome.Precipitation.RAIN) { ++ chunk.getBlockState(blockposition).getBlock().handleRain((net.minecraft.world.level.Level) this, blockposition); ++ // Paper end + } + } + +- gameprofilerfiller.popPush("tickBlocks"); +- timings.chunkTicksBlocks.startTiming(); // Paper ++ // Paper start - optimise random block ticking ++ gameprofilerfiller.pop(); + if (randomTickSpeed > 0) { +- LevelChunkSection[] achunksection = chunk.getSections(); +- int l = achunksection.length; ++ gameprofilerfiller.push("randomTick"); ++ timings.chunkTicksBlocks.startTiming(); // Paper + +- for (int i1 = 0; i1 < l; ++i1) { +- LevelChunkSection chunksection = achunksection[i1]; ++ LevelChunkSection[] sections = chunk.getSections(); + +- if (chunksection != LevelChunk.EMPTY_SECTION && chunksection.isRandomlyTicking()) { +- int j1 = chunksection.bottomBlockY(); ++ for (int sectionIndex = 0; sectionIndex < 16; ++sectionIndex) { ++ LevelChunkSection section = sections[sectionIndex]; ++ if (section == null || section.tickingList.size() == 0) { ++ continue; ++ } + +- for (int k1 = 0; k1 < randomTickSpeed; ++k1) { +- BlockPos blockposition2 = this.getBlockRandomPos(j, j1, k, 15); ++ int yPos = sectionIndex << 4; + +- gameprofilerfiller.push("randomTick"); +- BlockState iblockdata = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); ++ for (int a = 0; a < randomTickSpeed1; ++a) { ++ int tickingBlocks = section.tickingList.size(); ++ int index = this.randomTickRandom.nextInt(16 * 16 * 16); ++ if (index >= tickingBlocks) { ++ continue; ++ } + +- if (iblockdata.isRandomlyTicking()) { +- iblockdata.randomTick(this, blockposition2, this.random); +- } ++ long raw = section.tickingList.getRaw(index); ++ int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); ++ int randomX = location & 15; ++ int randomY = ((location >>> (4 + 4)) & 255) | yPos; ++ int randomZ = (location >>> 4) & 15; + +- FluidState fluid = iblockdata.getFluidState(); ++ BlockPos blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ); ++ BlockState iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); + +- if (fluid.isRandomlyTicking()) { +- fluid.randomTick(this, blockposition2, this.random); +- } ++ iblockdata.randomTick(this, blockposition2, this.randomTickRandom); + +- gameprofilerfiller.pop(); +- } ++ // We drop the fluid tick since LAVA is ALREADY TICKED by the above method. ++ // TODO CHECK ON UPDATE + } + } ++ gameprofilerfiller.pop(); ++ timings.chunkTicksBlocks.stopTiming(); // Paper ++ // Paper end + } +- timings.chunkTicksBlocks.stopTiming(); // Paper +- gameprofilerfiller.pop(); + } + + protected BlockPos findLightingTargetAround(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java +index dd84984f28484cf7129c294222696784e128221a..9ea72751354e893cd3820befaa5df3e5e503de6e 100644 +--- a/src/main/java/net/minecraft/util/BitStorage.java ++++ b/src/main/java/net/minecraft/util/BitStorage.java +@@ -112,4 +112,32 @@ public class BitStorage { + } + + } ++ ++ // Paper start ++ public final void forEach(DataBitConsumer consumer) { ++ int i = 0; ++ long[] along = this.data; ++ int j = along.length; ++ ++ for (int k = 0; k < j; ++k) { ++ long l = along[k]; ++ ++ for (int i1 = 0; i1 < this.valuesPerLong; ++i1) { ++ consumer.accept(i, (int) (l & this.mask)); ++ l >>= this.bits; ++ ++i; ++ if (i >= this.size) { ++ return; ++ } ++ } ++ } ++ } ++ ++ @FunctionalInterface ++ public static interface DataBitConsumer { ++ ++ void accept(int location, int data); ++ ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +index 42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3..0e15ca2fb9cd1aeb4a075b8d50350dd7fd463c72 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +@@ -91,7 +91,7 @@ public class Turtle extends Animal { + } + + public void setHomePos(BlockPos pos) { +- this.entityData.set(Turtle.HOME_POS, pos); ++ this.entityData.set(Turtle.HOME_POS, pos.immutable()); // Paper - called with mutablepos... + } + + public BlockPos getHomePos() { // Paper - public +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 1d536d77518a70bdc1a23924aea99df1042b3cd5..632f32405053fbcff2fd26fa99f98c6add9f9dc7 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -1472,10 +1472,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public abstract TagContainer getTagManager(); + + public BlockPos getBlockRandomPos(int x, int y, int z, int l) { ++ // Paper start - allow use of mutable pos ++ BlockPos.MutableBlockPos ret = new BlockPos.MutableBlockPos(); ++ this.getRandomBlockPosition(x, y, z, l, ret); ++ return ret.immutable(); ++ } ++ public final BlockPos.MutableBlockPos getRandomBlockPosition(int i, int j, int k, int l, BlockPos.MutableBlockPos out) { ++ // Paper end + this.randValue = this.randValue * 3 + 1013904223; + int i1 = this.randValue >> 2; + +- return new BlockPos(x + (i1 & 15), y + (i1 >> 16 & l), z + (i1 >> 8 & 15)); ++ out.setValues(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); // Paper - change to setValues call ++ return out; // Paper + } + + public boolean noSave() { +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 4fef3abe4b416cbebe1b456468b5c3e162de18f1..87d7a87a2925f2c062658e960bb5128738828d9f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -639,8 +639,8 @@ public class LevelChunk implements ChunkAccess { + this.entities.remove(entity); // Paper + } + +- @Override +- public int getHeight(Heightmap.Types type, int x, int z) { ++ public final int getHighestBlockY(Heightmap.Types heightmap_type, int i, int j) { return this.getHeight(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1 ++ @Override public int getHeight(Heightmap.Types type, int x, int z) { // Paper + return ((Heightmap) this.heightmaps.get(type)).getFirstAvailable(x & 15, z & 15) - 1; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a71ad031d9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -14,12 +14,14 @@ import net.minecraft.world.level.material.FluidState; + public class LevelChunkSection { + + public static final Palette GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState()); +- private final int bottomBlockY; ++ final int bottomBlockY; // Paper - private -> package-private + short nonEmptyBlockCount; // Paper - package-private +- private short tickingBlockCount; ++ short tickingBlockCount; // Paper - private -> package-private + private short tickingFluidCount; + final PalettedContainer states; // Paper - package-private + ++ public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper ++ + // Paper start - Anti-Xray - Add parameters + @Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere + public LevelChunkSection(int i, ChunkAccess chunk, Level world, boolean initializeBlocks) { +@@ -74,6 +76,9 @@ public class LevelChunkSection { + --this.nonEmptyBlockCount; + if (iblockdata1.isRandomlyTicking()) { + --this.tickingBlockCount; ++ // Paper start ++ this.tickingList.remove(x, y, z); ++ // Paper end + } + } + +@@ -85,6 +90,9 @@ public class LevelChunkSection { + ++this.nonEmptyBlockCount; + if (state.isRandomlyTicking()) { + ++this.tickingBlockCount; ++ // Paper start ++ this.tickingList.add(x, y, z, state); ++ // Paper end + } + } + +@@ -120,23 +128,29 @@ public class LevelChunkSection { + } + + public void recalcBlockCounts() { ++ // Paper start ++ this.tickingList.clear(); ++ // Paper end + this.nonEmptyBlockCount = 0; + this.tickingBlockCount = 0; + this.tickingFluidCount = 0; +- this.states.count((iblockdata, i) -> { ++ this.states.forEachLocation((iblockdata, location) -> { // Paper + FluidState fluid = iblockdata.getFluidState(); + + if (!iblockdata.isAir()) { +- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); ++ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); + if (iblockdata.isRandomlyTicking()) { +- this.tickingBlockCount = (short) (this.tickingBlockCount + i); ++ this.tickingBlockCount = (short) (this.tickingBlockCount + 1); ++ // Paper start ++ this.tickingList.add(location, iblockdata); ++ // Paper end + } + } + + if (!fluid.isEmpty()) { +- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); ++ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); + if (fluid.isRandomlyTicking()) { +- this.tickingFluidCount = (short) (this.tickingFluidCount + i); ++ this.tickingFluidCount = (short) (this.tickingFluidCount + 1); + } + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index dd252372e1e380674b1191e9ea265cbb10de437b..f93316b3ae5cd5fb960fa24f8c921b5b9276d9f3 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -285,6 +285,14 @@ public class PalettedContainer implements PaletteResize { + }); + } + ++ // Paper start ++ public void forEachLocation(PalettedContainer.CountConsumer datapaletteblock_a) { ++ this.getDataBits().forEach((int location, int data) -> { ++ datapaletteblock_a.accept(this.getDataPalette().getObject(data), location); ++ }); ++ } ++ // Paper end ++ + @FunctionalInterface + public interface CountConsumer { + diff --git a/Remapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch b/Remapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch new file mode 100644 index 0000000000..15c22b27a5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 8 Feb 2020 23:26:11 -0600 +Subject: [PATCH] Entity Jump API + + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index b84dab1043c56e2deb58aec8639226f98db165d1..43fbe7d220f61802ae0cb0620ad078c5df7b69bc 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -2873,8 +2873,10 @@ public abstract class LivingEntity extends Entity { + } else if (this.isInLava() && (!this.onGround || d7 > d8)) { + this.jumpInLiquid((Tag) FluidTags.LAVA); + } else if ((this.onGround || flag && d7 <= d8) && this.noJumpDelay == 0) { ++ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper + this.jumpFromGround(); + this.noJumpDelay = 10; ++ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop + } + } else { + this.noJumpDelay = 0; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java +index 1621d8748e96c6e1abb33b699a1273bb698f67d2..423bdbe25b6f2261cb5092378b0564a82faeecb4 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Panda.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java +@@ -489,7 +489,9 @@ public class Panda extends Animal { + Panda entitypanda = (Panda) iterator.next(); + + if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.canPerformAction()) { ++ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper + entitypanda.jumpFromGround(); ++ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop + } + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index a01bd035846df0e2e28dc55e2ef2f5f35b83f905..5dac3bf5a117bfbf57798238f0614558deafcd1b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -792,5 +792,19 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public org.bukkit.inventory.EquipmentSlot getHandRaised() { + return getHandle().getUsedItemHand() == net.minecraft.world.InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; + } ++ ++ @Override ++ public boolean isJumping() { ++ return getHandle().jumping; ++ } ++ ++ @Override ++ public void setJumping(boolean jumping) { ++ getHandle().setJumping(jumping); ++ if (jumping && getHandle() instanceof Mob) { ++ // this is needed to actually make a mob jump ++ ((Mob) getHandle()).getJumpControl().jump(); ++ } ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch b/Remapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch new file mode 100644 index 0000000000..d66918d012 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 7 Feb 2020 14:36:56 -0600 +Subject: [PATCH] Add option to nerf pigmen from nether portals + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 7fbd501d70dccf869a4454e2789a5d68f2e15754..9e4591ddc4b755f4ff5a6f1078b51cb13db80480 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -594,4 +594,9 @@ public class PaperWorldConfig { + disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); + log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); + } ++ ++ public boolean nerfNetherPortalPigmen = false; ++ private void nerfNetherPortalPigmen() { ++ nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index efc9cb6def2f4ee327329dc090d2918ff60d8e19..43f77d01fceab107d3502d282205aa579d64cc4b 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -277,6 +277,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public long activatedTick = Integer.MIN_VALUE; + public boolean isTemporarilyActive = false; // Paper + public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one ++ public boolean fromNetherPortal; // Paper + protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end +@@ -1693,6 +1694,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + if (spawnedViaMobSpawner) { + tag.putBoolean("Paper.FromMobSpawner", true); + } ++ if (fromNetherPortal) { ++ tag.putBoolean("Paper.FromNetherPortal", true); ++ } + // Paper end + return tag; + } catch (Throwable throwable) { +@@ -1827,6 +1831,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ fromNetherPortal = tag.getBoolean("Paper.FromNetherPortal"); + if (tag.contains("Paper.SpawnReason")) { + String spawnReasonName = tag.getString("Paper.SpawnReason"); + try { +diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +index 805d83a93bce20910d17c3f419bc085251b6cfc1..ae58929886921d0714bf811de92f99dc0dc120dc 100644 +--- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -8,6 +8,7 @@ import net.minecraft.network.chat.Component; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; +@@ -61,6 +62,8 @@ public class NetherPortalBlock extends Block { + + if (entity != null) { + entity.setPortalCooldown(); ++ entity.fromNetherPortal = true; // Paper ++ if (world.paperConfig.nerfNetherPortalPigmen) ((Mob) entity).aware = false; // Paper + } + } + } diff --git a/Remapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch b/Remapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch new file mode 100644 index 0000000000..c98d2918e6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch @@ -0,0 +1,439 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 2 Feb 2020 04:00:40 -0600 +Subject: [PATCH] Make the GUI graph fancier + + +diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphColor.java b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a4e641fdcccd3efcd1a2865dc6dc28d50671b995 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java +@@ -0,0 +1,44 @@ ++package com.destroystokyo.paper.gui; ++ ++import java.awt.Color; ++ ++public class GraphColor { ++ private static final Color[] colorLine = new Color[101]; ++ private static final Color[] colorFill = new Color[101]; ++ ++ static { ++ for (int i = 0; i < 101; i++) { ++ Color color = createColor(i); ++ colorLine[i] = new Color(color.getRed() / 2, color.getGreen() / 2, color.getBlue() / 2, 255); ++ colorFill[i] = new Color(colorLine[i].getRed(), colorLine[i].getGreen(), colorLine[i].getBlue(), 125); ++ } ++ } ++ ++ public static Color getLineColor(int percent) { ++ return colorLine[percent]; ++ } ++ ++ public static Color getFillColor(int percent) { ++ return colorFill[percent]; ++ } ++ ++ private static Color createColor(int percent) { ++ if (percent <= 50) { ++ return new Color(0X00FF00); ++ } ++ ++ int value = 510 - (int) (Math.min(Math.max(0, ((percent - 50) / 50F)), 1) * 510); ++ ++ int red, green; ++ if (value < 255) { ++ red = 255; ++ green = (int) (Math.sqrt(value) * 16); ++ } else { ++ green = 255; ++ value = value - 255; ++ red = 255 - (value * value / 255); ++ } ++ ++ return new Color(red, green, 0); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphData.java b/src/main/java/com/destroystokyo/paper/gui/GraphData.java +new file mode 100644 +index 0000000000000000000000000000000000000000..186fc722965e403f76b1480e1c2381fc34e29049 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/GraphData.java +@@ -0,0 +1,47 @@ ++package com.destroystokyo.paper.gui; ++ ++import java.awt.Color; ++ ++public class GraphData { ++ private long total; ++ private long free; ++ private long max; ++ private long usedMem; ++ private int usedPercent; ++ ++ public GraphData(long total, long free, long max) { ++ this.total = total; ++ this.free = free; ++ this.max = max; ++ this.usedMem = total - free; ++ this.usedPercent = usedMem == 0 ? 0 : (int) (usedMem * 100L / max); ++ } ++ ++ public long getTotal() { ++ return total; ++ } ++ ++ public long getFree() { ++ return free; ++ } ++ ++ public long getMax() { ++ return max; ++ } ++ ++ public long getUsedMem() { ++ return usedMem; ++ } ++ ++ public int getUsedPercent() { ++ return usedPercent; ++ } ++ ++ public Color getFillColor() { ++ return GraphColor.getFillColor(usedPercent); ++ } ++ ++ public Color getLineColor() { ++ return GraphColor.getLineColor(usedPercent); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0f29ad583e798c09b2fe3f568ed50cbc719e40e2 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.gui; ++ ++import net.minecraft.server.MinecraftServer; ++ ++import javax.swing.JPanel; ++import javax.swing.Timer; ++import java.awt.BorderLayout; ++import java.awt.Dimension; ++ ++public class GuiStatsComponent extends JPanel { ++ private final Timer timer; ++ private final RAMGraph ramGraph; ++ ++ public GuiStatsComponent(MinecraftServer server) { ++ super(new BorderLayout()); ++ ++ setOpaque(false); ++ ++ ramGraph = new RAMGraph(); ++ RAMDetails ramDetails = new RAMDetails(server); ++ ++ add(ramGraph, "North"); ++ add(ramDetails, "Center"); ++ ++ timer = new Timer(500, (event) -> { ++ ramGraph.update(); ++ ramDetails.update(); ++ }); ++ timer.start(); ++ } ++ ++ @Override ++ public Dimension getPreferredSize() { ++ return new Dimension(350, 200); ++ } ++ ++ public void stop() { a(); } public void a() { ++ timer.stop(); ++ ramGraph.stop(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c0923ec75ecced2e0a1c0d3ec2c046d69af3e9a9 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +@@ -0,0 +1,73 @@ ++package com.destroystokyo.paper.gui; ++ ++import net.minecraft.Util; ++import net.minecraft.server.MinecraftServer; ++ ++import javax.swing.DefaultListCellRenderer; ++import javax.swing.DefaultListSelectionModel; ++import javax.swing.JList; ++import javax.swing.border.EmptyBorder; ++import java.awt.Dimension; ++import java.text.DecimalFormat; ++import java.text.DecimalFormatSymbols; ++import java.util.Locale; ++import java.util.Vector; ++ ++public class RAMDetails extends JList { ++ public static final DecimalFormat DECIMAL_FORMAT = Util.peek(new DecimalFormat("########0.000"), (format) ++ -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT))); ++ ++ private final MinecraftServer server; ++ ++ public RAMDetails(MinecraftServer server) { ++ this.server = server; ++ ++ setBorder(new EmptyBorder(0, 10, 0, 0)); ++ setFixedCellHeight(20); ++ setOpaque(false); ++ ++ DefaultListCellRenderer renderer = new DefaultListCellRenderer(); ++ renderer.setOpaque(false); ++ setCellRenderer(renderer); ++ ++ setSelectionModel(new DefaultListSelectionModel() { ++ @Override ++ public void setAnchorSelectionIndex(final int anchorIndex) { ++ } ++ ++ @Override ++ public void setLeadAnchorNotificationEnabled(final boolean flag) { ++ } ++ ++ @Override ++ public void setLeadSelectionIndex(final int leadIndex) { ++ } ++ ++ @Override ++ public void setSelectionInterval(final int index0, final int index1) { ++ } ++ }); ++ } ++ ++ @Override ++ public Dimension getPreferredSize() { ++ return new Dimension(350, 100); ++ } ++ ++ public void update() { ++ GraphData data = RAMGraph.DATA.peekLast(); ++ Vector vector = new Vector<>(); ++ vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); ++ vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); ++ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); ++ setListData(vector); ++ } ++ ++ public double getAverage(long[] tickTimes) { ++ long total = 0L; ++ for (long value : tickTimes) { ++ total += value; ++ } ++ return ((double) total / (double) tickTimes.length) * 1.0E-6D; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c3e54da4ab6440811aab2f9dd1e218802ac13285 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java +@@ -0,0 +1,144 @@ ++package com.destroystokyo.paper.gui; ++ ++import javax.swing.JComponent; ++import javax.swing.SwingUtilities; ++import javax.swing.Timer; ++import javax.swing.ToolTipManager; ++import java.awt.Color; ++import java.awt.Dimension; ++import java.awt.Graphics; ++import java.awt.MouseInfo; ++import java.awt.Point; ++import java.awt.PointerInfo; ++import java.awt.event.MouseAdapter; ++import java.awt.event.MouseEvent; ++import java.text.SimpleDateFormat; ++import java.util.Date; ++import java.util.LinkedList; ++import java.util.concurrent.TimeUnit; ++ ++public class RAMGraph extends JComponent { ++ public static final LinkedList DATA = new LinkedList() { ++ @Override ++ public boolean add(GraphData data) { ++ if (size() >= 348) { ++ remove(); ++ } ++ return super.add(data); ++ } ++ }; ++ ++ static { ++ GraphData empty = new GraphData(0, 0, 0); ++ for (int i = 0; i < 350; i++) { ++ DATA.add(empty); ++ } ++ } ++ ++ private final Timer timer; ++ private final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); ++ ++ private int currentTick; ++ ++ public RAMGraph() { ++ ToolTipManager.sharedInstance().setInitialDelay(0); ++ ++ addMouseListener(new MouseAdapter() { ++ final int defaultDismissTimeout = ToolTipManager.sharedInstance().getDismissDelay(); ++ final int dismissDelayMinutes = (int) TimeUnit.MINUTES.toMillis(10); ++ ++ @Override ++ public void mouseEntered(MouseEvent me) { ++ ToolTipManager.sharedInstance().setDismissDelay(dismissDelayMinutes); ++ } ++ ++ @Override ++ public void mouseExited(MouseEvent me) { ++ ToolTipManager.sharedInstance().setDismissDelay(defaultDismissTimeout); ++ } ++ }); ++ ++ timer = new Timer(50, (event) -> repaint()); ++ timer.start(); ++ } ++ ++ @Override ++ public Dimension getPreferredSize() { ++ return new Dimension(350, 110); ++ } ++ ++ public void update() { ++ Runtime jvm = Runtime.getRuntime(); ++ DATA.add(new GraphData(jvm.totalMemory(), jvm.freeMemory(), jvm.maxMemory())); ++ ++ PointerInfo pointerInfo = MouseInfo.getPointerInfo(); ++ if (pointerInfo != null) { ++ Point point = pointerInfo.getLocation(); ++ if (point != null) { ++ Point loc = new Point(point); ++ SwingUtilities.convertPointFromScreen(loc, this); ++ if (this.contains(loc)) { ++ ToolTipManager.sharedInstance().mouseMoved( ++ new MouseEvent(this, -1, System.currentTimeMillis(), 0, loc.x, loc.y, ++ point.x, point.y, 0, false, 0)); ++ } ++ } ++ } ++ ++ currentTick++; ++ } ++ ++ @Override ++ public void paint(Graphics graphics) { ++ graphics.setColor(new Color(0xFFFFFFFF)); ++ graphics.fillRect(0, 0, 350, 100); ++ ++ graphics.setColor(new Color(0x888888)); ++ graphics.drawLine(1, 25, 348, 25); ++ graphics.drawLine(1, 50, 348, 50); ++ graphics.drawLine(1, 75, 348, 75); ++ ++ int i = 0; ++ for (GraphData data : DATA) { ++ i++; ++ if ((i + currentTick) % 120 == 0) { ++ graphics.setColor(new Color(0x888888)); ++ graphics.drawLine(i, 1, i, 99); ++ } ++ int used = data.getUsedPercent(); ++ if (used > 0) { ++ Color color = data.getLineColor(); ++ graphics.setColor(data.getFillColor()); ++ graphics.fillRect(i, 100 - used, 1, used); ++ graphics.setColor(color); ++ graphics.fillRect(i, 100 - used, 1, 1); ++ } ++ } ++ ++ graphics.setColor(new Color(0xFF000000)); ++ graphics.drawRect(0, 0, 348, 100); ++ ++ Point m = getMousePosition(); ++ if (m != null && m.x > 0 && m.x < 348 && m.y > 0 && m.y < 100) { ++ GraphData data = DATA.get(m.x); ++ int used = data.getUsedPercent(); ++ graphics.setColor(new Color(0x000000)); ++ graphics.drawLine(m.x, 1, m.x, 99); ++ graphics.drawOval(m.x - 2, 100 - used - 2, 5, 5); ++ graphics.setColor(data.getLineColor()); ++ graphics.fillOval(m.x - 2, 100 - used - 2, 5, 5); ++ setToolTipText(String.format("Used: %s mb (%s%%)
    %s", ++ Math.round(data.getUsedMem() / 1024F / 1024F), ++ used, getTime(m.x))); ++ } ++ } ++ ++ public String getTime(int halfSeconds) { ++ int millis = (348 - halfSeconds) / 2 * 1000; ++ return TIME_FORMAT.format(new Date((System.currentTimeMillis() - millis))); ++ } ++ ++ public void stop() { ++ timer.stop(); ++ } ++} +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index cec5ad5052c8cf6059e9b117117846bdb217748f..c2f747226f10479c826849af898538610a2dd659 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -259,6 +259,7 @@ public class Util { + return factory.get(); + } + ++ public static T peek(T t0, Consumer consumer) { return make(t0, consumer); } // Paper - OBFHELPER + public static T make(T object, Consumer initializer) { + initializer.accept(object); + return object; +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 7038897b8fb4c18ca97b95a3b24c30b40b62b005..e33189dc8375a3034910087654607fb531061636 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -216,7 +216,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { ++ private static final DecimalFormat DECIMAL_FORMAT = (DecimalFormat) Util.make(new DecimalFormat("########0.000"), (decimalformat) -> { // Paper - decompile error + decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); + }); + private final int[] values = new int[256]; diff --git a/Remapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch b/Remapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch new file mode 100644 index 0000000000..e93352bf03 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Sun, 1 Mar 2020 22:43:24 +0100 +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 e696d2e52532df25d74a1f559e2c9ca0f3d5058d..7d9a3b65b2d6b294d3a11414289e64fac88665f0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -337,13 +337,18 @@ public class CraftEventFactory { + } + + org.bukkit.inventory.ItemStack item; ++ //Paper start - add hand to BlockMultiPlaceEvent ++ EquipmentSlot equipmentSlot; + if (hand == InteractionHand.MAIN_HAND) { + item = player.getInventory().getItemInMainHand(); ++ equipmentSlot = EquipmentSlot.HAND; + } else { + item = player.getInventory().getItemInOffHand(); ++ equipmentSlot = EquipmentSlot.OFF_HAND; + } + +- BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild); ++ BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild, equipmentSlot); ++ //Paper end + craftServer.getPluginManager().callEvent(event); + + return event; diff --git a/Remapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch b/Remapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch new file mode 100644 index 0000000000..ef6164bd27 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 3 Mar 2020 05:26:40 +0000 +Subject: [PATCH] Prevent teleporting dead entities + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 2b79413bb8a592a7b7093e11d3a0cce895286c8f..09a663cc53cdf8ae45352b280200c8170dbbcdfc 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1468,6 +1468,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + + private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { ++ if (player.removed) { ++ LOGGER.info("Attempt to teleport dead player {} restricted", player.getScoreboardName()); ++ return; ++ } + // CraftBukkit start + if (Float.isNaN(f)) { + f = 0; diff --git a/Remapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch b/Remapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch new file mode 100644 index 0000000000..8fbefb7aec --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 7 Mar 2020 00:07:51 +0000 +Subject: [PATCH] Validate tripwire hook placement before update + + +diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java +index f44d4809fe87c832e4d3bda429af2254e8c746d6..20428aff54527b664d988a6a0f54236b693fda89 100644 +--- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java +@@ -169,6 +169,7 @@ public class TripWireHookBlock extends Block { + + this.playSound(world, pos, flag4, flag5, flag2, flag3); + if (!beingRemoved) { ++ if (world.getBlockState(pos).getBlock() == Blocks.TRIPWIRE_HOOK) // Paper - validate + world.setBlock(pos, (BlockState) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection), 3); + if (flag1) { + this.notifyNeighbors(world, pos, enumdirection); diff --git a/Remapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/Remapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch new file mode 100644 index 0000000000..163f5b9240 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 13 Apr 2019 16:50:58 -0500 +Subject: [PATCH] Add option to allow iron golems to spawn in air + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 9e4591ddc4b755f4ff5a6f1078b51cb13db80480..fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -387,6 +387,11 @@ public class PaperWorldConfig { + scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); + } + ++ public boolean ironGolemsCanSpawnInAir = false; ++ private void ironGolemsCanSpawnInAir() { ++ ironGolemsCanSpawnInAir = getBoolean("iron-golems-can-spawn-in-air", ironGolemsCanSpawnInAir); ++ } ++ + public boolean armorStandEntityLookups = true; + private void armorStandEntityLookups() { + armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); +diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +index 9cedac83304847bdc92c2e97c4e6e119664c3bd0..59f0224b6a743408a03b642dd7cbe545f406c57e 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java ++++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +@@ -297,7 +297,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { + BlockPos blockposition1 = blockposition.below(); + BlockState iblockdata = world.getBlockState(blockposition1); + +- if (!iblockdata.entityCanStandOn((BlockGetter) world, blockposition1, (Entity) this)) { ++ if (!iblockdata.entityCanStandOn((BlockGetter) world, blockposition1, (Entity) this) && !level.paperConfig.ironGolemsCanSpawnInAir) { // Paper + return false; + } else { + for (int i = 1; i < 3; ++i) { diff --git a/Remapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch b/Remapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch new file mode 100644 index 0000000000..1bf93843e4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zero +Date: Sat, 22 Feb 2020 16:10:31 -0500 +Subject: [PATCH] Configurable chance of villager zombie infection + +This allows you to solve an issue in vanilla behavior where: +* On easy difficulty your villagers will NEVER get infected, meaning they will always die. +* On normal difficulty they will have a 50% of getting infected or dying. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f..525d702d78a609af987ebd2c32169b873e5c05ed 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -604,4 +604,9 @@ public class PaperWorldConfig { + private void nerfNetherPortalPigmen() { + nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); + } ++ ++ public double zombieVillagerInfectionChance = -1.0; ++ private void zombieVillagerInfectionChance() { ++ zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 6fecf4188fc0247143edc688c03e645376960687..1e7c2c603b967c8c606efd94ce95a17c856f78d7 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -447,10 +447,14 @@ public class Zombie extends Monster { + @Override + public void killed(ServerLevel worldserver, LivingEntity entityliving) { + super.killed(worldserver, entityliving); +- if ((worldserver.getDifficulty() == Difficulty.NORMAL || worldserver.getDifficulty() == Difficulty.HARD) && entityliving instanceof Villager) { +- if (worldserver.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { ++ // Paper start ++ if (level.paperConfig.zombieVillagerInfectionChance != 0.0 && (level.paperConfig.zombieVillagerInfectionChance != -1.0 || worldserver.getDifficulty() == Difficulty.NORMAL || worldserver.getDifficulty() == Difficulty.HARD) && entityliving instanceof Villager) { ++ if (level.paperConfig.zombieVillagerInfectionChance == -1.0 && worldserver.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { + return; + } ++ if (level.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > level.paperConfig.zombieVillagerInfectionChance) { ++ return; ++ } // Paper end + + Villager entityvillager = (Villager) entityliving; + // CraftBukkit start diff --git a/Remapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch b/Remapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch new file mode 100644 index 0000000000..2ba043c076 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 14 Jan 2020 14:59:08 -0800 +Subject: [PATCH] Optimise Chunk#getFluid + +Removing the try catch and generally reducing ops should make it +faster on its own, however removing the try catch makes it +easier to inline due to code size + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 87d7a87a2925f2c062658e960bb5128738828d9f..8a14bdda4a408ec1e2b51efeb35467835f62b42c 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -430,25 +430,29 @@ public class LevelChunk implements ChunkAccess { + } + + public FluidState getFluidState(int x, int y, int z) { +- try { +- if (y >= 0 && y >> 4 < this.sections.length) { +- LevelChunkSection chunksection = this.sections[y >> 4]; +- +- if (!LevelChunkSection.isEmpty(chunksection)) { +- return chunksection.getFluidState(x & 15, y & 15, z & 15); ++ //try { // Paper - remove try catch ++ // Paper start - reduce the number of ops in this call ++ int index = y >> 4; ++ if (index >= 0 && index < this.sections.length) { ++ LevelChunkSection chunksection = this.sections[index]; ++ ++ if (chunksection != null) { ++ return chunksection.states.get((y & 15) << 8 | (z & 15) << 4 | x & 15).getFluidState(); + } ++ // Paper end + } + + return Fluids.EMPTY.defaultFluidState(); +- } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state"); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got"); ++ /*} catch (Throwable throwable) { // Paper - remove try catch ++ CrashReport crashreport = CrashReport.a(throwable, "Getting fluid state"); ++ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being got"); + +- crashreportsystemdetails.setDetail("Location", () -> { +- return CrashReportCategory.formatLocation(x, y, z); ++ crashreportsystemdetails.a("Location", () -> { ++ return CrashReportSystemDetails.a(i, j, k); + }); + throw new ReportedException(crashreport); + } ++ */ // Paper - remove try catch + } + + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index c44d32f966c61497b4a8892eb51da3a71ad031d9..5e7f6000df129100ef306703f325af9f60da8ae6 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -45,7 +45,7 @@ public class LevelChunkSection { + } + + public FluidState getFluidState(int x, int y, int z) { +- return ((BlockState) this.states.get(x, y, z)).getFluidState(); ++ return ((BlockState) this.states.get(x, y, z)).getFluidState(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid. + } + + public void acquire() { diff --git a/Remapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch b/Remapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch new file mode 100644 index 0000000000..6cf945010b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch @@ -0,0 +1,1301 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 14 Feb 2020 01:24:39 -0800 +Subject: [PATCH] Optimise TickListServer by rewriting it + +In my profiling TickListServer showed up as +~10% for saving chunks and ~5% for the scheduling +of items on a server with ~90 players at +view distance = 5. Most of the performance +loss is unneccessary. + +TickListServer has numerous performance issues: + 1. Handling scheduled items is O(nlogn) + 2. Getting scheduled items for a chunk is O(n), + with n being the the number of scheduled items + for all chunks (hits saving very hard) + 3. Checking if an item is scheduled for the current tick is O(n), + with n being the number of items scheduled for current tick + 4. Items not in ticking chunks are churned in the scheduler + +The biggest issues are 4 & 2. + +We solve 1 by splitting up scheduled items into short and long scheduled, +where we expect the vast majority of our entries to be in the short scheduled +set. Handling short scheduled items is O(n) due to how the comparison +process is reduced to mapping. See TickListServerInterval. However, +this isn't memory-efficient - which is why long scheduled exists. +Long scheduled is handled the same as TickListServer. + +2 is solved by mapping what entries are in what chunks. + +3 is solved by mapping what blocks have what scheduled for them. + +4 is solved by moving the items that are not in ticking chunks +into a map of entries for that chunk. Once the chunk is moved +to ticking, the items are re-scheduled. + +This patch has also added two flags to debug excessive tick delays: +-Dpaper.ticklist-warn-on-excessive-delay=true (false by default) +and -Dpaper.ticklist-excessive-delay-threshold=ticks which +sets the excessive tick delay to the specified ticks (defaults to +60 * 20 ticks, aka 60 seconds) + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 8bf4d2b8c38c02d6a5b2fea37113689a252f1571..da93d38fe63035e4ff198ada84a4431f52d97c01 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -354,6 +354,13 @@ public class PaperConfig { + maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); + } + ++ public static boolean useOptimizedTickList = true; ++ private static void useOptimizedTickList() { ++ if (config.contains("settings.use-optimized-ticklist")) { // don't add default, hopefully temporary config ++ useOptimizedTickList = config.getBoolean("settings.use-optimized-ticklist"); ++ } ++ } ++ + public static boolean asyncChunks = false; + private static void asyncChunks() { + ConfigurationSection section; +diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2d579909b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java +@@ -0,0 +1,628 @@ ++package com.destroystokyo.paper.server.ticklist; ++ ++import java.util.function.Function; ++import net.minecraft.CrashReport; ++import net.minecraft.CrashReportCategory; ++import net.minecraft.ReportedException; ++import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.ServerTickList; ++import net.minecraft.world.level.TickNextTickData; ++import net.minecraft.world.level.TickPriority; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.levelgen.structure.BoundingBox; ++import it.unimi.dsi.fastutil.longs.Long2ObjectMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; ++import java.util.ArrayDeque; ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.Comparator; ++import java.util.Iterator; ++import java.util.List; ++import java.util.function.Consumer; ++import java.util.function.Predicate; ++ ++public final class PaperTickList extends ServerTickList { // extend to avoid breaking ABI ++ ++ // in the order the state is expected to change (mostly) ++ public static final int STATE_UNSCHEDULED = 1 << 0; ++ public static final int STATE_SCHEDULED = 1 << 1; // scheduled for some tick ++ public static final int STATE_PENDING_TICK = 1 << 2; // for this tick ++ public static final int STATE_TICKING = 1 << 3; ++ public static final int STATE_TICKED = 1 << 4; // after this, it gets thrown back to unscheduled ++ public static final int STATE_CANCELLED_TICK = 1 << 5; // still gets moved to unscheduled after tick ++ ++ private static final int SHORT_SCHEDULE_TICK_THRESHOLD = 20 * 20 + 1; // 20 seconds ++ ++ private final ServerLevel world; ++ private final Predicate excludeFromScheduling; ++ private final Function getMinecraftKeyFrom; ++ //private final Function getObjectFronMinecraftKey; ++ private final Consumer> tickFunction; ++ ++ private final co.aikar.timings.Timing timingCleanup; // Paper ++ private final co.aikar.timings.Timing timingTicking; // Paper ++ private final co.aikar.timings.Timing timingFinished; ++ ++ // note: remove ops / add ops suck on fastutil, a chained hashtable implementation would work better, but Long... ++ // try to alleviate with a very small load factor ++ private final Long2ObjectOpenHashMap>> entriesByBlock = new Long2ObjectOpenHashMap<>(1024, 0.25f); ++ private final Long2ObjectOpenHashMap>> entriesByChunk = new Long2ObjectOpenHashMap<>(1024, 0.25f); ++ private final Long2ObjectOpenHashMap>> pendingChunkTickLoad = new Long2ObjectOpenHashMap<>(1024, 0.5f); ++ ++ // fastutil has O(1) first/last while TreeMap/TreeSet are log(n) ++ private final ObjectRBTreeSet> longScheduled = new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); ++ ++ private final ArrayDeque> toTickThisTick = new ArrayDeque<>(); ++ ++ private final TickListServerInterval[] shortScheduled = new TickListServerInterval[SHORT_SCHEDULE_TICK_THRESHOLD]; ++ { ++ for (int i = 0, len = this.shortScheduled.length; i < len; ++i) { ++ this.shortScheduled[i] = new TickListServerInterval<>(); ++ } ++ } ++ private int shortScheduledIndex; ++ ++ private long currentTick; ++ ++ private static final boolean WARN_ON_EXCESSIVE_DELAY = Boolean.getBoolean("paper.ticklist-warn-on-excessive-delay"); ++ private static final long EXCESSIVE_DELAY_THRESHOLD = Long.getLong("paper.ticklist-excessive-delay-threshold", 60 * 20).longValue(); // 1 min dfl ++ ++ // assume index < length ++ private static int getWrappedIndex(final int start, final int length, final int index) { ++ final int next = start + index; ++ return next < length ? next : next - length; ++ } ++ ++ private static int getNextIndex(final int curr, final int length) { ++ final int next = curr + 1; ++ return next < length ? next : 0; ++ } ++ ++ public PaperTickList(final ServerLevel world, final Predicate excludeFromScheduling, final Function getMinecraftKeyFrom, ++ final Consumer> tickFunction, final String timingsType) { ++ super(world, excludeFromScheduling, getMinecraftKeyFrom, tickFunction, timingsType); ++ this.world = world; ++ this.excludeFromScheduling = excludeFromScheduling; ++ this.getMinecraftKeyFrom = getMinecraftKeyFrom; ++ this.tickFunction = tickFunction; ++ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Cleanup"); // Paper ++ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Ticking"); // Paper ++ this.timingFinished = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Finish"); ++ this.currentTick = this.world.getGameTime(); ++ } ++ ++ private void queueEntryForTick(final TickNextTickData entry, final ServerChunkCache chunkProvider) { ++ if (entry.tickState == STATE_SCHEDULED) { ++ if (chunkProvider.isTickingReadyMainThread(entry.getPosition())) { ++ this.toTickThisTick.add(entry); ++ entry.tickState = STATE_PENDING_TICK; ++ } else { ++ // we dump them to a map to avoid constantly re-scheduling them ++ this.addToNotTickingReady(entry); ++ } ++ } ++ } ++ ++ private void addToNotTickingReady(final TickNextTickData entry) { ++ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (long keyInMap) -> { ++ return new ArrayList<>(); ++ }).add(entry); ++ } ++ ++ private void addToSchedule(final TickNextTickData entry) { ++ long delay = entry.getTargetTick() - (this.currentTick + 1); ++ if (delay < SHORT_SCHEDULE_TICK_THRESHOLD) { ++ if (delay < 0) { ++ // longScheduled orders by tick time, short scheduled does not ++ this.longScheduled.add(entry); ++ } else { ++ this.shortScheduled[getWrappedIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD, (int)delay)].addEntryLast(entry); ++ } ++ } else { ++ this.longScheduled.add(entry); ++ } ++ } ++ ++ private void removeEntry(final TickNextTickData entry) { ++ entry.tickState = STATE_CANCELLED_TICK; ++ // short/long scheduled will skip the entry ++ ++ final BlockPos pos = entry.getPosition(); ++ final long blockKey = MCUtil.getBlockKey(pos); ++ ++ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); ++ ++ if (currentEntries.size() == 1) { ++ // it should contain our entry ++ this.entriesByBlock.remove(blockKey); ++ } else { ++ // it's more likely that this entry is at the start of the list than the end ++ for (int i = 0, len = currentEntries.size(); i < len; ++i) { ++ final TickNextTickData currentEntry = currentEntries.get(i); ++ if (currentEntry == entry) { ++ currentEntries.remove(i); ++ break; ++ } ++ } ++ } ++ ++ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ ++ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); ++ ++ set.remove(entry); ++ ++ if (set.isEmpty()) { ++ this.entriesByChunk.remove(chunkKey); ++ } ++ ++ ArrayList> pendingTickingLoad = this.pendingChunkTickLoad.get(chunkKey); ++ ++ if (pendingTickingLoad != null) { ++ for (int i = 0, len = pendingTickingLoad.size(); i < len; ++i) { ++ if (pendingTickingLoad.get(i) == entry) { ++ pendingTickingLoad.remove(i); ++ break; ++ } ++ } ++ ++ if (pendingTickingLoad.isEmpty()) { ++ this.pendingChunkTickLoad.remove(chunkKey); ++ } ++ } ++ ++ long delay = entry.getTargetTick() - (this.currentTick + 1); ++ if (delay >= SHORT_SCHEDULE_TICK_THRESHOLD) { ++ this.longScheduled.remove(entry); ++ } ++ } ++ ++ public void onChunkSetTicking(final int chunkX, final int chunkZ) { ++ final ArrayList> pending = this.pendingChunkTickLoad.remove(MCUtil.getCoordinateKey(chunkX, chunkZ)); ++ if (pending == null) { ++ return; ++ } ++ ++ for (int i = 0, size = pending.size(); i < size; ++i) { ++ final TickNextTickData entry = pending.get(i); ++ // already in all the relevant reference maps, just need to add to longScheduled or shortScheduled ++ this.addToSchedule(entry); ++ } ++ } ++ ++ private void prepare() { ++ final long currentTick = this.currentTick; ++ ++ final ServerChunkCache chunkProvider = this.world.getChunkSource(); ++ ++ // here we setup what's going to tick ++ ++ // we don't remove items from shortScheduled (but do from longScheduled) because they're cleared at the end of ++ // this tick ++ if (this.longScheduled.isEmpty() || this.longScheduled.first().getTargetTick() > currentTick) { ++ // nothing in longScheduled to worry about ++ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; ++ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { ++ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { ++ this.queueEntryForTick(iterator.next(), chunkProvider); ++ } ++ } ++ } else { ++ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; ++ ++ // combine interval and longScheduled, keeping order ++ final Comparator> comparator = (Comparator)TickListServerInterval.ENTRY_COMPARATOR; ++ final Iterator> longScheduledIterator = this.longScheduled.iterator(); ++ TickNextTickData longCurrent = longScheduledIterator.next(); ++ ++ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { ++ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { ++ final TickNextTickData shortCurrent = iterator.next(); ++ if (longCurrent != null) { ++ // drain longCurrent until we can add shortCurrent ++ while (comparator.compare(longCurrent, shortCurrent) <= 0) { ++ this.queueEntryForTick(longCurrent, chunkProvider); ++ longScheduledIterator.remove(); ++ if (longScheduledIterator.hasNext()) { ++ longCurrent = longScheduledIterator.next(); ++ if (longCurrent.getTargetTick() > currentTick) { ++ longCurrent = null; ++ break; ++ } ++ } else { ++ longCurrent = null; ++ break; ++ } ++ } ++ } ++ this.queueEntryForTick(shortCurrent, chunkProvider); ++ } ++ } ++ ++ // add remaining from long scheduled ++ for (;;) { ++ if (longCurrent == null || longCurrent.getTargetTick() > currentTick) { ++ break; ++ } ++ longScheduledIterator.remove(); ++ this.queueEntryForTick(longCurrent, chunkProvider); ++ ++ if (longScheduledIterator.hasNext()) { ++ longCurrent = longScheduledIterator.next(); ++ } else { ++ break; ++ } ++ } ++ } ++ } ++ ++ private boolean warnedAboutDesync; ++ ++ @Override ++ public void nextTick() { ++ ++this.currentTick; ++ if (this.currentTick != this.world.getGameTime()) { ++ if (!this.warnedAboutDesync) { ++ this.warnedAboutDesync = true; ++ MinecraftServer.LOGGER.error("World tick desync detected! Expected " + this.currentTick + " ticks, but got " + this.world.getGameTime() + " ticks for world '" + this.world.getWorld().getName() + "'", new Throwable()); ++ MinecraftServer.LOGGER.error("Preventing redstone from breaking by refusing to accept new tick time"); ++ } ++ } ++ } ++ ++ @Override ++ public void tick() { ++ final ServerChunkCache chunkProvider = this.world.getChunkSource(); ++ ++ this.world.getProfiler().push("cleaning"); ++ this.timingCleanup.startTiming(); ++ ++ this.prepare(); ++ ++ // this must be done here in case something schedules in the tick code ++ this.shortScheduled[this.shortScheduledIndex].clear(); ++ this.shortScheduledIndex = getNextIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD); ++ ++ this.timingCleanup.stopTiming(); ++ this.world.getProfiler().popPush("ticking"); ++ this.timingTicking.startTiming(); ++ ++ for (final TickNextTickData toTick : this.toTickThisTick) { ++ if (toTick.tickState != STATE_PENDING_TICK) { ++ // onTickEnd gets called at end of tick ++ continue; ++ } ++ try { ++ if (chunkProvider.isTickingReadyMainThread(toTick.getPosition())) { ++ toTick.tickState = STATE_TICKING; ++ this.tickFunction.accept(toTick); ++ if (toTick.tickState == STATE_TICKING) { ++ toTick.tickState = STATE_TICKED; ++ } // else it's STATE_CANCELLED_TICK ++ } else { ++ // re-schedule eventually ++ toTick.tickState = STATE_SCHEDULED; ++ this.addToNotTickingReady(toTick); ++ } ++ } catch (final Throwable thr) { ++ // start copy from TickListServer // TODO check on update ++ CrashReport crashreport = CrashReport.forThrowable(thr, "Exception while ticking"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being ticked"); ++ ++ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, toTick.getPosition(), (BlockState) null); ++ throw new ReportedException(crashreport); ++ // end copy from TickListServer ++ } ++ } ++ ++ this.timingTicking.stopTiming(); ++ this.world.getProfiler().pop(); ++ this.timingFinished.startTiming(); ++ ++ // finished ticking, actual cleanup time ++ for (int i = 0, len = this.toTickThisTick.size(); i < len; ++i) { ++ final TickNextTickData entry = this.toTickThisTick.poll(); ++ if (entry.tickState != STATE_SCHEDULED) { ++ // some entries get re-scheduled due to their chunk not being loaded/at correct status, so do not ++ // call onTickEnd for them ++ this.onTickEnd(entry); ++ } ++ } ++ ++ this.timingFinished.stopTiming(); ++ } ++ ++ private void onTickEnd(final TickNextTickData entry) { ++ if (entry.tickState == STATE_CANCELLED_TICK) { ++ return; ++ } ++ entry.tickState = STATE_UNSCHEDULED; ++ ++ final BlockPos pos = entry.getPosition(); ++ final long blockKey = MCUtil.getBlockKey(pos); ++ ++ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); ++ ++ if (currentEntries.size() == 1) { ++ // it should contain our entry ++ this.entriesByBlock.remove(blockKey); ++ } else { ++ // it's more likely that this entry is at the start of the list than the end ++ for (int i = 0, len = currentEntries.size(); i < len; ++i) { ++ final TickNextTickData currentEntry = currentEntries.get(i); ++ if (currentEntry == entry) { ++ currentEntries.remove(i); ++ break; ++ } ++ } ++ } ++ ++ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ ++ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); ++ ++ set.remove(entry); ++ ++ if (set.isEmpty()) { ++ this.entriesByChunk.remove(chunkKey); ++ } ++ ++ // already removed from longScheduled or shortScheduled ++ } ++ ++ @Override ++ public boolean isPendingTickThisTick(final BlockPos blockposition, final T data) { ++ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); ++ ++ if (entries == null) { ++ return false; ++ } ++ ++ for (int i = 0, size = entries.size(); i < size; ++i) { ++ final TickNextTickData entry = entries.get(i); ++ if (entry.getData() == data && entry.tickState == STATE_PENDING_TICK) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ @Override ++ public boolean isScheduledForTick(final BlockPos blockposition, final T data) { ++ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); ++ ++ if (entries == null) { ++ return false; ++ } ++ ++ for (int i = 0, size = entries.size(); i < size; ++i) { ++ final TickNextTickData entry = entries.get(i); ++ if (entry.getData() == data && entry.tickState == STATE_SCHEDULED) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ @Override ++ public void schedule(BlockPos blockPosition, T t, int i, TickPriority tickListPriority) { ++ this.schedule(blockPosition, t, i + this.currentTick, tickListPriority); ++ } ++ ++ public void schedule(final TickNextTickData entry) { ++ this.schedule(entry.getPosition(), entry.getData(), entry.getTargetTick(), entry.getPriority()); ++ } ++ ++ public void schedule(final BlockPos pos, final T data, final long targetTick, final TickPriority priority) { ++ final TickNextTickData entry = new TickNextTickData<>(pos, data, targetTick, priority); ++ if (this.excludeFromScheduling.test(entry.getData())) { ++ return; ++ } ++ ++ if (WARN_ON_EXCESSIVE_DELAY) { ++ final long delay = entry.getTargetTick() - this.currentTick; ++ if (delay >= EXCESSIVE_DELAY_THRESHOLD) { ++ MinecraftServer.LOGGER.warn("Entry " + entry.toString() + " has been scheduled with an excessive delay of: " + delay, new Throwable()); ++ } ++ } ++ ++ final long blockKey = MCUtil.getBlockKey(pos); ++ ++ final ArrayList> currentEntries = this.entriesByBlock.computeIfAbsent(blockKey, (long keyInMap) -> new ArrayList<>(3)); ++ ++ if (currentEntries.isEmpty()) { ++ currentEntries.add(entry); ++ } else { ++ for (int i = 0, size = currentEntries.size(); i < size; ++i) { ++ final TickNextTickData currentEntry = currentEntries.get(i); ++ ++ // entries are only blocked from scheduling if currentEntry.equals(toSchedule) && currentEntry is scheduled to tick (NOT including pending) ++ if (currentEntry.getData() == entry.getData() && currentEntry.tickState == STATE_SCHEDULED) { ++ // can't add ++ return; ++ } ++ } ++ currentEntries.add(entry); ++ } ++ ++ entry.tickState = STATE_SCHEDULED; ++ ++ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (final long keyInMap) -> { ++ return new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); ++ }).add(entry); ++ ++ this.addToSchedule(entry); ++ } ++ ++ public void scheduleAll(final Iterator> iterator) { ++ while (iterator.hasNext()) { ++ this.schedule(iterator.next()); ++ } ++ } ++ ++ // this is not the standard interception calculation, but it's the one vanilla uses ++ // i.e the y value is ignored? the x, z calc isn't correct? ++ // however for the copy op they use the correct intersection, after using this one of course... ++ private static boolean isBlockInSortof(final BoundingBox boundingBox, final BlockPos pos) { ++ return pos.getX() >= boundingBox.getMinX() && pos.getX() < boundingBox.getMaxX() && pos.getZ() >= boundingBox.getMinZ() && pos.getZ() < boundingBox.getMaxZ(); ++ } ++ ++ @Override ++ public List> getEntriesInBoundingBox(final BoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { ++ if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) { ++ return Collections.emptyList(); // vanilla behaviour, check isBlockInSortof above ++ } ++ ++ final int lowerChunkX = structureboundingbox.getMinX() >> 4; ++ final int upperChunkX = (structureboundingbox.getMaxX() - 1) >> 4; // subtract 1 since maxX is exclusive ++ final int lowerChunkZ = structureboundingbox.getMinZ() >> 4; ++ final int upperChunkZ = (structureboundingbox.getMaxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive ++ ++ final int xChunksLength = (upperChunkX - lowerChunkX + 1); ++ final int zChunksLength = (upperChunkZ - lowerChunkZ + 1); ++ ++ final ObjectRBTreeSet>[] containingChunks = new ObjectRBTreeSet[xChunksLength * zChunksLength]; ++ ++ final int offset = (xChunksLength * -lowerChunkZ - lowerChunkX); ++ int totalEntries = 0; ++ for (int currChunkX = lowerChunkX; currChunkX <= upperChunkX; ++currChunkX) { ++ for (int currChunkZ = lowerChunkZ; currChunkZ <= upperChunkZ; ++currChunkZ) { ++ // todo optimize ++ //final int index = (currChunkX - lowerChunkX) + xChunksLength * (currChunkZ - lowerChunkZ); ++ final int index = offset + currChunkX + xChunksLength * currChunkZ; ++ final ObjectRBTreeSet> set = containingChunks[index] = this.entriesByChunk.get(MCUtil.getCoordinateKey(currChunkX, currChunkZ)); ++ if (set != null) { ++ totalEntries += set.size(); ++ } ++ } ++ } ++ ++ final List> ret = new ArrayList<>(totalEntries); ++ ++ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); ++ ++ MCUtil.mergeSortedSets((TickNextTickData entry) -> { ++ if (!isBlockInSortof(structureboundingbox, entry.getPosition())) { ++ return; ++ } ++ final int tickState = entry.tickState; ++ if ((tickState & matchOne) == 0) { ++ return; ++ } ++ ++ ret.add(entry); ++ return; ++ }, TickListServerInterval.ENTRY_COMPARATOR, containingChunks); ++ ++ if (removeReturned) { ++ for (TickNextTickData entry : ret) { ++ this.removeEntry(entry); ++ } ++ } ++ ++ return ret; ++ } ++ ++ @Override ++ public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { ++ // start copy from TickListServer // TODO check on update ++ List> list = this.getEntriesInBoundingBox(structureboundingbox, false, false); ++ Iterator> iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ TickNextTickData nextticklistentry = iterator.next(); ++ ++ if (structureboundingbox.hasPoint( nextticklistentry.getPosition())) { ++ BlockPos blockposition1 = nextticklistentry.getPosition().add(blockposition); ++ T t0 = nextticklistentry.getData(); ++ ++ this.schedule(new TickNextTickData<>(blockposition1, t0, nextticklistentry.getTargetTick(), nextticklistentry.getPriority())); ++ } ++ } ++ // end copy from TickListServer ++ } ++ ++ @Override ++ public List> getEntriesInChunk(ChunkPos chunkPos, boolean removeReturned, boolean excludeTicked) { ++ // Vanilla DOES get the entries 2 blocks out of the chunk too, but that doesn't matter since we ignore chunks ++ // not at ticking status, and ticking status requires neighbours loaded ++ // so with this method we will reduce scheduler churning ++ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); ++ ++ final ObjectRBTreeSet> entries = this.entriesByChunk.get(MCUtil.getCoordinateKey(chunkPos)); ++ ++ if (entries == null) { ++ return Collections.emptyList(); ++ } ++ ++ final List> ret = new ArrayList<>(entries.size()); ++ ++ for (TickNextTickData entry : entries) { ++ if ((entry.tickState & matchOne) == 0) { ++ continue; ++ } ++ ret.add(entry); ++ } ++ ++ if (removeReturned) { ++ for (TickNextTickData entry : ret) { ++ this.removeEntry(entry); ++ } ++ } ++ ++ return ret; ++ } ++ ++ @Override ++ public ListTag serialize(ChunkPos chunkcoordintpair) { ++ // start copy from TickListServer // TODO check on update ++ List> list = this.getEntriesInChunk(chunkcoordintpair, false, true); ++ ++ return ServerTickList.serialize(this.getMinecraftKeyFrom, list, this.currentTick); ++ // end copy from TickListServer ++ } ++ ++ @Override ++ public int getTotalScheduledEntries() { ++ // good thing this is only used in debug reports // TODO check on update ++ int ret = 0; ++ ++ for (TickNextTickData entry : this.longScheduled) { ++ if (entry.tickState == STATE_SCHEDULED) { ++ ++ret; ++ } ++ } ++ ++ for (Iterator>>> iterator = this.pendingChunkTickLoad.long2ObjectEntrySet().iterator(); iterator.hasNext();) { ++ ArrayList> list = iterator.next().getValue(); ++ ++ for (TickNextTickData entry : list) { ++ if (entry.tickState == STATE_SCHEDULED) { ++ ++ret; ++ } ++ } ++ } ++ ++ for (TickListServerInterval interval : this.shortScheduled) { ++ for (Iterable> set : interval.byPriority) { ++ for (TickNextTickData entry : set) { ++ if (entry.tickState == STATE_SCHEDULED) { ++ ++ret; ++ } ++ } ++ } ++ } ++ ++ return ret; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d40a7aff6c27883f3ae8ba878a94c97242619f2c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.server.ticklist; ++ ++import com.destroystokyo.paper.util.set.LinkedSortedSet; ++import java.util.Comparator; ++import net.minecraft.world.level.TickNextTickData; ++import net.minecraft.world.level.TickPriority; ++ ++// represents a set of entries to tick at a specified time ++public final class TickListServerInterval { ++ ++ public static final int TOTAL_PRIORITIES = TickPriority.values().length; ++ public static final Comparator> ENTRY_COMPARATOR_BY_ID = (entry1, entry2) -> { ++ return Long.compare(entry1.getId(), entry2.getId()); ++ }; ++ public static final Comparator> ENTRY_COMPARATOR = (Comparator)TickNextTickData.comparator(); ++ ++ // we do not record the interval, this class is meant to be used on a ring buffer ++ ++ // inlined enum map for TickListPriority ++ public final LinkedSortedSet>[] byPriority = new LinkedSortedSet[TOTAL_PRIORITIES]; ++ ++ { ++ for (int i = 0, len = this.byPriority.length; i < len; ++i) { ++ this.byPriority[i] = new LinkedSortedSet<>(ENTRY_COMPARATOR_BY_ID); ++ } ++ } ++ ++ public void addEntryLast(final TickNextTickData entry) { ++ this.byPriority[entry.getPriority().ordinal()].addLast(entry); ++ } ++ ++ public void addEntryFirst(final TickNextTickData entry) { ++ this.byPriority[entry.getPriority().ordinal()].addFirst(entry); ++ } ++ ++ public void clear() { ++ for (int i = 0, len = this.byPriority.length; i < len; ++i) { ++ this.byPriority[i].clear(); // O(1) clear ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..118988c39e58f28e8a2851792b9c014f341f06fc +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java +@@ -0,0 +1,142 @@ ++package com.destroystokyo.paper.util.set; ++ ++import java.util.Comparator; ++import java.util.Iterator; ++import java.util.NoSuchElementException; ++ ++public final class LinkedSortedSet implements Iterable { ++ ++ public final Comparator comparator; ++ ++ protected Link head; ++ protected Link tail; ++ ++ public LinkedSortedSet() { ++ this((Comparator)Comparator.naturalOrder()); ++ } ++ ++ public LinkedSortedSet(final Comparator comparator) { ++ this.comparator = comparator; ++ } ++ ++ public void clear() { ++ this.head = this.tail = null; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return new Iterator() { ++ ++ Link next = LinkedSortedSet.this.head; ++ ++ @Override ++ public boolean hasNext() { ++ return this.next != null; ++ } ++ ++ @Override ++ public E next() { ++ final Link next = this.next; ++ if (next == null) { ++ throw new NoSuchElementException(); ++ } ++ this.next = next.next; ++ return next.element; ++ } ++ }; ++ } ++ ++ public boolean addLast(final E element) { ++ final Comparator comparator = this.comparator; ++ ++ Link curr = this.tail; ++ if (curr != null) { ++ int compare; ++ ++ while ((compare = comparator.compare(element, curr.element)) < 0) { ++ Link prev = curr; ++ curr = curr.prev; ++ if (curr != null) { ++ continue; ++ } ++ this.head = prev.prev = new Link<>(element, null, prev); ++ return true; ++ } ++ ++ if (compare != 0) { ++ // insert after curr ++ final Link next = curr.next; ++ final Link insert = new Link<>(element, curr, next); ++ curr.next = insert; ++ ++ if (next == null) { ++ this.tail = insert; ++ } else { ++ next.prev = insert; ++ } ++ return true; ++ } ++ ++ return false; ++ } else { ++ this.head = this.tail = new Link<>(element); ++ return true; ++ } ++ } ++ ++ public boolean addFirst(final E element) { ++ final Comparator comparator = this.comparator; ++ ++ Link curr = this.head; ++ if (curr != null) { ++ int compare; ++ ++ while ((compare = comparator.compare(element, curr.element)) > 0) { ++ Link prev = curr; ++ curr = curr.next; ++ if (curr != null) { ++ continue; ++ } ++ this.tail = prev.next = new Link<>(element, prev, null); ++ return true; ++ } ++ ++ if (compare != 0) { ++ // insert before curr ++ final Link prev = curr.prev; ++ final Link insert = new Link<>(element, prev, curr); ++ curr.prev = insert; ++ ++ if (prev == null) { ++ this.head = insert; ++ } else { ++ prev.next = insert; ++ } ++ return true; ++ } ++ ++ return false; ++ } else { ++ this.head = this.tail = new Link<>(element); ++ return true; ++ } ++ } ++ ++ protected static final class Link { ++ public E element; ++ public Link prev; ++ public Link next; ++ ++ public Link() {} ++ ++ public Link(final E element) { ++ this.element = element; ++ } ++ ++ public Link(final E element, final Link prev, final Link next) { ++ this.element = element; ++ this.prev = prev; ++ this.next = next; ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 3db77d9eda98eacb099135643aff5e94751f4c7c..595abf528a7862478100770987906af1b13439fe 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -111,6 +111,7 @@ public class BlockPos extends Vec3i { + return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.getX() + x, this.getY() + y, this.getZ() + z); + } + ++ public final BlockPos add(Vec3i baseblockposition) { return this.offset(baseblockposition); } // Paper - OBFHELPER + public BlockPos offset(Vec3i pos) { + return this.offset(pos.getX(), pos.getY(), pos.getZ()); + } +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 77d3969200ac6f88f3af9add05def0b627ce6db3..d12d5459c847d3f0d655c85e31d81c27b7a2face 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -495,7 +495,9 @@ public class ChunkHolder { + ChunkHolder.this.isTickingReady = true; + + +- ++ // Paper start - rewrite ticklistserver ++ ChunkHolder.this.chunkMap.level.onChunkSetTicking(ChunkHolder.this.pos.x, ChunkHolder.this.pos.z); ++ // Paper end - rewrite ticklistserver + + } + }); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 3aeb8426b0461ec572c1499116be80f968bb4104..e2b1541042bceac965411e3176d08c61f217c07f 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -21,6 +21,7 @@ import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; + import net.minecraft.network.protocol.Packet; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.progress.ChunkProgressListener; + import net.minecraft.util.Mth; + import net.minecraft.util.profiling.ProfilerFiller; +@@ -217,6 +218,13 @@ public class ServerChunkCache extends ChunkSource { + } + // Paper end + ++ // Paper start - rewrite ticklistserver ++ public final boolean isTickingReadyMainThread(BlockPos pos) { ++ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(pos)); ++ return chunk != null && chunk.isTickingReady(); ++ } ++ // Paper end - rewrite ticklistserver ++ + public ServerChunkCache(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldloadlistener, Supplier supplier) { + this.level = worldserver; + this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(worldserver); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 5d85895456b5d65954889cadf932027ea23b400b..9da0d98bc2ed7876a00a734690ed42f01b9a9a9b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -292,6 +292,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + // Paper end + ++ // Paper start - rewrite ticklistserver ++ void onChunkSetTicking(int chunkX, int chunkZ) { ++ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { ++ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.blockTicks).onChunkSetTicking(chunkX, chunkZ); ++ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.liquidTicks).onChunkSetTicking(chunkX, chunkZ); ++ } ++ } ++ // Paper end - rewrite ticklistserver ++ + // Add env and gen to constructor, WorldData -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor +@@ -299,12 +308,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + convertable = convertable_conversionsession; + uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile()); + // CraftBukkit end +- this.blockTicks = new ServerTickList<>(this, (block) -> { +- return block == null || block.defaultBlockState().isAir(); +- }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings +- this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { +- return fluidtype == null || fluidtype == Fluids.EMPTY; +- }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings ++ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { ++ this.blockTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> { ++ return block == null || block.defaultBlockState().isAir(); ++ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings ++ this.liquidTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (fluidtype) -> { ++ return fluidtype == null || fluidtype == Fluids.EMPTY; ++ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings ++ } else { ++ this.blockTicks = new ServerTickList<>(this, (block) -> { ++ return block == null || block.defaultBlockState().isAir(); ++ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings ++ this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { ++ return fluidtype == null || fluidtype == Fluids.EMPTY; ++ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings ++ } + this.navigations = Sets.newHashSet(); + this.blockEvents = new ObjectLinkedOpenHashSet(); + this.tickTime = flag1; +@@ -639,7 +657,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (this.tickTime) { + long i = this.levelData.getGameTime() + 1L; + +- this.worldDataServer.setGameTime(i); ++ this.worldDataServer.setGameTime(i); // Paper - diff on change, we want the below to be ran right after this ++ this.blockTicks.nextTick(); // Paper ++ this.liquidTicks.nextTick(); // Paper + this.worldDataServer.getScheduledEvents().tick(this.server, i); + if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + this.setDayTime(this.levelData.getDayTime() + 1L); +diff --git a/src/main/java/net/minecraft/world/level/ChunkTickList.java b/src/main/java/net/minecraft/world/level/ChunkTickList.java +index 16757eb9c03c0dab51a7a1b569daff81cf9654f3..3008e0c42efe908e45dba1a1437928d4d4378f24 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkTickList.java ++++ b/src/main/java/net/minecraft/world/level/ChunkTickList.java +@@ -9,6 +9,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MinecraftServer; + + public class ChunkTickList implements TickList { + +@@ -61,6 +62,8 @@ public class ChunkTickList implements TickList { + return nbttaglist; + } + ++ private static final int MAX_TICK_DELAY = Integer.getInteger("paper.ticklist-max-tick-delay", -1).intValue(); // Paper - clean up broken entries ++ + public static ChunkTickList create(ListTag ticks, Function function, Function function1) { + List> list = Lists.newArrayList(); + +@@ -71,7 +74,14 @@ public class ChunkTickList implements TickList { + if (t0 != null) { + BlockPos blockposition = new BlockPos(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); + +- list.add(new ChunkTickList.ScheduledTick<>(t0, blockposition, nbttagcompound.getInt("t"), TickPriority.byValue(nbttagcompound.getInt("p")))); ++ // Paper start - clean up broken entries ++ int delay = nbttagcompound.getInt("t"); ++ if (MAX_TICK_DELAY > 0 && delay > MAX_TICK_DELAY) { ++ MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockposition + ", tick delay " + delay); ++ continue; ++ } ++ list.add(new ChunkTickList.ScheduledTick<>(t0, blockposition, delay, TickPriority.byValue(nbttagcompound.getInt("p")))); ++ // Paper end - clean up broken entries + } + } + +diff --git a/src/main/java/net/minecraft/world/level/ServerTickList.java b/src/main/java/net/minecraft/world/level/ServerTickList.java +index 10ac1ba0a3d192486f22c2127d5bc30353f0edb6..65b3a16f40a295c2916be2a9fd019b452fb65e4f 100644 +--- a/src/main/java/net/minecraft/world/level/ServerTickList.java ++++ b/src/main/java/net/minecraft/world/level/ServerTickList.java +@@ -50,7 +50,16 @@ public class ServerTickList implements TickList { + private final co.aikar.timings.Timing timingTicking; // Paper + // Paper end + ++ // Paper start ++ public void nextTick() {} ++ // Paper end ++ ++ public void tick() { ++ // Paper start - allow overriding ++ this.tick(); ++ } + public void tick() { ++ // Paper end + int i = this.tickNextTickList.size(); + + if (false) { // CraftBukkit +@@ -118,28 +127,43 @@ public class ServerTickList implements TickList { + + @Override + public boolean willTickThisTick(BlockPos pos, T object) { +- return this.currentlyTicking.contains(new TickNextTickData<>(pos, object)); ++ // Paper start - allow overriding ++ return this.isPendingTickThisTick(pos, object); ++ } ++ public boolean isPendingTickThisTick(BlockPos blockposition, T t0) { ++ // Paper end ++ return this.currentlyTicking.contains(new TickNextTickData<>(blockposition, t0)); + } + + public List> fetchTicksInChunk(ChunkPos chunkcoordintpair, boolean updateState, boolean getStaleTicks) { ++ // Paper start - allow overriding ++ return this.getEntriesInChunk(chunkcoordintpair, updateState, getStaleTicks); ++ } ++ public List> getEntriesInChunk(ChunkPos chunkcoordintpair, boolean flag, boolean flag1) { ++ // Paper end + int i = (chunkcoordintpair.x << 4) - 2; + int j = i + 16 + 2; + int k = (chunkcoordintpair.z << 4) - 2; + int l = k + 16 + 2; + +- return this.fetchTicksInArea(new BoundingBox(i, 0, k, j, 256, l), updateState, getStaleTicks); ++ return this.fetchTicksInArea(new BoundingBox(i, 0, k, j, 256, l), flag, flag1); + } + + public List> fetchTicksInArea(BoundingBox bounds, boolean updateState, boolean getStaleTicks) { +- List> list = this.fetchTicksInArea((List) null, this.tickNextTickList, bounds, updateState); ++ // Paper start - allow overriding ++ return this.getEntriesInBoundingBox(bounds, updateState, getStaleTicks); ++ } ++ public List> getEntriesInBoundingBox(BoundingBox structureboundingbox, boolean flag, boolean flag1) { ++ // Paper end ++ List> list = this.fetchTicksInArea((List) null, this.tickNextTickList, structureboundingbox, flag); + +- if (updateState && list != null) { ++ if (flag && list != null) { + this.tickNextTickSet.removeAll(list); + } + +- list = this.fetchTicksInArea(list, this.currentlyTicking, bounds, updateState); +- if (!getStaleTicks) { +- list = this.fetchTicksInArea(list, this.alreadyTicked, bounds, updateState); ++ list = this.fetchTicksInArea(list, this.currentlyTicking, structureboundingbox, flag); ++ if (!flag1) { ++ list = this.fetchTicksInArea(list, this.alreadyTicked, structureboundingbox, flag); + } + + return list == null ? Collections.emptyList() : list; +@@ -170,14 +194,19 @@ public class ServerTickList implements TickList { + } + + public void copy(BoundingBox box, BlockPos offset) { +- List> list = this.fetchTicksInArea(box, false, false); ++ // Paper start - allow overriding ++ this.copy(box, offset); ++ } ++ public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { ++ // Paper end ++ List> list = this.fetchTicksInArea(structureboundingbox, false, false); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { + TickNextTickData nextticklistentry = (TickNextTickData) iterator.next(); + +- if (box.isInside((Vec3i) nextticklistentry.pos)) { +- BlockPos blockposition1 = nextticklistentry.pos.offset((Vec3i) offset); ++ if (structureboundingbox.isInside((Vec3i) nextticklistentry.pos)) { ++ BlockPos blockposition1 = nextticklistentry.pos.offset((Vec3i) blockposition); + T t0 = nextticklistentry.getType(); + + this.addTickData(new TickNextTickData<>(blockposition1, t0, nextticklistentry.triggerTick, nextticklistentry.priority)); +@@ -187,11 +216,17 @@ public class ServerTickList implements TickList { + } + + public ListTag save(ChunkPos chunkcoordintpair) { ++ // Paper start - allow overriding ++ return this.serialize(chunkcoordintpair); ++ } ++ public ListTag serialize(ChunkPos chunkcoordintpair) { ++ // Paper end + List> list = this.fetchTicksInChunk(chunkcoordintpair, false, true); + + return saveTickList(this.toId, list, this.level.getGameTime()); + } + ++ public static ListTag serialize(Function function, Iterable> iterable, long i) { return ServerTickList.saveTickList(function, iterable, i); } // Paper - OBFHELPER + private static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { + ListTag nbttaglist = new ListTag(); + Iterator iterator = scheduledTicks.iterator(); +@@ -214,13 +249,23 @@ public class ServerTickList implements TickList { + + @Override + public boolean hasScheduledTick(BlockPos pos, T object) { +- return this.tickNextTickSet.contains(new TickNextTickData<>(pos, object)); ++ // Paper start - allow overriding ++ return this.isScheduledForTick(pos, object); ++ } ++ public boolean isScheduledForTick(BlockPos blockposition, T t0) { ++ // Paper end ++ return this.tickNextTickSet.contains(new TickNextTickData<>(blockposition, t0)); + } + + @Override + public void scheduleTick(BlockPos pos, T object, int delay, TickPriority priority) { +- if (!this.ignore.test(object)) { +- this.addTickData(new TickNextTickData<>(pos, object, (long) delay + this.level.getGameTime(), priority)); ++ // Paper start - allow overriding ++ this.schedule(pos, object, delay, priority); ++ } ++ public void schedule(BlockPos blockposition, T t0, int i, TickPriority ticklistpriority) { ++ // Paper end ++ if (!this.ignore.test(t0)) { ++ this.addTickData(new TickNextTickData<>(blockposition, t0, (long) i + this.level.getGameTime(), ticklistpriority)); + } + + } +@@ -234,6 +279,11 @@ public class ServerTickList implements TickList { + } + + public int size() { ++ // Paper start - allow overriding ++ return this.getTotalScheduledEntries(); ++ } ++ public int getTotalScheduledEntries() { ++ // Paper end + return this.tickNextTickSet.size(); + } + } +diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java +index 90833389022d7412bdda8868a356b84f62a00e03..61cdaf45368dcc40f3311e8b7f8637a6c93a2d76 100644 +--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java ++++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java +@@ -6,11 +6,13 @@ import net.minecraft.core.BlockPos; + public class TickNextTickData { + + private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading +- private final T type; +- public final BlockPos pos; +- public final long triggerTick; +- public final TickPriority priority; +- private final long c; ++ private final T type; public final T getData() { return this.type; } // Paper - OBFHELPER ++ public final BlockPos pos; public final BlockPos getPosition() { return this.pos; } // Paper - OBFHELPER ++ public final long triggerTick; public final long getTargetTick() { return this.triggerTick; } // Paper - OBFHELPER ++ public final TickPriority priority; public final TickPriority getPriority() { return this.priority; } // Paper - OBFHELPER ++ private final long c; public final long getId() { return this.c; } // Paper - OBFHELPER ++ private final int hash; // Paper ++ public int tickState; // Paper + + public TickNextTickData(BlockPos pos, T t) { + this(pos, t, 0L, TickPriority.NORMAL); +@@ -22,6 +24,7 @@ public class TickNextTickData { + this.type = t; + this.triggerTick = time; + this.priority = priority; ++ this.hash = this.computeHash(); // Paper + } + + public boolean equals(Object object) { +@@ -34,19 +37,31 @@ public class TickNextTickData { + } + } + ++ // Paper start - optimize hashcode ++ @Override + public int hashCode() { ++ return this.hash; ++ } ++ public final int computeHash() { ++ // Paper end - optimize hashcode + return this.pos.hashCode(); + } + +- public static Comparator createTimeComparator() { // Paper - decompile fix +- return Comparator.comparingLong((nextticklistentry) -> { +- return ((TickNextTickData) nextticklistentry).triggerTick; // Paper - decompile fix +- }).thenComparing((nextticklistentry) -> { +- return ((TickNextTickData) nextticklistentry).priority; // Paper - decompile fix +- }).thenComparingLong((nextticklistentry) -> { +- return ((TickNextTickData) nextticklistentry).c; // Paper - decompile fix +- }); ++ // Paper start - let's not use more functional code for no reason. ++ public static Comparator comparator() { return TickNextTickData.createTimeComparator(); } // Paper - OBFHELPER ++ public static Comparator createTimeComparator() { ++ return (Comparator)(Comparator)(TickNextTickData nextticklistentry, TickNextTickData nextticklistentry1) -> { ++ int i = Long.compare(nextticklistentry.getTargetTick(), nextticklistentry1.getTargetTick()); ++ ++ if (i != 0) { ++ return i; ++ } else { ++ i = nextticklistentry.getPriority().compareTo(nextticklistentry1.getPriority()); ++ return i != 0 ? i : Long.compare(nextticklistentry.getId(), nextticklistentry1.getId()); ++ } ++ }; + } ++ // Paper end - let's not use more functional code for no reason. + + public String toString() { + return this.type + ": " + this.pos + ", " + this.triggerTick + ", " + this.priority + ", " + this.c; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java b/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java +index 76bea58d35d352ee6f3d4bd0d10af3b6d615ae2c..4288fa253668196e6c32a876f18ec496fb3abad6 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java +@@ -8,12 +8,12 @@ import net.minecraft.nbt.IntArrayTag; + + public class BoundingBox { + +- public int x0; +- public int y0; +- public int z0; +- public int x1; +- public int y1; +- public int z1; ++ public int x0; public final int getMinX() { return this.x0; } // Paper - OBFHELPER ++ public int y0; public final int getMinY() { return this.y0; } // Paper - OBFHELPER ++ public int z0; public final int getMinZ() { return this.z0; } // Paper - OBFHELPER ++ public int x1; public final int getMaxX() { return this.x1; } // Paper - OBFHELPER ++ public int y1; public final int getMaxY() { return this.y1; } // Paper - OBFHELPER ++ public int z1; public final int getMaxZ() { return this.z1; } // Paper - OBFHELPER + + public BoundingBox() {} + +@@ -92,6 +92,7 @@ public class BoundingBox { + this.y1 = 512; + } + ++ public final boolean intersects(BoundingBox boundingBox) { return this.intersects(boundingBox); } // Paper - OBFHELPER + public boolean intersects(BoundingBox other) { + return this.x1 >= other.x0 && this.x0 <= other.x1 && this.z1 >= other.z0 && this.z0 <= other.z1 && this.y1 >= other.y0 && this.y0 <= other.y1; + } +@@ -126,6 +127,7 @@ public class BoundingBox { + this.move(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); + } + ++ public final boolean hasPoint(Vec3i baseblockposition) { return this.isInside(baseblockposition); } // Paper - OBFHELPER + public boolean isInside(Vec3i vec) { + return vec.getX() >= this.x0 && vec.getX() <= this.x1 && vec.getZ() >= this.z0 && vec.getZ() <= this.z1 && vec.getY() >= this.y0 && vec.getY() <= this.y1; + } diff --git a/Remapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch b/Remapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch new file mode 100644 index 0000000000..6e0269c7f2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch @@ -0,0 +1,155 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Sat, 1 Feb 2020 16:50:39 +0100 +Subject: [PATCH] Pillager patrol spawn settings and per player options + +This adds config options for defining the spawn chance, spawn delay and +spawn start day as well as toggles for handling the spawn delay and +start day per player. (Based on the time played statistic) +When not per player it will use the Vanilla mechanic of one delay per +world and the world age for the start day. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 525d702d78a609af987ebd2c32169b873e5c05ed..6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -582,10 +582,21 @@ public class PaperWorldConfig { + } + + public boolean disablePillagerPatrols = false; ++ public double patrolSpawnChance = 0.2; ++ public boolean patrolPerPlayerDelay = false; ++ public int patrolDelay = 12000; ++ public boolean patrolPerPlayerStart = false; ++ public int patrolStartDay = 5; + private void pillagerSettings() { + disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); ++ patrolSpawnChance = getDouble("game-mechanics.pillager-patrols.spawn-chance", patrolSpawnChance); ++ patrolPerPlayerDelay = getBoolean("game-mechanics.pillager-patrols.spawn-delay.per-player", patrolPerPlayerDelay); ++ patrolDelay = getInt("game-mechanics.pillager-patrols.spawn-delay.ticks", patrolDelay); ++ patrolPerPlayerStart = getBoolean("game-mechanics.pillager-patrols.start.per-player", patrolPerPlayerStart); ++ patrolStartDay = getInt("game-mechanics.pillager-patrols.start.day", patrolStartDay); + } + ++ + public boolean entitiesTargetWithFollowRange = false; + private void entitiesTargetWithFollowRange() { + entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 7f4e81ee3339e90b8525541dccf6dea187853cf7..a469016c43251f16913a365c4131b2448eaa4c48 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -213,6 +213,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public boolean wonGame; + private int containerUpdateDelay; // Paper + public long loginTime; // Paper ++ public int patrolSpawnDelay; // Paper - per player patrol spawns + // Paper start - cancellable death event + public boolean queueHealthUpdatePacket = false; + public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; +diff --git a/src/main/java/net/minecraft/stats/StatType.java b/src/main/java/net/minecraft/stats/StatType.java +index ba48795a7b7cbf4622e64273ab488e26d7a862e2..b85987910cf80b1d1a04a7b772e19200f4ce4372 100644 +--- a/src/main/java/net/minecraft/stats/StatType.java ++++ b/src/main/java/net/minecraft/stats/StatType.java +@@ -28,6 +28,7 @@ public class StatType implements Iterable> { + return this.map.values().iterator(); + } + ++ public final Stat get(T t) { return this.get(t); }; // Paper - OBFHELPER + public Stat get(T key) { + return this.get(key, StatFormatter.DEFAULT); + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +index 48efe133d294bb1b17e8ac8b44eea8a29f15845f..dcbe74bdb1b6e07f7b8845182576ef544493d377 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +@@ -4,11 +4,12 @@ import java.util.Random; + import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.stats.Stats; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.monster.PatrollingMonster; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.CustomSpawner; + import net.minecraft.world.level.GameRules; +@@ -20,13 +21,13 @@ import net.minecraft.world.level.block.state.BlockState; + + public class PatrolSpawner implements CustomSpawner { + +- private int nextTick; ++ private int nextTick;private int getSpawnDelay() { return nextTick; } private void setSpawnDelay(int spawnDelay) { this.nextTick = spawnDelay; } // Paper - OBFHELPER + + public PatrolSpawner() {} + + @Override + public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { +- if (world.paperConfig.disablePillagerPatrols) return 0; // Paper ++ if (world.paperConfig.disablePillagerPatrols || world.paperConfig.patrolSpawnChance == 0) return 0; // Paper + if (!spawnMonsters) { + return 0; + } else if (!world.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) { +@@ -34,23 +35,51 @@ public class PatrolSpawner implements CustomSpawner { + } else { + Random random = world.random; + +- --this.nextTick; +- if (this.nextTick > 0) { ++ // Paper start - Patrol settings ++ // Random player selection moved up for per player spawning and configuration ++ int j = world.players().size(); ++ if (j < 1) { + return 0; ++ } ++ ++ ServerPlayer entityhuman = world.players().get(random.nextInt(j)); ++ if (entityhuman.isSpectator()) { ++ return 0; ++ } ++ ++ int patrolSpawnDelay; ++ if (world.paperConfig.patrolPerPlayerDelay) { ++ --entityhuman.patrolSpawnDelay; ++ patrolSpawnDelay = entityhuman.patrolSpawnDelay; + } else { +- this.nextTick += 12000 + random.nextInt(1200); +- long i = world.getDayTime() / 24000L; ++ setSpawnDelay(getSpawnDelay() - 1); ++ patrolSpawnDelay = getSpawnDelay(); ++ } ++ ++ if (patrolSpawnDelay > 0) { ++ return 0; ++ } else { ++ long days; ++ if (world.paperConfig.patrolPerPlayerStart) { ++ days = entityhuman.getStats().getValue(Stats.CUSTOM.get(Stats.PLAY_ONE_MINUTE)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang ++ } else { ++ days = world.getDayTime() / 24000L; ++ } ++ if (world.paperConfig.patrolPerPlayerDelay) { ++ entityhuman.patrolSpawnDelay += world.paperConfig.patrolDelay + random.nextInt(1200); ++ } else { ++ setSpawnDelay(getSpawnDelay() + world.paperConfig.patrolDelay + random.nextInt(1200)); ++ } + +- if (i >= 5L && world.isDay()) { +- if (random.nextInt(5) != 0) { ++ if (days >= world.paperConfig.patrolStartDay && world.isDay()) { ++ if (random.nextDouble() >= world.paperConfig.patrolSpawnChance) { ++ // Paper end + return 0; + } else { +- int j = world.players().size(); + + if (j < 1) { + return 0; + } else { +- Player entityhuman = (Player) world.players().get(random.nextInt(j)); + + if (entityhuman.isSpectator()) { + return 0; diff --git a/Remapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch b/Remapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch new file mode 100644 index 0000000000..0c956bdb77 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 29 Mar 2020 18:26:14 -0400 +Subject: [PATCH] Ensure Entity is never double registered + +If something calls register twice, and the world is ticking, it could be +enqueued to add twice. + +Vs behavior of non ticking of just overwriting state. + +We will now simply log a warning when this happens instead of crashing the server. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 9da0d98bc2ed7876a00a734690ed42f01b9a9a9b..9898d5c8fab63c576831bd416ccf1854ed077b0d 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -643,6 +643,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + Entity entity2; + + while ((entity2 = (Entity) this.toAddAfterTick.poll()) != null) { ++ if (!entity2.isQueuedForRegister) continue; // Paper - ignore cancelled registers + this.add(entity2); + } + +@@ -1400,6 +1401,19 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + public void onEntityRemoved(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot ++ // Paper start - fix entity registration issues ++ if (entity instanceof EnderDragonPart) { ++ // Usually this is a no-op for complex parts, and ID's should be removed, but go ahead and remove it anyways ++ // Dragon parts are handled special in register. they don't receive a valid = true or register by UUID etc. ++ this.entitiesById.remove(entity.getId(), entity); ++ return; ++ } ++ if (!entity.valid) { ++ // Someone called remove before we ever got added, cancel the add. ++ entity.isQueuedForRegister = false; ++ return; ++ } ++ // Paper end + // Spigot start + if ( entity instanceof Player ) + { +@@ -1466,9 +1480,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + private void add(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot ++ // Paper start - don't double enqueue entity registration ++ //noinspection ObjectEquality ++ if (this.entitiesById.get(entity.getId()) == entity) { ++ LOGGER.error(entity + " was already registered!"); ++ new Throwable().printStackTrace(); ++ return; ++ } ++ // Paper end + if (this.tickingEntities) { +- this.toAddAfterTick.add(entity); ++ if (!entity.isQueuedForRegister) { // Paper ++ this.toAddAfterTick.add(entity); ++ entity.isQueuedForRegister = true; // Paper ++ } + } else { ++ entity.isQueuedForRegister = false; // Paper + this.entitiesById.put(entity.getId(), entity); + if (entity instanceof EnderDragon) { + EnderDragonPart[] aentitycomplexpart = ((EnderDragon) entity).getSubEntities(); +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 43f77d01fceab107d3502d282205aa579d64cc4b..7e198b94f349d4c4d61502f5ad8c60686800d88f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -147,6 +147,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + // Paper start ++ public boolean isQueuedForRegister = false; + public static Random SHARED_RANDOM = new Random() { + private boolean locked = false; + @Override diff --git a/Remapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch b/Remapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch new file mode 100644 index 0000000000..110790b17f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 31 Mar 2020 03:01:45 -0400 +Subject: [PATCH] Fix unregistering entities from unloading chunks + +CraftBukkit caused a regression here by making unloading chunks not +have a ticket added and returning unloaded future. + +This caused entities who were killed in same tick their chunk is unloading +to not be able to be removed from the chunk. + +This then results in dead entities lingering in the Chunk. + +Combine that with a buggy detail of the previous implementation of +the Dupe UUID patch, then this was the likely source of the "Ghost entities" + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 9898d5c8fab63c576831bd416ccf1854ed077b0d..c5dc41a3cf499038bd33451a189913cd3978b230 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1559,9 +1559,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + private void removeFromChunk(Entity entity) { +- ChunkAccess ichunkaccess = chunkSource.getChunkUnchecked(entity.xChunk, entity.zChunk); // CraftBukkit - SPIGOT-5228: getChunkAt won't find the entity's chunk if it has already been unloaded (i.e. if it switched to state INACCESSIBLE). ++ LevelChunk ichunkaccess = entity.getCurrentChunk(); // Paper - getChunkAt(x,z,full,false) is broken by CraftBukkit as it won't return an unloading chunk. Use our current chunk reference as this points to what chunk they need to be removed from anyways + +- if (ichunkaccess instanceof LevelChunk) { ++ if (ichunkaccess != null) { // Paper + ((LevelChunk) ichunkaccess).removeEntity(entity); + } + diff --git a/Remapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/Remapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch new file mode 100644 index 0000000000..a83d559354 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 31 Mar 2020 03:50:42 -0400 +Subject: [PATCH] Remote Connections shouldn't hold up shutdown + +Bugs in the connection logic appears to leave stale connections even, preventing shutdown + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 4862a9519d4ba5f05b634a0335837bea9812edee..f8ddc0aa98874c7879a51e76d1a629cbdaf58812 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -397,11 +397,11 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } + + if (this.rconThread != null) { +- this.rconThread.stop(); ++ //this.remoteControlListener.b(); // Paper - don't wait for remote connections + } + + if (this.queryThreadGs4 != null) { +- this.queryThreadGs4.stop(); ++ //this.remoteStatusListener.b(); // Paper - don't wait for remote connections + } + + System.exit(0); // CraftBukkit diff --git a/Remapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/Remapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch new file mode 100644 index 0000000000..044507e1b4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Tue, 17 Mar 2020 14:18:50 -0500 +Subject: [PATCH] Do not allow bees to load chunks for beehives + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java +index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e99b45d887 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -358,6 +358,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + if (this.hivePos == null) { + return false; + } else { ++ if (!this.level.isLoadedAndInBounds(hivePos)) return false; // Paper + BlockEntity tileentity = this.level.getBlockEntity(this.hivePos); + + return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby(); +@@ -390,6 +391,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + } + + private boolean doesHiveHaveSpace(BlockPos pos) { ++ if (!this.level.isLoadedAndInBounds(pos)) return false; // Paper + BlockEntity tileentity = this.level.getBlockEntity(pos); + + return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false; +@@ -632,6 +634,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + @Override + public boolean canBeeUse() { + if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerThan((Position) Bee.this.position(), 2.0D)) { ++ if (!Bee.this.level.isLoadedAndInBounds(Bee.this.hivePos)) return false; // Paper + BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos); + + if (tileentity instanceof BeehiveBlockEntity) { +@@ -655,6 +658,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + + @Override + public void start() { ++ if (!Bee.this.level.isLoadedAndInBounds(Bee.this.hivePos)) return; // Paper + BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos); + + if (tileentity instanceof BeehiveBlockEntity) { diff --git a/Remapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/Remapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch new file mode 100644 index 0000000000..720e9dcff9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 01:42:39 -0400 +Subject: [PATCH] Prevent Double PlayerChunkMap adds crashing server + +Suspected case would be around the technique used in .stopRiding +Stack will identify any causer of this and warn instead of crashing. + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 6da406c8403797a1cd9276ac06577c3c080a8a22..e6eeca5834a164d87f5b0e564fe6237902edaa6a 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1501,6 +1501,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + protected void addEntity(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot ++ // Paper start - ignore and warn about illegal addEntity calls instead of crashing server ++ if (!entity.valid || entity.level != this.level || this.entityMap.containsKey(entity.getId())) { ++ new Throwable("[ERROR] Illegal PlayerChunkMap::addEntity for world " + this.level.getWorld().getName() ++ + ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : "")) ++ .printStackTrace(); ++ return; ++ } ++ // Paper end + if (!(entity instanceof EnderDragonPart)) { + EntityType entitytypes = entity.getType(); + int i = entitytypes.clientTrackingRange() * 16; +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index c5dc41a3cf499038bd33451a189913cd3978b230..5127bce423a83711cea94e387b3ae7866215ded5 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1525,7 +1525,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + } + +- this.getChunkSource().addEntity(entity); ++ // this.getChunkProvider().addEntity(entity); // Paper - moved down below valid=true + // CraftBukkit start - SPIGOT-5278 + if (entity instanceof Drowned) { + this.navigations.add(((Drowned) entity).waterNavigation); +@@ -1536,6 +1536,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.navigations.add(((Mob) entity).getNavigation()); + } + entity.valid = true; // CraftBukkit ++ this.getChunkSource().addEntity(entity); // Paper - from above to be below valid=true + // Paper start - Set origin location when the entity is being added to the world + if (entity.origin == null) { + entity.origin = entity.getBukkitEntity().getLocation(); diff --git a/Remapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch b/Remapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch new file mode 100644 index 0000000000..58edb5460d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch @@ -0,0 +1,185 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 02:37:57 -0400 +Subject: [PATCH] Optimize Collision to not load chunks + +The collision code takes an AABB and generates a cuboid of checks rather +than a cylinder, so at high velocity this can generate a lot of chunk checks. + +Treat an unloaded chunk as a collision for entities, and also for players if +the "prevent moving into unloaded chunks" setting is enabled. + +If that serting is not enabled, collisions will be ignored for players, since +movement will load only the chunk the player enters anyways and avoids loading +massive amounts of surrounding chunks due to large AABB lookups. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index dfdde9722bc0d83916779014b7718eef2c01b3db..86c5549196a4e9011c5240e7918b466c299be4a3 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -59,12 +59,23 @@ import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.PlayerAdvancements; + import net.minecraft.server.ServerScoreboard; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.ServerPlayerGameMode; ++import net.minecraft.server.level.TicketType; ++import net.minecraft.server.network.ServerGamePacketListenerImpl; ++import net.minecraft.server.network.ServerLoginPacketListenerImpl; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.stats.ServerStatsCounter; ++import net.minecraft.stats.Stats; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.Tag; + import net.minecraft.util.Mth; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GameType; + import net.minecraft.world.level.Level; +@@ -90,15 +101,6 @@ import io.papermc.paper.adventure.PaperAdventure; // Paper + import com.google.common.base.Predicate; + import com.google.common.collect.Iterables; + import net.minecraft.server.dedicated.DedicatedServer; +-import net.minecraft.server.level.ServerLevel; +-import net.minecraft.server.level.ServerPlayer; +-import net.minecraft.server.level.ServerPlayerGameMode; +-import net.minecraft.server.network.ServerGamePacketListenerImpl; +-import net.minecraft.server.network.ServerLoginPacketListenerImpl; +-import net.minecraft.sounds.SoundEvents; +-import net.minecraft.sounds.SoundSource; +-import net.minecraft.stats.ServerStatsCounter; +-import net.minecraft.stats.Stats; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; + +@@ -805,6 +807,7 @@ public abstract class PlayerList { + entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + // CraftBukkit end + ++ worldserver1.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, new ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper + while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < 256.0D) { + entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 7e198b94f349d4c4d61502f5ad8c60686800d88f..b8dcc91a191f25ca578e0858abf6c1b874fee15d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -168,6 +168,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + private CraftEntity bukkitEntity; + + ChunkMap.TrackedEntity tracker; // Paper ++ public boolean collisionLoadChunks = false; // Paper + public Throwable addedToWorldStack; // Paper - entity debug + public CraftEntity getBukkitEntity() { + if (bukkitEntity == null) { +diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java +index d9e69195ee0af4dfb90bf0e8f4cc65e63f7ecf5b..1b52f2a0ce9cb847d7d57b38f4b8b6bed8de2cd9 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionGetter.java ++++ b/src/main/java/net/minecraft/world/level/CollisionGetter.java +@@ -54,7 +54,9 @@ public interface CollisionGetter extends BlockGetter { + } + + default boolean noCollision(@Nullable Entity entity, AABB axisalignedbb, Predicate predicate) { ++ try { if (entity != null) entity.collisionLoadChunks = true; // Paper + return this.getCollisions(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty); ++ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper + } + + Stream getEntityCollisions(@Nullable Entity entity, AABB axisalignedbb, Predicate predicate); +diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +index 7208c61da48ce5e735810b6268490584e1d5c260..feca9ff34936686c0665ae0dbc926869087df3a7 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java ++++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +@@ -7,6 +7,9 @@ import java.util.function.Consumer; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Cursor3D; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.WorldGenRegion; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.block.Blocks; +@@ -21,13 +24,13 @@ import net.minecraft.world.phys.shapes.VoxelShape; + public class CollisionSpliterator extends AbstractSpliterator { + + @Nullable +- private final Entity source; ++ private final Entity source; final Entity getEntity() { return this.source; } // Paper - OBFHELPER + private final AABB box; + private final CollisionContext context; + private final Cursor3D cursor; +- private final BlockPos.MutableBlockPos pos; ++ private final BlockPos.MutableBlockPos pos; final BlockPos.MutableBlockPos getMutablePos() { return this.pos; } // Paper - OBFHELPER + private final VoxelShape entityShape; +- private final CollisionGetter collisionGetter; ++ private final CollisionGetter collisionGetter; final CollisionGetter getCollisionAccess() { return this.collisionGetter; } // Paper - OBFHELPER + private boolean needsBorderCheck; + private final BiPredicate predicate; + +@@ -64,23 +67,37 @@ public class CollisionSpliterator extends AbstractSpliterator { + boolean collisionCheck(Consumer consumer) { + while (true) { + if (this.cursor.advance()) { +- int i = this.cursor.nextX(); +- int j = this.cursor.nextY(); +- int k = this.cursor.nextZ(); ++ int i = this.cursor.nextX(); final int x = i; ++ int j = this.cursor.nextY(); final int y = j; ++ int k = this.cursor.nextZ(); final int z = k; + int l = this.cursor.getNextType(); + + if (l == 3) { + continue; + } + +- BlockGetter iblockaccess = this.getChunk(i, k); +- +- if (iblockaccess == null) { ++ // Paper start - ensure we don't load chunks ++ Entity entity = this.getEntity(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getMutablePos(); ++ boolean far = entity != null && MCUtil.distanceSq(entity.getX(), y, entity.getZ(), x, y, z) > 14; ++ blockposition_mutableblockposition.setValues(x, y, z); ++ ++ boolean isRegionLimited = this.getCollisionAccess() instanceof WorldGenRegion; ++ BlockState iblockdata = isRegionLimited ? Blocks.VOID_AIR.defaultBlockState() : ((!far && entity instanceof ServerPlayer) || (entity != null && entity.collisionLoadChunks) ++ ? this.getCollisionAccess().getBlockState(blockposition_mutableblockposition) ++ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition) ++ ); ++ ++ if (iblockdata == null) { ++ if (!(entity instanceof ServerPlayer) || entity.level.paperConfig.preventMovingIntoUnloadedChunks) { ++ VoxelShape voxelshape3 = Shapes.of(far ? entity.getBoundingBox() : new AABB(new BlockPos(x, y, z))); ++ consumer.accept(voxelshape3); ++ return true; ++ } + continue; + } +- +- this.pos.set(i, j, k); +- BlockState iblockdata = iblockaccess.getBlockState(this.pos); ++ // Paper - moved up ++ // Paper end + + if (!this.predicate.test(iblockdata, this.pos) || l == 1 && !iblockdata.hasLargeCollisionShape() || l == 2 && !iblockdata.is(Blocks.MOVING_PISTON)) { + continue; +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index fa2942d0b0424390daee2121f8959034c5352e0b..c14d5ebe16a693834ed218af8f737714065b2e17 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -249,7 +249,8 @@ public final class Shapes { + + if (k2 < 3) { + blockposition_mutableblockposition.set(enumaxiscycle1, i2, j2, l1); +- BlockState iblockdata = world.getBlockState(blockposition_mutableblockposition); ++ BlockState iblockdata = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper ++ if (iblockdata == null) return 0.0D; // Paper + + if ((k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { + initial = iblockdata.getCollisionShape((BlockGetter) world, blockposition_mutableblockposition, context).collide(enumdirection_enumaxis2, box.move((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), initial); diff --git a/Remapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch b/Remapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch new file mode 100644 index 0000000000..b748ace1a1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 17:16:48 -0400 +Subject: [PATCH] Don't tick dead players + +Causes sync chunk loads and who knows what all else. +This is safe because Spectators are skipped in unloaded chunks too in vanilla. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index a469016c43251f16913a365c4131b2448eaa4c48..286b75a27103a084a9f9d79a90716ebcad65d813 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -606,7 +606,7 @@ public class ServerPlayer extends Player implements ContainerListener { + + public void doTick() { + try { +- if (!this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { ++ if (valid && !this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) + super.tick(); + } + diff --git a/Remapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch b/Remapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch new file mode 100644 index 0000000000..3e2b8e5352 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 19:31:16 -0400 +Subject: [PATCH] Dead Player's shouldn't be able to move + +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 0685920073a6a2b2c6a80018d0c9009b2ef860c4..32f1b180e82f41f3ce1b49ea7d67b7d55d2b9ca7 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1046,7 +1046,7 @@ public abstract class Player extends LivingEntity { + + @Override + protected boolean isImmobile() { +- return super.isImmobile() || this.isSleeping(); ++ return super.isImmobile() || this.isSleeping() || removed || !valid; // Paper - player's who are dead or not in a world shouldn't move... + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/Remapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch new file mode 100644 index 0000000000..a211d40a2c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch @@ -0,0 +1,294 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 8 Apr 2020 03:06:30 -0400 +Subject: [PATCH] Optimize PlayerChunkMap memory use for visibleChunks + +No longer clones visible chunks which is causing massive memory +allocation issues, likely the source of Humongous Objects on large servers. + +Instead we just synchronize, clear and rebuild, reusing the same object buffers +as before with only 2 small objects created (FastIterator/MapEntry) + +This should result in siginificant memory use reduction and improved GC behavior. + +diff --git a/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f6ff4d8132a95895680f5bc81f8f873e78f0bbdb +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java +@@ -0,0 +1,39 @@ ++package com.destroystokyo.paper.util.map; ++ ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++ ++public class Long2ObjectLinkedOpenHashMapFastCopy extends Long2ObjectLinkedOpenHashMap { ++ ++ public void copyFrom(Long2ObjectLinkedOpenHashMapFastCopy map) { ++ if (key.length != map.key.length) { ++ key = null; ++ key = new long[map.key.length]; ++ } ++ if (value.length != map.value.length) { ++ value = null; ++ //noinspection unchecked ++ value = (V[]) new Object[map.value.length]; ++ } ++ if (link.length != map.link.length) { ++ link = null; ++ link = new long[map.link.length]; ++ } ++ System.arraycopy(map.key, 0, this.key, 0, map.key.length); ++ System.arraycopy(map.value, 0, this.value, 0, map.value.length); ++ System.arraycopy(map.link, 0, this.link, 0, map.link.length); ++ this.size = map.size; ++ this.mask = map.mask; ++ this.first = map.first; ++ this.last = map.last; ++ this.n = map.n; ++ this.maxFill = map.maxFill; ++ this.containsNullKey = map.containsNullKey; ++ } ++ ++ @Override ++ public Long2ObjectLinkedOpenHashMapFastCopy clone() { ++ Long2ObjectLinkedOpenHashMapFastCopy clone = (Long2ObjectLinkedOpenHashMapFastCopy) super.clone(); ++ clone.copyFrom(this); ++ return clone; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 99c3337eec552ba47d3b8b2d8feaaa80acf2a86f..9abef8550a89df5e15ac28de1a5549d064f29122 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -616,7 +616,7 @@ public final class MCUtil { + + ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); + ChunkMap chunkMap = world.getChunkSource().chunkMap; +- Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunkMap; ++ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.getVisibleChunks(); + DistanceManager chunkMapDistance = chunkMap.distanceManager; + List allChunks = new ArrayList<>(visibleChunks.values()); + List players = world.players; +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc08174003f4a 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -104,8 +104,33 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + private static final Logger LOGGER = LogManager.getLogger(); + public static final int MAX_CHUNK_DISTANCE = 33 + ChunkStatus.maxDistance(); +- public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); +- public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; ++ // Paper start - faster copying ++ public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<>(); // Paper - faster copying ++ public final Long2ObjectLinkedOpenHashMap visibleChunkMap = new ProtectedVisibleChunksMap(); // Paper - faster copying ++ ++ private class ProtectedVisibleChunksMap extends com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy { ++ @Override ++ public ChunkHolder put(long k, ChunkHolder playerChunk) { ++ throw new UnsupportedOperationException("Updating visible Chunks"); ++ } ++ ++ @Override ++ public ChunkHolder remove(long k) { ++ throw new UnsupportedOperationException("Removing visible Chunks"); ++ } ++ ++ @Override ++ public ChunkHolder get(long k) { ++ return ChunkMap.this.getVisibleChunkIfPresent(k); ++ } ++ ++ public ChunkHolder safeGet(long k) { ++ return super.get(k); ++ } ++ } ++ // Paper end ++ public final com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy pendingVisibleChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy(); // Paper - this is used if the visible chunks is updated while iterating only ++ public transient com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy visibleChunksClone; // Paper - used for async access of visible chunks, clone and cache only when needed + private final Long2ObjectLinkedOpenHashMap pendingUnloads; + public final LongSet entitiesInLevel; // Paper - private -> public + public final ServerLevel level; +@@ -178,7 +203,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier supplier, int i, boolean flag) { + super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag); +- this.visibleChunkMap = this.updatingChunkMap.clone(); ++ //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning + this.pendingUnloads = new Long2ObjectLinkedOpenHashMap(); + this.entitiesInLevel = new LongOpenHashSet(); + this.toDrop = new LongOpenHashSet(); +@@ -270,9 +295,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return (ChunkHolder) this.updatingChunkMap.get(pos); + } + ++ // Paper start - remove cloning of visible chunks unless accessed as a collection async ++ private static final boolean DEBUG_ASYNC_VISIBLE_CHUNKS = Boolean.getBoolean("paper.debug-async-visible-chunks"); ++ private boolean isIterating = false; ++ private boolean hasPendingVisibleUpdate = false; ++ public void forEachVisibleChunk(java.util.function.Consumer consumer) { ++ org.spigotmc.AsyncCatcher.catchOp("forEachVisibleChunk"); ++ boolean prev = isIterating; ++ isIterating = true; ++ try { ++ for (ChunkHolder value : this.visibleChunkMap.values()) { ++ consumer.accept(value); ++ } ++ } finally { ++ this.isIterating = prev; ++ if (!this.isIterating && this.hasPendingVisibleUpdate) { ++ ((ProtectedVisibleChunksMap)this.visibleChunkMap).copyFrom(this.pendingVisibleChunks); ++ this.pendingVisibleChunks.clear(); ++ this.hasPendingVisibleUpdate = false; ++ } ++ } ++ } ++ public Long2ObjectLinkedOpenHashMap getVisibleChunks() { ++ if (Thread.currentThread() == this.level.thread) { ++ return this.visibleChunkMap; ++ } else { ++ synchronized (this.visibleChunkMap) { ++ if (DEBUG_ASYNC_VISIBLE_CHUNKS) new Throwable("Async getVisibleChunks").printStackTrace(); ++ if (this.visibleChunksClone == null) { ++ this.visibleChunksClone = this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.clone() : ((ProtectedVisibleChunksMap)this.visibleChunkMap).clone(); ++ } ++ return this.visibleChunksClone; ++ } ++ } ++ } ++ // Paper end ++ + @Nullable + public ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public +- return (ChunkHolder) this.visibleChunkMap.get(pos); ++ // Paper start - mt safe get ++ if (Thread.currentThread() != this.level.thread) { ++ synchronized (this.visibleChunkMap) { ++ return (ChunkHolder) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(pos) : ((ProtectedVisibleChunksMap)this.visibleChunkMap).safeGet(pos)); ++ } ++ } ++ return (ChunkHolder) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(pos) : ((ProtectedVisibleChunksMap)this.visibleChunkMap).safeGet(pos)); ++ // Paper end + } + + protected IntSupplier getChunkQueueLevel(long pos) { +@@ -460,8 +528,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end + + protected void saveAllChunks(boolean flush) { ++ Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) + if (flush) { +- List list = (List) this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); ++ List list = (List) visibleChunks.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); // Paper - remove cloning of visible chunks + MutableBoolean mutableboolean = new MutableBoolean(); + + do { +@@ -489,7 +558,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // this.i(); // Paper - nuke IOWorker + ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); + } else { +- this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { ++ visibleChunks.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { + ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error + + if (ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk) { +@@ -660,7 +729,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (!this.modified) { + return false; + } else { +- this.visibleChunkMap = this.updatingChunkMap.clone(); ++ // Paper start - stop cloning visibleChunks ++ synchronized (this.visibleChunkMap) { ++ if (isIterating) { ++ hasPendingVisibleUpdate = true; ++ this.pendingVisibleChunks.copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunkMap); ++ } else { ++ hasPendingVisibleUpdate = false; ++ this.pendingVisibleChunks.clear(); ++ ((ProtectedVisibleChunksMap)this.visibleChunkMap).copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunkMap); ++ this.visibleChunksClone = null; ++ } ++ } ++ // Paper end ++ + this.modified = false; + return true; + } +@@ -1139,12 +1221,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + protected Iterable getChunks() { +- return Iterables.unmodifiableIterable(this.visibleChunkMap.values()); ++ return Iterables.unmodifiableIterable(this.getVisibleChunks().values()); // Paper + } + + void dumpChunks(Writer writer) throws IOException { + CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("entity_count").addColumn("block_entity_count").build(writer); +- ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunkMap.long2ObjectEntrySet().iterator(); ++ ObjectBidirectionalIterator objectbidirectionaliterator = this.getVisibleChunks().long2ObjectEntrySet().iterator(); // Paper + + while (objectbidirectionaliterator.hasNext()) { + Entry entry = (Entry) objectbidirectionaliterator.next(); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index e2b1541042bceac965411e3176d08c61f217c07f..f5de878020be9465739fba07fd7dea46b0a3ae34 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -782,7 +782,7 @@ public class ServerChunkCache extends ChunkSource { + }; + // Paper end + this.level.timings.chunkTicks.startTiming(); // Paper +- this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... ++ this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + + if (optional.isPresent()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index fb74bdcf4c2935b56e92717cc5a1504fbc853d0a..1a839242e359fa32f32d0e571c6e918ac39642e9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -276,6 +276,7 @@ public class CraftWorld implements World { + return ret; + } + public int getTileEntityCount() { ++ return net.minecraft.server.MCUtil.ensureMain(() -> { + // We don't use the full world tile entity list, so we must iterate chunks + Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; + int size = 0; +@@ -287,11 +288,13 @@ public class CraftWorld implements World { + size += chunk.blockEntities.size(); + } + return size; ++ }); + } + public int getTickableTileEntityCount() { + return world.tickableBlockEntities.size(); + } + public int getChunkCount() { ++ return net.minecraft.server.MCUtil.ensureMain(() -> { + int ret = 0; + + for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { +@@ -300,7 +303,7 @@ public class CraftWorld implements World { + } + } + +- return ret; ++ return ret; }); + } + public int getPlayerCount() { + return world.players.size(); +@@ -425,6 +428,14 @@ public class CraftWorld implements World { + + @Override + public Chunk[] getLoadedChunks() { ++ // Paper start ++ if (Thread.currentThread() != world.getLevel().thread) { ++ synchronized (world.getChunkSource().chunkMap.visibleChunkMap) { ++ Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; ++ return chunks.values().stream().map(ChunkHolder::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new); ++ } ++ } ++ // Paper end + Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; + return chunks.values().stream().map(ChunkHolder::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new); + } diff --git a/Remapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch b/Remapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch new file mode 100644 index 0000000000..f5ba659507 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 8 Apr 2020 21:24:05 -0400 +Subject: [PATCH] Increase Light Queue Size + +Wiz mentioned that large WorldEdit operations cause light to run on +main thread. The queue was small, set to 5.. this bumps it to 20 +but makes it configurable per-world. + +The main risk of increasing this higher is during shutdown, some +queued light updates may be lost because mojang did not flush the +light engine on shutdown... + +The queue size only puts a cap on max loss, doesn't solve that problem. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1..cd248eb6be663e8be33f2c3c6b06b77b6d5753a4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -620,4 +620,9 @@ public class PaperWorldConfig { + private void zombieVillagerInfectionChance() { + zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); + } ++ ++ public int lightQueueSize = 20; ++ private void lightQueueSize() { ++ lightQueueSize = getInt("light-queue-size", lightQueueSize); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index e33189dc8375a3034910087654607fb531061636..11c6e8ce10c53dcb639145fbda32c5426eb6b3d9 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -775,7 +775,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Thu, 9 Apr 2020 00:09:26 -0400 +Subject: [PATCH] Mid Tick Chunk Tasks - Speed up processing of chunk loads and + generation + +Credit to Spotted for the idea + +A lot of the new chunk system requires constant back and forth the main thread +to handle priority scheduling and ensuring conflicting tasks do not run at the +same time. + +The issue is, these queues are only checked at either: + +A) Sync Chunk Loads +B) End of Tick while sleeping + +This results in generating chunks sitting waiting for a full tick to +complete before it will even start the next unit of work to do. + +Additionally, this also delays loading of chunks until this same timing. + +We will now periodically poll the chunk task queues throughout the tick, +looking for work to do. +We do this in a fair method that considers all worlds, not just the one being +ticked, so that each world can get 1 task procesed each before the next pass. + +In a view distance of 15, chunk loading performance was visually faster on the client. + +Flying at high speed in spectator mode was able to keep up with chunk loading (as long as they are already generated) + +diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java +index be3a62f543a5fec4739c14821fe5a443c1fa3f5b..6bff5317939635b925bb41eb7a67d1fd95715078 100644 +--- a/src/main/java/co/aikar/timings/MinecraftTimings.java ++++ b/src/main/java/co/aikar/timings/MinecraftTimings.java +@@ -17,6 +17,7 @@ import java.util.Map; + public final class MinecraftTimings { + + public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); ++ public static final Timing midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks"); + public static final Timing playerListTimer = Timings.ofSafe("Player List"); + public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); + public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index da93d38fe63035e4ff198ada84a4431f52d97c01..ddbc8cb712c50038922eded75dd6ca85fe851078 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -410,4 +410,9 @@ public class PaperConfig { + log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); + } + } ++ ++ public static int midTickChunkTasks = 1000; ++ private static void midTickChunkTasks() { ++ midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b174dee62 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1055,6 +1055,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { ++ midTickLoadChunks(); // will only do loads since we are still considered !canSleepForTick + return !this.canOversleep(); + }); + isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); +@@ -1318,13 +1337,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Paper - safe iterator incase chunk loads, also no wrapping ++ final int[] chunksTicked = {0}; this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + + if (optional.isPresent()) { +@@ -806,6 +809,7 @@ public class ServerChunkCache extends ChunkSource { + //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper + this.level.tickChunk(chunk, k); + //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper ++ if (chunksTicked[0]++ % 10 == 0) this.level.getServer().midTickLoadChunks(); // Paper + } + } + } +@@ -963,6 +967,41 @@ public class ServerChunkCache extends ChunkSource { + super.doRunTask(task); + } + ++ // Paper start ++ private long lastMidTickChunkTask = 0; ++ public boolean pollChunkLoadTasks() { ++ if (com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ServerChunkCache.this.level.asyncChunkTaskManager.pollNextChunkTask()) { ++ try { ++ ServerChunkCache.this.runDistanceManagerUpdates(); ++ } finally { ++ // from below: process pending Chunk loadCallback() and unloadCallback() after each run task ++ chunkMap.callbackExecutor.run(); ++ } ++ return true; ++ } ++ return false; ++ } ++ public void midTickLoadChunks() { ++ MinecraftServer server = ServerChunkCache.this.level.getServer(); ++ // always try to load chunks, restrain generation/other updates only. don't count these towards tick count ++ //noinspection StatementWithEmptyBody ++ while (pollChunkLoadTasks()) {} ++ ++ if (System.nanoTime() - lastMidTickChunkTask < 200000) { ++ return; ++ } ++ ++ for (;server.midTickChunksTasksRan < com.destroystokyo.paper.PaperConfig.midTickChunkTasks && server.haveTime();) { ++ if (this.pollTask()) { ++ server.midTickChunksTasksRan++; ++ lastMidTickChunkTask = System.nanoTime(); ++ } else { ++ break; ++ } ++ } ++ } ++ // Paper end ++ + @Override + protected boolean pollTask() { + // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 5127bce423a83711cea94e387b3ae7866215ded5..4e75cc5e52a5295e32ccadb371702a405bb518bb 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -565,6 +565,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + timings.scheduledBlocks.stopTiming(); // Paper + ++ this.getServer().midTickLoadChunks(); // Paper + gameprofilerfiller.popPush("raid"); + this.timings.raids.startTiming(); // Paper - timings + this.raids.tick(); +@@ -573,6 +574,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + timings.doSounds.startTiming(); // Spigot + this.runBlockEvents(); + timings.doSounds.stopTiming(); // Spigot ++ this.getServer().midTickLoadChunks(); // Paper + this.handlingTick = false; + gameprofilerfiller.popPush("entities"); + boolean flag3 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players +@@ -639,6 +641,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + timings.entityTick.stopTiming(); // Spigot + + this.tickingEntities = false; ++ this.getServer().midTickLoadChunks(); // Paper + + Entity entity2; + +@@ -648,6 +651,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + timings.tickEntities.stopTiming(); // Spigot ++ this.getServer().midTickLoadChunks(); // Paper + this.tickBlockEntities(); + } + diff --git a/Remapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch b/Remapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch new file mode 100644 index 0000000000..02f8b575b0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 9 Apr 2020 21:20:33 -0400 +Subject: [PATCH] Don't move existing players to world spawn + +This can cause a nasty server lag the spawn chunks are not kept loaded +or they aren't finished loading yet, or if the world spawn radius is +larger than the keep loaded range. + +By skipping this, we avoid potential for a large spike on server start. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 286b75a27103a084a9f9d79a90716ebcad65d813..162b1a8c6ab57aafa4f6deefc842755a8e14208e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -251,7 +251,7 @@ public class ServerPlayer extends Player implements ContainerListener { + this.stats = server.getPlayerList().getStatisticManager(this); + this.advancements = server.getPlayerList().getPlayerAdvancements(this); + this.maxUpStep = 1.0F; +- this.fudgeSpawnLocation(world); ++ //this.c(worldserver); // Paper - don't move to spawn on login, only first join + this.textFilter = server.createTextFilterForPlayer(this); + + this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper +@@ -303,6 +303,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + // CraftBukkit end + ++ public final void moveToSpawn(ServerLevel worldserver) { fudgeSpawnLocation(worldserver); } // Paper - OBFHELPER + private void fudgeSpawnLocation(ServerLevel world) { + BlockPos blockposition = world.getSpawn(); + +@@ -480,7 +481,7 @@ public class ServerPlayer extends Player implements ContainerListener { + position = Vec3.atCenterOf(((ServerLevel) world).getSpawn()); + } + this.level = world; +- this.setPos(position.x(), position.y(), position.z()); ++ this.setPosRaw(position.x(), position.y(), position.z()); // Paper - don't register to chunks yet + } + this.gameMode.setLevel((ServerLevel) world); + } +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 86c5549196a4e9011c5240e7918b466c299be4a3..30666fca36b683158ff60302684b5093f5536e24 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -204,6 +204,8 @@ public abstract class PlayerList { + worldserver1 = worldserver; + } + ++ if (nbttagcompound == null) player.moveToSpawn(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are.... ++ + player.setLevel(worldserver1); + player.gameMode.setLevel((ServerLevel) player.level); + String s1 = "local"; diff --git a/Remapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch b/Remapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch new file mode 100644 index 0000000000..0f2cf4005e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch @@ -0,0 +1,169 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 5 Apr 2020 22:23:14 -0500 +Subject: [PATCH] Add tick times API and /mspt command + + +diff --git a/src/main/java/com/destroystokyo/paper/MSPTCommand.java b/src/main/java/com/destroystokyo/paper/MSPTCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d0211d4f39f9d6af1d751ac66342b42cc6d7ba6d +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/MSPTCommand.java +@@ -0,0 +1,64 @@ ++package com.destroystokyo.paper; ++ ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.ChatColor; ++import org.bukkit.Location; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++ ++import java.text.DecimalFormat; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.List; ++ ++public class MSPTCommand extends Command { ++ private static final DecimalFormat DF = new DecimalFormat("########0.0"); ++ ++ public MSPTCommand(String name) { ++ super(name); ++ this.description = "View server tick times"; ++ this.usageMessage = "/mspt"; ++ this.setPermission("bukkit.command.mspt"); ++ } ++ ++ @Override ++ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { ++ return Collections.emptyList(); ++ } ++ ++ @Override ++ public boolean execute(CommandSender sender, String commandLabel, String[] args) { ++ if (!testPermission(sender)) return true; ++ ++ MinecraftServer server = MinecraftServer.getServer(); ++ ++ List times = new ArrayList<>(); ++ times.addAll(eval(server.tickTimes5s.getTimes())); ++ times.addAll(eval(server.tickTimes10s.getTimes())); ++ times.addAll(eval(server.tickTimes60s.getTimes())); ++ ++ sender.sendMessage("§6Server tick times §e(§7avg§e/§7min§e/§7max§e)§6 from last 5s§7,§6 10s§7,§6 1m§e:"); ++ sender.sendMessage(String.format("§6◴ %s§7/%s§7/%s§e, %s§7/%s§7/%s§e, %s§7/%s§7/%s", times.toArray())); ++ return true; ++ } ++ ++ private static List eval(long[] times) { ++ long min = Integer.MAX_VALUE; ++ long max = 0L; ++ long total = 0L; ++ for (long value : times) { ++ if (value > 0L && value < min) min = value; ++ if (value > max) max = value; ++ total += value; ++ } ++ double avgD = ((double) total / (double) times.length) * 1.0E-6D; ++ double minD = ((double) min) * 1.0E-6D; ++ double maxD = ((double) max) * 1.0E-6D; ++ return Arrays.asList(getColor(avgD), getColor(minD), getColor(maxD)); ++ } ++ ++ private static String getColor(double avg) { ++ return ChatColor.COLOR_CHAR + (avg >= 50 ? "c" : avg >= 40 ? "e" : "a") + DF.format(avg); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index ddbc8cb712c50038922eded75dd6ca85fe851078..78271b400c79578d043b20a5389a37b1bef9a70d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -69,6 +69,7 @@ public class PaperConfig { + + commands = new HashMap(); + commands.put("paper", new PaperCommand("paper")); ++ commands.put("mspt", new MSPTCommand("mspt")); + + version = getInt("config-version", 20); + set("config-version", 20); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 087f31ac0cc7816b1cbeffc45be6927b174dee62..99ee9de92264381a064066bc22bb66b4b2852a2e 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -217,6 +217,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Fri, 10 Apr 2020 21:24:12 -0400 +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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 4fa49b6bb26456d485f7f9193af560cb379e36f0..3f35e93b42efd03ff1002f09962fe3da51fb4c3f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2378,5 +2378,10 @@ public final class CraftServer implements Server { + public int getCurrentTick() { + return net.minecraft.server.MinecraftServer.currentTick; + } ++ ++ @Override ++ public boolean isStopping() { ++ return net.minecraft.server.MinecraftServer.getServer().hasStopped(); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch b/Remapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch new file mode 100644 index 0000000000..4f867cd88c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Thu, 30 Apr 2020 16:56:54 +0200 +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/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java +index b3838e709c1581c25da7738c9a03a827761845b1..05ace1d046e32a261e67bff5afc18c2d32e1a8aa 100644 +--- a/src/main/java/net/minecraft/nbt/NbtIo.java ++++ b/src/main/java/net/minecraft/nbt/NbtIo.java +@@ -51,6 +51,7 @@ public class NbtIo { + return nbttagcompound; + } + ++ public static CompoundTag readNBT(InputStream inputstream) throws IOException { return readCompressed(inputstream); } // Paper - OBFHELPER + public static CompoundTag readCompressed(InputStream stream) throws IOException { + DataInputStream datainputstream = new DataInputStream(new BufferedInputStream(new GZIPInputStream(stream))); + Throwable throwable = null; +@@ -106,6 +107,7 @@ public class NbtIo { + + } + ++ public static void writeNBT(CompoundTag nbttagcompound, OutputStream outputstream) throws IOException { writeCompressed(nbttagcompound, outputstream); } // Paper - OBFHELPER + public static void writeCompressed(CompoundTag tag, OutputStream stream) throws IOException { + DataOutputStream dataoutputstream = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(stream))); + Throwable throwable = null; +diff --git a/src/main/java/net/minecraft/util/datafix/DataFixers.java b/src/main/java/net/minecraft/util/datafix/DataFixers.java +index 950a4b67f9091af551ec1036ebeb943e3b335e91..dc4e2fc26e1bc2c545f955d30c052bb86e3ef614 100644 +--- a/src/main/java/net/minecraft/util/datafix/DataFixers.java ++++ b/src/main/java/net/minecraft/util/datafix/DataFixers.java +@@ -78,6 +78,7 @@ public class DataFixers { + return datafixerbuilder.build(Util.bootstrapExecutor()); + } + ++ public static DataFixer getDataFixer() { return getDataFixer(); } // Paper - OBFHELPER + public static DataFixer getDataFixer() { + return DataFixers.DATA_FIXER; + } +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index ac996d581925c8f92832009945c766962e5b51c5..458cdfbeac9d757c9721acd4557a548affa0ede1 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -196,6 +196,7 @@ public final class ItemStack { + this.updateEmptyCacheFlag(); + } + ++ public static ItemStack fromCompound(CompoundTag nbttagcompound) { return of(nbttagcompound); } // Paper - OBFHELPER + public static ItemStack of(CompoundTag tag) { + try { + return new ItemStack(tag); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 86b319337fc41a09dd45df466df60cadaed1343f..a5a5038a84434e69fda8f6b41d2f00b4989e25ae 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -378,6 +378,46 @@ public final class CraftMagicNumbers implements UnsafeValues { + public boolean isSupportedApiVersion(String apiVersion) { + return apiVersion != null && SUPPORTED_API.contains(apiVersion); + } ++ ++ @Override ++ public byte[] serializeItem(ItemStack item) { ++ Preconditions.checkNotNull(item, "null cannot be serialized"); ++ Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized"); ++ ++ java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); ++ CompoundTag compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).getHandle() : CraftItemStack.asNMSCopy(item)).save(new CompoundTag()); ++ compound.putInt("DataVersion", getDataVersion()); ++ try { ++ net.minecraft.nbt.NbtIo.writeNBT( ++ compound, ++ outputStream ++ ); ++ } catch (IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return outputStream.toByteArray(); ++ } ++ ++ @Override ++ public ItemStack deserializeItem(byte[] data) { ++ Preconditions.checkNotNull(data, "null cannot be deserialized"); ++ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing"); ++ ++ try { ++ CompoundTag compound = net.minecraft.nbt.NbtIo.readNBT( ++ new java.io.ByteArrayInputStream(data) ++ ); ++ int dataVersion = compound.getInt("DataVersion"); ++ ++ Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); ++ Dynamic converted = DataFixers.getDataFixer().update(References.ITEM_STACK, new Dynamic(NbtOps.INSTANCE, compound), dataVersion, getDataVersion()); ++ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.fromCompound((CompoundTag) converted.getValue())); ++ } catch (IOException ex) { ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(ex); ++ throw new RuntimeException(); ++ } ++ } + // Paper end + + /** diff --git a/Remapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch b/Remapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch new file mode 100644 index 0000000000..019eef698e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch @@ -0,0 +1,253 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 17:53:29 -0700 +Subject: [PATCH] Remove streams from Mob AI System + +The streams hurt performance and allocate tons of garbage, so +replace them with the standard iterator. + +Also optimise the stream.anyMatch statement to move to a bitset +where we can replace the call with a single bitwise operation. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +index 558dd72c47930f6993952467f83b5a54ead95d92..acc6306d659cd65a043d12cd42dcbaf55aaf5250 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +@@ -1,10 +1,12 @@ + package net.minecraft.world.entity.ai.goal; + ++import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector + import java.util.EnumSet; + + public abstract class Goal { + +- private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); ++ private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. ++ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector + + public Goal() {} + +@@ -28,16 +30,20 @@ public abstract class Goal { + public void tick() {} + + public void setFlags(EnumSet controls) { +- this.flags.clear(); +- this.flags.addAll(controls); ++ // Paper start - remove streams from pathfindergoalselector ++ this.goalTypes.clear(); ++ this.goalTypes.addAllUnchecked(controls); ++ // Paper end - remove streams from pathfindergoalselector + } + + public String toString() { + return this.getClass().getSimpleName(); + } + +- public EnumSet getFlags() { +- return this.flags; ++ // Paper start - remove streams from pathfindergoalselector ++ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { ++ return this.goalTypes; ++ // Paper end - remove streams from pathfindergoalselector + } + + public static enum Flag { +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +index 9bd2ee05a0de6678ad8933a8ffbe0ae66bd073b4..5da2d780c17522e07c733a5e23b17ec760c7b342 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +@@ -1,8 +1,10 @@ + package net.minecraft.world.entity.ai.goal; + ++import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector + import com.google.common.collect.Sets; + import java.util.EnumMap; + import java.util.EnumSet; ++import java.util.Iterator; // Paper - remove streams from pathfindergoalselector + import java.util.Map; + import java.util.Set; + import java.util.function.Supplier; +@@ -28,7 +30,8 @@ public class GoalSelector { + private final Map lockedFlags = new EnumMap(Goal.Flag.class); + private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER + private final Supplier profiler; +- private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); ++ private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. ++ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector + private int newGoalRate = 3;private int getTickRate() { return newGoalRate; } // Paper - OBFHELPER + private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO + +@@ -56,35 +59,38 @@ public class GoalSelector { + // Paper end + + public void removeGoal(Goal goal) { +- this.availableGoals.stream().filter((pathfindergoalwrapped) -> { +- return pathfindergoalwrapped.getGoal() == goal; +- }).filter(WrappedGoal::isRunning).forEach(WrappedGoal::stop); +- this.availableGoals.removeIf((pathfindergoalwrapped) -> { +- return pathfindergoalwrapped.getGoal() == goal; +- }); ++ // Paper start - remove streams from pathfindergoalselector ++ for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal goalWrapped = iterator.next(); ++ if (goalWrapped.getGoal() != goal) { ++ continue; ++ } ++ if (goalWrapped.isRunning()) { ++ goalWrapped.stop(); ++ } ++ iterator.remove(); ++ } ++ // Paper end - remove streams from pathfindergoalselector + } + ++ private static final Goal.Flag[] PATHFINDER_GOAL_TYPES = Goal.Flag.values(); // Paper - remove streams from pathfindergoalselector ++ + public void tick() { + ProfilerFiller gameprofilerfiller = (ProfilerFiller) this.profiler.get(); + + gameprofilerfiller.push("goalCleanup"); +- this.getRunningGoals().filter((pathfindergoalwrapped) -> { +- boolean flag; +- +- if (pathfindergoalwrapped.isRunning()) { +- Stream stream = pathfindergoalwrapped.getFlags().stream(); +- EnumSet enumset = this.disabledFlags; +- +- this.disabledFlags.getClass(); +- if (!stream.anyMatch(enumset::contains) && pathfindergoalwrapped.canContinueToUse()) { +- flag = false; +- return flag; +- } ++ // Paper start - remove streams from pathfindergoalselector ++ for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal wrappedGoal = iterator.next(); ++ if (!wrappedGoal.isRunning()) { ++ continue; + } +- +- flag = true; +- return flag; +- }).forEach(Goal::stop); ++ if (!this.goalTypes.hasCommonElements(wrappedGoal.getGoalTypes()) && wrappedGoal.canContinueToUse()) { ++ continue; ++ } ++ wrappedGoal.stop(); ++ } ++ // Paper end - remove streams from pathfindergoalselector + this.lockedFlags.forEach((pathfindergoal_type, pathfindergoalwrapped) -> { + if (!pathfindergoalwrapped.isRunning()) { + this.lockedFlags.remove(pathfindergoal_type); +@@ -93,30 +99,58 @@ public class GoalSelector { + }); + gameprofilerfiller.pop(); + gameprofilerfiller.push("goalUpdate"); +- this.availableGoals.stream().filter((pathfindergoalwrapped) -> { +- return !pathfindergoalwrapped.isRunning(); +- }).filter((pathfindergoalwrapped) -> { +- Stream stream = pathfindergoalwrapped.getFlags().stream(); +- EnumSet enumset = this.disabledFlags; +- +- this.disabledFlags.getClass(); +- return stream.noneMatch(enumset::contains); +- }).filter((pathfindergoalwrapped) -> { +- return pathfindergoalwrapped.getFlags().stream().allMatch((pathfindergoal_type) -> { +- return ((WrappedGoal) this.lockedFlags.getOrDefault(pathfindergoal_type, GoalSelector.NO_GOAL)).canBeReplacedBy(pathfindergoalwrapped); +- }); +- }).filter(WrappedGoal::canUse).forEach((pathfindergoalwrapped) -> { +- pathfindergoalwrapped.getFlags().forEach((pathfindergoal_type) -> { +- WrappedGoal pathfindergoalwrapped1 = (WrappedGoal) this.lockedFlags.getOrDefault(pathfindergoal_type, GoalSelector.NO_GOAL); +- +- pathfindergoalwrapped1.stop(); +- this.lockedFlags.put(pathfindergoal_type, pathfindergoalwrapped); +- }); +- pathfindergoalwrapped.start(); +- }); ++ // Paper start - remove streams from pathfindergoalselector ++ goal_update_loop: for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal wrappedGoal = iterator.next(); ++ if (wrappedGoal.isRunning()) { ++ continue; ++ } ++ ++ OptimizedSmallEnumSet wrappedGoalSet = wrappedGoal.getGoalTypes(); ++ ++ if (this.goalTypes.hasCommonElements(wrappedGoalSet)) { ++ continue; ++ } ++ ++ long iterator1 = wrappedGoalSet.getBackingSet(); ++ int wrappedGoalSize = wrappedGoalSet.size(); ++ for (int i = 0; i < wrappedGoalSize; ++i) { ++ Goal.Flag type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; ++ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); ++ WrappedGoal wrapped = this.lockedFlags.getOrDefault(type, GoalSelector.NO_GOAL); ++ if (!wrapped.canBeReplacedBy(wrappedGoal)) { ++ continue goal_update_loop; ++ } ++ } ++ ++ if (!wrappedGoal.canUse()) { ++ continue; ++ } ++ ++ iterator1 = wrappedGoalSet.getBackingSet(); ++ wrappedGoalSize = wrappedGoalSet.size(); ++ for (int i = 0; i < wrappedGoalSize; ++i) { ++ Goal.Flag type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; ++ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); ++ WrappedGoal wrapped = this.lockedFlags.getOrDefault(type, GoalSelector.NO_GOAL); ++ ++ wrapped.stop(); ++ this.lockedFlags.put(type, wrappedGoal); ++ } ++ ++ wrappedGoal.start(); ++ } ++ // Paper end - remove streams from pathfindergoalselector + gameprofilerfiller.pop(); + gameprofilerfiller.push("goalTick"); +- this.getRunningGoals().forEach(WrappedGoal::tick); ++ // Paper start - remove streams from pathfindergoalselector ++ for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal wrappedGoal = iterator.next(); ++ if (wrappedGoal.isRunning()) { ++ wrappedGoal.tick(); ++ } ++ } ++ // Paper end - remove streams from pathfindergoalselector + gameprofilerfiller.pop(); + } + +@@ -125,11 +159,11 @@ public class GoalSelector { + } + + public void disableControlFlag(Goal.Flag control) { +- this.disabledFlags.add(control); ++ this.goalTypes.addUnchecked(control); // Paper - remove streams from pathfindergoalselector + } + + public void enableControlFlag(Goal.Flag control) { +- this.disabledFlags.remove(control); ++ this.goalTypes.removeUnchecked(control); // Paper - remove streams from pathfindergoalselector + } + + public void setControlFlag(Goal.Flag control, boolean enabled) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +index 81b4618a7979ee8dd25e1749c084de9262318ef4..984146b2b6eb3e498433b1c4971397848166d9c9 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +@@ -59,9 +59,10 @@ public class WrappedGoal extends Goal { + this.goal.setFlags(controls); + } + +- @Override +- public EnumSet getFlags() { +- return this.goal.getFlags(); ++ // Paper start - remove streams from pathfindergoalselector ++ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { ++ return this.goal.getGoalTypes(); ++ // Paper end - remove streams from pathfindergoalselector + } + + public boolean isRunning() { return this.isRunning(); } // Paper - OBFHELPER diff --git a/Remapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch b/Remapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch new file mode 100644 index 0000000000..9fb51d1e35 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 11 Apr 2020 21:23:42 -0400 +Subject: [PATCH] Delay unsafe actions until after entity ticking is done + +This will help prevent many cases of unregistering entities during entity ticking + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 4e75cc5e52a5295e32ccadb371702a405bb518bb..b9978d296b83e73d3395b8254c0e8ccd9b36d0fa 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -172,6 +172,16 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final List players = Lists.newArrayList(); // Paper - private -> public + public final ServerChunkCache chunkSource; // Paper - public + boolean tickingEntities; ++ // Paper start ++ List afterEntityTickingTasks = Lists.newArrayList(); ++ public void doIfNotEntityTicking(java.lang.Runnable run) { ++ if (tickingEntities) { ++ afterEntityTickingTasks.add(run); ++ } else { ++ run.run(); ++ } ++ } ++ // Paper end + private final MinecraftServer server; + public final PrimaryLevelData worldDataServer; // CraftBukkit - type + public boolean noSave; +@@ -641,6 +651,16 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + timings.entityTick.stopTiming(); // Spigot + + this.tickingEntities = false; ++ // Paper start ++ for (java.lang.Runnable run : this.afterEntityTickingTasks) { ++ try { ++ run.run(); ++ } catch (Exception e) { ++ LOGGER.error("Error in After Entity Ticking Task", e); ++ } ++ } ++ this.afterEntityTickingTasks.clear(); ++ // Paper end + this.getServer().midTickLoadChunks(); // Paper + + Entity entity2; diff --git a/Remapped-Spigot-Server-Patches/0435-Async-command-map-building.patch b/Remapped-Spigot-Server-Patches/0435-Async-command-map-building.patch new file mode 100644 index 0000000000..87f32eb782 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0435-Async-command-map-building.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Callahan +Date: Wed, 8 Apr 2020 02:42:14 -0500 +Subject: [PATCH] Async command map building + + +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index 44f2e8a3741afc0e3c3bca3b0864e37ecf83e5d4..8154d9327c5411bbfea3bfa4d99d57feab764664 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -29,6 +29,7 @@ import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.game.ClientboundCommandsPacket; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.commands.AdvancementCommands; + import net.minecraft.server.commands.AttributeCommand; + import net.minecraft.server.commands.BanIpCommands; +@@ -328,25 +329,40 @@ public class Commands { + if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot + // CraftBukkit start + // Register Vanilla commands into builtRoot as before ++ // Paper start - Async command map building ++ java.util.concurrent.ForkJoinPool.commonPool().execute(() -> { ++ sendAsync(player); ++ }); ++ } ++ ++ private void sendAsync(ServerPlayer entityplayer) { ++ // Paper end - Async command map building + Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues + RootCommandNode vanillaRoot = new RootCommandNode(); + +- RootCommandNode vanilla = player.server.vanillaCommandDispatcher.getDispatcher().getRoot(); ++ RootCommandNode vanilla = entityplayer.server.vanillaCommandDispatcher.getDispatcher().getRoot(); + map.put(vanilla, vanillaRoot); +- this.fillUsableCommands(vanilla, vanillaRoot, player.createCommandSourceStack(), (Map) map); ++ this.fillUsableCommands(vanilla, vanillaRoot, entityplayer.createCommandSourceStack(), (Map) map); + + // Now build the global commands in a second pass + RootCommandNode rootcommandnode = new RootCommandNode(); + + map.put(this.dispatcher.getRoot(), rootcommandnode); +- this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, player.createCommandSourceStack(), (Map) map); ++ this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, entityplayer.createCommandSourceStack(), (Map) map); + + Collection bukkit = new LinkedHashSet<>(); + for (CommandNode node : rootcommandnode.getChildren()) { + bukkit.add(node.getName()); + } ++ // Paper start - Async command map building ++ MinecraftServer.getServer().execute(() -> { ++ runSync(entityplayer, bukkit, rootcommandnode); ++ }); ++ } + +- PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit)); ++ private void runSync(ServerPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { ++ // Paper end - Async command map building ++ PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); + event.getPlayer().getServer().getPluginManager().callEvent(event); + + // Remove labels that were removed during the event +@@ -356,7 +372,7 @@ public class Commands { + } + } + // CraftBukkit end +- player.connection.send(new ClientboundCommandsPacket(rootcommandnode)); ++ entityplayer.connection.send(new ClientboundCommandsPacket(rootcommandnode)); + } + + private void fillUsableCommands(CommandNode tree, CommandNode result, CommandSourceStack source, Map, CommandNode> resultNodes) { diff --git a/Remapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch b/Remapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch new file mode 100644 index 0000000000..928b62d524 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch @@ -0,0 +1,608 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 12 Apr 2020 15:50:48 -0400 +Subject: [PATCH] Improved Watchdog Support + +Forced Watchdog Crash support and Improve Async Shutdown + +If the request to shut down the server is received while we are in +a watchdog hang, immediately treat it as a crash and begin the shutdown +process. Shutdown process is now improved to also shutdown cleanly when +not using restart scripts either. + +If a server is deadlocked, a server owner can send SIGUP (or any other signal +the JVM understands to shut down as it currently does) and the watchdog +will no longer need to wait until the full timeout, allowing you to trigger +a close process and try to shut the server down gracefully, saving player and +world data. + +Previously there was no way to trigger this outside of waiting for a full watchdog +timeout, which may be set to a really long time... + +Additionally, fix everything to do with shutting the server down asynchronously. + +Previously, nearly everything about the process was fragile and unsafe. Main might +not have actually been frozen, and might still be manipulating state. + +Or, some reuest might ask main to do something in the shutdown but main is dead. + +Or worse, other things might start closing down items such as the Console or Thread Pool +before we are fully shutdown. + +This change tries to resolve all of these issues by moving everything into the stop +method and guaranteeing only one thread is stopping the server. + +We then issue Thread Death to the main thread of another thread initiates the stop process. +We have to ensure Thread Death propagates correctly though to stop main completely. + +This is to ensure that if main isn't truely stuck, it's not manipulating state we are trying to save. + +This also moves all plugins who register "delayed init" tasks to occur just before "Done" so they +are properly accounted for and wont trip watchdog on init. + +diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java +index 0b9e689d57705965721b5c55bc45d36657f360e4..dee00aac05f1acf050f05d4db557a08dd0f301c8 100644 +--- a/src/main/java/com/destroystokyo/paper/Metrics.java ++++ b/src/main/java/com/destroystokyo/paper/Metrics.java +@@ -92,7 +92,12 @@ public class Metrics { + * Starts the Scheduler which submits our data every 30 minutes. + */ + private void startSubmitting() { +- final Runnable submitTask = this::submitData; ++ final Runnable submitTask = () -> { ++ if (MinecraftServer.getServer().hasStopped()) { ++ return; ++ } ++ submitData(); ++ }; + + // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the + // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. +diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java +index 4008fbe506e74f2c463dc7b12f5dd0f3b6fc342d..766ab2fe536a2acccaec28e922ccf8993b0790dc 100644 +--- a/src/main/java/net/minecraft/CrashReport.java ++++ b/src/main/java/net/minecraft/CrashReport.java +@@ -257,6 +257,7 @@ public class CrashReport { + } + + public static CrashReport forThrowable(Throwable cause, String title) { ++ if (cause instanceof ThreadDeath) com.destroystokyo.paper.util.SneakyThrow.sneaky(cause); // Paper + while (cause instanceof CompletionException && cause.getCause() != null) { + cause = cause.getCause(); + } +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index c2f747226f10479c826849af898538610a2dd659..83f9f97586f8c0e9d228923e4fec6f121a6702e2 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -129,6 +129,7 @@ public class Util { + return Util.IO_POOL; + } + ++ public static void shutdownServerThreadPool() { shutdownExecutors(); } // Paper - OBFHELPER + public static void shutdownExecutors() { + shutdownExecutor(Util.BACKGROUND_EXECUTOR); + shutdownExecutor(Util.IO_POOL); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 99ee9de92264381a064066bc22bb66b4b2852a2e..e5ad635a480d32e7a10ee92c65cfc18a98beafad 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -269,7 +269,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) { + AtomicReference atomicreference = new AtomicReference(); + Thread thread = new Thread(() -> { +@@ -851,6 +854,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { ++ world.tickingEntities = false; ++ }); ++ } ++ // Paper end + // CraftBukkit end + MinecraftServer.LOGGER.info("Stopping server"); + MinecraftTimings.stopServer(); // Paper +@@ -930,7 +951,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop {}; ++ } ++ // Paper end + return new TickTask(this.tickCount, runnable); + } + +@@ -1421,6 +1478,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { + CompletableFuture completablefuture; +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index b9978d296b83e73d3395b8254c0e8ccd9b36d0fa..bf4e50cd1d561456c033cda2d5c5487c5e3fe1eb 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -171,7 +171,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + private final Queue toAddAfterTick = Queues.newArrayDeque(); + public final List players = Lists.newArrayList(); // Paper - private -> public + public final ServerChunkCache chunkSource; // Paper - public +- boolean tickingEntities; ++ public boolean tickingEntities; // Paper - expose for watchdog + // Paper start + List afterEntityTickingTasks = Lists.newArrayList(); + public void doIfNotEntityTicking(java.lang.Runnable run) { +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 30666fca36b683158ff60302684b5093f5536e24..984ac19dcab446531c816e365c7c149e2c49d567 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -503,7 +503,7 @@ public abstract class PlayerList { + cserver.getPluginManager().callEvent(playerQuitEvent); + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + +- entityplayer.doTick(); // SPIGOT-924 ++ if (server.isSameThread()) entityplayer.doTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) + // CraftBukkit end + + // Paper start - Remove from collideRule team if needed +diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +index a5ce61be7d6e85ac289730d9671e66a7190529f9..add18ba4833686ff51fbb280b0a5759f142b3f91 100644 +--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java ++++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +@@ -135,6 +135,7 @@ public abstract class BlockableEventLoop implements Processo + try { + task.run(); + } catch (Exception exception) { ++ if (exception.getCause() instanceof ThreadDeath) throw exception; // Paper + BlockableEventLoop.LOGGER.fatal("Error executing task on {}", this.name(), exception); + } + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 632f32405053fbcff2fd26fa99f98c6add9f9dc7..5860e7866724abd35bde2a5710d9c92799e5de67 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -858,6 +858,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + gameprofilerfiller.pop(); + } catch (Throwable throwable) { ++ if (throwable instanceof ThreadDeath) throw throwable; // Paper + // Paper start - Prevent tile entity and entity crashes + String msg = "TileEntity threw exception at " + tileentity.getLevel().getWorld().getName() + ":" + tileentity.getBlockPos().getX() + "," + tileentity.getBlockPos().getY() + "," + tileentity.getBlockPos().getZ(); + System.err.println(msg); +@@ -932,6 +933,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + try { + tickConsumer.accept(entity); + } catch (Throwable throwable) { ++ if (throwable instanceof ThreadDeath) throw throwable; // Paper + // Paper start - Prevent tile entity and entity crashes + String msg = "Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ(); + System.err.println(msg); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 3f35e93b42efd03ff1002f09962fe3da51fb4c3f..43c37e660a8a7f9d326ad38e66f9aa7c53c7b87c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1839,7 +1839,7 @@ public final class CraftServer implements Server { + + @Override + public boolean isPrimaryThread() { +- return Thread.currentThread().equals(console.serverThread); // Paper - Fix issues with detecting main thread properly ++ return Thread.currentThread().equals(console.serverThread) || Thread.currentThread().equals(net.minecraft.server.MinecraftServer.getServer().shutdownThread); // Paper - Fix issues with detecting main thread properly, the only time Watchdog will be used is during a crash shutdown which is a "try our best" scenario + } + + // Paper start +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index c519ceca6f7788ca7c5d74ad1001dbc09f62681c..c288b89bf5a22269823ba1d18af217032d7c6a36 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -12,6 +12,8 @@ import java.util.logging.Level; + import java.util.logging.Logger; + import joptsimple.OptionParser; + import joptsimple.OptionSet; ++import net.minecraft.util.ExceptionCollector; ++import net.minecraft.world.level.lighting.LayerLightEventListener; + import net.minecrell.terminalconsole.TerminalConsoleAppender; // Paper + + public class Main { +@@ -156,6 +158,36 @@ public class Main { + + OptionSet options = null; + ++ // Paper start - preload logger classes to avoid plugins mixing versions ++ tryPreloadClass("com.destroystokyo.paper.log.LogFullPolicy"); ++ tryPreloadClass("org.apache.logging.log4j.core.Core"); ++ tryPreloadClass("org.apache.logging.log4j.core.Appender"); ++ tryPreloadClass("org.apache.logging.log4j.core.ContextDataInjector"); ++ tryPreloadClass("org.apache.logging.log4j.core.Filter"); ++ tryPreloadClass("org.apache.logging.log4j.core.ErrorHandler"); ++ tryPreloadClass("org.apache.logging.log4j.core.LogEvent"); ++ tryPreloadClass("org.apache.logging.log4j.core.Logger"); ++ tryPreloadClass("org.apache.logging.log4j.core.LoggerContext"); ++ tryPreloadClass("org.apache.logging.log4j.core.LogEventListener"); ++ tryPreloadClass("org.apache.logging.log4j.core.AbstractLogEvent"); ++ tryPreloadClass("org.apache.logging.log4j.message.AsynchronouslyFormattable"); ++ tryPreloadClass("org.apache.logging.log4j.message.FormattedMessage"); ++ tryPreloadClass("org.apache.logging.log4j.message.ParameterizedMessage"); ++ tryPreloadClass("org.apache.logging.log4j.message.Message"); ++ tryPreloadClass("org.apache.logging.log4j.message.MessageFactory"); ++ tryPreloadClass("org.apache.logging.log4j.message.TimestampMessage"); ++ tryPreloadClass("org.apache.logging.log4j.message.SimpleMessage"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.AsyncLogger"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.AsyncLoggerContext"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.AsyncQueueFullPolicy"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.AsyncLoggerDisruptor"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.RingBufferLogEvent"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.DisruptorUtil"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.RingBufferLogEventHandler"); ++ tryPreloadClass("org.apache.logging.log4j.core.impl.ThrowableProxy"); ++ tryPreloadClass("org.apache.logging.log4j.core.impl.ExtendedClassInfo"); ++ tryPreloadClass("org.apache.logging.log4j.core.impl.ExtendedStackTraceElement"); ++ // Paper end + try { + options = parser.parse(args); + } catch (joptsimple.OptionException ex) { +@@ -251,8 +283,64 @@ public class Main { + } catch (Throwable t) { + t.printStackTrace(); + } ++ // Paper start ++ // load some required classes to avoid errors during shutdown if jar is replaced ++ // also to guarantee our version loads over plugins ++ tryPreloadClass("com.destroystokyo.paper.util.SneakyThrow"); ++ tryPreloadClass("com.google.common.collect.Iterators$PeekingImpl"); ++ tryPreloadClass("com.google.common.collect.MapMakerInternalMap$Values"); ++ tryPreloadClass("com.google.common.collect.MapMakerInternalMap$ValueIterator"); ++ tryPreloadClass("com.google.common.collect.MapMakerInternalMap$WriteThroughEntry"); ++ tryPreloadClass("com.google.common.collect.Iterables"); ++ for (int i = 1; i <= 15; i++) { ++ tryPreloadClass("com.google.common.collect.Iterables$" + i, false); ++ } ++ tryPreloadClass("org.apache.commons.lang3.mutable.MutableBoolean"); ++ tryPreloadClass("org.apache.commons.lang3.mutable.MutableInt"); ++ tryPreloadClass("org.jline.terminal.impl.MouseSupport"); ++ tryPreloadClass("org.jline.terminal.impl.MouseSupport$1"); ++ tryPreloadClass("org.jline.terminal.Terminal$MouseTracking"); ++ tryPreloadClass("co.aikar.timings.TimingHistory"); ++ tryPreloadClass("co.aikar.timings.TimingHistory$MinuteReport"); ++ tryPreloadClass("io.netty.channel.AbstractChannelHandlerContext"); ++ tryPreloadClass("io.netty.channel.AbstractChannelHandlerContext$11"); ++ tryPreloadClass("io.netty.channel.AbstractChannelHandlerContext$12"); ++ tryPreloadClass("io.netty.channel.AbstractChannel$AbstractUnsafe$8"); ++ tryPreloadClass("io.netty.util.concurrent.DefaultPromise"); ++ tryPreloadClass("io.netty.util.concurrent.DefaultPromise$1"); ++ tryPreloadClass("io.netty.util.internal.PromiseNotificationUtil"); ++ tryPreloadClass("io.netty.util.internal.SystemPropertyUtil"); ++ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler"); ++ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler$1"); ++ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler$2"); ++ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler$3"); ++ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler$4"); ++ tryPreloadClass("org.slf4j.helpers.MessageFormatter"); ++ tryPreloadClass("org.slf4j.helpers.FormattingTuple"); ++ tryPreloadClass("org.slf4j.helpers.BasicMarker"); ++ tryPreloadClass("org.slf4j.helpers.Util"); ++ tryPreloadClass("com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent"); ++ tryPreloadClass("com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent"); ++ // Minecraft, seen during saving ++ tryPreloadClass(LayerLightEventListener.DummyLightLayerEventListener.class.getName()); ++ tryPreloadClass(LayerLightEventListener.class.getName()); ++ tryPreloadClass(ExceptionCollector.class.getName()); ++ // Paper end ++ } ++ } ++ ++ // Paper start ++ private static void tryPreloadClass(String className) { ++ tryPreloadClass(className, true); ++ } ++ private static void tryPreloadClass(String className, boolean printError) { ++ try { ++ Class.forName(className); ++ } catch (ClassNotFoundException e) { ++ if (printError) System.err.println("An expected class " + className + " was not found for preloading: " + e.getMessage()); + } + } ++ // Paper end + + private static List asList(String... params) { + return Arrays.asList(params); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +index 449e99d1b673870ed6892f6ab2c715a2db35c35d..c7ed6e0f8a989cec97700df2b15198c9c481c549 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +@@ -12,12 +12,27 @@ public class ServerShutdownThread extends Thread { + @Override + public void run() { + try { ++ // Paper start - try to shutdown on main ++ server.safeShutdown(false, false); ++ for (int i = 1000; i > 0 && !server.hasStopped(); i -= 100) { ++ Thread.sleep(100); ++ } ++ if (server.hasStopped()) { ++ while (!server.hasFullyShutdown) Thread.sleep(1000); ++ return; ++ } ++ // Looks stalled, close async + org.spigotmc.AsyncCatcher.enabled = false; // Spigot + org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper ++ server.forceTicks = true; + server.close(); ++ while (!server.hasFullyShutdown) Thread.sleep(1000); ++ } catch (InterruptedException e) { ++ e.printStackTrace(); ++ // Paper end + } finally { + try { +- net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender ++ //net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Move into stop + } catch (Exception e) { + } + } +diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java +index 6dab105cd7cc4340c031c395c0346d4731355d79..6498dc4c6630bfef1a52edf74d8574e5e4876720 100644 +--- a/src/main/java/org/spigotmc/RestartCommand.java ++++ b/src/main/java/org/spigotmc/RestartCommand.java +@@ -139,7 +139,7 @@ public class RestartCommand extends Command + // Paper end + + // Paper start - copied from above and modified to return if the hook registered +- private static boolean addShutdownHook(String restartScript) ++ public static boolean addShutdownHook(String restartScript) + { + String[] split = restartScript.split( " " ); + if ( split.length > 0 && new File( split[0] ).isFile() ) +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 33a66322d253c7562ae5acbdbc6cc87f7d72a9af..26c9adf7af4328ce2d8e08568019c5b438e28b05 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -13,6 +13,7 @@ import org.bukkit.Bukkit; + public class WatchdogThread extends Thread + { + ++ public static final boolean DISABLE_WATCHDOG = Boolean.getBoolean("disable.watchdog"); // Paper + private static WatchdogThread instance; + private long timeoutTime; + private boolean restart; +@@ -41,6 +42,7 @@ public class WatchdogThread extends Thread + { + if ( instance == null ) + { ++ if (timeoutTime <= 0) timeoutTime = 300; // Paper + instance = new WatchdogThread( timeoutTime * 1000L, restart ); + instance.start(); + } else +@@ -71,12 +73,13 @@ public class WatchdogThread extends Thread + // Paper start + Logger log = Bukkit.getServer().getLogger(); + long currentTime = monotonicMillis(); +- if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) ++ MinecraftServer server = MinecraftServer.getServer(); ++ if (lastTick != 0 && timeoutTime > 0 && hasStarted && (!server.isRunning() || (currentTime > lastTick + earlyWarningEvery && !DISABLE_WATCHDOG) )) + { +- boolean isLongTimeout = currentTime > lastTick + timeoutTime; ++ boolean isLongTimeout = currentTime > lastTick + timeoutTime || (!server.isRunning() && !server.hasStopped() && currentTime > lastTick + 1000); + // Don't spam early warning dumps + if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; +- if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... ++ if ( !isLongTimeout && server.hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... + lastEarlyWarning = currentTime; + if (isLongTimeout) { + // Paper end +@@ -118,7 +121,7 @@ public class WatchdogThread extends Thread + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper +- dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); ++ dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // + // Paper start - Only print full dump on long timeouts +@@ -139,9 +142,25 @@ public class WatchdogThread extends Thread + + if ( isLongTimeout ) + { +- if ( restart && !MinecraftServer.getServer().hasStopped() ) ++ if ( !server.hasStopped() ) + { +- RestartCommand.restart(); ++ AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us ++ AsyncCatcher.shuttingDown = true; ++ server.forceTicks = true; ++ if (restart) { ++ RestartCommand.addShutdownHook( SpigotConfig.restartScript ); ++ } ++ // try one last chance to safe shutdown on main incase it 'comes back' ++ server.abnormalExit = true; ++ server.safeShutdown(false, restart); ++ try { ++ Thread.sleep(1000); ++ } catch (InterruptedException e) { ++ e.printStackTrace(); ++ } ++ if (!server.hasStopped()) { ++ server.close(); ++ } + } + break; + } // Paper end +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 476f4a5cbe664ddd05474cb88553018bd334a5b8..8af159abd3d0cc94cf155fec5b384c42f69551bf 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -1,5 +1,5 @@ + +- ++ + + + diff --git a/Remapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch b/Remapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch new file mode 100644 index 0000000000..9f2777798e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 02:02:07 -0600 +Subject: [PATCH] Optimize Pathfinding + +Prevents pathfinding from spamming failures for things such as +arrow attacks. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index a362506f38e8d30543b6cd6d215db561290dac76..c501e42b6fef4af065807182dc5b4c444e74e310 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -11,6 +11,7 @@ import net.minecraft.core.Position; + import net.minecraft.core.Vec3i; + import net.minecraft.network.protocol.game.DebugPackets; + import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.Mob; +@@ -32,7 +33,7 @@ public abstract class PathNavigation { + protected final Mob mob; public Entity getEntity() { return mob; } // Paper - OBFHELPER + protected final Level level; + @Nullable +- protected Path path; ++ protected Path path; protected final Path getCurrentPath() { return this.path; } // Paper - OBFHELPER + protected double speedModifier; + protected int tick; + protected int lastStuckCheck; +@@ -184,10 +185,30 @@ public abstract class PathNavigation { + return this.moveTo(this.createPath(x, y, z, 1), speed); + } + ++ // Paper start - optimise pathfinding ++ private int lastFailure = 0; ++ private int pathfindFailures = 0; ++ // Paper end ++ + public boolean moveTo(Entity entity, double speed) { ++ // Paper start - Pathfinding optimizations ++ if (this.pathfindFailures > 10 && this.getCurrentPath() == null && MinecraftServer.currentTick < this.lastFailure + 40) { ++ return false; ++ } ++ // Paper end + Path pathentity = this.createPath(entity, 1); + +- return pathentity != null && this.moveTo(pathentity, speed); ++ // Paper start - Pathfinding optimizations ++ if (pathentity != null && this.moveTo(pathentity, speed)) { ++ this.lastFailure = 0; ++ this.pathfindFailures = 0; ++ return true; ++ } else { ++ this.pathfindFailures++; ++ this.lastFailure = MinecraftServer.currentTick; ++ return false; ++ } ++ // Paper end + } + + public boolean setDestination(@Nullable Path pathentity, double speed) { return moveTo(pathentity, speed); } // Paper - OBFHELPER diff --git a/Remapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch b/Remapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch new file mode 100644 index 0000000000..991b0f903b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 18:35:09 -0700 +Subject: [PATCH] Reduce Either Optional allocation + +In order to get chunk values, we shouldn't need to create +an optional each time. + +diff --git a/src/main/java/com/mojang/datafixers/util/Either.java b/src/main/java/com/mojang/datafixers/util/Either.java +index fc8dbdf43833d76d8dc5f4e92575ca2965afa93a..ab71cdb3a8c2bec036ece630a0e0f088653e928f 100644 +--- a/src/main/java/com/mojang/datafixers/util/Either.java ++++ b/src/main/java/com/mojang/datafixers/util/Either.java +@@ -22,7 +22,7 @@ public abstract class Either implements App, L> { + } + + private static final class Left extends Either { +- private final L value; ++ private final L value; private Optional valueOptional; // Paper - reduce the optional allocation... + + public Left(final L value) { + this.value = value; +@@ -51,7 +51,7 @@ public abstract class Either implements App, L> { + + @Override + public Optional left() { +- return Optional.of(value); ++ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... + } + + @Override +@@ -83,7 +83,7 @@ public abstract class Either implements App, L> { + } + + private static final class Right extends Either { +- private final R value; ++ private final R value; private Optional valueOptional; // Paper - reduce the optional allocation... + + public Right(final R value) { + this.value = value; +@@ -117,7 +117,7 @@ public abstract class Either implements App, L> { + + @Override + public Optional right() { +- return Optional.of(value); ++ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch b/Remapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch new file mode 100644 index 0000000000..935abedc0d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 18:10:43 -0700 +Subject: [PATCH] Remove streams from PairedQueue + +We shouldn't be doing stream calls just to see if the queue is +empty. This creates loads of garbage thanks to how often it's called. + +diff --git a/src/main/java/net/minecraft/util/thread/StrictQueue.java b/src/main/java/net/minecraft/util/thread/StrictQueue.java +index cdc572b0261034248960fa13b8412e874fd20db5..07938519b699a31a280f3f419b34fb7cf6cf6883 100644 +--- a/src/main/java/net/minecraft/util/thread/StrictQueue.java ++++ b/src/main/java/net/minecraft/util/thread/StrictQueue.java +@@ -20,32 +20,30 @@ public interface StrictQueue { + + public static final class FixedPriorityQueue implements StrictQueue { + +- private final List> queueList; ++ private final List> queueList; private final List> getQueues() { return this.queueList; } // Paper - OBFHELPER + + public FixedPriorityQueue(int priorityCount) { +- this.queueList = (List) IntStream.range(0, priorityCount).mapToObj((j) -> { +- return Queues.newConcurrentLinkedQueue(); +- }).collect(Collectors.toList()); ++ // Paper start - remove streams ++ this.queueList = new java.util.ArrayList<>(priorityCount); // queues ++ for (int j = 0; j < priorityCount; ++j) { ++ this.getQueues().add(Queues.newConcurrentLinkedQueue()); ++ } ++ // Paper end - remove streams + } + + @Nullable + @Override + public Runnable pop() { +- Iterator iterator = this.queueList.iterator(); +- +- Runnable runnable; +- +- do { +- if (!iterator.hasNext()) { +- return null; ++ // Paper start - remove iterator creation ++ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { ++ Queue queue = this.getQueues().get(i); ++ Runnable ret = queue.poll(); ++ if (ret != null) { ++ return ret; + } +- +- Queue queue = (Queue) iterator.next(); +- +- runnable = (Runnable) queue.poll(); +- } while (runnable == null); +- +- return runnable; ++ } ++ return null; ++ // Paper end - remove iterator creation + } + + public boolean push(StrictQueue.IntRunnable message) { +@@ -57,7 +55,16 @@ public interface StrictQueue { + + @Override + public boolean isEmpty() { +- return this.queueList.stream().allMatch(Collection::isEmpty); ++ // Paper start - remove streams ++ // why are we doing streams every time we might want to execute a task? ++ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { ++ Queue queue = this.getQueues().get(i); ++ if (!queue.isEmpty()) { ++ return false; ++ } ++ } ++ return true; ++ // Paper end - remove streams + } + } + diff --git a/Remapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch b/Remapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch new file mode 100644 index 0000000000..dcba632a31 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 17:39:25 -0700 +Subject: [PATCH] Reduce memory footprint of NBTTagCompound + +Fastutil maps are going to have a lower memory footprint - which +is important because we clone chunk data after reading it for safety. +So, reduce the impact of the clone on GC. + +diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java +index a91bf94ed9f2f353a685194fc91c4b101ccc1232..c856ca720a9329a94bb07eaa3060c034f95718b3 100644 +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -26,6 +26,7 @@ import net.minecraft.ReportedException; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.TextComponent; ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; // Paper + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +@@ -47,7 +48,7 @@ public class CompoundTag implements Tag { + if (i > 512) { + throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512"); + } else { +- HashMap hashmap = Maps.newHashMap(); ++ Object2ObjectOpenHashMap hashmap = new Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound + + byte b0; + +@@ -83,7 +84,7 @@ public class CompoundTag implements Tag { + } + + public CompoundTag() { +- this(Maps.newHashMap()); ++ this(new Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - reduce memory footprint of NBTTagCompound + } + + @Override +@@ -417,9 +418,17 @@ public class CompoundTag implements Tag { + + @Override + public CompoundTag copy() { +- Map map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy)); ++ // Paper start - reduce memory footprint of NBTTagCompound ++ Object2ObjectOpenHashMap ret = new Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f); + +- return new CompoundTag(map); ++ Iterator> iterator = (this.tags instanceof Object2ObjectOpenHashMap) ? ((Object2ObjectOpenHashMap)this.tags).object2ObjectEntrySet().fastIterator() : this.tags.entrySet().iterator(); ++ while (iterator.hasNext()) { ++ Map.Entry entry = iterator.next(); ++ ret.put(entry.getKey(), entry.getValue().copy()); ++ } ++ ++ return new CompoundTag(ret); ++ // Paper end - reduce memory footprint of NBTTagCompound + } + + public boolean equals(Object object) { diff --git a/Remapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch b/Remapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch new file mode 100644 index 0000000000..7b2a22a56b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Mon, 13 Apr 2020 07:31:44 +0100 +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 162b1a8c6ab57aafa4f6deefc842755a8e14208e..efacfcaab444270b985f3a7fe0ef97e33c18a9de 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -557,7 +557,7 @@ public class ServerPlayer extends Player implements ContainerListener { + containerUpdateDelay = level.paperConfig.containerUpdateTickRate; + } + // Paper end +- if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { ++ if (!this.level.isClientSide && this.containerMenu != this.inventoryMenu && (isImmobile() || !this.containerMenu.stillValid(this))) { // Paper - auto close while frozen + this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.containerMenu = this.inventoryMenu; + } +@@ -1404,7 +1404,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } else { + // CraftBukkit start + this.containerMenu = container; +- this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); ++ if (!isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper + // CraftBukkit end + container.addSlotListener(this); + return OptionalInt.of(this.containerCounter); +@@ -2206,7 +2206,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + + @Override +- protected boolean isImmobile() { ++ public boolean isImmobile() { // Paper - protected > public + return super.isImmobile() || (this.connection != null && this.connection.isDisconnected()); // Paper + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index a73c6ddd6bf66cc21ae5b25daacdece8cbfeeeac..ae6faa331fcbefd99ee1cd92c88926d767fc50ee 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -323,7 +323,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper + + //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment +- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper ++ if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + getHandle().containerMenu = container; + getHandle().containerMenu.addSlotListener(player); + } +@@ -397,7 +397,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper + if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper + //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment +- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper ++ if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + player.containerMenu = container; + player.containerMenu.addSlotListener(player); + } diff --git a/Remapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch b/Remapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch new file mode 100644 index 0000000000..dad03aa170 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Apr 2020 18:23:28 -0700 +Subject: [PATCH] Optimise ArraySetSorted#removeIf + +Remove iterator allocation and ensure the call is always O(n) + +diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java +index 93813a508be1e1e600a8211f9822f2087328de70..8f03847eeb95ccdb69ad181b38b8724c9c72a76b 100644 +--- a/src/main/java/net/minecraft/util/SortedArraySet.java ++++ b/src/main/java/net/minecraft/util/SortedArraySet.java +@@ -10,8 +10,8 @@ import java.util.NoSuchElementException; + public class SortedArraySet extends AbstractSet { + + private final Comparator comparator; +- private T[] contents; +- private int size; ++ private T[] contents; private final T[] getBackingArray() { return this.contents; } // Paper - OBFHELPER ++ private int size; private final int getSize() { return this.size; } private final void setSize(int value) { this.size = value; } // Paper - OBFHELPER + + private SortedArraySet(int initialCapacity, Comparator comparator) { + this.comparator = comparator; +@@ -22,6 +22,42 @@ public class SortedArraySet extends AbstractSet { + } + } + ++ // Paper start - optimise removeIf ++ @Override ++ public boolean removeIf(java.util.function.Predicate filter) { ++ // prev. impl used an iterator, which could be n^2 and creates garbage ++ int i = 0, len = this.getSize(); ++ T[] backingArray = this.getBackingArray(); ++ ++ for (;;) { ++ if (i >= len) { ++ return false; ++ } ++ if (!filter.test(backingArray[i])) { ++ ++i; ++ continue; ++ } ++ break; ++ } ++ ++ // we only want to write back to backingArray if we really need to ++ ++ int lastIndex = i; // this is where new elements are shifted to ++ ++ for (; i < len; ++i) { ++ T curr = backingArray[i]; ++ if (!filter.test(curr)) { // if test throws we're screwed ++ backingArray[lastIndex++] = curr; ++ } ++ } ++ ++ // cleanup end ++ Arrays.fill(backingArray, lastIndex, len, null); ++ this.setSize(lastIndex); ++ return true; ++ } ++ // Paper end - optimise removeIf ++ + public static > SortedArraySet create(int initialCapacity) { + return new SortedArraySet<>(initialCapacity, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix + } diff --git a/Remapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch b/Remapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch new file mode 100644 index 0000000000..474688a9b3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Apr 2020 17:56:07 -0700 +Subject: [PATCH] Don't run entity collision code if not needed + +Will not run if max entity craming is disabled and +the max collisions per entity is less than or equal to 0 + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 43fbe7d220f61802ae0cb0620ad078c5df7b69bc..46b962183e2e27ed93054ad9fb6d8ecbf70bc5f9 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -2941,10 +2941,16 @@ public abstract class LivingEntity extends Entity { + protected void serverAiStep() {} + + protected void pushEntities() { ++ // Paper - start don't run getEntities if we're not going to use its result ++ int i = this.level.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); ++ if (i <= 0 && level.paperConfig.maxCollisionsPerEntity <= 0) { ++ return; ++ } ++ // Paper - end don't run getEntities if we're not going to use its result + List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); + + if (!list.isEmpty()) { +- int i = this.level.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); ++ // Paper - move up + int j; + + if (i > 0 && list.size() > i - 1 && this.random.nextInt(4) == 0) { diff --git a/Remapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch b/Remapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch new file mode 100644 index 0000000000..e6f6255656 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Thu, 16 Apr 2020 16:13:59 -0700 +Subject: [PATCH] Optimize ChunkProviderServer's chunk level checking helper + methods + +These can be hot functions (i.e entity ticking and block ticking), +so inline where possible, and avoid the abstraction of the +Either class. + +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 3744cce8611ac01b1b6c76cd3c4890795c1f06a2..531fe1259a1d60ff69321c3fefbf97f7141e6475 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -24,7 +24,6 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.progress.ChunkProgressListener; +-import net.minecraft.util.Mth; + import net.minecraft.util.profiling.ProfilerFiller; + import net.minecraft.util.thread.BlockableEventLoop; + import net.minecraft.world.entity.Entity; +@@ -644,21 +643,29 @@ public class ServerChunkCache extends ChunkSource { + + public final boolean isInEntityTickingChunk(Entity entity) { return this.isEntityTickingChunk(entity); } // Paper - OBFHELPER + @Override public boolean isEntityTickingChunk(Entity entity) { +- long i = ChunkPos.asLong(Mth.floor(entity.getX()) >> 4, Mth.floor(entity.getZ()) >> 4); +- +- return this.checkChunkFuture(i, (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error ++ // Paper start - optimize is ticking ready type functions ++ // entity ticking ++ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(MCUtil.getCoordinateKey(entity)); ++ return playerChunk != null && playerChunk.isEntityTickingReady(); ++ // Paper end - optimize is ticking ready type functions + } + + public final boolean isEntityTickingChunk(ChunkPos chunkcoordintpair) { return this.isEntityTickingChunk(chunkcoordintpair); } // Paper - OBFHELPER + @Override public boolean isEntityTickingChunk(ChunkPos pos) { +- return this.checkChunkFuture(pos.toLong(), (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error ++ // Paper start - optimize is ticking ready type functions ++ // is entity ticking ready ++ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(MCUtil.getCoordinateKey(pos)); ++ return playerChunk != null && playerChunk.isEntityTickingReady(); ++ // Paper end - optimize is ticking ready type functions + } + + @Override + public boolean isTickingChunk(BlockPos pos) { +- long i = ChunkPos.asLong(pos.getX() >> 4, pos.getZ() >> 4); +- +- return this.checkChunkFuture(i, (Function>>) ChunkHolder::getTickingChunkFuture); // CraftBukkit - decompile error ++ // Paper start - optimize is ticking ready type functions ++ // is ticking ready ++ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(MCUtil.getCoordinateKey(pos)); ++ return playerChunk != null && playerChunk.isTickingReady(); ++ // Paper end - optimize is ticking ready type functions + } + + private boolean checkChunkFuture(long pos, Function>> futureFunction) { diff --git a/Remapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch b/Remapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch new file mode 100644 index 0000000000..bc23f71417 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 16 Apr 2020 20:07:29 -0500 +Subject: [PATCH] Restrict vanilla teleport command to valid locations + +Fixes GH-3165, GH-3575 + +diff --git a/src/main/java/net/minecraft/server/commands/TeleportCommand.java b/src/main/java/net/minecraft/server/commands/TeleportCommand.java +index 774180d9e450199309fee65b1d10e1592f84548a..d04ce9a323b079b4556b8c341fb11186e8d3e05d 100644 +--- a/src/main/java/net/minecraft/server/commands/TeleportCommand.java ++++ b/src/main/java/net/minecraft/server/commands/TeleportCommand.java +@@ -141,6 +141,12 @@ public class TeleportCommand { + + private static void performTeleport(CommandSourceStack source, Entity target, ServerLevel world, double x, double y, double z, Set movementFlags, float yaw, float pitch, @Nullable TeleportCommand.LookAt facingLocation) throws CommandSyntaxException { + BlockPos blockposition = new BlockPos(x, y, z); ++ // Paper start - Don't allow teleport command to invalid locations ++ if (x <= -30000000 || z <= -30000000 || x > 30000000 || z > 30000000 || y > 30000000 || y <= -30000000) { // Copy/pasta from BaseBlockPosition#isValidLocation ++ org.bukkit.Bukkit.getLogger().warning("Refused to teleport " + target.getScoreboardName() + " to " + x + ", " + y + ", " + z); ++ return; ++ } ++ // Paper end + + if (!Level.isInSpawnableBounds(blockposition)) { + throw TeleportCommand.INVALID_POSITION.create(); diff --git a/Remapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch b/Remapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch new file mode 100644 index 0000000000..dcdbea5496 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch @@ -0,0 +1,188 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Mon, 20 Jan 2020 21:38:15 +0100 +Subject: [PATCH] Implement Player Client Options API + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperSkinParts.java b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabba57885e1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java +@@ -0,0 +1,74 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Objects; ++ ++import java.util.StringJoiner; ++ ++public class PaperSkinParts implements SkinParts { ++ ++ private final int raw; ++ ++ public PaperSkinParts(int raw) { ++ this.raw = raw; ++ } ++ ++ public boolean hasCapeEnabled() { ++ return (raw & 1) == 1; ++ } ++ ++ public boolean hasJacketEnabled() { ++ return (raw >> 1 & 1) == 1; ++ } ++ ++ public boolean hasLeftSleeveEnabled() { ++ return (raw >> 2 & 1) == 1; ++ } ++ ++ public boolean hasRightSleeveEnabled() { ++ return (raw >> 3 & 1) == 1; ++ } ++ ++ public boolean hasLeftPantsEnabled() { ++ return (raw >> 4 & 1) == 1; ++ } ++ ++ public boolean hasRightPantsEnabled() { ++ return (raw >> 5 & 1) == 1; ++ } ++ ++ public boolean hasHatsEnabled() { ++ return (raw >> 6 & 1) == 1; ++ } ++ ++ @Override ++ public int getRaw() { ++ return raw; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ PaperSkinParts that = (PaperSkinParts) o; ++ return raw == that.raw; ++ } ++ ++ @Override ++ public int hashCode() { ++ return Objects.hashCode(raw); ++ } ++ ++ @Override ++ public String toString() { ++ return new StringJoiner(", ", PaperSkinParts.class.getSimpleName() + "[", "]") ++ .add("raw=" + raw) ++ .add("cape=" + hasCapeEnabled()) ++ .add("jacket=" + hasJacketEnabled()) ++ .add("leftSleeve=" + hasLeftSleeveEnabled()) ++ .add("rightSleeve=" + hasRightSleeveEnabled()) ++ .add("leftPants=" + hasLeftPantsEnabled()) ++ .add("rightPants=" + hasRightPantsEnabled()) ++ .add("hats=" + hasHatsEnabled()) ++ .toString(); ++ } ++} +diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java +index 1f486cfd77b49568540398b1b3fa6127b17ba6aa..4b43740f9ff4feab4f1cd2f8e91d55be3cf8eb50 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java +@@ -41,14 +41,17 @@ public class ServerboundClientInformationPacket implements Packet POSES = ImmutableMap.builder().put(Pose.STANDING, Player.STANDING_DIMENSIONS).put(Pose.SLEEPING, Player.SLEEPING_DIMENSIONS).put(Pose.FALL_FLYING, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.SWIMMING, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.SPIN_ATTACK, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.CROUCHING, EntityDimensions.scalable(0.6F, 1.5F)).put(Pose.DYING, EntityDimensions.fixed(0.2F, 0.2F)).build(); + private static final EntityDataAccessor DATA_PLAYER_ABSORPTION_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.FLOAT); + private static final EntityDataAccessor DATA_SCORE_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.INT); +- protected static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); ++ protected static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); public static EntityDataAccessor getSkinPartsWatcher() { return DATA_PLAYER_MODE_CUSTOMISATION; } // Paper - OBFHELPER + protected static final EntityDataAccessor DATA_PLAYER_MAIN_HAND = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); + protected static final EntityDataAccessor DATA_SHOULDER_LEFT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); + protected static final EntityDataAccessor DATA_SHOULDER_RIGHT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 20de8e358789d05bb5ac15e4cdd7dda85b61b7f8..eb366396820c9b6731469df4198e0884a431a77c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1,5 +1,8 @@ + package org.bukkit.craftbukkit.entity; + ++import com.destroystokyo.paper.ClientOption.ChatVisibility; ++import com.destroystokyo.paper.PaperSkinParts; ++import com.destroystokyo.paper.ClientOption; + import com.destroystokyo.paper.Title; + import com.google.common.base.Preconditions; + import com.google.common.collect.ImmutableSet; +@@ -2250,6 +2253,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public void setViewDistance(int viewDistance) { + throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO + } ++ ++ @Override ++ public T getClientOption(ClientOption type) { ++ if(ClientOption.SKIN_PARTS.equals(type)) { ++ return type.getType().cast(new PaperSkinParts(getHandle().getEntityData().get(net.minecraft.world.entity.player.Player.getSkinPartsWatcher()))); ++ } else if(ClientOption.CHAT_COLORS_ENABLED.equals(type)) { ++ return type.getType().cast(getHandle().hasChatColorsEnabled()); ++ } else if(ClientOption.CHAT_VISIBILITY.equals(type)) { ++ return type.getType().cast(getHandle().getChatVisibility() == null ? ChatVisibility.UNKNOWN : ChatVisibility.valueOf(getHandle().getChatVisibility().name())); ++ } else if(ClientOption.LOCALE.equals(type)) { ++ return type.getType().cast(getLocale()); ++ } else if(ClientOption.MAIN_HAND.equals(type)) { ++ return type.getType().cast(getMainHand()); ++ } else if(ClientOption.VIEW_DISTANCE.equals(type)) { ++ return type.getType().cast(getClientViewDistance()); ++ } ++ throw new RuntimeException("Unknown settings type"); ++ } + // Paper end + + // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch b/Remapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch new file mode 100644 index 0000000000..1d32694a1d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 18 Apr 2020 04:36:11 -0400 +Subject: [PATCH] Fix Chunk Post Processing deadlock risk + +See: https://gist.github.com/aikar/dd22bbd2a3d78a2fd3d92e95e9f28dc6 + +as part of post processing a chunk, we can call ChunkConverter. + +ChunkConverter then kicks off major physics updates, and when blocks +that have connections across chunk boundries occur, a recursive risk +can occur where A updates a block that triggers a physics request. + +That physics request may trigger a chunk request, that then enqueues +a task into the Mailbox ChunkTaskQueueSorter. + +If anything requests that same chunk that is in the middle of conversion, +it's mailbox queue is going to be held up, so the subsequent chunk request +will be unable to proceed. + +We delay post processing of Chunk.A() 1 "pass" by re stuffing it back into +the executor so that the mailbox ChunkQueue is now considered empty. + +This successfully fixed a reoccurring and highly reproduceable crash +for heightmaps. + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 49728aab7512ea8486d277d34e80d3c6a4727aac..dbe60f5d24fb39be52c3cb8f933371b1626951df 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -181,6 +181,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }; + // CraftBukkit end + ++ final CallbackExecutor chunkLoadConversionCallbackExecutor = new CallbackExecutor(); // Paper ++ + // Paper start - distance maps + private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); + +@@ -1054,7 +1056,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return Either.left(chunk); + }); + }, (runnable) -> { +- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); ++ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, () -> ChunkMap.this.chunkLoadConversionCallbackExecutor.execute(runnable))); // Paper - delay running Chunk post processing until outside of the sorter to prevent a deadlock scenario when post processing causes another chunk request. + }); + + completablefuture1.thenAcceptAsync((either) -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 531fe1259a1d60ff69321c3fefbf97f7141e6475..b45fe750c8ca838e1beebff4077e5819eec2836c 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -1021,6 +1021,7 @@ public class ServerChunkCache extends ChunkSource { + return super.pollTask() || execChunkTask; // Paper + } + } finally { ++ chunkMap.chunkLoadConversionCallbackExecutor.run(); // Paper - Add chunk load conversion callback executor to prevent deadlock due to recursion in the chunk task queue sorter + chunkMap.callbackExecutor.run(); + } + // CraftBukkit end diff --git a/Remapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/Remapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch new file mode 100644 index 0000000000..1469edc105 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 18 Apr 2020 15:59:41 -0400 +Subject: [PATCH] Don't crash if player is attempted to be removed from + untracked chunk. + +I suspect it deals with teleporting as it uses players current x/y/z + +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 71a51cc99e26579e765f88340588e23956888929..90429d3f5c5b725098cfb001d54c70608f3df7bb 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -245,8 +245,8 @@ public abstract class DistanceManager { + ObjectSet objectset = (ObjectSet) this.playersPerChunk.get(i); + if (objectset == null) return; // CraftBukkit - SPIGOT-6208 + +- objectset.remove(player); +- if (objectset.isEmpty()) { ++ if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully. ++ if (objectset == null || objectset.isEmpty()) { // Paper + this.playersPerChunk.remove(i); + this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); + this.playerTicketManager.update(i, Integer.MAX_VALUE, false); diff --git a/Remapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch b/Remapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch new file mode 100644 index 0000000000..de365413d4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AvrooVulcan +Date: Fri, 17 Apr 2020 00:15:23 +0100 +Subject: [PATCH] Broadcast join message to console + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 984ac19dcab446531c816e365c7c149e2c49d567..e043722436492140162940770c22be47690fb47f 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -284,7 +284,9 @@ public abstract class PlayerList { + + if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure + joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure +- server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure ++ // Paper start - Removed sendAll for loop and broadcasted to console also ++ server.getPlayerList().sendMessage(joinMessage); // Paper - Adventure ++ // Paper end + } + // CraftBukkit end + diff --git a/Remapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/Remapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch new file mode 100644 index 0000000000..e4ac02eb91 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch @@ -0,0 +1,149 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 19 Apr 2020 00:05:46 -0400 +Subject: [PATCH] Fix Longstanding Broken behavior of PlayerJoinEvent + +For years, plugin developers have had to delay many things they do +inside of the PlayerJoinEvent by 1 tick to make it actually work. + +This all boiled down to 1 reason why: The event fired before the +player was fully ready and joined to the world! + +Additionally, if that player logged out on a vehicle, the event +fired before the vehicle was even loaded, so that plugins had no +access to the vehicle during this event either. + +This change finally fixes this issue, fully preparing the player +into the world as a fully ready entity, vehicle included. + +There should be no plugins that break because of this change, but might +improve consistency with other plugins instead. + +For example, if 2 plugins listens to this event, and the first one +teleported the player in the event, then the 2nd plugin actually +would be getting a valid player! + +This was very non deterministic. This change will ensure every plugin +receives a deterministic result, and should no longer require 1 tick +delays anymore. + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index dbe60f5d24fb39be52c3cb8f933371b1626951df..b3ca4300b280a24f3ed2acaffdd6ae2cdffd140d 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1584,7 +1584,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }); + } + +- protected void addEntity(Entity entity) { ++ public void addEntity(Entity entity) { // Paper - protected -> public + org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot + // Paper start - ignore and warn about illegal addEntity calls instead of crashing server + if (!entity.valid || entity.level != this.level || this.entityMap.containsKey(entity.getId())) { +@@ -1593,6 +1593,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + .printStackTrace(); + return; + } ++ if (entity instanceof ServerPlayer && ((ServerPlayer) entity).supressTrackerForLogin) return; // Delay adding to tracker until after list packets + // Paper end + if (!(entity instanceof EnderDragonPart)) { + EntityType entitytypes = entity.getType(); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index aa979d17c264840ebd528708df3d6118e69fec68..75a095e0c2177dc1b46b080597ff8f12f1480acc 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -237,6 +237,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public double maxHealthCache; + public boolean joining = true; + public boolean sentListPacket = false; ++ public boolean supressTrackerForLogin = false; // Paper + public Integer clientViewDistance; + // CraftBukkit end + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index e043722436492140162940770c22be47690fb47f..454d60566743e02e7e55868c7bb45e30583dfa8f 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -272,6 +272,12 @@ public abstract class PlayerList { + this.playersByUUID.put(player.getUUID(), player); + // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below + ++ // Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks ++ player.supressTrackerForLogin = true; ++ worldserver1.addNewPlayer(player); ++ this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below worldserver.addPlayerJoin(entityplayer); ++ mountSavedVehicle(player, worldserver1, nbttagcompound); ++ // Paper end + // CraftBukkit start + PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + cserver.getPluginManager().callEvent(playerJoinEvent); +@@ -307,6 +313,8 @@ public abstract class PlayerList { + player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); + } + player.sentListPacket = true; ++ player.supressTrackerForLogin = false; // Paper ++ ((ServerLevel)player.level).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now + // CraftBukkit end + + player.connection.send(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn +@@ -332,6 +340,11 @@ public abstract class PlayerList { + playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect)); + } + ++ // Paper start - move vehicle into method so it can be called above - short circuit around that code ++ onPlayerJoinFinish(player, worldserver1, s1); ++ } ++ private void mountSavedVehicle(ServerPlayer entityplayer, ServerLevel worldserver1, CompoundTag nbttagcompound) { ++ // Paper end + if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) { + CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); + // CraftBukkit start +@@ -354,20 +367,20 @@ public abstract class PlayerList { + Entity entity1; + + if (entity.getUUID().equals(uuid)) { +- player.startRiding(entity, true); ++ entityplayer.startRiding(entity, true); + } else { + iterator1 = entity.getIndirectPassengers().iterator(); + + while (iterator1.hasNext()) { + entity1 = (Entity) iterator1.next(); + if (entity1.getUUID().equals(uuid)) { +- player.startRiding(entity1, true); ++ entityplayer.startRiding(entity1, true); + break; + } + } + } + +- if (!player.isPassenger()) { ++ if (!entityplayer.isPassenger()) { + PlayerList.LOGGER.warn("Couldn't reattach entity to player"); + worldserver1.despawn(entity); + iterator1 = entity.getIndirectPassengers().iterator(); +@@ -380,16 +393,20 @@ public abstract class PlayerList { + } + } + +- player.initMenu(); ++ // Paper start ++ } ++ public void onPlayerJoinFinish(ServerPlayer entityplayer, ServerLevel worldserver1, String s1) { ++ // Paper end ++ entityplayer.initMenu(); + // Paper start - Add to collideRule team if needed + final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); + final PlayerTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName); +- if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) { +- scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); ++ if (this.collideRuleTeamName != null && collideRuleTeam != null && entityplayer.getTeam() == null) { ++ scoreboard.addPlayerToTeam(entityplayer.getScoreboardName(), collideRuleTeam); + } + // Paper end + // CraftBukkit - Moved from above, added world +- PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.worldDataServer.getLevelName(), player.getX(), player.getY(), player.getZ()); ++ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getName().getString(), s1, entityplayer.getId(), worldserver1.worldDataServer.getLevelName(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()); + } + + public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) { diff --git a/Remapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch b/Remapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch new file mode 100644 index 0000000000..f02494b2a2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch @@ -0,0 +1,416 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 19 Apr 2020 04:28:29 -0400 +Subject: [PATCH] Load Chunks for Login Asynchronously + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index b3ca4300b280a24f3ed2acaffdd6ae2cdffd140d..97a582614ad28f9fa864ae9be4860658e5979214 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -145,7 +145,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private final ProcessorHandle> worldgenMailbox; + private final ProcessorHandle> mainThreadMailbox; + public final ChunkProgressListener progressListener; +- public final ChunkMap.ChunkDistanceManager distanceManager; ++ public final ChunkMap.ChunkDistanceManager distanceManager; public final DistanceManager getChunkDistanceManager() { return this.distanceManager; } // Paper - OBFHELPER + private final AtomicInteger tickingGenerated; + public final StructureManager structureManager; // Paper - private -> public + private final File storageFolder; +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index b45fe750c8ca838e1beebff4077e5819eec2836c..79fb63c40dd0543a6f629e78f390f23f34992ba1 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -629,7 +629,7 @@ public class ServerChunkCache extends ChunkSource { + return this.mainThreadProcessor.pollTask(); + } + +- private boolean runDistanceManagerUpdates() { ++ public boolean runDistanceManagerUpdates() { // Paper - private -> public + boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); + boolean flag1 = this.chunkMap.promoteChunkMap(); + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 75a095e0c2177dc1b46b080597ff8f12f1480acc..24c508ade61a6ad90b0ef73cdc995f531ef18263 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -32,6 +32,7 @@ import net.minecraft.core.Vec3i; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; + import net.minecraft.nbt.Tag; ++import net.minecraft.network.Connection; + import net.minecraft.network.chat.ChatType; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.HoverEvent; +@@ -172,6 +173,7 @@ public class ServerPlayer extends Player implements ContainerListener { + + private static final Logger LOGGER = LogManager.getLogger(); + public ServerGamePacketListenerImpl connection; ++ public Connection networkManager; // Paper + public final MinecraftServer server; + public final ServerPlayerGameMode gameMode; + public final Deque removeQueue = new ArrayDeque<>(); // Paper +@@ -238,6 +240,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public boolean joining = true; + public boolean sentListPacket = false; + public boolean supressTrackerForLogin = false; // Paper ++ public boolean didPlayerJoinEvent = false; // Paper + public Integer clientViewDistance; + // CraftBukkit end + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index d09e4857b6c40410d134fa81b48e95919a7373bd..583587457790df826a8a3239a4bd1d0f1dcab1da 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -21,6 +21,7 @@ public class TicketType { + public static final TicketType FORCED = create("forced", Comparator.comparingLong(ChunkPos::toLong)); + public static final TicketType LIGHT = create("light", Comparator.comparingLong(ChunkPos::toLong)); + public static final TicketType PORTAL = create("portal", Vec3i::compareTo, 300); ++ public static final TicketType LOGIN = create("login", Long::compareTo, 100); // Paper + public static final TicketType POST_TELEPORT = create("post_teleport", Integer::compareTo, 5); + public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); + public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 09a663cc53cdf8ae45352b280200c8170dbbcdfc..1bed6e69bf3cc1ab9b0c1259de4f643bf58371aa 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -220,6 +220,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private static final Logger LOGGER = LogManager.getLogger(); + public final Connection connection; + private final MinecraftServer server; ++ public Runnable playerJoinReady; // Paper + public ServerPlayer player; + private int tickCount; + private long keepAliveTime = Util.getMillis(); private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER +@@ -298,6 +299,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit end + + public void tick() { ++ // Paper start - login async ++ Runnable playerJoinReady = this.playerJoinReady; ++ if (playerJoinReady != null) { ++ this.playerJoinReady = null; ++ playerJoinReady.run(); ++ } ++ // Don't tick if not valid (dead), otherwise we load chunks below ++ if (this.player.valid) { ++ // Paper end + this.resetPosition(); + this.player.xo = this.player.getX(); + this.player.yo = this.player.getY(); +@@ -339,7 +349,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.lastVehicle = null; + this.clientVehicleIsFloating = false; + this.aboveGroundVehicleTickCount = 0; +- } ++ }} // Paper - end if (valid) + + this.server.getProfiler().push("keepAlive"); + // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 9631fa93b821c7f6bc6dc707c2c82cce2ae8291e..e229c7735ba88be3d8721440104958408a2a075e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -86,7 +86,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + // Paper end + } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { +- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); ++ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper + + if (entityplayer == null) { + this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT; +@@ -186,7 +186,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + + this.connection.send(new ClientboundGameProfilePacket(this.gameProfile)); +- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); ++ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper + + if (entityplayer != null) { + this.state = ServerLoginPacketListenerImpl.State.DELAY_ACCEPT; +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 454d60566743e02e7e55868c7bb45e30583dfa8f..ffc8c9ee8b1768dd809189858ee45658fb9bf1c5 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -36,6 +36,7 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; + import net.minecraft.network.protocol.game.ClientboundChatPacket; + import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; ++import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; + import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; + import net.minecraft.network.protocol.game.ClientboundGameEventPacket; + import net.minecraft.network.protocol.game.ClientboundLoginPacket; +@@ -59,6 +60,8 @@ import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.PlayerAdvancements; + import net.minecraft.server.ServerScoreboard; ++import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.level.ServerPlayerGameMode; +@@ -124,11 +127,12 @@ public abstract class PlayerList { + private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); + private final MinecraftServer server; + public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety +- private final Map playersByUUID = Maps.newHashMap(); ++ private final Map playersByUUID = Maps.newHashMap();Map getUUIDMap() { return playersByUUID; } // Paper - OBFHELPER + private final UserBanList bans; + private final IpBanList ipBans; + private final ServerOpList ops; + private final UserWhiteList whitelist; ++ private final Map pendingPlayers = Maps.newHashMap(); // Paper + // CraftBukkit start + // private final Map o; + // private final Map p; +@@ -167,6 +171,11 @@ public abstract class PlayerList { + } + + public void placeNewPlayer(Connection connection, ServerPlayer player) { ++ ServerPlayer prev = pendingPlayers.put(player.getUUID(), player);// Paper ++ if (prev != null) { ++ disconnectPendingPlayer(prev); ++ } ++ player.networkManager = connection; // Paper + player.loginTime = System.currentTimeMillis(); // Paper + GameProfile gameprofile = player.getGameProfile(); + GameProfileCache usercache = this.server.getProfileCache(); +@@ -180,7 +189,7 @@ public abstract class PlayerList { + if (nbttagcompound != null && nbttagcompound.contains("bukkit")) { + CompoundTag bukkit = nbttagcompound.getCompound("bukkit"); + s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; +- } ++ }String lastKnownName = s; // Paper + // CraftBukkit end + + if (nbttagcompound != null) { +@@ -255,34 +264,79 @@ public abstract class PlayerList { + player.getRecipeBook().sendInitialRecipeBook(player); + this.updateEntireScoreboard(worldserver1.getScoreboard(), player); + this.server.invalidateStatus(); ++ // Paper start - async load spawn in chunk ++ ServerLevel finalWorldserver = worldserver1; ++ int chunkX = loc.getBlockX() >> 4; ++ int chunkZ = loc.getBlockZ() >> 4; ++ final ChunkPos pos = new ChunkPos(chunkX, chunkZ); ++ ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; ++ playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.toLong()); ++ worldserver1.getChunkSource().runDistanceManagerUpdates(); ++ worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { ++ ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); ++ if (updatingChunk != null) { ++ return updatingChunk.getEntityTickingFuture(); ++ } else { ++ return java.util.concurrent.CompletableFuture.completedFuture(chunk); ++ } ++ }).thenAccept(chunk -> { ++ playerconnection.playerJoinReady = () -> { ++ postChunkLoadJoin( ++ player, finalWorldserver, connection, playerconnection, ++ nbttagcompound, connection.getRemoteAddress().toString(), lastKnownName ++ ); ++ }; ++ }); ++ } ++ ++ public ServerPlayer getActivePlayer(UUID uuid) { ++ ServerPlayer player = this.getUUIDMap().get(uuid); ++ return player != null ? player : pendingPlayers.get(uuid); ++ } ++ ++ void disconnectPendingPlayer(ServerPlayer entityplayer) { ++ TranslatableComponent msg = new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0]); ++ entityplayer.networkManager.send(new ClientboundDisconnectPacket(msg), (future) -> { ++ entityplayer.networkManager.disconnect(msg); ++ entityplayer.networkManager = null; ++ }); ++ } ++ ++ private void postChunkLoadJoin(ServerPlayer entityplayer, ServerLevel worldserver1, Connection networkmanager, ServerGamePacketListenerImpl playerconnection, CompoundTag nbttagcompound, String s1, String s) { ++ pendingPlayers.remove(entityplayer.getUUID(), entityplayer); ++ if (!networkmanager.isConnected()) { ++ return; ++ } ++ entityplayer.didPlayerJoinEvent = true; ++ // Paper end + TranslatableComponent chatmessage; + +- if (player.getGameProfile().getName().equalsIgnoreCase(s)) { +- chatmessage = new TranslatableComponent("multiplayer.player.joined", new Object[]{player.getDisplayName()}); ++ if (entityplayer.getGameProfile().getName().equalsIgnoreCase(s)) { ++ chatmessage = new TranslatableComponent("multiplayer.player.joined", new Object[]{entityplayer.getDisplayName()}); + } else { +- chatmessage = new TranslatableComponent("multiplayer.player.joined.renamed", new Object[]{player.getDisplayName(), s}); ++ chatmessage = new TranslatableComponent("multiplayer.player.joined.renamed", new Object[]{entityplayer.getDisplayName(), s}); + } + // CraftBukkit start + chatmessage.withStyle(ChatFormatting.YELLOW); + Component joinMessage = chatmessage; // Paper - Adventure + +- playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.yRot, player.xRot); +- this.players.add(player); +- this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot +- this.playersByUUID.put(player.getUUID(), player); ++ playerconnection.teleport(entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), entityplayer.yRot, entityplayer.xRot); ++ this.players.add(entityplayer); ++ this.playersByName.put(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT), entityplayer); // Spigot ++ this.playersByUUID.put(entityplayer.getUUID(), entityplayer); + // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below + + // Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks +- player.supressTrackerForLogin = true; +- worldserver1.addNewPlayer(player); +- this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below worldserver.addPlayerJoin(entityplayer); +- mountSavedVehicle(player, worldserver1, nbttagcompound); ++ entityplayer.supressTrackerForLogin = true; ++ worldserver1.addNewPlayer(entityplayer); ++ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); // see commented out section below worldserver.addPlayerJoin(entityplayer); ++ mountSavedVehicle(entityplayer, worldserver1, nbttagcompound); + // Paper end + // CraftBukkit start +- PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure ++ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + cserver.getPluginManager().callEvent(playerJoinEvent); + +- if (!player.connection.connection.isConnected()) { ++ if (!entityplayer.connection.connection.isConnected()) { + return; + } + +@@ -297,51 +351,51 @@ public abstract class PlayerList { + // CraftBukkit end + + // CraftBukkit start - sendAll above replaced with this loop +- ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, player); ++ ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, entityplayer); + + for (int i = 0; i < this.players.size(); ++i) { + ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i); + +- if (entityplayer1.getBukkitEntity().canSee(player.getBukkitEntity())) { ++ if (entityplayer1.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { + entityplayer1.connection.send(packet); + } + +- if (!player.getBukkitEntity().canSee(entityplayer1.getBukkitEntity())) { ++ if (!entityplayer.getBukkitEntity().canSee(entityplayer1.getBukkitEntity())) { + continue; + } + +- player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); ++ entityplayer.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); + } +- player.sentListPacket = true; +- player.supressTrackerForLogin = false; // Paper +- ((ServerLevel)player.level).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now ++ entityplayer.sentListPacket = true; ++ entityplayer.supressTrackerForLogin = false; // Paper ++ ((ServerLevel)entityplayer.level).getChunkSource().chunkMap.addEntity(entityplayer); // Paper - track entity now + // CraftBukkit end + +- player.connection.send(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn ++ entityplayer.connection.send(new ClientboundSetEntityDataPacket(entityplayer.getId(), entityplayer.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn + + // CraftBukkit start - Only add if the player wasn't moved in the event +- if (player.level == worldserver1 && !worldserver1.players().contains(player)) { +- worldserver1.addNewPlayer(player); +- this.server.getCustomBossEvents().onPlayerConnect(player); ++ if (entityplayer.level == worldserver1 && !worldserver1.players().contains(entityplayer)) { ++ worldserver1.addNewPlayer(entityplayer); ++ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); + } + +- worldserver1 = player.getLevel(); // CraftBukkit - Update in case join event changed it ++ worldserver1 = entityplayer.getLevel(); // CraftBukkit - Update in case join event changed it + // CraftBukkit end +- this.sendLevelInfo(player, worldserver1); ++ this.sendLevelInfo(entityplayer, worldserver1); + if (!this.server.getResourcePack().isEmpty()) { +- player.sendTexturePack(this.server.getResourcePack(), this.server.getResourcePackHash()); ++ entityplayer.sendTexturePack(this.server.getResourcePack(), this.server.getResourcePackHash()); + } + +- Iterator iterator = player.getActiveEffects().iterator(); ++ Iterator iterator = entityplayer.getActiveEffects().iterator(); + + while (iterator.hasNext()) { + MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect)); ++ playerconnection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobeffect)); + } + + // Paper start - move vehicle into method so it can be called above - short circuit around that code +- onPlayerJoinFinish(player, worldserver1, s1); ++ onPlayerJoinFinish(entityplayer, worldserver1, s1); + } + private void mountSavedVehicle(ServerPlayer entityplayer, ServerLevel worldserver1, CompoundTag nbttagcompound) { + // Paper end +@@ -492,6 +546,7 @@ public abstract class PlayerList { + + protected void save(ServerPlayer player) { + if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit ++ if (!player.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) + this.playerIo.save(player); + ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit + +@@ -519,7 +574,7 @@ public abstract class PlayerList { + } + + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); +- cserver.getPluginManager().callEvent(playerQuitEvent); ++ if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + + if (server.isSameThread()) entityplayer.doTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) +@@ -572,6 +627,13 @@ public abstract class PlayerList { + // this.p.remove(uuid); + // CraftBukkit end + } ++ // Paper start ++ entityplayer1 = pendingPlayers.get(uuid); ++ if (entityplayer1 == entityplayer) { ++ pendingPlayers.remove(uuid); ++ } ++ entityplayer.networkManager = null; ++ // Paper end + + // CraftBukkit start + // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[]{entityplayer})); +@@ -589,7 +651,7 @@ public abstract class PlayerList { + cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); + // CraftBukkit end + +- return playerQuitEvent.quitMessage(); // Paper - Adventure ++ return entityplayer.didPlayerJoinEvent ? playerQuitEvent.quitMessage() : null; // CraftBukkit // Paper - Adventure // Paper - don't print quit if we never printed join + } + + // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer +@@ -608,6 +670,13 @@ public abstract class PlayerList { + list.add(entityplayer); + } + } ++ // Paper start - check pending players too ++ entityplayer = pendingPlayers.get(uuid); ++ if (entityplayer != null) { ++ this.pendingPlayers.remove(uuid); ++ disconnectPendingPlayer(entityplayer); ++ } ++ // Paper end + + Iterator iterator = list.iterator(); + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index b8dcc91a191f25ca578e0858abf6c1b874fee15d..9f0371282f5829d26dc9618c3d466bccaa4cd3af 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1371,7 +1371,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.yo = y; + this.zo = d4; + this.setPos(d3, y, d4); +- level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit ++ if (valid) level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit // Paper + } + + public void moveTo(Vec3 vec3d) { diff --git a/Remapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/Remapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch new file mode 100644 index 0000000000..eeaa3a49f4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2277 <38501234+2277@users.noreply.github.com> +Date: Tue, 31 Mar 2020 10:33:55 +0100 +Subject: [PATCH] Move player to spawn point if spawn in unloaded world + +The code following this has better support for null worlds to move +them back to the world spawn. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 9f0371282f5829d26dc9618c3d466bccaa4cd3af..34226102c50a4353c42e68917d41c44d251e602f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1808,9 +1808,11 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + bworld = server.getWorld(worldName); + } + +- if (bworld == null) { +- bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getLevel(Level.OVERWORLD).getWorld(); +- } ++ // Paper start - Move player to spawn point if spawn in unloaded world ++// if (bworld == null) { ++// bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld(); ++// } ++ // Paper end - Move player to spawn point if spawn in unloaded world + + setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle()); + } diff --git a/Remapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch b/Remapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch new file mode 100644 index 0000000000..f1eab97e33 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: nossr50 +Date: Thu, 26 Mar 2020 19:44:50 -0700 +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 46b962183e2e27ed93054ad9fb6d8ecbf70bc5f9..cec1e6105b8c2ac3d1482c00482d53d6be0d38d1 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1928,7 +1928,16 @@ public abstract class LivingEntity extends Entity { + + 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 ++ 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()) { ++ player.resetAttackStrengthTicker(); ++ } ++ } else { ++ ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); ++ } ++ // Paper end + } + if (event.isCancelled()) { + return false; diff --git a/Remapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/Remapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch new file mode 100644 index 0000000000..025b5a9d8e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 21 Apr 2020 03:51:53 -0400 +Subject: [PATCH] Allow multiple callbacks to schedule for Callback Executor + +ChunkMapDistance polls multiple entries for pendingChunkUpdates + +Each of these have the potential to move a chunk in and out of +"Loaded" state, which will result in multiple callbacks being +needed within a single tick of ChunkMapDistance + +Use an ArrayDeque to store this Queue + +We make sure to also implement a pattern that is recursion safe too. + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 97a582614ad28f9fa864ae9be4860658e5979214..6c7af93cead523830d32b007cc69b313e59abef1 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -160,24 +160,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final CallbackExecutor callbackExecutor = new CallbackExecutor(); + public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { + +- private Runnable queued; ++ // Paper start - replace impl with recursive safe multi entry queue ++ // it's possible to schedule multiple tasks currently, so it's vital we change this impl ++ // If we recurse into the executor again, we will append to another queue, ensuring task order consistency ++ private java.util.ArrayDeque queued = new java.util.ArrayDeque<>(); + + @Override + public void execute(Runnable runnable) { +- if (queued != null) { +- throw new IllegalStateException("Already queued"); ++ if (queued == null) { ++ queued = new java.util.ArrayDeque<>(); + } +- queued = runnable; ++ queued.add(runnable); + } + + @Override + public void run() { +- Runnable task = queued; ++ if (queued == null) { ++ return; ++ } ++ java.util.ArrayDeque queue = queued; + queued = null; +- if (task != null) { ++ Runnable task; ++ while ((task = queue.pollFirst()) != null) { + task.run(); + } + } ++ // Paper end + }; + // CraftBukkit end + diff --git a/Remapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch b/Remapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch new file mode 100644 index 0000000000..8997a0897d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 23 Apr 2020 01:36:39 -0400 +Subject: [PATCH] Don't fire BlockFade on worldgen threads + +Caused a deadlock + +diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java +index 31b6c1333c7d0af28385e804e94348cef398748b..ac63c5bef5b35b158e57835d765bbdd15fc60664 100644 +--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java +@@ -93,6 +93,7 @@ public class FireBlock extends BaseFireBlock { + @Override + public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { + // CraftBukkit start ++ if (!(world instanceof ServerLevel)) return this.canSurvive(state, world, pos) ? (BlockState) this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)) : Blocks.AIR.defaultBlockState(); // Paper - don't fire events in world generation + if (!this.canSurvive(state, world, pos)) { + // Suppress during worldgen + if (!(world instanceof Level)) { +@@ -108,7 +109,7 @@ public class FireBlock extends BaseFireBlock { + return blockState.getHandle(); + } + } +- return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)); ++ return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)); // Paper - diff on change, see "don't fire events in world generation" + // CraftBukkit end + } + diff --git a/Remapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch b/Remapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch new file mode 100644 index 0000000000..9a052de409 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 25 Apr 2020 15:13:41 -0500 +Subject: [PATCH] Add phantom creative and insomniac controls + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index cd248eb6be663e8be33f2c3c6b06b77b6d5753a4..46ac6d91422423f1e03b86d3efa3241f2599000d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -625,4 +625,11 @@ public class PaperWorldConfig { + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); + } ++ ++ public boolean phantomIgnoreCreative = true; ++ public boolean phantomOnlyAttackInsomniacs = true; ++ private void phantomSettings() { ++ phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); ++ phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index e7facd849e3511c64b4ae44b34382f4a4985f2a4..8ce62148ebaeac9988e7c9d4b2f7ee57f58d883e 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -3,6 +3,9 @@ package net.minecraft.world.entity; + import com.google.common.base.Predicates; + import java.util.function.Predicate; + import javax.annotation.Nullable; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.stats.Stats; ++import net.minecraft.util.Mth; + import net.minecraft.world.Container; + import net.minecraft.world.Difficulty; + import net.minecraft.world.entity.player.Player; +@@ -31,10 +34,11 @@ public final class EntitySelector { + public static final Predicate NO_SPECTATORS = (entity) -> { + return !entity.isSpectator(); + }; ++ public static Predicate isInsomniac = (player) -> Mth.clamp(((ServerPlayer) player).getStats().getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper + + // Paper start + public static final Predicate affectsSpawning = (entity) -> { +- return !entity.isSpectator() && entity.isAlive() && (entity instanceof EntityPlayer) && ((EntityPlayer) entity).affectsSpawning; ++ return !entity.isSpectator() && entity.isAlive() && (entity instanceof ServerPlayer) && ((ServerPlayer) entity).affectsSpawning; + }; + // Paper end + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index e37137a2890330b92e05d6f76c46ffc99a527803..a40c23e824652cff59633b7c314e27ec9a515c07 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -262,6 +262,7 @@ public class Phantom extends FlyingMob implements Enemy { + Player entityhuman = (Player) iterator.next(); + + if (Phantom.this.canAttack((LivingEntity) entityhuman, TargetingConditions.DEFAULT)) { ++ if (!level.paperConfig.phantomOnlyAttackInsomniacs || EntitySelector.isInsomniac.test(entityhuman)) // Paper + Phantom.this.setGoalTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason + return true; + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +index 42effcbd3ca7c38a4e8b1aa835543ad243112a33..79504dc3448402e73b09c4232b1fd0488872cf68 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +@@ -53,7 +53,7 @@ public class PhantomSpawner implements CustomSpawner { + while (iterator.hasNext()) { + Player entityhuman = (Player) iterator.next(); + +- if (!entityhuman.isSpectator()) { ++ if (!entityhuman.isSpectator() && (!world.paperConfig.phantomIgnoreCreative || !entityhuman.isCreative())) { // Paper + BlockPos blockposition = entityhuman.blockPosition(); + + if (!world.dimensionType().hasSkyLight() || blockposition.getY() >= world.getSeaLevel() && world.canSeeSky(blockposition)) { diff --git a/Remapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/Remapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch new file mode 100644 index 0000000000..9e378d1d32 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 25 Apr 2020 06:46:35 -0400 +Subject: [PATCH] Fix numerous item duplication issues and teleport issues + +This notably fixes the newest "Donkey Dupe", but also fixes a lot +of dupe bugs in general around nether portals and entity world transfer + +We also fix item duplication generically by anytime we clone an item +to drop it on the ground, destroy the source item. + +This avoid an itemstack ever existing twice in the world state pre +clean up stage. + +So even if something NEW comes up, it would be impossible to drop the +same item twice because the source was destroyed. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 34226102c50a4353c42e68917d41c44d251e602f..2b48c4a2b512c42bed2c767db90a28898c74286a 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1973,11 +1973,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } else { + // CraftBukkit start - Capture drops for death event + if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) { +- ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(stack)); ++ ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack)); // Paper - mirror so we can destroy it later + return null; + } + // CraftBukkit end +- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY() + (double) yOffset, this.getZ(), stack); ++ ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY() + (double) yOffset, this.getZ(), stack.copy()); // Paper - clone so we can destroy original ++ stack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe + + entityitem.setDefaultPickUpDelay(); + // CraftBukkit start +@@ -2625,6 +2626,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + @Nullable + public Entity teleportTo(ServerLevel worldserver, BlockPos location) { + // CraftBukkit end ++ // Paper start - fix bad state entities causing dupes ++ if (!isAlive() || !valid) { ++ LOGGER.warn("Illegal Entity Teleport " + this + " to " + worldserver + ":" + location, new Throwable()); ++ return null; ++ } ++ // Paper end + if (this.level instanceof ServerLevel && !this.removed) { + this.level.getProfiler().push("changeDimension"); + // CraftBukkit start +@@ -2645,6 +2652,11 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + // CraftBukkit end + + this.level.getProfiler().popPush("reloading"); ++ // Paper start - Change lead drop timing to prevent dupe ++ if (this instanceof Mob) { ++ ((Mob) this).dropLeash(true, true); // Paper drop lead ++ } ++ // Paper end + Entity entity = this.getType().create((Level) worldserver); + + if (entity != null) { +@@ -2658,10 +2670,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + // CraftBukkit start - Forward the CraftEntity to the new entity + this.getBukkitEntity().setHandle(entity); + entity.bukkitEntity = this.getBukkitEntity(); +- +- if (this instanceof Mob) { +- ((Mob) this).dropLeash(true, false); // Unleash to prevent duping of leads. +- } + // CraftBukkit end + } + +@@ -2786,7 +2794,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean canChangeDimensions() { +- return true; ++ return isAlive() && valid; // Paper + } + + 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/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 33d51852ed6fe3f5adcdecf8f405a23689f4265a..5714aa450ac09788bcf1c2790d4f1581c9a7c28b 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -598,7 +598,7 @@ public class ArmorStand extends LivingEntity { + for (i = 0; i < this.handItems.size(); ++i) { + itemstack = (ItemStack) this.handItems.get(i); + if (!itemstack.isEmpty()) { +- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe + this.handItems.set(i, ItemStack.EMPTY); + } + } +@@ -606,7 +606,7 @@ public class ArmorStand extends LivingEntity { + for (i = 0; i < this.armorItems.size(); ++i) { + itemstack = (ItemStack) this.armorItems.get(i); + if (!itemstack.isEmpty()) { +- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe + this.armorItems.set(i, ItemStack.EMPTY); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 7d9a3b65b2d6b294d3a11414289e64fac88665f0..87fe7f4f5ed70bf1b3dc1e2a392ba42a1f8f568b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -815,7 +815,8 @@ public class CraftEventFactory { + for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { + if (stack == null || stack.getType() == Material.AIR || stack.getAmount() == 0) continue; + +- world.dropItem(entity.getLocation(), stack); ++ world.dropItem(entity.getLocation(), stack); // Paper - note: dropItem already clones due to this being bukkit -> NMS ++ if (stack instanceof CraftItemStack) stack.setAmount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe, but don't nuke bukkit stacks of manually added items + } + + return event; diff --git a/Remapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch b/Remapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch new file mode 100644 index 0000000000..5504aee900 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch @@ -0,0 +1,139 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 19 Apr 2020 18:15:29 -0400 +Subject: [PATCH] Implement Brigadier Mojang API + +Adds AsyncPlayerSendCommandsEvent + - Allows modifying on a per command basis what command data they see. + +Adds CommandRegisteredEvent + - Allows manipulating the CommandNode to add more children/metadata for the client + +diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java +index f74765f31bc7272724ee7fac0cc5a8c852550006..e1f4ffaa36bfffb7741c74b7a094e26a03a9a1e6 100644 +--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java ++++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java +@@ -37,7 +37,7 @@ import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + import com.mojang.brigadier.tree.CommandNode; // CraftBukkit + +-public class CommandSourceStack implements SharedSuggestionProvider { ++public class CommandSourceStack implements SharedSuggestionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource { // Paper + + public static final SimpleCommandExceptionType ERROR_NOT_PLAYER = new SimpleCommandExceptionType(new TranslatableComponent("permissions.requires.player")); + public static final SimpleCommandExceptionType ERROR_NOT_ENTITY = new SimpleCommandExceptionType(new TranslatableComponent("permissions.requires.entity")); +@@ -149,6 +149,25 @@ public class CommandSourceStack implements SharedSuggestionProvider { + return this.textName; + } + ++ // Paper start ++ @Override ++ public org.bukkit.entity.Entity getBukkitEntity() { ++ return getEntity() != null ? getEntity().getBukkitEntity() : null; ++ } ++ ++ @Override ++ public org.bukkit.World getBukkitWorld() { ++ return getLevel() != null ? getLevel().getWorld() : null; ++ } ++ ++ @Override ++ public org.bukkit.Location getBukkitLocation() { ++ Vec3 pos = getPosition(); ++ org.bukkit.World world = getBukkitWorld(); ++ return world != null && pos != null ? new org.bukkit.Location(world, pos.x, pos.y, pos.z) : null; ++ } ++ // Paper end ++ + @Override + public boolean hasPermission(int level) { + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index 8154d9327c5411bbfea3bfa4d99d57feab764664..c63033e3eb50423a7c32acfc0e705623cc4bec68 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -355,6 +355,7 @@ public class Commands { + bukkit.add(node.getName()); + } + // Paper start - Async command map building ++ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper + MinecraftServer.getServer().execute(() -> { + runSync(entityplayer, bukkit, rootcommandnode); + }); +@@ -362,6 +363,7 @@ public class Commands { + + private void runSync(ServerPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { + // Paper end - Async command map building ++ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper + PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); + event.getPlayer().getServer().getPluginManager().callEvent(event); + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 1bed6e69bf3cc1ab9b0c1259de4f643bf58371aa..5f12987b93f1578624626c4e911d1757dee3d45f 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -768,8 +768,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); + + this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { +- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer +- this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); ++ // Paper start ++ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); ++ suggestEvent.setCancelled(suggestions.isEmpty()); ++ if (!suggestEvent.callEvent()) return; ++ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), (com.mojang.brigadier.suggestion.Suggestions) suggestEvent.getSuggestions())); // CraftBukkit - decompile error // Paper ++ // Paper end + }); + }); + } +@@ -778,7 +782,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); + completions.forEach(builder::suggest); +- player.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), builder.buildFuture().join())); ++ com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); ++ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); ++ suggestEvent.setCancelled(suggestions.isEmpty()); ++ if (!suggestEvent.callEvent()) return; ++ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestEvent.getSuggestions())); + } + // Paper end - async tab completion + } +diff --git a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java +index f9a245503c8982d1756503a6179f3715d919d910..b17002abdb43e74da4eb61e65e45c5e0e1dc0f95 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java +@@ -17,7 +17,7 @@ import net.minecraft.commands.CommandSourceStack; + import org.bukkit.command.Command; + import org.bukkit.craftbukkit.CraftServer; + +-public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider { ++public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommand { // Paper + + private final CraftServer server; + private final Command command; +@@ -28,10 +28,19 @@ public class BukkitCommandWrapper implements com.mojang.brigadier.Command register(CommandDispatcher dispatcher, String label) { +- return dispatcher.register( +- LiteralArgumentBuilder.literal(label).requires(this).executes(this) +- .then(RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this)) +- ); ++ // Paper start - Expose Brigadier to Paper-MojangAPI ++ com.mojang.brigadier.tree.RootCommandNode root = dispatcher.getRoot(); ++ LiteralCommandNode literal = LiteralArgumentBuilder.literal(label).requires(this).executes(this).build(); ++ com.mojang.brigadier.tree.ArgumentCommandNode defaultArgs = RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this).build(); ++ literal.addChild(defaultArgs); ++ com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent event = new com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent<>(label, this, this.command, root, literal, defaultArgs); ++ if (!event.callEvent()) { ++ return null; ++ } ++ literal = event.getLiteral(); ++ root.addChild(literal); ++ return literal; ++ // Paper end + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch b/Remapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch new file mode 100644 index 0000000000..49b6ff50fa --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: zbk +Date: Sun, 26 Apr 2020 23:49:01 -0400 +Subject: [PATCH] Villager Restocks API + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 4aa34320ef7d6c62ccb17734bfa61d406190b919..a83a7d37f3d769535161fda46fca6f71dcc4d515 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -112,7 +112,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + private long lastGossipDecayTime; + private int villagerXp; + private long lastRestockGameTime; +- private int numberOfRestocksToday; ++ private int numberOfRestocksToday; public int getRestocksToday(){ return this.numberOfRestocksToday; } public void setRestocksToday(int restocksToday){ this.numberOfRestocksToday = restocksToday; } // Paper OBFHELPER + private long lastRestockCheckDayTime; + private boolean assignProfessionWhenSpawned; + private static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.MOBS, MemoryModuleType.VISIBLE_MOBS, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.WALK_TARGET, new MemoryModuleType[]{MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +index 5a21e9447c3e0225b07144eec83c277dd101bfd5..d0b933cfd02b237bfe85011831dab6e8e966496e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +@@ -83,6 +83,18 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { + getHandle().setVillagerXp(experience); + } + ++ // Paper start ++ @Override ++ public int getRestocksToday() { ++ return getHandle().getRestocksToday(); ++ } ++ ++ @Override ++ public void setRestocksToday(int restocksToday) { ++ getHandle().setRestocksToday(restocksToday); ++ } ++ // Paper end ++ + @Override + public boolean sleep(Location location) { + Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/Remapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch b/Remapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch new file mode 100644 index 0000000000..34909e54c5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 2 May 2020 03:09:46 -0400 +Subject: [PATCH] Validate PickItem Packet and kick for invalid + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 5f12987b93f1578624626c4e911d1757dee3d45f..3f416479e23c60ec5b4b779cce9ab62c74865ac8 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -881,7 +881,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + @Override + public void handlePickItem(ServerboundPickItemPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); +- this.player.inventory.pickSlot(packet.getSlot()); ++ // Paper start - validate pick item position ++ if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.inventory.items.size())) { ++ ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); ++ this.disconnect("Invalid hotbar selection (Hacking?)"); ++ return; ++ } ++ this.player.inventory.pickSlot(packet.getSlot()); // Paper - Diff above if changed ++ // Paper end + this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, this.player.inventory.selected, this.player.inventory.getItem(this.player.inventory.selected))); + this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, packet.getSlot(), this.player.inventory.getItem(packet.getSlot()))); + this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.inventory.selected)); diff --git a/Remapped-Spigot-Server-Patches/0461-Expose-game-version.patch b/Remapped-Spigot-Server-Patches/0461-Expose-game-version.patch new file mode 100644 index 0000000000..9e0cf63bd9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0461-Expose-game-version.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Fri, 1 May 2020 17:39:26 +0300 +Subject: [PATCH] Expose game version + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 43c37e660a8a7f9d326ad38e66f9aa7c53c7b87c..1bfe96443877e460d22513d59ebc3b5988e8eb43 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -514,6 +514,13 @@ public final class CraftServer implements Server { + return bukkitVersion; + } + ++ // Paper start - expose game version ++ @Override ++ public String getMinecraftVersion() { ++ return console.getServerVersion(); ++ } ++ // Paper end ++ + @Override + public List getOnlinePlayers() { + return this.playerView; diff --git a/Remapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch b/Remapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch new file mode 100644 index 0000000000..935b12df1e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch @@ -0,0 +1,175 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 May 2020 22:35:09 -0400 +Subject: [PATCH] Optimize Voxel Shape Merging + +This method shows up as super hot in profiler, and also a high "self" time. + +Upon analyzing, it appears most usages of this method fall down to the final +else statement of the nasty ternary. + +Upon even further analyzation, it appears then the majority of those have a +consistent list 1.... One with Infinity head and Tails. + +First optimization is to detect these infinite states and immediately return that +VoxelShapeMergerList so we can avoid testing the rest for most cases. + +Break the method into 2 to help the JVM promote inlining of this fast path. + +Then it was also noticed that VoxelShapeMergerList constructor is also a hotspot +with a high self time... + +Well, knowing that in most cases our list 1 is actualy the same value, it allows +us to know that with an infinite list1, the result on the merger is essentially +list2 as the final values. + +This let us analyze the 2 potential states (Infinite with 2 sources or 4 sources) +and compute a deterministic result for the MergerList values. + +Additionally, this lets us avoid even allocating new objects for this too, further +reducing memory usage. + +diff --git a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java +index f0e74daa5bb9e88c028225e7c71deb04c481a7ac..abbe05b07831423eccf8779e854251dec5fbc2ae 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java +@@ -6,10 +6,16 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; + + public final class IndirectMerger implements IndexMerger { + +- private final DoubleArrayList result; ++ private final DoubleList a; // Paper + private final IntArrayList firstIndices; + private final IntArrayList secondIndices; + ++ // Paper start ++ private static final IntArrayList INFINITE_B_1 = new IntArrayList(new int[]{1, 1}); ++ private static final IntArrayList INFINITE_B_0 = new IntArrayList(new int[]{0, 0}); ++ private static final IntArrayList INFINITE_C = new IntArrayList(new int[]{0, 1}); ++ // Paper end ++ + protected IndirectMerger(DoubleList first, DoubleList second, boolean includeFirstOnly, boolean includeSecondOnly) { + int i = 0; + int j = 0; +@@ -18,7 +24,23 @@ public final class IndirectMerger implements IndexMerger { + int l = second.size(); + int i1 = k + l; + +- this.result = new DoubleArrayList(i1); ++ // Paper start - optimize common path of infinity doublelist ++ int size = first.size(); ++ double tail = first.getDouble(size - 1); ++ double head = first.getDouble(0); ++ if (head == Double.NEGATIVE_INFINITY && tail == Double.POSITIVE_INFINITY && !includeFirstOnly && !includeSecondOnly && (size == 2 || size == 4)) { ++ this.a = second; ++ if (size == 2) { ++ this.firstIndices = INFINITE_B_0; ++ } else { ++ this.firstIndices = INFINITE_B_1; ++ } ++ this.secondIndices = INFINITE_C; ++ return; ++ } ++ // Paper end ++ ++ this.a = new DoubleArrayList(i1); + this.firstIndices = new IntArrayList(i1); + this.secondIndices = new IntArrayList(i1); + +@@ -27,8 +49,8 @@ public final class IndirectMerger implements IndexMerger { + boolean flag3 = j < l; + + if (!flag2 && !flag3) { +- if (this.result.isEmpty()) { +- this.result.add(Math.min(first.getDouble(k - 1), second.getDouble(l - 1))); ++ if (this.a.isEmpty()) { ++ this.a.add(Math.min(first.getDouble(k - 1), second.getDouble(l - 1))); + } + + return; +@@ -41,9 +63,9 @@ public final class IndirectMerger implements IndexMerger { + if (!(d0 >= d1 - 1.0E-7D)) { // Paper - decompile error - welcome to hell + this.firstIndices.add(i - 1); + this.secondIndices.add(j - 1); +- this.result.add(d1); ++ this.a.add(d1); + d0 = d1; +- } else if (!this.result.isEmpty()) { ++ } else if (!this.a.isEmpty()) { + this.firstIndices.set(this.firstIndices.size() - 1, i - 1); + this.secondIndices.set(this.secondIndices.size() - 1, j - 1); + } +@@ -53,7 +75,7 @@ public final class IndirectMerger implements IndexMerger { + + @Override + public boolean forMergedIndexes(IndexMerger.IndexConsumer predicate) { +- for (int i = 0; i < this.result.size() - 1; ++i) { ++ for (int i = 0; i < this.a.size() - 1; ++i) { + if (!predicate.merge(this.firstIndices.getInt(i), this.secondIndices.getInt(i), i)) { + return false; + } +@@ -64,6 +86,6 @@ public final class IndirectMerger implements IndexMerger { + + @Override + public DoubleList getList() { +- return this.result; ++ return this.a; + } + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index c14d5ebe16a693834ed218af8f737714065b2e17..1603eb3f7d90a4b3a028b20776566db77d09c123 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -329,19 +329,46 @@ public final class Shapes { + } + + @VisibleForTesting +- protected static IndexMerger createIndexMerger(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { +- int j = first.size() - 1; +- int k = second.size() - 1; ++ private static IndexMerger createIndexMerger(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { // Paper - private ++ // Paper start - fast track the most common scenario ++ // doublelist is usually a DoubleArrayList with Infinite head/tails that falls to the final else clause ++ // This is actually the most common path, so jump to it straight away ++ if (first.getDouble(0) == Double.NEGATIVE_INFINITY && first.getDouble(first.size() - 1) == Double.POSITIVE_INFINITY) { ++ return new IndirectMerger(first, second, includeFirst, includeSecond); ++ } ++ // Split out rest to hopefully inline the above ++ return lessCommonMerge(size, first, second, includeFirst, includeSecond); ++ } ++ ++ private static IndexMerger lessCommonMerge(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { ++ int j = doublelist.size() - 1; ++ int k = doublelist1.size() - 1; ++ // Paper note - Rewrite below as optimized order if instead of nasty ternary + +- if (first instanceof CubePointRange && second instanceof CubePointRange) { ++ if (doublelist instanceof CubePointRange && doublelist1 instanceof CubePointRange) { + long l = lcm(j, k); + +- if ((long) size * l <= 256L) { ++ if ((long) i * l <= 256L) { + return new DiscreteCubeMerger(j, k); + } + } + +- return (IndexMerger) (first.getDouble(j) < second.getDouble(0) - 1.0E-7D ? new NonOverlappingMerger(first, second, false) : (second.getDouble(k) < first.getDouble(0) - 1.0E-7D ? new NonOverlappingMerger(second, first, true) : (j == k && Objects.equals(first, second) ? (first instanceof IdenticalMerger ? (IndexMerger) first : (second instanceof IdenticalMerger ? (IndexMerger) second : new IdenticalMerger(first))) : new IndirectMerger(first, second, includeFirst, includeSecond)))); ++ // Identical happens more often than Disjoint ++ if (j == k && Objects.equals(doublelist, doublelist1)) { ++ if (doublelist instanceof IdenticalMerger) { ++ return (IndexMerger) doublelist; ++ } else if (doublelist1 instanceof IdenticalMerger) { ++ return (IndexMerger) doublelist1; ++ } ++ return new IdenticalMerger(doublelist); ++ } else if (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-07) { ++ return new NonOverlappingMerger(doublelist, doublelist1, false); ++ } else if (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-07) { ++ return new NonOverlappingMerger(doublelist1, doublelist, true); ++ } else { ++ return new IndirectMerger(doublelist, doublelist1, flag, flag1); ++ } ++ // Paper end + } + + public interface DoubleLineConsumer { diff --git a/Remapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/Remapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch new file mode 100644 index 0000000000..d35e663567 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 4 May 2020 01:08:56 -0400 +Subject: [PATCH] Set cap on JDK per-thread native byte buffer cache + +See: https://www.evanjones.ca/java-bytebuffer-leak.html + +This is potentially a source of lots of native memory usage. + +We are clearly seeing native usage upwards to 1-4GB which doesn't make sense. + +Region File usage fixed in previous patch should of tecnically only been somewhat +temporary until GC finally gets it some time later, but between all the various +plugins doing IO on various threads, this hidden detail of the JDK could be +keeping long lived large direct buffers in cache. + +Set system properly at server startup if not set already to help protect from this. + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index c288b89bf5a22269823ba1d18af217032d7c6a36..bd10345cb90f98b8af1519afd603a5244f3a5ca2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -28,6 +28,7 @@ public class Main { + } + // Paper end + // Todo: Installation script ++ if (System.getProperty("jdk.nio.maxCachedBufferSize") == null) System.setProperty("jdk.nio.maxCachedBufferSize", "262144"); // Paper - cap per-thread NIO cache size + OptionParser parser = new OptionParser() { + { + acceptsAll(asList("?", "help"), "Show the help"); diff --git a/Remapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch b/Remapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch new file mode 100644 index 0000000000..0aaed21f24 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch @@ -0,0 +1,1104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Fri, 3 Jan 2020 16:26:19 +0100 +Subject: [PATCH] Implement Mob Goal API + + +diff --git a/pom.xml b/pom.xml +index 4c8a057e790c96b0ab5123549d0566371acacb46..1a9204c869dd36e80932b1366352db15ebd70723 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -176,6 +176,13 @@ + 1.3 + test + ++ ++ ++ io.github.classgraph ++ classgraph ++ 4.8.47 ++ test ++ + + + +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6ddb198f86ccf3bc2471752d5fb2f59d9a7ab4df +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java +@@ -0,0 +1,462 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import GoalKey; ++import GoalType; ++import com.destroystokyo.paper.entity.RangedEntity; ++import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; ++import com.google.common.collect.BiMap; ++import com.google.common.collect.HashBiMap; ++import java.lang.reflect.Constructor; ++import java.util.EnumSet; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.Map; ++import java.util.Set; ++import net.minecraft.world.entity.AgableMob; ++import net.minecraft.world.entity.FlyingMob; ++import net.minecraft.world.entity.PathfinderMob; ++import net.minecraft.world.entity.TamableAnimal; ++import net.minecraft.world.entity.ai.goal.Goal; ++import net.minecraft.world.entity.ambient.AmbientCreature; ++import net.minecraft.world.entity.animal.AbstractFish; ++import net.minecraft.world.entity.animal.AbstractGolem; ++import net.minecraft.world.entity.animal.AbstractSchoolingFish; ++import net.minecraft.world.entity.animal.Animal; ++import net.minecraft.world.entity.animal.Pufferfish; ++import net.minecraft.world.entity.animal.ShoulderRidingEntity; ++import net.minecraft.world.entity.animal.SnowGolem; ++import net.minecraft.world.entity.animal.WaterAnimal; ++import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; ++import net.minecraft.world.entity.boss.wither.WitherBoss; ++import net.minecraft.world.entity.monster.AbstractIllager; ++import net.minecraft.world.entity.monster.AbstractSkeleton; ++import net.minecraft.world.entity.monster.EnderMan; ++import net.minecraft.world.entity.monster.PatrollingMonster; ++import net.minecraft.world.entity.monster.RangedAttackMob; ++import net.minecraft.world.entity.monster.SpellcasterIllager; ++import net.minecraft.world.entity.monster.ZombifiedPiglin; ++import net.minecraft.world.entity.monster.piglin.AbstractPiglin; ++import org.bukkit.NamespacedKey; ++import org.bukkit.entity.AbstractHorse; ++import org.bukkit.entity.AbstractVillager; ++import org.bukkit.entity.Ageable; ++import org.bukkit.entity.Ambient; ++import org.bukkit.entity.Animals; ++import org.bukkit.entity.Bat; ++import org.bukkit.entity.Bee; ++import org.bukkit.entity.Blaze; ++import org.bukkit.entity.Cat; ++import org.bukkit.entity.CaveSpider; ++import org.bukkit.entity.ChestedHorse; ++import org.bukkit.entity.Chicken; ++import org.bukkit.entity.Cod; ++import org.bukkit.entity.Cow; ++import org.bukkit.entity.Creature; ++import org.bukkit.entity.Creeper; ++import org.bukkit.entity.Dolphin; ++import org.bukkit.entity.Donkey; ++import org.bukkit.entity.Drowned; ++import org.bukkit.entity.ElderGuardian; ++import org.bukkit.entity.EnderDragon; ++import org.bukkit.entity.Enderman; ++import org.bukkit.entity.Endermite; ++import org.bukkit.entity.Evoker; ++import org.bukkit.entity.Fish; ++import org.bukkit.entity.Flying; ++import org.bukkit.entity.Fox; ++import org.bukkit.entity.Ghast; ++import org.bukkit.entity.Giant; ++import org.bukkit.entity.Golem; ++import org.bukkit.entity.Guardian; ++import org.bukkit.entity.Hoglin; ++import org.bukkit.entity.Horse; ++import org.bukkit.entity.Husk; ++import org.bukkit.entity.Illager; ++import org.bukkit.entity.Illusioner; ++import org.bukkit.entity.IronGolem; ++import org.bukkit.entity.Llama; ++import org.bukkit.entity.MagmaCube; ++import org.bukkit.entity.Mob; ++import org.bukkit.entity.Monster; ++import org.bukkit.entity.Mule; ++import org.bukkit.entity.MushroomCow; ++import org.bukkit.entity.Ocelot; ++import org.bukkit.entity.Panda; ++import org.bukkit.entity.Parrot; ++import org.bukkit.entity.Phantom; ++import org.bukkit.entity.Pig; ++import org.bukkit.entity.PigZombie; ++import org.bukkit.entity.Piglin; ++import org.bukkit.entity.PiglinAbstract; ++import org.bukkit.entity.PiglinBrute; ++import org.bukkit.entity.Pillager; ++import org.bukkit.entity.PolarBear; ++import org.bukkit.entity.PufferFish; ++import org.bukkit.entity.Rabbit; ++import org.bukkit.entity.Raider; ++import org.bukkit.entity.Ravager; ++import org.bukkit.entity.Salmon; ++import org.bukkit.entity.Sheep; ++import org.bukkit.entity.Shulker; ++import org.bukkit.entity.Silverfish; ++import org.bukkit.entity.Skeleton; ++import org.bukkit.entity.SkeletonHorse; ++import org.bukkit.entity.Slime; ++import org.bukkit.entity.Snowman; ++import org.bukkit.entity.Spellcaster; ++import org.bukkit.entity.Spider; ++import org.bukkit.entity.Squid; ++import org.bukkit.entity.Stray; ++import org.bukkit.entity.Strider; ++import org.bukkit.entity.Tameable; ++import org.bukkit.entity.TraderLlama; ++import org.bukkit.entity.TropicalFish; ++import org.bukkit.entity.Turtle; ++import org.bukkit.entity.Vex; ++import org.bukkit.entity.Villager; ++import org.bukkit.entity.Vindicator; ++import org.bukkit.entity.WanderingTrader; ++import org.bukkit.entity.WaterMob; ++import org.bukkit.entity.Witch; ++import org.bukkit.entity.Wither; ++import org.bukkit.entity.WitherSkeleton; ++import org.bukkit.entity.Wolf; ++import org.bukkit.entity.Zoglin; ++import org.bukkit.entity.Zombie; ++import org.bukkit.entity.ZombieHorse; ++import org.bukkit.entity.ZombieVillager; ++ ++public class MobGoalHelper { ++ ++ private static final BiMap deobfuscationMap = HashBiMap.create(); ++ private static final Map, Class> entityClassCache = new HashMap<>(); ++ private static final Map, Class> bukkitMap = new HashMap<>(); ++ ++ static final Set ignored = new HashSet<>(); ++ ++ static { ++ // TODO these kinda should be checked on each release, in case obfuscation changes ++ deobfuscationMap.put("bee_b", "bee_attack"); ++ deobfuscationMap.put("bee_c", "bee_become_angry"); ++ deobfuscationMap.put("bee_d", "bee_enter_hive"); ++ deobfuscationMap.put("bee_e", "bee_go_to_hive"); ++ deobfuscationMap.put("bee_f", "bee_go_to_known_flower"); ++ deobfuscationMap.put("bee_g", "bee_grow_crop"); ++ deobfuscationMap.put("bee_h", "bee_hurt_by_other"); ++ deobfuscationMap.put("bee_i", "bee_locate_hive"); ++ deobfuscationMap.put("bee_k", "bee_pollinate"); ++ deobfuscationMap.put("bee_l", "bee_wander"); ++ deobfuscationMap.put("cat_a", "cat_avoid_entity"); ++ deobfuscationMap.put("cat_b", "cat_relax_on_owner"); ++ deobfuscationMap.put("dolphin_b", "dolphin_swim_to_treasure"); ++ deobfuscationMap.put("dolphin_c", "dolphin_swim_with_player"); ++ deobfuscationMap.put("dolphin_d", "dolphin_play_with_items"); ++ deobfuscationMap.put("drowned_a", "drowned_attack"); ++ deobfuscationMap.put("drowned_b", "drowned_goto_beach"); ++ deobfuscationMap.put("drowned_c", "drowned_goto_water"); ++ deobfuscationMap.put("drowned_e", "drowned_swim_up"); ++ deobfuscationMap.put("drowned_f", "drowned_trident_attack"); ++ deobfuscationMap.put("enderman_a", "enderman_freeze_when_looked_at"); ++ deobfuscationMap.put("evoker_a", "evoker_attack_spell"); ++ deobfuscationMap.put("evoker_b", "evoker_cast_spell"); ++ deobfuscationMap.put("evoker_c", "evoker_summon_spell"); ++ deobfuscationMap.put("evoker_d", "evoker_wololo_spell"); ++ deobfuscationMap.put("fish_b", "fish_swim"); ++ deobfuscationMap.put("fox_a", "fox_defend_trusted"); ++ deobfuscationMap.put("fox_b", "fox_faceplant"); ++ deobfuscationMap.put("fox_e", "fox_breed"); ++ deobfuscationMap.put("fox_f", "fox_eat_berries"); ++ deobfuscationMap.put("fox_g", "fox_float"); ++ deobfuscationMap.put("fox_h", "fox_follow_parent"); ++ deobfuscationMap.put("fox_j", "fox_look_at_player"); ++ deobfuscationMap.put("fox_l", "fox_melee_attack"); ++ deobfuscationMap.put("fox_n", "fox_panic"); ++ deobfuscationMap.put("fox_o", "fox_pounce"); ++ deobfuscationMap.put("fox_p", "fox_search_for_items"); ++ deobfuscationMap.put("fox_q", "fox_stroll_through_village"); ++ deobfuscationMap.put("fox_r", "fox_perch_and_search"); ++ deobfuscationMap.put("fox_s", "fox_seek_shelter"); ++ deobfuscationMap.put("fox_t", "fox_sleep"); ++ deobfuscationMap.put("fox_u", "fox_stalk_prey"); ++ deobfuscationMap.put("illager_abstract_b", "raider_open_door"); ++ deobfuscationMap.put("illager_illusioner_a", "illusioner_blindness_spell"); ++ deobfuscationMap.put("illager_illusioner_b", "illusioner_mirror_spell"); ++ deobfuscationMap.put("illager_wizard_b", "spellcaster_cast_spell"); ++ deobfuscationMap.put("llama_a", "llama_attack_wolf"); ++ deobfuscationMap.put("llama_c", "llama_hurt_by"); ++ deobfuscationMap.put("llama_trader_a", "llamatrader_defended_wandering_trader"); ++ deobfuscationMap.put("monster_patrolling_a", "long_distance_patrol"); ++ deobfuscationMap.put("ocelot_a", "ocelot_avoid_entity"); ++ deobfuscationMap.put("ocelot_b", "ocelot_tempt"); ++ deobfuscationMap.put("panda_b", "panda_attack"); ++ deobfuscationMap.put("panda_c", "panda_avoid"); ++ deobfuscationMap.put("panda_d", "panda_breed"); ++ deobfuscationMap.put("panda_e", "panda_hurt_by_target"); ++ deobfuscationMap.put("panda_f", "panda_lie_on_back"); ++ deobfuscationMap.put("panda_g", "panda_look_at_player"); ++ deobfuscationMap.put("panda_i", "panda_panic"); ++ deobfuscationMap.put("panda_j", "panda_roll"); ++ deobfuscationMap.put("panda_k", "panda_sit"); ++ deobfuscationMap.put("panda_l", "panda_sneeze"); ++ deobfuscationMap.put("phantom_b", "phantom_attack_player"); ++ deobfuscationMap.put("phantom_c", "phantom_attack_strategy"); ++ deobfuscationMap.put("phantom_e", "phantom_circle_around_anchor"); ++ deobfuscationMap.put("phantom_i", "phantom_sweep_attack"); ++ deobfuscationMap.put("polar_bear_a", "polarbear_attack_players"); ++ deobfuscationMap.put("polar_bear_b", "polarbear_hurt_by"); ++ deobfuscationMap.put("polar_bear_c", "polarbear_melee"); ++ deobfuscationMap.put("polar_bear_d", "polarbear_panic"); ++ deobfuscationMap.put("puffer_fish_a", "pufferfish_puff"); ++ deobfuscationMap.put("raider_a", "raider_hold_ground"); ++ deobfuscationMap.put("raider_b", "raider_obtain_banner"); ++ deobfuscationMap.put("raider_c", "raider_celebration"); ++ deobfuscationMap.put("raider_d", "raider_move_through_village"); ++ deobfuscationMap.put("ravager_a", "ravager_melee_attack"); ++ deobfuscationMap.put("shulker_a", "shulker_attack"); ++ deobfuscationMap.put("shulker_c", "shulker_defense"); ++ deobfuscationMap.put("shulker_d", "shulker_nearest"); ++ deobfuscationMap.put("shulker_e", "shulker_peek"); ++ deobfuscationMap.put("squid_a", "squid_flee"); ++ deobfuscationMap.put("skeleton_abstract_1", "skeleton_melee"); ++ deobfuscationMap.put("strider_a", "strider_go_to_lava"); ++ deobfuscationMap.put("turtle_a", "turtle_breed"); ++ deobfuscationMap.put("turtle_b", "turtle_go_home"); ++ deobfuscationMap.put("turtle_c", "turtle_goto_water"); ++ deobfuscationMap.put("turtle_d", "turtle_lay_egg"); ++ deobfuscationMap.put("turtle_f", "turtle_panic"); ++ deobfuscationMap.put("turtle_h", "turtle_random_stroll"); ++ deobfuscationMap.put("turtle_i", "turtle_tempt"); ++ deobfuscationMap.put("turtle_j", "turtle_travel"); ++ deobfuscationMap.put("vex_a", "vex_charge_attack"); ++ deobfuscationMap.put("vex_b", "vex_copy_target_of_owner"); ++ deobfuscationMap.put("vex_d", "vex_random_move"); ++ deobfuscationMap.put("villager_trader_a", "villagertrader_wander_to_position"); ++ deobfuscationMap.put("vindicator_a", "vindicator_break_door"); ++ deobfuscationMap.put("vindicator_b", "vindicator_johnny_attack"); ++ deobfuscationMap.put("vindicator_c", "vindicator_melee_attack"); ++ deobfuscationMap.put("wither_a", "wither_do_nothing"); ++ deobfuscationMap.put("wolf_a", "wolf_avoid_entity"); ++ deobfuscationMap.put("zombie_a", "zombie_attack_turtle_egg"); ++ ++ ignored.add("selector_1"); ++ ignored.add("selector_2"); ++ ignored.add("wrapped"); ++ ++ bukkitMap.put(net.minecraft.world.entity.Mob.class, Mob.class); ++ bukkitMap.put(AgableMob.class, Ageable.class); ++ bukkitMap.put(AmbientCreature.class, Ambient.class); ++ bukkitMap.put(Animal.class, Animals.class); ++ bukkitMap.put(net.minecraft.world.entity.ambient.Bat.class, Bat.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Bee.class, Bee.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Blaze.class, Blaze.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Cat.class, Cat.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.CaveSpider.class, CaveSpider.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Chicken.class, Chicken.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Cod.class, Cod.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Cow.class, Cow.class); ++ bukkitMap.put(PathfinderMob.class, Creature.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Creeper.class, Creeper.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Dolphin.class, Dolphin.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Drowned.class, Drowned.class); ++ bukkitMap.put(net.minecraft.world.entity.boss.enderdragon.EnderDragon.class, EnderDragon.class); ++ bukkitMap.put(EnderMan.class, Enderman.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Endermite.class, Endermite.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Evoker.class, Evoker.class); ++ bukkitMap.put(AbstractFish.class, Fish.class); ++ bukkitMap.put(AbstractSchoolingFish.class, Fish.class); // close enough ++ bukkitMap.put(FlyingMob.class, Flying.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Fox.class, Fox.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Ghast.class, Ghast.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Giant.class, Giant.class); ++ bukkitMap.put(AbstractGolem.class, Golem.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Guardian.class, Guardian.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.ElderGuardian.class, ElderGuardian.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.Horse.class, Horse.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.AbstractHorse.class, AbstractHorse.class); ++ bukkitMap.put(AbstractChestedHorse.class, ChestedHorse.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.Donkey.class, Donkey.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.Mule.class, Mule.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.SkeletonHorse.class, SkeletonHorse.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.ZombieHorse.class, ZombieHorse.class); ++ bukkitMap.put(AbstractIllager.class, Illager.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Illusioner.class, Illusioner.class); ++ bukkitMap.put(SpellcasterIllager.class, Spellcaster.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.IronGolem.class, IronGolem.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.Llama.class, Llama.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.TraderLlama.class, TraderLlama.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.MagmaCube.class, MagmaCube.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Monster.class, Monster.class); ++ bukkitMap.put(PatrollingMonster.class, Monster.class); // close enough ++ bukkitMap.put(net.minecraft.world.entity.animal.MushroomCow.class, MushroomCow.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Ocelot.class, Ocelot.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Panda.class, Panda.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Parrot.class, Parrot.class); ++ bukkitMap.put(ShoulderRidingEntity.class, Parrot.class); // close enough ++ bukkitMap.put(net.minecraft.world.entity.monster.Phantom.class, Phantom.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Pig.class, Pig.class); ++ bukkitMap.put(ZombifiedPiglin.class, PigZombie.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Pillager.class, Pillager.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.PolarBear.class, PolarBear.class); ++ bukkitMap.put(Pufferfish.class, PufferFish.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Rabbit.class, Rabbit.class); ++ bukkitMap.put(net.minecraft.world.entity.raid.Raider.class, Raider.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Ravager.class, Ravager.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Salmon.class, Salmon.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Sheep.class, Sheep.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Shulker.class, Shulker.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Silverfish.class, Silverfish.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Skeleton.class, Skeleton.class); ++ bukkitMap.put(AbstractSkeleton.class, Skeleton.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Stray.class, Stray.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.WitherSkeleton.class, WitherSkeleton.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Slime.class, Slime.class); ++ bukkitMap.put(SnowGolem.class, Snowman.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Spider.class, Spider.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Squid.class, Squid.class); ++ bukkitMap.put(TamableAnimal.class, Tameable.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.TropicalFish.class, TropicalFish.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Turtle.class, Turtle.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Vex.class, Vex.class); ++ bukkitMap.put(net.minecraft.world.entity.npc.Villager.class, Villager.class); ++ bukkitMap.put(net.minecraft.world.entity.npc.AbstractVillager.class, AbstractVillager.class); ++ bukkitMap.put(net.minecraft.world.entity.npc.WanderingTrader.class, WanderingTrader.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Vindicator.class, Vindicator.class); ++ bukkitMap.put(WaterAnimal.class, WaterMob.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Witch.class, Witch.class); ++ bukkitMap.put(WitherBoss.class, Wither.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Wolf.class, Wolf.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Zombie.class, Zombie.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Husk.class, Husk.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.ZombieVillager.class, ZombieVillager.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.hoglin.Hoglin.class, Hoglin.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.piglin.Piglin.class, Piglin.class); ++ bukkitMap.put(AbstractPiglin.class, PiglinAbstract.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.piglin.PiglinBrute.class, PiglinBrute.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Strider.class, Strider.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Zoglin.class, Zoglin.class); ++ } ++ ++ public static String getUsableName(Class clazz) { ++ String name = clazz.getName(); ++ name = name.substring(name.lastIndexOf(".") + 1); ++ boolean flag = false; ++ // inner classes ++ if (name.contains("$")) { ++ String cut = name.substring(name.indexOf("$") + 1); ++ if (cut.length() <= 2) { ++ name = name.replace("Entity", ""); ++ name = name.replace("$", "_"); ++ flag = true; ++ } else { ++ // mapped, wooo ++ name = cut; ++ } ++ } ++ name = name.replace("PathfinderGoal", ""); ++ StringBuilder sb = new StringBuilder(); ++ for (char c : name.toCharArray()) { ++ if (c >= 'A' && c <= 'Z') { ++ sb.append("_"); ++ sb.append(Character.toLowerCase(c)); ++ } else { ++ sb.append(c); ++ } ++ } ++ name = sb.toString(); ++ name = name.replaceFirst("_", ""); ++ ++ if (flag && !deobfuscationMap.containsKey(name.toLowerCase()) && !ignored.contains(name)) { ++ System.out.println("need to map " + clazz.getName() + " (" + name.toLowerCase() + ")"); ++ } ++ ++ // did we rename this key? ++ return deobfuscationMap.getOrDefault(name, name); ++ } ++ ++ public static EnumSet vanillaToPaper(OptimizedSmallEnumSet types) { ++ EnumSet goals = EnumSet.noneOf(GoalType.class); ++ for (GoalType type : GoalType.values()) { ++ if (types.hasElement(paperToVanilla(type))) { ++ goals.add(type); ++ } ++ } ++ return goals; ++ } ++ ++ public static GoalType vanillaToPaper(Goal.Flag type) { ++ switch (type) { ++ case MOVE: ++ return GoalType.MOVE; ++ case LOOK: ++ return GoalType.LOOK; ++ case JUMP: ++ return GoalType.JUMP; ++ case UNKNOWN_BEHAVIOR: ++ return GoalType.UNKNOWN_BEHAVIOR; ++ case TARGET: ++ return GoalType.TARGET; ++ default: ++ throw new IllegalArgumentException("Unknown vanilla mob goal type " + type.name()); ++ } ++ } ++ ++ public static EnumSet paperToVanilla(EnumSet types) { ++ EnumSet goals = EnumSet.noneOf(Goal.Flag.class); ++ for (GoalType type : types) { ++ goals.add(paperToVanilla(type)); ++ } ++ return goals; ++ } ++ ++ public static Goal.Flag paperToVanilla(GoalType type) { ++ switch (type) { ++ case MOVE: ++ return Goal.Flag.MOVE; ++ case LOOK: ++ return Goal.Flag.LOOK; ++ case JUMP: ++ return Goal.Flag.JUMP; ++ case UNKNOWN_BEHAVIOR: ++ return Goal.Flag.UNKNOWN_BEHAVIOR; ++ case TARGET: ++ return Goal.Flag.TARGET; ++ default: ++ throw new IllegalArgumentException("Unknown paper mob goal type " + type.name()); ++ } ++ } ++ ++ public static GoalKey getKey(Class goalClass) { ++ String name = getUsableName(goalClass); ++ if (ignored.contains(name)) { ++ //noinspection unchecked ++ return (GoalKey) GoalKey.of(Mob.class, NamespacedKey.minecraft(name)); ++ } ++ return GoalKey.of(getEntity(goalClass), NamespacedKey.minecraft(name)); ++ } ++ ++ public static Class getEntity(Class goalClass) { ++ //noinspection unchecked ++ return (Class) entityClassCache.computeIfAbsent(goalClass, key -> { ++ for (Constructor ctor : key.getDeclaredConstructors()) { ++ for (int i = 0; i < ctor.getParameterCount(); i++) { ++ Class param = ctor.getParameterTypes()[i]; ++ if (net.minecraft.world.entity.Mob.class.isAssignableFrom(param)) { ++ //noinspection unchecked ++ return toBukkitClass((Class) param); ++ } else if (RangedAttackMob.class.isAssignableFrom(param)) { ++ return RangedEntity.class; ++ } ++ } ++ } ++ throw new RuntimeException("Can't figure out applicable entity for mob goal " + goalClass); // maybe just return EntityInsentient? ++ }); ++ } ++ ++ public static Class toBukkitClass(Class nmsClass) { ++ Class bukkitClass = bukkitMap.get(nmsClass); ++ if (bukkitClass == null) { ++ throw new RuntimeException("Can't figure out applicable bukkit entity for nms entity " + nmsClass); // maybe just return Mob? ++ } ++ return bukkitClass; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java +new file mode 100644 +index 0000000000000000000000000000000000000000..14ddf844be10c04522aa3ec125fa7a0f540b10c2 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java +@@ -0,0 +1,55 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import GoalKey; ++import net.minecraft.world.entity.ai.goal.Goal; ++import org.bukkit.entity.Mob; ++ ++/** ++ * Wraps api in vanilla ++ */ ++public class PaperCustomGoal extends Goal { ++ ++ private final Goal handle; ++ ++ public PaperCustomGoal(Goal handle) { ++ this.handle = handle; ++ ++ this.setTypes(MobGoalHelper.paperToVanilla(handle.getTypes())); ++ if (this.getGoalTypes().size() == 0) { ++ this.getGoalTypes().addUnchecked(Flag.UNKNOWN_BEHAVIOR); ++ } ++ } ++ ++ @Override ++ public boolean shouldActivate() { ++ return handle.shouldActivate(); ++ } ++ ++ @Override ++ public boolean shouldStayActive() { ++ return handle.shouldStayActive(); ++ } ++ ++ @Override ++ public void start() { ++ handle.start(); ++ } ++ ++ @Override ++ public void onTaskReset() { ++ handle.stop(); ++ } ++ ++ @Override ++ public void tick() { ++ handle.tick(); ++ } ++ ++ public Goal getHandle() { ++ return handle; ++ } ++ ++ public GoalKey getKey() { ++ return handle.getKey(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java +new file mode 100644 +index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959e82e4ab1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java +@@ -0,0 +1,222 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import java.util.Collection; ++import java.util.EnumSet; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.LinkedList; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import net.minecraft.world.entity.ai.goal.Goal; ++import net.minecraft.world.entity.ai.goal.GoalSelector; ++import net.minecraft.world.entity.ai.goal.WrappedGoal; ++import org.bukkit.craftbukkit.entity.CraftMob; ++import org.bukkit.entity.Mob; ++ ++public class PaperMobGoals implements MobGoals { ++ ++ private final Map> instanceCache = new HashMap<>(); ++ ++ @Override ++ public void addGoal(T mob, int priority, Goal goal) { ++ CraftMob craftMob = (CraftMob) mob; ++ getHandle(craftMob, goal.getTypes()).addGoal(priority, new PaperCustomGoal<>(goal)); ++ } ++ ++ @Override ++ public void removeGoal(T mob, Goal goal) { ++ CraftMob craftMob = (CraftMob) mob; ++ if (goal instanceof PaperCustomGoal) { ++ getHandle(craftMob, goal.getTypes()).removeGoal((Goal) goal); ++ } else if (goal instanceof PaperVanillaGoal) { ++ getHandle(craftMob, goal.getTypes()).removeGoal(((PaperVanillaGoal) goal).getHandle()); ++ } else { ++ List toRemove = new LinkedList<>(); ++ for (WrappedGoal item : getHandle(craftMob, goal.getTypes()).getTasks()) { ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ if (((PaperCustomGoal) item.getGoal()).getHandle() == goal) { ++ toRemove.add(item.getGoal()); ++ } ++ } ++ } ++ ++ for (Goal g : toRemove) { ++ getHandle(craftMob, goal.getTypes()).removeGoal(g); ++ } ++ } ++ } ++ ++ @Override ++ public void removeAllGoals(T mob) { ++ for (GoalType type : GoalType.values()) { ++ removeAllGoals(mob, type); ++ } ++ } ++ ++ @Override ++ public void removeAllGoals(T mob, GoalType type) { ++ for (Goal goal : getAllGoals(mob, type)) { ++ removeGoal(mob, goal); ++ } ++ } ++ ++ @Override ++ public void removeGoal(T mob, GoalKey key) { ++ for (Goal goal : getGoals(mob, key)) { ++ removeGoal(mob, goal); ++ } ++ } ++ ++ @Override ++ public boolean hasGoal(T mob, GoalKey key) { ++ for (Goal g : getAllGoals(mob)) { ++ if (g.getKey().equals(key)) { ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ @Override ++ public Goal getGoal(T mob, GoalKey key) { ++ for (Goal g : getAllGoals(mob)) { ++ if (g.getKey().equals(key)) { ++ return g; ++ } ++ } ++ return null; ++ } ++ ++ @Override ++ public Collection> getGoals(T mob, GoalKey key) { ++ Set> goals = new HashSet<>(); ++ for (Goal g : getAllGoals(mob)) { ++ if (g.getKey().equals(key)) { ++ goals.add(g); ++ } ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getAllGoals(T mob) { ++ Set> goals = new HashSet<>(); ++ for (GoalType type : GoalType.values()) { ++ goals.addAll(getAllGoals(mob, type)); ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getAllGoals(T mob, GoalType type) { ++ CraftMob craftMob = (CraftMob) mob; ++ Set> goals = new HashSet<>(); ++ for (WrappedGoal item : getHandle(craftMob, type).getTasks()) { ++ if (!item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { ++ continue; ++ } ++ ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); ++ } else { ++ //noinspection unchecked ++ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); ++ } ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getAllGoalsWithout(T mob, GoalType type) { ++ CraftMob craftMob = (CraftMob) mob; ++ Set> goals = new HashSet<>(); ++ for (GoalType internalType : GoalType.values()) { ++ if (internalType == type) { ++ continue; ++ } ++ for (WrappedGoal item : getHandle(craftMob, internalType).getTasks()) { ++ if (item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { ++ continue; ++ } ++ ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); ++ } else { ++ //noinspection unchecked ++ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); ++ } ++ } ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getRunningGoals(T mob) { ++ Set> goals = new HashSet<>(); ++ for (GoalType type : GoalType.values()) { ++ goals.addAll(getRunningGoals(mob, type)); ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getRunningGoals(T mob, GoalType type) { ++ CraftMob craftMob = (CraftMob) mob; ++ Set> goals = new HashSet<>(); ++ getHandle(craftMob, type).getExecutingGoals() ++ .filter(item -> item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) ++ .forEach(item -> { ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); ++ } else { ++ //noinspection unchecked ++ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); ++ } ++ }); ++ return goals; ++ } ++ ++ @Override ++ public Collection> getRunningGoalsWithout(T mob, GoalType type) { ++ CraftMob craftMob = (CraftMob) mob; ++ Set> goals = new HashSet<>(); ++ for (GoalType internalType : GoalType.values()) { ++ if (internalType == type) { ++ continue; ++ } ++ getHandle(craftMob, internalType).getExecutingGoals() ++ .filter(item -> !item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) ++ .forEach(item -> { ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); ++ } else { ++ //noinspection unchecked ++ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); ++ } ++ }); ++ } ++ return goals; ++ } ++ ++ private GoalSelector getHandle(CraftMob mob, EnumSet types) { ++ if (types.contains(GoalType.TARGET)) { ++ return mob.getHandle().targetSelector; ++ } else { ++ return mob.getHandle().goalSelector; ++ } ++ } ++ ++ private GoalSelector getHandle(CraftMob mob, GoalType type) { ++ if (type == GoalType.TARGET) { ++ return mob.getHandle().targetSelector; ++ } else { ++ return mob.getHandle().goalSelector; ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d4fe9d517a05f99c715ab73d5baf1deb6a732068 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java +@@ -0,0 +1,62 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import GoalKey; ++import java.util.EnumSet; ++import net.minecraft.world.entity.ai.goal.Goal; ++import org.bukkit.entity.Mob; ++ ++/** ++ * Wraps vanilla in api ++ */ ++public class PaperVanillaGoal implements VanillaGoal { ++ ++ private final Goal handle; ++ private final GoalKey key; ++ ++ private final EnumSet types; ++ ++ public PaperVanillaGoal(Goal handle) { ++ this.handle = handle; ++ this.key = MobGoalHelper.getKey(handle.getClass()); ++ this.types = MobGoalHelper.vanillaToPaper(handle.getGoalTypes()); ++ } ++ ++ public Goal getHandle() { ++ return handle; ++ } ++ ++ @Override ++ public boolean shouldActivate() { ++ return handle.shouldActivate2(); ++ } ++ ++ @Override ++ public boolean shouldStayActive() { ++ return handle.shouldStayActive2(); ++ } ++ ++ @Override ++ public void start() { ++ handle.start(); ++ } ++ ++ @Override ++ public void stop() { ++ handle.onTaskReset(); ++ } ++ ++ @Override ++ public void tick() { ++ handle.tick(); ++ } ++ ++ @Override ++ public GoalKey getKey() { ++ return key; ++ } ++ ++ @Override ++ public EnumSet getTypes() { ++ return types; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java +index 9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f..b3329c6fcd6758a781a51f5ba8f5052ac1c77b49 100644 +--- a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java ++++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java +@@ -64,4 +64,8 @@ public final class OptimizedSmallEnumSet> { + public boolean hasCommonElements(final OptimizedSmallEnumSet other) { + return (other.backingSet & this.backingSet) != 0; + } ++ ++ public boolean hasElement(final E element) { ++ return (this.backingSet & (1L << element.ordinal())) != 0; ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +index acc6306d659cd65a043d12cd42dcbaf55aaf5250..f85dfd8b57cf81ad7c6b12753fdd42e93f772f9e 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +@@ -8,11 +8,17 @@ public abstract class Goal { + private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. + private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector + +- public Goal() {} ++ // Paper start make sure goaltypes is never empty ++ public Goal() { ++ if (this.goalTypes.size() == 0) { ++ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR); ++ } ++ } ++ // paper end + +- public abstract boolean canUse(); ++ public boolean canUse() { return this.shouldActivate(); } public boolean shouldActivate() { return false;} public boolean shouldActivate2() { return canUse(); } // Paper - OBFHELPER, for both directions... + +- public boolean canContinueToUse() { ++ public boolean canContinueToUse() { return this.shouldStayActive(); } public boolean shouldStayActive2() { return canContinueToUse(); } public boolean shouldStayActive() { // Paper - OBFHELPER, for both directions... + return this.canUse(); + } + +@@ -20,19 +26,23 @@ public abstract class Goal { + return true; + } + +- public void start() {} ++ public void start() { this.start(); } public void start() {} // Paper - OBFHELPER + + public void stop() { + onTaskReset(); // Paper + } + public void onTaskReset() {} // Paper + +- public void tick() {} ++ public void tick() { this.tick(); } public void tick() {} // Paper OBFHELPER + +- public void setFlags(EnumSet controls) { ++ public void setFlags(EnumSet controls) { this.setTypes(controls); } public void setTypes(EnumSet enumset) { // Paper - OBFHELPER + // Paper start - remove streams from pathfindergoalselector + this.goalTypes.clear(); +- this.goalTypes.addAllUnchecked(controls); ++ this.goalTypes.addAllUnchecked(enumset); ++ // make sure its never empty ++ if (this.goalTypes.size() == 0) { ++ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR); ++ } + // Paper end - remove streams from pathfindergoalselector + } + +@@ -48,7 +58,7 @@ public abstract class Goal { + + public static enum Flag { + +- MOVE, LOOK, JUMP, TARGET; ++ MOVE, LOOK, JUMP, TARGET, UNKNOWN_BEHAVIOR; // Paper - add unknown + + private Flag() {} + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +index 5da2d780c17522e07c733a5e23b17ec760c7b342..a03f72f67948efab3b000dfa1d48061abf7cc02f 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +@@ -28,7 +28,7 @@ public class GoalSelector { + } + }; + private final Map lockedFlags = new EnumMap(Goal.Flag.class); +- private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER ++ private final Set availableGoals = Sets.newLinkedHashSet(); public final Set getTasks() { return availableGoals; }// Paper - OBFHELPER // Paper - private -> public + private final Supplier profiler; + private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. + private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector +@@ -39,7 +39,7 @@ public class GoalSelector { + this.profiler = profiler; + } + +- public void addGoal(int priority, Goal goal) { ++ public void addGoal(int priority, Goal goal) {addGoal(priority, goal);} public void addGoal(int priority, Goal goal) { // Paper - OBFHELPER + this.availableGoals.add(new WrappedGoal(priority, goal)); + } + +@@ -58,7 +58,7 @@ public class GoalSelector { + } + // Paper end + +- public void removeGoal(Goal goal) { ++ public void removeGoal(Goal goal) {removeGoal(goal);} public void removeGoal(Goal goal) { // Paper - OBFHELPER + // Paper start - remove streams from pathfindergoalselector + for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { + WrappedGoal goalWrapped = iterator.next(); +@@ -154,6 +154,7 @@ public class GoalSelector { + gameprofilerfiller.pop(); + } + ++ public final Stream getExecutingGoals() { return getRunningGoals(); } // Paper - OBFHELPER + public Stream getRunningGoals() { + return this.availableGoals.stream().filter(WrappedGoal::isRunning); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +index 984146b2b6eb3e498433b1c4971397848166d9c9..06fe2248a52c180ffabe0a6fe0cf155b78d4752d 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +@@ -5,8 +5,8 @@ import javax.annotation.Nullable; + + public class WrappedGoal extends Goal { + +- private final Goal goal; +- private final int priority; ++ private final Goal goal; public Goal getGoal() {return goal;} // Paper - OBFHELPER ++ private final int priority; public int getPriority() {return priority;} // Paper - OBFHELPER + private boolean isRunning; + + public WrappedGoal(int priority, Goal goal) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 1bfe96443877e460d22513d59ebc3b5988e8eb43..c6dc314a1735bf849ee1572e01335909bed9b455 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2390,5 +2390,11 @@ public final class CraftServer implements Server { + public boolean isStopping() { + return net.minecraft.server.MinecraftServer.getServer().hasStopped(); + } ++ ++ private com.destroystokyo.paper.entity.ai.MobGoals mobGoals = new com.destroystokyo.paper.entity.ai.PaperMobGoals(); ++ @Override ++ public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { ++ return mobGoals; ++ } + // Paper end + } +diff --git a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c0525216a8469613c3e0d4b5774a82f69e70fb16 +--- /dev/null ++++ b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java +@@ -0,0 +1,104 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.entity.ai.goal.PathfinderGoal; ++import org.junit.Assert; ++import org.junit.Test; ++ ++import java.lang.reflect.Field; ++import java.lang.reflect.Modifier; ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++import java.util.stream.Collectors; ++ ++import org.bukkit.entity.Mob; ++ ++import io.github.classgraph.ClassGraph; ++import io.github.classgraph.ScanResult; ++ ++public class VanillaMobGoalTest { ++ ++ @Test ++ public void testKeys() { ++ List> deprecated = new ArrayList<>(); ++ List> keys = new ArrayList<>(); ++ for (Field field : VanillaGoal.class.getFields()) { ++ if (field.getType().equals(GoalKey.class)) { ++ try { ++ GoalKey goalKey = (GoalKey) field.get(null); ++ if (field.getAnnotation(Deprecated.class) != null) { ++ deprecated.add(goalKey); ++ } else { ++ keys.add(goalKey); ++ } ++ } catch (IllegalAccessException e) { ++ System.out.println("Skipping " + field.getName() + ": " + e.getMessage()); ++ } ++ } ++ } ++ ++ List> classes; ++ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) { ++ classes = scanResult.getSubclasses(PathfinderGoal.class.getName()).loadClasses(); ++ } ++ ++ List> vanillaNames = classes.stream() ++ .filter(VanillaMobGoalTest::hasNoEnclosingClass) ++ .filter(clazz -> !Modifier.isAbstract(clazz.getModifiers())) ++ .map(goalClass -> MobGoalHelper.getKey((Class) goalClass)) ++ .collect(Collectors.toList()); ++ ++ List> missingFromAPI = new ArrayList<>(vanillaNames); ++ missingFromAPI.removeAll(keys); ++ missingFromAPI.removeIf(k -> MobGoalHelper.ignored.contains(k.getNamespacedKey().getKey())); ++ List> missingFromVanilla = new ArrayList<>(keys); ++ missingFromVanilla.removeAll(vanillaNames); ++ ++ boolean shouldFail = false; ++ if (missingFromAPI.size() != 0) { ++ System.out.println("Missing from API: "); ++ for (GoalKey key : missingFromAPI) { ++ System.out.println("GoalKey<" + key.getEntityClass().getSimpleName() + "> " + key.getNamespacedKey().getKey().toUpperCase() + ++ " = GoalKey.of(" + key.getEntityClass().getSimpleName() + ".class, NamespacedKey.minecraft(\"" + key.getNamespacedKey().getKey() + "\"));"); ++ } ++ shouldFail = true; ++ } ++ if (missingFromVanilla.size() != 0) { ++ System.out.println("Missing from vanilla: "); ++ missingFromVanilla.forEach(System.out::println); ++ shouldFail = true; ++ } ++ ++ if (deprecated.size() != 0) { ++ System.out.println("Deprecated (might want to remove them at some point): "); ++ deprecated.forEach(System.out::println); ++ } ++ ++ if (shouldFail) Assert.fail("See above"); ++ } ++ ++ private static boolean hasNoEnclosingClass(Class clazz) { ++ return clazz.getEnclosingClass() == null || hasNoEnclosingClass(clazz.getSuperclass()); ++ } ++ ++ @Test ++ public void testBukkitMap() { ++ List> classes; ++ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft.world.entity").scan()) { ++ classes = scanResult.getSubclasses("net.minecraft.world.entity.EntityInsentient").loadClasses(); ++ } ++ Assert.assertNotEquals("There are supposed to be more than 0 entity types!", Collections.emptyList(), classes); ++ ++ boolean shouldFail = false; ++ for (Class nmsClass : classes) { ++ Class bukkitClass = MobGoalHelper.toBukkitClass((Class) nmsClass); ++ if (bukkitClass == null) { ++ shouldFail = true; ++ System.out.println("Missing bukkitMap.put(" + nmsClass.getSimpleName() + ".class, " + nmsClass.getSimpleName().replace("Entity", "") + ".class);"); ++ } ++ } ++ ++ if (shouldFail) Assert.fail("See above"); ++ } ++} diff --git a/Remapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch b/Remapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch new file mode 100644 index 0000000000..16a647e328 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch @@ -0,0 +1,413 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 5 May 2020 20:18:05 -0700 +Subject: [PATCH] Use distance map to optimise entity tracker + +Use the distance map to find candidate players for tracking. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index e5ad635a480d32e7a10ee92c65cfc18a98beafad..74f393ffa2ae2d0e25b3f0b674cef7a987e985d3 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1652,6 +1652,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); ++ // Paper start - use distance map to optimise tracker ++ public static boolean isLegacyTrackingEntity(Entity entity) { ++ return entity.isLegacyTrackingEntity; ++ } ++ ++ // inlined EnumMap, TrackingRange.TrackingRangeType ++ static final org.spigotmc.TrackingRange.TrackingRangeType[] TRACKING_RANGE_TYPES = org.spigotmc.TrackingRange.TrackingRangeType.values(); ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap[] playerEntityTrackerTrackMaps; ++ final int[] entityTrackerTrackRanges; ++ ++ private int convertSpigotRangeToVanilla(final int vanilla) { ++ return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); ++ } ++ // Paper end - use distance map to optimise tracker + + void addPlayerToDistanceMaps(ServerPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.getX()); + int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); + // Note: players need to be explicitly added to distance maps before they can be updated ++ // Paper start - use distance map to optimise entity tracker ++ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { ++ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; ++ int trackRange = this.entityTrackerTrackRanges[i]; ++ ++ trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); ++ } ++ // Paper end - use distance map to optimise entity tracker + } + + void removePlayerFromDistanceMaps(ServerPlayer player) { +- ++ // Paper start - use distance map to optimise tracker ++ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { ++ this.playerEntityTrackerTrackMaps[i].remove(player); ++ } ++ // Paper end - use distance map to optimise tracker + } + + void updateMaps(ServerPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.getX()); + int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); + // Note: players need to be explicitly added to distance maps before they can be updated ++ // Paper start - use distance map to optimise entity tracker ++ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { ++ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; ++ int trackRange = this.entityTrackerTrackRanges[i]; ++ ++ trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); ++ } ++ // Paper end - use distance map to optimise entity tracker + } + // Paper end + +@@ -244,6 +279,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper + this.setViewDistance(i); + this.playerMobDistanceMap = this.level.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper ++ // Paper start - use distance map to optimise entity tracker ++ this.playerEntityTrackerTrackMaps = new com.destroystokyo.paper.util.misc.PlayerAreaMap[TRACKING_RANGE_TYPES.length]; ++ this.entityTrackerTrackRanges = new int[TRACKING_RANGE_TYPES.length]; ++ ++ org.spigotmc.SpigotWorldConfig spigotWorldConfig = this.level.spigotConfig; ++ ++ for (int ordinal = 0, len = TRACKING_RANGE_TYPES.length; ordinal < len; ++ordinal) { ++ org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = TRACKING_RANGE_TYPES[ordinal]; ++ int configuredSpigotValue; ++ switch (trackingRangeType) { ++ case PLAYER: ++ configuredSpigotValue = spigotWorldConfig.playerTrackingRange; ++ break; ++ case ANIMAL: ++ configuredSpigotValue = spigotWorldConfig.animalTrackingRange; ++ break; ++ case MONSTER: ++ configuredSpigotValue = spigotWorldConfig.monsterTrackingRange; ++ break; ++ case MISC: ++ configuredSpigotValue = spigotWorldConfig.miscTrackingRange; ++ break; ++ case OTHER: ++ configuredSpigotValue = spigotWorldConfig.otherTrackingRange; ++ break; ++ case ENDERDRAGON: ++ configuredSpigotValue = EntityType.ENDER_DRAGON.clientTrackingRange() * 16; ++ break; ++ default: ++ throw new IllegalStateException("Missing case for enum " + trackingRangeType); ++ } ++ configuredSpigotValue = convertSpigotRangeToVanilla(configuredSpigotValue); ++ ++ int trackRange = (configuredSpigotValue >>> 4) + ((configuredSpigotValue & 15) != 0 ? 1 : 0); ++ this.entityTrackerTrackRanges[ordinal] = trackRange; ++ ++ this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); ++ } ++ // Paper end - use distance map to optimise entity tracker + } + + public void updatePlayerMobTypeMap(Entity entity) { +@@ -1490,17 +1564,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + public void move(ServerPlayer player) { +- ObjectIterator objectiterator = this.entityMap.values().iterator(); +- +- while (objectiterator.hasNext()) { +- ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); +- +- if (playerchunkmap_entitytracker.entity == player) { +- playerchunkmap_entitytracker.updatePlayers(this.level.players()); +- } else { +- playerchunkmap_entitytracker.updatePlayer(player); +- } +- } ++ // Paper - delay this logic for the entity tracker tick, no need to duplicate it + + int i = Mth.floor(player.getX()) >> 4; + int j = Mth.floor(player.getZ()) >> 4; +@@ -1616,7 +1680,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker + this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); +- playerchunkmap_entitytracker.updatePlayers(this.level.players()); ++ playerchunkmap_entitytracker.updatePlayers(entity.getPlayersInTrackRange()); // Paper - don't search all players + if (entity instanceof ServerPlayer) { + ServerPlayer entityplayer = (ServerPlayer) entity; + +@@ -1659,7 +1723,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + entity.tracker = null; // Paper - We're no longer tracked + } + ++ // Paper start - optimised tracker ++ private final void processTrackQueue() { ++ this.level.timings.tracker1.startTiming(); ++ try { ++ for (TrackedEntity tracker : this.entityMap.values()) { ++ // update tracker entry ++ tracker.updatePlayers(tracker.entity.getPlayersInTrackRange()); ++ } ++ } finally { ++ this.level.timings.tracker1.stopTiming(); ++ } ++ ++ ++ this.level.timings.tracker2.startTiming(); ++ try { ++ for (TrackedEntity tracker : this.entityMap.values()) { ++ tracker.serverEntity.tick(); ++ } ++ } finally { ++ this.level.timings.tracker2.stopTiming(); ++ } ++ } ++ // Paper end - optimised tracker ++ + protected void tick() { ++ // Paper start - optimized tracker ++ if (true) { ++ this.processTrackQueue(); ++ return; ++ } ++ // Paper end - optimized tracker + List list = Lists.newArrayList(); + List list1 = this.level.players(); + +@@ -1728,23 +1822,31 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos()); + List list = Lists.newArrayList(); + List list1 = Lists.newArrayList(); +- ObjectIterator objectiterator = this.entityMap.values().iterator(); ++ // Paper start - optimise entity tracker ++ // use the chunk entity list, not the whole trackedEntities map... ++ Entity[] entities = chunk.entities.getRawData(); ++ for (int i = 0, size = chunk.entities.size(); i < size; ++i) { ++ Entity entity = entities[i]; ++ if (entity == player) { ++ continue; ++ } ++ ChunkMap.TrackedEntity tracker = this.entityMap.get(entity.getId()); ++ if (tracker != null) { // dumb plugins... move on... ++ tracker.updatePlayer(player); ++ } + +- while (objectiterator.hasNext()) { +- ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); +- Entity entity = playerchunkmap_entitytracker.entity; ++ // keep the vanilla logic here - this is REQUIRED or else passengers and their vehicles disappear! ++ // (and god knows what the leash thing is) + +- if (entity != player && entity.xChunk == chunk.getPos().x && entity.zChunk == chunk.getPos().z) { +- playerchunkmap_entitytracker.updatePlayer(player); +- if (entity instanceof Mob && ((Mob) entity).getLeashHolder() != null) { +- list.add(entity); +- } ++ if (entity instanceof Mob && ((Mob)entity).getLeashHolder() != null) { ++ list.add(entity); ++ } + +- if (!entity.getPassengers().isEmpty()) { +- list1.add(entity); +- } ++ if (!entity.getPassengers().isEmpty()) { ++ list1.add(entity); + } + } ++ // Paper end - optimise entity tracker + + Iterator iterator; + Entity entity1; +@@ -1782,7 +1884,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + public class TrackedEntity { + +- private final ServerEntity serverEntity; ++ final ServerEntity serverEntity; // Paper - private -> package private + private final Entity entity; + private final int range; + private SectionPos lastSectionPos; +@@ -1799,6 +1901,42 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.lastSectionPos = SectionPos.of(entity); + } + ++ // Paper start - use distance map to optimise tracker ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet lastTrackerCandidates; ++ ++ final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet oldTrackerCandidates = this.lastTrackerCandidates; ++ this.lastTrackerCandidates = newTrackerCandidates; ++ ++ if (newTrackerCandidates != null) { ++ Object[] rawData = newTrackerCandidates.getBackingSet(); ++ for (int i = 0, len = rawData.length; i < len; ++i) { ++ Object raw = rawData[i]; ++ if (!(raw instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)raw; ++ this.updatePlayer(player); ++ } ++ } ++ ++ if (oldTrackerCandidates == newTrackerCandidates) { ++ // this is likely the case. ++ // means there has been no range changes, so we can just use the above for tracking. ++ return; ++ } ++ ++ // stuff could have been removed, so we need to check the trackedPlayers set ++ // for players that were removed ++ ++ for (ServerPlayer player : this.seenBy.toArray(new ServerPlayer[0])) { // avoid CME ++ if (newTrackerCandidates == null || !newTrackerCandidates.contains(player)) { ++ this.updatePlayer(player); ++ } ++ } ++ } ++ // Paper end - use distance map to optimise tracker ++ + public boolean equals(Object object) { + return object instanceof ChunkMap.TrackedEntity ? ((ChunkMap.TrackedEntity) object).entity.getId() == this.entity.getId() : false; + } +@@ -1899,7 +2037,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + int j = entity.getType().clientTrackingRange() * 16; + j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper + +- if (j > i) { ++ if (j < i) { // Paper - we need the lowest range thanks to the fact that our tracker doesn't account for passenger logic + i = j; + } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index 1609ab94c86e964421f996d4d46aef30f8b8e696..d797873db52ba265ac4478f9f3c6344badd4739e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -100,6 +100,7 @@ public class ServerEntity { + this.wasOnGround = entity.isOnGround(); + } + ++ public final void tick() { this.sendChanges(); } // Paper - OBFHELPER + public void sendChanges() { + List list = this.entity.getPassengers(); + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 2b48c4a2b512c42bed2c767db90a28898c74286a..d9bb00752ac81b2171d3ad25fd84904467a18e3b 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -46,6 +46,7 @@ import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.ServerLevel; +@@ -294,6 +295,21 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + // CraftBukkit end + ++ // Paper start - optimise entity tracking ++ final org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = org.spigotmc.TrackingRange.getTrackingRangeType(this); ++ ++ public boolean isLegacyTrackingEntity = false; ++ ++ public final void setLegacyTrackingEntity(final boolean isLegacyTrackingEntity) { ++ this.isLegacyTrackingEntity = isLegacyTrackingEntity; ++ } ++ ++ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayersInTrackRange() { ++ return ((ServerLevel)this.level).getChunkSource().chunkMap.playerEntityTrackerTrackMaps[this.trackingRangeType.ordinal()] ++ .getObjectsInRange(MCUtil.getCoordinateKey(this)); ++ } ++ // Paper end - optimise entity tracking ++ + public Entity(EntityType type, Level world) { + this.id = Entity.ENTITY_COUNTER.incrementAndGet(); + this.passengers = Lists.newArrayList(); +diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java +index b03fa9024c7f0238e1379f6ae4486db5300a70e9..7b6011be849ecffdd791d439f70ae5dffc96f264 100644 +--- a/src/main/java/org/spigotmc/TrackingRange.java ++++ b/src/main/java/org/spigotmc/TrackingRange.java +@@ -20,6 +20,7 @@ public class TrackingRange + */ + public static int getEntityTrackingRange(Entity entity, int defaultRange) + { ++ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return defaultRange; // Paper - enderdragon is exempt + SpigotWorldConfig config = entity.level.spigotConfig; + if ( entity instanceof ServerPlayer ) + { +@@ -43,8 +44,48 @@ public class TrackingRange + return config.miscTrackingRange; + } else + { +- if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt + return config.otherTrackingRange; + } + } ++ ++ // Paper start - optimise entity tracking ++ // copied from above, TODO check on update ++ public static TrackingRangeType getTrackingRangeType(Entity entity) ++ { ++ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return TrackingRangeType.ENDERDRAGON; // Paper - enderdragon is exempt ++ if ( entity instanceof ServerPlayer ) ++ { ++ return TrackingRangeType.PLAYER; ++ // Paper start - Simplify and set water mobs to animal tracking range ++ } ++ switch (entity.activationType) { ++ case RAIDER: ++ case MONSTER: ++ case FLYING_MONSTER: ++ return TrackingRangeType.MONSTER; ++ case WATER: ++ case VILLAGER: ++ case ANIMAL: ++ return TrackingRangeType.ANIMAL; ++ case MISC: ++ } ++ if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) ++ // Paper end ++ { ++ return TrackingRangeType.MISC; ++ } else ++ { ++ return TrackingRangeType.OTHER; ++ } ++ } ++ ++ public static enum TrackingRangeType { ++ PLAYER, ++ ANIMAL, ++ MONSTER, ++ MISC, ++ OTHER, ++ ENDERDRAGON; ++ } ++ // Paper end - optimise entity tracking + } diff --git a/Remapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch b/Remapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch new file mode 100644 index 0000000000..adc6c14065 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch @@ -0,0 +1,384 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 5 May 2020 20:40:53 -0700 +Subject: [PATCH] Optimize isOutsideRange to use distance maps + +Use a distance map to find the players in range quickly + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index d12d5459c847d3f0d655c85e31d81c27b7a2face..0147798c0285f64b8d767dfb2709d92f66ac72ef 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -69,6 +69,18 @@ public class ChunkHolder { + long lastAutoSaveTime; // Paper - incremental autosave + long inactiveTimeStart; // Paper - incremental autosave + ++ // Paper start - optimise isOutsideOfRange ++ // cached here to avoid a map lookup ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInMobSpawnRange; ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInChunkTickRange; ++ ++ void updateRanges() { ++ long key = net.minecraft.server.MCUtil.getCoordinateKey(this.pos); ++ this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key); ++ this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); ++ } ++ // Paper end - optimise isOutsideOfRange ++ + public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +@@ -85,6 +97,7 @@ public class ChunkHolder { + this.queueLevel = this.oldTicketLevel; + this.setTicketLevel(level); + this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper ++ this.updateRanges(); // Paper - optimise isOutsideOfRange + } + + // Paper start +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c756a5be9 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -208,6 +208,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); + } + // Paper end - use distance map to optimise tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ // A note about the naming used here: ++ // Previously, mojang used a "spawn range" of 8 for controlling both ticking and ++ // mob spawn range. However, spigot makes the spawn range configurable by ++ // checking if the chunk is in the tick range (8) and the spawn range ++ // obviously this means a spawn range > 8 cannot be implemented ++ ++ // these maps are named after spigot's uses ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + + void addPlayerToDistanceMaps(ServerPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.getX()); +@@ -221,6 +232,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); + } + // Paper end - use distance map to optimise entity tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + } + + void removePlayerFromDistanceMaps(ServerPlayer player) { +@@ -229,6 +243,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerEntityTrackerTrackMaps[i].remove(player); + } + // Paper end - use distance map to optimise tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerMobSpawnMap.remove(player); ++ this.playerChunkTickRangeMap.remove(player); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + } + + void updateMaps(ServerPlayer player) { +@@ -243,6 +261,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); + } + // Paper end - use distance map to optimise entity tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + } + // Paper end + +@@ -274,7 +295,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); + this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); + this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); +- this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); ++ this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper + this.overworldDataStorage = supplier; + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper + this.setViewDistance(i); +@@ -318,6 +339,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); + } + // Paper end - use distance map to optimise entity tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerChunkTickRangeMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInChunkTickRange = newState; ++ } ++ }, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInChunkTickRange = newState; ++ } ++ }); ++ this.playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInMobSpawnRange = newState; ++ } ++ }, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInMobSpawnRange = newState; ++ } ++ }); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + } + + public void updatePlayerMobTypeMap(Entity entity) { +@@ -337,6 +390,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return entityPlayer.mobCounts[enumCreatureType.ordinal()]; + } + ++ private static double getDistanceSquaredFromChunk(ChunkPos chunkPos, Entity entity) { return euclideanDistanceSquared(chunkPos, entity); } // Paper - OBFHELPER + private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { + double d0 = (double) (pos.x * 16 + 8); + double d1 = (double) (pos.z * 16 + 8); +@@ -515,6 +569,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } else { + if (holder != null) { + holder.setTicketLevel(level); ++ holder.updateRanges(); // Paper - optimise isOutsideOfRange + } + + if (holder != null) { +@@ -1493,30 +1548,53 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return isOutsideOfRange(chunkcoordintpair, false); + } + +- boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) { +- int chunkRange = level.spigotConfig.mobSpawnRange; +- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; +- chunkRange = (chunkRange > 8) ? 8 : chunkRange; ++ // Paper start - optimise isOutsideOfRange ++ final boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) { ++ return this.isOutsideOfRange(this.getUpdatingChunkIfPresent(chunkcoordintpair.toLong()), chunkcoordintpair, reducedRange); ++ } + +- final int finalChunkRange = chunkRange; // Paper for lambda below +- //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event +- // Spigot end +- long i = chunkcoordintpair.toLong(); ++ final boolean isOutsideOfRange(ChunkHolder playerchunk, ChunkPos chunkcoordintpair, boolean reducedRange) { ++ // this function is so hot that removing the map lookup call can have an order of magnitude impact on its performance ++ // tested and confirmed via System.nanoTime() ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInRange = reducedRange ? playerchunk.playersInMobSpawnRange : playerchunk.playersInChunkTickRange; + +- return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { +- // Paper start - +- com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; +- double blockRange = 16384.0D; +- if (reducedRange) { +- event = entityplayer.playerNaturallySpawnedEvent; +- if (event == null || event.isCancelled()) return false; +- blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); +- } ++ if (playersInRange == null) { ++ return true; ++ } + +- return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot +- // Paper end +- }); ++ Object[] backingSet = playersInRange.getBackingSet(); ++ ++ if (reducedRange) { ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object raw = backingSet[i]; ++ if (!(raw instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer) raw; ++ // don't check spectator and whatnot, already handled by mob spawn map update ++ if (player.lastEntitySpawnRadiusSquared > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { ++ return false; // in range ++ } ++ } ++ } else { ++ final double range = (DistanceManager.MOB_SPAWN_RANGE * 16) * (DistanceManager.MOB_SPAWN_RANGE * 16); ++ // before spigot, mob spawn range was actually mob spawn range + tick range, but it was split ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object raw = backingSet[i]; ++ if (!(raw instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer) raw; ++ // don't check spectator and whatnot, already handled by mob spawn map update ++ if (range > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { ++ return false; // in range ++ } ++ } ++ } ++ // no players in range ++ return true; + } ++ // Paper end - optimise isOutsideOfRange + + private boolean skipPlayer(ServerPlayer player) { + return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5980d3467 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -37,7 +37,7 @@ public abstract class DistanceManager { + private final Long2ObjectMap> playersPerChunk = new Long2ObjectOpenHashMap(); + public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); + private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); +- private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); ++ public static final int MOB_SPAWN_RANGE = 8; // private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used + private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); + // Paper start use a queue, but still keep unique requirement + public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { +@@ -56,6 +56,8 @@ public abstract class DistanceManager { + private final Executor mainThreadExecutor; + private long ticketTickCounter; + ++ ChunkMap chunkMap; // Paper ++ + protected DistanceManager(Executor workerExecutor, Executor mainThreadExecutor) { + mainThreadExecutor.getClass(); + ProcessorHandle mailbox = ProcessorHandle.of("player ticket throttler", mainThreadExecutor::execute); +@@ -100,7 +102,7 @@ public abstract class DistanceManager { + protected abstract ChunkHolder updateChunkScheduling(long pos, int level, @Nullable ChunkHolder holder, int k); + + public boolean runAllUpdates(ChunkMap chunkStorage) { +- this.naturalSpawnChunkCounter.runAllUpdates(); ++ //this.f.a(); // Paper - no longer used + this.playerTicketManager.runAllUpdates(); + int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE); + boolean flag = i != 0; +@@ -236,7 +238,7 @@ public abstract class DistanceManager { + ((ObjectSet) this.playersPerChunk.computeIfAbsent(i, (j) -> { + return new ObjectOpenHashSet(); + })).add(player); +- this.naturalSpawnChunkCounter.update(i, 0, true); ++ //this.f.update(i, 0, true); // Paper - no longer used + this.playerTicketManager.update(i, 0, true); + } + +@@ -248,7 +250,7 @@ public abstract class DistanceManager { + if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully. + if (objectset == null || objectset.isEmpty()) { // Paper + this.playersPerChunk.remove(i); +- this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); ++ //this.f.update(i, Integer.MAX_VALUE, false); // Paper - no longer used + this.playerTicketManager.update(i, Integer.MAX_VALUE, false); + } + +@@ -272,13 +274,17 @@ public abstract class DistanceManager { + } + + public int getNaturalSpawnChunkCount() { +- this.naturalSpawnChunkCounter.runAllUpdates(); +- return this.naturalSpawnChunkCounter.chunks.size(); ++ // Paper start - use distance map to implement ++ // note: this is the spawn chunk count ++ return this.chunkMap.playerChunkTickRangeMap.size(); ++ // Paper end - use distance map to implement + } + + public boolean hasPlayersNearby(long i) { +- this.naturalSpawnChunkCounter.runAllUpdates(); +- return this.naturalSpawnChunkCounter.chunks.containsKey(i); ++ // Paper start - use distance map to implement ++ // note: this is the is spawn chunk method ++ return this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(i) != null; ++ // Paper end - use distance map to implement + } + + public String getDebugStatus() { +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 79fb63c40dd0543a6f629e78f390f23f34992ba1..52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -753,6 +753,37 @@ public class ServerChunkCache extends ChunkSource { + boolean flag1 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !level.players().isEmpty(); // CraftBukkit + + if (!flag) { ++ // Paper start - optimize isOutisdeRange ++ ChunkMap playerChunkMap = this.chunkMap; ++ for (ServerPlayer player : this.level.players) { ++ if (!player.affectsSpawning || player.isSpectator()) { ++ playerChunkMap.playerMobSpawnMap.remove(player); ++ continue; ++ } ++ ++ int viewDistance = this.chunkMap.getEffectiveViewDistance(); ++ ++ // copied and modified from isOutisdeRange ++ int chunkRange = level.spigotConfig.mobSpawnRange; ++ chunkRange = (chunkRange > viewDistance) ? (byte)viewDistance : chunkRange; ++ chunkRange = (chunkRange > DistanceManager.MOB_SPAWN_RANGE) ? DistanceManager.MOB_SPAWN_RANGE : chunkRange; ++ ++ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(player.getBukkitEntity(), (byte)chunkRange); ++ event.callEvent(); ++ if (event.isCancelled() || event.getSpawnRadius() < 0 || playerChunkMap.playerChunkTickRangeMap.getLastViewDistance(player) == -1) { ++ playerChunkMap.playerMobSpawnMap.remove(player); ++ continue; ++ } ++ ++ int range = Math.min(event.getSpawnRadius(), 32); // limit to max view distance ++ int chunkX = net.minecraft.server.MCUtil.getChunkCoordinate(player.getX()); ++ int chunkZ = net.minecraft.server.MCUtil.getChunkCoordinate(player.getZ()); ++ ++ playerChunkMap.playerMobSpawnMap.addOrUpdate(player, chunkX, chunkZ, range); ++ player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in isOutsideRange ++ player.playerNaturallySpawnedEvent = event; ++ } ++ // Paper end - optimize isOutisdeRange + this.level.getProfiler().push("pollingChunks"); + int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); + boolean flag2 = level.ticksPerAnimalSpawns != 0L && worlddata.getGameTime() % level.ticksPerAnimalSpawns == 0L; // CraftBukkit +@@ -782,15 +813,7 @@ public class ServerChunkCache extends ChunkSource { + this.level.getProfiler().pop(); + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper +- //Paper start - call player naturally spawn event +- int chunkRange = level.spigotConfig.mobSpawnRange; +- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; +- chunkRange = Math.min(chunkRange, 8); +- for (ServerPlayer entityPlayer : this.level.players()) { +- entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); +- entityPlayer.playerNaturallySpawnedEvent.callEvent(); +- }; +- // Paper end ++ // Paper - moved up + this.level.timings.chunkTicks.startTiming(); // Paper + final int[] chunksTicked = {0}; this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); +@@ -807,9 +830,9 @@ public class ServerChunkCache extends ChunkSource { + LevelChunk chunk = (LevelChunk) optional1.get(); + ChunkPos chunkcoordintpair = playerchunk.getPos(); + +- if (!this.chunkMap.noPlayersCloseForSpawning(chunkcoordintpair)) { ++ if (!this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange + chunk.setInhabitedTime(chunk.getInhabitedTime() + j); +- if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot ++ if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange + NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 24c508ade61a6ad90b0ef73cdc995f531ef18263..95f1f4727a8e2000931e6f36b862e3ad28334a69 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -247,6 +247,8 @@ public class ServerPlayer extends Player implements ContainerListener { + + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + ++ double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks ++ + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { + super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); + this.respawnDimension = Level.OVERWORLD; diff --git a/Remapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch b/Remapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch new file mode 100644 index 0000000000..e9e6a043fc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch @@ -0,0 +1,320 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 27 Apr 2020 04:05:38 -0700 +Subject: [PATCH] Stop copy-on-write operations for updating light data + +Causes huge memory allocations + gc issues + +diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java +index 9f33fa8f84d10f8f4089030074ad6c0d81269ce8..a1ad4d73ddaf6afe97a1f1ff7e0622b52fac8761 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java +@@ -10,7 +10,7 @@ import net.minecraft.world.level.chunk.LightChunkGetter; + public class BlockLightSectionStorage extends LayerLightSectionStorage { + + protected BlockLightSectionStorage(LightChunkGetter chunkProvider) { +- super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new Long2ObjectOpenHashMap())); ++ super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data + } + + @Override +@@ -23,13 +23,13 @@ public class BlockLightSectionStorage extends LayerLightSectionStorage { + +- public BlockDataLayerStorageMap(Long2ObjectOpenHashMap arrays) { +- super(arrays); ++ public BlockDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data ++ super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data + } + + @Override + public BlockLightSectionStorage.BlockDataLayerStorageMap copy() { +- return new BlockLightSectionStorage.BlockDataLayerStorageMap(this.map.clone()); ++ return new BlockDataLayerStorageMap(this.data, true); // Paper - avoid copying light data + } + } + } +diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +index 01ae1c811862f56317a90e3811fe2ef4b593695f..4c9041f1c1cb4b3ec114fbd0c5d4db50a6f2526d 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java ++++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +@@ -9,10 +9,23 @@ public abstract class DataLayerStorageMap> { + private final long[] lastSectionKeys = new long[2]; + private final DataLayer[] lastSections = new DataLayer[2]; + private boolean cacheEnabled; +- protected final Long2ObjectOpenHashMap map; +- +- protected DataLayerStorageMap(Long2ObjectOpenHashMap arrays) { +- this.map = arrays; ++ protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data ++ protected final boolean isVisible; // Paper - avoid copying light data ++ java.util.function.Function lookup; // Paper - faster branchless lookup ++ ++ // Paper start - avoid copying light data ++ protected DataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { ++ if (isVisible) { ++ data.performUpdatesLockMap(); ++ } ++ this.data = data; ++ this.isVisible = isVisible; ++ if (isVisible) { ++ lookup = data::getVisibleAsync; ++ } else { ++ lookup = data::getUpdating; ++ } ++ // Paper end - avoid copying light data + this.clearCache(); + this.cacheEnabled = true; + } +@@ -20,16 +33,17 @@ public abstract class DataLayerStorageMap> { + public abstract M copy(); + + public void copyDataLayer(long pos) { +- this.map.put(pos, ((DataLayer) this.map.get(pos)).copy()); ++ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data ++ this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data + this.clearCache(); + } + + public boolean hasLayer(long chunkPos) { +- return this.map.containsKey(chunkPos); ++ return lookup.apply(chunkPos) != null; // Paper - avoid copying light data + } + + @Nullable +- public DataLayer getLayer(long chunkPos) { ++ public final DataLayer getLayer(long chunkPos) { // Paper - final + if (this.cacheEnabled) { + for (int j = 0; j < 2; ++j) { + if (chunkPos == this.lastSectionKeys[j]) { +@@ -38,7 +52,7 @@ public abstract class DataLayerStorageMap> { + } + } + +- DataLayer nibblearray = (DataLayer) this.map.get(chunkPos); ++ DataLayer nibblearray = lookup.apply(chunkPos); // Paper - avoid copying light data + + if (nibblearray == null) { + return null; +@@ -59,11 +73,13 @@ public abstract class DataLayerStorageMap> { + + @Nullable + public DataLayer removeLayer(long chunkPos) { +- return (DataLayer) this.map.remove(chunkPos); ++ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data ++ return (DataLayer) this.data.queueRemove(chunkPos); // Paper - avoid copying light data + } + + public void setLayer(long pos, DataLayer data) { +- this.map.put(pos, data); ++ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data ++ this.data.queueUpdate(pos, data); // Paper - avoid copying light data + } + + public void clearCache() { +@@ -71,7 +87,6 @@ public abstract class DataLayerStorageMap> { + this.lastSectionKeys[i] = Long.MAX_VALUE; + this.lastSections[i] = null; + } +- + } + + public void disableCache() { +diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +index 45be10a0d7c26e4b6e5738ba994ce343265210f5..177dae992d13674bb285a60b8427df9ea843dc99 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +@@ -26,8 +26,8 @@ public abstract class LayerLightSectionStorage> + protected final LongSet dataSectionSet = new LongOpenHashSet(); + protected final LongSet toMarkNoData = new LongOpenHashSet(); + protected final LongSet toMarkData = new LongOpenHashSet(); +- protected volatile M visibleSectionData; +- protected final M updatingSectionData; ++ protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change ++ protected final M updatingSectionData; // Paper - diff on change, should be "updating" + protected final LongSet changedSections = new LongOpenHashSet(); + protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet(); + protected final Long2ObjectMap queuedSections = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); +@@ -41,8 +41,8 @@ public abstract class LayerLightSectionStorage> + this.layer = lightType; + this.chunkSource = chunkProvider; + this.updatingSectionData = lightData; +- this.visibleSectionData = lightData.copy(); +- this.visibleSectionData.disableCache(); ++ this.e_visible = lightData.copy(); // Paper - avoid copying light data ++ this.e_visible.disableCache(); // Paper - avoid copying light data + } + + protected boolean storingLightForSection(long sectionPos) { +@@ -51,7 +51,15 @@ public abstract class LayerLightSectionStorage> + + @Nullable + protected DataLayer getDataLayer(long sectionPos, boolean cached) { +- return this.getDataLayer(cached ? this.updatingSectionData : this.visibleSectionData, sectionPos); ++ // Paper start - avoid copying light data ++ if (cached) { ++ return this.getDataLayer(this.updatingSectionData, sectionPos); ++ } else { ++ synchronized (this.visibleUpdateLock) { ++ return this.getDataLayer(this.e_visible, sectionPos); ++ } ++ } ++ // Paper end - avoid copying light data + } + + @Nullable +@@ -364,10 +372,12 @@ public abstract class LayerLightSectionStorage> + + protected void swapSectionMap() { + if (!this.changedSections.isEmpty()) { ++ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data + M m0 = this.updatingSectionData.copy(); + + m0.disableCache(); +- this.visibleSectionData = m0; ++ this.e_visible = m0; // Paper - avoid copying light data ++ } // Paper - avoid copying light data + this.changedSections.clear(); + } + +diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +index c304637ae8f80c65b58e8ba8a27609b532bb1184..410fcfa8c01b7e3d3e3829ebdb92a11badff16ea 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +@@ -23,15 +23,16 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data + } + + @Override + protected int getLightValue(long blockPos) { + long j = SectionPos.blockToSection(blockPos); + int k = SectionPos.y(j); +- SkyLightSectionStorage.SkyDataLayerStorageMap lightenginestoragesky_a = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.visibleSectionData; +- int l = lightenginestoragesky_a.topSections.get(SectionPos.getZeroNode(j)); ++ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data ++ SkyLightSectionStorage.SkyDataLayerStorageMap lightenginestoragesky_a = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.e_visible; // Paper - avoid copying light data - must be after lock acquire ++ int l = lightenginestoragesky_a.otherData.getVisibleAsync(SectionPos.getZeroNode(j)); // Paper - avoid copying light data + + if (l != lightenginestoragesky_a.currentLowestY && k < l) { + DataLayer nibblearray = this.getDataLayer(lightenginestoragesky_a, j); // Paper - decompile fix +@@ -52,6 +53,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage j) { + ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY = j; +- ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.defaultReturnValue(((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY); ++ ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.queueDefaultReturnValue(((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY); // Paper - avoid copying light data + } + + long k = SectionPos.getZeroNode(sectionPos); +- int l = ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.get(k); ++ int l = ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.getUpdating(k); // Paper - avoid copying light data + + if (l < j + 1) { +- ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.put(k, j + 1); ++ ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.queueUpdate(k, j + 1); // Paper - avoid copying light data + if (this.columnsWithSkySources.contains(k)) { + this.queueAddSource(sectionPos); + if (l > ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY) { +@@ -107,7 +109,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage= k; + } +@@ -327,18 +329,21 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage { + + private int currentLowestY; +- private final Long2IntOpenHashMap topSections; +- +- public SkyDataLayerStorageMap(Long2ObjectOpenHashMap arrays, Long2IntOpenHashMap columnToTopSection, int minSectionY) { +- super(arrays); +- this.topSections = columnToTopSection; +- columnToTopSection.defaultReturnValue(minSectionY); +- this.currentLowestY = minSectionY; ++ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data ++ ++ // Paper start - avoid copying light data ++ public SkyDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData, int i, boolean isVisible) { ++ super(data, isVisible); ++ this.otherData = otherData; ++ otherData.queueDefaultReturnValue(i); ++ // Paper end - avoid copying light data ++ this.currentLowestY = i; + } + + @Override + public SkyLightSectionStorage.SkyDataLayerStorageMap copy() { +- return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.map.clone(), this.topSections.clone(), this.currentLowestY); ++ this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data ++ return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.data, this.otherData, this.currentLowestY, true); // Paper - avoid copying light data + } + } + } diff --git a/Remapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch b/Remapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch new file mode 100644 index 0000000000..9fee42c2d0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch @@ -0,0 +1,819 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 5 May 2020 21:23:34 -0700 +Subject: [PATCH] No-Tick view distance implementation + +Implements world view distance getters/setters + +Per-Player is absent due to difficulty of maintaining +the diff required to make it happen. + +diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java +index 5bcf9cefc29eb20e2cfbfb49e2b2662ec394a87e..a696474b4bd0e32a26dadfbc1257580ee596f0c0 100644 +--- a/src/main/java/co/aikar/timings/TimingsExport.java ++++ b/src/main/java/co/aikar/timings/TimingsExport.java +@@ -156,7 +156,8 @@ public class TimingsExport extends Thread { + pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { + return pair(rule, world.getWorld().getGameRuleValue(rule)); + })), +- pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) ++ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()), ++ pair("notick-viewdistance", world.getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance()) + )); + })); + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 46ac6d91422423f1e03b86d3efa3241f2599000d..6463d3e4837d032a35654a035f42b8a805e0e286 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -632,4 +632,9 @@ public class PaperWorldConfig { + phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); + phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); + } ++ ++ public int noTickViewDistance; ++ private void viewDistance() { ++ this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 9abef8550a89df5e15ac28de1a5549d064f29122..d18497a33dc53f6b465e659967bf8c98731c46c0 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -638,7 +638,8 @@ public final class MCUtil { + }); + + worldData.addProperty("name", world.getWorld().getName()); +- worldData.addProperty("view-distance", world.spigotConfig.viewDistance); ++ worldData.addProperty("view-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance()); ++ worldData.addProperty("no-view-distance", world.getChunkSource().chunkMap.getRawNoTickViewDistance()); + worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); + worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); + worldData.addProperty("visible-chunk-count", visibleChunks.size()); +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 0147798c0285f64b8d767dfb2709d92f66ac72ef..9ebcfca10071cc42d4f1df02c25de5042c065f38 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -81,6 +81,18 @@ public class ChunkHolder { + } + // Paper end - optimise isOutsideOfRange + ++ // Paper start - no-tick view distance ++ public final LevelChunk getSendingChunk() { ++ // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used ++ // in Chunk's neighbour callback ++ LevelChunk ret = this.chunkMap.level.getChunkSource().getChunkAtIfLoadedImmediately(this.pos.x, this.pos.z); ++ if (ret != null && ret.areNeighboursLoaded(1)) { ++ return ret; ++ } ++ return null; ++ } ++ // Paper end - no-tick view distance ++ + public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +@@ -240,7 +252,7 @@ public class ChunkHolder { + } + + public void blockChanged(BlockPos blockposition) { +- LevelChunk chunk = this.getTickingChunk(); ++ LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { + byte b0 = (byte) SectionPos.blockToSectionCoord(blockposition.getY()); +@@ -256,7 +268,7 @@ public class ChunkHolder { + } + + public void sectionLightChanged(LightLayer type, int y) { +- LevelChunk chunk = this.getTickingChunk(); ++ LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { + chunk.setUnsaved(true); +@@ -338,9 +350,48 @@ public class ChunkHolder { + } + + private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { +- this.playerProvider.getPlayers(this.pos, onlyOnWatchDistanceEdge).forEach((entityplayer) -> { +- entityplayer.connection.send(packet); +- }); ++ // Paper start - per player view distance ++ // there can be potential desync with player's last mapped section and the view distance map, so use the ++ // view distance map here. ++ com.destroystokyo.paper.util.misc.PlayerAreaMap viewDistanceMap = this.chunkMap.playerViewDistanceBroadcastMap; ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = viewDistanceMap.getObjectsInRange(this.pos); ++ if (players == null) { ++ return; ++ } ++ ++ if (onlyOnWatchDistanceEdge) { // flag -> border only ++ Object[] backingSet = players.getBackingSet(); ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ ++ int viewDistance = viewDistanceMap.getLastViewDistance(player); ++ long lastPosition = viewDistanceMap.getLastCoordinate(player); ++ ++ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - this.pos.x); ++ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - this.pos.z); ++ ++ if (Math.max(distX, distZ) == viewDistance) { ++ player.connection.send(packet); ++ } ++ } ++ } else { ++ Object[] backingSet = players.getBackingSet(); ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ player.connection.send(packet); ++ } ++ } ++ ++ return; ++ // Paper end - per player view distance + } + + public CompletableFuture> getOrScheduleFuture(ChunkStatus targetStatus, ChunkMap chunkStorage) { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d3956c5f2efb 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -57,12 +57,14 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; + import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; + import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; ++import net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket; + import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; + import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; + import net.minecraft.network.protocol.game.DebugPackets; + import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.progress.ChunkProgressListener; ++import net.minecraft.server.network.ServerGamePacketListenerImpl; + import net.minecraft.util.CsvOutput; + import net.minecraft.util.Mth; + import net.minecraft.util.profiling.ProfilerFiller; +@@ -144,7 +146,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private boolean modified; + private final ChunkTaskPriorityQueueSorter queueSorter; + private final ProcessorHandle> worldgenMailbox; +- private final ProcessorHandle> mainThreadMailbox; ++ public final ProcessorHandle> mainThreadMailbox; // Paper - private -> public ++ // Paper start ++ final ProcessorHandle> mailboxLight; ++ public void addLightTask(ChunkHolder playerchunk, Runnable run) { ++ this.mailboxLight.tell(ChunkTaskPriorityQueueSorter.message(playerchunk, run)); ++ } ++ // Paper end + public final ChunkProgressListener progressListener; + public final ChunkMap.ChunkDistanceManager distanceManager; public final DistanceManager getChunkDistanceManager() { return this.distanceManager; } // Paper - OBFHELPER + private final AtomicInteger tickingGenerated; +@@ -219,6 +227,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick + public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ int noTickViewDistance; ++ public final int getRawNoTickViewDistance() { ++ return this.noTickViewDistance; ++ } ++ public final int getEffectiveNoTickViewDistance() { ++ return this.noTickViewDistance == -1 ? this.getEffectiveViewDistance() : this.noTickViewDistance; ++ } ++ public final int getLoadViewDistance() { ++ return Math.max(this.getEffectiveViewDistance(), this.getEffectiveNoTickViewDistance()); ++ } ++ ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceBroadcastMap; ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap; ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap; ++ // Paper end - no-tick view distance + + void addPlayerToDistanceMaps(ServerPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.getX()); +@@ -235,6 +259,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper start - optimise PlayerChunkMap#isOutsideRange + this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ int effectiveTickViewDistance = this.getEffectiveViewDistance(); ++ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); ++ ++ if (!this.cannotLoadChunks(player)) { ++ this.playerViewDistanceTickMap.add(player, chunkX, chunkZ, effectiveTickViewDistance); ++ this.playerViewDistanceNoTickMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) ++ } ++ ++ player.needsChunkCenterUpdate = true; ++ this.playerViewDistanceBroadcastMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured ++ player.needsChunkCenterUpdate = false; ++ // Paper end - no-tick view distance + } + + void removePlayerFromDistanceMaps(ServerPlayer player) { +@@ -247,6 +284,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerMobSpawnMap.remove(player); + this.playerChunkTickRangeMap.remove(player); + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ this.playerViewDistanceBroadcastMap.remove(player); ++ this.playerViewDistanceTickMap.remove(player); ++ this.playerViewDistanceNoTickMap.remove(player); ++ // Paper end - no-tick view distance + } + + void updateMaps(ServerPlayer player) { +@@ -264,6 +306,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper start - optimise PlayerChunkMap#isOutsideRange + this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ int effectiveTickViewDistance = this.getEffectiveViewDistance(); ++ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); ++ ++ if (!this.cannotLoadChunks(player)) { ++ this.playerViewDistanceTickMap.update(player, chunkX, chunkZ, effectiveTickViewDistance); ++ this.playerViewDistanceNoTickMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) ++ } ++ ++ player.needsChunkCenterUpdate = true; ++ this.playerViewDistanceBroadcastMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured ++ player.needsChunkCenterUpdate = false; ++ // Paper end - no-tick view distance + } + // Paper end + +@@ -371,6 +426,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + }); + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); ++ this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ if (newState.size() != 1) { ++ return; ++ } ++ LevelChunk chunk = ChunkMap.this.level.getChunkSource().getChunkAtIfLoadedMainThreadNoCache(rangeX, rangeZ); ++ if (chunk == null || !chunk.areNeighboursLoaded(2)) { ++ return; ++ } ++ ++ ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); ++ ChunkMap.this.level.getChunkSource().addTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update ++ }, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ if (newState != null) { ++ return; ++ } ++ ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); ++ ChunkMap.this.level.getChunkSource().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update ++ }); ++ this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); ++ this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ if (player.needsChunkCenterUpdate) { ++ player.needsChunkCenterUpdate = false; ++ player.connection.send(new ClientboundSetChunkCacheCenterPacket(currPosX, currPosZ)); ++ } ++ ChunkMap.this.updateChunkTracking(player, new ChunkPos(rangeX, rangeZ), new Packet[2], false, true); // unloaded, loaded ++ }, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkMap.this.updateChunkTracking(player, new ChunkPos(rangeX, rangeZ), null, true, false); // unloaded, loaded ++ }); ++ // Paper end - no-tick view distance + } + + public void updatePlayerMobTypeMap(Entity entity) { +@@ -1199,15 +1293,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + completablefuture1.thenAcceptAsync((either) -> { + either.mapLeft((chunk) -> { + this.tickingGenerated.getAndIncrement(); +- Packet[] apacket = new Packet[2]; +- +- this.getPlayers(chunkcoordintpair, false).forEach((entityplayer) -> { +- this.playerLoadedChunk(entityplayer, apacket, chunk); +- }); ++ // Paper - no-tick view distance - moved to Chunk neighbour update + return Either.left(chunk); + }); + }, (runnable) -> { +- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); ++ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); // Paper - diff on change, this is the scheduling method copied in Chunk used to schedule chunk broadcasts (on change it needs to be copied again) + }); + return completablefuture1; + } +@@ -1302,32 +1392,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + } + +- protected void setViewDistance(int watchDistance) { +- int j = Mth.clamp(watchDistance + 1, 3, 33); ++ public void setViewDistance(int watchDistance) { // Paper - public ++ int j = Mth.clamp(watchDistance + 1, 3, 33); // Paper - diff on change, these make the lower view distance limit 2 and the upper 32 + + if (j != this.viewDistance) { + int k = this.viewDistance; + + this.viewDistance = j; +- this.distanceManager.updatePlayerTickets(this.viewDistance); +- ObjectIterator objectiterator = this.updatingChunkMap.values().iterator(); ++ this.setNoTickViewDistance(this.getRawNoTickViewDistance()); //Paper - no-tick view distance - propagate changes to no-tick, which does the actual chunk loading/sending ++ } + +- while (objectiterator.hasNext()) { +- ChunkHolder playerchunk = (ChunkHolder) objectiterator.next(); +- ChunkPos chunkcoordintpair = playerchunk.getPos(); +- Packet[] apacket = new Packet[2]; ++ } + +- this.getPlayers(chunkcoordintpair, false).forEach((entityplayer) -> { +- int l = checkerboardDistance(chunkcoordintpair, entityplayer, true); +- boolean flag = l <= k; +- boolean flag1 = l <= this.viewDistance; ++ // Paper start - no-tick view distance ++ public final void setNoTickViewDistance(int viewDistance) { ++ viewDistance = viewDistance == -1 ? -1 : Mth.clamp(viewDistance, 2, 32); + +- this.updateChunkTracking(entityplayer, chunkcoordintpair, apacket, flag, flag1); +- }); ++ this.noTickViewDistance = viewDistance; ++ int loadViewDistance = this.getLoadViewDistance(); ++ this.distanceManager.setNoTickViewDistance(loadViewDistance + 2 + 2); // add 2 to account for the change to 31 -> 33 tickets // see notes in the distance map updating for the other + 2 ++ ++ if (this.level != null && this.level.players != null) { // this can be called from constructor, where these aren't set ++ for (ServerPlayer player : this.level.players) { ++ ServerGamePacketListenerImpl connection = player.connection; ++ if (connection != null) { ++ // moved in from PlayerList ++ connection.send(new ClientboundSetChunkCacheRadiusPacket(loadViewDistance)); ++ } ++ this.updateMaps(player); + } + } +- + } ++ // Paper end - no-tick view distance + + protected void updateChunkTracking(ServerPlayer player, ChunkPos pos, Packet[] packets, boolean withinMaxWatchDistance, boolean withinViewDistance) { + if (player.level == this.level) { +@@ -1335,7 +1431,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.toLong()); + + if (playerchunk != null) { +- LevelChunk chunk = playerchunk.getTickingChunk(); ++ LevelChunk chunk = playerchunk.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { + this.playerLoadedChunk(player, packets, chunk); +@@ -1596,6 +1692,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + // Paper end - optimise isOutsideOfRange + ++ private boolean cannotLoadChunks(ServerPlayer entityplayer) { return this.skipPlayer(entityplayer); } // Paper - OBFHELPER + private boolean skipPlayer(ServerPlayer player) { + return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); + } +@@ -1623,13 +1720,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.removePlayerFromDistanceMaps(player); // Paper - distance maps + } + +- for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { +- for (int l = j - this.viewDistance; l <= j + this.viewDistance; ++l) { +- ChunkPos chunkcoordintpair = new ChunkPos(k, l); +- +- this.updateChunkTracking(player, chunkcoordintpair, new Packet[2], !added, added); +- } +- } ++ // Paper - broadcast view distance map handles this (see remove/add calls above) + + } + +@@ -1637,7 +1728,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + SectionPos sectionposition = SectionPos.of((Entity) entityplayer); + + entityplayer.setLastSectionPos(sectionposition); +- entityplayer.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); ++ // Paper - distance map handles this now + return sectionposition; + } + +@@ -1682,6 +1773,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + int k1; + int l1; + ++ /* // Paper start - replaced by distance map + if (Math.abs(i1 - i) <= this.viewDistance * 2 && Math.abs(j1 - j) <= this.viewDistance * 2) { + k1 = Math.min(i, i1) - this.viewDistance; + l1 = Math.min(j, j1) - this.viewDistance; +@@ -1690,36 +1782,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + for (int k2 = k1; k2 <= i2; ++k2) { + for (int l2 = l1; l2 <= j2; ++l2) { +- ChunkPos chunkcoordintpair = new ChunkPos(k2, l2); +- boolean flag3 = checkerboardDistance(chunkcoordintpair, i1, j1) <= this.viewDistance; +- boolean flag4 = checkerboardDistance(chunkcoordintpair, i, j) <= this.viewDistance; ++ ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k2, l2); ++ boolean flag3 = a(chunkcoordintpair, i1, j1) <= this.viewDistance; ++ boolean flag4 = a(chunkcoordintpair, i, j) <= this.viewDistance; + +- this.updateChunkTracking(player, chunkcoordintpair, new Packet[2], flag3, flag4); ++ this.sendChunk(entityplayer, chunkcoordintpair, new Packet[2], flag3, flag4); + } + } + } else { +- ChunkPos chunkcoordintpair1; ++ ChunkCoordIntPair chunkcoordintpair1; + boolean flag5; + boolean flag6; + + for (k1 = i1 - this.viewDistance; k1 <= i1 + this.viewDistance; ++k1) { + for (l1 = j1 - this.viewDistance; l1 <= j1 + this.viewDistance; ++l1) { +- chunkcoordintpair1 = new ChunkPos(k1, l1); ++ chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1); + flag5 = true; + flag6 = false; +- this.updateChunkTracking(player, chunkcoordintpair1, new Packet[2], true, false); ++ this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], true, false); + } + } + + for (k1 = i - this.viewDistance; k1 <= i + this.viewDistance; ++k1) { + for (l1 = j - this.viewDistance; l1 <= j + this.viewDistance; ++l1) { +- chunkcoordintpair1 = new ChunkPos(k1, l1); ++ chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1); + flag5 = false; + flag6 = true; +- this.updateChunkTracking(player, chunkcoordintpair1, new Packet[2], false, true); ++ this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], false, true); + } + } +- } ++ }*/ // Paper end - replaced by distance map + + this.updateMaps(player); // Paper - distance maps + +@@ -1727,11 +1819,46 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + @Override + public Stream getPlayers(ChunkPos chunkPos, boolean onlyOnWatchDistanceEdge) { +- return this.playerMap.a(chunkPos.toLong()).filter((entityplayer) -> { +- int i = b(chunkcoordintpair, entityplayer, true); ++ // Paper start - per player view distance ++ // there can be potential desync with player's last mapped section and the view distance map, so use the ++ // view distance map here. ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = this.playerViewDistanceBroadcastMap.getObjectsInRange(chunkPos); + +- return i > this.viewDistance ? false : !flag || i == this.viewDistance; +- }); ++ if (inRange == null) { ++ return Stream.empty(); ++ } ++ // all current cases are inlined so we wont hit this code, it's just in case plugins or future updates use it ++ List players = new java.util.ArrayList<>(); ++ Object[] backingSet = inRange.getBackingSet(); ++ ++ if (onlyOnWatchDistanceEdge) { // flag -> border only ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ int viewDistance = this.playerViewDistanceBroadcastMap.getLastViewDistance(player); ++ long lastPosition = this.playerViewDistanceBroadcastMap.getLastCoordinate(player); ++ ++ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - chunkPos.x); ++ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - chunkPos.z); ++ if (Math.max(distX, distZ) == viewDistance) { ++ players.add(player); ++ } ++ } ++ } else { ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ players.add(player); ++ } ++ } ++ return players.stream(); ++ // Paper end - per player view distance + } + + public void addEntity(Entity entity) { // Paper - protected -> public +@@ -1889,7 +2016,48 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + } + +- private final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER ++ // Paper start ++ private static int getLightMask(final LevelChunk chunk) { ++ final ChunkSection[] chunkSections = chunk.getSections(); ++ int mask = 0; ++ ++ for (int i = 0; i < chunkSections.length; ++i) { ++ /* ++ ++ ++Lightmasks have 18 bits, from the -1 (void) section until the 17th (air) section. ++Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. ++ ++ */ ++ mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; ++ } ++ ++ return mask; ++ } ++ ++ private static int getCeilingLightMask(final LevelChunk chunk) { ++ int mask = getLightMask(chunk); ++ ++ /* ++ It is similar to get highest bit, it would turn an 001010 into an 001111 so basically the highest bit and all below. ++ We then invert this, so we'd have 110000 and compare that to the "main" chunk. ++ This is because the bug only appears when the current chunks lightmaps are higher than those of the neighbors, thus we can omit sending neighbors which are lower than the current chunks lights. ++ ++ so TLDR is that getCeilingLightMask returns a light mask with all bits set below the highest affected section. We could also count the number of leading zeros and invert them, somehow. ++ @TODO: Implement Leafs suggestion ++ either use Integer#numberOfLeadingZeros or document what this bithack is supposed to be doing then ++ */ ++ mask |= mask >> 1; ++ mask |= mask >> 2; ++ mask |= mask >> 4; ++ mask |= mask >> 8; ++ mask |= mask >> 16; ++ ++ return mask; ++ } ++ // Paper end ++ ++ public final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER + private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { + if (packets[0] == null) { + packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass +@@ -2075,7 +2243,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkPos chunkcoordintpair = new ChunkPos(this.entity.xChunk, this.entity.zChunk); + ChunkHolder playerchunk = ChunkMap.this.getVisibleChunkIfPresent(chunkcoordintpair.toLong()); + +- if (playerchunk != null && playerchunk.getTickingChunk() != null) { ++ if (playerchunk != null && playerchunk.getSendingChunk() != null) { // Paper - no-tick view distance + flag1 = ChunkMap.checkerboardDistance(chunkcoordintpair, player, false) <= ChunkMap.this.viewDistance; + } + } +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 91c672531087430c47365657a3219ab5980d3467..c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -269,8 +269,8 @@ public abstract class DistanceManager { + return s; + } + +- protected void updatePlayerTickets(int viewDistance) { +- this.playerTicketManager.updateViewDistance(viewDistance); ++ protected void setNoTickViewDistance(int i) { // Paper - force abi breakage on usage change ++ this.playerTicketManager.updateViewDistance(i); + } + + public int getNaturalSpawnChunkCount() { +@@ -388,7 +388,7 @@ public abstract class DistanceManager { + + private void onLevelChange(long pos, int distance, boolean oldWithinViewDistance, boolean withinViewDistance) { + if (oldWithinViewDistance != withinViewDistance) { +- Ticket ticket = new Ticket<>(TicketType.PLAYER, DistanceManager.PLAYER_TICKET_LEVEL, new ChunkPos(pos)); ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkPos(pos)); // Paper - no-tick view distance + + if (withinViewDistance) { + DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 95f1f4727a8e2000931e6f36b862e3ad28334a69..8e4cef60b760be385df81a74834d026f856a78c5 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -249,6 +249,8 @@ public class ServerPlayer extends Player implements ContainerListener { + + double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks + ++ boolean needsChunkCenterUpdate; // Paper - no-tick view distance ++ + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { + super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); + this.respawnDimension = Level.OVERWORLD; +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index ffc8c9ee8b1768dd809189858ee45658fb9bf1c5..8e00747c1a717836d12a43aa48d667bf801167b0 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -250,7 +250,7 @@ public abstract class PlayerList { + boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); + + // Spigot - view distance +- playerconnection.send(new ClientboundLoginPacket(player.getId(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), worlddata.isHardcore(), this.server.levelKeys(), this.registryHolder, worldserver1.dimensionType(), worldserver1.dimension(), this.getMaxPlayers(), worldserver1.spigotConfig.viewDistance, flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat())); ++ playerconnection.send(new ClientboundLoginPacket(player.getId(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), worlddata.isHardcore(), this.server.levelKeys(), this.registryHolder, worldserver1.dimensionType(), worldserver1.dimension(), this.getMaxPlayers(), worldserver1.getChunkSource().chunkMap.getLoadViewDistance(), flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat())); // Paper - no-tick view distance + player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit + playerconnection.send(new ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.BRAND, (new FriendlyByteBuf(Unpooled.buffer())).writeUtf(this.getServer().getServerModName()))); + playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); +@@ -904,7 +904,7 @@ public abstract class PlayerList { + // CraftBukkit start + LevelData worlddata = worldserver1.getLevelData(); + entityplayer1.connection.send(new ClientboundRespawnPacket(worldserver1.dimensionType(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), entityplayer1.gameMode.getGameModeForPlayer(), entityplayer1.gameMode.getPreviousGameModeForPlayer(), worldserver1.isDebug(), worldserver1.isFlat(), flag)); +- entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.spigotConfig.viewDistance)); // Spigot ++ entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.getChunkSource().chunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance + entityplayer1.setLevel(worldserver1); + entityplayer1.removed = false; + entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.yRot, entityplayer1.xRot)); +@@ -1372,7 +1372,7 @@ public abstract class PlayerList { + + public void setViewDistance(int viewDistance) { + this.viewDistance = viewDistance; +- this.broadcastAll(new ClientboundSetChunkCacheRadiusPacket(viewDistance)); ++ //this.sendAll(new PacketPlayOutViewDistance(i)); // Paper - move into setViewDistance + Iterator iterator = this.server.getAllLevels().iterator(); + + while (iterator.hasNext()) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 5860e7866724abd35bde2a5710d9c92799e5de67..67ab681a9c9157a420de5fd872bde1fc0de24561 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -525,8 +525,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); + } + +- if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement ++ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement // Paper - diff on change, see below + this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i); ++ // Paper start - per player view distance - allow block updates for non-ticking chunks in player view distance ++ // if copied from above ++ } else if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || ((ServerLevel)this).getChunkSource().chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.getCoordinateKey(blockposition)) != null)) { ++ ((ServerLevel)this).getChunkSource().blockChanged(blockposition); ++ // Paper end - per player view distance + } + + if ((i & 1) != 0) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 8a14bdda4a408ec1e2b51efeb35467835f62b42c..dbea2a4370ccf24a5084cdabeecbc81f206e910a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -27,9 +27,14 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.network.protocol.Packet; + import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.ChunkTaskPriorityQueueSorter; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.TicketType; + import net.minecraft.util.Mth; + import net.minecraft.world.Container; + import net.minecraft.world.entity.Entity; +@@ -242,7 +247,51 @@ public class LevelChunk implements ChunkAccess { + } + + protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { ++ // Paper start - no-tick view distance ++ ServerChunkCache chunkProviderServer = ((ServerLevel)this.world).getChunkSource(); ++ ChunkMap chunkMap = chunkProviderServer.chunkMap; ++ // this code handles the addition of ticking tickets - the distance map handles the removal ++ if (!areNeighboursLoaded(bitsetBefore, 2) && areNeighboursLoaded(bitsetAfter, 2)) { ++ if (chunkMap.playerViewDistanceTickMap.getObjectsInRange(this.coordinateKey) != null) { ++ // now we're ready for entity ticking ++ chunkProviderServer.mainThreadProcessor.execute(() -> { ++ // double check that this condition still holds. ++ if (LevelChunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(LevelChunk.this.coordinateKey) != null) { ++ chunkProviderServer.addTicketAtLevel(TicketType.PLAYER, LevelChunk.this.chunkPos, 31, LevelChunk.this.chunkPos); // 31 -> entity ticking, TODO check on update ++ } ++ }); ++ } ++ } + ++ // this code handles the chunk sending ++ if (!areNeighboursLoaded(bitsetBefore, 1) && areNeighboursLoaded(bitsetAfter, 1)) { ++ if (chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(this.coordinateKey) != null) { ++ // now we're ready to send ++ chunkMap.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(chunkMap.getUpdatingChunkIfPresent(this.coordinateKey), (() -> { // Copied frm PlayerChunkMap ++ // double check that this condition still holds. ++ if (!LevelChunk.this.areNeighboursLoaded(1)) { ++ return; ++ } ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(LevelChunk.this.coordinateKey); ++ if (inRange == null) { ++ return; ++ } ++ ++ // broadcast ++ Object[] backingSet = inRange.getBackingSet(); ++ Packet[] chunkPackets = new Packet[2]; ++ for (int index = 0, len = backingSet.length; index < len; ++index) { ++ Object temp = backingSet[index]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ chunkMap.sendChunk(player, chunkPackets, LevelChunk.this); ++ } ++ }))); ++ } ++ } ++ // Paper end - no-tick view distance + } + + public final boolean isAnyNeighborsLoaded() { +@@ -1131,7 +1180,7 @@ public class LevelChunk implements ChunkAccess { + BlockState iblockdata = this.getBlockState(blockposition); + BlockState iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, (LevelAccessor) this.world, blockposition); + +- this.world.setBlock(blockposition, iblockdata1, 20); ++ this.world.setBlock(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here + } + + this.postProcessing[i].clear(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 1a839242e359fa32f32d0e571c6e918ac39642e9..4fc44390f432ef13c9952aa22bbb29bc8bf47975 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -31,6 +31,7 @@ import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; + import net.minecraft.network.protocol.game.ClientboundSetTimePacket; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.DistanceManager; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.Ticket; +@@ -2532,10 +2533,39 @@ public class CraftWorld implements World { + // Spigot start + @Override + public int getViewDistance() { +- return world.spigotConfig.viewDistance; ++ return getHandle().getChunkSource().chunkMap.getEffectiveViewDistance(); // Paper - no-tick view distance + } + // Spigot end + ++ // Paper start - per player view distance ++ @Override ++ public void setViewDistance(int viewDistance) { ++ if (viewDistance < 2 || viewDistance > 32) { ++ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); ++ } ++ ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; ++ if (viewDistance != chunkMap.getEffectiveViewDistance()) { ++ chunkMap.setViewDistance(viewDistance); ++ } ++ } ++ ++ @Override ++ public int getNoTickViewDistance() { ++ return getHandle().getChunkSource().chunkMap.getEffectiveNoTickViewDistance(); ++ } ++ ++ @Override ++ public void setNoTickViewDistance(int viewDistance) { ++ if ((viewDistance < 2 || viewDistance > 32) && viewDistance != -1) { ++ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); ++ } ++ ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; ++ if (viewDistance != chunkMap.getRawNoTickViewDistance()) { ++ chunkMap.setNoTickViewDistance(viewDistance); ++ } ++ } ++ // Paper end - per player view distance ++ + // Spigot start + private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot() + { +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 8cbafad53d20366a36493f22160c4fa3e4ac3eaf..20d5da61fc0594e86c68ea8fb5ebe5517f27f126 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -4,6 +4,7 @@ import java.util.Collection; + import net.minecraft.core.BlockPos; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.FlyingMob; +@@ -192,7 +193,7 @@ public class ActivationRange + maxRange = Math.max( maxRange, waterActivationRange ); + maxRange = Math.max( maxRange, villagerActivationRange ); + // Paper end +- maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); ++ maxRange = Math.min( ( ((ServerLevel)world).getChunkSource().chunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance + + for ( Player player : world.players() ) + { diff --git a/Remapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch b/Remapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch new file mode 100644 index 0000000000..771a37b8cf --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch @@ -0,0 +1,155 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 22 Apr 2020 23:29:20 +0200 +Subject: [PATCH] Add villager reputation API + + +diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c6072615e95bf51c83b2f728fc3288a7043a89af +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java +@@ -0,0 +1,11 @@ ++package com.destroystokyo.paper.entity.villager; ++// Must have own package due to package-level constructor. ++ ++import Reputation; ++ ++public final class ReputationConstructor { ++ // Abuse the package-level constructor. ++ public static Reputation construct(int[] values) { ++ return new Reputation(values); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +index c4ece3ac4863067b12c10772debd1b1454bec5b4..0204f05d989d45c0848f810d1953adf0992ce3c2 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +@@ -27,7 +27,7 @@ import net.minecraft.core.SerializableUUID; + + public class GossipContainer { + +- private final Map gossips = Maps.newHashMap(); ++ private final Map gossips = Maps.newHashMap(); public Map getReputations() { return this.gossips; } // Paper - add getter for reputations + + public GossipContainer() {} + +@@ -142,11 +142,11 @@ public class GossipContainer { + return k > type.max ? Math.max(type.max, left) : k; + } + +- static class EntityGossips { ++ public static class EntityGossips { // Paper - make public + + private final Object2IntMap entries; + +- private EntityGossips() { ++ public EntityGossips() { // Paper - make public - update CraftVillager setReputation on change + this.entries = new Object2IntOpenHashMap(); + } + +@@ -200,6 +200,28 @@ public class GossipContainer { + public void remove(GossipType gossipType) { + this.entries.removeInt(gossipType); + } ++ ++ // Paper start - Add villager reputation API ++ private static final com.destroystokyo.paper.entity.villager.ReputationType[] REPUTATION_TYPES = com.destroystokyo.paper.entity.villager.ReputationType.values(); ++ public com.destroystokyo.paper.entity.villager.Reputation getPaperReputation() { ++ int[] reputation = new int[REPUTATION_TYPES.length]; ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE.ordinal()] = entries.getOrDefault(GossipType.MAJOR_NEGATIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE.ordinal()] = entries.getOrDefault(GossipType.MAJOR_POSITIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE.ordinal()] = entries.getOrDefault(GossipType.MINOR_NEGATIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE.ordinal()] = entries.getOrDefault(GossipType.MINOR_POSITIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.TRADING.ordinal()] = entries.getOrDefault(GossipType.TRADING, 0); ++ return com.destroystokyo.paper.entity.villager.ReputationConstructor.construct(reputation); ++ } ++ ++ public void assignFromPaperReputation(com.destroystokyo.paper.entity.villager.Reputation rep) { ++ int val; ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE)) != 0) this.entries.put(GossipType.MAJOR_NEGATIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE)) != 0) this.entries.put(GossipType.MAJOR_POSITIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE)) != 0) this.entries.put(GossipType.MINOR_NEGATIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE)) != 0) this.entries.put(GossipType.MINOR_POSITIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.TRADING)) != 0) this.entries.put(GossipType.TRADING, val); ++ } ++ // Paper end + } + + static class GossipEntry { +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index a83a7d37f3d769535161fda46fca6f71dcc4d515..e9912551e6a19d6ad3b20fad1b716577b9d28f99 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -1037,6 +1037,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + this.numberOfRestocksToday = 0; + } + ++ public GossipContainer getReputation() { return this.getGossips(); } // Paper - OBFHELPER + public GossipContainer getGossips() { + return this.gossips; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +index d0b933cfd02b237bfe85011831dab6e8e966496e..e3d4214ef6360b4a9949a73ba3d665ad08733b43 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +@@ -16,6 +16,13 @@ import org.bukkit.entity.Villager; + import org.bukkit.entity.Villager.Profession; + import org.bukkit.entity.Villager.Type; + ++// Paper start ++import com.destroystokyo.paper.entity.villager.Reputation; ++import com.google.common.collect.Maps; ++import java.util.Map; ++import java.util.UUID; ++// Paper end ++ + public class CraftVillager extends CraftAbstractVillager implements Villager { + + public CraftVillager(CraftServer server, net.minecraft.world.entity.npc.Villager entity) { +@@ -125,4 +132,45 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { + public static VillagerProfession bukkitToNmsProfession(Profession bukkit) { + return Registry.VILLAGER_PROFESSION.get(CraftNamespacedKey.toMinecraft(bukkit.getKey())); + } ++ ++ // Paper start - Add villager reputation API ++ @Override ++ public Reputation getReputation(UUID uniqueId) { ++ net.minecraft.world.entity.ai.gossip.GossipContainer.EntityGossips rep = getHandle().getReputation().getReputations().get(uniqueId); ++ if (rep == null) { ++ return new Reputation(Maps.newHashMap()); ++ } ++ ++ return rep.getPaperReputation(); ++ } ++ ++ @Override ++ public Map getReputations() { ++ return getHandle().getReputation().getReputations().entrySet() ++ .stream() ++ .collect(java.util.stream.Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getPaperReputation())); ++ } ++ ++ @Override ++ public void setReputation(UUID uniqueId, Reputation reputation) { ++ net.minecraft.world.entity.ai.gossip.GossipContainer.EntityGossips nmsReputation = ++ getHandle().getReputation().getReputations().computeIfAbsent( ++ uniqueId, ++ key -> new net.minecraft.world.entity.ai.gossip.GossipContainer.EntityGossips() ++ ); ++ nmsReputation.assignFromPaperReputation(reputation); ++ } ++ ++ @Override ++ public void setReputations(Map reputations) { ++ for (Map.Entry entry : reputations.entrySet()) { ++ setReputation(entry.getKey(), entry.getValue()); ++ } ++ } ++ ++ @Override ++ public void clearReputations() { ++ getHandle().getReputation().getReputations().clear(); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch b/Remapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch new file mode 100644 index 0000000000..382b91a80f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch @@ -0,0 +1,182 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 7 May 2020 19:17:36 -0400 +Subject: [PATCH] Fix Light Command + +This lets you run /paper fixlight (max 5) to automatically +fix all light data in the chunks. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index ff718bc7f521575e6a670e17fcf59a2d30841705..528c860fc0c04431e0ebb2ae6bc96bf9c2d04789 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -11,16 +11,20 @@ import com.google.common.collect.Maps; + import com.google.gson.JsonObject; + import com.google.gson.internal.Streams; + import com.google.gson.stream.JsonWriter; ++import net.minecraft.core.BlockPos; ++import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.ThreadedLevelLightEngine; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; +-import net.minecraft.server.MCUtil; ++import net.minecraft.world.level.chunk.LevelChunk; + import org.apache.commons.lang3.tuple.MutablePair; + import org.apache.commons.lang3.tuple.Pair; + import org.bukkit.Bukkit; +@@ -31,6 +35,7 @@ import org.bukkit.command.Command; + import org.bukkit.command.CommandSender; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftPlayer; + import org.bukkit.entity.Player; + + import java.io.File; +@@ -39,10 +44,12 @@ import java.io.PrintStream; + import java.io.StringWriter; + import java.time.LocalDateTime; + import java.time.format.DateTimeFormatter; ++import java.util.ArrayDeque; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collection; + import java.util.Collections; ++import java.util.Deque; + import java.util.Iterator; + import java.util.List; + import java.util.Locale; +@@ -52,7 +59,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); + + public PaperCommand(String name) { + super(name); +@@ -173,6 +180,9 @@ public class PaperCommand extends Command { + case "syncloadinfo": + this.doSyncLoadInfo(sender, args); + break; ++ case "fixlight": ++ this.doFixLight(sender, args); ++ break; + case "ver": + if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) + case "version": +@@ -190,6 +200,77 @@ public class PaperCommand extends Command { + return true; + } + ++ private void doFixLight(CommandSender sender, String[] args) { ++ if (!(sender instanceof Player)) { ++ sender.sendMessage("Only players can use this command"); ++ return; ++ } ++ int radius = 2; ++ if (args.length > 1) { ++ try { ++ radius = Math.min(5, Integer.parseInt(args[1])); ++ } catch (Exception e) { ++ sender.sendMessage("Not a number"); ++ return; ++ } ++ ++ } ++ ++ CraftPlayer player = (CraftPlayer) sender; ++ ServerPlayer handle = player.getHandle(); ++ ServerLevel world = (ServerLevel) handle.level; ++ ThreadedLevelLightEngine lightengine = world.getChunkSource().getLightEngine(); ++ ++ BlockPos center = MCUtil.toBlockPosition(player.getLocation()); ++ Deque queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius)); ++ updateLight(sender, world, lightengine, queue); ++ } ++ ++ private void updateLight(CommandSender sender, ServerLevel world, ThreadedLevelLightEngine lightengine, Deque queue) { ++ ChunkPos coord = queue.poll(); ++ if (coord == null) { ++ sender.sendMessage("All Chunks Light updated"); ++ return; ++ } ++ world.getChunkSource().getChunkAtAsynchronously(coord.x, coord.z, false, false).whenCompleteAsync((either, ex) -> { ++ if (ex != null) { ++ sender.sendMessage("Error loading chunk " + coord); ++ updateLight(sender, world, lightengine, queue); ++ return; ++ } ++ LevelChunk chunk = (LevelChunk) either.left().orElse(null); ++ if (chunk == null) { ++ updateLight(sender, world, lightengine, queue); ++ return; ++ } ++ lightengine.setTaskPerBatch(world.paperConfig.lightQueueSize + 16 * 256); // ensure full chunk can fit into queue ++ sender.sendMessage("Updating Light " + coord); ++ int cx = chunk.getPos().x << 4; ++ int cz = chunk.getPos().z << 4; ++ for (int y = 0; y < world.getHeight(); y++) { ++ for (int x = 0; x < 16; x++) { ++ for (int z = 0; z < 16; z++) { ++ BlockPos pos = new BlockPos(cx + x, y, cz + z); ++ lightengine.checkBlock(pos); ++ } ++ } ++ } ++ lightengine.tryScheduleUpdate(); ++ ChunkHolder visibleChunk = world.getChunkSource().chunkMap.getVisibleChunkIfPresent(chunk.coordinateKey); ++ if (visibleChunk != null) { ++ world.getChunkSource().chunkMap.addLightTask(visibleChunk, () -> { ++ MinecraftServer.getServer().processQueue.add(() -> { ++ visibleChunk.sendPacketToTrackedPlayers(new ClientboundLightUpdatePacket(chunk.getPos(), lightengine, true), false); ++ updateLight(sender, world, lightengine, queue); ++ }); ++ }); ++ } else { ++ updateLight(sender, world, lightengine, queue); ++ } ++ lightengine.setTaskPerBatch(world.paperConfig.lightQueueSize); ++ }, MinecraftServer.getServer()); ++ } ++ + private void doSyncLoadInfo(CommandSender sender, String[] args) { + if (!SyncLoadFinder.ENABLED) { + sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 9ebcfca10071cc42d4f1df02c25de5042c065f38..d907872d80f840b343419f49a6708082da6f921b 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -349,6 +349,7 @@ public class ChunkHolder { + + } + ++ public void sendPacketToTrackedPlayers(Packet packet, boolean flag) { broadcast(packet, flag); } // Paper - OBFHELPER + private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { + // Paper start - per player view distance + // there can be potential desync with player's last mapped section and the view distance map, so use the +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 6b51a082cf42bc3ffc550614e385d3956c5f2efb..67f748d5955453ba4873b0c9bb741b5bfe52d655 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -344,11 +344,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ProcessorHandle mailbox = ProcessorHandle.of("main", mainThreadExecutor::tell); + + this.progressListener = worldGenerationProgressListener; +- ProcessorMailbox threadedmailbox1 = ProcessorMailbox.create(workerExecutor, "light"); ++ ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(workerExecutor, "light"); // Paper + + this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), workerExecutor, Integer.MAX_VALUE); + this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); + this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); ++ this.mailboxLight = this.queueSorter.getProcessor(lightthreaded, false);// Paper + this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); + this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper + this.overworldDataStorage = supplier; diff --git a/Remapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch b/Remapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch new file mode 100644 index 0000000000..5968f9b0c8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Fri, 8 May 2020 00:49:18 -0400 +Subject: [PATCH] Fix PotionEffect ignores icon flag + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 5dac3bf5a117bfbf57798238f0614558deafcd1b..067eaf1e05ced344eb168431403f3fe786eafddf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -408,7 +408,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + + @Override + public boolean addPotionEffect(PotionEffect effect, boolean force) { +- getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN); ++ getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon + return true; + } + diff --git a/Remapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch b/Remapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch new file mode 100644 index 0000000000..d213e040be --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: virustotalop +Date: Thu, 16 Apr 2020 20:51:32 -0700 +Subject: [PATCH] Optimize brigadier child sorting performance + + +diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +index 120234605433165d1c78986b5f0f130e64c5a20a..5c35cef42af4053332c02b4960c227fe95d4c197 100644 +--- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java ++++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +@@ -26,7 +26,7 @@ import java.util.stream.Collectors; + import net.minecraft.commands.CommandSourceStack; + + public abstract class CommandNode implements Comparable> { +- private Map> children = Maps.newLinkedHashMap(); ++ private Map> children = Maps.newTreeMap(); //Paper - Switch to tree map for automatic sorting + private Map> literals = Maps.newLinkedHashMap(); + private Map> arguments = Maps.newLinkedHashMap(); + private final Predicate requirement; +@@ -106,8 +106,7 @@ public abstract class CommandNode implements Comparable> { + arguments.put(node.getName(), (ArgumentCommandNode) node); + } + } +- +- children = children.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); ++ //Paper - Remove manual sorting, it is no longer needed + } + + public void findAmbiguities(final AmbiguityConsumer consumer) { diff --git a/Remapped-Spigot-Server-Patches/0473-Potential-bed-API.patch b/Remapped-Spigot-Server-Patches/0473-Potential-bed-API.patch new file mode 100644 index 0000000000..efd1703506 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0473-Potential-bed-API.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Sun, 10 May 2020 23:06:30 -0400 +Subject: [PATCH] Potential bed API + +Adds a new method to fetch the location of a player's bed without generating any sync loads. + +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/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index ae6faa331fcbefd99ee1cd92c88926d767fc50ee..878a62e04962aafeaf192075fbe08e319298a800 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -12,6 +12,7 @@ import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; + import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.MenuProvider; + import net.minecraft.world.entity.Entity; +@@ -126,6 +127,22 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + return getHandle().sleepCounter; + } + ++ // Paper start - Potential bed api ++ @Override ++ public Location getPotentialBedLocation() { ++ ServerPlayer handle = (ServerPlayer) getHandle(); ++ BlockPos bed = handle.getRespawnPosition(); ++ if (bed == null) { ++ return null; ++ } ++ ++ ServerLevel worldServer = handle.server.getLevel(handle.getRespawnDimension()); ++ if (worldServer == null) { ++ return null; ++ } ++ return new Location(worldServer.getWorld(), bed.getX(), bed.getY(), bed.getZ()); ++ } ++ // Paper end + @Override + public boolean sleep(Location location, boolean force) { + Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/Remapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch b/Remapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch new file mode 100644 index 0000000000..dea3aa2ef9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 May 2020 22:16:17 -0400 +Subject: [PATCH] Wait for Async Tasks during shutdown + +Server.reload() had this logic to give time for tasks to shutdown, +however shutdown did not... + +Adds a 5 second grace period for any async tasks to finish and warns +if any are still running after that delay just as reload does. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 74f393ffa2ae2d0e25b3f0b674cef7a987e985d3..f530c739b6aee3718eb5d0e0e6a09d882d817c68 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -892,6 +892,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { ++ try { ++ Thread.sleep(100); ++ } catch (InterruptedException e) {} ++ pollCount++; ++ } ++ ++ List overdueWorkers = getScheduler().getActiveWorkers(); ++ for (BukkitWorker worker : overdueWorkers) { ++ Plugin plugin = worker.getOwner(); ++ String author = ""; ++ if (plugin.getDescription().getAuthors().size() > 0) { ++ author = plugin.getDescription().getAuthors().get(0); ++ } ++ getLogger().log(Level.SEVERE, String.format( ++ "Nag author: '%s' of '%s' about the following: %s", ++ author, ++ plugin.getDescription().getName(), ++ "This plugin is not properly shutting down its async tasks when it is being shut down. This task may throw errors during the final shutdown logs and might not complete before process dies." ++ )); ++ } ++ } ++ // Paper end ++ + @Override + public void reloadData() { + ReloadCommand.reload(console); diff --git a/Remapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/Remapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch new file mode 100644 index 0000000000..99d8f1263a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Sat, 9 May 2020 02:01:48 -0400 +Subject: [PATCH] Ensure EntityRaider respects game and entity rules for + picking up items + + +diff --git a/src/main/java/net/minecraft/world/entity/raid/Raider.java b/src/main/java/net/minecraft/world/entity/raid/Raider.java +index 6406b0a03b67ea61083b704cd24b9b25a0f33c87..5502615be430d9eba0c1c68e3f10826d75b08672 100644 +--- a/src/main/java/net/minecraft/world/entity/raid/Raider.java ++++ b/src/main/java/net/minecraft/world/entity/raid/Raider.java +@@ -523,7 +523,7 @@ public abstract class Raider extends PatrollingMonster { + + public class ObtainRaidLeaderBannerGoal extends Goal { + +- private final T mob; ++ private final T mob; private T getRaider() { return mob; } // Paper - obfhelper + + public ObtainRaidLeaderBannerGoal(T entityraider) { // CraftBukkit - decompile error + this.mob = entityraider; +@@ -532,6 +532,7 @@ public abstract class Raider extends PatrollingMonster { + + @Override + public boolean canUse() { ++ if (!getRaider().level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || !getRaider().canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items + Raid raid = this.mob.getCurrentRaid(); + + if (this.mob.hasActiveRaid() && !this.mob.getCurrentRaid().isOver() && this.mob.canBeLeader() && !ItemStack.matches(this.mob.getItemBySlot(EquipmentSlot.HEAD), Raid.getLeaderBannerInstance())) { diff --git a/Remapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/Remapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch new file mode 100644 index 0000000000..99a5355669 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch @@ -0,0 +1,173 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 13 May 2020 23:01:26 -0400 +Subject: [PATCH] Protect Bedrock and End Portal/Frames from being destroyed + +This fixes exploits that let players destroy bedrock by Pistons, explosions +and Mushrooom/Tree generation. + +These blocks are designed to not be broken except by creative players/commands. +So protect them from a multitude of methods of destroying them. + +A config is provided if you rather let players use these exploits, and let +them destroy the worlds End Portals and get on top of the nether easy. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 78271b400c79578d043b20a5389a37b1bef9a70d..5f3b0d95cc7e6a0434d78ea7305a70689c41c71c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -416,4 +416,17 @@ public class PaperConfig { + private static void midTickChunkTasks() { + midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); + } ++ ++ public static boolean allowBlockPermanentBreakingExploits = false; ++ private static void allowBlockPermanentBreakingExploits() { ++ if (config.contains("allow-perm-block-break-exploits")) { ++ allowBlockPermanentBreakingExploits = config.getBoolean("allow-perm-block-break-exploits", false); ++ config.set("allow-perm-block-break-exploits", null); ++ } ++ ++ config.set("settings.unsupported-settings.allow-permanent-block-break-exploits-readme", "This setting controls if players should be able to break bedrock, end portals and other intended to be permanent blocks."); ++ allowBlockPermanentBreakingExploits = getBoolean("settings.unsupported-settings.allow-permanent-block-break-exploits", allowBlockPermanentBreakingExploits); ++ ++ } ++ + } +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 667a6d645034c67639c01b8221591877bcb87b35..0f0a5fa2be5a7c69291b593a04cad83e069ba5b1 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -151,6 +151,7 @@ public class Explosion { + for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { + BlockPos blockposition = new BlockPos(d4, d5, d6); + BlockState iblockdata = this.level.getBlockState(blockposition); ++ if (!iblockdata.isDestroyable()) continue; // Paper + FluidState fluid = iblockdata.getFluidState(); // Paper + Optional optional = this.damageCalculator.a(this, this.level, blockposition, iblockdata, fluid); + +@@ -304,7 +305,7 @@ public class Explosion { + BlockState iblockdata = this.level.getBlockState(blockposition); + Block block = iblockdata.getBlock(); + +- if (!iblockdata.isAir()) { ++ if (!iblockdata.isAir() && iblockdata.isDestroyable()) { // Paper + BlockPos blockposition1 = blockposition.immutable(); + + this.level.getProfiler().push("explosion_blocks"); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 67ab681a9c9157a420de5fd872bde1fc0de24561..9b50b8030174338c04b60d441b980131e1d593e4 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -422,6 +422,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { + // CraftBukkit start - tree generation + if (this.captureTreeGeneration) { ++ // Paper start ++ BlockState type = getBlockState(pos); ++ if (!type.isDestroyable()) return false; ++ // Paper end + CraftBlockState blockstate = capturedBlockStates.get(pos); + if (blockstate == null) { + blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index fca5d175cbef24fb0ee2d0bbedc8d1c0af3eb528..5b84ee4091e354c4b6500f58a31931f2a6827ffc 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -62,6 +62,19 @@ public class Block extends BlockBehaviour implements ItemLike { + protected final StateDefinition stateDefinition; + private BlockState defaultBlockState; + // Paper start ++ public final boolean isDestroyable() { ++ return com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || ++ this != Blocks.BEDROCK && ++ this != Blocks.END_PORTAL_FRAME && ++ this != Blocks.END_PORTAL && ++ this != Blocks.END_GATEWAY && ++ this != Blocks.COMMAND_BLOCK && ++ this != Blocks.REPEATING_COMMAND_BLOCK && ++ this != Blocks.CHAIN_COMMAND_BLOCK && ++ this != Blocks.BARRIER && ++ this != Blocks.STRUCTURE_BLOCK && ++ this != Blocks.JIGSAW; ++ } + public co.aikar.timings.Timing timing; + public co.aikar.timings.Timing getTiming() { + if (timing == null) { +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +index dc9584a30c18d964afd9cc118c81c24a80beba63..40a18302dd682e5ade4ec77ac7f316b6c0f8c112 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -193,6 +193,12 @@ public class PistonBaseBlock extends DirectionalBlock { + @Override + public boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) { + Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING); ++ // Paper start - prevent retracting when we're facing the wrong way (we were replaced before retraction could occur) ++ Direction directionQueuedAs = Direction.from3DDataValue(data & 7); // Paper - copied from below ++ if (!com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits && enumdirection != directionQueuedAs) { ++ return false; ++ } ++ // Paper end - prevent retracting when we're facing the wrong way + + if (!world.isClientSide) { + boolean flag = this.getNeighborSignal(world, pos, enumdirection); +@@ -224,7 +230,7 @@ public class PistonBaseBlock extends DirectionalBlock { + BlockState iblockdata1 = (BlockState) ((BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, enumdirection)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); + + world.setBlock(pos, iblockdata1, 20); +- world.setBlockEntity(pos, MovingPistonBlock.newMovingBlockEntity((BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); ++ world.setBlockEntity(pos, MovingPistonBlock.newMovingBlockEntity((BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - diff on change, j is facing direction - copy this above + world.blockUpdated(pos, iblockdata1.getBlock()); + iblockdata1.updateNeighbourShapes(world, pos, 2); + if (this.isSticky) { +@@ -253,7 +259,14 @@ public class PistonBaseBlock extends DirectionalBlock { + } + } + } else { +- world.removeBlock(pos.relative(enumdirection), false); ++ // Paper start - fix headless pistons breaking blocks ++ BlockPos headPos = pos.relative(enumdirection); ++ if (com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || world.getBlockState(headPos) == Blocks.PISTON_HEAD.defaultBlockState().setValue(FACING, enumdirection)) { // double check to make sure we're not a headless piston. ++ world.setAir(headPos, false); ++ } else { ++ ((ServerLevel)world).getChunkSource().blockChanged(headPos); // ... fix client desync ++ } ++ // Paper end - fix headless pistons breaking blocks + } + + world.playSound((Player) null, pos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F); +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index 57eedaeedaa24bd274fb55c6e4521f1305382645..df2836b071158729728411f5b228cc38dddd4d4e 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -189,7 +189,7 @@ public abstract class BlockBehaviour { + + @Deprecated + public boolean canBeReplaced(BlockState state, BlockPlaceContext context) { +- return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || context.getItemInHand().getItem() != this.asItem()); ++ return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || context.getItemInHand().getItem() != this.asItem()) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().abilities.instabuild)); // Paper + } + + @Deprecated +@@ -393,7 +393,11 @@ public abstract class BlockBehaviour { + public Block getBlock() { + return (Block) this.owner; + } +- ++ // Paper start ++ public final boolean isDestroyable() { ++ return getBlock().isDestroyable(); ++ } ++ // Paper end + public Material getMaterial() { + return this.material; + } +@@ -483,7 +487,7 @@ public abstract class BlockBehaviour { + } + + public PushReaction getPistonPushReaction() { +- return this.getBlock().getPistonPushReaction(this.asState()); ++ return !isDestroyable() ? PushReaction.BLOCK : this.getBlock().getPistonPushReaction(this.asState()); // Paper + } + + public boolean isSolidRender(BlockGetter world, BlockPos pos) { diff --git a/Remapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch b/Remapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch new file mode 100644 index 0000000000..9cdcec0403 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch @@ -0,0 +1,394 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 May 2020 23:30:30 -0400 +Subject: [PATCH] Optimize NibbleArray to use pooled buffers + +Massively reduces memory allocation of 2048 byte buffers by using +an object pool for these. + +Uses lots of advanced new capabilities of the Paper codebase :) + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java +index bc1b4cc2e0a4181bde5ac05ce0a20a651cb0c4c3..902f14e2e5ac5aa11b545a68ac69e9b0282df7f4 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java +@@ -1,12 +1,16 @@ + package net.minecraft.network.protocol.game; + + import com.google.common.collect.Lists; ++import io.netty.channel.ChannelFuture; // Paper ++ + import java.io.IOException; + import java.util.Iterator; + import java.util.List; + import net.minecraft.core.SectionPos; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.chunk.DataLayer; +@@ -24,14 +28,43 @@ public class ClientboundLightUpdatePacket implements Packet blockUpdates; + private boolean trustEdges; + ++ // Paper start ++ java.lang.Runnable cleaner1; ++ java.lang.Runnable cleaner2; ++ java.util.concurrent.atomic.AtomicInteger remainingSends = new java.util.concurrent.atomic.AtomicInteger(0); ++ ++ @Override ++ public void onPacketDispatch(ServerPlayer player) { ++ remainingSends.incrementAndGet(); ++ } ++ ++ @Override ++ public void onPacketDispatchFinish(ServerPlayer player, ChannelFuture future) { ++ if (remainingSends.decrementAndGet() <= 0) { ++ // incase of any race conditions, schedule this delayed ++ MCUtil.scheduleTask(5, () -> { ++ if (remainingSends.get() == 0) { ++ cleaner1.run(); ++ cleaner2.run(); ++ } ++ }, "Light Packet Release"); ++ } ++ } ++ ++ @Override ++ public boolean hasFinishListener() { ++ return true; ++ } ++ ++ // Paper end + public ClientboundLightUpdatePacket() {} + + public ClientboundLightUpdatePacket(ChunkPos chunkcoordintpair, LevelLightEngine lightengine, boolean flag) { + this.x = chunkcoordintpair.x; + this.z = chunkcoordintpair.z; + this.trustEdges = flag; +- this.skyUpdates = Lists.newArrayList(); +- this.blockUpdates = Lists.newArrayList(); ++ this.skyUpdates = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.skyUpdates, DataLayer::releaseBytes); // Paper ++ this.blockUpdates = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.blockUpdates, DataLayer::releaseBytes); // Paper + + for (int i = 0; i < 18; ++i) { + DataLayer nibblearray = lightengine.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, -1 + i)); +@@ -42,7 +75,7 @@ public class ClientboundLightUpdatePacket implements Packet BYTE_2048 = new PooledObjects<>(() -> new byte[2048], maxPoolSize); ++ public static void releaseBytes(byte[] bytes) { ++ if (bytes != null && bytes != EMPTY_NIBBLE && bytes.length == 2048) { ++ System.arraycopy(EMPTY_NIBBLE, 0, bytes, 0, 2048); ++ BYTE_2048.release(bytes); ++ } ++ } ++ ++ public DataLayer markPoolSafe(byte[] bytes) { ++ if (bytes != EMPTY_NIBBLE) this.data = bytes; ++ return markPoolSafe(); ++ } ++ public DataLayer markPoolSafe() { ++ poolSafe = true; ++ return this; ++ } ++ public byte[] getIfSet() { ++ return this.data != null ? this.data : EMPTY_NIBBLE; ++ } ++ public byte[] getCloneIfSet() { ++ if (data == null) { ++ return EMPTY_NIBBLE; ++ } ++ byte[] ret = BYTE_2048.acquire(); ++ System.arraycopy(getIfSet(), 0, ret, 0, 2048); ++ return ret; ++ } ++ ++ public DataLayer cloneAndSet(byte[] bytes) { ++ if (bytes != null && bytes != EMPTY_NIBBLE) { ++ this.data = BYTE_2048.acquire(); ++ System.arraycopy(bytes, 0, this.data, 0, 2048); ++ } ++ return this; ++ } ++ boolean poolSafe = false; ++ public java.lang.Runnable cleaner; ++ private void registerCleaner() { ++ if (!poolSafe) { ++ cleaner = MCUtil.registerCleaner(this, this.data, DataLayer::releaseBytes); ++ } else { ++ cleaner = MCUtil.once(() -> DataLayer.releaseBytes(this.data)); ++ } ++ } ++ // Paper end ++ @Nullable protected byte[] data; ++ + + public DataLayer() {} + + public DataLayer(byte[] abyte) { ++ // Paper start ++ this(abyte, false); ++ } ++ public DataLayer(byte[] abyte, boolean isSafe) { + this.data = abyte; ++ if (!isSafe) this.data = getCloneIfSet(); // Paper - clone for safety ++ registerCleaner(); ++ // Paper end + if (abyte.length != 2048) { + throw (IllegalArgumentException) Util.pauseInIde((Throwable) (new IllegalArgumentException("ChunkNibbleArrays should be 2048 bytes not: " + abyte.length))); + } +@@ -46,7 +106,8 @@ public class DataLayer { + + public void set(int index, int value) { // PAIL: private -> public + if (this.data == null) { +- this.data = new byte[2048]; ++ this.data = BYTE_2048.acquire(); // Paper ++ registerCleaner();// Paper + } + + int k = this.getPosition(index); +@@ -68,14 +129,36 @@ public class DataLayer { + public byte[] getData() { + if (this.data == null) { + this.data = new byte[2048]; ++ } else { // Paper start ++ // Accessor may need this object past garbage collection so need to clone it and return pooled value ++ // If we know its safe for pre GC access, use asBytesPoolSafe(). If you just need read, use getIfSet() ++ Runnable cleaner = this.cleaner; ++ if (cleaner != null) { ++ this.data = this.data.clone(); ++ cleaner.run(); // release the previously pooled value ++ this.cleaner = null; ++ } ++ } ++ // Paper end ++ ++ return this.data; ++ } ++ ++ @Nonnull ++ public byte[] asBytesPoolSafe() { ++ if (this.data == null) { ++ this.data = BYTE_2048.acquire(); // Paper ++ registerCleaner(); // Paper + } + ++ //noinspection ConstantConditions + return this.data; + } ++ // Paper end + + public DataLayer copy() { return this.copy(); } // Paper - OBFHELPER + public DataLayer copy() { +- return this.data == null ? new DataLayer() : new DataLayer((byte[]) this.data.clone()); ++ return this.data == null ? new DataLayer() : new DataLayer(this.data); // Paper - clone in ctor + } + + public String toString() { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 6c28a611b9b79c3322ab07883972c07b3bfc3073..1e58958c3d7b10da5a5f22fc9591d9183e53e3cc 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -435,11 +435,11 @@ public class ChunkSerializer { + } + + if (nibblearray != null && !nibblearray.isEmpty()) { +- nbttagcompound2.putByteArray("BlockLight", nibblearray.getData()); ++ nbttagcompound2.putByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper + } + + if (nibblearray1 != null && !nibblearray1.isEmpty()) { +- nbttagcompound2.putByteArray("SkyLight", nibblearray1.getData()); ++ nbttagcompound2.putByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper + } + + nbttaglist.add(nbttagcompound2); +diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +index 4c9041f1c1cb4b3ec114fbd0c5d4db50a6f2526d..54cca3b376e5ce02936edc8b9c17e67e17f07147 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java ++++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.lighting; + + import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; + import javax.annotation.Nullable; ++import net.minecraft.server.MCUtil; + import net.minecraft.world.level.chunk.DataLayer; + + public abstract class DataLayerStorageMap> { +@@ -34,7 +35,9 @@ public abstract class DataLayerStorageMap> { + + public void copyDataLayer(long pos) { + if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data +- this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data ++ DataLayer updating = this.data.getUpdating(pos); // Paper - pool nibbles ++ this.data.queueUpdate(pos, new DataLayer().markPoolSafe(updating.getCloneIfSet())); // Paper - avoid copying light data - pool safe clone ++ if (updating.cleaner != null) MCUtil.scheduleTask(2, updating.cleaner, "Light Engine Release"); // Paper - delay clean incase anything holding ref was still using it + this.clearCache(); + } + +diff --git a/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java b/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java +index 9b95ae0ff193d7f52650f406c70e76e3f7e07e1c..c0d356ac4d54b952fe9ddaf5125b07177ac44d1f 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java ++++ b/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java +@@ -10,7 +10,7 @@ public class FlatDataLayer extends DataLayer { + + public FlatDataLayer(DataLayer nibblearray, int i) { + super(128); +- System.arraycopy(nibblearray.getData(), i * 128, this.data, 0, 128); ++ System.arraycopy(nibblearray.getIfSet(), i * 128, this.data, 0, 128); // Paper + } + + @Override +@@ -20,7 +20,7 @@ public class FlatDataLayer extends DataLayer { + + @Override + public byte[] getData() { +- byte[] abyte = new byte[2048]; ++ byte[] abyte = BYTE_2048.acquire(); // Paper + + for (int i = 0; i < 16; ++i) { + System.arraycopy(this.data, 0, abyte, i * 128, 128); +diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +index 177dae992d13674bb285a60b8427df9ea843dc99..5757bcfded35f112d52a7c81586850ba50e0d8dd 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +@@ -156,7 +156,7 @@ public abstract class LayerLightSectionStorage> + protected DataLayer createDataLayer(long sectionPos) { + DataLayer nibblearray = (DataLayer) this.queuedSections.get(sectionPos); + +- return nibblearray != null ? nibblearray : new DataLayer(); ++ return nibblearray != null ? nibblearray : new DataLayer().markPoolSafe(); // Paper + } + + protected void clearQueuedSectionBlocks(LayerLightEngine storage, long sectionPos) { +@@ -338,12 +338,12 @@ public abstract class LayerLightSectionStorage> + + protected void queueSectionData(long sectionPos, @Nullable DataLayer array, boolean flag) { + if (array != null) { +- this.queuedSections.put(sectionPos, array); ++ DataLayer remove = this.queuedSections.put(sectionPos, array); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed + if (!flag) { + this.untrustedSections.add(sectionPos); + } + } else { +- this.queuedSections.remove(sectionPos); ++ DataLayer remove = this.queuedSections.remove(sectionPos); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed + } + + } +diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +index 410fcfa8c01b7e3d3e3829ebdb92a11badff16ea..88f168f9d4c29cfc93500227bf8a60de4b6e4d8a 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +@@ -172,9 +172,9 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage +Date: Mon, 27 Apr 2020 02:48:06 -0700 +Subject: [PATCH] Reduce MutableInt allocations from light engine + +We can abuse the fact light is single threaded and share an instance +per light engine instance + +diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java +index 8979101a52537f4ec03a5f43030264b8e72fcea4..709fc42057f8a0282c3c942067e63abb874d9042 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java ++++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java +@@ -16,6 +16,7 @@ public final class BlockLightEngine extends LayerLightEngine= 15) { +diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java +index d99890121bdf1e499e364bdc953e628c04d69b95..ff1fbc46776b26ca56c3293e40ed55028230ec46 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java +@@ -15,6 +15,7 @@ public final class SkyLightEngine extends LayerLightEngine= 15) { + return level; + } else { +- MutableInt mutableint = new MutableInt(); ++ //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded + BlockState iblockdata = this.getStateAndOpacity(targetId, mutableint); + + if (mutableint.getValue() >= 15) { diff --git a/Remapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/Remapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch new file mode 100644 index 0000000000..6751467281 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 27 Apr 2020 00:04:16 -0700 +Subject: [PATCH] Reduce allocation of Vec3D by entity tracker + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 67f748d5955453ba4873b0c9bb741b5bfe52d655..738f1183ce663db7c67d2f0289823390a7f06a0e 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -95,7 +95,6 @@ import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelStorageSource; +-import net.minecraft.world.phys.Vec3; + import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper + import org.apache.commons.lang3.mutable.MutableBoolean; + import org.apache.logging.log4j.LogManager; +@@ -2233,9 +2232,14 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + public void updatePlayer(ServerPlayer player) { + org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot + if (player != this.entity) { +- Vec3 vec3d = player.position().subtract(this.entity.position()); // MC-155077, SPIGOT-5113 ++ // Paper start - remove allocation of Vec3D here ++ //Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 ++ double vec3d_dx = player.getX() - this.entity.getX(); ++ double vec3d_dy = player.getY() - this.entity.getY(); ++ double vec3d_dz = player.getZ() - this.entity.getZ(); ++ // Paper end - remove allocation of Vec3D here + int i = Math.min(this.getEffectiveRange(), (ChunkMap.this.viewDistance - 1) * 16); +- boolean flag = vec3d.x >= (double) (-i) && vec3d.x <= (double) i && vec3d.z >= (double) (-i) && vec3d.z <= (double) i && this.entity.broadcastToPlayer(player); ++ boolean flag = vec3d_dx >= (double) (-i) && vec3d_dx <= (double) i && vec3d_dz >= (double) (-i) && vec3d_dz <= (double) i && this.entity.broadcastToPlayer(player); // Paper - remove allocation of Vec3D here + + if (flag) { + boolean flag1 = this.entity.forcedLoading; +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index d797873db52ba265ac4478f9f3c6344badd4739e..75e2274578c2c28de3d786372df0b4102337a2cc 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -154,8 +154,12 @@ public class ServerEntity { + ++this.teleportDelay; + i = Mth.floor(this.entity.yRot * 256.0F / 360.0F); + j = Mth.floor(this.entity.xRot * 256.0F / 360.0F); +- Vec3 vec3d = this.entity.position().subtract(ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp)); +- boolean flag1 = vec3d.lengthSqr() >= 7.62939453125E-6D; ++ // Paper start - reduce allocation of Vec3D here ++ double vec3d_dx = this.entity.getX() - 2.44140625E-4D*(this.xp); ++ double vec3d_dy = this.entity.getY() - 2.44140625E-4D*(this.yp); ++ double vec3d_dz = this.entity.getZ() - 2.44140625E-4D*(this.zp); ++ boolean flag1 = (vec3d_dx * vec3d_dx + vec3d_dy * vec3d_dy + vec3d_dz * vec3d_dz) >= 7.62939453125E-6D; ++ // Paper end - reduce allocation of Vec3D here + Packet packet1 = null; + boolean flag2 = flag1 || this.tickCount % 60 == 0; + boolean flag3 = Math.abs(i - this.yRotp) >= 1 || Math.abs(j - this.xRotp) >= 1; +@@ -172,9 +176,11 @@ public class ServerEntity { + // CraftBukkit end + + if (this.tickCount > 0 || this.entity instanceof AbstractArrow) { +- long k = ClientboundMoveEntityPacket.entityToPacket(vec3d.x); +- long l = ClientboundMoveEntityPacket.entityToPacket(vec3d.y); +- long i1 = ClientboundMoveEntityPacket.entityToPacket(vec3d.z); ++ // Paper start - remove allocation of Vec3D here ++ long k = ClientboundMoveEntityPacket.entityToPacket(vec3d_dx); ++ long l = ClientboundMoveEntityPacket.entityToPacket(vec3d_dy); ++ long i1 = ClientboundMoveEntityPacket.entityToPacket(vec3d_dz); ++ // Paper end - remove allocation of Vec3D here + boolean flag4 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L; + + if (!flag4 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.isOnGround()) { diff --git a/Remapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch b/Remapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch new file mode 100644 index 0000000000..3ca91f50a5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Fri, 15 May 2020 01:10:03 -0400 +Subject: [PATCH] Ensure safe gateway teleport + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +index b70e0633435a272ae1e9fbd12d7f18862de0b951..3491956cb09b825bbfc99667b058d67cef127332 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -86,9 +86,14 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements + } else if (!this.level.isClientSide) { + List list = this.level.getEntitiesOfClass(Entity.class, new AABB(this.getBlockPos()), TheEndGatewayBlockEntity::canEntityTeleport); + +- if (!list.isEmpty()) { +- this.teleportEntity((Entity) list.get(this.level.random.nextInt(list.size()))); ++ // Paper start ++ for (Entity entity : list) { ++ if (entity.canChangeDimensions()) { ++ this.teleportEntity(entity); ++ break; ++ } + } ++ // Paper end + + if (this.age % 2400L == 0L) { + this.triggerCooldown(); diff --git a/Remapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch b/Remapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch new file mode 100644 index 0000000000..61d650c223 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 16 May 2020 10:12:15 +0200 +Subject: [PATCH] Add option for console having all permissions + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 5f3b0d95cc7e6a0434d78ea7305a70689c41c71c..7f140333c2e62012fa572c1a061d84432426997f 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -429,4 +429,9 @@ public class PaperConfig { + + } + ++ public static boolean consoleHasAllPermissions = false; ++ private static void consoleHasAllPermissions() { ++ consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); ++ } ++ + } +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 525cd44411b344bc4b5d43c087094fea88fa41a6..4817b8ab259d348b48bc325d34ba9351ffe951df 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1886,7 +1886,7 @@ public abstract class Player extends LivingEntity { + } + } + +- protected void removeEntitiesOnShoulder() { ++ public void removeEntitiesOnShoulder() { // Paper - protected -> public + if (this.timeEntitySatOnShoulder + 20L < this.level.getGameTime()) { + // CraftBukkit start + if (this.spawnEntityFromShoulder(this.getShoulderEntityLeft())) { +diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +index af986adfdb547cb61fbd52f0f89858f1a9e52cc3..80a67deaeaae3b3f0ceb9a298de5bb38b8ee707b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +@@ -86,5 +86,15 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co + public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { + this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); + } ++ ++ @Override ++ public boolean hasPermission(String name) { ++ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); ++ } ++ ++ @Override ++ public boolean hasPermission(org.bukkit.permissions.Permission perm) { ++ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java +index d0757d116ee689041c0e64e622d2c36e0b0bcaf1..7b53b5a0857fc0ce0463db319f86a1f79833ab93 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java +@@ -39,4 +39,16 @@ public class CraftRemoteConsoleCommandSender extends ServerCommandSender impleme + public void setOp(boolean value) { + throw new UnsupportedOperationException("Cannot change operator status of remote controller."); + } ++ ++ // Paper start ++ @Override ++ public boolean hasPermission(String name) { ++ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); ++ } ++ ++ @Override ++ public boolean hasPermission(org.bukkit.permissions.Permission perm) { ++ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/Remapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch new file mode 100644 index 0000000000..1346418468 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 23 May 2020 01:31:06 -0400 +Subject: [PATCH] Fix Non Full Status Chunk NBT Memory Leak + +Any full status chunk that was requested for any status less than full +would hold onto their entire nbt tree and every variable in that function. + +This was due to use of a lambda that persists on the Chunk object +until that chunk reaches FULL status. + +With introduction of no tick, we greatly increased the number of non +full chunks so this was really starting to hurt. + +We further improve it by making a copy of the nbt tag with only the memory +it needs, so that we dont have to hold a copy to the entire compound. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 1e58958c3d7b10da5a5f22fc9591d9183e53e3cc..0adf14af9841cd3a20a8b2c0c320eb06794ef261 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -26,6 +26,7 @@ import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.LongArrayTag; + import net.minecraft.nbt.ShortTag; ++import net.minecraft.nbt.Tag; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; +@@ -199,15 +200,9 @@ public class ChunkSerializer { + object2 = protochunkticklist1; + } + +- object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { +- postLoadChunk(nbttagcompound1, chunk); +- // CraftBukkit start - load chunk persistent data from nbt +- net.minecraft.nbt.Tag persistentBase = nbttagcompound1.get("ChunkBukkitValues"); +- if (persistentBase instanceof CompoundTag) { +- chunk.persistentDataContainer.putAll((CompoundTag) persistentBase); +- } +- // CraftBukkit end +- }); ++ object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. ++ createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities", "ChunkBukkitValues")) // Paper - move CB Chunk PDC into here ++ );// Paper end + } else { + ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter + +@@ -313,6 +308,50 @@ public class ChunkSerializer { + return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading + } + } ++ // Paper start ++ ++ /** ++ * This wrapper will error out if any key is accessed that wasn't copied so we can catch it easy on an update ++ */ ++ private static class SafeNBTCopy extends CompoundTag { ++ private final java.util.Set keys = new java.util.HashSet(); ++ public SafeNBTCopy(CompoundTag base, String... keys) { ++ for (String key : keys) { ++ this.keys.add(key); ++ final Tag nbtBase = base.get(key); ++ if (nbtBase != null) { ++ this.put(key, nbtBase); ++ } ++ } ++ } ++ ++ @Override ++ public boolean contains(String key) { ++ if (super.contains(key)) { ++ return true; ++ } else if (keys.contains(key)) { ++ return false; ++ } ++ throw new IllegalStateException("Missing Key " + key + " in SafeNBTCopy"); ++ } ++ ++ @Override ++ public boolean contains(String key, int type) { ++ return contains(key) && super.contains(key, type); ++ } ++ } ++ private static java.util.function.Consumer createLoadEntitiesConsumer(CompoundTag nbt) { ++ return (chunk) -> { ++ postLoadChunk(nbt, chunk); ++ // CraftBukkit start - load chunk persistent data from nbt ++ Tag persistentBase = nbt.get("ChunkBukkitValues"); ++ if (persistentBase instanceof CompoundTag) { ++ chunk.persistentDataContainer.putAll((CompoundTag) persistentBase); ++ } ++ // CraftBukkit end ++ }; ++ } ++ // Paper end + + // Paper start - async chunk save for unload + public static final class AsyncSaveData { diff --git a/Remapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch b/Remapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch new file mode 100644 index 0000000000..7918002d5e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch @@ -0,0 +1,137 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Tue, 12 May 2020 23:02:43 +0200 +Subject: [PATCH] Workaround for Client Lag Spikes (MC-162253) + +When crossing certain chunk boundaries, the client needlessly +calculates light maps for chunk neighbours. In some specific map +configurations, these calculations cause a 500ms+ freeze on the Client. + +This patch basically serves as a workaround by sending light maps +to the client, so that it doesn't attempt to calculate them. +This mitigates the frametime impact to a minimum (but it's still there). + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 738f1183ce663db7c67d2f0289823390a7f06a0e..8070acde38c47c364c1d26ec3b7d65da037554a5 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -85,6 +85,7 @@ import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.ImposterProtoChunk; + import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.LevelChunkSection; + import net.minecraft.world.level.chunk.LightChunkGetter; + import net.minecraft.world.level.chunk.ProtoChunk; + import net.minecraft.world.level.chunk.UpgradeData; +@@ -2018,7 +2019,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + // Paper start + private static int getLightMask(final LevelChunk chunk) { +- final ChunkSection[] chunkSections = chunk.getSections(); ++ final LevelChunkSection[] chunkSections = chunk.getSections(); + int mask = 0; + + for (int i = 0; i < chunkSections.length; ++i) { +@@ -2029,7 +2030,7 @@ Lightmasks have 18 bits, from the -1 (void) section until the 17th (air) section + Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. + + */ +- mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; ++ mask |= (LevelChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; + } + + return mask; +@@ -2060,9 +2061,68 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + public final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER + private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { + if (packets[0] == null) { ++ // Paper start - add 8 for light fix workaround ++ if (packets.length != 10) { // in case Plugins call sendChunk, resize ++ packets = new Packet[10]; ++ } ++ // Paper end + packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass + packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, true); ++ ++ // Paper start - Fix MC-162253 ++ final int lightMask = getLightMask(chunk); ++ int i = 1; ++ for (int x = -1; x <= 1; x++) { ++ for (int z = -1; z <= 1; z++) { ++ if (x == 0 && z == 0) { ++ continue; ++ } ++ ++ ++i; ++ ++ if (!chunk.isNeighbourLoaded(x, z)) { ++ continue; ++ } ++ ++ final LevelChunk neighbor = chunk.getRelativeNeighbourIfLoaded(x, z); ++ final int updateLightMask = lightMask & ~getCeilingLightMask(neighbor); ++ ++ if (updateLightMask == 0) { ++ continue; ++ } ++ ++ packets[i] = new ClientboundLightUpdatePacket(new ChunkPos(chunk.getPos().x + x, chunk.getPos().z + z), lightEngine, updateLightMask, 0, true); ++ } ++ } ++ } ++ ++ final int viewDistance = playerViewDistanceBroadcastMap.getLastViewDistance(player); ++ final long lastPosition = playerViewDistanceBroadcastMap.getLastCoordinate(player); ++ ++ int j = 1; ++ for (int x = -1; x <= 1; x++) { ++ for (int z = -1; z <= 1; z++) { ++ if (x == 0 && z == 0) { ++ continue; ++ } ++ ++ ++j; ++ ++ Packet packet = packets[j]; ++ if (packet == null) { ++ continue; ++ } ++ ++ final int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - (chunk.getPos().x + x)); ++ final int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - (chunk.getPos().z + z)); ++ ++ if (Math.max(distX, distZ) > viewDistance) { ++ continue; ++ } ++ player.connection.send(packet); ++ } + } ++ // Paper end - Fix MC-162253 + + player.trackChunk(chunk.getPos(), packets[0], packets[1]); + DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos()); +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index dbea2a4370ccf24a5084cdabeecbc81f206e910a..9b76dc15417eef420804e5184a6d684e1137a746 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -279,7 +279,7 @@ public class LevelChunk implements ChunkAccess { + + // broadcast + Object[] backingSet = inRange.getBackingSet(); +- Packet[] chunkPackets = new Packet[2]; ++ Packet[] chunkPackets = new Packet[10]; + for (int index = 0, len = backingSet.length; index < len; ++index) { + Object temp = backingSet[index]; + if (!(temp instanceof ServerPlayer)) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index 5e7f6000df129100ef306703f325af9f60da8ae6..cc7d930c1fcd7157efc181d766e1639669f6eab9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -107,6 +107,7 @@ public class LevelChunkSection { + return this.nonEmptyBlockCount == 0; + } + ++ public static boolean isEmpty(@Nullable LevelChunkSection chunksection) { return isEmpty(chunksection) ; } // Paper - OBFHELPER + public static boolean isEmpty(@Nullable LevelChunkSection section) { + return section == LevelChunk.EMPTY_SECTION || section.isEmpty(); + } diff --git a/Remapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/Remapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch new file mode 100644 index 0000000000..c64155c42a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch @@ -0,0 +1,1352 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 11 Apr 2020 03:56:07 -0400 +Subject: [PATCH] Implement Chunk Priority / Urgency System for Chunks + +Mark chunks that are blocking main thread for world generation as urgent + +Implements a general priority system so that chunks that are sorted in +the generator queues can prioritize certain chunks over another. + +Urgent chunks will jump to the front of the line, ensuring that a +sync chunk load on an ungenerated chunk does not lag the server for +a long period of time if the servers generator queues are filled with +lots of chunks already. + +This massively reduces the lag spikes from sync chunk gens. + +Then we further prioritize loading order so nearby chunks have higher +priority than distant chunks, reducing the pressure a high no tick +view distance holds on you. + +Chunks in front of the player have higher priority, to help with +fast traveling players keep up with their movement. + +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +index 499aff1f1e1ffc01ba8f9de43ca17899525a306f..97b85587525ddb62af9bfc8785b48727a6135599 100644 +--- a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +@@ -108,7 +108,7 @@ public final class ChunkTaskManager { + } + + static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z) { +- dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); ++ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 4); + } + + static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z, int indent, int maxDepth) { +@@ -129,6 +129,30 @@ public final class ChunkTaskManager { + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Priority - " + chunkHolder.getCurrentPriority()); ++ ++ if (!chunkHolder.neighbors.isEmpty()) { ++ if (indent >= maxDepth) { ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: (Can't show, too deeply nested)"); ++ return; ++ } ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: "); ++ for (ChunkHolder neighbor : chunkHolder.neighbors.keySet()) { ++ ChunkStatus status = neighbor.getChunkHolderStatus(); ++ if (status != null && status.isAtLeastStatus(ChunkHolder.getStatus(neighbor.getTicketLevel()))) { ++ continue; ++ } ++ int nx = neighbor.pos.x; ++ int nz = neighbor.pos.z; ++ if (seenChunks.contains(neighbor)) { ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + " (CIRCULAR)"); ++ continue; ++ } ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + ":"); ++ dumpChunkInfo(seenChunks, neighbor, nx, nz, indent + 1, maxDepth); ++ } ++ } ++ + } + } + +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index d18497a33dc53f6b465e659967bf8c98731c46c0..9a5737caf250dd2cc7f244248226f69117b27bad 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -631,10 +631,10 @@ public final class MCUtil { + + // sorting by coordinate makes the log easier to read + allChunks.sort((ChunkHolder v1, ChunkHolder v2) -> { +- if (v1.location.x != v2.location.x) { +- return Integer.compare(v1.location.x, v2.location.x); ++ if (v1.pos.x != v2.pos.x) { ++ return Integer.compare(v1.pos.x, v2.pos.x); + } +- return Integer.compare(v1.location.z, v2.location.z); ++ return Integer.compare(v1.pos.z, v2.pos.z); + }); + + worldData.addProperty("name", world.getWorld().getName()); +@@ -667,14 +667,15 @@ public final class MCUtil { + for (ChunkHolder playerChunk : allChunks) { + JsonObject chunkData = new JsonObject(); + +- Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.pair()); ++ Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.toLong()); + ChunkStatus status = getChunkStatus(playerChunk); + +- chunkData.addProperty("x", playerChunk.location.x); +- chunkData.addProperty("z", playerChunk.location.z); ++ chunkData.addProperty("x", playerChunk.pos.x); ++ chunkData.addProperty("z", playerChunk.pos.z); + chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); ++ chunkData.addProperty("priority", playerChunk.getCurrentPriority()); + chunkData.addProperty("state", ChunkHolder.getFullChunkStatus(playerChunk.getTicketLevel()).toString()); +- chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.pair())); ++ chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.toLong())); + chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); + + JsonArray ticketsData = new JsonArray(); +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index d907872d80f840b343419f49a6708082da6f921b..ce320672d7602c94dd75ad857435dca6ac3bab56 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -1,6 +1,7 @@ + package net.minecraft.server.level; + + import com.mojang.datafixers.util.Either; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper + import it.unimi.dsi.fastutil.shorts.ShortArraySet; + import it.unimi.dsi.fastutil.shorts.ShortSet; + import java.util.List; +@@ -19,6 +20,7 @@ import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; + import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; + import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; + import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; ++import net.minecraft.server.MCUtil; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LightLayer; +@@ -52,8 +54,8 @@ public class ChunkHolder { + private CompletableFuture chunkToSave; + public int oldTicketLevel; + private int ticketLevel; +- private int queueLevel; +- final ChunkPos pos; // Paper - private -> package ++ volatile int queueLevel; public final int getCurrentPriority() { return queueLevel; } // Paper - OBFHELPER - make volatile since this is concurrently accessed ++ public final ChunkPos pos; // Paper - private -> public + private boolean hasChangedSections; + private final ShortSet[] changedBlocksPerSection; + private int blockChangedLightSectionFilter; +@@ -65,6 +67,7 @@ public class ChunkHolder { + private boolean resendLight; + + private final ChunkMap chunkMap; // Paper ++ public ServerLevel getWorld() { return chunkMap.level; } // Paper + + long lastAutoSaveTime; // Paper - incremental autosave + long inactiveTimeStart; // Paper - incremental autosave +@@ -92,6 +95,120 @@ public class ChunkHolder { + return null; + } + // Paper end - no-tick view distance ++ // Paper start - Chunk gen/load priority system ++ volatile int neighborPriority = -1; ++ volatile int priorityBoost = 0; ++ public final java.util.concurrent.ConcurrentHashMap neighbors = new java.util.concurrent.ConcurrentHashMap<>(); ++ public final Long2ObjectOpenHashMap neighborPriorities = new Long2ObjectOpenHashMap<>(); ++ ++ private int getDemandedPriority() { ++ int priority = neighborPriority; // if we have a neighbor priority, use it ++ int myPriority = getMyPriority(); ++ ++ if (priority == -1 || (ticketLevel <= 33 && priority > myPriority)) { ++ priority = myPriority; ++ } ++ ++ return Math.max(1, Math.min(Math.max(ticketLevel, ChunkMap.MAX_CHUNK_DISTANCE), priority)); ++ } ++ ++ private int getMyPriority() { ++ if (priorityBoost == DistanceManager.URGENT_PRIORITY) { ++ return 2; // Urgent - ticket level isn't always 31 so 33-30 = 3, but allow 1 more tasks to go below this for dependents ++ } ++ return ticketLevel - priorityBoost; ++ } ++ ++ private int getNeighborsPriority() { ++ return (neighborPriorities.isEmpty() ? getMyPriority() : getDemandedPriority()) + 1; ++ } ++ ++ public void onNeighborRequest(ChunkHolder neighbor, ChunkStatus status) { ++ neighbor.setNeighborPriority(this, getNeighborsPriority()); ++ this.neighbors.compute(neighbor, (playerChunk, currentWantedStatus) -> { ++ if (currentWantedStatus == null || !currentWantedStatus.isAtLeastStatus(status)) { ++ //System.out.println(this + " request " + neighbor + " at " + status + " currently " + currentWantedStatus); ++ return status; ++ } else { ++ //System.out.println(this + " requested " + neighbor + " at " + status + " but thats lower than other wanted status " + currentWantedStatus); ++ return currentWantedStatus; ++ } ++ }); ++ ++ } ++ ++ public void onNeighborDone(ChunkHolder neighbor, ChunkStatus chunkstatus, ChunkAccess chunk) { ++ this.neighbors.compute(neighbor, (playerChunk, wantedStatus) -> { ++ if (wantedStatus != null && chunkstatus.isAtLeastStatus(wantedStatus)) { ++ //System.out.println(this + " neighbor done at " + neighbor + " for status " + chunkstatus + " wanted " + wantedStatus); ++ neighbor.removeNeighborPriority(this); ++ return null; ++ } else { ++ //System.out.println(this + " neighbor finished our previous request at " + neighbor + " for status " + chunkstatus + " but we now want instead " + wantedStatus); ++ return wantedStatus; ++ } ++ }); ++ } ++ ++ private void removeNeighborPriority(ChunkHolder requester) { ++ synchronized (neighborPriorities) { ++ neighborPriorities.remove(requester.pos.toLong()); ++ recalcNeighborPriority(); ++ } ++ checkPriority(); ++ } ++ ++ ++ private void setNeighborPriority(ChunkHolder requester, int priority) { ++ synchronized (neighborPriorities) { ++ neighborPriorities.put(requester.pos.toLong(), Integer.valueOf(priority)); ++ recalcNeighborPriority(); ++ } ++ checkPriority(); ++ } ++ ++ private void recalcNeighborPriority() { ++ neighborPriority = -1; ++ if (!neighborPriorities.isEmpty()) { ++ synchronized (neighborPriorities) { ++ for (Integer neighbor : neighborPriorities.values()) { ++ if (neighbor < neighborPriority || neighborPriority == -1) { ++ neighborPriority = neighbor; ++ } ++ } ++ } ++ } ++ } ++ private void checkPriority() { ++ if (getCurrentPriority() != getDemandedPriority()) this.chunkMap.queueHolderUpdate(this); ++ } ++ ++ public final double getDistance(ServerPlayer player) { ++ return getDistance(player.getX(), player.getZ()); ++ } ++ public final double getDistance(double blockX, double blockZ) { ++ int cx = MCUtil.fastFloor(blockX) >> 4; ++ int cz = MCUtil.fastFloor(blockZ) >> 4; ++ final double x = pos.x - cx; ++ final double z = pos.z - cz; ++ return (x * x) + (z * z); ++ } ++ ++ public final double getDistanceFrom(BlockPos pos) { ++ return getDistance(pos.getX(), pos.getZ()); ++ } ++ ++ @Override ++ public String toString() { ++ return "PlayerChunk{" + ++ "location=" + pos + ++ ", ticketLevel=" + ticketLevel + "/" + getStatus(this.ticketLevel) + ++ ", chunkHolderStatus=" + getChunkHolderStatus() + ++ ", neighborPriority=" + getNeighborsPriority() + ++ ", priority=(" + ticketLevel + " - " + priorityBoost +" vs N " + neighborPriority + ") = " + getDemandedPriority() + " A " + getCurrentPriority() + ++ '}'; ++ } ++ // Paper end + + public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); +@@ -194,6 +311,18 @@ public class ChunkHolder { + } + return null; + } ++ public static ChunkStatus getNextStatus(ChunkStatus status) { ++ if (status == ChunkStatus.FULL) { ++ return status; ++ } ++ return CHUNK_STATUSES.get(status.getStatusIndex() + 1); ++ } ++ public CompletableFuture> getStatusFutureUncheckedMain(ChunkStatus chunkstatus) { ++ return ensureMain(getFutureIfPresentUnchecked(chunkstatus)); ++ } ++ public CompletableFuture ensureMain(CompletableFuture future) { ++ return future.thenApplyAsync(r -> r, chunkMap.mainInvokingExecutor); ++ } + // Paper end + + public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { +@@ -440,6 +569,7 @@ public class ChunkHolder { + return this.queueLevel; + } + ++ private void setPriority(int i) { setQueueLevel(i); } // Paper - OBFHELPER + private void setQueueLevel(int level) { + this.queueLevel = level; + } +@@ -458,7 +588,7 @@ public class ChunkHolder { + // CraftBukkit start + // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. + if (playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { +- this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main + LevelChunk chunk = (LevelChunk)either.left().orElse(null); + if (chunk != null) { + chunkStorage.callbackExecutor.execute(() -> { +@@ -523,12 +653,13 @@ public class ChunkHolder { + if (!flag2 && flag3) { + // Paper start - cache ticking ready status + int expectCreateCount = ++this.fullChunkCreateCount; +- this.fullChunkFuture = chunkStorage.unpackTicks(this); this.fullChunkFuture.thenAccept((either) -> { ++ this.fullChunkFuture = chunkStorage.unpackTicks(this); ensureMain(this.fullChunkFuture).thenAccept((either) -> { // Paper - ensure main + if (either.left().isPresent() && ChunkHolder.this.fullChunkCreateCount == expectCreateCount) { + // note: Here is a very good place to add callbacks to logic waiting on this. + LevelChunk fullChunk = either.left().get(); + ChunkHolder.this.isFullChunkReady = true; + fullChunk.playerChunk = ChunkHolder.this; ++ this.chunkMap.distanceManager.clearPriorityTickets(pos); + + + } +@@ -553,7 +684,7 @@ public class ChunkHolder { + + if (!flag4 && flag5) { + // Paper start - cache ticking ready status +- this.tickingChunkFuture = chunkStorage.postProcess(this); this.tickingChunkFuture.thenAccept((either) -> { ++ this.tickingChunkFuture = chunkStorage.postProcess(this); ensureMain(this.tickingChunkFuture).thenAccept((either) -> { // Paper - ensure main + if (either.left().isPresent()) { + // note: Here is a very good place to add callbacks to logic waiting on this. + LevelChunk tickingChunk = either.left().get(); +@@ -584,7 +715,7 @@ public class ChunkHolder { + } + + // Paper start - cache ticking ready status +- this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); this.entityTickingChunkFuture.thenAccept((either) -> { ++ this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); ensureMain(this.entityTickingChunkFuture).thenAccept((either) -> { // Paper ensureMain + if (either.left().isPresent()) { + // note: Here is a very good place to add callbacks to logic waiting on this. + LevelChunk entityTickingChunk = either.left().get(); +@@ -604,12 +735,29 @@ public class ChunkHolder { + this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + } + +- this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); ++ // Paper start - raise IO/load priority if priority changes, use our preferred priority ++ priorityBoost = chunkMap.distanceManager.getChunkPriority(pos); ++ int priority = getDemandedPriority(); ++ if (getCurrentPriority() > priority) { ++ int ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; ++ if (priority <= 10) { ++ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; ++ } else if (priority <= 20) { ++ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; ++ } ++ chunkMap.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, ioPriority); ++ } ++ if (getCurrentPriority() != priority) { ++ this.onLevelChange.onLevelChange(this.pos, this::getCurrentPriority, priority, this::setPriority); // use preferred priority ++ int neighborsPriority = getNeighborsPriority(); ++ this.neighbors.forEach((neighbor, neighborDesired) -> neighbor.setNeighborPriority(this, neighborsPriority)); ++ } ++ // Paper end + this.oldTicketLevel = this.ticketLevel; + // CraftBukkit start + // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. + if (!playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { +- this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main + LevelChunk chunk = (LevelChunk)either.left().orElse(null); + if (chunk != null) { + chunkStorage.callbackExecutor.execute(() -> { +@@ -691,6 +839,7 @@ public class ChunkHolder { + + public interface LevelChangeListener { + ++ default void changePriority(ChunkPos chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer) { onLevelChange(chunkcoordintpair, intsupplier, i, intconsumer); } // Paper - OBFHELPER + void onLevelChange(ChunkPos pos, IntSupplier levelGetter, int targetLevel, IntConsumer levelSetter); + } + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c06720820 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -14,6 +14,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; + import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + import it.unimi.dsi.fastutil.longs.Long2ByteMap; + import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; // Paper + import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; + import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; + import it.unimi.dsi.fastutil.longs.LongIterator; +@@ -51,6 +52,7 @@ import net.minecraft.CrashReport; + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; + import net.minecraft.Util; ++import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.protocol.Packet; +@@ -102,6 +104,7 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + import org.bukkit.entity.Player; // CraftBukkit ++import org.spigotmc.AsyncCatcher; + + public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider { + +@@ -139,6 +142,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final ServerLevel level; + private final ThreadedLevelLightEngine lightEngine; + private final BlockableEventLoop mainThreadExecutor; ++ final java.util.concurrent.Executor mainInvokingExecutor; // Paper + public final ChunkGenerator generator; + private final Supplier overworldDataStorage; public final Supplier getWorldPersistentDataSupplier() { return this.overworldDataStorage; } // Paper - OBFHELPER + private final PoiManager poiManager; +@@ -176,6 +180,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + @Override + public void execute(Runnable runnable) { ++ AsyncCatcher.catchOp("Callback Executor execute"); + if (queued == null) { + queued = new java.util.ArrayDeque<>(); + } +@@ -184,6 +189,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + @Override + public void run() { ++ AsyncCatcher.catchOp("Callback Executor run"); + if (queued == null) { + return; + } +@@ -338,6 +344,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.level = worldserver; + this.generator = chunkGenerator; + this.mainThreadExecutor = mainThreadExecutor; ++ // Paper start ++ this.mainInvokingExecutor = (run) -> { ++ if (MCUtil.isMainThread()) { ++ run.run(); ++ } else { ++ mainThreadExecutor.execute(run); ++ } ++ }; ++ // Paper end + ProcessorMailbox threadedmailbox = ProcessorMailbox.create(workerExecutor, "worldgen"); + + mainThreadExecutor.getClass(); +@@ -432,6 +447,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, + (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ checkHighPriorityChunks(player); + if (newState.size() != 1) { + return; + } +@@ -450,7 +466,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); + ChunkMap.this.level.getChunkSource().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update +- }); ++ ChunkMap.this.level.getChunkSource().clearPriorityTickets(chunkPos); ++ }, (player, prevPos, newPos) -> { ++ player.lastHighPriorityChecked = -1; // reset and recheck ++ checkHighPriorityChunks(player); ++ }); + this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); + this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, + (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, +@@ -467,6 +487,115 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }); + // Paper end - no-tick view distance + } ++ // Paper start - Chunk Prioritization ++ public void queueHolderUpdate(ChunkHolder playerchunk) { ++ Runnable runnable = () -> { ++ if (isUnloading(playerchunk)) { ++ return; // unloaded ++ } ++ distanceManager.pendingChunkUpdates.add(playerchunk); ++ if (!distanceManager.pollingPendingChunkUpdates) { ++ level.getChunkSource().runDistanceManagerUpdates(); ++ } ++ }; ++ if (MCUtil.isMainThread()) { ++ // We can't use executor here because it will not execute tasks if its currently in the middle of executing tasks... ++ runnable.run(); ++ } else { ++ mainThreadExecutor.execute(runnable); ++ } ++ } ++ ++ private boolean isUnloading(ChunkHolder playerchunk) { ++ return playerchunk == null || toDrop.contains(playerchunk.pos.toLong()); ++ } ++ ++ private void updateChunkPriorityMap(Long2IntOpenHashMap map, long chunk, int level) { ++ int prev = map.getOrDefault(chunk, -1); ++ if (level > prev) { ++ map.put(chunk, level); ++ } ++ } ++ ++ public void checkHighPriorityChunks(ServerPlayer player) { ++ int currentTick = MinecraftServer.currentTick; ++ if (currentTick - player.lastHighPriorityChecked < 20 || !player.isRealPlayer) { // weed out fake players ++ return; ++ } ++ player.lastHighPriorityChecked = currentTick; ++ Long2IntOpenHashMap priorities = new Long2IntOpenHashMap(); ++ ++ int viewDistance = getEffectiveNoTickViewDistance(); ++ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); ++ ++ // Prioritize circular near ++ double playerChunkX = Mth.floor(player.getX()) >> 4; ++ double playerChunkZ = Mth.floor(player.getZ()) >> 4; ++ pos.setValues(player.getX(), 0, player.getZ()); ++ double twoThirdModifier = 2D / 3D; ++ MCUtil.getSpiralOutChunks(pos, Math.min(6, viewDistance)).forEach(coord -> { ++ if (shouldSkipPrioritization(coord)) return; ++ ++ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); ++ // Prioritize immediate ++ if (dist <= 4) { ++ updateChunkPriorityMap(priorities, coord.toLong(), (int) (27 - dist)); ++ return; ++ } ++ ++ // Prioritize nearby chunks ++ updateChunkPriorityMap(priorities, coord.toLong(), (int) (20 - dist * twoThirdModifier)); ++ }); ++ ++ // Prioritize Frustum near 3 ++ ChunkPos front3 = player.getChunkInFront(3); ++ pos.setValues(front3.x << 4, 0, front3.z << 4); ++ MCUtil.getSpiralOutChunks(pos, Math.min(5, viewDistance)).forEach(coord -> { ++ if (shouldSkipPrioritization(coord)) return; ++ ++ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); ++ updateChunkPriorityMap(priorities, coord.toLong(), (int) (25 - dist * twoThirdModifier)); ++ }); ++ ++ // Prioritize Frustum near 5 ++ if (viewDistance > 4) { ++ ChunkPos front5 = player.getChunkInFront(5); ++ pos.setValues(front5.x << 4, 0, front5.z << 4); ++ MCUtil.getSpiralOutChunks(pos, 4).forEach(coord -> { ++ if (shouldSkipPrioritization(coord)) return; ++ ++ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); ++ updateChunkPriorityMap(priorities, coord.toLong(), (int) (25 - dist * twoThirdModifier)); ++ }); ++ } ++ ++ // Prioritize Frustum far 7 ++ if (viewDistance > 6) { ++ ChunkPos front7 = player.getChunkInFront(7); ++ pos.setValues(front7.x << 4, 0, front7.z << 4); ++ MCUtil.getSpiralOutChunks(pos, 3).forEach(coord -> { ++ if (shouldSkipPrioritization(coord)) { ++ return; ++ } ++ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); ++ updateChunkPriorityMap(priorities, coord.toLong(), (int) (25 - dist * twoThirdModifier)); ++ }); ++ } ++ ++ if (priorities.isEmpty()) return; ++ distanceManager.delayDistanceManagerTick = true; ++ priorities.long2IntEntrySet().fastForEach(entry -> distanceManager.markHighPriority(new ChunkPos(entry.getLongKey()), entry.getIntValue())); ++ distanceManager.delayDistanceManagerTick = false; ++ level.getChunkSource().runDistanceManagerUpdates(); ++ ++ } ++ ++ private boolean shouldSkipPrioritization(ChunkPos coord) { ++ if (playerViewDistanceNoTickMap.getObjectsInRange(coord.toLong()) == null) return true; ++ ChunkHolder chunk = getUpdatingChunkIfPresent(coord.toLong()); ++ return chunk != null && (chunk.isFullChunkReady()); ++ } ++ // Paper end + + public void updatePlayerMobTypeMap(Entity entity) { + if (!this.level.paperConfig.perPlayerMobSpawns) { +@@ -596,6 +725,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + List>> list = Lists.newArrayList(); + int j = centerChunk.x; + int k = centerChunk.z; ++ ChunkHolder requestingNeighbor = getUpdatingChunkIfPresent(centerChunk.toLong()); // Paper + + for (int l = -margin; l <= margin; ++l) { + for (int i1 = -margin; i1 <= margin; ++i1) { +@@ -614,6 +744,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + ChunkStatus chunkstatus = (ChunkStatus) distanceToStatus.apply(j1); + CompletableFuture> completablefuture = playerchunk.getOrScheduleFuture(chunkstatus, this); ++ // Paper start ++ if (requestingNeighbor != null && requestingNeighbor != playerchunk && !completablefuture.isDone()) { ++ requestingNeighbor.onNeighborRequest(playerchunk, chunkstatus); ++ completablefuture.thenAccept(either -> { ++ requestingNeighbor.onNeighborDone(playerchunk, chunkstatus, either.left().orElse(null)); ++ }); ++ } ++ // Paper end + + list.add(completablefuture); + } +@@ -1081,14 +1219,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }; + + CompletableFuture chunkSaveFuture = this.level.asyncChunkTaskManager.getChunkSaveFuture(pos.x, pos.z); ++ ChunkHolder playerChunk = getUpdatingChunkIfPresent(pos.toLong()); ++ int chunkPriority = playerChunk != null ? playerChunk.getCurrentPriority() : 33; ++ int priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; ++ ++ if (chunkPriority <= 10) { ++ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; ++ } else if (chunkPriority <= 20) { ++ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; ++ } ++ boolean isHighestPriority = priority == com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; + if (chunkSaveFuture != null) { +- this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, +- com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); +- this.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); ++ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, priority, chunkHolderConsumer, isHighestPriority, chunkSaveFuture); + } else { +- this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, +- com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); ++ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, priority, chunkHolderConsumer, isHighestPriority); + } ++ this.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, priority); + return ret; + // Paper end + } +@@ -1233,7 +1379,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + long i = playerchunk.getPos().toLong(); + + playerchunk.getClass(); +- mailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, playerchunk::getTicketLevel)); ++ mailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, () -> 1)); // Paper - final loads are always urgent! + }); + } + +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a906f07e97 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -21,7 +21,10 @@ import java.util.Set; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.Executor; + import javax.annotation.Nullable; ++import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.util.SortedArraySet; + import net.minecraft.util.thread.ProcessorHandle; + import net.minecraft.world.level.ChunkPos; +@@ -29,6 +32,7 @@ import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.LevelChunk; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import org.spigotmc.AsyncCatcher; // Paper + + public abstract class DistanceManager { + +@@ -52,7 +56,7 @@ public abstract class DistanceManager { + private final ChunkTaskPriorityQueueSorter ticketThrottler; + private final ProcessorHandle> ticketThrottlerInput; + private final ProcessorHandle ticketThrottlerReleaser; +- private final LongSet ticketsToRelease = new LongOpenHashSet(); ++ private final LongSet ticketsToRelease = new LongOpenHashSet(); public final LongSet getOnPlayerTicketAddQueue() { return ticketsToRelease; } // Paper - OBFHELPER + private final Executor mainThreadExecutor; + private long ticketTickCounter; + +@@ -90,6 +94,7 @@ public abstract class DistanceManager { + } + + private static int getTicketLevelAt(SortedArraySet> arraysetsorted) { ++ AsyncCatcher.catchOp("ChunkMapDistance::getLowestTicketLevel"); // Paper + return !arraysetsorted.isEmpty() ? ((Ticket) arraysetsorted.first()).getTicketLevel() : ChunkMap.MAX_CHUNK_DISTANCE + 1; + } + +@@ -103,6 +108,7 @@ public abstract class DistanceManager { + + public boolean runAllUpdates(ChunkMap chunkStorage) { + //this.f.a(); // Paper - no longer used ++ AsyncCatcher.catchOp("DistanceManagerTick"); // Paper + this.playerTicketManager.runAllUpdates(); + int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE); + boolean flag = i != 0; +@@ -113,11 +119,13 @@ public abstract class DistanceManager { + + // Paper start + if (!this.pendingChunkUpdates.isEmpty()) { ++ this.pollingPendingChunkUpdates = true; try { + while(!this.pendingChunkUpdates.isEmpty()) { + ChunkHolder remove = this.pendingChunkUpdates.remove(); + remove.isUpdateQueued = false; + remove.updateFutures(chunkStorage); + } ++ } finally { this.pollingPendingChunkUpdates = false; } + // Paper end + return true; + } else { +@@ -153,8 +161,10 @@ public abstract class DistanceManager { + return flag; + } + } ++ boolean pollingPendingChunkUpdates = false; // Paper + + private boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ AsyncCatcher.catchOp("ChunkMapDistance::addTicket"); // Paper + SortedArraySet> arraysetsorted = this.getTickets(i); + int j = getTicketLevelAt(arraysetsorted); + Ticket ticket1 = (Ticket) arraysetsorted.addOrGet(ticket); // CraftBukkit - decompile error +@@ -168,7 +178,9 @@ public abstract class DistanceManager { + } + + private boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ AsyncCatcher.catchOp("ChunkMapDistance::removeTicket"); // Paper + SortedArraySet> arraysetsorted = this.getTickets(i); ++ int oldLevel = getTicketLevelAt(arraysetsorted); // Paper + + boolean removed = false; // CraftBukkit + if (arraysetsorted.remove(ticket)) { +@@ -179,7 +191,8 @@ public abstract class DistanceManager { + this.tickets.remove(i); + } + +- this.ticketTracker.update(i, getTicketLevelAt(arraysetsorted), false); ++ int newLevel = getTicketLevelAt(arraysetsorted); // Paper ++ if (newLevel > oldLevel) this.ticketTracker.update(i, newLevel, false); // Paper + return removed; // CraftBukkit + } + +@@ -188,6 +201,135 @@ public abstract class DistanceManager { + this.addTicketAtLevel(type, pos, level, argument); + } + ++ // Paper start ++ public static final int PRIORITY_TICKET_LEVEL = ChunkMap.MAX_CHUNK_DISTANCE; ++ public static final int URGENT_PRIORITY = 29; ++ public boolean delayDistanceManagerTick = false; ++ public boolean markUrgent(ChunkPos coords) { ++ return addPriorityTicket(coords, TicketType.URGENT, URGENT_PRIORITY); ++ } ++ public boolean markHighPriority(ChunkPos coords, int priority) { ++ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); ++ return addPriorityTicket(coords, TicketType.PRIORITY, priority); ++ } ++ ++ public void markAreaHighPriority(ChunkPos center, int priority, int radius) { ++ delayDistanceManagerTick = true; ++ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); ++ int finalPriority = priority; ++ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { ++ addPriorityTicket(coords, TicketType.PRIORITY, finalPriority); ++ }); ++ delayDistanceManagerTick = false; ++ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); ++ } ++ ++ public void clearAreaPriorityTickets(ChunkPos center, int radius) { ++ delayDistanceManagerTick = true; ++ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { ++ this.removeTicket(coords.toLong(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); ++ }); ++ delayDistanceManagerTick = false; ++ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); ++ } ++ ++ private boolean hasPlayerTicket(ChunkPos coords, int level) { ++ SortedArraySet> tickets = this.tickets.get(coords.toLong()); ++ if (tickets == null || tickets.isEmpty()) { ++ return false; ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getType() == TicketType.PLAYER && ticket.getTicketLevel() == level) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ private boolean addPriorityTicket(ChunkPos coords, TicketType ticketType, int priority) { ++ AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket"); ++ long pair = coords.toLong(); ++ ChunkHolder chunk = chunkMap.getUpdatingChunkIfPresent(pair); ++ boolean needsTicket = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(pair) != null && !hasPlayerTicket(coords, 33); ++ ++ if (needsTicket) { ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); ++ getOnPlayerTicketAddQueue().add(pair); ++ addTicket(pair, ticket); ++ } ++ if ((chunk != null && chunk.isFullChunkReady())) { ++ if (needsTicket) { ++ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); ++ } ++ return needsTicket; ++ } ++ ++ boolean success; ++ if (!(success = updatePriorityTicket(coords, ticketType, priority))) { ++ Ticket ticket = new Ticket(ticketType, PRIORITY_TICKET_LEVEL, coords); ++ ticket.priority = priority; ++ success = this.addTicket(pair, ticket); ++ } else { ++ if (chunk == null) { ++ chunk = chunkMap.getUpdatingChunkIfPresent(pair); ++ } ++ chunkMap.queueHolderUpdate(chunk); ++ } ++ ++ //chunkMap.world.getWorld().spawnParticle(priority <= 15 ? org.bukkit.Particle.EXPLOSION_HUGE : org.bukkit.Particle.EXPLOSION_NORMAL, chunkMap.world.getWorld().getPlayers(), null, coords.x << 4, 70, coords.z << 4, 2, 0, 0, 0, 1, null, true); ++ ++ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); ++ ++ return success; ++ } ++ ++ private boolean updatePriorityTicket(ChunkPos coords, TicketType type, int priority) { ++ SortedArraySet> tickets = this.tickets.get(coords.toLong()); ++ if (tickets == null) { ++ return false; ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getType() == type) { ++ // We only support increasing, not decreasing, too complicated ++ ticket.setCurrentTick(this.ticketTickCounter); ++ ticket.priority = Math.max(ticket.priority, priority); ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ public int getChunkPriority(ChunkPos coords) { ++ AsyncCatcher.catchOp("ChunkMapDistance::getChunkPriority"); ++ SortedArraySet> tickets = this.tickets.get(coords.toLong()); ++ if (tickets == null) { ++ return 0; ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getType() == TicketType.URGENT) { ++ return URGENT_PRIORITY; ++ } ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getType() == TicketType.PRIORITY && ticket.priority > 0) { ++ return ticket.priority; ++ } ++ } ++ return 0; ++ } ++ ++ public void clearPriorityTickets(ChunkPos coords) { ++ AsyncCatcher.catchOp("ChunkMapDistance::clearPriority"); ++ this.removeTicket(coords.toLong(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); ++ } ++ ++ public void clearUrgent(ChunkPos coords) { ++ AsyncCatcher.catchOp("ChunkMapDistance::clearUrgent"); ++ this.removeTicket(coords.toLong(), new Ticket(TicketType.URGENT, PRIORITY_TICKET_LEVEL, coords)); ++ } ++ // Paper end + public boolean addTicketAtLevel(TicketType ticketType, ChunkPos chunkcoordintpair, int level, T identifier) { + return this.addTicket(chunkcoordintpair.toLong(), new Ticket<>(ticketType, level, identifier)); + // CraftBukkit end +@@ -358,7 +500,7 @@ public abstract class DistanceManager { + + class PlayerTicketTracker extends DistanceManager.FixedPlayerDistanceChunkTracker { + +- private int viewDistance = 0; ++ private int viewDistance = 0; private int getViewDistance() { return viewDistance; } private void setViewDistance(int value) { this.viewDistance = value; } // Paper - OBFHELPER + private final Long2IntMap queueLevels = Long2IntMaps.synchronize(new Long2IntOpenHashMap()); + private final LongSet toUpdate = new LongOpenHashSet(); + +@@ -374,41 +516,68 @@ public abstract class DistanceManager { + + public void updateViewDistance(int watchDistance) { + ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); ++ // Paper start - set the view distance before scheduling chunk loads/unloads ++ int lastViewDistance = getViewDistance(); ++ setViewDistance(watchDistance); ++ // Paper end + + while (objectiterator.hasNext()) { + Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix + byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); + long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); + +- this.onLevelChange(j, b0, this.haveTicketFor(b0), b0 <= watchDistance - 2); ++ this.onLevelChange(j, b0, b0 <= lastViewDistance - 2, this.haveTicketFor(b0)); // Paper + } + +- this.viewDistance = watchDistance; ++ //this.e = i; // Paper - view distance is now set further up + } + + private void onLevelChange(long pos, int distance, boolean oldWithinViewDistance, boolean withinViewDistance) { + if (oldWithinViewDistance != withinViewDistance) { +- Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkPos(pos)); // Paper - no-tick view distance ++ ChunkPos coords = new ChunkPos(pos); // Paper ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); // Paper - no-tick view distance + + if (withinViewDistance) { +- DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { ++ scheduleChunkLoad(pos, MinecraftServer.currentTick, distance, (priority) -> { // Paper - smarter ticket delay based on frustum and distance ++ // Paper start - recheck its still valid if not cancel ++ if (!isChunkInRange(pos)) { ++ DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { ++ DistanceManager.this.mainThreadExecutor.execute(() -> { ++ DistanceManager.this.removeTicket(pos, ticket); ++ DistanceManager.this.clearPriorityTickets(coords); ++ }); ++ }, pos, false)); ++ return; ++ } ++ // abort early if we got a ticket already ++ if (hasPlayerTicket(coords, 33)) return; ++ // skip player ticket throttle for near chunks ++ if (priority <= 3) { ++ DistanceManager.this.addTicket(pos, ticket); ++ DistanceManager.this.ticketsToRelease.add(pos); ++ return; ++ } ++ // Paper end ++ DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { // CraftBukkit - decompile error + DistanceManager.this.mainThreadExecutor.execute(() -> { +- if (this.haveTicketFor(this.getLevel(pos))) { ++ if (isChunkInRange(pos)) { if (!hasPlayerTicket(coords, 33)) { // Paper - high priority might of already added it + DistanceManager.this.addTicket(pos, ticket); + DistanceManager.this.ticketsToRelease.add(pos); +- } else { +- DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { ++ }} else { // Paper ++ DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { // CraftBukkit - decompile error + }, pos, false)); + } + + }); + }, pos, () -> { +- return distance; ++ return Math.min(ChunkMap.MAX_CHUNK_DISTANCE, priority); // Paper + })); ++ }); // Paper + } else { + DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { + DistanceManager.this.mainThreadExecutor.execute(() -> { + DistanceManager.this.removeTicket(pos, ticket); ++ DistanceManager.this.clearPriorityTickets(coords); // Paper + }); + }, pos, true)); + } +@@ -416,6 +585,101 @@ public abstract class DistanceManager { + + } + ++ // Paper start - smart scheduling of player tickets ++ private boolean isChunkInRange(long i) { ++ return this.isLoadedChunkLevel(this.getChunkLevel(i)); ++ } ++ public void scheduleChunkLoad(long i, long startTick, int initialDistance, java.util.function.Consumer task) { ++ long elapsed = MinecraftServer.currentTick - startTick; ++ ChunkPos chunkPos = new ChunkPos(i); ++ ChunkHolder updatingChunk = chunkMap.getUpdatingChunkIfPresent(i); ++ if ((updatingChunk != null && updatingChunk.isFullChunkReady()) || !isChunkInRange(i) || getChunkPriority(chunkPos) > 0) { // Copied from above ++ // no longer needed ++ task.accept(1); ++ return; ++ } ++ ++ int desireDelay = 0; ++ double minDist = Double.MAX_VALUE; ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(i); ++ if (elapsed == 0 && initialDistance <= 4) { ++ // Aim for no delay on initial 6 chunk radius tickets save on performance of the below code to only > 6 ++ minDist = initialDistance; ++ } else if (players != null) { ++ Object[] backingSet = players.getBackingSet(); ++ ++ BlockPos blockPos = chunkPos.asPosition(); ++ ++ boolean isFront = false; ++ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); ++ for (int index = 0, len = backingSet.length; index < len; ++index) { ++ if (!(backingSet[index] instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer) backingSet[index]; ++ ++ ChunkPos pointInFront = player.getChunkInFront(5); ++ pos.setValues(pointInFront.x << 4, 0, pointInFront.z << 4); ++ double frontDist = MCUtil.distanceSq(pos, blockPos); ++ ++ pos.setValues(player.getX(), 0, player.getZ()); ++ double center = MCUtil.distanceSq(pos, blockPos); ++ ++ double dist = Math.min(frontDist, center); ++ if (!isFront) { ++ ChunkPos pointInBack = player.getChunkInFront(-7); ++ pos.setValues(pointInBack.x << 4, 0, pointInBack.z << 4); ++ double backDist = MCUtil.distanceSq(pos, blockPos); ++ if (frontDist < backDist) { ++ isFront = true; ++ } ++ } ++ if (dist < minDist) { ++ minDist = dist; ++ } ++ } ++ if (minDist == Double.MAX_VALUE) { ++ minDist = 15; ++ } else { ++ minDist = Math.sqrt(minDist) / 16; ++ } ++ if (minDist > 4) { ++ int desiredTimeDelayMax = isFront ? ++ (minDist < 10 ? 7 : 15) : // Front ++ (minDist < 10 ? 15 : 45); // Back ++ desireDelay += (desiredTimeDelayMax * 20) * (minDist / 32); ++ } ++ } else { ++ minDist = initialDistance; ++ desireDelay = 1; ++ } ++ long delay = desireDelay - elapsed; ++ if (delay <= 0 && minDist > 4 && minDist < Double.MAX_VALUE) { ++ boolean hasAnyNeighbor = false; ++ for (int x = -1; x <= 1; x++) { ++ for (int z = -1; z <= 1; z++) { ++ if (x == 0 && z == 0) continue; ++ long pair = ChunkPos.asLong(chunkPos.x + x, chunkPos.z + z); ++ ChunkHolder neighbor = chunkMap.getUpdatingChunkIfPresent(pair); ++ ChunkStatus current = neighbor != null ? neighbor.getChunkHolderStatus() : null; ++ if (current != null && current.isAtLeastStatus(ChunkStatus.LIGHT)) { ++ hasAnyNeighbor = true; ++ } ++ } ++ } ++ if (!hasAnyNeighbor) { ++ delay += 20; ++ } ++ } ++ if (delay <= 0) { ++ task.accept((int) minDist); ++ } else { ++ int taskDelay = (int) Math.min(delay, minDist >= 10 ? 40 : (minDist < 6 ? 5 : 20)); ++ MCUtil.scheduleTask(taskDelay, () -> scheduleChunkLoad(i, startTick, initialDistance, task), "Player Ticket Delayer"); ++ } ++ } ++ // Paper end ++ + @Override + public void runAllUpdates() { + super.runAllUpdates(); +@@ -447,6 +711,7 @@ public abstract class DistanceManager { + + } + ++ private boolean isLoadedChunkLevel(int i) { return haveTicketFor(i); } // Paper - OBFHELPER + private boolean haveTicketFor(int distance) { + return distance <= this.viewDistance - 2; + } +@@ -463,6 +728,7 @@ public abstract class DistanceManager { + this.chunks.defaultReturnValue((byte) (i + 2)); + } + ++ protected final int getChunkLevel(long i) { return getLevel(i); } // Paper - OBFHELPER + @Override + protected int getLevel(long id) { + return this.chunks.get(id); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd..f36badcafbad7fb4537ffdf54d9e266ae3d72459 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -467,6 +467,26 @@ public class ServerChunkCache extends ChunkSource { + public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { + this.distanceManager.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); + } ++ ++ public boolean markUrgent(ChunkPos coords) { ++ return this.distanceManager.markUrgent(coords); ++ } ++ ++ public boolean markHighPriority(ChunkPos coords, int priority) { ++ return this.distanceManager.markHighPriority(coords, priority); ++ } ++ ++ public void markAreaHighPriority(ChunkPos center, int priority, int radius) { ++ this.distanceManager.markAreaHighPriority(center, priority, radius); ++ } ++ ++ public void clearAreaPriorityTickets(ChunkPos center, int radius) { ++ this.distanceManager.clearAreaPriorityTickets(center, radius); ++ } ++ ++ public void clearPriorityTickets(ChunkPos coords) { ++ this.distanceManager.clearPriorityTickets(coords); ++ } + // Paper end + + @Nullable +@@ -505,6 +525,8 @@ public class ServerChunkCache extends ChunkSource { + + if (!completablefuture.isDone()) { // Paper + // Paper start - async chunk io/loading ++ ChunkPos pair = new ChunkPos(x1, z1); ++ this.distanceManager.markUrgent(pair); + this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); + // Paper end +@@ -513,6 +535,8 @@ public class ServerChunkCache extends ChunkSource { + this.mainThreadProcessor.managedBlock(completablefuture::isDone); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug + this.level.timings.syncChunkLoad.stopTiming(); // Paper ++ this.distanceManager.clearPriorityTickets(pair); // Paper ++ this.distanceManager.clearUrgent(pair); // Paper + } // Paper + ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { + return ichunkaccess1; +@@ -565,10 +589,12 @@ public class ServerChunkCache extends ChunkSource { + if (flag && !currentlyUnloading) { + // CraftBukkit end + this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); ++ if (isUrgent) this.distanceManager.markUrgent(chunkcoordintpair); // Paper + if (this.chunkAbsent(playerchunk, l)) { + ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + + gameprofilerfiller.push("chunkLoad"); ++ distanceManager.delayDistanceManagerTick = false; // Paper - ensure this is never false + this.runDistanceManagerUpdates(); + playerchunk = this.getVisibleChunkIfPresent(k); + gameprofilerfiller.pop(); +@@ -577,8 +603,13 @@ public class ServerChunkCache extends ChunkSource { + } + } + } +- +- return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkstatus, this.chunkMap); ++ // Paper start ++ CompletableFuture> future = this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkstatus, this.chunkMap); ++ if (isUrgent) { ++ future.thenAccept(either -> this.distanceManager.clearUrgent(chunkcoordintpair)); ++ } ++ return future; ++ // Paper end + } + + private boolean chunkAbsent(@Nullable ChunkHolder holder, int maxLevel) { +@@ -630,6 +661,7 @@ public class ServerChunkCache extends ChunkSource { + } + + public boolean runDistanceManagerUpdates() { // Paper - private -> public ++ if (distanceManager.delayDistanceManagerTick) return false; // Paper + boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); + boolean flag1 = this.chunkMap.promoteChunkMap(); + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 8e4cef60b760be385df81a74834d026f856a78c5..c5717f45a0110492aad41f21cc06fb8cbeb1f791 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -73,6 +73,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; + import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.PlayerAdvancements; + import net.minecraft.server.network.ServerGamePacketListenerImpl; +@@ -185,6 +186,12 @@ public class ServerPlayer extends Player implements ContainerListener { + private int lastRecordedArmor = Integer.MIN_VALUE; + private int lastRecordedLevel = Integer.MIN_VALUE; + private int lastRecordedExperience = Integer.MIN_VALUE; ++ public long lastHighPriorityChecked; // Paper ++ public void forceCheckHighPriority() { ++ lastHighPriorityChecked = -1; ++ getLevel().getChunkSource().chunkMap.checkHighPriorityChunks(this); ++ } ++ public boolean isRealPlayer; // Paper + private float lastSentHealth = -1.0E8F; + private int lastSentFood = -99999999; + private boolean lastFoodSaturationZero = true; +@@ -272,6 +279,21 @@ public class ServerPlayer extends Player implements ContainerListener { + this.maxHealthCache = this.getMaxHealth(); + this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper + } ++ // Paper start ++ public BlockPos getPointInFront(double inFront) { ++ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yRot+90)); // MC rotates yaw 90 for some odd reason ++ final double x = getX() + inFront * Math.cos(rads); ++ final double z = getZ() + inFront * Math.sin(rads); ++ return new BlockPos(x, getY(), z); ++ } ++ ++ public ChunkPos getChunkInFront(double inFront) { ++ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yRot+90)); // MC rotates yaw 90 for some odd reason ++ final double x = getX() + (inFront * 16) * Math.cos(rads); ++ final double z = getZ() + (inFront * 16) * Math.sin(rads); ++ return new ChunkPos(Mth.floor(x) >> 4, Mth.floor(z) >> 4); ++ } ++ // Paper end + + // Yes, this doesn't match Vanilla, but it's the best we can do for now. + // If this is an issue, PRs are welcome +@@ -619,6 +641,7 @@ public class ServerPlayer extends Player implements ContainerListener { + if (valid && !this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) + super.tick(); + } ++ if (valid && isAlive() && connection != null) ((ServerLevel)level).getChunkSource().chunkMap.checkHighPriorityChunks(this); // Paper + + for (int i = 0; i < this.inventory.getContainerSize(); ++i) { + ItemStack itemstack = this.inventory.getItem(i); +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index c6b5f32153b63ac92df9c4b31b8de168481f79f2..c0bfe136ccb9ad4fc0f8ccdd703254205213ec8e 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -8,6 +8,7 @@ public final class Ticket implements Comparable> { + private final int ticketLevel; + public final T key; public final T getObjectReason() { return this.key; } // Paper - OBFHELPER + private long createdTick; public final long getCreationTick() { return this.createdTick; } // Paper - OBFHELPER ++ public int priority = 0; // Paper + + protected Ticket(TicketType type, int level, T argument) { + this.type = type; +@@ -56,6 +57,7 @@ public final class Ticket implements Comparable> { + return this.ticketLevel; + } + ++ public final void setCurrentTick(long i) { this.setCreatedTick(i); } // Paper - OBFHELPER + protected void setCreatedTick(long tickCreated) { + this.createdTick = tickCreated; + } +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index 583587457790df826a8a3239a4bd1d0f1dcab1da..2444f6f676db543509b14e8c882491dc3f41b264 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -28,6 +28,8 @@ public class TicketType { + public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper + public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper ++ public static final TicketType PRIORITY = create("priority", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper ++ public static final TicketType URGENT = create("urgent", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper + + public static TicketType create(String name, Comparator comparator) { + return new TicketType<>(name, comparator, 0L); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 3f416479e23c60ec5b4b779cce9ab62c74865ac8..0625bc7ffd07b66b27176fe62ae3061aa7c67df2 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1528,6 +1528,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + this.awaitingTeleportTime = this.tickCount; + this.player.absMoveTo(d0, d1, d2, f, f1); ++ this.player.forceCheckHighPriority(); // Paper + this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); + } + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 8e00747c1a717836d12a43aa48d667bf801167b0..168895dab31a0d5356eb96f2642399a1c99fccab 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -271,8 +271,8 @@ public abstract class PlayerList { + final ChunkPos pos = new ChunkPos(chunkX, chunkZ); + ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; + playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.toLong()); +- worldserver1.getChunkSource().runDistanceManagerUpdates(); +- worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { ++ worldserver1.getChunkSource().markAreaHighPriority(pos, 28, 3); ++ worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, false).thenApply(chunk -> { + ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); + if (updatingChunk != null) { + return updatingChunk.getEntityTickingFuture(); +@@ -692,6 +692,7 @@ public abstract class PlayerList { + SocketAddress socketaddress = loginlistener.connection.getRemoteAddress(); + + ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameprofile, new ServerPlayerGameMode(this.server.getLevel(Level.OVERWORLD))); ++ entity.isRealPlayer = true; // Paper + Player player = entity.getBukkitEntity(); + PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.connection.getRawAddress()).getAddress()); + +@@ -898,6 +899,7 @@ public abstract class PlayerList { + // CraftBukkit end + + worldserver1.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, new ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper ++ entityplayer1.forceCheckHighPriority(); // Player + while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < 256.0D) { + entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } +diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java +index 7ccf830146c252cff8e22553d293e02d4b53dad8..4a5f318adf5bc2ca1c3fab5d173a99cddd77ab85 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkPos.java ++++ b/src/main/java/net/minecraft/world/level/ChunkPos.java +@@ -104,6 +104,7 @@ public class ChunkPos { + return "[" + this.x + ", " + this.z + "]"; + } + ++ public final BlockPos asPosition() { return getWorldPosition(); } // Paper - OBFHELPER + public BlockPos getWorldPosition() { + return new BlockPos(this.getMinBlockX(), 0, this.getMinBlockZ()); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 4fc44390f432ef13c9952aa22bbb29bc8bf47975..7261e22a71d219efe0949a08c5d3f10747759469 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2523,6 +2523,10 @@ public class CraftWorld implements World { + return future; + } + ++ if (!urgent) { ++ // if not urgent, at least use a slightly boosted priority ++ world.getChunkSource().markHighPriority(new ChunkPos(x, z), 1); ++ } + return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { + net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); + return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index eb366396820c9b6731469df4198e0884a431a77c..610eabd2e93f9efccee810c3b5a314bc3cc649d8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -60,6 +60,7 @@ import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.network.ServerGamePacketListenerImpl; + import net.minecraft.server.players.UserWhiteListEntry; ++import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.LivingEntity; +@@ -69,6 +70,7 @@ import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; ++import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.GameType; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.entity.SignBlockEntity; +@@ -848,6 +850,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + throw new UnsupportedOperationException("Cannot set rotation of players. Consider teleporting instead."); + } + ++ // Paper start ++ @Override ++ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull PlayerTeleportEvent.TeleportCause cause) { ++ ((CraftWorld)loc.getWorld()).getHandle().getChunkSource().markAreaHighPriority(new ChunkPos(Mth.floor(loc.getX()) >> 4, Mth.floor(loc.getZ()) >> 4), 28, 3); // Paper - load area high priority ++ return super.teleportAsync(loc, cause); ++ } ++ // Paper end ++ + @Override + public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) { + Preconditions.checkArgument(location != null, "location"); diff --git a/Remapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/Remapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch new file mode 100644 index 0000000000..e8add9864d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 23 May 2020 17:03:41 -0400 +Subject: [PATCH] Optimize sending packets to nearby locations (sounds/effects) + +Instead of using the entire world or player list, use the distance +maps to only iterate players who are even seeing the chunk the packet +is originating from. + +This will drastically cut down on packet sending cost for worlds with +lots of players in them. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 168895dab31a0d5356eb96f2642399a1c99fccab..713cc88dd067c0d918f253b1845f42c0d9eb920f 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1149,16 +1149,40 @@ public abstract class PlayerList { + } + + public void broadcast(@Nullable net.minecraft.world.entity.player.Player player, double x, double y, double z, double distance, ResourceKey worldKey, Packet packet) { +- for (int i = 0; i < this.players.size(); ++i) { +- ServerPlayer entityplayer = (ServerPlayer) this.players.get(i); ++ ServerLevel world = null; ++ if (player != null && player.level instanceof ServerLevel) { ++ world = (ServerLevel) player.level; ++ } + +- // CraftBukkit start - Test if player receiving packet can see the source of the packet +- if (player != null && player instanceof ServerPlayer && !entityplayer.getBukkitEntity().canSee(((ServerPlayer) player).getBukkitEntity())) { +- continue; ++ // Paper start ++ if (world == null) { ++ world = server.getLevel(worldKey); ++ } ++ ChunkMap chunkMap = world != null ? world.getChunkSource().chunkMap : null; ++ Object[] backingSet; ++ if (chunkMap == null) { ++ // Really shouldn't happen... ++ backingSet = world != null ? world.players.toArray() : players.toArray(); ++ } else { ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.fastFloor(x) >> 4, MCUtil.fastFloor(z) >> 4); ++ if (nearbyPlayers == null) { ++ return; + } ++ backingSet = nearbyPlayers.getBackingSet(); ++ } ++ ++ for (Object object : backingSet) { ++ if (!(object instanceof ServerPlayer)) continue; ++ ServerPlayer entityplayer = (ServerPlayer) object; ++ // Paper end ++ ++ // CraftBukkit start - Test if player receiving packet can see the source of the packet ++ //if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { // Paper ++ //continue; // Paper ++ //} // Paper + // CraftBukkit end + +- if (entityplayer != player && entityplayer.level.dimension() == worldKey) { ++ if (entityplayer != player && entityplayer.level.dimension() == worldKey && (!(player instanceof ServerPlayer) || entityplayer.getBukkitEntity().canSee(((ServerPlayer) player).getBukkitEntity()))) { // Paper + double d4 = x - entityplayer.getX(); + double d5 = y - entityplayer.getY(); + double d6 = z - entityplayer.getZ(); diff --git a/Remapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch b/Remapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch new file mode 100644 index 0000000000..38e09f9701 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 May 2020 23:32:14 -0400 +Subject: [PATCH] Improve Chunk Status Transition Speed + +When a chunk is loaded from disk that has already been generated, +the server has to promote the chunk through the system to reach +it's current desired status level. + +This results in every single status transition going from the main thread +to the world gen threads, only to discover it has no work it actually +needs to do.... and then it returns back to main. + +This back and forth costs a lot of time and can really delay chunk loads +when the server is under high TPS due to their being a lot of time in +between chunk load times, as well as hogs up the chunk threads from doing +actual generation and light work. + +Additionally, the whole task system uses a lot of CPU on the server threads anyways. + +So by optimizing status transitions for status's that are already complete, +we can run them to the desired level while on main thread (where it has +to happen anyways) instead of ever jumping to world gen thread. + +This will improve chunk loading effeciency to be reduced down to the following +scenario / path: + +1) MAIN: Chunk Requested, Load Request sent to ChunkTaskManager / IO Queue +2) IO: Once position in queue comes, submit read IO data and schedule to chunk task thread +3) CHUNK: Once IO is loaded and position in queue comes, deserialize the chunk data, process conversions, submit to main queue +4) MAIN: next Chunk Task process (Mid Tick or End Of Tick), load chunk data into world (POI, main thread tasks) +5) MAIN: process status transitions all the way to LIGHT, light schedules Threaded task +6) SERVER: Light tasks register light enablement for chunk and any lighting needing to be done +7) MAIN: Task returns to main, finish processing to FULL/TICKING status + +Previously would have hopped to SERVER around 12+ times there extra. + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index ce320672d7602c94dd75ad857435dca6ac3bab56..8260636da673ef095728c208db2d6237bab2db19 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -83,6 +83,13 @@ public class ChunkHolder { + this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); + } + // Paper end - optimise isOutsideOfRange ++ // Paper start - optimize chunk status progression without jumping through thread pool ++ public boolean canAdvanceStatus() { ++ ChunkStatus status = getChunkHolderStatus(); ++ ChunkAccess chunk = getAvailableChunkNow(); ++ return chunk != null && (status == null || chunk.getStatus().isAtLeastStatus(getNextStatus(status))); ++ } ++ // Paper end + + // Paper start - no-tick view distance + public final LevelChunk getSendingChunk() { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 7a1f6d1807757a43a7aa471db651404c06720820..acc566d14926dcf9e88f3e0837884e4c823d777c 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -792,7 +792,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return either.mapLeft((list) -> { + return (LevelChunk) list.get(list.size() / 2); + }); +- }, this.mainThreadExecutor); ++ }, this.mainInvokingExecutor); // Paper + } + + @Nullable +@@ -1142,7 +1142,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkAccess ichunkaccess = (ChunkAccess) optional.get(); + + if (ichunkaccess.getStatus().isOrAfter(requiredStatus)) { +- CompletableFuture completablefuture1; ++ CompletableFuture> completablefuture1; // Paper + + if (requiredStatus == ChunkStatus.LIGHT) { + completablefuture1 = this.scheduleChunkGeneration(holder, requiredStatus); +@@ -1158,7 +1158,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return this.scheduleChunkGeneration(holder, requiredStatus); + } + } +- }, this.mainThreadExecutor); ++ }, this.mainInvokingExecutor).thenComposeAsync(CompletableFuture::completedFuture, this.mainInvokingExecutor); // Paper - optimize chunk status progression without jumping through thread pool - ensure main + } + } + +@@ -1279,6 +1279,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return CompletableFuture.completedFuture(Either.right(playerchunk_failure)); + }); + }, (runnable) -> { ++ // Paper start - optimize chunk status progression without jumping through thread pool ++ if (holder.canAdvanceStatus()) { ++ this.mainInvokingExecutor.execute(runnable); ++ return; ++ } ++ // Paper end + this.worldgenMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); + }); + } diff --git a/Remapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch b/Remapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch new file mode 100644 index 0000000000..65b79cf458 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Fri, 5 Jun 2020 20:02:04 -0500 +Subject: [PATCH] Fix villager trading demand - MC-163962 + +Prevent demand from going negative and tending to negative infinity + +diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java +index 9ce1c1092970618a204f87c673144152afbade99..fa74813e0fe76612023830b2fc41d41aa0b4f10e 100644 +--- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java ++++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java +@@ -109,7 +109,7 @@ public class MerchantOffer { + } + + public void updateDemand() { +- this.demand = this.demand + this.uses - (this.maxUses - this.uses); ++ this.demand = Math.max(0, this.demand + this.uses - (this.maxUses - this.uses)); // Paper + } + + public ItemStack assemble() { diff --git a/Remapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch b/Remapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch new file mode 100644 index 0000000000..186fc75fa9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Sun, 7 Jun 2020 21:43:42 +0100 +Subject: [PATCH] Maps shouldn't load chunks + +Previously maps would load all chunks in a certain radius depending on + their scale when trying to update their content. This would result in + main thread chunk loads when they weren't really necessary, especially + on low view distances or "slow" async chunk loads after teleports or + other prioritisation. + + This changes it to only try to render already loaded chunks based on + the assumption that the chunks around the player will get loaded + eventually anyways and that maps will get checked for update every + five ticks that movement occur in anyways. + +diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java +index 1736d2eb33e5f2221210a0a4f3ceb8905555a162..05759dc6edaa790a5e3f2ca2e0ae27e53cfa4397 100644 +--- a/src/main/java/net/minecraft/world/item/MapItem.java ++++ b/src/main/java/net/minecraft/world/item/MapItem.java +@@ -119,9 +119,9 @@ public class MapItem extends ComplexItem { + int k2 = (j / i + k1 - 64) * i; + int l2 = (k / i + l1 - 64) * i; + Multiset multiset = LinkedHashMultiset.create(); +- LevelChunk chunk = world.getChunkAt(new BlockPos(k2, 0, l2)); ++ LevelChunk chunk = world.getChunkIfLoaded(new BlockPos(k2, 0, l2)); // Paper - Maps shouldn't load chunks + +- if (!chunk.isEmpty()) { ++ if (chunk != null && !chunk.isEmpty()) { // Paper - Maps shouldn't load chunks + ChunkPos chunkcoordintpair = chunk.getPos(); + int i3 = k2 & 15; + int j3 = l2 & 15; diff --git a/Remapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/Remapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch new file mode 100644 index 0000000000..356dcc464b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 7 Jun 2020 19:25:13 -0400 +Subject: [PATCH] Use seed based lookup for Treasure Maps - Fixes lag from + carto/sunken maps + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index bf4e50cd1d561456c033cda2d5c5487c5e3fe1eb..61aee2c109614a014149ae5a15ad2a28c796cb9d 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -415,8 +415,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.worldDataServer.setThundering(thundering); + } + +- @Override +- public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { ++ public Biome getBiomeBySeed(int i, int j, int k) { return getUncachedNoiseBiome(i, j, k); } // Paper - OBFHELPER ++ @Override public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { + return this.getChunkSource().getGenerator().getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ); + } + +diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java +index 05759dc6edaa790a5e3f2ca2e0ae27e53cfa4397..550892bc769a58991583b16295a72a162ceea788 100644 +--- a/src/main/java/net/minecraft/world/item/MapItem.java ++++ b/src/main/java/net/minecraft/world/item/MapItem.java +@@ -252,7 +252,7 @@ public class MapItem extends ComplexItem { + + for (l = 0; l < 128 * i; ++l) { + for (i1 = 0; i1 < 128 * i; ++i1) { +- abiomebase[l * 128 * i + i1] = worldserver.getBiome(new BlockPos((j / i - 64) * i + i1, 0, (k / i - 64) * i + l)); ++ abiomebase[l * 128 * i + i1] = worldserver.getBiomeBySeed((j / i - 64) * i + i1, 0, (k / i - 64) * i + l); // Paper + } + } + diff --git a/Remapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch b/Remapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch new file mode 100644 index 0000000000..f1615b3c0b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch @@ -0,0 +1,220 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 4 Jun 2020 02:24:49 -0400 +Subject: [PATCH] Optimize Bit Operations by inlining + +Inline bit operations and reduce instruction count to make these hot +operations faster + +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 595abf528a7862478100770987906af1b13439fe..727af6ac84075db87615ebac51a024e6376fa3cb 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -31,14 +31,16 @@ public class BlockPos extends Vec3i { + }).stable(); + private static final Logger LOGGER = LogManager.getLogger(); + public static final BlockPos ZERO = new BlockPos(0, 0, 0); +- private static final int PACKED_X_LENGTH = 1 + Mth.log2(Mth.smallestEncompassingPowerOfTwo(30000000)); +- private static final int PACKED_Z_LENGTH = BlockPos.PACKED_X_LENGTH; +- private static final int PACKED_Y_LENGTH = 64 - BlockPos.PACKED_X_LENGTH - BlockPos.PACKED_Z_LENGTH; +- private static final long PACKED_X_MASK = (1L << BlockPos.PACKED_X_LENGTH) - 1L; +- private static final long PACKED_Y_MASK = (1L << BlockPos.PACKED_Y_LENGTH) - 1L; +- private static final long PACKED_Z_MASK = (1L << BlockPos.PACKED_Z_LENGTH) - 1L; +- private static final int Z_OFFSET = BlockPos.PACKED_Y_LENGTH; +- private static final int X_OFFSET = BlockPos.PACKED_Y_LENGTH + BlockPos.PACKED_Z_LENGTH; ++ // Paper start - static constants ++ private static final int PACKED_X_LENGTH = 26; ++ private static final int PACKED_Z_LENGTH = 26; ++ private static final int PACKED_Y_LENGTH = 12; ++ private static final long PACKED_X_MASK = 67108863; ++ private static final long PACKED_Y_MASK = 4095; ++ private static final long PACKED_Z_MASK = 67108863; ++ private static final int Z_OFFSET = 12; ++ private static final int X_OFFSET = 38; ++ // Paper end + + public BlockPos(int x, int y, int z) { + super(x, y, z); +@@ -60,28 +62,29 @@ public class BlockPos extends Vec3i { + this(pos.getX(), pos.getY(), pos.getZ()); + } + ++ public static long getAdjacent(int baseX, int baseY, int baseZ, Direction enumdirection) { return asLong(baseX + enumdirection.getStepX(), baseY + enumdirection.getStepY(), baseZ + enumdirection.getStepZ()); } // Paper + public static long offset(long value, Direction direction) { + return offset(value, direction.getStepX(), direction.getStepY(), direction.getStepZ()); + } + + public static long offset(long value, int x, int y, int z) { +- return asLong(getX(value) + x, getY(value) + y, getZ(value) + z); ++ return asLong((int) (value >> 38) + x, (int) ((value << 52) >> 52) + y, (int) ((value << 26) >> 38) + z); // Paper - simplify/inline + } + + public static int getX(long packedPos) { +- return (int) (packedPos << 64 - BlockPos.X_OFFSET - BlockPos.PACKED_X_LENGTH >> 64 - BlockPos.PACKED_X_LENGTH); ++ return (int) (packedPos >> 38); // Paper - simplify/inline + } + + public static int getY(long packedPos) { +- return (int) (packedPos << 64 - BlockPos.PACKED_Y_LENGTH >> 64 - BlockPos.PACKED_Y_LENGTH); ++ return (int) ((packedPos << 52) >> 52); // Paper - simplify/inline + } + + public static int getZ(long packedPos) { +- return (int) (packedPos << 64 - BlockPos.Z_OFFSET - BlockPos.PACKED_Z_LENGTH >> 64 - BlockPos.PACKED_Z_LENGTH); ++ return (int) ((packedPos << 26) >> 38); // Paper - simplify/inline + } + + public static BlockPos of(long packedPos) { +- return new BlockPos(getX(packedPos), getY(packedPos), getZ(packedPos)); ++ return new BlockPos((int) (packedPos >> 38), (int) ((packedPos << 52) >> 52), (int) ((packedPos << 26) >> 38)); // Paper - simplify/inline + } + + public long asLong() { +@@ -90,12 +93,7 @@ public class BlockPos extends Vec3i { + + public static long asLong(int x, int y, int z) { return asLong(x, y, z); } // Paper - OBFHELPER + public static long asLong(int x, int y, int z) { +- long l = 0L; +- +- l |= ((long) x & BlockPos.PACKED_X_MASK) << BlockPos.X_OFFSET; +- l |= ((long) y & BlockPos.PACKED_Y_MASK) << 0; +- l |= ((long) z & BlockPos.PACKED_Z_MASK) << BlockPos.Z_OFFSET; +- return l; ++ return (((long) x & (long) 67108863) << 38) | (((long) y & (long) 4095)) | (((long) z & (long) 67108863) << 12); // Paper - inline constants and simplify + } + + public static long getFlatIndex(long y) { +diff --git a/src/main/java/net/minecraft/core/SectionPos.java b/src/main/java/net/minecraft/core/SectionPos.java +index 700e0d7b132242bd65d13ec61c1f7036905b2767..c4bf1bc383fbdfb8ec997883aececde38206c7dd 100644 +--- a/src/main/java/net/minecraft/core/SectionPos.java ++++ b/src/main/java/net/minecraft/core/SectionPos.java +@@ -19,7 +19,7 @@ public class SectionPos extends Vec3i { + } + + public static SectionPos of(BlockPos pos) { +- return new SectionPos(blockToSectionCoord(pos.getX()), blockToSectionCoord(pos.getY()), blockToSectionCoord(pos.getZ())); ++ return new SectionPos(pos.getX() >> 4, pos.getY() >> 4, pos.getZ() >> 4); // Paper + } + + public static SectionPos of(ChunkPos chunkPos, int y) { +@@ -31,15 +31,23 @@ public class SectionPos extends Vec3i { + } + + public static SectionPos of(long packed) { +- return new SectionPos(x(packed), y(packed), z(packed)); ++ return new SectionPos((int) (packed >> 42), (int) (packed << 44 >> 44), (int) (packed << 22 >> 42)); // Paper + } + + public static long offset(long packed, Direction direction) { + return offset(packed, direction.getStepX(), direction.getStepY(), direction.getStepZ()); + } + ++ // Paper start ++ public static long getAdjacentFromBlockPos(int x, int y, int z, Direction enumdirection) { ++ return (((long) ((x >> 4) + enumdirection.getStepX()) & 4194303L) << 42) | (((long) ((y >> 4) + enumdirection.getStepY()) & 1048575L)) | (((long) ((z >> 4) + enumdirection.getStepZ()) & 4194303L) << 20); ++ } ++ public static long getAdjacentFromSectionPos(int x, int y, int z, Direction enumdirection) { ++ return (((long) (x + enumdirection.getStepX()) & 4194303L) << 42) | (((long) ((y) + enumdirection.getStepY()) & 1048575L)) | (((long) (z + enumdirection.getStepZ()) & 4194303L) << 20); ++ } ++ // Paper end + public static long offset(long packed, int x, int y, int z) { +- return asLong(x(packed) + x, y(packed) + y, z(packed) + z); ++ return (((long) ((int) (packed >> 42) + x) & 4194303L) << 42) | (((long) ((int) (packed << 44 >> 44) + y) & 1048575L)) | (((long) ((int) (packed << 22 >> 42) + z) & 4194303L) << 20); // Simplify to reduce instruction count + } + + public static int blockToSectionCoord(int coord) { +@@ -51,11 +59,7 @@ public class SectionPos extends Vec3i { + } + + public static short sectionRelativePos(BlockPos pos) { +- int i = sectionRelative(pos.getX()); +- int j = sectionRelative(pos.getY()); +- int k = sectionRelative(pos.getZ()); +- +- return (short) (i << 8 | k << 4 | j << 0); ++ return (short) ((pos.getX() & 15) << 8 | (pos.getZ() & 15) << 4 | pos.getY() & 15); // Paper - simplify/inline + } + + public static int sectionRelativeX(short packedLocalPos) { +@@ -114,16 +118,16 @@ public class SectionPos extends Vec3i { + return this.getZ(); + } + +- public int minBlockX() { +- return this.x() << 4; ++ public final int minBlockX() { // Paper ++ return this.getX() << 4; // Paper + } + +- public int minBlockY() { +- return this.y() << 4; ++ public final int minBlockY() { // Paper ++ return this.getY() << 4; // Paper + } + +- public int minBlockZ() { +- return this.z() << 4; ++ public final int minBlockZ() { // Paper ++ return this.getZ() << 4; // Paper + } + + public int maxBlockX() { +@@ -138,8 +142,10 @@ public class SectionPos extends Vec3i { + return (this.z() << 4) + 15; + } + ++ public static long blockToSection(long i) { return blockToSection(i); } // Paper - OBFHELPER + public static long blockToSection(long blockPos) { +- return asLong(blockToSectionCoord(BlockPos.getX(blockPos)), blockToSectionCoord(BlockPos.getY(blockPos)), blockToSectionCoord(BlockPos.getZ(blockPos))); ++ // b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); ++ return (((long) (int) (blockPos >> 42) & 4194303L) << 42) | (((long) (int) ((blockPos << 52) >> 56) & 1048575L)) | (((long) (int) ((blockPos << 26) >> 42) & 4194303L) << 20); // Simplify to reduce instruction count + } + + public static long getZeroNode(long pos) { +@@ -160,17 +166,18 @@ public class SectionPos extends Vec3i { + return new ChunkPos(this.x(), this.z()); + } + ++ // Paper start ++ public static long blockPosAsSectionLong(int i, int j, int k) { ++ return (((long) (i >> 4) & 4194303L) << 42) | (((long) (j >> 4) & 1048575L)) | (((long) (k >> 4) & 4194303L) << 20); ++ } ++ // Paper end ++ public static long asLong(int i, int j, int k) { return asLong(i, j, k); } // Paper - OBFHELPER + public static long asLong(int x, int y, int z) { +- long l = 0L; +- +- l |= ((long) x & 4194303L) << 42; +- l |= ((long) y & 1048575L) << 0; +- l |= ((long) z & 4194303L) << 20; +- return l; ++ return (((long) x & 4194303L) << 42) | (((long) y & 1048575L)) | (((long) z & 4194303L) << 20); // Paper - Simplify to reduce instruction count + } + + public long asLong() { +- return asLong(this.x(), this.y(), this.z()); ++ return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count + } + + public Stream blocksInside() { +@@ -178,18 +185,11 @@ public class SectionPos extends Vec3i { + } + + public static Stream cube(SectionPos center, int radius) { +- int j = center.x(); +- int k = center.y(); +- int l = center.z(); +- +- return betweenClosedStream(j - radius, k - radius, l - radius, j + radius, k + radius, l + radius); ++ return betweenClosedStream(center.getX() - radius, center.getY() - radius, center.getZ() - radius, center.getX() + radius, center.getY() + radius, center.getZ() + radius); // Paper - simplify/inline + } + + public static Stream aroundChunk(ChunkPos center, int radius) { +- int j = center.x; +- int k = center.z; +- +- return betweenClosedStream(j - radius, 0, k - radius, j + radius, 15, k + radius); ++ return betweenClosedStream(center.x - radius, 0, center.z - radius, center.x + radius, 15, center.z + radius); // Paper - simplify/inline + } + + public static Stream betweenClosedStream(final int minX, final int minY, final int minZ, final int maxX, final int maxY, final int maxZ) { diff --git a/Remapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch b/Remapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch new file mode 100644 index 0000000000..53f26fe554 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch @@ -0,0 +1,1464 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 4 Jun 2020 22:43:29 -0400 +Subject: [PATCH] Optimize Light Engine + +Massive update to light to improve performance and chunk loading/generation. + +1) Massive bit packing/unpacking optimizations and inlining. + A lot of performance has to do with constant packing and unpacking of bits. + We now inline a most bit operations, and re-use base x/y/z bits in many places. + This helps with cpu level processing to just do all the math at once instead + of having to jump in and out of function calls. + + This much logic also is likely over the JVM Inline limit for JIT too. +2) Applied a few of JellySquid's Phosphor mod optimizations such as + - ensuring we don't notify neighbor chunks when neighbor chunk doesn't need to be notified + - reduce hasLight checks in initializing light, and prob some more, they are tagged JellySquid where phosphor influence was used. +3) Optimize hot path accesses to getting updating chunk to have less branching +4) Optimize getBlock accesses to have less branching, and less unpacking +5) Have a separate urgent bucket for chunk light tasks. These tasks will always cut in line over non blocking light tasks. +6) Retain chunk priority while light tasks are enqueued. So if a task comes in at high priority but the queue is full + of tasks already at a lower priority, before the task was simply added to the end. Now it can cut in line to the front. + this applies for both urgent and non urgent tasks. +7) Buffer non urgent tasks even if queueUpdate is called multiple times to improve efficiency. +8) Fix NPE risk that crashes server in getting nibble data + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 8260636da673ef095728c208db2d6237bab2db19..9e3629884709126574a52ad44fe7523f01dbcce9 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -753,6 +753,7 @@ public class ChunkHolder { + ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; + } + chunkMap.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, ioPriority); ++ chunkMap.level.getChunkSource().getLightEngine().queue.changePriority(pos.toLong(), getCurrentPriority(), priority); + } + if (getCurrentPriority() != priority) { + this.onLevelChange.onLevelChange(this.pos, this::getCurrentPriority, priority, this::setPriority); // use preferred priority +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index acc566d14926dcf9e88f3e0837884e4c823d777c..f4dd30c8b3326db72d3b3068ee2291de6f15de7c 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -98,6 +98,7 @@ import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelStorageSource; ++import net.minecraft.world.level.storage.PrimaryLevelData; + import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper + import org.apache.commons.lang3.mutable.MutableBoolean; + import org.apache.logging.log4j.LogManager; +@@ -328,6 +329,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + // Paper end + ++ private final java.util.concurrent.ExecutorService lightThread; + public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier supplier, int i, boolean flag) { + super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag); + //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning +@@ -359,7 +361,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ProcessorHandle mailbox = ProcessorHandle.of("main", mainThreadExecutor::tell); + + this.progressListener = worldGenerationProgressListener; +- ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(workerExecutor, "light"); // Paper ++ // Paper start - use light thread ++ ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(lightThread = java.util.concurrent.Executors.newSingleThreadExecutor(r -> { ++ Thread thread = new Thread(r); ++ thread.setName(((PrimaryLevelData)level.getLevelData()).getLevelName() + " - Light"); ++ thread.setDaemon(true); ++ thread.setPriority(Thread.NORM_PRIORITY+1); ++ return thread; ++ }), "light"); ++ // Paper end + + this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), workerExecutor, Integer.MAX_VALUE); + this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); +@@ -705,6 +715,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end + } + ++ protected final IntSupplier getPrioritySupplier(long i) { return getChunkQueueLevel(i); } // Paper - OBFHELPER + protected IntSupplier getChunkQueueLevel(long pos) { + return () -> { + ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos); +@@ -832,6 +843,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + @Override + public void close() throws IOException { + try { ++ this.lightThread.shutdown(); // Paper + this.queueSorter.close(); + this.level.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line + this.poiManager.close(); +diff --git a/src/main/java/net/minecraft/server/level/SectionTracker.java b/src/main/java/net/minecraft/server/level/SectionTracker.java +index 125ae965bb539ae24c60cb992eb7cfc35fd65b25..9fa6c290373b0e0cc0e7ed84c0c2363c8ad14dd3 100644 +--- a/src/main/java/net/minecraft/server/level/SectionTracker.java ++++ b/src/main/java/net/minecraft/server/level/SectionTracker.java +@@ -1,6 +1,5 @@ + package net.minecraft.server.level; + +-import net.minecraft.core.SectionPos; + import net.minecraft.world.level.lighting.DynamicGraphMinFixedPoint; + + public abstract class SectionTracker extends DynamicGraphMinFixedPoint { +@@ -16,14 +15,20 @@ public abstract class SectionTracker extends DynamicGraphMinFixedPoint { + + @Override + protected void checkNeighborsAfterUpdate(long id, int level, boolean decrease) { ++ // Paper start ++ int x = (int) (id >> 42); ++ int y = (int) (id << 44 >> 44); ++ int z = (int) (id << 22 >> 42); ++ // Paper end + for (int k = -1; k <= 1; ++k) { + for (int l = -1; l <= 1; ++l) { + for (int i1 = -1; i1 <= 1; ++i1) { +- long j1 = SectionPos.offset(id, k, l, i1); ++ if (k == 0 && l == 0 && i1 == 0) continue; // Paper ++ long j1 = (((long) (x + k) & 4194303L) << 42) | (((long) (y + l) & 1048575L)) | (((long) (z + i1) & 4194303L) << 20); // Paper + +- if (j1 != id) { ++ //if (j1 != i) { // Paper - checked above + this.checkNeighbor(id, j1, level, decrease); +- } ++ //} // Paper + } + } + } +@@ -34,10 +39,15 @@ public abstract class SectionTracker extends DynamicGraphMinFixedPoint { + protected int getComputedLevel(long id, long excludedId, int maxLevel) { + int l = maxLevel; + ++ // Paper start ++ int x = (int) (id >> 42); ++ int y = (int) (id << 44 >> 44); ++ int z = (int) (id << 22 >> 42); ++ // Paper end + for (int i1 = -1; i1 <= 1; ++i1) { + for (int j1 = -1; j1 <= 1; ++j1) { + for (int k1 = -1; k1 <= 1; ++k1) { +- long l1 = SectionPos.offset(id, i1, j1, k1); ++ long l1 = (((long) (x + i1) & 4194303L) << 42) | (((long) (y + j1) & 1048575L)) | (((long) (z + k1) & 4194303L) << 20); // Paper + + if (l1 == id) { + l1 = Long.MAX_VALUE; +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index f36badcafbad7fb4537ffdf54d9e266ae3d72459..7a615a18f1f297adfe7e046407a019d8933e9ed9 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -1072,7 +1072,7 @@ public class ServerChunkCache extends ChunkSource { + if (ServerChunkCache.this.runDistanceManagerUpdates()) { + return true; + } else { +- ServerChunkCache.this.lightEngine.tryScheduleUpdate(); ++ ServerChunkCache.this.lightEngine.tryScheduleUpdate(); // Paper - not needed + return super.pollTask() || execChunkTask; // Paper + } + } finally { +diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java +index cc4190b3a8904d1eaae0f542a3b3090583f5ff82..14835bfab300d305faee2db705d7386dc16427f5 100644 +--- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java ++++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java +@@ -1,6 +1,7 @@ + package net.minecraft.server.level; + + import com.mojang.datafixers.util.Pair; ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; // Paper + import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import it.unimi.dsi.fastutil.objects.ObjectList; + import it.unimi.dsi.fastutil.objects.ObjectListIterator; +@@ -16,6 +17,7 @@ import net.minecraft.util.thread.ProcessorMailbox; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.DataLayer; + import net.minecraft.world.level.chunk.LevelChunkSection; + import net.minecraft.world.level.chunk.LightChunkGetter; +@@ -27,15 +29,149 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl + + private static final Logger LOGGER = LogManager.getLogger(); + private final ProcessorMailbox taskMailbox; +- private final ObjectList> lightTasks = new ObjectArrayList(); +- private final ChunkMap chunkMap; ++ // Paper start ++ private static final int MAX_PRIORITIES = ChunkMap.MAX_CHUNK_DISTANCE + 2; ++ ++ private boolean isChunkLightStatus(long pair) { ++ ChunkHolder playerChunk = playerChunkMap.getVisibleChunkIfPresent(pair); ++ if (playerChunk == null) { ++ return false; ++ } ++ ChunkStatus status = ChunkHolder.getStatus(playerChunk.getTicketLevel()); ++ return status != null && status.isAtLeastStatus(ChunkStatus.LIGHT); ++ } ++ ++ static class ChunkLightQueue { ++ public boolean shouldFastUpdate; ++ java.util.ArrayDeque pre = new java.util.ArrayDeque(); ++ java.util.ArrayDeque post = new java.util.ArrayDeque(); ++ ++ ChunkLightQueue(long chunk) {} ++ } ++ ++ static class PendingLightTask { ++ long chunkId; ++ IntSupplier priority; ++ Runnable pre; ++ Runnable post; ++ boolean fastUpdate; ++ ++ public PendingLightTask(long chunkId, IntSupplier priority, Runnable pre, Runnable post, boolean fastUpdate) { ++ this.chunkId = chunkId; ++ this.priority = priority; ++ this.pre = pre; ++ this.post = post; ++ this.fastUpdate = fastUpdate; ++ } ++ } ++ ++ ++ // Retain the chunks priority level for queued light tasks ++ class LightQueue { ++ private int size = 0; ++ private final Long2ObjectLinkedOpenHashMap[] buckets = new Long2ObjectLinkedOpenHashMap[MAX_PRIORITIES]; ++ private final java.util.concurrent.ConcurrentLinkedQueue pendingTasks = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ private final java.util.concurrent.ConcurrentLinkedQueue priorityChanges = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ ++ private LightQueue() { ++ for (int i = 0; i < buckets.length; i++) { ++ buckets[i] = new Long2ObjectLinkedOpenHashMap<>(); ++ } ++ } ++ ++ public void changePriority(long pair, int currentPriority, int priority) { ++ this.priorityChanges.add(() -> { ++ ChunkLightQueue remove = this.buckets[currentPriority].remove(pair); ++ if (remove != null) { ++ ChunkLightQueue existing = this.buckets[Math.max(1, priority)].put(pair, remove); ++ if (existing != null) { ++ remove.pre.addAll(existing.pre); ++ remove.post.addAll(existing.post); ++ } ++ } ++ }); ++ } ++ ++ public final void addChunk(long chunkId, IntSupplier priority, Runnable pre, Runnable post) { ++ pendingTasks.add(new PendingLightTask(chunkId, priority, pre, post, true)); ++ tryScheduleUpdate(); ++ } ++ ++ public final void add(long chunkId, IntSupplier priority, ThreadedLevelLightEngine.TaskType type, Runnable run) { ++ pendingTasks.add(new PendingLightTask(chunkId, priority, type == TaskType.PRE_UPDATE ? run : null, type == TaskType.POST_UPDATE ? run : null, false)); ++ } ++ public final void add(PendingLightTask update) { ++ int priority = update.priority.getAsInt(); ++ ChunkLightQueue lightQueue = this.buckets[priority].computeIfAbsent(update.chunkId, ChunkLightQueue::new); ++ ++ if (update.pre != null) { ++ this.size++; ++ lightQueue.pre.add(update.pre); ++ } ++ if (update.post != null) { ++ this.size++; ++ lightQueue.post.add(update.post); ++ } ++ if (update.fastUpdate) { ++ lightQueue.shouldFastUpdate = true; ++ } ++ } ++ ++ public final boolean isEmpty() { ++ return this.size == 0 && this.pendingTasks.isEmpty(); ++ } ++ ++ public final int size() { ++ return this.size; ++ } ++ ++ public boolean poll(java.util.List pre, java.util.List post) { ++ PendingLightTask pending; ++ while ((pending = pendingTasks.poll()) != null) { ++ add(pending); ++ } ++ Runnable run; ++ while ((run = priorityChanges.poll()) != null) { ++ run.run(); ++ } ++ boolean hasWork = false; ++ Long2ObjectLinkedOpenHashMap[] buckets = this.buckets; ++ int priority = 0; ++ while (priority < MAX_PRIORITIES && !isEmpty()) { ++ Long2ObjectLinkedOpenHashMap bucket = buckets[priority]; ++ if (bucket.isEmpty()) { ++ priority++; ++ if (hasWork) { ++ return true; ++ } else { ++ continue; ++ } ++ } ++ ChunkLightQueue queue = bucket.removeFirst(); ++ this.size -= queue.pre.size() + queue.post.size(); ++ pre.addAll(queue.pre); ++ post.addAll(queue.post); ++ queue.pre.clear(); ++ queue.post.clear(); ++ hasWork = true; ++ if (queue.shouldFastUpdate) { ++ return true; ++ } ++ } ++ return hasWork; ++ } ++ } ++ ++ final LightQueue queue = new LightQueue(); ++ // Paper end ++ private final ChunkMap chunkMap; private final ChunkMap playerChunkMap; // Paper + private final ProcessorHandle> sorterMailbox; + private volatile int taskPerBatch = 5; + private final AtomicBoolean scheduled = new AtomicBoolean(); + + public ThreadedLevelLightEngine(LightChunkGetter chunkProvider, ChunkMap chunkStorage, boolean hasBlockLight, ProcessorMailbox processor, ProcessorHandle> executor) { + super(chunkProvider, true, hasBlockLight); +- this.chunkMap = chunkStorage; ++ this.chunkMap = chunkStorage; this.playerChunkMap = chunkMap; // Paper + this.sorterMailbox = executor; + this.taskMailbox = processor; + } +@@ -122,13 +258,9 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl + } + + private void addTask(int x, int z, IntSupplier completedLevelSupplier, ThreadedLevelLightEngine.TaskType stage, Runnable task) { +- this.sorterMailbox.tell(ChunkTaskPriorityQueueSorter.message(() -> { +- this.lightTasks.add(Pair.of(stage, task)); +- if (this.lightTasks.size() >= this.taskPerBatch) { +- this.runUpdate(); +- } +- +- }, ChunkPos.asLong(x, z), completedLevelSupplier)); ++ // Paper start - replace method ++ this.queue.add(ChunkPos.asLong(x, z), completedLevelSupplier, stage, task); ++ // Paper end + } + + @Override +@@ -145,8 +277,19 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl + public CompletableFuture lightChunk(ChunkAccess chunk, boolean excludeBlocks) { + ChunkPos chunkcoordintpair = chunk.getPos(); + +- chunk.setLightCorrect(false); +- this.addTask(chunkcoordintpair.x, chunkcoordintpair.z, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> { ++ // Paper start ++ //ichunkaccess.b(false); // Don't need to disable this ++ long pair = chunkcoordintpair.toLong(); ++ CompletableFuture future = new CompletableFuture<>(); ++ IntSupplier prioritySupplier = playerChunkMap.getPrioritySupplier(pair); ++ boolean[] skippedPre = {false}; ++ this.queue.addChunk(pair, prioritySupplier, Util.name(() -> { ++ if (!isChunkLightStatus(pair)) { ++ future.complete(chunk); ++ skippedPre[0] = true; ++ return; ++ } ++ // Paper end + LevelChunkSection[] achunksection = chunk.getSections(); + + for (int i = 0; i < 16; ++i) { +@@ -164,55 +307,48 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl + }); + } + +- this.chunkMap.releaseLightTicket(chunkcoordintpair); ++ // this.d.c(chunkcoordintpair); // Paper - move into post task below + }, () -> { + return "lightChunk " + chunkcoordintpair + " " + excludeBlocks; +- })); +- return CompletableFuture.supplyAsync(() -> { ++ // Paper start - merge the 2 together ++ }), () -> { ++ this.chunkMap.releaseLightTicket(chunkcoordintpair); // Paper - release light tickets as post task to ensure they stay loaded until fully done ++ if (skippedPre[0]) return; // Paper - future's already complete + chunk.setLightCorrect(true); + super.retainData(chunkcoordintpair, false); +- return chunk; +- }, (runnable) -> { +- this.addTask(chunkcoordintpair.x, chunkcoordintpair.z, ThreadedLevelLightEngine.TaskType.POST_UPDATE, runnable); ++ // Paper start ++ future.complete(chunk); + }); ++ return future; ++ // Paper end + } + + public void tryScheduleUpdate() { +- if ((!this.lightTasks.isEmpty() || super.hasLightWork()) && this.scheduled.compareAndSet(false, true)) { ++ if ((!this.queue.isEmpty() || super.hasLightWork()) && this.scheduled.compareAndSet(false, true)) { // Paper + this.taskMailbox.tell((() -> { // Paper - decompile error + this.runUpdate(); + this.scheduled.set(false); ++ tryScheduleUpdate(); // Paper - if we still have work to do, do it! + })); + } + + } + ++ // Paper start - replace impl ++ private final java.util.List pre = new java.util.ArrayList<>(); ++ private final java.util.List post = new java.util.ArrayList<>(); + private void runUpdate() { +- int i = Math.min(this.lightTasks.size(), this.taskPerBatch); +- ObjectListIterator> objectlistiterator = this.lightTasks.iterator(); +- +- Pair pair; +- int j; +- +- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { +- pair = (Pair) objectlistiterator.next(); +- if (pair.getFirst() == ThreadedLevelLightEngine.TaskType.PRE_UPDATE) { +- ((Runnable) pair.getSecond()).run(); +- } ++ if (queue.poll(pre, post)) { ++ pre.forEach(Runnable::run); ++ pre.clear(); ++ super.runUpdates(Integer.MAX_VALUE, true, true); ++ post.forEach(Runnable::run); ++ post.clear(); ++ } else { ++ // might have level updates to go still ++ super.runUpdates(Integer.MAX_VALUE, true, true); + } +- +- objectlistiterator.back(j); +- super.runUpdates(Integer.MAX_VALUE, true, true); +- +- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { +- pair = (Pair) objectlistiterator.next(); +- if (pair.getFirst() == ThreadedLevelLightEngine.TaskType.POST_UPDATE) { +- ((Runnable) pair.getSecond()).run(); +- } +- +- objectlistiterator.remove(); +- } +- ++ // Paper end + } + + public void setTaskPerBatch(int taskBatchSize) { +diff --git a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java +index c763aa0c0cf49dd844af94a820103258b49021ae..195535835bdc63f7cfdebeaa957dde590262ea42 100644 +--- a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java ++++ b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java +@@ -110,7 +110,8 @@ public class ProcessorMailbox implements ProcessorHandle, AutoCloseable, R + + } + +- @Override ++ ++ public final void queue(T t0) { tell(t0); } @Override // Paper - OBFHELPER + public void tell(T message) { + this.queue.push(message); + this.registerForExecution(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java +index 83e9d8bff9a31fe13a0e22445cd6eecb7abe8561..1e8ce9894fd0a121da83020c6064b7833af1c5f2 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java +@@ -11,6 +11,13 @@ import net.minecraft.server.MCUtil; + public class DataLayer { + + // Paper start ++ public static final DataLayer EMPTY_NIBBLE_ARRAY = new DataLayer() { ++ @Override ++ public byte[] getData() { ++ throw new IllegalStateException(); ++ } ++ }; ++ public long lightCacheKey = Long.MIN_VALUE; + public static byte[] EMPTY_NIBBLE = new byte[2048]; + private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072); + private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8)); +diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java +index 709fc42057f8a0282c3c942067e63abb874d9042..eaaaecb67966e5e366cf59f92674c82d1d87552e 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java ++++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java +@@ -23,9 +23,11 @@ public final class BlockLightEngine extends LayerLightEngine> 38); ++ int k = (int) ((blockPos << 52) >> 52); ++ int l = (int) ((blockPos << 26) >> 38); ++ // Paper end + BlockGetter iblockaccess = this.chunkSource.getChunkForLighting(j >> 4, l >> 4); + + return iblockaccess != null ? iblockaccess.getLightEmission(this.pos.set(j, k, l)) : 0; +@@ -40,25 +42,33 @@ public final class BlockLightEngine extends LayerLightEngine= 15) { + return level; + } else { +- int l = Integer.signum(BlockPos.getX(targetId) - BlockPos.getX(sourceId)); +- int i1 = Integer.signum(BlockPos.getY(targetId) - BlockPos.getY(sourceId)); +- int j1 = Integer.signum(BlockPos.getZ(targetId) - BlockPos.getZ(sourceId)); ++ // Paper start - reuse math - credit to JellySquid for idea ++ int jx = (int) (targetId >> 38); ++ int jy = (int) ((targetId << 52) >> 52); ++ int jz = (int) ((targetId << 26) >> 38); ++ int ix = (int) (sourceId >> 38); ++ int iy = (int) ((sourceId << 52) >> 52); ++ int iz = (int) ((sourceId << 26) >> 38); ++ int l = Integer.signum(jx - ix); ++ int i1 = Integer.signum(jy - iy); ++ int j1 = Integer.signum(jz - iz); ++ // Paper end + Direction enumdirection = Direction.fromNormal(l, i1, j1); + + if (enumdirection == null) { + return 15; + } else { + //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded +- BlockState iblockdata = this.getStateAndOpacity(targetId, mutableint); +- +- if (mutableint.getValue() >= 15) { ++ BlockState iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); // Paper ++ int blockedLight = mutableint.getValue(); // Paper ++ if (blockedLight >= 15) { // Paper + return 15; + } else { +- BlockState iblockdata1 = this.getStateAndOpacity(sourceId, (MutableInt) null); ++ BlockState iblockdata1 = this.getBlockOptimized(ix, iy, iz); // Paper + VoxelShape voxelshape = this.getShape(iblockdata1, sourceId, enumdirection); + VoxelShape voxelshape1 = this.getShape(iblockdata, targetId, enumdirection.getOpposite()); + +- return Shapes.faceShapeOccludes(voxelshape, voxelshape1) ? 15 : level + Math.max(1, mutableint.getValue()); ++ return Shapes.faceShapeOccludes(voxelshape, voxelshape1) ? 15 : level + Math.max(1, blockedLight); // Paper + } + } + } +@@ -66,14 +76,19 @@ public final class BlockLightEngine extends LayerLightEngine> 38); ++ int y = (int) ((id << 52) >> 52); ++ int z = (int) ((id << 26) >> 38); ++ long k = SectionPos.blockPosAsSectionLong(x, y, z); ++ // Paper end + Direction[] aenumdirection = BlockLightEngine.DIRECTIONS; + int l = aenumdirection.length; + + for (int i1 = 0; i1 < l; ++i1) { + Direction enumdirection = aenumdirection[i1]; +- long j1 = BlockPos.offset(id, enumdirection); +- long k1 = SectionPos.blockToSection(j1); ++ long j1 = BlockPos.getAdjacent(x, y, z, enumdirection); // Paper ++ long k1 = SectionPos.blockToSection(j1); // Paper + + if (k == k1 || ((BlockLightSectionStorage) this.storage).storingLightForSection(k1)) { + this.checkNeighbor(id, j1, level, decrease); +@@ -98,27 +113,37 @@ public final class BlockLightEngine extends LayerLightEngine> 38); ++ int baseY = (int) ((id << 52) >> 52); ++ int baseZ = (int) ((id << 26) >> 38); ++ long j1 = SectionPos.blockPosAsSectionLong(baseX, baseY, baseZ); ++ DataLayer nibblearray = this.storage.updating.getUpdatingOptimized(j1); ++ // Paper end + Direction[] aenumdirection = BlockLightEngine.DIRECTIONS; + int k1 = aenumdirection.length; + + for (int l1 = 0; l1 < k1; ++l1) { + Direction enumdirection = aenumdirection[l1]; +- long i2 = BlockPos.offset(id, enumdirection); ++ // Paper start ++ int newX = baseX + enumdirection.getStepX(); ++ int newY = baseY + enumdirection.getStepY(); ++ int newZ = baseZ + enumdirection.getStepZ(); ++ long i2 = BlockPos.asLong(newX, newY, newZ); + + if (i2 != excludedId) { +- long j2 = SectionPos.blockToSection(i2); ++ long j2 = SectionPos.blockPosAsSectionLong(newX, newY, newZ); ++ // Paper end + DataLayer nibblearray1; + + if (j1 == j2) { + nibblearray1 = nibblearray; + } else { +- nibblearray1 = ((BlockLightSectionStorage) this.storage).getDataLayer(j2, true); ++ nibblearray1 = ((BlockLightSectionStorage) this.storage).updating.getUpdatingOptimized(j2); // Paper + } + + if (nibblearray1 != null) { +- int k2 = this.computeLevelFromNeighbor(i2, id, this.getLevel(nibblearray1, i2)); ++ int k2 = this.computeLevelFromNeighbor(i2, id, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper + + if (l > k2) { + l = k2; +diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java +index a1ad4d73ddaf6afe97a1f1ff7e0622b52fac8761..f771ef8d841567b421b6c0529af3f0713c79eb7c 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java +@@ -1,8 +1,6 @@ + package net.minecraft.world.level.lighting; + + import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +-import net.minecraft.core.BlockPos; +-import net.minecraft.core.SectionPos; + import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.chunk.DataLayer; + import net.minecraft.world.level.chunk.LightChunkGetter; +@@ -15,10 +13,14 @@ public class BlockLightSectionStorage extends LayerLightSectionStorage> 38); ++ int baseY = (int) ((blockPos << 52) >> 52); ++ int baseZ = (int) ((blockPos << 26) >> 38); ++ long j = (((long) (baseX >> 4) & 4194303L) << 42) | (((long) (baseY >> 4) & 1048575L)) | (((long) (baseZ >> 4) & 4194303L) << 20); ++ DataLayer nibblearray = this.e_visible.lookup.apply(j); ++ return nibblearray == null ? 0 : nibblearray.get(baseX & 15, baseY & 15, baseZ & 15); ++ // Paper end + } + + public static final class BlockDataLayerStorageMap extends DataLayerStorageMap { +diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +index 54cca3b376e5ce02936edc8b9c17e67e17f07147..ed2ed6194670016086be580dc4514d5d3d1b235b 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java ++++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +@@ -7,13 +7,18 @@ import net.minecraft.world.level.chunk.DataLayer; + + public abstract class DataLayerStorageMap> { + +- private final long[] lastSectionKeys = new long[2]; +- private final DataLayer[] lastSections = new DataLayer[2]; ++ // private final long[] b = new long[2]; // Paper - unused ++ private final DataLayer[] lastSections = new DataLayer[]{DataLayer.EMPTY_NIBBLE_ARRAY, DataLayer.EMPTY_NIBBLE_ARRAY}; private final DataLayer[] cache = lastSections; // Paper - OBFHELPER + private boolean cacheEnabled; + protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data + protected final boolean isVisible; // Paper - avoid copying light data +- java.util.function.Function lookup; // Paper - faster branchless lookup + ++ // Paper start - faster lookups with less branching, use interface to avoid boxing instead of Function ++ public final NibbleArrayAccess lookup; ++ public interface NibbleArrayAccess { ++ DataLayer apply(long id); ++ } ++ // Paper end + // Paper start - avoid copying light data + protected DataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { + if (isVisible) { +@@ -21,12 +26,14 @@ public abstract class DataLayerStorageMap> { + } + this.data = data; + this.isVisible = isVisible; ++ // Paper end - avoid copying light data ++ // Paper start - faster lookups with less branching + if (isVisible) { + lookup = data::getVisibleAsync; + } else { +- lookup = data::getUpdating; ++ lookup = data.getUpdatingMap()::get; // jump straight the sub map + } +- // Paper end - avoid copying light data ++ // Paper end + this.clearCache(); + this.cacheEnabled = true; + } +@@ -36,7 +43,9 @@ public abstract class DataLayerStorageMap> { + public void copyDataLayer(long pos) { + if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data + DataLayer updating = this.data.getUpdating(pos); // Paper - pool nibbles +- this.data.queueUpdate(pos, new DataLayer().markPoolSafe(updating.getCloneIfSet())); // Paper - avoid copying light data - pool safe clone ++ DataLayer nibblearray = new DataLayer().markPoolSafe(updating.getCloneIfSet()); // Paper ++ nibblearray.lightCacheKey = pos; // Paper ++ this.data.queueUpdate(pos, nibblearray); // Paper - avoid copying light data - pool safe clone + if (updating.cleaner != null) MCUtil.scheduleTask(2, updating.cleaner, "Light Engine Release"); // Paper - delay clean incase anything holding ref was still using it + this.clearCache(); + } +@@ -45,34 +54,34 @@ public abstract class DataLayerStorageMap> { + return lookup.apply(chunkPos) != null; // Paper - avoid copying light data + } + +- @Nullable +- public final DataLayer getLayer(long chunkPos) { // Paper - final +- if (this.cacheEnabled) { +- for (int j = 0; j < 2; ++j) { +- if (chunkPos == this.lastSectionKeys[j]) { +- return this.lastSections[j]; +- } +- } +- } +- +- DataLayer nibblearray = lookup.apply(chunkPos); // Paper - avoid copying light data ++ // Paper start - less branching as we know we are using cache and updating ++ public final DataLayer getUpdatingOptimized(final long i) { // Paper - final ++ final DataLayer[] cache = this.cache; ++ if (cache[0].lightCacheKey == i) return cache[0]; ++ if (cache[1].lightCacheKey == i) return cache[1]; + ++ final DataLayer nibblearray = this.lookup.apply(i); // Paper - avoid copying light data + if (nibblearray == null) { + return null; + } else { +- if (this.cacheEnabled) { +- for (int k = 1; k > 0; --k) { +- this.lastSectionKeys[k] = this.lastSectionKeys[k - 1]; +- this.lastSections[k] = this.lastSections[k - 1]; +- } +- +- this.lastSectionKeys[0] = chunkPos; +- this.lastSections[0] = nibblearray; +- } +- ++ cache[1] = cache[0]; ++ cache[0] = nibblearray; + return nibblearray; + } + } ++ // Paper end ++ ++ @Nullable ++ public final DataLayer getLayer(final long chunkPos) { // Paper - final ++ // Paper start - optimize visible case or missed updating cases ++ if (this.cacheEnabled) { ++ // short circuit to optimized ++ return getUpdatingOptimized(chunkPos); ++ } ++ ++ return this.lookup.apply(chunkPos); ++ // Paper end ++ } + + @Nullable + public DataLayer removeLayer(long chunkPos) { +@@ -82,13 +91,14 @@ public abstract class DataLayerStorageMap> { + + public void setLayer(long pos, DataLayer data) { + if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data ++ data.lightCacheKey = pos; // Paper + this.data.queueUpdate(pos, data); // Paper - avoid copying light data + } + + public void clearCache() { + for (int i = 0; i < 2; ++i) { +- this.lastSectionKeys[i] = Long.MAX_VALUE; +- this.lastSections[i] = null; ++ // this.b[i] = Long.MAX_VALUE; // Paper - Unused ++ this.lastSections[i] = DataLayer.EMPTY_NIBBLE_ARRAY; // Paper + } + } + +diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightEngine.java +index 53f38fa95f4ffad12c73d94ab1d7ecf7ee78af09..088ea8a14f1bb264b59fcec626b1a28d7f6d7c47 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightEngine.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightEngine.java +@@ -10,6 +10,7 @@ import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.DataLayer; + import net.minecraft.world.level.chunk.LightChunkGetter; + import net.minecraft.world.phys.shapes.Shapes; +@@ -23,10 +24,37 @@ public abstract class LayerLightEngine, S exten + protected final LightLayer layer; + protected final S storage; + private boolean runningLightUpdates; +- protected final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); ++ protected final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); protected final BlockPos.MutableBlockPos pos = pos; // Paper + private final long[] lastChunkPos = new long[2]; +- private final BlockGetter[] lastChunk = new BlockGetter[2]; ++ private final ChunkAccess[] h = new ChunkAccess[2]; // Paper + ++ // Paper start - see fully commented out method below (look for Bedrock) ++ // optimized method with less branching for when scenarios arent needed. ++ // avoid using mutable version if can ++ protected final BlockState getBlockOptimized(int x, int y, int z, MutableInt mutableint) { ++ ChunkAccess iblockaccess = this.a(x >> 4, z >> 4); ++ ++ if (iblockaccess == null) { ++ mutableint.setValue(16); ++ return Blocks.BEDROCK.defaultBlockState(); ++ } else { ++ this.pos.setValues(x, y, z); ++ BlockState iblockdata = iblockaccess.getType(x, y, z); ++ mutableint.setValue(iblockdata.getLightBlock(this.chunkSource.getLevel(), this.pos)); ++ return iblockdata.canOcclude() && iblockdata.useShapeForLightOcclusion() ? iblockdata : Blocks.AIR.defaultBlockState(); ++ } ++ } ++ protected final BlockState getBlockOptimized(int x, int y, int z) { ++ ChunkAccess iblockaccess = this.a(x >> 4, z >> 4); ++ ++ if (iblockaccess == null) { ++ return Blocks.BEDROCK.defaultBlockState(); ++ } else { ++ BlockState iblockdata = iblockaccess.getType(x, y, z); ++ return iblockdata.canOcclude() && iblockdata.useShapeForLightOcclusion() ? iblockdata : Blocks.AIR.defaultBlockState(); ++ } ++ } ++ // Paper end + public LayerLightEngine(LightChunkGetter chunkProvider, LightLayer type, S lightStorage) { + super(16, 256, 8192); + this.chunkSource = chunkProvider; +@@ -45,63 +73,65 @@ public abstract class LayerLightEngine, S exten + } + + @Nullable +- private BlockGetter getChunk(int chunkX, int chunkZ) { +- long k = ChunkPos.asLong(chunkX, chunkZ); ++ private ChunkAccess a(int i, int j) { // Paper ++ long k = ChunkPos.asLong(i, j); + + for (int l = 0; l < 2; ++l) { + if (k == this.lastChunkPos[l]) { +- return this.lastChunk[l]; ++ return this.h[l]; + } + } + +- BlockGetter iblockaccess = this.chunkSource.getChunkForLighting(chunkX, chunkZ); ++ ChunkAccess iblockaccess = (ChunkAccess) this.chunkSource.getChunkForLighting(i, j); // Paper + + for (int i1 = 1; i1 > 0; --i1) { + this.lastChunkPos[i1] = this.lastChunkPos[i1 - 1]; +- this.lastChunk[i1] = this.lastChunk[i1 - 1]; ++ this.h[i1] = this.h[i1 - 1]; + } + + this.lastChunkPos[0] = k; +- this.lastChunk[0] = iblockaccess; ++ this.h[0] = iblockaccess; + return iblockaccess; + } + + private void clearCache() { + Arrays.fill(this.lastChunkPos, ChunkPos.INVALID_CHUNK_POS); +- Arrays.fill(this.lastChunk, (Object) null); ++ Arrays.fill(this.h, (Object) null); + } + +- protected BlockState getStateAndOpacity(long pos, @Nullable MutableInt mutableint) { +- if (pos == Long.MAX_VALUE) { +- if (mutableint != null) { +- mutableint.setValue(0); +- } +- +- return Blocks.AIR.defaultBlockState(); +- } else { +- int j = SectionPos.blockToSectionCoord(BlockPos.getX(pos)); +- int k = SectionPos.blockToSectionCoord(BlockPos.getZ(pos)); +- BlockGetter iblockaccess = this.getChunk(j, k); +- +- if (iblockaccess == null) { +- if (mutableint != null) { +- mutableint.setValue(16); +- } +- +- return Blocks.BEDROCK.defaultBlockState(); +- } else { +- this.pos.set(pos); +- BlockState iblockdata = iblockaccess.getBlockState(this.pos); +- boolean flag = iblockdata.canOcclude() && iblockdata.useShapeForLightOcclusion(); +- +- if (mutableint != null) { +- mutableint.setValue(iblockdata.getLightBlock(this.chunkSource.getLevel(), (BlockPos) this.pos)); +- } +- +- return flag ? iblockdata : Blocks.AIR.defaultBlockState(); +- } +- } +- } ++ // Paper start - comment out, see getBlockOptimized ++// protected IBlockData a(long i, @Nullable MutableInt mutableint) { ++// if (i == Long.MAX_VALUE) { ++// if (mutableint != null) { ++// mutableint.setValue(0); ++// } ++// ++// return Blocks.AIR.getBlockData(); ++// } else { ++// int j = SectionPosition.a(BlockPosition.b(i)); ++// int k = SectionPosition.a(BlockPosition.d(i)); ++// IBlockAccess iblockaccess = this.a(j, k); ++// ++// if (iblockaccess == null) { ++// if (mutableint != null) { ++// mutableint.setValue(16); ++// } ++// ++// return Blocks.BEDROCK.getBlockData(); ++// } else { ++// this.d.g(i); ++// IBlockData iblockdata = iblockaccess.getType(this.d); ++// boolean flag = iblockdata.l() && iblockdata.e(); ++// ++// if (mutableint != null) { ++// mutableint.setValue(iblockdata.b(this.a.getWorld(), (BlockPosition) this.d)); ++// } ++// ++// return flag ? iblockdata : Blocks.AIR.getBlockData(); ++// } ++// } ++// } ++ // Paper end + + protected VoxelShape getShape(BlockState world, long pos, Direction facing) { + return world.canOcclude() ? world.getFaceOcclusionShape(this.chunkSource.getLevel(), this.pos.set(pos), facing) : Shapes.empty(); +@@ -136,8 +166,9 @@ public abstract class LayerLightEngine, S exten + return id == Long.MAX_VALUE ? 0 : 15 - this.storage.getStoredLevel(id); + } + ++ protected int getNibbleLightInverse(DataLayer nibblearray, int x, int y, int z) { return 15 - nibblearray.get(x & 15, y & 15, z & 15); } // Paper - x/y/z version of below + protected int getLevel(DataLayer section, long blockPos) { +- return 15 - section.get(SectionPos.sectionRelative(BlockPos.getX(blockPos)), SectionPos.sectionRelative(BlockPos.getY(blockPos)), SectionPos.sectionRelative(BlockPos.getZ(blockPos))); ++ return 15 - section.get((int) (blockPos >> 38) & 15, (int) ((blockPos << 52) >> 52) & 15, (int) ((blockPos << 26) >> 38) & 15); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +index 5757bcfded35f112d52a7c81586850ba50e0d8dd..17a6610b352af5d3e2cbcdf9b4d9b0d4d356b5cf 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +@@ -27,9 +27,9 @@ public abstract class LayerLightSectionStorage> + protected final LongSet toMarkNoData = new LongOpenHashSet(); + protected final LongSet toMarkData = new LongOpenHashSet(); + protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change +- protected final M updatingSectionData; // Paper - diff on change, should be "updating" ++ protected final M updatingSectionData; protected final M updating; // Paper - diff on change, should be "updating" + protected final LongSet changedSections = new LongOpenHashSet(); +- protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet(); ++ protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet(); LongSet dirty = sectionsAffectedByLightUpdates; // Paper - OBFHELPER + protected final Long2ObjectMap queuedSections = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); + private final LongSet untrustedSections = new LongOpenHashSet(); + private final LongSet columnsToRetainQueuedDataFor = new LongOpenHashSet(); +@@ -37,33 +37,33 @@ public abstract class LayerLightSectionStorage> + protected volatile boolean hasToRemove; + + protected LayerLightSectionStorage(LightLayer lightType, LightChunkGetter chunkProvider, M lightData) { +- super(3, 16, 256); ++ super(3, 256, 256); // Paper - bump expected size of level sets to improve collisions and reduce rehashing (seen a lot of it) + this.layer = lightType; + this.chunkSource = chunkProvider; +- this.updatingSectionData = lightData; ++ this.updatingSectionData = lightData; updating = lightData; // Paper + this.e_visible = lightData.copy(); // Paper - avoid copying light data + this.e_visible.disableCache(); // Paper - avoid copying light data + } + +- protected boolean storingLightForSection(long sectionPos) { +- return this.getDataLayer(sectionPos, true) != null; ++ protected final boolean storingLightForSection(long sectionPos) { // Paper - final to help inlining ++ return this.updating.getUpdatingOptimized(sectionPos) != null; // Paper - inline to avoid branching + } + + @Nullable + protected DataLayer getDataLayer(long sectionPos, boolean cached) { + // Paper start - avoid copying light data + if (cached) { +- return this.getDataLayer(this.updatingSectionData, sectionPos); ++ return this.updating.getUpdatingOptimized(sectionPos); + } else { + synchronized (this.visibleUpdateLock) { +- return this.getDataLayer(this.e_visible, sectionPos); ++ return this.e_visible.lookup.apply(sectionPos); + } + } + // Paper end - avoid copying light data + } + + @Nullable +- protected DataLayer getDataLayer(M storage, long sectionPos) { ++ protected final DataLayer getDataLayer(M storage, long sectionPos) { // Paper + return storage.getLayer(sectionPos); + } + +@@ -77,27 +77,57 @@ public abstract class LayerLightSectionStorage> + protected abstract int getLightValue(long blockPos); + + protected int getStoredLevel(long blockPos) { +- long j = SectionPos.blockToSection(blockPos); +- DataLayer nibblearray = this.getDataLayer(j, true); ++ // Paper start - reuse and inline math, use Optimized Updating path ++ final int x = (int) (blockPos >> 38); ++ final int y = (int) ((blockPos << 52) >> 52); ++ final int z = (int) ((blockPos << 26) >> 38); ++ long j = SectionPos.blockPosAsSectionLong(x, y, z); ++ DataLayer nibblearray = this.updating.getUpdatingOptimized(j); ++ // BUG: Sometimes returns null and crashes, try to recover, but to prevent crash just return no light. ++ if (nibblearray == null) { ++ nibblearray = this.e_visible.lookup.apply(j); ++ } ++ if (nibblearray == null) { ++ System.err.println("Null nibble, preventing crash " + BlockPos.of(blockPos)); ++ return 0; ++ } + +- return nibblearray.get(SectionPos.sectionRelative(BlockPos.getX(blockPos)), SectionPos.sectionRelative(BlockPos.getY(blockPos)), SectionPos.sectionRelative(BlockPos.getZ(blockPos))); ++ return nibblearray.get(x & 15, y & 15, z & 15); // Paper - inline operations ++ // Paper end + } + + protected void setStoredLevel(long blockPos, int value) { +- long k = SectionPos.blockToSection(blockPos); ++ // Paper start - cache part of the math done in loop below ++ int x = (int) (blockPos >> 38); ++ int y = (int) ((blockPos << 52) >> 52); ++ int z = (int) ((blockPos << 26) >> 38); ++ long k = SectionPos.blockPosAsSectionLong(x, y, z); ++ // Paper end + + if (this.changedSections.add(k)) { + this.updatingSectionData.copyDataLayer(k); + } + + DataLayer nibblearray = this.getDataLayer(k, true); +- +- nibblearray.set(SectionPos.sectionRelative(BlockPos.getX(blockPos)), SectionPos.sectionRelative(BlockPos.getY(blockPos)), SectionPos.sectionRelative(BlockPos.getZ(blockPos)), value); +- +- for (int l = -1; l <= 1; ++l) { +- for (int i1 = -1; i1 <= 1; ++i1) { +- for (int j1 = -1; j1 <= 1; ++j1) { +- this.sectionsAffectedByLightUpdates.add(SectionPos.blockToSection(BlockPos.offset(blockPos, i1, j1, l))); ++ nibblearray.set(x & 15, y & 15, z & 15, value); // Paper - use already calculated x/y/z ++ ++ // Paper start - credit to JellySquid for a major optimization here: ++ /* ++ * An extremely important optimization is made here in regards to adding items to the pending notification set. The ++ * original implementation attempts to add the coordinate of every chunk which contains a neighboring block position ++ * even though a huge number of loop iterations will simply map to block positions within the same updating chunk. ++ * ++ * Our implementation here avoids this by pre-calculating the min/max chunk coordinates so we can iterate over only ++ * the relevant chunk positions once. This reduces what would always be 27 iterations to just 1-8 iterations. ++ * ++ * @reason Use faster implementation ++ * @author JellySquid ++ */ ++ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { ++ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { ++ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { ++ this.dirty.add(SectionPos.asLong(x2, y2, z2)); ++ // Paper end + } + } + } +@@ -129,17 +159,23 @@ public abstract class LayerLightSectionStorage> + } + + if (k >= 2 && level != 2) { +- if (this.toRemove.contains(id)) { +- this.toRemove.remove(id); +- } else { ++ if (!this.toRemove.remove(id)) { // Paper - remove useless contains - credit to JellySquid ++ //this.p.remove(i); // Paper ++ //} else { // Paper + this.updatingSectionData.setLayer(id, this.createDataLayer(id)); + this.changedSections.add(id); + this.onNodeAdded(id); + +- for (int l = -1; l <= 1; ++l) { +- for (int i1 = -1; i1 <= 1; ++i1) { +- for (int j1 = -1; j1 <= 1; ++j1) { +- this.sectionsAffectedByLightUpdates.add(SectionPos.blockToSection(BlockPos.offset(id, i1, j1, l))); ++ // Paper start - reuse x/y/z and only notify valid chunks - Credit to JellySquid (See above method for notes) ++ int x = (int) (id >> 38); ++ int y = (int) ((id << 52) >> 52); ++ int z = (int) ((id << 26) >> 38); ++ ++ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { ++ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { ++ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { ++ this.dirty.add(SectionPos.asLong(x2, y2, z2)); ++ // Paper end + } + } + } +@@ -165,9 +201,9 @@ public abstract class LayerLightSectionStorage> + return SectionPos.blockToSection(j) == sectionPos; + }); + } else { +- int j = SectionPos.sectionToBlockCoord(SectionPos.x(sectionPos)); +- int k = SectionPos.sectionToBlockCoord(SectionPos.y(sectionPos)); +- int l = SectionPos.sectionToBlockCoord(SectionPos.z(sectionPos)); ++ int j = (int) (sectionPos >> 42) << 4; // Paper - inline ++ int k = (int) (sectionPos << 44 >> 44) << 4; // Paper - inline ++ int l = (int) (sectionPos << 22 >> 42) << 4; // Paper - inline + + for (int i1 = 0; i1 < 16; ++i1) { + for (int j1 = 0; j1 < 16; ++j1) { +@@ -194,7 +230,7 @@ public abstract class LayerLightSectionStorage> + DataLayer nibblearray; + + while (longiterator.hasNext()) { +- i = (Long) longiterator.next(); ++ i = longiterator.nextLong(); // Paper + this.clearQueuedSectionBlocks(lightProvider, i); + DataLayer nibblearray1 = (DataLayer) this.queuedSections.remove(i); + +@@ -212,7 +248,7 @@ public abstract class LayerLightSectionStorage> + longiterator = this.toRemove.iterator(); + + while (longiterator.hasNext()) { +- i = (Long) longiterator.next(); ++ i = longiterator.nextLong(); // Paper + this.onNodeRemoved(i); + } + +@@ -223,12 +259,13 @@ public abstract class LayerLightSectionStorage> + Entry entry; + long j; + ++ DataLayer test = null; // Paper + while (objectiterator.hasNext()) { + entry = (Entry) objectiterator.next(); + j = entry.getLongKey(); +- if (this.storingLightForSection(j)) { ++ if ((test = this.updating.getUpdatingOptimized(j)) != null) { // Paper - dont look up nibble twice + nibblearray = (DataLayer) entry.getValue(); +- if (this.updatingSectionData.getLayer(j) != nibblearray) { ++ if (test != nibblearray) { // Paper + this.clearQueuedSectionBlocks(lightProvider, j); + this.updatingSectionData.setLayer(j, nibblearray); + this.changedSections.add(j); +@@ -241,14 +278,14 @@ public abstract class LayerLightSectionStorage> + longiterator = this.queuedSections.keySet().iterator(); + + while (longiterator.hasNext()) { +- i = (Long) longiterator.next(); ++ i = longiterator.nextLong(); // Paper + this.checkEdgesForSection(lightProvider, i); + } + } else { + longiterator = this.untrustedSections.iterator(); + + while (longiterator.hasNext()) { +- i = (Long) longiterator.next(); ++ i = longiterator.nextLong(); // Paper + this.checkEdgesForSection(lightProvider, i); + } + } +@@ -269,15 +306,20 @@ public abstract class LayerLightSectionStorage> + + private void checkEdgesForSection(LayerLightEngine lightProvider, long sectionPos) { + if (this.storingLightForSection(sectionPos)) { +- int j = SectionPos.sectionToBlockCoord(SectionPos.x(sectionPos)); +- int k = SectionPos.sectionToBlockCoord(SectionPos.y(sectionPos)); +- int l = SectionPos.sectionToBlockCoord(SectionPos.z(sectionPos)); ++ // Paper start ++ int secX = (int) (sectionPos >> 42); ++ int secY = (int) (sectionPos << 44 >> 44); ++ int secZ = (int) (sectionPos << 22 >> 42); ++ int j = secX << 4; // baseX ++ int k = secY << 4; // baseY ++ int l = secZ << 4; // baseZ ++ // Paper end + Direction[] aenumdirection = LayerLightSectionStorage.DIRECTIONS; + int i1 = aenumdirection.length; + + for (int j1 = 0; j1 < i1; ++j1) { + Direction enumdirection = aenumdirection[j1]; +- long k1 = SectionPos.offset(sectionPos, enumdirection); ++ long k1 = SectionPos.getAdjacentFromSectionPos(secX, secY, secZ, enumdirection); // Paper - avoid extra unpacking + + if (!this.queuedSections.containsKey(k1) && this.storingLightForSection(k1)) { + for (int l1 = 0; l1 < 16; ++l1) { +diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java +index ff1fbc46776b26ca56c3293e40ed55028230ec46..da4003aebc8d5ffce695071af9a27139568d773f 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java +@@ -4,6 +4,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.SectionPos; + import net.minecraft.world.level.LightLayer; ++import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.chunk.DataLayer; + import net.minecraft.world.level.chunk.LightChunkGetter; +@@ -38,21 +39,25 @@ public final class SkyLightEngine extends LayerLightEngine= 15) { ++ // Paper start - use x/y/z and optimized block lookup ++ int jx = (int) (targetId >> 38); ++ int jy = (int) ((targetId << 52) >> 52); ++ int jz = (int) ((targetId << 26) >> 38); ++ BlockState iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); ++ int blockedLight = mutableint.getValue(); ++ if (blockedLight >= 15) { ++ // Paper end + return 15; + } else { +- int l = BlockPos.getX(sourceId); +- int i1 = BlockPos.getY(sourceId); +- int j1 = BlockPos.getZ(sourceId); +- int k1 = BlockPos.getX(targetId); +- int l1 = BlockPos.getY(targetId); +- int i2 = BlockPos.getZ(targetId); +- boolean flag = l == k1 && j1 == i2; +- int j2 = Integer.signum(k1 - l); +- int k2 = Integer.signum(l1 - i1); +- int l2 = Integer.signum(i2 - j1); ++ // Paper start - inline math ++ int ix = (int) (sourceId >> 38); ++ int iy = (int) ((sourceId << 52) >> 52); ++ int iz = (int) ((sourceId << 26) >> 38); ++ boolean flag = ix == jx && iz == jz; ++ int j2 = Integer.signum(jx - ix); ++ int k2 = Integer.signum(jy - iy); ++ int l2 = Integer.signum(jz - iz); ++ // Paper end + Direction enumdirection; + + if (sourceId == Long.MAX_VALUE) { +@@ -61,7 +66,7 @@ public final class SkyLightEngine extends LayerLightEngine l1; ++ boolean flag1 = sourceId == Long.MAX_VALUE || flag && iy > jy; // Paper rename vars to iy > jy + +- return flag1 && level == 0 && mutableint.getValue() == 0 ? 0 : level + Math.max(1, mutableint.getValue()); ++ return flag1 && level == 0 && blockedLight == 0 ? 0 : level + Math.max(1, blockedLight); // Paper + } + } + } +@@ -101,10 +106,14 @@ public final class SkyLightEngine extends LayerLightEngine> 38); ++ int baseY = (int) ((id << 52) >> 52); ++ int baseZ = (int) ((id << 26) >> 38); ++ long k = SectionPos.blockPosAsSectionLong(baseX, baseY, baseZ); ++ int i1 = baseY & 15; ++ int j1 = baseY >> 4; ++ // Paper end + int k1; + + if (i1 != 0) { +@@ -119,15 +128,16 @@ public final class SkyLightEngine extends LayerLightEngine> 38); ++ int baseY = (int) ((id << 52) >> 52); ++ int baseZ = (int) ((id << 26) >> 38); ++ long j1 = SectionPos.blockPosAsSectionLong(baseX, baseY, baseZ); ++ DataLayer nibblearray = this.storage.updating.getUpdatingOptimized(j1); ++ // Paper end + Direction[] aenumdirection = SkyLightEngine.DIRECTIONS; + int k1 = aenumdirection.length; + + for (int l1 = 0; l1 < k1; ++l1) { + Direction enumdirection = aenumdirection[l1]; +- long i2 = BlockPos.offset(id, enumdirection); +- long j2 = SectionPos.blockToSection(i2); ++ // Paper start ++ int newX = baseX + enumdirection.getStepX(); ++ int newY = baseY + enumdirection.getStepY(); ++ int newZ = baseZ + enumdirection.getStepZ(); ++ long i2 = BlockPos.asLong(newX, newY, newZ); ++ long j2 = SectionPos.blockPosAsSectionLong(newX, newY, newZ); ++ // Paper end + DataLayer nibblearray1; + + if (j1 == j2) { + nibblearray1 = nibblearray; + } else { +- nibblearray1 = ((SkyLightSectionStorage) this.storage).getDataLayer(j2, true); ++ nibblearray1 = ((SkyLightSectionStorage) this.storage).updating.getUpdatingOptimized(j2); // Paper + } + + if (nibblearray1 != null) { + if (i2 != excludedId) { +- int k2 = this.computeLevelFromNeighbor(i2, id, this.getLevel(nibblearray1, i2)); ++ int k2 = this.computeLevelFromNeighbor(i2, id, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper + + if (l > k2) { + l = k2; +@@ -215,7 +235,7 @@ public final class SkyLightEngine extends LayerLightEngine> 38); ++ int baseY = (int) ((blockPos << 52) >> 52); ++ int baseZ = (int) ((blockPos << 26) >> 38); ++ long j = SectionPos.blockPosAsSectionLong(baseX, baseY, baseZ); ++ // Paper end + int k = SectionPos.y(j); + synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data + SkyLightSectionStorage.SkyDataLayerStorageMap lightenginestoragesky_a = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.e_visible; // Paper - avoid copying light data - must be after lock acquire +@@ -49,7 +54,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage> 52) & 15, (int) baseZ & 15); // Paper - y changed above + } else { + return 15; + } +@@ -168,7 +173,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage> 42) << 4; // Paper ++ int baseY = (int) (i << 44 >> 44) << 4; // Paper ++ int baseZ = (int) (i << 22 >> 42) << 4; // Paper + j = this.getLevel(i); + if (j != 2 && !this.sectionsToRemoveSourcesFrom.contains(i) && this.sectionsWithSources.add(i)) { + int l; +@@ -203,10 +211,10 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage> 42) << 4; // Paper ++ int baseY = (int) (i << 44 >> 44) << 4; // Paper ++ int baseZ = (int) (i << 22 >> 42) << 4; // Paper + if (this.sectionsWithSources.remove(i) && this.storingLightForSection(i)) { + for (j = 0; j < 16; ++j) { + for (k = 0; k < 16; ++k) { +- long l3 = BlockPos.asLong(SectionPos.sectionToBlockCoord(SectionPos.x(i)) + j, SectionPos.sectionToBlockCoord(SectionPos.y(i)) + 16 - 1, SectionPos.sectionToBlockCoord(SectionPos.z(i)) + k); ++ long l3 = BlockPos.asLong(baseX + j, baseY + 16 - 1, baseZ + k); // Paper + + lightProvider.checkEdge(Long.MAX_VALUE, l3, 15, false); + } diff --git a/Remapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/Remapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch new file mode 100644 index 0000000000..a8c890b13a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 18 Jun 2016 23:22:12 -0400 +Subject: [PATCH] Delay Chunk Unloads based on Player Movement + +When players are moving in the world, doing things such as building or exploring, +they will commonly go back and forth in a small area. This causes a ton of chunk load +and unload activity on the edge chunks of their view distance. + +A simple back and forth movement in 6 blocks could spam a chunk to thrash a +loading and unload cycle over and over again. + +This is very wasteful. This system introduces a delay of inactivity on a chunk +before it actually unloads, which will be handled by the ticket expiry process. + +This allows servers with smaller worlds who do less long distance exploring to stop +wasting cpu cycles on saving/unloading/reloading chunks repeatedly. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6463d3e4837d032a35654a035f42b8a805e0e286..1655bca0502e7b871de4addaa163536d86547a02 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -637,4 +637,13 @@ public class PaperWorldConfig { + private void viewDistance() { + this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); + } ++ ++ public long delayChunkUnloadsBy; ++ private void delayChunkUnloadsBy() { ++ delayChunkUnloadsBy = PaperConfig.getSeconds(getString("delay-chunk-unloads-by", "10s")); ++ if (delayChunkUnloadsBy > 0) { ++ log("Delaying chunk unloads by " + delayChunkUnloadsBy + " seconds"); ++ delayChunkUnloadsBy *= 20; ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index e41f388e8350010a471410436adf15a906f07e97..e0241b9d60cd2b72f8fb774f1ab4753dfd615184 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -185,6 +185,27 @@ public abstract class DistanceManager { + boolean removed = false; // CraftBukkit + if (arraysetsorted.remove(ticket)) { + removed = true; // CraftBukkit ++ // Paper start - delay chunk unloads for player tickets ++ long delayChunkUnloadsBy = chunkMap.level.paperConfig.delayChunkUnloadsBy; ++ if (ticket.getType() == TicketType.PLAYER && delayChunkUnloadsBy > 0) { ++ boolean hasPlayer = false; ++ for (Ticket ticket1 : arraysetsorted) { ++ if (ticket1.getType() == TicketType.PLAYER) { ++ hasPlayer = true; ++ break; ++ } ++ } ++ ChunkHolder playerChunk = chunkMap.getUpdatingChunkIfPresent(i); ++ if (!hasPlayer && playerChunk != null && playerChunk.isFullChunkReady()) { ++ Ticket delayUnload = new Ticket(TicketType.DELAY_UNLOAD, 33, i); ++ delayUnload.delayUnloadBy = delayChunkUnloadsBy; ++ delayUnload.setCurrentTick(this.ticketTickCounter); ++ arraysetsorted.remove(delayUnload); ++ // refresh ticket ++ arraysetsorted.add(delayUnload); ++ } ++ } ++ // Paper end + } + + if (arraysetsorted.isEmpty()) { +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index c0bfe136ccb9ad4fc0f8ccdd703254205213ec8e..f7898bd7806684d2c068898cecbf835d834df461 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -9,11 +9,13 @@ public final class Ticket implements Comparable> { + public final T key; public final T getObjectReason() { return this.key; } // Paper - OBFHELPER + private long createdTick; public final long getCreationTick() { return this.createdTick; } // Paper - OBFHELPER + public int priority = 0; // Paper ++ public long delayUnloadBy; // Paper + + protected Ticket(TicketType type, int level, T argument) { + this.type = type; + this.ticketLevel = level; + this.key = argument; ++ this.delayUnloadBy = type.timeout; // Paper + } + + public int compareTo(Ticket ticket) { +@@ -63,7 +65,7 @@ public final class Ticket implements Comparable> { + } + + protected boolean timedOut(long currentTick) { +- long j = this.type.timeout(); ++ long j = delayUnloadBy; // Paper + + return j != 0L && currentTick - this.createdTick > j; + } +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index 2444f6f676db543509b14e8c882491dc3f41b264..531ebf1bafec2b295af9f6dfec8f4b6466688287 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -30,6 +30,7 @@ public class TicketType { + public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper + public static final TicketType PRIORITY = create("priority", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper + public static final TicketType URGENT = create("urgent", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper ++ public static final TicketType DELAY_UNLOAD = create("delay_unload", Long::compareTo, 300); // Paper + + public static TicketType create(String name, Comparator comparator) { + return new TicketType<>(name, comparator, 0L); diff --git a/Remapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/Remapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch new file mode 100644 index 0000000000..2d4cc183be --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch @@ -0,0 +1,129 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 9 Jun 2020 03:33:03 -0400 +Subject: [PATCH] Add Plugin Tickets to API Chunk Methods + +Like previous versions, plugins loading chunks kept them loaded until +they garbage collected to avoid constant spamming of chunk loads + +This adds tickets to a few more places so that they can be unloaded. + +Additionally, this drops their ticket level to BORDER so they wont be ticking +so they will just sit inactive instead. + +Using .loadChunk to keep a chunk ticking was a horrible idea for upstream +when we have TWO methods that are able to do that already in the API. + +Also reduce their collection count down to a maximum of 1 second. Barely +anyone knows what chunk-gc is in bukkit.yml as its less relevant now, and +since this wasn't spigot behavior, this is safe to mostly ignore (unless someone +wants it to collect even faster, they can restore that setting back to 1 instead of 20+) + +Not adding it to .getType() though to keep behavior consistent with vanilla for performance reasons. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 92f1a6d32a96fee682342e86c3ffd3c65292150b..2ec41cb87cec97780f1fa8abfbb756fca4dba1bf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -342,7 +342,7 @@ public final class CraftServer implements Server { + ambientSpawn = configuration.getInt("spawn-limits.ambient"); + console.autosavePeriod = configuration.getInt("ticks-per.autosave"); + warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); +- TicketType.PLUGIN.timeout = configuration.getInt("chunk-gc.period-in-ticks"); ++ TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + minimumAPI = configuration.getString("settings.minimum-api"); + loadIcon(); + } +@@ -832,7 +832,7 @@ public final class CraftServer implements Server { + waterAmbientSpawn = configuration.getInt("spawn-limits.water-ambient"); + ambientSpawn = configuration.getInt("spawn-limits.ambient"); + warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); +- TicketType.PLUGIN.timeout = configuration.getInt("chunk-gc.period-in-ticks"); ++ TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + minimumAPI = configuration.getString("settings.minimum-api"); + printSaveWarning = false; + console.autosavePeriod = configuration.getInt("ticks-per.autosave"); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 7261e22a71d219efe0949a08c5d3f10747759469..4436b3d23dc8f33925da1ec539ea16307e0785b9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.ClientboundCustomSoundPacket; + import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; + import net.minecraft.network.protocol.game.ClientboundSetTimePacket; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.DistanceManager; +@@ -389,8 +390,21 @@ public class CraftWorld implements World { + + @Override + public Chunk getChunkAt(int x, int z) { +- return this.world.getChunkSource().getChunk(x, z, true).bukkitChunk; ++ // Paper start - add ticket to hold chunk for a little while longer if plugin accesses it ++ net.minecraft.world.level.chunk.LevelChunk chunk = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); ++ if (chunk == null) { ++ addTicket(x, z); ++ chunk = this.world.getChunkSource().getChunk(x, z, true); ++ } ++ return chunk.bukkitChunk; ++ // Paper end ++ } ++ ++ // Paper start ++ private void addTicket(int x, int z) { ++ MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE)); // Paper + } ++ // Paper end + + @Override + public Chunk getChunkAt(Block block) { +@@ -465,7 +479,7 @@ public class CraftWorld implements World { + public boolean unloadChunkRequest(int x, int z) { + org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot + if (isChunkLoaded(x, z)) { +- world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); ++ world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE); // Paper + } + + return true; +@@ -542,9 +556,12 @@ public class CraftWorld implements World { + org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot + // Paper start - Optimize this method + ChunkPos chunkPos = new ChunkPos(x, z); ++ ChunkAccess immediate = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); // Paper ++ if (immediate != null) return true; // Paper + + if (!generate) { +- ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z); ++ ++ //IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); // Paper + if (immediate == null) { + immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); + } +@@ -552,7 +569,7 @@ public class CraftWorld implements World { + if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) { + return false; // not full status + } +- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper + world.getChunk(x, z); // make sure we're at ticket level 32 or lower + return true; + } +@@ -579,7 +596,7 @@ public class CraftWorld implements World { + // we do this so we do not re-read the chunk data on disk + } + +- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper + world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); + return true; + // Paper end +@@ -2529,6 +2546,7 @@ public class CraftWorld implements World { + } + return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { + net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); ++ if (chunk != null) addTicket(x, z); // Paper + return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + }, net.minecraft.server.MinecraftServer.getServer()); + } diff --git a/Remapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch b/Remapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch new file mode 100644 index 0000000000..f86c4c1c6b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: David Slovikosky +Date: Tue, 9 Jun 2020 00:10:03 -0700 +Subject: [PATCH] Fix missing chunks due to integer overflow + +This patch fixes a bug in the WorldChunkManagerTheEnd class where the distance +from 0,0 squared overflows the maximum size of an integer. The overflow leads +to hard chunk borders around 370,000 blocks from 0,0. After this cutoff there +is a few hundred thousand block gap before end land resuming to generate at +530,000 blocks from spawn. This is due to the integer flipping back and forth. + +The fix for the issue is quite simple, casting chunk coordinates to longs +allows the distance calculation to avoid overflow and work as intended. + +diff --git a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +index af006c2e45e0a14367a0bc850c319024c6b82024..063369d3a64b4afc9cc6e1d20360900595e1a05f 100644 +--- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java ++++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +@@ -75,7 +75,9 @@ public class TheEndBiomeSource extends BiomeSource { + int l = j / 2; + int i1 = i % 2; + int j1 = j % 2; +- float f = 100.0F - Mth.sqrt((float) (i * i + j * j)) * 8.0F; ++ // Paper start - cast ints to long to avoid integer overflow ++ float f = 100.0F - Mth.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; ++ // Paper end + + f = Mth.clamp(f, -100.0F, 80.0F); + diff --git a/Remapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/Remapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch new file mode 100644 index 0000000000..423af0ebf9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ossi +Date: Fri, 12 Jun 2020 01:38:06 +0300 +Subject: [PATCH] Fix CraftScheduler#runTaskTimerAsynchronously(Plugin, + Consumer, long, long) scheduling a non-repeating task instead of + a repeating one. + + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index ca90237a53c9a026919d28adaedf483ca3c7c2a8..13e461ffb2ee2e7d0440c0f60809ea99629b843c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -184,7 +184,7 @@ public class CraftScheduler implements BukkitScheduler { + + @Override + public void runTaskTimerAsynchronously(Plugin plugin, Consumer task, long delay, long period) throws IllegalArgumentException { +- runTaskTimerAsynchronously(plugin, (Object) task, delay, CraftTask.NO_REPEATING); ++ runTaskTimerAsynchronously(plugin, (Object) task, delay, period); + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch b/Remapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch new file mode 100644 index 0000000000..1d54c7bad6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Thu, 11 Jun 2020 17:29:42 -0700 +Subject: [PATCH] Fix piston physics inconsistency - MC-188840 + +Pistons invoke physics when they move blocks. The physics can cause +tnt blocks to ignite. However, pistons (when storing the blocks they "moved") +don't actually go back to the world state sometimes to check if something +like that happened. As a result they end up moving the tnt like it was +never ignited. This resulted in the ability to create machines +that can duplicate tnt, called "world eaters". +This patch makes the piston logic retrieve the block state from the world +prevent this from occuring. + +This patch also sets the moved pos to air immediately after creating +the moving piston TE. This prevents the block from being updated from +other physics calls by the piston. + +Tested against the following tnt duper design: +https://www.youtube.com/watch?v=mS7xxNGhjxs + +This patch also affects every type of machine that utilises +this mechanic. For example, dead coral is removed by a physics +update when being moved while it is attached to slimeblocks. + +Standard piston machines that don't destroy or modify the +blocks they move by physics updates should be entirely +unaffected. + +This patch fixes https://bugs.mojang.com/browse/MC-188840 + +This patch also fixes rail duping and carpet duping. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 7f140333c2e62012fa572c1a061d84432426997f..b67ba8f75e4a3358d7c2462918b85b0bf9b5a922 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -434,4 +434,10 @@ public class PaperConfig { + consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); + } + ++ public static boolean allowPistonDuplication; ++ private static void allowPistonDuplication() { ++ config.set("settings.unsupported-settings.allow-piston-duplication-readme", "This setting controls if player should be able to use TNT duplication, but this also allows duplicating carpet, rails and potentially other items"); ++ allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); ++ set("settings.unsupported-settings.allow-tnt-duplication", null); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +index 40a18302dd682e5ade4ec77ac7f316b6c0f8c112..44876557515eaa6bbe33344b3d3ba03aee58409f 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -398,12 +398,24 @@ public class PistonBaseBlock extends DirectionalBlock { + } + + for (k = list.size() - 1; k >= 0; --k) { +- blockposition3 = (BlockPos) list.get(k); +- iblockdata1 = world.getBlockState(blockposition3); ++ // Paper start - fix a variety of piston desync dupes ++ boolean allowDesync = com.destroystokyo.paper.PaperConfig.allowPistonDuplication; ++ BlockPos oldPos = blockposition3 = (BlockPos) list.get(k); ++ iblockdata1 = allowDesync ? world.getBlockState(oldPos) : null; ++ // Paper end - fix a variety of piston desync dupes + blockposition3 = blockposition3.relative(enumdirection1); + map.remove(blockposition3); + world.setBlock(blockposition3, (BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, dir), 68); +- world.setBlockEntity(blockposition3, MovingPistonBlock.newMovingBlockEntity((BlockState) list1.get(k), dir, retract, false)); ++ // Paper start - fix a variety of piston desync dupes ++ if (!allowDesync) { ++ iblockdata1 = world.getBlockState(oldPos); ++ map.replace(oldPos, iblockdata1); ++ } ++ world.setBlockEntity(blockposition3, MovingPistonBlock.newMovingBlockEntity(allowDesync ? list1.get(k) : iblockdata1, dir, retract, false)); ++ if (!allowDesync) { ++ world.setBlock(oldPos, Blocks.AIR.defaultBlockState(), 2 | 4 | 16 | 1024); // set air to prevent later physics updates from seeing this block ++ } ++ // Paper end - fix a variety of piston desync dupes + aiblockdata[j++] = iblockdata1; + } + +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +index 73888713746e7ddd72ba9ac9d33d8e616eb3bd25..001e90da8b09e16b6df4849a5bac4f4821000c94 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +@@ -279,7 +279,7 @@ public class PistonMovingBlockEntity extends BlockEntity implements TickableBloc + BlockState iblockdata = Block.updateFromNeighbourShapes(this.movedState, (LevelAccessor) this.level, this.worldPosition); + + if (iblockdata.isAir()) { +- this.level.setBlock(this.worldPosition, this.movedState, 84); ++ this.level.setBlock(this.worldPosition, this.movedState, com.destroystokyo.paper.PaperConfig.allowPistonDuplication ? 84 : (84 | 2)); // Paper - force notify (flag 2), it's possible the set type by the piston block (which doesn't notify) set this block to air + Block.updateOrDestroy(this.movedState, iblockdata, this.level, this.worldPosition, 3); + } else { + if (iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) iblockdata.getValue(BlockStateProperties.WATERLOGGED)) { diff --git a/Remapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch b/Remapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch new file mode 100644 index 0000000000..d06a661655 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 12 Jun 2020 13:33:19 -0700 +Subject: [PATCH] Fix sand duping + +If the falling block dies during teleportation (entity#move), then we need +to detect that by placing a check after the move. + +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index ff8f7e4569a889ead1512b7c9908f9c5cad9eed5..2ba81e7179c7f9e2e1add1ad6bd6b96ee12c5da1 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -101,6 +101,11 @@ public class FallingBlockEntity extends Entity { + + @Override + public void tick() { ++ // Paper start - fix sand duping ++ if (this.removed) { ++ return; ++ } ++ // Paper end - fix sand duping + if (this.blockState.isAir()) { + this.remove(); + } else { +@@ -123,6 +128,12 @@ public class FallingBlockEntity extends Entity { + + this.move(MoverType.SELF, this.getDeltaMovement()); + ++ // Paper start - fix sand duping ++ if (this.removed) { ++ return; ++ } ++ // Paper end - fix sand duping ++ + // Paper start - Configurable EntityFallingBlock height nerf + if (this.level.paperConfig.fallingBlockHeightNerf != 0 && this.getY() > this.level.paperConfig.fallingBlockHeightNerf) { + if (this.dropItem && this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { diff --git a/Remapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch b/Remapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch new file mode 100644 index 0000000000..9994f830fa --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 12 Jun 2020 16:51:39 -0700 +Subject: [PATCH] Prevent position desync in playerconnection causing tp + exploit + +Caused the server to revert to the player's overworld coordinates +after teleporting into the end. + +Sidenote: The underlying issue is that the move call can teleport +entities and do other things like kill the entity. In the future, +to fix all exploits derieved from this usually unexpected +behaviour, we need to move all of this dangerous logic outside +of the move call and into an appropriate place in the tick method. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0625bc7ffd07b66b27176fe62ae3061aa7c67df2..fbafb89cc63744d942933546026e272122bd9fba 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1324,6 +1324,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9)); + this.player.setOnGround(packet.isOnGround()); // CraftBukkit - SPIGOT-5810, SPIGOT-5835: reset by this.player.move ++ // Paper start - prevent position desync ++ if (this.awaitingPositionFromClient != null) { ++ return; // ... thanks Mojang for letting move calls teleport across dimensions. ++ } ++ // Paper end - prevent position desync + double d12 = d8; + + d7 = d4 - this.player.getX(); diff --git a/Remapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch b/Remapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch new file mode 100644 index 0000000000..38690afc49 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 12 Jun 2020 22:25:11 -0700 +Subject: [PATCH] Fix enderdragon exp dupe + +Properly track death stage when unloading/loading in the +dragon + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index ec9436005a3a6fdfb4783d1092bb361224eb6414..b224a630f8adb1fa357c838e6b32c784aed0b15b 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -879,6 +879,7 @@ public class EnderDragon extends Mob implements Enemy { + public void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); + tag.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId()); ++ tag.putInt("Paper.DeathTick", this.dragonDeathTime); // Paper + } + + @Override +@@ -887,6 +888,7 @@ public class EnderDragon extends Mob implements Enemy { + if (tag.contains("DragonPhase")) { + this.phaseManager.setPhase(EnderDragonPhase.getById(tag.getInt("DragonPhase"))); + } ++ this.dragonDeathTime = tag.getInt("Paper.DeathTick"); // Paper + + } + diff --git a/Remapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch b/Remapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch new file mode 100644 index 0000000000..d25c9ffc5a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Wed, 10 Jun 2020 23:55:15 +0100 +Subject: [PATCH] Inventory getHolder method without block snapshot + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +index ef2d18d19a86b3701855aa1ac126462e663f8fcd..7ccc085228f373e6eba55d809bed480d43d5c211 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +@@ -10,6 +10,7 @@ import net.minecraft.world.inventory.PlayerEnderChestContainer; + import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; + import net.minecraft.world.level.block.entity.BarrelBlockEntity; + import net.minecraft.world.level.block.entity.BlastFurnaceBlockEntity; ++import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BrewingStandBlockEntity; + import net.minecraft.world.level.block.entity.DispenserBlockEntity; + import net.minecraft.world.level.block.entity.DropperBlockEntity; +@@ -525,6 +526,13 @@ public class CraftInventory implements Inventory { + return inventory.getOwner(); + } + ++ // Paper start - getHolder without snapshot ++ @Override ++ public InventoryHolder getHolder(boolean useSnapshot) { ++ return inventory instanceof BlockEntity ? ((BlockEntity) inventory).getOwner(useSnapshot) : getHolder(); ++ } ++ // Paper end ++ + @Override + public int getMaxStackSize() { + return inventory.getMaxStackSize(); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java +index 3245dfa94410d319e53543c862c990e80ed3c72d..23dcf6e9332bd2b42ebb851497483e41948355d8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java +@@ -64,6 +64,13 @@ public class CraftInventoryDoubleChest extends CraftInventory implements DoubleC + return new DoubleChest(this); + } + ++ // Paper start - getHolder without snapshot ++ @Override ++ public DoubleChest getHolder(boolean useSnapshot) { ++ return getHolder(); ++ } ++ // Paper end ++ + @Override + public Location getLocation() { + return getLeftSide().getLocation().add(getRightSide().getLocation()).multiply(0.5); diff --git a/Remapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch b/Remapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch new file mode 100644 index 0000000000..cafd641bc1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nesaak <52047222+Nesaak@users.noreply.github.com> +Date: Sat, 23 May 2020 10:31:11 -0400 +Subject: [PATCH] Expose Arrow getItemStack + + +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 3ce431c1fdf1f5bd62b49f26cca188e939e98efa..6225f390b51733217a809910182f58acea1055e2 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -556,6 +556,7 @@ public abstract class AbstractArrow extends Projectile { + } + } + ++ public final ItemStack getOriginalItemStack() { return getPickupItem(); } // Paper - OBFHELPER - exists purely due to overrides all as protected and dont want to change them all + protected abstract ItemStack getPickupItem(); + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +index 5b898118a46007a85254931c7b5bd18d7cda99be..91d32aff07e81608a2f8ecb1301ef3c08533494b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +@@ -102,6 +102,13 @@ public class CraftArrow extends AbstractProjectile implements AbstractArrow { + getHandle().pickup = net.minecraft.world.entity.projectile.AbstractArrow.Pickup.byOrdinal(status.ordinal()); + } + ++ // Paper start ++ @Override ++ public org.bukkit.craftbukkit.inventory.CraftItemStack getItemStack() { ++ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(getHandle().getOriginalItemStack()); ++ } ++ //Paper end ++ + @Override + public void setTicksLived(int value) { + super.setTicksLived(value); diff --git a/Remapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch b/Remapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch new file mode 100644 index 0000000000..412fc1c8ad --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Fri, 5 Jun 2020 18:24:06 -0400 +Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index fbafb89cc63744d942933546026e272122bd9fba..a0b2fc3fe59d97b9282a9451f35542b39df774e7 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2770,9 +2770,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + this.player.resetLastActionTime(); + if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu.isSynched(this.player) && this.player.containerMenu instanceof RecipeBookMenu) { +- this.server.getRecipeManager().byKey(packet.getRecipe()).ifPresent((irecipe) -> { +- ((RecipeBookMenu) this.player.containerMenu).handlePlacement(packet.isShiftDown(), irecipe, this.player); +- }); ++ // Paper start - fire event for clicking recipes in the recipe book ++ com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent event = new com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent( ++ player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(packet.getRecipe()), packet.isShiftDown()); ++ if (event.callEvent()) { ++ this.server.getRecipeManager().byKey(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getRecipe())).ifPresent((irecipe) -> { ++ ((ContainerRecipeBook) this.player.activeContainer).a(event.isMakeAll(), irecipe, this.player); ++ }); ++ } ++ // Paper end + } + } + diff --git a/Remapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch b/Remapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch new file mode 100644 index 0000000000..43a0839a47 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 26 Jun 2020 22:35:08 -0700 +Subject: [PATCH] Hide sync chunk writes behind flag + +Syncing writes on each write call has terrible performance +on harddrives. + +-DPaper.enable-sync-chunk-writes=true to enable + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +index 545096d9ba403396b6aaa7bb6d912f2de08a967e..3450a58fc02a472eb710aa1a31f6fecefc982b6f 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +@@ -108,7 +108,7 @@ public class DedicatedServerProperties extends Settings { + return Mth.clamp(integer, 1, 29999984); + }, 29999984); +- this.syncChunkWrites = this.get("sync-chunk-writes", true); ++ this.syncChunkWrites = this.get("sync-chunk-writes", true) && Boolean.getBoolean("Paper.enable-sync-chunk-writes"); // Paper - hide behind flag + this.enableJmxMonitoring = this.get("enable-jmx-monitoring", false); + this.enableStatus = this.get("enable-status", true); + this.entityBroadcastRangePercentage = this.get("entity-broadcast-range-percentage", (integer) -> { diff --git a/Remapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch b/Remapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch new file mode 100644 index 0000000000..1f74c2ced9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch @@ -0,0 +1,76 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Fri, 14 Sep 2018 17:42:08 +0200 +Subject: [PATCH] Limit lightning strike effect distance + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1655bca0502e7b871de4addaa163536d86547a02..978062774c1db286bfb9b0ffdef19d880b1f249b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -646,4 +646,26 @@ public class PaperWorldConfig { + delayChunkUnloadsBy *= 20; + } + } ++ ++ public double sqrMaxThunderDistance; ++ public double sqrMaxLightningImpactSoundDistance; ++ public double maxLightningFlashDistance; ++ private void lightningStrikeDistanceLimit() { ++ sqrMaxThunderDistance = getInt("lightning-strike-distance-limit.sound", -1); ++ if (sqrMaxThunderDistance > 0) { ++ sqrMaxThunderDistance *= sqrMaxThunderDistance; ++ } ++ ++ sqrMaxLightningImpactSoundDistance = getInt("lightning-strike-distance-limit.impact-sound", -1); ++ if (sqrMaxLightningImpactSoundDistance < 0) { ++ sqrMaxLightningImpactSoundDistance = 32 * 32; //Vanilla value ++ } else { ++ sqrMaxLightningImpactSoundDistance *= sqrMaxLightningImpactSoundDistance; ++ } ++ ++ maxLightningFlashDistance = getInt("lightning-strike-distance-limit.flash", -1); ++ if (maxLightningFlashDistance < 0) { ++ maxLightningFlashDistance = 512; // Vanilla value ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java +index e030e7f3d8bd9fe6578df0b560a237d494ec8a01..4b0dbeded2b8a475d32f518957909d3495a4b6fc 100644 +--- a/src/main/java/net/minecraft/world/entity/LightningBolt.java ++++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java +@@ -15,7 +15,6 @@ import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.Difficulty; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +@@ -74,6 +73,17 @@ public class LightningBolt extends Entity { + double deltaX = this.getX() - player.getX(); + double deltaZ = this.getZ() - player.getZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; ++ // Paper start - Limit lightning strike effect distance ++ if (distanceSquared <= this.level.paperConfig.sqrMaxLightningImpactSoundDistance) { ++ player.connection.send(new ClientboundSoundPacket(SoundEvents.LIGHTNING_BOLT_IMPACT, ++ SoundSource.WEATHER, this.getX(), this.getY(), this.getZ(), 2.0f, 0.5F + this.random.nextFloat() * 0.2F)); ++ } ++ ++ if (level.paperConfig.sqrMaxThunderDistance != -1 && distanceSquared >= level.paperConfig.sqrMaxThunderDistance) { ++ continue; ++ } ++ ++ // Paper end + if (distanceSquared > viewDistance * viewDistance) { + double deltaLength = Math.sqrt(distanceSquared); + double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance; +@@ -84,7 +94,7 @@ public class LightningBolt extends Entity { + } + } + // CraftBukkit end +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_IMPACT, SoundSource.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); ++// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); // Paper - Limit lightning strike effect distance (the packet is now sent from inside the loop) + } + + --this.life; diff --git a/Remapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch b/Remapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch new file mode 100644 index 0000000000..9e0fdeee13 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 16 May 2020 10:05:30 +0200 +Subject: [PATCH] Add permission for command blocks + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index af048ab682612233c01f7087d7b8afbf7e58945b..79f3e4176145c42debb9adc1e68175cf063c1f22 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -386,7 +386,7 @@ public class ServerPlayerGameMode { + BlockEntity tileentity = this.level.getBlockEntity(pos); + Block block = iblockdata.getBlock(); + +- if ((block instanceof CommandBlock || block instanceof StructureBlock || block instanceof JigsawBlock) && !this.player.canUseGameMasterBlocks()) { ++ if ((block instanceof CommandBlock || block instanceof StructureBlock || block instanceof JigsawBlock) && !this.player.canUseGameMasterBlocks() && !(block instanceof CommandBlock && (this.player.isCreative() && this.player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission + this.level.sendBlockUpdated(pos, iblockdata, iblockdata, 3); + return false; + } else if (this.player.blockActionRestricted((Level) this.level, pos, this.gameModeForPlayer)) { +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index a0b2fc3fe59d97b9282a9451f35542b39df774e7..471370a9aafa3eda83beb4097c6233650bd155ee 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -796,7 +796,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (!this.server.isCommandBlockEnabled()) { + this.player.sendMessage(new TranslatableComponent("advMode.notEnabled"), Util.NIL_UUID); +- } else if (!this.player.canUseGameMasterBlocks()) { ++ } else if (!this.player.canUseGameMasterBlocks() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission + this.player.sendMessage(new TranslatableComponent("advMode.notAllowed"), Util.NIL_UUID); + } else { + BaseCommandBlock commandblocklistenerabstract = null; +@@ -859,7 +859,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (!this.server.isCommandBlockEnabled()) { + this.player.sendMessage(new TranslatableComponent("advMode.notEnabled"), Util.NIL_UUID); +- } else if (!this.player.canUseGameMasterBlocks()) { ++ } else if (!this.player.canUseGameMasterBlocks() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission + this.player.sendMessage(new TranslatableComponent("advMode.notAllowed"), Util.NIL_UUID); + } else { + BaseCommandBlock commandblocklistenerabstract = packet.getCommandBlock(this.player.level); +diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +index 00dc4cd436023b946d7005f17a7ba983a4bbdfb6..23500428abf5e7daec19f8fb3c24e6c5361f0819 100644 +--- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java ++++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +@@ -192,7 +192,7 @@ public abstract class BaseCommandBlock implements CommandSource { + } + + public InteractionResult usedBy(Player player) { +- if (!player.canUseGameMasterBlocks()) { ++ if (!player.canUseGameMasterBlocks() && !player.isCreative() && !player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission + return InteractionResult.PASS; + } else { + if (player.getCommandSenderWorld().isClientSide) { +diff --git a/src/main/java/net/minecraft/world/level/block/CommandBlock.java b/src/main/java/net/minecraft/world/level/block/CommandBlock.java +index 088d78905732cacf69beb7a4b713dac4bec82220..c5e81e7d67504b1bc2a87c0b577bb93be4a57e9c 100644 +--- a/src/main/java/net/minecraft/world/level/block/CommandBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CommandBlock.java +@@ -128,7 +128,7 @@ public class CommandBlock extends BaseEntityBlock { + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { + BlockEntity tileentity = world.getBlockEntity(pos); + +- if (tileentity instanceof CommandBlockEntity && player.canUseGameMasterBlocks()) { ++ if (tileentity instanceof CommandBlockEntity && (player.canUseGameMasterBlocks() || (player.isCreative() && player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission + player.openCommandBlock((CommandBlockEntity) tileentity); + return InteractionResult.sidedSuccess(world.isClientSide); + } else { +diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java +index 525ebf961e5da0687183a5e2ead23ed92cbd9d79..a4a809f302c5ff9c76cde5fc0add2ceec1bdf9b5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java +@@ -16,6 +16,7 @@ public final class CraftDefaultPermissions { + DefaultPermissions.registerPermission(ROOT + ".nbt.copy", "Gives the user the ability to copy NBT in creative", org.bukkit.permissions.PermissionDefault.TRUE, parent); + DefaultPermissions.registerPermission(ROOT + ".debugstick", "Gives the user the ability to use the debug stick in creative", org.bukkit.permissions.PermissionDefault.OP, parent); + DefaultPermissions.registerPermission(ROOT + ".debugstick.always", "Gives the user the ability to use the debug stick in all game modes", org.bukkit.permissions.PermissionDefault.FALSE, parent); ++ DefaultPermissions.registerPermission(ROOT + ".commandblock", "Gives the user the ability to use command blocks.", org.bukkit.permissions.PermissionDefault.OP, parent); // Paper + // Spigot end + parent.recalculatePermissibles(); + } diff --git a/Remapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch b/Remapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch new file mode 100644 index 0000000000..f77fef5ea0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 May 2020 22:12:46 -0400 +Subject: [PATCH] Ensure Entity AABB's are never invalid + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d9bb00752ac81b2171d3ad25fd84904467a18e3b..728379292728cf58f5512feae3cdc74392980f68 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -66,6 +66,7 @@ import net.minecraft.world.Nameable; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.animal.AbstractFish; + import net.minecraft.world.entity.animal.Animal; ++import net.minecraft.world.entity.decoration.HangingEntity; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.AbstractMinecart; +@@ -478,7 +479,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + public void setPos(double x, double y, double z) { + this.setPosRaw(x, y, z); +- this.setBoundingBox(this.dimensions.makeBoundingBox(x, y, z)); ++ //this.a(this.size.a(d0, d1, d2)); // Paper - move into setPositionRaw + if (valid) ((ServerLevel) level).updateChunkPos(this); // CraftBukkit + } + +@@ -2998,6 +2999,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return new AABB(vec3d, vec3d1); + } + ++ public final void setBoundingBox(AABB axisalignedbb) { setBoundingBox(axisalignedbb); } // Paper - OBFHELPER + public void setBoundingBox(AABB boundingBox) { + // CraftBukkit start - block invalid bounding boxes + double minX = boundingBox.minX, +@@ -3436,6 +3438,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public void setPosRaw(double x, double y, double z) { ++ // Paper start - never allow AABB to become desynced from position ++ // hanging has its own special logic ++ if (!(this instanceof HangingEntity) && (this.position.x != x || this.position.y != y || this.position.z != z)) { ++ this.setBoundingBox(this.dimensions.makeBoundingBox(x, y, z)); ++ } ++ // Paper end + if (this.position.x != x || this.position.y != y || this.position.z != z) { + this.position = new Vec3(x, y, z); + int i = Mth.floor(x); diff --git a/Remapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch b/Remapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch new file mode 100644 index 0000000000..bc82f5847c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 10 May 2020 22:49:05 -0400 +Subject: [PATCH] Optimize WorldBorder collision checks and air + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 728379292728cf58f5512feae3cdc74392980f68..e9a658b11e2b6683831dc3f5bd20be9a7840ed69 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -102,7 +102,6 @@ import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; +-import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -908,7 +907,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + AABB axisalignedbb = this.getBoundingBox(); + CollisionContext voxelshapecollision = CollisionContext.of(this); + VoxelShape voxelshape = this.level.getWorldBorder().getCollisionShape(); +- Stream stream = Shapes.joinIsNotEmpty(voxelshape, Shapes.create(axisalignedbb.deflate(1.0E-7D)), BooleanOp.AND) ? Stream.empty() : Stream.of(voxelshape); ++ Stream stream = !this.level.getWorldBorder().isInBounds(axisalignedbb) ? Stream.empty() : Stream.of(voxelshape); // Paper + Stream stream1 = this.level.getEntityCollisions(this, axisalignedbb.expandTowards(movement), (entity) -> { + return true; + }); +diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +index feca9ff34936686c0665ae0dbc926869087df3a7..60f8585a736af5b654b8aaed89a39a8bf5e91301 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java ++++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +@@ -143,10 +143,10 @@ public class CollisionSpliterator extends AbstractSpliterator { + AABB axisalignedbb = this.source.getBoundingBox(); + + if (!isBoxFullyWithinWorldBorder(worldborder, axisalignedbb)) { +- VoxelShape voxelshape = worldborder.getCollisionShape(); +- +- if (!isOutsideBorder(voxelshape, axisalignedbb) && isCloseToBorder(voxelshape, axisalignedbb)) { +- consumer.accept(voxelshape); ++ // Paper start ++ if (worldborder.isInBounds(axisalignedbb.deflate(1.0E-7D)) && !worldborder.isInBounds(axisalignedbb.grow(1.0E-7D))) { ++ consumer.accept(worldborder.asVoxelShape()); ++ // Paper end + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index 7a728ca96ee2eaf776c391ba8351196a526e18ec..aaa6251838483de5c46913534413151b5cb1d3fe 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -52,6 +52,7 @@ public class WorldBorder { + return (double) pos.getMaxBlockX() > this.getMinX() && (double) pos.getMinBlockX() < this.getMaxX() && (double) pos.getMaxBlockZ() > this.getMinZ() && (double) pos.getMinBlockZ() < this.getMaxZ(); + } + ++ public final boolean isInBounds(AABB aabb) { return this.isWithinBounds(aabb); } // Paper - OBFHELPER + public boolean isWithinBounds(AABB box) { + return box.maxX > this.getMinX() && box.minX < this.getMaxX() && box.maxZ > this.getMinZ() && box.minZ < this.getMaxZ(); + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index 1603eb3f7d90a4b3a028b20776566db77d09c123..f28d2126bc29fad3971a32cf85a7a7c4803b36ab 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -252,7 +252,7 @@ public final class Shapes { + BlockState iblockdata = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper + if (iblockdata == null) return 0.0D; // Paper + +- if ((k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { ++ if (!iblockdata.isAir() && (k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { // Paper + initial = iblockdata.getCollisionShape((BlockGetter) world, blockposition_mutableblockposition, context).collide(enumdirection_enumaxis2, box.move((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), initial); + if (Math.abs(initial) < 1.0E-7D) { + return 0.0D; diff --git a/Remapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/Remapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch new file mode 100644 index 0000000000..568d1c34e6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 28 Jun 2020 03:59:10 -0400 +Subject: [PATCH] Fix Per World Difficulty / Remembering Difficulty + +Fixes per world difficulty with /difficulty command and also +makes it so that the server keeps the last difficulty used instead +of restoring the server.properties every single load. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index f530c739b6aee3718eb5d0e0e6a09d882d817c68..19544b794b5a46c129016172798ff7294fcfed33 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1645,11 +1645,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Sun, 28 Jun 2020 19:27:20 -0400 +Subject: [PATCH] Paper dumpitem command + +Let's you quickly view the item in your hands NBT data + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 528c860fc0c04431e0ebb2ae6bc96bf9c2d04789..6fad9329213e4e8a3ef9ce7fb568ad22484a11f3 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -12,6 +12,7 @@ import com.google.gson.JsonObject; + import com.google.gson.internal.Streams; + import com.google.gson.stream.JsonWriter; + import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MCUtil; +@@ -36,7 +37,9 @@ import org.bukkit.command.CommandSender; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.entity.Player; ++import org.bukkit.inventory.ItemStack; + + import java.io.File; + import java.io.FileOutputStream; +@@ -59,7 +62,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight", "dumpitem").build(); + + public PaperCommand(String name) { + super(name); +@@ -168,6 +171,9 @@ public class PaperCommand extends Command { + case "reload": + doReload(sender); + break; ++ case "dumpitem": ++ doDumpItem(sender); ++ break; + case "debug": + doDebug(sender, args); + break; +@@ -200,6 +206,19 @@ public class PaperCommand extends Command { + return true; + } + ++ private void doDumpItem(CommandSender sender) { ++ ItemStack itemInHand = ((CraftPlayer) sender).getItemInHand(); ++ net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(itemInHand); ++ CompoundTag tag = itemStack.getTag(); ++ if (tag != null) { ++ String nbt = org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(tag.getNbtPrettyComponent()); ++ Bukkit.getConsoleSender().sendMessage(nbt); ++ sender.sendMessage(nbt); ++ } else { ++ sender.sendMessage("Item does not have NBT"); ++ } ++ } ++ + private void doFixLight(CommandSender sender, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage("Only players can use this command"); +diff --git a/src/main/java/net/minecraft/nbt/Tag.java b/src/main/java/net/minecraft/nbt/Tag.java +index 85e9c5f4620fcf48cb3655fbb2db58b3fb31aa74..ba204cf135be333d4ac1c06ee6c2e961faadf8cb 100644 +--- a/src/main/java/net/minecraft/nbt/Tag.java ++++ b/src/main/java/net/minecraft/nbt/Tag.java +@@ -26,6 +26,7 @@ public interface Tag { + return this.toString(); + } + ++ default Component getNbtPrettyComponent() { return this.getPrettyDisplay(); } // Paper - OBFHELPER + default Component getPrettyDisplay() { + return this.getPrettyDisplay("", 0); + } diff --git a/Remapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch b/Remapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch new file mode 100644 index 0000000000..dfc52a21c5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 28 Jun 2020 19:36:55 -0400 +Subject: [PATCH] Don't allow null UUID's for chat + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +index 002a6c7933f64405707d7d34d3e5c17584539623..a983785bf3bc43f65bd0809870c14a9fd30a3fc1 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +@@ -3,6 +3,7 @@ package net.minecraft.network.protocol.game; + + import java.io.IOException; + import java.util.UUID; ++import net.minecraft.Util; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.chat.ChatType; + import net.minecraft.network.chat.Component; +@@ -21,7 +22,7 @@ public class ClientboundChatPacket implements Packet { + public ClientboundChatPacket(Component message, ChatType location, UUID senderUuid) { + this.message = message; + this.type = location; +- this.sender = senderUuid; ++ this.sender = senderUuid != null ? senderUuid : Util.getNullUUID(); // Paper + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch b/Remapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch new file mode 100644 index 0000000000..2f031e9064 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 28 Jun 2020 19:08:41 -0400 +Subject: [PATCH] Improve Legacy Component serialization size + +Don't constantly send format: false for all formatting options when parent already +has it false + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +index b27af66795d902a2e95d692fa0ff18eccbef8a75..b89660244ffad484e3fbf69ccb9cdc1bc178d2ad 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +@@ -46,6 +46,7 @@ public final class CraftChatMessage { + // Separate pattern with no group 3, new lines are part of previous string + private static final Pattern INCREMENTAL_PATTERN_KEEP_NEWLINES = Pattern.compile("(" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + "[0-9a-fk-orx])|((?:(?:https?):\\/\\/)?(?:[-\\w_\\.]{2,}\\.[a-z]{2,4}.*?(?=[\\.\\?!,;:]?(?:[" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + " ]|$))))", Pattern.CASE_INSENSITIVE); + // ChatColor.b does not explicitly reset, its more of empty ++ private static final Style EMPTY = Style.EMPTY.withItalic(false); // Paper - OBFHELPER + private static final Style RESET = Style.EMPTY.withBold(false).withItalic(false).setUnderline(false).setStrikethrough(false).setRandom(false); + + private final List list = new ArrayList(); +@@ -67,6 +68,7 @@ public final class CraftChatMessage { + Matcher matcher = (keepNewlines ? INCREMENTAL_PATTERN_KEEP_NEWLINES : INCREMENTAL_PATTERN).matcher(message); + String match = null; + boolean needsAdd = false; ++ boolean hasReset = false; // Paper + while (matcher.find()) { + int groupId = 0; + while ((match = matcher.group(++groupId)) == null) { +@@ -112,7 +114,26 @@ public final class CraftChatMessage { + throw new AssertionError("Unexpected message format"); + } + } else { // Color resets formatting +- modifier = RESET.withColor(format); ++ // Paper start - improve legacy formatting ++ Style previous = modifier; ++ modifier = (!hasReset ? RESET : EMPTY).withColor(format); ++ hasReset = true; ++ if (previous.isBold()) { ++ modifier = modifier.withBold(false); ++ } ++ if (previous.isItalic()) { ++ modifier = modifier.withItalic(false); ++ } ++ if (previous.isObfuscated()) { ++ modifier = modifier.setRandom(false); ++ } ++ if (previous.isStrikethrough()) { ++ modifier = modifier.setStrikethrough(false); ++ } ++ if (previous.isUnderlined()) { ++ modifier = modifier.setUnderline(false); ++ } ++ // Paper end + } + needsAdd = true; + break; diff --git a/Remapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch b/Remapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch new file mode 100644 index 0000000000..ffba727ac3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 29 Jun 2020 03:26:17 -0400 +Subject: [PATCH] Support old UUID format for NBT + +We have stored UUID in plenty of places that did not get DFU'd + +So just look for old format and load it if it exists. + +diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java +index c856ca720a9329a94bb07eaa3060c034f95718b3..0b739b5f040697049893d311c99456dbc5470e93 100644 +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -142,6 +142,12 @@ public class CompoundTag implements Tag { + + public void setUUID(String prefix, UUID uuid) { putUUID(prefix, uuid); } // Paper - OBFHELPER + public void putUUID(String key, UUID value) { ++ // Paper start - support old format ++ if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { ++ this.tags.remove(key + "Most"); ++ this.tags.remove(key + "Least"); ++ } ++ // Paper end + this.tags.put(key, NbtUtils.createUUID(value)); + } + +@@ -151,11 +157,21 @@ public class CompoundTag implements Tag { + */ + public UUID getUUID(String prefix) { return getUUID(prefix); } // Paper - OBFHELPER + public UUID getUUID(String key) { ++ // Paper start - support old format ++ if (!contains(key, 11) && this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { ++ return new UUID(this.getLong(key + "Most"), this.getLong(key + "Least")); ++ } ++ // Paper end + return NbtUtils.loadUUID(this.get(key)); + } + + public final boolean hasUUID(String s) { return this.hasUUID(s); } // Paper - OBFHELPER + public boolean hasUUID(String key) { ++ // Paper start - support old format ++ if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { ++ return true; ++ } ++ // Paper end + Tag nbtbase = this.get(key); + + return nbtbase != null && nbtbase.getType() == IntArrayTag.TYPE && ((IntArrayTag) nbtbase).getAsIntArray().length == 4; +diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java +index bf0da04ec9db3ec8313bddb06c278c13073819d1..f57c5e441045a81072a2edfed0f199d90e6d7fde 100644 +--- a/src/main/java/net/minecraft/nbt/NbtUtils.java ++++ b/src/main/java/net/minecraft/nbt/NbtUtils.java +@@ -40,6 +40,11 @@ public final class NbtUtils { + s = tag.getString("Name"); + } + ++ // Paper start - support string UUID's ++ if (tag.contains("Id", 8)) { ++ uuid = UUID.fromString(tag.getString("Id")); ++ } ++ // Paper end + if (tag.hasUUID("Id")) { + uuid = tag.getUUID("Id"); + } diff --git a/Remapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch b/Remapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch new file mode 100644 index 0000000000..40c9060216 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 1 Jul 2020 03:12:06 -0400 +Subject: [PATCH] Clean up duplicated GameProfile Properties + +We had a bug where we accidently cloned properties resulting in skulls +growing to large sizes and preventing login. + +This now automatically cleans up the extra properties. + +diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java +index f57c5e441045a81072a2edfed0f199d90e6d7fde..3abfd21ea84c54aec6256008b3b9e6bbc7ae694c 100644 +--- a/src/main/java/net/minecraft/nbt/NbtUtils.java ++++ b/src/main/java/net/minecraft/nbt/NbtUtils.java +@@ -59,8 +59,8 @@ public final class NbtUtils { + while (iterator.hasNext()) { + String s1 = (String) iterator.next(); + ListTag nbttaglist = nbttagcompound1.getList(s1, 10); +- +- for (int i = 0; i < nbttaglist.size(); ++i) { ++ if (nbttaglist.size() == 0) continue; // Paper - remove duplicate properties ++ for (int i = nbttaglist.size() - 1; i < nbttaglist.size(); ++i) { // Paper - remove duplicate properties + CompoundTag nbttagcompound2 = nbttaglist.getCompound(i); + String s2 = nbttagcompound2.getString("Value"); + +@@ -246,7 +246,7 @@ public final class NbtUtils { + Optional optional = property.getValue(propertiesTag.getString(key)); + + if (optional.isPresent()) { +- return (StateHolder) state.setValue(property, (Comparable) optional.get()); ++ return state.setValue(property, optional.get()); // Paper - decompile error + } else { + NbtUtils.LOGGER.warn("Unable to read property: {} with value: {} for blockstate: {}", key, propertiesTag.getString(key), mainTag.toString()); + return state; +@@ -276,8 +276,8 @@ public final class NbtUtils { + return nbttagcompound; + } + +- private static > String getName(net.minecraft.world.level.block.state.properties.Property property, Comparable value) { +- return property.value(value); ++ private static > String getName(net.minecraft.world.level.block.state.properties.Property property, Comparable value) {// Paper - decompile error ++ return property.getName((T) value);// Paper - decompile error + } + + public static CompoundTag update(DataFixer fixer, DataFixTypes fixTypes, CompoundTag tag, int oldVersion) { +diff --git a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java +index 1cb67832a849db96f1cce95c32b41574e990e5b7..d97be7a1dfa7ad413afb8ff7668189fd37baf264 100644 +--- a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java ++++ b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java +@@ -59,6 +59,18 @@ public class PlayerHeadItem extends StandingAndWallBlockItem { + return true; + } else { + // CraftBukkit start ++ // Paper start - clean up old duplicated properties ++ CompoundTag properties = tag.getCompound("SkullOwner").getCompound("Properties"); ++ for (String key : properties.getAllKeys()) { ++ net.minecraft.nbt.ListTag values = properties.getList(key, 10); ++ if (values.size() > 1) { ++ net.minecraft.nbt.Tag texture = values.get(values.size() - 1); ++ values = new net.minecraft.nbt.ListTag(); ++ values.add(texture); ++ properties.put(key, values); ++ } ++ } ++ // Paper end + net.minecraft.nbt.ListTag textures = tag.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts + for (int i = 0; i < textures.size(); i++) { + if (textures.get(i) instanceof CompoundTag && !((CompoundTag) textures.get(i)).contains("Signature", 8) && ((CompoundTag) textures.get(i)).getString("Value").trim().isEmpty()) { diff --git a/Remapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch b/Remapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch new file mode 100644 index 0000000000..9306e47d2d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 1 Jul 2020 04:50:22 -0400 +Subject: [PATCH] Convert legacy attributes in Item Meta + + +diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +index 2d547810125f00680ef7e60dd791d0bddd9ebd3e..320fd6780af2fa99e4e4f4193cbc9338d492dc6d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java ++++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +@@ -11,6 +11,20 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; + public class CraftAttributeMap implements Attributable { + + private final AttributeMap handle; ++ // Paper start - convert legacy attributes ++ private static final com.google.common.collect.ImmutableMap legacyNMS = com.google.common.collect.ImmutableMap.builder().put("generic.maxHealth", "generic.max_health").put("Max Health", "generic.max_health").put("zombie.spawnReinforcements", "zombie.spawn_reinforcements").put("Spawn Reinforcements Chance", "zombie.spawn_reinforcements").put("horse.jumpStrength", "horse.jump_strength").put("Jump Strength", "horse.jump_strength").put("generic.followRange", "generic.follow_range").put("Follow Range", "generic.follow_range").put("generic.knockbackResistance", "generic.knockback_resistance").put("Knockback Resistance", "generic.knockback_resistance").put("generic.movementSpeed", "generic.movement_speed").put("Movement Speed", "generic.movement_speed").put("generic.flyingSpeed", "generic.flying_speed").put("Flying Speed", "generic.flying_speed").put("generic.attackDamage", "generic.attack_damage").put("generic.attackKnockback", "generic.attack_knockback").put("generic.attackSpeed", "generic.attack_speed").put("generic.armorToughness", "generic.armor_toughness").build(); ++ ++ public static String convertIfNeeded(String nms) { ++ if (nms == null) { ++ return null; ++ } ++ nms = legacyNMS.getOrDefault(nms, nms); ++ if (!nms.toLowerCase().equals(nms) || nms.indexOf(' ') != -1) { ++ return null; ++ } ++ return nms; ++ } ++ // Paper end + + public CraftAttributeMap(AttributeMap handle) { + this.handle = handle; +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 45abfebf3f947dcbd2e7b1d95be8ba918f044e51..cb66998dbaa9d93e92ef4045b83efbb0fd486234 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -480,7 +480,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + + AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); + +- String attributeName = entry.getString(ATTRIBUTES_IDENTIFIER.NBT); ++ String attributeName = CraftAttributeMap.convertIfNeeded(entry.getString(ATTRIBUTES_IDENTIFIER.NBT)); // Paper + if (attributeName == null || attributeName.isEmpty()) { + continue; + } diff --git a/Remapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch b/Remapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch new file mode 100644 index 0000000000..26f90fc29a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch @@ -0,0 +1,143 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Mon, 29 Jun 2020 17:03:06 -0400 +Subject: [PATCH] Remove some streams from structures + +This showed up a lot in the spark profiler, should have a low-medium performance improvement. + +diff --git a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java +index e842dbc586234799a05b6df213b686e17b8ed1ac..2f88e015708cadb43a348ba2b144c3dd92bb95a5 100644 +--- a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java ++++ b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java +@@ -2,21 +2,22 @@ + package net.minecraft.world.level; + + import com.mojang.datafixers.DataFixUtils; ++import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper + import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; +-import net.minecraft.core.Vec3i; + import net.minecraft.server.level.WorldGenRegion; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.FeatureAccess; + import net.minecraft.world.level.levelgen.WorldGenSettings; + import net.minecraft.world.level.levelgen.feature.StructureFeature; ++import net.minecraft.world.level.levelgen.structure.StructurePiece; + import net.minecraft.world.level.levelgen.structure.StructureStart; + + public class StructureFeatureManager { + +- private final LevelAccessor level; ++ private final LevelAccessor level; public LevelAccessor getLevel() { return level; } // Paper - OBFHELPER + private final WorldGenSettings worldGenSettings; + + public StructureFeatureManager(LevelAccessor world, WorldGenSettings options) { +@@ -42,6 +43,20 @@ public class StructureFeatureManager { + }); + } + ++ // Paper start - remove structure streams ++ public java.util.List> getFeatureStarts(SectionPos sectionPosition, StructureFeature structureGenerator) { ++ java.util.List> list = new ObjectArrayList<>(); ++ for (Long curLong: getLevel().getChunk(sectionPosition.x(), sectionPosition.z(), ChunkStatus.STRUCTURE_REFERENCES).getReferencesForFeature(structureGenerator)) { ++ SectionPos sectionPosition1 = SectionPos.of(new ChunkPos(curLong), 0); ++ StructureStart structurestart = getStartForFeature(sectionPosition1, structureGenerator, getLevel().getChunk(sectionPosition1.x(), sectionPosition1.z(), ChunkStatus.STRUCTURE_STARTS)); ++ if (structurestart != null && structurestart.e()) { ++ list.add(structurestart); ++ } ++ } ++ return list; ++ } ++ // Paper end ++ + @Nullable + public StructureStart getStartForFeature(SectionPos pos, StructureFeature feature, FeatureAccess holder) { + return holder.getStartForFeature(feature); +@@ -60,13 +75,21 @@ public class StructureFeatureManager { + } + + public StructureStart getStructureAt(BlockPos pos, boolean matchChildren, StructureFeature feature) { +- return (StructureStart) DataFixUtils.orElse(this.startsForFeature(SectionPos.of(pos), feature).filter((structurestart) -> { +- return structurestart.c().b((Vec3i) pos); +- }).filter((structurestart) -> { +- return !matchChildren || structurestart.d().stream().anyMatch((structurepiece) -> { +- return structurepiece.g().b((BaseBlockPosition) blockposition); +- }); +- }).findFirst(), StructureStart.a); ++ // Paper start - remove structure streams ++ for (StructureStart structurestart : getFeatureStarts(SectionPos.of(pos), feature)) { ++ if (structurestart.c().b(pos)) { ++ if (!matchChildren) { ++ return structurestart; ++ } ++ for (StructurePiece structurepiece : structurestart.d()) { ++ if (structurepiece.g().b(pos)) { ++ return structurestart; ++ } ++ } ++ } ++ } ++ return StructureStart.a; ++ // Paper end + } + + // Spigot start +diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java +index ed83335175bb882741dfaef251ab30ce1590f74c..2422dbb8691b8c45401a68602a33d4d7f1718dfb 100644 +--- a/src/main/java/net/minecraft/world/level/biome/Biome.java ++++ b/src/main/java/net/minecraft/world/level/biome/Biome.java +@@ -39,6 +39,7 @@ import net.minecraft.world.level.levelgen.WorldgenRandom; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.levelgen.feature.StructureFeature; + import net.minecraft.world.level.levelgen.structure.BoundingBox; ++import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder; + import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise; + import net.minecraft.world.level.material.FluidState; +@@ -238,9 +239,11 @@ public final class Biome { + int l1 = j1 << 4; + + try { +- structureAccessor.startsForFeature(SectionPos.of(pos), structuregenerator).forEach((structurestart) -> { +- structurestart.a(region, structureAccessor, chunkGenerator, random, new BoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkPos(i1, j1)); +- }); ++ // Paper start - remove structure streams ++ for (StructureStart structureStart : structureAccessor.getFeatureStarts(SectionPos.of(pos), structuregenerator)) { ++ structureStart.a(region, structureAccessor, chunkGenerator, random, new BoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkPos(i1, j1)); ++ } ++ // Paper end + } catch (Exception exception) { + CrashReport crashreport = CrashReport.forThrowable(exception, "Feature placement"); + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +index 04adec255e4650ead8d80bee32a681c98686fb95..20f3899b7e39033ebc0f833e75fbdba29777a168 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +@@ -41,6 +41,7 @@ import net.minecraft.world.level.levelgen.feature.structures.StructureTemplatePo + import net.minecraft.world.level.levelgen.structure.BoundingBox; + import net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece; + import net.minecraft.world.level.levelgen.structure.StructurePiece; ++import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.synth.ImprovedNoise; + import net.minecraft.world.level.levelgen.synth.PerlinNoise; + import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise; +@@ -455,7 +456,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + while (iterator.hasNext()) { + StructureFeature structuregenerator = (StructureFeature) iterator.next(); + +- accessor.startsForFeature(SectionPos.of(chunkcoordintpair, 0), structuregenerator).forEach((structurestart) -> { ++ for (StructureStart structurestart : accessor.getFeatureStarts(SectionPos.of(chunkcoordintpair, 0), structuregenerator)) { // Paper - remove structure streams + Iterator iterator1 = structurestart.d().iterator(); + + while (iterator1.hasNext()) { +@@ -487,7 +488,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + } + } + +- }); ++ } // Paper - remove structure streams + } + + double[][][] adouble = new double[2][this.chunkCountZ + 1][this.chunkCountY + 1]; diff --git a/Remapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch b/Remapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch new file mode 100644 index 0000000000..a3582192b3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 1 Jul 2020 18:01:49 -0400 +Subject: [PATCH] Remove streams from classes related villager gossip + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +index 0204f05d989d45c0848f810d1953adf0992ce3c2..57832c392910d22aa81ac2b4816d043dd7ac867a 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +@@ -9,6 +9,7 @@ import com.mojang.serialization.DynamicOps; + import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import java.util.Arrays; + import java.util.Collection; +@@ -51,8 +52,21 @@ public class GossipContainer { + }); + } + ++ // Paper start - Remove streams from reputation ++ private List decompress() { ++ List list = new ObjectArrayList<>(); ++ for (Map.Entry entry : getReputations().entrySet()) { ++ for (GossipContainer.GossipEntry cur : entry.getValue().decompress(entry.getKey())) { ++ if (cur.weightedValue() != 0) ++ list.add(cur); ++ } ++ } ++ return list; ++ } ++ // Paper end ++ + private Collection selectGossipsForTransfer(Random random, int count) { +- List list = (List) this.unpack().collect(Collectors.toList()); ++ List list = decompress(); // Paper - Remove streams from reputation + + if (list.isEmpty()) { + return Collections.emptyList(); +@@ -119,7 +133,7 @@ public class GossipContainer { + } + + public Dynamic store(DynamicOps dynamicops) { +- return new Dynamic(dynamicops, dynamicops.createList(this.unpack().map((reputation_b) -> { ++ return new Dynamic(dynamicops, dynamicops.createList(this.decompress().stream().map((reputation_b) -> { + return reputation_b.store(dynamicops); + }).map(Dynamic::getValue))); + } +@@ -144,18 +158,30 @@ public class GossipContainer { + + public static class EntityGossips { // Paper - make public + +- private final Object2IntMap entries; ++ private final Object2IntMap entries; private Object2IntMap getEntries() { return entries; } // Paper - OBFHELPER + + public EntityGossips() { // Paper - make public - update CraftVillager setReputation on change + this.entries = new Object2IntOpenHashMap(); + } + + public int weightedValue(Predicate gossipTypeFilter) { +- return this.entries.object2IntEntrySet().stream().filter((entry) -> { +- return gossipTypeFilter.test(entry.getKey()); +- }).mapToInt((entry) -> { +- return entry.getIntValue() * ((GossipType) entry.getKey()).weight; +- }).sum(); ++ // Paper start - Remove streams from reputation ++ int weight = 0; ++ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { ++ if (gossipTypeFilter.test(entry.getKey())) { ++ weight += entry.getIntValue() * entry.getKey().getWeight(); ++ } ++ } ++ return weight; ++ } ++ ++ public List decompress(UUID uuid) { ++ List list = new ObjectArrayList<>(); ++ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { ++ list.add(new GossipContainer.GossipEntry(uuid, entry.getKey(), entry.getIntValue())); ++ } ++ return list; ++ // Paper - end + } + + public Stream unpack(UUID target) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java +index 808eaaae5d534427d197c90c8e53494f4c3bfd82..c775d0df2a8f8a0fd32a8ffc26d6ea6978cbb595 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java +@@ -11,7 +11,7 @@ public enum GossipType { + MAJOR_NEGATIVE("major_negative", -5, 100, 10, 10), MINOR_NEGATIVE("minor_negative", -1, 200, 20, 20), MINOR_POSITIVE("minor_positive", 1, 200, 1, 5), MAJOR_POSITIVE("major_positive", 5, 100, 0, 100), TRADING("trading", 1, 25, 2, 20); + + public final String id; +- public final int weight; ++ public final int weight; public int getWeight() { return weight; } // Paper - OBFHELPER + public final int max; + public final int decayPerDay; + public final int decayPerTransfer; diff --git a/Remapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch b/Remapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch new file mode 100644 index 0000000000..66bda208cc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Sat, 6 Jun 2020 18:13:42 +0200 +Subject: [PATCH] Support components in ItemMeta + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index cb66998dbaa9d93e92ef4045b83efbb0fd486234..20e008277d1188fc7b31bfb2522ef9f6429cc3fb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -874,11 +874,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return CraftChatMessage.fromJSONComponent(displayName); + } + ++ // 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(displayName); ++ } ++ // Paper end + @Override + public final void setDisplayName(String name) { + this.displayName = CraftChatMessage.fromStringOrNullToJSON(name); + } + ++ // Paper start ++ @Override ++ public void setDisplayNameComponent(net.md_5.bungee.api.chat.BaseComponent[] component) { ++ this.displayName = net.md_5.bungee.chat.ComponentSerializer.toString(component); ++ } ++ // Paper end + @Override + public boolean hasDisplayName() { + return displayName != null; +@@ -1021,6 +1033,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return this.lore == null ? null : new ArrayList(Lists.transform(this.lore, CraftChatMessage::fromJSONComponent)); + } + ++ // 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(entry) ++ ).collect(java.util.stream.Collectors.toList())); ++ } ++ // Paper end + @Override + public void setLore(List lore) { + if (lore == null || lore.isEmpty()) { +@@ -1035,6 +1055,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + } + ++ // 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 customModelData != null; +@@ -1496,6 +1531,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + + for (Object object : addFrom) { ++ // Paper start - support components ++ if(object instanceof net.md_5.bungee.api.chat.BaseComponent[]) { ++ addTo.add(net.md_5.bungee.chat.ComponentSerializer.toString((net.md_5.bungee.api.chat.BaseComponent[]) object)); ++ } else ++ // Paper end + if (!(object instanceof String)) { + if (object != null) { + throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName()); diff --git a/Remapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/Remapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch new file mode 100644 index 0000000000..52cd27053f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 3 Jul 2020 15:03:33 -0700 +Subject: [PATCH] Improve EntityTargetLivingEntityEvent for 1.16 mobs + +CraftBukkit has a bug in their implementation and is incorrectly handling forget +Also adds more target reasons for why it forgot target. + +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 738162a55eb186f66df4d31e017c9b9a7cc604c2..1b6f34c2a185368aac973e8a5316a03950e4314b 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 +@@ -33,15 +33,15 @@ public class StopAttackingIfTargetInvalid extends Behavior { + + protected void start(ServerLevel world, E entity, long time) { + if (isTiredOfTryingToReachTarget((LivingEntity) entity)) { +- this.clearAttackTarget(entity); ++ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // Paper + } else if (this.isCurrentTargetDeadOrRemoved(entity)) { +- this.clearAttackTarget(entity); ++ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_DIED); // Paper + } else if (this.isCurrentTargetInDifferentLevel(entity)) { +- this.clearAttackTarget(entity); ++ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_OTHER_LEVEL); // Paper + } else if (!EntitySelector.ATTACK_ALLOWED.test(this.getAttackTarget(entity))) { +- this.clearAttackTarget(entity); ++ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper + } else if (this.stopAttackingWhen.test(this.getAttackTarget(entity))) { +- this.clearAttackTarget(entity); ++ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper + } + } + +@@ -65,18 +65,21 @@ public class StopAttackingIfTargetInvalid extends Behavior { + return optional.isPresent() && !((LivingEntity) optional.get()).isAlive(); + } + +- private void clearAttackTarget(E entity) { ++ private void d(E e0, EntityTargetEvent.TargetReason reason) { + // CraftBukkit start +- LivingEntity old = entity.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); +- EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ // Paper start - fix this event ++ //EntityLiving old = e0.getBehaviorController().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(e0, null, reason); + if (event.isCancelled()) { + return; + } +- if (event.getTarget() != null) { +- entity.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); ++ // comment out, bad logic - bad ++ /*if (event.getTarget() != null) { ++ e0.getBehaviorController().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); + return; +- } ++ }*/ ++ // Paper end + // CraftBukkit end +- entity.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); ++ e0.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); + } + } diff --git a/Remapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch b/Remapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch new file mode 100644 index 0000000000..87da8f1dcb --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 2 Jul 2020 18:11:43 -0500 +Subject: [PATCH] Add entity liquid API + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index e9a658b11e2b6683831dc3f5bd20be9a7840ed69..aea2457510c75214bbb925307155611e981f115f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1164,12 +1164,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.wasTouchingWater; + } + +- private boolean isInRain() { ++ public boolean isInRain() { // Paper - private -> public + BlockPos blockposition = this.blockPosition(); + + return this.level.isRainingAt(blockposition) || this.level.isRainingAt(new BlockPos((double) blockposition.getX(), this.getBoundingBox().maxY, (double) blockposition.getZ())); + } + ++ public final boolean isInBubbleColumn() { return isInBubbleColumn(); } // Paper - OBFHELPER + private boolean isInBubbleColumn() { + return this.level.getBlockState(this.blockPosition()).is(Blocks.BUBBLE_COLUMN); + } +@@ -1183,6 +1184,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.isInWater() || this.isInRain() || this.isInBubbleColumn(); + } + ++ public final boolean isInWaterOrBubbleColumn() { return isInWaterOrBubble(); } // Paper - OBFHELPER + public boolean isInWaterOrBubble() { + return this.isInWater() || this.isInBubbleColumn(); + } +@@ -1325,6 +1327,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.fluidOnEyes == tag; + } + ++ public final boolean isInLava() { return isInLava(); } // Paper - OBFHELPER + public boolean isInLava() { + return !this.firstTick && this.fluidHeight.getDouble(FluidTags.LAVA) > 0.0D; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 76d652386806fd11961611486a1d0a12fe9616a4..deeae62e9926f9435907c68e7d35e7420f5e79dd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1135,5 +1135,29 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { + return getHandle().spawnReason; + } ++ ++ public boolean isInRain() { ++ return getHandle().isInRain(); ++ } ++ ++ public boolean isInBubbleColumn() { ++ return getHandle().isInBubbleColumn(); ++ } ++ ++ public boolean isInWaterOrRain() { ++ return getHandle().isInWaterOrRain(); ++ } ++ ++ public boolean isInWaterOrBubbleColumn() { ++ return getHandle().isInWaterOrBubbleColumn(); ++ } ++ ++ public boolean isInWaterOrRainOrBubbleColumn() { ++ return getHandle().isInWaterOrRainOrBubble(); ++ } ++ ++ public boolean isInLava() { ++ return getHandle().isInLava(); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch b/Remapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch new file mode 100644 index 0000000000..1b999bcc30 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 1 Jul 2020 11:57:40 -0500 +Subject: [PATCH] Update itemstack legacy name and lore + + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 458cdfbeac9d757c9721acd4557a548affa0ede1..04b717326524f400da3562655c25db59e72814ec 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -49,6 +49,7 @@ import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.StringTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.ComponentUtils; +@@ -135,6 +136,44 @@ public final class ItemStack { + list.sort((Comparator) enchantSorter); // Paper + } catch (Exception ignored) {} + } ++ ++ private void processText() { ++ CompoundTag display = getSubTag("display"); ++ if (display != null) { ++ if (display.contains("Name", 8)) { ++ String json = display.getString("Name"); ++ if (json != null && json.contains("\u00A7")) { ++ try { ++ display.put("Name", convert(json)); ++ } catch (JsonParseException jsonparseexception) { ++ display.remove("Name"); ++ } ++ } ++ } ++ if (display.contains("Lore", 9)) { ++ ListTag list = display.getList("Lore", 8); ++ for (int index = 0; index < list.size(); index++) { ++ String json = list.getString(index); ++ if (json != null && json.contains("\u00A7")) { // Only try if it has legacy in the unparsed json ++ try { ++ list.set(index, convert(json)); ++ } catch (JsonParseException e) { ++ list.set(index, StringTag.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(new TextComponent("")))); ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ private StringTag convert(String json) { ++ Component component = Component.Serializer.jsonToComponent(json); ++ if (component instanceof TextComponent && component.getContents().contains("\u00A7") && component.getSiblings().isEmpty()) { ++ // Only convert if the root component is a single comp with legacy in it, don't convert already normal components ++ component = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(component.getContents())[0]; ++ } ++ return StringTag.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(component)); ++ } + // Paper end + + public ItemStack(ItemLike item) { +@@ -180,6 +219,7 @@ public final class ItemStack { + // CraftBukkit start - make defensive copy as this data may be coming from the save thread + this.tag = (CompoundTag) nbttagcompound.getCompound("tag").copy(); + processEnchantOrder(this.tag); // Paper ++ processText(); // Paper + this.getItem().verifyTagAfterLoad(this.tag); + // CraftBukkit end + } +@@ -663,6 +703,7 @@ public final class ItemStack { + } + } + ++ @Nullable public CompoundTag getSubTag(String s) { return getTagElement(s); } // Paper - OBFHELPER + @Nullable + public CompoundTag getTagElement(String key) { + return this.tag != null && this.tag.contains(key, 10) ? this.tag.getCompound(key) : null; diff --git a/Remapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch b/Remapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch new file mode 100644 index 0000000000..5ec61b9dae --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Wyatt Childers +Date: Fri, 3 Jul 2020 14:57:05 -0400 +Subject: [PATCH] Spawn player in correct world on login + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 713cc88dd067c0d918f253b1845f42c0d9eb920f..f36c92e42300c2056075610caf63f8bef0e7edda 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -192,7 +192,18 @@ public abstract class PlayerList { + }String lastKnownName = s; // Paper + // CraftBukkit end + +- if (nbttagcompound != null) { ++ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID. ++ if (nbttagcompound != null && nbttagcompound.contains("WorldUUIDMost") && nbttagcompound.contains("WorldUUIDLeast")) { ++ UUID uid = new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast")); ++ org.bukkit.World bWorld = org.bukkit.Bukkit.getServer().getWorld(uid); ++ if (bWorld != null) { ++ resourcekey = ((CraftWorld) bWorld).getHandle().dimension(); ++ } else { ++ resourcekey = Level.OVERWORLD; ++ } ++ } else if (nbttagcompound != null) { ++ // Vanilla migration support ++ // Paper end + DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension"))); + Logger logger = PlayerList.LOGGER; + diff --git a/Remapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch b/Remapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch new file mode 100644 index 0000000000..be0c76ca05 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch @@ -0,0 +1,164 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 3 Jul 2020 11:58:56 -0500 +Subject: [PATCH] Add PrepareResultEvent + +Adds a new event for all crafting stations that generate a result slot item + +Anvil, Grindstone and Smithing now extend this event + +diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index 72b0cfcc5aab03e14e63440c734436e9c1432111..bc39e7464646d712b085251dc0277a5b1ec0a393 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -141,6 +141,7 @@ public abstract class AbstractContainerMenu { + return nonnulllist; + } + ++ public final void notifyListeners() { this.broadcastChanges(); } // Paper - OBFHELPER + public void broadcastChanges() { + int i; + +diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +index 3d53edae7e3d5bb00913384ad0eb67551a65750e..492a42ad5dc460717de8179d522d042cee11db60 100644 +--- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +@@ -307,6 +307,7 @@ public class AnvilMenu extends ItemCombinerMenu { + } + + this.createResult(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java +index 6183e33237a231be388a8ace0ca3b56720db13ee..464f27d3f0cc694257a550cf873a0ee4534e2189 100644 +--- a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java +@@ -146,6 +146,7 @@ public class CartographyTableMenu extends AbstractContainerMenu { + this.setupResultSlot(itemstack, itemstack1, itemstack2); + } + ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + private void setupResultSlot(ItemStack map, ItemStack item, ItemStack oldResult) { +diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +index e9e830117fe3e4e02a51eef8671a3d3b48c2858e..329a6d70d53c13cd554c64996f2ddc489bdc1e94 100644 +--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -156,6 +156,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { + super.slotsChanged(inventory); + if (inventory == this.repairSlots) { + this.createResult(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java +index d944cbcdf4d886d3b8b171edd8e2ac8a54dc19b9..8704c4dbead1ff661d84b751479babac5ebc5839 100644 +--- a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java +@@ -71,6 +71,7 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu { + super.slotsChanged(inventory); + if (inventory == this.inputSlots) { + this.createResult(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +index b33daf92752841e46f2fd9fa20dc1cfa79aa423a..3460fb2bb1451b8456a7fe42449ec4dbce641f40 100644 +--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +@@ -188,7 +188,8 @@ public class LoomMenu extends AbstractContainerMenu { + } + + this.setupResultSlot(); +- this.broadcastChanges(); ++ //this.c(); // Paper - done below ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 3); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/inventory/SmithingMenu.java b/src/main/java/net/minecraft/world/inventory/SmithingMenu.java +index befb2e6294c3d0a16ae4766c3804d04fd4e1bba5..44aa1f4f91ae9f84fc7ed38cc6b3c11f07d55ba1 100644 +--- a/src/main/java/net/minecraft/world/inventory/SmithingMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/SmithingMenu.java +@@ -78,6 +78,7 @@ public class SmithingMenu extends ItemCombinerMenu { + // CraftBukkit end + } + ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +index febf7fa112c470888af171e585ab6a052abb46ca..072bac443e7c54ac2b92e1d93b757bdacf230fbb 100644 +--- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +@@ -155,6 +155,7 @@ public class StonecutterMenu extends AbstractContainerMenu { + this.setupRecipeList(inventory, itemstack); + } + ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 1); // Paper + } + + private void setupRecipeList(Container input, ItemStack stack) { +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 87fe7f4f5ed70bf1b3dc1e2a392ba42a1f8f568b..64cfa14aa4e32430a6970fd4f3654a56146ba807 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1522,19 +1522,44 @@ public class CraftEventFactory { + return event; + } + +- public static PrepareAnvilEvent callPrepareAnvilEvent(InventoryView view, ItemStack item) { +- PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item).clone()); +- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); ++ // Paper start - disable this method, handled below ++ public static void callPrepareAnvilEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult ++ PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone ++ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // disable event + event.getInventory().setItem(2, event.getResult()); +- return event; ++ //return event; // Paper + } ++ // Paper end + +- public static PrepareSmithingEvent callPrepareSmithingEvent(InventoryView view, ItemStack item) { +- PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item).clone()); +- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); ++ // Paper start - disable this method, handled in callPrepareResultEvent ++ public static void callPrepareSmithingEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult ++ PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone ++ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // Paper - disable event + event.getInventory().setItem(2, event.getResult()); +- return event; ++ //return event; // Paper + } ++ // Paper end ++ ++ // Paper start - support specific overrides for prepare result ++ public static void callPrepareResultEvent(AbstractContainerMenu container, int resultSlot) { ++ com.destroystokyo.paper.event.inventory.PrepareResultEvent event; ++ InventoryView view = container.getBukkitView(); ++ org.bukkit.inventory.ItemStack origItem = view.getTopInventory().getItem(resultSlot); ++ CraftItemStack result = origItem != null ? CraftItemStack.asCraftCopy(origItem) : null; ++ if (view.getTopInventory() instanceof org.bukkit.inventory.AnvilInventory) { ++ event = new PrepareAnvilEvent(view, result); ++ } else if (view.getTopInventory() instanceof org.bukkit.inventory.GrindstoneInventory) { ++ event = new com.destroystokyo.paper.event.inventory.PrepareGrindstoneEvent(view, result); ++ } else if (view.getTopInventory() instanceof org.bukkit.inventory.SmithingInventory) { ++ event = new PrepareSmithingEvent(view, result); ++ } else { ++ event = new com.destroystokyo.paper.event.inventory.PrepareResultEvent(view, result); ++ } ++ event.callEvent(); ++ event.getInventory().setItem(resultSlot, event.getResult()); ++ container.notifyListeners(); ++ } ++ // Paper end + + /** + * Mob spawner event. diff --git a/Remapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch b/Remapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch new file mode 100644 index 0000000000..183e23a96c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch @@ -0,0 +1,104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Wed, 29 Apr 2020 02:10:32 +0200 +Subject: [PATCH] Allow delegation to vanilla chunk gen + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java +index aaa8d78b131c4095b36c6db6078f57f927c15374..54e560348836498f16dde017c6e7e3fcc263eeea 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java ++++ b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java +@@ -36,7 +36,7 @@ import org.apache.logging.log4j.Logger; + public class UpgradeData { + + private static final Logger LOGGER = LogManager.getLogger(); +- public static final UpgradeData EMPTY = new UpgradeData(); ++ public static final UpgradeData EMPTY = new UpgradeData(); public static UpgradeData getEmptyConverter() { return EMPTY; } // Paper - obfhelper + private static final Direction8[] DIRECTIONS = Direction8.values(); + private final EnumSet sides; + private final int[][] index; +@@ -322,7 +322,7 @@ public class UpgradeData { + if ((Integer) iblockdata.getValue(BlockStateProperties.DISTANCE) >= j) { + world.setBlock(blockposition, (BlockState) iblockdata.setValue(BlockStateProperties.DISTANCE, j), 18); + if (i != 7) { +- Direction[] aenumdirection = null.f; ++ Direction[] aenumdirection = DIRECTIONS; // Paper - decomp fix + int k = aenumdirection.length; + + for (int l = 0; l < k; ++l) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 2ec41cb87cec97780f1fa8abfbb756fca4dba1bf..e301aee53b19fc3f93a36d0ed03a649741123bfa 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2032,6 +2032,32 @@ public final class CraftServer implements Server { + return new CraftChunkData(world); + } + ++ // Paper start ++ @Override ++ public ChunkGenerator.ChunkData createVanillaChunkData(World world, int x, int z) { ++ // get empty object ++ CraftChunkData data = (CraftChunkData) createChunkData(world); ++ // do bunch of vanilla shit ++ net.minecraft.server.level.ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); ++ net.minecraft.world.level.chunk.ProtoChunk protoChunk = new net.minecraft.world.level.chunk.ProtoChunk(new net.minecraft.world.level.ChunkPos(x, z), net.minecraft.world.level.chunk.UpgradeData.getEmptyConverter(), nmsWorld); ++ List list = new ArrayList<>(); ++ list.add(protoChunk); ++ net.minecraft.server.level.WorldGenRegion genRegion = new net.minecraft.server.level.WorldGenRegion(nmsWorld, list); ++ // call vanilla generator, one feature after another. Order here is important! ++ net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator = nmsWorld.getChunkSource().generator; ++ if (chunkGenerator instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator) { ++ chunkGenerator = ((org.bukkit.craftbukkit.generator.CustomChunkGenerator) chunkGenerator).delegate; ++ } ++ chunkGenerator.createBiomes(nmsWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), protoChunk); ++ chunkGenerator.fillFromNoise(genRegion, nmsWorld.structureFeatureManager(), protoChunk); ++ chunkGenerator.buildSurfaceAndBedrock(genRegion, protoChunk); ++ // copy over generated sections ++ data.setRawChunkData(protoChunk.getSections()); ++ // hooray! ++ return data; ++ } ++ // Paper end ++ + @Override + public BossBar createBossBar(String title, BarColor color, BarStyle style, BarFlag... flags) { + return new CraftBossBar(title, color, style, flags); +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +index 8d72cd6a44cf462cfe3adac9bf99a16883a587df..fd2cb2a584fea360fcf8180338708f35c4e3dc1f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +@@ -19,7 +19,7 @@ import org.bukkit.material.MaterialData; + */ + public final class CraftChunkData implements ChunkGenerator.ChunkData { + private final int maxHeight; +- private final LevelChunkSection[] sections; ++ private LevelChunkSection[] sections; // Paper - remove final + private Set tiles; + private World world; // Paper - Anti-Xray - Add world + +@@ -168,6 +168,12 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + return sections; + } + ++ // Paper start ++ public void setRawChunkData(LevelChunkSection[] sections) { ++ this.sections = sections; ++ } ++ // Paper end ++ + Set getTiles() { + return tiles; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java +index eba3a6a2467116d93945ab2d5dc0a6f41d76f547..e25dc1c87752fcf73181cb02ddaf84b258ac4e9d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java +@@ -32,7 +32,7 @@ import org.bukkit.generator.ChunkGenerator.ChunkData; + + public class CustomChunkGenerator extends InternalChunkGenerator { + +- private final net.minecraft.world.level.chunk.ChunkGenerator delegate; ++ public final net.minecraft.world.level.chunk.ChunkGenerator delegate; // Paper - public + private final ChunkGenerator generator; + private final ServerLevel world; + private final Random random = new Random(); diff --git a/Remapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/Remapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch new file mode 100644 index 0000000000..253148a7ee --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 5 Jul 2020 14:59:31 -0400 +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 cec1e6105b8c2ac3d1482c00482d53d6be0d38d1..9724d4222311345a44aa101ec47523a1909fbe8f 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3038,7 +3038,7 @@ public abstract class LivingEntity extends Entity { + Entity entity = this.getVehicle(); + + super.stopRiding(suppressCancellation); // Paper - suppress +- if (entity != null && entity != this.getVehicle() && !this.level.isClientSide) { ++ if (entity != null && entity != this.getVehicle() && !this.level.isClientSide && entity.valid) { // Paper - don't process on world gen + this.dismountVehicle(entity); + } + diff --git a/Remapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch b/Remapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch new file mode 100644 index 0000000000..dc51ae715d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Sun, 5 Jul 2020 22:38:18 -0400 +Subject: [PATCH] Optimize NetworkManager Exception Handling + + +diff --git a/src/main/java/net/minecraft/network/ConnectionProtocol.java b/src/main/java/net/minecraft/network/ConnectionProtocol.java +index fca778d131aa10e88d5f7ed8d57eda6803318184..47a5ee9db64184f173af5984765e9b6d1a8ec367 100644 +--- a/src/main/java/net/minecraft/network/ConnectionProtocol.java ++++ b/src/main/java/net/minecraft/network/ConnectionProtocol.java +@@ -151,6 +151,7 @@ public enum ConnectionProtocol { + + @Nullable + public Packet createPacket(int id) { ++ if (id < 0 || id >= this.idToConstructor.size()) return null; // Paper + Supplier> supplier = (Supplier) this.idToConstructor.get(id); + + return supplier != null ? (Packet) supplier.get() : null; +diff --git a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java +index 8363b63f8dbd16948eeba3f912dc43605ad8db6a..fbebef6525a0872fecc081c7f63f27c1a04e11dc 100644 +--- a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java ++++ b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java +@@ -9,11 +9,21 @@ import java.util.List; + + public class Varint21FrameDecoder extends ByteToMessageDecoder { + ++ private final byte[] lenBuf = new byte[3]; // Paper + public Varint21FrameDecoder() {} + + protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { ++ // Paper start - if channel is not active just discard the packet ++ if (!channelhandlercontext.channel().isActive()) { ++ bytebuf.skipBytes(bytebuf.readableBytes()); ++ return; ++ } ++ // Paper end + bytebuf.markReaderIndex(); +- byte[] abyte = new byte[3]; ++ // Paper start - reuse temporary length buffer ++ byte[] abyte = lenBuf; ++ java.util.Arrays.fill(abyte, (byte) 0); ++ // Paper end + + for (int i = 0; i < abyte.length; ++i) { + if (!bytebuf.isReadable()) { +diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java +index 22db5d0d2cc33498ca40162c66aa3b5fbf2f569f..3163502cb9bbbb5a00e7f06cf0032b1ad93c354d 100644 +--- a/src/main/java/net/minecraft/network/protocol/Packet.java ++++ b/src/main/java/net/minecraft/network/protocol/Packet.java +@@ -2,8 +2,10 @@ package net.minecraft.network.protocol; + + import io.netty.channel.ChannelFuture; // Paper + import java.io.IOException; ++import net.minecraft.network.Connection; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.PacketListener; ++import net.minecraft.server.level.ServerPlayer; + + public interface Packet { + +@@ -18,17 +20,17 @@ public interface Packet { + /** + * @param player Null if not at PLAY stage yet + */ +- default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} ++ default void onPacketDispatch(@javax.annotation.Nullable ServerPlayer player) {} + + /** + * @param player Null if not at PLAY stage yet + * @param future Can be null if packet was cancelled + */ +- default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} ++ default void onPacketDispatchFinish(@javax.annotation.Nullable ServerPlayer player, @javax.annotation.Nullable ChannelFuture future) {} + default boolean hasFinishListener() { return false; } + default boolean isReady() { return true; } + default java.util.List getExtraPackets() { return null; } +- default boolean packetTooLarge(NetworkManager manager) { ++ default boolean packetTooLarge(Connection manager) { + return false; + } + // Paper end +diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java +index 4ae8201d7dcffeb3298a4e593f978e15ffc5ac15..5812e518222e419da141ab0f70d1e7a3939a0df0 100644 +--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java ++++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java +@@ -1,6 +1,9 @@ + package net.minecraft.network.protocol; + ++import net.minecraft.network.Connection; + import net.minecraft.network.PacketListener; ++import net.minecraft.network.chat.TextComponent; ++import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import co.aikar.timings.MinecraftTimings; // Paper +@@ -30,6 +33,21 @@ public class PacketUtils { + try (Timing ignored = timing.startTiming()) { // Paper - timings + packet.handle(listener); + } // Paper - timings ++ // Paper start ++ catch (Exception e) { ++ Connection networkmanager = listener.a(); ++ if (networkmanager.getPlayer() != null) { ++ LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), networkmanager.getRemoteAddress(), e); ++ } else { ++ LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getRemoteAddress(), e); ++ } ++ TextComponent error = new TextComponent("Packet processing error"); ++ networkmanager.send(new ClientboundDisconnectPacket(error), (future) -> { ++ networkmanager.disconnect(error); ++ }); ++ networkmanager.setReadOnly(); ++ } ++ // Paper end + } else { + PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); + } diff --git a/Remapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch b/Remapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch new file mode 100644 index 0000000000..7c0af04ac0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch @@ -0,0 +1,153 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 6 Jul 2020 18:36:41 -0400 +Subject: [PATCH] Fix Concurrency issue in WeightedList + +if multiple threads from worldgen sort at same time, it will crash. +So make a copy of the list for sorting purposes. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java +index 0a65e442ddc31c06f3bb0ff5aa152daee7a210af..a81ad258b39b7472312ab1bedeeacaf26ffae4f7 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java +@@ -17,7 +17,7 @@ public class GateBehavior extends Behavior { + private final Set> exitErasedMemories; + private final GateBehavior.OrderPolicy orderPolicy; + private final GateBehavior.RunningPolicy runningPolicy; +- private final WeightedList> behaviors = new WeightedList<>(); ++ private final WeightedList> behaviors = new WeightedList<>(false); // Paper - don't use a clone + + public GateBehavior(Map, MemoryStatus> requiredMemoryState, Set> memoriesToForgetWhenStopped, GateBehavior.OrderPolicy order, GateBehavior.RunningPolicy runMode, List, Integer>> tasks) { + super(requiredMemoryState); +@@ -65,10 +65,9 @@ public class GateBehavior extends Behavior { + }).forEach((behavior) -> { + behavior.g(world, entity, time); + }); +- Set set = this.exitErasedMemories; + Brain behaviorcontroller = entity.getBrain(); + +- set.forEach(behaviorcontroller::removeMemory); ++ this.exitErasedMemories.forEach(behaviorcontroller::eraseMemory); // Paper - decomp fix + } + + @Override +@@ -111,11 +110,11 @@ public class GateBehavior extends Behavior { + static enum OrderPolicy { + + ORDERED((weightedlist) -> { +- }), SHUFFLED(WeightedList::a); ++ }), SHUFFLED(WeightedList::shuffle); + + private final Consumer> consumer; + +- private OrderPolicy(Consumer consumer) { ++ private OrderPolicy(Consumer> consumer) { // Paper - decomp fix + this.consumer = consumer; + } + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java +index e4c1c58e9a9c744c7ebb9948a27766b84a081b9e..85df30ef7c03c2f8ae741a8cac8bf601490d2539 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java +@@ -6,7 +6,7 @@ import com.mojang.serialization.Codec; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import com.mojang.serialization.DynamicOps; +-import com.mojang.serialization.OptionalDynamic; ++ + import java.util.Comparator; + import java.util.List; + import java.util.Random; +@@ -14,26 +14,32 @@ import java.util.stream.Stream; + + public class WeightedList { + +- protected final List> entries; ++ protected final List> list; // Paper - decompile conflict + private final Random random; ++ private final boolean isUnsafe; // Paper + +- public WeightedList() { +- this(Lists.newArrayList()); ++ // Paper start - add useClone option ++ public WeightedList() { this(true); } ++ public WeightedList(boolean isUnsafe) { ++ this(Lists.newArrayList(), isUnsafe); + } + +- private WeightedList(List> entries) { ++ private WeightedList(List> entries) { this(entries, true); } ++ private WeightedList(List> list, boolean isUnsafe) { ++ this.isUnsafe = isUnsafe; ++ // Paper end + this.random = new Random(); +- this.entries = Lists.newArrayList(entries); ++ this.list = Lists.newArrayList(list); // Paper - decompile conflict + } + + public static Codec> codec(Codec codec) { +- return WeightedList.entries.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { +- return weightedlist.a; ++ return WeightedList.WeightedEntry.codec(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { // Paper - decompile conflict ++ return weightedlist.list; // Paper - decompile conflict + }); + } + + public WeightedList add(U item, int weight) { +- this.entries.add(new WeightedList.WeightedEntry<>(item, weight)); ++ this.list.add(new WeightedList.WeightedEntry<>(item, weight)); // Paper - decompile conflict + return this; + } + +@@ -42,21 +48,20 @@ public class WeightedList { + } + + public WeightedList shuffle(Random random) { +- this.entries.forEach((weightedlist_a) -> { +- weightedlist_a.setRandom(random.nextFloat()); +- }); +- this.entries.sort(Comparator.comparingDouble((object) -> { +- return ((WeightedList.WeightedEntry) object).getRandWeight(); +- })); +- return this; ++ // Paper start - make concurrent safe, work off a clone of the list ++ List> list = isUnsafe ? new java.util.ArrayList>(this.list) : this.list; ++ list.forEach((weightedlist_a) -> weightedlist_a.setRandom(random.nextFloat())); ++ list.sort(Comparator.comparingDouble(WeightedEntry::getRandWeight)); ++ return isUnsafe ? new WeightedList<>(list, isUnsafe) : this; ++ // Paper end + } + + public boolean isEmpty() { +- return this.entries.isEmpty(); ++ return this.list.isEmpty(); // Paper - decompile conflict + } + + public Stream stream() { +- return this.entries.stream().map(WeightedList.entries::a); ++ return this.list.stream().map(WeightedList.WeightedEntry::getData); // Paper - decompile conflict + } + + public U getOne(Random random) { +@@ -64,7 +69,7 @@ public class WeightedList { + } + + public String toString() { +- return "WeightedList[" + this.entries + "]"; ++ return "WeightedList[" + this.list + "]"; // Paper - decompile conflict + } + + public static class WeightedEntry { +@@ -98,11 +103,7 @@ public class WeightedList { + return new Codec>() { + public DataResult, T>> decode(DynamicOps dynamicops, T t0) { + Dynamic dynamic = new Dynamic(dynamicops, t0); +- OptionalDynamic optionaldynamic = dynamic.get("data"); +- Codec codec1 = codec; +- +- codec.getClass(); +- return optionaldynamic.flatMap(codec1::parse).map((object) -> { ++ return dynamic.get("data").flatMap(codec::parse).map((object) -> { // Paper - decompile error + return new WeightedList.WeightedEntry<>(object, dynamic.get("weight").asInt(1)); + }).map((weightedlist_a) -> { + return Pair.of(weightedlist_a, dynamicops.empty()); diff --git a/Remapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch b/Remapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch new file mode 100644 index 0000000000..a23f3a28c9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Wyatt Childers +Date: Sat, 4 Jul 2020 23:07:43 -0400 +Subject: [PATCH] Optimize the advancement data player iteration to be O(N) + rather than O(N^2) + + +diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index 5ab62fc74085bbbb0c81b2f4d16a35c9345cd1f1..af8553f1b22e24fbeb732937fbbffc95cb9dfe90 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -457,6 +457,16 @@ public class PlayerAdvancements { + } + + private void ensureVisibility(Advancement advancement) { ++ // Paper start ++ e(advancement, IterationEntryPoint.ROOT); ++ } ++ private enum IterationEntryPoint { ++ ROOT, ++ ITERATOR, ++ PARENT_OF_ITERATOR ++ } ++ private void e(Advancement advancement, IterationEntryPoint entryPoint) { ++ // Paper end + boolean flag = this.shouldBeVisible(advancement); + boolean flag1 = this.visible.contains(advancement); + +@@ -472,15 +482,23 @@ public class PlayerAdvancements { + } + + if (flag != flag1 && advancement.getParent() != null) { +- this.ensureVisibility(advancement.getParent()); ++ // Paper start - If we're not coming from an iterator consider this to be a root entry, otherwise ++ // market that we're entering from the parent of an iterator. ++ this.e(advancement.getParent(), entryPoint == IterationEntryPoint.ITERATOR ? IterationEntryPoint.PARENT_OF_ITERATOR : IterationEntryPoint.ROOT); + } + ++ // If this is true, we've went through a child iteration, entered the parent, processed the parent ++ // and are about to reprocess the children. Stop processing here to prevent O(N^2) processing. ++ if (entryPoint == IterationEntryPoint.PARENT_OF_ITERATOR) { ++ return; ++ } // Paper end ++ + Iterator iterator = advancement.getChildren().iterator(); + + while (iterator.hasNext()) { + Advancement advancement1 = (Advancement) iterator.next(); + +- this.ensureVisibility(advancement1); ++ this.e(advancement1, IterationEntryPoint.ITERATOR); // Paper - Mark this call as being from iteration + } + + } diff --git a/Remapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch b/Remapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch new file mode 100644 index 0000000000..677615b010 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 8 Jul 2020 11:24:30 -0500 +Subject: [PATCH] Fix arrows never despawning MC-125757 + +This forces the despawn counter to start ticking regardless of +state after the arrow has been alive for 200 ticks (10 seconds) +instead of getting stuck in a never despawn state (bubble columns, +etc). + +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 6225f390b51733217a809910182f58acea1055e2..73df844610530bbfb133bd59d00015117b59b215 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -169,6 +169,7 @@ public abstract class AbstractArrow extends Projectile { + + ++this.inGroundTime; + } else { ++ if (tickCount > 200) this.tickDespawnCounter(); // Paper - tick despawnCounter regardless after 10 seconds + this.inGroundTime = 0; + Vec3 vec3d2 = this.position(); + +@@ -290,6 +291,7 @@ public abstract class AbstractArrow extends Projectile { + + } + ++ protected final void tickDespawnCounter() { this.tickDespawn(); } // Paper - OBFHELPER + protected void tickDespawn() { + ++this.life; + if (this.life >= (pickup == Pickup.CREATIVE_ONLY ? level.paperConfig.creativeArrowDespawnRate : (pickup == Pickup.DISALLOWED ? level.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? diff --git a/Remapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch b/Remapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch new file mode 100644 index 0000000000..41cf790265 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 11 Jul 2020 03:54:28 -0400 +Subject: [PATCH] Thread Safe Vanilla Command permission checking + +Datapacks check this on load and are built concurrently. This was breaking them badly due +to race conditions. + +Plus, .canUse we want to be safe for async anyways. + +diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +index 5c35cef42af4053332c02b4960c227fe95d4c197..757ed7a0887f4bdb187ca7c757db5c188362f1a0 100644 +--- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java ++++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +@@ -74,10 +74,10 @@ public abstract class CommandNode implements Comparable> { + public synchronized boolean canUse(final S source) { + if (source instanceof CommandSourceStack) { + try { +- ((CommandSourceStack) source).currentCommand = this; ++ ((CommandSourceStack) source).currentCommand.set(this); // Paper + return requirement.test(source); + } finally { +- ((CommandSourceStack) source).currentCommand = null; ++ ((CommandSourceStack) source).currentCommand.set(null); // Paper + } + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java +index e1f4ffaa36bfffb7741c74b7a094e26a03a9a1e6..2c024f8f8b949dc8cebd29a10415eeac6d50902e 100644 +--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java ++++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java +@@ -54,7 +54,7 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy + private final ResultConsumer consumer; + private final EntityAnchorArgument.Anchor anchor; + private final Vec2 rotation; +- public volatile CommandNode currentCommand; // CraftBukkit ++ public ThreadLocal currentCommand = new ThreadLocal<>(); // CraftBukkit // Paper + + public CommandSourceStack(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String simpleName, Component name, MinecraftServer server, @Nullable Entity entity) { + this(output, pos, rot, world, level, simpleName, name, server, entity, false, (commandcontext, flag, j) -> { +@@ -171,9 +171,11 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy + @Override + public boolean hasPermission(int level) { + // CraftBukkit start +- CommandNode currentCommand = this.currentCommand; ++ // Paper start - fix concurrency issue ++ CommandNode currentCommand = this.currentCommand.get(); + if (currentCommand != null) { + return hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); ++ // Paper end + } + // CraftBukkit end + diff --git a/Remapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch b/Remapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch new file mode 100644 index 0000000000..7fba765097 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Jul 2020 19:34:11 -0700 +Subject: [PATCH] Move range check for block placing up + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 773f2589c14e16d2f5b01a6dbd48e09d17d19c7e..d264fca2737f83a0860394f7bb6b269ffe669594 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1661,15 +1661,19 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + BlockPos blockposition = movingobjectpositionblock.getBlockPos(); + Direction enumdirection = movingobjectpositionblock.getDirection(); + ++ // Paper start - move check up ++ Location eyeLoc = this.getPlayer().getEyeLocation(); ++ double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); ++ if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { ++ return; ++ } ++ // Paper end - move check up ++ + this.player.resetLastActionTime(); + if (blockposition.getY() < this.server.getMaxBuildHeight()) { + if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition)) { + // CraftBukkit start - Check if we can actually do something over this large a distance +- Location eyeLoc = this.getPlayer().getEyeLocation(); +- double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); +- if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { +- return; +- } ++ // Paper - move check up + this.player.stopUsingItem(); // SPIGOT-4706 + // CraftBukkit end + InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); diff --git a/Remapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch b/Remapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch new file mode 100644 index 0000000000..84a6a9da90 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 15 Jul 2020 21:42:52 -0400 +Subject: [PATCH] Fix SPIGOT-5989 + +Before this fix, if a player was respawning to a respawn anchor and +the respawn location was modified away from the anchor with the +PlayerRespawnEvent, the anchor would still lose some charge. +This fixes that by checking if the modified spawn location is +still at a respawn anchor. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index f36c92e42300c2056075610caf63f8bef0e7edda..882cd25c9610f0b995c27291aa62846922ab531f 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -84,6 +84,7 @@ import net.minecraft.world.level.GameType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.RespawnAnchorBlock; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.border.BorderChangeListener; + import net.minecraft.world.level.border.WorldBorder; +@@ -846,6 +847,7 @@ public abstract class PlayerList { + // Paper start + boolean isBedSpawn = false; + boolean isRespawn = false; ++ boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 + // Paper end + + // CraftBukkit start - fire PlayerRespawnEvent +@@ -856,7 +858,7 @@ public abstract class PlayerList { + Optional optional; + + if (blockposition != null) { +- optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, flag); ++ optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, true); // Paper - Fix SPIGOT-5989 + } else { + optional = Optional.empty(); + } +@@ -899,7 +901,12 @@ public abstract class PlayerList { + } + // Spigot End + +- location = respawnEvent.getRespawnLocation(); ++ // Paper start - Fix SPIGOT-5989 ++ if (!location.equals(respawnEvent.getRespawnLocation()) ) { ++ location = respawnEvent.getRespawnLocation(); ++ isLocAltered = true; ++ } ++ // Paper end + if (!flag) entityplayer.reset(); // SPIGOT-4785 + isRespawn = true; // Paper + } else { +@@ -937,8 +944,12 @@ public abstract class PlayerList { + } + // entityplayer1.syncInventory(); + entityplayer1.setHealth(entityplayer1.getHealth()); +- if (flag2) { +- entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 1.0F, 1.0F)); ++ // Paper start - Fix SPIGOT-5989 ++ if (flag2 && !isLocAltered) { ++ BlockState data = worldserver1.getBlockState(blockposition); ++ worldserver1.setBlock(blockposition, data.setValue(RespawnAnchorBlock.CHARGE, data.getValue(RespawnAnchorBlock.CHARGE) - 1), 3); ++ entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) location.getX(), (double) location.getY(), (double) location.getZ(), 1.0F, 1.0F)); ++ // Paper end + } + // Added from changeDimension + sendAllPlayerInfo(entityplayer); // Update health, etc... diff --git a/Remapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/Remapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch new file mode 100644 index 0000000000..52bb1345ae --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 10 Jul 2020 13:12:33 -0500 +Subject: [PATCH] Fix SPIGOT-5824 Bukkit world-container is not used + + +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 855b3b4c90d84d4efa8395a76010b4b194591cbc..4e353432281a6dbbb49eaa4a6cb4eb051d1a08c5 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -124,11 +124,20 @@ public class Main { + return; + } + +- File file = (File) optionset.valueOf("universe"); // CraftBukkit ++ // Paper start - fix SPIGOT-5824 ++ File file; ++ File userCacheFile = new File("usercache.json"); ++ if (optionset.has("universe")) { ++ file = (File) optionset.valueOf("universe"); // CraftBukkit ++ userCacheFile = new File(file, "usercache.json"); ++ } else { ++ file = new File(bukkitConfiguration.getString("settings.world-container", ".")); ++ } ++ // Paper end - fix SPIGOT-5824 + YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper + MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); + GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); +- GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName())); ++ GameProfileCache usercache = new GameProfileCache(gameprofilerepository, userCacheFile); // Paper - only move usercache.json into folder if --universe is used, not world-container + // CraftBukkit start + String s = (String) Optional.ofNullable(optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); + LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath()); diff --git a/Remapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/Remapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch new file mode 100644 index 0000000000..fb2e14a9d3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 10 Jul 2020 12:38:12 -0500 +Subject: [PATCH] Fix SPIGOT-5885 Unable to disable advancements + + +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 4e353432281a6dbbb49eaa4a6cb4eb051d1a08c5..9dc9a5e6ad7f23c8bf3553c765ceeecd67a49ac1 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -124,6 +124,7 @@ public class Main { + return; + } + ++ org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init + // Paper start - fix SPIGOT-5824 + File file; + File userCacheFile = new File("usercache.json"); diff --git a/Remapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/Remapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch new file mode 100644 index 0000000000..8ec38751cb --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 13 Jul 2020 06:22:54 -0700 +Subject: [PATCH] Fix AdvancementDataPlayer leak due from quitting early in + login + +Move the criterion storage to the AdvancementDataPlayer object +itself, so the criterion object stores no references - and thus +needs no cleanup. + +diff --git a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java +index 31650e41b37e322d2e8a4d4a3deec95851e72675..a645c79af856d2484a4ce7aa2885a32358b9a480 100644 +--- a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java ++++ b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java +@@ -16,25 +16,25 @@ import net.minecraft.world.level.storage.loot.LootContext; + + public abstract class SimpleCriterionTrigger implements CriterionTrigger { + +- private final Map>> a = Maps.newIdentityHashMap(); ++ //private final Map>> a = Maps.newIdentityHashMap(); // Paper - moved into AdvancementDataPlayer to fix memory leak + + public SimpleCriterionTrigger() {} + + @Override + public final void a(PlayerAdvancements advancementdataplayer, CriterionTrigger.Listener criteriontrigger_a) { +- ((Set) this.a.computeIfAbsent(advancementdataplayer, (advancementdataplayer1) -> { ++ (advancementdataplayer.criterionData.computeIfAbsent(this, (advancementdataplayer1) -> { // Paper - fix AdvancementDataPlayer leak + return Sets.newHashSet(); + })).add(criteriontrigger_a); + } + + @Override + public final void b(PlayerAdvancements advancementdataplayer, CriterionTrigger.Listener criteriontrigger_a) { +- Set> set = (Set) this.a.get(advancementdataplayer); ++ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak + + if (set != null) { + set.remove(criteriontrigger_a); + if (set.isEmpty()) { +- this.a.remove(advancementdataplayer); ++ advancementdataplayer.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak + } + } + +@@ -42,7 +42,7 @@ public abstract class SimpleCriterionTrigger tester) { + PlayerAdvancements advancementdataplayer = player.getAdvancements(); +- Set> set = (Set) this.a.get(advancementdataplayer); ++ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak + + if (set != null && !set.isEmpty()) { + LootContext loottableinfo = EntityPredicate.createContext(player, player); +@@ -67,7 +67,7 @@ public abstract class SimpleCriterionTrigger> criterionData = Maps.newIdentityHashMap(); ++ // Paper end - fix advancement data player leakage ++ + public PlayerAdvancements(DataFixer datafixer, PlayerList playerlist, ServerAdvancementManager advancementdataworld, File file, ServerPlayer entityplayer) { + this.dataFixer = datafixer; + this.playerList = playerlist; diff --git a/Remapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/Remapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch new file mode 100644 index 0000000000..468888ab9b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 26 Jul 2020 12:11:39 +0100 +Subject: [PATCH] Add missing strikeLighting call to + World#spigot()#strikeLightningEffect + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 4436b3d23dc8f33925da1ec539ea16307e0785b9..793b1309528671ce822d5a484ff9e40d6eba4e9d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2609,6 +2609,7 @@ public class CraftWorld implements World { + lightning.moveTo( loc.getX(), loc.getY(), loc.getZ() ); + lightning.visualOnly = true; + lightning.isSilent = isSilent; ++ world.strikeLightning( lightning ); + return (LightningStrike) lightning.getBukkitEntity(); + } + }; diff --git a/Remapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch b/Remapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch new file mode 100644 index 0000000000..a1593c3e27 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 24 Jul 2020 15:56:05 -0700 +Subject: [PATCH] Fix some rails connecting improperly + + +diff --git a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java +index 1a44c8b41928a83a22b53d1b6f45ce39b4caf2b2..7cef6d1fc2045c62d4e96a0fd0a311d089cb1406 100644 +--- a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java +@@ -62,6 +62,7 @@ public abstract class BaseRailBlock extends Block { + state = this.updateDir(world, pos, state, true); + if (this.isStraight) { + state.neighborChanged(world, pos, this, pos, notify); ++ state = world.getBlockState(pos); // Paper - don't desync, update again + } + + return state; +diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +index 0ab1e15d8575c3e90a10b80b94030e15a01faac9..1854809e045300e84a713dc7c3a8264f53ec6c0f 100644 +--- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +@@ -70,6 +70,7 @@ public class DetectorRailBlock extends BaseRailBlock { + + private void checkPressed(Level world, BlockPos pos, BlockState state) { + if (this.canSurvive(state, world, pos)) { ++ if (state.getBlock() != this) { return; } // Paper - not our block, don't do anything + boolean flag = (Boolean) state.getValue(DetectorRailBlock.POWERED); + boolean flag1 = false; + List list = this.getInteractingMinecartOfType(world, pos, AbstractMinecart.class, (Predicate) null); +diff --git a/src/main/java/net/minecraft/world/level/block/RailState.java b/src/main/java/net/minecraft/world/level/block/RailState.java +index 0d824ab98dcdd6ea9dac025c37970fb4ec464131..4c17bec369fb19f47760e30b391b2128cee6b276 100644 +--- a/src/main/java/net/minecraft/world/level/block/RailState.java ++++ b/src/main/java/net/minecraft/world/level/block/RailState.java +@@ -12,13 +12,19 @@ import net.minecraft.world.level.block.state.properties.RailShape; + + public class RailState { + +- private final Level level; +- private final BlockPos pos; ++ private final Level level; public final Level getWorld() { return this.level; } // Paper - OBFHELPER ++ private final BlockPos pos; public final BlockPos getPos() { return this.pos; } // Paper - OBFHELPER + private final BaseRailBlock block; +- private BlockState state; ++ private BlockState state; public final BlockState getRailState() { return this.state; } // Paper - OBFHELPER + private final boolean isStraight; + private final List connections = Lists.newArrayList(); + ++ // Paper start - prevent desync ++ public boolean isValid() { ++ return this.getWorld().getBlockState(this.getPos()).getBlock() == this.getRailState().getBlock(); ++ } ++ // Paper end - prevent desync ++ + public RailState(Level world, BlockPos pos, BlockState state) { + this.level = world; + this.pos = pos; +@@ -153,6 +159,11 @@ public class RailState { + } + + private void connectTo(RailState placementHelper) { ++ // Paper start - prevent desync ++ if (!this.isValid() || !placementHelper.isValid()) { ++ return; ++ } ++ // Paper end - prevent desync + this.connections.add(placementHelper.pos); + BlockPos blockposition = this.pos.north(); + BlockPos blockposition1 = this.pos.south(); +@@ -347,11 +358,16 @@ public class RailState { + this.state = (BlockState) this.state.setValue(this.block.getShapeProperty(), blockpropertytrackposition1); + if (forceUpdate || this.level.getBlockState(this.pos) != this.state) { + this.level.setBlock(this.pos, this.state, 3); ++ // Paper start - prevent desync ++ if (!this.isValid()) { ++ return this; ++ } ++ // Paper end - prevent desync + + for (int i = 0; i < this.connections.size(); ++i) { + RailState minecarttracklogic = this.getRail((BlockPos) this.connections.get(i)); + +- if (minecarttracklogic != null) { ++ if (minecarttracklogic != null && minecarttracklogic.isValid()) { // Paper - prevent desync + minecarttracklogic.removeSoftConnections(); + if (minecarttracklogic.canConnectTo(this)) { + minecarttracklogic.connectTo(this); +@@ -364,6 +380,6 @@ public class RailState { + } + + public BlockState getState() { +- return this.state; ++ return this.getWorld().getBlockState(this.getPos()); // Paper - prevent desync + } + } diff --git a/Remapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/Remapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch new file mode 100644 index 0000000000..7f15a77054 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch @@ -0,0 +1,159 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 4 Aug 2020 22:24:15 +0200 +Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections + +I utilized the IDE to convert streams to non streams code, so shouldn't +be any risk of behavior change. Only did minor optimization of the +generated code set to remove unnecessary things. + +I expect us to just drop this patch on next major update and re-apply +it with the IDE again and re-apply the collections optimization. + +Optimize collection by creating a list instead of a set of the key and value. + +This lets us get faster foreach iteration, as well as avoids map lookups on +the values when needed. + +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +index ba8ee93032aabe7ec4ecf52d452e1a580d6ebc20..2ef0e04af771e14f8d71aef4ccb81d3b81db7df5 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +@@ -33,28 +33,31 @@ public class PathFinder { + this.openSet.a(); + this.nodeEvaluator.prepare(world, mob); + Node pathpoint = this.nodeEvaluator.getStart(); +- Map map = (Map) positions.stream().collect(Collectors.toMap((blockposition) -> { +- return this.nodeEvaluator.getGoal((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); +- }, Function.identity())); +- Path pathentity = this.findPath(pathpoint, map, followRange, distance, rangeMultiplier); ++ // Paper start - remove streams - and optimize collection ++ List> map = Lists.newArrayList(); ++ for (BlockPos blockposition : positions) { ++ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal((double) blockposition.getX(), blockposition.getY(), blockposition.getZ()), blockposition)); ++ } ++ // Paper end ++ Path pathentity = this.a(pathpoint, map, followRange, distance, rangeMultiplier); + + this.nodeEvaluator.done(); + return pathentity; + } + + @Nullable +- private Path findPath(Node startNode, Map positions, float followRange, int distance, float rangeMultiplier) { +- Set set = positions.keySet(); ++ private Path a(Node pathpoint, List> list, float f, int i, float f1) { // Paper - optimize collection ++ //Set set = map.keySet(); // Paper + +- startNode.g = 0.0F; +- startNode.h = this.getBestH(startNode, set); +- startNode.f = startNode.h; ++ pathpoint.g = 0.0F; ++ pathpoint.h = this.a(pathpoint, list); // Paper - optimize collection ++ pathpoint.f = pathpoint.h; + this.openSet.a(); +- this.openSet.a(startNode); ++ this.openSet.a(pathpoint); + Set set1 = ImmutableSet.of(); + int j = 0; +- Set set2 = Sets.newHashSetWithExpectedSize(set.size()); +- int k = (int) ((float) this.maxVisitedNodes * rangeMultiplier); ++ List> set2 = Lists.newArrayListWithExpectedSize(list.size()); // Paper - optimize collection ++ int k = (int) ((float) this.maxVisitedNodes * f1); + + while (!this.openSet.e()) { + ++j; +@@ -65,14 +68,15 @@ public class PathFinder { + Node pathpoint1 = this.openSet.c(); + + pathpoint1.closed = true; +- Iterator iterator = set.iterator(); +- +- while (iterator.hasNext()) { +- Target pathdestination = (Target) iterator.next(); ++ // Paper start - optimize collection ++ for (int i1 = 0; i1 < list.size(); i1++) { ++ Map.Entry entry = list.get(i1); ++ Target pathdestination = entry.getKey(); + +- if (pathpoint1.distanceManhattan((Node) pathdestination) <= (float) distance) { ++ if (pathpoint1.distanceManhattan((Node) pathdestination) <= (float) i) { + pathdestination.setReached(); +- set2.add(pathdestination); ++ set2.add(entry); ++ // Paper end + } + } + +@@ -80,7 +84,7 @@ public class PathFinder { + break; + } + +- if (pathpoint1.distanceTo(startNode) < followRange) { ++ if (pathpoint1.distanceTo(pathpoint) < f) { + int l = this.nodeEvaluator.getNeighbors(this.neighbors, pathpoint1); + + for (int i1 = 0; i1 < l; ++i1) { +@@ -90,10 +94,10 @@ public class PathFinder { + pathpoint2.walkedDistance = pathpoint1.walkedDistance + f2; + float f3 = pathpoint1.g + f2 + pathpoint2.costMalus; + +- if (pathpoint2.walkedDistance < followRange && (!pathpoint2.inOpenSet() || f3 < pathpoint2.g)) { ++ if (pathpoint2.walkedDistance < f && (!pathpoint2.inOpenSet() || f3 < pathpoint2.g)) { + pathpoint2.cameFrom = pathpoint1; + pathpoint2.g = f3; +- pathpoint2.h = this.getBestH(pathpoint2, set) * 1.5F; ++ pathpoint2.h = this.a(pathpoint2, list) * 1.5F; // Paper - list instead of set + if (pathpoint2.inOpenSet()) { + this.openSet.a(pathpoint2, pathpoint2.g + pathpoint2.h); + } else { +@@ -105,31 +109,32 @@ public class PathFinder { + } + } + +- Optional optional = !set2.isEmpty() ? set2.stream().map((pathdestination1) -> { +- return this.reconstructPath(pathdestination1.getBestNode(), (BlockPos) positions.get(pathdestination1), true); +- }).min(Comparator.comparingInt(Path::getNodeCount)) : set.stream().map((pathdestination1) -> { +- return this.reconstructPath(pathdestination1.getBestNode(), (BlockPos) positions.get(pathdestination1), false); +- }).min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount)); +- +- if (!optional.isPresent()) { +- return null; +- } else { +- Path pathentity = (Path) optional.get(); +- +- return pathentity; ++ // Paper start - remove streams - and optimize collection ++ Path best = null; ++ boolean useSet1 = set2.isEmpty(); ++ Comparator comparator = useSet1 ? Comparator.comparingInt(Path::getNodeCount) ++ : Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount); ++ for (Map.Entry entry : useSet1 ? list : set2) { ++ Path pathEntity = this.reconstructPath(entry.getKey().getBestNode(), entry.getValue(), !useSet1); ++ if (best == null || comparator.compare(pathEntity, best) < 0) ++ best = pathEntity; + } ++ return best; ++ // Paper end + } + +- private float getBestH(Node node, Set targets) { ++ private float a(Node pathpoint, List> list) { // Paper - optimize collection + float f = Float.MAX_VALUE; + + float f1; + +- for (Iterator iterator = targets.iterator(); iterator.hasNext(); f = Math.min(f1, f)) { +- Target pathdestination = (Target) iterator.next(); ++ // Paper start - optimize collection ++ for (int i = 0, listSize = list.size(); i < listSize; f = Math.min(f1, f), i++) { // Paper ++ Target pathdestination = list.get(i).getKey(); // Paper ++ // Paper end + +- f1 = node.distanceTo(pathdestination); +- pathdestination.updateBest(f1, node); ++ f1 = pathpoint.distanceTo(pathdestination); ++ pathdestination.updateBest(f1, pathpoint); + } + + return f; diff --git a/Remapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch b/Remapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch new file mode 100644 index 0000000000..cd7713a510 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 9 Aug 2020 08:59:25 +0300 +Subject: [PATCH] Incremental player saving + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index b67ba8f75e4a3358d7c2462918b85b0bf9b5a922..fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -440,4 +440,15 @@ public class PaperConfig { + allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); + set("settings.unsupported-settings.allow-tnt-duplication", null); + } ++ ++ public static int playerAutoSaveRate = -1; ++ public static int maxPlayerAutoSavePerTick = 10; ++ private static void playerAutoSaveRate() { ++ playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1); ++ maxPlayerAutoSavePerTick = getInt("settings.max-player-auto-save-per-tick", -1); ++ if (maxPlayerAutoSavePerTick == -1) { // -1 Automatic / "Recommended" ++ // 10 should be safe for everyone unless you mass spamming player auto save ++ maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 19544b794b5a46c129016172798ff7294fcfed33..735c3c983e96e4e6f36de0975909fc48cb042081 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1347,9 +1347,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down + //MinecraftServer.LOGGER.debug("Autosave started"); // Paper + serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper ++ // Paper start ++ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate; ++ if (playerSaveInterval < 0) { ++ playerSaveInterval = autosavePeriod; ++ } ++ // Paper end + this.profiler.push("save"); +- if (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0) { // Paper +- this.playerList.saveAll(); ++ if (playerSaveInterval > 0) { // Paper ++ this.playerList.savePlayers(playerSaveInterval); // Paper + }// Paper + // Paper start + for (ServerLevel world : getAllLevels()) { +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index c5717f45a0110492aad41f21cc06fb8cbeb1f791..bd4d4ace35e966e819aa461d3962fe06ff402be7 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -173,6 +173,7 @@ import org.bukkit.inventory.MainHand; + public class ServerPlayer extends Player implements ContainerListener { + + private static final Logger LOGGER = LogManager.getLogger(); ++ public long lastSave = MinecraftServer.currentTick; // Paper + public ServerGamePacketListenerImpl connection; + public Connection networkManager; // Paper + public final MinecraftServer server; +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 882cd25c9610f0b995c27291aa62846922ab531f..b76735531ef96f9d4c870a5107feea01524a7670 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -559,6 +559,7 @@ public abstract class PlayerList { + protected void save(ServerPlayer player) { + if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit + if (!player.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) ++ player.lastSave = MinecraftServer.currentTick; // Paper + this.playerIo.save(player); + ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit + +@@ -1218,10 +1219,21 @@ public abstract class PlayerList { + } + + public void saveAll() { ++ // Paper start - incremental player saving ++ savePlayers(null); ++ } ++ public void savePlayers(Integer interval) { + MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main + MinecraftTimings.savePlayers.startTiming(); // Paper ++ int numSaved = 0; ++ long now = MinecraftServer.currentTick; + for (int i = 0; i < this.players.size(); ++i) { +- this.save((ServerPlayer) this.players.get(i)); ++ ServerPlayer entityplayer = this.players.get(i); ++ if (interval == null || now - entityplayer.lastSave >= interval) { ++ this.save(entityplayer); ++ if (interval != null && ++numSaved <= com.destroystokyo.paper.PaperConfig.maxPlayerAutoSavePerTick) { break; } ++ } ++ // Paper end + } + MinecraftTimings.savePlayers.stopTiming(); // Paper + return null; }); // Paper - ensure main diff --git a/Remapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch b/Remapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch new file mode 100644 index 0000000000..706c8236e3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 12 Aug 2020 11:33:04 +0200 +Subject: [PATCH] Import fastutil classes + + +diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java +index 95e166aa63f42c675df645a56e313bdffc2e8663..05f7d4a3835536f26f741d54a0884bd43fc82967 100644 +--- a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java ++++ b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java +@@ -16,6 +16,7 @@ import net.minecraft.CrashReport; + import net.minecraft.ReportedException; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.world.entity.Entity; ++import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; // Paper + import org.apache.commons.lang3.ObjectUtils; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -25,7 +26,7 @@ public class SynchedEntityData { + private static final Logger LOGGER = LogManager.getLogger(); + private static final Map, Integer> ENTITY_ID_POOL = Maps.newHashMap(); + private final Entity entity; +- private final it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap> entries = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL ++ private final Int2ObjectOpenHashMap> entries = new Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL + // private final ReadWriteLock lock = new ReentrantReadWriteLock(); // Spigot - not required + private boolean isEmpty = true; + private boolean isDirty; diff --git a/Remapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch b/Remapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch new file mode 100644 index 0000000000..3a19fd93b1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Fri, 14 Aug 2020 23:41:19 +0200 +Subject: [PATCH] Don't mark null chunk sections for block updates + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 9e3629884709126574a52ad44fe7523f01dbcce9..82205ad13ef0e987bd83979d06331545efe0a60a 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -449,6 +449,7 @@ public class ChunkHolder { + this.broadcastBlockEntityIfNeeded(world, blockposition, iblockdata); + } else { + LevelChunkSection chunksection = chunk.getSections()[sectionposition.getY()]; ++ if (chunksection == null) chunksection = new LevelChunkSection(sectionposition.getY(), chunk, world, true); // Paper - make a new chunk section if none was found + ClientboundSectionBlocksUpdatePacket packetplayoutmultiblockchange = new ClientboundSectionBlocksUpdatePacket(sectionposition, shortset, chunksection, this.resendLight); + + this.broadcast(packetplayoutmultiblockchange, false); diff --git a/Remapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch b/Remapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch new file mode 100644 index 0000000000..8e11c05922 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Fri, 14 Aug 2020 23:59:26 +0200 +Subject: [PATCH] Remove armour stand double add to world + + +diff --git a/src/main/java/net/minecraft/world/item/ArmorStandItem.java b/src/main/java/net/minecraft/world/item/ArmorStandItem.java +index a2dfcaac8a2a4a69e703de43be76d4fe369fd647..bed063497bb593683ea384605ae1a71a68f4fc1b 100644 +--- a/src/main/java/net/minecraft/world/item/ArmorStandItem.java ++++ b/src/main/java/net/minecraft/world/item/ArmorStandItem.java +@@ -53,7 +53,7 @@ public class ArmorStandItem extends Item { + return InteractionResult.FAIL; + } + +- worldserver.addFreshEntityWithPassengers(entityarmorstand); ++ // Paper - moved down + float f = (float) Mth.floor((Mth.wrapDegrees(context.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F; + + entityarmorstand.moveTo(entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), f, 0.0F); +@@ -63,7 +63,7 @@ public class ArmorStandItem extends Item { + return InteractionResult.FAIL; + } + // CraftBukkit end +- world.addFreshEntity(entityarmorstand); ++ worldserver.addFreshEntityWithPassengers(entityarmorstand); // Paper - moved down + world.playSound((Player) null, entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F); + } + diff --git a/Remapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch b/Remapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch new file mode 100644 index 0000000000..1e2cd52d5b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 15 Aug 2020 08:04:49 -0500 +Subject: [PATCH] Fix MC-187716 Use configured height + + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java +index 3f297ef7bde4159c77681574966446a0eba03f25..ff17c76f341028dd6d17f4c1f13f442c2e404532 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java +@@ -44,7 +44,7 @@ public abstract class NetherCappedSurfaceBuilder extends SurfaceBuilder= 0; --k2) { ++ for (int k2 = height; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height + blockposition_mutableblockposition.set(k1, k2, l1); + BlockState iblockdata5 = chunk.getBlockState(blockposition_mutableblockposition); + int l2; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java +index 4d6c03048022442dea467e1d9d018f150adc62c7..f64671b7359fb71e8af578d48d0a3c211e315057 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java +@@ -34,7 +34,7 @@ public class NetherForestSurfaceBuilder extends SurfaceBuilder= 0; --k2) { ++ for (int k2 = height; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height + blockposition_mutableblockposition.set(k1, k2, l1); + BlockState iblockdata3 = surfaceBlocks.getTopMaterial(); + BlockState iblockdata4 = chunk.getBlockState(blockposition_mutableblockposition); +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java +index c1e0fd7813786bf1cc03b08b204007711575f144..b222890e7bdff2c1470841677a99d4423f9c9d7f 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java +@@ -36,7 +36,7 @@ public class NetherSurfaceBuilder extends SurfaceBuilder= 0; --k2) { ++ for (int k2 = height; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height + blockposition_mutableblockposition.set(k1, k2, l1); + BlockState iblockdata4 = chunk.getBlockState(blockposition_mutableblockposition); + diff --git a/Remapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/Remapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch new file mode 100644 index 0000000000..c7a761474b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: mbax +Date: Mon, 17 Aug 2020 12:17:37 -0400 +Subject: [PATCH] Fix regex mistake in CB NBT int deserialization + +The existing regex is too open and allows for the absence of any actual +number data, detecting an NBT entry of just the letter "i" in upper or +lower case. This causes a single-character NBT entry to be processed as +an integer ending in "i", passing an empty String to to Integer.parseInt, +triggering an exception in loading the item. + +This commit forces numbers to be present prior to the ending "i" +letter. + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java +index 94d46bc56b3bc4c4750fcfb1732eea0e49a04195..8ec09ff3b5aae4267b753bd715f0a9d4ef0381bd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java +@@ -19,7 +19,7 @@ import net.minecraft.nbt.TagParser; + public class CraftNBTTagConfigSerializer { + + private static final Pattern ARRAY = Pattern.compile("^\\[.*]"); +- private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)?i", Pattern.CASE_INSENSITIVE); ++ private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)i", Pattern.CASE_INSENSITIVE); // Paper - fix regex + private static final Pattern DOUBLE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", Pattern.CASE_INSENSITIVE); + private static final TagParser MOJANGSON_PARSER = new TagParser(new StringReader("")); + diff --git a/Remapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch b/Remapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch new file mode 100644 index 0000000000..d47ebc8c6e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 23 Jul 2019 20:44:47 -0500 +Subject: [PATCH] Do not let the server load chunks from newer versions + +If the server attempts to load a chunk generated by a newer version of +the game, immediately stop the server to prevent data corruption. + +You can override this functionality at your own peril. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 0adf14af9841cd3a20a8b2c0c320eb06794ef261..f6a814f9305813eaafa56baa0327e0111cd4e38c 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -95,10 +95,24 @@ public class ChunkSerializer { + return holder.protoChunk; + } + ++ // Paper start ++ private static final int CURRENT_DATA_VERSION = SharedConstants.getCurrentVersion().getWorldVersion(); ++ private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion"); ++ // Paper end ++ + public static InProgressChunkHolder loadChunk(ServerLevel worldserver, StructureManager definedstructuremanager, PoiManager villageplace, ChunkPos chunkcoordintpair, CompoundTag nbttagcompound, boolean distinguish) { + ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); + // Paper end + ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); ++ // Paper start - Do NOT attempt to load chunks saved with newer versions ++ if (nbttagcompound.contains("DataVersion", 99)) { ++ int dataVersion = nbttagcompound.getInt("DataVersion"); ++ if (!JUST_CORRUPT_IT && dataVersion > CURRENT_DATA_VERSION) { ++ new RuntimeException("Server attempted to load chunk saved with newer version of minecraft! " + dataVersion + " > " + CURRENT_DATA_VERSION).printStackTrace(); ++ System.exit(1); ++ } ++ } ++ // Paper end + BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); + CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate + ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate diff --git a/Remapped-Spigot-Server-Patches/0545-Brand-support.patch b/Remapped-Spigot-Server-Patches/0545-Brand-support.patch new file mode 100644 index 0000000000..e134b27182 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0545-Brand-support.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DigitalRegent +Date: Sat, 11 Apr 2020 13:10:58 +0200 +Subject: [PATCH] Brand support + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index d264fca2737f83a0860394f7bb6b269ffe669594..ab6494f5a872bba5398bef0367b4d9257786f61e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -5,6 +5,7 @@ import com.google.common.primitives.Doubles; + import com.google.common.primitives.Floats; + import com.mojang.brigadier.ParseResults; + import com.mojang.brigadier.StringReader; ++import io.netty.buffer.Unpooled; + import io.netty.util.concurrent.Future; + import io.netty.util.concurrent.GenericFutureListener; + import it.unimi.dsi.fastutil.ints.Int2ShortMap; +@@ -37,6 +38,7 @@ import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.StringTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.Connection; ++import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.chat.ChatType; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.MutableComponent; +@@ -258,6 +260,8 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); + private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit + ++ private String clientBrandName = null; // Paper - Brand name ++ + public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { + this.server = server; + this.connection = connection; +@@ -2998,6 +3002,8 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register"); + private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister"); + ++ private static final ResourceLocation MINECRAFT_BRAND = new ResourceLocation("brand"); // Paper - Brand support ++ + @Override + public void handleCustomPayload(ServerboundCustomPayloadPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); +@@ -3025,6 +3031,16 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + try { + byte[] data = new byte[packet.data.readableBytes()]; + packet.data.readBytes(data); ++ ++ // Paper start - Brand support ++ if (packet.identifier.equals(MINECRAFT_BRAND)) { ++ try { ++ this.clientBrandName = new FriendlyByteBuf(Unpooled.copiedBuffer(data)).readUTF(256); ++ } catch (StringIndexOutOfBoundsException ex) { ++ this.clientBrandName = "illegal"; ++ } ++ } ++ // Paper end + craftServer.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packet.identifier.toString(), data); + } catch (Exception ex) { + ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); +@@ -3034,6 +3050,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + } + ++ // Paper start - brand support ++ public String getClientBrandName() { ++ return clientBrandName; ++ } ++ // Paper end ++ + public final boolean isDisconnected() { + return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 610eabd2e93f9efccee810c3b5a314bc3cc649d8..7aae63d22167dc1b3ec7e8bc8672855c2038007e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2385,6 +2385,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + // Paper end + }; + ++ // Paper start - brand support ++ @Override ++ public String getClientBrandName() { ++ return getHandle().connection != null ? getHandle().connection.getClientBrandName() : null; ++ } ++ // Paper end ++ + public Player.Spigot spigot() + { + return spigot; diff --git a/Remapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch b/Remapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch new file mode 100644 index 0000000000..d3257fe8be --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Thu, 20 Aug 2020 19:24:13 -0700 +Subject: [PATCH] Fix MC-99259 Wither Boss Bar doesn't update until + invulnerability period is over + + +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +index edd231568b75330d0cffbecb03a7e9dbc55d5f94..1f330d852eb9b3a36570542e10a88ae065798714 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -391,8 +391,9 @@ public class WitherBoss extends Monster implements RangedAttackMob { + this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + +- this.bossEvent.setPercent(this.getHealth() / this.getMaxHealth()); ++ //this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Moved down + } ++ this.bossEvent.setPercent(this.getHealth() / this.getMaxHealth()); // Paper - Fix MC-99259 (Boss bar does not update until Wither invulnerability period ends) + } + + public static boolean canDestroy(BlockState block) { diff --git a/Remapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch b/Remapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch new file mode 100644 index 0000000000..14ad3b04d2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ishland +Date: Sun, 23 Aug 2020 10:57:44 +0200 +Subject: [PATCH] Fix MC-197271 + +This patch only fixes an issue for servers running OpenJ9. + +diff --git a/src/main/java/net/minecraft/data/BuiltinRegistries.java b/src/main/java/net/minecraft/data/BuiltinRegistries.java +index d64cebb4431664762a14670c7d9d782dd7894ed5..0c403ea85f7ea20f2f978e06313f8675abf204b6 100644 +--- a/src/main/java/net/minecraft/data/BuiltinRegistries.java ++++ b/src/main/java/net/minecraft/data/BuiltinRegistries.java +@@ -48,11 +48,11 @@ public class BuiltinRegistries { + public static final Registry PROCESSOR_LIST = registerSimple(Registry.PROCESSOR_LIST_REGISTRY, () -> { + return ProcessorLists.b; + }); +- public static final Registry TEMPLATE_POOL = registerSimple(Registry.TEMPLATE_POOL_REGISTRY, Pools::bootstrap); ++ public static final Registry TEMPLATE_POOL = registerSimple(Registry.TEMPLATE_POOL_REGISTRY, () -> Pools.bootstrap()); // Paper - MC-197271 + public static final Registry BIOME = registerSimple(Registry.BIOME_REGISTRY, () -> { + return Biomes.PLAINS; + }); +- public static final Registry NOISE_GENERATOR_SETTINGS = registerSimple(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY, NoiseGeneratorSettings::bootstrap); ++ public static final Registry NOISE_GENERATOR_SETTINGS = registerSimple(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY, () -> NoiseGeneratorSettings.bootstrap()); // Paper - MC-197271 + + private static Registry registerSimple(ResourceKey> registryRef, Supplier defaultValueSupplier) { + return registerSimple(registryRef, Lifecycle.stable(), defaultValueSupplier); +@@ -66,9 +66,9 @@ public class BuiltinRegistries { + ResourceLocation minecraftkey = registryRef.location(); + + BuiltinRegistries.LOADERS.put(minecraftkey, defaultValueSupplier); +- WritableRegistry iregistrywritable = BuiltinRegistries.WRITABLE_REGISTRY; ++ WritableRegistry iregistrywritable = (WritableRegistry) BuiltinRegistries.WRITABLE_REGISTRY; // Paper - decompile fix + +- return (WritableRegistry) iregistrywritable.register(registryRef, (Object) registry, lifecycle); ++ return (R) iregistrywritable.register((ResourceKey) registryRef, registry, lifecycle); // Paper - decompile fix + } + + public static T register(Registry registry, String id, T object) { +@@ -76,11 +76,11 @@ public class BuiltinRegistries { + } + + public static T register(Registry registry, ResourceLocation id, T object) { +- return ((WritableRegistry) registry).register(ResourceKey.create(registry.key(), id), object, Lifecycle.stable()); ++ return (T) ((WritableRegistry) registry).register(ResourceKey.create(registry.key(), id), object, Lifecycle.stable()); // Paper - decompile fix + } + + public static T registerMapping(Registry iregistry, int rawId, ResourceKey resourcekey, T object) { +- return ((WritableRegistry) iregistry).registerMapping(rawId, resourcekey, object, Lifecycle.stable()); ++ return (T) ((WritableRegistry) iregistry).registerMapping(rawId, resourcekey, object, Lifecycle.stable()); // Paper - decompile fix + } + + public static void bootstrap() {} diff --git a/Remapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch b/Remapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch new file mode 100644 index 0000000000..fd35ea34e4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 21 Aug 2020 21:05:28 -0400 +Subject: [PATCH] MC-197883: Bandaid decode issue + +Mojang has a mix of type and name in the data sets, but you can only +use one. + +This will retry as name if type is asked for and not found. + +diff --git a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java +index de7d1e5e0319c65775d932144c268c2d55bb7dc7..bd6a0e1b5454e880a4f2a16be7dc8da64b73e11d 100644 +--- a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java ++++ b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java +@@ -48,7 +48,12 @@ public class KeyDispatchCodec extends MapCodec { + + @Override + public DataResult decode(final DynamicOps ops, final MapLike input) { +- final T elementName = input.get(typeKey); ++ // Paper start - bandaid MC-197883 ++ T elementName = input.get(typeKey); ++ if (elementName == null && "type".equals(typeKey)) { ++ elementName = input.get("name"); ++ } ++ // Paper end + if (elementName == null) { + return DataResult.error("Input does not contain a key [" + typeKey + "]: " + input); + } diff --git a/Remapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch b/Remapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch new file mode 100644 index 0000000000..bfd99ce60a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 22 Aug 2020 23:59:30 +0200 +Subject: [PATCH] Add #setMaxPlayers API + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index b76735531ef96f9d4c870a5107feea01524a7670..7e44c911f4abc5c7d0e89513bf2cfc3516f13492 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -141,7 +141,7 @@ public abstract class PlayerList { + public final PlayerDataStorage playerIo; + private boolean doWhiteList; + private final RegistryAccess.RegistryHolder registryHolder; +- protected final int maxPlayers; ++ protected int maxPlayers; public final void setMaxPlayers(int maxPlayers) { this.maxPlayers = maxPlayers; } // Paper - remove final and add setter + private int viewDistance; + private GameType overrideGameMode; + private boolean allowCheatsForAllPlayers; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index e301aee53b19fc3f93a36d0ed03a649741123bfa..e599be15af17e5e45d2b694c30140cc4a787a7f5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -613,6 +613,13 @@ public final class CraftServer implements Server { + return playerList.getMaxPlayers(); + } + ++ // Paper start ++ @Override ++ public void setMaxPlayers(int maxPlayers) { ++ this.playerList.setMaxPlayers(maxPlayers); ++ } ++ // Paper end ++ + // NOTE: These are dependent on the corresponding call in MinecraftServer + // so if that changes this will need to as well + @Override diff --git a/Remapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch b/Remapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch new file mode 100644 index 0000000000..e3089f12ce --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 23 Aug 2020 19:36:22 +0200 +Subject: [PATCH] Add playPickupItemAnimation to LivingEntity + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 067eaf1e05ced344eb168431403f3fe786eafddf..eb136af0f99f5d7520ceabb98cefd5a01122872c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -806,5 +806,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + ((Mob) getHandle()).getJumpControl().jump(); + } + } ++ ++ @Override ++ public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { ++ getHandle().take(((CraftItem) item).getHandle(), quantity); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch b/Remapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch new file mode 100644 index 0000000000..5ecdef5062 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sun, 23 Aug 2020 19:01:04 +0200 +Subject: [PATCH] Don't require FACING data + + +diff --git a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +index f7e60cdfa0b3f5970a897b5d52aaa72210f2fa57..ab8e69f9fc38012844ce01bd0cc5be8de2fcf4ab 100644 +--- a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +@@ -14,20 +14,22 @@ import org.bukkit.event.block.BlockDispenseEvent; + // CraftBukkit end + + public class DefaultDispenseItemBehavior implements DispenseItemBehavior { ++ private Direction enumdirection; // Paper + + public DefaultDispenseItemBehavior() {} + + @Override + public final ItemStack dispense(BlockSource pointer, ItemStack stack) { ++ enumdirection = pointer.getBlockState().getValue(DispenserBlock.FACING); // Paper - cache facing direction + ItemStack itemstack1 = this.execute(pointer, stack); + + this.playSound(pointer); +- this.playAnimation(pointer, (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING)); ++ this.playAnimation(pointer, enumdirection); // Paper - cache facing direction + return itemstack1; + } + + protected ItemStack execute(BlockSource pointer, ItemStack stack) { +- Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING); ++ // Paper - cached enum direction + Position iposition = DispenserBlock.getDispensePosition(pointer); + ItemStack itemstack1 = stack.split(1); + diff --git a/Remapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/Remapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch new file mode 100644 index 0000000000..7947c73149 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 22 Aug 2020 23:36:21 +0200 +Subject: [PATCH] Fix SpawnChangeEvent not firing for all use-cases + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 61aee2c109614a014149ae5a15ad2a28c796cb9d..22266fda4de9b5fbace3b8e55ce390b8d7e75a65 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1981,12 +1981,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + // Paper end + ++ public final void setSpawn(BlockPos blockposition, float f) { this.setDefaultSpawnPos(blockposition, f); } // Paper - OBFHELPER + public void setDefaultSpawnPos(BlockPos pos, float angle) { + // Paper - configurable spawn radius + BlockPos prevSpawn = this.getSpawn(); + //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); + + this.levelData.setSpawn(pos, angle); ++ new org.bukkit.event.world.SpawnChangeEvent(getWorld(), MCUtil.toLocation(this, prevSpawn)).callEvent(); // Paper + if (this.keepSpawnInMemory) { + // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add + this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 793b1309528671ce822d5a484ff9e40d6eba4e9d..37513a1774f5a6611338c1b90018b974238ddbf6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -371,11 +371,13 @@ public class CraftWorld implements World { + public boolean setSpawnLocation(int x, int y, int z, float angle) { + try { + Location previousLocation = getSpawnLocation(); +- world.levelData.setSpawn(new BlockPos(x, y, z), angle); ++ world.setSpawn(new BlockPos(x, y, z), angle); // Paper - use WorldServer#setSpawn + ++ // Paper start - move to nms.World + // Notify anyone who's listening. +- SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); +- server.getPluginManager().callEvent(event); ++ // SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); ++ // server.getPluginManager().callEvent(event); ++ // Paper end + + return true; + } catch (Exception e) { diff --git a/Remapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch b/Remapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch new file mode 100644 index 0000000000..bd3ee0c1e2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Aug 2020 16:32:11 +0200 +Subject: [PATCH] Add moon phase API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 37513a1774f5a6611338c1b90018b974238ddbf6..28bf53bc9fca21f57cd4851adf508d833ecdd33b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -310,6 +310,11 @@ public class CraftWorld implements World { + public int getPlayerCount() { + return world.players.size(); + } ++ ++ @Override ++ public io.papermc.paper.world.MoonPhase getMoonPhase() { ++ return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); ++ } + // Paper end + + private static final Random rand = new Random(); diff --git a/Remapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch b/Remapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch new file mode 100644 index 0000000000..15edeb8af6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: commandblockguy +Date: Fri, 14 Aug 2020 14:44:14 -0500 +Subject: [PATCH] Prevent headless pistons from being created + +Prevent headless pistons from being created by explosions or tree/mushroom growth. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb..faa1b775e45563b93ac1d5b904938b1f5ad8d80c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -441,6 +441,12 @@ public class PaperConfig { + set("settings.unsupported-settings.allow-tnt-duplication", null); + } + ++ public static boolean allowHeadlessPistons; ++ private static void allowHeadlessPistons() { ++ config.set("settings.unsupported-settings.allow-headless-pistons-readme", "This setting controls if players should be able to create headless pistons."); ++ allowHeadlessPistons = getBoolean("settings.unsupported-settings.allow-headless-pistons", false); ++ } ++ + public static int playerAutoSaveRate = -1; + public static int maxPlayerAutoSavePerTick = 10; + private static void playerAutoSaveRate() { +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 0f0a5fa2be5a7c69291b593a04cad83e069ba5b1..f7ca5294fe571770e3b0036e92563c5a099f76b1 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -15,6 +15,7 @@ import java.util.Random; + import java.util.Set; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; + import net.minecraft.core.Vec3i; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.server.level.ServerLevel; +@@ -35,6 +36,8 @@ import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.piston.PistonHeadBlock; ++import net.minecraft.world.level.block.piston.PistonMovingBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.storage.loot.LootContext; +@@ -161,6 +164,15 @@ public class Explosion { + + if (f > 0.0F && this.damageCalculator.a(this, this.level, blockposition, iblockdata, f) && blockposition.getY() < 256 && blockposition.getY() >= 0) { // CraftBukkit - don't wrap explosions + set.add(blockposition); ++ // Paper start - prevent headless pistons from forming ++ if (!com.destroystokyo.paper.PaperConfig.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) { ++ BlockEntity extension = this.level.getBlockEntity(blockposition); ++ if (extension instanceof PistonMovingBlockEntity && ((PistonMovingBlockEntity) extension).isHead()) { ++ Direction direction = iblockdata.getValue(PistonHeadBlock.FACING); ++ set.add(blockposition.relative(direction.getOpposite())); ++ } ++ } ++ // Paper end + } + + d4 += d0 * 0.30000001192092896D; +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +index 001e90da8b09e16b6df4849a5bac4f4821000c94..81f3c6fb7bab9de364537d3f3b2ea0f32795e5f1 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +@@ -65,6 +65,8 @@ public class PistonMovingBlockEntity extends BlockEntity implements TickableBloc + return this.direction; + } + ++ public final boolean isHead() { return this.isSourcePiston(); } // Paper - OBFHELPER ++ + public boolean isSourcePiston() { + return this.isSourcePiston; + } diff --git a/Remapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch b/Remapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch new file mode 100644 index 0000000000..05dfb6c0bb --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Eearslya Sleiarion +Date: Sun, 23 Aug 2020 13:04:02 +0200 +Subject: [PATCH] Add BellRingEvent + +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/net/minecraft/world/level/block/BellBlock.java b/src/main/java/net/minecraft/world/level/block/BellBlock.java +index affae471e50354bfa9594e188e6dcea183b9b5c9..dc5dc9e533c71908b7a9a3cc9e614bd4a0dcde98 100644 +--- a/src/main/java/net/minecraft/world/level/block/BellBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BellBlock.java +@@ -1,8 +1,11 @@ + package net.minecraft.world.level.block; + ++import io.papermc.paper.event.block.BellRingEvent; ++ + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +@@ -89,7 +92,7 @@ public class BellBlock extends BaseEntityBlock { + boolean flag1 = !flag || this.isProperHit(state, enumdirection, movingobjectpositionblock.getLocation().y - (double) blockposition.getY()); + + if (flag1) { +- boolean flag2 = this.attemptToRing(world, blockposition, enumdirection); ++ boolean flag2 = this.handleBellRing(world, blockposition, enumdirection, entityhuman); // Paper + + if (flag2 && entityhuman != null) { + entityhuman.awardStat(Stats.BELL_RING); +@@ -123,15 +126,21 @@ public class BellBlock extends BaseEntityBlock { + } + + public boolean attemptToRing(Level world, BlockPos pos, @Nullable Direction enumdirection) { +- BlockEntity tileentity = world.getBlockEntity(pos); ++ // Paper start - add ringer param ++ return this.handleBellRing(world, pos, enumdirection, null); ++ } ++ public boolean handleBellRing(Level world, BlockPos blockposition, @Nullable Direction enumdirection, @Nullable Entity ringer) { ++ // Paper end ++ BlockEntity tileentity = world.getBlockEntity(blockposition); + + if (!world.isClientSide && tileentity instanceof BellBlockEntity) { + if (enumdirection == null) { +- enumdirection = (Direction) world.getBlockState(pos).getValue(BellBlock.FACING); ++ enumdirection = (Direction) world.getBlockState(blockposition).getValue(BellBlock.FACING); + } + ++ if (!new BellRingEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, blockposition)), ringer == null ? null : ringer.getBukkitEntity()).callEvent()) return false; // Paper - BellRingEvent + ((BellBlockEntity) tileentity).onHit(enumdirection); +- world.playSound((Player) null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); ++ world.playSound((Player) null, blockposition, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); + return true; + } else { + return false; diff --git a/Remapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch b/Remapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch new file mode 100644 index 0000000000..d46a54fd32 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Aug 2020 15:47:34 +0200 +Subject: [PATCH] Add zombie targets turtle egg config + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 978062774c1db286bfb9b0ffdef19d880b1f249b..36ecdfce84141ac731b827e469ac842f5c666259 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -668,4 +668,9 @@ public class PaperWorldConfig { + maxLightningFlashDistance = 512; // Vanilla value + } + } ++ ++ public boolean zombiesTargetTurtleEggs = true; ++ private void zombiesTargetTurtleEggs() { ++ zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 1e7c2c603b967c8c606efd94ce95a17c856f78d7..4105c1763d25824aac35d305a793823c1604eee8 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -104,7 +104,7 @@ public class Zombie extends Monster { + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); ++ if (level.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); // Paper + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.addBehaviourGoals(); diff --git a/Remapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch b/Remapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch new file mode 100644 index 0000000000..b9f930aa4e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Wed, 19 Aug 2020 05:05:54 +0100 +Subject: [PATCH] Buffer joins to world + +This patch buffers the number of logins which will attempt to join +the world per tick, this attempts to reduce the impact that join floods +has on the server + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index faa1b775e45563b93ac1d5b904938b1f5ad8d80c..545948f20efd6c8dd42140b565af94cd6b52b661 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -457,4 +457,9 @@ public class PaperConfig { + maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; + } + } ++ ++ public static int maxJoinsPerTick; ++ private static void maxJoinsPerTick() { ++ maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); ++ } + } +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index fc63df21aecd4721efdb45d4744666ed0b562c1b..6f7cbce5a049d87d4a0ed7cc4517cb4e8694efb5 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -32,6 +32,7 @@ import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; + import net.minecraft.network.protocol.game.ClientboundKeepAlivePacket; + import net.minecraft.network.protocol.game.ClientboundSetTitlesPacket; + import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.RunningOnDifferentThreadException; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.network.ServerGamePacketListenerImpl; +@@ -382,10 +383,22 @@ public class Connection extends SimpleChannelInboundHandler> { + } + // Paper end + ++ private static final int MAX_PER_TICK = com.destroystokyo.paper.PaperConfig.maxJoinsPerTick; // Paper ++ private static int joinAttemptsThisTick; // Paper ++ private static int currTick; // Paper + public void tick() { + this.p(); ++ // Paper start ++ if (currTick != MinecraftServer.currentTick) { ++ currTick = MinecraftServer.currentTick; ++ joinAttemptsThisTick = 0; ++ } ++ // Paper end + if (this.packetListener instanceof ServerLoginPacketListenerImpl) { ++ if ( ((ServerLoginPacketListenerImpl) this.packetListener).getLoginState() != ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT // Paper ++ || (joinAttemptsThisTick++ < MAX_PER_TICK)) { // Paper - limit the number of joins which can be processed each tick + ((ServerLoginPacketListenerImpl) this.packetListener).tick(); ++ } // Paper + } + + if (this.packetListener instanceof ServerGamePacketListenerImpl) { +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index e229c7735ba88be3d8721440104958408a2a075e..659bf14cf3c949b896d0333f893a3d5e16ab9c92 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -420,7 +420,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + return new GameProfile(uuid, profile.getName()); + } + +- static enum State { ++ public enum State { // Paper - package private -> public + + HELLO, KEY, AUTHENTICATING, NEGOTIATING, READY_TO_ACCEPT, DELAY_ACCEPT, ACCEPTED; + diff --git a/Remapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch b/Remapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch new file mode 100644 index 0000000000..002eed1eeb --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch @@ -0,0 +1,1157 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: theosib +Date: Thu, 27 Sep 2018 01:43:35 -0600 +Subject: [PATCH] Optimize redstone algorithm + +Author: theosib +Co-authored-by: egg82 + +Original license: MIT + +This patch implements theosib's redstone algorithms to completely overhaul the way redstone works. +The new algorithms should be many times faster than current vanilla ones. +From the original author's comments, it looks like it shouldn't interfere with any redstone save for very extreme edge-cases. + +Surprisingly, not a lot was touched aside from a few obfuscation helpers and BlockRedstoneWire. +A lot of this code is self-contained in a helper class. + +Aside from making the obvious class/function renames and obfhelpers I didn't need to modify much. +Just added Bukkit's event system and took a few liberties with dead code and comment misspellings. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 36ecdfce84141ac731b827e469ac842f5c666259..02bb85364560784adea47c877c13291c3d016b86 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -673,4 +673,14 @@ public class PaperWorldConfig { + private void zombiesTargetTurtleEggs() { + zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); + } ++ ++ public boolean useEigencraftRedstone = false; ++ private void useEigencraftRedstone() { ++ useEigencraftRedstone = this.getBoolean("use-faster-eigencraft-redstone", false); ++ if (useEigencraftRedstone) { ++ log("Using Eigencraft redstone algorithm by theosib."); ++ } else { ++ log("Using vanilla redstone algorithm."); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java +new file mode 100644 +index 0000000000000000000000000000000000000000..19604f4d2d0cdf65cb9f164258c4435a5a3450bc +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java +@@ -0,0 +1,913 @@ ++package com.destroystokyo.paper.util; ++ ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.ThreadLocalRandom; ++import net.minecraft.core.BlockPos; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.item.Items; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.RedStoneWireBlock; ++import net.minecraft.world.level.block.state.BlockState; ++import org.bukkit.event.block.BlockRedstoneEvent; ++ ++import com.google.common.collect.Lists; ++import com.google.common.collect.Maps; ++ ++/** ++ * Used for the faster redstone algorithm. ++ * Original author: theosib ++ * Original license: MIT ++ * ++ * Ported to Paper and updated to 1.13 by egg82 ++ */ ++public class RedstoneWireTurbo { ++ /* ++ * This is Helper class for BlockRedstoneWire. It implements a minimally-invasive ++ * bolt-on accelerator that performs a breadth-first search through redstone wire blocks ++ * in order to more efficiently and deterministically compute new redstone wire power levels ++ * and determine the order in which other blocks should be updated. ++ * ++ * Features: ++ * - Changes to BlockRedstoneWire are very limited, no other classes are affected, and the ++ * choice between old and new redstone wire update algorithms is switchable on-line. ++ * - The vanilla implementation relied on World.notifyNeighborsOfStateChange for redstone ++ * wire blocks to communicate power level changes to each other, generating 36 block ++ * updates per call. This improved implementation propagates power level changes directly ++ * between redstone wire blocks. Redstone wire power levels are therefore computed more quickly, ++ * and block updates are sent only to non-redstone blocks, many of which may perform an ++ * action when informed of a change in redstone power level. (Note: Block updates are not ++ * the same as state changes to redstone wire. Wire block states are updated as soon ++ * as they are computed.) ++ * - Of the 36 block updates generated by a call to World.notifyNeighborsOfStateChange, ++ * 12 of them are obviously redundant (e.g. the west neighbor of the east neighbor). ++ * These are eliminated. ++ * - Updates to redstone wire and other connected blocks are propagated in a breath-first ++ * manner, radiating out from the initial trigger (a block update to a redstone wire ++ * from something other than redstone wire). ++ * - Updates are scheduled both deterministically and in an intuitive order, addressing bug ++ * MC-11193. ++ * - All redstone behavior that used to be locational now works the same in all locations. ++ * - All behaviors of redstone wire that used to be orientational now work the same in all ++ * orientations, as long as orientation can be determined; random otherwise. Some other ++ * redstone components still update directionally (e.g. switches), and this code can't ++ * compensate for that. ++ * - Information that is otherwise computed over and over again or which is expensive to ++ * to compute is cached for faster lookup. This includes coordinates of block position ++ * neighbors and block states that won't change behind our backs during the execution of ++ * this search algorithm. ++ * - Redundant block updates (both to redstone wire and to other blocks) are heavily ++ * consolidated. For worst-case scenarios (depowering of redstone wire) this results ++ * in a reduction of block updates by as much as 95% (factor of 1/21). Due to overheads, ++ * empirical testing shows a speedup better than 10x. This addresses bug MC-81098. ++ * ++ * Extensive testing has been performed to ensure that existing redstone contraptions still ++ * behave as expected. Results of early testing that identified undesirable behavior changes ++ * were addressed. Additionally, real-time performance testing revealed compute inefficiencies ++ * With earlier implementations of this accelerator. Some compatibility adjustments and ++ * performance optimizations resulted in harmless increases in block updates above the ++ * theoretical minimum. ++ * ++ * Only a single redstone machine was found to break: An instant dropper line hack that ++ * relies on powered rails and quasi-connectivity but doesn't work in all directions. The ++ * replacement is to lay redstone wire directly on top of the dropper line, which now works ++ * reliably in any direction. ++ * ++ * There are numerous other optimization that can be made, but those will be provided later in ++ * separate updates. This version is designed to be minimalistic. ++ * ++ * Many thanks to the following individuals for their help in testing this functionality: ++ * - pokechu22, _MethodZz_, WARBEN, NarcolepticFrog, CommandHelper (nessie), ilmango, ++ * OreoLamp, Xcom6000, tryashtar, RedCMD, Smokey95Dog, EDDxample, Rays Works, ++ * Nodnam, BlockyPlays, Grumm, NeunEinser, HelVince. ++ */ ++ ++ /* Reference to BlockRedstoneWire object, which uses this accelerator */ ++ private final RedStoneWireBlock wire; ++ ++ /* ++ * Implementation: ++ * ++ * RedstoneWire Blocks are updated in concentric rings or "layers" radiating out from the ++ * initial block update that came from a call to BlockRedstoneWire.neighborChanged(). ++ * All nodes put in Layer N are those with Manhattan distance N from the trigger ++ * position, reachable through connected redstone wire blocks. ++ * ++ * Layer 0 represents the trigger block position that was input to neighborChanged. ++ * Layer 1 contains the immediate neighbors of that position. ++ * Layer N contains the neighbors of blocks in layer N-1, not including ++ * those in previous layers. ++ * ++ * Layers enforce an update order that is a function of Manhattan distance ++ * from the initial coordinates input to neighborChanged. The same ++ * coordinates may appear in multiple layers, but redundant updates are minimized. ++ * Block updates are sent layer-by-layer. If multiple of a block's neighbors experience ++ * redstone wire changes before its layer is processed, then those updates will be merged. ++ * If a block's update has been sent, but its neighboring redstone changes ++ * after that, then another update will be sent. This preserves compatibility with ++ * machines that rely on zero-tick behavior, except that the new functionality is non- ++ * locational. ++ * ++ * Within each layer, updates are ordered left-to-right relative to the direction of ++ * information flow. This makes the implementation non-orientational. Only when ++ * this direction is ambiguous is randomness applied (intentionally). ++ */ ++ private List updateQueue0 = Lists.newArrayList(); ++ private List updateQueue1 = Lists.newArrayList(); ++ private List updateQueue2 = Lists.newArrayList(); ++ ++ public RedstoneWireTurbo(RedStoneWireBlock wire) { ++ this.wire = wire; ++ } ++ ++ /* ++ * Compute neighbors of a block. When a redstone wire value changes, previously it called ++ * World.notifyNeighborsOfStateChange. That lists immediately neighboring blocks in ++ * west, east, down, up, north, south order. For each of those neighbors, their own ++ * neighbors are updated in the same order. This generates 36 updates, but 12 of them are ++ * redundant; for instance the west neighbor of a block's east neighbor. ++ * ++ * Note that this ordering is only used to create the initial list of neighbors. Once ++ * the direction of signal flow is identified, the ordering of updates is completely ++ * reorganized. ++ */ ++ public static BlockPos[] computeAllNeighbors(final BlockPos pos) { ++ final int x = pos.getX(); ++ final int y = pos.getY(); ++ final int z = pos.getZ(); ++ final BlockPos[] n = new BlockPos[24]; ++ ++ // Immediate neighbors, in the same order as ++ // World.notifyNeighborsOfStateChange, etc.: ++ // west, east, down, up, north, south ++ n[0] = new BlockPos(x - 1, y, z); ++ n[1] = new BlockPos(x + 1, y, z); ++ n[2] = new BlockPos(x, y - 1, z); ++ n[3] = new BlockPos(x, y + 1, z); ++ n[4] = new BlockPos(x, y, z - 1); ++ n[5] = new BlockPos(x, y, z + 1); ++ ++ // Neighbors of neighbors, in the same order, ++ // except that duplicates are not included ++ n[6] = new BlockPos(x - 2, y, z); ++ n[7] = new BlockPos(x - 1, y - 1, z); ++ n[8] = new BlockPos(x - 1, y + 1, z); ++ n[9] = new BlockPos(x - 1, y, z - 1); ++ n[10] = new BlockPos(x - 1, y, z + 1); ++ n[11] = new BlockPos(x + 2, y, z); ++ n[12] = new BlockPos(x + 1, y - 1, z); ++ n[13] = new BlockPos(x + 1, y + 1, z); ++ n[14] = new BlockPos(x + 1, y, z - 1); ++ n[15] = new BlockPos(x + 1, y, z + 1); ++ n[16] = new BlockPos(x, y - 2, z); ++ n[17] = new BlockPos(x, y - 1, z - 1); ++ n[18] = new BlockPos(x, y - 1, z + 1); ++ n[19] = new BlockPos(x, y + 2, z); ++ n[20] = new BlockPos(x, y + 1, z - 1); ++ n[21] = new BlockPos(x, y + 1, z + 1); ++ n[22] = new BlockPos(x, y, z - 2); ++ n[23] = new BlockPos(x, y, z + 2); ++ return n; ++ } ++ ++ /* ++ * We only want redstone wires to update redstone wires that are ++ * immediately adjacent. Some more distant updates can result ++ * in cross-talk that (a) wastes time and (b) can make the update ++ * order unintuitive. Therefore (relative to the neighbor order ++ * computed by computeAllNeighbors), updates are not scheduled ++ * for redstone wire in those non-connecting positions. On the ++ * other hand, updates will always be sent to *other* types of blocks ++ * in any of the 24 neighboring positions. ++ */ ++ private static final boolean[] update_redstone = { ++ true, true, false, false, true, true, // 0 to 5 ++ false, true, true, false, false, false, // 6 to 11 ++ true, true, false, false, false, true, // 12 to 17 ++ true, false, true, true, false, false // 18 to 23 ++ }; ++ ++ // Internal numbering for cardinal directions ++ private static final int North = 0; ++ private static final int East = 1; ++ private static final int South = 2; ++ private static final int West = 3; ++ ++ /* ++ * These lookup tables completely remap neighbor positions into a left-to-right ++ * ordering, based on the cardinal direction that is determined to be forward. ++ * See below for more explanation. ++ */ ++ private static final int[] forward_is_north = {2, 3, 16, 19, 0, 4, 1, 5, 7, 8, 17, 20, 12, 13, 18, 21, 6, 9, 22, 14, 11, 10, 23, 15}; ++ private static final int[] forward_is_east = {2, 3, 16, 19, 4, 1, 5, 0, 17, 20, 12, 13, 18, 21, 7, 8, 22, 14, 11, 15, 23, 9, 6, 10}; ++ private static final int[] forward_is_south = {2, 3, 16, 19, 1, 5, 0, 4, 12, 13, 18, 21, 7, 8, 17, 20, 11, 15, 23, 10, 6, 14, 22, 9}; ++ private static final int[] forward_is_west = {2, 3, 16, 19, 5, 0, 4, 1, 18, 21, 7, 8, 17, 20, 12, 13, 23, 10, 6, 9, 22, 15, 11, 14}; ++ ++ /* For any orientation, we end up with the update order defined below. This order is relative to any redstone wire block ++ * that is itself having an update computed, and this center position is marked with C. ++ * - The update position marked 0 is computed first, and the one marked 23 is last. ++ * - Forward is determined by the local direction of information flow into position C from prior updates. ++ * - The first updates are scheduled for the four positions below and above C. ++ * - Then updates are scheduled for the four horizontal neighbors of C, followed by the positions below and above those neighbors. ++ * - Finally, updates are scheduled for the remaining positions with Manhattan distance 2 from C (at the same Y coordinate). ++ * - For a given horizontal distance from C, updates are scheduled starting from directly left and stepping clockwise to directly ++ * right. The remaining positions behind C are scheduled counterclockwise so as to maintain the left-to-right ordering. ++ * - If C is in layer N of the update schedule, then all 24 positions may be scheduled for layer N+1. For redstone wire, no ++ * updates are scheduled for positions that cannot directly connect. Additionally, the four positions above and below C ++ * are ALSO scheduled for layer N+2. ++ * - This update order was selected after experimenting with a number of alternative schedules, based on its compatibility ++ * with existing redstone designs and behaviors that were considered to be intuitive by various testers. WARBEN in particular ++ * made some of the most challenging test cases, but the 3-tick clocks (made by RedCMD) were also challenging to fix, ++ * along with the rail-based instant dropper line built by ilmango. Numerous others made test cases as well, including ++ * NarcolepticFrog, nessie, and Pokechu22. ++ * ++ * - The forward direction is determined locally. So when there are branches in the redstone wire, the left one will get updated ++ * before the right one. Each branch can have its own relative forward direction, resulting in the left side of a left branch ++ * having priority over the right branch of a left branch, which has priority over the left branch of a right branch, followed ++ * by the right branch of a right branch. And so forth. Since redstone power reduces to zero after a path distance of 15, ++ * that imposes a practical limit on the branching. Note that the branching is not tracked explicitly -- relative forward ++ * directions dictate relative sort order, which maintains the proper global ordering. This also makes it unnecessary to be ++ * concerned about branches meeting up with each other. ++ * ++ * ^ ++ * | ++ * Forward ++ * <-- Left Right --> ++ * ++ * 18 ++ * 10 17 5 19 11 ++ * 2 8 0 12 16 4 C 6 20 9 1 13 3 ++ * 14 21 7 23 15 ++ * Further 22 Further ++ * Down Down Up Up ++ * ++ * Backward ++ * | ++ * V ++ */ ++ ++ // This allows the above remapping tables to be looked up by cardial direction index ++ private static final int[][] reordering = { forward_is_north, forward_is_east, forward_is_south, forward_is_west }; ++ ++ /* ++ * Input: Array of UpdateNode objects in an order corresponding to the positions ++ * computed by computeAllNeighbors above. ++ * Output: Array of UpdateNode objects oriented using the above remapping tables ++ * corresponding to the identified heading (direction of information flow). ++ */ ++ private static void orientNeighbors(final UpdateNode[] src, final UpdateNode[] dst, final int heading) { ++ final int[] re = reordering[heading]; ++ for (int i = 0; i < 24; i++) { ++ dst[i] = src[re[i]]; ++ } ++ } ++ ++ /* ++ * Structure to keep track of redstone wire blocks and ++ * neighbors that will receive updates. ++ */ ++ private static class UpdateNode { ++ public static enum Type { ++ UNKNOWN, REDSTONE, OTHER ++ } ++ ++ BlockState currentState; // Keep track of redstone wire value ++ UpdateNode[] neighbor_nodes; // References to neighbors (directed graph edges) ++ BlockPos self; // UpdateNode's own position ++ BlockPos parent; // Which block pos spawned/updated this node ++ Type type = Type.UNKNOWN; // unknown, redstone wire, other type of block ++ int layer; // Highest layer this node is scheduled in ++ boolean visited; // To keep track of information flow direction, visited restone wire is marked ++ int xbias, zbias; // Remembers directionality of ancestor nodes; helps eliminate directional ambiguities. ++ } ++ ++ /* ++ * Keep track of all block positions discovered during search and their current states. ++ * We want to remember one entry for each position. ++ */ ++ private final Map nodeCache = Maps.newHashMap(); ++ ++ /* ++ * For a newly created UpdateNode object, determine what type of block it is. ++ */ ++ private void identifyNode(final Level worldIn, final UpdateNode upd1) { ++ final BlockPos pos = upd1.self; ++ final BlockState oldState = worldIn.getBlockState(pos); ++ upd1.currentState = oldState; ++ ++ // Some neighbors of redstone wire are other kinds of blocks. ++ // These need to receive block updates to inform them that ++ // redstone wire values have changed. ++ final Block block = oldState.getBlock(); ++ if (block != wire) { ++ // Mark this block as not redstone wire and therefore ++ // requiring updates ++ upd1.type = UpdateNode.Type.OTHER; ++ ++ // Non-redstone blocks may propagate updates, but those updates ++ // are not handled by this accelerator. Therefore, we do not ++ // expand this position's neighbors. ++ return; ++ } ++ ++ // One job of BlockRedstoneWire.neighborChanged is to convert ++ // redstone wires to items if the block beneath was removed. ++ // With this accelerator, BlockRedstoneWire.neighborChanged ++ // is only typically called for a single wire block, while ++ // others are processed internally by the breadth first search ++ // algorithm. To preserve this game behavior, this check must ++ // be replicated here. ++ if (!wire.canSurvive(null, worldIn, pos)) { ++ // Pop off the redstone dust ++ Block.popResource(worldIn, pos, new ItemStack(Items.REDSTONE)); // TODO ++ worldIn.setAir(pos); ++ ++ // Mark this position as not being redstone wire ++ upd1.type = UpdateNode.Type.OTHER; ++ ++ // Note: Sending updates to air blocks leads to an empty method. ++ // Testing shows this to be faster than explicitly avoiding updates to ++ // air blocks. ++ return; ++ } ++ ++ // If the above conditions fail, then this is a redstone wire block. ++ upd1.type = UpdateNode.Type.REDSTONE; ++ } ++ ++ /* ++ * Given which redstone wire blocks have been visited and not visited ++ * around the position currently being updated, compute the cardinal ++ * direction that is "forward." ++ * ++ * rx is the forward direction along the West/East axis ++ * rz is the forward direction along the North/South axis ++ */ ++ static private int computeHeading(final int rx, final int rz) { ++ // rx and rz can only take on values -1, 0, and 1, so we can ++ // compute a code number that allows us to use a single switch ++ // to determine the heading. ++ final int code = (rx + 1) + 3 * (rz + 1); ++ switch (code) { ++ case 0: { ++ // Both rx and rz are -1 (northwest) ++ // Randomly choose one to be forward. ++ final int j = ThreadLocalRandom.current().nextInt(0, 1); ++ return (j == 0) ? North : West; ++ } ++ case 1: { ++ // rx=0, rz=-1 ++ // Definitively North ++ return North; ++ } ++ case 2: { ++ // rx=1, rz=-1 (northeast) ++ // Choose randomly between north and east ++ final int j = ThreadLocalRandom.current().nextInt(0, 1); ++ return (j == 0) ? North : East; ++ } ++ case 3: { ++ // rx=-1, rz=0 ++ // Definitively West ++ return West; ++ } ++ case 4: { ++ // rx=0, rz=0 ++ // Heading is completely ambiguous. Choose ++ // randomly among the four cardinal directions. ++ return ThreadLocalRandom.current().nextInt(0, 4); ++ } ++ case 5: { ++ // rx=1, rz=0 ++ // Definitively East ++ return East; ++ } ++ case 6: { ++ // rx=-1, rz=1 (southwest) ++ // Choose randomly between south and west ++ final int j = ThreadLocalRandom.current().nextInt(0, 1); ++ return (j == 0) ? South : West; ++ } ++ case 7: { ++ // rx=0, rz=1 ++ // Definitively South ++ return South; ++ } ++ case 8: { ++ // rx=1, rz=1 (southeast) ++ // Choose randomly between south and east ++ final int j = ThreadLocalRandom.current().nextInt(0, 1); ++ return (j == 0) ? South : East; ++ } ++ } ++ ++ // We should never get here ++ return ThreadLocalRandom.current().nextInt(0, 4); ++ } ++ ++ // Select whether to use updateSurroundingRedstone from BlockRedstoneWire (old) ++ // or this helper class (new) ++ private static final boolean old_current_change = false; ++ ++ /* ++ * Process a node whose neighboring redstone wire has experienced value changes. ++ */ ++ private void updateNode(final Level worldIn, final UpdateNode upd1, final int layer) { ++ final BlockPos pos = upd1.self; ++ ++ // Mark this redstone wire as having been visited so that it can be used ++ // to calculate direction of information flow. ++ upd1.visited = true; ++ ++ // Look up the last known state. ++ // Due to the way other redstone components are updated, we do not ++ // have to worry about a state changing behind our backs. The rare ++ // exception is handled by scheduleReentrantNeighborChanged. ++ final BlockState oldState = upd1.currentState; ++ ++ // Ask the wire block to compute its power level from its neighbors. ++ // This will also update the wire's power level and return a new ++ // state if it has changed. When a wire power level is changed, ++ // calculateCurrentChanges will immediately update the block state in the world ++ // and return the same value here to be cached in the corresponding ++ // UpdateNode object. ++ BlockState newState; ++ if (old_current_change) { ++ newState = wire.calculateCurrentChanges(worldIn, pos, pos, oldState); ++ } else { ++ // Looking up block state is slow. This accelerator includes a version of ++ // calculateCurrentChanges that uses cahed wire values for a ++ // significant performance boost. ++ newState = this.calculateCurrentChanges(worldIn, upd1); ++ } ++ ++ // Only inform neighbors if the state has changed ++ if (newState != oldState) { ++ // Store the new state ++ upd1.currentState = newState; ++ ++ // Inform neighbors of the change ++ propagateChanges(worldIn, upd1, layer); ++ } ++ } ++ ++ /* ++ * This identifies the neighboring positions of a new UpdateNode object, ++ * determines their types, and links those to into the graph. Then based on ++ * what nodes in the redstone wire graph have been visited, the neighbors ++ * are reordered left-to-right relative to the direction of information flow. ++ */ ++ private void findNeighbors(final Level worldIn, final UpdateNode upd1) { ++ final BlockPos pos = upd1.self; ++ ++ // Get the list of neighbor coordinates ++ final BlockPos[] neighbors = computeAllNeighbors(pos); ++ ++ // Temporary array of neighbors in cardinal ordering ++ final UpdateNode[] neighbor_nodes = new UpdateNode[24]; ++ ++ // Target array of neighbors sorted left-to-right ++ upd1.neighbor_nodes = new UpdateNode[24]; ++ ++ for (int i=0; i<24; i++) { ++ // Look up each neighbor in the node cache ++ final BlockPos pos2 = neighbors[i]; ++ UpdateNode upd2 = nodeCache.get(pos2); ++ if (upd2 == null) { ++ // If this is a previously unreached position, create ++ // a new update node, add it to the cache, and identify what it is. ++ upd2 = new UpdateNode(); ++ upd2.self = pos2; ++ upd2.parent = pos; ++ nodeCache.put(pos2, upd2); ++ identifyNode(worldIn, upd2); ++ } ++ ++ // For non-redstone blocks, any of the 24 neighboring positions ++ // should receive a block update. However, some block coordinates ++ // may contain a redstone wire that does not directly connect to the ++ // one being expanded. To avoid redundant calculations and confusing ++ // cross-talk, those neighboring positions are not included. ++ if (update_redstone[i] || upd2.type != UpdateNode.Type.REDSTONE) { ++ neighbor_nodes[i] = upd2; ++ } ++ } ++ ++ // Determine the directions from which the redstone signal may have come from. This ++ // checks for redstone wire at the same Y level and also Y+1 and Y-1, relative to the ++ // block being expanded. ++ final boolean fromWest = (neighbor_nodes[0].visited || neighbor_nodes[7].visited || neighbor_nodes[8].visited); ++ final boolean fromEast = (neighbor_nodes[1].visited || neighbor_nodes[12].visited || neighbor_nodes[13].visited); ++ final boolean fromNorth = (neighbor_nodes[4].visited || neighbor_nodes[17].visited || neighbor_nodes[20].visited); ++ final boolean fromSouth = (neighbor_nodes[5].visited || neighbor_nodes[18].visited || neighbor_nodes[21].visited); ++ ++ int cx = 0, cz = 0; ++ if (fromWest) cx += 1; ++ if (fromEast) cx -= 1; ++ if (fromNorth) cz += 1; ++ if (fromSouth) cz -= 1; ++ ++ int heading; ++ if (cx==0 && cz==0) { ++ // If there is no clear direction, try to inherit the heading from ancestor nodes. ++ heading = computeHeading(upd1.xbias, upd1.zbias); ++ ++ // Propagate that heading to descendant nodes. ++ for (int i=0; i<24; i++) { ++ final UpdateNode nn = neighbor_nodes[i]; ++ if (nn != null) { ++ nn.xbias = upd1.xbias; ++ nn.zbias = upd1.zbias; ++ } ++ } ++ } else { ++ if (cx != 0 && cz != 0) { ++ // If the heading is somewhat ambiguous, try to disambiguate based on ++ // ancestor nodes. ++ if (upd1.xbias != 0) cz = 0; ++ if (upd1.zbias != 0) cx = 0; ++ } ++ heading = computeHeading(cx, cz); ++ ++ // Propagate that heading to descendant nodes. ++ for (int i=0; i<24; i++) { ++ final UpdateNode nn = neighbor_nodes[i]; ++ if (nn != null) { ++ nn.xbias = cx; ++ nn.zbias = cz; ++ } ++ } ++ } ++ ++ // Reorder neighboring UpdateNode objects according to the forward direction ++ // determined above. ++ orientNeighbors(neighbor_nodes, upd1.neighbor_nodes, heading); ++ } ++ ++ /* ++ * For any redstone wire block in layer N, inform neighbors to recompute their states ++ * in layers N+1 and N+2; ++ */ ++ private void propagateChanges(final Level worldIn, final UpdateNode upd1, final int layer) { ++ if (upd1.neighbor_nodes == null) { ++ // If this node has not been expanded yet, find its neighbors ++ findNeighbors(worldIn, upd1); ++ } ++ ++ final BlockPos pos = upd1.self; ++ ++ // All neighbors may be scheduled for layer N+1 ++ final int layer1 = layer + 1; ++ ++ // If the node being updated (upd1) has already been expanded, then merely ++ // schedule updates to its neighbors. ++ for (int i = 0; i < 24; i++) { ++ final UpdateNode upd2 = upd1.neighbor_nodes[i]; ++ ++ // This test ensures that an UpdateNode is never scheduled to the same layer ++ // more than once. Also, skip non-connecting redstone wire blocks ++ if (upd2 != null && layer1 > upd2.layer) { ++ upd2.layer = layer1; ++ updateQueue1.add(upd2); ++ ++ // Keep track of which block updated this neighbor ++ upd2.parent = pos; ++ } ++ } ++ ++ // Nodes above and below are scheduled ALSO for layer N+2 ++ final int layer2 = layer + 2; ++ ++ // Repeat of the loop above, but only for the first four (above and below) neighbors ++ // and for layer N+2; ++ for (int i = 0; i < 4; i++) { ++ final UpdateNode upd2 = upd1.neighbor_nodes[i]; ++ if (upd2 != null && layer2 > upd2.layer) { ++ upd2.layer = layer2; ++ updateQueue2.add(upd2); ++ upd2.parent = pos; ++ } ++ } ++ } ++ ++ // The breadth-first search below will send block updates to blocks ++ // that are not redstone wire. If one of those updates results in ++ // a distant redstone wire getting an update, then this.neighborChanged ++ // will get called. This would be a reentrant call, and ++ // it is necessary to properly integrate those updates into the ++ // on-going search through redstone wire. Thus, we make the layer ++ // currently being processed visible at the object level. ++ ++ // The current layer being processed by the breadth-first search ++ private int currentWalkLayer = 0; ++ ++ private void shiftQueue() { ++ final List t = updateQueue0; ++ t.clear(); ++ updateQueue0 = updateQueue1; ++ updateQueue1 = updateQueue2; ++ updateQueue2 = t; ++ } ++ ++ /* ++ * Perform a breadth-first (layer by layer) traversal through redstone ++ * wire blocks, propagating value changes to neighbors in an order ++ * that is a function of distance from the initial call to ++ * this.neighborChanged. ++ */ ++ private void breadthFirstWalk(final Level worldIn) { ++ shiftQueue(); ++ currentWalkLayer = 1; ++ ++ // Loop over all layers ++ while (updateQueue0.size()>0 || updateQueue1.size()>0) { ++ // Get the set of blocks in this layer ++ final List thisLayer = updateQueue0; ++ ++ // Loop over all blocks in the layer. Recall that ++ // this is a List, preserving the insertion order of ++ // left-to-right based on direction of information flow. ++ for (UpdateNode upd : thisLayer) { ++ if (upd.type == UpdateNode.Type.REDSTONE) { ++ // If the node is is redstone wire, ++ // schedule updates to neighbors if its value ++ // has changed. ++ updateNode(worldIn, upd, currentWalkLayer); ++ } else { ++ // If this block is not redstone wire, send a block update. ++ // Redstone wire blocks get state updates, but they don't ++ // need block updates. Only non-redstone neighbors need updates. ++ ++ // World.neighborChanged is called from ++ // World.notifyNeighborsOfStateChange, and ++ // notifyNeighborsOfStateExcept. We don't use ++ // World.notifyNeighborsOfStateChange here, since we are ++ // already keeping track of all of the neighbor positions ++ // that need to be updated. All on its own, handling neighbors ++ // this way reduces block updates by 1/3 (24 instead of 36). ++ worldIn.neighborChanged(upd.self, wire, upd.parent); ++ } ++ } ++ ++ // Move on to the next layer ++ shiftQueue(); ++ currentWalkLayer++; ++ } ++ ++ currentWalkLayer = 0; ++ } ++ ++ /* ++ * Normally, when Minecraft is computing redstone wire power changes, and a wire power level ++ * change sends a block update to a neighboring functional component (e.g. piston, repeater, etc.), ++ * those updates are queued. Only once all redstone wire updates are complete will any component ++ * action generate any further block updates to redstone wire. Instant repeater lines, for instance, ++ * will process all wire updates for one redstone line, after which the pistons will zero-tick, ++ * after which the next redstone line performs all of its updates. Thus, each wire is processed in its ++ * own discrete wave. ++ * ++ * However, there are some corner cases where this pattern breaks, with a proof of concept discovered ++ * by Rays Works, which works the same in vanilla. The scenario is as follows: ++ * (1) A redstone wire is conducting a signal. ++ * (2) Part-way through that wave of updates, a neighbor is updated that causes an update to a completely ++ * separate redstone wire. ++ * (3) This results in a call to BlockRedstoneWire.neighborChanged for that other wire, in the middle of ++ * an already on-going propagation through the first wire. ++ * ++ * The vanilla code, being depth-first, would end up fully processing the second wire before going back ++ * to finish processing the first one. (Although technically, vanilla has no special concept of "being ++ * in the middle" of processing updates to a wire.) For the breadth-first algorithm, we give this ++ * situation special handling, where the updates for the second wire are incorporated into the schedule ++ * for the first wire, and then the callstack is allowed to unwind back to the on-going search loop in ++ * order to continue processing both the first and second wire in the order of distance from the initial ++ * trigger. ++ */ ++ private BlockState scheduleReentrantNeighborChanged(final Level worldIn, final BlockPos pos, final BlockState newState, final BlockPos source) { ++ if (source != null) { ++ // If the cause of the redstone wire update is known, we can use that to help determine ++ // direction of information flow. ++ UpdateNode src = nodeCache.get(source); ++ if (src == null) { ++ src = new UpdateNode(); ++ src.self = source; ++ src.parent = source; ++ src.visited = true; ++ identifyNode(worldIn, src); ++ nodeCache.put(source, src); ++ } ++ } ++ ++ // Find or generate a node for the redstone block position receiving the update ++ UpdateNode upd = nodeCache.get(pos); ++ if (upd == null) { ++ upd = new UpdateNode(); ++ upd.self = pos; ++ upd.parent = pos; ++ upd.visited = true; ++ identifyNode(worldIn, upd); ++ nodeCache.put(pos, upd); ++ } ++ upd.currentState = newState; ++ ++ // Receiving this block update may mean something in the world changed. ++ // Therefore we clear the cached block info about all neighbors of ++ // the position receiving the update and then re-identify what they are. ++ if (upd.neighbor_nodes != null) { ++ for (int i=0; i<24; i++) { ++ final UpdateNode upd2 = upd.neighbor_nodes[i]; ++ if (upd2 == null) continue; ++ upd2.type = UpdateNode.Type.UNKNOWN; ++ upd2.currentState = null; ++ identifyNode(worldIn, upd2); ++ } ++ } ++ ++ // The block at 'pos' is a redstone wire and has been updated already by calling ++ // wire.calculateCurrentChanges, so we don't schedule that. However, we do need ++ // to schedule its neighbors. By passing the current value of 'currentWalkLayer' to ++ // propagateChanges, the neighbors of 'pos' are scheduled for layers currentWalkLayer+1 ++ // and currentWalkLayer+2. ++ propagateChanges(worldIn, upd, currentWalkLayer); ++ ++ // Return here. The call stack will unwind back to the first call to ++ // updateSurroundingRedstone, whereupon the new updates just scheduled will ++ // be propagated. This also facilitates elimination of superfluous and ++ // redundant block updates. ++ return newState; ++ } ++ ++ /* ++ * New version of pre-existing updateSurroundingRedstone, which is called from ++ * wire.updateSurroundingRedstone, which is called from wire.neighborChanged and a ++ * few other methods in BlockRedstoneWire. This sets off the breadth-first ++ * walk through all redstone dust connected to the initial position triggered. ++ */ ++ public BlockState updateSurroundingRedstone(final Level worldIn, final BlockPos pos, final BlockState state, final BlockPos source) { ++ // Check this block's neighbors and see if its power level needs to change ++ // Use the calculateCurrentChanges method in BlockRedstoneWire since we have no ++ // cached block states at this point. ++ final BlockState newState = wire.calculateCurrentChanges(worldIn, pos, pos, state); ++ ++ // If no change, exit ++ if (newState == state) { ++ return state; ++ } ++ ++ // Check to see if this update was received during an on-going breadth first search ++ if (currentWalkLayer > 0 || nodeCache.size() > 0) { ++ // As breadthFirstWalk progresses, it sends block updates to neighbors. Some of those ++ // neighbors may affect the world so as to cause yet another redstone wire block to receive ++ // an update. If that happens, we need to integrate those redstone wire updates into the ++ // already on-going graph walk being performed by breadthFirstWalk. ++ return scheduleReentrantNeighborChanged(worldIn, pos, newState, source); ++ } ++ // If there are no on-going walks through redstone wire, then start a new walk. ++ ++ // If the source of the block update to the redstone wire at 'pos' is known, we can use ++ // that to help determine the direction of information flow. ++ if (source != null) { ++ final UpdateNode src = new UpdateNode(); ++ src.self = source; ++ src.parent = source; ++ src.visited = true; ++ nodeCache.put(source, src); ++ identifyNode(worldIn, src); ++ } ++ ++ // Create a node representing the block at 'pos', and then propagate updates ++ // to its neighbors. As stated above, the call to wire.calculateCurrentChanges ++ // already performs the update to the block at 'pos', so it is not added to the schedule. ++ final UpdateNode upd = new UpdateNode(); ++ upd.self = pos; ++ upd.parent = source!=null ? source : pos; ++ upd.currentState = newState; ++ upd.type = UpdateNode.Type.REDSTONE; ++ upd.visited = true; ++ nodeCache.put(pos, upd); ++ propagateChanges(worldIn, upd, 0); ++ ++ // Perform the walk over all directly reachable redstone wire blocks, propagating wire value ++ // updates in a breadth first order out from the initial update received for the block at 'pos'. ++ breadthFirstWalk(worldIn); ++ ++ // With the whole search completed, clear the list of all known blocks. ++ // We do not want to keep around state information that may be changed by other code. ++ // In theory, we could cache the neighbor block positions, but that is a separate ++ // optimization. ++ nodeCache.clear(); ++ ++ return newState; ++ } ++ ++ // For any array of neighbors in an UpdateNode object, these are always ++ // the indices of the four immediate neighbors at the same Y coordinate. ++ private static final int[] rs_neighbors = {4, 5, 6, 7}; ++ private static final int[] rs_neighbors_up = {9, 11, 13, 15}; ++ private static final int[] rs_neighbors_dn = {8, 10, 12, 14}; ++ ++ /* ++ * Updated calculateCurrentChanges that is optimized for speed and uses ++ * the UpdateNode's neighbor array to find the redstone states of neighbors ++ * that might power it. ++ */ ++ private BlockState calculateCurrentChanges(final Level worldIn, final UpdateNode upd) { ++ BlockState state = upd.currentState; ++ final int i = state.getValue(RedStoneWireBlock.POWER).intValue(); ++ int j = 0; ++ j = getMaxCurrentStrength(upd, j); ++ int l = 0; ++ ++ wire.setCanProvidePower(false); ++ // Unfortunately, World.isBlockIndirectlyGettingPowered is complicated, ++ // and I'm not ready to try to replicate even more functionality from ++ // elsewhere in Minecraft into this accelerator. So sadly, we must ++ // suffer the performance hit of this very expensive call. If there ++ // is consistency to what this call returns, we may be able to cache it. ++ final int k = worldIn.isBlockIndirectlyGettingPowered(upd.self); ++ wire.setCanProvidePower(true); ++ ++ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. ++ // If 'k' has the highest level of all neighbors, then the power level of this ++ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the ++ // following loop can affect the power level of the wire. Therefore, the loop is ++ // skipped if k is already 15. ++ if (k < 15) { ++ if (upd.neighbor_nodes == null) { ++ // If this node's neighbors are not known, expand the node ++ findNeighbors(worldIn, upd); ++ } ++ ++ // These remain constant, so pull them out of the loop. ++ // Regardless of which direction is forward, the UpdateNode for the ++ // position directly above the node being calculated is always ++ // at index 1. ++ UpdateNode center_up = upd.neighbor_nodes[1]; ++ boolean center_up_is_cube = center_up.currentState.isRedstoneConductor(worldIn, center_up.self); // TODO ++ ++ for (int m = 0; m < 4; m++) { ++ // Get the neighbor array index of each of the four cardinal ++ // neighbors. ++ int n = rs_neighbors[m]; ++ ++ // Get the max redstone power level of each of the cardinal ++ // neighbors ++ UpdateNode neighbor = upd.neighbor_nodes[n]; ++ l = getMaxCurrentStrength(neighbor, l); ++ ++ // Also check the positions above and below the cardinal ++ // neighbors ++ boolean neighbor_is_cube = neighbor.currentState.isRedstoneConductor(worldIn, neighbor.self); // TODO ++ if (!neighbor_is_cube) { ++ UpdateNode neighbor_down = upd.neighbor_nodes[rs_neighbors_dn[m]]; ++ l = getMaxCurrentStrength(neighbor_down, l); ++ } else ++ if (!center_up_is_cube) { ++ UpdateNode neighbor_up = upd.neighbor_nodes[rs_neighbors_up[m]]; ++ l = getMaxCurrentStrength(neighbor_up, l); ++ } ++ } ++ } ++ ++ // The new code sets this RedstoneWire block's power level to the highest neighbor ++ // minus 1. This usually results in wire power levels dropping by 2 at a time. ++ // This optimization alone has no impact on update order, only the number of updates. ++ j = l - 1; ++ ++ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will ++ // always be in the range of 0 to 15, the following if will correct that. ++ if (k > j) j = k; ++ ++ // egg82's amendment ++ // Adding Bukkit's BlockRedstoneEvent - er.. event. ++ if (i != j) { ++ BlockRedstoneEvent event = new BlockRedstoneEvent(worldIn.getWorld().getBlockAt(upd.self.getX(), upd.self.getY(), upd.self.getZ()), i, j); ++ worldIn.getCraftServer().getPluginManager().callEvent(event); ++ j = event.getNewCurrent(); ++ } ++ ++ if (i != j) { ++ // If the power level has changed from its previous value, compute a new state ++ // and set it in the world. ++ // Possible optimization: Don't commit state changes to the world until they ++ // need to be known by some nearby non-redstone-wire block. ++ BlockPos pos = new BlockPos(upd.self.getX(), upd.self.getY(), upd.self.getZ()); ++ if (wire.canSurvive(null, worldIn, pos)) { ++ state = state.setValue(RedStoneWireBlock.POWER, Integer.valueOf(j)); ++ worldIn.setBlock(upd.self, state, 2); ++ } ++ } ++ ++ return state; ++ } ++ ++ /* ++ * Optimized function to compute a redstone wire's power level based on cached ++ * state. ++ */ ++ private static int getMaxCurrentStrength(final UpdateNode upd, final int strength) { ++ if (upd.type != UpdateNode.Type.REDSTONE) return strength; ++ final int i = upd.currentState.getValue(RedStoneWireBlock.POWER).intValue(); ++ return i > strength ? i : strength; ++ } ++} +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 9b50b8030174338c04b60d441b980131e1d593e4..ebb92f88e0402681c47834bcf45e6b236748289a 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -659,6 +659,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + } + ++ public void neighborChanged(BlockPos pos, Block blockIn, BlockPos fromPos) { neighborChanged(pos, blockIn, fromPos); } // Paper - OBFHELPER + public void neighborChanged(BlockPos sourcePos, Block sourceBlock, BlockPos neighborPos) { + if (!this.isClientSide) { + BlockState iblockdata = this.getBlockState(sourcePos); +@@ -1287,6 +1288,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return this.getSignal(pos.below(), Direction.DOWN) > 0 ? true : (this.getSignal(pos.above(), Direction.UP) > 0 ? true : (this.getSignal(pos.north(), Direction.NORTH) > 0 ? true : (this.getSignal(pos.south(), Direction.SOUTH) > 0 ? true : (this.getSignal(pos.west(), Direction.WEST) > 0 ? true : this.getSignal(pos.east(), Direction.EAST) > 0)))); + } + ++ public int isBlockIndirectlyGettingPowered(BlockPos pos) { return this.getBestNeighborSignal(pos); } // Paper - OBFHELPER + public int getBestNeighborSignal(BlockPos pos) { + int i = 0; + Direction[] aenumdirection = Level.DIRECTIONS; +diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java +index 7318536fe89cddda305007a9ab115970bf18f65d..e5558b73c6159e4c1901d286535a7875924434e9 100644 +--- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.level.block; + ++import com.destroystokyo.paper.PaperConfig; ++import com.destroystokyo.paper.util.RedstoneWireTurbo; + import com.google.common.collect.ImmutableMap; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; +@@ -49,7 +51,7 @@ public class RedStoneWireBlock extends Block { + private final Map SHAPES_CACHE = Maps.newHashMap(); + private static final Vector3f[] COLORS = new Vector3f[16]; + private final BlockState crossState; +- private boolean shouldSignal = true; ++ private boolean shouldSignal = true; public final boolean canProvidePower() { return this.shouldSignal; } public final void setCanProvidePower(boolean value) { this.shouldSignal = value; } // Paper - OBFHELPER + + public RedStoneWireBlock(BlockBehaviour.Properties settings) { + super(settings); +@@ -236,6 +238,121 @@ public class RedStoneWireBlock extends Block { + return floor.isFaceSturdy(world, pos, Direction.UP) || floor.is(Blocks.HOPPER); + } + ++ // Paper start - Optimize redstone ++ // The bulk of the new functionality is found in RedstoneWireTurbo.java ++ RedstoneWireTurbo turbo = new RedstoneWireTurbo(this); ++ ++ /* ++ * Modified version of pre-existing updateSurroundingRedstone, which is called from ++ * this.neighborChanged and a few other methods in this class. ++ * Note: Added 'source' argument so as to help determine direction of information flow ++ */ ++ private void updateSurroundingRedstone(Level worldIn, BlockPos pos, BlockState state, BlockPos source) { ++ if (worldIn.paperConfig.useEigencraftRedstone) { ++ turbo.updateSurroundingRedstone(worldIn, pos, state, source); ++ return; ++ } ++ updatePowerStrength(worldIn, pos, state); ++ } ++ ++ /* ++ * Slightly modified method to compute redstone wire power levels from neighboring blocks. ++ * Modifications cut the number of power level changes by about 45% from vanilla, and this ++ * optimization synergizes well with the breadth-first search implemented in ++ * RedstoneWireTurbo. ++ * Note: RedstoneWireTurbo contains a faster version of this code. ++ * Note: Made this public so that RedstoneWireTurbo can access it. ++ */ ++ public BlockState calculateCurrentChanges(Level worldIn, BlockPos pos1, BlockPos pos2, BlockState state) { ++ BlockState iblockstate = state; ++ int i = state.getValue(POWER); ++ int j = 0; ++ j = this.getPower(j, worldIn.getBlockState(pos2)); ++ this.setCanProvidePower(false); ++ int k = worldIn.isBlockIndirectlyGettingPowered(pos1); ++ this.setCanProvidePower(true); ++ ++ if (!worldIn.paperConfig.useEigencraftRedstone) { ++ // This code is totally redundant to if statements just below the loop. ++ if (k > 0 && k > j - 1) { ++ j = k; ++ } ++ } ++ ++ int l = 0; ++ ++ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. ++ // If 'k' has the highest level of all neighbors, then the power level of this ++ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the ++ // following loop can affect the power level of the wire. Therefore, the loop is ++ // skipped if k is already 15. ++ if (!worldIn.paperConfig.useEigencraftRedstone || k < 15) { ++ for (Direction enumfacing : Direction.Plane.HORIZONTAL) { ++ BlockPos blockpos = pos1.relative(enumfacing); ++ boolean flag = blockpos.getX() != pos2.getX() || blockpos.getZ() != pos2.getZ(); ++ ++ if (flag) { ++ l = this.getPower(l, worldIn.getBlockState(blockpos)); ++ } ++ ++ if (worldIn.getBlockState(blockpos).isRedstoneConductor(worldIn, blockpos) && !worldIn.getBlockState(pos1.above()).isRedstoneConductor(worldIn, pos1)) { ++ if (flag && pos1.getY() >= pos2.getY()) { ++ l = this.getPower(l, worldIn.getBlockState(blockpos.above())); ++ } ++ } else if (!worldIn.getBlockState(blockpos).isRedstoneConductor(worldIn, blockpos) && flag && pos1.getY() <= pos2.getY()) { ++ l = this.getPower(l, worldIn.getBlockState(blockpos.below())); ++ } ++ } ++ } ++ ++ if (!worldIn.paperConfig.useEigencraftRedstone) { ++ // The old code would decrement the wire value only by 1 at a time. ++ if (l > j) { ++ j = l - 1; ++ } else if (j > 0) { ++ --j; ++ } else { ++ j = 0; ++ } ++ ++ if (k > j - 1) { ++ j = k; ++ } ++ } else { ++ // The new code sets this RedstoneWire block's power level to the highest neighbor ++ // minus 1. This usually results in wire power levels dropping by 2 at a time. ++ // This optimization alone has no impact on update order, only the number of updates. ++ j = l - 1; ++ ++ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will ++ // always be in the range of 0 to 15, the following if will correct that. ++ if (k > j) j = k; ++ } ++ ++ if (i != j) { ++ state = state.setValue(POWER, j); ++ ++ if (worldIn.getBlockState(pos1) == iblockstate) { ++ worldIn.setBlock(pos1, state, 2); ++ } ++ ++ // 1.16(.1?) dropped the need for blocks needing updates. ++ // Whether this is necessary after all is to be seen. ++// if (!worldIn.paperConfig.useEigencraftRedstone) { ++// // The new search algorithm keeps track of blocks needing updates in its own data structures, ++// // so only add anything to blocksNeedingUpdate if we're using the vanilla update algorithm. ++// this.getBlocksNeedingUpdate().add(pos1); ++// ++// for (EnumDirection enumfacing1 : EnumDirection.values()) { ++// this.getBlocksNeedingUpdate().add(pos1.shift(enumfacing1)); ++// } ++// } ++ } ++ ++ return state; ++ } ++ // Paper end ++ + private void updatePowerStrength(Level world, BlockPos pos, BlockState state) { + int i = this.calculateTargetStrength(world, pos); + +@@ -305,6 +422,8 @@ public class RedStoneWireBlock extends Block { + return Math.max(i, j - 1); + } + ++ private int getPower(int min, BlockState iblockdata) { return Math.max(min, getPower(iblockdata)); } // Paper - Optimize redstone ++ private int getPower(BlockState iblockdata) { return this.getWireSignal(iblockdata); } // Paper - OBFHELPER + private int getWireSignal(BlockState state) { + return state.is((Block) this) ? (Integer) state.getValue(RedStoneWireBlock.POWER) : 0; + } +@@ -327,7 +446,7 @@ public class RedStoneWireBlock extends Block { + @Override + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + if (!oldState.is(state.getBlock()) && !world.isClientSide) { +- this.updatePowerStrength(world, pos, state); ++ this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone + Iterator iterator = Direction.Plane.VERTICAL.iterator(); + + while (iterator.hasNext()) { +@@ -354,7 +473,7 @@ public class RedStoneWireBlock extends Block { + world.updateNeighborsAt(pos.relative(enumdirection), this); + } + +- this.updatePowerStrength(world, pos, state); ++ this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone + this.updateNeighborsOfNeighboringWires(world, pos); + } + } +@@ -389,7 +508,7 @@ public class RedStoneWireBlock extends Block { + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { + if (!world.isClientSide) { + if (state.canSurvive(world, pos)) { +- this.updatePowerStrength(world, pos, state); ++ this.updateSurroundingRedstone(world, pos, state, fromPos); // Paper - Optimize redstone + } else { + dropResources(state, world, pos); + world.removeBlock(pos, false); diff --git a/Remapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch b/Remapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch new file mode 100644 index 0000000000..dfda54388f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Thu, 27 Aug 2020 16:57:25 -0400 +Subject: [PATCH] Fix hex colors not working in some kick messages + + +diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 6f98be2b9b00f71dd041e7511c70166fdecf0749..c648b73a4c478f9d8020274205d6684f7c7c416f 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -50,7 +50,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + synchronized (throttleTracker) { + if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { + throttleTracker.put(address, currentTime); +- TranslatableComponent chatmessage = new TranslatableComponent(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message ++ Component chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage, true)[0]; // Paper - Configurable connection throttle kick message // Paper - Fix hex colors not working in some kick messages + this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); + this.connection.disconnect(chatmessage); + return; +@@ -76,12 +76,12 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + } + // CraftBukkit end + if (packet.getProtocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { +- TranslatableComponent chatmessage; ++ Component chatmessage; // Paper - Fix hex colors not working in some kick messages + + if (packet.getProtocolVersion() < 754) { +- chatmessage = new TranslatableComponent( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) ); // Spigot ++ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages + } else { +- chatmessage = new TranslatableComponent( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) ); // Spigot ++ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages + } + + this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); +@@ -99,7 +99,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + if (event.callEvent()) { + // If we've failed somehow, let the client know so and go no further. + if (event.isFailed()) { +- chatmessage = new TranslatableComponent(event.getFailMessage()); ++ Component chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(event.getFailMessage(), true)[0]; // Paper - Fix hex colors not working in some kick messages + this.getNetworkManager().send(new ClientboundLoginDisconnectPacket(chatmessage)); + this.getNetworkManager().disconnect(chatmessage); + return; +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 659bf14cf3c949b896d0333f893a3d5e16ab9c92..573963a09f15046cfcaab83aef906801ce70d75a 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -104,14 +104,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + // CraftBukkit start + @Deprecated + public void disconnect(String s) { +- try { +- Component ichatbasecomponent = new TextComponent(s); +- ServerLoginPacketListenerImpl.LOGGER.info("Disconnecting {}: {}", this.getUserName(), s); +- this.connection.send(new ClientboundLoginDisconnectPacket(ichatbasecomponent)); +- this.connection.disconnect(ichatbasecomponent); +- } catch (Exception exception) { +- ServerLoginPacketListenerImpl.LOGGER.error("Error whilst disconnecting player", exception); +- } ++ disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s, true)[0]); // Paper - Fix hex colors not working in some kick messages + } + // CraftBukkit end + diff --git a/Remapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch b/Remapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch new file mode 100644 index 0000000000..0287c9ed0f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Fri, 21 Aug 2020 20:57:54 +0200 +Subject: [PATCH] PortalCreateEvent needs to know its entity + + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 04b717326524f400da3562655c25db59e72814ec..a9256fc4a0bc3cd277cb372a9c090028e03482f5 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -366,7 +366,7 @@ public final class ItemStack { + net.minecraft.world.level.block.state.BlockState block = world.getBlockState(newblockposition); + + if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically +- block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); ++ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true, itemactioncontext); // Paper - pass itemactioncontext + } + + world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point +diff --git a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +index cd005f7dbfcaf3cebae3a92da36e0d40c93dbf79..ad37261e716b15d62fc2083d137cdac818308cdd 100644 +--- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +@@ -7,6 +7,7 @@ import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.BlockPlaceContext; ++import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; +@@ -66,20 +67,23 @@ public abstract class BaseFireBlock extends Block { + super.entityInside(state, world, pos, entity); + } + ++ // Paper start - ItemActionContext param ++ @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { this.onPlace(state, world, pos, oldState, notify, null); } + @Override +- public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { +- if (!oldState.is(state.getBlock())) { ++ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { ++ // Paper end ++ if (!iblockdata1.is(iblockdata.getBlock())) { + if (inPortalDimension(world)) { +- Optional optional = PortalShape.findEmptyPortalShape((LevelAccessor) world, pos, Direction.Axis.X); ++ Optional optional = PortalShape.findEmptyPortalShape((LevelAccessor) world, blockposition, Direction.Axis.X); + + if (optional.isPresent()) { +- ((PortalShape) optional.get()).createPortal(); ++ ((PortalShape) optional.get()).createPortal(itemActionContext); // Paper - pass ItemActionContext param + return; + } + } + +- if (!state.canSurvive(world, pos)) { +- fireExtinguished(world, pos); // CraftBukkit - fuel block broke ++ if (!iblockdata.canSurvive(world, blockposition)) { ++ fireExtinguished(world, blockposition); // CraftBukkit - fuel block broke + } + + } +diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java +index ac63c5bef5b35b158e57835d765bbdd15fc60664..e690e7c366fc087d3b28d61323dcc78bb7154aed 100644 +--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java +@@ -15,6 +15,7 @@ import net.minecraft.core.Vec3i; + import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.item.context.BlockPlaceContext; ++import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +@@ -363,9 +364,11 @@ public class FireBlock extends BaseFireBlock { + } + + @Override +- public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { +- super.onPlace(state, world, pos, oldState, notify); +- world.getBlockTicks().a(pos, this, getFireTickDelay(world.random)); ++ // Paper start - ItemActionContext param ++ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { ++ super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext); ++ // Paper end ++ world.getBlockTicks().a(blockposition, this, getFireTickDelay(world.random)); + } + + private static int getFireTickDelay(Random random) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index df2836b071158729728411f5b228cc38dddd4d4e..f2fefdad26057c722085e60ba837fe2c117f55f7 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -32,6 +32,7 @@ import net.minecraft.world.item.DyeColor; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockPlaceContext; ++import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.EmptyBlockGetter; + import net.minecraft.world.level.Level; +@@ -119,6 +120,12 @@ public abstract class BlockBehaviour { + DebugPackets.sendNeighborsUpdatePacket(world, pos); + } + ++ // Paper start - add ItemActionContext param ++ @Deprecated ++ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { ++ this.onPlace(iblockdata, world, blockposition, iblockdata1, flag); ++ } ++ // Paper end + @Deprecated + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot +diff --git a/src/main/java/net/minecraft/world/level/portal/PortalShape.java b/src/main/java/net/minecraft/world/level/portal/PortalShape.java +index 7a99adbe39ca2566d42ed67dc9d6f609005f3d6f..500744b6383390266efed9e35a000511210cb5b9 100644 +--- a/src/main/java/net/minecraft/world/level/portal/PortalShape.java ++++ b/src/main/java/net/minecraft/world/level/portal/PortalShape.java +@@ -11,6 +11,7 @@ import net.minecraft.tags.BlockTags; + import net.minecraft.tags.Tag; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.NetherPortalBlock; +@@ -181,7 +182,10 @@ public class PortalShape { + } + + // CraftBukkit start - return boolean +- public boolean createPortal() { ++ // Paper start - ItemActionContext param ++ @Deprecated public boolean createPortal() { return this.createPortal(null); } ++ public boolean createPortal(UseOnContext itemActionContext) { ++ // Paper end + org.bukkit.World bworld = this.level.getLevel().getWorld(); + + // Copy below for loop +@@ -190,8 +194,7 @@ public class PortalShape { + BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { + blocks.setBlock(blockposition, iblockdata, 18); + }); +- +- PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); ++ PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, itemActionContext == null || itemActionContext.getPlayer() == null ? null : itemActionContext.getPlayer().getBukkitEntity(), PortalCreateEvent.CreateReason.FIRE); // Paper - pass entity param + this.level.getLevel().getServer().server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { diff --git a/Remapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch b/Remapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch new file mode 100644 index 0000000000..d30a891285 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: foss-mc <69294560+foss-mc@users.noreply.github.com> +Date: Sun, 30 Aug 2020 15:30:29 +0800 +Subject: [PATCH] Fix CraftTeam null check + + +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +index 7ebcba4ada42f5599d56cfdeb75dbf62f2a09b78..222e3d4e379fd5ca50c122f70e90ed11b2f5e1f7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +@@ -253,7 +253,7 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { + + @Override + public boolean hasEntry(String entry) throws IllegalArgumentException, IllegalStateException { +- Validate.notNull("Entry cannot be null"); ++ Validate.notNull(entry, "Entry cannot be null"); // Paper + + CraftScoreboard scoreboard = checkState(); + diff --git a/Remapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch b/Remapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch new file mode 100644 index 0000000000..af8a4c5513 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Aug 2020 15:28:35 +0200 +Subject: [PATCH] Add more Evoker API + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Evoker.java b/src/main/java/net/minecraft/world/entity/monster/Evoker.java +index c0a5b0074480aad717177c92b28fa27b8a1d707d..617075955506500dc2d9c734398c48b8fc10b69d 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Evoker.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Evoker.java +@@ -40,7 +40,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; + + public class Evoker extends SpellcasterIllager { + +- private Sheep wololoTarget; ++ private Sheep wololoTarget; public final Sheep getWololoTarget() { return this.wololoTarget; } public final void setWololoTarget(Sheep sheep) { this.wololoTarget = sheep; } // Paper - OBFHELPER + + public Evoker(EntityType type, Level world) { + super(type, world); +@@ -59,7 +59,7 @@ public class Evoker extends SpellcasterIllager { + this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); +- this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).canUse()); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers(new Class[0])); // Paper - decompile fix + this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); + this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, false)); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java +index 29fec87c938c4252cf5c9473ce9e5c1908ea9063..950e35f67f88138cc2ce923be1ea7976bd317d1f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import net.minecraft.world.entity.animal.Sheep; + import net.minecraft.world.entity.monster.SpellcasterIllager; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; +@@ -35,4 +36,17 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { + public void setCurrentSpell(Evoker.Spell spell) { + getHandle().setIsCastingSpell(spell == null ? SpellcasterIllager.IllagerSpell.NONE : SpellcasterIllager.IllagerSpell.byId(spell.ordinal())); + } ++ ++ // Paper start ++ @Override ++ public org.bukkit.entity.Sheep getWololoTarget() { ++ Sheep sheep = getHandle().getWololoTarget(); ++ return sheep == null ? null : (org.bukkit.entity.Sheep) sheep.getBukkitEntity(); ++ } ++ ++ @Override ++ public void setWololoTarget(org.bukkit.entity.Sheep sheep) { ++ getHandle().setWololoTarget(sheep == null ? null : ((org.bukkit.craftbukkit.entity.CraftSheep) sheep).getHandle()); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/Remapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch new file mode 100644 index 0000000000..163eac24a0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch @@ -0,0 +1,126 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Tue, 11 Aug 2020 19:16:09 +0200 +Subject: [PATCH] Add a way to get translation keys for blocks, entities and + materials + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index ae50030df7512c56c552e800b74ef4c69ec6d6d2..d38828485d6deb08036e11d8bf16b3d63a60fbae 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -278,6 +278,7 @@ public class EntityType { + return Registry.ENTITY_TYPE.getKey(type); + } + ++ public static Optional> getByName(String name) { return byString(name); } // Paper - OBFHELPER + public static Optional> byString(String id) { + return Registry.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(id)); + } +@@ -431,6 +432,7 @@ public class EntityType { + return this.category; + } + ++ public String getDescriptionId() { return getDescriptionId(); } // Paper - OBFHELPER + public String getDescriptionId() { + if (this.descriptionId == null) { + this.descriptionId = Util.makeDescriptionId("entity", Registry.ENTITY_TYPE.getKey(this)); +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index 6fce16e89c5492654c891d5754714360a7649bca..58400e84830c93675b0a1fe632be5e217c19a932 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -56,7 +56,7 @@ public class Item implements ItemLike { + private final FoodProperties foodProperties; + + public static int getId(Item item) { +- return item == null ? 0 : Registry.ITEM.getId((Object) item); ++ return item == null ? 0 : Registry.ITEM.getId(item); // Paper - Fix Decompiler Issue + } + + public static Item byId(int id) { +@@ -152,6 +152,7 @@ public class Item implements ItemLike { + return Registry.ITEM.getKey(this).getPath(); + } + ++ public String getOrCreateDescriptionId() { return getOrCreateDescriptionId(); } // Paper - OBFHELPER + protected String getOrCreateDescriptionId() { + if (this.descriptionId == null) { + this.descriptionId = Util.makeDescriptionId("item", Registry.ITEM.getKey(this)); +@@ -164,6 +165,7 @@ public class Item implements ItemLike { + return this.getOrCreateDescriptionId(); + } + ++ public String getDescriptionId(ItemStack itemStack) { return getDescriptionId(itemStack); } // Paper - OBFHELPER + public String getDescriptionId(ItemStack stack) { + return this.getDescriptionId(); + } +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 5b84ee4091e354c4b6500f58a31931f2a6827ffc..baa587e73a71d6324bb7817fa4702a7c3a2db726 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -318,6 +318,7 @@ public class Block extends BlockBehaviour implements ItemLike { + return !this.material.isBuildable() && !this.material.isLiquid(); + } + ++ public String getOrCreateDescriptionId() { return getDescriptionId(); } // Paper - OBFHELPER + public String getDescriptionId() { + if (this.descriptionId == null) { + this.descriptionId = Util.makeDescriptionId("block", Registry.BLOCK.getKey(this)); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 05f0833f762436bf8f5f5875c7e3cfed1da11e1c..e09f65f0b06c8fb9a965b921c2c8e68ae2ac1e55 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -761,5 +761,10 @@ public class CraftBlock implements Block { + public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { + return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().defaultBlockState().getSoundType()); + } ++ ++ @Override ++ public String getTranslationKey() { ++ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); ++ } + // 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 a5a5038a84434e69fda8f6b41d2f00b4989e25ae..de5d02a1345f9886200f0540ac08be0df5878708 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -43,6 +43,7 @@ import org.bukkit.Registry; + import org.bukkit.UnsafeValues; + import org.bukkit.advancement.Advancement; + import org.bukkit.block.data.BlockData; ++import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.block.data.CraftBlockData; + import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.craftbukkit.legacy.CraftLegacy; +@@ -418,6 +419,30 @@ public final class CraftMagicNumbers implements UnsafeValues { + throw new RuntimeException(); + } + } ++ ++ @Override ++ public String getTranslationKey(Material mat) { ++ if (mat.isBlock()) { ++ return getBlock(mat).getOrCreateDescriptionId(); ++ } ++ return getItem(mat).getDescriptionId(); ++ } ++ ++ @Override ++ public String getTranslationKey(org.bukkit.block.Block block) { ++ return ((org.bukkit.craftbukkit.block.CraftBlock)block).getNMS().getBlock().getOrCreateDescriptionId(); ++ } ++ ++ @Override ++ public String getTranslationKey(org.bukkit.entity.EntityType type) { ++ return net.minecraft.world.entity.EntityType.getByName(type.getName()).map(net.minecraft.world.entity.EntityType::getDescriptionId).orElse(null); ++ } ++ ++ @Override ++ public String getTranslationKey(org.bukkit.inventory.ItemStack itemStack) { ++ net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); ++ return nmsItemStack.getItem().getDescriptionId(nmsItemStack); ++ } + // Paper end + + /** diff --git a/Remapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch b/Remapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch new file mode 100644 index 0000000000..a7252fed8a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ysl3000 +Date: Mon, 6 Jul 2020 22:18:04 +0200 +Subject: [PATCH] Create HoverEvent from ItemStack Entity + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index 746755f76ae177b2eeccf66f8cd95e6ffd5acad9..2e0be9771ca3511f5d9364c57235556b70f07ec6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -365,5 +365,40 @@ public final class CraftItemFactory implements ItemFactory { + + return nms != null ? net.minecraft.locale.Language.getInstance().translateKey(nms.getItem().getDescriptionId()) : null; + } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(ItemStack itemStack) { ++ net.md_5.bungee.api.chat.ItemTag itemTag = net.md_5.bungee.api.chat.ItemTag.ofNbt(CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString()); ++ return new net.md_5.bungee.api.chat.hover.content.Item( ++ itemStack.getType().getKey().toString(), ++ itemStack.getAmount(), ++ itemTag); ++ } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity) { ++ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(entity.getCustomName()) ? null : new net.md_5.bungee.api.chat.TextComponent(entity.getCustomName())); ++ } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, String customName) { ++ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(customName) ? null : new net.md_5.bungee.api.chat.TextComponent(customName)); ++ } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent customName) { ++ return new net.md_5.bungee.api.chat.hover.content.Entity( ++ entity.getType().getKey().toString(), ++ entity.getUniqueId().toString(), ++ customName); ++ } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent[] customName) { ++ return new net.md_5.bungee.api.chat.hover.content.Entity( ++ entity.getType().getKey().toString(), ++ entity.getUniqueId().toString(), ++ new net.md_5.bungee.api.chat.TextComponent(customName)); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch b/Remapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch new file mode 100644 index 0000000000..b4924166cc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: miclebrick +Date: Thu, 6 Dec 2018 19:52:50 -0500 +Subject: [PATCH] Cache block data strings + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 735c3c983e96e4e6f36de0975909fc48cb042081..5c5903867432894b47bc62d89989f78c36a84ca1 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1953,6 +1953,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop%s", nms, bukkit); + } + ++ // Paper start - cache block data strings ++ private static Map stringDataCache = new HashMap<>(); ++ ++ static { ++ // cache all of the default states at startup, will not cache ones with the custom states inside of the ++ // brackets in a different order, though ++ reloadCache(); ++ } ++ ++ public static void reloadCache() { ++ stringDataCache.clear(); ++ Block.BLOCK_STATE_REGISTRY.forEach(blockData -> stringDataCache.put(blockData.toString(), blockData.createCraftBlockData())); ++ } ++ // Paper end ++ + public static CraftBlockData newData(Material material, String data) { + Preconditions.checkArgument(material == null || material.isBlock(), "Cannot get data for not block %s", material); + ++ // Paper start - cache block data strings ++ if (material != null) { ++ Block block = CraftMagicNumbers.getBlock(material); ++ if (block != null) { ++ ResourceLocation key = Registry.BLOCK.getKey(block); ++ data = data == null ? key.toString() : key + data; ++ } ++ } ++ ++ CraftBlockData cached = stringDataCache.computeIfAbsent(data, s -> createNewData(null, s)); ++ return (CraftBlockData) cached.clone(); ++ } ++ ++ private static CraftBlockData createNewData(Material material, String data) { ++ // Paper end - cache block data strings + BlockState blockData; + Block block = CraftMagicNumbers.getBlock(material); + Map, Comparable> parsed = null; diff --git a/Remapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/Remapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch new file mode 100644 index 0000000000..1e30590a64 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 25 Aug 2020 20:45:36 -0400 +Subject: [PATCH] Fix Entity Teleportation and cancel velocity if teleported + +Uses correct setPositionRotation for Entity teleporting instead of setLocation +as this is how Vanilla teleports entities. + +Cancel any pending motion when teleported. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index ab6494f5a872bba5398bef0367b4d9257786f61e..ab45497e8f7720c9d60626b32e9c95779af676b0 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -691,7 +691,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + public void handleAcceptTeleportPacket(ServerboundAcceptTeleportationPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (packet.getId() == this.awaitingTeleport && this.awaitingPositionFromClient != null) { // CraftBukkit +- this.player.absMoveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.yRot, this.player.xRot); ++ this.player.moveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.yRot, this.player.xRot); // Paper - use proper setPositionRotation for teleportation + this.lastGoodX = this.awaitingPositionFromClient.x; + this.lastGoodY = this.awaitingPositionFromClient.y; + this.lastGoodZ = this.awaitingPositionFromClient.z; +@@ -1536,7 +1536,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit end + + this.awaitingTeleportTime = this.tickCount; +- this.player.absMoveTo(d0, d1, d2, f, f1); ++ this.player.moveTo(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation + this.player.forceCheckHighPriority(); // Paper + this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index aea2457510c75214bbb925307155611e981f115f..d69981a1b5a40418c7d17de5f3bece30592ae586 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -143,6 +143,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + // CraftBukkit start + private static final int CURRENT_LEVEL = 2; ++ public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation + static boolean isLevelAtLeast(CompoundTag tag, int level) { + return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; + } +@@ -1406,6 +1407,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public void moveTo(double x, double y, double z, float yaw, float pitch) { ++ // Paper - cancel entity velocity if teleported ++ if (!preserveMotion) { ++ this.deltaMovement = Vec3.ZERO; ++ } else { ++ this.preserveMotion = false; ++ } ++ // Paper end + this.setPosAndOldPos(x, y, z); + this.yRot = yaw; + this.xRot = pitch; +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 6ca378ec7868b855d46c749910c656f82ddb009f..091e72474ac199c38fff979a5faf524e011d8d0a 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -165,6 +165,7 @@ public abstract class BaseSpawner { + return; + } + ++ entity.preserveMotion = true; // Paper - preserve entity motion from tag + entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), world.random.nextFloat() * 360.0F, 0.0F); + if (entity instanceof Mob) { + Mob entityinsentient = (Mob) entity; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index deeae62e9926f9435907c68e7d35e7420f5e79dd..1275768762884416fa3c68dab3a6671b24949976 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -556,7 +556,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + } + + // entity.setLocation() throws no event, and so cannot be cancelled +- entity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); ++ entity.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); // Paper - use proper setPosition, as per vanilla teleporting + // SPIGOT-619: Force sync head rotation also + entity.setYHeadRot(location.getYaw()); + ((net.minecraft.server.level.ServerLevel) entity.level).updateChunkPos(entity); // Spigot - register to new chunk diff --git a/Remapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch b/Remapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch new file mode 100644 index 0000000000..4f031f39de --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 26 Aug 2020 02:12:31 -0400 +Subject: [PATCH] Add additional open container api 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 878a62e04962aafeaf192075fbe08e319298a800..aceb57c93c91730345f49f78838780c41ce2dcef 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -459,6 +459,70 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + return this.getHandle().containerMenu.getBukkitView(); + } + ++ // Paper start - Add additional containers ++ @Override ++ public InventoryView openAnvil(Location location, boolean force) { ++ return openInventory(location, force, Material.ANVIL); ++ } ++ ++ @Override ++ public InventoryView openCartographyTable(Location location, boolean force) { ++ return openInventory(location, force, Material.CARTOGRAPHY_TABLE); ++ } ++ ++ @Override ++ public InventoryView openGrindstone(Location location, boolean force) { ++ return openInventory(location, force, Material.GRINDSTONE); ++ } ++ ++ @Override ++ public InventoryView openLoom(Location location, boolean force) { ++ return openInventory(location, force, Material.LOOM); ++ } ++ ++ @Override ++ public InventoryView openSmithingTable(Location location, boolean force) { ++ return openInventory(location, force, Material.SMITHING_TABLE); ++ } ++ ++ @Override ++ public InventoryView openStonecutter(Location location, boolean force) { ++ return openInventory(location, force, Material.STONECUTTER); ++ } ++ ++ private InventoryView openInventory(Location location, boolean force, Material material) { ++ org.spigotmc.AsyncCatcher.catchOp("open" + material); ++ if (location == null) { ++ location = getLocation(); ++ } ++ if (!force) { ++ Block block = location.getBlock(); ++ if (block.getType() != material) { ++ return null; ++ } ++ } ++ net.minecraft.world.level.block.Block block; ++ if (material == Material.ANVIL) { ++ block = Blocks.ANVIL; ++ } else if (material == Material.CARTOGRAPHY_TABLE) { ++ block = Blocks.CARTOGRAPHY_TABLE; ++ } else if (material == Material.GRINDSTONE) { ++ block = Blocks.GRINDSTONE; ++ } else if (material == Material.LOOM) { ++ block = Blocks.LOOM; ++ } else if (material == Material.SMITHING_TABLE) { ++ block = Blocks.SMITHING_TABLE; ++ } else if (material == Material.STONECUTTER) { ++ block = Blocks.STONECUTTER; ++ } else { ++ throw new IllegalArgumentException("Unsupported inventory type: " + material); ++ } ++ getHandle().openMenu(block.getMenuProvider(null, getHandle().level, new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()))); ++ getHandle().containerMenu.checkReachable = !force; ++ return getHandle().containerMenu.getBukkitView(); ++ } ++ // Paper end ++ + @Override + public void closeInventory() { + // Paper start diff --git a/Remapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/Remapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch new file mode 100644 index 0000000000..a02addc375 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 12 Sep 2020 17:21:38 -0400 +Subject: [PATCH] Cache DataFixerUpper Rewrite Rules on demand + +Mojang precaches every single potential rewrite rule that could ever +exist on server startup. This includes rules from all the way back to versions from 6+ years ago. + +This is the source of why the server hogs every CPU core at 100% every start. + +For anyone who hard resets for updates or has force upgraded their entire world, this +results in completely wasted cpu cycles. + +This massive CPU usage also delays server startup time. + +We improve this by making "min version to precache" that defaults to a future version +so that no rewrite rules are precached. + +someone who expects to be converting a lot chunks could theoretically set +-DPaper.minPrecachedDatafixVersion= as a startup +parameter and only build from that point on. + +However this will likely never be needed as the server will still run +the same cache logic on demand when it's actually needed. The only +cost would be some delay on the FIRST chunk conversion, but paper already +runs chunk conversions on another thread so this will likely never be +a concern for TPS. + +This patch will significantly reduce CPU use on startup, reduce memory usage, +and improve server startup time. + +diff --git a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java +index edb77982d273e9492ab1a669ca1ad89da2ec3c3e..abc265b00044b14abb55c2628d454ee01fef467b 100644 +--- a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java ++++ b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java +@@ -26,8 +26,10 @@ public class DataFixerBuilder { + private final Int2ObjectSortedMap schemas = new Int2ObjectAVLTreeMap<>(); + private final List globalList = Lists.newArrayList(); + private final IntSortedSet fixerVersions = new IntAVLTreeSet(); ++ private final int minDataFixPrecacheVersion; // Paper + + public DataFixerBuilder(final int dataVersion) { ++ minDataFixPrecacheVersion = Integer.getInteger("Paper.minPrecachedDatafixVersion", dataVersion+1) * 10; // Paper - default to precache nothing - mojang stores versions * 10 to allow for 'sub versions' + this.dataVersion = dataVersion; + } + +@@ -65,6 +67,7 @@ public class DataFixerBuilder { + final IntBidirectionalIterator iterator = fixerUpper.fixerVersions().iterator(); + while (iterator.hasNext()) { + final int versionKey = iterator.nextInt(); ++ if (versionKey < minDataFixPrecacheVersion) continue; // Paper + final Schema schema = schemas.get(versionKey); + for (final String typeName : schema.types()) { + CompletableFuture.runAsync(() -> { diff --git a/Remapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch b/Remapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch new file mode 100644 index 0000000000..21f6d53f47 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 17 Sep 2020 00:36:05 +0100 +Subject: [PATCH] Extend block drop capture to capture all items added to the + world + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 22266fda4de9b5fbace3b8e55ce390b8d7e75a65..fe7b71fbb3963beafe93a5d86bebdd629c7ec8f2 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -95,6 +95,7 @@ import net.minecraft.world.entity.ai.village.poi.PoiType; + import net.minecraft.world.entity.animal.horse.SkeletonHorse; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.monster.Drowned; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.raid.Raid; +@@ -1284,6 +1285,13 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } else if (this.isUUIDUsed(entity)) { + return false; + } else { ++ // Paper start - capture all item additions to the world ++ if (captureDrops != null && entity instanceof ItemEntity) { ++ captureDrops.add((ItemEntity) entity); ++ return true; ++ } ++ // Paper end ++ + if (!CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { + return false; + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 79f3e4176145c42debb9adc1e68175cf063c1f22..6269e37f2859417a80e6de16045f1c2325f9746f 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -6,6 +6,7 @@ import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.MenuProvider; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.DoubleHighBlockItem; + import net.minecraft.world.item.ItemStack; +@@ -418,10 +419,12 @@ public class ServerPlayerGameMode { + // return true; // CraftBukkit + } + // CraftBukkit start ++ java.util.List itemsToDrop = level.captureDrops; // Paper - store current list ++ level.captureDrops = null; // Paper - Remove this earlier so that we can actually drop stuff + if (event.isDropItems()) { +- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, level.captureDrops); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - use stored ref + } +- level.captureDrops = null; ++ //world.captureDrops = null; // Paper - move up + + // Drop event experience + if (flag && event != null) { diff --git a/Remapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/Remapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch new file mode 100644 index 0000000000..07195903cb --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sun, 27 Sep 2020 16:25:24 +0200 +Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086) + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 82205ad13ef0e987bd83979d06331545efe0a60a..50dc47e8c03ce274d558bc0dfa73ba3ab5fbae5c 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -388,6 +388,7 @@ public class ChunkHolder { + } + + public void blockChanged(BlockPos blockposition) { ++ if (!blockposition.isValidLocation()) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks + LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { diff --git a/Remapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/Remapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch new file mode 100644 index 0000000000..6eb1a44bc0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Fri, 28 Aug 2020 01:41:26 +0200 +Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and + non-conflicting Entity Ids + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d69981a1b5a40418c7d17de5f3bece30592ae586..fa22c0d7f676c96d34bf56d80181d6b047f2ff0b 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -3476,4 +3476,10 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + void accept(Entity entity, double x, double y, double z); + } ++ ++ // Paper start ++ public static int nextEntityId() { ++ return ENTITY_COUNTER.incrementAndGet(); ++ } ++ // 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 de5d02a1345f9886200f0540ac08be0df5878708..9a16882deee21faf78ea46e08b2f2ad3fbb6021b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -443,6 +443,10 @@ public final class CraftMagicNumbers implements UnsafeValues { + net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); + return nmsItemStack.getItem().getDescriptionId(nmsItemStack); + } ++ ++ public int nextEntityId() { ++ return net.minecraft.world.entity.Entity.nextEntityId(); ++ } + // Paper end + + /** diff --git a/Remapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch b/Remapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch new file mode 100644 index 0000000000..e06db589aa --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Sat, 3 Oct 2020 04:15:09 -0400 +Subject: [PATCH] Lazily track plugin scoreboards by default + +On servers with plugins that constantly churn through scoreboards, there is a risk of +degraded GC performance due to the number of scoreboards held on by weak references. +Most plugins don't even need the (vanilla) functionality that requires all plugin +scoreboards to be tracked by the server. Instead, only track scoreboards when an +objective is added with a non-dummy criteria. + +This is a breaking change, however the change is a much more sensible default. In case +this breaks your workflow you can always force all scoreboards to be tracked with +settings.track-plugin-scoreboards in paper.yml. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 545948f20efd6c8dd42140b565af94cd6b52b661..7d50aded88f5b7dfebaea1aebc86231f7b5c4e25 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -462,4 +462,9 @@ public class PaperConfig { + private static void maxJoinsPerTick() { + maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); + } ++ ++ public static boolean trackPluginScoreboards; ++ private static void trackPluginScoreboards() { ++ trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +index 4c93be31fd95d731327479519ecb34a08785c1ca..57537b8871dd5c54d97f3effe1802a3396644e46 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +@@ -18,6 +18,7 @@ import org.bukkit.scoreboard.Team; + + public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + final Scoreboard board; ++ boolean registeredGlobally = false; // Paper + + CraftScoreboard(Scoreboard board) { + this.board = board; +@@ -44,6 +45,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); + Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); + CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); ++ // Paper start - the block comment from the old registerNewObjective didnt cause a conflict when rebasing, so this block wasn't added to the adventure registerNewObjective ++ if (craftCriteria.criteria != net.minecraft.world.scores.criteria.ObjectiveCriteria.DUMMY && !registeredGlobally) { ++ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); ++ registeredGlobally = true; ++ } ++ // Paper end + net.minecraft.world.scores.Objective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); + return new CraftObjective(this, objective); + } +@@ -65,6 +72,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); + + CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); ++ // Paper start ++ if (craftCriteria.criteria != net.minecraft.server.IScoreboardCriteria.DUMMY && !registeredGlobally) { ++ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); ++ registeredGlobally = true; ++ } ++ // Paper end + ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); + return new CraftObjective(this, objective);*/ // Paper + return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +index 30b0d4986a7edcf324d94d9304d66d0567098855..8217e35f5a3093e63a165ee8c8b30bf3f28f3bd3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +@@ -30,6 +30,7 @@ public final class CraftScoreboardManager implements ScoreboardManager { + + public CraftScoreboardManager(MinecraftServer minecraftserver, net.minecraft.world.scores.Scoreboard scoreboardServer) { + mainScoreboard = new CraftScoreboard(scoreboardServer); ++ mainScoreboard.registeredGlobally = true; // Paper + server = minecraftserver; + scoreboards.add(mainScoreboard); + } +@@ -43,10 +44,22 @@ public final class CraftScoreboardManager implements ScoreboardManager { + public CraftScoreboard getNewScoreboard() { + org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot + CraftScoreboard scoreboard = new CraftScoreboard(new ServerScoreboard(server)); ++ // Paper start ++ if (com.destroystokyo.paper.PaperConfig.trackPluginScoreboards) { ++ scoreboard.registeredGlobally = true; + scoreboards.add(scoreboard); ++ } ++ // Paper end + return scoreboard; + } + ++ // Paper start ++ public void registerScoreboardForVanilla(CraftScoreboard scoreboard) { ++ org.spigotmc.AsyncCatcher.catchOp("scoreboard registration"); ++ scoreboards.add(scoreboard); ++ } ++ // Paper end ++ + // CraftBukkit method + public CraftScoreboard getPlayerBoard(CraftPlayer player) { + CraftScoreboard board = playerBoards.get(player); diff --git a/Remapped-Spigot-Server-Patches/0573-Entity-isTicking.patch b/Remapped-Spigot-Server-Patches/0573-Entity-isTicking.patch new file mode 100644 index 0000000000..22d5c7950d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0573-Entity-isTicking.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 3 Oct 2020 21:39:16 -0500 +Subject: [PATCH] Entity#isTicking + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index fa22c0d7f676c96d34bf56d80181d6b047f2ff0b..a623c22cd03ad92657e661851fddc76a30986755 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -49,6 +49,7 @@ import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.level.TicketType; +@@ -3481,5 +3482,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public static int nextEntityId() { + return ENTITY_COUNTER.incrementAndGet(); + } ++ ++ public boolean isTicking() { ++ return ((ServerChunkCache) level.getChunkSource()).isInEntityTickingChunk(this); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 1275768762884416fa3c68dab3a6671b24949976..502773ae60290125057fb342a3358ff55927d196 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1159,5 +1159,9 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public boolean isInLava() { + return getHandle().isInLava(); + } ++ ++ public boolean isTicking() { ++ return getHandle().isTicking(); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/Remapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch new file mode 100644 index 0000000000..2d6ec97910 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 3 Oct 2020 22:00:27 -0500 +Subject: [PATCH] Fix deop kicking non-whitelisted player when white list is + not enabled + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 5c5903867432894b47bc62d89989f78c36a84ca1..954dce690852da87a37e7797c6f9f549242e511a 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2018,6 +2018,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop list = Lists.newArrayList(playerlist.getPlayers()); + Iterator iterator = list.iterator(); + diff --git a/Remapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch b/Remapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch new file mode 100644 index 0000000000..5b9dbf362f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 8 Oct 2020 00:00:25 -0400 +Subject: [PATCH] Fix "Not a string" Map Conversion spam + +The maps did convert successfully, but had noisy logs due to Spigot +implementing this logic incorrectly. + +This stops the spam by converting the old format to new before +requesting the world. + +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +index 7582c7cd4235d212a0cf66a4c59ce0cedaa360ad..e7b178127228dea5a17ba0fbd6bae148d70e8eb5 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -12,6 +12,8 @@ import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.NumericTag; ++import net.minecraft.nbt.StringTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.Packet; +@@ -94,7 +96,26 @@ public class MapItemSavedData extends SavedData { + + @Override + public void load(CompoundTag tag) { +- DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, tag.get("dimension"))); // CraftBukkit - decompile error ++ // Paper start - fix "Not a string" spam ++ Tag dimension = tag.get("dimension"); ++ if (dimension instanceof NumericTag && ((NumericTag) dimension).getAsInt() >= CraftWorld.CUSTOM_DIMENSION_OFFSET) { ++ long least = tag.getLong("UUIDLeast"); ++ long most = tag.getLong("UUIDMost"); ++ ++ if (least != 0L && most != 0L) { ++ this.uniqueId = new UUID(most, least); ++ CraftWorld world = (CraftWorld) server.getWorld(this.uniqueId); ++ if (world != null) { ++ dimension = StringTag.create("minecraft:" + world.getName().toLowerCase(java.util.Locale.ENGLISH)); ++ } else { ++ dimension = StringTag.create("bukkit:_invalidworld_"); ++ } ++ } else { ++ dimension = StringTag.create("bukkit:_invalidworld_"); ++ } ++ } ++ DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, dimension)); // CraftBukkit - decompile error ++ // Paper end - fix "Not a string" spam + Logger logger = MapItemSavedData.LOGGER; + + logger.getClass(); diff --git a/Remapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/Remapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch new file mode 100644 index 0000000000..d952b410f0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Sun, 4 Oct 2020 19:55:25 -0700 +Subject: [PATCH] Fix CME on adding a passenger in CreatureSpawnEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a623c22cd03ad92657e661851fddc76a30986755..90e9797cc1f3a4aa0a2bee28dca364e6f6dd0c0b 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -3180,7 +3180,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public Stream getSelfAndPassengers() { +- return Stream.concat(Stream.of(this), this.passengers.stream().flatMap(Entity::getSelfAndPassengers)); ++ return Stream.concat(Stream.of(this), com.google.common.collect.ImmutableList.copyOf(this.passengers).stream().flatMap(Entity::getSelfAndPassengers)); // Paper + } + + public boolean hasOnePlayerPassenger() { diff --git a/Remapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch b/Remapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch new file mode 100644 index 0000000000..02442096a4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Wed, 18 Mar 2020 00:07:46 -0500 +Subject: [PATCH] MC-147729: Drop items that are extra from a crafting recipe + + +diff --git a/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java b/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java +index a18aa176850bef45afcaf5742e9afbfa39281e22..c6ba6aabf94c26cccbd14689ea32373c17bbccc4 100644 +--- a/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java ++++ b/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java +@@ -71,7 +71,12 @@ public class ServerPlaceRecipe implements PlaceRecipe +Date: Wed, 1 Jun 2016 23:29:17 -0400 +Subject: [PATCH] Reset Ender Crystals on Dragon Spawn + +Crystals can end up in a bad state in certain conditions which causes +an exception on the expected number of crystals going negative. + +This ensures the crystals/pillars are in expected state when the dragon spawns. + +See #3522 + +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 4b18931225ef60dbcffd7fcc20d0e9ce62348a07..590df3b93b897613cad74f9920aec62b33a2f7f7 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -441,6 +441,7 @@ public class EndDragonFight { + entityenderdragon.moveTo(0.0D, 128.0D, 0.0D, this.level.random.nextFloat() * 360.0F, 0.0F); + this.level.addFreshEntity(entityenderdragon); + this.dragonUUID = entityenderdragon.getUUID(); ++ this.resetSpikeCrystals(); // Paper + return entityenderdragon; + } + diff --git a/Remapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch b/Remapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch new file mode 100644 index 0000000000..42d90f77ee --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 17 May 2020 23:47:33 -0700 +Subject: [PATCH] Fix for large move vectors crashing server + +Check movement distance also based on current position. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index ab45497e8f7720c9d60626b32e9c95779af676b0..3a114bec14fcc6c1e1045e2b99178a6adb25f387 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -516,19 +516,24 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) { + ServerLevel worldserver = this.player.getLevel(); +- double d0 = entity.getX(); +- double d1 = entity.getY(); +- double d2 = entity.getZ(); +- double d3 = packet.getX(); +- double d4 = packet.getY(); +- double d5 = packet.getZ(); ++ double d0 = entity.getX();double fromX = d0; // Paper - OBFHELPER ++ double d1 = entity.getY();double fromY = d1; // Paper - OBFHELPER ++ double d2 = entity.getZ();double fromZ = d2; // Paper - OBFHELPER ++ double d3 = packet.getX();double toX = d3; // Paper - OBFHELPER ++ double d4 = packet.getY();double toY = d4; // Paper - OBFHELPER ++ double d5 = packet.getZ();double toZ = d5; // Paper - OBFHELPER + float f = packet.getYRot(); + float f1 = packet.getXRot(); + double d6 = d3 - this.vehicleFirstGoodX; + double d7 = d4 - this.vehicleFirstGoodY; + double d8 = d5 - this.vehicleFirstGoodZ; + double d9 = entity.getDeltaMovement().lengthSqr(); +- double d10 = d6 * d6 + d7 * d7 + d8 * d8; ++ // Paper start - fix large move vectors killing the server ++ double currDeltaX = toX - fromX; ++ double currDeltaY = toY - fromY; ++ double currDeltaZ = toZ - fromZ; ++ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); ++ // Paper end - fix large move vectors killing the server + + + // CraftBukkit start - handle custom speeds and skipped ticks +@@ -1230,7 +1235,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + double d2 = this.player.getZ(); + double d3 = this.player.getY(); + double d4 = packet.getX(this.player.getX());double toX = d4; // Paper - OBFHELPER +- double d5 = packet.getY(this.player.getY()); ++ double d5 = packet.getY(this.player.getY());double toY = d5; // Paper - OBFHELPER + double d6 = packet.getZ(this.player.getZ());double toZ = d6; // Paper - OBFHELPER + float f = packet.getYRot(this.player.yRot); + float f1 = packet.getXRot(this.player.xRot); +@@ -1238,7 +1243,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + double d8 = d5 - this.firstGoodY; + double d9 = d6 - this.firstGoodZ; + double d10 = this.player.getDeltaMovement().lengthSqr(); +- double d11 = d7 * d7 + d8 * d8 + d9 * d9; ++ // Paper start - fix large move vectors killing the server ++ double currDeltaX = toX - prevX; ++ double currDeltaY = toY - prevY; ++ double currDeltaZ = toZ - prevZ; ++ double d11 = Math.max(d7 * d7 + d8 * d8 + d9 * d9, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); ++ // Paper end - fix large move vectors killing the server + + if (this.player.isSleeping()) { + if (d11 > 1.0D) { diff --git a/Remapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch b/Remapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch new file mode 100644 index 0000000000..f1103a3993 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 3 Jun 2020 11:37:13 -0700 +Subject: [PATCH] Optimise getType calls + +Remove the map lookup for converting from Block->Bukkit Material + +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockState.java b/src/main/java/net/minecraft/world/level/block/state/BlockState.java +index 9958cdf55cef2177fafd0cdae48da9db064af9f1..4263ac345d57e36e010e3dd009130c02799b249c 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockState.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockState.java +@@ -11,6 +11,19 @@ public class BlockState extends BlockBehaviour.BlockStateBase { + + public static final Codec CODEC = codec((Codec) Registry.BLOCK, Block::defaultBlockState).stable(); + ++ ++ // Paper start - optimise getType calls ++ org.bukkit.Material cachedMaterial; ++ ++ public final org.bukkit.Material getBukkitMaterial() { ++ if (this.cachedMaterial == null) { ++ this.cachedMaterial = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(this.getBlock()); ++ } ++ ++ return this.cachedMaterial; ++ } ++ // Paper end - optimise getType calls ++ + public BlockState(Block block, ImmutableMap, Comparable> propertyMap, MapCodec mapcodec) { + super(block, propertyMap, mapcodec); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java +index fe00c8fdacc28a68c732aac0b887ea107d87e979..227974a85a81c623311301e28e83e85424b05f3d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java +@@ -78,7 +78,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot { + public Material getBlockType(int x, int y, int z) { + CraftChunk.validateChunkCoordinates(x, y, z); + +- return CraftMagicNumbers.getMaterial(blockids[y >> 4].get(x, y & 0xF, z).getBlock()); ++ return blockids[y >> 4].get(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index e09f65f0b06c8fb9a965b921c2c8e68ae2ac1e55..37eceaef1212e2ee13aa763a5ede24ec170e5391 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -211,7 +211,7 @@ public class CraftBlock implements Block { + + @Override + public Material getType() { +- return CraftMagicNumbers.getMaterial(world.getBlockState(position).getBlock()); ++ return world.getBlockState(position).getBukkitMaterial(); // Paper - optimise getType calls + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +index 754559c9e47032845fdc94eedad0cece0e0ae4c7..7e4c522605cf04a38a7a0f54e7ac6ea0e372c98d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +@@ -134,7 +134,7 @@ public class CraftBlockState implements BlockState { + + @Override + public Material getType() { +- return CraftMagicNumbers.getMaterial(data.getBlock()); ++ return data.getBukkitMaterial(); // Paper - optimise getType calls + } + + public void setFlag(int flag) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +index 03e065bf92cafd376ad0f878584cdac6fd196245..d93f2373f3127462aa2f9b69f7cc808b58d47b61 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +@@ -45,7 +45,7 @@ public class CraftBlockData implements BlockData { + + @Override + public Material getMaterial() { +- return CraftMagicNumbers.getMaterial(state.getBlock()); ++ return state.getBukkitMaterial(); // Paper - optimise getType calls + } + + public BlockState getState() { +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +index fd2cb2a584fea360fcf8180338708f35c4e3dc1f..a463b89888460e5a894098c20eb4c4a78c04642c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +@@ -73,7 +73,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + + @Override + public Material getType(int x, int y, int z) { +- return CraftMagicNumbers.getMaterial(getTypeId(x, y, z).getBlock()); ++ return getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch b/Remapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch new file mode 100644 index 0000000000..2d03e1410f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Mon, 7 Oct 2019 00:15:37 -0500 +Subject: [PATCH] Villager#resetOffers + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +index 9eee68a5a84e121698d26bd54212a72c75e16251..407a68edf6408400f1a6c5bb1a6cbbfae08ac2cd 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -111,6 +111,13 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan + return this.tradingPlayer != null; + } + ++ // Paper start ++ public void resetOffers() { ++ this.offers = new MerchantOffers(); ++ this.updateTrades(); ++ } ++ // Paper end ++ + @Override + public MerchantOffers getOffers() { + if (this.offers == null) { +@@ -232,6 +239,7 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan + return this.level; + } + ++ protected final void updateTrades() { updateTrades(); } // Paper - OBFHELPER + protected abstract void updateTrades(); + + protected void addOffersFromItemListings(MerchantOffers recipeList, VillagerTrades.ItemListing[] pool, int count) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java +index 8ffdfe3e8229b556838eab18dcb6bfb0c05a6063..7f887e883a87f2df7ae428ffddb072724d602d62 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java +@@ -70,4 +70,11 @@ public class CraftAbstractVillager extends CraftAgeable implements AbstractVilla + public HumanEntity getTrader() { + return getMerchant().getTrader(); + } ++ ++ // Paper start ++ @Override ++ public void resetOffers() { ++ getHandle().resetOffers(); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/Remapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch new file mode 100644 index 0000000000..fc2f46516c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Jul 2020 20:46:50 -0700 +Subject: [PATCH] Improve inlinig for some hot IBlockData methods + + +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index f2fefdad26057c722085e60ba837fe2c117f55f7..17baae6b11f191f4738a107c7e62ea5bdac17a3c 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -390,7 +390,14 @@ public abstract class BlockBehaviour { + } + // Paper end + ++ // Paper start ++ protected boolean isTicking; ++ protected FluidState fluid; ++ // Paper end ++ + public void initCache() { ++ this.fluid = this.getBlock().getFluidState(this.asState()); // Paper - moved from getFluid() ++ this.isTicking = this.getBlock().isRandomlyTicking(this.asState()); // Paper - moved from isTicking() + if (!this.getBlock().hasDynamicShape()) { + this.cache = new BlockBehaviour.BlockStateBase.Cache(this.asState()); + } +@@ -429,19 +436,19 @@ public abstract class BlockBehaviour { + return this.getBlock().getOcclusionShape(this.asState(), world, pos); + } + +- public boolean hasLargeCollisionShape() { ++ public final boolean hasLargeCollisionShape() { // Paper + return this.cache == null || this.cache.largeCollisionShape; + } + +- public boolean useShapeForLightOcclusion() { ++ public final boolean useShapeForLightOcclusion() { // Paper + return this.useShapeForLightOcclusion; + } + +- public int getLightEmission() { ++ public final int getLightEmission() { // Paper + return this.lightEmission; + } + +- public boolean isAir() { ++ public final boolean isAir() { // Paper + return this.isAir; + } + +@@ -507,7 +514,7 @@ public abstract class BlockBehaviour { + } + } + +- public boolean canOcclude() { ++ public final boolean canOcclude() { // Paper + return this.canOcclude; + } + +@@ -679,12 +686,12 @@ public abstract class BlockBehaviour { + return this.getBlock().is(block); + } + +- public FluidState getFluidState() { +- return this.getBlock().getFluidState(this.asState()); ++ public final FluidState getFluidState() { // Paper ++ return this.fluid; // Paper - moved into init + } + +- public boolean isRandomlyTicking() { +- return this.getBlock().isRandomlyTicking(this.asState()); ++ public final boolean isRandomlyTicking() { // Paper ++ return this.isTicking; // Paper - moved into init + } + + public SoundType getSoundType() { +diff --git a/src/main/java/net/minecraft/world/level/material/FluidState.java b/src/main/java/net/minecraft/world/level/material/FluidState.java +index c077e4a7ce6a484956206eaab9dfde057b7e429a..69cf9e149c207336c537a00f08251a2252752df6 100644 +--- a/src/main/java/net/minecraft/world/level/material/FluidState.java ++++ b/src/main/java/net/minecraft/world/level/material/FluidState.java +@@ -20,8 +20,12 @@ public final class FluidState extends StateHolder { + + public static final Codec CODEC = codec((Codec) Registry.FLUID, Fluid::defaultFluidState).stable(); + ++ // Paper start ++ protected final boolean isEmpty; ++ // Paper end + public FluidState(Fluid fluid, ImmutableMap, Comparable> propertiesMap, MapCodec mapcodec) { + super(fluid, propertiesMap, mapcodec); ++ this.isEmpty = fluid.isEmpty(); // Paper - moved from isEmpty() + } + + public Fluid getType() { +@@ -33,7 +37,7 @@ public final class FluidState extends StateHolder { + } + + public boolean isEmpty() { +- return this.getType().isEmpty(); ++ return this.isEmpty; // Paper - moved into constructor + } + + public float getHeight(BlockGetter world, BlockPos pos) { diff --git a/Remapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch b/Remapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch new file mode 100644 index 0000000000..1d1bff4b34 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 7 Aug 2020 04:27:56 -0700 +Subject: [PATCH] Retain block place order when capturing blockstates + +Fixes twisted vines not connecting properly when grown via +bonemeal by a player. + +In general, look at making this logic more robust (i.e properly handling +cases where a captured entry is overriden) - but for now this will do. + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index ebb92f88e0402681c47834bcf45e6b236748289a..2ad8a4558aa812885adebee8c05dab45f2bf5f90 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -135,7 +135,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean captureBlockStates = false; + public boolean captureTreeGeneration = false; + public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper +- public Map capturedTileEntities = new HashMap<>(); ++ public Map capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper + public List captureDrops; + public long ticksPerAnimalSpawns; + public long ticksPerMonsterSpawns; diff --git a/Remapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch b/Remapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch new file mode 100644 index 0000000000..9371d97aec --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 25 Apr 2020 17:10:55 -0700 +Subject: [PATCH] Reduce blockpos allocation from pathfinding + + +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +index 7ae24381b91c282745b7fe5f6897865e74bc0acf..3c460682611969a5db136aa41ca0d230c6228d56 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +@@ -498,7 +498,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { + return BlockPathTypes.DANGER_FIRE; + } + +- if (iblockaccess.getFluidState(blockposition_mutableblockposition).is((Tag) FluidTags.WATER)) { ++ if (iblockdata.getFluidState().is((Tag) FluidTags.WATER)) { // Paper - remove another getType call + return BlockPathTypes.WATER_BORDER; + } + } // Paper +@@ -528,7 +528,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { + } else if (iblockdata.is(Blocks.COCOA)) { + return BlockPathTypes.COCOA; + } else { +- FluidState fluid = iblockaccess.getFluidState(blockposition); ++ FluidState fluid = iblockdata.getFluidState(); // Paper - remove another get type call + + return fluid.is((Tag) FluidTags.WATER) ? BlockPathTypes.WATER : (fluid.is((Tag) FluidTags.LAVA) ? BlockPathTypes.LAVA : (isBurningBlock(iblockdata) ? BlockPathTypes.DAMAGE_FIRE : (DoorBlock.isWoodenDoor(iblockdata) && !(Boolean) iblockdata.getValue(DoorBlock.OPEN) ? BlockPathTypes.DOOR_WOOD_CLOSED : (block instanceof DoorBlock && material == Material.ORE && !(Boolean) iblockdata.getValue(DoorBlock.OPEN) ? BlockPathTypes.DOOR_IRON_CLOSED : (block instanceof DoorBlock && (Boolean) iblockdata.getValue(DoorBlock.OPEN) ? BlockPathTypes.DOOR_OPEN : (block instanceof BaseRailBlock ? BlockPathTypes.RAIL : (block instanceof LeavesBlock ? BlockPathTypes.LEAVES : (!block.is((Tag) BlockTags.FENCES) && !block.is((Tag) BlockTags.WALLS) && (!(block instanceof FenceGateBlock) || (Boolean) iblockdata.getValue(FenceGateBlock.OPEN)) ? (!iblockdata.isPathfindable(iblockaccess, blockposition, PathComputationType.LAND) ? BlockPathTypes.BLOCKED : BlockPathTypes.OPEN) : BlockPathTypes.FENCE)))))))); + } diff --git a/Remapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch b/Remapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch new file mode 100644 index 0000000000..535e3ffd30 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 3 Oct 2020 20:32:25 -0500 +Subject: [PATCH] Fix item locations dropped from campfires + +Fixes #4259 by not flooring the blockposition among other weirdness + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +index 0c90b1b13611843ba4402c8ccf0b15781b85e773..6c38361d744eae763b6c131ad314485f5a88fcfc 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +@@ -14,6 +14,7 @@ import net.minecraft.world.Clearable; + import net.minecraft.world.ContainerHelper; + import net.minecraft.world.Containers; + import net.minecraft.world.SimpleContainer; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.CampfireCookingRecipe; + import net.minecraft.world.item.crafting.RecipeType; +@@ -91,7 +92,11 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable, Ticka + result = blockCookEvent.getResult(); + itemstack1 = CraftItemStack.asNMSCopy(result); + // CraftBukkit end +- Containers.dropItemStack(this.level, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack1); ++ // Paper start ++ ItemEntity droppedItem = new ItemEntity(this.level, blockposition.getX() + 0.5D, blockposition.getY() + 0.5D, blockposition.getZ() + 0.5D, itemstack1.split(this.level.random.nextInt(21) + 10)); ++ droppedItem.setDeltaMovement(this.level.random.nextGaussian() * 0.05D, this.level.random.nextGaussian() * 0.05D + 0.2D, this.level.random.nextGaussian() * 0.05D); ++ this.level.addFreshEntity(droppedItem); ++ // Paper end + this.items.set(i, ItemStack.EMPTY); + this.markUpdated(); + } diff --git a/Remapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch b/Remapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch new file mode 100644 index 0000000000..92e087e79f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Tue, 14 Apr 2020 12:05:22 +0200 +Subject: [PATCH] Player elytra boost API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 7aae63d22167dc1b3ec7e8bc8672855c2038007e..94240b70e245bdc3dda60420f5787f8d5dcc1958 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -67,6 +67,7 @@ import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeMap; + import net.minecraft.world.entity.ai.attributes.Attributes; ++import net.minecraft.world.entity.projectile.FireworkRocketEntity; + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; +@@ -2281,6 +2282,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + throw new RuntimeException("Unknown settings type"); + } ++ ++ @Override ++ public org.bukkit.entity.Firework boostElytra(ItemStack firework) { ++ Validate.isTrue(isGliding(), "Player must be gliding"); ++ Validate.isTrue(firework != null, "firework == null"); ++ Validate.isTrue(firework.getType() == Material.FIREWORK_ROCKET, "Firework must be Material.FIREWORK_ROCKET"); ++ ++ net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(firework); ++ net.minecraft.world.level.Level world = ((CraftWorld) getWorld()).getHandle(); ++ FireworkRocketEntity entity = new FireworkRocketEntity(world, item, getHandle()); ++ return world.addFreshEntity(entity) ++ ? (org.bukkit.entity.Firework) entity.getBukkitEntity() ++ : null; ++ } + // Paper end + + // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch b/Remapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch new file mode 100644 index 0000000000..de814154fd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: giacomo <32515303+giacomozama@users.noreply.github.com> +Date: Sat, 10 Oct 2020 12:15:33 +0200 +Subject: [PATCH] Fixed TileEntityBell memory leak + +TileEntityBell has a list of entities (entitiesAtRing) that was not being cleared at the right time, causing leaks whenever a bell would be rung near a crowd of entities. + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +index aa45a142aa11acc9fd08b4877891741f3cbd936d..3f9179a7678091875161a34d13b6ec0e78025c4c 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -27,8 +27,8 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity + public int ticks; + public boolean shaking; + public Direction clickDirection; +- private List nearbyEntities; +- private boolean resonating; ++ private List nearbyEntities; private List getEntitiesAtRing() { return this.nearbyEntities; } // Paper - OBFHELPER ++ private boolean resonating; private boolean getShouldReveal() { return this.resonating; } // Paper - OBFHELPER + private int resonationTicks; + + public BellBlockEntity() { +@@ -57,6 +57,11 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity + + if (this.ticks >= 50) { + this.shaking = false; ++ // Paper start ++ if (!this.getShouldReveal()) { ++ this.getEntitiesAtRing().clear(); ++ } ++ // Paper end + this.ticks = 0; + } + +@@ -71,6 +76,7 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity + } else { + this.makeRaidersGlow(this.level); + this.showBellParticles(this.level); ++ this.getEntitiesAtRing().clear(); // Paper + this.resonating = false; + } + } +@@ -111,11 +117,12 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity + LivingEntity entityliving = (LivingEntity) iterator.next(); + + if (entityliving.isAlive() && !entityliving.removed && blockposition.closerThan((Position) entityliving.position(), 32.0D)) { +- entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, (Object) this.level.getGameTime()); ++ entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.level.getGameTime()); // Paper - decompile fix + } + } + } + ++ this.getEntitiesAtRing().removeIf(e -> !e.isAlive()); // Paper + } + + private boolean areRaidersNearby() { diff --git a/Remapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/Remapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch new file mode 100644 index 0000000000..6072b2edd8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Toon Schoenmakers +Date: Fri, 23 Oct 2020 15:01:44 +0200 +Subject: [PATCH] Avoid error bubbling up when item stack is empty in fishing + loot + +This can realistically only happen if there's custom loot active on fishing +which can return 0 items. This would disconnect the player who's fishing. + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +index 7bff012f3cd4458673ee02e5f5f830fc0ef983a3..ef71cca9922ed134ec82fb2982d375bf16f47b17 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +@@ -481,9 +481,15 @@ public class FishingHook extends Projectile { + + while (iterator.hasNext()) { + ItemStack itemstack1 = (ItemStack) iterator.next(); +- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), itemstack1); ++ // Paper start, new EntityItem would throw if for whatever reason (mostly shitty datapacks) the itemstack1 turns out to be empty ++ // if the item stack is empty we instead just have our entityitem as null ++ ItemEntity entityitem = null; ++ if (!itemstack1.isEmpty()) { ++ entityitem = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), itemstack1); ++ } ++ // Paper end + // CraftBukkit start +- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null + playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); + this.level.getCraftServer().getPluginManager().callEvent(playerFishEvent); + +@@ -496,8 +502,12 @@ public class FishingHook extends Projectile { + double d2 = entityhuman.getZ() - this.getZ(); + double d3 = 0.1D; + +- entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); +- this.level.addFreshEntity(entityitem); ++ // Paper start, entity item can be null, so we need to check against this ++ if (entityitem != null) { ++ entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); ++ this.level.addFreshEntity(entityitem); ++ } ++ // Paper end + // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() + if (playerFishEvent.getExpToDrop() > 0) { + entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper diff --git a/Remapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch b/Remapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch new file mode 100644 index 0000000000..b581372702 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: oxygencraft <21054297+oxygencraft@users.noreply.github.com> +Date: Sun, 25 Oct 2020 18:34:50 +1100 +Subject: [PATCH] Add getOfflinePlayerIfCached(String) + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index e599be15af17e5e45d2b694c30140cc4a787a7f5..046fbc646d2818bb2c7e08ff22093523e8246523 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1612,6 +1612,28 @@ public final class CraftServer implements Server { + return result; + } + ++ // Paper start ++ @Override ++ @Nullable ++ public OfflinePlayer getOfflinePlayerIfCached(String name) { ++ Validate.notNull(name, "Name cannot be null"); ++ Validate.notEmpty(name, "Name cannot be empty"); ++ ++ OfflinePlayer result = getPlayerExact(name); ++ if (result == null) { ++ GameProfile profile = console.getProfileCache().getProfileIfCached(name); ++ ++ if (profile != null) { ++ result = getOfflinePlayer(profile); ++ } ++ } else { ++ offlinePlayers.remove(result.getUniqueId()); ++ } ++ ++ return result; ++ } ++ // Paper end ++ + @Override + public OfflinePlayer getOfflinePlayer(UUID id) { + Validate.notNull(id, "UUID cannot be null"); diff --git a/Remapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch b/Remapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch new file mode 100644 index 0000000000..e20018337f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch @@ -0,0 +1,143 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Mon, 9 Nov 2020 20:44:51 +0100 +Subject: [PATCH] Add ignore discounts API + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index e9912551e6a19d6ad3b20fad1b716577b9d28f99..415fa3591add1f1ab22dd5866e110dbfccd0ec93 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -459,6 +459,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + + while (iterator.hasNext()) { + MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); ++ if (merchantrecipe.ignoreDiscounts) continue; // Paper + + // CraftBukkit start + int bonus = -Mth.floor((float) i * merchantrecipe.getPriceMultiplier()); +@@ -478,6 +479,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + + while (iterator1.hasNext()) { + MerchantOffer merchantrecipe1 = (MerchantOffer) iterator1.next(); ++ if (merchantrecipe1.ignoreDiscounts) continue; // Paper + double d0 = 0.3D + 0.0625D * (double) j; + int k = (int) Math.floor(d0 * (double) merchantrecipe1.getBaseCostA().getCount()); + +diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java +index fa74813e0fe76612023830b2fc41d41aa0b4f10e..25a0f180967911d5916eb71334a94baec84eafbf 100644 +--- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java ++++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java +@@ -19,6 +19,7 @@ public class MerchantOffer { + private int demand; + public float priceMultiplier; + public int xp; ++ public boolean ignoreDiscounts; // Paper + // CraftBukkit start + private CraftMerchantRecipe bukkitHandle; + +@@ -27,7 +28,12 @@ public class MerchantOffer { + } + + public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { +- this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier); ++ // Paper start - add ignoreDiscounts param ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, false, bukkit); ++ } ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, ignoreDiscounts); ++ // Paper end + this.bukkitHandle = bukkit; + } + // CraftBukkit end +@@ -59,6 +65,7 @@ public class MerchantOffer { + + this.specialPriceDiff = nbttagcompound.getInt("specialPrice"); + this.demand = nbttagcompound.getInt("demand"); ++ this.ignoreDiscounts = nbttagcompound.getBoolean("Paper.IgnoreDiscounts"); // Paper + } + + public MerchantOffer(ItemStack buyItem, ItemStack sellItem, int maxUses, int rewardedExp, float priceMultiplier) { +@@ -70,10 +77,19 @@ public class MerchantOffer { + } + + public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int rewardedExp, float priceMultiplier) { +- this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, rewardedExp, priceMultiplier, 0); ++ // Paper start - add ignoreDiscounts param ++ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, rewardedExp, priceMultiplier, false); ++ } ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, boolean ignoreDiscounts) { ++ this(itemstack, itemstack1, itemstack2, i, j, k, f, 0, ignoreDiscounts); + } + + public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l) { ++ this(itemstack, itemstack1, itemstack2, i, j, k, f, l, false); ++ } ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l, boolean ignoreDiscounts) { ++ this.ignoreDiscounts = ignoreDiscounts; ++ // Paper end + this.rewardExp = true; + this.xp = 1; + this.baseCostA = itemstack; +@@ -189,6 +205,7 @@ public class MerchantOffer { + nbttagcompound.putFloat("priceMultiplier", this.priceMultiplier); + nbttagcompound.putInt("specialPrice", this.specialPriceDiff); + nbttagcompound.putInt("demand", this.demand); ++ nbttagcompound.putBoolean("Paper.IgnoreDiscounts", this.ignoreDiscounts); // Paper + return nbttagcompound; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java +index 212f9c7f3e73ffedf27b94abeac957b7d866a086..a6c8588f10c4c109833aea6a8b02c9048b6d9ea4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java +@@ -17,7 +17,12 @@ public class CraftMerchantRecipe extends MerchantRecipe { + } + + public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier) { +- super(result, uses, maxUses, experienceReward, experience, priceMultiplier); ++ // Paper start - add ignoreDiscounts param ++ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, false); ++ } ++ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, boolean ignoreDiscounts) { ++ super(result, uses, maxUses, experienceReward, experience, priceMultiplier, ignoreDiscounts); ++ // Paper end + this.handle = new net.minecraft.world.item.trading.MerchantOffer( + net.minecraft.world.item.ItemStack.EMPTY, + net.minecraft.world.item.ItemStack.EMPTY, +@@ -26,6 +31,7 @@ public class CraftMerchantRecipe extends MerchantRecipe { + maxUses, + experience, + priceMultiplier, ++ ignoreDiscounts, // Paper - add ignoreDiscounts param + this + ); + this.setExperienceReward(experienceReward); +@@ -81,6 +87,18 @@ public class CraftMerchantRecipe extends MerchantRecipe { + handle.priceMultiplier = priceMultiplier; + } + ++ // Paper start ++ @Override ++ public boolean shouldIgnoreDiscounts() { ++ return this.handle.ignoreDiscounts; ++ } ++ ++ @Override ++ public void setIgnoreDiscounts(boolean ignoreDiscounts) { ++ this.handle.ignoreDiscounts = ignoreDiscounts; ++ } ++ // Paper end ++ + public net.minecraft.world.item.trading.MerchantOffer toMinecraft() { + List ingredients = getIngredients(); + Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients"); +@@ -95,7 +113,7 @@ public class CraftMerchantRecipe extends MerchantRecipe { + if (recipe instanceof CraftMerchantRecipe) { + return (CraftMerchantRecipe) recipe; + } else { +- CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier()); ++ CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.shouldIgnoreDiscounts()); // Paper - shouldIgnoreDiscounts + craft.setIngredients(recipe.getIngredients()); + + return craft; diff --git a/Remapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch b/Remapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch new file mode 100644 index 0000000000..184345a27e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 30 Sep 2020 22:49:14 +0200 +Subject: [PATCH] Toggle for removing existing dragon + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 02bb85364560784adea47c877c13291c3d016b86..424754a0183b071d20c86f0420cec784a8992e2b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -683,4 +683,12 @@ public class PaperWorldConfig { + log("Using vanilla redstone algorithm."); + } + } ++ ++ public boolean shouldRemoveDragon = false; ++ private void shouldRemoveDragon() { ++ shouldRemoveDragon = getBoolean("should-remove-dragon", shouldRemoveDragon); ++ if (shouldRemoveDragon) { ++ log("The Ender Dragon will be removed if she already exists without a portal."); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 590df3b93b897613cad74f9920aec62b33a2f7f7..84447e9845edad2d228b94184b35b4afb453a14b 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -210,7 +210,7 @@ public class EndDragonFight { + this.dragonUUID = entityenderdragon.getUUID(); + EndDragonFight.LOGGER.info("Found that there's a dragon still alive ({})", entityenderdragon); + this.dragonKilled = false; +- if (!flag) { ++ if (!flag && this.level.paperConfig.shouldRemoveDragon) { // Paper + EndDragonFight.LOGGER.info("But we didn't have a portal, let's remove it."); + entityenderdragon.remove(); + this.dragonUUID = null; diff --git a/Remapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch b/Remapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch new file mode 100644 index 0000000000..2affffb90a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Sat, 31 Oct 2020 11:49:01 -0700 +Subject: [PATCH] Fix client lag on advancement loading + +When new advancements are added via the UnsafeValues#loadAdvancement +API, it triggers a full datapack reload when this is not necessary. The +advancement is already loaded directly into the advancement registry, +and the point of saving the advancement to the Bukkit datapack seems to +be for persistence. By removing the call to reload datapacks when an +advancement is loaded, the client no longer completely freezes up when +adding a new advancement. +To ensure the client still receives the updated advancement data, we +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/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index acb41cc3965154c5b515cd8e808bf2cf5dc850e4..b8d3f2c59199e245e2035d6205dd1a042aa93f77 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -97,6 +97,7 @@ public class PlayerAdvancements { + + } + ++ public final void reload(ServerAdvancementManager advancementDataWorld) { this.reload(advancementDataWorld); } // Paper - OBFHELPER + public void reload(ServerAdvancementManager advancementLoader) { + this.stopListening(); + this.advancements.clear(); +@@ -393,6 +394,7 @@ public class PlayerAdvancements { + + } + ++ public final void sendUpdateIfNeeded(ServerPlayer entityPlayer) { this.flushDirty(entityPlayer); } // Paper - OBFHELPER + public void flushDirty(ServerPlayer player) { + if (this.isFirstPacket || !this.visibilityChanged.isEmpty() || !this.progressChanged.isEmpty()) { + Map map = Maps.newHashMap(); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 9a16882deee21faf78ea46e08b2f2ad3fbb6021b..ac94fd569bd4c79e30adef148e09e395ba8c1812 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -307,7 +307,13 @@ public final class CraftMagicNumbers implements UnsafeValues { + Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex); + } + +- MinecraftServer.getServer().getPlayerList().reloadResources(); ++ // Paper start ++ //MinecraftServer.getServer().getPlayerList().reload(); ++ MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> { ++ player.getAdvancements().reload(MinecraftServer.getServer().getAdvancements()); ++ player.getAdvancements().sendUpdateIfNeeded(player); ++ }); ++ // Paper end + + return bukkit; + } diff --git a/Remapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch b/Remapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch new file mode 100644 index 0000000000..0c17d7553d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Smith +Date: Sat, 7 Nov 2020 01:20:33 +0000 +Subject: [PATCH] Item no age & no player pickup + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +index 9a410f557988d737c3b930a79ef2ccb2b5c8b406..aff17bb3bd22de492b9736d27b7f3e4bdb37134c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +@@ -10,6 +10,12 @@ import org.bukkit.entity.Item; + import org.bukkit.inventory.ItemStack; + + public class CraftItem extends CraftEntity implements Item { ++ ++ // Paper start ++ private final static int NO_AGE_TIME = (int) Short.MIN_VALUE; ++ private final static int NO_PICKUP_TIME = (int) Short.MAX_VALUE; ++ // Paper end ++ + private final ItemEntity item; + + public CraftItem(CraftServer server, Entity entity, ItemEntity item) { +@@ -57,6 +63,26 @@ public class CraftItem extends CraftEntity implements Item { + public void setCanMobPickup(boolean canMobPickup) { + item.canMobPickup = canMobPickup; + } ++ ++ @Override ++ public boolean canPlayerPickup() { ++ return item.pickupDelay != NO_PICKUP_TIME; ++ } ++ ++ @Override ++ public void setCanPlayerPickup(boolean canPlayerPickup) { ++ item.pickupDelay = canPlayerPickup ? 0 : NO_PICKUP_TIME; ++ } ++ ++ @Override ++ public boolean willAge() { ++ return item.age != NO_AGE_TIME; ++ } ++ ++ @Override ++ public void setWillAge(boolean willAge) { ++ item.age = willAge ? 0 : NO_AGE_TIME; ++ } + // Paper End + + @Override diff --git a/Remapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch b/Remapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch new file mode 100644 index 0000000000..78d729cb3e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 24 Jun 2020 12:39:08 -0600 +Subject: [PATCH] Beacon API - custom effect ranges + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +index 5f75c6d653a31f65fcf9c0e280d796e15d059c00..fed29e5707e2a7f64159d284c52647dd91e1948e 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -71,6 +71,26 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + return (hasSecondaryEffect()) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, getLevelCb(), getAmplification(), true, true)) : null; + } + // CraftBukkit end ++ // Paper start - add field/methods for custom range ++ private final String PAPER_RANGE_TAG = "Paper.Range"; ++ private double effectRange = -1; ++ ++ public double getEffectRange() { ++ if (this.effectRange < 0) { ++ return this.levels * 10 + 10; ++ } else { ++ return effectRange; ++ } ++ } ++ ++ public void setEffectRange(double range) { ++ this.effectRange = range; ++ } ++ ++ public void resetEffectRange() { ++ this.effectRange = -1; ++ } ++ // Paper end + + public BeaconBlockEntity() { + super(BlockEntityType.BEACON); +@@ -261,7 +281,8 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + + public List getHumansInRange() { + { +- double d0 = (double) (this.levels * 10 + 10); ++ // Paper - custom beacon ranges ++ double d0 = this.getEffectRange(); + + AABB axisalignedbb = (new AABB(this.worldPosition)).inflate(d0).expandTowards(0.0D, (double) this.level.getMaxBuildHeight(), 0.0D); + List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.player.Player.class, axisalignedbb); +@@ -361,6 +382,9 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + this.secondaryPower = MobEffect.byId(tag.getInt("Secondary")); + this.levels = tag.getInt("Levels"); // SPIGOT-5053, use where available + // CraftBukkit end ++ // Paper ++ this.effectRange = tag.contains(PAPER_RANGE_TAG, 6) ? tag.getDouble(PAPER_RANGE_TAG) : -1; ++ + if (tag.contains("CustomName", 8)) { + this.name = Component.Serializer.fromJson(tag.getString("CustomName")); + } +@@ -377,6 +401,8 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + if (this.name != null) { + tag.putString("CustomName", Component.Serializer.toJson(this.name)); + } ++ // Paper ++ tag.putDouble(PAPER_RANGE_TAG, this.effectRange); + + this.lockKey.addToTag(tag); + return tag; +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +index 940fef58f14e06213c7f305f67dcb8918976c03d..2a10a9352fdb52f5cb27eae2b6d3baa9ff95e486 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +@@ -108,4 +108,19 @@ public class CraftBeacon extends CraftBlockEntityState implem + public void setLock(String key) { + this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key); + } ++ ++ @Override ++ public double getEffectRange() { ++ return this.getSnapshot().getEffectRange(); ++ } ++ ++ @Override ++ public void setEffectRange(double range) { ++ this.getSnapshot().setEffectRange(range); ++ } ++ ++ @Override ++ public void resetEffectRange() { ++ this.getSnapshot().resetEffectRange(); ++ } + } diff --git a/Remapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch b/Remapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch new file mode 100644 index 0000000000..988b77b058 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 14 Nov 2020 16:19:52 +0100 +Subject: [PATCH] Add API for quit reason + + +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 6f7cbce5a049d87d4a0ed7cc4517cb4e8694efb5..3ba9c38fc44a8edba9b504112a383249052a0035 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -137,12 +137,15 @@ public class Connection extends SimpleChannelInboundHandler> { + + this.handlingFault = true; + if (this.channel.isOpen()) { ++ ServerPlayer player = this.getPlayer(); // Paper + if (throwable instanceof TimeoutException) { + Connection.LOGGER.debug("Timeout", throwable); ++ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper + this.disconnect(new TranslatableComponent("disconnect.timeout")); + } else { + TranslatableComponent chatmessage = new TranslatableComponent("disconnect.genericReason", new Object[]{"Internal Exception: " + throwable}); + ++ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper + if (flag) { + Connection.LOGGER.debug("Failed to sent packet", throwable); + this.send(new ClientboundDisconnectPacket(chatmessage), (future) -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index bd4d4ace35e966e819aa461d3962fe06ff402be7..1b5f24920c46cd238a79f5a2857d26fa1c12b983 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -258,6 +258,7 @@ public class ServerPlayer extends Player implements ContainerListener { + double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks + + boolean needsChunkCenterUpdate; // Paper - no-tick view distance ++ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event + + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { + super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 3a114bec14fcc6c1e1045e2b99178a6adb25f387..ccfe5a1ec1e9895f7462b7c676fee80903502a88 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -447,6 +447,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + final Component ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure + // CraftBukkit end + ++ this.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper + this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> { + this.connection.disconnect(ichatbasecomponent); + }); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7e44c911f4abc5c7d0e89513bf2cfc3516f13492..cda21726f4929b03191e912550d4e4b1232b3b0b 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -586,7 +586,7 @@ public abstract class PlayerList { + entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper + } + +- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName())), entityplayer.quitReason); // Paper - quit reason + if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + diff --git a/Remapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch b/Remapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch new file mode 100644 index 0000000000..40529ba82f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch @@ -0,0 +1,115 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Mon, 13 Jan 2020 15:40:32 +0100 +Subject: [PATCH] Seed based feature search + +This tries to work around the issue where the server will load +surrounding chunks up to a radius of 100 chunks in order to search for +features e.g. when running the /locate command or for treasure maps +(issue #2312). +This is done by backporting Mojang's change in 1.17 which makes it so +that the biome (generated by the seed) is checked first if the feature +can be generated before actually to load the chunk. + +Additionally to that the center location of the target chunk is simply +returned if the chunk is not loaded to avoid the sync chunk load. +As this can lead to less precise locations a toggle is provided to +enable the sync loading of the target chunk again. + +The main downside of this is that it breaks once the seed or generator +changes but this should usually not happen. A config option to disable +this completely is added though in case that should ever be necessary. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 424754a0183b071d20c86f0420cec784a8992e2b..97870622e41cca36d9c7493bfad796f35f3831f4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -337,6 +337,14 @@ public class PaperWorldConfig { + } + } + ++ public boolean seedBasedFeatureSearch = true; ++ public boolean seedBasedFeatureSearchLoadsChunks = false; ++ private void seedBasedFeatureSearch() { ++ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch); ++ seedBasedFeatureSearchLoadsChunks = getBoolean("seed-based-feature-search-loads-chunks", seedBasedFeatureSearchLoadsChunks); ++ log("Feature search is based on seed: " + seedBasedFeatureSearch + ", loads chunks:" + seedBasedFeatureSearchLoadsChunks); ++ } ++ + public int maxCollisionsPerEntity; + private void maxEntityCollision() { + maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); +diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java +index 4a5f318adf5bc2ca1c3fab5d173a99cddd77ab85..f61a3eda40328922b95f166be4dc604500e000be 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkPos.java ++++ b/src/main/java/net/minecraft/world/level/ChunkPos.java +@@ -68,10 +68,12 @@ public class ChunkPos { + } + } + ++ public int getBlockX() { return getMinBlockX(); } // Paper - OBFHELPER + public int getMinBlockX() { + return this.x << 4; + } + ++ public int getBlockZ() { return getMinBlockZ(); } // Paper - OBFHELPER + public int getMinBlockZ() { + return this.z << 4; + } +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 2ad8a4558aa812885adebee8c05dab45f2bf5f90..066d5f7ee93351bff67c0d39ee9d940ac51515d8 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -1511,8 +1511,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return this.profiler; + } + +- @Override +- public BiomeManager getBiomeManager() { ++ public BiomeManager getBiomeManager() { return getBiomeManager(); } // Paper - OBFHELPER ++ @Override public BiomeManager getBiomeManager() { + return this.biomeManager; + } + +diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java +index d22ac114440d807a6cf5f286961bc63935fa7823..3a1909c0b198d89539f4351d70a39d16cfd84987 100644 +--- a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java ++++ b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java +@@ -23,6 +23,7 @@ public class BiomeManager { + return new BiomeManager(source, this.biomeZoomSeed, this.zoomer); + } + ++ public Biome getBiome(BlockPos blockposition) { return getBiome(blockposition); } // Paper - OBFHELPER + public Biome getBiome(BlockPos pos) { + return this.zoomer.getBiome(this.biomeZoomSeed, pos.getX(), pos.getY(), pos.getZ(), this.noiseBiomeSource); + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +index 0624b8270bc28c83c5479cd51fa4633ed5c36f44..6b24590a1ac460a7fd4bbc2c70d4a4981378e79c 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +@@ -176,7 +176,24 @@ public abstract class StructureFeature { + int j2 = i1 + k * l1; + ChunkPos chunkcoordintpair = this.getPotentialFeatureChunk(config, worldSeed, seededrandom, i2, j2); + if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper +- ChunkAccess ichunkaccess = world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); ++ // Paper start - seed based feature search ++ ChunkAccess ichunkaccess = null; ++ if (structureAccessor.getWorld().paperConfig.seedBasedFeatureSearch) { ++ Biome biomeBase = structureAccessor.getWorld().getBiomeManager().getBiome(new BlockPos(chunkcoordintpair.getBlockX() + 9, 0, chunkcoordintpair.getBlockZ() + 9)); ++ if (!biomeBase.getGenerationSettings().isValidStart(this)) { ++ continue; ++ } ++ if (!structureAccessor.getWorld().paperConfig.seedBasedFeatureSearchLoadsChunks) { ++ ichunkaccess = structureAccessor.getWorld().getChunkIfLoaded(chunkcoordintpair.x, chunkcoordintpair.z); ++ if (ichunkaccess == null) { ++ return chunkcoordintpair.asPosition().add(8, searchStartPos.getY(), 8); ++ } ++ } ++ } ++ if (ichunkaccess == null) { ++ ichunkaccess = world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); ++ } ++ // Paper end + StructureStart structurestart = structureAccessor.getStartForFeature(SectionPos.of(ichunkaccess.getPos(), 0), this, ichunkaccess); + + if (structurestart != null && structurestart.e()) { diff --git a/Remapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch b/Remapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch new file mode 100644 index 0000000000..2dbaff374a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Thu, 20 Aug 2020 11:20:12 -0700 +Subject: [PATCH] Add Wandering Trader spawn rate config options + +Adds config options for modifying the spawn rates of Wandering Traders. +These values are all easy to understand and configure after a quick read of this +page on the Minecraft wiki: https://minecraft.gamepedia.com/Wandering_Trader#Spawning +Usages of the vanilla WanderingTraderSpawnDelay and WanderingTraderSpawnChance values +in IWorldServerData are removed as they were only used in certain places, with hardcoded +values used in other places. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 97870622e41cca36d9c7493bfad796f35f3831f4..5a451cc855de57f79a57670ba38e3af2343cb510 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -699,4 +699,17 @@ public class PaperWorldConfig { + log("The Ender Dragon will be removed if she already exists without a portal."); + } + } ++ ++ public int wanderingTraderSpawnMinuteTicks = 1200; ++ public int wanderingTraderSpawnDayTicks = 24000; ++ public int wanderingTraderSpawnChanceFailureIncrement = 25; ++ public int wanderingTraderSpawnChanceMin = 25; ++ public int wanderingTraderSpawnChanceMax = 75; ++ private void wanderingTraderSettings() { ++ wanderingTraderSpawnMinuteTicks = getInt("wandering-trader.spawn-minute-length", wanderingTraderSpawnMinuteTicks); ++ wanderingTraderSpawnDayTicks = getInt("wandering-trader.spawn-day-length", wanderingTraderSpawnDayTicks); ++ wanderingTraderSpawnChanceFailureIncrement = getInt("wandering-trader.spawn-chance-failure-increment", wanderingTraderSpawnChanceFailureIncrement); ++ wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); ++ wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +index c297051bc48ff20a6764496cbf11eef601761d13..9074d57e1576db2da3e4c76add4f7e07e5567879 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +@@ -30,49 +30,59 @@ public class WanderingTraderSpawner implements CustomSpawner { + + private final Random random = new Random(); + private final ServerLevelData serverLevelData; +- private int tickDelay; +- private int spawnDelay; +- private int spawnChance; ++ private int tickDelay; public final int getMinuteTimer() { return this.tickDelay; } public final void setMinuteTimer(int x) { this.tickDelay = x; } // Paper - OBFHELPER ++ private int spawnDelay; public final int getDayTimer() { return this.spawnDelay; } public final void setDayTimer(int x) { this.spawnDelay = x; } // Paper - OBFHELPER ++ private int spawnChance; public final int getSpawnChance() { return this.spawnChance; } public final void setSpawnChance(int x) { this.spawnChance = x; } // Paper - OBFHELPER + + public WanderingTraderSpawner(ServerLevelData properties) { + this.serverLevelData = properties; +- this.tickDelay = 1200; +- this.spawnDelay = properties.getWanderingTraderSpawnDelay(); +- this.spawnChance = properties.getWanderingTraderSpawnChance(); +- if (this.spawnDelay == 0 && this.spawnChance == 0) { +- this.spawnDelay = 24000; +- properties.setWanderingTraderSpawnDelay(this.spawnDelay); +- this.spawnChance = 25; +- properties.setWanderingTraderSpawnChance(this.spawnChance); +- } ++ // Paper start ++ this.setMinuteTimer(Integer.MIN_VALUE); ++ //this.d = iworlddataserver.v(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value ++ //this.e = iworlddataserver.w(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value ++ //if (this.d == 0 && this.e == 0) { ++ // this.d = 24000; ++ // iworlddataserver.g(this.d); ++ // this.e = 25; ++ // iworlddataserver.h(this.e); ++ //} ++ // Paper end + + } + + @Override + public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { ++ // Paper start ++ if (this.getMinuteTimer() == Integer.MIN_VALUE) { ++ this.setMinuteTimer(world.paperConfig.wanderingTraderSpawnMinuteTicks); ++ this.setDayTimer(world.paperConfig.wanderingTraderSpawnDayTicks); ++ this.setSpawnChance(world.paperConfig.wanderingTraderSpawnChanceMin); ++ } + if (!world.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) { + return 0; +- } else if (--this.tickDelay > 0) { ++ } else if (this.getMinuteTimer() - 1 > 0) { ++ this.setMinuteTimer(this.getMinuteTimer() - 1); + return 0; + } else { +- this.tickDelay = 1200; +- this.spawnDelay -= 1200; +- this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay); +- if (this.spawnDelay > 0) { ++ this.setMinuteTimer(world.paperConfig.wanderingTraderSpawnMinuteTicks); ++ this.setDayTimer(getDayTimer() - world.paperConfig.wanderingTraderSpawnMinuteTicks); ++ //this.b.g(this.d); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways ++ if (this.getDayTimer() > 0) { + return 0; + } else { +- this.spawnDelay = 24000; ++ this.setDayTimer(world.paperConfig.wanderingTraderSpawnDayTicks); + if (!world.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { + return 0; + } else { +- int i = this.spawnChance; ++ int i = this.getSpawnChance(); + +- this.spawnChance = Mth.clamp(this.spawnChance + 25, 25, 75); +- this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); ++ this.setSpawnChance(Mth.clamp(i + world.paperConfig.wanderingTraderSpawnChanceFailureIncrement, world.paperConfig.wanderingTraderSpawnChanceMin, world.paperConfig.wanderingTraderSpawnChanceMax)); ++ //this.b.h(this.e); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways + if (this.random.nextInt(100) > i) { + return 0; + } else if (this.spawn(world)) { +- this.spawnChance = 25; ++ this.setSpawnChance(world.paperConfig.wanderingTraderSpawnChanceMin); ++ // Paper end + return 1; + } else { + return 0; diff --git a/Remapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch b/Remapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch new file mode 100644 index 0000000000..22a13c79b6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch @@ -0,0 +1,77 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com> +Date: Tue, 3 Nov 2020 23:48:05 -0600 +Subject: [PATCH] Significantly improve performance of the end generation + +This patch implements a noise cache for the end which significantly reduces the computation time of generation. This results in about a 3x improvement. + +Original code by SuperCoder7979 and Gegy in Lithium, licensed under LGPL-3.0 (Source: https://github.com/jellysquid3/lithium-fabric) + +Co-authored-by: Gegy +Co-authored-by: Dylan Xaldin +Co-authored-by: pop4959 + +diff --git a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +index 063369d3a64b4afc9cc6e1d20360900595e1a05f..f01d1b01ebc31f0967a73871f278aac9e414fb67 100644 +--- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java ++++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +@@ -3,10 +3,12 @@ package net.minecraft.world.level.biome; + import com.google.common.collect.ImmutableList; + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; ++import it.unimi.dsi.fastutil.HashCommon; // Paper + import java.util.List; + import net.minecraft.core.Registry; + import net.minecraft.resources.RegistryLookupCodec; + import net.minecraft.util.Mth; ++import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.levelgen.WorldgenRandom; + import net.minecraft.world.level.levelgen.synth.SimplexNoise; + +@@ -27,6 +29,16 @@ public class TheEndBiomeSource extends BiomeSource { + private final Biome midlands; + private final Biome islands; + private final Biome barrens; ++ // Paper start ++ private static final class NoiseCache { ++ public long[] keys = new long[8192]; ++ public float[] values = new float[8192]; ++ public NoiseCache() { ++ java.util.Arrays.fill(keys, Long.MIN_VALUE); ++ } ++ } ++ private static final ThreadLocal> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new); ++ // Paper end + + public TheEndBiomeSource(Registry biomeRegistry, long seed) { + this(biomeRegistry, seed, (Biome) biomeRegistry.lifecycle(Biomes.THE_END), (Biome) biomeRegistry.lifecycle(Biomes.END_HIGHLANDS), (Biome) biomeRegistry.lifecycle(Biomes.END_MIDLANDS), (Biome) biomeRegistry.lifecycle(Biomes.SMALL_END_ISLANDS), (Biome) biomeRegistry.lifecycle(Biomes.END_BARRENS)); +@@ -81,13 +93,27 @@ public class TheEndBiomeSource extends BiomeSource { + + f = Mth.clamp(f, -100.0F, 80.0F); + ++ NoiseCache cache = noiseCache.get().computeIfAbsent(noisegenerator3handler, m -> new NoiseCache()); // Paper + for (int k1 = -12; k1 <= 12; ++k1) { + for (int l1 = -12; l1 <= 12; ++l1) { + long i2 = (long) (k + k1); + long j2 = (long) (l + l1); + +- if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.getValue((double) i2, (double) j2) < -0.8999999761581421D) { +- float f1 = (Mth.abs((float) i2) * 3439.0F + Mth.abs((float) j2) * 147.0F) % 13.0F + 9.0F; ++ // Paper start - Significantly improve end generation performance by using a noise cache ++ long key = ChunkPos.asLong((int) i2, (int) j2); ++ int index = (int) HashCommon.mix(key) & 8191; ++ float f1 = Float.MIN_VALUE; ++ if (cache.keys[index] == key) { ++ f1 = cache.values[index]; ++ } else { ++ if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.getValue((double) i2, (double) j2) < -0.8999999761581421D) { ++ f1 = (Mth.abs((float) i2) * 3439.0F + Mth.abs((float) j2) * 147.0F) % 13.0F + 9.0F; ++ } ++ cache.keys[index] = key; ++ cache.values[index] = f1; ++ } ++ if (f1 != Float.MIN_VALUE) { ++ // Paper end + float f2 = (float) (i1 - k1 * 2); + float f3 = (float) (j1 - l1 * 2); + float f4 = 100.0F - Mth.sqrt(f2 * f2 + f3 * f3) * f1; diff --git a/Remapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch b/Remapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch new file mode 100644 index 0000000000..0086ded8da --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Tue, 17 Nov 2020 19:13:09 +0200 +Subject: [PATCH] Expose world spawn angle + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index cda21726f4929b03191e912550d4e4b1232b3b0b..7e07fd0c8dec9f9cdeda65dfa0ccf42b4dde010e 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -890,7 +890,7 @@ public abstract class PlayerList { + if (location == null) { + worldserver1 = this.server.getLevel(Level.OVERWORLD); + blockposition = entityplayer1.getSpawnPoint(worldserver1); +- location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F)); ++ location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F), worldserver1.levelData.getSpawnAngle(), 0.0F); // Paper - use world spawn angle + } + + Player respawnPlayer = cserver.getPlayer(entityplayer1); +diff --git a/src/main/java/net/minecraft/world/level/storage/LevelData.java b/src/main/java/net/minecraft/world/level/storage/LevelData.java +index 12a2371b15588ae84824d7a2d36a6d4c37e77013..078cee770a77b77d9b4a777754599d7b0b31f54b 100644 +--- a/src/main/java/net/minecraft/world/level/storage/LevelData.java ++++ b/src/main/java/net/minecraft/world/level/storage/LevelData.java +@@ -12,6 +12,7 @@ public interface LevelData { + + int getZSpawn(); + ++ default float getSpawnAngle() { return getSpawnAngle(); } // Paper - OBFHELPER + float getSpawnAngle(); + + long getGameTime(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 28bf53bc9fca21f57cd4851adf508d833ecdd33b..aaf97c13babce3b0ffc639ef950d59d1eba1398a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -362,7 +362,7 @@ public class CraftWorld implements World { + @Override + public Location getSpawnLocation() { + BlockPos spawn = world.getSpawn(); +- return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); ++ return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ(), world.levelData.getSpawnAngle(), 0.0F); // Paper - expose world spawn angle + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch b/Remapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch new file mode 100644 index 0000000000..53910619a5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ineusia +Date: Mon, 26 Oct 2020 11:48:06 -0500 +Subject: [PATCH] Add Destroy Speed API + +Co-authored-by: Jake Potrebic + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 37eceaef1212e2ee13aa763a5ede24ec170e5391..9defb202761296a825d035e27ddc51e17a311647 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -766,5 +766,23 @@ public class CraftBlock implements Block { + public String getTranslationKey() { + return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); + } ++ ++ @Override ++ public float getDestroySpeed(ItemStack itemStack, boolean considerEnchants) { ++ net.minecraft.world.item.ItemStack nmsItemStack; ++ if (itemStack instanceof CraftItemStack) { ++ nmsItemStack = ((CraftItemStack) itemStack).getHandle(); ++ } else { ++ nmsItemStack = CraftItemStack.asNMSCopy(itemStack); ++ } ++ float speed = nmsItemStack.getItem().getDestroySpeed(nmsItemStack, this.getNMSBlock().defaultBlockState()); ++ if (speed > 1.0F && considerEnchants) { ++ int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.BLOCK_EFFICIENCY, nmsItemStack); ++ if (enchantLevel > 0) { ++ speed += enchantLevel * enchantLevel + 1; ++ } ++ } ++ return speed; ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/Remapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch new file mode 100644 index 0000000000..95a480a03b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Esophose +Date: Sat, 3 Oct 2020 18:57:47 -0600 +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 94240b70e245bdc3dda60420f5787f8d5dcc1958..40380fff222cc1f3340cf6a6c4afbe60aaa5d3a6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2008,7 +2008,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + if (data != null && !particle.getDataType().isInstance(data)) { + throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); + } +- ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.toNMS(particle, data), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); ++ ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.toNMS(particle, data), true, x, y, z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); // Paper - Fix x/y/z coordinate precision loss + getHandle().connection.send(packetplayoutworldparticles); + + } diff --git a/Remapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch b/Remapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch new file mode 100644 index 0000000000..308d4591ab --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Anrza +Date: Wed, 15 Jul 2020 12:08:49 +0200 +Subject: [PATCH] Add LivingEntity#clearActiveItem + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index eb136af0f99f5d7520ceabb98cefd5a01122872c..170bb1124ee396a85dd64baed8110e39823ad849 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -773,6 +773,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return getHandle().useItem.asBukkitMirror(); + } + ++ // Paper start ++ @Override ++ public void clearActiveItem() { ++ getHandle().stopUsingItem(); ++ } ++ // Paper end ++ + @Override + public int getItemUseRemainingTime() { + return getHandle().getItemUseRemainingTime(); diff --git a/Remapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch b/Remapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch new file mode 100644 index 0000000000..4d8772cbb5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Tue, 25 Aug 2020 13:48:33 +0200 +Subject: [PATCH] Add PlayerItemCooldownEvent + + +diff --git a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java +index 93161583c215e1832570b39e72f7e7cfb94a700c..1983cdcefed60795e8c88737ae3459d5821cdcfa 100644 +--- a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java ++++ b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java +@@ -1,16 +1,27 @@ + package net.minecraft.world.item; + ++import io.papermc.paper.event.player.PlayerItemCooldownEvent; // Paper + import net.minecraft.network.protocol.game.ClientboundCooldownPacket; + import net.minecraft.server.level.ServerPlayer; + + public class ServerItemCooldowns extends ItemCooldowns { + +- private final ServerPlayer player; ++ private final ServerPlayer player; public ServerPlayer getEntityPlayer() { return player; } // Paper - OBFHELPER + + public ServerItemCooldowns(ServerPlayer player) { + this.player = player; + } + ++ // Paper start ++ @Override ++ public void addCooldown(Item item, int duration) { ++ PlayerItemCooldownEvent event = new PlayerItemCooldownEvent(getEntityPlayer().getBukkitEntity(), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(item), duration); ++ if (event.callEvent()) { ++ super.addCooldown(item, event.getCooldown()); ++ } ++ } ++ // Paper end ++ + @Override + protected void onCooldownStarted(Item item, int duration) { + super.onCooldownStarted(item, duration); diff --git a/Remapped-Spigot-Server-Patches/0604-More-lightning-API.patch b/Remapped-Spigot-Server-Patches/0604-More-lightning-API.patch new file mode 100644 index 0000000000..6c4c8bac10 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0604-More-lightning-API.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Sun, 26 Jul 2020 14:44:09 +0200 +Subject: [PATCH] More lightning API + + +diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java +index 4b0dbeded2b8a475d32f518957909d3495a4b6fc..3fdef4511e21e453b89e42a8f41e587fe300ba6b 100644 +--- a/src/main/java/net/minecraft/world/entity/LightningBolt.java ++++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java +@@ -28,7 +28,7 @@ public class LightningBolt extends Entity { + + private int life; + public long seed; +- private int flashes; ++ private int flashes; public int getFlashCount() { return flashes; } public void setFlashCount(int flashes) { this.flashes = flashes; } // Paper - OBFHELPER + public boolean visualOnly; + @Nullable + private ServerPlayer cause; +@@ -46,6 +46,16 @@ public class LightningBolt extends Entity { + this.visualOnly = cosmetic; + } + ++ // Paper start ++ public int getLifeTicks() { ++ return life; ++ } ++ ++ public void setLifeTicks(int lifeTicks) { ++ this.life = lifeTicks; ++ } ++ // Paper end ++ + @Override + public SoundSource getSoundSource() { + return SoundSource.WEATHER; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java +index 26506c22592b58b208487fb244985361d70988a8..c1593bb345b38deb4d8b28a73d8dc6246c17b873 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java +@@ -45,4 +45,27 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike + return spigot; + } + // Spigot end ++ ++ // Paper start ++ @Override ++ public int getFlashCount() { ++ return getHandle().getFlashCount(); ++ } ++ ++ @Override ++ public void setFlashCount(int flashes) { ++ com.google.common.base.Preconditions.checkArgument(flashes >= 0, "Flashes has to be a positive number!"); ++ getHandle().setFlashCount(flashes); ++ } ++ ++ @Override ++ public int getLifeTicks() { ++ return getHandle().getLifeTicks(); ++ } ++ ++ @Override ++ public void setLifeTicks(int lifeTicks) { ++ getHandle().setLifeTicks(lifeTicks); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch b/Remapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch new file mode 100644 index 0000000000..c25768004e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch @@ -0,0 +1,179 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 23 Aug 2020 20:59:00 +0200 +Subject: [PATCH] Climbing should not bypass cramming gamerule + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5a451cc855de57f79a57670ba38e3af2343cb510..7d3207a9af8360ddad228281d6aa65e1a0d24157 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -712,4 +712,9 @@ public class PaperWorldConfig { + wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); + wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); + } ++ ++ public boolean fixClimbingBypassingCrammingRule = false; ++ private void fixClimbingBypassingCrammingRule() { ++ fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 90e9797cc1f3a4aa0a2bee28dca364e6f6dd0c0b..ec98f5f59ca2b4cb58eb00ed8cdfa364f8bacd88 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1573,6 +1573,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean isPushable() { ++ // Paper start ++ return isCollidable(false); ++ } ++ ++ public boolean isCollidable(boolean ignoreClimbing) { ++ // Paper end + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index 8ce62148ebaeac9988e7c9d4b2f7ee57f58d883e..8d1e24c2fa844971908ae7ac918a8950026b40a6 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -51,11 +51,17 @@ public final class EntitySelector { + } + + public static Predicate pushableBy(Entity entity) { ++ // Paper start - ignoreClimbing param ++ return pushable(entity, false); ++ } ++ ++ public static Predicate pushable(Entity entity, boolean ignoreClimbing) { ++ // Paper end + Team scoreboardteambase = entity.getTeam(); + Team.CollisionRule scoreboardteambase_enumteampush = scoreboardteambase == null ? Team.CollisionRule.ALWAYS : scoreboardteambase.getCollisionRule(); + + return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> { +- if (!entity1.canCollideWithCb(entity) || !entity.canCollideWithCb(entity1)) { // CraftBukkit - collidable API ++ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWithCb(entity) || !entity.canCollideWithCb(entity1)) { // CraftBukkit - collidable API // Paper - isCollidable + return false; + } 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 9724d4222311345a44aa101ec47523a1909fbe8f..57b933afdbb2136ed48170da6945eb2b92edb4db 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -134,7 +134,6 @@ import org.bukkit.event.entity.EntityTeleportEvent; + import org.bukkit.event.player.PlayerItemConsumeEvent; + // CraftBukkit end + +-import co.aikar.timings.MinecraftTimings; // Paper + + public abstract class LivingEntity extends Entity { + +@@ -2956,7 +2955,7 @@ public abstract class LivingEntity extends Entity { + return; + } + // Paper - end don't run getEntities if we're not going to use its result +- List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); ++ List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushable(this, level.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule + + if (!list.isEmpty()) { + // Paper - move up +@@ -3094,9 +3093,16 @@ public abstract class LivingEntity extends Entity { + return !this.removed && this.collides; // CraftBukkit + } + ++ // Paper start + @Override + public boolean isPushable() { +- return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit ++ return this.isCollidable(level.paperConfig.fixClimbingBypassingCrammingRule); ++ } ++ ++ @Override ++ public boolean isCollidable(boolean ignoreClimbing) { ++ return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.onClimbable()) && this.collides; // CraftBukkit ++ // Paper end + } + + // CraftBukkit start - collidable API +diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java +index e56c575d744e1efe9a7512f337b781dc3715f6be..8e02e3a4464ab4096637fc69c03d083988bb426e 100644 +--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java ++++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java +@@ -75,7 +75,7 @@ public class Bat extends AmbientCreature { + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java +index 918628c0ed8fb32d44c034fddf045f08659c10f8..d6a9d0e94d80f1924cedef913829d15762456537 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java +@@ -368,8 +368,8 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { + } + + @Override +- public boolean isPushable() { +- return super.isPushable(); // CraftBukkit - collidable API ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper ++ return super.isCollidable(ignoreClimbing); // CraftBukkit - collidable API // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +index d9bfc754d7544a54ff214b41b4f6c0a6bc66df28..b298bcfb665b1036cd21445cec1518069eb08f06 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +@@ -226,7 +226,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return !this.isVehicle(); + } + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 5714aa450ac09788bcf1c2790d4f1581c9a7c28b..a89573670f7dccfd8f0c81fcd95673b6faf3fc10 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -358,7 +358,7 @@ public class ArmorStand extends LivingEntity { + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 1257a740a4ab79870fe89057782e8ffc6c658c14..9cbde70787d8044f0edeb3d459231dd7fbb79584 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -144,7 +144,7 @@ public abstract class AbstractMinecart extends Entity { + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return true; + } + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +index bddc51c656f04f25744ec29cabab31d465cf8bce..4f82c6797fe9bbb1a29420ea15277be50e44808c 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +@@ -149,7 +149,7 @@ public class Boat extends Entity { + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return true; + } + diff --git a/Remapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch b/Remapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch new file mode 100644 index 0000000000..25843d00d1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 16 Nov 2020 12:01:52 -0800 +Subject: [PATCH] Added missing default perms for commands + + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java +index d5f4ece060b61de9ca5292d1f2411c709de5ece2..f0a57d225b81a505ff12425155ba838d8fad990c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java +@@ -31,6 +31,59 @@ public final class CommandPermissions { + DefaultPermissions.registerPermission(PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands); ++ // Paper start ++ DefaultPermissions.registerPermission(PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "ban", "Allows the user to add players to banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "ban-ip", "Allows the user to add ip address to banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "banlist", "Allows the user to display banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "pardon", "Allows the user to remove entries from the banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "replaceitem", "Allows the user to replace items in inventories", PermissionDefault.OP, commands); // Remove in 1.17 (replaced by /item) ++ DefaultPermissions.registerPermission(PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands); ++ DefaultPermissions.registerPermission(PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands); ++ // Paper end + + DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands); + diff --git a/Remapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch b/Remapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch new file mode 100644 index 0000000000..c9ae36d161 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch @@ -0,0 +1,116 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Thu, 27 Aug 2020 15:02:48 -0400 +Subject: [PATCH] Add PlayerShearBlockEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java +index 1a01937f5250f3a529932dc2fdd9e1ebd9ae896a..125e646b39ef4a59be3989df16b5625c5504aac1 100644 +--- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.level.block; + ++import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts ++ + import java.util.Iterator; + import java.util.List; + import java.util.Random; +@@ -10,6 +12,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.Tag; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; +@@ -116,8 +119,19 @@ public class BeehiveBlock extends BaseEntityBlock { + + if (i >= 5) { + if (itemstack.getItem() == Items.SHEARS) { ++ // Paper start - Add PlayerShearBlockEvent ++ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); ++ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3))); ++ if (!event.callEvent()) { ++ return InteractionResult.PASS; ++ } ++ // Paper end + world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.NEUTRAL, 1.0F, 1.0F); +- dropHoneycomb(world, pos); ++ // Paper start - Add PlayerShearBlockEvent ++ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { ++ dropItem(world, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); ++ } ++ // Paper end + itemstack.hurtAndBreak(1, player, (entityhuman1) -> { + entityhuman1.broadcastBreakEvent(hand); + }); +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index baa587e73a71d6324bb7817fa4702a7c3a2db726..5f1853c3f22661809437bdb49f002482da7195f2 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -262,13 +262,13 @@ public class Block extends BlockBehaviour implements ItemLike { + + } + +- public static void popResource(Level world, BlockPos pos, ItemStack stack) { +- if (!world.isClientSide && !stack.isEmpty() && world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { ++ public static void popResource(Level world, BlockPos pos, ItemStack stack) { dropItem(world, pos, stack); } public static void dropItem(Level world, BlockPos blockposition, ItemStack itemstack) { // Paper - OBFHELPER ++ if (!world.isClientSide && !itemstack.isEmpty() && world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { + float f = 0.5F; + double d0 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; + double d1 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; + double d2 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; +- ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + d0, (double) pos.getY() + d1, (double) pos.getZ() + d2, stack); ++ ItemEntity entityitem = new ItemEntity(world, (double) blockposition.getX() + d0, (double) blockposition.getY() + d1, (double) blockposition.getZ() + d2, itemstack); + + entityitem.setDefaultPickUpDelay(); + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java +index fe528f7dee693982285ce035abd9929cb4e0cbdf..7cac13ad06ee7acfc3bdcbf79318dbfbd2a31e02 100644 +--- a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; + + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.InteractionHand; +@@ -14,6 +15,7 @@ import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.BlockHitResult; ++import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts + + public class PumpkinBlock extends StemGrownBlock { + +@@ -27,15 +29,26 @@ public class PumpkinBlock extends StemGrownBlock { + + if (itemstack.getItem() == Items.SHEARS) { + if (!world.isClientSide) { ++ // Paper start - Add PlayerShearBlockEvent ++ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); ++ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4))); ++ if (!event.callEvent()) { ++ return InteractionResult.PASS; ++ } ++ // Paper end + Direction enumdirection = hit.getDirection(); + Direction enumdirection1 = enumdirection.getAxis() == Direction.Axis.Y ? player.getDirection().getOpposite() : enumdirection; + + world.playSound((Player) null, pos, SoundEvents.PUMPKIN_CARVE, SoundSource.BLOCKS, 1.0F, 1.0F); + world.setBlock(pos, (BlockState) Blocks.CARVED_PUMPKIN.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, enumdirection1), 11); +- ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) enumdirection1.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) enumdirection1.getStepZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4)); ++ // Paper start - Add PlayerShearBlockEvent ++ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { ++ ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) enumdirection1.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) enumdirection1.getStepZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); ++ // Paper end + + entityitem.setDeltaMovement(0.05D * (double) enumdirection1.getStepX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double) enumdirection1.getStepZ() + world.random.nextDouble() * 0.02D); + world.addFreshEntity(entityitem); ++ } // Paper - Add PlayerShearBlockEvent + itemstack.hurtAndBreak(1, player, (entityhuman1) -> { + entityhuman1.broadcastBreakEvent(hand); + }); diff --git a/Remapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch b/Remapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch new file mode 100644 index 0000000000..ce4786d7fc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Wed, 2 Dec 2020 21:58:45 -0800 +Subject: [PATCH] Add warning for servers not running on Java 16 + + +diff --git a/src/main/java/io/papermc/paper/util/PaperJvmChecker.java b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fdf3ff8894e5e202229d1be52fe3c92ea039ef15 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java +@@ -0,0 +1,48 @@ ++package io.papermc.paper.util; ++ ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++ ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class PaperJvmChecker { ++ ++ private static int getJvmVersion() { ++ String javaVersion = System.getProperty("java.version"); ++ final Matcher matcher = Pattern.compile("(?:1\\.)?(\\d+)").matcher(javaVersion); ++ if (!matcher.find()) { ++ LogManager.getLogger().warn("Failed to determine Java version; Could not parse: {}", javaVersion); ++ return -1; ++ } ++ ++ final String version = matcher.group(1); ++ try { ++ return Integer.parseInt(version); ++ } catch (final NumberFormatException e) { ++ LogManager.getLogger().warn("Failed to determine Java version; Could not parse {} from {}", version, javaVersion, e); ++ return -1; ++ } ++ } ++ ++ public static void checkJvm() { ++ if (getJvmVersion() < 16) { ++ final Logger logger = LogManager.getLogger(); ++ logger.warn("************************************************************"); ++ logger.warn("* WARNING - YOU ARE RUNNING AN OUTDATED VERSION OF JAVA."); ++ logger.warn("* PAPER WILL STOP BEING COMPATIBLE WITH THIS VERSION OF"); ++ logger.warn("* JAVA WHEN MINECRAFT 1.17 IS RELEASED."); ++ logger.warn("*"); ++ logger.warn("* Please update the version of Java you use to run Paper"); ++ logger.warn("* to at least Java 16. When Paper for Minecraft 1.17 is"); ++ logger.warn("* released support for versions of Java before 16 will"); ++ logger.warn("* be dropped."); ++ logger.warn("*"); ++ logger.warn("* Current Java version: {}", System.getProperty("java.version")); ++ logger.warn("*"); ++ logger.warn("* Check this forum post for more information: "); ++ logger.warn("* https://papermc.io/java16"); ++ logger.warn("************************************************************"); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 954dce690852da87a37e7797c6f9f549242e511a..c83f2636ae93d92381e019d5b13ac82c5a1d30bf 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -180,6 +180,7 @@ import org.bukkit.event.server.ServerLoadEvent; + + import co.aikar.timings.MinecraftTimings; // Paper + import org.spigotmc.SlackActivityAccountant; // Spigot ++import io.papermc.paper.util.PaperJvmChecker; // Paper + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { + +@@ -1075,6 +1076,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Wed, 2 Dec 2020 20:17:54 -0800 +Subject: [PATCH] Set spigots verbose world setting to false by def + + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 6b015c1f26facb4e82d75b252164dec05731ca6c..094a934c168d232b0550c3efe722f2ebfbdf8e24 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -20,7 +20,7 @@ public class SpigotWorldConfig + + public void init() + { +- this.verbose = getBoolean( "verbose", true ); ++ this.verbose = getBoolean( "verbose", false ); // Paper + + log( "-------- World Settings For [" + worldName + "] --------" ); + SpigotConfig.readConfig( SpigotWorldConfig.class, this ); diff --git a/Remapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch b/Remapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch new file mode 100644 index 0000000000..852cffc989 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 8 Dec 2020 20:14:20 -0600 +Subject: [PATCH] Fix curing zombie villager discount exploit + +This fixes the exploit used to gain absurd trading discounts with infecting +and curing a villager on repeat by simply resetting the relevant part of +the reputation when it is cured. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 7d3207a9af8360ddad228281d6aa65e1a0d24157..a3b3e3e04b7a5e3a351992e06870cc91fbd8adc8 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -717,4 +717,9 @@ public class PaperWorldConfig { + private void fixClimbingBypassingCrammingRule() { + fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); + } ++ ++ public boolean fixCuringZombieVillagerDiscountExploit = true; ++ private void fixCuringExploit() { ++ fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +index 57832c392910d22aa81ac2b4816d043dd7ac867a..9a68201bab4fcbad69c85e2469a103634b65d7b3 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +@@ -223,6 +223,7 @@ public class GossipContainer { + + } + ++ public final void removeReputationForType(GossipType reputationType) { this.remove(reputationType); } // Paper - OBFHELPER + public void remove(GossipType gossipType) { + this.entries.removeInt(gossipType); + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 415fa3591add1f1ab22dd5866e110dbfccd0ec93..7817071b1964b962c8f4017d5bb39d74ca0ca3e4 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -1013,6 +1013,15 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + @Override + public void onReputationEventFrom(ReputationEventType interaction, Entity entity) { + if (interaction == ReputationEventType.ZOMBIE_VILLAGER_CURED) { ++ // Paper start - fix MC-181190 ++ if (level.paperConfig.fixCuringZombieVillagerDiscountExploit) { ++ final GossipContainer.EntityGossips playerReputation = this.getReputation().getReputations().get(entity.getUUID()); ++ if (playerReputation != null) { ++ playerReputation.removeReputationForType(GossipType.MAJOR_POSITIVE); ++ playerReputation.removeReputationForType(GossipType.MINOR_POSITIVE); ++ } ++ } ++ // Paper end + this.gossips.add(entity.getUUID(), GossipType.MAJOR_POSITIVE, 20); + this.gossips.add(entity.getUUID(), GossipType.MINOR_POSITIVE, 25); + } else if (interaction == ReputationEventType.TRADE) { diff --git a/Remapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch b/Remapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch new file mode 100644 index 0000000000..dc1bd95672 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 12 Dec 2020 23:45:28 +0000 +Subject: [PATCH] Limit recipe packets + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 7d50aded88f5b7dfebaea1aebc86231f7b5c4e25..652d87fc5d566dba8018c81676329f0e0bca471b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -334,6 +334,13 @@ public class PaperConfig { + tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); + } + ++ public static int autoRecipeIncrement = 1; ++ public static int autoRecipeLimit = 20; ++ private static void autoRecipieLimiters() { ++ autoRecipeIncrement = getInt("settings.spam-limiter.recipe-spam-increment", autoRecipeIncrement); ++ autoRecipeLimit = getInt("settings.spam-limiter.recipe-spam-limit", autoRecipeLimit); ++ } ++ + public static boolean velocitySupport; + public static boolean velocityOnlineMode; + public static byte[] velocitySecretKey; +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index ccfe5a1ec1e9895f7462b7c676fee80903502a88..e50e42cce60c725cdd981d8927e379c5760d9200 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1,5 +1,6 @@ + package net.minecraft.server.network; + ++import com.destroystokyo.paper.PaperConfig; + import com.google.common.collect.Lists; + import com.google.common.primitives.Doubles; + import com.google.common.primitives.Floats; +@@ -174,6 +175,7 @@ import io.papermc.paper.adventure.ChatProcessor; // Paper + import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.util.concurrent.ExecutionException; + import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; ++import org.bukkit.Bukkit; // Paper + import org.bukkit.Location; + import org.bukkit.craftbukkit.entity.CraftPlayer; + import org.bukkit.craftbukkit.event.CraftEventFactory; +@@ -232,6 +234,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private volatile int chatSpamTickCount; + private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(ServerGamePacketListenerImpl.class, "chatThrottle"); + private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits ++ private final java.util.concurrent.atomic.AtomicInteger recipeSpamPackets = new java.util.concurrent.atomic.AtomicInteger(); // Paper - auto recipe limit + // CraftBukkit end + private int dropSpamTickCount; + private final Int2ShortMap expectedAcks = new Int2ShortOpenHashMap(); +@@ -380,6 +383,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit start + for (int spam; (spam = this.chatSpamTickCount) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; + if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable ++ if (recipeSpamPackets.get() > 0) recipeSpamPackets.getAndDecrement(); // Paper + /* Use thread-safe field access instead + if (this.chatThrottle > 0) { + --this.chatThrottle; +@@ -2786,6 +2790,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + @Override + public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) { ++ // Paper start ++ if (!Bukkit.isPrimaryThread()) { ++ if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ return; ++ } ++ } ++ // Paper end + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + this.player.resetLastActionTime(); + if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu.isSynched(this.player) && this.player.containerMenu instanceof RecipeBookMenu) { diff --git a/Remapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch b/Remapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch new file mode 100644 index 0000000000..60e8ef1e6b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Thu, 17 Dec 2020 15:25:49 -0600 +Subject: [PATCH] Fix CraftSound backwards compatibility + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java +index 266563e72b563fd9db85f17bca710bbe45e8a22d..b2667c5f0794d521766203fea3299f12e21f5c76 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java +@@ -26,4 +26,10 @@ public class CraftSound { + public static Sound getBukkit(SoundEvent soundEffect) { + return Registry.SOUNDS.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.Registry.SOUND_EVENT.getKey(soundEffect))); + } ++ ++ // Paper start ++ public static String getSound(Sound sound) { ++ return sound.getKey().getKey(); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch b/Remapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch new file mode 100644 index 0000000000..3d3624adc8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 8 Dec 2020 20:24:52 -0600 +Subject: [PATCH] MC-4: Fix item position desync + +This fixes item position desync (MC-4) by running the item coordinates +through the encode/decode methods of the packet that causes the precision +loss, which forces the server to lose the same precision as the client +keeping them in sync. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 652d87fc5d566dba8018c81676329f0e0bca471b..c56e7fb18f9a56c8025eb70a524f028b5942da37 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -474,4 +474,9 @@ public class PaperConfig { + private static void trackPluginScoreboards() { + trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); + } ++ ++ public static boolean fixEntityPositionDesync = true; ++ private static void fixEntityPositionDesync() { ++ fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); ++ } + } +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java +index cb10c87728b5f9062c4bdd1fe5e4b2c7a558f323..6b97d60d923e772c7284e674bc3f2e9a5a0ddead 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java +@@ -19,11 +19,11 @@ public class ClientboundMoveEntityPacket implements Packet { ++ private static final float[] SIN = (float[]) Util.make((new float[65536]), (afloat) -> { // Paper - decompile error + for (int i = 0; i < afloat.length; ++i) { + afloat[i] = (float) Math.sin((double) i * 3.141592653589793D * 2.0D / 65536.0D); + } +@@ -49,6 +49,7 @@ public class Mth { + return d0 < (double) i ? i - 1 : i; + } + ++ public static long floorLong(double d0) { return lfloor(d0); } // Paper - OBFHELPER + public static long lfloor(double d0) { + long i = (long) d0; + +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 9311f9f411d09d4460f0be8235957fab9e195b7a..7476ae301fb4ee503944d39022cb25ccb19f1232 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -549,4 +549,16 @@ public class ItemEntity extends Entity { + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this); + } ++ ++ // Paper start - fix MC-4 ++ public void setPosRaw(double x, double y, double z) { ++ if (com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) { ++ // encode/decode from PacketPlayOutEntity ++ x = Mth.floorLong(x * 4096.0D) * (1 / 4096.0D); ++ y = Mth.floorLong(y * 4096.0D) * (1 / 4096.0D); ++ z = Mth.floorLong(z * 4096.0D) * (1 / 4096.0D); ++ } ++ super.setPosRaw(x, y, z); ++ } ++ // Paper end - fix MC-4 + } diff --git a/Remapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch b/Remapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch new file mode 100644 index 0000000000..d7abc567f0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ysl3000 +Date: Mon, 5 Oct 2020 21:25:16 +0200 +Subject: [PATCH] Player Chunk Load/Unload Events + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 1b5f24920c46cd238a79f5a2857d26fa1c12b983..ff831ca0cbc0cabbf78178c609ccf70d78da7980 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -136,6 +136,8 @@ import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.level.portal.PortalInfo; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++import io.papermc.paper.event.packet.PlayerChunkLoadEvent; // Paper ++import io.papermc.paper.event.packet.PlayerChunkUnloadEvent; // Paper + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import net.minecraft.world.Container; +@@ -2095,11 +2097,21 @@ public class ServerPlayer extends Player implements ContainerListener { + public void trackChunk(ChunkPos chunkcoordintpair, Packet packet, Packet packet1) { + this.connection.send(packet1); + this.connection.send(packet); ++ // Paper start ++ if(PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0){ ++ new PlayerChunkLoadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); ++ } ++ // Paper end + } + + public void untrackChunk(ChunkPos chunkcoordintpair) { + if (this.isAlive()) { + this.connection.send(new ClientboundForgetLevelChunkPacket(chunkcoordintpair.x, chunkcoordintpair.z)); ++ // Paper start ++ if(PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0){ ++ new PlayerChunkUnloadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); ++ } ++ // Paper end + } + + } diff --git a/Remapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch b/Remapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch new file mode 100644 index 0000000000..5a4efe035c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 21 Dec 2020 11:01:42 -0500 +Subject: [PATCH] Optimize Dynamic#get Missing Keys + +get was calling toString() on every NBT object that was ever asked for an optional +key from the object to build a string for the error text. + +When done on large NBT objects, this was using a ton of computation time building the +JSON representation of the NBT object. + +Now we will just skip the value when 99.9999% of the time the text is never even printed. + +diff --git a/src/main/java/com/mojang/serialization/Dynamic.java b/src/main/java/com/mojang/serialization/Dynamic.java +index a75d3db046dc985a03b4b870c91f41de1bd66bad..044facc9de9e8e582d7953d681c0c051578979c3 100644 +--- a/src/main/java/com/mojang/serialization/Dynamic.java ++++ b/src/main/java/com/mojang/serialization/Dynamic.java +@@ -17,6 +17,7 @@ import java.util.stream.Stream; + + @SuppressWarnings("unused") + public class Dynamic extends DynamicLike { ++ private static final boolean DEBUG_MISSING_KEYS = Boolean.getBoolean("Paper.debugDynamicMissingKeys"); // Paper + private final T value; + + public Dynamic(final DynamicOps ops) { +@@ -113,7 +114,7 @@ public class Dynamic extends DynamicLike { + return new OptionalDynamic<>(ops, ops.getMap(value).flatMap(m -> { + final T value = m.get(key); + if (value == null) { +- return DataResult.error("key missing: " + key + " in " + this.value); ++ return DataResult.error(DEBUG_MISSING_KEYS ? "key missing: " + key + " in " + this.value : "key missing: " + key); // Paper + } + return DataResult.success(new Dynamic<>(ops, value)); + })); diff --git a/Remapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch b/Remapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch new file mode 100644 index 0000000000..d179506896 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 13 Dec 2020 05:32:05 +0200 +Subject: [PATCH] Expose LivingEntity hurt direction + + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 57b933afdbb2136ed48170da6945eb2b92edb4db..02ddb84c563b3149c4f1b0e24899ce8a21ad61bb 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -160,7 +160,7 @@ public abstract class LivingEntity extends Entity { + public int removeStingerTime; + public int hurtTime; + public int hurtDuration; +- public float hurtDir; ++ public float hurtDir; public final float getHurtDirection() { return hurtDir; } public final void setHurtDirection(float hurtDirection) { this.hurtDir = hurtDirection; } // Paper - OBFHELPER + public int deathTime; + public float oAttackAnim; + public float attackAnim; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 170bb1124ee396a85dd64baed8110e39823ad849..a8d21382d5859edfd12e01a48924ce780790b4b7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -818,5 +818,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { + getHandle().take(((CraftItem) item).getHandle(), quantity); + } ++ ++ @Override ++ public float getHurtDirection() { ++ return getHandle().getHurtDirection(); ++ } ++ ++ @Override ++ public void setHurtDirection(float hurtDirection) { ++ getHandle().setHurtDirection(hurtDirection); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/Remapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch new file mode 100644 index 0000000000..d2162d0415 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 24 Dec 2020 12:43:39 -0800 +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 64cfa14aa4e32430a6970fd4f3654a56146ba807..34c7b1213b3f83ff1a1f2d606a9c25e57fea8ef3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -259,6 +259,10 @@ public class CraftEventFactory { + return BedEnterResult.TOO_FAR_AWAY; + case NOT_SAFE: + return BedEnterResult.NOT_SAFE; ++ // Paper start ++ case OBSTRUCTED: ++ return BedEnterResult.OBSTRUCTED; ++ // Paper end + default: + return BedEnterResult.OTHER_PROBLEM; + } diff --git a/Remapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/Remapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch new file mode 100644 index 0000000000..f57f5ee833 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 27 Dec 2020 11:31:06 +0000 +Subject: [PATCH] Do not crash from invalid ingredient lists in + VillagerAcquireTradeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +index 407a68edf6408400f1a6c5bb1a6cbbfae08ac2cd..335000713279b7964c5172937483678c671bfed1 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -270,7 +270,11 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan + Bukkit.getPluginManager().callEvent(event); + } + if (!event.isCancelled()) { +- recipeList.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ // Paper start ++ final CraftMerchantRecipe craftMerchantRecipe = CraftMerchantRecipe.fromBukkit(event.getRecipe()); ++ if (craftMerchantRecipe.getIngredients().isEmpty()) return; ++ recipeList.add(craftMerchantRecipe.toMinecraft()); ++ // Paper end + } + // CraftBukkit end + } diff --git a/Remapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch b/Remapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch new file mode 100644 index 0000000000..3589365354 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 2 Jul 2020 16:12:10 -0700 +Subject: [PATCH] added PlayerTradeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 40ab66f888f30a5506e3aa96a4b32485452e8978..87dd6c012bf1ca6a1e8df44dc0957c4c67d02adc 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -91,7 +91,7 @@ import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; + public abstract class Mob extends LivingEntity { + + private static final EntityDataAccessor DATA_MOB_FLAGS_ID = SynchedEntityData.defineId(Mob.class, EntityDataSerializers.BYTE); +- public int ambientSoundTime; ++ public int ambientSoundTime;public void setAmbientSoundTime(int time) { this.ambientSoundTime = time; } // Paper - OBFHELPER + protected int xpReward; + protected LookControl lookControl; + protected MoveControl moveControl; +@@ -293,6 +293,7 @@ public abstract class Mob extends LivingEntity { + this.entityData.define(Mob.DATA_MOB_FLAGS_ID, (byte) 0); + } + ++ public int getAmbientSoundInterval() { return getAmbientSoundInterval(); } // Paper - OBFHELPER + public int getAmbientSoundInterval() { + return 80; + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +index 335000713279b7964c5172937483678c671bfed1..d31b773f8aff09c9f214662aa3aa0c904119e12c 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -37,6 +37,9 @@ import org.bukkit.craftbukkit.inventory.CraftMerchant; + import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; + import org.bukkit.event.entity.VillagerAcquireTradeEvent; + // CraftBukkit end ++// Paper start ++import io.papermc.paper.event.player.PlayerTradeEvent; ++// Paper end + + public abstract class AbstractVillager extends AgableMob implements Npc, Merchant { + +@@ -133,16 +136,27 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan + + @Override + public void notifyTrade(MerchantOffer offer) { +- offer.increaseUses(); +- this.ambientSoundTime = -this.getAmbientSoundInterval(); +- this.rewardTradeXp(offer); ++ // Paper - moved down ++ // Paper start + if (this.tradingPlayer instanceof ServerPlayer) { +- CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, offer.getResult()); ++ PlayerTradeEvent event = new PlayerTradeEvent(((ServerPlayer) this.tradingPlayer).getBukkitEntity(), (org.bukkit.entity.AbstractVillager) this.getBukkitEntity(), offer.asBukkit(), true, true); ++ event.callEvent(); ++ if (!event.isCancelled()) { ++ MerchantOffer recipe = CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft(); ++ if (event.willIncreaseTradeUses()) recipe.increaseUses(); ++ this.setAmbientSoundTime(-getAmbientSoundInterval()); ++ if (event.isRewardingExp()) this.rewardTradeXp(recipe); ++ CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, recipe.getResult()); ++ } ++ } else { ++ offer.increaseUses(); ++ this.setAmbientSoundTime(-getAmbientSoundInterval()); ++ this.rewardTradeXp(offer); + } +- ++ // Paper end + } + +- protected abstract void rewardTradeXp(MerchantOffer offer); ++ protected abstract void rewardTradeXp(MerchantOffer offer); public void rewardTradeXp(MerchantOffer merchantrecipe) { this.rewardTradeXp(merchantrecipe); } // Paper - OBFHELPER + + @Override + public boolean showProgressBar() { diff --git a/Remapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch b/Remapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch new file mode 100644 index 0000000000..bc8c6c48be --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Wed, 25 Nov 2020 23:20:44 -0800 +Subject: [PATCH] Implement TargetHitEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/TargetBlock.java b/src/main/java/net/minecraft/world/level/block/TargetBlock.java +index bbaf90b30b07c97321541b8fe15d47975a34161d..a7215c9b9f0f191bbfe95cb1185c99a8d21ff785 100644 +--- a/src/main/java/net/minecraft/world/level/block/TargetBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TargetBlock.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.block; + ++import io.papermc.paper.event.block.TargetHitEvent; // Paper - Need to import because 'io' class exists in nms + import java.util.Random; + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.core.BlockPos; +@@ -34,13 +35,17 @@ public class TargetBlock extends Block { + @Override + public void onProjectileHit(Level world, BlockState state, BlockHitResult hit, Projectile projectile) { + int i = updateRedstoneOutput((LevelAccessor) world, state, hit, (Entity) projectile); +- Entity entity = projectile.getOwner(); ++ // Paper start ++ } ++ private static void awardTargetHitCriteria(Projectile iprojectile, BlockHitResult movingobjectpositionblock, int i) { ++ // Paper end ++ Entity entity = iprojectile.getOwner(); + + if (entity instanceof ServerPlayer) { + ServerPlayer entityplayer = (ServerPlayer) entity; + + entityplayer.awardStat(Stats.TARGET_HIT); +- CriteriaTriggers.TARGET_BLOCK_HIT.trigger(entityplayer, projectile, hit.getLocation(), i); ++ CriteriaTriggers.TARGET_BLOCK_HIT.trigger(entityplayer, iprojectile, movingobjectpositionblock.getLocation(), i); + } + + } +@@ -49,6 +54,20 @@ public class TargetBlock extends Block { + int i = getRedstoneStrength(movingobjectpositionblock, movingobjectpositionblock.getLocation()); + int j = entity instanceof AbstractArrow ? 20 : 8; + ++ // Paper start ++ if (entity instanceof Projectile) { ++ final Projectile projectile = (Projectile) entity; ++ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, movingobjectpositionblock.getBlockPos()); ++ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(movingobjectpositionblock.getDirection()); ++ final TargetHitEvent targetHitEvent = new TargetHitEvent((org.bukkit.entity.Projectile) projectile.getBukkitEntity(), craftBlock, blockFace, i); ++ if (targetHitEvent.callEvent()) { ++ i = targetHitEvent.getSignalStrength(); ++ awardTargetHitCriteria(projectile, movingobjectpositionblock, i); ++ } else { ++ return i; ++ } ++ } ++ // Paper end + if (!world.getBlockTicks().a(movingobjectpositionblock.getBlockPos(), state.getBlock())) { + setOutputPower(world, state, i, movingobjectpositionblock.getBlockPos(), j); + } diff --git a/Remapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch b/Remapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch new file mode 100644 index 0000000000..6aa789f4d3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 30 Dec 2020 19:43:01 -0500 +Subject: [PATCH] Additional Block Material API's + +Faster version for isSolid() that utilizes NMS's state for isSolid instead of the slower +process to do this in the Bukkit API + +Adds API for buildable, replaceable, burnable too. + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 9defb202761296a825d035e27ddc51e17a311647..376b0497c28a35d7ea615397c87b2558b95c596a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -618,6 +618,25 @@ public class CraftBlock implements Block { + return getNMS().getMaterial().isLiquid(); + } + ++ // Paper start ++ @Override ++ public boolean isBuildable() { ++ return getNMS().getMaterial().isBuildable(); ++ } ++ @Override ++ public boolean isBurnable() { ++ return getNMS().getMaterial().isBurnable(); ++ } ++ @Override ++ public boolean isReplaceable() { ++ return getNMS().getMaterial().isReplaceable(); ++ } ++ @Override ++ public boolean isSolid() { ++ return getNMS().getMaterial().blocksMotion(); ++ } ++ // Paper end ++ + @Override + public PistonMoveReaction getPistonMoveReaction() { + return PistonMoveReaction.getById(getNMS().getPistonPushReaction().ordinal()); diff --git a/Remapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch b/Remapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch new file mode 100644 index 0000000000..e5c11d28d2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> +Date: Thu, 23 Jul 2020 14:25:07 -0700 +Subject: [PATCH] Fix harming potion dupe + +EntityLiving#applyInstantEffect() immediately kills the player and drops their inventory. +Before this patch, instant effects would be applied before the potion ItemStack is removed and replaced with a glass bottle. This caused the potion ItemStack to be dropped before it was supposed to be removed from the inventory. It also caused the glass bottle to be put into a dead player's inventory. +This patch makes it so that instant effects are applied after the potion ItemStack is removed, and the glass bottle is only put into the player's inventory if the player is not dead. Otherwise, the glass bottle is dropped on the ground. + +diff --git a/src/main/java/net/minecraft/world/item/PotionItem.java b/src/main/java/net/minecraft/world/item/PotionItem.java +index 36ccec8ad2f605d5bceae476e26c2fbfbdae39d8..ba2bc044b259b0a5ba590d4ae6fd36e5c415ddff 100644 +--- a/src/main/java/net/minecraft/world/item/PotionItem.java ++++ b/src/main/java/net/minecraft/world/item/PotionItem.java +@@ -15,6 +15,7 @@ import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.alchemy.Potion; + import net.minecraft.world.item.alchemy.PotionUtils; + import net.minecraft.world.item.alchemy.Potions; ++import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; + + public class PotionItem extends Item { +@@ -36,6 +37,7 @@ public class PotionItem extends Item { + CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) entityhuman, stack); + } + ++ List instantLater = new java.util.ArrayList<>(); // Paper - Fix harming potion dupe + if (!world.isClientSide) { + List list = PotionUtils.getMobEffects(stack); + Iterator iterator = list.iterator(); +@@ -44,7 +46,7 @@ public class PotionItem extends Item { + MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + + if (mobeffect.getMobEffect().isInstant()) { +- mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D); ++ instantLater.add(mobeffect); // Paper - Fix harming potion dupe + } else { + user.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit + } +@@ -58,7 +60,20 @@ public class PotionItem extends Item { + } + } + ++ // Paper start - Fix harming potion dupe ++ for (MobEffectInstance mobeffect : instantLater) { ++ mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D); ++ } ++ // Paper end ++ + if (entityhuman == null || !entityhuman.abilities.instabuild) { ++ // Paper start - Fix harming potion dupe ++ if (user.getHealth() <= 0 && !user.level.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY)) { ++ user.dropItem(new ItemStack(Items.GLASS_BOTTLE), 0); ++ return ItemStack.NULL_ITEM; ++ } ++ // Paper end ++ + if (stack.isEmpty()) { + return new ItemStack(Items.GLASS_BOTTLE); + } diff --git a/Remapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/Remapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch new file mode 100644 index 0000000000..f956ace9fd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Thu, 31 Dec 2020 12:48:19 +1000 +Subject: [PATCH] Implement API to get Material from Boats and Minecarts + + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +index 4f82c6797fe9bbb1a29420ea15277be50e44808c..6a9c18540886979b2212bf7917a21753c9a9db3c 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +@@ -259,6 +259,7 @@ public class Boat extends Entity { + + } + ++ public final Item getBoatItem() { return this.getDropItem(); } // Paper - OBFHELPER + public Item getDropItem() { + switch (this.getBoatType()) { + case OAK: +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java +index de8e9e8d18fb9cc6f49d98ab0c57faffec61e5b5..5928ab97b91062963e5cca0a8ec50f2bc3a7ff96 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java +@@ -1,7 +1,9 @@ + package org.bukkit.craftbukkit.entity; + ++import org.bukkit.Material; // Paper + import org.bukkit.TreeSpecies; + import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper + import org.bukkit.entity.Boat; + import org.bukkit.entity.EntityType; + +@@ -65,6 +67,13 @@ public class CraftBoat extends CraftVehicle implements Boat { + getHandle().landBoats = workOnLand; + } + ++ // Paper start ++ @Override ++ public Material getBoatMaterial() { ++ return CraftMagicNumbers.getMaterial(getHandle().getBoatItem()); ++ } ++ // Paper end ++ + @Override + public net.minecraft.world.entity.vehicle.Boat getHandle() { + return (net.minecraft.world.entity.vehicle.Boat) entity; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java +index 55df92a4661e13a9085f325db0572a265a89948c..fb26b6125ad4090d87b2326add94ffaded82c8ef 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java +@@ -1,8 +1,10 @@ + package org.bukkit.craftbukkit.entity; + + import net.minecraft.world.entity.vehicle.AbstractMinecart; ++import net.minecraft.world.item.Items; // Paper + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; ++import org.bukkit.Material; // Paper + import org.bukkit.block.data.BlockData; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.block.data.CraftBlockData; +@@ -68,6 +70,38 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart { + getHandle().setDerailedVelocityMod(derailed); + } + ++ // Paper start ++ @Override ++ public Material getMinecartMaterial() { ++ net.minecraft.world.item.Item minecartItem; ++ switch (getHandle().getMinecartType()) { ++ case CHEST: ++ minecartItem = Items.CHEST_MINECART; ++ break; ++ case FURNACE: ++ minecartItem = Items.FURNACE_MINECART; ++ break; ++ case TNT: ++ minecartItem = Items.TNT_MINECART; ++ break; ++ case HOPPER: ++ minecartItem = Items.HOPPER_MINECART; ++ break; ++ case COMMAND_BLOCK: ++ minecartItem = Items.COMMAND_BLOCK_MINECART; ++ break; ++ case RIDEABLE: ++ case SPAWNER: ++ minecartItem = Items.MINECART; ++ break; ++ default: ++ throw new IllegalStateException("Unexpected value: " + getHandle().getMinecartType()); ++ } ++ ++ return CraftMagicNumbers.getMaterial(minecartItem); ++ } ++ // Paper end ++ + @Override + public AbstractMinecart getHandle() { + return (AbstractMinecart) entity; diff --git a/Remapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch b/Remapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch new file mode 100644 index 0000000000..3dd32bb45a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas +Date: Sun, 27 Dec 2020 17:19:51 +0100 +Subject: [PATCH] Optimized tick ready check + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 066d5f7ee93351bff67c0d39ee9d940ac51515d8..b89cefc8890774dbc64fd6bddeb038d2ee36d485 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -854,13 +854,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + if (!tileentity.isRemoved() && tileentity.hasLevel()) { + BlockPos blockposition = tileentity.getBlockPos(); + +- if (this.getChunkSource().isTickingChunk(blockposition) && this.getWorldBorder().isWithinBounds(blockposition)) { ++ LevelChunk chunk; ChunkHolder playerChunk; if ((chunk = tileentity.getCurrentChunk()) != null && (playerChunk = chunk.playerChunk) != null && playerChunk.isTickingReady() && this.getWorldBorder().isInBounds(blockposition)) { // Paper - optimized tick ready check by inlining ChunkProviderServer.a(BlockPosition). Chunk lookup is no longer required and we can use the PlayerChunk directly available through the tile entity + try { + gameprofilerfiller.push(() -> { + return String.valueOf(BlockEntityType.getKey(tileentity.getType())); + }); + tileentity.tickTimer.startTiming(); // Spigot +- if (tileentity.getType().isValid(this.getBlockState(blockposition).getBlock())) { ++ if (tileentity.getType().isValid(chunk.getBlockState(blockposition).getBlock())) { // Paper - reuse the chunk from above, do not look it up again + ((TickableBlockEntity) tileentity).tick(); + } else { + tileentity.logInvalidState(); +@@ -893,9 +893,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.tickableBlockEntities.remove(tileTickPosition--); + // Spigot end + //this.tileEntityList.remove(tileentity); // Paper - remove unused list +- if (this.hasChunkAt(tileentity.getBlockPos())) { +- this.getChunkAt(tileentity.getBlockPos()).removeBlockEntity(tileentity.getBlockPos()); ++ // Paper - prevent double chunk lookups ++ LevelChunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getBlockPos())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again ++ chunk.removeBlockEntity(tileentity.getBlockPos()); + } ++ // Paper end + } + } + +@@ -914,8 +916,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + // CraftBukkit end */ + +- if (this.hasChunkAt(tileentity1.getBlockPos())) { +- LevelChunk chunk = this.getChunkAt(tileentity1.getBlockPos()); ++ LevelChunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity1.getBlockPos())) != null) { // Paper - inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again ++ // Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); // Paper - already computed above + BlockState iblockdata = chunk.getBlockState(tileentity1.getBlockPos()); + + chunk.setBlockEntity(tileentity1.getBlockPos(), tileentity1); diff --git a/Remapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch b/Remapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch new file mode 100644 index 0000000000..4163e2cc84 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas +Date: Sun, 27 Dec 2020 16:47:00 +0100 +Subject: [PATCH] Cache burn durations + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 4126a36dbc7750108a883f0be14dcb0d2e6d7ae8..f47b46cebd43faa509b8139d2a51cc8f87615893 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.block.entity; + ++import com.google.common.collect.ImmutableMap; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; +@@ -111,7 +112,15 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + this.recipeType = recipeType; + } + ++ private static Map cachedBurnDurations = null; // Paper - cache burn durations ++ ++ public static Map getBurnDurations() { return getFuel(); } // Paper - OBFHELPER + public static Map getFuel() { ++ // Paper start - cache burn durations ++ if(cachedBurnDurations != null) { ++ return cachedBurnDurations; ++ } ++ // Paper end + Map map = Maps.newLinkedHashMap(); + + add(map, (ItemLike) Items.LAVA_BUCKET, 20000); +@@ -174,7 +183,10 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + add(map, (ItemLike) Blocks.FLETCHING_TABLE, 300); + add(map, (ItemLike) Blocks.SMITHING_TABLE, 300); + add(map, (ItemLike) Blocks.COMPOSTER, 300); +- return map; ++ // Paper start - cache burn durations ++ cachedBurnDurations = ImmutableMap.copyOf(map); ++ return cachedBurnDurations; ++ // Paper end + } + + // CraftBukkit start - add fields and methods +@@ -428,7 +440,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + } else { + Item item = fuel.getItem(); + +- return (Integer) getFuel().getOrDefault(item, 0); ++ return getBurnDurations().getOrDefault(item, 0); // Paper - cache burn durations + } + } + +@@ -441,7 +453,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + // Paper end + + public static boolean isFuel(ItemStack stack) { +- return getFuel().containsKey(stack.getItem()); ++ return getBurnDurations().containsKey(stack.getItem()); // Paper - cache burn durations + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/Remapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch new file mode 100644 index 0000000000..efb245db2f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BrodyBeckwith +Date: Fri, 9 Oct 2020 20:30:12 -0400 +Subject: [PATCH] Allow disabling mob spawner spawn egg transformation + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index a3b3e3e04b7a5e3a351992e06870cc91fbd8adc8..b48067c71f9de18ba40e970e2832f6245984a218 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -722,4 +722,9 @@ public class PaperWorldConfig { + private void fixCuringExploit() { + fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); + } ++ ++ public boolean disableMobSpawnerSpawnEggTransformation = false; ++ private void disableMobSpawnerSpawnEggTransformation() { ++ disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); ++ } + } +diff --git a/src/main/java/net/minecraft/world/item/SpawnEggItem.java b/src/main/java/net/minecraft/world/item/SpawnEggItem.java +index 9aae1435a271bb17d6355e4c75ccbce78cb9d449..7904a2176253eaf48b47e06dd2e19758a673873c 100644 +--- a/src/main/java/net/minecraft/world/item/SpawnEggItem.java ++++ b/src/main/java/net/minecraft/world/item/SpawnEggItem.java +@@ -60,7 +60,7 @@ public class SpawnEggItem extends Item { + Direction enumdirection = context.getClickedFace(); + BlockState iblockdata = world.getBlockState(blockposition); + +- if (iblockdata.is(Blocks.SPAWNER)) { ++ if (!world.paperConfig.disableMobSpawnerSpawnEggTransformation && iblockdata.is(Blocks.SPAWNER)) { // Paper + BlockEntity tileentity = world.getBlockEntity(blockposition); + + if (tileentity instanceof SpawnerBlockEntity) { diff --git a/Remapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch b/Remapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch new file mode 100644 index 0000000000..2c81edd9ad --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MisterVector +Date: Tue, 13 Aug 2019 19:45:06 -0700 +Subject: [PATCH] Implement PlayerFlowerPotManipulateEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java b/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java +index ae74e70457f8f46ee71bf0902ade3468da272e81..a1d1f3416df8e313688fedad47dd264444d7c465 100644 +--- a/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java +@@ -20,6 +20,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent; // Paper + + public class FlowerPotBlock extends Block { + +@@ -52,6 +53,27 @@ public class FlowerPotBlock extends Block { + boolean flag1 = this.content == Blocks.AIR; + + if (flag != flag1) { ++ // Paper start ++ org.bukkit.entity.Player player1 = (org.bukkit.entity.Player) player.getBukkitEntity(); ++ boolean placing = flag1; ++ org.bukkit.block.Block bukkitblock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos); ++ org.bukkit.inventory.ItemStack bukkititemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack); ++ org.bukkit.Material mat = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(content); ++ org.bukkit.inventory.ItemStack bukkititemstack1 = new org.bukkit.inventory.ItemStack(mat, 1); ++ org.bukkit.inventory.ItemStack whichitem = placing ? bukkititemstack : bukkititemstack1; ++ ++ PlayerFlowerPotManipulateEvent event = new PlayerFlowerPotManipulateEvent(player1, bukkitblock, whichitem, placing); ++ player1.getServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ // Update client ++ player1.sendBlockChange(bukkitblock.getLocation(), bukkitblock.getBlockData()); ++ player1.updateInventory(); ++ ++ return InteractionResult.PASS; ++ } ++ // Paper end ++ + if (flag1) { + world.setBlock(pos, block.defaultBlockState(), 3); + player.awardStat(Stats.POT_FLOWER); diff --git a/Remapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch b/Remapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch new file mode 100644 index 0000000000..5e69fe3a87 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheMolkaPL +Date: Sun, 21 Jun 2020 17:21:46 +0200 +Subject: [PATCH] Fix interact event not being called in adventure + +Call PlayerInteractEvent when left-clicking on a block in adventure mode + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index e50e42cce60c725cdd981d8927e379c5760d9200..cb6568b622abeb939a1195f4656accc8a1c3f1fc 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1701,7 +1701,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + MutableComponent ichatmutablecomponent = (new TranslatableComponent("build.tooHigh", new Object[]{this.server.getMaxBuildHeight()})).withStyle(ChatFormatting.RED); + + this.player.connection.send(new ClientboundChatPacket(ichatmutablecomponent, ChatType.GAME_INFO, Util.NIL_UUID)); +- } else if (enuminteractionresult.shouldSwing()) { ++ } else if (enuminteractionresult.shouldSwing() && !this.player.gameMode.interactResult) { + this.player.swing(enumhand, true); + } + } +@@ -2202,7 +2202,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + Vec3 vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); + HitResult movingobjectposition = this.player.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)); + +- if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK) { ++ if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK || this.player.gameMode.getGameModeForPlayer() == GameType.ADVENTURE) { // Paper - call PlayerInteractEvent when left-clicking on a block in adventure mode + CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.inventory.getSelected(), InteractionHand.MAIN_HAND); + } + diff --git a/Remapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch b/Remapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch new file mode 100644 index 0000000000..63b6f1e733 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 18 Nov 2020 11:32:46 -0800 +Subject: [PATCH] Zombie API - breaking doors + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 4105c1763d25824aac35d305a793823c1604eee8..77634a1e8e7539000f7db0b96f4548137af1a819 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -137,10 +137,12 @@ public class Zombie extends Monster { + return (Boolean) this.getEntityData().get(Zombie.DATA_DROWNED_CONVERSION_ID); + } + ++ public boolean canBreakDoors() { return this.canBreakDoors(); } // Paper - OBFHELPER + public boolean canBreakDoors() { + return this.canBreakDoors; + } + ++ public void setCanBreakDoors(boolean canBreakDoors) { this.setCanBreakDoors(canBreakDoors); } // Paper - OBFHELPER + public void setCanBreakDoors(boolean canBreakDoors) { + if (this.supportsBreakDoorGoal() && GoalUtils.hasGroundPathNavigation(this)) { + if (this.canBreakDoors != canBreakDoors) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +index 86f65c07806a118c49e900c59be86c2bd2eb124c..44f21b3b1c2f2fbc1f3f53931349b9a9426e97f8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +@@ -128,6 +128,16 @@ public class CraftZombie extends CraftMonster implements Zombie { + public void setShouldBurnInDay(boolean shouldBurnInDay) { + getHandle().setShouldBurnInDay(shouldBurnInDay); + } ++ ++ @Override ++ public boolean canBreakDoors() { ++ return getHandle().canBreakDoors(); ++ } ++ ++ @Override ++ public void setCanBreakDoors(boolean canBreakDoors) { ++ getHandle().setCanBreakDoors(canBreakDoors); ++ } + // Paper end + + @Override diff --git a/Remapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch b/Remapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch new file mode 100644 index 0000000000..85d8576628 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 24 Aug 2020 08:39:06 -0700 +Subject: [PATCH] Fix nerfed slime when splitting + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java +index 120ceb28ee3aee8a09cf67b45ac95d3d6613c133..2f04543c1c0a197f22fb26b2a38c7c79e6b4a63a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java +@@ -242,6 +242,7 @@ public class Slime extends Mob implements Enemy { + entityslime.setPersistenceRequired(); + } + ++ entityslime.aware = this.aware; // Paper + entityslime.setCustomName(ichatbasecomponent); + entityslime.setNoAi(flag); + entityslime.setInvulnerable(this.isInvulnerable()); diff --git a/Remapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch b/Remapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch new file mode 100644 index 0000000000..6eea724442 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 7 Oct 2020 12:04:01 -0400 +Subject: [PATCH] Add EntityLoadCrossbowEvent + + +diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java +index e1e58b7035e6dbafdad0a04cc5333464fc4febb8..32e927375daeaf16f4ea763bc9f7c4a244797bba 100644 +--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java ++++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java +@@ -3,6 +3,8 @@ package net.minecraft.world.item; + import com.google.common.collect.Lists; + import com.mojang.math.Quaternion; + import com.mojang.math.Vector3f; ++import org.bukkit.inventory.EquipmentSlot; // Paper ++import io.papermc.paper.event.entity.EntityLoadCrossbowEvent; // Paper - EntityLoadCrossbowEvent namespace conflicts + import java.util.List; + import java.util.Random; + import java.util.function.Predicate; +@@ -73,7 +75,11 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + int j = this.getUseDuration(stack) - remainingUseTicks; + float f = getPowerForTime(j, stack); + +- if (f >= 1.0F && !isCharged(stack) && tryLoadProjectiles(user, stack)) { ++ // Paper start - EntityLoadCrossbowEvent ++ if (f >= 1.0F && !isCharged(stack) /*&& a(entityliving, itemstack)*/) { ++ final EntityLoadCrossbowEvent event = new EntityLoadCrossbowEvent(user.getBukkitLivingEntity(), stack.asBukkitMirror(), user.getUsedItemHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND); ++ if (!event.callEvent() || !attemptProjectileLoad(user, stack, event.shouldConsumeItem())) return; ++ // Paper end + setCharged(stack, true); + SoundSource soundcategory = user instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE; + +@@ -82,11 +88,14 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + + } + +- private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack projectile) { +- int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, projectile); ++ private static boolean attemptProjectileLoad(LivingEntity ent, ItemStack bow) { return tryLoadProjectiles(ent, bow); } // Paper - EntityLoadCrossbowEvent - OBFHELPER ++ private static boolean attemptProjectileLoad(LivingEntity ent, ItemStack bow, boolean consume) { return a(ent, bow, consume); } // Paper - EntityLoadCrossbowEvent - OBFHELPER ++ private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack projectile) { return a(shooter, projectile, true); };// Paper - add consume ++ private static boolean a(LivingEntity entityliving, ItemStack itemstack, boolean consume) { // Paper - add consume ++ int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, itemstack); + int j = i == 0 ? 1 : 3; +- boolean flag = shooter instanceof Player && ((Player) shooter).abilities.instabuild; +- ItemStack itemstack1 = shooter.getProjectile(projectile); ++ boolean flag = !consume || entityliving instanceof Player && ((Player) entityliving).abilities.instabuild; // Paper - add consme ++ ItemStack itemstack1 = entityliving.getProjectile(itemstack); + ItemStack itemstack2 = itemstack1.copy(); + + for (int k = 0; k < j; ++k) { +@@ -103,7 +112,7 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + // CraftBukkit end + } + +- if (!loadProjectile(shooter, projectile, itemstack1, k > 0, flag)) { ++ if (!loadProjectile(entityliving, itemstack, itemstack1, k > 0, flag)) { + return false; + } + } diff --git a/Remapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch b/Remapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch new file mode 100644 index 0000000000..c16b905697 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gabscap +Date: Sat, 19 Mar 2016 22:25:11 +0100 +Subject: [PATCH] Guardian beam workaround + +This patch is a workaround for MC-165595 + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java +index a02f492c279f4e859b44d52e150a2990cbe8275a..4f177e7396db00db56f2106068fc02b9c2618407 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java +@@ -6,7 +6,7 @@ import net.minecraft.network.protocol.Packet; + + public class ClientboundSetTimePacket implements Packet { + +- private long gameTime; ++ private long gameTime; private final void setWorldAge(final long age) { this.gameTime = age; } private final long getWorldAge() { return this.gameTime; } // Paper - OBFHELPER + private long dayTime; + + public ClientboundSetTimePacket() {} +@@ -21,6 +21,9 @@ public class ClientboundSetTimePacket implements Packet +Date: Sun, 20 Dec 2020 16:41:44 -0800 +Subject: [PATCH] Added WorldGameRuleChangeEvent + + +diff --git a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java +index 87b968019fa10647522121c7b29094ed3e0dcf6d..7f124784dd7876cdb26f16e83deddf07dd9a198e 100644 +--- a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java +@@ -31,7 +31,7 @@ public class GameRuleCommand { + CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); + T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(key); // CraftBukkit + +- t0.setFromArgument(context, "value"); ++ t0.setValue(context, "value", key); // Paper + commandlistenerwrapper.sendSuccess(new TranslatableComponent("commands.gamerule.set", new Object[]{key.getId(), t0.toString()}), true); + return t0.getCommandResult(); + } +diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java +index 6c996d34ef34879db1d65c39adf99ce2d64e5499..1e6f299571a25729dbf8c5b0cd115c1e842a8a3c 100644 +--- a/src/main/java/net/minecraft/world/level/GameRules.java ++++ b/src/main/java/net/minecraft/world/level/GameRules.java +@@ -25,6 +25,7 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerPlayer; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import io.papermc.paper.event.world.WorldGameRuleChangeEvent; // Paper + + public class GameRules { + +@@ -177,8 +178,11 @@ public class GameRules { + } + + @Override +- protected void updateFromArgument(CommandContext context, String name) { +- this.value = BoolArgumentType.getBool(context, name); ++ protected void a(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { // Paper start ++ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(commandcontext, s))); ++ if (!event.callEvent()) return; ++ this.value = Boolean.parseBoolean(event.getValue()); ++ // Paper end + } + + public boolean get() { +@@ -237,8 +241,11 @@ public class GameRules { + } + + @Override +- protected void updateFromArgument(CommandContext context, String name) { +- this.value = IntegerArgumentType.getInteger(context, name); ++ protected void a(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { // Paper start ++ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(commandcontext, s))); ++ if (!event.callEvent()) return; ++ this.value = Integer.parseInt(event.getValue()); ++ // Paper end + } + + public int get() { +@@ -291,11 +298,13 @@ public class GameRules { + this.type = type; + } + +- protected abstract void updateFromArgument(CommandContext context, String name); ++ protected void updateValue(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { this.a(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER ++ protected abstract void a(CommandContext commandcontext, String s, GameRules.Key gameRuleKey); // Paper + +- public void setFromArgument(CommandContext context, String name) { +- this.updateFromArgument(context, name); +- this.onChanged(((CommandSourceStack) context.getSource()).getServer()); ++ public void setValue(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { this.b(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER ++ public void b(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { // Paper ++ this.updateValue(commandcontext, s, gameRuleKey); // Paper ++ this.onChanged(((CommandSourceStack) commandcontext.getSource()).getServer()); + } + + public void onChanged(@Nullable MinecraftServer server) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index aaf97c13babce3b0ffc639ef950d59d1eba1398a..f497b9e11a075a84ff0a2117eb79d0532e4a326f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2345,8 +2345,13 @@ public class CraftWorld implements World { + + if (!isGameRule(rule)) return false; + ++ // Paper start ++ GameRule gameRule = GameRule.getByName(rule); ++ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, gameRule, value); ++ if (!event.callEvent()) return false; ++ // Paper end + GameRules.Value handle = getHandle().getGameRules().getRule(getGameRulesNMS().get(rule)); +- handle.deserialize(value); ++ handle.deserialize(event.getValue().toString()); // Paper + handle.onChanged(getHandle().getServer()); + return true; + } +@@ -2381,8 +2386,12 @@ public class CraftWorld implements World { + + if (!isGameRule(rule.getName())) return false; + ++ // Paper start ++ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, rule, String.valueOf(newValue)); ++ if (!event.callEvent()) return false; ++ // Paper end + GameRules.Value handle = getHandle().getGameRules().getRule(getGameRulesNMS().get(rule.getName())); +- handle.deserialize(newValue.toString()); ++ handle.deserialize(event.getValue().toString()); // Paper + handle.onChanged(getHandle().getServer()); + return true; + } diff --git a/Remapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch b/Remapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch new file mode 100644 index 0000000000..02aef6be64 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 2 Dec 2020 20:04:01 -0800 +Subject: [PATCH] Added ServerResourcesReloadedEvent + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index c83f2636ae93d92381e019d5b13ac82c5a1d30bf..892ca65d258b0745be95d7ef4886c49899b24d92 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2,9 +2,6 @@ package net.minecraft.server; + + import com.google.common.base.Splitter; + import com.google.common.collect.ImmutableList; +-import co.aikar.timings.Timings; +-import com.destroystokyo.paper.event.server.PaperServerListPingEvent; +-import com.google.common.base.Stopwatch; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; +@@ -181,6 +178,7 @@ import org.bukkit.event.server.ServerLoadEvent; + import co.aikar.timings.MinecraftTimings; // Paper + import org.spigotmc.SlackActivityAccountant; // Spigot + import io.papermc.paper.util.PaperJvmChecker; // Paper ++import io.papermc.paper.event.server.ServerResourcesReloadedEvent; // Paper + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { + +@@ -1934,9 +1932,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop reloadResources(Collection datapacks) { ++ return this.reloadServerResources(datapacks, ServerResourcesReloadedEvent.Cause.PLUGIN); ++ } ++ public CompletableFuture reloadServerResources(Collection collection, ServerResourcesReloadedEvent.Cause cause) { ++ // Paper end + CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { +- Stream stream = datapacks.stream(); // CraftBukkit - decompile error ++ Stream stream = collection.stream(); // CraftBukkit - decompile error + PackRepository resourcepackrepository = this.packRepository; + + this.packRepository.getClass(); +@@ -1947,9 +1951,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop collection, CommandSourceStack commandlistenerwrapper) { +- commandlistenerwrapper.getServer().reloadResources(collection).exceptionally((throwable) -> { +- ReloadCommand.LOGGER.warn("Failed to execute reload", throwable); +- commandlistenerwrapper.sendFailure(new TranslatableComponent("commands.reload.failure")); ++ commandlistenerwrapper.getServer().reloadServerResources(collection, ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally((throwable) -> { // Paper ++ CommandReload.LOGGER.warn("Failed to execute reload", throwable); ++ commandlistenerwrapper.sendFailureMessage(new ChatMessage("commands.reload.failure")); + return null; + }); + } +@@ -48,7 +49,7 @@ public class ReloadCommand { + WorldData savedata = minecraftserver.getWorldData(); + Collection collection = resourcepackrepository.getSelectedIds(); + Collection collection1 = discoverNewPacks(resourcepackrepository, savedata, collection); +- minecraftserver.reloadResources(collection1); ++ minecraftserver.reloadServerResources(collection1, ServerResourcesReloadedEvent.Cause.PLUGIN); // Paper + } + // CraftBukkit end + diff --git a/Remapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch b/Remapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch new file mode 100644 index 0000000000..ead34bbc60 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 28 Nov 2020 18:43:52 -0800 +Subject: [PATCH] Added world settings for mobs picking up loot + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index b48067c71f9de18ba40e970e2832f6245984a218..23a23e2ea133ce81d3dedc4ffd17435a995497ef 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -363,6 +363,14 @@ public class PaperWorldConfig { + log("Creeper lingering effect: " + disableCreeperLingeringEffect); + } + ++ public boolean zombiesAlwaysCanPickUpLoot; ++ public boolean skeletonsAlwaysCanPickUpLoot; ++ private void setMobsAlwaysCanPickUpLoot() { ++ zombiesAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.zombies", false); ++ skeletonsAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.skeletons", false); ++ log("Zombies can always pick up loot: " + zombiesAlwaysCanPickUpLoot + ". Skeletons can always pick up loot: " + skeletonsAlwaysCanPickUpLoot + "."); ++ } ++ + public int expMergeMaxValue; + private void expMergeMaxValue() { + expMergeMaxValue = getInt("experience-merge-max-value", -1); +diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +index 76027a7c9615495af64102744e264d7ba7c9b87e..68e52e3a31e70569d1a92602aff4b7b81c594757 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -149,7 +149,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + this.populateDefaultEquipmentSlots(difficulty); + this.populateDefaultEquipmentEnchantments(difficulty); + this.reassessWeaponGoal(); +- this.setCanPickUpLoot(this.random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); ++ this.setCanPickUpLoot(this.level.paperConfig.skeletonsAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper + if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { + LocalDate localdate = LocalDate.now(); + int i = localdate.get(ChronoField.DAY_OF_MONTH); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 77634a1e8e7539000f7db0b96f4548137af1a819..74fd175c4dc2d0d9832ee41efaf065b75a43f4b8 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -494,7 +494,7 @@ public class Zombie extends Monster { + Object object = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag); + float f = difficulty.getSpecialMultiplier(); + +- this.setCanPickUpLoot(this.random.nextFloat() < 0.55F * f); ++ this.setCanPickUpLoot(this.level.paperConfig.zombiesAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * f); // Paper + if (object == null) { + object = new Zombie.ZombieGroupData(getSpawnAsBabyOdds(world.getRandom()), true); + } diff --git a/Remapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch b/Remapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch new file mode 100644 index 0000000000..a7a4e49910 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheViperShow <29604693+TheViperShow@users.noreply.github.com> +Date: Wed, 22 Apr 2020 09:40:38 +0200 +Subject: [PATCH] Implemented BlockFailedDispenseEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +index bfb2e21ccbcc67d6c9b4b329db1949d7d938bd2e..2a4cb76bdfcf55ba222b4976359c1b8efb165009 100644 +--- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +@@ -81,6 +81,7 @@ public class DispenserBlock extends BaseEntityBlock { + int i = tileentitydispenser.getRandomSlot(); + + if (i < 0) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, pos)) // Paper - BlockFailedDispenseEvent is called here + worldserver.levelEvent(1001, pos, 0); + } else { + ItemStack itemstack = tileentitydispenser.getItem(i); +diff --git a/src/main/java/net/minecraft/world/level/block/DropperBlock.java b/src/main/java/net/minecraft/world/level/block/DropperBlock.java +index 154ec671e9d741e536464b794783da859e8447c1..492b19b94e2e2439f72ed9478d75641b0f50451a 100644 +--- a/src/main/java/net/minecraft/world/level/block/DropperBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DropperBlock.java +@@ -45,6 +45,7 @@ public class DropperBlock extends DispenserBlock { + int i = tileentitydispenser.getRandomSlot(); + + if (i < 0) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, pos)) // Paper - BlockFailedDispenseEvent is called here + worldserver.levelEvent(1001, pos, 0); + } 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 34c7b1213b3f83ff1a1f2d606a9c25e57fea8ef3..8829ef03d0be16d8317aaf05bcd286b74f20656a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -4,6 +4,7 @@ import com.google.common.base.Function; + import com.google.common.base.Functions; + import com.google.common.collect.Lists; + import com.mojang.datafixers.util.Either; ++import io.papermc.paper.event.block.BlockFailedDispenseEvent; + import java.net.InetAddress; + import java.util.ArrayList; + import java.util.Collections; +@@ -111,7 +112,6 @@ import org.bukkit.entity.ThrownPotion; + import org.bukkit.entity.Vehicle; + import org.bukkit.entity.Villager; + import org.bukkit.entity.Villager.Profession; +-import org.bukkit.entity.ExperienceOrb; // Paper + import org.bukkit.event.Cancellable; + import org.bukkit.event.Event; + import org.bukkit.event.Event.Result; +@@ -1784,4 +1784,12 @@ public class CraftEventFactory { + Bukkit.getPluginManager().callEvent(event); + return event; + } ++ ++ // Paper start ++ public static boolean handleBlockFailedDispenseEvent(ServerLevel worldserver, BlockPos blockposition) { ++ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); ++ return event.callEvent(); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch b/Remapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch new file mode 100644 index 0000000000..b4eacbfa37 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 23 Nov 2020 12:58:51 -0800 +Subject: [PATCH] Added PlayerLecternPageChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index bc39e7464646d712b085251dc0277a5b1ec0a393..b5d79635cd8b0eb6b17962450b347010aeb52654 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -561,6 +561,7 @@ public abstract class AbstractContainerMenu { + this.getSlot(slot).set(stack); + } + ++ public void setData(int index, int value) { this.setData(index, value); } // Paper - OBFHELPER + public void setData(int id, int value) { + ((DataSlot) this.dataSlots.get(id)).set(value); + } +diff --git a/src/main/java/net/minecraft/world/inventory/LecternMenu.java b/src/main/java/net/minecraft/world/inventory/LecternMenu.java +index 29e8dbc6be57faf50a8ca68eed6bf2e203b7e87a..a7be91a9336065899c409526a890e55f37b98751 100644 +--- a/src/main/java/net/minecraft/world/inventory/LecternMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/LecternMenu.java +@@ -11,6 +11,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryView; + import org.bukkit.entity.Player; + import org.bukkit.event.player.PlayerTakeLecternBookEvent; + // CraftBukkit end ++import io.papermc.paper.event.player.PlayerLecternPageChangeEvent; // Paper + + public class LecternMenu extends AbstractContainerMenu { + +@@ -58,6 +59,7 @@ public class LecternMenu extends AbstractContainerMenu { + @Override + public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + int j; ++ PlayerLecternPageChangeEvent playerLecternPageChangeEvent; CraftInventoryLectern bukkitView; // Paper + + if (id >= 100) { + j = id - 100; +@@ -67,11 +69,25 @@ public class LecternMenu extends AbstractContainerMenu { + switch (id) { + case 1: + j = this.lecternData.get(0); +- this.setData(0, j - 1); ++ // Paper start ++ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); ++ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, j, j - 1); ++ if (!playerLecternPageChangeEvent.callEvent()) { ++ return false; ++ } ++ this.setData(0, playerLecternPageChangeEvent.getNewPage()); ++ // Paper end + return true; + case 2: + j = this.lecternData.get(0); +- this.setData(0, j + 1); ++ // Paper start ++ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); ++ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, j, j + 1); ++ if (!playerLecternPageChangeEvent.callEvent()) { ++ return false; ++ } ++ this.setData(0, playerLecternPageChangeEvent.getNewPage()); ++ // Paper end + return true; + case 3: + if (!player.mayBuild()) { diff --git a/Remapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch b/Remapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch new file mode 100644 index 0000000000..a893ed5f5c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch @@ -0,0 +1,265 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 17 Mar 2019 21:46:56 +0200 +Subject: [PATCH] Fire event on GS4 query + + +diff --git a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java +index d10de580430d754204b36de809376538a14591e6..f6f0539a8e6edbeb1c412cee753a282b24a38046 100644 +--- a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java ++++ b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java +@@ -18,15 +18,27 @@ public class NetworkDataOutputStream { + this.dataOutputStream.write(abyte, 0, abyte.length); + } + ++ public void writeString(String string) throws IOException { this.writeString(string); } // Paper - OBFHELPER + public void writeString(String s) throws IOException { + this.dataOutputStream.writeBytes(s); + this.dataOutputStream.write(0); + } ++ // Paper start - unchecked exception variant to use in Stream API ++ public void writeStringUnchecked(String string) { ++ try { ++ writeString(string); ++ } catch (IOException e) { ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(e); ++ } ++ } ++ // Paper end + ++ public void writeInt(int i) throws IOException { this.write(i); } // Paper - OBFHELPER + public void write(int i) throws IOException { + this.dataOutputStream.write(i); + } + ++ public void writeShort(short i) throws IOException { this.writeShort(i); } // Paper - OBFHELPER + public void writeShort(short short0) throws IOException { + this.dataOutputStream.writeShort(Short.reverseBytes(short0)); + } +diff --git a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java +index 170d047463154bd6851199f06fe343ccb1896213..5562a3caff328bb08857b4f06a79b1e52f390fdd 100644 +--- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java ++++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java +@@ -16,6 +16,7 @@ import java.util.Random; + import javax.annotation.Nullable; + import net.minecraft.Util; + import net.minecraft.server.ServerInterface; ++import net.minecraft.server.dedicated.DedicatedServer; + import net.minecraft.server.rcon.NetworkDataOutputStream; + import net.minecraft.server.rcon.PktUtils; + import org.apache.logging.log4j.LogManager; +@@ -26,18 +27,18 @@ public class QueryThreadGs4 extends GenericThread { + private static final Logger LOGGER = LogManager.getLogger(); + private long lastChallengeCheck; + private final int port; +- private final int serverPort; +- private final int maxPlayers; +- private final String serverName; +- private final String worldName; ++ private final int serverPort; private final int getServerPort() { return this.serverPort; } // Paper - OBFHELPER ++ private final int maxPlayers; private final int getMaxPlayers() { return this.maxPlayers; } // Paper - OBFHELPER ++ private final String serverName; private final String getMotd() { return this.serverName; } // Paper - OBFHELPER ++ private final String worldName; private final String getWorldName() { return this.worldName; } // Paper - OBFHELPER + private DatagramSocket socket; + private final byte[] buffer = new byte[1460]; +- private String hostIp; ++ private String hostIp; public final String getServerHost() { return this.hostIp; } // Paper - OBFHELPER + private String serverIp; + private final Map validChallenges; +- private final NetworkDataOutputStream rulesResponse; ++ private final NetworkDataOutputStream rulesResponse; private final NetworkDataOutputStream getCachedFullResponse() { return this.rulesResponse; } // Paper - OBFHELPER + private long lastRulesResponse; +- private final ServerInterface serverInterface; ++ private final ServerInterface serverInterface; private final ServerInterface getServer() { return this.serverInterface; } // Paper - OBFHELPER + + private QueryThreadGs4(ServerInterface server, int queryPort) { + super("Query Listener"); +@@ -107,13 +108,39 @@ public class QueryThreadGs4 extends GenericThread { + + remotestatusreply.write((int) 0); + remotestatusreply.writeBytes(this.getIdentBytes(packet.getSocketAddress())); +- remotestatusreply.writeString(this.serverName); ++ /* Paper start - GS4 Query event ++ remotestatusreply.a(this.i); ++ remotestatusreply.a("SMP"); ++ remotestatusreply.a(this.j); ++ remotestatusreply.a(Integer.toString(this.r.getPlayerCount())); ++ remotestatusreply.a(Integer.toString(this.h)); ++ remotestatusreply.a((short) this.g); ++ remotestatusreply.a(this.m); ++ */ ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.BASIC; ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() ++ .motd(this.getMotd()) ++ .map(this.getWorldName()) ++ .currentPlayers(this.getServer().getPlayerCount()) ++ .maxPlayers(this.getMaxPlayers()) ++ .port(this.getServerPort()) ++ .hostname(this.getServerHost()) ++ .gameVersion(this.getServer().getServerVersion()) ++ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) ++ .build(); ++ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = ++ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, packet.getAddress(), queryResponse); ++ queryEvent.callEvent(); ++ queryResponse = queryEvent.getResponse(); ++ remotestatusreply.writeString(queryResponse.getMotd()); + remotestatusreply.writeString("SMP"); +- remotestatusreply.writeString(this.worldName); +- remotestatusreply.writeString(Integer.toString(this.serverInterface.getPlayerCount())); +- remotestatusreply.writeString(Integer.toString(this.maxPlayers)); +- remotestatusreply.writeShort((short) this.serverPort); +- remotestatusreply.writeString(this.hostIp); ++ remotestatusreply.writeString(queryResponse.getMap()); ++ remotestatusreply.writeString(Integer.toString(queryResponse.getCurrentPlayers())); ++ remotestatusreply.writeString(Integer.toString(queryResponse.getMaxPlayers())); ++ remotestatusreply.writeShort((short) queryResponse.getPort()); ++ remotestatusreply.writeString(queryResponse.getHostname()); ++ // Paper end + this.sendTo(remotestatusreply.toByteArray(), packet); + QueryThreadGs4.LOGGER.debug("Status [{}]", socketaddress); + } +@@ -150,41 +177,115 @@ public class QueryThreadGs4 extends GenericThread { + this.rulesResponse.writeString("splitnum"); + this.rulesResponse.write((int) 128); + this.rulesResponse.write((int) 0); +- this.rulesResponse.writeString("hostname"); +- this.rulesResponse.writeString(this.serverName); +- this.rulesResponse.writeString("gametype"); +- this.rulesResponse.writeString("SMP"); +- this.rulesResponse.writeString("game_id"); +- this.rulesResponse.writeString("MINECRAFT"); +- this.rulesResponse.writeString("version"); +- this.rulesResponse.writeString(this.serverInterface.getServerVersion()); +- this.rulesResponse.writeString("plugins"); +- this.rulesResponse.writeString(this.serverInterface.getPluginNames()); +- this.rulesResponse.writeString("map"); +- this.rulesResponse.writeString(this.worldName); +- this.rulesResponse.writeString("numplayers"); +- this.rulesResponse.writeString("" + this.serverInterface.getPlayerCount()); +- this.rulesResponse.writeString("maxplayers"); +- this.rulesResponse.writeString("" + this.maxPlayers); +- this.rulesResponse.writeString("hostport"); +- this.rulesResponse.writeString("" + this.serverPort); +- this.rulesResponse.writeString("hostip"); +- this.rulesResponse.writeString(this.hostIp); +- this.rulesResponse.write((int) 0); +- this.rulesResponse.write((int) 1); +- this.rulesResponse.writeString("player_"); +- this.rulesResponse.write((int) 0); +- String[] astring = this.serverInterface.getPlayerNames(); ++ /* Paper start - GS4 Query event ++ this.p.a("hostname"); ++ this.p.a(this.i); ++ this.p.a("gametype"); ++ this.p.a("SMP"); ++ this.p.a("game_id"); ++ this.p.a("MINECRAFT"); ++ this.p.a("version"); ++ this.p.a(this.r.getVersion()); ++ this.p.a("plugins"); ++ this.p.a(this.r.getPlugins()); ++ this.p.a("map"); ++ this.p.a(this.j); ++ this.p.a("numplayers"); ++ this.p.a("" + this.r.getPlayerCount()); ++ this.p.a("maxplayers"); ++ this.p.a("" + this.h); ++ this.p.a("hostport"); ++ this.p.a("" + this.g); ++ this.p.a("hostip"); ++ this.p.a(this.m); ++ this.p.a((int) 0); ++ this.p.a((int) 1); ++ this.p.a("player_"); ++ this.p.a((int) 0); ++ String[] astring = this.r.getPlayers(); + String[] astring1 = astring; + int j = astring.length; + + for (int k = 0; k < j; ++k) { + String s = astring1[k]; + +- this.rulesResponse.writeString(s); ++ this.p.a(s); + } + +- this.rulesResponse.write((int) 0); ++ this.p.a((int) 0); ++ */ ++ // Pack plugins ++ java.util.List plugins = java.util.Collections.emptyList(); ++ org.bukkit.plugin.Plugin[] bukkitPlugins; ++ if (((DedicatedServer) this.getServer()).server.getQueryPlugins() && (bukkitPlugins = org.bukkit.Bukkit.getPluginManager().getPlugins()).length > 0) { ++ plugins = java.util.stream.Stream.of(bukkitPlugins) ++ .map(plugin -> com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation.of(plugin.getName(), plugin.getDescription().getVersion())) ++ .collect(java.util.stream.Collectors.toList()); ++ } ++ ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() ++ .motd(this.getMotd()) ++ .map(this.getWorldName()) ++ .currentPlayers(this.getServer().getPlayerCount()) ++ .maxPlayers(this.getMaxPlayers()) ++ .port(this.getServerPort()) ++ .hostname(this.getServerHost()) ++ .plugins(plugins) ++ .players(this.getServer().getPlayerNames()) ++ .gameVersion(this.getServer().getServerVersion()) ++ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) ++ .build(); ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.FULL; ++ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = ++ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, packet.getAddress(), queryResponse); ++ queryEvent.callEvent(); ++ queryResponse = queryEvent.getResponse(); ++ this.getCachedFullResponse().writeString("hostname"); ++ this.getCachedFullResponse().writeString(queryResponse.getMotd()); ++ this.getCachedFullResponse().writeString("gametype"); ++ this.getCachedFullResponse().writeString("SMP"); ++ this.getCachedFullResponse().writeString("game_id"); ++ this.getCachedFullResponse().writeString("MINECRAFT"); ++ this.getCachedFullResponse().writeString("version"); ++ this.getCachedFullResponse().writeString(queryResponse.getGameVersion()); ++ this.getCachedFullResponse().writeString("plugins"); ++ java.lang.StringBuilder pluginsString = new java.lang.StringBuilder(); ++ pluginsString.append(queryResponse.getServerVersion()); ++ if (!queryResponse.getPlugins().isEmpty()) { ++ pluginsString.append(": "); ++ java.util.Iterator iter = queryResponse.getPlugins().iterator(); ++ while (iter.hasNext()) { ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation info = iter.next(); ++ pluginsString.append(info.getName()); ++ if (info.getVersion() != null) { ++ pluginsString.append(' ').append(info.getVersion().replace(";", ",")); ++ } ++ if (iter.hasNext()) { ++ pluginsString.append(';').append(' '); ++ } ++ } ++ } ++ this.getCachedFullResponse().writeString(pluginsString.toString()); ++ this.getCachedFullResponse().writeString("map"); ++ this.getCachedFullResponse().writeString(queryResponse.getMap()); ++ this.getCachedFullResponse().writeString("numplayers"); ++ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getCurrentPlayers())); ++ this.getCachedFullResponse().writeString("maxplayers"); ++ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getMaxPlayers())); ++ this.getCachedFullResponse().writeString("hostport"); ++ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getPort())); ++ this.getCachedFullResponse().writeString("hostip"); ++ this.getCachedFullResponse().writeString(queryResponse.getHostname()); ++ // The "meaningless data" start, copied from above ++ this.getCachedFullResponse().writeInt(0); ++ this.getCachedFullResponse().writeInt(1); ++ this.getCachedFullResponse().writeString("player_"); ++ this.getCachedFullResponse().writeInt(0); ++ // "Meaningless data" end ++ queryResponse.getPlayers().forEach(this.getCachedFullResponse()::writeStringUnchecked); ++ this.getCachedFullResponse().writeInt(0); ++ // Paper end + return this.rulesResponse.toByteArray(); + } + } diff --git a/Remapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch b/Remapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch new file mode 100644 index 0000000000..3c2cf5afe6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 25 Nov 2020 16:33:27 -0800 +Subject: [PATCH] Added PlayerLoomPatternSelectEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +index 3460fb2bb1451b8456a7fe42449ec4dbce641f40..0dc1b0b7181c0f93dcf6213c63baffcd4694d70c 100644 +--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +@@ -20,6 +20,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; + import org.bukkit.craftbukkit.inventory.CraftInventoryView; + import org.bukkit.entity.Player; + // CraftBukkit end ++import io.papermc.paper.event.player.PlayerLoomPatternSelectEvent; // Paper + + public class LoomMenu extends AbstractContainerMenu { + +@@ -39,7 +40,7 @@ public class LoomMenu extends AbstractContainerMenu { + } + // CraftBukkit end + private final ContainerLevelAccess access; +- private final DataSlot selectedBannerPatternIndex; ++ private final DataSlot selectedBannerPatternIndex; public final DataSlot getSelectedBannerPattern() { return this.selectedBannerPatternIndex; }; // Paper - OBFHELPER + private Runnable slotUpdateListener; + private final Slot bannerSlot; + private final Slot dyeSlot; +@@ -158,7 +159,22 @@ public class LoomMenu extends AbstractContainerMenu { + @Override + public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + if (id > 0 && id <= BannerPattern.AVAILABLE_PATTERNS) { +- this.selectedBannerPatternIndex.set(id); ++ // Paper start ++ int enumBannerPatternTypeOrdinal = id; ++ PlayerLoomPatternSelectEvent event = new PlayerLoomPatternSelectEvent((Player) player.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.block.banner.PatternType.getByIdentifier(BannerPattern.values()[id].getIdentifier())); ++ if (!event.callEvent()) { ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ return false; ++ } ++ for (BannerPattern nms : BannerPattern.values()) { ++ if (event.getPatternType().getIdentifier().equals(nms.getIdentifier())) { ++ enumBannerPatternTypeOrdinal = nms.ordinal(); ++ break; ++ } ++ } ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ this.getSelectedBannerPattern().set(enumBannerPatternTypeOrdinal); ++ // Paper end + this.setupResultSlot(); + return true; + } else { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java b/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java +index 9ea01d5888a21b0dedb555d118a4dc07af2b50fd..9ee3f8bb2294fc552735a64efbddf661d39602c7 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java +@@ -33,6 +33,7 @@ public enum BannerPattern { + this.hasPatternItem = flag; + } + ++ public String getIdentifier() { return this.getHashname(); } // Paper - OBFHELPER + public String getHashname() { + return this.hashname; + } diff --git a/Remapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch b/Remapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch new file mode 100644 index 0000000000..c1c84edf4d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 3 Jan 2021 22:27:43 -0800 +Subject: [PATCH] Configurable door breaking difficulty + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 23a23e2ea133ce81d3dedc4ffd17435a995497ef..7ebc85264a2cbfb601dfe5472b561cac1a7cf8bf 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -5,7 +5,10 @@ import java.util.EnumMap; + import java.util.HashMap; + import java.util.List; + import java.util.Map; +- ++import java.util.stream.Collectors; ++import net.minecraft.world.Difficulty; ++import net.minecraft.world.entity.monster.Vindicator; ++import net.minecraft.world.entity.monster.Zombie; + import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; + import org.bukkit.Bukkit; + import org.bukkit.Material; +@@ -73,6 +76,11 @@ public class PaperWorldConfig { + return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); + } + ++ private > List getEnumList(String path, List def, Class type) { ++ config.addDefault("world-settings.default." + path, def.stream().map(Enum::name).collect(Collectors.toList())); ++ return ((List) (config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)))).stream().map(s -> Enum.valueOf(type, s)).collect(Collectors.toList()); ++ } ++ + public int cactusMaxHeight; + public int reedMaxHeight; + public int bambooMaxHeight; +@@ -735,4 +743,23 @@ public class PaperWorldConfig { + private void disableMobSpawnerSpawnEggTransformation() { + disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); + } ++ ++ public List zombieBreakDoors; ++ public List vindicatorBreakDoors; ++ private void setupEntityBreakingDoors() { ++ zombieBreakDoors = getEnumList( ++ "door-breaking-difficulty.zombie", ++ Arrays.stream(Difficulty.values()) ++ .filter(Zombie.getDoorBreakingPredicate()) ++ .collect(Collectors.toList()), ++ Difficulty.class ++ ); ++ vindicatorBreakDoors = getEnumList( ++ "door-breaking-difficulty.vindicator", ++ Arrays.stream(Difficulty.values()) ++ .filter(Vindicator.getDoorBreakingPredicate()) ++ .collect(Collectors.toList()), ++ Difficulty.class ++ ); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +index 623de661f3b56062792e3a7dbc508637aa58aca5..48700094da6e97610ccc652593a9e229ba7b1003 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +@@ -48,6 +48,7 @@ import net.minecraft.world.level.ServerLevelAccessor; + + public class Vindicator extends AbstractIllager { + ++ public static final Predicate getDoorBreakingPredicate() { return DOOR_BREAKING_PREDICATE; } // Paper - OBFHELPER + private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { + return enumdifficulty == Difficulty.NORMAL || enumdifficulty == Difficulty.HARD; + }; +@@ -204,7 +205,7 @@ public class Vindicator extends AbstractIllager { + static class VindicatorBreakDoorGoal extends BreakDoorGoal { + + public VindicatorBreakDoorGoal(Mob mob) { +- super(mob, 6, Vindicator.DOOR_BREAKING_PREDICATE); ++ super(mob, 6, com.google.common.base.Predicates.in(mob.level.paperConfig.vindicatorBreakDoors)); // Paper + this.setFlags(EnumSet.of(Goal.Flag.MOVE)); + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 74fd175c4dc2d0d9832ee41efaf065b75a43f4b8..caa99a2737598bd74ede54f1c35ce4b99ce1e6d3 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -83,6 +83,7 @@ public class Zombie extends Monster { + private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT); + public static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); ++ public static final Predicate getDoorBreakingPredicate() { return DOOR_BREAKING_PREDICATE; } // Paper - OBFHELPER + private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { + return enumdifficulty == Difficulty.HARD; + }; +@@ -95,7 +96,7 @@ public class Zombie extends Monster { + + public Zombie(EntityType type, Level world) { + super(type, world); +- this.breakDoorGoal = new BreakDoorGoal(this, Zombie.DOOR_BREAKING_PREDICATE); ++ this.breakDoorGoal = new BreakDoorGoal(this, com.google.common.base.Predicates.in(world.paperConfig.zombieBreakDoors)); // Paper + } + + public Zombie(Level world) { diff --git a/Remapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch b/Remapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch new file mode 100644 index 0000000000..a9abc78c3f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 6 Jan 2021 23:38:43 +0100 +Subject: [PATCH] Empty commands shall not be dispatched + + +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index c63033e3eb50423a7c32acfc0e705623cc4bec68..5ed78383ce247ceb24cda0335dbeae293958055c 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -223,6 +223,7 @@ public class Commands { + command = event.getCommand(); + + String[] args = command.split(" "); ++ if (args.length == 0) return 0; // Paper - empty commands shall not be dispatched + + String cmd = args[0]; + if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); diff --git a/Remapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch b/Remapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch new file mode 100644 index 0000000000..4f115620e4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Mon, 4 Jan 2021 16:40:27 +1000 +Subject: [PATCH] Implement API to expose exact interaction point + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 6269e37f2859417a80e6de16045f1c2325f9746f..37761176861027d0ee06f50d60584687fdac669b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -495,7 +495,7 @@ public class ServerPlayerGameMode { + cancelledBlock = true; + } + +- PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand); ++ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand, hitResult.getLocation()); // Paper + firedInteract = true; + interactResult = event.useItemInHand() == Event.Result.DENY; + 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 8829ef03d0be16d8317aaf05bcd286b74f20656a..586d21eed8189adf696ca6d3642afebbe752d1b5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -58,7 +58,9 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import net.minecraft.world.phys.Vec3; + import org.bukkit.Bukkit; ++import org.bukkit.Location; // Paper + import org.bukkit.Material; + import org.bukkit.NamespacedKey; + import org.bukkit.Server; +@@ -475,7 +477,13 @@ public class CraftEventFactory { + return callPlayerInteractEvent(who, action, position, direction, itemstack, false, hand); + } + ++ // Paper start - Add interactionPoint + public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, InteractionHand hand) { ++ return callPlayerInteractEvent(who, action, position, direction, itemstack, cancelledBlock, hand, null); ++ } ++ ++ public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, InteractionHand hand, Vec3 hitVec) { ++ // Paper end + Player player = (who == null) ? null : (Player) who.getBukkitEntity(); + CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack); + +@@ -501,7 +509,10 @@ public class CraftEventFactory { + itemInHand = null; + } + +- PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); ++ // Paper start ++ Location interactionPoint = hitVec == null ? null : new Location(craftWorld, hitVec.x, hitVec.y, hitVec.z); ++ PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND), interactionPoint); ++ // Paper end + if (cancelledBlock) { + event.setUseInteractedBlock(Event.Result.DENY); + } diff --git a/Remapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch b/Remapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch new file mode 100644 index 0000000000..561ae57f81 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 9 Jan 2021 14:17:07 +0100 +Subject: [PATCH] Remove stale POIs + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index fe7b71fbb3963beafe93a5d86bebdd629c7ec8f2..9f1838d12b13d64f10871eb672ed2aec78d9936e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -2071,6 +2071,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + }); + optional1.ifPresent((villageplacetype) -> { + this.getServer().execute(() -> { ++ // Paper start ++ if (!optional.isPresent() && this.getPoiStorage().test(blockposition1, com.google.common.base.Predicates.alwaysTrue())) { ++ this.getPoiStorage().remove(blockposition1); ++ } ++ // Paper end + this.getPoiManager().add(blockposition1, villageplacetype); + DebugPackets.sendPoiAddedPacket(this, blockposition1); + }); +@@ -2078,6 +2083,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + } + ++ public final PoiManager getPoiStorage() { return this.getPoiManager(); } // Paper - OBFHELPER + public PoiManager getPoiManager() { + return this.getChunkSource().getPoiManager(); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +index b9d32e3322c2cce1aca2a90df71b6175a6f8c548..25b26a78a55f98687ed22e986b54d5e9d47a16ea 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +@@ -54,6 +54,7 @@ public class PoiManager extends SectionStorage { + ((PoiSection) this.getOrCreate(SectionPos.of(pos).asLong())).add(pos, type); + } + ++ public void remove(BlockPos blockposition) { this.remove(blockposition); } // Paper - OBFHELPER + public void remove(BlockPos pos) { + ((PoiSection) this.getOrCreate(SectionPos.of(pos).asLong())).remove(pos); + } +@@ -138,6 +139,7 @@ public class PoiManager extends SectionStorage { + return ((PoiSection) this.getOrCreate(SectionPos.of(pos).asLong())).release(pos); + } + ++ public final boolean test(BlockPos blockposition, Predicate predicate) { return this.exists(blockposition, predicate); } // Paper - OBFHELPER + public boolean exists(BlockPos pos, Predicate predicate) { + return (Boolean) this.getOrLoad(SectionPos.of(pos).asLong()).map((villageplacesection) -> { + return villageplacesection.exists(pos, predicate); diff --git a/Remapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch b/Remapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch new file mode 100644 index 0000000000..bc4c9d15d6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Mon, 11 Jan 2021 12:43:51 -0800 +Subject: [PATCH] Fix villager boat exploit + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7e07fd0c8dec9f9cdeda65dfa0ccf42b4dde010e..9d1116f601b79dabf7a0d9e5ecf5c2a0306f9aa4 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -78,6 +78,7 @@ import net.minecraft.util.Mth; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.npc.AbstractVillager; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GameType; +@@ -617,6 +618,15 @@ public abstract class PlayerList { + + for (Iterator iterator = entity.getIndirectPassengers().iterator(); iterator.hasNext(); entity1.removed = true) { + entity1 = (Entity) iterator.next(); ++ // Paper start ++ if (entity1 instanceof AbstractVillager) { ++ final AbstractVillager villager = (AbstractVillager) entity1; ++ final net.minecraft.world.entity.player.Player human = villager.getTradingPlayer(); ++ if (human != null) { ++ villager.setTradingPlayer(null); ++ } ++ } ++ // Paper end + worldserver.despawn(entity1); + } + diff --git a/Remapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch b/Remapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch new file mode 100644 index 0000000000..a9cb53ca69 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Wed, 18 Nov 2020 20:52:25 -0800 +Subject: [PATCH] Entity load/save limit per chunk + +Adds a config option to limit the number of entities saved and loaded +to a chunk. The default values of -1 disable the limit. Although +defaults are only included for certain entites, this allows setting +limits for any entity type. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 7ebc85264a2cbfb601dfe5472b561cac1a7cf8bf..486e5438254348db68017228af131cba7defd637 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -7,6 +7,7 @@ import java.util.List; + import java.util.Map; + import java.util.stream.Collectors; + import net.minecraft.world.Difficulty; ++import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.monster.Vindicator; + import net.minecraft.world.entity.monster.Zombie; + import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; +@@ -762,4 +763,18 @@ public class PaperWorldConfig { + Difficulty.class + ); + } ++ ++ public Map, Integer> entityPerChunkSaveLimits = new HashMap<>(); ++ private void entityPerChunkSaveLimits() { ++ getInt("entity-per-chunk-save-limit.experience_orb", -1); ++ getInt("entity-per-chunk-save-limit.snowball", -1); ++ getInt("entity-per-chunk-save-limit.ender_pearl", -1); ++ getInt("entity-per-chunk-save-limit.arrow", -1); ++ EntityType.getEntityNameList().forEach(name -> { ++ final EntityType type = EntityType.getByName(name.getPath()).orElseThrow(() -> new IllegalStateException("Unknown Entity Type: " + name.toString())); ++ final String path = ".entity-per-chunk-save-limit." + name.getPath(); ++ final int value = config.getInt("world-settings." + worldName + path, config.getInt("world-settings.default" + path, -1)); // get without setting defaults ++ if (value != -1) entityPerChunkSaveLimits.put(type, value); ++ }); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index f6a814f9305813eaafa56baa0327e0111cd4e38c..30f80f8549c3236d6bfe594e323e4ca6e702005d 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -539,11 +539,22 @@ public class ChunkSerializer { + + chunk.setLastSaveHadEntities(false); + ++ // Paper start ++ final Map, Integer> savedEntityCounts = Maps.newHashMap(); + for (int j = 0; j < chunk.getEntitySlices().length; ++j) { + Iterator iterator1 = chunk.getEntitySlices()[j].iterator(); + + while (iterator1.hasNext()) { + Entity entity = (Entity) iterator1.next(); ++ final EntityType entityType = entity.getType(); ++ final int saveLimit = worldserver.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ continue; ++ } ++ savedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end + CompoundTag nbttagcompound4 = new CompoundTag(); + // Paper start + if (asyncsavedata == null && !entity.removed && (int) Math.floor(entity.getX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk.getPos().z) { +@@ -674,10 +685,21 @@ public class ChunkSerializer { + ListTag nbttaglist = tag.getList("Entities", 10); + Level world = chunk.getLevel(); + ++ // Paper start ++ final Map, Integer> loadedEntityCounts = Maps.newHashMap(); + for (int i = 0; i < nbttaglist.size(); ++i) { + CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); + + EntityType.loadEntityRecursive(nbttagcompound1, world, (entity) -> { ++ final EntityType entityType = entity.getType(); ++ final int saveLimit = world.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ return null; ++ } ++ loadedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end + chunk.addEntity(entity); + return entity; + }); diff --git a/Remapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch b/Remapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch new file mode 100644 index 0000000000..82ff3e57c1 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Tue, 29 Dec 2020 15:03:03 +0100 +Subject: [PATCH] Add sendOpLevel API + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 9d1116f601b79dabf7a0d9e5ecf5c2a0306f9aa4..c962b6fc0c65dc5e2ea636220727bca63bf4b740 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1134,22 +1134,29 @@ public abstract class PlayerList { + } + + private void sendPlayerPermissionLevel(ServerPlayer player, int permissionLevel) { +- if (player.connection != null) { ++ // Paper start - add recalculatePermissions parameter ++ this.sendPlayerOperatorStatus(player, permissionLevel, true); ++ } ++ public void sendPlayerOperatorStatus(ServerPlayer entityplayer, int i, boolean recalculatePermissions) { ++ // Paper end ++ if (entityplayer.connection != null) { + byte b0; + +- if (permissionLevel <= 0) { ++ if (i <= 0) { + b0 = 24; +- } else if (permissionLevel >= 4) { ++ } else if (i >= 4) { + b0 = 28; + } else { +- b0 = (byte) (24 + permissionLevel); ++ b0 = (byte) (24 + i); + } + +- player.connection.send(new ClientboundEntityEventPacket(player, b0)); ++ entityplayer.connection.send(new ClientboundEntityEventPacket(entityplayer, b0)); + } + +- player.getBukkitEntity().recalculatePermissions(); // CraftBukkit +- this.server.getCommands().sendCommands(player); ++ if (recalculatePermissions) { // Paper ++ entityplayer.getBukkitEntity().recalculatePermissions(); // CraftBukkit ++ this.server.getCommands().sendCommands(entityplayer); ++ } // Paper + } + + // Paper start +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 40380fff222cc1f3340cf6a6c4afbe60aaa5d3a6..d2d179cdef8129653983b01d94928ba83f64f644 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2296,6 +2296,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + ? (org.bukkit.entity.Firework) entity.getBukkitEntity() + : null; + } ++ ++ @Override ++ public void sendOpLevel(byte level) { ++ Preconditions.checkArgument(level >= 0 && level <= 4, "Level must be within [0, 4]"); ++ ++ this.getHandle().getServer().getPlayerList().sendPlayerOperatorStatus(this.getHandle(), level, false); ++ } + // Paper end + + // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch b/Remapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch new file mode 100644 index 0000000000..6aaa2cdea9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: dfsek +Date: Wed, 16 Sep 2020 01:12:29 -0700 +Subject: [PATCH] Add StructureLocateEvent + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +index 860af116dbc7dd9d691ff27d28a2d10dbec83df4..29310d96eb562ead1e568a97b6f3019e43ca0a88 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.chunk; + + import com.google.common.collect.Lists; + import com.mojang.serialization.Codec; ++import io.papermc.paper.event.world.StructureLocateEvent; // Paper - Add import due to naming conflict. + import java.util.BitSet; + import java.util.Iterator; + import java.util.List; +@@ -160,6 +161,22 @@ public abstract class ChunkGenerator { + + @Nullable + public BlockPos findNearestMapFeature(ServerLevel world, StructureFeature feature, BlockPos center, int radius, boolean skipExistingChunks) { ++ // Paper start ++ org.bukkit.World world1 = world.getWorld(); ++ org.bukkit.Location originLocation = new org.bukkit.Location(world1, center.getX(), center.getY(), center.getZ()); ++ StructureLocateEvent event = new StructureLocateEvent(world1, originLocation, org.bukkit.StructureType.getStructureTypes().get(feature.getFeatureName()), radius, skipExistingChunks); ++ if(!event.callEvent()) return null; ++ // If event call set a final location, skip structure finding and just return set result. ++ if(event.getResult() != null) return new BlockPos(event.getResult().getBlockX(), event.getResult().getBlockY(), event.getResult().getBlockZ()); ++ // Get origin location (re)defined by event call. ++ center = new BlockPos(event.getOrigin().getBlockX(), event.getOrigin().getBlockY(), event.getOrigin().getBlockZ()); ++ // Get world (re)defined by event call. ++ world = ((org.bukkit.craftbukkit.CraftWorld) event.getOrigin().getWorld()).getHandle(); ++ // Get radius and whether to find unexplored structures (re)defined by event call. ++ radius = event.getRadius(); ++ skipExistingChunks = event.shouldFindUnexplored(); ++ feature = StructureFeature.STRUCTURES_REGISTRY.get(event.getType().getName()); ++ // Paper end + if (!this.biomeSource.canGenerateStructure(feature)) { + return null; + } else if (feature == StructureFeature.STRONGHOLD) { diff --git a/Remapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch b/Remapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch new file mode 100644 index 0000000000..33e77f9b2e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 14 Nov 2020 16:48:37 +0100 +Subject: [PATCH] Collision option for requiring a player participant + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 486e5438254348db68017228af131cba7defd637..3dd228ae8071a747f2cd7b2b46a2215183f72cd0 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -717,6 +717,18 @@ public class PaperWorldConfig { + } + } + ++ public boolean onlyPlayersCollide = false; ++ public boolean allowVehicleCollisions = true; ++ private void onlyPlayersCollide() { ++ onlyPlayersCollide = getBoolean("only-players-collide", onlyPlayersCollide); ++ allowVehicleCollisions = getBoolean("allow-vehicle-collisions", allowVehicleCollisions); ++ if (onlyPlayersCollide && !allowVehicleCollisions) { ++ log("Collisions will only work if a player is one of the two entities colliding."); ++ } else if (onlyPlayersCollide) { ++ log("Collisions will only work if a player OR a vehicle is one of the two entities colliding."); ++ } ++ } ++ + public int wanderingTraderSpawnMinuteTicks = 1200; + public int wanderingTraderSpawnDayTicks = 24000; + public int wanderingTraderSpawnChanceFailureIncrement = 25; +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index ec98f5f59ca2b4cb58eb00ed8cdfa364f8bacd88..87c719caf796f54296ff7e412548062e02af270e 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1465,6 +1465,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public void push(Entity entity) { + if (!this.isPassengerOfSameVehicle(entity)) { + if (!entity.noPhysics && !this.noPhysics) { ++ if (this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer || this instanceof ServerPlayer)) return; // Paper + double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); + double d2 = Mth.absMax(d0, d1); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 9cbde70787d8044f0edeb3d459231dd7fbb79584..25df3ef6b96bec39847a732394af8eccdb4d5d45 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -21,6 +21,7 @@ import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.Tag; + import net.minecraft.util.Mth; +@@ -766,6 +767,7 @@ public abstract class AbstractMinecart extends Entity { + public void push(Entity entity) { + if (!this.level.isClientSide) { + if (!entity.noPhysics && !this.noPhysics) { ++ if (!this.level.paperConfig.allowVehicleCollisions && this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer)) return; // Paper + if (!this.hasPassenger(entity)) { + // CraftBukkit start + VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +index 6a9c18540886979b2212bf7917a21753c9a9db3c..e7ac3bff190c899397d6576fabbf4966878ea7e5 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +@@ -14,6 +14,7 @@ import net.minecraft.network.protocol.game.ServerboundPaddleBoatPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.FluidTags; +@@ -229,6 +230,7 @@ public class Boat extends Entity { + + @Override + public void push(Entity entity) { ++ if (!this.level.paperConfig.allowVehicleCollisions && this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer)) return; // Paper + if (entity instanceof Boat) { + if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { + // CraftBukkit start diff --git a/Remapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/Remapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch new file mode 100644 index 0000000000..ed43990f0e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 16 Jan 2021 14:30:12 -0500 +Subject: [PATCH] Remove ProjectileHitEvent call when fireballs dead + +The duplicate ProjectileHitEvent in EntityFireball was removed. The +event was always called before the duplicate call. + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +index 872ff430547276e2a41a48aa07ae63b87ab39e5d..cba1b361162456cf297d88439f76586a2f61fc45 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +@@ -86,7 +86,7 @@ public abstract class AbstractHurtingProjectile extends Projectile { + + // CraftBukkit start - Fire ProjectileHitEvent + if (this.removed) { +- CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ // CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); // Paper - this is an undesired duplicate event + } + // CraftBukkit end + } diff --git a/Remapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch b/Remapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch new file mode 100644 index 0000000000..8f0e61039a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: CDFN +Date: Tue, 7 Jul 2020 17:53:23 +0200 +Subject: [PATCH] Return chat component with empty text instead of throwing + exception + + +diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index b5d79635cd8b0eb6b17962450b347010aeb52654..d2f762371f82d54bcec8b1a0a02d0866e55fd174 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -12,6 +12,7 @@ import net.minecraft.ReportedException; + import net.minecraft.core.NonNullList; + import net.minecraft.core.Registry; + import net.minecraft.network.chat.Component; ++import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; +@@ -60,7 +61,12 @@ public abstract class AbstractContainerMenu { + } + private Component title; + public final Component getTitle() { +- Preconditions.checkState(this.title != null, "Title not set"); ++ // Paper start - return chat component with empty text instead of throwing error ++ // Preconditions.checkState(this.title != null, "Title not set"); ++ if(this.title == null){ ++ return new TextComponent(""); ++ } ++ // Paper end + return this.title; + } + public final void setTitle(Component title) { diff --git a/Remapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch b/Remapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch new file mode 100644 index 0000000000..24fcb77734 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 4 Jan 2021 19:52:44 -0800 +Subject: [PATCH] Make schedule command per-world + + +diff --git a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java +index 122a790285734ecd95fe6817043a84cf1752dbe8..173ab97b01b2191d9d731a28f2690eb4f539880b 100644 +--- a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java ++++ b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java +@@ -32,7 +32,7 @@ public class ScheduleCommand { + return new TranslatableComponent("commands.schedule.cleared.failure", new Object[]{object}); + }); + private static final SuggestionProvider SUGGEST_SCHEDULE = (commandcontext, suggestionsbuilder) -> { +- return SharedSuggestionProvider.suggest((Iterable) ((CommandSourceStack) commandcontext.getSource()).getServer().getWorldData().overworldData().getScheduledEvents().getEventsIds(), suggestionsbuilder); ++ return SharedSuggestionProvider.suggest((Iterable) ((CommandSourceStack) commandcontext.getSource()).getLevel().worldDataServer.overworldData().getScheduledEvents().getEventsIds(), suggestionsbuilder); // Paper + }; + + public static void register(CommandDispatcher dispatcher) { +@@ -55,7 +55,7 @@ public class ScheduleCommand { + } else { + long j = source.getLevel().getGameTime() + (long) i; + ResourceLocation minecraftkey = (ResourceLocation) pair.getFirst(); +- TimerQueue customfunctioncallbacktimerqueue = source.getServer().getWorldData().overworldData().getScheduledEvents(); ++ TimerQueue customfunctioncallbacktimerqueue = source.getLevel().worldDataServer.overworldData().getScheduledEvents(); // Paper + + ((Either) pair.getSecond()).ifLeft((customfunction) -> { + String s = minecraftkey.toString(); +@@ -81,7 +81,7 @@ public class ScheduleCommand { + } + + private static int remove(CommandSourceStack commandlistenerwrapper, String s) throws CommandSyntaxException { +- int i = commandlistenerwrapper.getServer().getWorldData().overworldData().getScheduledEvents().remove(s); ++ int i = commandlistenerwrapper.getLevel().worldDataServer.overworldData().getScheduledEvents().remove(s); // Paper + + if (i == 0) { + throw ScheduleCommand.ERROR_CANT_REMOVE.create(s); diff --git a/Remapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch b/Remapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch new file mode 100644 index 0000000000..42d46d7655 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 3 Jan 2021 21:04:03 -0800 +Subject: [PATCH] Configurable max leash distance + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3dd228ae8071a747f2cd7b2b46a2215183f72cd0..c4ca7ed5b251a2a3d64297351ef32541a4243c35 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -166,6 +166,12 @@ public class PaperWorldConfig { + } + } + ++ public float maxLeashDistance = 10f; ++ private void maxLeashDistance() { ++ maxLeashDistance = getFloat("max-leash-distance", maxLeashDistance); ++ log("Max leash distance: " + maxLeashDistance); ++ } ++ + public boolean disableEndCredits; + private void disableEndCredits() { + disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +index 7c82d453388a27b69207d051dec316fc14715e2b..a884940cc576704951d42c6b0d00f5a319297c29 100644 +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -46,7 +46,7 @@ public abstract class PathfinderMob extends Mob { + float f = this.distanceTo(entity); + + if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) { +- if (f > 10.0F) { ++ if (f > entity.level.paperConfig.maxLeashDistance) { // Paper + this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + } +@@ -55,7 +55,7 @@ public abstract class PathfinderMob extends Mob { + } + + this.onLeashDistance(f); +- if (f > 10.0F) { ++ if (f > entity.level.paperConfig.maxLeashDistance) { // Paper + this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + this.goalSelector.disableControlFlag(Goal.Flag.MOVE); diff --git a/Remapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch b/Remapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch new file mode 100644 index 0000000000..fea75084e5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Sun, 17 Jan 2021 13:16:09 +1000 +Subject: [PATCH] Implement BlockPreDispenseEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +index 2a4cb76bdfcf55ba222b4976359c1b8efb165009..08ce586f8d024b57a20031868ca2a3058bc500ee 100644 +--- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +@@ -88,6 +88,7 @@ public class DispenserBlock extends BaseEntityBlock { + DispenseItemBehavior idispensebehavior = this.getDispenseMethod(itemstack); + + if (idispensebehavior != DispenseItemBehavior.NOOP) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(worldserver, pos, itemstack, i)) return; // Paper - BlockPreDispenseEvent is called here + eventFired = false; // CraftBukkit - reset event status + tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 586d21eed8189adf696ca6d3642afebbe752d1b5..34c0216baa69206aca51821aec421484b18cb04c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -59,6 +59,7 @@ import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import io.papermc.paper.event.block.BlockPreDispenseEvent; // Paper + import org.bukkit.Bukkit; + import org.bukkit.Location; // Paper + import org.bukkit.Material; +@@ -1802,5 +1803,11 @@ public class CraftEventFactory { + BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); + return event.callEvent(); + } ++ ++ public static boolean handleBlockPreDispenseEvent(ServerLevel worldserver, BlockPos blockposition, ItemStack itemStack, int slot) { ++ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ BlockPreDispenseEvent event = new BlockPreDispenseEvent(block, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), slot); ++ return event.callEvent(); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch b/Remapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch new file mode 100644 index 0000000000..fcf1ba26d8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 3 Jan 2021 20:03:35 -0800 +Subject: [PATCH] Added Vanilla Entity Tags + + +diff --git a/src/main/java/io/papermc/paper/CraftEntityTag.java b/src/main/java/io/papermc/paper/CraftEntityTag.java +new file mode 100644 +index 0000000000000000000000000000000000000000..687edf189871fc989174248dbf070bcba161f1a8 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/CraftEntityTag.java +@@ -0,0 +1,28 @@ ++package io.papermc.paper; ++ ++import org.bukkit.craftbukkit.tag.CraftTag; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.entity.EntityType; ++ ++import java.util.Collections; ++import java.util.Set; ++import java.util.stream.Collectors; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.tags.TagCollection; ++ ++public class CraftEntityTag extends CraftTag, EntityType> { ++ ++ public CraftEntityTag(TagCollection> registry, ResourceLocation tag) { ++ super(registry, tag); ++ } ++ ++ @Override ++ public boolean isTagged(EntityType item) { ++ return getHandle().isTagged(CraftMagicNumbers.getEntityTypes(item)); ++ } ++ ++ @Override ++ public Set getValues() { ++ return Collections.unmodifiableSet(getHandle().getTagged().stream().map(CraftMagicNumbers::getEntityType).collect(Collectors.toSet())); ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 046fbc646d2818bb2c7e08ff22093523e8246523..3d7cc98710bb925743e6fe8de1f154096334d46c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2221,6 +2221,11 @@ public final class CraftServer implements Server { + Preconditions.checkArgument(clazz == org.bukkit.Fluid.class, "Fluid namespace must have fluid type"); + + return (org.bukkit.Tag) new CraftFluidTag(console.getTags().getFluids(), key); ++ // Paper start ++ case org.bukkit.Tag.REGISTRY_ENTITIES: ++ Preconditions.checkArgument(clazz == org.bukkit.entity.EntityType.class, "Entity namespace must have entitytype type"); ++ return (org.bukkit.Tag) new io.papermc.paper.CraftEntityTag(console.getTags().getEntityTypes(), key); ++ // Paper end + default: + throw new IllegalArgumentException(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index ac94fd569bd4c79e30adef148e09e395ba8c1812..25a29d997f163ce2b11330d66a691601f514a9cb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -116,8 +116,17 @@ public final class CraftMagicNumbers implements UnsafeValues { + private static final Map MATERIAL_ITEM = new HashMap<>(); + private static final Map MATERIAL_BLOCK = new HashMap<>(); + private static final Map MATERIAL_FLUID = new HashMap<>(); ++ // Paper start ++ private static final Map> ENTITY_TYPE_ENTITY_TYPES = new HashMap<>(); ++ private static final Map, org.bukkit.entity.EntityType> ENTITY_TYPES_ENTITY_TYPE = new HashMap<>(); + + static { ++ for (org.bukkit.entity.EntityType type : org.bukkit.entity.EntityType.values()) { ++ if (type == org.bukkit.entity.EntityType.UNKNOWN) continue; ++ ENTITY_TYPE_ENTITY_TYPES.put(type, net.minecraft.core.Registry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey()))); ++ ENTITY_TYPES_ENTITY_TYPE.put(net.minecraft.core.Registry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey())), type); ++ } ++ // Paper end + for (Block block : net.minecraft.core.Registry.BLOCK) { + BLOCK_MATERIAL.put(block, Material.getMaterial(net.minecraft.core.Registry.BLOCK.getKey(block).getPath().toUpperCase(Locale.ROOT))); + } +@@ -183,6 +192,14 @@ public final class CraftMagicNumbers implements UnsafeValues { + public static ResourceLocation key(Material mat) { + return CraftNamespacedKey.toMinecraft(mat.getKey()); + } ++ // Paper start ++ public static net.minecraft.world.entity.EntityType getEntityTypes(org.bukkit.entity.EntityType type) { ++ return ENTITY_TYPE_ENTITY_TYPES.get(type); ++ } ++ public static org.bukkit.entity.EntityType getEntityType(net.minecraft.world.entity.EntityType entityTypes) { ++ return ENTITY_TYPES_ENTITY_TYPE.get(entityTypes); ++ } ++ // Paper end + // ======================================================================== + // Paper start + @Override diff --git a/Remapped-Spigot-Server-Patches/0655-added-Wither-API.patch b/Remapped-Spigot-Server-Patches/0655-added-Wither-API.patch new file mode 100644 index 0000000000..175023cea0 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0655-added-Wither-API.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 5 Jul 2020 15:39:19 -0700 +Subject: [PATCH] added Wither API + + +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +index 1f330d852eb9b3a36570542e10a88ae065798714..fd91c80cd6337b5fa41d6060ecdb44b8fa68a16a 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -80,6 +80,11 @@ public class WitherBoss extends Monster implements RangedAttackMob { + return entityliving.getMobType() != MobType.UNDEAD && entityliving.attackable(); + }; + private static final TargetingConditions TARGETING_CONDITIONS = (new TargetingConditions()).range(20.0D).selector(WitherBoss.LIVING_ENTITY_SELECTOR); ++ // Paper start ++ private boolean canPortal = false; ++ ++ public void setCanTravelThroughPortals(boolean canPortal) { this.canPortal = canPortal; } ++ // Paper end + + public WitherBoss(EntityType type, Level world) { + super(type, world); +@@ -578,6 +583,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { + this.entityData.set((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(headIndex), id); + } + ++ public final boolean isPowered() { return this.isPowered(); } // Paper - OBFHELPER + public boolean isPowered() { + return this.getHealth() <= this.getMaxHealth() / 2.0F; + } +@@ -594,7 +600,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { + + @Override + public boolean canChangeDimensions() { +- return false; ++ return super.canChangeDimensions() && canPortal; // Paper + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +index fdcd680b972da54f9cdb41dff5563e42bd12d8e3..a09f46c586416b77dda40067fe1639a9250af3f0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +@@ -38,4 +38,31 @@ public class CraftWither extends CraftMonster implements Wither, com.destroystok + public BossBar getBossBar() { + return bossBar; + } ++ ++ // Paper start ++ @Override ++ public boolean isCharged() { ++ return getHandle().isPowered(); ++ } ++ ++ @Override ++ public int getInvulnerableTicks() { ++ return getHandle().getInvulnerableTicks(); ++ } ++ ++ @Override ++ public void setInvulnerableTicks(int ticks) { ++ getHandle().setInvulnerableTicks(ticks); ++ } ++ ++ @Override ++ public boolean canTravelThroughPortals() { ++ return getHandle().canChangeDimensions(); ++ } ++ ++ @Override ++ public void setCanTravelThroughPortals(boolean value) { ++ getHandle().setCanTravelThroughPortals(value); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/Remapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch new file mode 100644 index 0000000000..e2d21ff095 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 24 Jun 2020 15:14:51 -0600 +Subject: [PATCH] Added firing of PlayerChangeBeaconEffectEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java +index 1371bfe4a4b5bb065de4d2118b2b32f4ee0b78d9..20069eeece4e03827ed4b3b4e2b713c43b23a366 100644 +--- a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java +@@ -11,6 +11,10 @@ import net.minecraft.world.level.block.Blocks; + import org.bukkit.craftbukkit.inventory.CraftInventoryView; + // CraftBukkit end + ++// Paper start ++import io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent; ++// Paper end ++ + public class BeaconMenu extends AbstractContainerMenu { + + private final Container beacon; +@@ -137,9 +141,15 @@ public class BeaconMenu extends AbstractContainerMenu { + + public void updateEffects(int primaryEffectId, int secondaryEffectId) { + if (this.paymentSlot.hasItem()) { +- this.beaconData.set(1, primaryEffectId); +- this.beaconData.set(2, secondaryEffectId); ++ // Paper start ++ PlayerChangeBeaconEffectEvent event = new PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), org.bukkit.potion.PotionEffectType.getById(primaryEffectId), org.bukkit.potion.PotionEffectType.getById(secondaryEffectId), this.access.getLocation().getBlock()); ++ if (event.callEvent()) { ++ this.beaconData.set(1, event.getPrimary() == null ? 0 : event.getPrimary().getId()); ++ this.beaconData.set(2, event.getSecondary() == null ? 0 : event.getSecondary().getId()); ++ if (!event.willConsumeItem()) return; + this.paymentSlot.a(1); ++ } ++ // Paper end + } + + } diff --git a/Remapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch b/Remapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch new file mode 100644 index 0000000000..239c089fb6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Thu, 19 Nov 2020 02:07:10 +0000 +Subject: [PATCH] Fix console spam when removing chests in water + + +diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +index 6b95cd2e2af66eef324dfcc8f7642da2f9e39d4e..d061548b5490f441b91a2dd90e7668a05f7f2112 100644 +--- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +@@ -239,7 +239,7 @@ public class ChestBlock extends AbstractChestBlock implements + @Override + public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) { + if (!state.is(newState.getBlock())) { +- BlockEntity tileentity = world.getBlockEntity(pos); ++ BlockEntity tileentity = world.getTileEntity(pos, false); // Paper - Don't validate TE - Fix console spam when removing chests in water + + if (tileentity instanceof Container) { + Containers.dropContents(world, pos, (Container) tileentity); diff --git a/Remapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch b/Remapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch new file mode 100644 index 0000000000..2dafd06172 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 26 Nov 2020 11:47:24 +0000 +Subject: [PATCH] Add toggle for always placing the dragon egg + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index c4ca7ed5b251a2a3d64297351ef32541a4243c35..40939de88b1a8169dbfc7a0cd288c2fe9b706426 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -795,4 +795,9 @@ public class PaperWorldConfig { + if (value != -1) entityPerChunkSaveLimits.put(type, value); + }); + } ++ ++ public boolean enderDragonsDeathAlwaysPlacesDragonEgg = false; ++ private void enderDragonsDeathAlwaysPlacesDragonEgg() { ++ enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 84447e9845edad2d228b94184b35b4afb453a14b..e2f784b771b12bd646d519938c33b1c86cc2686d 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -396,7 +396,7 @@ public class EndDragonFight { + this.dragonEvent.setVisible(false); + this.spawnExitPortal(true); + this.spawnNewGateway(); +- if (!this.previouslyKilled) { ++ if (this.level.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg + this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.END_PODIUM_LOCATION), Blocks.DRAGON_EGG.defaultBlockState()); + } + diff --git a/Remapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch b/Remapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch new file mode 100644 index 0000000000..aab6a1ebc8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 27 Nov 2020 17:14:27 -0800 +Subject: [PATCH] Added PlayerStonecutterRecipeSelectEvent + +Co-Authored-By: MiniDigger + +diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index d2f762371f82d54bcec8b1a0a02d0866e55fd174..b5eeb2749237d589eafdfbea073bfe90e609600b 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -117,7 +117,7 @@ public abstract class AbstractContainerMenu { + return slot; + } + +- protected DataSlot addDataSlot(DataSlot containerproperty) { ++ protected DataSlot addDataSlot(DataSlot containerproperty) { return addDataSlot(containerproperty); } protected DataSlot addDataSlot(DataSlot containerproperty) { // Paper - OBFHELPER + this.dataSlots.add(containerproperty); + return containerproperty; + } +diff --git a/src/main/java/net/minecraft/world/inventory/DataSlot.java b/src/main/java/net/minecraft/world/inventory/DataSlot.java +index 56d99e39f8cfe46a780bd17a0f99c3cbbe01c719..e851d6c8e5ad58091a58d489a48cd3ec379ce0da 100644 +--- a/src/main/java/net/minecraft/world/inventory/DataSlot.java ++++ b/src/main/java/net/minecraft/world/inventory/DataSlot.java +@@ -20,7 +20,7 @@ public abstract class DataSlot { + }; + } + +- public static DataSlot shared(final int[] array, final int index) { ++ public static DataSlot shared(final int[] aint, final int i) { return shared(aint, i); } public static DataSlot shared(final int[] array, final int index) { // Paper - OBFHELPER + return new DataSlot() { + @Override + public int get() { +@@ -54,7 +54,7 @@ public abstract class DataSlot { + + public abstract void set(int value); + +- public boolean checkAndClearUpdateFlag() { ++ public boolean checkAndClearUpdateFlag() { return checkAndClearUpdateFlag(); } public boolean checkAndClearUpdateFlag() { // Paper - OBFHELPER + int i = this.get(); + boolean flag = i != this.prevValue; + +diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +index 072bac443e7c54ac2b92e1d93b757bdacf230fbb..beb02f953719170d1668ada1c09d073d84bb7baf 100644 +--- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +@@ -21,13 +21,14 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; + import org.bukkit.craftbukkit.inventory.CraftInventoryView; + import org.bukkit.entity.Player; + // CraftBukkit end ++import io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent; // Paper + + public class StonecutterMenu extends AbstractContainerMenu { + + private final ContainerLevelAccess access; + private final DataSlot selectedRecipeIndex; + private final Level level; +- private List recipes; ++ private List recipes; public final List getRecipes() { return this.recipes; } // Paper - OBFHELPER + private ItemStack input; + private long lastSoundTime; + final Slot inputSlot; +@@ -57,7 +58,7 @@ public class StonecutterMenu extends AbstractContainerMenu { + + public StonecutterMenu(int syncId, Inventory playerInventory, final ContainerLevelAccess context) { + super(MenuType.STONECUTTER, syncId); +- this.selectedRecipeIndex = DataSlot.standalone(); ++ this.selectedRecipeIndex = addDataSlot(DataSlot.shared(new int[1], 0)); // Paper - allow replication + this.recipes = Lists.newArrayList(); + this.input = ItemStack.EMPTY; + this.slotUpdateListener = () -> { +@@ -135,13 +136,36 @@ public class StonecutterMenu extends AbstractContainerMenu { + @Override + public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + if (this.isValidRecipeIndex(id)) { +- this.selectedRecipeIndex.set(id); ++ // Paper start ++ int recipeIndex = id; ++ this.selectedRecipeIndex.set(recipeIndex); ++ this.selectedRecipeIndex.checkAndClearUpdateFlag(); // mark as changed ++ if (this.isValidRecipeIndex(id)) { ++ PlayerStonecutterRecipeSelectEvent event = new PlayerStonecutterRecipeSelectEvent((Player) player.getBukkitEntity(), (org.bukkit.inventory.StonecutterInventory) getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) this.getRecipes().get(id).toBukkitRecipe()); ++ if (!event.callEvent()) { ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ return false; ++ } ++ int newRecipeIndex; ++ if (!this.getRecipes().get(recipeIndex).getId().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { // If the recipe did NOT stay the same ++ for (newRecipeIndex = 0; newRecipeIndex < this.getRecipes().size(); newRecipeIndex++) { ++ if (this.getRecipes().get(newRecipeIndex).getId().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { ++ recipeIndex = newRecipeIndex; ++ break; ++ } ++ } ++ } ++ } ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ this.selectedRecipeIndex.set(recipeIndex); // set new index, so that listeners can read it ++ // Paper end + this.setupResultSlot(); + } + + return true; + } + ++ private boolean isValidRecipeIndex(int index) { return this.isValidRecipeIndex(index); } // Paper - OBFHELPER + private boolean isValidRecipeIndex(int i) { + return i >= 0 && i < this.recipes.size(); + } diff --git a/Remapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/Remapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch new file mode 100644 index 0000000000..33a094ba1f --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch @@ -0,0 +1,156 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Fri, 29 Jan 2021 15:13:11 +0100 +Subject: [PATCH] Add dropLeash variable to EntityUnleashEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 87dd6c012bf1ca6a1e8df44dc0957c4c67d02adc..ea34306858116e5626383af408529091836c2752 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -86,6 +86,7 @@ import org.bukkit.event.entity.EntityTargetEvent; + import org.bukkit.event.entity.EntityTransformEvent; + import org.bukkit.event.entity.EntityUnleashEvent; + import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; ++import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper + // CraftBukkit end + + public abstract class Mob extends LivingEntity { +@@ -1205,12 +1206,15 @@ public abstract class Mob extends LivingEntity { + return InteractionResult.PASS; + } else if (this.getLeashHolder() == player) { + // CraftBukkit start - fire PlayerUnleashEntityEvent +- if (CraftEventFactory.callPlayerUnleashEntityEvent(this, player).isCancelled()) { ++ // Paper start - drop leash variable ++ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, player, !player.abilities.instabuild); ++ if (event.isCancelled()) { ++ // Paper end + ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); + return InteractionResult.PASS; + } + // CraftBukkit end +- this.dropLeash(true, !player.abilities.instabuild); ++ this.dropLeash(true, event.isDropLeash()); // Paper - drop leash variable + return InteractionResult.sidedSuccess(this.level.isClientSide); + } else { + InteractionResult enuminteractionresult = this.checkAndHandleImportantInteractions(player, hand); +@@ -1364,8 +1368,11 @@ public abstract class Mob extends LivingEntity { + + if (this.leashHolder != null) { + if (!this.isAlive() || !this.leashHolder.isAlive()) { +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit +- this.dropLeash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE, true); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + } + + } +@@ -1433,8 +1440,11 @@ public abstract class Mob extends LivingEntity { + boolean flag1 = super.startRiding(entity, force); + + if (flag1 && this.isLeashed()) { +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit +- this.dropLeash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, true); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + } + + return flag1; +@@ -1636,7 +1646,10 @@ public abstract class Mob extends LivingEntity { + @Override + protected void removeAfterChangingDimensions() { + super.removeAfterChangingDimensions(); +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit +- this.dropLeash(true, false); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, false); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +index a884940cc576704951d42c6b0d00f5a319297c29..d16a7bab5495d58ea9e6811d4b507667cfa3d264 100644 +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -47,8 +47,11 @@ public abstract class PathfinderMob extends Mob { + + if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) { + if (f > entity.level.paperConfig.maxLeashDistance) { // Paper +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit +- this.dropLeash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + } + + return; +@@ -56,8 +59,11 @@ public abstract class PathfinderMob extends Mob { + + this.onLeashDistance(f); + if (f > entity.level.paperConfig.maxLeashDistance) { // Paper +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit +- this.dropLeash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + this.goalSelector.disableControlFlag(Goal.Flag.MOVE); + } else if (f > 6.0F) { + double d0 = (entity.getX() - this.getX()) / (double) f; +diff --git a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java +index 465548de7e32028a2aed4b6e9543e1bd9b73700b..1f54c020cc2b1928b2e7edda9ddf7b9d61e6424b 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java +@@ -28,6 +28,8 @@ import net.minecraft.world.phys.AABB; + import org.bukkit.craftbukkit.event.CraftEventFactory; + // CraftBukkit end + ++import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper ++ + public class LeashFenceKnotEntity extends HangingEntity { + + public LeashFenceKnotEntity(EntityType type, Level world) { +@@ -123,11 +125,14 @@ public class LeashFenceKnotEntity extends HangingEntity { + entityinsentient = (Mob) iterator.next(); + if (entityinsentient.isLeashed() && entityinsentient.getLeashHolder() == this) { + // CraftBukkit start +- if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, player).isCancelled()) { ++ // Paper start - drop leash variable ++ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, player, !player.abilities.instabuild); ++ if (event.isCancelled()) { ++ // Paper end + die = false; + continue; + } +- entityinsentient.dropLeash(true, !player.abilities.instabuild); // false -> survival mode boolean ++ entityinsentient.dropLeash(true, event.isDropLeash()); // false -> survival mode boolean // Paper - drop leash variable + // CraftBukkit end + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 34c0216baa69206aca51821aec421484b18cb04c..ea7c30ef17fc66c1fb55d5909f94651c98b181be 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1460,8 +1460,10 @@ public class CraftEventFactory { + return itemInHand; + } + +- public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(Mob entity, net.minecraft.world.entity.player.Player player) { +- PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity()); ++ // Paper start - drop leash variable ++ public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(Mob entity, net.minecraft.world.entity.player.Player player, boolean dropLeash) { ++ PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), dropLeash); ++ // Paper end + entity.level.getCraftServer().getPluginManager().callEvent(event); + return event; + } diff --git a/Remapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch b/Remapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch new file mode 100644 index 0000000000..fac284074d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Beech Horn +Date: Fri, 14 Feb 2020 19:39:59 +0000 +Subject: [PATCH] Skip distance map update when spawning disabled. + + +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 7a615a18f1f297adfe7e046407a019d8933e9ed9..8e27559a12ada05e0530c7fe5b0bfbc4422ccbd6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -825,7 +825,7 @@ public class ServerChunkCache extends ChunkSource { + int l = this.distanceManager.getNaturalSpawnChunkCount(); + // Paper start - per player mob spawning + NaturalSpawner.SpawnState spawnercreature_d; // moved down +- if (this.chunkMap.playerMobDistanceMap != null) { ++ if ((this.spawnFriendlies || this.spawnEnemies) && this.chunkMap.playerMobDistanceMap != null) { // don't update when animals and monsters are disabled + // update distance map + this.level.timings.playerMobDistanceMapUpdate.startTiming(); + this.chunkMap.playerMobDistanceMap.update(this.level.players, this.chunkMap.viewDistance); diff --git a/Remapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch b/Remapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch new file mode 100644 index 0000000000..4349f8f4d8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Yive +Date: Sun, 24 Jan 2021 08:55:19 -0800 +Subject: [PATCH] Reset shield blocking on dimension change + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index ff831ca0cbc0cabbf78178c609ccf70d78da7980..314f168c9d17ab3654c9dda07e48839570f0d332 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1115,6 +1115,11 @@ public class ServerPlayer extends Player implements ContainerListener { + this.level.getCraftServer().getPluginManager().callEvent(changeEvent); + // CraftBukkit end + } ++ // Paper start ++ if (this.isBlocking()) { ++ this.stopUsingItem(); ++ } ++ // Paper end + + return this; + } diff --git a/Remapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch b/Remapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch new file mode 100644 index 0000000000..17cbf7f9ae --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Mon, 25 Jan 2021 14:53:57 +0100 +Subject: [PATCH] add DragonEggFormEvent + + +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index e2f784b771b12bd646d519938c33b1c86cc2686d..f32e2c71929a73258e4eb521c160c247690744d2 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -57,6 +57,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfigur + import net.minecraft.world.phys.AABB; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import io.papermc.paper.event.block.DragonEggFormEvent; // Paper - DragonEggFormEvent + + public class EndDragonFight { + +@@ -396,9 +397,24 @@ public class EndDragonFight { + this.dragonEvent.setVisible(false); + this.spawnExitPortal(true); + this.spawnNewGateway(); ++ // Paper start - DragonEggFormEvent ++ BlockPos eggPosition = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getPosition()); ++ org.bukkit.craftbukkit.block.CraftBlock eggBlock = org.bukkit.craftbukkit.block.CraftBlock.at(this.level, eggPosition); ++ org.bukkit.craftbukkit.block.CraftBlockState eggState = new org.bukkit.craftbukkit.block.CraftBlockState(eggBlock); ++ eggState.setData(Blocks.DRAGON_EGG.defaultBlockState()); ++ DragonEggFormEvent eggEvent = new DragonEggFormEvent(eggBlock, eggState, ++ new org.bukkit.craftbukkit.boss.CraftDragonBattle(this)); ++ // Paper end - DragonEggFormEvent + if (this.level.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg +- this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.END_PODIUM_LOCATION), Blocks.DRAGON_EGG.defaultBlockState()); ++ // Paper start - DragonEggFormEvent ++ //this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); ++ } else { ++ eggEvent.setCancelled(true); ++ } ++ if (eggEvent.callEvent()) { ++ eggEvent.getNewState().update(true); + } ++ // Paper end - DragonEggFormEvent + + this.previouslyKilled = true; + this.dragonKilled = true; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java +index cd24e9db1e9a490117716d4883376bb6b59c7c67..e085607f4033476e80b7dcd7b026449c12a47cf6 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java +@@ -14,7 +14,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConf + + public class EndPodiumFeature extends Feature { + +- public static final BlockPos END_PODIUM_LOCATION = BlockPos.ZERO; ++ public static final BlockPos END_PODIUM_LOCATION = BlockPos.ZERO; public static BlockPos getPosition() { return END_PODIUM_LOCATION; } // Paper - OBFHELPER + private final boolean active; + + public EndPodiumFeature(boolean open) { +@@ -22,43 +22,43 @@ public class EndPodiumFeature extends Feature { + this.active = open; + } + +- public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, NoneFeatureConfiguration config) { +- Iterator iterator = BlockPos.betweenClosed(new BlockPos(pos.getX() - 4, pos.getY() - 1, pos.getZ() - 4), new BlockPos(pos.getX() + 4, pos.getY() + 32, pos.getZ() + 4)).iterator(); ++ public boolean generate(WorldGenLevel generatoraccessseed, ChunkGenerator chunkgenerator, Random random, BlockPos blockposition, NoneFeatureConfiguration worldgenfeatureemptyconfiguration) { // Paper - decompile fix ++ Iterator iterator = BlockPos.betweenClosed(new BlockPos(blockposition.getX() - 4, blockposition.getY() - 1, blockposition.getZ() - 4), new BlockPos(blockposition.getX() + 4, blockposition.getY() + 32, blockposition.getZ() + 4)).iterator(); + + while (iterator.hasNext()) { + BlockPos blockposition1 = (BlockPos) iterator.next(); +- boolean flag = blockposition1.closerThan((Vec3i) pos, 2.5D); ++ boolean flag = blockposition1.closerThan((Vec3i) blockposition, 2.5D); + +- if (flag || blockposition1.closerThan((Vec3i) pos, 3.5D)) { +- if (blockposition1.getY() < pos.getY()) { ++ if (flag || blockposition1.closerThan((Vec3i) blockposition, 3.5D)) { ++ if (blockposition1.getY() < blockposition.getY()) { + if (flag) { +- this.setBlock(world, blockposition1, Blocks.BEDROCK.defaultBlockState()); +- } else if (blockposition1.getY() < pos.getY()) { +- this.setBlock(world, blockposition1, Blocks.END_STONE.defaultBlockState()); ++ this.setBlock(generatoraccessseed, blockposition1, Blocks.BEDROCK.defaultBlockState()); ++ } else if (blockposition1.getY() < blockposition.getY()) { ++ this.setBlock(generatoraccessseed, blockposition1, Blocks.END_STONE.defaultBlockState()); + } +- } else if (blockposition1.getY() > pos.getY()) { +- this.setBlock(world, blockposition1, Blocks.AIR.defaultBlockState()); ++ } else if (blockposition1.getY() > blockposition.getY()) { ++ this.setBlock(generatoraccessseed, blockposition1, Blocks.AIR.defaultBlockState()); + } else if (!flag) { +- this.setBlock(world, blockposition1, Blocks.BEDROCK.defaultBlockState()); ++ this.setBlock(generatoraccessseed, blockposition1, Blocks.BEDROCK.defaultBlockState()); + } else if (this.active) { +- this.setBlock(world, new BlockPos(blockposition1), Blocks.END_PORTAL.defaultBlockState()); ++ this.setBlock(generatoraccessseed, new BlockPos(blockposition1), Blocks.END_PORTAL.defaultBlockState()); + } else { +- this.setBlock(world, new BlockPos(blockposition1), Blocks.AIR.defaultBlockState()); ++ this.setBlock(generatoraccessseed, new BlockPos(blockposition1), Blocks.AIR.defaultBlockState()); + } + } + } + + for (int i = 0; i < 4; ++i) { +- this.setBlock(world, pos.above(i), Blocks.BEDROCK.defaultBlockState()); ++ this.setBlock(generatoraccessseed, blockposition.above(i), Blocks.BEDROCK.defaultBlockState()); + } + +- BlockPos blockposition2 = pos.above(2); ++ BlockPos blockposition2 = blockposition.above(2); + Iterator iterator1 = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator1.hasNext()) { + Direction enumdirection = (Direction) iterator1.next(); + +- this.setBlock(world, blockposition2.relative(enumdirection), (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, enumdirection)); ++ this.setBlock(generatoraccessseed, blockposition2.relative(enumdirection), (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, enumdirection)); + } + + return true; diff --git a/Remapped-Spigot-Server-Patches/0664-EntityMoveEvent.patch b/Remapped-Spigot-Server-Patches/0664-EntityMoveEvent.patch new file mode 100644 index 0000000000..eec865bf53 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0664-EntityMoveEvent.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Tue, 11 Feb 2020 21:56:48 -0600 +Subject: [PATCH] EntityMoveEvent + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 892ca65d258b0745be95d7ef4886c49899b24d92..bc44811f26076871848ba8f5c582ab26b1fd7170 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -13,6 +13,7 @@ import io.netty.buffer.ByteBuf; + import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; + import io.papermc.paper.adventure.PaperAdventure; // Paper ++import io.papermc.paper.event.entity.EntityMoveEvent; + import it.unimi.dsi.fastutil.longs.LongIterator; + import java.awt.image.BufferedImage; + import java.io.BufferedWriter; +@@ -1458,6 +1459,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper ++ worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper + HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + + this.profiler.push(() -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 9f1838d12b13d64f10871eb672ed2aec78d9936e..338b4c382fb8ea349ce81f2009e96de1df7ac5e2 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -207,6 +207,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper ++ public boolean hasEntityMoveEvent = false; // Paper + private static Throwable getAddToWorldStackTrace(Entity entity) { + return new Throwable(entity + " Added to world at " + new java.util.Date()); + } +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 02ddb84c563b3149c4f1b0e24899ce8a21ad61bb..8bc74878919ab7cf6a50d425da61f1b8a8b0ee44 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -10,6 +10,7 @@ import com.mojang.datafixers.util.Pair; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import com.mojang.serialization.DynamicOps; ++import io.papermc.paper.event.entity.EntityMoveEvent; + import java.util.Collection; + import java.util.ConcurrentModificationException; + import java.util.Iterator; +@@ -2909,6 +2910,20 @@ public abstract class LivingEntity extends Entity { + + this.pushEntities(); + this.level.getProfiler().pop(); ++ // Paper start ++ if (((ServerLevel) level).hasEntityMoveEvent) { ++ if (xo != getX() || yo != getY() || zo != getZ() || yRotO != yRot || xRotO != xRot) { ++ Location from = new Location(level.getWorld(), xo, yo, zo, yRotO, xRotO); ++ Location to = new Location (level.getWorld(), getX(), getY(), getZ(), yRot, xRot); ++ EntityMoveEvent event = new EntityMoveEvent(getBukkitLivingEntity(), from, to.clone()); ++ if (!event.callEvent()) { ++ absMoveTo(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); ++ } else if (!to.equals(event.getTo())) { ++ absMoveTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); ++ } ++ } ++ } ++ // Paper end + if (!this.level.isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { + this.hurt(DamageSource.DROWN, 1.0F); + } diff --git a/Remapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch b/Remapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch new file mode 100644 index 0000000000..ca84c216d2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas81298 +Date: Mon, 25 Jan 2021 14:37:57 +0100 +Subject: [PATCH] added option to disable pathfinding updates on block changes + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 40939de88b1a8169dbfc7a0cd288c2fe9b706426..bbb1d0ed9e76f414dc7d73b4f7786891425f55cd 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -800,4 +800,9 @@ public class PaperWorldConfig { + private void enderDragonsDeathAlwaysPlacesDragonEgg() { + enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); + } ++ ++ public boolean updatePathfindingOnBlockUpdate = true; ++ private void setUpdatePathfindingOnBlockUpdate() { ++ updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 338b4c382fb8ea349ce81f2009e96de1df7ac5e2..a7553a856b9c99bee8f75d514b97cfab952bfd33 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1678,6 +1678,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + @Override + public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) { + this.getChunkSource().blockChanged(pos); ++ if(this.paperConfig.updatePathfindingOnBlockUpdate) { // Paper - option to disable pathfinding updates + VoxelShape voxelshape = oldState.getCollisionShape(this, pos); + VoxelShape voxelshape1 = newState.getCollisionShape(this, pos); + +@@ -1706,6 +1707,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + this.tickingEntities = wasTicking; // Paper + } ++ } // Paper + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch b/Remapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch new file mode 100644 index 0000000000..bf3e677ed6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Mon, 18 Jan 2021 20:45:25 -0500 +Subject: [PATCH] Inline shift direction fields + +Removes a layer of indirection for EnumDirection.getAdjacent(X|Y|Z)(), which is in the +critical section for much of the server, including the lighting engine. + +diff --git a/src/main/java/net/minecraft/core/Direction.java b/src/main/java/net/minecraft/core/Direction.java +index 3ebc62fe93a0cd0048e07b0343fc724f2c056010..51217f7e5288162b8e76c8717506b393cd262537 100644 +--- a/src/main/java/net/minecraft/core/Direction.java ++++ b/src/main/java/net/minecraft/core/Direction.java +@@ -53,6 +53,11 @@ public enum Direction implements StringRepresentable { + }, (enumdirection, enumdirection1) -> { + throw new IllegalArgumentException("Duplicate keys"); + }, Long2ObjectOpenHashMap::new)); ++ // Paper start ++ private final int adjX; ++ private final int adjY; ++ private final int adjZ; ++ // Paper end + + private Direction(int i, int j, int k, String s, Direction.AxisDirection enumdirection_enumaxisdirection, Direction.Axis enumdirection_enumaxis, Vec3i baseblockposition) { + this.data3d = i; +@@ -62,6 +67,11 @@ public enum Direction implements StringRepresentable { + this.axis = enumdirection_enumaxis; + this.axisDirection = enumdirection_enumaxisdirection; + this.normal = baseblockposition; ++ // Paper start ++ this.adjX = baseblockposition.getX(); ++ this.adjY = baseblockposition.getY(); ++ this.adjZ = baseblockposition.getZ(); ++ // Paper end + } + + public static Direction[] orderedByNearest(Entity entity) { +@@ -137,15 +147,15 @@ public enum Direction implements StringRepresentable { + } + + public int getStepX() { +- return this.normal.getX(); ++ return this.adjX; // Paper + } + + public int getStepY() { +- return this.normal.getY(); ++ return this.adjY; // Paper + } + + public int getStepZ() { +- return this.normal.getZ(); ++ return this.adjZ; // Paper + } + + public String getName() { diff --git a/Remapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch b/Remapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch new file mode 100644 index 0000000000..973fb6de6c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Wed, 20 Jan 2021 14:23:37 -0600 +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 ea7c30ef17fc66c1fb55d5909f94651c98b181be..5145968c9c6ccabfb15b91102f82e8a3a2d3cf82 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -389,13 +389,30 @@ public class CraftEventFactory { + } + + public static void handleBlockDropItemEvent(Block block, BlockState state, ServerPlayer player, List items) { +- BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), Lists.transform(items, (item) -> (org.bukkit.entity.Item) item.getBukkitEntity())); ++ // Paper start ++ List list = new ArrayList<>(); ++ for (ItemEntity item : items) { ++ list.add((Item) item.getBukkitEntity()); ++ } ++ BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), list); ++ // Paper end + Bukkit.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { +- for (ItemEntity item : items) { +- item.level.addFreshEntity(item); ++ // Paper start ++ for (Item bukkit : list) { ++ if (!bukkit.isValid()) { ++ Entity item = ((org.bukkit.craftbukkit.entity.CraftItem) bukkit).getHandle(); ++ item.level.addFreshEntity(item); ++ } ++ } ++ } else { ++ for (Item bukkit : list) { ++ if (bukkit.isValid()) { ++ bukkit.remove(); ++ } + } ++ // Paper end + } + } + diff --git a/Remapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/Remapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch new file mode 100644 index 0000000000..f2acd9e212 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aleksander Jagiello +Date: Sun, 24 Jan 2021 22:17:54 +0100 +Subject: [PATCH] Add getMainThreadExecutor to BukkitScheduler + + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 13e461ffb2ee2e7d0440c0f60809ea99629b843c..0be39dac4b9dd69d7d73d86d64cf1e33e4086e81 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -635,4 +635,15 @@ public class CraftScheduler implements BukkitScheduler { + public BukkitTask runTaskTimerAsynchronously(Plugin plugin, BukkitRunnable task, long delay, long period) throws IllegalArgumentException { + throw new UnsupportedOperationException("Use BukkitRunnable#runTaskTimerAsynchronously(Plugin, long, long)"); + } ++ ++ // Paper start - add getMainThreadExecutor ++ @Override ++ public Executor getMainThreadExecutor(Plugin plugin) { ++ Validate.notNull(plugin, "Plugin cannot be null"); ++ return command -> { ++ Validate.notNull(command, "Command cannot be null"); ++ this.runTask(plugin, command); ++ }; ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch b/Remapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch new file mode 100644 index 0000000000..78a2270873 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ysl3000 +Date: Sat, 24 Oct 2020 16:37:44 +0200 +Subject: [PATCH] living entity allow attribute registration + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java +index a501f334ce0bcc606dd2bb186cf7195102cd6c09..8acd102c0778e4e546e5191b6098eacbd15bd9f9 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java ++++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java +@@ -21,7 +21,7 @@ import org.apache.logging.log4j.Logger; + public class AttributeMap { + + private static final Logger LOGGER = LogManager.getLogger(); +- private final Map attributes = Maps.newHashMap(); ++ private final Map attributes = Maps.newHashMap(); private final Map attributeMap = attributes; // Paper - OBFHELPER + private final Set dirtyAttributes = Sets.newHashSet(); + private final AttributeSupplier supplier; + +@@ -135,4 +135,12 @@ public class AttributeMap { + } + + } ++ ++ // Paper - start ++ public void registerAttribute(Attribute attributeBase) { ++ AttributeInstance attributeModifiable = new AttributeInstance(attributeBase, AttributeInstance::getAttribute); ++ attributeMap.put(attributeBase, attributeModifiable); ++ } ++ // Paper - end ++ + } +diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +index 320fd6780af2fa99e4e4f4193cbc9338d492dc6d..a57b16679889f5b20c74712651f94d6796b8c661 100644 +--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java ++++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +@@ -38,6 +38,14 @@ public class CraftAttributeMap implements Attributable { + return (nms == null) ? null : new CraftAttributeInstance(nms, attribute); + } + ++ // Paper start ++ @Override ++ public void registerAttribute(Attribute attribute) { ++ Preconditions.checkArgument(attribute != null, "attribute"); ++ handle.registerAttribute(CraftAttributeMap.toMinecraft(attribute)); ++ } ++ // Paper end ++ + public static net.minecraft.world.entity.ai.attributes.Attribute toMinecraft(Attribute attribute) { + return net.minecraft.core.Registry.ATTRIBUTE.get(CraftNamespacedKey.toMinecraft(attribute.getKey())); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index a8d21382d5859edfd12e01a48924ce780790b4b7..eefb6bd580ea176c3a242695ab4af46e7c61b492 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -663,6 +663,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return getHandle().craftAttributes.getAttribute(attribute); + } + ++ // Paper start ++ @Override ++ public void registerAttribute(Attribute attribute) { ++ getHandle().craftAttributes.registerAttribute(attribute); ++ } ++ // Paper end ++ + @Override + public void setAI(boolean ai) { + if (this.getHandle() instanceof Mob) { diff --git a/Remapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch b/Remapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch new file mode 100644 index 0000000000..72df11355c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Fri, 5 Feb 2021 22:12:13 +0100 +Subject: [PATCH] fix dead slime setSize invincibility + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +index 340036135588d06e43cbd229dd3a6613b04bb9ab..d1bb7e1f7f7837774512e0af0c8b855d34d5a85b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +@@ -17,7 +17,7 @@ public class CraftSlime extends CraftMob implements Slime { + + @Override + public void setSize(int size) { +- getHandle().setSize(size, true); ++ getHandle().setSize(size, /* true */ getHandle().isAlive()); // Paper - fix dead slime setSize invincibility + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch b/Remapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch new file mode 100644 index 0000000000..c4baf4a043 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Wed, 10 Feb 2021 14:53:36 -0800 +Subject: [PATCH] Merchant#getRecipes should return an immutable list + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java +index 3437ec2c7c1a84debb7d7b7c90283d7e25208604..b4bcbd6329c67ea3deeeb1bf38233ebd15e922b7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java +@@ -24,7 +24,7 @@ public class CraftMerchant implements Merchant { + + @Override + public List getRecipes() { +- return Collections.unmodifiableList(Lists.transform(merchant.getOffers(), new Function() { ++ return com.google.common.collect.ImmutableList.copyOf(Lists.transform(merchant.getOffers(), new Function() { // Paper - javadoc says 'an immutable list of trades' - not 'an unmodifiable view of a list of trades'. fixes issue with setRecipes(getRecipes()) + @Override + public MerchantRecipe apply(net.minecraft.world.item.trading.MerchantOffer recipe) { + return recipe.asBukkit(); diff --git a/Remapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch b/Remapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch new file mode 100644 index 0000000000..f56af1f8b5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 18 Feb 2021 20:23:28 +0000 +Subject: [PATCH] misc debugging dumps + + +diff --git a/src/main/java/io/papermc/paper/util/TraceUtil.java b/src/main/java/io/papermc/paper/util/TraceUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2d5494d2813b773e60ddba6790b750a9a08f21f8 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/util/TraceUtil.java +@@ -0,0 +1,18 @@ ++package io.papermc.paper.util; ++ ++import org.bukkit.Bukkit; ++ ++public final class TraceUtil { ++ ++ public static void dumpTraceForThread(Thread thread, String reason) { ++ Bukkit.getLogger().warning(thread.getName() + ": " + reason); ++ StackTraceElement[] trace = thread.getStackTrace(); ++ for (StackTraceElement traceElement : trace) { ++ Bukkit.getLogger().warning("\tat " + traceElement); ++ } ++ } ++ ++ public static void dumpTraceForThread(String reason) { ++ new Throwable(reason).printStackTrace(); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index bc44811f26076871848ba8f5c582ab26b1fd7170..9b654fed2a00740cef84cf72258abfc7aeafc0c2 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -14,6 +14,7 @@ import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; + import io.papermc.paper.adventure.PaperAdventure; // Paper + import io.papermc.paper.event.entity.EntityMoveEvent; ++import io.papermc.paper.util.TraceUtil; + import it.unimi.dsi.fastutil.longs.LongIterator; + import java.awt.image.BufferedImage; + import java.io.BufferedWriter; +@@ -855,6 +856,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Sat, 20 Feb 2021 13:09:59 -0500 +Subject: [PATCH] Add support for hex color codes in console + +Converts upstream's hex color code legacy format into actual hex color codes in the console. + +diff --git a/src/main/java/io/papermc/paper/console/HexFormattingConverter.java b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a4315961b7a465fb4872a4d67e7c26d4b4ed1fb9 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java +@@ -0,0 +1,178 @@ ++package io.papermc.paper.console; ++ ++import net.minecrell.terminalconsole.TerminalConsoleAppender; ++import org.apache.logging.log4j.core.LogEvent; ++import org.apache.logging.log4j.core.config.Configuration; ++import org.apache.logging.log4j.core.config.plugins.Plugin; ++import org.apache.logging.log4j.core.layout.PatternLayout; ++import org.apache.logging.log4j.core.pattern.*; ++import org.apache.logging.log4j.util.PerformanceSensitive; ++import org.apache.logging.log4j.util.PropertiesUtil; ++ ++import java.util.List; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++import static net.minecrell.terminalconsole.MinecraftFormattingConverter.KEEP_FORMATTING_PROPERTY; ++ ++/** ++ * Modified version of ++ * TerminalConsoleAppender's MinecraftFormattingConverter to support hex color codes using the md_5 &x&r&r&g&g&b&b format. ++ */ ++@Plugin(name = "paperMinecraftFormatting", category = PatternConverter.CATEGORY) ++@ConverterKeys({ "paperMinecraftFormatting" }) ++@PerformanceSensitive("allocation") ++public final class HexFormattingConverter extends LogEventPatternConverter { ++ ++ private static final boolean KEEP_FORMATTING = PropertiesUtil.getProperties().getBooleanProperty(KEEP_FORMATTING_PROPERTY); ++ ++ private static final String ANSI_RESET = "\u001B[m"; ++ ++ private static final char COLOR_CHAR = '§'; ++ private static final String LOOKUP = "0123456789abcdefklmnor"; ++ ++ private static final String RGB_ANSI = "\u001B[38;2;%d;%d;%dm"; ++ private static final Pattern NAMED_PATTERN = Pattern.compile(COLOR_CHAR + "[0-9a-fk-orA-FK-OR]"); ++ private static final Pattern RGB_PATTERN = Pattern.compile(COLOR_CHAR + "x(" + COLOR_CHAR + "[0-9a-fA-F]){6}"); ++ ++ private static final String[] ansiCodes = new String[] { ++ "\u001B[0;30m", // Black §0 ++ "\u001B[0;34m", // Dark Blue §1 ++ "\u001B[0;32m", // Dark Green §2 ++ "\u001B[0;36m", // Dark Aqua §3 ++ "\u001B[0;31m", // Dark Red §4 ++ "\u001B[0;35m", // Dark Purple §5 ++ "\u001B[0;33m", // Gold §6 ++ "\u001B[0;37m", // Gray §7 ++ "\u001B[0;30;1m", // Dark Gray §8 ++ "\u001B[0;34;1m", // Blue §9 ++ "\u001B[0;32;1m", // Green §a ++ "\u001B[0;36;1m", // Aqua §b ++ "\u001B[0;31;1m", // Red §c ++ "\u001B[0;35;1m", // Light Purple §d ++ "\u001B[0;33;1m", // Yellow §e ++ "\u001B[0;37;1m", // White §f ++ "\u001B[5m", // Obfuscated §k ++ "\u001B[21m", // Bold §l ++ "\u001B[9m", // Strikethrough §m ++ "\u001B[4m", // Underline §n ++ "\u001B[3m", // Italic §o ++ ANSI_RESET, // Reset §r ++ }; ++ ++ private final boolean ansi; ++ private final List formatters; ++ ++ /** ++ * Construct the converter. ++ * ++ * @param formatters The pattern formatters to generate the text to manipulate ++ * @param strip If true, the converter will strip all formatting codes ++ */ ++ protected HexFormattingConverter(List formatters, boolean strip) { ++ super("paperMinecraftFormatting", null); ++ this.formatters = formatters; ++ this.ansi = !strip; ++ } ++ ++ @Override ++ public void format(LogEvent event, StringBuilder toAppendTo) { ++ int start = toAppendTo.length(); ++ //noinspection ForLoopReplaceableByForEach ++ for (int i = 0, size = formatters.size(); i < size; i++) { ++ formatters.get(i).format(event, toAppendTo); ++ } ++ ++ if (KEEP_FORMATTING || toAppendTo.length() == start) { ++ // Skip replacement if disabled or if the content is empty ++ return; ++ } ++ ++ boolean useAnsi = ansi && TerminalConsoleAppender.isAnsiSupported(); ++ String content = toAppendTo.substring(start); ++ content = useAnsi ? convertRGBColors(content) : stripRGBColors(content); ++ format(content, toAppendTo, start, useAnsi); ++ } ++ ++ private static String convertRGBColors(String input) { ++ Matcher matcher = RGB_PATTERN.matcher(input); ++ StringBuffer buffer = new StringBuffer(); ++ while (matcher.find()) { ++ String s = matcher.group().replace(String.valueOf(COLOR_CHAR), "").replace('x', '#'); ++ int hex = Integer.decode(s); ++ int red = (hex >> 16) & 0xFF; ++ int green = (hex >> 8) & 0xFF; ++ int blue = hex & 0xFF; ++ String replacement = String.format(RGB_ANSI, red, green, blue); ++ matcher.appendReplacement(buffer, replacement); ++ } ++ matcher.appendTail(buffer); ++ return buffer.toString(); ++ } ++ ++ private static String stripRGBColors(String input) { ++ Matcher matcher = RGB_PATTERN.matcher(input); ++ StringBuffer buffer = new StringBuffer(); ++ while (matcher.find()) { ++ matcher.appendReplacement(buffer, ""); ++ } ++ matcher.appendTail(buffer); ++ return buffer.toString(); ++ } ++ ++ static void format(String content, StringBuilder result, int start, boolean ansi) { ++ int next = content.indexOf(COLOR_CHAR); ++ int last = content.length() - 1; ++ if (next == -1 || next == last) { ++ result.setLength(start); ++ result.append(content); ++ if (ansi) { ++ result.append(ANSI_RESET); ++ } ++ return; ++ } ++ ++ Matcher matcher = NAMED_PATTERN.matcher(content); ++ StringBuffer buffer = new StringBuffer(); ++ while (matcher.find()) { ++ int format = LOOKUP.indexOf(Character.toLowerCase(matcher.group().charAt(1))); ++ if (format != -1) { ++ matcher.appendReplacement(buffer, ansi ? ansiCodes[format] : ""); ++ } ++ } ++ matcher.appendTail(buffer); ++ ++ result.setLength(start); ++ result.append(buffer.toString()); ++ if (ansi) { ++ result.append(ANSI_RESET); ++ } ++ } ++ ++ /** ++ * Gets a new instance of the {@link HexFormattingConverter} with the ++ * specified options. ++ * ++ * @param config The current configuration ++ * @param options The pattern options ++ * @return The new instance ++ * ++ * @see HexFormattingConverter ++ */ ++ public static HexFormattingConverter newInstance(Configuration config, String[] options) { ++ if (options.length < 1 || options.length > 2) { ++ LOGGER.error("Incorrect number of options on paperMinecraftFormatting. Expected at least 1, max 2 received " + options.length); ++ return null; ++ } ++ if (options[0] == null) { ++ LOGGER.error("No pattern supplied on paperMinecraftFormatting"); ++ return null; ++ } ++ ++ PatternParser parser = PatternLayout.createPatternParser(config); ++ List formatters = parser.parse(options[0]); ++ boolean strip = options.length > 1 && "strip".equals(options[1]); ++ return new HexFormattingConverter(formatters, strip); ++ } ++ ++} +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 8af159abd3d0cc94cf155fec5b384c42f69551bf..67da1aa7a21622fb231d19dede3775a282a4a12e 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -6,21 +6,21 @@ + + + +- ++ + + + ++ pattern="%highlightError{[%d{HH:mm:ss} %level]: %paperMinecraftFormatting{%msg}%n%xEx{full}}" /> + + + + + +- ++ + + + ++ pattern="[%d{HH:mm:ss}] [%t/%level]: %paperMinecraftFormatting{%msg}{strip}%n%xEx{full}" /> + + + diff --git a/Remapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch b/Remapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch new file mode 100644 index 0000000000..08d7212876 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tom +Date: Fri, 26 Feb 2021 16:10:53 -0600 +Subject: [PATCH] Clear SyncLoadInfo + +This patch merely adds the extra argument "clear" after /paper syncloadinfo to clear currently stored syncload info. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 6fad9329213e4e8a3ef9ce7fb568ad22484a11f3..a6b2b69a5a79fb8cea81e55018ee7f57c8820e56 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -295,6 +295,13 @@ public class PaperCommand extends Command { + sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); + return; + } ++ ++ if (args.length > 1 && args[1].equals("clear")) { ++ SyncLoadFinder.clear(); ++ sender.sendMessage(ChatColor.GRAY + "Sync load data cleared."); ++ return; ++ } ++ + File file = new File(new File(new File("."), "debug"), + "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); + file.getParentFile().mkdirs(); +diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java +index 524f33371b9de1d4dd6972fe59ffbe1804d7c5f3..0bb4aaa546939b67a5d22865190f30478a9337c1 100644 +--- a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java ++++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java +@@ -26,6 +26,10 @@ public class SyncLoadFinder { + public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); + } + ++ public static void clear() { ++ SYNC_LOADS.clear(); ++ } ++ + public static void logSyncLoad(final Level world, final int chunkX, final int chunkZ) { + if (!ENABLED) { + return; diff --git a/Remapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch b/Remapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch new file mode 100644 index 0000000000..7997af8fee --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tom +Date: Fri, 26 Feb 2021 16:24:25 -0600 +Subject: [PATCH] Expose Tracked Players + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 87c719caf796f54296ff7e412548062e02af270e..ec30f886585d407fbd122e05107ebca44895c585 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -170,7 +170,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper + private CraftEntity bukkitEntity; + +- ChunkMap.TrackedEntity tracker; // Paper ++ public ChunkMap.TrackedEntity tracker; // Paper package private -> public + public boolean collisionLoadChunks = false; // Paper + public Throwable addedToWorldStack; // Paper - entity debug + public CraftEntity getBukkitEntity() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index d2d179cdef8129653983b01d94928ba83f64f644..ec8c7499662c0a810f1337ebc0fa24d2f3ca79e7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -16,6 +16,7 @@ import java.net.InetSocketAddress; + import java.net.SocketAddress; + import java.util.ArrayList; + import java.util.Collection; ++import java.util.Collections; // Paper + import java.util.HashMap; + import java.util.HashSet; + import java.util.LinkedHashMap; +@@ -2305,6 +2306,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + // Paper end + ++ // Paper start ++ @Override ++ public Set getTrackedPlayers() { ++ if (entity.tracker == null) { ++ return Collections.emptySet(); ++ } ++ ++ Set set = new HashSet<>(entity.tracker.seenBy.size()); ++ for (ServerPlayer entityPlayer : entity.tracker.seenBy) { ++ set.add(entityPlayer.getBukkitEntity().getPlayer()); ++ } ++ return set; ++ } ++ // Paper end ++ + // Spigot start + private final Player.Spigot spigot = new Player.Spigot() + { diff --git a/Remapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch b/Remapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch new file mode 100644 index 0000000000..f305e85937 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Bjarne Koll +Date: Wed, 3 Mar 2021 12:48:48 +0100 +Subject: [PATCH] Remove streams from SensorNearest + +The behavioural nearby sensors are validated every tick on the entities +that registered the respective sensors and are therefore a good subject +to performance improvements. + +More specifically this commit replaces the Stream#filter usage with +ArrayList#removeIf as the removeIf method on an array list is heavily +optimized towards a single internal array re-allocation without any +further overhead on the removeIf call. + +The only negative of this change is the rather agressive diff these +patches introduce as the methods are basically being reimplemented +compared to the previous stream-based implementation. + +See: https://nipafx.dev/java-stream-performance/ + +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java +index 91295b8501b1e9d60bf9a7e954ea7fbce9cdea7f..0cd5a19beeb6103dec454b9071cc2e40adf2d006 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java +@@ -27,18 +27,16 @@ public class NearestItemSensor extends Sensor { + List list = world.getEntitiesOfClass(ItemEntity.class, entity.getBoundingBox().inflate(8.0D, 4.0D, 8.0D), (entityitem) -> { + return true; + }); +- +- entity.getClass(); ++ // Paper start - remove streams in favour of lists + list.sort(Comparator.comparingDouble(entity::distanceToSqr)); +- Stream stream = list.stream().filter((entityitem) -> { +- return entity.wantsToPickUp(entityitem.getItem()); +- }).filter((entityitem) -> { +- return entityitem.closerThan((Entity) entity, 9.0D); +- }); +- +- entity.getClass(); +- Optional optional = stream.filter(entity::hasLineOfSight).findFirst(); +- +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); ++ ItemEntity nearest = null; ++ for (ItemEntity entityItem : list) { ++ if (entity.wantsToPickUp(entityItem.getItem()) && entityItem.closerThan(entity, 9.0D) && entity.canSee(entityItem)) { ++ nearest = entityItem; ++ break; ++ } ++ } ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +index bf38e8b465ae0f50e34b94e0d7830dfdc1be1d59..fa827377ef0ef7cb280d1d54e156e45579899e6c 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +@@ -26,10 +26,12 @@ public class NearestLivingEntitySensor extends Sensor { + list.sort(Comparator.comparingDouble(entity::distanceToSqr)); + Brain behaviorcontroller = entity.getBrain(); + +- behaviorcontroller.setMemory(MemoryModuleType.MOBS, (Object) list); +- behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, list.stream().filter((entityliving1) -> { +- return doTick(entity, entityliving1); +- }).collect(Collectors.toList())); ++ behaviorcontroller.setMemory(MemoryModuleType.MOBS, list); // Paper - decompile error ++ // Paper start - remove streams in favour of lists ++ List visibleMobs = new java.util.ArrayList<>(list); ++ visibleMobs.removeIf(otherEntityLiving -> !Sensor.a(entity, otherEntityLiving)); ++ behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, visibleMobs); ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +index 41a9db2cc4af26baa7072b3c4cebc5357ff43301..fe7414293f144656a938de42524841592c9f40d4 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +@@ -26,22 +26,26 @@ public class PlayerSensor extends Sensor { + + @Override + protected void doTick(ServerLevel world, LivingEntity entity) { +- Stream stream = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((entityplayer) -> { +- return entity.closerThan((Entity) entityplayer, 16.0D); +- }); ++ // Paper start - remove streams in favour of lists ++ List players = new java.util.ArrayList<>(world.players()); ++ players.removeIf(player -> !EntitySelector.notSpectator().test(player) || !entity.closerThan(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator ++ players.sort(Comparator.comparingDouble(entity::distanceToSqr)); + +- entity.getClass(); +- List list = (List) stream.sorted(Comparator.comparingDouble(entity::h)).collect(Collectors.toList()); + Brain behaviorcontroller = entity.getBrain(); +- +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, (Object) list); +- List list1 = (List) list.stream().filter((entityhuman) -> { +- return doTick(entity, (LivingEntity) entityhuman); +- }).collect(Collectors.toList()); +- +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, (Object) (list1.isEmpty() ? null : (Player) list1.get(0))); +- Optional optional = list1.stream().filter(EntitySelector.ATTACK_ALLOWED).findFirst(); +- +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, optional); ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); ++ ++ Player nearest = null, nearestTargetable = null; ++ for (Player player : players) { ++ if (Sensor.a(entity, player)) { ++ if (nearest == null) nearest = player; ++ if (EntitySelector.canAITarget().test(player)) { ++ nearestTargetable = player; ++ break; // Both variables are assigned, no reason to loop further ++ } ++ } ++ } ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, nearestTargetable); ++ // Paper end + } + } diff --git a/Remapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch b/Remapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch new file mode 100644 index 0000000000..e8d0daacfc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch @@ -0,0 +1,239 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas81298 +Date: Sun, 13 Dec 2020 13:42:55 +0100 +Subject: [PATCH] do not create unnecessary copies of passenger list + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java +index a6ecb82d14ccab5d8229689a2a6cb67c579b1f71..cded79352dff0978e0d633eae9d9020b4dec1d4b 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java +@@ -15,7 +15,7 @@ public class ClientboundSetPassengersPacket implements Packet list = entity.getPassengers(); ++ List list = entity.passengers; // Paper - do not create a copy of the list + + this.passengers = new int[list.size()]; + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index f4dd30c8b3326db72d3b3068ee2291de6f15de7c..c17e827a976f509c8294df65335f12139cd36a9f 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -2312,7 +2312,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + list.add(entity); + } + +- if (!entity.getPassengers().isEmpty()) { ++ if (!entity.passengers.isEmpty()) { // Paper - do not copy list + list1.add(entity); + } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index 75e2274578c2c28de3d786372df0b4102337a2cc..e703233db7879c73378b3a06b2e89f7fcea97979 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -102,10 +102,10 @@ public class ServerEntity { + + public final void tick() { this.sendChanges(); } // Paper - OBFHELPER + public void sendChanges() { +- List list = this.entity.getPassengers(); ++ List list = this.entity.passengers; // Paper - do not copy list + + if (!list.equals(this.lastPassengers)) { +- this.lastPassengers = list; ++ this.lastPassengers = com.google.common.collect.ImmutableList.copyOf(list); // Paper - only copy list if something has changed + this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit + } + +@@ -375,7 +375,7 @@ public class ServerEntity { + } + } + +- if (!this.entity.getPassengers().isEmpty()) { ++ if (!this.entity.passengers.isEmpty()) { // Paper - do not create copy of list + consumer.accept(new ClientboundSetPassengersPacket(this.entity)); + } + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index ec30f886585d407fbd122e05107ebca44895c585..d055b362459e5b4658aa220e16118ee6174c0de4 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2233,7 +2233,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + protected boolean canAddPassenger(Entity passenger) { +- return this.getPassengers().size() < 1; ++ return this.passengers.size() < 1; // Paper - do not copy list + } + + public final float getCollisionBorderSize() { return getPickRadius(); } // Paper - OBFHELPER +@@ -2329,7 +2329,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean isVehicle() { +- return !this.getPassengers().isEmpty(); ++ return !this.passengers.isEmpty(); // Paper - do not copy list + } + + public boolean rideableUnderWater() { +@@ -3141,7 +3141,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean hasPassenger(Entity passenger) { +- Iterator iterator = this.getPassengers().iterator(); ++ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list + + Entity entity1; + +@@ -3157,7 +3157,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean hasPassenger(Class clazz) { +- Iterator iterator = this.getPassengers().iterator(); ++ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list + + Entity entity; + +@@ -3174,7 +3174,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + public Collection getIndirectPassengers() { + Set set = Sets.newHashSet(); +- Iterator iterator = this.getPassengers().iterator(); ++ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +@@ -3200,7 +3200,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + private void fillIndirectPassengers(boolean playersOnly, Set output) { + Entity entity; + +- for (Iterator iterator = this.getPassengers().iterator(); iterator.hasNext(); entity.fillIndirectPassengers(playersOnly, output)) { ++ for (Iterator iterator = this.passengers.iterator(); iterator.hasNext(); entity.fillIndirectPassengers(playersOnly, output)) { // Paper - do not copy list + entity = (Entity) iterator.next(); + if (!playersOnly || ServerPlayer.class.isAssignableFrom(entity.getClass())) { + output.add(entity); +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java +index 3d919e878908e19d598d70011c44cf980676f4f8..debf53a8bf6f062a237160a7b7e0a251a9756ef6 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java +@@ -52,7 +52,7 @@ public class RunAroundLikeCrazyGoal extends Goal { + @Override + public void tick() { + if (!this.horse.isTamed() && this.horse.getRandom().nextInt(50) == 0) { +- Entity entity = (Entity) this.horse.getPassengers().get(0); ++ Entity entity = this.horse.passengers.isEmpty() ? null : this.horse.passengers.get(0); // Paper - do not copy list, fixed array out of bounds exception as well + + if (entity == null) { + return; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.java +index e512a38ccbba93266f0234e3b2fcf7f62693039b..7a60c0b2c301e8cb768c39ad20f273a5921428cb 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Pig.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java +@@ -85,7 +85,7 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { + @Nullable + @Override + public Entity getControllingPassenger() { +- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); ++ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +index b298bcfb665b1036cd21445cec1518069eb08f06..5901e92a749af50166c517bda575d541554756f5 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +@@ -971,7 +971,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, + @Nullable + @Override + public Entity getControllingPassenger() { +- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); ++ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list + } + + @Nullable +diff --git a/src/main/java/net/minecraft/world/entity/monster/Ravager.java b/src/main/java/net/minecraft/world/entity/monster/Ravager.java +index e50d72c98f2ee3cd3349d2df9a0cdc47b733f7cd..ccc9d941b28ee090436a5958e1b48589d48d9d6f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java +@@ -134,7 +134,7 @@ public class Ravager extends Raider { + @Nullable + @Override + public Entity getControllingPassenger() { +- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); ++ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 25df3ef6b96bec39847a732394af8eccdb4d5d45..23421c4964c67a963a55ce08595c8de112a2ba6e 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -560,7 +560,7 @@ public abstract class AbstractMinecart extends Entity { + + vec3d1 = new Vec3(d8 * d4 / d6, vec3d1.y, d8 * d5 / d6); + this.setDeltaMovement(vec3d1); +- Entity entity = this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); ++ Entity entity = this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list + + if (entity instanceof Player) { + Vec3 vec3d2 = entity.getDeltaMovement(); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +index e7ac3bff190c899397d6576fabbf4966878ea7e5..37f0e359ec858eebfa15d01f23a9ce0103816c8b 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +@@ -316,7 +316,7 @@ public class Boat extends Entity { + super.tick(); + this.tickLerp(); + if (this.isControlledByLocalInstance()) { +- if (this.getPassengers().isEmpty() || !(this.getPassengers().get(0) instanceof Player)) { ++ if (this.passengers.isEmpty() || !(this.passengers.get(0) instanceof Player)) { // Paper - do not copy list + this.setPaddleState(false, false); + } + +@@ -379,7 +379,7 @@ public class Boat extends Entity { + Entity entity = (Entity) list.get(j); + + if (!entity.hasPassenger(this)) { +- if (flag && this.getPassengers().size() < 2 && !entity.isPassenger() && entity.getBbWidth() < this.getBbWidth() && entity instanceof LivingEntity && !(entity instanceof WaterAnimal) && !(entity instanceof Player)) { ++ if (flag && this.passengers.size() < 2 && !entity.isPassenger() && entity.getBbWidth() < this.getBbWidth() && entity instanceof LivingEntity && !(entity instanceof WaterAnimal) && !(entity instanceof Player)) { // Paper - do not copy passenger list + entity.startRiding(this); + } else { + this.push(entity); +@@ -726,8 +726,8 @@ public class Boat extends Entity { + float f = 0.0F; + float f1 = (float) ((this.removed ? 0.009999999776482582D : this.getPassengersRidingOffset()) + passenger.getMyRidingOffset()); + +- if (this.getPassengers().size() > 1) { +- int i = this.getPassengers().indexOf(passenger); ++ if (this.passengers.size() > 1) { // Paper - do not copy list ++ int i = this.passengers.indexOf(passenger); // Paper - do not copy list + + if (i == 0) { + f = 0.2F; +@@ -746,7 +746,7 @@ public class Boat extends Entity { + passenger.yRot += this.deltaRotation; + passenger.setYHeadRot(passenger.getYHeadRot() + this.deltaRotation); + this.clampRotation(passenger); +- if (passenger instanceof Animal && this.getPassengers().size() > 1) { ++ if (passenger instanceof Animal && this.passengers.size() > 1) { // Paper - do not copy list + int j = passenger.getId() % 2 == 0 ? 90 : 270; + + passenger.setYBodyRot(((Animal) passenger).yBodyRot + (float) j); +@@ -906,13 +906,13 @@ public class Boat extends Entity { + + @Override + protected boolean canAddPassenger(Entity passenger) { +- return this.getPassengers().size() < 2 && !this.isEyeInFluid((Tag) FluidTags.WATER); ++ return this.passengers.size() < 2 && !this.isEyeInFluid((Tag) FluidTags.WATER); // Paper - do not copy list + } + + @Nullable + @Override + public Entity getControllingPassenger() { +- List list = this.getPassengers(); ++ List list = this.passengers; // Paper - do not copy list + + return list.isEmpty() ? null : (Entity) list.get(0); + } diff --git a/Remapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch b/Remapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch new file mode 100644 index 0000000000..ec43d966cb --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheShermanTanker +Date: Thu, 1 Oct 2020 01:11:03 +0800 +Subject: [PATCH] MC-29274: Fix Wither hostility towards players + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index bbb1d0ed9e76f414dc7d73b4f7786891425f55cd..eb367b8feda8219a97a547c3ef6ab82d278d2f25 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -805,4 +805,10 @@ public class PaperWorldConfig { + private void setUpdatePathfindingOnBlockUpdate() { + updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); + } ++ ++ public boolean fixWitherTargetingBug = false; ++ private void witherSettings() { ++ fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); ++ log("Withers properly target players: " + fixWitherTargetingBug); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +index fd91c80cd6337b5fa41d6060ecdb44b8fa68a16a..b364b442d4cb1f3351850140b85c62c30c888bed 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -102,6 +102,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); + this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); ++ if(this.level.paperConfig.fixWitherTargetingBug) this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 0, false, false, null)); // Paper - Fix MC-29274 + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Mob.class, 0, false, false, WitherBoss.LIVING_ENTITY_SELECTOR)); + } + diff --git a/Remapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch b/Remapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch new file mode 100644 index 0000000000..cdc493b6d3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sun, 1 Nov 2020 16:43:11 +0100 +Subject: [PATCH] Throw proper exception on empty JsonList file + + +diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java +index e2982a8ac5448110378bc92247952332bdffe12c..71de59cadcbd214b9e3a91a6051f918d9b421b16 100644 +--- a/src/main/java/net/minecraft/server/players/StoredUserList.java ++++ b/src/main/java/net/minecraft/server/players/StoredUserList.java +@@ -189,6 +189,7 @@ public abstract class StoredUserList> { + + try { + JsonArray jsonarray = (JsonArray) StoredUserList.GSON.fromJson(bufferedreader, JsonArray.class); ++ com.google.common.base.Preconditions.checkState(jsonarray != null, "The file \"" + this.file.getName() + "\" is either empty or corrupt"); // Paper + + this.map.clear(); + Iterator iterator = jsonarray.iterator(); diff --git a/Remapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch b/Remapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch new file mode 100644 index 0000000000..46ebed8c68 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch @@ -0,0 +1,400 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com> +Date: Sat, 3 Oct 2020 08:27:40 +0200 +Subject: [PATCH] Improve ServerGUI + +- Added logo to server frame +- Show tps in the server stats + +diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +index c0923ec75ecced2e0a1c0d3ec2c046d69af3e9a9..a3e17c1cb54938908d72d3e86e43f4655f1db194 100644 +--- a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java ++++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +@@ -57,9 +57,18 @@ public class RAMDetails extends JList { + public void update() { + GraphData data = RAMGraph.DATA.peekLast(); + Vector vector = new Vector<>(); ++ ++ double[] tps = new double[] {server.tps1.getAverage(), server.tps5.getAverage(), server.tps15.getAverage()}; ++ String[] tpsAvg = new String[tps.length]; ++ ++ for ( int g = 0; g < tps.length; g++) { ++ tpsAvg[g] = format( tps[g] ); ++ } + vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); + vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); + vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); ++ vector.add("TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg)); ++ + setListData(vector); + } + +@@ -70,4 +79,9 @@ public class RAMDetails extends JList { + } + return ((double) total / (double) tickTimes.length) * 1.0E-6D; + } ++ ++ private static String format(double tps) ++ { ++ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); ++ } + } +diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java +index 2567c588a1dcf732800e6cf87352b020c7bb84d6..ad912fae191777256dd88f6c863ec92f8b6a9c13 100644 +--- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java ++++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java +@@ -31,6 +31,11 @@ import net.minecraft.DefaultUncaughtExceptionHandler; + import net.minecraft.server.dedicated.DedicatedServer; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++// Paper start ++import java.io.IOException; ++import java.util.Objects; ++import javax.imageio.ImageIO; ++// Paper end + + public class MinecraftServerGui extends JComponent { + +@@ -56,6 +61,15 @@ public class MinecraftServerGui extends JComponent { + jframe.pack(); + jframe.setLocationRelativeTo((Component) null); + jframe.setVisible(true); ++ jframe.setName("Minecraft server"); // Paper ++ ++ // Paper start - Add logo as frame image ++ try { ++ jframe.setIconImage(ImageIO.read(Objects.requireNonNull(MinecraftServerGui.class.getClassLoader().getResourceAsStream("logo.png")))); ++ } catch (IOException ignore) { ++ } ++ // Paper end ++ + jframe.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent windowevent) { + if (!servergui.isClosing.getAndSet(true)) { +diff --git a/src/main/java/net/minecraft/server/gui/StatsComponent.java b/src/main/java/net/minecraft/server/gui/StatsComponent.java +index 09414d04208a843f8d337569b53f61b34e64ed92..d2583c762fe655dd1d7bed1061e41cd08ac0c092 100644 +--- a/src/main/java/net/minecraft/server/gui/StatsComponent.java ++++ b/src/main/java/net/minecraft/server/gui/StatsComponent.java +@@ -18,7 +18,7 @@ public class StatsComponent extends JComponent { + }); + private final int[] values = new int[256]; + private int vp; +- private final String[] msgs = new String[11]; ++ private final String[] msgs = new String[12]; public String[] getStatEntries() { return this.msgs; } // Paper - change size, OBFHELPER + private final MinecraftServer server; + private final Timer timer; + +@@ -37,8 +37,18 @@ public class StatsComponent extends JComponent { + private void tick() { + long i = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + ++ // Paper start - Add tps entry ++ double[] tps = org.bukkit.Bukkit.getTPS(); ++ String[] tpsAvg = new String[tps.length]; ++ ++ for ( int g = 0; g < tps.length; g++) { ++ tpsAvg[g] = format( tps[g] ); ++ } + this.msgs[0] = "Memory use: " + i / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)"; + this.msgs[1] = "Avg tick: " + StatsComponent.DECIMAL_FORMAT.format(this.getAverage(this.server.tickTimes) * 1.0E-6D) + " ms"; ++ getStatEntries()[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg); ++ // Paper end ++ + this.values[this.vp++ & 255] = (int) (i * 100L / Runtime.getRuntime().maxMemory()); + this.repaint(); + } +@@ -85,4 +95,10 @@ public class StatsComponent extends JComponent { + public void close() { + this.timer.stop(); + } ++ ++ // Paper - start Add tps entry ++ private static String format(double tps) { ++ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise ++ } ++ // Paper end + } +diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png +new file mode 100644 +index 0000000000000000000000000000000000000000..a7d785f60c884ee4ee487cc364402d66c3dc2ecc +GIT binary patch +literal 14310 +zcmXY21yoy2uugDycPmm{N^yd_Q`}vP7YOd|PH`>8wLo!q*HRn`6f5rV?*HD)IX5{c +zxpy-=`|Zxo_svGBD$Agwkf4A-AaprdNp;|J21vifLD%hMrT$lZeEex|7Xe0mqFAZArC{!qp)zJmbab@utqA`6 +z61Z~|e!k$IbXNT?PvGuuzT7G514$8e!}lsR>%nURMm+~pde``@(!O=ISt0%B93;Ez +za-qRi4n0Q>zQ2#2^_y08QOl3jT*!Ir5@<8VrFx(6f9sP|H8ttjftN;wrX>jP4BcG1;MfU5x^L`zc09u!bDBt#+ll=7@ +zB;}A$BKgu}V?#qfHvm`~pt%wG2y{MOc%B!8I`p|pc +zO#?sq!Zd&j8UPmvY4RQnfo>!6{a}GFV!}g@qu<3Wu$07X(O`vikNW$~q!ngF23Ls2 +z53p8js<-B_Qd?xX6rtq43Mdz(jOg2QXx#Wng_9^1^^~KqFNq{Kvb@Ap9}bf&xFA-C +z5+#cQ`#v$A=kd0O=agATcleBaxXf_(dnqbQz|cL9R&&Ni1omTs+6~YApmk)MCghxj +z1}mq&IU>1nEiF=q=PI`%jQbyRd=hVI83Sm{E-4uTc#w;NNwEW)C(C`xvWzY_%`_MmO +zD&g-sEaE)}6(&g)y-N&rNy;5@+{M`}!{60Y8wMgF5;HmO#B~hG`W$;7xLG*yF((rq +zxP6I#r#o`B3FppK{v(q1!C+YLFSfySDcHyoW!}EfzuCB1B|C5+oP}dtocnwkcNy1EZ6#5JX4=ePl&cu~0tMnt&79+I4%PaK>VqFx;r!QdNmnxlEqdU-QR%Nmu{aWP +zJxwXvt5fFTCOVgB)Zq +z%H0U=9q7Y0lu&1kc4zYT3*lHA@XJfoK>3WFM&WWf2u6^+wCm8##D$x@Gkw+t^HoO( +z4pxDRqg;$5S=t^k22H5^V3V0Qfy%Ogl8I%LD$52=7)J>Ki9Ej1HyEi_ujELlz8$-+?cdD1Zxi02kW0 +zaY=caFq4~s^R?zxcc3Z0X|az}Aww<{P$>6rk+5Di5J7$kWor0{Q&>+DWSBH^Gf`SP +zT{4}IOFh-hB7xwBdewq%de)q6QvxorV(()2>@j8i!kj)=^hN +zl_N{$9xTHHA;V&Zx#tX&1pOO;v^NiOP#_UK@J;;lp+OOhOOO2mlMdxM;Qv-mWG+^vzox|8t`w| +z=gPlM3)y6G*hfV1WwuMe>bO-vP9g`h5BqgO9x{ROBD;aPl>XDmvt(3PUxt|4RFRpK +z5OEtRz{(Oa_W_!Z4XHf#h;Z-~71XM7wlF*L!-#h_Uy2tGuy-rAZ)4{qE~feNkp}qf +zgvBtLkFPI~I7%C=OHZfPZz$j>L9)rb;l +z@J^dxncy52;wmHg=wC3|Xn6jPYCR7xc}~D0wNjoYxmoRh_zh=6@8coM1UQIa_z*1)cZPw4v40qoZQp-uy#DLv=oP +zX9b3vzFA2r8}|_AO8W1(OMG__0{1AUD&Z%&7-(>s+Z-X6Sv}G5QguIbZ3mYa--?09 +z;wNw?n=yAag4%m#w$$-YZ{(ZJUcwHfzu&!gykNjG)e}!=q8xy2_KS=ULsQwv45NK! +zVqqD8#S{vRjg4(Q6HM_F&tihNIQns<%DVjE$cv33ET>Dvc^#{z&#u&&9RgXO?ZLuebczKv#;! +zCS|2lIa37Bp#3RWj0$V3=I2>o40{(J^LD|EUH?!2;Z&HS*>7*V%{v1)wHaUP85mcX +z%q!K}Ntr*IzJD%++btJ;VQO*OjJL1t{GvR3cy@OC-~pe^bV?N`z0QKCr?Tom)4u%A +z3mi2k&eIgh0^rGI#Di+&3lrsy-r+}zwBkDQtswtPbkj!Y^l`{f!# +zLseC0M;DiifDa!({-G4{W$Wxsgv*(NX%HMyXhArVwY105dUHg?+=@6Sy8n@slS76x +zU7%PI8ToKm#qahfR;7kn#|t@9y(0EkooWBDqA1(mpO)>BBz))giBi8xVHlj#dR9U8 +zRo%`iBdlj8%_tRn^qa%T>{nsLLwTNld&WHLyfbPzv2W62m6q=Nsdxnk +z#{P==5!Lidx3bcr_qlUl%BX!xjywA?jv>FU^mJDa0zQT9Kw8RRHq>7B +zb~DXw0(oqBrOQunsm2ghWV2i1VmN{F?)U;0%*j{FEUxazAJ3)KSWomuhklkDi?5h*MTLDS5ma_Nk1sNZYzZ#$maGRyiXBzjG@(G__fuyBl(^A>s&{jF+J%5| +zv#7nD1XK806#_U_4#N2ANAxznk%;U$Y$z#{K*O07mADqx6LjACqwP<`HFV#C6Q*wx +z8JVP_qGF}V7B?^8)f*2F5AON7v$L~Kr?2}oPai_kG!_6MI(U`LS~+Mo*CSyrw>pPE +zllqxy +z^&rnDn4XA@AUY7~`1lwTCrm8KlVRqX&!kZFH&;i9@=R}UDxNSh*)Iq2U+#9}@ag1t +z%KUOEw0DXT)>hQoLTprY^z=BC=8NAyi3pZWT7A`?;rI<3%65Nqb93%pJ=!+dNtB>W +z7f3O-e-S7ZBgBntcyt~wOG_p$AU2zlGH8=%TEm+z8kLYReEMTkIo#2YiA=iKWrH); +zS%uT3xAyyY=!U)0Evpgx{{38MPR2nN<3913M<0O#YCO=TSt^4IzV3^D%2zC>t_OO} +z_h~AVOk+IIi$Ov;-g93a4j@WaekCC#HFm2_Vu9s)8-GbYtr{LgrxnSIN^PW9)!jYX +z?%-yssA~&R3F)C)wj5i|@!atCx?Qy%P1QEGSZm;iUNai`-F(8a%y+_a>CMzx$XEKx +z>sW|JbN36s+Y{4SZsrspH%UH=+Q6J`c&_-JLGL&5|$XUA1vFOC+rgoc&xT{dFT&pMaEBKwyD;plX0>2nla;jTlQ{!fn2M=Ak*=K*g% +zBm0-$ly1~}CT-5gv){jex9)7&b8u!a+vYHXU>=NF2>g3+_rN{(LUMGwRWKk49sS$v +zazyX8zZ1hwZ|U*5{fK@i@hRl*U%Q2cg+!iIfb)6W%S5F{91qinEZE%~4Gl>rBw9S< +zMP5$exl1jESyt}d~jo?hf`z^32b!}UGtJH+w9(0UrI#~Ei*ii&6z(AVE?(}k_A +zE9Z@mj7HF-ch46I0ipe3gapRj{=zk_J1E^b_JwdrhKi4ytBuwP)m>e$@9v`A{1N{h +zwUN6H=_W+h(a?rGaQ%%LP5C4)XiZ*`1uUwgqWvk`LyDD!Ps#Q5oI($KDJ%8n5kBi- +zghsLx`~mf<>WT)6-cJBbp|htk1NfkZ@e#B4@l?UH7!MDMpO?1NETGk_Eg{z!N3!D< +zWg8gtgS%b(0Bg7dw9u35xq)1vNdnM8iu7Eje*u?#sZ~%^q*HDaZC?5z4ZzhSA%ndS +z4&$M&7(|(9nWY%QShCnuN0 +z`n9&UeypypUgx;R+x;XM#8uDM{p`9~j<49)^dotHJVO*A@HL&g7F={FP#trj@{dzm +zeQUiqRWJ&pkKkA1O-|vOf8O1UQ$$0lIExffio|}F@ROV#MXcPH$ +z?$$kxAF@B#KT}u;R@SVyIO>1sw1!i?C(_013w9@?8$bKaLQi34zC$g*^}F&(%NEO6 +zQzD-^6}HQMnGJ{h$J*)HjSxjblWegsW&rLC8Ov_r_20jLjUS$Ptnm|p9fK%r0j+4; +z57^mjL&lISh8>DC;eB$B69$h4XxE3qU4T&zUpDeV@4g>or%D-x@qhie>6mqD959ck74(h?S0BA0}YQ18d?hr6}%}y{%ZNJ^-(?=Op~; +z#2-UNh)jH9>RXmvPJ(Y!8(uhyW|sFpyvv)AaNeljHj^Fx+RC +z!`@c->W1C^FUKHmG2w_atkdsMnzY+l!CV8havQ8-Gu)<8t{#V*2Pwp4h?ayXsi5Z> +zo!guta>TA~iv#iJpQkN>#)QF%As@2WgU&V_Y^qm#E*O}M_ijJfFWq}ts)-l4>D)kCqJJ@MG2$69ph0jzwI8ry1u8D@CyinC$oT?7S*Z}Eg +zYs}PWLqr4u@)w}#!{cMx;KxO6W2H6~3k$laJjAt+C{0mmCRnfs=OJYbh}HMh&e`#> +zj;jrpjqKCh41OK{FOS`@_sPP$iCm46G^EMNk8(l-1f>!gEV+4vMVRZ#8infUenP+k +zL^tBOHF^=)k&U-Tw{gfijqQ&^ +z-RHHII5yp}2|o8pTsf6x7$teW9Em!~iy2DN?D@|U)g%I6VG%JBO$|~;c~1Q^3|x`1 +z6HRbq1#~Ke)wWpALcc&@P;m+*sGavR0{aOx3=IwUE3YPWAwV45pzD$~02inxi7(6X +z$zk683M=_r#M*+6fQ)&FK0y|lm7JLwS)K=t&ZJk!U_-y%_o@fhr{s37MUEQOF*M)3 +zB$;4>Zx;Xk*(hwFjb>1iJ1f*D#nyWL{=>{2|9*^vCNN!%bF8Oe<`xz#s;jFz?;I}4M3lL;!fy_;J-E96Of+;sG%K=fZdR)99pJ}fM( +zq%(s8UrsEL{NrdF`!#RY+VjFyPpE_vtqPMM!MQ+QnE)+_g9Z^{4^;k&Sa^=w*yuxB_*Z!U%!3{_9Qr)Jfz4IeS#io4oj_Kqhq`HCUub|Ke!v$1-$v=kc+O#rlCej?%dhY +zxxKUTsFPG1nfoFp3%7@gh9S?vM0N27#*fpJyaX;Vy{!pt*}!9_mX9uC#J5RyjknW2Dm3dCvZYU +zSW?0kvI9!o2un}*%`AYhr^CQT1aZF=-Nt^atn@Kt%b2!hT(pK!|MclbBv3-<+6{>_ +z8toMfWc9rpOk(8|KW>Z-k>Fr(xc_+q9ocf`8!_n}XYUrW?Ax|*_|=5m*4F0V+46wJ +z1IGS^Z5t=0Zj86J2MfJc +zUq#WKCfhoB<;P2&&`*_G4^_0uqDR20m!>T8ay_rxSzA&9_v5##g6tzXTkx+KRfz32 +z9vvpp?+YxHTxDthCBu7)&Q052y4s9*$M4_2w-OdPyK?F-EBoUuSsIk@@(!gA*A_!0 +z2eu1y;-Q$Ut(M>8FCOtw?vZR-%*ly^x)<95vK@P0tJoZws@+M*NGhg_NU`!}DZnWBHQz%*@6))$BWN;EM0xAF+B4Mph#S??J?K+&viwPmes*n^HGDL9iBf +zCk|mDu46wwughN!isu&G((DO>Ws`(VLY?^#w=RONxUgFGby--Y=5NJ|(>qXOS`;lZhmXyMEyBdVM@jJh71E-})~`?t4w8^Kwy) +z<+KACjs!F^TS-;FT24_iWF+=l(nR}j7U#;Vd +z)IT3=b&}A}1PUKFa6DKfgHkJci!~7u?a%k9h7Rri^{y`|;;xNDoQbV}+oJ=LdApL}|77o@C= +z;~aed)XpbrMtt1x3gHPWxbliQH4nKBCew{9 +z*-_PTyn~`1VrwKcc4ZrhI^!MsZ{D0O0%O2!SHHi^Dfyr9*x*DGFKwc()b;q6nM*M7 +zvA$x_?$BMJJHN5HIn9Ps{_7-sn79~BZegaa5V;s(BA<5BnU?^AeJHXtd)cIj_UCjA +zW|N@MjV~vrJz{sE0Dzv}tXxUDQAXm)1(kX7C_ZVFX%!TlZ850i(P1A0BxaJu)#LcH +zoxMFRzxoxw$bM=B6gpuMD#vcsa^00?%=D+T9-dQqV*=zD|)W!3BLun2&^n)~$ +z2_^{i9~sGXOAsF_S=k&4mWJ@`mD+G%MiPTlhuomboeFNwHb(< +zVpVR!mwf;JmpO3JL|B%L-!;@7TG}+`HZA;-{VIlQGY|T=f|!9!S=!c?sq5|KeEQ*~ +zm!1xeZcJPbSsfjU9e>K|=Ni<+YgrIG!|5@|Z>4bjx+`1j^O-{QK8XARf +zUG$nLRiTEtt;)9F30rvw>nj)@vCF{$d7>o2n>}~Y2^^C79l@s`uXRZOcuy>^%2@t- +zRGv={pKlDXFUgvG_^DWGR==il1rIzn{$p4r(FVOQxZi!_*Ksfl2hR{Aj>01RbFAM= +zpr0wzMwlOwlkt4|JLK)$>VL+{4nv>^`yMa)T;(9f*B(9;{T+)_=M4dN>M&&hS-#(G +z)-sW(WxVkHR)`x#g)25Lu7qnN;~Q-bvKDZ=;^fyLy@okDpvt&ZU{!U)WVtmnp +zAN-CzM{jPFWep9NAKDDq@=kynkGi_GQ@Z2y_Wn)xc_q3-&+9`qdGy_{PF-2c^$)%x +zd0sonEJhtG*2|P*Q-f_3`Akk96HzBz2 +z!5tnJaCcA2hGQrSw*{F)epvfYX?7toP=O0dN +zizY2w`>O@4Vqff!dBhQ^><#TjMP}loM9ProiD-Og@$V=*zQ|Avg0D!+96lr^u(1fl +z3J52PHoJYDdvdiIW?q?JIC*r?88VruLx#bp0lys39v$(c6uC*j}2IFFh +zViOX|K+DH18cd9%Rgjs$*sXuoW<>p^Fv-7CV|zpgTUnj812pyyX-nhA4TZ^UyYY9; +z?}BOarTT1q;0xSTjV_DPWE11?Y2+wSA*ybzebDoy8JwhznKa6SvYxE$WswX7Z6pG$ +zsA2GgHFFL3^zA@XTYK{a+6$Q8di%@1-|q9U15y+~R-L7Kwx8*xr(FP{g*JDPa`e((jSl#~?Rx=3ne(nLfeP9k0grubJK +zU4euzZqt~$Cl%k^{-!e6YQZi|D3#+MUS}VsYZ)0S>y@)kyqRI?A_esvAu-{`1Uq@! +zC+b`wnMK&<_mitl+k@e*$*{&S>vayX*>D>Q5sw2FZ?l(8ff%(8lo<^mBMrwQXOXe+ +z*7sZdWzBTIwZO$y^F)qZL1XbOMY<@M_a56y{({Vg@YN<_y}toq41V%~w=+4ZQvg)X +zVw~l$z-sId^nKU%dlk7W(mG}eS&KV2BdYqNJnX-p=YrG&&`_m0fzA_|iKD${5?oL* +zdS$heR@%Q+(3!!T&k;tIN|v2j=UI))rgkvyC7MTTrKP3g>Fma@_R0`GE5(tL%sS$7 +zG41ag%(Y(xZ5cjlk=R~(3XC+$25r*Fo=G5OhGgR}i!nDoG?^sult?Eo*x$x6CH-3L@LtZ0dfq!Bbbw-S}RwlN%lpH8c=4l2qH +z1wRszHSPh~=esnWvXD8B{D4<}?}6cA+@Ob1760Is6`g!zl@WL(L&={LA}SxAt0>Tw +z%b7i^&yNKM;(vGcNwuxAK{g|S3Y1&pH_6U1G +z3M4zx5FU=O;=l_?VzQ-~bx~xN1axPgYI0am3d25BjYmfSTX7Q}==Vcryl6@Se0(Jv +zxKW_o%H`jdnC7QXlkFbCsACHN1Dx=0gf<~@PW-&<=`1Hd)@#ypH7%OpalDj-P=ts+3^~yWs~TV}BD20HjkW6zc1L +z0#HzMkn3JV%7N-18_@tgE82*YnmEzxirriDSx#_|<|q1vL{k}7>^mRzO(ueTSN2~H +zG}kxp)Qn!&)><3|e>62+GXSpQKcemfqU!&BHZ5Ca;DT<63bBM&uV1BDS?MM$M;x8w>gShAPMxJM^BbMZn}Unm{OC9^4x3%% +zlmX8!km-u$N4fQXQ>jRe`7)3+RFGjhz +z18zf(Fo2<>YV^7LJO^UTZ2Ivd#mpN}o?7pBV&q=f%ID>haV7M8R3jsF*@a%iwIy>| +zsZ!-y{!%&j7`B?W8TcF4NH-RHH1xZ{;7BsA<#APu!;cND)te)FhoXz$BIU}2&^7WP +zT}TX>ZO58$VNPuh6JV7~s(W$vAj`^%AtUamex3YdVl3~4+pqk?G)qUibNMrj0*M25 +zY>5Ac|Dnv6xBQmV#$3JA?&HTN(lYl~J}@$l{*TY^kORrCB)3dDO}^^v!dcLf^CHty +zanjllIQeSLmpuG+h&ae`r*v!C*0A&W^a&q>93?BAXzG7n +z2*3TGPIcN`-_hY9&oaiv#fiv~>}7`T`4=pInEqWX*3e8+yPm^9h-tr&ts55$l+388 +zW)~F}2JH!}VLbQ>?6~H@&k`MnSsTeVj0TRVP4jGbP*!!CwM6`Z11c)yI2w$+R0zxo +zT|obYS1&&`{>>Z9(jnVU&=yI*%PGe*f78ie*_9oap?sd7fx7{r^WT>=XHF +zl`f{=UJEn2?tRw`Fem?eRE6#*nOes(ebRcmaK3~a3{a3EyE1zXSF0p7I_iDJ&%;3V +zU;AS}e?*mH#Yh2P9E3QBigIqu2iXf=@t)2+I~f*_E^JtEP1@IR{CBfTj%T}E3e#n% +zUa{@vU?D$l4DEANwkkK@ruP4ta)E*e^KLGg%$PizyPmHvKNMWtuJQ6sPXY=(1m#>W +z7V?9E!Vj}>a|KfQx5ESpH+q6$@gAp-P#~lbz`aj1_?xinN>3o8b2-Z3w>UZ3QZ}W0 +zWg-!>p>AADDcU^4;0*L4UFgB0QLlXd^y1E&4>txV!T|!`RwjZGl`;-4ZgFf>luHIy +zZ8d8Rh{I3r!g-ht6mAZxMB6VxRqnA0UY`h|mJZy2 +z17BazT$jMKFL3J6Ue_HL1^)4s%$Jj~Qx~1HG#tS@kwL(KP_ZI3dWz0SH(sqj#-*TNGsIWqPj>cj?!GyWvfdEiNOu4$>MIqL=F&Cc0{g*~L5 +zA1wt)=_zMFUkCT5$l!G{1-Y9QtGQ#qm5E(3fYPms_EP*sSVI)bfXN|uNO`BqVuCvd +zv)z8IGRgtM1<_trndVhQ^xA)wn~*W~#d*X@E=W)jcQWI8+?kdzHe;DZ`%+JE%gE}m +z6H=FO8rJxM{N90S=Gi!Mel)TyanxPa;E}C?hJl@e9UWad->;S|v;axgFjrY$z3(rV{MiJ}3M)t;Q?P5wZy0e3G{dcDO7n}3slDXLMrB$;#*W@Qv)D$=?Xs$F(8eTcyGIQ~IWgD%Gn&E>F9y#o>cR-7spE;Rur<_E~Pu)e0I +z#&y1|@8D~8c55<|KMf;&x;hg!A%VOZ38_+uk`jH4#=b9M&xcpxV-7cMN{jXVRnKSe +zlKJJ%=VBV{$DNeI1QkiA;DfdVT?$;O#22z6v6bTK9)fjrfIh!Hq__l~KzuNqT{&kA +zKs@YV6^1ZLGjTgR%(=NHS-DvWnnP)NM#qbHINqmQdCE5??co$3nuikqgm=s7*#Kd*+j_weKrZjMeLeHEoiJm>zuDRU` +zh~ggr^knneWU!Nn}AQt=0Id6Hk; +z4bJqse|V$H`stT?NS0yreYvaZ9YF!fw+N}{3#yXRU!C7?exl35BDC%+!jDMGT^DN# +zN9FGd#5t#;$h}5UgQ?q-Gr15>C6=nLUszle9<+_!!oi_m@_L^-R>_Qty7_g|C%m|5 +z-7^5X5V_ARi?h9_LW%2vByD3X_IvUktqBv{%SYXO1&;e&O#Ll_cfC`Wv1u+l_#RI< +zQ5Kly0;P`%TXaQN(heOg~>V&L{d+ZDA%eq-UKo#1)$rkjSm=nzAE2r +z5--RyKhxfXoGVU3^ab{5XGlyL1+26foG)4HZvN +zG@&I3h0fnK5lIjcrg*XxPy1(gK3_TN`&VYnxP;C|j$~0rT$0f|*#=OzM^NbE-1T5D +z%Csnt)n!sx3N#b(8G&+G3W~Q_B#StA6jZZ=p#wuu`DrAMXm{T@#S;ku4Dme@{Njmk +zCtrh3z6O>o)~o{&Htx+6kn*)$NNBH-biu^aYtWUq +z(G>4rCEKr#tO>!x8A@%W@6g)Xs%2Hq!y#Mbb@9R2@GDWi&!{jhZvzQ1D9nMuPoOS+ +z+cj{9nx5X{jJOIavbFf)Kz5Jnbe5Bu#(XE-z$j&iaP%c9W59OoT0~|N#D*(N2kz={ +zs(|)nH!_+_g1)#ZH2xk>ZTG#6WN#qa3BxZM{NWxq`*#$H255k6Ky?hw*hSA6`c_fl +zT@Ua%E5Ez3;~`kQFmrC#$Nlvc_Uy3#yzhd-6UYuuIwgIBZZC-`dwOBJbfurL(FfhH +z{YkjE+9OrOveY`{t{sGw&51YO1@{iO4)Ki=!Z5#q=m_Hi)_j0`>?;t2j);vv%BUif +z;wpTZdLQLsGvZ()DCdxYudn^Pt;BZ}Rin$4F8h{R`HxT2z`uc&aMXIQOvwgA5%{&) +zFW52MiN!$!EXgx}Px~e1!EMp;#&kY65oDho95j~!qD%YJr`+aK4jCJ4UJ^;q>w@Lf +zvDfg|M`S^@DGxu+7aR3Cx#;%?advj&1~L-m +zJqCP9&TW3migV*`Z$#)Qa>3>Jf)g9D6Ki28P@iX(uso)hic8Dp1F< +zeF;(n8Po8A*~^T{De(J)Z2nqLl@Vv3yoSlGwq0aeOg4ymI(KIkTeur-=J-yp9z?qe)it6gq-wl@I +z0D-_I{|T<5kwD9uH3yf1GWXp5*8eOgJf*q0IRoK|+r{}Fug&0WpNDKMTC@(Xc)9K8 +zy`lByMn!1fnY)1KYP(0Je1)c~WilUuh<&Q8^OE?L9Q^xK*Y@M$`6D6TDCZ^@l8{|} +zxmmNw)mng$hYBii+&ZqedxWT0dnV#LG4zC%+kzcK+-??vEHT>Q-T8zu|s_1IbA#OV)^+1pg1OmmZn` + +literal 0 +HcmV?d00001 + diff --git a/Remapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/Remapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch new file mode 100644 index 0000000000..1099f41d55 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Tue, 2 Feb 2021 09:17:59 +0100 +Subject: [PATCH] stop firing pressure plate EntityInteractEvent for ignored + entities + + +diff --git a/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java b/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java +index f12bf33aa8cc8043052aa1048087f61d9a6d4d52..ae5b052b80665bfba126f5ca5dcd78608cb27d48 100644 +--- a/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java +@@ -81,6 +81,7 @@ public class PressurePlateBlock extends BasePressurePlateBlock { + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); ++ if (entity.isIgnoringBlockTriggers()) continue; // Paper - don't call event for ignored entities + + // CraftBukkit start - Call interact event when turning on a pressure plate + if (this.getSignalForState(world.getBlockState(pos)) == 0) { diff --git a/Remapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch b/Remapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch new file mode 100644 index 0000000000..950227fe76 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 4 Jan 2021 19:49:15 -0800 +Subject: [PATCH] fix converting txt to json file + + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java +index 603b4f841bcc276997d130f1545c4cf550dcac2d..2eafb7e27d06a975cee48cc18c7596d610483d16 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java +@@ -18,6 +18,11 @@ public class DedicatedPlayerList extends PlayerList { + + this.setViewDistance(dedicatedserverproperties.viewDistance); + super.setUsingWhiteList((Boolean) dedicatedserverproperties.whiteList.get()); ++ // Paper start - moved from constructor ++ } ++ @Override ++ public void loadAndSaveFiles() { ++ // Paper end + this.loadUserBanList(); + this.saveUserBanList(); + this.loadIpBanList(); +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 95f9863bbccaa23d08c409792314df4f2397a317..c2947313cc0eda3247fb4b20ddd1d0b86c37c50a 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -195,6 +195,12 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); + org.spigotmc.SpigotConfig.registerCommands(); + // Spigot end ++ // Paper start - moved up to right after PlayerList creation but before file load/save ++ if (this.convertOldUsers()) { ++ this.getProfileCache().save(false); // Paper ++ } ++ this.getPlayerList().loadAndSaveFiles(); // Must be after convertNames ++ // Paper end + // Paper start + try { + com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); +@@ -257,10 +263,6 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + DedicatedServer.LOGGER.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file."); + } + +- if (this.convertOldUsers()) { +- this.getProfileCache().b(false); // Paper +- } +- + if (!OldUsersConverter.serverReadyAfterUserconversion(this)) { + return false; + } else { +diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java +index 941b7e356c377fd8ad4e27409cd74c0046878396..f23ca6bebf2c0b7e02dc6aa51e384cee4e3d12c3 100644 +--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java ++++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +@@ -243,6 +243,7 @@ public class GameProfileCache { + return arraylist; + } + ++ public void save(boolean asyncSave) { b(asyncSave); } // Paper - OBFHELPER + public void b(boolean asyncSave) { // Paper + JsonArray jsonarray = new JsonArray(); + DateFormat dateformat = createDateFormat(); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index c962b6fc0c65dc5e2ea636220727bca63bf4b740..dd121ec8f779b3786eeb7fe85519cf9e472f5adf 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -171,6 +171,7 @@ public abstract class PlayerList { + this.maxPlayers = maxPlayers; + this.playerIo = saveHandler; + } ++ abstract public void loadAndSaveFiles(); // Paper - moved from DedicatedPlayerList constructor + + public void placeNewPlayer(Connection connection, ServerPlayer player) { + ServerPlayer prev = pendingPlayers.put(player.getUUID(), player);// Paper diff --git a/Remapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch b/Remapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch new file mode 100644 index 0000000000..33286aca0e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch @@ -0,0 +1,122 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 4 Jan 2021 22:40:34 -0800 +Subject: [PATCH] Add worldborder events + + +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index aaa6251838483de5c46913534413151b5cb1d3fe..4ad686f4fcd3a23c4230faa03946db1f338bc904 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -14,6 +14,9 @@ import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import io.papermc.paper.event.world.border.WorldBorderBoundsChangeFinishEvent; // Paper ++import io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent; // Paper ++import io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent; // Paper + + public class WorldBorder { + +@@ -102,15 +105,19 @@ public class WorldBorder { + } + + public void setCenter(double x, double z) { +- this.centerX = x; +- this.centerZ = z; ++ // Paper start ++ WorldBorderCenterChangeEvent event = new WorldBorderCenterChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), new org.bukkit.Location(world.getWorld(), this.getCenterX(), 0, this.getCenterZ()), new org.bukkit.Location(world.getWorld(), x, 0, z)); ++ if (!event.callEvent()) return; ++ this.centerX = event.getNewCenter().getX(); ++ this.centerZ = event.getNewCenter().getZ(); ++ // Paper end + this.extent.onCenterChange(); + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { + BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- iworldborderlistener.onBorderCenterSet(this, x, z); ++ iworldborderlistener.onBorderCenterSet(this, event.getNewCenter().getX(), event.getNewCenter().getZ()); // Paper + } + + } +@@ -128,25 +135,43 @@ public class WorldBorder { + } + + public void setSize(double size) { +- this.extent = new WorldBorder.StaticBorderExtent(size); ++ // Paper start ++ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE, getSize(), size, 0); ++ if (!event.callEvent()) return; ++ if (event.getType() == WorldBorderBoundsChangeEvent.Type.STARTED_MOVE && event.getDuration() > 0) { // If changed to a timed transition ++ lerpSizeBetween(event.getOldSize(), event.getNewSize(), event.getDuration()); ++ return; ++ } ++ this.extent = new WorldBorder.StaticBorderExtent(event.getNewSize()); ++ // Paper end + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { + BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- iworldborderlistener.onBorderSizeSet(this, size); ++ iworldborderlistener.onBorderSizeSet(this, event.getNewSize()); // Paper + } + + } + + public void lerpSizeBetween(double fromSize, double toSize, long time) { +- this.extent = (WorldBorder.BorderExtent) (fromSize == toSize ? new WorldBorder.StaticBorderExtent(toSize) : new WorldBorder.MovingBorderExtent(fromSize, toSize, time)); ++ // Paper start ++ WorldBorderBoundsChangeEvent.Type type; ++ if (fromSize == toSize) { // new size = old size ++ type = WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE; // Use INSTANT_MOVE because below it creates a Static border if they are equal. ++ } else { ++ type = WorldBorderBoundsChangeEvent.Type.STARTED_MOVE; ++ } ++ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), type, fromSize, toSize, time); ++ if (!event.callEvent()) return; ++ this.extent = (WorldBorder.BorderExtent) (fromSize == event.getNewSize() ? new WorldBorder.StaticBorderExtent(event.getNewSize()) : new WorldBorder.MovingBorderExtent(fromSize, event.getNewSize(), event.getDuration())); ++ // Paper end + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { + BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- iworldborderlistener.onBorderSizeLerping(this, fromSize, toSize, time); ++ iworldborderlistener.onBorderSizeLerping(this, fromSize, event.getNewSize(), event.getDuration()); // Paper + } + + } +@@ -434,11 +459,11 @@ public class WorldBorder { + + class MovingBorderExtent implements WorldBorder.BorderExtent { + +- private final double from; +- private final double to; ++ private final double from; public final double getOldSize() { return this.from; } // Paper - OBFHELPER ++ private final double to; public final double getNewSize() { return this.to; } // Paper - OBFHELPER + private final long lerpEnd; + private final long lerpBegin; +- private final double lerpDuration; ++ private final double lerpDuration; public final double getDuration() { return this.lerpDuration; } // Paper - OBFHELPER + + private MovingBorderExtent(double d0, double d1, long i) { + this.from = d0; +@@ -493,6 +518,7 @@ public class WorldBorder { + + @Override + public WorldBorder.BorderExtent update() { ++ if (this.getLerpTimeRemaining() <= 0L) new WorldBorderBoundsChangeFinishEvent(world.getWorld(), world.getWorld().getWorldBorder(), getOldSize(), getNewSize(), getDuration()).callEvent(); // Paper + return (WorldBorder.BorderExtent) (this.getLerpRemainingTime() <= 0L ? WorldBorder.this.new StaticBorderExtent(this.to) : this); + } + +@@ -514,6 +540,7 @@ public class WorldBorder { + + double getSize(); + ++ default long getLerpTimeRemaining() { return getLerpRemainingTime(); } // Paper - OBFHELPER + long getLerpRemainingTime(); + + double getLerpTarget(); diff --git a/Remapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch b/Remapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch new file mode 100644 index 0000000000..64f85dbc14 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 5 Jul 2020 00:33:54 -0700 +Subject: [PATCH] added PlayerNameEntityEvent + + +diff --git a/src/main/java/net/minecraft/world/item/NameTagItem.java b/src/main/java/net/minecraft/world/item/NameTagItem.java +index 5e38077c3de0a40f3cfd856bf2e48f7061e39a9d..5c575798c20f15d28350f767ecf15bfc042ebc8c 100644 +--- a/src/main/java/net/minecraft/world/item/NameTagItem.java ++++ b/src/main/java/net/minecraft/world/item/NameTagItem.java +@@ -1,5 +1,10 @@ + package net.minecraft.world.item; + ++// Paper start ++import io.papermc.paper.adventure.PaperAdventure; ++import io.papermc.paper.event.player.PlayerNameEntityEvent; ++// Paper end ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.InteractionHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.LivingEntity; +@@ -16,11 +21,15 @@ public class NameTagItem extends Item { + public InteractionResult interactLivingEntity(ItemStack stack, Player user, LivingEntity entity, InteractionHand hand) { + if (stack.hasCustomHoverName() && !(entity instanceof Player)) { + if (!user.level.isClientSide && entity.isAlive()) { +- entity.setCustomName(stack.getHoverName()); +- if (entity instanceof Mob) { +- ((Mob) entity).setPersistenceRequired(); ++ // Paper start ++ PlayerNameEntityEvent event = new PlayerNameEntityEvent(((ServerPlayer) user).getBukkitEntity(), entity.getBukkitLivingEntity(), PaperAdventure.asAdventure(stack.getHoverName()), true); ++ if (!event.callEvent()) return InteractionResult.PASS; ++ LivingEntity newEntityLiving = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle(); ++ newEntityLiving.setCustomName(event.getName() != null ? PaperAdventure.asVanilla(event.getName()) : null); ++ if (event.isPersistent() && newEntityLiving instanceof Mob) { ++ ((Mob) newEntityLiving).setPersistenceRequired(); + } +- ++ // Paper end + stack.shrink(1); + } + diff --git a/Remapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch b/Remapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch new file mode 100644 index 0000000000..9f050a4e9b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Tue, 16 Feb 2021 21:37:51 -0600 +Subject: [PATCH] Prevent grindstones from overstacking items + + +diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +index 329a6d70d53c13cd554c64996f2ddc489bdc1e94..445d408963538fbc01d61902805b2e35c861e4ce 100644 +--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -195,13 +195,13 @@ public class GrindstoneMenu extends AbstractContainerMenu { + i = Math.max(item.getMaxDamage() - l, 0); + itemstack2 = this.mergeEnchants(itemstack, itemstack1); + if (!itemstack2.isDamageableItem()) { +- if (!ItemStack.matches(itemstack, itemstack1)) { ++ if (!ItemStack.matches(itemstack, itemstack1) || itemstack2.getMaxStackSize() == 1) { // Paper - add max stack size check + this.resultSlots.setItem(0, ItemStack.EMPTY); + this.broadcastChanges(); + return; + } + +- b0 = 2; ++ b0 = 2; // Paper - the problem line for above change, causing over-stacking + } + } else { + boolean flag3 = !itemstack.isEmpty(); diff --git a/Remapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch b/Remapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch new file mode 100644 index 0000000000..e43e7804ac --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> +Date: Wed, 6 Jan 2021 12:04:03 -0800 +Subject: [PATCH] Add recipe to cook events + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index f47b46cebd43faa509b8139d2a51cc8f87615893..2dcabfc765cbf6341546a7e2c48156fd921fcc82 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -393,7 +393,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); + org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); + +- FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()), source, result); ++ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()), source, result, (org.bukkit.inventory.CookingRecipe) recipe.toBukkitRecipe()); // Paper + this.level.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent); + + if (furnaceSmeltEvent.isCancelled()) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +index 6c38361d744eae763b6c131ad314485f5a88fcfc..39b4782df965c785be7946d6964e0b7a4381ff74 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +@@ -73,7 +73,10 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable, Ticka + + if (this.cookingProgress[i] >= this.cookingTime[i]) { + SimpleContainer inventorysubcontainer = new SimpleContainer(new ItemStack[]{itemstack}); +- ItemStack itemstack1 = (ItemStack) this.level.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, inventorysubcontainer, this.level).map((recipecampfire) -> { ++ // Paper start ++ Optional recipe = this.level.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, inventorysubcontainer, this.level); ++ ItemStack itemstack1 = (ItemStack) recipe.map((recipecampfire) -> { ++ // Paper end + return recipecampfire.assemble(inventorysubcontainer); + }).orElse(itemstack); + BlockPos blockposition = this.getBlockPos(); +@@ -82,7 +85,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable, Ticka + CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); + org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); + +- BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.level, this.worldPosition), source, result); ++ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.level, this.worldPosition), source, result, (org.bukkit.inventory.CookingRecipe) recipe.map(CampfireCookingRecipe::toBukkitRecipe).orElse(null)); // Paper + this.level.getCraftServer().getPluginManager().callEvent(blockCookEvent); + + if (blockCookEvent.isCancelled()) { diff --git a/Remapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch b/Remapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch new file mode 100644 index 0000000000..a9fe23e278 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 6 Jul 2020 12:44:31 -0700 +Subject: [PATCH] Add Block#isValidTool + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 376b0497c28a35d7ea615397c87b2558b95c596a..def19e23996b85e1e540cd5edc6821ae0ae37f91 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -803,5 +803,9 @@ public class CraftBlock implements Block { + } + return speed; + } ++ ++ public boolean isValidTool(ItemStack itemStack) { ++ return getDrops(itemStack).size() != 0; ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch b/Remapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch new file mode 100644 index 0000000000..fa0bc9f104 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Anton Lindroth +Date: Wed, 15 Apr 2020 01:54:02 +0200 +Subject: [PATCH] Allow using signs inside spawn protection + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index eb367b8feda8219a97a547c3ef6ab82d278d2f25..108a005c296c4ed370de4af636163088971bed13 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -811,4 +811,9 @@ public class PaperWorldConfig { + fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); + log("Withers properly target players: " + fixWitherTargetingBug); + } ++ ++ public boolean allowUsingSignsInsideSpawnProtection = false; ++ private void allowUsingSignsInsideSpawnProtection() { ++ allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index cb6568b622abeb939a1195f4656accc8a1c3f1fc..1add53082ab9382cb2e90dc8305b8c71ef1c6a46 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -152,6 +152,7 @@ import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CommandBlock; ++import net.minecraft.world.level.block.SignBlock; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.CommandBlockEntity; + import net.minecraft.world.level.block.entity.JigsawBlockEntity; +@@ -1690,7 +1691,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + this.player.resetLastActionTime(); + if (blockposition.getY() < this.server.getMaxBuildHeight()) { +- if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition)) { ++ if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && (worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition) || (worldserver.paperConfig.allowUsingSignsInsideSpawnProtection && worldserver.getBlockState(blockposition).getBlock() instanceof SignBlock))) { // Paper + // CraftBukkit start - Check if we can actually do something over this large a distance + // Paper - move check up + this.player.stopUsingItem(); // SPIGOT-4706 diff --git a/Remapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch b/Remapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch new file mode 100644 index 0000000000..94fd5a3703 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 6 Jan 2021 00:34:04 -0800 +Subject: [PATCH] Implement Keyed on World + + +diff --git a/src/main/java/net/minecraft/core/Registry.java b/src/main/java/net/minecraft/core/Registry.java +index 5a98bc1522c2035487ce0a048c236903dbfa816e..4924d8cd3004a6e1ce76cd5cf7520556c23fe20a 100644 +--- a/src/main/java/net/minecraft/core/Registry.java ++++ b/src/main/java/net/minecraft/core/Registry.java +@@ -130,7 +130,7 @@ public abstract class Registry implements Codec, Keyable, IdMap { + public static final ResourceKey> LOOT_FUNCTION_REGISTRY = createRegistryKey("loot_function_type"); + public static final ResourceKey> LOOT_ITEM_REGISTRY = createRegistryKey("loot_condition_type"); + public static final ResourceKey> DIMENSION_TYPE_REGISTRY = createRegistryKey("dimension_type"); +- public static final ResourceKey> DIMENSION_REGISTRY = createRegistryKey("dimension"); ++ public static final ResourceKey> DIMENSION_REGISTRY = createRegistryKey("dimension"); public static final ResourceKey> getWorldRegistry() { return DIMENSION_REGISTRY; } // Paper - OBFHELPER + public static final ResourceKey> LEVEL_STEM_REGISTRY = createRegistryKey("dimension"); + public static final Registry SOUND_EVENT = registerSimple(Registry.SOUND_EVENT_REGISTRY, () -> { + return SoundEvents.ITEM_PICKUP; +@@ -339,9 +339,9 @@ public abstract class Registry implements Codec, Keyable, IdMap { + ResourceLocation minecraftkey = resourcekey.location(); + + Registry.LOADERS.put(minecraftkey, defaultEntry); +- WritableRegistry iregistrywritable = Registry.WRITABLE_REGISTRY; ++ WritableRegistry iregistrywritable = Registry.WRITABLE_REGISTRY; // Paper - decompile fix + +- return (WritableRegistry) iregistrywritable.register(resourcekey, (Object) registry, lifecycle); ++ return (R) iregistrywritable.register(resourcekey, (Object) registry, lifecycle); // Paper - decompile fix + } + + protected Registry(ResourceKey> key, Lifecycle lifecycle) { +@@ -428,11 +428,11 @@ public abstract class Registry implements Codec, Keyable, IdMap { + } + + public static T register(Registry registry, ResourceLocation id, T entry) { +- return ((WritableRegistry) registry).register(ResourceKey.create(registry.key, id), entry, Lifecycle.stable()); ++ return ((WritableRegistry) registry).register(ResourceKey.create(registry.key, id), entry, Lifecycle.stable()); // Paper - decompile fix + } + + public static T registerMapping(Registry registry, int rawId, String id, T entry) { +- return ((WritableRegistry) registry).registerMapping(rawId, ResourceKey.create(registry.key, new ResourceLocation(id)), entry, Lifecycle.stable()); ++ return ((WritableRegistry) registry).registerMapping(rawId, ResourceKey.create(registry.key, new ResourceLocation(id)), entry, Lifecycle.stable()); // Paper - decompile fix + } + + static { +diff --git a/src/main/java/net/minecraft/resources/ResourceKey.java b/src/main/java/net/minecraft/resources/ResourceKey.java +index 2f39438ee9b23706efb2fd877fe223777b6968c7..3085ec1f20f4c945242697b809188a8c828cfb75 100644 +--- a/src/main/java/net/minecraft/resources/ResourceKey.java ++++ b/src/main/java/net/minecraft/resources/ResourceKey.java +@@ -12,6 +12,7 @@ public class ResourceKey { + private final ResourceLocation registryName; + private final ResourceLocation location; + ++ public static ResourceKey newResourceKey(ResourceKey> registryKey, ResourceLocation minecraftKey) { return create(registryKey, minecraftKey); } // Paper - OBFHELPER + public static ResourceKey create(ResourceKey> registry, ResourceLocation value) { + return create(registry.location, value); + } +@@ -41,6 +42,7 @@ public class ResourceKey { + return this.registryName.equals(registry.location()); + } + ++ public ResourceLocation getLocation() { return location(); } // Paper - OBFHELPER + public ResourceLocation location() { + return this.location; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 794b894ed24636aec60de9a28ba7613d7a917324..6905256147d9bd79e5f52bf86bdb21c89b8411a7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1156,7 +1156,7 @@ public final class CraftServer implements Server { + } else if (name.equals(levelName + "_the_end")) { + worldKey = net.minecraft.world.level.Level.END; + } else { +- worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(name.toLowerCase(java.util.Locale.ENGLISH))); ++ worldKey = ResourceKey.newResourceKey(Registry.getWorldRegistry(), new net.minecraft.resources.ResourceLocation(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper + } + + ServerLevel internal = (ServerLevel) new ServerLevel(console, console.executor, worldSession, worlddata, worldKey, dimensionmanager, getServer().progressListenerFactory.create(11), +@@ -1246,6 +1246,15 @@ public final class CraftServer implements Server { + return null; + } + ++ // Paper start ++ @Override ++ public World getWorld(NamespacedKey worldKey) { ++ ServerLevel worldServer = console.getLevel(ResourceKey.newResourceKey(Registry.getWorldRegistry(), CraftNamespacedKey.toMinecraft(worldKey))); ++ if (worldServer == null) return null; ++ return worldServer.getWorld(); ++ } ++ // Paper end ++ + public void addWorld(World world) { + // Check if a World already exists with the UID. + if (getWorld(world.getUID()) != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index f497b9e11a075a84ff0a2117eb79d0532e4a326f..b0212b2043ee5fd77c8876ef0b51ef91488712f0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2566,6 +2566,11 @@ public class CraftWorld implements World { + return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + }, net.minecraft.server.MinecraftServer.getServer()); + } ++ ++ @Override ++ public org.bukkit.NamespacedKey getKey() { ++ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(world.dimension().getLocation()); ++ } + // Paper end + + // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch b/Remapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch new file mode 100644 index 0000000000..b395761137 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Irmo van den Berge +Date: Wed, 10 Mar 2021 21:26:31 +0100 +Subject: [PATCH] Add fast alternative constructor for Vector3f + +Signed-off-by: Irmo van den Berge + +diff --git a/src/main/java/net/minecraft/core/Rotations.java b/src/main/java/net/minecraft/core/Rotations.java +index e3c2affb5dfaf2d78139e98c9e8a40b37c92bf2f..4782cbd9d86d8246954db76993741a8a749a7fe0 100644 +--- a/src/main/java/net/minecraft/core/Rotations.java ++++ b/src/main/java/net/minecraft/core/Rotations.java +@@ -19,6 +19,18 @@ public class Rotations { + this(serialized.getFloat(0), serialized.getFloat(1), serialized.getFloat(2)); + } + ++ // Paper start - faster alternative constructor ++ private Rotations(float x, float y, float z, Void dummy_var) { ++ this.x = x; ++ this.y = y; ++ this.z = z; ++ } ++ ++ public static Rotations createWithoutValidityChecks(float x, float y, float z) { ++ return new Rotations(x, y, z, null); ++ } ++ // Paper end ++ + public ListTag save() { + ListTag nbttaglist = new ListTag(); + diff --git a/Remapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch b/Remapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch new file mode 100644 index 0000000000..51a841f551 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 12 Mar 2021 17:09:42 -0800 +Subject: [PATCH] Item Rarity API + + +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index 58400e84830c93675b0a1fe632be5e217c19a932..cb079bfd5339b96ad372b0a3b483d02cd0636bfd 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -45,7 +45,7 @@ public class Item implements ItemLike { + protected static final UUID BASE_ATTACK_SPEED_UUID = UUID.fromString("FA233E1C-4180-4865-B01B-BCCE9785ACA3"); + protected static final Random random = new Random(); + protected final CreativeModeTab category; +- private final Rarity rarity; ++ private final Rarity rarity; public final Rarity getItemRarity() { return rarity; } // Paper - OBFHELPER + private final int maxStackSize; + private final int maxDamage; + private final boolean isFireResistant; +@@ -209,6 +209,7 @@ public class Item implements ItemLike { + return stack.isEnchanted(); + } + ++ public Rarity getItemStackRarity(ItemStack itemStack) { return getRarity(itemStack); } // Paper - OBFHELPER + public Rarity getRarity(ItemStack stack) { + if (!stack.isEnchanted()) { + return this.rarity; +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 25a29d997f163ce2b11330d66a691601f514a9cb..472b0615dcdc3c0c52bd377fd69752716f354262 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -470,6 +470,20 @@ public final class CraftMagicNumbers implements UnsafeValues { + public int nextEntityId() { + return net.minecraft.world.entity.Entity.nextEntityId(); + } ++ ++ @Override ++ public io.papermc.paper.inventory.ItemRarity getItemRarity(org.bukkit.Material material) { ++ Item item = getItem(material); ++ if (item == null) { ++ throw new IllegalArgumentException(material + " is not an item, and rarity does not apply to blocks"); ++ } ++ return io.papermc.paper.inventory.ItemRarity.values()[item.getItemRarity().ordinal()]; ++ } ++ ++ @Override ++ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { ++ return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; ++ } + // Paper end + + /** diff --git a/Remapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/Remapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch new file mode 100644 index 0000000000..c076df0076 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Fri, 19 Mar 2021 16:07:21 -0700 +Subject: [PATCH] Only set despawnTimer for Wandering Traders spawned by + MobSpawnerTrader + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index d38828485d6deb08036e11d8bf16b3d63a60fbae..f6d2aca2fe3ee9b69a0b200c8b2ea35f222fb521 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -319,6 +319,12 @@ public class EntityType { + + @Nullable + public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // Paper start - add consumer to modify entity before spawn ++ return this.spawnCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1, spawnReason, null); ++ } ++ @Nullable ++ public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason, @Nullable java.util.function.Consumer op) { ++ // Paper end + // Paper start - Call PreCreatureSpawnEvent + org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath()); + if (type != null) { +@@ -334,6 +340,7 @@ public class EntityType { + } + // Paper end + T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); ++ if (t0 != null && op != null) op.accept(t0); // Paper + + if (t0 != null) { + worldserver.addAllEntities(t0, spawnReason); +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +index 69d92590d265abe8a04d8bf48bbe9a6ae606ae50..04c4cca4be8886feb59f180915977b77f9c7dde8 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -61,7 +61,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + public WanderingTrader(EntityType type, Level world) { + super(type, world); + this.forcedLoading = true; +- this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader ++ //this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set. + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +index 9074d57e1576db2da3e4c76add4f7e07e5567879..f861d83affbb0b5eaf7440a909ca3b5f7a604da7 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +@@ -114,7 +114,7 @@ public class WanderingTraderSpawner implements CustomSpawner { + return false; + } + +- WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawnCreature(worldserver, (CompoundTag) null, (Component) null, (Player) null, blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit ++ WanderingTrader entityvillagertrader = EntityType.WANDERING_TRADER.spawnCreature(worldserver, null, null, null, blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, trader -> trader.setDespawnDelay(48000)); // CraftBukkit // Paper - set despawnTimer before spawn events called + + if (entityvillagertrader != null) { + for (int i = 0; i < 2; ++i) { diff --git a/Remapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch b/Remapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch new file mode 100644 index 0000000000..862aed64d3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 23 Mar 2021 06:43:30 +0000 +Subject: [PATCH] copy TESign#isEditable from snapshots + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java +index 65e8a349c80a700f63dd27b11bb2099f65cbc069..eb0739c0927e821a5080d14e762225fd4936b82d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java +@@ -109,6 +109,7 @@ public class CraftSign extends CraftBlockEntityState implements + } + // Paper end + } ++ sign.isEditable = getSnapshot().isEditable; // Paper - copy manually + } + + // Paper start diff --git a/Remapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch b/Remapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch new file mode 100644 index 0000000000..4e8128fd64 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Thu, 4 Feb 2021 20:32:01 +0300 +Subject: [PATCH] Drop carried item when player has disconnected + +Fixes disappearance of held items, when a player gets disconnected and PlayerDropItemEvent is cancelled. +Closes #5036 + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index dd121ec8f779b3786eeb7fe85519cf9e472f5adf..23cfaf5c432221f2d1afe37ba657f723d6d21a73 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -79,6 +79,7 @@ import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.npc.AbstractVillager; ++import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GameType; +@@ -605,6 +606,14 @@ public abstract class PlayerList { + } + // Paper end + ++ // Paper - Drop carried item when player has disconnected ++ if (!entityplayer.inventory.getCarried().isEmpty()) { ++ ItemStack carried = entityplayer.inventory.getCarried(); ++ entityplayer.inventory.setCarried(ItemStack.NULL_ITEM); ++ entityplayer.drop(carried, false); ++ } ++ // Paper end ++ + this.save(entityplayer); + if (entityplayer.isPassenger()) { + Entity entity = entityplayer.getRootVehicle(); diff --git a/Remapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch b/Remapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch new file mode 100644 index 0000000000..4b433dc16c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Sat, 27 Mar 2021 09:24:23 +0100 +Subject: [PATCH] forced whitelist: use configurable kick message + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 9b654fed2a00740cef84cf72258abfc7aeafc0c2..fd76d776c7003585c9efef44c6d7da0f6c3f574e 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -73,7 +73,6 @@ import net.minecraft.nbt.NbtOps; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TextComponent; +-import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; + import net.minecraft.network.protocol.game.ClientboundSetTimePacket; +@@ -2040,7 +2039,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Mon, 29 Mar 2021 09:07:25 +0200 +Subject: [PATCH] Make sure to remove correct TE during TE tick + +This looks like it can cause premature TE removal. + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index b89cefc8890774dbc64fd6bddeb038d2ee36d485..4523bc1f49e7be248a47eeb599fa7b6550dbb08d 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -895,7 +895,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + //this.tileEntityList.remove(tileentity); // Paper - remove unused list + // Paper - prevent double chunk lookups + LevelChunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getBlockPos())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again +- chunk.removeBlockEntity(tileentity.getBlockPos()); ++ chunk.removeTileEntity(tileentity.getBlockPos(), tileentity); // Paper - remove correct TE + } + // Paper end + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 9b76dc15417eef420804e5184a6d684e1137a746..a15c08be3e1bd0e7934175db6ae0684bbb05e249 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -818,10 +818,18 @@ public class LevelChunk implements ChunkAccess { + + @Override + public void removeBlockEntity(BlockPos pos) { ++ // Paper start - remove correct TE ++ removeTileEntity(pos, null); ++ } ++ public void removeTileEntity(BlockPos blockposition, BlockEntity match) { ++ // Paper end + if (this.loaded || this.world.isClientSide()) { +- BlockEntity tileentity = (BlockEntity) this.blockEntities.remove(pos); ++ // Paper start ++ BlockEntity tileentity = (BlockEntity) this.blockEntities.get(blockposition); + +- if (tileentity != null) { ++ if (tileentity != null && (match == null || match == tileentity)) { ++ this.blockEntities.remove(blockposition); ++ // Paper end + tileentity.setRemoved(); + } + } diff --git a/Remapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/Remapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch new file mode 100644 index 0000000000..930a7a71e6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Mon, 5 Apr 2021 18:35:15 -0700 +Subject: [PATCH] Don't ignore result of PlayerEditBookEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 1add53082ab9382cb2e90dc8305b8c71ef1c6a46..65afc23f4791aca19bff78ed86b3b0d31fa81977 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1144,7 +1144,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + list.stream().map(StringTag::valueOf).forEach(nbttaglist::add); + ItemStack old = itemstack.copy(); // CraftBukkit + itemstack.addTagElement("pages", (Tag) nbttaglist); +- CraftEventFactory.handleEditBookEvent(player, i, old, itemstack); // CraftBukkit ++ this.player.inventory.setItem(i, CraftEventFactory.handleEditBookEvent(player, i, old, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) + } + } + diff --git a/Remapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch b/Remapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch new file mode 100644 index 0000000000..00cd7e5d6c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Sat, 27 Mar 2021 11:13:30 +0100 +Subject: [PATCH] fix cancelling block falling causing client desync + + +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 2ba81e7179c7f9e2e1add1ad6bd6b96ee12c5da1..718e20f83a9b510c095d7e12241616cdce33d2d6 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -13,6 +13,7 @@ import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.FluidTags; + import net.minecraft.tags.Tag; +@@ -41,6 +42,7 @@ import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class FallingBlockEntity extends Entity { +@@ -114,8 +116,18 @@ public class FallingBlockEntity extends Entity { + + if (this.time++ == 0) { + blockposition = this.blockPosition(); +- if (this.level.getBlockState(blockposition).is(block) && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { +- this.level.removeBlock(blockposition, false); ++ // Paper start - fix cancelling block falling causing client desync ++ if (this.level.getBlockState(blockposition).isSameInstance(block)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ if (this.level.getBlockState(blockposition).isSameInstance(block)) { //if listener didn't update the block ++ ((ServerLevel) level).getChunkSource().blockChanged(blockposition); ++ } ++ this.remove(); ++ return; ++ } else { ++ this.level.setAir(blockposition, false); ++ } ++ // Paper end - fix cancelling block falling causing client desync + } else if (!this.level.isClientSide) { + this.remove(); + return; +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index 17baae6b11f191f4738a107c7e62ea5bdac17a3c..32cda8c2e14cf8b218cb006a9b25330f0dab849a 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -682,6 +682,7 @@ public abstract class BlockBehaviour { + return this.getBlock().is(tag) && predicate.test(this); + } + ++ public final boolean isSameInstance(Block block) { return is(block); } // Paper - OBFHELPER + public boolean is(Block block) { + return this.getBlock().is(block); + } diff --git a/Remapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch b/Remapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch new file mode 100644 index 0000000000..0e4392f5f9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Fri, 26 Mar 2021 11:23:17 +0100 +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 472b0615dcdc3c0c52bd377fd69752716f354262..402e5a98290a1701dd67d27c484c97e0a6067c4f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -484,6 +484,11 @@ public final class CraftMagicNumbers implements UnsafeValues { + public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { + return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; + } ++ ++ @Override ++ public int getProtocolVersion() { ++ return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion(); ++ } + // Paper end + + /** diff --git a/Remapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/Remapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch new file mode 100644 index 0000000000..036bfe3e5a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch @@ -0,0 +1,132 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Thu, 1 Apr 2021 00:34:02 -0700 +Subject: [PATCH] Allow for Component suggestion tooltips in + AsyncTabCompleteEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 65afc23f4791aca19bff78ed86b3b0d31fa81977..67defaf71752ed29fde483e8232aa358ffa53675 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -769,12 +769,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + // Paper start - async tab completion + com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; +- java.util.List completions = new java.util.ArrayList<>(); + String buffer = packet.getCommand(); +- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), + buffer, true, null); + event.callEvent(); +- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); ++ java.util.List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); + // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server + if (!event.isHandled()) { + if (!event.isCancelled()) { +@@ -793,10 +792,16 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + }); + } + } else if (!completions.isEmpty()) { +- com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); ++ com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); + +- builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); +- completions.forEach(builder::suggest); ++ final com.mojang.brigadier.suggestion.SuggestionsBuilder builder = builder0.createOffset(builder0.getInput().lastIndexOf(' ') + 1); ++ completions.forEach(completion -> { ++ if (completion.tooltip() == null) { ++ builder.suggest(completion.suggestion()); ++ } else { ++ builder.suggest(completion.suggestion(), PaperAdventure.asVanilla(completion.tooltip())); ++ } ++ }); + com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); + com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); + suggestEvent.setCancelled(suggestions.isEmpty()); +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index c5e00bd9e2790992202aadf8eec2002fc88c78f1..dd8e87ad192c19743577bb95253a127072ea196c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -29,34 +29,56 @@ public class ConsoleCommandCompleter implements Completer { + final CraftServer server = this.server.server; + final String buffer = line.line(); + // Async Tab Complete +- com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; +- java.util.List completions = new java.util.ArrayList<>(); +- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, +- buffer, true, null); ++ final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event = ++ new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), buffer, true, null); + event.callEvent(); +- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); ++ final List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); + + if (event.isCancelled() || event.isHandled()) { + // Still fire sync event with the provided completions, if someone is listening + if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { +- List finalCompletions = completions; ++ List finalCompletions = new java.util.ArrayList<>(completions); + Waitable> syncCompletions = new Waitable>() { + @Override + protected List evaluate() { +- org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); ++ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, ++ finalCompletions.stream() ++ .map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::suggestion) ++ .collect(java.util.stream.Collectors.toList())); + return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); + } + }; + server.getServer().processQueue.add(syncCompletions); + try { +- completions = syncCompletions.get(); ++ final List legacyCompletions = syncCompletions.get(); ++ completions.removeIf(it -> !legacyCompletions.contains(it.suggestion())); // remove any suggestions that were removed ++ // add any new suggestions ++ for (final String completion : legacyCompletions) { ++ if (notNewSuggestion(completions, completion)) { ++ continue; ++ } ++ completions.add(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion(completion)); ++ } + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } + } + + if (!completions.isEmpty()) { +- candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); ++ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { ++ if (completion.suggestion().isEmpty()) { ++ continue; ++ } ++ candidates.add(new Candidate( ++ completion.suggestion(), ++ completion.suggestion(), ++ null, ++ io.papermc.paper.adventure.PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null), ++ null, ++ null, ++ false ++ )); ++ } + } + return; + } +@@ -106,4 +128,15 @@ public class ConsoleCommandCompleter implements Completer { + Thread.currentThread().interrupt(); + } + } ++ ++ // Paper start ++ private boolean notNewSuggestion(final List completions, final String completion) { ++ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion it : completions) { ++ if (it.suggestion().equals(completion)) { ++ return true; ++ } ++ } ++ return false; ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch b/Remapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch new file mode 100644 index 0000000000..f6416177a9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch @@ -0,0 +1,316 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Tue, 30 Mar 2021 16:06:08 -0700 +Subject: [PATCH] Enhance console tab completions for brigadier commands + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index c56e7fb18f9a56c8025eb70a524f028b5942da37..efc1e42d606e1c9feb1a4871c0714933ae92a1b2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -479,4 +479,11 @@ public class PaperConfig { + private static void fixEntityPositionDesync() { + fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); + } ++ ++ public static boolean enableBrigadierConsoleHighlighting = true; ++ public static boolean enableBrigadierConsoleCompletions = true; ++ private static void consoleSettings() { ++ enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); ++ enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +index a4070b59e261f0f1ac4beec47b11492f4724bf27..372a459bd08f79f10ffd1391ec492e37f1e8bb50 100644 +--- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java ++++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +@@ -1,5 +1,7 @@ + package com.destroystokyo.paper.console; + ++import com.destroystokyo.paper.PaperConfig; ++import io.papermc.paper.console.BrigadierCommandHighlighter; + import net.minecraft.server.dedicated.DedicatedServer; + import net.minecrell.terminalconsole.SimpleTerminalConsole; + import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; +@@ -16,11 +18,15 @@ public final class PaperConsole extends SimpleTerminalConsole { + + @Override + protected LineReader buildReader(LineReaderBuilder builder) { +- return super.buildReader(builder ++ builder + .appName("Paper") + .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) + .completer(new ConsoleCommandCompleter(this.server)) +- ); ++ .option(LineReader.Option.COMPLETE_IN_WORD, true); ++ if (PaperConfig.enableBrigadierConsoleHighlighting) { ++ builder.highlighter(new BrigadierCommandHighlighter(this.server, this.server.createCommandSourceStack())); ++ } ++ return super.buildReader(builder); + } + + @Override +diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2768028750fb9a95b3f3b409d047be14bb0083d5 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java +@@ -0,0 +1,95 @@ ++package io.papermc.paper.console; ++ ++import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion; ++import com.mojang.brigadier.CommandDispatcher; ++import com.mojang.brigadier.ParseResults; ++import com.mojang.brigadier.StringReader; ++import com.mojang.brigadier.suggestion.Suggestion; ++import io.papermc.paper.adventure.PaperAdventure; ++import net.minecraft.commands.CommandSourceStack; ++import net.minecraft.network.chat.ComponentUtils; ++import net.minecraft.server.dedicated.DedicatedServer; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jline.reader.Candidate; ++import org.jline.reader.LineReader; ++import org.jline.reader.ParsedLine; ++ ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++ ++import static com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion; ++ ++public final class BrigadierCommandCompleter { ++ private final CommandSourceStack commandSourceStack; ++ private final DedicatedServer server; ++ ++ public BrigadierCommandCompleter(final @NonNull DedicatedServer server, final @NonNull CommandSourceStack commandSourceStack) { ++ this.server = server; ++ this.commandSourceStack = commandSourceStack; ++ } ++ ++ public void complete(final @NonNull LineReader reader, final @NonNull ParsedLine line, final @NonNull List candidates, final @NonNull List existing) { ++ if (!com.destroystokyo.paper.PaperConfig.enableBrigadierConsoleCompletions) { ++ this.addCandidates(candidates, Collections.emptyList(), existing); ++ return; ++ } ++ final CommandDispatcher dispatcher = this.server.getCommands().dispatcher(); ++ final ParseResults results = dispatcher.parse(prepareStringReader(line.line()), this.commandSourceStack); ++ this.addCandidates( ++ candidates, ++ dispatcher.getCompletionSuggestions(results, line.cursor()).join().getList(), ++ existing ++ ); ++ } ++ ++ private void addCandidates( ++ final @NonNull List candidates, ++ final @NonNull List brigSuggestions, ++ final @NonNull List existing ++ ) { ++ final List completions = new ArrayList<>(); ++ brigSuggestions.forEach(it -> completions.add(toCompletion(it))); ++ for (final Completion completion : existing) { ++ if (completion.suggestion().isEmpty() || brigSuggestions.stream().anyMatch(it -> it.getText().equals(completion.suggestion()))) { ++ continue; ++ } ++ completions.add(completion); ++ } ++ for (final Completion completion : completions) { ++ if (completion.suggestion().isEmpty()) { ++ continue; ++ } ++ candidates.add(toCandidate(completion)); ++ } ++ } ++ ++ private static @NonNull Candidate toCandidate(final @NonNull Completion completion) { ++ final String suggestionText = completion.suggestion(); ++ final String suggestionTooltip = PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null); ++ return new Candidate( ++ suggestionText, ++ suggestionText, ++ null, ++ suggestionTooltip, ++ null, ++ null, ++ false ++ ); ++ } ++ ++ private static @NonNull Completion toCompletion(final @NonNull Suggestion suggestion) { ++ if (suggestion.getTooltip() == null) { ++ return completion(suggestion.getText()); ++ } ++ return completion(suggestion.getText(), PaperAdventure.asAdventure(ComponentUtils.fromMessage(suggestion.getTooltip()))); ++ } ++ ++ static @NonNull StringReader prepareStringReader(final @NonNull String line) { ++ final StringReader stringReader = new StringReader(line); ++ if (stringReader.canRead() && stringReader.peek() == '/') { ++ stringReader.skip(); ++ } ++ return stringReader; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..812027fb84e1b7825f2dd0fb6fa33831367c2dc0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java +@@ -0,0 +1,57 @@ ++package io.papermc.paper.console; ++ ++import com.mojang.brigadier.ParseResults; ++import com.mojang.brigadier.context.ParsedCommandNode; ++import com.mojang.brigadier.tree.LiteralCommandNode; ++import net.minecraft.commands.CommandSourceStack; ++import net.minecraft.server.dedicated.DedicatedServer; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jline.reader.Highlighter; ++import org.jline.reader.LineReader; ++import org.jline.utils.AttributedString; ++import org.jline.utils.AttributedStringBuilder; ++import org.jline.utils.AttributedStyle; ++ ++public final class BrigadierCommandHighlighter implements Highlighter { ++ private static final int[] COLORS = {AttributedStyle.CYAN, AttributedStyle.YELLOW, AttributedStyle.GREEN, AttributedStyle.MAGENTA, /* Client uses GOLD here, not BLUE, however there is no GOLD AttributedStyle. */ AttributedStyle.BLUE}; ++ private final CommandSourceStack commandSourceStack; ++ private final DedicatedServer server; ++ ++ public BrigadierCommandHighlighter(final @NonNull DedicatedServer server, final @NonNull CommandSourceStack commandSourceStack) { ++ this.server = server; ++ this.commandSourceStack = commandSourceStack; ++ } ++ ++ @Override ++ public AttributedString highlight(final @NonNull LineReader reader, final @NonNull String buffer) { ++ final AttributedStringBuilder builder = new AttributedStringBuilder(); ++ final ParseResults results = this.server.getCommands().dispatcher().parse(BrigadierCommandCompleter.prepareStringReader(buffer), this.commandSourceStack); ++ int pos = 0; ++ if (buffer.startsWith("/")) { ++ builder.append("/", AttributedStyle.DEFAULT); ++ pos = 1; ++ } ++ int component = -1; ++ for (final ParsedCommandNode node : results.getContext().getLastChild().getNodes()) { ++ if (node.getRange().getStart() >= buffer.length()) { ++ break; ++ } ++ final int start = node.getRange().getStart(); ++ final int end = Math.min(node.getRange().getEnd(), buffer.length()); ++ builder.append(buffer.substring(pos, start), AttributedStyle.DEFAULT); ++ if (node.getNode() instanceof LiteralCommandNode) { ++ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT); ++ } else { ++ if (++component >= COLORS.length) { ++ component = 0; ++ } ++ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT.foreground(COLORS[component])); ++ } ++ pos = end; ++ } ++ if (pos < buffer.length()) { ++ builder.append((buffer.substring(pos)), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)); ++ } ++ return builder.toAttributedString(); ++ } ++} +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index 5ed78383ce247ceb24cda0335dbeae293958055c..e2f18b5bf1e091fe5fd868520a6d1bcc2669c24c 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -440,7 +440,7 @@ public class Commands { + }; + } + +- public com.mojang.brigadier.CommandDispatcher getDispatcher() { ++ public com.mojang.brigadier.CommandDispatcher getDispatcher() { return this.dispatcher(); } public com.mojang.brigadier.CommandDispatcher dispatcher() { // Paper - OBFHELPER + return this.dispatcher; + } + +diff --git a/src/main/java/net/minecraft/network/chat/ComponentUtils.java b/src/main/java/net/minecraft/network/chat/ComponentUtils.java +index b5a59aed5d5cfbe0f75a8209b058b368b1f2b595..ed90c4348ca030d678251b0f9891d00153992f89 100644 +--- a/src/main/java/net/minecraft/network/chat/ComponentUtils.java ++++ b/src/main/java/net/minecraft/network/chat/ComponentUtils.java +@@ -90,7 +90,7 @@ public class ComponentUtils { + TextComponent chatcomponenttext = new TextComponent(""); + boolean flag = true; + +- for (Iterator iterator = elements.iterator(); iterator.hasNext(); flag = false) { ++ for (Iterator iterator = elements.iterator(); iterator.hasNext(); flag = false) { // Paper - decompile fix + T t0 = iterator.next(); + + if (!flag) { +@@ -108,7 +108,7 @@ public class ComponentUtils { + return new TranslatableComponent("chat.square_brackets", new Object[]{text}); + } + +- public static Component fromMessage(Message message) { ++ public static Component fromMessage(Message message) { return fromMessage(message); } public static Component fromMessage(final @org.checkerframework.checker.nullness.qual.NonNull Message message) { // Paper - OBFHELPER + return (Component) (message instanceof Component ? (Component) message : new TextComponent(message.getString())); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index dd8e87ad192c19743577bb95253a127072ea196c..eaad328d0d15ef450bb5a305828ce413d1eab53b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -18,9 +18,11 @@ import org.bukkit.event.server.TabCompleteEvent; + + public class ConsoleCommandCompleter implements Completer { + private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer ++ private final io.papermc.paper.console.BrigadierCommandCompleter brigadierCompleter; // Paper + + public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer + this.server = server; ++ this.brigadierCompleter = new io.papermc.paper.console.BrigadierCommandCompleter(this.server, this.server.createCommandSourceStack()); // Paper + } + + // Paper start - Change method signature for JLine update +@@ -64,7 +66,7 @@ public class ConsoleCommandCompleter implements Completer { + } + } + +- if (!completions.isEmpty()) { ++ if (false && !completions.isEmpty()) { + for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { + if (completion.suggestion().isEmpty()) { + continue; +@@ -80,6 +82,7 @@ public class ConsoleCommandCompleter implements Completer { + )); + } + } ++ this.addCompletions(reader, line, candidates, completions); + return; + } + +@@ -99,10 +102,12 @@ public class ConsoleCommandCompleter implements Completer { + try { + List offers = waitable.get(); + if (offers == null) { ++ this.addCompletions(reader, line, candidates, Collections.emptyList()); // Paper + return; // Paper - Method returns void + } + + // Paper start - JLine update ++ /* + for (String completion : offers) { + if (completion.isEmpty()) { + continue; +@@ -110,6 +115,8 @@ public class ConsoleCommandCompleter implements Completer { + + candidates.add(new Candidate(completion)); + } ++ */ ++ this.addCompletions(reader, line, candidates, offers.stream().map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::completion).collect(java.util.stream.Collectors.toList())); + // Paper end + + // Paper start - JLine handles cursor now +@@ -138,5 +145,9 @@ public class ConsoleCommandCompleter implements Completer { + } + return false; + } ++ ++ private void addCompletions(final LineReader reader, final ParsedLine line, final List candidates, final List existing) { ++ this.brigadierCompleter.complete(reader, line, candidates, existing); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/Remapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch new file mode 100644 index 0000000000..a86a2c1b40 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Fri, 19 Mar 2021 00:33:15 -0500 +Subject: [PATCH] Fix PlayerItemConsumeEvent cancelling properly + +When the active item is not cleared, the item is still readied +for use and will repeatedly trigger the PlayerItemConsumeEvent +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 8bc74878919ab7cf6a50d425da61f1b8a8b0ee44..37787a725725d22b0870dcab0f3bec8b94cfd130 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3348,6 +3348,7 @@ public abstract class LivingEntity extends Entity { + level.getCraftServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { ++ this.stopUsingItem(); // Paper - event is using an item, clear active item to reset its use + // Update client + ((ServerPlayer) this).getBukkitEntity().updateInventory(); + ((ServerPlayer) this).getBukkitEntity().updateScaledHealth(); diff --git a/Remapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch b/Remapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch new file mode 100644 index 0000000000..88f6d3d8dc --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 18 Apr 2021 21:27:01 +0100 +Subject: [PATCH] Add bypass host check + +Paper.bypassHostCheck + +Seriously, fix your firewalls. -.- + +diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index c648b73a4c478f9d8020274205d6684f7c7c416f..4e055a41de3ee410682cc05a3b883ac8babeb290 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -30,6 +30,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + private static final Component IGNORE_STATUS_REASON = new TextComponent("Ignoring status request"); + private final MinecraftServer server; + private final Connection connection; final Connection getNetworkManager() { return this.connection; } // Paper - OBFHELPER ++ private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper + + public ServerHandshakePacketListenerImpl(MinecraftServer server, Connection connection) { + this.server = server; +@@ -118,7 +119,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + // Spigot Start + //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! + String[] split = packet.hostName.split("\00"); +- if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { ++ if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper + packet.hostName = split[0]; + connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort()); + connection.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); diff --git a/Remapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch b/Remapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch new file mode 100644 index 0000000000..487cbc3ff9 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 20 Apr 2021 01:15:04 +0100 +Subject: [PATCH] don't throw when loading invalid TEs + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 05fa76c02ce61e26891ad995fe89e925ea086557..b7ebb213efd759253f0042f77e11f2a8102ea6ca 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.block.entity; + + import javax.annotation.Nullable; + import net.minecraft.CrashReportCategory; ++import net.minecraft.ResourceLocationException; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; +@@ -133,7 +134,13 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + public static BlockEntity loadStatic(BlockState state, CompoundTag tag) { + String s = tag.getString("id"); + +- return (BlockEntity) Registry.BLOCK_ENTITY_TYPE.getOptional(new ResourceLocation(s)).map((tileentitytypes) -> { ++ // Paper ++ ResourceLocation minecraftKey = null; ++ try { ++ minecraftKey = new ResourceLocation(s); ++ } catch (ResourceLocationException ex) {} ++ // Paper end ++ return (BlockEntity) Registry.BLOCK_ENTITY_TYPE.getOptional(minecraftKey).map((tileentitytypes) -> { + try { + return tileentitytypes.create(); + } catch (Throwable throwable) { diff --git a/Remapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch b/Remapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch new file mode 100644 index 0000000000..f907ad7a6b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Mon, 5 Apr 2021 16:58:20 -0400 +Subject: [PATCH] Set area affect cloud rotation + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index b0212b2043ee5fd77c8876ef0b51ef91488712f0..b44e83d93bba579e439b93e5093350675137b070 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1959,6 +1959,7 @@ public class CraftWorld implements World { + entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(world); + } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { + entity = new net.minecraft.world.entity.AreaEffectCloud(world, x, y, z); ++ entity.moveTo(x, y, z, yaw, pitch); // Paper - Set area effect cloud Rotation + } else if (EvokerFangs.class.isAssignableFrom(clazz)) { + entity = new net.minecraft.world.entity.projectile.EvokerFangs(world, x, y, z, (float) Math.toRadians(yaw), 0, null); + } diff --git a/Remapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch b/Remapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch new file mode 100644 index 0000000000..75f3e9118b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 8 Apr 2021 17:36:10 -0700 +Subject: [PATCH] add isDeeplySleeping 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 aceb57c93c91730345f49f78838780c41ce2dcef..0559f2cfab817e989c02ce2d13bcdabb8ad3b82b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -122,6 +122,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + } + } + ++ // Paper start ++ @Override ++ public boolean isDeeplySleeping() { ++ return getHandle().isSleepingLongEnough(); ++ } ++ // Paper end ++ + @Override + public int getSleepTicks() { + return getHandle().sleepCounter; diff --git a/Remapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch b/Remapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch new file mode 100644 index 0000000000..0672393254 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch @@ -0,0 +1,113 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alphaesia +Date: Fri, 23 Apr 2021 09:57:56 +1200 +Subject: [PATCH] Fix duplicating /give items on item drop cancel + +Fixes SPIGOT-2942 (Give command fires PlayerDropItemEvent, cancelling it causes item duplication). + +For every stack of items to give, /give puts the item stack straight +into the player's inventory. However, it also summons a "fake item" +at the player's location. When the PlayerDropItemEvent for this fake +item is cancelled, the server attempts to put the item back into the +player's inventory. The result is that the fake item, which is never +meant to be obtained, is combined with the real items injected directly +into the player's inventory. This means more items than the amount +specified in /give are given to the player - one for every stack of +items given. (e.g. /give @s dirt 1 gives you 2 dirt). + +While this isn't a big issue for general building usage, it can affect +e.g. adventure maps where the number of items the player receives is +important (and you want to restrict the player from throwing items). + +If there are any overflow items that didn't make it into the inventory +(insufficient space), those items are dropped as a real item instead +of a fake one. While cancelling this drop would also result in the +server attempting to put those items into the inventory, since it is +full this has no effect. + +Just ignoring cancellation of the PlayerDropItemEvent seems like the +cleanest and least intrusive way to fix it. + +diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java +index a6259e9160f291cf527a4ea5533a2e5530471874..3b8a7b9bdd2445afa93e4f2dc971a1d252c1463a 100644 +--- a/src/main/java/net/minecraft/server/commands/GiveCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java +@@ -49,7 +49,7 @@ public class GiveCommand { + + if (flag && itemstack.isEmpty()) { + itemstack.setCount(1); +- entityitem = entityplayer.drop(itemstack, false); ++ entityitem = entityplayer.drop(itemstack, false, false, true); // Paper - Fix duplicating /give items on item drop cancel + if (entityitem != null) { + entityitem.makeFakeItem(); + } +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 4817b8ab259d348b48bc325d34ba9351ffe951df..cfb9bd6b9863a0f6f0f50181b7553adce90cfebe 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -639,7 +639,14 @@ public abstract class Player extends LivingEntity { + + @Nullable + public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership) { +- if (stack.isEmpty()) { ++ // Paper start - Fix duplicating /give items on item drop cancel ++ return this.drop(stack, throwRandomly, retainOwnership, false); ++ } ++ ++ @Nullable ++ public ItemEntity drop(ItemStack itemstack, boolean flag, boolean flag1, boolean alwaysSucceed) { ++ // Paper end ++ if (itemstack.isEmpty()) { + return null; + } else { + if (this.level.isClientSide) { +@@ -647,17 +654,17 @@ public abstract class Player extends LivingEntity { + } + + double d0 = this.getEyeY() - 0.30000001192092896D; +- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), d0, this.getZ(), stack); ++ ItemEntity entityitem = new ItemEntity(this.level, this.getX(), d0, this.getZ(), itemstack); + + entityitem.setPickUpDelay(40); +- if (retainOwnership) { ++ if (flag1) { + entityitem.setThrower(this.getUUID()); + } + + float f; + float f1; + +- if (throwRandomly) { ++ if (flag) { + f = this.random.nextFloat() * 0.5F; + f1 = this.random.nextFloat() * 6.2831855F; + entityitem.setDeltaMovement((double) (-Mth.sin(f1) * f), 0.20000000298023224D, (double) (Mth.cos(f1) * f)); +@@ -680,12 +687,12 @@ public abstract class Player extends LivingEntity { + PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); + this.level.getCraftServer().getPluginManager().callEvent(event); + +- if (event.isCancelled()) { ++ if (event.isCancelled() && !alwaysSucceed) { // Paper - Fix duplicating /give items on item drop cancel + org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); +- if (retainOwnership && (cur == null || cur.getAmount() == 0)) { ++ if (flag1 && (cur == null || cur.getAmount() == 0)) { + // The complete stack was dropped + player.getInventory().setItemInHand(drop.getItemStack()); +- } else if (retainOwnership && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { ++ } else if (flag1 && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { + // Only one item is dropped + cur.setAmount(cur.getAmount() + 1); + player.getInventory().setItemInHand(cur); +@@ -697,9 +704,9 @@ public abstract class Player extends LivingEntity { + } + // CraftBukkit end + // Paper start - remove player from map on drop +- if (stack.getItem() == Items.FILLED_MAP) { +- MapItemSavedData worldmap = MapItem.getOrCreateSavedData(stack, this.level); +- worldmap.updateSeenPlayers(this, stack); ++ if (itemstack.getItem() == Items.FILLED_MAP) { ++ MapItemSavedData worldmap = MapItem.getOrCreateSavedData(itemstack, this.level); ++ worldmap.updateSeenPlayers(this, itemstack); + } + // Paper end + diff --git a/Remapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch b/Remapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch new file mode 100644 index 0000000000..f9cc308842 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 22 Apr 2021 16:45:28 -0700 +Subject: [PATCH] add consumeFuel to FurnaceBurnEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 2dcabfc765cbf6341546a7e2c48156fd921fcc82..6e4feb2280021c26dbbfb92feb08c95165e126fe 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -329,7 +329,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + if (this.isLit() && furnaceBurnEvent.isBurning()) { + // CraftBukkit end + flag1 = true; +- if (!itemstack.isEmpty()) { ++ if (!itemstack.isEmpty() && furnaceBurnEvent.willConsumeFuel()) { // Paper + Item item = itemstack.getItem(); + + itemstack.shrink(1); diff --git a/Remapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch b/Remapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch new file mode 100644 index 0000000000..c18ac532d5 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 22 Apr 2021 00:28:11 -0700 +Subject: [PATCH] add get-set drop chance to EntityEquipment + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java +index e8d6e1abf29a5c50e1cafa01c602f36596d42ecf..9841b4ed648b95272feee45e6f1e8fd9399c322e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java +@@ -244,6 +244,17 @@ public class CraftEntityEquipment implements EntityEquipment { + public void setBootsDropChance(float chance) { + setDropChance(net.minecraft.world.entity.EquipmentSlot.FEET, chance); + } ++ // Paper start ++ @Override ++ public float getDropChance(EquipmentSlot slot) { ++ return getDropChance(CraftEquipmentSlot.getNMS(slot)); ++ } ++ ++ @Override ++ public void setDropChance(EquipmentSlot slot, float chance) { ++ setDropChance(CraftEquipmentSlot.getNMS(slot), chance); ++ } ++ // Paper end + + private void setDropChance(net.minecraft.world.entity.EquipmentSlot slot, float chance) { + if (slot == net.minecraft.world.entity.EquipmentSlot.MAINHAND || slot == net.minecraft.world.entity.EquipmentSlot.OFFHAND) { +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +index 7a8181f559cc3c92c3b3aa2ff8eda515719eba08..c326a75728fffbab301654afd94b6839c009fe93 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +@@ -354,4 +354,15 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i + public void setBootsDropChance(float chance) { + throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); + } ++ // Paper start ++ @Override ++ public float getDropChance(EquipmentSlot slot) { ++ return 1; ++ } ++ ++ @Override ++ public void setDropChance(EquipmentSlot slot, float chance) { ++ throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch b/Remapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch new file mode 100644 index 0000000000..5d4feaac2c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Thu, 18 Mar 2021 21:38:01 +0100 +Subject: [PATCH] fix PigZombieAngerEvent cancellation + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +index f85dfd8b57cf81ad7c6b12753fdd42e93f772f9e..16f4dbfd21a287bad3e10c174fa77a1cac771afa 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +@@ -28,6 +28,7 @@ public abstract class Goal { + + public void start() { this.start(); } public void start() {} // Paper - OBFHELPER + ++ public final void onTaskResetObfHelper() { stop(); } // Paper - OBFHELPER + public void stop() { + onTaskReset(); // Paper + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +index d1cbbfbf9d3c5e65785aad00c2292245a5de1422..d67a50740b1c6d4ecd49a5541d24d1e4bacb8887 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +@@ -49,6 +49,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + private UUID persistentAngerTarget; + private static final IntRange ALERT_INTERVAL = TimeUtil.rangeOfSeconds(4, 6); + private int ticksUntilNextAlert; ++ private HurtByTargetGoal pathfinderGoalHurtByTarget; // Paper + + public ZombifiedPiglin(EntityType type, Level world) { + super(type, world); +@@ -69,7 +70,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + protected void addBehaviourGoals() { + this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers(new Class[0])); // CraftBukkit - decompile error ++ this.targetSelector.addGoal(1, pathfinderGoalHurtByTarget = new HurtByTargetGoal(this).setAlertOthers(new Class[0])); // CraftBukkit - decompile error // Paper - assign field + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); + this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true)); + } +@@ -172,6 +173,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + this.level.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.setPersistentAngerTarget(null); ++ pathfinderGoalHurtByTarget.onTaskResetObfHelper(); // Paper - clear goalTargets to fix cancellation + return; + } + this.setRemainingPersistentAngerTime(event.getNewAnger()); diff --git a/Remapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch b/Remapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch new file mode 100644 index 0000000000..38d7d768a3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sun, 4 Apr 2021 14:25:04 -0400 +Subject: [PATCH] Fix checkReach check for Shulker boxes + + +diff --git a/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java b/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java +index c40518b0e4ad2b043a9acc858413648d6419f3a3..4b7814a31deeef31e877cee96f0d51b348e7a281 100644 +--- a/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java +@@ -65,6 +65,7 @@ public class ShulkerBoxMenu extends AbstractContainerMenu { + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // Paper - Add reachable override for ContainerShulkerBox + return this.container.stillValid(player); + } + diff --git a/Remapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch b/Remapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch new file mode 100644 index 0000000000..094351a8ff --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Thu, 22 Apr 2021 19:02:07 -0700 +Subject: [PATCH] fix PlayerItemHeldEvent firing twice + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java +index 68026536cfc26f07ca99ee9e76fd74b4ed4a995c..848fb02988b0fb319655f790112274ac2a437d25 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java +@@ -24,6 +24,7 @@ public class ServerboundSetCarriedItemPacket implements Packet= 0 && packet.getSlot() < Inventory.getSelectionSize()) { ++ if (packet.getItemInHandIndex() == this.player.inventory.selected) { return; } // Paper - don't fire itemheldevent when there wasn't a slot change + PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.selected, packet.getSlot()); + this.craftServer.getPluginManager().callEvent(event); + if (event.isCancelled()) { diff --git a/Remapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch b/Remapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch new file mode 100644 index 0000000000..14d231bf04 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 21 Apr 2021 15:58:19 -0700 +Subject: [PATCH] Added 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 cfb9bd6b9863a0f6f0f50181b7553adce90cfebe..c0d2ca1daca0c0c6f21334bc4d9d039440efc453 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -232,6 +232,11 @@ public abstract class Player extends LivingEntity { + + if (this.isSleeping()) { + ++this.sleepCounter; ++ // Paper start ++ if (this.sleepCounter == 100) { ++ if (!new io.papermc.paper.event.player.PlayerDeepSleepEvent((org.bukkit.entity.Player) getBukkitEntity()).callEvent()) { this.sleepCounter = Integer.MIN_VALUE; } ++ } ++ // Paper end + if (this.sleepCounter > 100) { + this.sleepCounter = 100; + } diff --git a/Remapped-Spigot-Server-Patches/0714-More-World-API.patch b/Remapped-Spigot-Server-Patches/0714-More-World-API.patch new file mode 100644 index 0000000000..37cb7379d4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0714-More-World-API.patch @@ -0,0 +1,146 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 7 Jul 2020 10:52:34 -0700 +Subject: [PATCH] More World API + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index a7553a856b9c99bee8f75d514b97cfab952bfd33..511e6a941d441c55a4b38660f0f7f8c47fa689dd 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1863,6 +1863,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return !this.worldDataServer.worldGenSettings().generateFeatures() ? null : this.getChunkSource().getGenerator().findNearestMapFeature(this, feature, pos, radius, skipExistingChunks); // CraftBukkit + } + ++ public BlockPos getNearestBiome(Biome biomeBase, BlockPos blockPosition, int radius, int step) { return this.findNearestBiome(biomeBase, blockPosition, radius, step); } // Paper - OBFHELPER + @Nullable + public BlockPos findNearestBiome(Biome biome, BlockPos pos, int radius, int j) { + return this.getChunkSource().getGenerator().getBiomeSource().findBiomeHorizontal(pos.getX(), pos.getY(), pos.getZ(), radius, j, (biomebase1) -> { +@@ -1885,6 +1886,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return this.noSave; + } + ++ public RegistryAccess getWorldCustomRegistry() { return registryAccess(); } // Paper - OBFHELPER + @Override + public RegistryAccess registryAccess() { + return this.server.registryAccess(); +diff --git a/src/main/java/net/minecraft/world/level/dimension/DimensionType.java b/src/main/java/net/minecraft/world/level/dimension/DimensionType.java +index 7dead90a0d77e936816c2a54fe70c87d92dc8e5b..fb2bdfbeb44de6ce967af2deb4738972b44dcf44 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/DimensionType.java ++++ b/src/main/java/net/minecraft/world/level/dimension/DimensionType.java +@@ -142,10 +142,10 @@ public class DimensionType { + public static RegistryAccess.RegistryHolder registerBuiltin(RegistryAccess.RegistryHolder registryManager) { + WritableRegistry iregistrywritable = registryManager.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); + +- iregistrywritable.register(DimensionType.OVERWORLD_LOCATION, (Object) DimensionType.DEFAULT_OVERWORLD, Lifecycle.stable()); +- iregistrywritable.register(DimensionType.OVERWORLD_CAVES_LOCATION, (Object) DimensionType.DEFAULT_OVERWORLD_CAVES, Lifecycle.stable()); +- iregistrywritable.register(DimensionType.NETHER_LOCATION, (Object) DimensionType.DEFAULT_NETHER, Lifecycle.stable()); +- iregistrywritable.register(DimensionType.END_LOCATION, (Object) DimensionType.DEFAULT_END, Lifecycle.stable()); ++ iregistrywritable.register(DimensionType.OVERWORLD_LOCATION, DimensionType.DEFAULT_OVERWORLD, Lifecycle.stable()); // Paper - decompile fix ++ iregistrywritable.register(DimensionType.OVERWORLD_CAVES_LOCATION, DimensionType.DEFAULT_OVERWORLD_CAVES, Lifecycle.stable()); // Paper - decompile fix ++ iregistrywritable.register(DimensionType.NETHER_LOCATION, DimensionType.DEFAULT_NETHER, Lifecycle.stable()); // Paper - decompile fix ++ iregistrywritable.register(DimensionType.END_LOCATION, DimensionType.DEFAULT_END, Lifecycle.stable()); // Paper - decompile fix + return registryManager; + } + +@@ -164,10 +164,10 @@ public class DimensionType { + public static MappedRegistry defaultDimensions(Registry dimensionRegistry, Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed) { + MappedRegistry registrymaterials = new MappedRegistry<>(Registry.LEVEL_STEM_REGISTRY, Lifecycle.experimental()); + +- registrymaterials.register(LevelStem.NETHER, (Object) (new LevelStem(() -> { ++ registrymaterials.register(LevelStem.NETHER, (new LevelStem(() -> { // Paper - decompile fix + return (DimensionType) dimensionRegistry.getOrThrow(DimensionType.NETHER_LOCATION); + }, defaultNetherGenerator(biomeRegistry, chunkGeneratorSettingsRegistry, seed))), Lifecycle.stable()); +- registrymaterials.register(LevelStem.END, (Object) (new LevelStem(() -> { ++ registrymaterials.register(LevelStem.END, (new LevelStem(() -> { // Paper - decompile fix + return (DimensionType) dimensionRegistry.getOrThrow(DimensionType.END_LOCATION); + }, defaultEndGenerator(biomeRegistry, chunkGeneratorSettingsRegistry, seed))), Lifecycle.stable()); + return registrymaterials; +@@ -256,6 +256,7 @@ public class DimensionType { + return this.brightnessRamp[i]; + } + ++ public Tag getInfiniburnTag() { return infiniburn(); } // Paper - OBFHELPER + public Tag infiniburn() { + Tag tag = BlockTags.getAllTags().getTag(this.infiniburn); + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index b44e83d93bba579e439b93e5093350675137b070..a1fa2d5e00bd125abd38a00e0bc3936f2fb8186f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2515,6 +2515,75 @@ public class CraftWorld implements World { + return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); + } + ++ // Paper start ++ @Override ++ public Location locateNearestBiome(Location origin, Biome biome, int radius) { ++ return this.locateNearestBiome(origin, biome, radius, 8); ++ } ++ ++ @Override ++ public Location locateNearestBiome(Location origin, Biome biome, int radius, int step) { ++ BlockPos originPos = new BlockPos(origin.getX(), origin.getY(), origin.getZ()); ++ BlockPos nearest = getHandle().getNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().getWorldCustomRegistry().registryOrThrow(Registry.BIOME_REGISTRY), biome), originPos, radius, step); ++ return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); ++ } ++ ++ @Override ++ public boolean isUltrawarm() { ++ return getHandle().dimensionType().ultraWarm(); ++ } ++ ++ @Override ++ public boolean isNatural() { ++ return getHandle().dimensionType().natural(); ++ } ++ ++ @Override ++ public double getCoordinateScale() { ++ return getHandle().dimensionType().coordinateScale(); ++ } ++ ++ @Override ++ public boolean hasSkylight() { ++ return getHandle().dimensionType().hasSkyLight(); ++ } ++ ++ @Override ++ public boolean hasBedrockCeiling() { ++ return getHandle().dimensionType().hasSkyLight(); ++ } ++ ++ @Override ++ public boolean isPiglinSafe() { ++ return getHandle().dimensionType().piglinSafe(); ++ } ++ ++ @Override ++ public boolean doesBedWork() { ++ return getHandle().dimensionType().bedWorks(); ++ } ++ ++ @Override ++ public boolean doesRespawnAnchorWork() { ++ return getHandle().dimensionType().respawnAnchorWorks(); ++ } ++ ++ @Override ++ public boolean hasRaids() { ++ return getHandle().dimensionType().hasRaids(); ++ } ++ ++ @Override ++ public boolean isFixedTime() { ++ return getHandle().dimensionType().hasFixedTime(); ++ } ++ ++ @Override ++ public Collection getInfiniburn() { ++ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().dimensionType().getInfiniburnTag().getTagged().iterator(), CraftMagicNumbers::getMaterial)); ++ } ++ // Paper end ++ + @Override + public Raid locateNearestRaid(Location location, int radius) { + Validate.notNull(location, "Location cannot be null"); diff --git a/Remapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch b/Remapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch new file mode 100644 index 0000000000..87c355341c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 24 Dec 2020 12:27:41 -0800 +Subject: [PATCH] Added PlayerBedFailEnterEvent + + +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 c0d2ca1daca0c0c6f21334bc4d9d039440efc453..007d9476943f5a9c75554927df941bda0f7dd6d5 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -2230,6 +2230,7 @@ public abstract class Player extends LivingEntity { + this.message = ichatbasecomponent; + } + ++ public @Nullable Component getChatComponent() { return this.getMessage(); }; // Paper - OBFHELPER + @Nullable + public Component getMessage() { + return this.message; +diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java +index 9dcbc0f741f5980305ae031daac70c7933bc6862..9dcf145b6d1a93785150d268828bca4bb31984c8 100644 +--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java +@@ -43,6 +43,8 @@ import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; + import org.apache.commons.lang3.ArrayUtils; ++import io.papermc.paper.event.player.PlayerBedFailEnterEvent; // Paper ++import io.papermc.paper.adventure.PaperAdventure; // Paper + + public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock { + +@@ -101,14 +103,23 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock + BlockPos finalblockposition = pos; + // CraftBukkit end + player.startSleepInBed(pos).ifLeft((entityhuman_enumbedresult) -> { ++ // Paper start - PlayerBedFailEnterEvent ++ if (entityhuman_enumbedresult != null) { ++ PlayerBedFailEnterEvent event = new PlayerBedFailEnterEvent((org.bukkit.entity.Player) player.getBukkitEntity(), PlayerBedFailEnterEvent.FailReason.VALUES[entityhuman_enumbedresult.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(world, finalblockposition), entityhuman_enumbedresult == Player.BedSleepingProblem.NOT_POSSIBLE_HERE, PaperAdventure.asAdventure(entityhuman_enumbedresult.getChatComponent())); ++ if (!event.callEvent()) { ++ return; ++ } ++ // Paper end + // CraftBukkit start - handling bed explosion from below here +- if (entityhuman_enumbedresult == Player.BedSleepingProblem.NOT_POSSIBLE_HERE) { ++ if (event.getWillExplode()) { // Paper + this.explodeBed(finaliblockdata, world, finalblockposition); + } else + // CraftBukkit end + if (entityhuman_enumbedresult != null) { +- player.displayClientMessage(entityhuman_enumbedresult.getMessage(), true); ++ final net.kyori.adventure.text.Component message = event.getMessage(); // Paper ++ if(message != null) player.displayClientMessage(PaperAdventure.asVanilla(message), true); // Paper + } ++ } // Paper + + }); + return InteractionResult.SUCCESS; diff --git a/Remapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch b/Remapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch new file mode 100644 index 0000000000..e796b62074 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Sat, 24 Apr 2021 02:09:32 -0700 +Subject: [PATCH] Implement methods to convert between Component and + Brigadier's Message + + +diff --git a/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..dd6012b6a097575b2d1471be5069eccee4537c0a +--- /dev/null ++++ b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java +@@ -0,0 +1,30 @@ ++package io.papermc.paper.brigadier; ++ ++import com.mojang.brigadier.Message; ++import io.papermc.paper.adventure.PaperAdventure; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.ComponentLike; ++import net.minecraft.network.chat.ComponentUtils; ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++import static java.util.Objects.requireNonNull; ++ ++public enum PaperBrigadierProviderImpl implements PaperBrigadierProvider { ++ INSTANCE; ++ ++ PaperBrigadierProviderImpl() { ++ PaperBrigadierProvider.initialize(this); ++ } ++ ++ @Override ++ public @NonNull Message message(final @NonNull ComponentLike componentLike) { ++ requireNonNull(componentLike, "componentLike"); ++ return PaperAdventure.asVanilla(componentLike.asComponent()); ++ } ++ ++ @Override ++ public @NonNull Component componentFromMessage(final @NonNull Message message) { ++ requireNonNull(message, "message"); ++ return PaperAdventure.asAdventure(ComponentUtils.fromMessage(message)); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index c2947313cc0eda3247fb4b20ddd1d0b86c37c50a..0198268bc614b190cd84f625a62f6c55247a01c8 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -210,6 +210,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } + com.destroystokyo.paper.PaperConfig.registerCommands(); + com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now ++ io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider + // Paper end + + this.setPvpAllowed(dedicatedserverproperties.pvp); diff --git a/Remapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/Remapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch new file mode 100644 index 0000000000..cf90fd18e8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Fri, 23 Apr 2021 22:42:42 +0100 +Subject: [PATCH] Fix anchor respawn acting as a bed respawn from the end + portal + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 23cfaf5c432221f2d1afe37ba657f723d6d21a73..a4e897171ce05736bcead319b7fda74d2b02fd2e 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -867,6 +867,7 @@ public abstract class PlayerList { + + // Paper start + boolean isBedSpawn = false; ++ boolean isAnchorSpawn = false; + boolean isRespawn = false; + boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 + // Paper end +@@ -887,6 +888,7 @@ public abstract class PlayerList { + if (optional.isPresent()) { + BlockState iblockdata = worldserver1.getBlockState(blockposition); + boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); ++ isAnchorSpawn = flag3; // Paper - Fix anchor respawn acting as a bed respawn from the end portal + Vec3 vec3d = (Vec3) optional.get(); + float f1; + +@@ -914,7 +916,7 @@ public abstract class PlayerList { + } + + Player respawnPlayer = cserver.getPlayer(entityplayer1); +- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag2, flag2); ++ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal + cserver.getPluginManager().callEvent(respawnEvent); + // Spigot Start + if (entityplayer.connection.isDisconnected()) { diff --git a/Remapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch b/Remapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch new file mode 100644 index 0000000000..b0c5ab3263 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 22 Apr 2021 17:17:47 -0700 +Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 5b0eb8744dba5df6f16bafd6d907cd1efd508fe6..a0e69cac7699ddc318057c8016e329850d3baa26 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2440,7 +2440,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + case PERFORM_RESPAWN: + if (this.player.wonGame) { + this.player.wonGame = false; +- this.player = this.server.getPlayerList().respawn(this.player, true); ++ this.player = this.server.getPlayerList().moveToWorld(this.player, this.server.getLevel(this.player.getRespawnDimension()), true, null, true, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); // Paper - add isEndCreditsRespawn argument + CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD); + } else { + if (this.player.getHealth() > 0.0F) { +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index a4e897171ce05736bcead319b7fda74d2b02fd2e..6011b43ae8a858f88b8fcf6dc0bf147024a4742c 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -816,7 +816,13 @@ public abstract class PlayerList { + return this.moveToWorld(player, this.server.getLevel(player.getRespawnDimension()), alive, null, true); + } + ++ // Paper start + public ServerPlayer moveToWorld(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation) { ++ return moveToWorld(entityplayer, worldserver, flag, location, avoidSuffocation, new org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag[0]); ++ } ++ ++ public ServerPlayer moveToWorld(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag...respawnFlags) { ++ // Paper end + entityplayer.stopRiding(); // CraftBukkit + this.players.remove(entityplayer); + this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot +@@ -916,7 +922,7 @@ public abstract class PlayerList { + } + + Player respawnPlayer = cserver.getPlayer(entityplayer1); +- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal ++ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn, com.google.common.collect.ImmutableSet.builder().add(respawnFlags)); // Paper - Fix anchor respawn acting as a bed respawn from the end portal + cserver.getPluginManager().callEvent(respawnEvent); + // Spigot Start + if (entityplayer.connection.isDisconnected()) { diff --git a/Remapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch b/Remapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch new file mode 100644 index 0000000000..57b84d6df6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spyridon Pagkalos +Date: Thu, 25 Mar 2021 20:28:04 +0200 +Subject: [PATCH] Introduce beacon activation/deactivation events + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +index fed29e5707e2a7f64159d284c52647dd91e1948e..7025a27c25f8640df06a3c65c2086059769870b5 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -199,6 +199,15 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + this.playSound(SoundEvents.BEACON_AMBIENT); + } + } ++ // Paper start - beacon activation/deactivation events ++ if (!(i1 > 0) && this.levels > 0) { ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); ++ new io.papermc.paper.event.block.BeaconActivatedEvent(block).callEvent(); ++ } else if (i1 > 0 && !(this.levels > 0)) { ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); ++ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); ++ } ++ // Paper end + + if (this.lastCheckY >= l) { + this.lastCheckY = -1; +@@ -255,6 +264,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + + @Override + public void setRemoved() { ++ // Paper start - BeaconDeactivatedEvent ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); ++ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); ++ // Paper end + this.playSound(SoundEvents.BEACON_DEACTIVATE); + super.setRemoved(); + } diff --git a/Remapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch b/Remapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch new file mode 100644 index 0000000000..72cbb09b5a --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Thu, 29 Apr 2021 21:19:33 +0200 +Subject: [PATCH] Add Channel initialization listeners + + +diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java +new file mode 100644 +index 0000000000000000000000000000000000000000..88099df34c2d74daba9645aadf65b446ca795a91 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java +@@ -0,0 +1,15 @@ ++package io.papermc.paper.network; ++ ++import io.netty.channel.Channel; ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++/** ++ * Internal API to register channel initialization listeners. ++ *

    ++ * This is not officially supported API and we make no guarantees to the existence or state of this interface. ++ */ ++@FunctionalInterface ++public interface ChannelInitializeListener { ++ ++ void afterInitChannel(@NonNull Channel channel); ++} +diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..30e62719e0a83525daa33cf41cb61df360c0e046 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java +@@ -0,0 +1,74 @@ ++package io.papermc.paper.network; ++ ++import io.netty.channel.Channel; ++import net.kyori.adventure.key.Key; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++ ++import java.util.Collections; ++import java.util.HashMap; ++import java.util.Map; ++ ++/** ++ * Internal API to register channel initialization listeners. ++ *

    ++ * This is not officially supported API and we make no guarantees to the existence or state of this class. ++ */ ++public final class ChannelInitializeListenerHolder { ++ ++ private static final Map LISTENERS = new HashMap<>(); ++ private static final Map IMMUTABLE_VIEW = Collections.unmodifiableMap(LISTENERS); ++ ++ private ChannelInitializeListenerHolder() { ++ } ++ ++ /** ++ * Registers whether an initialization listener is registered under the given key. ++ * ++ * @param key key ++ * @return whether an initialization listener is registered under the given key ++ */ ++ public static boolean hasListener(@NonNull Key key) { ++ return LISTENERS.containsKey(key); ++ } ++ ++ /** ++ * Registers a channel initialization listener called after ServerConnection is initialized. ++ * ++ * @param key key ++ * @param listener initialization listeners ++ */ ++ public static void addListener(@NonNull Key key, @NonNull ChannelInitializeListener listener) { ++ LISTENERS.put(key, listener); ++ } ++ ++ /** ++ * Removes and returns an initialization listener registered by the given key if present. ++ * ++ * @param key key ++ * @return removed initialization listener if present ++ */ ++ public static @Nullable ChannelInitializeListener removeListener(@NonNull Key key) { ++ return LISTENERS.remove(key); ++ } ++ ++ /** ++ * Returns an immutable map of registered initialization listeners. ++ * ++ * @return immutable map of registered initialization listeners ++ */ ++ public static @NonNull Map getListeners() { ++ return IMMUTABLE_VIEW; ++ } ++ ++ /** ++ * Calls the registered listeners with the given channel. ++ * ++ * @param channel channel ++ */ ++ public static void callListeners(@NonNull Channel channel) { ++ for (ChannelInitializeListener listener : LISTENERS.values()) { ++ listener.afterInitChannel(channel); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +index d46910cfdc0aef046a0c79731a85d381953c328a..bcc19d0a4b6c5f683dc416e27a13705b57213d21 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +@@ -104,6 +104,7 @@ public class ServerConnectionListener { + pending.add((Connection) object); // Paper + channel.pipeline().addLast("packet_handler", (ChannelHandler) object); + ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); ++ io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper + } + }).group((EventLoopGroup) lazyinitvar.get()).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit + } diff --git a/Remapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch b/Remapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch new file mode 100644 index 0000000000..de0a65c719 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Mon, 26 Apr 2021 01:27:08 +0100 +Subject: [PATCH] Send empty commands if tab completion is disabled + + +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index e2f18b5bf1e091fe5fd868520a6d1bcc2669c24c..1d880a80348527d036b6f8b04f7dd1c4a479fcfd 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -327,7 +327,12 @@ public class Commands { + } + + public void sendCommands(ServerPlayer player) { +- if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot ++ // Paper start - Send empty commands if tab completion is disabled ++ if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) { //return; // Spigot ++ player.connection.send(new ClientboundCommandsPacket(new RootCommandNode<>())); ++ return; ++ } ++ // Paper end + // CraftBukkit start + // Register Vanilla commands into builtRoot as before + // Paper start - Async command map building diff --git a/Remapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch b/Remapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch new file mode 100644 index 0000000000..b99c0c4512 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Thu, 6 May 2021 14:56:43 +0100 +Subject: [PATCH] Add more WanderingTrader API + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +index 04c4cca4be8886feb59f180915977b77f9c7dde8..22a695ee3f6c60d484285f1b441b809da61f2436 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -57,6 +57,10 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + @Nullable + private BlockPos wanderTarget; + private int despawnDelay; ++ // Paper start - Add more WanderingTrader API ++ public boolean canDrinkPotion = true; ++ public boolean canDrinkMilk = true; ++ // Paper end + + public WanderingTrader(EntityType type, Level world) { + super(type, world); +@@ -68,10 +72,10 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(0, new UseItemGoal<>(this, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEvents.WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { +- return this.world.isNight() && !entityvillagertrader.isInvisible(); ++ return canDrinkPotion && this.world.isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API + })); + this.goalSelector.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { +- return this.level.isDay() && entityvillagertrader.isInvisible(); ++ return canDrinkMilk && this.level.isDay() && entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API + })); + this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this)); + this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zombie.class, 8.0F, 0.5D, 0.5D)); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java +index a00b1ee5d80d3918ece2260dc1360aa90de16c8a..de58fc26bd811e87cd393bdecee796faf72e65e1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java +@@ -34,4 +34,26 @@ public class CraftWanderingTrader extends CraftAbstractVillager implements Wande + public void setDespawnDelay(int despawnDelay) { + getHandle().setDespawnDelay(despawnDelay); + } ++ ++ // Paper start - Add more WanderingTrader API ++ @Override ++ public void setCanDrinkPotion(boolean bool) { ++ getHandle().canDrinkPotion = bool; ++ } ++ ++ @Override ++ public boolean canDrinkPotion() { ++ return getHandle().canDrinkPotion; ++ } ++ ++ @Override ++ public void setCanDrinkMilk(boolean bool) { ++ getHandle().canDrinkMilk = bool; ++ } ++ ++ @Override ++ public boolean canDrinkMilk() { ++ return getHandle().canDrinkMilk; ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch b/Remapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch new file mode 100644 index 0000000000..530ee44dcf --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Mon, 5 Apr 2021 18:12:29 -0400 +Subject: [PATCH] Add EntityBlockStorage#clearEntities() + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +index cbd0587eeecf14b1914bdb33f7a4584bd6b5c8d0..83e5367ee1126afe31e9f704a0daedd310339d15 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +@@ -120,6 +120,11 @@ public class BeehiveBlockEntity extends BlockEntity implements TickableBlockEnti + return this.stored.size(); + } + ++ // Paper start - Add EntityBlockStorage clearEntities ++ public void clearBees() { ++ this.stored.clear(); ++ } ++ // Paper end + public static int getHoneyLevel(BlockState state) { + return (Integer) state.getValue(BeehiveBlock.HONEY_LEVEL); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java +index e61ea9c7fb711e8335a5d0fd5a8bc0152a225038..3346a1962a992566fe840fd0a75cfa06f694833a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java +@@ -83,4 +83,10 @@ public class CraftBeehive extends CraftBlockEntityState impl + + getSnapshot().addOccupant(((CraftBee) entity).getHandle(), false); + } ++ // Paper start - Add EntityBlockStorage clearEntities ++ @Override ++ public void clearEntities() { ++ getSnapshot().clearBees(); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/Remapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch new file mode 100644 index 0000000000..9006bd8edb --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alvinn8 <42838560+Alvinn8@users.noreply.github.com> +Date: Fri, 8 Jan 2021 20:31:13 +0100 +Subject: [PATCH] Add Adventure message to PlayerAdvancementDoneEvent + + +diff --git a/src/main/java/net/minecraft/advancements/Advancement.java b/src/main/java/net/minecraft/advancements/Advancement.java +index 9d27b658d32297337fb367bae628a1cc3a78712a..4abbe45237667c08753c040ef1281af1b2f34f88 100644 +--- a/src/main/java/net/minecraft/advancements/Advancement.java ++++ b/src/main/java/net/minecraft/advancements/Advancement.java +@@ -76,6 +76,7 @@ public class Advancement { + return this.parent; + } + ++ public final @Nullable DisplayInfo getAdvancementDisplay() { return this.getDisplay(); } // Paper - OBFHELPER + @Nullable + public DisplayInfo getDisplay() { + return this.display; +@@ -125,6 +126,7 @@ public class Advancement { + return this.requirements; + } + ++ public final Component getChatComponent() { return this.getChatComponent(); } // Paper - OBFHELPER + public Component getChatComponent() { + return this.chatComponent; + } +diff --git a/src/main/java/net/minecraft/advancements/DisplayInfo.java b/src/main/java/net/minecraft/advancements/DisplayInfo.java +index 2bcf14826ec1c6a1654246844d03184ceae55d79..1b41578fed1da6d15a806a7200e53954f608b625 100644 +--- a/src/main/java/net/minecraft/advancements/DisplayInfo.java ++++ b/src/main/java/net/minecraft/advancements/DisplayInfo.java +@@ -54,10 +54,12 @@ public class DisplayInfo { + return this.description; + } + ++ public final FrameType getFrameType() { return this.getFrame(); } // Paper - OBFHELPER + public FrameType getFrame() { + return this.frame; + } + ++ public final boolean shouldAnnounceToChat() { return this.shouldAnnounceChat(); } // Paper - OBFHELPER + public boolean shouldAnnounceChat() { + return this.announceChat; + } +diff --git a/src/main/java/net/minecraft/advancements/FrameType.java b/src/main/java/net/minecraft/advancements/FrameType.java +index 0ccac480a760259412b525e66c43de3a209543f5..f6d4b876bdd25942763780f17c8bb69ac3d56031 100644 +--- a/src/main/java/net/minecraft/advancements/FrameType.java ++++ b/src/main/java/net/minecraft/advancements/FrameType.java +@@ -20,6 +20,7 @@ public enum FrameType { + this.displayName = new TranslatableComponent("advancements.toast." + s); + } + ++ public final String getId() { return this.getName(); } // Paper - OBFHELPER + public String getName() { + return this.name; + } +diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index b8d3f2c59199e245e2035d6205dd1a042aa93f77..fcb59f6538e66fa43d11d4998e6eeac2e33b0393 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -51,6 +51,7 @@ import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.level.GameRules; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + + public class PlayerAdvancements { + +@@ -313,10 +314,18 @@ public class PlayerAdvancements { + this.progressChanged.add(advancement); + flag = true; + if (!flag1 && advancementprogress.isDone()) { +- this.player.level.getCraftServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit)); // CraftBukkit ++ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent ++ boolean announceToChat = advancement.getAdvancementDisplay() != null && advancement.getAdvancementDisplay().shouldAnnounceToChat(); ++ net.kyori.adventure.text.Component message = announceToChat ? PaperAdventure.asAdventure(new TranslatableComponent("chat.type.advancement." + advancement.getAdvancementDisplay().getFrameType().getId(), this.player.getDisplayName(), advancement.getChatComponent())) : null; ++ org.bukkit.event.player.PlayerAdvancementDoneEvent event = new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit, message); ++ this.player.level.getCraftServer().getPluginManager().callEvent(event); ++ message = event.message(); ++ // Paper end + advancement.getRewards().a(this.player); +- if (advancement.getDisplay() != null && advancement.getDisplay().shouldAnnounceChat() && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { +- this.playerList.broadcastMessage(new TranslatableComponent("chat.type.advancement." + advancement.getDisplay().getFrame().getName(), new Object[]{this.player.getDisplayName(), advancement.getChatComponent()}), ChatType.SYSTEM, Util.NIL_UUID); ++ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent ++ if (message != null && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { ++ this.playerList.broadcastMessage(PaperAdventure.asVanilla(message), ChatType.SYSTEM, Util.getNullUUID()); ++ // Paper end + } + } + } diff --git a/Remapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/Remapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch new file mode 100644 index 0000000000..a376cbbc19 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Connor Linfoot +Date: Wed, 12 May 2021 08:09:19 +0100 +Subject: [PATCH] Add raw address to AsyncPlayerPreLoginEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 573963a09f15046cfcaab83aef906801ce70d75a..99275a8bc2e7bf242ff3c5b5c29924af5328327a 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -325,12 +325,13 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + // Paper end + String playerName = gameProfile.getName(); + java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); ++ java.net.InetAddress rawAddress = ((java.net.InetSocketAddress) connection.getRawAddress()).getAddress(); // Paper + java.util.UUID uniqueId = gameProfile.getId(); + final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; + + // Paper start + PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); +- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); ++ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile); + server.getPluginManager().callEvent(asyncEvent); + profile = asyncEvent.getPlayerProfile(); + profile.complete(true); diff --git a/Remapped-Spigot-Server-Patches/0726-Inventory-close.patch b/Remapped-Spigot-Server-Patches/0726-Inventory-close.patch new file mode 100644 index 0000000000..f206ea0fbd --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0726-Inventory-close.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 11 May 2021 14:54:56 -0700 +Subject: [PATCH] Inventory#close + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +index 7ccc085228f373e6eba55d809bed480d43d5c211..16d34f44e92e26d13188417942f444952f98dfa1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +@@ -448,6 +448,14 @@ public class CraftInventory implements Inventory { + clear(i); + } + } ++ // Paper start ++ @Override ++ public int close() { ++ int count = this.inventory.getViewers().size(); ++ com.google.common.collect.Lists.newArrayList(this.inventory.getViewers()).forEach(HumanEntity::closeInventory); ++ return count; ++ } ++ // Paper end + + @Override + public ListIterator iterator() { diff --git a/Remapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch b/Remapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch new file mode 100644 index 0000000000..4776fc7a79 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 12 May 2021 03:21:22 -0700 +Subject: [PATCH] call PortalCreateEvent players and end platform + + +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 727af6ac84075db87615ebac51a024e6376fa3cb..6e2a272075ead399004dabfb7d4f0ea5fd32ffc2 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -496,6 +496,7 @@ public class BlockPos extends Vec3i { + return this.set(this.getX() + direction.getStepX() * distance, this.getY() + direction.getStepY() * distance, this.getZ() + direction.getStepZ() * distance); + } + ++ public BlockPos.MutableBlockPos withOffset(int x, int y, int z) { return move(x, y, z); } // Paper - OBFHELPER + public BlockPos.MutableBlockPos move(int dx, int dy, int dz) { + return this.set(this.getX() + dx, this.getY() + dy, this.getZ() + dz); + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 314f168c9d17ab3654c9dda07e48839570f0d332..5d710a1f4e0c61d4be6efe8cebd9b80789868338 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1142,15 +1142,21 @@ public class ServerPlayer extends Player implements ContainerListener { + private void createEndPlatform(ServerLevel world, BlockPos centerPos) { + BlockPos.MutableBlockPos blockposition_mutableblockposition = centerPos.mutable(); + ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(world); // Paper + for (int i = -2; i <= 2; ++i) { + for (int j = -2; j <= 2; ++j) { + for (int k = -1; k < 3; ++k) { + BlockState iblockdata = k == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); + +- world.setBlockAndUpdate(blockposition_mutableblockposition.set(centerPos).move(j, k, i), iblockdata); ++ blockList.setBlock(blockposition_mutableblockposition.setValues(centerPos).withOffset(j, k, i), iblockdata, 3); // Paper + } + } + } ++ // Paper start ++ if (new org.bukkit.event.world.PortalCreateEvent((List< org.bukkit.block.BlockState>) (List) blockList.getList(), world.getWorld(), this.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM).callEvent()) { ++ blockList.updateList(); ++ } ++ // Paper end + + } + diff --git a/Remapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/Remapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch new file mode 100644 index 0000000000..fb4c1ca38d --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch @@ -0,0 +1,126 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Tue, 11 May 2021 00:48:33 +0200 +Subject: [PATCH] Add a "should burn in sunlight" API for Phantoms and + Skeletons + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +index 68e52e3a31e70569d1a92602aff4b7b81c594757..a8a0dba43453b7ac73e8e0faf7728445d9bcc2cd 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -98,9 +98,15 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + return MobType.UNDEAD; + } + ++ // Paper start ++ private boolean shouldBurnInDay = true; ++ public boolean shouldBurnInDay() { return shouldBurnInDay; } ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } ++ // Paper end ++ + @Override + public void aiStep() { +- boolean flag = this.isSunBurnTick(); ++ boolean flag = shouldBurnInDay && this.isSunBurnTick(); // Paper - Configurable Burning + + if (flag) { + ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); +@@ -224,7 +230,16 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + public void readAdditionalSaveData(CompoundTag tag) { + super.readAdditionalSaveData(tag); + this.reassessWeaponGoal(); ++ this.shouldBurnInDay = tag.getBoolean("Paper.ShouldBurnInDay"); // Paper ++ } ++ ++ // Paper start ++ @Override ++ public void addAdditionalSaveData(CompoundTag tag) { ++ super.addAdditionalSaveData(tag); ++ tag.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); + } ++ // Paper end + + @Override + public void setItemSlot(EquipmentSlot slot, ItemStack stack) { +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index a40c23e824652cff59633b7c314e27ec9a515c07..8f4dd4540330966689e71568e9e9ef77f82a786a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -134,7 +134,7 @@ public class Phantom extends FlyingMob implements Enemy { + + @Override + public void aiStep() { +- if (this.isAlive() && this.isSunBurnTick()) { ++ if (this.isAlive() && shouldBurnInDay && this.isSunBurnTick()) { // Paper - Configurable Burning + this.setSecondsOnFire(8); + } + +@@ -165,6 +165,7 @@ public class Phantom extends FlyingMob implements Enemy { + if (tag.hasUUID("Paper.SpawningEntity")) { + this.spawningEntity = tag.getUUID("Paper.SpawningEntity"); + } ++ this.shouldBurnInDay = tag.getBoolean("Paper.ShouldBurnInDay"); + // Paper end + } + +@@ -179,6 +180,7 @@ public class Phantom extends FlyingMob implements Enemy { + if (this.spawningEntity != null) { + tag.setUUID("Paper.SpawningEntity", this.spawningEntity); + } ++ tag.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); + // Paper end + } + +@@ -233,6 +235,10 @@ public class Phantom extends FlyingMob implements Enemy { + return spawningEntity; + } + public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } ++ ++ private boolean shouldBurnInDay = true; ++ public boolean shouldBurnInDay() { return shouldBurnInDay; } ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } + // Paper end + + class PhantomAttackPlayerTargetGoal extends Goal { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +index 92162fa22f5e98b7837bde5830bd47c31b8b52d8..011ad2224a3a3a2d255b2498e406fbb047359240 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +@@ -39,5 +39,15 @@ public class CraftPhantom extends CraftFlying implements Phantom { + public java.util.UUID getSpawningEntity() { + return getHandle().getSpawningEntity(); + } ++ ++ @Override ++ public boolean shouldBurnInDay() { ++ return getHandle().shouldBurnInDay(); ++ } ++ ++ @Override ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { ++ getHandle().setShouldBurnInDay(shouldBurnInDay); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +index b2d3244cca4d9d108159f3537d8a9aace3f8e77f..28dda8beb1793fad47b2c9db815c0b6cf6ed781a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +@@ -36,4 +36,16 @@ public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroy + public void setSkeletonType(SkeletonType type) { + throw new UnsupportedOperationException("Not supported."); + } ++ ++ // Paper start ++ @Override ++ public boolean shouldBurnInDay() { ++ return getHandle().shouldBurnInDay(); ++ } ++ ++ @Override ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { ++ getHandle().setShouldBurnInDay(shouldBurnInDay); ++ } ++ // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch b/Remapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch new file mode 100644 index 0000000000..140b30b682 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sceri +Date: Fri, 14 May 2021 19:06:51 +0500 +Subject: [PATCH] Fix CraftPotionBrewer cache + + +diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java +index e20d96ec67dcbe935357b4de7e0e9a6984dc3303..eb28a055ba60bb1da3412cf0dbbe5ce76a779f38 100644 +--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java ++++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java +@@ -15,12 +15,18 @@ import org.bukkit.potion.PotionEffectType; + import org.bukkit.potion.PotionType; + + public class CraftPotionBrewer implements PotionBrewer { +- private static final Map> cache = Maps.newHashMap(); ++ private static final Map> cache = Maps.newHashMap(); // Paper + + @Override + public Collection getEffects(PotionType damage, boolean upgraded, boolean extended) { +- if (cache.containsKey(damage)) +- return cache.get(damage); ++ // Paper start ++ int key = damage.ordinal() << 2; ++ key |= (upgraded ? 1 : 0) << 1; ++ key |= extended ? 1 : 0; ++ ++ if (cache.containsKey(key)) ++ return cache.get(key); ++ // Paper end + + List mcEffects = Potion.byName(CraftPotionUtil.fromBukkit(new PotionData(damage, extended, upgraded))).getEffects(); + +@@ -29,9 +35,9 @@ public class CraftPotionBrewer implements PotionBrewer { + builder.add(CraftPotionUtil.toBukkit(effect)); + } + +- cache.put(damage, builder.build()); ++ cache.put(key, builder.build()); // Paper + +- return cache.get(damage); ++ return cache.get(key); // Paper + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch b/Remapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch new file mode 100644 index 0000000000..547e7cb557 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch @@ -0,0 +1,174 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Connor Linfoot +Date: Sun, 16 May 2021 15:07:34 +0100 +Subject: [PATCH] Add basic Datapack API + + +diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java +new file mode 100644 +index 0000000000000000000000000000000000000000..66debefcd474e4dcc2a8889a82af6c1809c93f46 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java +@@ -0,0 +1,51 @@ ++package io.papermc.paper.datapack; ++ ++import Compatibility; ++import io.papermc.paper.event.server.ServerResourcesReloadedEvent; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.packs.repository.Pack; ++import java.util.List; ++import java.util.stream.Collectors; ++ ++public class PaperDatapack implements Datapack { ++ private final String name; ++ private final Compatibility compatibility; ++ private final boolean enabled; ++ ++ PaperDatapack(Pack loader, boolean enabled) { ++ this.name = loader.getName(); ++ this.compatibility = Compatibility.valueOf(loader.getVersion().name()); ++ this.enabled = enabled; ++ } ++ ++ @Override ++ public String getName() { ++ return name; ++ } ++ ++ @Override ++ public Compatibility getCompatibility() { ++ return compatibility; ++ } ++ ++ @Override ++ public boolean isEnabled() { ++ return enabled; ++ } ++ ++ @Override ++ public void setEnabled(boolean enabled) { ++ if (enabled == this.enabled) { ++ return; ++ } ++ ++ MinecraftServer server = MinecraftServer.getServer(); ++ List enabledKeys = server.getPackRepository().getEnabledPacks().stream().map(Pack::getName).collect(Collectors.toList()); ++ if (enabled) { ++ enabledKeys.add(this.name); ++ } else { ++ enabledKeys.remove(this.name); ++ } ++ server.reloadServerResources(enabledKeys, ServerResourcesReloadedEvent.Cause.PLUGIN); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ec221183bef1065bda0a37e1025958df0d1f6318 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java +@@ -0,0 +1,25 @@ ++package io.papermc.paper.datapack; ++ ++import java.util.Collection; ++import java.util.stream.Collectors; ++import net.minecraft.server.packs.repository.Pack; ++import net.minecraft.server.packs.repository.PackRepository; ++ ++public class PaperDatapackManager implements DatapackManager { ++ private final PackRepository repository; ++ ++ public PaperDatapackManager(PackRepository repository) { ++ this.repository = repository; ++ } ++ ++ @Override ++ public Collection getPacks() { ++ Collection enabledPacks = repository.getEnabledPacks(); ++ return repository.getPacks().stream().map(loader -> new PaperDatapack(loader, enabledPacks.contains(loader))).collect(Collectors.toList()); ++ } ++ ++ @Override ++ public Collection getEnabledPacks() { ++ return repository.getEnabledPacks().stream().map(loader -> new PaperDatapack(loader, true)).collect(Collectors.toList()); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/packs/repository/Pack.java b/src/main/java/net/minecraft/server/packs/repository/Pack.java +index df5d258b80e37077fa236e4190ad934853c88619..4120326e0d047347e5d7ab9521babe7bb6b6a7db 100644 +--- a/src/main/java/net/minecraft/server/packs/repository/Pack.java ++++ b/src/main/java/net/minecraft/server/packs/repository/Pack.java +@@ -101,6 +101,7 @@ public class Pack implements AutoCloseable { + }); + } + ++ public final PackCompatibility getVersion() { return this.getCompatibility(); } // Paper - OBFHELPER + public PackCompatibility getCompatibility() { + return this.compatibility; + } +@@ -109,6 +110,7 @@ public class Pack implements AutoCloseable { + return (PackResources) this.supplier.get(); + } + ++ public final String getName() { return this.getId(); } // Paper - OBFHELPER + public String getId() { + return this.id; + } +diff --git a/src/main/java/net/minecraft/server/packs/repository/PackRepository.java b/src/main/java/net/minecraft/server/packs/repository/PackRepository.java +index bce2fd67048bd1fd53865eef81bac262dbda2865..8d0ef3bdf9fa283f54628800768717181df28aa5 100644 +--- a/src/main/java/net/minecraft/server/packs/repository/PackRepository.java ++++ b/src/main/java/net/minecraft/server/packs/repository/PackRepository.java +@@ -88,6 +88,7 @@ public class PackRepository implements AutoCloseable { + return this.available.keySet(); + } + ++ public final Collection getPacks() { return this.getAvailablePacks(); } // Paper - OBFHELPER + public Collection getAvailablePacks() { + return this.available.values(); + } +@@ -96,6 +97,7 @@ public class PackRepository implements AutoCloseable { + return (Collection) this.selected.stream().map(Pack::getId).collect(ImmutableSet.toImmutableSet()); + } + ++ public final Collection getEnabledPacks() { return this.getSelectedPacks(); } // Paper - OBFHELPER + public Collection getSelectedPacks() { + return this.selected; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 6905256147d9bd79e5f52bf86bdb21c89b8411a7..63639923f7875d76f569b8c6e958782c6462d906 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -18,6 +18,7 @@ import com.mojang.serialization.Lifecycle; + import io.netty.buffer.ByteBuf; + import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; ++import io.papermc.paper.datapack.PaperDatapackManager; // Paper + import io.papermc.paper.util.TraceUtil; + import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; + import java.awt.image.BufferedImage; +@@ -264,6 +265,7 @@ public final class CraftServer implements Server { + public boolean ignoreVanillaPermissions = false; + private final List playerView; + public int reloadCount; ++ private final PaperDatapackManager datapackManager; // Paper + public static Exception excessiveVelEx; // Paper - Velocity warnings + + static { +@@ -346,6 +348,7 @@ public final class CraftServer implements Server { + TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + minimumAPI = configuration.getString("settings.minimum-api"); + loadIcon(); ++ datapackManager = new PaperDatapackManager(console.getPackRepository()); // Paper + } + + public boolean getCommandBlockOverride(String command) { +@@ -2496,5 +2499,11 @@ public final class CraftServer implements Server { + public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { + return mobGoals; + } ++ ++ @Override ++ public PaperDatapackManager getDatapackManager() { ++ return datapackManager; ++ } ++ + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch b/Remapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch new file mode 100644 index 0000000000..a1f57cca90 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Riley Park +Date: Mon, 17 May 2021 00:34:55 -0700 +Subject: [PATCH] Add environment variable to disable server gui + + +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 9dc9a5e6ad7f23c8bf3553c765ceeecd67a49ac1..ba6c17da4875c3a342da99e354c9f07cc7f17326 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -225,6 +225,7 @@ public class Main { + */ + boolean flag1 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui"); + ++ if(!Boolean.parseBoolean(System.getenv().getOrDefault("PAPER_DISABLE_SERVER_GUI", String.valueOf(false)))) // Paper + if (flag1 && !GraphicsEnvironment.isHeadless()) { + dedicatedserver1.showGui(); + } diff --git a/Remapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch b/Remapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch new file mode 100644 index 0000000000..31a8669378 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch @@ -0,0 +1,138 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 10:04:43 -0700 +Subject: [PATCH] additions to PlayerGameModeChangeEvent + + +diff --git a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java +index c0098a8f8a9fa2671ff66cbcf50ac74b057d1446..ebbd6f2b0e7236b33d136ab2218c8eca4c5df03e 100644 +--- a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java ++++ b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java +@@ -43,7 +43,13 @@ public class DefaultGameModeCommands { + ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + + if (entityplayer.gameMode.getGameModeForPlayer() != defaultGameMode) { +- entityplayer.setGameMode(defaultGameMode); ++ // Paper start - handle event cancelling the change ++ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(defaultGameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getScoreboardName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); ++ if (event != null && event.isCancelled()) { ++ source.sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); ++ continue; ++ } ++ // Paper end + ++i; + } + } +diff --git a/src/main/java/net/minecraft/server/commands/GameModeCommand.java b/src/main/java/net/minecraft/server/commands/GameModeCommand.java +index 3e999090fb3b03b996a9790c53e5b4618c8891f7..3b17c81167f8e011e7f9c09bf42eb632f5a3c2f2 100644 +--- a/src/main/java/net/minecraft/server/commands/GameModeCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GameModeCommand.java +@@ -62,13 +62,13 @@ public class GameModeCommand { + ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + + if (entityplayer.gameMode.getGameModeForPlayer() != gameMode) { +- entityplayer.setGameMode(gameMode); +- // CraftBukkit start - handle event cancelling the change +- if (entityplayer.gameMode.getGameModeForPlayer() != gameMode) { +- context.getSource().sendFailure(new net.minecraft.network.chat.TextComponent("Failed to set the gamemode of '" + entityplayer.getScoreboardName() + "'")); ++ // Paper start - handle event cancelling the change ++ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getScoreboardName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); ++ if (event != null && event.isCancelled()) { ++ context.getSource().sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); + continue; + } +- // CraftBukkit end ++ // Paper end + logGamemodeChange((CommandSourceStack) context.getSource(), entityplayer, gameMode); + ++i; + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 5d710a1f4e0c61d4be6efe8cebd9b80789868338..779b926921fd435620cbbc69ed6f9931a422b652 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -393,7 +393,16 @@ public class ServerPlayer extends Player implements ContainerListener { + if (this.getY() > 300) this.setPosRaw(getX(), 257, getZ()); // Paper - bring down to a saner Y level if out of world + if (tag.contains("playerGameType", 99)) { + if (this.getServer().getForceGameType()) { ++ // Paper start - call PlayerGameModeChangeEvent on join for players that do not have the correct gamemode ++ if (this.getServer().getDefaultGameType() != GameType.byId(tag.getInt("playerGameType"))) { ++ if (new org.bukkit.event.player.PlayerGameModeChangeEvent(this.getBukkitEntity(), GameMode.getByValue(this.getServer().getDefaultGameType().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) { + this.gameMode.setGameModeForPlayer(this.getServer().getDefaultGameType(), GameType.NOT_SET); ++ } else { ++ this.gameMode.setGameModeForPlayer(GameType.byId(tag.getInt("playerGameType")), tag.contains("previousPlayerGameType", 3) ? GameType.byId(tag.getInt("previousPlayerGameType")) : GameType.NOT_SET); // copied from below; if cancelled, set gamemode normally ++ } ++ } else { ++ this.gameMode.setGameModeForPlayer(GameType.byId(tag.getInt("playerGameType")), tag.contains("previousPlayerGameType", 3) ? GameType.byId(tag.getInt("previousPlayerGameType")) : GameType.NOT_SET); // copied from below; if no change needed, set gamemode normally ++ } // Paper end + } else { + this.gameMode.setGameModeForPlayer(GameType.byId(tag.getInt("playerGameType")), tag.contains("previousPlayerGameType", 3) ? GameType.byId(tag.getInt("previousPlayerGameType")) : GameType.NOT_SET); + } +@@ -1789,21 +1798,27 @@ public class ServerPlayer extends Player implements ContainerListener { + + @Override + public void setGameMode(GameType gameMode) { ++ // Paper start - Add cause and nullable message to event ++ setGamemode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null); ++ } ++ ++ public PlayerGameModeChangeEvent setGamemode(GameType enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component message) { ++ // Paper end + // CraftBukkit start +- if (gameMode == this.gameMode.getGameModeForPlayer()) { +- return; ++ if (enumgamemode == this.gameMode.getGameModeForPlayer()) { ++ return null; // Paper + } + +- PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(gameMode.getId())); ++ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(enumgamemode.getId()), cause, message); // Paper + level.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { +- return; ++ return event; // Paper + } + // CraftBukkit end + +- this.gameMode.setGameModeForPlayer(gameMode); +- this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) gameMode.getId())); +- if (gameMode == GameType.SPECTATOR) { ++ this.gameMode.setGameModeForPlayer(enumgamemode); ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) enumgamemode.getId())); ++ if (enumgamemode == GameType.SPECTATOR) { + this.removeEntitiesOnShoulder(); + this.stopRiding(); + } else { +@@ -1812,6 +1827,7 @@ public class ServerPlayer extends Player implements ContainerListener { + + this.onUpdateAbilities(); + this.updateEffectVisibility(); ++ return event; // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index a0e69cac7699ddc318057c8016e329850d3baa26..c454908f23a436f66f8e64fc346186f113b6eefb 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2449,7 +2449,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + this.player = this.server.getPlayerList().respawn(this.player, false); + if (this.server.isHardcore()) { +- this.player.setGameMode(GameType.SPECTATOR); ++ this.player.setGamemode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper + ((GameRules.BooleanValue) this.player.getLevel().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, this.server); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index ec8c7499662c0a810f1337ebc0fa24d2f3ca79e7..3dbe94d9b9647f5cc1e27335b36042e50c652cea 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1189,7 +1189,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + throw new IllegalArgumentException("Mode cannot be null"); + } + +- getHandle().setGameMode(GameType.byId(mode.getValue())); ++ getHandle().setGamemode(GameType.byId(mode.getValue()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.PLUGIN, null); // Paper + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch b/Remapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch new file mode 100644 index 0000000000..74dbd3c778 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 22:11:11 -0700 +Subject: [PATCH] ItemStack repair check API + + +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index cb079bfd5339b96ad372b0a3b483d02cd0636bfd..42085d3f4ae5c6ceecaffde79fb3187712a2af00 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -269,6 +269,7 @@ public class Item implements ItemLike { + return this.category; + } + ++ public boolean canRepair(ItemStack toBeRepaired, ItemStack repairMaterial) { return isValidRepairItem(toBeRepaired, repairMaterial); } // Paper - OBFHELPER + public boolean isValidRepairItem(ItemStack stack, ItemStack ingredient) { + return false; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 402e5a98290a1701dd67d27c484c97e0a6067c4f..34eed57c7ed884e0d634ca403e38d25c95b6a038 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -485,6 +485,14 @@ public final class CraftMagicNumbers implements UnsafeValues { + return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; + } + ++ @Override ++ public boolean isValidRepairItemStack(org.bukkit.inventory.ItemStack itemToBeRepaired, org.bukkit.inventory.ItemStack repairMaterial) { ++ if (!itemToBeRepaired.getType().isItem() || !repairMaterial.getType().isItem()) { ++ return false; ++ } ++ return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); ++ } ++ + @Override + public int getProtocolVersion() { + return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion(); +diff --git a/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8d9c9b3bd53d407391d4fcb7fc773153d1a7b402 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java +@@ -0,0 +1,48 @@ ++package io.papermc.paper.util; ++ ++import org.bukkit.Material; ++import org.bukkit.inventory.ItemStack; ++import org.bukkit.support.AbstractTestingBase; ++import org.junit.Test; ++ ++import static org.junit.Assert.assertFalse; ++import static org.junit.Assert.assertThrows; ++import static org.junit.Assert.assertTrue; ++ ++public class ItemStackRepairCheckTest extends AbstractTestingBase { ++ ++ @Test ++ public void testIsRepariableBy() { ++ ItemStack diamondPick = new ItemStack(Material.DIAMOND_PICKAXE); ++ ++ assertTrue("diamond pick isn't repairable by a diamond", diamondPick.isRepairableBy(new ItemStack(Material.DIAMOND))); ++ } ++ ++ @Test ++ public void testCanRepair() { ++ ItemStack diamond = new ItemStack(Material.DIAMOND); ++ ++ assertTrue("diamond can't repair a diamond axe", diamond.canRepair(new ItemStack(Material.DIAMOND_AXE))); ++ } ++ ++ @Test ++ public void testIsNotRepairableBy() { ++ ItemStack notDiamondPick = new ItemStack(Material.ACACIA_SAPLING); ++ ++ assertFalse("acacia sapling is repairable by a diamond", notDiamondPick.isRepairableBy(new ItemStack(Material.DIAMOND))); ++ } ++ ++ @Test ++ public void testCanNotRepair() { ++ ItemStack diamond = new ItemStack(Material.DIAMOND); ++ ++ assertFalse("diamond can repair oak button", diamond.canRepair(new ItemStack(Material.OAK_BUTTON))); ++ } ++ ++ @Test ++ public void testInvalidItem() { ++ ItemStack badItemStack = new ItemStack(Material.ACACIA_WALL_SIGN); ++ ++ assertFalse("acacia wall sign is repairable by diamond", badItemStack.isRepairableBy(new ItemStack(Material.DIAMOND))); ++ } ++} diff --git a/Remapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch b/Remapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch new file mode 100644 index 0000000000..4bf44e22d8 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch @@ -0,0 +1,211 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 6 May 2021 19:57:58 -0700 +Subject: [PATCH] More Enchantment API + + +diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +index c23ec1b31950471905c65e46273ae105de853d9b..b994a7aca0ce01b5c0d44b9b126295ffcd2f795d 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +@@ -17,7 +17,7 @@ import net.minecraft.world.item.ItemStack; + + public abstract class Enchantment { + +- private final EquipmentSlot[] slots; ++ private final EquipmentSlot[] slots; public final EquipmentSlot[] getSlots() { return this.slots; } // Paper - OBFHELPER + private final Enchantment.Rarity rarity; + public final EnchantmentCategory category; + @Nullable +@@ -46,6 +46,7 @@ public abstract class Enchantment { + return map; + } + ++ public Enchantment.Rarity getRarity() { return getRarity(); } // Paper - OBFHELPER + public Enchantment.Rarity getRarity() { + return this.rarity; + } +@@ -70,6 +71,7 @@ public abstract class Enchantment { + return 0; + } + ++ public float getDamageIncrease(int level, MobType enumMonsterType) { return getDamageBonus(level, enumMonsterType); } // Paper - OBFHELPER + public float getDamageBonus(int level, MobType group) { + return 0.0F; + } +@@ -123,14 +125,17 @@ public abstract class Enchantment { + return false; + } + ++ public boolean isCursed() { return isCurse(); } // Paper - OBFHELPER + public boolean isCurse() { + return false; + } + ++ public boolean isTradeable() { return isTradeable(); } // Paper - OBFHELPER + public boolean isTradeable() { + return true; + } + ++ public boolean isDiscoverable() { return isDiscoverable(); } // Paper - OBFHELPER + public boolean isDiscoverable() { + return true; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +index b1ffe6c7a5915f00a476e88f3a38349b740b4910..20858bb8463ff86c96b5fcdeca455c20c696870f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java ++++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +@@ -1,8 +1,6 @@ + package org.bukkit.craftbukkit.enchantments; + + import net.minecraft.core.Registry; +-import net.minecraft.world.item.enchantment.BindingCurseEnchantment; +-import net.minecraft.world.item.enchantment.VanishingCurseEnchantment; + import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.craftbukkit.util.CraftNamespacedKey; + import org.bukkit.enchantments.Enchantment; +@@ -71,7 +69,7 @@ public class CraftEnchantment extends Enchantment { + + @Override + public boolean isCursed() { +- return target instanceof BindingCurseEnchantment || target instanceof VanishingCurseEnchantment; ++ return target.isCursed(); // Paper + } + + @Override +@@ -192,6 +190,45 @@ public class CraftEnchantment extends Enchantment { + public net.kyori.adventure.text.Component displayName(int level) { + return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); + } ++ ++ @Override ++ public boolean isTradeable() { ++ return target.isTradeable(); ++ } ++ ++ @Override ++ public boolean isDiscoverable() { ++ return target.isDiscoverable(); ++ } ++ ++ @Override ++ public io.papermc.paper.enchantments.EnchantmentRarity getRarity() { ++ return fromNMSRarity(target.getRarity()); ++ } ++ ++ @Override ++ public float getDamageIncrease(int level, org.bukkit.entity.EntityCategory entityCategory) { ++ return target.getDamageIncrease(level, org.bukkit.craftbukkit.entity.CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); ++ } ++ ++ @Override ++ public java.util.Set getActiveSlots() { ++ return java.util.stream.Stream.of(target.getSlots()).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet()); ++ } ++ ++ public static io.papermc.paper.enchantments.EnchantmentRarity fromNMSRarity(net.minecraft.world.item.enchantment.Enchantment.Rarity nmsRarity) { ++ if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.COMMON) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.COMMON; ++ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.UNCOMMON) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.UNCOMMON; ++ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.RARE) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.RARE; ++ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.VERY_RARE) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.VERY_RARE; ++ } ++ ++ throw new IllegalArgumentException(String.format("Unable to convert %s to a enum value of %s.", nmsRarity, io.papermc.paper.enchantments.EnchantmentRarity.class)); ++ } + // Paper end + + public net.minecraft.world.item.enchantment.Enchantment getHandle() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index eefb6bd580ea176c3a242695ab4af46e7c61b492..25ba7a26c951fc5e4638bdb0db36e94d3e08fb2e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -835,5 +835,21 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setHurtDirection(float hurtDirection) { + getHandle().setHurtDirection(hurtDirection); + } ++ ++ public static MobType fromBukkitEntityCategory(EntityCategory entityCategory) { ++ switch (entityCategory) { ++ case NONE: ++ return MobType.UNDEFINED; ++ case UNDEAD: ++ return MobType.UNDEAD; ++ case ARTHROPOD: ++ return MobType.ARTHROPOD; ++ case ILLAGER: ++ return MobType.ILLAGER; ++ case WATER: ++ return MobType.WATER; ++ } ++ throw new IllegalArgumentException(entityCategory + " is an unrecognized entity category"); ++ } + // Paper end + } +diff --git a/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..62b56b5b43696b03fc72cac59f986d006edc3f76 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java +@@ -0,0 +1,18 @@ ++package io.papermc.paper.enchantments; ++ ++import net.minecraft.world.item.enchantment.Enchantment.Rarity; ++import org.bukkit.craftbukkit.enchantments.CraftEnchantment; ++import org.junit.Test; ++ ++import static org.junit.Assert.assertNotNull; ++ ++public class EnchantmentRarityTest { ++ ++ @Test ++ public void test() { ++ for (Rarity nmsRarity : Rarity.values()) { ++ // Will throw exception if a bukkit counterpart is not found ++ CraftEnchantment.fromNMSRarity(nmsRarity); ++ } ++ } ++} +diff --git a/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..adb0e5b4268fa115b814143cf29d9a3688e4bc17 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java +@@ -0,0 +1,34 @@ ++package io.papermc.paper.entity; ++ ++import com.google.common.base.Joiner; ++import com.google.common.collect.Maps; ++import com.google.common.collect.Sets; ++import net.minecraft.world.entity.EnumMonsterType; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.EntityCategory; ++import org.junit.Test; ++ ++import java.lang.reflect.Field; ++import java.util.Map; ++import java.util.Set; ++ ++import static org.junit.Assert.assertTrue; ++ ++public class EntityCategoryTest { ++ ++ @Test ++ public void test() throws IllegalAccessException { ++ ++ Map enumMonsterTypeFieldMap = Maps.newHashMap(); ++ for (Field field : EnumMonsterType.class.getDeclaredFields()) { ++ if (field.getType() == EnumMonsterType.class) { ++ enumMonsterTypeFieldMap.put( (EnumMonsterType) field.get(null), field.getName()); ++ } ++ } ++ ++ for (EntityCategory entityCategory : EntityCategory.values()) { ++ enumMonsterTypeFieldMap.remove(CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); ++ } ++ assertTrue(EnumMonsterType.class.getName() + " instance(s): " + Joiner.on(", ").join(enumMonsterTypeFieldMap.values()) + " do not have bukkit equivalents", enumMonsterTypeFieldMap.size() == 0); ++ } ++} diff --git a/Remapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/Remapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch new file mode 100644 index 0000000000..6c752cc24c --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Tue, 18 May 2021 14:39:44 -0700 +Subject: [PATCH] Add command line option to load extra plugin jars not in the + plugins folder + +ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 63639923f7875d76f569b8c6e958782c6462d906..f1e6d0050092ad51bf233c80b6a51a121e961b07 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -384,8 +384,13 @@ public final class CraftServer implements Server { + + File pluginFolder = (File) console.options.valueOf("plugins"); + +- if (pluginFolder.exists()) { +- Plugin[] plugins = pluginManager.loadPlugins(pluginFolder); ++ // Paper start ++ if (true || pluginFolder.exists()) { ++ if (!pluginFolder.exists()) { ++ pluginFolder.mkdirs(); ++ } ++ Plugin[] plugins = pluginManager.loadPlugins(pluginFolder, this.extraPluginJars()); ++ // Paper end + for (Plugin plugin : plugins) { + try { + String message = String.format("Loading %s", plugin.getDescription().getFullName()); +@@ -400,6 +405,18 @@ public final class CraftServer implements Server { + } + } + ++ // Paper start ++ private List extraPluginJars() { ++ @SuppressWarnings("unchecked") ++ final List jars = (List) this.console.options.valuesOf("add-plugin"); ++ return jars.stream() ++ .filter(File::exists) ++ .filter(File::isFile) ++ .filter(file -> file.getName().endsWith(".jar")) ++ .collect(java.util.stream.Collectors.toList()); ++ } ++ // Paper end ++ + public void enablePlugins(PluginLoadOrder type) { + if (type == PluginLoadOrder.STARTUP) { + helpMap.clear(); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index bd10345cb90f98b8af1519afd603a5244f3a5ca2..521542999b25b1da448fadb3fe6531e083f93e67 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -153,6 +153,12 @@ public class Main { + .ofType(String.class) + .defaultsTo("Unknown Server") + .describedAs("Name"); ++ ++ acceptsAll(asList("add-plugin", "add-extra-plugin-jar")) ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File[] {}) ++ .describedAs("Specify paths to extra plugin jars to be loaded in addition to those in the plugins folder. This argument can be specified multiple times, once for each extra plugin jar path."); + // Paper end + } + }; diff --git a/Remapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/Remapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch new file mode 100644 index 0000000000..7f7be61f7b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 10 May 2021 15:46:57 -0700 +Subject: [PATCH] Fix incorrect status dataconverter for pre 1.13 chunks + +Vanilla was setting non-populated OR non-lit chunks to empty, but +really this is just completely wrong. It should be set to "carved" +at minmum, because pre 1.13 chunks went through 3 distinct stages +of generation: carving, population, and lighting - in this order. +There is no "empty" status, because a chunk was simply carved +or it didn't exist. So mapping any chunk data to empty is simply +invalid. + +If the chunk is terrain populated, then obviously it must be at +minmum "decorated." If the chunk is lit and populated, then it is marked +"mobs_spawned" (which is what Vanilla is doing, and this is the last +stage before moving to full so it looks correct). + +So now here is a table representing the new status conversion: + +Chunk is lit Chunk is populated Vanilla + F F empty + T F empty + F T empty + T T mobs_spawned + +Chunk is lit Chunk is populated Paper + F F carved + T F carved + F T decorated + T T mobs_spawned + +This should fix some problems converting old data, as the +changes here are going to prevent the chunk from being regenerated +incorrectly. + +diff --git a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java +index 16f6aa39385e2d278d4883a32c11ddd119d0d85d..3d262dcf6db0e395d2fa457f7197f24013037ac1 100644 +--- a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java ++++ b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java +@@ -43,13 +43,21 @@ public class ChunkToProtochunkFix extends DataFix { + return dynamic.asStreamOpt().result(); + }); + Dynamic dynamic = (Dynamic) typed1.get(DSL.remainderFinder()); +- boolean flag = dynamic.get("TerrainPopulated").asBoolean(false) && (!dynamic.get("LightPopulated").asNumber().result().isPresent() || dynamic.get("LightPopulated").asBoolean(false)); +- +- dynamic = dynamic.set("Status", dynamic.createString(flag ? "mobs_spawned" : "empty")); ++ // Paper start - fix incorrect status conversion ++ // Vanilla is setting chunks to incorrect status here, they should be using at minimum carved. ++ // for populated chunks, it should be at minimum decorated ++ // and for lit and populated, mobs_spawned is correct (technically mobs_spawned should be for populated, ++ // but if it's not lit then it can't be set above lit) ++ final boolean terrainPopulated = dynamic.get("TerrainPopulated").asBoolean(false); ++ final boolean lightPopulated = dynamic.get("LightPopulated").asBoolean(false) || dynamic.get("LightPopulated").asNumber().result().isPresent(); ++ final String newStatus = !terrainPopulated ? "carved" : (lightPopulated ? "mobs_spawned" : "decorated"); ++ ++ dynamic = dynamic.set("Status", dynamic.createString(newStatus)); + dynamic = dynamic.set("hasLegacyStructureData", dynamic.createBoolean(true)); +- Dynamic dynamic1; ++ // Paper end - fix incorrect status conversion ++ Dynamic dynamic1; // Paper - decompile fix + +- if (flag) { ++ if (true) { // Paper - fix incorrect status conversion + Optional optional1 = dynamic.get("Biomes").asByteBufferOpt().result(); + + if (optional1.isPresent()) { +@@ -70,7 +78,7 @@ public class ChunkToProtochunkFix extends DataFix { + }).collect(Collectors.toList()); + + if (optional.isPresent()) { +- ((Stream) optional.get()).forEach((dynamic2) -> { ++ optional.get().forEach((dynamic2) -> { // Paper - decompile fix + int j = dynamic2.get("x").asInt(0); + int k = dynamic2.get("y").asInt(0); + int l = dynamic2.get("z").asInt(0); +@@ -78,11 +86,11 @@ public class ChunkToProtochunkFix extends DataFix { + + ((ShortList) list.get(k >> 4)).add(short0); + }); ++ Dynamic finalDynamic = dynamic; // Paper - decompile fix + dynamic = dynamic.set("ToBeTicked", dynamic.createList(list.stream().map((shortlist) -> { +- Stream stream = shortlist.stream(); ++ Stream stream = shortlist.stream(); // Paper - decompile fix + +- dynamic.getClass(); +- return dynamic.createList(stream.map(dynamic::createShort)); ++ return finalDynamic.createList(stream.map(finalDynamic::createShort)); + }))); + } + diff --git a/Remapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch b/Remapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch new file mode 100644 index 0000000000..885e2d6ca3 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SamB440 +Date: Fri, 21 May 2021 00:22:09 +0100 +Subject: [PATCH] Fix MC-148809: Increase structure block data length to 128 + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java +index 4c797dd82bb1989861e350a7e628eb847b58bbd8..4792aafd8d992cd64d05f8bbef5cbf30988949ed 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java +@@ -43,7 +43,7 @@ public class ServerboundSetStructureBlockPacket implements Packet +Date: Thu, 20 May 2021 07:02:22 -0700 +Subject: [PATCH] Fix and optimise world force upgrading + +The WorldUpgrader class was incorrectly modified by +CB. It will store an IChunkLoader instance for all +dimension types in the world, but obviously with how +CB shifts around worlds only one dimension type exists +per world. But this would be OK if CB did this +change correctly. All IChunkLoader instances +will point to the same regionfiles. And all +IChunkLoader instances are going to be read from. + +This problem hasn't really been reported because +it relies on the persistent legacy data to be converted +as well to cause corruption. Why? Because the legacy +data is also shared, it will result in different +outputs from conversion (as once conversion for legacy +persistent data takes place, it is REMOVED - so the next +convert will _not_ have the data). Which means different +sizes on disk. Which means different regionfile sector +allocations. Which means there are 3 different possible +regionfile sector allocations in memory, and none of them +are going to be correct. + +I've fixed this by writing a world upgrader suited to +CB's changes to world folder format. It was brain dead +easy to add threading, so I did. + +diff --git a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f476f21bcfd64d4eb2b690c9100275093c49c9d6 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java +@@ -0,0 +1,200 @@ ++package io.papermc.paper.world; ++ ++import com.mojang.datafixers.DataFixer; ++import net.minecraft.SharedConstants; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.resources.ResourceKey; ++import net.minecraft.util.worldupdate.WorldUpgrader; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.chunk.storage.ChunkStorage; ++import net.minecraft.world.level.chunk.storage.RegionFileStorage; ++import net.minecraft.world.level.dimension.DimensionType; ++import net.minecraft.world.level.dimension.LevelStem; ++import net.minecraft.world.level.storage.DimensionDataStorage; ++import net.minecraft.world.level.storage.LevelStorageSource; ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++import java.io.File; ++import java.io.IOException; ++import java.text.DecimalFormat; ++import java.util.concurrent.ExecutorService; ++import java.util.concurrent.Executors; ++import java.util.concurrent.ThreadFactory; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.concurrent.atomic.AtomicLong; ++import java.util.function.Supplier; ++ ++public class ThreadedWorldUpgrader { ++ ++ private static final Logger LOGGER = LogManager.getLogger(); ++ ++ private final ResourceKey dimensionType; ++ private final ResourceKey worldKey; ++ private final String worldName; ++ private final ExecutorService threadPool; ++ private final DataFixer dataFixer; ++ private final boolean removeCaches; ++ ++ public ThreadedWorldUpgrader(final ResourceKey dimensionType, final ResourceKey worldKey, final String worldName, final int threads, ++ final DataFixer dataFixer, final boolean removeCaches) { ++ this.dimensionType = dimensionType; ++ this.worldKey = worldKey; ++ this.worldName = worldName; ++ this.threadPool = Executors.newFixedThreadPool(Math.max(1, threads), new ThreadFactory() { ++ private final AtomicInteger threadCounter = new AtomicInteger(); ++ ++ @Override ++ public Thread newThread(final Runnable run) { ++ final Thread ret = new Thread(run); ++ ++ ret.setName("World upgrader thread for world " + ThreadedWorldUpgrader.this.worldName + " #" + this.threadCounter.getAndIncrement()); ++ ret.setUncaughtExceptionHandler((thread, throwable) -> { ++ LOGGER.fatal("Error upgrading world", throwable); ++ }); ++ ++ return ret; ++ } ++ }); ++ this.dataFixer = dataFixer; ++ this.removeCaches = removeCaches; ++ } ++ ++ public void convert() { ++ final File worldFolder = LevelStorageSource.getFolder(new File(this.worldName), this.dimensionType); ++ final DimensionDataStorage worldPersistentData = new DimensionDataStorage(new File(worldFolder, "data"), this.dataFixer); ++ ++ final File regionFolder = new File(worldFolder, "region"); ++ ++ LOGGER.info("Force upgrading " + this.worldName); ++ LOGGER.info("Counting regionfiles for " + this.worldName); ++ final File[] regionFiles = regionFolder.listFiles((final File dir, final String name) -> { ++ return WorldUpgrader.getRegionfileRegex().matcher(name).matches(); ++ }); ++ if (regionFiles == null) { ++ LOGGER.info("Found no regionfiles to convert for world " + this.worldName); ++ return; ++ } ++ LOGGER.info("Found " + regionFiles.length + " regionfiles to convert"); ++ LOGGER.info("Starting conversion now for world " + this.worldName); ++ ++ final WorldInfo info = new WorldInfo(() -> worldPersistentData, ++ new ChunkStorage(regionFolder, this.dataFixer, false), this.removeCaches, this.worldKey); ++ ++ long expectedChunks = (long)regionFiles.length * (32L * 32L); ++ ++ for (final File regionFile : regionFiles) { ++ final ChunkPos regionPos = RegionFileStorage.getRegionFileCoordinates(regionFile); ++ if (regionPos == null) { ++ expectedChunks -= (32L * 32L); ++ continue; ++ } ++ ++ this.threadPool.execute(new ConvertTask(info, regionPos.x >> 5, regionPos.z >> 5)); ++ } ++ this.threadPool.shutdown(); ++ ++ final DecimalFormat format = new DecimalFormat("#0.00"); ++ ++ final long start = System.nanoTime(); ++ ++ while (!this.threadPool.isTerminated()) { ++ final long current = info.convertedChunks.get(); ++ ++ LOGGER.info("{}% completed ({} / {} chunks)...", format.format((double)current / (double)expectedChunks * 100.0), current, expectedChunks); ++ ++ try { ++ Thread.sleep(1000L); ++ } catch (final InterruptedException ignore) {} ++ } ++ ++ final long end = System.nanoTime(); ++ ++ try { ++ info.loader.close(); ++ } catch (final IOException ex) { ++ LOGGER.fatal("Failed to close chunk loader", ex); ++ } ++ LOGGER.info("Completed conversion. Took {}s, {} out of {} chunks needed to be converted/modified ({}%)", ++ (int)Math.ceil((end - start) * 1.0e-9), info.modifiedChunks.get(), expectedChunks, format.format((double)info.modifiedChunks.get() / (double)expectedChunks * 100.0)); ++ } ++ ++ private static final class WorldInfo { ++ ++ public final Supplier persistentDataSupplier; ++ public final ChunkStorage loader; ++ public final boolean removeCaches; ++ public final ResourceKey worldKey; ++ public final AtomicLong convertedChunks = new AtomicLong(); ++ public final AtomicLong modifiedChunks = new AtomicLong(); ++ ++ private WorldInfo(final Supplier persistentDataSupplier, final ChunkStorage loader, final boolean removeCaches, ++ final ResourceKey worldKey) { ++ this.persistentDataSupplier = persistentDataSupplier; ++ this.loader = loader; ++ this.removeCaches = removeCaches; ++ this.worldKey = worldKey; ++ } ++ } ++ ++ private static final class ConvertTask implements Runnable { ++ ++ private final WorldInfo worldInfo; ++ private final int regionX; ++ private final int regionZ; ++ ++ public ConvertTask(final WorldInfo worldInfo, final int regionX, final int regionZ) { ++ this.worldInfo = worldInfo; ++ this.regionX = regionX; ++ this.regionZ = regionZ; ++ } ++ ++ @Override ++ public void run() { ++ final int regionCX = this.regionX << 5; ++ final int regionCZ = this.regionZ << 5; ++ ++ final Supplier persistentDataSupplier = this.worldInfo.persistentDataSupplier; ++ final ChunkStorage loader = this.worldInfo.loader; ++ final boolean removeCaches = this.worldInfo.removeCaches; ++ final ResourceKey worldKey = this.worldInfo.worldKey; ++ ++ for (int cz = regionCZ; cz < (regionCZ + 32); ++cz) { ++ for (int cx = regionCX; cx < (regionCX + 32); ++cx) { ++ final ChunkPos chunkPos = new ChunkPos(cx, cz); ++ try { ++ // no need to check the coordinate of the chunk, the regionfilecache does that for us ++ ++ CompoundTag chunkNBT = loader.read(chunkPos); ++ ++ if (chunkNBT == null) { ++ continue; ++ } ++ ++ final int versionBefore = ChunkStorage.getVersion(chunkNBT); ++ ++ chunkNBT = loader.getChunkData(worldKey, persistentDataSupplier, chunkNBT, chunkPos, null); ++ ++ boolean modified = versionBefore < SharedConstants.getCurrentVersion().getWorldVersion(); ++ ++ if (removeCaches) { ++ final CompoundTag level = chunkNBT.getCompound("Level"); ++ modified |= level.contains("Heightmaps"); ++ level.remove("Heightmaps"); ++ modified |= level.contains("isLightOn"); ++ level.remove("isLightOn"); ++ } ++ ++ if (modified) { ++ this.worldInfo.modifiedChunks.getAndIncrement(); ++ loader.write(chunkPos, chunkNBT); ++ } ++ } catch (final Exception ex) { ++ LOGGER.error("Error upgrading chunk {}", chunkPos, ex); ++ } finally { ++ this.worldInfo.convertedChunks.getAndIncrement(); ++ } ++ } ++ } ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index ba6c17da4875c3a342da99e354c9f07cc7f17326..d0105061c714af4403b3e14e96e54e17a82c172b 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -15,6 +15,7 @@ import java.nio.file.Paths; + import java.util.Optional; + import java.util.concurrent.CompletableFuture; + import java.util.function.BooleanSupplier; ++import io.papermc.paper.world.ThreadedWorldUpgrader; + import joptsimple.NonOptionArgumentSpec; + import joptsimple.OptionParser; + import joptsimple.OptionSet; +@@ -269,6 +270,15 @@ public class Main { + } + // Paper end + ++ // Paper start - fix and optimise world upgrading ++ public static void convertWorldButItWorks(ResourceKey dimensionType, ResourceKey worldKey, String worldName, ++ DataFixer dataFixer, boolean removeCaches) { ++ int threads = Runtime.getRuntime().availableProcessors() * 3 / 8; ++ final ThreadedWorldUpgrader worldUpgrader = new ThreadedWorldUpgrader(dimensionType, worldKey, worldName, threads, dataFixer, removeCaches); ++ worldUpgrader.convert(); ++ } ++ // Paper end - fix and optimise world upgrading ++ + public static void forceUpgrade(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, boolean eraseCache, BooleanSupplier booleansupplier, ImmutableSet> worlds) { // CraftBukkit + Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit + WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, worlds, eraseCache); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index fd76d776c7003585c9efef44c6d7da0f6c3f574e..9d7cebd703bd0171ca3e95d2985c1a52fdb59712 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -512,13 +512,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +- return true; +- }, worlddata.worldGenSettings().dimensions().entrySet().stream().map((entry1) -> { +- return ResourceKey.create(Registry.DIMENSION_TYPE_REGISTRY, ((ResourceKey) entry1.getKey()).location()); +- }).collect(ImmutableSet.toImmutableSet())); +- } ++ // Paper - move down + + ServerLevelData iworlddataserver = worlddata; + WorldGenSettings generatorsettings = worlddata.worldGenSettings(); +@@ -538,6 +532,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, dimensionKey.location()); + + if (dimensionKey == LevelStem.OVERWORLD) { +diff --git a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java +index 79491c5081dbc0cc479d6bc0329ff9b374559c9b..29c0fe698e91e232bcebfafdd853d222c83d5af8 100644 +--- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java ++++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java +@@ -52,7 +52,7 @@ public class WorldUpgrader { + private volatile int skipped; + private final Object2FloatMap> progressMap = Object2FloatMaps.synchronize(new Object2FloatOpenCustomHashMap(Util.identityStrategy())); // CraftBukkit + private volatile Component status = new TranslatableComponent("optimizeWorld.stage.counting"); +- private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); ++ private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); public static final Pattern getRegionfileRegex() { return REGEX; } // Paper - OBFHELPER + private final DimensionDataStorage overworldDataStorage; + + public WorldUpgrader(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, ImmutableSet> worlds, boolean eraseCache) { // CraftBukkit +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 4523bc1f49e7be248a47eeb599fa7b6550dbb08d..d155d00abf8f423e64e6e6d80ddadbc1cfb58a64 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -181,6 +181,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return typeKey; + } + ++ // Paper start - fix and optimise world upgrading ++ // copied from below ++ public static ResourceKey getDimensionKey(DimensionType manager) { ++ return ((org.bukkit.craftbukkit.CraftServer)org.bukkit.Bukkit.getServer()).getHandle().getServer().registryHolder.dimensionTypes().getResourceKey(manager).orElseThrow(() -> { ++ return new IllegalStateException("Unregistered dimension type: " + manager); ++ }); ++ } ++ // Paper end - fix and optimise world upgrading ++ + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot + this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +index 1af804c5c6fb2b20ea3f020610763c1d7dcee110..0e38f2f31d167c417b707f00aa68cacaef3d9f6c 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -109,6 +109,7 @@ public class ChunkStorage implements AutoCloseable { + return nbttagcompound; + } + ++ public static int getVersion(CompoundTag nbttagcompound) { return getVersion(nbttagcompound); } // Paper - OBFHELPER + public static int getVersion(CompoundTag tag) { + return tag.contains("DataVersion", 99) ? tag.getInt("DataVersion") : -1; + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index 0498982ac14f20145d68dbf64a46bcaacf5516ef..7a01f2fbe459e36cee5416455a049b25963e257a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -30,6 +30,28 @@ public class RegionFileStorage implements AutoCloseable { // Paper - no final + + + // Paper start ++ public static ChunkPos getRegionFileCoordinates(File file) { ++ String fileName = file.getName(); ++ if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) { ++ return null; ++ } ++ ++ String[] split = fileName.split("\\."); ++ ++ if (split.length != 4) { ++ return null; ++ } ++ ++ try { ++ int x = Integer.parseInt(split[1]); ++ int z = Integer.parseInt(split[2]); ++ ++ return new ChunkPos(x << 5, z << 5); ++ } catch (NumberFormatException ex) { ++ return null; ++ } ++ } ++ + public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { // Paper - synchronize for async io + return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index f1e6d0050092ad51bf233c80b6a51a121e961b07..831f187cde88e815c9a859e52ab45fbbe054f83e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1145,14 +1145,7 @@ public final class CraftServer implements Server { + } + worlddata.checkName(name); + worlddata.setModdedInfo(console.getServerModName(), console.getModdedStatus().isPresent()); +- +- if (console.options.has("forceUpgrade")) { +- net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), console.options.has("eraseCache"), () -> { +- return true; +- }, worlddata.worldGenSettings().dimensions().entrySet().stream().map((entry) -> { +- return ResourceKey.create(Registry.DIMENSION_TYPE_REGISTRY, ((ResourceKey) entry.getKey()).location()); +- }).collect(ImmutableSet.toImmutableSet())); +- } ++ // Paper - move down + + long j = BiomeManager.obfuscateSeed(creator.seed()); + List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata)); +@@ -1169,6 +1162,14 @@ public final class CraftServer implements Server { + chunkgenerator = worlddimension.generator(); + } + ++ // Paper start - fix and optimise world upgrading ++ if (console.options.has("forceUpgrade")) { ++ net.minecraft.server.Main.convertWorldButItWorks( ++ actualDimension, net.minecraft.world.level.Level.getDimensionKey(dimensionmanager), worldSession.getLevelId(), DataFixers.getDataFixer(), console.options.has("eraseCache") ++ ); ++ } ++ // Paper end - fix and optimise world upgrading ++ + ResourceKey worldKey; + String levelName = this.getServer().getProperties().levelName; + if (name.equals(levelName + "_nether")) { diff --git a/Remapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch b/Remapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch new file mode 100644 index 0000000000..ce42177784 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 14 May 2021 13:42:17 -0500 +Subject: [PATCH] Add Mob#lookAt API + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index ea34306858116e5626383af408529091836c2752..5692b497875ba2ee455859bc8a88d7888afd86fc 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -850,14 +850,17 @@ public abstract class Mob extends LivingEntity { + + protected void customServerAiStep() {} + ++ public int getMaxHeadXRot() { return getMaxHeadXRot(); } // Paper - OBFHELPER + public int getMaxHeadXRot() { + return 40; + } + ++ public int getMaxHeadYRot() { return getMaxHeadYRot(); } // Paper - OBFHELPER + public int getMaxHeadYRot() { + return 75; + } + ++ public int getHeadRotSpeed() { return getHeadRotSpeed(); } // Paper - OBFHELPER + public int getHeadRotSpeed() { + return 10; + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java b/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java +index faba4a95883bb0fcfd4f65c3f62bd6f476ded249..3fe159c4bdc3ad3e95354e18e2921305af121725 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java +@@ -20,18 +20,28 @@ public class LookControl { + this.mob = entity; + } + ++ public void lookAt(Vec3 vec3d) { setLookAt(vec3d); } // Paper - OBFHELPER + public void setLookAt(Vec3 direction) { + this.setLookAt(direction.x, direction.y, direction.z); + } + ++ // Paper start ++ public void lookAt(Entity entity) { ++ this.lookAt(entity.getX(), getWantedY(entity), entity.getZ()); ++ } ++ // Paper end ++ ++ public void lookAt(Entity entity, float f, float f1) { setLookAt(entity, f, f1); } // Paper - OBFHELPER + public void setLookAt(Entity entity, float yawSpeed, float pitchSpeed) { + this.setLookAt(entity.getX(), getWantedY(entity), entity.getZ(), yawSpeed, pitchSpeed); + } + ++ public void lookAt(double d0, double d1, double d2) { setLookAt(d0, d1, d2); } // Paper - OBFHELPER + public void setLookAt(double x, double y, double z) { + this.setLookAt(x, y, z, (float) this.mob.getHeadRotSpeed(), (float) this.mob.getMaxHeadXRot()); + } + ++ public void lookAt(double d0, double d1, double d2, float f, float f1) { setLookAt(d0, d1, d2, f, f1); } // Paper - OBFHELPER + public void setLookAt(double x, double y, double z, float yawSpeed, float pitchSpeed) { + this.wantedX = x; + this.wantedY = y; +@@ -103,6 +113,7 @@ public class LookControl { + return from + f4; + } + ++ public static double getWantedY(Entity entity) { return getWantedY(entity); } // Paper - OBFHELPER + private static double getWantedY(Entity entity) { + return entity instanceof LivingEntity ? entity.getEyeY() : (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0D; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +index 1e3a0851c75d8067d2699f00bb3f6621d1d739d8..f597cf70779fde265cc45868aba3ae9db898fb6e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +@@ -83,5 +83,53 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { + public boolean isInDaylight() { + return getHandle().isInDaylight(); + } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location) { ++ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); ++ getHandle().getLookControl().lookAt(location.getX(), location.getY(), location.getZ()); ++ } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location, float headRotationSpeed, float maxHeadPitch) { ++ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); ++ getHandle().getLookControl().lookAt(location.getX(), location.getY(), location.getZ(), headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity) { ++ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); ++ getHandle().getLookControl().lookAt(((CraftEntity) entity).getHandle()); ++ } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity, float headRotationSpeed, float maxHeadPitch) { ++ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); ++ getHandle().getLookControl().lookAt(((CraftEntity) entity).getHandle(), headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public void lookAt(double x, double y, double z) { ++ getHandle().getLookControl().lookAt(x, y, z); ++ } ++ ++ @Override ++ public void lookAt(double x, double y, double z, float headRotationSpeed, float maxHeadPitch) { ++ getHandle().getLookControl().lookAt(x, y, z, headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public int getHeadRotationSpeed() { ++ return getHandle().getHeadRotSpeed(); ++ } ++ ++ @Override ++ public int getMaxHeadPitch() { ++ return getHandle().getMaxHeadXRot(); ++ } + // Paper end + } diff --git a/Remapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch b/Remapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch new file mode 100644 index 0000000000..83c74f604e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch @@ -0,0 +1,141 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Tue, 11 May 2021 17:39:22 -0400 +Subject: [PATCH] Add Unix domain socket support + +For Windows and ARM support, JEP-380 is required: +https://inside.java/2021/02/03/jep380-unix-domain-sockets-channels/ +This will be possible as of the Minecraft 1.17 Java version bump. + +Tested-by: Mariell Hoversholm +Reviewed-by: Mariell Hoversholm + +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 3ba9c38fc44a8edba9b504112a383249052a0035..cc823a1337bea3ad552687add46706128311f26d 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -564,6 +564,11 @@ public class Connection extends SimpleChannelInboundHandler> { + // Spigot Start + public SocketAddress getRawAddress() + { ++ // Paper start - this can be nullable in the case of a Unix domain socket, so if it is, fake something ++ if (this.channel.remoteAddress() == null) { ++ return new java.net.InetSocketAddress(java.net.InetAddress.getLoopbackAddress(), 0); ++ } ++ // Paper end + return this.channel.remoteAddress(); + } + // Spigot End +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 0198268bc614b190cd84f625a62f6c55247a01c8..2821fa9505d6b5adc8e776219df024713fc1a486 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -222,6 +222,20 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist); + // this.saveData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading + DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode); ++ // Paper start - Unix domain socket support ++ java.net.SocketAddress bindAddress; ++ if (this.getLocalIp().startsWith("unix:")) { ++ if (!io.netty.channel.epoll.Epoll.isAvailable()) { ++ DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!"); ++ DedicatedServer.LOGGER.fatal("You are trying to use a Unix domain socket but you're not on a supported OS."); ++ return false; ++ } else if (!com.destroystokyo.paper.PaperConfig.velocitySupport && !org.spigotmc.SpigotConfig.bungee) { ++ DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!"); ++ DedicatedServer.LOGGER.fatal("Unix domain sockets require IPs to be forwarded from a proxy."); ++ return false; ++ } ++ bindAddress = new io.netty.channel.unix.DomainSocketAddress(this.getLocalIp().substring("unix:".length())); ++ } else { + InetAddress inetaddress = null; + + if (!this.getLocalIp().isEmpty()) { +@@ -231,12 +245,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + if (this.getPort() < 0) { + this.setPort(dedicatedserverproperties.serverPort); + } ++ bindAddress = new java.net.InetSocketAddress(inetaddress, this.getPort()); ++ } ++ // Paper end + + this.initializeKeyPair(); + DedicatedServer.LOGGER.info("Starting Minecraft server on {}:{}", this.getLocalIp().isEmpty() ? "*" : this.getLocalIp(), this.getPort()); + + try { +- this.getConnection().startTcpServerListener(inetaddress, this.getPort()); ++ this.getConnection().bind(bindAddress); // Paper - Unix domain socket support + } catch (IOException ioexception) { + DedicatedServer.LOGGER.warn("**** FAILED TO BIND TO PORT!"); + DedicatedServer.LOGGER.warn("The exception was: {}", ioexception.toString()); +diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +index bcc19d0a4b6c5f683dc416e27a13705b57213d21..67a17ced9460bc83a6f564b38fdb43b1a7f1b8a0 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +@@ -70,7 +70,12 @@ public class ServerConnectionListener { + this.running = true; + } + ++ // Paper start + public void startTcpServerListener(@Nullable InetAddress address, int port) throws IOException { ++ bind(new java.net.InetSocketAddress(address, port)); ++ } ++ public void bind(java.net.SocketAddress address) throws IOException { ++ // Paper end + List list = this.channels; + + synchronized (this.channels) { +@@ -78,7 +83,11 @@ public class ServerConnectionListener { + LazyLoadedValue lazyinitvar; + + if (Epoll.isAvailable() && this.server.isEpollEnabled()) { ++ if (address instanceof io.netty.channel.unix.DomainSocketAddress) { ++ oclass = io.netty.channel.epoll.EpollServerDomainSocketChannel.class; ++ } else { + oclass = EpollServerSocketChannel.class; ++ } + lazyinitvar = ServerConnectionListener.SERVER_EPOLL_EVENT_GROUP; + ServerConnectionListener.LOGGER.info("Using epoll channel type"); + } else { +@@ -106,7 +115,7 @@ public class ServerConnectionListener { + ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); + io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper + } +- }).group((EventLoopGroup) lazyinitvar.get()).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit ++ }).group((EventLoopGroup) lazyinitvar.get()).localAddress(address)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit // Paper + } + } + +diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 4e055a41de3ee410682cc05a3b883ac8babeb290..e1fbb207d6921516c7423e9a3cded8efb5676d49 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -44,6 +44,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + this.connection.setProtocol(ConnectionProtocol.LOGIN); + // CraftBukkit start - Connection throttle + try { ++ if (!(this.connection.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress)) { // Paper - the connection throttle is useless when you have a Unix domain socket + long currentTime = System.currentTimeMillis(); + long connectionThrottle = this.server.server.getConnectionThrottle(); + InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress(); +@@ -72,6 +73,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + } + } + } ++ } // Paper - add closing bracket for if check above + } catch (Throwable t) { + org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); + } +@@ -120,8 +122,11 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! + String[] split = packet.hostName.split("\00"); + if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper ++ // Paper start - Unix domain socket support ++ java.net.SocketAddress socketAddress = connection.getRemoteAddress(); + packet.hostName = split[0]; +- connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort()); ++ connection.address = new java.net.InetSocketAddress(split[1], socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); ++ // Paper end + connection.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); + } else + { diff --git a/Remapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch b/Remapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch new file mode 100644 index 0000000000..6380d78daa --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch @@ -0,0 +1,222 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 8 May 2021 18:02:36 -0700 +Subject: [PATCH] Add EntityInsideBlockEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +index ad37261e716b15d62fc2083d137cdac818308cdd..58519e224a5005bf6468b99196acb7209b2e1398 100644 +--- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +@@ -48,6 +48,7 @@ public abstract class BaseFireBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!entity.fireImmune()) { + entity.setRemainingFireTicks(entity.getRemainingFireTicks() + 1); + if (entity.getRemainingFireTicks() == 0) { +diff --git a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java +index 6acb24f96591d555e550d399d2ed38036a0220fe..8d8fd646c9527852bfe9a2d3cd0a6bf1bfa9e4a2 100644 +--- a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java +@@ -65,6 +65,7 @@ public abstract class BasePressurePlateBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide) { + int i = this.getSignalForState(state); + +diff --git a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java +index f741980d0e1759e3fefe322b654760dab35200d6..faa1070aaf3fcc40bf7e36a0dda8ec7879c89dd6 100644 +--- a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java +@@ -33,6 +33,7 @@ public class BubbleColumnBlock extends Block implements BucketPickup { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + BlockState iblockdata1 = world.getBlockState(pos.above()); + + if (iblockdata1.isAir()) { +diff --git a/src/main/java/net/minecraft/world/level/block/ButtonBlock.java b/src/main/java/net/minecraft/world/level/block/ButtonBlock.java +index 52ca5dad75674b81b997f8a1cf3f5d52bf4313c1..2c4c5fc6d45225cc9f7f1c2038bd4d0ae20c9daa 100644 +--- a/src/main/java/net/minecraft/world/level/block/ButtonBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ButtonBlock.java +@@ -179,6 +179,7 @@ public abstract class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide && this.sensitive && !(Boolean) state.getValue(ButtonBlock.POWERED)) { + this.checkPressed(state, world, pos); + } +diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java +index de61393e3f702554817d81ff10693ec3fb63d492..28b083a8220856723b6169b5b13677b965a4dab6 100644 +--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java +@@ -115,6 +115,7 @@ public class CactusBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + CraftEventFactory.blockDamage = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit + entity.hurt(DamageSource.CACTUS, 1.0F); + CraftEventFactory.blockDamage = null; // CraftBukkit +diff --git a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java +index 87f106ad9139157af69a0ae1602c32ed372a04be..b0c6ac74daea347f4acb5da95e6b0cb013827509 100644 +--- a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java +@@ -88,6 +88,7 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!entity.fireImmune() && (Boolean) state.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { + entity.hurt(DamageSource.IN_FIRE, (float) this.fireDamage); + } +diff --git a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java +index 941061b50f7909278e962fb2aa080bb630862aa1..7d23adaa833c9c45708705294969fe268153b927 100644 +--- a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java +@@ -58,6 +58,7 @@ public class CauldronBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + int i = (Integer) state.getValue(CauldronBlock.LEVEL); + float f = (float) pos.getY() + (6.0F + (float) (3 * i)) / 16.0F; + +diff --git a/src/main/java/net/minecraft/world/level/block/CropBlock.java b/src/main/java/net/minecraft/world/level/block/CropBlock.java +index 4cd6f18e0a2ee8d0495b3c822b227e212a13b11f..8368a5911690a9abb26c0f381bda7a0633197548 100644 +--- a/src/main/java/net/minecraft/world/level/block/CropBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CropBlock.java +@@ -159,6 +159,7 @@ public class CropBlock extends BushBlock implements BonemealableBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (entity instanceof Ravager && !CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)).isCancelled()) { // CraftBukkit + world.destroyBlock(pos, true, entity); + } +diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +index 1854809e045300e84a713dc7c3a8264f53ec6c0f..d970fe7137f7dd37221b54e4025b98d15b950489 100644 +--- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +@@ -44,6 +44,7 @@ public class DetectorRailBlock extends BaseRailBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide) { + if (!(Boolean) state.getValue(DetectorRailBlock.POWERED)) { + this.checkPressed(world, pos, state); +diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +index a6d793478be8e2aab1f72b68a6a96c86642ad1fc..2231680140d0e3c4c10b6722fd13fe0ee55ce294 100644 +--- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +@@ -41,6 +41,7 @@ public class EndPortalBlock extends BaseEntityBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (world instanceof ServerLevel && !entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-pos.getX()), (double) (-pos.getY()), (double) (-pos.getZ()))), state.getShape(world, pos), BooleanOp.AND)) { + ResourceKey resourcekey = world.getTypeKey() == DimensionType.END_LOCATION ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends + ServerLevel worldserver = ((ServerLevel) world).getServer().getLevel(resourcekey); +diff --git a/src/main/java/net/minecraft/world/level/block/HoneyBlock.java b/src/main/java/net/minecraft/world/level/block/HoneyBlock.java +index 7d0206dc5ac46220970adad51863028840b4a9ad..ef74852a1677a4ec80149aa7eafca910fac5ee91 100644 +--- a/src/main/java/net/minecraft/world/level/block/HoneyBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/HoneyBlock.java +@@ -49,6 +49,7 @@ public class HoneyBlock extends HalfTransparentBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (this.isSlidingDown(pos, entity)) { + this.maybeDoSlideAchievement(entity, pos); + this.doSlideMovement(entity); +diff --git a/src/main/java/net/minecraft/world/level/block/HopperBlock.java b/src/main/java/net/minecraft/world/level/block/HopperBlock.java +index 1f50c2b4bebeb6a224eb0ac552d6ea693f7831a6..40b1bba69ae96e4cd652261e3f97850e2e7c51a3 100644 +--- a/src/main/java/net/minecraft/world/level/block/HopperBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/HopperBlock.java +@@ -197,6 +197,7 @@ public class HopperBlock extends BaseEntityBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + BlockEntity tileentity = world.getBlockEntity(pos); + + if (tileentity instanceof HopperBlockEntity) { +diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +index ae58929886921d0714bf811de92f99dc0dc120dc..53e7570cc2538e73f1cfe3d28ffc491f61cac372 100644 +--- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -81,6 +81,7 @@ public class NetherPortalBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions()) { + // CraftBukkit start - Entity in portal + EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); +diff --git a/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java b/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java +index 09122e2031e9ddfae4544911f8c25b937b03933f..6b5e8654ddd2c268627d0244b01dadeaeb4a7de4 100644 +--- a/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java +@@ -66,6 +66,7 @@ public class SweetBerryBushBlock extends BushBlock implements BonemealableBlock + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (entity instanceof LivingEntity && entity.getType() != EntityType.FOX && entity.getType() != EntityType.BEE) { + entity.makeStuckInBlock(state, new Vec3(0.800000011920929D, 0.75D, 0.800000011920929D)); + if (!world.isClientSide && (Integer) state.getValue(SweetBerryBushBlock.AGE) > 0 && (entity.xOld != entity.getX() || entity.zOld != entity.getZ())) { +diff --git a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java +index eaee409bc8fbf8c5541afd10d24975535556a7f6..a488a2a589126df617564d9278eb0496915b6f88 100644 +--- a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java +@@ -118,6 +118,7 @@ public class TripWireBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide) { + if (!(Boolean) state.getValue(TripWireBlock.POWERED)) { + this.checkPressed(world, pos); +diff --git a/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java b/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java +index 2b2a28d0383ccc8c0e7debd90331570b02b5e65f..bd4295f8d24ca9fd8c3af31abcd13da24db1c5d5 100644 +--- a/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java +@@ -25,6 +25,7 @@ public class WaterlilyBlock extends BushBlock { + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { + super.entityInside(state, world, pos, entity); ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (world instanceof ServerLevel && entity instanceof Boat && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { // CraftBukkit + world.destroyBlock(new BlockPos(pos), true, entity); + } +diff --git a/src/main/java/net/minecraft/world/level/block/WebBlock.java b/src/main/java/net/minecraft/world/level/block/WebBlock.java +index c368531420d464414de3661e1624e2a284976ab6..fc1c2e057e8b63048c919b5cbcc0a0e897f1dd01 100644 +--- a/src/main/java/net/minecraft/world/level/block/WebBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/WebBlock.java +@@ -15,6 +15,7 @@ public class WebBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + entity.makeStuckInBlock(state, new Vec3(0.25D, 0.05000000074505806D, 0.25D)); + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java b/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java +index c1648c28c761cdf31089d434f9cb896ddef41521..5cb4e1ec7ce3087163d2ecf26d043894310768d1 100644 +--- a/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java +@@ -26,6 +26,7 @@ public class WitherRoseBlock extends FlowerBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide && world.getDifficulty() != Difficulty.PEACEFUL) { + if (entity instanceof LivingEntity) { + LivingEntity entityliving = (LivingEntity) entity; diff --git a/Remapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch b/Remapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch new file mode 100644 index 0000000000..ce7b672b14 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 8 May 2021 15:01:54 -0700 +Subject: [PATCH] Attributes API for item defaults + + +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index 42085d3f4ae5c6ceecaffde79fb3187712a2af00..3043378c3addf959e0ccf323c1cde8b300b5f237 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -274,6 +274,7 @@ public class Item implements ItemLike { + return false; + } + ++ public Multimap getAttributesForSlot(EquipmentSlot enumItemSlot) { return getDefaultAttributeModifiers(enumItemSlot); } // Paper - OBFHELPER + public Multimap getDefaultAttributeModifiers(EquipmentSlot slot) { + return ImmutableMultimap.of(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 34eed57c7ed884e0d634ca403e38d25c95b6a038..824111fc74bade75ce06b1f0b57498006d0a66cd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -493,6 +493,19 @@ public final class CraftMagicNumbers implements UnsafeValues { + return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); + } + ++ @Override ++ public com.google.common.collect.Multimap getItemAttributes(org.bukkit.Material material, org.bukkit.inventory.EquipmentSlot equipmentSlot) { ++ Item item = this.getItem(material); ++ if (item == null) { ++ throw new IllegalArgumentException(material + " is not an item and therefore does not have attributes"); ++ } ++ com.google.common.collect.ImmutableMultimap.Builder attributeMapBuilder = com.google.common.collect.ImmutableMultimap.builder(); ++ item.getAttributesForSlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(equipmentSlot)).forEach((attributeBase, attributeModifier) -> { ++ attributeMapBuilder.put(org.bukkit.Registry.ATTRIBUTE.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.Registry.ATTRIBUTE.getKey(attributeBase))), org.bukkit.craftbukkit.attribute.CraftAttributeInstance.convert(attributeModifier)); ++ }); ++ return attributeMapBuilder.build(); ++ } ++ + @Override + public int getProtocolVersion() { + return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion(); diff --git a/Remapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/Remapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch new file mode 100644 index 0000000000..339837dc3e --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexander +Date: Thu, 6 May 2021 13:01:25 +0100 +Subject: [PATCH] Have CraftMerchantCustom emit PlayerPurchaseEvent + + +diff --git a/src/main/java/net/minecraft/world/item/trading/Merchant.java b/src/main/java/net/minecraft/world/item/trading/Merchant.java +index 8298e667aa3a17d987bbc4cc2b63600af48beabc..334df355470bff98db63396b33c8db6a0abcc61a 100644 +--- a/src/main/java/net/minecraft/world/item/trading/Merchant.java ++++ b/src/main/java/net/minecraft/world/item/trading/Merchant.java +@@ -19,7 +19,7 @@ public interface Merchant { + + MerchantOffers getOffers(); + +- void notifyTrade(MerchantOffer offer); ++ void notifyTrade(MerchantOffer offer); default void handlePurchase(MerchantOffer merchantRecipe) { notifyTrade(merchantRecipe); } // Paper - OBFHELPER + + void notifyTradeUpdated(ItemStack stack); + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +index 306c6483708ae1b41bd16f122d36beec1916a776..d52192545c39734be3c97c7978652a54d7b9f029 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +@@ -81,6 +81,35 @@ public class CraftMerchantCustom extends CraftMerchant { + + @Override + public void notifyTrade(MerchantOffer offer) { ++ // Paper start ++ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerAbstract#b(MerchantRecipe)} */ ++ if (getTradingPlayer() instanceof net.minecraft.server.level.ServerPlayer) { ++ final net.minecraft.server.level.ServerPlayer trader = (net.minecraft.server.level.ServerPlayer) getTradingPlayer(); ++ final io.papermc.paper.event.player.PlayerPurchaseEvent event = new io.papermc.paper.event.player.PlayerPurchaseEvent( ++ trader.getBukkitEntity(), ++ offer.asBukkit(), ++ false, // reward xp? ++ true); // should increase uses? ++ event.callEvent(); ++ if (event.isCancelled()) { ++ return; ++ } ++ final org.bukkit.inventory.MerchantRecipe eventTrade = event.getTrade(); ++ if (event.willIncreaseTradeUses()) { ++ eventTrade.setUses(eventTrade.getUses() + 1); ++ } ++ if (event.isRewardingExp() && eventTrade.hasExperienceReward()) { ++ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerTrader#b(MerchantRecipe)} */ ++ final int xp = 3 + net.minecraft.world.entity.Entity.SHARED_RANDOM.nextInt(4); ++ final Level world = trader.getCommandSenderWorld(); ++ world.addFreshEntity(new net.minecraft.world.entity.ExperienceOrb( ++ world, trader.getX(), trader.getY() + 0.5d, trader.getZ(), xp, ++ org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, trader, null)); ++ } ++ return; ++ } ++ // Paper end ++ + // increase recipe's uses + offer.increaseUses(); + } diff --git a/Remapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch b/Remapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch new file mode 100644 index 0000000000..fb889a4693 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch @@ -0,0 +1,136 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 2 Dec 2020 18:23:26 -0800 +Subject: [PATCH] Add cause to Weather/ThunderChangeEvents + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 511e6a941d441c55a4b38660f0f7f8c47fa689dd..85e62e3c52950a517c4dbae739d21d879cb467a4 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -413,8 +413,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.worldDataServer.setClearWeatherTime(clearDuration); + this.worldDataServer.setRainTime(rainDuration); + this.worldDataServer.setThunderTime(rainDuration); +- this.worldDataServer.setRaining(raining); +- this.worldDataServer.setThundering(thundering); ++ this.worldDataServer.setRaining(raining, org.bukkit.event.weather.WeatherChangeEvent.Cause.COMMAND); // Paper ++ this.worldDataServer.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.COMMAND); // Paper + } + + public Biome getBiomeBySeed(int i, int j, int k) { return getUncachedNoiseBiome(i, j, k); } // Paper - OBFHELPER +@@ -476,8 +476,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.worldDataServer.setThunderTime(j); + this.worldDataServer.setRainTime(k); + this.worldDataServer.setClearWeatherTime(i); +- this.worldDataServer.setThundering(flag1); +- this.worldDataServer.setRaining(flag2); ++ this.worldDataServer.setThundering(flag1, org.bukkit.event.weather.ThunderChangeEvent.Cause.NATURAL); // Paper ++ this.worldDataServer.setRaining(flag2, org.bukkit.event.weather.WeatherChangeEvent.Cause.NATURAL); // Paper + } + + this.oThunderLevel = this.thunderLevel; +@@ -879,14 +879,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + private void stopWeather() { + // CraftBukkit start +- this.worldDataServer.setRaining(false); ++ this.worldDataServer.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - when passing the night + // If we stop due to everyone sleeping we should reset the weather duration to some other random value. + // Not that everyone ever manages to get the whole server to sleep at the same time.... + if (!this.worldDataServer.isRaining()) { + this.worldDataServer.setRainTime(0); + } + // CraftBukkit end +- this.worldDataServer.setThundering(false); ++ this.worldDataServer.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - when passing the night + // CraftBukkit start + // If we stop due to everyone sleeping we should reset the weather duration to some other random value. + // Not that everyone ever manages to get the whole server to sleep at the same time.... +diff --git a/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java b/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java +index 83f2fdfa1ac2435f5199b5c33bfc409d2e94f4ed..e902534fd64f72e46feefa04f526e0dacd612627 100644 +--- a/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java ++++ b/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java +@@ -325,21 +325,26 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { + + @Override + public void setThundering(boolean thundering) { ++ // Paper start ++ this.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.UNKNOWN); ++ } ++ public void setThundering(boolean flag, org.bukkit.event.weather.ThunderChangeEvent.Cause cause) { ++ // Paper end + // CraftBukkit start +- if (this.thundering == thundering) { ++ if (this.thundering == flag) { + return; + } + + org.bukkit.World world = Bukkit.getWorld(getLevelName()); + if (world != null) { +- ThunderChangeEvent thunder = new ThunderChangeEvent(world, thundering); ++ ThunderChangeEvent thunder = new ThunderChangeEvent(world, flag, cause); // Paper + Bukkit.getServer().getPluginManager().callEvent(thunder); + if (thunder.isCancelled()) { + return; + } + } + // CraftBukkit end +- this.thundering = thundering; ++ this.thundering = flag; + } + + @Override +@@ -359,21 +364,27 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { + + @Override + public void setRaining(boolean raining) { ++ // Paper start ++ this.setRaining(raining, org.bukkit.event.weather.WeatherChangeEvent.Cause.UNKNOWN); ++ } ++ ++ public void setStorm(boolean flag, org.bukkit.event.weather.WeatherChangeEvent.Cause cause) { ++ // Paper end + // CraftBukkit start +- if (this.raining == raining) { ++ if (this.raining == flag) { + return; + } + + org.bukkit.World world = Bukkit.getWorld(getLevelName()); + if (world != null) { +- WeatherChangeEvent weather = new WeatherChangeEvent(world, raining); ++ WeatherChangeEvent weather = new WeatherChangeEvent(world, flag, cause); // Paper + Bukkit.getServer().getPluginManager().callEvent(weather); + if (weather.isCancelled()) { + return; + } + } + // CraftBukkit end +- this.raining = raining; ++ this.raining = flag; + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index a1fa2d5e00bd125abd38a00e0bc3936f2fb8186f..1c9321cef1a05c5e8a22dd52bc63a5103eaf7311 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1452,7 +1452,7 @@ public class CraftWorld implements World { + + @Override + public void setStorm(boolean hasStorm) { +- world.levelData.setRaining(hasStorm); ++ world.worldDataServer.setRaining(hasStorm, org.bukkit.event.weather.WeatherChangeEvent.Cause.PLUGIN); // Paper + setWeatherDuration(0); // Reset weather duration (legacy behaviour) + setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) + } +@@ -1474,7 +1474,7 @@ public class CraftWorld implements World { + + @Override + public void setThundering(boolean thundering) { +- world.worldDataServer.setThundering(thundering); ++ world.worldDataServer.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.PLUGIN); // Paper + setThunderDuration(0); // Reset weather duration (legacy behaviour) + setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) + } diff --git a/Remapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch b/Remapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch new file mode 100644 index 0000000000..5a3dcda899 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: LemonCaramel +Date: Sun, 23 May 2021 17:49:51 +0900 +Subject: [PATCH] More Lidded Block API + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java +index 8f0477d9620ef71e10855bbca07f9b6984d5d794..70ca456fad052ca6eeaf8c4242c78d15d81084a5 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java +@@ -10,8 +10,9 @@ public class EnderChestBlockEntity extends BlockEntity { // Paper - Remove ITick + + public float openness; + public float oOpenness; +- public int openCount; ++ public int openCount; public int getViewerCount() { return openCount; } // Paper - OBFHELPER + private int tickInterval; ++ public boolean opened; // Paper - More Lidded Block API + + public EnderChestBlockEntity() { + super(BlockEntityType.ENDER_CHEST); +@@ -106,12 +107,14 @@ public class EnderChestBlockEntity extends BlockEntity { // Paper - Remove ITick + + public void startOpen() { + ++this.openCount; ++ if (opened) return; // Paper - More Lidded Block API + this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); + doOpenLogic(); // Paper + } + + public void stopOpen() { + --this.openCount; ++ if (opened) return; // Paper - More Lidded Block API + this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); + doCloseLogic(); // Paper + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java +index a0eadcbcb2575eb18f7b4951ae9eadfbc2e8af6f..fc4397a48425a23d64e0a679ace9e58fbf9b770b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java +@@ -59,4 +59,11 @@ public class CraftBarrel extends CraftLootable implements Bar + } + getTileEntity().opened = false; + } ++ ++ // Paper start - More Lidded Block API ++ @Override ++ public boolean isOpen() { ++ return getTileEntity().opened; ++ } ++ // Paper end - More Lidded Block API + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +index a821df3e13e2ddc479dc5f55540671f43563cdac..9d7af8717085ba5c170a998aa863686d72840a40 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +@@ -78,4 +78,11 @@ public class CraftChest extends CraftLootable implements Chest + } + getTileEntity().opened = false; + } ++ ++ // Paper start - More Lidded Block API ++ @Override ++ public boolean isOpen() { ++ return getTileEntity().opened; ++ } ++ // Paper end - More Lidded Block API + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java +index 25add8bee6ea35beeb205dd828759304346e4f48..fabcb2b8dc950fd074d65fed95d6b371dcfbf842 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java +@@ -14,4 +14,33 @@ public class CraftEnderChest extends CraftBlockEntityState implem + if (getTileEntity().opened) { + Level world = getTileEntity().getLevel(); + world.blockEvent(getPosition(), getTileEntity().getBlockState().getBlock(), 1, 0); +- world.playSound(null, getPosition(), SoundEvents.SHULKER_BOX_OPEN, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); ++ world.playSound(null, getPosition(), SoundEvents.SHULKER_BOX_CLOSE, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); // Paper - More Lidded Block API (Wrong sound) + } + getTileEntity().opened = false; + } ++ ++ // Paper start - More Lidded Block API ++ @Override ++ public boolean isOpen() { ++ return getTileEntity().opened; ++ } ++ // Paper end - More Lidded Block API + } diff --git a/Remapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch b/Remapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch new file mode 100644 index 0000000000..82c7b23bb7 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch @@ -0,0 +1,393 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 20:30:45 -0700 +Subject: [PATCH] Add PlayerKickEvent causes + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 9d7cebd703bd0171ca3e95d2985c1a52fdb59712..9e3b8c7478d97bf65a875807a268d1c98389c1f8 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2041,7 +2041,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 80) { + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); +- this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_PLAYER); // Paper - use configurable kick message & kick event cause + return; + } + } else { +@@ -346,7 +346,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) { + if (++this.aboveGroundVehicleTickCount > 80) { + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); +- this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_VEHICLE); // Paper - use configurable kick message & kick event cause + return; + } + } else { +@@ -368,7 +368,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + if (this.isPendingPing()) { + if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info +- this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0])); ++ this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause + } + } else { + if (elapsedTime >= 15000L) { // 15 seconds +@@ -398,7 +398,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) (this.server.getPlayerIdleTimeout() * 1000 * 60)) { + this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause + } + + } +@@ -423,14 +423,22 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + public void disconnect(String s) { + // Paper start +- this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); ++ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); ++ } ++ ++ public void disconnect(String s, PlayerKickEvent.Cause cause) { ++ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s), cause); + } + + public void disconnect(final Component reason) { +- this.disconnect(PaperAdventure.asAdventure(reason)); ++ this.disconnect(PaperAdventure.asAdventure(reason), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); ++ } ++ ++ public void disconnect(final Component reason, PlayerKickEvent.Cause cause) { ++ this.disconnect(PaperAdventure.asAdventure(reason), cause); + } + +- public void disconnect(net.kyori.adventure.text.Component reason) { ++ public void disconnect(net.kyori.adventure.text.Component reason, org.bukkit.event.player.PlayerKickEvent.Cause cause) { + // Paper end + // CraftBukkit start - fire PlayerKickEvent + if (this.processedDisconnect) { +@@ -438,7 +446,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure + +- PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure ++ PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), reason, leaveMessage, cause); // Paper - Adventure & kick event reason + + if (this.craftServer.getServer().isRunning()) { + this.craftServer.getPluginManager().callEvent(event); +@@ -516,7 +524,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + public void handleMoveVehicle(ServerboundMoveVehiclePacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (containsInvalidValues(packet)) { +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_vehicle_movement")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_vehicle_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_VEHICLE_MOVEMENT); // Paper - kick event cause + } else { + Entity entity = this.player.getRootVehicle(); + +@@ -750,13 +758,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async + // CraftBukkit start + if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable +- server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause + return; + } + // Paper start + String str = packet.getCommand(); int index = -1; + if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { +- server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause + return; + } + // Paper end +@@ -904,7 +912,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // Paper start - validate pick item position + if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.inventory.items.size())) { + ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); +- this.disconnect("Invalid hotbar selection (Hacking?)"); ++ this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause + return; + } + this.player.inventory.pickSlot(packet.getSlot()); // Paper - Diff above if changed +@@ -1058,7 +1066,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + ListTag pageList = testStack.getTag().getList("pages", 8); + if (pageList.size() > 100) { + ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with too many pages"); +- server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause + return; + } + long byteTotal = 0; +@@ -1070,7 +1078,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; + if (byteLength > 256 * 4) { + ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!"); +- server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause + return; + } + byteTotal += byteLength; +@@ -1093,14 +1101,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + if (byteTotal > byteAllowed) { + ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); +- server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause + return; + } + } + // Paper end + // CraftBukkit start + if (this.lastBookTick + 20 > MinecraftServer.currentTick) { +- this.disconnect("Book edited too quickly!"); ++ this.disconnect("Book edited too quickly!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause + return; + } + this.lastBookTick = MinecraftServer.currentTick; +@@ -1212,7 +1220,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + public void handleMovePlayer(ServerboundMovePlayerPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (containsInvalidValues(packet)) { +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause + } else { + ServerLevel worldserver = this.player.getLevel(); + +@@ -1611,7 +1619,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.dropCount++; + if (this.dropCount >= 20) { + LOGGER.warn(this.player.getScoreboardName() + " dropped their items too quickly!"); +- this.disconnect("You dropped your items too quickly (Hacking?)"); ++ this.disconnect("You dropped your items too quickly (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause + return; + } + } +@@ -1924,7 +1932,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.player.resetLastActionTime(); + } else { + ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); +- this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit ++ this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // CraftBukkit // Paper - kick event cause + } + } + +@@ -1961,7 +1969,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + Waitable waitable = new Waitable() { + @Override + protected Object evaluate() { +- ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters")); ++ ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause + return null; + } + }; +@@ -1976,7 +1984,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + throw new RuntimeException(e); + } + } else { +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause + } + // CraftBukkit end + return; +@@ -2030,7 +2038,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + Waitable waitable = new Waitable() { + @Override + protected Object evaluate() { +- ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("disconnect.spam")); ++ ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause + return null; + } + }; +@@ -2045,7 +2053,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + throw new RuntimeException(e); + } + } else { +- this.disconnect(new TranslatableComponent("disconnect.spam")); ++ this.disconnect(new TranslatableComponent("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause + } + // CraftBukkit end + } +@@ -2318,7 +2326,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // Spigot Start + if ( entity == player && !player.isSpectator() ) + { +- disconnect( "Cannot interact with self!" ); ++ disconnect( "Cannot interact with self!", org.bukkit.event.player.PlayerKickEvent.Cause.SELF_INTERACTION ); // Paper - kick event cause + return; + } + // Spigot End +@@ -2395,7 +2403,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit end + } else if (packet.getAction() == ServerboundInteractPacket.Action.ATTACK) { + if (entity instanceof ItemEntity || entity instanceof ExperienceOrb || entity instanceof AbstractArrow || (entity == this.player && !player.isSpectator())) { // CraftBukkit +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_ENTITY_ATTACKED); // Paper - kick event cause + ServerGamePacketListenerImpl.LOGGER.warn("Player {} tried to attack an invalid entity", this.player.getName().getString()); + return; + } +@@ -2800,7 +2808,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // Paper start + if (!Bukkit.isPrimaryThread()) { + if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { +- server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause + return; + } + } +@@ -2999,7 +3007,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } else if (!this.isSingleplayerOwner()) { + // Paper start - This needs to be handled on the main thread for plugins + server.scheduleOnMain(() -> { +- this.disconnect(new TranslatableComponent("disconnect.timeout")); ++ this.disconnect(new TranslatableComponent("disconnect.timeout"), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause + }); + // Paper end + } +@@ -3045,7 +3053,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + } catch (Exception ex) { + ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex); +- this.disconnect("Invalid payload REGISTER!"); ++ this.disconnect("Invalid payload REGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause + } + } else if (packet.identifier.equals(CUSTOM_UNREGISTER)) { + try { +@@ -3055,7 +3063,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + } catch (Exception ex) { + ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t unregister custom payload", ex); +- this.disconnect("Invalid payload UNREGISTER!"); ++ this.disconnect("Invalid payload UNREGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause + } + } else { + try { +@@ -3074,7 +3082,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + craftServer.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packet.identifier.toString(), data); + } catch (Exception ex) { + ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); +- this.disconnect("Invalid custom payload!"); ++ this.disconnect("Invalid custom payload!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause + } + } + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 6011b43ae8a858f88b8fcf6dc0bf147024a4742c..9e138bf9f9ee4efee462271d1a69a2126aa94946 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -716,7 +716,7 @@ public abstract class PlayerList { + while (iterator.hasNext()) { + entityplayer = (ServerPlayer) iterator.next(); + save(entityplayer); // CraftBukkit - Force the player's inventory to be saved +- entityplayer.connection.disconnect(new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0])); ++ entityplayer.connection.disconnect(new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause + } + + // Instead of kicking then returning, we need to store the kick reason +@@ -1385,8 +1385,8 @@ public abstract class PlayerList { + public void shutdown(boolean isRestarting) { + // CraftBukkit start - disconnect safely + for (ServerPlayer player : this.players) { +- if (isRestarting) player.connection.disconnect(org.spigotmc.SpigotConfig.restartMessage); else // Paper +- player.connection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure ++ if (isRestarting) player.connection.disconnect(org.spigotmc.SpigotConfig.restartMessage, org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); else // Paper - kick event cause (cause is never used here) ++ player.connection.disconnect(this.server.server.shutdownMessage(), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); // CraftBukkit - add custom shutdown message // Paper - Adventure & KickEventCause (cause is never used here) + } + // CraftBukkit end + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 3dbe94d9b9647f5cc1e27335b36042e50c652cea..97aec6370a8a24a13ae04443d03f250f8938b2e0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -495,16 +495,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + org.spigotmc.AsyncCatcher.catchOp("player kick"); // Spigot + if (getHandle().connection == null) return; + +- getHandle().connection.disconnect(message == null ? "" : message); ++ getHandle().connection.disconnect(message == null ? "" : message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause + } + + // Paper start + @Override + public void kick(final net.kyori.adventure.text.Component message) { ++ kick(message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); ++ } ++ ++ @Override ++ public void kick(net.kyori.adventure.text.Component message, org.bukkit.event.player.PlayerKickEvent.Cause cause) { + org.spigotmc.AsyncCatcher.catchOp("player kick"); + final ServerGamePacketListenerImpl connection = this.getHandle().connection; + if (connection != null) { +- connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); ++ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message, cause); + } + } + // Paper end +diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java +index 6498dc4c6630bfef1a52edf74d8574e5e4876720..ea1f088ac94616978af5e01a59c558cd2db4b619 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(SpigotConfig.restartMessage); ++ p.connection.disconnect(SpigotConfig.restartMessage, 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/Remapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch b/Remapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch new file mode 100644 index 0000000000..276c9629f2 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Yive +Date: Wed, 26 May 2021 15:09:33 -0700 +Subject: [PATCH] Limit item frame cursors on maps + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 108a005c296c4ed370de4af636163088971bed13..9287dfcf29ce6f89a937f4e10b70be8faab9ab9e 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -816,4 +816,9 @@ public class PaperWorldConfig { + private void allowUsingSignsInsideSpawnProtection() { + allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); + } ++ ++ public int mapItemFrameCursorLimit = 128; ++ private void mapItemFrameCursorLimit() { ++ mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +index e7b178127228dea5a17ba0fbd6bae148d70e8eb5..e2f550c833030d8ad12b80d3d379f4731ddeb2ec 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -279,8 +279,12 @@ public class MapItemSavedData extends SavedData { + + MapFrame worldmapframe1 = new MapFrame(blockposition, entityitemframe.getDirection().get2DDataValue() * 90, entityitemframe.getId()); + ++ // Paper start ++ if (this.decorations.size() < player.level.paperConfig.mapItemFrameCursorLimit) { + this.addDecoration(MapDecoration.Type.FRAME, player.level, "frame-" + entityitemframe.getId(), (double) blockposition.getX(), (double) blockposition.getZ(), (double) (entityitemframe.getDirection().get2DDataValue() * 90), (Component) null); + this.frameMarkers.put(worldmapframe1.getId(), worldmapframe1); ++ } ++ // Paper end + } + + CompoundTag nbttagcompound = stack.getTag(); diff --git a/Remapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch b/Remapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch new file mode 100644 index 0000000000..58dca35d6b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Mon, 10 May 2021 16:59:05 +0100 +Subject: [PATCH] Add PufferFishStateChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java +index eb80bde66fbb03dad845e36f1bd1a8eaf8592fbf..44b7b62622d65326aa3926764bb1bb1ed8694511 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java +@@ -89,25 +89,39 @@ public class Pufferfish extends AbstractFish { + public void tick() { + if (!this.level.isClientSide && this.isAlive() && this.isEffectiveAi()) { + if (this.inflateCounter > 0) { ++ boolean increase = true; // Paper - Add PufferFishStateChangeEvent + if (this.getPuffState() == 0) { ++ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent + this.playSound(SoundEvents.PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.getVoicePitch()); + this.setPuffState(1); ++ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent + } else if (this.inflateCounter > 40 && this.getPuffState() == 1) { ++ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 2).callEvent()) { // Paper - Add PufferFishStateChangeEvent + this.playSound(SoundEvents.PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.getVoicePitch()); + this.setPuffState(2); ++ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent + } + ++ if (increase) { // Paper - Add PufferFishStateChangeEvent + ++this.inflateCounter; ++ } // Paper - Add PufferFishStateChangeEvent + } else if (this.getPuffState() != 0) { ++ boolean increase = true; // Paper - Add PufferFishStateChangeEvent + if (this.deflateTimer > 60 && this.getPuffState() == 2) { ++ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent + this.playSound(SoundEvents.PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.getVoicePitch()); + this.setPuffState(1); ++ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent + } else if (this.deflateTimer > 100 && this.getPuffState() == 1) { ++ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 0).callEvent()) { // Paper - Add PufferFishStateChangeEvent + this.playSound(SoundEvents.PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.getVoicePitch()); + this.setPuffState(0); ++ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent + } + ++ if (increase) { // Paper - Add PufferFishStateChangeEvent + ++this.deflateTimer; ++ } // Paper - Add PufferFishStateChangeEvent + } + } + diff --git a/Remapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/Remapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch new file mode 100644 index 0000000000..85fe9b3b12 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 20 May 2021 22:16:37 -0700 +Subject: [PATCH] Fix PlayerBucketEmptyEvent result itemstack + +Fixes SPIGOT-2560: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-2560 + +diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java +index d0e847e58483695d2af1c1410826bb25231cd6f6..08c00a084b2972420eae020e13480489b29aec64 100644 +--- a/src/main/java/net/minecraft/world/item/BucketItem.java ++++ b/src/main/java/net/minecraft/world/item/BucketItem.java +@@ -116,6 +116,13 @@ public class BucketItem extends Item { + } + + protected ItemStack getEmptySuccessItem(ItemStack stack, Player player) { ++ // Paper ++ if (itemLeftInHandAfterPlayerBucketEmptyEvent != null) { ++ ItemStack itemInHand = itemLeftInHandAfterPlayerBucketEmptyEvent; ++ itemLeftInHandAfterPlayerBucketEmptyEvent = null; ++ return itemInHand; ++ } ++ // Paper + return !player.abilities.instabuild ? new ItemStack(Items.BUCKET) : stack; + } + +@@ -126,6 +133,7 @@ public class BucketItem extends Item { + return a(player, world, pos, movingobjectpositionblock, null, null, null, null); + } + ++ private ItemStack itemLeftInHandAfterPlayerBucketEmptyEvent = null; // Paper + public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, InteractionHand enumhand) { + // Paper end + // CraftBukkit end +@@ -146,6 +154,9 @@ public class BucketItem extends Item { + ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 + return false; + } ++ // Paper start ++ itemLeftInHandAfterPlayerBucketEmptyEvent = event.getItemStack().equals(CraftItemStack.asNewCraftStack(net.minecraft.world.item.Items.BUCKET)) ? null : CraftItemStack.asNMSCopy(event.getItemStack()); ++ // Paper end + } + // CraftBukkit end + if (!flag1) { diff --git a/Remapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch b/Remapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch new file mode 100644 index 0000000000..3cd329efc6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: GioSDA +Date: Wed, 10 Mar 2021 10:06:45 -0800 +Subject: [PATCH] Add option to fix items merging through walls + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 9287dfcf29ce6f89a937f4e10b70be8faab9ab9e..74f2413773fbe30597314e02a5284172e0fc40b2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -821,4 +821,9 @@ public class PaperWorldConfig { + private void mapItemFrameCursorLimit() { + mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); + } ++ ++ public boolean fixItemsMergingThroughWalls; ++ private void fixItemsMergingThroughWalls() { ++ fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 7476ae301fb4ee503944d39022cb25ccb19f1232..d937a74d2e822c8542286fb5bcdfcec7895d845c 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -227,6 +227,14 @@ public class ItemEntity extends Entity { + ItemEntity entityitem = (ItemEntity) iterator.next(); + + if (entityitem.isMergable()) { ++ // Paper Start - Fix items merging through walls ++ if (this.level.paperConfig.fixItemsMergingThroughWalls) { ++ net.minecraft.world.level.ClipContext rayTrace = new net.minecraft.world.level.ClipContext(this.position(), entityitem.position(), ++ net.minecraft.world.level.ClipContext.Block.COLLIDER, net.minecraft.world.level.ClipContext.Fluid.NONE, this); ++ net.minecraft.world.phys.BlockHitResult rayTraceResult = level.clip(rayTrace); ++ if (rayTraceResult.getType() == net.minecraft.world.phys.HitResult.Type.BLOCK) continue; ++ } ++ // Paper End + this.tryToMerge(entityitem); + if (this.removed) { + break; diff --git a/Remapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch b/Remapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch new file mode 100644 index 0000000000..78020871e6 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Wed, 26 May 2021 17:09:07 -0400 +Subject: [PATCH] Add BellRevealRaiderEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +index 3f9179a7678091875161a34d13b6ec0e78025c4c..03c2831a7c4f310936dad1ee72f402ed38f3c9e7 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -6,6 +6,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.Position; + import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.EntityTypeTags; +@@ -181,6 +182,7 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity + } + + private void glow(LivingEntity entity) { ++ if (!new io.papermc.paper.event.block.BellRevealRaiderEvent(level.getWorld().getBlockAt(MCUtil.toLocation(level, worldPosition)), entity.getBukkitEntity()).callEvent()) return; // Paper - BellRevealRaiderEvent + entity.addEffect(new MobEffectInstance(MobEffects.GLOWING, 60)); + } + } diff --git a/Remapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch b/Remapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch new file mode 100644 index 0000000000..d830a00fa4 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch @@ -0,0 +1,105 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Max Lee +Date: Thu, 27 May 2021 14:52:30 -0700 +Subject: [PATCH] Fix invulnerable end crystals + +MC-108513 + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 74f2413773fbe30597314e02a5284172e0fc40b2..dc5ebbb44238cb5928f385d2962c9057388575f8 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -826,4 +826,9 @@ public class PaperWorldConfig { + private void fixItemsMergingThroughWalls() { + fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); + } ++ ++ public boolean fixInvulnerableEndCrystalExploit = true; ++ private void fixInvulnerableEndCrystalExploit() { ++ fixInvulnerableEndCrystalExploit = getBoolean("unsupported-settings.fix-invulnerable-end-crystal-exploit", fixInvulnerableEndCrystalExploit); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +index 6292d04464950ac52fcd6d69345db5125d3127eb..8583209750e4bb70e86d7243a47c525f1726ee42 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +@@ -29,6 +29,7 @@ public class EndCrystal extends Entity { + private static final EntityDataAccessor> DATA_BEAM_TARGET = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.OPTIONAL_BLOCK_POS); + private static final EntityDataAccessor DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN); + public int time; ++ public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals + + public EndCrystal(EntityType type, Level world) { + super(type, world); +@@ -65,6 +66,17 @@ public class EndCrystal extends Entity { + } + // CraftBukkit end + } ++ // Paper start - Fix invulnerable end crystals ++ if (this.level.paperConfig.fixInvulnerableEndCrystalExploit && this.generatedByDragonFight && this.isInvulnerable()) { ++ if ((this.origin.getWorld() != null && !((ServerLevel) this.level).uuid.equals(this.origin.getWorld().getUID())) ++ || ((ServerLevel) this.level).dragonFight() == null ++ || ((ServerLevel) this.level).dragonFight().respawnStage == null ++ || ((ServerLevel) this.level).dragonFight().respawnStage.ordinal() > net.minecraft.world.level.dimension.end.DragonRespawnAnimation.SUMMONING_DRAGON.ordinal()) { ++ this.setInvulnerable(false); ++ this.setBeamTarget(null); ++ } ++ } ++ // Paper end + } + + } +@@ -76,6 +88,7 @@ public class EndCrystal extends Entity { + } + + tag.putBoolean("ShowBottom", this.showsBottom()); ++ if (this.generatedByDragonFight) tag.putBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals + } + + @Override +@@ -87,6 +100,7 @@ public class EndCrystal extends Entity { + if (tag.contains("ShowBottom", 1)) { + this.setShowBottom(tag.getBoolean("ShowBottom")); + } ++ if (tag.contains("Paper.GeneratedByDragonFight", 1)) this.generatedByDragonFight = tag.getBoolean("Paper.GeneratedByDragonFight"); // Paper - Fix invulnerable end crystals + + } + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java +index b99576b524a65cc1a0de88c49324d929503d655f..d51d2fb6d24bfee63b04f32f2cb157fec9d8ee6c 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java +@@ -42,11 +42,11 @@ public class SpikeFeature extends Feature { + return (List) SpikeFeature.SPIKE_CACHE.getUnchecked(i); + } + +- public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, SpikeConfiguration config) { +- List list = config.getSpikes(); ++ public boolean generate(WorldGenLevel generatoraccessseed, ChunkGenerator chunkgenerator, Random random, BlockPos blockposition, SpikeConfiguration worldgenfeatureendspikeconfiguration) { // Paper - decompile fix ++ List list = worldgenfeatureendspikeconfiguration.getSpikes(); + + if (list.isEmpty()) { +- list = getSpikesForLevel(world); ++ list = getSpikesForLevel(generatoraccessseed); + } + + Iterator iterator = list.iterator(); +@@ -54,8 +54,8 @@ public class SpikeFeature extends Feature { + while (iterator.hasNext()) { + SpikeFeature.EndSpike worldgenender_spike = (SpikeFeature.EndSpike) iterator.next(); + +- if (worldgenender_spike.isCenterWithinChunk(pos)) { +- this.placeSpike(world, random, config, worldgenender_spike); ++ if (worldgenender_spike.isCenterWithinChunk(blockposition)) { ++ this.placeSpike(generatoraccessseed, random, worldgenfeatureendspikeconfiguration, worldgenender_spike); + } + } + +@@ -106,6 +106,7 @@ public class SpikeFeature extends Feature { + entityendercrystal.setBeamTarget(config.getCrystalBeamTarget()); + entityendercrystal.setInvulnerable(config.isCrystalInvulnerable()); + entityendercrystal.moveTo((double) spike.getCenterX() + 0.5D, (double) (spike.getHeight() + 1), (double) spike.getCenterZ() + 0.5D, random.nextFloat() * 360.0F, 0.0F); ++ entityendercrystal.generatedByDragonFight = true; + world.addFreshEntity(entityendercrystal); + this.setBlock(world, new BlockPos(spike.getCenterX(), spike.getHeight(), spike.getCenterZ()), Blocks.BEDROCK.defaultBlockState()); + } diff --git a/Remapped-Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch b/Remapped-Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch new file mode 100644 index 0000000000..2e0af7d211 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Fri, 19 Mar 2021 23:39:09 -0400 +Subject: [PATCH] Add ElderGuardianAppearanceEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +index b6a842f9a24634ff84f2f4f94c0f2838f10cddb0..0cf6a06f8bddac0a2a1a00f3a4b266116f7ae594 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java ++++ b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +@@ -77,10 +77,12 @@ public class ElderGuardian extends Guardian { + while (iterator.hasNext()) { + ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + ++ if (new io.papermc.paper.event.entity.ElderGuardianAppearanceEvent(getBukkitEntity(), entityplayer.getBukkitEntity()).callEvent()) { // Paper - Add Guardian Appearance Event + if (!entityplayer.hasEffect(mobeffectlist) || entityplayer.getEffect(mobeffectlist).getAmplifier() < 2 || entityplayer.getEffect(mobeffectlist).getDuration() < 1200) { + entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)); + entityplayer.addEffect(new MobEffectInstance(mobeffectlist, 6000, 2), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } ++ } // Paper - Add Guardian Appearance Event + } + } + diff --git a/Remapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch b/Remapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch new file mode 100644 index 0000000000..a6ef1d69fa --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 1 Jun 2021 22:05:08 -0500 +Subject: [PATCH] Reset villager inventory on cancelled pickup event + + +diff --git a/src/main/java/net/minecraft/world/SimpleContainer.java b/src/main/java/net/minecraft/world/SimpleContainer.java +index d6bb1d540e6dcbbad5e5bdf54803c495a4f3e771..3e639f5af83bea6760669696425dffd2d741cc16 100644 +--- a/src/main/java/net/minecraft/world/SimpleContainer.java ++++ b/src/main/java/net/minecraft/world/SimpleContainer.java +@@ -34,6 +34,16 @@ public class SimpleContainer implements Container, StackedContentsCompatible { + return this.items; + } + ++ // Paper start ++ public void setContents(List items) { ++ this.items.clear(); ++ for(int i = 0; i < items.size(); i++) { ++ this.items.set(i, items.get(i)); ++ } ++ this.setChanged(); ++ } ++ // Paper end ++ + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } +@@ -148,6 +158,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible { + return itemstack; + } + ++ public ItemStack addItem(ItemStack itemstack) { return addItem(itemstack); } // Paper - OBFHELPER + public ItemStack addItem(ItemStack stack) { + ItemStack itemstack1 = stack.copy(); + +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 7817071b1964b962c8f4017d5bb39d74ca0ca3e4..1fbb7a2db5c362a5fc9e3f81382f729c962e377b 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -844,15 +844,19 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + } + + // CraftBukkit start +- ItemStack remaining = new SimpleContainer(inventorysubcontainer).addItem(itemstack); +- if (CraftEventFactory.callEntityPickupItemEvent(this, item, remaining.getCount(), false).isCancelled()) { ++ // Paper start ++ List contentsSnapshot = new java.util.ArrayList<>(inventorysubcontainer.getContents()); ++ ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); ++ if (CraftEventFactory.callEntityPickupItemEvent(this, item, itemstack1.getCount(), false).isCancelled()) { ++ inventorysubcontainer.setContents(contentsSnapshot); ++ // Paper end + return; + } + // CraftBukkit end + + this.onItemPickup(item); + this.take(item, itemstack.getCount()); +- ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); ++ // ItemStack itemstack1 = inventorysubcontainer.a(itemstack); // Paper - moved up + + if (itemstack1.isEmpty()) { + item.remove(); diff --git a/Remapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch b/Remapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch new file mode 100644 index 0000000000..a1fbfe0408 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 4 Jun 2021 17:06:52 -0400 +Subject: [PATCH] Fix dangerous end portal logic + +End portals could teleport entities during move calls. Stupid +logic given the caller will never expect that kind of thing, +and will result in all kinds of dupes. + +Move the tick logic into the post tick, where portaling was +designed to happen in the first place. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 779b926921fd435620cbbc69ed6f9931a422b652..25711ab723386db0f448c54e18ef069bfcd0dd99 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1020,6 +1020,7 @@ public class ServerPlayer extends Player implements ContainerListener { + return b(destination, TeleportCause.UNKNOWN); + } + ++ @Nullable public final Entity changeDimension(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { return this.b(worldserver, cause); } // Paper - OBFHELPER + @Nullable + public Entity b(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d055b362459e5b4658aa220e16118ee6174c0de4..2462a78d976937cf4737f1ce0bfde2b2b7d5b1f7 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -312,6 +312,37 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + // Paper end - optimise entity tracking + ++ // Paper start - make end portalling safe ++ public BlockPos portalBlock; ++ public ServerLevel portalWorld; ++ public void tickEndPortal() { ++ BlockPos pos = this.portalBlock; ++ ServerLevel world = this.portalWorld; ++ this.portalBlock = null; ++ this.portalWorld = null; ++ ++ if (pos == null || world == null || world != this.level) { ++ return; ++ } ++ ++ if (this.isPassenger() || this.isVehicle() || !this.canChangeDimensions() || this.removed || !this.valid || !this.isAlive()) { ++ return; ++ } ++ ++ ResourceKey resourcekey = world.getTypeKey() == DimensionType.END_LOCATION ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends ++ ServerLevel worldserver = world.getServer().getLevel(resourcekey); ++ ++ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(this.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); ++ event.callEvent(); ++ ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer)this).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); ++ return; ++ } ++ this.teleportTo(worldserver, null); ++ } ++ // Paper end - make end portalling safe ++ + public Entity(EntityType type, Level world) { + this.id = Entity.ENTITY_COUNTER.incrementAndGet(); + this.passengers = Lists.newArrayList(); +@@ -2297,6 +2328,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + this.processPortalCooldown(); ++ this.tickEndPortal(); // Paper - make end portalling safe + } + } + +diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +index 2231680140d0e3c4c10b6722fd13fe0ee55ce294..52884b87b25bef8abfa824f40d02efe3f947f330 100644 +--- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +@@ -3,7 +3,6 @@ package net.minecraft.world.level.block; + import net.minecraft.core.BlockPos; + import net.minecraft.resources.ResourceKey; + import net.minecraft.server.level.ServerLevel; +-import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; +@@ -50,16 +49,10 @@ public class EndPortalBlock extends BaseEntityBlock { + // return; // CraftBukkit - always fire event in case plugins wish to change it + } + +- // CraftBukkit start - Entity in portal +- EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); +- world.getCraftServer().getPluginManager().callEvent(event); +- +- if (entity instanceof ServerPlayer) { +- ((ServerPlayer) entity).b(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); +- return; +- } +- // CraftBukkit end +- entity.changeDimension(worldserver); ++ // Paper start - move all of this logic into portal tick ++ entity.portalWorld = ((ServerLevel)world); ++ entity.portalBlock = pos.immutable(); ++ // Paper end - move all of this logic into portal tick + } + + } diff --git a/Remapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch b/Remapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch new file mode 100644 index 0000000000..964f15ad4b --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 4 Jun 2021 12:12:35 -0700 +Subject: [PATCH] Make item validations configurable + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index efc1e42d606e1c9feb1a4871c0714933ae92a1b2..7acf077bc131af718c7548cc29deef558c04e463 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -486,4 +486,19 @@ public class PaperConfig { + enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); + enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); + } ++ ++ public static int itemValidationDisplayNameLength = 8192; ++ public static int itemValidationLocNameLength = 8192; ++ public static int itemValidationLoreLineLength = 8192; ++ public static int itemValidationBookTitleLength = 8192; ++ public static int itemValidationBookAuthorLength = 8192; ++ public static int itemValidationBookPageLength = 16384; ++ private static void itemValidationSettings() { ++ itemValidationDisplayNameLength = getInt("settings.item-validation.display-name", itemValidationDisplayNameLength); ++ itemValidationLocNameLength = getInt("settings.item-validation.loc-name", itemValidationLocNameLength); ++ itemValidationLoreLineLength = getInt("settings.item-validation.lore-line", itemValidationLoreLineLength); ++ itemValidationBookTitleLength = getInt("settings.item-validation.book.title", itemValidationBookTitleLength); ++ itemValidationBookAuthorLength = getInt("settings.item-validation.book.author", itemValidationBookAuthorLength); ++ itemValidationBookPageLength = getInt("settings.item-validation.book.page", itemValidationBookPageLength); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +index 80397e223990f11c9aa413f3f4ebd7c1b8ce1cff..2ff1619e6898add074481c7ca43bfbf9a8d163ca 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +@@ -94,11 +94,11 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + super(tag); + + if (tag.contains(BOOK_TITLE.NBT)) { +- this.title = limit( tag.getString(BOOK_TITLE.NBT), 8192 ); // Spigot ++ this.title = limit( tag.getString(BOOK_TITLE.NBT), com.destroystokyo.paper.PaperConfig.itemValidationBookTitleLength); // Spigot // Paper - make configurable + } + + if (tag.contains(BOOK_AUTHOR.NBT)) { +- this.author = limit( tag.getString(BOOK_AUTHOR.NBT), 8192 ); // Spigot ++ this.author = limit( tag.getString(BOOK_AUTHOR.NBT), com.destroystokyo.paper.PaperConfig.itemValidationBookAuthorLength ); // Spigot // Paper - make configurable + } + + if (tag.contains(RESOLVED.NBT)) { +@@ -126,7 +126,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + } else { + page = validatePage(page); + } +- this.pages.add( limit( page, 16384 ) ); // Spigot ++ this.pages.add( limit( page, com.destroystokyo.paper.PaperConfig.itemValidationBookPageLength ) ); // Spigot // Paper - make configurable + } + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 20e008277d1188fc7b31bfb2522ef9f6429cc3fb..99e18748b3cc4168b1d15c030f992a128b666d84 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -357,18 +357,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + CompoundTag display = tag.getCompound(DISPLAY.NBT); + + if (display.contains(NAME.NBT)) { +- displayName = limit( display.getString(NAME.NBT), 8192 ); // Spigot ++ displayName = limit( display.getString(NAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationDisplayNameLength); // Spigot // Paper - make configurable + } + + if (display.contains(LOCNAME.NBT)) { +- locName = limit( display.getString(LOCNAME.NBT), 8192 ); // Spigot ++ locName = limit( display.getString(LOCNAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationLocNameLength ); // Spigot // Paper - make configurable + } + + if (display.contains(LORE.NBT)) { + ListTag list = display.getList(LORE.NBT, CraftMagicNumbers.NBT.TAG_STRING); + lore = new ArrayList(list.size()); + for (int index = 0; index < list.size(); index++) { +- String line = limit( list.getString(index), 8192 ); // Spigot ++ String line = limit( list.getString(index), com.destroystokyo.paper.PaperConfig.itemValidationLoreLineLength ); // Spigot // Paper - make configurable + lore.add(line); + } + } diff --git a/Remapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch b/Remapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch new file mode 100644 index 0000000000..2961b16b07 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TwoLeggedCat <80929284+TwoLeggedCat@users.noreply.github.com> +Date: Sat, 29 May 2021 14:33:25 -0500 +Subject: [PATCH] Add more line of sight methods + + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 37787a725725d22b0870dcab0f3bec8b94cfd130..79b43b1b0f8e223f256c2aaec1925426931a9a54 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3091,6 +3091,7 @@ public abstract class LivingEntity extends Entity { + Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); + Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); + ++ // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists + return this.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 1c9321cef1a05c5e8a22dd52bc63a5103eaf7311..312ed9c693cc5108d51ad90e15d6be4bb21904e1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -315,6 +315,17 @@ public class CraftWorld implements World { + public io.papermc.paper.world.MoonPhase getMoonPhase() { + return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); + } ++ ++ @Override ++ public boolean lineOfSightExists(Location from, Location to) { ++ Validate.notNull(from, "from parameter in lineOfSightExists cannot be null"); ++ Validate.notNull(to, "to parameter in lineOfSightExists cannot be null"); ++ if (from.getWorld() != to.getWorld()) return false; ++ Vec3 vec3d = new Vec3(from.getX(), from.getY(), from.getZ()); ++ Vec3 vec3d1 = new Vec3(to.getX(), to.getY(), to.getZ()); ++ ++ return this.getHandle().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, null)).getType() == HitResult.Type.MISS; ++ } + // Paper end + + private static final Random rand = new Random(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 25ba7a26c951fc5e4638bdb0db36e94d3e08fb2e..cd42edd8f36cea3acad76974c39eb0cd1585f73d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -549,6 +549,17 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return getHandle().canSee(((CraftEntity) other).getHandle()); + } + ++ // Paper start ++ @Override ++ public boolean hasLineOfSight(Location loc) { ++ if (this.getHandle().level != ((CraftWorld) loc.getWorld()).getHandle()) return false; ++ Vec3 vec3d = new Vec3(this.getHandle().getX(), this.getHandle().getEyeY(), this.getHandle().getZ()); ++ Vec3 vec3d1 = new Vec3(loc.getX(), loc.getY(), loc.getZ()); ++ ++ return this.getHandle().level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this.getHandle())).getType() == HitResult.Type.MISS; ++ } ++ // Paper end ++ + @Override + public boolean getRemoveWhenFarAway() { + return getHandle() instanceof Mob && !((Mob) getHandle()).persistenceRequired; diff --git a/Remapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch b/Remapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch new file mode 100644 index 0000000000..b4f5cd5335 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chase +Date: Wed, 2 Dec 2020 22:43:39 -0800 +Subject: [PATCH] add per world spawn limits + +Taken from #2982. Credit to Chasewhip8 + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index dc5ebbb44238cb5928f385d2962c9057388575f8..f80186f663ff654ab6b69189941cd26815f65f09 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -652,6 +652,19 @@ public class PaperWorldConfig { + zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); + } + ++ public int spawnLimitMonsters = -1; ++ public int spawnLimitAnimals = -1; ++ public int spawnLimitWaterAnimals = -1; ++ public int spawnLimitWaterAmbient = -1; ++ public int spawnLimitAmbient = -1; ++ private void perWorldSpawnLimits() { ++ spawnLimitMonsters = getInt("spawn-limits.monsters", spawnLimitMonsters); ++ spawnLimitAnimals = getInt("spawn-limits.animals", spawnLimitAnimals); ++ spawnLimitWaterAnimals = getInt("spawn-limits.water-animals", spawnLimitWaterAnimals); ++ spawnLimitWaterAmbient = getInt("spawn-limits.water-ambient", spawnLimitWaterAmbient); ++ spawnLimitAmbient = getInt("spawn-limits.ambient", spawnLimitAmbient); ++ } ++ + public int lightQueueSize = 20; + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 312ed9c693cc5108d51ad90e15d6be4bb21904e1..89aac4214084bd72a83eaaf043b7d47cc0b748f5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -335,6 +335,13 @@ public class CraftWorld implements World { + this.generator = gen; + + environment = env; ++ // Paper start - per world spawn limits ++ this.monsterSpawn = this.world.paperConfig.spawnLimitMonsters; ++ this.animalSpawn = this.world.paperConfig.spawnLimitAnimals; ++ this.waterAnimalSpawn = this.world.paperConfig.spawnLimitWaterAnimals; ++ this.waterAmbientSpawn = this.world.paperConfig.spawnLimitWaterAmbient; ++ this.ambientSpawn = this.world.paperConfig.spawnLimitAmbient; ++ // Paper end + } + + @Override diff --git a/Remapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch b/Remapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch new file mode 100644 index 0000000000..f351ce4533 --- /dev/null +++ b/Remapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 20 May 2021 20:40:53 -0700 +Subject: [PATCH] Fix PotionSplashEvent for water splash potions + +Fixes SPIGOT-6221: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-6221 + +diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java +index ed81d2a306d28561370745bb3389c49012f677a7..fbdfab50af195d219f9745324c8924fc777f76ec 100644 +--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java ++++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java +@@ -99,6 +99,7 @@ public class DamageSource { + return (new IndirectEntityDamageSource("thrown", projectile, attacker)).setProjectile(); + } + ++ public static DamageSource indirectMagic(Entity target, Entity cause) { return indirectMagic(target, cause); } // Paper - OBFHELPER + public static DamageSource indirectMagic(Entity magic, @Nullable Entity attacker) { + return (new IndirectEntityDamageSource("indirectMagic", magic, attacker)).bypassArmor().setMagic(); + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java +index 2ff7e8dfc0a520fb330177c140a1ae5c729f14c0..8bf095bce9dfec6479185b6e60c2e9d76e3363eb 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java +@@ -122,6 +122,7 @@ public class ThrownPotion extends ThrowableItemProjectile { + private void applyWater() { + AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); + List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb, ThrownPotion.WATER_SENSITIVE); ++ Map affected = new HashMap<>(); // Paper + + if (!list.isEmpty()) { + Iterator iterator = list.iterator(); +@@ -131,11 +132,22 @@ public class ThrownPotion extends ThrowableItemProjectile { + double d0 = this.distanceToSqr(entityliving); + + if (d0 < 16.0D && entityliving.isSensitiveToWater()) { +- entityliving.hurt(DamageSource.indirectMagic(entityliving, this.getOwner()), 1.0F); ++ // Paper start ++ double intensity = 1.0D - Math.sqrt(d0) / 4.0D; ++ affected.put(entityliving.getBukkitLivingEntity(), intensity); ++ // entityliving.damageEntity(DamageSource.c(entityliving, this.getShooter()), 1.0F); // Paper - moved down + } + } + } + ++ org.bukkit.event.entity.PotionSplashEvent event = CraftEventFactory.callPotionSplashEvent(this, affected); ++ if (!event.isCancelled()) { ++ for (LivingEntity affectedEntity : event.getAffectedEntities()) { ++ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) affectedEntity).getHandle(); ++ entityliving.hurt(DamageSource.indirectMagic(entityliving, this.getOwner()), 1.0F); ++ } ++ } ++ // Paper end + } + + private void applySplash(List statusEffects, @Nullable Entity entity) { +@@ -153,6 +165,7 @@ public class ThrownPotion extends ThrowableItemProjectile { + double d0 = this.distanceToSqr(entityliving); + + if (d0 < 16.0D) { ++ // Paper - diff on change, used when calling the splash event for water splash potions + double d1 = 1.0D - Math.sqrt(d0) / 4.0D; + + if (entityliving == entity) { From 4d225813a18ba48ff50d3223db01d26d21e9450d Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Fri, 11 Jun 2021 14:02:28 +0200 Subject: [PATCH 007/226] Move patches around --- build.gradle.kts | 3 + patches/api-unmapped/0001-POM-changes.patch | 106 + .../0002-Add-FastUtil-to-Bukkit.patch | 24 + patches/api-unmapped/0003-Paper-Utils.patch | 28 + patches/api-unmapped/0004-Timings-v2.patch | 3759 +++++++++++++ patches/api-unmapped/0005-Adventure.patch | 4124 ++++++++++++++ .../0006-Player-affects-spawning-API.patch | 33 + .../api-unmapped/0007-Add-getTPS-method.patch | 49 + .../api-unmapped/0008-Entity-Origin-API.patch | 66 + .../0009-Version-Command-2.0.patch | 185 + .../0010-Add-PlayerLocaleChangeEvent.patch | 62 + .../0011-Add-player-view-distance-API.patch | 39 + .../0012-Add-BeaconEffectEvent.patch | 98 + .../0013-Add-PlayerInitialSpawnEvent.patch | 29 + ...ly-disable-plugins-that-fail-to-load.patch | 21 + .../0015-Expose-server-CommandMap.patch | 50 + ...cord-chat-API-from-spigot-subclasses.patch | 124 + .../0017-Player-Tab-List-and-Title-APIs.patch | 577 ++ .../0018-Add-exception-reporting-event.patch | 604 ++ ...erverListPingEvent-flagging-as-Async.patch | 27 + ...t-sendMessage-methods-to-CommandSend.patch | 54 + ...working-with-arrows-stuck-in-living-.patch | 30 + .../0022-Complete-resource-pack-API.patch | 118 + .../0023-Use-ASM-for-event-executors.patch | 398 ++ .../0024-Add-a-call-helper-to-Event.patch | 34 + ...der-name-to-commands.yml-replacement.patch | 43 + ...eload-permissions.yml-and-require-co.patch | 104 + ...7-Custom-replacement-for-eaten-items.patch | 48 + ...Entity-AddTo-RemoveFrom-World-Events.patch | 79 + .../0029-EntityPathfindEvent.patch | 95 + ...synchronization-in-MetadataStoreBase.patch | 90 + ...d-MetadataStoreBase.removeAll-Plugin.patch | 46 + ...0032-Add-PlayerUseUnknownEntityEvent.patch | 58 + ...ent-to-allow-plugins-to-handle-clien.patch | 290 + .../0034-Arrow-pickup-rule-API.patch | 49 + ...ityRegainHealthEvent-isFastRegen-API.patch | 42 + patches/api-unmapped/0036-LootTable-API.patch | 402 ++ .../0037-Add-EntityZapEvent.patch | 123 + patches/api-unmapped/0038-Misc-Utils.patch | 46 + ...9-Allow-Reloading-of-Command-Aliases.patch | 108 + ...0-Add-source-to-PlayerExpChangeEvent.patch | 54 + .../0041-Add-ProjectileCollideEvent.patch | 79 + ...0042-Add-String-based-Action-Bar-API.patch | 86 + ...to-control-if-armour-stands-can-move.patch | 32 + .../0044-IllegalPacketEvent.patch | 89 + .../api-unmapped/0045-Fireworks-API-s.patch | 28 + .../0046-PlayerTeleportEndGatewayEvent.patch | 42 + ...rovide-E-TE-Chunk-count-stat-methods.patch | 46 + ...PI-for-Reason-Source-Triggering-play.patch | 122 + ...orldBorder-isInBounds-Location-check.patch | 29 + ...n-option-to-prevent-player-names-fro.patch | 60 + ...upstream-javadoc-warnings-and-errors.patch | 46 + .../0052-Item-canEntityPickup.patch | 31 + ...PlayerPickupItemEvent-setFlyAtPlayer.patch | 54 + .../0054-PlayerAttemptPickupItemEvent.patch | 102 + .../0055-Add-UnknownCommandEvent.patch | 126 + .../0056-Basic-PlayerProfile-API.patch | 351 ++ .../0057-Shoulder-Entities-Release-API.patch | 37 + .../0058-Profile-Lookup-Events.patch | 174 + .../0059-Entity-fromMobSpawner.patch | 23 + ...60-Improve-the-Saddle-API-for-Horses.patch | 83 + .../0061-ensureServerConversions-API.patch | 62 + .../0062-Add-getI18NDisplayName-API.patch | 52 + .../0063-ProfileWhitelistVerifyEvent.patch | 157 + .../0064-Make-plugins-list-alphabetical.patch | 56 + .../0065-LivingEntity-setKiller.patch | 26 + ...efixes-in-implementation-logging-con.patch | 41 + ...low-plugins-to-use-SLF4J-for-logging.patch | 51 + ...or-plugins-modifying-the-parent-of-t.patch | 117 + .../0069-Add-PlayerJumpEvent.patch | 118 + ...nt-protocol-version-and-virtual-host.patch | 71 + .../0071-Add-PlayerArmorChangeEvent.patch | 149 + ...-get-a-BlockState-without-a-snapshot.patch | 31 + .../0073-AsyncTabCompleteEvent.patch | 266 + ...lay-warning-on-deprecated-recipe-API.patch | 35 + .../0075-PlayerPickupExperienceEvent.patch | 93 + .../0076-ExperienceOrbMergeEvent.patch | 102 + ...7-Ability-to-apply-mending-to-XP-API.patch | 50 + .../0078-PreCreatureSpawnEvent.patch | 127 + ...9-PlayerNaturallySpawnCreaturesEvent.patch | 80 + ...-Add-setPlayerProfile-API-for-Skulls.patch | 78 + .../0081-Fill-Profile-Property-Events.patch | 176 + ...PlayerAdvancementCriterionGrantEvent.patch | 75 + .../0083-Add-ArmorStand-Item-Meta.patch | 96 + .../api-unmapped/0084-Optimize-Hoppers.patch | 39 + .../0085-Tameable-getOwnerUniqueId-API.patch | 42 + ...e-PlayerProfile-in-AsyncPreLoginEven.patch | 91 + ...dd-extended-PaperServerListPingEvent.patch | 381 ++ .../0088-Player.setPlayerProfile-API.patch | 40 + .../0089-getPlayerUniqueId-API.patch | 58 + ...-support-to-PaperServerListPingEvent.patch | 30 + ...d-method-to-open-already-placed-sign.patch | 25 + ...92-Add-Ban-Methods-to-Player-Objects.patch | 253 + .../0093-EndermanEscapeEvent.patch | 102 + .../0094-Enderman.teleportRandomly.patch | 29 + ...tional-world.getNearbyEntities-API-s.patch | 292 + .../0096-Location.isChunkLoaded-API.patch | 18 + ...ld.spawnParticle-API-and-add-Builder.patch | 579 ++ .../0098-EndermanAttackPlayerEvent.patch | 116 + ...lose-Plugin-Class-Loaders-on-Disable.patch | 141 + .../0100-WitchConsumePotionEvent.patch | 122 + .../0101-WitchThrowPotionEvent.patch | 93 + ...ion.toBlockLocation-toCenterLocation.patch | 43 + .../0103-PotionEffect-clone-methods.patch | 44 + .../0104-WitchReadyPotionEvent.patch | 93 + ...0105-ItemStack-getMaxItemUseDuration.patch | 25 + ...06-Add-EntityTeleportEndGatewayEvent.patch | 43 + ...e-shield-blocking-delay-configurable.patch | 30 + ...ent-consumeArrow-and-getArrowItem-AP.patch | 44 + ...Add-getNearbyXXX-methods-to-Location.patch | 275 + .../0110-PlayerReadyArrowEvent.patch | 107 + ...111-Add-EntityKnockbackByEntityEvent.patch | 94 + .../0112-Expand-Explosions-API.patch | 200 + ...PI-additions-for-quantity-flags-lore.patch | 206 + ...ivingEntity-Hand-Raised-Item-Use-API.patch | 62 + .../api-unmapped/0115-RangedEntity-API.patch | 188 + .../0116-Add-World.getEntity-UUID-API.patch | 28 + .../0117-InventoryCloseEvent-Reason-API.patch | 93 + .../0118-Entity-getChunk-API.patch | 33 + ...dd-an-asterisk-to-legacy-API-plugins.patch | 66 + .../0120-EnderDragon-Events.patch | 225 + .../0121-PlayerLaunchProjectileEvent.patch | 95 + .../0122-PlayerElytraBoostEvent.patch | 97 + .../0123-EntityTransformedEvent.patch | 104 + ...Allow-disabling-armour-stand-ticking.patch | 32 + .../0125-SkeletonHorse-Additions.patch | 92 + ...126-Expand-Location-Manipulation-API.patch | 66 + .../0127-Expand-ArmorStand-API.patch | 103 + .../api-unmapped/0128-AnvilDamageEvent.patch | 160 + ...deadlock-risk-in-firing-async-events.patch | 137 + .../0130-Add-hand-to-bucket-events.patch | 130 + .../api-unmapped/0131-Add-TNTPrimeEvent.patch | 126 + ...vide-Chunk-Coordinates-as-a-Long-API.patch | 72 + .../api-unmapped/0133-Async-Chunks-API.patch | 534 ++ .../0134-Make-EnderDragon-extend-Mob.patch | 19 + ...ile-Entities-from-a-chunk-without-sn.patch | 57 + ...hots-for-Timings-Tile-Entity-reports.patch | 19 + ...Blocks-to-be-accessed-via-a-long-key.patch | 169 + .../0138-Slime-Pathfinder-Events.patch | 217 + .../0139-isChunkGenerated-API.patch | 57 + .../0140-Add-More-Creeper-API.patch | 91 + .../0141-Add-PhantomPreSpawnEvent.patch | 71 + ...dd-source-block-to-BlockPhysicsEvent.patch | 24 + .../0143-Inventory-removeItemAnySlot.patch | 45 + ...-ray-tracing-methods-to-LivingEntity.patch | 148 + .../0145-Improve-death-events.patch | 181 + .../0146-Mob-Pathfinding-API.patch | 259 + ...e-attack-cooldown-methods-for-Player.patch | 37 + ...CanPlaceOn-and-CanDestroy-NBT-values.patch | 319 ++ ...currency-Improvements-to-Permissions.patch | 113 + ...-Add-ItemStackRecipeChoice-Draft-API.patch | 66 + ...nt-furnace-cook-speed-multiplier-API.patch | 38 + .../0152-PreSpawnerSpawnEvent.patch | 45 + .../0153-Material-API-additions.patch | 41 + .../api-unmapped/0154-Add-Material-Tags.patch | 1044 ++++ ...155-Allow-setting-the-vex-s-summoner.patch | 40 + ...156-Add-LivingEntity-getTargetEntity.patch | 105 + .../0157-Add-sun-related-API.patch | 45 + patches/api-unmapped/0158-Here-s-Johnny.patch | 42 + patches/api-unmapped/0159-Turtle-API.patch | 283 + .../0160-Add-spectator-target-events.patch | 141 + .../0161-Add-more-Witch-API.patch | 64 + ...ault-permission-message-configurable.patch | 57 + ...tion-supression-of-EntityDismount-Ve.patch | 109 + .../0164-Add-more-Zombie-API.patch | 66 + ...eserved-channel-check-to-be-sensible.patch | 34 + .../0166-Add-PlayerConnectionCloseEvent.patch | 136 + ...-replace-OfflinePlayer-getLastPlayed.patch | 62 + .../api-unmapped/0168-BlockDestroyEvent.patch | 110 + ...-ItemStack-Recipe-API-helper-methods.patch | 70 + .../0170-Add-WhitelistToggleEvent.patch | 52 + .../0171-Annotation-Test-changes.patch | 29 + .../0172-Entity-getEntitySpawnReason.patch | 27 + .../0173-Add-GS4-Query-event.patch | 424 ++ .../0174-Add-PlayerPostRespawnEvent.patch | 64 + ...rivate-methods-for-nullability-annot.patch | 20 + ...lip-some-Spigot-API-null-annotations.patch | 127 + .../0177-Server-Tick-Events.patch | 110 + ...0178-PlayerDeathEvent-getItemsToKeep.patch | 63 + .../api-unmapped/0179-Add-Heightmap-API.patch | 196 + .../0180-Mob-Spawner-API-Enhancements.patch | 41 + .../0181-Add-BlockSoundGroup-interface.patch | 94 + ...ractAtEntityEvent-javadoc-for-ArmorS.patch | 20 + ...-custom-payload-channel-message-size.patch | 21 + ...184-Expose-the-internal-current-tick.patch | 38 + ...layerDeathEvent-shouldDropExperience.patch | 79 + ...-Add-effect-to-block-break-naturally.patch | 29 + .../0187-Add-ThrownEggHatchEvent.patch | 129 + .../api-unmapped/0188-Entity-Jump-API.patch | 88 + ...189-add-hand-to-BlockMultiPlaceEvent.patch | 29 + .../0190-Add-tick-times-API.patch | 62 + ...191-Expose-MinecraftServer-isRunning.patch | 44 + ...nts-firing-Async-errors-during-shutd.patch | 25 + ...93-Make-JavaPluginLoader-thread-safe.patch | 53 + .../0194-Add-Player-Client-Options-API.patch | 202 + ...PlayerAttackEntityCooldownResetEvent.patch | 88 + ...mStack-swapping-the-extended-and-upg.patch | 21 + .../0197-Villager-Restocks-API.patch | 31 + .../0198-Expose-game-version.patch | 50 + ...99-Add-item-slot-convenience-methods.patch | 283 + .../api-unmapped/0200-Add-Mob-Goal-API.patch | 481 ++ .../0201-World-view-distance-api.patch | 45 + .../0202-Add-villager-reputation-API.patch | 177 + .../api-unmapped/0203-Spawn-Reason-API.patch | 62 + .../api-unmapped/0204-Potential-bed-API.patch | 33 + ...rioritise-own-classes-where-possible.patch | 86 + ...Add-Raw-Byte-ItemStack-Serialization.patch | 56 + ...-a-useful-PluginClassLoader-toString.patch | 30 + ...Holder-method-without-block-snapshot.patch | 51 + .../0209-Expose-Arrow-getItemStack.patch | 25 + ...implement-PlayerRecipeBookClickEvent.patch | 96 + .../0211-Support-components-in-ItemMeta.patch | 93 + ...-TargetReasons-for-1.16-mob-behavior.patch | 25 + .../0213-Add-entity-liquid-API.patch | 46 + ...reResultEvent-PrepareGrindstoneEvent.patch | 211 + ...llow-delegation-to-vanilla-chunk-gen.patch | 85 + ...-Support-hex-colors-in-getLastColors.patch | 34 + .../0217-Add-setMaxPlayers-API.patch | 48 + .../0218-Add-moon-phase-API.patch | 65 + ...yPickupItemAnimation-to-LivingEntity.patch | 39 + .../api-unmapped/0220-Add-BellRingEvent.patch | 69 + patches/api-unmapped/0221-Brand-support.patch | 27 + .../0222-Add-more-Evoker-API.patch | 30 + ...-translation-keys-for-blocks-entitie.patch | 127 + ...ate-HoverEvent-from-ItemStack-Entity.patch | 73 + ...al-open-container-api-to-HumanEntity.patch | 103 + ...y-Counter-to-allow-plugins-to-use-va.patch | 24 + .../api-unmapped/0227-Entity-isTicking.patch | 21 + ...docs-for-Entity.getEntitySpawnReason.patch | 19 + .../0229-Villager-resetOffers.patch | 22 + .../0230-Player-elytra-boost-API.patch | 30 + ...-Add-getOfflinePlayerIfCached-String.patch | 68 + .../0232-Add-ignore-discounts-API.patch | 52 + .../0233-Item-no-age-no-player-pickup.patch | 45 + ...0234-Beacon-API-custom-effect-ranges.patch | 37 + .../0235-Add-API-for-quit-reason.patch | 79 + .../0236-Add-Destroy-Speed-API.patch | 41 + ...237-Add-LivingEntity-clearActiveItem.patch | 24 + .../0238-Add-PlayerItemCooldownEvent.patch | 89 + .../0239-More-lightning-API.patch | 49 + .../0240-Add-PlayerShearBlockEvent.patch | 120 + ...241-Enable-multi-release-plugin-jars.patch | 30 + ...0242-Player-Chunk-Load-Unload-Events.patch | 100 + ...3-Expose-LivingEntity-hurt-direction.patch | 30 + .../0244-Added-PlayerTradeEvent.patch | 166 + ...-OBSTRUCTED-reason-to-BedEnterResult.patch | 23 + .../0246-Add-TargetHitEvent-API.patch | 81 + ...0247-Additional-Block-Material-API-s.patch | 57 + ...et-Material-from-Boats-and-Minecarts.patch | 58 + ...9-Add-PlayerFlowerPotManipulateEvent.patch | 94 + .../0250-Zombie-API-breaking-doors.patch | 30 + .../0251-Add-EntityLoadCrossbowEvent.patch | 113 + .../0252-Added-WorldGameRuleChangeEvent.patch | 103 + ...3-Added-ServerResourcesReloadedEvent.patch | 60 + .../0254-Add-BlockFailedDispenseEvent.patch | 69 + ...5-Added-PlayerLecternPageChangeEvent.patch | 127 + ...6-Added-PlayerLoomPatternSelectEvent.patch | 89 + .../0257-Better-AnnotationTest-printout.patch | 69 + ...xact-interaction-point-in-PlayerInte.patch | 67 + .../0259-Add-sendOpLevel-API.patch | 28 + .../0260-Add-StructureLocateEvent.patch | 167 + ...onent-with-empty-text-instead-of-thr.patch | 20 + .../0262-Add-BlockPreDispenseEvent.patch | 72 + .../0263-Added-Vanilla-Entity-Tags.patch | 43 + .../api-unmapped/0264-added-Wither-API.patch | 45 + ...-Added-PlayerChangeBeaconEffectEvent.patch | 153 + ...Leash-variable-to-EntityUnleashEvent.patch | 78 + ...d-PlayerStonecutterRecipeSelectEvent.patch | 71 + .../api-unmapped/0268-EntityMoveEvent.patch | 152 + .../0269-add-DragonEggFormEvent.patch | 75 + ...w-adding-items-to-BlockDropItemEvent.patch | 19 + ...ainThreadExecutor-to-BukkitScheduler.patch | 26 + ...-entity-allow-attribute-registration.patch | 25 + .../0273-Add-missing-effects.patch | 76 + .../0274-Expose-Tracked-Players.patch | 33 + ...Cache-the-result-of-Material-isBlock.patch | 38 + .../0276-Add-worldborder-events.patch | 308 ++ .../0277-added-PlayerNameEntityEvent.patch | 130 + .../0278-Add-recipe-to-cook-events.patch | 69 + .../0279-Add-Block-isValidTool.patch | 26 + .../0280-Implement-Keyed-on-World.patch | 164 + ...ventory-getContents-null-annotations.patch | 22 + .../api-unmapped/0282-Item-Rarity-API.patch | 109 + .../0283-Expose-protocol-version.patch | 23 + ...-add-isDeeplySleeping-to-HumanEntity.patch | 26 + ...-add-consumeFuel-to-FurnaceBurnEvent.patch | 44 + ...t-set-drop-chance-to-EntityEquipment.patch | 43 + .../0287-Added-PlayerDeepSleepEvent.patch | 58 + .../api-unmapped/0288-More-World-API.patch | 131 + .../0289-Added-PlayerBedFailEnterEvent.patch | 131 + ...eacon-activation-deactivation-events.patch | 101 + .../0291-PlayerMoveEvent-Improvements.patch | 64 + ...d-RespawnFlags-to-PlayerRespawnEvent.patch | 73 + .../0293-Add-more-WanderingTrader-API.patch | 41 + ...ent-suggestion-tooltips-in-AsyncTabC.patch | 407 ++ ...Add-EntityBlockStorage-clearEntities.patch | 22 + ...essage-to-PlayerAdvancementDoneEvent.patch | 71 + ...-address-to-AsyncPlayerPreLoginEvent.patch | 50 + .../api-unmapped/0298-Inventory-close.patch | 26 + ...n-in-sunlight-API-for-Phantoms-and-S.patch | 55 + .../0300-Add-basic-Datapack-API.patch | 106 + ...ditions-to-PlayerGameModeChangeEvent.patch | 111 + .../0302-ItemStack-repair-check-API.patch | 59 + .../0303-More-Enchantment-API.patch | 124 + ...-option-to-load-extra-plugin-jars-no.patch | 142 + ...-missing-hard-depends-not-just-first.patch | 91 + .../0306-Add-Mob-lookAt-API.patch | 99 + .../0307-ItemStack-editMeta.patch | 42 + .../0308-Add-EntityInsideBlockEvent.patch | 92 + ...309-Attributes-API-for-item-defaults.patch | 53 + ...cause-to-Weather-ThunderChangeEvents.patch | 104 + .../0311-More-Lidded-Block-API.patch | 34 + .../0312-Add-PlayerKickEvent-causes.patch | 127 + .../0313-Add-PufferFishStateChangeEvent.patch | 92 + .../0314-Add-BellRevealRaiderEvent.patch | 70 + ...315-Add-ElderGuardianAppearanceEvent.patch | 81 + .../0316-Add-more-line-of-sight-methods.patch | 49 + .../api/0001-Convert-project-to-Gradle.patch | 76 + ...le-speed-for-water-flowing-over-lava.patch | 0 .../removed}/0033-Generator-Settings.patch | 0 ...lowing-block-if-material-has-changed.patch | 0 .../removed}/0036-Fast-draining.patch | 0 ...sition-the-first-time-an-entity-is-s.patch | 0 ...w-BlockFromToEvent-from-loading-chun.patch | 0 ...-mobs-should-only-spawn-in-the-water.patch | 0 ...-dispenser-dropper-furnace-placement.patch | 0 ...0280-Configurable-Unrestricted-Signs.patch | 0 .../0532-Unload-leaked-Cached-Chunks.patch | 0 .../0032-Add-player-view-distance-API.patch | 0 .../0061-Chunk-save-queue-improvements.patch | 0 ...70-Optimized-Light-Level-Comparisons.patch | 0 .../0071-Pass-world-to-Village-creation.patch | 0 .../1.14/0078-Optimize-Chunk-Access.patch | 0 ...am-reload-spawn-chunks-in-nether-end.patch | 0 .../0112-Entity-Tracking-Improvements.patch | 0 ...-Ensure-Chunks-never-ever-load-async.patch | 0 ...unk-Unloads-based-on-Player-Movement.patch | 0 ...vent-Auto-Save-if-Save-Queue-is-full.patch | 0 .../0143-Chunk-Save-Stats-Debug-Option.patch | 0 .../1.14/0144-Fix-block-break-desync.patch | 0 .../0161-ShulkerBox-Dupe-Prevention.patch | 0 ...lages-loading-chunks-for-door-checks.patch | 0 ...emove-entities-on-dimension-teleport.patch | 0 ...spawn-if-entity-is-in-a-chunk-schedu.patch | 0 ...Optimize-getChunkIfLoaded-type-calls.patch | 0 ...1-Async-Chunk-Loading-and-Generation.patch | 0 .../0363-Optimize-Light-Recalculations.patch | 0 .../0366-Fix-Sending-Chunks-to-Client.patch | 0 ...-Fix-FileIOThread-concurrency-issues.patch | 0 ...377-Optimize-Persistent-Data-Loading.patch | 0 ...-Use-EntityTypes-for-living-entities.patch | 0 ...at-which-we-ll-consider-an-attackabl.patch | 0 ...uce-IO-ops-opening-a-new-region-file.patch | 0 ...-Do-not-load-chunks-for-light-checks.patch | 0 ...o-use-a-versioned-world-folder-for-t.patch | 0 ...tect-and-repair-corrupt-Region-Files.patch | 0 ...76-Handle-bad-chunks-more-gracefully.patch | 0 ...sh-on-save-flag-for-reliable-regionf.patch | 0 .../0412-Improve-POI-data-saving-logic.patch | 0 ...ups-for-Entity-TileEntity-Current-Ch.patch | 0 .../0238-Configurable-Bed-Search-Radius.patch | 0 .../0298-Support-Overriding-World-Seeds.patch | 0 ...quid-s-Entity-Collision-optimisation.patch | 0 ...me-Streams-usage-in-Entity-Collision.patch | 0 .../1.16/0530-Optimize-Villagers.patch | 0 ...ets-from-world-player-list-not-serve.patch | 0 .../0302-Avoid-dimension-id-collisions.patch | 0 .../No longer Needed/0316-Fix-MC-93764.patch | 0 ...x-some-generation-concurrency-issues.patch | 0 ...ro-tick-instant-grow-farms-MC-113809.patch | 0 ...-Fix-spawn-radius-being-treated-as-0.patch | 0 .../0429-Seed-based-feature-search.patch | 0 ...-Villager-AI-optimizations-DROP-1.16.patch | 0 .../0049-Player-Tab-List-and-Title-APIs.patch | 0 .../removed}/Scheduler-decompile-fixes.patch | 0 .../server-remapped/0001-POM-Changes.patch | 291 + .../0002-Paper-config-files.patch | 820 +++ .../server-remapped/0003-MC-Dev-fixes.patch | 929 ++++ patches/server-remapped/0004-MC-Utils.patch | 4859 +++++++++++++++++ .../server-remapped/0005-Paper-Metrics.patch | 735 +++ ...-MinecraftKey-Information-to-Objects.patch | 144 + ...to-current-Chunk-for-Entity-and-Bloc.patch | 171 + ...ts-for-each-Entity-Block-Entity-Type.patch | 55 + patches/server-remapped/0009-Timings-v2.patch | 2330 ++++++++ patches/server-remapped/0010-Adventure.patch | 3238 +++++++++++ ...actus-bamboo-and-reed-growth-heights.patch | 114 + ...figurable-baby-zombie-movement-speed.patch | 51 + ...013-Configurable-fishing-time-ranges.patch | 38 + ...d-mobs-to-jump-and-take-water-damage.patch | 105 + ...-despawn-distances-for-living-entiti.patch | 55 + ...6-Allow-for-toggling-of-spawn-chunks.patch | 33 + ...ck-and-tnt-entities-at-the-specified.patch | 94 + ...ient-crashes-server-lists-and-Mojang.patch | 117 + .../0019-Implement-Paper-VersionChecker.patch | 150 + ...d-version-history-to-version-command.patch | 215 + .../0021-Player-affects-spawning-API.patch | 157 + ...ve-invalid-mob-spawner-tile-entities.patch | 31 + .../0023-Optimize-TileEntity-Ticking.patch | 279 + ...024-Further-improve-server-tick-loop.patch | 208 + ...025-Only-refresh-abilities-if-needed.patch | 25 + .../0026-Entity-Origin-API.patch | 140 + ...event-tile-entity-and-entity-crashes.patch | 65 + ...nfigurable-top-of-nether-void-damage.patch | 93 + ...e-before-converting-and-renaming-pla.patch | 19 + .../0030-Always-tick-falling-blocks.patch | 18 + .../0031-Configurable-end-credits.patch | 42 + ...-explosions-processing-dead-entities.patch | 19 + .../0033-Optimize-explosions.patch | 148 + .../0034-Disable-explosion-knockback.patch | 69 + .../0035-Disable-thunder.patch | 33 + .../0036-Disable-ice-and-snow.patch | 33 + ...7-Configurable-mob-spawner-tick-rate.patch | 65 + ...sition-the-first-time-an-entity-is-s.patch | 108 + .../0039-Add-BeaconEffectEvent.patch | 103 + ...figurable-container-update-tick-rate.patch | 46 + .../0041-Use-UserCache-for-player-heads.patch | 25 + .../0042-Disable-spigot-tick-limiters.patch | 21 + .../0043-Add-PlayerInitialSpawnEvent.patch | 48 + ...urable-Disabling-Cat-Chest-Detection.patch | 37 + ...45-Ensure-commands-are-not-ran-async.patch | 119 + ...chunks-are-slime-spawn-chunks-toggle.patch | 33 + .../0047-Expose-server-CommandMap.patch | 18 + ...e-informative-in-maxHealth-exception.patch | 22 + .../0049-Player-Tab-List-and-Title-APIs.patch | 173 + .../0050-Ensure-inv-drag-is-in-bounds.patch | 19 + ...entation-of-tile-entity-removal-list.patch | 48 + ...dd-configurable-portal-search-radius.patch | 56 + .../0053-Add-velocity-warnings.patch | 89 + ...ble-inter-world-teleportation-safety.patch | 44 + .../0055-Add-exception-reporting-event.patch | 264 + ...-don-t-need-to-when-cerealising-text.patch | 27 + ...oreboards-for-non-players-by-default.patch | 50 + ...working-with-arrows-stuck-in-living-.patch | 27 + .../0059-Complete-resource-pack-API.patch | 71 + .../0060-Chunk-Save-Reattempt.patch | 59 + ...ading-permissions.yml-before-plugins.patch | 52 + ...llow-Reloading-of-Custom-Permissions.patch | 35 + .../0063-Remove-Metadata-on-reload.patch | 31 + ...064-Handle-Item-Meta-Inconsistencies.patch | 339 ++ ...urable-Non-Player-Arrow-Despawn-Rate.patch | 44 + .../0066-Add-World-Util-Methods.patch | 65 + ...7-Custom-replacement-for-eaten-items.patch | 48 + ...th-absorb-values-and-repair-bad-data.patch | 57 + ...069-Use-a-Shared-Random-for-Entities.patch | 42 + ...le-spawn-chances-for-skeleton-horses.patch | 36 + ...Location-getType-and-getBlockData-fo.patch | 206 + ...ckPhysicsEvent-if-a-plugin-has-a-lis.patch | 95 + ...Entity-AddTo-RemoveFrom-World-Events.patch | 27 + ...74-Configurable-Chunk-Inhabited-Time.patch | 44 + .../0075-EntityPathfindEvent.patch | 125 + ...egionFileCache-and-make-configurable.patch | 39 + ...7-Do-not-load-chunks-for-Pathfinding.patch | 68 + ...0078-Add-PlayerUseUnknownEntityEvent.patch | 40 + ...dDebugInfo-not-initialized-on-client.patch | 18 + ...-Configurable-Grass-Spread-Tick-Rate.patch | 41 + ...g-BlockPlaceEvent-triggering-physics.patch | 18 + .../0082-Optimize-DataBits.patch | 84 + ...nilla-per-world-scoreboard-coloring-.patch | 66 + ...nd-for-setting-passengers-on-players.patch | 29 + ...Remove-unused-World-Tile-Entity-List.patch | 90 + .../0086-Don-t-tick-Skulls-unused-code.patch | 28 + .../0087-Configurable-Player-Collision.patch | 131 + ...ent-to-allow-plugins-to-handle-clien.patch | 57 + .../0089-Configurable-RCON-IP-address.patch | 59 + ...e-from-loading-chunks-wrongly-spread.patch | 82 + ...91-Implement-PlayerLocaleChangeEvent.patch | 48 + ...ityRegainHealthEvent-isFastRegen-API.patch | 42 + ...-to-configure-frosted_ice-properties.patch | 52 + ...-possibility-for-getServer-singleton.patch | 36 + ...item-frames-performance-and-bug-fixe.patch | 144 + ...-API-Replenishable-Lootables-Feature.patch | 739 +++ ...y-scoreboard-teams-to-scoreboard.dat.patch | 32 + ...tem-property-for-disabling-watchdoge.patch | 19 + .../0099-Optimize-UserCache-Thread-Safe.patch | 117 + ...blocking-on-Network-Manager-creation.patch | 45 + ...1-Optional-TNT-doesn-t-move-in-water.patch | 121 + ...r-redstone-torch-rapid-clock-removal.patch | 98 + .../0103-Add-server-name-parameter.patch | 25 + ...on-Wither-Death-sounds-to-same-world.patch | 47 + .../0105-Fix-Double-World-Add-issues.patch | 21 + .../0106-Fix-Old-Sign-Conversion.patch | 59 + ...e-profiles-that-have-no-UUID-and-no-.patch | 19 + ...setting-for-proxy-online-mode-status.patch | 81 + ...ptimise-BlockState-s-hashCode-equals.patch | 84 + ...onfigurable-packet-in-spam-threshold.patch | 45 + ...11-Configurable-flying-kick-messages.patch | 44 + .../0112-Chunk-registration-fixes.patch | 22 + ...ok-reference-on-Craft-Entity-removal.patch | 25 + ...uto-fix-bad-Y-levels-on-player-login.patch | 19 + ...tion-to-remove-corrupt-tile-entities.patch | 37 + .../0116-Add-EntityZapEvent.patch | 58 + ...a-from-ArmorStand-and-SpawnEgg-items.patch | 49 + ...118-Cache-user-authenticator-threads.patch | 102 + .../0119-Optimise-removeQueue.patch | 67 + ...0-Allow-Reloading-of-Command-Aliases.patch | 36 + ...1-Add-source-to-PlayerExpChangeEvent.patch | 49 + ...2-Don-t-let-fishinghooks-use-portals.patch | 22 + .../0123-Add-ProjectileCollideEvent.patch | 109 + ...vent-Pathfinding-out-of-World-Border.patch | 20 + ...imize-World.isLoaded-BlockPosition-Z.patch | 22 + ...-Bound-Treasure-Maps-to-World-Border.patch | 47 + ...figurable-Cartographer-Treasure-Maps.patch | 65 + .../0128-Optimize-ItemStack.isEmpty.patch | 20 + ...to-control-if-armour-stands-can-move.patch | 106 + ...30-Properly-fix-item-duplication-bug.patch | 35 + .../0131-String-based-Action-Bar-API.patch | 48 + .../server-remapped/0132-Firework-API-s.patch | 124 + .../0133-PlayerTeleportEndGatewayEvent.patch | 28 + ...rovide-E-TE-Chunk-count-stat-methods.patch | 61 + .../0135-Enforce-Sync-Player-Saves.patch | 27 + ...llow-entities-to-ride-themselves-572.patch | 18 + ...PI-for-Reason-Source-Triggering-play.patch | 332 ++ .../0138-Cap-Entity-Collisions.patch | 57 + ...e-CraftScheduler-Async-Task-Debugger.patch | 48 + ...more-aggressive-in-the-chunk-unload-.patch | 47 + .../0141-Do-not-let-armorstands-drown.patch | 42 + ...le-async-calls-to-restart-the-server.patch | 307 ++ ...property-to-disable-book-size-limits.patch | 51 + ...ke-parrots-stay-on-shoulders-despite.patch | 58 + ...n-option-to-prevent-player-names-fro.patch | 36 + ...oleAppender-for-console-improvements.patch | 558 ++ ...urable-option-to-disable-creeper-lin.patch | 35 + .../0148-Item-canEntityPickup.patch | 55 + ...PlayerPickupItemEvent-setFlyAtPlayer.patch | 46 + .../0150-PlayerAttemptPickupItemEvent.patch | 41 + .../0151-Add-UnknownCommandEvent.patch | 25 + .../0152-Basic-PlayerProfile-API.patch | 577 ++ .../0153-Shoulder-Entities-Release-API.patch | 96 + .../0154-Profile-Lookup-Events.patch | 81 + ...player-logins-during-server-shutdown.patch | 23 + .../0156-Entity-fromMobSpawner.patch | 65 + ...57-Improve-the-Saddle-API-for-Horses.patch | 59 + ...mplement-ensureServerConversions-API.patch | 24 + .../0159-Implement-getI18NDisplayName.patch | 58 + .../0160-ProfileWhitelistVerifyEvent.patch | 50 + .../0161-Fix-this-stupid-bullshit.patch | 30 + ...awns-should-honor-nametags-and-leash.patch | 19 + ...imer-when-spawner-event-is-cancelled.patch | 27 + ...64-Fix-MC-117075-TE-Unload-Lag-Spike.patch | 23 + ...-a-custom-authentication-servers-dow.patch | 43 + .../0166-LivingEntity-setKiller.patch | 48 + ...n-prefixes-using-Log4J-configuration.patch | 71 + ...e-Log4J-Configuration-Plugin-Loggers.patch | 47 + .../0169-Add-PlayerJumpEvent.patch | 46 + ...0-handle-PacketPlayInKeepAlive-async.patch | 40 + ...nt-protocol-version-and-virtual-host.patch | 128 + ...rt-serverside-behavior-of-keepalives.patch | 75 + ...dEffects-only-to-players-who-can-see.patch | 80 + ...-maximum-exp-value-when-merging-orbs.patch | 61 + .../0175-Add-PlayerArmorChangeEvent.patch | 43 + ...rom-being-processed-when-the-player-.patch | 24 + ...e-implementations-for-captured-block.patch | 60 + ...-get-a-BlockState-without-a-snapshot.patch | 147 + .../0179-AsyncTabCompleteEvent.patch | 130 + ...180-Avoid-NPE-in-PathfinderGoalTempt.patch | 19 + .../0181-PlayerPickupExperienceEvent.patch | 28 + .../0182-ExperienceOrbMergeEvent.patch | 22 + ...3-Ability-to-apply-mending-to-XP-API.patch | 101 + ...-max-squid-spawn-height-configurable.patch | 36 + .../0185-PreCreatureSpawnEvent.patch | 215 + ...6-PlayerNaturallySpawnCreaturesEvent.patch | 79 + ...-Add-setPlayerProfile-API-for-Skulls.patch | 109 + .../0188-Fill-Profile-Property-Events.patch | 42 + ...PlayerAdvancementCriterionGrantEvent.patch | 23 + .../0190-Add-ArmorStand-Item-Meta.patch | 296 + ...-Extend-Player-Interact-cancellation.patch | 60 + .../0192-Tameable-getOwnerUniqueId-API.patch | 36 + ...r-crits-helps-mitigate-hacked-client.patch | 34 + ...sted-Ice-from-loading-holding-chunks.patch | 31 + ...le-Explicit-Network-Manager-Flushing.patch | 34 + ...nt-extended-PaperServerListPingEvent.patch | 378 ++ .../0197-Improved-Async-Task-Scheduler.patch | 370 ++ ...e-PlayerProfile-in-AsyncPreLoginEven.patch | 45 + .../0199-Player.setPlayerProfile-API.patch | 142 + .../0200-Fix-Dragon-Server-Crashes.patch | 21 + .../0201-getPlayerUniqueId-API.patch | 40 + ...Make-player-data-saving-configurable.patch | 27 + ...ke-legacy-ping-handler-more-reliable.patch | 181 + ...ServerListPingEvent-for-legacy-pings.patch | 154 + ...05-Flag-to-disable-the-channel-limit.patch | 31 + ...d-method-to-open-already-placed-sign.patch | 36 + ...urable-sprint-interruption-on-attack.patch | 38 + ...-allowed-colored-signs-to-be-created.patch | 31 + .../0209-EndermanEscapeEvent.patch | 82 + .../0210-Enderman.teleportRandomly.patch | 31 + ...0211-Block-Enderpearl-Travel-Exploit.patch | 40 + ...ld.spawnParticle-API-and-add-Builder.patch | 67 + .../0213-EndermanAttackPlayerEvent.patch | 46 + .../0214-WitchConsumePotionEvent.patch | 24 + .../0215-WitchThrowPotionEvent.patch | 30 + ...Item-entities-with-World.spawnEntity.patch | 24 + .../0217-WitchReadyPotionEvent.patch | 23 + ...0218-ItemStack-getMaxItemUseDuration.patch | 37 + ...lement-EntityTeleportEndGatewayEvent.patch | 32 + ...ed-flag-on-cancel-of-Explosion-Event.patch | 28 + .../0221-Fix-CraftEntity-hashCode.patch | 46 + ...le-Alternative-LootPool-Luck-Formula.patch | 118 + ...ils-when-failing-to-save-player-data.patch | 19 + ...e-shield-blocking-delay-configurable.patch | 69 + .../0225-Improve-EntityShootBowEvent.patch | 44 + .../0226-PlayerReadyArrowEvent.patch | 39 + ...plement-EntityKnockbackByEntityEvent.patch | 93 + .../0228-Expand-Explosions-API.patch | 23 + ...ivingEntity-Hand-Raised-Item-Use-API.patch | 68 + .../0230-RangedEntity-API.patch | 171 + ...to-disable-ender-dragon-legacy-check.patch | 33 + ...2-Implement-World.getEntity-UUID-API.patch | 26 + .../0233-InventoryCloseEvent-Reason-API.patch | 228 + .../0234-Vex-getSummoner-API.patch | 37 + ...nventory-when-cancelling-PlayerInter.patch | 29 + ...ge-the-Entity-Random-seed-for-squids.patch | 19 + ...nilla-entity-warnings-for-duplicates.patch | 22 + ...e-if-stack-size-above-max-stack-size.patch | 21 + ...239-Use-asynchronous-Log4j-2-loggers.patch | 55 + ...-more-information-to-Entity.toString.patch | 20 + ...ies-option-to-debug-dupe-uuid-issues.patch | 131 + .../0242-EnderDragon-Events.patch | 62 + .../0243-PlayerElytraBoostEvent.patch | 31 + .../0244-Improve-BlockPosition-inlining.patch | 75 + .../0245-Optimize-RegistryID.c.patch | 67 + ...t-armor-stands-from-doing-entity-loo.patch | 58 + ...7-Vanished-players-don-t-have-rights.patch | 194 + ...-anytime-entities-change-to-guarante.patch | 27 + ...dd-some-Debug-to-Chunk-Entity-slices.patch | 99 + .../0250-SkeletonHorse-Additions.patch | 152 + ...revent-Saving-Bad-entities-to-chunks.patch | 127 + ...on-t-call-getItemMeta-on-hasItemMeta.patch | 64 + ...ead-Entities-in-entityList-iteration.patch | 120 + ...54-Implement-Expanded-ArmorStand-API.patch | 104 + .../0255-AnvilDamageEvent.patch | 28 + .../0256-Add-TNTPrimeEvent.patch | 148 + ...nd-make-tab-spam-limits-configurable.patch | 75 + .../0258-Add-hand-to-bucket-events.patch | 341 ++ ...6-Experience-should-save-as-Integers.patch | 28 + ...ient-rendering-skulls-from-same-user.patch | 147 + ...dd-Early-Warning-Feature-to-WatchDog.patch | 184 + .../0262-Make-EnderDragon-implement-Mob.patch | 33 + ...63-Use-ConcurrentHashMap-in-JsonList.patch | 147 + ...64-Use-a-Queue-for-Queueing-Commands.patch | 39 + ...ile-Entities-from-a-chunk-without-sn.patch | 73 + ...Allow-disabling-armour-stand-ticking.patch | 159 + ...ptimize-BlockPosition-helper-methods.patch | 100 + ...efault-mob-spawn-range-and-water-ani.patch | 33 + .../0269-Slime-Pathfinder-Events.patch | 229 + ...le-speed-for-water-flowing-over-lava.patch | 72 + ...271-Optimize-CraftBlockData-Creation.patch | 49 + .../0272-Optimize-RegistryMaterials.patch | 96 + .../0273-Add-PhantomPreSpawnEvent.patch | 96 + .../0274-Add-More-Creeper-API.patch | 49 + .../0275-Inventory-removeItemAnySlot.patch | 58 + ...loadChunk-int-int-false-load-unconve.patch | 20 + ...-ray-tracing-methods-to-LivingEntity.patch | 99 + ...e-attack-cooldown-methods-for-Player.patch | 41 + .../0279-Improve-death-events.patch | 458 ++ ...ow-chests-to-be-placed-with-NBT-data.patch | 31 + .../0281-Mob-Pathfinding-API.patch | 290 + ...ent-chunk-loading-from-Fluid-Flowing.patch | 75 + ...-for-CanPlaceOn-and-CanDestroy-NBT-v.patch | 446 ++ ...ent-Mob-AI-Rules-from-Loading-Chunks.patch | 83 + ...wning-from-loading-generating-chunks.patch | 32 + ...e-Biome-Mob-Lookups-for-Mob-Spawning.patch | 97 + ...nt-furnace-cook-speed-multiplier-API.patch | 102 + .../0288-PreSpawnerSpawnEvent.patch | 29 + ...arseException-in-Entity-and-TE-names.patch | 110 + .../0290-Honor-EntityAgeable.ageLock.patch | 18 + ...ble-connection-throttle-kick-message.patch | 35 + .../0292-Hook-into-CB-plugin-rewrites.patch | 184 + ...293-Allow-setting-the-vex-s-summoner.patch | 33 + .../0294-Add-sun-related-API.patch | 52 + patches/server-remapped/0295-Turtle-API.patch | 150 + ...ther-worlds-for-shooter-of-projectil.patch | 36 + ...tator-target-events-and-improve-impl.patch | 99 + ...8-Add-Velocity-IP-Forwarding-Support.patch | 303 + .../0299-Add-more-Witch-API.patch | 150 + ...owned-for-Villager-Aggression-Config.patch | 19 + .../server-remapped/0301-Here-s-Johnny.patch | 38 + ...event-players-from-moving-into-unloa.patch | 64 + ...03-Reset-players-airTicks-on-respawn.patch | 30 + ...-after-profile-lookups-if-not-needed.patch | 33 + ...er-Thread-Pool-and-Thread-Priorities.patch | 121 + .../0306-Optimize-World-Time-Updates.patch | 42 + ...store-custom-InventoryHolder-support.patch | 46 + .../0308-Use-Vanilla-Minecart-Speeds.patch | 24 + .../0309-Fix-SpongeAbsortEvent-handling.patch | 37 + ...t-allow-digging-into-unloaded-chunks.patch | 68 + .../0311-Book-Size-Limits.patch | 80 + ...ault-permission-message-configurable.patch | 46 + ...Prevent-rayTrace-from-loading-chunks.patch | 29 + ...e-Large-Packets-disconnecting-client.patch | 130 + ...entity-dismount-during-teleportation.patch | 134 + .../0316-Add-more-Zombie-API.patch | 117 + .../0317-Add-PlayerConnectionCloseEvent.patch | 82 + ...Prevent-Enderman-from-loading-chunks.patch | 30 + ...-replace-OfflinePlayer-getLastPlayed.patch | 164 + ...vehicle-tracking-issue-on-disconnect.patch | 24 + ...onRetractEvent-for-all-empty-pistons.patch | 47 + ...-remove-from-being-called-on-Players.patch | 33 + .../0323-BlockDestroyEvent.patch | 46 + ...om-Shapeless-Custom-Crafting-Recipes.patch | 68 + .../0325-Fix-sign-edit-memory-leak.patch | 44 + .../0326-Limit-Client-Sign-length-more.patch | 54 + ...ConvertSigns-boolean-every-sign-save.patch | 29 + ...-Manager-and-add-advanced-packet-sup.patch | 394 ++ ...le-Oversized-Tile-Entities-in-chunks.patch | 54 + ...0-Fix-Whitelist-On-Off-inconsistency.patch | 45 + ...st-tick-at-start-of-drowning-process.patch | 19 + ...332-Allow-Saving-of-Oversized-Chunks.patch | 271 + ...oggleEvent-when-whitelist-is-toggled.patch | 18 + ...334-Add-LivingEntity-getTargetEntity.patch | 187 + ...ength-when-serialising-BungeeCord-te.patch | 32 + .../0336-Entity-getEntitySpawnReason.patch | 121 + ...ity-Metadata-for-all-tracked-players.patch | 43 + ...338-Implement-PlayerPostRespawnEvent.patch | 48 + ...-for-pickupDelay-breaks-picking-up-i.patch | 27 + .../0340-Server-Tick-Events.patch | 32 + ...0341-PlayerDeathEvent-getItemsToKeep.patch | 74 + ...-Optimize-Captured-TileEntity-Lookup.patch | 32 + .../0343-Add-Heightmap-API.patch | 55 + .../0344-Mob-Spawner-API-Enhancements.patch | 139 + ...layer-View-Distance-API-placeholders.patch | 70 + ...l-to-changed-postToMainThread-method.patch | 19 + ...n-item-frames-are-modified-MC-123450.patch | 20 + ...isPrimaryThread-and-MinecraftServer-.patch | 43 + ...h-entity-loss-due-to-unloaded-chunks.patch | 53 + .../0350-Duplicate-UUID-Resolve-Option.patch | 249 + ...351-improve-CraftWorld-isChunkLoaded.patch | 30 + ...le-Keep-Spawn-Loaded-range-per-world.patch | 260 + ...tityAreaEffectCloud-from-going-negat.patch | 24 + .../0354-ChunkMapDistance-CME.patch | 93 + .../0355-Implement-CraftBlockSoundGroup.patch | 83 + .../0356-Chunk-debug-command.patch | 490 ++ ...eptions-from-dispenser-entity-spawns.patch | 33 + ...358-Fix-World-isChunkGenerated-calls.patch | 390 ++ ...ate-location-if-we-failed-to-read-it.patch | 34 + ...PaletteBlock-instead-of-ReentrantLoc.patch | 117 + .../0361-incremental-chunk-saving.patch | 317 ++ patches/server-remapped/0362-Anti-Xray.patch | 1624 ++++++ ...al-Spawned-mobs-towards-natural-spaw.patch | 57 + ...gurable-projectile-relative-velocity.patch | 53 + ...-being-ticked-when-notifying-navigat.patch | 26 + .../0366-offset-item-frame-ticking.patch | 19 + ...opper-searches-if-there-are-no-items.patch | 127 + ...68-Asynchronous-chunk-IO-and-loading.patch | 4410 +++++++++++++++ ...etChunkIfLoadedImmediately-in-places.patch | 119 + .../0370-Reduce-sync-loads.patch | 350 ++ ...lement-alternative-item-despawn-rate.patch | 127 + ...if-we-have-a-custom-Bukkit-generator.patch | 42 + .../server-remapped/0373-Fix-MC-158900.patch | 25 + ...ement-optional-per-player-mob-spawns.patch | 924 ++++ ...revent-consuming-the-wrong-itemstack.patch | 52 + .../0376-Generator-Settings.patch | 89 + .../server-remapped/0377-Fix-MC-161754.patch | 23 + ...ce-improvement-for-Chunk.getEntities.patch | 35 + ...hanging-entities-that-are-not-ItemFr.patch | 25 + ...380-Expose-the-internal-current-tick.patch | 21 + ...-sneak-when-changing-worlds-MC-10657.patch | 32 + ...d-option-to-disable-pillager-patrols.patch | 32 + ...or-when-player-hand-set-to-empty-typ.patch | 35 + .../0384-PlayerLaunchProjectileEvent.patch | 351 ++ ...ftMagicNumbers.isSupportedApiVersion.patch | 22 + ...nk-loads-when-villagers-try-to-find-.patch | 20 + ...5656-Fix-Follow-Range-Initial-Target.patch | 73 + .../0388-Optimize-Hoppers.patch | 605 ++ ...layerDeathEvent-shouldDropExperience.patch | 19 + ...oading-chunks-checking-hive-position.patch | 18 + ...Chunks-from-Hoppers-and-other-things.patch | 32 + ...rializing-mismatching-chunk-coordina.patch | 62 + ...timise-IEntityAccess-getPlayerByUUID.patch | 44 + ...0394-Fix-items-not-falling-correctly.patch | 29 + .../0395-Lag-compensate-eating.patch | 83 + ...mize-call-to-getFluid-for-explosions.patch | 19 + ...k-in-stack-not-having-effects-when-d.patch | 23 + ...-Add-effect-to-block-break-naturally.patch | 32 + .../0399-Tracking-Range-Improvements.patch | 75 + .../0400-Entity-Activation-Range-2.0.patch | 908 +++ ...x-items-vanishing-through-end-portal.patch | 28 + ...get-gravity-in-void.-Fixes-MC-167279.patch | 55 + ...e-getChunkAt-calls-for-loaded-chunks.patch | 66 + ...ow-overriding-the-java-version-check.patch | 20 + .../0405-Add-ThrownEggHatchEvent.patch | 29 + .../0406-Optimise-random-block-ticking.patch | 407 ++ .../0407-Entity-Jump-API.patch | 59 + ...n-to-nerf-pigmen-from-nether-portals.patch | 71 + .../0409-Make-the-GUI-graph-fancier.patch | 439 ++ ...410-add-hand-to-BlockMultiPlaceEvent.patch | 30 + ...11-Prevent-teleporting-dead-entities.patch | 21 + ...ripwire-hook-placement-before-update.patch | 18 + ...to-allow-iron-golems-to-spawn-in-air.patch | 35 + ...-chance-of-villager-zombie-infection.patch | 44 + .../0415-Optimise-Chunk-getFluid.patch | 67 + ...imise-TickListServer-by-rewriting-it.patch | 1301 +++++ ...spawn-settings-and-per-player-option.patch | 155 + ...re-Entity-is-never-double-registered.patch | 79 + ...ering-entities-from-unloading-chunks.patch | 32 + ...nnections-shouldn-t-hold-up-shutdown.patch | 25 + ...low-bees-to-load-chunks-for-beehives.patch | 42 + ...-PlayerChunkMap-adds-crashing-server.patch | 48 + ...ptimize-Collision-to-not-load-chunks.patch | 185 + .../0424-Don-t-tick-dead-players.patch | 21 + ...d-Player-s-shouldn-t-be-able-to-move.patch | 21 + ...hunkMap-memory-use-for-visibleChunks.patch | 294 + .../0427-Increase-Light-Queue-Size.patch | 42 + ...asks-Speed-up-processing-of-chunk-lo.patch | 271 + ...move-existing-players-to-world-spawn.patch | 54 + ...-Add-tick-times-API-and-mspt-command.patch | 169 + ...431-Expose-MinecraftServer-isRunning.patch | 22 + ...Add-Raw-Byte-ItemStack-Serialization.patch | 102 + ...33-Remove-streams-from-Mob-AI-System.patch | 253 + ...ions-until-after-entity-ticking-is-d.patch | 45 + .../0435-Async-command-map-building.patch | 72 + .../0436-Improved-Watchdog-Support.patch | 608 +++ .../0437-Optimize-Pathfinding.patch | 61 + ...38-Reduce-Either-Optional-allocation.patch | 48 + ...0439-Remove-streams-from-PairedQueue.patch | 79 + ...e-memory-footprint-of-NBTTagCompound.patch | 59 + ...vent-opening-inventories-when-frozen.patch | 59 + ...442-Optimise-ArraySetSorted-removeIf.patch | 65 + ...-entity-collision-code-if-not-needed.patch | 30 + ...oviderServer-s-chunk-level-checking-.patch | 59 + ...-teleport-command-to-valid-locations.patch | 24 + ...-Implement-Player-Client-Options-API.patch | 188 + ...-Chunk-Post-Processing-deadlock-risk.patch | 60 + ...layer-is-attempted-to-be-removed-fro.patch | 23 + ...49-Broadcast-join-message-to-console.patch | 21 + ...g-Broken-behavior-of-PlayerJoinEvent.patch | 149 + ...Load-Chunks-for-Login-Asynchronously.patch | 416 ++ ...pawn-point-if-spawn-in-unloaded-worl.patch | 27 + ...PlayerAttackEntityCooldownResetEvent.patch | 28 + ...allbacks-to-schedule-for-Callback-Ex.patch | 58 + ...t-fire-BlockFade-on-worldgen-threads.patch | 28 + ...ntom-creative-and-insomniac-controls.patch | 74 + ...m-duplication-issues-and-teleport-is.patch | 117 + .../0458-Implement-Brigadier-Mojang-API.patch | 139 + .../0459-Villager-Restocks-API.patch | 42 + ...PickItem-Packet-and-kick-for-invalid.patch | 26 + .../0461-Expose-game-version.patch | 24 + .../0462-Optimize-Voxel-Shape-Merging.patch | 175 + ...-per-thread-native-byte-buffer-cache.patch | 30 + .../0464-Implement-Mob-Goal-API.patch | 1104 ++++ ...tance-map-to-optimise-entity-tracker.patch | 413 ++ ...-isOutsideRange-to-use-distance-maps.patch | 384 ++ ...te-operations-for-updating-light-dat.patch | 320 ++ ...No-Tick-view-distance-implementation.patch | 819 +++ .../0469-Add-villager-reputation-API.patch | 155 + .../0470-Fix-Light-Command.patch | 182 + ...1-Fix-PotionEffect-ignores-icon-flag.patch | 19 + ...-brigadier-child-sorting-performance.patch | 29 + .../0473-Potential-bed-API.patch | 44 + ...Wait-for-Async-Tasks-during-shutdown.patch | 63 + ...der-respects-game-and-entity-rules-f.patch | 28 + ...and-End-Portal-Frames-from-being-des.patch | 173 + ...ze-NibbleArray-to-use-pooled-buffers.patch | 394 ++ ...bleInt-allocations-from-light-engine.patch | 50 + ...llocation-of-Vec3D-by-entity-tracker.patch | 69 + .../0480-Ensure-safe-gateway-teleport.patch | 27 + ...n-for-console-having-all-permissions.patch | 74 + ...on-Full-Status-Chunk-NBT-Memory-Leak.patch | 99 + ...ound-for-Client-Lag-Spikes-MC-162253.patch | 137 + ...k-Priority-Urgency-System-for-Chunks.patch | 1352 +++++ ...-packets-to-nearby-locations-sounds-.patch | 63 + ...mprove-Chunk-Status-Transition-Speed.patch | 99 + ...ix-villager-trading-demand-MC-163962.patch | 20 + .../0488-Maps-shouldn-t-load-chunks.patch | 32 + ...ookup-for-Treasure-Maps-Fixes-lag-fr.patch | 35 + ...-Optimize-Bit-Operations-by-inlining.patch | 220 + .../0491-Optimize-Light-Engine.patch | 1464 +++++ ...unk-Unloads-based-on-Player-Movement.patch | 107 + ...-Plugin-Tickets-to-API-Chunk-Methods.patch | 129 + ...ssing-chunks-due-to-integer-overflow.patch | 29 + ...er-runTaskTimerAsynchronously-Plugin.patch | 21 + ...ston-physics-inconsistency-MC-188840.patch | 93 + .../0497-Fix-sand-duping.patch | 37 + ...-desync-in-playerconnection-causing-.patch | 31 + .../0499-Fix-enderdragon-exp-dupe.patch | 28 + ...Holder-method-without-block-snapshot.patch | 50 + .../0501-Expose-Arrow-getItemStack.patch | 36 + ...implement-PlayerRecipeBookClickEvent.patch | 29 + ...3-Hide-sync-chunk-writes-behind-flag.patch | 23 + ...mit-lightning-strike-effect-distance.patch | 76 + ...05-Add-permission-for-command-blocks.patch | 79 + ...sure-Entity-AABB-s-are-never-invalid.patch | 48 + ...WorldBorder-collision-checks-and-air.patch | 71 + ...ld-Difficulty-Remembering-Difficulty.patch | 86 + .../0509-Paper-dumpitem-command.patch | 80 + ...510-Don-t-allow-null-UUID-s-for-chat.patch | 27 + ...-Legacy-Component-serialization-size.patch | 56 + ...0512-Support-old-UUID-format-for-NBT.patch | 64 + ...up-duplicated-GameProfile-Properties.patch | 68 + ...nvert-legacy-attributes-in-Item-Meta.patch | 44 + ...-Remove-some-streams-from-structures.patch | 143 + ...from-classes-related-villager-gossip.patch | 100 + .../0517-Support-components-in-ItemMeta.patch | 83 + ...argetLivingEntityEvent-for-1.16-mobs.patch | 62 + .../0519-Add-entity-liquid-API.patch | 75 + ...pdate-itemstack-legacy-name-and-lore.patch | 79 + ...awn-player-in-correct-world-on-login.patch | 30 + .../0522-Add-PrepareResultEvent.patch | 164 + ...llow-delegation-to-vanilla-chunk-gen.patch | 104 + ...k-for-portal-on-world-gen-entity-add.patch | 19 + ...ze-NetworkManager-Exception-Handling.patch | 117 + ...ix-Concurrency-issue-in-WeightedList.patch | 153 + ...ancement-data-player-iteration-to-be.patch | 54 + ...ix-arrows-never-despawning-MC-125757.patch | 30 + ...-Vanilla-Command-permission-checking.patch | 53 + ...ove-range-check-for-block-placing-up.patch | 35 + .../0531-Fix-SPIGOT-5989.patch | 69 + ...4-Bukkit-world-container-is-not-used.patch | 33 + ...-5885-Unable-to-disable-advancements.patch | 18 + ...ataPlayer-leak-due-from-quitting-ear.patch | 94 + ...keLighting-call-to-World-spigot-stri.patch | 19 + ...Fix-some-rails-connecting-improperly.patch | 95 + ...der-Remove-Streams-Optimized-collect.patch | 159 + .../0538-Incremental-player-saving.patch | 95 + .../0539-Import-fastutil-classes.patch | 27 + ...ull-chunk-sections-for-block-updates.patch | 18 + ...ove-armour-stand-double-add-to-world.patch | 28 + ...-Fix-MC-187716-Use-configured-height.patch | 45 + ...istake-in-CB-NBT-int-deserialization.patch | 27 + ...erver-load-chunks-from-newer-version.patch | 39 + .../server-remapped/0545-Brand-support.patch | 92 + ...her-Boss-Bar-doesn-t-update-until-in.patch | 22 + .../server-remapped/0547-Fix-MC-197271.patch | 51 + .../0548-MC-197883-Bandaid-decode-issue.patch | 28 + .../0549-Add-setMaxPlayers-API.patch | 37 + ...yPickupItemAnimation-to-LivingEntity.patch | 21 + .../0551-Don-t-require-FACING-data.patch | 35 + ...geEvent-not-firing-for-all-use-cases.patch | 46 + .../0553-Add-moon-phase-API.patch | 22 + ...-headless-pistons-from-being-created.patch | 74 + .../0555-Add-BellRingEvent.patch | 58 + ...Add-zombie-targets-turtle-egg-config.patch | 33 + .../0557-Buffer-joins-to-world.patch | 71 + .../0558-Optimize-redstone-algorithm.patch | 1157 ++++ ...rs-not-working-in-some-kick-messages.patch | 64 + ...CreateEvent-needs-to-know-its-entity.patch | 147 + .../0561-Fix-CraftTeam-null-check.patch | 19 + .../0562-Add-more-Evoker-API.patch | 57 + ...-translation-keys-for-blocks-entitie.patch | 126 + ...ate-HoverEvent-from-ItemStack-Entity.patch | 51 + .../0565-Cache-block-data-strings.patch | 70 + ...ortation-and-cancel-velocity-if-tele.patch | 83 + ...al-open-container-api-to-HumanEntity.patch | 81 + ...taFixerUpper-Rewrite-Rules-on-demand.patch | 54 + ...p-capture-to-capture-all-items-added.patch | 60 + ...rty-in-invalid-locations-SPIGOT-6086.patch | 18 + ...y-Counter-to-allow-plugins-to-use-va.patch | 37 + ...-track-plugin-scoreboards-by-default.patch | 102 + .../0573-Entity-isTicking.patch | 42 + ...-non-whitelisted-player-when-white-l.patch | 19 + ...Fix-Not-a-string-Map-Conversion-spam.patch | 52 + ...ng-a-passenger-in-CreatureSpawnEvent.patch | 19 + ...tems-that-are-extra-from-a-crafting-.patch | 24 + ...Reset-Ender-Crystals-on-Dragon-Spawn.patch | 24 + ...r-large-move-vectors-crashing-server.patch | 66 + .../0580-Optimise-getType-calls.patch | 96 + .../0581-Villager-resetOffers.patch | 48 + ...inig-for-some-hot-IBlockData-methods.patch | 101 + ...ace-order-when-capturing-blockstates.patch | 24 + ...blockpos-allocation-from-pathfinding.patch | 28 + ...tem-locations-dropped-from-campfires.patch | 32 + .../0586-Player-elytra-boost-API.patch | 39 + ...587-Fixed-TileEntityBell-memory-leak.patch | 56 + ...ling-up-when-item-stack-is-empty-in-.patch | 46 + ...-Add-getOfflinePlayerIfCached-String.patch | 39 + .../0590-Add-ignore-discounts-API.patch | 143 + ...-Toggle-for-removing-existing-dragon.patch | 36 + ...ix-client-lag-on-advancement-loading.patch | 55 + .../0593-Item-no-age-no-player-pickup.patch | 50 + ...0594-Beacon-API-custom-effect-ranges.patch | 90 + .../0595-Add-API-for-quit-reason.patch | 63 + .../0596-Seed-based-feature-search.patch | 115 + ...ing-Trader-spawn-rate-config-options.patch | 120 + ...prove-performance-of-the-end-generat.patch | 77 + .../0599-Expose-world-spawn-angle.patch | 44 + .../0600-Add-Destroy-Speed-API.patch | 35 + ...r-spawnParticle-x-y-z-precision-loss.patch | 19 + ...602-Add-LivingEntity-clearActiveItem.patch | 24 + .../0603-Add-PlayerItemCooldownEvent.patch | 39 + .../0604-More-lightning-API.patch | 68 + ...-should-not-bypass-cramming-gamerule.patch | 179 + ...d-missing-default-perms-for-commands.patch | 70 + .../0607-Add-PlayerShearBlockEvent.patch | 116 + ...g-for-servers-not-running-on-Java-16.patch | 80 + ...erbose-world-setting-to-false-by-def.patch | 19 + ...ing-zombie-villager-discount-exploit.patch | 55 + .../0611-Limit-recipe-packets.patch | 74 + ...x-CraftSound-backwards-compatibility.patch | 21 + .../0613-MC-4-Fix-item-position-desync.patch | 84 + ...0614-Player-Chunk-Load-Unload-Events.patch | 41 + ...15-Optimize-Dynamic-get-Missing-Keys.patch | 34 + ...6-Expose-LivingEntity-hurt-direction.patch | 39 + ...-OBSTRUCTED-reason-to-BedEnterResult.patch | 21 + ...m-invalid-ingredient-lists-in-Villag.patch | 24 + .../0619-added-PlayerTradeEvent.patch | 75 + .../0620-Implement-TargetHitEvent.patch | 58 + ...0621-Additional-Block-Material-API-s.patch | 40 + .../0622-Fix-harming-potion-dupe.patch | 59 + ...-get-Material-from-Boats-and-Minecar.patch | 100 + .../0624-Optimized-tick-ready-check.patch | 51 + .../0625-Cache-burn-durations.patch | 63 + ...mob-spawner-spawn-egg-transformation.patch | 33 + ...ement-PlayerFlowerPotManipulateEvent.patch | 46 + ...-event-not-being-called-in-adventure.patch | 29 + .../0629-Zombie-API-breaking-doors.patch | 44 + ...0630-Fix-nerfed-slime-when-splitting.patch | 18 + .../0631-Add-EntityLoadCrossbowEvent.patch | 60 + .../0632-Guardian-beam-workaround.patch | 30 + .../0633-Added-WorldGameRuleChangeEvent.patch | 110 + ...4-Added-ServerResourcesReloadedEvent.patch | 90 + ...ld-settings-for-mobs-picking-up-loot.patch | 51 + ...Implemented-BlockFailedDispenseEvent.patch | 63 + ...7-Added-PlayerLecternPageChangeEvent.patch | 66 + .../0638-Fire-event-on-GS4-query.patch | 265 + ...9-Added-PlayerLoomPatternSelectEvent.patch | 63 + ...onfigurable-door-breaking-difficulty.patch | 100 + ...pty-commands-shall-not-be-dispatched.patch | 18 + ...PI-to-expose-exact-interaction-point.patch | 59 + .../0643-Remove-stale-POIs.patch | 50 + .../0644-Fix-villager-boat-exploit.patch | 34 + ...645-Entity-load-save-limit-per-chunk.patch | 90 + .../0646-Add-sendOpLevel-API.patch | 65 + .../0647-Add-StructureLocateEvent.patch | 41 + ...n-for-requiring-a-player-participant.patch | 81 + ...ileHitEvent-call-when-fireballs-dead.patch | 21 + ...onent-with-empty-text-instead-of-thr.patch | 33 + ...0651-Make-schedule-command-per-world.patch | 37 + ...0652-Configurable-max-leash-distance.patch | 45 + ...0653-Implement-BlockPreDispenseEvent.patch | 42 + .../0654-Added-Vanilla-Entity-Tags.patch | 93 + .../0655-added-Wither-API.patch | 75 + ...ing-of-PlayerChangeBeaconEffectEvent.patch | 39 + ...e-spam-when-removing-chests-in-water.patch | 19 + ...le-for-always-placing-the-dragon-egg.patch | 33 + ...d-PlayerStonecutterRecipeSelectEvent.patch | 109 + ...Leash-variable-to-EntityUnleashEvent.patch | 156 + ...ce-map-update-when-spawning-disabled.patch | 19 + ...-shield-blocking-on-dimension-change.patch | 22 + .../0663-add-DragonEggFormEvent.patch | 117 + .../0664-EntityMoveEvent.patch | 71 + ...disable-pathfinding-updates-on-block.patch | 40 + .../0666-Inline-shift-direction-fields.patch | 55 + ...w-adding-items-to-BlockDropItemEvent.patch | 44 + ...ainThreadExecutor-to-BukkitScheduler.patch | 26 + ...-entity-allow-attribute-registration.patch | 69 + ...fix-dead-slime-setSize-invincibility.patch | 19 + ...ipes-should-return-an-immutable-list.patch | 19 + .../0672-misc-debugging-dumps.patch | 87 + ...pport-for-hex-color-codes-in-console.patch | 221 + .../0674-Clear-SyncLoadInfo.patch | 40 + .../0675-Expose-Tracked-Players.patch | 53 + ...76-Remove-streams-from-SensorNearest.patch | 120 + ...unnecessary-copies-of-passenger-list.patch | 239 + ...Fix-Wither-hostility-towards-players.patch | 33 + ...per-exception-on-empty-JsonList-file.patch | 18 + .../0680-Improve-ServerGUI.patch | 400 ++ ...sure-plate-EntityInteractEvent-for-i.patch | 19 + ...0682-fix-converting-txt-to-json-file.patch | 74 + .../0683-Add-worldborder-events.patch | 122 + .../0684-added-PlayerNameEntityEvent.patch | 41 + ...-grindstones-from-overstacking-items.patch | 26 + .../0686-Add-recipe-to-cook-events.patch | 44 + .../0687-Add-Block-isValidTool.patch | 20 + ...-using-signs-inside-spawn-protection.patch | 41 + .../0689-Implement-Keyed-on-World.patch | 110 + ...alternative-constructor-for-Vector3f.patch | 30 + .../0691-Item-Rarity-API.patch | 52 + ...Timer-for-Wandering-Traders-spawned-.patch | 58 + ...opy-TESign-isEditable-from-snapshots.patch | 18 + ...ed-item-when-player-has-disconnected.patch | 35 + ...telist-use-configurable-kick-message.patch | 27 + ...-to-remove-correct-TE-during-TE-tick.patch | 45 + ...ignore-result-of-PlayerEditBookEvent.patch | 19 + ...-block-falling-causing-client-desync.patch | 59 + .../0699-Expose-protocol-version.patch | 22 + ...ent-suggestion-tooltips-in-AsyncTabC.patch | 132 + ...tab-completions-for-brigadier-comman.patch | 316 ++ ...ItemConsumeEvent-cancelling-properly.patch | 22 + .../0703-Add-bypass-host-check.patch | 30 + ...don-t-throw-when-loading-invalid-TEs.patch | 33 + .../0705-Set-area-affect-cloud-rotation.patch | 18 + ...-add-isDeeplySleeping-to-HumanEntity.patch | 24 + ...ating-give-items-on-item-drop-cancel.patch | 113 + ...-add-consumeFuel-to-FurnaceBurnEvent.patch | 19 + ...t-set-drop-chance-to-EntityEquipment.patch | 48 + ...fix-PigZombieAngerEvent-cancellation.patch | 47 + ...x-checkReach-check-for-Shulker-boxes.patch | 18 + ...fix-PlayerItemHeldEvent-firing-twice.patch | 30 + .../0713-Added-PlayerDeepSleepEvent.patch | 22 + .../server-remapped/0714-More-World-API.patch | 146 + .../0715-Added-PlayerBedFailEnterEvent.patch | 57 + ...s-to-convert-between-Component-and-B.patch | 55 + ...wn-acting-as-a-bed-respawn-from-the-.patch | 36 + ...d-RespawnFlags-to-PlayerRespawnEvent.patch | 46 + ...eacon-activation-deactivation-events.patch | 37 + ...Add-Channel-initialization-listeners.patch | 119 + ...mmands-if-tab-completion-is-disabled.patch | 24 + .../0722-Add-more-WanderingTrader-API.patch | 65 + ...Add-EntityBlockStorage-clearEntities.patch | 37 + ...essage-to-PlayerAdvancementDoneEvent.patch | 89 + ...-address-to-AsyncPlayerPreLoginEvent.patch | 25 + .../0726-Inventory-close.patch | 25 + ...CreateEvent-players-and-end-platform.patch | 45 + ...n-in-sunlight-API-for-Phantoms-and-S.patch | 126 + .../0729-Fix-CraftPotionBrewer-cache.patch | 44 + .../0730-Add-basic-Datapack-API.patch | 174 + ...nment-variable-to-disable-server-gui.patch | 18 + ...ditions-to-PlayerGameModeChangeEvent.patch | 138 + .../0733-ItemStack-repair-check-API.patch | 91 + .../0734-More-Enchantment-API.patch | 211 + ...-option-to-load-extra-plugin-jars-no.patch | 64 + ...atus-dataconverter-for-pre-1.13-chun.patch | 91 + ...crease-structure-block-data-length-t.patch | 19 + ...x-and-optimise-world-force-upgrading.patch | 411 ++ .../0739-Add-Mob-lookAt-API.patch | 127 + .../0740-Add-Unix-domain-socket-support.patch | 141 + .../0741-Add-EntityInsideBlockEvent.patch | 222 + ...742-Attributes-API-for-item-defaults.patch | 42 + ...chantCustom-emit-PlayerPurchaseEvent.patch | 59 + ...cause-to-Weather-ThunderChangeEvents.patch | 136 + .../0745-More-Lidded-Block-API.patch | 127 + .../0746-Add-PlayerKickEvent-causes.patch | 393 ++ ...747-Limit-item-frame-cursors-on-maps.patch | 37 + .../0748-Add-PufferFishStateChangeEvent.patch | 50 + ...yerBucketEmptyEvent-result-itemstack.patch | 43 + ...n-to-fix-items-merging-through-walls.patch | 39 + .../0751-Add-BellRevealRaiderEvent.patch | 26 + .../0752-Fix-invulnerable-end-crystals.patch | 105 + ...753-Add-ElderGuardianAppearanceEvent.patch | 23 + ...-inventory-on-cancelled-pickup-event.patch | 62 + .../0755-Fix-dangerous-end-portal-logic.patch | 107 + ...6-Make-item-validations-configurable.patch | 83 + .../0757-Add-more-line-of-sight-methods.patch | 62 + .../0758-add-per-world-spawn-limits.patch | 49 + ...SplashEvent-for-water-splash-potions.patch | 63 + .../server-unmapped/0001-POM-Changes.patch | 291 + .../0002-Paper-config-files.patch | 820 +++ .../server-unmapped/0003-MC-Dev-fixes.patch | 893 +++ patches/server-unmapped/0004-MC-Utils.patch | 4850 ++++++++++++++++ .../server-unmapped/0005-Paper-Metrics.patch | 735 +++ ...-MinecraftKey-Information-to-Objects.patch | 144 + ...to-current-Chunk-for-Entity-and-Bloc.patch | 171 + ...ts-for-each-Entity-Block-Entity-Type.patch | 55 + patches/server-unmapped/0009-Timings-v2.patch | 2309 ++++++++ patches/server-unmapped/0010-Adventure.patch | 3278 +++++++++++ ...actus-bamboo-and-reed-growth-heights.patch | 114 + ...figurable-baby-zombie-movement-speed.patch | 51 + ...013-Configurable-fishing-time-ranges.patch | 38 + ...d-mobs-to-jump-and-take-water-damage.patch | 98 + ...-despawn-distances-for-living-entiti.patch | 55 + ...6-Allow-for-toggling-of-spawn-chunks.patch | 33 + ...ck-and-tnt-entities-at-the-specified.patch | 94 + ...ient-crashes-server-lists-and-Mojang.patch | 117 + .../0019-Implement-Paper-VersionChecker.patch | 150 + ...d-version-history-to-version-command.patch | 215 + .../0021-Player-affects-spawning-API.patch | 157 + ...ve-invalid-mob-spawner-tile-entities.patch | 33 + .../0023-Optimize-TileEntity-Ticking.patch | 248 + ...024-Further-improve-server-tick-loop.patch | 208 + ...025-Only-refresh-abilities-if-needed.patch | 25 + .../0026-Entity-Origin-API.patch | 140 + ...event-tile-entity-and-entity-crashes.patch | 65 + ...nfigurable-top-of-nether-void-damage.patch | 89 + ...e-before-converting-and-renaming-pla.patch | 19 + .../0030-Always-tick-falling-blocks.patch | 18 + .../0031-Configurable-end-credits.patch | 42 + ...-explosions-processing-dead-entities.patch | 19 + .../0033-Optimize-explosions.patch | 148 + .../0034-Disable-explosion-knockback.patch | 69 + .../0035-Disable-thunder.patch | 33 + .../0036-Disable-ice-and-snow.patch | 33 + ...7-Configurable-mob-spawner-tick-rate.patch | 65 + ...sition-the-first-time-an-entity-is-s.patch | 108 + .../0039-Add-BeaconEffectEvent.patch | 67 + ...figurable-container-update-tick-rate.patch | 46 + .../0041-Use-UserCache-for-player-heads.patch | 25 + .../0042-Disable-spigot-tick-limiters.patch | 21 + .../0043-Add-PlayerInitialSpawnEvent.patch | 48 + ...urable-Disabling-Cat-Chest-Detection.patch | 37 + ...45-Ensure-commands-are-not-ran-async.patch | 119 + ...chunks-are-slime-spawn-chunks-toggle.patch | 33 + .../0047-Expose-server-CommandMap.patch | 18 + ...e-informative-in-maxHealth-exception.patch | 22 + .../0049-Player-Tab-List-and-Title-APIs.patch | 142 + .../0050-Ensure-inv-drag-is-in-bounds.patch | 19 + ...entation-of-tile-entity-removal-list.patch | 20 + ...dd-configurable-portal-search-radius.patch | 56 + .../0053-Add-velocity-warnings.patch | 89 + ...ble-inter-world-teleportation-safety.patch | 44 + .../0055-Add-exception-reporting-event.patch | 264 + ...-don-t-need-to-when-cerealising-text.patch | 27 + ...oreboards-for-non-players-by-default.patch | 50 + ...working-with-arrows-stuck-in-living-.patch | 27 + .../0059-Complete-resource-pack-API.patch | 71 + .../0060-Chunk-Save-Reattempt.patch | 59 + ...ading-permissions.yml-before-plugins.patch | 52 + ...llow-Reloading-of-Custom-Permissions.patch | 35 + .../0063-Remove-Metadata-on-reload.patch | 31 + ...064-Handle-Item-Meta-Inconsistencies.patch | 331 ++ ...urable-Non-Player-Arrow-Despawn-Rate.patch | 44 + .../0066-Add-World-Util-Methods.patch | 65 + ...7-Custom-replacement-for-eaten-items.patch | 48 + ...th-absorb-values-and-repair-bad-data.patch | 57 + ...069-Use-a-Shared-Random-for-Entities.patch | 42 + ...le-spawn-chances-for-skeleton-horses.patch | 36 + ...Location-getType-and-getBlockData-fo.patch | 206 + ...ckPhysicsEvent-if-a-plugin-has-a-lis.patch | 95 + ...Entity-AddTo-RemoveFrom-World-Events.patch | 27 + ...74-Configurable-Chunk-Inhabited-Time.patch | 44 + .../0075-EntityPathfindEvent.patch | 107 + ...egionFileCache-and-make-configurable.patch | 39 + ...7-Do-not-load-chunks-for-Pathfinding.patch | 68 + ...0078-Add-PlayerUseUnknownEntityEvent.patch | 40 + ...dDebugInfo-not-initialized-on-client.patch | 18 + ...-Configurable-Grass-Spread-Tick-Rate.patch | 41 + ...g-BlockPlaceEvent-triggering-physics.patch | 18 + .../0082-Optimize-DataBits.patch | 84 + ...nilla-per-world-scoreboard-coloring-.patch | 66 + ...nd-for-setting-passengers-on-players.patch | 29 + ...Remove-unused-World-Tile-Entity-List.patch | 90 + .../0086-Don-t-tick-Skulls-unused-code.patch | 28 + .../0087-Configurable-Player-Collision.patch | 131 + ...ent-to-allow-plugins-to-handle-clien.patch | 57 + .../0089-Configurable-RCON-IP-address.patch | 59 + ...e-from-loading-chunks-wrongly-spread.patch | 82 + ...91-Implement-PlayerLocaleChangeEvent.patch | 48 + ...ityRegainHealthEvent-isFastRegen-API.patch | 42 + ...-to-configure-frosted_ice-properties.patch | 52 + ...-possibility-for-getServer-singleton.patch | 36 + ...item-frames-performance-and-bug-fixe.patch | 144 + ...-API-Replenishable-Lootables-Feature.patch | 736 +++ ...y-scoreboard-teams-to-scoreboard.dat.patch | 32 + ...tem-property-for-disabling-watchdoge.patch | 19 + .../0099-Optimize-UserCache-Thread-Safe.patch | 117 + ...blocking-on-Network-Manager-creation.patch | 45 + ...1-Optional-TNT-doesn-t-move-in-water.patch | 122 + ...r-redstone-torch-rapid-clock-removal.patch | 98 + .../0103-Add-server-name-parameter.patch | 25 + ...on-Wither-Death-sounds-to-same-world.patch | 39 + .../0105-Fix-Double-World-Add-issues.patch | 21 + .../0106-Fix-Old-Sign-Conversion.patch | 59 + ...e-profiles-that-have-no-UUID-and-no-.patch | 19 + ...setting-for-proxy-online-mode-status.patch | 81 + ...ptimise-BlockState-s-hashCode-equals.patch | 84 + ...onfigurable-packet-in-spam-threshold.patch | 45 + ...11-Configurable-flying-kick-messages.patch | 44 + .../0112-Chunk-registration-fixes.patch | 22 + ...ok-reference-on-Craft-Entity-removal.patch | 25 + ...uto-fix-bad-Y-levels-on-player-login.patch | 19 + ...tion-to-remove-corrupt-tile-entities.patch | 37 + .../0116-Add-EntityZapEvent.patch | 58 + ...a-from-ArmorStand-and-SpawnEgg-items.patch | 49 + ...118-Cache-user-authenticator-threads.patch | 68 + .../0119-Optimise-removeQueue.patch | 67 + ...0-Allow-Reloading-of-Command-Aliases.patch | 36 + ...1-Add-source-to-PlayerExpChangeEvent.patch | 49 + ...2-Don-t-let-fishinghooks-use-portals.patch | 22 + .../0123-Add-ProjectileCollideEvent.patch | 109 + ...vent-Pathfinding-out-of-World-Border.patch | 20 + ...imize-World.isLoaded-BlockPosition-Z.patch | 22 + ...-Bound-Treasure-Maps-to-World-Border.patch | 47 + ...figurable-Cartographer-Treasure-Maps.patch | 65 + .../0128-Optimize-ItemStack.isEmpty.patch | 20 + ...to-control-if-armour-stands-can-move.patch | 81 + ...30-Properly-fix-item-duplication-bug.patch | 35 + .../0131-String-based-Action-Bar-API.patch | 48 + .../server-unmapped/0132-Firework-API-s.patch | 124 + .../0133-PlayerTeleportEndGatewayEvent.patch | 28 + ...rovide-E-TE-Chunk-count-stat-methods.patch | 61 + .../0135-Enforce-Sync-Player-Saves.patch | 26 + ...llow-entities-to-ride-themselves-572.patch | 18 + ...PI-for-Reason-Source-Triggering-play.patch | 315 ++ .../0138-Cap-Entity-Collisions.patch | 57 + ...e-CraftScheduler-Async-Task-Debugger.patch | 48 + ...more-aggressive-in-the-chunk-unload-.patch | 47 + .../0141-Do-not-let-armorstands-drown.patch | 42 + ...le-async-calls-to-restart-the-server.patch | 307 ++ ...property-to-disable-book-size-limits.patch | 51 + ...ke-parrots-stay-on-shoulders-despite.patch | 58 + ...n-option-to-prevent-player-names-fro.patch | 36 + ...oleAppender-for-console-improvements.patch | 549 ++ ...urable-option-to-disable-creeper-lin.patch | 35 + .../0148-Item-canEntityPickup.patch | 55 + ...PlayerPickupItemEvent-setFlyAtPlayer.patch | 46 + .../0150-PlayerAttemptPickupItemEvent.patch | 41 + .../0151-Add-UnknownCommandEvent.patch | 25 + .../0152-Basic-PlayerProfile-API.patch | 575 ++ .../0153-Shoulder-Entities-Release-API.patch | 96 + .../0154-Profile-Lookup-Events.patch | 81 + ...player-logins-during-server-shutdown.patch | 23 + .../0156-Entity-fromMobSpawner.patch | 65 + ...57-Improve-the-Saddle-API-for-Horses.patch | 59 + ...mplement-ensureServerConversions-API.patch | 24 + .../0159-Implement-getI18NDisplayName.patch | 58 + .../0160-ProfileWhitelistVerifyEvent.patch | 50 + .../0161-Fix-this-stupid-bullshit.patch | 30 + ...awns-should-honor-nametags-and-leash.patch | 19 + ...imer-when-spawner-event-is-cancelled.patch | 27 + ...64-Fix-MC-117075-TE-Unload-Lag-Spike.patch | 23 + ...-a-custom-authentication-servers-dow.patch | 43 + .../0166-LivingEntity-setKiller.patch | 48 + ...n-prefixes-using-Log4J-configuration.patch | 71 + ...e-Log4J-Configuration-Plugin-Loggers.patch | 47 + .../0169-Add-PlayerJumpEvent.patch | 46 + ...0-handle-PacketPlayInKeepAlive-async.patch | 40 + ...nt-protocol-version-and-virtual-host.patch | 129 + ...rt-serverside-behavior-of-keepalives.patch | 75 + ...dEffects-only-to-players-who-can-see.patch | 80 + ...-maximum-exp-value-when-merging-orbs.patch | 61 + .../0175-Add-PlayerArmorChangeEvent.patch | 43 + ...rom-being-processed-when-the-player-.patch | 24 + ...e-implementations-for-captured-block.patch | 60 + ...-get-a-BlockState-without-a-snapshot.patch | 147 + .../0179-AsyncTabCompleteEvent.patch | 130 + ...180-Avoid-NPE-in-PathfinderGoalTempt.patch | 19 + .../0181-PlayerPickupExperienceEvent.patch | 28 + .../0182-ExperienceOrbMergeEvent.patch | 22 + ...3-Ability-to-apply-mending-to-XP-API.patch | 104 + ...-max-squid-spawn-height-configurable.patch | 36 + .../0185-PreCreatureSpawnEvent.patch | 200 + ...6-PlayerNaturallySpawnCreaturesEvent.patch | 79 + ...-Add-setPlayerProfile-API-for-Skulls.patch | 99 + .../0188-Fill-Profile-Property-Events.patch | 42 + ...PlayerAdvancementCriterionGrantEvent.patch | 23 + .../0190-Add-ArmorStand-Item-Meta.patch | 296 + ...-Extend-Player-Interact-cancellation.patch | 68 + .../0192-Tameable-getOwnerUniqueId-API.patch | 36 + ...r-crits-helps-mitigate-hacked-client.patch | 34 + ...sted-Ice-from-loading-holding-chunks.patch | 31 + ...le-Explicit-Network-Manager-Flushing.patch | 34 + ...nt-extended-PaperServerListPingEvent.patch | 283 + .../0197-Improved-Async-Task-Scheduler.patch | 370 ++ ...e-PlayerProfile-in-AsyncPreLoginEven.patch | 45 + .../0199-Player.setPlayerProfile-API.patch | 142 + .../0200-Fix-Dragon-Server-Crashes.patch | 21 + .../0201-getPlayerUniqueId-API.patch | 40 + ...Make-player-data-saving-configurable.patch | 27 + ...ke-legacy-ping-handler-more-reliable.patch | 168 + ...ServerListPingEvent-for-legacy-pings.patch | 154 + ...05-Flag-to-disable-the-channel-limit.patch | 31 + ...d-method-to-open-already-placed-sign.patch | 36 + ...urable-sprint-interruption-on-attack.patch | 38 + ...-allowed-colored-signs-to-be-created.patch | 31 + .../0209-EndermanEscapeEvent.patch | 82 + .../0210-Enderman.teleportRandomly.patch | 31 + ...0211-Block-Enderpearl-Travel-Exploit.patch | 40 + ...ld.spawnParticle-API-and-add-Builder.patch | 67 + .../0213-EndermanAttackPlayerEvent.patch | 29 + .../0214-WitchConsumePotionEvent.patch | 24 + .../0215-WitchThrowPotionEvent.patch | 30 + ...Item-entities-with-World.spawnEntity.patch | 24 + .../0217-WitchReadyPotionEvent.patch | 23 + ...0218-ItemStack-getMaxItemUseDuration.patch | 37 + ...lement-EntityTeleportEndGatewayEvent.patch | 32 + ...ed-flag-on-cancel-of-Explosion-Event.patch | 28 + .../0221-Fix-CraftEntity-hashCode.patch | 46 + ...le-Alternative-LootPool-Luck-Formula.patch | 110 + ...ils-when-failing-to-save-player-data.patch | 19 + ...e-shield-blocking-delay-configurable.patch | 69 + .../0225-Improve-EntityShootBowEvent.patch | 44 + .../0226-PlayerReadyArrowEvent.patch | 39 + ...plement-EntityKnockbackByEntityEvent.patch | 93 + .../0228-Expand-Explosions-API.patch | 23 + ...ivingEntity-Hand-Raised-Item-Use-API.patch | 68 + .../0230-RangedEntity-API.patch | 171 + ...to-disable-ender-dragon-legacy-check.patch | 44 + ...2-Implement-World.getEntity-UUID-API.patch | 26 + .../0233-InventoryCloseEvent-Reason-API.patch | 227 + .../0234-Vex-getSummoner-API.patch | 37 + ...nventory-when-cancelling-PlayerInter.patch | 29 + ...ge-the-Entity-Random-seed-for-squids.patch | 19 + ...nilla-entity-warnings-for-duplicates.patch | 22 + ...e-if-stack-size-above-max-stack-size.patch | 21 + ...239-Use-asynchronous-Log4j-2-loggers.patch | 55 + ...-more-information-to-Entity.toString.patch | 20 + ...ies-option-to-debug-dupe-uuid-issues.patch | 131 + .../0242-EnderDragon-Events.patch | 62 + .../0243-PlayerElytraBoostEvent.patch | 31 + .../0244-Improve-BlockPosition-inlining.patch | 75 + .../0245-Optimize-RegistryID.c.patch | 65 + ...t-armor-stands-from-doing-entity-loo.patch | 58 + ...7-Vanished-players-don-t-have-rights.patch | 194 + ...-anytime-entities-change-to-guarante.patch | 27 + ...dd-some-Debug-to-Chunk-Entity-slices.patch | 80 + .../0250-SkeletonHorse-Additions.patch | 152 + ...revent-Saving-Bad-entities-to-chunks.patch | 127 + ...on-t-call-getItemMeta-on-hasItemMeta.patch | 64 + ...ead-Entities-in-entityList-iteration.patch | 120 + ...54-Implement-Expanded-ArmorStand-API.patch | 112 + .../0255-AnvilDamageEvent.patch | 28 + .../0256-Add-TNTPrimeEvent.patch | 148 + ...nd-make-tab-spam-limits-configurable.patch | 75 + .../0258-Add-hand-to-bucket-events.patch | 174 + ...6-Experience-should-save-as-Integers.patch | 28 + ...ient-rendering-skulls-from-same-user.patch | 147 + ...dd-Early-Warning-Feature-to-WatchDog.patch | 184 + .../0262-Make-EnderDragon-implement-Mob.patch | 33 + ...63-Use-ConcurrentHashMap-in-JsonList.patch | 136 + ...64-Use-a-Queue-for-Queueing-Commands.patch | 33 + ...ile-Entities-from-a-chunk-without-sn.patch | 73 + ...Allow-disabling-armour-stand-ticking.patch | 159 + ...ptimize-BlockPosition-helper-methods.patch | 100 + ...efault-mob-spawn-range-and-water-ani.patch | 33 + .../0269-Slime-Pathfinder-Events.patch | 167 + ...le-speed-for-water-flowing-over-lava.patch | 72 + ...271-Optimize-CraftBlockData-Creation.patch | 49 + .../0272-Optimize-RegistryMaterials.patch | 61 + .../0273-Add-PhantomPreSpawnEvent.patch | 96 + .../0274-Add-More-Creeper-API.patch | 49 + .../0275-Inventory-removeItemAnySlot.patch | 58 + ...loadChunk-int-int-false-load-unconve.patch | 20 + ...-ray-tracing-methods-to-LivingEntity.patch | 99 + ...e-attack-cooldown-methods-for-Player.patch | 41 + .../0279-Improve-death-events.patch | 425 ++ ...ow-chests-to-be-placed-with-NBT-data.patch | 31 + .../0281-Mob-Pathfinding-API.patch | 290 + ...ent-chunk-loading-from-Fluid-Flowing.patch | 75 + ...-for-CanPlaceOn-and-CanDestroy-NBT-v.patch | 446 ++ ...ent-Mob-AI-Rules-from-Loading-Chunks.patch | 83 + ...wning-from-loading-generating-chunks.patch | 32 + ...e-Biome-Mob-Lookups-for-Mob-Spawning.patch | 92 + ...nt-furnace-cook-speed-multiplier-API.patch | 102 + .../0288-PreSpawnerSpawnEvent.patch | 29 + ...arseException-in-Entity-and-TE-names.patch | 110 + .../0290-Honor-EntityAgeable.ageLock.patch | 18 + ...ble-connection-throttle-kick-message.patch | 35 + .../0292-Hook-into-CB-plugin-rewrites.patch | 184 + ...293-Allow-setting-the-vex-s-summoner.patch | 33 + .../0294-Add-sun-related-API.patch | 52 + patches/server-unmapped/0295-Turtle-API.patch | 150 + ...ther-worlds-for-shooter-of-projectil.patch | 36 + ...tator-target-events-and-improve-impl.patch | 101 + ...8-Add-Velocity-IP-Forwarding-Support.patch | 307 ++ .../0299-Add-more-Witch-API.patch | 153 + ...owned-for-Villager-Aggression-Config.patch | 19 + .../server-unmapped/0301-Here-s-Johnny.patch | 38 + ...event-players-from-moving-into-unloa.patch | 64 + ...03-Reset-players-airTicks-on-respawn.patch | 30 + ...-after-profile-lookups-if-not-needed.patch | 33 + ...er-Thread-Pool-and-Thread-Priorities.patch | 108 + .../0306-Optimize-World-Time-Updates.patch | 42 + ...store-custom-InventoryHolder-support.patch | 46 + .../0308-Use-Vanilla-Minecart-Speeds.patch | 24 + .../0309-Fix-SpongeAbsortEvent-handling.patch | 37 + ...t-allow-digging-into-unloaded-chunks.patch | 68 + .../0311-Book-Size-Limits.patch | 80 + ...ault-permission-message-configurable.patch | 46 + ...Prevent-rayTrace-from-loading-chunks.patch | 29 + ...e-Large-Packets-disconnecting-client.patch | 130 + ...entity-dismount-during-teleportation.patch | 134 + .../0316-Add-more-Zombie-API.patch | 117 + .../0317-Add-PlayerConnectionCloseEvent.patch | 82 + ...Prevent-Enderman-from-loading-chunks.patch | 30 + ...-replace-OfflinePlayer-getLastPlayed.patch | 164 + ...vehicle-tracking-issue-on-disconnect.patch | 24 + ...onRetractEvent-for-all-empty-pistons.patch | 47 + ...-remove-from-being-called-on-Players.patch | 33 + .../0323-BlockDestroyEvent.patch | 46 + ...om-Shapeless-Custom-Crafting-Recipes.patch | 68 + .../0325-Fix-sign-edit-memory-leak.patch | 44 + .../0326-Limit-Client-Sign-length-more.patch | 54 + ...ConvertSigns-boolean-every-sign-save.patch | 29 + ...-Manager-and-add-advanced-packet-sup.patch | 390 ++ ...le-Oversized-Tile-Entities-in-chunks.patch | 54 + ...0-Fix-Whitelist-On-Off-inconsistency.patch | 36 + ...st-tick-at-start-of-drowning-process.patch | 19 + ...332-Allow-Saving-of-Oversized-Chunks.patch | 272 + ...oggleEvent-when-whitelist-is-toggled.patch | 18 + ...334-Add-LivingEntity-getTargetEntity.patch | 187 + ...ength-when-serialising-BungeeCord-te.patch | 32 + .../0336-Entity-getEntitySpawnReason.patch | 121 + ...ity-Metadata-for-all-tracked-players.patch | 43 + ...338-Implement-PlayerPostRespawnEvent.patch | 48 + ...-for-pickupDelay-breaks-picking-up-i.patch | 27 + .../0340-Server-Tick-Events.patch | 32 + ...0341-PlayerDeathEvent-getItemsToKeep.patch | 74 + ...-Optimize-Captured-TileEntity-Lookup.patch | 32 + .../0343-Add-Heightmap-API.patch | 55 + .../0344-Mob-Spawner-API-Enhancements.patch | 140 + ...layer-View-Distance-API-placeholders.patch | 62 + ...l-to-changed-postToMainThread-method.patch | 19 + ...n-item-frames-are-modified-MC-123450.patch | 20 + ...isPrimaryThread-and-MinecraftServer-.patch | 43 + ...h-entity-loss-due-to-unloaded-chunks.patch | 53 + .../0350-Duplicate-UUID-Resolve-Option.patch | 249 + ...351-improve-CraftWorld-isChunkLoaded.patch | 30 + ...le-Keep-Spawn-Loaded-range-per-world.patch | 261 + ...tityAreaEffectCloud-from-going-negat.patch | 24 + .../0354-ChunkMapDistance-CME.patch | 83 + .../0355-Implement-CraftBlockSoundGroup.patch | 83 + .../0356-Chunk-debug-command.patch | 486 ++ ...eptions-from-dispenser-entity-spawns.patch | 33 + ...358-Fix-World-isChunkGenerated-calls.patch | 390 ++ ...ate-location-if-we-failed-to-read-it.patch | 34 + ...PaletteBlock-instead-of-ReentrantLoc.patch | 101 + .../0361-incremental-chunk-saving.patch | 317 ++ patches/server-unmapped/0362-Anti-Xray.patch | 1567 ++++++ ...al-Spawned-mobs-towards-natural-spaw.patch | 57 + ...gurable-projectile-relative-velocity.patch | 53 + ...-being-ticked-when-notifying-navigat.patch | 26 + .../0366-offset-item-frame-ticking.patch | 19 + ...opper-searches-if-there-are-no-items.patch | 127 + ...68-Asynchronous-chunk-IO-and-loading.patch | 4203 ++++++++++++++ ...etChunkIfLoadedImmediately-in-places.patch | 96 + .../0370-Reduce-sync-loads.patch | 342 ++ ...lement-alternative-item-despawn-rate.patch | 127 + ...if-we-have-a-custom-Bukkit-generator.patch | 42 + .../server-unmapped/0373-Fix-MC-158900.patch | 25 + ...ement-optional-per-player-mob-spawns.patch | 848 +++ ...revent-consuming-the-wrong-itemstack.patch | 45 + .../0376-Generator-Settings.patch | 89 + .../server-unmapped/0377-Fix-MC-161754.patch | 23 + ...ce-improvement-for-Chunk.getEntities.patch | 35 + ...hanging-entities-that-are-not-ItemFr.patch | 25 + ...380-Expose-the-internal-current-tick.patch | 21 + ...-sneak-when-changing-worlds-MC-10657.patch | 32 + ...d-option-to-disable-pillager-patrols.patch | 32 + ...or-when-player-hand-set-to-empty-typ.patch | 35 + .../0384-PlayerLaunchProjectileEvent.patch | 329 ++ ...ftMagicNumbers.isSupportedApiVersion.patch | 22 + ...nk-loads-when-villagers-try-to-find-.patch | 20 + ...5656-Fix-Follow-Range-Initial-Target.patch | 73 + .../0388-Optimize-Hoppers.patch | 517 ++ ...layerDeathEvent-shouldDropExperience.patch | 19 + ...oading-chunks-checking-hive-position.patch | 18 + ...Chunks-from-Hoppers-and-other-things.patch | 32 + ...rializing-mismatching-chunk-coordina.patch | 62 + ...timise-IEntityAccess-getPlayerByUUID.patch | 44 + ...0394-Fix-items-not-falling-correctly.patch | 29 + .../0395-Lag-compensate-eating.patch | 83 + ...mize-call-to-getFluid-for-explosions.patch | 19 + ...k-in-stack-not-having-effects-when-d.patch | 23 + ...-Add-effect-to-block-break-naturally.patch | 32 + .../0399-Tracking-Range-Improvements.patch | 67 + .../0400-Entity-Activation-Range-2.0.patch | 869 +++ ...x-items-vanishing-through-end-portal.patch | 28 + ...get-gravity-in-void.-Fixes-MC-167279.patch | 55 + ...e-getChunkAt-calls-for-loaded-chunks.patch | 66 + ...ow-overriding-the-java-version-check.patch | 20 + .../0405-Add-ThrownEggHatchEvent.patch | 29 + .../0406-Optimise-random-block-ticking.patch | 407 ++ .../0407-Entity-Jump-API.patch | 59 + ...n-to-nerf-pigmen-from-nether-portals.patch | 71 + .../0409-Make-the-GUI-graph-fancier.patch | 436 ++ ...410-add-hand-to-BlockMultiPlaceEvent.patch | 30 + ...11-Prevent-teleporting-dead-entities.patch | 21 + ...ripwire-hook-placement-before-update.patch | 18 + ...to-allow-iron-golems-to-spawn-in-air.patch | 35 + ...-chance-of-villager-zombie-infection.patch | 44 + .../0415-Optimise-Chunk-getFluid.patch | 62 + ...imise-TickListServer-by-rewriting-it.patch | 1267 +++++ ...spawn-settings-and-per-player-option.patch | 151 + ...re-Entity-is-never-double-registered.patch | 79 + ...ering-entities-from-unloading-chunks.patch | 32 + ...nnections-shouldn-t-hold-up-shutdown.patch | 25 + ...low-bees-to-load-chunks-for-beehives.patch | 42 + ...-PlayerChunkMap-adds-crashing-server.patch | 48 + ...ptimize-Collision-to-not-load-chunks.patch | 161 + .../0424-Don-t-tick-dead-players.patch | 21 + ...d-Player-s-shouldn-t-be-able-to-move.patch | 21 + ...hunkMap-memory-use-for-visibleChunks.patch | 294 + .../0427-Increase-Light-Queue-Size.patch | 42 + ...asks-Speed-up-processing-of-chunk-lo.patch | 271 + ...move-existing-players-to-world-spawn.patch | 54 + ...-Add-tick-times-API-and-mspt-command.patch | 169 + ...431-Expose-MinecraftServer-isRunning.patch | 22 + ...Add-Raw-Byte-ItemStack-Serialization.patch | 102 + ...33-Remove-streams-from-Mob-AI-System.patch | 253 + ...ions-until-after-entity-ticking-is-d.patch | 45 + .../0435-Async-command-map-building.patch | 48 + .../0436-Improved-Watchdog-Support.patch | 608 +++ .../0437-Optimize-Pathfinding.patch | 61 + ...38-Reduce-Either-Optional-allocation.patch | 48 + ...0439-Remove-streams-from-PairedQueue.patch | 79 + ...e-memory-footprint-of-NBTTagCompound.patch | 59 + ...vent-opening-inventories-when-frozen.patch | 59 + ...442-Optimise-ArraySetSorted-removeIf.patch | 65 + ...-entity-collision-code-if-not-needed.patch | 30 + ...oviderServer-s-chunk-level-checking-.patch | 51 + ...-teleport-command-to-valid-locations.patch | 24 + ...-Implement-Player-Client-Options-API.patch | 188 + ...-Chunk-Post-Processing-deadlock-risk.patch | 60 + ...layer-is-attempted-to-be-removed-fro.patch | 23 + ...49-Broadcast-join-message-to-console.patch | 21 + ...g-Broken-behavior-of-PlayerJoinEvent.patch | 111 + ...Load-Chunks-for-Login-Asynchronously.patch | 306 ++ ...pawn-point-if-spawn-in-unloaded-worl.patch | 27 + ...PlayerAttackEntityCooldownResetEvent.patch | 28 + ...allbacks-to-schedule-for-Callback-Ex.patch | 58 + ...t-fire-BlockFade-on-worldgen-threads.patch | 28 + ...ntom-creative-and-insomniac-controls.patch | 69 + ...m-duplication-issues-and-teleport-is.patch | 117 + .../0458-Implement-Brigadier-Mojang-API.patch | 139 + .../0459-Villager-Restocks-API.patch | 42 + ...PickItem-Packet-and-kick-for-invalid.patch | 26 + .../0461-Expose-game-version.patch | 24 + .../0462-Optimize-Voxel-Shape-Merging.patch | 127 + ...-per-thread-native-byte-buffer-cache.patch | 30 + .../0464-Implement-Mob-Goal-API.patch | 1170 ++++ ...tance-map-to-optimise-entity-tracker.patch | 413 ++ ...-isOutsideRange-to-use-distance-maps.patch | 384 ++ ...te-operations-for-updating-light-dat.patch | 319 ++ ...No-Tick-view-distance-implementation.patch | 774 +++ .../0469-Add-villager-reputation-API.patch | 153 + .../0470-Fix-Light-Command.patch | 185 + ...1-Fix-PotionEffect-ignores-icon-flag.patch | 19 + ...-brigadier-child-sorting-performance.patch | 29 + .../0473-Potential-bed-API.patch | 44 + ...Wait-for-Async-Tasks-during-shutdown.patch | 63 + ...der-respects-game-and-entity-rules-f.patch | 28 + ...and-End-Portal-Frames-from-being-des.patch | 173 + ...ze-NibbleArray-to-use-pooled-buffers.patch | 394 ++ ...bleInt-allocations-from-light-engine.patch | 50 + ...llocation-of-Vec3D-by-entity-tracker.patch | 61 + .../0480-Ensure-safe-gateway-teleport.patch | 27 + ...n-for-console-having-all-permissions.patch | 74 + ...on-Full-Status-Chunk-NBT-Memory-Leak.patch | 99 + ...ound-for-Client-Lag-Spikes-MC-162253.patch | 119 + ...k-Priority-Urgency-System-for-Chunks.patch | 1326 +++++ ...-packets-to-nearby-locations-sounds-.patch | 63 + ...mprove-Chunk-Status-Transition-Speed.patch | 99 + ...ix-villager-trading-demand-MC-163962.patch | 20 + .../0488-Maps-shouldn-t-load-chunks.patch | 32 + ...ookup-for-Treasure-Maps-Fixes-lag-fr.patch | 35 + ...-Optimize-Bit-Operations-by-inlining.patch | 220 + .../0491-Optimize-Light-Engine.patch | 1433 +++++ ...unk-Unloads-based-on-Player-Movement.patch | 107 + ...-Plugin-Tickets-to-API-Chunk-Methods.patch | 129 + ...ssing-chunks-due-to-integer-overflow.patch | 29 + ...er-runTaskTimerAsynchronously-Plugin.patch | 21 + ...ston-physics-inconsistency-MC-188840.patch | 93 + .../0497-Fix-sand-duping.patch | 37 + ...-desync-in-playerconnection-causing-.patch | 31 + .../0499-Fix-enderdragon-exp-dupe.patch | 28 + ...Holder-method-without-block-snapshot.patch | 50 + .../0501-Expose-Arrow-getItemStack.patch | 36 + ...implement-PlayerRecipeBookClickEvent.patch | 29 + ...3-Hide-sync-chunk-writes-behind-flag.patch | 23 + ...mit-lightning-strike-effect-distance.patch | 68 + ...05-Add-permission-for-command-blocks.patch | 79 + ...sure-Entity-AABB-s-are-never-invalid.patch | 48 + ...WorldBorder-collision-checks-and-air.patch | 63 + ...ld-Difficulty-Remembering-Difficulty.patch | 86 + .../0509-Paper-dumpitem-command.patch | 80 + ...510-Don-t-allow-null-UUID-s-for-chat.patch | 27 + ...-Legacy-Component-serialization-size.patch | 56 + ...0512-Support-old-UUID-format-for-NBT.patch | 64 + ...up-duplicated-GameProfile-Properties.patch | 68 + ...nvert-legacy-attributes-in-Item-Meta.patch | 44 + ...-Remove-some-streams-from-structures.patch | 140 + ...from-classes-related-villager-gossip.patch | 100 + .../0517-Support-components-in-ItemMeta.patch | 83 + ...argetLivingEntityEvent-for-1.16-mobs.patch | 59 + .../0519-Add-entity-liquid-API.patch | 75 + ...pdate-itemstack-legacy-name-and-lore.patch | 79 + ...awn-player-in-correct-world-on-login.patch | 30 + .../0522-Add-PrepareResultEvent.patch | 164 + ...llow-delegation-to-vanilla-chunk-gen.patch | 104 + ...k-for-portal-on-world-gen-entity-add.patch | 19 + ...ze-NetworkManager-Exception-Handling.patch | 96 + ...ix-Concurrency-issue-in-WeightedList.patch | 148 + ...ancement-data-player-iteration-to-be.patch | 54 + ...ix-arrows-never-despawning-MC-125757.patch | 30 + ...-Vanilla-Command-permission-checking.patch | 53 + ...ove-range-check-for-block-placing-up.patch | 35 + .../0531-Fix-SPIGOT-5989.patch | 69 + ...4-Bukkit-world-container-is-not-used.patch | 33 + ...-5885-Unable-to-disable-advancements.patch | 18 + ...ataPlayer-leak-due-from-quitting-ear.patch | 94 + ...keLighting-call-to-World-spigot-stri.patch | 19 + ...Fix-some-rails-connecting-improperly.patch | 95 + ...der-Remove-Streams-Optimized-collect.patch | 134 + .../0538-Incremental-player-saving.patch | 95 + .../0539-Import-fastutil-classes.patch | 27 + ...ull-chunk-sections-for-block-updates.patch | 18 + ...ove-armour-stand-double-add-to-world.patch | 28 + ...-Fix-MC-187716-Use-configured-height.patch | 45 + ...istake-in-CB-NBT-int-deserialization.patch | 27 + ...erver-load-chunks-from-newer-version.patch | 39 + .../server-unmapped/0545-Brand-support.patch | 92 + ...her-Boss-Bar-doesn-t-update-until-in.patch | 22 + .../server-unmapped/0547-Fix-MC-197271.patch | 51 + .../0548-MC-197883-Bandaid-decode-issue.patch | 28 + .../0549-Add-setMaxPlayers-API.patch | 37 + ...yPickupItemAnimation-to-LivingEntity.patch | 21 + .../0551-Don-t-require-FACING-data.patch | 35 + ...geEvent-not-firing-for-all-use-cases.patch | 46 + .../0553-Add-moon-phase-API.patch | 22 + ...-headless-pistons-from-being-created.patch | 74 + .../0555-Add-BellRingEvent.patch | 53 + ...Add-zombie-targets-turtle-egg-config.patch | 33 + .../0557-Buffer-joins-to-world.patch | 71 + .../0558-Optimize-redstone-algorithm.patch | 1158 ++++ ...rs-not-working-in-some-kick-messages.patch | 64 + ...CreateEvent-needs-to-know-its-entity.patch | 135 + .../0561-Fix-CraftTeam-null-check.patch | 19 + .../0562-Add-more-Evoker-API.patch | 57 + ...-translation-keys-for-blocks-entitie.patch | 126 + ...ate-HoverEvent-from-ItemStack-Entity.patch | 51 + .../0565-Cache-block-data-strings.patch | 70 + ...ortation-and-cancel-velocity-if-tele.patch | 83 + ...al-open-container-api-to-HumanEntity.patch | 81 + ...taFixerUpper-Rewrite-Rules-on-demand.patch | 54 + ...p-capture-to-capture-all-items-added.patch | 60 + ...rty-in-invalid-locations-SPIGOT-6086.patch | 18 + ...y-Counter-to-allow-plugins-to-use-va.patch | 37 + ...-track-plugin-scoreboards-by-default.patch | 102 + .../0573-Entity-isTicking.patch | 42 + ...-non-whitelisted-player-when-white-l.patch | 19 + ...Fix-Not-a-string-Map-Conversion-spam.patch | 54 + ...ng-a-passenger-in-CreatureSpawnEvent.patch | 19 + ...tems-that-are-extra-from-a-crafting-.patch | 24 + ...Reset-Ender-Crystals-on-Dragon-Spawn.patch | 24 + ...r-large-move-vectors-crashing-server.patch | 66 + .../0580-Optimise-getType-calls.patch | 96 + .../0581-Villager-resetOffers.patch | 48 + ...inig-for-some-hot-IBlockData-methods.patch | 101 + ...ace-order-when-capturing-blockstates.patch | 24 + ...blockpos-allocation-from-pathfinding.patch | 28 + ...tem-locations-dropped-from-campfires.patch | 32 + .../0586-Player-elytra-boost-API.patch | 46 + ...587-Fixed-TileEntityBell-memory-leak.patch | 56 + ...ling-up-when-item-stack-is-empty-in-.patch | 46 + ...-Add-getOfflinePlayerIfCached-String.patch | 39 + .../0590-Add-ignore-discounts-API.patch | 143 + ...-Toggle-for-removing-existing-dragon.patch | 36 + ...ix-client-lag-on-advancement-loading.patch | 55 + .../0593-Item-no-age-no-player-pickup.patch | 50 + ...0594-Beacon-API-custom-effect-ranges.patch | 90 + .../0595-Add-API-for-quit-reason.patch | 63 + .../0596-Seed-based-feature-search.patch | 115 + ...ing-Trader-spawn-rate-config-options.patch | 120 + ...prove-performance-of-the-end-generat.patch | 77 + .../0599-Expose-world-spawn-angle.patch | 44 + .../0600-Add-Destroy-Speed-API.patch | 35 + ...r-spawnParticle-x-y-z-precision-loss.patch | 19 + ...602-Add-LivingEntity-clearActiveItem.patch | 24 + .../0603-Add-PlayerItemCooldownEvent.patch | 38 + .../0604-More-lightning-API.patch | 68 + ...-should-not-bypass-cramming-gamerule.patch | 179 + ...d-missing-default-perms-for-commands.patch | 70 + .../0607-Add-PlayerShearBlockEvent.patch | 109 + ...g-for-servers-not-running-on-Java-16.patch | 80 + ...erbose-world-setting-to-false-by-def.patch | 19 + ...ing-zombie-villager-discount-exploit.patch | 55 + .../0611-Limit-recipe-packets.patch | 74 + ...x-CraftSound-backwards-compatibility.patch | 21 + .../0613-MC-4-Fix-item-position-desync.patch | 84 + ...0614-Player-Chunk-Load-Unload-Events.patch | 41 + ...15-Optimize-Dynamic-get-Missing-Keys.patch | 34 + ...6-Expose-LivingEntity-hurt-direction.patch | 39 + ...-OBSTRUCTED-reason-to-BedEnterResult.patch | 21 + ...m-invalid-ingredient-lists-in-Villag.patch | 24 + .../0619-added-PlayerTradeEvent.patch | 75 + .../0620-Implement-TargetHitEvent.patch | 49 + ...0621-Additional-Block-Material-API-s.patch | 40 + .../0622-Fix-harming-potion-dupe.patch | 59 + ...-get-Material-from-Boats-and-Minecar.patch | 101 + .../0624-Optimized-tick-ready-check.patch | 51 + .../0625-Cache-burn-durations.patch | 63 + ...mob-spawner-spawn-egg-transformation.patch | 33 + ...ement-PlayerFlowerPotManipulateEvent.patch | 47 + ...-event-not-being-called-in-adventure.patch | 29 + .../0629-Zombie-API-breaking-doors.patch | 44 + ...0630-Fix-nerfed-slime-when-splitting.patch | 18 + .../0631-Add-EntityLoadCrossbowEvent.patch | 48 + .../0632-Guardian-beam-workaround.patch | 30 + .../0633-Added-WorldGameRuleChangeEvent.patch | 108 + ...4-Added-ServerResourcesReloadedEvent.patch | 79 + ...ld-settings-for-mobs-picking-up-loot.patch | 51 + ...Implemented-BlockFailedDispenseEvent.patch | 63 + ...7-Added-PlayerLecternPageChangeEvent.patch | 66 + .../0638-Fire-event-on-GS4-query.patch | 204 + ...9-Added-PlayerLoomPatternSelectEvent.patch | 63 + ...onfigurable-door-breaking-difficulty.patch | 101 + ...pty-commands-shall-not-be-dispatched.patch | 18 + ...PI-to-expose-exact-interaction-point.patch | 59 + .../0643-Remove-stale-POIs.patch | 50 + .../0644-Fix-villager-boat-exploit.patch | 34 + ...645-Entity-load-save-limit-per-chunk.patch | 90 + .../0646-Add-sendOpLevel-API.patch | 51 + .../0647-Add-StructureLocateEvent.patch | 41 + ...n-for-requiring-a-player-participant.patch | 81 + ...ileHitEvent-call-when-fireballs-dead.patch | 21 + ...onent-with-empty-text-instead-of-thr.patch | 33 + ...0651-Make-schedule-command-per-world.patch | 37 + ...0652-Configurable-max-leash-distance.patch | 45 + ...0653-Implement-BlockPreDispenseEvent.patch | 42 + .../0654-Added-Vanilla-Entity-Tags.patch | 94 + .../0655-added-Wither-API.patch | 75 + ...ing-of-PlayerChangeBeaconEffectEvent.patch | 39 + ...e-spam-when-removing-chests-in-water.patch | 19 + ...le-for-always-placing-the-dragon-egg.patch | 33 + ...d-PlayerStonecutterRecipeSelectEvent.patch | 109 + ...Leash-variable-to-EntityUnleashEvent.patch | 156 + ...ce-map-update-when-spawning-disabled.patch | 19 + ...-shield-blocking-on-dimension-change.patch | 22 + .../0663-add-DragonEggFormEvent.patch | 66 + .../0664-EntityMoveEvent.patch | 71 + ...disable-pathfinding-updates-on-block.patch | 40 + .../0666-Inline-shift-direction-fields.patch | 55 + ...w-adding-items-to-BlockDropItemEvent.patch | 44 + ...ainThreadExecutor-to-BukkitScheduler.patch | 26 + ...-entity-allow-attribute-registration.patch | 69 + ...fix-dead-slime-setSize-invincibility.patch | 19 + ...ipes-should-return-an-immutable-list.patch | 19 + .../0672-misc-debugging-dumps.patch | 87 + ...pport-for-hex-color-codes-in-console.patch | 221 + .../0674-Clear-SyncLoadInfo.patch | 40 + .../0675-Expose-Tracked-Players.patch | 53 + ...76-Remove-streams-from-SensorNearest.patch | 120 + ...unnecessary-copies-of-passenger-list.patch | 239 + ...Fix-Wither-hostility-towards-players.patch | 33 + ...per-exception-on-empty-JsonList-file.patch | 18 + .../0680-Improve-ServerGUI.patch | 400 ++ ...sure-plate-EntityInteractEvent-for-i.patch | 19 + ...0682-fix-converting-txt-to-json-file.patch | 74 + .../0683-Add-worldborder-events.patch | 122 + .../0684-added-PlayerNameEntityEvent.patch | 48 + ...-grindstones-from-overstacking-items.patch | 26 + .../0686-Add-recipe-to-cook-events.patch | 44 + .../0687-Add-Block-isValidTool.patch | 20 + ...-using-signs-inside-spawn-protection.patch | 41 + .../0689-Implement-Keyed-on-World.patch | 110 + ...alternative-constructor-for-Vector3f.patch | 30 + .../0691-Item-Rarity-API.patch | 52 + ...Timer-for-Wandering-Traders-spawned-.patch | 58 + ...opy-TESign-isEditable-from-snapshots.patch | 18 + ...ed-item-when-player-has-disconnected.patch | 35 + ...telist-use-configurable-kick-message.patch | 19 + ...-to-remove-correct-TE-during-TE-tick.patch | 45 + ...ignore-result-of-PlayerEditBookEvent.patch | 19 + ...-block-falling-causing-client-desync.patch | 59 + .../0699-Expose-protocol-version.patch | 22 + ...ent-suggestion-tooltips-in-AsyncTabC.patch | 132 + ...tab-completions-for-brigadier-comman.patch | 316 ++ ...ItemConsumeEvent-cancelling-properly.patch | 22 + .../0703-Add-bypass-host-check.patch | 30 + ...don-t-throw-when-loading-invalid-TEs.patch | 33 + .../0705-Set-area-affect-cloud-rotation.patch | 18 + ...-add-isDeeplySleeping-to-HumanEntity.patch | 24 + ...ating-give-items-on-item-drop-cancel.patch | 70 + ...-add-consumeFuel-to-FurnaceBurnEvent.patch | 19 + ...t-set-drop-chance-to-EntityEquipment.patch | 48 + ...fix-PigZombieAngerEvent-cancellation.patch | 47 + ...x-checkReach-check-for-Shulker-boxes.patch | 18 + ...fix-PlayerItemHeldEvent-firing-twice.patch | 30 + .../0713-Added-PlayerDeepSleepEvent.patch | 22 + .../server-unmapped/0714-More-World-API.patch | 146 + .../0715-Added-PlayerBedFailEnterEvent.patch | 57 + ...s-to-convert-between-Component-and-B.patch | 55 + ...wn-acting-as-a-bed-respawn-from-the-.patch | 36 + ...d-RespawnFlags-to-PlayerRespawnEvent.patch | 46 + ...eacon-activation-deactivation-events.patch | 37 + ...Add-Channel-initialization-listeners.patch | 119 + ...mmands-if-tab-completion-is-disabled.patch | 24 + .../0722-Add-more-WanderingTrader-API.patch | 65 + ...Add-EntityBlockStorage-clearEntities.patch | 37 + ...essage-to-PlayerAdvancementDoneEvent.patch | 89 + ...-address-to-AsyncPlayerPreLoginEvent.patch | 25 + .../0726-Inventory-close.patch | 25 + ...CreateEvent-players-and-end-platform.patch | 45 + ...n-in-sunlight-API-for-Phantoms-and-S.patch | 126 + .../0729-Fix-CraftPotionBrewer-cache.patch | 44 + .../0730-Add-basic-Datapack-API.patch | 175 + ...nment-variable-to-disable-server-gui.patch | 18 + ...ditions-to-PlayerGameModeChangeEvent.patch | 128 + .../0733-ItemStack-repair-check-API.patch | 91 + .../0734-More-Enchantment-API.patch | 202 + ...-option-to-load-extra-plugin-jars-no.patch | 64 + ...atus-dataconverter-for-pre-1.13-chun.patch | 91 + ...crease-structure-block-data-length-t.patch | 19 + ...x-and-optimise-world-force-upgrading.patch | 411 ++ .../0739-Add-Mob-lookAt-API.patch | 127 + .../0740-Add-Unix-domain-socket-support.patch | 141 + .../0741-Add-EntityInsideBlockEvent.patch | 222 + ...742-Attributes-API-for-item-defaults.patch | 42 + ...chantCustom-emit-PlayerPurchaseEvent.patch | 59 + ...cause-to-Weather-ThunderChangeEvents.patch | 118 + .../0745-More-Lidded-Block-API.patch | 127 + .../0746-Add-PlayerKickEvent-causes.patch | 393 ++ ...747-Limit-item-frame-cursors-on-maps.patch | 37 + .../0748-Add-PufferFishStateChangeEvent.patch | 50 + ...yerBucketEmptyEvent-result-itemstack.patch | 43 + ...n-to-fix-items-merging-through-walls.patch | 39 + .../0751-Add-BellRevealRaiderEvent.patch | 26 + .../0752-Fix-invulnerable-end-crystals.patch | 88 + ...753-Add-ElderGuardianAppearanceEvent.patch | 23 + ...-inventory-on-cancelled-pickup-event.patch | 62 + .../0755-Fix-dangerous-end-portal-logic.patch | 99 + ...6-Make-item-validations-configurable.patch | 83 + .../0757-Add-more-line-of-sight-methods.patch | 62 + .../0758-add-per-world-spawn-limits.patch | 49 + ...SplashEvent-for-water-splash-potions.patch | 63 + .../server/0001-Setup-Gradle-project.patch | 95 + patches/server/0002-Decompile-fixes.patch | 77 + 1895 files changed, 212111 insertions(+) create mode 100644 patches/api-unmapped/0001-POM-changes.patch create mode 100644 patches/api-unmapped/0002-Add-FastUtil-to-Bukkit.patch create mode 100644 patches/api-unmapped/0003-Paper-Utils.patch create mode 100644 patches/api-unmapped/0004-Timings-v2.patch create mode 100644 patches/api-unmapped/0005-Adventure.patch create mode 100644 patches/api-unmapped/0006-Player-affects-spawning-API.patch create mode 100644 patches/api-unmapped/0007-Add-getTPS-method.patch create mode 100644 patches/api-unmapped/0008-Entity-Origin-API.patch create mode 100644 patches/api-unmapped/0009-Version-Command-2.0.patch create mode 100644 patches/api-unmapped/0010-Add-PlayerLocaleChangeEvent.patch create mode 100644 patches/api-unmapped/0011-Add-player-view-distance-API.patch create mode 100644 patches/api-unmapped/0012-Add-BeaconEffectEvent.patch create mode 100644 patches/api-unmapped/0013-Add-PlayerInitialSpawnEvent.patch create mode 100644 patches/api-unmapped/0014-Automatically-disable-plugins-that-fail-to-load.patch create mode 100644 patches/api-unmapped/0015-Expose-server-CommandMap.patch create mode 100644 patches/api-unmapped/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch create mode 100644 patches/api-unmapped/0017-Player-Tab-List-and-Title-APIs.patch create mode 100644 patches/api-unmapped/0018-Add-exception-reporting-event.patch create mode 100644 patches/api-unmapped/0019-Fix-ServerListPingEvent-flagging-as-Async.patch create mode 100644 patches/api-unmapped/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch create mode 100644 patches/api-unmapped/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch create mode 100644 patches/api-unmapped/0022-Complete-resource-pack-API.patch create mode 100644 patches/api-unmapped/0023-Use-ASM-for-event-executors.patch create mode 100644 patches/api-unmapped/0024-Add-a-call-helper-to-Event.patch create mode 100644 patches/api-unmapped/0025-Add-sender-name-to-commands.yml-replacement.patch create mode 100644 patches/api-unmapped/0026-Add-command-to-reload-permissions.yml-and-require-co.patch create mode 100644 patches/api-unmapped/0027-Custom-replacement-for-eaten-items.patch create mode 100644 patches/api-unmapped/0028-Entity-AddTo-RemoveFrom-World-Events.patch create mode 100644 patches/api-unmapped/0029-EntityPathfindEvent.patch create mode 100644 patches/api-unmapped/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch create mode 100644 patches/api-unmapped/0031-Add-MetadataStoreBase.removeAll-Plugin.patch create mode 100644 patches/api-unmapped/0032-Add-PlayerUseUnknownEntityEvent.patch create mode 100644 patches/api-unmapped/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch create mode 100644 patches/api-unmapped/0034-Arrow-pickup-rule-API.patch create mode 100644 patches/api-unmapped/0035-EntityRegainHealthEvent-isFastRegen-API.patch create mode 100644 patches/api-unmapped/0036-LootTable-API.patch create mode 100644 patches/api-unmapped/0037-Add-EntityZapEvent.patch create mode 100644 patches/api-unmapped/0038-Misc-Utils.patch create mode 100644 patches/api-unmapped/0039-Allow-Reloading-of-Command-Aliases.patch create mode 100644 patches/api-unmapped/0040-Add-source-to-PlayerExpChangeEvent.patch create mode 100644 patches/api-unmapped/0041-Add-ProjectileCollideEvent.patch create mode 100644 patches/api-unmapped/0042-Add-String-based-Action-Bar-API.patch create mode 100644 patches/api-unmapped/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch create mode 100644 patches/api-unmapped/0044-IllegalPacketEvent.patch create mode 100644 patches/api-unmapped/0045-Fireworks-API-s.patch create mode 100644 patches/api-unmapped/0046-PlayerTeleportEndGatewayEvent.patch create mode 100644 patches/api-unmapped/0047-Provide-E-TE-Chunk-count-stat-methods.patch create mode 100644 patches/api-unmapped/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch create mode 100644 patches/api-unmapped/0049-Expose-WorldBorder-isInBounds-Location-check.patch create mode 100644 patches/api-unmapped/0050-Add-configuration-option-to-prevent-player-names-fro.patch create mode 100644 patches/api-unmapped/0051-Fix-upstream-javadoc-warnings-and-errors.patch create mode 100644 patches/api-unmapped/0052-Item-canEntityPickup.patch create mode 100644 patches/api-unmapped/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch create mode 100644 patches/api-unmapped/0054-PlayerAttemptPickupItemEvent.patch create mode 100644 patches/api-unmapped/0055-Add-UnknownCommandEvent.patch create mode 100644 patches/api-unmapped/0056-Basic-PlayerProfile-API.patch create mode 100644 patches/api-unmapped/0057-Shoulder-Entities-Release-API.patch create mode 100644 patches/api-unmapped/0058-Profile-Lookup-Events.patch create mode 100644 patches/api-unmapped/0059-Entity-fromMobSpawner.patch create mode 100644 patches/api-unmapped/0060-Improve-the-Saddle-API-for-Horses.patch create mode 100644 patches/api-unmapped/0061-ensureServerConversions-API.patch create mode 100644 patches/api-unmapped/0062-Add-getI18NDisplayName-API.patch create mode 100644 patches/api-unmapped/0063-ProfileWhitelistVerifyEvent.patch create mode 100644 patches/api-unmapped/0064-Make-plugins-list-alphabetical.patch create mode 100644 patches/api-unmapped/0065-LivingEntity-setKiller.patch create mode 100644 patches/api-unmapped/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch create mode 100644 patches/api-unmapped/0067-Allow-plugins-to-use-SLF4J-for-logging.patch create mode 100644 patches/api-unmapped/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch create mode 100644 patches/api-unmapped/0069-Add-PlayerJumpEvent.patch create mode 100644 patches/api-unmapped/0070-Expose-client-protocol-version-and-virtual-host.patch create mode 100644 patches/api-unmapped/0071-Add-PlayerArmorChangeEvent.patch create mode 100644 patches/api-unmapped/0072-API-to-get-a-BlockState-without-a-snapshot.patch create mode 100644 patches/api-unmapped/0073-AsyncTabCompleteEvent.patch create mode 100644 patches/api-unmapped/0074-Display-warning-on-deprecated-recipe-API.patch create mode 100644 patches/api-unmapped/0075-PlayerPickupExperienceEvent.patch create mode 100644 patches/api-unmapped/0076-ExperienceOrbMergeEvent.patch create mode 100644 patches/api-unmapped/0077-Ability-to-apply-mending-to-XP-API.patch create mode 100644 patches/api-unmapped/0078-PreCreatureSpawnEvent.patch create mode 100644 patches/api-unmapped/0079-PlayerNaturallySpawnCreaturesEvent.patch create mode 100644 patches/api-unmapped/0080-Add-setPlayerProfile-API-for-Skulls.patch create mode 100644 patches/api-unmapped/0081-Fill-Profile-Property-Events.patch create mode 100644 patches/api-unmapped/0082-PlayerAdvancementCriterionGrantEvent.patch create mode 100644 patches/api-unmapped/0083-Add-ArmorStand-Item-Meta.patch create mode 100644 patches/api-unmapped/0084-Optimize-Hoppers.patch create mode 100644 patches/api-unmapped/0085-Tameable-getOwnerUniqueId-API.patch create mode 100644 patches/api-unmapped/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch create mode 100644 patches/api-unmapped/0087-Add-extended-PaperServerListPingEvent.patch create mode 100644 patches/api-unmapped/0088-Player.setPlayerProfile-API.patch create mode 100644 patches/api-unmapped/0089-getPlayerUniqueId-API.patch create mode 100644 patches/api-unmapped/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch create mode 100644 patches/api-unmapped/0091-Add-method-to-open-already-placed-sign.patch create mode 100644 patches/api-unmapped/0092-Add-Ban-Methods-to-Player-Objects.patch create mode 100644 patches/api-unmapped/0093-EndermanEscapeEvent.patch create mode 100644 patches/api-unmapped/0094-Enderman.teleportRandomly.patch create mode 100644 patches/api-unmapped/0095-Additional-world.getNearbyEntities-API-s.patch create mode 100644 patches/api-unmapped/0096-Location.isChunkLoaded-API.patch create mode 100644 patches/api-unmapped/0097-Expand-World.spawnParticle-API-and-add-Builder.patch create mode 100644 patches/api-unmapped/0098-EndermanAttackPlayerEvent.patch create mode 100644 patches/api-unmapped/0099-Close-Plugin-Class-Loaders-on-Disable.patch create mode 100644 patches/api-unmapped/0100-WitchConsumePotionEvent.patch create mode 100644 patches/api-unmapped/0101-WitchThrowPotionEvent.patch create mode 100644 patches/api-unmapped/0102-Location.toBlockLocation-toCenterLocation.patch create mode 100644 patches/api-unmapped/0103-PotionEffect-clone-methods.patch create mode 100644 patches/api-unmapped/0104-WitchReadyPotionEvent.patch create mode 100644 patches/api-unmapped/0105-ItemStack-getMaxItemUseDuration.patch create mode 100644 patches/api-unmapped/0106-Add-EntityTeleportEndGatewayEvent.patch create mode 100644 patches/api-unmapped/0107-Make-shield-blocking-delay-configurable.patch create mode 100644 patches/api-unmapped/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch create mode 100644 patches/api-unmapped/0109-Add-getNearbyXXX-methods-to-Location.patch create mode 100644 patches/api-unmapped/0110-PlayerReadyArrowEvent.patch create mode 100644 patches/api-unmapped/0111-Add-EntityKnockbackByEntityEvent.patch create mode 100644 patches/api-unmapped/0112-Expand-Explosions-API.patch create mode 100644 patches/api-unmapped/0113-ItemStack-API-additions-for-quantity-flags-lore.patch create mode 100644 patches/api-unmapped/0114-LivingEntity-Hand-Raised-Item-Use-API.patch create mode 100644 patches/api-unmapped/0115-RangedEntity-API.patch create mode 100644 patches/api-unmapped/0116-Add-World.getEntity-UUID-API.patch create mode 100644 patches/api-unmapped/0117-InventoryCloseEvent-Reason-API.patch create mode 100644 patches/api-unmapped/0118-Entity-getChunk-API.patch create mode 100644 patches/api-unmapped/0119-Add-an-asterisk-to-legacy-API-plugins.patch create mode 100644 patches/api-unmapped/0120-EnderDragon-Events.patch create mode 100644 patches/api-unmapped/0121-PlayerLaunchProjectileEvent.patch create mode 100644 patches/api-unmapped/0122-PlayerElytraBoostEvent.patch create mode 100644 patches/api-unmapped/0123-EntityTransformedEvent.patch create mode 100644 patches/api-unmapped/0124-Allow-disabling-armour-stand-ticking.patch create mode 100644 patches/api-unmapped/0125-SkeletonHorse-Additions.patch create mode 100644 patches/api-unmapped/0126-Expand-Location-Manipulation-API.patch create mode 100644 patches/api-unmapped/0127-Expand-ArmorStand-API.patch create mode 100644 patches/api-unmapped/0128-AnvilDamageEvent.patch create mode 100644 patches/api-unmapped/0129-Remove-deadlock-risk-in-firing-async-events.patch create mode 100644 patches/api-unmapped/0130-Add-hand-to-bucket-events.patch create mode 100644 patches/api-unmapped/0131-Add-TNTPrimeEvent.patch create mode 100644 patches/api-unmapped/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch create mode 100644 patches/api-unmapped/0133-Async-Chunks-API.patch create mode 100644 patches/api-unmapped/0134-Make-EnderDragon-extend-Mob.patch create mode 100644 patches/api-unmapped/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch create mode 100644 patches/api-unmapped/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch create mode 100644 patches/api-unmapped/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch create mode 100644 patches/api-unmapped/0138-Slime-Pathfinder-Events.patch create mode 100644 patches/api-unmapped/0139-isChunkGenerated-API.patch create mode 100644 patches/api-unmapped/0140-Add-More-Creeper-API.patch create mode 100644 patches/api-unmapped/0141-Add-PhantomPreSpawnEvent.patch create mode 100644 patches/api-unmapped/0142-Add-source-block-to-BlockPhysicsEvent.patch create mode 100644 patches/api-unmapped/0143-Inventory-removeItemAnySlot.patch create mode 100644 patches/api-unmapped/0144-Add-ray-tracing-methods-to-LivingEntity.patch create mode 100644 patches/api-unmapped/0145-Improve-death-events.patch create mode 100644 patches/api-unmapped/0146-Mob-Pathfinding-API.patch create mode 100644 patches/api-unmapped/0147-Expose-attack-cooldown-methods-for-Player.patch create mode 100644 patches/api-unmapped/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch create mode 100644 patches/api-unmapped/0149-Performance-Concurrency-Improvements-to-Permissions.patch create mode 100644 patches/api-unmapped/0150-Add-ItemStackRecipeChoice-Draft-API.patch create mode 100644 patches/api-unmapped/0151-Implement-furnace-cook-speed-multiplier-API.patch create mode 100644 patches/api-unmapped/0152-PreSpawnerSpawnEvent.patch create mode 100644 patches/api-unmapped/0153-Material-API-additions.patch create mode 100644 patches/api-unmapped/0154-Add-Material-Tags.patch create mode 100644 patches/api-unmapped/0155-Allow-setting-the-vex-s-summoner.patch create mode 100644 patches/api-unmapped/0156-Add-LivingEntity-getTargetEntity.patch create mode 100644 patches/api-unmapped/0157-Add-sun-related-API.patch create mode 100644 patches/api-unmapped/0158-Here-s-Johnny.patch create mode 100644 patches/api-unmapped/0159-Turtle-API.patch create mode 100644 patches/api-unmapped/0160-Add-spectator-target-events.patch create mode 100644 patches/api-unmapped/0161-Add-more-Witch-API.patch create mode 100644 patches/api-unmapped/0162-Make-the-default-permission-message-configurable.patch create mode 100644 patches/api-unmapped/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch create mode 100644 patches/api-unmapped/0164-Add-more-Zombie-API.patch create mode 100644 patches/api-unmapped/0165-Change-the-reserved-channel-check-to-be-sensible.patch create mode 100644 patches/api-unmapped/0166-Add-PlayerConnectionCloseEvent.patch create mode 100644 patches/api-unmapped/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch create mode 100644 patches/api-unmapped/0168-BlockDestroyEvent.patch create mode 100644 patches/api-unmapped/0169-Add-ItemStack-Recipe-API-helper-methods.patch create mode 100644 patches/api-unmapped/0170-Add-WhitelistToggleEvent.patch create mode 100644 patches/api-unmapped/0171-Annotation-Test-changes.patch create mode 100644 patches/api-unmapped/0172-Entity-getEntitySpawnReason.patch create mode 100644 patches/api-unmapped/0173-Add-GS4-Query-event.patch create mode 100644 patches/api-unmapped/0174-Add-PlayerPostRespawnEvent.patch create mode 100644 patches/api-unmapped/0175-Ignore-package-private-methods-for-nullability-annot.patch create mode 100644 patches/api-unmapped/0176-Flip-some-Spigot-API-null-annotations.patch create mode 100644 patches/api-unmapped/0177-Server-Tick-Events.patch create mode 100644 patches/api-unmapped/0178-PlayerDeathEvent-getItemsToKeep.patch create mode 100644 patches/api-unmapped/0179-Add-Heightmap-API.patch create mode 100644 patches/api-unmapped/0180-Mob-Spawner-API-Enhancements.patch create mode 100644 patches/api-unmapped/0181-Add-BlockSoundGroup-interface.patch create mode 100644 patches/api-unmapped/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch create mode 100644 patches/api-unmapped/0183-Increase-custom-payload-channel-message-size.patch create mode 100644 patches/api-unmapped/0184-Expose-the-internal-current-tick.patch create mode 100644 patches/api-unmapped/0185-PlayerDeathEvent-shouldDropExperience.patch create mode 100644 patches/api-unmapped/0186-Add-effect-to-block-break-naturally.patch create mode 100644 patches/api-unmapped/0187-Add-ThrownEggHatchEvent.patch create mode 100644 patches/api-unmapped/0188-Entity-Jump-API.patch create mode 100644 patches/api-unmapped/0189-add-hand-to-BlockMultiPlaceEvent.patch create mode 100644 patches/api-unmapped/0190-Add-tick-times-API.patch create mode 100644 patches/api-unmapped/0191-Expose-MinecraftServer-isRunning.patch create mode 100644 patches/api-unmapped/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch create mode 100644 patches/api-unmapped/0193-Make-JavaPluginLoader-thread-safe.patch create mode 100644 patches/api-unmapped/0194-Add-Player-Client-Options-API.patch create mode 100644 patches/api-unmapped/0195-Add-PlayerAttackEntityCooldownResetEvent.patch create mode 100644 patches/api-unmapped/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch create mode 100644 patches/api-unmapped/0197-Villager-Restocks-API.patch create mode 100644 patches/api-unmapped/0198-Expose-game-version.patch create mode 100644 patches/api-unmapped/0199-Add-item-slot-convenience-methods.patch create mode 100644 patches/api-unmapped/0200-Add-Mob-Goal-API.patch create mode 100644 patches/api-unmapped/0201-World-view-distance-api.patch create mode 100644 patches/api-unmapped/0202-Add-villager-reputation-API.patch create mode 100644 patches/api-unmapped/0203-Spawn-Reason-API.patch create mode 100644 patches/api-unmapped/0204-Potential-bed-API.patch create mode 100644 patches/api-unmapped/0205-Prioritise-own-classes-where-possible.patch create mode 100644 patches/api-unmapped/0206-Add-Raw-Byte-ItemStack-Serialization.patch create mode 100644 patches/api-unmapped/0207-Provide-a-useful-PluginClassLoader-toString.patch create mode 100644 patches/api-unmapped/0208-Inventory-getHolder-method-without-block-snapshot.patch create mode 100644 patches/api-unmapped/0209-Expose-Arrow-getItemStack.patch create mode 100644 patches/api-unmapped/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch create mode 100644 patches/api-unmapped/0211-Support-components-in-ItemMeta.patch create mode 100644 patches/api-unmapped/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch create mode 100644 patches/api-unmapped/0213-Add-entity-liquid-API.patch create mode 100644 patches/api-unmapped/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch create mode 100644 patches/api-unmapped/0215-Allow-delegation-to-vanilla-chunk-gen.patch create mode 100644 patches/api-unmapped/0216-Support-hex-colors-in-getLastColors.patch create mode 100644 patches/api-unmapped/0217-Add-setMaxPlayers-API.patch create mode 100644 patches/api-unmapped/0218-Add-moon-phase-API.patch create mode 100644 patches/api-unmapped/0219-Add-playPickupItemAnimation-to-LivingEntity.patch create mode 100644 patches/api-unmapped/0220-Add-BellRingEvent.patch create mode 100644 patches/api-unmapped/0221-Brand-support.patch create mode 100644 patches/api-unmapped/0222-Add-more-Evoker-API.patch create mode 100644 patches/api-unmapped/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch create mode 100644 patches/api-unmapped/0224-Create-HoverEvent-from-ItemStack-Entity.patch create mode 100644 patches/api-unmapped/0225-Add-additional-open-container-api-to-HumanEntity.patch create mode 100644 patches/api-unmapped/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch create mode 100644 patches/api-unmapped/0227-Entity-isTicking.patch create mode 100644 patches/api-unmapped/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch create mode 100644 patches/api-unmapped/0229-Villager-resetOffers.patch create mode 100644 patches/api-unmapped/0230-Player-elytra-boost-API.patch create mode 100644 patches/api-unmapped/0231-Add-getOfflinePlayerIfCached-String.patch create mode 100644 patches/api-unmapped/0232-Add-ignore-discounts-API.patch create mode 100644 patches/api-unmapped/0233-Item-no-age-no-player-pickup.patch create mode 100644 patches/api-unmapped/0234-Beacon-API-custom-effect-ranges.patch create mode 100644 patches/api-unmapped/0235-Add-API-for-quit-reason.patch create mode 100644 patches/api-unmapped/0236-Add-Destroy-Speed-API.patch create mode 100644 patches/api-unmapped/0237-Add-LivingEntity-clearActiveItem.patch create mode 100644 patches/api-unmapped/0238-Add-PlayerItemCooldownEvent.patch create mode 100644 patches/api-unmapped/0239-More-lightning-API.patch create mode 100644 patches/api-unmapped/0240-Add-PlayerShearBlockEvent.patch create mode 100644 patches/api-unmapped/0241-Enable-multi-release-plugin-jars.patch create mode 100644 patches/api-unmapped/0242-Player-Chunk-Load-Unload-Events.patch create mode 100644 patches/api-unmapped/0243-Expose-LivingEntity-hurt-direction.patch create mode 100644 patches/api-unmapped/0244-Added-PlayerTradeEvent.patch create mode 100644 patches/api-unmapped/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch create mode 100644 patches/api-unmapped/0246-Add-TargetHitEvent-API.patch create mode 100644 patches/api-unmapped/0247-Additional-Block-Material-API-s.patch create mode 100644 patches/api-unmapped/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch create mode 100644 patches/api-unmapped/0249-Add-PlayerFlowerPotManipulateEvent.patch create mode 100644 patches/api-unmapped/0250-Zombie-API-breaking-doors.patch create mode 100644 patches/api-unmapped/0251-Add-EntityLoadCrossbowEvent.patch create mode 100644 patches/api-unmapped/0252-Added-WorldGameRuleChangeEvent.patch create mode 100644 patches/api-unmapped/0253-Added-ServerResourcesReloadedEvent.patch create mode 100644 patches/api-unmapped/0254-Add-BlockFailedDispenseEvent.patch create mode 100644 patches/api-unmapped/0255-Added-PlayerLecternPageChangeEvent.patch create mode 100644 patches/api-unmapped/0256-Added-PlayerLoomPatternSelectEvent.patch create mode 100644 patches/api-unmapped/0257-Better-AnnotationTest-printout.patch create mode 100644 patches/api-unmapped/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch create mode 100644 patches/api-unmapped/0259-Add-sendOpLevel-API.patch create mode 100644 patches/api-unmapped/0260-Add-StructureLocateEvent.patch create mode 100644 patches/api-unmapped/0261-Return-chat-component-with-empty-text-instead-of-thr.patch create mode 100644 patches/api-unmapped/0262-Add-BlockPreDispenseEvent.patch create mode 100644 patches/api-unmapped/0263-Added-Vanilla-Entity-Tags.patch create mode 100644 patches/api-unmapped/0264-added-Wither-API.patch create mode 100644 patches/api-unmapped/0265-Added-PlayerChangeBeaconEffectEvent.patch create mode 100644 patches/api-unmapped/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch create mode 100644 patches/api-unmapped/0267-Added-PlayerStonecutterRecipeSelectEvent.patch create mode 100644 patches/api-unmapped/0268-EntityMoveEvent.patch create mode 100644 patches/api-unmapped/0269-add-DragonEggFormEvent.patch create mode 100644 patches/api-unmapped/0270-Allow-adding-items-to-BlockDropItemEvent.patch create mode 100644 patches/api-unmapped/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch create mode 100644 patches/api-unmapped/0272-living-entity-allow-attribute-registration.patch create mode 100644 patches/api-unmapped/0273-Add-missing-effects.patch create mode 100644 patches/api-unmapped/0274-Expose-Tracked-Players.patch create mode 100644 patches/api-unmapped/0275-Cache-the-result-of-Material-isBlock.patch create mode 100644 patches/api-unmapped/0276-Add-worldborder-events.patch create mode 100644 patches/api-unmapped/0277-added-PlayerNameEntityEvent.patch create mode 100644 patches/api-unmapped/0278-Add-recipe-to-cook-events.patch create mode 100644 patches/api-unmapped/0279-Add-Block-isValidTool.patch create mode 100644 patches/api-unmapped/0280-Implement-Keyed-on-World.patch create mode 100644 patches/api-unmapped/0281-fix-Inventory-getContents-null-annotations.patch create mode 100644 patches/api-unmapped/0282-Item-Rarity-API.patch create mode 100644 patches/api-unmapped/0283-Expose-protocol-version.patch create mode 100644 patches/api-unmapped/0284-add-isDeeplySleeping-to-HumanEntity.patch create mode 100644 patches/api-unmapped/0285-add-consumeFuel-to-FurnaceBurnEvent.patch create mode 100644 patches/api-unmapped/0286-add-get-set-drop-chance-to-EntityEquipment.patch create mode 100644 patches/api-unmapped/0287-Added-PlayerDeepSleepEvent.patch create mode 100644 patches/api-unmapped/0288-More-World-API.patch create mode 100644 patches/api-unmapped/0289-Added-PlayerBedFailEnterEvent.patch create mode 100644 patches/api-unmapped/0290-Introduce-beacon-activation-deactivation-events.patch create mode 100644 patches/api-unmapped/0291-PlayerMoveEvent-Improvements.patch create mode 100644 patches/api-unmapped/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch create mode 100644 patches/api-unmapped/0293-Add-more-WanderingTrader-API.patch create mode 100644 patches/api-unmapped/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch create mode 100644 patches/api-unmapped/0295-Add-EntityBlockStorage-clearEntities.patch create mode 100644 patches/api-unmapped/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch create mode 100644 patches/api-unmapped/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch create mode 100644 patches/api-unmapped/0298-Inventory-close.patch create mode 100644 patches/api-unmapped/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch create mode 100644 patches/api-unmapped/0300-Add-basic-Datapack-API.patch create mode 100644 patches/api-unmapped/0301-additions-to-PlayerGameModeChangeEvent.patch create mode 100644 patches/api-unmapped/0302-ItemStack-repair-check-API.patch create mode 100644 patches/api-unmapped/0303-More-Enchantment-API.patch create mode 100644 patches/api-unmapped/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch create mode 100644 patches/api-unmapped/0305-List-all-missing-hard-depends-not-just-first.patch create mode 100644 patches/api-unmapped/0306-Add-Mob-lookAt-API.patch create mode 100644 patches/api-unmapped/0307-ItemStack-editMeta.patch create mode 100644 patches/api-unmapped/0308-Add-EntityInsideBlockEvent.patch create mode 100644 patches/api-unmapped/0309-Attributes-API-for-item-defaults.patch create mode 100644 patches/api-unmapped/0310-Add-cause-to-Weather-ThunderChangeEvents.patch create mode 100644 patches/api-unmapped/0311-More-Lidded-Block-API.patch create mode 100644 patches/api-unmapped/0312-Add-PlayerKickEvent-causes.patch create mode 100644 patches/api-unmapped/0313-Add-PufferFishStateChangeEvent.patch create mode 100644 patches/api-unmapped/0314-Add-BellRevealRaiderEvent.patch create mode 100644 patches/api-unmapped/0315-Add-ElderGuardianAppearanceEvent.patch create mode 100644 patches/api-unmapped/0316-Add-more-line-of-sight-methods.patch create mode 100644 patches/api/0001-Convert-project-to-Gradle.patch rename {removed => patches/removed}/0017-Configurable-speed-for-water-flowing-over-lava.patch (100%) rename {removed => patches/removed}/0033-Generator-Settings.patch (100%) rename {removed => patches/removed}/0035-Stop-updating-flowing-block-if-material-has-changed.patch (100%) rename {removed => patches/removed}/0036-Fast-draining.patch (100%) rename {removed => patches/removed}/0037-Send-absolute-position-the-first-time-an-entity-is-s.patch (100%) rename {removed => patches/removed}/0097-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch (100%) rename {removed => patches/removed}/0115-Water-mobs-should-only-spawn-in-the-water.patch (100%) rename {removed => patches/removed}/0123-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch (100%) rename {removed => patches/removed}/0280-Configurable-Unrestricted-Signs.patch (100%) rename {removed => patches/removed}/0532-Unload-leaked-Cached-Chunks.patch (100%) rename {removed => patches/removed}/1.14/0032-Add-player-view-distance-API.patch (100%) rename {removed => patches/removed}/1.14/0061-Chunk-save-queue-improvements.patch (100%) rename {removed => patches/removed}/1.14/0070-Optimized-Light-Level-Comparisons.patch (100%) rename {removed => patches/removed}/1.14/0071-Pass-world-to-Village-creation.patch (100%) rename {removed => patches/removed}/1.14/0078-Optimize-Chunk-Access.patch (100%) rename {removed => patches/removed}/1.14/0096-Don-t-spam-reload-spawn-chunks-in-nether-end.patch (100%) rename {removed => patches/removed}/1.14/0112-Entity-Tracking-Improvements.patch (100%) rename {removed => patches/removed}/1.14/0120-Ensure-Chunks-never-ever-load-async.patch (100%) rename {removed => patches/removed}/1.14/0123-Delay-Chunk-Unloads-based-on-Player-Movement.patch (100%) rename {removed => patches/removed}/1.14/0142-Prevent-Auto-Save-if-Save-Queue-is-full.patch (100%) rename {removed => patches/removed}/1.14/0143-Chunk-Save-Stats-Debug-Option.patch (100%) rename {removed => patches/removed}/1.14/0144-Fix-block-break-desync.patch (100%) rename {removed => patches/removed}/1.14/0161-ShulkerBox-Dupe-Prevention.patch (100%) rename {removed => patches/removed}/1.14/0258-Configurable-Villages-loading-chunks-for-door-checks.patch (100%) rename {removed => patches/removed}/1.14/0263-Properly-remove-entities-on-dimension-teleport.patch (100%) rename {removed => patches/removed}/1.14/0285-Don-t-process-despawn-if-entity-is-in-a-chunk-schedu.patch (100%) rename {removed => patches/removed}/1.14/0341-Optimize-getChunkIfLoaded-type-calls.patch (100%) rename {removed => patches/removed}/1.14/0361-Async-Chunk-Loading-and-Generation.patch (100%) rename {removed => patches/removed}/1.14/0363-Optimize-Light-Recalculations.patch (100%) rename {removed => patches/removed}/1.14/0366-Fix-Sending-Chunks-to-Client.patch (100%) rename {removed => patches/removed}/1.14/0368-Fix-FileIOThread-concurrency-issues.patch (100%) rename {removed => patches/removed}/1.14/0377-Optimize-Persistent-Data-Loading.patch (100%) rename {removed => patches/removed}/1.14/0388-Use-EntityTypes-for-living-entities.patch (100%) rename {removed => patches/removed}/1.14/0400-limit-the-range-at-which-we-ll-consider-an-attackabl.patch (100%) rename {removed => patches/removed}/1.15/0078-Reduce-IO-ops-opening-a-new-region-file.patch (100%) rename {removed => patches/removed}/1.15/0081-Do-not-load-chunks-for-light-checks.patch (100%) rename {removed => patches/removed}/1.15/0269-Provide-option-to-use-a-versioned-world-folder-for-t.patch (100%) rename {removed => patches/removed}/1.15/0280-Detect-and-repair-corrupt-Region-Files.patch (100%) rename {removed => patches/removed}/1.15/0376-Handle-bad-chunks-more-gracefully.patch (100%) rename {removed => patches/removed}/1.15/0403-Preserve-old-flush-on-save-flag-for-reliable-regionf.patch (100%) rename {removed => patches/removed}/1.15/0412-Improve-POI-data-saving-logic.patch (100%) rename {removed => patches/removed}/1.15/0417-Avoid-Chunk-Lookups-for-Entity-TileEntity-Current-Ch.patch (100%) rename {removed => patches/removed}/1.16/0238-Configurable-Bed-Search-Radius.patch (100%) rename {removed => patches/removed}/1.16/0298-Support-Overriding-World-Seeds.patch (100%) rename {removed => patches/removed}/1.16/0511-Implement-JellySquid-s-Entity-Collision-optimisation.patch (100%) rename {removed => patches/removed}/1.16/0512-Remove-some-Streams-usage-in-Entity-Collision.patch (100%) rename {removed => patches/removed}/1.16/0530-Optimize-Villagers.patch (100%) rename {removed => patches/removed}/1.16/No longer Needed/0276-Send-nearby-packets-from-world-player-list-not-serve.patch (100%) rename {removed => patches/removed}/1.16/No longer Needed/0302-Avoid-dimension-id-collisions.patch (100%) rename {removed => patches/removed}/1.16/No longer Needed/0316-Fix-MC-93764.patch (100%) rename {removed => patches/removed}/1.16/No longer Needed/0373-Fix-some-generation-concurrency-issues.patch (100%) rename {removed => patches/removed}/1.16/No longer Needed/0401-Fix-zero-tick-instant-grow-farms-MC-113809.patch (100%) rename {removed => patches/removed}/1.16/No longer Needed/0412-Fix-spawn-radius-being-treated-as-0.patch (100%) rename {removed => patches/removed}/1.16/No longer Needed/0429-Seed-based-feature-search.patch (100%) rename {removed => patches/removed}/1.16/No longer Needed/0468-Port-20w15a-Villager-AI-optimizations-DROP-1.16.patch (100%) rename {removed => patches/removed}/1.17/0049-Player-Tab-List-and-Title-APIs.patch (100%) rename {removed => patches/removed}/Scheduler-decompile-fixes.patch (100%) create mode 100644 patches/server-remapped/0001-POM-Changes.patch create mode 100644 patches/server-remapped/0002-Paper-config-files.patch create mode 100644 patches/server-remapped/0003-MC-Dev-fixes.patch create mode 100644 patches/server-remapped/0004-MC-Utils.patch create mode 100644 patches/server-remapped/0005-Paper-Metrics.patch create mode 100644 patches/server-remapped/0006-Add-MinecraftKey-Information-to-Objects.patch create mode 100644 patches/server-remapped/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch create mode 100644 patches/server-remapped/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch create mode 100644 patches/server-remapped/0009-Timings-v2.patch create mode 100644 patches/server-remapped/0010-Adventure.patch create mode 100644 patches/server-remapped/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch create mode 100644 patches/server-remapped/0012-Configurable-baby-zombie-movement-speed.patch create mode 100644 patches/server-remapped/0013-Configurable-fishing-time-ranges.patch create mode 100644 patches/server-remapped/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch create mode 100644 patches/server-remapped/0015-Add-configurable-despawn-distances-for-living-entiti.patch create mode 100644 patches/server-remapped/0016-Allow-for-toggling-of-spawn-chunks.patch create mode 100644 patches/server-remapped/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch create mode 100644 patches/server-remapped/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch create mode 100644 patches/server-remapped/0019-Implement-Paper-VersionChecker.patch create mode 100644 patches/server-remapped/0020-Add-version-history-to-version-command.patch create mode 100644 patches/server-remapped/0021-Player-affects-spawning-API.patch create mode 100644 patches/server-remapped/0022-Remove-invalid-mob-spawner-tile-entities.patch create mode 100644 patches/server-remapped/0023-Optimize-TileEntity-Ticking.patch create mode 100644 patches/server-remapped/0024-Further-improve-server-tick-loop.patch create mode 100644 patches/server-remapped/0025-Only-refresh-abilities-if-needed.patch create mode 100644 patches/server-remapped/0026-Entity-Origin-API.patch create mode 100644 patches/server-remapped/0027-Prevent-tile-entity-and-entity-crashes.patch create mode 100644 patches/server-remapped/0028-Configurable-top-of-nether-void-damage.patch create mode 100644 patches/server-remapped/0029-Check-online-mode-before-converting-and-renaming-pla.patch create mode 100644 patches/server-remapped/0030-Always-tick-falling-blocks.patch create mode 100644 patches/server-remapped/0031-Configurable-end-credits.patch create mode 100644 patches/server-remapped/0032-Fix-lag-from-explosions-processing-dead-entities.patch create mode 100644 patches/server-remapped/0033-Optimize-explosions.patch create mode 100644 patches/server-remapped/0034-Disable-explosion-knockback.patch create mode 100644 patches/server-remapped/0035-Disable-thunder.patch create mode 100644 patches/server-remapped/0036-Disable-ice-and-snow.patch create mode 100644 patches/server-remapped/0037-Configurable-mob-spawner-tick-rate.patch create mode 100644 patches/server-remapped/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch create mode 100644 patches/server-remapped/0039-Add-BeaconEffectEvent.patch create mode 100644 patches/server-remapped/0040-Configurable-container-update-tick-rate.patch create mode 100644 patches/server-remapped/0041-Use-UserCache-for-player-heads.patch create mode 100644 patches/server-remapped/0042-Disable-spigot-tick-limiters.patch create mode 100644 patches/server-remapped/0043-Add-PlayerInitialSpawnEvent.patch create mode 100644 patches/server-remapped/0044-Configurable-Disabling-Cat-Chest-Detection.patch create mode 100644 patches/server-remapped/0045-Ensure-commands-are-not-ran-async.patch create mode 100644 patches/server-remapped/0046-All-chunks-are-slime-spawn-chunks-toggle.patch create mode 100644 patches/server-remapped/0047-Expose-server-CommandMap.patch create mode 100644 patches/server-remapped/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch create mode 100644 patches/server-remapped/0049-Player-Tab-List-and-Title-APIs.patch create mode 100644 patches/server-remapped/0050-Ensure-inv-drag-is-in-bounds.patch create mode 100644 patches/server-remapped/0051-Change-implementation-of-tile-entity-removal-list.patch create mode 100644 patches/server-remapped/0052-Add-configurable-portal-search-radius.patch create mode 100644 patches/server-remapped/0053-Add-velocity-warnings.patch create mode 100644 patches/server-remapped/0054-Configurable-inter-world-teleportation-safety.patch create mode 100644 patches/server-remapped/0055-Add-exception-reporting-event.patch create mode 100644 patches/server-remapped/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch create mode 100644 patches/server-remapped/0057-Disable-Scoreboards-for-non-players-by-default.patch create mode 100644 patches/server-remapped/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch create mode 100644 patches/server-remapped/0059-Complete-resource-pack-API.patch create mode 100644 patches/server-remapped/0060-Chunk-Save-Reattempt.patch create mode 100644 patches/server-remapped/0061-Default-loading-permissions.yml-before-plugins.patch create mode 100644 patches/server-remapped/0062-Allow-Reloading-of-Custom-Permissions.patch create mode 100644 patches/server-remapped/0063-Remove-Metadata-on-reload.patch create mode 100644 patches/server-remapped/0064-Handle-Item-Meta-Inconsistencies.patch create mode 100644 patches/server-remapped/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch create mode 100644 patches/server-remapped/0066-Add-World-Util-Methods.patch create mode 100644 patches/server-remapped/0067-Custom-replacement-for-eaten-items.patch create mode 100644 patches/server-remapped/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch create mode 100644 patches/server-remapped/0069-Use-a-Shared-Random-for-Entities.patch create mode 100644 patches/server-remapped/0070-Configurable-spawn-chances-for-skeleton-horses.patch create mode 100644 patches/server-remapped/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch create mode 100644 patches/server-remapped/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch create mode 100644 patches/server-remapped/0073-Entity-AddTo-RemoveFrom-World-Events.patch create mode 100644 patches/server-remapped/0074-Configurable-Chunk-Inhabited-Time.patch create mode 100644 patches/server-remapped/0075-EntityPathfindEvent.patch create mode 100644 patches/server-remapped/0076-Sanitise-RegionFileCache-and-make-configurable.patch create mode 100644 patches/server-remapped/0077-Do-not-load-chunks-for-Pathfinding.patch create mode 100644 patches/server-remapped/0078-Add-PlayerUseUnknownEntityEvent.patch create mode 100644 patches/server-remapped/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch create mode 100644 patches/server-remapped/0080-Configurable-Grass-Spread-Tick-Rate.patch create mode 100644 patches/server-remapped/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch create mode 100644 patches/server-remapped/0082-Optimize-DataBits.patch create mode 100644 patches/server-remapped/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch create mode 100644 patches/server-remapped/0084-Workaround-for-setting-passengers-on-players.patch create mode 100644 patches/server-remapped/0085-Remove-unused-World-Tile-Entity-List.patch create mode 100644 patches/server-remapped/0086-Don-t-tick-Skulls-unused-code.patch create mode 100644 patches/server-remapped/0087-Configurable-Player-Collision.patch create mode 100644 patches/server-remapped/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch create mode 100644 patches/server-remapped/0089-Configurable-RCON-IP-address.patch create mode 100644 patches/server-remapped/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch create mode 100644 patches/server-remapped/0091-Implement-PlayerLocaleChangeEvent.patch create mode 100644 patches/server-remapped/0092-EntityRegainHealthEvent-isFastRegen-API.patch create mode 100644 patches/server-remapped/0093-Add-ability-to-configure-frosted_ice-properties.patch create mode 100644 patches/server-remapped/0094-remove-null-possibility-for-getServer-singleton.patch create mode 100644 patches/server-remapped/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch create mode 100644 patches/server-remapped/0096-LootTable-API-Replenishable-Lootables-Feature.patch create mode 100644 patches/server-remapped/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch create mode 100644 patches/server-remapped/0098-System-property-for-disabling-watchdoge.patch create mode 100644 patches/server-remapped/0099-Optimize-UserCache-Thread-Safe.patch create mode 100644 patches/server-remapped/0100-Avoid-blocking-on-Network-Manager-creation.patch create mode 100644 patches/server-remapped/0101-Optional-TNT-doesn-t-move-in-water.patch create mode 100644 patches/server-remapped/0102-Faster-redstone-torch-rapid-clock-removal.patch create mode 100644 patches/server-remapped/0103-Add-server-name-parameter.patch create mode 100644 patches/server-remapped/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch create mode 100644 patches/server-remapped/0105-Fix-Double-World-Add-issues.patch create mode 100644 patches/server-remapped/0106-Fix-Old-Sign-Conversion.patch create mode 100644 patches/server-remapped/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch create mode 100644 patches/server-remapped/0108-Add-setting-for-proxy-online-mode-status.patch create mode 100644 patches/server-remapped/0109-Optimise-BlockState-s-hashCode-equals.patch create mode 100644 patches/server-remapped/0110-Configurable-packet-in-spam-threshold.patch create mode 100644 patches/server-remapped/0111-Configurable-flying-kick-messages.patch create mode 100644 patches/server-remapped/0112-Chunk-registration-fixes.patch create mode 100644 patches/server-remapped/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch create mode 100644 patches/server-remapped/0114-Auto-fix-bad-Y-levels-on-player-login.patch create mode 100644 patches/server-remapped/0115-Option-to-remove-corrupt-tile-entities.patch create mode 100644 patches/server-remapped/0116-Add-EntityZapEvent.patch create mode 100644 patches/server-remapped/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch create mode 100644 patches/server-remapped/0118-Cache-user-authenticator-threads.patch create mode 100644 patches/server-remapped/0119-Optimise-removeQueue.patch create mode 100644 patches/server-remapped/0120-Allow-Reloading-of-Command-Aliases.patch create mode 100644 patches/server-remapped/0121-Add-source-to-PlayerExpChangeEvent.patch create mode 100644 patches/server-remapped/0122-Don-t-let-fishinghooks-use-portals.patch create mode 100644 patches/server-remapped/0123-Add-ProjectileCollideEvent.patch create mode 100644 patches/server-remapped/0124-Prevent-Pathfinding-out-of-World-Border.patch create mode 100644 patches/server-remapped/0125-Optimize-World.isLoaded-BlockPosition-Z.patch create mode 100644 patches/server-remapped/0126-Bound-Treasure-Maps-to-World-Border.patch create mode 100644 patches/server-remapped/0127-Configurable-Cartographer-Treasure-Maps.patch create mode 100644 patches/server-remapped/0128-Optimize-ItemStack.isEmpty.patch create mode 100644 patches/server-remapped/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch create mode 100644 patches/server-remapped/0130-Properly-fix-item-duplication-bug.patch create mode 100644 patches/server-remapped/0131-String-based-Action-Bar-API.patch create mode 100644 patches/server-remapped/0132-Firework-API-s.patch create mode 100644 patches/server-remapped/0133-PlayerTeleportEndGatewayEvent.patch create mode 100644 patches/server-remapped/0134-Provide-E-TE-Chunk-count-stat-methods.patch create mode 100644 patches/server-remapped/0135-Enforce-Sync-Player-Saves.patch create mode 100644 patches/server-remapped/0136-Don-t-allow-entities-to-ride-themselves-572.patch create mode 100644 patches/server-remapped/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch create mode 100644 patches/server-remapped/0138-Cap-Entity-Collisions.patch create mode 100644 patches/server-remapped/0139-Remove-CraftScheduler-Async-Task-Debugger.patch create mode 100644 patches/server-remapped/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch create mode 100644 patches/server-remapped/0141-Do-not-let-armorstands-drown.patch create mode 100644 patches/server-remapped/0142-Properly-handle-async-calls-to-restart-the-server.patch create mode 100644 patches/server-remapped/0143-Add-system-property-to-disable-book-size-limits.patch create mode 100644 patches/server-remapped/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch create mode 100644 patches/server-remapped/0145-Add-configuration-option-to-prevent-player-names-fro.patch create mode 100644 patches/server-remapped/0146-Use-TerminalConsoleAppender-for-console-improvements.patch create mode 100644 patches/server-remapped/0147-provide-a-configurable-option-to-disable-creeper-lin.patch create mode 100644 patches/server-remapped/0148-Item-canEntityPickup.patch create mode 100644 patches/server-remapped/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch create mode 100644 patches/server-remapped/0150-PlayerAttemptPickupItemEvent.patch create mode 100644 patches/server-remapped/0151-Add-UnknownCommandEvent.patch create mode 100644 patches/server-remapped/0152-Basic-PlayerProfile-API.patch create mode 100644 patches/server-remapped/0153-Shoulder-Entities-Release-API.patch create mode 100644 patches/server-remapped/0154-Profile-Lookup-Events.patch create mode 100644 patches/server-remapped/0155-Block-player-logins-during-server-shutdown.patch create mode 100644 patches/server-remapped/0156-Entity-fromMobSpawner.patch create mode 100644 patches/server-remapped/0157-Improve-the-Saddle-API-for-Horses.patch create mode 100644 patches/server-remapped/0158-Implement-ensureServerConversions-API.patch create mode 100644 patches/server-remapped/0159-Implement-getI18NDisplayName.patch create mode 100644 patches/server-remapped/0160-ProfileWhitelistVerifyEvent.patch create mode 100644 patches/server-remapped/0161-Fix-this-stupid-bullshit.patch create mode 100644 patches/server-remapped/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch create mode 100644 patches/server-remapped/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch create mode 100644 patches/server-remapped/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch create mode 100644 patches/server-remapped/0165-Allow-specifying-a-custom-authentication-servers-dow.patch create mode 100644 patches/server-remapped/0166-LivingEntity-setKiller.patch create mode 100644 patches/server-remapped/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch create mode 100644 patches/server-remapped/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch create mode 100644 patches/server-remapped/0169-Add-PlayerJumpEvent.patch create mode 100644 patches/server-remapped/0170-handle-PacketPlayInKeepAlive-async.patch create mode 100644 patches/server-remapped/0171-Expose-client-protocol-version-and-virtual-host.patch create mode 100644 patches/server-remapped/0172-revert-serverside-behavior-of-keepalives.patch create mode 100644 patches/server-remapped/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch create mode 100644 patches/server-remapped/0174-Option-for-maximum-exp-value-when-merging-orbs.patch create mode 100644 patches/server-remapped/0175-Add-PlayerArmorChangeEvent.patch create mode 100644 patches/server-remapped/0176-Prevent-logins-from-being-processed-when-the-player-.patch create mode 100644 patches/server-remapped/0177-use-CB-BlockState-implementations-for-captured-block.patch create mode 100644 patches/server-remapped/0178-API-to-get-a-BlockState-without-a-snapshot.patch create mode 100644 patches/server-remapped/0179-AsyncTabCompleteEvent.patch create mode 100644 patches/server-remapped/0180-Avoid-NPE-in-PathfinderGoalTempt.patch create mode 100644 patches/server-remapped/0181-PlayerPickupExperienceEvent.patch create mode 100644 patches/server-remapped/0182-ExperienceOrbMergeEvent.patch create mode 100644 patches/server-remapped/0183-Ability-to-apply-mending-to-XP-API.patch create mode 100644 patches/server-remapped/0184-Make-max-squid-spawn-height-configurable.patch create mode 100644 patches/server-remapped/0185-PreCreatureSpawnEvent.patch create mode 100644 patches/server-remapped/0186-PlayerNaturallySpawnCreaturesEvent.patch create mode 100644 patches/server-remapped/0187-Add-setPlayerProfile-API-for-Skulls.patch create mode 100644 patches/server-remapped/0188-Fill-Profile-Property-Events.patch create mode 100644 patches/server-remapped/0189-PlayerAdvancementCriterionGrantEvent.patch create mode 100644 patches/server-remapped/0190-Add-ArmorStand-Item-Meta.patch create mode 100644 patches/server-remapped/0191-Extend-Player-Interact-cancellation.patch create mode 100644 patches/server-remapped/0192-Tameable-getOwnerUniqueId-API.patch create mode 100644 patches/server-remapped/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch create mode 100644 patches/server-remapped/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch create mode 100644 patches/server-remapped/0195-Disable-Explicit-Network-Manager-Flushing.patch create mode 100644 patches/server-remapped/0196-Implement-extended-PaperServerListPingEvent.patch create mode 100644 patches/server-remapped/0197-Improved-Async-Task-Scheduler.patch create mode 100644 patches/server-remapped/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch create mode 100644 patches/server-remapped/0199-Player.setPlayerProfile-API.patch create mode 100644 patches/server-remapped/0200-Fix-Dragon-Server-Crashes.patch create mode 100644 patches/server-remapped/0201-getPlayerUniqueId-API.patch create mode 100644 patches/server-remapped/0202-Make-player-data-saving-configurable.patch create mode 100644 patches/server-remapped/0203-Make-legacy-ping-handler-more-reliable.patch create mode 100644 patches/server-remapped/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch create mode 100644 patches/server-remapped/0205-Flag-to-disable-the-channel-limit.patch create mode 100644 patches/server-remapped/0206-Add-method-to-open-already-placed-sign.patch create mode 100644 patches/server-remapped/0207-Configurable-sprint-interruption-on-attack.patch create mode 100644 patches/server-remapped/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch create mode 100644 patches/server-remapped/0209-EndermanEscapeEvent.patch create mode 100644 patches/server-remapped/0210-Enderman.teleportRandomly.patch create mode 100644 patches/server-remapped/0211-Block-Enderpearl-Travel-Exploit.patch create mode 100644 patches/server-remapped/0212-Expand-World.spawnParticle-API-and-add-Builder.patch create mode 100644 patches/server-remapped/0213-EndermanAttackPlayerEvent.patch create mode 100644 patches/server-remapped/0214-WitchConsumePotionEvent.patch create mode 100644 patches/server-remapped/0215-WitchThrowPotionEvent.patch create mode 100644 patches/server-remapped/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch create mode 100644 patches/server-remapped/0217-WitchReadyPotionEvent.patch create mode 100644 patches/server-remapped/0218-ItemStack-getMaxItemUseDuration.patch create mode 100644 patches/server-remapped/0219-Implement-EntityTeleportEndGatewayEvent.patch create mode 100644 patches/server-remapped/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch create mode 100644 patches/server-remapped/0221-Fix-CraftEntity-hashCode.patch create mode 100644 patches/server-remapped/0222-Configurable-Alternative-LootPool-Luck-Formula.patch create mode 100644 patches/server-remapped/0223-Print-Error-details-when-failing-to-save-player-data.patch create mode 100644 patches/server-remapped/0224-Make-shield-blocking-delay-configurable.patch create mode 100644 patches/server-remapped/0225-Improve-EntityShootBowEvent.patch create mode 100644 patches/server-remapped/0226-PlayerReadyArrowEvent.patch create mode 100644 patches/server-remapped/0227-Implement-EntityKnockbackByEntityEvent.patch create mode 100644 patches/server-remapped/0228-Expand-Explosions-API.patch create mode 100644 patches/server-remapped/0229-LivingEntity-Hand-Raised-Item-Use-API.patch create mode 100644 patches/server-remapped/0230-RangedEntity-API.patch create mode 100644 patches/server-remapped/0231-Add-config-to-disable-ender-dragon-legacy-check.patch create mode 100644 patches/server-remapped/0232-Implement-World.getEntity-UUID-API.patch create mode 100644 patches/server-remapped/0233-InventoryCloseEvent-Reason-API.patch create mode 100644 patches/server-remapped/0234-Vex-getSummoner-API.patch create mode 100644 patches/server-remapped/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch create mode 100644 patches/server-remapped/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch create mode 100644 patches/server-remapped/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch create mode 100644 patches/server-remapped/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch create mode 100644 patches/server-remapped/0239-Use-asynchronous-Log4j-2-loggers.patch create mode 100644 patches/server-remapped/0240-add-more-information-to-Entity.toString.patch create mode 100644 patches/server-remapped/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch create mode 100644 patches/server-remapped/0242-EnderDragon-Events.patch create mode 100644 patches/server-remapped/0243-PlayerElytraBoostEvent.patch create mode 100644 patches/server-remapped/0244-Improve-BlockPosition-inlining.patch create mode 100644 patches/server-remapped/0245-Optimize-RegistryID.c.patch create mode 100644 patches/server-remapped/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch create mode 100644 patches/server-remapped/0247-Vanished-players-don-t-have-rights.patch create mode 100644 patches/server-remapped/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch create mode 100644 patches/server-remapped/0249-Add-some-Debug-to-Chunk-Entity-slices.patch create mode 100644 patches/server-remapped/0250-SkeletonHorse-Additions.patch create mode 100644 patches/server-remapped/0251-Prevent-Saving-Bad-entities-to-chunks.patch create mode 100644 patches/server-remapped/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch create mode 100644 patches/server-remapped/0253-Ignore-Dead-Entities-in-entityList-iteration.patch create mode 100644 patches/server-remapped/0254-Implement-Expanded-ArmorStand-API.patch create mode 100644 patches/server-remapped/0255-AnvilDamageEvent.patch create mode 100644 patches/server-remapped/0256-Add-TNTPrimeEvent.patch create mode 100644 patches/server-remapped/0257-Break-up-and-make-tab-spam-limits-configurable.patch create mode 100644 patches/server-remapped/0258-Add-hand-to-bucket-events.patch create mode 100644 patches/server-remapped/0259-MC-135506-Experience-should-save-as-Integers.patch create mode 100644 patches/server-remapped/0260-Fix-client-rendering-skulls-from-same-user.patch create mode 100644 patches/server-remapped/0261-Add-Early-Warning-Feature-to-WatchDog.patch create mode 100644 patches/server-remapped/0262-Make-EnderDragon-implement-Mob.patch create mode 100644 patches/server-remapped/0263-Use-ConcurrentHashMap-in-JsonList.patch create mode 100644 patches/server-remapped/0264-Use-a-Queue-for-Queueing-Commands.patch create mode 100644 patches/server-remapped/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch create mode 100644 patches/server-remapped/0266-Allow-disabling-armour-stand-ticking.patch create mode 100644 patches/server-remapped/0267-Optimize-BlockPosition-helper-methods.patch create mode 100644 patches/server-remapped/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch create mode 100644 patches/server-remapped/0269-Slime-Pathfinder-Events.patch create mode 100644 patches/server-remapped/0270-Configurable-speed-for-water-flowing-over-lava.patch create mode 100644 patches/server-remapped/0271-Optimize-CraftBlockData-Creation.patch create mode 100644 patches/server-remapped/0272-Optimize-RegistryMaterials.patch create mode 100644 patches/server-remapped/0273-Add-PhantomPreSpawnEvent.patch create mode 100644 patches/server-remapped/0274-Add-More-Creeper-API.patch create mode 100644 patches/server-remapped/0275-Inventory-removeItemAnySlot.patch create mode 100644 patches/server-remapped/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch create mode 100644 patches/server-remapped/0277-Add-ray-tracing-methods-to-LivingEntity.patch create mode 100644 patches/server-remapped/0278-Expose-attack-cooldown-methods-for-Player.patch create mode 100644 patches/server-remapped/0279-Improve-death-events.patch create mode 100644 patches/server-remapped/0280-Allow-chests-to-be-placed-with-NBT-data.patch create mode 100644 patches/server-remapped/0281-Mob-Pathfinding-API.patch create mode 100644 patches/server-remapped/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch create mode 100644 patches/server-remapped/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch create mode 100644 patches/server-remapped/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch create mode 100644 patches/server-remapped/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch create mode 100644 patches/server-remapped/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch create mode 100644 patches/server-remapped/0287-Implement-furnace-cook-speed-multiplier-API.patch create mode 100644 patches/server-remapped/0288-PreSpawnerSpawnEvent.patch create mode 100644 patches/server-remapped/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch create mode 100644 patches/server-remapped/0290-Honor-EntityAgeable.ageLock.patch create mode 100644 patches/server-remapped/0291-Configurable-connection-throttle-kick-message.patch create mode 100644 patches/server-remapped/0292-Hook-into-CB-plugin-rewrites.patch create mode 100644 patches/server-remapped/0293-Allow-setting-the-vex-s-summoner.patch create mode 100644 patches/server-remapped/0294-Add-sun-related-API.patch create mode 100644 patches/server-remapped/0295-Turtle-API.patch create mode 100644 patches/server-remapped/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch create mode 100644 patches/server-remapped/0297-Call-player-spectator-target-events-and-improve-impl.patch create mode 100644 patches/server-remapped/0298-Add-Velocity-IP-Forwarding-Support.patch create mode 100644 patches/server-remapped/0299-Add-more-Witch-API.patch create mode 100644 patches/server-remapped/0300-Check-Drowned-for-Villager-Aggression-Config.patch create mode 100644 patches/server-remapped/0301-Here-s-Johnny.patch create mode 100644 patches/server-remapped/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch create mode 100644 patches/server-remapped/0303-Reset-players-airTicks-on-respawn.patch create mode 100644 patches/server-remapped/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch create mode 100644 patches/server-remapped/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch create mode 100644 patches/server-remapped/0306-Optimize-World-Time-Updates.patch create mode 100644 patches/server-remapped/0307-Restore-custom-InventoryHolder-support.patch create mode 100644 patches/server-remapped/0308-Use-Vanilla-Minecart-Speeds.patch create mode 100644 patches/server-remapped/0309-Fix-SpongeAbsortEvent-handling.patch create mode 100644 patches/server-remapped/0310-Don-t-allow-digging-into-unloaded-chunks.patch create mode 100644 patches/server-remapped/0311-Book-Size-Limits.patch create mode 100644 patches/server-remapped/0312-Make-the-default-permission-message-configurable.patch create mode 100644 patches/server-remapped/0313-Prevent-rayTrace-from-loading-chunks.patch create mode 100644 patches/server-remapped/0314-Handle-Large-Packets-disconnecting-client.patch create mode 100644 patches/server-remapped/0315-force-entity-dismount-during-teleportation.patch create mode 100644 patches/server-remapped/0316-Add-more-Zombie-API.patch create mode 100644 patches/server-remapped/0317-Add-PlayerConnectionCloseEvent.patch create mode 100644 patches/server-remapped/0318-Prevent-Enderman-from-loading-chunks.patch create mode 100644 patches/server-remapped/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch create mode 100644 patches/server-remapped/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch create mode 100644 patches/server-remapped/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch create mode 100644 patches/server-remapped/0322-Block-Entity-remove-from-being-called-on-Players.patch create mode 100644 patches/server-remapped/0323-BlockDestroyEvent.patch create mode 100644 patches/server-remapped/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch create mode 100644 patches/server-remapped/0325-Fix-sign-edit-memory-leak.patch create mode 100644 patches/server-remapped/0326-Limit-Client-Sign-length-more.patch create mode 100644 patches/server-remapped/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch create mode 100644 patches/server-remapped/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch create mode 100644 patches/server-remapped/0329-Handle-Oversized-Tile-Entities-in-chunks.patch create mode 100644 patches/server-remapped/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch create mode 100644 patches/server-remapped/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch create mode 100644 patches/server-remapped/0332-Allow-Saving-of-Oversized-Chunks.patch create mode 100644 patches/server-remapped/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch create mode 100644 patches/server-remapped/0334-Add-LivingEntity-getTargetEntity.patch create mode 100644 patches/server-remapped/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch create mode 100644 patches/server-remapped/0336-Entity-getEntitySpawnReason.patch create mode 100644 patches/server-remapped/0337-Update-entity-Metadata-for-all-tracked-players.patch create mode 100644 patches/server-remapped/0338-Implement-PlayerPostRespawnEvent.patch create mode 100644 patches/server-remapped/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch create mode 100644 patches/server-remapped/0340-Server-Tick-Events.patch create mode 100644 patches/server-remapped/0341-PlayerDeathEvent-getItemsToKeep.patch create mode 100644 patches/server-remapped/0342-Optimize-Captured-TileEntity-Lookup.patch create mode 100644 patches/server-remapped/0343-Add-Heightmap-API.patch create mode 100644 patches/server-remapped/0344-Mob-Spawner-API-Enhancements.patch create mode 100644 patches/server-remapped/0345-Per-Player-View-Distance-API-placeholders.patch create mode 100644 patches/server-remapped/0346-Fix-CB-call-to-changed-postToMainThread-method.patch create mode 100644 patches/server-remapped/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch create mode 100644 patches/server-remapped/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch create mode 100644 patches/server-remapped/0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch create mode 100644 patches/server-remapped/0350-Duplicate-UUID-Resolve-Option.patch create mode 100644 patches/server-remapped/0351-improve-CraftWorld-isChunkLoaded.patch create mode 100644 patches/server-remapped/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch create mode 100644 patches/server-remapped/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch create mode 100644 patches/server-remapped/0354-ChunkMapDistance-CME.patch create mode 100644 patches/server-remapped/0355-Implement-CraftBlockSoundGroup.patch create mode 100644 patches/server-remapped/0356-Chunk-debug-command.patch create mode 100644 patches/server-remapped/0357-Catch-exceptions-from-dispenser-entity-spawns.patch create mode 100644 patches/server-remapped/0358-Fix-World-isChunkGenerated-calls.patch create mode 100644 patches/server-remapped/0359-Show-blockstate-location-if-we-failed-to-read-it.patch create mode 100644 patches/server-remapped/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch create mode 100644 patches/server-remapped/0361-incremental-chunk-saving.patch create mode 100644 patches/server-remapped/0362-Anti-Xray.patch create mode 100644 patches/server-remapped/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch create mode 100644 patches/server-remapped/0364-Configurable-projectile-relative-velocity.patch create mode 100644 patches/server-remapped/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch create mode 100644 patches/server-remapped/0366-offset-item-frame-ticking.patch create mode 100644 patches/server-remapped/0367-Avoid-hopper-searches-if-there-are-no-items.patch create mode 100644 patches/server-remapped/0368-Asynchronous-chunk-IO-and-loading.patch create mode 100644 patches/server-remapped/0369-Use-getChunkIfLoadedImmediately-in-places.patch create mode 100644 patches/server-remapped/0370-Reduce-sync-loads.patch create mode 100644 patches/server-remapped/0371-Implement-alternative-item-despawn-rate.patch create mode 100644 patches/server-remapped/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch create mode 100644 patches/server-remapped/0373-Fix-MC-158900.patch create mode 100644 patches/server-remapped/0374-implement-optional-per-player-mob-spawns.patch create mode 100644 patches/server-remapped/0375-Prevent-consuming-the-wrong-itemstack.patch create mode 100644 patches/server-remapped/0376-Generator-Settings.patch create mode 100644 patches/server-remapped/0377-Fix-MC-161754.patch create mode 100644 patches/server-remapped/0378-Performance-improvement-for-Chunk.getEntities.patch create mode 100644 patches/server-remapped/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch create mode 100644 patches/server-remapped/0380-Expose-the-internal-current-tick.patch create mode 100644 patches/server-remapped/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch create mode 100644 patches/server-remapped/0382-Add-option-to-disable-pillager-patrols.patch create mode 100644 patches/server-remapped/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch create mode 100644 patches/server-remapped/0384-PlayerLaunchProjectileEvent.patch create mode 100644 patches/server-remapped/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch create mode 100644 patches/server-remapped/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch create mode 100644 patches/server-remapped/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch create mode 100644 patches/server-remapped/0388-Optimize-Hoppers.patch create mode 100644 patches/server-remapped/0389-PlayerDeathEvent-shouldDropExperience.patch create mode 100644 patches/server-remapped/0390-Prevent-bees-loading-chunks-checking-hive-position.patch create mode 100644 patches/server-remapped/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch create mode 100644 patches/server-remapped/0392-Guard-against-serializing-mismatching-chunk-coordina.patch create mode 100644 patches/server-remapped/0393-Optimise-IEntityAccess-getPlayerByUUID.patch create mode 100644 patches/server-remapped/0394-Fix-items-not-falling-correctly.patch create mode 100644 patches/server-remapped/0395-Lag-compensate-eating.patch create mode 100644 patches/server-remapped/0396-Optimize-call-to-getFluid-for-explosions.patch create mode 100644 patches/server-remapped/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch create mode 100644 patches/server-remapped/0398-Add-effect-to-block-break-naturally.patch create mode 100644 patches/server-remapped/0399-Tracking-Range-Improvements.patch create mode 100644 patches/server-remapped/0400-Entity-Activation-Range-2.0.patch create mode 100644 patches/server-remapped/0401-Fix-items-vanishing-through-end-portal.patch create mode 100644 patches/server-remapped/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch create mode 100644 patches/server-remapped/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch create mode 100644 patches/server-remapped/0404-Allow-overriding-the-java-version-check.patch create mode 100644 patches/server-remapped/0405-Add-ThrownEggHatchEvent.patch create mode 100644 patches/server-remapped/0406-Optimise-random-block-ticking.patch create mode 100644 patches/server-remapped/0407-Entity-Jump-API.patch create mode 100644 patches/server-remapped/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch create mode 100644 patches/server-remapped/0409-Make-the-GUI-graph-fancier.patch create mode 100644 patches/server-remapped/0410-add-hand-to-BlockMultiPlaceEvent.patch create mode 100644 patches/server-remapped/0411-Prevent-teleporting-dead-entities.patch create mode 100644 patches/server-remapped/0412-Validate-tripwire-hook-placement-before-update.patch create mode 100644 patches/server-remapped/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch create mode 100644 patches/server-remapped/0414-Configurable-chance-of-villager-zombie-infection.patch create mode 100644 patches/server-remapped/0415-Optimise-Chunk-getFluid.patch create mode 100644 patches/server-remapped/0416-Optimise-TickListServer-by-rewriting-it.patch create mode 100644 patches/server-remapped/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch create mode 100644 patches/server-remapped/0418-Ensure-Entity-is-never-double-registered.patch create mode 100644 patches/server-remapped/0419-Fix-unregistering-entities-from-unloading-chunks.patch create mode 100644 patches/server-remapped/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch create mode 100644 patches/server-remapped/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch create mode 100644 patches/server-remapped/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch create mode 100644 patches/server-remapped/0423-Optimize-Collision-to-not-load-chunks.patch create mode 100644 patches/server-remapped/0424-Don-t-tick-dead-players.patch create mode 100644 patches/server-remapped/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch create mode 100644 patches/server-remapped/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch create mode 100644 patches/server-remapped/0427-Increase-Light-Queue-Size.patch create mode 100644 patches/server-remapped/0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch create mode 100644 patches/server-remapped/0429-Don-t-move-existing-players-to-world-spawn.patch create mode 100644 patches/server-remapped/0430-Add-tick-times-API-and-mspt-command.patch create mode 100644 patches/server-remapped/0431-Expose-MinecraftServer-isRunning.patch create mode 100644 patches/server-remapped/0432-Add-Raw-Byte-ItemStack-Serialization.patch create mode 100644 patches/server-remapped/0433-Remove-streams-from-Mob-AI-System.patch create mode 100644 patches/server-remapped/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch create mode 100644 patches/server-remapped/0435-Async-command-map-building.patch create mode 100644 patches/server-remapped/0436-Improved-Watchdog-Support.patch create mode 100644 patches/server-remapped/0437-Optimize-Pathfinding.patch create mode 100644 patches/server-remapped/0438-Reduce-Either-Optional-allocation.patch create mode 100644 patches/server-remapped/0439-Remove-streams-from-PairedQueue.patch create mode 100644 patches/server-remapped/0440-Reduce-memory-footprint-of-NBTTagCompound.patch create mode 100644 patches/server-remapped/0441-Prevent-opening-inventories-when-frozen.patch create mode 100644 patches/server-remapped/0442-Optimise-ArraySetSorted-removeIf.patch create mode 100644 patches/server-remapped/0443-Don-t-run-entity-collision-code-if-not-needed.patch create mode 100644 patches/server-remapped/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch create mode 100644 patches/server-remapped/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch create mode 100644 patches/server-remapped/0446-Implement-Player-Client-Options-API.patch create mode 100644 patches/server-remapped/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch create mode 100644 patches/server-remapped/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch create mode 100644 patches/server-remapped/0449-Broadcast-join-message-to-console.patch create mode 100644 patches/server-remapped/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch create mode 100644 patches/server-remapped/0451-Load-Chunks-for-Login-Asynchronously.patch create mode 100644 patches/server-remapped/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch create mode 100644 patches/server-remapped/0453-Add-PlayerAttackEntityCooldownResetEvent.patch create mode 100644 patches/server-remapped/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch create mode 100644 patches/server-remapped/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch create mode 100644 patches/server-remapped/0456-Add-phantom-creative-and-insomniac-controls.patch create mode 100644 patches/server-remapped/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch create mode 100644 patches/server-remapped/0458-Implement-Brigadier-Mojang-API.patch create mode 100644 patches/server-remapped/0459-Villager-Restocks-API.patch create mode 100644 patches/server-remapped/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch create mode 100644 patches/server-remapped/0461-Expose-game-version.patch create mode 100644 patches/server-remapped/0462-Optimize-Voxel-Shape-Merging.patch create mode 100644 patches/server-remapped/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch create mode 100644 patches/server-remapped/0464-Implement-Mob-Goal-API.patch create mode 100644 patches/server-remapped/0465-Use-distance-map-to-optimise-entity-tracker.patch create mode 100644 patches/server-remapped/0466-Optimize-isOutsideRange-to-use-distance-maps.patch create mode 100644 patches/server-remapped/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch create mode 100644 patches/server-remapped/0468-No-Tick-view-distance-implementation.patch create mode 100644 patches/server-remapped/0469-Add-villager-reputation-API.patch create mode 100644 patches/server-remapped/0470-Fix-Light-Command.patch create mode 100644 patches/server-remapped/0471-Fix-PotionEffect-ignores-icon-flag.patch create mode 100644 patches/server-remapped/0472-Optimize-brigadier-child-sorting-performance.patch create mode 100644 patches/server-remapped/0473-Potential-bed-API.patch create mode 100644 patches/server-remapped/0474-Wait-for-Async-Tasks-during-shutdown.patch create mode 100644 patches/server-remapped/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch create mode 100644 patches/server-remapped/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch create mode 100644 patches/server-remapped/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch create mode 100644 patches/server-remapped/0478-Reduce-MutableInt-allocations-from-light-engine.patch create mode 100644 patches/server-remapped/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch create mode 100644 patches/server-remapped/0480-Ensure-safe-gateway-teleport.patch create mode 100644 patches/server-remapped/0481-Add-option-for-console-having-all-permissions.patch create mode 100644 patches/server-remapped/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch create mode 100644 patches/server-remapped/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch create mode 100644 patches/server-remapped/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch create mode 100644 patches/server-remapped/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch create mode 100644 patches/server-remapped/0486-Improve-Chunk-Status-Transition-Speed.patch create mode 100644 patches/server-remapped/0487-Fix-villager-trading-demand-MC-163962.patch create mode 100644 patches/server-remapped/0488-Maps-shouldn-t-load-chunks.patch create mode 100644 patches/server-remapped/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch create mode 100644 patches/server-remapped/0490-Optimize-Bit-Operations-by-inlining.patch create mode 100644 patches/server-remapped/0491-Optimize-Light-Engine.patch create mode 100644 patches/server-remapped/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch create mode 100644 patches/server-remapped/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch create mode 100644 patches/server-remapped/0494-Fix-missing-chunks-due-to-integer-overflow.patch create mode 100644 patches/server-remapped/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch create mode 100644 patches/server-remapped/0496-Fix-piston-physics-inconsistency-MC-188840.patch create mode 100644 patches/server-remapped/0497-Fix-sand-duping.patch create mode 100644 patches/server-remapped/0498-Prevent-position-desync-in-playerconnection-causing-.patch create mode 100644 patches/server-remapped/0499-Fix-enderdragon-exp-dupe.patch create mode 100644 patches/server-remapped/0500-Inventory-getHolder-method-without-block-snapshot.patch create mode 100644 patches/server-remapped/0501-Expose-Arrow-getItemStack.patch create mode 100644 patches/server-remapped/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch create mode 100644 patches/server-remapped/0503-Hide-sync-chunk-writes-behind-flag.patch create mode 100644 patches/server-remapped/0504-Limit-lightning-strike-effect-distance.patch create mode 100644 patches/server-remapped/0505-Add-permission-for-command-blocks.patch create mode 100644 patches/server-remapped/0506-Ensure-Entity-AABB-s-are-never-invalid.patch create mode 100644 patches/server-remapped/0507-Optimize-WorldBorder-collision-checks-and-air.patch create mode 100644 patches/server-remapped/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch create mode 100644 patches/server-remapped/0509-Paper-dumpitem-command.patch create mode 100644 patches/server-remapped/0510-Don-t-allow-null-UUID-s-for-chat.patch create mode 100644 patches/server-remapped/0511-Improve-Legacy-Component-serialization-size.patch create mode 100644 patches/server-remapped/0512-Support-old-UUID-format-for-NBT.patch create mode 100644 patches/server-remapped/0513-Clean-up-duplicated-GameProfile-Properties.patch create mode 100644 patches/server-remapped/0514-Convert-legacy-attributes-in-Item-Meta.patch create mode 100644 patches/server-remapped/0515-Remove-some-streams-from-structures.patch create mode 100644 patches/server-remapped/0516-Remove-streams-from-classes-related-villager-gossip.patch create mode 100644 patches/server-remapped/0517-Support-components-in-ItemMeta.patch create mode 100644 patches/server-remapped/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch create mode 100644 patches/server-remapped/0519-Add-entity-liquid-API.patch create mode 100644 patches/server-remapped/0520-Update-itemstack-legacy-name-and-lore.patch create mode 100644 patches/server-remapped/0521-Spawn-player-in-correct-world-on-login.patch create mode 100644 patches/server-remapped/0522-Add-PrepareResultEvent.patch create mode 100644 patches/server-remapped/0523-Allow-delegation-to-vanilla-chunk-gen.patch create mode 100644 patches/server-remapped/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch create mode 100644 patches/server-remapped/0525-Optimize-NetworkManager-Exception-Handling.patch create mode 100644 patches/server-remapped/0526-Fix-Concurrency-issue-in-WeightedList.patch create mode 100644 patches/server-remapped/0527-Optimize-the-advancement-data-player-iteration-to-be.patch create mode 100644 patches/server-remapped/0528-Fix-arrows-never-despawning-MC-125757.patch create mode 100644 patches/server-remapped/0529-Thread-Safe-Vanilla-Command-permission-checking.patch create mode 100644 patches/server-remapped/0530-Move-range-check-for-block-placing-up.patch create mode 100644 patches/server-remapped/0531-Fix-SPIGOT-5989.patch create mode 100644 patches/server-remapped/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch create mode 100644 patches/server-remapped/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch create mode 100644 patches/server-remapped/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch create mode 100644 patches/server-remapped/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch create mode 100644 patches/server-remapped/0536-Fix-some-rails-connecting-improperly.patch create mode 100644 patches/server-remapped/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch create mode 100644 patches/server-remapped/0538-Incremental-player-saving.patch create mode 100644 patches/server-remapped/0539-Import-fastutil-classes.patch create mode 100644 patches/server-remapped/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch create mode 100644 patches/server-remapped/0541-Remove-armour-stand-double-add-to-world.patch create mode 100644 patches/server-remapped/0542-Fix-MC-187716-Use-configured-height.patch create mode 100644 patches/server-remapped/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch create mode 100644 patches/server-remapped/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch create mode 100644 patches/server-remapped/0545-Brand-support.patch create mode 100644 patches/server-remapped/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch create mode 100644 patches/server-remapped/0547-Fix-MC-197271.patch create mode 100644 patches/server-remapped/0548-MC-197883-Bandaid-decode-issue.patch create mode 100644 patches/server-remapped/0549-Add-setMaxPlayers-API.patch create mode 100644 patches/server-remapped/0550-Add-playPickupItemAnimation-to-LivingEntity.patch create mode 100644 patches/server-remapped/0551-Don-t-require-FACING-data.patch create mode 100644 patches/server-remapped/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch create mode 100644 patches/server-remapped/0553-Add-moon-phase-API.patch create mode 100644 patches/server-remapped/0554-Prevent-headless-pistons-from-being-created.patch create mode 100644 patches/server-remapped/0555-Add-BellRingEvent.patch create mode 100644 patches/server-remapped/0556-Add-zombie-targets-turtle-egg-config.patch create mode 100644 patches/server-remapped/0557-Buffer-joins-to-world.patch create mode 100644 patches/server-remapped/0558-Optimize-redstone-algorithm.patch create mode 100644 patches/server-remapped/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch create mode 100644 patches/server-remapped/0560-PortalCreateEvent-needs-to-know-its-entity.patch create mode 100644 patches/server-remapped/0561-Fix-CraftTeam-null-check.patch create mode 100644 patches/server-remapped/0562-Add-more-Evoker-API.patch create mode 100644 patches/server-remapped/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch create mode 100644 patches/server-remapped/0564-Create-HoverEvent-from-ItemStack-Entity.patch create mode 100644 patches/server-remapped/0565-Cache-block-data-strings.patch create mode 100644 patches/server-remapped/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch create mode 100644 patches/server-remapped/0567-Add-additional-open-container-api-to-HumanEntity.patch create mode 100644 patches/server-remapped/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch create mode 100644 patches/server-remapped/0569-Extend-block-drop-capture-to-capture-all-items-added.patch create mode 100644 patches/server-remapped/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch create mode 100644 patches/server-remapped/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch create mode 100644 patches/server-remapped/0572-Lazily-track-plugin-scoreboards-by-default.patch create mode 100644 patches/server-remapped/0573-Entity-isTicking.patch create mode 100644 patches/server-remapped/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch create mode 100644 patches/server-remapped/0575-Fix-Not-a-string-Map-Conversion-spam.patch create mode 100644 patches/server-remapped/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch create mode 100644 patches/server-remapped/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch create mode 100644 patches/server-remapped/0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch create mode 100644 patches/server-remapped/0579-Fix-for-large-move-vectors-crashing-server.patch create mode 100644 patches/server-remapped/0580-Optimise-getType-calls.patch create mode 100644 patches/server-remapped/0581-Villager-resetOffers.patch create mode 100644 patches/server-remapped/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch create mode 100644 patches/server-remapped/0583-Retain-block-place-order-when-capturing-blockstates.patch create mode 100644 patches/server-remapped/0584-Reduce-blockpos-allocation-from-pathfinding.patch create mode 100644 patches/server-remapped/0585-Fix-item-locations-dropped-from-campfires.patch create mode 100644 patches/server-remapped/0586-Player-elytra-boost-API.patch create mode 100644 patches/server-remapped/0587-Fixed-TileEntityBell-memory-leak.patch create mode 100644 patches/server-remapped/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch create mode 100644 patches/server-remapped/0589-Add-getOfflinePlayerIfCached-String.patch create mode 100644 patches/server-remapped/0590-Add-ignore-discounts-API.patch create mode 100644 patches/server-remapped/0591-Toggle-for-removing-existing-dragon.patch create mode 100644 patches/server-remapped/0592-Fix-client-lag-on-advancement-loading.patch create mode 100644 patches/server-remapped/0593-Item-no-age-no-player-pickup.patch create mode 100644 patches/server-remapped/0594-Beacon-API-custom-effect-ranges.patch create mode 100644 patches/server-remapped/0595-Add-API-for-quit-reason.patch create mode 100644 patches/server-remapped/0596-Seed-based-feature-search.patch create mode 100644 patches/server-remapped/0597-Add-Wandering-Trader-spawn-rate-config-options.patch create mode 100644 patches/server-remapped/0598-Significantly-improve-performance-of-the-end-generat.patch create mode 100644 patches/server-remapped/0599-Expose-world-spawn-angle.patch create mode 100644 patches/server-remapped/0600-Add-Destroy-Speed-API.patch create mode 100644 patches/server-remapped/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch create mode 100644 patches/server-remapped/0602-Add-LivingEntity-clearActiveItem.patch create mode 100644 patches/server-remapped/0603-Add-PlayerItemCooldownEvent.patch create mode 100644 patches/server-remapped/0604-More-lightning-API.patch create mode 100644 patches/server-remapped/0605-Climbing-should-not-bypass-cramming-gamerule.patch create mode 100644 patches/server-remapped/0606-Added-missing-default-perms-for-commands.patch create mode 100644 patches/server-remapped/0607-Add-PlayerShearBlockEvent.patch create mode 100644 patches/server-remapped/0608-Add-warning-for-servers-not-running-on-Java-16.patch create mode 100644 patches/server-remapped/0609-Set-spigots-verbose-world-setting-to-false-by-def.patch create mode 100644 patches/server-remapped/0610-Fix-curing-zombie-villager-discount-exploit.patch create mode 100644 patches/server-remapped/0611-Limit-recipe-packets.patch create mode 100644 patches/server-remapped/0612-Fix-CraftSound-backwards-compatibility.patch create mode 100644 patches/server-remapped/0613-MC-4-Fix-item-position-desync.patch create mode 100644 patches/server-remapped/0614-Player-Chunk-Load-Unload-Events.patch create mode 100644 patches/server-remapped/0615-Optimize-Dynamic-get-Missing-Keys.patch create mode 100644 patches/server-remapped/0616-Expose-LivingEntity-hurt-direction.patch create mode 100644 patches/server-remapped/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch create mode 100644 patches/server-remapped/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch create mode 100644 patches/server-remapped/0619-added-PlayerTradeEvent.patch create mode 100644 patches/server-remapped/0620-Implement-TargetHitEvent.patch create mode 100644 patches/server-remapped/0621-Additional-Block-Material-API-s.patch create mode 100644 patches/server-remapped/0622-Fix-harming-potion-dupe.patch create mode 100644 patches/server-remapped/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch create mode 100644 patches/server-remapped/0624-Optimized-tick-ready-check.patch create mode 100644 patches/server-remapped/0625-Cache-burn-durations.patch create mode 100644 patches/server-remapped/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch create mode 100644 patches/server-remapped/0627-Implement-PlayerFlowerPotManipulateEvent.patch create mode 100644 patches/server-remapped/0628-Fix-interact-event-not-being-called-in-adventure.patch create mode 100644 patches/server-remapped/0629-Zombie-API-breaking-doors.patch create mode 100644 patches/server-remapped/0630-Fix-nerfed-slime-when-splitting.patch create mode 100644 patches/server-remapped/0631-Add-EntityLoadCrossbowEvent.patch create mode 100644 patches/server-remapped/0632-Guardian-beam-workaround.patch create mode 100644 patches/server-remapped/0633-Added-WorldGameRuleChangeEvent.patch create mode 100644 patches/server-remapped/0634-Added-ServerResourcesReloadedEvent.patch create mode 100644 patches/server-remapped/0635-Added-world-settings-for-mobs-picking-up-loot.patch create mode 100644 patches/server-remapped/0636-Implemented-BlockFailedDispenseEvent.patch create mode 100644 patches/server-remapped/0637-Added-PlayerLecternPageChangeEvent.patch create mode 100644 patches/server-remapped/0638-Fire-event-on-GS4-query.patch create mode 100644 patches/server-remapped/0639-Added-PlayerLoomPatternSelectEvent.patch create mode 100644 patches/server-remapped/0640-Configurable-door-breaking-difficulty.patch create mode 100644 patches/server-remapped/0641-Empty-commands-shall-not-be-dispatched.patch create mode 100644 patches/server-remapped/0642-Implement-API-to-expose-exact-interaction-point.patch create mode 100644 patches/server-remapped/0643-Remove-stale-POIs.patch create mode 100644 patches/server-remapped/0644-Fix-villager-boat-exploit.patch create mode 100644 patches/server-remapped/0645-Entity-load-save-limit-per-chunk.patch create mode 100644 patches/server-remapped/0646-Add-sendOpLevel-API.patch create mode 100644 patches/server-remapped/0647-Add-StructureLocateEvent.patch create mode 100644 patches/server-remapped/0648-Collision-option-for-requiring-a-player-participant.patch create mode 100644 patches/server-remapped/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch create mode 100644 patches/server-remapped/0650-Return-chat-component-with-empty-text-instead-of-thr.patch create mode 100644 patches/server-remapped/0651-Make-schedule-command-per-world.patch create mode 100644 patches/server-remapped/0652-Configurable-max-leash-distance.patch create mode 100644 patches/server-remapped/0653-Implement-BlockPreDispenseEvent.patch create mode 100644 patches/server-remapped/0654-Added-Vanilla-Entity-Tags.patch create mode 100644 patches/server-remapped/0655-added-Wither-API.patch create mode 100644 patches/server-remapped/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch create mode 100644 patches/server-remapped/0657-Fix-console-spam-when-removing-chests-in-water.patch create mode 100644 patches/server-remapped/0658-Add-toggle-for-always-placing-the-dragon-egg.patch create mode 100644 patches/server-remapped/0659-Added-PlayerStonecutterRecipeSelectEvent.patch create mode 100644 patches/server-remapped/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch create mode 100644 patches/server-remapped/0661-Skip-distance-map-update-when-spawning-disabled.patch create mode 100644 patches/server-remapped/0662-Reset-shield-blocking-on-dimension-change.patch create mode 100644 patches/server-remapped/0663-add-DragonEggFormEvent.patch create mode 100644 patches/server-remapped/0664-EntityMoveEvent.patch create mode 100644 patches/server-remapped/0665-added-option-to-disable-pathfinding-updates-on-block.patch create mode 100644 patches/server-remapped/0666-Inline-shift-direction-fields.patch create mode 100644 patches/server-remapped/0667-Allow-adding-items-to-BlockDropItemEvent.patch create mode 100644 patches/server-remapped/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch create mode 100644 patches/server-remapped/0669-living-entity-allow-attribute-registration.patch create mode 100644 patches/server-remapped/0670-fix-dead-slime-setSize-invincibility.patch create mode 100644 patches/server-remapped/0671-Merchant-getRecipes-should-return-an-immutable-list.patch create mode 100644 patches/server-remapped/0672-misc-debugging-dumps.patch create mode 100644 patches/server-remapped/0673-Add-support-for-hex-color-codes-in-console.patch create mode 100644 patches/server-remapped/0674-Clear-SyncLoadInfo.patch create mode 100644 patches/server-remapped/0675-Expose-Tracked-Players.patch create mode 100644 patches/server-remapped/0676-Remove-streams-from-SensorNearest.patch create mode 100644 patches/server-remapped/0677-do-not-create-unnecessary-copies-of-passenger-list.patch create mode 100644 patches/server-remapped/0678-MC-29274-Fix-Wither-hostility-towards-players.patch create mode 100644 patches/server-remapped/0679-Throw-proper-exception-on-empty-JsonList-file.patch create mode 100644 patches/server-remapped/0680-Improve-ServerGUI.patch create mode 100644 patches/server-remapped/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch create mode 100644 patches/server-remapped/0682-fix-converting-txt-to-json-file.patch create mode 100644 patches/server-remapped/0683-Add-worldborder-events.patch create mode 100644 patches/server-remapped/0684-added-PlayerNameEntityEvent.patch create mode 100644 patches/server-remapped/0685-Prevent-grindstones-from-overstacking-items.patch create mode 100644 patches/server-remapped/0686-Add-recipe-to-cook-events.patch create mode 100644 patches/server-remapped/0687-Add-Block-isValidTool.patch create mode 100644 patches/server-remapped/0688-Allow-using-signs-inside-spawn-protection.patch create mode 100644 patches/server-remapped/0689-Implement-Keyed-on-World.patch create mode 100644 patches/server-remapped/0690-Add-fast-alternative-constructor-for-Vector3f.patch create mode 100644 patches/server-remapped/0691-Item-Rarity-API.patch create mode 100644 patches/server-remapped/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch create mode 100644 patches/server-remapped/0693-copy-TESign-isEditable-from-snapshots.patch create mode 100644 patches/server-remapped/0694-Drop-carried-item-when-player-has-disconnected.patch create mode 100644 patches/server-remapped/0695-forced-whitelist-use-configurable-kick-message.patch create mode 100644 patches/server-remapped/0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch create mode 100644 patches/server-remapped/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch create mode 100644 patches/server-remapped/0698-fix-cancelling-block-falling-causing-client-desync.patch create mode 100644 patches/server-remapped/0699-Expose-protocol-version.patch create mode 100644 patches/server-remapped/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch create mode 100644 patches/server-remapped/0701-Enhance-console-tab-completions-for-brigadier-comman.patch create mode 100644 patches/server-remapped/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch create mode 100644 patches/server-remapped/0703-Add-bypass-host-check.patch create mode 100644 patches/server-remapped/0704-don-t-throw-when-loading-invalid-TEs.patch create mode 100644 patches/server-remapped/0705-Set-area-affect-cloud-rotation.patch create mode 100644 patches/server-remapped/0706-add-isDeeplySleeping-to-HumanEntity.patch create mode 100644 patches/server-remapped/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch create mode 100644 patches/server-remapped/0708-add-consumeFuel-to-FurnaceBurnEvent.patch create mode 100644 patches/server-remapped/0709-add-get-set-drop-chance-to-EntityEquipment.patch create mode 100644 patches/server-remapped/0710-fix-PigZombieAngerEvent-cancellation.patch create mode 100644 patches/server-remapped/0711-Fix-checkReach-check-for-Shulker-boxes.patch create mode 100644 patches/server-remapped/0712-fix-PlayerItemHeldEvent-firing-twice.patch create mode 100644 patches/server-remapped/0713-Added-PlayerDeepSleepEvent.patch create mode 100644 patches/server-remapped/0714-More-World-API.patch create mode 100644 patches/server-remapped/0715-Added-PlayerBedFailEnterEvent.patch create mode 100644 patches/server-remapped/0716-Implement-methods-to-convert-between-Component-and-B.patch create mode 100644 patches/server-remapped/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch create mode 100644 patches/server-remapped/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch create mode 100644 patches/server-remapped/0719-Introduce-beacon-activation-deactivation-events.patch create mode 100644 patches/server-remapped/0720-Add-Channel-initialization-listeners.patch create mode 100644 patches/server-remapped/0721-Send-empty-commands-if-tab-completion-is-disabled.patch create mode 100644 patches/server-remapped/0722-Add-more-WanderingTrader-API.patch create mode 100644 patches/server-remapped/0723-Add-EntityBlockStorage-clearEntities.patch create mode 100644 patches/server-remapped/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch create mode 100644 patches/server-remapped/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch create mode 100644 patches/server-remapped/0726-Inventory-close.patch create mode 100644 patches/server-remapped/0727-call-PortalCreateEvent-players-and-end-platform.patch create mode 100644 patches/server-remapped/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch create mode 100644 patches/server-remapped/0729-Fix-CraftPotionBrewer-cache.patch create mode 100644 patches/server-remapped/0730-Add-basic-Datapack-API.patch create mode 100644 patches/server-remapped/0731-Add-environment-variable-to-disable-server-gui.patch create mode 100644 patches/server-remapped/0732-additions-to-PlayerGameModeChangeEvent.patch create mode 100644 patches/server-remapped/0733-ItemStack-repair-check-API.patch create mode 100644 patches/server-remapped/0734-More-Enchantment-API.patch create mode 100644 patches/server-remapped/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch create mode 100644 patches/server-remapped/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch create mode 100644 patches/server-remapped/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch create mode 100644 patches/server-remapped/0738-Fix-and-optimise-world-force-upgrading.patch create mode 100644 patches/server-remapped/0739-Add-Mob-lookAt-API.patch create mode 100644 patches/server-remapped/0740-Add-Unix-domain-socket-support.patch create mode 100644 patches/server-remapped/0741-Add-EntityInsideBlockEvent.patch create mode 100644 patches/server-remapped/0742-Attributes-API-for-item-defaults.patch create mode 100644 patches/server-remapped/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch create mode 100644 patches/server-remapped/0744-Add-cause-to-Weather-ThunderChangeEvents.patch create mode 100644 patches/server-remapped/0745-More-Lidded-Block-API.patch create mode 100644 patches/server-remapped/0746-Add-PlayerKickEvent-causes.patch create mode 100644 patches/server-remapped/0747-Limit-item-frame-cursors-on-maps.patch create mode 100644 patches/server-remapped/0748-Add-PufferFishStateChangeEvent.patch create mode 100644 patches/server-remapped/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch create mode 100644 patches/server-remapped/0750-Add-option-to-fix-items-merging-through-walls.patch create mode 100644 patches/server-remapped/0751-Add-BellRevealRaiderEvent.patch create mode 100644 patches/server-remapped/0752-Fix-invulnerable-end-crystals.patch create mode 100644 patches/server-remapped/0753-Add-ElderGuardianAppearanceEvent.patch create mode 100644 patches/server-remapped/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch create mode 100644 patches/server-remapped/0755-Fix-dangerous-end-portal-logic.patch create mode 100644 patches/server-remapped/0756-Make-item-validations-configurable.patch create mode 100644 patches/server-remapped/0757-Add-more-line-of-sight-methods.patch create mode 100644 patches/server-remapped/0758-add-per-world-spawn-limits.patch create mode 100644 patches/server-remapped/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch create mode 100644 patches/server-unmapped/0001-POM-Changes.patch create mode 100644 patches/server-unmapped/0002-Paper-config-files.patch create mode 100644 patches/server-unmapped/0003-MC-Dev-fixes.patch create mode 100644 patches/server-unmapped/0004-MC-Utils.patch create mode 100644 patches/server-unmapped/0005-Paper-Metrics.patch create mode 100644 patches/server-unmapped/0006-Add-MinecraftKey-Information-to-Objects.patch create mode 100644 patches/server-unmapped/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch create mode 100644 patches/server-unmapped/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch create mode 100644 patches/server-unmapped/0009-Timings-v2.patch create mode 100644 patches/server-unmapped/0010-Adventure.patch create mode 100644 patches/server-unmapped/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch create mode 100644 patches/server-unmapped/0012-Configurable-baby-zombie-movement-speed.patch create mode 100644 patches/server-unmapped/0013-Configurable-fishing-time-ranges.patch create mode 100644 patches/server-unmapped/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch create mode 100644 patches/server-unmapped/0015-Add-configurable-despawn-distances-for-living-entiti.patch create mode 100644 patches/server-unmapped/0016-Allow-for-toggling-of-spawn-chunks.patch create mode 100644 patches/server-unmapped/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch create mode 100644 patches/server-unmapped/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch create mode 100644 patches/server-unmapped/0019-Implement-Paper-VersionChecker.patch create mode 100644 patches/server-unmapped/0020-Add-version-history-to-version-command.patch create mode 100644 patches/server-unmapped/0021-Player-affects-spawning-API.patch create mode 100644 patches/server-unmapped/0022-Remove-invalid-mob-spawner-tile-entities.patch create mode 100644 patches/server-unmapped/0023-Optimize-TileEntity-Ticking.patch create mode 100644 patches/server-unmapped/0024-Further-improve-server-tick-loop.patch create mode 100644 patches/server-unmapped/0025-Only-refresh-abilities-if-needed.patch create mode 100644 patches/server-unmapped/0026-Entity-Origin-API.patch create mode 100644 patches/server-unmapped/0027-Prevent-tile-entity-and-entity-crashes.patch create mode 100644 patches/server-unmapped/0028-Configurable-top-of-nether-void-damage.patch create mode 100644 patches/server-unmapped/0029-Check-online-mode-before-converting-and-renaming-pla.patch create mode 100644 patches/server-unmapped/0030-Always-tick-falling-blocks.patch create mode 100644 patches/server-unmapped/0031-Configurable-end-credits.patch create mode 100644 patches/server-unmapped/0032-Fix-lag-from-explosions-processing-dead-entities.patch create mode 100644 patches/server-unmapped/0033-Optimize-explosions.patch create mode 100644 patches/server-unmapped/0034-Disable-explosion-knockback.patch create mode 100644 patches/server-unmapped/0035-Disable-thunder.patch create mode 100644 patches/server-unmapped/0036-Disable-ice-and-snow.patch create mode 100644 patches/server-unmapped/0037-Configurable-mob-spawner-tick-rate.patch create mode 100644 patches/server-unmapped/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch create mode 100644 patches/server-unmapped/0039-Add-BeaconEffectEvent.patch create mode 100644 patches/server-unmapped/0040-Configurable-container-update-tick-rate.patch create mode 100644 patches/server-unmapped/0041-Use-UserCache-for-player-heads.patch create mode 100644 patches/server-unmapped/0042-Disable-spigot-tick-limiters.patch create mode 100644 patches/server-unmapped/0043-Add-PlayerInitialSpawnEvent.patch create mode 100644 patches/server-unmapped/0044-Configurable-Disabling-Cat-Chest-Detection.patch create mode 100644 patches/server-unmapped/0045-Ensure-commands-are-not-ran-async.patch create mode 100644 patches/server-unmapped/0046-All-chunks-are-slime-spawn-chunks-toggle.patch create mode 100644 patches/server-unmapped/0047-Expose-server-CommandMap.patch create mode 100644 patches/server-unmapped/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch create mode 100644 patches/server-unmapped/0049-Player-Tab-List-and-Title-APIs.patch create mode 100644 patches/server-unmapped/0050-Ensure-inv-drag-is-in-bounds.patch create mode 100644 patches/server-unmapped/0051-Change-implementation-of-tile-entity-removal-list.patch create mode 100644 patches/server-unmapped/0052-Add-configurable-portal-search-radius.patch create mode 100644 patches/server-unmapped/0053-Add-velocity-warnings.patch create mode 100644 patches/server-unmapped/0054-Configurable-inter-world-teleportation-safety.patch create mode 100644 patches/server-unmapped/0055-Add-exception-reporting-event.patch create mode 100644 patches/server-unmapped/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch create mode 100644 patches/server-unmapped/0057-Disable-Scoreboards-for-non-players-by-default.patch create mode 100644 patches/server-unmapped/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch create mode 100644 patches/server-unmapped/0059-Complete-resource-pack-API.patch create mode 100644 patches/server-unmapped/0060-Chunk-Save-Reattempt.patch create mode 100644 patches/server-unmapped/0061-Default-loading-permissions.yml-before-plugins.patch create mode 100644 patches/server-unmapped/0062-Allow-Reloading-of-Custom-Permissions.patch create mode 100644 patches/server-unmapped/0063-Remove-Metadata-on-reload.patch create mode 100644 patches/server-unmapped/0064-Handle-Item-Meta-Inconsistencies.patch create mode 100644 patches/server-unmapped/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch create mode 100644 patches/server-unmapped/0066-Add-World-Util-Methods.patch create mode 100644 patches/server-unmapped/0067-Custom-replacement-for-eaten-items.patch create mode 100644 patches/server-unmapped/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch create mode 100644 patches/server-unmapped/0069-Use-a-Shared-Random-for-Entities.patch create mode 100644 patches/server-unmapped/0070-Configurable-spawn-chances-for-skeleton-horses.patch create mode 100644 patches/server-unmapped/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch create mode 100644 patches/server-unmapped/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch create mode 100644 patches/server-unmapped/0073-Entity-AddTo-RemoveFrom-World-Events.patch create mode 100644 patches/server-unmapped/0074-Configurable-Chunk-Inhabited-Time.patch create mode 100644 patches/server-unmapped/0075-EntityPathfindEvent.patch create mode 100644 patches/server-unmapped/0076-Sanitise-RegionFileCache-and-make-configurable.patch create mode 100644 patches/server-unmapped/0077-Do-not-load-chunks-for-Pathfinding.patch create mode 100644 patches/server-unmapped/0078-Add-PlayerUseUnknownEntityEvent.patch create mode 100644 patches/server-unmapped/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch create mode 100644 patches/server-unmapped/0080-Configurable-Grass-Spread-Tick-Rate.patch create mode 100644 patches/server-unmapped/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch create mode 100644 patches/server-unmapped/0082-Optimize-DataBits.patch create mode 100644 patches/server-unmapped/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch create mode 100644 patches/server-unmapped/0084-Workaround-for-setting-passengers-on-players.patch create mode 100644 patches/server-unmapped/0085-Remove-unused-World-Tile-Entity-List.patch create mode 100644 patches/server-unmapped/0086-Don-t-tick-Skulls-unused-code.patch create mode 100644 patches/server-unmapped/0087-Configurable-Player-Collision.patch create mode 100644 patches/server-unmapped/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch create mode 100644 patches/server-unmapped/0089-Configurable-RCON-IP-address.patch create mode 100644 patches/server-unmapped/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch create mode 100644 patches/server-unmapped/0091-Implement-PlayerLocaleChangeEvent.patch create mode 100644 patches/server-unmapped/0092-EntityRegainHealthEvent-isFastRegen-API.patch create mode 100644 patches/server-unmapped/0093-Add-ability-to-configure-frosted_ice-properties.patch create mode 100644 patches/server-unmapped/0094-remove-null-possibility-for-getServer-singleton.patch create mode 100644 patches/server-unmapped/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch create mode 100644 patches/server-unmapped/0096-LootTable-API-Replenishable-Lootables-Feature.patch create mode 100644 patches/server-unmapped/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch create mode 100644 patches/server-unmapped/0098-System-property-for-disabling-watchdoge.patch create mode 100644 patches/server-unmapped/0099-Optimize-UserCache-Thread-Safe.patch create mode 100644 patches/server-unmapped/0100-Avoid-blocking-on-Network-Manager-creation.patch create mode 100644 patches/server-unmapped/0101-Optional-TNT-doesn-t-move-in-water.patch create mode 100644 patches/server-unmapped/0102-Faster-redstone-torch-rapid-clock-removal.patch create mode 100644 patches/server-unmapped/0103-Add-server-name-parameter.patch create mode 100644 patches/server-unmapped/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch create mode 100644 patches/server-unmapped/0105-Fix-Double-World-Add-issues.patch create mode 100644 patches/server-unmapped/0106-Fix-Old-Sign-Conversion.patch create mode 100644 patches/server-unmapped/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch create mode 100644 patches/server-unmapped/0108-Add-setting-for-proxy-online-mode-status.patch create mode 100644 patches/server-unmapped/0109-Optimise-BlockState-s-hashCode-equals.patch create mode 100644 patches/server-unmapped/0110-Configurable-packet-in-spam-threshold.patch create mode 100644 patches/server-unmapped/0111-Configurable-flying-kick-messages.patch create mode 100644 patches/server-unmapped/0112-Chunk-registration-fixes.patch create mode 100644 patches/server-unmapped/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch create mode 100644 patches/server-unmapped/0114-Auto-fix-bad-Y-levels-on-player-login.patch create mode 100644 patches/server-unmapped/0115-Option-to-remove-corrupt-tile-entities.patch create mode 100644 patches/server-unmapped/0116-Add-EntityZapEvent.patch create mode 100644 patches/server-unmapped/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch create mode 100644 patches/server-unmapped/0118-Cache-user-authenticator-threads.patch create mode 100644 patches/server-unmapped/0119-Optimise-removeQueue.patch create mode 100644 patches/server-unmapped/0120-Allow-Reloading-of-Command-Aliases.patch create mode 100644 patches/server-unmapped/0121-Add-source-to-PlayerExpChangeEvent.patch create mode 100644 patches/server-unmapped/0122-Don-t-let-fishinghooks-use-portals.patch create mode 100644 patches/server-unmapped/0123-Add-ProjectileCollideEvent.patch create mode 100644 patches/server-unmapped/0124-Prevent-Pathfinding-out-of-World-Border.patch create mode 100644 patches/server-unmapped/0125-Optimize-World.isLoaded-BlockPosition-Z.patch create mode 100644 patches/server-unmapped/0126-Bound-Treasure-Maps-to-World-Border.patch create mode 100644 patches/server-unmapped/0127-Configurable-Cartographer-Treasure-Maps.patch create mode 100644 patches/server-unmapped/0128-Optimize-ItemStack.isEmpty.patch create mode 100644 patches/server-unmapped/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch create mode 100644 patches/server-unmapped/0130-Properly-fix-item-duplication-bug.patch create mode 100644 patches/server-unmapped/0131-String-based-Action-Bar-API.patch create mode 100644 patches/server-unmapped/0132-Firework-API-s.patch create mode 100644 patches/server-unmapped/0133-PlayerTeleportEndGatewayEvent.patch create mode 100644 patches/server-unmapped/0134-Provide-E-TE-Chunk-count-stat-methods.patch create mode 100644 patches/server-unmapped/0135-Enforce-Sync-Player-Saves.patch create mode 100644 patches/server-unmapped/0136-Don-t-allow-entities-to-ride-themselves-572.patch create mode 100644 patches/server-unmapped/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch create mode 100644 patches/server-unmapped/0138-Cap-Entity-Collisions.patch create mode 100644 patches/server-unmapped/0139-Remove-CraftScheduler-Async-Task-Debugger.patch create mode 100644 patches/server-unmapped/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch create mode 100644 patches/server-unmapped/0141-Do-not-let-armorstands-drown.patch create mode 100644 patches/server-unmapped/0142-Properly-handle-async-calls-to-restart-the-server.patch create mode 100644 patches/server-unmapped/0143-Add-system-property-to-disable-book-size-limits.patch create mode 100644 patches/server-unmapped/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch create mode 100644 patches/server-unmapped/0145-Add-configuration-option-to-prevent-player-names-fro.patch create mode 100644 patches/server-unmapped/0146-Use-TerminalConsoleAppender-for-console-improvements.patch create mode 100644 patches/server-unmapped/0147-provide-a-configurable-option-to-disable-creeper-lin.patch create mode 100644 patches/server-unmapped/0148-Item-canEntityPickup.patch create mode 100644 patches/server-unmapped/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch create mode 100644 patches/server-unmapped/0150-PlayerAttemptPickupItemEvent.patch create mode 100644 patches/server-unmapped/0151-Add-UnknownCommandEvent.patch create mode 100644 patches/server-unmapped/0152-Basic-PlayerProfile-API.patch create mode 100644 patches/server-unmapped/0153-Shoulder-Entities-Release-API.patch create mode 100644 patches/server-unmapped/0154-Profile-Lookup-Events.patch create mode 100644 patches/server-unmapped/0155-Block-player-logins-during-server-shutdown.patch create mode 100644 patches/server-unmapped/0156-Entity-fromMobSpawner.patch create mode 100644 patches/server-unmapped/0157-Improve-the-Saddle-API-for-Horses.patch create mode 100644 patches/server-unmapped/0158-Implement-ensureServerConversions-API.patch create mode 100644 patches/server-unmapped/0159-Implement-getI18NDisplayName.patch create mode 100644 patches/server-unmapped/0160-ProfileWhitelistVerifyEvent.patch create mode 100644 patches/server-unmapped/0161-Fix-this-stupid-bullshit.patch create mode 100644 patches/server-unmapped/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch create mode 100644 patches/server-unmapped/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch create mode 100644 patches/server-unmapped/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch create mode 100644 patches/server-unmapped/0165-Allow-specifying-a-custom-authentication-servers-dow.patch create mode 100644 patches/server-unmapped/0166-LivingEntity-setKiller.patch create mode 100644 patches/server-unmapped/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch create mode 100644 patches/server-unmapped/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch create mode 100644 patches/server-unmapped/0169-Add-PlayerJumpEvent.patch create mode 100644 patches/server-unmapped/0170-handle-PacketPlayInKeepAlive-async.patch create mode 100644 patches/server-unmapped/0171-Expose-client-protocol-version-and-virtual-host.patch create mode 100644 patches/server-unmapped/0172-revert-serverside-behavior-of-keepalives.patch create mode 100644 patches/server-unmapped/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch create mode 100644 patches/server-unmapped/0174-Option-for-maximum-exp-value-when-merging-orbs.patch create mode 100644 patches/server-unmapped/0175-Add-PlayerArmorChangeEvent.patch create mode 100644 patches/server-unmapped/0176-Prevent-logins-from-being-processed-when-the-player-.patch create mode 100644 patches/server-unmapped/0177-use-CB-BlockState-implementations-for-captured-block.patch create mode 100644 patches/server-unmapped/0178-API-to-get-a-BlockState-without-a-snapshot.patch create mode 100644 patches/server-unmapped/0179-AsyncTabCompleteEvent.patch create mode 100644 patches/server-unmapped/0180-Avoid-NPE-in-PathfinderGoalTempt.patch create mode 100644 patches/server-unmapped/0181-PlayerPickupExperienceEvent.patch create mode 100644 patches/server-unmapped/0182-ExperienceOrbMergeEvent.patch create mode 100644 patches/server-unmapped/0183-Ability-to-apply-mending-to-XP-API.patch create mode 100644 patches/server-unmapped/0184-Make-max-squid-spawn-height-configurable.patch create mode 100644 patches/server-unmapped/0185-PreCreatureSpawnEvent.patch create mode 100644 patches/server-unmapped/0186-PlayerNaturallySpawnCreaturesEvent.patch create mode 100644 patches/server-unmapped/0187-Add-setPlayerProfile-API-for-Skulls.patch create mode 100644 patches/server-unmapped/0188-Fill-Profile-Property-Events.patch create mode 100644 patches/server-unmapped/0189-PlayerAdvancementCriterionGrantEvent.patch create mode 100644 patches/server-unmapped/0190-Add-ArmorStand-Item-Meta.patch create mode 100644 patches/server-unmapped/0191-Extend-Player-Interact-cancellation.patch create mode 100644 patches/server-unmapped/0192-Tameable-getOwnerUniqueId-API.patch create mode 100644 patches/server-unmapped/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch create mode 100644 patches/server-unmapped/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch create mode 100644 patches/server-unmapped/0195-Disable-Explicit-Network-Manager-Flushing.patch create mode 100644 patches/server-unmapped/0196-Implement-extended-PaperServerListPingEvent.patch create mode 100644 patches/server-unmapped/0197-Improved-Async-Task-Scheduler.patch create mode 100644 patches/server-unmapped/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch create mode 100644 patches/server-unmapped/0199-Player.setPlayerProfile-API.patch create mode 100644 patches/server-unmapped/0200-Fix-Dragon-Server-Crashes.patch create mode 100644 patches/server-unmapped/0201-getPlayerUniqueId-API.patch create mode 100644 patches/server-unmapped/0202-Make-player-data-saving-configurable.patch create mode 100644 patches/server-unmapped/0203-Make-legacy-ping-handler-more-reliable.patch create mode 100644 patches/server-unmapped/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch create mode 100644 patches/server-unmapped/0205-Flag-to-disable-the-channel-limit.patch create mode 100644 patches/server-unmapped/0206-Add-method-to-open-already-placed-sign.patch create mode 100644 patches/server-unmapped/0207-Configurable-sprint-interruption-on-attack.patch create mode 100644 patches/server-unmapped/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch create mode 100644 patches/server-unmapped/0209-EndermanEscapeEvent.patch create mode 100644 patches/server-unmapped/0210-Enderman.teleportRandomly.patch create mode 100644 patches/server-unmapped/0211-Block-Enderpearl-Travel-Exploit.patch create mode 100644 patches/server-unmapped/0212-Expand-World.spawnParticle-API-and-add-Builder.patch create mode 100644 patches/server-unmapped/0213-EndermanAttackPlayerEvent.patch create mode 100644 patches/server-unmapped/0214-WitchConsumePotionEvent.patch create mode 100644 patches/server-unmapped/0215-WitchThrowPotionEvent.patch create mode 100644 patches/server-unmapped/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch create mode 100644 patches/server-unmapped/0217-WitchReadyPotionEvent.patch create mode 100644 patches/server-unmapped/0218-ItemStack-getMaxItemUseDuration.patch create mode 100644 patches/server-unmapped/0219-Implement-EntityTeleportEndGatewayEvent.patch create mode 100644 patches/server-unmapped/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch create mode 100644 patches/server-unmapped/0221-Fix-CraftEntity-hashCode.patch create mode 100644 patches/server-unmapped/0222-Configurable-Alternative-LootPool-Luck-Formula.patch create mode 100644 patches/server-unmapped/0223-Print-Error-details-when-failing-to-save-player-data.patch create mode 100644 patches/server-unmapped/0224-Make-shield-blocking-delay-configurable.patch create mode 100644 patches/server-unmapped/0225-Improve-EntityShootBowEvent.patch create mode 100644 patches/server-unmapped/0226-PlayerReadyArrowEvent.patch create mode 100644 patches/server-unmapped/0227-Implement-EntityKnockbackByEntityEvent.patch create mode 100644 patches/server-unmapped/0228-Expand-Explosions-API.patch create mode 100644 patches/server-unmapped/0229-LivingEntity-Hand-Raised-Item-Use-API.patch create mode 100644 patches/server-unmapped/0230-RangedEntity-API.patch create mode 100644 patches/server-unmapped/0231-Add-config-to-disable-ender-dragon-legacy-check.patch create mode 100644 patches/server-unmapped/0232-Implement-World.getEntity-UUID-API.patch create mode 100644 patches/server-unmapped/0233-InventoryCloseEvent-Reason-API.patch create mode 100644 patches/server-unmapped/0234-Vex-getSummoner-API.patch create mode 100644 patches/server-unmapped/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch create mode 100644 patches/server-unmapped/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch create mode 100644 patches/server-unmapped/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch create mode 100644 patches/server-unmapped/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch create mode 100644 patches/server-unmapped/0239-Use-asynchronous-Log4j-2-loggers.patch create mode 100644 patches/server-unmapped/0240-add-more-information-to-Entity.toString.patch create mode 100644 patches/server-unmapped/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch create mode 100644 patches/server-unmapped/0242-EnderDragon-Events.patch create mode 100644 patches/server-unmapped/0243-PlayerElytraBoostEvent.patch create mode 100644 patches/server-unmapped/0244-Improve-BlockPosition-inlining.patch create mode 100644 patches/server-unmapped/0245-Optimize-RegistryID.c.patch create mode 100644 patches/server-unmapped/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch create mode 100644 patches/server-unmapped/0247-Vanished-players-don-t-have-rights.patch create mode 100644 patches/server-unmapped/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch create mode 100644 patches/server-unmapped/0249-Add-some-Debug-to-Chunk-Entity-slices.patch create mode 100644 patches/server-unmapped/0250-SkeletonHorse-Additions.patch create mode 100644 patches/server-unmapped/0251-Prevent-Saving-Bad-entities-to-chunks.patch create mode 100644 patches/server-unmapped/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch create mode 100644 patches/server-unmapped/0253-Ignore-Dead-Entities-in-entityList-iteration.patch create mode 100644 patches/server-unmapped/0254-Implement-Expanded-ArmorStand-API.patch create mode 100644 patches/server-unmapped/0255-AnvilDamageEvent.patch create mode 100644 patches/server-unmapped/0256-Add-TNTPrimeEvent.patch create mode 100644 patches/server-unmapped/0257-Break-up-and-make-tab-spam-limits-configurable.patch create mode 100644 patches/server-unmapped/0258-Add-hand-to-bucket-events.patch create mode 100644 patches/server-unmapped/0259-MC-135506-Experience-should-save-as-Integers.patch create mode 100644 patches/server-unmapped/0260-Fix-client-rendering-skulls-from-same-user.patch create mode 100644 patches/server-unmapped/0261-Add-Early-Warning-Feature-to-WatchDog.patch create mode 100644 patches/server-unmapped/0262-Make-EnderDragon-implement-Mob.patch create mode 100644 patches/server-unmapped/0263-Use-ConcurrentHashMap-in-JsonList.patch create mode 100644 patches/server-unmapped/0264-Use-a-Queue-for-Queueing-Commands.patch create mode 100644 patches/server-unmapped/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch create mode 100644 patches/server-unmapped/0266-Allow-disabling-armour-stand-ticking.patch create mode 100644 patches/server-unmapped/0267-Optimize-BlockPosition-helper-methods.patch create mode 100644 patches/server-unmapped/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch create mode 100644 patches/server-unmapped/0269-Slime-Pathfinder-Events.patch create mode 100644 patches/server-unmapped/0270-Configurable-speed-for-water-flowing-over-lava.patch create mode 100644 patches/server-unmapped/0271-Optimize-CraftBlockData-Creation.patch create mode 100644 patches/server-unmapped/0272-Optimize-RegistryMaterials.patch create mode 100644 patches/server-unmapped/0273-Add-PhantomPreSpawnEvent.patch create mode 100644 patches/server-unmapped/0274-Add-More-Creeper-API.patch create mode 100644 patches/server-unmapped/0275-Inventory-removeItemAnySlot.patch create mode 100644 patches/server-unmapped/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch create mode 100644 patches/server-unmapped/0277-Add-ray-tracing-methods-to-LivingEntity.patch create mode 100644 patches/server-unmapped/0278-Expose-attack-cooldown-methods-for-Player.patch create mode 100644 patches/server-unmapped/0279-Improve-death-events.patch create mode 100644 patches/server-unmapped/0280-Allow-chests-to-be-placed-with-NBT-data.patch create mode 100644 patches/server-unmapped/0281-Mob-Pathfinding-API.patch create mode 100644 patches/server-unmapped/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch create mode 100644 patches/server-unmapped/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch create mode 100644 patches/server-unmapped/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch create mode 100644 patches/server-unmapped/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch create mode 100644 patches/server-unmapped/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch create mode 100644 patches/server-unmapped/0287-Implement-furnace-cook-speed-multiplier-API.patch create mode 100644 patches/server-unmapped/0288-PreSpawnerSpawnEvent.patch create mode 100644 patches/server-unmapped/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch create mode 100644 patches/server-unmapped/0290-Honor-EntityAgeable.ageLock.patch create mode 100644 patches/server-unmapped/0291-Configurable-connection-throttle-kick-message.patch create mode 100644 patches/server-unmapped/0292-Hook-into-CB-plugin-rewrites.patch create mode 100644 patches/server-unmapped/0293-Allow-setting-the-vex-s-summoner.patch create mode 100644 patches/server-unmapped/0294-Add-sun-related-API.patch create mode 100644 patches/server-unmapped/0295-Turtle-API.patch create mode 100644 patches/server-unmapped/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch create mode 100644 patches/server-unmapped/0297-Call-player-spectator-target-events-and-improve-impl.patch create mode 100644 patches/server-unmapped/0298-Add-Velocity-IP-Forwarding-Support.patch create mode 100644 patches/server-unmapped/0299-Add-more-Witch-API.patch create mode 100644 patches/server-unmapped/0300-Check-Drowned-for-Villager-Aggression-Config.patch create mode 100644 patches/server-unmapped/0301-Here-s-Johnny.patch create mode 100644 patches/server-unmapped/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch create mode 100644 patches/server-unmapped/0303-Reset-players-airTicks-on-respawn.patch create mode 100644 patches/server-unmapped/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch create mode 100644 patches/server-unmapped/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch create mode 100644 patches/server-unmapped/0306-Optimize-World-Time-Updates.patch create mode 100644 patches/server-unmapped/0307-Restore-custom-InventoryHolder-support.patch create mode 100644 patches/server-unmapped/0308-Use-Vanilla-Minecart-Speeds.patch create mode 100644 patches/server-unmapped/0309-Fix-SpongeAbsortEvent-handling.patch create mode 100644 patches/server-unmapped/0310-Don-t-allow-digging-into-unloaded-chunks.patch create mode 100644 patches/server-unmapped/0311-Book-Size-Limits.patch create mode 100644 patches/server-unmapped/0312-Make-the-default-permission-message-configurable.patch create mode 100644 patches/server-unmapped/0313-Prevent-rayTrace-from-loading-chunks.patch create mode 100644 patches/server-unmapped/0314-Handle-Large-Packets-disconnecting-client.patch create mode 100644 patches/server-unmapped/0315-force-entity-dismount-during-teleportation.patch create mode 100644 patches/server-unmapped/0316-Add-more-Zombie-API.patch create mode 100644 patches/server-unmapped/0317-Add-PlayerConnectionCloseEvent.patch create mode 100644 patches/server-unmapped/0318-Prevent-Enderman-from-loading-chunks.patch create mode 100644 patches/server-unmapped/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch create mode 100644 patches/server-unmapped/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch create mode 100644 patches/server-unmapped/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch create mode 100644 patches/server-unmapped/0322-Block-Entity-remove-from-being-called-on-Players.patch create mode 100644 patches/server-unmapped/0323-BlockDestroyEvent.patch create mode 100644 patches/server-unmapped/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch create mode 100644 patches/server-unmapped/0325-Fix-sign-edit-memory-leak.patch create mode 100644 patches/server-unmapped/0326-Limit-Client-Sign-length-more.patch create mode 100644 patches/server-unmapped/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch create mode 100644 patches/server-unmapped/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch create mode 100644 patches/server-unmapped/0329-Handle-Oversized-Tile-Entities-in-chunks.patch create mode 100644 patches/server-unmapped/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch create mode 100644 patches/server-unmapped/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch create mode 100644 patches/server-unmapped/0332-Allow-Saving-of-Oversized-Chunks.patch create mode 100644 patches/server-unmapped/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch create mode 100644 patches/server-unmapped/0334-Add-LivingEntity-getTargetEntity.patch create mode 100644 patches/server-unmapped/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch create mode 100644 patches/server-unmapped/0336-Entity-getEntitySpawnReason.patch create mode 100644 patches/server-unmapped/0337-Update-entity-Metadata-for-all-tracked-players.patch create mode 100644 patches/server-unmapped/0338-Implement-PlayerPostRespawnEvent.patch create mode 100644 patches/server-unmapped/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch create mode 100644 patches/server-unmapped/0340-Server-Tick-Events.patch create mode 100644 patches/server-unmapped/0341-PlayerDeathEvent-getItemsToKeep.patch create mode 100644 patches/server-unmapped/0342-Optimize-Captured-TileEntity-Lookup.patch create mode 100644 patches/server-unmapped/0343-Add-Heightmap-API.patch create mode 100644 patches/server-unmapped/0344-Mob-Spawner-API-Enhancements.patch create mode 100644 patches/server-unmapped/0345-Per-Player-View-Distance-API-placeholders.patch create mode 100644 patches/server-unmapped/0346-Fix-CB-call-to-changed-postToMainThread-method.patch create mode 100644 patches/server-unmapped/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch create mode 100644 patches/server-unmapped/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch create mode 100644 patches/server-unmapped/0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch create mode 100644 patches/server-unmapped/0350-Duplicate-UUID-Resolve-Option.patch create mode 100644 patches/server-unmapped/0351-improve-CraftWorld-isChunkLoaded.patch create mode 100644 patches/server-unmapped/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch create mode 100644 patches/server-unmapped/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch create mode 100644 patches/server-unmapped/0354-ChunkMapDistance-CME.patch create mode 100644 patches/server-unmapped/0355-Implement-CraftBlockSoundGroup.patch create mode 100644 patches/server-unmapped/0356-Chunk-debug-command.patch create mode 100644 patches/server-unmapped/0357-Catch-exceptions-from-dispenser-entity-spawns.patch create mode 100644 patches/server-unmapped/0358-Fix-World-isChunkGenerated-calls.patch create mode 100644 patches/server-unmapped/0359-Show-blockstate-location-if-we-failed-to-read-it.patch create mode 100644 patches/server-unmapped/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch create mode 100644 patches/server-unmapped/0361-incremental-chunk-saving.patch create mode 100644 patches/server-unmapped/0362-Anti-Xray.patch create mode 100644 patches/server-unmapped/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch create mode 100644 patches/server-unmapped/0364-Configurable-projectile-relative-velocity.patch create mode 100644 patches/server-unmapped/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch create mode 100644 patches/server-unmapped/0366-offset-item-frame-ticking.patch create mode 100644 patches/server-unmapped/0367-Avoid-hopper-searches-if-there-are-no-items.patch create mode 100644 patches/server-unmapped/0368-Asynchronous-chunk-IO-and-loading.patch create mode 100644 patches/server-unmapped/0369-Use-getChunkIfLoadedImmediately-in-places.patch create mode 100644 patches/server-unmapped/0370-Reduce-sync-loads.patch create mode 100644 patches/server-unmapped/0371-Implement-alternative-item-despawn-rate.patch create mode 100644 patches/server-unmapped/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch create mode 100644 patches/server-unmapped/0373-Fix-MC-158900.patch create mode 100644 patches/server-unmapped/0374-implement-optional-per-player-mob-spawns.patch create mode 100644 patches/server-unmapped/0375-Prevent-consuming-the-wrong-itemstack.patch create mode 100644 patches/server-unmapped/0376-Generator-Settings.patch create mode 100644 patches/server-unmapped/0377-Fix-MC-161754.patch create mode 100644 patches/server-unmapped/0378-Performance-improvement-for-Chunk.getEntities.patch create mode 100644 patches/server-unmapped/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch create mode 100644 patches/server-unmapped/0380-Expose-the-internal-current-tick.patch create mode 100644 patches/server-unmapped/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch create mode 100644 patches/server-unmapped/0382-Add-option-to-disable-pillager-patrols.patch create mode 100644 patches/server-unmapped/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch create mode 100644 patches/server-unmapped/0384-PlayerLaunchProjectileEvent.patch create mode 100644 patches/server-unmapped/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch create mode 100644 patches/server-unmapped/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch create mode 100644 patches/server-unmapped/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch create mode 100644 patches/server-unmapped/0388-Optimize-Hoppers.patch create mode 100644 patches/server-unmapped/0389-PlayerDeathEvent-shouldDropExperience.patch create mode 100644 patches/server-unmapped/0390-Prevent-bees-loading-chunks-checking-hive-position.patch create mode 100644 patches/server-unmapped/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch create mode 100644 patches/server-unmapped/0392-Guard-against-serializing-mismatching-chunk-coordina.patch create mode 100644 patches/server-unmapped/0393-Optimise-IEntityAccess-getPlayerByUUID.patch create mode 100644 patches/server-unmapped/0394-Fix-items-not-falling-correctly.patch create mode 100644 patches/server-unmapped/0395-Lag-compensate-eating.patch create mode 100644 patches/server-unmapped/0396-Optimize-call-to-getFluid-for-explosions.patch create mode 100644 patches/server-unmapped/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch create mode 100644 patches/server-unmapped/0398-Add-effect-to-block-break-naturally.patch create mode 100644 patches/server-unmapped/0399-Tracking-Range-Improvements.patch create mode 100644 patches/server-unmapped/0400-Entity-Activation-Range-2.0.patch create mode 100644 patches/server-unmapped/0401-Fix-items-vanishing-through-end-portal.patch create mode 100644 patches/server-unmapped/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch create mode 100644 patches/server-unmapped/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch create mode 100644 patches/server-unmapped/0404-Allow-overriding-the-java-version-check.patch create mode 100644 patches/server-unmapped/0405-Add-ThrownEggHatchEvent.patch create mode 100644 patches/server-unmapped/0406-Optimise-random-block-ticking.patch create mode 100644 patches/server-unmapped/0407-Entity-Jump-API.patch create mode 100644 patches/server-unmapped/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch create mode 100644 patches/server-unmapped/0409-Make-the-GUI-graph-fancier.patch create mode 100644 patches/server-unmapped/0410-add-hand-to-BlockMultiPlaceEvent.patch create mode 100644 patches/server-unmapped/0411-Prevent-teleporting-dead-entities.patch create mode 100644 patches/server-unmapped/0412-Validate-tripwire-hook-placement-before-update.patch create mode 100644 patches/server-unmapped/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch create mode 100644 patches/server-unmapped/0414-Configurable-chance-of-villager-zombie-infection.patch create mode 100644 patches/server-unmapped/0415-Optimise-Chunk-getFluid.patch create mode 100644 patches/server-unmapped/0416-Optimise-TickListServer-by-rewriting-it.patch create mode 100644 patches/server-unmapped/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch create mode 100644 patches/server-unmapped/0418-Ensure-Entity-is-never-double-registered.patch create mode 100644 patches/server-unmapped/0419-Fix-unregistering-entities-from-unloading-chunks.patch create mode 100644 patches/server-unmapped/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch create mode 100644 patches/server-unmapped/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch create mode 100644 patches/server-unmapped/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch create mode 100644 patches/server-unmapped/0423-Optimize-Collision-to-not-load-chunks.patch create mode 100644 patches/server-unmapped/0424-Don-t-tick-dead-players.patch create mode 100644 patches/server-unmapped/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch create mode 100644 patches/server-unmapped/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch create mode 100644 patches/server-unmapped/0427-Increase-Light-Queue-Size.patch create mode 100644 patches/server-unmapped/0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch create mode 100644 patches/server-unmapped/0429-Don-t-move-existing-players-to-world-spawn.patch create mode 100644 patches/server-unmapped/0430-Add-tick-times-API-and-mspt-command.patch create mode 100644 patches/server-unmapped/0431-Expose-MinecraftServer-isRunning.patch create mode 100644 patches/server-unmapped/0432-Add-Raw-Byte-ItemStack-Serialization.patch create mode 100644 patches/server-unmapped/0433-Remove-streams-from-Mob-AI-System.patch create mode 100644 patches/server-unmapped/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch create mode 100644 patches/server-unmapped/0435-Async-command-map-building.patch create mode 100644 patches/server-unmapped/0436-Improved-Watchdog-Support.patch create mode 100644 patches/server-unmapped/0437-Optimize-Pathfinding.patch create mode 100644 patches/server-unmapped/0438-Reduce-Either-Optional-allocation.patch create mode 100644 patches/server-unmapped/0439-Remove-streams-from-PairedQueue.patch create mode 100644 patches/server-unmapped/0440-Reduce-memory-footprint-of-NBTTagCompound.patch create mode 100644 patches/server-unmapped/0441-Prevent-opening-inventories-when-frozen.patch create mode 100644 patches/server-unmapped/0442-Optimise-ArraySetSorted-removeIf.patch create mode 100644 patches/server-unmapped/0443-Don-t-run-entity-collision-code-if-not-needed.patch create mode 100644 patches/server-unmapped/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch create mode 100644 patches/server-unmapped/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch create mode 100644 patches/server-unmapped/0446-Implement-Player-Client-Options-API.patch create mode 100644 patches/server-unmapped/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch create mode 100644 patches/server-unmapped/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch create mode 100644 patches/server-unmapped/0449-Broadcast-join-message-to-console.patch create mode 100644 patches/server-unmapped/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch create mode 100644 patches/server-unmapped/0451-Load-Chunks-for-Login-Asynchronously.patch create mode 100644 patches/server-unmapped/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch create mode 100644 patches/server-unmapped/0453-Add-PlayerAttackEntityCooldownResetEvent.patch create mode 100644 patches/server-unmapped/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch create mode 100644 patches/server-unmapped/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch create mode 100644 patches/server-unmapped/0456-Add-phantom-creative-and-insomniac-controls.patch create mode 100644 patches/server-unmapped/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch create mode 100644 patches/server-unmapped/0458-Implement-Brigadier-Mojang-API.patch create mode 100644 patches/server-unmapped/0459-Villager-Restocks-API.patch create mode 100644 patches/server-unmapped/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch create mode 100644 patches/server-unmapped/0461-Expose-game-version.patch create mode 100644 patches/server-unmapped/0462-Optimize-Voxel-Shape-Merging.patch create mode 100644 patches/server-unmapped/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch create mode 100644 patches/server-unmapped/0464-Implement-Mob-Goal-API.patch create mode 100644 patches/server-unmapped/0465-Use-distance-map-to-optimise-entity-tracker.patch create mode 100644 patches/server-unmapped/0466-Optimize-isOutsideRange-to-use-distance-maps.patch create mode 100644 patches/server-unmapped/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch create mode 100644 patches/server-unmapped/0468-No-Tick-view-distance-implementation.patch create mode 100644 patches/server-unmapped/0469-Add-villager-reputation-API.patch create mode 100644 patches/server-unmapped/0470-Fix-Light-Command.patch create mode 100644 patches/server-unmapped/0471-Fix-PotionEffect-ignores-icon-flag.patch create mode 100644 patches/server-unmapped/0472-Optimize-brigadier-child-sorting-performance.patch create mode 100644 patches/server-unmapped/0473-Potential-bed-API.patch create mode 100644 patches/server-unmapped/0474-Wait-for-Async-Tasks-during-shutdown.patch create mode 100644 patches/server-unmapped/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch create mode 100644 patches/server-unmapped/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch create mode 100644 patches/server-unmapped/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch create mode 100644 patches/server-unmapped/0478-Reduce-MutableInt-allocations-from-light-engine.patch create mode 100644 patches/server-unmapped/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch create mode 100644 patches/server-unmapped/0480-Ensure-safe-gateway-teleport.patch create mode 100644 patches/server-unmapped/0481-Add-option-for-console-having-all-permissions.patch create mode 100644 patches/server-unmapped/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch create mode 100644 patches/server-unmapped/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch create mode 100644 patches/server-unmapped/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch create mode 100644 patches/server-unmapped/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch create mode 100644 patches/server-unmapped/0486-Improve-Chunk-Status-Transition-Speed.patch create mode 100644 patches/server-unmapped/0487-Fix-villager-trading-demand-MC-163962.patch create mode 100644 patches/server-unmapped/0488-Maps-shouldn-t-load-chunks.patch create mode 100644 patches/server-unmapped/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch create mode 100644 patches/server-unmapped/0490-Optimize-Bit-Operations-by-inlining.patch create mode 100644 patches/server-unmapped/0491-Optimize-Light-Engine.patch create mode 100644 patches/server-unmapped/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch create mode 100644 patches/server-unmapped/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch create mode 100644 patches/server-unmapped/0494-Fix-missing-chunks-due-to-integer-overflow.patch create mode 100644 patches/server-unmapped/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch create mode 100644 patches/server-unmapped/0496-Fix-piston-physics-inconsistency-MC-188840.patch create mode 100644 patches/server-unmapped/0497-Fix-sand-duping.patch create mode 100644 patches/server-unmapped/0498-Prevent-position-desync-in-playerconnection-causing-.patch create mode 100644 patches/server-unmapped/0499-Fix-enderdragon-exp-dupe.patch create mode 100644 patches/server-unmapped/0500-Inventory-getHolder-method-without-block-snapshot.patch create mode 100644 patches/server-unmapped/0501-Expose-Arrow-getItemStack.patch create mode 100644 patches/server-unmapped/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch create mode 100644 patches/server-unmapped/0503-Hide-sync-chunk-writes-behind-flag.patch create mode 100644 patches/server-unmapped/0504-Limit-lightning-strike-effect-distance.patch create mode 100644 patches/server-unmapped/0505-Add-permission-for-command-blocks.patch create mode 100644 patches/server-unmapped/0506-Ensure-Entity-AABB-s-are-never-invalid.patch create mode 100644 patches/server-unmapped/0507-Optimize-WorldBorder-collision-checks-and-air.patch create mode 100644 patches/server-unmapped/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch create mode 100644 patches/server-unmapped/0509-Paper-dumpitem-command.patch create mode 100644 patches/server-unmapped/0510-Don-t-allow-null-UUID-s-for-chat.patch create mode 100644 patches/server-unmapped/0511-Improve-Legacy-Component-serialization-size.patch create mode 100644 patches/server-unmapped/0512-Support-old-UUID-format-for-NBT.patch create mode 100644 patches/server-unmapped/0513-Clean-up-duplicated-GameProfile-Properties.patch create mode 100644 patches/server-unmapped/0514-Convert-legacy-attributes-in-Item-Meta.patch create mode 100644 patches/server-unmapped/0515-Remove-some-streams-from-structures.patch create mode 100644 patches/server-unmapped/0516-Remove-streams-from-classes-related-villager-gossip.patch create mode 100644 patches/server-unmapped/0517-Support-components-in-ItemMeta.patch create mode 100644 patches/server-unmapped/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch create mode 100644 patches/server-unmapped/0519-Add-entity-liquid-API.patch create mode 100644 patches/server-unmapped/0520-Update-itemstack-legacy-name-and-lore.patch create mode 100644 patches/server-unmapped/0521-Spawn-player-in-correct-world-on-login.patch create mode 100644 patches/server-unmapped/0522-Add-PrepareResultEvent.patch create mode 100644 patches/server-unmapped/0523-Allow-delegation-to-vanilla-chunk-gen.patch create mode 100644 patches/server-unmapped/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch create mode 100644 patches/server-unmapped/0525-Optimize-NetworkManager-Exception-Handling.patch create mode 100644 patches/server-unmapped/0526-Fix-Concurrency-issue-in-WeightedList.patch create mode 100644 patches/server-unmapped/0527-Optimize-the-advancement-data-player-iteration-to-be.patch create mode 100644 patches/server-unmapped/0528-Fix-arrows-never-despawning-MC-125757.patch create mode 100644 patches/server-unmapped/0529-Thread-Safe-Vanilla-Command-permission-checking.patch create mode 100644 patches/server-unmapped/0530-Move-range-check-for-block-placing-up.patch create mode 100644 patches/server-unmapped/0531-Fix-SPIGOT-5989.patch create mode 100644 patches/server-unmapped/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch create mode 100644 patches/server-unmapped/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch create mode 100644 patches/server-unmapped/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch create mode 100644 patches/server-unmapped/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch create mode 100644 patches/server-unmapped/0536-Fix-some-rails-connecting-improperly.patch create mode 100644 patches/server-unmapped/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch create mode 100644 patches/server-unmapped/0538-Incremental-player-saving.patch create mode 100644 patches/server-unmapped/0539-Import-fastutil-classes.patch create mode 100644 patches/server-unmapped/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch create mode 100644 patches/server-unmapped/0541-Remove-armour-stand-double-add-to-world.patch create mode 100644 patches/server-unmapped/0542-Fix-MC-187716-Use-configured-height.patch create mode 100644 patches/server-unmapped/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch create mode 100644 patches/server-unmapped/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch create mode 100644 patches/server-unmapped/0545-Brand-support.patch create mode 100644 patches/server-unmapped/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch create mode 100644 patches/server-unmapped/0547-Fix-MC-197271.patch create mode 100644 patches/server-unmapped/0548-MC-197883-Bandaid-decode-issue.patch create mode 100644 patches/server-unmapped/0549-Add-setMaxPlayers-API.patch create mode 100644 patches/server-unmapped/0550-Add-playPickupItemAnimation-to-LivingEntity.patch create mode 100644 patches/server-unmapped/0551-Don-t-require-FACING-data.patch create mode 100644 patches/server-unmapped/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch create mode 100644 patches/server-unmapped/0553-Add-moon-phase-API.patch create mode 100644 patches/server-unmapped/0554-Prevent-headless-pistons-from-being-created.patch create mode 100644 patches/server-unmapped/0555-Add-BellRingEvent.patch create mode 100644 patches/server-unmapped/0556-Add-zombie-targets-turtle-egg-config.patch create mode 100644 patches/server-unmapped/0557-Buffer-joins-to-world.patch create mode 100644 patches/server-unmapped/0558-Optimize-redstone-algorithm.patch create mode 100644 patches/server-unmapped/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch create mode 100644 patches/server-unmapped/0560-PortalCreateEvent-needs-to-know-its-entity.patch create mode 100644 patches/server-unmapped/0561-Fix-CraftTeam-null-check.patch create mode 100644 patches/server-unmapped/0562-Add-more-Evoker-API.patch create mode 100644 patches/server-unmapped/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch create mode 100644 patches/server-unmapped/0564-Create-HoverEvent-from-ItemStack-Entity.patch create mode 100644 patches/server-unmapped/0565-Cache-block-data-strings.patch create mode 100644 patches/server-unmapped/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch create mode 100644 patches/server-unmapped/0567-Add-additional-open-container-api-to-HumanEntity.patch create mode 100644 patches/server-unmapped/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch create mode 100644 patches/server-unmapped/0569-Extend-block-drop-capture-to-capture-all-items-added.patch create mode 100644 patches/server-unmapped/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch create mode 100644 patches/server-unmapped/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch create mode 100644 patches/server-unmapped/0572-Lazily-track-plugin-scoreboards-by-default.patch create mode 100644 patches/server-unmapped/0573-Entity-isTicking.patch create mode 100644 patches/server-unmapped/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch create mode 100644 patches/server-unmapped/0575-Fix-Not-a-string-Map-Conversion-spam.patch create mode 100644 patches/server-unmapped/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch create mode 100644 patches/server-unmapped/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch create mode 100644 patches/server-unmapped/0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch create mode 100644 patches/server-unmapped/0579-Fix-for-large-move-vectors-crashing-server.patch create mode 100644 patches/server-unmapped/0580-Optimise-getType-calls.patch create mode 100644 patches/server-unmapped/0581-Villager-resetOffers.patch create mode 100644 patches/server-unmapped/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch create mode 100644 patches/server-unmapped/0583-Retain-block-place-order-when-capturing-blockstates.patch create mode 100644 patches/server-unmapped/0584-Reduce-blockpos-allocation-from-pathfinding.patch create mode 100644 patches/server-unmapped/0585-Fix-item-locations-dropped-from-campfires.patch create mode 100644 patches/server-unmapped/0586-Player-elytra-boost-API.patch create mode 100644 patches/server-unmapped/0587-Fixed-TileEntityBell-memory-leak.patch create mode 100644 patches/server-unmapped/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch create mode 100644 patches/server-unmapped/0589-Add-getOfflinePlayerIfCached-String.patch create mode 100644 patches/server-unmapped/0590-Add-ignore-discounts-API.patch create mode 100644 patches/server-unmapped/0591-Toggle-for-removing-existing-dragon.patch create mode 100644 patches/server-unmapped/0592-Fix-client-lag-on-advancement-loading.patch create mode 100644 patches/server-unmapped/0593-Item-no-age-no-player-pickup.patch create mode 100644 patches/server-unmapped/0594-Beacon-API-custom-effect-ranges.patch create mode 100644 patches/server-unmapped/0595-Add-API-for-quit-reason.patch create mode 100644 patches/server-unmapped/0596-Seed-based-feature-search.patch create mode 100644 patches/server-unmapped/0597-Add-Wandering-Trader-spawn-rate-config-options.patch create mode 100644 patches/server-unmapped/0598-Significantly-improve-performance-of-the-end-generat.patch create mode 100644 patches/server-unmapped/0599-Expose-world-spawn-angle.patch create mode 100644 patches/server-unmapped/0600-Add-Destroy-Speed-API.patch create mode 100644 patches/server-unmapped/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch create mode 100644 patches/server-unmapped/0602-Add-LivingEntity-clearActiveItem.patch create mode 100644 patches/server-unmapped/0603-Add-PlayerItemCooldownEvent.patch create mode 100644 patches/server-unmapped/0604-More-lightning-API.patch create mode 100644 patches/server-unmapped/0605-Climbing-should-not-bypass-cramming-gamerule.patch create mode 100644 patches/server-unmapped/0606-Added-missing-default-perms-for-commands.patch create mode 100644 patches/server-unmapped/0607-Add-PlayerShearBlockEvent.patch create mode 100644 patches/server-unmapped/0608-Add-warning-for-servers-not-running-on-Java-16.patch create mode 100644 patches/server-unmapped/0609-Set-spigots-verbose-world-setting-to-false-by-def.patch create mode 100644 patches/server-unmapped/0610-Fix-curing-zombie-villager-discount-exploit.patch create mode 100644 patches/server-unmapped/0611-Limit-recipe-packets.patch create mode 100644 patches/server-unmapped/0612-Fix-CraftSound-backwards-compatibility.patch create mode 100644 patches/server-unmapped/0613-MC-4-Fix-item-position-desync.patch create mode 100644 patches/server-unmapped/0614-Player-Chunk-Load-Unload-Events.patch create mode 100644 patches/server-unmapped/0615-Optimize-Dynamic-get-Missing-Keys.patch create mode 100644 patches/server-unmapped/0616-Expose-LivingEntity-hurt-direction.patch create mode 100644 patches/server-unmapped/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch create mode 100644 patches/server-unmapped/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch create mode 100644 patches/server-unmapped/0619-added-PlayerTradeEvent.patch create mode 100644 patches/server-unmapped/0620-Implement-TargetHitEvent.patch create mode 100644 patches/server-unmapped/0621-Additional-Block-Material-API-s.patch create mode 100644 patches/server-unmapped/0622-Fix-harming-potion-dupe.patch create mode 100644 patches/server-unmapped/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch create mode 100644 patches/server-unmapped/0624-Optimized-tick-ready-check.patch create mode 100644 patches/server-unmapped/0625-Cache-burn-durations.patch create mode 100644 patches/server-unmapped/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch create mode 100644 patches/server-unmapped/0627-Implement-PlayerFlowerPotManipulateEvent.patch create mode 100644 patches/server-unmapped/0628-Fix-interact-event-not-being-called-in-adventure.patch create mode 100644 patches/server-unmapped/0629-Zombie-API-breaking-doors.patch create mode 100644 patches/server-unmapped/0630-Fix-nerfed-slime-when-splitting.patch create mode 100644 patches/server-unmapped/0631-Add-EntityLoadCrossbowEvent.patch create mode 100644 patches/server-unmapped/0632-Guardian-beam-workaround.patch create mode 100644 patches/server-unmapped/0633-Added-WorldGameRuleChangeEvent.patch create mode 100644 patches/server-unmapped/0634-Added-ServerResourcesReloadedEvent.patch create mode 100644 patches/server-unmapped/0635-Added-world-settings-for-mobs-picking-up-loot.patch create mode 100644 patches/server-unmapped/0636-Implemented-BlockFailedDispenseEvent.patch create mode 100644 patches/server-unmapped/0637-Added-PlayerLecternPageChangeEvent.patch create mode 100644 patches/server-unmapped/0638-Fire-event-on-GS4-query.patch create mode 100644 patches/server-unmapped/0639-Added-PlayerLoomPatternSelectEvent.patch create mode 100644 patches/server-unmapped/0640-Configurable-door-breaking-difficulty.patch create mode 100644 patches/server-unmapped/0641-Empty-commands-shall-not-be-dispatched.patch create mode 100644 patches/server-unmapped/0642-Implement-API-to-expose-exact-interaction-point.patch create mode 100644 patches/server-unmapped/0643-Remove-stale-POIs.patch create mode 100644 patches/server-unmapped/0644-Fix-villager-boat-exploit.patch create mode 100644 patches/server-unmapped/0645-Entity-load-save-limit-per-chunk.patch create mode 100644 patches/server-unmapped/0646-Add-sendOpLevel-API.patch create mode 100644 patches/server-unmapped/0647-Add-StructureLocateEvent.patch create mode 100644 patches/server-unmapped/0648-Collision-option-for-requiring-a-player-participant.patch create mode 100644 patches/server-unmapped/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch create mode 100644 patches/server-unmapped/0650-Return-chat-component-with-empty-text-instead-of-thr.patch create mode 100644 patches/server-unmapped/0651-Make-schedule-command-per-world.patch create mode 100644 patches/server-unmapped/0652-Configurable-max-leash-distance.patch create mode 100644 patches/server-unmapped/0653-Implement-BlockPreDispenseEvent.patch create mode 100644 patches/server-unmapped/0654-Added-Vanilla-Entity-Tags.patch create mode 100644 patches/server-unmapped/0655-added-Wither-API.patch create mode 100644 patches/server-unmapped/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch create mode 100644 patches/server-unmapped/0657-Fix-console-spam-when-removing-chests-in-water.patch create mode 100644 patches/server-unmapped/0658-Add-toggle-for-always-placing-the-dragon-egg.patch create mode 100644 patches/server-unmapped/0659-Added-PlayerStonecutterRecipeSelectEvent.patch create mode 100644 patches/server-unmapped/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch create mode 100644 patches/server-unmapped/0661-Skip-distance-map-update-when-spawning-disabled.patch create mode 100644 patches/server-unmapped/0662-Reset-shield-blocking-on-dimension-change.patch create mode 100644 patches/server-unmapped/0663-add-DragonEggFormEvent.patch create mode 100644 patches/server-unmapped/0664-EntityMoveEvent.patch create mode 100644 patches/server-unmapped/0665-added-option-to-disable-pathfinding-updates-on-block.patch create mode 100644 patches/server-unmapped/0666-Inline-shift-direction-fields.patch create mode 100644 patches/server-unmapped/0667-Allow-adding-items-to-BlockDropItemEvent.patch create mode 100644 patches/server-unmapped/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch create mode 100644 patches/server-unmapped/0669-living-entity-allow-attribute-registration.patch create mode 100644 patches/server-unmapped/0670-fix-dead-slime-setSize-invincibility.patch create mode 100644 patches/server-unmapped/0671-Merchant-getRecipes-should-return-an-immutable-list.patch create mode 100644 patches/server-unmapped/0672-misc-debugging-dumps.patch create mode 100644 patches/server-unmapped/0673-Add-support-for-hex-color-codes-in-console.patch create mode 100644 patches/server-unmapped/0674-Clear-SyncLoadInfo.patch create mode 100644 patches/server-unmapped/0675-Expose-Tracked-Players.patch create mode 100644 patches/server-unmapped/0676-Remove-streams-from-SensorNearest.patch create mode 100644 patches/server-unmapped/0677-do-not-create-unnecessary-copies-of-passenger-list.patch create mode 100644 patches/server-unmapped/0678-MC-29274-Fix-Wither-hostility-towards-players.patch create mode 100644 patches/server-unmapped/0679-Throw-proper-exception-on-empty-JsonList-file.patch create mode 100644 patches/server-unmapped/0680-Improve-ServerGUI.patch create mode 100644 patches/server-unmapped/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch create mode 100644 patches/server-unmapped/0682-fix-converting-txt-to-json-file.patch create mode 100644 patches/server-unmapped/0683-Add-worldborder-events.patch create mode 100644 patches/server-unmapped/0684-added-PlayerNameEntityEvent.patch create mode 100644 patches/server-unmapped/0685-Prevent-grindstones-from-overstacking-items.patch create mode 100644 patches/server-unmapped/0686-Add-recipe-to-cook-events.patch create mode 100644 patches/server-unmapped/0687-Add-Block-isValidTool.patch create mode 100644 patches/server-unmapped/0688-Allow-using-signs-inside-spawn-protection.patch create mode 100644 patches/server-unmapped/0689-Implement-Keyed-on-World.patch create mode 100644 patches/server-unmapped/0690-Add-fast-alternative-constructor-for-Vector3f.patch create mode 100644 patches/server-unmapped/0691-Item-Rarity-API.patch create mode 100644 patches/server-unmapped/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch create mode 100644 patches/server-unmapped/0693-copy-TESign-isEditable-from-snapshots.patch create mode 100644 patches/server-unmapped/0694-Drop-carried-item-when-player-has-disconnected.patch create mode 100644 patches/server-unmapped/0695-forced-whitelist-use-configurable-kick-message.patch create mode 100644 patches/server-unmapped/0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch create mode 100644 patches/server-unmapped/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch create mode 100644 patches/server-unmapped/0698-fix-cancelling-block-falling-causing-client-desync.patch create mode 100644 patches/server-unmapped/0699-Expose-protocol-version.patch create mode 100644 patches/server-unmapped/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch create mode 100644 patches/server-unmapped/0701-Enhance-console-tab-completions-for-brigadier-comman.patch create mode 100644 patches/server-unmapped/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch create mode 100644 patches/server-unmapped/0703-Add-bypass-host-check.patch create mode 100644 patches/server-unmapped/0704-don-t-throw-when-loading-invalid-TEs.patch create mode 100644 patches/server-unmapped/0705-Set-area-affect-cloud-rotation.patch create mode 100644 patches/server-unmapped/0706-add-isDeeplySleeping-to-HumanEntity.patch create mode 100644 patches/server-unmapped/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch create mode 100644 patches/server-unmapped/0708-add-consumeFuel-to-FurnaceBurnEvent.patch create mode 100644 patches/server-unmapped/0709-add-get-set-drop-chance-to-EntityEquipment.patch create mode 100644 patches/server-unmapped/0710-fix-PigZombieAngerEvent-cancellation.patch create mode 100644 patches/server-unmapped/0711-Fix-checkReach-check-for-Shulker-boxes.patch create mode 100644 patches/server-unmapped/0712-fix-PlayerItemHeldEvent-firing-twice.patch create mode 100644 patches/server-unmapped/0713-Added-PlayerDeepSleepEvent.patch create mode 100644 patches/server-unmapped/0714-More-World-API.patch create mode 100644 patches/server-unmapped/0715-Added-PlayerBedFailEnterEvent.patch create mode 100644 patches/server-unmapped/0716-Implement-methods-to-convert-between-Component-and-B.patch create mode 100644 patches/server-unmapped/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch create mode 100644 patches/server-unmapped/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch create mode 100644 patches/server-unmapped/0719-Introduce-beacon-activation-deactivation-events.patch create mode 100644 patches/server-unmapped/0720-Add-Channel-initialization-listeners.patch create mode 100644 patches/server-unmapped/0721-Send-empty-commands-if-tab-completion-is-disabled.patch create mode 100644 patches/server-unmapped/0722-Add-more-WanderingTrader-API.patch create mode 100644 patches/server-unmapped/0723-Add-EntityBlockStorage-clearEntities.patch create mode 100644 patches/server-unmapped/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch create mode 100644 patches/server-unmapped/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch create mode 100644 patches/server-unmapped/0726-Inventory-close.patch create mode 100644 patches/server-unmapped/0727-call-PortalCreateEvent-players-and-end-platform.patch create mode 100644 patches/server-unmapped/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch create mode 100644 patches/server-unmapped/0729-Fix-CraftPotionBrewer-cache.patch create mode 100644 patches/server-unmapped/0730-Add-basic-Datapack-API.patch create mode 100644 patches/server-unmapped/0731-Add-environment-variable-to-disable-server-gui.patch create mode 100644 patches/server-unmapped/0732-additions-to-PlayerGameModeChangeEvent.patch create mode 100644 patches/server-unmapped/0733-ItemStack-repair-check-API.patch create mode 100644 patches/server-unmapped/0734-More-Enchantment-API.patch create mode 100644 patches/server-unmapped/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch create mode 100644 patches/server-unmapped/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch create mode 100644 patches/server-unmapped/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch create mode 100644 patches/server-unmapped/0738-Fix-and-optimise-world-force-upgrading.patch create mode 100644 patches/server-unmapped/0739-Add-Mob-lookAt-API.patch create mode 100644 patches/server-unmapped/0740-Add-Unix-domain-socket-support.patch create mode 100644 patches/server-unmapped/0741-Add-EntityInsideBlockEvent.patch create mode 100644 patches/server-unmapped/0742-Attributes-API-for-item-defaults.patch create mode 100644 patches/server-unmapped/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch create mode 100644 patches/server-unmapped/0744-Add-cause-to-Weather-ThunderChangeEvents.patch create mode 100644 patches/server-unmapped/0745-More-Lidded-Block-API.patch create mode 100644 patches/server-unmapped/0746-Add-PlayerKickEvent-causes.patch create mode 100644 patches/server-unmapped/0747-Limit-item-frame-cursors-on-maps.patch create mode 100644 patches/server-unmapped/0748-Add-PufferFishStateChangeEvent.patch create mode 100644 patches/server-unmapped/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch create mode 100644 patches/server-unmapped/0750-Add-option-to-fix-items-merging-through-walls.patch create mode 100644 patches/server-unmapped/0751-Add-BellRevealRaiderEvent.patch create mode 100644 patches/server-unmapped/0752-Fix-invulnerable-end-crystals.patch create mode 100644 patches/server-unmapped/0753-Add-ElderGuardianAppearanceEvent.patch create mode 100644 patches/server-unmapped/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch create mode 100644 patches/server-unmapped/0755-Fix-dangerous-end-portal-logic.patch create mode 100644 patches/server-unmapped/0756-Make-item-validations-configurable.patch create mode 100644 patches/server-unmapped/0757-Add-more-line-of-sight-methods.patch create mode 100644 patches/server-unmapped/0758-add-per-world-spawn-limits.patch create mode 100644 patches/server-unmapped/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch create mode 100644 patches/server/0001-Setup-Gradle-project.patch create mode 100644 patches/server/0002-Decompile-fixes.patch diff --git a/build.gradle.kts b/build.gradle.kts index 0de5a09f47..0687edd2a5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -74,6 +74,9 @@ paperweight { serverProject.set(project(":Paper-Server")) paper { + spigotApiPatchDir.set(file("patches/api")) + spigotServerPatchDir.set(file("patches/server")) + mappingsPatch.set(file("build-data/mappings-patch.tiny")) additionalSpigotMemberMappings.set(file("build-data/additional-spigot-member-mappings.csrg")) diff --git a/patches/api-unmapped/0001-POM-changes.patch b/patches/api-unmapped/0001-POM-changes.patch new file mode 100644 index 0000000000..b6c98e0a08 --- /dev/null +++ b/patches/api-unmapped/0001-POM-changes.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 00:16:08 +0100 +Subject: [PATCH] POM changes + + +diff --git a/pom.xml b/pom.xml +index debe5bd7adb1f41e8a6878a8545de4bfcad1a590..d7cf64f05d0a2f5b186ca13b2b88e390abe84226 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -2,33 +2,34 @@ + + 4.0.0 ++ ++ com.destroystokyo.paper ++ paper-parent ++ dev-SNAPSHOT ++ + +- org.spigotmc +- spigot-api ++ com.destroystokyo.paper ++ paper-api + 1.17-R0.1-SNAPSHOT + jar + +- Spigot-API +- https://www.spigotmc.org/ ++ Paper-API ++ https://github.com/PaperMC/Paper + An enhanced plugin API for Minecraft servers. + + +- true ++ + 1.8 + 1.8 + UTF-8 + + +- ++ + +- spigotmc-releases +- https://hub.spigotmc.org/nexus/content/repositories/releases/ ++ sonatype ++ https://oss.sonatype.org/content/groups/public/ + +- +- spigotmc-snapshots +- https://hub.spigotmc.org/nexus/content/repositories/snapshots/ +- +- ++ + + + +@@ -37,6 +38,20 @@ + 2.6 + compile + ++ ++ ++ com.google.code.findbugs ++ jsr305 ++ 1.3.9 ++ compile ++ ++ ++ ++ com.googlecode.json-simple ++ json-simple ++ 1.1.1 ++ compile ++ + + + com.google.guava +@@ -112,6 +127,7 @@ + + + ++ clean install + + + net.md-5 +@@ -130,10 +146,6 @@ + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 +- +- +- eclipse +- + + + org.codehaus.plexus +@@ -183,6 +195,7 @@ + + + ++ ${project.build.directory}/dependency-reduced-pom.xml + + true + diff --git a/patches/api-unmapped/0002-Add-FastUtil-to-Bukkit.patch b/patches/api-unmapped/0002-Add-FastUtil-to-Bukkit.patch new file mode 100644 index 0000000000..a5e6eda88d --- /dev/null +++ b/patches/api-unmapped/0002-Add-FastUtil-to-Bukkit.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 1 Apr 2016 00:02:47 -0400 +Subject: [PATCH] Add FastUtil to Bukkit + +Doesn't expose to plugins, just allows Paper-API to use it for optimization + +diff --git a/pom.xml b/pom.xml +index 61b8ee4e3e122dd2671f50ea3b432e4abd4600a2..12306d830c6889c2c9b12699abebe0411262aef6 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -32,6 +32,12 @@ + + + ++ ++ it.unimi.dsi ++ fastutil ++ 8.2.2 ++ provided ++ + + commons-lang + commons-lang diff --git a/patches/api-unmapped/0003-Paper-Utils.patch b/patches/api-unmapped/0003-Paper-Utils.patch new file mode 100644 index 0000000000..a647b698ad --- /dev/null +++ b/patches/api-unmapped/0003-Paper-Utils.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 23 Feb 2019 11:26:21 -0500 +Subject: [PATCH] Paper Utils + + +diff --git a/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java b/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9db0056ab94145819628b3ad8d8d26130d117fcf +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java +@@ -0,0 +1,16 @@ ++package com.destroystokyo.paper.util; ++ ++import org.jetbrains.annotations.NotNull; ++ ++public class SneakyThrow { ++ ++ public static void sneaky(@NotNull Throwable exception) { ++ SneakyThrow.throwSneaky(exception); ++ } ++ ++ @SuppressWarnings("unchecked") ++ private static void throwSneaky(@NotNull Throwable exception) throws T { ++ throw (T) exception; ++ } ++ ++} diff --git a/patches/api-unmapped/0004-Timings-v2.patch b/patches/api-unmapped/0004-Timings-v2.patch new file mode 100644 index 0000000000..9cfffce81e --- /dev/null +++ b/patches/api-unmapped/0004-Timings-v2.patch @@ -0,0 +1,3759 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 29 Feb 2016 18:48:17 -0600 +Subject: [PATCH] Timings v2 + + +diff --git a/src/main/java/co/aikar/timings/FullServerTickHandler.java b/src/main/java/co/aikar/timings/FullServerTickHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..dfaa266ff53e43ad48dc5a5a5657fe70600f539a +--- /dev/null ++++ b/src/main/java/co/aikar/timings/FullServerTickHandler.java +@@ -0,0 +1,85 @@ ++package co.aikar.timings; ++ ++import static co.aikar.timings.TimingsManager.*; ++ ++import org.bukkit.Bukkit; ++import org.jetbrains.annotations.NotNull; ++ ++public class FullServerTickHandler extends TimingHandler { ++ private static final TimingIdentifier IDENTITY = new TimingIdentifier("Minecraft", "Full Server Tick", null); ++ final TimingData minuteData; ++ double avgFreeMemory = -1D; ++ double avgUsedMemory = -1D; ++ FullServerTickHandler() { ++ super(IDENTITY); ++ minuteData = new TimingData(id); ++ ++ TIMING_MAP.put(IDENTITY, this); ++ } ++ ++ @NotNull ++ @Override ++ public Timing startTiming() { ++ if (TimingsManager.needsFullReset) { ++ TimingsManager.resetTimings(); ++ } else if (TimingsManager.needsRecheckEnabled) { ++ TimingsManager.recheckEnabled(); ++ } ++ return super.startTiming(); ++ } ++ ++ @Override ++ public void stopTiming() { ++ super.stopTiming(); ++ if (!isEnabled() || Bukkit.isStopping()) { ++ return; ++ } ++ if (TimingHistory.timedTicks % 20 == 0) { ++ final Runtime runtime = Runtime.getRuntime(); ++ double usedMemory = runtime.totalMemory() - runtime.freeMemory(); ++ double freeMemory = runtime.maxMemory() - usedMemory; ++ if (this.avgFreeMemory == -1) { ++ this.avgFreeMemory = freeMemory; ++ } else { ++ this.avgFreeMemory = (this.avgFreeMemory * (59 / 60D)) + (freeMemory * (1 / 60D)); ++ } ++ ++ if (this.avgUsedMemory == -1) { ++ this.avgUsedMemory = usedMemory; ++ } else { ++ this.avgUsedMemory = (this.avgUsedMemory * (59 / 60D)) + (usedMemory * (1 / 60D)); ++ } ++ } ++ ++ long start = System.nanoTime(); ++ TimingsManager.tick(); ++ long diff = System.nanoTime() - start; ++ TIMINGS_TICK.addDiff(diff, null); ++ // addDiff for TIMINGS_TICK incremented this, bring it back down to 1 per tick. ++ record.setCurTickCount(record.getCurTickCount()-1); ++ ++ minuteData.setCurTickTotal(record.getCurTickTotal()); ++ minuteData.setCurTickCount(1); ++ ++ boolean violated = isViolated(); ++ minuteData.processTick(violated); ++ TIMINGS_TICK.processTick(violated); ++ processTick(violated); ++ ++ ++ if (TimingHistory.timedTicks % 1200 == 0) { ++ MINUTE_REPORTS.add(new TimingHistory.MinuteReport()); ++ TimingHistory.resetTicks(false); ++ minuteData.reset(); ++ } ++ if (TimingHistory.timedTicks % Timings.getHistoryInterval() == 0) { ++ TimingsManager.HISTORY.add(new TimingHistory()); ++ TimingsManager.resetTimings(); ++ } ++ Bukkit.getUnsafe().reportTimings(); ++ } ++ ++ boolean isViolated() { ++ return record.getCurTickTotal() > 50000000; ++ } ++} +diff --git a/src/main/java/co/aikar/timings/NullTimingHandler.java b/src/main/java/co/aikar/timings/NullTimingHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9b45ce887b9172f30302b83fe24b99b76b16dac3 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/NullTimingHandler.java +@@ -0,0 +1,68 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++public final class NullTimingHandler implements Timing { ++ public static final Timing NULL = new NullTimingHandler(); ++ @NotNull ++ @Override ++ public Timing startTiming() { ++ return this; ++ } ++ ++ @Override ++ public void stopTiming() { ++ ++ } ++ ++ @NotNull ++ @Override ++ public Timing startTimingIfSync() { ++ return this; ++ } ++ ++ @Override ++ public void stopTimingIfSync() { ++ ++ } ++ ++ @Override ++ public void abort() { ++ ++ } ++ ++ @Nullable ++ @Override ++ public TimingHandler getTimingHandler() { ++ return null; ++ } ++ ++ @Override ++ public void close() { ++ ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimedEventExecutor.java b/src/main/java/co/aikar/timings/TimedEventExecutor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4e6e1b8e8aeb07e34536941d2cbfc25e5cfa6c27 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimedEventExecutor.java +@@ -0,0 +1,83 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.event.Event; ++import org.bukkit.event.EventException; ++import org.bukkit.event.Listener; ++import org.bukkit.plugin.EventExecutor; ++import org.bukkit.plugin.Plugin; ++ ++import java.lang.reflect.Method; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++public class TimedEventExecutor implements EventExecutor { ++ ++ private final EventExecutor executor; ++ private final Timing timings; ++ ++ /** ++ * Wraps an event executor and associates a timing handler to it. ++ * ++ * @param executor Executor to wrap ++ * @param plugin Owning plugin ++ * @param method EventHandler method ++ * @param eventClass Owning class ++ */ ++ public TimedEventExecutor(@NotNull EventExecutor executor, @NotNull Plugin plugin, @Nullable Method method, @NotNull Class eventClass) { ++ this.executor = executor; ++ String id; ++ ++ if (method == null) { ++ if (executor.getClass().getEnclosingClass() != null) { // Oh Skript, how we love you ++ method = executor.getClass().getEnclosingMethod(); ++ } ++ } ++ ++ if (method != null) { ++ id = method.getDeclaringClass().getName(); ++ } else { ++ id = executor.getClass().getName(); ++ } ++ ++ ++ final String eventName = eventClass.getSimpleName(); ++ boolean verbose = "BlockPhysicsEvent".equals(eventName); ++ this.timings = Timings.ofSafe(plugin, (verbose ? "## " : "") + ++ "Event: " + id + " (" + eventName + ")"); ++ } ++ ++ @Override ++ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { ++ if (event.isAsynchronous() || !Timings.timingsEnabled || !Bukkit.isPrimaryThread()) { ++ executor.execute(listener, event); ++ return; ++ } ++ try (Timing ignored = timings.startTiming()){ ++ executor.execute(listener, event); ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/timings/Timing.java b/src/main/java/co/aikar/timings/Timing.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a21e5ead5024fd0058c5e3302d8201dd249d32bc +--- /dev/null ++++ b/src/main/java/co/aikar/timings/Timing.java +@@ -0,0 +1,83 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Provides an ability to time sections of code within the Minecraft Server ++ */ ++public interface Timing extends AutoCloseable { ++ /** ++ * Starts timing the execution until {@link #stopTiming()} is called. ++ * ++ * @return Timing ++ */ ++ @NotNull ++ Timing startTiming(); ++ ++ /** ++ *

    Stops timing and records the data. Propagates the data up to group handlers.

    ++ * ++ * Will automatically be called when this Timing is used with try-with-resources ++ */ ++ void stopTiming(); ++ ++ /** ++ * Starts timing the execution until {@link #stopTiming()} is called. ++ * ++ * But only if we are on the primary thread. ++ * ++ * @return Timing ++ */ ++ @NotNull ++ Timing startTimingIfSync(); ++ ++ /** ++ *

    Stops timing and records the data. Propagates the data up to group handlers.

    ++ * ++ *

    Will automatically be called when this Timing is used with try-with-resources

    ++ * ++ * But only if we are on the primary thread. ++ */ ++ void stopTimingIfSync(); ++ ++ /** ++ * @deprecated Doesn't do anything - Removed ++ */ ++ @Deprecated ++ void abort(); ++ ++ /** ++ * Used internally to get the actual backing Handler in the case of delegated Handlers ++ * ++ * @return TimingHandler ++ */ ++ @Nullable ++ TimingHandler getTimingHandler(); ++ ++ @Override ++ void close(); ++} +diff --git a/src/main/java/co/aikar/timings/TimingData.java b/src/main/java/co/aikar/timings/TimingData.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a5d13a1e44edb861f45c83a9b4309fbf799d407d +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingData.java +@@ -0,0 +1,122 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import java.util.List; ++import org.jetbrains.annotations.NotNull; ++ ++import static co.aikar.util.JSONUtil.toArray; ++ ++/** ++ *

    Lightweight object for tracking timing data

    ++ * ++ * This is broken out to reduce memory usage ++ */ ++class TimingData { ++ private final int id; ++ private int count = 0; ++ private int lagCount = 0; ++ private long totalTime = 0; ++ private long lagTotalTime = 0; ++ private int curTickCount = 0; ++ private long curTickTotal = 0; ++ ++ TimingData(int id) { ++ this.id = id; ++ } ++ ++ private TimingData(TimingData data) { ++ this.id = data.id; ++ this.totalTime = data.totalTime; ++ this.lagTotalTime = data.lagTotalTime; ++ this.count = data.count; ++ this.lagCount = data.lagCount; ++ } ++ ++ void add(long diff) { ++ ++curTickCount; ++ curTickTotal += diff; ++ } ++ ++ void processTick(boolean violated) { ++ totalTime += curTickTotal; ++ count += curTickCount; ++ if (violated) { ++ lagTotalTime += curTickTotal; ++ lagCount += curTickCount; ++ } ++ curTickTotal = 0; ++ curTickCount = 0; ++ } ++ ++ void reset() { ++ count = 0; ++ lagCount = 0; ++ curTickTotal = 0; ++ curTickCount = 0; ++ totalTime = 0; ++ lagTotalTime = 0; ++ } ++ ++ protected TimingData clone() { ++ return new TimingData(this); ++ } ++ ++ @NotNull ++ List export() { ++ List list = toArray( ++ id, ++ count, ++ totalTime); ++ if (lagCount > 0) { ++ list.add(lagCount); ++ list.add(lagTotalTime); ++ } ++ return list; ++ } ++ ++ boolean hasData() { ++ return count > 0; ++ } ++ ++ long getTotalTime() { ++ return totalTime; ++ } ++ ++ int getCurTickCount() { ++ return curTickCount; ++ } ++ ++ void setCurTickCount(int curTickCount) { ++ this.curTickCount = curTickCount; ++ } ++ ++ long getCurTickTotal() { ++ return curTickTotal; ++ } ++ ++ void setCurTickTotal(long curTickTotal) { ++ this.curTickTotal = curTickTotal; ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingHandler.java b/src/main/java/co/aikar/timings/TimingHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..199789d56d22fcb1b77ebd56805cc28aa5a5ab0a +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingHandler.java +@@ -0,0 +1,226 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import co.aikar.util.LoadingIntMap; ++import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; ++ ++import java.util.ArrayDeque; ++import java.util.Deque; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++ ++import org.bukkit.Bukkit; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++class TimingHandler implements Timing { ++ ++ private static AtomicInteger idPool = new AtomicInteger(1); ++ private static Deque TIMING_STACK = new ArrayDeque<>(); ++ final int id = idPool.getAndIncrement(); ++ ++ final TimingIdentifier identifier; ++ private final boolean verbose; ++ ++ private final Int2ObjectOpenHashMap children = new LoadingIntMap<>(TimingData::new); ++ ++ final TimingData record; ++ private TimingHandler startParent; ++ private final TimingHandler groupHandler; ++ ++ private long start = 0; ++ private int timingDepth = 0; ++ private boolean added; ++ private boolean timed; ++ private boolean enabled; ++ ++ TimingHandler(@NotNull TimingIdentifier id) { ++ this.identifier = id; ++ this.verbose = id.name.startsWith("##"); ++ this.record = new TimingData(this.id); ++ this.groupHandler = id.groupHandler; ++ ++ TimingIdentifier.getGroup(id.group).handlers.add(this); ++ checkEnabled(); ++ } ++ ++ final void checkEnabled() { ++ enabled = Timings.timingsEnabled && (!verbose || Timings.verboseEnabled); ++ } ++ ++ void processTick(boolean violated) { ++ if (timingDepth != 0 || record.getCurTickCount() == 0) { ++ timingDepth = 0; ++ start = 0; ++ return; ++ } ++ ++ record.processTick(violated); ++ for (TimingData handler : children.values()) { ++ handler.processTick(violated); ++ } ++ } ++ ++ @NotNull ++ @Override ++ public Timing startTimingIfSync() { ++ startTiming(); ++ return this; ++ } ++ ++ @Override ++ public void stopTimingIfSync() { ++ stopTiming(); ++ } ++ ++ @NotNull ++ public Timing startTiming() { ++ if (!enabled || !Bukkit.isPrimaryThread()) { ++ return this; ++ } ++ if (++timingDepth == 1) { ++ startParent = TIMING_STACK.peekLast(); ++ start = System.nanoTime(); ++ } ++ TIMING_STACK.addLast(this); ++ return this; ++ } ++ ++ public void stopTiming() { ++ if (!enabled || timingDepth <= 0 || start == 0 || !Bukkit.isPrimaryThread()) { ++ return; ++ } ++ ++ popTimingStack(); ++ if (--timingDepth == 0) { ++ addDiff(System.nanoTime() - start, startParent); ++ startParent = null; ++ start = 0; ++ } ++ } ++ ++ private void popTimingStack() { ++ TimingHandler last; ++ while ((last = TIMING_STACK.removeLast()) != this) { ++ last.timingDepth = 0; ++ if ("Minecraft".equalsIgnoreCase(last.identifier.group)) { ++ Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Look above this for any errors and report this to Paper unless it has a plugin in the stack trace (" + last.identifier + " did not stopTiming)"); ++ } else { ++ Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Report this to the plugin " + last.identifier.group + " (Look for errors above this in the logs) (" + last.identifier + " did not stopTiming)", new Throwable()); ++ } ++ ++ boolean found = TIMING_STACK.contains(this); ++ if (!found) { ++ // We aren't even in the stack... Don't pop everything ++ TIMING_STACK.addLast(last); ++ break; ++ } ++ } ++ } ++ ++ @Override ++ public final void abort() { ++ ++ } ++ ++ void addDiff(long diff, @Nullable TimingHandler parent) { ++ if (parent != null) { ++ parent.children.get(id).add(diff); ++ } ++ ++ record.add(diff); ++ if (!added) { ++ added = true; ++ timed = true; ++ TimingsManager.HANDLERS.add(this); ++ } ++ if (groupHandler != null) { ++ groupHandler.addDiff(diff, parent); ++ groupHandler.children.get(id).add(diff); ++ } ++ } ++ ++ /** ++ * Reset this timer, setting all values to zero. ++ */ ++ void reset(boolean full) { ++ record.reset(); ++ if (full) { ++ timed = false; ++ } ++ start = 0; ++ timingDepth = 0; ++ added = false; ++ children.clear(); ++ checkEnabled(); ++ } ++ ++ @NotNull ++ @Override ++ public TimingHandler getTimingHandler() { ++ return this; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ return (this == o); ++ } ++ ++ @Override ++ public int hashCode() { ++ return id; ++ } ++ ++ /** ++ * This is simply for the Closeable interface so it can be used with try-with-resources () ++ */ ++ @Override ++ public void close() { ++ stopTimingIfSync(); ++ } ++ ++ public boolean isSpecial() { ++ return this == TimingsManager.FULL_SERVER_TICK || this == TimingsManager.TIMINGS_TICK; ++ } ++ ++ boolean isTimed() { ++ return timed; ++ } ++ ++ public boolean isEnabled() { ++ return enabled; ++ } ++ ++ @NotNull ++ TimingData[] cloneChildren() { ++ final TimingData[] clonedChildren = new TimingData[children.size()]; ++ int i = 0; ++ for (TimingData child : children.values()) { ++ clonedChildren[i++] = child.clone(); ++ } ++ return clonedChildren; ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingHistory.java b/src/main/java/co/aikar/timings/TimingHistory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ddaed81275fcc12d1671b668697acf318e96888b +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingHistory.java +@@ -0,0 +1,354 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import co.aikar.timings.TimingHistory.RegionData.RegionId; ++import com.google.common.base.Function; ++import com.google.common.collect.Sets; ++import org.bukkit.Bukkit; ++import org.bukkit.Chunk; ++import org.bukkit.Material; ++import org.bukkit.World; ++import org.bukkit.block.BlockState; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.EntityType; ++import org.bukkit.entity.Player; ++import co.aikar.util.LoadingMap; ++import co.aikar.util.MRUMapCache; ++ ++import java.lang.management.ManagementFactory; ++import java.util.Collection; ++import java.util.EnumMap; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import static co.aikar.timings.TimingsManager.FULL_SERVER_TICK; ++import static co.aikar.timings.TimingsManager.MINUTE_REPORTS; ++import static co.aikar.util.JSONUtil.*; ++ ++@SuppressWarnings({"deprecation", "SuppressionAnnotation", "Convert2Lambda", "Anonymous2MethodRef"}) ++public class TimingHistory { ++ public static long lastMinuteTime; ++ public static long timedTicks; ++ public static long playerTicks; ++ public static long entityTicks; ++ public static long tileEntityTicks; ++ public static long activatedEntityTicks; ++ private static int worldIdPool = 1; ++ static Map worldMap = LoadingMap.newHashMap(new Function() { ++ @NotNull ++ @Override ++ public Integer apply(@Nullable String input) { ++ return worldIdPool++; ++ } ++ }); ++ private final long endTime; ++ private final long startTime; ++ private final long totalTicks; ++ private final long totalTime; // Represents all time spent running the server this history ++ private final MinuteReport[] minuteReports; ++ ++ private final TimingHistoryEntry[] entries; ++ final Set tileEntityTypeSet = Sets.newHashSet(); ++ final Set entityTypeSet = Sets.newHashSet(); ++ private final Map worlds; ++ ++ TimingHistory() { ++ this.endTime = System.currentTimeMillis() / 1000; ++ this.startTime = TimingsManager.historyStart / 1000; ++ if (timedTicks % 1200 != 0 || MINUTE_REPORTS.isEmpty()) { ++ this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size() + 1]); ++ this.minuteReports[this.minuteReports.length - 1] = new MinuteReport(); ++ } else { ++ this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size()]); ++ } ++ long ticks = 0; ++ for (MinuteReport mp : this.minuteReports) { ++ ticks += mp.ticksRecord.timed; ++ } ++ this.totalTicks = ticks; ++ this.totalTime = FULL_SERVER_TICK.record.getTotalTime(); ++ this.entries = new TimingHistoryEntry[TimingsManager.HANDLERS.size()]; ++ ++ int i = 0; ++ for (TimingHandler handler : TimingsManager.HANDLERS) { ++ entries[i++] = new TimingHistoryEntry(handler); ++ } ++ ++ // Information about all loaded chunks/entities ++ //noinspection unchecked ++ this.worlds = toObjectMapper(Bukkit.getWorlds(), new Function() { ++ @NotNull ++ @Override ++ public JSONPair apply(World world) { ++ Map regions = LoadingMap.newHashMap(RegionData.LOADER); ++ ++ for (Chunk chunk : world.getLoadedChunks()) { ++ RegionData data = regions.get(new RegionId(chunk.getX(), chunk.getZ())); ++ ++ for (Entity entity : chunk.getEntities()) { ++ if (entity == null) { ++ Bukkit.getLogger().warning("Null entity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ()); ++ continue; ++ } ++ ++ data.entityCounts.get(entity.getType()).increment(); ++ } ++ ++ for (BlockState tileEntity : chunk.getTileEntities()) { ++ if (tileEntity == null) { ++ Bukkit.getLogger().warning("Null tileentity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ()); ++ continue; ++ } ++ ++ data.tileEntityCounts.get(tileEntity.getBlock().getType()).increment(); ++ } ++ } ++ return pair( ++ worldMap.get(world.getName()), ++ toArrayMapper(regions.values(),new Function() { ++ @NotNull ++ @Override ++ public Object apply(RegionData input) { ++ return toArray( ++ input.regionId.x, ++ input.regionId.z, ++ toObjectMapper(input.entityCounts.entrySet(), ++ new Function, JSONPair>() { ++ @NotNull ++ @Override ++ public JSONPair apply(Map.Entry entry) { ++ entityTypeSet.add(entry.getKey()); ++ return pair( ++ String.valueOf(entry.getKey().ordinal()), ++ entry.getValue().count() ++ ); ++ } ++ } ++ ), ++ toObjectMapper(input.tileEntityCounts.entrySet(), ++ new Function, JSONPair>() { ++ @NotNull ++ @Override ++ public JSONPair apply(Map.Entry entry) { ++ tileEntityTypeSet.add(entry.getKey()); ++ return pair( ++ String.valueOf(entry.getKey().ordinal()), ++ entry.getValue().count() ++ ); ++ } ++ } ++ ) ++ ); ++ } ++ }) ++ ); ++ } ++ }); ++ } ++ static class RegionData { ++ final RegionId regionId; ++ @SuppressWarnings("Guava") ++ static Function LOADER = new Function() { ++ @NotNull ++ @Override ++ public RegionData apply(@NotNull RegionId id) { ++ return new RegionData(id); ++ } ++ }; ++ RegionData(@NotNull RegionId id) { ++ this.regionId = id; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) { ++ return true; ++ } ++ if (o == null || getClass() != o.getClass()) { ++ return false; ++ } ++ ++ RegionData that = (RegionData) o; ++ ++ return regionId.equals(that.regionId); ++ ++ } ++ ++ @Override ++ public int hashCode() { ++ return regionId.hashCode(); ++ } ++ ++ @SuppressWarnings("unchecked") ++ final Map entityCounts = MRUMapCache.of(LoadingMap.of( ++ new EnumMap(EntityType.class), k -> new Counter() ++ )); ++ @SuppressWarnings("unchecked") ++ final Map tileEntityCounts = MRUMapCache.of(LoadingMap.of( ++ new EnumMap(Material.class), k -> new Counter() ++ )); ++ ++ static class RegionId { ++ final int x, z; ++ final long regionId; ++ RegionId(int x, int z) { ++ this.x = x >> 5 << 5; ++ this.z = z >> 5 << 5; ++ this.regionId = ((long) (this.x) << 32) + (this.z >> 5 << 5) - Integer.MIN_VALUE; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ ++ RegionId regionId1 = (RegionId) o; ++ ++ return regionId == regionId1.regionId; ++ ++ } ++ ++ @Override ++ public int hashCode() { ++ return (int) (regionId ^ (regionId >>> 32)); ++ } ++ } ++ } ++ static void resetTicks(boolean fullReset) { ++ if (fullReset) { ++ // Non full is simply for 1 minute reports ++ timedTicks = 0; ++ } ++ lastMinuteTime = System.nanoTime(); ++ playerTicks = 0; ++ tileEntityTicks = 0; ++ entityTicks = 0; ++ activatedEntityTicks = 0; ++ } ++ ++ @NotNull ++ Object export() { ++ return createObject( ++ pair("s", startTime), ++ pair("e", endTime), ++ pair("tk", totalTicks), ++ pair("tm", totalTime), ++ pair("w", worlds), ++ pair("h", toArrayMapper(entries, new Function() { ++ @Nullable ++ @Override ++ public Object apply(TimingHistoryEntry entry) { ++ TimingData record = entry.data; ++ if (!record.hasData()) { ++ return null; ++ } ++ return entry.export(); ++ } ++ })), ++ pair("mp", toArrayMapper(minuteReports, new Function() { ++ @NotNull ++ @Override ++ public Object apply(MinuteReport input) { ++ return input.export(); ++ } ++ })) ++ ); ++ } ++ ++ static class MinuteReport { ++ final long time = System.currentTimeMillis() / 1000; ++ ++ final TicksRecord ticksRecord = new TicksRecord(); ++ final PingRecord pingRecord = new PingRecord(); ++ final TimingData fst = TimingsManager.FULL_SERVER_TICK.minuteData.clone(); ++ final double tps = 1E9 / ( System.nanoTime() - lastMinuteTime ) * ticksRecord.timed; ++ final double usedMemory = TimingsManager.FULL_SERVER_TICK.avgUsedMemory; ++ final double freeMemory = TimingsManager.FULL_SERVER_TICK.avgFreeMemory; ++ final double loadAvg = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage(); ++ ++ @NotNull ++ List export() { ++ return toArray( ++ time, ++ Math.round(tps * 100D) / 100D, ++ Math.round(pingRecord.avg * 100D) / 100D, ++ fst.export(), ++ toArray(ticksRecord.timed, ++ ticksRecord.player, ++ ticksRecord.entity, ++ ticksRecord.activatedEntity, ++ ticksRecord.tileEntity ++ ), ++ usedMemory, ++ freeMemory, ++ loadAvg ++ ); ++ } ++ } ++ ++ private static class TicksRecord { ++ final long timed; ++ final long player; ++ final long entity; ++ final long tileEntity; ++ final long activatedEntity; ++ ++ TicksRecord() { ++ timed = timedTicks - (TimingsManager.MINUTE_REPORTS.size() * 1200); ++ player = playerTicks; ++ entity = entityTicks; ++ tileEntity = tileEntityTicks; ++ activatedEntity = activatedEntityTicks; ++ } ++ ++ } ++ ++ private static class PingRecord { ++ final double avg; ++ ++ PingRecord() { ++ final Collection onlinePlayers = Bukkit.getOnlinePlayers(); ++ int totalPing = 0; ++ for (Player player : onlinePlayers) { ++ totalPing += player.spigot().getPing(); ++ } ++ avg = onlinePlayers.isEmpty() ? 0 : totalPing / onlinePlayers.size(); ++ } ++ } ++ ++ ++ private static class Counter { ++ private int count = 0; ++ public int increment() { ++ return ++count; ++ } ++ public int count() { ++ return count; ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingHistoryEntry.java b/src/main/java/co/aikar/timings/TimingHistoryEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..86d5ac6bd0d7d0003688761aceb3f3343575319f +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingHistoryEntry.java +@@ -0,0 +1,58 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import com.google.common.base.Function; ++ ++import java.util.List; ++import org.jetbrains.annotations.NotNull; ++ ++import static co.aikar.util.JSONUtil.toArrayMapper; ++ ++class TimingHistoryEntry { ++ final TimingData data; ++ private final TimingData[] children; ++ ++ TimingHistoryEntry(@NotNull TimingHandler handler) { ++ this.data = handler.record.clone(); ++ children = handler.cloneChildren(); ++ } ++ ++ @NotNull ++ List export() { ++ List result = data.export(); ++ if (children.length > 0) { ++ result.add( ++ toArrayMapper(children, new Function() { ++ @NotNull ++ @Override ++ public Object apply(TimingData child) { ++ return child.export(); ++ } ++ }) ++ ); ++ } ++ return result; ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingIdentifier.java b/src/main/java/co/aikar/timings/TimingIdentifier.java +new file mode 100644 +index 0000000000000000000000000000000000000000..df142a89b8c43acb81eb383eac0ef048a1f49a6e +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingIdentifier.java +@@ -0,0 +1,116 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import co.aikar.util.LoadingMap; ++ ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++import java.util.Map; ++import java.util.Objects; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.atomic.AtomicInteger; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ *

    Used as a basis for fast HashMap key comparisons for the Timing Map.

    ++ * ++ * This class uses interned strings giving us the ability to do an identity check instead of equals() on the strings ++ */ ++final class TimingIdentifier { ++ /** ++ * Holds all groups. Autoloads on request for a group by name. ++ */ ++ static final Map GROUP_MAP = LoadingMap.of(new ConcurrentHashMap<>(64, .5F), TimingGroup::new); ++ private static final TimingGroup DEFAULT_GROUP = getGroup("Minecraft"); ++ final String group; ++ final String name; ++ final TimingHandler groupHandler; ++ private final int hashCode; ++ ++ TimingIdentifier(@Nullable String group, @NotNull String name, @Nullable Timing groupHandler) { ++ this.group = group != null ? group: DEFAULT_GROUP.name; ++ this.name = name; ++ this.groupHandler = groupHandler != null ? groupHandler.getTimingHandler() : null; ++ this.hashCode = (31 * this.group.hashCode()) + this.name.hashCode(); ++ } ++ ++ @NotNull ++ static TimingGroup getGroup(@Nullable String groupName) { ++ if (groupName == null) { ++ //noinspection ConstantConditions ++ return DEFAULT_GROUP; ++ } ++ ++ return GROUP_MAP.get(groupName); ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (o == null) { ++ return false; ++ } ++ ++ TimingIdentifier that = (TimingIdentifier) o; ++ return Objects.equals(group, that.group) && Objects.equals(name, that.name); ++ } ++ ++ @Override ++ public int hashCode() { ++ return hashCode; ++ } ++ ++ @Override ++ public String toString() { ++ return "TimingIdentifier{id=" + group + ":" + name +'}'; ++ } ++ ++ static class TimingGroup { ++ ++ private static AtomicInteger idPool = new AtomicInteger(1); ++ final int id = idPool.getAndIncrement(); ++ ++ final String name; ++ final List handlers = Collections.synchronizedList(new ArrayList<>(64)); ++ ++ private TimingGroup(String name) { ++ this.name = name; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ TimingGroup that = (TimingGroup) o; ++ return id == that.id; ++ } ++ ++ @Override ++ public int hashCode() { ++ return id; ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/timings/Timings.java b/src/main/java/co/aikar/timings/Timings.java +new file mode 100644 +index 0000000000000000000000000000000000000000..da76e1aaee1dee794e38ddd4e0a28e0071e90bbf +--- /dev/null ++++ b/src/main/java/co/aikar/timings/Timings.java +@@ -0,0 +1,296 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import com.google.common.base.Preconditions; ++import com.google.common.collect.EvictingQueue; ++import com.google.common.collect.Lists; ++import org.apache.commons.lang.Validate; ++import org.bukkit.Bukkit; ++import org.bukkit.command.CommandSender; ++import org.bukkit.plugin.Plugin; ++ ++import java.util.List; ++import java.util.Queue; ++import java.util.logging.Level; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++@SuppressWarnings({"UnusedDeclaration", "WeakerAccess", "SameParameterValue"}) ++public final class Timings { ++ ++ final static List requestingReport = Lists.newArrayList(); ++ private static final int MAX_HISTORY_FRAMES = 12; ++ public static final Timing NULL_HANDLER = new NullTimingHandler(); ++ static boolean timingsEnabled = false; ++ static boolean verboseEnabled = false; ++ private static int historyInterval = -1; ++ private static int historyLength = -1; ++ ++ private Timings() {} ++ ++ /** ++ * Returns a Timing for a plugin corresponding to a name. ++ * ++ * @param plugin Plugin to own the Timing ++ * @param name Name of Timing ++ * @return Handler ++ */ ++ @NotNull ++ public static Timing of(@NotNull Plugin plugin, @NotNull String name) { ++ Timing pluginHandler = null; ++ if (plugin != null) { ++ pluginHandler = ofSafe(plugin.getName(), "Combined Total", TimingsManager.PLUGIN_GROUP_HANDLER); ++ } ++ return of(plugin, name, pluginHandler); ++ } ++ ++ /** ++ *

    Returns a handler that has a groupHandler timer handler. Parent timers should not have their ++ * start/stop methods called directly, as the children will call it for you.

    ++ * ++ * Parent Timers are used to group multiple subsections together and get a summary of them combined ++ * Parent Handler can not be changed after first call ++ * ++ * @param plugin Plugin to own the Timing ++ * @param name Name of Timing ++ * @param groupHandler Parent handler to mirror .start/stop calls to ++ * @return Timing Handler ++ */ ++ @NotNull ++ public static Timing of(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) { ++ Preconditions.checkNotNull(plugin, "Plugin can not be null"); ++ return TimingsManager.getHandler(plugin.getName(), name, groupHandler); ++ } ++ ++ /** ++ * Returns a Timing object after starting it, useful for Java7 try-with-resources. ++ * ++ * try (Timing ignored = Timings.ofStart(plugin, someName)) { ++ * // timed section ++ * } ++ * ++ * @param plugin Plugin to own the Timing ++ * @param name Name of Timing ++ * @return Timing Handler ++ */ ++ @NotNull ++ public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name) { ++ return ofStart(plugin, name, null); ++ } ++ ++ /** ++ * Returns a Timing object after starting it, useful for Java7 try-with-resources. ++ * ++ * try (Timing ignored = Timings.ofStart(plugin, someName, groupHandler)) { ++ * // timed section ++ * } ++ * ++ * @param plugin Plugin to own the Timing ++ * @param name Name of Timing ++ * @param groupHandler Parent handler to mirror .start/stop calls to ++ * @return Timing Handler ++ */ ++ @NotNull ++ public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) { ++ Timing timing = of(plugin, name, groupHandler); ++ timing.startTiming(); ++ return timing; ++ } ++ ++ /** ++ * Gets whether or not the Spigot Timings system is enabled ++ * ++ * @return Enabled or not ++ */ ++ public static boolean isTimingsEnabled() { ++ return timingsEnabled; ++ } ++ ++ /** ++ *

    Sets whether or not the Spigot Timings system should be enabled

    ++ * ++ * Calling this will reset timing data. ++ * ++ * @param enabled Should timings be reported ++ */ ++ public static void setTimingsEnabled(boolean enabled) { ++ timingsEnabled = enabled; ++ reset(); ++ } ++ ++ /** ++ *

    Sets whether or not the Timings should monitor at Verbose level.

    ++ * ++ *

    When Verbose is disabled, high-frequency timings will not be available.

    ++ * ++ * @return Enabled or not ++ */ ++ public static boolean isVerboseTimingsEnabled() { ++ return verboseEnabled; ++ } ++ ++ /** ++ *

    Sets whether or not the Timings should monitor at Verbose level.

    ++ * ++ * When Verbose is disabled, high-frequency timings will not be available. ++ * Calling this will reset timing data. ++ * ++ * @param enabled Should high-frequency timings be reported ++ */ ++ public static void setVerboseTimingsEnabled(boolean enabled) { ++ verboseEnabled = enabled; ++ TimingsManager.needsRecheckEnabled = true; ++ } ++ ++ /** ++ *

    Gets the interval between Timing History report generation.

    ++ * ++ * Defaults to 5 minutes (6000 ticks) ++ * ++ * @return Interval in ticks ++ */ ++ public static int getHistoryInterval() { ++ return historyInterval; ++ } ++ ++ /** ++ *

    Sets the interval between Timing History report generations.

    ++ * ++ *

    Defaults to 5 minutes (6000 ticks)

    ++ * ++ * This will recheck your history length, so lowering this value will lower your ++ * history length if you need more than 60 history windows. ++ * ++ * @param interval Interval in ticks ++ */ ++ public static void setHistoryInterval(int interval) { ++ historyInterval = Math.max(20*60, interval); ++ // Recheck the history length with the new Interval ++ if (historyLength != -1) { ++ setHistoryLength(historyLength); ++ } ++ } ++ ++ /** ++ * Gets how long in ticks Timings history is kept for the server. ++ * ++ * Defaults to 1 hour (72000 ticks) ++ * ++ * @return Duration in Ticks ++ */ ++ public static int getHistoryLength() { ++ return historyLength; ++ } ++ ++ /** ++ * Sets how long Timing History reports are kept for the server. ++ * ++ * Defaults to 1 hours(72000 ticks) ++ * ++ * This value is capped at a maximum of getHistoryInterval() * MAX_HISTORY_FRAMES (12) ++ * ++ * Will not reset Timing Data but may truncate old history if the new length is less than old length. ++ * ++ * @param length Duration in ticks ++ */ ++ public static void setHistoryLength(int length) { ++ // Cap at 12 History Frames, 1 hour at 5 minute frames. ++ int maxLength = historyInterval * MAX_HISTORY_FRAMES; ++ // For special cases of servers with special permission to bypass the max. ++ // This max helps keep data file sizes reasonable for processing on Aikar's Timing parser side. ++ // Setting this will not help you bypass the max unless Aikar has added an exception on the API side. ++ if (System.getProperty("timings.bypassMax") != null) { ++ maxLength = Integer.MAX_VALUE; ++ } ++ historyLength = Math.max(Math.min(maxLength, length), historyInterval); ++ Queue oldQueue = TimingsManager.HISTORY; ++ int frames = (getHistoryLength() / getHistoryInterval()); ++ if (length > maxLength) { ++ Bukkit.getLogger().log(Level.WARNING, "Timings Length too high. Requested " + length + ", max is " + maxLength + ". To get longer history, you must increase your interval. Set Interval to " + Math.ceil(length / MAX_HISTORY_FRAMES) + " to achieve this length."); ++ } ++ TimingsManager.HISTORY = EvictingQueue.create(frames); ++ TimingsManager.HISTORY.addAll(oldQueue); ++ } ++ ++ /** ++ * Resets all Timing Data ++ */ ++ public static void reset() { ++ TimingsManager.reset(); ++ } ++ ++ /** ++ * Generates a report and sends it to the specified command sender. ++ * ++ * If sender is null, ConsoleCommandSender will be used. ++ * @param sender The sender to send to, or null to use the ConsoleCommandSender ++ */ ++ public static void generateReport(@Nullable CommandSender sender) { ++ if (sender == null) { ++ sender = Bukkit.getConsoleSender(); ++ } ++ requestingReport.add(sender); ++ } ++ ++ /** ++ * Generates a report and sends it to the specified listener. ++ * Use with {@link org.bukkit.command.BufferedCommandSender} to get full response when done! ++ * @param sender The listener to send responses too. ++ */ ++ public static void generateReport(@NotNull TimingsReportListener sender) { ++ Validate.notNull(sender); ++ requestingReport.add(sender); ++ } ++ ++ /* ++ ================= ++ Protected API: These are for internal use only in Bukkit/CraftBukkit ++ These do not have isPrimaryThread() checks in the startTiming/stopTiming ++ ================= ++ */ ++ @NotNull ++ static TimingHandler ofSafe(@NotNull String name) { ++ return ofSafe(null, name, null); ++ } ++ ++ @NotNull ++ static Timing ofSafe(@Nullable Plugin plugin, @NotNull String name) { ++ Timing pluginHandler = null; ++ if (plugin != null) { ++ pluginHandler = ofSafe(plugin.getName(), "Combined Total", TimingsManager.PLUGIN_GROUP_HANDLER); ++ } ++ return ofSafe(plugin != null ? plugin.getName() : "Minecraft - Invalid Plugin", name, pluginHandler); ++ } ++ ++ @NotNull ++ static TimingHandler ofSafe(@NotNull String name, @Nullable Timing groupHandler) { ++ return ofSafe(null, name, groupHandler); ++ } ++ ++ @NotNull ++ static TimingHandler ofSafe(@Nullable String groupName, @NotNull String name, @Nullable Timing groupHandler) { ++ return TimingsManager.getHandler(groupName, name, groupHandler); ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingsCommand.java b/src/main/java/co/aikar/timings/TimingsCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f7c2245a310a084367ff25db539b3c967d5cb141 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingsCommand.java +@@ -0,0 +1,119 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import com.google.common.collect.ImmutableList; ++import org.apache.commons.lang.Validate; ++import org.bukkit.ChatColor; ++import org.bukkit.command.CommandSender; ++import org.bukkit.command.defaults.BukkitCommand; ++import org.bukkit.util.StringUtil; ++ ++import java.util.ArrayList; ++import java.util.List; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++ ++public class TimingsCommand extends BukkitCommand { ++ private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste", "verbon", "verboff"); ++ private long lastResetAttempt = 0; ++ ++ public TimingsCommand(@NotNull String name) { ++ super(name); ++ this.description = "Manages Spigot Timings data to see performance of the server."; ++ this.usageMessage = "/timings "; ++ this.setPermission("bukkit.command.timings"); ++ } ++ ++ @Override ++ public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { ++ if (!testPermission(sender)) { ++ return true; ++ } ++ if (args.length < 1) { ++ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); ++ return true; ++ } ++ final String arg = args[0]; ++ if ("on".equalsIgnoreCase(arg)) { ++ Timings.setTimingsEnabled(true); ++ sender.sendMessage("Enabled Timings & Reset"); ++ return true; ++ } else if ("off".equalsIgnoreCase(arg)) { ++ Timings.setTimingsEnabled(false); ++ sender.sendMessage("Disabled Timings"); ++ return true; ++ } ++ ++ if (!Timings.isTimingsEnabled()) { ++ sender.sendMessage("Please enable timings by typing /timings on"); ++ return true; ++ } ++ ++ long now = System.currentTimeMillis(); ++ if ("verbon".equalsIgnoreCase(arg)) { ++ Timings.setVerboseTimingsEnabled(true); ++ sender.sendMessage("Enabled Verbose Timings"); ++ return true; ++ } else if ("verboff".equalsIgnoreCase(arg)) { ++ Timings.setVerboseTimingsEnabled(false); ++ sender.sendMessage("Disabled Verbose Timings"); ++ return true; ++ } else if ("reset".equalsIgnoreCase(arg)) { ++ if (now - lastResetAttempt < 30000) { ++ TimingsManager.reset(); ++ sender.sendMessage(ChatColor.RED + "Timings reset. Please wait 5-10 minutes before using /timings report."); ++ } else { ++ lastResetAttempt = now; ++ sender.sendMessage(ChatColor.RED + "WARNING: Timings v2 should not be reset. If you are encountering lag, please wait 3 minutes and then issue a report. The best timings will include 10+ minutes, with data before and after your lag period. If you really want to reset, run this command again within 30 seconds."); ++ } ++ } else if ( ++ "paste".equalsIgnoreCase(arg) || ++ "report".equalsIgnoreCase(arg) || ++ "get".equalsIgnoreCase(arg) || ++ "merged".equalsIgnoreCase(arg) || ++ "separate".equalsIgnoreCase(arg) ++ ) { ++ Timings.generateReport(sender); ++ } else { ++ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); ++ } ++ return true; ++ } ++ ++ @NotNull ++ @Override ++ public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { ++ Validate.notNull(sender, "Sender cannot be null"); ++ Validate.notNull(args, "Arguments cannot be null"); ++ Validate.notNull(alias, "Alias cannot be null"); ++ ++ if (args.length == 1) { ++ return StringUtil.copyPartialMatches(args[0], TIMINGS_SUBCOMMANDS, ++ new ArrayList(TIMINGS_SUBCOMMANDS.size())); ++ } ++ return ImmutableList.of(); ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingsManager.java b/src/main/java/co/aikar/timings/TimingsManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ef824d701c97cad8b31e76ad98c94fc4367a7eda +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingsManager.java +@@ -0,0 +1,188 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import co.aikar.util.LoadingMap; ++import com.google.common.collect.EvictingQueue; ++import org.bukkit.Bukkit; ++import org.bukkit.Server; ++import org.bukkit.command.Command; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.java.PluginClassLoader; ++ ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.logging.Level; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++public final class TimingsManager { ++ static final Map TIMING_MAP = LoadingMap.of( ++ new ConcurrentHashMap<>(4096, .5F), TimingHandler::new ++ ); ++ public static final FullServerTickHandler FULL_SERVER_TICK = new FullServerTickHandler(); ++ public static final TimingHandler TIMINGS_TICK = Timings.ofSafe("Timings Tick", FULL_SERVER_TICK); ++ public static final Timing PLUGIN_GROUP_HANDLER = Timings.ofSafe("Plugins"); ++ public static List hiddenConfigs = new ArrayList(); ++ public static boolean privacy = false; ++ ++ static final List HANDLERS = new ArrayList<>(1024); ++ static final List MINUTE_REPORTS = new ArrayList<>(64); ++ ++ static EvictingQueue HISTORY = EvictingQueue.create(12); ++ static long timingStart = 0; ++ static long historyStart = 0; ++ static boolean needsFullReset = false; ++ static boolean needsRecheckEnabled = false; ++ ++ private TimingsManager() {} ++ ++ /** ++ * Resets all timing data on the next tick ++ */ ++ static void reset() { ++ needsFullReset = true; ++ } ++ ++ /** ++ * Ticked every tick by CraftBukkit to count the number of times a timer ++ * caused TPS loss. ++ */ ++ static void tick() { ++ if (Timings.timingsEnabled) { ++ boolean violated = FULL_SERVER_TICK.isViolated(); ++ ++ for (TimingHandler handler : HANDLERS) { ++ if (handler.isSpecial()) { ++ // We manually call this ++ continue; ++ } ++ handler.processTick(violated); ++ } ++ ++ TimingHistory.playerTicks += Bukkit.getOnlinePlayers().size(); ++ TimingHistory.timedTicks++; ++ // Generate TPS/Ping/Tick reports every minute ++ } ++ } ++ static void stopServer() { ++ Timings.timingsEnabled = false; ++ recheckEnabled(); ++ } ++ static void recheckEnabled() { ++ synchronized (TIMING_MAP) { ++ for (TimingHandler timings : TIMING_MAP.values()) { ++ timings.checkEnabled(); ++ } ++ } ++ needsRecheckEnabled = false; ++ } ++ static void resetTimings() { ++ if (needsFullReset) { ++ // Full resets need to re-check every handlers enabled state ++ // Timing map can be modified from async so we must sync on it. ++ synchronized (TIMING_MAP) { ++ for (TimingHandler timings : TIMING_MAP.values()) { ++ timings.reset(true); ++ } ++ } ++ Bukkit.getLogger().log(Level.INFO, "Timings Reset"); ++ HISTORY.clear(); ++ needsFullReset = false; ++ needsRecheckEnabled = false; ++ timingStart = System.currentTimeMillis(); ++ } else { ++ // Soft resets only need to act on timings that have done something ++ // Handlers can only be modified on main thread. ++ for (TimingHandler timings : HANDLERS) { ++ timings.reset(false); ++ } ++ } ++ ++ HANDLERS.clear(); ++ MINUTE_REPORTS.clear(); ++ ++ TimingHistory.resetTicks(true); ++ historyStart = System.currentTimeMillis(); ++ } ++ ++ @NotNull ++ static TimingHandler getHandler(@Nullable String group, @NotNull String name, @Nullable Timing parent) { ++ return TIMING_MAP.get(new TimingIdentifier(group, name, parent)); ++ } ++ ++ ++ /** ++ *

    Due to access restrictions, we need a helper method to get a Command TimingHandler with String group

    ++ * ++ * Plugins should never call this ++ * ++ * @param pluginName Plugin this command is associated with ++ * @param command Command to get timings for ++ * @return TimingHandler ++ */ ++ @NotNull ++ public static Timing getCommandTiming(@Nullable String pluginName, @NotNull Command command) { ++ Plugin plugin = null; ++ final Server server = Bukkit.getServer(); ++ if (!( server == null || pluginName == null || ++ "minecraft".equals(pluginName) || "bukkit".equals(pluginName) || ++ "spigot".equalsIgnoreCase(pluginName) || "paper".equals(pluginName) ++ )) { ++ plugin = server.getPluginManager().getPlugin(pluginName); ++ } ++ if (plugin == null) { ++ // Plugin is passing custom fallback prefix, try to look up by class loader ++ plugin = getPluginByClassloader(command.getClass()); ++ } ++ if (plugin == null) { ++ return Timings.ofSafe("Command: " + pluginName + ":" + command.getTimingName()); ++ } ++ ++ return Timings.ofSafe(plugin, "Command: " + pluginName + ":" + command.getTimingName()); ++ } ++ ++ /** ++ * Looks up the class loader for the specified class, and if it is a PluginClassLoader, return the ++ * Plugin that created this class. ++ * ++ * @param clazz Class to check ++ * @return Plugin if created by a plugin ++ */ ++ @Nullable ++ public static Plugin getPluginByClassloader(@Nullable Class clazz) { ++ if (clazz == null) { ++ return null; ++ } ++ final ClassLoader classLoader = clazz.getClassLoader(); ++ if (classLoader instanceof PluginClassLoader) { ++ PluginClassLoader pluginClassLoader = (PluginClassLoader) classLoader; ++ return pluginClassLoader.getPlugin(); ++ } ++ return null; ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingsReportListener.java b/src/main/java/co/aikar/timings/TimingsReportListener.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ef58a6c00f444bd498a2d8fc4e457236f393954f +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingsReportListener.java +@@ -0,0 +1,77 @@ ++package co.aikar.timings; ++ ++import com.google.common.collect.Lists; ++import org.apache.commons.lang.Validate; ++import org.bukkit.Bukkit; ++import org.bukkit.command.CommandSender; ++import org.bukkit.command.ConsoleCommandSender; ++import org.bukkit.command.MessageCommandSender; ++import org.bukkit.command.RemoteConsoleCommandSender; ++ ++import java.util.List; ++import java.util.UUID; ++ ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++@SuppressWarnings("WeakerAccess") ++public class TimingsReportListener implements MessageCommandSender { ++ private final List senders; ++ private final Runnable onDone; ++ private String timingsURL; ++ ++ public TimingsReportListener(@NotNull CommandSender senders) { ++ this(senders, null); ++ } ++ public TimingsReportListener(@NotNull CommandSender sender, @Nullable Runnable onDone) { ++ this(Lists.newArrayList(sender), onDone); ++ } ++ public TimingsReportListener(@NotNull List senders) { ++ this(senders, null); ++ } ++ public TimingsReportListener(@NotNull List senders, @Nullable Runnable onDone) { ++ Validate.notNull(senders); ++ Validate.notEmpty(senders); ++ ++ this.senders = Lists.newArrayList(senders); ++ this.onDone = onDone; ++ } ++ ++ @Nullable ++ public String getTimingsURL() { ++ return timingsURL; ++ } ++ ++ public void done() { ++ done(null); ++ } ++ ++ public void done(@Nullable String url) { ++ this.timingsURL = url; ++ if (onDone != null) { ++ onDone.run(); ++ } ++ for (CommandSender sender : senders) { ++ if (sender instanceof TimingsReportListener) { ++ ((TimingsReportListener) sender).done(); ++ } ++ } ++ } ++ ++ @Override ++ public void sendMessage(@NotNull String message) { ++ senders.forEach((sender) -> sender.sendMessage(message)); ++ } ++ ++ public void addConsoleIfNeeded() { ++ boolean hasConsole = false; ++ for (CommandSender sender : this.senders) { ++ if (sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender) { ++ hasConsole = true; ++ } ++ } ++ if (!hasConsole) { ++ this.senders.add(Bukkit.getConsoleSender()); ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/timings/UnsafeTimingHandler.java b/src/main/java/co/aikar/timings/UnsafeTimingHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..632c4961515f5052551f841cfa840e60bba7a257 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/UnsafeTimingHandler.java +@@ -0,0 +1,53 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import org.bukkit.Bukkit; ++import org.jetbrains.annotations.NotNull; ++ ++class UnsafeTimingHandler extends TimingHandler { ++ ++ UnsafeTimingHandler(@NotNull TimingIdentifier id) { ++ super(id); ++ } ++ ++ private static void checkThread() { ++ if (!Bukkit.isPrimaryThread()) { ++ throw new IllegalStateException("Calling Timings from Async Operation"); ++ } ++ } ++ ++ @NotNull ++ @Override ++ public Timing startTiming() { ++ checkThread(); ++ return super.startTiming(); ++ } ++ ++ @Override ++ public void stopTiming() { ++ checkThread(); ++ super.stopTiming(); ++ } ++} +diff --git a/src/main/java/co/aikar/util/Counter.java b/src/main/java/co/aikar/util/Counter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..eff63c371c39e21a5a9cb5af8c2dcf78a60dd52b +--- /dev/null ++++ b/src/main/java/co/aikar/util/Counter.java +@@ -0,0 +1,38 @@ ++package co.aikar.util; ++ ++import com.google.common.collect.ForwardingMap; ++ ++import java.util.HashMap; ++import java.util.Map; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++public class Counter extends ForwardingMap { ++ private final Map counts = new HashMap<>(); ++ ++ public long decrement(@Nullable T key) { ++ return increment(key, -1); ++ } ++ public long increment(@Nullable T key) { ++ return increment(key, 1); ++ } ++ public long decrement(@Nullable T key, long amount) { ++ return increment(key, -amount); ++ } ++ public long increment(@Nullable T key, long amount) { ++ Long count = this.getCount(key); ++ count += amount; ++ this.counts.put(key, count); ++ return count; ++ } ++ ++ public long getCount(@Nullable T key) { ++ return this.counts.getOrDefault(key, 0L); ++ } ++ ++ @NotNull ++ @Override ++ protected Map delegate() { ++ return this.counts; ++ } ++} +diff --git a/src/main/java/co/aikar/util/JSONUtil.java b/src/main/java/co/aikar/util/JSONUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..190bf0598442c89c2a1c93ad7c8c1a29797304ae +--- /dev/null ++++ b/src/main/java/co/aikar/util/JSONUtil.java +@@ -0,0 +1,140 @@ ++package co.aikar.util; ++ ++import com.google.common.base.Function; ++import com.google.common.collect.Lists; ++import com.google.common.collect.Maps; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.json.simple.JSONArray; ++import org.json.simple.JSONObject; ++ ++import java.util.ArrayList; ++import java.util.LinkedHashMap; ++import java.util.List; ++import java.util.Map; ++ ++/** ++ * Provides Utility methods that assist with generating JSON Objects ++ */ ++@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) ++public final class JSONUtil { ++ private JSONUtil() {} ++ ++ /** ++ * Creates a key/value "JSONPair" object ++ * ++ * @param key Key to use ++ * @param obj Value to use ++ * @return JSONPair ++ */ ++ @NotNull ++ public static JSONPair pair(@NotNull String key, @Nullable Object obj) { ++ return new JSONPair(key, obj); ++ } ++ ++ @NotNull ++ public static JSONPair pair(long key, @Nullable Object obj) { ++ return new JSONPair(String.valueOf(key), obj); ++ } ++ ++ /** ++ * Creates a new JSON object from multiple JSONPair key/value pairs ++ * ++ * @param data JSONPairs ++ * @return Map ++ */ ++ @NotNull ++ public static Map createObject(@NotNull JSONPair... data) { ++ return appendObjectData(new LinkedHashMap(), data); ++ } ++ ++ /** ++ * This appends multiple key/value Obj pairs into a JSON Object ++ * ++ * @param parent Map to be appended to ++ * @param data Data to append ++ * @return Map ++ */ ++ @NotNull ++ public static Map appendObjectData(@NotNull Map parent, @NotNull JSONPair... data) { ++ for (JSONPair JSONPair : data) { ++ parent.put(JSONPair.key, JSONPair.val); ++ } ++ return parent; ++ } ++ ++ /** ++ * This builds a JSON array from a set of data ++ * ++ * @param data Data to build JSON array from ++ * @return List ++ */ ++ @NotNull ++ public static List toArray(@NotNull Object... data) { ++ return Lists.newArrayList(data); ++ } ++ ++ /** ++ * These help build a single JSON array using a mapper function ++ * ++ * @param collection Collection to apply to ++ * @param mapper Mapper to apply ++ * @param Element Type ++ * @return List ++ */ ++ @NotNull ++ public static List toArrayMapper(@NotNull E[] collection, @NotNull Function mapper) { ++ return toArrayMapper(Lists.newArrayList(collection), mapper); ++ } ++ ++ @NotNull ++ public static List toArrayMapper(@NotNull Iterable collection, @NotNull Function mapper) { ++ List array = Lists.newArrayList(); ++ for (E e : collection) { ++ Object object = mapper.apply(e); ++ if (object != null) { ++ array.add(object); ++ } ++ } ++ return array; ++ } ++ ++ /** ++ * These help build a single JSON Object from a collection, using a mapper function ++ * ++ * @param collection Collection to apply to ++ * @param mapper Mapper to apply ++ * @param Element Type ++ * @return Map ++ */ ++ @NotNull ++ public static Map toObjectMapper(@NotNull E[] collection, @NotNull Function mapper) { ++ return toObjectMapper(Lists.newArrayList(collection), mapper); ++ } ++ ++ @NotNull ++ public static Map toObjectMapper(@NotNull Iterable collection, @NotNull Function mapper) { ++ Map object = Maps.newLinkedHashMap(); ++ for (E e : collection) { ++ JSONPair JSONPair = mapper.apply(e); ++ if (JSONPair != null) { ++ object.put(JSONPair.key, JSONPair.val); ++ } ++ } ++ return object; ++ } ++ ++ /** ++ * Simply stores a key and a value, used internally by many methods below. ++ */ ++ @SuppressWarnings("PublicInnerClass") ++ public static class JSONPair { ++ final String key; ++ final Object val; ++ ++ JSONPair(@NotNull String key, @NotNull Object val) { ++ this.key = key; ++ this.val = val; ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/util/LoadingIntMap.java b/src/main/java/co/aikar/util/LoadingIntMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..63a899c7dbdb69daa4876a2ce2a7dfb734b5af9d +--- /dev/null ++++ b/src/main/java/co/aikar/util/LoadingIntMap.java +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (c) 2015. Starlis LLC / dba Empire Minecraft ++ * ++ * This source code is proprietary software and must not be redistributed without Starlis LLC's approval ++ * ++ */ ++package co.aikar.util; ++ ++ ++import com.google.common.base.Function; ++import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Allows you to pass a Loader function that when a key is accessed that doesn't exist, ++ * automatically loads the entry into the map by calling the loader Function. ++ * ++ * .get() Will only return null if the Loader can return null. ++ * ++ * You may pass any backing Map to use. ++ * ++ * This class is not thread safe and should be wrapped with Collections.synchronizedMap on the OUTSIDE of the LoadingMap if needed. ++ * ++ * Do not wrap the backing map with Collections.synchronizedMap. ++ * ++ * @param Value ++ */ ++public class LoadingIntMap extends Int2ObjectOpenHashMap { ++ private final Function loader; ++ ++ public LoadingIntMap(@NotNull Function loader) { ++ super(); ++ this.loader = loader; ++ } ++ ++ public LoadingIntMap(int expectedSize, @NotNull Function loader) { ++ super(expectedSize); ++ this.loader = loader; ++ } ++ ++ public LoadingIntMap(int expectedSize, float loadFactor, @NotNull Function loader) { ++ super(expectedSize, loadFactor); ++ this.loader = loader; ++ } ++ ++ ++ @Nullable ++ @Override ++ public V get(int key) { ++ V res = super.get(key); ++ if (res == null) { ++ res = loader.apply(key); ++ if (res != null) { ++ put(key, res); ++ } ++ } ++ return res; ++ } ++ ++ /** ++ * Due to java stuff, you will need to cast it to (Function) for some cases ++ * ++ * @param Type ++ */ ++ public abstract static class Feeder implements Function { ++ @Nullable ++ @Override ++ public T apply(@Nullable Object input) { ++ return apply(); ++ } ++ ++ @Nullable ++ public abstract T apply(); ++ } ++} +diff --git a/src/main/java/co/aikar/util/LoadingMap.java b/src/main/java/co/aikar/util/LoadingMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..aedbb03321886cb267879d7994653e447b485f6a +--- /dev/null ++++ b/src/main/java/co/aikar/util/LoadingMap.java +@@ -0,0 +1,368 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.util; ++ ++import com.google.common.base.Preconditions; ++import java.lang.reflect.Constructor; ++import java.util.AbstractMap; ++import java.util.Collection; ++import java.util.HashMap; ++import java.util.IdentityHashMap; ++import java.util.Map; ++import java.util.Set; ++import java.util.function.Function; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Allows you to pass a Loader function that when a key is accessed that doesn't exists, ++ * automatically loads the entry into the map by calling the loader Function. ++ * ++ * .get() Will only return null if the Loader can return null. ++ * ++ * You may pass any backing Map to use. ++ * ++ * This class is not thread safe and should be wrapped with Collections.synchronizedMap on the OUTSIDE of the LoadingMap if needed. ++ * ++ * Do not wrap the backing map with Collections.synchronizedMap. ++ * ++ * @param Key ++ * @param Value ++ */ ++public class LoadingMap extends AbstractMap { ++ private final Map backingMap; ++ private final java.util.function.Function loader; ++ ++ /** ++ * Initializes an auto loading map using specified loader and backing map ++ * @param backingMap Map to wrap ++ * @param loader Loader ++ */ ++ public LoadingMap(@NotNull Map backingMap, @NotNull java.util.function.Function loader) { ++ this.backingMap = backingMap; ++ this.loader = loader; ++ } ++ ++ /** ++ * Creates a new LoadingMap with the specified map and loader ++ * ++ * @param backingMap Actual map being used. ++ * @param loader Loader to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map of(@NotNull Map backingMap, @NotNull Function loader) { ++ return new LoadingMap<>(backingMap, loader); ++ } ++ ++ /** ++ * Creates a LoadingMap with an auto instantiating loader. ++ * ++ * Will auto construct class of of Value when not found ++ * ++ * Since this uses Reflection, It is more effecient to define your own static loader ++ * than using this helper, but if performance is not critical, this is easier. ++ * ++ * @param backingMap Actual map being used. ++ * @param keyClass Class used for the K generic ++ * @param valueClass Class used for the V generic ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map that auto instantiates on .get() ++ */ ++ @NotNull ++ public static Map newAutoMap(@NotNull Map backingMap, @Nullable final Class keyClass, ++ @NotNull final Class valueClass) { ++ return new LoadingMap<>(backingMap, new AutoInstantiatingLoader<>(keyClass, valueClass)); ++ } ++ /** ++ * Creates a LoadingMap with an auto instantiating loader. ++ * ++ * Will auto construct class of of Value when not found ++ * ++ * Since this uses Reflection, It is more effecient to define your own static loader ++ * than using this helper, but if performance is not critical, this is easier. ++ * ++ * @param backingMap Actual map being used. ++ * @param valueClass Class used for the V generic ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map that auto instantiates on .get() ++ */ ++ @NotNull ++ public static Map newAutoMap(@NotNull Map backingMap, ++ @NotNull final Class valueClass) { ++ return newAutoMap(backingMap, null, valueClass); ++ } ++ ++ /** ++ * @see #newAutoMap ++ * ++ * new Auto initializing map using a HashMap. ++ * ++ * @param keyClass Class used for the K generic ++ * @param valueClass Class used for the V generic ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map that auto instantiates on .get() ++ */ ++ @NotNull ++ public static Map newHashAutoMap(@Nullable final Class keyClass, @NotNull final Class valueClass) { ++ return newAutoMap(new HashMap<>(), keyClass, valueClass); ++ } ++ ++ /** ++ * @see #newAutoMap ++ * ++ * new Auto initializing map using a HashMap. ++ * ++ * @param valueClass Class used for the V generic ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map that auto instantiates on .get() ++ */ ++ @NotNull ++ public static Map newHashAutoMap(@NotNull final Class valueClass) { ++ return newHashAutoMap(null, valueClass); ++ } ++ ++ /** ++ * @see #newAutoMap ++ * ++ * new Auto initializing map using a HashMap. ++ * ++ * @param keyClass Class used for the K generic ++ * @param valueClass Class used for the V generic ++ * @param initialCapacity Initial capacity to use ++ * @param loadFactor Load factor to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map that auto instantiates on .get() ++ */ ++ @NotNull ++ public static Map newHashAutoMap(@Nullable final Class keyClass, @NotNull final Class valueClass, int initialCapacity, float loadFactor) { ++ return newAutoMap(new HashMap<>(initialCapacity, loadFactor), keyClass, valueClass); ++ } ++ ++ /** ++ * @see #newAutoMap ++ * ++ * new Auto initializing map using a HashMap. ++ * ++ * @param valueClass Class used for the V generic ++ * @param initialCapacity Initial capacity to use ++ * @param loadFactor Load factor to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map that auto instantiates on .get() ++ */ ++ @NotNull ++ public static Map newHashAutoMap(@NotNull final Class valueClass, int initialCapacity, float loadFactor) { ++ return newHashAutoMap(null, valueClass, initialCapacity, loadFactor); ++ } ++ ++ /** ++ * Initializes an auto loading map using a HashMap ++ * ++ * @param loader Loader to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map newHashMap(@NotNull Function loader) { ++ return new LoadingMap<>(new HashMap<>(), loader); ++ } ++ ++ /** ++ * Initializes an auto loading map using a HashMap ++ * ++ * @param loader Loader to use ++ * @param initialCapacity Initial capacity to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map newHashMap(@NotNull Function loader, int initialCapacity) { ++ return new LoadingMap<>(new HashMap<>(initialCapacity), loader); ++ } ++ /** ++ * Initializes an auto loading map using a HashMap ++ * ++ * @param loader Loader to use ++ * @param initialCapacity Initial capacity to use ++ * @param loadFactor Load factor to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map newHashMap(@NotNull Function loader, int initialCapacity, float loadFactor) { ++ return new LoadingMap<>(new HashMap<>(initialCapacity, loadFactor), loader); ++ } ++ ++ /** ++ * Initializes an auto loading map using an Identity HashMap ++ * ++ * @param loader Loader to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map newIdentityHashMap(@NotNull Function loader) { ++ return new LoadingMap<>(new IdentityHashMap<>(), loader); ++ } ++ ++ /** ++ * Initializes an auto loading map using an Identity HashMap ++ * ++ * @param loader Loader to use ++ * @param initialCapacity Initial capacity to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map newIdentityHashMap(@NotNull Function loader, int initialCapacity) { ++ return new LoadingMap<>(new IdentityHashMap<>(initialCapacity), loader); ++ } ++ ++ @Override ++ public int size() {return backingMap.size();} ++ ++ @Override ++ public boolean isEmpty() {return backingMap.isEmpty();} ++ ++ @Override ++ public boolean containsKey(@Nullable Object key) {return backingMap.containsKey(key);} ++ ++ @Override ++ public boolean containsValue(@Nullable Object value) {return backingMap.containsValue(value);} ++ ++ @Nullable ++ @Override ++ public V get(@Nullable Object key) { ++ V v = backingMap.get(key); ++ if (v != null) { ++ return v; ++ } ++ return backingMap.computeIfAbsent((K) key, loader); ++ } ++ ++ @Nullable ++ public V put(@Nullable K key, @Nullable V value) {return backingMap.put(key, value);} ++ ++ @Nullable ++ @Override ++ public V remove(@Nullable Object key) {return backingMap.remove(key);} ++ ++ public void putAll(@NotNull Map m) {backingMap.putAll(m);} ++ ++ @Override ++ public void clear() {backingMap.clear();} ++ ++ @NotNull ++ @Override ++ public Set keySet() {return backingMap.keySet();} ++ ++ @NotNull ++ @Override ++ public Collection values() {return backingMap.values();} ++ ++ @Override ++ public boolean equals(@Nullable Object o) {return backingMap.equals(o);} ++ ++ @Override ++ public int hashCode() {return backingMap.hashCode();} ++ ++ @NotNull ++ @Override ++ public Set> entrySet() { ++ return backingMap.entrySet(); ++ } ++ ++ @NotNull ++ public LoadingMap clone() { ++ return new LoadingMap<>(backingMap, loader); ++ } ++ ++ private static class AutoInstantiatingLoader implements Function { ++ final Constructor constructor; ++ private final Class valueClass; ++ ++ AutoInstantiatingLoader(@Nullable Class keyClass, @NotNull Class valueClass) { ++ try { ++ this.valueClass = valueClass; ++ if (keyClass != null) { ++ constructor = valueClass.getConstructor(keyClass); ++ } else { ++ constructor = null; ++ } ++ } catch (NoSuchMethodException e) { ++ throw new IllegalStateException( ++ valueClass.getName() + " does not have a constructor for " + (keyClass != null ? keyClass.getName() : null)); ++ } ++ } ++ ++ @NotNull ++ @Override ++ public V apply(@Nullable K input) { ++ try { ++ return (constructor != null ? constructor.newInstance(input) : valueClass.newInstance()); ++ } catch (Exception e) { ++ throw new ExceptionInInitializerError(e); ++ } ++ } ++ ++ @Override ++ public int hashCode() { ++ return super.hashCode(); ++ } ++ ++ @Override ++ public boolean equals(Object object) { ++ return false; ++ } ++ } ++ ++ /** ++ * Due to java stuff, you will need to cast it to (Function) for some cases ++ * ++ * @param Type ++ */ ++ public abstract static class Feeder implements Function { ++ @Nullable ++ @Override ++ public T apply(@Nullable Object input) { ++ return apply(); ++ } ++ ++ @Nullable ++ public abstract T apply(); ++ } ++} +diff --git a/src/main/java/co/aikar/util/MRUMapCache.java b/src/main/java/co/aikar/util/MRUMapCache.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5989ee21297935651b0edd44b8239e655eaef1d9 +--- /dev/null ++++ b/src/main/java/co/aikar/util/MRUMapCache.java +@@ -0,0 +1,111 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.util; ++ ++import java.util.AbstractMap; ++import java.util.Collection; ++import java.util.Map; ++import java.util.Set; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Implements a Most Recently Used cache in front of a backing map, to quickly access the last accessed result. ++ * ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ */ ++public class MRUMapCache extends AbstractMap { ++ final Map backingMap; ++ Object cacheKey; ++ V cacheValue; ++ public MRUMapCache(@NotNull final Map backingMap) { ++ this.backingMap = backingMap; ++ } ++ ++ public int size() {return backingMap.size();} ++ ++ public boolean isEmpty() {return backingMap.isEmpty();} ++ ++ public boolean containsKey(@Nullable Object key) { ++ return key != null && key.equals(cacheKey) || backingMap.containsKey(key); ++ } ++ ++ public boolean containsValue(@Nullable Object value) { ++ return value != null && value == cacheValue || backingMap.containsValue(value); ++ } ++ ++ @Nullable ++ public V get(@Nullable Object key) { ++ if (cacheKey != null && cacheKey.equals(key)) { ++ return cacheValue; ++ } ++ cacheKey = key; ++ return cacheValue = backingMap.get(key); ++ } ++ ++ @Nullable ++ public V put(@Nullable K key, @Nullable V value) { ++ cacheKey = key; ++ return cacheValue = backingMap.put(key, value); ++ } ++ ++ @Nullable ++ public V remove(@Nullable Object key) { ++ if (key != null && key.equals(cacheKey)) { ++ cacheKey = null; ++ } ++ return backingMap.remove(key); ++ } ++ ++ public void putAll(@NotNull Map m) {backingMap.putAll(m);} ++ ++ public void clear() { ++ cacheKey = null; ++ cacheValue = null; ++ backingMap.clear(); ++ } ++ ++ @NotNull ++ public Set keySet() {return backingMap.keySet();} ++ ++ @NotNull ++ public Collection values() {return backingMap.values();} ++ ++ @NotNull ++ public Set> entrySet() {return backingMap.entrySet();} ++ ++ /** ++ * Wraps the specified map with a most recently used cache ++ * ++ * @param map Map to be wrapped ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map of(@NotNull Map map) { ++ return new MRUMapCache(map); ++ } ++} +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 7168dd083ee30a47b104ab32cabb3215815f7470..7c715fdc11ab7837552b1fe3ffd08b31cec0a63b 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -649,7 +649,6 @@ public final class Bukkit { + */ + public static void reload() { + server.reload(); +- org.spigotmc.CustomTimingsHandler.reload(); // Spigot + } + + /** +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 4ba8572f1beb3b9ad46620946eb4ee89ac91818e..a6b9e4f158583e5932bf8ca210d531857e9f5360 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1344,6 +1344,26 @@ public interface Server extends PluginMessageRecipient { + throw new UnsupportedOperationException("Not supported yet."); + } + ++ // Paper start ++ @NotNull ++ public org.bukkit.configuration.file.YamlConfiguration getBukkitConfig() ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } ++ ++ @NotNull ++ public org.bukkit.configuration.file.YamlConfiguration getSpigotConfig() ++ { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ @NotNull ++ public org.bukkit.configuration.file.YamlConfiguration getPaperConfig() ++ { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // Paper end ++ + /** + * 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 247d194f86c00db11acbc58e7d163b2606db4f07..945b8b030d1b2a13afc0c4efad76997eb7bf00ba 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -18,6 +18,7 @@ import org.bukkit.plugin.PluginDescriptionFile; + @Deprecated + public interface UnsafeValues { + ++ void reportTimings(); // Paper + Material toLegacy(Material material); + + Material fromLegacy(Material material); +@@ -69,4 +70,12 @@ public interface UnsafeValues { + * @return true if a file matching this key was found and deleted + */ + boolean removeAdvancement(NamespacedKey key); ++ ++ // Paper start ++ /** ++ * Server name to report to timings v2 ++ * @return name ++ */ ++ String getTimingsServerName(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/command/BufferedCommandSender.java b/src/main/java/org/bukkit/command/BufferedCommandSender.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f9a00aecca5ec41b460bf41dfe1c69694768cf98 +--- /dev/null ++++ b/src/main/java/org/bukkit/command/BufferedCommandSender.java +@@ -0,0 +1,21 @@ ++package org.bukkit.command; ++ ++import org.jetbrains.annotations.NotNull; ++ ++public class BufferedCommandSender implements MessageCommandSender { ++ private final StringBuffer buffer = new StringBuffer(); ++ @Override ++ public void sendMessage(@NotNull String message) { ++ buffer.append(message); ++ buffer.append("\n"); ++ } ++ ++ @NotNull ++ public String getBuffer() { ++ return buffer.toString(); ++ } ++ ++ public void reset() { ++ this.buffer.setLength(0); ++ } ++} +diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java +index 4bfc214685164a38ba4261b2bae7faa8a3bd297e..03bdc1622791e1206406c87065978688d602e39e 100644 +--- a/src/main/java/org/bukkit/command/Command.java ++++ b/src/main/java/org/bukkit/command/Command.java +@@ -33,7 +33,8 @@ public abstract class Command { + protected String usageMessage; + private String permission; + private String permissionMessage; +- public org.spigotmc.CustomTimingsHandler timings; // Spigot ++ public co.aikar.timings.Timing timings; // Paper ++ @NotNull public String getTimingName() {return getName();} // Paper + + protected Command(@NotNull String name) { + this(name, "", "/" + name, new ArrayList()); +@@ -47,7 +48,6 @@ public abstract class Command { + this.usageMessage = (usageMessage == null) ? "/" + name : usageMessage; + this.aliases = aliases; + this.activeAliases = new ArrayList(aliases); +- this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot + } + + /** +@@ -245,7 +245,6 @@ public abstract class Command { + } + this.nextLabel = name; + if (!isRegistered()) { +- this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot + this.label = name; + return true; + } +diff --git a/src/main/java/org/bukkit/command/FormattedCommandAlias.java b/src/main/java/org/bukkit/command/FormattedCommandAlias.java +index d6c8938b1e13b63116b7b0e074ea8ef5997f8dc3..a6ad94ef98a1df1d2842635d850bc990b0137849 100644 +--- a/src/main/java/org/bukkit/command/FormattedCommandAlias.java ++++ b/src/main/java/org/bukkit/command/FormattedCommandAlias.java +@@ -9,6 +9,7 @@ public class FormattedCommandAlias extends Command { + + public FormattedCommandAlias(@NotNull String alias, @NotNull String[] formatStrings) { + super(alias); ++ timings = co.aikar.timings.TimingsManager.getCommandTiming("minecraft", this); // Spigot + this.formatStrings = formatStrings; + } + +@@ -113,6 +114,10 @@ public class FormattedCommandAlias extends Command { + return formatString; + } + ++ @NotNull ++ @Override // Paper ++ public String getTimingName() {return "Command Forwarder - " + super.getTimingName();} // Paper ++ + private static boolean inRange(int i, int j, int k) { + return i >= j && i <= k; + } +diff --git a/src/main/java/org/bukkit/command/MessageCommandSender.java b/src/main/java/org/bukkit/command/MessageCommandSender.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a7ef1f51c2b96617a32e6e7b1723e8770ba8a6a8 +--- /dev/null ++++ b/src/main/java/org/bukkit/command/MessageCommandSender.java +@@ -0,0 +1,129 @@ ++package org.bukkit.command; ++ ++import org.apache.commons.lang.NotImplementedException; ++import org.bukkit.Bukkit; ++import org.bukkit.Server; ++import org.bukkit.permissions.Permission; ++import org.bukkit.permissions.PermissionAttachment; ++import org.bukkit.permissions.PermissionAttachmentInfo; ++import org.bukkit.plugin.Plugin; ++ ++import java.util.Set; ++import java.util.UUID; ++ ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * For when all you care about is just messaging ++ */ ++public interface MessageCommandSender extends CommandSender { ++ ++ @Override ++ default void sendMessage(@NotNull String[] messages) { ++ for (String message : messages) { ++ sendMessage(message); ++ } ++ } ++ ++ @Override ++ default void sendMessage(@Nullable UUID sender, @NotNull String message) { ++ sendMessage(message); ++ } ++ ++ @Override ++ default void sendMessage(@Nullable UUID sender, @NotNull String[] messages) { ++ for (String message : messages) { ++ sendMessage(message); ++ } ++ } ++ ++ @NotNull ++ @Override ++ default Server getServer() { ++ return Bukkit.getServer(); ++ } ++ ++ @NotNull ++ @Override ++ default String getName() { ++ throw new NotImplementedException(); ++ } ++ ++ @Override ++ default boolean isOp() { ++ throw new NotImplementedException(); ++ } ++ ++ @Override ++ default void setOp(boolean value) { ++ throw new NotImplementedException(); ++ } ++ ++ @Override ++ default boolean isPermissionSet(@NotNull String name) { ++ throw new NotImplementedException(); ++ } ++ ++ @Override ++ default boolean isPermissionSet(@NotNull Permission perm) { ++ throw new NotImplementedException(); ++ } ++ ++ @Override ++ default boolean hasPermission(@NotNull String name) { ++ throw new NotImplementedException(); ++ } ++ ++ @Override ++ default boolean hasPermission(@NotNull Permission perm) { ++ throw new NotImplementedException(); ++ } ++ ++ @NotNull ++ @Override ++ default PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value) { ++ throw new NotImplementedException(); ++ } ++ ++ @NotNull ++ @Override ++ default PermissionAttachment addAttachment(@NotNull Plugin plugin) { ++ throw new NotImplementedException(); ++ } ++ ++ @NotNull ++ @Override ++ default PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks) { ++ throw new NotImplementedException(); ++ } ++ ++ @NotNull ++ @Override ++ default PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks) { ++ throw new NotImplementedException(); ++ } ++ ++ @Override ++ default void removeAttachment(@NotNull PermissionAttachment attachment) { ++ throw new NotImplementedException(); ++ } ++ ++ @Override ++ default void recalculatePermissions() { ++ throw new NotImplementedException(); ++ } ++ ++ @NotNull ++ @Override ++ default Set getEffectivePermissions() { ++ throw new NotImplementedException(); ++ } ++ ++ @NotNull ++ @Override ++ default Spigot spigot() { ++ throw new NotImplementedException(); ++ } ++ ++} +diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java +index 81e4fa57337f5a40c4b673136dd5eb595cce4629..f020cb04eba27a2e70fc7cf799ebbfb434b9d974 100644 +--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java ++++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java +@@ -15,7 +15,6 @@ import org.bukkit.command.defaults.BukkitCommand; + import org.bukkit.command.defaults.HelpCommand; + import org.bukkit.command.defaults.PluginsCommand; + import org.bukkit.command.defaults.ReloadCommand; +-import org.bukkit.command.defaults.TimingsCommand; + import org.bukkit.command.defaults.VersionCommand; + import org.bukkit.entity.Player; + import org.bukkit.util.StringUtil; +@@ -35,7 +34,7 @@ public class SimpleCommandMap implements CommandMap { + register("bukkit", new VersionCommand("version")); + register("bukkit", new ReloadCommand("reload")); + register("bukkit", new PluginsCommand("plugins")); +- register("bukkit", new TimingsCommand("timings")); ++ register("bukkit", new co.aikar.timings.TimingsCommand("timings")); // Paper + } + + public void setFallbackCommands() { +@@ -67,6 +66,7 @@ public class SimpleCommandMap implements CommandMap { + */ + @Override + public boolean register(@NotNull String label, @NotNull String fallbackPrefix, @NotNull Command command) { ++ command.timings = co.aikar.timings.TimingsManager.getCommandTiming(fallbackPrefix, command); // Paper + label = label.toLowerCase(java.util.Locale.ENGLISH).trim(); + fallbackPrefix = fallbackPrefix.toLowerCase(java.util.Locale.ENGLISH).trim(); + boolean registered = register(label, command, false, fallbackPrefix); +@@ -143,16 +143,22 @@ public class SimpleCommandMap implements CommandMap { + return false; + } + ++ // Paper start - Plugins do weird things to workaround normal registration ++ if (target.timings == null) { ++ target.timings = co.aikar.timings.TimingsManager.getCommandTiming(null, target); ++ } ++ // Paper end ++ + try { +- target.timings.startTiming(); // Spigot ++ try (co.aikar.timings.Timing ignored = target.timings.startTiming()) { // Paper - use try with resources + // Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false) + target.execute(sender, sentCommandLabel, Arrays.copyOfRange(args, 1, args.length)); +- target.timings.stopTiming(); // Spigot ++ } // target.timings.stopTiming(); // Spigot // Paper + } catch (CommandException ex) { +- target.timings.stopTiming(); // Spigot ++ //target.timings.stopTiming(); // Spigot // Paper + throw ex; + } catch (Throwable ex) { +- target.timings.stopTiming(); // Spigot ++ //target.timings.stopTiming(); // Spigot // Paper + throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex); + } + +diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java +deleted file mode 100644 +index 2a145d851ce30360aa39549745bd87590c034584..0000000000000000000000000000000000000000 +--- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java ++++ /dev/null +@@ -1,250 +0,0 @@ +-package org.bukkit.command.defaults; +- +-import com.google.common.collect.ImmutableList; +-import java.io.File; +-import java.io.IOException; +-import java.io.PrintStream; +-import java.util.ArrayList; +-import java.util.List; +-import org.apache.commons.lang.Validate; +-import org.bukkit.Bukkit; +-import org.bukkit.ChatColor; +-import org.bukkit.command.CommandSender; +-import org.bukkit.event.Event; +-import org.bukkit.event.HandlerList; +-import org.bukkit.plugin.Plugin; +-import org.bukkit.plugin.RegisteredListener; +-import org.bukkit.plugin.TimedRegisteredListener; +-import org.bukkit.util.StringUtil; +-import org.jetbrains.annotations.NotNull; +- +-// Spigot start +-// CHECKSTYLE:OFF +-import java.io.ByteArrayOutputStream; +-import java.io.OutputStream; +-import java.net.HttpURLConnection; +-import java.net.URL; +-import java.util.logging.Level; +-import org.bukkit.command.RemoteConsoleCommandSender; +-import org.bukkit.plugin.SimplePluginManager; +-import org.spigotmc.CustomTimingsHandler; +-// CHECKSTYLE:ON +-// Spigot end +- +-public class TimingsCommand extends BukkitCommand { +- private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste"); // Spigot +- public static long timingStart = 0; // Spigot +- +- public TimingsCommand(@NotNull String name) { +- super(name); +- this.description = "Manages Spigot Timings data to see performance of the server."; // Spigot +- this.usageMessage = "/timings "; // Spigot +- this.setPermission("bukkit.command.timings"); +- } +- +- // Spigot start - redesigned Timings Command +- public void executeSpigotTimings(@NotNull CommandSender sender, @NotNull String[] args) { +- if ("on".equals(args[0])) { +- ((SimplePluginManager) Bukkit.getPluginManager()).useTimings(true); +- CustomTimingsHandler.reload(); +- sender.sendMessage("Enabled Timings & Reset"); +- return; +- } else if ("off".equals(args[0])) { +- ((SimplePluginManager) Bukkit.getPluginManager()).useTimings(false); +- sender.sendMessage("Disabled Timings"); +- return; +- } +- +- if (!Bukkit.getPluginManager().useTimings()) { +- sender.sendMessage("Please enable timings by typing /timings on"); +- return; +- } +- +- boolean paste = "paste".equals(args[0]); +- if ("reset".equals(args[0])) { +- CustomTimingsHandler.reload(); +- sender.sendMessage("Timings reset"); +- } else if ("merged".equals(args[0]) || "report".equals(args[0]) || paste) { +- long sampleTime = System.nanoTime() - timingStart; +- int index = 0; +- File timingFolder = new File("timings"); +- timingFolder.mkdirs(); +- File timings = new File(timingFolder, "timings.txt"); +- ByteArrayOutputStream bout = (paste) ? new ByteArrayOutputStream() : null; +- while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt"); +- PrintStream fileTimings = null; +- try { +- fileTimings = (paste) ? new PrintStream(bout) : new PrintStream(timings); +- +- CustomTimingsHandler.printTimings(fileTimings); +- fileTimings.println("Sample time " + sampleTime + " (" + sampleTime / 1E9 + "s)"); +- +- fileTimings.println(""); +- fileTimings.println(Bukkit.spigot().getConfig().saveToString()); +- fileTimings.println(""); +- +- if (paste) { +- new PasteThread(sender, bout).start(); +- return; +- } +- +- sender.sendMessage("Timings written to " + timings.getPath()); +- sender.sendMessage("Paste contents of file into form at http://www.spigotmc.org/go/timings to read results."); +- +- } catch (IOException e) { +- } finally { +- if (fileTimings != null) { +- fileTimings.close(); +- } +- } +- } +- } +- // Spigot end +- +- @Override +- public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { +- if (!testPermission(sender)) return true; +- if (args.length < 1) { // Spigot +- sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); +- return false; +- } +- // Spigot start +- if (true) { +- executeSpigotTimings(sender, args); +- return true; +- } +- // Spigot end +- if (!sender.getServer().getPluginManager().useTimings()) { +- sender.sendMessage("Please enable timings by setting \"settings.plugin-profiling\" to true in bukkit.yml"); +- return true; +- } +- +- boolean separate = "separate".equalsIgnoreCase(args[0]); +- if ("reset".equalsIgnoreCase(args[0])) { +- for (HandlerList handlerList : HandlerList.getHandlerLists()) { +- for (RegisteredListener listener : handlerList.getRegisteredListeners()) { +- if (listener instanceof TimedRegisteredListener) { +- ((TimedRegisteredListener) listener).reset(); +- } +- } +- } +- sender.sendMessage("Timings reset"); +- } else if ("merged".equalsIgnoreCase(args[0]) || separate) { +- +- int index = 0; +- int pluginIdx = 0; +- File timingFolder = new File("timings"); +- timingFolder.mkdirs(); +- File timings = new File(timingFolder, "timings.txt"); +- File names = null; +- while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt"); +- PrintStream fileTimings = null; +- PrintStream fileNames = null; +- try { +- fileTimings = new PrintStream(timings); +- if (separate) { +- names = new File(timingFolder, "names" + index + ".txt"); +- fileNames = new PrintStream(names); +- } +- for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { +- pluginIdx++; +- long totalTime = 0; +- if (separate) { +- fileNames.println(pluginIdx + " " + plugin.getDescription().getFullName()); +- fileTimings.println("Plugin " + pluginIdx); +- } else { +- fileTimings.println(plugin.getDescription().getFullName()); +- } +- for (RegisteredListener listener : HandlerList.getRegisteredListeners(plugin)) { +- if (listener instanceof TimedRegisteredListener) { +- TimedRegisteredListener trl = (TimedRegisteredListener) listener; +- long time = trl.getTotalTime(); +- int count = trl.getCount(); +- if (count == 0) continue; +- long avg = time / count; +- totalTime += time; +- Class eventClass = trl.getEventClass(); +- if (count > 0 && eventClass != null) { +- fileTimings.println(" " + eventClass.getSimpleName() + (trl.hasMultiple() ? " (and sub-classes)" : "") + " Time: " + time + " Count: " + count + " Avg: " + avg); +- } +- } +- } +- fileTimings.println(" Total time " + totalTime + " (" + totalTime / 1000000000 + "s)"); +- } +- sender.sendMessage("Timings written to " + timings.getPath()); +- if (separate) sender.sendMessage("Names written to " + names.getPath()); +- } catch (IOException e) { +- } finally { +- if (fileTimings != null) { +- fileTimings.close(); +- } +- if (fileNames != null) { +- fileNames.close(); +- } +- } +- } else { +- sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); +- return false; +- } +- return true; +- } +- +- @NotNull +- @Override +- public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { +- Validate.notNull(sender, "Sender cannot be null"); +- Validate.notNull(args, "Arguments cannot be null"); +- Validate.notNull(alias, "Alias cannot be null"); +- +- if (args.length == 1) { +- return StringUtil.copyPartialMatches(args[0], TIMINGS_SUBCOMMANDS, new ArrayList(TIMINGS_SUBCOMMANDS.size())); +- } +- return ImmutableList.of(); +- } +- +- // Spigot start +- private static class PasteThread extends Thread { +- +- private final CommandSender sender; +- private final ByteArrayOutputStream bout; +- +- public PasteThread(@NotNull CommandSender sender, @NotNull ByteArrayOutputStream bout) { +- super("Timings paste thread"); +- this.sender = sender; +- this.bout = bout; +- } +- +- @Override +- public synchronized void start() { +- if (sender instanceof RemoteConsoleCommandSender) { +- run(); +- } else { +- super.start(); +- } +- } +- +- @Override +- public void run() { +- try { +- HttpURLConnection con = (HttpURLConnection) new URL("https://timings.spigotmc.org/paste").openConnection(); +- con.setDoOutput(true); +- con.setRequestMethod("POST"); +- con.setInstanceFollowRedirects(false); +- +- OutputStream out = con.getOutputStream(); +- out.write(bout.toByteArray()); +- out.close(); +- +- com.google.gson.JsonObject location = new com.google.gson.Gson().fromJson(new java.io.InputStreamReader(con.getInputStream()), com.google.gson.JsonObject.class); +- con.getInputStream().close(); +- +- String pasteID = location.get("key").getAsString(); +- sender.sendMessage(ChatColor.GREEN + "Timings results can be viewed at https://www.spigotmc.org/go/timings?url=" + pasteID); +- } catch (IOException ex) { +- sender.sendMessage(ChatColor.RED + "Error pasting timings, check your console for more information"); +- Bukkit.getServer().getLogger().log(Level.WARNING, "Could not paste timings", ex); +- } +- } +- } +- // Spigot end +-} +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index da1b5b5253c0ac0abe1019096166e6c76a50e699..586fd9ebd02039ebd2c071cbbbf60f24879f96b9 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1368,7 +1368,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); ++ ++ } ++ ++ // Paper start ++ public int getPing() { ++ throw new UnsupportedOperationException( "Not supported yet." ); + } ++ // Paper end + } + + @NotNull +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index 77dcfe35e6a765c8ccb38bc5d900989dc0456b13..7548e40af8043c1b5716f2d7d0122833466854c4 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -358,7 +358,6 @@ public final class SimplePluginManager implements PluginManager { + } + } + +- org.bukkit.command.defaults.TimingsCommand.timingStart = System.nanoTime(); // Spigot + return result.toArray(new Plugin[result.size()]); + } + +@@ -397,9 +396,9 @@ public final class SimplePluginManager implements PluginManager { + + if (result != null) { + plugins.add(result); +- lookupNames.put(result.getDescription().getName(), result); ++ lookupNames.put(result.getDescription().getName().toLowerCase(java.util.Locale.ENGLISH), result); // Paper + for (String provided : result.getDescription().getProvides()) { +- lookupNames.putIfAbsent(provided, result); ++ lookupNames.putIfAbsent(provided.toLowerCase(java.util.Locale.ENGLISH), result); // Paper + } + } + +@@ -428,7 +427,7 @@ public final class SimplePluginManager implements PluginManager { + @Override + @Nullable + public synchronized Plugin getPlugin(@NotNull String name) { +- return lookupNames.get(name.replace(' ', '_')); ++ return lookupNames.get(name.replace(' ', '_').toLowerCase(java.util.Locale.ENGLISH)); // Paper + } + + @Override +@@ -646,7 +645,8 @@ public final class SimplePluginManager implements PluginManager { + throw new IllegalPluginAccessException("Plugin attempted to register " + event + " while not enabled"); + } + +- if (useTimings) { ++ executor = new co.aikar.timings.TimedEventExecutor(executor, plugin, null, event); // Paper ++ if (false) { // Spigot - RL handles useTimings check now // Paper + getEventListeners(event).register(new TimedRegisteredListener(listener, executor, priority, plugin, ignoreCancelled)); + } else { + getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin, ignoreCancelled)); +@@ -861,7 +861,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public boolean useTimings() { +- return useTimings; ++ return co.aikar.timings.Timings.isTimingsEnabled(); // Spigot + } + + /** +@@ -870,6 +870,6 @@ public final class SimplePluginManager implements PluginManager { + * @param use True if per event timing code should be used + */ + public void useTimings(boolean use) { +- useTimings = use; ++ co.aikar.timings.Timings.setTimingsEnabled(use); // Paper + } + } +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index a09c3f71ca563b6f40a118ce1344d0eb273bed40..cf2f517765d8f2a23cc4a17d9ee2dcd81f841b1b 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -54,7 +54,6 @@ public final class JavaPluginLoader implements PluginLoader { + private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; + private final List loaders = new CopyOnWriteArrayList(); + private final LibraryLoader libraryLoader; +- public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot + + /** + * This class was not meant to be constructed explicitly +@@ -292,27 +291,21 @@ public final class JavaPluginLoader implements PluginLoader { + } + } + +- final CustomTimingsHandler timings = new CustomTimingsHandler("Plugin: " + plugin.getDescription().getFullName() + " Event: " + listener.getClass().getName() + "::" + method.getName() + "(" + eventClass.getSimpleName() + ")", pluginParentTimer); // Spigot +- EventExecutor executor = new EventExecutor() { ++ EventExecutor executor = new co.aikar.timings.TimedEventExecutor(new EventExecutor() { // Paper + @Override +- public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { ++ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { // Paper + try { + if (!eventClass.isAssignableFrom(event.getClass())) { + return; + } +- // Spigot start +- boolean isAsync = event.isAsynchronous(); +- if (!isAsync) timings.startTiming(); + method.invoke(listener, event); +- if (!isAsync) timings.stopTiming(); +- // Spigot end + } catch (InvocationTargetException ex) { + throw new EventException(ex.getCause()); + } catch (Throwable t) { + throw new EventException(t); + } + } +- }; ++ }, plugin, method, eventClass); // Paper + if (false) { // Spigot - RL handles useTimings check now + eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); + } else { +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index 6843e32438492f380e2e72bb40dd49d45fe675cb..5ffa98bb9c76d802a9d0ea6c572a704a2732c67c 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -29,7 +29,8 @@ import org.jetbrains.annotations.Nullable; + /** + * A ClassLoader for plugins, to allow shared classes across multiple plugins + */ +-final class PluginClassLoader extends URLClassLoader { ++public final class PluginClassLoader extends URLClassLoader { // Spigot ++ public JavaPlugin getPlugin() { return plugin; } // Spigot + private final JavaPluginLoader loader; + private final Map> classes = new ConcurrentHashMap>(); + private final PluginDescriptionFile description; +diff --git a/src/main/java/org/bukkit/util/CachedServerIcon.java b/src/main/java/org/bukkit/util/CachedServerIcon.java +index 5ca863b3692b2e1b58e7fb4d82f554a92cc4f01e..612958a331575d1da2715531ebdf6b1168f2e860 100644 +--- a/src/main/java/org/bukkit/util/CachedServerIcon.java ++++ b/src/main/java/org/bukkit/util/CachedServerIcon.java +@@ -2,6 +2,7 @@ package org.bukkit.util; + + import org.bukkit.Server; + import org.bukkit.event.server.ServerListPingEvent; ++import org.jetbrains.annotations.Nullable; + + /** + * This is a cached version of a server-icon. It's internal representation +@@ -12,4 +13,9 @@ import org.bukkit.event.server.ServerListPingEvent; + * @see Server#loadServerIcon(java.io.File) + * @see ServerListPingEvent#setServerIcon(CachedServerIcon) + */ +-public interface CachedServerIcon {} ++public interface CachedServerIcon { ++ ++ @Nullable ++ public String getData(); // Paper ++ ++} +diff --git a/src/main/java/org/spigotmc/CustomTimingsHandler.java b/src/main/java/org/spigotmc/CustomTimingsHandler.java +index 44badfedcc3fdc26bdc293b85d8c781d6f659faa..3cbe5c2bb55dead7968a6f165ef267e3e2931061 100644 +--- a/src/main/java/org/spigotmc/CustomTimingsHandler.java ++++ b/src/main/java/org/spigotmc/CustomTimingsHandler.java +@@ -1,3 +1,26 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ + package org.spigotmc; + + import java.io.PrintStream; +@@ -5,133 +28,84 @@ import java.util.Queue; + import java.util.concurrent.ConcurrentLinkedQueue; + import org.bukkit.Bukkit; + import org.bukkit.World; +-import org.bukkit.command.defaults.TimingsCommand; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; ++import org.bukkit.plugin.AuthorNagException; ++import org.bukkit.plugin.Plugin; ++import co.aikar.timings.Timing; ++import co.aikar.timings.Timings; ++import co.aikar.timings.TimingsManager; ++ ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.Method; ++import java.util.logging.Level; + + /** +- * Provides custom timing sections for /timings merged. ++ * This is here for legacy purposes incase any plugin used it. ++ * ++ * If you use this, migrate ASAP as this will be removed in the future! ++ * ++ * @deprecated ++ * @see co.aikar.timings.Timings#of + */ +-public class CustomTimingsHandler { +- +- private static Queue HANDLERS = new ConcurrentLinkedQueue(); +- /*========================================================================*/ +- private final String name; +- private final CustomTimingsHandler parent; +- private long count = 0; +- private long start = 0; +- private long timingDepth = 0; +- private long totalTime = 0; +- private long curTickTotal = 0; +- private long violations = 0; ++@Deprecated ++public final class CustomTimingsHandler { ++ private final Timing handler; ++ private static Boolean sunReflectAvailable; ++ private static Method getCallerClass; + + public CustomTimingsHandler(@NotNull String name) { +- this(name, null); +- } ++ if (sunReflectAvailable == null) { ++ String javaVer = System.getProperty("java.version"); ++ String[] elements = javaVer.split("\\."); + +- public CustomTimingsHandler(@NotNull String name, @Nullable CustomTimingsHandler parent) { +- this.name = name; +- this.parent = parent; +- HANDLERS.add(this); +- } ++ int major = Integer.parseInt(elements.length >= 2 ? elements[1] : javaVer); ++ if (major <= 8) { ++ sunReflectAvailable = true; + +- /** +- * Prints the timings and extra data to the given stream. +- * +- * @param printStream output stream +- */ +- public static void printTimings(@NotNull PrintStream printStream) { +- printStream.println("Minecraft"); +- for (CustomTimingsHandler timings : HANDLERS) { +- long time = timings.totalTime; +- long count = timings.count; +- if (count == 0) { +- continue; ++ try { ++ Class reflection = Class.forName("sun.reflect.Reflection"); ++ getCallerClass = reflection.getMethod("getCallerClass", int.class); ++ } catch (ClassNotFoundException | NoSuchMethodException ignored) { ++ } ++ } else { ++ sunReflectAvailable = false; + } +- long avg = time / count; +- +- printStream.println(" " + timings.name + " Time: " + time + " Count: " + count + " Avg: " + avg + " Violations: " + timings.violations); +- } +- printStream.println("# Version " + Bukkit.getVersion()); +- int entities = 0; +- int livingEntities = 0; +- for (World world : Bukkit.getWorlds()) { +- entities += world.getEntities().size(); +- livingEntities += world.getLivingEntities().size(); + } +- printStream.println("# Entities " + entities); +- printStream.println("# LivingEntities " + livingEntities); +- } + +- /** +- * Resets all timings. +- */ +- public static void reload() { +- if (Bukkit.getPluginManager().useTimings()) { +- for (CustomTimingsHandler timings : HANDLERS) { +- timings.reset(); ++ Class calling = null; ++ if (sunReflectAvailable) { ++ try { ++ calling = (Class) getCallerClass.invoke(null, 2); ++ } catch (IllegalAccessException | InvocationTargetException ignored) { + } + } +- TimingsCommand.timingStart = System.nanoTime(); +- } + +- /** +- * Ticked every tick by CraftBukkit to count the number of times a timer +- * caused TPS loss. +- */ +- public static void tick() { +- if (Bukkit.getPluginManager().useTimings()) { +- for (CustomTimingsHandler timings : HANDLERS) { +- if (timings.curTickTotal > 50000000) { +- timings.violations += Math.ceil(timings.curTickTotal / 50000000); +- } +- timings.curTickTotal = 0; +- timings.timingDepth = 0; // incase reset messes this up +- } +- } +- } ++ Timing timing; + +- /** +- * Starts timing to track a section of code. +- */ +- public void startTiming() { +- // If second condtion fails we are already timing +- if (Bukkit.getPluginManager().useTimings() && ++timingDepth == 1) { +- start = System.nanoTime(); +- if (parent != null && ++parent.timingDepth == 1) { +- parent.start = start; +- } +- } +- } ++ Plugin plugin = null; ++ try { ++ plugin = TimingsManager.getPluginByClassloader(calling); ++ } catch (Exception ignored) {} + +- /** +- * Stops timing a section of code. +- */ +- public void stopTiming() { +- if (Bukkit.getPluginManager().useTimings()) { +- if (--timingDepth != 0 || start == 0) { +- return; +- } +- long diff = System.nanoTime() - start; +- totalTime += diff; +- curTickTotal += diff; +- count++; +- start = 0; +- if (parent != null) { +- parent.stopTiming(); ++ new AuthorNagException("Deprecated use of CustomTimingsHandler. Please Switch to Timings.of ASAP").printStackTrace(); ++ if (plugin != null) { ++ timing = Timings.of(plugin, "(Deprecated API) " + name); ++ } else { ++ try { ++ final Method ofSafe = TimingsManager.class.getDeclaredMethod("getHandler", String.class, String.class, Timing.class); ++ ofSafe.setAccessible(true); ++ timing = (Timing) ofSafe.invoke(null,"Minecraft", "(Deprecated API) " + name, null); ++ } catch (Exception e) { ++ e.printStackTrace(); ++ Bukkit.getLogger().log(Level.SEVERE, "This handler could not be registered"); ++ timing = Timings.NULL_HANDLER; + } + } ++ handler = timing; + } + +- /** +- * Reset this timer, setting all values to zero. +- */ +- public void reset() { +- count = 0; +- violations = 0; +- curTickTotal = 0; +- totalTime = 0; +- start = 0; +- timingDepth = 0; +- } ++ public void startTiming() { handler.startTiming(); } ++ public void stopTiming() { handler.stopTiming(); } ++ + } diff --git a/patches/api-unmapped/0005-Adventure.patch b/patches/api-unmapped/0005-Adventure.patch new file mode 100644 index 0000000000..bbfafdf464 --- /dev/null +++ b/patches/api-unmapped/0005-Adventure.patch @@ -0,0 +1,4124 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Riley Park +Date: Fri, 29 Jan 2021 17:21:55 +0100 +Subject: [PATCH] Adventure + +Co-authored-by: zml +Co-authored-by: Jake Potrebic + +diff --git a/pom.xml b/pom.xml +index 1ebc4c096638128194cea9c2a4131f901e7d6896..cae43ce5c1287a4cd117fd069d34ebc1b64b7fdb 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -22,6 +22,7 @@ + 1.8 + 1.8 + UTF-8 ++ 4.7.0 + + + +@@ -31,7 +32,39 @@ + + + ++ ++ ++ ++ ++ net.kyori ++ adventure-bom ++ ${adventure.version} ++ pom ++ import ++ ++ ++ ++ ++ + ++ ++ ++ net.kyori ++ adventure-api ++ ++ ++ net.kyori ++ adventure-text-serializer-gson ++ ++ ++ net.kyori ++ adventure-text-serializer-legacy ++ ++ ++ net.kyori ++ adventure-text-serializer-plain ++ ++ + + it.unimi.dsi + fastutil +@@ -216,6 +249,12 @@ + https://javadoc.io/doc/org.yaml/snakeyaml/1.27/ + https://javadoc.io/doc/org.jetbrains/annotations-java5/20.1.0/ + https://javadoc.io/doc/net.md-5/bungeecord-chat/1.16-R0.4/ ++ ++ https://jd.adventure.kyori.net/api/${adventure.version}/ ++ https://jd.adventure.kyori.net/text-serializer-gson/${adventure.version}/ ++ https://jd.adventure.kyori.net/text-serializer-legacy/${adventure.version}/ ++ https://jd.adventure.kyori.net/text-serializer-plain/${adventure.version}/ ++ + + + +diff --git a/src/main/java/co/aikar/timings/TimingsReportListener.java b/src/main/java/co/aikar/timings/TimingsReportListener.java +index ef58a6c00f444bd498a2d8fc4e457236f393954f..ecd149157d4fb80444f34bf5633d74bcdb63dec5 100644 +--- a/src/main/java/co/aikar/timings/TimingsReportListener.java ++++ b/src/main/java/co/aikar/timings/TimingsReportListener.java +@@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + + @SuppressWarnings("WeakerAccess") +-public class TimingsReportListener implements MessageCommandSender { ++public class TimingsReportListener implements net.kyori.adventure.audience.ForwardingAudience, MessageCommandSender { // Paper + private final List senders; + private final Runnable onDone; + private String timingsURL; +@@ -74,4 +74,17 @@ public class TimingsReportListener implements MessageCommandSender { + this.senders.add(Bukkit.getConsoleSender()); + } + } ++ ++ // Paper start ++ @Override ++ public void sendMessage(final @NotNull net.kyori.adventure.identity.Identity source, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { ++ net.kyori.adventure.audience.ForwardingAudience.super.sendMessage(source, message, type); ++ } ++ ++ @NotNull ++ @Override ++ public Iterable audiences() { ++ return this.senders; ++ } ++ // Paper end + } +diff --git a/src/main/java/io/papermc/paper/chat/ChatComposer.java b/src/main/java/io/papermc/paper/chat/ChatComposer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7d2fb50210246bb42d166f7e6d1c0cdfad0bdb3d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/chat/ChatComposer.java +@@ -0,0 +1,29 @@ ++package io.papermc.paper.chat; ++ ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A chat composer is responsible for composing chat messages sent by {@link Player}s to the server. ++ * ++ * @deprecated for removal with 1.17, in favor of {@link ChatRenderer} ++ */ ++@Deprecated ++@FunctionalInterface ++public interface ChatComposer { ++ ChatComposer DEFAULT = (player, displayName, message) -> Component.translatable("chat.type.text", displayName, message); ++ ++ /** ++ * Composes a chat message. ++ * ++ * @param source the message source ++ * @param displayName the display name of the {@link Player} sending the message ++ * @param message the chat message ++ * @return a composed chat message ++ * @deprecated for removal with 1.17 ++ */ ++ @Deprecated ++ @NotNull ++ Component composeChat(final @NotNull Player source, final @NotNull Component displayName, final @NotNull Component message); ++} +diff --git a/src/main/java/io/papermc/paper/chat/ChatFormatter.java b/src/main/java/io/papermc/paper/chat/ChatFormatter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ba784ab037adfd37b01b222ea33abea00161ecae +--- /dev/null ++++ b/src/main/java/io/papermc/paper/chat/ChatFormatter.java +@@ -0,0 +1,29 @@ ++package io.papermc.paper.chat; ++ ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A chat formatter is responsible for the formatting of chat messages sent by {@link Player}s to the server. ++ * ++ * @deprecated for removal with 1.17, in favour of {@link ChatRenderer} ++ */ ++@Deprecated ++@FunctionalInterface ++public interface ChatFormatter { ++ @Deprecated ++ ChatFormatter DEFAULT = (displayName, message) -> Component.translatable("chat.type.text", displayName, message); ++ ++ /** ++ * Formats a chat message. ++ * ++ * @param displayName the display name of the {@link Player} sending the message ++ * @param message the chat message ++ * @return a formatted chat message ++ * @deprecated for removal with 1.17 ++ */ ++ @Deprecated ++ @NotNull ++ Component chat(final @NotNull Component displayName, final @NotNull Component message); ++} +diff --git a/src/main/java/io/papermc/paper/chat/ChatRenderer.java b/src/main/java/io/papermc/paper/chat/ChatRenderer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..85fd5d6777b53bab09cc54c360bb75141635bdd3 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/chat/ChatRenderer.java +@@ -0,0 +1,75 @@ ++package io.papermc.paper.chat; ++ ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A chat renderer is responsible for rendering chat messages sent by {@link Player}s to the server. ++ */ ++@FunctionalInterface ++public interface ChatRenderer { ++ /** ++ * Renders a chat message. This will be called once for each receiving {@link Audience}. ++ * ++ * @param source the message source ++ * @param sourceDisplayName the display name of the source player ++ * @param message the chat message ++ * @param viewer the receiving {@link Audience} ++ * @return a rendered chat message ++ */ ++ @NotNull ++ Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message, @NotNull Audience viewer); ++ ++ /** ++ * Create a new instance of the default {@link ChatRenderer}. ++ * ++ * @return a new {@link ChatRenderer} ++ */ ++ @NotNull ++ static ChatRenderer defaultRenderer() { ++ return viewerUnaware((source, sourceDisplayName, message) -> Component.translatable("chat.type.text", sourceDisplayName, message)); ++ } ++ ++ /** ++ * Creates a new viewer-unaware {@link ChatRenderer}, which will render the chat message a single time, ++ * displaying the same rendered message to every viewing {@link Audience}. ++ * ++ * @param renderer the viewer unaware renderer ++ * @return a new {@link ChatRenderer} ++ */ ++ @NotNull ++ static ChatRenderer viewerUnaware(final @NotNull ViewerUnaware renderer) { ++ return new ChatRenderer() { ++ private @MonotonicNonNull Component message; ++ ++ @Override ++ public @NotNull Component render(final @NotNull Player source, final @NotNull Component sourceDisplayName, final @NotNull Component message, final @NotNull Audience viewer) { ++ if (this.message == null) { ++ this.message = renderer.render(source, sourceDisplayName, message); ++ } ++ return this.message; ++ } ++ }; ++ } ++ ++ /** ++ * Similar to {@link ChatRenderer}, but without knowledge of the message viewer. ++ * ++ * @see ChatRenderer#viewerUnaware(ViewerUnaware) ++ */ ++ interface ViewerUnaware { ++ /** ++ * Renders a chat message. ++ * ++ * @param source the message source ++ * @param sourceDisplayName the display name of the source player ++ * @param message the chat message ++ * @return a rendered chat message ++ */ ++ @NotNull ++ Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java b/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..718b860ace4077affad715a4e43961e10a83e9d9 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java +@@ -0,0 +1,299 @@ ++package io.papermc.paper.event.player; ++ ++import io.papermc.paper.chat.ChatComposer; ++import io.papermc.paper.chat.ChatFormatter; ++import java.util.HashSet; ++import java.util.Set; ++import io.papermc.paper.chat.ChatRenderer; ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.audience.ForwardingAudience; ++import net.kyori.adventure.text.Component; ++import org.bukkit.Bukkit; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.player.PlayerEvent; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++import org.jetbrains.annotations.NotNull; ++ ++import static java.util.Objects.requireNonNull; ++ ++/** ++ * An abstract implementation of a chat event, handling shared logic. ++ */ ++public abstract class AbstractChatEvent extends PlayerEvent implements Cancellable { ++ private final Set viewers; ++ @Deprecated private final Set recipients; ++ private boolean cancelled = false; ++ private ChatRenderer renderer; ++ @Deprecated private @Nullable ChatComposer composer; ++ @Deprecated private @Nullable ChatFormatter formatter; ++ private final Component originalMessage; ++ private Component message; ++ ++ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { ++ super(player, async); ++ this.viewers = viewers; ++ this.recipients = new HashSet<>(Bukkit.getOnlinePlayers()); ++ this.renderer = renderer; ++ this.message = message; ++ this.originalMessage = originalMessage; ++ } ++ ++ /** ++ * @deprecated for removal with 1.17 ++ */ ++ @Deprecated ++ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { ++ super(player, async); ++ this.viewers = viewers; ++ this.recipients = new HashSet<>(Bukkit.getOnlinePlayers()); ++ this.renderer = renderer; ++ this.message = message; ++ this.originalMessage = message; ++ } ++ ++ /** ++ * @deprecated for removal with 1.17 ++ */ ++ @Deprecated ++ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { ++ super(player, async); ++ this.recipients = recipients; ++ this.viewers = viewers; ++ this.renderer = renderer; ++ this.message = message; ++ this.originalMessage = originalMessage; ++ } ++ ++ /** ++ * @deprecated for removal with 1.17 ++ */ ++ @Deprecated ++ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { ++ super(player, async); ++ this.recipients = recipients; ++ this.viewers = viewers; ++ this.renderer = renderer; ++ this.message = message; ++ this.originalMessage = message; ++ } ++ ++ /** ++ * @deprecated for removal with 1.17 ++ */ ++ @Deprecated ++ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatComposer composer, final @NotNull Component message) { ++ super(player, async); ++ this.recipients = recipients; ++ final Set audiences = new HashSet<>(recipients); ++ audiences.add(Bukkit.getConsoleSender()); ++ this.viewers = audiences; ++ this.composer = composer; ++ this.message = message; ++ this.originalMessage = message; ++ } ++ ++ /** ++ * @deprecated for removal with 1.17 ++ */ ++ @Deprecated ++ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) { ++ super(player, async); ++ this.recipients = recipients; ++ final Set audiences = new HashSet<>(recipients); ++ audiences.add(Bukkit.getConsoleSender()); ++ this.viewers = audiences; ++ this.formatter = formatter; ++ this.message = message; ++ this.originalMessage = message; ++ } ++ ++ /** ++ * Gets a set of {@link Audience audiences} that this chat message will be displayed to. ++ * ++ *

    The set returned is not guaranteed to be mutable and may auto-populate ++ * on access. Any listener accessing the returned set should be aware that ++ * it may reduce performance for a lazy set implementation.

    ++ * ++ *

    Listeners should be aware that modifying the list may throw {@link ++ * UnsupportedOperationException} if the event caller provides an ++ * unmodifiable set.

    ++ * ++ * @return a set of {@link Audience audiences} who will receive the chat message ++ */ ++ @NotNull ++ public final Set viewers() { ++ return this.viewers; ++ } ++ ++ /** ++ * Gets a set of recipients that this chat message will be displayed to. ++ * ++ *

    The set returned is not guaranteed to be mutable and may auto-populate ++ * on access. Any listener accessing the returned set should be aware that ++ * it may reduce performance for a lazy set implementation.

    ++ * ++ *

    Listeners should be aware that modifying the list may throw {@link ++ * UnsupportedOperationException} if the event caller provides an ++ * unmodifiable set.

    ++ * ++ * @return a set of players who will receive the chat message ++ * @deprecated for removal with 1.17, in favor of {@link #viewers()} ++ */ ++ @Deprecated ++ @NotNull ++ public final Set recipients() { ++ return this.recipients; ++ } ++ ++ /** ++ * Sets the chat renderer. ++ * ++ * @param renderer the chat renderer ++ * @throws NullPointerException if {@code renderer} is {@code null} ++ */ ++ public final void renderer(final @NotNull ChatRenderer renderer) { ++ this.renderer = requireNonNull(renderer, "renderer"); ++ this.formatter = null; ++ this.composer = null; ++ } ++ ++ /** ++ * Gets the chat renderer. ++ * ++ * @return the chat renderer ++ */ ++ @NotNull ++ public final ChatRenderer renderer() { ++ if(this.renderer == null) { ++ if(this.composer != null) { ++ this.renderer = ChatRenderer.viewerUnaware((source, displayName, message) -> this.composer.composeChat(source, source.displayName(), message)); ++ } else { ++ requireNonNull(this.formatter, "renderer, composer, and formatter"); ++ this.renderer = ChatRenderer.viewerUnaware((source, displayName, message) -> this.formatter.chat(source.displayName(), message)); ++ } ++ } ++ return this.renderer; ++ } ++ ++ /** ++ * Gets the chat composer. ++ * ++ * @return the chat composer ++ * @deprecated for removal with 1.17, in favour of {@link #renderer()} ++ */ ++ @Deprecated ++ @NotNull ++ public final ChatComposer composer() { ++ if(this.composer == null) { ++ if(this.renderer != null) { ++ this.composer = (source, displayName, message) -> this.renderer.render(source, displayName, message, this.legacyForwardingAudience()); ++ } else { ++ requireNonNull(this.formatter, "renderer, composer, and formatter"); ++ this.composer = (source, displayName, message) -> this.formatter.chat(displayName, message); ++ } ++ } ++ return this.composer; ++ } ++ ++ /** ++ * Sets the chat composer. ++ * ++ * @param composer the chat composer ++ * @throws NullPointerException if {@code composer} is {@code null} ++ * @deprecated for removal with 1.17, in favour of {@link #renderer(ChatRenderer)} ++ */ ++ @Deprecated ++ public final void composer(final @NotNull ChatComposer composer) { ++ this.composer = requireNonNull(composer, "composer"); ++ this.formatter = null; ++ this.renderer = null; ++ } ++ ++ /** ++ * Gets the chat formatter. ++ * ++ * @return the chat formatter ++ * @deprecated for removal with 1.17, in favour of {@link #renderer()} ++ */ ++ @Deprecated ++ @NotNull ++ public final ChatFormatter formatter() { ++ if(this.formatter == null) { ++ if(this.renderer != null) { ++ this.formatter = (displayName, message) -> this.renderer.render(this.player, displayName, message, this.legacyForwardingAudience()); ++ } else { ++ requireNonNull(this.composer, "renderer, composer, and formatter"); ++ this.formatter = (displayName, message) -> this.composer.composeChat(this.player, displayName, message); ++ } ++ } ++ return this.formatter; ++ } ++ ++ /** ++ * Sets the chat formatter. ++ * ++ * @param formatter the chat formatter ++ * @throws NullPointerException if {@code formatter} is {@code null} ++ * @deprecated for removal with 1.17, in favour of {@link #renderer(ChatRenderer)} ++ */ ++ @Deprecated ++ public final void formatter(final @NotNull ChatFormatter formatter) { ++ this.formatter = requireNonNull(formatter, "formatter"); ++ this.composer = null; ++ this.renderer = null; ++ } ++ ++ /** ++ * Gets the user-supplied message. ++ * The return value will reflect changes made using {@link #message(Component)}. ++ * ++ * @return the user-supplied message ++ */ ++ @NotNull ++ public final Component message() { ++ return this.message; ++ } ++ ++ /** ++ * Sets the user-supplied message. ++ * ++ * @param message the user-supplied message ++ * @throws NullPointerException if {@code message} is {@code null} ++ */ ++ public final void message(final @NotNull Component message) { ++ this.message = requireNonNull(message, "message"); ++ } ++ ++ /** ++ * Gets the original and unmodified user-supplied message. ++ * The return value will not reflect changes made using ++ * {@link #message(Component)}. ++ * ++ * @return the original user-supplied message ++ */ ++ @NotNull ++ public final Component originalMessage() { ++ return this.originalMessage; ++ } ++ ++ @Override ++ public final boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public final void setCancelled(final boolean cancelled) { ++ this.cancelled = cancelled; ++ } ++ ++ private @NotNull Audience legacyForwardingAudience() { ++ return new ForwardingAudience() { ++ @Override ++ public @NonNull Iterable audiences() { ++ return AbstractChatEvent.this.viewers; ++ } ++ }; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ee7ec316a2f814ec759e0a3e5dfe5efbee782b22 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java +@@ -0,0 +1,73 @@ ++package io.papermc.paper.event.player; ++ ++import io.papermc.paper.chat.ChatComposer; ++import io.papermc.paper.chat.ChatFormatter; ++import java.util.Set; ++import io.papermc.paper.chat.ChatRenderer; ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * An event fired when a {@link Player} sends a chat message to the server. ++ */ ++public final class AsyncChatEvent extends AbstractChatEvent { ++ private static final HandlerList HANDLERS = new HandlerList(); ++ ++ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { ++ super(async, player, viewers, renderer, message, originalMessage); ++ } ++ ++ /** ++ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} ++ */ ++ @Deprecated ++ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { ++ super(async, player, viewers, renderer, message); ++ } ++ ++ /** ++ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} ++ */ ++ @Deprecated ++ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { ++ super(async, player, recipients, viewers, renderer, message, originalMessage); ++ } ++ ++ /** ++ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} ++ */ ++ @Deprecated ++ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { ++ super(async, player, recipients, viewers, renderer, message); ++ } ++ ++ /** ++ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} ++ */ ++ @Deprecated ++ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatComposer composer, final @NotNull Component message) { ++ super(async, player, recipients, composer, message); ++ } ++ ++ /** ++ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} ++ */ ++ @Deprecated ++ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) { ++ super(async, player, recipients, formatter, message); ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLERS; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLERS; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/player/ChatEvent.java b/src/main/java/io/papermc/paper/event/player/ChatEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c6bcf0dc3f77c631aa7eeb9b1e88b5bbfe445fc6 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/ChatEvent.java +@@ -0,0 +1,70 @@ ++package io.papermc.paper.event.player; ++ ++import io.papermc.paper.chat.ChatComposer; ++import io.papermc.paper.chat.ChatFormatter; ++import java.util.Set; ++import io.papermc.paper.chat.ChatRenderer; ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.text.Component; ++import org.bukkit.Warning; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * An event fired when a {@link Player} sends a chat message to the server. ++ * ++ * @deprecated Listening to this event forces chat to wait for the main thread, delaying chat messages. It is recommended to use {@link AsyncChatEvent} instead, wherever possible. ++ */ ++@Deprecated ++@Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.") ++public final class ChatEvent extends AbstractChatEvent { ++ private static final HandlerList HANDLERS = new HandlerList(); ++ ++ public ChatEvent(final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { ++ super(false, player, viewers, renderer, message, originalMessage); ++ } ++ ++ /** ++ * @deprecated for removal with 1.17, use {@link #ChatEvent(Player, Set, ChatRenderer, Component, Component)} ++ */ ++ @Deprecated ++ public ChatEvent(final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { ++ super(false, player, viewers, renderer, message); ++ } ++ ++ /** ++ * @deprecated for removal with 1.17, use {@link #ChatEvent(Player, Set, ChatRenderer, Component, Component)} ++ */ ++ @Deprecated ++ public ChatEvent(final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { ++ super(false, player, recipients, viewers, renderer, message, originalMessage); ++ } ++ ++ /** ++ * @deprecated for removal with 1.17, use {@link #ChatEvent(Player, Set, ChatRenderer, Component, Component)} ++ */ ++ @Deprecated ++ public ChatEvent(final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatComposer composer, final @NotNull Component message) { ++ super(false, player, recipients, composer, message); ++ } ++ ++ /** ++ * @deprecated for removal with 1.17, use {@link #ChatEvent(Player, Set, ChatRenderer, Component, Component)} ++ */ ++ @Deprecated ++ public ChatEvent(final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) { ++ super(false, player, recipients, formatter, message); ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLERS; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLERS; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/text/PaperComponents.java b/src/main/java/io/papermc/paper/text/PaperComponents.java +new file mode 100644 +index 0000000000000000000000000000000000000000..77db592d05b754f879f8d1790642e9d9bbd30a4e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/text/PaperComponents.java +@@ -0,0 +1,88 @@ ++package io.papermc.paper.text; ++ ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.flattener.ComponentFlattener; ++import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; ++import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; ++import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; ++import org.bukkit.Bukkit; ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++/** ++ * Paper API-specific methods for working with {@link Component}s and related. ++ */ ++public final class PaperComponents { ++ private PaperComponents() { ++ throw new RuntimeException("PaperComponents is not to be instantiated!"); ++ } ++ ++ /** ++ * Return a component flattener that can use game data to resolve extra information about components. ++ * ++ * @return a component flattener ++ */ ++ public static @NonNull ComponentFlattener flattener() { ++ return Bukkit.getUnsafe().componentFlattener(); ++ } ++ ++ /** ++ * Get a serializer for {@link Component}s that will convert components to ++ * a plain-text string. ++ * ++ *

    Implementations may provide a serializer capable of processing any ++ * information that requires access to implementation details.

    ++ * ++ * @return a serializer to plain text ++ */ ++ public static @NonNull PlainComponentSerializer plainSerializer() { ++ return Bukkit.getUnsafe().plainComponentSerializer(); ++ } ++ ++ /** ++ * Get a serializer for {@link Component}s that will convert to and from the ++ * standard JSON serialization format using Gson. ++ * ++ *

    Implementations may provide a serializer capable of processing any ++ * information that requires implementation details, such as legacy ++ * (pre-1.16) hover events.

    ++ * ++ * @return a json component serializer ++ */ ++ public static @NonNull GsonComponentSerializer gsonSerializer() { ++ return Bukkit.getUnsafe().gsonComponentSerializer(); ++ } ++ ++ /** ++ * Get a serializer for {@link Component}s that will convert to and from the ++ * standard JSON serialization format using Gson, downsampling any RGB colors ++ * to their nearest {@link NamedTextColor} counterpart. ++ * ++ *

    Implementations may provide a serializer capable of processing any ++ * information that requires implementation details, such as legacy ++ * (pre-1.16) hover events.

    ++ * ++ * @return a json component serializer ++ */ ++ public static @NonNull GsonComponentSerializer colorDownsamplingGsonSerializer() { ++ return Bukkit.getUnsafe().colorDownsamplingGsonComponentSerializer(); ++ } ++ ++ /** ++ * Get a serializer for {@link Component}s that will convert to and from the ++ * legacy component format used by Bukkit. This serializer uses the ++ * {@link LegacyComponentSerializer.Builder#useUnusualXRepeatedCharacterHexFormat()} ++ * option to match upstream behavior. ++ * ++ *

    This legacy serializer uses the standard section symbol to mark ++ * formatting characters.

    ++ * ++ *

    Implementations may provide a serializer capable of processing any ++ * information that requires access to implementation details.

    ++ * ++ * @return a section serializer ++ */ ++ public static @NonNull LegacyComponentSerializer legacySectionSerializer() { ++ return Bukkit.getUnsafe().legacyComponentSerializer(); ++ } ++} +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 7c715fdc11ab7837552b1fe3ffd08b31cec0a63b..f3b07f0f1b3be14c8ecd059e1f3594cc90f84442 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -278,7 +278,9 @@ public final class Bukkit { + * + * @param message the message + * @return the number of players ++ * @deprecated in favour of {@link Server#broadcast(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public static int broadcastMessage(@NotNull String message) { + return server.broadcastMessage(message); + } +@@ -836,6 +838,19 @@ public final class Bukkit { + server.shutdown(); + } + ++ // Paper start ++ /** ++ * Broadcast a message to all players. ++ *

    ++ * This is the same as calling {@link #broadcast(net.kyori.adventure.text.Component, ++ * java.lang.String)} with the {@link Server#BROADCAST_CHANNEL_USERS} permission. ++ * ++ * @param message the message ++ * @return the number of players ++ */ ++ public static int broadcast(@NotNull net.kyori.adventure.text.Component message) { ++ return server.broadcast(message); ++ } + /** + * Broadcasts the specified message to every user with the given + * permission name. +@@ -845,6 +860,21 @@ public final class Bukkit { + * permissibles} must have to receive the broadcast + * @return number of message recipients + */ ++ public static int broadcast(@NotNull net.kyori.adventure.text.Component message, @NotNull String permission) { ++ return server.broadcast(message, permission); ++ } ++ // Paper end ++ /** ++ * Broadcasts the specified message to every user with the given ++ * permission name. ++ * ++ * @param message message to broadcast ++ * @param permission the required permission {@link Permissible ++ * permissibles} must have to receive the broadcast ++ * @return number of message recipients ++ * @deprecated in favour of {@link #broadcast(net.kyori.adventure.text.Component, String)} ++ */ ++ @Deprecated // Paper + public static int broadcast(@NotNull String message, @NotNull String permission) { + return server.broadcast(message, permission); + } +@@ -1044,6 +1074,7 @@ public final class Bukkit { + return server.createInventory(owner, type); + } + ++ // Paper start + /** + * 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; +@@ -1069,6 +1100,38 @@ public final class Bukkit { + * @see InventoryType#isCreatable() + */ + @NotNull ++ public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull net.kyori.adventure.text.Component title) { ++ return server.createInventory(owner, type, title); ++ } ++ // Paper end ++ ++ /** ++ * 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; ++ * otherwise the new inventory has the normal size for its type.
    ++ * It should be noted that some inventory types do not support titles and ++ * may not render with said titles on the Minecraft client. ++ *
    ++ * {@link InventoryType#WORKBENCH} will not process crafting recipes if ++ * created with this method. Use ++ * {@link Player#openWorkbench(Location, boolean)} instead. ++ *
    ++ * {@link InventoryType#ENCHANTING} will not process {@link ItemStack}s ++ * for possible enchanting results. Use ++ * {@link Player#openEnchanting(Location, boolean)} instead. ++ * ++ * @param owner The holder of the inventory; can be null if there's no holder. ++ * @param type The type of inventory to create. ++ * @param title The title of the inventory, to be displayed when it is viewed. ++ * @return The new inventory. ++ * @throws IllegalArgumentException if the {@link InventoryType} cannot be ++ * viewed. ++ * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} ++ * ++ * @see InventoryType#isCreatable() ++ */ ++ @Deprecated // Paper ++ @NotNull + public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title) { + return server.createInventory(owner, type, title); + } +@@ -1087,6 +1150,7 @@ public final class Bukkit { + return server.createInventory(owner, size); + } + ++ // Paper start + /** + * Creates an empty inventory of type {@link InventoryType#CHEST} with the + * specified size and title. +@@ -1099,10 +1163,30 @@ public final class Bukkit { + * @throws IllegalArgumentException if the size is not a multiple of 9 + */ + @NotNull ++ public static Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull net.kyori.adventure.text.Component title) throws IllegalArgumentException { ++ return server.createInventory(owner, size, title); ++ } ++ // Paper end ++ ++ /** ++ * Creates an empty inventory of type {@link InventoryType#CHEST} with the ++ * specified size and title. ++ * ++ * @param owner the holder of the inventory, or null to indicate no holder ++ * @param size a multiple of 9 as the size of inventory to create ++ * @param title the title of the inventory, displayed when inventory is ++ * viewed ++ * @return a new inventory ++ * @throws IllegalArgumentException if the size is not a multiple of 9 ++ * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated // Paper ++ @NotNull + public static Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException { + return server.createInventory(owner, size, title); + } + ++ // Paper start + /** + * Creates an empty merchant. + * +@@ -1110,7 +1194,20 @@ public final class Bukkit { + * when the merchant inventory is viewed + * @return a new merchant + */ ++ public static @NotNull Merchant createMerchant(@Nullable net.kyori.adventure.text.Component title) { ++ return server.createMerchant(title); ++ } ++ // Paper start ++ /** ++ * Creates an empty merchant. ++ * ++ * @param title the title of the corresponding merchant inventory, displayed ++ * when the merchant inventory is viewed ++ * @return a new merchant ++ * @deprecated in favour of {@link #createMerchant(net.kyori.adventure.text.Component)} ++ */ + @NotNull ++ @Deprecated // Paper + public static Merchant createMerchant(@Nullable String title) { + return server.createMerchant(title); + } +@@ -1181,22 +1278,47 @@ public final class Bukkit { + return server.isPrimaryThread(); + } + ++ // Paper start ++ /** ++ * Gets the message that is displayed on the server list. ++ * ++ * @return the server's MOTD ++ */ ++ @NotNull public static net.kyori.adventure.text.Component motd() { ++ return server.motd(); ++ } ++ // Paper end ++ + /** + * Gets the message that is displayed on the server list. + * + * @return the servers MOTD ++ * @deprecated in favour of {@link #motd()} + */ + @NotNull ++ @Deprecated // Paper + public static String getMotd() { + return server.getMotd(); + } + ++ // Paper start ++ /** ++ * Gets the default message that is displayed when the server is stopped. ++ * ++ * @return the shutdown message ++ */ ++ public static @Nullable net.kyori.adventure.text.Component shutdownMessage() { ++ return server.shutdownMessage(); ++ } ++ // Paper end + /** + * Gets the default message that is displayed when the server is stopped. + * + * @return the shutdown message ++ * @deprecated in favour of {@link #shutdownMessage()} + */ + @Nullable ++ @Deprecated // Paper + public static String getShutdownMessage() { + return server.getShutdownMessage(); + } +diff --git a/src/main/java/org/bukkit/Nameable.java b/src/main/java/org/bukkit/Nameable.java +index fee814e01a653d2b53c56e8b566383ca44aa5346..2acdf2a6d3955923c721222b9da784f3278f6418 100644 +--- a/src/main/java/org/bukkit/Nameable.java ++++ b/src/main/java/org/bukkit/Nameable.java +@@ -4,6 +4,30 @@ import org.jetbrains.annotations.Nullable; + + public interface Nameable { + ++ // Paper start ++ /** ++ * Gets the custom name. ++ * ++ *

    This value has no effect on players, they will always use their real name.

    ++ * ++ * @return the custom name ++ */ ++ @Nullable net.kyori.adventure.text.Component customName(); ++ ++ /** ++ * Sets the custom name. ++ * ++ *

    This name will be used in death messages and can be sent to the client as a nameplate over the mob.

    ++ * ++ *

    Setting the name to {@code null} will clear it.

    ++ * ++ *

    This value has no effect on players, they will always use their real name.

    ++ * ++ * @param customName the custom name to set ++ */ ++ void customName(final @Nullable net.kyori.adventure.text.Component customName); ++ // Paper end ++ + /** + * Gets the custom name on a mob or block. If there is no name this method + * will return null. +diff --git a/src/main/java/org/bukkit/NamespacedKey.java b/src/main/java/org/bukkit/NamespacedKey.java +index 803fa0019869127ee8c7e4fb1777a59c43e66f8a..c65f0d6569c130b4920a9e71ad24af6427f1f030 100644 +--- a/src/main/java/org/bukkit/NamespacedKey.java ++++ b/src/main/java/org/bukkit/NamespacedKey.java +@@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable; + * underscores, hyphens, and forward slashes. + * + */ +-public final class NamespacedKey { ++public final class NamespacedKey implements net.kyori.adventure.key.Key { // Paper - implement Key + + /** + * The namespace representing all inbuilt keys. +@@ -212,4 +212,24 @@ public final class NamespacedKey { + public static NamespacedKey fromString(@NotNull String key) { + return fromString(key, null); + } ++ ++ // Paper start ++ @NotNull ++ @Override ++ public String namespace() { ++ return this.getNamespace(); ++ } ++ ++ @NotNull ++ @Override ++ public String value() { ++ return this.getKey(); ++ } ++ ++ @NotNull ++ @Override ++ public String asString() { ++ return this.namespace + ':' + this.key; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index a6b9e4f158583e5932bf8ca210d531857e9f5360..7abdbf43e2f52e8e9e0f7bd7c7a58baf347e3929 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -55,13 +55,13 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a server implementation. + */ +-public interface Server extends PluginMessageRecipient { ++public interface Server extends PluginMessageRecipient, net.kyori.adventure.audience.ForwardingAudience { // Paper + + /** + * Used for all administrative messages, such as an operator using a + * command. + *

    +- * For use in {@link #broadcast(java.lang.String, java.lang.String)}. ++ * For use in {@link #broadcast(net.kyori.adventure.text.Component, java.lang.String)}. + */ + public static final String BROADCAST_CHANNEL_ADMINISTRATIVE = "bukkit.broadcast.admin"; + +@@ -69,7 +69,7 @@ public interface Server extends PluginMessageRecipient { + * Used for all announcement messages, such as informing users that a + * player has joined. + *

    +- * For use in {@link #broadcast(java.lang.String, java.lang.String)}. ++ * For use in {@link #broadcast(net.kyori.adventure.text.Component, java.lang.String)}. + */ + public static final String BROADCAST_CHANNEL_USERS = "bukkit.broadcast.user"; + +@@ -229,7 +229,9 @@ public interface Server extends PluginMessageRecipient { + * + * @param message the message + * @return the number of players ++ * @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public int broadcastMessage(@NotNull String message); + + /** +@@ -703,8 +705,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 ++ * @deprecated in favour of {@link #broadcast(net.kyori.adventure.text.Component, String)} + */ ++ @Deprecated // Paper + public int broadcast(@NotNull String message, @NotNull String permission); ++ // Paper start ++ /** ++ * Broadcast a message to all players. ++ *

    ++ * This is the same as calling {@link #broadcast(net.kyori.adventure.text.Component, ++ * java.lang.String)} with the {@link #BROADCAST_CHANNEL_USERS} permission. ++ * ++ * @param message the message ++ * @return the number of players ++ */ ++ int broadcast(@NotNull net.kyori.adventure.text.Component message); ++ ++ /** ++ * Broadcasts the specified message to every user with the given ++ * permission name. ++ * ++ * @param message message to broadcast ++ * @param permission the required permission {@link Permissible ++ * permissibles} must have to receive the broadcast ++ * @return number of message recipients ++ */ ++ int broadcast(@NotNull net.kyori.adventure.text.Component message, @NotNull String permission); ++ // Paper end + + /** + * Gets the player by the given name, regardless if they are offline or +@@ -869,6 +896,7 @@ public interface Server extends PluginMessageRecipient { + @NotNull + Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type); + ++ // Paper start + /** + * 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; +@@ -894,6 +922,36 @@ public interface Server extends PluginMessageRecipient { + * @see InventoryType#isCreatable() + */ + @NotNull ++ Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull net.kyori.adventure.text.Component title); ++ // Paper end ++ ++ /** ++ * 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; ++ * otherwise the new inventory has the normal size for its type.
    ++ * It should be noted that some inventory types do not support titles and ++ * may not render with said titles on the Minecraft client. ++ *
    ++ * {@link InventoryType#WORKBENCH} will not process crafting recipes if ++ * created with this method. Use ++ * {@link Player#openWorkbench(Location, boolean)} instead. ++ *
    ++ * {@link InventoryType#ENCHANTING} will not process {@link ItemStack}s ++ * for possible enchanting results. Use ++ * {@link Player#openEnchanting(Location, boolean)} instead. ++ * ++ * @param owner The holder of the inventory; can be null if there's no holder. ++ * @param type The type of inventory to create. ++ * @param title The title of the inventory, to be displayed when it is viewed. ++ * @return The new inventory. ++ * @throws IllegalArgumentException if the {@link InventoryType} cannot be ++ * viewed. ++ * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} ++ * ++ * @see InventoryType#isCreatable() ++ */ ++ @Deprecated // Paper ++ @NotNull + Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title); + + /** +@@ -908,6 +966,22 @@ public interface Server extends PluginMessageRecipient { + @NotNull + Inventory createInventory(@Nullable InventoryHolder owner, int size) throws IllegalArgumentException; + ++ // Paper start ++ /** ++ * Creates an empty inventory of type {@link InventoryType#CHEST} with the ++ * specified size and title. ++ * ++ * @param owner the holder of the inventory, or null to indicate no holder ++ * @param size a multiple of 9 as the size of inventory to create ++ * @param title the title of the inventory, displayed when inventory is ++ * viewed ++ * @return a new inventory ++ * @throws IllegalArgumentException if the size is not a multiple of 9 ++ */ ++ @NotNull ++ Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull net.kyori.adventure.text.Component title) throws IllegalArgumentException; ++ // Paper end ++ + /** + * Creates an empty inventory of type {@link InventoryType#CHEST} with the + * specified size and title. +@@ -918,10 +992,13 @@ public interface Server extends PluginMessageRecipient { + * viewed + * @return a new inventory + * @throws IllegalArgumentException if the size is not a multiple of 9 ++ * @deprecated in favour of {@link #createInventory(InventoryHolder, int, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + @NotNull + Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException; + ++ // Paper start + /** + * Creates an empty merchant. + * +@@ -929,7 +1006,18 @@ public interface Server extends PluginMessageRecipient { + * when the merchant inventory is viewed + * @return a new merchant + */ ++ @NotNull Merchant createMerchant(@Nullable net.kyori.adventure.text.Component title); ++ // Paper start ++ /** ++ * Creates an empty merchant. ++ * ++ * @param title the title of the corresponding merchant inventory, displayed ++ * when the merchant inventory is viewed ++ * @return a new merchant ++ * @deprecated in favour of {@link #createMerchant(net.kyori.adventure.text.Component)} ++ */ + @NotNull ++ @Deprecated // Paper + Merchant createMerchant(@Nullable String title); + + /** +@@ -986,20 +1074,41 @@ public interface Server extends PluginMessageRecipient { + */ + boolean isPrimaryThread(); + ++ // Paper start ++ /** ++ * Gets the message that is displayed on the server list. ++ * ++ * @return the server's MOTD ++ */ ++ @NotNull net.kyori.adventure.text.Component motd(); ++ // Paper end ++ + /** + * Gets the message that is displayed on the server list. + * + * @return the servers MOTD ++ * @deprecated in favour of {@link #motd()} + */ + @NotNull ++ @Deprecated // Paper + String getMotd(); + ++ // Paper start ++ /** ++ * Gets the default message that is displayed when the server is stopped. ++ * ++ * @return the shutdown message ++ */ ++ @Nullable net.kyori.adventure.text.Component shutdownMessage(); ++ // Paper end + /** + * Gets the default message that is displayed when the server is stopped. + * + * @return the shutdown message ++ * @deprecated in favour of {@link #shutdownMessage()} + */ + @Nullable ++ @Deprecated // Paper + String getShutdownMessage(); + + /** +@@ -1368,7 +1477,9 @@ public interface Server extends PluginMessageRecipient { + * Sends the component to the player + * + * @param component the components to send ++ * @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -1377,7 +1488,9 @@ public interface Server extends PluginMessageRecipient { + * Sends an array of components as a single message to the player + * + * @param components the components to send ++ * @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); + } +diff --git a/src/main/java/org/bukkit/Sound.java b/src/main/java/org/bukkit/Sound.java +index 2c8cc0c2af4741df9ae594ab9c436dea5347167c..445b6bf18e6ee26fe6cafca8cf5f1775bcd72d1e 100644 +--- a/src/main/java/org/bukkit/Sound.java ++++ b/src/main/java/org/bukkit/Sound.java +@@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; + * guarantee values will not be removed from this Enum. As such, you should not + * depend on the ordinal values of this class. + */ +-public enum Sound implements Keyed { ++public enum Sound implements Keyed, net.kyori.adventure.sound.Sound.Type { // Paper - implement Sound.Type + + AMBIENT_BASALT_DELTAS_ADDITIONS("ambient.basalt_deltas.additions"), + AMBIENT_BASALT_DELTAS_LOOP("ambient.basalt_deltas.loop"), +@@ -1214,4 +1214,12 @@ public enum Sound implements Keyed { + public NamespacedKey getKey() { + return key; + } ++ ++ // Paper start ++ @NotNull ++ @Override ++ public net.kyori.adventure.key.@org.checkerframework.checker.nullness.qual.NonNull Key key() { ++ return this.key; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 945b8b030d1b2a13afc0c4efad76997eb7bf00ba..207c656c0a11a3a630bc70491efcf433b2681e18 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -17,6 +17,13 @@ import org.bukkit.plugin.PluginDescriptionFile; + */ + @Deprecated + public interface UnsafeValues { ++ // Paper start ++ net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener(); ++ net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer(); ++ net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer(); ++ net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer(); ++ net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer(); ++ // Paper end + + void reportTimings(); // Paper + Material toLegacy(Material material); +diff --git a/src/main/java/org/bukkit/Warning.java b/src/main/java/org/bukkit/Warning.java +index efb97712cc9dc7c1e12a59f5b94e4f2ad7c6b7d8..3024468af4c073324e536c1cb26beffb1e09f3f4 100644 +--- a/src/main/java/org/bukkit/Warning.java ++++ b/src/main/java/org/bukkit/Warning.java +@@ -67,6 +67,7 @@ public @interface Warning { + * + */ + public boolean printFor(@Nullable Warning warning) { ++ if (Boolean.getBoolean("paper.alwaysPrintWarningState")) return true; // Paper + if (this == DEFAULT) { + return warning == null || warning.value(); + } +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index bc4417d8ffa92a78f690bfa5705d3e42cdc11fd2..d3519fa5b99e2888a194c6382415537785fbeef0 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -38,7 +38,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a world, which may contain entities, chunks and blocks + */ +-public interface World extends PluginMessageRecipient, Metadatable { ++public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience { // Paper + + /** + * Gets the {@link Block} at the given coordinates +@@ -640,6 +640,14 @@ public interface World extends PluginMessageRecipient, Metadatable { + @NotNull + public List getPlayers(); + ++ // Paper start ++ @NotNull ++ @Override ++ default Iterable audiences() { ++ return this.getPlayers(); ++ } ++ // Paper end ++ + /** + * Returns a list of entities within a bounding box centered around a + * Location. +diff --git a/src/main/java/org/bukkit/block/Sign.java b/src/main/java/org/bukkit/block/Sign.java +index a52dff9ef1c1cd7d3705e66510dfa2c91119539c..cdcf02ff9e80f5908a8fa22e82701445d5e2d298 100644 +--- a/src/main/java/org/bukkit/block/Sign.java ++++ b/src/main/java/org/bukkit/block/Sign.java +@@ -7,13 +7,48 @@ import org.jetbrains.annotations.NotNull; + * Represents a captured state of either a SignPost or a WallSign. + */ + public interface Sign extends TileState, Colorable { ++ // Paper start ++ /** ++ * Gets all the lines of text currently on this sign. ++ * ++ * @return Array of Strings containing each line of text ++ */ ++ @NotNull ++ public java.util.List lines(); ++ ++ /** ++ * Gets the line of text at the specified index. ++ *

    ++ * For example, getLine(0) will return the first line of text. ++ * ++ * @param index Line number to get the text from, starting at 0 ++ * @throws IndexOutOfBoundsException Thrown when the line does not exist ++ * @return Text on the given line ++ */ ++ @NotNull ++ public net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException; ++ ++ /** ++ * Sets the line of text at the specified index. ++ *

    ++ * For example, setLine(0, "Line One") will set the first line of text to ++ * "Line One". ++ * ++ * @param index Line number to set the text at, starting from 0 ++ * @param line New text to set at the specified index ++ * @throws IndexOutOfBoundsException If the index is out of the range 0..3 ++ */ ++ public void line(int index, @NotNull net.kyori.adventure.text.Component line) throws IndexOutOfBoundsException; ++ // Paper end + + /** + * Gets all the lines of text currently on this sign. + * + * @return Array of Strings containing each line of text ++ * @deprecated in favour of {@link #lines()} + */ + @NotNull ++ @Deprecated // Paper + public String[] getLines(); + + /** +@@ -24,8 +59,10 @@ public interface Sign extends TileState, Colorable { + * @param index Line number to get the text from, starting at 0 + * @throws IndexOutOfBoundsException Thrown when the line does not exist + * @return Text on the given line ++ * @deprecated in favour of {@link #line(int)} + */ + @NotNull ++ @Deprecated // Paper + public String getLine(int index) throws IndexOutOfBoundsException; + + /** +@@ -37,7 +74,9 @@ public interface Sign extends TileState, Colorable { + * @param index Line number to set the text at, starting from 0 + * @param line New text to set at the specified index + * @throws IndexOutOfBoundsException If the index is out of the range 0..3 ++ * @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException; + + /** +diff --git a/src/main/java/org/bukkit/command/CommandSender.java b/src/main/java/org/bukkit/command/CommandSender.java +index ac772bf349e0ffe9cab1df165d9460b387f2fe69..c88418c7aa19b4fecdfa9af3d18ff202a5dc5763 100644 +--- a/src/main/java/org/bukkit/command/CommandSender.java ++++ b/src/main/java/org/bukkit/command/CommandSender.java +@@ -6,12 +6,13 @@ import org.bukkit.permissions.Permissible; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + +-public interface CommandSender extends Permissible { ++public interface CommandSender extends net.kyori.adventure.audience.Audience, Permissible { // Paper + + /** + * Sends this sender a message + * + * @param message Message to be displayed ++ * @see #sendMessage(net.kyori.adventure.text.Component) + */ + public void sendMessage(@NotNull String message); + +@@ -19,6 +20,7 @@ public interface CommandSender extends Permissible { + * Sends this sender multiple messages + * + * @param messages An array of messages to be displayed ++ * @see #sendMessage(net.kyori.adventure.text.Component) + */ + public void sendMessage(@NotNull String[] messages); + +@@ -27,6 +29,7 @@ public interface CommandSender extends Permissible { + * + * @param message Message to be displayed + * @param sender The sender of this message ++ * @see #sendMessage(net.kyori.adventure.identity.Identified, net.kyori.adventure.text.Component) + */ + public void sendMessage(@Nullable UUID sender, @NotNull String message); + +@@ -35,6 +38,7 @@ public interface CommandSender extends Permissible { + * + * @param messages An array of messages to be displayed + * @param sender The sender of this message ++ * @see #sendMessage(net.kyori.adventure.identity.Identified, net.kyori.adventure.text.Component) + */ + public void sendMessage(@Nullable UUID sender, @NotNull String[] messages); + +@@ -61,7 +65,9 @@ public interface CommandSender extends Permissible { + * Sends this sender a chat component. + * + * @param component the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -70,7 +76,9 @@ public interface CommandSender extends Permissible { + * Sends an array of components as a single message to the sender. + * + * @param components the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -80,7 +88,9 @@ public interface CommandSender extends Permissible { + * + * @param component the components to send + * @param sender the sender of the message ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -90,7 +100,9 @@ public interface CommandSender extends Permissible { + * + * @param components the components to send + * @param sender the sender of the message ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -99,4 +111,11 @@ public interface CommandSender extends Permissible { + @NotNull + Spigot spigot(); + // Spigot end ++ ++ // Paper start ++ @Override ++ default void sendMessage(final @NotNull net.kyori.adventure.identity.Identity identity, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { ++ this.sendMessage(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(message)); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/command/ProxiedCommandSender.java b/src/main/java/org/bukkit/command/ProxiedCommandSender.java +index fcc34b640265f4dccb46b9f09466ab8e1d96043e..74599b4ee0518481c0e3a5f6ab2f5302837f1ae3 100644 +--- a/src/main/java/org/bukkit/command/ProxiedCommandSender.java ++++ b/src/main/java/org/bukkit/command/ProxiedCommandSender.java +@@ -3,7 +3,7 @@ package org.bukkit.command; + + import org.jetbrains.annotations.NotNull; + +-public interface ProxiedCommandSender extends CommandSender { ++public interface ProxiedCommandSender extends CommandSender, net.kyori.adventure.audience.ForwardingAudience.Single { // Paper + + /** + * Returns the CommandSender which triggered this proxied command +@@ -21,4 +21,16 @@ public interface ProxiedCommandSender extends CommandSender { + @NotNull + CommandSender getCallee(); + ++ // Paper start ++ @Override ++ default void sendMessage(final @NotNull net.kyori.adventure.identity.Identity source, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { ++ net.kyori.adventure.audience.ForwardingAudience.Single.super.sendMessage(source, message, type); ++ } ++ ++ @NotNull ++ @Override ++ default net.kyori.adventure.audience.Audience audience() { ++ return this.getCaller(); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java +index b833ef63fbe01271ceb2bd83a9eb4a84c9912761..8eb0497c81744874809ebc4bc2e28b128e66a926 100644 +--- a/src/main/java/org/bukkit/enchantments/Enchantment.java ++++ b/src/main/java/org/bukkit/enchantments/Enchantment.java +@@ -294,6 +294,19 @@ public abstract class Enchantment implements Keyed { + * @return True if the enchantment may be applied, otherwise False + */ + public abstract boolean canEnchantItem(@NotNull ItemStack item); ++ // Paper start ++ /** ++ * Get the name of the enchantment with its applied level. ++ *

    ++ * If the given {@code level} is either less than the {@link #getStartLevel()} or greater than the {@link #getMaxLevel()}, ++ * the level may not be shown in the numeral format one may otherwise expect. ++ *

    ++ * ++ * @param level the level of the enchantment to show ++ * @return the name of the enchantment with {@code level} applied ++ */ ++ public abstract @NotNull net.kyori.adventure.text.Component displayName(int level); ++ // Paper end + + @Override + public boolean equals(Object obj) { +diff --git a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java +index 9566e4306ada5e82dede0f002aa06da12c44996b..4d5f0837bd0e02a30c943d8969fb6b13452322e0 100644 +--- a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java ++++ b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java +@@ -63,4 +63,11 @@ public class EnchantmentWrapper extends Enchantment { + public boolean conflictsWith(@NotNull Enchantment other) { + return getEnchantment().conflictsWith(other); + } ++ // Paper start ++ @NotNull ++ @Override ++ public net.kyori.adventure.text.Component displayName(int level) { ++ return getEnchantment().displayName(level); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 0831f2519a32cf1c5c7d5b72864bcb1c22c52eda..03e12de470f983e89a473c4e42c21941085b1d37 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a base entity in the world + */ +-public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder { ++public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource { // Paper + + /** + * Gets the entity's current position +@@ -648,4 +648,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + @Override + Spigot spigot(); + // Spigot end ++ ++ // Paper start ++ @NotNull ++ @Override ++ default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { ++ return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.customName()))); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5a2f8469c 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -30,7 +30,28 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a player, connected or not + */ +-public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient { ++public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified { // Paper ++ ++ // Paper start ++ @Override ++ default @NotNull net.kyori.adventure.identity.Identity identity() { ++ return net.kyori.adventure.identity.Identity.identity(this.getUniqueId()); ++ } ++ ++ /** ++ * Gets the "friendly" name to display of this player. ++ * ++ * @return the display name ++ */ ++ @NotNull net.kyori.adventure.text.Component displayName(); ++ ++ /** ++ * Sets the "friendly" name to display of this player. ++ * ++ * @param displayName the display name to set ++ */ ++ void displayName(final @Nullable net.kyori.adventure.text.Component displayName); ++ // Paper end + + /** + * Gets the "friendly" name to display of this player. This may include +@@ -40,7 +61,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * places defined by plugins. + * + * @return the friendly name ++ * @deprecated in favour of {@link #displayName()} + */ ++ @Deprecated // Paper + @NotNull + public String getDisplayName(); + +@@ -52,15 +75,50 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * places defined by plugins. + * + * @param name The new display name. ++ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setDisplayName(@Nullable String name); + ++ // Paper start ++ /** ++ * Sets the name that is shown on the in-game player list. ++ *

    ++ * If the value is null, the name will be identical to {@link #getName()}. ++ * ++ * @param name new player list name ++ */ ++ void playerListName(@Nullable net.kyori.adventure.text.Component name); ++ ++ /** ++ * Gets the name that is shown on the in-game player list. ++ * ++ * @return the player list name ++ */ ++ @Nullable net.kyori.adventure.text.Component playerListName(); ++ ++ /** ++ * Gets the currently displayed player list header for this player. ++ * ++ * @return player list header or null ++ */ ++ @Nullable net.kyori.adventure.text.Component playerListHeader(); ++ ++ /** ++ * Gets the currently displayed player list footer for this player. ++ * ++ * @return player list footer or null ++ */ ++ @Nullable net.kyori.adventure.text.Component playerListFooter(); ++ // Paper end + /** + * Gets the name that is shown on the player list. + * + * @return the player list name ++ * @deprecated in favour of {@link #playerListName()} + */ + @NotNull ++ @Deprecated // Paper + public String getPlayerListName(); + + /** +@@ -69,14 +127,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * If the value is null, the name will be identical to {@link #getName()}. + * + * @param name new player list name ++ * @deprecated in favour of {@link #playerListName(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setPlayerListName(@Nullable String name); + + /** + * Gets the currently displayed player list header for this player. + * + * @return player list header or null ++ * @deprecated in favour of {@link #playerListHeader()} + */ ++ @Deprecated // Paper + @Nullable + public String getPlayerListHeader(); + +@@ -84,7 +146,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * Gets the currently displayed player list footer for this player. + * + * @return player list header or null ++ * @deprecated in favour of {@link #playerListFooter()} + */ ++ @Deprecated // Paper + @Nullable + public String getPlayerListFooter(); + +@@ -92,14 +156,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * Sets the currently displayed player list header for this player. + * + * @param header player list header, null for empty ++ * @deprecated in favour of {@link #sendPlayerListHeader(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setPlayerListHeader(@Nullable String header); + + /** + * Sets the currently displayed player list footer for this player. + * + * @param footer player list footer, null for empty ++ * @deprecated in favour of {@link #sendPlayerListFooter(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setPlayerListFooter(@Nullable String footer); + + /** +@@ -108,7 +176,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * + * @param header player list header, null for empty + * @param footer player list footer, null for empty ++ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setPlayerListHeaderFooter(@Nullable String header, @Nullable String footer); + + /** +@@ -146,9 +216,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * Kicks player with custom kick message. + * + * @param message kick message ++ * @deprecated in favour of {@link #kick(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void kickPlayer(@Nullable String message); + ++ // Paper start ++ /** ++ * Kicks player with custom kick message. ++ * ++ * @param message kick message ++ */ ++ void kick(final @Nullable net.kyori.adventure.text.Component message); ++ // Paper end ++ + /** + * Says a message (or runs a command). + * +@@ -448,6 +529,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + @Deprecated + public boolean sendChunkChange(@NotNull Location loc, int sx, int sy, int sz, @NotNull byte[] data); + ++ // Paper start + /** + * Send a sign change. This fakes a sign change packet for a user at + * a certain location. This will not actually change the world in any way. +@@ -463,6 +545,43 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @throws IllegalArgumentException if location is null + * @throws IllegalArgumentException if lines is non-null and has a length less than 4 + */ ++ void sendSignChange(@NotNull Location loc, @Nullable java.util.List lines) throws IllegalArgumentException; ++ /** ++ * Send a sign change. This fakes a sign change packet for a user at ++ * a certain location. This will not actually change the world in any way. ++ * This method will use a sign at the location's block or a faked sign ++ * sent via ++ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. ++ *

    ++ * If the client does not have a sign at the given location it will ++ * display an error message to the user. ++ * ++ * @param loc the location of the sign ++ * @param lines the new text on the sign or null to clear it ++ * @param dyeColor the color of the sign ++ * @throws IllegalArgumentException if location is null ++ * @throws IllegalArgumentException if dyeColor is null ++ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 ++ */ ++ void sendSignChange(@NotNull Location loc, @Nullable java.util.List lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException; ++ // Paper end ++ /** ++ * Send a sign change. This fakes a sign change packet for a user at ++ * a certain location. This will not actually change the world in any way. ++ * This method will use a sign at the location's block or a faked sign ++ * sent via ++ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. ++ *

    ++ * If the client does not have a sign at the given location it will ++ * display an error message to the user. ++ * ++ * @param loc the location of the sign ++ * @param lines the new text on the sign or null to clear it ++ * @throws IllegalArgumentException if location is null ++ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 ++ * @deprecated in favour of {@link #sendSignChange(org.bukkit.Location, java.util.List)} ++ */ ++ @Deprecated // Paper + public void sendSignChange(@NotNull Location loc, @Nullable String[] lines) throws IllegalArgumentException; + + +@@ -482,7 +601,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @throws IllegalArgumentException if location is null + * @throws IllegalArgumentException if dyeColor is null + * @throws IllegalArgumentException if lines is non-null and has a length less than 4 ++ * @deprecated in favour of {@link #sendSignChange(org.bukkit.Location, java.util.List, org.bukkit.DyeColor)} + */ ++ @Deprecated // Paper + public void sendSignChange(@NotNull Location loc, @Nullable String[] lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException; + + /** +@@ -1220,6 +1341,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public int getClientViewDistance(); + ++ // Paper start ++ /** ++ * Gets the player's current locale. ++ * ++ * @return the player's locale ++ */ ++ @NotNull java.util.Locale locale(); ++ // Paper end + /** + * Gets the player's estimated ping in milliseconds. + * +@@ -1245,8 +1374,10 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * they wish. + * + * @return the player's locale ++ * @deprecated in favour of {@link #locale()} + */ + @NotNull ++ @Deprecated // Paper + public String getLocale(); + + /** +@@ -1264,6 +1395,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public void openBook(@NotNull ItemStack book); + ++ // Paper start ++ @NotNull ++ @Override ++ default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { ++ return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.displayName()))); ++ } ++ // Paper end ++ + // Spigot start + public class Spigot extends Entity.Spigot { + +@@ -1318,11 +1457,13 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + throw new UnsupportedOperationException("Not supported yet."); + } + ++ @Deprecated // Paper + @Override + public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { + throw new UnsupportedOperationException("Not supported yet."); + } + ++ @Deprecated // Paper + @Override + public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); +@@ -1333,7 +1474,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * + * @param position the screen position + * @param component the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -1343,7 +1486,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * + * @param position the screen position + * @param components the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -1354,7 +1499,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @param position the screen position + * @param sender the sender of the message + * @param component the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -1365,7 +1512,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @param position the screen position + * @param sender the sender of the message + * @param components the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); + +diff --git a/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java b/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java +index 63c80b4ee1f7adc8a9efc3b607993104b1991f90..91cab8b13d5bba34007f124838b32a1df58c5ac7 100644 +--- a/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java ++++ b/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java +@@ -32,7 +32,9 @@ public interface CommandMinecart extends Minecart { + * same as setting it to "@". + * + * @param name New name for this CommandMinecart. ++ * @deprecated in favour of {@link #customName(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setName(@Nullable String name); + + } +diff --git a/src/main/java/org/bukkit/event/block/SignChangeEvent.java b/src/main/java/org/bukkit/event/block/SignChangeEvent.java +index 7190db11eff7d48df8a99f405a9dbaefdfa76e3d..1f79f704abf339150df08900b8ea7da4cefef258 100644 +--- a/src/main/java/org/bukkit/event/block/SignChangeEvent.java ++++ b/src/main/java/org/bukkit/event/block/SignChangeEvent.java +@@ -16,12 +16,25 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private boolean cancel = false; + private final Player player; +- private final String[] lines; ++ // Paper start ++ private final java.util.List adventure$lines; + ++ public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player player, @NotNull final java.util.List adventure$lines) { ++ super(theBlock); ++ this.player = player; ++ this.adventure$lines = adventure$lines; ++ } ++ ++ @Deprecated // Paper end + public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player thePlayer, @NotNull final String[] theLines) { + super(theBlock); + this.player = thePlayer; +- this.lines = theLines; ++ // Paper start ++ this.adventure$lines = new java.util.ArrayList<>(); ++ for (String theLine : theLines) { ++ this.adventure$lines.add(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(theLine)); ++ } ++ // Paper end + } + + /** +@@ -34,14 +47,52 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { + return player; + } + ++ // Paper start ++ /** ++ * Gets all of the lines of text from the sign involved in this event. ++ * ++ * @return the String array for the sign's lines new text ++ */ ++ public @NotNull java.util.List lines() { ++ return this.adventure$lines; ++ } ++ ++ /** ++ * Gets a single line of text from the sign involved in this event. ++ * ++ * @param index index of the line to get ++ * @return the String containing the line of text associated with the ++ * provided index ++ * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 ++ * or < 0} ++ */ ++ public @Nullable net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException { ++ return this.adventure$lines.get(index); ++ } ++ ++ /** ++ * Sets a single line for the sign involved in this event ++ * ++ * @param index index of the line to set ++ * @param line text to set ++ * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 ++ * or < 0} ++ */ ++ public void line(int index, @Nullable net.kyori.adventure.text.Component line) throws IndexOutOfBoundsException { ++ this.adventure$lines.set(index, line); ++ } ++ // Paper end ++ + /** + * Gets all of the lines of text from the sign involved in this event. + * + * @return the String array for the sign's lines new text ++ * @deprecated in favour of {@link #lines()} + */ + @NotNull ++ @Deprecated // Paper + public String[] getLines() { +- return lines; ++ return adventure$lines.stream().map(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer()::serialize).toArray(String[]::new); // Paper + } + + /** +@@ -52,10 +103,12 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { + * provided index + * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 + * or < 0} ++ * @deprecated in favour of {@link #line(int)} + */ + @Nullable ++ @Deprecated // Paper + public String getLine(int index) throws IndexOutOfBoundsException { +- return lines[index]; ++ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.adventure$lines.get(index)); // Paper + } + + /** +@@ -65,9 +118,11 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { + * @param line text to set + * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 + * or < 0} ++ * @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setLine(int index, @Nullable String line) throws IndexOutOfBoundsException { +- lines[index] = line; ++ adventure$lines.set(index, line != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(line) : null); // Paper + } + + @Override +diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +index 3c2ea8fec3a748cab7f5ad9100d12bd8213ec6c9..a01d4c21bedc7f1a54f5a330bb4c2909ce3a18e4 100644 +--- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java ++++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +@@ -12,25 +12,48 @@ import org.jetbrains.annotations.Nullable; + public class PlayerDeathEvent extends EntityDeathEvent { + private int newExp = 0; + private String deathMessage = ""; ++ private net.kyori.adventure.text.Component adventure$deathMessage; // Paper + private int newLevel = 0; + private int newTotalExp = 0; + private boolean keepLevel = false; + private boolean keepInventory = false; ++ // Paper start ++ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage) { ++ this(player, drops, droppedExp, 0, adventure$deathMessage, null); ++ } ++ ++ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage) { ++ this(player, drops, droppedExp, newExp, 0, 0, adventure$deathMessage, deathMessage); ++ } + ++ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage) { ++ super(player, drops, droppedExp); ++ this.newExp = newExp; ++ this.newTotalExp = newTotalExp; ++ this.newLevel = newLevel; ++ this.deathMessage = deathMessage; ++ this.adventure$deathMessage = adventure$deathMessage; ++ } ++ // Paper end ++ ++ @Deprecated // Paper + public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final String deathMessage) { + this(player, drops, droppedExp, 0, deathMessage); + } + ++ @Deprecated // Paper + public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, @Nullable final String deathMessage) { + this(player, drops, droppedExp, newExp, 0, 0, deathMessage); + } + ++ @Deprecated // Paper + public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final String deathMessage) { + super(player, drops, droppedExp); + this.newExp = newExp; + this.newTotalExp = newTotalExp; + this.newLevel = newLevel; + this.deathMessage = deathMessage; ++ this.adventure$deathMessage = deathMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(deathMessage) : net.kyori.adventure.text.Component.empty(); // Paper + } + + @NotNull +@@ -39,25 +62,55 @@ public class PlayerDeathEvent extends EntityDeathEvent { + return (Player) entity; + } + ++ // Paper start ++ /** ++ * Set the death message that will appear to everyone on the server. ++ * ++ * @param deathMessage Message to appear to other players on the server. ++ */ ++ public void deathMessage(@Nullable net.kyori.adventure.text.Component deathMessage) { ++ this.deathMessage = null; ++ this.adventure$deathMessage = deathMessage; ++ } ++ ++ /** ++ * Get the death message that will appear to everyone on the server. ++ * ++ * @return Message to appear to other players on the server. ++ */ ++ public @Nullable net.kyori.adventure.text.Component deathMessage() { ++ return this.adventure$deathMessage; ++ } ++ // Paper end ++ + /** + * Set the death message that will appear to everyone on the server. + * + * @param deathMessage Message to appear to other players on the server. ++ * @deprecated in favour of {@link #deathMessage(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setDeathMessage(@Nullable String deathMessage) { + this.deathMessage = deathMessage; ++ this.adventure$deathMessage = deathMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(deathMessage) : net.kyori.adventure.text.Component.empty(); // Paper + } + + /** + * Get the death message that will appear to everyone on the server. + * + * @return Message to appear to other players on the server. ++ * @deprecated in favour of {@link #deathMessage()} + */ + @Nullable ++ @Deprecated // Paper + public String getDeathMessage() { +- return deathMessage; ++ return this.deathMessage != null ? this.deathMessage : (this.adventure$deathMessage != null ? getDeathMessageString(this.adventure$deathMessage) : null); // Paper + } +- ++ // Paper start //TODO: add translation API to drop String deathMessage in favor of just Adventure ++ private static String getDeathMessageString(net.kyori.adventure.text.Component component) { ++ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(component); ++ } ++ // Paper end + /** + * Gets how much EXP the Player should have at respawn. + *

    +diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java +index f1e9bc9bc797b7216336d3470e3c696a06f2b21a..090d22bd30f7947103771aaaf09a2398970ac337 100644 +--- a/src/main/java/org/bukkit/event/inventory/InventoryType.java ++++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java +@@ -136,6 +136,18 @@ public enum InventoryType { + private final String title; + private final boolean isCreatable; + ++ // Paper start ++ private final net.kyori.adventure.text.Component defaultTitleComponent; ++ ++ /** ++ * Gets the inventory's default title. ++ * ++ * @return the inventory's default title ++ */ ++ public @NotNull net.kyori.adventure.text.Component defaultTitle() { ++ return defaultTitleComponent; ++ } ++ // Paper end + private InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle) { + this(defaultSize, defaultTitle, true); + } +@@ -144,6 +156,7 @@ public enum InventoryType { + size = defaultSize; + title = defaultTitle; + this.isCreatable = isCreatable; ++ this.defaultTitleComponent = net.kyori.adventure.text.Component.text(defaultTitle); // Paper - Adventure + } + + public int getDefaultSize() { +@@ -151,6 +164,7 @@ public enum InventoryType { + } + + @NotNull ++ @Deprecated // Paper + public String getDefaultTitle() { + return title; + } +diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java +index 9c68c3f2d61500479f48b80264f625aaae2f3204..399afcd19fcb6acd24857ed6ab48cf0d105a01a3 100644 +--- a/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java ++++ b/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java +@@ -22,7 +22,11 @@ import org.jetbrains.annotations.NotNull; + *

    + * Care should be taken to check {@link #isAsynchronous()} and treat the event + * appropriately. ++ * ++ * @deprecated use {@link io.papermc.paper.event.player.AsyncChatEvent} instead + */ ++@Deprecated // Paper ++@org.bukkit.Warning(value = false, reason = "Don't nag on old event yet") // Paper + public class AsyncPlayerChatEvent extends PlayerEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private boolean cancel = false; +diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +index c8384da69af61e1970f254a3a9c206ee81d7a989..d3b4219a57fff4519ef8d803c333c854fafa7859 100644 +--- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java ++++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +@@ -14,7 +14,7 @@ import org.jetbrains.annotations.NotNull; + public class AsyncPlayerPreLoginEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + private Result result; +- private String message; ++ private net.kyori.adventure.text.Component message; // Paper + private final String name; + private final InetAddress ipAddress; + private final UUID uniqueId; +@@ -27,7 +27,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId) { + super(true); + this.result = Result.ALLOWED; +- this.message = ""; ++ this.message = net.kyori.adventure.text.Component.empty(); // Paper + this.name = name; + this.ipAddress = ipAddress; + this.uniqueId = uniqueId; +@@ -79,6 +79,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + this.result = result == null ? null : Result.valueOf(result.name()); + } + ++ // Paper start + /** + * Gets the current kick message that will be used if getResult() != + * Result.ALLOWED +@@ -86,7 +87,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + * @return Current kick message + */ + @NotNull +- public String getKickMessage() { ++ public net.kyori.adventure.text.Component kickMessage() { + return message; + } + +@@ -95,16 +96,66 @@ public class AsyncPlayerPreLoginEvent extends Event { + * + * @param message New kick message + */ +- public void setKickMessage(@NotNull final String message) { ++ public void kickMessage(@NotNull final net.kyori.adventure.text.Component message) { ++ this.message = message; ++ } ++ ++ /** ++ * Disallows the player from logging in, with the given reason ++ * ++ * @param result New result for disallowing the player ++ * @param message Kick message to display to the user ++ */ ++ public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { ++ this.result = result; + this.message = message; + } + ++ /** ++ * Disallows the player from logging in, with the given reason ++ * ++ * @param result New result for disallowing the player ++ * @param message Kick message to display to the user ++ * @deprecated This method uses a deprecated enum from {@link ++ * PlayerPreLoginEvent} ++ * @see #disallow(Result, String) ++ */ ++ @Deprecated ++ public void disallow(@NotNull final PlayerPreLoginEvent.Result result, @NotNull final net.kyori.adventure.text.Component message) { ++ this.result = result == null ? null : Result.valueOf(result.name()); ++ this.message = message; ++ } ++ // Paper end ++ /** ++ * Gets the current kick message that will be used if getResult() != ++ * Result.ALLOWED ++ * ++ * @return Current kick message ++ * @deprecated in favour of {@link #kickMessage()} ++ */ ++ @NotNull ++ @Deprecated // Paper ++ public String getKickMessage() { ++ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); // Paper ++ } ++ ++ /** ++ * Sets the kick message to display if getResult() != Result.ALLOWED ++ * ++ * @param message New kick message ++ * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated // Paper ++ public void setKickMessage(@NotNull final String message) { ++ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper ++ } ++ + /** + * Allows the player to log in + */ + public void allow() { + result = Result.ALLOWED; +- message = ""; ++ message = net.kyori.adventure.text.Component.empty(); // Paper + } + + /** +@@ -112,10 +163,12 @@ public class AsyncPlayerPreLoginEvent extends Event { + * + * @param result New result for disallowing the player + * @param message Kick message to display to the user ++ * @deprecated in favour of {@link #disallow(org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void disallow(@NotNull final Result result, @NotNull final String message) { + this.result = result; +- this.message = message; ++ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper + } + + /** +@@ -130,7 +183,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + @Deprecated + public void disallow(@NotNull final PlayerPreLoginEvent.Result result, @NotNull final String message) { + this.result = result == null ? null : Result.valueOf(result.name()); +- this.message = message; ++ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper + } + + /** +diff --git a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java +index 8ea56aac752544f798728b429e7152afbee497e4..213837794c603cb9f152f917941b912326a08030 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java +@@ -18,6 +18,7 @@ import org.jetbrains.annotations.NotNull; + * Listening to this event forces chat to wait for the main thread which + * causes delays for chat. {@link AsyncPlayerChatEvent} is the encouraged + * alternative for thread safe implementations. ++ * @deprecated use {@link io.papermc.paper.event.player.ChatEvent} instead + */ + @Deprecated + @Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.") +diff --git a/src/main/java/org/bukkit/event/player/PlayerEvent.java b/src/main/java/org/bukkit/event/player/PlayerEvent.java +index 793b661b6d2d05de3d7f4fc26a4c018a2af58e62..f6d3b817de3001f04ea4554c7c39a1290af3fd6d 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerEvent.java +@@ -14,7 +14,7 @@ public abstract class PlayerEvent extends Event { + player = who; + } + +- PlayerEvent(@NotNull final Player who, boolean async) { ++ public PlayerEvent(@NotNull final Player who, boolean async) { // Paper - public + super(async); + player = who; + +diff --git a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java +index d06684aba7688ce06777dbd837a46856a9d7767f..851a189d42e271679abc78f95049d8badf7a2b64 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java +@@ -10,30 +10,60 @@ import org.jetbrains.annotations.Nullable; + */ + public class PlayerJoinEvent extends PlayerEvent { + private static final HandlerList handlers = new HandlerList(); +- private String joinMessage; ++ // Paper start ++ private net.kyori.adventure.text.Component joinMessage; ++ public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final net.kyori.adventure.text.Component joinMessage) { ++ super(playerJoined); ++ this.joinMessage = joinMessage; ++ } + ++ @Deprecated // Paper end + public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final String joinMessage) { + super(playerJoined); ++ this.joinMessage = joinMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(joinMessage) : null; // Paper end ++ } ++ ++ // Paper start ++ /** ++ * Gets the join message to send to all online players ++ * ++ * @return string join message. Can be null ++ */ ++ public @Nullable net.kyori.adventure.text.Component joinMessage() { ++ return this.joinMessage; ++ } ++ ++ /** ++ * Sets the join message to send to all online players ++ * ++ * @param joinMessage join message. If null, no message will be sent ++ */ ++ public void joinMessage(@Nullable net.kyori.adventure.text.Component joinMessage) { + this.joinMessage = joinMessage; + } ++ // Paper end + + /** + * Gets the join message to send to all online players + * + * @return string join message. Can be null ++ * @deprecated in favour of {@link #joinMessage()} + */ + @Nullable ++ @Deprecated // Paper + public String getJoinMessage() { +- return joinMessage; ++ return this.joinMessage == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.joinMessage); // Paper + } + + /** + * Sets the join message to send to all online players + * + * @param joinMessage join message. If null, no message will be sent ++ * @deprecated in favour of {@link #joinMessage(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setJoinMessage(@Nullable String joinMessage) { +- this.joinMessage = joinMessage; ++ this.joinMessage = joinMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(joinMessage) : null; // Paper + } + + @NotNull +diff --git a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java +index 14c337f15fc804f52e52cb0a185aad38d89303a8..5c0efe74237dbe6803ce023fde99682ff70d1a92 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java +@@ -10,35 +10,84 @@ import org.jetbrains.annotations.NotNull; + */ + public class PlayerKickEvent extends PlayerEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); +- private String leaveMessage; +- private String kickReason; ++ private net.kyori.adventure.text.Component leaveMessage; // Paper ++ private net.kyori.adventure.text.Component kickReason; // Paper + private Boolean cancel; + ++ @Deprecated // Paper + public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final String kickReason, @NotNull final String leaveMessage) { ++ super(playerKicked); ++ this.kickReason = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickReason); // Paper ++ this.leaveMessage = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(leaveMessage); // Paper ++ this.cancel = false; ++ } ++ // Paper start ++ public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final net.kyori.adventure.text.Component kickReason, @NotNull final net.kyori.adventure.text.Component leaveMessage) { + super(playerKicked); + this.kickReason = kickReason; + this.leaveMessage = leaveMessage; + this.cancel = false; + } + ++ /** ++ * Gets the leave message send to all online players ++ * ++ * @return string kick reason ++ */ ++ public @NotNull net.kyori.adventure.text.Component leaveMessage() { ++ return this.leaveMessage; ++ } ++ ++ /** ++ * Sets the leave message send to all online players ++ * ++ * @param leaveMessage leave message ++ */ ++ public void leaveMessage(@NotNull net.kyori.adventure.text.Component leaveMessage) { ++ this.leaveMessage = leaveMessage; ++ } ++ + /** + * Gets the reason why the player is getting kicked + * + * @return string kick reason + */ ++ public @NotNull net.kyori.adventure.text.Component reason() { ++ return this.kickReason; ++ } ++ ++ /** ++ * Sets the reason why the player is getting kicked ++ * ++ * @param kickReason kick reason ++ */ ++ public void reason(@NotNull net.kyori.adventure.text.Component kickReason) { ++ this.kickReason = kickReason; ++ } ++ // Paper end ++ ++ /** ++ * Gets the reason why the player is getting kicked ++ * ++ * @return string kick reason ++ * @deprecated in favour of {@link #reason()} ++ */ + @NotNull ++ @Deprecated // Paper + public String getReason() { +- return kickReason; ++ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.kickReason); // Paper + } + + /** + * Gets the leave message send to all online players + * + * @return string kick reason ++ * @deprecated in favour of {@link #leaveMessage()} + */ + @NotNull ++ @Deprecated // Paper + public String getLeaveMessage() { +- return leaveMessage; ++ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.leaveMessage); // Paper + } + + @Override +@@ -55,18 +104,22 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { + * Sets the reason why the player is getting kicked + * + * @param kickReason kick reason ++ * @deprecated in favour of {@link #reason(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setReason(@NotNull String kickReason) { +- this.kickReason = kickReason; ++ this.kickReason = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickReason); // Paper + } + + /** + * Sets the leave message send to all online players + * + * @param leaveMessage leave message ++ * @deprecated in favour of {@link #leaveMessage(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setLeaveMessage(@NotNull String leaveMessage) { +- this.leaveMessage = leaveMessage; ++ this.leaveMessage = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(leaveMessage); // Paper + } + + @NotNull +diff --git a/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java b/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java +index 1db386bb701cb6974daedc6bb5b93a3afbc42100..84521186404b8e43c81a2f9513dce2be40d27840 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java +@@ -12,18 +12,32 @@ public class PlayerLocaleChangeEvent extends PlayerEvent { + private static final HandlerList handlers = new HandlerList(); + // + private final String locale; ++ // Paper start ++ private final java.util.Locale adventure$locale; ++ /** ++ * @see Player#getLocale() ++ * ++ * @return the player's new locale ++ */ ++ public @NotNull java.util.Locale locale() { ++ return this.adventure$locale; ++ } ++ // Paper end + + public PlayerLocaleChangeEvent(@NotNull Player who, @NotNull String locale) { + super(who); + this.locale = locale; ++ this.adventure$locale = net.kyori.adventure.translation.Translator.parseLocale(locale); // Paper + } + + /** + * @see Player#getLocale() + * + * @return the player's new locale ++ * @deprecated in favour of {@link #locale()} + */ + @NotNull ++ @Deprecated // Paper + public String getLocale() { + return locale; + } +diff --git a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java +index 084ca8cfcb7381bfa4fa6280748cf9b81210a9c1..75cc54739ef841cd90568d74927d6002d4cfa7e0 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java +@@ -17,7 +17,7 @@ public class PlayerLoginEvent extends PlayerEvent { + private final InetAddress address; + private final String hostname; + private Result result = Result.ALLOWED; +- private String message = ""; ++ private net.kyori.adventure.text.Component message = net.kyori.adventure.text.Component.empty(); + private final InetAddress realAddress; // Spigot + + /** +@@ -53,12 +53,52 @@ public class PlayerLoginEvent extends PlayerEvent { + * @param result The result status for this event + * @param message The message to be displayed if result denies login + * @param realAddress the actual, unspoofed connecting address ++ * @deprecated in favour of {@link #PlayerLoginEvent(Player, String, InetAddress, Result, net.kyori.adventure.text.Component, InetAddress)} + */ ++ @Deprecated // Paper + public PlayerLoginEvent(@NotNull final Player player, @NotNull String hostname, @NotNull final InetAddress address, @NotNull final Result result, @NotNull final String message, @NotNull final InetAddress realAddress) { // Spigot + this(player, hostname, address, realAddress); // Spigot + this.result = result; ++ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper ++ } ++ ++ // Paper start ++ /** ++ * This constructor pre-configures the event with a result and message ++ * ++ * @param player The {@link Player} for this event ++ * @param hostname The hostname that was used to connect to the server ++ * @param address The address the player used to connect, provided for ++ * timing issues ++ * @param result The result status for this event ++ * @param message The message to be displayed if result denies login ++ * @param realAddress the actual, unspoofed connecting address ++ */ ++ public PlayerLoginEvent(@NotNull final Player player, @NotNull String hostname, @NotNull final InetAddress address, @NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message, @NotNull final InetAddress realAddress) { // Spigot ++ this(player, hostname, address, realAddress); // Spigot ++ this.result = result; ++ this.message = message; ++ } ++ ++ /** ++ * Gets the current kick message that will be used if getResult() != ++ * Result.ALLOWED ++ * ++ * @return Current kick message ++ */ ++ public @NotNull net.kyori.adventure.text.Component kickMessage() { ++ return this.message; ++ } ++ ++ /** ++ * Sets the kick message to display if getResult() != Result.ALLOWED ++ * ++ * @param message New kick message ++ */ ++ public void kickMessage(@NotNull net.kyori.adventure.text.Component message) { + this.message = message; + } ++ // Paper end + + // Spigot start + /** +@@ -96,19 +136,23 @@ public class PlayerLoginEvent extends PlayerEvent { + * Result.ALLOWED + * + * @return Current kick message ++ * @deprecated in favour of {@link #kickMessage()} + */ + @NotNull ++ @Deprecated // Paper + public String getKickMessage() { +- return message; ++ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); // Paper + } + + /** + * Sets the kick message to display if getResult() != Result.ALLOWED + * + * @param message New kick message ++ * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setKickMessage(@NotNull final String message) { +- this.message = message; ++ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper + } + + /** +@@ -127,7 +171,7 @@ public class PlayerLoginEvent extends PlayerEvent { + */ + public void allow() { + result = Result.ALLOWED; +- message = ""; ++ message = net.kyori.adventure.text.Component.empty(); // Paper + } + + /** +@@ -135,8 +179,21 @@ public class PlayerLoginEvent extends PlayerEvent { + * + * @param result New result for disallowing the player + * @param message Kick message to display to the user ++ * @deprecated in favour of {@link #disallow(Result, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper start + public void disallow(@NotNull final Result result, @NotNull final String message) { ++ this.result = result; ++ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); ++ } ++ /** ++ * Disallows the player from logging in, with the given reason ++ * ++ * @param result New result for disallowing the player ++ * @param message Kick message to display to the user ++ */ ++ public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { ++ // Paper end + this.result = result; + this.message = message; + } +diff --git a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java +index fb066251f793ec3b41bfc075b9478901b15ee549..123979ed64939d615b061f91c19c630e1e1db8c7 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java +@@ -19,7 +19,7 @@ import org.jetbrains.annotations.NotNull; + public class PlayerPreLoginEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + private Result result; +- private String message; ++ private net.kyori.adventure.text.Component message; // Paper + private final String name; + private final InetAddress ipAddress; + private final UUID uniqueId; +@@ -31,7 +31,7 @@ public class PlayerPreLoginEvent extends Event { + + public PlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId) { + this.result = Result.ALLOWED; +- this.message = ""; ++ this.message = net.kyori.adventure.text.Component.empty(); // Paper + this.name = name; + this.ipAddress = ipAddress; + this.uniqueId = uniqueId; +@@ -56,6 +56,7 @@ public class PlayerPreLoginEvent extends Event { + this.result = result; + } + ++ // Paper start + /** + * Gets the current kick message that will be used if getResult() != + * Result.ALLOWED +@@ -63,7 +64,7 @@ public class PlayerPreLoginEvent extends Event { + * @return Current kick message + */ + @NotNull +- public String getKickMessage() { ++ public net.kyori.adventure.text.Component kickMessage() { + return message; + } + +@@ -72,16 +73,51 @@ public class PlayerPreLoginEvent extends Event { + * + * @param message New kick message + */ +- public void setKickMessage(@NotNull final String message) { ++ public void kickMessage(@NotNull final net.kyori.adventure.text.Component message) { + this.message = message; + } + ++ /** ++ * Disallows the player from logging in, with the given reason ++ * ++ * @param result New result for disallowing the player ++ * @param message Kick message to display to the user ++ */ ++ public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { ++ this.result = result; ++ this.message = message; ++ } ++ // Paper end ++ /** ++ * Gets the current kick message that will be used if getResult() != ++ * Result.ALLOWED ++ * ++ * @return Current kick message ++ * @deprecated in favour of {@link #kickMessage()} ++ */ ++ @Deprecated // Paper ++ @NotNull ++ public String getKickMessage() { ++ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); // Paper ++ } ++ ++ /** ++ * Sets the kick message to display if getResult() != Result.ALLOWED ++ * ++ * @param message New kick message ++ * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated // Paper ++ public void setKickMessage(@NotNull final String message) { ++ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper ++ } ++ + /** + * Allows the player to log in + */ + public void allow() { + result = Result.ALLOWED; +- message = ""; ++ message = net.kyori.adventure.text.Component.empty(); // Paper + } + + /** +@@ -89,10 +125,12 @@ public class PlayerPreLoginEvent extends Event { + * + * @param result New result for disallowing the player + * @param message Kick message to display to the user ++ * @deprecated in favour of {@link #disallow(org.bukkit.event.player.PlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void disallow(@NotNull final Result result, @NotNull final String message) { + this.result = result; +- this.message = message; ++ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper + } + + /** +diff --git a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java +index d70c25f404e994766a9ebce89a917c8d0719777c..849e8f10dd77e9fb46aab17752b8f1ff79e9d42e 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java +@@ -10,30 +10,59 @@ import org.jetbrains.annotations.Nullable; + */ + public class PlayerQuitEvent extends PlayerEvent { + private static final HandlerList handlers = new HandlerList(); +- private String quitMessage; ++ private net.kyori.adventure.text.Component quitMessage; // Paper + ++ @Deprecated // Paper + public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage) { + super(who); ++ this.quitMessage = quitMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(quitMessage) : null; // Paper ++ } ++ // Paper start ++ public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage) { ++ super(who); ++ this.quitMessage = quitMessage; ++ } ++ ++ /** ++ * Gets the quit message to send to all online players ++ * ++ * @return string quit message ++ */ ++ public @Nullable net.kyori.adventure.text.Component quitMessage() { ++ return quitMessage; ++ } ++ ++ /** ++ * Sets the quit message to send to all online players ++ * ++ * @param quitMessage quit message ++ */ ++ public void quitMessage(@Nullable net.kyori.adventure.text.Component quitMessage) { + this.quitMessage = quitMessage; + } ++ // Paper end + + /** + * Gets the quit message to send to all online players + * + * @return string quit message ++ * @deprecated in favour of {@link #quitMessage()} + */ + @Nullable ++ @Deprecated // Paper + public String getQuitMessage() { +- return quitMessage; ++ return this.quitMessage == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.quitMessage); // Paper + } + + /** + * Sets the quit message to send to all online players + * + * @param quitMessage quit message ++ * @deprecated in favour of {@link #quitMessage(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setQuitMessage(@Nullable String quitMessage) { +- this.quitMessage = quitMessage; ++ this.quitMessage = quitMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(quitMessage) : null; // Paper + } + + @NotNull +diff --git a/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java b/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java +index 03bfca9d368bbe4b7c1353d52c883e756bf69bda..4f8c85222c7bd33217c7db0ff5f47bf397f8f3e5 100644 +--- a/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java ++++ b/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java +@@ -18,7 +18,7 @@ import org.jetbrains.annotations.NotNull; + public class BroadcastMessageEvent extends ServerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); +- private String message; ++ private net.kyori.adventure.text.Component message; // Paper + private final Set recipients; + private boolean cancelled = false; + +@@ -27,29 +27,66 @@ public class BroadcastMessageEvent extends ServerEvent implements Cancellable { + this(false, message, recipients); + } + ++ @Deprecated // Paper + public BroadcastMessageEvent(boolean isAsync, @NotNull String message, @NotNull Set recipients) { ++ // Paper start ++ super(isAsync); ++ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); ++ this.recipients = recipients; ++ } ++ ++ @Deprecated ++ public BroadcastMessageEvent(@NotNull net.kyori.adventure.text.Component message, @NotNull Set recipients) { ++ this(false, message, recipients); ++ } ++ ++ public BroadcastMessageEvent(boolean isAsync, @NotNull net.kyori.adventure.text.Component message, @NotNull Set recipients) { ++ // Paper end + super(isAsync); + this.message = message; + this.recipients = recipients; + } ++ // Paper start ++ /** ++ * Get the broadcast message. ++ * ++ * @return Message to broadcast ++ */ ++ public @NotNull net.kyori.adventure.text.Component message() { ++ return this.message; ++ } ++ ++ /** ++ * Set the broadcast message. ++ * ++ * @param message New message to broadcast ++ */ ++ public void message(@NotNull net.kyori.adventure.text.Component message) { ++ this.message = message; ++ } ++ // Paper end + + /** + * Get the message to broadcast. + * + * @return Message to broadcast ++ * @deprecated in favour of {@link #message()} + */ + @NotNull ++ @Deprecated // Paper + public String getMessage() { +- return message; ++ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); // Paper + } + + /** + * Set the message to broadcast. + * + * @param message New message to broadcast ++ * @deprecated in favour of {@link #message(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setMessage(@NotNull String message) { +- this.message = message; ++ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper + } + + /** +diff --git a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java +index 7a2a58bac8e721c3f0c64f69f77be07a51f76d58..ede5a41bc071a9c9cea369b227b37a50222f295d 100644 +--- a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java ++++ b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java +@@ -17,15 +17,16 @@ public class ServerListPingEvent extends ServerEvent implements Iterable + private static final int MAGIC_PLAYER_COUNT = Integer.MIN_VALUE; + private static final HandlerList handlers = new HandlerList(); + private final InetAddress address; +- private String motd; ++ private net.kyori.adventure.text.Component motd; // Paper + private final int numPlayers; + private int maxPlayers; + ++ @Deprecated // Paper + public ServerListPingEvent(@NotNull final InetAddress address, @NotNull final String motd, final int numPlayers, final int maxPlayers) { + super(true); + Validate.isTrue(numPlayers >= 0, "Cannot have negative number of players online", numPlayers); + this.address = address; +- this.motd = motd; ++ this.motd = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(motd); // Paper + this.numPlayers = numPlayers; + this.maxPlayers = maxPlayers; + } +@@ -38,14 +39,58 @@ public class ServerListPingEvent extends ServerEvent implements Iterable + * @param address the address of the pinger + * @param motd the message of the day + * @param maxPlayers the max number of players ++ * @deprecated in favour of {@link #ServerListPingEvent(java.net.InetAddress, net.kyori.adventure.text.Component, int)} + */ ++ @Deprecated // Paper + protected ServerListPingEvent(@NotNull final InetAddress address, @NotNull final String motd, final int maxPlayers) { ++ super(true); ++ this.numPlayers = MAGIC_PLAYER_COUNT; ++ this.address = address; ++ this.motd = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(motd); // Paper ++ this.maxPlayers = maxPlayers; ++ } ++ // Paper start ++ public ServerListPingEvent(@NotNull final InetAddress address, @NotNull final net.kyori.adventure.text.Component motd, final int numPlayers, final int maxPlayers) { ++ super(true); ++ Validate.isTrue(numPlayers >= 0, "Cannot have negative number of players online", numPlayers); ++ this.address = address; ++ this.motd = motd; ++ this.numPlayers = numPlayers; ++ this.maxPlayers = maxPlayers; ++ } ++ /** ++ * This constructor is intended for implementations that provide the ++ * {@link #iterator()} method, thus provided the {@link #getNumPlayers()} ++ * count. ++ * ++ * @param address the address of the pinger ++ * @param motd the message of the day ++ * @param maxPlayers the max number of players ++ */ ++ protected ServerListPingEvent(@NotNull final InetAddress address, @NotNull final net.kyori.adventure.text.Component motd, final int maxPlayers) { + super(true); + this.numPlayers = MAGIC_PLAYER_COUNT; + this.address = address; + this.motd = motd; + this.maxPlayers = maxPlayers; + } ++ /** ++ * Get the message of the day message. ++ * ++ * @return the message of the day ++ */ ++ public @NotNull net.kyori.adventure.text.Component motd() { ++ return motd; ++ } ++ /** ++ * Change the message of the day message. ++ * ++ * @param motd the message of the day ++ */ ++ public void motd(@NotNull net.kyori.adventure.text.Component motd) { ++ this.motd = motd; ++ } ++ // Paper end + + /** + * Get the address the ping is coming from. +@@ -61,19 +106,23 @@ public class ServerListPingEvent extends ServerEvent implements Iterable + * Get the message of the day message. + * + * @return the message of the day ++ * @deprecated in favour of {@link #motd()} + */ + @NotNull ++ @Deprecated // Paper + public String getMotd() { +- return motd; ++ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.motd); // Paper + } + + /** + * Change the message of the day message. + * + * @param motd the message of the day ++ * @deprecated in favour of {@link #motd(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setMotd(@NotNull String motd) { +- this.motd = motd; ++ this.motd = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(motd); // Paper + } + + /** +diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java +index 14346d83bc99581b18e53d19af03708c0bf22cf7..664de64b020cf9090a2fbee0afe2bfaf150adc3c 100644 +--- a/src/main/java/org/bukkit/inventory/InventoryView.java ++++ b/src/main/java/org/bukkit/inventory/InventoryView.java +@@ -446,11 +446,25 @@ public abstract class InventoryView { + return getPlayer().setWindowProperty(prop, value); + } + ++ // Paper start + /** + * Get the title of this inventory window. + * + * @return The title. + */ + @NotNull ++ public /*abstract*/ net.kyori.adventure.text.Component title() { ++ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(this.getTitle()); ++ } ++ // Paper end ++ ++ /** ++ * Get the title of this inventory window. ++ * ++ * @return The title. ++ * @deprecated in favour of {@link #title()} ++ */ ++ @Deprecated // Paper ++ @NotNull + public abstract String getTitle(); + } +diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java +index 4ff149fd98895dd8ba45939a37c223b1f8d7281f..6cc4bad2ecd19f44a680ff03cbfb99d48ea5c337 100644 +--- a/src/main/java/org/bukkit/inventory/ItemFactory.java ++++ b/src/main/java/org/bukkit/inventory/ItemFactory.java +@@ -141,4 +141,24 @@ public interface ItemFactory { + @Deprecated + @NotNull + Material updateMaterial(@NotNull final ItemMeta meta, @NotNull final Material material) throws IllegalArgumentException; ++ ++ // Paper start ++ /** ++ * Creates a hover event for the given item. ++ * ++ * @param item The item ++ * @return A hover event ++ */ ++ @NotNull ++ net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull ItemStack item, final @NotNull java.util.function.UnaryOperator op); ++ ++ /** ++ * Get the formatted display name of the {@link ItemStack}. ++ * ++ * @param itemStack the {@link ItemStack} ++ * @return display name of the {@link ItemStack} ++ */ ++ @NotNull ++ net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index f70a6a22b85ff0da76e67e9b223ad4e0b020b5c4..a15abec467bac70116a6fc21a300d4930b909f15 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -22,7 +22,7 @@ import org.jetbrains.annotations.Nullable; + * use this class to encapsulate Materials for which {@link Material#isItem()} + * returns false. + */ +-public class ItemStack implements Cloneable, ConfigurationSerializable { ++public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyori.adventure.text.event.HoverEventSource { // Paper + private Material type = Material.AIR; + private int amount = 0; + private MaterialData data = null; +@@ -595,4 +595,21 @@ public class ItemStack implements Cloneable, ConfigurationSerializable { + + return true; + } ++ ++ // Paper start ++ @NotNull ++ @Override ++ public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { ++ return org.bukkit.Bukkit.getServer().getItemFactory().asHoverEvent(this, op); ++ } ++ ++ /** ++ * Get the formatted display name of the {@link ItemStack}. ++ * ++ * @return display name of the {@link ItemStack} ++ */ ++ public @NotNull net.kyori.adventure.text.Component displayName() { ++ return Bukkit.getServer().getItemFactory().displayName(this); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/meta/BookMeta.java b/src/main/java/org/bukkit/inventory/meta/BookMeta.java +index 94852d50e88d0594b84b581cd627174043629995..4947251f347d83fa326a67735293401c10d87ba4 100644 +--- a/src/main/java/org/bukkit/inventory/meta/BookMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/BookMeta.java +@@ -1,8 +1,12 @@ + package org.bukkit.inventory.meta; + + import java.util.List; ++ ++import net.kyori.adventure.inventory.Book; + import net.md_5.bungee.api.chat.BaseComponent; + import org.bukkit.Material; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.common.returnsreceiver.qual.This; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + +@@ -10,7 +14,7 @@ import org.jetbrains.annotations.Nullable; + * Represents a book ({@link Material#WRITABLE_BOOK} or {@link + * Material#WRITTEN_BOOK}) that can have a title, an author, and pages. + */ +-public interface BookMeta extends ItemMeta { ++public interface BookMeta extends ItemMeta, net.kyori.adventure.inventory.Book { // Paper + + /** + * Represents the generation (or level of copying) of a written book +@@ -119,6 +123,117 @@ public interface BookMeta extends ItemMeta { + */ + boolean hasPages(); + ++ // Paper start ++ /** ++ * Gets the title of the book. ++ *

    ++ * Plugins should check that hasTitle() returns true before calling this ++ * method. ++ * ++ * @return the title of the book ++ */ ++ @Nullable ++ @Override ++ net.kyori.adventure.text.Component title(); ++ ++ /** ++ * Sets the title of the book. ++ *

    ++ * Limited to 32 characters. Removes title when given null. ++ * ++ * @param title the title to set ++ * @return the same {@link BookMeta} instance ++ */ ++ @NotNull ++ @Override ++ @This BookMeta title(@Nullable net.kyori.adventure.text.Component title); ++ ++ /** ++ * Gets the author of the book. ++ *

    ++ * Plugins should check that hasAuthor() returns true before calling this ++ * method. ++ * ++ * @return the author of the book ++ */ ++ @Nullable ++ @Override ++ net.kyori.adventure.text.Component author(); ++ ++ /** ++ * Sets the author of the book. Removes author when given null. ++ * ++ * @param author the author to set ++ * @return the same {@link BookMeta} instance ++ */ ++ @NotNull ++ @Override ++ @This BookMeta author(@Nullable net.kyori.adventure.text.Component author); ++ /** ++ * Gets the specified page in the book. The page must exist. ++ *

    ++ * Pages are 1-indexed. ++ * ++ * @param page the page number to get, in range [1, getPageCount()] ++ * @return the page from the book ++ */ ++ @NotNull net.kyori.adventure.text.Component page(int page); ++ ++ /** ++ * Sets the specified page in the book. Pages of the book must be ++ * contiguous. ++ *

    ++ * The data can be up to 256 characters in length, additional characters ++ * are truncated. ++ *

    ++ * Pages are 1-indexed. ++ * ++ * @param page the page number to set, in range [1, getPageCount()] ++ * @param data the data to set for that page ++ */ ++ void page(int page, @NotNull net.kyori.adventure.text.Component data); ++ ++ /** ++ * Adds new pages to the end of the book. Up to a maximum of 50 pages with ++ * 256 characters per page. ++ * ++ * @param pages A list of strings, each being a page ++ */ ++ void addPages(@NotNull net.kyori.adventure.text.Component... pages); ++ ++ interface BookMetaBuilder extends Builder { ++ ++ @NotNull ++ @Override ++ BookMetaBuilder title(@Nullable net.kyori.adventure.text.Component title); ++ ++ @NotNull ++ @Override ++ BookMetaBuilder author(@Nullable net.kyori.adventure.text.Component author); ++ ++ @NotNull ++ @Override ++ BookMetaBuilder addPage(@NotNull net.kyori.adventure.text.Component page); ++ ++ @NotNull ++ @Override ++ BookMetaBuilder pages(@NotNull net.kyori.adventure.text.Component... pages); ++ ++ @NotNull ++ @Override ++ BookMetaBuilder pages(@NotNull java.util.Collection pages); ++ ++ @NotNull ++ @Override ++ BookMeta build(); ++ } ++ ++ @Override ++ @NonNull ++ BookMetaBuilder toBuilder(); ++ ++ // Paper end ++ + /** + * Gets the specified page in the book. The given page must exist. + *

    +@@ -126,8 +241,10 @@ public interface BookMeta extends ItemMeta { + * + * @param page the page number to get, in range [1, getPageCount()] + * @return the page from the book ++ * @deprecated in favour of {@link #page(int)} + */ + @NotNull ++ @Deprecated // Paper + String getPage(int page); + + /** +@@ -141,15 +258,19 @@ public interface BookMeta extends ItemMeta { + * + * @param page the page number to set, in range [1, getPageCount()] + * @param data the data to set for that page ++ * @deprecated in favour of {@link #page(int, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setPage(int page, @NotNull String data); + + /** + * Gets all the pages in the book. + * + * @return list of all the pages in the book ++ * @deprecated in favour of {@link #pages()} + */ + @NotNull ++ @Deprecated // Paper + List getPages(); + + /** +@@ -157,7 +278,9 @@ public interface BookMeta extends ItemMeta { + * pages. Maximum 100 pages with 256 characters per page. + * + * @param pages A list of pages to set the book to use ++ * @deprecated in favour of {@link #pages(List)} + */ ++ @Deprecated // Paper + void setPages(@NotNull List pages); + + /** +@@ -165,7 +288,9 @@ public interface BookMeta extends ItemMeta { + * pages. Maximum 50 pages with 256 characters per page. + * + * @param pages A list of strings, each being a page ++ * @deprecated in favour of {@link #pages(net.kyori.adventure.text.Component...)} + */ ++ @Deprecated // Paper + void setPages(@NotNull String... pages); + + /** +@@ -173,7 +298,9 @@ public interface BookMeta extends ItemMeta { + * 256 characters per page. + * + * @param pages A list of strings, each being a page ++ * @deprecated in favour of {@link #addPages(net.kyori.adventure.text.Component...)} + */ ++ @Deprecated // Paper + void addPage(@NotNull String... pages); + + /** +@@ -195,8 +322,10 @@ public interface BookMeta extends ItemMeta { + * + * @param page the page number to get + * @return the page from the book ++ * @deprecated in favour of {@link #page(int)} + */ + @NotNull ++ @Deprecated // Paper + public BaseComponent[] getPage(int page) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -210,7 +339,9 @@ public interface BookMeta extends ItemMeta { + * + * @param page the page number to set + * @param data the data to set for that page ++ * @deprecated in favour of {@link #page(int, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setPage(int page, @Nullable BaseComponent... data) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -219,8 +350,10 @@ public interface BookMeta extends ItemMeta { + * Gets all the pages in the book. + * + * @return list of all the pages in the book ++ * @deprecated in favour of {@link #pages()} + */ + @NotNull ++ @Deprecated // Paper + public List getPages() { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -230,7 +363,9 @@ public interface BookMeta extends ItemMeta { + * pages. Maximum 50 pages with 256 characters per page. + * + * @param pages A list of pages to set the book to use ++ * @deprecated in favour of {@link #pages(java.util.List)} + */ ++ @Deprecated // Paper + public void setPages(@NotNull List pages) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -240,7 +375,9 @@ public interface BookMeta extends ItemMeta { + * pages. Maximum 50 pages with 256 characters per page. + * + * @param pages A list of component arrays, each being a page ++ * @deprecated in favour of {@link #pages(net.kyori.adventure.text.Component...)} + */ ++ @Deprecated // Paper + public void setPages(@NotNull BaseComponent[]... pages) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -250,7 +387,9 @@ public interface BookMeta extends ItemMeta { + * with 256 characters per page. + * + * @param pages A list of component arrays, each being a page ++ * @deprecated in favour of {@link #addPages(net.kyori.adventure.text.Component...)} + */ ++ @Deprecated // Paper + public void addPage(@NotNull BaseComponent[]... pages) { + throw new UnsupportedOperationException("Not supported yet."); + } +diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java +index f2e9f2753ec92aa4a3e3f06ca6053bd70b9091d7..1c362636c56db0e6c118171ba367c43c4f7cff33 100644 +--- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java +@@ -31,6 +31,24 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + */ + boolean hasDisplayName(); + ++ // Paper start ++ /** ++ * Gets the display name. ++ * ++ *

    Plugins should check that {@link #hasDisplayName()} returns true before calling this method.

    ++ * ++ * @return the display name ++ */ ++ @Nullable net.kyori.adventure.text.Component displayName(); ++ ++ /** ++ * Sets the display name. ++ * ++ * @param displayName the display name to set ++ */ ++ void displayName(final @Nullable net.kyori.adventure.text.Component displayName); ++ // Paper end ++ + /** + * Gets the display name that is set. + *

    +@@ -38,7 +56,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + * before calling this method. + * + * @return the display name that is set ++ * @deprecated in favour of {@link #displayName()} + */ ++ @Deprecated // Paper + @NotNull + String getDisplayName(); + +@@ -46,7 +66,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + * Sets the display name. + * + * @param name the name to set ++ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setDisplayName(@Nullable String name); + + /** +@@ -81,6 +103,24 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + */ + boolean hasLore(); + ++ // Paper start ++ /** ++ * Gets the lore. ++ * ++ *

    Plugins should check that {@link #hasLore()} returns true before calling this method.

    ++ * ++ * @return the display name ++ */ ++ @Nullable List lore(); ++ ++ /** ++ * Sets the lore. ++ * ++ * @param lore the lore to set ++ */ ++ void lore(final @Nullable List lore); ++ // Paper end ++ + /** + * Gets the lore that is set. + *

    +@@ -88,7 +128,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + * calling this method. + * + * @return a list of lore that is set ++ * @deprecated in favour of {@link #lore()} + */ ++ @Deprecated // Paper + @Nullable + List getLore(); + +@@ -97,7 +139,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + * Removes lore when given null. + * + * @param lore the lore that will be set ++ * @deprecated in favour of {@link #lore(List)} + */ ++ @Deprecated // Paper + void setLore(@Nullable List lore); + + /** +diff --git a/src/main/java/org/bukkit/map/MapCursor.java b/src/main/java/org/bukkit/map/MapCursor.java +index 83354b2a38b6261b172b91c1008dcf3313cc4a8f..ed0bc2024a0bb85837e25f75ae89d1fe257b2e60 100644 +--- a/src/main/java/org/bukkit/map/MapCursor.java ++++ b/src/main/java/org/bukkit/map/MapCursor.java +@@ -10,7 +10,7 @@ public final class MapCursor { + private byte x, y; + private byte direction, type; + private boolean visible; +- private String caption; ++ private net.kyori.adventure.text.Component caption; // Paper + + /** + * Initialize the map cursor. +@@ -24,7 +24,7 @@ public final class MapCursor { + */ + @Deprecated + public MapCursor(byte x, byte y, byte direction, byte type, boolean visible) { +- this(x, y, direction, type, visible, null); ++ this(x, y, direction, type, visible, (String) null); // Paper + } + + /** +@@ -37,7 +37,7 @@ public final class MapCursor { + * @param visible Whether the cursor is visible by default. + */ + public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible) { +- this(x, y, direction, type, visible, null); ++ this(x, y, direction, type, visible, (String) null); // Paper + } + + /** +@@ -49,7 +49,7 @@ public final class MapCursor { + * @param type The type (color/style) of the map cursor. + * @param visible Whether the cursor is visible by default. + * @param caption cursor caption +- * @deprecated Magic value ++ * @deprecated Magic value. Use {@link #MapCursor(byte, byte, byte, byte, boolean, net.kyori.adventure.text.Component)} + */ + @Deprecated + public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, @Nullable String caption) { +@@ -58,8 +58,42 @@ public final class MapCursor { + setDirection(direction); + setRawType(type); + this.visible = visible; +- this.caption = caption; ++ this.caption = caption == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(caption); // Paper + } ++ // Paper start ++ /** ++ * Initialize the map cursor. ++ * ++ * @param x The x coordinate, from -128 to 127. ++ * @param y The y coordinate, from -128 to 127. ++ * @param direction The facing of the cursor, from 0 to 15. ++ * @param type The type (color/style) of the map cursor. ++ * @param visible Whether the cursor is visible by default. ++ * @param caption cursor caption ++ * @deprecated Magic value ++ */ ++ @Deprecated ++ public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, @Nullable net.kyori.adventure.text.Component caption) { ++ this.x = x; this.y = y; this.visible = visible; this.caption = caption; ++ setDirection(direction); ++ setRawType(type); ++ } ++ /** ++ * Initialize the map cursor. ++ * ++ * @param x The x coordinate, from -128 to 127. ++ * @param y The y coordinate, from -128 to 127. ++ * @param direction The facing of the cursor, from 0 to 15. ++ * @param type The type (color/style) of the map cursor. ++ * @param visible Whether the cursor is visible by default. ++ * @param caption cursor caption ++ */ ++ public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible, @Nullable net.kyori.adventure.text.Component caption) { ++ this.x = x; this.y = y; this.visible = visible; this.caption = caption; ++ setDirection(direction); ++ setType(type); ++ } ++ // Paper end + + /** + * Initialize the map cursor. +@@ -77,7 +111,7 @@ public final class MapCursor { + setDirection(direction); + setType(type); + this.visible = visible; +- this.caption = caption; ++ this.caption = caption == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(caption); // Paper + } + + /** +@@ -200,23 +234,45 @@ public final class MapCursor { + this.visible = visible; + } + ++ // Paper start ++ /** ++ * Gets the caption on this cursor. ++ * ++ * @return caption ++ */ ++ public @Nullable net.kyori.adventure.text.Component caption() { ++ return this.caption; ++ } ++ /** ++ * Sets the caption on this cursor. ++ * ++ * @param caption new caption ++ */ ++ public void caption(@Nullable net.kyori.adventure.text.Component caption) { ++ this.caption = caption; ++ } ++ // Paper end + /** + * Gets the caption on this cursor. + * + * @return caption ++ * @deprecated in favour of {@link #caption()} + */ + @Nullable ++ @Deprecated // Paper + public String getCaption() { +- return caption; ++ return this.caption == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.caption); // Paper + } + + /** + * Sets the caption on this cursor. + * + * @param caption new caption ++ * @deprecated in favour of {@link #caption(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setCaption(@Nullable String caption) { +- this.caption = caption; ++ this.caption = caption == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(caption); // Paper + } + + /** +diff --git a/src/main/java/org/bukkit/map/MapCursorCollection.java b/src/main/java/org/bukkit/map/MapCursorCollection.java +index 4dba721aefe4fc6699b3b4bfa7ecb0b19c2a2a1a..01dec2c877df58c9dc22445e8b1f9ce2e53066da 100644 +--- a/src/main/java/org/bukkit/map/MapCursorCollection.java ++++ b/src/main/java/org/bukkit/map/MapCursorCollection.java +@@ -117,4 +117,22 @@ public final class MapCursorCollection { + public MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible, @Nullable String caption) { + return addCursor(new MapCursor((byte) x, (byte) y, direction, type, visible, caption)); + } ++ // Paper start ++ /** ++ * Add a cursor to the collection. ++ * ++ * @param x The x coordinate, from -128 to 127. ++ * @param y The y coordinate, from -128 to 127. ++ * @param direction The facing of the cursor, from 0 to 15. ++ * @param type The type (color/style) of the map cursor. ++ * @param visible Whether the cursor is visible. ++ * @param caption banner caption ++ * @return The newly added MapCursor. ++ * @deprecated Magic value ++ */ ++ @Deprecated ++ public @NotNull MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible, @Nullable net.kyori.adventure.text.Component caption) { ++ return addCursor(new MapCursor((byte) x, (byte) y, direction, type, visible, caption)); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/scoreboard/Objective.java b/src/main/java/org/bukkit/scoreboard/Objective.java +index f5cbf6df32ef169cf0f2266f7c6e9c4f771ccb7d..58bddb11fd534e7c33a4ffd7b72b055ba92c767a 100644 +--- a/src/main/java/org/bukkit/scoreboard/Objective.java ++++ b/src/main/java/org/bukkit/scoreboard/Objective.java +@@ -19,14 +19,35 @@ public interface Objective { + */ + @NotNull + String getName() throws IllegalStateException; ++ // Paper start ++ /** ++ * Gets the name displayed to players for this objective ++ * ++ * @return this objective's display name ++ * @throws IllegalStateException if this objective has been unregistered ++ */ ++ @NotNull net.kyori.adventure.text.Component displayName() throws IllegalStateException; ++ /** ++ * Sets the name displayed to players for this objective. ++ * ++ * @param displayName Display name to set ++ * @throws IllegalStateException if this objective has been unregistered ++ * @throws IllegalArgumentException if displayName is null ++ * @throws IllegalArgumentException if displayName is longer than 128 ++ * characters. ++ */ ++ void displayName(@Nullable net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException; ++ // Paper end + + /** + * Gets the name displayed to players for this objective + * + * @return this objective's display name + * @throws IllegalStateException if this objective has been unregistered ++ * @deprecated in favour of {@link #displayName()} + */ + @NotNull ++ @Deprecated // Paper + String getDisplayName() throws IllegalStateException; + + /** +@@ -37,7 +58,9 @@ public interface Objective { + * @throws IllegalArgumentException if displayName is null + * @throws IllegalArgumentException if displayName is longer than 128 + * characters. ++ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setDisplayName(@NotNull String displayName) throws IllegalStateException, IllegalArgumentException; + + /** +diff --git a/src/main/java/org/bukkit/scoreboard/Scoreboard.java b/src/main/java/org/bukkit/scoreboard/Scoreboard.java +index 4bfaaea78c9b6aa5d392629aa943d26dbe6a7d4a..f09ff32cc3ffc16af379a378b1948991435393e8 100644 +--- a/src/main/java/org/bukkit/scoreboard/Scoreboard.java ++++ b/src/main/java/org/bukkit/scoreboard/Scoreboard.java +@@ -27,6 +27,48 @@ public interface Scoreboard { + @Deprecated + @NotNull + Objective registerNewObjective(@NotNull String name, @NotNull String criteria) throws IllegalArgumentException; ++ // Paper start ++ /** ++ * Registers an Objective on this Scoreboard ++ * ++ * @param name Name of the Objective ++ * @param criteria Criteria for the Objective ++ * @param displayName Name displayed to players for the Objective. ++ * @return The registered Objective ++ * @throws IllegalArgumentException if name is null ++ * @throws IllegalArgumentException if name is longer than 16 ++ * characters. ++ * @throws IllegalArgumentException if criteria is null ++ * @throws IllegalArgumentException if displayName is null ++ * @throws IllegalArgumentException if displayName is longer than 128 ++ * characters. ++ * @throws IllegalArgumentException if an objective by that name already ++ * exists ++ */ ++ @NotNull ++ Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @Nullable net.kyori.adventure.text.Component displayName) throws IllegalArgumentException; ++ /** ++ * Registers an Objective on this Scoreboard ++ * ++ * @param name Name of the Objective ++ * @param criteria Criteria for the Objective ++ * @param displayName Name displayed to players for the Objective. ++ * @param renderType Manner of rendering the Objective ++ * @return The registered Objective ++ * @throws IllegalArgumentException if name is null ++ * @throws IllegalArgumentException if name is longer than 16 ++ * characters. ++ * @throws IllegalArgumentException if criteria is null ++ * @throws IllegalArgumentException if displayName is null ++ * @throws IllegalArgumentException if displayName is longer than 128 ++ * characters. ++ * @throws IllegalArgumentException if renderType is null ++ * @throws IllegalArgumentException if an objective by that name already ++ * exists ++ */ ++ @NotNull ++ Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @Nullable net.kyori.adventure.text.Component displayName, @NotNull RenderType renderType) throws IllegalArgumentException; ++ // Paper end + + /** + * Registers an Objective on this Scoreboard +@@ -44,8 +86,10 @@ public interface Scoreboard { + * characters. + * @throws IllegalArgumentException if an objective by that name already + * exists ++ * @deprecated in favour of {@link #registerNewObjective(String, String, net.kyori.adventure.text.Component)} + */ + @NotNull ++ @Deprecated // Paper + Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @NotNull String displayName) throws IllegalArgumentException; + + /** +@@ -66,8 +110,10 @@ public interface Scoreboard { + * @throws IllegalArgumentException if renderType is null + * @throws IllegalArgumentException if an objective by that name already + * exists ++ * @deprecated in favour of {@link #registerNewObjective(String, String, net.kyori.adventure.text.Component, RenderType)} + */ + @NotNull ++ @Deprecated // Paper + Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @NotNull String displayName, @NotNull RenderType renderType) throws IllegalArgumentException; + + /** +diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java +index da01d2926cc8a2485a3349ac1ebb32cad20e287c..f0af10a5b9ad048be197ed5ec6c8ed2672eb3dd5 100644 +--- a/src/main/java/org/bukkit/scoreboard/Team.java ++++ b/src/main/java/org/bukkit/scoreboard/Team.java +@@ -22,14 +22,95 @@ public interface Team { + */ + @NotNull + String getName() throws IllegalStateException; ++ // Paper start ++ /** ++ * Gets the name displayed to entries for this team ++ * ++ * @return Team display name ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ @NotNull net.kyori.adventure.text.Component displayName() throws IllegalStateException; ++ ++ /** ++ * Sets the name displayed to entries for this team ++ * ++ * @param displayName New display name ++ * @throws IllegalArgumentException if displayName is longer than 128 ++ * characters. ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ void displayName(@Nullable net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException; ++ ++ /** ++ * Gets the prefix prepended to the display of entries on this team. ++ * ++ * @return Team prefix ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ @NotNull net.kyori.adventure.text.Component prefix() throws IllegalStateException; ++ ++ /** ++ * Sets the prefix prepended to the display of entries on this team. ++ * ++ * @param prefix New prefix ++ * @throws IllegalArgumentException if prefix is null ++ * @throws IllegalArgumentException if prefix is longer than 64 ++ * characters ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ void prefix(@Nullable net.kyori.adventure.text.Component prefix) throws IllegalStateException, IllegalArgumentException; ++ ++ /** ++ * Gets the suffix appended to the display of entries on this team. ++ * ++ * @return the team's current suffix ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ @NotNull net.kyori.adventure.text.Component suffix() throws IllegalStateException; ++ ++ /** ++ * Sets the suffix appended to the display of entries on this team. ++ * ++ * @param suffix the new suffix for this team. ++ * @throws IllegalArgumentException if suffix is null ++ * @throws IllegalArgumentException if suffix is longer than 64 ++ * characters ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ void suffix(@Nullable net.kyori.adventure.text.Component suffix) throws IllegalStateException, IllegalArgumentException; ++ ++ /** ++ * Gets the color of the team. ++ *
    ++ * This only sets the team outline, other occurrences of colors such as in ++ * names are handled by prefixes / suffixes. ++ * ++ * @return team color, defaults to {@link ChatColor#RESET} ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ @NotNull net.kyori.adventure.text.format.TextColor color() throws IllegalStateException; ++ ++ /** ++ * Sets the color of the team. ++ *
    ++ * This only sets the team outline, other occurrences of colors such as in ++ * names are handled by prefixes / suffixes. ++ * ++ * @param color new color, must be non-null. Use {@link ChatColor#RESET} for ++ * no color ++ */ ++ void color(@Nullable net.kyori.adventure.text.format.NamedTextColor color); ++ // Paper end + + /** + * Gets the name displayed to entries for this team + * + * @return Team display name + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #displayName()} + */ + @NotNull ++ @Deprecated // Paper + String getDisplayName() throws IllegalStateException; + + /** +@@ -39,7 +120,9 @@ public interface Team { + * @throws IllegalArgumentException if displayName is longer than 128 + * characters. + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setDisplayName(@NotNull String displayName) throws IllegalStateException, IllegalArgumentException; + + /** +@@ -47,8 +130,10 @@ public interface Team { + * + * @return Team prefix + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #prefix()} + */ + @NotNull ++ @Deprecated // Paper + String getPrefix() throws IllegalStateException; + + /** +@@ -59,7 +144,9 @@ public interface Team { + * @throws IllegalArgumentException if prefix is longer than 64 + * characters + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #prefix(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setPrefix(@NotNull String prefix) throws IllegalStateException, IllegalArgumentException; + + /** +@@ -67,8 +154,10 @@ public interface Team { + * + * @return the team's current suffix + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #suffix()} + */ + @NotNull ++ @Deprecated // Paper + String getSuffix() throws IllegalStateException; + + /** +@@ -79,7 +168,9 @@ public interface Team { + * @throws IllegalArgumentException if suffix is longer than 64 + * characters + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #suffix(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setSuffix(@NotNull String suffix) throws IllegalStateException, IllegalArgumentException; + + /** +@@ -90,8 +181,10 @@ public interface Team { + * + * @return team color, defaults to {@link ChatColor#RESET} + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #color()} + */ + @NotNull ++ @Deprecated // Paper + ChatColor getColor() throws IllegalStateException; + + /** +@@ -102,7 +195,9 @@ public interface Team { + * + * @param color new color, must be non-null. Use {@link ChatColor#RESET} for + * no color ++ * @deprecated in favour of {@link #color(net.kyori.adventure.text.format.NamedTextColor)} + */ ++ @Deprecated // Paper + void setColor(@NotNull ChatColor color); + + /** +diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java +index 0c7377247ad9251c9e498039511e7220370aba2d..c62919f18f318fec15a6c364d8b6d562c2b04762 100644 +--- a/src/test/java/org/bukkit/AnnotationTest.java ++++ b/src/test/java/org/bukkit/AnnotationTest.java +@@ -26,6 +26,12 @@ import org.objectweb.asm.tree.ParameterNode; + public class AnnotationTest { + + private static final String[] ACCEPTED_ANNOTATIONS = { ++ // Paper start ++ "Lorg/checkerframework/checker/nullness/qual/Nullable;", ++ "Lorg/checkerframework/checker/nullness/qual/NonNull;", ++ "Lorg/checkerframework/checker/nullness/qual/PolyNull;", ++ "Lorg/checkerframework/checker/nullness/qual/MonotonicNonNull;", ++ // Paper end + "Lorg/jetbrains/annotations/Nullable;", + "Lorg/jetbrains/annotations/NotNull;", + "Lorg/jetbrains/annotations/Contract;", +@@ -66,7 +72,7 @@ public class AnnotationTest { + continue; + } + +- if (mustBeAnnotated(Type.getReturnType(method.desc)) && !isWellAnnotated(method.invisibleAnnotations)) { ++ if (mustBeAnnotated(Type.getReturnType(method.desc)) && !isWellAnnotated(method.invisibleAnnotations) && !isWellAnnotated(method.visibleTypeAnnotations)) { // Paper - also check visible type annotations + warn(errors, clazz, method, "return value"); + } + +@@ -174,7 +180,7 @@ public class AnnotationTest { + return true; + } + +- private static boolean isWellAnnotated(@Nullable List annotations) { ++ private static boolean isWellAnnotated(@Nullable List annotations) { // Paper - allow children of AnnotationNode + if (annotations == null) { + return false; + } diff --git a/patches/api-unmapped/0006-Player-affects-spawning-API.patch b/patches/api-unmapped/0006-Player-affects-spawning-API.patch new file mode 100644 index 0000000000..f923a3d19b --- /dev/null +++ b/patches/api-unmapped/0006-Player-affects-spawning-API.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Mon, 29 Feb 2016 17:22:34 -0600 +Subject: [PATCH] Player affects spawning API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 171e2663301f654258dbd772a57688b5a2f8469c..76ac0b20842002ce1b593e338bea98483e7080ac 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1380,6 +1380,22 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + @Deprecated // Paper + public String getLocale(); + ++ // Paper start ++ /** ++ * Get whether the player can affect mob spawning ++ * ++ * @return if the player can affect mob spawning ++ */ ++ public boolean getAffectsSpawning(); ++ ++ /** ++ * Set whether the player can affect mob spawning ++ * ++ * @param affects Whether the player can affect mob spawning ++ */ ++ public void setAffectsSpawning(boolean affects); ++ // Paper end ++ + /** + * Update the list of commands sent to the client. + *
    diff --git a/patches/api-unmapped/0007-Add-getTPS-method.patch b/patches/api-unmapped/0007-Add-getTPS-method.patch new file mode 100644 index 0000000000..22aef5d962 --- /dev/null +++ b/patches/api-unmapped/0007-Add-getTPS-method.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 29 Feb 2016 17:24:57 -0600 +Subject: [PATCH] Add getTPS method + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index ab4d5aca6251b620ef5d654fa4ea3fc31783c2f2..0636edd8d9121eabfa60957c8c224261d228a16b 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1543,6 +1543,17 @@ public final class Bukkit { + return server.getEntity(uuid); + } + ++ // Paper start ++ /** ++ * Gets the current server TPS ++ * @return current server TPS (1m, 5m, 15m in Paper-Server) ++ */ ++ @NotNull ++ public static double[] getTPS() { ++ return server.getTPS(); ++ } ++ // Paper end ++ + /** + * 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 b862f22d5f31934eb46b50ecf04f8c1bf23c5044..5c638e0d45e8896382bdbf9b9c10474b05a97df5 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1301,6 +1301,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @Nullable + Entity getEntity(@NotNull UUID uuid); + ++ // Paper start ++ /** ++ * Gets the current server TPS ++ * ++ * @return current server TPS (1m, 5m, 15m in Paper-Server) ++ */ ++ @NotNull ++ public double[] getTPS(); ++ // Paper end ++ + /** + * Get the advancement specified by this key. + * diff --git a/patches/api-unmapped/0008-Entity-Origin-API.patch b/patches/api-unmapped/0008-Entity-Origin-API.patch new file mode 100644 index 0000000000..626916f4f7 --- /dev/null +++ b/patches/api-unmapped/0008-Entity-Origin-API.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Mon, 29 Feb 2016 17:50:31 -0600 +Subject: [PATCH] Entity Origin API + + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 03e12de470f983e89a473c4e42c21941085b1d37..fdce246aecac775c3ff4a028c307b09762505258 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -655,5 +655,15 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { + return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.customName()))); + } ++ ++ /** ++ * Gets the location where this entity originates from. ++ *

    ++ * This value can be null if the entity hasn't yet been added to the world. ++ * ++ * @return Location where entity originates or null if not yet added ++ */ ++ @Nullable ++ Location getOrigin(); + // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/FallingBlock.java b/src/main/java/org/bukkit/entity/FallingBlock.java +index 64f9d3fd870d65afd2ee9a85625b149163eee144..14cb0d770561151570ab4399ca5facff43076819 100644 +--- a/src/main/java/org/bukkit/entity/FallingBlock.java ++++ b/src/main/java/org/bukkit/entity/FallingBlock.java +@@ -54,4 +54,15 @@ public interface FallingBlock extends Entity { + * @param hurtEntities whether entities will be damaged by this block. + */ + void setHurtEntities(boolean hurtEntities); ++ ++ /** ++ * Gets the source block location of the FallingBlock ++ * ++ * @return the source block location the FallingBlock was spawned from ++ * @deprecated replaced by {@link Entity#getOrigin()} ++ */ ++ @Deprecated ++ default org.bukkit.Location getSourceLoc() { ++ return this.getOrigin(); ++ } + } +diff --git a/src/main/java/org/bukkit/entity/TNTPrimed.java b/src/main/java/org/bukkit/entity/TNTPrimed.java +index a23cfdf66877f0a61eae700de084c76e6ee7b431..0813bd913c8fdb2001963ce3e82c07c2af105418 100644 +--- a/src/main/java/org/bukkit/entity/TNTPrimed.java ++++ b/src/main/java/org/bukkit/entity/TNTPrimed.java +@@ -53,4 +53,15 @@ public interface TNTPrimed extends Explosive { + * @param source the source of this primed TNT + */ + public void setSource(@Nullable Entity source); ++ ++ /** ++ * Gets the source block location of the TNTPrimed ++ * ++ * @return the source block location the TNTPrimed was spawned from ++ * @deprecated replaced by {@link Entity#getOrigin()} ++ */ ++ @Deprecated ++ default org.bukkit.Location getSourceLoc() { ++ return this.getOrigin(); ++ } + } diff --git a/patches/api-unmapped/0009-Version-Command-2.0.patch b/patches/api-unmapped/0009-Version-Command-2.0.patch new file mode 100644 index 0000000000..c7cc974e1a --- /dev/null +++ b/patches/api-unmapped/0009-Version-Command-2.0.patch @@ -0,0 +1,185 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 27 May 2019 01:10:06 -0500 +Subject: [PATCH] Version Command 2.0 + + +diff --git a/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a736d7bcdc5861a01b66ba36158db1c716339346 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java +@@ -0,0 +1,45 @@ ++package com.destroystokyo.paper.util; ++ ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.format.NamedTextColor; ++import org.bukkit.Bukkit; ++import org.jetbrains.annotations.NotNull; ++ ++public interface VersionFetcher { ++ /** ++ * Amount of time to cache results for in milliseconds ++ *

    ++ * Negative values will never cache. ++ * ++ * @return cache time ++ */ ++ long getCacheTime(); ++ ++ /** ++ * Gets the version message to cache and show to command senders. ++ * ++ *

    NOTE: This is run in a new thread separate from that of the command processing thread

    ++ * ++ * @param serverVersion the current version of the server (will match {@link Bukkit#getVersion()}) ++ * @return the message to show when requesting a version ++ */ ++ @NotNull ++ Component getVersionMessage(@NotNull String serverVersion); ++ ++ class DummyVersionFetcher implements VersionFetcher { ++ ++ @Override ++ public long getCacheTime() { ++ return -1; ++ } ++ ++ @NotNull ++ @Override ++ public Component getVersionMessage(@NotNull String serverVersion) { ++ Bukkit.getLogger().warning("Version provider has not been set, cannot check for updates!"); ++ Bukkit.getLogger().info("Override the default implementation of org.bukkit.UnsafeValues#getVersionFetcher()"); ++ new Throwable().printStackTrace(); ++ return Component.text("Unable to check for updates. No version provider set.", NamedTextColor.RED); ++ } ++ } ++} +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 207c656c0a11a3a630bc70491efcf433b2681e18..195b6bb328de92c4d17d1cd14e13578226b1ac3c 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -84,5 +84,12 @@ public interface UnsafeValues { + * @return name + */ + String getTimingsServerName(); ++ ++ /** ++ * Called once by the version command on first use, then cached. ++ */ ++ default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { ++ return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher(); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/command/defaults/VersionCommand.java b/src/main/java/org/bukkit/command/defaults/VersionCommand.java +index 2305eb40832a82159cd89162934870cf57e1aa0e..4c2ddc722a9dc4011906ad9530b13fa9be1d3ff9 100644 +--- a/src/main/java/org/bukkit/command/defaults/VersionCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/VersionCommand.java +@@ -1,5 +1,6 @@ + package org.bukkit.command.defaults; + ++import com.destroystokyo.paper.util.VersionFetcher; // Paper - version supplier + import com.google.common.base.Charsets; + import com.google.common.collect.ImmutableList; + import com.google.common.io.Resources; +@@ -16,6 +17,7 @@ import java.util.HashSet; + import java.util.List; + import java.util.Set; + import java.util.concurrent.locks.ReentrantLock; ++import net.kyori.adventure.text.Component; // Paper + import org.apache.commons.lang.Validate; + import org.bukkit.Bukkit; + import org.bukkit.ChatColor; +@@ -26,6 +28,15 @@ import org.bukkit.util.StringUtil; + import org.jetbrains.annotations.NotNull; + + public class VersionCommand extends BukkitCommand { ++ private VersionFetcher versionFetcher; ++ private VersionFetcher getVersionFetcher() { // lazy load because unsafe isn't available at command registration ++ if (versionFetcher == null) { ++ versionFetcher = Bukkit.getUnsafe().getVersionFetcher(); ++ } ++ ++ return versionFetcher; ++ } ++ + public VersionCommand(@NotNull String name) { + super(name); + +@@ -40,7 +51,7 @@ public class VersionCommand extends BukkitCommand { + if (!testPermission(sender)) return true; + + if (args.length == 0) { +- sender.sendMessage("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")"); ++ //sender.sendMessage("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")"); // Paper - moved to setVersionMessage + sendVersion(sender); + } else { + StringBuilder name = new StringBuilder(); +@@ -146,14 +157,14 @@ public class VersionCommand extends BukkitCommand { + + private final ReentrantLock versionLock = new ReentrantLock(); + private boolean hasVersion = false; +- private String versionMessage = null; ++ private Component versionMessage = null; // Paper + private final Set versionWaiters = new HashSet(); + private boolean versionTaskStarted = false; + private long lastCheck = 0; + + private void sendVersion(@NotNull CommandSender sender) { + if (hasVersion) { +- if (System.currentTimeMillis() - lastCheck > 21600000) { ++ if (System.currentTimeMillis() - lastCheck > getVersionFetcher().getCacheTime()) { // Paper - use version supplier + lastCheck = System.currentTimeMillis(); + hasVersion = false; + } else { +@@ -168,7 +179,7 @@ public class VersionCommand extends BukkitCommand { + return; + } + versionWaiters.add(sender); +- sender.sendMessage("Checking version, please wait..."); ++ sender.sendMessage(Component.text("Checking version, please wait...", net.kyori.adventure.text.format.NamedTextColor.WHITE, net.kyori.adventure.text.format.TextDecoration.ITALIC)); // Paper + if (!versionTaskStarted) { + versionTaskStarted = true; + new Thread(new Runnable() { +@@ -186,6 +197,13 @@ public class VersionCommand extends BukkitCommand { + + private void obtainVersion() { + String version = Bukkit.getVersion(); ++ // Paper start ++ if (version.startsWith("null")) { // running from ide? ++ setVersionMessage(Component.text("Unknown version, custom build?", net.kyori.adventure.text.format.NamedTextColor.YELLOW)); ++ return; ++ } ++ setVersionMessage(getVersionFetcher().getVersionMessage(version)); ++ /* + if (version == null) version = "Custom"; + String[] parts = version.substring(0, version.indexOf(' ')).split("-"); + if (parts.length == 4) { +@@ -215,11 +233,24 @@ public class VersionCommand extends BukkitCommand { + } else { + setVersionMessage("Unknown version, custom build?"); + } ++ */ ++ // Paper end + } + +- private void setVersionMessage(@NotNull String msg) { ++ // Paper start ++ private void setVersionMessage(final @NotNull Component msg) { + lastCheck = System.currentTimeMillis(); +- versionMessage = msg; ++ final Component message = net.kyori.adventure.text.TextComponent.ofChildren( ++ Component.text("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")", net.kyori.adventure.text.format.NamedTextColor.WHITE), ++ Component.newline(), ++ msg ++ ); ++ this.versionMessage = Component.text() ++ .append(message) ++ .hoverEvent(Component.text("Click to copy to clipboard", net.kyori.adventure.text.format.NamedTextColor.WHITE)) ++ .clickEvent(net.kyori.adventure.text.event.ClickEvent.copyToClipboard(net.kyori.adventure.text.serializer.plain.PlainComponentSerializer.plain().serialize(message))) ++ .build(); ++ // Paper end + versionLock.lock(); + try { + hasVersion = true; diff --git a/patches/api-unmapped/0010-Add-PlayerLocaleChangeEvent.patch b/patches/api-unmapped/0010-Add-PlayerLocaleChangeEvent.patch new file mode 100644 index 0000000000..10593168ec --- /dev/null +++ b/patches/api-unmapped/0010-Add-PlayerLocaleChangeEvent.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Isaac Moore +Date: Mon, 29 Feb 2016 18:02:25 -0600 +Subject: [PATCH] Add PlayerLocaleChangeEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..29dd763a99ce7c6ecb176b9fb346a400369d48a0 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java +@@ -0,0 +1,50 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++ ++/** ++ * Called when the locale of the player is changed. ++ * ++ * @deprecated Replaced by {@link org.bukkit.event.player.PlayerLocaleChangeEvent} upstream ++ */ ++@Deprecated ++public class PlayerLocaleChangeEvent extends PlayerEvent { ++ private static final HandlerList handlers = new HandlerList(); ++ private final String oldLocale; ++ private final String newLocale; ++ ++ public PlayerLocaleChangeEvent(final Player player, final String oldLocale, final String newLocale) { ++ super(player); ++ this.oldLocale = oldLocale; ++ this.newLocale = newLocale; ++ } ++ ++ /** ++ * Gets the locale the player switched from. ++ * ++ * @return player's old locale ++ */ ++ public String getOldLocale() { ++ return oldLocale; ++ } ++ ++ /** ++ * Gets the locale the player is changed to. ++ * ++ * @return player's new locale ++ */ ++ public String getNewLocale() { ++ return newLocale; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0011-Add-player-view-distance-API.patch b/patches/api-unmapped/0011-Add-player-view-distance-API.patch new file mode 100644 index 0000000000..8b5561ac14 --- /dev/null +++ b/patches/api-unmapped/0011-Add-player-view-distance-API.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Mon, 29 Feb 2016 18:05:37 -0600 +Subject: [PATCH] Add player view distance API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 76ac0b20842002ce1b593e338bea98483e7080ac..f34601480a3b3069c30c52d258a35a2a79c981fb 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1394,6 +1394,28 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @param affects Whether the player can affect mob spawning + */ + public void setAffectsSpawning(boolean affects); ++ ++ /** ++ * Gets the view distance for this player ++ * ++ * @return the player's view distance ++ * @deprecated This is unimplemented and will throw an exception at runtime. The {@link org.bukkit.World World}-based methods still work. ++ * @see org.bukkit.World#getViewDistance() ++ * @see org.bukkit.World#getNoTickViewDistance() ++ */ ++ @Deprecated ++ public int getViewDistance(); ++ ++ /** ++ * Sets the view distance for this player ++ * ++ * @param viewDistance the player's view distance ++ * @deprecated This is unimplemented and will throw an exception at runtime. The {@link org.bukkit.World World}-based methods still work. ++ * @see org.bukkit.World#setViewDistance(int) ++ * @see org.bukkit.World#setNoTickViewDistance(int) ++ */ ++ @Deprecated ++ public void setViewDistance(int viewDistance); + // Paper end + + /** diff --git a/patches/api-unmapped/0012-Add-BeaconEffectEvent.patch b/patches/api-unmapped/0012-Add-BeaconEffectEvent.patch new file mode 100644 index 0000000000..43af3c3828 --- /dev/null +++ b/patches/api-unmapped/0012-Add-BeaconEffectEvent.patch @@ -0,0 +1,98 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Mon, 29 Feb 2016 18:09:40 -0600 +Subject: [PATCH] Add BeaconEffectEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..978813b94a5eae0afccbd3b38b463091a46b56ac +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java +@@ -0,0 +1,86 @@ ++package com.destroystokyo.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.bukkit.potion.PotionEffect; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a beacon effect is being applied to a player. ++ */ ++public class BeaconEffectEvent extends BlockEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ private PotionEffect effect; ++ private Player player; ++ private boolean primary; ++ ++ public BeaconEffectEvent(@NotNull Block block, @NotNull PotionEffect effect, @NotNull Player player, boolean primary) { ++ super(block); ++ this.effect = effect; ++ this.player = player; ++ this.primary = primary; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancelled) { ++ this.cancelled = cancelled; ++ } ++ ++ /** ++ * Gets the potion effect being applied. ++ * ++ * @return Potion effect ++ */ ++ @NotNull ++ public PotionEffect getEffect() { ++ return effect; ++ } ++ ++ /** ++ * Sets the potion effect that will be applied. ++ * ++ * @param effect Potion effect ++ */ ++ public void setEffect(@NotNull PotionEffect effect) { ++ this.effect = effect; ++ } ++ ++ /** ++ * Gets the player who the potion effect is being applied to. ++ * ++ * @return Affected player ++ */ ++ @NotNull ++ public Player getPlayer() { ++ return player; ++ } ++ ++ /** ++ * Gets whether the effect is a primary beacon effect. ++ * ++ * @return true if this event represents a primary effect ++ */ ++ public boolean isPrimary() { ++ return primary; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0013-Add-PlayerInitialSpawnEvent.patch b/patches/api-unmapped/0013-Add-PlayerInitialSpawnEvent.patch new file mode 100644 index 0000000000..c113777bf5 --- /dev/null +++ b/patches/api-unmapped/0013-Add-PlayerInitialSpawnEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Steve Anton +Date: Mon, 29 Feb 2016 18:13:58 -0600 +Subject: [PATCH] Add PlayerInitialSpawnEvent + +For modifying a player's initial spawn location as they join the server + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8b1fdb9d2869d4c1862d557c91bf8a1d8c537507 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java +@@ -0,0 +1,16 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.Player; ++import org.jetbrains.annotations.NotNull; ++import org.spigotmc.event.player.PlayerSpawnLocationEvent; ++ ++/** ++ * @deprecated Use {@link PlayerSpawnLocationEvent}, Duplicate API ++ */ ++public class PlayerInitialSpawnEvent extends PlayerSpawnLocationEvent { ++ ++ public PlayerInitialSpawnEvent(@NotNull Player who, @NotNull Location spawnLocation) { ++ super(who, spawnLocation); ++ } ++} diff --git a/patches/api-unmapped/0014-Automatically-disable-plugins-that-fail-to-load.patch b/patches/api-unmapped/0014-Automatically-disable-plugins-that-fail-to-load.patch new file mode 100644 index 0000000000..55aeb559ba --- /dev/null +++ b/patches/api-unmapped/0014-Automatically-disable-plugins-that-fail-to-load.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 29 Feb 2016 19:45:21 -0600 +Subject: [PATCH] Automatically disable plugins that fail to load + + +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index cf2f517765d8f2a23cc4a17d9ee2dcd81f841b1b..2e306c7b984a02e12a74fac14589bf29ab6488bf 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -335,6 +335,10 @@ public final class JavaPluginLoader implements PluginLoader { + jPlugin.setEnabled(true); + } catch (Throwable ex) { + server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ // Paper start - Disable plugins that fail to load ++ disablePlugin(jPlugin); ++ return; ++ // Paper end + } + + // Perhaps abort here, rather than continue going, but as it stands, diff --git a/patches/api-unmapped/0015-Expose-server-CommandMap.patch b/patches/api-unmapped/0015-Expose-server-CommandMap.patch new file mode 100644 index 0000000000..6d7e3f1431 --- /dev/null +++ b/patches/api-unmapped/0015-Expose-server-CommandMap.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Mon, 29 Feb 2016 19:48:59 -0600 +Subject: [PATCH] Expose server CommandMap + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 0636edd8d9121eabfa60957c8c224261d228a16b..8d707e117035d5bc0d8c9a5fd386ee8355359259 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1717,6 +1717,19 @@ public final class Bukkit { + return server.getUnsafe(); + } + ++ ++ // Paper start ++ /** ++ * Gets the active {@link org.bukkit.command.CommandMap} ++ * ++ * @return the active command map ++ */ ++ @NotNull ++ public static org.bukkit.command.CommandMap getCommandMap() { ++ return server.getCommandMap(); ++ } ++ // Paper end ++ + @NotNull + 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 5c638e0d45e8896382bdbf9b9c10474b05a97df5..24bcc63afbda5f27aad385dc707f262d1a3a3399 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1311,6 +1311,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + public double[] getTPS(); + // Paper end + ++ // Paper start ++ /** ++ * Gets the active {@link org.bukkit.command.CommandMap} ++ * ++ * @return the active command map ++ */ ++ @NotNull ++ org.bukkit.command.CommandMap getCommandMap(); ++ + /** + * Get the advancement specified by this key. + * diff --git a/patches/api-unmapped/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch b/patches/api-unmapped/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch new file mode 100644 index 0000000000..28128cfb69 --- /dev/null +++ b/patches/api-unmapped/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch @@ -0,0 +1,124 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 29 Feb 2016 19:54:32 -0600 +Subject: [PATCH] Graduate bungeecord chat API from spigot subclasses + +Change Javadoc to be accurate + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 10274053320f1ec690a65d3794abb44b58658059..22b83b142de97dcba28fa9a49730de7880d0b5d2 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -285,6 +285,30 @@ public final class Bukkit { + return server.broadcastMessage(message); + } + ++ // Paper start ++ /** ++ * Sends the component to all online players. ++ * ++ * @param component the component to send ++ * @deprecated use {@code sendMessage} methods on {@link #getServer()} that accept {@link net.kyori.adventure.text.Component} ++ */ ++ @Deprecated ++ public static void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { ++ server.broadcast(component); ++ } ++ ++ /** ++ * Sends an array of components as a single message to all online players. ++ * ++ * @param components the components to send ++ * @deprecated use {@code sendMessage} methods on {@link #getServer()} that accept {@link net.kyori.adventure.text.Component} ++ */ ++ @Deprecated ++ public static void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { ++ server.broadcast(components); ++ } ++ // Paper end ++ + /** + * Gets the name of the update folder. The update folder is used to safely + * update plugins at the right moment on a plugin load. +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 7e4a728ceb943b6a32b9ba9b84bada34e71c0980..9ce9b4ce2da6c57c62607502ae2042e30fc26d88 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -234,6 +234,30 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @Deprecated // Paper + public int broadcastMessage(@NotNull String message); + ++ // Paper start ++ /** ++ * Sends the component to all online players. ++ * ++ * @param component the component to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} ++ */ ++ @Deprecated ++ public default void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { ++ spigot().broadcast(component); ++ } ++ ++ /** ++ * Sends an array of components as a single message to all online players. ++ * ++ * @param components the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} ++ */ ++ @Deprecated ++ public default void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { ++ spigot().broadcast(components); ++ } ++ // Paper end ++ + /** + * Gets the name of the update folder. The update folder is used to safely + * update plugins at the right moment on a plugin load. +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 68795a48cb15d322906ce0569b7701231c1f94c2..88853cc165c67fd60a0a8f87e4ce356e4ca045f9 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -614,6 +614,42 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public void sendMap(@NotNull MapView map); + ++ // Paper start ++ /** ++ * Sends the component to the player ++ * ++ * @param component the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} ++ */ ++ @Override ++ @Deprecated ++ public default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { ++ spigot().sendMessage(component); ++ } ++ ++ /** ++ * Sends an array of components as a single message to the player ++ * ++ * @param components the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} ++ */ ++ @Override ++ @Deprecated ++ public default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { ++ spigot().sendMessage(components); ++ } ++ ++ /** ++ * Sends an array of components as a single message to the specified screen position of this player ++ * ++ * @param position the screen position ++ * @param components the components to send ++ */ ++ public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { ++ spigot().sendMessage(position, components); ++ } ++ // Paper end ++ + /** + * Forces an update of the player's entire inventory. + * diff --git a/patches/api-unmapped/0017-Player-Tab-List-and-Title-APIs.patch b/patches/api-unmapped/0017-Player-Tab-List-and-Title-APIs.patch new file mode 100644 index 0000000000..90316cae1d --- /dev/null +++ b/patches/api-unmapped/0017-Player-Tab-List-and-Title-APIs.patch @@ -0,0 +1,577 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Mon, 29 Feb 2016 20:02:40 -0600 +Subject: [PATCH] Player Tab List and Title APIs + +Co-authored-by: Fruxz + +diff --git a/src/main/java/com/destroystokyo/paper/Title.java b/src/main/java/com/destroystokyo/paper/Title.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9e90c3df567a65b48a0b9341f784eb902cb35d8c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/Title.java +@@ -0,0 +1,420 @@ ++package com.destroystokyo.paper; ++ ++import net.md_5.bungee.api.chat.BaseComponent; ++import net.md_5.bungee.api.chat.TextComponent; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.entity.Player; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collection; ++import java.util.List; ++ ++import static com.google.common.base.Preconditions.checkArgument; ++import static com.google.common.base.Preconditions.checkNotNull; ++import static com.google.common.base.Preconditions.checkState; ++ ++/** ++ * Represents a title to may be sent to a {@link Player}. ++ * ++ *

    A title can be sent without subtitle text.

    ++ * ++ * @deprecated use {@link net.kyori.adventure.title.Title} ++ */ ++@Deprecated ++public final class Title { ++ ++ /** ++ * The default number of ticks for the title to fade in. ++ */ ++ public static final int DEFAULT_FADE_IN = 20; ++ /** ++ * The default number of ticks for the title to stay. ++ */ ++ public static final int DEFAULT_STAY = 200; ++ /** ++ * The default number of ticks for the title to fade out. ++ */ ++ public static final int DEFAULT_FADE_OUT = 20; ++ ++ private final BaseComponent[] title; ++ private final BaseComponent[] subtitle; ++ private final int fadeIn; ++ private final int stay; ++ private final int fadeOut; ++ ++ /** ++ * Create a title with the default time values and no subtitle. ++ * ++ *

    Times use default values.

    ++ * ++ * @param title the main text of the title ++ * @throws NullPointerException if the title is null ++ */ ++ public Title(@NotNull BaseComponent title) { ++ this(title, null); ++ } ++ ++ /** ++ * Create a title with the default time values and no subtitle. ++ * ++ *

    Times use default values.

    ++ * ++ * @param title the main text of the title ++ * @throws NullPointerException if the title is null ++ */ ++ public Title(@NotNull BaseComponent[] title) { ++ this(title, null); ++ } ++ ++ /** ++ * Create a title with the default time values and no subtitle. ++ * ++ *

    Times use default values.

    ++ * ++ * @param title the main text of the title ++ * @throws NullPointerException if the title is null ++ */ ++ public Title(@NotNull String title) { ++ this(title, null); ++ } ++ ++ /** ++ * Create a title with the default time values. ++ * ++ *

    Times use default values.

    ++ * ++ * @param title the main text of the title ++ * @param subtitle the secondary text of the title ++ */ ++ public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle) { ++ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT); ++ } ++ ++ /** ++ * Create a title with the default time values. ++ * ++ *

    Times use default values.

    ++ * ++ * @param title the main text of the title ++ * @param subtitle the secondary text of the title ++ */ ++ public Title(@NotNull BaseComponent[] title, @Nullable BaseComponent[] subtitle) { ++ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT); ++ } ++ ++ /** ++ * Create a title with the default time values. ++ * ++ *

    Times use default values.

    ++ * ++ * @param title the main text of the title ++ * @param subtitle the secondary text of the title ++ */ ++ public Title(@NotNull String title, @Nullable String subtitle) { ++ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT); ++ } ++ ++ /** ++ * Creates a new title. ++ * ++ * @param title the main text of the title ++ * @param subtitle the secondary text of the title ++ * @param fadeIn the number of ticks for the title to fade in ++ * @param stay the number of ticks for the title to stay on screen ++ * @param fadeOut the number of ticks for the title to fade out ++ * @throws IllegalArgumentException if any of the times are negative ++ */ ++ public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle, int fadeIn, int stay, int fadeOut) { ++ this( ++ new BaseComponent[]{checkNotNull(title, "title")}, ++ subtitle == null ? null : new BaseComponent[]{subtitle}, ++ fadeIn, ++ stay, ++ fadeOut ++ ); ++ } ++ ++ /** ++ * Creates a new title. ++ * ++ * @param title the main text of the title ++ * @param subtitle the secondary text of the title ++ * @param fadeIn the number of ticks for the title to fade in ++ * @param stay the number of ticks for the title to stay on screen ++ * @param fadeOut the number of ticks for the title to fade out ++ * @throws IllegalArgumentException if any of the times are negative ++ */ ++ public Title(@Nullable BaseComponent[] title, @NotNull BaseComponent[] subtitle, int fadeIn, int stay, int fadeOut) { ++ checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn); ++ checkArgument(stay >= 0, "Negative stay: %s", stay); ++ checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut); ++ this.title = checkNotNull(title, "title"); ++ this.subtitle = subtitle; ++ this.fadeIn = fadeIn; ++ this.stay = stay; ++ this.fadeOut = fadeOut; ++ } ++ ++ /** ++ * Creates a new title. ++ * ++ *

    It is recommended to the {@link BaseComponent} constrctors.

    ++ * ++ * @param title the main text of the title ++ * @param subtitle the secondary text of the title ++ * @param fadeIn the number of ticks for the title to fade in ++ * @param stay the number of ticks for the title to stay on screen ++ * @param fadeOut the number of ticks for the title to fade out ++ */ ++ public Title(@NotNull String title, @Nullable String subtitle, int fadeIn, int stay, int fadeOut) { ++ this( ++ TextComponent.fromLegacyText(checkNotNull(title, "title")), ++ subtitle == null ? null : TextComponent.fromLegacyText(subtitle), ++ fadeIn, ++ stay, ++ fadeOut ++ ); ++ } ++ ++ /** ++ * Gets the text of this title ++ * ++ * @return the text ++ */ ++ @NotNull ++ public BaseComponent[] getTitle() { ++ return this.title; ++ } ++ ++ /** ++ * Gets the text of this title's subtitle ++ * ++ * @return the text ++ */ ++ @Nullable ++ public BaseComponent[] getSubtitle() { ++ return this.subtitle; ++ } ++ ++ /** ++ * Gets the number of ticks to fade in. ++ * ++ *

    The returned value is never negative.

    ++ * ++ * @return the number of ticks to fade in ++ */ ++ public int getFadeIn() { ++ return this.fadeIn; ++ } ++ ++ /** ++ * Gets the number of ticks to stay. ++ * ++ *

    The returned value is never negative.

    ++ * ++ * @return the number of ticks to stay ++ */ ++ public int getStay() { ++ return this.stay; ++ } ++ ++ /** ++ * Gets the number of ticks to fade out. ++ * ++ *

    The returned value is never negative.

    ++ * ++ * @return the number of ticks to fade out ++ */ ++ public int getFadeOut() { ++ return this.fadeOut; ++ } ++ ++ /** ++ * Sends the title directly to an player ++ * ++ * @param player the receiver of the title ++ */ ++ public void send(@NotNull Player player) { ++ player.sendTitle(this); ++ } ++ ++ /** ++ * Sends the title directly to the defined players ++ * ++ * @param players the receivers of the title ++ */ ++ public void send(@NotNull Collection players) { ++ for (Player player : players) { ++ player.sendTitle(this); ++ } ++ } ++ ++ /** ++ * Sends the title directly to the defined players ++ * ++ * @param players the receivers of the title ++ */ ++ public void send(@NotNull Player[] players) { ++ for (Player player : players) { ++ player.sendTitle(this); ++ } ++ } ++ ++ /** ++ * Sends the title directly to all online players ++ */ ++ public void broadcast() { ++ send(Bukkit.getOnlinePlayers()); ++ } ++ ++ @NotNull ++ public static Builder builder() { ++ return new Builder(); ++ } ++ ++ /** ++ * A builder for creating titles ++ */ ++ public static final class Builder { ++ ++ private BaseComponent[] title; ++ private BaseComponent[] subtitle; ++ private int fadeIn = DEFAULT_FADE_IN; ++ private int stay = DEFAULT_STAY; ++ private int fadeOut = DEFAULT_FADE_OUT; ++ ++ /** ++ * Sets the title to the given text. ++ * ++ * @param title the title text ++ * @return this builder instance ++ * @throws NullPointerException if the title is null ++ */ ++ @NotNull ++ public Builder title(@NotNull BaseComponent title) { ++ return this.title(new BaseComponent[]{checkNotNull(title, "title")}); ++ } ++ ++ /** ++ * Sets the title to the given text. ++ * ++ * @param title the title text ++ * @return this builder instance ++ * @throws NullPointerException if the title is null ++ */ ++ @NotNull ++ public Builder title(@NotNull BaseComponent[] title) { ++ this.title = checkNotNull(title, "title"); ++ return this; ++ } ++ ++ /** ++ * Sets the title to the given text. ++ * ++ *

    It is recommended to the {@link BaseComponent} methods.

    ++ * ++ * @param title the title text ++ * @return this builder instance ++ * @throws NullPointerException if the title is null ++ */ ++ @NotNull ++ public Builder title(@NotNull String title) { ++ return this.title(TextComponent.fromLegacyText(checkNotNull(title, "title"))); ++ } ++ ++ /** ++ * Sets the subtitle to the given text. ++ * ++ * @param subtitle the title text ++ * @return this builder instance ++ */ ++ @NotNull ++ public Builder subtitle(@Nullable BaseComponent subtitle) { ++ return this.subtitle(subtitle == null ? null : new BaseComponent[]{subtitle}); ++ } ++ ++ /** ++ * Sets the subtitle to the given text. ++ * ++ * @param subtitle the title text ++ * @return this builder instance ++ */ ++ @NotNull ++ public Builder subtitle(@Nullable BaseComponent[] subtitle) { ++ this.subtitle = subtitle; ++ return this; ++ } ++ ++ /** ++ * Sets the subtitle to the given text. ++ * ++ *

    It is recommended to the {@link BaseComponent} methods.

    ++ * ++ * @param subtitle the title text ++ * @return this builder instance ++ */ ++ @NotNull ++ public Builder subtitle(@Nullable String subtitle) { ++ return this.subtitle(subtitle == null ? null : TextComponent.fromLegacyText(subtitle)); ++ } ++ ++ /** ++ * Sets the number of ticks for the title to fade in ++ * ++ * @param fadeIn the number of ticks to fade in ++ * @return this builder instance ++ * @throws IllegalArgumentException if it is negative ++ */ ++ @NotNull ++ public Builder fadeIn(int fadeIn) { ++ checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn); ++ this.fadeIn = fadeIn; ++ return this; ++ } ++ ++ ++ /** ++ * Sets the number of ticks for the title to stay. ++ * ++ * @param stay the number of ticks to stay ++ * @return this builder instance ++ * @throws IllegalArgumentException if it is negative ++ */ ++ @NotNull ++ public Builder stay(int stay) { ++ checkArgument(stay >= 0, "Negative stay: %s", stay); ++ this.stay = stay; ++ return this; ++ } ++ ++ /** ++ * Sets the number of ticks for the title to fade out. ++ * ++ * @param fadeOut the number of ticks to fade out ++ * @return this builder instance ++ * @throws IllegalArgumentException if it is negative ++ */ ++ @NotNull ++ public Builder fadeOut(int fadeOut) { ++ checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut); ++ this.fadeOut = fadeOut; ++ return this; ++ } ++ ++ /** ++ * Create a title based on the values in the builder. ++ * ++ * @return a title from the values in this builder ++ * @throws IllegalStateException if title isn't specified ++ */ ++ @NotNull ++ public Title build() { ++ checkState(title != null, "Title not specified"); ++ return new Title(this.title, this.subtitle, this.fadeIn, this.stay, this.fadeOut); ++ } ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 88853cc165c67fd60a0a8f87e4ce356e4ca045f9..c9e4cb2d153fc0c6853fe520263a0073e7504e38 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -2,6 +2,7 @@ package org.bukkit.entity; + + import java.net.InetSocketAddress; + import java.util.UUID; ++import com.destroystokyo.paper.Title; // Paper + import org.bukkit.DyeColor; + import org.bukkit.Effect; + import org.bukkit.GameMode; +@@ -648,6 +649,131 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { + spigot().sendMessage(position, components); + } ++ ++ /** ++ * Set the text displayed in the player list header and footer for this player ++ * ++ * @param header content for the top of the player list ++ * @param footer content for the bottom of the player list ++ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated ++ public void setPlayerListHeaderFooter(@Nullable net.md_5.bungee.api.chat.BaseComponent[] header, @Nullable net.md_5.bungee.api.chat.BaseComponent[] footer); ++ ++ /** ++ * Set the text displayed in the player list header and footer for this player ++ * ++ * @param header content for the top of the player list ++ * @param footer content for the bottom of the player list ++ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated ++ public void setPlayerListHeaderFooter(@Nullable net.md_5.bungee.api.chat.BaseComponent header, @Nullable net.md_5.bungee.api.chat.BaseComponent footer); ++ ++ /** ++ * Update the times for titles displayed to the player ++ * ++ * @param fadeInTicks ticks to fade-in ++ * @param stayTicks ticks to stay visible ++ * @param fadeOutTicks ticks to fade-out ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} ++ */ ++ @Deprecated ++ public void setTitleTimes(int fadeInTicks, int stayTicks, int fadeOutTicks); ++ ++ /** ++ * Update the subtitle of titles displayed to the player ++ * ++ * @param subtitle Subtitle to set ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} ++ */ ++ @Deprecated ++ public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent[] subtitle); ++ ++ /** ++ * Update the subtitle of titles displayed to the player ++ * ++ * @param subtitle Subtitle to set ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} ++ */ ++ @Deprecated ++ public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent subtitle); ++ ++ /** ++ * Show the given title to the player, along with the last subtitle set, using the last set times ++ * ++ * @param title Title to set ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} ++ */ ++ @Deprecated ++ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent[] title); ++ ++ /** ++ * Show the given title to the player, along with the last subtitle set, using the last set times ++ * ++ * @param title Title to set ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} ++ */ ++ @Deprecated ++ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent title); ++ ++ /** ++ * Show the given title and subtitle to the player using the given times ++ * ++ * @param title big text ++ * @param subtitle little text under it ++ * @param fadeInTicks ticks to fade-in ++ * @param stayTicks ticks to stay visible ++ * @param fadeOutTicks ticks to fade-out ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} ++ */ ++ @Deprecated ++ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent[] title, @Nullable net.md_5.bungee.api.chat.BaseComponent[] subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks); ++ ++ /** ++ * Show the given title and subtitle to the player using the given times ++ * ++ * @param title big text ++ * @param subtitle little text under it ++ * @param fadeInTicks ticks to fade-in ++ * @param stayTicks ticks to stay visible ++ * @param fadeOutTicks ticks to fade-out ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} ++ */ ++ @Deprecated ++ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent title, @Nullable net.md_5.bungee.api.chat.BaseComponent subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks); ++ ++ /** ++ * Show the title to the player, overriding any previously displayed title. ++ * ++ *

    This method overrides any previous title, use {@link #updateTitle(Title)} to change the existing one.

    ++ * ++ * @param title the title to send ++ * @throws NullPointerException if the title is null ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} ++ */ ++ @Deprecated ++ void sendTitle(@NotNull Title title); ++ ++ /** ++ * Show the title to the player, overriding any previously displayed title. ++ * ++ *

    This method doesn't override previous titles, but changes their values.

    ++ * ++ * @param title the title to send ++ * @throws NullPointerException if title is null ++ * @deprecated use {@link #showTitle(net.kyori.adventure.title.Title)} ++ */ ++ @Deprecated ++ void updateTitle(@NotNull Title title); ++ ++ /** ++ * Hide any title that is currently visible to the player ++ * ++ * @deprecated use {@link #clearTitle()} ++ */ ++ @Deprecated ++ public void hideTitle(); + // Paper end + + /** diff --git a/patches/api-unmapped/0018-Add-exception-reporting-event.patch b/patches/api-unmapped/0018-Add-exception-reporting-event.patch new file mode 100644 index 0000000000..b295b466fc --- /dev/null +++ b/patches/api-unmapped/0018-Add-exception-reporting-event.patch @@ -0,0 +1,604 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 29 Feb 2016 20:24:35 -0600 +Subject: [PATCH] Add exception reporting event + + +diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2f573299a9a817a98372817a1de8bf641aaca956 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java +@@ -0,0 +1,43 @@ ++package com.destroystokyo.paper.event.server; ++ ++import com.google.common.base.Preconditions; ++import org.apache.commons.lang.Validate; ++import org.bukkit.Bukkit; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import com.destroystokyo.paper.exception.ServerException; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called whenever an exception is thrown in a recoverable section of the server. ++ */ ++public class ServerExceptionEvent extends Event { ++ private static final HandlerList handlers = new HandlerList(); ++ @NotNull private ServerException exception; ++ ++ public ServerExceptionEvent(@NotNull ServerException exception) { ++ super(!Bukkit.isPrimaryThread()); ++ this.exception = Preconditions.checkNotNull(exception, "exception"); ++ } ++ ++ /** ++ * Gets the wrapped exception that was thrown. ++ * ++ * @return Exception thrown ++ */ ++ @NotNull ++ public ServerException getException() { ++ return exception; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java b/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6fb39af0479a818f7f1465bcdfe505ab4ff7da1a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java +@@ -0,0 +1,64 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++ ++import static com.google.common.base.Preconditions.checkNotNull; ++ ++/** ++ * Thrown when a command throws an exception ++ */ ++public class ServerCommandException extends ServerException { ++ ++ private final Command command; ++ private final CommandSender commandSender; ++ private final String[] arguments; ++ ++ public ServerCommandException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) { ++ super(message, cause); ++ this.commandSender = checkNotNull(commandSender, "commandSender"); ++ this.arguments = checkNotNull(arguments, "arguments"); ++ this.command = checkNotNull(command, "command"); ++ } ++ ++ public ServerCommandException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) { ++ super(cause); ++ this.commandSender = checkNotNull(commandSender, "commandSender"); ++ this.arguments = checkNotNull(arguments, "arguments"); ++ this.command = checkNotNull(command, "command"); ++ } ++ ++ protected ServerCommandException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) { ++ super(message, cause, enableSuppression, writableStackTrace); ++ this.commandSender = checkNotNull(commandSender, "commandSender"); ++ this.arguments = checkNotNull(arguments, "arguments"); ++ this.command = checkNotNull(command, "command"); ++ } ++ ++ /** ++ * Gets the command which threw the exception ++ * ++ * @return exception throwing command ++ */ ++ public Command getCommand() { ++ return command; ++ } ++ ++ /** ++ * Gets the command sender which executed the command request ++ * ++ * @return command sender of exception thrown command request ++ */ ++ public CommandSender getCommandSender() { ++ return commandSender; ++ } ++ ++ /** ++ * Gets the arguments which threw the exception for the command ++ * ++ * @return arguments of exception thrown command request ++ */ ++ public String[] getArguments() { ++ return arguments; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java b/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..410b24139535cd5d8439ad581c43c61b5757fbf6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java +@@ -0,0 +1,52 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.event.Event; ++import org.bukkit.event.Listener; ++import org.bukkit.plugin.Plugin; ++ ++import static com.google.common.base.Preconditions.*; ++ ++/** ++ * Exception thrown when a server event listener throws an exception ++ */ ++public class ServerEventException extends ServerPluginException { ++ ++ private final Listener listener; ++ private final Event event; ++ ++ public ServerEventException(String message, Throwable cause, Plugin responsiblePlugin, Listener listener, Event event) { ++ super(message, cause, responsiblePlugin); ++ this.listener = checkNotNull(listener, "listener"); ++ this.event = checkNotNull(event, "event"); ++ } ++ ++ public ServerEventException(Throwable cause, Plugin responsiblePlugin, Listener listener, Event event) { ++ super(cause, responsiblePlugin); ++ this.listener = checkNotNull(listener, "listener"); ++ this.event = checkNotNull(event, "event"); ++ } ++ ++ protected ServerEventException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, Listener listener, Event event) { ++ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin); ++ this.listener = checkNotNull(listener, "listener"); ++ this.event = checkNotNull(event, "event"); ++ } ++ ++ /** ++ * Gets the listener which threw the exception ++ * ++ * @return event listener ++ */ ++ public Listener getListener() { ++ return listener; ++ } ++ ++ /** ++ * Gets the event which caused the exception ++ * ++ * @return event ++ */ ++ public Event getEvent() { ++ return event; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerException.java b/src/main/java/com/destroystokyo/paper/exception/ServerException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c06ea3942447d4824b83ff839cb449fb818dede1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerException.java +@@ -0,0 +1,23 @@ ++package com.destroystokyo.paper.exception; ++ ++/** ++ * Wrapper exception for all exceptions that are thrown by the server. ++ */ ++public class ServerException extends Exception { ++ ++ public ServerException(String message) { ++ super(message); ++ } ++ ++ public ServerException(String message, Throwable cause) { ++ super(message, cause); ++ } ++ ++ public ServerException(Throwable cause) { ++ super(cause); ++ } ++ ++ protected ServerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { ++ super(message, cause, enableSuppression, writableStackTrace); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java b/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e762ed0dbad51625e65fef2e1898679108459a36 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java +@@ -0,0 +1,35 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.Bukkit; ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++ ++/** ++ * Thrown when the internal server throws a recoverable exception. ++ */ ++public class ServerInternalException extends ServerException { ++ ++ public ServerInternalException(String message) { ++ super(message); ++ } ++ ++ public ServerInternalException(String message, Throwable cause) { ++ super(message, cause); ++ } ++ ++ public ServerInternalException(Throwable cause) { ++ super(cause); ++ } ++ ++ protected ServerInternalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { ++ super(message, cause, enableSuppression, writableStackTrace); ++ } ++ ++ public static void reportInternalException(Throwable cause) { ++ try { ++ Bukkit.getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(cause))); ++ ; ++ } catch (Throwable t) { ++ t.printStackTrace(); // Don't want to rethrow! ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f016ba3b1b62e554a9bacbb9635f2dbe441b3c4e +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java +@@ -0,0 +1,20 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.plugin.Plugin; ++ ++/** ++ * Thrown whenever there is an exception with any enabling or disabling of plugins. ++ */ ++public class ServerPluginEnableDisableException extends ServerPluginException { ++ public ServerPluginEnableDisableException(String message, Throwable cause, Plugin responsiblePlugin) { ++ super(message, cause, responsiblePlugin); ++ } ++ ++ public ServerPluginEnableDisableException(Throwable cause, Plugin responsiblePlugin) { ++ super(cause, responsiblePlugin); ++ } ++ ++ protected ServerPluginEnableDisableException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) { ++ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin); ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6defac287d0214fdf99418d979144050cc1e53bc +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java +@@ -0,0 +1,38 @@ ++package com.destroystokyo.paper.exception; ++ ++import com.google.common.base.Preconditions; ++import org.apache.commons.lang.Validate; ++import org.bukkit.plugin.Plugin; ++ ++import static com.google.common.base.Preconditions.*; ++ ++/** ++ * Wrapper exception for all cases to which a plugin can be immediately blamed for ++ */ ++public class ServerPluginException extends ServerException { ++ public ServerPluginException(String message, Throwable cause, Plugin responsiblePlugin) { ++ super(message, cause); ++ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin"); ++ } ++ ++ public ServerPluginException(Throwable cause, Plugin responsiblePlugin) { ++ super(cause); ++ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin"); ++ } ++ ++ protected ServerPluginException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) { ++ super(message, cause, enableSuppression, writableStackTrace); ++ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin"); ++ } ++ ++ private final Plugin responsiblePlugin; ++ ++ /** ++ * Gets the plugin which is directly responsible for the exception being thrown ++ * ++ * @return plugin which is responsible for the exception throw ++ */ ++ public Plugin getResponsiblePlugin() { ++ return responsiblePlugin; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..89e132525cfae0ce979e37b3e2793df781e47227 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java +@@ -0,0 +1,64 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.plugin.Plugin; ++ ++import static com.google.common.base.Preconditions.*; ++ ++/** ++ * Thrown when an incoming plugin message channel throws an exception ++ */ ++public class ServerPluginMessageException extends ServerPluginException { ++ ++ private final Player player; ++ private final String channel; ++ private final byte[] data; ++ ++ public ServerPluginMessageException(String message, Throwable cause, Plugin responsiblePlugin, Player player, String channel, byte[] data) { ++ super(message, cause, responsiblePlugin); ++ this.player = checkNotNull(player, "player"); ++ this.channel = checkNotNull(channel, "channel"); ++ this.data = checkNotNull(data, "data"); ++ } ++ ++ public ServerPluginMessageException(Throwable cause, Plugin responsiblePlugin, Player player, String channel, byte[] data) { ++ super(cause, responsiblePlugin); ++ this.player = checkNotNull(player, "player"); ++ this.channel = checkNotNull(channel, "channel"); ++ this.data = checkNotNull(data, "data"); ++ } ++ ++ protected ServerPluginMessageException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, Player player, String channel, byte[] data) { ++ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin); ++ this.player = checkNotNull(player, "player"); ++ this.channel = checkNotNull(channel, "channel"); ++ this.data = checkNotNull(data, "data"); ++ } ++ ++ /** ++ * Gets the channel to which the error occurred from recieving data from ++ * ++ * @return exception channel ++ */ ++ public String getChannel() { ++ return channel; ++ } ++ ++ /** ++ * Gets the data to which the error occurred from ++ * ++ * @return exception data ++ */ ++ public byte[] getData() { ++ return data; ++ } ++ ++ /** ++ * Gets the player which the plugin message causing the exception originated from ++ * ++ * @return exception player ++ */ ++ public Player getPlayer() { ++ return player; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java b/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2d0b2d4a9b3e5bdeec0e4ea7ab69858d86aa3715 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java +@@ -0,0 +1,37 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.scheduler.BukkitTask; ++ ++import static com.google.common.base.Preconditions.checkNotNull; ++ ++/** ++ * Thrown when a plugin's scheduler fails with an exception ++ */ ++public class ServerSchedulerException extends ServerPluginException { ++ ++ private final BukkitTask task; ++ ++ public ServerSchedulerException(String message, Throwable cause, BukkitTask task) { ++ super(message, cause, task.getOwner()); ++ this.task = checkNotNull(task, "task"); ++ } ++ ++ public ServerSchedulerException(Throwable cause, BukkitTask task) { ++ super(cause, task.getOwner()); ++ this.task = checkNotNull(task, "task"); ++ } ++ ++ protected ServerSchedulerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, BukkitTask task) { ++ super(message, cause, enableSuppression, writableStackTrace, task.getOwner()); ++ this.task = checkNotNull(task, "task"); ++ } ++ ++ /** ++ * Gets the task which threw the exception ++ * ++ * @return exception throwing task ++ */ ++ public BukkitTask getTask() { ++ return task; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java b/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5582999fe94c7a3dac655044ccc6d078cd9521a1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java +@@ -0,0 +1,22 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++ ++/** ++ * Called when a tab-complete request throws an exception ++ */ ++public class ServerTabCompleteException extends ServerCommandException { ++ ++ public ServerTabCompleteException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) { ++ super(message, cause, command, commandSender, arguments); ++ } ++ ++ public ServerTabCompleteException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) { ++ super(cause, command, commandSender, arguments); ++ } ++ ++ protected ServerTabCompleteException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) { ++ super(message, cause, enableSuppression, writableStackTrace, command, commandSender, arguments); ++ } ++} +diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java +index f020cb04eba27a2e70fc7cf799ebbfb434b9d974..adfc7aae2c0f49bbcdd358e83b04a0cf078a7d52 100644 +--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java ++++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java +@@ -8,6 +8,10 @@ import java.util.HashMap; + import java.util.Iterator; + import java.util.List; + import java.util.Map; ++ ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerCommandException; ++import com.destroystokyo.paper.exception.ServerTabCompleteException; + import org.apache.commons.lang.Validate; + import org.bukkit.Location; + import org.bukkit.Server; +@@ -155,11 +159,14 @@ public class SimpleCommandMap implements CommandMap { + target.execute(sender, sentCommandLabel, Arrays.copyOfRange(args, 1, args.length)); + } // target.timings.stopTiming(); // Spigot // Paper + } catch (CommandException ex) { ++ server.getPluginManager().callEvent(new ServerExceptionEvent(new ServerCommandException(ex, target, sender, args))); // Paper + //target.timings.stopTiming(); // Spigot // Paper + throw ex; + } catch (Throwable ex) { + //target.timings.stopTiming(); // Spigot // Paper +- throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex); ++ String msg = "Unhandled exception executing '" + commandLine + "' in " + target; ++ server.getPluginManager().callEvent(new ServerExceptionEvent(new ServerCommandException(ex, target, sender, args))); // Paper ++ throw new CommandException(msg, ex); + } + + // return true as command was handled +@@ -238,7 +245,9 @@ public class SimpleCommandMap implements CommandMap { + } catch (CommandException ex) { + throw ex; + } catch (Throwable ex) { +- throw new CommandException("Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target, ex); ++ String msg = "Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target; ++ server.getPluginManager().callEvent(new ServerExceptionEvent(new ServerTabCompleteException(msg, ex, target, sender, args))); // Paper ++ throw new CommandException(msg, ex); + } + } + +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index 745eaa8f2f2ff83536301db8ca47a8af30df7a73..d0fec44d2546290091649879450761ce08514fcb 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -23,6 +23,10 @@ import java.util.WeakHashMap; + import java.util.logging.Level; + import java.util.regex.Matcher; + import java.util.regex.Pattern; ++ ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerEventException; ++import com.destroystokyo.paper.exception.ServerPluginEnableDisableException; + import org.apache.commons.lang.Validate; + import org.bukkit.Server; + import org.bukkit.World; +@@ -478,7 +482,8 @@ public final class SimplePluginManager implements PluginManager { + try { + plugin.getPluginLoader().enablePlugin(plugin); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ handlePluginException("Error occurred (in the plugin loader) while enabling " ++ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); + } + + HandlerList.bakeAll(); +@@ -499,32 +504,37 @@ public final class SimplePluginManager implements PluginManager { + try { + plugin.getPluginLoader().disablePlugin(plugin); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ handlePluginException("Error occurred (in the plugin loader) while disabling " ++ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper + } + + try { + server.getScheduler().cancelTasks(plugin); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while cancelling tasks for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ handlePluginException("Error occurred (in the plugin loader) while cancelling tasks for " ++ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper + } + + try { + server.getServicesManager().unregisterAll(plugin); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering services for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ handlePluginException("Error occurred (in the plugin loader) while unregistering services for " ++ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper + } + + try { + HandlerList.unregisterAll(plugin); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering events for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ handlePluginException("Error occurred (in the plugin loader) while unregistering events for " ++ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper + } + + try { + server.getMessenger().unregisterIncomingPluginChannel(plugin); + server.getMessenger().unregisterOutgoingPluginChannel(plugin); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering plugin channels for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ handlePluginException("Error occurred (in the plugin loader) while unregistering plugin channels for " ++ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper + } + + try { +@@ -537,6 +547,13 @@ public final class SimplePluginManager implements PluginManager { + } + } + ++ // Paper start ++ private void handlePluginException(String msg, Throwable ex, Plugin plugin) { ++ server.getLogger().log(Level.SEVERE, msg, ex); ++ callEvent(new ServerExceptionEvent(new ServerPluginEnableDisableException(msg, ex, plugin))); ++ } ++ // Paper end ++ + @Override + public void clearPlugins() { + synchronized (this) { +@@ -600,7 +617,13 @@ public final class SimplePluginManager implements PluginManager { + )); + } + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(), ex); ++ // Paper start - error reporting ++ String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(); ++ server.getLogger().log(Level.SEVERE, msg, ex); ++ if (!(event instanceof ServerExceptionEvent)) { // We don't want to cause an endless event loop ++ callEvent(new ServerExceptionEvent(new ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event))); ++ } ++ // Paper end + } + } + } diff --git a/patches/api-unmapped/0019-Fix-ServerListPingEvent-flagging-as-Async.patch b/patches/api-unmapped/0019-Fix-ServerListPingEvent-flagging-as-Async.patch new file mode 100644 index 0000000000..87d3369578 --- /dev/null +++ b/patches/api-unmapped/0019-Fix-ServerListPingEvent-flagging-as-Async.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 29 Feb 2016 20:26:39 -0600 +Subject: [PATCH] Fix ServerListPingEvent flagging as Async + +This event can sometimes fire Async, set the proper boolean + +diff --git a/src/main/java/org/bukkit/event/server/ServerEvent.java b/src/main/java/org/bukkit/event/server/ServerEvent.java +index 46b119017a1e3dfcd9ae5fb91b4fe8c20b0d6b86..05167fb34e4c42edc67af6e6700a2a3cc0f92769 100644 +--- a/src/main/java/org/bukkit/event/server/ServerEvent.java ++++ b/src/main/java/org/bukkit/event/server/ServerEvent.java +@@ -1,5 +1,6 @@ + package org.bukkit.event.server; + ++import org.bukkit.Bukkit; + import org.bukkit.event.Event; + + /** +@@ -8,7 +9,7 @@ import org.bukkit.event.Event; + public abstract class ServerEvent extends Event { + + public ServerEvent() { +- super(); ++ super(!Bukkit.isPrimaryThread()); // Paper + } + + public ServerEvent(boolean isAsync) { diff --git a/patches/api-unmapped/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch b/patches/api-unmapped/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch new file mode 100644 index 0000000000..b8376a9108 --- /dev/null +++ b/patches/api-unmapped/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Tue, 8 Mar 2016 13:05:59 -0800 +Subject: [PATCH] Add BaseComponent sendMessage methods to CommandSender + + +diff --git a/src/main/java/org/bukkit/command/CommandSender.java b/src/main/java/org/bukkit/command/CommandSender.java +index c88418c7aa19b4fecdfa9af3d18ff202a5dc5763..fb0e608fa92dae99b9eee8fc1cbdf4b91a33e620 100644 +--- a/src/main/java/org/bukkit/command/CommandSender.java ++++ b/src/main/java/org/bukkit/command/CommandSender.java +@@ -1,6 +1,9 @@ + package org.bukkit.command; + + import java.util.UUID; ++import net.kyori.adventure.audience.MessageType; ++import net.kyori.adventure.identity.Identity; ++import net.kyori.adventure.text.Component; + import org.bukkit.Server; + import org.bukkit.permissions.Permissible; + import org.jetbrains.annotations.NotNull; +@@ -117,5 +120,33 @@ public interface CommandSender extends net.kyori.adventure.audience.Audience, Pe + default void sendMessage(final @NotNull net.kyori.adventure.identity.Identity identity, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { + this.sendMessage(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(message)); + } ++ ++ /** ++ * Sends the component to the sender ++ * ++ *

    If this sender does not support sending full components then ++ * the component will be sent as legacy text.

    ++ * ++ * @param component the component to send ++ * @deprecated use {@link #sendMessage(Identity, Component, MessageType)} instead ++ */ ++ @Deprecated ++ default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { ++ this.sendMessage(component.toLegacyText()); ++ } ++ ++ /** ++ * Sends an array of components as a single message to the sender ++ * ++ *

    If this sender does not support sending full components then ++ * the components will be sent as legacy text.

    ++ * ++ * @param components the components to send ++ * @deprecated use {@link #sendMessage(Identity, Component, MessageType)} instead ++ */ ++ @Deprecated ++ default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { ++ this.sendMessage(new net.md_5.bungee.api.chat.TextComponent(components).toLegacyText()); ++ } + // Paper end + } diff --git a/patches/api-unmapped/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/api-unmapped/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch new file mode 100644 index 0000000000..515b56ff03 --- /dev/null +++ b/patches/api-unmapped/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: mrapple +Date: Sun, 25 Nov 2012 13:47:27 -0600 +Subject: [PATCH] Add methods for working with arrows stuck in living entities + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 24c858182f25496cc7254f7cf9e996b3bea1f9ec..45e9f585c3e522ecf94a6bc42cdc190e1a191a5c 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -605,4 +605,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + * @return Whether the entity is invisible + */ + public boolean isInvisible(); ++ ++ // Paper start ++ /** ++ * Get the number of arrows stuck in this entity ++ * @return Number of arrows stuck ++ */ ++ int getArrowsStuck(); ++ ++ /** ++ * Set the number of arrows stuck in this entity ++ * ++ * @param arrows Number of arrows to stick in this entity ++ */ ++ void setArrowsStuck(int arrows); ++ // Paper end + } diff --git a/patches/api-unmapped/0022-Complete-resource-pack-API.patch b/patches/api-unmapped/0022-Complete-resource-pack-API.patch new file mode 100644 index 0000000000..ff78c17d14 --- /dev/null +++ b/patches/api-unmapped/0022-Complete-resource-pack-API.patch @@ -0,0 +1,118 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 4 Apr 2015 22:59:54 -0400 +Subject: [PATCH] Complete resource pack API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 769ad98fd7a6a866b320e1ccffd7962228d564cf..ddbe5734ac0f905b0c388e30f17a281530b82262 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1124,7 +1124,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @throws IllegalArgumentException Thrown if the URL is null. + * @throws IllegalArgumentException Thrown if the URL is too long. The + * length restriction is an implementation specific arbitrary value. ++ * @deprecated use {@link #setResourcePack(String, String)} + */ ++ @Deprecated // Paper + public void setResourcePack(@NotNull String url); + + /** +@@ -1601,6 +1603,60 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { + return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.displayName()))); + } ++ ++ /** ++ * Request that the player's client download and switch resource packs. ++ *

    ++ * The player's client will download the new resource pack asynchronously ++ * in the background, and will automatically switch to it once the ++ * download is complete. If the client has downloaded and cached the same ++ * resource pack in the past, it will perform a quick timestamp check ++ * over the network to determine if the resource pack has changed and ++ * needs to be downloaded again. When this request is sent for the very ++ * first time from a given server, the client will first display a ++ * confirmation GUI to the player before proceeding with the download. ++ *

    ++ * Notes: ++ *

      ++ *
    • Players can disable server resources on their client, in which ++ * case this method will have no affect on them. ++ *
    • There is no concept of resetting resource packs back to default ++ * within Minecraft, so players will have to relog to do so. ++ *
    ++ * ++ * @param url The URL from which the client will download the resource ++ * pack. The string must contain only US-ASCII characters and should ++ * be encoded as per RFC 1738. ++ * @param hash A 40 character hexadecimal and lowercase SHA-1 digest of ++ * the resource pack file. ++ * @throws IllegalArgumentException Thrown if the URL is null. ++ * @throws IllegalArgumentException Thrown if the URL is too long. The ++ * length restriction is an implementation specific arbitrary value. ++ */ ++ void setResourcePack(@NotNull String url, @NotNull String hash); ++ ++ /** ++ * @return the most recent resource pack status received from the player, ++ * or null if no status has ever been received from this player. ++ */ ++ @Nullable ++ org.bukkit.event.player.PlayerResourcePackStatusEvent.Status getResourcePackStatus(); ++ ++ /** ++ * @return the most recent resource pack hash received from the player, ++ * or null if no hash has ever been received from this player. ++ * ++ * @deprecated This is no longer sent from the client and will always be null ++ */ ++ @Nullable ++ @Deprecated ++ String getResourcePackHash(); ++ ++ /** ++ * @return true if the last resource pack status received from this player ++ * was {@link org.bukkit.event.player.PlayerResourcePackStatusEvent.Status#SUCCESSFULLY_LOADED} ++ */ ++ boolean hasResourcePack(); + // Paper end + + // Spigot start +diff --git a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java +index b98195650d49d78ec35970ca0376b6289b861e4b..4c2102a11c3d682d98f0db4ccafa35231e66bcdd 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java +@@ -11,13 +11,32 @@ import org.jetbrains.annotations.NotNull; + public class PlayerResourcePackStatusEvent extends PlayerEvent { + + private static final HandlerList handlers = new HandlerList(); ++ @Deprecated ++ private final String hash; // Paper + private final Status status; + + public PlayerResourcePackStatusEvent(@NotNull final Player who, @NotNull Status resourcePackStatus) { + super(who); ++ this.hash = null; // Paper + this.status = resourcePackStatus; + } + ++ @Deprecated // Paper ++ public PlayerResourcePackStatusEvent(final Player who, Status resourcePackStatus, String hash) { ++ super(who); ++ this.hash = hash; // Paper ++ this.status = resourcePackStatus; ++ } ++ ++ @Deprecated ++ /** ++ * @deprecated Hash does not seem to ever be set ++ */ ++ public String getHash() { ++ return this.hash; ++ } ++ // Paper end ++ + /** + * Gets the status of this pack. + * diff --git a/patches/api-unmapped/0023-Use-ASM-for-event-executors.patch b/patches/api-unmapped/0023-Use-ASM-for-event-executors.patch new file mode 100644 index 0000000000..bcbe8ec071 --- /dev/null +++ b/patches/api-unmapped/0023-Use-ASM-for-event-executors.patch @@ -0,0 +1,398 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Thu, 3 Mar 2016 13:20:33 -0700 +Subject: [PATCH] Use ASM for event executors. + +Uses method handles for private or static methods. + +diff --git a/pom.xml b/pom.xml +index 1ced7a212684cee8faf07fa9a083adcd47be7fcb..7ec7e6047193a6b390d24f6d2722e35d1d36830d 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -163,6 +163,17 @@ + 9.1 + test +
    ++ ++ ++ org.ow2.asm ++ asm ++ 9.0 ++ ++ ++ org.ow2.asm ++ asm-commons ++ 9.0 ++ +
    + + +diff --git a/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5b28e9b1daba7834af67dbc193dd656bedd9a994 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java +@@ -0,0 +1,42 @@ ++package com.destroystokyo.paper.event.executor; ++ ++import java.lang.invoke.MethodHandle; ++import java.lang.invoke.MethodHandles; ++import java.lang.reflect.Method; ++ ++import com.destroystokyo.paper.util.SneakyThrow; ++import org.bukkit.event.Event; ++import org.bukkit.event.EventException; ++import org.bukkit.event.Listener; ++import org.bukkit.plugin.EventExecutor; ++import org.jetbrains.annotations.NotNull; ++ ++public class MethodHandleEventExecutor implements EventExecutor { ++ private final Class eventClass; ++ private final MethodHandle handle; ++ ++ public MethodHandleEventExecutor(@NotNull Class eventClass, @NotNull MethodHandle handle) { ++ this.eventClass = eventClass; ++ this.handle = handle; ++ } ++ ++ public MethodHandleEventExecutor(@NotNull Class eventClass, @NotNull Method m) { ++ this.eventClass = eventClass; ++ try { ++ m.setAccessible(true); ++ this.handle = MethodHandles.lookup().unreflect(m); ++ } catch (IllegalAccessException e) { ++ throw new AssertionError("Unable to set accessible", e); ++ } ++ } ++ ++ @Override ++ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { ++ if (!eventClass.isInstance(event)) return; ++ try { ++ handle.invoke(listener, event); ++ } catch (Throwable t) { ++ SneakyThrow.sneaky(t); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c83672427324bd068ed52916f700b68446a226f6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java +@@ -0,0 +1,43 @@ ++package com.destroystokyo.paper.event.executor; ++ ++import java.lang.invoke.MethodHandle; ++import java.lang.invoke.MethodHandles; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++ ++import com.destroystokyo.paper.util.SneakyThrow; ++import com.google.common.base.Preconditions; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.event.Event; ++import org.bukkit.event.EventException; ++import org.bukkit.event.Listener; ++import org.bukkit.plugin.EventExecutor; ++import org.jetbrains.annotations.NotNull; ++ ++public class StaticMethodHandleEventExecutor implements EventExecutor { ++ private final Class eventClass; ++ private final MethodHandle handle; ++ ++ public StaticMethodHandleEventExecutor(@NotNull Class eventClass, @NotNull Method m) { ++ Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m); ++ Preconditions.checkArgument(eventClass != null, "eventClass is null"); ++ this.eventClass = eventClass; ++ try { ++ m.setAccessible(true); ++ this.handle = MethodHandles.lookup().unreflect(m); ++ } catch (IllegalAccessException e) { ++ throw new AssertionError("Unable to set accessible", e); ++ } ++ } ++ ++ @Override ++ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { ++ if (!eventClass.isInstance(event)) return; ++ try { ++ handle.invoke(event); ++ } catch (Throwable throwable) { ++ SneakyThrow.sneaky(throwable); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b6e7d8ee8d903ebf975d60bec0e08603d9a49fdb +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java +@@ -0,0 +1,47 @@ ++package com.destroystokyo.paper.event.executor.asm; ++ ++import java.lang.reflect.Method; ++import java.util.concurrent.atomic.AtomicInteger; ++ ++import org.bukkit.plugin.EventExecutor; ++import org.jetbrains.annotations.NotNull; ++import org.objectweb.asm.ClassWriter; ++import org.objectweb.asm.Type; ++import org.objectweb.asm.commons.GeneratorAdapter; ++ ++import static org.objectweb.asm.Opcodes.*; ++ ++public class ASMEventExecutorGenerator { ++ @NotNull ++ public static byte[] generateEventExecutor(@NotNull Method m, @NotNull String name) { ++ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); ++ writer.visit(V1_8, ACC_PUBLIC, name.replace('.', '/'), null, Type.getInternalName(Object.class), new String[] {Type.getInternalName(EventExecutor.class)}); ++ // Generate constructor ++ GeneratorAdapter methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "", "()V", null, null), ACC_PUBLIC, "", "()V"); ++ methodGenerator.loadThis(); ++ methodGenerator.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "", "()V", false); // Invoke the super class (Object) constructor ++ methodGenerator.returnValue(); ++ methodGenerator.endMethod(); ++ // Generate the execute method ++ methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "execute", "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Event;)V", null, null), ACC_PUBLIC, "execute", "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Listener;)V");; ++ methodGenerator.loadArg(0); ++ methodGenerator.checkCast(Type.getType(m.getDeclaringClass())); ++ methodGenerator.loadArg(1); ++ methodGenerator.checkCast(Type.getType(m.getParameterTypes()[0])); ++ methodGenerator.visitMethodInsn(m.getDeclaringClass().isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, Type.getInternalName(m.getDeclaringClass()), m.getName(), Type.getMethodDescriptor(m), m.getDeclaringClass().isInterface()); ++ if (m.getReturnType() != void.class) { ++ methodGenerator.pop(); ++ } ++ methodGenerator.returnValue(); ++ methodGenerator.endMethod(); ++ writer.visitEnd(); ++ return writer.toByteArray(); ++ } ++ ++ public static AtomicInteger NEXT_ID = new AtomicInteger(1); ++ @NotNull ++ public static String generateName() { ++ int id = NEXT_ID.getAndIncrement(); ++ return "com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor" + id; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f79685b48bb581277a6891927988b6f7a4389dc4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java +@@ -0,0 +1,34 @@ ++package com.destroystokyo.paper.event.executor.asm; ++ ++import org.jetbrains.annotations.NotNull; ++ ++public interface ClassDefiner { ++ ++ /** ++ * Returns if the defined classes can bypass access checks ++ * ++ * @return if classes bypass access checks ++ */ ++ public default boolean isBypassAccessChecks() { ++ return false; ++ } ++ ++ /** ++ * Define a class ++ * ++ * @param parentLoader the parent classloader ++ * @param name the name of the class ++ * @param data the class data to load ++ * @return the defined class ++ * @throws ClassFormatError if the class data is invalid ++ * @throws NullPointerException if any of the arguments are null ++ */ ++ @NotNull ++ public Class defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data); ++ ++ @NotNull ++ public static ClassDefiner getInstance() { ++ return SafeClassDefiner.INSTANCE; ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ac99477e9f2c08041aeff31abc1d1edee58d0a67 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java +@@ -0,0 +1,66 @@ ++package com.destroystokyo.paper.event.executor.asm; ++ ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.ConcurrentMap; ++ ++import com.google.common.base.Preconditions; ++ ++import com.google.common.collect.MapMaker; ++import org.jetbrains.annotations.NotNull; ++import org.objectweb.asm.Type; ++ ++public class SafeClassDefiner implements ClassDefiner { ++ /* default */ static final SafeClassDefiner INSTANCE = new SafeClassDefiner(); ++ ++ private SafeClassDefiner() {} ++ ++ private final ConcurrentMap loaders = new MapMaker().weakKeys().makeMap(); ++ ++ @NotNull ++ @Override ++ public Class defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data) { ++ GeneratedClassLoader loader = loaders.computeIfAbsent(parentLoader, GeneratedClassLoader::new); ++ synchronized (loader.getClassLoadingLock(name)) { ++ Preconditions.checkState(!loader.hasClass(name), "%s already defined", name); ++ Class c = loader.define(name, data); ++ assert c.getName().equals(name); ++ return c; ++ } ++ } ++ ++ private static class GeneratedClassLoader extends ClassLoader { ++ static { ++ ClassLoader.registerAsParallelCapable(); ++ } ++ ++ protected GeneratedClassLoader(@NotNull ClassLoader parent) { ++ super(parent); ++ } ++ ++ private Class define(@NotNull String name, byte[] data) { ++ synchronized (getClassLoadingLock(name)) { ++ assert !hasClass(name); ++ Class c = defineClass(name, data, 0, data.length); ++ resolveClass(c); ++ return c; ++ } ++ } ++ ++ @Override ++ @NotNull ++ public Object getClassLoadingLock(@NotNull String name) { ++ return super.getClassLoadingLock(name); ++ } ++ ++ public boolean hasClass(@NotNull String name) { ++ synchronized (getClassLoadingLock(name)) { ++ try { ++ Class.forName(name); ++ return true; ++ } catch (ClassNotFoundException e) { ++ return false; ++ } ++ } ++ } ++ } ++} +diff --git a/src/main/java/org/bukkit/plugin/EventExecutor.java b/src/main/java/org/bukkit/plugin/EventExecutor.java +index a850f0780de05463fc0d3f9e15ff7f19d88b2aed..9026e108ccd3a88aee1267ee275137befa646455 100644 +--- a/src/main/java/org/bukkit/plugin/EventExecutor.java ++++ b/src/main/java/org/bukkit/plugin/EventExecutor.java +@@ -5,9 +5,75 @@ import org.bukkit.event.EventException; + import org.bukkit.event.Listener; + import org.jetbrains.annotations.NotNull; + ++// Paper start ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.ConcurrentMap; ++import java.util.function.Function; ++ ++import com.destroystokyo.paper.event.executor.MethodHandleEventExecutor; ++import com.destroystokyo.paper.event.executor.StaticMethodHandleEventExecutor; ++import com.destroystokyo.paper.event.executor.asm.ASMEventExecutorGenerator; ++import com.destroystokyo.paper.event.executor.asm.ClassDefiner; ++import com.google.common.base.Preconditions; ++// Paper end ++ + /** + * Interface which defines the class for event call backs to plugins + */ + public interface EventExecutor { + public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException; ++ ++ // Paper start ++ ConcurrentMap> eventExecutorMap = new ConcurrentHashMap>() { ++ @NotNull ++ @Override ++ public Class computeIfAbsent(@NotNull Method key, @NotNull Function> mappingFunction) { ++ Class executorClass = get(key); ++ if (executorClass != null) ++ return executorClass; ++ ++ //noinspection SynchronizationOnLocalVariableOrMethodParameter ++ synchronized (key) { ++ executorClass = get(key); ++ if (executorClass != null) ++ return executorClass; ++ ++ return super.computeIfAbsent(key, mappingFunction); ++ } ++ } ++ }; ++ ++ @NotNull ++ public static EventExecutor create(@NotNull Method m, @NotNull Class eventClass) { ++ Preconditions.checkNotNull(m, "Null method"); ++ Preconditions.checkArgument(m.getParameterCount() != 0, "Incorrect number of arguments %s", m.getParameterCount()); ++ Preconditions.checkArgument(m.getParameterTypes()[0] == eventClass, "First parameter %s doesn't match event class %s", m.getParameterTypes()[0], eventClass); ++ ClassDefiner definer = ClassDefiner.getInstance(); ++ if (Modifier.isStatic(m.getModifiers())) { ++ return new StaticMethodHandleEventExecutor(eventClass, m); ++ } else if (definer.isBypassAccessChecks() || Modifier.isPublic(m.getDeclaringClass().getModifiers()) && Modifier.isPublic(m.getModifiers())) { ++ // get the existing generated EventExecutor class for the Method or generate one ++ Class executorClass = eventExecutorMap.computeIfAbsent(m, (__) -> { ++ String name = ASMEventExecutorGenerator.generateName(); ++ byte[] classData = ASMEventExecutorGenerator.generateEventExecutor(m, name); ++ return definer.defineClass(m.getDeclaringClass().getClassLoader(), name, classData).asSubclass(EventExecutor.class); ++ }); ++ ++ try { ++ EventExecutor asmExecutor = executorClass.newInstance(); ++ // Define a wrapper to conform to bukkit stupidity (passing in events that don't match and wrapper exception) ++ return (listener, event) -> { ++ if (!eventClass.isInstance(event)) return; ++ asmExecutor.execute(listener, event); ++ }; ++ } catch (InstantiationException | IllegalAccessException e) { ++ throw new AssertionError("Unable to initialize generated event executor", e); ++ } ++ } else { ++ return new MethodHandleEventExecutor(eventClass, m); ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index 2e306c7b984a02e12a74fac14589bf29ab6488bf..79ac529017aac059d13fe342f279e9c8faeba599 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -291,21 +291,7 @@ public final class JavaPluginLoader implements PluginLoader { + } + } + +- EventExecutor executor = new co.aikar.timings.TimedEventExecutor(new EventExecutor() { // Paper +- @Override +- public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { // Paper +- try { +- if (!eventClass.isAssignableFrom(event.getClass())) { +- return; +- } +- method.invoke(listener, event); +- } catch (InvocationTargetException ex) { +- throw new EventException(ex.getCause()); +- } catch (Throwable t) { +- throw new EventException(t); +- } +- } +- }, plugin, method, eventClass); // Paper ++ EventExecutor executor = new co.aikar.timings.TimedEventExecutor(EventExecutor.create(method, eventClass), plugin, method, eventClass); // Paper // Paper (Yes.) - Use factory method `EventExecutor.create()` + if (false) { // Spigot - RL handles useTimings check now + eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); + } else { diff --git a/patches/api-unmapped/0024-Add-a-call-helper-to-Event.patch b/patches/api-unmapped/0024-Add-a-call-helper-to-Event.patch new file mode 100644 index 0000000000..4b287bfa56 --- /dev/null +++ b/patches/api-unmapped/0024-Add-a-call-helper-to-Event.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 19 May 2013 20:36:58 -0400 +Subject: [PATCH] Add a call helper to Event + +Reduces diff in Server patches + +diff --git a/src/main/java/org/bukkit/event/Event.java b/src/main/java/org/bukkit/event/Event.java +index 18d0636b749913bfdcea8eebc7d0840d192fb071..8ec56cd6b8e0f5c5dd8c7c88b4671e18dcf109d0 100644 +--- a/src/main/java/org/bukkit/event/Event.java ++++ b/src/main/java/org/bukkit/event/Event.java +@@ -35,6 +35,22 @@ public abstract class Event { + this.async = isAsync; + } + ++ // Paper start ++ /** ++ * Calls the event and tests if cancelled. ++ * ++ * @return false if event was cancelled, if cancellable. otherwise true. ++ */ ++ public boolean callEvent() { ++ org.bukkit.Bukkit.getPluginManager().callEvent(this); ++ if (this instanceof Cancellable) { ++ return !((Cancellable) this).isCancelled(); ++ } else { ++ return true; ++ } ++ } ++ // Paper end ++ + /** + * Convenience method for providing a user-friendly identifier. By + * default, it is the event's class's {@linkplain Class#getSimpleName() diff --git a/patches/api-unmapped/0025-Add-sender-name-to-commands.yml-replacement.patch b/patches/api-unmapped/0025-Add-sender-name-to-commands.yml-replacement.patch new file mode 100644 index 0000000000..7122fed4a2 --- /dev/null +++ b/patches/api-unmapped/0025-Add-sender-name-to-commands.yml-replacement.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 22 Jul 2015 18:50:41 -0400 +Subject: [PATCH] Add sender name to commands.yml replacement + +This allows you to use $sender in commands.yml definitions to make +commands that auto target self. + +diff --git a/src/main/java/org/bukkit/command/FormattedCommandAlias.java b/src/main/java/org/bukkit/command/FormattedCommandAlias.java +index a6ad94ef98a1df1d2842635d850bc990b0137849..9d4f553c04784cca63901a56a7aea62a5cae1d72 100644 +--- a/src/main/java/org/bukkit/command/FormattedCommandAlias.java ++++ b/src/main/java/org/bukkit/command/FormattedCommandAlias.java +@@ -1,6 +1,9 @@ + package org.bukkit.command; + + import java.util.ArrayList; ++import java.util.regex.Matcher; // Paper ++import java.util.regex.Pattern; // Paper ++ + import org.bukkit.Bukkit; + import org.jetbrains.annotations.NotNull; + +@@ -19,7 +22,7 @@ public class FormattedCommandAlias extends Command { + ArrayList commands = new ArrayList(); + for (String formatString : formatStrings) { + try { +- commands.add(buildCommand(formatString, args)); ++ commands.add(buildCommand(sender, formatString, args)); // Paper + } catch (Throwable throwable) { + if (throwable instanceof IllegalArgumentException) { + sender.sendMessage(throwable.getMessage()); +@@ -37,7 +40,10 @@ public class FormattedCommandAlias extends Command { + return result; + } + +- private String buildCommand(@NotNull String formatString, @NotNull String[] args) { ++ private String buildCommand(@NotNull CommandSender sender, @NotNull String formatString, @NotNull String[] args) { // Paper ++ if (formatString.contains("$sender")) { // Paper ++ formatString = formatString.replaceAll(Pattern.quote("$sender"), Matcher.quoteReplacement(sender.getName())); // Paper ++ } // Paper + int index = formatString.indexOf('$'); + while (index != -1) { + int start = index; diff --git a/patches/api-unmapped/0026-Add-command-to-reload-permissions.yml-and-require-co.patch b/patches/api-unmapped/0026-Add-command-to-reload-permissions.yml-and-require-co.patch new file mode 100644 index 0000000000..d7a1bb7514 --- /dev/null +++ b/patches/api-unmapped/0026-Add-command-to-reload-permissions.yml-and-require-co.patch @@ -0,0 +1,104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William +Date: Fri, 18 Mar 2016 03:28:07 -0400 +Subject: [PATCH] Add command to reload permissions.yml and require confirm to + reload + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 8646fc0987a8833996c5d977c36fe0d01bf72992..72375883b07ede041a7ea5f7b6785f71aef702c0 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1752,6 +1752,13 @@ public final class Bukkit { + public static org.bukkit.command.CommandMap getCommandMap() { + return server.getCommandMap(); + } ++ ++ /** ++ * Reload the Permissions in permissions.yml ++ */ ++ public static void reloadPermissions() { ++ server.reloadPermissions(); ++ } + // Paper end + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 599347ef656acad9a40be15fc5030e5d0f1630df..a2940eafa61814aae7f766262309495e991533d6 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1549,4 +1549,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @NotNull + Spigot spigot(); + // Spigot end ++ ++ void reloadPermissions(); // Paper + } +diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +index 50cc311be7904cc8fc6070a21c8e4de3a489fd20..c62da4131b17e66892678e8b618fb9ba3de93b56 100644 +--- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +@@ -13,15 +13,35 @@ public class ReloadCommand extends BukkitCommand { + public ReloadCommand(@NotNull String name) { + super(name); + this.description = "Reloads the server configuration and plugins"; +- this.usageMessage = "/reload"; ++ this.usageMessage = "/reload [permissions]"; // Paper + this.setPermission("bukkit.command.reload"); + this.setAliases(Arrays.asList("rl")); + } + + @Override +- public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { ++ public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { // Paper + if (!testPermission(sender)) return true; + ++ // Paper start - Reload permissions.yml & require confirm ++ boolean confirmed = System.getProperty("LetMeReload") != null; ++ if (args.length == 1) { ++ if (args[0].equalsIgnoreCase("permissions")) { ++ Bukkit.getServer().reloadPermissions(); ++ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Permissions successfully reloaded."); ++ return true; ++ } else if ("confirm".equalsIgnoreCase(args[0])) { ++ confirmed = true; ++ } else { ++ Command.broadcastCommandMessage(sender, ChatColor.RED + "Usage: " + usageMessage); ++ return true; ++ } ++ } ++ if (!confirmed) { ++ Command.broadcastCommandMessage(sender, ChatColor.RED + "Are you sure you wish to reload your server? Doing so may cause bugs and memory leaks. It is recommended to restart instead of using /reload. To confirm, please type " + ChatColor.YELLOW + "/reload confirm"); ++ return true; ++ } ++ // Paper end ++ + Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues when using some plugins."); + Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); + Bukkit.reload(); +@@ -33,6 +53,6 @@ public class ReloadCommand extends BukkitCommand { + @NotNull + @Override + public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException { +- return Collections.emptyList(); ++ return java.util.Collections.singletonList("permissions"); // Paper + } + } +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index c2c49ee9b5531bc4761d2da54cd707c57fc647bf..2d27dfb859c312d46a14d0356c7c3f227e965a67 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -895,4 +895,13 @@ public final class SimplePluginManager implements PluginManager { + public void useTimings(boolean use) { + co.aikar.timings.Timings.setTimingsEnabled(use); // Paper + } ++ ++ // Paper start ++ public void clearPermissions() { ++ permissions.clear(); ++ defaultPerms.get(true).clear(); ++ defaultPerms.get(false).clear(); ++ } ++ // Paper end ++ + } diff --git a/patches/api-unmapped/0027-Custom-replacement-for-eaten-items.patch b/patches/api-unmapped/0027-Custom-replacement-for-eaten-items.patch new file mode 100644 index 0000000000..94ff9d88e2 --- /dev/null +++ b/patches/api-unmapped/0027-Custom-replacement-for-eaten-items.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sun, 21 Jun 2015 15:05:21 -0400 +Subject: [PATCH] Custom replacement for eaten items + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java b/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java +index c2793f3ef01c1246c130971c17e1c2bf8f551435..373f4b5b5185aa81ff728da89c9cc4e0ccf87889 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java +@@ -22,6 +22,7 @@ public class PlayerItemConsumeEvent extends PlayerEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private boolean isCancelled = false; + private ItemStack item; ++ @Nullable private ItemStack replacement; // Paper + + /** + * @param player the player consuming +@@ -58,6 +59,29 @@ public class PlayerItemConsumeEvent extends PlayerEvent implements Cancellable { + } + } + ++ // Paper start ++ /** ++ * Return the custom item stack that will replace the consumed item, or null if no ++ * custom replacement has been set (which means the default replacement will be used). ++ * ++ * @return The custom item stack that will replace the consumed item or null ++ */ ++ @Nullable ++ public ItemStack getReplacement() { ++ return this.replacement; ++ } ++ ++ /** ++ * Set a custom item stack to replace the consumed item. Pass null to clear any custom ++ * stack that has been set and use the default replacement. ++ * ++ * @param replacement Replacement item to set, null to clear any custom stack and use default ++ */ ++ public void setReplacement(@Nullable ItemStack replacement) { ++ this.replacement = replacement; ++ } ++ // Paper end ++ + @Override + public boolean isCancelled() { + return this.isCancelled; diff --git a/patches/api-unmapped/0028-Entity-AddTo-RemoveFrom-World-Events.patch b/patches/api-unmapped/0028-Entity-AddTo-RemoveFrom-World-Events.patch new file mode 100644 index 0000000000..5dc11c88f8 --- /dev/null +++ b/patches/api-unmapped/0028-Entity-AddTo-RemoveFrom-World-Events.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 20:26:34 -0400 +Subject: [PATCH] Entity AddTo/RemoveFrom World Events + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..07660202e41ee86f1b66bad3335cf6fe126e7f9c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java +@@ -0,0 +1,32 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired any time an entity is being added to the world for any reason. ++ * ++ * Not to be confused with {@link org.bukkit.event.entity.CreatureSpawnEvent} ++ * This will fire anytime a chunk is reloaded too. ++ */ ++public class EntityAddToWorldEvent extends EntityEvent { ++ ++ public EntityAddToWorldEvent(@NotNull Entity entity) { ++ super(entity); ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e5dbbd660409bae0d3b96e83390511d3a423a52e +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java +@@ -0,0 +1,29 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired any time an entity is being removed from a world for any reason ++ */ ++public class EntityRemoveFromWorldEvent extends EntityEvent { ++ ++ public EntityRemoveFromWorldEvent(@NotNull Entity entity) { ++ super(entity); ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0029-EntityPathfindEvent.patch b/patches/api-unmapped/0029-EntityPathfindEvent.patch new file mode 100644 index 0000000000..697b76661a --- /dev/null +++ b/patches/api-unmapped/0029-EntityPathfindEvent.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 21:15:34 -0400 +Subject: [PATCH] EntityPathfindEvent + +Fires when an Entity decides to start moving to a location. + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..63e46b2fb1b12b36fcb1e98b178cf29dd2e3d1b5 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java +@@ -0,0 +1,82 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Fired when an Entity decides to start moving towards a location. ++ * ++ * This event does not fire for the entities actual movement. Only when it ++ * is choosing to start moving to a location. ++ */ ++public class EntityPathfindEvent extends EntityEvent implements Cancellable { ++ @Nullable private final Entity targetEntity; ++ @NotNull private final Location loc; ++ ++ public EntityPathfindEvent(@NotNull Entity entity, @NotNull Location loc, @Nullable Entity targetEntity) { ++ super(entity); ++ this.targetEntity = targetEntity; ++ this.loc = loc; ++ } ++ ++ /** ++ * The Entity that is pathfinding. ++ * @return The Entity that is pathfinding. ++ */ ++ @NotNull ++ public Entity getEntity() { ++ return entity; ++ } ++ ++ /** ++ * If the Entity is trying to pathfind to an entity, this is the entity in relation. ++ * ++ * Otherwise this will return null. ++ * ++ * @return The entity target or null ++ */ ++ @Nullable ++ public Entity getTargetEntity() { ++ return targetEntity; ++ } ++ ++ /** ++ * The Location of where the entity is about to move to. ++ * ++ * Note that if the target happened to of been an entity ++ * @return Location of where the entity is trying to pathfind to. ++ */ ++ @NotNull ++ public Location getLoc() { ++ return loc; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch b/patches/api-unmapped/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch new file mode 100644 index 0000000000..d4674ca2f4 --- /dev/null +++ b/patches/api-unmapped/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: crast +Date: Sat, 1 Jun 2013 13:52:30 -0600 +Subject: [PATCH] Reduce thread synchronization in MetadataStoreBase + +Use ConcurrentHashMap to allow thread-safe access methods and very +limited synchronized portions to allow much higher concurrency in +MetadataStore as well as far less locking, especially on reads + +diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java +index baf850226aed8545a5794deba6dff9603953b4b2..d363d517c05b3335101d829ce4ec22d049059c24 100644 +--- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java ++++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java +@@ -12,7 +12,7 @@ import org.bukkit.plugin.Plugin; + import org.jetbrains.annotations.NotNull; + + public abstract class MetadataStoreBase { +- private Map> metadataMap = new HashMap>(); ++ private Map> metadataMap = new java.util.concurrent.ConcurrentHashMap>(); // Paper + + /** + * Adds a metadata value to an object. Each metadata value is owned by a +@@ -46,7 +46,9 @@ public abstract class MetadataStoreBase { + entry = new WeakHashMap(1); + metadataMap.put(key, entry); + } +- entry.put(owningPlugin, newMetadataValue); ++ synchronized (entry) { ++ entry.put(owningPlugin, newMetadataValue); ++ } + } + + /** +@@ -60,10 +62,11 @@ public abstract class MetadataStoreBase { + * @see MetadataStore#getMetadata(Object, String) + */ + @NotNull +- public synchronized List getMetadata(@NotNull T subject, @NotNull String metadataKey) { ++ public List getMetadata(@NotNull T subject, @NotNull String metadataKey) { // Paper + String key = disambiguate(subject, metadataKey); +- if (metadataMap.containsKey(key)) { +- Collection values = metadataMap.get(key).values(); ++ Map entry = metadataMap.get(key); ++ if (entry != null) { ++ Collection values = entry.values(); + return Collections.unmodifiableList(new ArrayList(values)); + } else { + return Collections.emptyList(); +@@ -78,7 +81,7 @@ public abstract class MetadataStoreBase { + * @param metadataKey the unique metadata key being queried. + * @return the existence of the metadataKey within subject. + */ +- public synchronized boolean hasMetadata(@NotNull T subject, @NotNull String metadataKey) { ++ public boolean hasMetadata(@NotNull T subject, @NotNull String metadataKey) { // Paper + String key = disambiguate(subject, metadataKey); + return metadataMap.containsKey(key); + } +@@ -94,17 +97,18 @@ public abstract class MetadataStoreBase { + * @see MetadataStore#removeMetadata(Object, String, + * org.bukkit.plugin.Plugin) + */ +- public synchronized void removeMetadata(@NotNull T subject, @NotNull String metadataKey, @NotNull Plugin owningPlugin) { ++ public void removeMetadata(@NotNull T subject, @NotNull String metadataKey, @NotNull Plugin owningPlugin) { // Paper + Validate.notNull(owningPlugin, "Plugin cannot be null"); + String key = disambiguate(subject, metadataKey); + Map entry = metadataMap.get(key); + if (entry == null) { + return; + } +- +- entry.remove(owningPlugin); +- if (entry.isEmpty()) { +- metadataMap.remove(key); ++ synchronized (entry) { ++ entry.remove(owningPlugin); ++ if (entry.isEmpty()) { ++ metadataMap.remove(key); ++ } + } + } + +@@ -117,7 +121,7 @@ public abstract class MetadataStoreBase { + * @throws IllegalArgumentException If plugin is null + * @see MetadataStore#invalidateAll(org.bukkit.plugin.Plugin) + */ +- public synchronized void invalidateAll(@NotNull Plugin owningPlugin) { ++ public void invalidateAll(@NotNull Plugin owningPlugin) { // Paper + Validate.notNull(owningPlugin, "Plugin cannot be null"); + for (Map values : metadataMap.values()) { + if (values.containsKey(owningPlugin)) { diff --git a/patches/api-unmapped/0031-Add-MetadataStoreBase.removeAll-Plugin.patch b/patches/api-unmapped/0031-Add-MetadataStoreBase.removeAll-Plugin.patch new file mode 100644 index 0000000000..d15d19b316 --- /dev/null +++ b/patches/api-unmapped/0031-Add-MetadataStoreBase.removeAll-Plugin.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 16 Jul 2013 21:26:50 -0400 +Subject: [PATCH] Add MetadataStoreBase.removeAll(Plugin) + +So that on reload, metadata will be cleared + +diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java +index d363d517c05b3335101d829ce4ec22d049059c24..abbe545af572687a0399c2387434863cd2b70f68 100644 +--- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java ++++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java +@@ -4,6 +4,7 @@ import java.util.ArrayList; + import java.util.Collection; + import java.util.Collections; + import java.util.HashMap; ++import java.util.Iterator; // Paper + import java.util.List; + import java.util.Map; + import java.util.WeakHashMap; +@@ -130,6 +131,26 @@ public abstract class MetadataStoreBase { + } + } + ++ /** ++ * Removes all metadata in the metadata store that originates from the ++ * given plugin. ++ * ++ * @param owningPlugin the plugin requesting the invalidation. ++ * @throws IllegalArgumentException If plugin is null ++ */ ++ public void removeAll(@NotNull Plugin owningPlugin) { ++ Validate.notNull(owningPlugin, "Plugin cannot be null"); ++ for (Iterator> iterator = metadataMap.values().iterator(); iterator.hasNext(); ) { ++ Map values = iterator.next(); ++ if (values.containsKey(owningPlugin)) { ++ values.remove(owningPlugin); ++ } ++ if (values.isEmpty()) { ++ iterator.remove(); ++ } ++ } ++ } ++ + /** + * Creates a unique name for the object receiving metadata by combining + * unique data from the subject with a metadataKey. diff --git a/patches/api-unmapped/0032-Add-PlayerUseUnknownEntityEvent.patch b/patches/api-unmapped/0032-Add-PlayerUseUnknownEntityEvent.patch new file mode 100644 index 0000000000..8fa59475c2 --- /dev/null +++ b/patches/api-unmapped/0032-Add-PlayerUseUnknownEntityEvent.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 2 Apr 2016 05:08:36 -0400 +Subject: [PATCH] Add PlayerUseUnknownEntityEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..09cfdf48ead8f03f3497646537292174241b0868 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java +@@ -0,0 +1,46 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.EquipmentSlot; ++import org.jetbrains.annotations.NotNull; ++ ++public class PlayerUseUnknownEntityEvent extends PlayerEvent { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private final int entityId; ++ private final boolean attack; ++ @NotNull private final EquipmentSlot hand; ++ ++ public PlayerUseUnknownEntityEvent(@NotNull Player who, int entityId, boolean attack, @NotNull EquipmentSlot hand) { ++ super(who); ++ this.entityId = entityId; ++ this.attack = attack; ++ this.hand = hand; ++ } ++ ++ public int getEntityId() { ++ return this.entityId; ++ } ++ ++ public boolean isAttack() { ++ return this.attack; ++ } ++ ++ @NotNull ++ public EquipmentSlot getHand() { ++ return this.hand; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/patches/api-unmapped/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch new file mode 100644 index 0000000000..eb1703e485 --- /dev/null +++ b/patches/api-unmapped/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch @@ -0,0 +1,290 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 13 Apr 2016 20:20:18 -0700 +Subject: [PATCH] Add handshake event to allow plugins to handle client + handshaking logic themselves + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a077962fa786a3291849abfa823c7f0ec4664fce +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java +@@ -0,0 +1,277 @@ ++package com.destroystokyo.paper.event.player; ++ ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.format.NamedTextColor; ++import org.apache.commons.lang.Validate; ++import org.bukkit.Bukkit; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++ ++import java.util.UUID; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * This event is fired during a player handshake. ++ * ++ *

    If there are no listeners listening to this event, the logic default ++ * to your server platform will be ran.

    ++ * ++ *

    WARNING: TAMPERING WITH THIS EVENT CAN BE DANGEROUS

    ++ */ ++public class PlayerHandshakeEvent extends Event implements Cancellable { ++ ++ private static final HandlerList HANDLERS = new HandlerList(); ++ @NotNull private final String originalHandshake; ++ @NotNull private final String originalSocketAddressHostname; ++ private boolean cancelled; ++ @Nullable private String serverHostname; ++ @Nullable private String socketAddressHostname; ++ @Nullable private UUID uniqueId; ++ @Nullable private String propertiesJson; ++ private boolean failed; ++ private Component failMessage = Component.text("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!", NamedTextColor.YELLOW); ++ ++ /** ++ * Creates a new {@link PlayerHandshakeEvent}. ++ * ++ * @param originalHandshake the original handshake string ++ * @param cancelled if this event is enabled ++ * ++ * @deprecated in favour of {@link PlayerHandshakeEvent(String, String, boolean)} ++ */ ++ @Deprecated ++ public PlayerHandshakeEvent(@NotNull String originalHandshake, boolean cancelled) { ++ this(originalHandshake, "127.0.0.1", cancelled); ++ } ++ ++ /** ++ * Creates a new {@link PlayerHandshakeEvent}. ++ * ++ * @param originalHandshake the original handshake string ++ * @param originalSocketAddressHostname the original socket address hostname ++ * @param cancelled if this event is enabled ++ */ ++ public PlayerHandshakeEvent(@NotNull String originalHandshake, @NotNull String originalSocketAddressHostname, boolean cancelled) { ++ super(true); ++ this.originalHandshake = originalHandshake; ++ this.originalSocketAddressHostname = originalSocketAddressHostname; ++ this.cancelled = cancelled; ++ } ++ ++ /** ++ * Determines if this event is cancelled. ++ * ++ *

    When this event is cancelled, custom handshake logic will not ++ * be processed.

    ++ * ++ * @return {@code true} if this event is cancelled, {@code false} otherwise ++ */ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ /** ++ * Sets if this event is cancelled. ++ * ++ *

    When this event is cancelled, custom handshake logic will not ++ * be processed.

    ++ * ++ * @param cancelled {@code true} if this event is cancelled, {@code false} otherwise ++ */ ++ @Override ++ public void setCancelled(boolean cancelled) { ++ this.cancelled = cancelled; ++ } ++ ++ /** ++ * Gets the original handshake string. ++ * ++ * @return the original handshake string ++ */ ++ @NotNull ++ public String getOriginalHandshake() { ++ return this.originalHandshake; ++ } ++ ++ /** ++ * Gets the original socket address hostname. ++ * ++ *

    This does not include the port.

    ++ *

    In cases where this event is manually fired and the plugin wasn't updated yet, the default is {@code "127.0.0.1"}.

    ++ * ++ * @return the original socket address hostname ++ */ ++ @NotNull ++ public String getOriginalSocketAddressHostname() { ++ return this.originalSocketAddressHostname; ++ } ++ ++ /** ++ * Gets the server hostname string. ++ * ++ *

    This should not include the port.

    ++ * ++ * @return the server hostname string ++ */ ++ @Nullable ++ public String getServerHostname() { ++ return this.serverHostname; ++ } ++ ++ /** ++ * Sets the server hostname string. ++ * ++ *

    This should not include the port.

    ++ * ++ * @param serverHostname the server hostname string ++ */ ++ public void setServerHostname(@NotNull String serverHostname) { ++ this.serverHostname = serverHostname; ++ } ++ ++ /** ++ * Gets the socket address hostname string. ++ * ++ *

    This should not include the port.

    ++ * ++ * @return the socket address hostname string ++ */ ++ @Nullable ++ public String getSocketAddressHostname() { ++ return this.socketAddressHostname; ++ } ++ ++ /** ++ * Sets the socket address hostname string. ++ * ++ *

    This should not include the port.

    ++ * ++ * @param socketAddressHostname the socket address hostname string ++ */ ++ public void setSocketAddressHostname(@NotNull String socketAddressHostname) { ++ this.socketAddressHostname = socketAddressHostname; ++ } ++ ++ /** ++ * Gets the unique id. ++ * ++ * @return the unique id ++ */ ++ @Nullable ++ public UUID getUniqueId() { ++ return this.uniqueId; ++ } ++ ++ /** ++ * Sets the unique id. ++ * ++ * @param uniqueId the unique id ++ */ ++ public void setUniqueId(@NotNull UUID uniqueId) { ++ this.uniqueId = uniqueId; ++ } ++ ++ /** ++ * Gets the profile properties. ++ * ++ *

    This should be a valid JSON string.

    ++ * ++ * @return the profile properties, as JSON ++ */ ++ @Nullable ++ public String getPropertiesJson() { ++ return this.propertiesJson; ++ } ++ ++ /** ++ * Determines if authentication failed. ++ * ++ *

    When {@code true}, the client connecting will be disconnected ++ * with the {@link #getFailMessage() fail message}.

    ++ * ++ * @return {@code true} if authentication failed, {@code false} otherwise ++ */ ++ public boolean isFailed() { ++ return this.failed; ++ } ++ ++ /** ++ * Sets if authentication failed and the client should be disconnected. ++ * ++ *

    When {@code true}, the client connecting will be disconnected ++ * with the {@link #getFailMessage() fail message}.

    ++ * ++ * @param failed {@code true} if authentication failed, {@code false} otherwise ++ */ ++ public void setFailed(boolean failed) { ++ this.failed = failed; ++ } ++ ++ /** ++ * Sets the profile properties. ++ * ++ *

    This should be a valid JSON string.

    ++ * ++ * @param propertiesJson the profile properties, as JSON ++ */ ++ public void setPropertiesJson(@NotNull String propertiesJson) { ++ this.propertiesJson = propertiesJson; ++ } ++ ++ /** ++ * Gets the message to display to the client when authentication fails. ++ * ++ * @return the message to display to the client ++ */ ++ @NotNull ++ public Component failMessage() { ++ return this.failMessage; ++ } ++ ++ /** ++ * Sets the message to display to the client when authentication fails. ++ * ++ * @param failMessage the message to display to the client ++ */ ++ public void failMessage(@NotNull Component failMessage) { ++ this.failMessage = failMessage; ++ } ++ ++ /** ++ * Gets the message to display to the client when authentication fails. ++ * ++ * @return the message to display to the client ++ * @deprecated use {@link #failMessage()} ++ */ ++ @NotNull ++ @Deprecated ++ public String getFailMessage() { ++ return Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.failMessage()); ++ } ++ ++ /** ++ * Sets the message to display to the client when authentication fails. ++ * ++ * @param failMessage the message to display to the client ++ * @deprecated use {@link #failMessage(Component)} ++ */ ++ @Deprecated ++ public void setFailMessage(@NotNull String failMessage) { ++ Validate.notEmpty(failMessage, "fail message cannot be null or empty"); ++ this.failMessage(Bukkit.getUnsafe().legacyComponentSerializer().deserialize(failMessage)); ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLERS; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLERS; ++ } ++} diff --git a/patches/api-unmapped/0034-Arrow-pickup-rule-API.patch b/patches/api-unmapped/0034-Arrow-pickup-rule-API.patch new file mode 100644 index 0000000000..fb3753f0e1 --- /dev/null +++ b/patches/api-unmapped/0034-Arrow-pickup-rule-API.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Fri, 4 Mar 2016 03:13:18 -0500 +Subject: [PATCH] Arrow pickup rule API + + +diff --git a/src/main/java/org/bukkit/entity/AbstractArrow.java b/src/main/java/org/bukkit/entity/AbstractArrow.java +index 5b50a4e10e8ace8cc53ad3c8d7c3185f88d5c8db..e8e56e89e32d84af0639fe2e9b0eeabd747b6007 100644 +--- a/src/main/java/org/bukkit/entity/AbstractArrow.java ++++ b/src/main/java/org/bukkit/entity/AbstractArrow.java +@@ -141,4 +141,38 @@ public interface AbstractArrow extends Projectile { + */ + CREATIVE_ONLY + } ++ ++ // Paper start ++ /** ++ * Gets the {@link PickupRule} for this arrow. ++ * ++ *

    This is generally {@link PickupRule#ALLOWED} only if the arrow was ++ * not fired from a bow with the infinity enchantment.

    ++ * ++ * @return The pickup rule ++ * @deprecated Use {@link Arrow#getPickupStatus()} as an upstream compatible replacement for this function ++ */ ++ @Deprecated ++ default PickupRule getPickupRule() { ++ return PickupRule.valueOf(this.getPickupStatus().name()); ++ } ++ ++ /** ++ * Set the rule for which players can pickup this arrow as an item. ++ * ++ * @param rule The pickup rule ++ * @deprecated Use {@link Arrow#setPickupStatus(PickupStatus)} with {@link PickupStatus} as an upstream compatible replacement for this function ++ */ ++ @Deprecated ++ default void setPickupRule(PickupRule rule) { ++ this.setPickupStatus(PickupStatus.valueOf(rule.name())); ++ } ++ ++ @Deprecated ++ enum PickupRule { ++ DISALLOWED, ++ ALLOWED, ++ CREATIVE_ONLY; ++ } ++ // Paper end + } diff --git a/patches/api-unmapped/0035-EntityRegainHealthEvent-isFastRegen-API.patch b/patches/api-unmapped/0035-EntityRegainHealthEvent-isFastRegen-API.patch new file mode 100644 index 0000000000..f06ee13d15 --- /dev/null +++ b/patches/api-unmapped/0035-EntityRegainHealthEvent-isFastRegen-API.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 22 Apr 2016 01:43:11 -0500 +Subject: [PATCH] EntityRegainHealthEvent isFastRegen API + + +diff --git a/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java b/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java +index 8feb6698f9630f099be99e52d1149cd6bc615197..d51d2ec1d04d9ea8a25a70d0d856f2355ebfcb4a 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java +@@ -13,12 +13,31 @@ public class EntityRegainHealthEvent extends EntityEvent implements Cancellable + private boolean cancelled; + private double amount; + private final RegainReason regainReason; ++ private final boolean isFastRegen; // Paper + + public EntityRegainHealthEvent(@NotNull final Entity entity, final double amount, @NotNull final RegainReason regainReason) { ++ // Paper start - Forward ++ this(entity, amount, regainReason, false); ++ } ++ ++ public EntityRegainHealthEvent(@NotNull final Entity entity, final double amount, @NotNull final RegainReason regainReason, boolean isFastRegen) { ++ // Paper end + super(entity); + this.amount = amount; + this.regainReason = regainReason; ++ this.isFastRegen = isFastRegen; // Paper ++ } ++ ++ // Paper start - Add getter for isFastRegen ++ /** ++ * Is this event a result of the fast regeneration mechanic ++ * ++ * @return Whether the event is the result of a fast regeneration mechanic ++ */ ++ public boolean isFastRegen() { ++ return isFastRegen; + } ++ // Paper end + + /** + * Gets the amount of regained health diff --git a/patches/api-unmapped/0036-LootTable-API.patch b/patches/api-unmapped/0036-LootTable-API.patch new file mode 100644 index 0000000000..ed6e56042d --- /dev/null +++ b/patches/api-unmapped/0036-LootTable-API.patch @@ -0,0 +1,402 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 1 May 2016 15:19:49 -0400 +Subject: [PATCH] LootTable API + +Provides API to control what Loot Table an object uses. + +Also provides an Event to control if a lootable inventory should +auto replenish for a player. + +Provides methods to determine players looted state for an object + +diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..92d7b853a2ccaae5afa8ac141bead840942944ef +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.loottable; ++ ++import org.bukkit.block.Block; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents an Inventory that can generate loot, such as Chests inside of Fortresses and Mineshafts ++ */ ++public interface LootableBlockInventory extends LootableInventory { ++ ++ /** ++ * Gets the block that is lootable ++ * @return The Block ++ */ ++ @NotNull ++ Block getBlock(); ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b387894fe8001edb41ad2ad2b70ebabe065b682e +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.loottable; ++ ++import org.bukkit.entity.Entity; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents an Inventory that can generate loot, such as Minecarts inside of Mineshafts ++ */ ++public interface LootableEntityInventory extends LootableInventory { ++ ++ /** ++ * Gets the entity that is lootable ++ * @return The Entity ++ */ ++ @NotNull ++ Entity getEntity(); ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..97815eeb231cf0706b34fa47a4f7d1bb786305b4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java +@@ -0,0 +1,116 @@ ++package com.destroystokyo.paper.loottable; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.loot.Lootable; ++ ++import java.util.UUID; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Represents an Inventory that contains a Loot Table associated to it that will ++ * automatically fill on first open. ++ * ++ * A new feature and API is provided to support automatically refreshing the contents ++ * of the inventory based on that Loot Table after a configurable amount of time has passed. ++ * ++ * The behavior of how the Inventory is filled based on the loot table may vary based ++ * on Minecraft versions and the Loot Table feature. ++ */ ++public interface LootableInventory extends Lootable { ++ ++ /** ++ * Server owners have to enable whether or not an object in a world should refill ++ * ++ * @return If the world this inventory is currently in has Replenishable Lootables enabled ++ */ ++ boolean isRefillEnabled(); ++ ++ /** ++ * Whether or not this object has ever been filled ++ * @return Has ever been filled ++ */ ++ boolean hasBeenFilled(); ++ ++ /** ++ * Has this player ever looted this block ++ * @param player The player to check ++ * @return Whether or not this player has looted this block ++ */ ++ default boolean hasPlayerLooted(@NotNull Player player) { ++ return hasPlayerLooted(player.getUniqueId()); ++ } ++ ++ /** ++ * Has this player ever looted this block ++ * @param player The player to check ++ * @return Whether or not this player has looted this block ++ */ ++ boolean hasPlayerLooted(@NotNull UUID player); ++ ++ /** ++ * Gets the timestamp, in milliseconds, of when the player last looted this object ++ * ++ * @param player The player to check ++ * @return Timestamp last looted, or null if player has not looted this object ++ */ ++ @Nullable ++ default Long getLastLooted(@NotNull Player player) { ++ return getLastLooted(player.getUniqueId()); ++ } ++ ++ /** ++ * Gets the timestamp, in milliseconds, of when the player last looted this object ++ * ++ * @param player The player to check ++ * @return Timestamp last looted, or null if player has not looted this object ++ */ ++ @Nullable ++ Long getLastLooted(@NotNull UUID player); ++ ++ /** ++ * Change the state of whether or not a player has looted this block ++ * @param player The player to change state for ++ * @param looted true to add player to looted list, false to remove ++ * @return The previous state of whether the player had looted this or not ++ */ ++ default boolean setHasPlayerLooted(@NotNull Player player, boolean looted) { ++ return setHasPlayerLooted(player.getUniqueId(), looted); ++ } ++ ++ /** ++ * Change the state of whether or not a player has looted this block ++ * @param player The player to change state for ++ * @param looted true to add player to looted list, false to remove ++ * @return The previous state of whether the player had looted this or not ++ */ ++ boolean setHasPlayerLooted(@NotNull UUID player, boolean looted); ++ ++ /** ++ * Returns Whether or not this object has been filled and now has a pending refill ++ * @return Has pending refill ++ */ ++ boolean hasPendingRefill(); ++ ++ /** ++ * Gets the timestamp in milliseconds that the Lootable object was last refilled ++ * ++ * @return -1 if it was never refilled, or timestamp in milliseconds ++ */ ++ long getLastFilled(); ++ ++ /** ++ * Gets the timestamp in milliseconds that the Lootable object will refill ++ * ++ * @return -1 if it is not scheduled for refill, or timestamp in milliseconds ++ */ ++ long getNextRefill(); ++ ++ /** ++ * Sets the timestamp in milliseconds of the next refill for this object ++ * ++ * @param refillAt timestamp in milliseconds. -1 to clear next refill ++ * @return The previous scheduled time to refill, or -1 if was not scheduled ++ */ ++ long setNextRefill(long refillAt); ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fd184f13f5e8ee5cf829fff4f44696e1f760430b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java +@@ -0,0 +1,45 @@ ++package com.destroystokyo.paper.loottable; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++public class LootableInventoryReplenishEvent extends PlayerEvent implements Cancellable { ++ @NotNull private final LootableInventory inventory; ++ ++ public LootableInventoryReplenishEvent(@NotNull Player player, @NotNull LootableInventory inventory) { ++ super(player); ++ this.inventory = inventory; ++ } ++ ++ @NotNull ++ public LootableInventory getInventory() { ++ return inventory; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} +diff --git a/src/main/java/org/bukkit/block/Chest.java b/src/main/java/org/bukkit/block/Chest.java +index b451191312e4fb19f2131c2d0a0c0337953f6c7c..db6affbc78106b2d93b41953b624a0bca0ca1d72 100644 +--- a/src/main/java/org/bukkit/block/Chest.java ++++ b/src/main/java/org/bukkit/block/Chest.java +@@ -1,5 +1,7 @@ + package org.bukkit.block; + ++import com.destroystokyo.paper.loottable.LootableBlockInventory; // Paper ++import org.bukkit.Nameable; // Paper + import org.bukkit.inventory.Inventory; + import org.bukkit.loot.Lootable; + import org.jetbrains.annotations.NotNull; +@@ -7,7 +9,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a captured state of a chest. + */ +-public interface Chest extends Container, Lootable, Lidded { ++public interface Chest extends Container, LootableBlockInventory, Lidded { // Paper + + /** + * Gets the inventory of the chest block represented by this block state. +diff --git a/src/main/java/org/bukkit/block/Dispenser.java b/src/main/java/org/bukkit/block/Dispenser.java +index 74cd194c9a98245dc52e7e352d7d6c046e1e5cf3..07af1a3f011d4b96275f919d302ac367198e923e 100644 +--- a/src/main/java/org/bukkit/block/Dispenser.java ++++ b/src/main/java/org/bukkit/block/Dispenser.java +@@ -1,5 +1,6 @@ + package org.bukkit.block; + ++import com.destroystokyo.paper.loottable.LootableBlockInventory; + import org.bukkit.Nameable; + import org.bukkit.loot.Lootable; + import org.bukkit.projectiles.BlockProjectileSource; +@@ -8,7 +9,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a captured state of a dispenser. + */ +-public interface Dispenser extends Container, Nameable, Lootable { ++public interface Dispenser extends Container, Nameable, LootableBlockInventory { // Paper + + /** + * Gets the BlockProjectileSource object for the dispenser. +diff --git a/src/main/java/org/bukkit/block/Dropper.java b/src/main/java/org/bukkit/block/Dropper.java +index 424392fb5ed4628199b0e73689522aa3c90740cb..c76202321e29ad67597ca3017eb8d9baf6787383 100644 +--- a/src/main/java/org/bukkit/block/Dropper.java ++++ b/src/main/java/org/bukkit/block/Dropper.java +@@ -1,11 +1,12 @@ + package org.bukkit.block; + ++import com.destroystokyo.paper.loottable.LootableBlockInventory; + import org.bukkit.loot.Lootable; + + /** + * Represents a captured state of a dropper. + */ +-public interface Dropper extends Container, Lootable { ++public interface Dropper extends Container, LootableBlockInventory { // Paper + + /** + * Tries to drop a randomly selected item from the dropper's inventory, +diff --git a/src/main/java/org/bukkit/block/Hopper.java b/src/main/java/org/bukkit/block/Hopper.java +index 58e493099810fb8d4705ecd49b4a5e1e1949b87b..7ade312f180b7e30871d3a3240c76325cc369c26 100644 +--- a/src/main/java/org/bukkit/block/Hopper.java ++++ b/src/main/java/org/bukkit/block/Hopper.java +@@ -1,8 +1,9 @@ + package org.bukkit.block; + ++import com.destroystokyo.paper.loottable.LootableBlockInventory; + import org.bukkit.loot.Lootable; + + /** + * Represents a captured state of a hopper. + */ +-public interface Hopper extends Container, Lootable { } ++public interface Hopper extends Container, LootableBlockInventory { } // Paper +diff --git a/src/main/java/org/bukkit/block/ShulkerBox.java b/src/main/java/org/bukkit/block/ShulkerBox.java +index 387b2892886e1ccb2bd928e5111fb9bd41d777ab..5dc5318b0a451937228a8a059dfec1cd9de389a6 100644 +--- a/src/main/java/org/bukkit/block/ShulkerBox.java ++++ b/src/main/java/org/bukkit/block/ShulkerBox.java +@@ -1,5 +1,6 @@ + package org.bukkit.block; + ++import com.destroystokyo.paper.loottable.LootableBlockInventory; + import org.bukkit.DyeColor; + import org.bukkit.loot.Lootable; + import org.jetbrains.annotations.Nullable; +@@ -7,7 +8,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a captured state of a ShulkerBox. + */ +-public interface ShulkerBox extends Container, Lootable, Lidded { ++public interface ShulkerBox extends Container, LootableBlockInventory, Lidded { // Paper + + /** + * Get the {@link DyeColor} corresponding to this ShulkerBox +diff --git a/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java b/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java +index 937b99f8734d71b2ad33af142afbc251b81d9745..db69687a7ad4b18d17ab1677cae5d8dd4dcd3678 100644 +--- a/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java ++++ b/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java +@@ -1,5 +1,6 @@ + package org.bukkit.entity.minecart; + ++import com.destroystokyo.paper.loottable.LootableEntityInventory; + import org.bukkit.entity.Minecart; + import org.bukkit.inventory.InventoryHolder; + import org.bukkit.loot.Lootable; +@@ -7,7 +8,7 @@ import org.bukkit.loot.Lootable; + /** + * Represents a Minecart with a Hopper inside it + */ +-public interface HopperMinecart extends Minecart, InventoryHolder, Lootable { ++public interface HopperMinecart extends Minecart, InventoryHolder, LootableEntityInventory { + + /** + * Checks whether or not this Minecart will pick up +diff --git a/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java b/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java +index 9ea403e6fd8e960d017660e0aec118abeda2c42b..238d118f7788b13cd86b7e9ea3a0fc38e2e09715 100644 +--- a/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java ++++ b/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java +@@ -1,5 +1,6 @@ + package org.bukkit.entity.minecart; + ++import com.destroystokyo.paper.loottable.LootableEntityInventory; + import org.bukkit.entity.Minecart; + import org.bukkit.inventory.InventoryHolder; + import org.bukkit.loot.Lootable; +@@ -9,5 +10,5 @@ import org.bukkit.loot.Lootable; + * minecarts} have their own inventory that can be accessed using methods + * from the {@link InventoryHolder} interface. + */ +-public interface StorageMinecart extends Minecart, InventoryHolder, Lootable { ++public interface StorageMinecart extends Minecart, InventoryHolder, LootableEntityInventory { // Paper + } +diff --git a/src/main/java/org/bukkit/loot/Lootable.java b/src/main/java/org/bukkit/loot/Lootable.java +index 24a3d989db3bc67e7afe8459a3d4bb132f448ea7..901db852498e0658c79a57582508dab29bf0a798 100644 +--- a/src/main/java/org/bukkit/loot/Lootable.java ++++ b/src/main/java/org/bukkit/loot/Lootable.java +@@ -36,6 +36,34 @@ public interface Lootable { + @Nullable + LootTable getLootTable(); + ++ // Paper start ++ /** ++ * Set the loot table and seed for a container or entity at the same time. ++ * ++ * @param table the Loot Table this {@link org.bukkit.block.Container} or {@link org.bukkit.entity.Mob} will have. ++ * @param seed the seed to used to generate loot. Default is 0. ++ */ ++ default void setLootTable(@Nullable LootTable table, long seed) { ++ setLootTable(table); ++ setSeed(seed); ++ } ++ ++ /** ++ * Returns whether or not this object has a Loot Table ++ * @return Has a loot table ++ */ ++ default boolean hasLootTable() { ++ return getLootTable() != null; ++ } ++ ++ /** ++ * Clears the associated Loot Table to this object ++ */ ++ default void clearLootTable() { ++ setLootTable(null); ++ } ++ // Paper end ++ + /** + * Set the seed used when this Loot Table generates loot. + * diff --git a/patches/api-unmapped/0037-Add-EntityZapEvent.patch b/patches/api-unmapped/0037-Add-EntityZapEvent.patch new file mode 100644 index 0000000000..41d603f073 --- /dev/null +++ b/patches/api-unmapped/0037-Add-EntityZapEvent.patch @@ -0,0 +1,123 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaBlend +Date: Sun, 16 Oct 2016 23:19:34 -0700 +Subject: [PATCH] Add EntityZapEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3b725a489008d333630af166d2be5fc48168a6b9 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java +@@ -0,0 +1,65 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.apache.commons.lang.Validate; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.LightningStrike; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++ ++import java.util.Collections; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when lightning strikes an entity ++ */ ++public class EntityZapEvent extends EntityTransformEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ @NotNull private final LightningStrike bolt; ++ ++ public EntityZapEvent(@NotNull final Entity entity, @NotNull final LightningStrike bolt, @NotNull final Entity replacementEntity) { ++ super(entity, Collections.singletonList(replacementEntity), TransformReason.LIGHTNING); ++ Validate.notNull(bolt); ++ Validate.notNull(replacementEntity); ++ this.bolt = bolt; ++ } ++ ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ /** ++ * Gets the lightning bolt that is striking the entity. ++ * @return The lightning bolt responsible for this event ++ */ ++ @NotNull ++ public LightningStrike getBolt() { ++ return bolt; ++ } ++ ++ /** ++ * Gets the entity that will replace the struck entity. ++ * @return The entity that will replace the struck entity ++ */ ++ @NotNull ++ public Entity getReplacementEntity() { ++ return getTransformedEntity(); ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/org/bukkit/event/entity/PigZapEvent.java b/src/main/java/org/bukkit/event/entity/PigZapEvent.java +index 0e0ed93b568fd2c0d8f6e359c31dc29cb0fa71c2..d3949edfc736b3d67a627ef378748b374769e183 100644 +--- a/src/main/java/org/bukkit/event/entity/PigZapEvent.java ++++ b/src/main/java/org/bukkit/event/entity/PigZapEvent.java +@@ -2,6 +2,7 @@ package org.bukkit.event.entity; + + import java.util.Collections; + import org.bukkit.entity.Entity; ++import com.destroystokyo.paper.event.entity.EntityZapEvent; + import org.bukkit.entity.LightningStrike; + import org.bukkit.entity.Pig; + import org.bukkit.entity.PigZombie; +@@ -12,14 +13,14 @@ import org.jetbrains.annotations.NotNull; + /** + * Stores data for pigs being zapped + */ +-public class PigZapEvent extends EntityTransformEvent implements Cancellable { +- private static final HandlerList handlers = new HandlerList(); ++public class PigZapEvent extends EntityZapEvent implements Cancellable { ++ //private static final HandlerList handlers = new HandlerList(); + private boolean canceled; + private final PigZombie pigzombie; + private final LightningStrike bolt; + + public PigZapEvent(@NotNull final Pig pig, @NotNull final LightningStrike bolt, @NotNull final PigZombie pigzombie) { +- super(pig, Collections.singletonList((Entity) pigzombie), TransformReason.LIGHTNING); ++ super(pig, bolt, pigzombie); + this.bolt = bolt; + this.pigzombie = pigzombie; + } +@@ -63,6 +64,8 @@ public class PigZapEvent extends EntityTransformEvent implements Cancellable { + return pigzombie; + } + ++ // Paper start ++ /* + @NotNull + @Override + public HandlerList getHandlers() { +@@ -73,4 +76,6 @@ public class PigZapEvent extends EntityTransformEvent implements Cancellable { + public static HandlerList getHandlerList() { + return handlers; + } ++ */ ++ // Paper end + } diff --git a/patches/api-unmapped/0038-Misc-Utils.patch b/patches/api-unmapped/0038-Misc-Utils.patch new file mode 100644 index 0000000000..fac858b16c --- /dev/null +++ b/patches/api-unmapped/0038-Misc-Utils.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: vemacs +Date: Wed, 23 Nov 2016 12:53:43 -0500 +Subject: [PATCH] Misc Utils + + +diff --git a/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java b/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5bb677ce585b856b3d3e589e29786a29619c56a7 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java +@@ -0,0 +1,34 @@ ++package com.destroystokyo.paper.utils; ++ ++import java.util.concurrent.ConcurrentLinkedQueue; ++import java.util.concurrent.atomic.LongAdder; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++public class CachedSizeConcurrentLinkedQueue extends ConcurrentLinkedQueue { ++ private final LongAdder cachedSize = new LongAdder(); ++ ++ @Override ++ public boolean add(@NotNull E e) { ++ boolean result = super.add(e); ++ if (result) { ++ cachedSize.increment(); ++ } ++ return result; ++ } ++ ++ @Nullable ++ @Override ++ public E poll() { ++ E result = super.poll(); ++ if (result != null) { ++ cachedSize.decrement(); ++ } ++ return result; ++ } ++ ++ @Override ++ public int size() { ++ return cachedSize.intValue(); ++ } ++} diff --git a/patches/api-unmapped/0039-Allow-Reloading-of-Command-Aliases.patch b/patches/api-unmapped/0039-Allow-Reloading-of-Command-Aliases.patch new file mode 100644 index 0000000000..dcad4e696d --- /dev/null +++ b/patches/api-unmapped/0039-Allow-Reloading-of-Command-Aliases.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: willies952002 +Date: Mon, 28 Nov 2016 10:16:39 -0500 +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 1380a26f34a9d2b162e88fbea14b17118945643c..7b3a0c958b4b4bffb6c19a0e4d3bf4824f8db237 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1759,6 +1759,15 @@ public final class Bukkit { + public static void reloadPermissions() { + server.reloadPermissions(); + } ++ ++ /** ++ * Reload the Command Aliases in commands.yml ++ * ++ * @return Whether the reload was successful ++ */ ++ public static boolean reloadCommandAliases() { ++ return server.reloadCommandAliases(); ++ } + // Paper end + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 4c201097ef98f545acb604fa72d56413553e4d4f..6f4817af249e258905c97f4dac3d2f33804bdfc5 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1551,4 +1551,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + // Spigot end + + void reloadPermissions(); // Paper ++ ++ boolean reloadCommandAliases(); // Paper + } +diff --git a/src/main/java/org/bukkit/command/CommandMap.java b/src/main/java/org/bukkit/command/CommandMap.java +index bd2c7a6964722412148fae39e1b4951fc0002b9b..864c263bbd4dd6dd7c37a74b39b1a40a884d0731 100644 +--- a/src/main/java/org/bukkit/command/CommandMap.java ++++ b/src/main/java/org/bukkit/command/CommandMap.java +@@ -128,4 +128,14 @@ public interface CommandMap { + */ + @Nullable + public List tabComplete(@NotNull CommandSender sender, @NotNull String cmdLine, @Nullable Location location) throws IllegalArgumentException; ++ ++ // Paper start - Expose Known Commands ++ /** ++ * Return a Map of known commands ++ * ++ * @return known commands ++ */ ++ @NotNull ++ public java.util.Map getKnownCommands(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java +index adfc7aae2c0f49bbcdd358e83b04a0cf078a7d52..460fda05a62b12db2edcfb7ea8b2a5dd8e4b110d 100644 +--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java ++++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java +@@ -297,4 +297,11 @@ public class SimpleCommandMap implements CommandMap { + } + } + } ++ ++ // Paper start - Expose Known Commands ++ @NotNull ++ public Map getKnownCommands() { ++ return knownCommands; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +index c62da4131b17e66892678e8b618fb9ba3de93b56..0c7ba0718de2b93d013968ca0fec34ffd423990f 100644 +--- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +@@ -13,7 +13,7 @@ public class ReloadCommand extends BukkitCommand { + public ReloadCommand(@NotNull String name) { + super(name); + this.description = "Reloads the server configuration and plugins"; +- this.usageMessage = "/reload [permissions]"; // Paper ++ this.usageMessage = "/reload [permissions|commands|confirm]"; // Paper + this.setPermission("bukkit.command.reload"); + this.setAliases(Arrays.asList("rl")); + } +@@ -29,6 +29,13 @@ public class ReloadCommand extends BukkitCommand { + Bukkit.getServer().reloadPermissions(); + Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Permissions successfully reloaded."); + return true; ++ } else if ("commands".equalsIgnoreCase(args[0])) { ++ if (Bukkit.getServer().reloadCommandAliases()) { ++ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Command aliases successfully reloaded."); ++ } else { ++ Command.broadcastCommandMessage(sender, ChatColor.RED + "An error occurred while trying to reload command aliases."); ++ } ++ return true; + } else if ("confirm".equalsIgnoreCase(args[0])) { + confirmed = true; + } else { +@@ -53,6 +60,6 @@ public class ReloadCommand extends BukkitCommand { + @NotNull + @Override + public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException { +- return java.util.Collections.singletonList("permissions"); // Paper ++ return com.google.common.collect.Lists.newArrayList("permissions", "commands"); // Paper + } + } diff --git a/patches/api-unmapped/0040-Add-source-to-PlayerExpChangeEvent.patch b/patches/api-unmapped/0040-Add-source-to-PlayerExpChangeEvent.patch new file mode 100644 index 0000000000..675b2be839 --- /dev/null +++ b/patches/api-unmapped/0040-Add-source-to-PlayerExpChangeEvent.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaBlend +Date: Thu, 8 Sep 2016 08:47:08 -0700 +Subject: [PATCH] Add source to PlayerExpChangeEvent + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerExpChangeEvent.java b/src/main/java/org/bukkit/event/player/PlayerExpChangeEvent.java +index c99c9281e98e4b510dddb711b8785bcd56b3b92f..7c340f539c31a431d7d9204a8135e0bfc31863a8 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerExpChangeEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerExpChangeEvent.java +@@ -1,21 +1,43 @@ + package org.bukkit.event.player; + ++import org.bukkit.entity.Entity; // Paper + import org.bukkit.entity.Player; + import org.bukkit.event.HandlerList; + import org.jetbrains.annotations.NotNull; + ++import org.jetbrains.annotations.Nullable; // Paper ++ + /** + * Called when a players experience changes naturally + */ + public class PlayerExpChangeEvent extends PlayerEvent { + private static final HandlerList handlers = new HandlerList(); ++ // Paper start ++ @Nullable ++ private final Entity source; + private int exp; + + public PlayerExpChangeEvent(@NotNull final Player player, final int expAmount) { ++ this(player, null, expAmount); ++ } ++ ++ public PlayerExpChangeEvent(@NotNull final Player player, @Nullable final Entity sourceEntity, final int expAmount) { + super(player); ++ source = sourceEntity; + exp = expAmount; + } + ++ /** ++ * Get the source that provided the experience. ++ * ++ * @return The source of the experience ++ */ ++ @Nullable ++ public Entity getSource() { ++ return source; ++ } ++ // Paper end ++ + /** + * Get the amount of experience the player will receive + * diff --git a/patches/api-unmapped/0041-Add-ProjectileCollideEvent.patch b/patches/api-unmapped/0041-Add-ProjectileCollideEvent.patch new file mode 100644 index 0000000000..a5c9df18df --- /dev/null +++ b/patches/api-unmapped/0041-Add-ProjectileCollideEvent.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Fri, 16 Dec 2016 21:25:39 -0600 +Subject: [PATCH] Add ProjectileCollideEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..453663893021768ae21d4980ce17ffba55d9e129 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java +@@ -0,0 +1,67 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Projectile; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when an projectile collides with an entity ++ *

    ++ * This event is called before {@link org.bukkit.event.entity.EntityDamageByEntityEvent}, and cancelling it will allow the projectile to continue flying ++ */ ++public class ProjectileCollideEvent extends EntityEvent implements Cancellable { ++ @NotNull private final Entity collidedWith; ++ ++ /** ++ * Get the entity the projectile collided with ++ * ++ * @return the entity collided with ++ */ ++ @NotNull ++ public Entity getCollidedWith() { ++ return collidedWith; ++ } ++ ++ public ProjectileCollideEvent(@NotNull Projectile what, @NotNull Entity collidedWith) { ++ super(what); ++ this.collidedWith = collidedWith; ++ } ++ ++ /** ++ * Get the projectile that collided ++ * ++ * @return the projectile that collided ++ */ ++ @NotNull ++ public Projectile getEntity() { ++ return (Projectile) super.getEntity(); ++ } ++ ++ private static final HandlerList handlerList = new HandlerList(); ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlerList; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlerList; ++ } ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0042-Add-String-based-Action-Bar-API.patch b/patches/api-unmapped/0042-Add-String-based-Action-Bar-API.patch new file mode 100644 index 0000000000..ae3f76e08c --- /dev/null +++ b/patches/api-unmapped/0042-Add-String-based-Action-Bar-API.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 20 Dec 2016 15:55:55 -0500 +Subject: [PATCH] Add String based Action Bar API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index ddbe5734ac0f905b0c388e30f17a281530b82262..6bb0bb8052c12c5a215abf4bd9602fbefc769523 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -3,6 +3,7 @@ package org.bukkit.entity; + import java.net.InetSocketAddress; + import java.util.UUID; + import com.destroystokyo.paper.Title; // Paper ++import net.kyori.adventure.text.Component; + import org.bukkit.DyeColor; + import org.bukkit.Effect; + import org.bukkit.GameMode; +@@ -616,6 +617,39 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + public void sendMap(@NotNull MapView map); + + // Paper start ++ ++ /** ++ * Sends an Action Bar message to the client. ++ * ++ * Use Section symbols for legacy color codes to send formatting. ++ * ++ * @param message The message to send ++ * @deprecated use {@link #sendActionBar(Component)} ++ */ ++ @Deprecated ++ public void sendActionBar(@NotNull String message); ++ ++ /** ++ * Sends an Action Bar message to the client. ++ * ++ * Use supplied alternative character to the section symbol to represent legacy color codes. ++ * ++ * @param alternateChar Alternate symbol such as '&' ++ * @param message The message to send ++ * @deprecated use {@link #sendActionBar(Component)} ++ */ ++ @Deprecated ++ public void sendActionBar(char alternateChar, @NotNull String message); ++ ++ /** ++ * Sends an Action Bar message to the client. ++ * ++ * @param message The components to send ++ * @deprecated use {@link #sendActionBar(Component)} ++ */ ++ @Deprecated ++ public void sendActionBar(@NotNull net.md_5.bungee.api.chat.BaseComponent... message); ++ + /** + * Sends the component to the player + * +@@ -643,9 +677,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + /** + * Sends an array of components as a single message to the specified screen position of this player + * ++ * @deprecated This is unlikely the API you want to use. See {@link #sendActionBar(String)} for a more proper Action Bar API. This deprecated API may send unsafe items to the client. + * @param position the screen position + * @param components the components to send + */ ++ @Deprecated + public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { + spigot().sendMessage(position, components); + } +@@ -1728,6 +1764,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + /** + * Sends the component to the specified screen position of this player + * ++ * @deprecated This is unlikely the API you want to use. See {@link #sendActionBar(String)} for a more proper Action Bar API. This deprecated API may send unsafe items to the client. + * @param position the screen position + * @param component the components to send + * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} +@@ -1740,6 +1777,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + /** + * Sends an array of components as a single message to the specified screen position of this player + * ++ * @deprecated This is unlikely the API you want to use. See {@link #sendActionBar(String)} for a more proper Action Bar API. This deprecated API may send unsafe items to the client. + * @param position the screen position + * @param components the components to send + * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} diff --git a/patches/api-unmapped/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch b/patches/api-unmapped/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch new file mode 100644 index 0000000000..3f2a539353 --- /dev/null +++ b/patches/api-unmapped/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 21 Dec 2016 11:47:25 -0600 +Subject: [PATCH] Add API methods to control if armour stands can move + + +diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java +index e94ec567fbda93f4f5783f84b4b5136b309d0eab..fddc063798edc8084ca695578a47485204a7f3cd 100644 +--- a/src/main/java/org/bukkit/entity/ArmorStand.java ++++ b/src/main/java/org/bukkit/entity/ArmorStand.java +@@ -344,4 +344,21 @@ public interface ArmorStand extends LivingEntity { + */ + ADDING; + } ++ // Paper start ++ /** ++ * Tests if this armor stand can move. ++ * ++ *

    The default value is {@code true}.

    ++ * ++ * @return {@code true} if this armour stand can move, {@code false} otherwise ++ */ ++ boolean canMove(); ++ ++ /** ++ * Sets if this armor stand can move. ++ * ++ * @param move {@code true} if this armour stand can move, {@code false} otherwise ++ */ ++ void setCanMove(boolean move); ++ // Paper end + } diff --git a/patches/api-unmapped/0044-IllegalPacketEvent.patch b/patches/api-unmapped/0044-IllegalPacketEvent.patch new file mode 100644 index 0000000000..7eb8d61aaa --- /dev/null +++ b/patches/api-unmapped/0044-IllegalPacketEvent.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 4 Dec 2016 01:19:14 -0500 +Subject: [PATCH] IllegalPacketEvent + +Fire an event when an illegal packet is received to let plugins handle it + +Lets plugins change the kick message and if it should kick or not. + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java b/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8d8e9b16f2a6707d2af7567c7682dfc5db51a737 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java +@@ -0,0 +1,74 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * @deprecated Not used ++ */ ++@Deprecated ++public class IllegalPacketEvent extends PlayerEvent { ++ @Nullable private final String type; ++ @Nullable private final String ex; ++ @Nullable private String kickMessage; ++ private boolean shouldKick = true; ++ ++ public IllegalPacketEvent(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception e) { ++ super(player); ++ this.type = type; ++ this.kickMessage = kickMessage; ++ this.ex = e.getMessage(); ++ } ++ ++ public boolean isShouldKick() { ++ return shouldKick; ++ } ++ ++ public void setShouldKick(boolean shouldKick) { ++ this.shouldKick = shouldKick; ++ } ++ ++ @Nullable ++ public String getKickMessage() { ++ return kickMessage; ++ } ++ ++ public void setKickMessage(@Nullable String kickMessage) { ++ this.kickMessage = kickMessage; ++ } ++ ++ @Nullable ++ public String getType() { ++ return type; ++ } ++ ++ @Nullable ++ public String getExceptionMessage() { ++ return ex; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ public static void process(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception exception) { ++ IllegalPacketEvent event = new IllegalPacketEvent(player, type, kickMessage, exception); ++ event.callEvent(); ++ if (event.shouldKick) { ++ player.kickPlayer(kickMessage); ++ } ++ Bukkit.getLogger().severe(player.getName() + "/" + type + ": " + exception.getMessage()); ++ } ++} diff --git a/patches/api-unmapped/0045-Fireworks-API-s.patch b/patches/api-unmapped/0045-Fireworks-API-s.patch new file mode 100644 index 0000000000..a0ed753ac6 --- /dev/null +++ b/patches/api-unmapped/0045-Fireworks-API-s.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 28 Dec 2016 01:18:55 -0500 +Subject: [PATCH] Fireworks API's + +Get the Entity being boosted +Get the firework launcher + +diff --git a/src/main/java/org/bukkit/entity/Firework.java b/src/main/java/org/bukkit/entity/Firework.java +index 05e86cb9d826cdf14490fa649348d46c51adbfdb..d616d5941b3c7b85e350e845901da798601b9a3c 100644 +--- a/src/main/java/org/bukkit/entity/Firework.java ++++ b/src/main/java/org/bukkit/entity/Firework.java +@@ -43,4 +43,15 @@ public interface Firework extends Projectile { + * @param shotAtAngle the new shotAtAngle + */ + void setShotAtAngle(boolean shotAtAngle); ++ ++ // Paper start ++ @org.jetbrains.annotations.Nullable ++ public java.util.UUID getSpawningEntity(); ++ /** ++ * If this firework is boosting an entity, return it ++ * @return The entity being boosted ++ */ ++ @org.jetbrains.annotations.Nullable ++ public LivingEntity getBoostedEntity(); ++ // Paper end + } diff --git a/patches/api-unmapped/0046-PlayerTeleportEndGatewayEvent.patch b/patches/api-unmapped/0046-PlayerTeleportEndGatewayEvent.patch new file mode 100644 index 0000000000..664edd24cd --- /dev/null +++ b/patches/api-unmapped/0046-PlayerTeleportEndGatewayEvent.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 31 Dec 2016 20:29:33 -0500 +Subject: [PATCH] PlayerTeleportEndGatewayEvent + +Allows you to access the Gateway being used in a teleport event + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b64ab6eecd8bc4ca9c109b9d83c82861d6260793 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java +@@ -0,0 +1,29 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.Location; ++import org.bukkit.block.EndGateway; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when a teleport is triggered for an End Gateway ++ */ ++public class PlayerTeleportEndGatewayEvent extends PlayerTeleportEvent { ++ @NotNull private final EndGateway gateway; ++ ++ public PlayerTeleportEndGatewayEvent(@NotNull Player player, @NotNull Location from, @NotNull Location to, @NotNull EndGateway gateway) { ++ super(player, from, to, PlayerTeleportEvent.TeleportCause.END_GATEWAY); ++ this.gateway = gateway; ++ } ++ ++ /** ++ * The gateway triggering the teleport ++ * ++ * @return EndGateway used ++ */ ++ @NotNull ++ public EndGateway getGateway() { ++ return gateway; ++ } ++} diff --git a/patches/api-unmapped/0047-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/api-unmapped/0047-Provide-E-TE-Chunk-count-stat-methods.patch new file mode 100644 index 0000000000..fc838a6f02 --- /dev/null +++ b/patches/api-unmapped/0047-Provide-E-TE-Chunk-count-stat-methods.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 Jan 2017 15:23:03 -0500 +Subject: [PATCH] Provide E/TE/Chunk count stat methods + +Provides counts without the ineffeciency of using .getEntities().size() +which creates copy of the collections. + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 6b5dbe4ea711807a1944cfe2aae2ce415d4f2638..789e070f6aee83e4b6426def784e05df98e1bc65 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -40,6 +40,33 @@ import org.jetbrains.annotations.Nullable; + */ + public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience { // Paper + ++ // Paper start ++ /** ++ * @return The amount of Entities in this world ++ */ ++ int getEntityCount(); ++ ++ /** ++ * @return The amount of Tile Entities in this world ++ */ ++ int getTileEntityCount(); ++ ++ /** ++ * @return The amount of Tickable Tile Entities in this world ++ */ ++ int getTickableTileEntityCount(); ++ ++ /** ++ * @return The amount of Chunks in this world ++ */ ++ int getChunkCount(); ++ ++ /** ++ * @return The amount of Players in this world ++ */ ++ int getPlayerCount(); ++ // Paper end ++ + /** + * Gets the {@link Block} at the given coordinates + * diff --git a/patches/api-unmapped/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/api-unmapped/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch new file mode 100644 index 0000000000..5dadaf640f --- /dev/null +++ b/patches/api-unmapped/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch @@ -0,0 +1,122 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 16:28:32 -0500 +Subject: [PATCH] ExperienceOrbs API for Reason/Source/Triggering player + +Adds lots of information about why this orb exists. + +Replaces isFromBottle() with logic that persists entity reloads too. + +diff --git a/src/main/java/org/bukkit/entity/ExperienceOrb.java b/src/main/java/org/bukkit/entity/ExperienceOrb.java +index c286edfd827e185a76e44c44faace19a80325d7a..dec70bbfaf73a9d525b2c45682b804c684e1645b 100644 +--- a/src/main/java/org/bukkit/entity/ExperienceOrb.java ++++ b/src/main/java/org/bukkit/entity/ExperienceOrb.java +@@ -1,5 +1,8 @@ + package org.bukkit.entity; + ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; // Paper ++ + /** + * Represents an Experience Orb. + */ +@@ -18,4 +21,99 @@ public interface ExperienceOrb extends Entity { + * @param value Amount of experience + */ + public void setExperience(int value); ++ ++ // Paper start ++ /** ++ * Check if this orb was spawned from a {@link ThrownExpBottle} ++ * ++ * @return if orb was spawned from a bottle ++ * @deprecated Use getSpawnReason() == EXP_BOTTLE ++ */ ++ @Deprecated ++ default boolean isFromBottle() { ++ return getSpawnReason() == SpawnReason.EXP_BOTTLE; ++ } ++ ++ /** ++ * Reasons for why this Experience Orb was spawned ++ */ ++ enum SpawnReason { ++ /** ++ * Spawned by a player dying ++ */ ++ PLAYER_DEATH, ++ /** ++ * Spawned by an entity dying after being damaged by a player ++ */ ++ ENTITY_DEATH, ++ /** ++ * Spawned by player using a furnace ++ */ ++ FURNACE, ++ /** ++ * Spawned by player breeding animals ++ */ ++ BREED, ++ /** ++ * Spawned by player trading with a villager ++ */ ++ VILLAGER_TRADE, ++ /** ++ * Spawned by player fishing ++ */ ++ FISHING, ++ /** ++ * Spawned by player breaking a block that gives experience points such as Diamond Ore ++ */ ++ BLOCK_BREAK, ++ /** ++ * Spawned by Bukkit API ++ */ ++ CUSTOM, ++ /** ++ * Spawned by a player throwing an experience points bottle ++ */ ++ EXP_BOTTLE, ++ /** ++ * Spawned by a player using a grindstone ++ */ ++ GRINDSTONE, ++ /** ++ * We do not know why it was spawned ++ */ ++ UNKNOWN ++ } ++ ++ /** ++ * If this experience orb was triggered to be spawned by ++ * an entity such as a player, due to events such as killing entity, ++ * breaking blocks, smelting in a furnace, etc, this will return the UUID ++ * of the entity that triggered this orb to drop. ++ * ++ * In the case of an entity being killed, this will be the killers UUID. ++ * ++ * @return UUID of the player that triggered this orb to drop, or null if unknown/no triggering entity ++ */ ++ @Nullable java.util.UUID getTriggerEntityId(); ++ ++ /** ++ * If this experience orb was spawned in relation to another ++ * entity, such as a player or other living entity death, or breeding, ++ * return the source entity UUID. ++ * ++ * In the case of breeding, this will be the new baby entities UUID. ++ * In the case of an entity being killed, this will be the dead entities UUID. ++ * ++ * @return The UUID of the entity that sourced this experience orb ++ */ ++ @Nullable java.util.UUID getSourceEntityId(); ++ ++ /** ++ * Gets the reason that this experience orb was spawned. For any case that we ++ * do not know, such as orbs spawned before this API was added, UNKNOWN is returned. ++ * @return The reason for this orb being spawned. ++ */ ++ @NotNull ++ SpawnReason getSpawnReason(); ++ // Paper end + } diff --git a/patches/api-unmapped/0049-Expose-WorldBorder-isInBounds-Location-check.patch b/patches/api-unmapped/0049-Expose-WorldBorder-isInBounds-Location-check.patch new file mode 100644 index 0000000000..f700226be3 --- /dev/null +++ b/patches/api-unmapped/0049-Expose-WorldBorder-isInBounds-Location-check.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 21 Jan 2017 17:03:10 -0600 +Subject: [PATCH] Expose WorldBorder#isInBounds(Location) check + + +diff --git a/src/main/java/org/bukkit/WorldBorder.java b/src/main/java/org/bukkit/WorldBorder.java +index 7e8f5649ce0eb0090899514b1e228601eb644613..afb7b136b461202026290624836446cff9f9e45d 100644 +--- a/src/main/java/org/bukkit/WorldBorder.java ++++ b/src/main/java/org/bukkit/WorldBorder.java +@@ -117,4 +117,18 @@ public interface WorldBorder { + * @return if this location is inside the border or not + */ + public boolean isInside(@NotNull Location location); ++ ++ // Paper start ++ /** ++ * Checks if the location is within the boundaries of this border. ++ * ++ * @param location specific location to check ++ * @return true if the location is within the bounds of this border, false otherwise. ++ * @deprecated use {@link #isInside(Location)} for an upstream compatible replacement ++ */ ++ @Deprecated ++ public default boolean isInBounds(@NotNull Location location) { ++ return this.isInside(location); ++ } ++ // Paper end + } diff --git a/patches/api-unmapped/0050-Add-configuration-option-to-prevent-player-names-fro.patch b/patches/api-unmapped/0050-Add-configuration-option-to-prevent-player-names-fro.patch new file mode 100644 index 0000000000..195a5c5c39 --- /dev/null +++ b/patches/api-unmapped/0050-Add-configuration-option-to-prevent-player-names-fro.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Fri, 9 Jun 2017 07:24:24 -0700 +Subject: [PATCH] Add configuration option to prevent player names from being + suggested + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 7b3a0c958b4b4bffb6c19a0e4d3bf4824f8db237..e2052baa65ed3525a89b26c065b3e2a58916ab99 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1768,6 +1768,16 @@ public final class Bukkit { + public static boolean reloadCommandAliases() { + return server.reloadCommandAliases(); + } ++ ++ /** ++ * Checks if player names should be suggested when a command returns {@code null} as ++ * their tab completion result. ++ * ++ * @return true if player names should be suggested ++ */ ++ public static boolean suggestPlayerNamesWhenNullTabCompletions() { ++ return server.suggestPlayerNamesWhenNullTabCompletions(); ++ } + // Paper end + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 6f4817af249e258905c97f4dac3d2f33804bdfc5..8fd026e4ffcdf009365ae04b87f7559bed32c7d3 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1553,4 +1553,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + void reloadPermissions(); // Paper + + boolean reloadCommandAliases(); // Paper ++ ++ // Paper start - allow preventing player name suggestions by default ++ /** ++ * Checks if player names should be suggested when a command returns {@code null} as ++ * their tab completion result. ++ * ++ * @return true if player names should be suggested ++ */ ++ boolean suggestPlayerNamesWhenNullTabCompletions(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java +index 03bdc1622791e1206406c87065978688d602e39e..7c80dc54776d0d66f7816b77136f6dbd9b801704 100644 +--- a/src/main/java/org/bukkit/command/Command.java ++++ b/src/main/java/org/bukkit/command/Command.java +@@ -99,7 +99,7 @@ public abstract class Command { + Validate.notNull(args, "Arguments cannot be null"); + Validate.notNull(alias, "Alias cannot be null"); + +- if (args.length == 0) { ++ if (args.length == 0 || !sender.getServer().suggestPlayerNamesWhenNullTabCompletions()) { // Paper - allow preventing player name suggestions by default) { + return ImmutableList.of(); + } + diff --git a/patches/api-unmapped/0051-Fix-upstream-javadoc-warnings-and-errors.patch b/patches/api-unmapped/0051-Fix-upstream-javadoc-warnings-and-errors.patch new file mode 100644 index 0000000000..083596bdd2 --- /dev/null +++ b/patches/api-unmapped/0051-Fix-upstream-javadoc-warnings-and-errors.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 10 Jun 2017 16:59:40 -0500 +Subject: [PATCH] Fix upstream javadoc warnings and errors + +Upstream still refuses to use Java 8 with the API so they are likely unaware these are even issues. + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 3f68baef538098d9ce66b91195b6fa17f26f0d78..e71b048e53ee2db4e768eea2ddf19b00a14d2484 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -634,7 +634,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * + * Use supplied alternative character to the section symbol to represent legacy color codes. + * +- * @param alternateChar Alternate symbol such as '&' ++ * @param alternateChar Alternate symbol such as '&' + * @param message The message to send + * @deprecated use {@link #sendActionBar(Component)} + */ +diff --git a/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java b/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java +index 1b2267f4e8ebded198773ec80e2bff2c861c7084..1a58734d919fae247eeb85dd785fd59990856505 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java +@@ -78,7 +78,7 @@ public class PlayerMoveEvent extends PlayerEvent implements Cancellable { + * + * @return Location the player moved to + */ +- @Nullable ++ @NotNull // Paper + public Location getTo() { + return to; + } +diff --git a/src/main/java/org/bukkit/inventory/PlayerInventory.java b/src/main/java/org/bukkit/inventory/PlayerInventory.java +index 91afd844dafec4ed9ab9e2e16b220ffbd35e7495..1e45c9078ffffe9d3c25538fdd433780ae751270 100644 +--- a/src/main/java/org/bukkit/inventory/PlayerInventory.java ++++ b/src/main/java/org/bukkit/inventory/PlayerInventory.java +@@ -106,7 +106,7 @@ public interface PlayerInventory extends Inventory { + * + * @return the ItemStack in the given slot + */ +- @NotNull ++ @Nullable + public ItemStack getItem(@NotNull EquipmentSlot slot); + + /** diff --git a/patches/api-unmapped/0052-Item-canEntityPickup.patch b/patches/api-unmapped/0052-Item-canEntityPickup.patch new file mode 100644 index 0000000000..27894bda93 --- /dev/null +++ b/patches/api-unmapped/0052-Item-canEntityPickup.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 5 May 2017 03:57:08 -0500 +Subject: [PATCH] Item#canEntityPickup + + +diff --git a/src/main/java/org/bukkit/entity/Item.java b/src/main/java/org/bukkit/entity/Item.java +index 3f2736fbddd8661e764bc2f8d0499bd13ca91df5..c404a5b8efea7c780db5ddae19456753808abb3d 100644 +--- a/src/main/java/org/bukkit/entity/Item.java ++++ b/src/main/java/org/bukkit/entity/Item.java +@@ -75,4 +75,20 @@ public interface Item extends Entity { + */ + @Nullable + public UUID getThrower(); ++ ++ // Paper Start ++ /** ++ * Gets if non-player entities can pick this Item up ++ * ++ * @return True if non-player entities can pickup ++ */ ++ public boolean canMobPickup(); ++ ++ /** ++ * Sets if non-player entities can pick this Item up ++ * ++ * @param canMobPickup True to allow non-player entity pickup ++ */ ++ public void setCanMobPickup(boolean canMobPickup); ++ // Paper end + } diff --git a/patches/api-unmapped/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch b/patches/api-unmapped/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch new file mode 100644 index 0000000000..353d395911 --- /dev/null +++ b/patches/api-unmapped/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 7 May 2017 06:26:01 -0500 +Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java b/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java +index 951ea2cc763973655beedcba3c75332d3f297313..18d82c111f30e0279c10a174a51bac018185cd38 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java +@@ -17,6 +17,7 @@ import org.jetbrains.annotations.NotNull; + public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private final Item item; ++ private boolean flyAtPlayer = true; // Paper + private boolean cancel = false; + private final int remaining; + +@@ -45,6 +46,27 @@ public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable { + return remaining; + } + ++ // Paper Start ++ /** ++ * Set if the item will fly at the player ++ *

    Cancelling the event will set this value to false.

    ++ * ++ * @param flyAtPlayer True for item to fly at player ++ */ ++ public void setFlyAtPlayer(boolean flyAtPlayer) { ++ this.flyAtPlayer = flyAtPlayer; ++ } ++ ++ /** ++ * Gets if the item will fly at the player ++ * ++ * @return True if the item will fly at the player ++ */ ++ public boolean getFlyAtPlayer() { ++ return flyAtPlayer; ++ } ++ // Paper End ++ + @Override + public boolean isCancelled() { + return cancel; +@@ -53,6 +75,7 @@ public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable { + @Override + public void setCancelled(boolean cancel) { + this.cancel = cancel; ++ this.flyAtPlayer = !cancel; // Paper + } + + @NotNull diff --git a/patches/api-unmapped/0054-PlayerAttemptPickupItemEvent.patch b/patches/api-unmapped/0054-PlayerAttemptPickupItemEvent.patch new file mode 100644 index 0000000000..6b504ae688 --- /dev/null +++ b/patches/api-unmapped/0054-PlayerAttemptPickupItemEvent.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 11 Jun 2017 16:30:37 -0500 +Subject: [PATCH] PlayerAttemptPickupItemEvent + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java b/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0788153a9641e75da565d2e6eee37eeee1cbc61e +--- /dev/null ++++ b/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java +@@ -0,0 +1,90 @@ ++package org.bukkit.event.player; ++ ++import org.bukkit.entity.Item; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Thrown when a player attempts to pick an item up from the ground ++ */ ++public class PlayerAttemptPickupItemEvent extends PlayerEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ @NotNull private final Item item; ++ private final int remaining; ++ private boolean flyAtPlayer = true; ++ private boolean isCancelled = false; ++ ++ @Deprecated // Remove in 1.13 // Remove in 1.14? ++ public PlayerAttemptPickupItemEvent(@NotNull final Player player, @NotNull final Item item) { ++ this(player, item, 0); ++ } ++ ++ public PlayerAttemptPickupItemEvent(@NotNull final Player player, @NotNull final Item item, final int remaining) { ++ super(player); ++ this.item = item; ++ this.remaining = remaining; ++ } ++ ++ /** ++ * Gets the Item attempted by the player. ++ * ++ * @return Item ++ */ ++ @NotNull ++ public Item getItem() { ++ return item; ++ } ++ ++ /** ++ * Gets the amount that will remain on the ground, if any ++ * ++ * @return amount that will remain on the ground ++ */ ++ public int getRemaining() { ++ return remaining; ++ } ++ ++ /** ++ * Set if the item will fly at the player ++ *

    Cancelling the event will set this value to false.

    ++ * ++ * @param flyAtPlayer True for item to fly at player ++ */ ++ public void setFlyAtPlayer(boolean flyAtPlayer) { ++ this.flyAtPlayer = flyAtPlayer; ++ } ++ ++ /** ++ * Gets if the item will fly at the player ++ * ++ * @return True if the item will fly at the player ++ */ ++ public boolean getFlyAtPlayer() { ++ return this.flyAtPlayer; ++ } ++ ++ ++ @Override ++ public boolean isCancelled() { ++ return this.isCancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.isCancelled = cancel; ++ this.flyAtPlayer = !cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0055-Add-UnknownCommandEvent.patch b/patches/api-unmapped/0055-Add-UnknownCommandEvent.patch new file mode 100644 index 0000000000..9e3d997b0d --- /dev/null +++ b/patches/api-unmapped/0055-Add-UnknownCommandEvent.patch @@ -0,0 +1,126 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sweepyoface +Date: Sat, 17 Jun 2017 18:48:06 -0400 +Subject: [PATCH] Add UnknownCommandEvent + + +diff --git a/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java b/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d5632d352590dec6982a372b285a8d4a332fa589 +--- /dev/null ++++ b/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java +@@ -0,0 +1,114 @@ ++package org.bukkit.event.command; ++ ++import net.kyori.adventure.text.Component; ++import org.bukkit.Bukkit; ++import org.bukkit.command.CommandSender; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.Event; ++ ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Thrown when a player executes a command that is not defined ++ */ ++public class UnknownCommandEvent extends Event { ++ private static final HandlerList handlers = new HandlerList(); ++ @NotNull private CommandSender sender; ++ @NotNull private String commandLine; ++ @Nullable private Component message; ++ ++ @Deprecated ++ public UnknownCommandEvent(@NotNull final CommandSender sender, @NotNull final String commandLine, @Nullable final String message) { ++ this(sender, commandLine, message == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message)); ++ } ++ ++ public UnknownCommandEvent(@NotNull final CommandSender sender, @NotNull final String commandLine, @Nullable final Component message) { ++ super(false); ++ this.sender = sender; ++ this.commandLine = commandLine; ++ this.message = message; ++ } ++ ++ /** ++ * Gets the CommandSender or ConsoleCommandSender ++ *

    ++ * ++ * @return Sender of the command ++ */ ++ @NotNull ++ public CommandSender getSender() { ++ return sender; ++ } ++ ++ /** ++ * Gets the command that was send ++ *

    ++ * ++ * @return Command sent ++ */ ++ @NotNull ++ public String getCommandLine() { ++ return commandLine; ++ } ++ ++ /** ++ * Gets message that will be returned ++ *

    ++ * ++ * @return Unknown command message ++ * @deprecated use {@link #message()} ++ */ ++ @Nullable ++ @Deprecated ++ public String getMessage() { ++ return this.message == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); ++ } ++ ++ /** ++ * Sets message that will be returned ++ *

    ++ * Set to null to avoid any message being sent ++ * ++ * @param message the message to be returned, or null ++ * @deprecated use {@link #message(Component)} ++ */ ++ @Deprecated ++ public void setMessage(@Nullable String message) { ++ this.message(message == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message)); ++ } ++ ++ /** ++ * Gets message that will be returned ++ *

    ++ * ++ * @return Unknown command message ++ */ ++ @Nullable ++ public Component message() { ++ return this.message; ++ } ++ ++ /** ++ * Sets message that will be returned ++ *

    ++ * Set to null to avoid any message being sent ++ * ++ * @param message the message to be returned, or null ++ */ ++ public void message(@Nullable Component message) { ++ this.message = message; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} ++ diff --git a/patches/api-unmapped/0056-Basic-PlayerProfile-API.patch b/patches/api-unmapped/0056-Basic-PlayerProfile-API.patch new file mode 100644 index 0000000000..1c7a3ce8f5 --- /dev/null +++ b/patches/api-unmapped/0056-Basic-PlayerProfile-API.patch @@ -0,0 +1,351 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 15 Jan 2018 21:46:46 -0500 +Subject: [PATCH] Basic PlayerProfile API + +Provides basic elements of a PlayerProfile to be used by future API/events + +diff --git a/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2ef9a7bd55e2c9cf8cb20d5f77282676ae11181f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java +@@ -0,0 +1,177 @@ ++package com.destroystokyo.paper.profile; ++ ++import java.util.Collection; ++import java.util.Set; ++import java.util.UUID; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Represents a players profile for the game, such as UUID, Name, and textures. ++ */ ++public interface PlayerProfile { ++ ++ /** ++ * @return The players name, if set ++ */ ++ @Nullable ++ String getName(); ++ ++ /** ++ * Sets this profiles Name ++ * ++ * @param name The new Name ++ * @return The previous Name ++ */ ++ @NotNull ++ String setName(@Nullable String name); ++ ++ /** ++ * @return The players unique identifier, if set ++ */ ++ @Nullable UUID getId(); ++ ++ /** ++ * Sets this profiles UUID ++ * ++ * @param uuid The new UUID ++ * @return The previous UUID ++ */ ++ @Nullable ++ UUID setId(@Nullable UUID uuid); ++ ++ /** ++ * @return A Mutable set of this players properties, such as textures. ++ * Values specified here are subject to implementation details. ++ */ ++ @NotNull Set getProperties(); ++ ++ /** ++ * Check if the Profile has the specified property ++ * @param property Property name to check ++ * @return If the property is set ++ */ ++ boolean hasProperty(@Nullable String property); ++ ++ /** ++ * Sets a property. If the property already exists, the previous one will be replaced ++ * @param property Property to set. ++ */ ++ void setProperty(@NotNull ProfileProperty property); ++ ++ /** ++ * Sets multiple properties. If any of the set properties already exist, it will be replaced ++ * @param properties The properties to set ++ */ ++ void setProperties(@NotNull Collection properties); ++ ++ /** ++ * Removes a specific property from this profile ++ * @param property The property to remove ++ * @return If a property was removed ++ */ ++ boolean removeProperty(@Nullable String property); ++ ++ /** ++ * Removes a specific property from this profile ++ * @param property The property to remove ++ * @return If a property was removed ++ */ ++ default boolean removeProperty(@NotNull ProfileProperty property) { ++ return removeProperty(property.getName()); ++ } ++ ++ /** ++ * Removes all properties in the collection ++ * @param properties The properties to remove ++ * @return If any property was removed ++ */ ++ default boolean removeProperties(@NotNull Collection properties) { ++ boolean removed = false; ++ for (ProfileProperty property : properties) { ++ if (removeProperty(property)) { ++ removed = true; ++ } ++ } ++ return removed; ++ } ++ ++ /** ++ * Clears all properties on this profile ++ */ ++ void clearProperties(); ++ ++ /** ++ * @return If the profile is now complete (has UUID and Name) ++ */ ++ boolean isComplete(); ++ ++ /** ++ * Like {@link #complete(boolean)} but will try only from cache, and not make network calls ++ * Does not account for textures. ++ * ++ * @return If the profile is now complete (has UUID and Name) ++ */ ++ boolean completeFromCache(); ++ ++ /** ++ * Like {@link #complete(boolean)} but will try only from cache, and not make network calls ++ * Does not account for textures. ++ * ++ * @param onlineMode Treat this as online mode or not ++ * @return If the profile is now complete (has UUID and Name) ++ */ ++ boolean completeFromCache(boolean onlineMode); ++ ++ /** ++ * Like {@link #complete(boolean)} but will try only from cache, and not make network calls ++ * Does not account for textures. ++ * ++ * @param lookupUUID If only name is supplied, should we do a UUID lookup ++ * @param onlineMode Treat this as online mode or not ++ * @return If the profile is now complete (has UUID and Name) ++ */ ++ boolean completeFromCache(boolean lookupUUID, boolean onlineMode); ++ ++ /** ++ * If this profile is not complete, then make the API call to complete it. ++ * This is a blocking operation and should be done asynchronously. ++ * ++ * This will also complete textures. If you do not want to load textures, use {{@link #complete(boolean)}} ++ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail) ++ */ ++ default boolean complete() { ++ return complete(true); ++ } ++ ++ /** ++ * If this profile is not complete, then make the API call to complete it. ++ * This is a blocking operation and should be done asynchronously. ++ * ++ * Optionally will also fill textures. ++ * ++ * Online mode will be automatically determined ++ * @param textures controls if we should fill the profile with texture properties ++ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail) ++ */ ++ boolean complete(boolean textures); ++ ++ /** ++ * If this profile is not complete, then make the API call to complete it. ++ * This is a blocking operation and should be done asynchronously. ++ * ++ * Optionally will also fill textures. ++ * @param textures controls if we should fill the profile with texture properties ++ * @param onlineMode Treat this server as online mode or not ++ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail) ++ */ ++ boolean complete(boolean textures, boolean onlineMode); ++ ++ /** ++ * Whether or not this Profile has textures associated to it ++ * @return If has a textures property ++ */ ++ default boolean hasTextures() { ++ return hasProperty("textures"); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java b/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7b3b6ef533d32169fbeca389bd61cfc6b0e0faee +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java +@@ -0,0 +1,72 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.google.common.base.Preconditions; ++ ++import java.util.Objects; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Represents a property on a {@link PlayerProfile} ++ */ ++public class ProfileProperty { ++ private final String name; ++ private final String value; ++ private final String signature; ++ ++ public ProfileProperty(@NotNull String name, @NotNull String value) { ++ this(name, value, null); ++ } ++ ++ public ProfileProperty(@NotNull String name, @NotNull String value, @Nullable String signature) { ++ this.name = Preconditions.checkNotNull(name, "ProfileProperty name can not be null"); ++ this.value = Preconditions.checkNotNull(value, "ProfileProperty value can not be null"); ++ this.signature = signature; ++ } ++ ++ /** ++ * @return The property name, ie "textures" ++ */ ++ @NotNull ++ public String getName() { ++ return name; ++ } ++ ++ /** ++ * @return The property value, likely to be base64 encoded ++ */ ++ @NotNull ++ public String getValue() { ++ return value; ++ } ++ ++ /** ++ * @return A signature from Mojang for signed properties ++ */ ++ @Nullable ++ public String getSignature() { ++ return signature; ++ } ++ ++ /** ++ * @return If this property has a signature or not ++ */ ++ public boolean isSigned() { ++ return this.signature != null; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ ProfileProperty that = (ProfileProperty) o; ++ return Objects.equals(name, that.name) && ++ Objects.equals(value, that.value) && ++ Objects.equals(signature, that.signature); ++ } ++ ++ @Override ++ public int hashCode() { ++ return Objects.hash(name); ++ } ++} +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index e2052baa65ed3525a89b26c065b3e2a58916ab99..39942b4c5683f2dcc40be5a23af36a3bb32badb1 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1778,6 +1778,40 @@ public final class Bukkit { + public static boolean suggestPlayerNamesWhenNullTabCompletions() { + return server.suggestPlayerNamesWhenNullTabCompletions(); + } ++ ++ /** ++ * Creates a PlayerProfile for the specified uuid, with name as null ++ * @param uuid UUID to create profile for ++ * @return A PlayerProfile object ++ */ ++ @NotNull ++ public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull UUID uuid) { ++ return server.createProfile(uuid); ++ } ++ ++ /** ++ * Creates a PlayerProfile for the specified name, with UUID as null ++ * @param name Name to create profile for ++ * @return A PlayerProfile object ++ */ ++ @NotNull ++ public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull String name) { ++ return server.createProfile(name); ++ } ++ ++ /** ++ * Creates a PlayerProfile for the specified name/uuid ++ * ++ * Both UUID and Name can not be null at same time. One must be supplied. ++ * ++ * @param uuid UUID to create profile for ++ * @param name Name to create profile for ++ * @return A PlayerProfile object ++ */ ++ @NotNull ++ public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { ++ return server.createProfile(uuid, name); ++ } + // Paper end + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 8fd026e4ffcdf009365ae04b87f7559bed32c7d3..0c1fbaee08cb614dfdd1de0200dfa7fa351fc52d 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1562,5 +1562,33 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + * @return true if player names should be suggested + */ + boolean suggestPlayerNamesWhenNullTabCompletions(); ++ ++ /** ++ * Creates a PlayerProfile for the specified uuid, with name as null ++ * @param uuid UUID to create profile for ++ * @return A PlayerProfile object ++ */ ++ @NotNull ++ com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull UUID uuid); ++ ++ /** ++ * Creates a PlayerProfile for the specified name, with UUID as null ++ * @param name Name to create profile for ++ * @return A PlayerProfile object ++ */ ++ @NotNull ++ com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull String name); ++ ++ /** ++ * Creates a PlayerProfile for the specified name/uuid ++ * ++ * Both UUID and Name can not be null at same time. One must be supplied. ++ * ++ * @param uuid UUID to create profile for ++ * @param name Name to create profile for ++ * @return A PlayerProfile object ++ */ ++ @NotNull ++ com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name); + // Paper end + } diff --git a/patches/api-unmapped/0057-Shoulder-Entities-Release-API.patch b/patches/api-unmapped/0057-Shoulder-Entities-Release-API.patch new file mode 100644 index 0000000000..249e81f7ad --- /dev/null +++ b/patches/api-unmapped/0057-Shoulder-Entities-Release-API.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 17 Jun 2017 15:04:51 -0400 +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 72178c3036f567ceaf15016978a9737eb9c4afc4..d212d5123b6294f7873d72f125505a006c290b05 100644 +--- a/src/main/java/org/bukkit/entity/HumanEntity.java ++++ b/src/main/java/org/bukkit/entity/HumanEntity.java +@@ -300,6 +300,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder + */ + public int getExpToLevel(); + ++ // Paper start ++ /** ++ * If there is an Entity on this entities left shoulder, it will be released to the world and returned. ++ * If no Entity is released, null will be returned. ++ * ++ * @return The released entity, or null ++ */ ++ @Nullable ++ public Entity releaseLeftShoulderEntity(); ++ ++ /** ++ * If there is an Entity on this entities left shoulder, it will be released to the world and returned. ++ * If no Entity is released, null will be returned. ++ * ++ * @return The released entity, or null ++ */ ++ @Nullable ++ public Entity releaseRightShoulderEntity(); ++ // Paper end ++ + /** + * Gets the current cooldown for a player's attack. + * diff --git a/patches/api-unmapped/0058-Profile-Lookup-Events.patch b/patches/api-unmapped/0058-Profile-Lookup-Events.patch new file mode 100644 index 0000000000..1cdb35476d --- /dev/null +++ b/patches/api-unmapped/0058-Profile-Lookup-Events.patch @@ -0,0 +1,174 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 17 Jun 2017 16:30:44 -0400 +Subject: [PATCH] Profile Lookup Events + +Adds a Pre Lookup Event and a Post Lookup Event so that plugins may prefill in profile data, and cache the responses from +profiles that had to be looked up. + +diff --git a/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8df37c07cd55ddf110d1dd68183d7b697f7a6756 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java +@@ -0,0 +1,46 @@ ++package com.destroystokyo.paper.event.profile; ++ ++import com.destroystokyo.paper.profile.PlayerProfile; ++import org.bukkit.Bukkit; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++ ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Allows a plugin to be notified anytime AFTER a Profile has been looked up from the Mojang API ++ * This is an opportunity to view the response and potentially cache things. ++ * ++ * No guarantees are made about thread execution context for this event. If you need to know, check ++ * event.isAsync() ++ */ ++public class LookupProfileEvent extends Event { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull private final PlayerProfile profile; ++ ++ public LookupProfileEvent(@NotNull PlayerProfile profile) { ++ super(!Bukkit.isPrimaryThread()); ++ this.profile = profile; ++ } ++ ++ /** ++ * @return The profile that was recently looked up. This profile can be mutated ++ */ ++ @NotNull ++ public PlayerProfile getPlayerProfile() { ++ return profile; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4dcf6242c9acc62d030a94f67b78729ed29f8c85 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java +@@ -0,0 +1,108 @@ ++package com.destroystokyo.paper.event.profile; ++ ++import com.destroystokyo.paper.profile.PlayerProfile; ++import com.destroystokyo.paper.profile.ProfileProperty; ++import com.google.common.collect.ArrayListMultimap; ++import org.bukkit.Bukkit; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++ ++import java.util.HashSet; ++import java.util.Set; ++import java.util.UUID; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Allows a plugin to intercept a Profile Lookup for a Profile by name ++ * ++ * At the point of event fire, the UUID and properties are unset. ++ * ++ * If a plugin sets the UUID, and optionally the properties, the API call to look up the profile may be skipped. ++ * ++ * No guarantees are made about thread execution context for this event. If you need to know, check ++ * event.isAsync() ++ */ ++public class PreLookupProfileEvent extends Event { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ @NotNull private final String name; ++ private UUID uuid; ++ @NotNull private Set properties = new HashSet<>(); ++ ++ public PreLookupProfileEvent(@NotNull String name) { ++ super(!Bukkit.isPrimaryThread()); ++ this.name = name; ++ } ++ ++ /** ++ * @return Name of the profile ++ */ ++ @NotNull ++ public String getName() { ++ return name; ++ } ++ ++ /** ++ * If this value is left null by the completion of the event call, then the server will ++ * trigger a call to the Mojang API to look up the UUID (Network Request), and subsequently, fire a ++ * {@link LookupProfileEvent} ++ * ++ * @return The UUID of the profile if it has already been provided by a plugin ++ */ ++ @Nullable ++ public UUID getUUID() { ++ return uuid; ++ } ++ ++ /** ++ * Sets the UUID for this player name. This will skip the initial API call to find the players UUID. ++ * ++ * However, if Profile Properties are needed by the server, you must also set them or else an API call might still be made. ++ * ++ * @param uuid the UUID to set for the profile or null to reset ++ */ ++ public void setUUID(@Nullable UUID uuid) { ++ this.uuid = uuid; ++ } ++ ++ /** ++ * @return The currently pending prepopulated properties. ++ * Any property in this Set will be automatically prefilled on this Profile ++ */ ++ @NotNull ++ public Set getProfileProperties() { ++ return this.properties; ++ } ++ ++ /** ++ * Clears any existing prepopulated properties and uses the supplied properties ++ * Any property in this Set will be automatically prefilled on this Profile ++ * @param properties The properties to add ++ */ ++ public void setProfileProperties(@NotNull Set properties) { ++ this.properties = new HashSet<>(); ++ this.properties.addAll(properties); ++ } ++ ++ /** ++ * Adds any properties currently missing to the prepopulated properties set, replacing any that already were set. ++ * Any property in this Set will be automatically prefilled on this Profile ++ * @param properties The properties to add ++ */ ++ public void addProfileProperties(@NotNull Set properties) { ++ this.properties.addAll(properties); ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++} diff --git a/patches/api-unmapped/0059-Entity-fromMobSpawner.patch b/patches/api-unmapped/0059-Entity-fromMobSpawner.patch new file mode 100644 index 0000000000..73b4016c92 --- /dev/null +++ b/patches/api-unmapped/0059-Entity-fromMobSpawner.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 18 Jun 2017 18:17:05 -0500 +Subject: [PATCH] Entity#fromMobSpawner() + + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index fdce246aecac775c3ff4a028c307b09762505258..fdc95c87a6020bdcaee5b0b8ab5a996c0e241b33 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -665,5 +665,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + */ + @Nullable + Location getOrigin(); ++ ++ /** ++ * Returns whether this entity was spawned from a mob spawner. ++ * ++ * @return True if entity spawned from a mob spawner ++ */ ++ boolean fromMobSpawner(); + // Paper end + } diff --git a/patches/api-unmapped/0060-Improve-the-Saddle-API-for-Horses.patch b/patches/api-unmapped/0060-Improve-the-Saddle-API-for-Horses.patch new file mode 100644 index 0000000000..85814456bf --- /dev/null +++ b/patches/api-unmapped/0060-Improve-the-Saddle-API-for-Horses.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 10 Dec 2016 16:12:48 -0500 +Subject: [PATCH] Improve the Saddle API for Horses + +Not all horses with Saddles have armor. This lets us break up the horses with saddles +and access their saddle state separately from an interface shared with Armor. + +diff --git a/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java b/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..163ffe8ff76ded6265d865901d5110fb6a56950d +--- /dev/null ++++ b/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java +@@ -0,0 +1,21 @@ ++package org.bukkit.inventory; ++ ++import org.jetbrains.annotations.Nullable; ++ ++public interface ArmoredHorseInventory extends AbstractHorseInventory { ++ ++ /** ++ * Gets the item in the horse's armor slot. ++ * ++ * @return the armor item ++ */ ++ @Nullable ++ ItemStack getArmor(); ++ ++ /** ++ * Sets the item in the horse's armor slot. ++ * ++ * @param stack the new item ++ */ ++ void setArmor(@Nullable ItemStack stack); ++} +diff --git a/src/main/java/org/bukkit/inventory/HorseInventory.java b/src/main/java/org/bukkit/inventory/HorseInventory.java +index 608e99c4207405bf9dd88d44ad8e82eefa19e45c..53498debe4cfb80592ef3025270bc8e5df4a5fec 100644 +--- a/src/main/java/org/bukkit/inventory/HorseInventory.java ++++ b/src/main/java/org/bukkit/inventory/HorseInventory.java +@@ -5,20 +5,4 @@ import org.jetbrains.annotations.Nullable; + /** + * An interface to the inventory of a Horse. + */ +-public interface HorseInventory extends AbstractHorseInventory { +- +- /** +- * Gets the item in the horse's armor slot. +- * +- * @return the armor item +- */ +- @Nullable +- ItemStack getArmor(); +- +- /** +- * Sets the item in the horse's armor slot. +- * +- * @param stack the new item +- */ +- void setArmor(@Nullable ItemStack stack); +-} ++public interface HorseInventory extends AbstractHorseInventory, ArmoredHorseInventory {} +diff --git a/src/main/java/org/bukkit/inventory/LlamaInventory.java b/src/main/java/org/bukkit/inventory/LlamaInventory.java +index 2fa2c9d07ecbafaf2396d913af90f1f4d432b238..5ac1afb8a213fa0fe344db4730ecbc5de6eed445 100644 +--- a/src/main/java/org/bukkit/inventory/LlamaInventory.java ++++ b/src/main/java/org/bukkit/inventory/LlamaInventory.java +@@ -6,7 +6,7 @@ import org.jetbrains.annotations.Nullable; + /** + * An interface to the inventory of a {@link Llama}. + */ +-public interface LlamaInventory extends AbstractHorseInventory { ++public interface LlamaInventory extends SaddledHorseInventory { + + /** + * Gets the item in the llama's decor slot. +diff --git a/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java b/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7944f26a3e2a92601c3be0e55c00c39cc16cf177 +--- /dev/null ++++ b/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java +@@ -0,0 +1,3 @@ ++package org.bukkit.inventory; ++ ++public interface SaddledHorseInventory extends AbstractHorseInventory {} diff --git a/patches/api-unmapped/0061-ensureServerConversions-API.patch b/patches/api-unmapped/0061-ensureServerConversions-API.patch new file mode 100644 index 0000000000..ed64978a06 --- /dev/null +++ b/patches/api-unmapped/0061-ensureServerConversions-API.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 May 2016 23:55:48 -0400 +Subject: [PATCH] ensureServerConversions API + +This will take a Bukkit ItemStack and run it through any conversions a server process would perform on it, +to ensure it meets latest minecraft expectations. + +diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java +index 6cc4bad2ecd19f44a680ff03cbfb99d48ea5c337..42551f8aa6666a6144815b619327c6d8f3c3776b 100644 +--- a/src/main/java/org/bukkit/inventory/ItemFactory.java ++++ b/src/main/java/org/bukkit/inventory/ItemFactory.java +@@ -160,5 +160,17 @@ public interface ItemFactory { + */ + @NotNull + net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); ++ ++ /** ++ * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks. ++ * ++ * Use this method to to ensure any desired data conversions are processed. ++ * The input itemstack will not be the same as the returned itemstack. ++ * ++ * @param item The item to process conversions on ++ * @return A potentially Data Converted ItemStack ++ */ ++ @NotNull ++ ItemStack ensureServerConversions(@NotNull ItemStack item); + // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index a15abec467bac70116a6fc21a300d4930b909f15..f9d226962f16821d07ac80f1bf69cb01a5de2654 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -536,7 +536,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + } + } + +- return result; ++ return result.ensureServerConversions(); // Paper + } + + /** +@@ -611,5 +611,18 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + public @NotNull net.kyori.adventure.text.Component displayName() { + return Bukkit.getServer().getItemFactory().displayName(this); + } ++ ++ /** ++ * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks. ++ * ++ * Use this method to to ensure any desired data conversions are processed. ++ * The input itemstack will not be the same as the returned itemstack. ++ * ++ * @return A potentially Data Converted ItemStack ++ */ ++ @NotNull ++ public ItemStack ensureServerConversions() { ++ return Bukkit.getServer().getItemFactory().ensureServerConversions(this); ++ } + // Paper end + } diff --git a/patches/api-unmapped/0062-Add-getI18NDisplayName-API.patch b/patches/api-unmapped/0062-Add-getI18NDisplayName-API.patch new file mode 100644 index 0000000000..e4dde4f260 --- /dev/null +++ b/patches/api-unmapped/0062-Add-getI18NDisplayName-API.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 May 2016 23:55:48 -0400 +Subject: [PATCH] Add getI18NDisplayName API + +Gets the Display name as seen in the Client. +Currently the server only supports the English language. To override this, +You must replace the language file embedded in the server jar. + +diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java +index 44a858490f4db37f979fd487ed7a5b2b8b7f1a3f..3fd56a95de7d4cbeaf5d8554fbc7127a627cb977 100644 +--- a/src/main/java/org/bukkit/inventory/ItemFactory.java ++++ b/src/main/java/org/bukkit/inventory/ItemFactory.java +@@ -172,5 +172,16 @@ public interface ItemFactory { + */ + @NotNull + ItemStack ensureServerConversions(@NotNull ItemStack item); ++ ++ /** ++ * Gets the Display name as seen in the Client. ++ * Currently the server only supports the English language. To override this, ++ * You must replace the language file embedded in the server jar. ++ * ++ * @param item Item to return Display name of ++ * @return Display name of Item ++ */ ++ @Nullable ++ String getI18NDisplayName(@Nullable ItemStack item); + // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index 47d8611221967d32b654ddac0fbf0e405ef62352..82bd3e6701dbd7df9f0f8c3801c5ae1baba4eec5 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -624,5 +624,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + public ItemStack ensureServerConversions() { + return Bukkit.getServer().getItemFactory().ensureServerConversions(this); + } ++ ++ /** ++ * Gets the Display name as seen in the Client. ++ * Currently the server only supports the English language. To override this, ++ * You must replace the language file embedded in the server jar. ++ * ++ * @return Display name of Item ++ */ ++ @Nullable ++ public String getI18NDisplayName() { ++ return Bukkit.getServer().getItemFactory().getI18NDisplayName(this); ++ } + // Paper end + } diff --git a/patches/api-unmapped/0063-ProfileWhitelistVerifyEvent.patch b/patches/api-unmapped/0063-ProfileWhitelistVerifyEvent.patch new file mode 100644 index 0000000000..ff996377f4 --- /dev/null +++ b/patches/api-unmapped/0063-ProfileWhitelistVerifyEvent.patch @@ -0,0 +1,157 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 3 Jul 2017 18:11:34 -0500 +Subject: [PATCH] ProfileWhitelistVerifyEvent + +Fires when the server is validating if a player is whitelisted. + +Allows you to do dynamic whitelisting and change of kick message + +diff --git a/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8a259ab49ea79673b6da9e4e2aaecec67469994e +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java +@@ -0,0 +1,142 @@ ++/* ++ * Copyright (c) 2017 - Daniel Ennis (Aikar) - MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package com.destroystokyo.paper.event.profile; ++ ++import com.destroystokyo.paper.profile.PlayerProfile; ++import net.kyori.adventure.text.Component; ++import org.bukkit.Bukkit; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Fires when the server needs to verify if a player is whitelisted. ++ * ++ * Plugins may override/control the servers whitelist with this event, ++ * and dynamically change the kick message. ++ */ ++public class ProfileWhitelistVerifyEvent extends Event { ++ private static final HandlerList handlers = new HandlerList(); ++ @NotNull private final PlayerProfile profile; ++ private final boolean whitelistEnabled; ++ private boolean whitelisted; ++ private final boolean isOp; ++ @Nullable private Component kickMessage; ++ ++ @Deprecated ++ public ProfileWhitelistVerifyEvent(@NotNull final PlayerProfile profile, boolean whitelistEnabled, boolean whitelisted, boolean isOp, @Nullable String kickMessage) { ++ this(profile, whitelistEnabled, whitelisted, isOp, kickMessage == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickMessage)); ++ } ++ ++ public ProfileWhitelistVerifyEvent(@NotNull final PlayerProfile profile, boolean whitelistEnabled, boolean whitelisted, boolean isOp, @Nullable Component kickMessage) { ++ this.profile = profile; ++ this.whitelistEnabled = whitelistEnabled; ++ this.whitelisted = whitelisted; ++ this.isOp = isOp; ++ this.kickMessage = kickMessage; ++ } ++ ++ /** ++ * @return the currently planned message to send to the user if they are not whitelisted ++ * @deprecated use {@link #kickMessage()} ++ */ ++ @Deprecated ++ @Nullable ++ public String getKickMessage() { ++ return this.kickMessage == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().serialize(kickMessage); ++ } ++ ++ /** ++ * @param kickMessage The message to send to the player on kick if not whitelisted. May set to null to use the server configured default ++ * @deprecated Use {@link #kickMessage(Component)} ++ */ ++ @Deprecated ++ public void setKickMessage(@Nullable String kickMessage) { ++ this.kickMessage(kickMessage == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickMessage)); ++ } ++ ++ /** ++ * @return the currently planned message to send to the user if they are not whitelisted ++ */ ++ @Nullable ++ public Component kickMessage() { ++ return this.kickMessage; ++ } ++ ++ /** ++ * @param kickMessage The message to send to the player on kick if not whitelisted. May set to null to use the server configured default ++ */ ++ public void kickMessage(@Nullable Component kickMessage) { ++ this.kickMessage = kickMessage; ++ } ++ ++ /** ++ * @return The profile of the player trying to connect ++ */ ++ @NotNull ++ public PlayerProfile getPlayerProfile() { ++ return profile; ++ } ++ ++ /** ++ * @return Whether the player is whitelisted to play on this server (whitelist may be off is why its true) ++ */ ++ public boolean isWhitelisted() { ++ return whitelisted; ++ } ++ ++ /** ++ * Changes the players whitelisted state. false will deny the login ++ * @param whitelisted The new whitelisted state ++ */ ++ public void setWhitelisted(boolean whitelisted) { ++ this.whitelisted = whitelisted; ++ } ++ ++ /** ++ * @return if the player obtained whitelist status by having op ++ */ ++ public boolean isOp() { ++ return isOp; ++ } ++ ++ /** ++ * @return if the server even has whitelist on ++ */ ++ public boolean isWhitelistEnabled() { ++ return whitelistEnabled; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0064-Make-plugins-list-alphabetical.patch b/patches/api-unmapped/0064-Make-plugins-list-alphabetical.patch new file mode 100644 index 0000000000..ec1fc9814a --- /dev/null +++ b/patches/api-unmapped/0064-Make-plugins-list-alphabetical.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 31 Jul 2017 02:08:55 -0500 +Subject: [PATCH] Make /plugins list alphabetical + + +diff --git a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java +index bcb576a4271b1ec7b1cfe6f83cf161b7d89ed2e5..4de959bbd1270d7d6ea8e5e69521bcca6abe2138 100644 +--- a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java +@@ -3,6 +3,9 @@ package org.bukkit.command.defaults; + import java.util.Arrays; + import java.util.Collections; + import java.util.List; ++import java.util.Map; ++import java.util.TreeMap; ++ + import org.bukkit.Bukkit; + import org.bukkit.ChatColor; + import org.bukkit.command.CommandSender; +@@ -34,15 +37,22 @@ public class PluginsCommand extends BukkitCommand { + + @NotNull + private String getPluginList() { +- StringBuilder pluginList = new StringBuilder(); +- Plugin[] plugins = Bukkit.getPluginManager().getPlugins(); ++ // Paper start ++ TreeMap plugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); ++ ++ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { ++ plugins.put(plugin.getDescription().getName(), plugin); ++ } + +- for (Plugin plugin : plugins) { ++ StringBuilder pluginList = new StringBuilder(); ++ for (Map.Entry entry : plugins.entrySet()) { + if (pluginList.length() > 0) { + pluginList.append(ChatColor.WHITE); + pluginList.append(", "); + } + ++ Plugin plugin = entry.getValue(); ++ + pluginList.append(plugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED); + pluginList.append(plugin.getDescription().getName()); + +@@ -51,6 +61,8 @@ public class PluginsCommand extends BukkitCommand { + } + } + +- return "(" + plugins.length + "): " + pluginList.toString(); ++ return "(" + plugins.size() + "): " + pluginList.toString(); ++ // Paper end + } ++ + } diff --git a/patches/api-unmapped/0065-LivingEntity-setKiller.patch b/patches/api-unmapped/0065-LivingEntity-setKiller.patch new file mode 100644 index 0000000000..b7b93870eb --- /dev/null +++ b/patches/api-unmapped/0065-LivingEntity-setKiller.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 31 Jul 2017 01:49:43 -0500 +Subject: [PATCH] LivingEntity#setKiller + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 45e9f585c3e522ecf94a6bc42cdc190e1a191a5c..33fffda7c8b05cde3c95623937e7eb6c8b628ec6 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -279,6 +279,15 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + @Nullable + public Player getKiller(); + ++ // Paper start ++ /** ++ * Sets the player identified as the killer of the living entity. ++ * ++ * @param killer player ++ */ ++ public void setKiller(@Nullable Player killer); ++ // Paper end ++ + /** + * Adds the given {@link PotionEffect} to the living entity. + * diff --git a/patches/api-unmapped/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch b/patches/api-unmapped/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch new file mode 100644 index 0000000000..a1273c87c6 --- /dev/null +++ b/patches/api-unmapped/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Thu, 21 Sep 2017 16:14:13 +0200 +Subject: [PATCH] Handle plugin prefixes in implementation logging + configuration + +Currently, plugin prefixes are prepended to the log message in +the PluginLogger before passing the message to the underlying +logging framework. This is bad design because they need to be +stripped manually when using custom appenders to log messages +in a different format. + +Additionally, it makes integration of alternative logging APIs hard +because all logging must go through the PluginLogger. Avoid using +PluginLogger and create a regular logger using the plugin name. +The implementation should handle plugin prefixes by displaying +logger names when appropriate. + +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +index 2231900549607a0917dd04e8b433c027b846cef9..bb2e55e97bf887a28cac7d4f9a0a23960d22cf56 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +@@ -42,7 +42,7 @@ public abstract class JavaPlugin extends PluginBase { + private boolean naggable = true; + private FileConfiguration newConfig = null; + private File configFile = null; +- private PluginLogger logger = null; ++ private Logger logger = null; // Paper - PluginLogger -> Logger + + public JavaPlugin() { + final ClassLoader classLoader = this.getClass().getClassLoader(); +@@ -276,7 +276,8 @@ public abstract class JavaPlugin extends PluginBase { + this.dataFolder = dataFolder; + this.classLoader = classLoader; + this.configFile = new File(dataFolder, "config.yml"); +- this.logger = new PluginLogger(this); ++ // Paper - Handle plugin prefix in implementation ++ this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); + } + + /** diff --git a/patches/api-unmapped/0067-Allow-plugins-to-use-SLF4J-for-logging.patch b/patches/api-unmapped/0067-Allow-plugins-to-use-SLF4J-for-logging.patch new file mode 100644 index 0000000000..58225ea7be --- /dev/null +++ b/patches/api-unmapped/0067-Allow-plugins-to-use-SLF4J-for-logging.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Thu, 21 Sep 2017 16:33:12 +0200 +Subject: [PATCH] Allow plugins to use SLF4J for logging + +SLF4J is a commonly used abstraction for various logging frameworks +such as java.util.logging (JUL) or Log4j. Currently, plugins are +required to do all their logging using the provided JUL logger. +This is annoying for plugins that target multiple platforms or when +using libraries that log messages using SLF4J. + +Expose SLF4J as optional logging API for plugins, so they can use +it without having to shade it in the plugin and going through +several layers of logging abstraction. + +diff --git a/pom.xml b/pom.xml +index 2c757ffb2253748c6a81f9b373290108209b6ff2..8cf6e1f78d4c1ae388bb478700d5dceaab65c4e7 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -144,6 +144,13 @@ + 21.0.1 + provided + ++ ++ ++ org.slf4j ++ slf4j-api ++ 1.7.25 ++ compile ++ + + + junit +diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java +index febfec6efafd76bb59b4b43aa223af16f73339b4..79890c68f1ad31f951dfdbd9a16dac500ec58c40 100644 +--- a/src/main/java/org/bukkit/plugin/Plugin.java ++++ b/src/main/java/org/bukkit/plugin/Plugin.java +@@ -166,6 +166,13 @@ public interface Plugin extends TabExecutor { + @NotNull + public Logger getLogger(); + ++ // Paper start - Add SLF4J logger ++ @NotNull ++ default org.slf4j.Logger getSLF4JLogger() { ++ return org.slf4j.LoggerFactory.getLogger(getLogger().getName()); ++ } ++ // Paper end ++ + /** + * Returns the name of the plugin. + *

    diff --git a/patches/api-unmapped/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/patches/api-unmapped/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch new file mode 100644 index 0000000000..47b6099ab7 --- /dev/null +++ b/patches/api-unmapped/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Thu, 21 Sep 2017 19:41:20 +0200 +Subject: [PATCH] Add workaround for plugins modifying the parent of the plugin + logger + +Essentials uses a custom logger name ("Essentials") instead of the +plugin logger. Log messages are redirected to the plugin logger by +setting the parent of the "Essentials" logger to the plugin logger. + +With our changes, the plugin logger is now also called "Essentials", +resulting in an infinite loop. Make sure plugins can't change the +parent of the plugin logger to avoid this. + +diff --git a/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java +new file mode 100644 +index 0000000000000000000000000000000000000000..76f2cb9cd99cad2a9484eab2becd8c36f1dd91b3 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.utils; ++ ++import org.bukkit.plugin.PluginDescriptionFile; ++ ++import java.util.logging.Level; ++import java.util.logging.LogManager; ++import java.util.logging.Logger; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Prevents plugins (e.g. Essentials) from changing the parent of the plugin logger. ++ */ ++public class PaperPluginLogger extends Logger { ++ ++ @NotNull ++ public static Logger getLogger(@NotNull PluginDescriptionFile description) { ++ Logger logger = new PaperPluginLogger(description); ++ if (!LogManager.getLogManager().addLogger(logger)) { ++ // Disable this if it's going to happen across reloads anyways... ++ //logger.log(Level.WARNING, "Could not insert plugin logger - one was already found: {}", LogManager.getLogManager().getLogger(this.getName())); ++ logger = LogManager.getLogManager().getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); ++ } ++ ++ return logger; ++ } ++ ++ private PaperPluginLogger(@NotNull PluginDescriptionFile description) { ++ super(description.getPrefix() != null ? description.getPrefix() : description.getName(), null); ++ } ++ ++ @Override ++ public void setParent(@NotNull Logger parent) { ++ if (getParent() != null) { ++ warning("Ignoring attempt to change parent of plugin logger"); ++ } else { ++ this.log(Level.FINE, "Setting plugin logger parent to {0}", parent); ++ super.setParent(parent); ++ } ++ } ++ ++} +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +index bb2e55e97bf887a28cac7d4f9a0a23960d22cf56..04fa3991f6ce4e9dad804f28fc6c947695857089 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +@@ -42,7 +42,7 @@ public abstract class JavaPlugin extends PluginBase { + private boolean naggable = true; + private FileConfiguration newConfig = null; + private File configFile = null; +- private Logger logger = null; // Paper - PluginLogger -> Logger ++ Logger logger = null; // Paper - PluginLogger -> Logger, package-private + + public JavaPlugin() { + final ClassLoader classLoader = this.getClass().getClassLoader(); +@@ -276,8 +276,11 @@ public abstract class JavaPlugin extends PluginBase { + this.dataFolder = dataFolder; + this.classLoader = classLoader; + this.configFile = new File(dataFolder, "config.yml"); +- // Paper - Handle plugin prefix in implementation +- this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); ++ // Paper start ++ if (this.logger == null) { ++ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(this.description); ++ } ++ // Paper end + } + + /** +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index 13100c688bfccb826b3072aaa92901f8634cf9ab..b9766b9b47547c400ed075f1635bb1461cb5e860 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -44,6 +44,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + private JavaPlugin pluginInit; + private IllegalStateException pluginState; + private final Set seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>()); ++ private java.util.logging.Logger logger; // Paper - add field + + static { + ClassLoader.registerAsParallelCapable(); +@@ -62,6 +63,8 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + this.url = file.toURI().toURL(); + this.libraryLoader = libraryLoader; + ++ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(description); // Paper - Register logger early ++ + try { + Class jarClass; + try { +@@ -222,6 +225,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + pluginState = new IllegalStateException("Initial initialization"); + this.pluginInit = javaPlugin; + ++ javaPlugin.logger = this.logger; // Paper - set logger + javaPlugin.init(loader, loader.server, description, dataFolder, file, this); + } + } diff --git a/patches/api-unmapped/0069-Add-PlayerJumpEvent.patch b/patches/api-unmapped/0069-Add-PlayerJumpEvent.patch new file mode 100644 index 0000000000..18f2c35b4d --- /dev/null +++ b/patches/api-unmapped/0069-Add-PlayerJumpEvent.patch @@ -0,0 +1,118 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 28 Sep 2017 17:21:32 -0400 +Subject: [PATCH] Add PlayerJumpEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..289a0d784a3c74caf8a7231b4dd166096b1849a1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java +@@ -0,0 +1,106 @@ ++package com.destroystokyo.paper.event.player; ++ ++import com.google.common.base.Preconditions; ++import org.bukkit.Location; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when the server detects the player is jumping. ++ *

    ++ * Added to avoid the overhead and special case logic that many plugins use ++ * when checking for jumps via PlayerMoveEvent, this event is fired whenever ++ * the server detects that the player is jumping. ++ */ ++public class PlayerJumpEvent extends PlayerEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancel = false; ++ @NotNull private Location from; ++ @NotNull private Location to; ++ ++ public PlayerJumpEvent(@NotNull final Player player, @NotNull final Location from, @NotNull final Location to) { ++ super(player); ++ this.from = from; ++ this.to = to; ++ } ++ ++ /** ++ * Gets the cancellation state of this event. A cancelled event will not ++ * be executed in the server, but will still pass to other plugins ++ *

    ++ * If a jump event is cancelled, the player will be moved or ++ * teleported back to the Location as defined by getFrom(). This will not ++ * fire an event ++ * ++ * @return true if this event is cancelled ++ */ ++ public boolean isCancelled() { ++ return cancel; ++ } ++ ++ /** ++ * Sets the cancellation state of this event. A cancelled event will not ++ * be executed in the server, but will still pass to other plugins ++ *

    ++ * If a jump event is cancelled, the player will be moved or ++ * teleported back to the Location as defined by getFrom(). This will not ++ * fire an event ++ * ++ * @param cancel true if you wish to cancel this event ++ */ ++ public void setCancelled(boolean cancel) { ++ this.cancel = cancel; ++ } ++ ++ /** ++ * Gets the location this player jumped from ++ * ++ * @return Location the player jumped from ++ */ ++ @NotNull ++ public Location getFrom() { ++ return from; ++ } ++ ++ /** ++ * Sets the location to mark as where the player jumped from ++ * ++ * @param from New location to mark as the players previous location ++ */ ++ public void setFrom(@NotNull Location from) { ++ validateLocation(from); ++ this.from = from; ++ } ++ ++ /** ++ * Gets the location this player jumped to ++ * ++ * This information is based on what the client sends, it typically ++ * has little relation to the arc of the jump at any given point. ++ * ++ * @return Location the player jumped to ++ */ ++ @NotNull ++ public Location getTo() { ++ return to; ++ } ++ ++ private void validateLocation(Location loc) { ++ Preconditions.checkArgument(loc != null, "Cannot use null location!"); ++ Preconditions.checkArgument(loc.getWorld() != null, "Cannot use location with null world!"); ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0070-Expose-client-protocol-version-and-virtual-host.patch b/patches/api-unmapped/0070-Expose-client-protocol-version-and-virtual-host.patch new file mode 100644 index 0000000000..ff8f83ac14 --- /dev/null +++ b/patches/api-unmapped/0070-Expose-client-protocol-version-and-virtual-host.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Tue, 10 Oct 2017 18:44:42 +0200 +Subject: [PATCH] Expose client protocol version and virtual host + +Add a NetworkClient interface that provides access to: + - The socket address + - The protocol version + - The virtual host (the hostname/port the client used to connect + to the server) + +diff --git a/src/main/java/com/destroystokyo/paper/network/NetworkClient.java b/src/main/java/com/destroystokyo/paper/network/NetworkClient.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7b2af1bd72dfbcf4e962a982940fc49b851aa04f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/NetworkClient.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.network; ++ ++import java.net.InetSocketAddress; ++ ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Represents a client connected to the server. ++ */ ++public interface NetworkClient { ++ ++ /** ++ * Returns the socket address of the client. ++ * ++ * @return The client's socket address ++ */ ++ @NotNull ++ InetSocketAddress getAddress(); ++ ++ /** ++ * Returns the protocol version of the client. ++ * ++ * @return The client's protocol version, or {@code -1} if unknown ++ * @see List of protocol ++ * version numbers ++ */ ++ int getProtocolVersion(); ++ ++ /** ++ * Returns the virtual host the client is connected to. ++ * ++ *

    The virtual host refers to the hostname/port the client used to ++ * connect to the server.

    ++ * ++ * @return The client's virtual host, or {@code null} if unknown ++ */ ++ @Nullable ++ InetSocketAddress getVirtualHost(); ++ ++} +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 9cf7adf244335ac7dccbdf11f605a8c6910f7414..04f1a6513711dde8576c9b5c2b04619c56b48d8a 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a player, connected or not + */ +-public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified { // Paper ++public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, com.destroystokyo.paper.network.NetworkClient { // Paper + + // Paper start + @Override diff --git a/patches/api-unmapped/0071-Add-PlayerArmorChangeEvent.patch b/patches/api-unmapped/0071-Add-PlayerArmorChangeEvent.patch new file mode 100644 index 0000000000..4e9d795db3 --- /dev/null +++ b/patches/api-unmapped/0071-Add-PlayerArmorChangeEvent.patch @@ -0,0 +1,149 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: pkt77 +Date: Fri, 10 Nov 2017 23:45:59 -0500 +Subject: [PATCH] Add PlayerArmorChangeEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e406ce639a2e88b78f82f25e71678a669d0a958b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java +@@ -0,0 +1,137 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.Material; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.ItemStack; ++ ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.HashSet; ++import java.util.Set; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import static org.bukkit.Material.*; ++ ++/** ++ * Called when the player themselves change their armor items ++ *

    ++ * Not currently called for environmental factors though it MAY BE IN THE FUTURE ++ */ ++public class PlayerArmorChangeEvent extends PlayerEvent { ++ private static final HandlerList HANDLERS = new HandlerList(); ++ ++ @NotNull private final SlotType slotType; ++ @Nullable private final ItemStack oldItem; ++ @Nullable private final ItemStack newItem; ++ ++ public PlayerArmorChangeEvent(@NotNull Player player, @NotNull SlotType slotType, @Nullable ItemStack oldItem, @Nullable ItemStack newItem) { ++ super(player); ++ this.slotType = slotType; ++ this.oldItem = oldItem; ++ this.newItem = newItem; ++ } ++ ++ /** ++ * Gets the type of slot being altered. ++ * ++ * @return type of slot being altered ++ */ ++ @NotNull ++ public SlotType getSlotType() { ++ return this.slotType; ++ } ++ ++ /** ++ * Gets the existing item that's being replaced ++ * ++ * @return old item ++ */ ++ @Nullable ++ public ItemStack getOldItem() { ++ return this.oldItem; ++ } ++ ++ /** ++ * Gets the new item that's replacing the old ++ * ++ * @return new item ++ */ ++ @Nullable ++ public ItemStack getNewItem() { ++ return this.newItem; ++ } ++ ++ @Override ++ public String toString() { ++ return "ArmorChangeEvent{" + "player=" + player + ", slotType=" + slotType + ", oldItem=" + oldItem + ", newItem=" + newItem + '}'; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLERS; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLERS; ++ } ++ ++ public enum SlotType { ++ HEAD(NETHERITE_HELMET, DIAMOND_HELMET, GOLDEN_HELMET, IRON_HELMET, CHAINMAIL_HELMET, LEATHER_HELMET, CARVED_PUMPKIN, PLAYER_HEAD, SKELETON_SKULL, ZOMBIE_HEAD, CREEPER_HEAD, WITHER_SKELETON_SKULL, TURTLE_HELMET), ++ CHEST(NETHERITE_CHESTPLATE, DIAMOND_CHESTPLATE, GOLDEN_CHESTPLATE, IRON_CHESTPLATE, CHAINMAIL_CHESTPLATE, LEATHER_CHESTPLATE, ELYTRA), ++ LEGS(NETHERITE_LEGGINGS, DIAMOND_LEGGINGS, GOLDEN_LEGGINGS, IRON_LEGGINGS, CHAINMAIL_LEGGINGS, LEATHER_LEGGINGS), ++ FEET(NETHERITE_BOOTS, DIAMOND_BOOTS, GOLDEN_BOOTS, IRON_BOOTS, CHAINMAIL_BOOTS, LEATHER_BOOTS); ++ ++ private final Set mutableTypes = new HashSet<>(); ++ private Set immutableTypes; ++ ++ SlotType(Material... types) { ++ this.mutableTypes.addAll(Arrays.asList(types)); ++ } ++ ++ /** ++ * Gets an immutable set of all allowed material types that can be placed in an ++ * armor slot. ++ * ++ * @return immutable set of material types ++ */ ++ @NotNull ++ public Set getTypes() { ++ if (immutableTypes == null) { ++ immutableTypes = Collections.unmodifiableSet(mutableTypes); ++ } ++ ++ return immutableTypes; ++ } ++ ++ /** ++ * Gets the type of slot via the specified material ++ * ++ * @param material material to get slot by ++ * @return slot type the material will go in, or null if it won't ++ */ ++ @Nullable ++ public static SlotType getByMaterial(@NotNull Material material) { ++ for (SlotType slotType : values()) { ++ if (slotType.getTypes().contains(material)) { ++ return slotType; ++ } ++ } ++ return null; ++ } ++ ++ /** ++ * Gets whether or not this material can be equipped to a slot ++ * ++ * @param material material to check ++ * @return whether or not this material can be equipped ++ */ ++ public static boolean isEquipable(@NotNull Material material) { ++ return getByMaterial(material) != null; ++ } ++ } ++} diff --git a/patches/api-unmapped/0072-API-to-get-a-BlockState-without-a-snapshot.patch b/patches/api-unmapped/0072-API-to-get-a-BlockState-without-a-snapshot.patch new file mode 100644 index 0000000000..9d4f264793 --- /dev/null +++ b/patches/api-unmapped/0072-API-to-get-a-BlockState-without-a-snapshot.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 6 Nov 2017 21:10:01 -0500 +Subject: [PATCH] API to get a BlockState without a snapshot + +This allows you to get a BlockState without creating a snapshot, operating +on the real tile entity. + +This is useful for where performance is needed + +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index 0cfad6f84eda6f7bfa1fae041341ccb1021b157d..e89c8079625525667f496c06207da655fe43d749 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -269,6 +269,16 @@ public interface Block extends Metadatable { + @NotNull + BlockState getState(); + ++ // Paper start ++ /** ++ * @see #getState() optionally disables use of snapshot, to operate on real block data ++ * @param useSnapshot if this block is a TE, should we create a fully copy of the TileEntity ++ * @return BlockState with the current state of this block ++ */ ++ @NotNull ++ BlockState getState(boolean useSnapshot); ++ // Paper end ++ + /** + * Returns the biome that this block resides in + * diff --git a/patches/api-unmapped/0073-AsyncTabCompleteEvent.patch b/patches/api-unmapped/0073-AsyncTabCompleteEvent.patch new file mode 100644 index 0000000000..e86dd9b401 --- /dev/null +++ b/patches/api-unmapped/0073-AsyncTabCompleteEvent.patch @@ -0,0 +1,266 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 26 Nov 2017 13:17:09 -0500 +Subject: [PATCH] AsyncTabCompleteEvent + +Let plugins be able to control tab completion of commands and chat async. + +This will be useful for frameworks like ACF so we can define async safe completion handlers, +and avoid going to main for tab completions. + +Especially useful if you need to query a database in order to obtain the results for tab +completion, such as offline players. + +diff --git a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..619ed37169c126a8c75d02699a04728bac49d10d +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java +@@ -0,0 +1,177 @@ ++/* ++ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package com.destroystokyo.paper.event.server; ++ ++import com.google.common.collect.ImmutableList; ++import org.apache.commons.lang.Validate; ++import org.bukkit.Location; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++ ++import java.util.ArrayList; ++import java.util.List; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Allows plugins to compute tab completion results asynchronously. If this event provides completions, then the standard synchronous process will not be fired to populate the results. However, the synchronous TabCompleteEvent will fire with the Async results. ++ * ++ * Only 1 process will be allowed to provide completions, the Async Event, or the standard process. ++ */ ++public class AsyncTabCompleteEvent extends Event implements Cancellable { ++ @NotNull private final CommandSender sender; ++ @NotNull private final String buffer; ++ private final boolean isCommand; ++ @Nullable ++ private final Location loc; ++ @NotNull private List completions; ++ private boolean cancelled; ++ private boolean handled = false; ++ private boolean fireSyncHandler = true; ++ ++ public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull List completions, @NotNull String buffer, boolean isCommand, @Nullable Location loc) { ++ super(true); ++ this.sender = sender; ++ this.completions = completions; ++ this.buffer = buffer; ++ this.isCommand = isCommand; ++ this.loc = loc; ++ } ++ ++ /** ++ * Get the sender completing this command. ++ * ++ * @return the {@link CommandSender} instance ++ */ ++ @NotNull ++ public CommandSender getSender() { ++ return sender; ++ } ++ ++ /** ++ * The list of completions which will be offered to the sender, in order. ++ * This list is mutable and reflects what will be offered. ++ * ++ * If this collection is not empty after the event is fired, then ++ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} ++ * or current player names will not be called. ++ * ++ * @return a list of offered completions ++ */ ++ @NotNull ++ public List getCompletions() { ++ return completions; ++ } ++ ++ /** ++ * Set the completions offered, overriding any already set. ++ * If this collection is not empty after the event is fired, then ++ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} ++ * or current player names will not be called. ++ * ++ * The passed collection will be cloned to a new List. You must call {{@link #getCompletions()}} to mutate from here ++ * ++ * @param completions the new completions ++ */ ++ public void setCompletions(@NotNull List completions) { ++ Validate.notNull(completions); ++ this.completions = new ArrayList<>(completions); ++ } ++ ++ /** ++ * Return the entire buffer which formed the basis of this completion. ++ * ++ * @return command buffer, as entered ++ */ ++ @NotNull ++ public String getBuffer() { ++ return buffer; ++ } ++ ++ /** ++ * @return True if it is a command being tab completed, false if it is a chat message. ++ */ ++ public boolean isCommand() { ++ return isCommand; ++ } ++ ++ /** ++ * @return The position looked at by the sender, or null if none ++ */ ++ @Nullable ++ public Location getLocation() { ++ return loc; ++ } ++ ++ /** ++ * If true, the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} ++ * or current player names will not be called. ++ * ++ * @return Is completions considered handled. Always true if completions is not empty. ++ */ ++ public boolean isHandled() { ++ return !completions.isEmpty() || handled; ++ } ++ ++ /** ++ * Sets whether or not to consider the completion request handled. ++ * If true, the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} ++ * or current player names will not be called. ++ * ++ * @param handled if this completion should be marked as being handled ++ */ ++ public void setHandled(boolean handled) { ++ this.handled = handled; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * Will provide no completions, and will not fire the synchronous process ++ * @param cancelled true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancelled) { ++ this.cancelled = cancelled; ++ } ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java +index d1a9956a1573dab54c5ff2e5d67ca86cfe1dc01a..f96c4ba53ab41ea66d4f9a4d54eeabb63f992b58 100644 +--- a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java ++++ b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java +@@ -1,5 +1,6 @@ + package org.bukkit.event.server; + ++import java.util.ArrayList; + import java.util.List; + import org.apache.commons.lang.Validate; + import org.bukkit.command.CommandSender; +@@ -8,6 +9,7 @@ import org.bukkit.event.Event; + import org.bukkit.event.HandlerList; + import org.bukkit.event.player.PlayerCommandSendEvent; + import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; + + /** + * Called when a {@link CommandSender} of any description (ie: player or +@@ -29,6 +31,13 @@ public class TabCompleteEvent extends Event implements Cancellable { + private boolean cancelled; + + public TabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, @NotNull List completions) { ++ // Paper start ++ this(sender, buffer, completions, sender instanceof org.bukkit.command.ConsoleCommandSender || buffer.startsWith("/"), null); ++ } ++ public TabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, @NotNull List completions, boolean isCommand, @Nullable org.bukkit.Location location) { ++ this.isCommand = isCommand; ++ this.loc = location; ++ // Paper end + Validate.notNull(sender, "sender"); + Validate.notNull(buffer, "buffer"); + Validate.notNull(completions, "completions"); +@@ -69,14 +78,35 @@ public class TabCompleteEvent extends Event implements Cancellable { + return completions; + } + ++ // Paper start ++ private final boolean isCommand; ++ private final org.bukkit.Location loc; ++ /** ++ * @return True if it is a command being tab completed, false if it is a chat message. ++ */ ++ public boolean isCommand() { ++ return isCommand; ++ } ++ ++ /** ++ * @return The position looked at by the sender, or null if none ++ */ ++ @Nullable ++ public org.bukkit.Location getLocation() { ++ return loc; ++ } ++ // Paper end ++ + /** + * Set the completions offered, overriding any already set. + * ++ * The passed collection will be cloned to a new List. You must call {{@link #getCompletions()}} to mutate from here ++ * + * @param completions the new completions + */ + public void setCompletions(@NotNull List completions) { + Validate.notNull(completions); +- this.completions = completions; ++ this.completions = new ArrayList<>(completions); // Paper + } + + @Override diff --git a/patches/api-unmapped/0074-Display-warning-on-deprecated-recipe-API.patch b/patches/api-unmapped/0074-Display-warning-on-deprecated-recipe-API.patch new file mode 100644 index 0000000000..2b6c78a2c4 --- /dev/null +++ b/patches/api-unmapped/0074-Display-warning-on-deprecated-recipe-API.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 9 Dec 2017 12:40:25 -0500 +Subject: [PATCH] Display warning on deprecated recipe API + +Any plugin still using this API will result in the server saving an inconsistent UUID to player data files, +which then triggers warnings such as "Tried to load unrecognized recipe: bukkit:9e5b92f5-e549-4f47-b0a8-9f89390ed77b removed now." +on the players login. + +Plugin authors need to define a key to keep it consistent between server restarts. + +diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java +index d74b3114f535e1e5e36ae007f1fe0522916a0362..d742c4058ba9aed4fbe1591fd755a06608b06e98 100644 +--- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java ++++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java +@@ -25,6 +25,7 @@ public class ShapedRecipe implements Recipe, Keyed { + public ShapedRecipe(@NotNull ItemStack result) { + Preconditions.checkArgument(result.getType() != Material.AIR, "Recipe must have non-AIR result."); + this.key = NamespacedKey.randomKey(); ++ new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace(); + this.output = new ItemStack(result); + } + +diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java +index 68447fb8c12356e779b96ec98c54119045046751..84062dd719cb8a6142dc8c806777cb208c6b42b2 100644 +--- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java ++++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java +@@ -26,6 +26,7 @@ public class ShapelessRecipe implements Recipe, Keyed { + public ShapelessRecipe(@NotNull ItemStack result) { + Preconditions.checkArgument(result.getType() != Material.AIR, "Recipe must have non-AIR result."); + this.key = NamespacedKey.randomKey(); ++ new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace(); + this.output = new ItemStack(result); + } + diff --git a/patches/api-unmapped/0075-PlayerPickupExperienceEvent.patch b/patches/api-unmapped/0075-PlayerPickupExperienceEvent.patch new file mode 100644 index 0000000000..906a8ec7c3 --- /dev/null +++ b/patches/api-unmapped/0075-PlayerPickupExperienceEvent.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 22:00:41 -0500 +Subject: [PATCH] PlayerPickupExperienceEvent + +Allows plugins to cancel a player picking up an experience orb + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f7beb22d5105157940b39efe594ace9d4cb153f5 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.entity.ExperienceOrb; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when a player is attempting to pick up an experience orb ++ */ ++public class PlayerPickupExperienceEvent extends PlayerEvent implements Cancellable { ++ @NotNull private final ExperienceOrb experienceOrb; ++ ++ public PlayerPickupExperienceEvent(@NotNull Player player, @NotNull ExperienceOrb experienceOrb) { ++ super(player); ++ this.experienceOrb = experienceOrb; ++ } ++ ++ /** ++ * @return Returns the Orb that the player is picking up ++ */ ++ @NotNull ++ public ExperienceOrb getExperienceOrb() { ++ return experienceOrb; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * If true, Cancels picking up the experience orb, leaving it in the world ++ * @param cancel true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0076-ExperienceOrbMergeEvent.patch b/patches/api-unmapped/0076-ExperienceOrbMergeEvent.patch new file mode 100644 index 0000000000..3a4722a776 --- /dev/null +++ b/patches/api-unmapped/0076-ExperienceOrbMergeEvent.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 22:56:24 -0500 +Subject: [PATCH] ExperienceOrbMergeEvent + +Fired when the server is about to merge 2 experience orbs +Plugins can cancel this if they want to ensure experience orbs do not lose important +metadata such as spawn reason, or conditionally move data from source to target. + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0ce3e397716c28c30ed05e153babd0bfb9dd354a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java +@@ -0,0 +1,87 @@ ++/* ++ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.ExperienceOrb; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired anytime the server is about to merge 2 experience orbs into one ++ */ ++public class ExperienceOrbMergeEvent extends EntityEvent implements Cancellable { ++ @NotNull private final ExperienceOrb mergeTarget; ++ @NotNull private final ExperienceOrb mergeSource; ++ ++ public ExperienceOrbMergeEvent(@NotNull ExperienceOrb mergeTarget, @NotNull ExperienceOrb mergeSource) { ++ super(mergeTarget); ++ this.mergeTarget = mergeTarget; ++ this.mergeSource = mergeSource; ++ } ++ ++ /** ++ * @return The orb that will absorb the other experience orb ++ */ ++ @NotNull ++ public ExperienceOrb getMergeTarget() { ++ return mergeTarget; ++ } ++ ++ /** ++ * @return The orb that is subject to being removed and merged into the target orb ++ */ ++ @NotNull ++ public ExperienceOrb getMergeSource() { ++ return mergeSource; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * @param cancel true if you wish to cancel this event, and prevent the orbs from merging ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0077-Ability-to-apply-mending-to-XP-API.patch b/patches/api-unmapped/0077-Ability-to-apply-mending-to-XP-API.patch new file mode 100644 index 0000000000..a225f3dedc --- /dev/null +++ b/patches/api-unmapped/0077-Ability-to-apply-mending-to-XP-API.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 20 Dec 2017 17:38:07 -0500 +Subject: [PATCH] Ability to apply mending to XP API + +This allows plugins that give players the ability to apply the experience +points to the Item Mending formula, which will repair an item instead +of giving the player experience points. + +Both an API To standalone mend, and apply mending logic to .giveExp has been added. + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 21bed0d8075335538374fadfdf1cb868e4eebe80..9d1ad67b7d220ab425ac9bf6b1c8d8fb8d5f416c 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -892,12 +892,33 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public void resetPlayerWeather(); + ++ // Paper start ++ /** ++ * Gives the player the amount of experience specified. ++ * ++ * @param amount Exp amount to give ++ */ ++ public default void giveExp(int amount) { ++ giveExp(amount, false); ++ } + /** + * Gives the player the amount of experience specified. + * + * @param amount Exp amount to give ++ * @param applyMending Mend players items with mending, with same behavior as picking up orbs. calls {@link #applyMending(int)} + */ +- public void giveExp(int amount); ++ public void giveExp(int amount, boolean applyMending); ++ ++ /** ++ * Applies the mending effect to any items just as picking up an orb would. ++ * ++ * Can also be called with {@link #giveExp(int, boolean)} by passing true to applyMending ++ * ++ * @param amount Exp to apply ++ * @return the remaining experience ++ */ ++ public int applyMending(int amount); ++ // Paper end + + /** + * Gives the player the amount of experience levels specified. Levels can diff --git a/patches/api-unmapped/0078-PreCreatureSpawnEvent.patch b/patches/api-unmapped/0078-PreCreatureSpawnEvent.patch new file mode 100644 index 0000000000..0090330de9 --- /dev/null +++ b/patches/api-unmapped/0078-PreCreatureSpawnEvent.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 14 Jan 2018 16:59:43 -0500 +Subject: [PATCH] PreCreatureSpawnEvent + +Adds an event to fire before an Entity is created, so that plugins that need to cancel +CreatureSpawnEvent can do so from this event instead. + +Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste +as it's done after the Entity object has been fully created. + +Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event +instead and save a lot of server resources. + +See: https://github.com/PaperMC/Paper/issues/917 + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3ad231aa3206c8cfd5ec995249584cebab5d11f3 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java +@@ -0,0 +1,105 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import com.google.common.base.Preconditions; ++import org.bukkit.Location; ++import org.bukkit.entity.EntityType; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * WARNING: This event only fires for a limited number of cases, and not for every case that CreatureSpawnEvent does. ++ * ++ * You should still listen to CreatureSpawnEvent as a backup, and only use this event as an "enhancement". ++ * The intent of this event is to improve server performance, so it fires even if the spawning might fail later, for ++ * example when the entity would be unable to spawn due to limited space or lighting. ++ * ++ * Currently: NATURAL and SPAWNER based reasons. Please submit a Pull Request for future additions. ++ * Also, Plugins that replace Entity Registrations with their own custom entities might not fire this event. ++ */ ++public class PreCreatureSpawnEvent extends Event implements Cancellable { ++ @NotNull private final Location location; ++ @NotNull private final EntityType type; ++ @NotNull private final CreatureSpawnEvent.SpawnReason reason; ++ private boolean shouldAbortSpawn; ++ ++ public PreCreatureSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason) { ++ this.location = Preconditions.checkNotNull(location, "Location may not be null").clone(); ++ this.type = Preconditions.checkNotNull(type, "Type may not be null"); ++ this.reason = Preconditions.checkNotNull(reason, "Reason may not be null"); ++ } ++ ++ /** ++ * @return The location this creature is being spawned at ++ */ ++ @NotNull ++ public Location getSpawnLocation() { ++ return location; ++ } ++ ++ /** ++ * @return The type of creature being spawned ++ */ ++ @NotNull ++ public EntityType getType() { ++ return type; ++ } ++ ++ /** ++ * @return Reason this creature is spawning (ie, NATURAL vs SPAWNER) ++ */ ++ @NotNull ++ public CreatureSpawnEvent.SpawnReason getReason() { ++ return reason; ++ } ++ ++ /** ++ * @return If the spawn process should be aborted vs trying more attempts ++ */ ++ public boolean shouldAbortSpawn() { ++ return shouldAbortSpawn; ++ } ++ ++ /** ++ * Set this if you are more blanket blocking all types of these spawns, and wish to abort the spawn process from ++ * trying more attempts after this cancellation. ++ * ++ * @param shouldAbortSpawn Set if the spawn process should be aborted vs trying more attempts ++ */ ++ public void setShouldAbortSpawn(boolean shouldAbortSpawn) { ++ this.shouldAbortSpawn = shouldAbortSpawn; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ /** ++ * @return If the spawn of this creature is cancelled or not ++ */ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * Cancelling this event is more effecient than cancelling CreatureSpawnEvent ++ * @param cancel true if you wish to cancel this event, and abort the spawn of this creature ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0079-PlayerNaturallySpawnCreaturesEvent.patch b/patches/api-unmapped/0079-PlayerNaturallySpawnCreaturesEvent.patch new file mode 100644 index 0000000000..a6fa8a9b72 --- /dev/null +++ b/patches/api-unmapped/0079-PlayerNaturallySpawnCreaturesEvent.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 14 Jan 2018 17:31:37 -0500 +Subject: [PATCH] PlayerNaturallySpawnCreaturesEvent + +This event can be used for when you want to exclude a certain player +from triggering monster spawns on a server. + +Also a highly more effecient way to blanket block spawns in a world + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..112a0dbf522b8e74ce882678434923814e6b187f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java +@@ -0,0 +1,64 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when the server is calculating what chunks to try to spawn monsters in every Monster Spawn Tick event ++ */ ++public class PlayerNaturallySpawnCreaturesEvent extends PlayerEvent implements Cancellable { ++ private byte radius; ++ ++ public PlayerNaturallySpawnCreaturesEvent(@NotNull Player player, byte radius) { ++ super(player); ++ this.radius = radius; ++ } ++ ++ /** ++ * @return The radius of chunks around this player to be included in natural spawn selection ++ */ ++ public byte getSpawnRadius() { ++ return radius; ++ } ++ ++ /** ++ * @param radius The radius of chunks around this player to be included in natural spawn selection ++ */ ++ public void setSpawnRadius(byte radius) { ++ this.radius = radius; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ /** ++ * @return If this players chunks will be excluded from natural spawns ++ */ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * @param cancel true if you wish to cancel this event, and not include this players chunks for natural spawning ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0080-Add-setPlayerProfile-API-for-Skulls.patch b/patches/api-unmapped/0080-Add-setPlayerProfile-API-for-Skulls.patch new file mode 100644 index 0000000000..42ffd3f948 --- /dev/null +++ b/patches/api-unmapped/0080-Add-setPlayerProfile-API-for-Skulls.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 19 Jan 2018 00:29:28 -0500 +Subject: [PATCH] Add setPlayerProfile API for Skulls + +This allows you to create already filled textures on Skulls to avoid texture lookups +which commonly cause rate limit issues with Mojang API + +diff --git a/src/main/java/org/bukkit/block/Skull.java b/src/main/java/org/bukkit/block/Skull.java +index 943d751fb3e48212fbe258845beba03c25fa22d9..a6914f01e01e9103702185f92b0209b3c84c152a 100644 +--- a/src/main/java/org/bukkit/block/Skull.java ++++ b/src/main/java/org/bukkit/block/Skull.java +@@ -7,6 +7,7 @@ import org.bukkit.block.data.BlockData; + import org.jetbrains.annotations.Contract; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; ++import com.destroystokyo.paper.profile.PlayerProfile; // Paper + + /** + * Represents a captured state of a skull block. +@@ -61,6 +62,20 @@ public interface Skull extends TileState { + */ + public void setOwningPlayer(@NotNull OfflinePlayer player); + ++ // Paper start ++ /** ++ * Sets this skull to use the supplied Player Profile, which can include textures already prefilled. ++ * @param profile The profile to set this Skull to use, may not be null ++ */ ++ void setPlayerProfile(@NotNull PlayerProfile profile); ++ ++ /** ++ * If the skull has an owner, per {@link #hasOwner()}, return the owners {@link PlayerProfile} ++ * @return The profile of the owner, if set ++ */ ++ @Nullable PlayerProfile getPlayerProfile(); ++ // Paper end ++ + /** + * Gets the rotation of the skull in the world (or facing direction if this + * is a wall mounted skull). +diff --git a/src/main/java/org/bukkit/inventory/meta/SkullMeta.java b/src/main/java/org/bukkit/inventory/meta/SkullMeta.java +index 496254f959345d74167a9b44d160ea1bb428c5a1..88d1c889c09adb91abb09a8e43a30c871b217da2 100644 +--- a/src/main/java/org/bukkit/inventory/meta/SkullMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/SkullMeta.java +@@ -1,9 +1,11 @@ + package org.bukkit.inventory.meta; + ++import com.destroystokyo.paper.profile.PlayerProfile; + import org.bukkit.OfflinePlayer; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + ++ + /** + * Represents a skull that can have an owner. + */ +@@ -36,6 +38,20 @@ public interface SkullMeta extends ItemMeta { + @Deprecated + boolean setOwner(@Nullable String owner); + ++ // Paper start ++ /** ++ * Sets this skull to use the supplied Player Profile, which can include textures already prefilled. ++ * @param profile The profile to set this Skull to use, or null to clear owner ++ */ ++ void setPlayerProfile(@Nullable PlayerProfile profile); ++ ++ /** ++ * If the skull has an owner, per {@link #hasOwner()}, return the owners {@link PlayerProfile} ++ * @return The profile of the owner, if set ++ */ ++ @Nullable PlayerProfile getPlayerProfile(); ++ // Paper end ++ + /** + * Gets the owner of the skull. + * diff --git a/patches/api-unmapped/0081-Fill-Profile-Property-Events.patch b/patches/api-unmapped/0081-Fill-Profile-Property-Events.patch new file mode 100644 index 0000000000..5511f6449a --- /dev/null +++ b/patches/api-unmapped/0081-Fill-Profile-Property-Events.patch @@ -0,0 +1,176 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 2 Jan 2018 00:31:08 -0500 +Subject: [PATCH] Fill Profile Property Events + +Allows plugins to populate profile properties from local sources to avoid calls out to Mojang API +to fill in textures for example. + +If Mojang API does need to be hit, event fire so you can get the results. + +This is useful for implementing a ProfileCache for Player Skulls + +diff --git a/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..71f36e9cae209ec6861835a5e76e018de959040a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package com.destroystokyo.paper.event.profile; ++ ++import com.destroystokyo.paper.profile.PlayerProfile; ++import com.destroystokyo.paper.profile.ProfileProperty; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++ ++import java.util.Set; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired once a profiles additional properties (such as textures) has been filled ++ */ ++public class FillProfileEvent extends Event { ++ @NotNull private final PlayerProfile profile; ++ ++ public FillProfileEvent(@NotNull PlayerProfile profile) { ++ super(!org.bukkit.Bukkit.isPrimaryThread()); ++ this.profile = profile; ++ } ++ ++ /** ++ * @return The Profile that had properties filled ++ */ ++ @NotNull ++ public PlayerProfile getPlayerProfile() { ++ return profile; ++ } ++ ++ /** ++ * Same as .getPlayerProfile().getProperties() ++ * ++ * @see PlayerProfile#getProperties() ++ * @return The new properties on the profile. ++ */ ++ @NotNull ++ public Set getProperties() { ++ return profile.getProperties(); ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..021bc86310a06f84b39459e0eb8927802726399c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package com.destroystokyo.paper.event.profile; ++ ++import com.destroystokyo.paper.profile.PlayerProfile; ++import com.destroystokyo.paper.profile.ProfileProperty; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++ ++import java.util.Collection; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when the server is requesting to fill in properties of an incomplete profile, such as textures. ++ * ++ * Allows plugins to pre populate cached properties and avoid a call to the Mojang API ++ */ ++public class PreFillProfileEvent extends Event { ++ @NotNull private final PlayerProfile profile; ++ ++ public PreFillProfileEvent(@NotNull PlayerProfile profile) { ++ super(!org.bukkit.Bukkit.isPrimaryThread()); ++ this.profile = profile; ++ } ++ ++ /** ++ * @return The profile that needs its properties filled ++ */ ++ @NotNull ++ public PlayerProfile getPlayerProfile() { ++ return profile; ++ } ++ ++ /** ++ * Sets the properties on the profile, avoiding the call to the Mojang API ++ * Same as .getPlayerProfile().setProperties(properties); ++ * ++ * @see PlayerProfile#setProperties(Collection) ++ * @param properties The properties to set/append ++ */ ++ public void setProperties(@NotNull Collection properties) { ++ profile.setProperties(properties); ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0082-PlayerAdvancementCriterionGrantEvent.patch b/patches/api-unmapped/0082-PlayerAdvancementCriterionGrantEvent.patch new file mode 100644 index 0000000000..5e8eaca58a --- /dev/null +++ b/patches/api-unmapped/0082-PlayerAdvancementCriterionGrantEvent.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 19 Jan 2018 08:15:14 -0600 +Subject: [PATCH] PlayerAdvancementCriterionGrantEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bb8d7c959cdea4b66455a49e74804ea4b126620d +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java +@@ -0,0 +1,63 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.advancement.Advancement; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a player is granted a criteria in an advancement. ++ */ ++public class PlayerAdvancementCriterionGrantEvent extends PlayerEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ @NotNull private final Advancement advancement; ++ @NotNull private final String criterion; ++ private boolean cancel = false; ++ ++ public PlayerAdvancementCriterionGrantEvent(@NotNull Player who, @NotNull Advancement advancement, @NotNull String criterion) { ++ super(who); ++ this.advancement = advancement; ++ this.criterion = criterion; ++ } ++ ++ /** ++ * Get the advancement which has been affected. ++ * ++ * @return affected advancement ++ */ ++ @NotNull ++ public Advancement getAdvancement() { ++ return advancement; ++ } ++ ++ /** ++ * Get the criterion which has been granted. ++ * ++ * @return granted criterion ++ */ ++ @NotNull ++ public String getCriterion() { ++ return criterion; ++ } ++ ++ public boolean isCancelled() { ++ return cancel; ++ } ++ ++ public void setCancelled(boolean cancel) { ++ this.cancel = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0083-Add-ArmorStand-Item-Meta.patch b/patches/api-unmapped/0083-Add-ArmorStand-Item-Meta.patch new file mode 100644 index 0000000000..6287ef49e7 --- /dev/null +++ b/patches/api-unmapped/0083-Add-ArmorStand-Item-Meta.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 27 Jan 2018 17:06:24 -0500 +Subject: [PATCH] Add ArmorStand Item Meta + +This is adds basic item meta for armor stands. It does not add all +possible metadata however. + +There are armor, hand, and equipment types, as well as position data +that can also be added here. This initial addition should serve a +starting point for future additions in this area. + +diff --git a/src/main/java/com/destroystokyo/paper/inventory/meta/ArmorStandMeta.java b/src/main/java/com/destroystokyo/paper/inventory/meta/ArmorStandMeta.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7e4acfff16db80a75e1ff2fee1972b16955b0918 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/inventory/meta/ArmorStandMeta.java +@@ -0,0 +1,78 @@ ++package com.destroystokyo.paper.inventory.meta; ++ ++import org.bukkit.inventory.meta.ItemMeta; ++ ++public interface ArmorStandMeta extends ItemMeta { ++ ++ /** ++ * Gets whether the ArmorStand should be invisible when spawned ++ * ++ * @return true if this should be invisible ++ */ ++ boolean isInvisible(); ++ ++ /** ++ * Gets whether this ArmorStand should have no base plate when spawned ++ * ++ * @return true if it will not have a base plate ++ */ ++ boolean hasNoBasePlate(); ++ ++ /** ++ * Gets whether this ArmorStand should show arms when spawned ++ * ++ * @return true if it will show arms ++ */ ++ boolean shouldShowArms(); ++ ++ /** ++ * Gets whether this ArmorStand will be small when spawned ++ * ++ * @return true if it will be small ++ */ ++ boolean isSmall(); ++ ++ /** ++ * Gets whether this ArmorStand will be a marker when spawned ++ * The exact details of this flag are an implementation detail ++ * ++ * @return true if it will be a marker ++ */ ++ boolean isMarker(); ++ ++ /** ++ * Sets that this ArmorStand should be invisible when spawned ++ * ++ * @param invisible true if set invisible ++ */ ++ void setInvisible(boolean invisible); ++ ++ /** ++ * Sets that this ArmorStand should have no base plate when spawned ++ * ++ * @param noBasePlate true if no base plate ++ */ ++ void setNoBasePlate(boolean noBasePlate); ++ ++ /** ++ * Sets that this ArmorStand should show arms when spawned ++ * ++ * @param showArms true if show arms ++ */ ++ void setShowArms(boolean showArms); ++ ++ /** ++ * Sets that this ArmorStand should be small when spawned ++ * ++ * @param small true if small ++ */ ++ void setSmall(boolean small); ++ ++ /** ++ * Sets that this ArmorStand should be a marker when spawned ++ * The exact details of this flag are an implementation detail ++ * ++ * @param marker true if a marker ++ */ ++ void setMarker(boolean marker); ++} diff --git a/patches/api-unmapped/0084-Optimize-Hoppers.patch b/patches/api-unmapped/0084-Optimize-Hoppers.patch new file mode 100644 index 0000000000..79c141af55 --- /dev/null +++ b/patches/api-unmapped/0084-Optimize-Hoppers.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 18 Jan 2018 01:00:27 -0500 +Subject: [PATCH] Optimize Hoppers + +Adds data about what Item related methods were used in InventoryMoveItem event +so that the server can improve the performance of this event. + +diff --git a/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java +index a8c48f5a416326e96c431e5fa22edee04825530e..04d4a83bfc4f86341f9d72128458154d08c8ec43 100644 +--- a/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java +@@ -31,6 +31,8 @@ public class InventoryMoveItemEvent extends Event implements Cancellable { + private final Inventory destinationInventory; + private ItemStack itemStack; + private final boolean didSourceInitiate; ++ public boolean calledGetItem; // Paper ++ public boolean calledSetItem; // Paper + + public InventoryMoveItemEvent(@NotNull final Inventory sourceInventory, @NotNull final ItemStack itemStack, @NotNull final Inventory destinationInventory, final boolean didSourceInitiate) { + Validate.notNull(itemStack, "ItemStack cannot be null"); +@@ -58,7 +60,8 @@ public class InventoryMoveItemEvent extends Event implements Cancellable { + */ + @NotNull + public ItemStack getItem() { +- return itemStack.clone(); ++ calledGetItem = true; // Paper - record this method was used for auto detection of mode ++ return itemStack; // Paper - Removed clone, handled better in Server + } + + /** +@@ -70,6 +73,7 @@ public class InventoryMoveItemEvent extends Event implements Cancellable { + */ + public void setItem(@NotNull ItemStack itemStack) { + Validate.notNull(itemStack, "ItemStack cannot be null. Cancel the event if you want nothing to be transferred."); ++ calledSetItem = true; // Paper - record this method was used for auto detection of mode + this.itemStack = itemStack.clone(); + } + diff --git a/patches/api-unmapped/0085-Tameable-getOwnerUniqueId-API.patch b/patches/api-unmapped/0085-Tameable-getOwnerUniqueId-API.patch new file mode 100644 index 0000000000..b911542a60 --- /dev/null +++ b/patches/api-unmapped/0085-Tameable-getOwnerUniqueId-API.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 24 Feb 2018 00:55:52 -0500 +Subject: [PATCH] Tameable#getOwnerUniqueId API + +This is faster if all you need is the UUID, as .getOwner() will cause +an OfflinePlayer to be loaded from disk. + +diff --git a/src/main/java/org/bukkit/entity/Tameable.java b/src/main/java/org/bukkit/entity/Tameable.java +index 26c996cd41acc88490ac0135a9239cffc03e8efb..65e68da98ab66ed781bce2f0dbe0913be48d2990 100644 +--- a/src/main/java/org/bukkit/entity/Tameable.java ++++ b/src/main/java/org/bukkit/entity/Tameable.java +@@ -1,5 +1,6 @@ + package org.bukkit.entity; + ++import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + + public interface Tameable extends Animals { +@@ -25,9 +26,22 @@ public interface Tameable extends Animals { + */ + public void setTamed(boolean tame); + ++ // Paper start ++ /** ++ * Gets the owners UUID ++ * ++ * @return the owners UUID, or null if not owned ++ */ ++ @Nullable ++ public java.util.UUID getOwnerUniqueId(); ++ // Paper end ++ + /** + * Gets the current owning AnimalTamer + * ++ * @see #getOwnerUniqueId() Recommended to use UUID version instead of this for performance. ++ * This method will cause OfflinePlayer to be loaded from disk if the owner is not online. ++ * + * @return the owning AnimalTamer, or null if not owned + */ + @Nullable diff --git a/patches/api-unmapped/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/patches/api-unmapped/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch new file mode 100644 index 0000000000..a2a9f5270f --- /dev/null +++ b/patches/api-unmapped/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 18 Mar 2018 11:43:30 -0400 +Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent + +This will allow you to change the players name or skin on login. + +diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +index 992d1025ca02020e87a9ab5db83d249427f41d69..a40b57edb1aeff71fc0b9767d410950da5c06283 100644 +--- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java ++++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +@@ -2,6 +2,9 @@ package org.bukkit.event.player; + + import java.net.InetAddress; + import java.util.UUID; ++ ++import com.destroystokyo.paper.profile.PlayerProfile; ++import org.bukkit.Bukkit; + import org.bukkit.event.Event; + import org.bukkit.event.HandlerList; + import org.jetbrains.annotations.NotNull; +@@ -15,9 +18,9 @@ public class AsyncPlayerPreLoginEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + private Result result; + private net.kyori.adventure.text.Component message; // Paper +- private final String name; ++ //private String name; // Paper - Not used anymore + private final InetAddress ipAddress; +- private final UUID uniqueId; ++ //private UUID uniqueId; // Paper - Not used anymore + + @Deprecated + public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress) { +@@ -25,12 +28,37 @@ public class AsyncPlayerPreLoginEvent extends Event { + } + + public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId) { ++ // Paper start ++ this(name, ipAddress, uniqueId, Bukkit.createProfile(uniqueId, name)); ++ } ++ private PlayerProfile profile; ++ ++ /** ++ * Gets the PlayerProfile of the player logging in ++ * @return The Profile ++ */ ++ @NotNull ++ public PlayerProfile getPlayerProfile() { ++ return profile; ++ } ++ ++ /** ++ * Changes the PlayerProfile the player will login as ++ * @param profile The profile to use ++ */ ++ public void setPlayerProfile(@NotNull PlayerProfile profile) { ++ this.profile = profile; ++ } ++ ++ public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId, @NotNull PlayerProfile profile) { + super(true); ++ this.profile = profile; ++ // Paper end + this.result = Result.ALLOWED; + this.message = net.kyori.adventure.text.Component.empty(); // Paper +- this.name = name; ++ //this.name = name; // Paper - Not used anymore + this.ipAddress = ipAddress; +- this.uniqueId = uniqueId; ++ //this.uniqueId = uniqueId; // Paper - Not used anymore + } + + /** +@@ -193,7 +221,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + */ + @NotNull + public String getName() { +- return name; ++ return profile.getName(); // Paper + } + + /** +@@ -213,7 +241,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + */ + @NotNull + public UUID getUniqueId() { +- return uniqueId; ++ return profile.getId(); // Paper + } + + @NotNull diff --git a/patches/api-unmapped/0087-Add-extended-PaperServerListPingEvent.patch b/patches/api-unmapped/0087-Add-extended-PaperServerListPingEvent.patch new file mode 100644 index 0000000000..f35ae4323f --- /dev/null +++ b/patches/api-unmapped/0087-Add-extended-PaperServerListPingEvent.patch @@ -0,0 +1,381 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Wed, 11 Oct 2017 15:55:38 +0200 +Subject: [PATCH] Add extended PaperServerListPingEvent + +Add a new event that extends the original ServerListPingEvent +and allows full control of the response sent to the client. + +diff --git a/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java b/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..baac2e4f090a490372ef4aed92c8a5771955e921 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java +@@ -0,0 +1,334 @@ ++package com.destroystokyo.paper.event.server; ++ ++import static java.util.Objects.requireNonNull; ++ ++import com.destroystokyo.paper.network.StatusClient; ++import com.destroystokyo.paper.profile.PlayerProfile; ++import org.bukkit.Bukkit; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.server.ServerListPingEvent; ++import org.bukkit.util.CachedServerIcon; ++ ++import java.util.ArrayList; ++import java.util.Iterator; ++import java.util.List; ++import java.util.NoSuchElementException; ++import java.util.UUID; ++ ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Extended version of {@link ServerListPingEvent} that allows full control ++ * of the response sent to the client. ++ */ ++public class PaperServerListPingEvent extends ServerListPingEvent implements Cancellable { ++ ++ @NotNull private final StatusClient client; ++ ++ private int numPlayers; ++ private boolean hidePlayers; ++ @NotNull private final List playerSample = new ArrayList<>(); ++ ++ @NotNull private String version; ++ private int protocolVersion; ++ ++ @Nullable private CachedServerIcon favicon; ++ ++ private boolean cancelled; ++ ++ private boolean originalPlayerCount = true; ++ private Object[] players; ++ ++ @Deprecated ++ public PaperServerListPingEvent(@NotNull StatusClient client, @NotNull String motd, int numPlayers, int maxPlayers, ++ @NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon) { ++ super(client.getAddress().getAddress(), motd, numPlayers, maxPlayers); ++ this.client = client; ++ this.numPlayers = numPlayers; ++ this.version = version; ++ this.protocolVersion = protocolVersion; ++ setServerIcon(favicon); ++ } ++ ++ public PaperServerListPingEvent(@NotNull StatusClient client, @NotNull net.kyori.adventure.text.Component motd, int numPlayers, int maxPlayers, ++ @NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon) { ++ super(client.getAddress().getAddress(), motd, numPlayers, maxPlayers); ++ this.client = client; ++ this.numPlayers = numPlayers; ++ this.version = version; ++ this.protocolVersion = protocolVersion; ++ setServerIcon(favicon); ++ } ++ ++ /** ++ * Returns the {@link StatusClient} pinging the server. ++ * ++ * @return The client ++ */ ++ @NotNull ++ public StatusClient getClient() { ++ return this.client; ++ } ++ ++ /** ++ * {@inheritDoc} ++ * ++ *

    Returns {@code -1} if players are hidden using ++ * {@link #shouldHidePlayers()}.

    ++ */ ++ @Override ++ public int getNumPlayers() { ++ if (this.hidePlayers) { ++ return -1; ++ } ++ ++ return this.numPlayers; ++ } ++ ++ /** ++ * Sets the number of players displayed in the server list. ++ * ++ *

    Note that this won't have any effect if {@link #shouldHidePlayers()} ++ * is enabled.

    ++ * ++ * @param numPlayers The number of online players ++ */ ++ public void setNumPlayers(int numPlayers) { ++ if (this.numPlayers != numPlayers) { ++ this.numPlayers = numPlayers; ++ this.originalPlayerCount = false; ++ } ++ } ++ ++ /** ++ * {@inheritDoc} ++ * ++ *

    Returns {@code -1} if players are hidden using ++ * {@link #shouldHidePlayers()}.

    ++ */ ++ @Override ++ public int getMaxPlayers() { ++ if (this.hidePlayers) { ++ return -1; ++ } ++ ++ return super.getMaxPlayers(); ++ } ++ ++ /** ++ * Returns whether all player related information is hidden in the server ++ * list. This will cause {@link #getNumPlayers()}, {@link #getMaxPlayers()} ++ * and {@link #getPlayerSample()} to be skipped in the response. ++ * ++ *

    The Vanilla Minecraft client will display the player count as {@code ???} ++ * when this option is enabled.

    ++ * ++ * @return {@code true} if the player count is hidden ++ */ ++ public boolean shouldHidePlayers() { ++ return hidePlayers; ++ } ++ ++ /** ++ * Sets whether all player related information is hidden in the server ++ * list. This will cause {@link #getNumPlayers()}, {@link #getMaxPlayers()} ++ * and {@link #getPlayerSample()} to be skipped in the response. ++ * ++ *

    The Vanilla Minecraft client will display the player count as {@code ???} ++ * when this option is enabled.

    ++ * ++ * @param hidePlayers {@code true} if the player count should be hidden ++ */ ++ public void setHidePlayers(boolean hidePlayers) { ++ this.hidePlayers = hidePlayers; ++ } ++ ++ /** ++ * Returns a mutable list of {@link PlayerProfile} that will be displayed ++ * as online players on the client. ++ * ++ *

    The Vanilla Minecraft client will display them when hovering the ++ * player count with the mouse.

    ++ * ++ * @return The mutable player sample list ++ */ ++ @NotNull ++ public List getPlayerSample() { ++ return this.playerSample; ++ } ++ ++ /** ++ * Returns the version that will be sent as server version on the client. ++ * ++ * @return The server version ++ */ ++ @NotNull ++ public String getVersion() { ++ return version; ++ } ++ ++ /** ++ * Sets the version that will be sent as server version to the client. ++ * ++ * @param version The server version ++ */ ++ public void setVersion(@NotNull String version) { ++ this.version = requireNonNull(version, "version"); ++ } ++ ++ /** ++ * Returns the protocol version that will be sent as the protocol version ++ * of the server to the client. ++ * ++ * @return The protocol version of the server, or {@code -1} if the server ++ * has not finished initialization yet ++ */ ++ public int getProtocolVersion() { ++ return protocolVersion; ++ } ++ ++ /** ++ * Sets the protocol version that will be sent as the protocol version ++ * of the server to the client. ++ * ++ * @param protocolVersion The protocol version of the server ++ */ ++ public void setProtocolVersion(int protocolVersion) { ++ this.protocolVersion = protocolVersion; ++ } ++ ++ /** ++ * Gets the server icon sent to the client. ++ * ++ * @return The icon to send to the client, or {@code null} for none ++ */ ++ @Nullable ++ public CachedServerIcon getServerIcon() { ++ return this.favicon; ++ } ++ ++ /** ++ * Sets the server icon sent to the client. ++ * ++ * @param icon The icon to send to the client, or {@code null} for none ++ */ ++ @Override ++ public void setServerIcon(@Nullable CachedServerIcon icon) { ++ if (icon != null && icon.isEmpty()) { ++ // Represent empty icons as null ++ icon = null; ++ } ++ ++ this.favicon = icon; ++ } ++ ++ /** ++ * {@inheritDoc} ++ * ++ *

    Cancelling this event will cause the connection to be closed immediately, ++ * without sending a response to the client.

    ++ */ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ /** ++ * {@inheritDoc} ++ * ++ *

    Cancelling this event will cause the connection to be closed immediately, ++ * without sending a response to the client.

    ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ /** ++ * {@inheritDoc} ++ * ++ *

    Note: For compatibility reasons, this method will return all ++ * online players, not just the ones referenced in {@link #getPlayerSample()}. ++ * Removing a player will:

    ++ * ++ *
      ++ *
    • Decrement the online player count (if and only if) the player ++ * count wasn't changed by another plugin before.
    • ++ *
    • Remove all entries from {@link #getPlayerSample()} that refer to ++ * the removed player (based on their {@link UUID}).
    • ++ *
    ++ */ ++ @NotNull ++ @Override ++ public Iterator iterator() { ++ if (this.players == null) { ++ this.players = getOnlinePlayers(); ++ } ++ ++ return new PlayerIterator(); ++ } ++ ++ @NotNull ++ protected Object[] getOnlinePlayers() { ++ return Bukkit.getOnlinePlayers().toArray(); ++ } ++ ++ @NotNull ++ protected Player getBukkitPlayer(@NotNull Object player) { ++ return (Player) player; ++ } ++ ++ private final class PlayerIterator implements Iterator { ++ ++ private int next; ++ private int current; ++ @Nullable private Player player; ++ ++ @Override ++ public boolean hasNext() { ++ for (; this.next < players.length; this.next++) { ++ if (players[this.next] != null) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ @NotNull ++ @Override ++ public Player next() { ++ if (!hasNext()) { ++ this.player = null; ++ throw new NoSuchElementException(); ++ } ++ ++ this.current = this.next++; ++ return this.player = getBukkitPlayer(players[this.current]); ++ } ++ ++ @Override ++ public void remove() { ++ if (this.player == null) { ++ throw new IllegalStateException(); ++ } ++ ++ UUID uniqueId = this.player.getUniqueId(); ++ this.player = null; ++ ++ // Remove player from iterator ++ players[this.current] = null; ++ ++ // Remove player from sample ++ getPlayerSample().removeIf(p -> uniqueId.equals(p.getId())); ++ ++ // Decrement player count ++ if (originalPlayerCount) { ++ numPlayers--; ++ } ++ } ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/network/StatusClient.java b/src/main/java/com/destroystokyo/paper/network/StatusClient.java +new file mode 100644 +index 0000000000000000000000000000000000000000..517d15238ed117f38bbd39f570874014cecf7bb5 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/StatusClient.java +@@ -0,0 +1,13 @@ ++package com.destroystokyo.paper.network; ++ ++import com.destroystokyo.paper.event.server.PaperServerListPingEvent; ++ ++/** ++ * Represents a client requesting the current status from the server (e.g. from ++ * the server list). ++ * ++ * @see PaperServerListPingEvent ++ */ ++public interface StatusClient extends NetworkClient { ++ ++} +diff --git a/src/main/java/org/bukkit/util/CachedServerIcon.java b/src/main/java/org/bukkit/util/CachedServerIcon.java +index 612958a331575d1da2715531ebdf6b1168f2e860..bb4f7702ced0baf0670a7a21d48ad528b7249361 100644 +--- a/src/main/java/org/bukkit/util/CachedServerIcon.java ++++ b/src/main/java/org/bukkit/util/CachedServerIcon.java +@@ -18,4 +18,9 @@ public interface CachedServerIcon { + @Nullable + public String getData(); // Paper + ++ // Paper start ++ default boolean isEmpty() { ++ return getData() == null; ++ } ++ // Paper end + } diff --git a/patches/api-unmapped/0088-Player.setPlayerProfile-API.patch b/patches/api-unmapped/0088-Player.setPlayerProfile-API.patch new file mode 100644 index 0000000000..5a914436ae --- /dev/null +++ b/patches/api-unmapped/0088-Player.setPlayerProfile-API.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 18 Mar 2018 12:28:55 -0400 +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/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 9a262d412b2762a33a60b1e8762a7d9c9c3f933d..3ae4d670059f80bd057870a37f4025261e397dfa 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -4,6 +4,7 @@ import java.net.InetSocketAddress; + import java.util.UUID; + import com.destroystokyo.paper.Title; // Paper + import net.kyori.adventure.text.Component; ++import com.destroystokyo.paper.profile.PlayerProfile; // Paper + import org.bukkit.DyeColor; + import org.bukkit.Effect; + import org.bukkit.GameMode; +@@ -1714,6 +1715,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * was {@link org.bukkit.event.player.PlayerResourcePackStatusEvent.Status#SUCCESSFULLY_LOADED} + */ + boolean hasResourcePack(); ++ ++ /** ++ * Gets a copy of this players profile ++ * @return The players profile object ++ */ ++ @NotNull ++ PlayerProfile getPlayerProfile(); ++ ++ /** ++ * Changes the PlayerProfile for this player. This will cause this player ++ * to be reregistered to all clients that can currently see this player ++ * @param profile The new profile to use ++ */ ++ void setPlayerProfile(@NotNull PlayerProfile profile); + // Paper end + + // Spigot start diff --git a/patches/api-unmapped/0089-getPlayerUniqueId-API.patch b/patches/api-unmapped/0089-getPlayerUniqueId-API.patch new file mode 100644 index 0000000000..6586351ea9 --- /dev/null +++ b/patches/api-unmapped/0089-getPlayerUniqueId-API.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 22 Mar 2018 01:39:28 -0400 +Subject: [PATCH] getPlayerUniqueId API + +Gets the unique ID of the player currently known as the specified player name +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 f5d3a7370390871d1b6075f32846d1a942b05b7f..2d7f8e128e23934a8fe26baf19198b7ffc8447bb 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -504,6 +504,20 @@ public final class Bukkit { + return server.getPlayer(id); + } + ++ // Paper start ++ /** ++ * Gets the unique ID of the player currently known as the specified player name ++ * In Offline Mode, will return an Offline UUID ++ * ++ * @param playerName the player name to look up the unique ID for ++ * @return A UUID, or null if that player name is not registered with Minecraft and the server is in online mode ++ */ ++ @Nullable ++ public static UUID getPlayerUniqueId(@NotNull String playerName) { ++ return server.getPlayerUniqueId(playerName); ++ } ++ // Paper end ++ + /** + * 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 38d138b217734e598581ed14065ff2015135ee9a..01657abaff86cf7bb3ffb857024c5032781b8660 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -429,6 +429,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @Nullable + public Player getPlayer(@NotNull UUID id); + ++ // Paper start ++ /** ++ * Gets the unique ID of the player currently known as the specified player name ++ * In Offline Mode, will return an Offline UUID ++ * ++ * @param playerName the player name to look up the unique ID for ++ * @return A UUID, or null if that player name is not registered with Minecraft and the server is in online mode ++ */ ++ @Nullable ++ public UUID getPlayerUniqueId(@NotNull String playerName); ++ // Paper end ++ + /** + * Gets the plugin manager for interfacing with plugins. + * diff --git a/patches/api-unmapped/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch b/patches/api-unmapped/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch new file mode 100644 index 0000000000..f21c766148 --- /dev/null +++ b/patches/api-unmapped/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Wed, 11 Oct 2017 19:30:20 +0200 +Subject: [PATCH] Add legacy ping support to PaperServerListPingEvent + +Add a new method to StatusClient check if the client is a legacy +client that does not support all of the features provided in the +event. + +diff --git a/src/main/java/com/destroystokyo/paper/network/StatusClient.java b/src/main/java/com/destroystokyo/paper/network/StatusClient.java +index 517d15238ed117f38bbd39f570874014cecf7bb5..ffda9f6a8b094942009aa78b331d22d9dcca2802 100644 +--- a/src/main/java/com/destroystokyo/paper/network/StatusClient.java ++++ b/src/main/java/com/destroystokyo/paper/network/StatusClient.java +@@ -10,4 +10,16 @@ import com.destroystokyo.paper.event.server.PaperServerListPingEvent; + */ + public interface StatusClient extends NetworkClient { + ++ /** ++ * Returns whether the client is using an older version that doesn't ++ * support all of the features in {@link PaperServerListPingEvent}. ++ * ++ *

    For Vanilla, this returns {@code true} for all clients older than 1.7.

    ++ * ++ * @return {@code true} if the client is using legacy ping ++ */ ++ default boolean isLegacy() { ++ return false; ++ } ++ + } diff --git a/patches/api-unmapped/0091-Add-method-to-open-already-placed-sign.patch b/patches/api-unmapped/0091-Add-method-to-open-already-placed-sign.patch new file mode 100644 index 0000000000..c75d281c23 --- /dev/null +++ b/patches/api-unmapped/0091-Add-method-to-open-already-placed-sign.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 1 Apr 2018 02:28:43 +0300 +Subject: [PATCH] Add method to open already placed sign + + +diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java +index d212d5123b6294f7873d72f125505a006c290b05..7430bc85301d0fcb34c6035fbe08ae245c76e043 100644 +--- a/src/main/java/org/bukkit/entity/HumanEntity.java ++++ b/src/main/java/org/bukkit/entity/HumanEntity.java +@@ -461,6 +461,14 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder + */ + @Deprecated + public void setShoulderEntityRight(@Nullable Entity entity); ++ // Paper start - Add method to open already placed sign ++ /** ++ * Opens an editor window for the specified sign ++ * ++ * @param sign The sign to open ++ */ ++ void openSign(@NotNull org.bukkit.block.Sign sign); ++ // Paper end + + /** + * Make the entity drop the item in their hand. diff --git a/patches/api-unmapped/0092-Add-Ban-Methods-to-Player-Objects.patch b/patches/api-unmapped/0092-Add-Ban-Methods-to-Player-Objects.patch new file mode 100644 index 0000000000..540eeb4d36 --- /dev/null +++ b/patches/api-unmapped/0092-Add-Ban-Methods-to-Player-Objects.patch @@ -0,0 +1,253 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 28 Apr 2018 10:28:50 -0400 +Subject: [PATCH] Add Ban Methods to Player Objects + +Allows a more logical API for banning players. + +player.banPlayer("Breaking the rules"); + +diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java +index 58313929f81509030216a0e5e3869da63e11108e..6cf05fed701c67a2c797a4e0839c795802a238a1 100644 +--- a/src/main/java/org/bukkit/OfflinePlayer.java ++++ b/src/main/java/org/bukkit/OfflinePlayer.java +@@ -45,6 +45,61 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio + * @return true if banned, otherwise false + */ + public boolean isBanned(); ++ // Paper start ++ ++ /** ++ * Permanently Bans this player from the server ++ * ++ * @param reason Reason for Ban ++ * @return Ban Entry ++ */ ++ @NotNull ++ public default BanEntry banPlayer(@Nullable String reason) { ++ return banPlayer(reason, null, null); ++ } ++ ++ /** ++ * Permanently Bans this player from the server ++ * @param reason Reason for Ban ++ * @param source Source of the ban, or null for default ++ * @return Ban Entry ++ */ ++ @NotNull ++ public default BanEntry banPlayer(@Nullable String reason, @Nullable String source) { ++ return banPlayer(reason, null, source); ++ } ++ ++ /** ++ * Bans this player from the server ++ * @param reason Reason for Ban ++ * @param expires When to expire the ban ++ * @return Ban Entry ++ */ ++ @NotNull ++ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.Date expires) { ++ return banPlayer(reason, expires, null); ++ } ++ ++ /** ++ * Bans this player from the server ++ * @param reason Reason for Ban ++ * @param expires When to expire the ban ++ * @param source Source of the ban or null for default ++ * @return Ban Entry ++ */ ++ @NotNull ++ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.Date expires, @Nullable String source) { ++ return banPlayer(reason, expires, source, true); ++ } ++ @NotNull ++ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.Date expires, @Nullable String source, boolean kickIfOnline) { ++ BanEntry banEntry = Bukkit.getServer().getBanList(BanList.Type.NAME).addBan(getName(), reason, expires, source); ++ if (kickIfOnline && isOnline()) { ++ getPlayer().kickPlayer(reason); ++ } ++ return banEntry; ++ } ++ // Paper end + + /** + * Checks if this player is whitelisted or not +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 6769330f336afcd5f26c0f7286defa00bead543c..88fd4cdeaad4d27f414c6b268022cdedf73492e7 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -5,6 +5,10 @@ import java.util.UUID; + import com.destroystokyo.paper.Title; // Paper + import net.kyori.adventure.text.Component; + import com.destroystokyo.paper.profile.PlayerProfile; // Paper ++import java.util.Date; // Paper ++import org.bukkit.BanEntry; // Paper ++import org.bukkit.BanList; // Paper ++import org.bukkit.Bukkit; // Paper + import org.bukkit.DyeColor; + import org.bukkit.Effect; + import org.bukkit.GameMode; +@@ -618,6 +622,162 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + public void sendMap(@NotNull MapView map); + + // Paper start ++ /** ++ * Permanently Bans the Profile and IP address currently used by the player. ++ * ++ * @param reason Reason for ban ++ * @return Ban Entry ++ */ ++ // For reference, Bukkit defines this as nullable, while they impl isn't, we'll follow API. ++ @Nullable ++ public default BanEntry banPlayerFull(@Nullable String reason) { ++ return banPlayerFull(reason, null, null); ++ } ++ ++ /** ++ * Permanently Bans the Profile and IP address currently used by the player. ++ * ++ * @param reason Reason for ban ++ * @param source Source of ban, or null for default ++ * @return Ban Entry ++ */ ++ @Nullable ++ public default BanEntry banPlayerFull(@Nullable String reason, @Nullable String source) { ++ return banPlayerFull(reason, null, source); ++ } ++ ++ /** ++ * Bans the Profile and IP address currently used by the player. ++ * ++ * @param reason Reason for Ban ++ * @param expires When to expire the ban ++ * @return Ban Entry ++ */ ++ @Nullable ++ public default BanEntry banPlayerFull(@Nullable String reason, @Nullable Date expires) { ++ return banPlayerFull(reason, expires, null); ++ } ++ ++ /** ++ * Bans the Profile and IP address currently used by the player. ++ * ++ * @param reason Reason for Ban ++ * @param expires When to expire the ban ++ * @param source Source of the ban, or null for default ++ * @return Ban Entry ++ */ ++ @Nullable ++ public default BanEntry banPlayerFull(@Nullable String reason, @Nullable Date expires, @Nullable String source) { ++ banPlayer(reason, expires, source); ++ return banPlayerIP(reason, expires, source, true); ++ } ++ ++ /** ++ * Permanently Bans the IP address currently used by the player. ++ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} ++ * ++ * @param reason Reason for ban ++ * @param kickPlayer Whether or not to kick the player afterwards ++ * @return Ban Entry ++ */ ++ @Nullable ++ public default BanEntry banPlayerIP(@Nullable String reason, boolean kickPlayer) { ++ return banPlayerIP(reason, null, null, kickPlayer); ++ } ++ ++ /** ++ * Permanently Bans the IP address currently used by the player. ++ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} ++ * @param reason Reason for ban ++ * @param source Source of ban, or null for default ++ * @param kickPlayer Whether or not to kick the player afterwards ++ * @return Ban Entry ++ */ ++ @Nullable ++ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable String source, boolean kickPlayer) { ++ return banPlayerIP(reason, null, source, kickPlayer); ++ } ++ ++ /** ++ * Bans the IP address currently used by the player. ++ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} ++ * @param reason Reason for Ban ++ * @param expires When to expire the ban ++ * @param kickPlayer Whether or not to kick the player afterwards ++ * @return Ban Entry ++ */ ++ @Nullable ++ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable Date expires, boolean kickPlayer) { ++ return banPlayerIP(reason, expires, null, kickPlayer); ++ } ++ ++ /** ++ * Permanently Bans the IP address currently used by the player. ++ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} ++ * ++ * @param reason Reason for ban ++ * @return Ban Entry ++ */ ++ @Nullable ++ public default BanEntry banPlayerIP(@Nullable String reason) { ++ return banPlayerIP(reason, null, null); ++ } ++ ++ /** ++ * Permanently Bans the IP address currently used by the player. ++ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} ++ * @param reason Reason for ban ++ * @param source Source of ban, or null for default ++ * @return Ban Entry ++ */ ++ @Nullable ++ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable String source) { ++ return banPlayerIP(reason, null, source); ++ } ++ ++ /** ++ * Bans the IP address currently used by the player. ++ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} ++ * @param reason Reason for Ban ++ * @param expires When to expire the ban ++ * @return Ban Entry ++ */ ++ @Nullable ++ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable Date expires) { ++ return banPlayerIP(reason, expires, null); ++ } ++ ++ /** ++ * Bans the IP address currently used by the player. ++ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} ++ * @param reason Reason for Ban ++ * @param expires When to expire the ban ++ * @param source Source of the banm or null for default ++ * @return Ban Entry ++ */ ++ @Nullable ++ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable Date expires, @Nullable String source) { ++ return banPlayerIP(reason, expires, source, true); ++ } ++ ++ /** ++ * Bans the IP address currently used by the player. ++ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} ++ * @param reason Reason for Ban ++ * @param expires When to expire the ban ++ * @param source Source of the banm or null for default ++ * @param kickPlayer if the targeted player should be kicked ++ * @return Ban Entry ++ */ ++ @Nullable ++ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable Date expires, @Nullable String source, boolean kickPlayer) { ++ BanEntry banEntry = Bukkit.getServer().getBanList(BanList.Type.IP).addBan(getAddress().getAddress().getHostAddress(), reason, expires, source); ++ if (kickPlayer && isOnline()) { ++ getPlayer().kickPlayer(reason); ++ } ++ ++ return banEntry; ++ } + + /** + * Sends an Action Bar message to the client. diff --git a/patches/api-unmapped/0093-EndermanEscapeEvent.patch b/patches/api-unmapped/0093-EndermanEscapeEvent.patch new file mode 100644 index 0000000000..82d22fd0ea --- /dev/null +++ b/patches/api-unmapped/0093-EndermanEscapeEvent.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 13:14:30 -0400 +Subject: [PATCH] EndermanEscapeEvent + +Fires an event anytime an enderman intends to teleport away from the player + +You may cancel this, enabling ranged attacks to damage the enderman for example. + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..806112a8b5a7ce31166675f5b074ceaf42e364b6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java +@@ -0,0 +1,87 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Enderman; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++public class EndermanEscapeEvent extends EntityEvent implements Cancellable { ++ @NotNull private final Reason reason; ++ ++ public EndermanEscapeEvent(@NotNull Enderman entity, @NotNull Reason reason) { ++ super(entity); ++ this.reason = reason; ++ } ++ ++ @NotNull ++ @Override ++ public Enderman getEntity() { ++ return (Enderman) super.getEntity(); ++ } ++ ++ /** ++ * @return The reason the enderman is trying to escape ++ */ ++ @NotNull ++ public Reason getReason() { ++ return reason; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * Cancels the escape. ++ * ++ * If this escape normally would of resulted in damage avoidance such as indirect, ++ * the enderman will now take damage. ++ * ++ * @param cancel true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++ ++ public enum Reason { ++ /** ++ * The enderman has stopped attacking and ran away ++ */ ++ RUNAWAY, ++ /** ++ * The enderman has teleported away due to indirect damage (ranged) ++ */ ++ INDIRECT, ++ /** ++ * The enderman has teleported away due to a critical hit ++ */ ++ CRITICAL_HIT, ++ /** ++ * The enderman has teleported away due to the player staring at it during combat ++ */ ++ STARE, ++ /** ++ * Specific case for CRITICAL_HIT where the enderman is taking rain damage ++ */ ++ DROWN ++ } ++} diff --git a/patches/api-unmapped/0094-Enderman.teleportRandomly.patch b/patches/api-unmapped/0094-Enderman.teleportRandomly.patch new file mode 100644 index 0000000000..9c226d009c --- /dev/null +++ b/patches/api-unmapped/0094-Enderman.teleportRandomly.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 13:29:15 -0400 +Subject: [PATCH] Enderman.teleportRandomly() + +Ability to trigger the vanilla "teleport randomly" mechanic of an enderman. + +diff --git a/src/main/java/org/bukkit/entity/Enderman.java b/src/main/java/org/bukkit/entity/Enderman.java +index bb325d9c802e33431530bbccdcf5de5839e5fe68..821c690f8a32918bdb284ffec4af98f411f76ccc 100644 +--- a/src/main/java/org/bukkit/entity/Enderman.java ++++ b/src/main/java/org/bukkit/entity/Enderman.java +@@ -10,6 +10,17 @@ import org.jetbrains.annotations.Nullable; + */ + public interface Enderman extends Monster { + ++ // Paper start ++ /** ++ * Try to teleport the enderman to a random nearby location. ++ * ++ * May conditionally fail if the random location was not valid ++ * @return If the enderman teleported successfully or not ++ */ ++ ++ public boolean teleportRandomly(); ++ // Paper end ++ + /** + * Gets the id and data of the block that the Enderman is carrying. + * diff --git a/patches/api-unmapped/0095-Additional-world.getNearbyEntities-API-s.patch b/patches/api-unmapped/0095-Additional-world.getNearbyEntities-API-s.patch new file mode 100644 index 0000000000..cde5bb2148 --- /dev/null +++ b/patches/api-unmapped/0095-Additional-world.getNearbyEntities-API-s.patch @@ -0,0 +1,292 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 17:55:28 -0400 +Subject: [PATCH] Additional world.getNearbyEntities API's + +Provides more methods to get nearby entities, and filter by types and predicates + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 0f86a9c67797fd662cbbfdb808789bcab95caba4..cae848ce698337d0b254bd48938abfc1e68ad561 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -1,6 +1,9 @@ + package org.bukkit; + + import java.io.File; ++import org.bukkit.generator.ChunkGenerator; ++ ++import java.util.ArrayList; + import java.util.Collection; + import java.util.HashMap; + import java.util.List; +@@ -659,6 +662,256 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + @NotNull + public Collection getEntitiesByClasses(@NotNull Class... classes); + ++ // Paper start ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param loc Center location ++ * @param radius Radius ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyLivingEntities(@NotNull Location loc, double radius) { ++ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, radius, radius, radius); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param loc Center location ++ * @param xzRadius X/Z Radius ++ * @param yRadius Y Radius ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyLivingEntities(@NotNull Location loc, double xzRadius, double yRadius) { ++ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, xzRadius, yRadius, xzRadius); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param loc Center location ++ * @param xRadius X Radius ++ * @param yRadius Y Radius ++ * @param zRadius Z radius ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyLivingEntities(@NotNull Location loc, double xRadius, double yRadius, double zRadius) { ++ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, xRadius, yRadius, zRadius); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param loc Center location ++ * @param radius X Radius ++ * @param predicate a predicate used to filter results ++ * @return the collection of living entities near location. This will always be a non-null collection ++ */ ++ @NotNull ++ public default Collection getNearbyLivingEntities(@NotNull Location loc, double radius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, radius, radius, radius, predicate); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param loc Center location ++ * @param xzRadius X/Z Radius ++ * @param yRadius Y Radius ++ * @param predicate a predicate used to filter results ++ * @return the collection of living entities near location. This will always be a non-null collection ++ */ ++ @NotNull ++ public default Collection getNearbyLivingEntities(@NotNull Location loc, double xzRadius, double yRadius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, xzRadius, yRadius, xzRadius, predicate); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param loc Center location ++ * @param xRadius X Radius ++ * @param yRadius Y Radius ++ * @param zRadius Z radius ++ * @param predicate a predicate used to filter results ++ * @return the collection of living entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyLivingEntities(@NotNull Location loc, double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, xRadius, yRadius, zRadius, predicate); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param loc Center location ++ * @param radius X/Y/Z Radius ++ * @return the collection of living entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyPlayers(@NotNull Location loc, double radius) { ++ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, radius, radius, radius); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param loc Center location ++ * @param xzRadius X/Z Radius ++ * @param yRadius Y Radius ++ * @return the collection of living entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyPlayers(@NotNull Location loc, double xzRadius, double yRadius) { ++ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, xzRadius, yRadius, xzRadius); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param loc Center location ++ * @param xRadius X Radius ++ * @param yRadius Y Radius ++ * @param zRadius Z Radius ++ * @return the collection of players near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyPlayers(@NotNull Location loc, double xRadius, double yRadius, double zRadius) { ++ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, xRadius, yRadius, zRadius); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param loc Center location ++ * @param radius X/Y/Z Radius ++ * @param predicate a predicate used to filter results ++ * @return the collection of players near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyPlayers(@NotNull Location loc, double radius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, radius, radius, radius, predicate); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param loc Center location ++ * @param xzRadius X/Z Radius ++ * @param yRadius Y Radius ++ * @param predicate a predicate used to filter results ++ * @return the collection of players near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyPlayers(@NotNull Location loc, double xzRadius, double yRadius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, xzRadius, yRadius, xzRadius, predicate); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param loc Center location ++ * @param xRadius X Radius ++ * @param yRadius Y Radius ++ * @param zRadius Z Radius ++ * @param predicate a predicate used to filter results ++ * @return the collection of players near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyPlayers(@NotNull Location loc, double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, xRadius, yRadius, zRadius, predicate); ++ } ++ ++ /** ++ * Gets all nearby entities of the specified type, within the specified radius (bounding box) ++ * @param clazz Type to filter by ++ * @param loc Center location ++ * @param radius X/Y/Z radius to search within ++ * @param the entity type ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double radius) { ++ return getNearbyEntitiesByType(clazz, loc, radius, radius, radius, null); ++ } ++ ++ /** ++ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box) ++ * @param clazz Type to filter by ++ * @param loc Center location ++ * @param xzRadius X/Z radius to search within ++ * @param yRadius Y radius to search within ++ * @param the entity type ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double xzRadius, double yRadius) { ++ return getNearbyEntitiesByType(clazz, loc, xzRadius, yRadius, xzRadius, null); ++ } ++ ++ /** ++ * Gets all nearby entities of the specified type, within the specified radius (bounding box) ++ * @param clazz Type to filter by ++ * @param loc Center location ++ * @param xRadius X Radius ++ * @param yRadius Y Radius ++ * @param zRadius Z Radius ++ * @param the entity type ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double xRadius, double yRadius, double zRadius) { ++ return getNearbyEntitiesByType(clazz, loc, xRadius, yRadius, zRadius, null); ++ } ++ ++ /** ++ * Gets all nearby entities of the specified type, within the specified radius (bounding box) ++ * @param clazz Type to filter by ++ * @param loc Center location ++ * @param radius X/Y/Z radius to search within ++ * @param predicate a predicate used to filter results ++ * @param the entity type ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double radius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(clazz, loc, radius, radius, radius, predicate); ++ } ++ ++ /** ++ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box) ++ * @param clazz Type to filter by ++ * @param loc Center location ++ * @param xzRadius X/Z radius to search within ++ * @param yRadius Y radius to search within ++ * @param predicate a predicate used to filter results ++ * @param the entity type ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double xzRadius, double yRadius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(clazz, loc, xzRadius, yRadius, xzRadius, predicate); ++ } ++ ++ /** ++ * Gets all nearby entities of the specified type, within the specified radius (bounding box) ++ * @param clazz Type to filter by ++ * @param loc Center location ++ * @param xRadius X Radius ++ * @param yRadius Y Radius ++ * @param zRadius Z Radius ++ * @param predicate a predicate used to filter results ++ * @param the entity type ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { ++ if (clazz == null) { ++ clazz = Entity.class; ++ } ++ List nearby = new ArrayList<>(); ++ for (Entity bukkitEntity : getNearbyEntities(loc, xRadius, yRadius, zRadius)) { ++ //noinspection unchecked ++ if (clazz.isAssignableFrom(bukkitEntity.getClass()) && (predicate == null || predicate.test((T) bukkitEntity))) { ++ //noinspection unchecked ++ nearby.add((T) bukkitEntity); ++ } ++ } ++ return nearby; ++ } ++ // Paper end ++ + /** + * Get a list of all players in this World + * +diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +index a40b57edb1aeff71fc0b9767d410950da5c06283..184d9462ebbc500d8b81aaf14fe138d247bf2470 100644 +--- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java ++++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +@@ -42,8 +42,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + return profile; + } + +- /** +- * Changes the PlayerProfile the player will login as ++ /* * Changes the PlayerProfile the player will login as + * @param profile The profile to use + */ + public void setPlayerProfile(@NotNull PlayerProfile profile) { diff --git a/patches/api-unmapped/0096-Location.isChunkLoaded-API.patch b/patches/api-unmapped/0096-Location.isChunkLoaded-API.patch new file mode 100644 index 0000000000..1670d20348 --- /dev/null +++ b/patches/api-unmapped/0096-Location.isChunkLoaded-API.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 19:27:31 -0400 +Subject: [PATCH] Location.isChunkLoaded() API + + +diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java +index 0939a8070f9cc4f66f1679fef74862debb7d32ae..6c8b8eddcdb81f7151202eb12541308040790d45 100644 +--- a/src/main/java/org/bukkit/Location.java ++++ b/src/main/java/org/bukkit/Location.java +@@ -533,6 +533,7 @@ public class Location implements Cloneable, ConfigurationSerializable { + return this; + } + ++ public boolean isChunkLoaded() { return this.getWorld().isChunkLoaded(locToBlock(x) >> 4, locToBlock(z) >> 4); } // Paper + @Override + public boolean equals(Object obj) { + if (obj == null) { diff --git a/patches/api-unmapped/0097-Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/api-unmapped/0097-Expand-World.spawnParticle-API-and-add-Builder.patch new file mode 100644 index 0000000000..da01d6d5c3 --- /dev/null +++ b/patches/api-unmapped/0097-Expand-World.spawnParticle-API-and-add-Builder.patch @@ -0,0 +1,579 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 29 Aug 2017 23:58:48 -0400 +Subject: [PATCH] Expand World.spawnParticle API and add Builder + +Adds ability to control who receives it and who is the source/sender (vanish API) +the standard API is to send the packet to everyone in the world, which is ineffecient. + +This adds a new Builder API which is much friendlier to use. + +diff --git a/src/main/java/com/destroystokyo/paper/ParticleBuilder.java b/src/main/java/com/destroystokyo/paper/ParticleBuilder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..06f1602f5b327705f726d0a99dd6b95e1554d382 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/ParticleBuilder.java +@@ -0,0 +1,478 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.collect.Lists; ++import org.bukkit.Color; ++import org.bukkit.Location; ++import org.bukkit.Particle; ++import org.bukkit.World; ++import org.bukkit.entity.Player; ++import org.bukkit.util.NumberConversions; ++ ++import java.util.Collection; ++import java.util.List; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Helps prepare a particle to be sent to players. ++ * ++ * Usage of the builder is preferred over the super long {@link World#spawnParticle(Particle, Location, int, double, double, double, double, Object)} API ++ */ ++public class ParticleBuilder { ++ ++ private Particle particle; ++ private List receivers; ++ private Player source; ++ private Location location; ++ private int count = 1; ++ private double offsetX = 0, offsetY = 0, offsetZ = 0; ++ private double extra = 1; ++ private Object data; ++ private boolean force = true; ++ ++ public ParticleBuilder(@NotNull Particle particle) { ++ this.particle = particle; ++ } ++ ++ /** ++ * Sends the particle to all receiving players (or all). This method is safe to use ++ * Asynchronously ++ * ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder spawn() { ++ if (this.location == null) { ++ throw new IllegalStateException("Please specify location for this particle"); ++ } ++ location.getWorld().spawnParticle(particle, receivers, source, ++ location.getX(), location.getY(), location.getZ(), ++ count, offsetX, offsetY, offsetZ, extra, data, force ++ ); ++ return this; ++ } ++ ++ /** ++ * @return The particle going to be sent ++ */ ++ @NotNull ++ public Particle particle() { ++ return particle; ++ } ++ ++ /** ++ * Changes what particle will be sent ++ * ++ * @param particle The particle ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder particle(@NotNull Particle particle) { ++ this.particle = particle; ++ return this; ++ } ++ ++ /** ++ * @return List of players who will receive the particle, or null for all in world ++ */ ++ @Nullable ++ public List receivers() { ++ return receivers; ++ } ++ ++ /** ++ * Example use: ++ * ++ * builder.receivers(16); if (builder.hasReceivers()) { sendParticleAsync(builder); } ++ * ++ * @return If this particle is going to be sent to someone ++ */ ++ public boolean hasReceivers() { ++ return (receivers == null && !location.getWorld().getPlayers().isEmpty()) || ( ++ receivers != null && !receivers.isEmpty()); ++ } ++ ++ /** ++ * Sends this particle to all players in the world. This is rather silly and you should likely not ++ * be doing this. ++ * ++ * Just be a logical person and use receivers by radius or collection. ++ * ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder allPlayers() { ++ this.receivers = null; ++ return this; ++ } ++ ++ /** ++ * @param receivers List of players to receive this particle, or null for all players in the ++ * world ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder receivers(@Nullable List receivers) { ++ // Had to keep this as we first made API List<> and not Collection, but removing this may break plugins compiled on older jars ++ // TODO: deprecate? ++ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null; ++ return this; ++ } ++ ++ /** ++ * @param receivers List of players to receive this particle, or null for all players in the ++ * world ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder receivers(@Nullable Collection receivers) { ++ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null; ++ return this; ++ } ++ ++ /** ++ * @param receivers List of players to be receive this particle, or null for all players in the ++ * world ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder receivers(@Nullable Player... receivers) { ++ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null; ++ return this; ++ } ++ ++ /** ++ * Selects all players within a cuboid selection around the particle location, within the ++ * specified bounding box. If you want a more spherical check, see {@link #receivers(int, ++ * boolean)} ++ * ++ * @param radius amount to add on all axis ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder receivers(int radius) { ++ return receivers(radius, radius); ++ } ++ ++ /** ++ * Selects all players within the specified radius around the particle location. If byDistance is ++ * false, behavior uses cuboid selection the same as {@link #receivers(int, int)} If byDistance is ++ * true, radius is tested by distance in a spherical shape ++ * ++ * @param radius amount to add on each axis ++ * @param byDistance true to use a spherical radius, false to use a cuboid ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder receivers(int radius, boolean byDistance) { ++ if (!byDistance) { ++ return receivers(radius, radius, radius); ++ } else { ++ this.receivers = Lists.newArrayList(); ++ for (Player nearbyPlayer : location.getWorld() ++ .getNearbyPlayers(location, radius, radius, radius)) { ++ Location loc = nearbyPlayer.getLocation(); ++ double x = NumberConversions.square(location.getX() - loc.getX()); ++ double y = NumberConversions.square(location.getY() - loc.getY()); ++ double z = NumberConversions.square(location.getZ() - loc.getZ()); ++ if (Math.sqrt(x + y + z) > radius) { ++ continue; ++ } ++ this.receivers.add(nearbyPlayer); ++ } ++ return this; ++ } ++ } ++ ++ /** ++ * Selects all players within a cuboid selection around the particle location, within the ++ * specified bounding box. Allows specifying a different Y size than X and Z If you want a more ++ * cylinder check, see {@link #receivers(int, int, boolean)} If you want a more spherical check, ++ * see {@link #receivers(int, boolean)} ++ * ++ * @param xzRadius amount to add on the x/z axis ++ * @param yRadius amount to add on the y axis ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder receivers(int xzRadius, int yRadius) { ++ return receivers(xzRadius, yRadius, xzRadius); ++ } ++ ++ /** ++ * Selects all players within the specified radius around the particle location. If byDistance is ++ * false, behavior uses cuboid selection the same as {@link #receivers(int, int)} If byDistance is ++ * true, radius is tested by distance on the y plane and on the x/z plane, in a cylinder shape. ++ * ++ * @param xzRadius amount to add on the x/z axis ++ * @param yRadius amount to add on the y axis ++ * @param byDistance true to use a cylinder shape, false to use cuboid ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder receivers(int xzRadius, int yRadius, boolean byDistance) { ++ if (!byDistance) { ++ return receivers(xzRadius, yRadius, xzRadius); ++ } else { ++ this.receivers = Lists.newArrayList(); ++ for (Player nearbyPlayer : location.getWorld() ++ .getNearbyPlayers(location, xzRadius, yRadius, xzRadius)) { ++ Location loc = nearbyPlayer.getLocation(); ++ if (Math.abs(loc.getY() - this.location.getY()) > yRadius) { ++ continue; ++ } ++ double x = NumberConversions.square(location.getX() - loc.getX()); ++ double z = NumberConversions.square(location.getZ() - loc.getZ()); ++ if (x + z > NumberConversions.square(xzRadius)) { ++ continue; ++ } ++ this.receivers.add(nearbyPlayer); ++ } ++ return this; ++ } ++ } ++ ++ /** ++ * Selects all players within a cuboid selection around the particle location, within the ++ * specified bounding box. If you want a more cylinder check, see {@link #receivers(int, int, ++ * boolean)} If you want a more spherical check, see {@link #receivers(int, boolean)} ++ * ++ * @param xRadius amount to add on the x axis ++ * @param yRadius amount to add on the y axis ++ * @param zRadius amount to add on the z axis ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder receivers(int xRadius, int yRadius, int zRadius) { ++ if (location == null) { ++ throw new IllegalStateException("Please set location first"); ++ } ++ return receivers(location.getWorld().getNearbyPlayers(location, xRadius, yRadius, zRadius)); ++ } ++ ++ /** ++ * @return The player considered the source of this particle (for Visibility concerns), or null ++ */ ++ @Nullable ++ public Player source() { ++ return source; ++ } ++ ++ /** ++ * Sets the source of this particle for visibility concerns (Vanish API) ++ * ++ * @param source The player who is considered the source ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder source(@Nullable Player source) { ++ this.source = source; ++ return this; ++ } ++ ++ /** ++ * @return Location of where the particle will spawn ++ */ ++ @Nullable ++ public Location location() { ++ return location; ++ } ++ ++ /** ++ * Sets the location of where to spawn the particle ++ * ++ * @param location The location of the particle ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder location(@NotNull Location location) { ++ this.location = location.clone(); ++ return this; ++ } ++ ++ /** ++ * Sets the location of where to spawn the particle ++ * ++ * @param world World to spawn particle in ++ * @param x X location ++ * @param y Y location ++ * @param z Z location ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder location(@NotNull World world, double x, double y, double z) { ++ this.location = new Location(world, x, y, z); ++ return this; ++ } ++ ++ /** ++ * @return Number of particles to spawn ++ */ ++ public int count() { ++ return count; ++ } ++ ++ /** ++ * Sets the number of particles to spawn ++ * ++ * @param count Number of particles ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder count(int count) { ++ this.count = count; ++ return this; ++ } ++ ++ /** ++ * Particle offset X. Varies by particle on how this is used ++ * ++ * @return Particle offset X. ++ */ ++ public double offsetX() { ++ return offsetX; ++ } ++ ++ /** ++ * Particle offset Y. Varies by particle on how this is used ++ * ++ * @return Particle offset Y. ++ */ ++ public double offsetY() { ++ return offsetY; ++ } ++ ++ /** ++ * Particle offset Z. Varies by particle on how this is used ++ * ++ * @return Particle offset Z. ++ */ ++ public double offsetZ() { ++ return offsetZ; ++ } ++ ++ /** ++ * Sets the particle offset. Varies by particle on how this is used ++ * ++ * @param offsetX Particle offset X ++ * @param offsetY Particle offset Y ++ * @param offsetZ Particle offset Z ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder offset(double offsetX, double offsetY, double offsetZ) { ++ this.offsetX = offsetX; ++ this.offsetY = offsetY; ++ this.offsetZ = offsetZ; ++ return this; ++ } ++ ++ /** ++ * Gets the Particle extra data. Varies by particle on how this is used ++ * ++ * @return the extra particle data ++ */ ++ public double extra() { ++ return extra; ++ } ++ ++ /** ++ * Sets the particle extra data. Varies by particle on how this is used ++ * ++ * @param extra the extra particle data ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder extra(double extra) { ++ this.extra = extra; ++ return this; ++ } ++ ++ /** ++ * Gets the particle custom data. Varies by particle on how this is used ++ * ++ * @param The Particle data type ++ * @return the ParticleData for this particle ++ */ ++ @Nullable ++ public T data() { ++ //noinspection unchecked ++ return (T) data; ++ } ++ ++ /** ++ * Sets the particle custom data. Varies by particle on how this is used ++ * ++ * @param data The new particle data ++ * @param The Particle data type ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder data(@Nullable T data) { ++ this.data = data; ++ return this; ++ } ++ ++ /** ++ * Sets whether the particle is forcefully shown to the player. If forced, the particle will show ++ * faraway, as far as the player's view distance allows. If false, the particle will show ++ * according to the client's particle settings. ++ * ++ * @param force true to force, false for normal ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder force(boolean force) { ++ this.force = force; ++ return this; ++ } ++ ++ /** ++ * Sets the particle Color. Only valid for REDSTONE. ++ * ++ * @param color the new particle color ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder color(@Nullable Color color) { ++ return color(color, 1); ++ } ++ ++ /** ++ * Sets the particle Color and size. Only valid for REDSTONE. ++ * ++ * @param color the new particle color ++ * @param size the size of the particle ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder color(@Nullable Color color, float size) { ++ if (particle != Particle.REDSTONE && color != null) { ++ throw new IllegalStateException("Color may only be set on REDSTONE"); ++ } ++ ++ // We don't officially support reusing these objects, but here we go ++ if (color == null) { ++ if (data instanceof Particle.DustOptions) { ++ return data(null); ++ } else { ++ return this; ++ } ++ } ++ ++ return data(new Particle.DustOptions(color, size)); ++ } ++ ++ /** ++ * Sets the particle Color. ++ * Only valid for REDSTONE. ++ * @param r red color component ++ * @param g green color component ++ * @param b blue color component ++ * @return a reference to this object. ++ */ ++ @NotNull ++ public ParticleBuilder color(int r, int g, int b) { ++ return color(Color.fromRGB(r, g, b)); ++ } ++} +diff --git a/src/main/java/org/bukkit/Particle.java b/src/main/java/org/bukkit/Particle.java +index c5315ee1ed435c39a3ae298e248b67c5dc291497..687a62707c8021f87e03d6bc358b3b4e6da331e7 100644 +--- a/src/main/java/org/bukkit/Particle.java ++++ b/src/main/java/org/bukkit/Particle.java +@@ -123,6 +123,17 @@ public enum Particle { + return dataType; + } + ++ // Paper start - Particle API expansion ++ /** ++ * Creates a {@link com.destroystokyo.paper.ParticleBuilder} ++ * ++ * @return a {@link com.destroystokyo.paper.ParticleBuilder} for the particle ++ */ ++ @NotNull ++ public com.destroystokyo.paper.ParticleBuilder builder() { ++ return new com.destroystokyo.paper.ParticleBuilder(this); ++ } ++ // Paper end + /** + * Options which can be applied to redstone dust particles - a particle + * color and size. +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 6cc9c7fc913f229c4869a976e73253acb74fcda3..ca2b1cbff153c53ec9182e44a1979350bacd695b 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -2592,7 +2592,57 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + * @param data the data to use for the particle or null, + * the type of this depends on {@link Particle#getDataType()} + */ +- public void spawnParticle(@NotNull Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data); ++ public default void spawnParticle(@NotNull Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data) { spawnParticle(particle, null, null, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, true); }// Paper start - Expand Particle API ++ /** ++ * Spawns the particle (the number of times specified by count) ++ * at the target location. The position of each particle will be ++ * randomized positively and negatively by the offset parameters ++ * on each axis. ++ * ++ * @param particle the particle to spawn ++ * @param receivers List of players to receive the particles, or null for all in world ++ * @param source Source of the particles to be used in visibility checks, or null if no player source ++ * @param x the position on the x axis to spawn at ++ * @param y the position on the y axis to spawn at ++ * @param z the position on the z axis to spawn at ++ * @param count the number of particles ++ * @param offsetX the maximum random offset on the X axis ++ * @param offsetY the maximum random offset on the Y axis ++ * @param offsetZ the maximum random offset on the Z axis ++ * @param extra the extra data for this particle, depends on the ++ * particle used (normally speed) ++ * @param data the data to use for the particle or null, ++ * the type of this depends on {@link Particle#getDataType()} ++ * @param Type ++ */ ++ public default void spawnParticle(@NotNull Particle particle, @Nullable List receivers, @NotNull Player source, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data) { spawnParticle(particle, receivers, source, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, true); } ++ /** ++ * Spawns the particle (the number of times specified by count) ++ * at the target location. The position of each particle will be ++ * randomized positively and negatively by the offset parameters ++ * on each axis. ++ * ++ * @param particle the particle to spawn ++ * @param receivers List of players to receive the particles, or null for all in world ++ * @param source Source of the particles to be used in visibility checks, or null if no player source ++ * @param x the position on the x axis to spawn at ++ * @param y the position on the y axis to spawn at ++ * @param z the position on the z axis to spawn at ++ * @param count the number of particles ++ * @param offsetX the maximum random offset on the X axis ++ * @param offsetY the maximum random offset on the Y axis ++ * @param offsetZ the maximum random offset on the Z axis ++ * @param extra the extra data for this particle, depends on the ++ * particle used (normally speed) ++ * @param data the data to use for the particle or null, ++ * the type of this depends on {@link Particle#getDataType()} ++ * @param Type ++ * @param force allows the particle to be seen further away from the player ++ * and shows to players using any vanilla client particle settings ++ */ ++ public void spawnParticle(@NotNull Particle particle, @Nullable List receivers, @Nullable Player source, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data, boolean force); ++ // Paper end ++ + + /** + * Spawns the particle (the number of times specified by count) diff --git a/patches/api-unmapped/0098-EndermanAttackPlayerEvent.patch b/patches/api-unmapped/0098-EndermanAttackPlayerEvent.patch new file mode 100644 index 0000000000..9f3e105c9d --- /dev/null +++ b/patches/api-unmapped/0098-EndermanAttackPlayerEvent.patch @@ -0,0 +1,116 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 1 May 2018 20:17:44 -0400 +Subject: [PATCH] EndermanAttackPlayerEvent + +Allow control over whether or not an enderman aggros a player. + +This allows you to override/extend the pumpkin/stare logic. + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f530a3d9314e17d1da896cac633f6a422258d9a9 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java +@@ -0,0 +1,101 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Enderman; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when an Enderman determines if it should attack a player or not. ++ * Starts off cancelled if the player is wearing a pumpkin head or is not looking ++ * at the Enderman, according to Vanilla rules. ++ * ++ */ ++public class EndermanAttackPlayerEvent extends EntityEvent implements Cancellable { ++ @NotNull private final Player player; ++ ++ public EndermanAttackPlayerEvent(@NotNull Enderman entity, @NotNull Player player) { ++ super(entity); ++ this.player = player; ++ } ++ ++ /** ++ * The enderman considering attacking ++ * ++ * @return The enderman considering attacking ++ */ ++ @NotNull ++ @Override ++ public Enderman getEntity() { ++ return (Enderman) super.getEntity(); ++ } ++ ++ /** ++ * The player the Enderman is considering attacking ++ * ++ * @return The player the Enderman is considering attacking ++ */ ++ @NotNull ++ public Player getPlayer() { ++ return player; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ /** ++ * ++ * @return If cancelled, the enderman will not attack ++ */ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * Cancels if the Enderman will attack this player ++ * @param cancel true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0099-Close-Plugin-Class-Loaders-on-Disable.patch b/patches/api-unmapped/0099-Close-Plugin-Class-Loaders-on-Disable.patch new file mode 100644 index 0000000000..6580fe3c76 --- /dev/null +++ b/patches/api-unmapped/0099-Close-Plugin-Class-Loaders-on-Disable.patch @@ -0,0 +1,141 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 1 May 2018 21:33:35 -0400 +Subject: [PATCH] Close Plugin Class Loaders on Disable + +This should close more memory leaks from /reload and disabling plugins, +by closing the class loader and the jar file. + +diff --git a/src/main/java/org/bukkit/plugin/PluginLoader.java b/src/main/java/org/bukkit/plugin/PluginLoader.java +index a88733f1cd1ddb5d85ab1b0e6af4fd5b80bbc1c6..6ab9cd8213cbe35943748dcf42948d5fc048c84c 100644 +--- a/src/main/java/org/bukkit/plugin/PluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/PluginLoader.java +@@ -77,4 +77,18 @@ public interface PluginLoader { + * @param plugin Plugin to disable + */ + public void disablePlugin(@NotNull Plugin plugin); ++ // Paper start - close Classloader on disable ++ /** ++ * Disables the specified plugin ++ *

    ++ * Attempting to disable a plugin that is not enabled will have no effect ++ * ++ * @param plugin Plugin to disable ++ * @param closeClassloader if the classloader for the Plugin should be closed ++ */ ++ // provide default to allow other PluginLoader implementations to work ++ default public void disablePlugin(@NotNull Plugin plugin, boolean closeClassloader) { ++ disablePlugin(plugin); ++ } ++ // Paper end - close Classloader on disable + } +diff --git a/src/main/java/org/bukkit/plugin/PluginManager.java b/src/main/java/org/bukkit/plugin/PluginManager.java +index 41e26451fe12d8e6e0ef73c85731b24b4e3f200c..86cc5025ad98f7a752c51713b7cd6a39d5136ecc 100644 +--- a/src/main/java/org/bukkit/plugin/PluginManager.java ++++ b/src/main/java/org/bukkit/plugin/PluginManager.java +@@ -161,6 +161,18 @@ public interface PluginManager { + */ + public void disablePlugin(@NotNull Plugin plugin); + ++ // Paper start - close Classloader on disable ++ /** ++ * Disables the specified plugin ++ *

    ++ * Attempting to disable a plugin that is not enabled will have no effect ++ * ++ * @param plugin Plugin to disable ++ * @param closeClassloader if the classloader for the Plugin should be closed ++ */ ++ public void disablePlugin(@NotNull Plugin plugin, boolean closeClassloader); ++ // Paper end - close Classloader on disable ++ + /** + * Gets a {@link Permission} from its fully qualified name + * +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index 8b33d914d29897c0276f9e2e7ce83bd2c316d5e2..a7393d2830b95d7167121b02066a3f357cee6085 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -492,17 +492,28 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void disablePlugins() { ++ disablePlugins(false); ++ } ++ ++ public void disablePlugins(boolean closeClassloaders) { ++ // Paper end - close Classloader on disable + Plugin[] plugins = getPlugins(); + for (int i = plugins.length - 1; i >= 0; i--) { +- disablePlugin(plugins[i]); ++ disablePlugin(plugins[i], closeClassloaders); // Paper - close Classloader on disable + } + } + + @Override + public void disablePlugin(@NotNull final Plugin plugin) { ++ disablePlugin(plugin, false); ++ } ++ ++ @Override ++ public void disablePlugin(@NotNull final Plugin plugin, boolean closeClassloader) { ++ // Paper end - close Classloader on disable + if (plugin.isEnabled()) { + try { +- plugin.getPluginLoader().disablePlugin(plugin); ++ plugin.getPluginLoader().disablePlugin(plugin, closeClassloader); // Paper - close Classloader on disable + } catch (Throwable ex) { + handlePluginException("Error occurred (in the plugin loader) while disabling " + + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper +@@ -557,7 +568,7 @@ public final class SimplePluginManager implements PluginManager { + @Override + public void clearPlugins() { + synchronized (this) { +- disablePlugins(); ++ disablePlugins(true); // Paper - close Classloader on disable + plugins.clear(); + lookupNames.clear(); + dependencyGraph = GraphBuilder.directed().build(); +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index 79ac529017aac059d13fe342f279e9c8faeba599..816c2b1797447ab315ceb6eda89d25f27d2bce98 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -322,7 +322,7 @@ public final class JavaPluginLoader implements PluginLoader { + } catch (Throwable ex) { + server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); + // Paper start - Disable plugins that fail to load +- disablePlugin(jPlugin); ++ server.getPluginManager().disablePlugin(jPlugin, true); // Paper - close Classloader on disable - She's dead jim + return; + // Paper end + } +@@ -335,6 +335,12 @@ public final class JavaPluginLoader implements PluginLoader { + + @Override + public void disablePlugin(@NotNull Plugin plugin) { ++ // Paper start - close Classloader on disable ++ disablePlugin(plugin, false); // Retain old behavior unless requested ++ } ++ ++ public void disablePlugin(@NotNull Plugin plugin, boolean closeClassloader) { ++ // Paper end - close Class Loader on disable + Validate.isTrue(plugin instanceof JavaPlugin, "Plugin is not associated with this PluginLoader"); + + if (plugin.isEnabled()) { +@@ -367,6 +373,16 @@ public final class JavaPluginLoader implements PluginLoader { + } catch (IOException ex) { + // + } ++ // Paper start - close Class Loader on disable ++ try { ++ if (closeClassloader) { ++ loader.close(); ++ } ++ } catch (IOException e) { ++ server.getLogger().log(Level.WARNING, "Error closing the Plugin Class Loader for " + plugin.getDescription().getFullName()); ++ e.printStackTrace(); ++ } ++ // Paper end + } + } + } diff --git a/patches/api-unmapped/0100-WitchConsumePotionEvent.patch b/patches/api-unmapped/0100-WitchConsumePotionEvent.patch new file mode 100644 index 0000000000..fab6106411 --- /dev/null +++ b/patches/api-unmapped/0100-WitchConsumePotionEvent.patch @@ -0,0 +1,122 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 16 May 2018 20:26:16 -0400 +Subject: [PATCH] WitchConsumePotionEvent + +Fires when a witch consumes the potion in their hand + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchConsumePotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchConsumePotionEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fbbace36d69373046a7f3618ed5c1c1318b489b9 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchConsumePotionEvent.java +@@ -0,0 +1,70 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Witch; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Fired when a witch consumes the potion in their hand to buff themselves. ++ */ ++public class WitchConsumePotionEvent extends EntityEvent implements Cancellable { ++ @Nullable private ItemStack potion; ++ ++ public WitchConsumePotionEvent(@NotNull Witch witch, @Nullable ItemStack potion) { ++ super(witch); ++ this.potion = potion; ++ } ++ ++ @NotNull ++ @Override ++ public Witch getEntity() { ++ return (Witch) super.getEntity(); ++ } ++ ++ /** ++ * @return the potion the witch will consume and have the effects applied. ++ */ ++ @Nullable ++ public ItemStack getPotion() { ++ return potion; ++ } ++ ++ /** ++ * Sets the potion to be consumed and applied to the witch. ++ * @param potion The potion ++ */ ++ public void setPotion(@Nullable ItemStack potion) { ++ this.potion = potion != null ? potion.clone() : null; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ /** ++ * @return Event was cancelled or potion was null ++ */ ++ @Override ++ public boolean isCancelled() { ++ return cancelled || potion == null; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6ef6367b67261c2b653a97322b9703a9409b3499 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java +@@ -0,0 +1,33 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++ ++public class WitchThrowPotionEvent extends Event implements Cancellable { ++ public WitchThrowPotionEvent() { ++ } ++ ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0101-WitchThrowPotionEvent.patch b/patches/api-unmapped/0101-WitchThrowPotionEvent.patch new file mode 100644 index 0000000000..a5dfe42f35 --- /dev/null +++ b/patches/api-unmapped/0101-WitchThrowPotionEvent.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 16 May 2018 20:39:09 -0400 +Subject: [PATCH] WitchThrowPotionEvent + +Fired when a witch throws a potion at a player + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java +index 6ef6367b67261c2b653a97322b9703a9409b3499..688a596aa2b925651a92bf092e1ef4d77a47258c 100644 +--- a/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java ++++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java +@@ -1,29 +1,77 @@ + package com.destroystokyo.paper.event.entity; + ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Witch; + import org.bukkit.event.Cancellable; +-import org.bukkit.event.Event; + import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; + +-public class WitchThrowPotionEvent extends Event implements Cancellable { +- public WitchThrowPotionEvent() { ++/** ++ * Fired when a witch throws a potion at a player ++ */ ++public class WitchThrowPotionEvent extends EntityEvent implements Cancellable { ++ @NotNull private final LivingEntity target; ++ @Nullable private ItemStack potion; ++ ++ public WitchThrowPotionEvent(@NotNull Witch witch, @NotNull LivingEntity target, @Nullable ItemStack potion) { ++ super(witch); ++ this.target = target; ++ this.potion = potion; + } + ++ @NotNull ++ @Override ++ public Witch getEntity() { ++ return (Witch) super.getEntity(); ++ } ++ ++ /** ++ * @return The target of the potion ++ */ ++ @NotNull ++ public LivingEntity getTarget() { ++ return target; ++ } ++ ++ /** ++ * @return The potion the witch will throw at a player ++ */ ++ @Nullable ++ public ItemStack getPotion() { ++ return potion; ++ } ++ ++ /** ++ * Sets the potion to be thrown at a player ++ * @param potion The potion ++ */ ++ public void setPotion(@Nullable ItemStack potion) { ++ this.potion = potion != null ? potion.clone() : null; ++ } + + private static final HandlerList handlers = new HandlerList(); + ++ @NotNull + public HandlerList getHandlers() { + return handlers; + } + ++ @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + + private boolean cancelled = false; + ++ /** ++ * @return Event was cancelled or potion was null ++ */ + @Override + public boolean isCancelled() { +- return cancelled; ++ return cancelled || potion == null; + } + + @Override diff --git a/patches/api-unmapped/0102-Location.toBlockLocation-toCenterLocation.patch b/patches/api-unmapped/0102-Location.toBlockLocation-toCenterLocation.patch new file mode 100644 index 0000000000..1f3ad622a7 --- /dev/null +++ b/patches/api-unmapped/0102-Location.toBlockLocation-toCenterLocation.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 24 May 2018 21:01:13 -0400 +Subject: [PATCH] Location.toBlockLocation/toCenterLocation() + +Convert location objects to their block coordinates, or the center of the block + +diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java +index 6c8b8eddcdb81f7151202eb12541308040790d45..f61bf28afe99f83cdac6490bcc114509698d0aad 100644 +--- a/src/main/java/org/bukkit/Location.java ++++ b/src/main/java/org/bukkit/Location.java +@@ -534,6 +534,31 @@ public class Location implements Cloneable, ConfigurationSerializable { + } + + public boolean isChunkLoaded() { return this.getWorld().isChunkLoaded(locToBlock(x) >> 4, locToBlock(z) >> 4); } // Paper ++ ++ // Paper start ++ /** ++ * @return A new location where X/Y/Z are on the Block location (integer value of X/Y/Z) ++ */ ++ @NotNull ++ public Location toBlockLocation() { ++ Location blockLoc = clone(); ++ blockLoc.setX(getBlockX()); ++ blockLoc.setY(getBlockY()); ++ blockLoc.setZ(getBlockZ()); ++ return blockLoc; ++ } ++ /** ++ * @return A new location where X/Y/Z are the center of the block ++ */ ++ @NotNull ++ public Location toCenterLocation() { ++ Location centerLoc = clone(); ++ centerLoc.setX(getBlockX() + 0.5); ++ centerLoc.setY(getBlockY() + 0.5); ++ centerLoc.setZ(getBlockZ() + 0.5); ++ return centerLoc; ++ } ++ // Paper end + @Override + public boolean equals(Object obj) { + if (obj == null) { diff --git a/patches/api-unmapped/0103-PotionEffect-clone-methods.patch b/patches/api-unmapped/0103-PotionEffect-clone-methods.patch new file mode 100644 index 0000000000..7f4e064a78 --- /dev/null +++ b/patches/api-unmapped/0103-PotionEffect-clone-methods.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 Jun 2018 04:10:13 -0400 +Subject: [PATCH] PotionEffect clone methods + + +diff --git a/src/main/java/org/bukkit/potion/PotionEffect.java b/src/main/java/org/bukkit/potion/PotionEffect.java +index 60716c627d315b08c3fe03b1a945af60c350711f..74767751199bce03d63f2a9524712656193f850c 100644 +--- a/src/main/java/org/bukkit/potion/PotionEffect.java ++++ b/src/main/java/org/bukkit/potion/PotionEffect.java +@@ -101,6 +101,33 @@ public class PotionEffect implements ConfigurationSerializable { + this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT, false), getBool(map, PARTICLES, true), getBool(map, ICON, getBool(map, PARTICLES, true))); + } + ++ // Paper start ++ @NotNull ++ public PotionEffect withType(@NotNull PotionEffectType type) { ++ return new PotionEffect(type, duration, amplifier, ambient, particles, icon); ++ } ++ @NotNull ++ public PotionEffect withDuration(int duration) { ++ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); ++ } ++ @NotNull ++ public PotionEffect withAmplifier(int amplifier) { ++ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); ++ } ++ @NotNull ++ public PotionEffect withAmbient(boolean ambient) { ++ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); ++ } ++ @NotNull ++ public PotionEffect withParticles(boolean particles) { ++ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); ++ } ++ @NotNull ++ public PotionEffect withIcon(boolean icon) { ++ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); ++ } ++ // Paper end ++ + @NotNull + private static PotionEffectType getEffectType(@NotNull Map map) { + int type = getInt(map, TYPE); diff --git a/patches/api-unmapped/0104-WitchReadyPotionEvent.patch b/patches/api-unmapped/0104-WitchReadyPotionEvent.patch new file mode 100644 index 0000000000..5722426049 --- /dev/null +++ b/patches/api-unmapped/0104-WitchReadyPotionEvent.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Jun 2018 22:47:08 -0400 +Subject: [PATCH] WitchReadyPotionEvent + +Control what potion the witch readies to use + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchReadyPotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchReadyPotionEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5351b523defa054ba56ae3fb591029283ca7510d +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchReadyPotionEvent.java +@@ -0,0 +1,80 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.Material; ++import org.bukkit.entity.Witch; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++public class WitchReadyPotionEvent extends EntityEvent implements Cancellable { ++ private ItemStack potion; ++ ++ public WitchReadyPotionEvent(@NotNull Witch witch, @Nullable ItemStack potion) { ++ super(witch); ++ this.potion = potion; ++ } ++ ++ /** ++ * Fires thee event, returning the desired potion, or air of cancelled ++ * @param witch the witch whom is readying to use a potion ++ * @param potion the potion to be used ++ * @return The ItemStack to be used ++ */ ++ @Nullable ++ public static ItemStack process(@NotNull Witch witch, @Nullable ItemStack potion) { ++ WitchReadyPotionEvent event = new WitchReadyPotionEvent(witch, potion); ++ if (!event.callEvent() || event.getPotion() == null) { ++ return new ItemStack(Material.AIR); ++ } ++ return event.getPotion(); ++ } ++ ++ @NotNull ++ @Override ++ public Witch getEntity() { ++ return (Witch) super.getEntity(); ++ } ++ ++ /** ++ * @return the potion the witch is readying to use ++ */ ++ @Nullable ++ public ItemStack getPotion() { ++ return potion; ++ } ++ ++ /** ++ * Sets the potion the which is going to hold and use ++ * @param potion The potion ++ */ ++ public void setPotion(@Nullable ItemStack potion) { ++ this.potion = potion != null ? potion.clone() : null; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0105-ItemStack-getMaxItemUseDuration.patch b/patches/api-unmapped/0105-ItemStack-getMaxItemUseDuration.patch new file mode 100644 index 0000000000..b00193d717 --- /dev/null +++ b/patches/api-unmapped/0105-ItemStack-getMaxItemUseDuration.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Jun 2018 22:59:50 -0400 +Subject: [PATCH] ItemStack#getMaxItemUseDuration + +Allows you to determine how long it takes to use a usable/consumable item + +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index 82bd3e6701dbd7df9f0f8c3801c5ae1baba4eec5..f41701e6374ca23eca4bdb092e385053a12eb718 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -636,5 +636,13 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + public String getI18NDisplayName() { + return Bukkit.getServer().getItemFactory().getI18NDisplayName(this); + } ++ ++ public int getMaxItemUseDuration() { ++ if (type == null || type == Material.AIR || !type.isItem()) { ++ return 0; ++ } ++ // Requires access to NMS ++ return ensureServerConversions().getMaxItemUseDuration(); ++ } + // Paper end + } diff --git a/patches/api-unmapped/0106-Add-EntityTeleportEndGatewayEvent.patch b/patches/api-unmapped/0106-Add-EntityTeleportEndGatewayEvent.patch new file mode 100644 index 0000000000..0422ec9858 --- /dev/null +++ b/patches/api-unmapped/0106-Add-EntityTeleportEndGatewayEvent.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 9 Jun 2018 13:08:21 +0100 +Subject: [PATCH] Add EntityTeleportEndGatewayEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityTeleportEndGatewayEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityTeleportEndGatewayEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bfc69a43c291fbed91b9d0387e4ef18b0ed1b9de +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityTeleportEndGatewayEvent.java +@@ -0,0 +1,31 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.Location; ++import org.bukkit.block.EndGateway; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired any time an entity attempts to teleport in an end gateway ++ */ ++public class EntityTeleportEndGatewayEvent extends EntityTeleportEvent { ++ ++ @NotNull private final EndGateway gateway; ++ ++ public EntityTeleportEndGatewayEvent(@NotNull Entity what, @NotNull Location from, @NotNull Location to, @NotNull EndGateway gateway) { ++ super(what, from, to); ++ this.gateway = gateway; ++ } ++ ++ /** ++ * The gateway triggering the teleport ++ * ++ * @return EndGateway used ++ */ ++ @NotNull ++ public EndGateway getGateway() { ++ return gateway; ++ } ++ ++} diff --git a/patches/api-unmapped/0107-Make-shield-blocking-delay-configurable.patch b/patches/api-unmapped/0107-Make-shield-blocking-delay-configurable.patch new file mode 100644 index 0000000000..cec33b7a78 --- /dev/null +++ b/patches/api-unmapped/0107-Make-shield-blocking-delay-configurable.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 16 Jun 2018 01:17:39 -0500 +Subject: [PATCH] Make shield blocking delay configurable + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 33fffda7c8b05cde3c95623937e7eb6c8b628ec6..879dec59f202ee95043bd7317a672cd59ab3bbbe 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -628,5 +628,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + * @param arrows Number of arrows to stick in this entity + */ + void setArrowsStuck(int arrows); ++ ++ /** ++ * Get the delay (in ticks) before blocking is effective for this entity ++ * ++ * @return Delay in ticks ++ */ ++ int getShieldBlockingDelay(); ++ ++ /** ++ * Set the delay (in ticks) before blocking is effective for this entity ++ * ++ * @param delay Delay in ticks ++ */ ++ void setShieldBlockingDelay(int delay); + // Paper end + } diff --git a/patches/api-unmapped/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch b/patches/api-unmapped/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch new file mode 100644 index 0000000000..71a82a8eae --- /dev/null +++ b/patches/api-unmapped/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 15 Jun 2013 19:52:04 -0400 +Subject: [PATCH] EntityShootBowEvent consumeArrow and getArrowItem API + +Adds ability to get what arrow was shot, and control if it should be consumed. + +diff --git a/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java b/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java +index d4d7ad9c3c953680342c121f39ddaef476549047..719d0d878320c1903b44076053989ba99fa0e92a 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java +@@ -22,7 +22,32 @@ public class EntityShootBowEvent extends EntityEvent implements Cancellable { + private final float force; + private boolean consumeItem; + private boolean cancelled; ++ // Paper start ++ @Deprecated ++ public void setConsumeArrow(boolean consumeArrow) { ++ this.setConsumeItem(consumeArrow); ++ } ++ ++ @Deprecated ++ public boolean getConsumeArrow() { ++ return this.shouldConsumeItem(); ++ } ++ ++ @NotNull @Deprecated ++ public ItemStack getArrowItem() { ++ return this.getConsumable(); ++ } ++ ++ @Deprecated ++ public EntityShootBowEvent(@NotNull final LivingEntity shooter, @Nullable final ItemStack bow, @NotNull final Entity projectile, final float force) { ++ this(shooter, bow, new ItemStack(org.bukkit.Material.AIR), projectile, force); ++ } + ++ @Deprecated ++ public EntityShootBowEvent(@NotNull final LivingEntity shooter, @Nullable final ItemStack bow, @NotNull ItemStack arrowItem, @NotNull final Entity projectile, final float force) { ++ this(shooter, bow, arrowItem, projectile, EquipmentSlot.HAND, force, true); ++ } ++ // Paper end + public EntityShootBowEvent(@NotNull final LivingEntity shooter, @Nullable final ItemStack bow, @Nullable final ItemStack consumable, @NotNull final Entity projectile, @NotNull final EquipmentSlot hand, final float force, final boolean consumeItem) { + super(shooter); + this.bow = bow; diff --git a/patches/api-unmapped/0109-Add-getNearbyXXX-methods-to-Location.patch b/patches/api-unmapped/0109-Add-getNearbyXXX-methods-to-Location.patch new file mode 100644 index 0000000000..a362af6260 --- /dev/null +++ b/patches/api-unmapped/0109-Add-getNearbyXXX-methods-to-Location.patch @@ -0,0 +1,275 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 18 Jun 2018 00:41:46 -0500 +Subject: [PATCH] Add "getNearbyXXX" methods to Location + + +diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java +index f61bf28afe99f83cdac6490bcc114509698d0aad..4cf22afc3c1f1cc19b6e5350043431215908a612 100644 +--- a/src/main/java/org/bukkit/Location.java ++++ b/src/main/java/org/bukkit/Location.java +@@ -12,6 +12,15 @@ import org.bukkit.util.Vector; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + ++// Paper start ++import java.util.Collection; ++import java.util.Collections; ++import java.util.function.Predicate; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Player; ++// Paper end ++ + /** + * Represents a 3-dimensional position in a world. + *
    +@@ -558,6 +567,248 @@ public class Location implements Cloneable, ConfigurationSerializable { + centerLoc.setZ(getBlockZ() + 0.5); + return centerLoc; + } ++ ++ /** ++ * Returns a list of entities within a bounding box centered around a Location. ++ * ++ * Some implementations may impose artificial restrictions on the size of the search bounding box. ++ * ++ * @param x 1/2 the size of the box along x axis ++ * @param y 1/2 the size of the box along y axis ++ * @param z 1/2 the size of the box along z axis ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyEntities(double x, double y, double z) { ++ World world = this.getWorld(); ++ if (world == null) { ++ throw new IllegalArgumentException("Location has no world"); ++ } ++ return world.getNearbyEntities(this, x, y, z); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param radius X Radius ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyLivingEntities(double radius) { ++ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, radius, radius, radius); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param xzRadius X/Z Radius ++ * @param yRadius Y Radius ++ * @return the collection of living entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyLivingEntities(double xzRadius, double yRadius) { ++ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, xzRadius, yRadius, xzRadius); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param xRadius X Radius ++ * @param yRadius Y Radius ++ * @param zRadius Z radius ++ * @return the collection of living entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyLivingEntities(double xRadius, double yRadius, double zRadius) { ++ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, xRadius, yRadius, zRadius); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param radius Radius ++ * @param predicate a predicate used to filter results ++ * @return the collection of living entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyLivingEntities(double radius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, radius, radius, radius, predicate); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param xzRadius X/Z Radius ++ * @param yRadius Y Radius ++ * @param predicate a predicate used to filter results ++ * @return the collection of living entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyLivingEntities(double xzRadius, double yRadius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, xzRadius, yRadius, xzRadius, predicate); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param xRadius X Radius ++ * @param yRadius Y Radius ++ * @param zRadius Z radius ++ * @param predicate a predicate used to filter results ++ * @return the collection of living entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyLivingEntities(double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, xRadius, yRadius, zRadius, predicate); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param radius X/Y/Z Radius ++ * @return the collection of players near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyPlayers(double radius) { ++ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, radius, radius, radius); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param xzRadius X/Z Radius ++ * @param yRadius Y Radius ++ * @return the collection of players near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyPlayers(double xzRadius, double yRadius) { ++ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, xzRadius, yRadius, xzRadius); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param xRadius X Radius ++ * @param yRadius Y Radius ++ * @param zRadius Z Radius ++ * @return the collection of players near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyPlayers(double xRadius, double yRadius, double zRadius) { ++ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, xRadius, yRadius, zRadius); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param radius X/Y/Z Radius ++ * @param predicate a predicate used to filter results ++ * @return the collection of players near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyPlayers(double radius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, radius, radius, radius, predicate); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param xzRadius X/Z Radius ++ * @param yRadius Y Radius ++ * @param predicate a predicate used to filter results ++ * @return the collection of players near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyPlayers(double xzRadius, double yRadius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, xzRadius, yRadius, xzRadius, predicate); ++ } ++ ++ /** ++ * Gets nearby players within the specified radius (bounding box) ++ * @param xRadius X Radius ++ * @param yRadius Y Radius ++ * @param zRadius Z Radius ++ * @param predicate a predicate used to filter results ++ * @return the collection of players near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyPlayers(double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, xRadius, yRadius, zRadius, predicate); ++ } ++ ++ /** ++ * Gets all nearby entities of the specified type, within the specified radius (bounding box) ++ * @param clazz Type to filter by ++ * @param radius X/Y/Z radius to search within ++ * @param the entity type ++ * @return the collection of entities of type clazz near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double radius) { ++ return getNearbyEntitiesByType(clazz, radius, radius, radius, null); ++ } ++ ++ /** ++ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box) ++ * @param clazz Type to filter by ++ * @param xzRadius X/Z radius to search within ++ * @param yRadius Y radius to search within ++ * @param the entity type ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double xzRadius, double yRadius) { ++ return getNearbyEntitiesByType(clazz, xzRadius, yRadius, xzRadius, null); ++ } ++ ++ /** ++ * Gets all nearby entities of the specified type, within the specified radius (bounding box) ++ * @param clazz Type to filter by ++ * @param xRadius X Radius ++ * @param yRadius Y Radius ++ * @param zRadius Z Radius ++ * @param the entity type ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double xRadius, double yRadius, double zRadius) { ++ return getNearbyEntitiesByType(clazz, xRadius, yRadius, zRadius, null); ++ } ++ ++ /** ++ * Gets all nearby entities of the specified type, within the specified radius (bounding box) ++ * @param clazz Type to filter by ++ * @param radius X/Y/Z radius to search within ++ * @param predicate a predicate used to filter results ++ * @param the entity type ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double radius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(clazz, radius, radius, radius, predicate); ++ } ++ ++ /** ++ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box) ++ * @param clazz Type to filter by ++ * @param xzRadius X/Z radius to search within ++ * @param yRadius Y radius to search within ++ * @param predicate a predicate used to filter results ++ * @param the entity type ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double xzRadius, double yRadius, @Nullable Predicate predicate) { ++ return getNearbyEntitiesByType(clazz, xzRadius, yRadius, xzRadius, predicate); ++ } ++ ++ /** ++ * Gets all nearby entities of the specified type, within the specified radius (bounding box) ++ * @param clazz Type to filter by ++ * @param xRadius X Radius ++ * @param yRadius Y Radius ++ * @param zRadius Z Radius ++ * @param predicate a predicate used to filter results ++ * @param the entity type ++ * @return the collection of entities near location. This will always be a non-null collection. ++ */ ++ @NotNull ++ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { ++ World world = this.getWorld(); ++ if (world == null) { ++ throw new IllegalArgumentException("Location has no world"); ++ } ++ return world.getNearbyEntitiesByType(clazz, this, xRadius, yRadius, zRadius, predicate); ++ } + // Paper end + @Override + public boolean equals(Object obj) { diff --git a/patches/api-unmapped/0110-PlayerReadyArrowEvent.patch b/patches/api-unmapped/0110-PlayerReadyArrowEvent.patch new file mode 100644 index 0000000000..7ea1740581 --- /dev/null +++ b/patches/api-unmapped/0110-PlayerReadyArrowEvent.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 18 Jun 2018 01:09:27 -0400 +Subject: [PATCH] PlayerReadyArrowEvent + +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/com/destroystokyo/paper/event/player/PlayerReadyArrowEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerReadyArrowEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5d04a22fd6964d8d44a2aa069c9629722893b1f4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerReadyArrowEvent.java +@@ -0,0 +1,93 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a player is firing a bow and the server is choosing an arrow to use. ++ */ ++public class PlayerReadyArrowEvent extends PlayerEvent implements Cancellable { ++ @NotNull private final ItemStack bow; ++ @NotNull private final ItemStack arrow; ++ ++ public PlayerReadyArrowEvent(@NotNull Player player, @NotNull ItemStack bow, @NotNull ItemStack arrow) { ++ super(player); ++ this.bow = bow; ++ this.arrow = arrow; ++ } ++ ++ /** ++ * @return the player is using to fire the arrow ++ */ ++ @NotNull ++ public ItemStack getBow() { ++ return bow; ++ } ++ ++ /** ++ * @return the arrow that is attempting to be used ++ */ ++ @NotNull ++ public ItemStack getArrow() { ++ return arrow; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ /** ++ * Whether or not use of this arrow is cancelled. On cancel, the server will try the next arrow available and fire another event. ++ */ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * Cancel use of this arrow. On cancel, the server will try the next arrow available and fire another event. ++ * @param cancel true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0111-Add-EntityKnockbackByEntityEvent.patch b/patches/api-unmapped/0111-Add-EntityKnockbackByEntityEvent.patch new file mode 100644 index 0000000000..1620ab68a6 --- /dev/null +++ b/patches/api-unmapped/0111-Add-EntityKnockbackByEntityEvent.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Mon, 18 Jun 2018 15:40:39 +0200 +Subject: [PATCH] Add EntityKnockbackByEntityEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityKnockbackByEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityKnockbackByEntityEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9efecabab813f575bb447a356e5e7e952d110f30 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityKnockbackByEntityEvent.java +@@ -0,0 +1,82 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.bukkit.util.Vector; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when an Entity is knocked back by the hit of another Entity. The acceleration ++ * vector can be modified. If this event is cancelled, the entity is not knocked back. ++ * ++ */ ++public class EntityKnockbackByEntityEvent extends EntityEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull private final Entity hitBy; ++ private final float knockbackStrength; ++ @NotNull private final Vector acceleration; ++ private boolean cancelled = false; ++ ++ public EntityKnockbackByEntityEvent(@NotNull LivingEntity entity, @NotNull Entity hitBy, float knockbackStrength, @NotNull Vector acceleration) { ++ super(entity); ++ this.hitBy = hitBy; ++ this.knockbackStrength = knockbackStrength; ++ this.acceleration = acceleration; ++ } ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++ ++ /** ++ * @return the entity which was knocked back ++ */ ++ @NotNull ++ @Override ++ public LivingEntity getEntity() { ++ return (LivingEntity) super.getEntity(); ++ } ++ ++ /** ++ * @return the original knockback strength. ++ */ ++ public float getKnockbackStrength() { ++ return knockbackStrength; ++ } ++ ++ /** ++ * @return the Entity which hit ++ */ ++ @NotNull ++ public Entity getHitBy() { ++ return hitBy; ++ } ++ ++ /** ++ * @return the acceleration that will be applied ++ */ ++ @NotNull ++ public Vector getAcceleration() { ++ return acceleration; ++ } ++} diff --git a/patches/api-unmapped/0112-Expand-Explosions-API.patch b/patches/api-unmapped/0112-Expand-Explosions-API.patch new file mode 100644 index 0000000000..389fec9570 --- /dev/null +++ b/patches/api-unmapped/0112-Expand-Explosions-API.patch @@ -0,0 +1,200 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 16:24:42 -0500 +Subject: [PATCH] Expand Explosions API + +Add Entity as a Source capability, and add more API choices, and on Location. + +diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java +index 4cf22afc3c1f1cc19b6e5350043431215908a612..af2ee43f2c5133668c18710f526a107d94a5d898 100644 +--- a/src/main/java/org/bukkit/Location.java ++++ b/src/main/java/org/bukkit/Location.java +@@ -7,6 +7,7 @@ import java.util.HashMap; + import java.util.Map; + import org.bukkit.block.Block; + import org.bukkit.configuration.serialization.ConfigurationSerializable; ++import org.bukkit.entity.Entity; // Paper + import org.bukkit.util.NumberConversions; + import org.bukkit.util.Vector; + import org.jetbrains.annotations.NotNull; +@@ -568,6 +569,87 @@ public class Location implements Cloneable, ConfigurationSerializable { + return centerLoc; + } + ++ /** ++ * Creates explosion at this location with given power ++ * ++ * Will break blocks and ignite blocks on fire. ++ * ++ * @param power The power of explosion, where 4F is TNT ++ * @return false if explosion was canceled, otherwise true ++ */ ++ public boolean createExplosion(float power) { ++ return this.getWorld().createExplosion(this, power); ++ } ++ ++ /** ++ * Creates explosion at this location with given power and optionally ++ * setting blocks on fire. ++ * ++ * Will break blocks. ++ * ++ * @param power The power of explosion, where 4F is TNT ++ * @param setFire Whether or not to set blocks on fire ++ * @return false if explosion was canceled, otherwise true ++ */ ++ public boolean createExplosion(float power, boolean setFire) { ++ return this.getWorld().createExplosion(this, power, setFire); ++ } ++ ++ /** ++ * Creates explosion at this location with given power and optionally ++ * setting blocks on fire. ++ * ++ * @param power The power of explosion, where 4F is TNT ++ * @param setFire Whether or not to set blocks on fire ++ * @param breakBlocks Whether or not to have blocks be destroyed ++ * @return false if explosion was canceled, otherwise true ++ */ ++ public boolean createExplosion(float power, boolean setFire, boolean breakBlocks) { ++ return this.getWorld().createExplosion(this, power, setFire, breakBlocks); ++ } ++ ++ /** ++ * Creates explosion at this location with given power, with the specified entity as the source. ++ * ++ * Will break blocks and ignite blocks on fire. ++ * ++ * @param source The source entity of the explosion ++ * @param power The power of explosion, where 4F is TNT ++ * @return false if explosion was canceled, otherwise true ++ */ ++ public boolean createExplosion(@Nullable Entity source, float power) { ++ return this.getWorld().createExplosion(source, this, power, true, true); ++ } ++ ++ /** ++ * Creates explosion at this location with given power and optionally ++ * setting blocks on fire, with the specified entity as the source. ++ * ++ * Will break blocks. ++ * ++ * @param source The source entity of the explosion ++ * @param power The power of explosion, where 4F is TNT ++ * @param setFire Whether or not to set blocks on fire ++ * @return false if explosion was canceled, otherwise true ++ */ ++ public boolean createExplosion(@Nullable Entity source, float power, boolean setFire) { ++ return this.getWorld().createExplosion(source, this, power, setFire, true); ++ } ++ ++ /** ++ * Creates explosion at this location with given power and optionally ++ * setting blocks on fire, with the specified entity as the source. ++ * ++ * @param source The source entity of the explosion ++ * @param power The power of explosion, where 4F is TNT ++ * @param setFire Whether or not to set blocks on fire ++ * @param breakBlocks Whether or not to have blocks be destroyed ++ * @return false if explosion was canceled, otherwise true ++ */ ++ public boolean createExplosion(@NotNull Entity source, float power, boolean setFire, boolean breakBlocks) { ++ return this.getWorld().createExplosion(source, this, power, setFire, breakBlocks); ++ } ++ + /** + * Returns a list of entities within a bounding box centered around a Location. + * +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 05643d0f2bf2cb2dedb0a2ad693b2121565d3f1f..c7cdbc36f96a8ee9eaac2a2145afbfc76bc38cc9 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -1442,6 +1442,88 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + */ + public boolean createExplosion(@NotNull Location loc, float power, boolean setFire); + ++ // Paper start ++ /** ++ * Creates explosion at given location with given power and optionally ++ * setting blocks on fire, with the specified entity as the source. ++ * ++ * @param source The source entity of the explosion ++ * @param loc Location to blow up ++ * @param power The power of explosion, where 4F is TNT ++ * @param setFire Whether or not to set blocks on fire ++ * @param breakBlocks Whether or not to have blocks be destroyed ++ * @return false if explosion was canceled, otherwise true ++ */ ++ public boolean createExplosion(@Nullable Entity source, @NotNull Location loc, float power, boolean setFire, boolean breakBlocks); ++ ++ /** ++ * Creates explosion at given location with given power and optionally ++ * setting blocks on fire, with the specified entity as the source. ++ * ++ * Will destroy other blocks ++ * ++ * @param source The source entity of the explosion ++ * @param loc Location to blow up ++ * @param power The power of explosion, where 4F is TNT ++ * @param setFire Whether or not to set blocks on fire ++ * @return false if explosion was canceled, otherwise true ++ */ ++ public default boolean createExplosion(@Nullable Entity source, @NotNull Location loc, float power, boolean setFire) { ++ return createExplosion(source, loc, power, setFire, true); ++ } ++ /** ++ * Creates explosion at given location with given power, with the specified entity as the source. ++ * Will set blocks on fire and destroy blocks. ++ * ++ * @param source The source entity of the explosion ++ * @param loc Location to blow up ++ * @param power The power of explosion, where 4F is TNT ++ * @return false if explosion was canceled, otherwise true ++ */ ++ public default boolean createExplosion(@Nullable Entity source, @NotNull Location loc, float power) { ++ return createExplosion(source, loc, power, true, true); ++ } ++ /** ++ * Creates explosion at given entities location with given power and optionally ++ * setting blocks on fire, with the specified entity as the source. ++ * ++ * @param source The source entity of the explosion ++ * @param power The power of explosion, where 4F is TNT ++ * @param setFire Whether or not to set blocks on fire ++ * @param breakBlocks Whether or not to have blocks be destroyed ++ * @return false if explosion was canceled, otherwise true ++ */ ++ public default boolean createExplosion(@NotNull Entity source, float power, boolean setFire, boolean breakBlocks) { ++ return createExplosion(source, source.getLocation(), power, setFire, breakBlocks); ++ } ++ /** ++ * Creates explosion at given entities location with given power and optionally ++ * setting blocks on fire, with the specified entity as the source. ++ * ++ * Will destroy blocks. ++ * ++ * @param source The source entity of the explosion ++ * @param power The power of explosion, where 4F is TNT ++ * @param setFire Whether or not to set blocks on fire ++ * @return false if explosion was canceled, otherwise true ++ */ ++ public default boolean createExplosion(@NotNull Entity source, float power, boolean setFire) { ++ return createExplosion(source, source.getLocation(), power, setFire, true); ++ } ++ ++ /** ++ * Creates explosion at given entities location with given power and optionally ++ * setting blocks on fire, with the specified entity as the source. ++ * ++ * @param source The source entity of the explosion ++ * @param power The power of explosion, where 4F is TNT ++ * @return false if explosion was canceled, otherwise true ++ */ ++ public default boolean createExplosion(@NotNull Entity source, float power) { ++ return createExplosion(source, source.getLocation(), power, true, true); ++ } ++ // Paper end ++ + /** + * Creates explosion at given coordinates with given power and optionally + * setting blocks on fire or breaking blocks. diff --git a/patches/api-unmapped/0113-ItemStack-API-additions-for-quantity-flags-lore.patch b/patches/api-unmapped/0113-ItemStack-API-additions-for-quantity-flags-lore.patch new file mode 100644 index 0000000000..d5b56b9832 --- /dev/null +++ b/patches/api-unmapped/0113-ItemStack-API-additions-for-quantity-flags-lore.patch @@ -0,0 +1,206 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 22 Jun 2018 22:59:18 -0400 +Subject: [PATCH] ItemStack API additions for quantity/flags/lore + + +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index f41701e6374ca23eca4bdb092e385053a12eb718..07fd8a495828ff79239359c736c425c4902543a4 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -2,7 +2,9 @@ package org.bukkit.inventory; + + import com.google.common.collect.ImmutableMap; + import java.util.LinkedHashMap; ++import java.util.List; // Paper + import java.util.Map; ++import java.util.Set; // Paper + import org.apache.commons.lang.Validate; + import org.bukkit.Bukkit; + import org.bukkit.Material; +@@ -644,5 +646,185 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + // Requires access to NMS + return ensureServerConversions().getMaxItemUseDuration(); + } ++ ++ /** ++ * Clones the itemstack and returns it a single quantity. ++ * @return The new itemstack with 1 quantity ++ */ ++ @NotNull ++ public ItemStack asOne() { ++ return asQuantity(1); ++ } ++ ++ /** ++ * Clones the itemstack and returns it as the specified quantity ++ * @param qty The quantity of the cloned item ++ * @return The new itemstack with specified quantity ++ */ ++ @NotNull ++ public ItemStack asQuantity(int qty) { ++ ItemStack clone = clone(); ++ clone.setAmount(qty); ++ return clone; ++ } ++ ++ /** ++ * Adds 1 to this itemstack. Will not go over the items max stack size. ++ * @return The same item (not a clone) ++ */ ++ @NotNull ++ public ItemStack add() { ++ return add(1); ++ } ++ ++ /** ++ * Adds quantity to this itemstack. Will not go over the items max stack size. ++ * ++ * @param qty The amount to add ++ * @return The same item (not a clone) ++ */ ++ @NotNull ++ public ItemStack add(int qty) { ++ setAmount(Math.min(getMaxStackSize(), getAmount() + qty)); ++ return this; ++ } ++ ++ /** ++ * Subtracts 1 to this itemstack. Going to 0 or less will invalidate the item. ++ * @return The same item (not a clone) ++ */ ++ @NotNull ++ public ItemStack subtract() { ++ return subtract(1); ++ } ++ ++ /** ++ * Subtracts quantity to this itemstack. Going to 0 or less will invalidate the item. ++ * ++ * @param qty The amount to add ++ * @return The same item (not a clone) ++ */ ++ @NotNull ++ public ItemStack subtract(int qty) { ++ setAmount(Math.max(0, getAmount() - qty)); ++ return this; ++ } ++ ++ /** ++ * If the item has lore, returns it, else it will return null ++ * @return The lore, or null ++ * @deprecated in favor of {@link #lore()} ++ */ ++ @Deprecated ++ public @Nullable List getLore() { ++ if (!hasItemMeta()) { ++ return null; ++ } ++ ItemMeta itemMeta = getItemMeta(); ++ if (!itemMeta.hasLore()) { ++ return null; ++ } ++ return itemMeta.getLore(); ++ } ++ ++ /** ++ * If the item has lore, returns it, else it will return null ++ * @return The lore, or null ++ */ ++ public @Nullable List lore() { ++ if (!this.hasItemMeta()) { ++ return null; ++ } ++ final ItemMeta itemMeta = getItemMeta(); ++ if (!itemMeta.hasLore()) { ++ return null; ++ } ++ return itemMeta.lore(); ++ } ++ ++ /** ++ * Sets the lore for this item. ++ * Removes lore when given null. ++ * ++ * @param lore the lore that will be set ++ * @deprecated in favour of {@link #lore(List)} ++ */ ++ @Deprecated ++ public void setLore(@Nullable List lore) { ++ ItemMeta itemMeta = getItemMeta(); ++ if (itemMeta == null) { ++ throw new IllegalStateException("Cannot set lore on " + getType()); ++ } ++ itemMeta.setLore(lore); ++ setItemMeta(itemMeta); ++ } ++ ++ /** ++ * Sets the lore for this item. ++ * Removes lore when given null. ++ * ++ * @param lore the lore that will be set ++ */ ++ public void lore(@Nullable List lore) { ++ ItemMeta itemMeta = getItemMeta(); ++ if (itemMeta == null) { ++ throw new IllegalStateException("Cannot set lore on " + getType()); ++ } ++ itemMeta.lore(lore); ++ this.setItemMeta(itemMeta); ++ } ++ ++ /** ++ * Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. ++ * ++ * @param itemFlags The hideflags which shouldn't be rendered ++ */ ++ public void addItemFlags(@NotNull ItemFlag... itemFlags) { ++ ItemMeta itemMeta = getItemMeta(); ++ if (itemMeta == null) { ++ throw new IllegalStateException("Cannot add flags on " + getType()); ++ } ++ itemMeta.addItemFlags(itemFlags); ++ setItemMeta(itemMeta); ++ } ++ ++ /** ++ * Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. ++ * ++ * @param itemFlags Hideflags which should be removed ++ */ ++ public void removeItemFlags(@NotNull ItemFlag... itemFlags) { ++ ItemMeta itemMeta = getItemMeta(); ++ if (itemMeta == null) { ++ throw new IllegalStateException("Cannot remove flags on " + getType()); ++ } ++ itemMeta.removeItemFlags(itemFlags); ++ setItemMeta(itemMeta); ++ } ++ ++ /** ++ * Get current set itemFlags. The collection returned is unmodifiable. ++ * ++ * @return A set of all itemFlags set ++ */ ++ @NotNull ++ public Set getItemFlags() { ++ ItemMeta itemMeta = getItemMeta(); ++ if (itemMeta == null) { ++ return java.util.Collections.emptySet(); ++ } ++ return itemMeta.getItemFlags(); ++ } ++ ++ /** ++ * Check if the specified flag is present on this item. ++ * ++ * @param flag the flag to check ++ * @return if it is present ++ */ ++ public boolean hasItemFlag(@NotNull ItemFlag flag) { ++ ItemMeta itemMeta = getItemMeta(); ++ return itemMeta != null && itemMeta.hasItemFlag(flag); ++ } + // Paper end + } diff --git a/patches/api-unmapped/0114-LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/api-unmapped/0114-LivingEntity-Hand-Raised-Item-Use-API.patch new file mode 100644 index 0000000000..62fef67f7a --- /dev/null +++ b/patches/api-unmapped/0114-LivingEntity-Hand-Raised-Item-Use-API.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 Jun 2018 00:19:19 -0400 +Subject: [PATCH] LivingEntity Hand Raised/Item Use API + +How long an entity has raised hands to charge an attack or use an item + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 879dec59f202ee95043bd7317a672cd59ab3bbbe..4f62a49e7b0538f0ce9cecd2c1b645f40ce17b3d 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -12,6 +12,7 @@ import org.bukkit.attribute.Attributable; + import org.bukkit.block.Block; + import org.bukkit.entity.memory.MemoryKey; + import org.bukkit.inventory.EntityEquipment; ++import org.bukkit.inventory.ItemStack; + import org.bukkit.potion.PotionEffect; + import org.bukkit.potion.PotionEffectType; + import org.bukkit.projectiles.ProjectileSource; +@@ -642,5 +643,42 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + * @param delay Delay in ticks + */ + void setShieldBlockingDelay(int delay); ++ ++ /** ++ * Get's the item being actively "used" or consumed. ++ * @return The item. Will be null if no active item. ++ */ ++ @Nullable ++ ItemStack getActiveItem(); ++ ++ /** ++ * Get's remaining time a player needs to keep hands raised with an item to finish using it. ++ * @return Remaining ticks to use the item ++ */ ++ int getItemUseRemainingTime(); ++ ++ /** ++ * Get how long the players hands have been raised (Charging Bow attack, using a potion, etc) ++ * ++ * @return Get how long the players hands have been raised (Charging Bow attack, using a potion, etc) ++ */ ++ int getHandRaisedTime(); ++ ++ /** ++ * Whether or not this entity is using or charging an attack (Bow pulled back, drinking potion, eating food) ++ * ++ * @return Whether or not this entity is using or charging an attack (Bow pulled back, drinking potion, eating food) ++ */ ++ boolean isHandRaised(); ++ ++ /** ++ * Gets the hand raised by this living entity. Will be either ++ * {@link org.bukkit.inventory.EquipmentSlot#HAND} or ++ * {@link org.bukkit.inventory.EquipmentSlot#OFF_HAND}. ++ * ++ * @return the hand raised ++ */ ++ @NotNull ++ org.bukkit.inventory.EquipmentSlot getHandRaised(); + // Paper end + } diff --git a/patches/api-unmapped/0115-RangedEntity-API.patch b/patches/api-unmapped/0115-RangedEntity-API.patch new file mode 100644 index 0000000000..f609bc2f0e --- /dev/null +++ b/patches/api-unmapped/0115-RangedEntity-API.patch @@ -0,0 +1,188 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 26 Jun 2018 21:34:40 -0400 +Subject: [PATCH] RangedEntity API + +Allows you to determine if an entity is capable of ranged attacks, +and to perform an attack. + +diff --git a/src/main/java/com/destroystokyo/paper/entity/RangedEntity.java b/src/main/java/com/destroystokyo/paper/entity/RangedEntity.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f2e3233a3d1744e32fb76d3731b9858ef0067e30 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/RangedEntity.java +@@ -0,0 +1,31 @@ ++package com.destroystokyo.paper.entity; ++ ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Mob; ++import org.jetbrains.annotations.NotNull; ++ ++public interface RangedEntity extends Mob { ++ /** ++ * Attack the specified entity using a ranged attack. ++ * ++ * @param target the entity to target ++ * @param charge How "charged" the attack is (how far back the bow was pulled for Bow attacks). ++ * This should be a value between 0 and 1, represented as targetDistance/maxDistance. ++ */ ++ void rangedAttack(@NotNull LivingEntity target, float charge); ++ ++ /** ++ * Sets that the Entity is "charging" up an attack, by raising its hands ++ * ++ * @param raiseHands Whether the entities hands are raised to charge attack ++ */ ++ void setChargingAttack(boolean raiseHands); ++ ++ /** ++ * Alias to {@link LivingEntity#isHandRaised()}, if the entity is charging an attack ++ * @return If entities hands are raised ++ */ ++ default boolean isChargingAttack() { ++ return isHandRaised(); ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/Drowned.java b/src/main/java/org/bukkit/entity/Drowned.java +index 1dee177ae6e21da000607dc8dd8fd76857f323b9..8d1ad9ef757cb1e8d72b145262df73612a76c746 100644 +--- a/src/main/java/org/bukkit/entity/Drowned.java ++++ b/src/main/java/org/bukkit/entity/Drowned.java +@@ -1,6 +1,8 @@ + package org.bukkit.entity; + ++import com.destroystokyo.paper.entity.RangedEntity; ++ + /** + * Drowned zombie. + */ +-public interface Drowned extends Zombie { } ++public interface Drowned extends Zombie, RangedEntity { } // Paper +diff --git a/src/main/java/org/bukkit/entity/Illusioner.java b/src/main/java/org/bukkit/entity/Illusioner.java +index 7c92c431b32754dca12b4d584bd6fa93ff73badf..14e6c5ee06ece3d1bbc1239afa67c847a479948f 100644 +--- a/src/main/java/org/bukkit/entity/Illusioner.java ++++ b/src/main/java/org/bukkit/entity/Illusioner.java +@@ -1,6 +1,10 @@ + package org.bukkit.entity; + ++import com.destroystokyo.paper.entity.RangedEntity; ++ + /** + * Represents an Illusioner "Illager". + */ +-public interface Illusioner extends Spellcaster { } ++public interface Illusioner extends Spellcaster, RangedEntity { // Paper ++ ++} +diff --git a/src/main/java/org/bukkit/entity/Llama.java b/src/main/java/org/bukkit/entity/Llama.java +index c43854298548391679c1d280bd42edbeed7759b9..d23226ccb0f6c25028f000ce31346cd0a8898e6a 100644 +--- a/src/main/java/org/bukkit/entity/Llama.java ++++ b/src/main/java/org/bukkit/entity/Llama.java +@@ -1,12 +1,13 @@ + package org.bukkit.entity; + ++import com.destroystokyo.paper.entity.RangedEntity; + import org.bukkit.inventory.LlamaInventory; + import org.jetbrains.annotations.NotNull; + + /** + * Represents a Llama. + */ +-public interface Llama extends ChestedHorse { ++public interface Llama extends ChestedHorse, RangedEntity { // Paper + + /** + * Represents the base color that the llama has. +diff --git a/src/main/java/org/bukkit/entity/Piglin.java b/src/main/java/org/bukkit/entity/Piglin.java +index b96e57552245e2c6d452755d4227c572266fcec7..6fdc0e0bb62189dbf3cf9ce7a87b7fbb995956a3 100644 +--- a/src/main/java/org/bukkit/entity/Piglin.java ++++ b/src/main/java/org/bukkit/entity/Piglin.java +@@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a Piglin. + */ +-public interface Piglin extends PiglinAbstract, InventoryHolder { ++public interface Piglin extends PiglinAbstract, InventoryHolder, com.destroystokyo.paper.entity.RangedEntity { // Paper + + /** + * Get whether the piglin is able to hunt hoglins. +diff --git a/src/main/java/org/bukkit/entity/Pillager.java b/src/main/java/org/bukkit/entity/Pillager.java +index 9a2252fef56be1ed3ae2169aea46cb567e965c6c..11f38187fca830d974be01fea2966a31936184cb 100644 +--- a/src/main/java/org/bukkit/entity/Pillager.java ++++ b/src/main/java/org/bukkit/entity/Pillager.java +@@ -1,8 +1,10 @@ + package org.bukkit.entity; + ++import com.destroystokyo.paper.entity.RangedEntity; // Paper ++ + import org.bukkit.inventory.InventoryHolder; + + /** + * Illager entity. + */ +-public interface Pillager extends Illager, InventoryHolder { } ++public interface Pillager extends Illager, InventoryHolder, RangedEntity { } // Paper +diff --git a/src/main/java/org/bukkit/entity/Skeleton.java b/src/main/java/org/bukkit/entity/Skeleton.java +index 16b1293887cee2bc5267f3da771fb5a6ece1b4e9..1c367f78eadf24850061a84ce63b950b79d3c435 100644 +--- a/src/main/java/org/bukkit/entity/Skeleton.java ++++ b/src/main/java/org/bukkit/entity/Skeleton.java +@@ -2,11 +2,12 @@ package org.bukkit.entity; + + import org.jetbrains.annotations.Contract; + import org.jetbrains.annotations.NotNull; ++import com.destroystokyo.paper.entity.RangedEntity; + + /** + * Represents a Skeleton. + */ +-public interface Skeleton extends Monster { ++public interface Skeleton extends Monster, RangedEntity { // Paper + + /** + * Gets the current type of this skeleton. +diff --git a/src/main/java/org/bukkit/entity/Snowman.java b/src/main/java/org/bukkit/entity/Snowman.java +index 818efe2a4d1ac0c4d8dca6c757850d99cdc2cb4b..10f8f6d45ae9280651c3ebddd1f90acbd7d6ff29 100644 +--- a/src/main/java/org/bukkit/entity/Snowman.java ++++ b/src/main/java/org/bukkit/entity/Snowman.java +@@ -1,9 +1,11 @@ + package org.bukkit.entity; + ++import com.destroystokyo.paper.entity.RangedEntity; ++ + /** + * Represents a snowman entity + */ +-public interface Snowman extends Golem { ++public interface Snowman extends Golem, RangedEntity { // Paper + + /** + * Gets whether this snowman is in "derp mode", meaning it is not wearing a +diff --git a/src/main/java/org/bukkit/entity/Witch.java b/src/main/java/org/bukkit/entity/Witch.java +index b4343903b66a7fb5250c1da2e09c9e5863c20daf..aa88aede6c4e66a608a63d07bc66d60357b0bee9 100644 +--- a/src/main/java/org/bukkit/entity/Witch.java ++++ b/src/main/java/org/bukkit/entity/Witch.java +@@ -1,7 +1,9 @@ + package org.bukkit.entity; + ++import com.destroystokyo.paper.entity.RangedEntity; ++ + /** + * Represents a Witch + */ +-public interface Witch extends Raider { ++public interface Witch extends Raider, RangedEntity { // Paper + } +diff --git a/src/main/java/org/bukkit/entity/Wither.java b/src/main/java/org/bukkit/entity/Wither.java +index 3bc332ee7f7d428bef6e2566ddded8b941858e2e..426d3693317cd303d35d8203026b528d87e401d5 100644 +--- a/src/main/java/org/bukkit/entity/Wither.java ++++ b/src/main/java/org/bukkit/entity/Wither.java +@@ -1,7 +1,9 @@ + package org.bukkit.entity; + ++import com.destroystokyo.paper.entity.RangedEntity; ++ + /** + * Represents a Wither boss + */ +-public interface Wither extends Monster, Boss { ++public interface Wither extends Monster, Boss, RangedEntity { // Paper + } diff --git a/patches/api-unmapped/0116-Add-World.getEntity-UUID-API.patch b/patches/api-unmapped/0116-Add-World.getEntity-UUID-API.patch new file mode 100644 index 0000000000..bb7e7eafdf --- /dev/null +++ b/patches/api-unmapped/0116-Add-World.getEntity-UUID-API.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Tue, 3 Jul 2018 16:07:16 +0200 +Subject: [PATCH] Add World.getEntity(UUID) API + + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index c7cdbc36f96a8ee9eaac2a2145afbfc76bc38cc9..edf136ef50c9cdd8ccea2e35508e4464c3de99bd 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -946,6 +946,17 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + @NotNull + public Collection getNearbyEntities(@NotNull Location location, double x, double y, double z); + ++ // Paper start - getEntity by UUID API ++ /** ++ * Gets an entity in this world by its UUID ++ * ++ * @param uuid the UUID of the entity ++ * @return the entity with the given UUID, or null if it isn't found ++ */ ++ @Nullable ++ public Entity getEntity(@NotNull UUID uuid); ++ // Paper end ++ + /** + * Returns a list of entities within a bounding box centered around a + * Location. diff --git a/patches/api-unmapped/0117-InventoryCloseEvent-Reason-API.patch b/patches/api-unmapped/0117-InventoryCloseEvent-Reason-API.patch new file mode 100644 index 0000000000..c03581bf2f --- /dev/null +++ b/patches/api-unmapped/0117-InventoryCloseEvent-Reason-API.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 3 Jul 2018 21:52:52 -0400 +Subject: [PATCH] InventoryCloseEvent Reason API + +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 7430bc85301d0fcb34c6035fbe08ae245c76e043..3418133d07250a7fd50caad8d97924b86fb30bad 100644 +--- a/src/main/java/org/bukkit/entity/HumanEntity.java ++++ b/src/main/java/org/bukkit/entity/HumanEntity.java +@@ -153,6 +153,15 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder + */ + public void closeInventory(); + ++ // Paper start ++ /** ++ * Force-closes the currently open inventory view for this player, if any. ++ * ++ * @param reason why the inventory is closing ++ */ ++ public void closeInventory(@NotNull org.bukkit.event.inventory.InventoryCloseEvent.Reason reason); ++ // Paper end ++ + /** + * Returns the ItemStack currently in your hand, can be empty. + * +diff --git a/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java +index 5861247c1b8ee4fe2736fd5098e05a2ca9ab78ea..21ad8888c0e403bfc63518502577d651c02dda05 100644 +--- a/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java +@@ -11,9 +11,60 @@ import org.jetbrains.annotations.NotNull; + */ + public class InventoryCloseEvent extends InventoryEvent { + private static final HandlerList handlers = new HandlerList(); ++ // Paper start ++ private final Reason reason; ++ @NotNull ++ public Reason getReason() { ++ return reason; ++ } ++ ++ public enum Reason { ++ /** ++ * Unknown reason ++ */ ++ UNKNOWN, ++ /** ++ * Player is teleporting ++ */ ++ TELEPORT, ++ /** ++ * Player is no longer permitted to use this inventory ++ */ ++ CANT_USE, ++ /** ++ * The chunk the inventory was in was unloaded ++ */ ++ UNLOADED, ++ /** ++ * Opening new inventory instead ++ */ ++ OPEN_NEW, ++ /** ++ * Closed ++ */ ++ PLAYER, ++ /** ++ * Closed due to disconnect ++ */ ++ DISCONNECT, ++ /** ++ * The player died ++ */ ++ DEATH, ++ /** ++ * Closed by Bukkit API ++ */ ++ PLUGIN, ++ } + + public InventoryCloseEvent(@NotNull InventoryView transaction) { ++ this(transaction, Reason.UNKNOWN); ++ } ++ ++ public InventoryCloseEvent(@NotNull InventoryView transaction, @NotNull Reason reason) { + super(transaction); ++ this.reason = reason; ++ // Paper end + } + + /** diff --git a/patches/api-unmapped/0118-Entity-getChunk-API.patch b/patches/api-unmapped/0118-Entity-getChunk-API.patch new file mode 100644 index 0000000000..1a598ac537 --- /dev/null +++ b/patches/api-unmapped/0118-Entity-getChunk-API.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 02:25:48 -0400 +Subject: [PATCH] Entity#getChunk API + +Get the chunk the entity is currently registered to + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index fdc95c87a6020bdcaee5b0b8ab5a996c0e241b33..76c20d84fee011af4f1850d0cab8ac00a69f2b34 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -3,6 +3,7 @@ package org.bukkit.entity; + import java.util.List; + import java.util.Set; + import java.util.UUID; ++import org.bukkit.Chunk; // Paper + import org.bukkit.EntityEffect; + import org.bukkit.Location; + import org.bukkit.Nameable; +@@ -672,5 +673,13 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + * @return True if entity spawned from a mob spawner + */ + boolean fromMobSpawner(); ++ ++ /** ++ * Gets the latest chunk an entity is currently or was in. ++ * ++ * @return The current, or most recent chunk if the entity is invalid (which may load the chunk) ++ */ ++ @NotNull ++ Chunk getChunk(); + // Paper end + } diff --git a/patches/api-unmapped/0119-Add-an-asterisk-to-legacy-API-plugins.patch b/patches/api-unmapped/0119-Add-an-asterisk-to-legacy-API-plugins.patch new file mode 100644 index 0000000000..d768a18607 --- /dev/null +++ b/patches/api-unmapped/0119-Add-an-asterisk-to-legacy-API-plugins.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Tue, 1 Dec 2020 14:57:02 +0100 +Subject: [PATCH] Add an asterisk to legacy API plugins + +Not here to name and shame, only so server admins can be aware of which +plugins have and haven't been updated. + +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 195b6bb328de92c4d17d1cd14e13578226b1ac3c..d6897f43a0692e031bed8a212d9a637ef548cc60 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -91,5 +91,11 @@ public interface UnsafeValues { + default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { + return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher(); + } ++ ++ boolean isSupportedApiVersion(String apiVersion); ++ ++ static boolean isLegacyPlugin(org.bukkit.plugin.Plugin plugin) { ++ return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java +index 4de959bbd1270d7d6ea8e5e69521bcca6abe2138..1aa58c59e1e8738bbdc77752885ff3b18b29de42 100644 +--- a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java +@@ -52,9 +52,15 @@ public class PluginsCommand extends BukkitCommand { + } + + Plugin plugin = entry.getValue(); +- ++ + pluginList.append(plugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED); +- pluginList.append(plugin.getDescription().getName()); ++ // Paper start - Add an asterisk to legacy plugins (so admins are aware) ++ String pluginName = plugin.getDescription().getName(); ++ if (org.bukkit.UnsafeValues.isLegacyPlugin(plugin)) { ++ pluginName += "*"; ++ } ++ pluginList.append(pluginName); ++ // Paper end + + if (plugin.getDescription().getProvides().size() > 0) { + pluginList.append(" (").append(String.join(", ", plugin.getDescription().getProvides())).append(")"); +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index 816c2b1797447ab315ceb6eda89d25f27d2bce98..f26303315c9c93356f0b04440136855dd54d32b7 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -306,7 +306,14 @@ public final class JavaPluginLoader implements PluginLoader { + Validate.isTrue(plugin instanceof JavaPlugin, "Plugin is not associated with this PluginLoader"); + + if (!plugin.isEnabled()) { +- plugin.getLogger().info("Enabling " + plugin.getDescription().getFullName()); ++ // Paper start - Add an asterisk to legacy plugins (so admins are aware) ++ String enableMsg = "Enabling " + plugin.getDescription().getFullName(); ++ if (org.bukkit.UnsafeValues.isLegacyPlugin(plugin)) { ++ enableMsg += "*"; ++ } ++ ++ plugin.getLogger().info(enableMsg); ++ // Paper end + + JavaPlugin jPlugin = (JavaPlugin) plugin; + diff --git a/patches/api-unmapped/0120-EnderDragon-Events.patch b/patches/api-unmapped/0120-EnderDragon-Events.patch new file mode 100644 index 0000000000..68ed791382 --- /dev/null +++ b/patches/api-unmapped/0120-EnderDragon-Events.patch @@ -0,0 +1,225 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 01:51:05 -0500 +Subject: [PATCH] EnderDragon Events + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFireballHitEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFireballHitEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..118c7b6772a52c250649af2a9286f483f43da385 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFireballHitEvent.java +@@ -0,0 +1,79 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.AreaEffectCloud; ++import org.bukkit.entity.DragonFireball; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++ ++import java.util.Collection; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Fired when a DragonFireball collides with a block/entity and spawns an AreaEffectCloud ++ */ ++public class EnderDragonFireballHitEvent extends EntityEvent implements Cancellable { ++ @Nullable private final Collection targets; ++ @NotNull private final AreaEffectCloud areaEffectCloud; ++ ++ public EnderDragonFireballHitEvent(@NotNull DragonFireball fireball, @Nullable Collection targets, @NotNull AreaEffectCloud areaEffectCloud) { ++ super(fireball); ++ this.targets = targets; ++ this.areaEffectCloud = areaEffectCloud; ++ } ++ ++ /** ++ * The fireball involved in this event ++ */ ++ @NotNull ++ @Override ++ public DragonFireball getEntity() { ++ return (DragonFireball) super.getEntity(); ++ } ++ ++ /** ++ * The living entities hit by fireball ++ * ++ * May be null if no entities were hit ++ * ++ * @return the targets ++ */ ++ @Nullable ++ public Collection getTargets() { ++ return targets; ++ } ++ ++ /** ++ * @return The area effect cloud spawned in this collision ++ */ ++ @NotNull ++ public AreaEffectCloud getAreaEffectCloud() { ++ return areaEffectCloud; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFlameEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFlameEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1915177f4b8f8013656fbdb41240f6c5c88f95d7 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFlameEvent.java +@@ -0,0 +1,61 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.AreaEffectCloud; ++import org.bukkit.entity.EnderDragon; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when an EnderDragon spawns an AreaEffectCloud by shooting flames ++ */ ++public class EnderDragonFlameEvent extends EntityEvent implements Cancellable { ++ @NotNull private final AreaEffectCloud areaEffectCloud; ++ ++ public EnderDragonFlameEvent(@NotNull EnderDragon enderDragon, @NotNull AreaEffectCloud areaEffectCloud) { ++ super(enderDragon); ++ this.areaEffectCloud = areaEffectCloud; ++ } ++ ++ /** ++ * The enderdragon involved in this event ++ */ ++ @NotNull ++ @Override ++ public EnderDragon getEntity() { ++ return (EnderDragon) super.getEntity(); ++ } ++ ++ /** ++ * @return The area effect cloud spawned in this collision ++ */ ++ @NotNull ++ public AreaEffectCloud getAreaEffectCloud() { ++ return areaEffectCloud; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonShootFireballEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonShootFireballEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8414bd805ec68d7b305fbf645c59f8d5b762c9ce +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonShootFireballEvent.java +@@ -0,0 +1,61 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.DragonFireball; ++import org.bukkit.entity.EnderDragon; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when an EnderDragon shoots a fireball ++ */ ++public class EnderDragonShootFireballEvent extends EntityEvent implements Cancellable { ++ @NotNull private final DragonFireball fireball; ++ ++ public EnderDragonShootFireballEvent(@NotNull EnderDragon entity, @NotNull DragonFireball fireball) { ++ super(entity); ++ this.fireball = fireball; ++ } ++ ++ /** ++ * The enderdragon shooting the fireball ++ */ ++ @NotNull ++ @Override ++ public EnderDragon getEntity() { ++ return (EnderDragon) super.getEntity(); ++ } ++ ++ /** ++ * @return The fireball being shot ++ */ ++ @NotNull ++ public DragonFireball getFireball() { ++ return fireball; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0121-PlayerLaunchProjectileEvent.patch b/patches/api-unmapped/0121-PlayerLaunchProjectileEvent.patch new file mode 100644 index 0000000000..7524daea92 --- /dev/null +++ b/patches/api-unmapped/0121-PlayerLaunchProjectileEvent.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 03:10:50 -0500 +Subject: [PATCH] PlayerLaunchProjectileEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerLaunchProjectileEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerLaunchProjectileEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9074b2ede01f76c0560e5318246382163cc91591 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerLaunchProjectileEvent.java +@@ -0,0 +1,83 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.entity.Projectile; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a player shoots a projectile ++ */ ++public class PlayerLaunchProjectileEvent extends PlayerEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ @NotNull private final Projectile projectile; ++ @NotNull private final ItemStack itemStack; ++ private boolean consumeItem = true; ++ private boolean cancelled; ++ ++ public PlayerLaunchProjectileEvent(@NotNull Player shooter, @NotNull ItemStack itemStack, @NotNull Projectile projectile) { ++ super(shooter); ++ this.itemStack = itemStack; ++ this.projectile = projectile; ++ } ++ ++ /** ++ * Gets the projectile which will be launched by this event ++ * ++ * @return the launched projectile ++ */ ++ @NotNull ++ public Projectile getProjectile() { ++ return projectile; ++ } ++ ++ /** ++ * Get the ItemStack used to fire the projectile ++ * ++ * @return The ItemStack used ++ */ ++ @NotNull ++ public ItemStack getItemStack() { ++ return itemStack; ++ } ++ ++ /** ++ * Get whether to consume the ItemStack or not ++ * ++ * @return True to consume ++ */ ++ public boolean shouldConsume() { ++ return consumeItem; ++ } ++ ++ /** ++ * Set whether to consume the ItemStack or not ++ * ++ * @param consumeItem True to consume ++ */ ++ public void setShouldConsume(boolean consumeItem) { ++ this.consumeItem = consumeItem; ++ } ++ ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0122-PlayerElytraBoostEvent.patch b/patches/api-unmapped/0122-PlayerElytraBoostEvent.patch new file mode 100644 index 0000000000..c5d8e5ddf3 --- /dev/null +++ b/patches/api-unmapped/0122-PlayerElytraBoostEvent.patch @@ -0,0 +1,97 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 01:59:53 -0500 +Subject: [PATCH] PlayerElytraBoostEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerElytraBoostEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerElytraBoostEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e9a76a25fa5445905a09dbc2fd5b35bff56d80b3 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerElytraBoostEvent.java +@@ -0,0 +1,85 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.entity.Firework; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when a player boosts elytra flight with a firework ++ */ ++public class PlayerElytraBoostEvent extends PlayerEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled = false; ++ @NotNull private final ItemStack itemStack; ++ @NotNull private Firework firework; ++ private boolean consume = true; ++ ++ public PlayerElytraBoostEvent(@NotNull Player player, @NotNull ItemStack itemStack, @NotNull Firework firework) { ++ super(player); ++ this.itemStack = itemStack; ++ this.firework = firework; ++ } ++ ++ /** ++ * Get the firework itemstack used ++ * ++ * @return ItemStack of firework ++ */ ++ @NotNull ++ public ItemStack getItemStack() { ++ return itemStack; ++ } ++ ++ /** ++ * Get the firework entity that was spawned ++ * ++ * @return Firework entity ++ */ ++ @NotNull ++ public Firework getFirework() { ++ return firework; ++ } ++ ++ /** ++ * Get whether to consume the firework or not ++ * ++ * @return True to consume ++ */ ++ public boolean shouldConsume() { ++ return consume; ++ } ++ ++ /** ++ * Set whether to consume the firework or not ++ * ++ * @param consume True to consume ++ */ ++ public void setShouldConsume(boolean consume) { ++ this.consume = consume; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0123-EntityTransformedEvent.patch b/patches/api-unmapped/0123-EntityTransformedEvent.patch new file mode 100644 index 0000000000..c77c4a8ba6 --- /dev/null +++ b/patches/api-unmapped/0123-EntityTransformedEvent.patch @@ -0,0 +1,104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Anthony MacAllister +Date: Thu, 26 Jul 2018 15:28:53 -0400 +Subject: [PATCH] EntityTransformedEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityTransformedEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityTransformedEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..12194f1fc7f03ca6785904b6187b3dfd03b16461 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityTransformedEvent.java +@@ -0,0 +1,92 @@ ++package com.destroystokyo.paper.event.entity; ++ ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++ ++/** ++ * Fired when an entity transforms into another entity ++ *

    ++ * If the event is cancelled, the entity will not transform ++ * @deprecated Bukkit has added {@link EntityTransformEvent}, you should start using that ++ */ ++@Deprecated ++public class EntityTransformedEvent extends EntityEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ private final Entity transformed; ++ private final TransformedReason reason; ++ ++ public EntityTransformedEvent(Entity entity, Entity transformed, TransformedReason reason) { ++ super(entity); ++ this.transformed = transformed; ++ this.reason = reason; ++ } ++ ++ /** ++ * The entity after it has transformed ++ * ++ * @return Transformed entity ++ * @deprecated see {@link EntityTransformEvent#getTransformedEntity()} ++ */ ++ @Deprecated ++ public Entity getTransformed() { ++ return transformed; ++ } ++ ++ /** ++ * @return The reason for the transformation ++ * @deprecated see {@link EntityTransformEvent#getTransformReason()} ++ */ ++ @Deprecated ++ public TransformedReason getReason() { ++ return reason; ++ } ++ ++ ++ @Override ++ public HandlerList getHandlers(){ ++ return handlers; ++ } ++ ++ public static HandlerList getHandlerList(){ ++ return handlers; ++ } ++ ++ @Override ++ public boolean isCancelled(){ ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel){ ++ cancelled = cancel; ++ } ++ ++ public enum TransformedReason { ++ /** ++ * When a zombie drowns ++ */ ++ DROWNED, ++ /** ++ * When a zombie villager is cured ++ */ ++ CURED, ++ /** ++ * When a villager turns to a zombie villager ++ */ ++ INFECTED, ++ /** ++ * When a mooshroom turns to a cow ++ */ ++ SHEARED, ++ /** ++ * When a pig turns to a zombiepigman ++ */ ++ LIGHTNING ++ ++ } ++} diff --git a/patches/api-unmapped/0124-Allow-disabling-armour-stand-ticking.patch b/patches/api-unmapped/0124-Allow-disabling-armour-stand-ticking.patch new file mode 100644 index 0000000000..30f0bf5227 --- /dev/null +++ b/patches/api-unmapped/0124-Allow-disabling-armour-stand-ticking.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 15 Aug 2018 01:26:03 -0700 +Subject: [PATCH] Allow disabling armour stand ticking + + +diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java +index fddc063798edc8084ca695578a47485204a7f3cd..365d3a3c5fc4a47efe56225ef1eb87b5046034f4 100644 +--- a/src/main/java/org/bukkit/entity/ArmorStand.java ++++ b/src/main/java/org/bukkit/entity/ArmorStand.java +@@ -360,5 +360,21 @@ public interface ArmorStand extends LivingEntity { + * @param move {@code true} if this armour stand can move, {@code false} otherwise + */ + void setCanMove(boolean move); ++ ++ /** ++ * Tests if this armor stand can tick. ++ * ++ *

    The default value is defined in {@code paper.yml}.

    ++ * ++ * @return {@code true} if this armour stand can tick, {@code false} otherwise ++ */ ++ boolean canTick(); ++ ++ /** ++ * Sets if this armor stand can tick. ++ * ++ * @param tick {@code true} if this armour stand can tick, {@code false} otherwise ++ */ ++ void setCanTick(final boolean tick); + // Paper end + } diff --git a/patches/api-unmapped/0125-SkeletonHorse-Additions.patch b/patches/api-unmapped/0125-SkeletonHorse-Additions.patch new file mode 100644 index 0000000000..8d4dd478ab --- /dev/null +++ b/patches/api-unmapped/0125-SkeletonHorse-Additions.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 27 Jul 2018 22:36:17 -0500 +Subject: [PATCH] SkeletonHorse Additions + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9ce2948dfaa56d0adf53fe9b6117a90d7773b771 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java +@@ -0,0 +1,62 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import com.google.common.collect.ImmutableList; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.entity.SkeletonHorse; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.List; ++ ++/** ++ * Event called when a player gets close to a skeleton horse and triggers the lightning trap ++ */ ++public class SkeletonHorseTrapEvent extends EntityEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ private final List eligibleHumans; ++ ++ public SkeletonHorseTrapEvent(@NotNull SkeletonHorse horse) { ++ this(horse, ImmutableList.of()); ++ } ++ ++ public SkeletonHorseTrapEvent(@NotNull SkeletonHorse horse, @NotNull List eligibleHumans) { ++ super(horse); ++ this.eligibleHumans = eligibleHumans; ++ } ++ ++ @NotNull ++ @Override ++ public SkeletonHorse getEntity() { ++ return (SkeletonHorse) super.getEntity(); ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ public List getEligibleHumans() { ++ return eligibleHumans; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} ++ +diff --git a/src/main/java/org/bukkit/entity/SkeletonHorse.java b/src/main/java/org/bukkit/entity/SkeletonHorse.java +index b2c6b6a8689f6bd6ce784bbe6f571f756dd700c1..ba9983463263f77db3d3487bc12f01db4508a32b 100644 +--- a/src/main/java/org/bukkit/entity/SkeletonHorse.java ++++ b/src/main/java/org/bukkit/entity/SkeletonHorse.java +@@ -3,4 +3,12 @@ package org.bukkit.entity; + /** + * Represents a SkeletonHorse - variant of {@link AbstractHorse}. + */ +-public interface SkeletonHorse extends AbstractHorse { } ++public interface SkeletonHorse extends AbstractHorse { ++ // Paper start ++ int getTrapTime(); ++ ++ boolean isTrap(); ++ ++ void setTrap(boolean trap); ++ // Paper end ++} diff --git a/patches/api-unmapped/0126-Expand-Location-Manipulation-API.patch b/patches/api-unmapped/0126-Expand-Location-Manipulation-API.patch new file mode 100644 index 0000000000..271041f256 --- /dev/null +++ b/patches/api-unmapped/0126-Expand-Location-Manipulation-API.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 25 Jul 2018 01:36:07 -0400 +Subject: [PATCH] Expand Location Manipulation API + +Adds set(x, y, z), add(base, x, y, z), subtract(base, x, y, z); + +diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java +index af2ee43f2c5133668c18710f526a107d94a5d898..369ce9ff6c8bb97a64a8e229115564412e6e7654 100644 +--- a/src/main/java/org/bukkit/Location.java ++++ b/src/main/java/org/bukkit/Location.java +@@ -546,6 +546,54 @@ public class Location implements Cloneable, ConfigurationSerializable { + public boolean isChunkLoaded() { return this.getWorld().isChunkLoaded(locToBlock(x) >> 4, locToBlock(z) >> 4); } // Paper + + // Paper start ++ ++ /** ++ * Sets the position of this Location and returns itself ++ * ++ * This mutates this object, clone first. ++ * @param x X coordinate ++ * @param y Y coordinate ++ * @param z Z coordinate ++ * @return self (not cloned) ++ */ ++ @NotNull ++ public Location set(double x, double y, double z) { ++ this.x = x; ++ this.y = y; ++ this.z = z; ++ return this; ++ } ++ ++ /** ++ * Takes the x/y/z from base and adds the specified x/y/z to it and returns self ++ * ++ * This mutates this object, clone first. ++ * @param base The base coordinate to modify ++ * @param x X coordinate to add to base ++ * @param y Y coordinate to add to base ++ * @param z Z coordinate to add to base ++ * @return self (not cloned) ++ */ ++ @NotNull ++ public Location add(@NotNull Location base, double x, double y, double z) { ++ return this.set(base.x + x, base.y + y, base.z + z); ++ } ++ ++ /** ++ * Takes the x/y/z from base and subtracts the specified x/y/z to it and returns self ++ * ++ * This mutates this object, clone first. ++ * @param base The base coordinate to modify ++ * @param x X coordinate to subtract from base ++ * @param y Y coordinate to subtract from base ++ * @param z Z coordinate to subtract from base ++ * @return self (not cloned) ++ */ ++ @NotNull ++ public Location subtract(@NotNull Location base, double x, double y, double z) { ++ return this.set(base.x - x, base.y - y, base.z - z); ++ } ++ + /** + * @return A new location where X/Y/Z are on the Block location (integer value of X/Y/Z) + */ diff --git a/patches/api-unmapped/0127-Expand-ArmorStand-API.patch b/patches/api-unmapped/0127-Expand-ArmorStand-API.patch new file mode 100644 index 0000000000..036951f69d --- /dev/null +++ b/patches/api-unmapped/0127-Expand-ArmorStand-API.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: willies952002 +Date: Thu, 26 Jul 2018 02:22:44 -0400 +Subject: [PATCH] Expand ArmorStand API + +Add the following: +- Add proper methods for getting and setting items in both hands. Deprecates old methods +- Enable/Disable slot interactions + +diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java +index 365d3a3c5fc4a47efe56225ef1eb87b5046034f4..8ca6c9eba926f436203af211c6e274a59ddb15e8 100644 +--- a/src/main/java/org/bukkit/entity/ArmorStand.java ++++ b/src/main/java/org/bukkit/entity/ArmorStand.java +@@ -13,7 +13,7 @@ public interface ArmorStand extends LivingEntity { + * Returns the item the armor stand is currently holding. + * + * @return the held item +- * @deprecated prefer {@link EntityEquipment#getItemInHand()} ++ * @deprecated prefer {@link ArmorStand#getItem(EquipmentSlot)} // Paper + * @see #getEquipment() + */ + @NotNull +@@ -25,7 +25,7 @@ public interface ArmorStand extends LivingEntity { + * + * @param item the item to hold + * @deprecated prefer +- * {@link EntityEquipment#setItemInHand(org.bukkit.inventory.ItemStack)} ++ * {@link ArmorStand#setItem(EquipmentSlot, ItemStack)} // Paper + * @see #getEquipment() + */ + @Deprecated +@@ -376,5 +376,71 @@ public interface ArmorStand extends LivingEntity { + * @param tick {@code true} if this armour stand can tick, {@code false} otherwise + */ + void setCanTick(final boolean tick); ++ ++ /** ++ * Returns the item the armor stand has ++ * equip in the given equipment slot ++ * ++ * @param slot the equipment slot to get ++ * @return the ItemStack in the equipment slot ++ */ ++ @NotNull ++ ItemStack getItem(@NotNull final org.bukkit.inventory.EquipmentSlot slot); ++ ++ /** ++ * Sets the item the armor stand has ++ * equip in the given equipment slot ++ * ++ * @param slot the equipment slot to set ++ * @param item the item to hold ++ */ ++ void setItem(@NotNull final org.bukkit.inventory.EquipmentSlot slot, @Nullable final ItemStack item); ++ ++ /** ++ * Get the list of disabled slots ++ * ++ * @return list of disabled slots ++ */ ++ @NotNull ++ java.util.Set getDisabledSlots(); ++ ++ /** ++ * Set the disabled slots ++ * ++ * This makes it so a player is unable to interact with the Armor Stand to place, remove, or replace an item in the given slot(s) ++ * Note: Once a slot is disabled, the only way to get an item back it to break the armor stand. ++ * ++ * @param slots var-arg array of slots to lock ++ */ ++ void setDisabledSlots(@NotNull org.bukkit.inventory.EquipmentSlot... slots); ++ ++ /** ++ * Disable specific slots, adding them ++ * to the currently disabled slots ++ * ++ * This makes it so a player is unable to interact with the Armor Stand to place, remove, or replace an item in the given slot(s) ++ * Note: Once a slot is disabled, the only way to get an item back it to break the armor stand. ++ * ++ * @param slots var-arg array of slots to lock ++ */ ++ void addDisabledSlots(@NotNull final org.bukkit.inventory.EquipmentSlot... slots); ++ ++ /** ++ * Remove the given slots from the disabled ++ * slots list, enabling them. ++ * ++ * This makes it so a player is able to interact with the Armor Stand to place, remove, or replace an item in the given slot(s) ++ * ++ * @param slots var-arg array of slots to unlock ++ */ ++ void removeDisabledSlots(@NotNull final org.bukkit.inventory.EquipmentSlot... slots); ++ ++ /** ++ * Check if a specific slot is disabled ++ * ++ * @param slot The slot to check ++ * @return {@code true} if the slot is disabled, else {@code false}. ++ */ ++ boolean isSlotDisabled(@NotNull org.bukkit.inventory.EquipmentSlot slot); + // Paper end + } diff --git a/patches/api-unmapped/0128-AnvilDamageEvent.patch b/patches/api-unmapped/0128-AnvilDamageEvent.patch new file mode 100644 index 0000000000..7561b6a9db --- /dev/null +++ b/patches/api-unmapped/0128-AnvilDamageEvent.patch @@ -0,0 +1,160 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 20 Jul 2018 23:36:55 -0500 +Subject: [PATCH] AnvilDamageEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/block/AnvilDamagedEvent.java b/src/main/java/com/destroystokyo/paper/event/block/AnvilDamagedEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a83c286c1c11af25fc4d16af7a42b95ce90b9dee +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/block/AnvilDamagedEvent.java +@@ -0,0 +1,148 @@ ++package com.destroystokyo.paper.event.block; ++ ++import org.bukkit.Material; ++import org.bukkit.block.data.BlockData; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.inventory.InventoryEvent; ++import org.bukkit.inventory.AnvilInventory; ++import org.bukkit.inventory.InventoryView; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when an anvil is damaged from being used ++ */ ++public class AnvilDamagedEvent extends InventoryEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancel; ++ private DamageState damageState; ++ ++ public AnvilDamagedEvent(@NotNull InventoryView inventory, @NotNull BlockData blockData) { ++ super(inventory); ++ this.damageState = DamageState.getState(blockData); ++ } ++ ++ @NotNull ++ @Override ++ public AnvilInventory getInventory() { ++ return (AnvilInventory) super.getInventory(); ++ } ++ ++ /** ++ * Gets the new state of damage on the anvil ++ * ++ * @return Damage state ++ */ ++ @NotNull ++ public DamageState getDamageState() { ++ return damageState; ++ } ++ ++ /** ++ * Sets the new state of damage on the anvil ++ * ++ * @param damageState Damage state ++ */ ++ public void setDamageState(@NotNull DamageState damageState) { ++ this.damageState = damageState; ++ } ++ ++ /** ++ * Gets if anvil is breaking on this use ++ * ++ * @return True if breaking ++ */ ++ public boolean isBreaking() { ++ return damageState == DamageState.BROKEN; ++ } ++ ++ /** ++ * Sets if anvil is breaking on this use ++ * ++ * @param breaking True if breaking ++ */ ++ public void setBreaking(boolean breaking) { ++ if (breaking) { ++ damageState = DamageState.BROKEN; ++ } else if (damageState == DamageState.BROKEN) { ++ damageState = DamageState.DAMAGED; ++ } ++ } ++ ++ public boolean isCancelled() { ++ return cancel; ++ } ++ ++ public void setCancelled(boolean cancel) { ++ this.cancel = cancel; ++ } ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ /** ++ * Represents the amount of damage on an anvil block ++ */ ++ public enum DamageState { ++ FULL(Material.ANVIL), ++ CHIPPED(Material.CHIPPED_ANVIL), ++ DAMAGED(Material.DAMAGED_ANVIL), ++ BROKEN(Material.AIR); ++ ++ private Material material; ++ ++ DamageState(@NotNull Material material) { ++ this.material = material; ++ } ++ ++ /** ++ * Get block material of this state ++ * ++ * @return Material ++ */ ++ @NotNull ++ public Material getMaterial() { ++ return material; ++ } ++ ++ /** ++ * Get damaged state by block data ++ * ++ * @param blockData Block data ++ * @return DamageState ++ * @throws IllegalArgumentException If non anvil block data is given ++ */ ++ @NotNull ++ public static DamageState getState(@Nullable BlockData blockData) { ++ return blockData == null ? BROKEN : getState(blockData.getMaterial()); ++ } ++ ++ /** ++ * Get damaged state by block material ++ * ++ * @param material Block material ++ * @return DamageState ++ * @throws IllegalArgumentException If non anvil material is given ++ */ ++ @NotNull ++ public static DamageState getState(@Nullable Material material) { ++ if (material == null) { ++ return BROKEN; ++ } ++ for (DamageState state : values()) { ++ if (state.material == material) { ++ return state; ++ } ++ } ++ throw new IllegalArgumentException("Material not an anvil"); ++ } ++ } ++} diff --git a/patches/api-unmapped/0129-Remove-deadlock-risk-in-firing-async-events.patch b/patches/api-unmapped/0129-Remove-deadlock-risk-in-firing-async-events.patch new file mode 100644 index 0000000000..2725c79f2e --- /dev/null +++ b/patches/api-unmapped/0129-Remove-deadlock-risk-in-firing-async-events.patch @@ -0,0 +1,137 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 9 Sep 2018 00:32:05 -0400 +Subject: [PATCH] Remove deadlock risk in firing async events + +The PluginManager incorrectly used synchronization on firing any event +that was marked as synchronous. + +This synchronized did not even protect any concurrency risk as +handlers were already thread safe in terms of mutations during event +dispatch. + +The way it was used, has commonly led to deadlocks on the server, +which results in a hard crash. + +This change removes the synchronize and adds some protection around enable/disable + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 9b8823279524d1c1566176c589aa5794eb8aafbc..707638c327077a74c777a603b9f2392f46b51c0c 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable; + */ + public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource { // Paper + +- /** ++ /* + * Gets the entity's current position + * + * @return a new copy of Location containing the position of this entity +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index a7393d2830b95d7167121b02066a3f357cee6085..a1a805004941d67abb0b9aa1721e0370c45b5289 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -462,7 +462,7 @@ public final class SimplePluginManager implements PluginManager { + * @return true if the plugin is enabled, otherwise false + */ + @Override +- public boolean isPluginEnabled(@Nullable Plugin plugin) { ++ public synchronized boolean isPluginEnabled(@Nullable Plugin plugin) { // Paper - synchronize + if ((plugin != null) && (plugins.contains(plugin))) { + return plugin.isEnabled(); + } else { +@@ -471,7 +471,7 @@ public final class SimplePluginManager implements PluginManager { + } + + @Override +- public void enablePlugin(@NotNull final Plugin plugin) { ++ public synchronized void enablePlugin(@NotNull final Plugin plugin) { // Paper - synchronize + if (!plugin.isEnabled()) { + List pluginCommands = PluginCommandYamlParser.parse(plugin); + +@@ -509,7 +509,7 @@ public final class SimplePluginManager implements PluginManager { + } + + @Override +- public void disablePlugin(@NotNull final Plugin plugin, boolean closeClassloader) { ++ public synchronized void disablePlugin(@NotNull final Plugin plugin, boolean closeClassloader) { // Paper - synchronize + // Paper end - close Classloader on disable + if (plugin.isEnabled()) { + try { +@@ -579,6 +579,7 @@ public final class SimplePluginManager implements PluginManager { + defaultPerms.get(false).clear(); + } + } ++ private void fireEvent(Event event) { callEvent(event); } // Paper - support old method incase plugin uses reflection + + /** + * Calls an event with the given details. +@@ -587,23 +588,13 @@ public final class SimplePluginManager implements PluginManager { + */ + @Override + public void callEvent(@NotNull Event event) { +- if (event.isAsynchronous()) { +- if (Thread.holdsLock(this)) { +- throw new IllegalStateException(event.getEventName() + " cannot be triggered asynchronously from inside synchronized code."); +- } +- if (server.isPrimaryThread()) { +- throw new IllegalStateException(event.getEventName() + " cannot be triggered asynchronously from primary server thread."); +- } +- } else { +- if (!server.isPrimaryThread()) { +- throw new IllegalStateException(event.getEventName() + " cannot be triggered asynchronously from another thread."); +- } ++ // Paper - replace callEvent by merging to below method ++ if (event.isAsynchronous() && server.isPrimaryThread()) { ++ throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously."); ++ } else if (!event.isAsynchronous() && !server.isPrimaryThread()) { ++ throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously."); + } + +- fireEvent(event); +- } +- +- private void fireEvent(@NotNull Event event) { + HandlerList handlers = event.getHandlers(); + RegisteredListener[] listeners = handlers.getRegisteredListeners(); + +diff --git a/src/test/java/org/bukkit/plugin/PluginManagerTest.java b/src/test/java/org/bukkit/plugin/PluginManagerTest.java +index f188cd4f3b07027c30d41f1162db77a506b7b6bb..1941c9f49e9514c1236c5f4ea9f7af47f7be85c5 100644 +--- a/src/test/java/org/bukkit/plugin/PluginManagerTest.java ++++ b/src/test/java/org/bukkit/plugin/PluginManagerTest.java +@@ -17,7 +17,7 @@ public class PluginManagerTest { + private static final PluginManager pm = TestServer.getInstance().getPluginManager(); + + private final MutableObject store = new MutableObject(); +- ++/* // Paper start - remove unneeded test + @Test + public void testAsyncSameThread() { + final Event event = new TestEvent(true); +@@ -28,14 +28,14 @@ public class PluginManagerTest { + return; + } + throw new IllegalStateException("No exception thrown"); +- } ++ }*/ // Paper end + + @Test + public void testSyncSameThread() { + final Event event = new TestEvent(false); + pm.callEvent(event); + } +- ++/* // Paper start - remove unneeded test + @Test + public void testAsyncLocked() throws InterruptedException { + final Event event = new TestEvent(true); +@@ -129,7 +129,7 @@ public class PluginManagerTest { + if (store.value == null) { + throw new IllegalStateException("No exception thrown"); + } +- } ++ } */ // Paper + + @Test + public void testRemovePermissionByNameLower() { diff --git a/patches/api-unmapped/0130-Add-hand-to-bucket-events.patch b/patches/api-unmapped/0130-Add-hand-to-bucket-events.patch new file mode 100644 index 0000000000..85c5c370f3 --- /dev/null +++ b/patches/api-unmapped/0130-Add-hand-to-bucket-events.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Thu, 2 Aug 2018 08:44:20 -0500 +Subject: [PATCH] Add hand to bucket events + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java b/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java +index 7f225baa9fd3ff6f4f950ae70f9500141c674f66..25bd8153ef2ab7ab1052cf756bb599f1095732e7 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java +@@ -5,6 +5,7 @@ import org.bukkit.block.Block; + import org.bukkit.block.BlockFace; + import org.bukkit.entity.Player; + import org.bukkit.event.HandlerList; ++import org.bukkit.inventory.EquipmentSlot; + import org.bukkit.inventory.ItemStack; + import org.jetbrains.annotations.NotNull; + +@@ -22,6 +23,16 @@ public class PlayerBucketEmptyEvent extends PlayerBucketEvent { + public PlayerBucketEmptyEvent(@NotNull final Player who, @NotNull final Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand) { + super(who, block, blockClicked, blockFace, bucket, itemInHand); + } ++ // Paper start - add EquipmentSlot ++ @Deprecated ++ public PlayerBucketEmptyEvent(@NotNull final Player who, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @org.jetbrains.annotations.Nullable final EquipmentSlot hand) { ++ super(who, blockClicked, blockFace, bucket, itemInHand, hand); ++ } ++ ++ public PlayerBucketEmptyEvent(@NotNull final Player who, @NotNull final Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @org.jetbrains.annotations.Nullable final EquipmentSlot hand) { ++ super(who, block, blockClicked, blockFace, bucket, itemInHand, hand); ++ } ++ // Paper end + + @NotNull + @Override +diff --git a/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java b/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java +index 0e4fa04ea73baaf2f9ad86725d379b569d7d6381..1e0f7ee7d198c08ce421ce105be42c4d01dc924f 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java +@@ -5,6 +5,7 @@ import org.bukkit.block.Block; + import org.bukkit.block.BlockFace; + import org.bukkit.entity.Player; + import org.bukkit.event.Cancellable; ++import org.bukkit.inventory.EquipmentSlot; + import org.bukkit.inventory.ItemStack; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; +@@ -19,6 +20,7 @@ public abstract class PlayerBucketEvent extends PlayerEvent implements Cancellab + private final Block blockClicked; + private final BlockFace blockFace; + private final Material bucket; ++ private final EquipmentSlot hand; // Paper - add EquipmentSlot + + @Deprecated + public PlayerBucketEvent(@NotNull final Player who, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand) { +@@ -26,12 +28,24 @@ public abstract class PlayerBucketEvent extends PlayerEvent implements Cancellab + } + + public PlayerBucketEvent(@NotNull final Player who, @NotNull final Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand) { ++ // Paper start - add EquipmentSlot ++ this(who, block, blockClicked, blockFace, bucket, itemInHand, null); ++ } ++ ++ @Deprecated ++ public PlayerBucketEvent(@NotNull final Player who,@NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @Nullable final EquipmentSlot hand) { ++ this(who, null, blockClicked, blockFace, bucket, itemInHand, hand); ++ } ++ ++ public PlayerBucketEvent(@NotNull final Player who, @NotNull final Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @Nullable final EquipmentSlot hand) { ++ // Paper end + super(who); + this.block = block; + this.blockClicked = blockClicked; + this.blockFace = blockFace; + this.itemStack = itemInHand; + this.bucket = bucket; ++ this.hand = hand == null ? player.getInventory().getItemInMainHand().equals(itemInHand) ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND : hand; // Paper - add EquipmentSlot + } + + /** +@@ -93,6 +107,18 @@ public abstract class PlayerBucketEvent extends PlayerEvent implements Cancellab + return blockFace; + } + ++ // Paper start ++ /** ++ * The hand used to perform this action. ++ * ++ * @return the hand used ++ */ ++ @NotNull ++ public EquipmentSlot getHand() { ++ return hand; ++ } ++ // Paper end ++ + @Override + public boolean isCancelled() { + return cancelled; +diff --git a/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java b/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java +index 77c3a6e5c89ffde564d63b98b2d9e36c356d79fd..56f1cc2d773d2c58207ee291bac596692980a731 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java +@@ -5,6 +5,7 @@ import org.bukkit.block.Block; + import org.bukkit.block.BlockFace; + import org.bukkit.entity.Player; + import org.bukkit.event.HandlerList; ++import org.bukkit.inventory.EquipmentSlot; + import org.bukkit.inventory.ItemStack; + import org.jetbrains.annotations.NotNull; + +@@ -23,6 +24,18 @@ public class PlayerBucketFillEvent extends PlayerBucketEvent { + super(who, block, blockClicked, blockFace, bucket, itemInHand); + } + ++ // Paper start - add EquipmentSlot ++ @Deprecated ++ public PlayerBucketFillEvent(@NotNull final Player who, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @org.jetbrains.annotations.Nullable final EquipmentSlot hand) { ++ super(who, blockClicked, blockFace, bucket, itemInHand, hand); ++ } ++ ++ // Paper start - add EquipmentSlot ++ public PlayerBucketFillEvent(@NotNull final Player who, @NotNull Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @org.jetbrains.annotations.Nullable final EquipmentSlot hand) { ++ super(who, block, blockClicked, blockFace, bucket, itemInHand, hand); ++ } ++ // Paper end ++ + @NotNull + @Override + public HandlerList getHandlers() { diff --git a/patches/api-unmapped/0131-Add-TNTPrimeEvent.patch b/patches/api-unmapped/0131-Add-TNTPrimeEvent.patch new file mode 100644 index 0000000000..2bddc56f13 --- /dev/null +++ b/patches/api-unmapped/0131-Add-TNTPrimeEvent.patch @@ -0,0 +1,126 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 15 Jul 2018 22:17:55 +0300 +Subject: [PATCH] Add TNTPrimeEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/block/TNTPrimeEvent.java b/src/main/java/com/destroystokyo/paper/event/block/TNTPrimeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..73dabb82c7fbea3f0cccade0a2944b11a80ede06 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/block/TNTPrimeEvent.java +@@ -0,0 +1,114 @@ ++package com.destroystokyo.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when TNT block is about to turn into {@link org.bukkit.entity.TNTPrimed} ++ *

    ++ * Cancelling it won't turn TNT into {@link org.bukkit.entity.TNTPrimed} and leaves ++ * the TNT block as-is ++ * ++ * @author Mark Vainomaa ++ */ ++public class TNTPrimeEvent extends BlockEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ @NotNull private PrimeReason reason; ++ @Nullable private Entity primerEntity; ++ ++ public TNTPrimeEvent(@NotNull Block theBlock, @NotNull PrimeReason reason, @Nullable Entity primerEntity) { ++ super(theBlock); ++ this.reason = reason; ++ this.primerEntity = primerEntity; ++ } ++ ++ /** ++ * Gets the TNT prime reason ++ * ++ * @return Prime reason ++ */ ++ @NotNull ++ public PrimeReason getReason() { ++ return this.reason; ++ } ++ ++ /** ++ * Gets the TNT primer {@link Entity}. ++ * ++ * It's null if {@link #getReason()} is {@link PrimeReason#REDSTONE} or {@link PrimeReason#FIRE}. ++ * It's not null if {@link #getReason()} is {@link PrimeReason#ITEM} or {@link PrimeReason#PROJECTILE} ++ * It might be null if {@link #getReason()} is {@link PrimeReason#EXPLOSION} ++ * ++ * @return The {@link Entity} who primed the TNT ++ */ ++ @Nullable ++ public Entity getPrimerEntity() { ++ return this.primerEntity; ++ } ++ ++ /** ++ * Gets whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not ++ * ++ * @return Whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not ++ */ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ /** ++ * Sets whether to cancel spawning {@link org.bukkit.entity.TNTPrimed} or not ++ * ++ * @param cancel whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Nullable ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @Nullable ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ public enum PrimeReason { ++ /** ++ * When TNT prime was caused by other explosion (chain reaction) ++ */ ++ EXPLOSION, ++ ++ /** ++ * When TNT prime was caused by fire ++ */ ++ FIRE, ++ ++ /** ++ * When {@link org.bukkit.entity.Player} used {@link org.bukkit.Material#FLINT_AND_STEEL} or ++ * {@link org.bukkit.Material#FIRE_CHARGE} on given TNT block ++ */ ++ ITEM, ++ ++ /** ++ * When TNT prime was caused by an {@link Entity} shooting TNT ++ * using a bow with {@link org.bukkit.enchantments.Enchantment#ARROW_FIRE} enchantment ++ */ ++ PROJECTILE, ++ ++ /** ++ * When redstone power triggered the TNT prime ++ */ ++ REDSTONE ++ } ++} diff --git a/patches/api-unmapped/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch b/patches/api-unmapped/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch new file mode 100644 index 0000000000..3616f82f03 --- /dev/null +++ b/patches/api-unmapped/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 4 Aug 2018 19:37:35 -0400 +Subject: [PATCH] Provide Chunk Coordinates as a Long API + +Allows you to easily access the chunks X/z as a long, and a method +to look up by the long key too. + +diff --git a/src/main/java/org/bukkit/Chunk.java b/src/main/java/org/bukkit/Chunk.java +index beac1439c71fb28f1a3baecf56157237e12ccfd5..fa576096e908f8fbdbef53e1bd91215ac9e73ed6 100644 +--- a/src/main/java/org/bukkit/Chunk.java ++++ b/src/main/java/org/bukkit/Chunk.java +@@ -28,6 +28,32 @@ public interface Chunk extends PersistentDataHolder { + */ + int getZ(); + ++ // Paper start ++ /** ++ * @return The Chunks X and Z coordinates packed into a long ++ */ ++ default long getChunkKey() { ++ return getChunkKey(getX(), getZ()); ++ } ++ ++ /** ++ * @param loc Location to get chunk key ++ * @return Location's chunk coordinates packed into a long ++ */ ++ static long getChunkKey(@NotNull Location loc) { ++ return getChunkKey((int) Math.floor(loc.getX()) >> 4, (int) Math.floor(loc.getZ()) >> 4); ++ } ++ ++ /** ++ * @param x X Coordinate ++ * @param z Z Coordinate ++ * @return Chunk coordinates packed into a long ++ */ ++ static long getChunkKey(int x, int z) { ++ return (long) x & 0xffffffffL | ((long) z & 0xffffffffL) << 32; ++ } ++ // Paper end ++ + /** + * Gets the world containing this chunk + * +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 9c4f2d9e1a4011e3a9860d913e1a718030696bed..e372b3d43960ac7df58985609ef729c68fca0533 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -207,6 +207,22 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + @NotNull + public Chunk getChunkAt(@NotNull Block block); + ++ // Paper start ++ /** ++ * Gets the chunk at the specified chunk key, which is the X and Z packed into a long. ++ * ++ * See {@link Chunk#getChunkKey()} for easy access to the key, or you may calculate it as: ++ * long chunkKey = (long) chunkX & 0xffffffffL | ((long) chunkZ & 0xffffffffL) >> 32; ++ * ++ * @param chunkKey The Chunk Key to look up the chunk by ++ * @return The chunk at the specified key ++ */ ++ @NotNull ++ public default Chunk getChunkAt(long chunkKey) { ++ return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); ++ } ++ // Paper end ++ + /** + * Checks if the specified {@link Chunk} is loaded + * diff --git a/patches/api-unmapped/0133-Async-Chunks-API.patch b/patches/api-unmapped/0133-Async-Chunks-API.patch new file mode 100644 index 0000000000..992af6f95b --- /dev/null +++ b/patches/api-unmapped/0133-Async-Chunks-API.patch @@ -0,0 +1,534 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 29 Feb 2016 17:43:33 -0600 +Subject: [PATCH] Async Chunks API + +Adds API's to load or generate chunks asynchronously. + +Also adds utility methods to Entity to teleport asynchronously. + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index e372b3d43960ac7df58985609ef729c68fca0533..3f231c28842f02f80fd3136c36fe99b41726137f 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -221,6 +221,482 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + public default Chunk getChunkAt(long chunkKey) { + return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); + } ++ ++ /** ++ * This is the Legacy API before Java 8 was supported. Java 8 Consumer is provided, ++ * as well as future support ++ * ++ * Used by {@link World#getChunkAtAsync(Location,ChunkLoadCallback)} methods ++ * to request a {@link Chunk} to be loaded, with this callback receiving ++ * the chunk when it is finished. ++ * ++ * This callback will be executed on synchronously on the main thread. ++ * ++ * Timing and order this callback is fired is intentionally not defined and ++ * and subject to change. ++ * ++ * @deprecated Use either the Future or the Consumer based methods ++ */ ++ @Deprecated ++ public static interface ChunkLoadCallback extends java.util.function.Consumer { ++ public void onLoad(@NotNull Chunk chunk); ++ ++ // backwards compat to old api ++ @Override ++ default void accept(@NotNull Chunk chunk) { ++ onLoad(chunk); ++ } ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The {@link ChunkLoadCallback} will always be executed synchronously ++ * on the main Server Thread. ++ * ++ * @deprecated Use either the Future or the Consumer based methods ++ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16) ++ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16) ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ @Deprecated ++ public default void getChunkAtAsync(int x, int z, @NotNull ChunkLoadCallback cb) { ++ getChunkAtAsync(x, z, true).thenAccept(cb::onLoad).exceptionally((ex) -> { ++ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); ++ return null; ++ }); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given {@link Location} ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The {@link ChunkLoadCallback} will always be executed synchronously ++ * on the main Server Thread. ++ * ++ * @deprecated Use either the Future or the Consumer based methods ++ * @param loc Location of the chunk ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ @Deprecated ++ public default void getChunkAtAsync(@NotNull Location loc, @NotNull ChunkLoadCallback cb) { ++ getChunkAtAsync(loc, true).thenAccept(cb::onLoad).exceptionally((ex) -> { ++ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); ++ return null; ++ }); ++ } ++ ++ /** ++ * Requests {@link Chunk} to be loaded that contains the given {@link Block} ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The {@link ChunkLoadCallback} will always be executed synchronously ++ * on the main Server Thread. ++ * ++ * @deprecated Use either the Future or the Consumer based methods ++ * @param block Block to get the containing chunk from ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ @Deprecated ++ public default void getChunkAtAsync(@NotNull Block block, @NotNull ChunkLoadCallback cb) { ++ getChunkAtAsync(block, true).thenAccept(cb::onLoad).exceptionally((ex) -> { ++ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); ++ return null; ++ }); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The {@link java.util.function.Consumer} will always be executed synchronously ++ * on the main Server Thread. ++ * ++ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16) ++ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16) ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ public default void getChunkAtAsync(int x, int z, @NotNull java.util.function.Consumer cb) { ++ getChunkAtAsync(x, z, true).thenAccept(cb).exceptionally((ex) -> { ++ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); ++ return null; ++ }); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The {@link java.util.function.Consumer} will always be executed synchronously ++ * on the main Server Thread. ++ * ++ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16) ++ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16) ++ * @param gen Should we generate a chunk if it doesn't exists or not ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ public default void getChunkAtAsync(int x, int z, boolean gen, @NotNull java.util.function.Consumer cb) { ++ getChunkAtAsync(x, z, gen).thenAccept(cb).exceptionally((ex) -> { ++ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); ++ return null; ++ }); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given {@link Location} ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The {@link java.util.function.Consumer} will always be executed synchronously ++ * on the main Server Thread. ++ * ++ * @param loc Location of the chunk ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ public default void getChunkAtAsync(@NotNull Location loc, @NotNull java.util.function.Consumer cb) { ++ getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, true, cb); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given {@link Location} ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The {@link java.util.function.Consumer} will always be executed synchronously ++ * on the main Server Thread. ++ * ++ * @param loc Location of the chunk ++ * @param gen Should the chunk generate ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ public default void getChunkAtAsync(@NotNull Location loc, boolean gen, @NotNull java.util.function.Consumer cb) { ++ getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, gen, cb); ++ } ++ ++ /** ++ * Requests {@link Chunk} to be loaded that contains the given {@link Block} ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The {@link java.util.function.Consumer} will always be executed synchronously ++ * on the main Server Thread. ++ * ++ * @param block Block to get the containing chunk from ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ public default void getChunkAtAsync(@NotNull Block block, @NotNull java.util.function.Consumer cb) { ++ getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, true, cb); ++ } ++ ++ /** ++ * Requests {@link Chunk} to be loaded that contains the given {@link Block} ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The {@link java.util.function.Consumer} will always be executed synchronously ++ * on the main Server Thread. ++ * ++ * @param block Block to get the containing chunk from ++ * @param gen Should the chunk generate ++ * @param cb Callback to receive the chunk when it is loaded. ++ * will be executed synchronously ++ */ ++ public default void getChunkAtAsync(@NotNull Block block, boolean gen, @NotNull java.util.function.Consumer cb) { ++ getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, gen, cb); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The future will always be executed synchronously ++ * on the main Server Thread. ++ * @param loc Location to load the corresponding chunk from ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture getChunkAtAsync(@NotNull Location loc) { ++ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, true); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The future will always be executed synchronously ++ * on the main Server Thread. ++ * @param loc Location to load the corresponding chunk from ++ * @param gen Should the chunk generate ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture getChunkAtAsync(@NotNull Location loc, boolean gen) { ++ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, gen); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The future will always be executed synchronously ++ * on the main Server Thread. ++ * @param block Block to load the corresponding chunk from ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture getChunkAtAsync(@NotNull Block block) { ++ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, true); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The future will always be executed synchronously ++ * on the main Server Thread. ++ * @param block Block to load the corresponding chunk from ++ * @param gen Should the chunk generate ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture getChunkAtAsync(@NotNull Block block, boolean gen) { ++ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, gen); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The future will always be executed synchronously ++ * on the main Server Thread. ++ * ++ * @param x X Coord ++ * @param z Z Coord ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z) { ++ return getChunkAtAsync(x, z, true); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The future will always be executed synchronously ++ * on the main Server Thread. ++ * ++ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16) ++ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16) ++ * @param gen Should we generate a chunk if it doesn't exists or not ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen) { ++ return getChunkAtAsync(x, z, gen, false); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The future will always be executed synchronously ++ * on the main Server Thread. ++ * @param loc Location to load the corresponding chunk from ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(@NotNull Location loc) { ++ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, true, true); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The future will always be executed synchronously ++ * on the main Server Thread. ++ * @param loc Location to load the corresponding chunk from ++ * @param gen Should the chunk generate ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(@NotNull Location loc, boolean gen) { ++ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, gen, true); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The future will always be executed synchronously ++ * on the main Server Thread. ++ * @param block Block to load the corresponding chunk from ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(@NotNull Block block) { ++ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, true, true); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The future will always be executed synchronously ++ * on the main Server Thread. ++ * @param block Block to load the corresponding chunk from ++ * @param gen Should the chunk generate ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(@NotNull Block block, boolean gen) { ++ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, gen, true); ++ } ++ ++ /** ++ * Requests a {@link Chunk} to be loaded at the given coordinates ++ * ++ * This method makes no guarantee on how fast the chunk will load, ++ * and will return the chunk to the callback at a later time. ++ * ++ * You should use this method if you need a chunk but do not need it ++ * immediately, and you wish to let the server control the speed ++ * of chunk loads, keeping performance in mind. ++ * ++ * The future will always be executed synchronously ++ * on the main Server Thread. ++ * ++ * @param x X Coord ++ * @param z Z Coord ++ * @return Future that will resolve when the chunk is loaded ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(int x, int z) { ++ return getChunkAtAsync(x, z, true, true); ++ } ++ ++ @NotNull ++ java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent); + // Paper end + + /** +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 707638c327077a74c777a603b9f2392f46b51c0c..c137199ed0537874010f1abf311a9cbee56831ac 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -163,6 +163,33 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + */ + public boolean teleport(@NotNull Entity destination, @NotNull TeleportCause cause); + ++ // Paper start ++ /** ++ * Loads/Generates(in 1.13+) the Chunk asynchronously, and then teleports the entity when the chunk is ready. ++ * @param loc Location to teleport to ++ * @return A future that will be completed with the result of the teleport ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture teleportAsync(@NotNull Location loc) { ++ return teleportAsync(loc, TeleportCause.PLUGIN); ++ } ++ /** ++ * Loads/Generates(in 1.13+) the Chunk asynchronously, and then teleports the entity when the chunk is ready. ++ * @param loc Location to teleport to ++ * @param cause Reason for teleport ++ * @return A future that will be completed with the result of the teleport ++ */ ++ @NotNull ++ public default java.util.concurrent.CompletableFuture teleportAsync(@NotNull Location loc, @NotNull TeleportCause cause) { ++ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); ++ loc.getWorld().getChunkAtAsyncUrgently(loc).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { ++ future.completeExceptionally(ex); ++ return null; ++ }); ++ return future; ++ } ++ // Paper end ++ + /** + * Returns a list of entities within a bounding box centered around this + * entity diff --git a/patches/api-unmapped/0134-Make-EnderDragon-extend-Mob.patch b/patches/api-unmapped/0134-Make-EnderDragon-extend-Mob.patch new file mode 100644 index 0000000000..6779d66171 --- /dev/null +++ b/patches/api-unmapped/0134-Make-EnderDragon-extend-Mob.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 10 Aug 2018 22:08:34 -0400 +Subject: [PATCH] Make EnderDragon extend Mob + + +diff --git a/src/main/java/org/bukkit/entity/EnderDragon.java b/src/main/java/org/bukkit/entity/EnderDragon.java +index c14278d2c99deedddfd9c8afdc900760b0331546..92da609fb2bdf7c6396ba868410a40725fda05f0 100644 +--- a/src/main/java/org/bukkit/entity/EnderDragon.java ++++ b/src/main/java/org/bukkit/entity/EnderDragon.java +@@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents an Ender Dragon + */ +-public interface EnderDragon extends ComplexLivingEntity, Boss { ++public interface EnderDragon extends ComplexLivingEntity, Boss, org.bukkit.entity.Mob { // Paper - add Mob + + /** + * Represents a phase or action that an Ender Dragon can perform. diff --git a/patches/api-unmapped/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/patches/api-unmapped/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch new file mode 100644 index 0000000000..cbe8cd6f69 --- /dev/null +++ b/patches/api-unmapped/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 15 Aug 2018 01:04:58 -0400 +Subject: [PATCH] Ability to get Tile Entities from a chunk without snapshots + + +diff --git a/src/main/java/org/bukkit/Chunk.java b/src/main/java/org/bukkit/Chunk.java +index fa576096e908f8fbdbef53e1bd91215ac9e73ed6..98263d896f316983609432c45b85401a2692432d 100644 +--- a/src/main/java/org/bukkit/Chunk.java ++++ b/src/main/java/org/bukkit/Chunk.java +@@ -1,6 +1,8 @@ + package org.bukkit; + + import java.util.Collection; ++import java.util.function.Predicate; ++ + import org.bukkit.block.Block; + import org.bukkit.block.BlockState; + import org.bukkit.block.data.BlockData; +@@ -103,13 +105,36 @@ public interface Chunk extends PersistentDataHolder { + @NotNull + Entity[] getEntities(); + ++ // Paper start + /** + * Get a list of all tile entities in the chunk. + * + * @return The tile entities. + */ + @NotNull +- BlockState[] getTileEntities(); ++ default BlockState[] getTileEntities() { ++ return getTileEntities(true); ++ } ++ ++ /** ++ * Get a list of all tile entities in the chunk. ++ * ++ * @param useSnapshot Take snapshots or direct references ++ * @return The tile entities. ++ */ ++ @NotNull ++ BlockState[] getTileEntities(boolean useSnapshot); ++ ++ /** ++ * Get a list of all tile entities that match a given predicate in the chunk. ++ * ++ * @param blockPredicate The predicate of blocks to return tile entities for ++ * @param useSnapshot Take snapshots or direct references ++ * @return The tile entities. ++ */ ++ @NotNull ++ Collection getTileEntities(@NotNull Predicate blockPredicate, boolean useSnapshot); ++ // Paper end + + /** + * Checks if the chunk is loaded. diff --git a/patches/api-unmapped/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch b/patches/api-unmapped/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch new file mode 100644 index 0000000000..536fdc2d06 --- /dev/null +++ b/patches/api-unmapped/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 15 Aug 2018 01:19:37 -0400 +Subject: [PATCH] Don't use snapshots for Timings Tile Entity reports + + +diff --git a/src/main/java/co/aikar/timings/TimingHistory.java b/src/main/java/co/aikar/timings/TimingHistory.java +index ddaed81275fcc12d1671b668697acf318e96888b..203cda0f9a4dea4f28a21ea9ee8db7a7369842e3 100644 +--- a/src/main/java/co/aikar/timings/TimingHistory.java ++++ b/src/main/java/co/aikar/timings/TimingHistory.java +@@ -119,7 +119,7 @@ public class TimingHistory { + data.entityCounts.get(entity.getType()).increment(); + } + +- for (BlockState tileEntity : chunk.getTileEntities()) { ++ for (BlockState tileEntity : chunk.getTileEntities(false)) { + if (tileEntity == null) { + Bukkit.getLogger().warning("Null tileentity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ()); + continue; diff --git a/patches/api-unmapped/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch b/patches/api-unmapped/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch new file mode 100644 index 0000000000..568d6bcd6e --- /dev/null +++ b/patches/api-unmapped/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch @@ -0,0 +1,169 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 14 Aug 2018 21:42:10 -0700 +Subject: [PATCH] Allow Blocks to be accessed via a long key + +The key can be retrieved via methods Location#toBlockKey() and +Block#getBlockKey() + +World provides lookup for blocks by long key via method World#getBlockAtKey(long) + +The formatting for the key is as follows: + +10 bit y|27 bit z|27 bit x + +The y value is considered unsigned while z and x are considered two's complement + +Y range: [0, 1023] +X, Z range: [-67 108 864, 67 108 863] + +diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java +index 369ce9ff6c8bb97a64a8e229115564412e6e7654..e700875beb76dadd55b585aca748338def286908 100644 +--- a/src/main/java/org/bukkit/Location.java ++++ b/src/main/java/org/bukkit/Location.java +@@ -15,7 +15,6 @@ import org.jetbrains.annotations.Nullable; + + // Paper start + import java.util.Collection; +-import java.util.Collections; + import java.util.function.Predicate; + import org.bukkit.entity.Entity; + import org.bukkit.entity.LivingEntity; +@@ -605,6 +604,17 @@ public class Location implements Cloneable, ConfigurationSerializable { + blockLoc.setZ(getBlockZ()); + return blockLoc; + } ++ ++ // Paper Start ++ /** ++ * @return The block key for this location's block location. ++ * @see Block#getBlockKey(int, int, int) ++ */ ++ public long toBlockKey() { ++ return Block.getBlockKey(getBlockX(), getBlockY(), getBlockZ()); ++ } ++ // Paper End ++ + /** + * @return A new location where X/Y/Z are the center of the block + */ +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 3f231c28842f02f80fd3136c36fe99b41726137f..d8674c773d61517f79d0fe77276392e47fd3e1e1 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -90,6 +90,38 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + @NotNull + public Block getBlockAt(@NotNull Location location); + ++ // Paper start ++ /** ++ * Gets the {@link Block} at the given block key ++ * ++ * @param key The block key. See {@link Block#getBlockKey()} ++ * @return Block at the key ++ * @see Block#getBlockKey(int, int, int) ++ */ ++ @NotNull ++ public default Block getBlockAtKey(long key) { ++ int x = Block.getBlockKeyX(key); ++ int y = Block.getBlockKeyY(key); ++ int z = Block.getBlockKeyZ(key); ++ return getBlockAt(x, y, z); ++ } ++ ++ /** ++ * Gets the {@link Location} at the given block key ++ * ++ * @param key The block key. See {@link Location#toBlockKey()} ++ * @return Location at the key ++ * @see Block#getBlockKey(int, int, int) ++ */ ++ @NotNull ++ public default Location getLocationAtKey(long key) { ++ int x = Block.getBlockKeyX(key); ++ int y = Block.getBlockKeyY(key); ++ int z = Block.getBlockKeyZ(key); ++ return new Location(this, x, y, z); ++ } ++ // Paper end ++ + /** + * Gets the highest non-empty (impassable) coordinate at the given + * coordinates. +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index e89c8079625525667f496c06207da655fe43d749..d6f74dbcfeb153d4b17be2827e2989f2d8160d21 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -153,6 +153,72 @@ public interface Block extends Metadatable { + */ + int getZ(); + ++ // Paper Start ++ /** ++ * Returns this block's coordinates packed into a long value. ++ * Computed via: {@code Block.getBlockKey(this.getX(), this.getY(), this.getZ())} ++ * @see Block#getBlockKey(int, int, int) ++ * @return This block's x, y, and z coordinates packed into a long value ++ */ ++ public default long getBlockKey() { ++ return Block.getBlockKey(this.getX(), this.getY(), this.getZ()); ++ } ++ ++ /** ++ * Returns the specified block coordinates packed into a long value ++ *

    ++ * The return value can be computed as follows: ++ *
    ++ * {@code long value = ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54);} ++ *

    ++ * ++ *

    ++ * And may be unpacked as follows: ++ *
    ++ * {@code int x = (int) ((packed << 37) >> 37);} ++ *
    ++ * {@code int y = (int) (packed >>> 54);} ++ *
    ++ * {@code int z = (int) ((packed << 10) >> 37);} ++ *

    ++ * ++ * @return This block's x, y, and z coordinates packed into a long value ++ */ ++ public static long getBlockKey(int x, int y, int z) { ++ return ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54); ++ } ++ ++ /** ++ * Returns the x component from the packed value. ++ * @param packed The packed value, as computed by {@link Block#getBlockKey(int, int, int)} ++ * @see Block#getBlockKey(int, int, int) ++ * @return The x component from the packed value. ++ */ ++ public static int getBlockKeyX(long packed) { ++ return (int) ((packed << 37) >> 37); ++ } ++ ++ /** ++ * Returns the y component from the packed value. ++ * @param packed The packed value, as computed by {@link Block#getBlockKey(int, int, int)} ++ * @see Block#getBlockKey(int, int, int) ++ * @return The y component from the packed value. ++ */ ++ public static int getBlockKeyY(long packed) { ++ return (int) (packed >>> 54); ++ } ++ ++ /** ++ * Returns the z component from the packed value. ++ * @param packed The packed value, as computed by {@link Block#getBlockKey(int, int, int)} ++ * @see Block#getBlockKey(int, int, int) ++ * @return The z component from the packed value. ++ */ ++ public static int getBlockKeyZ(long packed) { ++ return (int) ((packed << 10) >> 37); ++ } ++ // Paper End ++ + /** + * Gets the Location of the block + * diff --git a/patches/api-unmapped/0138-Slime-Pathfinder-Events.patch b/patches/api-unmapped/0138-Slime-Pathfinder-Events.patch new file mode 100644 index 0000000000..8d27bd1b14 --- /dev/null +++ b/patches/api-unmapped/0138-Slime-Pathfinder-Events.patch @@ -0,0 +1,217 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 24 Aug 2018 08:18:27 -0500 +Subject: [PATCH] Slime Pathfinder Events + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimeChangeDirectionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimeChangeDirectionEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2638bbd3e1392b3d8640be58163f6eb2789dee4a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimeChangeDirectionEvent.java +@@ -0,0 +1,38 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Slime; ++import org.bukkit.event.Cancellable; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when a Slime decides to change it's facing direction. ++ *

    ++ * This event does not fire for the entity's actual movement. Only when it ++ * is choosing to change direction. ++ */ ++public class SlimeChangeDirectionEvent extends SlimePathfindEvent implements Cancellable { ++ private float yaw; ++ ++ public SlimeChangeDirectionEvent(@NotNull Slime slime, float yaw) { ++ super(slime); ++ this.yaw = yaw; ++ } ++ ++ /** ++ * Get the new chosen yaw ++ * ++ * @return Chosen yaw ++ */ ++ public float getNewYaw() { ++ return yaw; ++ } ++ ++ /** ++ * Set the new chosen yaw ++ * ++ * @param yaw Chosen yaw ++ */ ++ public void setNewYaw(float yaw) { ++ this.yaw = yaw; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimePathfindEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimePathfindEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..14b67da109321ae6521eab2ac6f6945f05d02db5 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimePathfindEvent.java +@@ -0,0 +1,53 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Slime; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when a Slime decides to start pathfinding. ++ *

    ++ * This event does not fire for the entity's actual movement. Only when it ++ * is choosing to start moving. ++ */ ++public class SlimePathfindEvent extends EntityEvent implements Cancellable { ++ public SlimePathfindEvent(@NotNull Slime slime) { ++ super(slime); ++ } ++ ++ /** ++ * The Slime that is pathfinding. ++ * ++ * @return The Slime that is pathfinding. ++ */ ++ @NotNull ++ public Slime getEntity() { ++ return (Slime) entity; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimeSwimEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimeSwimEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c8dd49d11da5a90a1bac965a75f2b65fd825f3f7 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimeSwimEvent.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Slime; ++import org.bukkit.event.Cancellable; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when a Slime decides to start jumping while swimming in water/lava. ++ *

    ++ * This event does not fire for the entity's actual movement. Only when it ++ * is choosing to start jumping. ++ */ ++public class SlimeSwimEvent extends SlimeWanderEvent implements Cancellable { ++ public SlimeSwimEvent(@NotNull Slime slime) { ++ super(slime); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimeTargetLivingEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimeTargetLivingEntityEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e9ba32799ed838779e49cd4c5011b7515b3363cb +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimeTargetLivingEntityEvent.java +@@ -0,0 +1,31 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Slime; ++import org.bukkit.event.Cancellable; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when a Slime decides to change direction to target a LivingEntity. ++ *

    ++ * This event does not fire for the entity's actual movement. Only when it ++ * is choosing to start moving. ++ */ ++public class SlimeTargetLivingEntityEvent extends SlimePathfindEvent implements Cancellable { ++ @NotNull private final LivingEntity target; ++ ++ public SlimeTargetLivingEntityEvent(@NotNull Slime slime, @NotNull LivingEntity target) { ++ super(slime); ++ this.target = target; ++ } ++ ++ /** ++ * Get the targeted entity ++ * ++ * @return Targeted entity ++ */ ++ @NotNull ++ public LivingEntity getTarget() { ++ return target; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimeWanderEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimeWanderEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4683a7237d2ed527fc85b9b4e5b2eaaf5ae3d797 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimeWanderEvent.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Slime; ++import org.bukkit.event.Cancellable; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when a Slime decides to start wandering. ++ *

    ++ * This event does not fire for the entity's actual movement. Only when it ++ * is choosing to start moving. ++ */ ++public class SlimeWanderEvent extends SlimePathfindEvent implements Cancellable { ++ public SlimeWanderEvent(@NotNull Slime slime) { ++ super(slime); ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/Slime.java b/src/main/java/org/bukkit/entity/Slime.java +index 1119e26e270bb45f517955b19d95a9ec3d113634..c4791f95d788d3a9e013dc89d8e64103ad8480a1 100644 +--- a/src/main/java/org/bukkit/entity/Slime.java ++++ b/src/main/java/org/bukkit/entity/Slime.java +@@ -14,4 +14,20 @@ public interface Slime extends Mob { + * @param sz The new size of the slime. + */ + public void setSize(int sz); ++ ++ // Paper start ++ /** ++ * Get whether this slime can randomly wander/jump around on its own ++ * ++ * @return true if can wander ++ */ ++ public boolean canWander(); ++ ++ /** ++ * Set whether this slime can randomly wander/jump around on its own ++ * ++ * @param canWander true if can wander ++ */ ++ public void setWander(boolean canWander); ++ // Paper end + } diff --git a/patches/api-unmapped/0139-isChunkGenerated-API.patch b/patches/api-unmapped/0139-isChunkGenerated-API.patch new file mode 100644 index 0000000000..a26301e9c3 --- /dev/null +++ b/patches/api-unmapped/0139-isChunkGenerated-API.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: cswhite2000 <18whitechristop@gmail.com> +Date: Tue, 21 Aug 2018 19:39:46 -0700 +Subject: [PATCH] isChunkGenerated API + + +diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java +index e700875beb76dadd55b585aca748338def286908..9c91c49ed7302c12fcb1d8e9bc58712efc199954 100644 +--- a/src/main/java/org/bukkit/Location.java ++++ b/src/main/java/org/bukkit/Location.java +@@ -3,6 +3,7 @@ package org.bukkit; + import com.google.common.base.Preconditions; + import java.lang.ref.Reference; + import java.lang.ref.WeakReference; ++import com.google.common.base.Preconditions; // Paper + import java.util.HashMap; + import java.util.Map; + import org.bukkit.block.Block; +@@ -545,6 +546,16 @@ public class Location implements Cloneable, ConfigurationSerializable { + public boolean isChunkLoaded() { return this.getWorld().isChunkLoaded(locToBlock(x) >> 4, locToBlock(z) >> 4); } // Paper + + // Paper start ++ /** ++ * Checks if a {@link Chunk} has been generated at this location. ++ * ++ * @return true if a chunk has been generated at this location ++ */ ++ public boolean isGenerated() { ++ World world = this.getWorld(); ++ Preconditions.checkNotNull(world, "Location has no world!"); ++ return world.isChunkGenerated(locToBlock(x) >> 4, locToBlock(z) >> 4); ++ } + + /** + * Sets the position of this Location and returns itself +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index d8674c773d61517f79d0fe77276392e47fd3e1e1..cf831f96efa302f789cf26a384a091df51215a76 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -254,6 +254,17 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); + } + ++ /** ++ * Checks if a {@link Chunk} has been generated at the specified chunk key, ++ * which is the X and Z packed into a long. ++ * ++ * @param chunkKey The Chunk Key to look up the chunk by ++ * @return true if the chunk has been generated, otherwise false ++ */ ++ public default boolean isChunkGenerated(long chunkKey) { ++ return isChunkGenerated((int) chunkKey, (int) (chunkKey >> 32)); ++ } ++ + /** + * This is the Legacy API before Java 8 was supported. Java 8 Consumer is provided, + * as well as future support diff --git a/patches/api-unmapped/0140-Add-More-Creeper-API.patch b/patches/api-unmapped/0140-Add-More-Creeper-API.patch new file mode 100644 index 0000000000..b45e2fbeba --- /dev/null +++ b/patches/api-unmapped/0140-Add-More-Creeper-API.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 24 Aug 2018 11:50:16 -0500 +Subject: [PATCH] Add More Creeper API + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/CreeperIgniteEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/CreeperIgniteEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ff10251b6ded533b08048ec533525176eff03707 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/CreeperIgniteEvent.java +@@ -0,0 +1,54 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Creeper; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a Creeper is ignite flag is changed (armed/disarmed to explode). ++ */ ++public class CreeperIgniteEvent extends EntityEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean canceled; ++ private boolean ignited; ++ ++ public CreeperIgniteEvent(@NotNull Creeper creeper, boolean ignited) { ++ super(creeper); ++ this.ignited = ignited; ++ } ++ ++ @NotNull ++ @Override ++ public Creeper getEntity() { ++ return (Creeper) entity; ++ } ++ ++ public boolean isIgnited() { ++ return ignited; ++ } ++ ++ public void setIgnited(boolean ignited) { ++ this.ignited = ignited; ++ } ++ ++ public boolean isCancelled() { ++ return canceled; ++ } ++ ++ public void setCancelled(boolean cancel) { ++ canceled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/Creeper.java b/src/main/java/org/bukkit/entity/Creeper.java +index 5793193d93d76a062fd0431475c269c4978ec993..e144f618702122bf28ebedc5cb8ce0f6ef27c107 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. + */ + public void ignite(); ++ // Paper start ++ ++ /** ++ * Set whether creeper is ignited or not (armed to explode) ++ * ++ * @param ignited New ignited state ++ */ ++ public void setIgnited(boolean ignited); ++ ++ /** ++ * Check if creeper is ignited or not (armed to explode) ++ * ++ * @return Ignited state ++ */ ++ public boolean isIgnited(); ++ // Paper end + } diff --git a/patches/api-unmapped/0141-Add-PhantomPreSpawnEvent.patch b/patches/api-unmapped/0141-Add-PhantomPreSpawnEvent.patch new file mode 100644 index 0000000000..5ffdc818cb --- /dev/null +++ b/patches/api-unmapped/0141-Add-PhantomPreSpawnEvent.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 25 Aug 2018 19:56:42 -0500 +Subject: [PATCH] Add PhantomPreSpawnEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PhantomPreSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PhantomPreSpawnEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9022f697ab244df43074e48c9150f39d44217531 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/PhantomPreSpawnEvent.java +@@ -0,0 +1,31 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.EntityType; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++ ++/** ++ * Called when a phantom is spawned for an exhausted player ++ */ ++public class PhantomPreSpawnEvent extends PreCreatureSpawnEvent { ++ @NotNull private final Entity entity; ++ ++ public PhantomPreSpawnEvent(@NotNull Location location, @NotNull Entity entity, @NotNull CreatureSpawnEvent.SpawnReason reason) { ++ super(location, EntityType.PHANTOM, reason); ++ this.entity = entity; ++ } ++ ++ /** ++ * Get the entity this phantom is spawning for ++ * ++ * @return Entity ++ */ ++ @Nullable ++ public Entity getSpawningEntity() { ++ return entity; ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/Phantom.java b/src/main/java/org/bukkit/entity/Phantom.java +index 1a1044edc57078f96c4a95c994d0865da382c152..ed4d417c2deefb78807cb61b01df5afcd334d754 100644 +--- a/src/main/java/org/bukkit/entity/Phantom.java ++++ b/src/main/java/org/bukkit/entity/Phantom.java +@@ -1,5 +1,8 @@ + package org.bukkit.entity; + ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ + /** + * Represents a phantom. + */ +@@ -14,4 +17,14 @@ public interface Phantom extends Flying { + * @param sz The new size of the phantom. + */ + public void setSize(int sz); ++ ++ // Paper start ++ /** ++ * Get the UUID of the entity that caused this phantom to spawn ++ * ++ * @return UUID ++ */ ++ @Nullable ++ public java.util.UUID getSpawningEntity(); ++ // Paper end + } diff --git a/patches/api-unmapped/0142-Add-source-block-to-BlockPhysicsEvent.patch b/patches/api-unmapped/0142-Add-source-block-to-BlockPhysicsEvent.patch new file mode 100644 index 0000000000..965de7c24a --- /dev/null +++ b/patches/api-unmapped/0142-Add-source-block-to-BlockPhysicsEvent.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sotr +Date: Thu, 23 Aug 2018 16:14:25 +0800 +Subject: [PATCH] Add source block to BlockPhysicsEvent + + +diff --git a/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java b/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java +index e3a5f5824ed882058f5bac5003f66ce79733a868..c382f9fc2b8c5b959df7071007110dab737e400e 100644 +--- a/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java +@@ -32,6 +32,13 @@ public class BlockPhysicsEvent extends BlockEvent implements Cancellable { + private final Block sourceBlock; + private boolean cancel = false; + ++ // Paper start - Legacy constructor, use #BlockPhysicsEvent(Block, BlockData, Block) ++ @Deprecated ++ public BlockPhysicsEvent(final Block block, final BlockData changed, final int sourceX, final int sourceY, final int sourceZ) { ++ this(block, changed, block.getWorld().getBlockAt(sourceX, sourceY, sourceZ)); ++ } ++ // Paper end ++ + public BlockPhysicsEvent(@NotNull final Block block, @NotNull final BlockData changed) { + this(block, changed, block); + } diff --git a/patches/api-unmapped/0143-Inventory-removeItemAnySlot.patch b/patches/api-unmapped/0143-Inventory-removeItemAnySlot.patch new file mode 100644 index 0000000000..4d6f2e9e57 --- /dev/null +++ b/patches/api-unmapped/0143-Inventory-removeItemAnySlot.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 28 Aug 2018 23:04:06 -0400 +Subject: [PATCH] Inventory#removeItemAnySlot + + +diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java +index 5576a6a8df8c95164bf2dde45d756ce8b7ec957a..9c6a5bdac8c3ab682bbfae04ff24b76a62bc2883 100644 +--- a/src/main/java/org/bukkit/inventory/Inventory.java ++++ b/src/main/java/org/bukkit/inventory/Inventory.java +@@ -125,6 +125,34 @@ public interface Inventory extends Iterable { + @NotNull + public HashMap removeItem(@NotNull ItemStack... items) throws IllegalArgumentException; + ++ // Paper start ++ /** ++ * Searches all possible inventory slots in order to remove the given ItemStacks. ++ *

    ++ * Similar to {@link Inventory#removeItem(ItemStack...)} in behavior, except this ++ * method will check all possible slots in the inventory, rather than just the main ++ * storage contents. ++ *

    ++ * It will try to remove 'as much as possible' from the types and amounts ++ * you give as arguments. ++ *

    ++ * The returned HashMap contains what it couldn't remove, where the key is ++ * the index of the parameter, and the value is the ItemStack at that ++ * index of the varargs parameter. If all the given ItemStacks are ++ * removed, it will return an empty HashMap. ++ *

    ++ * It is known that in some implementations this method will also set the ++ * inputted argument amount to the number of that item not removed from ++ * slots. ++ * ++ * @param items The ItemStacks to remove ++ * @return A HashMap containing items that couldn't be removed. ++ * @throws IllegalArgumentException if items is null ++ */ ++ @NotNull ++ public HashMap removeItemAnySlot(@NotNull ItemStack... items) throws IllegalArgumentException; ++ // Paper end ++ + /** + * Returns all ItemStacks from the inventory + * diff --git a/patches/api-unmapped/0144-Add-ray-tracing-methods-to-LivingEntity.patch b/patches/api-unmapped/0144-Add-ray-tracing-methods-to-LivingEntity.patch new file mode 100644 index 0000000000..96c37c9d46 --- /dev/null +++ b/patches/api-unmapped/0144-Add-ray-tracing-methods-to-LivingEntity.patch @@ -0,0 +1,148 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 3 Sep 2018 18:13:53 -0500 +Subject: [PATCH] Add ray tracing methods to LivingEntity + + +diff --git a/src/main/java/com/destroystokyo/paper/block/TargetBlockInfo.java b/src/main/java/com/destroystokyo/paper/block/TargetBlockInfo.java +new file mode 100644 +index 0000000000000000000000000000000000000000..18a96dbb01d3b34476652264b2d6be3782a154ec +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/block/TargetBlockInfo.java +@@ -0,0 +1,54 @@ ++package com.destroystokyo.paper.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.block.BlockFace; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents information about a targeted block ++ */ ++public class TargetBlockInfo { ++ private final Block block; ++ private final BlockFace blockFace; ++ ++ public TargetBlockInfo(@NotNull Block block, @NotNull BlockFace blockFace) { ++ this.block = block; ++ this.blockFace = blockFace; ++ } ++ ++ /** ++ * Get the block that is targeted ++ * ++ * @return Targeted block ++ */ ++ @NotNull ++ public Block getBlock() { ++ return block; ++ } ++ ++ /** ++ * Get the targeted BlockFace ++ * ++ * @return Targeted blockface ++ */ ++ @NotNull ++ public BlockFace getBlockFace() { ++ return blockFace; ++ } ++ ++ /** ++ * Get the relative Block to the targeted block on the side it is targeted at ++ * ++ * @return Block relative to targeted block ++ */ ++ @NotNull ++ public Block getRelativeBlock() { ++ return block.getRelative(blockFace); ++ } ++ ++ public enum FluidMode { ++ NEVER, ++ SOURCE_ONLY, ++ ALWAYS ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 8b89c0701dd557bcab0c05c1593354ee704b9fe4..8fe7ccf12339355554835542cc1068d9f6c3a435 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -82,6 +82,77 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + @NotNull + public Block getTargetBlock(@Nullable Set transparent, int maxDistance); + ++ // Paper start ++ /** ++ * Gets the block that the living entity has targeted, ignoring fluids ++ * ++ * @param maxDistance this is the maximum distance to scan ++ * @return block that the living entity has targeted, ++ * or null if no block is within maxDistance ++ */ ++ @Nullable ++ public default Block getTargetBlock(int maxDistance) { ++ return getTargetBlock(maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode.NEVER); ++ } ++ ++ /** ++ * Gets the block that the living entity has targeted ++ * ++ * @param maxDistance this is the maximum distance to scan ++ * @param fluidMode whether to check fluids or not ++ * @return block that the living entity has targeted, ++ * or null if no block is within maxDistance ++ */ ++ @Nullable ++ public Block getTargetBlock(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode); ++ ++ /** ++ * Gets the blockface of that block that the living entity has targeted, ignoring fluids ++ * ++ * @param maxDistance this is the maximum distance to scan ++ * @return blockface of the block that the living entity has targeted, ++ * or null if no block is targeted ++ */ ++ @Nullable ++ public default org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance) { ++ return getTargetBlockFace(maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode.NEVER); ++ } ++ ++ /** ++ * Gets the blockface of that block that the living entity has targeted ++ * ++ * @param maxDistance this is the maximum distance to scan ++ * @param fluidMode whether to check fluids or not ++ * @return blockface of the block that the living entity has targeted, ++ * or null if no block is targeted ++ */ ++ @Nullable ++ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode); ++ ++ /** ++ * Gets information about the block the living entity has targeted, ignoring fluids ++ * ++ * @param maxDistance this is the maximum distance to scan ++ * @return TargetBlockInfo about the block the living entity has targeted, ++ * or null if no block is targeted ++ */ ++ @Nullable ++ public default com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance) { ++ return getTargetBlockInfo(maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode.NEVER); ++ } ++ ++ /** ++ * Gets information about the block the living entity has targeted ++ * ++ * @param maxDistance this is the maximum distance to scan ++ * @param fluidMode whether to check fluids or not ++ * @return TargetBlockInfo about the block the living entity has targeted, ++ * or null if no block is targeted ++ */ ++ @Nullable ++ public com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode); ++ // Paper end ++ + /** + * Gets the last two blocks along the living entity's line of sight. + *

    diff --git a/patches/api-unmapped/0145-Improve-death-events.patch b/patches/api-unmapped/0145-Improve-death-events.patch new file mode 100644 index 0000000000..f42921460c --- /dev/null +++ b/patches/api-unmapped/0145-Improve-death-events.patch @@ -0,0 +1,181 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Tue, 21 Aug 2018 01:32:28 +0100 +Subject: [PATCH] Improve death events + +This adds the ability to cancel the death events and to modify the sound +an entity makes when dying. (In cases were no sound should it will be +called with shouldPlaySound set to false allowing unsilencing of silent +entities) + +It makes handling of entity deaths a lot nicer as you no longer need +to listen on the damage event and calculate if the entity dies yourself +to cancel the death which has the benefit of also receiving the dropped +items and experience which is otherwise only properly possible by using +internal code. + +diff --git a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java +index a5984ab06cce95d30e70511e125f69339b574c04..e19a3df9aa2204b44c0b029bda141ae6306f60a1 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java +@@ -5,14 +5,24 @@ import org.bukkit.entity.LivingEntity; + import org.bukkit.event.HandlerList; + import org.bukkit.inventory.ItemStack; + import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; + + /** + * Thrown whenever a LivingEntity dies + */ +-public class EntityDeathEvent extends EntityEvent { ++public class EntityDeathEvent extends EntityEvent implements org.bukkit.event.Cancellable { // Paper - make cancellable + private static final HandlerList handlers = new HandlerList(); + private final List drops; + private int dropExp = 0; ++ // Paper start - make cancellable ++ private boolean cancelled; ++ private double reviveHealth = 0; ++ private boolean shouldPlayDeathSound; ++ @Nullable private org.bukkit.Sound deathSound; ++ @Nullable private org.bukkit.SoundCategory deathSoundCategory; ++ private float deathSoundVolume; ++ private float deathSoundPitch; ++ // Paper end + + public EntityDeathEvent(@NotNull final LivingEntity entity, @NotNull final List drops) { + this(entity, drops, 0); +@@ -74,4 +84,134 @@ public class EntityDeathEvent extends EntityEvent { + public static HandlerList getHandlerList() { + return handlers; + } ++ ++ // Paper start - make cancellable ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++ ++ /** ++ * Get the amount of health that the entity should revive with after cancelling the event. ++ * Set to the entity's max health by default. ++ * ++ * @return The amount of health ++ */ ++ public double getReviveHealth() { ++ return reviveHealth; ++ } ++ ++ /** ++ * Set the amount of health that the entity should revive with after cancelling the event. ++ * Revive health value must be between 0 (exclusive) and the entity's max health (inclusive). ++ * ++ * @param reviveHealth The amount of health ++ * @throws IllegalArgumentException Thrown if the health is {@literal <= 0 or >} max health ++ */ ++ public void setReviveHealth(double reviveHealth) throws IllegalArgumentException { ++ double maxHealth = ((LivingEntity) entity).getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue(); ++ if ((maxHealth != 0 && reviveHealth <= 0) || (reviveHealth > maxHealth)) { ++ throw new IllegalArgumentException("Health must be between 0 (exclusive) and " + maxHealth + " (inclusive), but was " + reviveHealth); ++ } ++ this.reviveHealth = reviveHealth; ++ } ++ ++ ++ /** ++ * Whether or not the death sound should play when the entity dies. If the event is cancelled it does not play! ++ * ++ * @return Whether or not the death sound should play. Event is called with this set to false if the entity is silent. ++ */ ++ public boolean shouldPlayDeathSound() { ++ return shouldPlayDeathSound; ++ } ++ ++ /** ++ * Set whether or not the death sound should play when the entity dies. If the event is cancelled it does not play! ++ * ++ * @param playDeathSound Enable or disable the death sound ++ */ ++ public void setShouldPlayDeathSound(boolean playDeathSound) { ++ this.shouldPlayDeathSound = playDeathSound; ++ } ++ ++ /** ++ * Get the sound that the entity makes when dying ++ * ++ * @return The sound that the entity makes ++ */ ++ @Nullable ++ public org.bukkit.Sound getDeathSound() { ++ return deathSound; ++ } ++ ++ /** ++ * Set the sound that the entity makes when dying ++ * ++ * @param sound The sound that the entity should make when dying ++ */ ++ public void setDeathSound(@Nullable org.bukkit.Sound sound) { ++ deathSound = sound; ++ } ++ ++ /** ++ * Get the sound category that the death sound should play in ++ * ++ * @return The sound category ++ */ ++ @Nullable ++ public org.bukkit.SoundCategory getDeathSoundCategory() { ++ return deathSoundCategory; ++ } ++ ++ /** ++ * Set the sound category that the death sound should play in. ++ * ++ * @param soundCategory The sound category ++ */ ++ public void setDeathSoundCategory(@Nullable org.bukkit.SoundCategory soundCategory) { ++ this.deathSoundCategory = soundCategory; ++ } ++ ++ /** ++ * Get the volume that the death sound will play at. ++ * ++ * @return The volume the death sound will play at ++ */ ++ public float getDeathSoundVolume() { ++ return deathSoundVolume; ++ } ++ ++ /** ++ * Set the volume the death sound should play at. If the event is cancelled this will not play the sound! ++ * ++ * @param volume The volume the death sound should play at ++ */ ++ public void setDeathSoundVolume(float volume) { ++ this.deathSoundVolume = volume; ++ } ++ ++ /** ++ * Get the pitch that the death sound will play with. ++ * ++ * @return The pitch the death sound will play with ++ */ ++ public float getDeathSoundPitch() { ++ return deathSoundPitch; ++ } ++ ++ /** ++ * GSetet the pitch that the death sound should play with. ++ * ++ * @param pitch The pitch the death sound should play with ++ */ ++ public void setDeathSoundPitch(float pitch) { ++ this.deathSoundPitch = pitch; ++ } ++ // Paper end + } diff --git a/patches/api-unmapped/0146-Mob-Pathfinding-API.patch b/patches/api-unmapped/0146-Mob-Pathfinding-API.patch new file mode 100644 index 0000000000..8408100069 --- /dev/null +++ b/patches/api-unmapped/0146-Mob-Pathfinding-API.patch @@ -0,0 +1,259 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 9 Sep 2018 12:39:06 -0400 +Subject: [PATCH] Mob Pathfinding API + +Adds an API to allow plugins to instruct a Mob to Pathfind to a Location or Entity + +This does not do anything to stop other AI rules from changing the location, so +it is still up to the plugin to control that or override after another goal changed +the location. + +You can use EntityPathfindEvent to cancel new pathfinds from overriding your current. + +diff --git a/src/main/java/com/destroystokyo/paper/entity/Pathfinder.java b/src/main/java/com/destroystokyo/paper/entity/Pathfinder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e2a6f9c3881ff9d7373ac30e60009200432555aa +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/Pathfinder.java +@@ -0,0 +1,212 @@ ++package com.destroystokyo.paper.entity; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Mob; ++ ++import java.util.List; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Handles pathfinding operations for an Entity ++ */ ++public interface Pathfinder { ++ ++ /** ++ * ++ * @return The entity that is controlled by this pathfinder ++ */ ++ @NotNull ++ Mob getEntity(); ++ ++ /** ++ * Instructs the Entity to stop trying to navigate to its current desired location ++ */ ++ void stopPathfinding(); ++ ++ /** ++ * If the entity is currently trying to navigate to a destination, this will return true ++ * @return true if the entity is navigating to a destination ++ */ ++ boolean hasPath(); ++ ++ /** ++ * @return The location the entity is trying to navigate to, or null if there is no destination ++ */ ++ @Nullable ++ PathResult getCurrentPath(); ++ ++ /** ++ * Calculates a destination for the Entity to navigate to, but does not set it ++ * as the current target. Useful for calculating what would happen before setting it. ++ * @param loc Location to navigate to ++ * @return The closest Location the Entity can get to for this navigation, or null if no path could be calculated ++ */ ++ @Nullable PathResult findPath(@NotNull Location loc); ++ ++ /** ++ * Calculates a destination for the Entity to navigate to to reach the target entity, ++ * but does not set it as the current target. ++ * Useful for calculating what would happen before setting it. ++ * ++ * The behavior of this PathResult is subject to the games pathfinding rules, and may ++ * result in the pathfinding automatically updating to follow the target Entity. ++ * ++ * However, this behavior is not guaranteed, and is subject to the games behavior. ++ * ++ * @param target the Entity to navigate to ++ * @return The closest Location the Entity can get to for this navigation, or null if no path could be calculated ++ */ ++ @Nullable PathResult findPath(@NotNull LivingEntity target); ++ ++ /** ++ * Calculates a destination for the Entity to navigate to, and sets it with default speed ++ * as the current target. ++ * @param loc Location to navigate to ++ * @return If the pathfinding was successfully started ++ */ ++ default boolean moveTo(@NotNull Location loc) { ++ return moveTo(loc, 1); ++ } ++ ++ /** ++ * Calculates a destination for the Entity to navigate to, with desired speed ++ * as the current target. ++ * @param loc Location to navigate to ++ * @param speed Speed multiplier to navigate at, where 1 is 'normal' ++ * @return If the pathfinding was successfully started ++ */ ++ default boolean moveTo(@NotNull Location loc, double speed) { ++ PathResult path = findPath(loc); ++ return path != null && moveTo(path, speed); ++ } ++ ++ /** ++ * Calculates a destination for the Entity to navigate to to reach the target entity, ++ * and sets it with default speed. ++ * ++ * The behavior of this PathResult is subject to the games pathfinding rules, and may ++ * result in the pathfinding automatically updating to follow the target Entity. ++ * ++ * However, this behavior is not guaranteed, and is subject to the games behavior. ++ * ++ * @param target the Entity to navigate to ++ * @return If the pathfinding was successfully started ++ */ ++ default boolean moveTo(@NotNull LivingEntity target) { ++ return moveTo(target, 1); ++ } ++ ++ /** ++ * Calculates a destination for the Entity to navigate to to reach the target entity, ++ * and sets it with specified speed. ++ * ++ * The behavior of this PathResult is subject to the games pathfinding rules, and may ++ * result in the pathfinding automatically updating to follow the target Entity. ++ * ++ * However, this behavior is not guaranteed, and is subject to the games behavior. ++ * ++ * @param target the Entity to navigate to ++ * @param speed Speed multiplier to navigate at, where 1 is 'normal' ++ * @return If the pathfinding was successfully started ++ */ ++ default boolean moveTo(@NotNull LivingEntity target, double speed) { ++ PathResult path = findPath(target); ++ return path != null && moveTo(path, speed); ++ } ++ ++ /** ++ * Takes the result of a previous pathfinding calculation and sets it ++ * as the active pathfinding with default speed. ++ * ++ * @param path The Path to start following ++ * @return If the pathfinding was successfully started ++ */ ++ default boolean moveTo(@NotNull PathResult path) { ++ return moveTo(path, 1); ++ } ++ ++ /** ++ * Takes the result of a previous pathfinding calculation and sets it ++ * as the active pathfinding, ++ * ++ * @param path The Path to start following ++ * @param speed Speed multiplier to navigate at, where 1 is 'normal' ++ * @return If the pathfinding was successfully started ++ */ ++ boolean moveTo(@NotNull PathResult path, double speed); ++ ++ /** ++ * Checks if this pathfinder allows passing through closed doors. ++ * ++ * @return if this pathfinder allows passing through closed doors ++ */ ++ boolean canOpenDoors(); ++ ++ /** ++ * Allows this pathfinder to pass through closed doors, or not ++ * ++ * @param canOpenDoors if the mob can pass through closed doors, or not ++ */ ++ void setCanOpenDoors(boolean canOpenDoors); ++ ++ /** ++ * Checks if this pathfinder allows passing through open doors. ++ * ++ * @return if this pathfinder allows passing through open doors ++ */ ++ boolean canPassDoors(); ++ ++ /** ++ * Allows this pathfinder to pass through open doors, or not ++ * ++ * @param canPassDoors if the mob can pass through open doors, or not ++ */ ++ void setCanPassDoors(boolean canPassDoors); ++ ++ /** ++ * Checks if this pathfinder assumes that the mob can float ++ * ++ * @return if this pathfinder assumes that the mob can float ++ */ ++ boolean canFloat(); ++ ++ /** ++ * Makes this pathfinder assume that the mob can float, or not ++ * ++ * @param canFloat if the mob can float, or not ++ */ ++ void setCanFloat(boolean canFloat); ++ ++ /** ++ * Represents the result of a pathfinding calculation ++ */ ++ interface PathResult { ++ ++ /** ++ * All currently calculated points to follow along the path to reach the destination location ++ * ++ * Will return points the entity has already moved past, see {@link #getNextPointIndex()} ++ * @return List of points ++ */ ++ @NotNull ++ List getPoints(); ++ ++ /** ++ * @return Returns the index of the current point along the points returned in {@link #getPoints()} the entity ++ * is trying to reach, or null if we are done with this pathfinding. ++ */ ++ int getNextPointIndex(); ++ ++ /** ++ * @return The next location in the path points the entity is trying to reach, or null if there is no next point ++ */ ++ @Nullable Location getNextPoint(); ++ ++ /** ++ * @return The closest point the path can get to the target location ++ */ ++ @Nullable Location getFinalPoint(); ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java +index be9334a8b5fba9181ad63c211697e798be63da25..b132287817d35579ca5128a1ed5c242bf229771a 100644 +--- a/src/main/java/org/bukkit/entity/Mob.java ++++ b/src/main/java/org/bukkit/entity/Mob.java +@@ -1,6 +1,7 @@ + package org.bukkit.entity; + + import org.bukkit.loot.Lootable; ++import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + + /** +@@ -8,6 +9,15 @@ import org.jetbrains.annotations.Nullable; + */ + public interface Mob extends LivingEntity, Lootable { + ++ // Paper start ++ /** ++ * Enables access to control the pathing of an Entity ++ * @return Pathfinding Manager for this entity ++ */ ++ @NotNull ++ com.destroystokyo.paper.entity.Pathfinder getPathfinder(); ++ // Paper end ++ + /** + * Instructs this Mob to set the specified LivingEntity as its target. + *

    diff --git a/patches/api-unmapped/0147-Expose-attack-cooldown-methods-for-Player.patch b/patches/api-unmapped/0147-Expose-attack-cooldown-methods-for-Player.patch new file mode 100644 index 0000000000..e67693668d --- /dev/null +++ b/patches/api-unmapped/0147-Expose-attack-cooldown-methods-for-Player.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 4 Sep 2018 15:01:54 -0500 +Subject: [PATCH] Expose attack cooldown methods for Player + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 257bf4a75393d1e25839bcae0ca5551ee832c627..ec87c78d0f9379511467b6d13b9cdfa4c19d15ca 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1889,6 +1889,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @param profile The new profile to use + */ + void setPlayerProfile(@NotNull PlayerProfile profile); ++ ++ /** ++ * Returns the amount of ticks the current cooldown lasts ++ * ++ * @return Amount of ticks cooldown will last ++ */ ++ float getCooldownPeriod(); ++ ++ /** ++ * Returns the percentage of attack power available based on the cooldown (zero to one). ++ * ++ * @param adjustTicks Amount of ticks to add to cooldown counter for this calculation ++ * @return Percentage of attack power available ++ */ ++ float getCooledAttackStrength(float adjustTicks); ++ ++ /** ++ * Reset the cooldown counter to 0, effectively starting the cooldown period. ++ */ ++ void resetCooldown(); + // Paper end + + // Spigot start diff --git a/patches/api-unmapped/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/patches/api-unmapped/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch new file mode 100644 index 0000000000..c5b4ce2e41 --- /dev/null +++ b/patches/api-unmapped/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch @@ -0,0 +1,319 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Wed, 12 Sep 2018 18:53:35 +0300 +Subject: [PATCH] Add an API for CanPlaceOn and CanDestroy NBT values + + +diff --git a/src/main/java/com/destroystokyo/paper/Namespaced.java b/src/main/java/com/destroystokyo/paper/Namespaced.java +new file mode 100644 +index 0000000000000000000000000000000000000000..cd1a34b82870684e09e18c47169bd472ecbbb91f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/Namespaced.java +@@ -0,0 +1,40 @@ ++package com.destroystokyo.paper; ++ ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents a namespaced resource, see {@link org.bukkit.NamespacedKey} for single elements ++ * or {@link com.destroystokyo.paper.NamespacedTag} for a collection of elements ++ * ++ * Namespaces may only contain lowercase alphanumeric characters, periods, ++ * underscores, and hyphens. ++ *

    ++ * Keys may only contain lowercase alphanumeric characters, periods, ++ * underscores, hyphens, and forward slashes. ++ *

    ++ * You should not be implementing this interface yourself, use {@link org.bukkit.NamespacedKey} ++ * or {@link com.destroystokyo.paper.NamespacedTag} as needed instead. ++ */ ++public interface Namespaced { ++ /** ++ * Gets the namespace this resource is a part of ++ *

    ++ * This is contractually obligated to only contain lowercase alphanumeric characters, ++ * periods, underscores, and hyphens. ++ * ++ * @return resource namespace ++ */ ++ @NotNull ++ String getNamespace(); ++ ++ /** ++ * Gets the key corresponding to this resource ++ *

    ++ * This is contractually obligated to only contain lowercase alphanumeric characters, ++ * periods, underscores, hyphens, and forward slashes. ++ * ++ * @return resource key ++ */ ++ @NotNull ++ String getKey(); ++} +diff --git a/src/main/java/com/destroystokyo/paper/NamespacedTag.java b/src/main/java/com/destroystokyo/paper/NamespacedTag.java +new file mode 100644 +index 0000000000000000000000000000000000000000..28f3fda950999a9c964a3608042ca60567ae1d6a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/NamespacedTag.java +@@ -0,0 +1,142 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Preconditions; ++import java.util.Locale; ++import java.util.UUID; ++import java.util.regex.Pattern; ++import org.bukkit.plugin.Plugin; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents a String based key pertaining to a tagged entry. Consists of two components - a namespace ++ * and a key. ++ *

    ++ * Namespaces may only contain lowercase alphanumeric characters, periods, ++ * underscores, and hyphens. ++ *

    ++ * Keys may only contain lowercase alphanumeric characters, periods, ++ * underscores, hyphens, and forward slashes. ++ * ++ */ ++// Paper - entire class, based on org.bukkit.NamespacedKey ++public final class NamespacedTag implements com.destroystokyo.paper.Namespaced { ++ ++ /** ++ * The namespace representing all inbuilt keys. ++ */ ++ public static final String MINECRAFT = "minecraft"; ++ /** ++ * The namespace representing all keys generated by Bukkit for backwards ++ * compatibility measures. ++ */ ++ public static final String BUKKIT = "bukkit"; ++ // ++ private static final Pattern VALID_NAMESPACE = Pattern.compile("[a-z0-9._-]+"); ++ private static final Pattern VALID_KEY = Pattern.compile("[a-z0-9/._-]+"); ++ // ++ private final String namespace; ++ private final String key; ++ ++ /** ++ * Create a key in a specific namespace. ++ * ++ * @param namespace String representing a grouping of keys ++ * @param key Name for this specific key ++ * @deprecated should never be used by plugins, for internal use only!! ++ */ ++ @Deprecated ++ public NamespacedTag(@NotNull String namespace, @NotNull String key) { ++ Preconditions.checkArgument(namespace != null && VALID_NAMESPACE.matcher(namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", namespace); ++ Preconditions.checkArgument(key != null && VALID_KEY.matcher(key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", key); ++ ++ this.namespace = namespace; ++ this.key = key; ++ ++ String string = toString(); ++ Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters", string); ++ } ++ ++ /** ++ * Create a key in the plugin's namespace. ++ *

    ++ * Namespaces may only contain lowercase alphanumeric characters, periods, ++ * underscores, and hyphens. ++ *

    ++ * Keys may only contain lowercase alphanumeric characters, periods, ++ * underscores, hyphens, and forward slashes. ++ * ++ * @param plugin the plugin to use for the namespace ++ * @param key the key to create ++ */ ++ public NamespacedTag(@NotNull Plugin plugin, @NotNull String key) { ++ Preconditions.checkArgument(plugin != null, "Plugin cannot be null"); ++ Preconditions.checkArgument(key != null, "Key cannot be null"); ++ ++ this.namespace = plugin.getName().toLowerCase(Locale.ROOT); ++ this.key = key.toLowerCase().toLowerCase(Locale.ROOT); ++ ++ // Check validity after normalization ++ Preconditions.checkArgument(VALID_NAMESPACE.matcher(this.namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", this.namespace); ++ Preconditions.checkArgument(VALID_KEY.matcher(this.key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", this.key); ++ ++ String string = toString(); ++ Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters (%s)", string); ++ } ++ ++ @NotNull ++ public String getNamespace() { ++ return namespace; ++ } ++ ++ @NotNull ++ public String getKey() { ++ return key; ++ } ++ ++ @Override ++ public int hashCode() { ++ int hash = 7; ++ hash = 47 * hash + this.namespace.hashCode(); ++ hash = 47 * hash + this.key.hashCode(); ++ return hash; ++ } ++ ++ @Override ++ public boolean equals(Object obj) { ++ if (obj == null) { ++ return false; ++ } ++ if (getClass() != obj.getClass()) { ++ return false; ++ } ++ final NamespacedTag other = (NamespacedTag) obj; ++ return this.namespace.equals(other.namespace) && this.key.equals(other.key); ++ } ++ ++ @Override ++ public String toString() { ++ return "#" + this.namespace + ":" + this.key; ++ } ++ ++ /** ++ * Return a new random key in the {@link #BUKKIT} namespace. ++ * ++ * @return new key ++ * @deprecated should never be used by plugins, for internal use only!! ++ */ ++ @Deprecated ++ public static NamespacedTag randomKey() { ++ return new NamespacedTag(BUKKIT, UUID.randomUUID().toString()); ++ } ++ ++ /** ++ * Get a key in the Minecraft namespace. ++ * ++ * @param key the key to use ++ * @return new key in the Minecraft namespace ++ */ ++ @NotNull ++ public static NamespacedTag minecraft(@NotNull String key) { ++ return new NamespacedTag(MINECRAFT, key); ++ } ++} +diff --git a/src/main/java/org/bukkit/NamespacedKey.java b/src/main/java/org/bukkit/NamespacedKey.java +index c65f0d6569c130b4920a9e71ad24af6427f1f030..01bcb3a1bdb5accdf844d0178cec3d25746b3eaa 100644 +--- a/src/main/java/org/bukkit/NamespacedKey.java ++++ b/src/main/java/org/bukkit/NamespacedKey.java +@@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable; + * underscores, hyphens, and forward slashes. + * + */ +-public final class NamespacedKey implements net.kyori.adventure.key.Key { // Paper - implement Key ++public final class NamespacedKey implements net.kyori.adventure.key.Key, com.destroystokyo.paper.Namespaced { // Paper - implement Key and Namespaced + + /** + * The namespace representing all inbuilt keys. +@@ -84,11 +84,13 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key { // Pap + } + + @NotNull ++ @Override // Paper + public String getNamespace() { + return namespace; + } + + @NotNull ++ @Override // Paper + public String getKey() { + return key; + } +diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java +index 1c362636c56db0e6c118171ba367c43c4f7cff33..01b462fccce71cef3398dd43944046f322b8e57e 100644 +--- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java +@@ -432,4 +432,87 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + @SuppressWarnings("javadoc") + @NotNull + ItemMeta clone(); ++ ++ // Paper start - Add an API for CanPlaceOn and CanDestroy NBT values ++ /** ++ * Gets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} ++ * ++ * @return Set of materials ++ * @deprecated Minecraft does not limit this to the material enum, Use {@link #getDestroyableKeys()} as a replacement ++ */ ++ @Deprecated ++ Set getCanDestroy(); ++ ++ /** ++ * Sets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} ++ * ++ * @param canDestroy Set of materials ++ * @deprecated Minecraft does not limit this to the material enum, Use {@link #setDestroyableKeys(Collection)} as a replacement ++ */ ++ @Deprecated ++ void setCanDestroy(Set canDestroy); ++ ++ /** ++ * Gets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} ++ * ++ * @return Set of materials ++ * @deprecated Minecraft does not limit this to the material enum, Use {@link #getPlaceableKeys()} as a replacement ++ */ ++ @Deprecated ++ Set getCanPlaceOn(); ++ ++ /** ++ * Sets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} ++ * ++ * @param canPlaceOn Set of materials ++ * @deprecated Minecraft does not limit this to the material enum, Use {@link #setPlaceableKeys(Collection)} as a replacement ++ */ ++ @Deprecated ++ void setCanPlaceOn(Set canPlaceOn); ++ ++ /** ++ * Gets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE} ++ * ++ * @return Set of {@link com.destroystokyo.paper.Namespaced} ++ */ ++ @NotNull ++ Set getDestroyableKeys(); ++ ++ /** ++ * Sets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE} ++ * ++ * @param canDestroy Collection of {@link com.destroystokyo.paper.Namespaced} ++ */ ++ void setDestroyableKeys(@NotNull Collection canDestroy); ++ ++ /** ++ * Gets the collection of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} ++ * ++ * @return Set of {@link com.destroystokyo.paper.Namespaced} ++ */ ++ @NotNull ++ Set getPlaceableKeys(); ++ ++ /** ++ * Sets the set of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} ++ * ++ * @param canPlaceOn Collection of {@link com.destroystokyo.paper.Namespaced} ++ */ ++ @NotNull ++ void setPlaceableKeys(@NotNull Collection canPlaceOn); ++ ++ /** ++ * Checks for the existence of any keys that the item can be placed on ++ * ++ * @return true if this item has placeable keys ++ */ ++ boolean hasPlaceableKeys(); ++ ++ /** ++ * Checks for the existence of any keys that the item can destroy ++ * ++ * @return true if this item has destroyable keys ++ */ ++ boolean hasDestroyableKeys(); ++ // Paper end + } diff --git a/patches/api-unmapped/0149-Performance-Concurrency-Improvements-to-Permissions.patch b/patches/api-unmapped/0149-Performance-Concurrency-Improvements-to-Permissions.patch new file mode 100644 index 0000000000..4d64579e4a --- /dev/null +++ b/patches/api-unmapped/0149-Performance-Concurrency-Improvements-to-Permissions.patch @@ -0,0 +1,113 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 13 Sep 2018 20:51:50 -0400 +Subject: [PATCH] Performance & Concurrency Improvements to Permissions + +Modifying of permissions was only half protected, enabling concurrency +issues to occur if permissions were modified async. + +While no plugin really should be doing that, modifying operations +are not heavily called, so they are safe to add synchronization to. + +Now, all modification API's will be synchronized ensuring safety. + +Additionally, hasPermission was victim to a common java newbie mistake +of calling if (containsKey(k)) return get(k), resulting in 2 map lookups. + +Optimized it to simply be a single get call cutting permission map +lookups in half. + +diff --git a/src/main/java/org/bukkit/permissions/PermissibleBase.java b/src/main/java/org/bukkit/permissions/PermissibleBase.java +index 497775f7f8fa2eae34555ca0f0c6ba72d6cfab3f..c94e4cdb5785d5dfcb704c4adabda0b19a20ec7d 100644 +--- a/src/main/java/org/bukkit/permissions/PermissibleBase.java ++++ b/src/main/java/org/bukkit/permissions/PermissibleBase.java +@@ -75,8 +75,11 @@ public class PermissibleBase implements Permissible { + + String name = inName.toLowerCase(java.util.Locale.ENGLISH); + +- if (isPermissionSet(name)) { +- return permissions.get(name).getValue(); ++ // Paper start ++ PermissionAttachmentInfo info = permissions.get(name); ++ if (info != null) { ++ return info.getValue(); ++ // Paper end + } else { + Permission perm = Bukkit.getServer().getPluginManager().getPermission(name); + +@@ -96,15 +99,18 @@ public class PermissibleBase implements Permissible { + + String name = perm.getName().toLowerCase(java.util.Locale.ENGLISH); + +- if (isPermissionSet(name)) { +- return permissions.get(name).getValue(); ++ // Paper start ++ PermissionAttachmentInfo info = permissions.get(name); ++ if (info != null) { ++ return info.getValue(); + } ++ // Paper end + return perm.getDefault().getValue(isOp()); + } + + @Override + @NotNull +- public PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value) { ++ public synchronized PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value) { // Paper - synchronized + if (name == null) { + throw new IllegalArgumentException("Permission name cannot be null"); + } else if (plugin == null) { +@@ -123,7 +129,7 @@ public class PermissibleBase implements Permissible { + + @Override + @NotNull +- public PermissionAttachment addAttachment(@NotNull Plugin plugin) { ++ public synchronized PermissionAttachment addAttachment(@NotNull Plugin plugin) { // Paper - synchronized + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } else if (!plugin.isEnabled()) { +@@ -139,7 +145,7 @@ public class PermissibleBase implements Permissible { + } + + @Override +- public void removeAttachment(@NotNull PermissionAttachment attachment) { ++ public synchronized void removeAttachment(@NotNull PermissionAttachment attachment) { // Paper - synchronized + if (attachment == null) { + throw new IllegalArgumentException("Attachment cannot be null"); + } +@@ -159,7 +165,7 @@ public class PermissibleBase implements Permissible { + } + + @Override +- public void recalculatePermissions() { ++ public synchronized void recalculatePermissions() { // Paper - synchronized + clearPermissions(); + Set defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(isOp()); + Bukkit.getServer().getPluginManager().subscribeToDefaultPerms(isOp(), parent); +@@ -208,7 +214,7 @@ public class PermissibleBase implements Permissible { + + @Override + @Nullable +- public PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks) { ++ public synchronized PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks) { // Paper + if (name == null) { + throw new IllegalArgumentException("Permission name cannot be null"); + } else if (plugin == null) { +@@ -228,7 +234,7 @@ public class PermissibleBase implements Permissible { + + @Override + @Nullable +- public PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks) { ++ public synchronized PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks) { // Paper - synchronized + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } else if (!plugin.isEnabled()) { +@@ -248,7 +254,7 @@ public class PermissibleBase implements Permissible { + + @Override + @NotNull +- public Set getEffectivePermissions() { ++ public synchronized Set getEffectivePermissions() { // Paper - synchronized + return new HashSet(permissions.values()); + } + diff --git a/patches/api-unmapped/0150-Add-ItemStackRecipeChoice-Draft-API.patch b/patches/api-unmapped/0150-Add-ItemStackRecipeChoice-Draft-API.patch new file mode 100644 index 0000000000..1a4eca8cc0 --- /dev/null +++ b/patches/api-unmapped/0150-Add-ItemStackRecipeChoice-Draft-API.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 13 Sep 2018 21:39:26 -0400 +Subject: [PATCH] Add ItemStackRecipeChoice Draft API + +This is based on Spigots Draft API. This is subject to change + +Allows creating recipes that must match isSimilar to full item stack. + +diff --git a/src/main/java/com/destroystokyo/paper/inventory/ItemStackRecipeChoice.java b/src/main/java/com/destroystokyo/paper/inventory/ItemStackRecipeChoice.java +new file mode 100644 +index 0000000000000000000000000000000000000000..43e6576b1d1bb811f9feb22de0024d9c823cb21a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/inventory/ItemStackRecipeChoice.java +@@ -0,0 +1,51 @@ ++package com.destroystokyo.paper.inventory; ++ ++import org.bukkit.inventory.ItemStack; ++import org.bukkit.inventory.RecipeChoice; ++ ++import java.util.ArrayList; ++import java.util.List; ++ ++/** ++ * Allows crafting Items that require full matching itemstacks to complete the recipe for custom items ++ * @deprecated Draft API ++ */ ++@Deprecated ++public class ItemStackRecipeChoice implements RecipeChoice { ++ ++ protected final List choices = new ArrayList<>(); ++ ++ public ItemStackRecipeChoice(ItemStack choices) { ++ this.choices.add(choices); ++ } ++ ++ public ItemStackRecipeChoice(List choices) { ++ this.choices.addAll(choices); ++ } ++ ++ @Override ++ public ItemStack getItemStack() { ++ return choices.isEmpty() ? null : choices.get(0); ++ } ++ ++ @Override ++ public RecipeChoice clone() { ++ try { ++ ItemStackRecipeChoice clone = (ItemStackRecipeChoice) super.clone(); ++ clone.choices.addAll(this.choices); ++ return clone; ++ } catch (CloneNotSupportedException ex) { ++ throw new AssertionError(ex); ++ } ++ } ++ ++ @Override ++ public boolean test(ItemStack itemStack) { ++ for (ItemStack stack : choices) { ++ if (stack.isSimilar(itemStack)) { ++ return true; ++ } ++ } ++ return false; ++ } ++} diff --git a/patches/api-unmapped/0151-Implement-furnace-cook-speed-multiplier-API.patch b/patches/api-unmapped/0151-Implement-furnace-cook-speed-multiplier-API.patch new file mode 100644 index 0000000000..cb4250b87c --- /dev/null +++ b/patches/api-unmapped/0151-Implement-furnace-cook-speed-multiplier-API.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tassu +Date: Thu, 13 Sep 2018 08:45:01 +0300 +Subject: [PATCH] Implement furnace cook speed multiplier API + +Signed-off-by: Tassu + +diff --git a/src/main/java/org/bukkit/block/Furnace.java b/src/main/java/org/bukkit/block/Furnace.java +index c5a8c96fa2204d6b4d2409b1bfc97697d39d964e..9063cf370a0fe66c2a27086e125f9111b77366ae 100644 +--- a/src/main/java/org/bukkit/block/Furnace.java ++++ b/src/main/java/org/bukkit/block/Furnace.java +@@ -61,6 +61,26 @@ public interface Furnace extends Container { + */ + public void setCookTimeTotal(int cookTimeTotal); + ++ // Paper start ++ /** ++ * Gets the cook speed multiplier that this {@link Furnace} will cook ++ * compared to vanilla. ++ * ++ * @return the multiplier, a value between 0 and 200 ++ */ ++ public double getCookSpeedMultiplier(); ++ ++ /** ++ * Sets the speed multiplier that this {@link Furnace} will cook ++ * compared to vanilla. ++ * ++ * @param multiplier the multiplier to set, a value between 0 and 200 ++ * @throws IllegalArgumentException if value is less than 0 ++ * @throws IllegalArgumentException if value is more than 200 ++ */ ++ public void setCookSpeedMultiplier(double multiplier); ++ // Paper end ++ + @NotNull + @Override + public FurnaceInventory getInventory(); diff --git a/patches/api-unmapped/0152-PreSpawnerSpawnEvent.patch b/patches/api-unmapped/0152-PreSpawnerSpawnEvent.patch new file mode 100644 index 0000000000..70ec0d47bd --- /dev/null +++ b/patches/api-unmapped/0152-PreSpawnerSpawnEvent.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Tue, 18 Sep 2018 23:50:10 +0100 +Subject: [PATCH] PreSpawnerSpawnEvent + +This adds a separate event before an entity is spawned by a spawner +which contains the location of the spawner too similarly to how the +SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for +spawners. + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..48cff063594840a07aeaf35513780e28ea019a76 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java +@@ -0,0 +1,29 @@ ++package com.destroystokyo.paper.event.entity; ++ ++ ++import com.google.common.base.Preconditions; ++import org.bukkit.Location; ++import org.bukkit.entity.EntityType; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called before an entity is spawned into a world by a spawner. ++ * ++ * This only includes the spawner's location and not the full BlockState snapshot for performance reasons. ++ * If you really need it you have to get the spawner yourself. ++ */ ++ ++public class PreSpawnerSpawnEvent extends PreCreatureSpawnEvent { ++ @NotNull private final Location spawnerLocation; ++ ++ public PreSpawnerSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull Location spawnerLocation) { ++ super(location, type, CreatureSpawnEvent.SpawnReason.SPAWNER); ++ this.spawnerLocation = Preconditions.checkNotNull(spawnerLocation, "Spawner location may not be null"); ++ } ++ ++ @NotNull ++ public Location getSpawnerLocation() { ++ return spawnerLocation; ++ } ++} diff --git a/patches/api-unmapped/0153-Material-API-additions.patch b/patches/api-unmapped/0153-Material-API-additions.patch new file mode 100644 index 0000000000..629bed4425 --- /dev/null +++ b/patches/api-unmapped/0153-Material-API-additions.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 6 Oct 2018 21:14:29 -0400 +Subject: [PATCH] Material API additions + + +diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java +index a9769ae0bad61d200c70331eba0b655da4ba03b2..9c28351c7c3f60c6a3b4020329344f91efeedae1 100644 +--- a/src/main/java/org/bukkit/Material.java ++++ b/src/main/java/org/bukkit/Material.java +@@ -98,6 +98,7 @@ import org.jetbrains.annotations.Nullable; + /** + * An enum of all material IDs accepted by the official server and client + */ ++@SuppressWarnings({"DeprecatedIsStillUsed", "deprecation"}) // Paper + public enum Material implements Keyed { + // + AIR(9648, 0), +@@ -3976,6 +3977,22 @@ public enum Material implements Keyed { + } + } + ++ // Paper start ++ ++ /** ++ * @return If the type is either AIR, CAVE_AIR or VOID_AIR ++ */ ++ public boolean isEmpty() { ++ switch (this) { ++ case AIR: ++ case CAVE_AIR: ++ case VOID_AIR: ++ return true; ++ } ++ return false; ++ } ++ // Paper end ++ + /** + * Do not use for any reason. + * diff --git a/patches/api-unmapped/0154-Add-Material-Tags.patch b/patches/api-unmapped/0154-Add-Material-Tags.patch new file mode 100644 index 0000000000..7fa999bf70 --- /dev/null +++ b/patches/api-unmapped/0154-Add-Material-Tags.patch @@ -0,0 +1,1044 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 17 Jul 2018 01:27:15 -0400 +Subject: [PATCH] Add Material Tags + +This adds a bunch of useful and missing Tags to be able to identify items that +are related to each other by a trait. + +Co-authored-by: Jake Potrebic + +diff --git a/src/main/java/com/destroystokyo/paper/MaterialSetTag.java b/src/main/java/com/destroystokyo/paper/MaterialSetTag.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a02a02aa0c87e0f0ed9e509e4dcab01565b3d92a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/MaterialSetTag.java +@@ -0,0 +1,97 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ */ ++ ++package com.destroystokyo.paper; ++ ++import com.google.common.collect.Lists; ++import io.papermc.paper.tag.BaseTag; ++import org.bukkit.Material; ++import org.bukkit.NamespacedKey; ++import org.bukkit.block.Block; ++import org.bukkit.block.BlockState; ++import org.bukkit.block.data.BlockData; ++import org.bukkit.inventory.ItemStack; ++ ++import java.util.Collection; ++import java.util.Set; ++import java.util.function.Predicate; ++import java.util.stream.Collectors; ++import java.util.stream.Stream; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++public class MaterialSetTag extends BaseTag { ++ ++ /** ++ * @deprecated Use NamespacedKey version of constructor ++ */ ++ @Deprecated ++ public MaterialSetTag(@NotNull Predicate filter) { ++ this(null, Stream.of(Material.values()).filter(filter).collect(Collectors.toList())); ++ } ++ ++ /** ++ * @deprecated Use NamespacedKey version of constructor ++ */ ++ @Deprecated ++ public MaterialSetTag(@NotNull Collection materials) { ++ this(null, materials); ++ } ++ ++ /** ++ * @deprecated Use NamespacedKey version of constructor ++ */ ++ @Deprecated ++ public MaterialSetTag(@NotNull Material... materials) { ++ this(null, materials); ++ } ++ ++ public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Predicate filter) { ++ this(key, Stream.of(Material.values()).filter(filter).collect(Collectors.toList())); ++ } ++ ++ public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Material... materials) { ++ this(key, Lists.newArrayList(materials)); ++ } ++ ++ public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Collection materials) { ++ this(key != null ? key : NamespacedKey.randomKey(), materials, ((Predicate) Material::isLegacy).negate()); ++ } ++ ++ public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Collection materials, @NotNull Predicate...globalPredicates) { ++ super(Material.class, key != null ? key : NamespacedKey.randomKey(), materials, globalPredicates); ++ } ++ ++ @NotNull ++ @Override ++ protected Set getAllPossibleValues() { ++ return Stream.of(Material.values()).collect(Collectors.toSet()); ++ } ++ ++ @Override ++ @NotNull ++ protected String getName(@NotNull Material value) { ++ return value.name(); ++ } ++ ++ public boolean isTagged(@NotNull BlockData block) { ++ return isTagged(block.getMaterial()); ++ } ++ ++ public boolean isTagged(@NotNull BlockState block) { ++ return isTagged(block.getType()); ++ } ++ ++ public boolean isTagged(@NotNull Block block) { ++ return isTagged(block.getType()); ++ } ++ ++ public boolean isTagged(@NotNull ItemStack item) { ++ return isTagged(item.getType()); ++ } ++ ++ public boolean isTagged(@NotNull Material material) { ++ return this.tagged.contains(material); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/MaterialTags.java b/src/main/java/com/destroystokyo/paper/MaterialTags.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2b5a61a8afa8f73006676cdcb8a34640b43de1c3 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/MaterialTags.java +@@ -0,0 +1,558 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package com.destroystokyo.paper; ++ ++import org.bukkit.Material; ++import org.bukkit.NamespacedKey; ++import org.bukkit.Tag; ++ ++/** ++ * Represents a collection tags to identify materials that share common properties. ++ * Will map to minecraft for missing tags, as well as custom ones that may be useful. ++ */ ++@SuppressWarnings({"NonFinalUtilityClass", "unused", "WeakerAccess"}) ++public class MaterialTags { ++ ++ private static NamespacedKey keyFor(String key) { ++ //noinspection deprecation ++ return new NamespacedKey("paper", key + "_settag"); ++ } ++ public static final MaterialSetTag ARROWS = new MaterialSetTag(keyFor("arrows")) ++ .endsWith("ARROW") ++ .ensureSize("ARROWS", 3); ++ ++ /** ++ * Covers all colors of beds. ++ */ ++ public static final MaterialSetTag BEDS = new MaterialSetTag(keyFor("beds")) ++ .endsWith("_BED") ++ .ensureSize("BEDS", 16); ++ ++ /** ++ * Covers all bucket items. ++ */ ++ public static final MaterialSetTag BUCKETS = new MaterialSetTag(keyFor("buckets")) ++ .endsWith("BUCKET") ++ .ensureSize("BUCKETS", 8); ++ ++ /** ++ * Covers coal and charcoal. ++ */ ++ public static final MaterialSetTag COALS = new MaterialSetTag(keyFor("coals")) ++ .add(Material.COAL, Material.CHARCOAL); ++ ++ /** ++ * Covers both cobblestone wall variants. ++ */ ++ public static final MaterialSetTag COBBLESTONE_WALLS = new MaterialSetTag(keyFor("cobblestone_walls")) ++ .endsWith("COBBLESTONE_WALL") ++ .ensureSize("COBBLESTONE_WALLS", 2); ++ ++ /** ++ * Covers both cobblestone and mossy Cobblestone. ++ */ ++ public static final MaterialSetTag COBBLESTONES = new MaterialSetTag(keyFor("cobblestones")) ++ .add(Material.COBBLESTONE, Material.MOSSY_COBBLESTONE); ++ ++ /** ++ * Covers all colors of concrete. ++ */ ++ public static final MaterialSetTag CONCRETES = new MaterialSetTag(keyFor("concretes")) ++ .endsWith("_CONCRETE") ++ .ensureSize("CONCRETES", 16); ++ ++ /** ++ * Covers all colors of concrete powder. ++ */ ++ public static final MaterialSetTag CONCRETE_POWDER = new MaterialSetTag(keyFor("concrete_powder")) ++ .endsWith("_CONCRETE_POWDER") ++ .ensureSize("CONCRETE_POWDER", 16); ++ ++ /** ++ * Covers the two types of cooked fish. ++ */ ++ public static final MaterialSetTag COOKED_FISH = new MaterialSetTag(keyFor("cooked_fish")) ++ .add(Material.COOKED_COD, Material.COOKED_SALMON); ++ ++ /** ++ * Covers all variants of doors. ++ */ ++ public static final MaterialSetTag DOORS = new MaterialSetTag(keyFor("doors")) ++ .endsWith("_DOOR") ++ .ensureSize("DOORS", 9); ++ ++ /** ++ * Covers all dyes. ++ */ ++ public static final MaterialSetTag DYES = new MaterialSetTag(keyFor("dyes")) ++ .endsWith("_DYE") ++ .ensureSize("DYES", 16); ++ ++ /** ++ * Covers all variants of gates. ++ */ ++ public static final MaterialSetTag FENCE_GATES = new MaterialSetTag(keyFor("fence_gates")) ++ .endsWith("_GATE") ++ .ensureSize("FENCE_GATES", 8); ++ ++ /** ++ * Covers all variants of fences. ++ */ ++ public static final MaterialSetTag FENCES = new MaterialSetTag(keyFor("fences")) ++ .endsWith("_FENCE") ++ .ensureSize("FENCES", 9); ++ ++ /** ++ * Covers all variants of fish buckets. ++ */ ++ public static final MaterialSetTag FISH_BUCKETS = new MaterialSetTag(keyFor("fish_buckets")) ++ .add(Material.COD_BUCKET, Material.PUFFERFISH_BUCKET, Material.SALMON_BUCKET, Material.TROPICAL_FISH_BUCKET); ++ ++ /** ++ * Covers the non-colored glass and 16 stained glass (not panes). ++ */ ++ public static final MaterialSetTag GLASS = new MaterialSetTag(keyFor("glass")) ++ .endsWith("_GLASS") ++ .add(Material.GLASS) ++ .ensureSize("GLASS", 17); ++ ++ /** ++ * Covers the non-colored glass panes and stained glass panes (panes only). ++ */ ++ public static final MaterialSetTag GLASS_PANES = new MaterialSetTag(keyFor("glass_panes")) ++ .endsWith("GLASS_PANE") ++ .ensureSize("GLASS_PANES", 17); ++ ++ /** ++ * Covers all glazed terracotta blocks. ++ */ ++ public static final MaterialSetTag GLAZED_TERRACOTTA = new MaterialSetTag(keyFor("glazed_terracotta")) ++ .endsWith("GLAZED_TERRACOTTA") ++ .ensureSize("GLAZED_TERRACOTTA", 16); ++ ++ /** ++ * Covers the colors of stained terracotta. ++ */ ++ public static final MaterialSetTag STAINED_TERRACOTTA = new MaterialSetTag(keyFor("stained_terracotta")) ++ .endsWith("TERRACOTTA") ++ .not(Material.TERRACOTTA) ++ .notEndsWith("GLAZED_TERRACOTTA") ++ .ensureSize("STAINED_TERRACOTTA", 16); ++ ++ /** ++ * Covers terracotta along with the stained variants. ++ */ ++ public static final MaterialSetTag TERRACOTTA = new MaterialSetTag(keyFor("terracotta")) ++ .endsWith("TERRACOTTA") ++ .ensureSize("TERRACOTTA", 33); ++ ++ /** ++ * Covers both golden apples. ++ */ ++ public static final MaterialSetTag GOLDEN_APPLES = new MaterialSetTag(keyFor("golden_apples")) ++ .endsWith("GOLDEN_APPLE") ++ .ensureSize("GOLDEN_APPLES", 2); ++ ++ /** ++ * Covers the variants of horse armor. ++ */ ++ public static final MaterialSetTag HORSE_ARMORS = new MaterialSetTag(keyFor("horse_armors")) ++ .endsWith("_HORSE_ARMOR") ++ .ensureSize("HORSE_ARMORS", 4); ++ ++ /** ++ * Covers the variants of infested blocks. ++ */ ++ public static final MaterialSetTag INFESTED_BLOCKS = new MaterialSetTag(keyFor("infested_blocks")) ++ .startsWith("INFESTED_") ++ .ensureSize("INFESTED_BLOCKS", 6); ++ ++ /** ++ * Covers the variants of mushroom blocks. ++ */ ++ public static final MaterialSetTag MUSHROOM_BLOCKS = new MaterialSetTag(keyFor("mushroom_blocks")) ++ .endsWith("MUSHROOM_BLOCK") ++ .add(Material.MUSHROOM_STEM) ++ .ensureSize("MUSHROOM_BLOCKS", 3); ++ ++ /** ++ * Covers all mushrooms. ++ */ ++ public static final MaterialSetTag MUSHROOMS = new MaterialSetTag(keyFor("mushrooms")) ++ .add(Material.BROWN_MUSHROOM, Material.RED_MUSHROOM); ++ ++ /** ++ * Covers all music disc items. ++ */ ++ public static final MaterialSetTag MUSIC_DISCS = new MaterialSetTag(keyFor("music_discs")) ++ .startsWith("MUSIC_DISC_"); ++ ++ /** ++ * Covers all ores. ++ */ ++ public static final MaterialSetTag ORES = new MaterialSetTag(keyFor("ores")) ++ .add(Material.ANCIENT_DEBRIS) ++ .endsWith("_ORE") ++ .ensureSize("ORES", 10); ++ ++ /** ++ * Covers all piston typed items and blocks including the piston head and moving piston. ++ */ ++ public static final MaterialSetTag PISTONS = new MaterialSetTag(keyFor("pistons")) ++ .contains("PISTON") ++ .ensureSize("PISTONS", 4); ++ ++ /** ++ * Covers all potato items. ++ */ ++ public static final MaterialSetTag POTATOES = new MaterialSetTag(keyFor("potatoes")) ++ .endsWith("POTATO") ++ .ensureSize("POTATOES", 3); ++ ++ /** ++ * Covers all wooden pressure plates and the weighted pressure plates and the stone pressure plate. ++ */ ++ public static final MaterialSetTag PRESSURE_PLATES = new MaterialSetTag(keyFor("pressure_plates")) ++ .endsWith("_PRESSURE_PLATE") ++ .ensureSize("PRESSURE_PLATES", 12); ++ ++ /** ++ * Covers the variants of prismarine blocks. ++ */ ++ public static final MaterialSetTag PRISMARINE = new MaterialSetTag(keyFor("prismarine")) ++ .add(Material.PRISMARINE, Material.PRISMARINE_BRICKS, Material.DARK_PRISMARINE); ++ ++ /** ++ * Covers the variants of prismarine slabs. ++ */ ++ public static final MaterialSetTag PRISMARINE_SLABS = new MaterialSetTag(keyFor("prismarine_slabs")) ++ .add(Material.PRISMARINE_SLAB, Material.PRISMARINE_BRICK_SLAB, Material.DARK_PRISMARINE_SLAB); ++ ++ /** ++ * Covers the variants of prismarine stairs. ++ */ ++ public static final MaterialSetTag PRISMARINE_STAIRS = new MaterialSetTag(keyFor("prismarine_stairs")) ++ .add(Material.PRISMARINE_STAIRS, Material.PRISMARINE_BRICK_STAIRS, Material.DARK_PRISMARINE_STAIRS); ++ ++ /** ++ * Covers the variants of pumpkins. ++ */ ++ public static final MaterialSetTag PUMPKINS = new MaterialSetTag(keyFor("pumpkins")) ++ .add(Material.CARVED_PUMPKIN, Material.JACK_O_LANTERN, Material.PUMPKIN); ++ ++ /** ++ * Covers the variants of quartz blocks. ++ */ ++ public static final MaterialSetTag QUARTZ_BLOCKS = new MaterialSetTag(keyFor("quartz_blocks")) ++ .add(Material.QUARTZ_BLOCK, Material.QUARTZ_PILLAR, Material.CHISELED_QUARTZ_BLOCK, Material.SMOOTH_QUARTZ); ++ ++ /** ++ * Covers all uncooked fish items. ++ */ ++ public static final MaterialSetTag RAW_FISH = new MaterialSetTag(keyFor("raw_fish")) ++ .add(Material.COD, Material.PUFFERFISH, Material.SALMON, Material.TROPICAL_FISH); ++ ++ /** ++ * Covers the variants of red sandstone blocks. ++ */ ++ public static final MaterialSetTag RED_SANDSTONES = new MaterialSetTag(keyFor("red_sandstones")) ++ .endsWith("RED_SANDSTONE") ++ .ensureSize("RED_SANDSTONES", 4); ++ ++ /** ++ * Covers the variants of sandstone blocks. ++ */ ++ public static final MaterialSetTag SANDSTONES = new MaterialSetTag(keyFor("sandstones")) ++ .add(Material.SANDSTONE, Material.CHISELED_SANDSTONE, Material.CUT_SANDSTONE, Material.SMOOTH_SANDSTONE); ++ ++ /** ++ * Covers sponge and wet sponge. ++ */ ++ public static final MaterialSetTag SPONGES = new MaterialSetTag(keyFor("sponges")) ++ .endsWith("SPONGE") ++ .ensureSize("SPONGES", 2); ++ ++ /** ++ * Covers the non-colored and colored shulker boxes. ++ */ ++ public static final MaterialSetTag SHULKER_BOXES = new MaterialSetTag(keyFor("shulker_boxes")) ++ .endsWith("SHULKER_BOX") ++ .ensureSize("SHULKER_BOXES", 17); ++ ++ /** ++ * Covers zombie, creeper, skeleton, dragon, and player heads. ++ */ ++ public static final MaterialSetTag SKULLS = new MaterialSetTag(keyFor("skulls")) ++ .endsWith("_HEAD") ++ .endsWith("_SKULL") ++ .not(Material.PISTON_HEAD) ++ .ensureSize("SKULLS", 12); ++ ++ /** ++ * Covers all spawn egg items. ++ */ ++ public static final MaterialSetTag SPAWN_EGGS = new MaterialSetTag(keyFor("spawn_eggs")) ++ .endsWith("_SPAWN_EGG") ++ .ensureSize("SPAWN_EGGS", 64); ++ ++ /** ++ * Covers all colors of stained glass. ++ */ ++ public static final MaterialSetTag STAINED_GLASS = new MaterialSetTag(keyFor("stained_glass")) ++ .endsWith("_STAINED_GLASS") ++ .ensureSize("STAINED_GLASS", 16); ++ ++ /** ++ * Covers all colors of stained glass panes. ++ */ ++ public static final MaterialSetTag STAINED_GLASS_PANES = new MaterialSetTag(keyFor("stained_glass_panes")) ++ .endsWith("STAINED_GLASS_PANE") ++ .ensureSize("STAINED_GLASS_PANES", 16); ++ ++ /** ++ * Covers all variants of trapdoors. ++ */ ++ public static final MaterialSetTag TRAPDOORS = new MaterialSetTag(keyFor("trapdoors")) ++ .endsWith("_TRAPDOOR") ++ .ensureSize("TRAPDOORS", 9); ++ ++ /** ++ * Covers all wood variants of doors. ++ */ ++ public static final MaterialSetTag WOODEN_DOORS = new MaterialSetTag(keyFor("wooden_doors")) ++ .endsWith("_DOOR") ++ .not(Material.IRON_DOOR) ++ .ensureSize("WOODEN_DOORS", 8); ++ ++ /** ++ * Covers all wood variants of fences. ++ */ ++ public static final MaterialSetTag WOODEN_FENCES = new MaterialSetTag(keyFor("wooden_fences")) ++ .endsWith("_FENCE") ++ .not(Material.NETHER_BRICK_FENCE) ++ .ensureSize("WOODEN_FENCES", 8); ++ ++ /** ++ * Covers all wood variants of trapdoors. ++ */ ++ public static final MaterialSetTag WOODEN_TRAPDOORS = new MaterialSetTag(keyFor("wooden_trapdoors")) ++ .endsWith("_TRAPDOOR") ++ .not(Material.IRON_TRAPDOOR) ++ .ensureSize("WOODEN_TRAPDOORS", 8); ++ ++ /** ++ * Covers the wood variants of gates. ++ */ ++ public static final MaterialSetTag WOODEN_GATES = new MaterialSetTag(keyFor("wooden_gates")) ++ .endsWith("_GATE") ++ .ensureSize("WOODEN_GATES", 8); ++ ++ /** ++ * Covers the variants of purpur. ++ */ ++ public static final MaterialSetTag PURPUR = new MaterialSetTag(keyFor("purpur")) ++ .startsWith("PURPUR_") ++ .ensureSize("PURPUR", 4); ++ ++ /** ++ * Covers the variants of signs. ++ */ ++ public static final MaterialSetTag SIGNS = new MaterialSetTag(keyFor("signs")) ++ .endsWith("_SIGN") ++ .ensureSize("SIGNS", 16); ++ ++ /** ++ * Covers the variants of a regular torch. ++ */ ++ public static final MaterialSetTag TORCH = new MaterialSetTag(keyFor("torch")) ++ .add(Material.TORCH, Material.WALL_TORCH) ++ .ensureSize("TORCH", 2); ++ ++ /** ++ * Covers the variants of a redstone torch. ++ */ ++ public static final MaterialSetTag REDSTONE_TORCH = new MaterialSetTag(keyFor("restone_torch")) ++ .add(Material.REDSTONE_TORCH, Material.REDSTONE_WALL_TORCH) ++ .ensureSize("REDSTONE_TORCH", 2); ++ ++ /** ++ * Covers the variants of a soul torch. ++ */ ++ public static final MaterialSetTag SOUL_TORCH = new MaterialSetTag(keyFor("soul_torch")) ++ .add(Material.SOUL_TORCH, Material.SOUL_WALL_TORCH) ++ .ensureSize("SOUL_TORCH", 2); ++ ++ /** ++ * Covers the variants of torches. ++ */ ++ public static final MaterialSetTag TORCHES = new MaterialSetTag(keyFor("torches")) ++ .add(TORCH, REDSTONE_TORCH, SOUL_TORCH) ++ .ensureSize("TORCHES", 6); ++ ++ /** ++ * Covers the variants of lanterns. ++ */ ++ public static final MaterialSetTag LANTERNS = new MaterialSetTag(keyFor("lanterns")) ++ .add(Material.LANTERN, Material.SOUL_LANTERN) ++ .ensureSize("LANTERNS", 2); ++ ++ /** ++ * Covers the variants of rails. ++ */ ++ public static final MaterialSetTag RAILS = new MaterialSetTag(keyFor("rails")) ++ .endsWith("RAIL") ++ .ensureSize("RAILS", 4); ++ ++ /** ++ * Covers the variants of swords. ++ */ ++ public static final MaterialSetTag SWORDS = new MaterialSetTag(keyFor("swords")) ++ .endsWith("_SWORD") ++ .ensureSize("SWORDS", 6); ++ ++ /** ++ * Covers the variants of shovels. ++ */ ++ public static final MaterialSetTag SHOVELS = new MaterialSetTag(keyFor("shovels")) ++ .endsWith("_SHOVEL") ++ .ensureSize("SHOVELS", 6); ++ ++ /** ++ * Covers the variants of pickaxes. ++ */ ++ public static final MaterialSetTag PICKAXES = new MaterialSetTag(keyFor("pickaxes")) ++ .endsWith("_PICKAXE") ++ .ensureSize("PICKAXES", 6); ++ ++ /** ++ * Covers the variants of axes. ++ */ ++ public static final MaterialSetTag AXES = new MaterialSetTag(keyFor("axes")) ++ .endsWith("_AXE") ++ .ensureSize("AXES", 6); ++ ++ /** ++ * Covers the variants of hoes. ++ */ ++ public static final MaterialSetTag HOES = new MaterialSetTag(keyFor("hoes")) ++ .endsWith("_HOE") ++ .ensureSize("HOES", 6); ++ ++ /** ++ * Covers the variants of helmets. ++ */ ++ public static final MaterialSetTag HELMETS = new MaterialSetTag(keyFor("helmets")) ++ .endsWith("_HELMET") ++ .ensureSize("HELMETS", 7); ++ ++ /** ++ * Covers the variants of items that can be equipped in the helmet slot. ++ */ ++ public static final MaterialSetTag HEAD_EQUIPPABLE = new MaterialSetTag(keyFor("head_equippable")) ++ .endsWith("_HELMET") ++ .add(SKULLS) ++ .add(Material.CARVED_PUMPKIN) ++ .ensureSize("HEAD_EQUIPPABLE", 20); ++ ++ /** ++ * Covers the variants of chestplate. ++ */ ++ public static final MaterialSetTag CHESTPLATES = new MaterialSetTag(keyFor("chestplates")) ++ .endsWith("_CHESTPLATE") ++ .ensureSize("CHESTPLATES", 6); ++ ++ /** ++ * Covers the variants of items that can be equipped in the chest slot. ++ */ ++ public static final MaterialSetTag CHEST_EQUIPPABLE = new MaterialSetTag(keyFor("chest_equippable")) ++ .endsWith("_CHESTPLATE") ++ .add(Material.ELYTRA) ++ .ensureSize("CHEST_EQUIPPABLE", 7); ++ ++ /** ++ * Covers the variants of leggings. ++ */ ++ public static final MaterialSetTag LEGGINGS = new MaterialSetTag(keyFor("leggings")) ++ .endsWith("_LEGGINGS") ++ .ensureSize("LEGGINGS", 6); ++ ++ /** ++ * Covers the variants of boots. ++ */ ++ public static final MaterialSetTag BOOTS = new MaterialSetTag(keyFor("boots")) ++ .endsWith("_BOOTS") ++ .ensureSize("BOOTS", 6); ++ ++ /** ++ * Covers the variants of bows. ++ */ ++ public static final MaterialSetTag BOWS = new MaterialSetTag(keyFor("bows")) ++ .add(Material.BOW) ++ .add(Material.CROSSBOW) ++ .ensureSize("BOWS", 2); ++ ++ /** ++ * Covers the variants of player-throwable projectiles (not requiring a bow or any other "assistance"). ++ */ ++ public static final MaterialSetTag THROWABLE_PROJECTILES = new MaterialSetTag(keyFor("throwable_projectiles")) ++ .add(Material.EGG, Material.SNOWBALL, Material.SPLASH_POTION, Material.TRIDENT, Material.ENDER_PEARL, Material.EXPERIENCE_BOTTLE, Material.FIREWORK_ROCKET); ++ ++ /** ++ * Covers materials that can be colored, such as wool, shulker boxes, stained glass etc. ++ */ ++ @SuppressWarnings("unchecked") ++ public static final MaterialSetTag COLORABLE = new MaterialSetTag(keyFor("colorable")) ++ .add(Tag.WOOL, Tag.CARPETS).add(SHULKER_BOXES, STAINED_GLASS, STAINED_GLASS_PANES, CONCRETES, BEDS); ++ //.ensureSize("COLORABLE", 81); unit test don't have the vanilla item tags, so counts don't line up for real ++ ++ /** ++ * Covers the variants of coral. ++ */ ++ public static final MaterialSetTag CORAL = new MaterialSetTag(keyFor("coral")) ++ .endsWith("_CORAL") ++ .ensureSize("CORAL", 10); ++ ++ /** ++ * Covers the variants of coral fans. ++ */ ++ public static final MaterialSetTag CORAL_FANS = new MaterialSetTag(keyFor("coral_fans")) ++ .endsWith("_CORAL_FAN") ++ .endsWith("_CORAL_WALL_FAN") ++ .ensureSize("CORAL_FANS", 20); ++ ++ /** ++ * Covers the variants of coral blocks. ++ */ ++ public static final MaterialSetTag CORAL_BLOCKS = new MaterialSetTag(keyFor("coral_blocks")) ++ .endsWith("_CORAL_BLOCK") ++ .ensureSize("CORAL_BLOCKS", 10); ++ ++ /** ++ * Covers all items that can be enchanted from the enchantment table or anvil. ++ */ ++ public static final MaterialSetTag ENCHANTABLE = new MaterialSetTag(keyFor("enchantable")) ++ .add(PICKAXES, SWORDS, SHOVELS, AXES, HOES, HELMETS, CHEST_EQUIPPABLE, LEGGINGS, BOOTS, BOWS) ++ .add(Material.TRIDENT, Material.SHIELD, Material.FISHING_ROD, Material.SHEARS, Material.FLINT_AND_STEEL, Material.CARROT_ON_A_STICK, Material.WARPED_FUNGUS_ON_A_STICK) ++ .ensureSize("ENCHANTABLE", 65); ++} +diff --git a/src/main/java/io/papermc/paper/tag/BaseTag.java b/src/main/java/io/papermc/paper/tag/BaseTag.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4b8552e4e4c07b197fa9431fa911535b0222561e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/tag/BaseTag.java +@@ -0,0 +1,160 @@ ++package io.papermc.paper.tag; ++ ++import com.google.common.collect.Lists; ++import org.bukkit.Keyed; ++import org.bukkit.NamespacedKey; ++import org.bukkit.Tag; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.Collection; ++import java.util.EnumSet; ++import java.util.HashSet; ++import java.util.List; ++import java.util.Set; ++import java.util.function.Predicate; ++import java.util.stream.Collectors; ++ ++public abstract class BaseTag> implements Tag { ++ ++ protected final NamespacedKey key; ++ protected final Set tagged; ++ private final List> globalPredicates; ++ ++ public BaseTag(@NotNull Class clazz, @NotNull NamespacedKey key, @NotNull Predicate filter) { ++ this(clazz, key); ++ add(filter); ++ } ++ ++ public BaseTag(@NotNull Class clazz, @NotNull NamespacedKey key, @NotNull T...values) { ++ this(clazz, key, Lists.newArrayList(values)); ++ } ++ ++ public BaseTag(@NotNull Class clazz, @NotNull NamespacedKey key, @NotNull Collection values) { ++ this(clazz, key, values, o -> true); ++ } ++ ++ public BaseTag(@NotNull Class clazz, @NotNull NamespacedKey key, @NotNull Collection values, @NotNull Predicate... globalPredicates) { ++ this.key = key != null ? key : NamespacedKey.randomKey(); ++ this.tagged = clazz.isEnum() ? createEnumSet(clazz) : new HashSet<>(); ++ this.tagged.addAll(values); ++ this.globalPredicates = Lists.newArrayList(globalPredicates); ++ } ++ ++ private Set createEnumSet(Class enumClass) { ++ assert enumClass.isEnum(); ++ return (Set) EnumSet.noneOf((Class) enumClass); ++ } ++ ++ @NotNull ++ @Override ++ public NamespacedKey getKey() { ++ return key; ++ } ++ ++ @NotNull ++ @Override ++ public Set getValues() { ++ return tagged; ++ } ++ ++ @Override ++ public boolean isTagged(@NotNull T item) { ++ return tagged.contains(item); ++ } ++ ++ @NotNull ++ public C add(@NotNull Tag...tags) { ++ for (Tag tag : tags) { ++ add(tag.getValues()); ++ } ++ return (C) this; ++ } ++ ++ @NotNull ++ public C add(@NotNull T...values) { ++ this.tagged.addAll(Lists.newArrayList(values)); ++ return (C) this; ++ } ++ ++ @NotNull ++ public C add(@NotNull Collection collection) { ++ this.tagged.addAll(collection); ++ return (C) this; ++ } ++ ++ @NotNull ++ public C add(@NotNull Predicate filter) { ++ return add(getAllPossibleValues().stream().filter(globalPredicates.stream().reduce(Predicate::or).orElse(t -> true)).filter(filter).collect(Collectors.toSet())); ++ } ++ ++ @NotNull ++ public C contains(@NotNull String with) { ++ return add(value -> getName(value).contains(with)); ++ } ++ ++ @NotNull ++ public C endsWith(@NotNull String with) { ++ return add(value -> getName(value).endsWith(with)); ++ } ++ ++ @NotNull ++ public C startsWith(@NotNull String with) { ++ return add(value -> getName(value).startsWith(with)); ++ } ++ ++ @NotNull ++ public C not(@NotNull Tag...tags) { ++ for (Tag tag : tags) { ++ not(tag.getValues()); ++ } ++ return (C) this; ++ } ++ ++ @NotNull ++ public C not(@NotNull T...values) { ++ this.tagged.removeAll(Lists.newArrayList(values)); ++ return (C) this; ++ } ++ ++ @NotNull ++ public C not(@NotNull Collection values) { ++ this.tagged.removeAll(values); ++ return (C) this; ++ } ++ ++ @NotNull ++ public C not(@NotNull Predicate filter) { ++ not(getAllPossibleValues().stream().filter(globalPredicates.stream().reduce(Predicate::or).orElse(t -> true)).filter(filter).collect(Collectors.toSet())); ++ return (C) this; ++ } ++ ++ @NotNull ++ public C notContains(@NotNull String with) { ++ return not(value -> getName(value).contains(with)); ++ } ++ ++ @NotNull ++ public C notEndsWith(@NotNull String with) { ++ return not(value -> getName(value).endsWith(with)); ++ } ++ ++ @NotNull ++ public C notStartsWith(@NotNull String with) { ++ return not(value -> getName(value).startsWith(with)); ++ } ++ ++ @NotNull ++ public C ensureSize(@NotNull String label, int size) { ++ long actual = this.tagged.stream().filter(globalPredicates.stream().reduce(Predicate::or).orElse(t -> true)).count(); ++ if (size != actual) { ++ throw new IllegalStateException(key.toString() + ": " + label + " - Expected " + size + " values, got " + actual); ++ } ++ return (C) this; ++ } ++ ++ @NotNull ++ protected abstract Set getAllPossibleValues(); ++ ++ @NotNull ++ protected abstract String getName(@NotNull T value); ++} +diff --git a/src/main/java/io/papermc/paper/tag/EntitySetTag.java b/src/main/java/io/papermc/paper/tag/EntitySetTag.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c89c4619aaf388197834d98eb95af2f1e93db871 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/tag/EntitySetTag.java +@@ -0,0 +1,42 @@ ++package io.papermc.paper.tag; ++ ++import org.bukkit.NamespacedKey; ++import org.bukkit.entity.EntityType; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.Collection; ++import java.util.Set; ++import java.util.function.Predicate; ++import java.util.stream.Collectors; ++import java.util.stream.Stream; ++ ++public class EntitySetTag extends BaseTag { ++ ++ public EntitySetTag(@NotNull NamespacedKey key, @NotNull Predicate filter) { ++ super(EntityType.class, key, filter); ++ } ++ ++ public EntitySetTag(@NotNull NamespacedKey key, @NotNull EntityType... values) { ++ super(EntityType.class, key, values); ++ } ++ ++ public EntitySetTag(@NotNull NamespacedKey key, @NotNull Collection values) { ++ super(EntityType.class, key, values); ++ } ++ ++ public EntitySetTag(@NotNull NamespacedKey key, @NotNull Collection values, @NotNull Predicate... globalPredicates) { ++ super(EntityType.class, key, values, globalPredicates); ++ } ++ ++ @NotNull ++ @Override ++ protected Set getAllPossibleValues() { ++ return Stream.of(EntityType.values()).collect(Collectors.toSet()); ++ } ++ ++ @NotNull ++ @Override ++ protected String getName(@NotNull EntityType value) { ++ return value.name(); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/tag/EntityTags.java b/src/main/java/io/papermc/paper/tag/EntityTags.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9266c9d77e2eef7cd717dc729834a190f1fc7c1d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/tag/EntityTags.java +@@ -0,0 +1,50 @@ ++package io.papermc.paper.tag; ++ ++import org.bukkit.NamespacedKey; ++ ++import static org.bukkit.entity.EntityType.*; ++ ++public class EntityTags { ++ ++ private static NamespacedKey keyFor(String key) { ++ //noinspection deprecation ++ return new NamespacedKey("paper", key + "_settag"); ++ } ++ ++ /** ++ * Covers undead mobs ++ * @see https://minecraft.gamepedia.com/Mob#Undead_mobs ++ */ ++ public static final EntitySetTag UNDEADS = new EntitySetTag(keyFor("undeads")) ++ .add(DROWNED, HUSK, PHANTOM, SKELETON, SKELETON_HORSE, STRAY, WITHER, WITHER_SKELETON, ZOGLIN, ZOMBIE, ZOMBIE_HORSE, ZOMBIE_VILLAGER, ZOMBIFIED_PIGLIN) ++ .ensureSize("UNDEADS", 13); ++ ++ /** ++ * Covers all horses ++ */ ++ public static final EntitySetTag HORSES = new EntitySetTag(keyFor("horses")) ++ .contains("HORSE") ++ .ensureSize("HORSES", 3); ++ ++ /** ++ * Covers all minecarts ++ */ ++ public static final EntitySetTag MINECARTS = new EntitySetTag(keyFor("minecarts")) ++ .contains("MINECART") ++ .ensureSize("MINECARTS", 7); ++ ++ /** ++ * Covers mobs that split into smaller mobs ++ */ ++ public static final EntitySetTag SPLITTING_MOBS = new EntitySetTag(keyFor("splitting_mobs")) ++ .add(SLIME, MAGMA_CUBE) ++ .ensureSize("SLIMES", 2); ++ ++ /** ++ * Covers all water based mobs ++ * @see https://minecraft.gamepedia.com/Mob#Water-based_mobs ++ */ ++ public static final EntitySetTag WATER_BASED = new EntitySetTag(keyFor("water_based")) ++ .add(DOLPHIN, SQUID, GUARDIAN, ELDER_GUARDIAN, TURTLE, COD, SALMON, PUFFERFISH, TROPICAL_FISH) ++ .ensureSize("WATER_BASED", 9); ++} +diff --git a/src/main/java/org/bukkit/Tag.java b/src/main/java/org/bukkit/Tag.java +index aacbfadc91f580cc667603c8165eacbadee38cca..3c2a6a2167eab43097f5d6ccf1550e12795fc0b6 100644 +--- a/src/main/java/org/bukkit/Tag.java ++++ b/src/main/java/org/bukkit/Tag.java +@@ -10,6 +10,10 @@ import org.jetbrains.annotations.NotNull; + * Note that whilst all tags defined within this interface must be present in + * implementations, their existence is not guaranteed across future versions. + * ++ *

    Custom tags defined by Paper are not present (as constants) in this class. ++ * To access them please refer to {@link com.destroystokyo.paper.MaterialTags} ++ * and {@link io.papermc.paper.tag.EntityTags}.

    ++ * + * @param the type of things grouped by this tag + */ + public interface Tag extends Keyed { +diff --git a/src/test/java/com/destroystokyo/paper/MaterialTagsTest.java b/src/test/java/com/destroystokyo/paper/MaterialTagsTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..328c51471dc12e81c1a1b643455337b3fef4d14a +--- /dev/null ++++ b/src/test/java/com/destroystokyo/paper/MaterialTagsTest.java +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ */ ++ ++package com.destroystokyo.paper; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.TestServer; ++import org.junit.Test; ++ ++import java.util.logging.Level; ++ ++public class MaterialTagsTest { ++ @Test ++ public void testInitialize() { ++ try { ++ TestServer.getInstance(); ++ MaterialTags.SHULKER_BOXES.getValues(); ++ assert true; ++ } catch (Throwable e) { ++ Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e); ++ assert false; ++ } ++ } ++} +diff --git a/src/test/java/io/papermc/paper/EntityTagsTest.java b/src/test/java/io/papermc/paper/EntityTagsTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..06bb9d1180361d3d00c699796bbacbce5bef2177 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/EntityTagsTest.java +@@ -0,0 +1,24 @@ ++package io.papermc.paper; ++ ++import com.destroystokyo.paper.MaterialTags; ++import io.papermc.paper.tag.EntityTags; ++import org.bukkit.Bukkit; ++import org.bukkit.TestServer; ++import org.junit.Test; ++ ++import java.util.logging.Level; ++ ++public class EntityTagsTest { ++ ++ @Test ++ public void testInitialize() { ++ try { ++ TestServer.getInstance(); ++ EntityTags.HORSES.getValues(); ++ assert true; ++ } catch (Throwable e) { ++ Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e); ++ assert false; ++ } ++ } ++} +diff --git a/src/test/java/org/bukkit/TestServer.java b/src/test/java/org/bukkit/TestServer.java +index 61993528e6975c38d82213e9b5caf996fe777328..5f9d348241210689eaf41a39ace5948e7a237b12 100644 +--- a/src/test/java/org/bukkit/TestServer.java ++++ b/src/test/java/org/bukkit/TestServer.java +@@ -29,6 +29,16 @@ public final class TestServer implements InvocationHandler { + } + } + ); ++ // Paper start ++ methodMap.put( ++ Server.class.getMethod("getTag", String.class, NamespacedKey.class, Class.class), ++ new MethodHandler() { ++ public Object handle(TestServer server, Object[] args) { ++ return new com.destroystokyo.paper.MaterialSetTag(); ++ } ++ } ++ ); ++ // Paper end + methodMap.put( + Server.class.getMethod("getPluginManager"), + new MethodHandler() { diff --git a/patches/api-unmapped/0155-Allow-setting-the-vex-s-summoner.patch b/patches/api-unmapped/0155-Allow-setting-the-vex-s-summoner.patch new file mode 100644 index 0000000000..68b33503be --- /dev/null +++ b/patches/api-unmapped/0155-Allow-setting-the-vex-s-summoner.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 6 Oct 2018 21:47:09 -0500 +Subject: [PATCH] Allow setting the vex's summoner + + +diff --git a/src/main/java/org/bukkit/entity/Vex.java b/src/main/java/org/bukkit/entity/Vex.java +index 6b61c4ab773c731fe5ae9577fd13e44707be9787..c34a3ea7b4d16817b4bee25d5c69787e22ec44d8 100644 +--- a/src/main/java/org/bukkit/entity/Vex.java ++++ b/src/main/java/org/bukkit/entity/Vex.java +@@ -1,5 +1,7 @@ + package org.bukkit.entity; + ++import org.jetbrains.annotations.Nullable; ++ + /** + * Represents a Vex. + */ +@@ -22,4 +24,21 @@ public interface Vex extends Monster { + * @param charging new state + */ + void setCharging(boolean charging); ++ ++ // Paper start ++ /** ++ * Get the Mob that summoned this vex ++ * ++ * @return Mob that summoned this vex ++ */ ++ @Nullable ++ Mob getSummoner(); ++ ++ /** ++ * Set the summoner of this vex ++ * ++ * @param summoner New summoner ++ */ ++ void setSummoner(@Nullable Mob summoner); ++ // Paper end + } diff --git a/patches/api-unmapped/0156-Add-LivingEntity-getTargetEntity.patch b/patches/api-unmapped/0156-Add-LivingEntity-getTargetEntity.patch new file mode 100644 index 0000000000..cc02ae973f --- /dev/null +++ b/patches/api-unmapped/0156-Add-LivingEntity-getTargetEntity.patch @@ -0,0 +1,105 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 22 Sep 2018 00:32:53 -0500 +Subject: [PATCH] Add LivingEntity#getTargetEntity + + +diff --git a/src/main/java/com/destroystokyo/paper/entity/TargetEntityInfo.java b/src/main/java/com/destroystokyo/paper/entity/TargetEntityInfo.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f52644fab1522bdf83ff4f489e9805b274421094 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/TargetEntityInfo.java +@@ -0,0 +1,38 @@ ++package com.destroystokyo.paper.entity; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.util.Vector; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents information about a targeted entity ++ */ ++public class TargetEntityInfo { ++ private final Entity entity; ++ private final Vector hitVec; ++ ++ public TargetEntityInfo(@NotNull Entity entity, @NotNull Vector hitVec) { ++ this.entity = entity; ++ this.hitVec = hitVec; ++ } ++ ++ /** ++ * Get the entity that is targeted ++ * ++ * @return Targeted entity ++ */ ++ @NotNull ++ public Entity getEntity() { ++ return entity; ++ } ++ ++ /** ++ * Get the position the entity is targeted at ++ * ++ * @return Targeted position ++ */ ++ @NotNull ++ public Vector getHitVector() { ++ return hitVec; ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 8fe7ccf12339355554835542cc1068d9f6c3a435..561db9d594633e3909fd6d69dad1dc2976928d58 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -151,6 +151,50 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + */ + @Nullable + public com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode); ++ ++ /** ++ * Gets information about the entity being targeted ++ * ++ * @param maxDistance this is the maximum distance to scan ++ * @return entity being targeted, or null if no entity is targeted ++ */ ++ @Nullable ++ public default Entity getTargetEntity(int maxDistance) { ++ return getTargetEntity(maxDistance, false); ++ } ++ ++ /** ++ * Gets information about the entity being targeted ++ * ++ * @param maxDistance this is the maximum distance to scan ++ * @param ignoreBlocks true to scan through blocks ++ * @return entity being targeted, or null if no entity is targeted ++ */ ++ @Nullable ++ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks); ++ ++ /** ++ * Gets information about the entity being targeted ++ * ++ * @param maxDistance this is the maximum distance to scan ++ * @return TargetEntityInfo about the entity being targeted, ++ * or null if no entity is targeted ++ */ ++ @Nullable ++ public default com.destroystokyo.paper.entity.TargetEntityInfo getTargetEntityInfo(int maxDistance) { ++ return getTargetEntityInfo(maxDistance, false); ++ } ++ ++ /** ++ * Gets information about the entity being targeted ++ * ++ * @param maxDistance this is the maximum distance to scan ++ * @param ignoreBlocks true to scan through blocks ++ * @return TargetEntityInfo about the entity being targeted, ++ * or null if no entity is targeted ++ */ ++ @Nullable ++ public com.destroystokyo.paper.entity.TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks); + // Paper end + + /** diff --git a/patches/api-unmapped/0157-Add-sun-related-API.patch b/patches/api-unmapped/0157-Add-sun-related-API.patch new file mode 100644 index 0000000000..85efb56e43 --- /dev/null +++ b/patches/api-unmapped/0157-Add-sun-related-API.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 7 Oct 2018 00:54:15 -0500 +Subject: [PATCH] Add sun related API + + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index ec8e3a949a869545a8e0cb8c2f59f1a6dd8f5485..ce1a3de1d03e10b18c0098ee2778361cc9a4cb01 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -1812,6 +1812,16 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + */ + public void setFullTime(long time); + ++ // Paper start ++ ++ /** ++ * Check if it is currently daytime in this world ++ * ++ * @return True if it is daytime ++ */ ++ public boolean isDayTime(); ++ // Paper end ++ + /** + * Gets the full in-game time on this world since the world generation + * +diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java +index b132287817d35579ca5128a1ed5c242bf229771a..d726453c041a980576312b6bee96a07837f37974 100644 +--- a/src/main/java/org/bukkit/entity/Mob.java ++++ b/src/main/java/org/bukkit/entity/Mob.java +@@ -16,6 +16,13 @@ public interface Mob extends LivingEntity, Lootable { + */ + @NotNull + com.destroystokyo.paper.entity.Pathfinder getPathfinder(); ++ ++ /** ++ * Check if this mob is exposed to daylight ++ * ++ * @return True if mob is exposed to daylight ++ */ ++ boolean isInDaylight(); + // Paper end + + /** diff --git a/patches/api-unmapped/0158-Here-s-Johnny.patch b/patches/api-unmapped/0158-Here-s-Johnny.patch new file mode 100644 index 0000000000..faaadfb5db --- /dev/null +++ b/patches/api-unmapped/0158-Here-s-Johnny.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 12 Oct 2018 01:37:16 -0500 +Subject: [PATCH] Here's Johnny! + + +diff --git a/src/main/java/org/bukkit/entity/Vindicator.java b/src/main/java/org/bukkit/entity/Vindicator.java +index b8ea68a8f420c1ba99c0621a15e654d3ee48c8d6..c5d9e76a6a4125eb0409967a57e3836b8f2d24a0 100644 +--- a/src/main/java/org/bukkit/entity/Vindicator.java ++++ b/src/main/java/org/bukkit/entity/Vindicator.java +@@ -3,4 +3,30 @@ package org.bukkit.entity; + /** + * Represents a Vindicator. + */ +-public interface Vindicator extends Illager { } ++public interface Vindicator extends Illager { ++ // Paper start ++ /** ++ * Check if this Vindicator is set to Johnny mode. ++ *

    ++ * When in Johnny mode the Vindicator will be hostile to any kind of mob, except ++ * for evokers, ghasts, illusioners and other vindicators. It will even be hostile ++ * to vexes. All mobs, except for endermites, phantoms, guardians, slimes and ++ * magma cubes, will try to attack the vindicator in return. ++ * ++ * @return True if in Johnny mode ++ */ ++ boolean isJohnny(); ++ ++ /** ++ * Set this Vindicator's Johnny mode. ++ *

    ++ * When in Johnny mode the Vindicator will be hostile to any kind of mob, except ++ * for evokers, ghasts, illusioners and other vindicators. It will even be hostile ++ * to vexes. All mobs, except for endermites, phantoms, guardians, slimes and ++ * magma cubes, will try to attack the vindicator in return. ++ * ++ * @param johnny True to enable Johnny mode ++ */ ++ void setJohnny(boolean johnny); ++ // Paper end ++} diff --git a/patches/api-unmapped/0159-Turtle-API.patch b/patches/api-unmapped/0159-Turtle-API.patch new file mode 100644 index 0000000000..06abb703f4 --- /dev/null +++ b/patches/api-unmapped/0159-Turtle-API.patch @@ -0,0 +1,283 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 28 Sep 2018 17:08:09 -0500 +Subject: [PATCH] Turtle API + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/TurtleGoHomeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/TurtleGoHomeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..021356d151ed638068e3e89b8cc77b3795883233 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/TurtleGoHomeEvent.java +@@ -0,0 +1,49 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Turtle; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when a Turtle decides to go home ++ */ ++public class TurtleGoHomeEvent extends EntityEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled = false; ++ ++ public TurtleGoHomeEvent(@NotNull Turtle turtle) { ++ super(turtle); ++ } ++ ++ /** ++ * The turtle going home ++ * ++ * @return The turtle ++ */ ++ @NotNull ++ public Turtle getEntity() { ++ return (Turtle) entity; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a315c5185cd465dcf63c0ababef195da76dfc786 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java +@@ -0,0 +1,87 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.Turtle; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when a Turtle lays eggs ++ */ ++public class TurtleLayEggEvent extends EntityEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled = false; ++ @NotNull ++ private final Location location; ++ private int eggCount; ++ ++ public TurtleLayEggEvent(@NotNull Turtle turtle, @NotNull Location location, int eggCount) { ++ super(turtle); ++ this.location = location; ++ this.eggCount = eggCount; ++ } ++ ++ /** ++ * The turtle laying the eggs ++ * ++ * @return The turtle ++ */ ++ @NotNull ++ public Turtle getEntity() { ++ return (Turtle) entity; ++ } ++ ++ /** ++ * Get the location where the eggs are being laid ++ * ++ * @return Location of eggs ++ */ ++ @NotNull ++ public Location getLocation() { ++ return location; ++ } ++ ++ /** ++ * Get the number of eggs being laid ++ * ++ * @return Number of eggs ++ */ ++ public int getEggCount() { ++ return eggCount; ++ } ++ ++ /** ++ * Set the number of eggs being laid ++ * ++ * @param eggCount Number of eggs ++ */ ++ public void setEggCount(int eggCount) { ++ if (eggCount < 1) { ++ cancelled = true; ++ return; ++ } ++ eggCount = Math.min(eggCount, 4); ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..abeb24fccda2acfdb0dfdadacb8fe688bd97cf78 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java +@@ -0,0 +1,62 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.Turtle; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when a Turtle starts digging to lay eggs ++ */ ++public class TurtleStartDiggingEvent extends EntityEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled = false; ++ @NotNull private final Location location; ++ ++ public TurtleStartDiggingEvent(@NotNull Turtle turtle, @NotNull Location location) { ++ super(turtle); ++ this.location = location; ++ } ++ ++ /** ++ * The turtle digging ++ * ++ * @return The turtle ++ */ ++ @NotNull ++ public Turtle getEntity() { ++ return (Turtle) entity; ++ } ++ ++ /** ++ * Get the location where the turtle is digging ++ * ++ * @return Location where digging ++ */ ++ @NotNull ++ public Location getLocation() { ++ return location; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/Turtle.java b/src/main/java/org/bukkit/entity/Turtle.java +index 0a4cd29930c2f1c28f5a3e6884c7dec45b5cac11..5375ea14097f4f10b2294488b92924a35a72d4d7 100644 +--- a/src/main/java/org/bukkit/entity/Turtle.java ++++ b/src/main/java/org/bukkit/entity/Turtle.java +@@ -1,6 +1,55 @@ + package org.bukkit.entity; + ++import org.bukkit.Location; ++import org.jetbrains.annotations.NotNull; ++ + /** + * Represents a turtle. + */ +-public interface Turtle extends Animals { } ++public interface Turtle extends Animals { ++ // Paper start ++ ++ /** ++ * Get the turtle's home location ++ * ++ * @return Home location ++ */ ++ @NotNull ++ Location getHome(); ++ ++ /** ++ * Set the turtle's home location ++ * ++ * @param location Home location ++ */ ++ void setHome(@NotNull Location location); ++ ++ /** ++ * Check if turtle is currently pathfinding to it's home ++ * ++ * @return True if going home ++ */ ++ boolean isGoingHome(); ++ ++ /** ++ * Get if turtle is digging to lay eggs ++ * ++ * @return True if digging ++ */ ++ boolean isDigging(); ++ ++ /** ++ * Get if turtle is carrying egg ++ * ++ * @return True if carrying egg ++ */ ++ boolean hasEgg(); ++ ++ /** ++ * Set if turtle is carrying egg ++ * ++ * @param hasEgg True if carrying egg ++ */ ++ void setHasEgg(boolean hasEgg); ++ // Paper end ++} diff --git a/patches/api-unmapped/0160-Add-spectator-target-events.patch b/patches/api-unmapped/0160-Add-spectator-target-events.patch new file mode 100644 index 0000000000..c5d4b7c4db --- /dev/null +++ b/patches/api-unmapped/0160-Add-spectator-target-events.patch @@ -0,0 +1,141 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Caleb Bassham +Date: Fri, 28 Sep 2018 02:30:56 -0500 +Subject: [PATCH] Add spectator target events + +- PlayerStartSpectatingEntityEvent +- PlayerStopSpectatingEntityEvent + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerStartSpectatingEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerStartSpectatingEntityEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b8ec7ef2d4ef0683cc0d6ca86885dd9a01f47e16 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerStartSpectatingEntityEvent.java +@@ -0,0 +1,67 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Triggered when a player starts spectating an entity in spectator mode. ++ */ ++public class PlayerStartSpectatingEntityEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ @NotNull private final Entity currentSpectatorTarget; ++ @NotNull private final Entity newSpectatorTarget; ++ ++ public PlayerStartSpectatingEntityEvent(@NotNull Player player, @NotNull Entity currentSpectatorTarget, @NotNull Entity newSpectatorTarget) { ++ super(player); ++ this.currentSpectatorTarget = currentSpectatorTarget; ++ this.newSpectatorTarget = newSpectatorTarget; ++ } ++ ++ /** ++ * Gets the entity that the player is currently spectating or themselves if they weren't spectating anything ++ * ++ * @return The entity the player is currently spectating (before they start spectating the new target). ++ */ ++ @NotNull ++ public Entity getCurrentSpectatorTarget() { ++ return currentSpectatorTarget; ++ } ++ ++ /** ++ * Gets the new entity that the player will now be spectating ++ * ++ * @return The entity the player is now going to be spectating. ++ */ ++ @NotNull ++ public Entity getNewSpectatorTarget() { ++ return newSpectatorTarget; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} ++ +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerStopSpectatingEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerStopSpectatingEntityEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..693d119ab920a1bd0d1b5a0feb092631715ec0ad +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerStopSpectatingEntityEvent.java +@@ -0,0 +1,54 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Triggered when a player stops spectating an entity in spectator mode. ++ */ ++public class PlayerStopSpectatingEntityEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ @NotNull private final Entity spectatorTarget; ++ ++ public PlayerStopSpectatingEntityEvent(@NotNull Player player, @NotNull Entity spectatorTarget) { ++ super(player); ++ this.spectatorTarget = spectatorTarget; ++ } ++ ++ /** ++ * Gets the entity that the player is spectating ++ * ++ * @return The entity the player is currently spectating (before they will stop). ++ */ ++ @NotNull ++ public Entity getSpectatorTarget() { ++ return spectatorTarget; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0161-Add-more-Witch-API.patch b/patches/api-unmapped/0161-Add-more-Witch-API.patch new file mode 100644 index 0000000000..8fa1dd1e47 --- /dev/null +++ b/patches/api-unmapped/0161-Add-more-Witch-API.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 12 Oct 2018 03:47:26 -0500 +Subject: [PATCH] Add more Witch API + + +diff --git a/src/main/java/org/bukkit/entity/Witch.java b/src/main/java/org/bukkit/entity/Witch.java +index aa88aede6c4e66a608a63d07bc66d60357b0bee9..b7f9db08fb2e4633e1dfad5c752451f6ac23d437 100644 +--- a/src/main/java/org/bukkit/entity/Witch.java ++++ b/src/main/java/org/bukkit/entity/Witch.java +@@ -2,8 +2,53 @@ package org.bukkit.entity; + + import com.destroystokyo.paper.entity.RangedEntity; + ++// Paper start ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.Nullable; ++// Paper end ++ + /** + * Represents a Witch + */ + public interface Witch extends Raider, RangedEntity { // Paper ++ // Paper start ++ /** ++ * Check if Witch is drinking a potion ++ * ++ * @return True if drinking a potion ++ */ ++ boolean isDrinkingPotion(); ++ ++ /** ++ * Get time remaining (in ticks) the Witch is drinking a potion ++ * ++ * @return Time remaining (in ticks) ++ */ ++ int getPotionUseTimeLeft(); ++ ++ /** ++ * Set time remaining (in ticks) that the Witch is drinking a potion. ++ *

    ++ * This only has an effect while the Witch is drinking a potion. ++ * ++ * @param ticks Time in ticks remaining ++ * @see #isDrinkingPotion ++ */ ++ void setPotionUseTimeLeft(int ticks); ++ ++ /** ++ * Get the potion the Witch is drinking ++ * ++ * @return The potion the witch is drinking ++ */ ++ @Nullable ++ ItemStack getDrinkingPotion(); ++ ++ /** ++ * Set the potion the Witch should drink ++ * ++ * @param potion Potion to drink ++ */ ++ void setDrinkingPotion(@Nullable ItemStack potion); ++ // Paper end + } diff --git a/patches/api-unmapped/0162-Make-the-default-permission-message-configurable.patch b/patches/api-unmapped/0162-Make-the-default-permission-message-configurable.patch new file mode 100644 index 0000000000..06ba70ae7d --- /dev/null +++ b/patches/api-unmapped/0162-Make-the-default-permission-message-configurable.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 18 Nov 2018 19:44:54 +0000 +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 6b619b85fee86ccc599cb46d789e39b81af3201c..dcaefdaf5a0de8486f59115c8c4d4c211b7d64cd 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1793,6 +1793,15 @@ public final class Bukkit { + return server.suggestPlayerNamesWhenNullTabCompletions(); + } + ++ /** ++ * ++ * @return the default no permission message used on the server ++ */ ++ @NotNull ++ public static String getPermissionMessage() { ++ return server.getPermissionMessage(); ++ } ++ + /** + * Creates a PlayerProfile for the specified uuid, with name as null + * @param uuid UUID to create profile for +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index c642fe9cfae6407404f5cf17264f42ef83a01280..9b8e6b7bbbed44e2659379c8046acaa35aaa8910 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1575,6 +1575,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + */ + boolean suggestPlayerNamesWhenNullTabCompletions(); + ++ /** ++ * ++ * @return the default no permission message used on the server ++ */ ++ @NotNull ++ String getPermissionMessage(); ++ + /** + * Creates a PlayerProfile for the specified uuid, with name as null + * @param uuid UUID to create profile for +diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java +index 7c80dc54776d0d66f7816b77136f6dbd9b801704..c10fc8d2386301bc2caddcdb1cd18566bcaa8689 100644 +--- a/src/main/java/org/bukkit/command/Command.java ++++ b/src/main/java/org/bukkit/command/Command.java +@@ -185,7 +185,7 @@ public abstract class Command { + } + + if (permissionMessage == null) { +- target.sendMessage(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is a mistake."); ++ target.sendMessage(Bukkit.getPermissionMessage()); // Paper + } else if (permissionMessage.length() != 0) { + for (String line : permissionMessage.replace("", permission).split("\n")) { + target.sendMessage(line); diff --git a/patches/api-unmapped/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch b/patches/api-unmapped/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch new file mode 100644 index 0000000000..a36772974a --- /dev/null +++ b/patches/api-unmapped/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 18 Nov 2018 15:53:43 +0000 +Subject: [PATCH] Support cancellation supression of EntityDismount/VehicleExit + events" + +Entities must be dismounted before teleportation in order to avoid +multiple issues in the server with regards to teleportation, shamefully, +too many plugins rely on the events firing, which means that not firing +these events caues more issues than it solves; + +In order to counteract this, Entity dismount/exit vehicle events have +been modified to supress cancellation (and has a method to allow plugins +to check if this has been set), noting that cancellation will be silently +surpressed given that plugins are not expecting this event to not be cancellable. + +This is a far from ideal scenario, however: given the current state of this +event and other alternatives causing issues elsewhere, I believe that +this is going to be the best soultion all around. + +Improvements/suggestions welcome! + +diff --git a/src/main/java/org/bukkit/event/vehicle/VehicleExitEvent.java b/src/main/java/org/bukkit/event/vehicle/VehicleExitEvent.java +index 963b9ead4ca0426b2e95c5641b0e89317c48853d..a976c32de6ad5e90b0a96a0f387136ab0f5eb52e 100644 +--- a/src/main/java/org/bukkit/event/vehicle/VehicleExitEvent.java ++++ b/src/main/java/org/bukkit/event/vehicle/VehicleExitEvent.java +@@ -13,10 +13,18 @@ public class VehicleExitEvent extends VehicleEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private final LivingEntity exited; ++ private final boolean isCancellable; // Paper + +- public VehicleExitEvent(@NotNull final Vehicle vehicle, @NotNull final LivingEntity exited) { ++ public VehicleExitEvent(@NotNull final Vehicle vehicle, @NotNull final LivingEntity exited, boolean isCancellable) { // Paper + super(vehicle); + this.exited = exited; ++ // Paper start ++ this.isCancellable = isCancellable; ++ } ++ ++ public VehicleExitEvent(@NotNull final Vehicle vehicle, @NotNull final LivingEntity exited) { ++ this(vehicle, exited, true); ++ // Paper end + } + + /** +@@ -36,9 +44,18 @@ public class VehicleExitEvent extends VehicleEvent implements Cancellable { + + @Override + public void setCancelled(boolean cancel) { ++ // Paper start ++ if (cancel && !isCancellable) { ++ return; ++ } + this.cancelled = cancel; + } + ++ public boolean isCancellable() { ++ return isCancellable; ++ // paper end ++ } ++ + @NotNull + @Override + public HandlerList getHandlers() { +diff --git a/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java b/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java +index 00d8ec81b4ae6ca5e438161ec9135e3c1edea6f4..a7632c8f5cb1bce4be0e456ec34f4a69c5ce80f3 100644 +--- a/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java ++++ b/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java +@@ -14,10 +14,19 @@ public class EntityDismountEvent extends EntityEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private final Entity dismounted; ++ private final boolean isCancellable; // Paper + + public EntityDismountEvent(@NotNull Entity what, @NotNull Entity dismounted) { +- super(what); ++ // Paper start ++ this(what, dismounted, true); ++ } ++ ++ ++ public EntityDismountEvent(@NotNull Entity what, @NotNull Entity dismounted, boolean isCancellable) { ++ // Paper end ++ super( what ); + this.dismounted = dismounted; ++ this.isCancellable = isCancellable; // Paper + } + + @NotNull +@@ -32,9 +41,18 @@ public class EntityDismountEvent extends EntityEvent implements Cancellable { + + @Override + public void setCancelled(boolean cancel) { ++ // Paper start ++ if (cancel && !isCancellable) { ++ return; ++ } + this.cancelled = cancel; + } + ++ public boolean isCancellable() { ++ return isCancellable; ++ // Paper end ++ } ++ + @NotNull + @Override + public HandlerList getHandlers() { diff --git a/patches/api-unmapped/0164-Add-more-Zombie-API.patch b/patches/api-unmapped/0164-Add-more-Zombie-API.patch new file mode 100644 index 0000000000..ec2c93dc46 --- /dev/null +++ b/patches/api-unmapped/0164-Add-more-Zombie-API.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 7 Oct 2018 04:29:51 -0500 +Subject: [PATCH] Add more Zombie API + + +diff --git a/src/main/java/org/bukkit/entity/Zombie.java b/src/main/java/org/bukkit/entity/Zombie.java +index a5b20b0454af5ea78e2bb7f16a56c38670c84efb..1217576e6f08abf0175ab800cfca058d5deda116 100644 +--- a/src/main/java/org/bukkit/entity/Zombie.java ++++ b/src/main/java/org/bukkit/entity/Zombie.java +@@ -90,4 +90,55 @@ public interface Zombie extends Monster, Ageable { + * @param time new conversion time + */ + void setConversionTime(int time); ++ // Paper start ++ /** ++ * Check if zombie is drowning ++ * ++ * @return True if zombie conversion process has begun ++ */ ++ boolean isDrowning(); ++ ++ /** ++ * Make zombie start drowning ++ * ++ * @param drownedConversionTime Amount of time until zombie converts from drowning ++ * ++ * @deprecated See {@link #setConversionTime(int)} ++ */ ++ @Deprecated ++ void startDrowning(int drownedConversionTime); ++ ++ /** ++ * Stop a zombie from starting the drowning conversion process ++ */ ++ void stopDrowning(); ++ ++ /** ++ * Set if zombie has its arms raised ++ * ++ * @param raised True to raise arms ++ */ ++ void setArmsRaised(boolean raised); ++ ++ /** ++ * Check if zombie has arms raised ++ * ++ * @return True if arms are raised ++ */ ++ boolean isArmsRaised(); ++ ++ /** ++ * Check if this zombie will burn in the sunlight ++ * ++ * @return True if zombie will burn in sunlight ++ */ ++ boolean shouldBurnInDay(); ++ ++ /** ++ * Set if this zombie should burn in the sunlight ++ * ++ * @param shouldBurnInDay True to burn in sunlight ++ */ ++ void setShouldBurnInDay(boolean shouldBurnInDay); ++ // Paper end + } diff --git a/patches/api-unmapped/0165-Change-the-reserved-channel-check-to-be-sensible.patch b/patches/api-unmapped/0165-Change-the-reserved-channel-check-to-be-sensible.patch new file mode 100644 index 0000000000..fa3de62864 --- /dev/null +++ b/patches/api-unmapped/0165-Change-the-reserved-channel-check-to-be-sensible.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DoNotSpamPls <7570108+DoNotSpamPls@users.noreply.github.com> +Date: Tue, 23 Oct 2018 19:32:55 +0300 +Subject: [PATCH] Change the reserved channel check to be sensible + + +diff --git a/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java b/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java +index 1d061412cdafa28c6940c7433747ab1dabe23de1..6fda7f3aa68e76af64362e9afed70fc6a5e92986 100644 +--- a/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java ++++ b/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java +@@ -172,7 +172,7 @@ public class StandardMessenger implements Messenger { + public boolean isReservedChannel(@NotNull String channel) { + channel = validateAndCorrectChannel(channel); + +- return channel.contains("minecraft") && !channel.equals("minecraft:brand"); ++ return channel.equals("minecraft:register") || channel.equals("minecraft:unregister"); // Paper + } + + @Override +diff --git a/src/test/java/org/bukkit/plugin/messaging/StandardMessengerTest.java b/src/test/java/org/bukkit/plugin/messaging/StandardMessengerTest.java +index dce3d619a6f1791197e44277c2dee9eaf19ff56f..7e2335ed8acc692af1e70eddcf97ee7a56e30f68 100644 +--- a/src/test/java/org/bukkit/plugin/messaging/StandardMessengerTest.java ++++ b/src/test/java/org/bukkit/plugin/messaging/StandardMessengerTest.java +@@ -25,8 +25,8 @@ public class StandardMessengerTest { + assertTrue(messenger.isReservedChannel("minecraft:register")); + assertFalse(messenger.isReservedChannel("test:register")); + assertTrue(messenger.isReservedChannel("minecraft:unregister")); +- assertFalse(messenger.isReservedChannel("test:nregister")); +- assertTrue(messenger.isReservedChannel("minecraft:something")); ++ assertFalse(messenger.isReservedChannel("test:unregister")); // Paper - fix typo ++ assertFalse(messenger.isReservedChannel("minecraft:something")); // Paper - now less strict + assertFalse(messenger.isReservedChannel("minecraft:brand")); + } + diff --git a/patches/api-unmapped/0166-Add-PlayerConnectionCloseEvent.patch b/patches/api-unmapped/0166-Add-PlayerConnectionCloseEvent.patch new file mode 100644 index 0000000000..f1a017f4fb --- /dev/null +++ b/patches/api-unmapped/0166-Add-PlayerConnectionCloseEvent.patch @@ -0,0 +1,136 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 7 Oct 2018 12:05:06 -0700 +Subject: [PATCH] Add PlayerConnectionCloseEvent + +This event is invoked when a player has disconnected. It is guaranteed that, +if the server is in online-mode, that the provided uuid and username have been +validated. + +The event is invoked for players who have not yet logged into the world, whereas +PlayerQuitEvent is only invoked on players who have logged into the world. + +The event is invoked for players who have already logged into the world, +although whether or not the player exists in the world at the time of +firing is undefined. (That is, whether the plugin can retrieve a Player object +using the event parameters is undefined). However, it is guaranteed that this +event is invoked AFTER PlayerQuitEvent, if the player has already logged into +the world. + +This event is guaranteed to never fire unless AsyncPlayerPreLoginEvent has +been called beforehand, and this event may not be called in parallel with +AsyncPlayerPreLoginEvent for the same connection. + +Cancelling the AsyncPlayerPreLoginEvent guarantees the corresponding +PlayerConnectionCloseEvent is never called. + +The event may be invoked asynchronously or synchronously. As it stands, +it is never invoked asynchronously. However, plugins should check +Event#isAsynchronous to be future-proof. + +On purpose, the deprecated PlayerPreLoginEvent event is left out of the +API spec for this event. Plugins should not be using that event, and +how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent +is undefined. + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..12c1c6fe9dc8dc5f5faf6dcf99f6857219ef22b8 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java +@@ -0,0 +1,95 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++ ++import java.net.InetAddress; ++import java.util.UUID; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ *

    ++ * This event is invoked when a player has disconnected. It is guaranteed that, ++ * if the server is in online-mode, that the provided uuid and username have been ++ * validated. ++ *

    ++ * ++ *

    ++ * The event is invoked for players who have not yet logged into the world, whereas ++ * {@link org.bukkit.event.player.PlayerQuitEvent} is only invoked on players who have logged into the world. ++ *

    ++ * ++ *

    ++ * The event is invoked for players who have already logged into the world, ++ * although whether or not the player exists in the world at the time of ++ * firing is undefined. (That is, whether the plugin can retrieve a Player object ++ * using the event parameters is undefined). However, it is guaranteed that this ++ * event is invoked AFTER {@link org.bukkit.event.player.PlayerQuitEvent}, if the player has already logged into the world. ++ *

    ++ * ++ *

    ++ * This event is guaranteed to never fire unless {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} has ++ * been fired beforehand, and this event may not be called in parallel with ++ * {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} for the same connection. ++ *

    ++ * ++ *

    ++ * Cancelling the {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} guarantees the corresponding ++ * {@code PlayerConnectionCloseEvent} is never called. ++ *

    ++ * ++ *

    ++ * The event may be invoked asynchronously or synchronously. Plugins should check ++ * {@link Event#isAsynchronous()} and handle accordingly. ++ *

    ++ */ ++public class PlayerConnectionCloseEvent extends Event { ++ ++ private static final HandlerList HANDLERS = new HandlerList(); ++ ++ @NotNull private final UUID playerUniqueId; ++ @NotNull private final String playerName; ++ @NotNull private final InetAddress ipAddress; ++ ++ public PlayerConnectionCloseEvent(@NotNull final UUID playerUniqueId, @NotNull final String playerName, @NotNull final InetAddress ipAddress, final boolean async) { ++ super(async); ++ this.playerUniqueId = playerUniqueId; ++ this.playerName = playerName; ++ this.ipAddress = ipAddress; ++ } ++ ++ /** ++ * Returns the {@code UUID} of the player disconnecting. ++ */ ++ @NotNull ++ public UUID getPlayerUniqueId() { ++ return this.playerUniqueId; ++ } ++ ++ /** ++ * Returns the name of the player disconnecting. ++ */ ++ @NotNull ++ public String getPlayerName() { ++ return this.playerName; ++ } ++ ++ /** ++ * Returns the player's IP address. ++ */ ++ @NotNull ++ public InetAddress getIpAddress() { ++ return this.ipAddress; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLERS; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLERS; ++ } ++} diff --git a/patches/api-unmapped/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/patches/api-unmapped/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch new file mode 100644 index 0000000000..ec2b79af2d --- /dev/null +++ b/patches/api-unmapped/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Jan 2019 00:31:12 -0600 +Subject: [PATCH] Add APIs to replace OfflinePlayer#getLastPlayed + +Currently OfflinePlayer#getLastPlayed could more accurately be described +as "OfflinePlayer#getLastTimeTheirDataWasSaved". + +The API doc says it should return the last time the server "witnessed" +the player, whilst also saying it should return the last time they +logged in. The current implementation does neither. + +Given this interesting contradiction in the API documentation and the +current defacto implementation, I've elected to deprecate (with no +intent to remove) and replace it with two new methods, clearly named and +documented as to their purpose. + +diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java +index 6cf05fed701c67a2c797a4e0839c795802a238a1..3afd5f5c0208a4ee93b5dbfc2aab2b9d2e8a7544 100644 +--- a/src/main/java/org/bukkit/OfflinePlayer.java ++++ b/src/main/java/org/bukkit/OfflinePlayer.java +@@ -147,7 +147,9 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio + * UTC. + * + * @return Date of last log-in for this player, or 0 ++ * @deprecated The API contract is ambiguous and the implementation may or may not return the correct value given this API ambiguity. It is instead recommended use {@link #getLastLogin()} or {@link #getLastSeen()} depending on your needs. + */ ++ @Deprecated + public long getLastPlayed(); + + /** +@@ -165,6 +167,30 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio + */ + @Nullable + public Location getBedSpawnLocation(); ++ // Paper start ++ /** ++ * Gets the last date and time that this player logged into the server. ++ *

    ++ * If the player has never played before, this will return 0. Otherwise, ++ * it will be the amount of milliseconds since midnight, January 1, 1970 ++ * UTC. ++ * ++ * @return last login time ++ */ ++ public long getLastLogin(); ++ ++ /** ++ * Gets the last date and time that this player was seen on the server. ++ *

    ++ * If the player has never played before, this will return 0. If the ++ * player is currently online, this will return the current time. ++ * Otherwise it will be the amount of milliseconds since midnight, ++ * January 1, 1970 UTC. ++ * ++ * @return last seen time ++ */ ++ public long getLastSeen(); ++ // Paper end + + /** + * Increments the given statistic for this player. diff --git a/patches/api-unmapped/0168-BlockDestroyEvent.patch b/patches/api-unmapped/0168-BlockDestroyEvent.patch new file mode 100644 index 0000000000..4ad73d8ef1 --- /dev/null +++ b/patches/api-unmapped/0168-BlockDestroyEvent.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 Feb 2019 00:19:33 -0500 +Subject: [PATCH] BlockDestroyEvent + +Adds an event for when the server is going to destroy a current block, +potentially causing it to drop. This event can be cancelled to avoid +the block destruction, such as preventing signs from popping when +floating in the air. + +This can replace many uses of BlockPhysicsEvent + +diff --git a/src/main/java/com/destroystokyo/paper/event/block/BlockDestroyEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BlockDestroyEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..28255dc39eab5faf324d1fe556ab12daed527ff6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/block/BlockDestroyEvent.java +@@ -0,0 +1,92 @@ ++package com.destroystokyo.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.block.data.BlockData; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired anytime the server intends to 'destroy' a block through some triggering reason. ++ * This does not fire anytime a block is set to air, but only with more direct triggers such ++ * as physics updates, pistons, Entities changing blocks, commands set to "Destroy". ++ * ++ * This event is associated with the game playing a sound effect at the block in question, when ++ * something can be described as "intend to destroy what is there", ++ * ++ * Events such as leaves decaying, pistons retracting (where the block is moving), does NOT fire this event. ++ * ++ */ ++public class BlockDestroyEvent extends BlockEvent implements Cancellable { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull private final BlockData newState; ++ private final boolean willDrop; ++ private boolean playEffect = true; ++ ++ private boolean cancelled = false; ++ ++ public BlockDestroyEvent(@NotNull Block block, @NotNull BlockData newState, boolean willDrop) { ++ super(block); ++ this.newState = newState; ++ this.willDrop = willDrop; ++ } ++ ++ /** ++ * @return The new state of this block (Air, or a Fluid type) ++ */ ++ @NotNull ++ public BlockData getNewState() { ++ return newState; ++ } ++ ++ /** ++ * @return If the server is going to drop the block in question with this destroy event ++ */ ++ public boolean willDrop() { ++ return this.willDrop; ++ } ++ ++ /** ++ * @return If the server is going to play the sound effect for this destruction ++ */ ++ public boolean playEffect() { ++ return this.playEffect; ++ } ++ ++ /** ++ * @param playEffect If the server should play the sound effect for this destruction ++ */ ++ public void setPlayEffect(boolean playEffect) { ++ this.playEffect = playEffect; ++ } ++ ++ /** ++ * @return If the event is cancelled, meaning the block will not be destroyed ++ */ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * If the event is cancelled, the block will remain in its previous state. ++ * @param cancel true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0169-Add-ItemStack-Recipe-API-helper-methods.patch b/patches/api-unmapped/0169-Add-ItemStack-Recipe-API-helper-methods.patch new file mode 100644 index 0000000000..9b2dfc0c72 --- /dev/null +++ b/patches/api-unmapped/0169-Add-ItemStack-Recipe-API-helper-methods.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 28 Jan 2014 19:13:57 -0500 +Subject: [PATCH] Add ItemStack Recipe API helper methods + +Allows using ExactChoice Recipes with easier methodss + +diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java +index d742c4058ba9aed4fbe1591fd755a06608b06e98..222a12baa8e93ad686ab59426653f066d5876e38 100644 +--- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java ++++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java +@@ -145,6 +145,13 @@ public class ShapedRecipe implements Recipe, Keyed { + return this; + } + ++ // Paper start ++ @NotNull ++ public ShapedRecipe setIngredient(char key, @NotNull ItemStack item) { ++ return setIngredient(key, new RecipeChoice.ExactChoice(item)); ++ } ++ // Paper end ++ + /** + * Get a copy of the ingredients map. + * +diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java +index 84062dd719cb8a6142dc8c806777cb208c6b42b2..7f6d3c71c5b3a9aa54c84a4c3b7c3614a0d477ce 100644 +--- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java ++++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java +@@ -143,6 +143,40 @@ public class ShapelessRecipe implements Recipe, Keyed { + return this; + } + ++ // Paper start ++ @NotNull ++ public ShapelessRecipe addIngredient(@NotNull ItemStack item) { ++ return addIngredient(item.getAmount(), item); ++ } ++ ++ @NotNull ++ public ShapelessRecipe addIngredient(int count, @NotNull ItemStack item) { ++ Validate.isTrue(ingredients.size() + count <= 9, "Shapeless recipes cannot have more than 9 ingredients"); ++ while (count-- > 0) { ++ ingredients.add(new RecipeChoice.ExactChoice(item)); ++ } ++ return this; ++ } ++ ++ @NotNull ++ public ShapelessRecipe removeIngredient(@NotNull ItemStack item) { ++ return removeIngredient(1, item); ++ } ++ ++ @NotNull ++ public ShapelessRecipe removeIngredient(int count, @NotNull ItemStack item) { ++ Iterator iterator = ingredients.iterator(); ++ while (count > 0 && iterator.hasNext()) { ++ ItemStack stack = iterator.next().getItemStack(); ++ if (stack.equals(item)) { ++ iterator.remove(); ++ count--; ++ } ++ } ++ return this; ++ } ++ // Paper end ++ + /** + * Removes an ingredient from the list. + * diff --git a/patches/api-unmapped/0170-Add-WhitelistToggleEvent.patch b/patches/api-unmapped/0170-Add-WhitelistToggleEvent.patch new file mode 100644 index 0000000000..4bb54b5c92 --- /dev/null +++ b/patches/api-unmapped/0170-Add-WhitelistToggleEvent.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Wed, 13 Mar 2019 20:04:43 +0200 +Subject: [PATCH] Add WhitelistToggleEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/server/WhitelistToggleEvent.java b/src/main/java/com/destroystokyo/paper/event/server/WhitelistToggleEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fdd5eedb2b7401439912a3a4343a920f32edc860 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/server/WhitelistToggleEvent.java +@@ -0,0 +1,40 @@ ++package com.destroystokyo.paper.event.server; ++ ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * This event is fired when whitelist is toggled ++ * ++ * @author Mark Vainomaa ++ */ ++public class WhitelistToggleEvent extends Event { ++ private static final HandlerList handlers = new HandlerList(); ++ ++ private boolean enabled; ++ ++ public WhitelistToggleEvent(boolean enabled) { ++ this.enabled = enabled; ++ } ++ ++ /** ++ * Gets whether whitelist is going to be enabled or not ++ * ++ * @return Whether whitelist is going to be enabled or not ++ */ ++ public boolean isEnabled() { ++ return enabled; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0171-Annotation-Test-changes.patch b/patches/api-unmapped/0171-Annotation-Test-changes.patch new file mode 100644 index 0000000000..380b55d775 --- /dev/null +++ b/patches/api-unmapped/0171-Annotation-Test-changes.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 17 Mar 2019 23:04:30 +0000 +Subject: [PATCH] Annotation Test changes + + +diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java +index c62919f18f318fec15a6c364d8b6d562c2b04762..2bb75e967d4250476a151599b68de80011d222b2 100644 +--- a/src/test/java/org/bukkit/AnnotationTest.java ++++ b/src/test/java/org/bukkit/AnnotationTest.java +@@ -46,7 +46,17 @@ public class AnnotationTest { + "org/bukkit/util/io/Wrapper", + "org/bukkit/plugin/java/PluginClassLoader", + // Generic functional interface +- "org/bukkit/util/Consumer" ++ "org/bukkit/util/Consumer", ++ // Paper start ++ // Timings history is broken in terms of nullability due to guavas Function defining that the param is NonNull ++ "co/aikar/timings/TimingHistory$2", ++ "co/aikar/timings/TimingHistory$2$1", ++ "co/aikar/timings/TimingHistory$2$1$1", ++ "co/aikar/timings/TimingHistory$2$1$2", ++ "co/aikar/timings/TimingHistory$3", ++ "co/aikar/timings/TimingHistory$4", ++ "co/aikar/timings/TimingHistoryEntry$1" ++ // Paper end + }; + + @Test diff --git a/patches/api-unmapped/0172-Entity-getEntitySpawnReason.patch b/patches/api-unmapped/0172-Entity-getEntitySpawnReason.patch new file mode 100644 index 0000000000..080a5c3186 --- /dev/null +++ b/patches/api-unmapped/0172-Entity-getEntitySpawnReason.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Mar 2019 00:21:23 -0400 +Subject: [PATCH] Entity#getEntitySpawnReason + +Allows you to return the SpawnReason for why an Entity Spawned + +Pre existing entities will return NATURAL if it was a non +persistenting Living Entity, SPAWNER for spawners, +or DEFAULT since data was not stored. + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 4b1f9b0ad5dc9ad6f33fddafc376b6f983a556ef..5b382091b1466b25ad42325d5808785a8e948552 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -708,5 +708,11 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + */ + @NotNull + Chunk getChunk(); ++ ++ /** ++ * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity. ++ */ ++ @NotNull ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason(); + // Paper end + } diff --git a/patches/api-unmapped/0173-Add-GS4-Query-event.patch b/patches/api-unmapped/0173-Add-GS4-Query-event.patch new file mode 100644 index 0000000000..ffab49a92a --- /dev/null +++ b/patches/api-unmapped/0173-Add-GS4-Query-event.patch @@ -0,0 +1,424 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 17 Mar 2019 21:46:27 +0200 +Subject: [PATCH] Add GS4 Query event + + +diff --git a/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java b/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..77a19995f6792a182c5a43d6714e7bda0f42df5b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java +@@ -0,0 +1,412 @@ ++package com.destroystokyo.paper.event.server; ++ ++import com.google.common.base.Preconditions; ++import com.google.common.collect.ImmutableList; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++import java.net.InetAddress; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collection; ++import java.util.List; ++ ++/** ++ * This event is fired if server is getting queried over GS4 Query protocol ++ * ++ * Adapted from Velocity's ProxyQueryEvent ++ * ++ * @author Mark Vainomaa ++ */ ++public final class GS4QueryEvent extends Event { ++ private static final HandlerList handlers = new HandlerList(); ++ ++ private final QueryType queryType; ++ private final InetAddress querierAddress; ++ private QueryResponse response; ++ ++ public GS4QueryEvent(@NotNull QueryType queryType, @NotNull InetAddress querierAddress, @NotNull QueryResponse response) { ++ super(true); // should always be called async ++ this.queryType = Preconditions.checkNotNull(queryType, "queryType"); ++ this.querierAddress = Preconditions.checkNotNull(querierAddress, "querierAddress"); ++ this.response = Preconditions.checkNotNull(response, "response"); ++ } ++ ++ /** ++ * Get query type ++ * @return query type ++ */ ++ @NotNull ++ public QueryType getQueryType() { ++ return queryType; ++ } ++ ++ /** ++ * Get querier address ++ * @return querier address ++ */ ++ @NotNull ++ public InetAddress getQuerierAddress() { ++ return querierAddress; ++ } ++ ++ /** ++ * Get query response ++ * @return query response ++ */ ++ @NotNull ++ public QueryResponse getResponse() { ++ return response; ++ } ++ ++ /** ++ * Set query response ++ * @param response query response ++ */ ++ public void setResponse(@NotNull QueryResponse response) { ++ this.response = Preconditions.checkNotNull(response, "response"); ++ } ++ ++ @Override ++ public String toString() { ++ return "GS4QueryEvent{" + ++ "queryType=" + queryType + ++ ", querierAddress=" + querierAddress + ++ ", response=" + response + ++ '}'; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ /** ++ * The type of query ++ */ ++ public enum QueryType { ++ /** ++ * Basic query asks only a subset of information, such as motd, game type (hardcoded to

    MINECRAFT
    ), map, ++ * current players, max players, server port and server motd ++ */ ++ BASIC, ++ ++ /** ++ * Full query asks pretty much everything present on this event (only hardcoded values cannot be modified here). ++ */ ++ FULL ++ ; ++ } ++ ++ public final static class QueryResponse { ++ private final String motd; ++ private final String gameVersion; ++ private final String map; ++ private final int currentPlayers; ++ private final int maxPlayers; ++ private final String hostname; ++ private final int port; ++ private final Collection players; ++ private final String serverVersion; ++ private final Collection plugins; ++ ++ private QueryResponse(String motd, String gameVersion, String map, int currentPlayers, int maxPlayers, String hostname, int port, Collection players, String serverVersion, Collection plugins) { ++ this.motd = motd; ++ this.gameVersion = gameVersion; ++ this.map = map; ++ this.currentPlayers = currentPlayers; ++ this.maxPlayers = maxPlayers; ++ this.hostname = hostname; ++ this.port = port; ++ this.players = players; ++ this.serverVersion = serverVersion; ++ this.plugins = plugins; ++ } ++ ++ /** ++ * Get motd which will be used to reply to the query. By default it is {@link org.bukkit.Server#getMotd()}. ++ * @return motd ++ */ ++ @NotNull ++ public String getMotd() { ++ return motd; ++ } ++ ++ /** ++ * Get game version which will be used to reply to the query. By default supported Minecraft versions range is sent. ++ * @return game version ++ */ ++ @NotNull ++ public String getGameVersion() { ++ return gameVersion; ++ } ++ ++ /** ++ * Get map name which will be used to reply to the query. By default {@code world} is sent. ++ * @return map name ++ */ ++ @NotNull ++ public String getMap() { ++ return map; ++ } ++ ++ /** ++ * Get current online player count which will be used to reply to the query. ++ * @return online player count ++ */ ++ public int getCurrentPlayers() { ++ return currentPlayers; ++ } ++ ++ /** ++ * Get max player count which will be used to reply to the query. ++ * @return max player count ++ */ ++ public int getMaxPlayers() { ++ return maxPlayers; ++ } ++ ++ /** ++ * Get server (public facing) hostname ++ * @return server hostname ++ */ ++ @NotNull ++ public String getHostname() { ++ return hostname; ++ } ++ ++ /** ++ * Get server (public facing) port ++ * @return server port ++ */ ++ public int getPort() { ++ return port; ++ } ++ ++ /** ++ * Get collection of players which will be used to reply to the query. ++ * @return collection of players ++ */ ++ @NotNull ++ public Collection getPlayers() { ++ return players; ++ } ++ ++ /** ++ * Get server software (name and version) which will be used to reply to the query. ++ * @return server software ++ */ ++ @NotNull ++ public String getServerVersion() { ++ return serverVersion; ++ } ++ ++ /** ++ * Get list of plugins which will be used to reply to the query. ++ * @return collection of plugins ++ */ ++ @NotNull ++ public Collection getPlugins() { ++ return plugins; ++ } ++ ++ ++ /** ++ * Creates a new {@link Builder} instance from data represented by this response ++ * @return {@link QueryResponse} builder ++ */ ++ @NotNull ++ public Builder toBuilder() { ++ return QueryResponse.builder() ++ .motd(getMotd()) ++ .gameVersion(getGameVersion()) ++ .map(getMap()) ++ .currentPlayers(getCurrentPlayers()) ++ .maxPlayers(getMaxPlayers()) ++ .hostname(getHostname()) ++ .port(getPort()) ++ .players(getPlayers()) ++ .serverVersion(getServerVersion()) ++ .plugins(getPlugins()); ++ } ++ ++ /** ++ * Creates a new {@link Builder} instance ++ * @return {@link QueryResponse} builder ++ */ ++ @NotNull ++ public static Builder builder() { ++ return new Builder(); ++ } ++ ++ /** ++ * A builder for {@link QueryResponse} objects. ++ */ ++ public static final class Builder { ++ private String motd; ++ private String gameVersion; ++ private String map; ++ private String hostname; ++ private String serverVersion; ++ ++ private int currentPlayers; ++ private int maxPlayers; ++ private int port; ++ ++ private List players = new ArrayList<>(); ++ private List plugins = new ArrayList<>(); ++ ++ private Builder() {} ++ ++ @NotNull ++ public Builder motd(@NotNull String motd) { ++ this.motd = Preconditions.checkNotNull(motd, "motd"); ++ return this; ++ } ++ ++ @NotNull ++ public Builder gameVersion(@NotNull String gameVersion) { ++ this.gameVersion = Preconditions.checkNotNull(gameVersion, "gameVersion"); ++ return this; ++ } ++ ++ @NotNull ++ public Builder map(@NotNull String map) { ++ this.map = Preconditions.checkNotNull(map, "map"); ++ return this; ++ } ++ ++ @NotNull ++ public Builder currentPlayers(int currentPlayers) { ++ Preconditions.checkArgument(currentPlayers >= 0, "currentPlayers cannot be negative"); ++ this.currentPlayers = currentPlayers; ++ return this; ++ } ++ ++ @NotNull ++ public Builder maxPlayers(int maxPlayers) { ++ Preconditions.checkArgument(maxPlayers >= 0, "maxPlayers cannot be negative"); ++ this.maxPlayers = maxPlayers; ++ return this; ++ } ++ ++ @NotNull ++ public Builder hostname(@NotNull String hostname) { ++ this.hostname = Preconditions.checkNotNull(hostname, "hostname"); ++ return this; ++ } ++ ++ @NotNull ++ public Builder port(int port) { ++ Preconditions.checkArgument(port >= 1 && port <= 65535, "port must be between 1-65535"); ++ this.port = port; ++ return this; ++ } ++ ++ @NotNull ++ public Builder players(@NotNull Collection players) { ++ this.players.addAll(Preconditions.checkNotNull(players, "players")); ++ return this; ++ } ++ ++ @NotNull ++ public Builder players(@NotNull String... players) { ++ this.players.addAll(Arrays.asList(Preconditions.checkNotNull(players, "players"))); ++ return this; ++ } ++ ++ @NotNull ++ public Builder clearPlayers() { ++ this.players.clear(); ++ return this; ++ } ++ ++ @NotNull ++ public Builder serverVersion(@NotNull String serverVersion) { ++ this.serverVersion = Preconditions.checkNotNull(serverVersion, "serverVersion"); ++ return this; ++ } ++ ++ @NotNull ++ public Builder plugins(@NotNull Collection plugins) { ++ this.plugins.addAll(Preconditions.checkNotNull(plugins, "plugins")); ++ return this; ++ } ++ ++ @NotNull ++ public Builder plugins(@NotNull PluginInformation... plugins) { ++ this.plugins.addAll(Arrays.asList(Preconditions.checkNotNull(plugins, "plugins"))); ++ return this; ++ } ++ ++ @NotNull ++ public Builder clearPlugins() { ++ this.plugins.clear(); ++ return this; ++ } ++ ++ /** ++ * Builds new {@link QueryResponse} with supplied data ++ * @return response ++ */ ++ @NotNull ++ public QueryResponse build() { ++ return new QueryResponse( ++ Preconditions.checkNotNull(motd, "motd"), ++ Preconditions.checkNotNull(gameVersion, "gameVersion"), ++ Preconditions.checkNotNull(map, "map"), ++ currentPlayers, ++ maxPlayers, ++ Preconditions.checkNotNull(hostname, "hostname"), ++ port, ++ ImmutableList.copyOf(players), ++ Preconditions.checkNotNull(serverVersion, "serverVersion"), ++ ImmutableList.copyOf(plugins) ++ ); ++ } ++ } ++ ++ /** ++ * Plugin information ++ */ ++ public static class PluginInformation { ++ private String name; ++ private String version; ++ ++ public PluginInformation(@NotNull String name, @NotNull String version) { ++ this.name = Preconditions.checkNotNull(name, "name"); ++ this.version = Preconditions.checkNotNull(version, "version"); ++ } ++ ++ @NotNull ++ public String getName() { ++ return name; ++ } ++ ++ public void setName(@NotNull String name) { ++ this.name = name; ++ } ++ ++ public void setVersion(@NotNull String version) { ++ this.version = version; ++ } ++ ++ @NotNull ++ public String getVersion() { ++ return version; ++ } ++ ++ @NotNull ++ public static PluginInformation of(@NotNull String name, @NotNull String version) { ++ return new PluginInformation(name, version); ++ } ++ } ++ } ++} diff --git a/patches/api-unmapped/0174-Add-PlayerPostRespawnEvent.patch b/patches/api-unmapped/0174-Add-PlayerPostRespawnEvent.patch new file mode 100644 index 0000000000..2eb0647eac --- /dev/null +++ b/patches/api-unmapped/0174-Add-PlayerPostRespawnEvent.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MisterVector +Date: Fri, 26 Oct 2018 21:33:13 -0700 +Subject: [PATCH] Add PlayerPostRespawnEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..31f34b54801f6699ce43355fa2a0a51f1ad0c997 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java +@@ -0,0 +1,52 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired after a player has respawned ++ */ ++public class PlayerPostRespawnEvent extends PlayerEvent { ++ private final static HandlerList handlers = new HandlerList(); ++ private final Location respawnedLocation; ++ private final boolean isBedSpawn; ++ ++ public PlayerPostRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnedLocation, final boolean isBedSpawn) { ++ super(respawnPlayer); ++ this.respawnedLocation = respawnedLocation; ++ this.isBedSpawn = isBedSpawn; ++ } ++ ++ /** ++ * Returns the location of the respawned player ++ * ++ * @return location of the respawned player ++ */ ++ @NotNull ++ public Location getRespawnedLocation() { ++ return respawnedLocation.clone(); ++ } ++ ++ /** ++ * Checks if the player respawned to their bed ++ * ++ * @return whether the player respawned to their bed ++ */ ++ public boolean isBedSpawn() { ++ return isBedSpawn; ++ } ++ ++ @Override ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0175-Ignore-package-private-methods-for-nullability-annot.patch b/patches/api-unmapped/0175-Ignore-package-private-methods-for-nullability-annot.patch new file mode 100644 index 0000000000..28d9857af0 --- /dev/null +++ b/patches/api-unmapped/0175-Ignore-package-private-methods-for-nullability-annot.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Mar 2019 18:44:26 -0400 +Subject: [PATCH] Ignore package-private methods for nullability annotations + +This isn't API + +diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java +index 2bb75e967d4250476a151599b68de80011d222b2..03229d5f4ec36a82197beb391356d791ff67fb2f 100644 +--- a/src/test/java/org/bukkit/AnnotationTest.java ++++ b/src/test/java/org/bukkit/AnnotationTest.java +@@ -168,7 +168,7 @@ public class AnnotationTest { + + private static boolean isMethodIncluded(@NotNull ClassNode clazz, @NotNull MethodNode method, @NotNull Map allClasses) { + // Exclude private, synthetic and deprecated methods +- if ((method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED)) != 0) { ++ if ((method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED)) != 0 || (method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) == 0) { // Paper - ignore package-private + return false; + } + diff --git a/patches/api-unmapped/0176-Flip-some-Spigot-API-null-annotations.patch b/patches/api-unmapped/0176-Flip-some-Spigot-API-null-annotations.patch new file mode 100644 index 0000000000..44f9bcdbe3 --- /dev/null +++ b/patches/api-unmapped/0176-Flip-some-Spigot-API-null-annotations.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Mar 2019 18:39:01 -0400 +Subject: [PATCH] Flip some Spigot API null annotations + +while some of these may of been true, they are extreme cases and cause +a ton of noise to plugin developers. + +These do not help plugin developers if they bring moise noise than value. + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index dcaefdaf5a0de8486f59115c8c4d4c211b7d64cd..e3304fcc8c4fd176abd3fb7d4b47e5ccb7bdd37f 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1389,7 +1389,7 @@ public final class Bukkit { + * + * @return the scoreboard manager or null if no worlds are loaded. + */ +- @Nullable ++ @NotNull // Paper + public static ScoreboardManager getScoreboardManager() { + return server.getScoreboardManager(); + } +@@ -1686,7 +1686,7 @@ public final class Bukkit { + * @param clazz the class of the tag entries + * @return the tag or null + */ +- @Nullable ++ @UndefinedNullability // Paper + public static Tag getTag(@NotNull String registry, @NotNull NamespacedKey tag, @NotNull Class clazz) { + return server.getTag(registry, tag, clazz); + } +diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java +index 9c91c49ed7302c12fcb1d8e9bc58712efc199954..d5d67b3d84cd88ed0f858497e68535ec0162c700 100644 +--- a/src/main/java/org/bukkit/Location.java ++++ b/src/main/java/org/bukkit/Location.java +@@ -46,7 +46,7 @@ public class Location implements Cloneable, ConfigurationSerializable { + * @param y The y-coordinate of this new location + * @param z The z-coordinate of this new location + */ +- public Location(@Nullable final World world, final double x, final double y, final double z) { ++ public Location(@UndefinedNullability final World world, final double x, final double y, final double z) { // Paper + this(world, x, y, z, 0, 0); + } + +@@ -60,7 +60,7 @@ public class Location implements Cloneable, ConfigurationSerializable { + * @param yaw The absolute rotation on the x-plane, in degrees + * @param pitch The absolute rotation on the y-plane, in degrees + */ +- public Location(@Nullable final World world, final double x, final double y, final double z, final float yaw, final float pitch) { ++ public Location(@UndefinedNullability final World world, final double x, final double y, final double z, final float yaw, final float pitch) { + if (world != null) { + this.world = new WeakReference<>(world); + } +@@ -102,7 +102,7 @@ public class Location implements Cloneable, ConfigurationSerializable { + * @throws IllegalArgumentException when world is unloaded + * @see #isWorldLoaded() + */ +- @Nullable ++ @UndefinedNullability + public World getWorld() { + if (this.world == null) { + return null; +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 9b8e6b7bbbed44e2659379c8046acaa35aaa8910..989a732e5ef2053deede245d65fbf99cdf117c5e 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1171,7 +1171,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + * + * @return the scoreboard manager or null if no worlds are loaded. + */ +- @Nullable ++ @NotNull // Paper + ScoreboardManager getScoreboardManager(); + + /** +@@ -1441,7 +1441,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + * @param clazz the class of the tag entries + * @return the tag or null + */ +- @Nullable ++ @UndefinedNullability + Tag getTag(@NotNull String registry, @NotNull NamespacedKey tag, @NotNull Class clazz); + + /** +diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java +index 591e095dabd4cb72881abf206b1d7f0c8818cef3..ecf509a970ed4f0052d5d2c756406bf96052a680 100644 +--- a/src/main/java/org/bukkit/inventory/ItemFactory.java ++++ b/src/main/java/org/bukkit/inventory/ItemFactory.java +@@ -3,6 +3,7 @@ package org.bukkit.inventory; + import org.bukkit.Color; + import org.bukkit.Material; + import org.bukkit.Server; ++import org.bukkit.UndefinedNullability; + import org.bukkit.inventory.meta.BookMeta; + import org.bukkit.inventory.meta.ItemMeta; + import org.bukkit.inventory.meta.SkullMeta; +@@ -25,7 +26,7 @@ public interface ItemFactory { + * @return a new ItemMeta that could be applied to an item stack of the + * specified material + */ +- @Nullable ++ @UndefinedNullability // Paper + ItemMeta getItemMeta(@NotNull final Material material); + + /** +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index 686e2a0b9fe061816b41435ef2337870dbdca8e5..290c3f0fd6e8c3407d421b697e0ee01584f4cebd 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -8,6 +8,7 @@ import java.util.Set; // Paper + import org.apache.commons.lang.Validate; + import org.bukkit.Bukkit; + import org.bukkit.Material; ++import org.bukkit.UndefinedNullability; + import org.bukkit.Utility; + import org.bukkit.configuration.serialization.ConfigurationSerializable; + import org.bukkit.enchantments.Enchantment; +@@ -546,7 +547,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + * + * @return a copy of the current ItemStack's ItemData + */ +- @Nullable ++ @UndefinedNullability // Paper + public ItemMeta getItemMeta() { + return this.meta == null ? Bukkit.getItemFactory().getItemMeta(this.type) : this.meta.clone(); + } diff --git a/patches/api-unmapped/0177-Server-Tick-Events.patch b/patches/api-unmapped/0177-Server-Tick-Events.patch new file mode 100644 index 0000000000..9cb8b9a4c0 --- /dev/null +++ b/patches/api-unmapped/0177-Server-Tick-Events.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 27 Mar 2019 21:58:55 -0400 +Subject: [PATCH] Server Tick Events + +Fires event at start and end of a server tick + +diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerTickEndEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerTickEndEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9fd28e03649f66f71fb7f0536a137557ec32cd25 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/server/ServerTickEndEvent.java +@@ -0,0 +1,59 @@ ++package com.destroystokyo.paper.event.server; ++ ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when the server has finished ticking the main loop ++ */ ++public class ServerTickEndEvent extends Event { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private final int tickNumber; ++ private final double tickDuration; ++ private final long timeEnd; ++ ++ public ServerTickEndEvent(int tickNumber, double tickDuration, long timeRemaining) { ++ this.tickNumber = tickNumber; ++ this.tickDuration = tickDuration; ++ this.timeEnd = System.nanoTime() + timeRemaining; ++ } ++ ++ /** ++ * @return What tick this was since start (first tick = 1) ++ */ ++ public int getTickNumber() { ++ return tickNumber; ++ } ++ ++ /** ++ * @return Time in milliseconds of how long this tick took ++ */ ++ public double getTickDuration() { ++ return tickDuration; ++ } ++ ++ /** ++ * Amount of nanoseconds remaining before the next tick should start. ++ * ++ * If this value is negative, then that means the server has exceeded the tick time limit and TPS has been lost. ++ * ++ * Method will continously return the updated time remaining value. (return value is not static) ++ * ++ * @return Amount of nanoseconds remaining before the next tick should start ++ */ ++ public long getTimeRemaining() { ++ return this.timeEnd - System.nanoTime(); ++ } ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerTickStartEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerTickStartEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..eac85f1f49088bb71afb01eff4d5f53887306461 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/server/ServerTickStartEvent.java +@@ -0,0 +1,32 @@ ++package com.destroystokyo.paper.event.server; ++ ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++public class ServerTickStartEvent extends Event { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private final int tickNumber; ++ ++ public ServerTickStartEvent(int tickNumber) { ++ this.tickNumber = tickNumber; ++ } ++ ++ /** ++ * @return What tick this is going be since start (first tick = 1) ++ */ ++ public int getTickNumber() { ++ return tickNumber; ++ } ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0178-PlayerDeathEvent-getItemsToKeep.patch b/patches/api-unmapped/0178-PlayerDeathEvent-getItemsToKeep.patch new file mode 100644 index 0000000000..e41136bc7f --- /dev/null +++ b/patches/api-unmapped/0178-PlayerDeathEvent-getItemsToKeep.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 11 Mar 2013 20:04:34 -0400 +Subject: [PATCH] PlayerDeathEvent#getItemsToKeep + +Exposes a mutable array on items a player should keep on death + +Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4 + +diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +index a01d4c21bedc7f1a54f5a330bb4c2909ce3a18e4..8c46eaebf004823c1c31eb2c7304181487cb1332 100644 +--- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java ++++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +@@ -36,7 +36,6 @@ public class PlayerDeathEvent extends EntityDeathEvent { + } + // Paper end + +- @Deprecated // Paper + public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final String deathMessage) { + this(player, drops, droppedExp, 0, deathMessage); + } +@@ -56,6 +55,41 @@ public class PlayerDeathEvent extends EntityDeathEvent { + this.adventure$deathMessage = deathMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(deathMessage) : net.kyori.adventure.text.Component.empty(); // Paper + } + ++ @Deprecated // Paper ++ // Paper start ++ private List itemsToKeep = new java.util.ArrayList<>(); ++ ++ /** ++ * A mutable collection to add items that the player should retain in their inventory on death (Similar to KeepInventory game rule) ++ * ++ * You MUST remove the item from the .getDrops() collection too or it will duplicate! ++ *
    {@code
    ++     *    {@literal @EventHandler(ignoreCancelled = true)}
    ++     *     public void onPlayerDeath(PlayerDeathEvent event) {
    ++     *         for (Iterator iterator = event.getDrops().iterator(); iterator.hasNext(); ) {
    ++     *             ItemStack drop = iterator.next();
    ++     *             List lore = drop.getLore();
    ++     *             if (lore != null && !lore.isEmpty()) {
    ++     *                 if (lore.get(0).contains("(SOULBOUND)")) {
    ++     *                     iterator.remove();
    ++     *                     event.getItemsToKeep().add(drop);
    ++     *                 }
    ++     *             }
    ++     *         }
    ++     *     }
    ++     * }
    ++ * ++ * Adding an item to this list that the player did not previously have will give them the item on death. ++ * An example case could be a "Note" that "You died at X/Y/Z coordinates" ++ * ++ * @return The list to hold items to keep ++ */ ++ @NotNull ++ public List getItemsToKeep() { ++ return itemsToKeep; ++ } ++ // Paper end ++ + @NotNull + @Override + public Player getEntity() { diff --git a/patches/api-unmapped/0179-Add-Heightmap-API.patch b/patches/api-unmapped/0179-Add-Heightmap-API.patch new file mode 100644 index 0000000000..73e1e8d46f --- /dev/null +++ b/patches/api-unmapped/0179-Add-Heightmap-API.patch @@ -0,0 +1,196 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 1 Dec 2018 19:00:36 -0800 +Subject: [PATCH] Add Heightmap API + +Changed to use upstream's heightmap API - Machine_Maker + +diff --git a/src/main/java/com/destroystokyo/paper/HeightmapType.java b/src/main/java/com/destroystokyo/paper/HeightmapType.java +new file mode 100644 +index 0000000000000000000000000000000000000000..709e44ea1b14ab6917501c928e689cc6cbdf4bb4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/HeightmapType.java +@@ -0,0 +1,39 @@ ++package com.destroystokyo.paper; ++ ++import org.bukkit.*; ++ ++/** ++ * Enumeration of different heightmap types maintained by the server. Generally using these maps is much faster ++ * than using an iterative search for a block in a given x, z coordinate. ++ * ++ * @deprecated Upstream has added their own API for using the game heightmaps. See {@link org.bukkit.HeightMap} and the ++ * non-deprecated getHighestBlock methods on World such as {@link org.bukkit.World#getHighestBlockAt(Location, HeightMap)}. ++ */ ++@Deprecated ++public enum HeightmapType { ++ ++ /** ++ * The highest block used for lighting in the world. Also the block returned by {@link World#getHighestBlockYAt(int, int)}} ++ */ ++ LIGHT_BLOCKING, ++ ++ /** ++ * References the highest block in the world. ++ */ ++ ANY, ++ ++ /** ++ * References the highest solid block in a world. ++ */ ++ SOLID, ++ ++ /** ++ * References the highest solid or liquid block in a world. ++ */ ++ SOLID_OR_LIQUID, ++ ++ /** ++ * References the highest solid or liquid block in a world, excluding leaves. ++ */ ++ SOLID_OR_LIQUID_NO_LEAVES; ++} +diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java +index d5d67b3d84cd88ed0f858497e68535ec0162c700..432d5711b7ec34eafeb27df82d367612dfe1fe54 100644 +--- a/src/main/java/org/bukkit/Location.java ++++ b/src/main/java/org/bukkit/Location.java +@@ -638,6 +638,47 @@ public class Location implements Cloneable, ConfigurationSerializable { + return centerLoc; + } + ++ // Paper start - Add heightmap api ++ ++ /** ++ * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ()) ++ * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ()) ++ * @throws NullPointerException if {{@link #getWorld()}} is {@code null} ++ */ ++ @NotNull ++ public Location toHighestLocation() { ++ return this.toHighestLocation(HeightMap.WORLD_SURFACE); ++ } ++ ++ /** ++ * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightmap) ++ * @param heightmap The heightmap to use for finding the highest y location. ++ * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightmap) ++ * @throws NullPointerException if {{@link #getWorld()}} is {@code null} ++ * @throws UnsupportedOperationException if {@link World#getHighestBlockYAt(int, int, com.destroystokyo.paper.HeightmapType)} does not support the specified heightmap ++ * @deprecated Use {@link org.bukkit.Location#toHighestLocation(HeightMap)} ++ */ ++ @NotNull ++ @Deprecated ++ public Location toHighestLocation(@NotNull final com.destroystokyo.paper.HeightmapType heightmap) { ++ final Location ret = this.clone(); ++ ret.setY(this.getWorld().getHighestBlockYAt(this, heightmap)); ++ return ret; ++ } ++ ++ /** ++ * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightMap) ++ * @param heightMap The heightmap to use for finding the highest y location. ++ * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightMap) ++ */ ++ @NotNull ++ public Location toHighestLocation(@NotNull final HeightMap heightMap) { ++ final Location ret = this.clone(); ++ ret.setY(this.getWorld().getHighestBlockYAt(this, heightMap)); ++ return ret; ++ } ++ // Paper end ++ + /** + * Creates explosion at this location with given power + * +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 19060c7d9c74b9b2808103f3d5627444aece6ccb..f8e104d5e61e52c5fe658d7cda373f62424c7bea 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -160,6 +160,87 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + @NotNull + public Block getHighestBlockAt(@NotNull Location location); + ++ // Paper start - Add heightmap API ++ /** ++ * Returns the highest block's y-coordinate at the specified block coordinates that match the specified heightmap's conditions. ++ *

    ++ * implNote: Implementations are recommended to use an iterative search as a fallback before resorting to ++ * throwing an {@code UnsupportedOperationException}. ++ *

    ++ * ++ * @param x The block's x-coordinate. ++ * @param z The block's z-coordinate. ++ * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType} ++ * @return The highest block's y-coordinate at (x, z) that matches the specified heightmap's conditions. ++ * @throws UnsupportedOperationException If the heightmap type is not supported. ++ * @deprecated Upstream has added support for this, use {@link World#getHighestBlockYAt(int, int, HeightMap)} ++ * ++ * @see com.destroystokyo.paper.HeightmapType ++ */ ++ @Deprecated ++ public int getHighestBlockYAt(int x, int z, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException; ++ ++ /** ++ * Returns the highest block's y-coordinate at the specified block coordinates that match the specified heightmap's conditions. ++ * Note that the y-coordinate of the specified location is ignored. ++ *

    ++ * implNote: Implementations are recommended to use an iterative search as a fallback before resorting to ++ * throwing an {@code UnsupportedOperationException}. ++ *

    ++ * ++ * @param location The specified block coordinates. ++ * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType} ++ * @return The highest block's y-coordinate at {@code location} that matches the specified heightmap's conditions. ++ * @throws UnsupportedOperationException If the heightmap type is not supported. ++ * @deprecated Upstream has added support for this, use {@link World#getHighestBlockYAt(Location, HeightMap)} ++ * @see com.destroystokyo.paper.HeightmapType ++ */ ++ @Deprecated ++ default int getHighestBlockYAt(@NotNull Location location, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { ++ return this.getHighestBlockYAt(location.getBlockX(), location.getBlockZ(), heightmap); ++ } ++ ++ /** ++ * Returns the highest {@link Block} at the specified block coordinates that match the specified heightmap's conditions. ++ *

    ++ * implNote: Implementations are recommended to use an iterative search as a fallback before resorting to ++ * throwing an {@code UnsupportedOperationException}. ++ *

    ++ * @param x The block's x-coordinate. ++ * @param z The block's z-coordinate. ++ * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType} ++ * @return The highest {@link Block} at (x, z) that matches the specified heightmap's conditions. ++ * @throws UnsupportedOperationException If the heightmap type is not supported. ++ * @deprecated Upstream has added support for this, use {@link World#getHighestBlockAt(int, int, HeightMap)} ++ * @see com.destroystokyo.paper.HeightmapType ++ */ ++ @Deprecated ++ @NotNull ++ default Block getHighestBlockAt(int x, int z, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { ++ return this.getBlockAt(x, this.getHighestBlockYAt(x, z, heightmap), z); ++ } ++ ++ /** ++ * Returns the highest {@link Block} at the specified block coordinates that match the specified heightmap's conditions. ++ * Note that the y-coordinate of the specified location is ignored. ++ *

    ++ * implNote: Implementations are recommended to use an iterative search as a fallback before resorting to ++ * throwing an {@code UnsupportedOperationException}. ++ *

    ++ * @param location The specified block coordinates. ++ * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType} ++ * @return The highest {@link Block} at {@code location} that matches the specified heightmap's conditions. ++ * @throws UnsupportedOperationException If the heightmap type is not supported. ++ * @deprecated Upstream has added support for this, use {@link World#getHighestBlockAt(Location, HeightMap)} ++ * @see com.destroystokyo.paper.HeightmapType ++ */ ++ @Deprecated ++ @NotNull ++ default Block getHighestBlockAt(@NotNull Location location, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { ++ return this.getHighestBlockAt(location.getBlockX(), location.getBlockZ(), heightmap); ++ } ++ // Paper end ++ + /** + * Gets the highest coordinate corresponding to the {@link HeightMap} at the + * given coordinates. diff --git a/patches/api-unmapped/0180-Mob-Spawner-API-Enhancements.patch b/patches/api-unmapped/0180-Mob-Spawner-API-Enhancements.patch new file mode 100644 index 0000000000..2bbe92cbe9 --- /dev/null +++ b/patches/api-unmapped/0180-Mob-Spawner-API-Enhancements.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +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 cb447a4ad5a9dce7c98999a5d7fcd6111fc9b10e..5bbae759ce39d42886994e500fd9454ec328f804 100644 +--- a/src/main/java/org/bukkit/block/CreatureSpawner.java ++++ b/src/main/java/org/bukkit/block/CreatureSpawner.java +@@ -199,4 +199,30 @@ public interface CreatureSpawner extends TileState { + * @see #getSpawnRange() + */ + public void setSpawnRange(int spawnRange); ++ ++ // Paper start ++ /** ++ * Check if spawner is activated (a player is close enough) ++ * ++ * @return True if a player is close enough to activate it ++ */ ++ public boolean isActivated(); ++ ++ /** ++ * Resets the spawn delay timer within the min/max range ++ */ ++ public void resetTimer(); ++ ++ /** ++ * Sets the {@link EntityType} to {@link EntityType#DROPPED_ITEM} and sets the data to the given ++ * {@link org.bukkit.inventory.ItemStack ItemStack}. ++ *

    ++ * {@link #setSpawnCount(int)} does not dictate the amount of items in the stack spawned, but rather how many ++ * stacks should be spawned. ++ * ++ * @param itemStack The item to spawn. Must not {@link org.bukkit.Material#isAir be air}. ++ * @see #setSpawnedType(EntityType) ++ */ ++ void setSpawnedItem(@NotNull org.bukkit.inventory.ItemStack itemStack); ++ // Paper end + } diff --git a/patches/api-unmapped/0181-Add-BlockSoundGroup-interface.patch b/patches/api-unmapped/0181-Add-BlockSoundGroup-interface.patch new file mode 100644 index 0000000000..428810f1d8 --- /dev/null +++ b/patches/api-unmapped/0181-Add-BlockSoundGroup-interface.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: simpleauthority +Date: Tue, 28 May 2019 03:41:28 -0700 +Subject: [PATCH] Add BlockSoundGroup interface + +This PR adds the getSoundGroup() method in Block which returns a BlockSoundGroup + +diff --git a/src/main/java/com/destroystokyo/paper/block/BlockSoundGroup.java b/src/main/java/com/destroystokyo/paper/block/BlockSoundGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8cf87d228a7006658d52ce0da16c2d74f4706545 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/block/BlockSoundGroup.java +@@ -0,0 +1,52 @@ ++package com.destroystokyo.paper.block; ++ ++import org.bukkit.Sound; ++import org.bukkit.block.Block; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents the sounds that a {@link Block} makes in certain situations ++ *

    ++ * The sound group includes break, step, place, hit, and fall sounds. ++ */ ++public interface BlockSoundGroup { ++ /** ++ * Gets the sound that plays when breaking this block ++ * ++ * @return The break sound ++ */ ++ @NotNull ++ Sound getBreakSound(); ++ ++ /** ++ * Gets the sound that plays when stepping on this block ++ * ++ * @return The step sound ++ */ ++ @NotNull ++ Sound getStepSound(); ++ ++ /** ++ * Gets the sound that plays when placing this block ++ * ++ * @return The place sound ++ */ ++ @NotNull ++ Sound getPlaceSound(); ++ ++ /** ++ * Gets the sound that plays when hitting this block ++ * ++ * @return The hit sound ++ */ ++ @NotNull ++ Sound getHitSound(); ++ ++ /** ++ * Gets the sound that plays when this block falls ++ * ++ * @return The fall sound ++ */ ++ @NotNull ++ Sound getFallSound(); ++} +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index b090938f883c486e703cb7c036c47925f3016704..5e2aa4fb8cf8130df21d3172dd94e857317f7653 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -1,6 +1,7 @@ + package org.bukkit.block; + + import java.util.Collection; ++ + import org.bukkit.Chunk; + import org.bukkit.FluidCollisionMode; + import org.bukkit.Location; +@@ -560,4 +561,16 @@ public interface Block extends Metadatable { + */ + @NotNull + BoundingBox getBoundingBox(); ++ ++ // Paper start ++ /** ++ * Gets the {@link com.destroystokyo.paper.block.BlockSoundGroup} for this block. ++ *

    ++ * This object contains the block, step, place, hit, and fall sounds. ++ * ++ * @return the sound group for this block ++ */ ++ @NotNull ++ com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup(); ++ // Paper end + } diff --git a/patches/api-unmapped/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch b/patches/api-unmapped/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch new file mode 100644 index 0000000000..b5148c5574 --- /dev/null +++ b/patches/api-unmapped/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: simpleauthority +Date: Thu, 11 Jul 2019 10:35:56 -0700 +Subject: [PATCH] Amend PlayerInteractAtEntityEvent javadoc for ArmorStands + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerInteractAtEntityEvent.java b/src/main/java/org/bukkit/event/player/PlayerInteractAtEntityEvent.java +index 1075dbb8135d2fd2fd69d1e821dd1ba7f90824d5..3f24d302e28170f7f6e5885b5b9abb22cbbb7d66 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerInteractAtEntityEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerInteractAtEntityEvent.java +@@ -13,6 +13,9 @@ import org.jetbrains.annotations.NotNull; + *
    + * Note that the client may sometimes spuriously send this packet in addition to {@link PlayerInteractEntityEvent}. + * Users are advised to listen to this (parent) class unless specifically required. ++ *
    ++ * Note that interacting with Armor Stands fires this event only and not its parent and as such users are expressly required ++ * to listen to this event for that scenario. + */ + public class PlayerInteractAtEntityEvent extends PlayerInteractEntityEvent { + private static final HandlerList handlers = new HandlerList(); diff --git a/patches/api-unmapped/0183-Increase-custom-payload-channel-message-size.patch b/patches/api-unmapped/0183-Increase-custom-payload-channel-message-size.patch new file mode 100644 index 0000000000..24aacd2b29 --- /dev/null +++ b/patches/api-unmapped/0183-Increase-custom-payload-channel-message-size.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Fri, 18 Oct 2019 17:39:05 +0100 +Subject: [PATCH] Increase custom payload channel message size + +Doubles the custom payload size limit imposed by bukkit, also creates a system +property to allow customizing the size `paper.maxCustomChannelName` + +diff --git a/src/main/java/org/bukkit/plugin/messaging/Messenger.java b/src/main/java/org/bukkit/plugin/messaging/Messenger.java +index 9d2c68c826f3b867d407e7f13c6394a899cc8ee8..682c77188436d696d4dafbc70cf131d5c921e94d 100644 +--- a/src/main/java/org/bukkit/plugin/messaging/Messenger.java ++++ b/src/main/java/org/bukkit/plugin/messaging/Messenger.java +@@ -24,7 +24,7 @@ public interface Messenger { + /** + * Represents the largest size that a Plugin Channel may be. + */ +- public static final int MAX_CHANNEL_SIZE = 64; ++ public static final int MAX_CHANNEL_SIZE = Integer.getInteger("paper.maxCustomChannelName", 64); // Paper + + /** + * Checks if the specified channel is a reserved name. diff --git a/patches/api-unmapped/0184-Expose-the-internal-current-tick.patch b/patches/api-unmapped/0184-Expose-the-internal-current-tick.patch new file mode 100644 index 0000000000..b127872bfe --- /dev/null +++ b/patches/api-unmapped/0184-Expose-the-internal-current-tick.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 20 Apr 2019 19:47:29 -0500 +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 e3304fcc8c4fd176abd3fb7d4b47e5ccb7bdd37f..49bf621a2c0e5e9641b334a42b2769944c991d5d 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1835,6 +1835,10 @@ public final class Bukkit { + public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { + return server.createProfile(uuid, name); + } ++ ++ public static int getCurrentTick() { ++ return server.getCurrentTick(); ++ } + // Paper end + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 989a732e5ef2053deede245d65fbf99cdf117c5e..e448ae78304974f7664b7ef18568a547833ece9f 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1609,5 +1609,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + */ + @NotNull + com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name); ++ ++ /** ++ * Get the current internal server tick ++ * ++ * @return Current tick ++ */ ++ int getCurrentTick(); + // Paper end + } diff --git a/patches/api-unmapped/0185-PlayerDeathEvent-shouldDropExperience.patch b/patches/api-unmapped/0185-PlayerDeathEvent-shouldDropExperience.patch new file mode 100644 index 0000000000..f19bdcd569 --- /dev/null +++ b/patches/api-unmapped/0185-PlayerDeathEvent-shouldDropExperience.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 24 Dec 2019 00:35:31 +0000 +Subject: [PATCH] PlayerDeathEvent#shouldDropExperience + + +diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +index 7b78afe9281681cb9262fa044c1069a6121358eb..46917615ac4734bf5fa4ddea497132466eb5cc35 100644 +--- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java ++++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +@@ -1,6 +1,8 @@ + package org.bukkit.event.entity; + + import java.util.List; ++ ++import org.bukkit.GameMode; + import org.bukkit.entity.Player; + import org.bukkit.inventory.ItemStack; + import org.jetbrains.annotations.NotNull; +@@ -18,6 +20,8 @@ public class PlayerDeathEvent extends EntityDeathEvent { + private boolean keepLevel = false; + private boolean keepInventory = false; + // Paper start ++ private boolean doExpDrop; ++ + public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage) { + this(player, drops, droppedExp, 0, adventure$deathMessage, null); + } +@@ -27,12 +31,17 @@ public class PlayerDeathEvent extends EntityDeathEvent { + } + + public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage) { ++ this(player, drops, droppedExp, newExp, newTotalExp, newLevel, adventure$deathMessage, deathMessage, true); ++ } ++ ++ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage, boolean doExpDrop) { + super(player, drops, droppedExp); + this.newExp = newExp; + this.newTotalExp = newTotalExp; + this.newLevel = newLevel; + this.deathMessage = deathMessage; + this.adventure$deathMessage = adventure$deathMessage; ++ this.doExpDrop = doExpDrop; + } + // Paper end + +@@ -47,6 +56,11 @@ public class PlayerDeathEvent extends EntityDeathEvent { + + @Deprecated // Paper + public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final String deathMessage) { ++ this(player, drops, droppedExp, newExp, newTotalExp, newLevel, deathMessage, true); ++ } ++ ++ @Deprecated // Paper ++ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final String deathMessage, boolean doExpDrop) { + super(player, drops, droppedExp); + this.newExp = newExp; + this.newTotalExp = newTotalExp; +@@ -88,6 +102,20 @@ public class PlayerDeathEvent extends EntityDeathEvent { + public List getItemsToKeep() { + return itemsToKeep; + } ++ ++ /** ++ * @return should experience be dropped from this death ++ */ ++ public boolean shouldDropExperience() { ++ return doExpDrop; ++ } ++ ++ /** ++ * @param doExpDrop sets if experience should be dropped from this death ++ */ ++ public void setShouldDropExperience(boolean doExpDrop) { ++ this.doExpDrop = doExpDrop; ++ } + // Paper end + + @NotNull diff --git a/patches/api-unmapped/0186-Add-effect-to-block-break-naturally.patch b/patches/api-unmapped/0186-Add-effect-to-block-break-naturally.patch new file mode 100644 index 0000000000..7c52aaa446 --- /dev/null +++ b/patches/api-unmapped/0186-Add-effect-to-block-break-naturally.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 2 Jan 2020 12:25:16 -0600 +Subject: [PATCH] Add effect to block break naturally + + +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index d4ba9c2b858204825d47fd6e91dab8c003df085a..f8c599718143fe638de422fd4625f353ee6c54ae 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -469,6 +469,18 @@ public interface Block extends Metadatable { + */ + boolean breakNaturally(@Nullable ItemStack tool); + ++ // Paper start ++ /** ++ * Breaks the block and spawns items as if a player had digged it with a ++ * specific tool ++ * ++ * @param tool The tool or item in hand used for digging ++ * @param triggerEffect Play the block break particle effect and sound ++ * @return true if the block was destroyed ++ */ ++ boolean breakNaturally(@NotNull ItemStack tool, boolean triggerEffect); ++ // Paper end ++ + /** + * Simulate bone meal application to this block (if possible). + * diff --git a/patches/api-unmapped/0187-Add-ThrownEggHatchEvent.patch b/patches/api-unmapped/0187-Add-ThrownEggHatchEvent.patch new file mode 100644 index 0000000000..f605a2a11b --- /dev/null +++ b/patches/api-unmapped/0187-Add-ThrownEggHatchEvent.patch @@ -0,0 +1,129 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 9 Feb 2020 00:19:08 -0600 +Subject: [PATCH] Add ThrownEggHatchEvent + +Adds a new event similar to PlayerEggThrowEvent, but without the Player requirement +(dispensers can throw eggs to hatch them, too). + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ThrownEggHatchEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ThrownEggHatchEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..085d77dde83d6ed13eb83f23cf3e51d380187c9c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/ThrownEggHatchEvent.java +@@ -0,0 +1,115 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Egg; ++import org.bukkit.entity.EntityType; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a thrown egg might hatch. ++ *

    ++ * This event fires for all thrown eggs that may hatch, players, dispensers, etc. ++ */ ++public class ThrownEggHatchEvent extends Event { ++ private static final HandlerList handlers = new HandlerList(); ++ private final Egg egg; ++ private boolean hatching; ++ private EntityType hatchType; ++ private byte numHatches; ++ ++ public ThrownEggHatchEvent(@NotNull final Egg egg, final boolean hatching, final byte numHatches, @NotNull final EntityType hatchingType) { ++ this.egg = egg; ++ this.hatching = hatching; ++ this.numHatches = numHatches; ++ this.hatchType = hatchingType; ++ } ++ ++ /** ++ * Gets the egg involved in this event. ++ * ++ * @return the egg involved in this event ++ */ ++ @NotNull ++ public Egg getEgg() { ++ return egg; ++ } ++ ++ /** ++ * Gets whether the egg is hatching or not. Will be what the server ++ * would've done without interaction. ++ * ++ * @return boolean Whether the egg is going to hatch or not ++ */ ++ public boolean isHatching() { ++ return hatching; ++ } ++ ++ /** ++ * Sets whether the egg will hatch or not. ++ * ++ * @param hatching true if you want the egg to hatch, false if you want it ++ * not to ++ */ ++ public void setHatching(boolean hatching) { ++ this.hatching = hatching; ++ } ++ ++ /** ++ * Get the type of the mob being hatched (EntityType.CHICKEN by default) ++ * ++ * @return The type of the mob being hatched by the egg ++ */ ++ @NotNull ++ public EntityType getHatchingType() { ++ return hatchType; ++ } ++ ++ /** ++ * Change the type of mob being hatched by the egg ++ * ++ * @param hatchType The type of the mob being hatched by the egg ++ */ ++ public void setHatchingType(@NotNull EntityType hatchType) { ++ if (!hatchType.isSpawnable()) throw new IllegalArgumentException("Can't spawn that entity type from an egg!"); ++ this.hatchType = hatchType; ++ } ++ ++ /** ++ * Get the number of mob hatches from the egg. By default the number will ++ * be the number the server would've done ++ *

      ++ *
    • 7/8 chance of being 0 ++ *
    • 31/256 ~= 1/8 chance to be 1 ++ *
    • 1/256 chance to be 4 ++ *
    ++ * ++ * @return The number of mobs going to be hatched by the egg ++ */ ++ public byte getNumHatches() { ++ return numHatches; ++ } ++ ++ /** ++ * Change the number of mobs coming out of the hatched egg ++ *

    ++ * The boolean hatching will override this number. Ie. If hatching = ++ * false, this number will not matter ++ * ++ * @param numHatches The number of mobs coming out of the egg ++ */ ++ public void setNumHatches(byte numHatches) { ++ this.numHatches = numHatches; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0188-Entity-Jump-API.patch b/patches/api-unmapped/0188-Entity-Jump-API.patch new file mode 100644 index 0000000000..dd4991158c --- /dev/null +++ b/patches/api-unmapped/0188-Entity-Jump-API.patch @@ -0,0 +1,88 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 8 Feb 2020 23:26:18 -0600 +Subject: [PATCH] Entity Jump API + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityJumpEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityJumpEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f0067c2e953d18e1a33536980071ba3f0152ecb4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityJumpEvent.java +@@ -0,0 +1,46 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when an entity jumps ++ *

    ++ * Cancelling the event will stop the entity from jumping ++ */ ++public class EntityJumpEvent extends EntityEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean canceled; ++ ++ public EntityJumpEvent(@NotNull LivingEntity entity) { ++ super(entity); ++ } ++ ++ @NotNull ++ @Override ++ public LivingEntity getEntity() { ++ return (LivingEntity) entity; ++ } ++ ++ public boolean isCancelled() { ++ return canceled; ++ } ++ ++ public void setCancelled(boolean cancel) { ++ canceled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index ac6921093457cee6d01fd27690c8bb6034b4af53..a46379b3a777a9071b0b13357bbd6af40dbfb569 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -795,5 +795,25 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + */ + @NotNull + org.bukkit.inventory.EquipmentSlot getHandRaised(); ++ ++ /** ++ * Get entity jump state. ++ *

    ++ * Jump state will be true when the entity has been marked to jump. ++ * ++ * @return entity jump state. ++ */ ++ boolean isJumping(); ++ ++ /** ++ * Set entity jump state ++ *

    ++ * Setting to true will mark the entity to jump. ++ *

    ++ * Setting to false will unmark the entity to jump but will not stop a jump already in-progress. ++ * ++ * @param jumping entity jump state ++ */ ++ void setJumping(boolean jumping); + // Paper end + } diff --git a/patches/api-unmapped/0189-add-hand-to-BlockMultiPlaceEvent.patch b/patches/api-unmapped/0189-add-hand-to-BlockMultiPlaceEvent.patch new file mode 100644 index 0000000000..f61bddb960 --- /dev/null +++ b/patches/api-unmapped/0189-add-hand-to-BlockMultiPlaceEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Sun, 1 Mar 2020 22:43:34 +0100 +Subject: [PATCH] add hand to BlockMultiPlaceEvent + + +diff --git a/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java b/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java +index fe2ec79dd6084509cb8cbb8155a356f4162466fd..8460aa4f5e211fb0a6ab11f7487d38dba927e1da 100644 +--- a/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java +@@ -18,9 +18,17 @@ import org.jetbrains.annotations.NotNull; + public class BlockMultiPlaceEvent extends BlockPlaceEvent { + private final List states; + ++ @Deprecated // Paper + public BlockMultiPlaceEvent(@NotNull List states, @NotNull Block clicked, @NotNull ItemStack itemInHand, @NotNull Player thePlayer, boolean canBuild) { +- super(states.get(0).getBlock(), states.get(0), clicked, itemInHand, thePlayer, canBuild); ++ //Paper start - add hand to BlockMultiPlaceEvent ++ this(states, clicked, itemInHand, thePlayer, canBuild, org.bukkit.inventory.EquipmentSlot.HAND); ++ } ++ ++ ++ public BlockMultiPlaceEvent(@NotNull List states, @NotNull Block clicked, @NotNull ItemStack itemInHand, @NotNull Player thePlayer, boolean canBuild, @NotNull org.bukkit.inventory.EquipmentSlot hand) { ++ super(states.get(0).getBlock(), states.get(0), clicked, itemInHand, thePlayer, canBuild, hand); + this.states = ImmutableList.copyOf(states); ++ //Paper end + } + + /** diff --git a/patches/api-unmapped/0190-Add-tick-times-API.patch b/patches/api-unmapped/0190-Add-tick-times-API.patch new file mode 100644 index 0000000000..a4ae8d485c --- /dev/null +++ b/patches/api-unmapped/0190-Add-tick-times-API.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 5 Apr 2020 22:22:58 -0500 +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 49bf621a2c0e5e9641b334a42b2769944c991d5d..4bae8a4387b86c868149f06b490ef6dfced2ff41 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1590,6 +1590,25 @@ public final class Bukkit { + public static double[] getTPS() { + return server.getTPS(); + } ++ ++ /** ++ * Get a sample of the servers last tick times (in nanos) ++ * ++ * @return A sample of the servers last tick times (in nanos) ++ */ ++ @NotNull ++ public static long[] getTickTimes() { ++ return server.getTickTimes(); ++ } ++ ++ /** ++ * Get the average tick time (in millis) ++ * ++ * @return Average tick time (in millis) ++ */ ++ public static double getAverageTickTime() { ++ return server == null ? 0D : server.getAverageTickTime(); ++ } + // Paper end + + /** +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index e448ae78304974f7664b7ef18568a547833ece9f..bea7ffdb00e6de1391e9143901c62f0aceaaf727 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1345,6 +1345,21 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + */ + @NotNull + public double[] getTPS(); ++ ++ /** ++ * Get a sample of the servers last tick times (in nanos) ++ * ++ * @return A sample of the servers last tick times (in nanos) ++ */ ++ @NotNull ++ long[] getTickTimes(); ++ ++ /** ++ * Get the average tick time (in millis) ++ * ++ * @return Average tick time (in millis) ++ */ ++ double getAverageTickTime(); + // Paper end + + // Paper start diff --git a/patches/api-unmapped/0191-Expose-MinecraftServer-isRunning.patch b/patches/api-unmapped/0191-Expose-MinecraftServer-isRunning.patch new file mode 100644 index 0000000000..33f2570121 --- /dev/null +++ b/patches/api-unmapped/0191-Expose-MinecraftServer-isRunning.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Fri, 10 Apr 2020 21:24:35 -0400 +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 4bae8a4387b86c868149f06b490ef6dfced2ff41..4dadea432c8d79b15fa126b4f0c810e9a72b4029 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1858,6 +1858,15 @@ public final class Bukkit { + public static int getCurrentTick() { + return server.getCurrentTick(); + } ++ ++ /** ++ * Checks if the server is in the process of being shutdown. ++ * ++ * @return true if server is in the process of being shutdown ++ */ ++ public static boolean isStopping() { ++ return server.isStopping(); ++ } + // Paper end + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index bea7ffdb00e6de1391e9143901c62f0aceaaf727..b92261e09790e89788560bf7c9784c8399504810 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1631,5 +1631,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + * @return Current tick + */ + int getCurrentTick(); ++ ++ /** ++ * Checks if the server is in the process of being shutdown. ++ * ++ * @return true if server is in the process of being shutdown ++ */ ++ boolean isStopping(); + // Paper end + } diff --git a/patches/api-unmapped/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch b/patches/api-unmapped/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch new file mode 100644 index 0000000000..5ca0264ed8 --- /dev/null +++ b/patches/api-unmapped/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 11 Apr 2020 21:38:59 -0400 +Subject: [PATCH] Disable Sync Events firing Async errors during shutdown + +This is how it use to behave on Paper, and this is totally destroying +the ability to try to shut the server down gracefully during the +shutdown process as events firing on the watchdog thread are throwing +errors. + +This isn't an issue on Spigot + +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index a1a805004941d67abb0b9aa1721e0370c45b5289..26685f59b235ea5b4c4fb7ae21acb5149edaa2b3 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -591,7 +591,7 @@ public final class SimplePluginManager implements PluginManager { + // Paper - replace callEvent by merging to below method + if (event.isAsynchronous() && server.isPrimaryThread()) { + throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously."); +- } else if (!event.isAsynchronous() && !server.isPrimaryThread()) { ++ } else if (!event.isAsynchronous() && !server.isPrimaryThread() && !server.isStopping() ) { + throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously."); + } + diff --git a/patches/api-unmapped/0193-Make-JavaPluginLoader-thread-safe.patch b/patches/api-unmapped/0193-Make-JavaPluginLoader-thread-safe.patch new file mode 100644 index 0000000000..be66a6a695 --- /dev/null +++ b/patches/api-unmapped/0193-Make-JavaPluginLoader-thread-safe.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Wed, 15 Apr 2020 01:24:55 -0400 +Subject: [PATCH] Make JavaPluginLoader thread-safe + + +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index f26303315c9c93356f0b04440136855dd54d32b7..ce751577623eaad0f31e2eb7bf0842d1ab73e845 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -52,6 +52,8 @@ import org.yaml.snakeyaml.error.YAMLException; + public final class JavaPluginLoader implements PluginLoader { + final Server server; + private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; ++ private final Map classLoadLock = new java.util.HashMap(); // Paper ++ private final Map classLoadLockCount = new java.util.HashMap(); // Paper + private final List loaders = new CopyOnWriteArrayList(); + private final LibraryLoader libraryLoader; + +@@ -201,12 +203,33 @@ public final class JavaPluginLoader implements PluginLoader { + + @Nullable + Class getClassByName(final String name, boolean resolve, PluginDescriptionFile description) { ++ // Paper start - make MT safe ++ java.util.concurrent.locks.ReentrantReadWriteLock lock; ++ synchronized (classLoadLock) { ++ lock = classLoadLock.computeIfAbsent(name, (x) -> new java.util.concurrent.locks.ReentrantReadWriteLock()); ++ classLoadLockCount.compute(name, (x, prev) -> prev != null ? prev + 1 : 1); ++ } ++ lock.writeLock().lock();try { ++ // Paper end + for (PluginClassLoader loader : loaders) { + try { + return loader.loadClass0(name, resolve, false, ((SimplePluginManager) server.getPluginManager()).isTransitiveDepend(description, loader.plugin.getDescription())); + } catch (ClassNotFoundException cnfe) { + } + } ++ // Paper start - make MT safe ++ } finally { ++ synchronized (classLoadLock) { ++ lock.writeLock().unlock(); ++ if (classLoadLockCount.get(name) == 1) { ++ classLoadLock.remove(name); ++ classLoadLockCount.remove(name); ++ } else { ++ classLoadLockCount.compute(name, (x, prev) -> prev - 1); ++ } ++ } ++ } ++ // Paper end + return null; + } + diff --git a/patches/api-unmapped/0194-Add-Player-Client-Options-API.patch b/patches/api-unmapped/0194-Add-Player-Client-Options-API.patch new file mode 100644 index 0000000000..c156119b15 --- /dev/null +++ b/patches/api-unmapped/0194-Add-Player-Client-Options-API.patch @@ -0,0 +1,202 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Mon, 20 Jan 2020 21:38:34 +0100 +Subject: [PATCH] Add Player Client Options API + + +diff --git a/src/main/java/com/destroystokyo/paper/ClientOption.java b/src/main/java/com/destroystokyo/paper/ClientOption.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9dad814cf51bc59ec5dfbf14474fea6557de38aa +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/ClientOption.java +@@ -0,0 +1,33 @@ ++package com.destroystokyo.paper; ++ ++import org.jetbrains.annotations.NotNull; ++ ++import org.bukkit.inventory.MainHand; ++ ++public final class ClientOption { ++ ++ public static final ClientOption SKIN_PARTS = new ClientOption<>(SkinParts.class); ++ public static final ClientOption CHAT_COLORS_ENABLED = new ClientOption<>(Boolean.class); ++ public static final ClientOption CHAT_VISIBILITY = new ClientOption<>(ChatVisibility.class); ++ public static final ClientOption LOCALE = new ClientOption<>(String.class); ++ public static final ClientOption MAIN_HAND = new ClientOption<>(MainHand.class); ++ public static final ClientOption VIEW_DISTANCE = new ClientOption<>(Integer.class); ++ ++ private final Class type; ++ ++ private ClientOption(@NotNull Class type) { ++ this.type = type; ++ } ++ ++ @NotNull ++ public Class getType() { ++ return type; ++ } ++ ++ public enum ChatVisibility { ++ FULL, ++ SYSTEM, ++ HIDDEN, ++ UNKNOWN ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/SkinParts.java b/src/main/java/com/destroystokyo/paper/SkinParts.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4a0c39405d4fbed457787e3c6ded4cc6591bc8c2 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/SkinParts.java +@@ -0,0 +1,20 @@ ++package com.destroystokyo.paper; ++ ++public interface SkinParts { ++ ++ boolean hasCapeEnabled(); ++ ++ boolean hasJacketEnabled(); ++ ++ boolean hasLeftSleeveEnabled(); ++ ++ boolean hasRightSleeveEnabled(); ++ ++ boolean hasLeftPantsEnabled(); ++ ++ boolean hasRightPantsEnabled(); ++ ++ boolean hasHatsEnabled(); ++ ++ int getRaw(); ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerClientOptionsChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerClientOptionsChangeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f7f171c4ee0b8339b2f8fbe82442d65f17202f28 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerClientOptionsChangeEvent.java +@@ -0,0 +1,100 @@ ++package com.destroystokyo.paper.event.player; ++ ++import com.destroystokyo.paper.ClientOption; ++import com.destroystokyo.paper.ClientOption.ChatVisibility; ++import com.destroystokyo.paper.SkinParts; ++ ++import org.jetbrains.annotations.NotNull; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.MainHand; ++ ++/** ++ * Called when the player changes his client settings ++ */ ++public class PlayerClientOptionsChangeEvent extends PlayerEvent { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ private final String locale; ++ private final int viewDistance; ++ private final ChatVisibility chatVisibility; ++ private final boolean chatColors; ++ private final SkinParts skinparts; ++ private final MainHand mainHand; ++ ++ public PlayerClientOptionsChangeEvent(@NotNull Player player, @NotNull String locale, int viewDistance, @NotNull ChatVisibility chatVisibility, boolean chatColors, @NotNull SkinParts skinParts, @NotNull MainHand mainHand) { ++ super(player); ++ this.locale = locale; ++ this.viewDistance = viewDistance; ++ this.chatVisibility = chatVisibility; ++ this.chatColors = chatColors; ++ this.skinparts = skinParts; ++ this.mainHand = mainHand; ++ } ++ ++ @NotNull ++ public String getLocale() { ++ return locale; ++ } ++ ++ public boolean hasLocaleChanged() { ++ return !locale.equals(player.getClientOption(ClientOption.LOCALE)); ++ } ++ ++ public int getViewDistance() { ++ return viewDistance; ++ } ++ ++ public boolean hasViewDistanceChanged() { ++ return viewDistance != player.getClientOption(ClientOption.VIEW_DISTANCE); ++ } ++ ++ @NotNull ++ public ChatVisibility getChatVisibility() { ++ return chatVisibility; ++ } ++ ++ public boolean hasChatVisibilityChanged() { ++ return chatVisibility != player.getClientOption(ClientOption.CHAT_VISIBILITY); ++ } ++ ++ public boolean hasChatColorsEnabled() { ++ return chatColors; ++ } ++ ++ public boolean hasChatColorsEnabledChanged() { ++ return chatColors != player.getClientOption(ClientOption.CHAT_COLORS_ENABLED); ++ } ++ ++ @NotNull ++ public SkinParts getSkinParts() { ++ return skinparts; ++ } ++ ++ public boolean hasSkinPartsChanged() { ++ return skinparts.getRaw() != player.getClientOption(ClientOption.SKIN_PARTS).getRaw(); ++ } ++ ++ @NotNull ++ public MainHand getMainHand() { ++ return mainHand; ++ } ++ ++ public boolean hasMainHandChanged() { ++ return mainHand != player.getClientOption(ClientOption.MAIN_HAND); ++ } ++ ++ @Override ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index ec87c78d0f9379511467b6d13b9cdfa4c19d15ca..2530c811f52f51d6338900221b4681c952c1c752 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -2,6 +2,7 @@ package org.bukkit.entity; + + import java.net.InetSocketAddress; + import java.util.UUID; ++import com.destroystokyo.paper.ClientOption; // Paper + import com.destroystokyo.paper.Title; // Paper + import net.kyori.adventure.text.Component; + import com.destroystokyo.paper.profile.PlayerProfile; // Paper +@@ -1909,6 +1910,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * Reset the cooldown counter to 0, effectively starting the cooldown period. + */ + void resetCooldown(); ++ ++ /** ++ * @return the client option value of the player ++ */ ++ @NotNull ++ T getClientOption(@NotNull ClientOption option); + // Paper end + + // Spigot start diff --git a/patches/api-unmapped/0195-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/api-unmapped/0195-Add-PlayerAttackEntityCooldownResetEvent.patch new file mode 100644 index 0000000000..15fa2db392 --- /dev/null +++ b/patches/api-unmapped/0195-Add-PlayerAttackEntityCooldownResetEvent.patch @@ -0,0 +1,88 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: nossr50 +Date: Thu, 26 Mar 2020 19:30:58 -0700 +Subject: [PATCH] Add PlayerAttackEntityCooldownResetEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerAttackEntityCooldownResetEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerAttackEntityCooldownResetEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ebdebe7b6ec6ed5aadc7ee925ba0147e61e6bc84 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerAttackEntityCooldownResetEvent.java +@@ -0,0 +1,76 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when processing a player's attack on an entity when the player's attack strength cooldown is reset ++ */ ++public class PlayerAttackEntityCooldownResetEvent extends PlayerEvent implements Cancellable { ++ ++ private final float cooledAttackStrength; ++ private boolean cancel = false; ++ private static final HandlerList handlers = new HandlerList(); ++ @NotNull private final Entity attackedEntity; ++ ++ public PlayerAttackEntityCooldownResetEvent(@NotNull Player who, @NotNull Entity attackedEntity, float cooledAttackStrength) { ++ super(who); ++ this.attackedEntity = attackedEntity; ++ this.cooledAttackStrength = cooledAttackStrength; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ public static @NotNull HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ /** ++ * Gets the cancellation state of this event. A cancelled event will not ++ * be executed in the server, but will still pass to other plugins ++ *

    ++ * If an attack cooldown event is cancelled, the players attack strength will remain at the same value instead of being reset. ++ * ++ * @return true if this event is cancelled ++ */ ++ @Override ++ public boolean isCancelled() { ++ return cancel; ++ } ++ ++ /** ++ * Cancelling this event will prevent the target player from having their cooldown reset from attacking this entity ++ * ++ * @param cancel true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancel = cancel; ++ } ++ ++ /** ++ * Get the value of the players cooldown attack strength when they initiated the attack ++ * ++ * @return returns the original player cooldown value ++ */ ++ public float getCooledAttackStrength() { ++ return cooledAttackStrength; ++ } ++ ++ /** ++ * Returns the entity attacked by the player ++ * ++ * @return the entity attacked by the player ++ */ ++ @NotNull ++ public Entity getAttackedEntity() { ++ return attackedEntity; ++ } ++} diff --git a/patches/api-unmapped/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch b/patches/api-unmapped/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch new file mode 100644 index 0000000000..800d5364e2 --- /dev/null +++ b/patches/api-unmapped/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Wesley Smith +Date: Fri, 24 Apr 2020 18:30:26 -0400 +Subject: [PATCH] Fix Potion#toItemStack swapping the extended and upgraded + constructor values. + +While the Potion class is deprecated, it is still used in some plugins for cross-version potion handling. This issue has existed for a long time, and has caused many heaches along the way. + +diff --git a/src/main/java/org/bukkit/potion/Potion.java b/src/main/java/org/bukkit/potion/Potion.java +index b9dbbfd07dea643d7ac749822548571968adaa94..ac02ae4fc179483b4ac3d1adc41684a8426197eb 100644 +--- a/src/main/java/org/bukkit/potion/Potion.java ++++ b/src/main/java/org/bukkit/potion/Potion.java +@@ -267,7 +267,7 @@ public class Potion { + } + ItemStack itemStack = new ItemStack(material, amount); + PotionMeta meta = (PotionMeta) itemStack.getItemMeta(); +- meta.setBasePotionData(new PotionData(type, level == 2, extended)); ++ meta.setBasePotionData(new PotionData(type, extended, level == 2)); // Paper - fix swapped values + itemStack.setItemMeta(meta); + return itemStack; + } diff --git a/patches/api-unmapped/0197-Villager-Restocks-API.patch b/patches/api-unmapped/0197-Villager-Restocks-API.patch new file mode 100644 index 0000000000..e2dcfc3144 --- /dev/null +++ b/patches/api-unmapped/0197-Villager-Restocks-API.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: zbk +Date: Sun, 26 Apr 2020 23:49:03 -0400 +Subject: [PATCH] Villager Restocks API + + +diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java +index ef48ad9b28750ab7b33071f6b8e354e922731909..d1579153092c1b80350155110f1b9926b1a1ef57 100644 +--- a/src/main/java/org/bukkit/entity/Villager.java ++++ b/src/main/java/org/bukkit/entity/Villager.java +@@ -77,6 +77,20 @@ public interface Villager extends AbstractVillager { + */ + public void setVillagerExperience(int experience); + ++ // Paper start ++ /** ++ * Gets the amount of times a villager has restocked their trades today ++ * @return The amount of trade restocks. ++ */ ++ public int getRestocksToday(); ++ ++ /** ++ * Sets the amount of times a villager has restocked their trades today ++ * @param restocksToday new restock count ++ */ ++ public void setRestocksToday(int restocksToday); ++ // Paper end ++ + /** + * Attempts to make this villager sleep at the given location. + *
    diff --git a/patches/api-unmapped/0198-Expose-game-version.patch b/patches/api-unmapped/0198-Expose-game-version.patch new file mode 100644 index 0000000000..560d2370a1 --- /dev/null +++ b/patches/api-unmapped/0198-Expose-game-version.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Fri, 1 May 2020 17:39:02 +0300 +Subject: [PATCH] Expose game version + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 86ac6702b3aeab1126b2b2879b87ef3883793d44..12214ce2af7363d40cf44652e46f05c5c1f2fe5a 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -118,6 +118,18 @@ public final class Bukkit { + return server.getBukkitVersion(); + } + ++ // Paper start - expose game version ++ /** ++ * Gets the version of game this server implements ++ * ++ * @return version of game ++ */ ++ @NotNull ++ public static String getMinecraftVersion() { ++ return server.getMinecraftVersion(); ++ } ++ // Paper end ++ + /** + * 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 16a74b834c4d4b907f9b11ccf9ef9804514df224..360decea2eb6de4c567fa4cceea8f19bceff6823 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -97,6 +97,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @NotNull + public String getBukkitVersion(); + ++ // Paper start - expose game version ++ /** ++ * Gets the version of game this server implements ++ * ++ * @return version of game ++ */ ++ @NotNull ++ String getMinecraftVersion(); ++ // Paper end ++ + /** + * Gets a view of all currently logged in players. This {@linkplain + * Collections#unmodifiableCollection(Collection) view} is a reused diff --git a/patches/api-unmapped/0199-Add-item-slot-convenience-methods.patch b/patches/api-unmapped/0199-Add-item-slot-convenience-methods.patch new file mode 100644 index 0000000000..3b3612713f --- /dev/null +++ b/patches/api-unmapped/0199-Add-item-slot-convenience-methods.patch @@ -0,0 +1,283 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Sat, 25 Apr 2020 23:31:28 +0200 +Subject: [PATCH] Add item slot convenience methods + + +diff --git a/src/main/java/org/bukkit/inventory/AnvilInventory.java b/src/main/java/org/bukkit/inventory/AnvilInventory.java +index 4af562426aa38faeb6822abb0c878a3ac346b383..b95e563b5454306a9188ae3295309ee86a756477 100644 +--- a/src/main/java/org/bukkit/inventory/AnvilInventory.java ++++ b/src/main/java/org/bukkit/inventory/AnvilInventory.java +@@ -49,4 +49,64 @@ public interface AnvilInventory extends Inventory { + * @param levels the maximum experience cost + */ + void setMaximumRepairCost(int levels); ++ ++ // Paper start ++ /** ++ * Gets the item in the left input slot. ++ * ++ * @return item in the first slot ++ */ ++ @Nullable ++ default ItemStack getFirstItem() { ++ return getItem(0); ++ } ++ ++ /** ++ * Sets the item in the left input slot. ++ * ++ * @param firstItem item to set ++ */ ++ default void setFirstItem(@Nullable ItemStack firstItem) { ++ setItem(0, firstItem); ++ } ++ ++ /** ++ * Gets the item in the right input slot. ++ * ++ * @return item in the second slot ++ */ ++ @Nullable ++ default ItemStack getSecondItem() { ++ return getItem(1); ++ } ++ ++ /** ++ * Sets the item in the right input slot. ++ * ++ * @param secondItem item to set ++ */ ++ default void setSecondItem(@Nullable ItemStack secondItem) { ++ setItem(1, secondItem); ++ } ++ ++ /** ++ * Gets the item in the result slot. ++ * ++ * @return item in the result slot ++ */ ++ @Nullable ++ default ItemStack getResult() { ++ return getItem(2); ++ } ++ ++ /** ++ * Sets the item in the result slot. ++ * Note that the client might not be able to take out the item if it does not match the input items. ++ * ++ * @param result item to set ++ */ ++ default void setResult(@Nullable ItemStack result) { ++ setItem(2, result); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/GrindstoneInventory.java b/src/main/java/org/bukkit/inventory/GrindstoneInventory.java +index 9048892c8768c6b4d6cea03da73339f13bfbe82e..1c750108f55a0a31ad23433b333e0ea486a63ff2 100644 +--- a/src/main/java/org/bukkit/inventory/GrindstoneInventory.java ++++ b/src/main/java/org/bukkit/inventory/GrindstoneInventory.java +@@ -1,6 +1,68 @@ + package org.bukkit.inventory; + ++import org.jetbrains.annotations.Nullable; // Paper ++ + /** + * Interface to the inventory of a Grindstone. + */ +-public interface GrindstoneInventory extends Inventory { } ++public interface GrindstoneInventory extends Inventory { ++ ++ // Paper start ++ /** ++ * Gets the upper input item. ++ * ++ * @return upper input item ++ */ ++ @Nullable ++ default ItemStack getUpperItem() { ++ return getItem(0); ++ } ++ ++ /** ++ * Sets the upper input item. ++ * ++ * @param upperItem item to set ++ */ ++ default void setUpperItem(@Nullable ItemStack upperItem) { ++ setItem(0, upperItem); ++ } ++ ++ /** ++ * Gets the lower input item. ++ * ++ * @return lower input item ++ */ ++ @Nullable ++ default ItemStack getLowerItem() { ++ return getItem(1); ++ } ++ ++ /** ++ * Sets the lower input item. ++ * ++ * @param lowerItem item to set ++ */ ++ default void setLowerItem(@Nullable ItemStack lowerItem) { ++ setItem(1, lowerItem); ++ } ++ ++ /** ++ * Gets the result. ++ * ++ * @return result ++ */ ++ @Nullable ++ default ItemStack getResult() { ++ return getItem(2); ++ } ++ ++ /** ++ * Sets the result. ++ * ++ * @param result item to set ++ */ ++ default void setResult(@Nullable ItemStack result) { ++ setItem(2, result); ++ } ++ // Paper end ++} +diff --git a/src/main/java/org/bukkit/inventory/LecternInventory.java b/src/main/java/org/bukkit/inventory/LecternInventory.java +index 4a0c43acc2714e095973eb78536041bb1a179ddc..acf2244f77133df53eb5f862c8e713c85192f13d 100644 +--- a/src/main/java/org/bukkit/inventory/LecternInventory.java ++++ b/src/main/java/org/bukkit/inventory/LecternInventory.java +@@ -11,4 +11,25 @@ public interface LecternInventory extends Inventory { + @Nullable + @Override + public Lectern getHolder(); ++ ++ // Paper start ++ /** ++ * Gets the lectern's held book. ++ * ++ * @return book set in the lectern ++ */ ++ @Nullable ++ default ItemStack getBook() { ++ return getItem(0); ++ } ++ ++ /** ++ * Sets the lectern's held book. ++ * ++ * @param book the new book ++ */ ++ default void setBook(@Nullable ItemStack book) { ++ setItem(0, book); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/SmithingInventory.java b/src/main/java/org/bukkit/inventory/SmithingInventory.java +index 96d526b7b153e56c9a97de42ce3270b6638510e4..a41ca6bd2672db2810dd70c4925b84a4f081af05 100644 +--- a/src/main/java/org/bukkit/inventory/SmithingInventory.java ++++ b/src/main/java/org/bukkit/inventory/SmithingInventory.java +@@ -30,4 +30,44 @@ public interface SmithingInventory extends Inventory { + */ + @Nullable + Recipe getRecipe(); ++ ++ // Paper start ++ /** ++ * Gets the input equipment (first slot). ++ * ++ * @return input equipment item ++ */ ++ @Nullable ++ default ItemStack getInputEquipment() { ++ return getItem(0); ++ } ++ ++ /** ++ * Sets the input equipment (first slot). ++ * ++ * @param itemStack item to set ++ */ ++ default void setInputEquipment(@Nullable ItemStack itemStack) { ++ setItem(0, itemStack); ++ } ++ ++ /** ++ * Gets the input mineral (second slot). ++ * ++ * @return input mineral item ++ */ ++ @Nullable ++ default ItemStack getInputMineral() { ++ return getItem(1); ++ } ++ ++ /** ++ * Sets the input mineral (second slot). ++ * ++ * @param itemStack item to set ++ */ ++ default void setInputMineral(@Nullable ItemStack itemStack) { ++ setItem(1, itemStack); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/StonecutterInventory.java b/src/main/java/org/bukkit/inventory/StonecutterInventory.java +index dbb034fae3b8bfaf40e6341460e274c21e321a3b..e7a8e7188bf8b9840de56dc80c2b79d64a9389cb 100644 +--- a/src/main/java/org/bukkit/inventory/StonecutterInventory.java ++++ b/src/main/java/org/bukkit/inventory/StonecutterInventory.java +@@ -1,6 +1,49 @@ + package org.bukkit.inventory; + ++import org.jetbrains.annotations.Nullable; // Paper ++ + /** + * Interface to the inventory of a Stonecutter. + */ +-public interface StonecutterInventory extends Inventory { } ++public interface StonecutterInventory extends Inventory { ++ ++ // Paper start ++ /** ++ * Gets the input item. ++ * ++ * @return input item ++ */ ++ @Nullable ++ default ItemStack getInputItem() { ++ return getItem(0); ++ } ++ ++ /** ++ * Sets the input item. ++ * ++ * @param itemStack item to set ++ */ ++ default void setInputItem(@Nullable ItemStack itemStack) { ++ setItem(0, itemStack); ++ } ++ ++ /** ++ * Gets the result item. ++ * ++ * @return result ++ */ ++ @Nullable ++ default ItemStack getResult() { ++ return getItem(1); ++ } ++ ++ /** ++ * Sets the result item. ++ * ++ * @param itemStack item to set ++ */ ++ default void setResult(@Nullable ItemStack itemStack) { ++ setItem(1, itemStack); ++ } ++ // Paper end ++} diff --git a/patches/api-unmapped/0200-Add-Mob-Goal-API.patch b/patches/api-unmapped/0200-Add-Mob-Goal-API.patch new file mode 100644 index 0000000000..24855e7426 --- /dev/null +++ b/patches/api-unmapped/0200-Add-Mob-Goal-API.patch @@ -0,0 +1,481 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Fri, 3 Jan 2020 16:24:46 +0100 +Subject: [PATCH] Add Mob Goal API + + +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/Goal.java b/src/main/java/com/destroystokyo/paper/entity/ai/Goal.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c57c5416c88e2070a082403ab0dda9d7f08d2a57 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/Goal.java +@@ -0,0 +1,66 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.EnumSet; ++ ++import org.bukkit.entity.Mob; ++ ++/** ++ * Represents an AI goal of an entity ++ */ ++public interface Goal { ++ ++ /** ++ * Checks if this goal should be activated ++ * ++ * @return if this goal should be activated ++ */ ++ boolean shouldActivate(); ++ ++ /** ++ * Checks if this goal should stay active, defaults to {@link Goal#shouldActivate()} ++ * ++ * @return if this goal should stay active ++ */ ++ default boolean shouldStayActive() { ++ return shouldActivate(); ++ } ++ ++ /** ++ * Called when this goal gets activated ++ */ ++ default void start() { ++ } ++ ++ /** ++ * Called when this goal gets stopped ++ */ ++ default void stop() { ++ } ++ ++ /** ++ * Called each tick the goal is activated ++ */ ++ default void tick() { ++ } ++ ++ /** ++ * A unique key that identifies this type of goal. Plugins should use their own namespace, not the minecraft ++ * namespace. Additionally, this key also specifies to what mobs this goal can be applied to ++ * ++ * @return the goal key ++ */ ++ @NotNull ++ GoalKey getKey(); ++ ++ /** ++ * Returns a list of all applicable flags for this goal.
    ++ * ++ * This method is only called on construction. ++ * ++ * @return the subtypes. ++ */ ++ @NotNull ++ EnumSet getTypes(); ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/GoalKey.java b/src/main/java/com/destroystokyo/paper/entity/ai/GoalKey.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9cd98c6fcfa3eb439d9013ef76ef4661175a0e5a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/GoalKey.java +@@ -0,0 +1,64 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import com.google.common.base.Objects; ++ ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.StringJoiner; ++ ++import org.bukkit.NamespacedKey; ++import org.bukkit.entity.Mob; ++ ++/** ++ * ++ * Used to identify a Goal. Consists of a {@link NamespacedKey} and the type of mob the goal can be applied to ++ * ++ * @param the type of mob the goal can be applied to ++ */ ++public class GoalKey { ++ ++ private final Class entityClass; ++ private final NamespacedKey namespacedKey; ++ ++ private GoalKey(@NotNull Class entityClass, @NotNull NamespacedKey namespacedKey) { ++ this.entityClass = entityClass; ++ this.namespacedKey = namespacedKey; ++ } ++ ++ @NotNull ++ public Class getEntityClass() { ++ return entityClass; ++ } ++ ++ @NotNull ++ public NamespacedKey getNamespacedKey() { ++ return namespacedKey; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ GoalKey goalKey = (GoalKey) o; ++ return Objects.equal(entityClass, goalKey.entityClass) && ++ Objects.equal(namespacedKey, goalKey.namespacedKey); ++ } ++ ++ @Override ++ public int hashCode() { ++ return Objects.hashCode(entityClass, namespacedKey); ++ } ++ ++ @Override ++ public String toString() { ++ return new StringJoiner(", ", GoalKey.class.getSimpleName() + "[", "]") ++ .add("entityClass=" + entityClass) ++ .add("namespacedKey=" + namespacedKey) ++ .toString(); ++ } ++ ++ @NotNull ++ public static GoalKey of(@NotNull Class entityClass, @NotNull NamespacedKey namespacedKey) { ++ return new GoalKey<>(entityClass, namespacedKey); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/GoalType.java b/src/main/java/com/destroystokyo/paper/entity/ai/GoalType.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7024c8f484d2460abf3abfe65a29771d814105ec +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/GoalType.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++/** ++ * Represents the subtype of a goal. Used by minecraft to disable certain types of goals if needed. ++ */ ++public enum GoalType { ++ ++ MOVE, ++ LOOK, ++ JUMP, ++ TARGET, ++ /** ++ * Used to map vanilla goals, that are a behavior goal but don't have a type set... ++ */ ++ UNKNOWN_BEHAVIOR, ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoals.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e21f7574763dd4f13794f91bbef192ef66a8f5e9 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoals.java +@@ -0,0 +1,50 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.Collection; ++ ++import org.bukkit.entity.Mob; ++ ++/** ++ * Represents a part of the "brain" of a mob. It tracks all tasks (running or not), allows adding and removing goals ++ */ ++public interface MobGoals { ++ ++ void addGoal(@NotNull T mob, int priority, @NotNull Goal goal); ++ ++ void removeGoal(@NotNull T mob, @NotNull Goal goal); ++ ++ void removeAllGoals(@NotNull T mob); ++ ++ void removeAllGoals(@NotNull T mob, @NotNull GoalType type); ++ ++ void removeGoal(@NotNull T mob, @NotNull GoalKey key); ++ ++ boolean hasGoal(@NotNull T mob, @NotNull GoalKey key); ++ ++ @Nullable ++ Goal getGoal(@NotNull T mob, @NotNull GoalKey key); ++ ++ @NotNull ++ Collection> getGoals(@NotNull T mob, @NotNull GoalKey key); ++ ++ @NotNull ++ Collection> getAllGoals(@NotNull T mob); ++ ++ @NotNull ++ Collection> getAllGoals(@NotNull T mob, @NotNull GoalType type); ++ ++ @NotNull ++ Collection> getAllGoalsWithout(@NotNull T mob, @NotNull GoalType type); ++ ++ @NotNull ++ Collection> getRunningGoals(@NotNull T mob); ++ ++ @NotNull ++ Collection> getRunningGoals(@NotNull T mob, @NotNull GoalType type); ++ ++ @NotNull ++ Collection> getRunningGoalsWithout(@NotNull T mob, @NotNull GoalType type); ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b42091752981a1f309ab350e9a394092cb334824 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java +@@ -0,0 +1,209 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import com.destroystokyo.paper.entity.RangedEntity; ++ ++import org.bukkit.NamespacedKey; ++import org.bukkit.entity.*; ++ ++/** ++ * Represents a vanilla goal. Plugins should never implement this.
    ++ * Generated by VanillaPathfinderTest in paper-server ++ */ ++public interface VanillaGoal extends Goal { ++ ++ GoalKey BEE_ATTACK = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_attack")); ++ GoalKey BEE_BECOME_ANGRY = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_become_angry")); ++ GoalKey BEE_ENTER_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_enter_hive")); ++ GoalKey BEE_GO_TO_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_go_to_hive")); ++ GoalKey BEE_GO_TO_KNOWN_FLOWER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_go_to_known_flower")); ++ GoalKey BEE_GROW_CROP = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_grow_crop")); ++ GoalKey BEE_HURT_BY_OTHER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_hurt_by_other")); ++ GoalKey BEE_LOCATE_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_locate_hive")); ++ GoalKey BEE_POLLINATE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_pollinate")); ++ GoalKey BEE_WANDER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_wander")); ++ GoalKey BLAZE_FIREBALL = GoalKey.of(Blaze.class, NamespacedKey.minecraft("blaze_fireball")); ++ GoalKey TEMPT_CHANCE = GoalKey.of(Cat.class, NamespacedKey.minecraft("tempt_chance")); ++ GoalKey CAT_AVOID_ENTITY = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_avoid_entity")); ++ GoalKey CAT_RELAX_ON_OWNER = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_relax_on_owner")); ++ GoalKey DOLPHIN_SWIM_TO_TREASURE = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_swim_to_treasure")); ++ GoalKey DOLPHIN_SWIM_WITH_PLAYER = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_swim_with_player")); ++ GoalKey DOLPHIN_PLAY_WITH_ITEMS = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_play_with_items")); ++ GoalKey DROWNED_ATTACK = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack")); ++ GoalKey DROWNED_GOTO_BEACH = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_goto_beach")); ++ GoalKey DROWNED_GOTO_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("drowned_goto_water")); ++ GoalKey DROWNED_SWIM_UP = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_swim_up")); ++ GoalKey DROWNED_TRIDENT_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("drowned_trident_attack")); ++ GoalKey ENDERMAN_PICKUP_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_pickup_block")); ++ GoalKey ENDERMAN_PLACE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_place_block")); ++ GoalKey PLAYER_WHO_LOOKED_AT_TARGET = GoalKey.of(Enderman.class, NamespacedKey.minecraft("player_who_looked_at_target")); ++ GoalKey ENDERMAN_FREEZE_WHEN_LOOKED_AT = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_freeze_when_looked_at")); ++ GoalKey EVOKER_ATTACK_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_attack_spell")); ++ GoalKey EVOKER_CAST_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_cast_spell")); ++ GoalKey EVOKER_SUMMON_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_summon_spell")); ++ GoalKey EVOKER_WOLOLO_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_wololo_spell")); ++ GoalKey FISH_SWIM = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_swim")); ++ GoalKey FOX_DEFEND_TRUSTED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_defend_trusted")); ++ GoalKey FOX_FACEPLANT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_faceplant")); ++ GoalKey FOX_BREED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_breed")); ++ GoalKey FOX_EAT_BERRIES = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_eat_berries")); ++ GoalKey FOX_FLOAT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_float")); ++ GoalKey FOX_FOLLOW_PARENT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_follow_parent")); ++ GoalKey FOX_LOOK_AT_PLAYER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_look_at_player")); ++ GoalKey FOX_MELEE_ATTACK = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_melee_attack")); ++ GoalKey FOX_PANIC = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_panic")); ++ GoalKey FOX_PERCH_AND_SEARCH = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_perch_and_search")); ++ GoalKey FOX_POUNCE = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_pounce")); ++ GoalKey FOX_SEARCH_FOR_ITEMS = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_search_for_items")); ++ GoalKey FOX_SLEEP = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_sleep")); ++ GoalKey FOX_STROLL_THROUGH_VILLAGE = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stroll_through_village")); ++ GoalKey FOX_SEEK_SHELTER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_seek_shelter")); ++ GoalKey FOX_STALK_PREY = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stalk_prey")); ++ GoalKey GHAST_ATTACK_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_attack_target")); ++ GoalKey GHAST_IDLE_MOVE = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_idle_move")); ++ GoalKey GHAST_MOVE_TOWARDS_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_move_towards_target")); ++ GoalKey GUARDIAN_ATTACK = GoalKey.of(Guardian.class, NamespacedKey.minecraft("guardian_attack")); ++ GoalKey RAIDER_OPEN_DOOR = GoalKey.of(Illager.class, NamespacedKey.minecraft("raider_open_door")); ++ GoalKey ILLUSIONER_BLINDNESS_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_blindness_spell")); ++ GoalKey ILLUSIONER_MIRROR_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_mirror_spell")); ++ GoalKey SPELLCASTER_CAST_SPELL = GoalKey.of(Spellcaster.class, NamespacedKey.minecraft("spellcaster_cast_spell")); ++ GoalKey LLAMA_ATTACK_WOLF = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_attack_wolf")); ++ GoalKey LLAMA_HURT_BY = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_hurt_by")); ++ GoalKey LLAMATRADER_DEFENDED_WANDERING_TRADER = GoalKey.of(TraderLlama.class, NamespacedKey.minecraft("llamatrader_defended_wandering_trader")); ++ GoalKey LONG_DISTANCE_PATROL = GoalKey.of(Monster.class, NamespacedKey.minecraft("long_distance_patrol")); ++ GoalKey OCELOT_AVOID_ENTITY = GoalKey.of(Ocelot.class, NamespacedKey.minecraft("ocelot_avoid_entity")); ++ GoalKey OCELOT_TEMPT = GoalKey.of(Ocelot.class, NamespacedKey.minecraft("ocelot_tempt")); ++ GoalKey PANDA_ATTACK = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_attack")); ++ GoalKey PANDA_AVOID = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_avoid")); ++ GoalKey PANDA_BREED = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_breed")); ++ GoalKey PANDA_HURT_BY_TARGET = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_hurt_by_target")); ++ GoalKey PANDA_LIE_ON_BACK = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_lie_on_back")); ++ GoalKey PANDA_LOOK_AT_PLAYER = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_look_at_player")); ++ GoalKey PANDA_PANIC = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_panic")); ++ GoalKey PANDA_ROLL = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_roll")); ++ GoalKey PANDA_SIT = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_sit")); ++ GoalKey PANDA_SNEEZE = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_sneeze")); ++ GoalKey PHANTOM_ATTACK_PLAYER = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_player")); ++ GoalKey PHANTOM_ATTACK_STRATEGY = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_strategy")); ++ GoalKey PHANTOM_CIRCLE_AROUND_ANCHOR = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_circle_around_anchor")); ++ GoalKey PHANTOM_SWEEP_ATTACK = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_sweep_attack")); ++ /** ++ * @deprecated removed in 1.16 ++ */ ++ @Deprecated ++ GoalKey ANGER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger")); ++ /** ++ * @deprecated removed in 1.16 ++ */ ++ @Deprecated ++ GoalKey ANGER_OTHER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger_other")); ++ GoalKey POLARBEAR_ATTACK_PLAYERS = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_attack_players")); ++ GoalKey POLARBEAR_HURT_BY = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_hurt_by")); ++ GoalKey POLARBEAR_MELEE = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_melee")); ++ GoalKey POLARBEAR_PANIC = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_panic")); ++ GoalKey PUFFERFISH_PUFF = GoalKey.of(PufferFish.class, NamespacedKey.minecraft("pufferfish_puff")); ++ GoalKey EAT_CARROTS = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("eat_carrots")); ++ GoalKey KILLER_RABBIT_MELEE_ATTACK = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("killer_rabbit_melee_attack")); ++ GoalKey RABBIT_AVOID_TARGET = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_avoid_target")); ++ GoalKey RABBIT_PANIC = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_panic")); ++ GoalKey RAIDER_HOLD_GROUND = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_hold_ground")); ++ GoalKey RAIDER_OBTAIN_BANNER = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_obtain_banner")); ++ GoalKey RAIDER_CELEBRATION = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_celebration")); ++ GoalKey RAIDER_MOVE_THROUGH_VILLAGE = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_move_through_village")); ++ GoalKey RAVAGER_MELEE_ATTACK = GoalKey.of(Ravager.class, NamespacedKey.minecraft("ravager_melee_attack")); ++ GoalKey SHULKER_ATTACK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_attack")); ++ GoalKey SHULKER_DEFENSE = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_defense")); ++ GoalKey SHULKER_NEAREST = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_nearest")); ++ GoalKey SHULKER_PEEK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_peek")); ++ GoalKey SILVERFISH_HIDE_IN_BLOCK = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_hide_in_block")); ++ GoalKey SILVERFISH_WAKE_OTHERS = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_wake_others")); ++ GoalKey SKELETON_MELEE = GoalKey.of(Skeleton.class, NamespacedKey.minecraft("skeleton_melee")); ++ GoalKey SLIME_IDLE = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_idle")); ++ GoalKey SLIME_NEAREST_PLAYER = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_nearest_player")); ++ GoalKey SLIME_RANDOM_DIRECTION = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_direction")); ++ GoalKey SLIME_RANDOM_JUMP = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_jump")); ++ GoalKey SPIDER_MELEE_ATTACK = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_melee_attack")); ++ GoalKey SPIDER_NEAREST_ATTACKABLE_TARGET = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_nearest_attackable_target")); ++ GoalKey STRIDER_GO_TO_LAVA = GoalKey.of(Strider.class, NamespacedKey.minecraft("strider_go_to_lava")); ++ GoalKey SQUID = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid")); ++ GoalKey SQUID_FLEE = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid_flee")); ++ GoalKey TURTLE_BREED = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_breed")); ++ GoalKey TURTLE_GO_HOME = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_go_home")); ++ GoalKey TURTLE_GOTO_WATER = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_goto_water")); ++ GoalKey TURTLE_LAY_EGG = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_lay_egg")); ++ GoalKey TURTLE_PANIC = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_panic")); ++ GoalKey TURTLE_RANDOM_STROLL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_random_stroll")); ++ GoalKey TURTLE_TEMPT = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_tempt")); ++ GoalKey TURTLE_TRAVEL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_travel")); ++ GoalKey VEX_CHARGE_ATTACK = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_charge_attack")); ++ GoalKey VEX_COPY_TARGET_OF_OWNER = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_copy_target_of_owner")); ++ GoalKey VEX_RANDOM_MOVE = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_random_move")); ++ GoalKey VILLAGERTRADER_WANDER_TO_POSITION = GoalKey.of(WanderingTrader.class, NamespacedKey.minecraft("villagertrader_wander_to_position")); ++ GoalKey VINDICATOR_BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("vindicator_break_door")); ++ GoalKey VINDICATOR_JOHNNY_ATTACK = GoalKey.of(Vindicator.class, NamespacedKey.minecraft("vindicator_johnny_attack")); ++ GoalKey VINDICATOR_MELEE_ATTACK = GoalKey.of(Vindicator.class, NamespacedKey.minecraft("vindicator_melee_attack")); ++ GoalKey WITHER_DO_NOTHING = GoalKey.of(Wither.class, NamespacedKey.minecraft("wither_do_nothing")); ++ GoalKey WOLF_AVOID_ENTITY = GoalKey.of(Wolf.class, NamespacedKey.minecraft("wolf_avoid_entity")); ++ GoalKey ZOMBIE_ATTACK_TURTLE_EGG = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack_turtle_egg")); ++ GoalKey ARROW_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("arrow_attack")); ++ GoalKey AVOID_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("avoid_target")); ++ GoalKey BEG = GoalKey.of(Wolf.class, NamespacedKey.minecraft("beg")); ++ GoalKey BOW_SHOOT = GoalKey.of(Monster.class, NamespacedKey.minecraft("bow_shoot")); ++ GoalKey BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("break_door")); ++ GoalKey BREATH = GoalKey.of(Creature.class, NamespacedKey.minecraft("breath")); ++ GoalKey BREED = GoalKey.of(Animals.class, NamespacedKey.minecraft("breed")); ++ GoalKey CAT_SIT_ON_BED = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_sit_on_bed")); ++ GoalKey CROSSBOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("crossbow_attack")); ++ GoalKey DEFEND_VILLAGE = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("defend_village")); ++ GoalKey DOOR_OPEN = GoalKey.of(Mob.class, NamespacedKey.minecraft("door_open")); ++ GoalKey EAT_TILE = GoalKey.of(Mob.class, NamespacedKey.minecraft("eat_tile")); ++ GoalKey FISH_SCHOOL = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_school")); ++ GoalKey FLEE_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("flee_sun")); ++ GoalKey FLOAT = GoalKey.of(Mob.class, NamespacedKey.minecraft("float")); ++ GoalKey FOLLOW_BOAT = GoalKey.of(Creature.class, NamespacedKey.minecraft("follow_boat")); ++ GoalKey FOLLOW_ENTITY = GoalKey.of(Mob.class, NamespacedKey.minecraft("follow_entity")); ++ GoalKey FOLLOW_OWNER = GoalKey.of(Tameable.class, NamespacedKey.minecraft("follow_owner")); ++ GoalKey FOLLOW_PARENT = GoalKey.of(Animals.class, NamespacedKey.minecraft("follow_parent")); ++ GoalKey HORSE_TRAP = GoalKey.of(SkeletonHorse.class, NamespacedKey.minecraft("horse_trap")); ++ GoalKey HURT_BY_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("hurt_by_target")); ++ GoalKey INTERACT = GoalKey.of(Mob.class, NamespacedKey.minecraft("interact")); ++ GoalKey JUMP_ON_BLOCK = GoalKey.of(Cat.class, NamespacedKey.minecraft("jump_on_block")); ++ GoalKey LEAP_AT_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("leap_at_target")); ++ GoalKey LLAMA_FOLLOW = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_follow")); ++ GoalKey LOOK_AT_PLAYER = GoalKey.of(Mob.class, NamespacedKey.minecraft("look_at_player")); ++ GoalKey LOOK_AT_TRADING_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("look_at_trading_player")); ++ GoalKey MELEE_ATTACK = GoalKey.of(Creature.class, NamespacedKey.minecraft("melee_attack")); ++ GoalKey MOVE_THROUGH_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_through_village")); ++ GoalKey MOVE_TOWARDS_RESTRICTION = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_restriction")); ++ GoalKey MOVE_TOWARDS_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_target")); ++ GoalKey NEAREST_ATTACKABLE_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("nearest_attackable_target")); ++ GoalKey NEAREST_ATTACKABLE_TARGET_WITCH = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_attackable_target_witch")); ++ GoalKey NEAREST_HEALABLE_RAIDER = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_healable_raider")); ++ GoalKey NEAREST_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("nearest_village")); ++ GoalKey OCELOT_ATTACK = GoalKey.of(Mob.class, NamespacedKey.minecraft("ocelot_attack")); ++ GoalKey OFFER_FLOWER = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("offer_flower")); ++ GoalKey OWNER_HURT_BY_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_by_target")); ++ GoalKey OWNER_HURT_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_target")); ++ GoalKey PANIC = GoalKey.of(Creature.class, NamespacedKey.minecraft("panic")); ++ GoalKey PERCH = GoalKey.of(Parrot.class, NamespacedKey.minecraft("perch")); ++ GoalKey RAID = GoalKey.of(Raider.class, NamespacedKey.minecraft("raid")); ++ GoalKey RANDOM_FLY = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_fly")); ++ GoalKey RANDOM_LOOKAROUND = GoalKey.of(Mob.class, NamespacedKey.minecraft("random_lookaround")); ++ GoalKey RANDOM_STROLL = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll")); ++ GoalKey RANDOM_STROLL_LAND = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll_land")); ++ GoalKey RANDOM_SWIM = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_swim")); ++ GoalKey RANDOM_TARGET_NON_TAMED = GoalKey.of(Tameable.class, NamespacedKey.minecraft("random_target_non_tamed")); ++ GoalKey REMOVE_BLOCK = GoalKey.of(Creature.class, NamespacedKey.minecraft("remove_block")); ++ GoalKey RESTRICT_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("restrict_sun")); ++ GoalKey SIT = GoalKey.of(Tameable.class, NamespacedKey.minecraft("sit")); ++ GoalKey STROLL_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village")); ++ GoalKey SWELL = GoalKey.of(Creeper.class, NamespacedKey.minecraft("swell")); ++ GoalKey TAME = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("tame")); ++ GoalKey TEMPT = GoalKey.of(Creature.class, NamespacedKey.minecraft("tempt")); ++ GoalKey TRADE_WITH_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("trade_with_player")); ++ GoalKey USE_ITEM = GoalKey.of(Mob.class, NamespacedKey.minecraft("use_item")); ++ GoalKey WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("water")); ++ GoalKey WATER_JUMP = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("water_jump")); ++ GoalKey ZOMBIE_ATTACK = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack")); ++ GoalKey STROLL_VILLAGE_GOLEM = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village_golem")); ++ GoalKey UNIVERSAL_ANGER_RESET = GoalKey.of(Mob.class, NamespacedKey.minecraft("universal_anger_reset")); ++} +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index bbf15311a48ba96e14ffa2ab9d59613e79f06618..4cffbc4f665e267371e99094e8b7de975fffc223 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1879,6 +1879,16 @@ public final class Bukkit { + public static boolean isStopping() { + return server.isStopping(); + } ++ ++ /** ++ * Returns the {@link com.destroystokyo.paper.entity.ai.MobGoals} manager ++ * ++ * @return the mob goals manager ++ */ ++ @NotNull ++ public static com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { ++ return server.getMobGoals(); ++ } + // Paper end + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 21ebe1e70a4b9df54a5c730cee6d024cc1358b88..969cba46ba2790dde32724111ad77332c5872e0b 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1648,5 +1648,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + * @return true if server is in the process of being shutdown + */ + boolean isStopping(); ++ ++ /** ++ * Returns the {@link com.destroystokyo.paper.entity.ai.MobGoals} manager ++ * ++ * @return the mob goals manager ++ */ ++ @NotNull ++ com.destroystokyo.paper.entity.ai.MobGoals getMobGoals(); + // Paper end + } diff --git a/patches/api-unmapped/0201-World-view-distance-api.patch b/patches/api-unmapped/0201-World-view-distance-api.patch new file mode 100644 index 0000000000..17a9a94f12 --- /dev/null +++ b/patches/api-unmapped/0201-World-view-distance-api.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 5 May 2020 21:28:01 -0700 +Subject: [PATCH] World view distance api + + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 7bf85151efddcbd561afb0fb2d423aa97ac176c1..61dfb057d94d89477d11b9e8d4be7c16032e25a9 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -3447,6 +3447,34 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + int getViewDistance(); + // Spigot end + ++ // Paper start - view distance api ++ /** ++ * Sets the view distance for this world. ++ * @param viewDistance view distance in [2, 32] ++ */ ++ void setViewDistance(int viewDistance); ++ ++ /** ++ * Returns the no-tick view distance for this world. ++ *

    ++ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not ++ * be set to tick. ++ *

    ++ * @return The no-tick view distance for this world. ++ */ ++ int getNoTickViewDistance(); ++ ++ /** ++ * Sets the no-tick view distance for this world. ++ *

    ++ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not ++ * be set to tick. ++ *

    ++ * @param viewDistance view distance in [2, 32] ++ */ ++ void setNoTickViewDistance(int viewDistance); ++ // Paper end - view distance api ++ + // Spigot start + public class Spigot { + diff --git a/patches/api-unmapped/0202-Add-villager-reputation-API.patch b/patches/api-unmapped/0202-Add-villager-reputation-API.patch new file mode 100644 index 0000000000..cef4ea6027 --- /dev/null +++ b/patches/api-unmapped/0202-Add-villager-reputation-API.patch @@ -0,0 +1,177 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 22 Apr 2020 23:13:49 +0200 +Subject: [PATCH] Add villager reputation API + + +diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/Reputation.java b/src/main/java/com/destroystokyo/paper/entity/villager/Reputation.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1cc9ef255df888cb7dd7f7f2c5014e818d1be613 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/villager/Reputation.java +@@ -0,0 +1,54 @@ ++package com.destroystokyo.paper.entity.villager; ++ ++import com.google.common.base.Preconditions; ++import java.util.Map; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A reputation score for a player on a villager. ++ */ ++public final class Reputation { ++ private static final ReputationType[] REPUTATION_TYPES = ReputationType.values(); // Avoid allocation ++ @NotNull ++ private final int[] reputation; ++ ++ public Reputation() { ++ this(new int[REPUTATION_TYPES.length]); ++ } ++ ++ // Package level to avoid plugins creating reputations with "magic values". ++ Reputation(@NotNull int[] reputation) { ++ this.reputation = reputation; ++ } ++ ++ public Reputation(@NotNull final Map reputation) { ++ this(); ++ Preconditions.checkNotNull(reputation, "reputation cannot be null"); ++ ++ for (Map.Entry entry : reputation.entrySet()) { ++ setReputation(entry.getKey(), entry.getValue()); ++ } ++ } ++ ++ /** ++ * Gets the reputation value for a specific {@link ReputationType}. ++ * ++ * @param type The {@link ReputationType type} of reputation to get. ++ * @return The value of the {@link ReputationType type}. ++ */ ++ public int getReputation(@NotNull ReputationType type) { ++ Preconditions.checkNotNull(type, "the reputation type cannot be null"); ++ return reputation[type.ordinal()]; ++ } ++ ++ /** ++ * Sets the reputation value for a specific {@link ReputationType}. ++ * ++ * @param type The {@link ReputationType type} of reputation to set. ++ * @param value The value of the {@link ReputationType type}. ++ */ ++ public void setReputation(@NotNull ReputationType type, int value) { ++ Preconditions.checkNotNull(type, "the reputation type cannot be null"); ++ reputation[type.ordinal()] = value; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/ReputationType.java b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationType.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5600fcdc9795a9f49091db48d73bbd4964b8b737 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationType.java +@@ -0,0 +1,36 @@ ++package com.destroystokyo.paper.entity.villager; ++ ++/** ++ * A type of reputation gained with a {@link org.bukkit.entity.Villager Villager}. ++ *

    ++ * All types but {@link #MAJOR_POSITIVE} are shared to other villagers. ++ */ ++public enum ReputationType { ++ /** ++ * A gossip with a majorly negative effect. This is only gained through killing a nearby ++ * villager. ++ */ ++ MAJOR_NEGATIVE, ++ ++ /** ++ * A gossip with a minor negative effect. This is only gained through damaging a villager. ++ */ ++ MINOR_NEGATIVE, ++ ++ /** ++ * A gossip with a minor positive effect. This is only gained through curing a zombie ++ * villager. ++ */ ++ MINOR_POSITIVE, ++ ++ /** ++ * A gossip with a major positive effect. This is only gained through curing a zombie ++ * villager. ++ */ ++ MAJOR_POSITIVE, ++ ++ /** ++ * A gossip with a minor positive effect. This is only gained through trading with a villager. ++ */ ++ TRADING, ++} +diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java +index d1579153092c1b80350155110f1b9926b1a1ef57..c8777a476e38ef5e72b6709761990a339eb43d2b 100644 +--- a/src/main/java/org/bukkit/entity/Villager.java ++++ b/src/main/java/org/bukkit/entity/Villager.java +@@ -1,10 +1,13 @@ + package org.bukkit.entity; + + import java.util.Locale; ++import java.util.Map; // Paper ++import java.util.UUID; // Paper + import org.bukkit.Keyed; + import org.bukkit.Location; + import org.bukkit.NamespacedKey; + import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; // Paper + + /** + * Represents a villager NPC +@@ -224,4 +227,50 @@ public interface Villager extends AbstractVillager { + return key; + } + } ++ ++ // Paper start - Add villager reputation API ++ /** ++ * Get the {@link com.destroystokyo.paper.entity.villager.Reputation reputation} ++ * for a specific player by {@link UUID}. ++ * ++ * @param uniqueId The {@link UUID} of the player to get the reputation of. ++ * @return The player's copied reputation with this villager. ++ */ ++ @Nullable ++ public com.destroystokyo.paper.entity.villager.Reputation getReputation(@NotNull UUID uniqueId); ++ ++ /** ++ * Get all {@link com.destroystokyo.paper.entity.villager.Reputation reputations} ++ * for all players mapped by their {@link UUID unique IDs}. ++ * ++ * @return All {@link com.destroystokyo.paper.entity.villager.Reputation reputations} for all players ++ * in a copied map. ++ */ ++ @NotNull ++ public Map getReputations(); ++ ++ /** ++ * Set the {@link com.destroystokyo.paper.entity.villager.Reputation reputation} ++ * for a specific player by {@link UUID}. ++ * ++ * @param uniqueId The {@link UUID} of the player to set the reputation of. ++ * @param reputation The {@link com.destroystokyo.paper.entity.villager.Reputation reputation} to set. ++ */ ++ public void setReputation(@NotNull UUID uniqueId, @NotNull com.destroystokyo.paper.entity.villager.Reputation reputation); ++ ++ /** ++ * Set all {@link com.destroystokyo.paper.entity.villager.Reputation reputations} ++ * for all players mapped by their {@link UUID unique IDs}. ++ * ++ * @param reputations All {@link com.destroystokyo.paper.entity.villager.Reputation reputations} ++ * for all players mapped by their {@link UUID unique IDs}. ++ */ ++ public void setReputations(@NotNull Map reputations); ++ ++ /** ++ * Clear all reputations from this villager. This removes every single ++ * reputation regardless of its impact and the player associated. ++ */ ++ public void clearReputations(); ++ // Paper end + } diff --git a/patches/api-unmapped/0203-Spawn-Reason-API.patch b/patches/api-unmapped/0203-Spawn-Reason-API.patch new file mode 100644 index 0000000000..0ee08ee996 --- /dev/null +++ b/patches/api-unmapped/0203-Spawn-Reason-API.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 10 Apr 2014 23:18:28 -0400 +Subject: [PATCH] Spawn Reason API + + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 476184db904d8a2e1347e1219e8ba196bf4da5cb..c1010e314144a65e12eaf5514d639a87f45891a9 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -1,6 +1,8 @@ + package org.bukkit; + + import java.io.File; ++ ++import org.bukkit.event.entity.CreatureSpawnEvent; + import org.bukkit.generator.ChunkGenerator; + + import java.util.ArrayList; +@@ -2249,6 +2251,12 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + @NotNull + public T spawn(@NotNull Location location, @NotNull Class clazz) throws IllegalArgumentException; + ++ // Paper start ++ @NotNull ++ public default T spawn(@NotNull Location location, @NotNull Class clazz, @NotNull CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException { ++ return spawn(location, clazz, reason, null); ++ } ++ + /** + * Spawn an entity of a specific class at the given {@link Location}, with + * the supplied function run before the entity is added to the world. +@@ -2266,7 +2274,28 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + * {@link Entity} requested cannot be spawned + */ + @NotNull +- public T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function) throws IllegalArgumentException; ++ public default T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function) throws IllegalArgumentException { ++ return spawn(location, clazz, CreatureSpawnEvent.SpawnReason.CUSTOM, function); ++ } ++ ++ @NotNull ++ public default T spawn(@NotNull Location location, @NotNull Class clazz, @NotNull CreatureSpawnEvent.SpawnReason reason, @Nullable Consumer function) throws IllegalArgumentException { ++ return spawn(location, clazz, function, reason); ++ } ++ ++ @NotNull ++ public default Entity spawnEntity(@NotNull Location loc, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason) { ++ return spawn(loc, (Class) type.getEntityClass(), reason, null); ++ } ++ ++ @NotNull ++ public default Entity spawnEntity(@NotNull Location loc, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason, @Nullable Consumer function) { ++ return spawn(loc, (Class) type.getEntityClass(), reason, function); ++ } ++ ++ @NotNull ++ public T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function, @NotNull CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException; ++ // Paper end + + /** + * Spawn a {@link FallingBlock} entity at the given {@link Location} of diff --git a/patches/api-unmapped/0204-Potential-bed-API.patch b/patches/api-unmapped/0204-Potential-bed-API.patch new file mode 100644 index 0000000000..b8b1e2519a --- /dev/null +++ b/patches/api-unmapped/0204-Potential-bed-API.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Sun, 10 May 2020 23:06:41 -0400 +Subject: [PATCH] Potential bed API + +Adds a new method to fetch the location of a player's bed without generating any sync loads. + +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 3418133d07250a7fd50caad8d97924b86fb30bad..b09d12390d5f77330ac84452e0fee63a169bd01f 100644 +--- a/src/main/java/org/bukkit/entity/HumanEntity.java ++++ b/src/main/java/org/bukkit/entity/HumanEntity.java +@@ -240,6 +240,19 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder + */ + public int getSleepTicks(); + ++ ++ // Paper start - Potential bed api ++ /** ++ * Gets the Location of the player's bed, null if they have not slept ++ * in one. This method will not attempt to validate if the current bed ++ * is still valid. ++ * ++ * @return Bed Location if has slept in one, otherwise null. ++ */ ++ @Nullable ++ public Location getPotentialBedLocation(); ++ // Paper end ++ + /** + * Attempts to make the entity sleep at the given location. + *
    diff --git a/patches/api-unmapped/0205-Prioritise-own-classes-where-possible.patch b/patches/api-unmapped/0205-Prioritise-own-classes-where-possible.patch new file mode 100644 index 0000000000..be1c895ad7 --- /dev/null +++ b/patches/api-unmapped/0205-Prioritise-own-classes-where-possible.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Mon, 27 Apr 2020 12:31:59 +0200 +Subject: [PATCH] Prioritise own classes where possible + +This adds the server property `Paper.DisableClassPrioritization` to disable +prioritization of own classes for plugins' classloaders. + +This value is by default not present, and this will therefore break any +plugins which abuse behaviour related to not using their own classes +while still loading their own. This is often an issue with failing to +relocate or shade properly, such as when shading plugin APIs like Vault. + +A plugin's classloader will first look in the same jar as it is loading +in for a requested class, then load it. It does not re-use other +plugins' classes if it has the chance to avoid doing so. + +If a class is not found in the same jar as it is loading for and it does +find it elsewhere, it will still choose the class elsewhere. This is +intended behaviour, as it will only prioritise classes it has in its own +jar, no other plugins' classes will be prioritised in any other order +than the one they were registered in. + +The patch in general terms just loads the class in the plugin's jar +before it starts looking elsewhere for it. + +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index ce751577623eaad0f31e2eb7bf0842d1ab73e845..31793f46e5623729dfb4048e901f274082f57826 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -51,6 +51,7 @@ import org.yaml.snakeyaml.error.YAMLException; + */ + public final class JavaPluginLoader implements PluginLoader { + final Server server; ++ private static final boolean DISABLE_CLASS_PRIORITIZATION = Boolean.getBoolean("Paper.DisableClassPrioritization"); // Paper + private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; + private final Map classLoadLock = new java.util.HashMap(); // Paper + private final Map classLoadLockCount = new java.util.HashMap(); // Paper +@@ -203,6 +204,11 @@ public final class JavaPluginLoader implements PluginLoader { + + @Nullable + Class getClassByName(final String name, boolean resolve, PluginDescriptionFile description) { ++ // Paper start - prioritize self ++ return getClassByName(name, resolve, description, null); ++ } ++ Class getClassByName(final String name, boolean resolve, PluginDescriptionFile description, PluginClassLoader requester) { ++ // Paper end + // Paper start - make MT safe + java.util.concurrent.locks.ReentrantReadWriteLock lock; + synchronized (classLoadLock) { +@@ -210,6 +216,13 @@ public final class JavaPluginLoader implements PluginLoader { + classLoadLockCount.compute(name, (x, prev) -> prev != null ? prev + 1 : 1); + } + lock.writeLock().lock();try { ++ // Paper start - prioritize self ++ if (!DISABLE_CLASS_PRIORITIZATION && requester != null) { ++ try { ++ return requester.loadClass0(name, false, false, ((SimplePluginManager) server.getPluginManager()).isTransitiveDepend(description, requester.getDescription())); ++ } catch (ClassNotFoundException cnfe) {} ++ } ++ // Paper end + // Paper end + for (PluginClassLoader loader : loaders) { + try { +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index b9766b9b47547c400ed075f1635bb1461cb5e860..87016d01640d8ea86b93cf2f7ead4c88b6d9d778 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -33,7 +33,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + public JavaPlugin getPlugin() { return plugin; } // Spigot + private final JavaPluginLoader loader; + private final Map> classes = new ConcurrentHashMap>(); +- private final PluginDescriptionFile description; ++ private final PluginDescriptionFile description; PluginDescriptionFile getDescription() { return description; } // Paper + private final File dataFolder; + private final File file; + private final JarFile jar; +@@ -118,7 +118,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + + if (checkGlobal) { + // This ignores the libraries of other plugins, unless they are transitive dependencies. +- Class result = loader.getClassByName(name, resolve, description); ++ Class result = loader.getClassByName(name, resolve, description, this); // Paper - prioritize self + + // If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check. + if (result != null && result.getClassLoader() instanceof PluginClassLoader) { diff --git a/patches/api-unmapped/0206-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/api-unmapped/0206-Add-Raw-Byte-ItemStack-Serialization.patch new file mode 100644 index 0000000000..8ffb283fa6 --- /dev/null +++ b/patches/api-unmapped/0206-Add-Raw-Byte-ItemStack-Serialization.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Thu, 30 Apr 2020 16:56:31 +0200 +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 d6897f43a0692e031bed8a212d9a637ef548cc60..e348034288c74ab80360086d71f0b7f61551df24 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -97,5 +97,9 @@ public interface UnsafeValues { + static boolean isLegacyPlugin(org.bukkit.plugin.Plugin plugin) { + return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); + } ++ ++ byte[] serializeItem(ItemStack item); ++ ++ ItemStack deserializeItem(byte[] data); + // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index bf39989dbe08c93120d75bed6281ae75c460afca..15b48ad1ba5bcf7394fb3f52ce2cc6baa6632f66 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -628,6 +628,30 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + return Bukkit.getServer().getItemFactory().ensureServerConversions(this); + } + ++ /** ++ * Deserializes this itemstack from raw NBT bytes. NBT is safer for data migrations as it will ++ * use the built in data converter instead of bukkits dangerous serialization system. ++ * ++ * This expects that the DataVersion was stored on the root of the Compound, as saved from ++ * the {@link #serializeAsBytes()} API returned. ++ * @param bytes bytes representing an item in NBT ++ * @return ItemStack migrated to this version of Minecraft if needed. ++ */ ++ @NotNull ++ public static ItemStack deserializeBytes(@NotNull byte[] bytes) { ++ return org.bukkit.Bukkit.getUnsafe().deserializeItem(bytes); ++ } ++ ++ /** ++ * Serializes this itemstack to raw bytes in NBT. NBT is safer for data migrations as it will ++ * use the built in data converter instead of bukkits dangerous serialization system. ++ * @return bytes representing this item in NBT. ++ */ ++ @NotNull ++ public byte[] serializeAsBytes() { ++ return org.bukkit.Bukkit.getUnsafe().serializeItem(this); ++ } ++ + /** + * Gets the Display name as seen in the Client. + * Currently the server only supports the English language. To override this, diff --git a/patches/api-unmapped/0207-Provide-a-useful-PluginClassLoader-toString.patch b/patches/api-unmapped/0207-Provide-a-useful-PluginClassLoader-toString.patch new file mode 100644 index 0000000000..f993bdc2b7 --- /dev/null +++ b/patches/api-unmapped/0207-Provide-a-useful-PluginClassLoader-toString.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 31 May 2020 15:26:17 +0100 +Subject: [PATCH] Provide a useful PluginClassLoader#toString + +There are several cases where the plugin classloader may be dumped to the logs, +however, this provides no indication of the owner of the classloader, making +these messages effectively useless, this patch rectifies this + +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index 87016d01640d8ea86b93cf2f7ead4c88b6d9d778..cb62666d14a8eeb6338ecef75d57a1946cfa99a4 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -228,4 +228,16 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + javaPlugin.logger = this.logger; // Paper - set logger + javaPlugin.init(loader, loader.server, description, dataFolder, file, this); + } ++ ++ // Paper start ++ @Override ++ public String toString() { ++ JavaPlugin currPlugin = plugin != null ? plugin : pluginInit; ++ return "PluginClassLoader{" + ++ "plugin=" + currPlugin + ++ ", pluginEnabled=" + (currPlugin == null ? "uninitialized" : currPlugin.isEnabled()) + ++ ", url=" + file + ++ '}'; ++ } ++ // Paper end + } diff --git a/patches/api-unmapped/0208-Inventory-getHolder-method-without-block-snapshot.patch b/patches/api-unmapped/0208-Inventory-getHolder-method-without-block-snapshot.patch new file mode 100644 index 0000000000..5b633e50af --- /dev/null +++ b/patches/api-unmapped/0208-Inventory-getHolder-method-without-block-snapshot.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Wed, 10 Jun 2020 23:55:16 +0100 +Subject: [PATCH] Inventory getHolder method without block snapshot + + +diff --git a/src/main/java/org/bukkit/block/DoubleChest.java b/src/main/java/org/bukkit/block/DoubleChest.java +index 83a4642119c3f33749e04c774cf2b39839f797e2..a39d2f1acbbd84ae0e2cf29f85594e09e55e9355 100644 +--- a/src/main/java/org/bukkit/block/DoubleChest.java ++++ b/src/main/java/org/bukkit/block/DoubleChest.java +@@ -34,6 +34,18 @@ public class DoubleChest implements InventoryHolder { + return inventory.getRightSide().getHolder(); + } + ++ // Paper start - getHolder without snapshot ++ @Nullable ++ public InventoryHolder getLeftSide(boolean useSnapshot) { ++ return inventory.getLeftSide().getHolder(useSnapshot); ++ } ++ ++ @Nullable ++ public InventoryHolder getRightSide(boolean useSnapshot) { ++ return inventory.getRightSide().getHolder(useSnapshot); ++ } ++ // Paper end ++ + @NotNull + public Location getLocation() { + return getInventory().getLocation(); +diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java +index 9c6a5bdac8c3ab682bbfae04ff24b76a62bc2883..6386206188e820206bb1a9f516b5e194fdc9d952 100644 +--- a/src/main/java/org/bukkit/inventory/Inventory.java ++++ b/src/main/java/org/bukkit/inventory/Inventory.java +@@ -384,6 +384,17 @@ public interface Inventory extends Iterable { + @Nullable + public InventoryHolder getHolder(); + ++ // Paper start - getHolder without snapshot ++ /** ++ * Gets the block or entity belonging to the open inventory ++ * ++ * @param useSnapshot Create a snapshot if the holder is a tile entity ++ * @return The holder of the inventory; null if it has no holder. ++ */ ++ @Nullable ++ public InventoryHolder getHolder(boolean useSnapshot); ++ // Paper end ++ + @NotNull + @Override + public ListIterator iterator(); diff --git a/patches/api-unmapped/0209-Expose-Arrow-getItemStack.patch b/patches/api-unmapped/0209-Expose-Arrow-getItemStack.patch new file mode 100644 index 0000000000..e718e0e598 --- /dev/null +++ b/patches/api-unmapped/0209-Expose-Arrow-getItemStack.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nesaak <52047222+Nesaak@users.noreply.github.com> +Date: Fri, 22 May 2020 13:35:21 -0400 +Subject: [PATCH] Expose Arrow getItemStack + + +diff --git a/src/main/java/org/bukkit/entity/AbstractArrow.java b/src/main/java/org/bukkit/entity/AbstractArrow.java +index e8e56e89e32d84af0639fe2e9b0eeabd747b6007..b1d8007eed489aa061c1a6813bcdafc101231e56 100644 +--- a/src/main/java/org/bukkit/entity/AbstractArrow.java ++++ b/src/main/java/org/bukkit/entity/AbstractArrow.java +@@ -143,6 +143,14 @@ public interface AbstractArrow extends Projectile { + } + + // Paper start ++ /** ++ * Gets the ItemStack for this arrow. ++ * ++ * @return The ItemStack, as if a player picked up the arrow ++ */ ++ @NotNull ++ org.bukkit.inventory.ItemStack getItemStack(); ++ + /** + * Gets the {@link PickupRule} for this arrow. + * diff --git a/patches/api-unmapped/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/api-unmapped/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch new file mode 100644 index 0000000000..93bd233b85 --- /dev/null +++ b/patches/api-unmapped/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: LordKorea +Date: Mon, 11 May 2020 22:38:10 -0400 +Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerRecipeBookClickEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerRecipeBookClickEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7fa937d339ee98ad308deebb523fead6522eb262 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerRecipeBookClickEvent.java +@@ -0,0 +1,84 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.NamespacedKey; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a player clicks a recipe in the recipe book ++ */ ++public class PlayerRecipeBookClickEvent extends PlayerEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancel = false; ++ @NotNull private NamespacedKey recipe; ++ private boolean makeAll; ++ ++ public PlayerRecipeBookClickEvent(@NotNull Player player, @NotNull NamespacedKey recipe, boolean makeAll) { ++ super(player); ++ this.recipe = recipe; ++ this.makeAll = makeAll; ++ } ++ ++ /** ++ * Gets the namespaced key of the recipe that was clicked by the player ++ * ++ * @return The namespaced key of the recipe ++ */ ++ @NotNull ++ public NamespacedKey getRecipe() { ++ return recipe; ++ } ++ ++ /** ++ * Changes what recipe is requested. This sets the requested recipe to the recipe with the given key ++ * ++ * @param recipe The key of the recipe that should be requested ++ */ ++ public void setRecipe(@NotNull NamespacedKey recipe) { ++ this.recipe = recipe; ++ } ++ ++ /** ++ * Gets a boolean which indicates whether or not the player requested to make the maximum amount of results. This is ++ * true if shift is pressed while the recipe is clicked in the recipe book ++ * ++ * @return {@code true} if shift is pressed while the recipe is clicked ++ */ ++ public boolean isMakeAll() { ++ return makeAll; ++ } ++ ++ /** ++ * Sets whether or not the maximum amount of results should be made. If this is true, the request is handled as if ++ * the player had pressed shift while clicking on the recipe ++ * ++ * @param makeAll {@code true} if the request should attempt to make the maximum amount of results ++ */ ++ public void setMakeAll(boolean makeAll) { ++ this.makeAll = makeAll; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancel; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancel = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0211-Support-components-in-ItemMeta.patch b/patches/api-unmapped/0211-Support-components-in-ItemMeta.patch new file mode 100644 index 0000000000..1b51f21c69 --- /dev/null +++ b/patches/api-unmapped/0211-Support-components-in-ItemMeta.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Sat, 6 Jun 2020 18:13:16 +0200 +Subject: [PATCH] Support components in ItemMeta + + +diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java +index 01b462fccce71cef3398dd43944046f322b8e57e..f093f991f1fedd20fcef041b093398250b7fb286 100644 +--- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java +@@ -5,6 +5,7 @@ import java.util.Collection; + import java.util.List; + import java.util.Map; + import java.util.Set; ++import net.kyori.adventure.text.Component; + import org.bukkit.attribute.Attribute; + import org.bukkit.attribute.AttributeModifier; + import org.bukkit.configuration.serialization.ConfigurationSerializable; +@@ -62,6 +63,20 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + @NotNull + String getDisplayName(); + ++ // Paper start ++ /** ++ * Gets the display name that is set. ++ *

    ++ * Plugins should check that hasDisplayName() returns true ++ * before calling this method. ++ * ++ * @return the display name that is set ++ * @deprecated use {@link #displayName()} ++ */ ++ @NotNull ++ @Deprecated ++ net.md_5.bungee.api.chat.BaseComponent[] getDisplayNameComponent(); ++ // Paper end + /** + * Sets the display name. + * +@@ -71,6 +86,16 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + @Deprecated // Paper + void setDisplayName(@Nullable String name); + ++ // Paper start ++ /** ++ * Sets the display name. ++ * ++ * @param component the name component to set ++ * @deprecated use {@link #displayName(Component)} ++ */ ++ @Deprecated ++ void setDisplayNameComponent(@Nullable net.md_5.bungee.api.chat.BaseComponent[] component); ++ // Paper end + /** + * Checks for existence of a localized name. + * +@@ -134,6 +159,19 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + @Nullable + List getLore(); + ++ /** ++ * Gets the lore that is set. ++ *

    ++ * Plugins should check if hasLore() returns true before ++ * calling this method. ++ * ++ * @return a list of lore that is set ++ * @deprecated use {@link #lore()} ++ */ ++ @Nullable ++ @Deprecated ++ List getLoreComponents(); ++ + /** + * Sets the lore for this item. + * Removes lore when given null. +@@ -144,6 +182,16 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + @Deprecated // Paper + void setLore(@Nullable List lore); + ++ /** ++ * Sets the lore for this item. ++ * Removes lore when given null. ++ * ++ * @param lore the lore that will be set ++ * @deprecated use {@link #lore(List)} ++ */ ++ @Deprecated ++ void setLoreComponents(@Nullable List lore); ++ + /** + * Checks for existence of custom model data. + *

    diff --git a/patches/api-unmapped/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch b/patches/api-unmapped/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch new file mode 100644 index 0000000000..747470a546 --- /dev/null +++ b/patches/api-unmapped/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 3 Jul 2020 15:05:54 -0700 +Subject: [PATCH] added 2 new TargetReasons for 1.16 mob behavior + + +diff --git a/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java b/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java +index dee186e99463a56394bbc2039d1e763d109125b9..601904150156d475c18286b485f3409307a75950 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java +@@ -159,6 +159,14 @@ public class EntityTargetEvent extends EntityEvent implements Cancellable { + * as wheat in it's hand. + */ + TEMPT, ++ /** ++ * When the target is in a different dimension ++ */ ++ TARGET_OTHER_LEVEL, // Paper ++ /** ++ * When the target is in creative or spectator mode, or the gamemode is peaceful, or other reasons ++ */ ++ TARGET_INVALID, // Paper + /** + * A currently unknown reason for the entity changing target. + */ diff --git a/patches/api-unmapped/0213-Add-entity-liquid-API.patch b/patches/api-unmapped/0213-Add-entity-liquid-API.patch new file mode 100644 index 0000000000..c38113b716 --- /dev/null +++ b/patches/api-unmapped/0213-Add-entity-liquid-API.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 2 Jul 2020 18:11:33 -0500 +Subject: [PATCH] Add entity liquid API + + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 5b382091b1466b25ad42325d5808785a8e948552..ecb5595332ab493224d06a75904e142ab541aad9 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -714,5 +714,35 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + */ + @NotNull + org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason(); ++ ++ /** ++ * Check if entity is in rain ++ */ ++ public boolean isInRain(); ++ ++ /** ++ * Check if entity is in bubble column ++ */ ++ public boolean isInBubbleColumn(); ++ ++ /** ++ * Check if entity is in water or rain ++ */ ++ public boolean isInWaterOrRain(); ++ ++ /** ++ * Check if entity is in water or bubble column ++ */ ++ public boolean isInWaterOrBubbleColumn(); ++ ++ /** ++ * Check if entity is in water or rain or bubble column ++ */ ++ public boolean isInWaterOrRainOrBubbleColumn(); ++ ++ /** ++ * Check if entity is in lava ++ */ ++ public boolean isInLava(); + // Paper end + } diff --git a/patches/api-unmapped/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch b/patches/api-unmapped/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch new file mode 100644 index 0000000000..5dc61d601d --- /dev/null +++ b/patches/api-unmapped/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch @@ -0,0 +1,211 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 3 Jul 2020 11:58:56 -0500 +Subject: [PATCH] Add PrepareResultEvent / PrepareGrindstoneEvent + +Adds a new event for all crafting stations that generate a result slot item + +Anvil, Grindstone and Smithing now extend this event + +Grindstone is a backwards compat from a previous PrepareGrindstoneEvent + +diff --git a/src/main/java/com/destroystokyo/paper/event/inventory/PrepareGrindstoneEvent.java b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareGrindstoneEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..449e8c06f8434b59d49a76481fa60c5c49e80579 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareGrindstoneEvent.java +@@ -0,0 +1,28 @@ ++package com.destroystokyo.paper.event.inventory; ++ ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.inventory.InventoryEvent; ++import org.bukkit.inventory.GrindstoneInventory; ++import org.bukkit.inventory.InventoryView; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when an item is put in a slot for grinding in a Grindstone ++ * @see com.destroystokyo.paper.event.inventory.PrepareResultEvent ++ */ ++@Deprecated ++public class PrepareGrindstoneEvent extends PrepareResultEvent { ++ ++ public PrepareGrindstoneEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) { ++ super(inventory, result); ++ } ++ ++ @NotNull ++ @Override ++ public GrindstoneInventory getInventory() { ++ return (GrindstoneInventory) super.getInventory(); ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/inventory/PrepareResultEvent.java b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareResultEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..045ce9ec3c9134aced5f5235b760ac85599d16c6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareResultEvent.java +@@ -0,0 +1,48 @@ ++package com.destroystokyo.paper.event.inventory; ++ ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.inventory.InventoryEvent; ++import org.bukkit.event.inventory.InventoryType; ++import org.bukkit.inventory.InventoryView; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when an item is put in an inventory containing a result slot ++ */ ++public class PrepareResultEvent extends InventoryEvent { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private ItemStack result; ++ ++ public PrepareResultEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) { ++ super(inventory); ++ this.result = result; ++ } ++ ++ /** ++ * Get result item, may be null. ++ * ++ * @return result item ++ */ ++ @Nullable ++ public ItemStack getResult() { ++ return result; ++ } ++ ++ public void setResult(@Nullable ItemStack result) { ++ this.result = result; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java b/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java +index 77109a07f07aa6985106dc1a9ad5218f6c7f360f..f1f6f4ab4f81a3f21e757fef4a30b00e94371f8d 100644 +--- a/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java +@@ -1,5 +1,6 @@ + package org.bukkit.event.inventory; + ++import com.destroystokyo.paper.event.inventory.PrepareResultEvent; + import org.bukkit.event.HandlerList; + import org.bukkit.inventory.AnvilInventory; + import org.bukkit.inventory.InventoryView; +@@ -10,14 +11,16 @@ import org.jetbrains.annotations.Nullable; + /** + * Called when an item is put in a slot for repair by an anvil. + */ +-public class PrepareAnvilEvent extends InventoryEvent { ++// Paper start - extend PrepareResultEvent ++public class PrepareAnvilEvent extends PrepareResultEvent { + +- private static final HandlerList handlers = new HandlerList(); +- private ItemStack result; ++ //private static final HandlerList handlers = new HandlerList(); ++ //private ItemStack result; + + public PrepareAnvilEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) { +- super(inventory); +- this.result = result; ++ super(inventory, result); ++ //this.result = result; ++ // Paper end + } + + @NotNull +@@ -33,13 +36,14 @@ public class PrepareAnvilEvent extends InventoryEvent { + */ + @Nullable + public ItemStack getResult() { +- return result; ++ return super.getResult(); // Paper + } + + public void setResult(@Nullable ItemStack result) { +- this.result = result; ++ super.setResult(result); // Paper + } + ++ /* // Paper - comment out + @NotNull + @Override + public HandlerList getHandlers() { +@@ -50,4 +54,5 @@ public class PrepareAnvilEvent extends InventoryEvent { + public static HandlerList getHandlerList() { + return handlers; + } ++ */ // Paper + } +diff --git a/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java b/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java +index 99af1540324c4d68c5890ac40b591c5cbdd2e870..0bc0ca4f96c800e9c46c61710f44446691d8b93f 100644 +--- a/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java +@@ -1,5 +1,6 @@ + package org.bukkit.event.inventory; + ++import com.destroystokyo.paper.event.inventory.PrepareResultEvent; + import org.bukkit.event.HandlerList; + import org.bukkit.inventory.InventoryView; + import org.bukkit.inventory.ItemStack; +@@ -10,14 +11,16 @@ import org.jetbrains.annotations.Nullable; + /** + * Called when an item is put in a slot for upgrade by a Smithing Table. + */ +-public class PrepareSmithingEvent extends InventoryEvent { ++// Paper start - extend PrepareResultEvent ++public class PrepareSmithingEvent extends PrepareResultEvent { + +- private static final HandlerList handlers = new HandlerList(); +- private ItemStack result; ++ //private static final HandlerList handlers = new HandlerList(); ++ //private ItemStack result; + + public PrepareSmithingEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) { +- super(inventory); +- this.result = result; ++ super(inventory, result); ++ //this.result = result; ++ // Paper end + } + + @NotNull +@@ -33,13 +36,14 @@ public class PrepareSmithingEvent extends InventoryEvent { + */ + @Nullable + public ItemStack getResult() { +- return result; ++ return super.getResult(); // Paper + } + + public void setResult(@Nullable ItemStack result) { +- this.result = result; ++ super.setResult(result); // Paper + } + ++ /* // Paper - comment out + @NotNull + @Override + public HandlerList getHandlers() { +@@ -50,4 +54,5 @@ public class PrepareSmithingEvent extends InventoryEvent { + public static HandlerList getHandlerList() { + return handlers; + } ++ */ // Paper + } diff --git a/patches/api-unmapped/0215-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/api-unmapped/0215-Allow-delegation-to-vanilla-chunk-gen.patch new file mode 100644 index 0000000000..c270243b46 --- /dev/null +++ b/patches/api-unmapped/0215-Allow-delegation-to-vanilla-chunk-gen.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Wed, 29 Apr 2020 02:09:17 +0200 +Subject: [PATCH] Allow delegation to vanilla chunk gen + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 4cffbc4f665e267371e99094e8b7de975fffc223..a1e211653e05f3c9bc2ddf5aa1b69dea1c4bb61b 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1490,6 +1490,22 @@ public final class Bukkit { + return server.createChunkData(world); + } + ++ // Paper start ++ /** ++ * Create a ChunkData for use in a generator, that is populated by the vanilla generator for that world ++ * ++ * @param world the world to create the ChunkData for ++ * @param x the x coordinate of the chunk ++ * @param z the z coordinate of the chunk ++ * @return a new ChunkData for the world ++ * ++ */ ++ @NotNull ++ public static ChunkGenerator.ChunkData createVanillaChunkData(@NotNull World world, int x, int z) { ++ return server.createVanillaChunkData(world, x, z); ++ } ++ // Paper stop ++ + /** + * Creates a boss bar instance to display to players. The progress + * defaults to 1.0 +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 969cba46ba2790dde32724111ad77332c5872e0b..71538dfce294776b8f98046cbddde21dc9ae89e7 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1256,6 +1256,20 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @NotNull + public ChunkGenerator.ChunkData createChunkData(@NotNull World world); + ++ // Paper start ++ /** ++ * Create a ChunkData for use in a generator, that is populated by the vanilla generator for that world ++ * ++ * @param world the world to create the ChunkData for ++ * @param x the x coordinate of the chunk ++ * @param z the z coordinate of the chunk ++ * @return a new ChunkData for the world ++ * ++ */ ++ @NotNull ++ ChunkGenerator.ChunkData createVanillaChunkData(@NotNull World world, int x, int z); ++ // Paper end ++ + /** + * Creates a boss bar instance to display to players. The progress + * defaults to 1.0 +diff --git a/src/main/java/org/bukkit/generator/ChunkGenerator.java b/src/main/java/org/bukkit/generator/ChunkGenerator.java +index 7caef27682f22a77de283dd6f391ec8bc0b0312b..5ba77d40a38e5e592ee265e4fbd510043a0b4345 100644 +--- a/src/main/java/org/bukkit/generator/ChunkGenerator.java ++++ b/src/main/java/org/bukkit/generator/ChunkGenerator.java +@@ -227,6 +227,22 @@ public abstract class ChunkGenerator { + return false; + } + ++ // Paper start ++ /** ++ * Create a ChunkData for use in a generator, that is populated by the vanilla generator for that world ++ * ++ * @param world the world to create the ChunkData for ++ * @param x the x coordinate of the chunk ++ * @param z the z coordinate of the chunk ++ * @return a new ChunkData for the world ++ * ++ */ ++ @NotNull ++ public ChunkData createVanillaChunkData(@NotNull World world, int x, int z) { ++ return Bukkit.getServer().createVanillaChunkData(world, x, z); ++ } ++ // Paper end ++ + /** + * Data for a Chunk. + */ diff --git a/patches/api-unmapped/0216-Support-hex-colors-in-getLastColors.patch b/patches/api-unmapped/0216-Support-hex-colors-in-getLastColors.patch new file mode 100644 index 0000000000..a3117a4377 --- /dev/null +++ b/patches/api-unmapped/0216-Support-hex-colors-in-getLastColors.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gerrygames +Date: Thu, 16 Jul 2020 10:40:10 +0200 +Subject: [PATCH] Support hex colors in getLastColors + + +diff --git a/src/main/java/org/bukkit/ChatColor.java b/src/main/java/org/bukkit/ChatColor.java +index 44d597d7a6f66a18b8037e971170ff7cea5e825f..4594701d77c5d0f744bece871b98d9f6f73eb5a7 100644 +--- a/src/main/java/org/bukkit/ChatColor.java ++++ b/src/main/java/org/bukkit/ChatColor.java +@@ -363,6 +363,7 @@ public enum ChatColor { + return new String(b); + } + ++ private static final Pattern HEX_COLOR_PATTERN = Pattern.compile(COLOR_CHAR + "x(?>" + COLOR_CHAR + "[0-9a-f]){6}", Pattern.CASE_INSENSITIVE); // Paper - Support hex colors in getLastColors + /** + * Gets the ChatColors used at the end of the given input string. + * +@@ -380,6 +381,15 @@ public enum ChatColor { + for (int index = length - 1; index > -1; index--) { + char section = input.charAt(index); + if (section == COLOR_CHAR && index < length - 1) { ++ // Paper start - Support hex colors ++ if (index > 11 && input.charAt(index - 12) == COLOR_CHAR && (input.charAt(index - 11) == 'x' || input.charAt(index - 11) == 'X')) { ++ String color = input.substring(index - 12, index + 2); ++ if (HEX_COLOR_PATTERN.matcher(color).matches()) { ++ result = color + result; ++ break; ++ } ++ } ++ // Paper end + char c = input.charAt(index + 1); + ChatColor color = getByChar(c); + diff --git a/patches/api-unmapped/0217-Add-setMaxPlayers-API.patch b/patches/api-unmapped/0217-Add-setMaxPlayers-API.patch new file mode 100644 index 0000000000..17b9d923f2 --- /dev/null +++ b/patches/api-unmapped/0217-Add-setMaxPlayers-API.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 22 Aug 2020 23:59:25 +0200 +Subject: [PATCH] Add #setMaxPlayers API + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 1eaf6aae1e13c48a7f911e523015cb9b8cca8638..6228d7eca85fba52296c8d63d32804f32af1b421 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -171,6 +171,17 @@ public final class Bukkit { + return server.getMaxPlayers(); + } + ++ // Paper start ++ /** ++ * Set the maximum amount of players which can login to this server. ++ * ++ * @param maxPlayers the amount of players this server allows ++ */ ++ public static void setMaxPlayers(int maxPlayers) { ++ server.setMaxPlayers(maxPlayers); ++ } ++ // Paper end ++ + /** + * Get the game port that the server runs on. + * +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 8ee02c3d6cc8751704e5993fecd05293714e492f..6237578b373002c009efde4fb4c1864f0bf4f19e 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -144,6 +144,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + */ + public int getMaxPlayers(); + ++ // Paper start ++ /** ++ * Set the maximum amount of players which can login to this server. ++ * ++ * @param maxPlayers the amount of players this server allows ++ */ ++ public void setMaxPlayers(int maxPlayers); ++ // Paper end ++ + /** + * Get the game port that the server runs on. + * diff --git a/patches/api-unmapped/0218-Add-moon-phase-API.patch b/patches/api-unmapped/0218-Add-moon-phase-API.patch new file mode 100644 index 0000000000..c9e9827954 --- /dev/null +++ b/patches/api-unmapped/0218-Add-moon-phase-API.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Aug 2020 16:32:03 +0200 +Subject: [PATCH] Add moon phase API + + +diff --git a/src/main/java/io/papermc/paper/world/MoonPhase.java b/src/main/java/io/papermc/paper/world/MoonPhase.java +new file mode 100644 +index 0000000000000000000000000000000000000000..df05153397b42930cd53d37b30824c7e5f008f7e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/world/MoonPhase.java +@@ -0,0 +1,36 @@ ++package io.papermc.paper.world; ++ ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.HashMap; ++import java.util.Map; ++ ++public enum MoonPhase { ++ FULL_MOON(0L), ++ WANING_GIBBOUS(1L), ++ LAST_QUARTER(2L), ++ WANING_CRESCENT(3L), ++ NEW_MOON(4L), ++ WAXING_CRESCENT(5L), ++ FIRST_QUARTER(6L), ++ WAXING_GIBBOUS(7L); ++ ++ private final long day; ++ ++ MoonPhase(long day) { ++ this.day = day; ++ } ++ ++ private static final Map BY_DAY = new HashMap<>(); ++ ++ static { ++ for (MoonPhase phase : values()) { ++ BY_DAY.put(phase.day, phase); ++ } ++ } ++ ++ @NotNull ++ public static MoonPhase getPhase(long day) { ++ return BY_DAY.get(day % 8L); ++ } ++} +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 6441d4e45e5d5f008f95233cdc34048b8be38592..e20d863d1308b470a294cb7ab022aac4b9a91f71 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -70,6 +70,12 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + * @return The amount of Players in this world + */ + int getPlayerCount(); ++ ++ /** ++ * @return the current moon phase at the current time in the world ++ */ ++ @NotNull ++ io.papermc.paper.world.MoonPhase getMoonPhase(); + // Paper end + + /** diff --git a/patches/api-unmapped/0219-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/api-unmapped/0219-Add-playPickupItemAnimation-to-LivingEntity.patch new file mode 100644 index 0000000000..561ec4779e --- /dev/null +++ b/patches/api-unmapped/0219-Add-playPickupItemAnimation-to-LivingEntity.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 23 Aug 2020 19:36:08 +0200 +Subject: [PATCH] Add playPickupItemAnimation to LivingEntity + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index a46379b3a777a9071b0b13357bbd6af40dbfb569..c4fe44dce3bcb3502b26af7c76ec6b36c2a2bebe 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -815,5 +815,28 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + * @param jumping entity jump state + */ + void setJumping(boolean jumping); ++ ++ /** ++ * Plays pickup item animation towards this entity. ++ *

    ++ * This will remove the item on the client. ++ *

    ++ * Quantity is inferred to be that of the {@link Item}. ++ * ++ * @param item item to pickup ++ */ ++ default void playPickupItemAnimation(@NotNull Item item) { ++ playPickupItemAnimation(item, item.getItemStack().getAmount()); ++ } ++ ++ /** ++ * Plays pickup item animation towards this entity. ++ *

    ++ * This will remove the item on the client. ++ * ++ * @param item item to pickup ++ * @param quantity quantity of item ++ */ ++ void playPickupItemAnimation(@NotNull Item item, int quantity); + // Paper end + } diff --git a/patches/api-unmapped/0220-Add-BellRingEvent.patch b/patches/api-unmapped/0220-Add-BellRingEvent.patch new file mode 100644 index 0000000000..7862ad8c88 --- /dev/null +++ b/patches/api-unmapped/0220-Add-BellRingEvent.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Eearslya Sleiarion +Date: Mon, 24 Jun 2019 21:27:39 -0700 +Subject: [PATCH] Add BellRingEvent + +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/io/papermc/paper/event/block/BellRingEvent.java b/src/main/java/io/papermc/paper/event/block/BellRingEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..881e545df51409e6101b4bb49f699655a744f13f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/BellRingEvent.java +@@ -0,0 +1,55 @@ ++package io.papermc.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.bukkit.potion.PotionEffect; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when a bell is rung. ++ */ ++public class BellRingEvent extends BlockEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ private final Entity entity; ++ ++ public BellRingEvent(@NotNull Block block, @Nullable Entity entity) { ++ super(block); ++ this.entity = entity; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancelled) { ++ this.cancelled = cancelled; ++ } ++ ++ /** ++ * Gets the entity that rang the bell. ++ * ++ * @return the ringer or null if none ++ */ ++ @Nullable ++ public Entity getEntity() { ++ return entity; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0221-Brand-support.patch b/patches/api-unmapped/0221-Brand-support.patch new file mode 100644 index 0000000000..2c6d0a6ab9 --- /dev/null +++ b/patches/api-unmapped/0221-Brand-support.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DigitalRegent +Date: Mon, 6 Apr 2020 20:30:09 +0200 +Subject: [PATCH] Brand support + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 2530c811f52f51d6338900221b4681c952c1c752..828b2b0538d4f936bee57d9fca55774723e13970 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -2044,6 +2044,16 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + // Paper end + } + ++ // Paper start - brand support ++ /** ++ * Returns player's client brand name. If the client didn't send this information, the brand name will be null.
    ++ * For the Notchian client this name defaults to vanilla. Some modified clients report other names such as forge.
    ++ * @return client brand name ++ */ ++ @Nullable ++ String getClientBrandName(); ++ // Paper end ++ + @NotNull + @Override + Spigot spigot(); diff --git a/patches/api-unmapped/0222-Add-more-Evoker-API.patch b/patches/api-unmapped/0222-Add-more-Evoker-API.patch new file mode 100644 index 0000000000..0d6f0f7328 --- /dev/null +++ b/patches/api-unmapped/0222-Add-more-Evoker-API.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Aug 2020 15:22:44 +0200 +Subject: [PATCH] Add more Evoker API + + +diff --git a/src/main/java/org/bukkit/entity/Evoker.java b/src/main/java/org/bukkit/entity/Evoker.java +index f8d173adc09197418883dc7bc66dd8bfff8c5c72..76f81cd124090337876c9e5e469862a1c8da4ec8 100644 +--- a/src/main/java/org/bukkit/entity/Evoker.java ++++ b/src/main/java/org/bukkit/entity/Evoker.java +@@ -64,4 +64,19 @@ public interface Evoker extends Spellcaster { + */ + @Deprecated + void setCurrentSpell(@Nullable Spell spell); ++ ++ // Paper start ++ /** ++ * @return the sheep being targeted by the {@link Spell#WOLOLO wololo spell}, or {@code null} if none ++ */ ++ @Nullable ++ Sheep getWololoTarget(); ++ ++ /** ++ * Set the sheep to be the target of the {@link Spell#WOLOLO wololo spell}, or {@code null} to clear. ++ * ++ * @param sheep new wololo target ++ */ ++ void setWololoTarget(@Nullable Sheep sheep); ++ // Paper end + } diff --git a/patches/api-unmapped/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/api-unmapped/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch new file mode 100644 index 0000000000..bfa151e84b --- /dev/null +++ b/patches/api-unmapped/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Tue, 11 Aug 2020 19:17:46 +0200 +Subject: [PATCH] Add a way to get translation keys for blocks, entities and + materials + + +diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java +index 9c28351c7c3f60c6a3b4020329344f91efeedae1..69c85c3a1f45476f7de0a9399852d82eeb4f9c86 100644 +--- a/src/main/java/org/bukkit/Material.java ++++ b/src/main/java/org/bukkit/Material.java +@@ -3991,6 +3991,16 @@ public enum Material implements Keyed { + } + return false; + } ++ ++ /** ++ * Return the translation key for the Material, so the client can translate it into the active ++ * locale when using a TranslatableComponent. ++ * @return the translation key ++ */ ++ @NotNull ++ public String getTranslationKey() { ++ return Bukkit.getUnsafe().getTranslationKey(this); ++ } + // Paper end + + /** +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index e348034288c74ab80360086d71f0b7f61551df24..2d9264ffe0fee863f1b814952ef063daa7962d76 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -101,5 +101,34 @@ public interface UnsafeValues { + byte[] serializeItem(ItemStack item); + + ItemStack deserializeItem(byte[] data); ++ ++ /** ++ * Return the translation key for the Material, so the client can translate it into the active ++ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}. ++ * @return the translation key ++ */ ++ String getTranslationKey(Material mat); ++ ++ /** ++ * Return the translation key for the Block, so the client can translate it into the active ++ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}. ++ * @return the translation key ++ */ ++ String getTranslationKey(org.bukkit.block.Block block); ++ ++ /** ++ * Return the translation key for the EntityType, so the client can translate it into the active ++ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.
    ++ * This is null, when the EntityType isn't known to NMS (custom entities) ++ * @return the translation key ++ */ ++ String getTranslationKey(org.bukkit.entity.EntityType type); ++ ++ /** ++ * Return the translation key for the ItemStack, so the client can translate it into the active ++ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.
    ++ * @return the translation key ++ */ ++ String getTranslationKey(ItemStack itemStack); + // Paper end + } +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index e1cc36fbe808973227c0e8ca7166453235c90279..e6647c45f65bae916759cd899256f8130790d242 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -584,5 +584,13 @@ public interface Block extends Metadatable { + */ + @NotNull + com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup(); ++ ++ /** ++ * Return the translation key for the Block, so the client can translate it into the active ++ * locale when using a TranslatableComponent. ++ * @return the translation key ++ */ ++ @NotNull ++ String getTranslationKey(); + // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/EntityType.java b/src/main/java/org/bukkit/entity/EntityType.java +index 9be5371c7f398d0ec8241403661415ff40661067..f415b61b0d4b57e1557aaf240a0f2ad5915035fc 100644 +--- a/src/main/java/org/bukkit/entity/EntityType.java ++++ b/src/main/java/org/bukkit/entity/EntityType.java +@@ -419,4 +419,15 @@ public enum EntityType implements Keyed { + public boolean isAlive() { + return living; + } ++ ++ /** ++ * Return the translation key for the EntityType, so the client can translate it into the active ++ * locale when using a TranslatableComponent.
    ++ * This is null, when the EntityType isn't known to NMS (custom entities) ++ * @return the translation key ++ */ ++ @Nullable ++ String getTranslationKey() { ++ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); ++ } + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index 9a878e4fde31c015e2f3fdf365d5d16c30198685..bd96c06aca1fc18807e65c34f399ce2ebe891816 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -851,5 +851,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + ItemMeta itemMeta = getItemMeta(); + return itemMeta != null && itemMeta.hasItemFlag(flag); + } ++ ++ /** ++ * Gets the translation key for this itemstack. ++ * This is not the same as getting the translation key ++ * for the material of this itemstack. ++ * ++ * @return the translation key ++ */ ++ @NotNull ++ public String getTranslationKey() { ++ return Bukkit.getUnsafe().getTranslationKey(this); ++ } + // Paper end + } diff --git a/patches/api-unmapped/0224-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/api-unmapped/0224-Create-HoverEvent-from-ItemStack-Entity.patch new file mode 100644 index 0000000000..9a15253cfd --- /dev/null +++ b/patches/api-unmapped/0224-Create-HoverEvent-from-ItemStack-Entity.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ysl3000 +Date: Mon, 6 Jul 2020 22:17:37 +0200 +Subject: [PATCH] Create HoverEvent from ItemStack Entity + + +diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java +index e2bcc96ad067e2abfe9108b3a2235fe5da7ab3eb..3cbe5afc3548d4b7d0c6e625d9029506133676ff 100644 +--- a/src/main/java/org/bukkit/inventory/ItemFactory.java ++++ b/src/main/java/org/bukkit/inventory/ItemFactory.java +@@ -184,5 +184,62 @@ public interface ItemFactory { + */ + @Nullable + String getI18NDisplayName(@Nullable ItemStack item); ++ ++ /** ++ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that ItemStack for displaying. ++ * ++ * @param itemStack ++ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that ItemStack ++ */ ++ @NotNull ++ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull ItemStack itemStack); ++ ++ /** ++ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying. ++ * Uses the display name of the entity, if present. ++ * ++ * @param entity Entity to create the HoverEvent for ++ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} ++ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent()} ++ */ ++ @NotNull ++ @Deprecated ++ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity); ++ ++ /** ++ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying. ++ * ++ * @param entity Entity to create the HoverEvent for ++ * @param customName a custom name that should be displayed, if not passed entity name will be displayed ++ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} ++ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent(java.util.function.UnaryOperator)} ++ */ ++ @NotNull ++ @Deprecated ++ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @Nullable String customName); ++ ++ /** ++ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying. ++ * ++ * @param entity Entity to create the HoverEvent for ++ * @param customName a custom name that should be displayed, if not passed entity name will be displayed ++ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} ++ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent(java.util.function.UnaryOperator)} ++ */ ++ @NotNull ++ @Deprecated ++ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @Nullable net.md_5.bungee.api.chat.BaseComponent customName); ++ ++ /** ++ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying. ++ * ++ * @param entity Entity to create the HoverEvent for ++ * @param customName a custom name that should be displayed, if not passed entity name will be displayed ++ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} ++ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent(java.util.function.UnaryOperator)} ++ */ ++ @NotNull ++ @Deprecated ++ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @NotNull net.md_5.bungee.api.chat.BaseComponent[] customName); + // Paper end + } diff --git a/patches/api-unmapped/0225-Add-additional-open-container-api-to-HumanEntity.patch b/patches/api-unmapped/0225-Add-additional-open-container-api-to-HumanEntity.patch new file mode 100644 index 0000000000..53584ff633 --- /dev/null +++ b/patches/api-unmapped/0225-Add-additional-open-container-api-to-HumanEntity.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 26 Aug 2020 02:11:58 -0400 +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 b09d12390d5f77330ac84452e0fee63a169bd01f..77bff8fb6bfdf739e413084e13677a83e723c71e 100644 +--- a/src/main/java/org/bukkit/entity/HumanEntity.java ++++ b/src/main/java/org/bukkit/entity/HumanEntity.java +@@ -148,6 +148,92 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder + @Nullable + public InventoryView openMerchant(@NotNull Merchant merchant, boolean force); + ++ // Paper start - Add additional containers ++ /** ++ * Opens an empty anvil inventory window with the player's inventory ++ * on the bottom. ++ * ++ * @param location The location to attach it to. If null, the player's ++ * location is used. ++ * @param force If false, and there is no anvil block at the location, ++ * no inventory will be opened and null will be returned. ++ * @return The newly opened inventory view, or null if it could not be ++ * opened. ++ */ ++ @Nullable ++ public InventoryView openAnvil(@Nullable Location location, boolean force); ++ ++ /** ++ * Opens an empty cartography table inventory window with the player's inventory ++ * on the bottom. ++ * ++ * @param location The location to attach it to. If null, the player's ++ * location is used. ++ * @param force If false, and there is no cartography table block at the location, ++ * no inventory will be opened and null will be returned. ++ * @return The newly opened inventory view, or null if it could not be ++ * opened. ++ */ ++ @Nullable ++ public InventoryView openCartographyTable(@Nullable Location location, boolean force); ++ ++ /** ++ * Opens an empty grindstone inventory window with the player's inventory ++ * on the bottom. ++ * ++ * @param location The location to attach it to. If null, the player's ++ * location is used. ++ * @param force If false, and there is no grindstone block at the location, ++ * no inventory will be opened and null will be returned. ++ * @return The newly opened inventory view, or null if it could not be ++ * opened. ++ */ ++ @Nullable ++ public InventoryView openGrindstone(@Nullable Location location, boolean force); ++ ++ /** ++ * Opens an empty loom inventory window with the player's inventory ++ * on the bottom. ++ * ++ * @param location The location to attach it to. If null, the player's ++ * location is used. ++ * @param force If false, and there is no loom block at the location, ++ * no inventory will be opened and null will be returned. ++ * @return The newly opened inventory view, or null if it could not be ++ * opened. ++ */ ++ @Nullable ++ public InventoryView openLoom(@Nullable Location location, boolean force); ++ ++ /** ++ * Opens an empty smithing table inventory window with the player's inventory ++ * on the bottom. ++ * ++ * @param location The location to attach it to. If null, the player's ++ * location is used. ++ * @param force If false, and there is no smithing table block at the location, ++ * no inventory will be opened and null will be returned. ++ * @return The newly opened inventory view, or null if it could not be ++ * opened. ++ */ ++ @Nullable ++ public InventoryView openSmithingTable(@Nullable Location location, boolean force); ++ ++ /** ++ * Opens an empty stonecutter inventory window with the player's inventory ++ * on the bottom. ++ * ++ * @param location The location to attach it to. If null, the player's ++ * location is used. ++ * @param force If false, and there is no stonecutter block at the location, ++ * no inventory will be opened and null will be returned. ++ * @return The newly opened inventory view, or null if it could not be ++ * opened. ++ */ ++ @Nullable ++ public InventoryView openStonecutter(@Nullable Location location, boolean force); ++ // Paper end ++ + /** + * Force-closes the currently open inventory view for this player, if any. + */ diff --git a/patches/api-unmapped/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/api-unmapped/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch new file mode 100644 index 0000000000..a92a435f5a --- /dev/null +++ b/patches/api-unmapped/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Fri, 28 Aug 2020 01:41:31 +0200 +Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and + non-conflicting Entity Ids + + +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 2d9264ffe0fee863f1b814952ef063daa7962d76..84eda68281c6c6968d95b1313a33696c3a9980d4 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -130,5 +130,12 @@ public interface UnsafeValues { + * @return the translation key + */ + String getTranslationKey(ItemStack itemStack); ++ ++ /** ++ * Creates and returns the next EntityId available. ++ *

    ++ * Use this when sending custom packets, so that there are no collisions on the client or server. ++ */ ++ public int nextEntityId(); + // Paper end + } diff --git a/patches/api-unmapped/0227-Entity-isTicking.patch b/patches/api-unmapped/0227-Entity-isTicking.patch new file mode 100644 index 0000000000..315c89bf3b --- /dev/null +++ b/patches/api-unmapped/0227-Entity-isTicking.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 3 Oct 2020 21:39:07 -0500 +Subject: [PATCH] Entity#isTicking + + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index ecb5595332ab493224d06a75904e142ab541aad9..4ed8c74f874dbd1017764d7592acfdafbc5d5fe1 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -744,5 +744,10 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + * Check if entity is in lava + */ + public boolean isInLava(); ++ ++ /** ++ * Check if entity is inside a ticking chunk ++ */ ++ public boolean isTicking(); + // Paper end + } diff --git a/patches/api-unmapped/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch b/patches/api-unmapped/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch new file mode 100644 index 0000000000..2947f78299 --- /dev/null +++ b/patches/api-unmapped/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aurora +Date: Sat, 3 Oct 2020 16:28:41 +0200 +Subject: [PATCH] Clarify the Javadocs for Entity.getEntitySpawnReason() + + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 4ed8c74f874dbd1017764d7592acfdafbc5d5fe1..14470b23f7b4102cf2dca777bc832ebcbcd5edc6 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -710,7 +710,7 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + Chunk getChunk(); + + /** +- * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity. ++ * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that initially spawned this entity. + */ + @NotNull + org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason(); diff --git a/patches/api-unmapped/0229-Villager-resetOffers.patch b/patches/api-unmapped/0229-Villager-resetOffers.patch new file mode 100644 index 0000000000..60fedfba0f --- /dev/null +++ b/patches/api-unmapped/0229-Villager-resetOffers.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Mon, 7 Oct 2019 00:15:28 -0500 +Subject: [PATCH] Villager#resetOffers + + +diff --git a/src/main/java/org/bukkit/entity/AbstractVillager.java b/src/main/java/org/bukkit/entity/AbstractVillager.java +index d2b0c08554dba4d34b37b440f1d77ae0e64cb99e..7fbe31c4fd69d4fca7ef96c0a56b0e0204d60cf4 100644 +--- a/src/main/java/org/bukkit/entity/AbstractVillager.java ++++ b/src/main/java/org/bukkit/entity/AbstractVillager.java +@@ -21,4 +21,11 @@ public interface AbstractVillager extends Breedable, NPC, InventoryHolder, Merch + @NotNull + @Override + Inventory getInventory(); ++ ++ // Paper start ++ /** ++ * Reset this villager's trade offers ++ */ ++ public void resetOffers(); ++ // Paper end + } diff --git a/patches/api-unmapped/0230-Player-elytra-boost-API.patch b/patches/api-unmapped/0230-Player-elytra-boost-API.patch new file mode 100644 index 0000000000..1f9e683db7 --- /dev/null +++ b/patches/api-unmapped/0230-Player-elytra-boost-API.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Tue, 14 Apr 2020 12:06:14 +0200 +Subject: [PATCH] Player elytra boost API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 828b2b0538d4f936bee57d9fca55774723e13970..7aa9fb852dce23c53fee80e97e0dcdb278ae82ba 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1916,6 +1916,19 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + @NotNull + T getClientOption(@NotNull ClientOption option); ++ ++ /** ++ * Boost a Player that's {@link #isGliding()} using a {@link Firework}. ++ * If the creation of the entity is cancelled, no boosting is done. ++ * This method does not fire {@link com.destroystokyo.paper.event.player.PlayerElytraBoostEvent}. ++ * ++ * @param firework The {@link Material#FIREWORK_ROCKET} to boost the player with ++ * @return The {@link Firework} boosting the Player or null if the spawning of the entity was cancelled ++ * @throws IllegalArgumentException if {@link #isGliding()} is false ++ * or if the {@code firework} isn't a {@link Material#FIREWORK_ROCKET} ++ */ ++ @Nullable ++ Firework boostElytra(@NotNull ItemStack firework); + // Paper end + + // Spigot start diff --git a/patches/api-unmapped/0231-Add-getOfflinePlayerIfCached-String.patch b/patches/api-unmapped/0231-Add-getOfflinePlayerIfCached-String.patch new file mode 100644 index 0000000000..f39340e7f4 --- /dev/null +++ b/patches/api-unmapped/0231-Add-getOfflinePlayerIfCached-String.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: oxygencraft <21054297+oxygencraft@users.noreply.github.com> +Date: Sun, 25 Oct 2020 18:35:58 +1100 +Subject: [PATCH] Add getOfflinePlayerIfCached(String) + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 3a930ee1b1dce3639d590a8646f68b4ab92207fb..a498c5267458767e1f7802ab3d3b7a22f987d985 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -962,6 +962,27 @@ public final class Bukkit { + return server.getOfflinePlayer(name); + } + ++ // Paper start ++ /** ++ * Gets the player by the given name, regardless if they are offline or ++ * online. ++ *

    ++ * This will not make a web request to get the UUID for the given name, ++ * thus this method will not block. However this method will return ++ * {@code null} if the player is not cached. ++ *

    ++ * ++ * @param name the name of the player to retrieve ++ * @return an offline player if cached, {@code null} otherwise ++ * @see #getOfflinePlayer(String) ++ * @see #getOfflinePlayer(java.util.UUID) ++ */ ++ @Nullable ++ public static OfflinePlayer getOfflinePlayerIfCached(@NotNull String name) { ++ return server.getOfflinePlayerIfCached(name); ++ } ++ // Paper end ++ + /** + * 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 9d8886526ae0cd31ec5771462f3cd57692b1cb53..bbc7a1a35da6c8c66c18779ba4fb1aca1a567e6f 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -808,6 +808,25 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @NotNull + public OfflinePlayer getOfflinePlayer(@NotNull String name); + ++ // Paper start ++ /** ++ * Gets the player by the given name, regardless if they are offline or ++ * online. ++ *

    ++ * This will not make a web request to get the UUID for the given name, ++ * thus this method will not block. However this method will return ++ * {@code null} if the player is not cached. ++ *

    ++ * ++ * @param name the name of the player to retrieve ++ * @return an offline player if cached, {@code null} otherwise ++ * @see #getOfflinePlayer(String) ++ * @see #getOfflinePlayer(java.util.UUID) ++ */ ++ @Nullable ++ public OfflinePlayer getOfflinePlayerIfCached(@NotNull String name); ++ // Paper end ++ + /** + * Gets the player by the given UUID, regardless if they are offline or + * online. diff --git a/patches/api-unmapped/0232-Add-ignore-discounts-API.patch b/patches/api-unmapped/0232-Add-ignore-discounts-API.patch new file mode 100644 index 0000000000..492c998c91 --- /dev/null +++ b/patches/api-unmapped/0232-Add-ignore-discounts-API.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Mon, 9 Nov 2020 20:33:38 +0100 +Subject: [PATCH] Add ignore discounts API + + +diff --git a/src/main/java/org/bukkit/inventory/MerchantRecipe.java b/src/main/java/org/bukkit/inventory/MerchantRecipe.java +index 1fb4a1c53791776f9c5a952a592f15fc35cb2703..2be2f3fe655c417bfc8f8e840f9e9415d168f37e 100644 +--- a/src/main/java/org/bukkit/inventory/MerchantRecipe.java ++++ b/src/main/java/org/bukkit/inventory/MerchantRecipe.java +@@ -28,6 +28,7 @@ public class MerchantRecipe implements Recipe { + private boolean experienceReward; + private int villagerExperience; + private float priceMultiplier; ++ private boolean ignoreDiscounts; // Paper + + public MerchantRecipe(@NotNull ItemStack result, int maxUses) { + this(result, 0, maxUses, false); +@@ -38,6 +39,12 @@ public class MerchantRecipe implements Recipe { + } + + public MerchantRecipe(@NotNull ItemStack result, int uses, int maxUses, boolean experienceReward, int villagerExperience, float priceMultiplier) { ++ // Paper start - add ignoreDiscounts param ++ this(result, uses, maxUses, experienceReward, villagerExperience, priceMultiplier, false); ++ } ++ public MerchantRecipe(@NotNull ItemStack result, int uses, int maxUses, boolean experienceReward, int villagerExperience, float priceMultiplier, boolean ignoreDiscounts) { ++ this.ignoreDiscounts = ignoreDiscounts; ++ // Paper end + this.result = result; + this.uses = uses; + this.maxUses = maxUses; +@@ -172,4 +179,20 @@ public class MerchantRecipe implements Recipe { + public void setPriceMultiplier(float priceMultiplier) { + this.priceMultiplier = priceMultiplier; + } ++ ++ // Paper start ++ /** ++ * @return Whether all discounts on this trade should be ignored. ++ */ ++ public boolean shouldIgnoreDiscounts() { ++ return ignoreDiscounts; ++ } ++ ++ /** ++ * @param ignoreDiscounts Whether all discounts on this trade should be ignored. ++ */ ++ public void setIgnoreDiscounts(boolean ignoreDiscounts) { ++ this.ignoreDiscounts = ignoreDiscounts; ++ } ++ // Paper end + } diff --git a/patches/api-unmapped/0233-Item-no-age-no-player-pickup.patch b/patches/api-unmapped/0233-Item-no-age-no-player-pickup.patch new file mode 100644 index 0000000000..142a8b5202 --- /dev/null +++ b/patches/api-unmapped/0233-Item-no-age-no-player-pickup.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Smith +Date: Sat, 7 Nov 2020 01:20:27 +0000 +Subject: [PATCH] Item no age & no player pickup + + +diff --git a/src/main/java/org/bukkit/entity/Item.java b/src/main/java/org/bukkit/entity/Item.java +index c404a5b8efea7c780db5ddae19456753808abb3d..0ee072645ecf1bf5feb74de6960947ef76db366e 100644 +--- a/src/main/java/org/bukkit/entity/Item.java ++++ b/src/main/java/org/bukkit/entity/Item.java +@@ -90,5 +90,34 @@ public interface Item extends Entity { + * @param canMobPickup True to allow non-player entity pickup + */ + public void setCanMobPickup(boolean canMobPickup); ++ ++ /** ++ * Gets whether the player can pickup the item or not ++ * ++ * @return True if a player can pickup the item ++ */ ++ public boolean canPlayerPickup(); ++ ++ /** ++ * Sets whether the item can be picked up or not. Modifies the pickup delay value to do so. ++ * ++ * @param canPlayerPickup True if the player can pickup the item ++ */ ++ public void setCanPlayerPickup(boolean canPlayerPickup); ++ ++ /** ++ * Gets whether the item will age and despawn from being on the ground too long ++ * ++ * @return True if the item will age ++ */ ++ public boolean willAge(); ++ ++ /** ++ * Sets whether the item will age or not. If the item is not ageing, it will not despawn ++ * by being on the ground for too long. ++ * ++ * @param willAge True if the item should age ++ */ ++ public void setWillAge(boolean willAge); + // Paper end + } diff --git a/patches/api-unmapped/0234-Beacon-API-custom-effect-ranges.patch b/patches/api-unmapped/0234-Beacon-API-custom-effect-ranges.patch new file mode 100644 index 0000000000..ff56b99ebf --- /dev/null +++ b/patches/api-unmapped/0234-Beacon-API-custom-effect-ranges.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 24 Jun 2020 12:38:15 -0600 +Subject: [PATCH] Beacon API - custom effect ranges + + +diff --git a/src/main/java/org/bukkit/block/Beacon.java b/src/main/java/org/bukkit/block/Beacon.java +index 6349fa9da3f96df3553fb9552c1cab95338cecb0..78475fc6faff0f295828d7b53792001d51aa2889 100644 +--- a/src/main/java/org/bukkit/block/Beacon.java ++++ b/src/main/java/org/bukkit/block/Beacon.java +@@ -64,4 +64,26 @@ public interface Beacon extends TileState, Lockable, Nameable { + * @param effect desired secondary effect + */ + void setSecondaryEffect(@Nullable PotionEffectType effect); ++ ++ // Paper start - Custom effect ranges ++ /** ++ * Gets the effect range of this beacon. ++ * A negative range value means the beacon is using its default range based on tier. ++ * @return Either the custom range set with {@link #setEffectRange(double)} or the range based on the beacon tier. ++ */ ++ double getEffectRange(); ++ ++ /** ++ * Sets the effect range of the beacon ++ * A negative range value means the beacon is using its default range based on tier. ++ * @param range Radius of effect range. ++ */ ++ void setEffectRange(double range); ++ ++ /** ++ * Resets the custom range from this beacon and falls back to the range based on the the beacon tier. ++ * Shortcut for setting the effect range to a negative number. ++ */ ++ void resetEffectRange(); ++ // Paper end + } diff --git a/patches/api-unmapped/0235-Add-API-for-quit-reason.patch b/patches/api-unmapped/0235-Add-API-for-quit-reason.patch new file mode 100644 index 0000000000..63d864224b --- /dev/null +++ b/patches/api-unmapped/0235-Add-API-for-quit-reason.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 14 Nov 2020 16:19:58 +0100 +Subject: [PATCH] Add API for quit reason + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java +index 849e8f10dd77e9fb46aab17752b8f1ff79e9d42e..b6016aa1e91863efc252eecab69ade6f54c89f27 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java +@@ -11,16 +11,28 @@ import org.jetbrains.annotations.Nullable; + public class PlayerQuitEvent extends PlayerEvent { + private static final HandlerList handlers = new HandlerList(); + private net.kyori.adventure.text.Component quitMessage; // Paper ++ private final QuitReason reason; // Paper + + @Deprecated // Paper + public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage) { ++ // Paper start ++ this(who, quitMessage, null); ++ } ++ @Deprecated // Paper ++ public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage, @Nullable QuitReason quitReason) { + super(who); + this.quitMessage = quitMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(quitMessage) : null; // Paper ++ this.reason = quitReason == null ? QuitReason.DISCONNECTED : quitReason; + } + // Paper start ++ @Deprecated + public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage) { ++ this(who, quitMessage, null); ++ } ++ public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage, @Nullable QuitReason quitReason) { + super(who); + this.quitMessage = quitMessage; ++ this.reason = quitReason == null ? QuitReason.DISCONNECTED : quitReason; + } + + /** +@@ -75,4 +87,39 @@ public class PlayerQuitEvent extends PlayerEvent { + public static HandlerList getHandlerList() { + return handlers; + } ++ ++ // Paper start ++ @NotNull ++ public QuitReason getReason() { ++ return this.reason; ++ } ++ ++ public enum QuitReason { ++ /** ++ * The player left on their own behalf. ++ *

    ++ * This does not mean they pressed the disconnect button in their client, but rather that the client severed the ++ * connection themselves. This may occur if no keep-alive packet is received on their side, among other things. ++ */ ++ DISCONNECTED, ++ ++ /** ++ * The player was kicked from the server. ++ */ ++ KICKED, ++ ++ /** ++ * The player has timed out. ++ */ ++ TIMED_OUT, ++ ++ /** ++ * The player's connection has entered an erroneous state. ++ *

    ++ * Reasons for this may include invalid packets, invalid data, and uncaught exceptions in the packet handler, ++ * among others. ++ */ ++ ERRONEOUS_STATE, ++ } ++ // Paper end + } diff --git a/patches/api-unmapped/0236-Add-Destroy-Speed-API.patch b/patches/api-unmapped/0236-Add-Destroy-Speed-API.patch new file mode 100644 index 0000000000..bdf3dd2bbe --- /dev/null +++ b/patches/api-unmapped/0236-Add-Destroy-Speed-API.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ineusia +Date: Mon, 26 Oct 2020 11:37:48 -0500 +Subject: [PATCH] Add Destroy Speed API + +Co-authored-by: Jake Potrebic + +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index e6647c45f65bae916759cd899256f8130790d242..e4e3be0ee9c557e04d9ed1ab6f1569bd36a0e846 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -592,5 +592,29 @@ public interface Block extends Metadatable { + */ + @NotNull + String getTranslationKey(); ++ ++ /** ++ * Gets the speed at which this block will be destroyed by a given {@link ItemStack} ++ * ++ *

    Default value is 1.0

    ++ * ++ * @param itemStack {@link ItemStack} used to mine this Block ++ * @return the speed that this Block will be mined by the given {@link ItemStack} ++ */ ++ @NotNull ++ public default float getDestroySpeed(@NotNull ItemStack itemStack) { ++ return getDestroySpeed(itemStack, false); ++ } ++ ++ /** ++ * Gets the speed at which this blook will be destroyed by a given {@link org.bukkit.inventory.ItemStack} ++ *

    ++ * Default value is 1.0 ++ * @param itemStack {@link org.bukkit.inventory.ItemStack} used to mine this Block ++ * @param considerEnchants true to look at enchants on the itemstack ++ * @return the speed that this Block will be mined by the given {@link org.bukkit.inventory.ItemStack} ++ */ ++ @NotNull ++ float getDestroySpeed(@NotNull ItemStack itemStack, boolean considerEnchants); + // Paper end + } diff --git a/patches/api-unmapped/0237-Add-LivingEntity-clearActiveItem.patch b/patches/api-unmapped/0237-Add-LivingEntity-clearActiveItem.patch new file mode 100644 index 0000000000..bb5b5e0b5e --- /dev/null +++ b/patches/api-unmapped/0237-Add-LivingEntity-clearActiveItem.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Anrza +Date: Wed, 15 Jul 2020 12:07:58 +0200 +Subject: [PATCH] Add LivingEntity#clearActiveItem + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 9bf525b795ff1d88d2596b1f2bc787ce0df047bb..e535750d01a6c1bf4b1fe94df518166213da9b08 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -766,6 +766,13 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + @Nullable + ItemStack getActiveItem(); + ++ // Paper start ++ /** ++ * Interrupts any ongoing active "usage" or consumption or an item. ++ */ ++ void clearActiveItem(); ++ // Paper end ++ + /** + * Get's remaining time a player needs to keep hands raised with an item to finish using it. + * @return Remaining ticks to use the item diff --git a/patches/api-unmapped/0238-Add-PlayerItemCooldownEvent.patch b/patches/api-unmapped/0238-Add-PlayerItemCooldownEvent.patch new file mode 100644 index 0000000000..3bf6084e14 --- /dev/null +++ b/patches/api-unmapped/0238-Add-PlayerItemCooldownEvent.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Tue, 25 Aug 2020 13:45:15 +0200 +Subject: [PATCH] Add PlayerItemCooldownEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerItemCooldownEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerItemCooldownEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..58d18f05af13d836ddc62fcd30befcb06f07c57c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerItemCooldownEvent.java +@@ -0,0 +1,77 @@ ++package io.papermc.paper.event.player; ++ ++import com.google.common.base.Preconditions; ++import org.bukkit.Material; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired when a player receives an item cooldown. ++ */ ++public class PlayerItemCooldownEvent extends PlayerEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ @NotNull ++ private final Material type; ++ private boolean cancelled; ++ private int cooldown; ++ ++ public PlayerItemCooldownEvent(@NotNull Player player, @NotNull Material type, int cooldown) { ++ super(player); ++ this.type = type; ++ this.cooldown = cooldown; ++ } ++ ++ /** ++ * Get the material affected by the cooldown. ++ * ++ * @return material affected by the cooldown ++ */ ++ @NotNull ++ public Material getType() { ++ return type; ++ } ++ ++ /** ++ * Gets the cooldown in ticks. ++ * ++ * @return cooldown in ticks ++ */ ++ public int getCooldown() { ++ return cooldown; ++ } ++ ++ /** ++ * Sets the cooldown of the material in ticks. ++ * Setting the cooldown to 0 results in removing an already existing cooldown for the material. ++ * ++ * @param cooldown cooldown in ticks, has to be a positive number ++ */ ++ public void setCooldown(int cooldown) { ++ Preconditions.checkArgument(cooldown >= 0, "The cooldown has to be equal to or greater than 0!"); ++ this.cooldown = cooldown; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0239-More-lightning-API.patch b/patches/api-unmapped/0239-More-lightning-API.patch new file mode 100644 index 0000000000..1b6f512299 --- /dev/null +++ b/patches/api-unmapped/0239-More-lightning-API.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Sun, 26 Jul 2020 14:44:16 +0200 +Subject: [PATCH] More lightning API + + +diff --git a/src/main/java/org/bukkit/entity/LightningStrike.java b/src/main/java/org/bukkit/entity/LightningStrike.java +index be347c3d0291f44036bae29a4e7e4645d6a4cdf6..2c81a3f685588431a3c7675c84b35a28975232af 100644 +--- a/src/main/java/org/bukkit/entity/LightningStrike.java ++++ b/src/main/java/org/bukkit/entity/LightningStrike.java +@@ -31,4 +31,38 @@ public interface LightningStrike extends Entity { + @Override + Spigot spigot(); + // Spigot end ++ ++ // Paper start ++ /** ++ * Returns the amount of flash iterations that will be done before the lightning dies. ++ * ++ * @see #getLifeTicks() for how long the current flash will last ++ * @return amount of flashes that will be shown before the lightning dies ++ */ ++ int getFlashCount(); ++ ++ /** ++ * Sets the amount of life iterations that will be done before the lightning dies. ++ * Default number of flashes on creation is between 1-3. ++ * ++ * @param flashes amount of iterations that will be done before the lightning dies, must to be a positive number ++ */ ++ void setFlashCount(int flashes); ++ ++ /** ++ * Returns the amount of ticks the current flash will do damage for. ++ * Starts with 2 by default, will damage while it is equal to or above 0, with the next flash beginning somewhere between 0 and -9. ++ * ++ * @return ticks the current flash will do damage for ++ */ ++ int getLifeTicks(); ++ ++ /** ++ * Sets the amount of ticks the current flash will do damage/fire for. ++ * Default is 2 for each flash, on which the sound and effect will also be played. ++ * ++ * @param lifeTicks ticks the current flash will do damage for ++ */ ++ void setLifeTicks(int lifeTicks); ++ // Paper end + } diff --git a/patches/api-unmapped/0240-Add-PlayerShearBlockEvent.patch b/patches/api-unmapped/0240-Add-PlayerShearBlockEvent.patch new file mode 100644 index 0000000000..051544b4a9 --- /dev/null +++ b/patches/api-unmapped/0240-Add-PlayerShearBlockEvent.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Thu, 27 Aug 2020 12:32:35 -0400 +Subject: [PATCH] Add PlayerShearBlockEvent + + +diff --git a/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java b/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..aa7d440b797eac9e62678d03cc87f42838758bfd +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java +@@ -0,0 +1,108 @@ ++package io.papermc.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.List; ++ ++/** ++ * Called when a player uses sheers on a block. ++ *

    ++ * This event is not called when breaking blocks with shears but instead only when a ++ * player uses the sheer item on a block to garner drops from said block and/or change its state. ++ *

    ++ * Examples include shearing a pumpkin to turn it into a carved pumpkin or shearing a beehive to get honeycomb. ++ */ ++public class PlayerShearBlockEvent extends PlayerEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled = false; ++ private final Block block; ++ private final ItemStack item; ++ private final EquipmentSlot hand; ++ private final List drops; ++ ++ public PlayerShearBlockEvent(@NotNull Player who, @NotNull Block block, @NotNull ItemStack item, @NotNull EquipmentSlot hand, @NotNull List drops) { ++ super(who); ++ this.block = block; ++ this.item = item; ++ this.hand = hand; ++ this.drops = drops; ++ } ++ ++ /** ++ * Gets the block being sheared in this event. ++ * ++ * @return The {@link Block} which block is being sheared in this event. ++ */ ++ @NotNull ++ public Block getBlock() { ++ return block; ++ } ++ ++ /** ++ * Gets the item used to shear the block. ++ * ++ * @return The {@link ItemStack} of the shears. ++ */ ++ @NotNull ++ public ItemStack getItem() { ++ return item; ++ } ++ ++ /** ++ * Gets the hand used to shear the block. ++ * ++ * @return Either {@link EquipmentSlot#HAND} OR {@link EquipmentSlot#OFF_HAND}. ++ */ ++ @NotNull ++ public EquipmentSlot getHand() { ++ return hand; ++ } ++ ++ /** ++ * Gets the resulting drops of this event. ++ * ++ * @return A {@link List list} of {@link ItemStack items} that will be dropped as result of this event. ++ */ ++ @NotNull ++ public List getDrops() { ++ return drops; ++ } ++ ++ /** ++ * Gets whether the shearing of the block should be cancelled or not. ++ * ++ * @return Whether the shearing of the block should be cancelled or not. ++ */ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * Sets whether the shearing of the block should be cancelled or not. ++ * ++ * @param cancel whether the shearing of the block should be cancelled or not. ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0241-Enable-multi-release-plugin-jars.patch b/patches/api-unmapped/0241-Enable-multi-release-plugin-jars.patch new file mode 100644 index 0000000000..9f71d1c074 --- /dev/null +++ b/patches/api-unmapped/0241-Enable-multi-release-plugin-jars.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Fri, 4 Dec 2020 15:53:19 -0800 +Subject: [PATCH] Enable multi-release plugin jars + + +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index 11e5618ff66385574ba04db0942a75227cf8eb0f..c833cee9fddd12afdfe6bde1435559819b9ad656 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -58,7 +58,18 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + this.description = description; + this.dataFolder = dataFolder; + this.file = file; +- this.jar = new JarFile(file); ++ // Paper - enable multi-release jars for Java 9+ ++ JarFile jarFile; ++ try { ++ final java.lang.reflect.Method runtimeVersionMethod = JarFile.class.getMethod("runtimeVersion"); ++ final Object runtimeVersion = runtimeVersionMethod.invoke(null); ++ @SuppressWarnings("JavaReflectionMemberAccess") final java.lang.reflect.Constructor constructor = JarFile.class.getConstructor(File.class, boolean.class, int.class, runtimeVersion.getClass()); ++ jarFile = constructor.newInstance(file, true, java.util.zip.ZipFile.OPEN_READ, runtimeVersion); ++ } catch (Exception ignored) { ++ jarFile = new JarFile(file); ++ } ++ this.jar = jarFile; ++ // Paper end + this.manifest = jar.getManifest(); + this.url = file.toURI().toURL(); + this.libraryLoader = libraryLoader; diff --git a/patches/api-unmapped/0242-Player-Chunk-Load-Unload-Events.patch b/patches/api-unmapped/0242-Player-Chunk-Load-Unload-Events.patch new file mode 100644 index 0000000000..e2ce87ec9d --- /dev/null +++ b/patches/api-unmapped/0242-Player-Chunk-Load-Unload-Events.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ysl3000 +Date: Mon, 5 Oct 2020 21:24:45 +0200 +Subject: [PATCH] Player Chunk Load/Unload Events + + +diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2c1cda1126e577a88f19071e958eddb5a38785af +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java +@@ -0,0 +1,42 @@ ++package io.papermc.paper.event.packet; ++ ++import org.bukkit.Chunk; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.world.ChunkEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Is called when a {@link org.bukkit.entity.Player} receives a {@link org.bukkit.Chunk} ++ *

    ++ * Can for example be used for spawning a fake entity when the player receives a chunk. ++ * ++ * Should only be used for packet/clientside related stuff. ++ * Not intended for modifying server side state. ++ */ ++public class PlayerChunkLoadEvent extends ChunkEvent { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private final Player player; ++ ++ public PlayerChunkLoadEvent(@NotNull Chunk chunk, @NotNull Player player) { ++ super(chunk); ++ this.player = player; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public Player getPlayer() { ++ return player; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..12163a7b0591a7d022dc7eb9ee6608a1b6c39d9b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java +@@ -0,0 +1,40 @@ ++package io.papermc.paper.event.packet; ++ ++import org.bukkit.Chunk; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.world.ChunkEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Is called when a {@link Player} receives a chunk unload packet. ++ * ++ * Should only be used for packet/clientside related stuff. ++ * Not intended for modifying server side. ++ */ ++public class PlayerChunkUnloadEvent extends ChunkEvent { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private final Player player; ++ ++ public PlayerChunkUnloadEvent(@NotNull Chunk chunk, @NotNull Player player) { ++ super(chunk); ++ this.player = player; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public Player getPlayer() { ++ return player; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0243-Expose-LivingEntity-hurt-direction.patch b/patches/api-unmapped/0243-Expose-LivingEntity-hurt-direction.patch new file mode 100644 index 0000000000..95b46eabc4 --- /dev/null +++ b/patches/api-unmapped/0243-Expose-LivingEntity-hurt-direction.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 13 Dec 2020 05:32:12 +0200 +Subject: [PATCH] Expose LivingEntity hurt direction + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index b96b5f4f2fc754298e2223b2f449a0755469278c..b6de41e3e718fa5d1b82c6f68b153e60a81265e7 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -845,5 +845,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + * @param quantity quantity of item + */ + void playPickupItemAnimation(@NotNull Item item, int quantity); ++ ++ /** ++ * Gets player hurt direction ++ * ++ * @return hurt direction ++ */ ++ float getHurtDirection(); ++ ++ /** ++ * Sets player hurt direction ++ * ++ * @param hurtDirection hurt direction ++ */ ++ void setHurtDirection(float hurtDirection); + // Paper end + } diff --git a/patches/api-unmapped/0244-Added-PlayerTradeEvent.patch b/patches/api-unmapped/0244-Added-PlayerTradeEvent.patch new file mode 100644 index 0000000000..e09b088160 --- /dev/null +++ b/patches/api-unmapped/0244-Added-PlayerTradeEvent.patch @@ -0,0 +1,166 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 2 Jul 2020 16:10:10 -0700 +Subject: [PATCH] Added PlayerTradeEvent + +[Amendment: Alexander ] +PlayerTradeEvent is used for player purchases from villagers and wandering +traders, but not custom merchants created via Bukkit.createMerchant(). During +discussions in Discord it was decided that it'd be better to add a new event +that PlayerTradeEvent inherits from than change getVillager()'s annotation to +@Nullable, especially since that'd also infringe on the implication of the +event being about villager trades. + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerPurchaseEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerPurchaseEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c5648055c5e815474bf1e564a5c192ff5c0624fb +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerPurchaseEvent.java +@@ -0,0 +1,112 @@ ++package io.papermc.paper.event.player; ++ ++import java.util.Objects; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.MerchantRecipe; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a player trades with a standalone merchant GUI. ++ */ ++public class PlayerPurchaseEvent extends PlayerEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ ++ private boolean increaseTradeUses; ++ private boolean rewardExp; ++ private MerchantRecipe trade; ++ ++ public PlayerPurchaseEvent(@NotNull Player player, ++ @NotNull MerchantRecipe trade, ++ boolean rewardExp, ++ boolean increaseTradeUses) { ++ super(Objects.requireNonNull(player, "Player cannot be null!")); ++ setTrade(trade); ++ this.rewardExp = rewardExp; ++ this.increaseTradeUses = increaseTradeUses; ++ } ++ ++ /** ++ * Gets the associated trade with this event ++ * @return the trade ++ */ ++ @NotNull ++ public MerchantRecipe getTrade() { ++ return this.trade; ++ } ++ ++ /** ++ * Sets the trade. This is then used to determine the next prices ++ * @param trade the trade to use ++ */ ++ public void setTrade(@NotNull MerchantRecipe trade) { ++ this.trade = Objects.requireNonNull(trade, "Trade cannot be null!"); ++ } ++ ++ /** ++ * @return will trade try to reward exp ++ */ ++ public boolean isRewardingExp() { ++ return this.rewardExp; ++ } ++ ++ /** ++ * Sets whether the trade will try to reward exp ++ * @param rewardExp try to reward exp ++ */ ++ public void setRewardExp(boolean rewardExp) { ++ this.rewardExp = rewardExp; ++ } ++ ++ /** ++ * @return whether or not the trade will count as a use of the trade ++ */ ++ public boolean willIncreaseTradeUses() { ++ return this.increaseTradeUses; ++ } ++ ++ /** ++ * Sets whether or not the trade will count as a use ++ * @param increaseTradeUses true to count/false to not count ++ */ ++ public void setIncreaseTradeUses(boolean increaseTradeUses) { ++ this.increaseTradeUses = increaseTradeUses; ++ } ++ ++ /** ++ * Gets the cancellation state of this event. A cancelled event will not ++ * be executed in the server, but will still pass to other plugins ++ * ++ * @return true if this event is cancelled ++ */ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ /** ++ * Sets the cancellation state of this event. A cancelled event will not ++ * be executed in the server, but will still pass to other plugins. ++ * ++ * @param cancel true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java +new file mode 100755 +index 0000000000000000000000000000000000000000..a41fc186746b87f76347dfcc1f80d0969398322b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java +@@ -0,0 +1,29 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.entity.AbstractVillager; ++import org.bukkit.entity.Player; ++import org.bukkit.inventory.MerchantRecipe; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a player trades with a villager or wandering trader ++ */ ++public class PlayerTradeEvent extends PlayerPurchaseEvent { ++ ++ private final AbstractVillager villager; ++ ++ public PlayerTradeEvent(@NotNull Player player, @NotNull AbstractVillager villager, @NotNull MerchantRecipe trade, boolean rewardExp, boolean increaseTradeUses) { ++ super(player, trade, rewardExp, increaseTradeUses); ++ this.villager = villager; ++ } ++ ++ /** ++ * Gets the Villager or Wandering trader associated with this event ++ * @return the villager or wandering trader ++ */ ++ @NotNull ++ public AbstractVillager getVillager() { ++ return this.villager; ++ } ++ ++} diff --git a/patches/api-unmapped/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/api-unmapped/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch new file mode 100644 index 0000000000..eed087f1f6 --- /dev/null +++ b/patches/api-unmapped/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 24 Dec 2020 12:43:30 -0800 +Subject: [PATCH] Add OBSTRUCTED reason to BedEnterResult + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java b/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java +index c7d57e286c11eaa578ff6fd457b02a9ff829aa71..24b371b11347abf31fda4dadde8e0a7af60b181b 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java +@@ -37,6 +37,12 @@ public class PlayerBedEnterEvent extends PlayerEvent implements Cancellable { + * Entering the bed is prevented due to the player being too far away. + */ + TOO_FAR_AWAY, ++ // Paper start ++ /** ++ * Bed was obstructed. ++ */ ++ OBSTRUCTED, ++ // Paper end + /** + * Entering the bed is prevented due to there being monsters nearby. + */ diff --git a/patches/api-unmapped/0246-Add-TargetHitEvent-API.patch b/patches/api-unmapped/0246-Add-TargetHitEvent-API.patch new file mode 100644 index 0000000000..ddc1efeb9e --- /dev/null +++ b/patches/api-unmapped/0246-Add-TargetHitEvent-API.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Wed, 25 Nov 2020 23:21:32 -0800 +Subject: [PATCH] Add TargetHitEvent API + + +diff --git a/src/main/java/io/papermc/paper/event/block/TargetHitEvent.java b/src/main/java/io/papermc/paper/event/block/TargetHitEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..cc067ae118af9957b1b9f5c8d45f63f9154f4942 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/TargetHitEvent.java +@@ -0,0 +1,69 @@ ++package io.papermc.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.block.BlockFace; ++import org.bukkit.entity.Projectile; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.ProjectileHitEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a Target Block is hit by a projectile. ++ *

    ++ * Cancelling this event will stop the Target from emitting a redstone signal, ++ * and in the case that the shooter is a player, will stop them from receiving ++ * advancement criteria. ++ */ ++public class TargetHitEvent extends ProjectileHitEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ private int signalStrength; ++ ++ public TargetHitEvent(@NotNull Projectile projectile, @NotNull Block block, @NotNull BlockFace blockFace, int signalStrength) { ++ super(projectile, null, block, blockFace); ++ this.signalStrength = signalStrength; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancelled) { ++ this.cancelled = cancelled; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ /** ++ * Gets the strength of the redstone signal to be emitted by the Target block ++ * ++ * @return the strength of the redstone signal to be emitted ++ */ ++ public int getSignalStrength() { ++ return signalStrength; ++ } ++ ++ /** ++ * Sets the strength of the redstone signal to be emitted by the Target block ++ * ++ * @param signalStrength the strength of the redstone signal to be emitted ++ */ ++ public void setSignalStrength(int signalStrength) { ++ if (signalStrength < 0 || signalStrength > 15) { ++ throw new IllegalArgumentException("Signal strength out of range (" + signalStrength + "), must be in range [0,15]"); ++ } ++ this.signalStrength = signalStrength; ++ } ++} diff --git a/patches/api-unmapped/0247-Additional-Block-Material-API-s.patch b/patches/api-unmapped/0247-Additional-Block-Material-API-s.patch new file mode 100644 index 0000000000..87283b0984 --- /dev/null +++ b/patches/api-unmapped/0247-Additional-Block-Material-API-s.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 30 Dec 2020 17:27:27 -0500 +Subject: [PATCH] Additional Block Material API's + +Faster version for isSolid() that utilizes NMS's state for isSolid instead of the slower +process to do this in the Bukkit API + +Adds API for buildable, replaceable, burnable too. + +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index 6933fd6ad353a2d008c4a64c52a64bf36bd8035c..0c72d00ad238ab69d7ae0941e3ecb6c86e71624d 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -427,6 +427,42 @@ public interface Block extends Metadatable { + */ + boolean isLiquid(); + ++ // Paper start ++ /** ++ * Check if this block is solid ++ *

    ++ * Determined by Minecraft, typically a block a player can use to place a new block to build things. ++ * An example of a non buildable block would be liquids, flowers, or fire ++ * ++ * @return true if block is buildable ++ */ ++ boolean isBuildable(); ++ /** ++ * Check if this block is burnable ++ *

    ++ * Determined by Minecraft, typically a block that fire can destroy (Wool, Wood) ++ * ++ * @return true if block is burnable ++ */ ++ boolean isBurnable(); ++ /** ++ * Check if this block is replaceable ++ *

    ++ * Determined by Minecraft, representing a block that is not AIR that you can still place a new block at, such as flowers. ++ * @return true if block is replaceable ++ */ ++ boolean isReplaceable(); ++ /** ++ * Check if this block is solid ++ *

    ++ * Determined by Minecraft, typically a block a player can stand on and can't be passed through. ++ * ++ * This API is faster than accessing Material#isSolid as it avoids a material lookup and switch statement. ++ * @return true if block is solid ++ */ ++ boolean isSolid(); ++ // Paper end ++ + /** + * Gets the temperature of this block. + *

    diff --git a/patches/api-unmapped/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch b/patches/api-unmapped/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch new file mode 100644 index 0000000000..d6cdb8862b --- /dev/null +++ b/patches/api-unmapped/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Thu, 31 Dec 2020 12:48:38 +1000 +Subject: [PATCH] Add API to get Material from Boats and Minecarts + + +diff --git a/src/main/java/org/bukkit/entity/Boat.java b/src/main/java/org/bukkit/entity/Boat.java +index 24751b5c4e3bc24bdfa85af8f6fcba37413aa002..e0d0537606d4f9a3fe588ebf7d02f314c0359335 100644 +--- a/src/main/java/org/bukkit/entity/Boat.java ++++ b/src/main/java/org/bukkit/entity/Boat.java +@@ -1,5 +1,6 @@ + package org.bukkit.entity; + ++import org.bukkit.Material; + import org.bukkit.TreeSpecies; + import org.jetbrains.annotations.NotNull; + +@@ -103,4 +104,14 @@ public interface Boat extends Vehicle { + */ + @Deprecated + public void setWorkOnLand(boolean workOnLand); ++ ++ // Paper start ++ /** ++ * Gets the {@link Material} that represents this Boat type. ++ * ++ * @return the boat material. ++ */ ++ @NotNull ++ public Material getBoatMaterial(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/Minecart.java b/src/main/java/org/bukkit/entity/Minecart.java +index 95c79c5fa0c4e30201f887da6467ce5f81c8a255..53b042f8ebbbf6ee77435b93d4e89371375cc515 100644 +--- a/src/main/java/org/bukkit/entity/Minecart.java ++++ b/src/main/java/org/bukkit/entity/Minecart.java +@@ -1,5 +1,6 @@ + package org.bukkit.entity; + ++import org.bukkit.Material; + import org.bukkit.block.data.BlockData; + import org.bukkit.material.MaterialData; + import org.bukkit.util.Vector; +@@ -143,4 +144,14 @@ public interface Minecart extends Vehicle { + * @return the current block offset for this minecart. + */ + public int getDisplayBlockOffset(); ++ ++ // Paper start ++ /** ++ * Gets the {@link Material} that represents this Minecart type. ++ * ++ * @return the minecart material. ++ */ ++ @NotNull ++ public Material getMinecartMaterial(); ++ // Paper end + } diff --git a/patches/api-unmapped/0249-Add-PlayerFlowerPotManipulateEvent.patch b/patches/api-unmapped/0249-Add-PlayerFlowerPotManipulateEvent.patch new file mode 100644 index 0000000000..d9cd5a9f01 --- /dev/null +++ b/patches/api-unmapped/0249-Add-PlayerFlowerPotManipulateEvent.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MisterVector +Date: Tue, 13 Aug 2019 19:44:19 -0700 +Subject: [PATCH] Add PlayerFlowerPotManipulateEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerFlowerPotManipulateEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerFlowerPotManipulateEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4c141f3d8f668cdf9c75865a8e3ecbd012d9e521 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerFlowerPotManipulateEvent.java +@@ -0,0 +1,82 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.block.Block; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a player places an item in or takes an item out of a flowerpot. ++ */ ++public class PlayerFlowerPotManipulateEvent extends PlayerEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ private final Block flowerpot; ++ @NotNull ++ private final ItemStack item; ++ private final boolean placing; ++ ++ private boolean cancel = false; ++ ++ public PlayerFlowerPotManipulateEvent(@NotNull final Player player, @NotNull final Block flowerpot, @NotNull final ItemStack item, final boolean placing) { ++ super(player); ++ this.flowerpot = flowerpot; ++ this.item = item; ++ this.placing = placing; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancel; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancel = cancel; ++ } ++ ++ /** ++ * Gets the flowerpot that is involved in this event. ++ * ++ * @return the flowerpot that is involved with this event ++ */ ++ @NotNull ++ public Block getFlowerpot() { ++ return flowerpot; ++ } ++ ++ /** ++ * Gets the item being placed, or taken from, the flower pot. ++ * Check if placing with {@link #isPlacing()}. ++ * ++ * @return the item placed, or taken from, the flowerpot ++ */ ++ @NotNull ++ public ItemStack getItem() { ++ return item; ++ } ++ ++ /** ++ * Gets if the item is being placed into the flowerpot. ++ * ++ * @return if the item is being placed into the flowerpot ++ */ ++ public boolean isPlacing() { ++ return placing; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0250-Zombie-API-breaking-doors.patch b/patches/api-unmapped/0250-Zombie-API-breaking-doors.patch new file mode 100644 index 0000000000..e2a1a8350e --- /dev/null +++ b/patches/api-unmapped/0250-Zombie-API-breaking-doors.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 18 Nov 2020 11:32:15 -0800 +Subject: [PATCH] Zombie API - breaking doors + + +diff --git a/src/main/java/org/bukkit/entity/Zombie.java b/src/main/java/org/bukkit/entity/Zombie.java +index 1217576e6f08abf0175ab800cfca058d5deda116..a39fbc9fa0903be8ed8e89f3ef39f93c02dfc90b 100644 +--- a/src/main/java/org/bukkit/entity/Zombie.java ++++ b/src/main/java/org/bukkit/entity/Zombie.java +@@ -140,5 +140,19 @@ public interface Zombie extends Monster, Ageable { + * @param shouldBurnInDay True to burn in sunlight + */ + void setShouldBurnInDay(boolean shouldBurnInDay); ++ ++ /** ++ * Check if this zombie can break doors ++ * ++ * @return True if zombie can break doors ++ */ ++ boolean canBreakDoors(); ++ ++ /** ++ * Sets if this zombie can break doors ++ * ++ * @param canBreakDoors True if zombie can break doors ++ */ ++ void setCanBreakDoors(boolean canBreakDoors); + // Paper end + } diff --git a/patches/api-unmapped/0251-Add-EntityLoadCrossbowEvent.patch b/patches/api-unmapped/0251-Add-EntityLoadCrossbowEvent.patch new file mode 100644 index 0000000000..f484d40cca --- /dev/null +++ b/patches/api-unmapped/0251-Add-EntityLoadCrossbowEvent.patch @@ -0,0 +1,113 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 7 Oct 2020 12:04:17 -0400 +Subject: [PATCH] Add EntityLoadCrossbowEvent + + +diff --git a/src/main/java/io/papermc/paper/event/entity/EntityLoadCrossbowEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityLoadCrossbowEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..287f487b266d5c12fcf6f028452735e314d55636 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/EntityLoadCrossbowEvent.java +@@ -0,0 +1,101 @@ ++package io.papermc.paper.event.entity; ++ ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when a LivingEntity loads a crossbow with a projectile. ++ */ ++public class EntityLoadCrossbowEvent extends EntityEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private final ItemStack crossbow; ++ private final EquipmentSlot hand; ++ private boolean cancelled; ++ private boolean consumeItem = true; ++ ++ public EntityLoadCrossbowEvent(@NotNull LivingEntity entity, @Nullable ItemStack crossbow, @NotNull EquipmentSlot hand) { ++ super(entity); ++ this.crossbow = crossbow; ++ this.hand = hand; ++ } ++ ++ @NotNull ++ @Override ++ public LivingEntity getEntity() { ++ return (LivingEntity) entity; ++ } ++ ++ /** ++ * Gets the crossbow {@link ItemStack} being loaded. ++ * ++ * @return the crossbow involved in this event ++ */ ++ @Nullable ++ public ItemStack getCrossbow() { ++ return crossbow; ++ } ++ ++ /** ++ * Gets the hand from which the crossbow was loaded. ++ * ++ * @return the hand ++ */ ++ @NotNull ++ public EquipmentSlot getHand() { ++ return hand; ++ } ++ ++ /** ++ * ++ * @return should the itemstack be consumed ++ */ ++ public boolean shouldConsumeItem() { ++ return consumeItem; ++ } ++ ++ /** ++ * ++ * @param consume should the item be consumed ++ */ ++ public void setConsumeItem(boolean consume) { ++ this.consumeItem = consume; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * Set whether or not to cancel the crossbow being loaded. If canceled, the ++ * projectile that would be loaded into the crossbow will not be consumed. ++ * ++ * If set to false, and this event is pertaining to a player entity, ++ * it's recommended that a call to {@link Player#updateInventory()} is made ++ * as the client may think the server still loaded an item into the crossbow. ++ * ++ * @param cancel true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0252-Added-WorldGameRuleChangeEvent.patch b/patches/api-unmapped/0252-Added-WorldGameRuleChangeEvent.patch new file mode 100644 index 0000000000..8ef5f7efcd --- /dev/null +++ b/patches/api-unmapped/0252-Added-WorldGameRuleChangeEvent.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 20 Dec 2020 16:41:44 -0800 +Subject: [PATCH] Added WorldGameRuleChangeEvent + + +diff --git a/src/main/java/io/papermc/paper/event/world/WorldGameRuleChangeEvent.java b/src/main/java/io/papermc/paper/event/world/WorldGameRuleChangeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..20c25a0f9d65188402e8bb3981348bc6462904bf +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/world/WorldGameRuleChangeEvent.java +@@ -0,0 +1,91 @@ ++package io.papermc.paper.event.world; ++ ++import org.bukkit.GameRule; ++import org.bukkit.World; ++import org.bukkit.command.CommandSender; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.world.WorldEvent; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when a world's gamerule is changed, either by command or by api. ++ */ ++public class WorldGameRuleChangeEvent extends WorldEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final CommandSender commandSender; ++ private final GameRule gameRule; ++ private String value; ++ private boolean cancelled; ++ ++ public WorldGameRuleChangeEvent(@NotNull World world, @Nullable CommandSender commandSender, @NotNull GameRule gameRule, @NotNull String value) { ++ super(world); ++ this.commandSender = commandSender; ++ this.gameRule = gameRule; ++ this.value = value; ++ } ++ ++ /** ++ * Gets the command sender associated with this event. ++ * ++ * @return {@code null} if the gamerule was changed via api, otherwise the {@link CommandSender}. ++ */ ++ @Nullable ++ public CommandSender getCommandSender() { ++ return commandSender; ++ } ++ ++ /** ++ * Gets the game rule associated with this event. ++ * ++ * @return the gamerule being changed. ++ */ ++ @NotNull ++ public GameRule getGameRule() { ++ return gameRule; ++ } ++ ++ /** ++ * Gets the new value of the gamerule. ++ * ++ * @return the new value of the gamerule. ++ */ ++ @NotNull ++ public String getValue() { ++ return value; ++ } ++ ++ /** ++ * Sets the new value of this gamerule. ++ * ++ * @param value the new value of the gamerule. ++ */ ++ public void setValue(@NotNull String value) { ++ this.value = value; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api-unmapped/0253-Added-ServerResourcesReloadedEvent.patch b/patches/api-unmapped/0253-Added-ServerResourcesReloadedEvent.patch new file mode 100644 index 0000000000..de081bbae7 --- /dev/null +++ b/patches/api-unmapped/0253-Added-ServerResourcesReloadedEvent.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 2 Dec 2020 20:04:16 -0800 +Subject: [PATCH] Added ServerResourcesReloadedEvent + + +diff --git a/src/main/java/io/papermc/paper/event/server/ServerResourcesReloadedEvent.java b/src/main/java/io/papermc/paper/event/server/ServerResourcesReloadedEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7a8d6815c17a107039399298f7ac9f0612faee02 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/server/ServerResourcesReloadedEvent.java +@@ -0,0 +1,48 @@ ++package io.papermc.paper.event.server; ++ ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.server.ServerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when resources such as datapacks are reloaded (e.g. /minecraft:reload) ++ *

    ++ * Intended for use to re-register custom recipes, advancements that may be lost during a reload like this. ++ *

    ++ */ ++public class ServerResourcesReloadedEvent extends ServerEvent { ++ ++ public static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Cause cause; ++ ++ public ServerResourcesReloadedEvent(@NotNull Cause cause) { ++ this.cause = cause; ++ } ++ ++ /** ++ * Gets the cause of the resource reload. ++ * ++ * @return the reload cause ++ */ ++ @NotNull ++ public Cause getCause() { ++ return cause; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public enum Cause { ++ COMMAND, ++ PLUGIN, ++ } ++} diff --git a/patches/api-unmapped/0254-Add-BlockFailedDispenseEvent.patch b/patches/api-unmapped/0254-Add-BlockFailedDispenseEvent.patch new file mode 100644 index 0000000000..126714b965 --- /dev/null +++ b/patches/api-unmapped/0254-Add-BlockFailedDispenseEvent.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheViperShow <29604693+TheViperShow@users.noreply.github.com> +Date: Wed, 22 Apr 2020 09:40:23 +0200 +Subject: [PATCH] Add BlockFailedDispenseEvent + + +diff --git a/src/main/java/io/papermc/paper/event/block/BlockFailedDispenseEvent.java b/src/main/java/io/papermc/paper/event/block/BlockFailedDispenseEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..dab794341170ed10d5a05c1b4c180d164e0f70e2 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/BlockFailedDispenseEvent.java +@@ -0,0 +1,57 @@ ++package io.papermc.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a block tries to dispense an item, but its inventory is empty. ++ */ ++public class BlockFailedDispenseEvent extends BlockEvent { ++ private static final HandlerList handlers = new HandlerList(); ++ ++ private boolean shouldPlayEffect = true; ++ ++ public BlockFailedDispenseEvent(@NotNull Block theBlock) { ++ super(theBlock); ++ } ++ ++ /** ++ * @return if the effect should be played ++ */ ++ public boolean shouldPlayEffect() { ++ return this.shouldPlayEffect; ++ } ++ ++ /** ++ * Sets if the effect for empty dispensers should be played ++ * ++ * @param playEffect if the effect should be played ++ */ ++ public void shouldPlayEffect(boolean playEffect) { ++ this.shouldPlayEffect = playEffect; ++ } ++ ++ /** ++ * {@inheritDoc} ++ * ++ * @return {@link #shouldPlayEffect()} ++ */ ++ @Override ++ public boolean callEvent() { ++ super.callEvent(); ++ return this.shouldPlayEffect(); ++ } ++ ++ @Override ++ public @NotNull ++ HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ public static @NotNull ++ HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0255-Added-PlayerLecternPageChangeEvent.patch b/patches/api-unmapped/0255-Added-PlayerLecternPageChangeEvent.patch new file mode 100644 index 0000000000..2b65c3a245 --- /dev/null +++ b/patches/api-unmapped/0255-Added-PlayerLecternPageChangeEvent.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 23 Nov 2020 12:58:16 -0800 +Subject: [PATCH] Added PlayerLecternPageChangeEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerLecternPageChangeEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerLecternPageChangeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..26370e46e4a12e3470e9bb747fac5786a7305810 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerLecternPageChangeEvent.java +@@ -0,0 +1,115 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.block.Lectern; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++public class PlayerLecternPageChangeEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private boolean cancelled; ++ private final Lectern lectern; ++ private final ItemStack book; ++ private final PageChangeDirection pageChangeDirection; ++ private final int oldPage; ++ private int newPage; ++ ++ public PlayerLecternPageChangeEvent(@NotNull Player player, @NotNull Lectern lectern, @NotNull ItemStack book, @NotNull PageChangeDirection pageChangeDirection, int oldPage, int newPage) { ++ super(player); ++ this.lectern = lectern; ++ this.book = book; ++ this.pageChangeDirection = pageChangeDirection; ++ this.oldPage = oldPage; ++ this.newPage = newPage; ++ } ++ ++ /** ++ * Gets the lectern involved. ++ * ++ * @return the Lectern ++ */ ++ @NotNull ++ public Lectern getLectern() { ++ return lectern; ++ } ++ ++ /** ++ * Gets the current ItemStack on the lectern. ++ * ++ * @return the ItemStack on the Lectern ++ */ ++ @NotNull ++ public ItemStack getBook() { ++ return this.book; ++ } ++ ++ /** ++ * Gets the page change direction. This is essentially returns which button the player clicked, left or right. ++ * ++ * @return the page change direction ++ */ ++ @NotNull ++ public PageChangeDirection getPageChangeDirection() { ++ return pageChangeDirection; ++ } ++ ++ /** ++ * Gets the page changed from. Pages are 0-indexed. ++ * ++ * @return the page changed from ++ */ ++ public int getOldPage() { ++ return oldPage; ++ } ++ ++ /** ++ * Gets the page changed to. Pages are 0-indexed. ++ * ++ * @return the page changed to ++ */ ++ public int getNewPage() { ++ return newPage; ++ } ++ ++ /** ++ * Sets the page changed to. Pages are 0-indexed. ++ * Page indices that are greater than the number of pages will show the last page. ++ * ++ * @param newPage the new paged changed to ++ */ ++ public void setNewPage(int newPage) { ++ this.newPage = newPage; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ public enum PageChangeDirection { ++ LEFT, ++ RIGHT, ++ } ++} diff --git a/patches/api-unmapped/0256-Added-PlayerLoomPatternSelectEvent.patch b/patches/api-unmapped/0256-Added-PlayerLoomPatternSelectEvent.patch new file mode 100644 index 0000000000..5677026956 --- /dev/null +++ b/patches/api-unmapped/0256-Added-PlayerLoomPatternSelectEvent.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 25 Nov 2020 16:33:42 -0800 +Subject: [PATCH] Added PlayerLoomPatternSelectEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerLoomPatternSelectEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerLoomPatternSelectEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8cb05709f7cb5dee993ff6fea1626c41b90a7d8b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerLoomPatternSelectEvent.java +@@ -0,0 +1,77 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.block.banner.PatternType; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.LoomInventory; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a player selects a banner patten in a loom inventory. ++ */ ++public class PlayerLoomPatternSelectEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private boolean cancelled; ++ private final LoomInventory loomInventory; ++ private PatternType patternType; ++ ++ public PlayerLoomPatternSelectEvent(@NotNull Player player, @NotNull LoomInventory loomInventory, @NotNull PatternType patternType) { ++ super(player); ++ this.loomInventory = loomInventory; ++ this.patternType = patternType; ++ } ++ ++ /** ++ * Gets the loom inventory involved. ++ * ++ * @return the loom inventory ++ */ ++ @NotNull ++ public LoomInventory getLoomInventory() { ++ return loomInventory; ++ } ++ ++ /** ++ * Gets the pattern type selected. ++ * ++ * @return the pattern type ++ */ ++ @NotNull ++ public PatternType getPatternType() { ++ return patternType; ++ } ++ ++ /** ++ * Sets the pattern type selected. ++ * ++ * @param patternType the pattern type ++ */ ++ public void setPatternType(@NotNull PatternType patternType) { ++ this.patternType = patternType; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api-unmapped/0257-Better-AnnotationTest-printout.patch b/patches/api-unmapped/0257-Better-AnnotationTest-printout.patch new file mode 100644 index 0000000000..2a40d2b44f --- /dev/null +++ b/patches/api-unmapped/0257-Better-AnnotationTest-printout.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 3 Dec 2020 14:04:57 -0800 +Subject: [PATCH] Better AnnotationTest printout + + +diff --git a/pom.xml b/pom.xml +index 6b71d9a397dd5b72320402a47b8e7197d24e061c..73fbd5d5a591871a3a386fb5c455cd96a3992e7a 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -257,6 +257,19 @@ + true + + ++ ++ org.apache.maven.plugins ++ maven-surefire-plugin ++ 2.22.2 ++ ++ ++ ++ listener ++ io.papermc.paper.JunitEventListener ++ ++ ++ ++ + + org.apache.maven.plugins + maven-javadoc-plugin +diff --git a/src/test/java/io/papermc/paper/JunitEventListener.java b/src/test/java/io/papermc/paper/JunitEventListener.java +new file mode 100644 +index 0000000000000000000000000000000000000000..072ac1a96394b8d494f42fca8dfe08115eaed3fe +--- /dev/null ++++ b/src/test/java/io/papermc/paper/JunitEventListener.java +@@ -0,0 +1,6 @@ ++package io.papermc.paper; ++ ++import org.junit.runner.notification.RunListener; ++ ++public class JunitEventListener extends RunListener { ++} +diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java +index 03229d5f4ec36a82197beb391356d791ff67fb2f..19271057cf24329757c9419fa6c97848e008a96c 100644 +--- a/src/test/java/org/bukkit/AnnotationTest.java ++++ b/src/test/java/org/bukkit/AnnotationTest.java +@@ -107,13 +107,18 @@ public class AnnotationTest { + + Collections.sort(errors); + +- System.out.println(errors.size() + " missing annotation(s):"); ++ StringBuilder builder = new StringBuilder() ++ .append("There ") ++ .append(errors.size() != 1 ? "are " : "is ") ++ .append(errors.size()) ++ .append(" missing annotation") ++ .append(errors.size() != 1 ? "s:\n" : ":\n"); ++ + for (String message : errors) { +- System.out.print("\t"); +- System.out.println(message); ++ builder.append("\t").append(message).append("\n"); + } + +- Assert.fail("There " + errors.size() + " are missing annotation(s)"); ++ Assert.fail(builder.toString()); + } + + private static void collectClasses(@NotNull File from, @NotNull Map to) throws IOException { diff --git a/patches/api-unmapped/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch b/patches/api-unmapped/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch new file mode 100644 index 0000000000..197d00ca14 --- /dev/null +++ b/patches/api-unmapped/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Mon, 4 Jan 2021 16:40:55 +1000 +Subject: [PATCH] Add API to get exact interaction point in PlayerInteractEvent + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java b/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java +index 1208e1f8c2163d83c5b12bbb9b7ac044c72380e0..a01f86e6aba8b66ecc713da0787cd861e2930a2a 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java +@@ -1,5 +1,6 @@ + package org.bukkit.event.player; + ++import org.bukkit.Location; + import org.bukkit.Material; + import org.bukkit.block.Block; + import org.bukkit.block.BlockFace; +@@ -34,22 +35,30 @@ public class PlayerInteractEvent extends PlayerEvent implements Cancellable { + private Result useClickedBlock; + private Result useItemInHand; + private EquipmentSlot hand; ++ private Location interactionPoint; // Paper + + public PlayerInteractEvent(@NotNull final Player who, @NotNull final Action action, @Nullable final ItemStack item, @Nullable final Block clickedBlock, @NotNull final BlockFace clickedFace) { + this(who, action, item, clickedBlock, clickedFace, EquipmentSlot.HAND); + } + + public PlayerInteractEvent(@NotNull final Player who, @NotNull final Action action, @Nullable final ItemStack item, @Nullable final Block clickedBlock, @NotNull final BlockFace clickedFace, @Nullable final EquipmentSlot hand) { ++ // Paper start - Add interactionPoint ++ this(who, action, item, clickedBlock, clickedFace, hand, null); ++ } ++ ++ public PlayerInteractEvent(@NotNull final Player who, @NotNull final Action action, @Nullable final ItemStack item, @Nullable final Block clickedBlock, @NotNull final BlockFace clickedFace, @Nullable final EquipmentSlot hand, @Nullable final Location interactionPoint) { + super(who); + this.action = action; + this.item = item; + this.blockClicked = clickedBlock; + this.blockFace = clickedFace; + this.hand = hand; ++ this.interactionPoint = interactionPoint; + + useItemInHand = Result.DEFAULT; + useClickedBlock = clickedBlock == null ? Result.DENY : Result.ALLOW; + } ++ // Paper end + + /** + * Returns the action type +@@ -221,6 +230,18 @@ public class PlayerInteractEvent extends PlayerEvent implements Cancellable { + return hand; + } + ++ // Paper start ++ /** ++ * The exact point at which the interaction occurred. May be null. ++ * ++ * @return the exact interaction point. May be null. ++ */ ++ @Nullable ++ public Location getInteractionPoint() { ++ return interactionPoint; ++ } ++ // Paper end ++ + @NotNull + @Override + public HandlerList getHandlers() { diff --git a/patches/api-unmapped/0259-Add-sendOpLevel-API.patch b/patches/api-unmapped/0259-Add-sendOpLevel-API.patch new file mode 100644 index 0000000000..d1a8696b2d --- /dev/null +++ b/patches/api-unmapped/0259-Add-sendOpLevel-API.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Tue, 29 Dec 2020 15:02:57 +0100 +Subject: [PATCH] Add sendOpLevel API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 7aa9fb852dce23c53fee80e97e0dcdb278ae82ba..68a03821a5f06308a9c51fdf107d3924c44886c8 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1929,6 +1929,17 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + @Nullable + Firework boostElytra(@NotNull ItemStack firework); ++ ++ /** ++ * Send a packet to the player indicating its operator status level. ++ *

    ++ * Note: This will not persist across more than the current connection, and setting the player's operator ++ * status as a later point will override the effects of this. ++ * ++ * @param level The level to send to the player. Must be in {@code [0, 4]}. ++ * @throws IllegalArgumentException If the level is negative or greater than {@code 4} (i.e. not within {@code [0, 4]}). ++ */ ++ void sendOpLevel(byte level); + // Paper end + + // Spigot start diff --git a/patches/api-unmapped/0260-Add-StructureLocateEvent.patch b/patches/api-unmapped/0260-Add-StructureLocateEvent.patch new file mode 100644 index 0000000000..88c14d8ea6 --- /dev/null +++ b/patches/api-unmapped/0260-Add-StructureLocateEvent.patch @@ -0,0 +1,167 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: dfsek +Date: Tue, 15 Sep 2020 21:59:16 -0700 +Subject: [PATCH] Add StructureLocateEvent + + +diff --git a/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java b/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..45b6694fc5741831e2df638b1f760a3ca28a4907 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java +@@ -0,0 +1,155 @@ ++package io.papermc.paper.event.world; ++ ++import org.bukkit.Location; ++import org.bukkit.StructureType; ++import org.bukkit.World; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.world.WorldEvent; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called before a structure/feature is located. ++ * This happens when: ++ *

      ++ *
    • The /locate command is used.
    • ++ *
    • An Eye of Ender is used.
    • ++ *
    • An Explorer/Treasure Map is activated.
    • ++ *
    • {@link World#locateNearestStructure(Location, StructureType, int, boolean)} is invoked.
    • ++ *
    ++ */ ++public class StructureLocateEvent extends WorldEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private final Location origin; ++ private Location result = null; ++ private StructureType type; ++ private int radius; ++ private boolean findUnexplored; ++ private boolean cancelled = false; ++ ++ public StructureLocateEvent(@NotNull World world, @NotNull Location origin, @NotNull StructureType structureType, int radius, boolean findUnexplored) { ++ super(world); ++ this.origin = origin; ++ this.type = structureType; ++ this.radius = radius; ++ this.findUnexplored = findUnexplored; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ /** ++ * Gets the location set as the structure location, if it was defined. ++ *

    ++ * Returns {@code null} if it has not been set by {@link StructureLocateEvent#setResult(Location)}. ++ * Since this event fires before the search is done, the actual location is unknown at this point. ++ * ++ * @return The result location, if it has been set. null if it has not. ++ * @see World#locateNearestStructure(Location, StructureType, int, boolean) ++ */ ++ @Nullable ++ public Location getResult() { ++ return result; ++ } ++ ++ /** ++ * Sets the result {@link Location}. This causes the search to be skipped, and the location passed here to be used as the result. ++ * ++ * @param result the {@link Location} of the structure. ++ */ ++ public void setResult(@Nullable Location result) { ++ this.result = result; ++ } ++ ++ /** ++ * Gets the {@link StructureType} that is to be located. ++ * ++ * @return the structure type. ++ */ ++ @NotNull ++ public StructureType getType() { ++ return type; ++ } ++ ++ /** ++ * Sets the {@link StructureType} that is to be located. ++ * ++ * @param type the structure type. ++ */ ++ public void setType(@NotNull StructureType type) { ++ this.type = type; ++ } ++ ++ /** ++ * Gets the {@link Location} from which the search is to be conducted. ++ * ++ * @return {@link Location} where search begins ++ */ ++ @NotNull ++ public Location getOrigin() { ++ return origin; ++ } ++ ++ /** ++ * Gets the search radius in which to attempt locating the structure. ++ *

    ++ * This radius may not always be obeyed during the structure search! ++ * ++ * @return the search radius. ++ */ ++ public int getRadius() { ++ return radius; ++ } ++ ++ /** ++ * Sets the search radius in which to attempt locating the structure. ++ *

    ++ * This radius may not always be obeyed during the structure search! ++ * ++ * @param radius the search radius. ++ */ ++ public void setRadius(int radius) { ++ this.radius = radius; ++ } ++ ++ /** ++ * Gets whether to search exclusively for unexplored structures. ++ *

    ++ * As with the search radius, this value is not always obeyed. ++ * ++ * @return Whether to search for only unexplored structures. ++ */ ++ public boolean shouldFindUnexplored() { ++ return findUnexplored; ++ } ++ ++ /** ++ * Sets whether to search exclusively for unexplored structures. ++ *

    ++ * As with the search radius, this value is not always obeyed. ++ * ++ * @param findUnexplored Whether to search for only unexplored structures. ++ */ ++ public void setFindUnexplored(boolean findUnexplored) { ++ this.findUnexplored = findUnexplored; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0261-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/api-unmapped/0261-Return-chat-component-with-empty-text-instead-of-thr.patch new file mode 100644 index 0000000000..e7986f5bb1 --- /dev/null +++ b/patches/api-unmapped/0261-Return-chat-component-with-empty-text-instead-of-thr.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: CDFN +Date: Tue, 7 Jul 2020 17:53:23 +0200 +Subject: [PATCH] Return chat component with empty text instead of throwing + exception + + +diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java +index 664de64b020cf9090a2fbee0afe2bfaf150adc3c..b06995aa57aa9cba0bb59f1d26d81015619a08e6 100644 +--- a/src/main/java/org/bukkit/inventory/InventoryView.java ++++ b/src/main/java/org/bukkit/inventory/InventoryView.java +@@ -450,7 +450,7 @@ public abstract class InventoryView { + /** + * Get the title of this inventory window. + * +- * @return The title. ++ * @return The title or empty string when title is {@code null}. + */ + @NotNull + public /*abstract*/ net.kyori.adventure.text.Component title() { diff --git a/patches/api-unmapped/0262-Add-BlockPreDispenseEvent.patch b/patches/api-unmapped/0262-Add-BlockPreDispenseEvent.patch new file mode 100644 index 0000000000..5850391175 --- /dev/null +++ b/patches/api-unmapped/0262-Add-BlockPreDispenseEvent.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Sun, 17 Jan 2021 13:15:54 +1000 +Subject: [PATCH] Add BlockPreDispenseEvent + + +diff --git a/src/main/java/io/papermc/paper/event/block/BlockPreDispenseEvent.java b/src/main/java/io/papermc/paper/event/block/BlockPreDispenseEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..07aad3f4ff60a6a6de69634b0d31926e9c00e77b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/BlockPreDispenseEvent.java +@@ -0,0 +1,60 @@ ++package io.papermc.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++ ++public class BlockPreDispenseEvent extends BlockEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled = false; ++ private final ItemStack itemStack; ++ private final int slot; ++ ++ public BlockPreDispenseEvent(@NotNull Block block, @NotNull ItemStack itemStack, int slot) { ++ super(block); ++ this.itemStack = itemStack; ++ this.slot = slot; ++ } ++ ++ /** ++ * Gets the {@link ItemStack} to be dispensed. ++ * ++ * @return The item to be dispensed ++ */ ++ @NotNull ++ public ItemStack getItemStack() { ++ return itemStack; ++ } ++ ++ /** ++ * Gets the inventory slot of the dispenser to dispense from. ++ * ++ * @return The inventory slot ++ */ ++ public int getSlot() { ++ return slot; ++ } ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++} diff --git a/patches/api-unmapped/0263-Added-Vanilla-Entity-Tags.patch b/patches/api-unmapped/0263-Added-Vanilla-Entity-Tags.patch new file mode 100644 index 0000000000..53c933017b --- /dev/null +++ b/patches/api-unmapped/0263-Added-Vanilla-Entity-Tags.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 3 Jan 2021 20:03:40 -0800 +Subject: [PATCH] Added Vanilla Entity Tags + + +diff --git a/src/main/java/org/bukkit/Tag.java b/src/main/java/org/bukkit/Tag.java +index 88ea8b6c5c2c4d2116f646341de62590718bc28c..a2da2cbef6c09b9defbdf97e79cfb3efd742d439 100644 +--- a/src/main/java/org/bukkit/Tag.java ++++ b/src/main/java/org/bukkit/Tag.java +@@ -589,6 +589,32 @@ public interface Tag extends Keyed { + * Vanilla fluid tag representing water and flowing water. + */ + Tag FLUIDS_WATER = Bukkit.getTag(REGISTRY_FLUIDS, NamespacedKey.minecraft("water"), Fluid.class); ++ // Paper start ++ /** ++ * Key for the build in entity registry ++ */ ++ String REGISTRY_ENTITIES = "entities"; ++ /** ++ * Vanilla entity tag representing arrow entities. ++ */ ++ Tag ARROWS = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("arrows"), org.bukkit.entity.EntityType.class); ++ /** ++ * Vanilla entity tag representing entities that live in beehives ++ */ ++ Tag BEEHIVE_INHABITORS = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("beehive_inhabitors"), org.bukkit.entity.EntityType.class); ++ /** ++ * Vanilla entity tag representing projectiles that impact ++ */ ++ Tag IMPACT_PROJECTILES = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("impact_projectiles"), org.bukkit.entity.EntityType.class); ++ /** ++ * Vanilla entity tag for village raiders ++ */ ++ Tag RAIDERS = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("raiders"), org.bukkit.entity.EntityType.class); ++ /** ++ * Vanilla entity tag for skeleton types ++ */ ++ Tag SKELETONS = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("skeletons"), org.bukkit.entity.EntityType.class); ++ // Paper end + + /** + * Returns whether or not this tag has an entry for the specified item. diff --git a/patches/api-unmapped/0264-added-Wither-API.patch b/patches/api-unmapped/0264-added-Wither-API.patch new file mode 100644 index 0000000000..dbfc15a42c --- /dev/null +++ b/patches/api-unmapped/0264-added-Wither-API.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 5 Jul 2020 15:39:40 -0700 +Subject: [PATCH] added Wither API + + +diff --git a/src/main/java/org/bukkit/entity/Wither.java b/src/main/java/org/bukkit/entity/Wither.java +index 426d3693317cd303d35d8203026b528d87e401d5..8c95cd6933f11076de936854f379e6fc8600b525 100644 +--- a/src/main/java/org/bukkit/entity/Wither.java ++++ b/src/main/java/org/bukkit/entity/Wither.java +@@ -6,4 +6,34 @@ import com.destroystokyo.paper.entity.RangedEntity; + * Represents a Wither boss + */ + public interface Wither extends Monster, Boss, RangedEntity { // Paper ++ // Paper start ++ /** ++ * @return whether the wither is charged ++ */ ++ boolean isCharged(); ++ ++ /** ++ * @return ticks the wither is invulnerable for ++ */ ++ int getInvulnerableTicks(); ++ ++ /** ++ * Sets for how long in the future, the wither should be invulnerable. ++ * ++ * @param ticks ticks the wither is invulnerable for ++ */ ++ void setInvulnerableTicks(int ticks); ++ ++ /** ++ * @return whether the wither can travel through portals ++ */ ++ boolean canTravelThroughPortals(); ++ ++ /** ++ * Sets whether the wither can travel through portals. ++ * ++ * @param value whether the wither can travel through portals ++ */ ++ void setCanTravelThroughPortals(boolean value); ++ // Paper end + } diff --git a/patches/api-unmapped/0265-Added-PlayerChangeBeaconEffectEvent.patch b/patches/api-unmapped/0265-Added-PlayerChangeBeaconEffectEvent.patch new file mode 100644 index 0000000000..4331e880bb --- /dev/null +++ b/patches/api-unmapped/0265-Added-PlayerChangeBeaconEffectEvent.patch @@ -0,0 +1,153 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 24 Jun 2020 15:12:18 -0600 +Subject: [PATCH] Added PlayerChangeBeaconEffectEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerChangeBeaconEffectEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerChangeBeaconEffectEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c80183a79713b1e73549911e474a8c585cfdeb52 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerChangeBeaconEffectEvent.java +@@ -0,0 +1,141 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.block.Block; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.potion.PotionEffectType; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when a player sets the effect for a beacon ++ */ ++public class PlayerChangeBeaconEffectEvent extends PlayerEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ ++ private PotionEffectType primary; ++ private PotionEffectType secondary; ++ private final Block beacon; ++ private boolean consumeItem = true; ++ ++ private boolean isCancelled; ++ ++ public PlayerChangeBeaconEffectEvent(@NotNull Player player, @Nullable PotionEffectType primary, @Nullable PotionEffectType secondary, @Nullable Block beacon) { ++ super(player); ++ this.primary = primary; ++ this.secondary = secondary; ++ this.isCancelled = false; ++ this.beacon = beacon; ++ } ++ ++ /** ++ * @return the primary effect ++ */ ++ @Nullable public PotionEffectType getPrimary() { ++ return primary; ++ } ++ ++ /** ++ * Sets the primary effect ++ *

    ++ * NOTE: The primary effect still has to be one of the valid effects for a beacon. ++ * ++ * @param primary the primary effect ++ */ ++ public void setPrimary(@Nullable PotionEffectType primary) { ++ this.primary = primary; ++ } ++ ++ /** ++ * @return the secondary effect ++ */ ++ @Nullable public PotionEffectType getSecondary() { ++ return secondary; ++ } ++ ++ /** ++ * Sets the secondary effect ++ *

    ++ * This only has an effect when the beacon is able to accept a secondary effect. ++ * NOTE: The secondary effect still has to be a valid effect for a beacon. ++ * ++ * @param secondary the secondary effect ++ */ ++ public void setSecondary(@Nullable PotionEffectType secondary) { ++ this.secondary = secondary; ++ } ++ ++ /** ++ * @return the beacon block associated with this event, or null if not found ++ */ ++ @Nullable ++ public Block getBeacon() { ++ return beacon; ++ } ++ ++ /** ++ * Gets if the item used to change the beacon will be consume. ++ *

    ++ * Independant of {@link #isCancelled()}. If the event is cancelled ++ * the item will NOT be consumed. ++ * ++ * @return true if item will be consumed ++ */ ++ public boolean willConsumeItem() { ++ return consumeItem; ++ } ++ ++ /** ++ * Sets if the item used to change the beacon should be consumed. ++ *

    ++ * Independant of {@link #isCancelled()}. If the event is cancelled ++ * the item will NOT be consumed. ++ * ++ * @param consumeItem true if item should be consumed ++ */ ++ public void setConsumeItem(boolean consumeItem) { ++ this.consumeItem = consumeItem; ++ } ++ ++ /** ++ * Gets the cancellation state of this event. A cancelled event will not ++ * be executed in the server, but will still pass to other plugins ++ *

    ++ * If a {@link PlayerChangeBeaconEffectEvent} is cancelled, the changes will ++ * not take effect ++ * ++ * @return true if this event is cancelled ++ */ ++ @Override ++ public boolean isCancelled() { ++ return this.isCancelled; ++ } ++ ++ /** ++ * Sets the cancellation state of this event. A cancelled event will not ++ * be executed in the server, but will still pass to other plugins ++ *

    ++ * If cancelled, the item will NOT be consumed regardless of what {@link #willConsumeItem()} says ++ *

    ++ * If a {@link PlayerChangeBeaconEffectEvent} is cancelled, the changes will not be applied ++ * or saved. ++ * ++ * @param cancel true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.isCancelled = cancel; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/api-unmapped/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch new file mode 100644 index 0000000000..1a81930699 --- /dev/null +++ b/patches/api-unmapped/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Fri, 29 Jan 2021 15:13:04 +0100 +Subject: [PATCH] Add dropLeash variable to EntityUnleashEvent + + +diff --git a/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java b/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java +index a33986a0c437a673435206fc337031a7eebdab3b..e0e068799a1868c8e561869015f41f553ef4fbdb 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java +@@ -10,10 +10,19 @@ import org.jetbrains.annotations.NotNull; + public class EntityUnleashEvent extends EntityEvent { + private static final HandlerList handlers = new HandlerList(); + private final UnleashReason reason; ++ private boolean dropLeash; // Paper + ++ // Paper start - drop leash variable ++ @Deprecated + public EntityUnleashEvent(@NotNull Entity entity, @NotNull UnleashReason reason) { ++ this(entity, reason, false); ++ } ++ ++ public EntityUnleashEvent(@NotNull Entity entity, @NotNull UnleashReason reason, boolean dropLeash) { + super(entity); ++ // Paper end + this.reason = reason; ++ this.dropLeash = dropLeash; // Paper + } + + /** +@@ -26,6 +35,26 @@ public class EntityUnleashEvent extends EntityEvent { + return reason; + } + ++ // Paper start ++ /** ++ * Returns whether a leash item will be dropped. ++ * ++ * @return Whether the leash item will be dropped ++ */ ++ public boolean isDropLeash() { ++ return dropLeash; ++ } ++ ++ /** ++ * Sets whether a leash item should be dropped. ++ * ++ * @param dropLeash Whether the leash item should be dropped ++ */ ++ public void setDropLeash(boolean dropLeash) { ++ this.dropLeash = dropLeash; ++ } ++ // Paper end ++ + @NotNull + @Override + public HandlerList getHandlers() { +diff --git a/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java b/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java +index cf78950b56d4977f6c4d9d98d183bfc5ba3bacc0..68eab1563caba1ee4f52b308f390e4e172667fc5 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java +@@ -13,8 +13,15 @@ public class PlayerUnleashEntityEvent extends EntityUnleashEvent implements Canc + private final Player player; + private boolean cancelled = false; + ++ // Paper start - drop leash variable ++ @Deprecated + public PlayerUnleashEntityEvent(@NotNull Entity entity, @NotNull Player player) { +- super(entity, UnleashReason.PLAYER_UNLEASH); ++ this(entity, player, false); ++ } ++ ++ public PlayerUnleashEntityEvent(@NotNull Entity entity, @NotNull Player player, boolean dropLeash) { ++ super(entity, UnleashReason.PLAYER_UNLEASH, dropLeash); ++ // Paper end + this.player = player; + } + diff --git a/patches/api-unmapped/0267-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/api-unmapped/0267-Added-PlayerStonecutterRecipeSelectEvent.patch new file mode 100644 index 0000000000..ce446c46fe --- /dev/null +++ b/patches/api-unmapped/0267-Added-PlayerStonecutterRecipeSelectEvent.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 27 Nov 2020 17:13:59 -0800 +Subject: [PATCH] Added PlayerStonecutterRecipeSelectEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerStonecutterRecipeSelectEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerStonecutterRecipeSelectEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fb1bca3a9d12096c9a2b2663f466a8ff5f2b4319 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerStonecutterRecipeSelectEvent.java +@@ -0,0 +1,59 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.StonecutterInventory; ++import org.bukkit.inventory.StonecuttingRecipe; ++import org.jetbrains.annotations.NotNull; ++ ++public class PlayerStonecutterRecipeSelectEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private boolean cancelled; ++ private final StonecutterInventory stonecutterInventory; ++ private StonecuttingRecipe stonecuttingRecipe; ++ ++ public PlayerStonecutterRecipeSelectEvent(@NotNull Player player, @NotNull StonecutterInventory stonecutterInventory, @NotNull StonecuttingRecipe stonecuttingRecipe) { ++ super(player); ++ this.stonecutterInventory = stonecutterInventory; ++ this.stonecuttingRecipe = stonecuttingRecipe; ++ } ++ ++ @NotNull ++ public StonecutterInventory getStonecutterInventory() { ++ return stonecutterInventory; ++ } ++ ++ @NotNull ++ public StonecuttingRecipe getStonecuttingRecipe() { ++ return stonecuttingRecipe; ++ } ++ ++ public void setStonecuttingRecipe(@NotNull StonecuttingRecipe stonecuttingRecipe) { ++ this.stonecuttingRecipe = stonecuttingRecipe; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api-unmapped/0268-EntityMoveEvent.patch b/patches/api-unmapped/0268-EntityMoveEvent.patch new file mode 100644 index 0000000000..0f5a4c5a81 --- /dev/null +++ b/patches/api-unmapped/0268-EntityMoveEvent.patch @@ -0,0 +1,152 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Tue, 11 Feb 2020 21:56:38 -0600 +Subject: [PATCH] EntityMoveEvent + + +diff --git a/src/main/java/io/papermc/paper/event/entity/EntityMoveEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityMoveEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fae0b1daf733e85d8f691f5ef934b8c0b51db194 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/EntityMoveEvent.java +@@ -0,0 +1,140 @@ ++package io.papermc.paper.event.entity; ++ ++import com.google.common.base.Preconditions; ++import org.bukkit.Location; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Holds information for living entity movement events ++ */ ++public class EntityMoveEvent extends EntityEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean canceled; ++ private Location from; ++ private Location to; ++ ++ public EntityMoveEvent(@NotNull LivingEntity entity, @NotNull Location from, @NotNull Location to) { ++ super(entity); ++ this.from = from; ++ this.to = to; ++ } ++ ++ @Override ++ @NotNull ++ public LivingEntity getEntity() { ++ return (LivingEntity) entity; ++ } ++ ++ public boolean isCancelled() { ++ return canceled; ++ } ++ ++ public void setCancelled(boolean cancel) { ++ canceled = cancel; ++ } ++ ++ /** ++ * Gets the location this entity moved from ++ * ++ * @return Location the entity moved from ++ */ ++ @NotNull ++ public Location getFrom() { ++ return from; ++ } ++ ++ /** ++ * Sets the location to mark as where the entity moved from ++ * ++ * @param from New location to mark as the entity's previous location ++ */ ++ public void setFrom(@NotNull Location from) { ++ validateLocation(from); ++ this.from = from; ++ } ++ ++ /** ++ * Gets the location this entity moved to ++ * ++ * @return Location the entity moved to ++ */ ++ @NotNull ++ public Location getTo() { ++ return to; ++ } ++ ++ /** ++ * Sets the location that this entity will move to ++ * ++ * @param to New Location this entity will move to ++ */ ++ public void setTo(@NotNull Location to) { ++ validateLocation(to); ++ this.to = to; ++ } ++ ++ /** ++ * Check if the entity has changed position (even within the same block) in the event ++ * ++ * @return whether the entity has changed position or not ++ */ ++ public boolean hasChangedPosition() { ++ return hasExplicitlyChangedPosition() || !from.getWorld().equals(to.getWorld()); ++ } ++ ++ /** ++ * Check if the entity has changed position (even within the same block) in the event, disregarding a possible world change ++ * ++ * @return whether the entity has changed position or not ++ */ ++ public boolean hasExplicitlyChangedPosition() { ++ return from.getX() != to.getX() || from.getY() != to.getY() || from.getZ() != to.getZ(); ++ } ++ ++ /** ++ * Check if the entity has moved to a new block in the event ++ * ++ * @return whether the entity has moved to a new block or not ++ */ ++ public boolean hasChangedBlock() { ++ return hasExplicitlyChangedBlock() || !from.getWorld().equals(to.getWorld()); ++ } ++ ++ /** ++ * Check if the entity has moved to a new block in the event, disregarding a possible world change ++ * ++ * @return whether the entity has moved to a new block or not ++ */ ++ public boolean hasExplicitlyChangedBlock() { ++ return from.getBlockX() != to.getBlockX() || from.getBlockY() != to.getBlockY() || from.getBlockZ() != to.getBlockZ(); ++ } ++ ++ /** ++ * Check if the entity has changed orientation in the event ++ * ++ * @return whether the entity has changed orientation or not ++ */ ++ public boolean hasChangedOrientation() { ++ return from.getPitch() != to.getPitch() || from.getYaw() != to.getYaw(); ++ } ++ ++ private void validateLocation(@NotNull Location loc) { ++ Preconditions.checkArgument(loc != null, "Cannot use null location!"); ++ Preconditions.checkArgument(loc.getWorld() != null, "Cannot use null location with null world!"); ++ } ++ ++ @Override ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0269-add-DragonEggFormEvent.patch b/patches/api-unmapped/0269-add-DragonEggFormEvent.patch new file mode 100644 index 0000000000..c465295e88 --- /dev/null +++ b/patches/api-unmapped/0269-add-DragonEggFormEvent.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Mon, 25 Jan 2021 14:53:49 +0100 +Subject: [PATCH] add DragonEggFormEvent + + +diff --git a/src/main/java/io/papermc/paper/event/block/DragonEggFormEvent.java b/src/main/java/io/papermc/paper/event/block/DragonEggFormEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5495b87330518363498e1ac5d8f0a832be35fefb +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/DragonEggFormEvent.java +@@ -0,0 +1,63 @@ ++package io.papermc.paper.event.block; ++ ++import org.bukkit.Material; ++import org.bukkit.block.Block; ++import org.bukkit.block.BlockState; ++import org.bukkit.boss.DragonBattle; ++import org.bukkit.entity.EnderDragon; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockFormEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when the {@link EnderDragon} is defeated (killed) in a {@link DragonBattle}, ++ * causing a {@link Material#DRAGON_EGG} (more formally: {@link #getNewState()}) ++ * to possibly appear depending on {@link #isCancelled()}. ++ * This event might be cancelled by default depending on ++ * eg. {@link DragonBattle#hasBeenPreviouslyKilled()} and server configuration. ++ */ ++public class DragonEggFormEvent extends BlockFormEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private final DragonBattle dragonBattle; ++ private boolean cancelled; ++ ++ public DragonEggFormEvent(@NotNull Block block, @NotNull BlockState newState, ++ @NotNull DragonBattle dragonBattle) { ++ super(block, newState); ++ this.dragonBattle = dragonBattle; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancelled) { ++ this.cancelled = cancelled; ++ } ++ ++ /** ++ * Gets the {@link DragonBattle} associated with this event. ++ * Keep in mind that the {@link EnderDragon} is already dead ++ * when this event is called. ++ * ++ * @return the dragon battle ++ */ ++ @NotNull ++ public DragonBattle getDragonBattle() { ++ return dragonBattle; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0270-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/api-unmapped/0270-Allow-adding-items-to-BlockDropItemEvent.patch new file mode 100644 index 0000000000..984da00f52 --- /dev/null +++ b/patches/api-unmapped/0270-Allow-adding-items-to-BlockDropItemEvent.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Wed, 20 Jan 2021 14:25:26 -0600 +Subject: [PATCH] Allow adding items to BlockDropItemEvent + + +diff --git a/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java b/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java +index a0f6f1af304190b4c5db4b284d460f625eeb7801..3dd4bd38e72c04e74e5787fb38ca9abd10bad06b 100644 +--- a/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java +@@ -64,7 +64,7 @@ public class BlockDropItemEvent extends BlockEvent implements Cancellable { + * Gets list of the Item drops caused by the block break. + * + * This list is mutable - removing an item from it will cause it to not +- * drop. It is not legal however to add new items to the list. ++ * drop. Adding to the list is allowed. + * + * @return The Item the block caused to drop + */ diff --git a/patches/api-unmapped/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/api-unmapped/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch new file mode 100644 index 0000000000..6de1a3b396 --- /dev/null +++ b/patches/api-unmapped/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aleksander Jagiello +Date: Sun, 24 Jan 2021 22:17:29 +0100 +Subject: [PATCH] Add getMainThreadExecutor to BukkitScheduler + + +diff --git a/src/main/java/org/bukkit/scheduler/BukkitScheduler.java b/src/main/java/org/bukkit/scheduler/BukkitScheduler.java +index ac140fc2c638e22e06b2920db3e376ab9e8c3733..f5e3bfd22d4d38182065b5215e5f78d9bb13381e 100644 +--- a/src/main/java/org/bukkit/scheduler/BukkitScheduler.java ++++ b/src/main/java/org/bukkit/scheduler/BukkitScheduler.java +@@ -458,4 +458,15 @@ public interface BukkitScheduler { + @Deprecated + @NotNull + public BukkitTask runTaskTimerAsynchronously(@NotNull Plugin plugin, @NotNull BukkitRunnable task, long delay, long period) throws IllegalArgumentException; ++ ++ // Paper start - add getMainThreadExecutor ++ /** ++ * Returns an executor that will run tasks on the next server tick. ++ * ++ * @param plugin the reference to the plugin scheduling tasks ++ * @return an executor associated with the given plugin ++ */ ++ @NotNull ++ public java.util.concurrent.Executor getMainThreadExecutor(@NotNull Plugin plugin); ++ // Paper end + } diff --git a/patches/api-unmapped/0272-living-entity-allow-attribute-registration.patch b/patches/api-unmapped/0272-living-entity-allow-attribute-registration.patch new file mode 100644 index 0000000000..e7ded6dabb --- /dev/null +++ b/patches/api-unmapped/0272-living-entity-allow-attribute-registration.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ysl3000 +Date: Sat, 24 Oct 2020 16:37:21 +0200 +Subject: [PATCH] living entity allow attribute registration + + +diff --git a/src/main/java/org/bukkit/attribute/Attributable.java b/src/main/java/org/bukkit/attribute/Attributable.java +index 0ed96b5af0e6e93590882e0ad8239221bcc3f688..474ed1df364a5ca18661d0fbc29901760e39cb07 100644 +--- a/src/main/java/org/bukkit/attribute/Attributable.java ++++ b/src/main/java/org/bukkit/attribute/Attributable.java +@@ -17,4 +17,14 @@ public interface Attributable { + */ + @Nullable + AttributeInstance getAttribute(@NotNull Attribute attribute); ++ ++ // Paper start ++ /** ++ * Registers a generic attribute to that attributable instance. ++ * Allows it to add attributes not registered by default to that entity. ++ * ++ * @param attribute the generic attribute to register ++ */ ++ void registerAttribute(@NotNull Attribute attribute); ++ // Paper end + } diff --git a/patches/api-unmapped/0273-Add-missing-effects.patch b/patches/api-unmapped/0273-Add-missing-effects.patch new file mode 100644 index 0000000000..57086bea9c --- /dev/null +++ b/patches/api-unmapped/0273-Add-missing-effects.patch @@ -0,0 +1,76 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Tue, 5 Jan 2021 10:19:11 +0200 +Subject: [PATCH] Add missing effects + + +diff --git a/src/main/java/org/bukkit/Effect.java b/src/main/java/org/bukkit/Effect.java +index d0c812c72967469122f7f276ced31cfb0e9482dc..0f598fa0560d14b44dcc65205364870c0bbfa0d8 100644 +--- a/src/main/java/org/bukkit/Effect.java ++++ b/src/main/java/org/bukkit/Effect.java +@@ -201,6 +201,65 @@ public enum Effect { + * The sound of an enderdragon growling + */ + ENDERDRAGON_GROWL(3001, Type.SOUND), ++ // Paper start - add missing effects ++ /** ++ * The sound of a wither spawning ++ */ ++ WITHER_SPAWNED(1023, Type.SOUND), ++ /** ++ * The sound of an ender dragon dying ++ */ ++ ENDER_DRAGON_DEATH(1028, Type.SOUND), ++ /** ++ * The sound of an ender portal being created in the overworld ++ */ ++ END_PORTAL_CREATED_IN_OVERWORLD(1038, Type.SOUND), ++ /** ++ * The sound of phantom's bites ++ */ ++ PHANTOM_BITES(1039, Type.SOUND), ++ /** ++ * The sound of zombie converting to drowned zombie ++ */ ++ ZOMBIE_CONVERTS_TO_DROWNED(1040, Type.SOUND), ++ /** ++ * The sound of a husk converting to zombie by drowning ++ */ ++ HUSK_CONVERTS_TO_ZOMBIE(1041, Type.SOUND), ++ /** ++ * The sound of a grindstone being used ++ */ ++ GRINDSTONE_USED(1042, Type.SOUND), ++ /** ++ * The sound of a book page being turned ++ */ ++ BOOK_PAGE_TURNED(1043, Type.SOUND), ++ /** ++ * Particles displayed when a composter composts ++ */ ++ COMPOSTER_COMPOSTS(1500, Type.VISUAL), ++ /** ++ * Particles displayed when lava converts a block (either water to stone, or ++ * removing existing blocks such as torches) ++ */ ++ LAVA_CONVERTS_BLOCK(1501, Type.VISUAL), ++ /** ++ * Particles displayd when a redstone torch burns out ++ */ ++ REDSTONE_TORCH_BURNS_OUT(1502, Type.VISUAL), ++ /** ++ * Particles displayed when an ender eye is placed ++ */ ++ ENDER_EYE_PLACED(1503, Type.VISUAL), ++ /** ++ * Particles displayed when an ender dragon destroys block ++ */ ++ ENDER_DRAGON_DESTROYS_BLOCK(2008, Type.VISUAL), ++ /** ++ * Particles displayed when a wet sponge vaporizes in nether. ++ */ ++ WET_SPONGE_VAPORIZES_IN_NETHER(2009, Type.VISUAL) ++ // Paper end + ; + + private final int id; diff --git a/patches/api-unmapped/0274-Expose-Tracked-Players.patch b/patches/api-unmapped/0274-Expose-Tracked-Players.patch new file mode 100644 index 0000000000..1c4214897c --- /dev/null +++ b/patches/api-unmapped/0274-Expose-Tracked-Players.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tom +Date: Fri, 26 Feb 2021 16:24:25 -0600 +Subject: [PATCH] Expose Tracked Players + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 68a03821a5f06308a9c51fdf107d3924c44886c8..34b51466ffb281b05f531b3f7deda245ae7fd96a 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1,6 +1,7 @@ + package org.bukkit.entity; + + import java.net.InetSocketAddress; ++import java.util.Set; // Paper + import java.util.UUID; + import com.destroystokyo.paper.ClientOption; // Paper + import com.destroystokyo.paper.Title; // Paper +@@ -1942,6 +1943,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + void sendOpLevel(byte level); + // Paper end + ++ // Paper start ++ /** ++ * @return Returns a set of Players within this player's tracking range (that the player's client can "see") ++ */ ++ @NotNull ++ Set getTrackedPlayers(); ++ // Paper end ++ + // Spigot start + public class Spigot extends Entity.Spigot { + diff --git a/patches/api-unmapped/0275-Cache-the-result-of-Material-isBlock.patch b/patches/api-unmapped/0275-Cache-the-result-of-Material-isBlock.patch new file mode 100644 index 0000000000..7eca03bdf5 --- /dev/null +++ b/patches/api-unmapped/0275-Cache-the-result-of-Material-isBlock.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Tue, 2 Mar 2021 15:24:58 -0800 +Subject: [PATCH] Cache the result of Material#isBlock + + +diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java +index 69c85c3a1f45476f7de0a9399852d82eeb4f9c86..0f081835c0484e15fca4fadaa27e90cadd394276 100644 +--- a/src/main/java/org/bukkit/Material.java ++++ b/src/main/java/org/bukkit/Material.java +@@ -3935,6 +3935,7 @@ public enum Material implements Keyed { + public final Class data; + private final boolean legacy; + private final NamespacedKey key; ++ private boolean isBlock; // Paper + + private Material(final int id) { + this(id, 64); +@@ -4132,6 +4133,11 @@ public enum Material implements Keyed { + * @return true if this material is a block + */ + public boolean isBlock() { ++ // Paper start - cache isBlock ++ return this.isBlock; ++ } ++ private boolean isBlock0() { ++ // Paper end + switch (this) { + // + case ACACIA_BUTTON: +@@ -5213,6 +5219,7 @@ public enum Material implements Keyed { + static { + for (Material material : values()) { + BY_NAME.put(material.name(), material); ++ material.isBlock = material.isBlock0(); // Paper + } + } + diff --git a/patches/api-unmapped/0276-Add-worldborder-events.patch b/patches/api-unmapped/0276-Add-worldborder-events.patch new file mode 100644 index 0000000000..09c3770e16 --- /dev/null +++ b/patches/api-unmapped/0276-Add-worldborder-events.patch @@ -0,0 +1,308 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 4 Jan 2021 22:40:26 -0800 +Subject: [PATCH] Add worldborder events + + +diff --git a/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeEvent.java b/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..126fe50b519a8d7cd158f799058cb235f9c4cbdb +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeEvent.java +@@ -0,0 +1,114 @@ ++package io.papermc.paper.event.world.border; ++ ++import org.bukkit.World; ++import org.bukkit.WorldBorder; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a world border changes its bounds, either over time, or instantly. ++ */ ++public class WorldBorderBoundsChangeEvent extends WorldBorderEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private Type type; ++ private final double oldSize; ++ private double newSize; ++ private long duration; ++ private boolean cancelled; ++ ++ public WorldBorderBoundsChangeEvent(@NotNull World world, @NotNull WorldBorder worldBorder, @NotNull Type type, double oldSize, double newSize, long duration) { ++ super(world, worldBorder); ++ this.type = type; ++ this.oldSize = oldSize; ++ this.newSize = newSize; ++ this.duration = duration; ++ } ++ ++ /** ++ * Gets if this change is an instant change or over-time change. ++ * ++ * @return the change type ++ */ ++ @NotNull ++ public Type getType() { ++ return type; ++ } ++ ++ /** ++ * Gets the old size or the world border. ++ * ++ * @return the old size ++ */ ++ public double getOldSize() { ++ return oldSize; ++ } ++ ++ /** ++ * Gets the new size of the world border. ++ * ++ * @return the new size ++ */ ++ public double getNewSize() { ++ return newSize; ++ } ++ ++ /** ++ * Sets the new size of the world border. ++ * ++ * @param newSize the new size ++ */ ++ public void setNewSize(double newSize) { ++ // PAIL: TODO: Magic Values ++ this.newSize = Math.min(6.0E7D, Math.max(1.0D, newSize)); ++ } ++ ++ /** ++ * Gets the time in milliseconds for the change. Will be 0 if instant. ++ * ++ * @return the time in milliseconds for the change ++ */ ++ public long getDuration() { ++ return duration; ++ } ++ ++ /** ++ * Sets the time in milliseconds for the change. Will change {@link #getType()} to return ++ * {@link Type#STARTED_MOVE}. ++ * ++ * @param duration the time in milliseconds for the change ++ */ ++ public void setDuration(long duration) { ++ // PAIL: TODO: Magic Values ++ this.duration = Math.min(9223372036854775L, Math.max(0L, duration)); ++ if (duration >= 0 && type == Type.INSTANT_MOVE) type = Type.STARTED_MOVE; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ public enum Type { ++ STARTED_MOVE, ++ INSTANT_MOVE ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeFinishEvent.java b/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeFinishEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c3d578ae2c5615b0ebace99d9bacf100b086c971 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeFinishEvent.java +@@ -0,0 +1,65 @@ ++package io.papermc.paper.event.world.border; ++ ++import org.bukkit.World; ++import org.bukkit.WorldBorder; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a moving world border has finished it's move. ++ */ ++public class WorldBorderBoundsChangeFinishEvent extends WorldBorderEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final double oldSize; ++ private final double newSize; ++ private final double duration; ++ ++ public WorldBorderBoundsChangeFinishEvent(@NotNull World world, @NotNull WorldBorder worldBorder, double oldSize, double newSize, double duration) { ++ super(world, worldBorder); ++ this.oldSize = oldSize; ++ this.newSize = newSize; ++ this.duration = duration; ++ } ++ ++ /** ++ * Gets the old size of the worldborder. ++ * ++ * @return the old size ++ */ ++ public double getOldSize() { ++ return oldSize; ++ } ++ ++ /** ++ * Gets the new size of the worldborder. ++ * ++ * @return the new size ++ */ ++ public double getNewSize() { ++ return newSize; ++ } ++ ++ /** ++ * Gets the duration this worldborder took to make the change. ++ *

    ++ * Can be 0 if handlers for {@link io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent} set the duration to 0. ++ * ++ * @return the duration of the transition ++ */ ++ public double getDuration() { ++ return duration; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/world/border/WorldBorderCenterChangeEvent.java b/src/main/java/io/papermc/paper/event/world/border/WorldBorderCenterChangeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4a10c773a8d05a596066e63306dead74c1363fd7 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/world/border/WorldBorderCenterChangeEvent.java +@@ -0,0 +1,77 @@ ++package io.papermc.paper.event.world.border; ++ ++import org.bukkit.Location; ++import org.bukkit.World; ++import org.bukkit.WorldBorder; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.world.WorldEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a world border's center is changed. ++ */ ++public class WorldBorderCenterChangeEvent extends WorldBorderEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Location oldCenter; ++ private Location newCenter; ++ private boolean cancelled; ++ ++ public WorldBorderCenterChangeEvent(@NotNull World world, @NotNull WorldBorder worldBorder, @NotNull Location oldCenter, @NotNull Location newCenter) { ++ super(world, worldBorder); ++ this.oldCenter = oldCenter; ++ this.newCenter = newCenter; ++ } ++ ++ /** ++ * Gets the original center location of the world border. ++ * ++ * @return the old center ++ */ ++ @NotNull ++ public Location getOldCenter() { ++ return oldCenter; ++ } ++ ++ /** ++ * Gets the new center location for the world border. ++ * ++ * @return the new center ++ */ ++ @NotNull ++ public Location getNewCenter() { ++ return newCenter; ++ } ++ ++ /** ++ * Sets the new center location for the world border. Y coordinate is ignored. ++ * ++ * @param newCenter the new center ++ */ ++ public void setNewCenter(@NotNull Location newCenter) { ++ this.newCenter = newCenter; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/world/border/WorldBorderEvent.java b/src/main/java/io/papermc/paper/event/world/border/WorldBorderEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..67bd469d3680c9554ce6c1d5493826a252682835 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/world/border/WorldBorderEvent.java +@@ -0,0 +1,22 @@ ++package io.papermc.paper.event.world.border; ++ ++import org.bukkit.World; ++import org.bukkit.WorldBorder; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.world.WorldEvent; ++import org.jetbrains.annotations.NotNull; ++ ++public abstract class WorldBorderEvent extends WorldEvent { ++ ++ private final WorldBorder worldBorder; ++ ++ public WorldBorderEvent(@NotNull World world, @NotNull WorldBorder worldBorder) { ++ super(world); ++ this.worldBorder = worldBorder; ++ } ++ ++ @NotNull ++ public WorldBorder getWorldBorder() { ++ return worldBorder; ++ } ++} diff --git a/patches/api-unmapped/0277-added-PlayerNameEntityEvent.patch b/patches/api-unmapped/0277-added-PlayerNameEntityEvent.patch new file mode 100644 index 0000000000..a38082f8e8 --- /dev/null +++ b/patches/api-unmapped/0277-added-PlayerNameEntityEvent.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 5 Jul 2020 00:34:24 -0700 +Subject: [PATCH] added PlayerNameEntityEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerNameEntityEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerNameEntityEvent.java +new file mode 100755 +index 0000000000000000000000000000000000000000..ef9e53a73eff469bbaa8fb20c634297acb9d1986 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerNameEntityEvent.java +@@ -0,0 +1,118 @@ ++package io.papermc.paper.event.player; ++ ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when the player is attempting to rename a mob ++ */ ++public class PlayerNameEntityEvent extends PlayerEvent implements Cancellable { ++ ++ private LivingEntity entity; ++ private Component name; ++ private boolean persistent; ++ private boolean cancelled; ++ ++ public PlayerNameEntityEvent(@NotNull Player player, @NotNull LivingEntity entity, @NotNull Component name, boolean persistent) { ++ super(player); ++ this.entity = entity; ++ this.name = name; ++ this.persistent = persistent; ++ } ++ ++ /** ++ * Gets the name to be given to the entity. ++ * @return the name ++ */ ++ @Nullable ++ public Component getName() { ++ return name; ++ } ++ ++ /** ++ * Sets the name to be given to the entity. ++ * ++ * @param name the name ++ */ ++ public void setName(@Nullable Component name) { ++ this.name = name; ++ } ++ ++ /** ++ * Gets the entity involved in this event. ++ * ++ * @return the entity ++ */ ++ @NotNull ++ public LivingEntity getEntity() { ++ return entity; ++ } ++ ++ /** ++ * Sets the entity involved in this event. ++ * ++ * @param entity the entity ++ */ ++ public void setEntity(@NotNull LivingEntity entity) { ++ this.entity = entity; ++ } ++ ++ /** ++ * Gets whether this will set the mob to be persistent. ++ * ++ * @return persistent ++ */ ++ public boolean isPersistent() { ++ return persistent; ++ } ++ ++ /** ++ * Sets whether this will set the mob to be persistent. ++ * ++ * @param persistent persistent ++ */ ++ public void setPersistent(boolean persistent) { ++ this.persistent = persistent; ++ } ++ ++ /** ++ * Gets the cancellation state of this event. A cancelled event will not ++ * be executed in the server, but will still pass to other plugins ++ * ++ * @return true if this event is cancelled ++ */ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * Sets the cancellation state of this event. A cancelled event will not ++ * be executed in the server, but will still pass to other plugins. ++ * ++ * @param cancel true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api-unmapped/0278-Add-recipe-to-cook-events.patch b/patches/api-unmapped/0278-Add-recipe-to-cook-events.patch new file mode 100644 index 0000000000..b0b34773c0 --- /dev/null +++ b/patches/api-unmapped/0278-Add-recipe-to-cook-events.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> +Date: Wed, 6 Jan 2021 12:05:29 -0800 +Subject: [PATCH] Add recipe to cook events + + +diff --git a/src/main/java/org/bukkit/event/block/BlockCookEvent.java b/src/main/java/org/bukkit/event/block/BlockCookEvent.java +index be7af5440bf9923f0c9c84efa4d70a89337a2f96..a3f1c9cb36c9069ed622985a525bfc2a7a27ab91 100644 +--- a/src/main/java/org/bukkit/event/block/BlockCookEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockCookEvent.java +@@ -14,12 +14,21 @@ public class BlockCookEvent extends BlockEvent implements Cancellable { + private final ItemStack source; + private ItemStack result; + private boolean cancelled; ++ private final org.bukkit.inventory.CookingRecipe recipe; // Paper + ++ @Deprecated // Paper + public BlockCookEvent(@NotNull final Block block, @NotNull final ItemStack source, @NotNull final ItemStack result) { ++ // Paper start ++ this(block, source, result, null); ++ } ++ ++ public BlockCookEvent(@NotNull final Block block, @NotNull final ItemStack source, @NotNull final ItemStack result, @org.jetbrains.annotations.Nullable org.bukkit.inventory.CookingRecipe recipe) { ++ // Paper end + super(block); + this.source = source; + this.result = result; + this.cancelled = false; ++ this.recipe = recipe; // Paper + } + + /** +@@ -61,6 +70,18 @@ public class BlockCookEvent extends BlockEvent implements Cancellable { + this.cancelled = cancel; + } + ++ // Paper start ++ /** ++ * Gets the cooking recipe associated with this event. ++ * ++ * @return the recipe ++ */ ++ @org.jetbrains.annotations.Nullable ++ public org.bukkit.inventory.CookingRecipe getRecipe() { ++ return recipe; ++ } ++ // Paper end ++ + @NotNull + @Override + public HandlerList getHandlers() { +diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java +index 066e7dd9a34d35c8b643a5efcf95d6a5ef47c7ee..16b3ab8f525c4e863f804cc8460a330407d85478 100644 +--- a/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java +@@ -10,7 +10,13 @@ import org.jetbrains.annotations.NotNull; + */ + public class FurnaceSmeltEvent extends BlockCookEvent { + ++ @Deprecated // Paper + public FurnaceSmeltEvent(@NotNull final Block furnace, @NotNull final ItemStack source, @NotNull final ItemStack result) { + super(furnace, source, result); + } ++ // Paper start ++ public FurnaceSmeltEvent(@NotNull final Block furnace, @NotNull final ItemStack source, @NotNull final ItemStack result, @org.jetbrains.annotations.Nullable org.bukkit.inventory.CookingRecipe recipe) { ++ super(furnace, source, result, recipe); ++ } ++ // Paper end + } diff --git a/patches/api-unmapped/0279-Add-Block-isValidTool.patch b/patches/api-unmapped/0279-Add-Block-isValidTool.patch new file mode 100644 index 0000000000..f037cf8c32 --- /dev/null +++ b/patches/api-unmapped/0279-Add-Block-isValidTool.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 6 Jul 2020 12:44:23 -0700 +Subject: [PATCH] Add Block#isValidTool + + +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index 181658c679d306ffc4ad45259494571ee224ef47..08e6f1741685f54506c8a4ff29bbd30f62cf8e45 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -218,6 +218,15 @@ public interface Block extends Metadatable { + public static int getBlockKeyZ(long packed) { + return (int) ((packed << 10) >> 37); + } ++ ++ /** ++ * Checks if the itemstack is a valid tool to ++ * break the block with ++ * ++ * @param itemStack The (tool) itemstack ++ * @return whether the block will drop items ++ */ ++ boolean isValidTool(@NotNull ItemStack itemStack); + // Paper End + + /** diff --git a/patches/api-unmapped/0280-Implement-Keyed-on-World.patch b/patches/api-unmapped/0280-Implement-Keyed-on-World.patch new file mode 100644 index 0000000000..75f66d5848 --- /dev/null +++ b/patches/api-unmapped/0280-Implement-Keyed-on-World.patch @@ -0,0 +1,164 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 6 Jan 2021 00:34:10 -0800 +Subject: [PATCH] Implement Keyed on World + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 68101a322ffab8ec28843386b79b8079576fa720..5f7208196684d9c8373df28b7cfb5f9e21baa41e 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -639,6 +639,18 @@ public final class Bukkit { + public static World getWorld(@NotNull UUID uid) { + return server.getWorld(uid); + } ++ // Paper start ++ /** ++ * Gets the world from the given NamespacedKey ++ * ++ * @param worldKey the NamespacedKey of the world to retrieve ++ * @return a world with the given NamespacedKey, or null if none exists ++ */ ++ @Nullable ++ public static World getWorld(@NotNull NamespacedKey worldKey) { ++ return server.getWorld(worldKey); ++ } ++ // Paper end + + /** + * Gets the map from the given item ID. +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index a79fa08b9e6fb924b2da933eb6e4b365d14d938d..f3e27d2d02a9407bb1b091b8c1125ad5abf99e55 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -541,6 +541,17 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @Nullable + public World getWorld(@NotNull UUID uid); + ++ // Paper start ++ /** ++ * Gets the world from the given NamespacedKey ++ * ++ * @param worldKey the NamespacedKey of the world to retrieve ++ * @return a world with the given NamespacedKey, or null if none exists ++ */ ++ @Nullable ++ public World getWorld(@NotNull NamespacedKey worldKey); ++ // Paper end ++ + /** + * Gets the map from the given item ID. + * +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index ced33fc6de6bfa2767123131d532e7ae9ef3a5be..98512bddbb0c8bd6a3f487c60b1ec77b274b991e 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -43,7 +43,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a world, which may contain entities, chunks and blocks + */ +-public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience { // Paper ++public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience, Keyed { // Paper + + // Paper start + /** +@@ -829,6 +829,15 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + + @NotNull + java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent); ++ ++ /** ++ * Get the world's key ++ * ++ * @return the world's key ++ */ ++ @NotNull ++ @Override ++ NamespacedKey getKey(); + // Paper end + + /** +diff --git a/src/main/java/org/bukkit/WorldCreator.java b/src/main/java/org/bukkit/WorldCreator.java +index 6e6945dd4c770be04ec09da3958fae751717527a..e6a83252f42da31ad38f8dc1beccc7aa2c3f54b8 100644 +--- a/src/main/java/org/bukkit/WorldCreator.java ++++ b/src/main/java/org/bukkit/WorldCreator.java +@@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; + * Represents various types of options that may be used to create a world. + */ + public class WorldCreator { ++ private final NamespacedKey key; // Paper + private final String name; + private long seed; + private World.Environment environment = World.Environment.NORMAL; +@@ -26,13 +27,67 @@ public class WorldCreator { + * @param name Name of the world that will be created + */ + public WorldCreator(@NotNull String name) { +- if (name == null) { +- throw new IllegalArgumentException("World name cannot be null"); +- } ++ // Paper start ++ this(name, NamespacedKey.minecraft(name.toLowerCase(java.util.Locale.ENGLISH).replace(" ", "_"))); ++ } + +- this.name = name; ++ /** ++ * Creates an empty WorldCreator for the given world name and key ++ * ++ * @param levelName LevelName of the world that will be created ++ * @param worldKey NamespacedKey of the world that will be created ++ */ ++ public WorldCreator(@NotNull String levelName, @NotNull NamespacedKey worldKey) { ++ if (levelName == null || worldKey == null) { ++ throw new IllegalArgumentException("World name and key cannot be null"); ++ } ++ this.name = levelName; + this.seed = (new Random()).nextLong(); ++ this.key = worldKey; ++ } ++ ++ /** ++ * Creates an empty WorldCreator for the given key. ++ * LevelName will be the Key part of the NamespacedKey. ++ * ++ * @param worldKey NamespacedKey of the world that will be created ++ */ ++ public WorldCreator(@NotNull NamespacedKey worldKey) { ++ this(worldKey.getKey(), worldKey); ++ } ++ ++ /** ++ * Gets the key for this WorldCreator ++ * ++ * @return the key ++ */ ++ @NotNull ++ public NamespacedKey key() { ++ return key; ++ } ++ ++ /** ++ * Creates an empty WorldCreator for the given world name and key ++ * ++ * @param levelName LevelName of the world that will be created ++ * @param worldKey NamespacedKey of the world that will be created ++ */ ++ @NotNull ++ public static WorldCreator ofNameAndKey(@NotNull String levelName, @NotNull NamespacedKey worldKey) { ++ return new WorldCreator(levelName, worldKey); ++ } ++ ++ /** ++ * Creates an empty WorldCreator for the given key. ++ * LevelName will be the Key part of the NamespacedKey. ++ * ++ * @param worldKey NamespacedKey of the world that will be created ++ */ ++ @NotNull ++ public static WorldCreator ofKey(@NotNull NamespacedKey worldKey) { ++ return new WorldCreator(worldKey); + } ++ // Paper end + + /** + * Copies the options from the specified world diff --git a/patches/api-unmapped/0281-fix-Inventory-getContents-null-annotations.patch b/patches/api-unmapped/0281-fix-Inventory-getContents-null-annotations.patch new file mode 100644 index 0000000000..4d216020ec --- /dev/null +++ b/patches/api-unmapped/0281-fix-Inventory-getContents-null-annotations.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: CDFN +Date: Fri, 12 Mar 2021 18:31:31 +0100 +Subject: [PATCH] fix Inventory#getContents null annotations + + +diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java +index 6386206188e820206bb1a9f516b5e194fdc9d952..7956aebcb390379677dccf7c9561866cf94c024c 100644 +--- a/src/main/java/org/bukkit/inventory/Inventory.java ++++ b/src/main/java/org/bukkit/inventory/Inventory.java +@@ -158,9 +158,8 @@ public interface Inventory extends Iterable { + * + * @return An array of ItemStacks from the inventory. Individual items may be null. + */ +- @NotNull +- public ItemStack[] getContents(); +- ++ public @org.checkerframework.checker.nullness.qual.Nullable ItemStack @org.checkerframework.checker.nullness.qual.NonNull [] getContents(); // Paper - make array elements nullable instead array ++ + /** + * Completely replaces the inventory's contents. Removes all existing + * contents and replaces it with the ItemStacks given in the array. diff --git a/patches/api-unmapped/0282-Item-Rarity-API.patch b/patches/api-unmapped/0282-Item-Rarity-API.patch new file mode 100644 index 0000000000..8f0f4fc977 --- /dev/null +++ b/patches/api-unmapped/0282-Item-Rarity-API.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 12 Mar 2021 17:09:40 -0800 +Subject: [PATCH] Item Rarity API + + +diff --git a/src/main/java/io/papermc/paper/inventory/ItemRarity.java b/src/main/java/io/papermc/paper/inventory/ItemRarity.java +new file mode 100644 +index 0000000000000000000000000000000000000000..74ef8395cc040ce488c2acaa416db20272cc2734 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/inventory/ItemRarity.java +@@ -0,0 +1,28 @@ ++package io.papermc.paper.inventory; ++ ++import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.format.TextColor; ++import org.jetbrains.annotations.NotNull; ++ ++public enum ItemRarity { ++ ++ COMMON(NamedTextColor.WHITE), ++ UNCOMMON(NamedTextColor.YELLOW), ++ RARE(NamedTextColor.AQUA), ++ EPIC(NamedTextColor.LIGHT_PURPLE); ++ ++ TextColor color; ++ ++ ItemRarity(TextColor color) { ++ this.color = color; ++ } ++ ++ /** ++ * Gets the color formatting associated with the rarity. ++ * @return ++ */ ++ @NotNull ++ public TextColor getColor() { ++ return color; ++ } ++} +diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java +index 0f081835c0484e15fca4fadaa27e90cadd394276..07b8b913434bb575df8670230d693b2d4cec2571 100644 +--- a/src/main/java/org/bukkit/Material.java ++++ b/src/main/java/org/bukkit/Material.java +@@ -4002,6 +4002,17 @@ public enum Material implements Keyed { + public String getTranslationKey() { + return Bukkit.getUnsafe().getTranslationKey(this); + } ++ ++ /** ++ * Returns the item rarity for the item. The Material MUST be an Item not a block. ++ * Use {@link #isItem()} before this. ++ * ++ * @return the item rarity ++ */ ++ @NotNull ++ public io.papermc.paper.inventory.ItemRarity getItemRarity() { ++ return Bukkit.getUnsafe().getItemRarity(this); ++ } + // Paper end + + /** +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 84eda68281c6c6968d95b1313a33696c3a9980d4..bcd10b2c9255d778b678310febf1937301d01a50 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -137,5 +137,22 @@ public interface UnsafeValues { + * Use this when sending custom packets, so that there are no collisions on the client or server. + */ + public int nextEntityId(); ++ ++ /** ++ * Gets the item rarity of a material. The material MUST be an item. ++ * Use {@link Material#isItem()} before this. ++ * ++ * @param material the material to get the rarity of ++ * @return the item rarity ++ */ ++ public io.papermc.paper.inventory.ItemRarity getItemRarity(Material material); ++ ++ /** ++ * Gets the item rarity of the itemstack. The rarity can change based on enchantements. ++ * ++ * @param itemStack the itemstack to get the rarity of ++ * @return the itemstack rarity ++ */ ++ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(ItemStack itemStack); + // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index bd96c06aca1fc18807e65c34f399ce2ebe891816..f72d3d62d61755bbaf1950ebcb228ce95d1faf58 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -863,5 +863,15 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + public String getTranslationKey() { + return Bukkit.getUnsafe().getTranslationKey(this); + } ++ ++ /** ++ * Gets the item rarity of the itemstack. The rarity can change based on enchantements. ++ * ++ * @return the itemstack rarity ++ */ ++ @NotNull ++ public io.papermc.paper.inventory.ItemRarity getRarity() { ++ return Bukkit.getUnsafe().getItemStackRarity(this); ++ } + // Paper end + } diff --git a/patches/api-unmapped/0283-Expose-protocol-version.patch b/patches/api-unmapped/0283-Expose-protocol-version.patch new file mode 100644 index 0000000000..f5e20e22d7 --- /dev/null +++ b/patches/api-unmapped/0283-Expose-protocol-version.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Fri, 26 Mar 2021 11:23:27 +0100 +Subject: [PATCH] Expose protocol version + + +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index bcd10b2c9255d778b678310febf1937301d01a50..6dbd520182b1e7713a68baad09b7f613424ef619 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -154,5 +154,12 @@ public interface UnsafeValues { + * @return the itemstack rarity + */ + public io.papermc.paper.inventory.ItemRarity getItemStackRarity(ItemStack itemStack); ++ ++ /** ++ * Returns the server's protocol version. ++ * ++ * @return the server's protocol version ++ */ ++ int getProtocolVersion(); + // Paper end + } diff --git a/patches/api-unmapped/0284-add-isDeeplySleeping-to-HumanEntity.patch b/patches/api-unmapped/0284-add-isDeeplySleeping-to-HumanEntity.patch new file mode 100644 index 0000000000..b0f198f0e1 --- /dev/null +++ b/patches/api-unmapped/0284-add-isDeeplySleeping-to-HumanEntity.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 8 Apr 2021 17:36:15 -0700 +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 f0e0710fef5a3e0b722ece7ccf89c3d0f88f8f0f..2ce774c81a93260a1464183d435b4c418ed61648 100644 +--- a/src/main/java/org/bukkit/entity/HumanEntity.java ++++ b/src/main/java/org/bukkit/entity/HumanEntity.java +@@ -319,6 +319,15 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder + */ + public void setCooldown(@NotNull Material material, int ticks); + ++ // Paper start ++ /** ++ * If the player has slept enough to count towards passing the night. ++ * ++ * @return true if the player has slept enough ++ */ ++ public boolean isDeeplySleeping(); ++ // Paper end ++ + /** + * Get the sleep ticks of the player. This value may be capped. + * diff --git a/patches/api-unmapped/0285-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/api-unmapped/0285-add-consumeFuel-to-FurnaceBurnEvent.patch new file mode 100644 index 0000000000..6c8b681cd9 --- /dev/null +++ b/patches/api-unmapped/0285-add-consumeFuel-to-FurnaceBurnEvent.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 22 Apr 2021 16:45:15 -0700 +Subject: [PATCH] add consumeFuel to FurnaceBurnEvent + + +diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java +index bc71bc2d3ace0d19d730c09f05f9e0655bcee8f5..caef53d0f6546516fa7aabb2cb3abed70808b3ba 100644 +--- a/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java +@@ -16,6 +16,7 @@ public class FurnaceBurnEvent extends BlockEvent implements Cancellable { + private int burnTime; + private boolean cancelled; + private boolean burning; ++ private boolean consumeFuel = true; // Paper + + public FurnaceBurnEvent(@NotNull final Block furnace, @NotNull final ItemStack fuel, final int burnTime) { + super(furnace); +@@ -70,6 +71,25 @@ public class FurnaceBurnEvent extends BlockEvent implements Cancellable { + public void setBurning(boolean burning) { + this.burning = burning; + } ++ // Paper start ++ /** ++ * Gets whether the furnace's fuel will be consumed or not. ++ * ++ * @return whether the furnace's fuel will be consumed ++ */ ++ public boolean willConsumeFuel() { ++ return consumeFuel; ++ } ++ ++ /** ++ * Sets whether the furnace's fuel will be consumed or not. ++ * ++ * @param consumeFuel true to consume the fuel ++ */ ++ public void setConsumeFuel(boolean consumeFuel) { ++ this.consumeFuel = consumeFuel; ++ } ++ // Paper end + + @Override + public boolean isCancelled() { diff --git a/patches/api-unmapped/0286-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/api-unmapped/0286-add-get-set-drop-chance-to-EntityEquipment.patch new file mode 100644 index 0000000000..447a45db06 --- /dev/null +++ b/patches/api-unmapped/0286-add-get-set-drop-chance-to-EntityEquipment.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 22 Apr 2021 00:28:20 -0700 +Subject: [PATCH] add get-set drop chance to EntityEquipment + + +diff --git a/src/main/java/org/bukkit/inventory/EntityEquipment.java b/src/main/java/org/bukkit/inventory/EntityEquipment.java +index f905bf7a28a42d8bd2aecd42030d2b2092696fc3..58cfd450973f56bfbdd20f9dca8c1e7455260a55 100644 +--- a/src/main/java/org/bukkit/inventory/EntityEquipment.java ++++ b/src/main/java/org/bukkit/inventory/EntityEquipment.java +@@ -405,4 +405,32 @@ public interface EntityEquipment { + */ + @Nullable + Entity getHolder(); ++ // Paper start ++ /** ++ * Gets the drop chance of specified slot. ++ * ++ *

      ++ *
    • A drop chance of 0.0F will never drop ++ *
    • A drop chance of 1.0F will always drop ++ *
    ++ * ++ * @param slot the slot to get the drop chance of ++ * @return the drop chance for the slot ++ */ ++ float getDropChance(@NotNull EquipmentSlot slot); ++ ++ /** ++ * Sets the drop chance of the specified slot. ++ * ++ *
      ++ *
    • A drop chance of 0.0F will never drop ++ *
    • A drop chance of 1.0F will always drop ++ *
    ++ * ++ * @param slot the slot to set the drop chance of ++ * @param chance the drop chance for the slot ++ * @throws UnsupportedOperationException when called on players ++ */ ++ void setDropChance(@NotNull EquipmentSlot slot, float chance); ++ // Paper end + } diff --git a/patches/api-unmapped/0287-Added-PlayerDeepSleepEvent.patch b/patches/api-unmapped/0287-Added-PlayerDeepSleepEvent.patch new file mode 100644 index 0000000000..d8dccca755 --- /dev/null +++ b/patches/api-unmapped/0287-Added-PlayerDeepSleepEvent.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 21 Apr 2021 15:58:25 -0700 +Subject: [PATCH] Added PlayerDeepSleepEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerDeepSleepEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerDeepSleepEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e3ee540bb0a5bc578b148fbcf8b5e39ab9c8575c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerDeepSleepEvent.java +@@ -0,0 +1,46 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a player has slept long enough ++ * to count as passing the night/storm. ++ *

    ++ * Cancelling this event will prevent the player from being counted as deeply sleeping ++ * unless they exit and re-enter the bed. ++ */ ++public class PlayerDeepSleepEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private boolean cancelled; ++ ++ public PlayerDeepSleepEvent(@NotNull Player player) { ++ super(player); ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api-unmapped/0288-More-World-API.patch b/patches/api-unmapped/0288-More-World-API.patch new file mode 100644 index 0000000000..1a3c73561c --- /dev/null +++ b/patches/api-unmapped/0288-More-World-API.patch @@ -0,0 +1,131 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 7 Jul 2020 10:53:22 -0700 +Subject: [PATCH] More World API + + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 98512bddbb0c8bd6a3f487c60b1ec77b274b991e..a1496fe00a2d5ba6c1af054d4327f868b2cd7344 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -3482,6 +3482,120 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + @Nullable + public Location locateNearestStructure(@NotNull Location origin, @NotNull StructureType structureType, int radius, boolean findUnexplored); + ++ // Paper start ++ /** ++ * Locates the nearest biome based on an origin, biome type, and radius to search. ++ * Step defaults to {@code 8}. ++ * ++ * @param origin Origin location ++ * @param biome Biome to find ++ * @param radius radius to search ++ * @return Location of biome or null if not found in specified radius ++ */ ++ @Nullable ++ Location locateNearestBiome(@NotNull Location origin, @NotNull Biome biome, int radius); ++ ++ /** ++ * Locates the nearest biome based on an origin, biome type, and radius to search ++ * and step ++ * ++ * @param origin Origin location ++ * @param biome Biome to find ++ * @param radius radius to search ++ * @param step Search step 1 would mean checking every block, 8 would be every 8th block ++ * @return Location of biome or null if not found in specified radius ++ */ ++ @Nullable ++ Location locateNearestBiome(@NotNull Location origin, @NotNull Biome biome, int radius, int step); ++ ++ /** ++ * Checks if the world: ++ *

      ++ *
    • evaporates water
    • ++ *
    • dries sponges
    • ++ *
    • has lava spread faster and further
    • ++ *
    ++ * ++ * @return true if ultrawarm, false if not ++ */ ++ boolean isUltrawarm(); ++ ++ /** ++ * Checks if the world is natural. ++ *

    ++ * If {@code false}, compasses will spin randomly in the world. ++ * If {@code true}, nether portals will spawn zombified piglins. ++ *

    ++ * ++ * @return true or false ++ */ ++ boolean isNatural(); ++ ++ /** ++ * Gets the coordinate scaling of this world. ++ * ++ * @return the coordinate scale ++ */ ++ double getCoordinateScale(); ++ ++ /** ++ * Checks if the world has skylight access ++ * ++ * @return whether there is skylight ++ */ ++ boolean hasSkylight(); ++ ++ /** ++ * Checks if the world has a bedrock ceiling ++ * ++ * @return whether the world has a bedrock ceiling ++ */ ++ boolean hasBedrockCeiling(); ++ ++ /** ++ * Checks if piglins will turn into Zombified Piglins in this world ++ * ++ * @return whether Piglins will not transform ++ */ ++ boolean isPiglinSafe(); ++ ++ /** ++ * Checks if beds work ++ * ++ * @return whether beds work ++ */ ++ boolean doesBedWork(); ++ ++ /** ++ * Checks if respawn anchors work ++ * ++ * @return whether respawn anchors work ++ */ ++ boolean doesRespawnAnchorWork(); ++ ++ /** ++ * Checks if this world supports raids ++ * ++ * @return whether this world supports raids ++ */ ++ boolean hasRaids(); ++ ++ /** ++ * Checks if this world has a fixed time ++ * ++ * @return whether this world has fixed time ++ */ ++ boolean isFixedTime(); ++ ++ /** ++ * Gets the collection of materials that burn infinitely in this world. ++ * ++ * @return the materials that will forever stay lit by fire ++ */ ++ @NotNull ++ Collection getInfiniburn(); ++ // Paper end ++ + // Spigot start + /** + * Returns the view distance used for this world. diff --git a/patches/api-unmapped/0289-Added-PlayerBedFailEnterEvent.patch b/patches/api-unmapped/0289-Added-PlayerBedFailEnterEvent.patch new file mode 100644 index 0000000000..a622f2b98f --- /dev/null +++ b/patches/api-unmapped/0289-Added-PlayerBedFailEnterEvent.patch @@ -0,0 +1,131 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 24 Dec 2020 12:27:49 -0800 +Subject: [PATCH] Added PlayerBedFailEnterEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerBedFailEnterEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerBedFailEnterEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e0028733615ddc9e34359f673ca1c3cadb133948 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerBedFailEnterEvent.java +@@ -0,0 +1,119 @@ ++package io.papermc.paper.event.player; ++ ++import net.kyori.adventure.text.Component; ++import org.bukkit.block.Block; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++public class PlayerBedFailEnterEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final FailReason failReason; ++ private final Block bed; ++ private boolean willExplode; ++ private Component message; ++ private boolean cancelled; ++ ++ public PlayerBedFailEnterEvent(@NotNull Player player, @NotNull FailReason failReason, @NotNull Block bed, boolean willExplode, @Nullable Component message) { ++ super(player); ++ this.failReason = failReason; ++ this.bed = bed; ++ this.willExplode = willExplode; ++ this.message = message; ++ } ++ ++ @NotNull ++ public FailReason getFailReason() { ++ return failReason; ++ } ++ ++ @NotNull ++ public Block getBed() { ++ return bed; ++ } ++ ++ public boolean getWillExplode() { ++ return willExplode; ++ } ++ ++ public void setWillExplode(boolean willExplode) { ++ this.willExplode = willExplode; ++ } ++ ++ @Nullable ++ public Component getMessage() { ++ return message; ++ } ++ ++ public void setMessage(@Nullable Component message) { ++ this.message = message; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * Cancel this event. ++ *

    ++ * NOTE: This does not cancel the player getting in the bed, but any messages/explosions ++ * that may occur because of the interaction. ++ * @param cancel true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ public static enum FailReason { ++ /** ++ * The world doesn't allow sleeping (ex. Nether or The End). Entering ++ * the bed is prevented and the bed explodes. ++ */ ++ NOT_POSSIBLE_HERE, ++ /** ++ * Entering the bed is prevented due to it not being night nor ++ * thundering currently. ++ *

    ++ * If the event is forcefully allowed during daytime, the player will ++ * enter the bed (and set its bed location), but might get immediately ++ * thrown out again. ++ */ ++ NOT_POSSIBLE_NOW, ++ /** ++ * Entering the bed is prevented due to the player being too far away. ++ */ ++ TOO_FAR_AWAY, ++ /** ++ * Bed is obstructed. ++ */ ++ OBSTRUCTED, ++ /** ++ * Entering the bed is prevented due to there being some other problem. ++ */ ++ OTHER_PROBLEM, ++ /** ++ * Entering the bed is prevented due to there being monsters nearby. ++ */ ++ NOT_SAFE; ++ ++ public static final FailReason[] VALUES = values(); ++ } ++} diff --git a/patches/api-unmapped/0290-Introduce-beacon-activation-deactivation-events.patch b/patches/api-unmapped/0290-Introduce-beacon-activation-deactivation-events.patch new file mode 100644 index 0000000000..c2f0577191 --- /dev/null +++ b/patches/api-unmapped/0290-Introduce-beacon-activation-deactivation-events.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spyridon Pagkalos +Date: Thu, 25 Mar 2021 20:25:47 +0200 +Subject: [PATCH] Introduce beacon activation/deactivation events + + +diff --git a/src/main/java/io/papermc/paper/event/block/BeaconActivatedEvent.java b/src/main/java/io/papermc/paper/event/block/BeaconActivatedEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7575ca7dd84dee89528ec2e5e5f99f97d8a10f58 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/BeaconActivatedEvent.java +@@ -0,0 +1,40 @@ ++package io.papermc.paper.event.block; ++ ++import org.bukkit.block.Beacon; ++import org.bukkit.block.Block; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a beacon is activated. ++ * Activation occurs when the beacon beam becomes visible. ++ */ ++public class BeaconActivatedEvent extends BlockEvent { ++ private static final HandlerList handlers = new HandlerList(); ++ ++ public BeaconActivatedEvent(@NotNull Block block) { ++ super(block); ++ } ++ ++ /** ++ * Returns the beacon that was activated. ++ * ++ * @return the beacon that was activated. ++ */ ++ @NotNull ++ public Beacon getBeacon() { ++ return (Beacon) block.getState(); ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/block/BeaconDeactivatedEvent.java b/src/main/java/io/papermc/paper/event/block/BeaconDeactivatedEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..34f18468b4cfc08717cc3442778c9e85124e5a22 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/BeaconDeactivatedEvent.java +@@ -0,0 +1,43 @@ ++package io.papermc.paper.event.block; ++ ++import org.bukkit.Material; ++import org.bukkit.block.Beacon; ++import org.bukkit.block.Block; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when a beacon is deactivated, either because its base block(s) or itself were destroyed. ++ */ ++public class BeaconDeactivatedEvent extends BlockEvent { ++ private static final HandlerList handlers = new HandlerList(); ++ ++ public BeaconDeactivatedEvent(@NotNull Block block) { ++ super(block); ++ } ++ ++ /** ++ * Returns the beacon that was deactivated. ++ * This will return null if the beacon does not exist. ++ * (which can occur after the deactivation of a now broken beacon) ++ * ++ * @return The beacon that got deactivated, or null if it does not exist. ++ */ ++ @Nullable ++ public Beacon getBeacon() { ++ return block.getType() == Material.BEACON ? (Beacon) block.getState() : null; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0291-PlayerMoveEvent-Improvements.patch b/patches/api-unmapped/0291-PlayerMoveEvent-Improvements.patch new file mode 100644 index 0000000000..33cf16e54b --- /dev/null +++ b/patches/api-unmapped/0291-PlayerMoveEvent-Improvements.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Thu, 29 Apr 2021 10:31:44 +0100 +Subject: [PATCH] PlayerMoveEvent Improvements + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java b/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java +index 1a58734d919fae247eeb85dd785fd59990856505..b484abf3b06b1fb3577b43d50d64498dcd7652c9 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java +@@ -93,6 +93,53 @@ public class PlayerMoveEvent extends PlayerEvent implements Cancellable { + this.to = to; + } + ++ // Paper start - PlayerMoveEvent improvements ++ /** ++ * Check if the player has changed position (even within the same block) in the event ++ * ++ * @return whether the player has changed position or not ++ */ ++ public boolean hasChangedPosition() { ++ return hasExplicitlyChangedPosition() || !from.getWorld().equals(to.getWorld()); ++ } ++ ++ /** ++ * Check if the player has changed position (even within the same block) in the event, disregarding a possible world change ++ * ++ * @return whether the player has changed position or not ++ */ ++ public boolean hasExplicitlyChangedPosition() { ++ return from.getX() != to.getX() || from.getY() != to.getY() || from.getZ() != to.getZ(); ++ } ++ ++ /** ++ * Check if the player has moved to a new block in the event ++ * ++ * @return whether the player has moved to a new block or not ++ */ ++ public boolean hasChangedBlock() { ++ return hasExplicitlyChangedBlock() || !from.getWorld().equals(to.getWorld()); ++ } ++ ++ /** ++ * Check if the player has moved to a new block in the event, disregarding a possible world change ++ * ++ * @return whether the player has moved to a new block or not ++ */ ++ public boolean hasExplicitlyChangedBlock() { ++ return from.getBlockX() != to.getBlockX() || from.getBlockY() != to.getBlockY() || from.getBlockZ() != to.getBlockZ(); ++ } ++ ++ /** ++ * Check if the player has changed orientation in the event ++ * ++ * @return whether the player has changed orientation or not ++ */ ++ public boolean hasChangedOrientation() { ++ return from.getPitch() != to.getPitch() || from.getYaw() != to.getYaw(); ++ } ++ // Paper end ++ + private void validateLocation(@NotNull Location loc) { + Preconditions.checkArgument(loc != null, "Cannot use null location!"); + Preconditions.checkArgument(loc.getWorld() != null, "Cannot use null location with null world!"); diff --git a/patches/api-unmapped/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/api-unmapped/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch new file mode 100644 index 0000000000..41342d0d34 --- /dev/null +++ b/patches/api-unmapped/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 22 Apr 2021 17:17:54 -0700 +Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java b/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java +index d2be2ad2e3665728e614a89dd62ef9237f1d3ce6..359e385bd6854a4b146cd0a54badb9c3d31ca12d 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java +@@ -14,17 +14,30 @@ public class PlayerRespawnEvent extends PlayerEvent { + private Location respawnLocation; + private final boolean isBedSpawn; + private final boolean isAnchorSpawn; ++ private final java.util.Set respawnFlags; // Paper + + @Deprecated + public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn) { + this(respawnPlayer, respawnLocation, isBedSpawn, false); + } + ++ @Deprecated // Paper + public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn) { ++ // Paper start ++ this(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, com.google.common.collect.ImmutableSet.builder()); ++ } ++ ++ public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn, @NotNull final com.google.common.collect.ImmutableSet.Builder respawnFlags) { ++ // Paper end + super(respawnPlayer); + this.respawnLocation = respawnLocation; + this.isBedSpawn = isBedSpawn; + this.isAnchorSpawn = isAnchorSpawn; ++ // Paper start ++ if (this.isBedSpawn) { respawnFlags.add(RespawnFlag.BED_SPAWN); } ++ if (this.isAnchorSpawn) { respawnFlags.add(RespawnFlag.ANCHOR_SPAWN); } ++ this.respawnFlags = respawnFlags.build(); ++ // Paper end + } + + /** +@@ -77,4 +90,31 @@ public class PlayerRespawnEvent extends PlayerEvent { + public static HandlerList getHandlerList() { + return handlers; + } ++ ++ // Paper start ++ /** ++ * Get the set of flags that apply to this respawn. ++ * ++ * @return an immutable set of the flags that apply to this respawn ++ */ ++ @NotNull ++ public java.util.Set getRespawnFlags() { ++ return respawnFlags; ++ } ++ ++ public enum RespawnFlag { ++ /** ++ * Will use the bed spawn location ++ */ ++ BED_SPAWN, ++ /** ++ * Will use the respawn anchor location ++ */ ++ ANCHOR_SPAWN, ++ /** ++ * Is caused by going to the end portal in the end. ++ */ ++ END_PORTAL, ++ } ++ // Paper end + } diff --git a/patches/api-unmapped/0293-Add-more-WanderingTrader-API.patch b/patches/api-unmapped/0293-Add-more-WanderingTrader-API.patch new file mode 100644 index 0000000000..99045d4949 --- /dev/null +++ b/patches/api-unmapped/0293-Add-more-WanderingTrader-API.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Thu, 6 May 2021 14:56:26 +0100 +Subject: [PATCH] Add more WanderingTrader API + + +diff --git a/src/main/java/org/bukkit/entity/WanderingTrader.java b/src/main/java/org/bukkit/entity/WanderingTrader.java +index 55394ed5c68cb0bf4333fc918e3b4c8c4e3db0c6..da76e1ed5406322073dd8c7a89ca55aa68620ac4 100644 +--- a/src/main/java/org/bukkit/entity/WanderingTrader.java ++++ b/src/main/java/org/bukkit/entity/WanderingTrader.java +@@ -28,4 +28,30 @@ public interface WanderingTrader extends AbstractVillager { + * {@link WanderingTrader} is forcibly despawned + */ + public void setDespawnDelay(int despawnDelay); ++ ++ // Paper start - Add more WanderingTrader API ++ /** ++ * Set if the Wandering Trader can and will drink an invisibility potion. ++ * @param bool whether the mob will drink ++ */ ++ public void setCanDrinkPotion(boolean bool); ++ ++ /** ++ * Get if the Wandering Trader can and will drink an invisibility potion. ++ * @return whether the mob will drink ++ */ ++ public boolean canDrinkPotion(); ++ ++ /** ++ * Set if the Wandering Trader can and will drink milk. ++ * @param bool whether the mob will drink ++ */ ++ public void setCanDrinkMilk(boolean bool); ++ ++ /** ++ * Get if the Wandering Trader can and will drink milk. ++ * @return whether the mob will drink ++ */ ++ public boolean canDrinkMilk(); ++ // Paper end + } diff --git a/patches/api-unmapped/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/api-unmapped/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch new file mode 100644 index 0000000000..b2fb9bb339 --- /dev/null +++ b/patches/api-unmapped/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch @@ -0,0 +1,407 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Thu, 1 Apr 2021 00:34:41 -0700 +Subject: [PATCH] Allow for Component suggestion tooltips in + AsyncTabCompleteEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java +index 619ed37169c126a8c75d02699a04728bac49d10d..4cd97cb102e1ec53b3fe1a451b65b4b640fde099 100644 +--- a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java ++++ b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java +@@ -24,6 +24,11 @@ + package com.destroystokyo.paper.event.server; + + import com.google.common.collect.ImmutableList; ++import io.papermc.paper.util.TransformingRandomAccessList; ++import net.kyori.adventure.text.Component; ++import net.kyori.examination.Examinable; ++import net.kyori.examination.ExaminableProperty; ++import net.kyori.examination.string.StringExaminer; + import org.apache.commons.lang.Validate; + import org.bukkit.Location; + import org.bukkit.command.Command; +@@ -34,6 +39,7 @@ import org.bukkit.event.HandlerList; + + import java.util.ArrayList; + import java.util.List; ++import java.util.stream.Stream; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + +@@ -48,15 +54,29 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { + private final boolean isCommand; + @Nullable + private final Location loc; +- @NotNull private List completions; ++ private final List completions = new ArrayList<>(); ++ private final List stringCompletions = new TransformingRandomAccessList<>( ++ this.completions, ++ Completion::suggestion, ++ Completion::completion ++ ); + private boolean cancelled; + private boolean handled = false; + private boolean fireSyncHandler = true; + ++ public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, boolean isCommand, @Nullable Location loc) { ++ super(true); ++ this.sender = sender; ++ this.buffer = buffer; ++ this.isCommand = isCommand; ++ this.loc = loc; ++ } ++ ++ @Deprecated + public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull List completions, @NotNull String buffer, boolean isCommand, @Nullable Location loc) { + super(true); + this.sender = sender; +- this.completions = completions; ++ this.completions.addAll(fromStrings(completions)); + this.buffer = buffer; + this.isCommand = isCommand; + this.loc = loc; +@@ -84,7 +104,7 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { + */ + @NotNull + public List getCompletions() { +- return completions; ++ return this.stringCompletions; + } + + /** +@@ -98,8 +118,42 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { + * @param completions the new completions + */ + public void setCompletions(@NotNull List completions) { ++ if (completions == this.stringCompletions) { ++ return; ++ } + Validate.notNull(completions); +- this.completions = new ArrayList<>(completions); ++ this.completions.clear(); ++ this.completions.addAll(fromStrings(completions)); ++ } ++ ++ /** ++ * The list of {@link Completion completions} which will be offered to the sender, in order. ++ * This list is mutable and reflects what will be offered. ++ *

    ++ * If this collection is not empty after the event is fired, then ++ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} ++ * or current player names will not be called. ++ * ++ * @return a list of offered completions ++ */ ++ public @NotNull List completions() { ++ return this.completions; ++ } ++ ++ /** ++ * Set the {@link Completion completions} offered, overriding any already set. ++ * If this collection is not empty after the event is fired, then ++ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} ++ * or current player names will not be called. ++ *

    ++ * The passed collection will be cloned to a new List. You must call {{@link #completions()}} to mutate from here ++ * ++ * @param newCompletions the new completions ++ */ ++ public void completions(final @NotNull List newCompletions) { ++ Validate.notNull(newCompletions, "new completions"); ++ this.completions.clear(); ++ this.completions.addAll(newCompletions); + } + + /** +@@ -174,4 +228,102 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { + public static HandlerList getHandlerList() { + return handlers; + } ++ ++ private static @NotNull List fromStrings(final @NotNull List strings) { ++ final List list = new ArrayList<>(); ++ for (final String it : strings) { ++ list.add(new CompletionImpl(it, null)); ++ } ++ return list; ++ } ++ ++ /** ++ * A rich tab completion, consisting of a string suggestion, and a nullable {@link Component} tooltip. ++ */ ++ public interface Completion extends Examinable { ++ /** ++ * Get the suggestion string for this {@link Completion}. ++ * ++ * @return suggestion string ++ */ ++ @NotNull String suggestion(); ++ ++ /** ++ * Get the suggestion tooltip for this {@link Completion}. ++ * ++ * @return tooltip component ++ */ ++ @Nullable Component tooltip(); ++ ++ @Override ++ default @NotNull Stream examinableProperties() { ++ return Stream.of(ExaminableProperty.of("suggestion", this.suggestion()), ExaminableProperty.of("tooltip", this.tooltip())); ++ } ++ ++ /** ++ * Create a new {@link Completion} from a suggestion string. ++ * ++ * @param suggestion suggestion string ++ * @return new completion instance ++ */ ++ static @NotNull Completion completion(final @NotNull String suggestion) { ++ return new CompletionImpl(suggestion, null); ++ } ++ ++ /** ++ * Create a new {@link Completion} from a suggestion string and a tooltip {@link Component}. ++ * ++ *

    If the provided component is null, the suggestion will not have a tooltip.

    ++ * ++ * @param suggestion suggestion string ++ * @param tooltip tooltip component, or null ++ * @return new completion instance ++ */ ++ static @NotNull Completion completion(final @NotNull String suggestion, final @Nullable Component tooltip) { ++ return new CompletionImpl(suggestion, tooltip); ++ } ++ } ++ ++ static final class CompletionImpl implements Completion { ++ private final String suggestion; ++ private final Component tooltip; ++ ++ CompletionImpl(final @NotNull String suggestion, final @Nullable Component tooltip) { ++ this.suggestion = suggestion; ++ this.tooltip = tooltip; ++ } ++ ++ @Override ++ public @NotNull String suggestion() { ++ return this.suggestion; ++ } ++ ++ @Override ++ public @Nullable Component tooltip() { ++ return this.tooltip; ++ } ++ ++ @Override ++ public boolean equals(final @Nullable Object o) { ++ if (this == o) { ++ return true; ++ } ++ if (o == null || this.getClass() != o.getClass()) { ++ return false; ++ } ++ final CompletionImpl that = (CompletionImpl) o; ++ return this.suggestion.equals(that.suggestion) ++ && java.util.Objects.equals(this.tooltip, that.tooltip); ++ } ++ ++ @Override ++ public int hashCode() { ++ return java.util.Objects.hash(this.suggestion, this.tooltip); ++ } ++ ++ @Override ++ public @NotNull String toString() { ++ return StringExaminer.simpleEscaping().examine(this); ++ } ++ } + } +diff --git a/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java b/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276118c1c7b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java +@@ -0,0 +1,169 @@ ++package io.papermc.paper.util; ++ ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.AbstractList; ++import java.util.Iterator; ++import java.util.List; ++import java.util.ListIterator; ++import java.util.RandomAccess; ++import java.util.function.Function; ++import java.util.function.Predicate; ++ ++import static com.google.common.base.Preconditions.checkNotNull; ++ ++/** ++ * Modified version of the Guava class with the same name to support add operations. ++ * ++ * @param backing list element type ++ * @param transformed list element type ++ */ ++public final class TransformingRandomAccessList extends AbstractList implements RandomAccess { ++ final List fromList; ++ final Function toFunction; ++ final Function fromFunction; ++ ++ /** ++ * Create a new {@link TransformingRandomAccessList}. ++ * ++ * @param fromList backing list ++ * @param toFunction function mapping backing list element type to transformed list element type ++ * @param fromFunction function mapping transformed list element type to backing list element type ++ */ ++ public TransformingRandomAccessList( ++ final @NonNull List fromList, ++ final @NonNull Function toFunction, ++ final @NonNull Function fromFunction ++ ) { ++ this.fromList = checkNotNull(fromList); ++ this.toFunction = checkNotNull(toFunction); ++ this.fromFunction = checkNotNull(fromFunction); ++ } ++ ++ @Override ++ public void clear() { ++ this.fromList.clear(); ++ } ++ ++ @Override ++ public T get(int index) { ++ return this.toFunction.apply(this.fromList.get(index)); ++ } ++ ++ @Override ++ public @NotNull Iterator iterator() { ++ return this.listIterator(); ++ } ++ ++ @Override ++ public @NotNull ListIterator listIterator(int index) { ++ return new TransformedListIterator(this.fromList.listIterator(index)) { ++ @Override ++ T transform(F from) { ++ return TransformingRandomAccessList.this.toFunction.apply(from); ++ } ++ ++ @Override ++ F transformBack(T from) { ++ return TransformingRandomAccessList.this.fromFunction.apply(from); ++ } ++ }; ++ } ++ ++ @Override ++ public boolean isEmpty() { ++ return this.fromList.isEmpty(); ++ } ++ ++ @Override ++ public boolean removeIf(Predicate filter) { ++ checkNotNull(filter); ++ return this.fromList.removeIf(element -> filter.test(this.toFunction.apply(element))); ++ } ++ ++ @Override ++ public T remove(int index) { ++ return this.toFunction.apply(this.fromList.remove(index)); ++ } ++ ++ @Override ++ public int size() { ++ return this.fromList.size(); ++ } ++ ++ @Override ++ public T set(int i, T t) { ++ return this.toFunction.apply(this.fromList.set(i, this.fromFunction.apply(t))); ++ } ++ ++ @Override ++ public void add(int i, T t) { ++ this.fromList.add(i, this.fromFunction.apply(t)); ++ } ++ ++ static abstract class TransformedListIterator implements ListIterator, Iterator { ++ final Iterator backingIterator; ++ ++ TransformedListIterator(ListIterator backingIterator) { ++ this.backingIterator = checkNotNull((Iterator) backingIterator); ++ } ++ ++ private ListIterator backingIterator() { ++ return cast(this.backingIterator); ++ } ++ ++ static
    ListIterator cast(Iterator iterator) { ++ return (ListIterator) iterator; ++ } ++ ++ @Override ++ public final boolean hasPrevious() { ++ return this.backingIterator().hasPrevious(); ++ } ++ ++ @Override ++ public final T previous() { ++ return this.transform(this.backingIterator().previous()); ++ } ++ ++ @Override ++ public final int nextIndex() { ++ return this.backingIterator().nextIndex(); ++ } ++ ++ @Override ++ public final int previousIndex() { ++ return this.backingIterator().previousIndex(); ++ } ++ ++ @Override ++ public void set(T element) { ++ this.backingIterator().set(this.transformBack(element)); ++ } ++ ++ @Override ++ public void add(T element) { ++ this.backingIterator().add(this.transformBack(element)); ++ } ++ ++ abstract T transform(F from); ++ ++ abstract F transformBack(T to); ++ ++ @Override ++ public final boolean hasNext() { ++ return this.backingIterator.hasNext(); ++ } ++ ++ @Override ++ public final T next() { ++ return this.transform(this.backingIterator.next()); ++ } ++ ++ @Override ++ public final void remove() { ++ this.backingIterator.remove(); ++ } ++ } ++} +diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java +index 19271057cf24329757c9419fa6c97848e008a96c..82b2783497947f336b0dd95db61f31f8f77f446c 100644 +--- a/src/test/java/org/bukkit/AnnotationTest.java ++++ b/src/test/java/org/bukkit/AnnotationTest.java +@@ -48,6 +48,8 @@ public class AnnotationTest { + // Generic functional interface + "org/bukkit/util/Consumer", + // Paper start ++ "io/papermc/paper/util/TransformingRandomAccessList", ++ "io/papermc/paper/util/TransformingRandomAccessList$TransformedListIterator", + // Timings history is broken in terms of nullability due to guavas Function defining that the param is NonNull + "co/aikar/timings/TimingHistory$2", + "co/aikar/timings/TimingHistory$2$1", diff --git a/patches/api-unmapped/0295-Add-EntityBlockStorage-clearEntities.patch b/patches/api-unmapped/0295-Add-EntityBlockStorage-clearEntities.patch new file mode 100644 index 0000000000..7032ba6155 --- /dev/null +++ b/patches/api-unmapped/0295-Add-EntityBlockStorage-clearEntities.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Mon, 5 Apr 2021 18:12:06 -0400 +Subject: [PATCH] Add EntityBlockStorage#clearEntities() + + +diff --git a/src/main/java/org/bukkit/block/EntityBlockStorage.java b/src/main/java/org/bukkit/block/EntityBlockStorage.java +index f3f8d765d5d487aa14edf0b88c32608fb804c331..739911cda33b373f99df627a3a378b37d7d461aa 100644 +--- a/src/main/java/org/bukkit/block/EntityBlockStorage.java ++++ b/src/main/java/org/bukkit/block/EntityBlockStorage.java +@@ -53,4 +53,11 @@ public interface EntityBlockStorage extends TileState { + * @param entity Entity to add to the block + */ + void addEntity(@NotNull T entity); ++ ++ // Paper start - Add EntityBlockStorage clearEntities ++ /** ++ * Clear all currently stored entities in the block. ++ */ ++ void clearEntities(); ++ // Paper end + } diff --git a/patches/api-unmapped/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/api-unmapped/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch new file mode 100644 index 0000000000..16af3a7728 --- /dev/null +++ b/patches/api-unmapped/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alvinn8 <42838560+Alvinn8@users.noreply.github.com> +Date: Fri, 8 Jan 2021 20:29:58 +0100 +Subject: [PATCH] Add Adventure message to PlayerAdvancementDoneEvent + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerAdvancementDoneEvent.java b/src/main/java/org/bukkit/event/player/PlayerAdvancementDoneEvent.java +index 21ff095afb434d15babcdbe85fa0b94cbb7e75a7..6f618bb140a901c5c1cd08210978a6a651677ba4 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerAdvancementDoneEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerAdvancementDoneEvent.java +@@ -4,6 +4,10 @@ import org.bukkit.advancement.Advancement; + import org.bukkit.entity.Player; + import org.bukkit.event.HandlerList; + import org.jetbrains.annotations.NotNull; ++// Paper start ++import org.jetbrains.annotations.Nullable; ++import net.kyori.adventure.text.Component; ++// Paper end + + /** + * Called when a player has completed all criteria in an advancement. +@@ -13,10 +17,17 @@ public class PlayerAdvancementDoneEvent extends PlayerEvent { + private static final HandlerList handlers = new HandlerList(); + // + private final Advancement advancement; ++ private Component message; // Paper - Add Adventure message + + public PlayerAdvancementDoneEvent(@NotNull Player who, @NotNull Advancement advancement) { ++ // Paper start - Add Adventure message ++ this(who, advancement, null); ++ } ++ public PlayerAdvancementDoneEvent(@NotNull Player who, @NotNull Advancement advancement, @Nullable Component message) { ++ // Paper end + super(who); + this.advancement = advancement; ++ this.message = message; // Paper - Add Adventure message + } + + /** +@@ -29,6 +40,31 @@ public class PlayerAdvancementDoneEvent extends PlayerEvent { + return advancement; + } + ++ // Paper start - Add Adventure message ++ /** ++ * Gets the message to send to all online players. ++ *

    ++ * Will be null if the advancement does not announce to chat, for example if ++ * it is a recipe unlock or a root advancement. ++ * ++ * @return The announcement message, or null ++ */ ++ @Nullable ++ public Component message() { ++ return this.message; ++ } ++ ++ /** ++ * Sets the message to send to all online players. ++ *

    ++ * If set to null the message will not be sent. ++ * ++ * @param message The new message ++ */ ++ public void message(@Nullable Component message) { ++ this.message = message; ++ } ++ // Paper end + @NotNull + @Override + public HandlerList getHandlers() { diff --git a/patches/api-unmapped/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/api-unmapped/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch new file mode 100644 index 0000000000..58db0a8a2b --- /dev/null +++ b/patches/api-unmapped/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Connor Linfoot +Date: Wed, 12 May 2021 08:09:19 +0100 +Subject: [PATCH] Add raw address to AsyncPlayerPreLoginEvent + + +diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +index c9af02b0f62b3d18da1e91d1ea02ce0864fc60b9..77aefda5aac4602bf5bf71c29600e7450defdd4e 100644 +--- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java ++++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +@@ -20,6 +20,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + private net.kyori.adventure.text.Component message; // Paper + //private String name; // Paper - Not used anymore + private final InetAddress ipAddress; ++ private final InetAddress rawAddress; // Paper + //private UUID uniqueId; // Paper - Not used anymore + + @Deprecated +@@ -49,7 +50,23 @@ public class AsyncPlayerPreLoginEvent extends Event { + this.profile = profile; + } + ++ // Paper Start ++ /** ++ * Gets the raw address of the player logging in ++ * @return The address ++ */ ++ @NotNull ++ public InetAddress getRawAddress() { ++ return rawAddress; ++ } ++ // Paper end ++ ++ @Deprecated + public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId, @NotNull PlayerProfile profile) { ++ this(name, ipAddress, ipAddress, uniqueId, profile); ++ } ++ ++ public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final InetAddress rawAddress, @NotNull final UUID uniqueId, @NotNull PlayerProfile profile) { + super(true); + this.profile = profile; + // Paper end +@@ -57,6 +74,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + this.message = net.kyori.adventure.text.Component.empty(); // Paper + //this.name = name; // Paper - Not used anymore + this.ipAddress = ipAddress; ++ this.rawAddress = rawAddress; // Paper + //this.uniqueId = uniqueId; // Paper - Not used anymore + } + diff --git a/patches/api-unmapped/0298-Inventory-close.patch b/patches/api-unmapped/0298-Inventory-close.patch new file mode 100644 index 0000000000..550e287fa6 --- /dev/null +++ b/patches/api-unmapped/0298-Inventory-close.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 11 May 2021 14:54:20 -0700 +Subject: [PATCH] Inventory#close + + +diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java +index 7956aebcb390379677dccf7c9561866cf94c024c..8f00cb2e3bc9963e9657c1b2493e8b015a6664d0 100644 +--- a/src/main/java/org/bukkit/inventory/Inventory.java ++++ b/src/main/java/org/bukkit/inventory/Inventory.java +@@ -353,6 +353,15 @@ public interface Inventory extends Iterable { + */ + public void clear(); + ++ // Paper start ++ /** ++ * Closes the inventory for all viewers. ++ * ++ * @return the number if viewers the inventory was closed for ++ */ ++ public int close(); ++ // Paper end ++ + /** + * Gets a list of players viewing the inventory. Note that a player is + * considered to be viewing their own inventory and internal crafting diff --git a/patches/api-unmapped/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/api-unmapped/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch new file mode 100644 index 0000000000..9b01b30676 --- /dev/null +++ b/patches/api-unmapped/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Tue, 11 May 2021 00:48:51 +0200 +Subject: [PATCH] Add a "should burn in sunlight" API for Phantoms and + Skeletons + + +diff --git a/src/main/java/org/bukkit/entity/Phantom.java b/src/main/java/org/bukkit/entity/Phantom.java +index ed4d417c2deefb78807cb61b01df5afcd334d754..a40b045f08b85e22e75459b547e7e7c0b95103ed 100644 +--- a/src/main/java/org/bukkit/entity/Phantom.java ++++ b/src/main/java/org/bukkit/entity/Phantom.java +@@ -26,5 +26,19 @@ public interface Phantom extends Flying { + */ + @Nullable + public java.util.UUID getSpawningEntity(); ++ ++ /** ++ * Check if this phantom will burn in the sunlight ++ * ++ * @return True if phantom will burn in sunlight ++ */ ++ public boolean shouldBurnInDay(); ++ ++ /** ++ * Set if this phantom should burn in the sunlight ++ * ++ * @param shouldBurnInDay True to burn in sunlight ++ */ ++ public void setShouldBurnInDay(boolean shouldBurnInDay); + // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/Skeleton.java b/src/main/java/org/bukkit/entity/Skeleton.java +index 1c367f78eadf24850061a84ce63b950b79d3c435..684477b894e52ff33f9fce2edf76e58c292dd75e 100644 +--- a/src/main/java/org/bukkit/entity/Skeleton.java ++++ b/src/main/java/org/bukkit/entity/Skeleton.java +@@ -46,4 +46,19 @@ public interface Skeleton extends Monster, RangedEntity { // Paper + */ + STRAY; + } ++ // Paper start ++ /** ++ * Check if this skeleton will burn in the sunlight ++ * ++ * @return True if skeleton will burn in sunlight ++ */ ++ boolean shouldBurnInDay(); ++ ++ /** ++ * Set if this skeleton should burn in the sunlight ++ * ++ * @param shouldBurnInDay True to burn in sunlight ++ */ ++ void setShouldBurnInDay(boolean shouldBurnInDay); ++ // Paper end + } diff --git a/patches/api-unmapped/0300-Add-basic-Datapack-API.patch b/patches/api-unmapped/0300-Add-basic-Datapack-API.patch new file mode 100644 index 0000000000..ae9149d2f3 --- /dev/null +++ b/patches/api-unmapped/0300-Add-basic-Datapack-API.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Connor Linfoot +Date: Sun, 16 May 2021 15:07:34 +0100 +Subject: [PATCH] Add basic Datapack API + + +diff --git a/src/main/java/io/papermc/paper/datapack/Datapack.java b/src/main/java/io/papermc/paper/datapack/Datapack.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7b2ab0be10a21e0496ad1d485ff8cb2c0b92a2cb +--- /dev/null ++++ b/src/main/java/io/papermc/paper/datapack/Datapack.java +@@ -0,0 +1,32 @@ ++package io.papermc.paper.datapack; ++ ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++public interface Datapack { ++ ++ /** ++ * @return the name of the pack ++ */ ++ @NonNull ++ String getName(); ++ ++ /** ++ * @return the compatibility of the pack ++ */ ++ @NonNull ++ Compatibility getCompatibility(); ++ ++ /** ++ * @return whether or not the pack is currently enabled ++ */ ++ boolean isEnabled(); ++ ++ void setEnabled(boolean enabled); ++ ++ enum Compatibility { ++ TOO_OLD, ++ TOO_NEW, ++ COMPATIBLE, ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/datapack/DatapackManager.java b/src/main/java/io/papermc/paper/datapack/DatapackManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..58f78d5e91beacaf710f62461cf869f70d08b2a2 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/datapack/DatapackManager.java +@@ -0,0 +1,21 @@ ++package io.papermc.paper.datapack; ++ ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++import java.util.Collection; ++ ++public interface DatapackManager { ++ ++ /** ++ * @return all the packs known to the server ++ */ ++ @NonNull ++ Collection getPacks(); ++ ++ /** ++ * @return all the packs which are currently enabled ++ */ ++ @NonNull ++ Collection getEnabledPacks(); ++ ++} +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 050ee6a6fd0b74d9bfdd9dfe88cd4cd3d17da868..a8b6cc350e85d4f1a31f30dee42feafd0edb6009 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1949,6 +1949,14 @@ public final class Bukkit { + public static com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { + return server.getMobGoals(); + } ++ ++ /** ++ * @return the datapack manager ++ */ ++ @NotNull ++ public static io.papermc.paper.datapack.DatapackManager getDatapackManager() { ++ return server.getDatapackManager(); ++ } + // Paper end + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index eb7f604600839618eaf27e0e5444b4830716eb07..2b400079559abd6b847782ae8480f2ae1948e22a 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1709,5 +1709,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + */ + @NotNull + com.destroystokyo.paper.entity.ai.MobGoals getMobGoals(); ++ ++ /** ++ * @return the datapack manager ++ */ ++ @NotNull ++ io.papermc.paper.datapack.DatapackManager getDatapackManager(); + // Paper end + } diff --git a/patches/api-unmapped/0301-additions-to-PlayerGameModeChangeEvent.patch b/patches/api-unmapped/0301-additions-to-PlayerGameModeChangeEvent.patch new file mode 100644 index 0000000000..07c662e585 --- /dev/null +++ b/patches/api-unmapped/0301-additions-to-PlayerGameModeChangeEvent.patch @@ -0,0 +1,111 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 10:04:50 -0700 +Subject: [PATCH] additions to PlayerGameModeChangeEvent + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerGameModeChangeEvent.java b/src/main/java/org/bukkit/event/player/PlayerGameModeChangeEvent.java +index 4b96e0573c7ce32ad8c41124ee9ecab8359318a5..b71f37dc8ac00175efd9275e9d8988bb5f2d9c47 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerGameModeChangeEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerGameModeChangeEvent.java +@@ -13,10 +13,22 @@ public class PlayerGameModeChangeEvent extends PlayerEvent implements Cancellabl + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private final GameMode newGameMode; ++ // Paper start ++ private final Cause cause; ++ private net.kyori.adventure.text.Component cancelMessage; + ++ @Deprecated // Paper end + public PlayerGameModeChangeEvent(@NotNull final Player player, @NotNull final GameMode newGameMode) { ++ // Paper start ++ this(player, newGameMode, Cause.UNKNOWN, null); ++ } ++ ++ public PlayerGameModeChangeEvent(@NotNull final Player player, @NotNull final GameMode newGameMode, @NotNull Cause cause, @org.jetbrains.annotations.Nullable net.kyori.adventure.text.Component cancelMessage) { ++ // Paper end + super(player); + this.newGameMode = newGameMode; ++ this.cause = cause; // Paper ++ this.cancelMessage = cancelMessage; // Paper + } + + @Override +@@ -49,4 +61,77 @@ public class PlayerGameModeChangeEvent extends PlayerEvent implements Cancellabl + public static HandlerList getHandlerList() { + return handlers; + } ++ // Paper start ++ /** ++ * Gets the cause of this gamemode change. ++ * ++ * @return the cause ++ */ ++ @NotNull ++ public Cause getCause() { ++ return cause; ++ } ++ ++ /** ++ * Only valid if the cause of the gamemode change was directly due to a command.. ++ * Gets the message shown to the command user if the event is cancelled ++ * as a notification that a player's gamemode was not changed. ++ *

    ++ * This returns {@code null} if the gamemode change was due to a plugin, or a ++ * player joining the game with a gamemode not equal to the server default gamemode ++ * and {@code force-gamemode} is set to true. ++ * ++ * @return the error message shown to the command user, null if not directly caused by a command ++ */ ++ @org.jetbrains.annotations.Nullable ++ public net.kyori.adventure.text.Component cancelMessage() { ++ return cancelMessage; ++ } ++ ++ /** ++ * Sets the message shown to the command user if the event was cancelled. ++ * The message is only shown to cancelled events that are directly called by a command ++ * not by a plugin or a player joining with the wrong gamemode. ++ * ++ * @param message the error message shown to the command user, null to show no message. ++ */ ++ public void cancelMessage(@org.jetbrains.annotations.Nullable net.kyori.adventure.text.Component message) { ++ this.cancelMessage = message; ++ } ++ ++ public enum Cause { ++ ++ /** ++ * A plugin changed the player's gamemode with ++ * {@link Player#setGameMode(GameMode)}. ++ */ ++ PLUGIN, ++ ++ /** ++ * The {@code /gamemode} command was used. ++ */ ++ COMMAND, ++ ++ /** ++ * A player had their gamemode changed as a result of ++ * the {@code /defaultgamemode} command, or they joined ++ * with a gamemode that was not the default gamemode and ++ * {@code force-gamemode} in {@code server.properties} is set to true. ++ */ ++ DEFAULT_GAMEMODE, ++ ++ /** ++ * When the player dies in a hardcore world and has their gamemode ++ * changed to {@link GameMode#SPECTATOR}. ++ */ ++ HARDCORE_DEATH, ++ ++ /** ++ * This cause is only used if a plugin fired their own ++ * {@link PlayerGameModeChangeEvent} and did not include a ++ * cause. Can usually be ignored. ++ */ ++ UNKNOWN, ++ } ++ // Paper end + } diff --git a/patches/api-unmapped/0302-ItemStack-repair-check-API.patch b/patches/api-unmapped/0302-ItemStack-repair-check-API.patch new file mode 100644 index 0000000000..2281b38541 --- /dev/null +++ b/patches/api-unmapped/0302-ItemStack-repair-check-API.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 22:10:50 -0700 +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 6dbd520182b1e7713a68baad09b7f613424ef619..e504567cf755557be8511f2c93c171572b78e722 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -155,6 +155,16 @@ public interface UnsafeValues { + */ + public io.papermc.paper.inventory.ItemRarity getItemStackRarity(ItemStack itemStack); + ++ /** ++ * Checks if an itemstack can be repaired with another itemstack. ++ * Returns false if either argument's type is not an item ({@link Material#isItem()}). ++ * ++ * @param itemToBeRepaired the itemstack to be repaired ++ * @param repairMaterial the repair material ++ * @return true if valid repair, false if not ++ */ ++ public boolean isValidRepairItemStack(@org.jetbrains.annotations.NotNull ItemStack itemToBeRepaired, @org.jetbrains.annotations.NotNull ItemStack repairMaterial); ++ + /** + * Returns the server's protocol version. + * +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index fccfae41f53a175e1a6a670c793e464456de6b60..0f8c593ae9bca46081f0b22c2d763a2699175398 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -873,5 +873,27 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + public io.papermc.paper.inventory.ItemRarity getRarity() { + return Bukkit.getUnsafe().getItemStackRarity(this); + } ++ ++ /** ++ * Checks if an itemstack can repair this itemstack. ++ * Returns false if {@code this} or {@code repairMaterial}'s type is not an item ({@link Material#isItem()}). ++ * ++ * @param repairMaterial the repair material ++ * @return true if it is repairable by, false if not ++ */ ++ public boolean isRepairableBy(@NotNull ItemStack repairMaterial) { ++ return Bukkit.getUnsafe().isValidRepairItemStack(this, repairMaterial); ++ } ++ ++ /** ++ * Checks if this itemstack can repair another. ++ * Returns false if {@code this} or {@code toBeRepaired}'s type is not an item ({@link Material#isItem()}). ++ * ++ * @param toBeRepaired the itemstack to be repaired ++ * @return true if it can repair, false if not ++ */ ++ public boolean canRepair(@NotNull ItemStack toBeRepaired) { ++ return Bukkit.getUnsafe().isValidRepairItemStack(toBeRepaired, this); ++ } + // Paper end + } diff --git a/patches/api-unmapped/0303-More-Enchantment-API.patch b/patches/api-unmapped/0303-More-Enchantment-API.patch new file mode 100644 index 0000000000..dda68575ca --- /dev/null +++ b/patches/api-unmapped/0303-More-Enchantment-API.patch @@ -0,0 +1,124 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 6 May 2021 19:58:03 -0700 +Subject: [PATCH] More Enchantment API + + +diff --git a/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java b/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e6a40c1fcea761bd66743b50e3da3d14797d05b0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java +@@ -0,0 +1,24 @@ ++package io.papermc.paper.enchantments; ++ ++public enum EnchantmentRarity { ++ ++ COMMON(10), ++ UNCOMMON(5), ++ RARE(2), ++ VERY_RARE(1); ++ ++ private final int weight; ++ ++ EnchantmentRarity(int weight) { ++ this.weight = weight; ++ } ++ ++ /** ++ * Gets the weight for the rarity. ++ * ++ * @return the weight ++ */ ++ public int getWeight() { ++ return weight; ++ } ++} +diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java +index 8eb0497c81744874809ebc4bc2e28b128e66a926..799813410f40589ba1d7d530a47d87f609764705 100644 +--- a/src/main/java/org/bukkit/enchantments/Enchantment.java ++++ b/src/main/java/org/bukkit/enchantments/Enchantment.java +@@ -306,6 +306,46 @@ public abstract class Enchantment implements Keyed { + * @return the name of the enchantment with {@code level} applied + */ + public abstract @NotNull net.kyori.adventure.text.Component displayName(int level); ++ ++ /** ++ * Checks if this enchantment can be found in villager trades. ++ * ++ * @return true if the enchantment can be found in trades ++ */ ++ public abstract boolean isTradeable(); ++ ++ /** ++ * Checks if this enchantment can be found in an enchanting table ++ * or use to enchant items generated by loot tables. ++ * ++ * @return true if the enchantment can be found in a table or by loot tables ++ */ ++ public abstract boolean isDiscoverable(); ++ ++ /** ++ * Gets the rarity of this enchantment. ++ * ++ * @return the rarity ++ */ ++ @NotNull ++ public abstract io.papermc.paper.enchantments.EnchantmentRarity getRarity(); ++ ++ /** ++ * Gets the damage increase as a result of the level and entity category specified ++ * ++ * @param level the level of enchantment ++ * @param entityCategory the category of entity ++ * @return the damage increase ++ */ ++ public abstract float getDamageIncrease(int level, @NotNull org.bukkit.entity.EntityCategory entityCategory); ++ ++ /** ++ * Gets the equipment slots where this enchantment is considered "active". ++ * ++ * @return the equipment slots ++ */ ++ @NotNull ++ public abstract java.util.Set getActiveSlots(); + // Paper end + + @Override +diff --git a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java +index 4d5f0837bd0e02a30c943d8969fb6b13452322e0..ca097db904db96e81c0ea4b06b445a13e9333cfe 100644 +--- a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java ++++ b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java +@@ -69,5 +69,32 @@ public class EnchantmentWrapper extends Enchantment { + public net.kyori.adventure.text.Component displayName(int level) { + return getEnchantment().displayName(level); + } ++ ++ @Override ++ public boolean isTradeable() { ++ return getEnchantment().isTradeable(); ++ } ++ ++ @Override ++ public boolean isDiscoverable() { ++ return getEnchantment().isDiscoverable(); ++ } ++ ++ @NotNull ++ @Override ++ public io.papermc.paper.enchantments.EnchantmentRarity getRarity() { ++ return getEnchantment().getRarity(); ++ } ++ ++ @Override ++ public float getDamageIncrease(int level, @NotNull org.bukkit.entity.EntityCategory entityCategory) { ++ return getEnchantment().getDamageIncrease(level, entityCategory); ++ } ++ ++ @NotNull ++ @Override ++ public java.util.Set getActiveSlots() { ++ return getEnchantment().getActiveSlots(); ++ } + // Paper end + } diff --git a/patches/api-unmapped/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/api-unmapped/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch new file mode 100644 index 0000000000..c4cd74cdbe --- /dev/null +++ b/patches/api-unmapped/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch @@ -0,0 +1,142 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Tue, 18 May 2021 14:42:26 -0700 +Subject: [PATCH] Add command line option to load extra plugin jars not in the + plugins folder + +ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar + +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index 26685f59b235ea5b4c4fb7ae21acb5149edaa2b3..ca866876f2f35a1c41eb009064412423fa09e441 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -60,6 +60,7 @@ public final class SimplePluginManager implements PluginManager { + private final Map> permSubs = new HashMap>(); + private final Map> defSubs = new HashMap>(); + private boolean useTimings = false; ++ private File pluginsDirectory; public @Nullable File pluginsDirectory() { return this.pluginsDirectory; } // Paper + + public SimplePluginManager(@NotNull Server instance, @NotNull SimpleCommandMap commandMap) { + server = instance; +@@ -115,6 +116,13 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Plugin[] loadPlugins(@NotNull File directory) { ++ // Paper start - extra jars ++ return this.loadPlugins(directory, java.util.Collections.emptyList()); ++ } ++ @NotNull ++ public Plugin[] loadPlugins(final @NotNull File directory, final @NotNull List extraPluginJars) { ++ this.pluginsDirectory = directory; ++ // Paper end + Validate.notNull(directory, "Directory cannot be null"); + Validate.isTrue(directory.isDirectory(), "Directory must be a directory"); + +@@ -132,7 +140,11 @@ public final class SimplePluginManager implements PluginManager { + Map> softDependencies = new HashMap>(); + + // This is where it figures out all possible plugins +- for (File file : directory.listFiles()) { ++ // Paper start - extra jars ++ final List pluginJars = new ArrayList<>(java.util.Arrays.asList(directory.listFiles())); ++ pluginJars.addAll(extraPluginJars); ++ for (File file : pluginJars) { ++ // Paper end + PluginLoader loader = null; + for (Pattern filter : filters) { + Matcher match = filter.matcher(file.getName()); +@@ -148,14 +160,14 @@ public final class SimplePluginManager implements PluginManager { + description = loader.getPluginDescription(file); + String name = description.getName(); + if (name.equalsIgnoreCase("bukkit") || name.equalsIgnoreCase("minecraft") || name.equalsIgnoreCase("mojang")) { +- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "': Restricted Name"); ++ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "': Restricted Name"); // Paper + continue; + } else if (description.rawName.indexOf(' ') != -1) { +- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "': uses the space-character (0x20) in its name"); ++ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "': uses the space-character (0x20) in its name"); // Paper + continue; + } + } catch (InvalidDescriptionException ex) { +- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", ex); ++ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'", ex); // Paper + continue; + } + +@@ -166,7 +178,7 @@ public final class SimplePluginManager implements PluginManager { + description.getName(), + file.getPath(), + replacedFile.getPath(), +- directory.getPath() ++ file.getParentFile().getPath() // Paper + )); + } + +@@ -187,7 +199,7 @@ public final class SimplePluginManager implements PluginManager { + file.getPath(), + provided, + pluginFile.getPath(), +- directory.getPath() ++ file.getParentFile().getPath() // Paper + )); + } else { + String replacedPlugin = pluginsProvided.put(provided, description.getName()); +@@ -269,7 +281,7 @@ public final class SimplePluginManager implements PluginManager { + + server.getLogger().log( + Level.SEVERE, +- "Could not load '" + entry.getValue().getPath() + "' in folder '" + directory.getPath() + "'", ++ "Could not load '" + entry.getValue().getPath() + "' in folder '" + entry.getValue().getParentFile().getPath() + "'", // Paper + new UnknownDependencyException("Unknown dependency " + dependency + ". Please download and install " + dependency + " to run this plugin.")); + break; + } +@@ -308,11 +320,11 @@ public final class SimplePluginManager implements PluginManager { + loadedPlugins.add(loadedPlugin.getName()); + loadedPlugins.addAll(loadedPlugin.getDescription().getProvides()); + } else { +- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'"); ++ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'"); // Paper + } + continue; + } catch (InvalidPluginException ex) { +- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", ex); ++ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'", ex); // Paper + } + } + } +@@ -339,11 +351,11 @@ public final class SimplePluginManager implements PluginManager { + loadedPlugins.add(loadedPlugin.getName()); + loadedPlugins.addAll(loadedPlugin.getDescription().getProvides()); + } else { +- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'"); ++ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'"); // Paper + } + break; + } catch (InvalidPluginException ex) { +- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", ex); ++ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'", ex); // Paper + } + } + } +@@ -356,7 +368,7 @@ public final class SimplePluginManager implements PluginManager { + while (failedPluginIterator.hasNext()) { + File file = failedPluginIterator.next(); + failedPluginIterator.remove(); +- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "': circular dependency detected"); ++ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "': circular dependency detected"); // Paper + } + } + } +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index 31793f46e5623729dfb4048e901f274082f57826..d3812d8cd195017841ee08ffbc53a5748fcc74ec 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -94,7 +94,7 @@ public final class JavaPluginLoader implements PluginLoader { + throw new InvalidPluginException(ex); + } + +- final File parentFile = file.getParentFile(); ++ final File parentFile = ((SimplePluginManager) this.server.getPluginManager()).pluginsDirectory(); // Paper + final File dataFolder = new File(parentFile, description.getName()); + @SuppressWarnings("deprecation") + final File oldDataFolder = new File(parentFile, description.getRawName()); diff --git a/patches/api-unmapped/0305-List-all-missing-hard-depends-not-just-first.patch b/patches/api-unmapped/0305-List-all-missing-hard-depends-not-just-first.patch new file mode 100644 index 0000000000..bbbab43d60 --- /dev/null +++ b/patches/api-unmapped/0305-List-all-missing-hard-depends-not-just-first.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 18 May 2021 10:38:10 -0700 +Subject: [PATCH] List all missing hard depends not just first + + +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index ca866876f2f35a1c41eb009064412423fa09e441..d1c35e4cf778070f8d18bbe0af8d423334c6dfbf 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -264,6 +264,7 @@ public final class SimplePluginManager implements PluginManager { + + if (dependencies.containsKey(plugin)) { + Iterator dependencyIterator = dependencies.get(plugin).iterator(); ++ final Set missingHardDependencies = new HashSet<>(dependencies.get(plugin).size()); // Paper - list all missing hard depends + + while (dependencyIterator.hasNext()) { + String dependency = dependencyIterator.next(); +@@ -274,6 +275,12 @@ public final class SimplePluginManager implements PluginManager { + + // We have a dependency not found + } else if (!plugins.containsKey(dependency) && !pluginsProvided.containsKey(dependency)) { ++ // Paper start ++ missingHardDependencies.add(dependency); ++ } ++ } ++ if (!missingHardDependencies.isEmpty()) { ++ // Paper end + missingDependency = false; + pluginIterator.remove(); + softDependencies.remove(plugin); +@@ -282,9 +289,7 @@ public final class SimplePluginManager implements PluginManager { + server.getLogger().log( + Level.SEVERE, + "Could not load '" + entry.getValue().getPath() + "' in folder '" + entry.getValue().getParentFile().getPath() + "'", // Paper +- new UnknownDependencyException("Unknown dependency " + dependency + ". Please download and install " + dependency + " to run this plugin.")); +- break; +- } ++ new UnknownDependencyException(missingHardDependencies, plugin)); // Paper + } + + if (dependencies.containsKey(plugin) && dependencies.get(plugin).isEmpty()) { +diff --git a/src/main/java/org/bukkit/plugin/UnknownDependencyException.java b/src/main/java/org/bukkit/plugin/UnknownDependencyException.java +index a80251eff75430863b37db1c131e22593f3fcd5e..7b2e607a21f1173d98ee84581881411176380625 100644 +--- a/src/main/java/org/bukkit/plugin/UnknownDependencyException.java ++++ b/src/main/java/org/bukkit/plugin/UnknownDependencyException.java +@@ -26,6 +26,19 @@ public class UnknownDependencyException extends RuntimeException { + super(message); + } + ++ // Paper start ++ /** ++ * Create a new {@link UnknownDependencyException} with a message informing ++ * about which dependencies are missing for what plugin. ++ * ++ * @param missingDependencies missing dependencies ++ * @param pluginName plugin which is missing said dependencies ++ */ ++ public UnknownDependencyException(final @org.jetbrains.annotations.NotNull java.util.Collection missingDependencies, final @org.jetbrains.annotations.NotNull String pluginName) { ++ this("Unknown/missing dependency plugins: [" + String.join(", ", missingDependencies) + "]. Please download and install these plugins to run '" + pluginName + "'."); ++ } ++ // Paper end ++ + /** + * Constructs a new UnknownDependencyException based on the given + * Exception +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index d3812d8cd195017841ee08ffbc53a5748fcc74ec..b622cedeeee017f042bcf92485d81832030a8030 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -132,13 +132,19 @@ public final class JavaPluginLoader implements PluginLoader { + )); + } + ++ Set missingHardDependencies = new HashSet<>(description.getDepend().size()); // Paper - list all missing hard depends + for (final String pluginName : description.getDepend()) { + Plugin current = server.getPluginManager().getPlugin(pluginName); + + if (current == null) { +- throw new UnknownDependencyException("Unknown dependency " + pluginName + ". Please download and install " + pluginName + " to run this plugin."); ++ missingHardDependencies.add(pluginName); // Paper - list all missing hard depends + } + } ++ // Paper start - list all missing hard depends ++ if (!missingHardDependencies.isEmpty()) { ++ throw new UnknownDependencyException(missingHardDependencies, description.getFullName()); ++ } ++ // Paper end + + server.getUnsafe().checkSupported(description); + diff --git a/patches/api-unmapped/0306-Add-Mob-lookAt-API.patch b/patches/api-unmapped/0306-Add-Mob-lookAt-API.patch new file mode 100644 index 0000000000..b1a75288cb --- /dev/null +++ b/patches/api-unmapped/0306-Add-Mob-lookAt-API.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 14 May 2021 13:42:06 -0500 +Subject: [PATCH] Add Mob#lookAt API + + +diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java +index d726453c041a980576312b6bee96a07837f37974..7d4ce660adb21e579e564796568945ee20f0ca59 100644 +--- a/src/main/java/org/bukkit/entity/Mob.java ++++ b/src/main/java/org/bukkit/entity/Mob.java +@@ -23,6 +23,88 @@ public interface Mob extends LivingEntity, Lootable { + * @return True if mob is exposed to daylight + */ + boolean isInDaylight(); ++ ++ /** ++ * Instruct this Mob to look at a specific Location ++ *

    ++ * Useful when implementing custom mob goals ++ * ++ * @param location location to look at ++ */ ++ void lookAt(@NotNull org.bukkit.Location location); ++ ++ /** ++ * Instruct this Mob to look at a specific Location ++ *

    ++ * Useful when implementing custom mob goals ++ * ++ * @param location location to look at ++ * @param headRotationSpeed head rotation speed ++ * @param maxHeadPitch max head pitch rotation ++ */ ++ void lookAt(@NotNull org.bukkit.Location location, float headRotationSpeed, float maxHeadPitch); ++ ++ /** ++ * Instruct this Mob to look at a specific Entity ++ *

    ++ * If a LivingEntity, look at eye location ++ *

    ++ * Useful when implementing custom mob goals ++ * ++ * @param entity entity to look at ++ */ ++ void lookAt(@NotNull Entity entity); ++ ++ /** ++ * Instruct this Mob to look at a specific Entity ++ *

    ++ * If a LivingEntity, look at eye location ++ *

    ++ * Useful when implementing custom mob goals ++ * ++ * @param entity entity to look at ++ * @param headRotationSpeed head rotation speed ++ * @param maxHeadPitch max head pitch rotation ++ */ ++ void lookAt(@NotNull Entity entity, float headRotationSpeed, float maxHeadPitch); ++ ++ /** ++ * Instruct this Mob to look at a specific position ++ *

    ++ * Useful when implementing custom mob goals ++ * ++ * @param x x coordinate ++ * @param y y coordinate ++ * @param z z coordinate ++ */ ++ void lookAt(double x, double y, double z); ++ ++ /** ++ * Instruct this Mob to look at a specific position ++ *

    ++ * Useful when implementing custom mob goals ++ * ++ * @param x x coordinate ++ * @param y y coordinate ++ * @param z z coordinate ++ * @param headRotationSpeed head rotation speed ++ * @param maxHeadPitch max head pitch rotation ++ */ ++ void lookAt(double x, double y, double z, float headRotationSpeed, float maxHeadPitch); ++ ++ /** ++ * Gets the head rotation speed ++ * ++ * @return the head rotation speed ++ */ ++ int getHeadRotationSpeed(); ++ ++ /** ++ * Gets the max head pitch rotation ++ * ++ * @return the max head pitch rotation ++ */ ++ int getMaxHeadPitch(); + // Paper end + + /** diff --git a/patches/api-unmapped/0307-ItemStack-editMeta.patch b/patches/api-unmapped/0307-ItemStack-editMeta.patch new file mode 100644 index 0000000000..d9b90f5c32 --- /dev/null +++ b/patches/api-unmapped/0307-ItemStack-editMeta.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Riley Park +Date: Sun, 23 May 2021 05:04:28 -0700 +Subject: [PATCH] ItemStack#editMeta + + +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index 1bd9f7582bb907ff178fd110fdc92834885d1d78..a7909406e9d54c1ab4789b984ed6b1da50837fce 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -542,6 +542,31 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + return result.ensureServerConversions(); // Paper + } + ++ // Paper start ++ /** ++ * Edits the {@link ItemMeta} of this stack. ++ *

    ++ * The {@link java.util.function.Consumer} must only interact ++ * with this stack's {@link ItemMeta} through the provided {@link ItemMeta} instance. ++ * Calling this method or any other meta-related method of the {@link ItemStack} class ++ * (such as {@link #getItemMeta()}, {@link #addItemFlags(ItemFlag...)}, {@link #lore()}, etc.) ++ * from inside the consumer is disallowed and will produce undefined results or exceptions. ++ *

    ++ * ++ * @param consumer the meta consumer ++ * @return {@code true} if the edit was successful, {@code false} otherwise ++ */ ++ public boolean editMeta(final @NotNull java.util.function.Consumer consumer) { ++ final ItemMeta meta = this.getItemMeta(); ++ if (meta != null) { ++ consumer.accept(meta); ++ this.setItemMeta(meta); ++ return true; ++ } ++ return false; ++ } ++ // Paper end ++ + /** + * Get a copy of this ItemStack's {@link ItemMeta}. + * diff --git a/patches/api-unmapped/0308-Add-EntityInsideBlockEvent.patch b/patches/api-unmapped/0308-Add-EntityInsideBlockEvent.patch new file mode 100644 index 0000000000..26c188e7a0 --- /dev/null +++ b/patches/api-unmapped/0308-Add-EntityInsideBlockEvent.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 8 May 2021 18:02:06 -0700 +Subject: [PATCH] Add EntityInsideBlockEvent + + +diff --git a/src/main/java/io/papermc/paper/event/entity/EntityInsideBlockEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityInsideBlockEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..94e8b6f6501c92711bd0bc9ee0f67e28f85a605f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/EntityInsideBlockEvent.java +@@ -0,0 +1,80 @@ ++package io.papermc.paper.event.entity; ++ ++import org.bukkit.block.Block; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when an entity enters the hitbox of a block. ++ * Only called for blocks that react when an entity is inside. ++ * If cancelled, any action that would have resulted from that entity ++ * being in the block will not happen (such as extinguishing an entity in a cauldron). ++ *

    ++ * Blocks this is currently called for: ++ *

      ++ *
    • Bubble column
    • ++ *
    • Buttons
    • ++ *
    • Cactus
    • ++ *
    • Campfire
    • ++ *
    • Cauldron
    • ++ *
    • Crops
    • ++ *
    • Ender Portal
    • ++ *
    • Fires
    • ++ *
    • Honey
    • ++ *
    • Hopper
    • ++ *
    • Detector rails
    • ++ *
    • Nether portals
    • ++ *
    • Pressure plates
    • ++ *
    • Sweet berry bush
    • ++ *
    • Tripwire
    • ++ *
    • Waterlily
    • ++ *
    • Web
    • ++ *
    • Wither rose
    • ++ *
    ++ */ ++public class EntityInsideBlockEvent extends EntityEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Block block; ++ private boolean cancelled; ++ ++ public EntityInsideBlockEvent(@NotNull Entity entity, @NotNull Block block) { ++ super(entity); ++ this.block = block; ++ } ++ ++ /** ++ * Gets the block. ++ * ++ * @return the block ++ */ ++ @NotNull ++ public Block getBlock() { ++ return block; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api-unmapped/0309-Attributes-API-for-item-defaults.patch b/patches/api-unmapped/0309-Attributes-API-for-item-defaults.patch new file mode 100644 index 0000000000..fa1b8ce93a --- /dev/null +++ b/patches/api-unmapped/0309-Attributes-API-for-item-defaults.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 8 May 2021 15:02:00 -0700 +Subject: [PATCH] Attributes API for item defaults + + +diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java +index 07b8b913434bb575df8670230d693b2d4cec2571..397591da25fbb0e4d3012431df70d661d9bc9188 100644 +--- a/src/main/java/org/bukkit/Material.java ++++ b/src/main/java/org/bukkit/Material.java +@@ -4013,6 +4013,19 @@ public enum Material implements Keyed { + public io.papermc.paper.inventory.ItemRarity getItemRarity() { + return Bukkit.getUnsafe().getItemRarity(this); + } ++ ++ /** ++ * Returns an immutable multimap of attributes for the slot. ++ * {@link #isItem()} must be true for this material. ++ * ++ * @param equipmentSlot the slot to get the attributes for ++ * @throws IllegalArgumentException if {@link #isItem()} is false ++ * @return an immutable multimap of attributes ++ */ ++ @NotNull ++ public com.google.common.collect.Multimap getItemAttributes(@NotNull EquipmentSlot equipmentSlot) { ++ return Bukkit.getUnsafe().getItemAttributes(this, equipmentSlot); ++ } + // Paper end + + /** +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index e504567cf755557be8511f2c93c171572b78e722..379acee1b5f2d06e6a96f3444783f4a29ca24095 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -165,6 +165,18 @@ public interface UnsafeValues { + */ + public boolean isValidRepairItemStack(@org.jetbrains.annotations.NotNull ItemStack itemToBeRepaired, @org.jetbrains.annotations.NotNull ItemStack repairMaterial); + ++ /** ++ * Returns an immutable multimap of attributes for the material and slot. ++ * {@link Material#isItem()} must be true for this material. ++ * ++ * @param material the material ++ * @param equipmentSlot the slot to get the attributes for ++ * @throws IllegalArgumentException if {@link Material#isItem()} is false ++ * @return an immutable multimap of attributes ++ */ ++ @org.jetbrains.annotations.NotNull ++ public com.google.common.collect.Multimap getItemAttributes(@org.jetbrains.annotations.NotNull Material material, @org.jetbrains.annotations.NotNull org.bukkit.inventory.EquipmentSlot equipmentSlot); ++ + /** + * Returns the server's protocol version. + * diff --git a/patches/api-unmapped/0310-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/api-unmapped/0310-Add-cause-to-Weather-ThunderChangeEvents.patch new file mode 100644 index 0000000000..8e5d45d87b --- /dev/null +++ b/patches/api-unmapped/0310-Add-cause-to-Weather-ThunderChangeEvents.patch @@ -0,0 +1,104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 2 Dec 2020 18:25:31 -0800 +Subject: [PATCH] Add cause to Weather/ThunderChangeEvents + + +diff --git a/src/main/java/org/bukkit/event/weather/ThunderChangeEvent.java b/src/main/java/org/bukkit/event/weather/ThunderChangeEvent.java +index 6cdf83476b4e366bed79960e3706bea5ebe56788..032395c7114b6d757acf1918ce2b014870e85fcd 100644 +--- a/src/main/java/org/bukkit/event/weather/ThunderChangeEvent.java ++++ b/src/main/java/org/bukkit/event/weather/ThunderChangeEvent.java +@@ -12,10 +12,20 @@ public class ThunderChangeEvent extends WeatherEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private boolean canceled; + private final boolean to; ++ // Paper start ++ private final Cause cause; + ++ public ThunderChangeEvent(@NotNull final World world, final boolean to, @NotNull final Cause cause) { ++ super(world); ++ this.to = to; ++ this.cause = cause; ++ } ++ ++ @Deprecated // Paper end + public ThunderChangeEvent(@NotNull final World world, final boolean to) { + super(world); + this.to = to; ++ this.cause = Cause.UNKNOWN; // Paper + } + + @Override +@@ -47,4 +57,23 @@ public class ThunderChangeEvent extends WeatherEvent implements Cancellable { + public static HandlerList getHandlerList() { + return handlers; + } ++ // Paper start ++ /** ++ * Gets the cause of the weather change. ++ * ++ * @return the weather change cause ++ */ ++ @NotNull ++ public Cause getCause() { ++ return this.cause; ++ } ++ ++ public enum Cause { ++ COMMAND, ++ NATURAL, ++ SLEEP, ++ PLUGIN, ++ UNKNOWN ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/event/weather/WeatherChangeEvent.java b/src/main/java/org/bukkit/event/weather/WeatherChangeEvent.java +index d562d87e7418641e52f4dae44f573eaa31add44a..dabd390b84354c14c269c03cbed2006014d004b2 100644 +--- a/src/main/java/org/bukkit/event/weather/WeatherChangeEvent.java ++++ b/src/main/java/org/bukkit/event/weather/WeatherChangeEvent.java +@@ -12,10 +12,20 @@ public class WeatherChangeEvent extends WeatherEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private boolean canceled; + private final boolean to; ++ // Paper start ++ private final Cause cause; + ++ public WeatherChangeEvent(@NotNull final World world, final boolean to, @NotNull Cause cause) { ++ super(world); ++ this.to = to; ++ this.cause = cause; ++ } ++ ++ @Deprecated // Paper end + public WeatherChangeEvent(@NotNull final World world, final boolean to) { + super(world); + this.to = to; ++ this.cause = Cause.UNKNOWN; // Paper + } + + @Override +@@ -47,4 +57,23 @@ public class WeatherChangeEvent extends WeatherEvent implements Cancellable { + public static HandlerList getHandlerList() { + return handlers; + } ++ // Paper start ++ /** ++ * Gets the cause of the weather change. ++ * ++ * @return the weather change cause ++ */ ++ @NotNull ++ public Cause getCause() { ++ return cause; ++ } ++ ++ public enum Cause { ++ COMMAND, ++ NATURAL, ++ SLEEP, ++ PLUGIN, ++ UNKNOWN ++ } ++ // Paper end + } diff --git a/patches/api-unmapped/0311-More-Lidded-Block-API.patch b/patches/api-unmapped/0311-More-Lidded-Block-API.patch new file mode 100644 index 0000000000..ca6b5ed744 --- /dev/null +++ b/patches/api-unmapped/0311-More-Lidded-Block-API.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: LemonCaramel +Date: Sun, 23 May 2021 17:49:31 +0900 +Subject: [PATCH] More Lidded Block API + + +diff --git a/src/main/java/org/bukkit/block/EnderChest.java b/src/main/java/org/bukkit/block/EnderChest.java +index 17843e338f2cbccfa9342b420c62d0e4d6eec31d..ebae4e660244df15bf93a78d41f8c0c5c7083b27 100644 +--- a/src/main/java/org/bukkit/block/EnderChest.java ++++ b/src/main/java/org/bukkit/block/EnderChest.java +@@ -3,4 +3,4 @@ package org.bukkit.block; + /** + * Represents a captured state of an ender chest. + */ +-public interface EnderChest extends TileState { } ++public interface EnderChest extends TileState, Lidded { } // Paper - More Lidded Block API +diff --git a/src/main/java/org/bukkit/block/Lidded.java b/src/main/java/org/bukkit/block/Lidded.java +index 9da2566e02e63be1a0188deaa27b841fa61688ea..30c7df0021df44a411e50636d906d4a1d30fd927 100644 +--- a/src/main/java/org/bukkit/block/Lidded.java ++++ b/src/main/java/org/bukkit/block/Lidded.java +@@ -13,4 +13,13 @@ public interface Lidded { + * viewing this block. + */ + void close(); ++ ++ // Paper start - More Lidded Block API ++ /** ++ * Checks if the block's animation state. ++ * ++ * @return true if the block's animation state is set to open. ++ */ ++ boolean isOpen(); ++ // Paper end - More Lidded Block API + } diff --git a/patches/api-unmapped/0312-Add-PlayerKickEvent-causes.patch b/patches/api-unmapped/0312-Add-PlayerKickEvent-causes.patch new file mode 100644 index 0000000000..b3cfb136d3 --- /dev/null +++ b/patches/api-unmapped/0312-Add-PlayerKickEvent-causes.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 20:30:34 -0700 +Subject: [PATCH] Add PlayerKickEvent causes + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 34b51466ffb281b05f531b3f7deda245ae7fd96a..a4b236d75e77176a163094edd31f81725bbf4eca 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -237,6 +237,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @param message kick message + */ + void kick(final @Nullable net.kyori.adventure.text.Component message); ++ ++ /** ++ * Kicks player with custom kick message and cause. ++ * ++ * @param message kick message ++ * @param cause kick cause ++ */ ++ void kick(final @Nullable Component message, @NotNull org.bukkit.event.player.PlayerKickEvent.Cause cause); + // Paper end + + /** +diff --git a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java +index 5c0efe74237dbe6803ce023fde99682ff70d1a92..02914c0743852e9e4fd2c085fd4b735e74d8875b 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java +@@ -12,6 +12,7 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private net.kyori.adventure.text.Component leaveMessage; // Paper + private net.kyori.adventure.text.Component kickReason; // Paper ++ private final Cause cause; // Paper + private Boolean cancel; + + @Deprecated // Paper +@@ -19,14 +20,25 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { + super(playerKicked); + this.kickReason = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickReason); // Paper + this.leaveMessage = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(leaveMessage); // Paper ++ this.cause = Cause.UNKNOWN; // Paper + this.cancel = false; + } + // Paper start ++ @Deprecated + public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final net.kyori.adventure.text.Component kickReason, @NotNull final net.kyori.adventure.text.Component leaveMessage) { + super(playerKicked); + this.kickReason = kickReason; + this.leaveMessage = leaveMessage; + this.cancel = false; ++ this.cause = Cause.UNKNOWN; ++ } ++ ++ public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final net.kyori.adventure.text.Component kickReason, @NotNull final net.kyori.adventure.text.Component leaveMessage, @NotNull final Cause cause) { ++ super(playerKicked); ++ this.kickReason = kickReason; ++ this.leaveMessage = leaveMessage; ++ this.cancel = false; ++ this.cause = cause; + } + + /** +@@ -132,4 +144,63 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { + public static HandlerList getHandlerList() { + return handlers; + } ++ // Paper start ++ /** ++ * Gets the cause of this kick ++ * ++ * @return ++ */ ++ @NotNull ++ public org.bukkit.event.player.PlayerKickEvent.Cause getCause() { ++ return cause; ++ } ++ ++ public enum Cause { ++ ++ PLUGIN, ++ ++ WHITELIST, ++ ++ BANNED, ++ ++ IP_BANNED, ++ ++ KICK_COMMAND, ++ ++ FLYING_PLAYER, ++ ++ FLYING_VEHICLE, ++ ++ TIMEOUT, ++ ++ IDLING, ++ ++ INVALID_VEHICLE_MOVEMENT, ++ ++ INVALID_PLAYER_MOVEMENT, ++ ++ INVALID_ENTITY_ATTACKED, ++ ++ INVALID_PAYLOAD, ++ ++ SPAM, ++ ++ ILLEGAL_ACTION, ++ ++ ILLEGAL_CHARACTERS, ++ ++ SELF_INTERACTION, ++ ++ DUPLICATE_LOGIN, ++ ++ /** ++ * Spigot's restart command ++ */ ++ RESTART_COMMAND, ++ /** ++ * Fallback cause ++ */ ++ UNKNOWN, ++ } ++ // Paper end + } diff --git a/patches/api-unmapped/0313-Add-PufferFishStateChangeEvent.patch b/patches/api-unmapped/0313-Add-PufferFishStateChangeEvent.patch new file mode 100644 index 0000000000..c3014534d3 --- /dev/null +++ b/patches/api-unmapped/0313-Add-PufferFishStateChangeEvent.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Mon, 10 May 2021 16:58:38 +0100 +Subject: [PATCH] Add PufferFishStateChangeEvent + + +diff --git a/src/main/java/io/papermc/paper/event/entity/PufferFishStateChangeEvent.java b/src/main/java/io/papermc/paper/event/entity/PufferFishStateChangeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3585457b21aca2a2f1779868a0fa91f8011ad3c9 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/PufferFishStateChangeEvent.java +@@ -0,0 +1,80 @@ ++package io.papermc.paper.event.entity; ++ ++import org.bukkit.entity.PufferFish; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called just before a {@link PufferFish} inflates or deflates. ++ */ ++public class PufferFishStateChangeEvent extends EntityEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private boolean cancelled; ++ private int newPuffState; ++ ++ public PufferFishStateChangeEvent(@NotNull PufferFish entity, int newPuffState) { ++ super(entity); ++ this.newPuffState = newPuffState; ++ } ++ ++ @NotNull ++ @Override ++ public PufferFish getEntity() { ++ return (PufferFish) entity; ++ } ++ ++ /** ++ * Get the new puff state of the {@link PufferFish}. ++ *

    ++ * This is what the {@link PufferFish}'s new puff state will be after this event if it isn't cancelled.
    ++ * Refer to {@link PufferFish#getPuffState()} to get the current puff state. ++ * @return The new puff state, 0 being not inflated, 1 being slightly inflated and 2 being fully inflated ++ */ ++ public int getNewPuffState() { ++ return this.newPuffState; ++ } ++ ++ /** ++ * Get if the {@link PufferFish} is going to inflate. ++ * @return If its going to inflate ++ */ ++ public boolean isInflating() { ++ return getNewPuffState() > getEntity().getPuffState(); ++ } ++ ++ /** ++ * Get if the {@link PufferFish} is going to deflate. ++ * @return If its going to deflate ++ */ ++ public boolean isDeflating() { ++ return getNewPuffState() < getEntity().getPuffState(); ++ } ++ ++ /** ++ * Set whether or not to cancel the {@link PufferFish} (in/de)flating. ++ * ++ * @param cancel true if you wish to cancel the (in/de)flation ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0314-Add-BellRevealRaiderEvent.patch b/patches/api-unmapped/0314-Add-BellRevealRaiderEvent.patch new file mode 100644 index 0000000000..8b0ee3e5b4 --- /dev/null +++ b/patches/api-unmapped/0314-Add-BellRevealRaiderEvent.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Wed, 26 May 2021 17:08:57 -0400 +Subject: [PATCH] Add BellRevealRaiderEvent + + +diff --git a/src/main/java/io/papermc/paper/event/block/BellRevealRaiderEvent.java b/src/main/java/io/papermc/paper/event/block/BellRevealRaiderEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..03dae5be7dba8ab550d03f365c05af4ba73e4224 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/BellRevealRaiderEvent.java +@@ -0,0 +1,58 @@ ++package io.papermc.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Raider; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a {@link org.bukkit.entity.Raider} is revealed by a bell. ++ */ ++public class BellRevealRaiderEvent extends BlockEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ ++ private boolean cancelled = false; ++ private final Raider raider; ++ ++ public BellRevealRaiderEvent(@NotNull Block theBlock, @NotNull Entity raider) { ++ super(theBlock); ++ this.raider = (Raider) raider; ++ } ++ ++ /** ++ * Gets the raider that the bell revealed. ++ * ++ * @return The raider ++ */ ++ @NotNull ++ public Raider getEntity() { ++ return raider; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * {@inheritDoc} ++ *

    ++ * This does not cancel the particle effects shown on the bell, only the entity. ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ public static @NotNull HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0315-Add-ElderGuardianAppearanceEvent.patch b/patches/api-unmapped/0315-Add-ElderGuardianAppearanceEvent.patch new file mode 100644 index 0000000000..8d925d10ac --- /dev/null +++ b/patches/api-unmapped/0315-Add-ElderGuardianAppearanceEvent.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Fri, 19 Mar 2021 23:39:21 -0400 +Subject: [PATCH] Add ElderGuardianAppearanceEvent + + +diff --git a/src/main/java/io/papermc/paper/event/entity/ElderGuardianAppearanceEvent.java b/src/main/java/io/papermc/paper/event/entity/ElderGuardianAppearanceEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4cd551c8311ff8f7321ed2dc6a4efc87162dadfe +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/ElderGuardianAppearanceEvent.java +@@ -0,0 +1,69 @@ ++package io.papermc.paper.event.entity; ++ ++import org.bukkit.entity.ElderGuardian; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.Collections; ++import java.util.List; ++ ++/** ++ * Is called when an {@link org.bukkit.entity.ElderGuardian} appears in front of a {@link org.bukkit.entity.Player}. ++ */ ++public class ElderGuardianAppearanceEvent extends EntityEvent implements Cancellable { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ private boolean cancelled; ++ private final Player affectedPlayer; ++ ++ public ElderGuardianAppearanceEvent(@NotNull Entity what, @NotNull Player affectedPlayer) { ++ super(what); ++ this.affectedPlayer = affectedPlayer; ++ } ++ ++ /** ++ * Get the player affected by the guardian appearance. ++ * ++ * @return Player affected by the appearance ++ */ ++ @NotNull ++ public Player getAffectedPlayer() { ++ return affectedPlayer; ++ } ++ ++ /** ++ * The elder guardian playing the effect. ++ * ++ * @return The elder guardian ++ */ ++ @NotNull ++ public ElderGuardian getEntity() { ++ return (ElderGuardian) entity; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api-unmapped/0316-Add-more-line-of-sight-methods.patch b/patches/api-unmapped/0316-Add-more-line-of-sight-methods.patch new file mode 100644 index 0000000000..be49c1cc25 --- /dev/null +++ b/patches/api-unmapped/0316-Add-more-line-of-sight-methods.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TwoLeggedCat <80929284+TwoLeggedCat@users.noreply.github.com> +Date: Sat, 29 May 2021 14:33:18 -0500 +Subject: [PATCH] Add more line of sight methods + + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index a1496fe00a2d5ba6c1af054d4327f868b2cd7344..f66ec2dfdc64871f8b752bf44086954300804f08 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -76,6 +76,14 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + */ + @NotNull + io.papermc.paper.world.MoonPhase getMoonPhase(); ++ ++ /** ++ * Tell whether a line of sight exists between the given locations ++ * @param from Location to start at ++ * @param to target Location ++ * @return whether a line of sight exists between {@code from} and {@code to} ++ */ ++ public boolean lineOfSightExists(@NotNull Location from, @NotNull Location to); + // Paper end + + /** +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index b6de41e3e718fa5d1b82c6f68b153e60a81265e7..ccb81ceee74fff50ec3ed88ae0a41f790c40ae87 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -483,6 +483,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + */ + public boolean hasLineOfSight(@NotNull Entity other); + ++ // Paper start ++ /** ++ * Checks whether the living entity has block line of sight to the given block. ++ *

    ++ * This uses the same algorithm that hostile mobs use to find the closest ++ * player. ++ * ++ * @param location the location to determine line of sight to ++ * @return true if there is a line of sight, false if not ++ */ ++ public boolean hasLineOfSight(@NotNull Location location); ++ // Paper end ++ + /** + * Returns if the living entity despawns when away from players or not. + *

    diff --git a/patches/api/0001-Convert-project-to-Gradle.patch b/patches/api/0001-Convert-project-to-Gradle.patch new file mode 100644 index 0000000000..d34ab3ef3c --- /dev/null +++ b/patches/api/0001-Convert-project-to-Gradle.patch @@ -0,0 +1,76 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Thu, 10 Dec 2020 20:50:33 -0800 +Subject: [PATCH] Convert project to Gradle + + +diff --git a/.gitignore b/.gitignore +index e431e3435737e28394d81b56568a08b3c3148b9b..c484aff2c192bf42059b5689327909e4af654401 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -1,3 +1,5 @@ ++.gradle/ ++ + # Eclipse stuff + /.classpath + /.project +diff --git a/build.gradle.kts b/build.gradle.kts +new file mode 100644 +index 0000000000000000000000000000000000000000..a0f1c1d1ac63fdcce942922ffe68a8d44c712513 +--- /dev/null ++++ b/build.gradle.kts +@@ -0,0 +1,54 @@ ++plugins { ++ `java-library` ++ checkstyle ++} ++ ++java { ++ withSourcesJar() ++ withJavadocJar() ++} ++ ++dependencies { ++ // api dependencies are listed transitively to API consumers ++ api("commons-lang:commons-lang:2.6") ++ api("com.google.guava:guava:21.0") ++ api("com.google.code.gson:gson:2.8.0") ++ api("net.md-5:bungeecord-chat:1.16-R0.4") ++ api("org.yaml:snakeyaml:1.29") ++ ++ compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") ++ compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") ++ compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") ++ ++ val annotations = "org.jetbrains:annotations-java5:21.0.1" ++ compileOnly(annotations) ++ testCompileOnly(annotations) ++ ++ testImplementation("junit:junit:4.13.1") ++ testImplementation("org.hamcrest:hamcrest-library:1.3") ++ testImplementation("org.ow2.asm:asm-tree:9.1") ++ ++ checkstyle("com.puppycrawl.tools:checkstyle:8.39") ++} ++ ++tasks.jar { ++ manifest { ++ attributes += mapOf( ++ "Automatic-Module-Name" to "org.bukkit" ++ ) ++ } ++} ++ ++tasks.withType().configureEach { ++ (options as StandardJavadocDocletOptions).links( ++ "https://guava.dev/releases/21.0/api/docs/", ++ "https://javadoc.io/doc/org.yaml/snakeyaml/1.27/", ++ "https://javadoc.io/doc/org.jetbrains/annotations-java5/20.1.0/", ++ "https://javadoc.io/doc/net.md-5/bungeecord-chat/1.16-R0.4/" ++ ) ++} ++ ++checkstyle { ++ configFile = file("checkstyle.xml") ++ sourceSets = listOf(project.sourceSets.main.get(), project.sourceSets.test.get()) ++} diff --git a/removed/0017-Configurable-speed-for-water-flowing-over-lava.patch b/patches/removed/0017-Configurable-speed-for-water-flowing-over-lava.patch similarity index 100% rename from removed/0017-Configurable-speed-for-water-flowing-over-lava.patch rename to patches/removed/0017-Configurable-speed-for-water-flowing-over-lava.patch diff --git a/removed/0033-Generator-Settings.patch b/patches/removed/0033-Generator-Settings.patch similarity index 100% rename from removed/0033-Generator-Settings.patch rename to patches/removed/0033-Generator-Settings.patch diff --git a/removed/0035-Stop-updating-flowing-block-if-material-has-changed.patch b/patches/removed/0035-Stop-updating-flowing-block-if-material-has-changed.patch similarity index 100% rename from removed/0035-Stop-updating-flowing-block-if-material-has-changed.patch rename to patches/removed/0035-Stop-updating-flowing-block-if-material-has-changed.patch diff --git a/removed/0036-Fast-draining.patch b/patches/removed/0036-Fast-draining.patch similarity index 100% rename from removed/0036-Fast-draining.patch rename to patches/removed/0036-Fast-draining.patch diff --git a/removed/0037-Send-absolute-position-the-first-time-an-entity-is-s.patch b/patches/removed/0037-Send-absolute-position-the-first-time-an-entity-is-s.patch similarity index 100% rename from removed/0037-Send-absolute-position-the-first-time-an-entity-is-s.patch rename to patches/removed/0037-Send-absolute-position-the-first-time-an-entity-is-s.patch diff --git a/removed/0097-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch b/patches/removed/0097-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch similarity index 100% rename from removed/0097-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch rename to patches/removed/0097-Prevent-Waterflow-BlockFromToEvent-from-loading-chun.patch diff --git a/removed/0115-Water-mobs-should-only-spawn-in-the-water.patch b/patches/removed/0115-Water-mobs-should-only-spawn-in-the-water.patch similarity index 100% rename from removed/0115-Water-mobs-should-only-spawn-in-the-water.patch rename to patches/removed/0115-Water-mobs-should-only-spawn-in-the-water.patch diff --git a/removed/0123-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch b/patches/removed/0123-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch similarity index 100% rename from removed/0123-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch rename to patches/removed/0123-SPIGOT-1401-Fix-dispenser-dropper-furnace-placement.patch diff --git a/removed/0280-Configurable-Unrestricted-Signs.patch b/patches/removed/0280-Configurable-Unrestricted-Signs.patch similarity index 100% rename from removed/0280-Configurable-Unrestricted-Signs.patch rename to patches/removed/0280-Configurable-Unrestricted-Signs.patch diff --git a/removed/0532-Unload-leaked-Cached-Chunks.patch b/patches/removed/0532-Unload-leaked-Cached-Chunks.patch similarity index 100% rename from removed/0532-Unload-leaked-Cached-Chunks.patch rename to patches/removed/0532-Unload-leaked-Cached-Chunks.patch diff --git a/removed/1.14/0032-Add-player-view-distance-API.patch b/patches/removed/1.14/0032-Add-player-view-distance-API.patch similarity index 100% rename from removed/1.14/0032-Add-player-view-distance-API.patch rename to patches/removed/1.14/0032-Add-player-view-distance-API.patch diff --git a/removed/1.14/0061-Chunk-save-queue-improvements.patch b/patches/removed/1.14/0061-Chunk-save-queue-improvements.patch similarity index 100% rename from removed/1.14/0061-Chunk-save-queue-improvements.patch rename to patches/removed/1.14/0061-Chunk-save-queue-improvements.patch diff --git a/removed/1.14/0070-Optimized-Light-Level-Comparisons.patch b/patches/removed/1.14/0070-Optimized-Light-Level-Comparisons.patch similarity index 100% rename from removed/1.14/0070-Optimized-Light-Level-Comparisons.patch rename to patches/removed/1.14/0070-Optimized-Light-Level-Comparisons.patch diff --git a/removed/1.14/0071-Pass-world-to-Village-creation.patch b/patches/removed/1.14/0071-Pass-world-to-Village-creation.patch similarity index 100% rename from removed/1.14/0071-Pass-world-to-Village-creation.patch rename to patches/removed/1.14/0071-Pass-world-to-Village-creation.patch diff --git a/removed/1.14/0078-Optimize-Chunk-Access.patch b/patches/removed/1.14/0078-Optimize-Chunk-Access.patch similarity index 100% rename from removed/1.14/0078-Optimize-Chunk-Access.patch rename to patches/removed/1.14/0078-Optimize-Chunk-Access.patch diff --git a/removed/1.14/0096-Don-t-spam-reload-spawn-chunks-in-nether-end.patch b/patches/removed/1.14/0096-Don-t-spam-reload-spawn-chunks-in-nether-end.patch similarity index 100% rename from removed/1.14/0096-Don-t-spam-reload-spawn-chunks-in-nether-end.patch rename to patches/removed/1.14/0096-Don-t-spam-reload-spawn-chunks-in-nether-end.patch diff --git a/removed/1.14/0112-Entity-Tracking-Improvements.patch b/patches/removed/1.14/0112-Entity-Tracking-Improvements.patch similarity index 100% rename from removed/1.14/0112-Entity-Tracking-Improvements.patch rename to patches/removed/1.14/0112-Entity-Tracking-Improvements.patch diff --git a/removed/1.14/0120-Ensure-Chunks-never-ever-load-async.patch b/patches/removed/1.14/0120-Ensure-Chunks-never-ever-load-async.patch similarity index 100% rename from removed/1.14/0120-Ensure-Chunks-never-ever-load-async.patch rename to patches/removed/1.14/0120-Ensure-Chunks-never-ever-load-async.patch diff --git a/removed/1.14/0123-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/patches/removed/1.14/0123-Delay-Chunk-Unloads-based-on-Player-Movement.patch similarity index 100% rename from removed/1.14/0123-Delay-Chunk-Unloads-based-on-Player-Movement.patch rename to patches/removed/1.14/0123-Delay-Chunk-Unloads-based-on-Player-Movement.patch diff --git a/removed/1.14/0142-Prevent-Auto-Save-if-Save-Queue-is-full.patch b/patches/removed/1.14/0142-Prevent-Auto-Save-if-Save-Queue-is-full.patch similarity index 100% rename from removed/1.14/0142-Prevent-Auto-Save-if-Save-Queue-is-full.patch rename to patches/removed/1.14/0142-Prevent-Auto-Save-if-Save-Queue-is-full.patch diff --git a/removed/1.14/0143-Chunk-Save-Stats-Debug-Option.patch b/patches/removed/1.14/0143-Chunk-Save-Stats-Debug-Option.patch similarity index 100% rename from removed/1.14/0143-Chunk-Save-Stats-Debug-Option.patch rename to patches/removed/1.14/0143-Chunk-Save-Stats-Debug-Option.patch diff --git a/removed/1.14/0144-Fix-block-break-desync.patch b/patches/removed/1.14/0144-Fix-block-break-desync.patch similarity index 100% rename from removed/1.14/0144-Fix-block-break-desync.patch rename to patches/removed/1.14/0144-Fix-block-break-desync.patch diff --git a/removed/1.14/0161-ShulkerBox-Dupe-Prevention.patch b/patches/removed/1.14/0161-ShulkerBox-Dupe-Prevention.patch similarity index 100% rename from removed/1.14/0161-ShulkerBox-Dupe-Prevention.patch rename to patches/removed/1.14/0161-ShulkerBox-Dupe-Prevention.patch diff --git a/removed/1.14/0258-Configurable-Villages-loading-chunks-for-door-checks.patch b/patches/removed/1.14/0258-Configurable-Villages-loading-chunks-for-door-checks.patch similarity index 100% rename from removed/1.14/0258-Configurable-Villages-loading-chunks-for-door-checks.patch rename to patches/removed/1.14/0258-Configurable-Villages-loading-chunks-for-door-checks.patch diff --git a/removed/1.14/0263-Properly-remove-entities-on-dimension-teleport.patch b/patches/removed/1.14/0263-Properly-remove-entities-on-dimension-teleport.patch similarity index 100% rename from removed/1.14/0263-Properly-remove-entities-on-dimension-teleport.patch rename to patches/removed/1.14/0263-Properly-remove-entities-on-dimension-teleport.patch diff --git a/removed/1.14/0285-Don-t-process-despawn-if-entity-is-in-a-chunk-schedu.patch b/patches/removed/1.14/0285-Don-t-process-despawn-if-entity-is-in-a-chunk-schedu.patch similarity index 100% rename from removed/1.14/0285-Don-t-process-despawn-if-entity-is-in-a-chunk-schedu.patch rename to patches/removed/1.14/0285-Don-t-process-despawn-if-entity-is-in-a-chunk-schedu.patch diff --git a/removed/1.14/0341-Optimize-getChunkIfLoaded-type-calls.patch b/patches/removed/1.14/0341-Optimize-getChunkIfLoaded-type-calls.patch similarity index 100% rename from removed/1.14/0341-Optimize-getChunkIfLoaded-type-calls.patch rename to patches/removed/1.14/0341-Optimize-getChunkIfLoaded-type-calls.patch diff --git a/removed/1.14/0361-Async-Chunk-Loading-and-Generation.patch b/patches/removed/1.14/0361-Async-Chunk-Loading-and-Generation.patch similarity index 100% rename from removed/1.14/0361-Async-Chunk-Loading-and-Generation.patch rename to patches/removed/1.14/0361-Async-Chunk-Loading-and-Generation.patch diff --git a/removed/1.14/0363-Optimize-Light-Recalculations.patch b/patches/removed/1.14/0363-Optimize-Light-Recalculations.patch similarity index 100% rename from removed/1.14/0363-Optimize-Light-Recalculations.patch rename to patches/removed/1.14/0363-Optimize-Light-Recalculations.patch diff --git a/removed/1.14/0366-Fix-Sending-Chunks-to-Client.patch b/patches/removed/1.14/0366-Fix-Sending-Chunks-to-Client.patch similarity index 100% rename from removed/1.14/0366-Fix-Sending-Chunks-to-Client.patch rename to patches/removed/1.14/0366-Fix-Sending-Chunks-to-Client.patch diff --git a/removed/1.14/0368-Fix-FileIOThread-concurrency-issues.patch b/patches/removed/1.14/0368-Fix-FileIOThread-concurrency-issues.patch similarity index 100% rename from removed/1.14/0368-Fix-FileIOThread-concurrency-issues.patch rename to patches/removed/1.14/0368-Fix-FileIOThread-concurrency-issues.patch diff --git a/removed/1.14/0377-Optimize-Persistent-Data-Loading.patch b/patches/removed/1.14/0377-Optimize-Persistent-Data-Loading.patch similarity index 100% rename from removed/1.14/0377-Optimize-Persistent-Data-Loading.patch rename to patches/removed/1.14/0377-Optimize-Persistent-Data-Loading.patch diff --git a/removed/1.14/0388-Use-EntityTypes-for-living-entities.patch b/patches/removed/1.14/0388-Use-EntityTypes-for-living-entities.patch similarity index 100% rename from removed/1.14/0388-Use-EntityTypes-for-living-entities.patch rename to patches/removed/1.14/0388-Use-EntityTypes-for-living-entities.patch diff --git a/removed/1.14/0400-limit-the-range-at-which-we-ll-consider-an-attackabl.patch b/patches/removed/1.14/0400-limit-the-range-at-which-we-ll-consider-an-attackabl.patch similarity index 100% rename from removed/1.14/0400-limit-the-range-at-which-we-ll-consider-an-attackabl.patch rename to patches/removed/1.14/0400-limit-the-range-at-which-we-ll-consider-an-attackabl.patch diff --git a/removed/1.15/0078-Reduce-IO-ops-opening-a-new-region-file.patch b/patches/removed/1.15/0078-Reduce-IO-ops-opening-a-new-region-file.patch similarity index 100% rename from removed/1.15/0078-Reduce-IO-ops-opening-a-new-region-file.patch rename to patches/removed/1.15/0078-Reduce-IO-ops-opening-a-new-region-file.patch diff --git a/removed/1.15/0081-Do-not-load-chunks-for-light-checks.patch b/patches/removed/1.15/0081-Do-not-load-chunks-for-light-checks.patch similarity index 100% rename from removed/1.15/0081-Do-not-load-chunks-for-light-checks.patch rename to patches/removed/1.15/0081-Do-not-load-chunks-for-light-checks.patch diff --git a/removed/1.15/0269-Provide-option-to-use-a-versioned-world-folder-for-t.patch b/patches/removed/1.15/0269-Provide-option-to-use-a-versioned-world-folder-for-t.patch similarity index 100% rename from removed/1.15/0269-Provide-option-to-use-a-versioned-world-folder-for-t.patch rename to patches/removed/1.15/0269-Provide-option-to-use-a-versioned-world-folder-for-t.patch diff --git a/removed/1.15/0280-Detect-and-repair-corrupt-Region-Files.patch b/patches/removed/1.15/0280-Detect-and-repair-corrupt-Region-Files.patch similarity index 100% rename from removed/1.15/0280-Detect-and-repair-corrupt-Region-Files.patch rename to patches/removed/1.15/0280-Detect-and-repair-corrupt-Region-Files.patch diff --git a/removed/1.15/0376-Handle-bad-chunks-more-gracefully.patch b/patches/removed/1.15/0376-Handle-bad-chunks-more-gracefully.patch similarity index 100% rename from removed/1.15/0376-Handle-bad-chunks-more-gracefully.patch rename to patches/removed/1.15/0376-Handle-bad-chunks-more-gracefully.patch diff --git a/removed/1.15/0403-Preserve-old-flush-on-save-flag-for-reliable-regionf.patch b/patches/removed/1.15/0403-Preserve-old-flush-on-save-flag-for-reliable-regionf.patch similarity index 100% rename from removed/1.15/0403-Preserve-old-flush-on-save-flag-for-reliable-regionf.patch rename to patches/removed/1.15/0403-Preserve-old-flush-on-save-flag-for-reliable-regionf.patch diff --git a/removed/1.15/0412-Improve-POI-data-saving-logic.patch b/patches/removed/1.15/0412-Improve-POI-data-saving-logic.patch similarity index 100% rename from removed/1.15/0412-Improve-POI-data-saving-logic.patch rename to patches/removed/1.15/0412-Improve-POI-data-saving-logic.patch diff --git a/removed/1.15/0417-Avoid-Chunk-Lookups-for-Entity-TileEntity-Current-Ch.patch b/patches/removed/1.15/0417-Avoid-Chunk-Lookups-for-Entity-TileEntity-Current-Ch.patch similarity index 100% rename from removed/1.15/0417-Avoid-Chunk-Lookups-for-Entity-TileEntity-Current-Ch.patch rename to patches/removed/1.15/0417-Avoid-Chunk-Lookups-for-Entity-TileEntity-Current-Ch.patch diff --git a/removed/1.16/0238-Configurable-Bed-Search-Radius.patch b/patches/removed/1.16/0238-Configurable-Bed-Search-Radius.patch similarity index 100% rename from removed/1.16/0238-Configurable-Bed-Search-Radius.patch rename to patches/removed/1.16/0238-Configurable-Bed-Search-Radius.patch diff --git a/removed/1.16/0298-Support-Overriding-World-Seeds.patch b/patches/removed/1.16/0298-Support-Overriding-World-Seeds.patch similarity index 100% rename from removed/1.16/0298-Support-Overriding-World-Seeds.patch rename to patches/removed/1.16/0298-Support-Overriding-World-Seeds.patch diff --git a/removed/1.16/0511-Implement-JellySquid-s-Entity-Collision-optimisation.patch b/patches/removed/1.16/0511-Implement-JellySquid-s-Entity-Collision-optimisation.patch similarity index 100% rename from removed/1.16/0511-Implement-JellySquid-s-Entity-Collision-optimisation.patch rename to patches/removed/1.16/0511-Implement-JellySquid-s-Entity-Collision-optimisation.patch diff --git a/removed/1.16/0512-Remove-some-Streams-usage-in-Entity-Collision.patch b/patches/removed/1.16/0512-Remove-some-Streams-usage-in-Entity-Collision.patch similarity index 100% rename from removed/1.16/0512-Remove-some-Streams-usage-in-Entity-Collision.patch rename to patches/removed/1.16/0512-Remove-some-Streams-usage-in-Entity-Collision.patch diff --git a/removed/1.16/0530-Optimize-Villagers.patch b/patches/removed/1.16/0530-Optimize-Villagers.patch similarity index 100% rename from removed/1.16/0530-Optimize-Villagers.patch rename to patches/removed/1.16/0530-Optimize-Villagers.patch diff --git a/removed/1.16/No longer Needed/0276-Send-nearby-packets-from-world-player-list-not-serve.patch b/patches/removed/1.16/No longer Needed/0276-Send-nearby-packets-from-world-player-list-not-serve.patch similarity index 100% rename from removed/1.16/No longer Needed/0276-Send-nearby-packets-from-world-player-list-not-serve.patch rename to patches/removed/1.16/No longer Needed/0276-Send-nearby-packets-from-world-player-list-not-serve.patch diff --git a/removed/1.16/No longer Needed/0302-Avoid-dimension-id-collisions.patch b/patches/removed/1.16/No longer Needed/0302-Avoid-dimension-id-collisions.patch similarity index 100% rename from removed/1.16/No longer Needed/0302-Avoid-dimension-id-collisions.patch rename to patches/removed/1.16/No longer Needed/0302-Avoid-dimension-id-collisions.patch diff --git a/removed/1.16/No longer Needed/0316-Fix-MC-93764.patch b/patches/removed/1.16/No longer Needed/0316-Fix-MC-93764.patch similarity index 100% rename from removed/1.16/No longer Needed/0316-Fix-MC-93764.patch rename to patches/removed/1.16/No longer Needed/0316-Fix-MC-93764.patch diff --git a/removed/1.16/No longer Needed/0373-Fix-some-generation-concurrency-issues.patch b/patches/removed/1.16/No longer Needed/0373-Fix-some-generation-concurrency-issues.patch similarity index 100% rename from removed/1.16/No longer Needed/0373-Fix-some-generation-concurrency-issues.patch rename to patches/removed/1.16/No longer Needed/0373-Fix-some-generation-concurrency-issues.patch diff --git a/removed/1.16/No longer Needed/0401-Fix-zero-tick-instant-grow-farms-MC-113809.patch b/patches/removed/1.16/No longer Needed/0401-Fix-zero-tick-instant-grow-farms-MC-113809.patch similarity index 100% rename from removed/1.16/No longer Needed/0401-Fix-zero-tick-instant-grow-farms-MC-113809.patch rename to patches/removed/1.16/No longer Needed/0401-Fix-zero-tick-instant-grow-farms-MC-113809.patch diff --git a/removed/1.16/No longer Needed/0412-Fix-spawn-radius-being-treated-as-0.patch b/patches/removed/1.16/No longer Needed/0412-Fix-spawn-radius-being-treated-as-0.patch similarity index 100% rename from removed/1.16/No longer Needed/0412-Fix-spawn-radius-being-treated-as-0.patch rename to patches/removed/1.16/No longer Needed/0412-Fix-spawn-radius-being-treated-as-0.patch diff --git a/removed/1.16/No longer Needed/0429-Seed-based-feature-search.patch b/patches/removed/1.16/No longer Needed/0429-Seed-based-feature-search.patch similarity index 100% rename from removed/1.16/No longer Needed/0429-Seed-based-feature-search.patch rename to patches/removed/1.16/No longer Needed/0429-Seed-based-feature-search.patch diff --git a/removed/1.16/No longer Needed/0468-Port-20w15a-Villager-AI-optimizations-DROP-1.16.patch b/patches/removed/1.16/No longer Needed/0468-Port-20w15a-Villager-AI-optimizations-DROP-1.16.patch similarity index 100% rename from removed/1.16/No longer Needed/0468-Port-20w15a-Villager-AI-optimizations-DROP-1.16.patch rename to patches/removed/1.16/No longer Needed/0468-Port-20w15a-Villager-AI-optimizations-DROP-1.16.patch diff --git a/removed/1.17/0049-Player-Tab-List-and-Title-APIs.patch b/patches/removed/1.17/0049-Player-Tab-List-and-Title-APIs.patch similarity index 100% rename from removed/1.17/0049-Player-Tab-List-and-Title-APIs.patch rename to patches/removed/1.17/0049-Player-Tab-List-and-Title-APIs.patch diff --git a/removed/Scheduler-decompile-fixes.patch b/patches/removed/Scheduler-decompile-fixes.patch similarity index 100% rename from removed/Scheduler-decompile-fixes.patch rename to patches/removed/Scheduler-decompile-fixes.patch diff --git a/patches/server-remapped/0001-POM-Changes.patch b/patches/server-remapped/0001-POM-Changes.patch new file mode 100644 index 0000000000..8d0da0d549 --- /dev/null +++ b/patches/server-remapped/0001-POM-Changes.patch @@ -0,0 +1,291 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 29 Feb 2016 20:40:33 -0600 +Subject: [PATCH] POM Changes + + +diff --git a/pom.xml b/pom.xml +index 3fc047371e8f8a626e69697fad549d689c5dce89..a5d87d22cb1588d15e08da3b37e51c5e261c7799 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -1,15 +1,14 @@ + + 4.0.0 +- org.spigotmc +- spigot ++ paper + jar + 1.16.5-R0.1-SNAPSHOT +- Spigot +- https://www.spigotmc.org/ ++ Paper ++ https://papermc.io + + +- true ++ + UTF-8 + unknown + git +@@ -20,21 +19,39 @@ + + + +- org.spigotmc +- spigot-parent ++ com.destroystokyo.paper ++ paper-parent + dev-SNAPSHOT + ../pom.xml + + ++ ++ ++ ++ org.apache.logging.log4j ++ log4j-bom ++ 2.11.2 ++ pom ++ import ++ ++ ++ ++ + + +- org.spigotmc +- spigot-api ++ com.destroystokyo.paper ++ paper-api ++ ${project.version} ++ compile ++ ++ ++ com.destroystokyo.paper ++ paper-mojangapi + ${project.version} + compile + + +- org.spigotmc ++ io.papermc + minecraft-server + ${minecraft.version}-SNAPSHOT + compile +@@ -45,18 +62,15 @@ + 2.12.1 + compile + ++ ++ org.apache.logging.log4j ++ log4j-api ++ compile ++ + + org.apache.logging.log4j + log4j-iostreams +- 2.8.1 + compile +- +- +- +- org.apache.logging.log4j +- log4j-api +- +- + + + org.ow2.asm +@@ -64,12 +78,23 @@ + 9.1 + compile + ++ ++ ++ co.aikar ++ cleaner ++ 1.0-SNAPSHOT ++ ++ ++ io.netty ++ netty-all ++ 4.1.50.Final ++ + + + com.googlecode.json-simple + json-simple + 1.1.1 +- runtime ++ compile + + + org.xerial +@@ -80,7 +105,7 @@ + + mysql + mysql-connector-java +- 5.1.49 ++ 8.0.23 + runtime + + +@@ -105,7 +130,7 @@ + + org.apache.logging.log4j + log4j-slf4j-impl +- 2.8.1 ++ + runtime + + +@@ -132,34 +157,22 @@ + + + ++ paper-${minecraft.version} ++ clean install + + +- net.md-5 +- scriptus +- 0.4.1 ++ com.lukegb.mojo ++ gitdescribe-maven-plugin ++ 1.3 ++ ++ git-Paper- ++ .. ++ + + +- ex-spigot +- +- ${bt.name}-Spigot-%s +- ../ +- spigot.desc +- +- initialize +- +- describe +- +- +- +- ex-craftbukkit +- +- -%s +- ../../CraftBukkit +- craftbukkit.desc +- +- initialize ++ compile + +- describe ++ gitdescribe + + + +@@ -169,6 +182,7 @@ + maven-jar-plugin + 3.2.0 + ++ true + + + false +@@ -176,11 +190,13 @@ + + org.bukkit.craftbukkit.Main + CraftBukkit +- ${spigot.desc}${craftbukkit.desc} +- ${project.build.outputTimestamp} ++ ++ ${describe} ++ ${maven.build.timestamp} + Bukkit + ${api.version} + Bukkit Team ++ true + + + +@@ -216,14 +232,24 @@ + shade + + ++ ${project.build.directory}/dependency-reduced-pom.xml + ${shadeSourcesJar} + + +- org.spigotmc:minecraft-server ++ io.papermc:minecraft-server + + com/google/common/** + com/google/gson/** + com/google/thirdparty/** ++ ++ io/netty/** ++ META-INF/native/libnetty* ++ com/mojang/brigadier/** ++ META-INF/MANIFEST.MF ++ com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.class ++ com/mojang/datafixers/util/Either* ++ org/apache/logging/log4j/** ++ META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat + + + +@@ -245,10 +271,11 @@ + jline + org.bukkit.craftbukkit.libs.jline + +- +- it.unimi +- org.bukkit.craftbukkit.libs.it.unimi +- ++ ++ ++ ++ ++ + + org.apache.commons.codec + org.bukkit.craftbukkit.libs.org.apache.commons.codec +@@ -316,10 +343,6 @@ + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 +- +- +- eclipse +- + + + org.codehaus.plexus +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 4452427d0a8298d119ca29ef397b7a94f19eec28..46a16e31775b28c44f95a8ac5545ebcb656c74b6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -186,7 +186,7 @@ public class Main { + } + + if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { +- Date buildDate = new Date(Integer.parseInt(Main.class.getPackage().getImplementationVendor()) * 1000L); ++ Date buildDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(Main.class.getPackage().getImplementationVendor()); // Paper + + Calendar deadline = Calendar.getInstance(); + deadline.add(Calendar.DAY_OF_YEAR, -28); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +index 93046379d0cefd5d3236fc59e698809acdc18f80..674096cab190d62622f9947853b056f57d43a2a5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +@@ -11,7 +11,7 @@ public final class Versioning { + public static String getBukkitVersion() { + String result = "Unknown-Version"; + +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties"); ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.destroystokyo.paper/paper-api/pom.properties"); + Properties properties = new Properties(); + + if (stream != null) { diff --git a/patches/server-remapped/0002-Paper-config-files.patch b/patches/server-remapped/0002-Paper-config-files.patch new file mode 100644 index 0000000000..363f09b241 --- /dev/null +++ b/patches/server-remapped/0002-Paper-config-files.patch @@ -0,0 +1,820 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 29 Feb 2016 21:02:09 -0600 +Subject: [PATCH] Paper config files + +Loads each yml file for early init too so it can be used for early options + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d05eeaa711a09bb121b530654821894e795ff4ea +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -0,0 +1,286 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Functions; ++import com.google.common.base.Joiner; ++import com.google.common.collect.ImmutableSet; ++import com.google.common.collect.Iterables; ++import com.google.common.collect.Lists; ++import com.google.common.collect.Maps; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.level.ChunkPos; ++import org.apache.commons.lang3.tuple.MutablePair; ++import org.apache.commons.lang3.tuple.Pair; ++import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; ++import org.bukkit.Location; ++import org.bukkit.World; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.entity.Player; ++ ++import java.io.File; ++import java.time.LocalDateTime; ++import java.time.format.DateTimeFormatter; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collection; ++import java.util.Collections; ++import java.util.Iterator; ++import java.util.List; ++import java.util.Locale; ++import java.util.Map; ++import java.util.Set; ++import java.util.stream.Collectors; ++ ++public class PaperCommand extends Command { ++ private static final String BASE_PERM = "bukkit.command.paper."; ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); ++ ++ public PaperCommand(String name) { ++ super(name); ++ this.description = "Paper related commands"; ++ this.usageMessage = "/paper [" + Joiner.on(" | ").join(SUBCOMMANDS) + "]"; ++ this.setPermission("bukkit.command.paper;" + Joiner.on(';').join(SUBCOMMANDS.stream().map(s -> BASE_PERM + s).collect(Collectors.toSet()))); ++ } ++ ++ private static boolean testPermission(CommandSender commandSender, String permission) { ++ if (commandSender.hasPermission(BASE_PERM + permission) || commandSender.hasPermission("bukkit.command.paper")) return true; ++ commandSender.sendMessage(Bukkit.getPermissionMessage()); ++ return false; ++ } ++ ++ @Override ++ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { ++ if (args.length <= 1) ++ return getListMatchingLast(sender, args, SUBCOMMANDS); ++ ++ switch (args[0].toLowerCase(Locale.ENGLISH)) ++ { ++ case "entity": ++ if (args.length == 2) ++ return getListMatchingLast(sender, args, "help", "list"); ++ if (args.length == 3) ++ return getListMatchingLast(sender, args, EntityType.getEntityNameList().stream().map(ResourceLocation::toString).sorted().toArray(String[]::new)); ++ break; ++ } ++ return Collections.emptyList(); ++ } ++ ++ // Code from Mojang - copyright them ++ public static List getListMatchingLast(CommandSender sender, String[] args, String... matches) { ++ return getListMatchingLast(sender, args, (Collection) Arrays.asList(matches)); ++ } ++ ++ public static boolean matches(String s, String s1) { ++ return s1.regionMatches(true, 0, s, 0, s.length()); ++ } ++ ++ public static List getListMatchingLast(CommandSender sender, String[] strings, Collection collection) { ++ String last = strings[strings.length - 1]; ++ ArrayList results = Lists.newArrayList(); ++ ++ if (!collection.isEmpty()) { ++ Iterator iterator = Iterables.transform(collection, Functions.toStringFunction()).iterator(); ++ ++ while (iterator.hasNext()) { ++ String s1 = (String) iterator.next(); ++ ++ if (matches(last, s1) && (sender.hasPermission(BASE_PERM + s1) || sender.hasPermission("bukkit.command.paper"))) { ++ results.add(s1); ++ } ++ } ++ ++ if (results.isEmpty()) { ++ iterator = collection.iterator(); ++ ++ while (iterator.hasNext()) { ++ Object object = iterator.next(); ++ ++ if (object instanceof ResourceLocation && matches(last, ((ResourceLocation) object).getPath())) { ++ results.add(String.valueOf(object)); ++ } ++ } ++ } ++ } ++ ++ return results; ++ } ++ // end copy stuff ++ ++ @Override ++ public boolean execute(CommandSender sender, String commandLabel, String[] args) { ++ if (!testPermission(sender)) return true; ++ ++ if (args.length == 0) { ++ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); ++ return false; ++ } ++ if (SUBCOMMANDS.contains(args[0].toLowerCase(Locale.ENGLISH))) { ++ if (!testPermission(sender, args[0].toLowerCase(Locale.ENGLISH))) return true; ++ } ++ switch (args[0].toLowerCase(Locale.ENGLISH)) { ++ case "heap": ++ dumpHeap(sender); ++ break; ++ case "entity": ++ listEntities(sender, args); ++ break; ++ case "reload": ++ doReload(sender); ++ break; ++ case "ver": ++ if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) ++ case "version": ++ Command ver = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version"); ++ if (ver != null) { ++ ver.execute(sender, commandLabel, new String[0]); ++ break; ++ } ++ // else - fall through to default ++ default: ++ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); ++ return false; ++ } ++ ++ return true; ++ } ++ ++ /* ++ * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 ++ */ ++ private void listEntities(CommandSender sender, String[] args) { ++ if (args.length < 2 || args[1].toLowerCase(Locale.ENGLISH).equals("help")) { ++ sender.sendMessage(ChatColor.RED + "Use /paper entity [list] help for more information on a specific command."); ++ return; ++ } ++ ++ switch (args[1].toLowerCase(Locale.ENGLISH)) { ++ case "list": ++ String filter = "*"; ++ if (args.length > 2) { ++ if (args[2].toLowerCase(Locale.ENGLISH).equals("help")) { ++ sender.sendMessage(ChatColor.RED + "Use /paper entity list [filter] [worldName] to get entity info that matches the optional filter."); ++ return; ++ } ++ filter = args[2]; ++ } ++ final String cleanfilter = filter.replace("?", ".?").replace("*", ".*?"); ++ Set names = EntityType.getEntityNameList().stream() ++ .filter(n -> n.toString().matches(cleanfilter)) ++ .collect(Collectors.toSet()); ++ ++ if (names.isEmpty()) { ++ sender.sendMessage(ChatColor.RED + "Invalid filter, does not match any entities. Use /paper entity list for a proper list"); ++ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); ++ return; ++ } ++ ++ String worldName; ++ if (args.length > 3) { ++ worldName = args[3]; ++ } else if (sender instanceof Player) { ++ worldName = ((Player) sender).getWorld().getName(); ++ } else { ++ sender.sendMessage(ChatColor.RED + "Please specify the name of a world"); ++ sender.sendMessage(ChatColor.RED + "To do so without a filter, specify '*' as the filter"); ++ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); ++ return; ++ } ++ ++ Map>> list = Maps.newHashMap(); ++ World bukkitWorld = Bukkit.getWorld(worldName); ++ if (bukkitWorld == null) { ++ sender.sendMessage(ChatColor.RED + "Could not load world for " + worldName + ". Please select a valid world."); ++ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); ++ return; ++ } ++ ServerLevel world = ((CraftWorld) Bukkit.getWorld(worldName)).getHandle(); ++ ++ Map nonEntityTicking = Maps.newHashMap(); ++ ServerChunkCache chunkProviderServer = world.getChunkSource(); ++ ++ Collection entities = world.entitiesById.values(); ++ entities.forEach(e -> { ++ ResourceLocation key = new ResourceLocation(""); // TODO: update in next patch ++ ++ MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); ++ ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); ++ info.left++; ++ info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1); ++ if (!chunkProviderServer.isInEntityTickingChunk(e)) { ++ nonEntityTicking.merge(key, Integer.valueOf(1), Integer::sum); ++ } ++ }); ++ ++ if (names.size() == 1) { ++ ResourceLocation name = names.iterator().next(); ++ Pair> info = list.get(name); ++ int nonTicking = nonEntityTicking.getOrDefault(name, Integer.valueOf(0)).intValue(); ++ if (info == null) { ++ sender.sendMessage(ChatColor.RED + "No entities found."); ++ return; ++ } ++ sender.sendMessage("Entity: " + name + " Total Ticking: " + (info.getLeft() - nonTicking) + ", Total Non-Ticking: " + nonTicking); ++ info.getRight().entrySet().stream() ++ .sorted((a, b) -> !a.getValue().equals(b.getValue()) ? b.getValue() - a.getValue() : a.getKey().toString().compareTo(b.getKey().toString())) ++ .limit(10).forEach(e -> sender.sendMessage(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z + (chunkProviderServer.isEntityTickingChunk(e.getKey()) ? " (Ticking)" : " (Non-Ticking)"))); ++ } else { ++ List> info = list.entrySet().stream() ++ .filter(e -> names.contains(e.getKey())) ++ .map(e -> Pair.of(e.getKey(), e.getValue().left)) ++ .sorted((a, b) -> !a.getRight().equals(b.getRight()) ? b.getRight() - a.getRight() : a.getKey().toString().compareTo(b.getKey().toString())) ++ .collect(Collectors.toList()); ++ ++ if (info == null || info.size() == 0) { ++ sender.sendMessage(ChatColor.RED + "No entities found."); ++ return; ++ } ++ ++ int count = info.stream().mapToInt(Pair::getRight).sum(); ++ int nonTickingCount = nonEntityTicking.values().stream().mapToInt(Integer::intValue).sum(); ++ sender.sendMessage("Total Ticking: " + (count - nonTickingCount) + ", Total Non-Ticking: " + nonTickingCount); ++ info.forEach(e -> { ++ int nonTicking = nonEntityTicking.getOrDefault(e.getKey(), Integer.valueOf(0)).intValue(); ++ sender.sendMessage(" " + (e.getValue() - nonTicking) + " (" + nonTicking + ") " + ": " + e.getKey()); ++ }); ++ sender.sendMessage("* First number is ticking entities, second number is non-ticking entities"); ++ } ++ break; ++ } ++ } ++ ++ private void dumpHeap(CommandSender sender) { ++ java.nio.file.Path dir = java.nio.file.Paths.get("./dumps"); ++ String name = "heap-dump-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()); ++ ++ Command.broadcastCommandMessage(sender, ChatColor.YELLOW + "Writing JVM heap data..."); ++ ++ java.nio.file.Path file = CraftServer.dumpHeap(dir, name); ++ if (file != null) { ++ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Heap dump saved to " + file); ++ } else { ++ Command.broadcastCommandMessage(sender, ChatColor.RED + "Failed to write heap dump, see sever log for details"); ++ } ++ } ++ ++ private void doReload(CommandSender sender) { ++ Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues."); ++ Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); ++ ++ MinecraftServer console = MinecraftServer.getServer(); ++ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); ++ for (ServerLevel world : console.getAllLevels()) { ++ world.paperConfig.init(); ++ } ++ console.server.reloadCount++; ++ ++ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete."); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2c0514892d3993bef57ecf677cf8bb0fbe0216e4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -0,0 +1,185 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Throwables; ++ ++import java.io.File; ++import java.io.IOException; ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.TimeUnit; ++import java.util.logging.Level; ++import java.util.regex.Pattern; ++ ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++import org.bukkit.command.Command; ++import org.bukkit.configuration.ConfigurationSection; ++import org.bukkit.configuration.InvalidConfigurationException; ++import org.bukkit.configuration.file.YamlConfiguration; ++ ++public class PaperConfig { ++ ++ private static File CONFIG_FILE; ++ private static final String HEADER = "This is the main configuration file for Paper.\n" ++ + "As you can see, there's tons to configure. Some options may impact gameplay, so use\n" ++ + "with caution, and make sure you know what each option does before configuring.\n" ++ + "\n" ++ + "If you need help with the configuration or have any questions related to Paper,\n" ++ + "join us in our Discord or IRC channel.\n" ++ + "\n" ++ + "Discord: https://discord.gg/papermc\n" ++ + "IRC: #paper @ irc.esper.net ( https://webchat.esper.net/?channels=paper ) \n" ++ + "Website: https://papermc.io/ \n" ++ + "Docs: https://paper.readthedocs.org/ \n"; ++ /*========================================================================*/ ++ public static YamlConfiguration config; ++ static int version; ++ static Map commands; ++ private static boolean verbose; ++ private static boolean fatalError; ++ /*========================================================================*/ ++ ++ public static void init(File configFile) { ++ CONFIG_FILE = configFile; ++ config = new YamlConfiguration(); ++ try { ++ config.load(CONFIG_FILE); ++ } catch (IOException ex) { ++ } catch (InvalidConfigurationException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not load paper.yml, please correct your syntax errors", ex); ++ throw Throwables.propagate(ex); ++ } ++ config.options().header(HEADER); ++ config.options().copyDefaults(true); ++ verbose = getBoolean("verbose", false); ++ ++ commands = new HashMap(); ++ commands.put("paper", new PaperCommand("paper")); ++ ++ version = getInt("config-version", 20); ++ set("config-version", 20); ++ readConfig(PaperConfig.class, null); ++ } ++ ++ protected static void logError(String s) { ++ Bukkit.getLogger().severe(s); ++ } ++ ++ protected static void fatal(String s) { ++ fatalError = true; ++ throw new RuntimeException("Fatal paper.yml config error: " + s); ++ } ++ ++ protected static void log(String s) { ++ if (verbose) { ++ Bukkit.getLogger().info(s); ++ } ++ } ++ ++ public static void registerCommands() { ++ for (Map.Entry entry : commands.entrySet()) { ++ MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); ++ } ++ } ++ ++ static void readConfig(Class clazz, Object instance) { ++ for (Method method : clazz.getDeclaredMethods()) { ++ if (Modifier.isPrivate(method.getModifiers())) { ++ if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) { ++ try { ++ method.setAccessible(true); ++ method.invoke(instance); ++ } catch (InvocationTargetException ex) { ++ throw Throwables.propagate(ex.getCause()); ++ } catch (Exception ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex); ++ } ++ } ++ } ++ } ++ ++ try { ++ config.save(CONFIG_FILE); ++ } catch (IOException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex); ++ } ++ } ++ ++ private static final Pattern SPACE = Pattern.compile(" "); ++ private static final Pattern NOT_NUMERIC = Pattern.compile("[^-\\d.]"); ++ public static int getSeconds(String str) { ++ str = SPACE.matcher(str).replaceAll(""); ++ final char unit = str.charAt(str.length() - 1); ++ str = NOT_NUMERIC.matcher(str).replaceAll(""); ++ double num; ++ try { ++ num = Double.parseDouble(str); ++ } catch (Exception e) { ++ num = 0D; ++ } ++ switch (unit) { ++ case 'd': num *= (double) 60*60*24; break; ++ case 'h': num *= (double) 60*60; break; ++ case 'm': num *= (double) 60; break; ++ default: case 's': break; ++ } ++ return (int) num; ++ } ++ ++ protected static String timeSummary(int seconds) { ++ String time = ""; ++ ++ if (seconds > 60 * 60 * 24) { ++ time += TimeUnit.SECONDS.toDays(seconds) + "d"; ++ seconds %= 60 * 60 * 24; ++ } ++ ++ if (seconds > 60 * 60) { ++ time += TimeUnit.SECONDS.toHours(seconds) + "h"; ++ seconds %= 60 * 60; ++ } ++ ++ if (seconds > 0) { ++ time += TimeUnit.SECONDS.toMinutes(seconds) + "m"; ++ } ++ return time; ++ } ++ ++ private static void set(String path, Object val) { ++ config.set(path, val); ++ } ++ ++ private static boolean getBoolean(String path, boolean def) { ++ config.addDefault(path, def); ++ return config.getBoolean(path, config.getBoolean(path)); ++ } ++ ++ private static double getDouble(String path, double def) { ++ config.addDefault(path, def); ++ return config.getDouble(path, config.getDouble(path)); ++ } ++ ++ private static float getFloat(String path, float def) { ++ // TODO: Figure out why getFloat() always returns the default value. ++ return (float) getDouble(path, (double) def); ++ } ++ ++ private static int getInt(String path, int def) { ++ config.addDefault(path, def); ++ return config.getInt(path, config.getInt(path)); ++ } ++ ++ private static List getList(String path, T def) { ++ config.addDefault(path, def); ++ return (List) config.getList(path, config.getList(path)); ++ } ++ ++ private static String getString(String path, String def) { ++ config.addDefault(path, def); ++ return config.getString(path, config.getString(path)); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b31109d2dadd29e8852468c19265066b773d2be0 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -0,0 +1,68 @@ ++package com.destroystokyo.paper; ++ ++import java.util.List; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.configuration.file.YamlConfiguration; ++import org.spigotmc.SpigotWorldConfig; ++ ++import static com.destroystokyo.paper.PaperConfig.log; ++import static com.destroystokyo.paper.PaperConfig.logError; ++ ++public class PaperWorldConfig { ++ ++ private final String worldName; ++ private final SpigotWorldConfig spigotConfig; ++ private YamlConfiguration config; ++ private boolean verbose; ++ ++ public PaperWorldConfig(String worldName, SpigotWorldConfig spigotConfig) { ++ this.worldName = worldName; ++ this.spigotConfig = spigotConfig; ++ this.config = PaperConfig.config; ++ init(); ++ } ++ ++ public void init() { ++ this.config = PaperConfig.config; // grab updated reference ++ log("-------- World Settings For [" + worldName + "] --------"); ++ PaperConfig.readConfig(PaperWorldConfig.class, this); ++ } ++ ++ private void set(String path, Object val) { ++ config.set("world-settings.default." + path, val); ++ if (config.get("world-settings." + worldName + "." + path) != null) { ++ config.set("world-settings." + worldName + "." + path, val); ++ } ++ } ++ ++ private boolean getBoolean(String path, boolean def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path)); ++ } ++ ++ private double getDouble(String path, double def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getDouble("world-settings." + worldName + "." + path, config.getDouble("world-settings.default." + path)); ++ } ++ ++ private int getInt(String path, int def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getInt("world-settings." + worldName + "." + path, config.getInt("world-settings.default." + path)); ++ } ++ ++ private float getFloat(String path, float def) { ++ // TODO: Figure out why getFloat() always returns the default value. ++ return (float) getDouble(path, (double) def); ++ } ++ ++ private List getList(String path, List def) { ++ config.addDefault("world-settings.default." + path, def); ++ return (List) config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)); ++ } ++ ++ private String getString(String path, String def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 9366b5551047e87e455fafbf45be5fb145aa875b..5d83a8d4c69144219219877c521c364d912d2452 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -95,6 +95,12 @@ public class Main { + DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(iregistrycustom_dimension, optionset); // CraftBukkit - CLI argument support + + dedicatedserversettings.forceSave(); ++ // Paper start - load config files for access below if needed ++ org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = loadConfigFile((File) optionset.valueOf("bukkit-settings")); ++ org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = loadConfigFile((File) optionset.valueOf("spigot-settings")); ++ org.bukkit.configuration.file.YamlConfiguration paperConfiguration = loadConfigFile((File) optionset.valueOf("paper-settings")); ++ // Paper end ++ + java.nio.file.Path java_nio_file_path1 = Paths.get("eula.txt"); + Eula eula = new Eula(java_nio_file_path1); + +@@ -236,6 +242,20 @@ public class Main { + + } + ++ // Paper start - load config files ++ private static org.bukkit.configuration.file.YamlConfiguration loadConfigFile(File configFile) throws Exception { ++ org.bukkit.configuration.file.YamlConfiguration config = new org.bukkit.configuration.file.YamlConfiguration(); ++ if (configFile.exists()) { ++ try { ++ config.load(configFile); ++ } catch (Exception ex) { ++ throw new Exception("Failed to load configuration file: " + configFile.getName(), ex); ++ } ++ } ++ return config; ++ } ++ // Paper end ++ + public static void forceUpgrade(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, boolean eraseCache, BooleanSupplier booleansupplier, ImmutableSet> worlds) { // CraftBukkit + Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit + WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, worlds, eraseCache); +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 2228f83f251851aa683f739ac5ce2ec98f059f3f..23d6f803eafa78fd51ea4cdc4ca25c78661bc80b 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -184,6 +184,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); + org.spigotmc.SpigotConfig.registerCommands(); + // Spigot end ++ // Paper start ++ try { ++ com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); ++ } catch (Exception e) { ++ DedicatedServer.LOGGER.error("Unable to load server configuration", e); ++ return false; ++ } ++ com.destroystokyo.paper.PaperConfig.registerCommands(); ++ // Paper end + + this.setPvpAllowed(dedicatedserverproperties.pvp); + this.setFlightAllowed(dedicatedserverproperties.allowFlight); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index aa7bf54e4b93a9b6085aa943500f5dec5f60a117..7cc5070f70a4f740add9d971385ceaa4d44275a2 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -307,15 +307,15 @@ public class ServerChunkCache extends ChunkSource { + } + } + +- @Override +- public boolean isEntityTickingChunk(Entity entity) { ++ public final boolean isInEntityTickingChunk(Entity entity) { return this.isEntityTickingChunk(entity); } // Paper - OBFHELPER ++ @Override public boolean isEntityTickingChunk(Entity entity) { + long i = ChunkPos.asLong(Mth.floor(entity.getX()) >> 4, Mth.floor(entity.getZ()) >> 4); + + return this.checkChunkFuture(i, (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error + } + +- @Override +- public boolean isEntityTickingChunk(ChunkPos pos) { ++ public final boolean isEntityTickingChunk(ChunkPos chunkcoordintpair) { return this.isEntityTickingChunk(chunkcoordintpair); } // Paper - OBFHELPER ++ @Override public boolean isEntityTickingChunk(ChunkPos pos) { + return this.checkChunkFuture(pos.toLong(), (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error + } + +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index f82fd4a50921c3c4791be18a43778e6fd216f557..ff482d0349c18d0d1ba902ea0d10611b1ca4e588 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -2,6 +2,7 @@ package net.minecraft.world.entity; + + import com.google.common.collect.ImmutableSet; + import java.util.Optional; ++import java.util.Set; // Paper + import java.util.UUID; + import java.util.function.Function; + import java.util.stream.Stream; +@@ -599,4 +600,10 @@ public class EntityType { + return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval); + } + } ++ ++ // Paper start ++ public static Set getEntityNameList() { ++ return Registry.ENTITY_TYPE.keySet(); ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index b7c64fcf49ea50fa38a121d906ec6df20a1be31b..f08de81dcc4acd5a3e44407b431ce827a19b2e9c 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -129,6 +129,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean populating; + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + ++ public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper ++ + public final SpigotTimings.WorldTimingsHandler timings; // Spigot + public static BlockPos lastPhysicsProblem; // Spigot + private org.spigotmc.TickLimiter entityLimiter; +@@ -149,6 +151,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot ++ this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper + this.generator = gen; + this.world = new CraftWorld((ServerLevel) this, gen, env); + this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns(); // CraftBukkit +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 761ad2d7e538d1e299d3050446274addcde7d772..328d1e2b128b62f24917719c79823c9fb64a0dcf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -806,6 +806,7 @@ public final class CraftServer implements Server { + } + + org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot ++ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper + for (ServerLevel world : console.getAllLevels()) { + world.worldDataServer.setDifficulty(config.difficulty); + world.setSpawnSettings(config.spawnMonsters, config.spawnAnimals); +@@ -839,6 +840,7 @@ public final class CraftServer implements Server { + world.ticksPerAmbientSpawns = this.getTicksPerAmbientSpawns(); + } + world.spigotConfig.init(); // Spigot ++ world.paperConfig.init(); // Paper + } + + pluginManager.clearPlugins(); +@@ -846,6 +848,7 @@ public final class CraftServer implements Server { + resetRecipes(); + reloadData(); + org.spigotmc.SpigotConfig.registerCommands(); // Spigot ++ com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper + overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); + ignoreVanillaPermissions = commandsConfiguration.getBoolean("ignore-vanilla-permissions"); + +@@ -2101,4 +2104,35 @@ public final class CraftServer implements Server { + return spigot; + } + // Spigot end ++ ++ // Paper start ++ @SuppressWarnings({"rawtypes", "unchecked"}) ++ public static java.nio.file.Path dumpHeap(java.nio.file.Path dir, String name) { ++ try { ++ java.nio.file.Files.createDirectories(dir); ++ ++ javax.management.MBeanServer server = java.lang.management.ManagementFactory.getPlatformMBeanServer(); ++ java.nio.file.Path file; ++ ++ try { ++ Class clazz = Class.forName("openj9.lang.management.OpenJ9DiagnosticsMXBean"); ++ Object openj9Mbean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "openj9.lang.management:type=OpenJ9Diagnostics", clazz); ++ java.lang.reflect.Method m = clazz.getMethod("triggerDumpToFile", String.class, String.class); ++ file = dir.resolve(name + ".phd"); ++ m.invoke(openj9Mbean, "heap", file.toString()); ++ } catch (ClassNotFoundException e) { ++ Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean"); ++ Object hotspotMBean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", clazz); ++ java.lang.reflect.Method m = clazz.getMethod("dumpHeap", String.class, boolean.class); ++ file = dir.resolve(name + ".hprof"); ++ m.invoke(hotspotMBean, file.toString(), true); ++ } ++ ++ return file; ++ } catch (Throwable t) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not write heap", t); ++ return null; ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 46a16e31775b28c44f95a8ac5545ebcb656c74b6..05aedca561919a12ced1925c5cc9af585bb04523 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -129,6 +129,14 @@ public class Main { + .defaultsTo(new File("spigot.yml")) + .describedAs("Yml file"); + // Spigot End ++ ++ // Paper Start ++ acceptsAll(asList("paper", "paper-settings"), "File for paper settings") ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File("paper.yml")) ++ .describedAs("Yml file"); ++ // Paper end + } + }; + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 83d83ff7ceffbb77723da721b869dfd0091e496d..0efcbab8f8806aeb8dd8bd6384e5a7cee375d100 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -39,36 +39,36 @@ public class SpigotWorldConfig + config.set( "world-settings.default." + path, val ); + } + +- private boolean getBoolean(String path, boolean def) ++ public boolean getBoolean(String path, boolean def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return config.getBoolean( "world-settings." + worldName + "." + path, config.getBoolean( "world-settings.default." + path ) ); + } + +- private double getDouble(String path, double def) ++ public double getDouble(String path, double def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return config.getDouble( "world-settings." + worldName + "." + path, config.getDouble( "world-settings.default." + path ) ); + } + +- private int getInt(String path) ++ public int getInt(String path) // Paper - private -> public + { + return config.getInt( "world-settings." + worldName + "." + path ); + } + +- private int getInt(String path, int def) ++ public int getInt(String path, int def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return config.getInt( "world-settings." + worldName + "." + path, config.getInt( "world-settings.default." + path ) ); + } + +- private List getList(String path, T def) ++ public List getList(String path, T def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return (List) config.getList( "world-settings." + worldName + "." + path, config.getList( "world-settings.default." + path ) ); + } + +- private String getString(String path, String def) ++ public String getString(String path, String def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return config.getString( "world-settings." + worldName + "." + path, config.getString( "world-settings.default." + path ) ); diff --git a/patches/server-remapped/0003-MC-Dev-fixes.patch b/patches/server-remapped/0003-MC-Dev-fixes.patch new file mode 100644 index 0000000000..10c424b9a6 --- /dev/null +++ b/patches/server-remapped/0003-MC-Dev-fixes.patch @@ -0,0 +1,929 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 30 Mar 2016 19:36:20 -0400 +Subject: [PATCH] MC Dev fixes + + +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index 16220ce9a7db722c8b351f8016fd1df066ffcb98..8c378d3f3138953b3b22b289fecdb6b40a09ab63 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -65,8 +65,8 @@ public class Util { + return Collectors.toMap(Entry::getKey, Entry::getValue); + } + +- public static > String getPropertyName(Property iblockstate, Object object) { +- return iblockstate.value((Comparable) object); ++ public static > String a(Property iblockstate, T object) { // Paper - decompile fix ++ return iblockstate.getName(object); // Paper - decompile fix + } + + public static String makeDescriptionId(String type, @Nullable ResourceLocation id) { +@@ -234,8 +234,8 @@ public class Util { + public static T findPreviousInIterable(Iterable iterable, @Nullable T t0) { + Iterator iterator = iterable.iterator(); + +- Object object; +- Object object1; ++ T object; // Paper - decompile fix ++ T object1; // Paper - decompile fix + + for (object1 = null; iterator.hasNext(); object1 = object) { + object = iterator.next(); +@@ -260,7 +260,7 @@ public class Util { + } + + public static Strategy identityStrategy() { +- return Util.IdentityStrategy.INSTANCE; ++ return (Strategy) Util.IdentityStrategy.INSTANCE; // Paper - decompile fix + } + + public static CompletableFuture> sequence(List> futures) { +@@ -271,7 +271,7 @@ public class Util { + futures.forEach((completablefuture1) -> { + int i = list1.size(); + +- list1.add((Object) null); ++ list1.add(null); // Paper - decompile fix + acompletablefuture[i] = completablefuture1.whenComplete((object, throwable) -> { + if (throwable != null) { + completablefuture.completeExceptionally(throwable); +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index aa35d67cc27a4f982575eab3be46f4187f29d3fe..88147a1f25cf2fd549412b653b8f0eb5c60bb55d 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -241,8 +241,8 @@ public class BlockPos extends Vec3i { + }; + } + +- public static Iterable withinManhattan(BlockPos center, int xRange, int yRange, int zRange) { +- int l = xRange + yRange + zRange; ++ public static Iterable withinManhattan(BlockPos center, int xRange, int yRange, int zRange) { // Paper - decompile issues - variable name conflicts to inner class field refs ++ int l_decompiled = xRange + yRange + zRange; // Paper - decompile issues + int i1 = center.getX(); + int j1 = center.getY(); + int k1 = center.getZ(); +@@ -270,15 +270,15 @@ public class BlockPos extends Vec3i { + ++this.x; + if (this.x > this.maxX) { + ++this.currentDepth; +- if (this.currentDepth > x) { ++ if (this.currentDepth > l_decompiled) { // Paper - use proper l above (first line of this method) + return (BlockPos) this.endOfData(); + } + +- this.maxX = Math.min(currentDepth, this.currentDepth); ++ this.maxX = Math.min(xRange, this.currentDepth); // Paper - decompile issues + this.x = -this.maxX; + } + +- this.maxY = Math.min(maxX, this.currentDepth - Math.abs(this.x)); ++ this.maxY = Math.min(yRange, this.currentDepth - Math.abs(this.x)); // Paper - decompile issues + this.y = -this.maxY; + } + +@@ -286,7 +286,7 @@ public class BlockPos extends Vec3i { + int i2 = this.y; + int j2 = this.currentDepth - Math.abs(l1) - Math.abs(i2); + +- if (j2 <= maxY) { ++ if (j2 <= zRange) { // Paper - decompile issues + this.zMirror = j2 != 0; + blockposition_mutableblockposition = this.cursor.set(i1 + l1, j1 + i2, k1 + j2); + } +@@ -355,13 +355,13 @@ public class BlockPos extends Vec3i { + }; + } + +- public static Iterable spiralAround(BlockPos blockposition, int i, Direction enumdirection, Direction enumdirection1) { ++ public static Iterable spiralAround(BlockPos blockposition, int I, Direction enumdirection, Direction enumdirection1) { // Paper - decompile fix + Validate.validState(enumdirection.getAxis() != enumdirection1.getAxis(), "The two directions cannot be on the same axis", new Object[0]); + return () -> { + return new AbstractIterator() { + private final Direction[] directions = new Direction[]{enumdirection, enumdirection1, enumdirection.getOpposite(), enumdirection1.getOpposite()}; + private final BlockPos.MutableBlockPos cursor = blockposition.mutable().move(enumdirection1); +- private final int legs = 4 * legSize; ++ private final int legs = 4 * I; + private int leg = -1; + private int legSize; + private int legIndex; +diff --git a/src/main/java/net/minecraft/core/IdMapper.java b/src/main/java/net/minecraft/core/IdMapper.java +index 71c591487853bec3cecf5777c09ddc05bd658b64..424c6cacc2e7c7b1c9d0b92fe198237033a3fcbd 100644 +--- a/src/main/java/net/minecraft/core/IdMapper.java ++++ b/src/main/java/net/minecraft/core/IdMapper.java +@@ -27,7 +27,7 @@ public class IdMapper implements IdMap { + this.tToId.put(value, id); + + while (this.idToT.size() <= id) { +- this.idToT.add((Object) null); ++ this.idToT.add(null); // Paper - decompile fix + } + + this.idToT.set(id, value); +@@ -41,6 +41,13 @@ public class IdMapper implements IdMap { + this.addMapping(value, this.nextId); + } + ++ // Paper start - decompile fix ++ @Override ++ public int a(T t) { ++ return getId(t); ++ } ++ // Paper end ++ + public int getId(T entry) { + Integer integer = (Integer) this.tToId.get(entry); + +diff --git a/src/main/java/net/minecraft/nbt/ListTag.java b/src/main/java/net/minecraft/nbt/ListTag.java +index efc632a8ac13f77aaf2229a09e84416c09c86255..084340dc73acb3d972e0717b48da820c027a5137 100644 +--- a/src/main/java/net/minecraft/nbt/ListTag.java ++++ b/src/main/java/net/minecraft/nbt/ListTag.java +@@ -53,7 +53,7 @@ public class ListTag extends CollectionTag { + return "TAG_List"; + } + }; +- private static final ByteSet INLINE_ELEMENT_TYPES = new ByteOpenHashSet(Arrays.asList(1, 2, 3, 4, 5, 6)); ++ private static final ByteSet INLINE_ELEMENT_TYPES = new ByteOpenHashSet(Arrays.asList((byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6)); // Paper - decompiler fix + private final List list; + private byte type; + +diff --git a/src/main/java/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java +index 5494db9e8e04d976aa1b005a108b452cd481d0bb..c4fbc0bc8b80d16f09d3c6642acc7476a0817868 100644 +--- a/src/main/java/net/minecraft/nbt/NbtIo.java ++++ b/src/main/java/net/minecraft/nbt/NbtIo.java +@@ -18,6 +18,7 @@ import java.util.zip.GZIPOutputStream; + import net.minecraft.CrashReport; + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; ++import io.netty.buffer.ByteBufInputStream; // Paper + + public class NbtIo { + +@@ -137,7 +138,7 @@ public class NbtIo { + + public static CompoundTag read(DataInput input, NbtAccounter tracker) throws IOException { + // Spigot start +- if ( input instanceof io.netty.buffer.ByteBufInputStream ) ++ if ( input instanceof ByteBufInputStream) // Paper + { + input = new DataInputStream(new org.spigotmc.LimitStream((InputStream) input, tracker)); + } +diff --git a/src/main/java/net/minecraft/nbt/Tag.java b/src/main/java/net/minecraft/nbt/Tag.java +index 483c33e9b2d64c1a003d3bb543486b8a545bc96a..85e9c5f4620fcf48cb3655fbb2db58b3fb31aa74 100644 +--- a/src/main/java/net/minecraft/nbt/Tag.java ++++ b/src/main/java/net/minecraft/nbt/Tag.java +@@ -20,7 +20,7 @@ public interface Tag { + + TagType getType(); + +- Tag copy(); ++ public Tag copy(); // Paper - decompile fix + + default String getAsString() { + return this.toString(); +diff --git a/src/main/java/net/minecraft/network/ConnectionProtocol.java b/src/main/java/net/minecraft/network/ConnectionProtocol.java +index a12d169edf4e087b18fedf7199d6eb7ee58f0305..fca778d131aa10e88d5f7ed8d57eda6803318184 100644 +--- a/src/main/java/net/minecraft/network/ConnectionProtocol.java ++++ b/src/main/java/net/minecraft/network/ConnectionProtocol.java +@@ -14,23 +14,29 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketFlow; + import net.minecraft.network.protocol.game.*; + import net.minecraft.network.protocol.handshake.ClientIntentionPacket; ++import net.minecraft.network.protocol.handshake.ServerHandshakePacketListener; ++import net.minecraft.network.protocol.login.ClientLoginPacketListener; + import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; + import net.minecraft.network.protocol.login.ClientboundGameProfilePacket; + import net.minecraft.network.protocol.login.ClientboundHelloPacket; + import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; + import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; ++import net.minecraft.network.protocol.login.ServerLoginPacketListener; + import net.minecraft.network.protocol.login.ServerboundCustomQueryPacket; + import net.minecraft.network.protocol.login.ServerboundHelloPacket; + import net.minecraft.network.protocol.login.ServerboundKeyPacket; ++import net.minecraft.network.protocol.status.ClientStatusPacketListener; + import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; + import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; ++import net.minecraft.network.protocol.status.ServerStatusPacketListener; + import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; + import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; + import org.apache.logging.log4j.LogManager; + + public enum ConnectionProtocol { + +- HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))), PLAY(0, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new).a(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new).a(ClientboundAddMobPacket.class, ClientboundAddMobPacket::new).a(ClientboundAddPaintingPacket.class, ClientboundAddPaintingPacket::new).a(ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new).a(ClientboundAnimatePacket.class, ClientboundAnimatePacket::new).a(ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new).a(ClientboundBlockBreakAckPacket.class, ClientboundBlockBreakAckPacket::new).a(ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new).a(ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new).a(ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new).a(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new).a(ClientboundBossEventPacket.class, ClientboundBossEventPacket::new).a(ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new).a(ClientboundChatPacket.class, ClientboundChatPacket::new).a(ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new).a(ClientboundCommandsPacket.class, ClientboundCommandsPacket::new).a(ClientboundContainerAckPacket.class, ClientboundContainerAckPacket::new).a(ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new).a(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new).a(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new).a(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new).a(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new).a(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new).a(ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new).a(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new).a(ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new).a(ClientboundExplodePacket.class, ClientboundExplodePacket::new).a(ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new).a(ClientboundGameEventPacket.class, ClientboundGameEventPacket::new).a(ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new).a(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new).a(ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new).a(ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new).a(ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new).a(ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new).a(ClientboundLoginPacket.class, ClientboundLoginPacket::new).a(ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new).a(ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new).a(ClientboundMoveEntityPacket.Pos.class, ClientboundMoveEntityPacket.Pos::new).a(ClientboundMoveEntityPacket.PosRot.class, ClientboundMoveEntityPacket.PosRot::new).a(ClientboundMoveEntityPacket.Rot.class, ClientboundMoveEntityPacket.Rot::new).a(ClientboundMoveEntityPacket.class, ClientboundMoveEntityPacket::new).a(ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new).a(ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new).a(ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new).a(ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new).a(ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new).a(ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new).a(ClientboundPlayerCombatPacket.class, ClientboundPlayerCombatPacket::new).a(ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new).a(ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new).a(ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new).a(ClientboundRecipePacket.class, ClientboundRecipePacket::new).a(ClientboundRemoveEntitiesPacket.class, ClientboundRemoveEntitiesPacket::new).a(ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new).a(ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new).a(ClientboundRespawnPacket.class, ClientboundRespawnPacket::new).a(ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new).a(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new).a(ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new).a(ClientboundSetBorderPacket.class, ClientboundSetBorderPacket::new).a(ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new).a(ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new).a(ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new).a(ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new).a(ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new).a(ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new).a(ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new).a(ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new).a(ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new).a(ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new).a(ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new).a(ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new).a(ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new).a(ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new).a(ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new).a(ClientboundSetScorePacket.class, ClientboundSetScorePacket::new).a(ClientboundSetTimePacket.class, ClientboundSetTimePacket::new).a(ClientboundSetTitlesPacket.class, ClientboundSetTitlesPacket::new).a(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new).a(ClientboundSoundPacket.class, ClientboundSoundPacket::new).a(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new).a(ClientboundTabListPacket.class, ClientboundTabListPacket::new).a(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new).a(ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new).a(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new).a(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new).a(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new).a(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new).a(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new).a(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new)).a(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new).a(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new).a(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new).a(ServerboundChatPacket.class, ServerboundChatPacket::new).a(ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new).a(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new).a(ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new).a(ServerboundContainerAckPacket.class, ServerboundContainerAckPacket::new).a(ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new).a(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new).a(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new).a(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new).a(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new).a(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new).a(ServerboundInteractPacket.class, ServerboundInteractPacket::new).a(ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new).a(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new).a(ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new).a(ServerboundMovePlayerPacket.Pos.class, ServerboundMovePlayerPacket.Pos::new).a(ServerboundMovePlayerPacket.PosRot.class, ServerboundMovePlayerPacket.PosRot::new).a(ServerboundMovePlayerPacket.Rot.class, ServerboundMovePlayerPacket.Rot::new).a(ServerboundMovePlayerPacket.class, ServerboundMovePlayerPacket::new).a(ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new).a(ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new).a(ServerboundPickItemPacket.class, ServerboundPickItemPacket::new).a(ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new).a(ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new).a(ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new).a(ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new).a(ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new).a(ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new).a(ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new).a(ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new).a(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new).a(ServerboundSeenAdvancementsPacket.class, ServerboundSeenAdvancementsPacket::new).a(ServerboundSelectTradePacket.class, ServerboundSelectTradePacket::new).a(ServerboundSetBeaconPacket.class, ServerboundSetBeaconPacket::new).a(ServerboundSetCarriedItemPacket.class, ServerboundSetCarriedItemPacket::new).a(ServerboundSetCommandBlockPacket.class, ServerboundSetCommandBlockPacket::new).a(ServerboundSetCommandMinecartPacket.class, ServerboundSetCommandMinecartPacket::new).a(ServerboundSetCreativeModeSlotPacket.class, ServerboundSetCreativeModeSlotPacket::new).a(ServerboundSetJigsawBlockPacket.class, ServerboundSetJigsawBlockPacket::new).a(ServerboundSetStructureBlockPacket.class, ServerboundSetStructureBlockPacket::new).a(ServerboundSignUpdatePacket.class, ServerboundSignUpdatePacket::new).a(ServerboundSwingPacket.class, ServerboundSwingPacket::new).a(ServerboundTeleportToEntityPacket.class, ServerboundTeleportToEntityPacket::new).a(ServerboundUseItemOnPacket.class, ServerboundUseItemOnPacket::new).a(ServerboundUseItemPacket.class, ServerboundUseItemPacket::new))), STATUS(1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new).a(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)).a(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new).a(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new))), LOGIN(2, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new).a(ClientboundHelloPacket.class, ClientboundHelloPacket::new).a(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new).a(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new).a(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new)).a(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new).a(ServerboundKeyPacket.class, ServerboundKeyPacket::new).a(ServerboundCustomQueryPacket.class, ServerboundCustomQueryPacket::new))); ++ // Paper - fix decompile error - add generic names to < > like PacketListenerPlayOut ++ HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))), PLAY(0, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new).addPacket(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new).addPacket(ClientboundAddMobPacket.class, ClientboundAddMobPacket::new).addPacket(ClientboundAddPaintingPacket.class, ClientboundAddPaintingPacket::new).addPacket(ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new).addPacket(ClientboundAnimatePacket.class, ClientboundAnimatePacket::new).addPacket(ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new).addPacket(ClientboundBlockBreakAckPacket.class, ClientboundBlockBreakAckPacket::new).addPacket(ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new).addPacket(ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new).addPacket(ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new).addPacket(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new).addPacket(ClientboundBossEventPacket.class, ClientboundBossEventPacket::new).addPacket(ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new).addPacket(ClientboundChatPacket.class, ClientboundChatPacket::new).addPacket(ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new).addPacket(ClientboundCommandsPacket.class, ClientboundCommandsPacket::new).addPacket(ClientboundContainerAckPacket.class, ClientboundContainerAckPacket::new).addPacket(ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new).addPacket(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new).addPacket(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new).addPacket(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new).addPacket(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new).addPacket(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new).addPacket(ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new).addPacket(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new).addPacket(ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new).addPacket(ClientboundExplodePacket.class, ClientboundExplodePacket::new).addPacket(ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new).addPacket(ClientboundGameEventPacket.class, ClientboundGameEventPacket::new).addPacket(ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new).addPacket(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new).addPacket(ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new).addPacket(ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new).addPacket(ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new).addPacket(ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new).addPacket(ClientboundLoginPacket.class, ClientboundLoginPacket::new).addPacket(ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new).addPacket(ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new).addPacket(ClientboundMoveEntityPacket.Pos.class, ClientboundMoveEntityPacket.Pos::new).addPacket(ClientboundMoveEntityPacket.PosRot.class, ClientboundMoveEntityPacket.PosRot::new).addPacket(ClientboundMoveEntityPacket.Rot.class, ClientboundMoveEntityPacket.Rot::new).addPacket(ClientboundMoveEntityPacket.class, ClientboundMoveEntityPacket::new).addPacket(ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new).addPacket(ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new).addPacket(ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new).addPacket(ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new).addPacket(ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new).addPacket(ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new).addPacket(ClientboundPlayerCombatPacket.class, ClientboundPlayerCombatPacket::new).addPacket(ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new).addPacket(ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new).addPacket(ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new).addPacket(ClientboundRecipePacket.class, ClientboundRecipePacket::new).addPacket(ClientboundRemoveEntitiesPacket.class, ClientboundRemoveEntitiesPacket::new).addPacket(ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new).addPacket(ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new).addPacket(ClientboundRespawnPacket.class, ClientboundRespawnPacket::new).addPacket(ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new).addPacket(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new).addPacket(ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new).addPacket(ClientboundSetBorderPacket.class, ClientboundSetBorderPacket::new).addPacket(ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new).addPacket(ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new).addPacket(ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new).addPacket(ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new).addPacket(ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new).addPacket(ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new).addPacket(ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new).addPacket(ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new).addPacket(ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new).addPacket(ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new).addPacket(ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new).addPacket(ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new).addPacket(ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new).addPacket(ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new).addPacket(ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new).addPacket(ClientboundSetScorePacket.class, ClientboundSetScorePacket::new).addPacket(ClientboundSetTimePacket.class, ClientboundSetTimePacket::new).addPacket(ClientboundSetTitlesPacket.class, ClientboundSetTitlesPacket::new).addPacket(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new).addPacket(ClientboundSoundPacket.class, ClientboundSoundPacket::new).addPacket(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new).addPacket(ClientboundTabListPacket.class, ClientboundTabListPacket::new).addPacket(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new).addPacket(ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new).addPacket(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new).addPacket(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new).addPacket(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new).addPacket(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new).addPacket(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new).addPacket(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new).addPacket(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new).addPacket(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new).addPacket(ServerboundChatPacket.class, ServerboundChatPacket::new).addPacket(ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new).addPacket(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new).addPacket(ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new).addPacket(ServerboundContainerAckPacket.class, ServerboundContainerAckPacket::new).addPacket(ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new).addPacket(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new).addPacket(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new).addPacket(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new).addPacket(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new).addPacket(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new).addPacket(ServerboundInteractPacket.class, ServerboundInteractPacket::new).addPacket(ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new).addPacket(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new).addPacket(ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new).addPacket(ServerboundMovePlayerPacket.Pos.class, ServerboundMovePlayerPacket.Pos::new).addPacket(ServerboundMovePlayerPacket.PosRot.class, ServerboundMovePlayerPacket.PosRot::new).addPacket(ServerboundMovePlayerPacket.Rot.class, ServerboundMovePlayerPacket.Rot::new).addPacket(ServerboundMovePlayerPacket.class, ServerboundMovePlayerPacket::new).addPacket(ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new).addPacket(ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new).addPacket(ServerboundPickItemPacket.class, ServerboundPickItemPacket::new).addPacket(ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new).addPacket(ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new).addPacket(ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new).addPacket(ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new).addPacket(ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new).addPacket(ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new).addPacket(ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new).addPacket(ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new).addPacket(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new).addPacket(ServerboundSeenAdvancementsPacket.class, ServerboundSeenAdvancementsPacket::new).addPacket(ServerboundSelectTradePacket.class, ServerboundSelectTradePacket::new).addPacket(ServerboundSetBeaconPacket.class, ServerboundSetBeaconPacket::new).addPacket(ServerboundSetCarriedItemPacket.class, ServerboundSetCarriedItemPacket::new).addPacket(ServerboundSetCommandBlockPacket.class, ServerboundSetCommandBlockPacket::new).addPacket(ServerboundSetCommandMinecartPacket.class, ServerboundSetCommandMinecartPacket::new).addPacket(ServerboundSetCreativeModeSlotPacket.class, ServerboundSetCreativeModeSlotPacket::new).addPacket(ServerboundSetJigsawBlockPacket.class, ServerboundSetJigsawBlockPacket::new).addPacket(ServerboundSetStructureBlockPacket.class, ServerboundSetStructureBlockPacket::new).addPacket(ServerboundSignUpdatePacket.class, ServerboundSignUpdatePacket::new).addPacket(ServerboundSwingPacket.class, ServerboundSwingPacket::new).addPacket(ServerboundTeleportToEntityPacket.class, ServerboundTeleportToEntityPacket::new).addPacket(ServerboundUseItemOnPacket.class, ServerboundUseItemOnPacket::new).addPacket(ServerboundUseItemPacket.class, ServerboundUseItemPacket::new))), STATUS(1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new).addPacket(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)).addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new).addPacket(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new))), LOGIN(2, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new).addPacket(ClientboundHelloPacket.class, ClientboundHelloPacket::new).addPacket(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new).addPacket(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new).addPacket(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new).addPacket(ServerboundKeyPacket.class, ServerboundKeyPacket::new).addPacket(ServerboundCustomQueryPacket.class, ServerboundCustomQueryPacket::new))); + + private static final ConnectionProtocol[] LOOKUP = new ConnectionProtocol[4]; + private static final Map>, ConnectionProtocol> PROTOCOL_BY_PACKET = Maps.newHashMap(); +@@ -115,7 +121,7 @@ public enum ConnectionProtocol { + private final List>> idToConstructor; + + private PacketSet() { +- this.classToId = (Object2IntMap) Util.make((Object) (new Object2IntOpenHashMap()), (object2intopenhashmap) -> { ++ this.classToId = (Object2IntMap) Util.make(new Object2IntOpenHashMap(), (object2intopenhashmap) -> { // Paper - fix decompile error + object2intopenhashmap.defaultReturnValue(-1); + }); + this.idToConstructor = Lists.newArrayList(); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 21f461ce884bc547dbe81c5430be530423c1605c..37a51dee4cd37844e80fdd5c9853947201151dfc 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1673,9 +1673,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoopmap(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error + }, this).thenCompose((immutablelist) -> { +- return ServerResources.loadResources(immutablelist, this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this); ++ return ServerResources.loadResources(immutablelist, this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this); // Paper - decompile error + }).thenAcceptAsync((datapackresources) -> { + this.resources.close(); + this.resources = datapackresources; +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 37e938b258ee4eb5f5bab56145e83b640d80bcc7..23506a8903ce64fbfe849bb94e589bdbb6e61a74 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1913,7 +1913,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + // CraftBukkit - decompile error +- return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(it.unimi.dsi.fastutil.objects.Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { ++ return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { // Paper - decompile fix + return it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey() + ":" + it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue(); + }).collect(Collectors.joining(",")); + } catch (Exception exception) { +diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java +index ad8a9d14e17b5e40b2cc3a83154931734d6c73d7..cc4190b3a8904d1eaae0f542a3b3090583f5ff82 100644 +--- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java ++++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java +@@ -179,9 +179,9 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl + + public void tryScheduleUpdate() { + if ((!this.lightTasks.isEmpty() || super.hasLightWork()) && this.scheduled.compareAndSet(false, true)) { +- this.taskMailbox.tell((Object) (() -> { +- this.b(); +- this.g.set(false); ++ this.taskMailbox.tell((() -> { // Paper - decompile error ++ this.runUpdate(); ++ this.scheduled.set(false); + })); + } + +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index 90df41ec5081fe4ef2bc507e7289b18e0fea6e53..0c118d482e304c567fe7fe778c6ff386f960bdde 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -23,7 +23,7 @@ public final class Ticket implements Comparable> { + } else { + int j = Integer.compare(System.identityHashCode(this.type), System.identityHashCode(ticket.type)); + +- return j != 0 ? j : this.type.getComparator().compare(this.key, ticket.key); ++ return j != 0 ? j : this.type.getComparator().compare(this.key, (T)ticket.key); // Paper - decompile fix + } + } + +diff --git a/src/main/java/net/minecraft/stats/ServerStatsCounter.java b/src/main/java/net/minecraft/stats/ServerStatsCounter.java +index d624c390f8550c6aa44ca5920d127c901903ce27..7d435998680a363ad06c2e08139010c2573f7fb3 100644 +--- a/src/main/java/net/minecraft/stats/ServerStatsCounter.java ++++ b/src/main/java/net/minecraft/stats/ServerStatsCounter.java +@@ -203,7 +203,7 @@ public class ServerStatsCounter extends StatsCounter { + ObjectIterator objectiterator = this.stats.object2IntEntrySet().iterator(); + + while (objectiterator.hasNext()) { +- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); ++ Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix + Stat statistic = (Stat) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); + + ((JsonObject) map.computeIfAbsent(statistic.getType(), (statisticwrapper) -> { +diff --git a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java +index 74eb1ed6b3fafeaca7e65a88a982d759d6836853..66ad412e4368a8615cc66a97ac442c572813a3dd 100644 +--- a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java ++++ b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java +@@ -18,11 +18,18 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + + public CrudeIncrementalIntIdentityHashBiMap(int size) { + size = (int) ((float) size / 0.8F); +- this.keys = (Object[]) (new Object[size]); ++ this.keys = (K[]) (new Object[size]); // Paper - decompile fix + this.values = new int[size]; +- this.byId = (Object[]) (new Object[size]); ++ this.byId = (K[]) (new Object[size]); // Paper - decompile fix + } + ++ // Paper start - decompile fix ++ @Override ++ public int a(K k) { ++ return getId(k); ++ } ++ // Paper end ++ + public int getId(@Nullable K entry) { + return this.getValue(this.indexOf(entry, this.hash(entry))); + } +@@ -56,9 +63,9 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + K[] ak = this.keys; + int[] aint = this.values; + +- this.keys = (Object[]) (new Object[newSize]); ++ this.keys = (K[]) (new Object[newSize]); // Paper - decompile fix + this.values = new int[newSize]; +- this.byId = (Object[]) (new Object[newSize]); ++ this.byId = (K[]) (new Object[newSize]); // Paper - decompile fix + this.nextId = 0; + this.size = 0; + +diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java +index be40fc388c501c311d661927025f1c572f3b3493..93813a508be1e1e600a8211f9822f2087328de70 100644 +--- a/src/main/java/net/minecraft/util/SortedArraySet.java ++++ b/src/main/java/net/minecraft/util/SortedArraySet.java +@@ -23,11 +23,11 @@ public class SortedArraySet extends AbstractSet { + } + + public static > SortedArraySet create(int initialCapacity) { +- return new SortedArraySet<>(initialCapacity, Comparator.naturalOrder()); ++ return new SortedArraySet<>(initialCapacity, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix + } + + private static T[] castRawArray(Object[] array) { +- return (Object[]) array; ++ return (T[])array; // Paper - decompile fix + } + + private int findIndex(T object) { +@@ -101,7 +101,7 @@ public class SortedArraySet extends AbstractSet { + } + + public boolean remove(Object object) { +- int i = this.findIndex(object); ++ int i = this.findIndex((T)object); // Paper - decompile fix + + if (i >= 0) { + this.removeInternal(i); +@@ -116,7 +116,7 @@ public class SortedArraySet extends AbstractSet { + } + + public boolean contains(Object object) { +- int i = this.findIndex(object); ++ int i = this.findIndex((T)object); // Paper - decompile fix + + return i >= 0; + } +@@ -135,7 +135,7 @@ public class SortedArraySet extends AbstractSet { + + public U[] toArray(U[] au) { + if (au.length < this.size) { +- return (Object[]) Arrays.copyOf(this.contents, this.size, au.getClass()); ++ return (U[])Arrays.copyOf(this.contents, this.size, au.getClass()); // Paper - decompile fix + } else { + System.arraycopy(this.contents, 0, au, 0, this.size); + if (au.length > this.size) { +diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +index d9375f83de6d069f603f8a48cc5b02194e940052..03831adce7905916423d8c3834c42c90f3a1ca8f 100644 +--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java ++++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +@@ -55,7 +55,7 @@ public abstract class BlockableEventLoop implements Processo + return this.submitAsync(task); + } else { + task.run(); +- return CompletableFuture.completedFuture((Object) null); ++ return CompletableFuture.completedFuture(null); // Paper - decompile fix + } + } + +@@ -90,14 +90,14 @@ public abstract class BlockableEventLoop implements Processo + } + + protected boolean pollTask() { +- R r0 = (Runnable) this.pendingRunnables.peek(); ++ R r0 = this.pendingRunnables.peek(); // Paper - decompile fix + + if (r0 == null) { + return false; + } else if (this.blockingCount == 0 && !this.shouldRun(r0)) { + return false; + } else { +- this.doRunTask((Runnable) this.pendingRunnables.remove()); ++ this.doRunTask(this.pendingRunnables.remove()); // Paper - decompile fix + return true; + } + } +diff --git a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java +index cc77767947e458e7205e616dce3bea8da09ca0cf..c763aa0c0cf49dd844af94a820103258b49021ae 100644 +--- a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java ++++ b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java +@@ -100,7 +100,7 @@ public class ProcessorMailbox implements ProcessorHandle, AutoCloseable, R + + public void run() { + try { +- this.pollUntil((i) -> { ++ this.pollUntil((int i) -> { // Paper - decompile fix + return i == 0; + }); + } finally { +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +index 8f686f8608771d0a444dfd51dd4eabc90c6b2262..33a8604fa6c6431ccc5f61e484c163e09f1625a0 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +@@ -191,9 +191,9 @@ public class PoiManager extends SectionStorage { + } + + private static boolean mayHavePoi(LevelChunkSection chunksection) { +- Set set = PoiType.ALL_STATES; ++ Set set = PoiType.ALL_STATES; // Paper - decompile error + +- set.getClass(); ++ //set.getClass(); // Paper - decompile error + return chunksection.maybeHas(set::contains); + } + +@@ -211,7 +211,7 @@ public class PoiManager extends SectionStorage { + SectionPos.aroundChunk(new ChunkPos(pos), Math.floorDiv(radius, 16)).map((sectionposition) -> { + return Pair.of(sectionposition, this.getOrLoad(sectionposition.asLong())); + }).filter((pair) -> { +- return !(Boolean) ((Optional) pair.getSecond()).map(PoiSection::a).orElse(false); ++ return !(Boolean) (pair.getSecond()).map(PoiSection::isValid).orElse(false); // Paper - decompile fix + }).map((pair) -> { + return ((SectionPos) pair.getFirst()).chunk(); + }).filter((chunkcoordintpair) -> { +@@ -257,13 +257,13 @@ public class PoiManager extends SectionStorage { + + public static enum Occupancy { + +- HAS_SPACE(PoiRecord::d), IS_OCCUPIED(PoiRecord::e), ANY((villageplacerecord) -> { ++ HAS_SPACE(PoiRecord::hasSpace), IS_OCCUPIED(PoiRecord::isOccupied), ANY((villageplacerecord) -> { + return true; + }); + + private final Predicate test; + +- private Occupancy(Predicate predicate) { ++ private Occupancy(Predicate predicate) { // Paper - decompile fix + this.test = predicate; + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +index 97317517a729877e307407ca9fab5fa58657fe38..a41f61daf6cbbb13d0b86cdbad8a4cae00368653 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +@@ -65,7 +65,7 @@ public class Vindicator extends AbstractIllager { + this.goalSelector.addGoal(2, new AbstractIllager.RaiderOpenDoorGoal(this)); + this.goalSelector.addGoal(3, new Raider.HoldGroundAttackGoal(this, 10.0F)); + this.goalSelector.addGoal(4, new Vindicator.VindicatorMeleeAttackGoal(this)); +- this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).canUse()); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers(new Class[0])); // Paper - decompile fix + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); +diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +index ad4e181b24829980dc12f46807ec1c5226bd8e0c..fd1b84baae5f333c58dbbdcbfaa9198328f0961d 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java ++++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +@@ -47,12 +47,12 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + + public class VillagerTrades { + +- public static final Map> TRADES = (Map) Util.make((Object) Maps.newHashMap(), (hashmap) -> { ++ public static final Map> TRADES = Util.make(Maps.newHashMap(), (hashmap) -> { // Paper - decompile fix + hashmap.put(VillagerProfession.FARMER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WHEAT, 20, 16, 2), new VillagerTrades.EmeraldForItems(Items.POTATO, 26, 16, 2), new VillagerTrades.EmeraldForItems(Items.CARROT, 22, 16, 2), new VillagerTrades.EmeraldForItems(Items.BEETROOT, 15, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.BREAD, 1, 6, 16, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Blocks.PUMPKIN, 6, 12, 10), new VillagerTrades.ItemsForEmeralds(Items.PUMPKIN_PIE, 1, 4, 5), new VillagerTrades.ItemsForEmeralds(Items.APPLE, 1, 4, 16, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.COOKIE, 3, 18, 10), new VillagerTrades.EmeraldForItems(Blocks.MELON, 4, 12, 20)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Blocks.CAKE, 1, 1, 12, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.NIGHT_VISION, 100, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.JUMP, 160, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.WEAKNESS, 140, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.BLINDNESS, 120, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.POISON, 280, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.SATURATION, 7, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.GOLDEN_CARROT, 3, 3, 30), new VillagerTrades.ItemsForEmeralds(Items.GLISTERING_MELON_SLICE, 4, 3, 30)}))); +- hashmap.put(VillagerProfession.FISHERMAN, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STRING, 20, 16, 2), new VillagerTrades.EmeraldForItems(Items.COAL, 10, 16, 2), new VillagerTrades.ItemsAndEmeraldsToItems(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.ItemsForEmeralds(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COD, 15, 16, 10), new VillagerTrades.ItemsAndEmeraldsToItems(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.ItemsForEmeralds(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.SALMON, 13, 16, 20), new VillagerTrades.EnchantedItemForEmeralds(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.EmeraldsForVillagerTypeItem(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); ++ hashmap.put(VillagerProfession.FISHERMAN, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STRING, 20, 16, 2), new VillagerTrades.EmeraldForItems(Items.COAL, 10, 16, 2), new VillagerTrades.ItemsAndEmeraldsToItems(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.ItemsForEmeralds(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COD, 15, 16, 10), new VillagerTrades.ItemsAndEmeraldsToItems(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.ItemsForEmeralds(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.SALMON, 13, 16, 20), new VillagerTrades.EnchantedItemForEmeralds(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.EmeraldsForVillagerTypeItem(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); // Paper - add to ImmutableMap..builder() + hashmap.put(VillagerProfession.SHEPHERD, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Blocks.WHITE_WOOL, 18, 16, 2), new VillagerTrades.EmeraldForItems(Blocks.BROWN_WOOL, 18, 16, 2), new VillagerTrades.EmeraldForItems(Blocks.BLACK_WOOL, 18, 16, 2), new VillagerTrades.EmeraldForItems(Blocks.GRAY_WOOL, 18, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.SHEARS, 2, 1, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WHITE_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.GRAY_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.BLACK_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.LIGHT_BLUE_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.LIME_DYE, 12, 16, 10), new VillagerTrades.ItemsForEmeralds(Blocks.WHITE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.ORANGE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.MAGENTA_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.YELLOW_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIME_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PINK_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.CYAN_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PURPLE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BROWN_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GREEN_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.RED_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLACK_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.WHITE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.ORANGE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.MAGENTA_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.YELLOW_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIME_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PINK_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.CYAN_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PURPLE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BROWN_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GREEN_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.RED_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLACK_CARPET, 1, 4, 16, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.YELLOW_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.LIGHT_GRAY_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.ORANGE_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.RED_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.PINK_DYE, 12, 16, 20), new VillagerTrades.ItemsForEmeralds(Blocks.WHITE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.YELLOW_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.RED_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.BLACK_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.BLUE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.BROWN_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.CYAN_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.GRAY_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.GREEN_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_BLUE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_GRAY_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.LIME_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.MAGENTA_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.ORANGE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.PINK_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.PURPLE_BED, 3, 1, 12, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.BROWN_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.PURPLE_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.BLUE_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.GREEN_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.MAGENTA_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.CYAN_DYE, 12, 16, 30), new VillagerTrades.ItemsForEmeralds(Items.WHITE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.RED_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.PINK_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.GREEN_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.LIME_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.GRAY_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.BLACK_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.PURPLE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.MAGENTA_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.CYAN_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.BROWN_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.YELLOW_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.ORANGE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_GRAY_BANNER, 3, 1, 12, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.PAINTING, 2, 3, 30)}))); + hashmap.put(VillagerProfession.FLETCHER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STICK, 32, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.ARROW, 1, 16, 1), new VillagerTrades.ItemsAndEmeraldsToItems(Blocks.GRAVEL, 10, Items.FLINT, 10, 12, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.FLINT, 26, 12, 10), new VillagerTrades.ItemsForEmeralds(Items.BOW, 2, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STRING, 14, 16, 20), new VillagerTrades.ItemsForEmeralds(Items.CROSSBOW, 3, 1, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.FEATHER, 24, 16, 30), new VillagerTrades.EnchantedItemForEmeralds(Items.BOW, 2, 3, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.es, 8, 12, 30), new VillagerTrades.EnchantedItemForEmeralds(Items.CROSSBOW, 3, 3, 15), new VillagerTrades.TippedArrowForItemsAndEmeralds(Items.ARROW, 5, Items.TIPPED_ARROW, 5, 2, 12, 30)}))); +- hashmap.put(VillagerProfession.LIBRARIAN, toIntMap(ImmutableMap.builder().put(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PAPER, 24, 16, 2), new VillagerTrades.EnchantBookForEmeralds(1), new VillagerTrades.ItemsForEmeralds(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.BOOK, 4, 12, 10), new VillagerTrades.EnchantBookForEmeralds(5), new VillagerTrades.ItemsForEmeralds(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.INK_SAC, 5, 12, 20), new VillagerTrades.EnchantBookForEmeralds(10), new VillagerTrades.ItemsForEmeralds(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.EnchantBookForEmeralds(15), new VillagerTrades.ItemsForEmeralds(Items.CLOCK, 5, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.NAME_TAG, 20, 1, 30)}).build())); ++ hashmap.put(VillagerProfession.LIBRARIAN, toIntMap(ImmutableMap.builder().put(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PAPER, 24, 16, 2), new VillagerTrades.EnchantBookForEmeralds(1), new VillagerTrades.ItemsForEmeralds(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.BOOK, 4, 12, 10), new VillagerTrades.EnchantBookForEmeralds(5), new VillagerTrades.ItemsForEmeralds(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.INK_SAC, 5, 12, 20), new VillagerTrades.EnchantBookForEmeralds(10), new VillagerTrades.ItemsForEmeralds(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.EnchantBookForEmeralds(15), new VillagerTrades.ItemsForEmeralds(Items.CLOCK, 5, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.NAME_TAG, 20, 1, 30)}).build())); // Paper - add to ImmutableMap..builder() + hashmap.put(VillagerProfession.CARTOGRAPHER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PAPER, 24, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.MAP, 7, 1, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.dP, 11, 16, 10), new VillagerTrades.TreasureMapForEmeralds(13, StructureFeature.OCEAN_MONUMENT, MapDecoration.Type.MONUMENT, 12, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COMPASS, 1, 12, 20), new VillagerTrades.TreasureMapForEmeralds(14, StructureFeature.WOODLAND_MANSION, MapDecoration.Type.MANSION, 12, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.ITEM_FRAME, 7, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.WHITE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.BLUE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_BLUE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.RED_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.PINK_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.GREEN_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.LIME_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.GRAY_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.BLACK_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.PURPLE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.MAGENTA_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.CYAN_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.BROWN_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.YELLOW_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.ORANGE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_GRAY_BANNER, 3, 1, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.GLOBE_BANNER_PATTERN, 8, 1, 30)}))); + hashmap.put(VillagerProfession.CLERIC, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.ROTTEN_FLESH, 32, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.REDSTONE, 1, 2, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.GOLD_INGOT, 3, 12, 10), new VillagerTrades.ItemsForEmeralds(Items.LAPIS_LAZULI, 1, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.RABBIT_FOOT, 2, 12, 20), new VillagerTrades.ItemsForEmeralds(Blocks.GLOWSTONE, 4, 1, 12, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.SCUTE, 4, 12, 30), new VillagerTrades.EmeraldForItems(Items.GLASS_BOTTLE, 9, 12, 30), new VillagerTrades.ItemsForEmeralds(Items.ENDER_PEARL, 5, 1, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.NETHER_WART, 22, 12, 30), new VillagerTrades.ItemsForEmeralds(Items.EXPERIENCE_BOTTLE, 3, 1, 30)}))); + hashmap.put(VillagerProfession.ARMORER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COAL, 15, 16, 2), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_LEGGINGS), 7, 1, 12, 1, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_BOOTS), 4, 1, 12, 1, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_HELMET), 5, 1, 12, 1, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_CHESTPLATE), 9, 1, 12, 1, 0.2F)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.IRON_INGOT, 4, 12, 10), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.rj), 36, 1, 12, 5, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_BOOTS), 1, 1, 12, 5, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_LEGGINGS), 3, 1, 12, 5, 0.2F)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.LAVA_BUCKET, 1, 12, 20), new VillagerTrades.EmeraldForItems(Items.DIAMOND, 1, 12, 20), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_HELMET), 1, 1, 12, 10, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_CHESTPLATE), 4, 1, 12, 10, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.SHIELD), 5, 1, 12, 10, 0.2F)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_LEGGINGS, 14, 3, 15, 0.2F), new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_BOOTS, 8, 3, 15, 0.2F)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_HELMET, 8, 3, 30, 0.2F), new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_CHESTPLATE, 16, 3, 30, 0.2F)}))); +diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +index 86d7af20fad04405f95c71e078d41070abdc43ad..c4777997cfff364818fbaee70afd7c79099213fb 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java ++++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +@@ -75,7 +75,7 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { + } + + this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { +- return (entry1.getValue()); // CraftBukkit ++ return entry1.getValue(); // CraftBukkit // Paper - decompile fix - *shrugs internally* + })); + RecipeManager.LOGGER.info("Loaded {} recipes", map1.size()); + } +diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java +index 1276769b22ae21f0ff4271ecc72d4aa39ddff23f..7e7a58b9a9ececdcc37fc33b33703428eb1d5faf 100644 +--- a/src/main/java/net/minecraft/world/level/EntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/EntityGetter.java +@@ -167,22 +167,22 @@ public interface EntityGetter { + + @Nullable + default T getNearestEntity(Class entityClass, TargetingConditions targetPredicate, @Nullable LivingEntity entity, double x, double y, double z, AABB box) { +- return this.getNearestEntity(this.getEntitiesOfClass(entityClass, box, (Predicate) null), targetPredicate, entity, x, y, z); ++ return this.getNearestEntity(this.getEntitiesOfClass(entityClass, box, null), targetPredicate, entity, x, y, z); // Paper - decompile fix + } + + @Nullable + default T getNearestLoadedEntity(Class entityClass, TargetingConditions targetPredicate, @Nullable LivingEntity entity, double x, double y, double z, AABB box) { +- return this.getNearestEntity(this.getLoadedEntitiesOfClass(entityClass, box, (Predicate) null), targetPredicate, entity, x, y, z); ++ return this.getNearestEntity(this.getLoadedEntitiesOfClass(entityClass, box, null), targetPredicate, entity, x, y, z); // Paper - decompile fix + } + + @Nullable + default T getNearestEntity(List entityList, TargetingConditions targetPredicate, @Nullable LivingEntity entity, double x, double y, double z) { + double d3 = -1.0D; + T t0 = null; +- Iterator iterator = entityList.iterator(); ++ Iterator iterator = entityList.iterator(); // Paper - decompile fix + + while (iterator.hasNext()) { +- T t1 = (LivingEntity) iterator.next(); ++ T t1 = iterator.next(); // Paper - decompile fix + + if (targetPredicate.test(entity, t1)) { + double d4 = t1.distanceToSqr(x, y, z); +@@ -215,10 +215,10 @@ public interface EntityGetter { + default List getNearbyEntities(Class entityClass, TargetingConditions targetPredicate, LivingEntity targetingEntity, AABB box) { + List list = this.getEntitiesOfClass(entityClass, box, (Predicate) null); + List list1 = Lists.newArrayList(); +- Iterator iterator = list.iterator(); ++ Iterator iterator = list.iterator(); // Paper - decompile fix + + while (iterator.hasNext()) { +- T t0 = (LivingEntity) iterator.next(); ++ T t0 = iterator.next(); // Paper - decompile fix + + if (targetPredicate.test(targetingEntity, t0)) { + list1.add(t0); +diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java +index c6e64c5182d564664464e26df27e6b5f7da418e6..d97e266b83bb331fcd4031046a5843d29ce53164 100644 +--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java ++++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java +@@ -38,13 +38,13 @@ public class TickNextTickData { + return this.pos.hashCode(); + } + +- public static Comparator> createTimeComparator() { ++ public static Comparator createTimeComparator() { // Paper - decompile fix + return Comparator.comparingLong((nextticklistentry) -> { +- return nextticklistentry.b; ++ return ((TickNextTickData) nextticklistentry).triggerTick; // Paper - decompile fix + }).thenComparing((nextticklistentry) -> { +- return nextticklistentry.c; ++ return ((TickNextTickData) nextticklistentry).priority; // Paper - decompile fix + }).thenComparingLong((nextticklistentry) -> { +- return nextticklistentry.f; ++ return ((TickNextTickData) nextticklistentry).c; // Paper - decompile fix + }); + } + +diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java +index 79be56c26b66351bcfcd96c9967f0ce91e40d5ce..ed83335175bb882741dfaef251ab30ce1590f74c 100644 +--- a/src/main/java/net/minecraft/world/level/biome/Biome.java ++++ b/src/main/java/net/minecraft/world/level/biome/Biome.java +@@ -49,36 +49,43 @@ import org.apache.logging.log4j.Logger; + public final class Biome { + + public static final Logger LOGGER = LogManager.getLogger(); ++ // Paper start ++ private static class dProxy extends Biome.ClimateSettings { ++ private dProxy(Precipitation precipitation, float temperature, TemperatureModifier temperatureModifier, float downfall) { ++ super(precipitation, temperature, temperatureModifier, downfall); ++ } ++ }; ++ // Paper end + public static final Codec DIRECT_CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { +- return biomebase.j; ++ return instance.group(dProxy.CODEC.forGetter((biomebase) -> { // Paper ++ return biomebase.climateSettings; + }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biomebase) -> { +- return biomebase.o; ++ return biomebase.biomeCategory; + }), Codec.FLOAT.fieldOf("depth").forGetter((biomebase) -> { +- return biomebase.m; ++ return biomebase.depth; + }), Codec.FLOAT.fieldOf("scale").forGetter((biomebase) -> { +- return biomebase.n; ++ return biomebase.scale; + }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biomebase) -> { +- return biomebase.p; ++ return biomebase.specialEffects; + }), BiomeGenerationSettings.CODEC.forGetter((biomebase) -> { +- return biomebase.k; ++ return biomebase.generationSettings; + }), MobSpawnSettings.CODEC.forGetter((biomebase) -> { +- return biomebase.l; ++ return biomebase.mobSettings; + })).apply(instance, Biome::new); + }); + public static final Codec NETWORK_CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { +- return biomebase.j; ++ return instance.group(dProxy.CODEC.forGetter((biomebase) -> { // Paper ++ return biomebase.climateSettings; + }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biomebase) -> { +- return biomebase.o; ++ return biomebase.biomeCategory; + }), Codec.FLOAT.fieldOf("depth").forGetter((biomebase) -> { +- return biomebase.m; ++ return biomebase.depth; + }), Codec.FLOAT.fieldOf("scale").forGetter((biomebase) -> { +- return biomebase.n; ++ return biomebase.scale; + }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biomebase) -> { +- return biomebase.p; ++ return biomebase.specialEffects; + })).apply(instance, (biomebase_d, biomebase_geography, ofloat, ofloat1, biomefog) -> { +- return new BiomeBase(biomebase_d, biomebase_geography, ofloat, ofloat1, biomefog, BiomeSettingsGeneration.b, BiomeSettingsMobs.b); ++ return new Biome(biomebase_d, biomebase_geography, ofloat, ofloat1, biomefog, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY); + }); + }); + public static final Codec> CODEC = RegistryFileCodec.a(Registry.BIOME_REGISTRY, Biome.DIRECT_CODEC); +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +index 94a02cb23a210ee0cc789db15853b6672ec673f4..73888713746e7ddd72ba9ac9d33d8e616eb3bd25 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +@@ -160,7 +160,7 @@ public class PistonMovingBlockEntity extends BlockEntity implements TickableBloc + private static void moveEntityByPiston(Direction enumdirection, Entity entity, double d0, Direction enumdirection1) { + PistonMovingBlockEntity.NOCLIP.set(enumdirection); + entity.move(MoverType.PISTON, new Vec3(d0 * (double) enumdirection1.getStepX(), d0 * (double) enumdirection1.getStepY(), d0 * (double) enumdirection1.getStepZ())); +- PistonMovingBlockEntity.NOCLIP.set((Object) null); ++ PistonMovingBlockEntity.NOCLIP.set(null); // Paper - decompile fix + } + + private void moveStuckEntities(float f) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java +index 95ad396fc46a587d08b87943aa05dd72d35efd3a..60ce75c7f94c995d3753c40bc8d1ec09b4d37b1a 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java ++++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java +@@ -28,12 +28,12 @@ public abstract class StateHolder { + } else { + Property iblockstate = (Property) entry.getKey(); + +- return iblockstate.getName() + "=" + this.getName(iblockstate, (Comparable) entry.getValue()); ++ return iblockstate.getName() + "=" + this.getName((Property) iblockstate, (Comparable) entry.getValue()); // Paper - decompile fix + } + } + +- private > String getName(Property property, Comparable value) { +- return property.value(value); ++ private > String getName(Property property, T value) { // Paper - decompile error ++ return property.getName(value); + } + }; + protected final O owner; +@@ -48,11 +48,11 @@ public abstract class StateHolder { + } + + public > S cycle(Property property) { +- return this.setValue(property, (Comparable) findNextInCollection(property.getPossibleValues(), (Object) this.getValue(property))); ++ return this.setValue(property, findNextInCollection(property.getPossibleValues(), this.getValue(property))); // Paper - decompile error + } + + protected static T findNextInCollection(Collection values, T value) { +- Iterator iterator = values.iterator(); ++ Iterator iterator = values.iterator(); // Paper + + do { + if (!iterator.hasNext()) { +@@ -94,7 +94,7 @@ public abstract class StateHolder { + if (comparable == null) { + throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner); + } else { +- return (Comparable) property.getValueClass().cast(comparable); ++ return property.getValueClass().cast(comparable); // Paper - decompile error + } + } + +@@ -110,7 +110,7 @@ public abstract class StateHolder { + if (comparable == null) { + throw new IllegalArgumentException("Cannot set property " + property + " as it does not exist in " + this.owner); + } else if (comparable == value) { +- return this; ++ return (S) this; // Paper - decompile error + } else { + S s0 = this.neighbours.get(property, value); + +@@ -162,7 +162,7 @@ public abstract class StateHolder { + return codec.dispatch("Name", (iblockdataholder) -> { + return iblockdataholder.owner; + }, (object) -> { +- S s0 = (StateHolder) ownerToStateFunction.apply(object); ++ S s0 = ownerToStateFunction.apply(object); // Paper - decompile error + + return s0.getValues().isEmpty() ? Codec.unit(s0) : s0.propertiesCodec.fieldOf("Properties").codec(); + }); +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +index 9e0724c4bf06d207898e477e35412c09f3aa0f74..b5817645727f2af2785e0987ba824f431d4e9e32 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +@@ -21,10 +21,10 @@ public class EnumProperty & StringRepresentable> extends Prope + protected EnumProperty(String name, Class type, Collection values) { + super(name, type); + this.values = ImmutableSet.copyOf(values); +- Iterator iterator = values.iterator(); ++ Iterator iterator = values.iterator(); // Paper - decompile fix + + while (iterator.hasNext()) { +- T t0 = (Enum) iterator.next(); ++ T t0 = iterator.next(); // Paper - Decompile fix + String s1 = ((StringRepresentable) t0).getSerializedName(); + + if (this.names.containsKey(s1)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java +index 5a16a0079bc297fb4572d2e6e9b07a9d1a53c906..8cc07c70fde81e44679f3ea7d9a4c6b2447885d4 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java +@@ -17,12 +17,10 @@ public abstract class Property> { + private final Codec> valueCodec; + + protected Property(String name, Class type) { +- this.codec = Codec.STRING.comapFlatMap((s1) -> { +- return (DataResult) this.getValue(s1).map(DataResult::success).orElseGet(() -> { +- return DataResult.error("Unable to read property: " + this + " with value: " + s1); +- }); +- }, this::getName); +- this.valueCodec = this.codec.xmap(this::b, Property.clazz::b); ++ this.codec = Codec.STRING.comapFlatMap((s1) -> this.getValue(s1).map(DataResult::success).orElseGet(() -> { // Paper - decompile error ++ return DataResult.error("Unable to read property: " + this + " with value: " + s1); ++ }), this::getName); ++ this.valueCodec = this.codec.xmap(this::value, (Property.Value param) -> param.value()); // Paper - decompile fix + this.clazz = type; + this.name = name; + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +index 977ac6db5fbdd001c306ee6aa396bb395384dd8f..7de765786b3504dcffab98bb0d9dac64b30b3325 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +@@ -89,7 +89,7 @@ public class IOWorker implements AutoCloseable { + return this.submitTask(() -> { + try { + this.storage.flush(); +- return Either.left((Object) null); ++ return Either.left(null); // Paper - decompile error + } catch (Exception exception) { + IOWorker.LOGGER.warn("Failed to synchronized chunks", exception); + return Either.right(exception); +@@ -123,13 +123,13 @@ public class IOWorker implements AutoCloseable { + } + + private void tellStorePending() { +- this.mailbox.tell((Object) (new StrictQueue.IntRunnable(IOWorker.Priority.LOW.ordinal(), this::storePendingChunk))); ++ this.mailbox.tell((new StrictQueue.IntRunnable(IOWorker.Priority.LOW.ordinal(), this::storePendingChunk))); // Paper - decompile error + } + + private void runStore(ChunkPos pos, IOWorker.PendingStore ioworker_a) { + try { + this.storage.write(pos, ioworker_a.data); +- ioworker_a.result.complete((Object) null); ++ ioworker_a.result.complete(null); // Paper - decompile fix + } catch (Exception exception) { + IOWorker.LOGGER.error("Failed to store chunk {}", pos, exception); + ioworker_a.result.completeExceptionally(exception); +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 217065b88178342159154490ffabe0fe7d32d7bf..2386ffeec60851ba192b89bc6fd7ffff9c56aff5 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -430,7 +430,7 @@ public class EndDragonFight { + } + } + +- worldgenendtrophy.configured((FeatureConfiguration) FeatureConfiguration.NONE).a(this.level, this.level.getChunkSource().getGenerator(), new Random(), this.portalLocation); ++ worldgenendtrophy.configured(FeatureConfiguration.NONE).place(this.level, this.level.getChunkSource().getGenerator(), new Random(), this.portalLocation); // Paper - decompile fix + } + + private EnderDragon createNewDragon() { +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +index 418abfdc85de157d23807059670a2dfc964cbd5f..9f60abfe0a37e30c5528a1ca0546295b00598798 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +@@ -71,13 +71,13 @@ public abstract class StructureFeature { + public static final StructureFeature BASTION_REMNANT = register("Bastion_Remnant", new BastionFeature(JigsawConfiguration.CODEC), GenerationStep.Decoration.SURFACE_STRUCTURES); + public static final List> NOISE_AFFECTING_FEATURES = ImmutableList.of(StructureFeature.PILLAGER_OUTPOST, StructureFeature.VILLAGE, StructureFeature.NETHER_FOSSIL); + private static final ResourceLocation JIGSAW_RENAME = new ResourceLocation("jigsaw"); +- private static final Map RENAMES = ImmutableMap.builder().put(new ResourceLocation("nvi"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("pcp"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("bastionremnant"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("runtime"), StructureFeature.JIGSAW_RENAME).build(); ++ private static final Map RENAMES = ImmutableMap.builder().put(new ResourceLocation("nvi"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("pcp"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("bastionremnant"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("runtime"), StructureFeature.JIGSAW_RENAME).build(); // Paper - decompile fix + private final Codec>> y; + + private static > F register(String name, F structureFeature, GenerationStep.Decoration step) { + StructureFeature.STRUCTURES_REGISTRY.put(name.toLowerCase(Locale.ROOT), structureFeature); + StructureFeature.STEP.put(structureFeature, step); +- return (StructureFeature) Registry.registerDefaulted(Registry.STRUCTURE_FEATURE, name.toLowerCase(Locale.ROOT), (Object) structureFeature); ++ return (F) Registry.>register(Registry.STRUCTURE_FEATURE, name.toLowerCase(Locale.ROOT), structureFeature); // Paper - decomp fix + } + + public StructureFeature(Codec codec) { +diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +index cd2efdd5802605de5d3d636ce1b4a796e0c13310..c304637ae8f80c65b58e8ba8a27609b532bb1184 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +@@ -34,10 +34,10 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage= l) { +diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +index b106f2458361fc2a9168bbef8c9e5b35d8e359fb..60b7fdf9c092e8105d41f4af02a08651624f3eb9 100644 +--- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +@@ -44,7 +44,7 @@ public class DimensionDataStorage { + if (t0 != null) { + return t0; + } else { +- T t1 = (SavedData) factory.get(); ++ T t1 = factory.get(); // Paper - decompile fix + + this.set(t1); + return t1; +@@ -53,7 +53,7 @@ public class DimensionDataStorage { + + @Nullable + public T get(Supplier factory, String id) { +- SavedData persistentbase = (SavedData) this.cache.get(id); ++ T persistentbase = (T) this.cache.get(id); // Paper - decompile fix + + if (persistentbase == null && !this.cache.containsKey(id)) { + persistentbase = this.readSavedData(factory, id); +@@ -69,7 +69,7 @@ public class DimensionDataStorage { + File file = this.getDataFile(id); + + if (file.exists()) { +- T t0 = (SavedData) factory.get(); ++ T t0 = factory.get(); // Paper - decompile fix + CompoundTag nbttagcompound = this.readTagFromDisk(id, SharedConstants.getCurrentVersion().getWorldVersion()); + + t0.load(nbttagcompound.getCompound("data")); +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java +index 4093a4a1f924ac722d60599be9688a88d26a5c1a..802eb7fe690adae03c80db3fc0f72ea2788a3b2c 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java +@@ -42,7 +42,7 @@ public abstract class LootPoolEntryContainer implements ComposableEntryContainer + + // CraftBukkit start + @Override +- public final void serialize(JsonObject json, T entry, JsonSerializationContext context) { ++ public void serialize(JsonObject json, T entry, JsonSerializationContext context) { // Paper - remove final + if (!org.apache.commons.lang3.ArrayUtils.isEmpty(entry.conditions)) { + json.add("conditions", context.serialize(entry.conditions)); + } +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java +index c942459e0a492dd9fab296ef60d272651d13f049..ceb5e5405ed20c8de954847bbb269109107a43fc 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java +@@ -132,7 +132,7 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer + @Override + public T b(LootItemFunction.Builder lootitemfunction_a) { + this.functions.add(lootitemfunction_a.b()); +- return (LootPoolSingletonContainer.Builder) this.getThis(); ++ return this.getThis(); // Paper - decompile fix + } + + protected LootItemFunction[] getFunctions() { +@@ -141,12 +141,12 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer + + public T setWeight(int weight) { + this.weight = weight; +- return (LootPoolSingletonContainer.Builder) this.getThis(); ++ return this.getThis(); // Paper - decompile fix + } + + public T setQuality(int quality) { + this.quality = quality; +- return (LootPoolSingletonContainer.Builder) this.getThis(); ++ return this.getThis(); // Paper - decompile fix + } + } + +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java +index b77c921548ff55bab62bf37fa411ad1fd8d38f82..a3ce120b0da62f9be938c58c3414ce997f5d30ea 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java +@@ -89,7 +89,7 @@ public class ExplorationMapFunction extends LootItemConditionalFunction { + public Serializer() {} + + public void serialize(JsonObject json, ExplorationMapFunction object, JsonSerializationContext context) { +- super.serialize(json, (LootItemConditionalFunction) object, context); ++ super.serialize(json, object, context); // Paper - decompile fix + if (!object.destination.equals(ExplorationMapFunction.DEFAULT_FEATURE)) { + json.add("destination", context.serialize(object.destination.getFeatureName())); + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java +index bc1798f130184d6b107d7a9ba972cab686534439..f0e74daa5bb9e88c028225e7c71deb04c481a7ac 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java +@@ -38,7 +38,7 @@ public final class IndirectMerger implements IndexMerger { + double d1 = flag4 ? first.getDouble(i++) : second.getDouble(j++); + + if ((i != 0 && flag2 || flag4 || includeSecondOnly) && (j != 0 && flag3 || !flag4 || includeFirstOnly)) { +- if (d0 < d1 - 1.0E-7D) { ++ if (!(d0 >= d1 - 1.0E-7D)) { // Paper - decompile error - welcome to hell + this.firstIndices.add(i - 1); + this.secondIndices.add(j - 1); + this.result.add(d1); diff --git a/patches/server-remapped/0004-MC-Utils.patch b/patches/server-remapped/0004-MC-Utils.patch new file mode 100644 index 0000000000..cccd5824cd --- /dev/null +++ b/patches/server-remapped/0004-MC-Utils.patch @@ -0,0 +1,4859 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 20:55:47 -0400 +Subject: [PATCH] MC Utils + + +diff --git a/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4029dc68cf35d63aa70c4a76c35bf65a7fc6358f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java +@@ -0,0 +1,68 @@ ++package com.destroystokyo.paper.util.concurrent; ++ ++import java.util.concurrent.atomic.AtomicLong; ++ ++/** ++ * copied from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/lock/WeakSeqLock.java ++ * @author Spottedleaf ++ */ ++public final class WeakSeqLock { ++ // TODO when the switch to J11 is made, nuke this class from orbit ++ ++ protected final AtomicLong lock = new AtomicLong(); ++ ++ public WeakSeqLock() { ++ //VarHandle.storeStoreFence(); // warn: usages must be checked to ensure this behaviour isn't needed ++ } ++ ++ public void acquireWrite() { ++ // must be release-type write ++ this.lock.lazySet(this.lock.get() + 1); ++ } ++ ++ public boolean canRead(final long read) { ++ return (read & 1) == 0; ++ } ++ ++ public boolean tryAcquireWrite() { ++ this.acquireWrite(); ++ return true; ++ } ++ ++ public void releaseWrite() { ++ // must be acquire-type write ++ final long lock = this.lock.get(); // volatile here acts as store-store ++ this.lock.lazySet(lock + 1); ++ } ++ ++ public void abortWrite() { ++ // must be acquire-type write ++ final long lock = this.lock.get(); // volatile here acts as store-store ++ this.lock.lazySet(lock ^ 1); ++ } ++ ++ public long acquireRead() { ++ int failures = 0; ++ long curr; ++ ++ for (curr = this.lock.get(); !this.canRead(curr); curr = this.lock.get()) { ++ // without j11, our only backoff is the yield() call... ++ ++ if (++failures > 5_000) { /* TODO determine a threshold */ ++ Thread.yield(); ++ } ++ /* Better waiting is beyond the scope of this lock; if it is needed the lock is being misused */ ++ } ++ ++ //VarHandle.loadLoadFence(); // volatile acts as the load-load barrier ++ return curr; ++ } ++ ++ public boolean tryReleaseRead(final long read) { ++ return this.lock.get() == read; // volatile acts as the load-load barrier ++ } ++ ++ public long getSequentialCounter() { ++ return this.lock.get(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java +new file mode 100644 +index 0000000000000000000000000000000000000000..59868f37d14bbc0ece0836095cdad148778995e6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java +@@ -0,0 +1,162 @@ ++package com.destroystokyo.paper.util.map; ++ ++import com.destroystokyo.paper.util.concurrent.WeakSeqLock; ++import it.unimi.dsi.fastutil.longs.Long2IntMap; ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; ++import it.unimi.dsi.fastutil.longs.LongIterator; ++import it.unimi.dsi.fastutil.longs.LongOpenHashSet; ++import it.unimi.dsi.fastutil.objects.ObjectIterator; ++ ++/** ++ * @author Spottedleaf ++ */ ++public class QueuedChangesMapLong2Int { ++ ++ protected final Long2IntOpenHashMap updatingMap; ++ protected final Long2IntOpenHashMap visibleMap; ++ protected final Long2IntOpenHashMap queuedPuts; ++ protected final LongOpenHashSet queuedRemove; ++ ++ protected int queuedDefaultReturnValue; ++ ++ // we use a seqlock as writes are not common. ++ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); ++ ++ public QueuedChangesMapLong2Int() { ++ this(16, 0.75f); ++ } ++ ++ public QueuedChangesMapLong2Int(final int capacity, final float loadFactor) { ++ this.updatingMap = new Long2IntOpenHashMap(capacity, loadFactor); ++ this.visibleMap = new Long2IntOpenHashMap(capacity, loadFactor); ++ this.queuedPuts = new Long2IntOpenHashMap(); ++ this.queuedRemove = new LongOpenHashSet(); ++ } ++ ++ public void queueDefaultReturnValue(final int dfl) { ++ this.queuedDefaultReturnValue = dfl; ++ this.updatingMap.defaultReturnValue(dfl); ++ } ++ ++ public int queueUpdate(final long k, final int v) { ++ this.queuedRemove.remove(k); ++ this.queuedPuts.put(k, v); ++ ++ return this.updatingMap.put(k, v); ++ } ++ ++ public int queueRemove(final long k) { ++ this.queuedPuts.remove(k); ++ this.queuedRemove.add(k); ++ ++ return this.updatingMap.remove(k); ++ } ++ ++ public int getUpdating(final long k) { ++ return this.updatingMap.get(k); ++ } ++ ++ public int getVisible(final long k) { ++ return this.visibleMap.get(k); ++ } ++ ++ public int getVisibleAsync(final long k) { ++ long readlock; ++ int ret = 0; ++ ++ do { ++ readlock = this.updatingMapSeqLock.acquireRead(); ++ try { ++ ret = this.visibleMap.get(k); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ // ignore... ++ continue; ++ } ++ ++ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ ++ public boolean performUpdates() { ++ this.updatingMapSeqLock.acquireWrite(); ++ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); ++ this.updatingMapSeqLock.releaseWrite(); ++ ++ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { ++ return false; ++ } ++ ++ // update puts ++ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); ++ while (iterator0.hasNext()) { ++ final Long2IntMap.Entry entry = iterator0.next(); ++ final long key = entry.getLongKey(); ++ final int val = entry.getIntValue(); ++ ++ this.updatingMapSeqLock.acquireWrite(); ++ try { ++ this.visibleMap.put(key, val); ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ } ++ ++ this.queuedPuts.clear(); ++ ++ final LongIterator iterator1 = this.queuedRemove.iterator(); ++ while (iterator1.hasNext()) { ++ final long key = iterator1.nextLong(); ++ ++ this.updatingMapSeqLock.acquireWrite(); ++ try { ++ this.visibleMap.remove(key); ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ } ++ ++ this.queuedRemove.clear(); ++ ++ return true; ++ } ++ ++ public boolean performUpdatesLockMap() { ++ this.updatingMapSeqLock.acquireWrite(); ++ try { ++ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); ++ ++ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { ++ return false; ++ } ++ ++ // update puts ++ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); ++ while (iterator0.hasNext()) { ++ final Long2IntMap.Entry entry = iterator0.next(); ++ final long key = entry.getLongKey(); ++ final int val = entry.getIntValue(); ++ ++ this.visibleMap.put(key, val); ++ } ++ ++ this.queuedPuts.clear(); ++ ++ final LongIterator iterator1 = this.queuedRemove.iterator(); ++ while (iterator1.hasNext()) { ++ final long key = iterator1.nextLong(); ++ ++ this.visibleMap.remove(key); ++ } ++ ++ this.queuedRemove.clear(); ++ ++ return true; ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7bab31a312463cc963d9621cdc543a281459bd32 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java +@@ -0,0 +1,202 @@ ++package com.destroystokyo.paper.util.map; ++ ++import com.destroystokyo.paper.util.concurrent.WeakSeqLock; ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectMap; ++import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator; ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.List; ++ ++/** ++ * @author Spottedleaf ++ */ ++public class QueuedChangesMapLong2Object { ++ ++ protected static final Object REMOVED = new Object(); ++ ++ protected final Long2ObjectLinkedOpenHashMap updatingMap; ++ protected final Long2ObjectLinkedOpenHashMap visibleMap; ++ protected final Long2ObjectLinkedOpenHashMap queuedChanges; ++ ++ // we use a seqlock as writes are not common. ++ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); ++ ++ public QueuedChangesMapLong2Object() { ++ this(16, 0.75f); // dfl for fastutil ++ } ++ ++ public QueuedChangesMapLong2Object(final int capacity, final float loadFactor) { ++ this.updatingMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); ++ this.visibleMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); ++ this.queuedChanges = new Long2ObjectLinkedOpenHashMap<>(); ++ } ++ ++ public V queueUpdate(final long k, final V value) { ++ this.queuedChanges.put(k, value); ++ return this.updatingMap.put(k, value); ++ } ++ ++ public V queueRemove(final long k) { ++ this.queuedChanges.put(k, REMOVED); ++ return this.updatingMap.remove(k); ++ } ++ ++ public V getUpdating(final long k) { ++ return this.updatingMap.get(k); ++ } ++ ++ public boolean updatingContainsKey(final long k) { ++ return this.updatingMap.containsKey(k); ++ } ++ ++ public V getVisible(final long k) { ++ return this.visibleMap.get(k); ++ } ++ ++ public boolean visibleContainsKey(final long k) { ++ return this.visibleMap.containsKey(k); ++ } ++ ++ public V getVisibleAsync(final long k) { ++ long readlock; ++ V ret = null; ++ ++ do { ++ readlock = this.updatingMapSeqLock.acquireRead(); ++ ++ try { ++ ret = this.visibleMap.get(k); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ // ignore... ++ continue; ++ } ++ ++ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ ++ public boolean visibleContainsKeyAsync(final long k) { ++ long readlock; ++ boolean ret = false; ++ ++ do { ++ readlock = this.updatingMapSeqLock.acquireRead(); ++ ++ try { ++ ret = this.visibleMap.containsKey(k); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ // ignore... ++ continue; ++ } ++ ++ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ ++ public Long2ObjectLinkedOpenHashMap getVisibleMap() { ++ return this.visibleMap; ++ } ++ ++ public Long2ObjectLinkedOpenHashMap getUpdatingMap() { ++ return this.updatingMap; ++ } ++ ++ public int getVisibleSize() { ++ return this.visibleMap.size(); ++ } ++ ++ public int getVisibleSizeAsync() { ++ long readlock; ++ int ret; ++ ++ do { ++ readlock = this.updatingMapSeqLock.acquireRead(); ++ ret = this.visibleMap.size(); ++ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ ++ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map ++ public Collection getUpdatingValues() { ++ return this.updatingMap.values(); ++ } ++ ++ public List getUpdatingValuesCopy() { ++ return new ArrayList<>(this.updatingMap.values()); ++ } ++ ++ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map ++ public Collection getVisibleValues() { ++ return this.visibleMap.values(); ++ } ++ ++ public List getVisibleValuesCopy() { ++ return new ArrayList<>(this.visibleMap.values()); ++ } ++ ++ public boolean performUpdates() { ++ if (this.queuedChanges.isEmpty()) { ++ return false; ++ } ++ ++ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); ++ while (iterator.hasNext()) { ++ final Long2ObjectMap.Entry entry = iterator.next(); ++ final long key = entry.getLongKey(); ++ final Object val = entry.getValue(); ++ ++ this.updatingMapSeqLock.acquireWrite(); ++ try { ++ if (val == REMOVED) { ++ this.visibleMap.remove(key); ++ } else { ++ this.visibleMap.put(key, (V)val); ++ } ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ } ++ ++ this.queuedChanges.clear(); ++ return true; ++ } ++ ++ public boolean performUpdatesLockMap() { ++ if (this.queuedChanges.isEmpty()) { ++ return false; ++ } ++ ++ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); ++ ++ try { ++ this.updatingMapSeqLock.acquireWrite(); ++ ++ while (iterator.hasNext()) { ++ final Long2ObjectMap.Entry entry = iterator.next(); ++ final long key = entry.getLongKey(); ++ final Object val = entry.getValue(); ++ ++ if (val == REMOVED) { ++ this.visibleMap.remove(key); ++ } else { ++ this.visibleMap.put(key, (V)val); ++ } ++ } ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ ++ this.queuedChanges.clear(); ++ return true; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..554f4d4e63c1431721989e6f502a32ccc53a8807 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java +@@ -0,0 +1,128 @@ ++package com.destroystokyo.paper.util.maplist; ++ ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; ++import java.util.Arrays; ++import java.util.Iterator; ++import java.util.NoSuchElementException; ++import net.minecraft.world.level.chunk.LevelChunk; ++ ++// list with O(1) remove & contains ++/** ++ * @author Spottedleaf ++ */ ++public final class ChunkList implements Iterable { ++ ++ protected final Long2IntOpenHashMap chunkToIndex = new Long2IntOpenHashMap(2, 0.8f); ++ { ++ this.chunkToIndex.defaultReturnValue(Integer.MIN_VALUE); ++ } ++ ++ protected static final LevelChunk[] EMPTY_LIST = new LevelChunk[0]; ++ ++ protected LevelChunk[] chunks = EMPTY_LIST; ++ protected int count; ++ ++ public int size() { ++ return this.count; ++ } ++ ++ public boolean contains(final LevelChunk chunk) { ++ return this.chunkToIndex.containsKey(chunk.coordinateKey); ++ } ++ ++ public boolean remove(final LevelChunk chunk) { ++ final int index = this.chunkToIndex.remove(chunk.coordinateKey); ++ if (index == Integer.MIN_VALUE) { ++ return false; ++ } ++ ++ // move the entity at the end to this index ++ final int endIndex = --this.count; ++ final LevelChunk end = this.chunks[endIndex]; ++ if (index != endIndex) { ++ // not empty after this call ++ this.chunkToIndex.put(end.coordinateKey, index); // update index ++ } ++ this.chunks[index] = end; ++ this.chunks[endIndex] = null; ++ ++ return true; ++ } ++ ++ public boolean add(final LevelChunk chunk) { ++ final int count = this.count; ++ final int currIndex = this.chunkToIndex.putIfAbsent(chunk.coordinateKey, count); ++ ++ if (currIndex != Integer.MIN_VALUE) { ++ return false; // already in this list ++ } ++ ++ LevelChunk[] list = this.chunks; ++ ++ if (list.length == count) { ++ // resize required ++ list = this.chunks = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative ++ } ++ ++ list[count] = chunk; ++ this.count = count + 1; ++ ++ return true; ++ } ++ ++ public LevelChunk getChecked(final int index) { ++ if (index < 0 || index >= this.count) { ++ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); ++ } ++ return this.chunks[index]; ++ } ++ ++ public LevelChunk getUnchecked(final int index) { ++ return this.chunks[index]; ++ } ++ ++ public LevelChunk[] getRawData() { ++ return this.chunks; ++ } ++ ++ public void clear() { ++ this.chunkToIndex.clear(); ++ Arrays.fill(this.chunks, 0, this.count, null); ++ this.count = 0; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return new Iterator() { ++ ++ LevelChunk lastRet; ++ int current; ++ ++ @Override ++ public boolean hasNext() { ++ return this.current < ChunkList.this.count; ++ } ++ ++ @Override ++ public LevelChunk next() { ++ if (this.current >= ChunkList.this.count) { ++ throw new NoSuchElementException(); ++ } ++ return this.lastRet = ChunkList.this.chunks[this.current++]; ++ } ++ ++ @Override ++ public void remove() { ++ final LevelChunk lastRet = this.lastRet; ++ ++ if (lastRet == null) { ++ throw new IllegalStateException(); ++ } ++ this.lastRet = null; ++ ++ ChunkList.this.remove(lastRet); ++ --this.current; ++ } ++ }; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0133ea6feb1ab88f021f66855669f58367e7420b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java +@@ -0,0 +1,128 @@ ++package com.destroystokyo.paper.util.maplist; ++ ++import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; ++import net.minecraft.world.entity.Entity; ++import java.util.Arrays; ++import java.util.Iterator; ++import java.util.NoSuchElementException; ++ ++// list with O(1) remove & contains ++/** ++ * @author Spottedleaf ++ */ ++public final class EntityList implements Iterable { ++ ++ protected final Int2IntOpenHashMap entityToIndex = new Int2IntOpenHashMap(2, 0.8f); ++ { ++ this.entityToIndex.defaultReturnValue(Integer.MIN_VALUE); ++ } ++ ++ protected static final Entity[] EMPTY_LIST = new Entity[0]; ++ ++ protected Entity[] entities = EMPTY_LIST; ++ protected int count; ++ ++ public int size() { ++ return this.count; ++ } ++ ++ public boolean contains(final Entity entity) { ++ return this.entityToIndex.containsKey(entity.getId()); ++ } ++ ++ public boolean remove(final Entity entity) { ++ final int index = this.entityToIndex.remove(entity.getId()); ++ if (index == Integer.MIN_VALUE) { ++ return false; ++ } ++ ++ // move the entity at the end to this index ++ final int endIndex = --this.count; ++ final Entity end = this.entities[endIndex]; ++ if (index != endIndex) { ++ // not empty after this call ++ this.entityToIndex.put(end.getId(), index); // update index ++ } ++ this.entities[index] = end; ++ this.entities[endIndex] = null; ++ ++ return true; ++ } ++ ++ public boolean add(final Entity entity) { ++ final int count = this.count; ++ final int currIndex = this.entityToIndex.putIfAbsent(entity.getId(), count); ++ ++ if (currIndex != Integer.MIN_VALUE) { ++ return false; // already in this list ++ } ++ ++ Entity[] list = this.entities; ++ ++ if (list.length == count) { ++ // resize required ++ list = this.entities = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative ++ } ++ ++ list[count] = entity; ++ this.count = count + 1; ++ ++ return true; ++ } ++ ++ public Entity getChecked(final int index) { ++ if (index < 0 || index >= this.count) { ++ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); ++ } ++ return this.entities[index]; ++ } ++ ++ public Entity getUnchecked(final int index) { ++ return this.entities[index]; ++ } ++ ++ public Entity[] getRawData() { ++ return this.entities; ++ } ++ ++ public void clear() { ++ this.entityToIndex.clear(); ++ Arrays.fill(this.entities, 0, this.count, null); ++ this.count = 0; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return new Iterator() { ++ ++ Entity lastRet; ++ int current; ++ ++ @Override ++ public boolean hasNext() { ++ return this.current < EntityList.this.count; ++ } ++ ++ @Override ++ public Entity next() { ++ if (this.current >= EntityList.this.count) { ++ throw new NoSuchElementException(); ++ } ++ return this.lastRet = EntityList.this.entities[this.current++]; ++ } ++ ++ @Override ++ public void remove() { ++ final Entity lastRet = this.lastRet; ++ ++ if (lastRet == null) { ++ throw new IllegalStateException(); ++ } ++ this.lastRet = null; ++ ++ EntityList.this.remove(lastRet); ++ --this.current; ++ } ++ }; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..abe7f2f13ab713bf1cb0343059377ab7e1b48b6e +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java +@@ -0,0 +1,128 @@ ++package com.destroystokyo.paper.util.maplist; ++ ++import it.unimi.dsi.fastutil.longs.LongIterator; ++import it.unimi.dsi.fastutil.shorts.Short2LongOpenHashMap; ++import java.util.Arrays; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.GlobalPalette; ++import net.minecraft.world.level.chunk.LevelChunkSection; ++ ++/** ++ * @author Spottedleaf ++ */ ++public final class IBlockDataList { ++ ++ static final GlobalPalette GLOBAL_PALETTE = (GlobalPalette) LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE; ++ ++ // map of location -> (index | (location << 16) | (palette id << 32)) ++ private final Short2LongOpenHashMap map = new Short2LongOpenHashMap(2, 0.8f); ++ { ++ this.map.defaultReturnValue(Long.MAX_VALUE); ++ } ++ ++ private static final long[] EMPTY_LIST = new long[0]; ++ ++ private long[] byIndex = EMPTY_LIST; ++ private int size; ++ ++ public static int getLocationKey(final int x, final int y, final int z) { ++ return (x & 15) | (((z & 15) << 4)) | ((y & 255) << (4 + 4)); ++ } ++ ++ public static BlockState getBlockDataFromRaw(final long raw) { ++ return GLOBAL_PALETTE.getObject((int)(raw >>> 32)); ++ } ++ ++ public static int getIndexFromRaw(final long raw) { ++ return (int)(raw & 0xFFFF); ++ } ++ ++ public static int getLocationFromRaw(final long raw) { ++ return (int)((raw >>> 16) & 0xFFFF); ++ } ++ ++ public static long getRawFromValues(final int index, final int location, final BlockState data) { ++ return (long)index | ((long)location << 16) | (((long)GLOBAL_PALETTE.getOrCreateIdFor(data)) << 32); ++ } ++ ++ public static long setIndexRawValues(final long value, final int index) { ++ return value & ~(0xFFFF) | (index); ++ } ++ ++ public long add(final int x, final int y, final int z, final BlockState data) { ++ return this.add(getLocationKey(x, y, z), data); ++ } ++ ++ public long add(final int location, final BlockState data) { ++ final long curr = this.map.get((short)location); ++ ++ if (curr == Long.MAX_VALUE) { ++ final int index = this.size++; ++ final long raw = getRawFromValues(index, location, data); ++ this.map.put((short)location, raw); ++ ++ if (index >= this.byIndex.length) { ++ this.byIndex = Arrays.copyOf(this.byIndex, (int)Math.max(4L, this.byIndex.length * 2L)); ++ } ++ ++ this.byIndex[index] = raw; ++ return raw; ++ } else { ++ final int index = getIndexFromRaw(curr); ++ final long raw = this.byIndex[index] = getRawFromValues(index, location, data); ++ ++ this.map.put((short)location, raw); ++ ++ return raw; ++ } ++ } ++ ++ public long remove(final int x, final int y, final int z) { ++ return this.remove(getLocationKey(x, y, z)); ++ } ++ ++ public long remove(final int location) { ++ final long ret = this.map.remove((short)location); ++ final int index = getIndexFromRaw(ret); ++ if (ret == Long.MAX_VALUE) { ++ return ret; ++ } ++ ++ // move the entry at the end to this index ++ final int endIndex = --this.size; ++ final long end = this.byIndex[endIndex]; ++ if (index != endIndex) { ++ // not empty after this call ++ this.map.put((short)getLocationFromRaw(end), setIndexRawValues(end, index)); ++ } ++ this.byIndex[index] = end; ++ this.byIndex[endIndex] = 0L; ++ ++ return ret; ++ } ++ ++ public int size() { ++ return this.size; ++ } ++ ++ public long getRaw(final int index) { ++ return this.byIndex[index]; ++ } ++ ++ public int getLocation(final int index) { ++ return getLocationFromRaw(this.getRaw(index)); ++ } ++ ++ public BlockState getData(final int index) { ++ return getBlockDataFromRaw(this.getRaw(index)); ++ } ++ ++ public void clear() { ++ this.size = 0; ++ this.map.clear(); ++ } ++ ++ public LongIterator getRawIterator() { ++ return this.map.values().iterator(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c3b936f54b3fff418c265639ef223292ccc89356 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java +@@ -0,0 +1,230 @@ ++package com.destroystokyo.paper.util.math; ++ ++/** ++ * @author Spottedleaf ++ */ ++public final class IntegerUtil { ++ ++ public static final int HIGH_BIT_U32 = Integer.MIN_VALUE; ++ public static final long HIGH_BIT_U64 = Long.MIN_VALUE; ++ ++ public static int ceilLog2(final int value) { ++ return Integer.SIZE - Integer.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros ++ } ++ ++ public static long ceilLog2(final long value) { ++ return Long.SIZE - Long.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros ++ } ++ ++ public static int floorLog2(final int value) { ++ // xor is optimized subtract for 2^n -1 ++ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) ++ return (Integer.SIZE - 1) ^ Integer.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros ++ } ++ ++ public static int floorLog2(final long value) { ++ // xor is optimized subtract for 2^n -1 ++ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) ++ return (Long.SIZE - 1) ^ Long.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros ++ } ++ ++ public static int roundCeilLog2(final int value) { ++ // optimized variant of 1 << (32 - leading(val - 1)) ++ // given ++ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) ++ // 1 << (32 - leading(val - 1)) = HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) ++ // HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) ++ // HIGH_BIT_32 >>> (31 - 32 + leading(val - 1)) ++ // HIGH_BIT_32 >>> (-1 + leading(val - 1)) ++ return HIGH_BIT_U32 >>> (Integer.numberOfLeadingZeros(value - 1) - 1); ++ } ++ ++ public static long roundCeilLog2(final long value) { ++ // see logic documented above ++ return HIGH_BIT_U64 >>> (Long.numberOfLeadingZeros(value - 1) - 1); ++ } ++ ++ public static int roundFloorLog2(final int value) { ++ // optimized variant of 1 << (31 - leading(val)) ++ // given ++ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) ++ // 1 << (31 - leading(val)) = HIGH_BIT_32 >> (31 - (31 - leading(val))) ++ // HIGH_BIT_32 >> (31 - (31 - leading(val))) ++ // HIGH_BIT_32 >> (31 - 31 + leading(val)) ++ return HIGH_BIT_U32 >>> Integer.numberOfLeadingZeros(value); ++ } ++ ++ public static long roundFloorLog2(final long value) { ++ // see logic documented above ++ return HIGH_BIT_U64 >>> Long.numberOfLeadingZeros(value); ++ } ++ ++ public static boolean isPowerOfTwo(final int n) { ++ // 2^n has one bit ++ // note: this rets true for 0 still ++ return IntegerUtil.getTrailingBit(n) == n; ++ } ++ ++ public static boolean isPowerOfTwo(final long n) { ++ // 2^n has one bit ++ // note: this rets true for 0 still ++ return IntegerUtil.getTrailingBit(n) == n; ++ } ++ ++ ++ public static int getTrailingBit(final int n) { ++ return -n & n; ++ } ++ ++ public static long getTrailingBit(final long n) { ++ return -n & n; ++ } ++ ++ public static int trailingZeros(final int n) { ++ return Integer.numberOfTrailingZeros(n); ++ } ++ ++ public static long trailingZeros(final long n) { ++ return Long.numberOfTrailingZeros(n); ++ } ++ ++ // from hacker's delight (signed division magic value) ++ public static int getDivisorMultiple(final long numbers) { ++ return (int)(numbers >>> 32); ++ } ++ ++ // from hacker's delight (signed division magic value) ++ public static int getDivisorShift(final long numbers) { ++ return (int)numbers; ++ } ++ ++ // copied from hacker's delight (signed division magic value) ++ // http://www.hackersdelight.org/hdcodetxt/magic.c.txt ++ public static long getDivisorNumbers(final int d) { ++ final int ad = IntegerUtil.branchlessAbs(d); ++ ++ if (ad < 2) { ++ throw new IllegalArgumentException("|number| must be in [2, 2^31 -1], not: " + d); ++ } ++ ++ final int two31 = 0x80000000; ++ final long mask = 0xFFFFFFFFL; // mask for enforcing unsigned behaviour ++ ++ int p = 31; ++ ++ // all these variables are UNSIGNED! ++ int t = two31 + (d >>> 31); ++ int anc = t - 1 - t%ad; ++ int q1 = (int)((two31 & mask)/(anc & mask)); ++ int r1 = two31 - q1*anc; ++ int q2 = (int)((two31 & mask)/(ad & mask)); ++ int r2 = two31 - q2*ad; ++ int delta; ++ ++ do { ++ p = p + 1; ++ q1 = 2*q1; // Update q1 = 2**p/|nc|. ++ r1 = 2*r1; // Update r1 = rem(2**p, |nc|). ++ if ((r1 & mask) >= (anc & mask)) {// (Must be an unsigned comparison here) ++ q1 = q1 + 1; ++ r1 = r1 - anc; ++ } ++ q2 = 2*q2; // Update q2 = 2**p/|d|. ++ r2 = 2*r2; // Update r2 = rem(2**p, |d|). ++ if ((r2 & mask) >= (ad & mask)) {// (Must be an unsigned comparison here) ++ q2 = q2 + 1; ++ r2 = r2 - ad; ++ } ++ delta = ad - r2; ++ } while ((q1 & mask) < (delta & mask) || (q1 == delta && r1 == 0)); ++ ++ int magicNum = q2 + 1; ++ if (d < 0) { ++ magicNum = -magicNum; ++ } ++ int shift = p - 32; ++ return ((long)magicNum << 32) | shift; ++ } ++ ++ public static int branchlessAbs(final int val) { ++ // -n = -1 ^ n + 1 ++ final int mask = val >> (Integer.SIZE - 1); // -1 if < 0, 0 if >= 0 ++ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 ++ } ++ ++ public static long branchlessAbs(final long val) { ++ // -n = -1 ^ n + 1 ++ final long mask = val >> (Long.SIZE - 1); // -1 if < 0, 0 if >= 0 ++ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 ++ } ++ ++ //https://github.com/skeeto/hash-prospector for hash functions ++ ++ //score = ~590.47984224483832 ++ public static int hash0(int x) { ++ x *= 0x36935555; ++ x ^= x >>> 16; ++ return x; ++ } ++ ++ //score = ~310.01596637036749 ++ public static int hash1(int x) { ++ x ^= x >>> 15; ++ x *= 0x356aaaad; ++ x ^= x >>> 17; ++ return x; ++ } ++ ++ public static int hash2(int x) { ++ x ^= x >>> 16; ++ x *= 0x7feb352d; ++ x ^= x >>> 15; ++ x *= 0x846ca68b; ++ x ^= x >>> 16; ++ return x; ++ } ++ ++ public static int hash3(int x) { ++ x ^= x >>> 17; ++ x *= 0xed5ad4bb; ++ x ^= x >>> 11; ++ x *= 0xac4c1b51; ++ x ^= x >>> 15; ++ x *= 0x31848bab; ++ x ^= x >>> 14; ++ return x; ++ } ++ ++ //score = ~365.79959673201887 ++ public static long hash1(long x) { ++ x ^= x >>> 27; ++ x *= 0xb24924b71d2d354bL; ++ x ^= x >>> 28; ++ return x; ++ } ++ ++ //h2 hash ++ public static long hash2(long x) { ++ x ^= x >>> 32; ++ x *= 0xd6e8feb86659fd93L; ++ x ^= x >>> 32; ++ x *= 0xd6e8feb86659fd93L; ++ x ^= x >>> 32; ++ return x; ++ } ++ ++ public static long hash3(long x) { ++ x ^= x >>> 45; ++ x *= 0xc161abe5704b6c79L; ++ x ^= x >>> 41; ++ x *= 0xe3e5389aedbc90f7L; ++ x ^= x >>> 56; ++ x *= 0x1f9aba75a52db073L; ++ x ^= x >>> 53; ++ return x; ++ } ++ ++ private IntegerUtil() { ++ throw new RuntimeException(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c601f04b9c6dff76606763ea6f4a9a89b7e83203 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java +@@ -0,0 +1,453 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import com.destroystokyo.paper.util.math.IntegerUtil; ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.world.level.ChunkPos; ++import javax.annotation.Nullable; ++import java.util.Iterator; ++ ++/** @author Spottedleaf */ ++public abstract class AreaMap { ++ ++ /* Tested via https://gist.github.com/Spottedleaf/520419c6f41ef348fe9926ce674b7217 */ ++ ++ protected final Object2LongOpenHashMap objectToLastCoordinate = new Object2LongOpenHashMap<>(); ++ protected final Object2IntOpenHashMap objectToViewDistance = new Object2IntOpenHashMap<>(); ++ ++ { ++ this.objectToViewDistance.defaultReturnValue(-1); ++ this.objectToLastCoordinate.defaultReturnValue(Long.MIN_VALUE); ++ } ++ ++ // we use linked for better iteration. ++ // map of: coordinate to set of objects in coordinate ++ protected final Long2ObjectOpenHashMap> areaMap = new Long2ObjectOpenHashMap<>(1024, 0.7f); ++ protected final PooledLinkedHashSets pooledHashSets; ++ ++ protected final ChangeCallback addCallback; ++ protected final ChangeCallback removeCallback; ++ protected final ChangeSourceCallback changeSourceCallback; ++ ++ public AreaMap() { ++ this(new PooledLinkedHashSets<>()); ++ } ++ ++ // let users define a "global" or "shared" pooled sets if they wish ++ public AreaMap(final PooledLinkedHashSets pooledHashSets) { ++ this(pooledHashSets, null, null); ++ } ++ ++ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback) { ++ this(pooledHashSets, addCallback, removeCallback, null); ++ } ++ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { ++ this.pooledHashSets = pooledHashSets; ++ this.addCallback = addCallback; ++ this.removeCallback = removeCallback; ++ this.changeSourceCallback = changeSourceCallback; ++ } ++ ++ @Nullable ++ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final long key) { ++ return this.areaMap.get(key); ++ } ++ ++ @Nullable ++ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final ChunkPos chunkPos) { ++ return this.areaMap.get(MCUtil.getCoordinateKey(chunkPos)); ++ } ++ ++ @Nullable ++ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final int chunkX, final int chunkZ) { ++ return this.areaMap.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); ++ } ++ ++ // Long.MIN_VALUE indicates the object is not mapped ++ public final long getLastCoordinate(final E object) { ++ return this.objectToLastCoordinate.getOrDefault(object, Long.MIN_VALUE); ++ } ++ ++ // -1 indicates the object is not mapped ++ public final int getLastViewDistance(final E object) { ++ return this.objectToViewDistance.getOrDefault(object, -1); ++ } ++ ++ // returns the total number of mapped chunks ++ public final int size() { ++ return this.areaMap.size(); ++ } ++ ++ public final void addOrUpdate(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int oldViewDistance = this.objectToViewDistance.put(object, viewDistance); ++ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final long oldPos = this.objectToLastCoordinate.put(object, newPos); ++ ++ if (oldViewDistance == -1) { ++ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); ++ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); ++ } else { ++ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); ++ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); ++ } ++ //this.validate(object, viewDistance); ++ } ++ ++ public final boolean update(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int oldViewDistance = this.objectToViewDistance.replace(object, viewDistance); ++ if (oldViewDistance == -1) { ++ return false; ++ } else { ++ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final long oldPos = this.objectToLastCoordinate.put(object, newPos); ++ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); ++ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); ++ } ++ //this.validate(object, viewDistance); ++ return true; ++ } ++ ++ // called after the distance map updates ++ protected void updateObjectCallback(final E Object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { ++ if (newPosition != oldPosition && this.changeSourceCallback != null) { ++ this.changeSourceCallback.accept(Object, oldPosition, newPosition); ++ } ++ } ++ ++ public final boolean add(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int oldViewDistance = this.objectToViewDistance.putIfAbsent(object, viewDistance); ++ if (oldViewDistance != -1) { ++ return false; ++ } ++ ++ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ this.objectToLastCoordinate.put(object, newPos); ++ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); ++ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); ++ ++ //this.validate(object, viewDistance); ++ ++ return true; ++ } ++ ++ // called after the distance map updates ++ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} ++ ++ public final boolean remove(final E object) { ++ final long position = this.objectToLastCoordinate.removeLong(object); ++ final int viewDistance = this.objectToViewDistance.removeInt(object); ++ ++ if (viewDistance == -1) { ++ return false; ++ } ++ ++ final int currentX = MCUtil.getCoordinateX(position); ++ final int currentZ = MCUtil.getCoordinateZ(position); ++ ++ this.removeObject(object, currentX, currentZ, currentX, currentZ, viewDistance); ++ this.removeObjectCallback(object, currentX, currentZ, viewDistance); ++ //this.validate(object, -1); ++ return true; ++ } ++ ++ // called after the distance map updates ++ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} ++ ++ protected abstract PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final E object); ++ ++ // expensive op, only for debug ++ protected void validate(final E object, final int viewDistance) { ++ int entiesGot = 0; ++ int expectedEntries = (2 * viewDistance + 1); ++ expectedEntries *= expectedEntries; ++ if (viewDistance < 0) { ++ expectedEntries = 0; ++ } ++ ++ final long currPosition = this.objectToLastCoordinate.getLong(object); ++ ++ final int centerX = MCUtil.getCoordinateX(currPosition); ++ final int centerZ = MCUtil.getCoordinateZ(currPosition); ++ ++ for (Iterator>> iterator = this.areaMap.long2ObjectEntrySet().fastIterator(); ++ iterator.hasNext();) { ++ ++ final Long2ObjectLinkedOpenHashMap.Entry> entry = iterator.next(); ++ final long key = entry.getLongKey(); ++ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); ++ ++ if (map.referenceCount == 0) { ++ throw new IllegalStateException("Invalid map"); ++ } ++ ++ if (map.contains(object)) { ++ ++entiesGot; ++ ++ final int chunkX = MCUtil.getCoordinateX(key); ++ final int chunkZ = MCUtil.getCoordinateZ(key); ++ ++ final int dist = Math.max(IntegerUtil.branchlessAbs(chunkX - centerX), IntegerUtil.branchlessAbs(chunkZ - centerZ)); ++ ++ if (dist > viewDistance) { ++ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); ++ } ++ } ++ } ++ ++ if (entiesGot != expectedEntries) { ++ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); ++ } ++ } ++ ++ private void addObjectTo(final E object, final int chunkX, final int chunkZ, final int currChunkX, ++ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { ++ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet empty = this.getEmptySetFor(object); ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.putIfAbsent(key, empty); ++ ++ if (current != null) { ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWith(current, object); ++ if (next == current) { ++ throw new IllegalStateException("Expected different map: got " + next.toString()); ++ } ++ this.areaMap.put(key, next); ++ ++ current = next; ++ // fall through to callback ++ } else { ++ current = empty; ++ } ++ ++ if (this.addCallback != null) { ++ try { ++ this.addCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, current); ++ } catch (final Throwable ex) { ++ if (ex instanceof ThreadDeath) { ++ throw (ThreadDeath)ex; ++ } ++ MinecraftServer.LOGGER.error("Add callback for map threw exception ", ex); ++ } ++ } ++ } ++ ++ private void removeObjectFrom(final E object, final int chunkX, final int chunkZ, final int currChunkX, ++ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { ++ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.get(key); ++ ++ if (current == null) { ++ throw new IllegalStateException("Current map may not be null for " + object + ", (" + chunkX + "," + chunkZ + ")"); ++ } ++ ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWithout(current, object); ++ ++ if (next == current) { ++ throw new IllegalStateException("Current map [" + next.toString() + "] should have contained " + object + ", (" + chunkX + "," + chunkZ + ")"); ++ } ++ ++ if (next != null) { ++ this.areaMap.put(key, next); ++ } else { ++ this.areaMap.remove(key); ++ } ++ ++ if (this.removeCallback != null) { ++ try { ++ this.removeCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, next); ++ } catch (final Throwable ex) { ++ if (ex instanceof ThreadDeath) { ++ throw (ThreadDeath)ex; ++ } ++ MinecraftServer.LOGGER.error("Remove callback for map threw exception ", ex); ++ } ++ } ++ } ++ ++ private void addObject(final E object, final int chunkX, final int chunkZ, final int prevChunkX, final int prevChunkZ, final int viewDistance) { ++ final int maxX = chunkX + viewDistance; ++ final int maxZ = chunkZ + viewDistance; ++ final int minX = chunkX - viewDistance; ++ final int minZ = chunkZ - viewDistance; ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ this.addObjectTo(object, x, z, chunkX, chunkZ, prevChunkX, prevChunkZ); ++ } ++ } ++ } ++ ++ private void removeObject(final E object, final int chunkX, final int chunkZ, final int currentChunkX, final int currentChunkZ, final int viewDistance) { ++ final int maxX = chunkX + viewDistance; ++ final int maxZ = chunkZ + viewDistance; ++ final int minX = chunkX - viewDistance; ++ final int minZ = chunkZ - viewDistance; ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ this.removeObjectFrom(object, x, z, currentChunkX, currentChunkZ, chunkX, chunkZ); ++ } ++ } ++ } ++ ++ /* math sign function except 0 returns 1 */ ++ protected static int sign(int val) { ++ return 1 | (val >> (Integer.SIZE - 1)); ++ } ++ ++ private void updateObject(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { ++ final int toX = MCUtil.getCoordinateX(newPosition); ++ final int toZ = MCUtil.getCoordinateZ(newPosition); ++ final int fromX = MCUtil.getCoordinateX(oldPosition); ++ final int fromZ = MCUtil.getCoordinateZ(oldPosition); ++ ++ final int dx = toX - fromX; ++ final int dz = toZ - fromZ; ++ ++ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); ++ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); ++ ++ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { ++ // teleported? ++ this.removeObject(object, fromX, fromZ, fromX, fromZ, oldViewDistance); ++ this.addObject(object, toX, toZ, fromX, fromZ, newViewDistance); ++ return; ++ } ++ ++ if (oldViewDistance != newViewDistance) { ++ // remove loop ++ ++ final int oldMinX = fromX - oldViewDistance; ++ final int oldMinZ = fromZ - oldViewDistance; ++ final int oldMaxX = fromX + oldViewDistance; ++ final int oldMaxZ = fromZ + oldViewDistance; ++ for (int currX = oldMinX; currX <= oldMaxX; ++currX) { ++ for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) { ++ ++ // only remove if we're outside the new view distance... ++ if (Math.max(IntegerUtil.branchlessAbs(currX - toX), IntegerUtil.branchlessAbs(currZ - toZ)) > newViewDistance) { ++ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ // add loop ++ ++ final int newMinX = toX - newViewDistance; ++ final int newMinZ = toZ - newViewDistance; ++ final int newMaxX = toX + newViewDistance; ++ final int newMaxZ = toZ + newViewDistance; ++ for (int currX = newMinX; currX <= newMaxX; ++currX) { ++ for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) { ++ ++ // only add if we're outside the old view distance... ++ if (Math.max(IntegerUtil.branchlessAbs(currX - fromX), IntegerUtil.branchlessAbs(currZ - fromZ)) > oldViewDistance) { ++ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ return; ++ } ++ ++ // x axis is width ++ // z axis is height ++ // right refers to the x axis of where we moved ++ // top refers to the z axis of where we moved ++ ++ // same view distance ++ ++ // used for relative positioning ++ final int up = sign(dz); // 1 if dz >= 0, -1 otherwise ++ final int right = sign(dx); // 1 if dx >= 0, -1 otherwise ++ ++ // The area excluded by overlapping the two view distance squares creates four rectangles: ++ // Two on the left, and two on the right. The ones on the left we consider the "removed" section ++ // and on the right the "added" section. ++ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually ++ // exclusive to the regions they surround. ++ ++ // 4 points of the rectangle ++ int maxX; // exclusive ++ int minX; // inclusive ++ int maxZ; // exclusive ++ int minZ; // inclusive ++ ++ if (dx != 0) { ++ // handle right addition ++ ++ maxX = toX + (oldViewDistance * right) + right; // exclusive ++ minX = fromX + (oldViewDistance * right) + right; // inclusive ++ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive ++ minZ = toZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ if (dz != 0) { ++ // handle up addition ++ ++ maxX = toX + (oldViewDistance * right) + right; // exclusive ++ minX = toX - (oldViewDistance * right); // inclusive ++ maxZ = toZ + (oldViewDistance * up) + up; // exclusive ++ minZ = fromZ + (oldViewDistance * up) + up; // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ if (dx != 0) { ++ // handle left removal ++ ++ maxX = toX - (oldViewDistance * right); // exclusive ++ minX = fromX - (oldViewDistance * right); // inclusive ++ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive ++ minZ = toZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ if (dz != 0) { ++ // handle down removal ++ ++ maxX = fromX + (oldViewDistance * right) + right; // exclusive ++ minX = fromX - (oldViewDistance * right); // inclusive ++ maxZ = toZ - (oldViewDistance * up); // exclusive ++ minZ = fromZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ } ++ ++ @FunctionalInterface ++ public static interface ChangeCallback { ++ ++ // if there is no previous position, then prevPos = Integer.MIN_VALUE ++ void accept(final E object, final int rangeX, final int rangeZ, final int currPosX, final int currPosZ, final int prevPosX, final int prevPosZ, ++ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState); ++ ++ } ++ ++ @FunctionalInterface ++ public static interface ChangeSourceCallback { ++ void accept(final E object, final long prevPos, final long newPos); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9b8cb361767fbcf5f592db32a12186f0bd6373bd +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java +@@ -0,0 +1,175 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import com.destroystokyo.paper.util.math.IntegerUtil; ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; ++import net.minecraft.server.MCUtil; ++import net.minecraft.world.level.ChunkPos; ++ ++/** @author Spottedleaf */ ++public abstract class DistanceTrackingAreaMap extends AreaMap { ++ ++ // use this map only if you need distance tracking, the tracking here is obviously going to hit harder. ++ ++ protected final Long2IntOpenHashMap chunkToNearestDistance = new Long2IntOpenHashMap(1024, 0.7f); ++ { ++ this.chunkToNearestDistance.defaultReturnValue(-1); ++ } ++ ++ protected final DistanceChangeCallback distanceChangeCallback; ++ ++ public DistanceTrackingAreaMap() { ++ this(new PooledLinkedHashSets<>()); ++ } ++ ++ // let users define a "global" or "shared" pooled sets if they wish ++ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { ++ this(pooledHashSets, null, null, null); ++ } ++ ++ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, ++ final DistanceChangeCallback distanceChangeCallback) { ++ super(pooledHashSets, addCallback, removeCallback); ++ this.distanceChangeCallback = distanceChangeCallback; ++ } ++ ++ // ret -1 if there is nothing mapped ++ public final int getNearestObjectDistance(final long key) { ++ return this.chunkToNearestDistance.get(key); ++ } ++ ++ // ret -1 if there is nothing mapped ++ public final int getNearestObjectDistance(final ChunkPos chunkPos) { ++ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkPos)); ++ } ++ ++ // ret -1 if there is nothing mapped ++ public final int getNearestObjectDistance(final int chunkX, final int chunkZ) { ++ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); ++ } ++ ++ protected final void recalculateDistance(final int chunkX, final int chunkZ) { ++ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state = this.areaMap.get(key); ++ if (state == null) { ++ final int oldDistance = this.chunkToNearestDistance.remove(key); ++ // nothing here. ++ if (oldDistance == -1) { ++ // nothing was here previously ++ return; ++ } ++ if (this.distanceChangeCallback != null) { ++ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, -1, null); ++ } ++ return; ++ } ++ ++ int newDistance = Integer.MAX_VALUE; ++ ++ final Object[] rawData = state.getBackingSet(); ++ for (int i = 0, len = rawData.length; i < len; ++i) { ++ final Object raw = rawData[i]; ++ ++ if (raw == null) { ++ continue; ++ } ++ ++ final E object = (E)raw; ++ final long location = this.objectToLastCoordinate.getLong(object); ++ ++ final int distance = Math.max(IntegerUtil.branchlessAbs(chunkX - MCUtil.getCoordinateX(location)), IntegerUtil.branchlessAbs(chunkZ - MCUtil.getCoordinateZ(location))); ++ ++ if (distance < newDistance) { ++ newDistance = distance; ++ } ++ } ++ ++ final int oldDistance = this.chunkToNearestDistance.put(key, newDistance); ++ ++ if (oldDistance != newDistance) { ++ if (this.distanceChangeCallback != null) { ++ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, newDistance, state); ++ } ++ } ++ } ++ ++ @Override ++ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int maxX = chunkX + viewDistance; ++ final int maxZ = chunkZ + viewDistance; ++ final int minX = chunkX - viewDistance; ++ final int minZ = chunkZ - viewDistance; ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ this.recalculateDistance(x, z); ++ } ++ } ++ } ++ ++ @Override ++ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int maxX = chunkX + viewDistance; ++ final int maxZ = chunkZ + viewDistance; ++ final int minX = chunkX - viewDistance; ++ final int minZ = chunkZ - viewDistance; ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ this.recalculateDistance(x, z); ++ } ++ } ++ } ++ ++ @Override ++ protected void updateObjectCallback(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { ++ if (oldPosition == newPosition && newViewDistance == oldViewDistance) { ++ return; ++ } ++ ++ final int toX = MCUtil.getCoordinateX(newPosition); ++ final int toZ = MCUtil.getCoordinateZ(newPosition); ++ final int fromX = MCUtil.getCoordinateX(oldPosition); ++ final int fromZ = MCUtil.getCoordinateZ(oldPosition); ++ ++ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); ++ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); ++ ++ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { ++ // teleported? ++ this.removeObjectCallback(object, fromX, fromZ, oldViewDistance); ++ this.addObjectCallback(object, toX, toZ, newViewDistance); ++ return; ++ } ++ ++ final int minX = Math.min(fromX - oldViewDistance, toX - newViewDistance); ++ final int maxX = Math.max(fromX + oldViewDistance, toX + newViewDistance); ++ final int minZ = Math.min(fromZ - oldViewDistance, toZ - newViewDistance); ++ final int maxZ = Math.max(fromZ + oldViewDistance, toZ + newViewDistance); ++ ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ final int distXOld = IntegerUtil.branchlessAbs(x - fromX); ++ final int distZOld = IntegerUtil.branchlessAbs(z - fromZ); ++ ++ if (Math.max(distXOld, distZOld) <= oldViewDistance) { ++ this.recalculateDistance(x, z); ++ continue; ++ } ++ ++ final int distXNew = IntegerUtil.branchlessAbs(x - toX); ++ final int distZNew = IntegerUtil.branchlessAbs(z - toZ); ++ ++ if (Math.max(distXNew, distZNew) <= newViewDistance) { ++ this.recalculateDistance(x, z); ++ continue; ++ } ++ } ++ } ++ } ++ ++ @FunctionalInterface ++ public static interface DistanceChangeCallback { ++ ++ void accept(final int posX, final int posZ, final int oldNearestDistance, final int newNearestDistance, ++ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state); ++ ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..46954db7ecd35ac4018fdf476df7c8020d7ce6c8 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java +@@ -0,0 +1,32 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import net.minecraft.server.level.ServerPlayer; ++ ++/** ++ * @author Spottedleaf ++ */ ++public final class PlayerAreaMap extends AreaMap { ++ ++ public PlayerAreaMap() { ++ super(); ++ } ++ ++ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets) { ++ super(pooledHashSets); ++ } ++ ++ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, ++ final ChangeCallback removeCallback) { ++ this(pooledHashSets, addCallback, removeCallback, null); ++ } ++ ++ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, ++ final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { ++ super(pooledHashSets, addCallback, removeCallback, changeSourceCallback); ++ } ++ ++ @Override ++ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final ServerPlayer player) { ++ return player.cachedSingleHashSet; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d05dcea15f7047b58736c7c0e07920a04d6c5abe +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java +@@ -0,0 +1,24 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import net.minecraft.server.level.ServerPlayer; ++ ++public class PlayerDistanceTrackingAreaMap extends DistanceTrackingAreaMap { ++ ++ public PlayerDistanceTrackingAreaMap() { ++ super(); ++ } ++ ++ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { ++ super(pooledHashSets); ++ } ++ ++ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, ++ final ChangeCallback removeCallback, final DistanceChangeCallback distanceChangeCallback) { ++ super(pooledHashSets, addCallback, removeCallback, distanceChangeCallback); ++ } ++ ++ @Override ++ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final ServerPlayer player) { ++ return player.cachedSingleHashSet; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e51104e65a07b6ea7bbbcbb6afb066ef6401cc5b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java +@@ -0,0 +1,287 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; ++import java.lang.ref.WeakReference; ++ ++/** @author Spottedleaf */ ++public class PooledLinkedHashSets { ++ ++ /* Tested via https://gist.github.com/Spottedleaf/a93bb7a8993d6ce142d3efc5932bf573 */ ++ ++ // we really want to avoid that equals() check as much as possible... ++ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(128, 0.25f); ++ ++ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { ++ if (current.referenceCount == 0) { ++ throw new IllegalStateException("Cannot decrement reference count for " + current); ++ } ++ if (current.referenceCount == -1 || --current.referenceCount > 0) { ++ return; ++ } ++ ++ this.mapPool.remove(current); ++ return; ++ } ++ ++ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { ++ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); ++ ++ if (cached != null) { ++ decrementReferenceCount(current); ++ ++ if (cached.referenceCount == 0) { ++ // bring the map back from the dead ++ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); ++ if (contending != null) { ++ // a map already exists with the elements we want ++ if (contending.referenceCount != -1) { ++ ++contending.referenceCount; ++ } ++ current.updateAddCache(object, contending); ++ return contending; ++ } ++ ++ cached.referenceCount = 1; ++ } else if (cached.referenceCount != -1) { ++ ++cached.referenceCount; ++ } ++ ++ return cached; ++ } ++ ++ if (!current.add(object)) { ++ return current; ++ } ++ ++ // we use get/put since we use a different key on put ++ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); ++ ++ if (ret == null) { ++ ret = new PooledObjectLinkedOpenHashSet<>(current); ++ current.remove(object); ++ this.mapPool.put(ret, ret); ++ ret.referenceCount = 1; ++ } else { ++ if (ret.referenceCount != -1) { ++ ++ret.referenceCount; ++ } ++ current.remove(object); ++ } ++ ++ current.updateAddCache(object, ret); ++ ++ decrementReferenceCount(current); ++ return ret; ++ } ++ ++ // rets null if current.size() == 1 ++ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { ++ if (current.set.size() == 1) { ++ decrementReferenceCount(current); ++ return null; ++ } ++ ++ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); ++ ++ if (cached != null) { ++ decrementReferenceCount(current); ++ ++ if (cached.referenceCount == 0) { ++ // bring the map back from the dead ++ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); ++ if (contending != null) { ++ // a map already exists with the elements we want ++ if (contending.referenceCount != -1) { ++ ++contending.referenceCount; ++ } ++ current.updateRemoveCache(object, contending); ++ return contending; ++ } ++ ++ cached.referenceCount = 1; ++ } else if (cached.referenceCount != -1) { ++ ++cached.referenceCount; ++ } ++ ++ return cached; ++ } ++ ++ if (!current.remove(object)) { ++ return current; ++ } ++ ++ // we use get/put since we use a different key on put ++ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); ++ ++ if (ret == null) { ++ ret = new PooledObjectLinkedOpenHashSet<>(current); ++ current.add(object); ++ this.mapPool.put(ret, ret); ++ ret.referenceCount = 1; ++ } else { ++ if (ret.referenceCount != -1) { ++ ++ret.referenceCount; ++ } ++ current.add(object); ++ } ++ ++ current.updateRemoveCache(object, ret); ++ ++ decrementReferenceCount(current); ++ return ret; ++ } ++ ++ static final class RawSetObjectLinkedOpenHashSet extends ObjectOpenHashSet { ++ ++ public RawSetObjectLinkedOpenHashSet() { ++ super(); ++ } ++ ++ public RawSetObjectLinkedOpenHashSet(final int capacity) { ++ super(capacity); ++ } ++ ++ public RawSetObjectLinkedOpenHashSet(final int capacity, final float loadFactor) { ++ super(capacity, loadFactor); ++ } ++ ++ @Override ++ public RawSetObjectLinkedOpenHashSet clone() { ++ return (RawSetObjectLinkedOpenHashSet)super.clone(); ++ } ++ ++ public E[] getRawSet() { ++ return this.key; ++ } ++ } ++ ++ public static final class PooledObjectLinkedOpenHashSet { ++ ++ private static final WeakReference NULL_REFERENCE = new WeakReference<>(null); ++ ++ final RawSetObjectLinkedOpenHashSet set; ++ int referenceCount; // -1 if special ++ int hash; // optimize hashcode ++ ++ // add cache ++ WeakReference lastAddObject = NULL_REFERENCE; ++ WeakReference> lastAddMap = NULL_REFERENCE; ++ ++ // remove cache ++ WeakReference lastRemoveObject = NULL_REFERENCE; ++ WeakReference> lastRemoveMap = NULL_REFERENCE; ++ ++ public PooledObjectLinkedOpenHashSet(final PooledLinkedHashSets pooledSets) { ++ this.set = new RawSetObjectLinkedOpenHashSet<>(2, 0.8f); ++ } ++ ++ public PooledObjectLinkedOpenHashSet(final E single) { ++ this((PooledLinkedHashSets)null); ++ this.referenceCount = -1; ++ this.add(single); ++ } ++ ++ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { ++ this.set = other.set.clone(); ++ this.hash = other.hash; ++ } ++ ++ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java ++ // generated by https://github.com/skeeto/hash-prospector ++ private static int hash0(int x) { ++ x *= 0x36935555; ++ x ^= x >>> 16; ++ return x; ++ } ++ ++ PooledObjectLinkedOpenHashSet getAddCache(final E element) { ++ final E currentAdd = this.lastAddObject.get(); ++ ++ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { ++ return null; ++ } ++ ++ return this.lastAddMap.get(); ++ } ++ ++ PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { ++ final E currentRemove = this.lastRemoveObject.get(); ++ ++ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { ++ return null; ++ } ++ ++ return this.lastRemoveMap.get(); ++ } ++ ++ void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { ++ this.lastAddObject = new WeakReference<>(element); ++ this.lastAddMap = new WeakReference<>(map); ++ } ++ ++ void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { ++ this.lastRemoveObject = new WeakReference<>(element); ++ this.lastRemoveMap = new WeakReference<>(map); ++ } ++ ++ boolean add(final E element) { ++ boolean added = this.set.add(element); ++ ++ if (added) { ++ this.hash += hash0(element.hashCode()); ++ } ++ ++ return added; ++ } ++ ++ boolean remove(Object element) { ++ boolean removed = this.set.remove(element); ++ ++ if (removed) { ++ this.hash -= hash0(element.hashCode()); ++ } ++ ++ return removed; ++ } ++ ++ public boolean contains(final Object element) { ++ return this.set.contains(element); ++ } ++ ++ public E[] getBackingSet() { ++ return this.set.getRawSet(); ++ } ++ ++ public int size() { ++ return this.set.size(); ++ } ++ ++ @Override ++ public int hashCode() { ++ return this.hash; ++ } ++ ++ @Override ++ public boolean equals(final Object other) { ++ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { ++ return false; ++ } ++ if (this.referenceCount == 0) { ++ return other == this; ++ } else { ++ if (other == this) { ++ // Unfortunately we are never equal to our own instance while in use! ++ return false; ++ } ++ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); ++ } ++ } ++ ++ @Override ++ public String toString() { ++ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + ++ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d0c77068e9a53d1b8bbad0f3f6b420d6bc85f8c8 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java +@@ -0,0 +1,85 @@ ++package com.destroystokyo.paper.util.pooled; ++ ++import net.minecraft.server.MCUtil; ++import org.apache.commons.lang3.mutable.MutableInt; ++ ++import java.util.ArrayDeque; ++import java.util.function.Consumer; ++import java.util.function.Supplier; ++ ++public final class PooledObjects { ++ ++ /** ++ * Wrapper for an object that will be have a cleaner registered for it, and may be automatically returned to pool. ++ */ ++ public class AutoReleased { ++ private final E object; ++ private final Runnable cleaner; ++ ++ public AutoReleased(E object, Runnable cleaner) { ++ this.object = object; ++ this.cleaner = cleaner; ++ } ++ ++ public final E getObject() { ++ return object; ++ } ++ ++ public final Runnable getCleaner() { ++ return cleaner; ++ } ++ } ++ ++ public static final PooledObjects POOLED_MUTABLE_INTEGERS = new PooledObjects<>(MutableInt::new, 1024); ++ ++ private final Supplier creator; ++ private final Consumer releaser; ++ private final int maxPoolSize; ++ private final ArrayDeque queue; ++ ++ public PooledObjects(final Supplier creator, int maxPoolSize) { ++ this(creator, maxPoolSize, null); ++ } ++ public PooledObjects(final Supplier creator, int maxPoolSize, Consumer releaser) { ++ if (creator == null) { ++ throw new NullPointerException("Creator must not be null"); ++ } ++ if (maxPoolSize <= 0) { ++ throw new IllegalArgumentException("Max pool size must be greater-than 0"); ++ } ++ ++ this.queue = new ArrayDeque<>(maxPoolSize); ++ this.maxPoolSize = maxPoolSize; ++ this.creator = creator; ++ this.releaser = releaser; ++ } ++ ++ public AutoReleased acquireCleaner(Object holder) { ++ return acquireCleaner(holder, this::release); ++ } ++ ++ public AutoReleased acquireCleaner(Object holder, Consumer releaser) { ++ E resource = acquire(); ++ Runnable cleaner = MCUtil.registerCleaner(holder, resource, releaser); ++ return new AutoReleased(resource, cleaner); ++ } ++ ++ public final E acquire() { ++ E value; ++ synchronized (queue) { ++ value = this.queue.pollLast(); ++ } ++ return value != null ? value : this.creator.get(); ++ } ++ ++ public final void release(final E value) { ++ if (this.releaser != null) { ++ this.releaser.accept(value); ++ } ++ synchronized (this.queue) { ++ if (queue.size() < this.maxPoolSize) { ++ this.queue.addLast(value); ++ } ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java +@@ -0,0 +1,67 @@ ++package com.destroystokyo.paper.util.set; ++ ++import java.util.Collection; ++ ++/** ++ * @author Spottedleaf ++ */ ++public final class OptimizedSmallEnumSet> { ++ ++ private final Class enumClass; ++ private long backingSet; ++ ++ public OptimizedSmallEnumSet(final Class clazz) { ++ if (clazz == null) { ++ throw new IllegalArgumentException("Null class"); ++ } ++ if (!clazz.isEnum()) { ++ throw new IllegalArgumentException("Class must be enum, not " + clazz.getCanonicalName()); ++ } ++ this.enumClass = clazz; ++ } ++ ++ public boolean addUnchecked(final E element) { ++ final int ordinal = element.ordinal(); ++ final long key = 1L << ordinal; ++ ++ final long prev = this.backingSet; ++ this.backingSet = prev | key; ++ ++ return (prev & key) == 0; ++ } ++ ++ public boolean removeUnchecked(final E element) { ++ final int ordinal = element.ordinal(); ++ final long key = 1L << ordinal; ++ ++ final long prev = this.backingSet; ++ this.backingSet = prev & ~key; ++ ++ return (prev & key) != 0; ++ } ++ ++ public void clear() { ++ this.backingSet = 0L; ++ } ++ ++ public int size() { ++ return Long.bitCount(this.backingSet); ++ } ++ ++ public void addAllUnchecked(final Collection enums) { ++ for (final E element : enums) { ++ if (element == null) { ++ throw new NullPointerException("Null element"); ++ } ++ this.backingSet |= (1L << element.ordinal()); ++ } ++ } ++ ++ public long getBackingSet() { ++ return this.backingSet; ++ } ++ ++ public boolean hasCommonElements(final OptimizedSmallEnumSet other) { ++ return (other.backingSet & this.backingSet) != 0; ++ } ++} +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index 8c378d3f3138953b3b22b289fecdb6b40a09ab63..67fa685f4b8de3eae1431c0de399c246678b542a 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -78,7 +78,7 @@ public class Util { + } + + public static long getNanos() { +- return Util.timeSource.getAsLong(); ++ return System.nanoTime(); // Paper + } + + public static long getEpochMillis() { +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 88147a1f25cf2fd549412b653b8f0eb5c60bb55d..6a58059a05e16d96894b67a544c2f595d9546c78 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -105,6 +105,7 @@ public class BlockPos extends Vec3i { + return x == 0.0D && y == 0.0D && z == 0.0D ? this : new BlockPos((double) this.getX() + x, (double) this.getY() + y, (double) this.getZ() + z); + } + ++ public final BlockPos add(int i, int j, int k) {return offset(i, j, k);} // Paper - OBFHELPER + public BlockPos offset(int x, int y, int z) { + return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.getX() + x, this.getY() + y, this.getZ() + z); + } +@@ -436,6 +437,7 @@ public class BlockPos extends Vec3i { + return super.rotate(rotation).immutable(); + } + ++ public final BlockPos.MutableBlockPos setValues(int i, int j, int k) { return set(i, j, k);} // Paper - OBFHELPER + public BlockPos.MutableBlockPos set(int x, int y, int z) { + this.setX(x); + this.setY(y); +@@ -443,6 +445,7 @@ public class BlockPos extends Vec3i { + return this; + } + ++ public final BlockPos.MutableBlockPos setValues(double d0, double d1, double d2) { return set(d0, d1, d2);} // Paper - OBFHELPER + public BlockPos.MutableBlockPos set(double x, double y, double z) { + return this.set(Mth.floor(x), Mth.floor(y), Mth.floor(z)); + } +@@ -496,20 +499,21 @@ public class BlockPos extends Vec3i { + } + } + ++ /* // Paper start - comment out useless overrides @Override + @Override +- public void setX(int x) { +- super.setX(x); ++ public void o(int i) { ++ super.o(i); + } + + @Override +- public void setY(int y) { +- super.setY(y); ++ public void p(int i) { ++ super.p(i); + } + +- @Override +- public void setZ(int z) { +- super.setZ(z); ++ public void q(int i) { ++ super.q(i); + } ++ */ // Paper end + + @Override + public BlockPos immutable() { +diff --git a/src/main/java/net/minecraft/core/IdMapper.java b/src/main/java/net/minecraft/core/IdMapper.java +index 424c6cacc2e7c7b1c9d0b92fe198237033a3fcbd..e7358721e9d78bc9cbbfc3e71ce927ea4b82ce7c 100644 +--- a/src/main/java/net/minecraft/core/IdMapper.java ++++ b/src/main/java/net/minecraft/core/IdMapper.java +@@ -64,6 +64,7 @@ public class IdMapper implements IdMap { + return Iterators.filter(this.idToT.iterator(), Predicates.notNull()); + } + ++ public int size() { return this.size(); } // Paper - OBFHELPER + public int size() { + return this.tToId.size(); + } +diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java +index 9bd2120bdcfe204184eb9a9e1daa5e3338665e51..3e79b274b8e0406a3cbdd94c7cec091b583109ca 100644 +--- a/src/main/java/net/minecraft/core/Vec3i.java ++++ b/src/main/java/net/minecraft/core/Vec3i.java +@@ -18,9 +18,9 @@ public class Vec3i implements Comparable { + return IntStream.of(new int[]{baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()}); + }); + public static final Vec3i ZERO = new Vec3i(0, 0, 0); +- private int x; +- private int y; +- private int z; ++ private int x;public final void setX(final int x) { this.x = x; } // Paper - OBFHELPER ++ private int y;public final void setY(final int y) { this.y = y; } // Paper - OBFHELPER ++ private int z;public final void setZ(final int z) { this.z = z; } // Paper - OBFHELPER + + public Vec3i(int x, int y, int z) { + this.x = x; +@@ -64,15 +64,15 @@ public class Vec3i implements Comparable { + return this.z; + } + +- protected void setX(int x) { ++ public void setX(int x) { // Paper - protected -> public + this.x = x; + } + +- protected void setY(int y) { ++ public void setY(int y) { // Paper - protected -> public + this.y = y; + } + +- protected void setZ(int z) { ++ public void setZ(int z) { // Paper - protected -> public + this.z = z; + } + +@@ -108,6 +108,7 @@ public class Vec3i implements Comparable { + return this.distSqr(pos.x(), pos.y(), pos.z(), true) < distance * distance; + } + ++ public final double distanceSquared(Vec3i baseblockposition) { return distSqr(baseblockposition); } // Paper - OBFHELPER + public double distSqr(Vec3i vec) { + return this.distSqr((double) vec.getX(), (double) vec.getY(), (double) vec.getZ(), true); + } +diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java +index 077383bd9af79851351eba50e7d7ea31cc106cad..4c8f249e45e5deb7628997d4dbd9dab613ac5241 100644 +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -76,7 +76,7 @@ public class CompoundTag implements Tag { + return "TAG_Compound"; + } + }; +- private final Map tags; ++ public final Map tags; // Paper + + protected CompoundTag(Map tags) { + this.tags = tags; +@@ -139,10 +139,16 @@ public class CompoundTag implements Tag { + this.tags.put(key, LongTag.valueOf(value)); + } + ++ public void setUUID(String prefix, UUID uuid) { putUUID(prefix, uuid); } // Paper - OBFHELPER + public void putUUID(String key, UUID value) { + this.tags.put(key, NbtUtils.createUUID(value)); + } + ++ ++ /** ++ * You must use {@link #hasUUID(String)} before or else it will throw an NPE. ++ */ ++ public UUID getUUID(String prefix) { return getUUID(prefix); } // Paper - OBFHELPER + public UUID getUUID(String key) { + return NbtUtils.loadUUID(this.get(key)); + } +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 8ce3a74821a0e540423a2e8e67be640b8b876035..92c5c5bbcfe364475578b6a0eddfaa85858ace8a 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -168,6 +168,7 @@ public class Connection extends SimpleChannelInboundHandler> { + + } + ++ private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.sendPacket(packet, genericFutureListener); } // Paper - OBFHELPER + private void sendPacket(Packet packet, @Nullable GenericFutureListener> callback) { + ConnectionProtocol enumprotocol = ConnectionProtocol.getProtocolForPacket(packet); + ConnectionProtocol enumprotocol1 = (ConnectionProtocol) this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).get(); +@@ -208,6 +209,7 @@ public class Connection extends SimpleChannelInboundHandler> { + + } + ++ private void sendPacketQueue() { this.flushQueue(); } // Paper - OBFHELPER + private void flushQueue() { + if (this.channel != null && this.channel.isOpen()) { + Queue queue = this.queue; +@@ -344,9 +346,9 @@ public class Connection extends SimpleChannelInboundHandler> { + + static class PacketHolder { + +- private final Packet packet; ++ private final Packet packet; private final Packet getPacket() { return this.packet; } // Paper - OBFHELPER + @Nullable +- private final GenericFutureListener> listener; ++ private final GenericFutureListener> listener; private final GenericFutureListener> getGenericFutureListener() { return this.listener; } // Paper - OBFHELPER + + public PacketHolder(Packet packet, @Nullable GenericFutureListener> callback) { + this.packet = packet; +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index e0dc41a8f408b7fa0b8554833ea4d09e7e604913..50f14acb062c2f90266279dbd1945a3297396f0b 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -48,6 +48,7 @@ public class FriendlyByteBuf extends ByteBuf { + this.source = bytebuf; + } + ++ public static int countBytes(int i) { return FriendlyByteBuf.getVarIntSize(i); } // Paper - OBFHELPER + public static int getVarIntSize(int i) { + for (int j = 1; j < 5; ++j) { + if ((i & -1 << j * 7) == 0) { +diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java +index 7af36e5a889d04f6e80c80f7335bf149a4b5d224..14fa1371e52b9af5a7550a9aa144fa406b754046 100644 +--- a/src/main/java/net/minecraft/network/PacketEncoder.java ++++ b/src/main/java/net/minecraft/network/PacketEncoder.java +@@ -44,6 +44,7 @@ public class PacketEncoder extends MessageToByteEncoder> { + packet.write(packetdataserializer); + } catch (Throwable throwable) { + PacketEncoder.LOGGER.error(throwable); ++ throwable.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? + if (packet.isSkippable()) { + throw new SkipPacketException(throwable); + } else { +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index bda189ab2b3b934e6bf9fd11da5d95bd9b37ba70..e5d4363edb8c494d2db69d2e0223a2db1519f64b 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -28,7 +28,7 @@ public class ClientboundLevelChunkPacket implements Packet blockEntitiesTags; + private boolean fullChunk; + +@@ -140,6 +140,7 @@ public class ClientboundLevelChunkPacket implements Packet { + +- private ItemStack book; ++ private ItemStack book; public ItemStack getBook() { return book; } // Paper - OBFHELPER + private boolean signing; + private int slot; + +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d29fe67b7d39e368a873368a6be16042429e9209 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -0,0 +1,510 @@ ++package net.minecraft.server; ++ ++import com.destroystokyo.paper.block.TargetBlockInfo; ++import com.google.common.util.concurrent.ThreadFactoryBuilder; ++import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.ClipContext; ++import net.minecraft.world.level.Level; ++import org.apache.commons.lang.exception.ExceptionUtils; ++import org.bukkit.Location; ++import org.bukkit.block.BlockFace; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.spigotmc.AsyncCatcher; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++import java.util.List; ++import java.util.Queue; ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.ExecutionException; ++import java.util.concurrent.LinkedBlockingQueue; ++import java.util.concurrent.ThreadPoolExecutor; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++import java.util.concurrent.atomic.AtomicBoolean; ++import java.util.function.BiConsumer; ++import java.util.function.Consumer; ++import java.util.function.Supplier; ++ ++public final class MCUtil { ++ public static final ThreadPoolExecutor asyncExecutor = new ThreadPoolExecutor( ++ 0, 2, 60L, TimeUnit.SECONDS, ++ new LinkedBlockingQueue(), ++ new ThreadFactoryBuilder().setNameFormat("Paper Async Task Handler Thread - %1$d").build() ++ ); ++ public static final ThreadPoolExecutor cleanerExecutor = new ThreadPoolExecutor( ++ 1, 1, 0L, TimeUnit.SECONDS, ++ new LinkedBlockingQueue(), ++ new ThreadFactoryBuilder().setNameFormat("Paper Object Cleaner").build() ++ ); ++ ++ public static final long INVALID_CHUNK_KEY = getCoordinateKey(Integer.MAX_VALUE, Integer.MAX_VALUE); ++ ++ ++ public static Runnable once(Runnable run) { ++ AtomicBoolean ran = new AtomicBoolean(false); ++ return () -> { ++ if (ran.compareAndSet(false, true)) { ++ run.run(); ++ } ++ }; ++ } ++ ++ public static Runnable once(List list, Consumer cb) { ++ return once(() -> { ++ list.forEach(cb); ++ }); ++ } ++ ++ private static Runnable makeCleanerCallback(Runnable run) { ++ return once(() -> cleanerExecutor.execute(run)); ++ } ++ ++ /** ++ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! ++ * @param obj ++ * @param run ++ * @return ++ */ ++ public static Runnable registerCleaner(Object obj, Runnable run) { ++ // Wrap callback in its own method above or the lambda will leak object ++ Runnable cleaner = makeCleanerCallback(run); ++ co.aikar.cleaner.Cleaner.register(obj, cleaner); ++ return cleaner; ++ } ++ ++ /** ++ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! ++ * @param obj ++ * @param list ++ * @param cleaner ++ * @param ++ * @return ++ */ ++ public static Runnable registerListCleaner(Object obj, List list, Consumer cleaner) { ++ return registerCleaner(obj, () -> { ++ list.forEach(cleaner); ++ list.clear(); ++ }); ++ } ++ ++ /** ++ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! ++ * @param obj ++ * @param resource ++ * @param cleaner ++ * @param ++ * @return ++ */ ++ public static Runnable registerCleaner(Object obj, T resource, java.util.function.Consumer cleaner) { ++ return registerCleaner(obj, () -> cleaner.accept(resource)); ++ } ++ ++ public static List getSpiralOutChunks(BlockPos blockposition, int radius) { ++ List list = com.google.common.collect.Lists.newArrayList(); ++ ++ list.add(new ChunkPos(blockposition.getX() >> 4, blockposition.getZ() >> 4)); ++ for (int r = 1; r <= radius; r++) { ++ int x = -r; ++ int z = r; ++ ++ // Iterates the edge of half of the box; then negates for other half. ++ while (x <= r && z > -r) { ++ list.add(new ChunkPos((blockposition.getX() + (x << 4)) >> 4, (blockposition.getZ() + (z << 4)) >> 4)); ++ list.add(new ChunkPos((blockposition.getX() - (x << 4)) >> 4, (blockposition.getZ() - (z << 4)) >> 4)); ++ ++ if (x < r) { ++ x++; ++ } else { ++ z--; ++ } ++ } ++ } ++ return list; ++ } ++ ++ public static int fastFloor(double x) { ++ int truncated = (int)x; ++ return x < (double)truncated ? truncated - 1 : truncated; ++ } ++ ++ public static int fastFloor(float x) { ++ int truncated = (int)x; ++ return x < (double)truncated ? truncated - 1 : truncated; ++ } ++ ++ public static float normalizeYaw(float f) { ++ float f1 = f % 360.0F; ++ ++ if (f1 >= 180.0F) { ++ f1 -= 360.0F; ++ } ++ ++ if (f1 < -180.0F) { ++ f1 += 360.0F; ++ } ++ ++ return f1; ++ } ++ ++ /** ++ * Quickly generate a stack trace for current location ++ * ++ * @return Stacktrace ++ */ ++ public static String stack() { ++ return ExceptionUtils.getFullStackTrace(new Throwable()); ++ } ++ ++ /** ++ * Quickly generate a stack trace for current location with message ++ * ++ * @param str ++ * @return Stacktrace ++ */ ++ public static String stack(String str) { ++ return ExceptionUtils.getFullStackTrace(new Throwable(str)); ++ } ++ ++ public static long getCoordinateKey(final BlockPos blockPos) { ++ return ((long)(blockPos.getZ() >> 4) << 32) | ((blockPos.getX() >> 4) & 0xFFFFFFFFL); ++ } ++ ++ public static long getCoordinateKey(final Entity entity) { ++ return ((long)(MCUtil.fastFloor(entity.getZ()) >> 4) << 32) | ((MCUtil.fastFloor(entity.getX()) >> 4) & 0xFFFFFFFFL); ++ } ++ ++ public static long getCoordinateKey(final ChunkPos pair) { ++ return ((long)pair.z << 32) | (pair.x & 0xFFFFFFFFL); ++ } ++ ++ public static long getCoordinateKey(final int x, final int z) { ++ return ((long)z << 32) | (x & 0xFFFFFFFFL); ++ } ++ ++ public static int getCoordinateX(final long key) { ++ return (int)key; ++ } ++ ++ public static int getCoordinateZ(final long key) { ++ return (int)(key >>> 32); ++ } ++ ++ public static int getChunkCoordinate(final double coordinate) { ++ return MCUtil.fastFloor(coordinate) >> 4; ++ } ++ ++ public static int getBlockCoordinate(final double coordinate) { ++ return MCUtil.fastFloor(coordinate); ++ } ++ ++ public static long getBlockKey(final int x, final int y, final int z) { ++ return ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54); ++ } ++ ++ public static long getBlockKey(final BlockPos pos) { ++ return ((long)pos.getX() & 0x7FFFFFF) | (((long)pos.getZ() & 0x7FFFFFF) << 27) | ((long)pos.getY() << 54); ++ } ++ ++ public static long getBlockKey(final Entity entity) { ++ return getBlockKey(getBlockCoordinate(entity.getX()), getBlockCoordinate(entity.getY()), getBlockCoordinate(entity.getZ())); ++ } ++ ++ // assumes the sets have the same comparator, and if this comparator is null then assume T is Comparable ++ public static void mergeSortedSets(final java.util.function.Consumer consumer, final java.util.Comparator comparator, final java.util.SortedSet...sets) { ++ final ObjectRBTreeSet all = new ObjectRBTreeSet<>(comparator); ++ // note: this is done in log(n!) ~ nlogn time. It could be improved if it were to mimic what mergesort does. ++ for (java.util.SortedSet set : sets) { ++ if (set != null) { ++ all.addAll(set); ++ } ++ } ++ all.forEach(consumer); ++ } ++ ++ private MCUtil() {} ++ ++ public static final java.util.concurrent.Executor MAIN_EXECUTOR = (run) -> { ++ if (!isMainThread()) { ++ MinecraftServer.getServer().execute(run); ++ } else { ++ run.run(); ++ } ++ }; ++ ++ public static CompletableFuture ensureMain(CompletableFuture future) { ++ return future.thenApplyAsync(r -> r, MAIN_EXECUTOR); ++ } ++ ++ public static void thenOnMain(CompletableFuture future, Consumer consumer) { ++ future.thenAcceptAsync(consumer, MAIN_EXECUTOR); ++ } ++ public static void thenOnMain(CompletableFuture future, BiConsumer consumer) { ++ future.whenCompleteAsync(consumer, MAIN_EXECUTOR); ++ } ++ ++ public static boolean isMainThread() { ++ return MinecraftServer.getServer().isSameThread(); ++ } ++ ++ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable) { ++ return scheduleTask(ticks, runnable, null); ++ } ++ ++ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable, String taskName) { ++ return MinecraftServer.getServer().server.getScheduler().scheduleInternalTask(runnable, ticks, taskName); ++ } ++ ++ public static void processQueue() { ++ Runnable runnable; ++ Queue processQueue = getProcessQueue(); ++ while ((runnable = processQueue.poll()) != null) { ++ try { ++ runnable.run(); ++ } catch (Exception e) { ++ MinecraftServer.LOGGER.error("Error executing task", e); ++ } ++ } ++ } ++ public static T processQueueWhileWaiting(CompletableFuture future) { ++ try { ++ if (isMainThread()) { ++ while (!future.isDone()) { ++ try { ++ return future.get(1, TimeUnit.MILLISECONDS); ++ } catch (TimeoutException ignored) { ++ processQueue(); ++ } ++ } ++ } ++ return future.get(); ++ } catch (Exception e) { ++ throw new RuntimeException(e); ++ } ++ } ++ ++ public static void ensureMain(Runnable run) { ++ ensureMain(null, run); ++ } ++ /** ++ * Ensures the target code is running on the main thread ++ * @param reason ++ * @param run ++ * @return ++ */ ++ public static void ensureMain(String reason, Runnable run) { ++ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { ++ if (reason != null) { ++ new IllegalStateException("Asynchronous " + reason + "!").printStackTrace(); ++ } ++ getProcessQueue().add(run); ++ return; ++ } ++ run.run(); ++ } ++ ++ private static Queue getProcessQueue() { ++ return MinecraftServer.getServer().processQueue; ++ } ++ ++ public static T ensureMain(Supplier run) { ++ return ensureMain(null, run); ++ } ++ /** ++ * Ensures the target code is running on the main thread ++ * @param reason ++ * @param run ++ * @param ++ * @return ++ */ ++ public static T ensureMain(String reason, Supplier run) { ++ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { ++ if (reason != null) { ++ new IllegalStateException("Asynchronous " + reason + "! Blocking thread until it returns ").printStackTrace(); ++ } ++ Waitable wait = new Waitable() { ++ @Override ++ protected T evaluate() { ++ return run.get(); ++ } ++ }; ++ getProcessQueue().add(wait); ++ try { ++ return wait.get(); ++ } catch (InterruptedException | ExecutionException e) { ++ e.printStackTrace(); ++ } ++ return null; ++ } ++ return run.get(); ++ } ++ ++ /** ++ * Calculates distance between 2 entities ++ * @param e1 ++ * @param e2 ++ * @return ++ */ ++ public static double distance(Entity e1, Entity e2) { ++ return Math.sqrt(distanceSq(e1, e2)); ++ } ++ ++ ++ /** ++ * Calculates distance between 2 block positions ++ * @param e1 ++ * @param e2 ++ * @return ++ */ ++ public static double distance(BlockPos e1, BlockPos e2) { ++ return Math.sqrt(distanceSq(e1, e2)); ++ } ++ ++ /** ++ * Gets the distance between 2 positions ++ * @param x1 ++ * @param y1 ++ * @param z1 ++ * @param x2 ++ * @param y2 ++ * @param z2 ++ * @return ++ */ ++ public static double distance(double x1, double y1, double z1, double x2, double y2, double z2) { ++ return Math.sqrt(distanceSq(x1, y1, z1, x2, y2, z2)); ++ } ++ ++ /** ++ * Get's the distance squared between 2 entities ++ * @param e1 ++ * @param e2 ++ * @return ++ */ ++ public static double distanceSq(Entity e1, Entity e2) { ++ return distanceSq(e1.getX(),e1.getY(),e1.getZ(), e2.getX(),e2.getY(),e2.getZ()); ++ } ++ ++ /** ++ * Gets the distance sqaured between 2 block positions ++ * @param pos1 ++ * @param pos2 ++ * @return ++ */ ++ public static double distanceSq(BlockPos pos1, BlockPos pos2) { ++ return distanceSq(pos1.getX(), pos1.getY(), pos1.getZ(), pos2.getX(), pos2.getY(), pos2.getZ()); ++ } ++ ++ /** ++ * Gets the distance squared between 2 positions ++ * @param x1 ++ * @param y1 ++ * @param z1 ++ * @param x2 ++ * @param y2 ++ * @param z2 ++ * @return ++ */ ++ public static double distanceSq(double x1, double y1, double z1, double x2, double y2, double z2) { ++ return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2); ++ } ++ ++ /** ++ * Converts a NMS World/BlockPosition to Bukkit Location ++ * @param world ++ * @param x ++ * @param y ++ * @param z ++ * @return ++ */ ++ public static Location toLocation(Level world, double x, double y, double z) { ++ return new Location(world.getWorld(), x, y, z); ++ } ++ ++ /** ++ * Converts a NMS World/BlockPosition to Bukkit Location ++ * @param world ++ * @param pos ++ * @return ++ */ ++ public static Location toLocation(Level world, BlockPos pos) { ++ return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()); ++ } ++ ++ /** ++ * Converts an NMS entity's current location to a Bukkit Location ++ * @param entity ++ * @return ++ */ ++ public static Location toLocation(Entity entity) { ++ return new Location(entity.getCommandSenderWorld().getWorld(), entity.getX(), entity.getY(), entity.getZ()); ++ } ++ ++ public static org.bukkit.block.Block toBukkitBlock(Level world, BlockPos pos) { ++ return world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ } ++ ++ public static BlockPos toBlockPosition(Location loc) { ++ return new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); ++ } ++ ++ public static boolean isEdgeOfChunk(BlockPos pos) { ++ final int modX = pos.getX() & 15; ++ final int modZ = pos.getZ() & 15; ++ return (modX == 0 || modX == 15 || modZ == 0 || modZ == 15); ++ } ++ ++ /** ++ * Posts a task to be executed asynchronously ++ * @param run ++ */ ++ public static void scheduleAsyncTask(Runnable run) { ++ asyncExecutor.execute(run); ++ } ++ ++ @Nonnull ++ public static ServerLevel getNMSWorld(@Nonnull org.bukkit.World world) { ++ return ((CraftWorld) world).getHandle(); ++ } ++ ++ public static ServerLevel getNMSWorld(@Nonnull org.bukkit.entity.Entity entity) { ++ return getNMSWorld(entity.getWorld()); ++ } ++ ++ public static ClipContext.Fluid getNMSFluidCollisionOption(TargetBlockInfo.FluidMode fluidMode) { ++ if (fluidMode == TargetBlockInfo.FluidMode.NEVER) { ++ return ClipContext.Fluid.NONE; ++ } ++ if (fluidMode == TargetBlockInfo.FluidMode.SOURCE_ONLY) { ++ return ClipContext.Fluid.SOURCE_ONLY; ++ } ++ if (fluidMode == TargetBlockInfo.FluidMode.ALWAYS) { ++ return ClipContext.Fluid.ANY; ++ } ++ return null; ++ } ++ ++ public static BlockFace toBukkitBlockFace(Direction enumDirection) { ++ switch (enumDirection) { ++ case DOWN: ++ return BlockFace.DOWN; ++ case UP: ++ return BlockFace.UP; ++ case NORTH: ++ return BlockFace.NORTH; ++ case SOUTH: ++ return BlockFace.SOUTH; ++ case WEST: ++ return BlockFace.WEST; ++ case EAST: ++ return BlockFace.EAST; ++ default: ++ return null; ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 37a51dee4cd37844e80fdd5c9853947201151dfc..2406879e76a110e96a4753e66366432a4bc52d9b 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -882,6 +882,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop CHUNK_STATUSES = ChunkStatus.getStatusList(); + private static final ChunkHolder.FullChunkStatus[] FULL_CHUNK_STATUSES = ChunkHolder.FullChunkStatus.values(); + private final AtomicReferenceArray>> futures; +- private volatile CompletableFuture> fullChunkFuture; +- private volatile CompletableFuture> tickingChunkFuture; +- private volatile CompletableFuture> entityTickingChunkFuture; ++ private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage ++ private volatile CompletableFuture> tickingChunkFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage ++ private volatile CompletableFuture> entityTickingChunkFuture; private volatile boolean isEntityTickingReady; // Paper - cache chunk ticking stage + private CompletableFuture chunkToSave; + public int oldTicketLevel; + private int ticketLevel; +@@ -63,6 +63,8 @@ public class ChunkHolder { + private boolean wasAccessibleSinceLastSave; + private boolean resendLight; + ++ private final ChunkMap chunkMap; // Paper ++ + public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +@@ -78,10 +80,49 @@ public class ChunkHolder { + this.ticketLevel = this.oldTicketLevel; + this.queueLevel = this.oldTicketLevel; + this.setTicketLevel(level); ++ this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper ++ } ++ ++ // Paper start ++ @Nullable ++ public final LevelChunk getEntityTickingChunk() { ++ CompletableFuture> completablefuture = this.entityTickingChunkFuture; ++ Either either = completablefuture.getNow(null); ++ ++ return either == null ? null : either.left().orElse(null); ++ } ++ ++ @Nullable ++ public final LevelChunk getTickingChunk() { ++ CompletableFuture> completablefuture = this.tickingChunkFuture; ++ Either either = completablefuture.getNow(null); ++ ++ return either == null ? null : either.left().orElse(null); ++ } ++ ++ @Nullable ++ public final LevelChunk getFullReadyChunk() { ++ CompletableFuture> completablefuture = this.fullChunkFuture; ++ Either either = completablefuture.getNow(null); ++ ++ return either == null ? null : either.left().orElse(null); ++ } ++ ++ public final boolean isEntityTickingReady() { ++ return this.isEntityTickingReady; ++ } ++ ++ public final boolean isTickingReady() { ++ return this.isTickingReady; ++ } ++ ++ public final boolean isFullChunkReady() { ++ return this.isFullChunkReady; + } ++ // Paper end + + // CraftBukkit start +- public LevelChunk getFullChunk() { ++ public final LevelChunk getFullChunk() { // Paper - final for inline + if (!getFullChunkStatus(this.oldTicketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) return null; // note: using oldTicketLevel for isLoaded checks + return this.getFullChunkUnchecked(); + } +@@ -92,6 +133,14 @@ public class ChunkHolder { + return (either == null) ? null : (LevelChunk) either.left().orElse(null); + } + // CraftBukkit end ++ // Paper start - "real" get full chunk immediately ++ public final LevelChunk getFullChunkIfCached() { ++ // Note: Copied from above without ticket level check ++ CompletableFuture> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL); ++ Either either = (Either) statusFuture.getNow(null); ++ return either == null ? null : (LevelChunk) either.left().orElse(null); ++ } ++ // Paper end + + public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { + CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(leastStatus.getIndex()); +@@ -103,20 +152,23 @@ public class ChunkHolder { + return getStatus(this.ticketLevel).isOrAfter(leastStatus) ? this.getFutureIfPresentUnchecked(leastStatus) : ChunkHolder.UNLOADED_CHUNK_FUTURE; + } + +- public CompletableFuture> getTickingChunkFuture() { ++ public final CompletableFuture> getTickingFuture() { return this.getTickingChunkFuture(); } // Paper - OBFHELPER ++ public final CompletableFuture> getTickingChunkFuture() { // Paper - final for inline + return this.tickingChunkFuture; + } + +- public CompletableFuture> getEntityTickingChunkFuture() { ++ public final CompletableFuture> getEntityTickingFuture() { return this.getEntityTickingChunkFuture(); } // Paper - OBFHELPER ++ public final CompletableFuture> getEntityTickingChunkFuture() { // Paper - final for inline + return this.entityTickingChunkFuture; + } + +- public CompletableFuture> getFullChunkFuture() { ++ public final CompletableFuture> getFullChunkFuture() { return this.getFullChunkFuture(); } // Paper - OBFHELPER ++ public final CompletableFuture> getFullChunkFuture() { // Paper - final for inline + return this.fullChunkFuture; + } + + @Nullable +- public LevelChunk getTickingChunk() { ++ public final LevelChunk getTickingChunk() { // Paper - final for inline + CompletableFuture> completablefuture = this.getTickingChunkFuture(); + Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error + +@@ -141,7 +193,7 @@ public class ChunkHolder { + return null; + } + +- public CompletableFuture getChunkToSave() { ++ public final CompletableFuture getChunkToSave() { // Paper - final for inline + return this.chunkToSave; + } + +@@ -282,11 +334,11 @@ public class ChunkHolder { + }); + } + +- public ChunkPos getPos() { ++ public final ChunkPos getPos() { // Paper - final for inline + return this.pos; + } + +- public int getTicketLevel() { ++ public final int getTicketLevel() { // Paper - final for inline + return this.ticketLevel; + } + +@@ -357,13 +409,27 @@ public class ChunkHolder { + + this.wasAccessibleSinceLastSave |= flag3; + if (!flag2 && flag3) { +- this.fullChunkFuture = chunkStorage.unpackTicks(this); ++ // Paper start - cache ticking ready status ++ int expectCreateCount = ++this.fullChunkCreateCount; ++ this.fullChunkFuture = chunkStorage.unpackTicks(this); this.fullChunkFuture.thenAccept((either) -> { ++ if (either.left().isPresent() && ChunkHolder.this.fullChunkCreateCount == expectCreateCount) { ++ // note: Here is a very good place to add callbacks to logic waiting on this. ++ LevelChunk fullChunk = either.left().get(); ++ ChunkHolder.this.isFullChunkReady = true; ++ fullChunk.playerChunk = ChunkHolder.this; ++ ++ ++ } ++ }); ++ // Paper end + this.updateChunkToSave(this.fullChunkFuture); + } + + if (flag2 && !flag3) { + completablefuture = this.fullChunkFuture; + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; ++ ++this.fullChunkCreateCount; // Paper - cache ticking ready status ++ this.isFullChunkReady = false; // Paper - cache ticking ready status + this.updateChunkToSave(((CompletableFuture>) completablefuture).thenApply((either1) -> { // CraftBukkit - decompile error + chunkStorage.getClass(); + return either1.ifLeft(chunkStorage::packTicks); +@@ -374,12 +440,24 @@ public class ChunkHolder { + boolean flag5 = playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.TICKING); + + if (!flag4 && flag5) { +- this.tickingChunkFuture = chunkStorage.postProcess(this); ++ // Paper start - cache ticking ready status ++ this.tickingChunkFuture = chunkStorage.postProcess(this); this.tickingChunkFuture.thenAccept((either) -> { ++ if (either.left().isPresent()) { ++ // note: Here is a very good place to add callbacks to logic waiting on this. ++ LevelChunk tickingChunk = either.left().get(); ++ ChunkHolder.this.isTickingReady = true; ++ ++ ++ ++ ++ } ++ }); ++ // Paper end + this.updateChunkToSave(this.tickingChunkFuture); + } + + if (flag4 && !flag5) { +- this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); ++ this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); this.isTickingReady = false; // Paper - cache chunk ticking stage + this.tickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + } + +@@ -391,12 +469,24 @@ public class ChunkHolder { + throw (IllegalStateException) Util.pauseInIde((Throwable) (new IllegalStateException())); + } + +- this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); ++ // Paper start - cache ticking ready status ++ this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); this.entityTickingChunkFuture.thenAccept((either) -> { ++ if (either.left().isPresent()) { ++ // note: Here is a very good place to add callbacks to logic waiting on this. ++ LevelChunk entityTickingChunk = either.left().get(); ++ ChunkHolder.this.isEntityTickingReady = true; ++ ++ ++ ++ ++ } ++ }); ++ // Paper end + this.updateChunkToSave(this.entityTickingChunkFuture); + } + + if (flag6 && !flag7) { +- this.entityTickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); ++ this.entityTickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage + this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + } + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index aaa56d121cdb66066e869b7cbdc2c863974d51b0..d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -54,6 +54,7 @@ import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; + import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; + import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; + import net.minecraft.network.protocol.game.DebugPackets; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.progress.ChunkProgressListener; + import net.minecraft.util.CsvOutput; + import net.minecraft.util.Mth; +@@ -144,6 +145,26 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }; + // CraftBukkit end + ++ // Paper start - distance maps ++ private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); ++ ++ void addPlayerToDistanceMaps(ServerPlayer player) { ++ int chunkX = MCUtil.getChunkCoordinate(player.getX()); ++ int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); ++ // Note: players need to be explicitly added to distance maps before they can be updated ++ } ++ ++ void removePlayerFromDistanceMaps(ServerPlayer player) { ++ ++ } ++ ++ void updateMaps(ServerPlayer player) { ++ int chunkX = MCUtil.getChunkCoordinate(player.getX()); ++ int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); ++ // Note: players need to be explicitly added to distance maps before they can be updated ++ } ++ // Paper end ++ + public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier supplier, int i, boolean flag) { + super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag); + this.visibleChunkMap = this.updatingChunkMap.clone(); +@@ -233,6 +254,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }; + } + ++ // Paper start ++ public final int getEffectiveViewDistance() { ++ // TODO this needs to be checked on update ++ // Mojang currently sets it to +1 of the configured view distance. So subtract one to get the one we really want. ++ return this.viewDistance - 1; ++ } ++ // Paper end ++ + private CompletableFuture, ChunkHolder.ChunkLoadingFailure>> getChunkRangeFuture(ChunkPos centerChunk, int margin, IntFunction distanceToStatus) { + List>> list = Lists.newArrayList(); + int j = centerChunk.x; +@@ -951,6 +980,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (!flag1) { + this.distanceManager.addPlayer(SectionPos.of((Entity) player), player); + } ++ this.addPlayerToDistanceMaps(player); // Paper - distance maps + } else { + SectionPos sectionposition = player.getLastSectionPos(); + +@@ -958,6 +988,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (!flag2) { + this.distanceManager.removePlayer(sectionposition, player); + } ++ this.removePlayerFromDistanceMaps(player); // Paper - distance maps + } + + for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { +@@ -1068,6 +1099,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + } + ++ this.updateMaps(player); // Paper - distance maps ++ + } + + @Override +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 7cc5070f70a4f740add9d971385ceaa4d44275a2..ef336645f3bd7a86129ad1dff7e1a15dc93d1e3e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -42,6 +42,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelData; + import net.minecraft.world.level.storage.LevelStorageSource; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper + + public class ServerChunkCache extends ChunkSource { + +@@ -49,7 +50,7 @@ public class ServerChunkCache extends ChunkSource { + private final DistanceManager distanceManager; + public final ChunkGenerator generator; + private final ServerLevel level; +- private final Thread mainThread; ++ public final Thread mainThread; // Paper - private -> public + private final ThreadedLevelLightEngine lightEngine; + private final ServerChunkCache.MainThreadExecutor mainThreadProcessor; + public final ChunkMap chunkMap; +@@ -62,6 +63,158 @@ public class ServerChunkCache extends ChunkSource { + private final ChunkAccess[] lastChunk = new ChunkAccess[4]; + @Nullable + private NaturalSpawner.SpawnState lastSpawnState; ++ // Paper start ++ final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock(); ++ final Long2ObjectOpenHashMap loadedChunkMap = new Long2ObjectOpenHashMap<>(8192, 0.5f); ++ ++ private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4]; ++ ++ private static int getChunkCacheKey(int x, int z) { ++ return x & 3 | ((z & 3) << 2); ++ } ++ ++ public void addLoadedChunk(LevelChunk chunk) { ++ this.loadedChunkMapSeqLock.acquireWrite(); ++ try { ++ this.loadedChunkMap.put(chunk.coordinateKey, chunk); ++ } finally { ++ this.loadedChunkMapSeqLock.releaseWrite(); ++ } ++ ++ // rewrite cache if we have to ++ // we do this since we also cache null chunks ++ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); ++ ++ this.lastLoadedChunks[cacheKey] = chunk; ++ } ++ ++ public void removeLoadedChunk(LevelChunk chunk) { ++ this.loadedChunkMapSeqLock.acquireWrite(); ++ try { ++ this.loadedChunkMap.remove(chunk.coordinateKey); ++ } finally { ++ this.loadedChunkMapSeqLock.releaseWrite(); ++ } ++ ++ // rewrite cache if we have to ++ // we do this since we also cache null chunks ++ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); ++ ++ LevelChunk cachedChunk = this.lastLoadedChunks[cacheKey]; ++ if (cachedChunk != null && cachedChunk.coordinateKey == chunk.coordinateKey) { ++ this.lastLoadedChunks[cacheKey] = null; ++ } ++ } ++ ++ public final LevelChunk getChunkAtIfLoadedMainThread(int x, int z) { ++ int cacheKey = getChunkCacheKey(x, z); ++ ++ LevelChunk cachedChunk = this.lastLoadedChunks[cacheKey]; ++ if (cachedChunk != null && cachedChunk.locX == x & cachedChunk.locZ == z) { ++ return this.lastLoadedChunks[cacheKey]; ++ } ++ ++ long chunkKey = ChunkPos.asLong(x, z); ++ ++ cachedChunk = this.loadedChunkMap.get(chunkKey); ++ // Skipping a null check to avoid extra instructions to improve inline capability ++ this.lastLoadedChunks[cacheKey] = cachedChunk; ++ return cachedChunk; ++ } ++ ++ public final LevelChunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) { ++ return this.loadedChunkMap.get(ChunkPos.asLong(x, z)); ++ } ++ ++ public final LevelChunk getChunkAtMainThread(int x, int z) { ++ LevelChunk ret = this.getChunkAtIfLoadedMainThread(x, z); ++ if (ret != null) { ++ return ret; ++ } ++ return (LevelChunk)this.getChunk(x, z, ChunkStatus.FULL, true); ++ } ++ ++ private long chunkFutureAwaitCounter; ++ ++ public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.mainThread) { ++ this.mainThreadProcessor.execute(() -> { ++ ServerChunkCache.this.getEntityTickingChunkAsync(x, z, onLoad); ++ }); ++ return; ++ } ++ this.getChunkFutureAsynchronously(x, z, 31, ChunkHolder::getEntityTickingFuture, onLoad); ++ } ++ ++ public void getTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.mainThread) { ++ this.mainThreadProcessor.execute(() -> { ++ ServerChunkCache.this.getTickingChunkAsync(x, z, onLoad); ++ }); ++ return; ++ } ++ this.getChunkFutureAsynchronously(x, z, 32, ChunkHolder::getTickingFuture, onLoad); ++ } ++ ++ public void getFullChunkAsync(int x, int z, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.mainThread) { ++ this.mainThreadProcessor.execute(() -> { ++ ServerChunkCache.this.getFullChunkAsync(x, z, onLoad); ++ }); ++ return; ++ } ++ this.getChunkFutureAsynchronously(x, z, 33, ChunkHolder::getFullChunkFuture, onLoad); ++ } ++ ++ private void getChunkFutureAsynchronously(int x, int z, int ticketLevel, Function>> futureGet, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.mainThread) { ++ throw new IllegalStateException(); ++ } ++ ChunkPos chunkPos = new ChunkPos(x, z); ++ Long identifier = this.chunkFutureAwaitCounter++; ++ this.distanceManager.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); ++ this.runDistanceManagerUpdates(); ++ ++ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(chunkPos.toLong()); ++ ++ if (chunk == null) { ++ throw new IllegalStateException("Expected playerchunk " + chunkPos + " in world '" + this.level.getWorld().getName() + "'"); ++ } ++ ++ CompletableFuture> future = futureGet.apply(chunk); ++ ++ future.whenCompleteAsync((either, throwable) -> { ++ try { ++ if (throwable != null) { ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath)throwable; ++ } ++ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", throwable); ++ } else if (either.right().isPresent()) { ++ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "': " + either.right().get().toString()); ++ } ++ ++ try { ++ if (onLoad != null) { ++ chunkMap.callbackExecutor.execute(() -> { ++ onLoad.accept(either == null ? null : either.left().orElse(null)); // indicate failure to the callback. ++ }); ++ } ++ } catch (Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ net.minecraft.server.MinecraftServer.LOGGER.fatal("Load callback for future await failed " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", thr); ++ return; ++ } ++ } finally { ++ // due to odd behaviour with CB unload implementation we need to have these AFTER the load callback. ++ ServerChunkCache.this.distanceManager.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); ++ ServerChunkCache.this.distanceManager.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); ++ } ++ }, this.mainThreadProcessor); ++ } ++ // Paper end + + public ServerChunkCache(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldloadlistener, Supplier supplier) { + this.level = worldserver; +@@ -123,6 +276,49 @@ public class ServerChunkCache extends ChunkSource { + this.lastChunk[0] = chunk; + } + ++ // Paper start - "real" get chunk if loaded ++ // Note: Partially copied from the getChunkAt method below ++ @Nullable ++ public LevelChunk getChunkAtIfCachedImmediately(int x, int z) { ++ long k = ChunkPos.asLong(x, z); ++ ++ // Note: Bypass cache since we need to check ticket level, and to make this MT-Safe ++ ++ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(k); ++ if (playerChunk == null) { ++ return null; ++ } ++ ++ return playerChunk.getFullChunkIfCached(); ++ } ++ ++ @Nullable ++ public LevelChunk getChunkAtIfLoadedImmediately(int x, int z) { ++ long k = ChunkPos.asLong(x, z); ++ ++ if (Thread.currentThread() == this.mainThread) { ++ return this.getChunkAtIfLoadedMainThread(x, z); ++ } ++ ++ LevelChunk ret = null; ++ long readlock; ++ do { ++ readlock = this.loadedChunkMapSeqLock.acquireRead(); ++ try { ++ ret = this.loadedChunkMap.get(k); ++ } catch (Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ // re-try, this means a CME occurred... ++ continue; ++ } ++ } while (!this.loadedChunkMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ // Paper end ++ + @Nullable + @Override + public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) { +@@ -406,10 +602,9 @@ public class ServerChunkCache extends ChunkSource { + + this.lastSpawnState = spawnercreature_d; + this.level.getProfiler().pop(); +- List list = Lists.newArrayList(this.chunkMap.getChunks()); +- +- Collections.shuffle(list); +- list.forEach((playerchunk) -> { ++ //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper ++ //Collections.shuffle(list); // Paper ++ this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + + if (optional.isPresent()) { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 23506a8903ce64fbfe849bb94e589bdbb6e61a74..34ed8f0d348e7bc2339660ebc6490057ba9ef214 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -12,6 +12,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry; + import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.longs.LongSets; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; + import java.io.BufferedWriter; +@@ -163,7 +164,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + private final Map entitiesByUuid = Maps.newHashMap(); + private final Queue toAddAfterTick = Queues.newArrayDeque(); + private final List players = Lists.newArrayList(); +- private final ServerChunkCache chunkSource; ++ public final ServerChunkCache chunkSource; // Paper - public + boolean tickingEntities; + private final MinecraftServer server; + public final PrimaryLevelData worldDataServer; // CraftBukkit - type +@@ -1682,7 +1683,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + ObjectIterator objectiterator = spawnercreature_d.getMobCategoryCounts().object2IntEntrySet().iterator(); + + while (objectiterator.hasNext()) { +- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); ++ Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix + + bufferedwriter.write(String.format("spawn_count.%s: %d\n", ((MobCategory) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey()).getName(), it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue())); + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index d62c74318ac3bb139570fe2b5f12cdb6e900d70d..8d7fa186b0b47688f2822038b46c33b3f32d28ae 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -221,6 +221,8 @@ public class ServerPlayer extends Player implements ContainerListener { + public Integer clientViewDistance; + // CraftBukkit end + ++ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper ++ + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { + super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); + this.respawnDimension = Level.OVERWORLD; +@@ -233,6 +235,8 @@ public class ServerPlayer extends Player implements ContainerListener { + this.fudgeSpawnLocation(world); + this.textFilter = server.createTextFilterForPlayer(this); + ++ this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper ++ + // CraftBukkit start + this.displayName = this.getScoreboardName(); + this.canPickUpLoot = true; +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index 34dd10908101a6709e389bfa1d1c2a6599e8b102..cf3ced15c9a87e7a4dbccba17c57a7b32b77566c 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -25,6 +25,7 @@ public class TicketType { + public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); + public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit + public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit ++ public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper + + public static TicketType create(String name, Comparator comparator) { + return new TicketType<>(name, comparator, 0L); +diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java +index 0a9f76b7aef5c12879a408954384b4e70ac5b484..fdc56d602ef0bf3c50842f3081a3e6523b9765b0 100644 +--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java ++++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java +@@ -141,6 +141,26 @@ public class WorldGenRegion implements WorldGenLevel { + return chunkX >= this.firstPos.x && chunkX <= this.lastPos.x && chunkZ >= this.firstPos.z && chunkZ <= this.lastPos.z; + } + ++ // Paper start - if loaded util ++ @Nullable ++ @Override ++ public ChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ return this.getChunk(x, z, ChunkStatus.FULL, false); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getBlockState(blockposition); ++ } ++ ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getFluidState(blockposition); ++ } ++ // Paper end ++ + @Override + public BlockState getBlockState(BlockPos pos) { + return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4).getBlockState(pos); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 8766e79c1ed7a8557ef5fd91e8f3c65c3467efcd..35f3940cebb00ee29da54b1ee148ee931fa11636 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -218,9 +218,9 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private final MinecraftServer server; + public ServerPlayer player; + private int tickCount; +- private long keepAliveTime; +- private boolean keepAlivePending; +- private long keepAliveChallenge; ++ private long keepAliveTime; private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER ++ private boolean keepAlivePending; private void setPendingPing(boolean isPending) { this.keepAlivePending = isPending;}; private boolean isPendingPing() { return this.keepAlivePending;}; // Paper - OBFHELPER ++ private long keepAliveChallenge; private void setKeepAliveID(long keepAliveID) { this.keepAliveChallenge = keepAliveID;}; private long getKeepAliveID() {return this.keepAliveChallenge; }; // Paper - OBFHELPER + // CraftBukkit start - multithreaded fields + private volatile int chatSpamTickCount; + private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(ServerGamePacketListenerImpl.class, "chatThrottle"); +diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java +index 497e23e4ebf0d8b4e1a90ea3909608cdc066265f..97bde5f8402452e59b0da94edfe1b970cdb86748 100644 +--- a/src/main/java/net/minecraft/util/BitStorage.java ++++ b/src/main/java/net/minecraft/util/BitStorage.java +@@ -84,6 +84,7 @@ public class BitStorage { + return (int) (k >> l & this.mask); + } + ++ public final long[] getDataBits() { return this.getRaw(); } // Paper - OBFHELPER + public long[] getRaw() { + return this.data; + } +diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +index 03831adce7905916423d8c3834c42c90f3a1ca8f..e48fcfe2e4ff151258ae1d84cc0995d2cd54e9a6 100644 +--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java ++++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +@@ -68,6 +68,15 @@ public abstract class BlockableEventLoop implements Processo + + } + ++ // Paper start ++ public void scheduleOnMain(Runnable r0) { ++ // postToMainThread does not work the same as older versions of mc ++ // This method is actually used to create a TickTask, which can then be posted onto main ++ this.addTask(this.wrapRunnable(r0)); ++ } ++ // Paper end ++ ++ public final void addTask(R r0) { tell(r0); }; // Paper - OBFHELPER + public void tell(R r0) { + this.pendingRunnables.add(r0); + LockSupport.unpark(this.getRunningThread()); +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index ff482d0349c18d0d1ba902ea0d10611b1ca4e588..102298d57cf3143092d04ab1d5d0d69b28d696ea 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -3,6 +3,7 @@ package net.minecraft.world.entity; + import com.google.common.collect.ImmutableSet; + import java.util.Optional; + import java.util.Set; // Paper ++import java.util.Map; // Paper + import java.util.UUID; + import java.util.function.Function; + import java.util.stream.Stream; +@@ -441,8 +442,8 @@ public class EntityType { + return this.dimensions.height; + } + +- @Nullable +- public T create(Level world) { ++ public T create(Level world) { return this.create(world); } // Paper - OBFHELPER ++ @Nullable public T create(Level world) { // Paper - OBFHELPER + return this.factory.create(this, world); + } + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 3245c0d7310285dd423c5c1d44c26fb8c3d7bf7f..9e5dde73bd65bf4e51352c628fba024c36e29ef1 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -228,6 +228,7 @@ public abstract class LivingEntity extends Entity { + public boolean collides = true; + public Set collidableExemptions = new HashSet<>(); + public boolean canPickUpLoot; ++ public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper + + @Override + public float getBukkitYaw() { +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index f268b7e6f89068267ea2f07f7505e0dc69968b73..99cb4dc1a1009d4a29e651c94d21babcc61388ed 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -223,6 +223,7 @@ public abstract class Mob extends LivingEntity { + return this.target; + } + ++ public org.bukkit.craftbukkit.entity.CraftMob getBukkitMob() { return (org.bukkit.craftbukkit.entity.CraftMob) super.getBukkitEntity(); } // Paper + public void setTarget(@Nullable LivingEntity target) { + // CraftBukkit start - fire event + setGoalTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true); +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +index d090ffcf08e32a08d4b815b79ed58fc00bc26fd0..920ae9af8985705a0ada7da5b7085a1ed8ca7f27 100644 +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -12,6 +12,8 @@ import org.bukkit.event.entity.EntityUnleashEvent; + + public abstract class PathfinderMob extends Mob { + ++ public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper ++ + protected PathfinderMob(EntityType type, Level world) { + super(type, world); + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Monster.java b/src/main/java/net/minecraft/world/entity/monster/Monster.java +index fa886a89195312acfe53605169216ce95642ba87..407b7168b7e8d4408824039c06d02792d3c7e534 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Monster.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Monster.java +@@ -27,6 +27,7 @@ import net.minecraft.world.level.ServerLevelAccessor; + + public abstract class Monster extends PathfinderMob implements Enemy { + ++ public org.bukkit.craftbukkit.entity.CraftMonster getBukkitMonster() { return (org.bukkit.craftbukkit.entity.CraftMonster) super.getBukkitEntity(); } // Paper + protected Monster(EntityType type, Level world) { + super(type, world); + this.xpReward = 5; +diff --git a/src/main/java/net/minecraft/world/entity/player/Inventory.java b/src/main/java/net/minecraft/world/entity/player/Inventory.java +index c0e0a8deabf3dffcc974f9e5bea2332d0d6e57a5..7d06838c4c8eef7ebff64ae094cd12404b9edd53 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Inventory.java ++++ b/src/main/java/net/minecraft/world/entity/player/Inventory.java +@@ -37,7 +37,7 @@ public class Inventory implements Container, Nameable { + public final NonNullList items; + public final NonNullList armor; + public final NonNullList offhand; +- private final List> compartments; ++ private final List> compartments; public final List> getComponents() { return compartments; } // Paper - OBFHELPER + public int selected; + public final Player player; + private ItemStack carried; +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index da0fabafad0aa6c124abf52f8da68c73b7264fe9..2a6a6e291efbd7cc8fed6532f18321bd141e1306 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -101,7 +101,7 @@ public final class ItemStack { + })).apply(instance, ItemStack::new); + }); + private static final Logger LOGGER = LogManager.getLogger(); +- public static final ItemStack EMPTY = new ItemStack((Item) null); ++ public static final ItemStack EMPTY = new ItemStack((Item) null);public static final ItemStack NULL_ITEM = EMPTY; // Paper - OBFHELPER + public static final DecimalFormat ATTRIBUTE_MODIFIER_FORMAT = (DecimalFormat) Util.make((new DecimalFormat("#.##")), (decimalformat) -> { // CraftBukkit - decompile error + decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); + }); +@@ -658,6 +658,24 @@ public final class ItemStack { + return this.tag != null ? this.tag.getList("Enchantments", 10) : new ListTag(); + } + ++ // Paper start - (this is just a good no conflict location) ++ public org.bukkit.inventory.ItemStack asBukkitMirror() { ++ return CraftItemStack.asCraftMirror(this); ++ } ++ public org.bukkit.inventory.ItemStack asBukkitCopy() { ++ return CraftItemStack.asCraftMirror(this.copy()); ++ } ++ public static ItemStack fromBukkitCopy(org.bukkit.inventory.ItemStack itemstack) { ++ return CraftItemStack.asNMSCopy(itemstack); ++ } ++ private org.bukkit.craftbukkit.inventory.CraftItemStack bukkitStack; ++ public org.bukkit.inventory.ItemStack getBukkitStack() { ++ if (bukkitStack == null || bukkitStack.getHandle() != this) { ++ bukkitStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this); ++ } ++ return bukkitStack; ++ } ++ // Paper end + public void setTag(@Nullable CompoundTag tag) { + this.tag = tag; + if (this.getItem().canBeDepleted()) { +@@ -756,6 +774,7 @@ public final class ItemStack { + return this.tag != null && this.tag.contains("Enchantments", 9) ? !this.tag.getList("Enchantments", 10).isEmpty() : false; + } + ++ public void getOrCreateTagAndSet(String s, Tag nbtbase) { addTagElement(s, nbtbase);} // Paper - OBFHELPER + public void addTagElement(String key, Tag tag) { + this.getOrCreateTag().put(key, tag); + } +@@ -841,6 +860,7 @@ public final class ItemStack { + // CraftBukkit start + @Deprecated + public void setItem(Item item) { ++ this.bukkitStack = null; // Paper + this.item = item; + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java b/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java +index e38c38c7d7679f267283a5ac6245e2261829aa05..2285a0cf6a35d06de77f94ad8a14ae91c1a7929f 100644 +--- a/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java ++++ b/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java +@@ -121,6 +121,7 @@ public class PotionUtils { + return compound == null ? Potions.EMPTY : Potion.byName(compound.getString("Potion")); + } + ++ public static ItemStack addPotionToItemStack(ItemStack itemstack, Potion potionregistry) { return setPotion(itemstack, potionregistry); } // Paper - OBFHELPER + public static ItemStack setPotion(ItemStack stack, Potion potion) { + ResourceLocation minecraftkey = Registry.POTION.getKey(potion); + +diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java +index 3bbee667743d9a249c1513ea426e7a51d9185c4c..2feb187f62be5cf5d354a1e806087417cc189ab1 100644 +--- a/src/main/java/net/minecraft/world/level/BlockGetter.java ++++ b/src/main/java/net/minecraft/world/level/BlockGetter.java +@@ -8,9 +8,11 @@ import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.util.Mth; ++import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.material.FluidState; ++import net.minecraft.world.level.material.Material; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; +@@ -22,6 +24,19 @@ public interface BlockGetter { + BlockEntity getBlockEntity(BlockPos pos); + + BlockState getBlockState(BlockPos pos); ++ // Paper start - if loaded util ++ BlockState getTypeIfLoaded(BlockPos blockposition); ++ default Material getMaterialIfLoaded(BlockPos blockposition) { ++ BlockState type = this.getTypeIfLoaded(blockposition); ++ return type == null ? null : type.getMaterial(); ++ } ++ ++ default Block getBlockIfLoaded(BlockPos blockposition) { ++ BlockState type = this.getTypeIfLoaded(blockposition); ++ return type == null ? null : type.getBlock(); ++ } ++ FluidState getFluidIfLoaded(BlockPos blockposition); ++ // Paper end + + FluidState getFluidState(BlockPos pos); + +diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java +index 0caf067f9d888f9769db1503284d444e97c60c9c..7ccf830146c252cff8e22553d293e02d4b53dad8 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkPos.java ++++ b/src/main/java/net/minecraft/world/level/ChunkPos.java +@@ -12,27 +12,32 @@ public class ChunkPos { + public static final long INVALID_CHUNK_POS = asLong(1875016, 1875016); + public final int x; + public final int z; ++ public final long longKey; // Paper + + public ChunkPos(int x, int z) { + this.x = x; + this.z = z; ++ this.longKey = asLong(this.x, this.z); // Paper + } + + public ChunkPos(BlockPos pos) { + this.x = pos.getX() >> 4; + this.z = pos.getZ() >> 4; ++ this.longKey = asLong(this.x, this.z); // Paper + } + + public ChunkPos(long pos) { + this.x = (int) pos; + this.z = (int) (pos >> 32); ++ this.longKey = asLong(this.x, this.z); // Paper + } + + public long toLong() { +- return asLong(this.x, this.z); ++ return longKey; // Paper + } + +- public static long asLong(int chunkX, int chunkZ) { ++ public static long pair(final BlockPos pos) { return asLong(pos.getX() >> 4, pos.getZ() >> 4); } // Paper - OBFHELPER ++ public static long asLong(int chunkX, int chunkZ) { + return (long) chunkX & 4294967295L | ((long) chunkZ & 4294967295L) << 32; + } + +diff --git a/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java b/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java +index 82c14e1ac66792137ab9e647c868a698c1ec9929..2b4f9849d668dede4d1f7d10f3a6ec9ef7a6d828 100644 +--- a/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java ++++ b/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java +@@ -20,6 +20,18 @@ public enum EmptyBlockGetter implements BlockGetter { + return null; + } + ++ // Paper start - If loaded util ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ return this.getFluidState(blockposition); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ return this.getBlockState(blockposition); ++ } ++ // Paper end ++ + @Override + public BlockState getBlockState(BlockPos pos) { + return Blocks.AIR.defaultBlockState(); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index f08de81dcc4acd5a3e44407b431ce827a19b2e9c..5cc4c2668df72f83fb1526f4586b71d2ae0103dc 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -74,6 +74,7 @@ import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.block.CapturedBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockState; + import org.bukkit.craftbukkit.block.data.CraftBlockData; + import org.bukkit.event.block.BlockPhysicsEvent; + // CraftBukkit end +@@ -255,17 +256,50 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return y < 0 || y >= 256; + } + +- public LevelChunk getChunkAt(BlockPos pos) { ++ public final LevelChunk getChunkAt(BlockPos pos) { // Paper - help inline + return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); + } + + @Override +- public LevelChunk getChunk(int chunkX, int chunkZ) { +- return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL); ++ public final LevelChunk getChunk(int chunkX, int chunkZ) { // Paper - final to help inline ++ return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true); // Paper - avoid a method jump ++ } ++ ++ // Paper start - if loaded ++ @Nullable ++ @Override ++ public final ChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ return ((ServerLevel)this).chunkSource.getChunkAtIfLoadedImmediately(x, z); + } + + @Override +- public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { ++ public final BlockState getTypeIfLoaded(BlockPos blockposition) { ++ // CraftBukkit start - tree generation ++ if (captureTreeGeneration) { ++ CraftBlockState previous = capturedBlockStates.get(blockposition); ++ if (previous != null) { ++ return previous.getHandle(); ++ } ++ } ++ // CraftBukkit end ++ if (!isInWorldBounds(blockposition)) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ ++ return chunk == null ? null : chunk.getBlockState(blockposition); ++ } ++ ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ ++ return chunk == null ? null : chunk.getFluidState(blockposition); ++ } ++ // Paper end ++ ++ @Override ++ public final ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { // Paper - final for inline + ChunkAccess ichunkaccess = this.getChunkSource().getChunk(chunkX, chunkZ, leastStatus, create); + + if (ichunkaccess == null && create) { +@@ -276,7 +310,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + + @Override +- public boolean setBlock(BlockPos pos, BlockState state, int flags) { ++ public final boolean setBlock(BlockPos pos, BlockState state, int flags) { // Paper - final for inline + return this.setBlock(pos, state, flags, 512); + } + +@@ -422,8 +456,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + public void onBlockStateChange(BlockPos pos, BlockState oldBlock, BlockState newBlock) {} + +- @Override +- public boolean removeBlock(BlockPos pos, boolean move) { ++ public boolean setAir(BlockPos blockposition) { return this.removeBlock(blockposition, false); } // Paper - OBFHELPER ++ public boolean setAir(BlockPos blockposition, boolean moved) { return this.removeBlock(blockposition, moved); } // Paper - OBFHELPER ++ @Override public boolean removeBlock(BlockPos pos, boolean move) { // Paper - OBFHELPER + FluidState fluid = this.getFluidState(pos); + + return this.setBlock(pos, fluid.createLegacyBlock(), 3 | (move ? 64 : 0)); +@@ -569,7 +604,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + if (isOutsideBuildHeight(pos)) { + return Blocks.VOID_AIR.defaultBlockState(); + } else { +- LevelChunk chunk = this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); ++ LevelChunk chunk = (LevelChunk) this.getChunkSource().getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, true); // Paper - manually inline to reduce hops and avoid unnecessary null check to reduce total byte code size, this should never return null and if it does we will see it the next line but the real stack trace will matter in the chunk engine + + return chunk.getBlockState(pos); + } +diff --git a/src/main/java/net/minecraft/world/level/LevelReader.java b/src/main/java/net/minecraft/world/level/LevelReader.java +index b6877b78bf6ecf2069e59028f8910826c8b4eafe..6e4a53291ee87fac6d81d4ab9746906b6ae1b453 100644 +--- a/src/main/java/net/minecraft/world/level/LevelReader.java ++++ b/src/main/java/net/minecraft/world/level/LevelReader.java +@@ -18,6 +18,7 @@ import net.minecraft.world.phys.AABB; + + public interface LevelReader extends BlockAndTintGetter, CollisionGetter, BiomeManager.NoiseBiomeSource { + ++ @Nullable ChunkAccess getChunkIfLoadedImmediately(int x, int z); // Paper - ifLoaded api (we need this since current impl blocks if the chunk is loading) + @Nullable + ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create); + +diff --git a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java b/src/main/java/net/minecraft/world/level/PathNavigationRegion.java +index f1d759d87291f469bde3b433031a6e7c6a19fbf2..6db3f4efa6ea4a09aad7684a3b7cc7479fad2f5c 100644 +--- a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java ++++ b/src/main/java/net/minecraft/world/level/PathNavigationRegion.java +@@ -4,6 +4,7 @@ import java.util.function.Predicate; + import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntity; +@@ -23,7 +24,7 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { + protected final int centerZ; + protected final ChunkAccess[][] chunks; + protected boolean allEmpty; +- protected final Level level; ++ protected final Level level; protected final Level getWorld() { return level; } // Paper - OBFHELPER + + public PathNavigationRegion(Level world, BlockPos minPos, BlockPos maxPos) { + this.level = world; +@@ -42,7 +43,7 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { + + for (k = this.centerX; k <= i; ++k) { + for (l = this.centerZ; l <= j; ++l) { +- this.chunks[k - this.centerX][l - this.centerZ] = ichunkprovider.getChunkNow(k, l); ++ this.chunks[k - this.centerX][l - this.centerZ] = ((ServerLevel)world).getChunkSource().getChunkAtIfLoadedMainThreadNoCache(k, l); // Paper + } + } + +@@ -67,7 +68,7 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { + int k = i - this.centerX; + int l = j - this.centerZ; + +- if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { ++ if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { // Paper - if this changes, update getChunkIfLoaded below + ChunkAccess ichunkaccess = this.chunks[k][l]; + + return (ChunkAccess) (ichunkaccess != null ? ichunkaccess : new EmptyLevelChunk(this.level, new ChunkPos(i, j))); +@@ -86,6 +87,29 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { + return this.getChunk(chunkX, chunkZ); + } + ++ // Paper start - if loaded util ++ private ChunkAccess getChunkIfLoaded(int x, int z) { ++ int k = x - this.centerX; ++ int l = z - this.centerZ; ++ ++ if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { ++ return this.chunks[k][l]; ++ } ++ return null; ++ } ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getFluidState(blockposition); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getBlockState(blockposition); ++ } ++ // Paper end ++ + @Nullable + @Override + public BlockEntity getBlockEntity(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index c9713d1ab6498c09790503f673b31b5ef30ce4f3..e6928557a79f51302975f2832ec911c2692eaaeb 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -687,6 +687,7 @@ public abstract class BlockBehaviour { + return this.cache != null ? this.cache.isCollisionShapeFullBlock : Block.isShapeFullBlock(this.getCollisionShape(world, pos)); + } + ++ public final BlockState getBlockData() { return asState(); } // Paper - OBFHELPER + protected abstract BlockState asState(); + + public boolean requiresCorrectToolForDrops() { +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index fe1c10e5eeb434cd24e94b3247abbf5f73fce9cc..31f17956b3b031d1a47bda4d282554c8a7853097 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -47,6 +47,7 @@ public class WorldBorder { + return this.getDistanceToBorder(entity.getX(), entity.getZ()); + } + ++ public final VoxelShape asVoxelShape(){ return getCollisionShape();} // Paper - OBFHELPER + public VoxelShape getCollisionShape() { + return this.extent.getCollisionShape(); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 5a91d74f0acf393dbf098719b0924a4c00cf7128..e2c5a17aa72d1a5412d76881187d4d9ad1763297 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -59,7 +59,7 @@ public class LevelChunk implements ChunkAccess { + + private static final Logger LOGGER = LogManager.getLogger(); + @Nullable +- public static final LevelChunkSection EMPTY_SECTION = null; ++ public static final LevelChunkSection EMPTY_SECTION = null; public static final LevelChunkSection EMPTY_CHUNK_SECTION = EMPTY_SECTION; // Paper - OBFHELPER + private final LevelChunkSection[] sections; + private ChunkBiomeContainer biomes; + private final Map pendingBlockEntities; +@@ -82,7 +82,7 @@ public class LevelChunk implements ChunkAccess { + private Supplier fullStatus; + @Nullable + private Consumer postLoad; +- private final ChunkPos chunkPos; ++ private final ChunkPos chunkPos; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key + private volatile boolean isLightCorrect; + + public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes) { +@@ -99,7 +99,8 @@ public class LevelChunk implements ChunkAccess { + this.postProcessing = new ShortList[16]; + this.entitySlices = (List[]) (new List[16]); // Spigot + this.world = (ServerLevel) world; // CraftBukkit - type +- this.chunkPos = pos; ++ this.locX = pos.x; this.locZ = pos.z; // Paper - reduce need for field look ups ++ this.chunkPos = pos; this.coordinateKey = ChunkPos.asLong(locX, locZ); // Paper - cache long key + this.upgradeData = upgradeData; + Heightmap.Types[] aheightmap_type = Heightmap.Types.values(); + int j = aheightmap_type.length; +@@ -145,6 +146,110 @@ public class LevelChunk implements ChunkAccess { + public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY); + // CraftBukkit end + ++ // Paper start ++ public final com.destroystokyo.paper.util.maplist.EntityList entities = new com.destroystokyo.paper.util.maplist.EntityList(); ++ public ChunkHolder playerChunk; ++ ++ static final int NEIGHBOUR_CACHE_RADIUS = 3; ++ public static int getNeighbourCacheRadius() { ++ return NEIGHBOUR_CACHE_RADIUS; ++ } ++ ++ boolean loadedTicketLevel; ++ private long neighbourChunksLoadedBitset; ++ private final LevelChunk[] loadedNeighbourChunks = new LevelChunk[(NEIGHBOUR_CACHE_RADIUS * 2 + 1) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)]; ++ ++ private static int getNeighbourIndex(final int relativeX, final int relativeZ) { ++ // index = (relativeX + NEIGHBOUR_CACHE_RADIUS) + (relativeZ + NEIGHBOUR_CACHE_RADIUS) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1) ++ // optimised variant of the above by moving some of the ops to compile time ++ return relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))); ++ } ++ ++ public final LevelChunk getRelativeNeighbourIfLoaded(final int relativeX, final int relativeZ) { ++ return this.loadedNeighbourChunks[getNeighbourIndex(relativeX, relativeZ)]; ++ } ++ ++ public final boolean isNeighbourLoaded(final int relativeX, final int relativeZ) { ++ return (this.neighbourChunksLoadedBitset & (1L << getNeighbourIndex(relativeX, relativeZ))) != 0; ++ } ++ ++ public final void setNeighbourLoaded(final int relativeX, final int relativeZ, final LevelChunk chunk) { ++ if (chunk == null) { ++ throw new IllegalArgumentException("Chunk must be non-null, neighbour: (" + relativeX + "," + relativeZ + "), chunk: " + this.chunkPos); ++ } ++ final long before = this.neighbourChunksLoadedBitset; ++ final int index = getNeighbourIndex(relativeX, relativeZ); ++ this.loadedNeighbourChunks[index] = chunk; ++ this.neighbourChunksLoadedBitset |= (1L << index); ++ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); ++ } ++ ++ public final void setNeighbourUnloaded(final int relativeX, final int relativeZ) { ++ final long before = this.neighbourChunksLoadedBitset; ++ final int index = getNeighbourIndex(relativeX, relativeZ); ++ this.loadedNeighbourChunks[index] = null; ++ this.neighbourChunksLoadedBitset &= ~(1L << index); ++ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); ++ } ++ ++ public final void resetNeighbours() { ++ final long before = this.neighbourChunksLoadedBitset; ++ this.neighbourChunksLoadedBitset = 0L; ++ java.util.Arrays.fill(this.loadedNeighbourChunks, null); ++ this.onNeighbourChange(before, 0L); ++ } ++ ++ protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { ++ ++ } ++ ++ public final boolean isAnyNeighborsLoaded() { ++ return neighbourChunksLoadedBitset != 0; ++ } ++ public final boolean areNeighboursLoaded(final int radius) { ++ return LevelChunk.areNeighboursLoaded(this.neighbourChunksLoadedBitset, radius); ++ } ++ ++ public static boolean areNeighboursLoaded(final long bitset, final int radius) { ++ // index = relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))) ++ switch (radius) { ++ case 0: { ++ return (bitset & (1L << getNeighbourIndex(0, 0))) != 0; ++ } ++ case 1: { ++ long mask = 0L; ++ for (int dx = -1; dx <= 1; ++dx) { ++ for (int dz = -1; dz <= 1; ++dz) { ++ mask |= (1L << getNeighbourIndex(dx, dz)); ++ } ++ } ++ return (bitset & mask) == mask; ++ } ++ case 2: { ++ long mask = 0L; ++ for (int dx = -2; dx <= 2; ++dx) { ++ for (int dz = -2; dz <= 2; ++dz) { ++ mask |= (1L << getNeighbourIndex(dx, dz)); ++ } ++ } ++ return (bitset & mask) == mask; ++ } ++ case 3: { ++ long mask = 0L; ++ for (int dx = -3; dx <= 3; ++dx) { ++ for (int dz = -3; dz <= 3; ++dz) { ++ mask |= (1L << getNeighbourIndex(dx, dz)); ++ } ++ } ++ return (bitset & mask) == mask; ++ } ++ ++ default: ++ throw new IllegalArgumentException("Radius not recognized: " + radius); ++ } ++ } ++ // Paper end ++ + public LevelChunk(Level world, ProtoChunk protoChunk) { + this(world, protoChunk.getPos(), protoChunk.getBiomes(), protoChunk.getUpgradeData(), protoChunk.getBlockTicks(), protoChunk.getLiquidTicks(), protoChunk.getInhabitedTime(), protoChunk.getSections(), (Consumer) null); + Iterator iterator = protoChunk.getEntities().iterator(); +@@ -250,6 +355,18 @@ public class LevelChunk implements ChunkAccess { + } + } + ++ // Paper start - If loaded util ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ return this.getFluidState(blockposition); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ return this.getBlockState(blockposition); ++ } ++ // Paper end ++ + @Override + public FluidState getFluidState(BlockPos pos) { + return this.getFluidState(pos.getX(), pos.getY(), pos.getZ()); +@@ -390,6 +507,7 @@ public class LevelChunk implements ChunkAccess { + entity.xChunk = this.chunkPos.x; + entity.yChunk = k; + entity.zChunk = this.chunkPos.z; ++ this.entities.add(entity); // Paper - per chunk entity list + this.entitySlices[k].add(entity); + } + +@@ -413,6 +531,7 @@ public class LevelChunk implements ChunkAccess { + } + + this.entitySlices[section].remove(entity); ++ this.entities.remove(entity); // Paper + } + + @Override +@@ -434,6 +553,7 @@ public class LevelChunk implements ChunkAccess { + return this.getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); + } + ++ @Nullable public final BlockEntity getTileEntityImmediately(BlockPos pos) { return this.getBlockEntity(pos, EntityCreationType.IMMEDIATE); } // Paper - OBFHELPER + @Nullable + public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType) { + // CraftBukkit start +@@ -545,7 +665,25 @@ public class LevelChunk implements ChunkAccess { + + // CraftBukkit start + public void loadCallback() { ++ // Paper start - neighbour cache ++ int chunkX = this.chunkPos.x; ++ int chunkZ = this.chunkPos.z; ++ ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); ++ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { ++ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { ++ LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); ++ if (neighbour != null) { ++ neighbour.setNeighbourLoaded(-dx, -dz, this); ++ // should be in cached already ++ this.setNeighbourLoaded(dx, dz, neighbour); ++ } ++ } ++ } ++ this.setNeighbourLoaded(0, 0, this); ++ this.loadedTicketLevel = true; ++ // Paper end - neighbour cache + org.bukkit.Server server = this.world.getCraftServer(); ++ ((ServerLevel)this.world).getChunkSource().addLoadedChunk(this); // Paper + if (server != null) { + /* + * If it's a new world, the first few chunks are generated inside +@@ -584,6 +722,22 @@ public class LevelChunk implements ChunkAccess { + server.getPluginManager().callEvent(unloadEvent); + // note: saving can be prevented, but not forced if no saving is actually required + this.mustNotSave = !unloadEvent.isSaveChunk(); ++ ((ServerLevel)this.world).getChunkSource().removeLoadedChunk(this); // Paper ++ // Paper start - neighbour cache ++ int chunkX = this.chunkPos.x; ++ int chunkZ = this.chunkPos.z; ++ ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); ++ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { ++ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { ++ LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); ++ if (neighbour != null) { ++ neighbour.setNeighbourUnloaded(-dx, -dz); ++ } ++ } ++ } ++ this.loadedTicketLevel = false; ++ this.resetNeighbours(); ++ // Paper end + } + // CraftBukkit end + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index 8a4fca9f4882e65b831dd3f82f242e1113859fe0..b54d82e0f41a03c91e0de8df8249a91da3c04d0e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -139,6 +139,7 @@ public class LevelChunkSection { + return this.states; + } + ++ public void writeChunkSection(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER + public void write(FriendlyByteBuf packetdataserializer) { + packetdataserializer.writeShort(this.nonEmptyBlockCount); + this.states.write(packetdataserializer); +diff --git a/src/main/java/net/minecraft/world/level/chunk/Palette.java b/src/main/java/net/minecraft/world/level/chunk/Palette.java +index dcc030f4801b4c6e1fe5b8c2718ddfd7ba6bb248..78c56e1e2af50e923fb0b07c6ddd860c4aa77195 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Palette.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Palette.java +@@ -7,10 +7,12 @@ import net.minecraft.network.FriendlyByteBuf; + + public interface Palette { + ++ default int getOrCreateIdFor(T object) { return this.idFor(object); } // Paper - OBFHELPER + int idFor(T object); + + boolean maybeHas(Predicate predicate); + ++ @Nullable default T getObject(int dataBits) { return this.valueFor(dataBits); } // Paper - OBFHELPER + @Nullable + T valueFor(int index); + +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index f14f89f8916c832feaa3887bd28a5cf6b2f6ff1d..d4db27421736f665739436c1ac4d3c6d5cae95cd 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -19,7 +19,7 @@ import net.minecraft.util.Mth; + + public class PalettedContainer implements PaletteResize { + +- private final Palette globalPalette; ++ private final Palette globalPalette; private final Palette getDataPaletteGlobal() { return this.globalPalette; } // Paper - OBFHELPER + private final PaletteResize dummyPaletteResize = (i, object) -> { + return 0; + }; +@@ -27,9 +27,9 @@ public class PalettedContainer implements PaletteResize { + private final Function reader; + private final Function writer; + private final T defaultValue; +- protected BitStorage storage; +- private Palette palette; +- private int bits; ++ protected BitStorage storage; public final BitStorage getDataBits() { return this.storage; } // Paper - OBFHELPER ++ private Palette palette; private Palette getDataPalette() { return this.palette; } // Paper - OBFHELPER ++ private int bits; private int getBitsPerObject() { return this.bits; } // Paper - OBFHELPER + private final ReentrantLock lock = new ReentrantLock(); + + public void acquire() { +@@ -64,6 +64,7 @@ public class PalettedContainer implements PaletteResize { + return y << 8 | z << 4 | x; + } + ++ private void initialize(int bitsPerObject) { this.setBits(bitsPerObject); } // Paper - OBFHELPER + private void setBits(int size) { + if (size != this.bits) { + this.bits = size; +@@ -141,6 +142,7 @@ public class PalettedContainer implements PaletteResize { + return t0 == null ? this.defaultValue : t0; + } + ++ public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER + public void write(FriendlyByteBuf buf) { + this.acquire(); + buf.writeByte(this.bits); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index cecf8a68f215d85e84fba157930f6987ffd21e50..7cd3f89004b0a64772fc3dfbdd132ba5a850b63e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -99,6 +99,18 @@ public class ProtoChunk implements ChunkAccess { + + } + ++ // Paper start - If loaded util ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ return this.getFluidState(blockposition); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ return this.getBlockState(blockposition); ++ } ++ // Paper end ++ + @Override + public BlockState getBlockState(BlockPos pos) { + int i = pos.getY(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +index 7de765786b3504dcffab98bb0d9dac64b30b3325..5bd34b136f2892f541ba686debca19e0a4eef0be 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +@@ -27,7 +27,7 @@ public class IOWorker implements AutoCloseable { + private static final Logger LOGGER = LogManager.getLogger(); + private final AtomicBoolean shutdownRequested = new AtomicBoolean(); + private final ProcessorMailbox mailbox; +- private final RegionFileStorage storage; ++ private final RegionFileStorage storage;public RegionFileStorage getRegionFileCache() { return storage; } // Paper - OBFHELPER + private final Map pendingWrites = Maps.newLinkedHashMap(); + + protected IOWorker(File file, boolean flag, String s) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index aa3d6db08e4d744cc94de71d0f8dceb99948e2ab..60f410a4f838048bbfd2cde52caa7c4c9434b0ba 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -112,6 +112,7 @@ public class RegionFile implements AutoCloseable { + return this.externalFileDir.resolve(s); + } + ++ @Nullable public synchronized DataInputStream getReadStream(ChunkPos chunkCoordIntPair) throws IOException { return getChunkDataInputStream(chunkCoordIntPair);} // Paper - OBFHELPER + @Nullable + public synchronized DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException { + int i = this.getOffset(pos); +diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java +index 022fafff8b476f8bc1830bf5494760b0fef65297..983d0495ec35128ca3ef68566ada065bc4b21efc 100644 +--- a/src/main/java/net/minecraft/world/phys/AABB.java ++++ b/src/main/java/net/minecraft/world/phys/AABB.java +@@ -194,10 +194,12 @@ public class AABB { + return this.move(vec3d.x, vec3d.y, vec3d.z); + } + ++ public final boolean intersects(AABB axisalignedbb) { return this.intersects(axisalignedbb); } // Paper - OBFHELPER + public boolean intersects(AABB box) { + return this.intersects(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ); + } + ++ public final boolean intersects(double d0, double d1, double d2, double d3, double d4, double d5) { return intersects(d0, d1, d2, d3, d4, d5); } // Paper - OBFHELPER + public boolean intersects(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { + return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ; + } +@@ -210,6 +212,7 @@ public class AABB { + return x >= this.minX && x < this.maxX && y >= this.minY && y < this.maxY && z >= this.minZ && z < this.maxZ; + } + ++ public final double getAverageSideLength(){return getSize();} // Paper - OBFHELPER + public double getSize() { + double d0 = this.getXsize(); + double d1 = this.getYsize(); +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index eb07309be171ccadcae21f4096c44d2b700d22b3..2371b52b450e2b43fa9b9549a91f853c702a9dc0 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -31,10 +31,12 @@ public final class Shapes { + public static final VoxelShape INFINITY = box(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); + private static final VoxelShape EMPTY = new ArrayVoxelShape(new BitSetDiscreteVoxelShape(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); + ++ public static final VoxelShape empty() {return empty();} // Paper - OBFHELPER + public static VoxelShape empty() { + return Shapes.EMPTY; + } + ++ public static final VoxelShape fullCube() {return block();} // Paper - OBFHELPER + public static VoxelShape block() { + return Shapes.BLOCK; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index c34f63eaf3deca4623ca4dfbee863771014847ba..01df5263d77771a296ca091a0feec620e6e37229 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -85,6 +85,7 @@ public final class CraftItemStack extends ItemStack { + } + + net.minecraft.world.item.ItemStack handle; ++ public net.minecraft.world.item.ItemStack getHandle() { return handle; } // Paper + + /** + * Mirror +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 9ad17c560c8d99a396543ab9f97c34de648f6544..4bf48f77f3f7cd62a91590543f5af441c8268029 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -43,6 +43,7 @@ import org.bukkit.scheduler.BukkitWorker; + */ + public class CraftScheduler implements BukkitScheduler { + ++ static Plugin MINECRAFT = new MinecraftInternalPlugin(); + /** + * Counter for IDs. Order doesn't matter, only uniqueness. + */ +@@ -177,6 +178,11 @@ public class CraftScheduler implements BukkitScheduler { + runTaskTimer(plugin, (Object) task, delay, period); + } + ++ public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { ++ final CraftTask task = new CraftTask(run, nextId(), taskName); ++ return handle(task, delay); ++ } ++ + public BukkitTask runTaskTimer(Plugin plugin, Object runnable, long delay, long period) { + validate(plugin, runnable); + if (delay < 0L) { +@@ -400,13 +406,20 @@ public class CraftScheduler implements BukkitScheduler { + task.run(); + task.timings.stopTiming(); // Spigot + } catch (final Throwable throwable) { +- task.getOwner().getLogger().log( ++ // Paper start ++ String msg = String.format( ++ "Task #%s for %s generated an exception", ++ task.getTaskId(), ++ task.getOwner().getDescription().getFullName()); ++ if (task.getOwner() == MINECRAFT) { ++ net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable); ++ } else { ++ task.getOwner().getLogger().log( + Level.WARNING, +- String.format( +- "Task #%s for %s generated an exception", +- task.getTaskId(), +- task.getOwner().getDescription().getFullName()), ++ msg, + throwable); ++ } ++ // Paper end + } finally { + currentTask = null; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +index 3c7066192ea4c05c101404bb56cbc839771f4200..09aa6809c5400ce8548ac902908b750ce7c964ec 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +@@ -39,6 +39,21 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + CraftTask(final Object task) { + this(null, task, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); + } ++ // Paper start ++ public String taskName = null; ++ boolean internal = false; ++ CraftTask(final Object task, int id, String taskName) { ++ this.rTask = (Runnable) task; ++ this.cTask = null; ++ this.plugin = CraftScheduler.MINECRAFT; ++ this.taskName = taskName; ++ this.internal = true; ++ this.id = id; ++ this.period = CraftTask.NO_REPEATING; ++ this.taskName = taskName; ++ this.timings = null; // Will be changed in later patch ++ } ++ // Paper end + + CraftTask(final Plugin plugin, final Object task, final int id, final long period) { + this.plugin = plugin; +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java +new file mode 100644 +index 0000000000000000000000000000000000000000..49dc0c441b9dd7e7745cf15ced67f383ebee1f99 +--- /dev/null ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java +@@ -0,0 +1,132 @@ ++package org.bukkit.craftbukkit.scheduler; ++ ++ ++import org.bukkit.Server; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.bukkit.configuration.file.FileConfiguration; ++import org.bukkit.generator.ChunkGenerator; ++import org.bukkit.plugin.PluginBase; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.bukkit.plugin.PluginLoader; ++import org.bukkit.plugin.PluginLogger; ++ ++import java.io.File; ++import java.io.InputStream; ++import java.util.List; ++ ++public class MinecraftInternalPlugin extends PluginBase { ++ private boolean enabled = true; ++ ++ private final String pluginName; ++ private PluginDescriptionFile pdf; ++ ++ public MinecraftInternalPlugin() { ++ this.pluginName = "Minecraft"; ++ pdf = new PluginDescriptionFile(pluginName, "1.0", "nms"); ++ } ++ ++ public void setEnabled(boolean enabled) { ++ this.enabled = enabled; ++ } ++ ++ @Override ++ public File getDataFolder() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginDescriptionFile getDescription() { ++ return pdf; ++ } ++ ++ @Override ++ public FileConfiguration getConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public InputStream getResource(String filename) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void saveConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void saveDefaultConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void saveResource(String resourcePath, boolean replace) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void reloadConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginLogger getLogger() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginLoader getPluginLoader() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public Server getServer() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public boolean isEnabled() { ++ return enabled; ++ } ++ ++ @Override ++ public void onDisable() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void onLoad() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void onEnable() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public boolean isNaggable() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void setNaggable(boolean canNag) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java +index 33cd17c415ae19bc9028934257b396907995cb9a..40a2ad3e180cc50a755f44a8ff6d8261734bf733 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java +@@ -168,7 +168,23 @@ public class DummyGeneratorAccess implements LevelAccessor { + public FluidState getFluidState(BlockPos pos) { + throw new UnsupportedOperationException("Not supported yet."); + } ++ // Paper start - if loaded util ++ @javax.annotation.Nullable ++ @Override ++ public ChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } + ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // Paper end + @Override + public WorldBorder getWorldBorder() { + throw new UnsupportedOperationException("Not supported yet."); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java +index 1aec70a1f1a9d8fd2cd06bde4033e19e769ab331..f72c13bedaa6fa45e26f5dcad564835bdd4af61f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java +@@ -17,7 +17,7 @@ import java.util.RandomAccess; + public class UnsafeList extends AbstractList implements List, RandomAccess, Cloneable, Serializable { + private static final long serialVersionUID = 8683452581112892191L; + +- private transient Object[] data; ++ private transient Object[] data; public final Object[] getRawDataArray() { return this.data; } // Paper - expose for raw get + private int size; + private int initialCapacity; + +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 8d6f4d76d6f04a322a98faecaca6b1b69c5f49d6..dc11dab14624ca25e78bf0b919ecf461e0be430d 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -118,7 +118,11 @@ public class SpigotConfig + } + } + } +- ++ // Paper start ++ SpigotConfig.save(); ++ } ++ public static void save() { ++ // Paper end + try + { + config.save( CONFIG_FILE ); diff --git a/patches/server-remapped/0005-Paper-Metrics.patch b/patches/server-remapped/0005-Paper-Metrics.patch new file mode 100644 index 0000000000..82a9c9a2d4 --- /dev/null +++ b/patches/server-remapped/0005-Paper-Metrics.patch @@ -0,0 +1,735 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 24 Mar 2017 23:56:01 -0500 +Subject: [PATCH] Paper Metrics + +Removes Spigot's mcstats metrics in favor of a system using bStats + +To disable for privacy or other reasons go to the bStats folder in your plugins folder +and edit the config.yml file present there. + +Please keep in mind the data collected is anonymous and collection should have no +tangible effect on server performance. The data is used to allow the authors of +PaperMC to track version and platform usage so that we can make better management +decisions on behalf of the project. + +diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0b9e689d57705965721b5c55bc45d36657f360e4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/Metrics.java +@@ -0,0 +1,670 @@ ++package com.destroystokyo.paper; ++ ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++import org.bukkit.configuration.file.YamlConfiguration; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.plugin.Plugin; ++ ++import org.json.simple.JSONArray; ++import org.json.simple.JSONObject; ++ ++import javax.net.ssl.HttpsURLConnection; ++import java.io.ByteArrayOutputStream; ++import java.io.DataOutputStream; ++import java.io.File; ++import java.io.IOException; ++import java.net.URL; ++import java.util.*; ++import java.util.concurrent.Callable; ++import java.util.concurrent.Executors; ++import java.util.concurrent.ScheduledExecutorService; ++import java.util.concurrent.TimeUnit; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++import java.util.zip.GZIPOutputStream; ++ ++/** ++ * bStats collects some data for plugin authors. ++ * ++ * Check out https://bStats.org/ to learn more about bStats! ++ */ ++public class Metrics { ++ ++ // Executor service for requests ++ // We use an executor service because the Bukkit scheduler is affected by server lags ++ private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); ++ ++ // The version of this bStats class ++ public static final int B_STATS_VERSION = 1; ++ ++ // The url to which the data is sent ++ private static final String URL = "https://bStats.org/submitData/server-implementation"; ++ ++ // Should failed requests be logged? ++ private static boolean logFailedRequests = false; ++ ++ // The logger for the failed requests ++ private static Logger logger = Logger.getLogger("bStats"); ++ ++ // The name of the server software ++ private final String name; ++ ++ // The uuid of the server ++ private final String serverUUID; ++ ++ // A list with all custom charts ++ private final List charts = new ArrayList<>(); ++ ++ /** ++ * Class constructor. ++ * ++ * @param name The name of the server software. ++ * @param serverUUID The uuid of the server. ++ * @param logFailedRequests Whether failed requests should be logged or not. ++ * @param logger The logger for the failed requests. ++ */ ++ public Metrics(String name, String serverUUID, boolean logFailedRequests, Logger logger) { ++ this.name = name; ++ this.serverUUID = serverUUID; ++ Metrics.logFailedRequests = logFailedRequests; ++ Metrics.logger = logger; ++ ++ // Start submitting the data ++ startSubmitting(); ++ } ++ ++ /** ++ * Adds a custom chart. ++ * ++ * @param chart The chart to add. ++ */ ++ public void addCustomChart(CustomChart chart) { ++ if (chart == null) { ++ throw new IllegalArgumentException("Chart cannot be null!"); ++ } ++ charts.add(chart); ++ } ++ ++ /** ++ * Starts the Scheduler which submits our data every 30 minutes. ++ */ ++ private void startSubmitting() { ++ final Runnable submitTask = this::submitData; ++ ++ // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the ++ // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. ++ // WARNING: You must not modify any part of this Metrics class, including the submit delay or frequency! ++ // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! ++ long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); ++ long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); ++ scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); ++ scheduler.scheduleAtFixedRate(submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); ++ } ++ ++ /** ++ * Gets the plugin specific data. ++ * ++ * @return The plugin specific data. ++ */ ++ private JSONObject getPluginData() { ++ JSONObject data = new JSONObject(); ++ ++ data.put("pluginName", name); // Append the name of the server software ++ JSONArray customCharts = new JSONArray(); ++ for (CustomChart customChart : charts) { ++ // Add the data of the custom charts ++ JSONObject chart = customChart.getRequestJsonObject(); ++ if (chart == null) { // If the chart is null, we skip it ++ continue; ++ } ++ customCharts.add(chart); ++ } ++ data.put("customCharts", customCharts); ++ ++ return data; ++ } ++ ++ /** ++ * Gets the server specific data. ++ * ++ * @return The server specific data. ++ */ ++ private JSONObject getServerData() { ++ // OS specific data ++ String osName = System.getProperty("os.name"); ++ String osArch = System.getProperty("os.arch"); ++ String osVersion = System.getProperty("os.version"); ++ int coreCount = Runtime.getRuntime().availableProcessors(); ++ ++ JSONObject data = new JSONObject(); ++ ++ data.put("serverUUID", serverUUID); ++ ++ data.put("osName", osName); ++ data.put("osArch", osArch); ++ data.put("osVersion", osVersion); ++ data.put("coreCount", coreCount); ++ ++ return data; ++ } ++ ++ /** ++ * Collects the data and sends it afterwards. ++ */ ++ private void submitData() { ++ final JSONObject data = getServerData(); ++ ++ JSONArray pluginData = new JSONArray(); ++ pluginData.add(getPluginData()); ++ data.put("plugins", pluginData); ++ ++ try { ++ // We are still in the Thread of the timer, so nothing get blocked :) ++ sendData(data); ++ } catch (Exception e) { ++ // Something went wrong! :( ++ if (logFailedRequests) { ++ logger.log(Level.WARNING, "Could not submit stats of " + name, e); ++ } ++ } ++ } ++ ++ /** ++ * Sends the data to the bStats server. ++ * ++ * @param data The data to send. ++ * @throws Exception If the request failed. ++ */ ++ private static void sendData(JSONObject data) throws Exception { ++ if (data == null) { ++ throw new IllegalArgumentException("Data cannot be null!"); ++ } ++ HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); ++ ++ // Compress the data to save bandwidth ++ byte[] compressedData = compress(data.toString()); ++ ++ // Add headers ++ connection.setRequestMethod("POST"); ++ connection.addRequestProperty("Accept", "application/json"); ++ connection.addRequestProperty("Connection", "close"); ++ connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request ++ connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); ++ connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format ++ connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); ++ ++ // Send data ++ connection.setDoOutput(true); ++ DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); ++ outputStream.write(compressedData); ++ outputStream.flush(); ++ outputStream.close(); ++ ++ connection.getInputStream().close(); // We don't care about the response - Just send our data :) ++ } ++ ++ /** ++ * Gzips the given String. ++ * ++ * @param str The string to gzip. ++ * @return The gzipped String. ++ * @throws IOException If the compression failed. ++ */ ++ private static byte[] compress(final String str) throws IOException { ++ if (str == null) { ++ return null; ++ } ++ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ++ GZIPOutputStream gzip = new GZIPOutputStream(outputStream); ++ gzip.write(str.getBytes("UTF-8")); ++ gzip.close(); ++ return outputStream.toByteArray(); ++ } ++ ++ /** ++ * Represents a custom chart. ++ */ ++ public static abstract class CustomChart { ++ ++ // The id of the chart ++ final String chartId; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ */ ++ CustomChart(String chartId) { ++ if (chartId == null || chartId.isEmpty()) { ++ throw new IllegalArgumentException("ChartId cannot be null or empty!"); ++ } ++ this.chartId = chartId; ++ } ++ ++ private JSONObject getRequestJsonObject() { ++ JSONObject chart = new JSONObject(); ++ chart.put("chartId", chartId); ++ try { ++ JSONObject data = getChartData(); ++ if (data == null) { ++ // If the data is null we don't send the chart. ++ return null; ++ } ++ chart.put("data", data); ++ } catch (Throwable t) { ++ if (logFailedRequests) { ++ logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t); ++ } ++ return null; ++ } ++ return chart; ++ } ++ ++ protected abstract JSONObject getChartData() throws Exception; ++ ++ } ++ ++ /** ++ * Represents a custom simple pie. ++ */ ++ public static class SimplePie extends CustomChart { ++ ++ private final Callable callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public SimplePie(String chartId, Callable callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ String value = callable.call(); ++ if (value == null || value.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("value", value); ++ return data; ++ } ++ } ++ ++ /** ++ * Represents a custom advanced pie. ++ */ ++ public static class AdvancedPie extends CustomChart { ++ ++ private final Callable> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public AdvancedPie(String chartId, Callable> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ boolean allSkipped = true; ++ for (Map.Entry entry : map.entrySet()) { ++ if (entry.getValue() == 0) { ++ continue; // Skip this invalid ++ } ++ allSkipped = false; ++ values.put(entry.getKey(), entry.getValue()); ++ } ++ if (allSkipped) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("values", values); ++ return data; ++ } ++ } ++ ++ /** ++ * Represents a custom drilldown pie. ++ */ ++ public static class DrilldownPie extends CustomChart { ++ ++ private final Callable>> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public DrilldownPie(String chartId, Callable>> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ public JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map> map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ boolean reallyAllSkipped = true; ++ for (Map.Entry> entryValues : map.entrySet()) { ++ JSONObject value = new JSONObject(); ++ boolean allSkipped = true; ++ for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { ++ value.put(valueEntry.getKey(), valueEntry.getValue()); ++ allSkipped = false; ++ } ++ if (!allSkipped) { ++ reallyAllSkipped = false; ++ values.put(entryValues.getKey(), value); ++ } ++ } ++ if (reallyAllSkipped) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("values", values); ++ return data; ++ } ++ } ++ ++ /** ++ * Represents a custom single line chart. ++ */ ++ public static class SingleLineChart extends CustomChart { ++ ++ private final Callable callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public SingleLineChart(String chartId, Callable callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ int value = callable.call(); ++ if (value == 0) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("value", value); ++ return data; ++ } ++ ++ } ++ ++ /** ++ * Represents a custom multi line chart. ++ */ ++ public static class MultiLineChart extends CustomChart { ++ ++ private final Callable> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public MultiLineChart(String chartId, Callable> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ boolean allSkipped = true; ++ for (Map.Entry entry : map.entrySet()) { ++ if (entry.getValue() == 0) { ++ continue; // Skip this invalid ++ } ++ allSkipped = false; ++ values.put(entry.getKey(), entry.getValue()); ++ } ++ if (allSkipped) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("values", values); ++ return data; ++ } ++ ++ } ++ ++ /** ++ * Represents a custom simple bar chart. ++ */ ++ public static class SimpleBarChart extends CustomChart { ++ ++ private final Callable> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public SimpleBarChart(String chartId, Callable> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ for (Map.Entry entry : map.entrySet()) { ++ JSONArray categoryValues = new JSONArray(); ++ categoryValues.add(entry.getValue()); ++ values.put(entry.getKey(), categoryValues); ++ } ++ data.put("values", values); ++ return data; ++ } ++ ++ } ++ ++ /** ++ * Represents a custom advanced bar chart. ++ */ ++ public static class AdvancedBarChart extends CustomChart { ++ ++ private final Callable> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public AdvancedBarChart(String chartId, Callable> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ boolean allSkipped = true; ++ for (Map.Entry entry : map.entrySet()) { ++ if (entry.getValue().length == 0) { ++ continue; // Skip this invalid ++ } ++ allSkipped = false; ++ JSONArray categoryValues = new JSONArray(); ++ for (int categoryValue : entry.getValue()) { ++ categoryValues.add(categoryValue); ++ } ++ values.put(entry.getKey(), categoryValues); ++ } ++ if (allSkipped) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("values", values); ++ return data; ++ } ++ ++ } ++ ++ static class PaperMetrics { ++ static void startMetrics() { ++ // Get the config file ++ File configFile = new File(new File((File) MinecraftServer.getServer().options.valueOf("plugins"), "bStats"), "config.yml"); ++ YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); ++ ++ // Check if the config file exists ++ if (!config.isSet("serverUuid")) { ++ ++ // Add default values ++ config.addDefault("enabled", true); ++ // Every server gets it's unique random id. ++ config.addDefault("serverUuid", UUID.randomUUID().toString()); ++ // Should failed request be logged? ++ config.addDefault("logFailedRequests", false); ++ ++ // Inform the server owners about bStats ++ config.options().header( ++ "bStats collects some data for plugin authors like how many servers are using their plugins.\n" + ++ "To honor their work, you should not disable it.\n" + ++ "This has nearly no effect on the server performance!\n" + ++ "Check out https://bStats.org/ to learn more :)" ++ ).copyDefaults(true); ++ try { ++ config.save(configFile); ++ } catch (IOException ignored) { ++ } ++ } ++ // Load the data ++ String serverUUID = config.getString("serverUuid"); ++ boolean logFailedRequests = config.getBoolean("logFailedRequests", false); ++ // Only start Metrics, if it's enabled in the config ++ if (config.getBoolean("enabled", true)) { ++ Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger()); ++ ++ metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { ++ String minecraftVersion = Bukkit.getVersion(); ++ minecraftVersion = minecraftVersion.substring(minecraftVersion.indexOf("MC: ") + 4, minecraftVersion.length() - 1); ++ return minecraftVersion; ++ })); ++ ++ metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); ++ metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() || PaperConfig.isProxyOnlineMode() ? "online" : "offline")); ++ metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); ++ ++ metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { ++ Map> map = new HashMap<>(); ++ String javaVersion = System.getProperty("java.version"); ++ Map entry = new HashMap<>(); ++ entry.put(javaVersion, 1); ++ ++ // http://openjdk.java.net/jeps/223 ++ // Java decided to change their versioning scheme and in doing so modified the java.version system ++ // property to return $major[.$minor][.$secuity][-ea], as opposed to 1.$major.0_$identifier ++ // we can handle pre-9 by checking if the "major" is equal to "1", otherwise, 9+ ++ String majorVersion = javaVersion.split("\\.")[0]; ++ String release; ++ ++ int indexOf = javaVersion.lastIndexOf('.'); ++ ++ if (majorVersion.equals("1")) { ++ release = "Java " + javaVersion.substring(0, indexOf); ++ } else { ++ // of course, it really wouldn't be all that simple if they didn't add a quirk, now would it ++ // valid strings for the major may potentially include values such as -ea to deannotate a pre release ++ Matcher versionMatcher = Pattern.compile("\\d+").matcher(majorVersion); ++ if (versionMatcher.find()) { ++ majorVersion = versionMatcher.group(0); ++ } ++ release = "Java " + majorVersion; ++ } ++ map.put(release, entry); ++ ++ return map; ++ })); ++ ++ metrics.addCustomChart(new Metrics.DrilldownPie("legacy_plugins", () -> { ++ Map> map = new HashMap<>(); ++ ++ // count legacy plugins ++ int legacy = 0; ++ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { ++ if (CraftMagicNumbers.isLegacy(plugin.getDescription())) { ++ legacy++; ++ } ++ } ++ ++ // insert real value as lower dimension ++ Map entry = new HashMap<>(); ++ entry.put(String.valueOf(legacy), 1); ++ ++ // create buckets as higher dimension ++ if (legacy == 0) { ++ map.put("0 \uD83D\uDE0E", entry); // :sunglasses: ++ } else if (legacy <= 5) { ++ map.put("1-5", entry); ++ } else if (legacy <= 10) { ++ map.put("6-10", entry); ++ } else if (legacy <= 25) { ++ map.put("11-25", entry); ++ } else if (legacy <= 50) { ++ map.put("26-50", entry); ++ } else { ++ map.put("50+ \uD83D\uDE2D", entry); // :cry: ++ } ++ ++ return map; ++ })); ++ } ++ ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 2c0514892d3993bef57ecf677cf8bb0fbe0216e4..da922f395f0fff0881ead893c900c5b2623f48f0 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -42,6 +42,7 @@ public class PaperConfig { + private static boolean verbose; + private static boolean fatalError; + /*========================================================================*/ ++ private static boolean metricsStarted; + + public static void init(File configFile) { + CONFIG_FILE = configFile; +@@ -84,6 +85,11 @@ public class PaperConfig { + for (Map.Entry entry : commands.entrySet()) { + MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); + } ++ ++ if (!metricsStarted) { ++ Metrics.PaperMetrics.startMetrics(); ++ metricsStarted = true; ++ } + } + + static void readConfig(Class clazz, Object instance) { +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index dc11dab14624ca25e78bf0b919ecf461e0be430d..0083f979933d4a9035efb992ab0a2f250a56a979 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -83,6 +83,7 @@ public class SpigotConfig + MinecraftServer.getServer().server.getCommandMap().register( entry.getKey(), "Spigot", entry.getValue() ); + } + ++ /* // Paper - Replace with our own + if ( metrics == null ) + { + try +@@ -94,6 +95,7 @@ public class SpigotConfig + Bukkit.getServer().getLogger().log( Level.SEVERE, "Could not start metrics service", ex ); + } + } ++ */ // Paper end + } + + static void readConfig(Class clazz, Object instance) diff --git a/patches/server-remapped/0006-Add-MinecraftKey-Information-to-Objects.patch b/patches/server-remapped/0006-Add-MinecraftKey-Information-to-Objects.patch new file mode 100644 index 0000000000..91f564fb1b --- /dev/null +++ b/patches/server-remapped/0006-Add-MinecraftKey-Information-to-Objects.patch @@ -0,0 +1,144 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 01:40:13 -0400 +Subject: [PATCH] Add MinecraftKey Information to Objects + +Stores the reference to the objects respective MinecraftKey + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index d05eeaa711a09bb121b530654821894e795ff4ea..e95b91cefb0374bd5bb57cc090f5ecd566d7a618 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -208,7 +208,7 @@ public class PaperCommand extends Command { + + Collection entities = world.entitiesById.values(); + entities.forEach(e -> { +- ResourceLocation key = new ResourceLocation(""); // TODO: update in next patch ++ ResourceLocation key = e.getMinecraftKey(); + + MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); + ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); +diff --git a/src/main/java/net/minecraft/server/KeyedObject.java b/src/main/java/net/minecraft/server/KeyedObject.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3c9933050ca0a7453ba7950cb3cf4cc8b5b7081d +--- /dev/null ++++ b/src/main/java/net/minecraft/server/KeyedObject.java +@@ -0,0 +1,11 @@ ++package net.minecraft.server; ++ ++import net.minecraft.resources.ResourceLocation; ++ ++public interface KeyedObject { ++ ResourceLocation getMinecraftKey(); ++ default String getMinecraftKeyString() { ++ ResourceLocation key = getMinecraftKey(); ++ return key != null ? key.toString() : null; ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index c7008fcbd4d805fe0e743f1d4ad948dcd86ceae3..48c9d2b7d56832ebd13749a394b8b715f0b1704d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -135,7 +135,7 @@ import org.bukkit.event.player.PlayerTeleportEvent; + import org.bukkit.plugin.PluginManager; + // CraftBukkit end + +-public abstract class Entity implements Nameable, CommandSource { ++public abstract class Entity implements Nameable, CommandSource, net.minecraft.server.KeyedObject { // Paper + + // CraftBukkit start + private static final int CURRENT_LEVEL = 2; +@@ -1761,12 +1761,31 @@ public abstract class Entity implements Nameable, CommandSource { + return true; + } + ++ // Paper start ++ private ResourceLocation entityKey; ++ private String entityKeyString; ++ ++ @Override ++ public ResourceLocation getMinecraftKey() { ++ if (entityKey == null) { ++ this.entityKey = EntityType.getKey(this.getType()); ++ this.entityKeyString = this.entityKey != null ? this.entityKey.toString() : null; ++ } ++ return entityKey; ++ } ++ ++ @Override ++ public String getMinecraftKeyString() { ++ getMinecraftKey(); // Try to load if it doesn't exists. see: https://github.com/PaperMC/Paper/issues/1280 ++ return entityKeyString; ++ } + @Nullable + public final String getEncodeId() { + EntityType entitytypes = this.getType(); + ResourceLocation minecraftkey = EntityType.getKey(entitytypes); + +- return entitytypes.canSerialize() && minecraftkey != null ? minecraftkey.toString() : null; ++ return entitytypes != null && entitytypes.isPersistable() ? getMinecraftKeyString() : null; ++ // Paper end + } + + protected abstract void readAdditionalSaveData(CompoundTag tag); +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index 102298d57cf3143092d04ab1d5d0d69b28d696ea..2cb86de4bfc87a709f0cfa2c4e550d8e7928a3f0 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -384,6 +384,7 @@ public class EntityType { + } + } + ++ public boolean isPersistable() { return canSerialize(); } // Paper - OBFHELPER + public boolean canSerialize() { + return this.serialize; + } +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 8928a1ae51d24fd15aaae93bc8ea573548f2b012..846fc0f36377337630b2ec2a5f7a5a54c39c2965 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -23,7 +23,7 @@ import org.bukkit.inventory.InventoryHolder; + + import org.spigotmc.CustomTimingsHandler; // Spigot + +-public abstract class BlockEntity { ++public abstract class BlockEntity implements net.minecraft.server.KeyedObject { // Paper + + public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot + // CraftBukkit start - data containers +@@ -31,7 +31,7 @@ public abstract class BlockEntity { + public CraftPersistentDataContainer persistentDataContainer; + // CraftBukkit end + private static final Logger LOGGER = LogManager.getLogger(); +- private final BlockEntityType type; ++ private final BlockEntityType type; public BlockEntityType getTileEntityType() { return type; } // Paper - OBFHELPER + @Nullable + protected Level level; + protected BlockPos worldPosition; +@@ -45,6 +45,26 @@ public abstract class BlockEntity { + this.type = type; + } + ++ // Paper start ++ private String tileEntityKeyString = null; ++ private ResourceLocation tileEntityKey = null; ++ ++ @Override ++ public ResourceLocation getMinecraftKey() { ++ if (tileEntityKey == null) { ++ tileEntityKey = BlockEntityType.getKey(this.getTileEntityType()); ++ tileEntityKeyString = tileEntityKey != null ? tileEntityKey.toString() : null; ++ } ++ return tileEntityKey; ++ } ++ ++ @Override ++ public String getMinecraftKeyString() { ++ getMinecraftKey(); // Try to load if it doesn't exists. ++ return tileEntityKeyString; ++ } ++ // Paper end ++ + @Nullable + public Level getLevel() { + return this.level; diff --git a/patches/server-remapped/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch b/patches/server-remapped/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch new file mode 100644 index 0000000000..11ed8248cc --- /dev/null +++ b/patches/server-remapped/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch @@ -0,0 +1,171 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 02:10:36 -0400 +Subject: [PATCH] Store reference to current Chunk for Entity and Block + Entities + +This enables us a fast reference to the entities current chunk instead +of having to look it up by hashmap lookups. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 48c9d2b7d56832ebd13749a394b8b715f0b1704d..b633f6b3a36b793e6dbc1b8b554bfba74c719570 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -260,7 +260,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean isChunkLoaded() { +- return level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); ++ return getCurrentChunk() != null; + } + // CraftBukkit end + +@@ -1762,6 +1762,23 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + // Paper start ++ public java.lang.ref.WeakReference currentChunk = null; ++ ++ public void setCurrentChunk(net.minecraft.world.level.chunk.LevelChunk chunk) { ++ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; ++ } ++ /** ++ * Returns the entities current registered chunk. If the entity is not added to a chunk yet, it will return null ++ */ ++ public net.minecraft.world.level.chunk.LevelChunk getCurrentChunk() { ++ final net.minecraft.world.level.chunk.LevelChunk chunk = currentChunk != null ? currentChunk.get() : null; ++ if (chunk != null && chunk.loaded) { ++ return chunk; ++ } ++ ++ return !inChunk ? null : ((ServerLevel)level).getChunkSource().getChunkAtIfLoadedMainThreadNoCache(xChunk, zChunk); ++ } ++ + private ResourceLocation entityKey; + private String entityKeyString; + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 846fc0f36377337630b2ec2a5f7a5a54c39c2965..bb60c9da9f3ba0d5c5bad22512675ccb841a60e5 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -11,6 +11,7 @@ import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; + import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.LevelChunk; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import org.apache.logging.log4j.util.Supplier; +@@ -63,6 +64,15 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + getMinecraftKey(); // Try to load if it doesn't exists. + return tileEntityKeyString; + } ++ ++ private java.lang.ref.WeakReference currentChunk = null; ++ public LevelChunk getCurrentChunk() { ++ final LevelChunk chunk = currentChunk != null ? currentChunk.get() : null; ++ return chunk != null && chunk.loaded ? chunk : null; ++ } ++ public void setCurrentChunk(LevelChunk chunk) { ++ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; ++ } + // Paper end + + @Nullable +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index e2c5a17aa72d1a5412d76881187d4d9ad1763297..ae08fcce66d50d7f61bc3bd4a0e2547d56f53e82 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -89,11 +89,36 @@ public class LevelChunk implements ChunkAccess { + this(world, pos, biomes, UpgradeData.EMPTY, EmptyTickList.empty(), EmptyTickList.empty(), 0L, (LevelChunkSection[]) null, (Consumer) null); + } + ++ // Paper start ++ private class TileEntityHashMap extends java.util.HashMap { ++ @Override ++ public BlockEntity put(BlockPos key, BlockEntity value) { ++ BlockEntity replaced = super.put(key, value); ++ if (replaced != null) { ++ replaced.setCurrentChunk(null); ++ } ++ if (value != null) { ++ value.setCurrentChunk(LevelChunk.this); ++ } ++ return replaced; ++ } ++ ++ @Override ++ public BlockEntity remove(Object key) { ++ BlockEntity removed = super.remove(key); ++ if (removed != null) { ++ removed.setCurrentChunk(null); ++ } ++ return removed; ++ } ++ } ++ // Paper end ++ + public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes, UpgradeData upgradeData, TickList blockTickScheduler, TickList fluidTickScheduler, long inhabitedTime, @Nullable LevelChunkSection[] sections, @Nullable Consumer loadToWorldConsumer) { + this.sections = new LevelChunkSection[16]; + this.pendingBlockEntities = Maps.newHashMap(); + this.heightmaps = Maps.newEnumMap(Heightmap.Types.class); +- this.blockEntities = Maps.newHashMap(); ++ this.blockEntities = new TileEntityHashMap(); // Paper + this.structureStarts = Maps.newHashMap(); + this.structuresRefences = Maps.newHashMap(); + this.postProcessing = new ShortList[16]; +@@ -504,6 +529,7 @@ public class LevelChunk implements ChunkAccess { + } + + entity.inChunk = true; ++ entity.setCurrentChunk(this); // Paper + entity.xChunk = this.chunkPos.x; + entity.yChunk = k; + entity.zChunk = this.chunkPos.z; +@@ -516,6 +542,7 @@ public class LevelChunk implements ChunkAccess { + ((Heightmap) this.heightmaps.get(type)).setRawData(heightmap); + } + ++ public final void removeEntity(Entity entity) { this.removeEntity(entity); } // Paper - OBFHELPER + public void removeEntity(Entity entity) { + this.removeEntity(entity, entity.yChunk); + } +@@ -530,7 +557,12 @@ public class LevelChunk implements ChunkAccess { + section = this.entitySlices.length - 1; + } + +- this.entitySlices[section].remove(entity); ++ // Paper start ++ if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); ++ if (!this.entitySlices[section].remove(entity)) { ++ return; ++ } ++ // Paper end + this.entities.remove(entity); // Paper + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 080d3292e03c5a179b9eb89da1550718d263f817..eb61c803cf74c5ca2c51d5027a02ed3db6b53096 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -145,6 +145,7 @@ import net.minecraft.world.entity.vehicle.MinecartHopper; + import net.minecraft.world.entity.vehicle.MinecartSpawner; + import net.minecraft.world.entity.vehicle.MinecartTNT; + import net.minecraft.world.phys.AABB; ++import org.bukkit.Chunk; // Paper + import org.bukkit.EntityEffect; + import org.bukkit.Location; + import org.bukkit.Server; +@@ -186,6 +187,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + this.entity = entity; + } + ++ @Override ++ public Chunk getChunk() { ++ net.minecraft.world.level.chunk.LevelChunk currentChunk = entity.getCurrentChunk(); ++ return currentChunk != null ? currentChunk.bukkitChunk : getLocation().getChunk(); ++ } ++ + public static CraftEntity getEntity(CraftServer server, Entity entity) { + /* + * Order is *EXTREMELY* important -- keep it right! =D diff --git a/patches/server-remapped/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch b/patches/server-remapped/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch new file mode 100644 index 0000000000..ca1271ce76 --- /dev/null +++ b/patches/server-remapped/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 02:13:59 -0400 +Subject: [PATCH] Store counts for each Entity/Block Entity Type + +Opens door for future patches to optimize performance + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index ae08fcce66d50d7f61bc3bd4a0e2547d56f53e82..00ce55c17980da87a3834f952475a766543506b0 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -90,15 +90,19 @@ public class LevelChunk implements ChunkAccess { + } + + // Paper start ++ public final co.aikar.util.Counter entityCounts = new co.aikar.util.Counter<>(); ++ public final co.aikar.util.Counter tileEntityCounts = new co.aikar.util.Counter<>(); + private class TileEntityHashMap extends java.util.HashMap { + @Override + public BlockEntity put(BlockPos key, BlockEntity value) { + BlockEntity replaced = super.put(key, value); + if (replaced != null) { + replaced.setCurrentChunk(null); ++ tileEntityCounts.decrement(replaced.getMinecraftKeyString()); + } + if (value != null) { + value.setCurrentChunk(LevelChunk.this); ++ tileEntityCounts.increment(value.getMinecraftKeyString()); + } + return replaced; + } +@@ -108,6 +112,7 @@ public class LevelChunk implements ChunkAccess { + BlockEntity removed = super.remove(key); + if (removed != null) { + removed.setCurrentChunk(null); ++ tileEntityCounts.decrement(removed.getMinecraftKeyString()); + } + return removed; + } +@@ -528,6 +533,7 @@ public class LevelChunk implements ChunkAccess { + k = this.entitySlices.length - 1; + } + ++ if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper + entity.inChunk = true; + entity.setCurrentChunk(this); // Paper + entity.xChunk = this.chunkPos.x; +@@ -562,6 +568,7 @@ public class LevelChunk implements ChunkAccess { + if (!this.entitySlices[section].remove(entity)) { + return; + } ++ entityCounts.decrement(entity.getMinecraftKeyString()); + // Paper end + this.entities.remove(entity); // Paper + } diff --git a/patches/server-remapped/0009-Timings-v2.patch b/patches/server-remapped/0009-Timings-v2.patch new file mode 100644 index 0000000000..dc683eaeec --- /dev/null +++ b/patches/server-remapped/0009-Timings-v2.patch @@ -0,0 +1,2330 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 04:00:11 -0600 +Subject: [PATCH] Timings v2 + + +diff --git a/src/main/java/SpigotTimings.java b/src/main/java/SpigotTimings.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 +diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java +new file mode 100644 +index 0000000000000000000000000000000000000000..be3a62f543a5fec4739c14821fe5a443c1fa3f5b +--- /dev/null ++++ b/src/main/java/co/aikar/timings/MinecraftTimings.java +@@ -0,0 +1,152 @@ ++package co.aikar.timings; ++ ++import Timing; ++import com.google.common.collect.MapMaker; ++import net.minecraft.commands.CommandFunction; ++import net.minecraft.network.protocol.Packet; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.entity.BlockEntity; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.scheduler.BukkitTask; ++ ++import org.bukkit.craftbukkit.scheduler.CraftTask; ++ ++import java.util.Map; ++ ++// TODO: Re-implement missing timers ++public final class MinecraftTimings { ++ ++ public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); ++ public static final Timing playerListTimer = Timings.ofSafe("Player List"); ++ public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); ++ public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); ++ public static final Timing tickablesTimer = Timings.ofSafe("Tickables"); ++ public static final Timing minecraftSchedulerTimer = Timings.ofSafe("Minecraft Scheduler"); ++ public static final Timing bukkitSchedulerTimer = Timings.ofSafe("Bukkit Scheduler"); ++ public static final Timing bukkitSchedulerPendingTimer = Timings.ofSafe("Bukkit Scheduler - Pending"); ++ public static final Timing bukkitSchedulerFinishTimer = Timings.ofSafe("Bukkit Scheduler - Finishing"); ++ public static final Timing chunkIOTickTimer = Timings.ofSafe("ChunkIOTick"); ++ public static final Timing timeUpdateTimer = Timings.ofSafe("Time Update"); ++ public static final Timing serverCommandTimer = Timings.ofSafe("Server Command"); ++ public static final Timing savePlayers = Timings.ofSafe("Save Players"); ++ ++ public static final Timing tickEntityTimer = Timings.ofSafe("## tickEntity"); ++ public static final Timing tickTileEntityTimer = Timings.ofSafe("## tickTileEntity"); ++ public static final Timing packetProcessTimer = Timings.ofSafe("## Packet Processing"); ++ public static final Timing scheduledBlocksTimer = Timings.ofSafe("## Scheduled Blocks"); ++ public static final Timing structureGenerationTimer = Timings.ofSafe("Structure Generation"); ++ ++ public static final Timing processQueueTimer = Timings.ofSafe("processQueue"); ++ public static final Timing processTasksTimer = Timings.ofSafe("processTasks"); ++ ++ public static final Timing playerCommandTimer = Timings.ofSafe("playerCommand"); ++ ++ public static final Timing entityActivationCheckTimer = Timings.ofSafe("entityActivationCheck"); ++ ++ public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update"); ++ public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate"); ++ ++ private static final Map, String> taskNameCache = new MapMaker().weakKeys().makeMap(); ++ ++ private MinecraftTimings() {} ++ ++ public static Timing getInternalTaskName(String taskName) { ++ return Timings.ofSafe(taskName); ++ } ++ ++ /** ++ * Gets a timer associated with a plugins tasks. ++ * @param bukkitTask ++ * @param period ++ * @return ++ */ ++ public static Timing getPluginTaskTimings(BukkitTask bukkitTask, long period) { ++ if (!bukkitTask.isSync()) { ++ return NullTimingHandler.NULL; ++ } ++ Plugin plugin; ++ ++ CraftTask craftTask = (CraftTask) bukkitTask; ++ ++ final Class taskClass = craftTask.getTaskClass(); ++ if (bukkitTask.getOwner() != null) { ++ plugin = bukkitTask.getOwner(); ++ } else { ++ plugin = TimingsManager.getPluginByClassloader(taskClass); ++ } ++ ++ final String taskname = taskNameCache.computeIfAbsent(taskClass, clazz -> { ++ try { ++ String clsName = !clazz.isMemberClass() ++ ? clazz.getName() ++ : clazz.getCanonicalName(); ++ if (clsName != null && clsName.contains("$Lambda$")) { ++ clsName = clsName.replaceAll("(Lambda\\$.*?)/.*", "$1"); ++ } ++ return clsName != null ? clsName : "UnknownTask"; ++ } catch (Throwable ex) { ++ new Exception("Error occurred detecting class name", ex).printStackTrace(); ++ return "MangledClassFile"; ++ } ++ }); ++ ++ StringBuilder name = new StringBuilder(64); ++ name.append("Task: ").append(taskname); ++ if (period > 0) { ++ name.append(" (interval:").append(period).append(")"); ++ } else { ++ name.append(" (Single)"); ++ } ++ ++ if (plugin == null) { ++ return Timings.ofSafe(null, name.toString()); ++ } ++ ++ return Timings.ofSafe(plugin, name.toString()); ++ } ++ ++ /** ++ * Get a named timer for the specified entity type to track type specific timings. ++ * @param entityType ++ * @return ++ */ ++ public static Timing getEntityTimings(String entityType, String type) { ++ return Timings.ofSafe("Minecraft", "## tickEntity - " + entityType + " - " + type, tickEntityTimer); ++ } ++ ++ /** ++ * Get a named timer for the specified tile entity type to track type specific timings. ++ * @param entity ++ * @return ++ */ ++ public static Timing getTileEntityTimings(BlockEntity entity) { ++ String entityType = entity.getClass().getName(); ++ return Timings.ofSafe("Minecraft", "## tickTileEntity - " + entityType, tickTileEntityTimer); ++ } ++ public static Timing getCancelTasksTimer() { ++ return Timings.ofSafe("Cancel Tasks"); ++ } ++ public static Timing getCancelTasksTimer(Plugin plugin) { ++ return Timings.ofSafe(plugin, "Cancel Tasks"); ++ } ++ ++ public static void stopServer() { ++ TimingsManager.stopServer(); ++ } ++ ++ public static Timing getBlockTiming(Block block) { ++ return Timings.ofSafe("## Scheduled Block: " + block.toString(), scheduledBlocksTimer); ++ } ++/* ++ public static Timing getStructureTiming(StructureGenerator structureGenerator) { ++ return Timings.ofSafe("Structure Generator - " + structureGenerator.getName(), structureGenerationTimer); ++ }*/ ++ ++ public static Timing getPacketTiming(Packet packet) { ++ return Timings.ofSafe("## Packet - " + packet.getClass().getName(), packetProcessTimer); ++ } ++ ++ public static Timing getCommandFunctionTiming(CommandFunction function) { ++ return Timings.ofSafe("Command Function - " + function.getMinecraftKey().toString()); ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java +new file mode 100644 +index 0000000000000000000000000000000000000000..94adf0275a2e7093c152cc3b8b0a5747b3a13a86 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingsExport.java +@@ -0,0 +1,380 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import com.google.common.collect.Sets; ++import net.minecraft.server.MinecraftServer; ++import org.apache.commons.lang.StringUtils; ++import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; ++import org.bukkit.Material; ++import org.bukkit.configuration.ConfigurationSection; ++import org.bukkit.configuration.MemorySection; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.entity.EntityType; ++import org.json.simple.JSONObject; ++import org.json.simple.JSONValue; ++ ++import java.io.ByteArrayOutputStream; ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.OutputStream; ++import java.lang.management.ManagementFactory; ++import java.lang.management.OperatingSystemMXBean; ++import java.lang.management.RuntimeMXBean; ++import java.net.HttpURLConnection; ++import java.net.InetAddress; ++import java.net.URL; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import java.util.logging.Level; ++import java.util.zip.GZIPOutputStream; ++ ++import static co.aikar.timings.TimingsManager.HISTORY; ++import static co.aikar.util.JSONUtil.appendObjectData; ++import static co.aikar.util.JSONUtil.createObject; ++import static co.aikar.util.JSONUtil.pair; ++import static co.aikar.util.JSONUtil.toArray; ++import static co.aikar.util.JSONUtil.toArrayMapper; ++import static co.aikar.util.JSONUtil.toObjectMapper; ++ ++import TimingHistory; ++import TimingsReportListener; ++ ++@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) ++public class TimingsExport extends Thread { ++ ++ private final TimingsReportListener listeners; ++ private final Map out; ++ private final TimingHistory[] history; ++ private static long lastReport = 0; ++ ++ private TimingsExport(TimingsReportListener listeners, Map out, TimingHistory[] history) { ++ super("Timings paste thread"); ++ this.listeners = listeners; ++ this.out = out; ++ this.history = history; ++ } ++ ++ /** ++ * Checks if any pending reports are being requested, and builds one if needed. ++ */ ++ public static void reportTimings() { ++ if (Timings.requestingReport.isEmpty()) { ++ return; ++ } ++ TimingsReportListener listeners = new TimingsReportListener(Timings.requestingReport); ++ listeners.addConsoleIfNeeded(); ++ ++ Timings.requestingReport.clear(); ++ long now = System.currentTimeMillis(); ++ final long lastReportDiff = now - lastReport; ++ if (lastReportDiff < 60000) { ++ listeners.sendMessage(ChatColor.RED + "Please wait at least 1 minute in between Timings reports. (" + (int)((60000 - lastReportDiff) / 1000) + " seconds)"); ++ listeners.done(); ++ return; ++ } ++ final long lastStartDiff = now - TimingsManager.timingStart; ++ if (lastStartDiff < 180000) { ++ listeners.sendMessage(ChatColor.RED + "Please wait at least 3 minutes before generating a Timings report. Unlike Timings v1, v2 benefits from longer timings and is not as useful with short timings. (" + (int)((180000 - lastStartDiff) / 1000) + " seconds)"); ++ listeners.done(); ++ return; ++ } ++ listeners.sendMessage(ChatColor.GREEN + "Preparing Timings Report..."); ++ lastReport = now; ++ Map parent = createObject( ++ // Get some basic system details about the server ++ pair("version", Bukkit.getVersion()), ++ pair("maxplayers", Bukkit.getMaxPlayers()), ++ pair("start", TimingsManager.timingStart / 1000), ++ pair("end", System.currentTimeMillis() / 1000), ++ pair("online-mode", Bukkit.getServer().getOnlineMode()), ++ pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), ++ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedIds(), pack -> { ++ // Don't feel like obf helper'ing these, non fatal if its temp missed. ++ return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); ++ })) ++ ); ++ if (!TimingsManager.privacy) { ++ appendObjectData(parent, ++ pair("server", Bukkit.getUnsafe().getTimingsServerName()), ++ pair("motd", Bukkit.getServer().getMotd()), ++ pair("icon", Bukkit.getServer().getServerIcon().getData()) ++ ); ++ } ++ ++ final Runtime runtime = Runtime.getRuntime(); ++ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); ++ ++ OperatingSystemMXBean osInfo = ManagementFactory.getOperatingSystemMXBean(); ++ ++ parent.put("system", createObject( ++ pair("timingcost", getCost()), ++ pair("loadavg", osInfo.getSystemLoadAverage()), ++ pair("name", System.getProperty("os.name")), ++ pair("version", System.getProperty("os.version")), ++ pair("jvmversion", System.getProperty("java.version")), ++ pair("arch", System.getProperty("os.arch")), ++ pair("maxmem", runtime.maxMemory()), ++ pair("memory", createObject( ++ pair("heap", ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().toString()), ++ pair("nonheap", ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().toString()), ++ pair("finalizing", ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount()) ++ )), ++ pair("cpu", runtime.availableProcessors()), ++ pair("runtime", runtimeBean.getUptime()), ++ pair("flags", StringUtils.join(runtimeBean.getInputArguments(), " ")), ++ pair("gc", toObjectMapper(ManagementFactory.getGarbageCollectorMXBeans(), input -> pair(input.getName(), toArray(input.getCollectionCount(), input.getCollectionTime())))) ++ ) ++ ); ++ ++ parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getAllLevels(), world -> { ++ if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; ++ return pair(world.getWorldData().getName(), createObject( ++ pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { ++ return pair(rule, world.getWorld().getGameRuleValue(rule)); ++ })), ++ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) ++ )); ++ })); ++ ++ Set tileEntityTypeSet = Sets.newHashSet(); ++ Set entityTypeSet = Sets.newHashSet(); ++ ++ int size = HISTORY.size(); ++ TimingHistory[] history = new TimingHistory[size + 1]; ++ int i = 0; ++ for (TimingHistory timingHistory : HISTORY) { ++ tileEntityTypeSet.addAll(timingHistory.tileEntityTypeSet); ++ entityTypeSet.addAll(timingHistory.entityTypeSet); ++ history[i++] = timingHistory; ++ } ++ ++ history[i] = new TimingHistory(); // Current snapshot ++ tileEntityTypeSet.addAll(history[i].tileEntityTypeSet); ++ entityTypeSet.addAll(history[i].entityTypeSet); ++ ++ ++ Map handlers = createObject(); ++ Map groupData; ++ synchronized (TimingIdentifier.GROUP_MAP) { ++ for (TimingIdentifier.TimingGroup group : TimingIdentifier.GROUP_MAP.values()) { ++ synchronized (group.handlers) { ++ for (TimingHandler id : group.handlers) { ++ ++ if (!id.isTimed() && !id.isSpecial()) { ++ continue; ++ } ++ ++ String name = id.identifier.name; ++ if (name.startsWith("##")) { ++ name = name.substring(3); ++ } ++ handlers.put(id.id, toArray( ++ group.id, ++ name ++ )); ++ } ++ } ++ } ++ ++ groupData = toObjectMapper( ++ TimingIdentifier.GROUP_MAP.values(), group -> pair(group.id, group.name)); ++ } ++ ++ parent.put("idmap", createObject( ++ pair("groups", groupData), ++ pair("handlers", handlers), ++ pair("worlds", toObjectMapper(TimingHistory.worldMap.entrySet(), input -> pair(input.getValue(), input.getKey()))), ++ pair("tileentity", ++ toObjectMapper(tileEntityTypeSet, input -> pair(input.ordinal(), input.name()))), ++ pair("entity", ++ toObjectMapper(entityTypeSet, input -> pair(input.ordinal(), input.name()))) ++ )); ++ ++ // Information about loaded plugins ++ ++ parent.put("plugins", toObjectMapper(Bukkit.getPluginManager().getPlugins(), ++ plugin -> pair(plugin.getName(), createObject( ++ pair("version", plugin.getDescription().getVersion()), ++ pair("description", String.valueOf(plugin.getDescription().getDescription()).trim()), ++ pair("website", plugin.getDescription().getWebsite()), ++ pair("authors", StringUtils.join(plugin.getDescription().getAuthors(), ", ")) ++ )))); ++ ++ ++ ++ // Information on the users Config ++ ++ parent.put("config", createObject( ++ pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), ++ pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), ++ pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) ++ )); ++ ++ new TimingsExport(listeners, parent, history).start(); ++ } ++ ++ static long getCost() { ++ // Benchmark the users System.nanotime() for cost basis ++ int passes = 100; ++ TimingHandler SAMPLER1 = Timings.ofSafe("Timings Sampler 1"); ++ TimingHandler SAMPLER2 = Timings.ofSafe("Timings Sampler 2"); ++ TimingHandler SAMPLER3 = Timings.ofSafe("Timings Sampler 3"); ++ TimingHandler SAMPLER4 = Timings.ofSafe("Timings Sampler 4"); ++ TimingHandler SAMPLER5 = Timings.ofSafe("Timings Sampler 5"); ++ TimingHandler SAMPLER6 = Timings.ofSafe("Timings Sampler 6"); ++ ++ long start = System.nanoTime(); ++ for (int i = 0; i < passes; i++) { ++ SAMPLER1.startTiming(); ++ SAMPLER2.startTiming(); ++ SAMPLER3.startTiming(); ++ SAMPLER3.stopTiming(); ++ SAMPLER4.startTiming(); ++ SAMPLER5.startTiming(); ++ SAMPLER6.startTiming(); ++ SAMPLER6.stopTiming(); ++ SAMPLER5.stopTiming(); ++ SAMPLER4.stopTiming(); ++ SAMPLER2.stopTiming(); ++ SAMPLER1.stopTiming(); ++ } ++ long timingsCost = (System.nanoTime() - start) / passes / 6; ++ SAMPLER1.reset(true); ++ SAMPLER2.reset(true); ++ SAMPLER3.reset(true); ++ SAMPLER4.reset(true); ++ SAMPLER5.reset(true); ++ SAMPLER6.reset(true); ++ return timingsCost; ++ } ++ ++ private static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) { ++ ++ JSONObject object = new JSONObject(); ++ for (String key : config.getKeys(false)) { ++ String fullKey = (parentKey != null ? parentKey + "." + key : key); ++ if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld")) { ++ continue; ++ } ++ final Object val = config.get(key); ++ ++ object.put(key, valAsJSON(val, fullKey)); ++ } ++ return object; ++ } ++ ++ private static Object valAsJSON(Object val, final String parentKey) { ++ if (!(val instanceof MemorySection)) { ++ if (val instanceof List) { ++ Iterable v = (Iterable) val; ++ return toArrayMapper(v, input -> valAsJSON(input, parentKey)); ++ } else { ++ return String.valueOf(val); ++ } ++ } else { ++ return mapAsJSON((ConfigurationSection) val, parentKey); ++ } ++ } ++ ++ @Override ++ public void run() { ++ out.put("data", toArrayMapper(history, TimingHistory::export)); ++ ++ ++ String response = null; ++ String timingsURL = null; ++ try { ++ HttpURLConnection con = (HttpURLConnection) new URL("http://timings.aikar.co/post").openConnection(); ++ con.setDoOutput(true); ++ String hostName = "BrokenHost"; ++ try { ++ hostName = InetAddress.getLocalHost().getHostName(); ++ } catch (Exception ignored) {} ++ con.setRequestProperty("User-Agent", "Paper/" + Bukkit.getUnsafe().getTimingsServerName() + "/" + hostName); ++ con.setRequestMethod("POST"); ++ con.setInstanceFollowRedirects(false); ++ ++ OutputStream request = new GZIPOutputStream(con.getOutputStream()) {{ ++ this.def.setLevel(7); ++ }}; ++ ++ request.write(JSONValue.toJSONString(out).getBytes("UTF-8")); ++ request.close(); ++ ++ response = getResponse(con); ++ ++ if (con.getResponseCode() != 302) { ++ listeners.sendMessage( ++ ChatColor.RED + "Upload Error: " + con.getResponseCode() + ": " + con.getResponseMessage()); ++ listeners.sendMessage(ChatColor.RED + "Check your logs for more information"); ++ if (response != null) { ++ Bukkit.getLogger().log(Level.SEVERE, response); ++ } ++ return; ++ } ++ ++ timingsURL = con.getHeaderField("Location"); ++ listeners.sendMessage(ChatColor.GREEN + "View Timings Report: " + timingsURL); ++ ++ if (response != null && !response.isEmpty()) { ++ Bukkit.getLogger().log(Level.INFO, "Timing Response: " + response); ++ } ++ } catch (IOException ex) { ++ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); ++ if (response != null) { ++ Bukkit.getLogger().log(Level.SEVERE, response); ++ } ++ Bukkit.getLogger().log(Level.SEVERE, "Could not paste timings", ex); ++ } finally { ++ this.listeners.done(timingsURL); ++ } ++ } ++ ++ private String getResponse(HttpURLConnection con) throws IOException { ++ InputStream is = null; ++ try { ++ is = con.getInputStream(); ++ ByteArrayOutputStream bos = new ByteArrayOutputStream(); ++ ++ byte[] b = new byte[1024]; ++ int bytesRead; ++ while ((bytesRead = is.read(b)) != -1) { ++ bos.write(b, 0, bytesRead); ++ } ++ return bos.toString(); ++ ++ } catch (IOException ex) { ++ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); ++ Bukkit.getLogger().log(Level.WARNING, con.getResponseMessage(), ex); ++ return null; ++ } finally { ++ if (is != null) { ++ is.close(); ++ } ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..79ede25e4fe7a648b1d29c49d876482a2158f892 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +@@ -0,0 +1,120 @@ ++package co.aikar.timings; ++ ++import Timing; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.storage.PrimaryLevelData; ++ ++/** ++ * Set of timers per world, to track world specific timings. ++ */ ++// TODO: Re-implement missing timers ++public class WorldTimingsHandler { ++ public final Timing mobSpawn; ++ public final Timing doChunkUnload; ++ public final Timing doPortalForcer; ++ public final Timing scheduledBlocks; ++ public final Timing scheduledBlocksCleanup; ++ public final Timing scheduledBlocksTicking; ++ public final Timing chunkTicks; ++ public final Timing lightChunk; ++ public final Timing chunkTicksBlocks; ++ public final Timing doVillages; ++ public final Timing doChunkMap; ++ public final Timing doChunkMapUpdate; ++ public final Timing doChunkMapToUpdate; ++ public final Timing doChunkMapSortMissing; ++ public final Timing doChunkMapSortSendToPlayers; ++ public final Timing doChunkMapPlayersNeedingChunks; ++ public final Timing doChunkMapPendingSendToPlayers; ++ public final Timing doChunkMapUnloadChunks; ++ public final Timing doChunkGC; ++ public final Timing doSounds; ++ public final Timing entityRemoval; ++ public final Timing entityTick; ++ public final Timing tileEntityTick; ++ public final Timing tileEntityPending; ++ public final Timing tracker1; ++ public final Timing tracker2; ++ public final Timing doTick; ++ public final Timing tickEntities; ++ public final Timing chunks; ++ public final Timing newEntities; ++ public final Timing raids; ++ public final Timing chunkProviderTick; ++ public final Timing broadcastChunkUpdates; ++ public final Timing countNaturalMobs; ++ ++ public final Timing chunkLoad; ++ public final Timing chunkLoadPopulate; ++ public final Timing syncChunkLoad; ++ public final Timing chunkLoadLevelTimer; ++ public final Timing chunkIO; ++ public final Timing chunkPostLoad; ++ public final Timing worldSave; ++ public final Timing worldSaveChunks; ++ public final Timing worldSaveLevel; ++ public final Timing chunkSaveData; ++ ++ ++ public final Timing miscMobSpawning; ++ ++ public WorldTimingsHandler(Level server) { ++ String name = ((PrimaryLevelData) server.getLevelData()).getLevelName() + " - "; ++ ++ mobSpawn = Timings.ofSafe(name + "mobSpawn"); ++ doChunkUnload = Timings.ofSafe(name + "doChunkUnload"); ++ scheduledBlocks = Timings.ofSafe(name + "Scheduled Blocks"); ++ scheduledBlocksCleanup = Timings.ofSafe(name + "Scheduled Blocks - Cleanup"); ++ scheduledBlocksTicking = Timings.ofSafe(name + "Scheduled Blocks - Ticking"); ++ chunkTicks = Timings.ofSafe(name + "Chunk Ticks"); ++ lightChunk = Timings.ofSafe(name + "Light Chunk"); ++ chunkTicksBlocks = Timings.ofSafe(name + "Chunk Ticks - Blocks"); ++ doVillages = Timings.ofSafe(name + "doVillages"); ++ doChunkMap = Timings.ofSafe(name + "doChunkMap"); ++ doChunkMapUpdate = Timings.ofSafe(name + "doChunkMap - Update"); ++ doChunkMapToUpdate = Timings.ofSafe(name + "doChunkMap - To Update"); ++ doChunkMapSortMissing = Timings.ofSafe(name + "doChunkMap - Sort Missing"); ++ doChunkMapSortSendToPlayers = Timings.ofSafe(name + "doChunkMap - Sort Send To Players"); ++ doChunkMapPlayersNeedingChunks = Timings.ofSafe(name + "doChunkMap - Players Needing Chunks"); ++ doChunkMapPendingSendToPlayers = Timings.ofSafe(name + "doChunkMap - Pending Send To Players"); ++ doChunkMapUnloadChunks = Timings.ofSafe(name + "doChunkMap - Unload Chunks"); ++ doSounds = Timings.ofSafe(name + "doSounds"); ++ doChunkGC = Timings.ofSafe(name + "doChunkGC"); ++ doPortalForcer = Timings.ofSafe(name + "doPortalForcer"); ++ entityTick = Timings.ofSafe(name + "entityTick"); ++ entityRemoval = Timings.ofSafe(name + "entityRemoval"); ++ tileEntityTick = Timings.ofSafe(name + "tileEntityTick"); ++ tileEntityPending = Timings.ofSafe(name + "tileEntityPending"); ++ ++ chunkLoad = Timings.ofSafe(name + "Chunk Load"); ++ chunkLoadPopulate = Timings.ofSafe(name + "Chunk Load - Populate"); ++ syncChunkLoad = Timings.ofSafe(name + "Sync Chunk Load"); ++ chunkLoadLevelTimer = Timings.ofSafe(name + "Chunk Load - Load Level"); ++ chunkIO = Timings.ofSafe(name + "Chunk Load - DiskIO"); ++ chunkPostLoad = Timings.ofSafe(name + "Chunk Load - Post Load"); ++ worldSave = Timings.ofSafe(name + "World Save"); ++ worldSaveLevel = Timings.ofSafe(name + "World Save - Level"); ++ worldSaveChunks = Timings.ofSafe(name + "World Save - Chunks"); ++ chunkSaveData = Timings.ofSafe(name + "Chunk Save - Data"); ++ ++ tracker1 = Timings.ofSafe(name + "tracker stage 1"); ++ tracker2 = Timings.ofSafe(name + "tracker stage 2"); ++ doTick = Timings.ofSafe(name + "doTick"); ++ tickEntities = Timings.ofSafe(name + "tickEntities"); ++ ++ chunks = Timings.ofSafe(name + "Chunks"); ++ newEntities = Timings.ofSafe(name + "New entity registration"); ++ raids = Timings.ofSafe(name + "Raids"); ++ chunkProviderTick = Timings.ofSafe(name + "Chunk provider tick"); ++ broadcastChunkUpdates = Timings.ofSafe(name + "Broadcast chunk updates"); ++ countNaturalMobs = Timings.ofSafe(name + "Count natural mobs"); ++ ++ ++ miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); ++ } ++ ++ public static Timing getTickList(ServerLevel worldserver, String timingsType) { ++ return Timings.ofSafe(((PrimaryLevelData) worldserver.getLevelData()).getLevelName() + " - Scheduled " + timingsType); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index da922f395f0fff0881ead893c900c5b2623f48f0..1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -14,12 +14,15 @@ import java.util.concurrent.TimeUnit; + import java.util.logging.Level; + import java.util.regex.Pattern; + ++import com.google.common.collect.Lists; + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; + import org.bukkit.command.Command; + import org.bukkit.configuration.ConfigurationSection; + import org.bukkit.configuration.InvalidConfigurationException; + import org.bukkit.configuration.file.YamlConfiguration; ++import co.aikar.timings.Timings; ++import co.aikar.timings.TimingsManager; + + public class PaperConfig { + +@@ -188,4 +191,30 @@ public class PaperConfig { + config.addDefault(path, def); + return config.getString(path, config.getString(path)); + } ++ ++ public static String timingsServerName; ++ private static void timings() { ++ boolean timings = getBoolean("timings.enabled", true); ++ boolean verboseTimings = getBoolean("timings.verbose", true); ++ TimingsManager.privacy = getBoolean("timings.server-name-privacy", false); ++ TimingsManager.hiddenConfigs = getList("timings.hidden-config-entries", Lists.newArrayList("database", "settings.bungeecord-addresses", "settings.velocity-support.secret")); ++ if (!TimingsManager.hiddenConfigs.contains("settings.velocity-support.secret")) { ++ TimingsManager.hiddenConfigs.add("settings.velocity-support.secret"); ++ } ++ int timingHistoryInterval = getInt("timings.history-interval", 300); ++ int timingHistoryLength = getInt("timings.history-length", 3600); ++ timingsServerName = getString("timings.server-name", "Unknown Server"); ++ ++ ++ Timings.setVerboseTimingsEnabled(verboseTimings); ++ Timings.setTimingsEnabled(timings); ++ Timings.setHistoryInterval(timingHistoryInterval * 20); ++ Timings.setHistoryLength(timingHistoryLength * 20); ++ ++ log("Timings: " + timings + ++ " - Verbose: " + verboseTimings + ++ " - Interval: " + timeSummary(Timings.getHistoryInterval() / 20) + ++ " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + ++ " - Server Name: " + timingsServerName); ++ } + } +diff --git a/src/main/java/net/minecraft/commands/CommandFunction.java b/src/main/java/net/minecraft/commands/CommandFunction.java +index cf57de0e791a9362fe95b65134d9fe4f4e95adf4..07b891075191161a8a903876b02caa75d4db1366 100644 +--- a/src/main/java/net/minecraft/commands/CommandFunction.java ++++ b/src/main/java/net/minecraft/commands/CommandFunction.java +@@ -15,12 +15,22 @@ public class CommandFunction { + + private final CommandFunction.Entry[] entries; + private final ResourceLocation id; ++ // Paper start ++ public co.aikar.timings.Timing timing; ++ public co.aikar.timings.Timing getTiming() { ++ if (timing == null) { ++ timing = co.aikar.timings.MinecraftTimings.getCommandFunctionTiming(this); ++ } ++ return timing; ++ } ++ // Paper end + + public CommandFunction(ResourceLocation id, CommandFunction.Entry[] elements) { + this.id = id; + this.entries = elements; + } + ++ public final ResourceLocation getMinecraftKey() { return this.getId(); } // Paper - OBFHELPER + public ResourceLocation getId() { + return this.id; + } +diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java +index 23ccd095ad99fe90a6f2a16bcca368804b16101a..4ae8201d7dcffeb3298a4e593f978e15ffc5ac15 100644 +--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java ++++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java +@@ -3,6 +3,8 @@ package net.minecraft.network.protocol; + import net.minecraft.network.PacketListener; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import co.aikar.timings.MinecraftTimings; // Paper ++import co.aikar.timings.Timing; // Paper + + // CraftBukkit start + import net.minecraft.server.MinecraftServer; +@@ -21,10 +23,13 @@ public class PacketUtils { + + public static void ensureRunningOnSameThread(Packet packet, T listener, BlockableEventLoop engine) throws RunningOnDifferentThreadException { + if (!engine.isSameThread()) { ++ Timing timing = MinecraftTimings.getPacketTiming(packet); // Paper - timings + engine.execute(() -> { + if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerGamePacketListenerImpl && ((ServerGamePacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590 + if (listener.a().isConnected()) { ++ try (Timing ignored = timing.startTiming()) { // Paper - timings + packet.handle(listener); ++ } // Paper - timings + } else { + PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 2406879e76a110e96a4753e66366432a4bc52d9b..a456b9cbf0e5eea4e888e0e3d07ed17558650371 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -172,7 +172,7 @@ import org.bukkit.craftbukkit.Main; + import org.bukkit.event.server.ServerLoadEvent; + // CraftBukkit end + +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper + import org.spigotmc.SlackActivityAccountant; // Spigot + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { +@@ -226,8 +226,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +- return !this.haveTime(); ++ return !this.canSleepForTickNoOversleep(); // Paper - move oversleep into full server tick + }); + } + +@@ -1120,10 +1133,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { ++ return !this.canOversleep(); ++ }); ++ isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); ++ // Paper end ++ + ++this.tickCount; + this.tickChildren(shouldKeepTicking); + if (i - this.lastServerStatus >= 5000000000L) { +@@ -1141,14 +1162,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % autosavePeriod == 0) { // CraftBukkit +- SpigotTimings.worldSaveTimer.startTiming(); // Spigot + MinecraftServer.LOGGER.debug("Autosave started"); + this.profiler.push("save"); + this.playerList.saveAll(); + this.saveAllChunks(true, false, false); + this.profiler.pop(); + MinecraftServer.LOGGER.debug("Autosave finished"); +- SpigotTimings.worldSaveTimer.stopTiming(); // Spigot + } + + this.profiler.push("snooper"); +@@ -1161,6 +1180,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { + // CraftBukkit start - fire RemoteServerCommandEvent +@@ -677,10 +679,39 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + if (event.isCancelled()) { + return; + } ++ // Paper start ++ if (command.toLowerCase().startsWith("timings") && command.toLowerCase().matches("timings (report|paste|get|merged|seperate)")) { ++ org.bukkit.command.BufferedCommandSender sender = new org.bukkit.command.BufferedCommandSender(); ++ Waitable waitable = new Waitable() { ++ @Override ++ protected String evaluate() { ++ return sender.getBuffer(); ++ } ++ }; ++ waitableArray[0] = waitable; ++ co.aikar.timings.Timings.generateReport(new co.aikar.timings.TimingsReportListener(sender, waitable)); ++ } else { ++ // Paper end + ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), rconConsoleSource.createCommandSourceStack()); + server.dispatchServerCommand(remoteConsole, serverCommand); ++ } // Paper + // CraftBukkit end + }); ++ // Paper start ++ if (waitableArray[0] != null) { ++ //noinspection unchecked ++ Waitable waitable = waitableArray[0]; ++ try { ++ return waitable.get(); ++ } catch (java.util.concurrent.ExecutionException e) { ++ throw new RuntimeException("Exception processing rcon command " + command, e.getCause()); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // Maintain interrupted state ++ throw new RuntimeException("Interrupted processing rcon command " + command, e); ++ } ++ ++ } ++ // Paper end + return this.rconConsoleSource.getCommandResponse(); + } + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465..59a5f82c9f57d760ba4959a040ce8cbf0f49e4aa 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1,7 +1,9 @@ + package net.minecraft.server.level; + ++import co.aikar.timings.Timing; // Paper + import com.google.common.collect.ImmutableList; + import com.google.common.collect.Iterables; ++import com.google.common.collect.ComparisonChain; // Paper + import com.google.common.collect.Lists; + import com.google.common.collect.Queues; + import com.google.common.collect.Sets; +@@ -552,11 +554,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + private CompletableFuture> scheduleChunkLoad(ChunkPos pos) { + return CompletableFuture.supplyAsync(() -> { +- try { ++ try (Timing ignored = this.level.timings.chunkLoad.startTimingIfSync()) { // Paper + this.level.getProfiler().incrementCounter("chunkLoad"); +- CompoundTag nbttagcompound = this.readChunk(pos); ++ CompoundTag nbttagcompound; // Paper ++ try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings ++ nbttagcompound = this.readChunk(pos); ++ } // Paper end + +- if (nbttagcompound != null) { ++ if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings + boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8); + + if (flag) { +@@ -568,7 +573,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + ChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", pos); +- } ++ }} // Paper + } catch (ReportedException reportedexception) { + Throwable throwable = reportedexception.getCause(); + +@@ -605,7 +610,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return "chunkGenerate " + requiredStatus.getName(); + }); + return completablefuture.thenComposeAsync((either) -> { +- return (CompletableFuture) either.map((list) -> { ++ return either.map((list) -> { // Paper - Shut up. + try { + CompletableFuture> completablefuture1 = requiredStatus.generate(this.level, this.generator, this.structureManager, this.lightEngine, (ichunkaccess) -> { + return this.protoChunkToFullChunk(holder); +@@ -658,6 +663,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkStatus chunkstatus = ChunkHolder.getStatus(playerchunk.getTicketLevel()); + + return !chunkstatus.isOrAfter(ChunkStatus.FULL) ? ChunkHolder.UNLOADED_CHUNK : either.mapLeft((ichunkaccess) -> { ++ try (Timing ignored = level.timings.chunkPostLoad.startTimingIfSync()) { // Paper + ChunkPos chunkcoordintpair = playerchunk.getPos(); + LevelChunk chunk; + +@@ -717,6 +723,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + return chunk; ++ } // Paper + }); + }, (runnable) -> { + ProcessorHandle mailbox = this.mainThreadMailbox; +@@ -1175,6 +1182,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + ChunkMap.TrackedEntity playerchunkmap_entitytracker; + ObjectIterator objectiterator; ++ level.timings.tracker1.startTiming(); // Paper + + for (objectiterator = this.entityMap.values().iterator(); objectiterator.hasNext(); playerchunkmap_entitytracker.serverEntity.sendChanges()) { + playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); +@@ -1192,16 +1200,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + playerchunkmap_entitytracker.lastSectionPos = sectionposition1; + } + } ++ level.timings.tracker1.stopTiming(); // Paper + + if (!list.isEmpty()) { + objectiterator = this.entityMap.values().iterator(); + ++ level.timings.tracker2.startTiming(); // Paper + while (objectiterator.hasNext()) { + playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); + playerchunkmap_entitytracker.updatePlayers(list); + } ++ level.timings.tracker2.stopTiming(); // Paper + } + ++ + } + + protected void broadcast(Entity entity, Packet packet) { +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index ef336645f3bd7a86129ad1dff7e1a15dc93d1e3e..d0b0fdaf5451bcc7f7ac7dab28aa59ef77e6dd97 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -344,11 +344,13 @@ public class ServerChunkCache extends ChunkSource { + } + + gameprofilerfiller.incrementCounter("getChunkCacheMiss"); +- level.timings.syncChunkLoadTimer.startTiming(); // Spigot + CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); + ++ if (!completablefuture.isDone()) { // Paper ++ this.level.timings.syncChunkLoad.startTiming(); // Paper + this.mainThreadProcessor.managedBlock(completablefuture::isDone); +- level.timings.syncChunkLoadTimer.stopTiming(); // Spigot ++ this.level.timings.syncChunkLoad.stopTiming(); // Paper ++ } // Paper + ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { + return ichunkaccess1; + }, (playerchunk_failure) -> { +@@ -536,7 +538,9 @@ public class ServerChunkCache extends ChunkSource { + + public void save(boolean flush) { + this.runDistanceManagerUpdates(); ++ try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings + this.chunkMap.saveAllChunks(flush); ++ } // Paper - Timings + } + + @Override +@@ -573,7 +577,9 @@ public class ServerChunkCache extends ChunkSource { + this.runDistanceManagerUpdates(); + this.level.timings.doChunkMap.stopTiming(); // Spigot + this.level.getProfiler().popPush("chunks"); ++ this.level.timings.chunks.startTiming(); // Paper - timings + this.tickChunks(); ++ this.level.timings.chunks.stopTiming(); // Paper - timings + this.level.timings.doChunkUnload.startTiming(); // Spigot + this.level.getProfiler().popPush("unload"); + this.chunkMap.tick(shouldKeepTicking); +@@ -597,19 +603,24 @@ public class ServerChunkCache extends ChunkSource { + boolean flag2 = level.ticksPerAnimalSpawns != 0L && worlddata.getGameTime() % level.ticksPerAnimalSpawns == 0L; // CraftBukkit + + this.level.getProfiler().push("naturalSpawnCount"); ++ this.level.timings.countNaturalMobs.startTiming(); // Paper - timings + int l = this.distanceManager.getNaturalSpawnChunkCount(); + NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk); ++ this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings + + this.lastSpawnState = spawnercreature_d; + this.level.getProfiler().pop(); + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper ++ this.level.timings.chunkTicks.startTiming(); // Paper + this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + + if (optional.isPresent()) { + this.level.getProfiler().push("broadcast"); ++ this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timings + playerchunk.broadcastChanges((LevelChunk) optional.get()); ++ this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings + this.level.getProfiler().pop(); + Optional optional1 = ((Either) playerchunk.getEntityTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + +@@ -623,25 +634,26 @@ public class ServerChunkCache extends ChunkSource { + NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); + } + +- this.level.timings.doTickTiles.startTiming(); // Spigot ++ //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper + this.level.tickChunk(chunk, k); +- this.level.timings.doTickTiles.stopTiming(); // Spigot ++ //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper + } + } + } + }); ++ this.level.timings.chunkTicks.stopTiming(); // Paper + this.level.getProfiler().push("customSpawners"); + if (flag1) { ++ try (co.aikar.timings.Timing ignored = this.level.timings.miscMobSpawning.startTiming()) { // Paper - timings + this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); ++ } // Paper - timings + } + + this.level.getProfiler().pop(); + this.level.getProfiler().pop(); + } + +- this.level.timings.tracker.startTiming(); // Spigot + this.chunkMap.tick(); +- this.level.timings.tracker.stopTiming(); // Spigot + } + + private void getFullChunk(long pos, Consumer chunkConsumer) { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 34ed8f0d348e7bc2339660ebc6490057ba9ef214..0cc86ca4ea4a2e1b5acc3c0507397eef85dec0c1 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -2,6 +2,8 @@ package net.minecraft.server.level; + + import com.google.common.annotations.VisibleForTesting; + import com.google.common.collect.Iterables; ++import co.aikar.timings.TimingHistory; // Paper ++import co.aikar.timings.Timings; // Paper + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Queues; +@@ -147,7 +149,6 @@ import org.apache.logging.log4j.Logger; + import java.util.logging.Level; + import org.bukkit.Bukkit; + import org.bukkit.WeatherType; +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.event.CraftEventFactory; + import org.bukkit.craftbukkit.util.WorldUUID; + import org.bukkit.event.entity.CreatureSpawnEvent; +@@ -203,10 +204,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // CraftBukkit end + this.blockTicks = new ServerTickList<>(this, (block) -> { + return block == null || block.defaultBlockState().isAir(); +- }, Registry.BLOCK::getKey, this::tickBlock); ++ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings + this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { + return fluidtype == null || fluidtype == Fluids.EMPTY; +- }, Registry.FLUID::getKey, this::tickLiquid); ++ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings + this.navigations = Sets.newHashSet(); + this.blockEvents = new ObjectLinkedOpenHashSet(); + this.tickTime = flag1; +@@ -436,17 +437,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.updateSkyBrightness(); + this.tickTime(); + gameprofilerfiller.popPush("chunkSource"); ++ this.timings.chunkProviderTick.startTiming(); // Paper - timings + this.getChunkSource().tick(shouldKeepTicking); ++ this.timings.chunkProviderTick.stopTiming(); // Paper - timings + gameprofilerfiller.popPush("tickPending"); +- timings.doTickPending.startTiming(); // Spigot ++ timings.scheduledBlocks.startTiming(); // Paper + if (!this.isDebug()) { + this.blockTicks.tick(); + this.liquidTicks.tick(); + } +- timings.doTickPending.stopTiming(); // Spigot ++ timings.scheduledBlocks.stopTiming(); // Paper + + gameprofilerfiller.popPush("raid"); ++ this.timings.raids.startTiming(); // Paper - timings + this.raids.tick(); ++ this.timings.raids.stopTiming(); // Paper - timings + gameprofilerfiller.popPush("blockEvents"); + timings.doSounds.startTiming(); // Spigot + this.runBlockEvents(); +@@ -618,6 +623,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + gameprofilerfiller.popPush("tickBlocks"); ++ timings.chunkTicksBlocks.startTiming(); // Paper + if (randomTickSpeed > 0) { + LevelChunkSection[] achunksection = chunk.getSections(); + int l = achunksection.length; +@@ -649,7 +655,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + } + } +- ++ timings.chunkTicksBlocks.stopTiming(); // Paper + gameprofilerfiller.pop(); + } + +@@ -747,14 +753,22 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (!(entity instanceof Player) && !this.getChunkSource().isEntityTickingChunk(entity)) { + this.updateChunkPos(entity); + } else { ++ ++TimingHistory.entityTicks; // Paper - timings + // Spigot start ++ co.aikar.timings.Timing timer; // Paper + if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { + entity.tickCount++; ++ timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings + entity.inactiveTick(); ++ } finally { timer.stopTiming(); } // Paper + return; + } + // Spigot end +- entity.tickTimer.startTiming(); // Spigot ++ // Paper start- timings ++ TimingHistory.activatedEntityTicks++; ++ timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); ++ try { ++ // Paper end - timings + entity.setPosAndOldPos(entity.getX(), entity.getY(), entity.getZ()); + entity.yRotO = entity.yRot; + entity.xRotO = entity.xRot; +@@ -781,7 +795,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.tickPassenger(entity, entity1); + } + } +- entity.tickTimer.stopTiming(); // Spigot ++ } finally { timer.stopTiming(); } // Paper - timings + + } + } +@@ -859,6 +873,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + if (!flag1) { + org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit ++ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper + if (progressListener != null) { + progressListener.progressStartNoAbort(new TranslatableComponent("menu.savingLevel")); + } +@@ -868,7 +883,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + progressListener.progressStage(new TranslatableComponent("menu.savingChunks")); + } + ++ timings.worldSaveChunks.startTiming(); // Paper + chunkproviderserver.save(flush); ++ timings.worldSaveChunks.stopTiming(); // Paper ++ } // Paper + } + + // CraftBukkit start - moved from MinecraftServer.saveChunks +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 35f3940cebb00ee29da54b1ee148ee931fa11636..466c4322803bedf1fa61be281b954bf94fb8ff02 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -209,6 +209,7 @@ import org.bukkit.inventory.EquipmentSlot; + import org.bukkit.inventory.InventoryView; + import org.bukkit.inventory.SmithingInventory; + import org.bukkit.util.NumberConversions; ++import co.aikar.timings.MinecraftTimings; // Paper + // CraftBukkit end + + public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -291,7 +292,6 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit end + + public void tick() { +- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.startTiming(); // Spigot + this.resetPosition(); + this.player.xo = this.player.getX(); + this.player.yo = this.player.getY(); +@@ -367,7 +367,6 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 + this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling")); + } +- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.stopTiming(); // Spigot + + } + +@@ -1915,7 +1914,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit end + + private void handleCommand(String input) { +- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot ++ MinecraftTimings.playerCommandTimer.startTiming(); // Paper + // CraftBukkit start - whole method + if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot + this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + input); +@@ -1926,7 +1925,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.craftServer.getPluginManager().callEvent(event); + + if (event.isCancelled()) { +- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot ++ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper + return; + } + +@@ -1939,7 +1938,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); + return; + } finally { +- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot ++ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper + } + // this.minecraftServer.getCommandDispatcher().a(this.player.getCommandListener(), s); + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 28121e2fee9d862057042261d25360f0d4ee4530..88af57699d7f9e45ad1366243049e4f3565703ff 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1,5 +1,6 @@ + package net.minecraft.server.players; + ++import co.aikar.timings.MinecraftTimings; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; +@@ -1018,10 +1019,11 @@ public abstract class PlayerList { + } + + public void saveAll() { ++ MinecraftTimings.savePlayers.startTiming(); // Paper + for (int i = 0; i < this.players.size(); ++i) { + this.save((ServerPlayer) this.players.get(i)); + } +- ++ MinecraftTimings.savePlayers.stopTiming(); // Paper + } + + public UserWhiteList getWhiteList() { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index b633f6b3a36b793e6dbc1b8b554bfba74c719570..2a7f587e19fcdd6d01b360d6b47d9eadd9df92cc 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -115,7 +115,6 @@ import org.bukkit.craftbukkit.event.CraftPortalEvent; + import org.bukkit.entity.Hanging; + import org.bukkit.entity.LivingEntity; + import org.bukkit.entity.Vehicle; +-import org.spigotmc.CustomTimingsHandler; // Spigot + import org.bukkit.event.entity.EntityCombustByEntityEvent; + import org.bukkit.event.hanging.HangingBreakByEntityEvent; + import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; +@@ -247,7 +246,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only + public boolean forceExplosionKnockback; // SPIGOT-949 + public boolean persistentInvisibility = false; +- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot + // Spigot start + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; +@@ -616,7 +614,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public void move(MoverType type, Vec3 movement) { +- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot + if (this.noPhysics) { + this.setBoundingBox(this.getBoundingBox().move(movement)); + this.setLocationFromBoundingbox(); +@@ -752,7 +749,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + this.level.getProfiler().pop(); + } +- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot + } + + protected BlockPos getOnPos() { +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index 2cb86de4bfc87a709f0cfa2c4e550d8e7928a3f0..e3d92d1d35911b2960a7ca82bd4f324d285d0533 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -281,17 +281,27 @@ public class EntityType { + return Registry.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(id)); + } + +- public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet immutableset, EntityDimensions entitysize, int i, int j) { +- this.factory = factory; +- this.category = spawnGroup; +- this.canSpawnFarFromPlayer = spawnableFarFromPlayer; +- this.serialize = saveable; +- this.summon = summonable; +- this.fireImmune = fireImmune; ++ public final String id; ++ public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet immutableset, EntityDimensions entitysize, int i, int j) { this(factory, spawnGroup, saveable, summonable, fireImmune, spawnableFarFromPlayer, immutableset, entitysize, i, j, "custom"); } // Paper - old signature ++ public EntityType(EntityType.EntityFactory entitytypes_b, MobCategory enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntityDimensions entitysize, int i, int j, String id) { // Paper - add id ++ this.factory = entitytypes_b; ++ this.category = enumcreaturetype; ++ this.canSpawnFarFromPlayer = flag3; ++ this.serialize = flag; ++ this.summon = flag1; ++ this.fireImmune = flag2; + this.immuneTo = immutableset; + this.dimensions = entitysize; + this.clientTrackingRange = i; + this.updateInterval = j; ++ ++ // Paper start - timings ++ this.id = id; ++ this.tickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "tick"); ++ this.inactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "inactiveTick"); ++ this.passengerTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerTick"); ++ this.passengerInactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerInactiveTick"); ++ // Paper end + } + + @Nullable +@@ -512,6 +522,12 @@ public class EntityType { + return this.updateInterval; + } + ++ // Paper start - timings ++ public final co.aikar.timings.Timing tickTimer; ++ public final co.aikar.timings.Timing inactiveTickTimer; ++ public final co.aikar.timings.Timing passengerTickTimer; ++ public final co.aikar.timings.Timing passengerInactiveTickTimer; ++ // Paper end + public boolean trackDeltas() { + return this != EntityType.PLAYER && this != EntityType.LLAMA_SPIT && this != EntityType.WITHER && this != EntityType.BAT && this != EntityType.ITEM_FRAME && this != EntityType.LEASH_KNOT && this != EntityType.PAINTING && this != EntityType.END_CRYSTAL && this != EntityType.EVOKER_FANGS; + } +@@ -599,7 +615,7 @@ public class EntityType { + Util.fetchChoiceType(References.ENTITY_TREE, id); + } + +- return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval); ++ return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval, id); // Paper - add id + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 9e5dde73bd65bf4e51352c628fba024c36e29ef1..e5f8cee6726ea9a90c540bb10fd8594a35bb5e40 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -132,7 +132,7 @@ import org.bukkit.event.entity.EntityTeleportEvent; + import org.bukkit.event.player.PlayerItemConsumeEvent; + // CraftBukkit end + +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper + + public abstract class LivingEntity extends Entity { + +@@ -2455,7 +2455,6 @@ public abstract class LivingEntity extends Entity { + + @Override + public void tick() { +- SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot + super.tick(); + this.updatingUsingItem(); + this.updateSwimAmount(); +@@ -2504,9 +2503,7 @@ public abstract class LivingEntity extends Entity { + } + } + +- SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot + this.aiStep(); +- SpigotTimings.timerEntityTickRest.startTiming(); // Spigot + double d0 = this.getX() - this.xo; + double d1 = this.getZ() - this.zo; + float f = (float) (d0 * d0 + d1 * d1); +@@ -2586,8 +2583,6 @@ public abstract class LivingEntity extends Entity { + if (this.isSleeping()) { + this.xRot = 0.0F; + } +- +- SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot + } + + public void detectEquipmentUpdates() { +@@ -2769,7 +2764,6 @@ public abstract class LivingEntity extends Entity { + + this.setDeltaMovement(d4, d5, d6); + this.level.getProfiler().push("ai"); +- SpigotTimings.timerEntityAI.startTiming(); // Spigot + if (this.isImmobile()) { + this.jumping = false; + this.xxa = 0.0F; +@@ -2779,7 +2773,6 @@ public abstract class LivingEntity extends Entity { + this.serverAiStep(); + this.level.getProfiler().pop(); + } +- SpigotTimings.timerEntityAI.stopTiming(); // Spigot + + this.level.getProfiler().pop(); + this.level.getProfiler().push("jump"); +@@ -2814,9 +2807,9 @@ public abstract class LivingEntity extends Entity { + this.updateFallFlying(); + AABB axisalignedbb = this.getBoundingBox(); + +- SpigotTimings.timerEntityAIMove.startTiming(); // Spigot ++ // SpigotTimings.timerEntityAIMove.startTiming(); // Spigot // Paper + this.travel(new Vec3((double) this.xxa, (double) this.yya, (double) this.zza)); +- SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot ++ // SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot // Paper + this.level.getProfiler().pop(); + this.level.getProfiler().push("push"); + if (this.autoSpinAttackTicks > 0) { +@@ -2824,9 +2817,7 @@ public abstract class LivingEntity extends Entity { + this.checkAutoSpinAttack(axisalignedbb, this.getBoundingBox()); + } + +- SpigotTimings.timerEntityAICollision.startTiming(); // Spigot + this.pushEntities(); +- SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot + this.level.getProfiler().pop(); + if (!this.level.isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { + this.hurt(DamageSource.DROWN, 1.0F); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 5cc4c2668df72f83fb1526f4586b71d2ae0103dc..c153df1f4dea3dc0ae744bde01e334b3bd3b50af 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -70,7 +70,6 @@ import org.apache.logging.log4j.Logger; + import java.util.HashMap; + import java.util.Map; + import org.bukkit.Bukkit; +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.block.CapturedBlockState; +@@ -132,7 +131,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper + +- public final SpigotTimings.WorldTimingsHandler timings; // Spigot ++ public final co.aikar.timings.WorldTimingsHandler timings; // Paper + public static BlockPos lastPhysicsProblem; // Spigot + private org.spigotmc.TickLimiter entityLimiter; + private org.spigotmc.TickLimiter tileLimiter; +@@ -217,7 +216,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) {} + }); + // CraftBukkit end +- timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings ++ timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings + this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + } +@@ -797,15 +796,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + + timings.tileEntityPending.stopTiming(); // Spigot ++ co.aikar.timings.TimingHistory.tileEntityTicks += this.tickableBlockEntities.size(); // Paper + gameprofilerfiller.pop(); + spigotConfig.currentPrimedTnt = 0; // Spigot + } + + public void guardEntityTick(Consumer tickConsumer, Entity entity) { + try { +- SpigotTimings.tickEntityTimer.startTiming(); // Spigot + tickConsumer.accept(entity); +- SpigotTimings.tickEntityTimer.stopTiming(); // Spigot + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); +diff --git a/src/main/java/net/minecraft/world/level/ServerTickList.java b/src/main/java/net/minecraft/world/level/ServerTickList.java +index 0519d5adf392dd46b4a93c5c1b977c8355163c2e..10ac1ba0a3d192486f22c2127d5bc30353f0edb6 100644 +--- a/src/main/java/net/minecraft/world/level/ServerTickList.java ++++ b/src/main/java/net/minecraft/world/level/ServerTickList.java +@@ -38,12 +38,17 @@ public class ServerTickList implements TickList { + private final List> alreadyTicked = Lists.newArrayList(); + private final Consumer> ticker; + +- public ServerTickList(ServerLevel world, Predicate invalidObjPredicate, Function idToName, Consumer> consumer) { +- this.ignore = invalidObjPredicate; +- this.toId = idToName; +- this.level = world; ++ public ServerTickList(ServerLevel worldserver, Predicate predicate, Function function, Consumer> consumer, String timingsType) { // Paper ++ this.ignore = predicate; ++ this.toId = function; ++ this.level = worldserver; + this.ticker = consumer; ++ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Cleanup"); ++ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Ticking"); + } ++ private final co.aikar.timings.Timing timingCleanup; // Paper ++ private final co.aikar.timings.Timing timingTicking; // Paper ++ // Paper end + + public void tick() { + int i = this.tickNextTickList.size(); +@@ -66,6 +71,7 @@ public class ServerTickList implements TickList { + + this.level.getProfiler().push("cleaning"); + ++ this.timingCleanup.startTiming(); // Paper + TickNextTickData nextticklistentry; + + while (i > 0 && iterator.hasNext()) { +@@ -81,7 +87,9 @@ public class ServerTickList implements TickList { + --i; + } + } ++ this.timingCleanup.stopTiming(); // Paper + ++ this.timingTicking.startTiming(); // Paper + this.level.getProfiler().popPush("ticking"); + + while ((nextticklistentry = (TickNextTickData) this.currentlyTicking.poll()) != null) { +@@ -101,6 +109,7 @@ public class ServerTickList implements TickList { + } + } + ++ this.timingTicking.stopTiming(); // Paper + this.level.getProfiler().pop(); + this.alreadyTicked.clear(); + this.currentlyTicking.clear(); +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 73a271a1fccd6f82dac8d33c0d378f0d84ceb5e5..2ae786b8fc6da19ca2a40252b0606f9e06d31ded 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -61,6 +61,15 @@ public class Block extends BlockBehaviour implements ItemLike { + }); + protected final StateDefinition stateDefinition; + private BlockState defaultBlockState; ++ // Paper start ++ public co.aikar.timings.Timing timing; ++ public co.aikar.timings.Timing getTiming() { ++ if (timing == null) { ++ timing = co.aikar.timings.MinecraftTimings.getBlockTiming(this); ++ } ++ return timing; ++ } ++ // Paper end + @Nullable + private String descriptionId; + @Nullable +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index bb60c9da9f3ba0d5c5bad22512675ccb841a60e5..d445a1b7b7605eed66923789c5d8e2199c31c5ac 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -23,10 +23,12 @@ import org.bukkit.inventory.InventoryHolder; + // CraftBukkit end + + import org.spigotmc.CustomTimingsHandler; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper ++import co.aikar.timings.Timing; // Paper + + public abstract class BlockEntity implements net.minecraft.server.KeyedObject { // Paper + +- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot ++ public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper + // CraftBukkit start - data containers + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); + public CraftPersistentDataContainer persistentDataContainer; +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 00ce55c17980da87a3834f952475a766543506b0..f30793b81dfd9018b4879d655c7c18a9f9c25267 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -732,6 +732,7 @@ public class LevelChunk implements ChunkAccess { + server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(this.bukkitChunk, this.needsDecoration)); + + if (this.needsDecoration) { ++ try (co.aikar.timings.Timing ignored = this.world.timings.chunkLoadPopulate.startTiming()) { // Paper + this.needsDecoration = false; + java.util.Random random = new java.util.Random(); + random.setSeed(world.getSeed()); +@@ -751,6 +752,7 @@ public class LevelChunk implements ChunkAccess { + } + } + server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); ++ } // Paper + } + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 7e13a438bd80ab5452eacf107d418c42c2e5c727..0efaf4d0f58bcf38b427e76bf09b96e354294159 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.chunk.storage; + ++import co.aikar.timings.Timings; + import com.google.common.collect.Maps; + import it.unimi.dsi.fastutil.longs.LongOpenHashSet; + import it.unimi.dsi.fastutil.longs.LongSet; +@@ -446,7 +447,6 @@ public class ChunkSerializer { + private static void postLoadChunk(CompoundTag tag, LevelChunk chunk) { + ListTag nbttaglist = tag.getList("Entities", 10); + Level world = chunk.getLevel(); +- world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot + + for (int i = 0; i < nbttaglist.size(); ++i) { + CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); +@@ -458,8 +458,6 @@ public class ChunkSerializer { + chunk.setLastSaveHadEntities(true); + } + +- world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot +- world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot + ListTag nbttaglist1 = tag.getList("TileEntities", 10); + + for (int j = 0; j < nbttaglist1.size(); ++j) { +@@ -477,8 +475,6 @@ public class ChunkSerializer { + } + } + } +- world.timings.syncChunkLoadTileEntitiesTimer.stopTiming(); // Spigot +- + } + + private static CompoundTag packStructureData(ChunkPos pos, Map, StructureStart> structureStarts, Map, LongSet> structureReferences) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 328d1e2b128b62f24917719c79823c9fb64a0dcf..c4cf1394fe4c2782b1fea8b3653a817157d857eb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2073,12 +2073,31 @@ public final class CraftServer implements Server { + private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() + { + ++ @Deprecated + @Override + public YamlConfiguration getConfig() + { + return org.spigotmc.SpigotConfig.config; + } + ++ @Override ++ public YamlConfiguration getBukkitConfig() ++ { ++ return configuration; ++ } ++ ++ @Override ++ public YamlConfiguration getSpigotConfig() ++ { ++ return org.spigotmc.SpigotConfig.config; ++ } ++ ++ @Override ++ public YamlConfiguration getPaperConfig() ++ { ++ return com.destroystokyo.paper.PaperConfig.config; ++ } ++ + @Override + public void restart() { + org.spigotmc.RestartCommand.restart(); +diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +deleted file mode 100644 +index 56b644e272ddad0e5410061e0a202daaebb734b8..0000000000000000000000000000000000000000 +--- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java ++++ /dev/null +@@ -1,163 +0,0 @@ +-package org.bukkit.craftbukkit; +- +-import java.util.HashMap; +-import net.minecraft.world.entity.Entity; +-import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.storage.PrimaryLevelData; +-import org.bukkit.craftbukkit.scheduler.CraftTask; +-import org.bukkit.plugin.java.JavaPluginLoader; +-import org.bukkit.scheduler.BukkitTask; +-import org.spigotmc.CustomTimingsHandler; +- +-public class SpigotTimings { +- +- public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); +- public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); +- public static final CustomTimingsHandler commandFunctionsTimer = new CustomTimingsHandler("Command Functions"); +- public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler"); +- public static final CustomTimingsHandler playerConnectionTimer = new CustomTimingsHandler("** PlayerConnection"); +- public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); +- public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); +- public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update"); +- public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command"); +- public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save"); +- +- public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); +- public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); +- public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); +- public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); +- +- public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); +- public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); +- public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); +- public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); +- public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); +- +- public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue"); +- public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer); +- +- public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); +- +- public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); +- public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); +- +- public static final HashMap entityTypeTimingMap = new HashMap(); +- public static final HashMap tileEntityTypeTimingMap = new HashMap(); +- public static final HashMap pluginTaskTimingMap = new HashMap(); +- +- /** +- * Gets a timer associated with a plugins tasks. +- * @param task +- * @param period +- * @return +- */ +- public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { +- if (!task.isSync()) { +- return null; +- } +- String plugin; +- final CraftTask ctask = (CraftTask) task; +- +- if (task.getOwner() != null) { +- plugin = task.getOwner().getDescription().getFullName(); +- } else { +- plugin = "Unknown"; +- } +- String taskname = ctask.getTaskName(); +- +- String name = "Task: " + plugin + " Runnable: " + taskname; +- if (period > 0) { +- name += "(interval:" + period + ")"; +- } else { +- name += "(Single)"; +- } +- CustomTimingsHandler result = pluginTaskTimingMap.get(name); +- if (result == null) { +- result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); +- pluginTaskTimingMap.put(name, result); +- } +- return result; +- } +- +- /** +- * Get a named timer for the specified entity type to track type specific timings. +- * @param entity +- * @return +- */ +- public static CustomTimingsHandler getEntityTimings(Entity entity) { +- String entityType = entity.getClass().getName(); +- CustomTimingsHandler result = entityTypeTimingMap.get(entityType); +- if (result == null) { +- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), activatedEntityTimer); +- entityTypeTimingMap.put(entityType, result); +- } +- return result; +- } +- +- /** +- * Get a named timer for the specified tile entity type to track type specific timings. +- * @param entity +- * @return +- */ +- public static CustomTimingsHandler getTileEntityTimings(BlockEntity entity) { +- String entityType = entity.getClass().getName(); +- CustomTimingsHandler result = tileEntityTypeTimingMap.get(entityType); +- if (result == null) { +- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), tickTileEntityTimer); +- tileEntityTypeTimingMap.put(entityType, result); +- } +- return result; +- } +- +- /** +- * Set of timers per world, to track world specific timings. +- */ +- public static class WorldTimingsHandler { +- public final CustomTimingsHandler mobSpawn; +- public final CustomTimingsHandler doChunkUnload; +- public final CustomTimingsHandler doTickPending; +- public final CustomTimingsHandler doTickTiles; +- public final CustomTimingsHandler doChunkMap; +- public final CustomTimingsHandler doSounds; +- public final CustomTimingsHandler entityTick; +- public final CustomTimingsHandler tileEntityTick; +- public final CustomTimingsHandler tileEntityPending; +- public final CustomTimingsHandler tracker; +- public final CustomTimingsHandler doTick; +- public final CustomTimingsHandler tickEntities; +- +- public final CustomTimingsHandler syncChunkLoadTimer; +- public final CustomTimingsHandler syncChunkLoadStructuresTimer; +- public final CustomTimingsHandler syncChunkLoadEntitiesTimer; +- public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer; +- public final CustomTimingsHandler syncChunkLoadTileTicksTimer; +- public final CustomTimingsHandler syncChunkLoadPostTimer; +- +- public WorldTimingsHandler(Level server) { +- String name = ((PrimaryLevelData) server.levelData).getLevelName() + " - "; +- +- mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); +- doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); +- doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); +- doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); +- doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); +- doSounds = new CustomTimingsHandler("** " + name + "doSounds"); +- entityTick = new CustomTimingsHandler("** " + name + "entityTick"); +- tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); +- tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending"); +- +- syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); +- syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); +- syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); +- syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); +- syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); +- syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); +- +- +- tracker = new CustomTimingsHandler(name + "tracker"); +- doTick = new CustomTimingsHandler(name + "doTick"); +- tickEntities = new CustomTimingsHandler(name + "tickEntities"); +- } +- } +-} +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 8fbf6c56d8820f3fa86e70a2636c0b58043232c3..61e2d92471d1498eb97d42dc642605a2e00e6089 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1806,6 +1806,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + packet.components = components; + getHandle().connection.send(packet); + } ++ ++ // Paper start ++ @Override ++ public int getPing() ++ { ++ return getHandle().latency; ++ } ++ // Paper end + }; + + public Player.Spigot spigot() +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 4bf48f77f3f7cd62a91590543f5af441c8268029..ffe9cc1011226d604dc5499e7692e9a9a5132b72 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.scheduler; + ++import co.aikar.timings.MinecraftTimings; // Paper + import com.google.common.util.concurrent.ThreadFactoryBuilder; + import java.util.ArrayList; + import java.util.Comparator; +@@ -179,7 +180,8 @@ public class CraftScheduler implements BukkitScheduler { + } + + public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { +- final CraftTask task = new CraftTask(run, nextId(), taskName); ++ final CraftTask task = new CraftTask(run, nextId(), "Internal - " + (taskName != null ? taskName : "Unknown")); ++ task.internal = true; + return handle(task, delay); + } + +@@ -260,7 +262,7 @@ public class CraftScheduler implements BukkitScheduler { + } + return false; + } +- }); ++ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer();}}; // Paper + handle(task, 0L); + for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { + if (taskPending == task) { +@@ -295,7 +297,7 @@ public class CraftScheduler implements BukkitScheduler { + } + } + } +- }); ++ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer(plugin);}}; // Paper + handle(task, 0L); + for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { + if (taskPending == task) { +@@ -402,9 +404,7 @@ public class CraftScheduler implements BukkitScheduler { + if (task.isSync()) { + currentTask = task; + try { +- task.timings.startTiming(); // Spigot + task.run(); +- task.timings.stopTiming(); // Spigot + } catch (final Throwable throwable) { + // Paper start + String msg = String.format( +@@ -438,8 +438,10 @@ public class CraftScheduler implements BukkitScheduler { + runners.remove(task.getTaskId()); + } + } ++ MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); + pending.addAll(temp); + temp.clear(); ++ MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); + debugHead = debugHead.getNextHead(currentTick); + } + +@@ -472,6 +474,7 @@ public class CraftScheduler implements BukkitScheduler { + } + + private void parsePending() { ++ MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); + CraftTask head = this.head; + CraftTask task = head.getNext(); + CraftTask lastTask = head; +@@ -490,6 +493,7 @@ public class CraftScheduler implements BukkitScheduler { + task.setNext(null); + } + this.head = lastTask; ++ MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); + } + + private boolean isReady(final int currentTick) { +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +index 09aa6809c5400ce8548ac902908b750ce7c964ec..3c96807e97657502849093e4371e9fef3584a346 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +@@ -1,12 +1,15 @@ + package org.bukkit.craftbukkit.scheduler; + + import java.util.function.Consumer; ++ ++import co.aikar.timings.NullTimingHandler; + import org.bukkit.Bukkit; + import org.bukkit.plugin.Plugin; + import org.bukkit.scheduler.BukkitTask; + +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.spigotmc.CustomTimingsHandler; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper ++import co.aikar.timings.Timing; // Paper + + public class CraftTask implements BukkitTask, Runnable { // Spigot + +@@ -26,12 +29,12 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + */ + private volatile long period; + private long nextRun; +- private final Runnable rTask; +- private final Consumer cTask; ++ public final Runnable rTask; // Paper ++ public final Consumer cTask; // Paper ++ public Timing timings; // Paper + private final Plugin plugin; + private final int id; + +- final CustomTimingsHandler timings; // Spigot + CraftTask() { + this(null, null, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); + } +@@ -51,7 +54,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + this.id = id; + this.period = CraftTask.NO_REPEATING; + this.taskName = taskName; +- this.timings = null; // Will be changed in later patch ++ this.timings = MinecraftTimings.getInternalTaskName(taskName); + } + // Paper end + +@@ -72,7 +75,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + } + this.id = id; + this.period = period; +- this.timings = this.isSync() ? SpigotTimings.getPluginTaskTimings(this, period) : null; // Spigot ++ timings = task != null ? MinecraftTimings.getPluginTaskTimings(this, period) : NullTimingHandler.NULL; // Paper + } + + @Override +@@ -92,11 +95,13 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + + @Override + public void run() { ++ try (Timing ignored = timings.startTiming()) { // Paper + if (rTask != null) { + rTask.run(); + } else { + cTask.accept(this); + } ++ } // Paper + } + + long getPeriod() { +@@ -123,7 +128,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + this.next = next; + } + +- Class getTaskClass() { ++ public Class getTaskClass() { + return (rTask != null) ? rTask.getClass() : ((cTask != null) ? cTask.getClass() : null); + } + +@@ -147,9 +152,4 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + return true; + } + +- // Spigot start +- public String getTaskName() { +- return (getTaskClass() == null) ? "Unknown" : getTaskClass().getName(); +- } +- // Spigot end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java +index e52ef47b783785dc214746b678e7b549aea9a274..3d90b3426873a3528af14f7f1ab0adae0027da2e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java +@@ -5,6 +5,7 @@ import org.bukkit.util.CachedServerIcon; + public class CraftIconCache implements CachedServerIcon { + public final String value; + ++ public String getData() { return value; } // Paper + public CraftIconCache(final String value) { + this.value = value; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index ec3d663886eb134eb9ecc87e7517a73bcfb9ec02..ef7715774fbdc4c42b217d8192784e09a43fe66f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -156,6 +156,12 @@ public final class CraftMagicNumbers implements UnsafeValues { + return CraftNamespacedKey.toMinecraft(mat.getKey()); + } + // ======================================================================== ++ // Paper start ++ @Override ++ public void reportTimings() { ++ co.aikar.timings.TimingsExport.reportTimings(); ++ } ++ // Paper end + + public static byte toLegacyData(BlockState data) { + return CraftLegacy.toLegacyData(data); +@@ -330,6 +336,13 @@ public final class CraftMagicNumbers implements UnsafeValues { + return clazz; + } + ++ // Paper start ++ @Override ++ public String getTimingsServerName() { ++ return com.destroystokyo.paper.PaperConfig.timingsServerName; ++ } ++ // Paper end ++ + /** + * This helper class represents the different NBT Tags. + *

    +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index ac6fc546931f7884952058b42e7e3fab3ce42998..9bb35ec64e1538aabec9ff7831706c4717239449 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -29,7 +29,7 @@ import net.minecraft.world.entity.raid.Raider; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.phys.AABB; +-import org.bukkit.craftbukkit.SpigotTimings; ++import co.aikar.timings.MinecraftTimings; + + public class ActivationRange + { +@@ -73,8 +73,8 @@ public class ActivationRange + /** + * These entities are excluded from Activation range checks. + * +- * @param entity +- * @param config ++ * @param entity Entity to initialize ++ * @param config Spigot config to determine ranges + * @return boolean If it should always tick. + */ + public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) +@@ -109,7 +109,7 @@ public class ActivationRange + */ + public static void activateEntities(Level world) + { +- SpigotTimings.entityActivationCheckTimer.startTiming(); ++ MinecraftTimings.entityActivationCheckTimer.startTiming(); + final int miscActivationRange = world.spigotConfig.miscActivationRange; + final int raiderActivationRange = world.spigotConfig.raiderActivationRange; + final int animalActivationRange = world.spigotConfig.animalActivationRange; +@@ -146,7 +146,7 @@ public class ActivationRange + } + } + } +- SpigotTimings.entityActivationCheckTimer.stopTiming(); ++ MinecraftTimings.entityActivationCheckTimer.stopTiming(); + } + + /** +@@ -243,10 +243,8 @@ public class ActivationRange + */ + public static boolean checkIfActive(Entity entity) + { +- SpigotTimings.checkIfActiveTimer.startTiming(); + // Never safe to skip fireworks or entities not yet added to chunk + if ( !entity.inChunk || entity instanceof FireworkRocketEntity ) { +- SpigotTimings.checkIfActiveTimer.stopTiming(); + return true; + } + +@@ -270,7 +268,6 @@ public class ActivationRange + { + isActive = false; + } +- SpigotTimings.checkIfActiveTimer.stopTiming(); + return isActive; + } + } diff --git a/patches/server-remapped/0010-Adventure.patch b/patches/server-remapped/0010-Adventure.patch new file mode 100644 index 0000000000..4ad53cc5f6 --- /dev/null +++ b/patches/server-remapped/0010-Adventure.patch @@ -0,0 +1,3238 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Riley Park +Date: Fri, 29 Jan 2021 17:54:03 +0100 +Subject: [PATCH] Adventure + +Co-authored-by: zml +Co-authored-by: Jake Potrebic + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7..429b74474ced04d8dd8f038b8590b8dfe178bf4d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -217,4 +217,9 @@ public class PaperConfig { + " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + + " - Server Name: " + timingsServerName); + } ++ ++ public static boolean useDisplayNameInQuit = false; ++ private static void useDisplayNameInQuit() { ++ useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); ++ } + } +diff --git a/src/main/java/io/papermc/paper/adventure/AdventureComponent.java b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4b4cec054ad0146773b722c7e3708f988aeeb76d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java +@@ -0,0 +1,76 @@ ++package io.papermc.paper.adventure; ++ ++import com.google.gson.JsonElement; ++import com.google.gson.JsonSerializationContext; ++import com.google.gson.JsonSerializer; ++import java.lang.reflect.Type; ++import java.util.List; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.TextComponent; ++import net.minecraft.network.chat.MutableComponent; ++import net.minecraft.network.chat.Style; ++import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++ ++public final class AdventureComponent implements net.minecraft.network.chat.Component { ++ final Component wrapped; ++ private @MonotonicNonNull net.minecraft.network.chat.Component converted; ++ ++ public AdventureComponent(final Component wrapped) { ++ this.wrapped = wrapped; ++ } ++ ++ public net.minecraft.network.chat.Component deepConverted() { ++ net.minecraft.network.chat.Component converted = this.converted; ++ if (converted == null) { ++ converted = PaperAdventure.WRAPPER_AWARE_SERIALIZER.serialize(this.wrapped); ++ this.converted = converted; ++ } ++ return converted; ++ } ++ ++ public @Nullable net.minecraft.network.chat.Component deepConvertedIfPresent() { ++ return this.converted; ++ } ++ ++ @Override ++ public Style getStyle() { ++ return this.deepConverted().getStyle(); ++ } ++ ++ @Override ++ public String getContents() { ++ if (this.wrapped instanceof TextComponent) { ++ return ((TextComponent) this.wrapped).content(); ++ } else { ++ return this.deepConverted().getContents(); ++ } ++ } ++ ++ @Override ++ public String getString() { ++ return PaperAdventure.PLAIN.serialize(this.wrapped); ++ } ++ ++ @Override ++ public List getSiblings() { ++ return this.deepConverted().getSiblings(); ++ } ++ ++ @Override ++ public MutableComponent plainCopy() { ++ return this.deepConverted().plainCopy(); ++ } ++ ++ @Override ++ public MutableComponent copy() { ++ return this.deepConverted().copy(); ++ } ++ ++ public static class Serializer implements JsonSerializer { ++ @Override ++ public JsonElement serialize(final AdventureComponent src, final Type type, final JsonSerializationContext context) { ++ return PaperAdventure.GSON.serializer().toJsonTree(src.wrapped, Component.class); ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a29b6aaafd529e56a83dd96c32211f21e4aad348 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +@@ -0,0 +1,214 @@ ++package io.papermc.paper.adventure; ++ ++import io.papermc.paper.chat.ChatRenderer; ++import io.papermc.paper.event.player.AbstractChatEvent; ++import io.papermc.paper.event.player.AsyncChatEvent; ++import io.papermc.paper.event.player.ChatEvent; ++import java.util.Set; ++import java.util.concurrent.ExecutionException; ++import java.util.function.Consumer; ++import java.util.regex.Pattern; ++ ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.audience.MessageType; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.TextReplacementConfig; ++import net.kyori.adventure.text.event.ClickEvent; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.LazyPlayerSet; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.AsyncPlayerChatEvent; ++import org.bukkit.event.player.PlayerChatEvent; ++ ++public final class ChatProcessor { ++ // <-- copied from adventure-text-serializer-legacy ++ private static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?"); ++ private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("^[a-z][a-z0-9+\\-.]*:"); ++ private static final TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder() ++ .match(DEFAULT_URL_PATTERN) ++ .replacement(url -> { ++ String clickUrl = url.content(); ++ if (!URL_SCHEME_PATTERN.matcher(clickUrl).find()) { ++ clickUrl = "http://" + clickUrl; ++ } ++ return url.clickEvent(ClickEvent.openUrl(clickUrl)); ++ }) ++ .build(); ++ // copied from adventure-text-serializer-legacy --> ++ final MinecraftServer server; ++ final ServerPlayer player; ++ final String message; ++ final boolean async; ++ final Component originalMessage; ++ ++ public ChatProcessor(final MinecraftServer server, final ServerPlayer player, final String message, final boolean async) { ++ this.server = server; ++ this.player = player; ++ this.message = message; ++ this.async = async; ++ this.originalMessage = Component.text(message); ++ } ++ ++ @SuppressWarnings({"CodeBlock2Expr", "deprecated"}) ++ public void process() { ++ this.processingLegacyFirst( ++ // continuing from AsyncPlayerChatEvent (without PlayerChatEvent) ++ event -> { ++ this.processModern( ++ legacyRenderer(event.getFormat()), ++ event.getRecipients(), ++ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), ++ event.isCancelled() ++ ); ++ }, ++ // continuing from AsyncPlayerChatEvent and PlayerChatEvent ++ event -> { ++ this.processModern( ++ legacyRenderer(event.getFormat()), ++ event.getRecipients(), ++ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), ++ event.isCancelled() ++ ); ++ }, ++ // no legacy events called, all nice and fresh! ++ () -> { ++ this.processModern( ++ ChatRenderer.defaultRenderer(), ++ new LazyPlayerSet(this.server), ++ Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG), ++ false ++ ); ++ } ++ ); ++ } ++ ++ @SuppressWarnings("deprecation") ++ private void processingLegacyFirst( ++ final Consumer continueAfterAsync, ++ final Consumer continueAfterAsyncAndSync, ++ final Runnable modernOnly ++ ) { ++ final boolean listenersOnAsyncEvent = anyListeners(AsyncPlayerChatEvent.getHandlerList()); ++ final boolean listenersOnSyncEvent = anyListeners(PlayerChatEvent.getHandlerList()); ++ if (listenersOnAsyncEvent || listenersOnSyncEvent) { ++ final CraftPlayer player = this.player.getBukkitEntity(); ++ final AsyncPlayerChatEvent ae = new AsyncPlayerChatEvent(this.async, player, this.message, new LazyPlayerSet(this.server)); ++ post(ae); ++ if (listenersOnSyncEvent) { ++ final PlayerChatEvent se = new PlayerChatEvent(player, ae.getMessage(), ae.getFormat(), ae.getRecipients()); ++ se.setCancelled(ae.isCancelled()); // propagate cancelled state ++ this.queueIfAsyncOrRunImmediately(new Waitable() { ++ @Override ++ protected Void evaluate() { ++ post(se); ++ return null; ++ } ++ }); ++ continueAfterAsyncAndSync.accept(se); ++ } else { ++ continueAfterAsync.accept(ae); ++ } ++ } else { ++ modernOnly.run(); ++ } ++ } ++ ++ private void processModern(final ChatRenderer renderer, final Set recipients, final Component message, final boolean cancelled) { ++ final AsyncChatEvent ae = this.createAsync(renderer, recipients, new LazyChatAudienceSet(), message); ++ ae.setCancelled(cancelled); // propagate cancelled state ++ post(ae); ++ final boolean listenersOnSyncEvent = anyListeners(ChatEvent.getHandlerList()); ++ if (listenersOnSyncEvent) { ++ this.continueWithSyncFromWhereAsyncLeftOff(ae); ++ } else { ++ this.complete(ae); ++ } ++ } ++ ++ private void continueWithSyncFromWhereAsyncLeftOff(final AsyncChatEvent ae) { ++ this.queueIfAsyncOrRunImmediately(new Waitable() { ++ @Override ++ protected Void evaluate() { ++ final ChatEvent se = ChatProcessor.this.createSync(ae.renderer(), ae.recipients(), ae.viewers(), ae.message()); ++ se.setCancelled(ae.isCancelled()); // propagate cancelled state ++ post(se); ++ ChatProcessor.this.complete(se); ++ return null; ++ } ++ }); ++ } ++ ++ private void complete(final AbstractChatEvent event) { ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ final CraftPlayer player = this.player.getBukkitEntity(); ++ final Component displayName = displayName(player); ++ final Component message = event.message(); ++ final ChatRenderer renderer = event.renderer(); ++ ++ final Set viewers = event.viewers(); ++ final Set recipients = event.recipients(); ++ if (viewers instanceof LazyChatAudienceSet && recipients instanceof LazyPlayerSet && ++ (!((LazyChatAudienceSet) viewers).isLazy() || ((LazyPlayerSet) recipients).isLazy())) { ++ for (final Audience viewer : viewers) { ++ viewer.sendMessage(player, renderer.render(player, displayName, message, viewer), MessageType.CHAT); ++ } ++ } else { ++ this.server.console.sendMessage(player, renderer.render(player, displayName, message, this.server.console), MessageType.CHAT); ++ for (final Player recipient : recipients) { ++ recipient.sendMessage(player, renderer.render(player, displayName, message, recipient), MessageType.CHAT); ++ } ++ } ++ } ++ ++ private AsyncChatEvent createAsync(final ChatRenderer renderer, final Set recipients, final Set viewers, final Component message) { ++ return new AsyncChatEvent(this.async, this.player.getBukkitEntity(), recipients, viewers, renderer, message, this.originalMessage); ++ } ++ ++ private ChatEvent createSync(final ChatRenderer renderer, final Set recipients, final Set viewers, final Component message) { ++ return new ChatEvent(this.player.getBukkitEntity(), recipients, viewers, renderer, message, this.originalMessage); ++ } ++ ++ private static String legacyDisplayName(final CraftPlayer player) { ++ return player.getDisplayName(); ++ } ++ ++ private static Component displayName(final CraftPlayer player) { ++ return player.displayName(); ++ } ++ ++ private static ChatRenderer legacyRenderer(final String format) { ++ return (player, displayName, message, recipient) -> PaperAdventure.LEGACY_SECTION_UXRC.deserialize(String.format(format, legacyDisplayName((CraftPlayer) player), PaperAdventure.LEGACY_SECTION_UXRC.serialize(message))).replaceText(URL_REPLACEMENT_CONFIG); ++ } ++ ++ private void queueIfAsyncOrRunImmediately(final Waitable waitable) { ++ if (this.async) { ++ this.server.processQueue.add(waitable); ++ } else { ++ waitable.run(); ++ } ++ try { ++ waitable.get(); ++ } catch (final InterruptedException e) { ++ Thread.currentThread().interrupt(); // tag, you're it ++ } catch (final ExecutionException e) { ++ throw new RuntimeException("Exception processing chat", e.getCause()); ++ } ++ } ++ ++ private static void post(final Event event) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ ++ private static boolean anyListeners(final HandlerList handlers) { ++ return handlers.getRegisteredListeners().length > 0; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/DisplayNames.java b/src/main/java/io/papermc/paper/adventure/DisplayNames.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bfaf5d3c5aae8a587c2b11d90089c588b2a2aba0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/DisplayNames.java +@@ -0,0 +1,22 @@ ++package io.papermc.paper.adventure; ++ ++import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.ChatColor; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++ ++public final class DisplayNames { ++ private DisplayNames() { ++ } ++ ++ public static String getLegacy(final CraftPlayer player) { ++ return getLegacy(player.getHandle()); ++ } ++ ++ public static String getLegacy(final ServerPlayer player) { ++ final String legacy = player.displayName; ++ if (legacy != null) { ++ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName) + ChatColor.getLastColors(player.displayName); ++ } ++ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..10f08e2b73610ab06928d1f63348920fef8e91fa +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java +@@ -0,0 +1,21 @@ ++package io.papermc.paper.adventure; ++ ++import net.kyori.adventure.audience.Audience; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.util.LazyHashSet; ++import org.bukkit.craftbukkit.util.LazyPlayerSet; ++import org.bukkit.entity.Player; ++ ++import java.util.HashSet; ++import java.util.Set; ++ ++final class LazyChatAudienceSet extends LazyHashSet { ++ @Override ++ protected Set makeReference() { ++ final Set playerSet = LazyPlayerSet.makePlayerSet(MinecraftServer.getServer()); ++ final HashSet audiences = new HashSet<>(playerSet); ++ audiences.add(Bukkit.getConsoleSender()); ++ return audiences; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..eeedc30a45d9637d68f04f185b3dd90dd711b9e0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java +@@ -0,0 +1,88 @@ ++package io.papermc.paper.adventure; ++ ++import com.mojang.brigadier.exceptions.CommandSyntaxException; ++import java.io.IOException; ++import java.util.UUID; ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.nbt.api.BinaryTagHolder; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.event.HoverEvent; ++import net.kyori.adventure.text.serializer.gson.LegacyHoverEventSerializer; ++import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; ++import net.kyori.adventure.util.Codec; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.nbt.TagParser; ++ ++final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer { ++ public static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer(); ++ private static final Codec SNBT_CODEC = Codec.of(TagParser::parseTag, Tag::toString); ++ ++ static final String ITEM_TYPE = "id"; ++ static final String ITEM_COUNT = "Count"; ++ static final String ITEM_TAG = "tag"; ++ ++ static final String ENTITY_NAME = "name"; ++ static final String ENTITY_TYPE = "type"; ++ static final String ENTITY_ID = "id"; ++ ++ NBTLegacyHoverEventSerializer() { ++ } ++ ++ @Override ++ public HoverEvent.ShowItem deserializeShowItem(final Component input) throws IOException { ++ final String raw = PlainComponentSerializer.plain().serialize(input); ++ try { ++ final CompoundTag contents = SNBT_CODEC.decode(raw); ++ final CompoundTag tag = contents.getCompound(ITEM_TAG); ++ return HoverEvent.ShowItem.of( ++ Key.key(contents.getString(ITEM_TYPE)), ++ contents.contains(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1, ++ tag.isEmpty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC) ++ ); ++ } catch (final CommandSyntaxException ex) { ++ throw new IOException(ex); ++ } ++ } ++ ++ @Override ++ public HoverEvent.ShowEntity deserializeShowEntity(final Component input, final Codec.Decoder componentCodec) throws IOException { ++ final String raw = PlainComponentSerializer.plain().serialize(input); ++ try { ++ final CompoundTag contents = SNBT_CODEC.decode(raw); ++ return HoverEvent.ShowEntity.of( ++ Key.key(contents.getString(ENTITY_TYPE)), ++ UUID.fromString(contents.getString(ENTITY_ID)), ++ componentCodec.decode(contents.getString(ENTITY_NAME)) ++ ); ++ } catch (final CommandSyntaxException ex) { ++ throw new IOException(ex); ++ } ++ } ++ ++ @Override ++ public Component serializeShowItem(final HoverEvent.ShowItem input) throws IOException { ++ final CompoundTag tag = new CompoundTag(); ++ tag.putString(ITEM_TYPE, input.item().asString()); ++ tag.putByte(ITEM_COUNT, (byte) input.count()); ++ if (input.nbt() != null) { ++ try { ++ tag.put(ITEM_TAG, input.nbt().get(SNBT_CODEC)); ++ } catch (final CommandSyntaxException ex) { ++ throw new IOException(ex); ++ } ++ } ++ return Component.text(SNBT_CODEC.encode(tag)); ++ } ++ ++ @Override ++ public Component serializeShowEntity(final HoverEvent.ShowEntity input, final Codec.Encoder componentCodec) throws IOException { ++ final CompoundTag tag = new CompoundTag(); ++ tag.putString(ENTITY_ID, input.id().toString()); ++ tag.putString(ENTITY_TYPE, input.type().asString()); ++ if (input.name() != null) { ++ tag.putString(ENTITY_NAME, componentCodec.encode(input.name())); ++ } ++ return Component.text(SNBT_CODEC.encode(tag)); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java +new file mode 100644 +index 0000000000000000000000000000000000000000..696b7ad89af4e379d7b8f1961d1ab0cba1c3313f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java +@@ -0,0 +1,342 @@ ++package io.papermc.paper.adventure; ++ ++import com.mojang.brigadier.exceptions.CommandSyntaxException; ++import io.netty.util.AttributeKey; ++import java.io.IOException; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Locale; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++import net.kyori.adventure.bossbar.BossBar; ++import net.kyori.adventure.inventory.Book; ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.nbt.api.BinaryTagHolder; ++import net.kyori.adventure.sound.Sound; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.TranslatableComponent; ++import net.kyori.adventure.text.flattener.ComponentFlattener; ++import net.kyori.adventure.text.format.TextColor; ++import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; ++import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; ++import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; ++import net.kyori.adventure.translation.GlobalTranslator; ++import net.kyori.adventure.util.Codec; ++import net.minecraft.ChatFormatting; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.StringTag; ++import net.minecraft.nbt.TagParser; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.world.BossEvent; ++import net.minecraft.world.item.ItemStack; ++import org.bukkit.ChatColor; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++ ++public final class PaperAdventure { ++ public static final AttributeKey LOCALE_ATTRIBUTE = AttributeKey.valueOf("adventure:locale"); ++ private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s"); ++ public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder() ++ .complexMapper(TranslatableComponent.class, (translatable, consumer) -> { ++ final @NonNull String translated = LocaleLanguage.a().a(translatable.key()); ++ ++ final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated); ++ final List args = translatable.args(); ++ int argPosition = 0; ++ int lastIdx = 0; ++ while (matcher.find()) { ++ // append prior ++ if (lastIdx < matcher.start()) { ++ consumer.accept(Component.text(translated.substring(lastIdx, matcher.start()))); ++ } ++ lastIdx = matcher.end(); ++ ++ final @Nullable String argIdx = matcher.group(1); ++ // calculate argument position ++ if (argIdx != null) { ++ try { ++ final int idx = Integer.parseInt(argIdx) - 1; ++ if (idx < args.size()) { ++ consumer.accept(args.get(idx)); ++ } ++ } catch (final NumberFormatException ex) { ++ // ignore, drop the format placeholder ++ } ++ } else { ++ final int idx = argPosition++; ++ if (idx < args.size()) { ++ consumer.accept(args.get(idx)); ++ } ++ } ++ } ++ ++ // append tail ++ if (lastIdx < translated.length()) { ++ consumer.accept(Component.text(translated.substring(lastIdx))); ++ } ++ }) ++ .build(); ++ public static final LegacyComponentSerializer LEGACY_SECTION_UXRC = LegacyComponentSerializer.builder().flattener(FLATTENER).hexColors().useUnusualXRepeatedCharacterHexFormat().build(); ++ public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build(); ++ public static final GsonComponentSerializer GSON = GsonComponentSerializer.builder() ++ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) ++ .build(); ++ public static final GsonComponentSerializer COLOR_DOWNSAMPLING_GSON = GsonComponentSerializer.builder() ++ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) ++ .downsampleColors() ++ .build(); ++ private static final Codec NBT_CODEC = new Codec() { ++ @Override ++ public @NonNull CompoundTag decode(final @NonNull String encoded) throws IOException { ++ try { ++ return TagParser.parseTag(encoded); ++ } catch (final CommandSyntaxException e) { ++ throw new IOException(e); ++ } ++ } ++ ++ @Override ++ public @NonNull String encode(final @NonNull CompoundTag decoded) { ++ return decoded.toString(); ++ } ++ }; ++ static final WrapperAwareSerializer WRAPPER_AWARE_SERIALIZER = new WrapperAwareSerializer(); ++ ++ private PaperAdventure() { ++ } ++ ++ // Key ++ ++ public static ResourceLocation asVanilla(final Key key) { ++ return new ResourceLocation(key.namespace(), key.value()); ++ } ++ ++ public static ResourceLocation asVanillaNullable(final Key key) { ++ if (key == null) { ++ return null; ++ } ++ return new ResourceLocation(key.namespace(), key.value()); ++ } ++ ++ // Component ++ ++ public static Component asAdventure(final net.minecraft.network.chat.Component component) { ++ return component == null ? Component.empty() : GSON.serializer().fromJson(net.minecraft.network.chat.Component.Serializer.toJsonTree(component), Component.class); ++ } ++ ++ public static ArrayList asAdventure(final List vanillas) { ++ final ArrayList adventures = new ArrayList<>(vanillas.size()); ++ for (final net.minecraft.network.chat.Component vanilla : vanillas) { ++ adventures.add(asAdventure(vanilla)); ++ } ++ return adventures; ++ } ++ ++ public static ArrayList asAdventureFromJson(final List jsonStrings) { ++ final ArrayList adventures = new ArrayList<>(jsonStrings.size()); ++ for (final String json : jsonStrings) { ++ adventures.add(GsonComponentSerializer.gson().deserialize(json)); ++ } ++ return adventures; ++ } ++ ++ public static List asJson(final List adventures) { ++ final List jsons = new ArrayList<>(adventures.size()); ++ for (final Component component : adventures) { ++ jsons.add(GsonComponentSerializer.gson().serialize(component)); ++ } ++ return jsons; ++ } ++ ++ public static net.minecraft.network.chat.Component asVanilla(final Component component) { ++ if (true) return new AdventureComponent(component); ++ return net.minecraft.network.chat.Component.Serializer.fromJsonTree(GSON.serializer().toJsonTree(component)); ++ } ++ ++ public static List asVanilla(final List adventures) { ++ final List vanillas = new ArrayList<>(adventures.size()); ++ for (final Component adventure : adventures) { ++ vanillas.add(asVanilla(adventure)); ++ } ++ return vanillas; ++ } ++ ++ public static String asJsonString(final Component component, final Locale locale) { ++ return GSON.serialize( ++ GlobalTranslator.render( ++ component, ++ // play it safe ++ locale != null ++ ? locale ++ : Locale.US ++ ) ++ ); ++ } ++ ++ public static String asJsonString(final net.minecraft.network.chat.Component component, final Locale locale) { ++ if (component instanceof AdventureComponent) { ++ return asJsonString(((AdventureComponent) component).wrapped, locale); ++ } ++ return net.minecraft.network.chat.Component.Serializer.componentToJson(component); ++ } ++ ++ // thank you for being worse than wet socks, Bukkit ++ public static String superHackyLegacyRepresentationOfComponent(final Component component, final String string) { ++ return LEGACY_SECTION_UXRC.serialize(component) + ChatColor.getLastColors(string); ++ } ++ ++ // BossBar ++ ++ public static BossEvent.BossBarColor asVanilla(final BossBar.Color color) { ++ if (color == BossBar.Color.PINK) { ++ return BossEvent.BossBarColor.PINK; ++ } else if (color == BossBar.Color.BLUE) { ++ return BossEvent.BossBarColor.BLUE; ++ } else if (color == BossBar.Color.RED) { ++ return BossEvent.BossBarColor.RED; ++ } else if (color == BossBar.Color.GREEN) { ++ return BossEvent.BossBarColor.GREEN; ++ } else if (color == BossBar.Color.YELLOW) { ++ return BossEvent.BossBarColor.YELLOW; ++ } else if (color == BossBar.Color.PURPLE) { ++ return BossEvent.BossBarColor.PURPLE; ++ } else if (color == BossBar.Color.WHITE) { ++ return BossEvent.BossBarColor.WHITE; ++ } ++ throw new IllegalArgumentException(color.name()); ++ } ++ ++ public static BossBar.Color asAdventure(final BossEvent.BossBarColor color) { ++ if(color == BossEvent.BossBarColor.PINK) { ++ return BossBar.Color.PINK; ++ } else if(color == BossEvent.BossBarColor.BLUE) { ++ return BossBar.Color.BLUE; ++ } else if(color == BossEvent.BossBarColor.RED) { ++ return BossBar.Color.RED; ++ } else if(color == BossEvent.BossBarColor.GREEN) { ++ return BossBar.Color.GREEN; ++ } else if(color == BossEvent.BossBarColor.YELLOW) { ++ return BossBar.Color.YELLOW; ++ } else if(color == BossEvent.BossBarColor.PURPLE) { ++ return BossBar.Color.PURPLE; ++ } else if(color == BossEvent.BossBarColor.WHITE) { ++ return BossBar.Color.WHITE; ++ } ++ throw new IllegalArgumentException(color.name()); ++ } ++ ++ public static BossEvent.BossBarOverlay asVanilla(final BossBar.Overlay overlay) { ++ if (overlay == BossBar.Overlay.PROGRESS) { ++ return BossEvent.BossBarOverlay.PROGRESS; ++ } else if (overlay == BossBar.Overlay.NOTCHED_6) { ++ return BossEvent.BossBarOverlay.NOTCHED_6; ++ } else if (overlay == BossBar.Overlay.NOTCHED_10) { ++ return BossEvent.BossBarOverlay.NOTCHED_10; ++ } else if (overlay == BossBar.Overlay.NOTCHED_12) { ++ return BossEvent.BossBarOverlay.NOTCHED_12; ++ } else if (overlay == BossBar.Overlay.NOTCHED_20) { ++ return BossEvent.BossBarOverlay.NOTCHED_20; ++ } ++ throw new IllegalArgumentException(overlay.name()); ++ } ++ ++ public static BossBar.Overlay asAdventure(final BossEvent.BossBarOverlay overlay) { ++ if (overlay == BossEvent.BossBarOverlay.PROGRESS) { ++ return BossBar.Overlay.PROGRESS; ++ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_6) { ++ return BossBar.Overlay.NOTCHED_6; ++ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_10) { ++ return BossBar.Overlay.NOTCHED_10; ++ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_12) { ++ return BossBar.Overlay.NOTCHED_12; ++ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_20) { ++ return BossBar.Overlay.NOTCHED_20; ++ } ++ throw new IllegalArgumentException(overlay.name()); ++ } ++ ++ public static void setFlag(final BossBar bar, final BossBar.Flag flag, final boolean value) { ++ if (value) { ++ bar.addFlag(flag); ++ } else { ++ bar.removeFlag(flag); ++ } ++ } ++ ++ // Book ++ ++ public static ItemStack asItemStack(final Book book, final Locale locale) { ++ final ItemStack item = new ItemStack(net.minecraft.world.item.Items.WRITTEN_BOOK, 1); ++ final CompoundTag tag = item.getOrCreateTag(); ++ tag.putString("title", asJsonString(book.title(), locale)); ++ tag.putString("author", asJsonString(book.author(), locale)); ++ final ListTag pages = new ListTag(); ++ for (final Component page : book.pages()) { ++ pages.add(StringTag.create(asJsonString(page, locale))); ++ } ++ tag.put("pages", pages); ++ return item; ++ } ++ ++ // Sounds ++ ++ public static SoundSource asVanilla(final Sound.Source source) { ++ if (source == Sound.Source.MASTER) { ++ return SoundSource.MASTER; ++ } else if (source == Sound.Source.MUSIC) { ++ return SoundSource.MUSIC; ++ } else if (source == Sound.Source.RECORD) { ++ return SoundSource.RECORDS; ++ } else if (source == Sound.Source.WEATHER) { ++ return SoundSource.WEATHER; ++ } else if (source == Sound.Source.BLOCK) { ++ return SoundSource.BLOCKS; ++ } else if (source == Sound.Source.HOSTILE) { ++ return SoundSource.HOSTILE; ++ } else if (source == Sound.Source.NEUTRAL) { ++ return SoundSource.NEUTRAL; ++ } else if (source == Sound.Source.PLAYER) { ++ return SoundSource.PLAYERS; ++ } else if (source == Sound.Source.AMBIENT) { ++ return SoundSource.AMBIENT; ++ } else if (source == Sound.Source.VOICE) { ++ return SoundSource.VOICE; ++ } ++ throw new IllegalArgumentException(source.name()); ++ } ++ ++ public static @Nullable SoundSource asVanillaNullable(final Sound.@Nullable Source source) { ++ if (source == null) { ++ return null; ++ } ++ return asVanilla(source); ++ } ++ ++ // NBT ++ ++ public static @Nullable BinaryTagHolder asBinaryTagHolder(final @Nullable CompoundTag tag) { ++ if (tag == null) { ++ return null; ++ } ++ try { ++ return BinaryTagHolder.encode(tag, NBT_CODEC); ++ } catch (final IOException e) { ++ return null; ++ } ++ } ++ ++ // Colors ++ ++ public static @NonNull TextColor asAdventure(ChatFormatting minecraftColor) { ++ if (minecraftColor.getColor() == null) { ++ throw new IllegalArgumentException("Not a valid color"); ++ } ++ return TextColor.color(minecraftColor.getColor()); ++ } ++ ++ public static @Nullable ChatFormatting asVanilla(TextColor color) { ++ return ChatFormatting.getByHexValue(color.value()); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ee6d9d5c072d68cace63068a8e2ed603ad475378 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java +@@ -0,0 +1,41 @@ ++package io.papermc.paper.adventure; ++ ++import java.util.Set; ++import java.util.function.Consumer; ++import net.kyori.adventure.bossbar.BossBar; ++import net.kyori.adventure.text.Component; ++import net.minecraft.network.protocol.game.ClientboundBossEventPacket; ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++public final class VanillaBossBarListener implements BossBar.Listener { ++ private final Consumer action; ++ ++ public VanillaBossBarListener(final Consumer action) { ++ this.action = action; ++ } ++ ++ @Override ++ public void bossBarNameChanged(final @NonNull BossBar bar, final @NonNull Component oldName, final @NonNull Component newName) { ++ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_NAME); ++ } ++ ++ @Override ++ public void bossBarProgressChanged(final @NonNull BossBar bar, final float oldProgress, final float newProgress) { ++ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_PCT); ++ } ++ ++ @Override ++ public void bossBarColorChanged(final @NonNull BossBar bar, final BossBar.@NonNull Color oldColor, final BossBar.@NonNull Color newColor) { ++ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_STYLE); ++ } ++ ++ @Override ++ public void bossBarOverlayChanged(final @NonNull BossBar bar, final BossBar.@NonNull Overlay oldOverlay, final BossBar.@NonNull Overlay newOverlay) { ++ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_STYLE); ++ } ++ ++ @Override ++ public void bossBarFlagsChanged(final @NonNull BossBar bar, final @NonNull Set flagsAdded, final @NonNull Set flagsRemoved) { ++ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_PROPERTIES); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2e93ac0eb74a89c020f3356f77320cf6459727fd +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java +@@ -0,0 +1,19 @@ ++package io.papermc.paper.adventure; ++ ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.serializer.ComponentSerializer; ++ ++final class WrapperAwareSerializer implements ComponentSerializer { ++ @Override ++ public Component deserialize(final net.minecraft.network.chat.Component input) { ++ if (input instanceof AdventureComponent) { ++ return ((AdventureComponent) input).wrapped; ++ } ++ return PaperAdventure.GSON.serializer().fromJson(net.minecraft.network.chat.Component.Serializer.toJsonTree(input), Component.class); ++ } ++ ++ @Override ++ public net.minecraft.network.chat.Component serialize(final Component component) { ++ return net.minecraft.network.chat.Component.Serializer.fromJsonTree(PaperAdventure.GSON.serializer().toJsonTree(component)); ++ } ++} +diff --git a/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2dc92d8d2764d3e9b621d5c7d5e30c30367b3117 +--- /dev/null ++++ b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java +@@ -0,0 +1,36 @@ ++package net.kyori.adventure.bossbar; ++ ++import io.papermc.paper.adventure.PaperAdventure; ++import io.papermc.paper.adventure.VanillaBossBarListener; ++import net.minecraft.server.level.ServerBossEvent; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++ ++public abstract class HackyBossBarPlatformBridge { ++ public ServerBossEvent vanilla$bar; ++ private VanillaBossBarListener vanilla$listener; ++ ++ public final void paper$playerShow(final CraftPlayer player) { ++ if (this.vanilla$bar == null) { ++ final BossBar $this = (BossBar) this; ++ this.vanilla$bar = new ServerBossEvent( ++ PaperAdventure.asVanilla($this.name()), ++ PaperAdventure.asVanilla($this.color()), ++ PaperAdventure.asVanilla($this.overlay()) ++ ); ++ this.vanilla$bar.adventure = $this; ++ this.vanilla$listener = new VanillaBossBarListener(this.vanilla$bar::broadcast); ++ $this.addListener(this.vanilla$listener); ++ } ++ this.vanilla$bar.addPlayer(player.getHandle()); ++ } ++ ++ public final void paper$playerHide(final CraftPlayer player) { ++ if (this.vanilla$bar != null) { ++ this.vanilla$bar.removePlayer(player.getHandle()); ++ if (this.vanilla$bar.getPlayers().isEmpty()) { ++ ((BossBar) this).removeListener(this.vanilla$listener); ++ this.vanilla$bar = null; ++ } ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/ChatFormatting.java b/src/main/java/net/minecraft/ChatFormatting.java +index e888a90226c30757b190a3b89a56c1a312f32850..1720eba650c959810c6e4a3522979e75e10a1bb8 100644 +--- a/src/main/java/net/minecraft/ChatFormatting.java ++++ b/src/main/java/net/minecraft/ChatFormatting.java +@@ -61,6 +61,7 @@ public enum ChatFormatting { + return !this.isFormat && this != ChatFormatting.RESET; + } + ++ @Nullable public Integer getHexValue() { return this.getColor(); } // Paper - OBFHELPER + @Nullable + public Integer getColor() { + return this.color; +@@ -84,6 +85,18 @@ public enum ChatFormatting { + return name == null ? null : (ChatFormatting) ChatFormatting.FORMATTING_BY_NAME.get(cleanName(name)); + } + ++ // Paper start ++ @Nullable public static ChatFormatting getByHexValue(int i) { ++ for (ChatFormatting value : values()) { ++ if (value.getHexValue() != null && value.getHexValue() == i) { ++ return value; ++ } ++ } ++ ++ return null; ++ } ++ // Paper end ++ + @Nullable + public static ChatFormatting getById(int colorIndex) { + if (colorIndex < 0) { +diff --git a/src/main/java/net/minecraft/nbt/StringTag.java b/src/main/java/net/minecraft/nbt/StringTag.java +index 620e10b5ba9e57ff4d0d7967bf4240fafadb2be7..dab8983fa65b97ecf0fe20fdc06cc8ec60d8fe95 100644 +--- a/src/main/java/net/minecraft/nbt/StringTag.java ++++ b/src/main/java/net/minecraft/nbt/StringTag.java +@@ -43,6 +43,7 @@ public class StringTag implements Tag { + this.data = value; + } + ++ public static StringTag create(final String value) { return valueOf(value); } // Paper - OBFHELPER + public static StringTag valueOf(String value) { + return value.isEmpty() ? StringTag.EMPTY : new StringTag(value); + } +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index 50f14acb062c2f90266279dbd1945a3297396f0b..59788eaef0dae5ee01ceba1bf45e85cb07f88e53 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -10,6 +10,7 @@ import io.netty.buffer.ByteBufOutputStream; + import io.netty.handler.codec.DecoderException; + import io.netty.handler.codec.EncoderException; + import io.netty.util.ByteProcessor; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.io.DataInput; + import java.io.DataOutput; + import java.io.IOException; +@@ -43,6 +44,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit + public class FriendlyByteBuf extends ByteBuf { + + private final ByteBuf source; ++ public java.util.Locale adventure$locale; // Paper + + public FriendlyByteBuf(ByteBuf bytebuf) { + this.source = bytebuf; +@@ -164,8 +166,15 @@ public class FriendlyByteBuf extends ByteBuf { + return Component.Serializer.fromJson(this.readUtf(262144)); + } + ++ // Paper start ++ public FriendlyByteBuf writeComponent(final net.kyori.adventure.text.Component component) { ++ return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); ++ } ++ // Paper end ++ + public FriendlyByteBuf writeComponent(Component text) { +- return this.writeUtf(Component.Serializer.toJson(text), 262144); ++ //return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); // Paper - comment ++ return this.writeUtf(PaperAdventure.asJsonString(text, this.adventure$locale), 262144); // Paper + } + + public > T readEnum(Class oclass) { +@@ -348,6 +357,7 @@ public class FriendlyByteBuf extends ByteBuf { + return this.writeUtf(s, 32767); + } + ++ public FriendlyByteBuf writeUtf(final String string, final int maxLength) { return this.writeUtf(string, maxLength); } // Paper - OBFHELPER + public FriendlyByteBuf writeUtf(String s, int i) { + byte[] abyte = s.getBytes(StandardCharsets.UTF_8); + +diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java +index 14fa1371e52b9af5a7550a9aa144fa406b754046..d36d0424bcd4811af892f5f76fdcefda2af1ad33 100644 +--- a/src/main/java/net/minecraft/network/PacketEncoder.java ++++ b/src/main/java/net/minecraft/network/PacketEncoder.java +@@ -3,6 +3,7 @@ package net.minecraft.network; + import io.netty.buffer.ByteBuf; + import io.netty.channel.ChannelHandlerContext; + import io.netty.handler.codec.MessageToByteEncoder; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.io.IOException; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketFlow; +@@ -37,6 +38,7 @@ public class PacketEncoder extends MessageToByteEncoder> { + throw new IOException("Can't serialize unregistered packet"); + } else { + FriendlyByteBuf packetdataserializer = new FriendlyByteBuf(bytebuf); ++ packetdataserializer.adventure$locale = channelhandlercontext.channel().attr(PaperAdventure.LOCALE_ATTRIBUTE).get(); // Paper + + packetdataserializer.writeVarInt(integer); + +diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java +index 819ea90ea116dea396c225539fc0fbebd6176ba5..54d186a195aca6d0a4c412ed609d8c86dcc76072 100644 +--- a/src/main/java/net/minecraft/network/chat/Component.java ++++ b/src/main/java/net/minecraft/network/chat/Component.java +@@ -1,5 +1,6 @@ + package net.minecraft.network.chat; + ++import io.papermc.paper.adventure.AdventureComponent; // Paper + import com.google.gson.Gson; + import com.google.gson.GsonBuilder; + import com.google.gson.JsonArray; +@@ -110,6 +111,7 @@ public interface Component extends Message, FormattedText, Iterable { + GsonBuilder gsonbuilder = new GsonBuilder(); + + gsonbuilder.disableHtmlEscaping(); ++ gsonbuilder.registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()); // Paper + gsonbuilder.registerTypeHierarchyAdapter(Component.class, new Component.Serializer()); + gsonbuilder.registerTypeHierarchyAdapter(Style.class, new Style.Serializer()); + gsonbuilder.registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()); +@@ -262,6 +264,7 @@ public interface Component extends Message, FormattedText, Iterable { + } + + public JsonElement serialize(Component ichatbasecomponent, Type type, JsonSerializationContext jsonserializationcontext) { ++ if (ichatbasecomponent instanceof AdventureComponent) return jsonserializationcontext.serialize(ichatbasecomponent); // Paper + JsonObject jsonobject = new JsonObject(); + + if (!ichatbasecomponent.getStyle().isEmpty()) { +@@ -350,10 +353,12 @@ public interface Component extends Message, FormattedText, Iterable { + return jsonobject; + } + ++ public static String componentToJson(final Component component) { return toJson(component); } // Paper - OBFHELPER + public static String toJson(Component text) { + return Component.Serializer.GSON.toJson(text); + } + ++ public static JsonElement toJsonTree(final Component component) { return toJsonTree(component); } // Paper - OBFHELPER + public static JsonElement toJsonTree(Component text) { + return Component.Serializer.GSON.toJsonTree(text); + } +@@ -363,6 +368,7 @@ public interface Component extends Message, FormattedText, Iterable { + return (MutableComponent) GsonHelper.fromJson(Component.Serializer.GSON, json, MutableComponent.class, false); + } + ++ public static @Nullable Component fromJsonTree(final JsonElement json) { return fromJson(json); } // Paper - OBFHELPER + @Nullable + public static MutableComponent fromJson(JsonElement json) { + return (MutableComponent) Component.Serializer.GSON.fromJson(json, MutableComponent.class); +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +index ce64931b5c363352f03baddbc747246469d56a84..e47102cadb40ed8a9c011386445f15fd30de7596 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +@@ -11,6 +11,7 @@ import net.minecraft.network.protocol.Packet; + public class ClientboundChatPacket implements Packet { + + private Component message; ++ public net.kyori.adventure.text.Component adventure$message; // Paper + public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot + private ChatType type; + private UUID sender; +@@ -32,6 +33,11 @@ public class ClientboundChatPacket implements Packet { + + @Override + public void write(FriendlyByteBuf buf) throws IOException { ++ // Paper start ++ if (this.adventure$message != null) { ++ buf.writeComponent(this.adventure$message); ++ } else ++ // Paper end + // Spigot start + if (components != null) { + buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(components)); +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java +index 915120cc505c70153f7b70f07d8d42c13eb77ea7..69ff8df7340e60c476803256750a48f0b43414d3 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java +@@ -10,6 +10,7 @@ public class ClientboundSetTitlesPacket implements Packet 0 && flag) { // TODO: allow plugins to override? +- Component ichatbasecomponent; +- if (deathMessage.equals(deathmessage)) { +- ichatbasecomponent = this.getCombatTracker().getDeathMessage(); +- } else { +- ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage); +- } ++ if (deathMessage != null && deathMessage != net.kyori.adventure.text.Component.empty() && flag) { // Paper - Adventure // TODO: allow plugins to override? ++ Component ichatbasecomponent = PaperAdventure.asVanilla(deathMessage); // Paper - Adventure + + this.connection.send((Packet) (new ClientboundPlayerCombatPacket(this.getCombatTracker(), ClientboundPlayerCombatPacket.Event.ENTITY_DIED, ichatbasecomponent)), (future) -> { + if (!future.isSuccess()) { +@@ -1666,6 +1663,7 @@ public class ServerPlayer extends Player implements ContainerListener { + this.sendMessage(message, ChatType.SYSTEM, senderUuid); + } + ++ public void sendMessage(final Component message, final ChatType type, final UUID sender) { this.sendMessage(message, type, sender); } // Paper - OBFHELPER + public void sendMessage(Component message, ChatType type, UUID senderUuid) { + this.connection.send((Packet) (new ClientboundChatPacket(message, type, senderUuid)), (future) -> { + if (!future.isSuccess() && (type == ChatType.GAME_INFO || type == ChatType.SYSTEM)) { +@@ -1688,6 +1686,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + + public String locale = "en_us"; // CraftBukkit - add, lowercase ++ public java.util.Locale adventure$locale = java.util.Locale.US; // Paper + public void updateOptions(ServerboundClientInformationPacket packet) { + // CraftBukkit start + if (getMainArm() != packet.getMainHand()) { +@@ -1699,6 +1698,10 @@ public class ServerPlayer extends Player implements ContainerListener { + this.server.server.getPluginManager().callEvent(event); + } + this.locale = packet.language; ++ // Paper start ++ this.adventure$locale = net.kyori.adventure.translation.Translator.parseLocale(this.locale); ++ this.connection.connection.channel.attr(PaperAdventure.LOCALE_ATTRIBUTE).set(this.adventure$locale); ++ // Paper end + this.clientViewDistance = packet.viewDistance; + // CraftBukkit end + this.chatVisibility = packet.getChatVisibility(); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 466c4322803bedf1fa61be281b954bf94fb8ff02..016e91a6ca1c8457e3e367ac0597b73e81919b68 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -168,6 +168,8 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + // CraftBukkit start ++import io.papermc.paper.adventure.ChatProcessor; // Paper ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.util.concurrent.ExecutionException; + import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + import org.bukkit.Location; +@@ -388,21 +390,24 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + return this.server.isSingleplayerOwner(this.player.getGameProfile()); + } + +- // CraftBukkit start +- @Deprecated +- public void disconnect(Component reason) { +- disconnect(CraftChatMessage.fromComponent(reason)); ++ public void disconnect(String s) { ++ // Paper start ++ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); + } +- // CraftBukkit end + +- public void disconnect(String s) { ++ public void disconnect(final Component reason) { ++ this.disconnect(PaperAdventure.asAdventure(reason)); ++ } ++ ++ public void disconnect(net.kyori.adventure.text.Component reason) { ++ // Paper end + // CraftBukkit start - fire PlayerKickEvent + if (this.processedDisconnect) { + return; + } +- String leaveMessage = ChatFormatting.YELLOW + this.player.getScoreboardName() + " left the game."; ++ net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure + +- PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), s, leaveMessage); ++ PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure + + if (this.craftServer.getServer().isRunning()) { + this.craftServer.getPluginManager().callEvent(event); +@@ -413,8 +418,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + return; + } + // Send the possibly modified leave message +- s = event.getReason(); +- final Component ichatbasecomponent = CraftChatMessage.fromString(s, true)[0]; ++ final Component ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure + // CraftBukkit end + + this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> { +@@ -1631,9 +1635,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + */ + + this.player.disconnect(); +- String quitMessage = this.server.getPlayerList().disconnect(this.player); +- if ((quitMessage != null) && (quitMessage.length() > 0)) { +- this.server.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); ++ // Paper start - Adventure ++ net.kyori.adventure.text.Component quitMessage = this.server.getPlayerList().disconnect(this.player); ++ if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) { ++ this.server.getPlayerList().sendMessage(PaperAdventure.asVanilla(quitMessage)); ++ // Paper end + } + // CraftBukkit end + TextFilter itextfilter = this.player.getTextFilter(); +@@ -1849,8 +1855,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.handleCommand(s); + } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { + // Do nothing, this is coming from a plugin +- } else { +- Player player = this.getPlayer(); ++ // Paper start ++ } else if (true) { ++ final ChatProcessor cp = new ChatProcessor(this.server, this.player, s, async); ++ cp.process(); ++ // Paper end ++ } else if (false) { // Paper ++ Player player = this.getPlayer(); // Paper + AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(server)); + this.craftServer.getPluginManager().callEvent(event); + +@@ -2668,21 +2679,20 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + return; + } + +- // CraftBukkit start +- Player player = this.craftServer.getPlayer(this.player); +- int x = packetplayinupdatesign.getPos().getX(); +- int y = packetplayinupdatesign.getPos().getY(); +- int z = packetplayinupdatesign.getPos().getZ(); +- String[] lines = new String[4]; ++ // CraftBukkit start // Paper start - Adventure ++ List lines = new java.util.ArrayList<>(); + + for (int i = 0; i < list.size(); ++i) { +- lines[i] = ChatFormatting.stripFormatting(new TextComponent(ChatFormatting.stripFormatting((String) list.get(i))).getString()); ++ lines.add(net.kyori.adventure.text.Component.text(list.get(i))); + } +- SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.craftServer.getPlayer(this.player), lines); ++ SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); + this.craftServer.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { +- System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.messages, 0, 4); ++ for (int i = 0; i < 4; i++) { ++ tileentitysign.setMessage(i, PaperAdventure.asVanilla(event.line(i))); ++ } ++ // Paper end + tileentitysign.isEditable = false; + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index a1dd76f49c59ed0a0b7f2b68fbd1a9a70a89128b..9dbb3bb79ae2de6635f71e5ee5bebeb5e57b624e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -35,6 +35,7 @@ import net.minecraft.world.entity.player.Player; + import org.apache.commons.lang3.Validate; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import org.bukkit.craftbukkit.util.Waitable; + import org.bukkit.event.player.AsyncPlayerPreLoginEvent; + import org.bukkit.event.player.PlayerPreLoginEvent; +@@ -299,7 +300,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { + final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); + if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { +- event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); ++ event.disallow(asyncEvent.getResult(), asyncEvent.kickMessage()); // Paper - Adventure + } + Waitable waitable = new Waitable() { + @Override +@@ -310,12 +311,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + + ServerLoginPacketListenerImpl.this.server.processQueue.add(waitable); + if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { +- disconnect(event.getKickMessage()); ++ disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure + return; + } + } else { + if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { +- disconnect(asyncEvent.getKickMessage()); ++ disconnect(PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure + return; + } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +index de19aa66e7b6ddde17e9acf65643b4a71573d759..223df8d27c2ff1cbff634bca3dbde5cc24de7f98 100644 +--- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +@@ -55,7 +55,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + CraftIconCache icon = server.server.getServerIcon(); + + ServerListPingEvent() { +- super(((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.getMotd(), server.getPlayerList().getMaxPlayers()); ++ super(((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.server.motd(), server.getPlayerList().getMaxPlayers()); // Paper - Adventure + } + + @Override +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 88af57699d7f9e45ad1366243049e4f3565703ff..8cdecaf2f63c78196e0c5046fe2431b40e072c8a 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -8,6 +8,7 @@ import com.mojang.authlib.GameProfile; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import io.netty.buffer.Unpooled; ++import io.papermc.paper.adventure.PaperAdventure; + import java.io.File; + import java.net.SocketAddress; + import java.text.SimpleDateFormat; +@@ -83,6 +84,7 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + // CraftBukkit start ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import com.google.common.base.Predicate; + import com.google.common.collect.Iterables; + import net.minecraft.server.dedicated.DedicatedServer; +@@ -251,7 +253,7 @@ public abstract class PlayerList { + } + // CraftBukkit start + chatmessage.withStyle(ChatFormatting.YELLOW); +- String joinMessage = CraftChatMessage.fromComponent(chatmessage); ++ Component joinMessage = chatmessage; // Paper - Adventure + + playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.yRot, player.xRot); + this.players.add(player); +@@ -260,19 +262,18 @@ public abstract class PlayerList { + // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below + + // CraftBukkit start +- PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(cserver.getPlayer(player), joinMessage); ++ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + cserver.getPluginManager().callEvent(playerJoinEvent); + + if (!player.connection.connection.isConnected()) { + return; + } + +- joinMessage = playerJoinEvent.getJoinMessage(); ++ final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); + +- if (joinMessage != null && joinMessage.length() > 0) { +- for (Component line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { +- server.getPlayerList().broadcastAll(new ClientboundChatPacket(line, ChatType.SYSTEM, Util.NIL_UUID)); +- } ++ if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure ++ joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure ++ server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure + } + // CraftBukkit end + +@@ -469,7 +470,7 @@ public abstract class PlayerList { + + } + +- public String disconnect(ServerPlayer entityplayer) { // CraftBukkit - return string ++ public net.kyori.adventure.text.Component disconnect(ServerPlayer entityplayer) { // Paper - return Component + ServerLevel worldserver = entityplayer.getLevel(); + + entityplayer.awardStat(Stats.LEAVE_GAME); +@@ -480,7 +481,7 @@ public abstract class PlayerList { + entityplayer.closeContainer(); + } + +- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getScoreboardName() + " left the game"); ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); + cserver.getPluginManager().callEvent(playerQuitEvent); + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + +@@ -541,7 +542,7 @@ public abstract class PlayerList { + cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); + // CraftBukkit end + +- return playerQuitEvent.getQuitMessage(); // CraftBukkit ++ return playerQuitEvent.quitMessage(); // Paper - Adventure + } + + // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer +@@ -587,10 +588,10 @@ public abstract class PlayerList { + } + + // return chatmessage; +- if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); // Spigot ++ if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure + } else if (!this.isWhiteListed(gameprofile)) { + chatmessage = new TranslatableComponent("multiplayer.disconnect.not_whitelisted"); +- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot ++ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure + } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { + IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); + +@@ -600,17 +601,17 @@ public abstract class PlayerList { + } + + // return chatmessage; +- event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); ++ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + } else { + // return this.players.size() >= this.maxPlayers && !this.f(gameprofile) ? new ChatMessage("multiplayer.disconnect.server_full") : null; + if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) { +- event.disallow(PlayerLoginEvent.Result.KICK_FULL, org.spigotmc.SpigotConfig.serverFullMessage); // Spigot ++ event.disallow(PlayerLoginEvent.Result.KICK_FULL, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure + } + } + + cserver.getPluginManager().callEvent(event); + if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { +- loginlistener.disconnect(event.getKickMessage()); ++ loginlistener.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure + return null; + } + return entity; +@@ -1131,7 +1132,7 @@ public abstract class PlayerList { + public void removeAll() { + // CraftBukkit start - disconnect safely + for (ServerPlayer player : this.players) { +- player.connection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message ++ player.connection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure + } + // CraftBukkit end + +diff --git a/src/main/java/net/minecraft/world/BossEvent.java b/src/main/java/net/minecraft/world/BossEvent.java +index 8718449abc08ed7795ac70c2bef12d15b94d4127..adb7c8db8e173801a83e5ff1f4cad0dda2abeb82 100644 +--- a/src/main/java/net/minecraft/world/BossEvent.java ++++ b/src/main/java/net/minecraft/world/BossEvent.java +@@ -1,5 +1,6 @@ + package net.minecraft.world; + ++import io.papermc.paper.adventure.PaperAdventure; + import java.util.UUID; + import net.minecraft.ChatFormatting; + import net.minecraft.network.chat.Component; +@@ -14,6 +15,7 @@ public abstract class BossEvent { + protected boolean darkenScreen; + protected boolean playBossMusic; + protected boolean createWorldFog; ++ public net.kyori.adventure.bossbar.BossBar adventure; // Paper + + public BossEvent(UUID uuid, Component name, BossEvent.BossBarColor color, BossEvent.BossBarOverlay style) { + this.id = uuid; +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 2a6a6e291efbd7cc8fed6532f18321bd141e1306..3faf52e7ac5e7e22d09cfb73cfda6b9f622137d4 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -865,6 +865,7 @@ public final class ItemStack { + } + // CraftBukkit end + ++ public Component displayName() { return this.getDisplayName(); } // Paper - OBFHELPER + public Component getDisplayName() { + MutableComponent ichatmutablecomponent = (new TextComponent("")).append(this.getHoverName()); + +diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +index 72367311f79e3ef2868c05b38bae98c5a9fb129c..c23ec1b31950471905c65e46273ae105de853d9b 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +@@ -94,6 +94,7 @@ public abstract class Enchantment { + return this.getOrCreateDescriptionId(); + } + ++ public final Component getTranslationComponentForLevel(int level) { return this.getFullname(level); } // Paper - OBFHELPER + public Component getFullname(int level) { + TranslatableComponent chatmessage = new TranslatableComponent(this.getDescriptionId()); + +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +index 2cccec66fbc7114c65336769e354fe6f756c9fca..d44505b3ee2a35422568e9bce0d868191e348fc0 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -32,6 +32,7 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + // CraftBukkit start ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.util.UUID; + + import org.bukkit.craftbukkit.CraftServer; +@@ -473,7 +474,7 @@ public class MapItemSavedData extends SavedData { + for ( org.bukkit.map.MapCursor cursor : render.cursors) { + + if (cursor.isVisible()) { +- icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); ++ icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure + } + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index c4cf1394fe4c2782b1fea8b3653a817157d857eb..f7f5457d20586e0ba72368e64ff6025f6755e61e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -561,8 +561,10 @@ public final class CraftServer implements Server { + } + + @Override ++ @Deprecated // Paper start + public int broadcastMessage(String message) { +- return broadcast(message, BROADCAST_CHANNEL_USERS); ++ return this.broadcast(message, BROADCAST_CHANNEL_USERS); ++ // Paper end + } + + public Player getPlayer(final ServerPlayer entity) { +@@ -1306,7 +1308,15 @@ public final class CraftServer implements Server { + return configuration.getInt("settings.spawn-radius", -1); + } + ++ // Paper start + @Override ++ public net.kyori.adventure.text.Component shutdownMessage() { ++ String msg = getShutdownMessage(); ++ return msg != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(msg) : null; ++ } ++ // Paper end ++ @Override ++ @Deprecated // Paper + public String getShutdownMessage() { + return configuration.getString("settings.shutdown-message"); + } +@@ -1422,7 +1432,20 @@ public final class CraftServer implements Server { + } + + @Override ++ @Deprecated // Paper + public int broadcast(String message, String permission) { ++ // Paper start - Adventure ++ return this.broadcast(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(message), permission); ++ } ++ ++ @Override ++ public int broadcast(net.kyori.adventure.text.Component message) { ++ return this.broadcast(message, BROADCAST_CHANNEL_USERS); ++ } ++ ++ @Override ++ public int broadcast(net.kyori.adventure.text.Component message, String permission) { ++ // Paper end + Set recipients = new HashSet<>(); + for (Permissible permissible : getPluginManager().getPermissionSubscriptions(permission)) { + if (permissible instanceof CommandSender && permissible.hasPermission(permission)) { +@@ -1430,14 +1453,14 @@ public final class CraftServer implements Server { + } + } + +- BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); ++ BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); // Paper - Adventure + getPluginManager().callEvent(broadcastMessageEvent); + + if (broadcastMessageEvent.isCancelled()) { + return 0; + } + +- message = broadcastMessageEvent.getMessage(); ++ message = broadcastMessageEvent.message(); // Paper - Adventure + + for (CommandSender recipient : recipients) { + recipient.sendMessage(message); +@@ -1663,6 +1686,14 @@ public final class CraftServer implements Server { + return CraftInventoryCreator.INSTANCE.createInventory(owner, type); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); ++ return CraftInventoryCreator.INSTANCE.createInventory(owner, type, title); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { + Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); +@@ -1675,13 +1706,28 @@ public final class CraftServer implements Server { + return CraftInventoryCreator.INSTANCE.createInventory(owner, size); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) throws IllegalArgumentException { ++ Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); ++ return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder owner, int size, String title) throws IllegalArgumentException { + Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); + return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); + } + ++ // Paper start ++ @Override ++ public Merchant createMerchant(net.kyori.adventure.text.Component title) { ++ return new org.bukkit.craftbukkit.inventory.CraftMerchantCustom(title == null ? InventoryType.MERCHANT.defaultTitle() : title); ++ } ++ // Paper end + @Override ++ @Deprecated // Paper + public Merchant createMerchant(String title) { + return new CraftMerchantCustom(title == null ? InventoryType.MERCHANT.getDefaultTitle() : title); + } +@@ -1725,6 +1771,12 @@ public final class CraftServer implements Server { + return Thread.currentThread().equals(console.serverThread) || console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog) + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component motd() { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(new net.minecraft.network.chat.TextComponent(console.getMotd())); ++ } ++ // Paper end + @Override + public String getMotd() { + return console.getMotd(); +@@ -2153,5 +2205,15 @@ public final class CraftServer implements Server { + return null; + } + } ++ ++ // Paper start ++ private Iterable adventure$audiences; ++ @Override ++ public Iterable audiences() { ++ if (this.adventure$audiences == null) { ++ this.adventure$audiences = com.google.common.collect.Iterables.concat(java.util.Collections.singleton(this.getConsoleSender()), this.getOnlinePlayers()); ++ } ++ return this.adventure$audiences; ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 05aedca561919a12ced1925c5cc9af585bb04523..ce9f10f890a5866ab6208c7253b15b09fe323a81 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -19,6 +19,12 @@ public class Main { + public static boolean useConsole = true; + + public static void main(String[] args) { ++ // Paper start ++ final String warnWhenLegacyFormattingDetected = String.join(".", "net", "kyori", "adventure", "text", "warnWhenLegacyFormattingDetected"); ++ if (false && System.getProperty(warnWhenLegacyFormattingDetected) == null) { ++ System.setProperty(warnWhenLegacyFormattingDetected, String.valueOf(true)); ++ } ++ // Paper end + // Todo: Installation script + OptionParser parser = new OptionParser() { + { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +index 639577ab8b6467302a243c99ba5a4eede3aed655..940fef58f14e06213c7f305f67dcb8918976c03d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +@@ -70,6 +70,19 @@ public class CraftBeacon extends CraftBlockEntityState implem + this.getSnapshot().secondaryPower = (effect != null) ? MobEffect.byId(effect.getId()) : null; + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component customName() { ++ final BeaconBlockEntity be = this.getSnapshot(); ++ return be.name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.name) : null; ++ } ++ ++ @Override ++ public void customName(final net.kyori.adventure.text.Component customName) { ++ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); ++ } ++ // Paper end ++ + @Override + public String getCustomName() { + BeaconBlockEntity beacon = this.getSnapshot(); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java +index 16a0f6e390a7415635e3573c1f79f7d78e5ef859..b1edc96d7e0444e72b79f190982de1d1bb5987f3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java +@@ -32,6 +32,19 @@ public abstract class CraftContainer extends + this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component customName() { ++ final T be = this.getSnapshot(); ++ return be.hasCustomName() ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.getCustomName()) : null; ++ } ++ ++ @Override ++ public void customName(final net.kyori.adventure.text.Component customName) { ++ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); ++ } ++ // Paper end ++ + @Override + public String getCustomName() { + T container = this.getSnapshot(); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java +index add5b68d5fbd887e3fc2d226eff9ab00ed01ce73..2c3d6ba06d876df168aae4cc09b7b4400e2fa33d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java +@@ -16,6 +16,19 @@ public class CraftEnchantingTable extends CraftBlockEntityState implements Sign { + + // Lazily initialized only if requested: +- private String[] originalLines = null; +- private String[] lines = null; ++ // Paper start ++ private java.util.ArrayList originalLines = null; // ArrayList for RandomAccess ++ private java.util.ArrayList lines = null; // ArrayList for RandomAccess ++ // Paper end + + public CraftSign(final Block block) { + super(block, SignBlockEntity.class); +@@ -23,27 +25,52 @@ public class CraftSign extends CraftBlockEntityState implements + super(material, te); + } + ++ // Paper start + @Override +- public String[] getLines() { +- if (lines == null) { +- // Lazy initialization: +- SignBlockEntity sign = this.getSnapshot(); +- lines = new String[sign.messages.length]; +- System.arraycopy(revertComponents(sign.messages), 0, lines, 0, lines.length); +- originalLines = new String[lines.length]; +- System.arraycopy(lines, 0, originalLines, 0, originalLines.length); ++ public java.util.List lines() { ++ this.loadLines(); ++ return this.lines; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.Component line(int index) { ++ this.loadLines(); ++ return this.lines.get(index); ++ } ++ ++ @Override ++ public void line(int index, net.kyori.adventure.text.Component line) { ++ this.loadLines(); ++ this.lines.set(index, line); ++ } ++ ++ private void loadLines() { ++ if (lines != null) { ++ return; + } +- return lines; ++ ++ // Lazy initialization: ++ SignBlockEntity sign = this.getSnapshot(); ++ lines = io.papermc.paper.adventure.PaperAdventure.asAdventure(com.google.common.collect.Lists.newArrayList(sign.messages)); ++ originalLines = new java.util.ArrayList<>(lines); ++ } ++ // Paper end ++ @Override ++ public String[] getLines() { ++ this.loadLines(); ++ return this.lines.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).toArray(String[]::new); // Paper + } + + @Override + public String getLine(int index) throws IndexOutOfBoundsException { +- return getLines()[index]; ++ this.loadLines(); ++ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(this.lines.get(index)); // Paper + } + + @Override + public void setLine(int index, String line) throws IndexOutOfBoundsException { +- getLines()[index] = line; ++ this.loadLines(); ++ this.lines.set(index, line != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(line) : net.kyori.adventure.text.Component.empty()); // Paper + } + + @Override +@@ -71,16 +98,32 @@ public class CraftSign extends CraftBlockEntityState implements + super.applyTo(sign); + + if (lines != null) { +- for (int i = 0; i < lines.length; i++) { +- String line = (lines[i] == null) ? "" : lines[i]; +- if (line.equals(originalLines[i])) { ++ // Paper start ++ for (int i = 0; i < this.lines.size(); ++i) { ++ net.kyori.adventure.text.Component component = this.lines.get(i); ++ net.kyori.adventure.text.Component origComp = this.originalLines.get(i); ++ if (component.equals(origComp)) { + continue; // The line contents are still the same, skip. + } +- sign.messages[i] = CraftChatMessage.fromString(line)[0]; ++ sign.messages[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(component); + } ++ // Paper end + } + } + ++ // Paper start ++ public static Component[] sanitizeLines(java.util.List lines) { ++ Component[] components = new Component[4]; ++ for (int i = 0; i < 4; i++) { ++ if (i < lines.size() && lines.get(i) != null) { ++ components[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(lines.get(i)); ++ } else { ++ components[i] = new TextComponent(""); ++ } ++ } ++ return components; ++ } ++ // Paper end + public static Component[] sanitizeLines(String[] lines) { + Component[] components = new Component[4]; + +diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +index 089fe4a3458ed3106fa214f89a7004a5d3c6bb95..af986adfdb547cb61fbd52f0f89858f1a9e52cc3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +@@ -80,4 +80,11 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co + public boolean isConversing() { + return conversationTracker.isConversing(); + } ++ ++ // Paper start ++ @Override ++ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { ++ this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); ++ } ++ // 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 fd473d213f4050f420bd7d729fe0df757d5398bc..b1ffe6c7a5915f00a476e88f3a38349b740b4910 100644 +--- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java ++++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +@@ -187,6 +187,12 @@ public class CraftEnchantment extends Enchantment { + CraftEnchantment ench = (CraftEnchantment) other; + return !target.isCompatibleWith(ench.target); + } ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName(int level) { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); ++ } ++ // Paper end + + public net.minecraft.world.item.enchantment.Enchantment getHandle() { + return target; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index eb61c803cf74c5ca2c51d5027a02ed3db6b53096..53c231925ef1b17e48c5863570e3c54124874621 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -768,6 +768,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return getHandle().getVehicle().getBukkitEntity(); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component customName() { ++ final Component name = this.getHandle().getCustomName(); ++ return name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(name) : null; ++ } ++ ++ @Override ++ public void customName(final net.kyori.adventure.text.Component customName) { ++ this.getHandle().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); ++ } ++ // Paper end ++ + @Override + public void setCustomName(String name) { + // sane limit for name length +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index 7c200e43bdc170ecf8b8fbfadd7bb38c66133443..b5c0f3d91cf451a972f0cf293db03a306073c493 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -317,9 +317,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + container = CraftEventFactory.callInventoryOpenEvent(player, container); + if (container == null) return; + +- String title = container.getBukkitView().getTitle(); ++ //String title = container.getBukkitView().getTitle(); // Paper - comment ++ net.kyori.adventure.text.Component adventure$title = container.getBukkitView().title(); // Paper ++ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper + +- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); ++ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment ++ player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + getHandle().containerMenu = container; + getHandle().containerMenu.addSlotListener(player); + } +@@ -388,8 +391,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + + // Now open the window + MenuType windowType = CraftContainer.getNotchInventoryType(inventory.getTopInventory()); +- String title = inventory.getTitle(); +- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); ++ ++ //String title = inventory.getTitle(); // Paper - comment ++ net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper ++ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper ++ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment ++ player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + player.containerMenu = container; + player.containerMenu.addSlotListener(player); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05b891167b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -238,14 +238,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + @Override + public String getDisplayName() { ++ if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper + return getHandle().displayName; + } + + @Override + public void setDisplayName(final String name) { ++ this.getHandle().adventure$displayName = name != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(name) : net.kyori.adventure.text.Component.text(this.getName()); // Paper + getHandle().displayName = name == null ? getName() : name; + } + ++ // Paper start ++ @Override ++ public void playerListName(net.kyori.adventure.text.Component name) { ++ getHandle().listName = name == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(name); ++ for (ServerPlayer player : server.getHandle().players) { ++ if (player.getBukkitEntity().canSee(this)) { ++ player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME, getHandle())); ++ } ++ } ++ } ++ @Override ++ public net.kyori.adventure.text.Component playerListName() { ++ return getHandle().listName == null ? net.kyori.adventure.text.Component.text(getName()) : io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().listName); ++ } ++ @Override ++ public net.kyori.adventure.text.Component playerListHeader() { ++ return playerListHeader; ++ } ++ @Override ++ public net.kyori.adventure.text.Component playerListFooter() { ++ return playerListFooter; ++ } ++ // Paper end + @Override + public String getPlayerListName() { + return getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(getHandle().listName); +@@ -264,35 +289,35 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + } + +- private Component playerListHeader; +- private Component playerListFooter; ++ private net.kyori.adventure.text.Component playerListHeader; // Paper - Adventure ++ private net.kyori.adventure.text.Component playerListFooter; // Paper - Adventure + + @Override + public String getPlayerListHeader() { +- return (playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader); ++ return (playerListHeader == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListHeader); // Paper - Adventure + } + + @Override + public String getPlayerListFooter() { +- return (playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter); ++ return (playerListFooter == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListFooter); // Paper - Adventure + } + + @Override + public void setPlayerListHeader(String header) { +- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); ++ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure + updatePlayerListHeaderFooter(); + } + + @Override + public void setPlayerListFooter(String footer) { +- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); ++ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure + updatePlayerListHeaderFooter(); + } + + @Override + public void setPlayerListHeaderFooter(String header, String footer) { +- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); +- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); ++ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure ++ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure + updatePlayerListHeaderFooter(); + } + +@@ -300,8 +325,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + if (getHandle().connection == null) return; + + ClientboundTabListPacket packet = new ClientboundTabListPacket(); +- packet.header = (this.playerListHeader == null) ? new TextComponent("") : this.playerListHeader; +- packet.footer = (this.playerListFooter == null) ? new TextComponent("") : this.playerListFooter; ++ packet.header = (this.playerListHeader == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListHeader); // Paper - Adventure ++ packet.footer = (this.playerListFooter == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListFooter); // Paper - Adventure + getHandle().connection.send(packet); + } + +@@ -333,6 +358,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + getHandle().connection.disconnect(message == null ? "" : message); + } + ++ // Paper start ++ @Override ++ public void kick(final net.kyori.adventure.text.Component message) { ++ org.spigotmc.AsyncCatcher.catchOp("player kick"); ++ final ServerGamePacketListenerImpl connection = this.getHandle().connection; ++ if (connection != null) { ++ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); ++ } ++ } ++ // Paper end ++ + @Override + public void setCompassTarget(Location loc) { + if (getHandle().connection == null) return; +@@ -559,6 +595,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + getHandle().connection.send(packet); + } + ++ // Paper start ++ @Override ++ public void sendSignChange(Location loc, List lines) { ++ this.sendSignChange(loc, lines, org.bukkit.DyeColor.BLACK); ++ } ++ @Override ++ public void sendSignChange(Location loc, List lines, DyeColor dyeColor) { ++ if (getHandle().connection == null) { ++ return; ++ } ++ if (lines == null) { ++ lines = new java.util.ArrayList<>(4); ++ } ++ Validate.notNull(loc, "Location cannot be null"); ++ Validate.notNull(dyeColor, "DyeColor cannot be null"); ++ if (lines.size() < 4) { ++ throw new IllegalArgumentException("Must have at least 4 lines"); ++ } ++ Component[] components = CraftSign.sanitizeLines(lines); ++ this.sendSignChange0(components, loc, dyeColor); ++ } ++ ++ private void sendSignChange0(Component[] components, Location loc, DyeColor dyeColor) { ++ SignBlockEntity sign = new SignBlockEntity(); ++ sign.setPosition(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); ++ sign.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData())); ++ System.arraycopy(components, 0, sign.messages, 0, sign.messages.length); ++ ++ getHandle().connection.send(sign.getUpdatePacket()); ++ } ++ // Paper end + @Override + public void sendSignChange(Location loc, String[] lines) { + sendSignChange(loc, lines, DyeColor.BLACK); +@@ -581,12 +648,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + Component[] components = CraftSign.sanitizeLines(lines); +- SignBlockEntity sign = new SignBlockEntity(); +- sign.setPosition(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); +- sign.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData())); +- System.arraycopy(components, 0, sign.messages, 0, sign.messages.length); ++ /*TileEntitySign sign = new TileEntitySign(); // Paper ++ sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); ++ sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); ++ System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); + +- getHandle().connection.send(sign.getUpdatePacket()); ++ getHandle().playerConnection.sendPacket(sign.getUpdatePacket());*/ // Paper ++ this.sendSignChange0(components, loc, dyeColor); // Paper + } + + @Override +@@ -1686,6 +1754,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return (getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : getHandle().clientViewDistance; + } + ++ // Paper start ++ @Override ++ public java.util.Locale locale() { ++ return getHandle().adventure$locale; ++ } ++ // Paper end + @Override + public int getPing() { + return getHandle().latency; +@@ -1714,6 +1788,138 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + getInventory().setItemInMainHand(hand); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() { ++ return this.getHandle().adventure$displayName; ++ } ++ ++ @Override ++ public void displayName(final net.kyori.adventure.text.Component displayName) { ++ this.getHandle().adventure$displayName = displayName != null ? displayName : net.kyori.adventure.text.Component.text(this.getName()); ++ this.getHandle().displayName = null; ++ } ++ ++ @Override ++ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { ++ final ClientboundChatPacket packet = new ClientboundChatPacket(null, type == net.kyori.adventure.audience.MessageType.CHAT ? net.minecraft.network.chat.ChatType.CHAT : net.minecraft.network.chat.ChatType.SYSTEM, identity.uuid()); ++ packet.adventure$message = message; ++ this.getHandle().connection.send(packet); ++ } ++ ++ @Override ++ public void sendActionBar(final net.kyori.adventure.text.Component message) { ++ final ClientboundSetTitlesPacket packet = new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.ACTIONBAR, null); ++ packet.adventure$text = message; ++ this.getHandle().connection.send(packet); ++ } ++ ++ @Override ++ public void sendPlayerListHeader(final net.kyori.adventure.text.Component header) { ++ this.playerListHeader = header; ++ this.adventure$sendPlayerListHeaderAndFooter(); ++ } ++ ++ @Override ++ public void sendPlayerListFooter(final net.kyori.adventure.text.Component footer) { ++ this.playerListFooter = footer; ++ this.adventure$sendPlayerListHeaderAndFooter(); ++ } ++ ++ @Override ++ public void sendPlayerListHeaderAndFooter(final net.kyori.adventure.text.Component header, final net.kyori.adventure.text.Component footer) { ++ this.playerListHeader = header; ++ this.playerListFooter = footer; ++ this.adventure$sendPlayerListHeaderAndFooter(); ++ } ++ ++ private void adventure$sendPlayerListHeaderAndFooter() { ++ final ServerGamePacketListenerImpl connection = this.getHandle().connection; ++ if (connection == null) return; ++ final ClientboundTabListPacket packet = new ClientboundTabListPacket(); ++ packet.adventure$header = (this.playerListHeader == null) ? net.kyori.adventure.text.Component.empty() : this.playerListHeader; ++ packet.adventure$footer = (this.playerListFooter == null) ? net.kyori.adventure.text.Component.empty() : this.playerListFooter; ++ connection.send(packet); ++ } ++ ++ @Override ++ public void showTitle(final net.kyori.adventure.title.Title title) { ++ final ServerGamePacketListenerImpl connection = this.getHandle().connection; ++ final net.kyori.adventure.title.Title.Times times = title.times(); ++ if (times != null) { ++ connection.send(new ClientboundSetTitlesPacket(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut()))); ++ } ++ final ClientboundSetTitlesPacket sp = new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.SUBTITLE, null); ++ sp.adventure$text = title.subtitle(); ++ connection.send(sp); ++ final ClientboundSetTitlesPacket tp = new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.TITLE, null); ++ tp.adventure$text = title.title(); ++ connection.send(tp); ++ } ++ ++ private static int ticks(final java.time.Duration duration) { ++ if (duration == null) { ++ return -1; ++ } ++ return (int) (duration.toMillis() / 50L); ++ } ++ ++ @Override ++ public void clearTitle() { ++ this.getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.CLEAR, null)); ++ } ++ ++ // resetTitle implemented above ++ ++ @Override ++ public void showBossBar(final net.kyori.adventure.bossbar.BossBar bar) { ++ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerShow(this); ++ } ++ ++ @Override ++ public void hideBossBar(final net.kyori.adventure.bossbar.BossBar bar) { ++ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerHide(this); ++ } ++ ++ @Override ++ public void playSound(final net.kyori.adventure.sound.Sound sound) { ++ final Vec3 pos = this.getHandle().position(); ++ this.playSound(sound, pos.x, pos.y, pos.z); ++ } ++ ++ @Override ++ public void playSound(final net.kyori.adventure.sound.Sound sound, final double x, final double y, final double z) { ++ final ResourceLocation name = io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.name()); ++ final java.util.Optional event = net.minecraft.core.Registry.SOUND_EVENT.getOptional(name); ++ if (event.isPresent()) { ++ this.getHandle().connection.send(new ClientboundSoundPacket(event.get(), io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), x, y, z, sound.volume(), sound.pitch())); ++ } else { ++ this.getHandle().connection.send(new ClientboundCustomSoundPacket(name, io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), new Vec3(x, y, z), sound.volume(), sound.pitch())); ++ } ++ } ++ ++ @Override ++ public void stopSound(final net.kyori.adventure.sound.SoundStop stop) { ++ this.getHandle().connection.send(new ClientboundStopSoundPacket( ++ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.sound()), ++ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.source()) ++ )); ++ } ++ ++ @Override ++ public void openBook(final net.kyori.adventure.inventory.Book book) { ++ final java.util.Locale locale = this.getHandle().adventure$locale; ++ final net.minecraft.world.item.ItemStack item = io.papermc.paper.adventure.PaperAdventure.asItemStack(book, locale); ++ final ServerPlayer player = this.getHandle(); ++ final ServerGamePacketListenerImpl connection = player.connection; ++ final net.minecraft.world.entity.player.Inventory inventory = player.inventory; ++ final int slot = inventory.items.size() + inventory.selected; ++ connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, item)); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND)); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, inventory.getSelected())); ++ } ++ // Paper end ++ + // Spigot start + private final Player.Spigot spigot = new Player.Spigot() + { +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index abd65693aca1964b65d091e633a36c97513c1d69..7fde1bb7587e567270e3f936381c6d361870211f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -776,9 +776,9 @@ public class CraftEventFactory { + return event; + } + +- public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, List drops, String deathMessage, boolean keepInventory) { ++ public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, List drops, net.kyori.adventure.text.Component deathMessage, String stringDeathMessage, boolean keepInventory) { // Paper - Adventure + CraftPlayer entity = victim.getBukkitEntity(); +- PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage); ++ PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure + event.setKeepInventory(keepInventory); + org.bukkit.World world = entity.getWorld(); + Bukkit.getServer().getPluginManager().callEvent(event); +@@ -802,7 +802,7 @@ public class CraftEventFactory { + * Server methods + */ + public static ServerListPingEvent callServerListPingEvent(Server craftServer, InetAddress address, String motd, int numPlayers, int maxPlayers) { +- ServerListPingEvent event = new ServerListPingEvent(address, motd, numPlayers, maxPlayers); ++ ServerListPingEvent event = new ServerListPingEvent(address, craftServer.motd(), numPlayers, maxPlayers); // Paper - Adventure + craftServer.getPluginManager().callEvent(event); + return event; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +index a393bdae6ef588289c8814a1896146a993c92e71..680c7818a7097355158eb76662ecebbae6dd6637 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +@@ -1,6 +1,5 @@ + package org.bukkit.craftbukkit.inventory; + +-import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; + import net.minecraft.world.Container; + import net.minecraft.world.entity.player.Player; +@@ -38,6 +37,7 @@ public class CraftContainer extends AbstractContainerMenu { + + private final InventoryView view; + private InventoryType cachedType; ++ private net.kyori.adventure.text.Component adventure$title; // Paper + private String cachedTitle; + private AbstractContainerMenu delegate; + private final int cachedSize; +@@ -49,7 +49,9 @@ public class CraftContainer extends AbstractContainerMenu { + Container top = ((CraftInventory) view.getTopInventory()).getInventory(); + net.minecraft.world.entity.player.Inventory bottom = (net.minecraft.world.entity.player.Inventory) ((CraftInventory) view.getBottomInventory()).getInventory(); + cachedType = view.getType(); +- cachedTitle = view.getTitle(); ++ this.adventure$title = view.title(); // Paper ++ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper ++ //cachedTitle = view.getTitle(); // Paper - comment + cachedSize = getSize(); + setupSlots(top, bottom, player); + } +@@ -76,6 +78,13 @@ public class CraftContainer extends AbstractContainerMenu { + return inventory.getType(); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component title() { ++ return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).title() : net.kyori.adventure.text.Component.text(inventory.getType().getDefaultTitle()); ++ } ++ // Paper end ++ + @Override + public String getTitle() { + return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).getTitle() : inventory.getType().getDefaultTitle(); +@@ -94,7 +103,8 @@ public class CraftContainer extends AbstractContainerMenu { + + @Override + public boolean isSynched(Player player) { +- if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { ++ if (cachedType == view.getType() && cachedSize == getSize() && this.adventure$title.equals(view.title())) { // Paper ++ //if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { // Paper - comment + return true; + } + // If the window type has changed for some reason, update the player +@@ -102,7 +112,9 @@ public class CraftContainer extends AbstractContainerMenu { + // as good a place as any to put something like this. + boolean typeChanged = (cachedType != view.getType()); + cachedType = view.getType(); +- cachedTitle = view.getTitle(); ++ this.adventure$title = view.title(); // Paper ++ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper ++ //cachedTitle = view.getTitle(); // Paper - comment + if (view.getPlayer() instanceof CraftPlayer) { + CraftPlayer player1 = (CraftPlayer) view.getPlayer(); + MenuType type = getNotchInventoryType(view.getTopInventory()); +@@ -114,7 +126,8 @@ public class CraftContainer extends AbstractContainerMenu { + setupSlots(top, bottom, player1.getHandle()); + } + int size = getSize(); +- player1.getHandle().connection.send(new ClientboundOpenScreenPacket(this.containerId, type, new TextComponent(cachedTitle))); ++ player1.getHandle().connection.send(new ClientboundOpenScreenPacket(this.containerId, type, io.papermc.paper.adventure.PaperAdventure.asVanilla(this.adventure$title))); // Paper ++ //player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, new ChatComponentText(cachedTitle))); // Paper - comment + player1.updateInventory(); + } + return true; +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java +index 397cd9651381a8a0ddb4ca173690e9b80428b182..46805a25c0273b76c19a3bbd40078d78c5379f43 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java +@@ -19,6 +19,12 @@ public class CraftInventoryCustom extends CraftInventory { + super(new MinecraftInventory(owner, type)); + } + ++ // Paper start ++ public CraftInventoryCustom(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ super(new MinecraftInventory(owner, type, title)); ++ } ++ // Paper end ++ + public CraftInventoryCustom(InventoryHolder owner, InventoryType type, String title) { + super(new MinecraftInventory(owner, type, title)); + } +@@ -27,6 +33,12 @@ public class CraftInventoryCustom extends CraftInventory { + super(new MinecraftInventory(owner, size)); + } + ++ // Paper start ++ public CraftInventoryCustom(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { ++ super(new MinecraftInventory(owner, size, title)); ++ } ++ // Paper end ++ + public CraftInventoryCustom(InventoryHolder owner, int size, String title) { + super(new MinecraftInventory(owner, size, title)); + } +@@ -36,9 +48,17 @@ public class CraftInventoryCustom extends CraftInventory { + private int maxStack = MAX_STACK; + private final List viewers; + private final String title; ++ private final net.kyori.adventure.text.Component adventure$title; // Paper + private InventoryType type; + private final InventoryHolder owner; + ++ // Paper start ++ public MinecraftInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ this(owner, type.getDefaultSize(), title); ++ this.type = type; ++ } ++ // Paper end ++ + public MinecraftInventory(InventoryHolder owner, InventoryType type) { + this(owner, type.getDefaultSize(), type.getDefaultTitle()); + this.type = type; +@@ -57,11 +77,24 @@ public class CraftInventoryCustom extends CraftInventory { + Validate.notNull(title, "Title cannot be null"); + this.items = NonNullList.a(size, ItemStack.EMPTY); + this.title = title; ++ this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(title); + this.viewers = new ArrayList(); + this.owner = owner; + this.type = InventoryType.CHEST; + } + ++ // Paper start ++ public MinecraftInventory(final InventoryHolder owner, final int size, final net.kyori.adventure.text.Component title) { ++ Validate.notNull(title, "Title cannot be null"); ++ this.items = NonNullList.a(size, ItemStack.EMPTY); ++ this.title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); ++ this.adventure$title = title; ++ this.viewers = new ArrayList(); ++ this.owner = owner; ++ this.type = InventoryType.CHEST; ++ } ++ // Paper end ++ + @Override + public int getContainerSize() { + return items.size(); +@@ -183,6 +216,12 @@ public class CraftInventoryCustom extends CraftInventory { + return null; + } + ++ // Paper start ++ public net.kyori.adventure.text.Component title() { ++ return this.adventure$title; ++ } ++ // Paper end ++ + public String getTitle() { + return title; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java +index 326e8eb49e67ccfbf8f9b23bd6f03ea3576b9d35..945a80ca026c12e16a7ac5bebe56f846a437f847 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java +@@ -64,6 +64,13 @@ public class CraftInventoryView extends InventoryView { + return CraftItemStack.asCraftMirror(container.getSlot(slot).getItem()); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component title() { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.container.getTitle()); ++ } ++ // Paper end ++ + @Override + public String getTitle() { + return CraftChatMessage.fromComponent(container.getTitle()); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index 89a3617068421bb86baf4e8bfd9df2d0626adff7..32fa5ca0df07466e40817341d85d359b282f3078 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -334,4 +334,17 @@ public final class CraftItemFactory implements ItemFactory { + public Material updateMaterial(ItemMeta meta, Material material) throws IllegalArgumentException { + return ((CraftMetaItem) meta).updateMaterial(material); + } ++ ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final ItemStack item, final java.util.function.UnaryOperator op) { ++ final net.minecraft.nbt.CompoundTag tag = CraftItemStack.asNMSCopy(item).getTag(); ++ return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowItem.of(item.getType().getKey(), item.getAmount(), io.papermc.paper.adventure.PaperAdventure.asBinaryTagHolder(tag)))); ++ } ++ ++ @Override ++ public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +index 71136bb009d6c8c92595f957ee7680a771ea9a63..306c6483708ae1b41bd16f122d36beec1916a776 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +@@ -14,10 +14,17 @@ import org.apache.commons.lang.Validate; + + public class CraftMerchantCustom extends CraftMerchant { + ++ @Deprecated // Paper - Adventure + public CraftMerchantCustom(String title) { + super(new MinecraftMerchant(title)); + getMerchant().craftMerchant = this; + } ++ // Paper start ++ public CraftMerchantCustom(net.kyori.adventure.text.Component title) { ++ super(new MinecraftMerchant(title)); ++ getMerchant().craftMerchant = this; ++ } ++ // Paper end + + @Override + public String toString() { +@@ -37,10 +44,17 @@ public class CraftMerchantCustom extends CraftMerchant { + private Level tradingWorld; + protected CraftMerchant craftMerchant; + ++ @Deprecated // Paper - Adventure + public MinecraftMerchant(String title) { + Validate.notNull(title, "Title cannot be null"); + this.title = new TextComponent(title); + } ++ // Paper start ++ public MinecraftMerchant(net.kyori.adventure.text.Component title) { ++ Validate.notNull(title, "Title cannot be null"); ++ this.title = io.papermc.paper.adventure.PaperAdventure.asVanilla(title); ++ } ++ // Paper end + + @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 6dba12c4f58a462c8d466461eb8b804dd045766d..a592d4a286a775a61192dde2a4d21a0681090415 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +@@ -1,8 +1,9 @@ + package org.bukkit.craftbukkit.inventory; + + import com.google.common.collect.ImmutableList; +-import com.google.common.collect.ImmutableMap.Builder; + import com.google.common.collect.Lists; ++ ++import com.google.common.collect.ImmutableMap; // Paper + import java.util.ArrayList; + import java.util.Arrays; + import java.util.List; +@@ -17,9 +18,12 @@ import org.bukkit.craftbukkit.util.CraftChatMessage; + import org.bukkit.craftbukkit.util.CraftMagicNumbers; + import org.bukkit.inventory.meta.BookMeta; + import org.bukkit.inventory.meta.BookMeta.Generation; ++import org.checkerframework.checker.nullness.qual.NonNull; + + // Spigot start + import static org.spigotmc.ValidateUtils.*; ++ ++import BookMetaBuilder; + import java.util.AbstractList; + import net.md_5.bungee.api.chat.BaseComponent; + import net.md_5.bungee.chat.ComponentSerializer; +@@ -269,6 +273,141 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + this.generation = (generation == null) ? null : generation.ordinal(); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component title() { ++ return this.title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.title); ++ } ++ ++ @Override ++ public org.bukkit.inventory.meta.BookMeta title(net.kyori.adventure.text.Component title) { ++ this.setTitle(title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title)); ++ return this; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.Component author() { ++ return this.author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.author); ++ } ++ ++ @Override ++ public org.bukkit.inventory.meta.BookMeta author(net.kyori.adventure.text.Component author) { ++ this.setAuthor(author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author)); ++ return this; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.Component page(final int page) { ++ Validate.isTrue(isValidPage(page), "Invalid page number"); ++ return this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(pages.get(page - 1)) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(pages.get(page - 1)); ++ } ++ ++ @Override ++ public void page(final int page, net.kyori.adventure.text.Component data) { ++ if (!isValidPage(page)) { ++ throw new IllegalArgumentException("Invalid page number " + page + "/" + pages.size()); ++ } ++ if (data == null) { ++ data = net.kyori.adventure.text.Component.empty(); ++ } ++ pages.set(page - 1, this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(data) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(data)); ++ } ++ ++ @Override ++ public List pages() { ++ if (this.pages == null) return ImmutableList.of(); ++ if (this instanceof CraftMetaBookSigned) ++ return pages.stream().map(net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson()::deserialize).collect(ImmutableList.toImmutableList()); ++ else ++ return pages.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::deserialize).collect(ImmutableList.toImmutableList()); ++ } ++ ++ @Override ++ public BookMeta pages(List pages) { ++ if (this.pages != null) this.pages.clear(); ++ for (net.kyori.adventure.text.Component page : pages) { ++ addPages(page); ++ } ++ return this; ++ } ++ ++ @Override ++ public BookMeta pages(net.kyori.adventure.text.Component... pages) { ++ if (this.pages != null) this.pages.clear(); ++ addPages(pages); ++ return this; ++ } ++ ++ @Override ++ public void addPages(net.kyori.adventure.text.Component... pages) { ++ if (this.pages == null) this.pages = new ArrayList<>(); ++ for (net.kyori.adventure.text.Component page : pages) { ++ if (this.pages.size() >= MAX_PAGES) { ++ return; ++ } ++ ++ if (page == null) { ++ page = net.kyori.adventure.text.Component.empty(); ++ } ++ ++ this.pages.add(this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(page) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(page)); ++ } ++ } ++ ++ private CraftMetaBook(net.kyori.adventure.text.Component title, net.kyori.adventure.text.Component author, List pages) { ++ super((org.bukkit.craftbukkit.inventory.CraftMetaItem) org.bukkit.Bukkit.getItemFactory().getItemMeta(org.bukkit.Material.WRITABLE_BOOK)); ++ this.title = title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); ++ this.author = author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author); ++ this.pages = pages.subList(0, Math.min(MAX_PAGES, pages.size())).stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).collect(java.util.stream.Collectors.toList()); ++ } ++ ++ static final class CraftMetaBookBuilder implements BookMetaBuilder { ++ private net.kyori.adventure.text.Component title = null; ++ private net.kyori.adventure.text.Component author = null; ++ private final List pages = new java.util.ArrayList<>(); ++ ++ @Override ++ public BookMetaBuilder title(net.kyori.adventure.text.Component title) { ++ this.title = title; ++ return this; ++ } ++ ++ @Override ++ public BookMetaBuilder author(net.kyori.adventure.text.Component author) { ++ this.author = author; ++ return this; ++ } ++ ++ @Override ++ public BookMetaBuilder addPage(net.kyori.adventure.text.Component page) { ++ this.pages.add(page); ++ return this; ++ } ++ ++ @Override ++ public BookMetaBuilder pages(net.kyori.adventure.text.Component... pages) { ++ java.util.Collections.addAll(this.pages, pages); ++ return this; ++ } ++ ++ @Override ++ public BookMetaBuilder pages(java.util.Collection pages) { ++ this.pages.addAll(pages); ++ return this; ++ } ++ ++ @Override ++ public BookMeta build() { ++ return new CraftMetaBook(title, author, pages); ++ } ++ } ++ ++ @Override ++ public BookMetaBuilder toBuilder() { ++ return new CraftMetaBookBuilder(); ++ } ++ ++ // Paper end + @Override + public String getPage(final int page) { + Validate.isTrue(isValidPage(page), "Invalid page number"); +@@ -413,7 +552,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + } + + @Override +- Builder serialize(Builder builder) { ++ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { + super.serialize(builder); + + if (hasTitle()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java +index 00445fc7373c70f4cecc4114f9bcfb4b6f27c0e8..0cf60eb9b6ba1a79c9b603c4349debd478101f9a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java +@@ -1,6 +1,6 @@ + package org.bukkit.craftbukkit.inventory; + +-import com.google.common.collect.ImmutableMap.Builder; ++import com.google.common.collect.ImmutableMap; // Paper + import java.util.Map; + import net.minecraft.nbt.CompoundTag; + import org.bukkit.Material; +@@ -84,7 +84,7 @@ class CraftMetaBookSigned extends CraftMetaBook implements BookMeta { + } + + @Override +- Builder serialize(Builder builder) { ++ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { + super.serialize(builder); + return builder; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 2e819849e83967d751f7b0612a7cf4edb5a7264b..cca04daf84e506382365c0ba945cb024bd4d4475 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -744,6 +744,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() { ++ return displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(displayName); ++ } ++ ++ @Override ++ public void displayName(final net.kyori.adventure.text.Component displayName) { ++ this.displayName = displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(displayName); ++ } ++ // Paper end ++ + @Override + public String getDisplayName() { + return CraftChatMessage.fromJSONComponent(displayName); +@@ -779,6 +791,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return this.lore != null && !this.lore.isEmpty(); + } + ++ // Paper start ++ @Override ++ public List lore() { ++ return this.lore != null ? io.papermc.paper.adventure.PaperAdventure.asAdventureFromJson(this.lore) : null; ++ } ++ ++ @Override ++ public void lore(final List lore) { ++ this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asJson(lore) : null; ++ } ++ // Paper end ++ + @Override + public boolean hasRepairCost() { + return repairCost > 0; +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java +index ed4415f6dd588c08c922efd5beebb3b124beb9d6..78a7ac47f20e84ccd67ff44d0bc7a2f2faa0d476 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java +@@ -12,6 +12,13 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve + return new CraftInventoryCustom(holder, type); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ return new CraftInventoryCustom(owner, type, title); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { + return new CraftInventoryCustom(owner, type, title); +@@ -21,6 +28,12 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve + return new CraftInventoryCustom(owner, size); + } + ++ // Paper start ++ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { ++ return new CraftInventoryCustom(owner, size, title); ++ } ++ // Paper end ++ + public Inventory createInventory(InventoryHolder owner, int size, String title) { + return new CraftInventoryCustom(owner, size, title); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b833806a0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +@@ -43,6 +43,17 @@ public final class CraftInventoryCreator { + return converterMap.get(type).createInventory(holder, type); + } + ++ // Paper start ++ public Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title) { ++ // Paper start ++ if (holder != null) { ++ return DEFAULT_CONVERTER.createInventory(holder, type, title); ++ } ++ //noinspection ConstantConditions // Paper end ++ return converterMap.get(type).createInventory(holder, type, title); ++ } ++ // Paper end ++ + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { + return converterMap.get(type).createInventory(holder, type, title); + } +@@ -51,6 +62,12 @@ public final class CraftInventoryCreator { + return DEFAULT_CONVERTER.createInventory(holder, size); + } + ++ // Paper start ++ public Inventory createInventory(InventoryHolder holder, int size, net.kyori.adventure.text.Component title) { ++ return DEFAULT_CONVERTER.createInventory(holder, size, title); ++ } ++ // Paper end ++ + public Inventory createInventory(InventoryHolder holder, int size, String title) { + return DEFAULT_CONVERTER.createInventory(holder, size, title); + } +@@ -59,6 +76,10 @@ public final class CraftInventoryCreator { + + Inventory createInventory(InventoryHolder holder, InventoryType type); + ++ // Paper start ++ Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title); ++ // Paper end ++ + Inventory createInventory(InventoryHolder holder, InventoryType type, String title); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java +index 0395a6235d62126540e370d6ef77e6966c50ca1d..3ef9742a68084d159ea8ed5709298f9863e04a67 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java +@@ -31,6 +31,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat + return getInventory(getTileEntity()); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ Container te = getTileEntity(); ++ if (te instanceof RandomizableContainerBlockEntity) { ++ ((RandomizableContainerBlockEntity) te).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); ++ } ++ ++ return getInventory(te); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { + Container te = getTileEntity(); +@@ -54,6 +66,15 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat + return furnace; + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ Container tileEntity = getTileEntity(); ++ ((AbstractFurnaceBlockEntity) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); ++ return getInventory(tileEntity); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { + Container tileEntity = getTileEntity(); +@@ -74,6 +95,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat + return new BrewingStandBlockEntity(); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ // BrewingStand does not extend TileEntityLootable ++ Container tileEntity = getTileEntity(); ++ if (tileEntity instanceof BrewingStandBlockEntity) { ++ ((BrewingStandBlockEntity) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); ++ } ++ return getInventory(tileEntity); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { + // BrewingStand does not extend TileEntityLootable +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java +index d5ebb11447a8effa41138a13874fd3e5246dfe71..96ba508c87336d012c1ed5aa982588f55782a2fe 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java +@@ -30,6 +30,21 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective + return objective.getName(); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(objective.getDisplayName()); ++ } ++ @Override ++ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { ++ if (displayName == null) { ++ displayName = net.kyori.adventure.text.Component.empty(); ++ } ++ CraftScoreboard scoreboard = checkState(); ++ objective.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); ++ } ++ // Paper end + @Override + public String getDisplayName() throws IllegalStateException { + CraftScoreboard scoreboard = checkState(); +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +index af160d3bdb82f07c6c836a438b8ab37b803c29e2..4c93be31fd95d731327479519ecb34a08785c1ca 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +@@ -27,6 +27,27 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + public CraftObjective registerNewObjective(String name, String criteria) throws IllegalArgumentException { + return registerNewObjective(name, criteria, name); + } ++ // Paper start ++ @Override ++ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName) { ++ return registerNewObjective(name, criteria, displayName, org.bukkit.scoreboard.RenderType.INTEGER); ++ } ++ @Override ++ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName, RenderType renderType) { ++ if (displayName == null) { ++ displayName = net.kyori.adventure.text.Component.empty(); ++ } ++ Validate.notNull(name, "Objective name cannot be null"); ++ Validate.notNull(criteria, "Criteria cannot be null"); ++ Validate.notNull(displayName, "Display name cannot be null"); ++ Validate.notNull(renderType, "RenderType cannot be null"); ++ Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); ++ Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); ++ CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); ++ net.minecraft.world.scores.Objective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); ++ return new CraftObjective(this, objective); ++ } ++ // Paper end + + @Override + public CraftObjective registerNewObjective(String name, String criteria, String displayName) throws IllegalArgumentException { +@@ -35,7 +56,7 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + + @Override + public CraftObjective registerNewObjective(String name, String criteria, String displayName, RenderType renderType) throws IllegalArgumentException { +- Validate.notNull(name, "Objective name cannot be null"); ++ /*Validate.notNull(name, "Objective name cannot be null"); // Paper + Validate.notNull(criteria, "Criteria cannot be null"); + Validate.notNull(displayName, "Display name cannot be null"); + Validate.notNull(renderType, "RenderType cannot be null"); +@@ -44,8 +65,9 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); + + CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); +- net.minecraft.world.scores.Objective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); +- return new CraftObjective(this, objective); ++ ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); ++ return new CraftObjective(this, objective);*/ // Paper ++ return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +index f5237ff19d8b26be0b762659ad0ea6887205b3f9..7ebcba4ada42f5599d56cfdeb75dbf62f2a09b78 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +@@ -28,6 +28,55 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { + + return team.getName(); + } ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getDisplayName()); ++ } ++ @Override ++ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { ++ if (displayName == null) displayName = net.kyori.adventure.text.Component.empty(); ++ CraftScoreboard scoreboard = checkState(); ++ team.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); ++ } ++ @Override ++ public net.kyori.adventure.text.Component prefix() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPlayerPrefix()); ++ } ++ @Override ++ public void prefix(net.kyori.adventure.text.Component prefix) throws IllegalStateException, IllegalArgumentException { ++ if (prefix == null) prefix = net.kyori.adventure.text.Component.empty(); ++ CraftScoreboard scoreboard = checkState(); ++ team.setPlayerPrefix(io.papermc.paper.adventure.PaperAdventure.asVanilla(prefix)); ++ } ++ @Override ++ public net.kyori.adventure.text.Component suffix() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPlayerSuffix()); ++ } ++ @Override ++ public void suffix(net.kyori.adventure.text.Component suffix) throws IllegalStateException, IllegalArgumentException { ++ if (suffix == null) suffix = net.kyori.adventure.text.Component.empty(); ++ CraftScoreboard scoreboard = checkState(); ++ team.setPlayerSuffix(io.papermc.paper.adventure.PaperAdventure.asVanilla(suffix)); ++ } ++ @Override ++ public net.kyori.adventure.text.format.TextColor color() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ if (team.getColor().getHexValue() == null) throw new IllegalStateException("Team colors must have hex values"); ++ net.kyori.adventure.text.format.TextColor color = net.kyori.adventure.text.format.TextColor.color(team.getColor().getHexValue()); ++ if (!(color instanceof net.kyori.adventure.text.format.NamedTextColor)) throw new IllegalStateException("Team doesn't have a NamedTextColor"); ++ return (net.kyori.adventure.text.format.NamedTextColor) color; ++ } ++ @Override ++ public void color(net.kyori.adventure.text.format.NamedTextColor color) { ++ if (color == null) color = net.kyori.adventure.text.format.NamedTextColor.WHITE; ++ CraftScoreboard scoreboard = checkState(); ++ team.setColor(io.papermc.paper.adventure.PaperAdventure.asVanilla(color)); ++ } ++ // Paper end + + @Override + public String getDisplayName() throws IllegalStateException { +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +index 35e6ce5f33b3d6b86c3654e6a207e26aa44badb5..b27af66795d902a2e95d692fa0ff18eccbef8a75 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +@@ -290,6 +290,7 @@ public final class CraftChatMessage { + + public static String fromComponent(Component component) { + if (component == null) return ""; ++ if (component instanceof io.papermc.paper.adventure.AdventureComponent) component = ((io.papermc.paper.adventure.AdventureComponent) component).deepConverted(); + StringBuilder out = new StringBuilder(); + + 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 ef7715774fbdc4c42b217d8192784e09a43fe66f..2d4faef5a2b9c4fe8b65ff4f1346b8375e0e02c8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -57,6 +57,33 @@ public final class CraftMagicNumbers implements UnsafeValues { + + private CraftMagicNumbers() {} + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener() { ++ return io.papermc.paper.adventure.PaperAdventure.FLATTENER; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer() { ++ return io.papermc.paper.adventure.PaperAdventure.COLOR_DOWNSAMPLING_GSON; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer() { ++ return io.papermc.paper.adventure.PaperAdventure.GSON; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer() { ++ return io.papermc.paper.adventure.PaperAdventure.PLAIN; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer() { ++ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC; ++ } ++ // Paper end ++ + public static BlockState getBlock(MaterialData material) { + return getBlock(material.getItemType(), material.getData()); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java +index f194cf2663919ea18309a0501ddfab5e2ed639dd..4b110d6c6f22ff7c2fa0fd4b459820797066199d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java +@@ -80,7 +80,7 @@ public abstract class LazyHashSet implements Set { + return this.reference = makeReference(); + } + +- abstract Set makeReference(); ++ protected abstract Set makeReference(); // Paper - protected + + public boolean isLazy() { + return reference == null; +diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java +index 103c1407b2946e9cae2271646178e5f243c8abb1..b22b7603f3f66e1b64f413106e7989b30475110b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java +@@ -15,10 +15,15 @@ public class LazyPlayerSet extends LazyHashSet { + } + + @Override +- HashSet makeReference() { ++ protected HashSet makeReference() { // Paper - protected + if (reference != null) { + throw new IllegalStateException("Reference already created!"); + } ++ // Paper start ++ return makePlayerSet(this.server); ++ } ++ public static HashSet makePlayerSet(final MinecraftServer server) { ++ // Paper end + List players = server.getPlayerList().players; + HashSet reference = new HashSet(players.size()); + for (ServerPlayer player : players) { diff --git a/patches/server-remapped/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch b/patches/server-remapped/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch new file mode 100644 index 0000000000..2bef4fada9 --- /dev/null +++ b/patches/server-remapped/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch @@ -0,0 +1,114 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 13:02:51 -0600 +Subject: [PATCH] Configurable cactus bamboo and reed growth heights + +Bamboo - Both the minimum fully-grown heights and the maximum are configurable +- Machine_Maker + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index b31109d2dadd29e8852468c19265066b773d2be0..3618cc017feb60e257a28f67cbddca3f792a9833 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -65,4 +65,17 @@ public class PaperWorldConfig { + config.addDefault("world-settings.default." + path, def); + return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); + } ++ ++ public int cactusMaxHeight; ++ public int reedMaxHeight; ++ public int bambooMaxHeight; ++ public int bambooMinHeight; ++ private void blockGrowthHeight() { ++ cactusMaxHeight = getInt("max-growth-height.cactus", 3); ++ reedMaxHeight = getInt("max-growth-height.reeds", 3); ++ bambooMaxHeight = getInt("max-growth-height.bamboo.max", 16); ++ bambooMinHeight = getInt("max-growth-height.bamboo.min", 11); ++ log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); ++ ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/BambooBlock.java b/src/main/java/net/minecraft/world/level/block/BambooBlock.java +index 8f423ae6261434a670bb94aa70b6bc1694f1fc45..36583c189aa5e55de7f5eba362285e57c8279176 100644 +--- a/src/main/java/net/minecraft/world/level/block/BambooBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BambooBlock.java +@@ -124,7 +124,7 @@ public class BambooBlock extends Block implements BonemealableBlock { + if (random.nextInt(Math.max(1, (int) (100.0F / world.spigotConfig.bambooModifier) * 3)) == 0 && world.isEmptyBlock(pos.above()) && world.getRawBrightness(pos.above(), 0) >= 9) { // Spigot + int i = this.getHeightBelowUpToMax(world, pos) + 1; + +- if (i < 16) { ++ if (i < world.paperConfig.bambooMaxHeight) { // Paper + this.growBamboo(state, (Level) world, pos, random, i); + } + } +@@ -155,7 +155,7 @@ public class BambooBlock extends Block implements BonemealableBlock { + int i = this.getHeightAboveUpToMax(world, pos); + int j = this.getHeightBelowUpToMax(world, pos); + +- return i + j + 1 < 16 && (Integer) world.getBlockState(pos.above(i)).getValue(BambooBlock.STAGE) != 1; ++ return i + j + 1 < ((Level) world).paperConfig.bambooMaxHeight && (Integer) world.getBlockState(pos.above(i)).getValue(BambooBlock.STAGE) != 1; // Paper + } + + @Override +@@ -174,7 +174,7 @@ public class BambooBlock extends Block implements BonemealableBlock { + BlockPos blockposition1 = pos.above(i); + BlockState iblockdata1 = world.getBlockState(blockposition1); + +- if (k >= 16 || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here ++ if (k >= world.paperConfig.bambooMaxHeight || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here // Paper - Configurable cactus bamboo and reed growth heights + return; + } + +@@ -215,7 +215,7 @@ public class BambooBlock extends Block implements BonemealableBlock { + } + + int j = (Integer) state.getValue(BambooBlock.AGE) != 1 && !iblockdata2.is(Blocks.BAMBOO) ? 0 : 1; +- int k = (height < 11 || random.nextFloat() >= 0.25F) && height != 15 ? 0 : 1; ++ int k = (height < world.paperConfig.bambooMinHeight || random.nextFloat() >= 0.25F) && height != (world.paperConfig.bambooMaxHeight - 1) ? 0 : 1; // Paper + + // CraftBukkit start + if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, pos.above(), (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(BambooBlock.AGE, j)).setValue(BambooBlock.LEAVES, blockpropertybamboosize)).setValue(BambooBlock.STAGE, k), 3)) { +@@ -230,7 +230,7 @@ public class BambooBlock extends Block implements BonemealableBlock { + protected int getHeightAboveUpToMax(BlockGetter world, BlockPos pos) { + int i; + +- for (i = 0; i < 16 && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { ++ for (i = 0; i < ((Level) world).paperConfig.bambooMaxHeight && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper + ; + } + +@@ -240,7 +240,7 @@ public class BambooBlock extends Block implements BonemealableBlock { + protected int getHeightBelowUpToMax(BlockGetter world, BlockPos pos) { + int i; + +- for (i = 0; i < 16 && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { ++ for (i = 0; i < ((Level) world).paperConfig.bambooMaxHeight && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper + ; + } + +diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java +index d07fd9c1f726b1d45992352408499034c12683e6..de61393e3f702554817d81ff10693ec3fb63d492 100644 +--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java +@@ -54,7 +54,7 @@ public class CactusBlock extends Block { + ; + } + +- if (i < 3) { ++ if (i < world.paperConfig.cactusMaxHeight) { // Paper - Configurable growth height + int j = (Integer) state.getValue(CactusBlock.AGE); + + if (j >= (byte) range(3, ((100.0F / world.spigotConfig.cactusModifier) * 15) + 0.5F, 15)) { // Spigot +diff --git a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java +index 25f634ee93fa4678eaf09694d98783f2aef9d0f0..a795732af122204b88a01311e73892658132da25 100644 +--- a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java +@@ -51,7 +51,7 @@ public class SugarCaneBlock extends Block { + ; + } + +- if (i < 3) { ++ if (i < world.paperConfig.reedMaxHeight) { // Paper - Configurable growth height + int j = (Integer) state.getValue(SugarCaneBlock.AGE); + + if (j >= (byte) range(3, ((100.0F / world.spigotConfig.caneModifier) * 15) + 0.5F, 15)) { // Spigot diff --git a/patches/server-remapped/0012-Configurable-baby-zombie-movement-speed.patch b/patches/server-remapped/0012-Configurable-baby-zombie-movement-speed.patch new file mode 100644 index 0000000000..1b143bb4a0 --- /dev/null +++ b/patches/server-remapped/0012-Configurable-baby-zombie-movement-speed.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 13:09:16 -0600 +Subject: [PATCH] Configurable baby zombie movement speed + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3618cc017feb60e257a28f67cbddca3f792a9833..796c17e0941922a9716212c6eae91643d8360418 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -78,4 +78,15 @@ public class PaperWorldConfig { + log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); + + } ++ ++ public double babyZombieMovementModifier; ++ private void babyZombieMovementModifier() { ++ babyZombieMovementModifier = getDouble("baby-zombie-movement-modifier", 0.5D); ++ if (PaperConfig.version < 20) { ++ babyZombieMovementModifier = getDouble("baby-zombie-movement-speed", 0.5D); ++ set("baby-zombie-movement-modifier", babyZombieMovementModifier); ++ } ++ ++ log("Baby zombies will move at the speed of " + babyZombieMovementModifier); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 992c9646c274350b30c1abb75e0469adc471397f..94e2a8f74e74d68d4a9b82b667fbff24b7e9e629 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -79,7 +79,7 @@ import org.bukkit.event.entity.EntityTransformEvent; + public class Zombie extends Monster { + + private static final UUID SPEED_MODIFIER_BABY_UUID = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836"); +- private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); ++ private final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); private final AttributeModifier babyModifier = this.SPEED_MODIFIER_BABY; // Paper - remove static - Make baby speed configurable + private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT); + public static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); +@@ -182,9 +182,9 @@ public class Zombie extends Monster { + if (this.level != null && !this.level.isClientSide) { + AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- attributemodifiable.removeModifier(Zombie.SPEED_MODIFIER_BABY); ++ attributemodifiable.removeModifier(this.babyModifier); // Paper + if (baby) { +- attributemodifiable.addTransientModifier(Zombie.SPEED_MODIFIER_BABY); ++ attributemodifiable.addTransientModifier(this.babyModifier); // Paper + } + } + diff --git a/patches/server-remapped/0013-Configurable-fishing-time-ranges.patch b/patches/server-remapped/0013-Configurable-fishing-time-ranges.patch new file mode 100644 index 0000000000..33edff1ef7 --- /dev/null +++ b/patches/server-remapped/0013-Configurable-fishing-time-ranges.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 13:14:11 -0600 +Subject: [PATCH] Configurable fishing time ranges + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 796c17e0941922a9716212c6eae91643d8360418..78948c42b13194005bdbbbc69c2b7ae0732a78c5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -89,4 +89,12 @@ public class PaperWorldConfig { + + log("Baby zombies will move at the speed of " + babyZombieMovementModifier); + } ++ ++ public int fishingMinTicks; ++ public int fishingMaxTicks; ++ private void fishingTickRange() { ++ fishingMinTicks = getInt("fishing-time-range.MinimumTicks", 100); ++ fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); ++ log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +index d74dae6d7bd78c082b39a4e38da640a57c40b341..2f67c2065ef29f17f12190b25bd1ea53e1fb55b4 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +@@ -82,6 +82,10 @@ public class FishingHook extends Projectile { + owner.fishing = this; + this.luck = Math.max(0, lureLevel); + this.lureSpeed = Math.max(0, luckOfTheSeaLevel); ++ // Paper start ++ minWaitTime = world.paperConfig.fishingMinTicks; ++ maxWaitTime = world.paperConfig.fishingMaxTicks; ++ // paper end + } + + public FishingHook(net.minecraft.world.entity.player.Player thrower, Level world, int lureLevel, int luckOfTheSeaLevel) { diff --git a/patches/server-remapped/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/patches/server-remapped/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch new file mode 100644 index 0000000000..6f5fd676df --- /dev/null +++ b/patches/server-remapped/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch @@ -0,0 +1,105 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 13:24:16 -0600 +Subject: [PATCH] Allow nerfed mobs to jump and take water damage + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 78948c42b13194005bdbbbc69c2b7ae0732a78c5..b41e7922dd96c3358eb849ab39982a75736e3476 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -97,4 +97,9 @@ public class PaperWorldConfig { + fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); + log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); + } ++ ++ public boolean nerfedMobsShouldJump; ++ private void nerfedMobsShouldJump() { ++ nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 2a7f587e19fcdd6d01b360d6b47d9eadd9df92cc..584e83441a9fef88eb1b0a29bec8bda29d6a0c9c 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1104,6 +1104,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.isInWater() || this.isInRain(); + } + ++ public final boolean isInWaterOrRainOrBubble() { return isInWaterRainOrBubble(); } // Paper - OBFHELPER + public boolean isInWaterRainOrBubble() { + return this.isInWater() || this.isInRain() || this.isInBubbleColumn(); + } +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 99cb4dc1a1009d4a29e651c94d21babcc61388ed..151ebcffc1f2ae02fa55ab83d2ae7d8a0057f29d 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.entity; + ++import PathfinderGoalFloat; + import com.google.common.collect.Maps; + import java.util.Arrays; + import java.util.Iterator; +@@ -96,6 +97,7 @@ public abstract class Mob extends LivingEntity { + private final BodyRotationControl bodyRotationControl; + protected PathNavigation navigation; + public GoalSelector goalSelector; ++ @Nullable public PathfinderGoalFloat goalFloat; // Paper + public GoalSelector targetSelector; + private LivingEntity target; + private final Sensing sensing; +@@ -782,7 +784,17 @@ public abstract class Mob extends LivingEntity { + @Override + protected final void serverAiStep() { + ++this.noActionTime; +- if (!this.aware) return; // CraftBukkit ++ if (!this.aware) { // Paper start - Allow nerfed mobs to jump, float and take water damage ++ if (goalFloat != null) { ++ if (goalFloat.validConditions()) goalFloat.update(); ++ this.getJumpControl().jumpIfSet(); ++ } ++ if ((this instanceof EntityBlaze || this instanceof EntityEnderman) && isInWaterOrRainOrBubble()) { ++ hurt(DamageSource.DROWN, 1.0F); ++ } ++ return; ++ } ++ // Paper end + this.level.getProfiler().push("sensing"); + this.sensing.tick(); + this.level.getProfiler().pop(); +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java b/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java +index 5f7ad2b57d8d8f0f6a7d880f55e08b52f017cf51..09d1cda50ce9076e9236d124aa7766a26a50dae1 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java +@@ -15,6 +15,7 @@ public class JumpControl { + this.jump = true; + } + ++ public final void jumpIfSet() { this.tick(); } // Paper - OBFHELPER + public void tick() { + this.mob.setJumping(this.jump); + this.jump = false; +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java +index 7ea5cb5a92ff3b66859ebcd53031aa06689bd329..790b5646683247ef757095a0763dc52701afe97b 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java +@@ -11,15 +11,18 @@ public class FloatGoal extends Goal { + + public FloatGoal(Mob mob) { + this.mob = mob; ++ if (mob.getCommandSenderWorld().paperConfig.nerfedMobsShouldJump) mob.goalFloat = this; // Paper + this.setFlags(EnumSet.of(Goal.Flag.JUMP)); + mob.getNavigation().setCanFloat(true); + } + ++ public final boolean validConditions() { return this.canUse(); } // Paper - OBFHELPER + @Override + public boolean canUse() { + return this.mob.isInWater() && this.mob.getFluidHeight((Tag) FluidTags.WATER) > this.mob.getFluidJumpThreshold() || this.mob.isInLava(); + } + ++ public void update() { this.tick(); } // Paper - OBFHELPER + @Override + public void tick() { + if (this.mob.getRandom().nextFloat() < 0.8F) { diff --git a/patches/server-remapped/0015-Add-configurable-despawn-distances-for-living-entiti.patch b/patches/server-remapped/0015-Add-configurable-despawn-distances-for-living-entiti.patch new file mode 100644 index 0000000000..4a3d5d60ea --- /dev/null +++ b/patches/server-remapped/0015-Add-configurable-despawn-distances-for-living-entiti.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Suddenly +Date: Tue, 1 Mar 2016 13:51:54 -0600 +Subject: [PATCH] Add configurable despawn distances for living entities + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index b41e7922dd96c3358eb849ab39982a75736e3476..2f0d582baf0eb2bb477944d0cb1369db6ca33956 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -102,4 +102,20 @@ public class PaperWorldConfig { + private void nerfedMobsShouldJump() { + nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); + } ++ ++ public int softDespawnDistance; ++ public int hardDespawnDistance; ++ private void despawnDistances() { ++ softDespawnDistance = getInt("despawn-ranges.soft", 32); // 32^2 = 1024, Minecraft Default ++ hardDespawnDistance = getInt("despawn-ranges.hard", 128); // 128^2 = 16384, Minecraft Default ++ ++ if (softDespawnDistance > hardDespawnDistance) { ++ softDespawnDistance = hardDespawnDistance; ++ } ++ ++ log("Living Entity Despawn Ranges: Soft: " + softDespawnDistance + " Hard: " + hardDespawnDistance); ++ ++ softDespawnDistance = softDespawnDistance*softDespawnDistance; ++ hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 151ebcffc1f2ae02fa55ab83d2ae7d8a0057f29d..4d3000067ae3d46b7ed4dda6146a21993199c6d9 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -762,16 +762,16 @@ public abstract class Mob extends LivingEntity { + int i = this.getType().getCategory().getDespawnDistance(); + int j = i * i; + +- if (d0 > (double) j) { // CraftBukkit - remove isTypeNotPersistent() check ++ if (d0 > (double) level.paperConfig.hardDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances + this.remove(); + } + + int k = this.getType().getCategory().getNoDespawnDistance(); + int l = k * k; + +- if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > (double) l) { // CraftBukkit - remove isTypeNotPersistent() check ++ if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > level.paperConfig.softDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances + this.remove(); +- } else if (d0 < (double) l) { ++ } else if (d0 < level.paperConfig.softDespawnDistance) { // Paper - custom despawn distances + this.noActionTime = 0; + } + } diff --git a/patches/server-remapped/0016-Allow-for-toggling-of-spawn-chunks.patch b/patches/server-remapped/0016-Allow-for-toggling-of-spawn-chunks.patch new file mode 100644 index 0000000000..91cd6d02b8 --- /dev/null +++ b/patches/server-remapped/0016-Allow-for-toggling-of-spawn-chunks.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 3 Mar 2016 03:53:43 -0600 +Subject: [PATCH] Allow for toggling of spawn chunks + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2f0d582baf0eb2bb477944d0cb1369db6ca33956..89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -118,4 +118,10 @@ public class PaperWorldConfig { + softDespawnDistance = softDespawnDistance*softDespawnDistance; + hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; + } ++ ++ public boolean keepSpawnInMemory; ++ private void keepSpawnInMemory() { ++ keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); ++ log("Keep spawn chunk loaded: " + keepSpawnInMemory); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index c153df1f4dea3dc0ae744bde01e334b3bd3b50af..832abf73bdab2488c5814ea6e57888aac1b26154 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -217,6 +217,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + }); + // CraftBukkit end + timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings ++ this.keepSpawnInMemory = this.paperConfig.keepSpawnInMemory; // Paper + this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + } diff --git a/patches/server-remapped/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch b/patches/server-remapped/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch new file mode 100644 index 0000000000..91e53448a3 --- /dev/null +++ b/patches/server-remapped/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Tue, 1 Mar 2016 14:14:15 -0600 +Subject: [PATCH] Drop falling block and tnt entities at the specified height + +* Dec 2, 2020 Added tnt nerf for tnt minecarts - Machine_Maker + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75..d16ae924bcbe31c964f7fb448757c748e5c4418c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -124,4 +124,14 @@ public class PaperWorldConfig { + keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); + log("Keep spawn chunk loaded: " + keepSpawnInMemory); + } ++ ++ public int fallingBlockHeightNerf; ++ public int entityTNTHeightNerf; ++ private void heightNerfs() { ++ fallingBlockHeightNerf = getInt("falling-block-height-nerf", 0); ++ entityTNTHeightNerf = getInt("tnt-entity-height-nerf", 0); ++ ++ if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); ++ if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 584e83441a9fef88eb1b0a29bec8bda29d6a0c9c..706417f44c1eebc7cc5e8e7053fa0ab21f4caeba 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1849,6 +1849,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.spawnAtLocation(stack, 0.0F); + } + ++ @Nullable public final ItemEntity dropItem(ItemStack itemstack, float offset) { return this.spawnAtLocation(itemstack, offset); } // Paper - OBFHELPER + @Nullable + public ItemEntity spawnAtLocation(ItemStack stack, float yOffset) { + if (stack.isEmpty()) { +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 8a9e2316b9f5756503dc06e27981525d2cd7d1a5..5394bc6336cb84025c1c748fb5b3d38e0648a590 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -122,6 +122,17 @@ public class FallingBlockEntity extends Entity { + } + + this.move(MoverType.SELF, this.getDeltaMovement()); ++ ++ // Paper start - Configurable EntityFallingBlock height nerf ++ if (this.level.paperConfig.fallingBlockHeightNerf != 0 && this.getY() > this.level.paperConfig.fallingBlockHeightNerf) { ++ if (this.dropItem && this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { ++ this.spawnAtLocation(block); ++ } ++ ++ this.remove(); ++ return; ++ } ++ // Paper end + if (!this.level.isClientSide) { + blockposition = this.blockPosition(); + boolean flag = this.blockState.getBlock() instanceof ConcretePowderBlock; +diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +index ff15a372b7cad5fa88b7ef6de1f3441d93f9c67e..4c4262b8f0cb44b8cea8cb46194a6e70d4ce56f4 100644 +--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +@@ -69,6 +69,12 @@ public class PrimedTnt extends Entity { + } + + this.move(MoverType.SELF, this.getDeltaMovement()); ++ // Paper start - Configurable TNT entity height nerf ++ if (this.level.paperConfig.entityTNTHeightNerf != 0 && this.getY() > this.level.paperConfig.entityTNTHeightNerf) { ++ this.remove(); ++ return; ++ } ++ // Paper end + this.setDeltaMovement(this.getDeltaMovement().scale(0.98D)); + if (this.onGround) { + this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D)); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java +index c2ed3ba42d29a50386c94b109fdd3b2f2f1b433b..3b5e96f2325e14a94de0fb2d6da86812cecc7395 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java +@@ -47,6 +47,12 @@ public class MinecartTNT extends AbstractMinecart { + public void tick() { + super.tick(); + if (this.fuse > 0) { ++ // Paper start - Configurable TNT entity height nerf ++ if (this.level.paperConfig.entityTNTHeightNerf != 0 && this.getY() > this.level.paperConfig.entityTNTHeightNerf) { ++ this.remove(); ++ return; ++ } ++ // Paper end + --this.fuse; + this.level.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D); + } else if (this.fuse == 0) { diff --git a/patches/server-remapped/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/patches/server-remapped/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch new file mode 100644 index 0000000000..e00adead2f --- /dev/null +++ b/patches/server-remapped/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 14:32:43 -0600 +Subject: [PATCH] Show 'Paper' in client crashes, server lists, and Mojang + stats + + +diff --git a/src/main/java/net/minecraft/server/Eula.java b/src/main/java/net/minecraft/server/Eula.java +index 6934b0fdfe11ef673a3e4ae7564d04acee169252..9f104b1bd05d9f344579f086b2b9c00af1750690 100644 +--- a/src/main/java/net/minecraft/server/Eula.java ++++ b/src/main/java/net/minecraft/server/Eula.java +@@ -72,7 +72,7 @@ public class Eula { + Properties properties = new Properties(); + + properties.setProperty("eula", "false"); +- properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula)."); ++ properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\nYou also agree that tacos are tasty, and the best food in the world."); // Paper - fix lag; + } catch (Throwable throwable1) { + throwable = throwable1; + throw throwable1; +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index a456b9cbf0e5eea4e888e0e3d07ed17558650371..fa29790600021809f31092a90e1a3a9b84d5e0c4 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1340,7 +1340,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop // CraftBukkit - cb > vanilla! ++ return "Paper"; //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! + } + + public CrashReport fillReport(CrashReport report) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index f7f5457d20586e0ba72368e64ff6025f6755e61e..f81def94a1a7ab3a24b74a8bbd5f3e8ebae2c0d5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -224,7 +224,7 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; + import net.md_5.bungee.api.chat.BaseComponent; // Spigot + + public final class CraftServer implements Server { +- private final String serverName = "CraftBukkit"; ++ private final String serverName = "Paper"; // Paper + private final String serverVersion; + private final String bukkitVersion = Versioning.getBukkitVersion(); + private final Logger logger = Logger.getLogger("Minecraft"); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index ce9f10f890a5866ab6208c7253b15b09fe323a81..e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -206,12 +206,25 @@ public class Main { + deadline.add(Calendar.DAY_OF_YEAR, -28); + 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 ***"); ++ System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper + System.err.println("*** Server will start in 20 seconds ***"); + Thread.sleep(TimeUnit.SECONDS.toMillis(20)); + } + } + ++ // Paper start - Log Java and OS versioning to help with debugging plugin issues ++ java.lang.management.RuntimeMXBean runtimeMX = java.lang.management.ManagementFactory.getRuntimeMXBean(); ++ java.lang.management.OperatingSystemMXBean osMX = java.lang.management.ManagementFactory.getOperatingSystemMXBean(); ++ if (runtimeMX != null && osMX != null) { ++ String javaInfo = "Java " + runtimeMX.getSpecVersion() + " (" + runtimeMX.getVmName() + " " + runtimeMX.getVmVersion() + ")"; ++ String osInfo = "Host: " + osMX.getName() + " " + osMX.getVersion() + " (" + osMX.getArch() + ")"; ++ ++ System.out.println("System Info: " + javaInfo + " " + osInfo); ++ } else { ++ System.out.println("Unable to read system info"); ++ } ++ // Paper end ++ + System.out.println("Loading libraries, please wait..."); + net.minecraft.server.Main.main(options); + } catch (Throwable t) { +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 9a695b80ef57d677fbdee1bfc59f0f9125a7ebd4..21d7b483920841456707fe3f08b180c1f072b7f7 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -19,7 +19,7 @@ public class WatchdogThread extends Thread + + private WatchdogThread(long timeoutTime, boolean restart) + { +- super( "Spigot Watchdog Thread" ); ++ super( "Paper Watchdog Thread" ); + this.timeoutTime = timeoutTime; + this.restart = restart; + } +@@ -65,14 +65,14 @@ public class WatchdogThread extends Thread + { + Logger log = Bukkit.getServer().getLogger(); + log.log( Level.SEVERE, "------------------------------" ); +- log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Spigot bug." ); ++ log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper + log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); + log.log( Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring" ); + log.log( Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once" ); + log.log( Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes" ); +- log.log( Level.SEVERE, "If you are unsure or still think this is a Spigot bug, please report to https://www.spigotmc.org/" ); ++ log.log( Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues" ); + log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); +- log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() ); ++ log.log( Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion() ); + // + if ( net.minecraft.world.level.Level.lastPhysicsProblem != null ) + { +@@ -82,7 +82,7 @@ public class WatchdogThread extends Thread + } + // + log.log( Level.SEVERE, "------------------------------" ); +- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" ); ++ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // diff --git a/patches/server-remapped/0019-Implement-Paper-VersionChecker.patch b/patches/server-remapped/0019-Implement-Paper-VersionChecker.patch new file mode 100644 index 0000000000..66c45ee1f0 --- /dev/null +++ b/patches/server-remapped/0019-Implement-Paper-VersionChecker.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 27 May 2019 03:40:05 -0500 +Subject: [PATCH] Implement Paper VersionChecker + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1a1b50e475b9ede544b2f6d0d36632b24b68898c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +@@ -0,0 +1,122 @@ ++package com.destroystokyo.paper; ++ ++import com.destroystokyo.paper.util.VersionFetcher; ++import com.google.common.base.Charsets; ++import com.google.common.io.Resources; ++import com.google.gson.*; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.format.NamedTextColor; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++import java.io.*; ++import java.net.HttpURLConnection; ++import java.net.URL; ++import java.util.stream.StreamSupport; ++ ++public class PaperVersionFetcher implements VersionFetcher { ++ private static final java.util.regex.Pattern VER_PATTERN = java.util.regex.Pattern.compile("^([0-9\\.]*)\\-.*R"); // R is an anchor, will always give '-R' at end ++ private static final String GITHUB_BRANCH_NAME = "master"; ++ private static @Nullable String mcVer; ++ ++ @Override ++ public long getCacheTime() { ++ return 720000; ++ } ++ ++ @Nonnull ++ @Override ++ public Component getVersionMessage(@Nonnull String serverVersion) { ++ String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); ++ return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); ++ } ++ ++ private static @Nullable String getMinecraftVersion() { ++ if (mcVer == null) { ++ java.util.regex.Matcher matcher = VER_PATTERN.matcher(org.bukkit.Bukkit.getBukkitVersion()); ++ if (matcher.find()) { ++ String result = matcher.group(); ++ mcVer = result.substring(0, result.length() - 2); // strip 'R' anchor and trailing '-' ++ } else { ++ org.bukkit.Bukkit.getLogger().warning("Unable to match version to pattern! Report to PaperMC!"); ++ org.bukkit.Bukkit.getLogger().warning("Pattern: " + VER_PATTERN.toString()); ++ org.bukkit.Bukkit.getLogger().warning("Version: " + org.bukkit.Bukkit.getBukkitVersion()); ++ } ++ } ++ ++ return mcVer; ++ } ++ ++ private static Component getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) { ++ int distance; ++ try { ++ int jenkinsBuild = Integer.parseInt(versionInfo); ++ distance = fetchDistanceFromSiteApi(jenkinsBuild, getMinecraftVersion()); ++ } catch (NumberFormatException ignored) { ++ versionInfo = versionInfo.replace("\"", ""); ++ distance = fetchDistanceFromGitHub(repo, branch, versionInfo); ++ } ++ ++ switch (distance) { ++ case -1: ++ return Component.text("Error obtaining version information", NamedTextColor.YELLOW); ++ case 0: ++ return Component.text("You are running the latest version", NamedTextColor.GREEN); ++ case -2: ++ return Component.text("Unknown version", NamedTextColor.YELLOW); ++ default: ++ return Component.text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW); ++ } ++ } ++ ++ private static int fetchDistanceFromSiteApi(int jenkinsBuild, @Nullable String siteApiVersion) { ++ if (siteApiVersion == null) { return -1; } ++ try { ++ try (BufferedReader reader = Resources.asCharSource( ++ new URL("https://papermc.io/api/v2/projects/paper/versions/" + siteApiVersion), ++ Charsets.UTF_8 ++ ).openBufferedStream()) { ++ JsonObject json = new Gson().fromJson(reader, JsonObject.class); ++ JsonArray builds = json.getAsJsonArray("builds"); ++ int latest = StreamSupport.stream(builds.spliterator(), false) ++ .mapToInt(e -> e.getAsInt()) ++ .max() ++ .getAsInt(); ++ return latest - jenkinsBuild; ++ } catch (JsonSyntaxException ex) { ++ ex.printStackTrace(); ++ return -1; ++ } ++ } catch (IOException e) { ++ e.printStackTrace(); ++ return -1; ++ } ++ } ++ ++ // Contributed by Techcable in GH-65 ++ private static int fetchDistanceFromGitHub(@Nonnull String repo, @Nonnull String branch, @Nonnull String hash) { ++ try { ++ HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + repo + "/compare/" + branch + "..." + hash).openConnection(); ++ connection.connect(); ++ if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return -2; // Unknown commit ++ try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) { ++ JsonObject obj = new Gson().fromJson(reader, JsonObject.class); ++ String status = obj.get("status").getAsString(); ++ switch (status) { ++ case "identical": ++ return 0; ++ case "behind": ++ return obj.get("behind_by").getAsInt(); ++ default: ++ return -1; ++ } ++ } catch (JsonSyntaxException | NumberFormatException e) { ++ e.printStackTrace(); ++ return -1; ++ } ++ } catch (IOException e) { ++ e.printStackTrace(); ++ return -1; ++ } ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 2d4faef5a2b9c4fe8b65ff4f1346b8375e0e02c8..21052d0e88351b075733331d71e07b086354b820 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -368,6 +368,11 @@ public final class CraftMagicNumbers implements UnsafeValues { + public String getTimingsServerName() { + return com.destroystokyo.paper.PaperConfig.timingsServerName; + } ++ ++ @Override ++ public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { ++ return new com.destroystokyo.paper.PaperVersionFetcher(); ++ } + // Paper end + + /** diff --git a/patches/server-remapped/0020-Add-version-history-to-version-command.patch b/patches/server-remapped/0020-Add-version-history-to-version-command.patch new file mode 100644 index 0000000000..4985c3e747 --- /dev/null +++ b/patches/server-remapped/0020-Add-version-history-to-version-command.patch @@ -0,0 +1,215 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Thu, 1 Mar 2018 19:37:52 -0600 +Subject: [PATCH] Add version history to version command + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +index 1a1b50e475b9ede544b2f6d0d36632b24b68898c..580bae0d414d371a07a6bfeefc41fdd989dc0083 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java ++++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +@@ -5,7 +5,9 @@ import com.google.common.base.Charsets; + import com.google.common.io.Resources; + import com.google.gson.*; + import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.TextComponent; + import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.format.TextDecoration; + + import javax.annotation.Nonnull; + import javax.annotation.Nullable; +@@ -28,7 +30,10 @@ public class PaperVersionFetcher implements VersionFetcher { + @Override + public Component getVersionMessage(@Nonnull String serverVersion) { + String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); +- return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); ++ final Component updateMessage = getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); ++ final Component history = getHistory(); ++ ++ return history != null ? TextComponent.ofChildren(updateMessage, Component.newline(), history) : updateMessage; + } + + private static @Nullable String getMinecraftVersion() { +@@ -119,4 +124,19 @@ public class PaperVersionFetcher implements VersionFetcher { + return -1; + } + } ++ ++ @Nullable ++ private Component getHistory() { ++ final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); ++ if (data == null) { ++ return null; ++ } ++ ++ final String oldVersion = data.getOldVersion(); ++ if (oldVersion == null) { ++ return null; ++ } ++ ++ return Component.text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC); ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..aac3f66cb23d260729c2a48d8710a9de2346aa22 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java +@@ -0,0 +1,145 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.MoreObjects; ++import com.google.gson.Gson; ++import com.google.gson.JsonSyntaxException; ++import java.io.BufferedReader; ++import java.io.BufferedWriter; ++import java.io.IOException; ++import java.nio.charset.StandardCharsets; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.nio.file.Paths; ++import java.nio.file.StandardOpenOption; ++import java.util.Objects; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++import org.bukkit.Bukkit; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++ ++public enum VersionHistoryManager { ++ INSTANCE; ++ ++ private final Gson gson = new Gson(); ++ ++ private final Logger logger = Bukkit.getLogger(); ++ ++ private VersionData currentData = null; ++ ++ VersionHistoryManager() { ++ final Path path = Paths.get("version_history.json"); ++ ++ if (Files.exists(path)) { ++ // Basic file santiy checks ++ if (!Files.isRegularFile(path)) { ++ if (Files.isDirectory(path)) { ++ logger.severe(path + " is a directory, cannot be used for version history"); ++ } else { ++ logger.severe(path + " is not a regular file, cannot be used for version history"); ++ } ++ // We can't continue ++ return; ++ } ++ ++ try (final BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { ++ currentData = gson.fromJson(reader, VersionData.class); ++ } catch (final IOException e) { ++ logger.log(Level.SEVERE, "Failed to read version history file '" + path + "'", e); ++ return; ++ } catch (final JsonSyntaxException e) { ++ logger.log(Level.SEVERE, "Invalid json syntax for file '" + path + "'", e); ++ return; ++ } ++ ++ final String version = Bukkit.getVersion(); ++ if (version == null) { ++ logger.severe("Failed to retrieve current version"); ++ return; ++ } ++ ++ if (!version.equals(currentData.getCurrentVersion())) { ++ // The version appears to have changed ++ currentData.setOldVersion(currentData.getCurrentVersion()); ++ currentData.setCurrentVersion(version); ++ writeFile(path); ++ } ++ } else { ++ // File doesn't exist, start fresh ++ currentData = new VersionData(); ++ // oldVersion is null ++ currentData.setCurrentVersion(Bukkit.getVersion()); ++ writeFile(path); ++ } ++ } ++ ++ private void writeFile(@Nonnull final Path path) { ++ try (final BufferedWriter writer = Files.newBufferedWriter( ++ path, ++ StandardCharsets.UTF_8, ++ StandardOpenOption.WRITE, ++ StandardOpenOption.CREATE, ++ StandardOpenOption.TRUNCATE_EXISTING ++ )) { ++ gson.toJson(currentData, writer); ++ } catch (final IOException e) { ++ logger.log(Level.SEVERE, "Failed to write to version history file", e); ++ } ++ } ++ ++ @Nullable ++ public VersionData getVersionData() { ++ return currentData; ++ } ++ ++ public static class VersionData { ++ private String oldVersion; ++ ++ private String currentVersion; ++ ++ @Nullable ++ public String getOldVersion() { ++ return oldVersion; ++ } ++ ++ public void setOldVersion(@Nullable String oldVersion) { ++ this.oldVersion = oldVersion; ++ } ++ ++ @Nullable ++ public String getCurrentVersion() { ++ return currentVersion; ++ } ++ ++ public void setCurrentVersion(@Nullable String currentVersion) { ++ this.currentVersion = currentVersion; ++ } ++ ++ @Override ++ public String toString() { ++ return MoreObjects.toStringHelper(this) ++ .add("oldVersion", oldVersion) ++ .add("currentVersion", currentVersion) ++ .toString(); ++ } ++ ++ @Override ++ public boolean equals(@Nullable Object o) { ++ if (this == o) { ++ return true; ++ } ++ if (o == null || getClass() != o.getClass()) { ++ return false; ++ } ++ final VersionData versionData = (VersionData) o; ++ return Objects.equals(oldVersion, versionData.oldVersion) && ++ Objects.equals(currentVersion, versionData.currentVersion); ++ } ++ ++ @Override ++ public int hashCode() { ++ return Objects.hash(oldVersion, currentVersion); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 40fe03c844c8bf6a9c4c5ae028b259f01a81eead..c7655883262f122b373ac30a33ddb4c06cd9aebe 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -193,6 +193,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + return false; + } + com.destroystokyo.paper.PaperConfig.registerCommands(); ++ com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now + // Paper end + + this.setPvpAllowed(dedicatedserverproperties.pvp); diff --git a/patches/server-remapped/0021-Player-affects-spawning-API.patch b/patches/server-remapped/0021-Player-affects-spawning-API.patch new file mode 100644 index 0000000000..08d7ac1c4a --- /dev/null +++ b/patches/server-remapped/0021-Player-affects-spawning-API.patch @@ -0,0 +1,157 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Tue, 1 Mar 2016 14:47:52 -0600 +Subject: [PATCH] Player affects spawning API + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 706417f44c1eebc7cc5e8e7053fa0ab21f4caeba..392f2f2d67b688d5b37f77c8e4b3036348472d77 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1353,6 +1353,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return Mth.sqrt(f * f + f1 * f1 + f2 * f2); + } + ++ public double getDistanceSquared(double x, double y, double z) { return distanceToSqr(x, y, z); } // Paper - OBFHELPER + public double distanceToSqr(double x, double y, double z) { + double d3 = this.getX() - x; + double d4 = this.getY() - y; +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index f8c13881f59ccaccf8d8e5496d2f8f49ba7d7343..a3bad391a719363077740aa810c9412df34b4ae5 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -29,6 +29,12 @@ public final class EntitySelector { + return !entity.isSpectator(); + }; + ++ // Paper start ++ public static final Predicate affectsSpawning = (entity) -> { ++ return !entity.isSpectator() && entity.isAlive() && (entity instanceof EntityPlayer) && ((EntityPlayer) entity).affectsSpawning; ++ }; ++ // Paper end ++ + public static Predicate withinDistance(double x, double y, double z, double d3) { + double d4 = d3 * d3; + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 4d3000067ae3d46b7ed4dda6146a21993199c6d9..09d39b73e8a3987e58a502bd914a6451b807421b 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -755,7 +755,7 @@ public abstract class Mob extends LivingEntity { + if (this.level.getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) { + this.remove(); + } else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) { +- Player entityhuman = this.level.getNearestPlayer(this, -1.0D); ++ Player entityhuman = this.level.findNearbyPlayer(this, -1.0D, EntitySelector.affectsSpawning); // Paper + + if (entityhuman != null) { + double d0 = entityhuman.distanceToSqr((Entity) this); // CraftBukkit - decompile error +diff --git a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java +index 4ce9e37d7334ba0557c397c0ebd2cb7928c7c564..cfdbaec1de6add7a189c26eb66701dfa5f40fe4f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java +@@ -122,7 +122,7 @@ public class Silverfish extends Monster { + if (checkAnyLightMonsterSpawnRules(type, world, spawnReason, pos, random)) { + Player entityhuman = world.getNearestPlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0D, true); + +- return entityhuman == null; ++ return !(entityhuman != null && !entityhuman.affectsSpawning) && entityhuman == null; // Paper - Affects Spawning API + } else { + return 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 91f605c803c021c8743de87b67dcb0fb9fc807e9..3b451e75a7f49ea6b543aee9f0a51c0be3c4dfba 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -161,6 +161,9 @@ public abstract class Player extends LivingEntity { + private final ItemCooldowns cooldowns; + @Nullable + public FishingHook fishing; ++ // Paper start ++ public boolean affectsSpawning = true; ++ // Paper end + + // CraftBukkit start + public boolean fauxSleeping; +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 98f85d59bc48451ef6381a47fe341f77b9920981..10058d3c3565382faa893b79119c5caf845bf29a 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -66,7 +66,7 @@ public abstract class BaseSpawner { + private boolean isNearPlayer() { + BlockPos blockposition = this.getPos(); + +- return this.getLevel().hasNearbyAlivePlayer((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); ++ return this.getLevel().isAffectsSpawningPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper + } + + public void tick() { +diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java +index 7e7a58b9a9ececdcc37fc33b33703428eb1d5faf..66681b9f0e2531d3da25629e44180417b32b4d66 100644 +--- a/src/main/java/net/minecraft/world/level/EntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/EntityGetter.java +@@ -92,8 +92,9 @@ public interface EntityGetter { + } + } + +- @Nullable +- default Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate targetPredicate) { ++ default Player findNearbyPlayer(Entity entity, double d0, @Nullable Predicate predicate) { return this.findNearbyPlayer(entity.getX(), entity.getY(), entity.getZ(), d0, predicate); } // Paper ++ @Nullable default Player findNearbyPlayer(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { return getNearestPlayer(d0, d1, d2, d3, predicate); } // Paper - OBFHELPER ++ @Nullable default Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate targetPredicate) { // Paper + double d4 = -1.0D; + Player entityhuman = null; + Iterator iterator = this.players().iterator(); +@@ -126,6 +127,27 @@ public interface EntityGetter { + return this.getNearestPlayer(x, y, z, maxDistance, predicate); + } + ++ // Paper end ++ default boolean isAffectsSpawningPlayerNearby(double d0, double d1, double d2, double d3) { ++ Iterator iterator = this.players().iterator(); ++ double d4; ++ do { ++ Player entityhuman; ++ do { ++ if (!iterator.hasNext()) { ++ return false; ++ } ++ ++ entityhuman = (Player) iterator.next(); ++ } while (!EntitySelector.affectsSpawning.test(entityhuman)); ++ ++ d4 = entityhuman.getDistanceSquared(d0, d1, d2); ++ } while (d3 >= 0.0D && d4 >= d3 * d3); ++ ++ return true; ++ } ++ // Paper end ++ + default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) { + Iterator iterator = this.players().iterator(); + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 50d11611702e3d1f0e980fb8f2280b05b891167b..e6c39c822c6a910f63e9b4899d53b7d75e1b77cf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1768,8 +1768,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + @Override + public String getLocale() { + return getHandle().locale; ++ ++ } ++ ++ // Paper start ++ public void setAffectsSpawning(boolean affects) { ++ this.getHandle().affectsSpawning = affects; + } + ++ @Override ++ public boolean getAffectsSpawning() { ++ return this.getHandle().affectsSpawning; ++ } ++ // Paper end ++ + @Override + public void updateCommands() { + if (getHandle().connection == null) return; diff --git a/patches/server-remapped/0022-Remove-invalid-mob-spawner-tile-entities.patch b/patches/server-remapped/0022-Remove-invalid-mob-spawner-tile-entities.patch new file mode 100644 index 0000000000..23323c9803 --- /dev/null +++ b/patches/server-remapped/0022-Remove-invalid-mob-spawner-tile-entities.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Tue, 1 Mar 2016 15:08:03 -0600 +Subject: [PATCH] Remove invalid mob spawner tile entities + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index f30793b81dfd9018b4879d655c7c18a9f9c25267..300749822d52f9f973e71c6ec9c8bf29d6a6938e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -41,7 +41,9 @@ import net.minecraft.world.level.TickList; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EntityBlock; ++import net.minecraft.world.level.block.SpawnerBlock; + import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.entity.SpawnerBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.levelgen.DebugLevelSource; + import net.minecraft.world.level.levelgen.Heightmap; +@@ -647,6 +649,10 @@ public class LevelChunk implements ChunkAccess { + } + + // CraftBukkit start ++ // Paper start - Remove invalid mob spawner tile entities ++ } else if (blockEntity instanceof SpawnerBlockEntity && !(getBlockData(pos.getX(), pos.getY(), pos.getZ()).getBlock() instanceof SpawnerBlock)) { ++ this.blockEntities.remove(pos); ++ // Paper end + } else { + System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() + + " (" + getBlockState(pos) + ") where there was no entity tile!"); diff --git a/patches/server-remapped/0023-Optimize-TileEntity-Ticking.patch b/patches/server-remapped/0023-Optimize-TileEntity-Ticking.patch new file mode 100644 index 0000000000..db2d2e1d05 --- /dev/null +++ b/patches/server-remapped/0023-Optimize-TileEntity-Ticking.patch @@ -0,0 +1,279 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 8 Mar 2015 22:55:25 -0600 +Subject: [PATCH] Optimize TileEntity Ticking + + +diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java +index 94adf0275a2e7093c152cc3b8b0a5747b3a13a86..5bcf9cefc29eb20e2cfbfb49e2b2662ec394a87e 100644 +--- a/src/main/java/co/aikar/timings/TimingsExport.java ++++ b/src/main/java/co/aikar/timings/TimingsExport.java +@@ -112,7 +112,7 @@ public class TimingsExport extends Thread { + pair("end", System.currentTimeMillis() / 1000), + pair("online-mode", Bukkit.getServer().getOnlineMode()), + pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), +- pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedIds(), pack -> { ++ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedPacks(), pack -> { + // Don't feel like obf helper'ing these, non fatal if its temp missed. + return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); + })) +@@ -151,8 +151,8 @@ public class TimingsExport extends Thread { + ); + + parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getAllLevels(), world -> { +- if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; +- return pair(world.getWorldData().getName(), createObject( ++ if (world.getWorld().getName().equals("worldeditregentempworld")) return null; ++ return pair(world.getWorld().getName(), createObject( + pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { + return pair(rule, world.getWorld().getGameRuleValue(rule)); + })), +diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +index 56656bf34db07bc717ace8ae9c1b60f9bfd7ff05..1bda9a158eb4372b9ab7cf3097732e64810aefc6 100644 +--- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +@@ -54,8 +54,8 @@ import net.minecraft.world.phys.shapes.VoxelShape; + public class ChestBlock extends AbstractChestBlock implements SimpleWaterloggedBlock { + + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; +- public static final EnumProperty TYPE = BlockStateProperties.CHEST_TYPE; +- public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; ++ public static final EnumProperty TYPE = BlockStateProperties.CHEST_TYPE; public static final EnumProperty CHEST_TYPE_PROPERTY = TYPE; // Paper - OBFHELPER ++ public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; public static final BooleanProperty waterlogged() { return WATERLOGGED; } // Paper OBFHELPER + protected static final VoxelShape NORTH_AABB = Block.box(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D); + protected static final VoxelShape SOUTH_AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D); + protected static final VoxelShape WEST_AABB = Block.box(0.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java +index 7b08ee35d2d8dc3fe783d773bf6686a5197006b8..17289d28b6d0023279a573715ee3d182988dd651 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java +@@ -8,6 +8,7 @@ import net.minecraft.core.NonNullList; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; +@@ -32,7 +33,7 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.entity.HumanEntity; + // CraftBukkit end + +-public class ChestBlockEntity extends RandomizableContainerBlockEntity implements TickableBlockEntity { ++public class ChestBlockEntity extends RandomizableContainerBlockEntity { // Paper - Remove ITickable + + private NonNullList items; + protected float openness; +@@ -110,14 +111,20 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + return tag; + } + +- @Override + public void tick() { + int i = this.worldPosition.getX(); + int j = this.worldPosition.getY(); + int k = this.worldPosition.getZ(); + + ++this.tickInterval; +- this.openCount = getOpenCount(this.level, this, this.tickInterval, i, j, k, this.openCount); ++ } ++ ++ public void doOpenLogic() { ++ int i = this.worldPosition.getX(); ++ int j = this.worldPosition.getY(); ++ int k = this.worldPosition.getZ(); ++ ++ //this.viewingCount = a(this.world, this, this.j, i, j, k, this.viewingCount); // Paper - check is faulty given our logic is called before active container set + this.oOpenness = this.openness; + float f = 0.1F; + +@@ -131,25 +138,31 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + if (this.openCount > 0 && this.openness == 0.0F) { + this.playSound(SoundEvents.CHEST_OPEN); + } ++ } + +- if (this.openCount == 0 && this.openness > 0.0F || this.openCount > 0 && this.openness < 1.0F) { +- float f1 = this.openness; ++ public void doCloseLogic() { ++ if (this.openCount == 0 /* && this.a > 0.0F || this.viewingCount > 0 && this.a < 1.0F */) { // Paper - disable all but player count check ++ /* // Paper - disable animation stuff ++ float f1 = this.a; + +- if (this.openCount > 0) { +- this.openness += 0.1F; ++ if (this.viewingCount > 0) { ++ this.a += 0.1F; + } else { +- this.openness -= 0.1F; ++ this.a -= 0.1F; + } + +- if (this.openness > 1.0F) { +- this.openness = 1.0F; ++ if (this.a > 1.0F) { ++ this.a = 1.0F; + } + + float f2 = 0.5F; + +- if (this.openness < 0.5F && f1 >= 0.5F) { ++ if (this.a < 0.5F && f1 >= 0.5F) { ++ */ ++ MCUtil.scheduleTask(10, () -> { + this.playSound(SoundEvents.CHEST_CLOSE); +- } ++ }, "Chest Sounds"); ++ //} // Paper end + + if (this.openness < 0.0F) { + this.openness = 0.0F; +@@ -188,6 +201,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + } + + public void playSound(SoundEvent soundeffect) { ++ if (!this.getBlockState().contains(ChestBlock.CHEST_TYPE_PROPERTY)) { return; } // Paper - this can be delayed, double check exists - Fixes GH-2074 + ChestType blockpropertychesttype = (ChestType) this.getBlockState().getValue(ChestBlock.TYPE); + + if (blockpropertychesttype != ChestType.LEFT) { +@@ -226,6 +240,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + + ++this.openCount; + if (this.level == null) return; // CraftBukkit ++ doOpenLogic(); // Paper + + // CraftBukkit start - Call redstone event + if (this.getBlockState().getBlock() == Blocks.TRAPPED_CHEST) { +@@ -248,6 +263,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + --this.openCount; + + // CraftBukkit start - Call redstone event ++ doCloseLogic(); // Paper + if (this.getBlockState().getBlock() == Blocks.TRAPPED_CHEST) { + int newPower = Math.max(0, Math.min(15, this.openCount)); + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java +index b26337770e13c20f57a4e74282710ce697ac0d41..8f0477d9620ef71e10855bbca07f9b6984d5d794 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java +@@ -1,11 +1,12 @@ + package net.minecraft.world.level.block.entity; + ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.block.Blocks; + +-public class EnderChestBlockEntity extends BlockEntity implements TickableBlockEntity { ++public class EnderChestBlockEntity extends BlockEntity { // Paper - Remove ITickable + + public float openness; + public float oOpenness; +@@ -16,18 +17,28 @@ public class EnderChestBlockEntity extends BlockEntity implements TickableBlockE + super(BlockEntityType.ENDER_CHEST); + } + +- @Override + public void tick() { + if (++this.tickInterval % 20 * 4 == 0) { + this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); + } + + this.oOpenness = this.openness; ++ /* // Paper ++ int i = this.position.getX(); ++ int j = this.position.getY(); ++ int k = this.position.getZ(); ++ float f = 0.1F; ++ double d0; ++ // Paper start ++ */ ++ } ++ ++ private void doOpenLogic() { + int i = this.worldPosition.getX(); + int j = this.worldPosition.getY(); + int k = this.worldPosition.getZ(); +- float f = 0.1F; + double d0; ++ // Paper end + + if (this.openCount > 0 && this.openness == 0.0F) { + double d1 = (double) i + 0.5D; +@@ -35,28 +46,40 @@ public class EnderChestBlockEntity extends BlockEntity implements TickableBlockE + d0 = (double) k + 0.5D; + this.level.playSound((Player) null, d1, (double) j + 0.5D, d0, SoundEvents.ENDER_CHEST_OPEN, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); + } ++ // Paper start ++ } + +- if (this.openCount == 0 && this.openness > 0.0F || this.openCount > 0 && this.openness < 1.0F) { +- float f1 = this.openness; ++ private void doCloseLogic() { ++ int i = this.worldPosition.getX(); ++ int j = this.worldPosition.getY(); ++ int k = this.worldPosition.getZ(); ++ double d0; ++ ++ if (this.openCount == 0) { /* && this.a > 0.0F || this.c > 0 && this.a < 1.0F) { ++ // Paper end ++ float f1 = this.a; + +- if (this.openCount > 0) { +- this.openness += 0.1F; ++ if (this.c > 0) { ++ this.a += 0.1F; + } else { +- this.openness -= 0.1F; ++ this.a -= 0.1F; + } + +- if (this.openness > 1.0F) { +- this.openness = 1.0F; ++ if (this.a > 1.0F) { ++ this.a = 1.0F; + } + + float f2 = 0.5F; + +- if (this.openness < 0.5F && f1 >= 0.5F) { ++ if (this.a < 0.5F && f1 >= 0.5F) { ++ // Paper start ++ */ + d0 = (double) i + 0.5D; + double d2 = (double) k + 0.5D; + ++ MCUtil.scheduleTask(10, () -> { + this.level.playSound((Player) null, d0, (double) j + 0.5D, d2, SoundEvents.ENDER_CHEST_CLOSE, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); +- } ++ }, "Chest Sounds"); + + if (this.openness < 0.0F) { + this.openness = 0.0F; +@@ -84,11 +107,13 @@ public class EnderChestBlockEntity extends BlockEntity implements TickableBlockE + public void startOpen() { + ++this.openCount; + this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); ++ doOpenLogic(); // Paper + } + + public void stopOpen() { + --this.openCount; + this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); ++ doCloseLogic(); // Paper + } + + public boolean stillValid(Player entityhuman) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java +index 60ce75c7f94c995d3753c40bc8d1ec09b4d37b1a..ac10fb9cd4701f0f6477a86bec73cb5ac6496725 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java ++++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java +@@ -84,6 +84,7 @@ public abstract class StateHolder { + return Collections.unmodifiableCollection(this.values.keySet()); + } + ++ public > boolean contains(Property iblockstate) { return this.hasProperty(iblockstate); } // Paper - OBFHELPER + public > boolean hasProperty(Property property) { + return this.values.containsKey(property); + } diff --git a/patches/server-remapped/0024-Further-improve-server-tick-loop.patch b/patches/server-remapped/0024-Further-improve-server-tick-loop.patch new file mode 100644 index 0000000000..ee0ab66ab5 --- /dev/null +++ b/patches/server-remapped/0024-Further-improve-server-tick-loop.patch @@ -0,0 +1,208 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 1 Mar 2016 23:09:29 -0600 +Subject: [PATCH] Further improve server tick loop + +Improves how the catchup buffer is handled, allowing it to roll both ways +increasing the effeciency of the thread sleep so it only will sleep once. + +Also increases the buffer of the catchup to ensure server stays at 20 TPS unless extreme conditions + +Previous implementation did not calculate TPS correctly. +Switch to a realistic rolling average and factor in std deviation as an extra reporting variable + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index fa29790600021809f31092a90e1a3a9b84d5e0c4..526d6c0fa45bfba92a3f964f72e4965fd5c841c1 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -251,7 +251,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; + public Commands vanillaCommandDispatcher; +@@ -260,7 +260,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 5000L && this.nextTickTime - this.lastOverloadWarning >= 30000L) { // CraftBukkit + long j = i / 50L; + + if (server.getWarnOnOverload()) // CraftBukkit +- MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); ++ MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); + this.nextTickTime += j * 50L; + this.lastOverloadWarning = this.nextTickTime; + } + +- if ( tickCount++ % SAMPLE_INTERVAL == 0 ) ++ if ( ++MinecraftServer.currentTick % SAMPLE_INTERVAL == 0 ) + { +- double currentTps = 1E3 / ( curTime - tickSection ) * SAMPLE_INTERVAL; +- recentTps[0] = calcTps( recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min) +- recentTps[1] = calcTps( recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min) +- recentTps[2] = calcTps( recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min) ++ final long diff = curTime - tickSection; ++ java.math.BigDecimal currentTps = TPS_BASE.divide(new java.math.BigDecimal(diff), 30, java.math.RoundingMode.HALF_UP); ++ tps1.add(currentTps, diff); ++ tps5.add(currentTps, diff); ++ tps15.add(currentTps, diff); ++ // Backwards compat with bad plugins ++ recentTps[0] = tps1.getAverage(); ++ recentTps[1] = tps5.getAverage(); ++ recentTps[2] = tps15.getAverage(); ++ // Paper end + tickSection = curTime; + } + // Spigot end + +- MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit ++ //MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit // Paper - don't overwrite current tick time ++ lastTick = curTime; + this.nextTickTime += 50L; + SingleTickProfiler gameprofilertick = SingleTickProfiler.createTickProfiler("Server"); + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index f81def94a1a7ab3a24b74a8bbd5f3e8ebae2c0d5..6fa31ca31128b1094eebd5f848c5b506dfeedeeb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2121,6 +2121,17 @@ public final class CraftServer implements Server { + return CraftMagicNumbers.INSTANCE; + } + ++ // Paper - Add getTPS API - Further improve tick loop ++ @Override ++ public double[] getTPS() { ++ return new double[] { ++ net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(), ++ net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(), ++ net.minecraft.server.MinecraftServer.getServer().tps15.getAverage() ++ }; ++ } ++ // Paper end ++ + // Spigot start + private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() + { +diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java +index f5b6dec1cbe7501ce2ee9125920e810bc94670cc..e62890433ffbe0b4e48942fe6c38b599a19e58fd 100644 +--- a/src/main/java/org/spigotmc/TicksPerSecondCommand.java ++++ b/src/main/java/org/spigotmc/TicksPerSecondCommand.java +@@ -24,22 +24,30 @@ public class TicksPerSecondCommand extends Command + return true; + } + +- StringBuilder sb = new StringBuilder( ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " ); +- for ( double tps : MinecraftServer.getServer().recentTps ) +- { +- sb.append( format( tps ) ); +- sb.append( ", " ); ++ // Paper start - Further improve tick handling ++ double[] tps = org.bukkit.Bukkit.getTPS(); ++ String[] tpsAvg = new String[tps.length]; ++ ++ for ( int i = 0; i < tps.length; i++) { ++ tpsAvg[i] = format( tps[i] ); ++ } ++ sender.sendMessage(ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " + org.apache.commons.lang.StringUtils.join(tpsAvg, ", ")); ++ if (args.length > 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) { ++ sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); ++ if (!hasShownMemoryWarning) { ++ sender.sendMessage(ChatColor.RED + "Warning: " + ChatColor.GOLD + " Memory usage on modern garbage collectors is not a stable value and it is perfectly normal to see it reach max. Please do not pay it much attention."); ++ hasShownMemoryWarning = true; ++ } + } +- sender.sendMessage( sb.substring( 0, sb.length() - 2 ) ); +- sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " +- + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); ++ // Paper end + + return true; + } + +- private String format(double tps) ++ private boolean hasShownMemoryWarning; // Paper ++ private static String format(double tps) // Paper - Made static + { + return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString() +- + ( ( tps > 20.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); ++ + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise + } + } diff --git a/patches/server-remapped/0025-Only-refresh-abilities-if-needed.patch b/patches/server-remapped/0025-Only-refresh-abilities-if-needed.patch new file mode 100644 index 0000000000..b310cdcaa1 --- /dev/null +++ b/patches/server-remapped/0025-Only-refresh-abilities-if-needed.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 23:12:03 -0600 +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 e6c39c822c6a910f63e9b4899d53b7d75e1b77cf..2920ba3d8eeb62670897ea19b50aaf395ab84c5a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1437,12 +1437,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + @Override + public void setFlying(boolean value) { ++ boolean needsUpdate = getHandle().abilities.flying != value; // Paper - Only refresh abilities if needed + if (!getAllowFlight() && value) { + throw new IllegalArgumentException("Cannot make player fly if getAllowFlight() is false"); + } + + getHandle().abilities.flying = value; +- getHandle().onUpdateAbilities(); ++ if (needsUpdate) getHandle().onUpdateAbilities(); // Paper - Only refresh abilities if needed + } + + @Override diff --git a/patches/server-remapped/0026-Entity-Origin-API.patch b/patches/server-remapped/0026-Entity-Origin-API.patch new file mode 100644 index 0000000000..cc2e7adc4a --- /dev/null +++ b/patches/server-remapped/0026-Entity-Origin-API.patch @@ -0,0 +1,140 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Tue, 1 Mar 2016 23:45:08 -0600 +Subject: [PATCH] Entity Origin API + + +diff --git a/src/main/java/net/minecraft/nbt/ListTag.java b/src/main/java/net/minecraft/nbt/ListTag.java +index 084340dc73acb3d972e0717b48da820c027a5137..7927ebac41eb1f257738238500cfe0c06031fcaf 100644 +--- a/src/main/java/net/minecraft/nbt/ListTag.java ++++ b/src/main/java/net/minecraft/nbt/ListTag.java +@@ -190,6 +190,7 @@ public class ListTag extends CollectionTag { + return new int[0]; + } + ++ public final double getDoubleAt(int i) { return this.getDouble(i); } // Paper - OBFHELPER + public double getDouble(int index) { + if (index >= 0 && index < this.list.size()) { + Tag nbtbase = (Tag) this.list.get(index); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0cc86ca4ea4a2e1b5acc3c0507397eef85dec0c1..d2bb9385fbc21cdef6cef06680fac685d3da3570 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1240,6 +1240,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.navigations.add(((Mob) entity).getNavigation()); + } + entity.valid = true; // CraftBukkit ++ // Paper start - Set origin location when the entity is being added to the world ++ if (entity.origin == null) { ++ entity.origin = entity.getBukkitEntity().getLocation(); ++ } ++ // Paper end + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 392f2f2d67b688d5b37f77c8e4b3036348472d77..fd5b41ceb97dc8aa975f1c0ae05b58d0b09f2cd6 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -246,6 +246,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only + public boolean forceExplosionKnockback; // SPIGOT-949 + public boolean persistentInvisibility = false; ++ public org.bukkit.Location origin; // Paper + // Spigot start + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; +@@ -1624,6 +1625,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.bukkitEntity.storeBukkitValues(tag); + } + // CraftBukkit end ++ // Paper start - Save the entity's origin location ++ if (this.origin != null) { ++ tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); ++ tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); ++ } ++ // Paper end + return tag; + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); +@@ -1746,6 +1753,17 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + // CraftBukkit end + ++ // Paper start - Restore the entity's origin location ++ ListTag originTag = tag.getList("Paper.Origin", 6); ++ if (!originTag.isEmpty()) { ++ org.bukkit.World originWorld = level.getWorld(); ++ if (tag.contains("Paper.OriginWorld")) { ++ originWorld = Bukkit.getWorld(tag.getUUID("Paper.OriginWorld")); ++ } ++ origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); ++ } ++ // Paper end ++ + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded"); +@@ -1807,6 +1825,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + protected abstract void addAdditionalSaveData(CompoundTag tag); + ++ protected final ListTag createList(double... adouble) { return newDoubleList(adouble); } // Paper - OBFHELPER + protected ListTag newDoubleList(double... values) { + ListTag nbttaglist = new ListTag(); + double[] adouble1 = values; +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 5394bc6336cb84025c1c748fb5b3d38e0648a590..1d87717cc9002ea202ee2ca614aaa8a4c7ea3cb2 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -291,6 +291,14 @@ public class FallingBlockEntity extends Entity { + this.blockState = Blocks.SAND.defaultBlockState(); + } + ++ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility ++ if (tag.contains("SourceLoc_x")) { ++ int srcX = tag.getInt("SourceLoc_x"); ++ int srcY = tag.getInt("SourceLoc_y"); ++ int srcZ = tag.getInt("SourceLoc_z"); ++ origin = new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ); ++ } ++ // Paper end + } + + public void setHurtsEntities(boolean hurtEntities) { +diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +index 4c4262b8f0cb44b8cea8cb46194a6e70d4ce56f4..661848084fd986321ef782317934dac19ed4dce3 100644 +--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +@@ -119,6 +119,14 @@ public class PrimedTnt extends Entity { + @Override + protected void readAdditionalSaveData(CompoundTag tag) { + this.setFuse(tag.getShort("Fuse")); ++ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility ++ if (tag.contains("SourceLoc_x")) { ++ int srcX = tag.getInt("SourceLoc_x"); ++ int srcY = tag.getInt("SourceLoc_y"); ++ int srcZ = tag.getInt("SourceLoc_z"); ++ origin = new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ); ++ } ++ // Paper end + } + + @Nullable +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 53c231925ef1b17e48c5863570e3c54124874621..e7a59a8e0424a0839dfa73fc65f44c5b04bd3dec 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1062,4 +1062,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return spigot; + } + // Spigot end ++ ++ // Paper start ++ @Override ++ public Location getOrigin() { ++ Location origin = getHandle().origin; ++ return origin == null ? null : origin.clone(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0027-Prevent-tile-entity-and-entity-crashes.patch b/patches/server-remapped/0027-Prevent-tile-entity-and-entity-crashes.patch new file mode 100644 index 0000000000..cf3cf1beaa --- /dev/null +++ b/patches/server-remapped/0027-Prevent-tile-entity-and-entity-crashes.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 1 Mar 2016 23:52:34 -0600 +Subject: [PATCH] Prevent tile entity and entity crashes + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 832abf73bdab2488c5814ea6e57888aac1b26154..870843254d1c1fc49bc101a49cdf9d300ae3ca1b 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -737,11 +737,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + gameprofilerfiller.pop(); + } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking block entity"); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block entity being ticked"); +- +- tileentity.fillCrashReportCategory(crashreportsystemdetails); +- throw new ReportedException(crashreport); ++ // Paper start - Prevent tile entity and entity crashes ++ System.err.println("TileEntity threw exception at " + tileentity.level.getWorld().getName() + ":" + tileentity.worldPosition.getX() + "," + tileentity.worldPosition.getY() + "," + tileentity.worldPosition.getZ()); ++ throwable.printStackTrace(); ++ tilesThisCycle--; ++ this.tickableBlockEntities.remove(tileTickPosition--); ++ continue; ++ // Paper end + // Spigot start + } finally { + tileentity.tickTimer.stopTiming(); +@@ -806,11 +808,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + try { + tickConsumer.accept(entity); + } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); +- +- entity.fillCrashReportCategory(crashreportsystemdetails); +- throw new ReportedException(crashreport); ++ // Paper start - Prevent tile entity and entity crashes ++ System.err.println("Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ()); ++ throwable.printStackTrace(); ++ entity.removed = true; ++ return; ++ // Paper end + } + } + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index d445a1b7b7605eed66923789c5d8e2199c31c5ac..13115d1b28dfa2d87b45a50bd0feaa7f57769122 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -208,7 +208,12 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + return Registry.BLOCK_ENTITY_TYPE.getKey(this.getType()) + " // " + this.getClass().getCanonicalName(); + }); + if (this.level != null) { +- CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.worldPosition, this.getBlockState()); ++ // Paper start - Prevent TileEntity and Entity crashes ++ BlockState block = this.getBlockState(); ++ if (block != null) { ++ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.worldPosition, block); ++ } ++ // Paper end + CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.worldPosition, this.level.getBlockState(this.worldPosition)); + } + } diff --git a/patches/server-remapped/0028-Configurable-top-of-nether-void-damage.patch b/patches/server-remapped/0028-Configurable-top-of-nether-void-damage.patch new file mode 100644 index 0000000000..805929cc33 --- /dev/null +++ b/patches/server-remapped/0028-Configurable-top-of-nether-void-damage.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 23:58:50 -0600 +Subject: [PATCH] Configurable top of nether void damage + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index d16ae924bcbe31c964f7fb448757c748e5c4418c..4bba6977a0287837b8927718c040ac61463f0469 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -134,4 +134,19 @@ public class PaperWorldConfig { + if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); + if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); + } ++ ++ public int netherVoidTopDamageHeight; ++ public boolean doNetherTopVoidDamage() { return netherVoidTopDamageHeight > 0; } ++ private void netherVoidTopDamageHeight() { ++ netherVoidTopDamageHeight = getInt("nether-ceiling-void-damage-height", 0); ++ log("Top of the nether void damage height: " + netherVoidTopDamageHeight); ++ ++ if (PaperConfig.version < 18) { ++ boolean legacy = getBoolean("nether-ceiling-void-damage", false); ++ if (legacy) { ++ netherVoidTopDamageHeight = 128; ++ set("nether-ceiling-void-damage-height", netherVoidTopDamageHeight); ++ } ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index fd5b41ceb97dc8aa975f1c0ae05b58d0b09f2cd6..f3f48c268639937874dd39eea9bd8e119eebdce7 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -499,9 +499,16 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.fallDistance *= 0.5F; + } + +- if (this.getY() < -64.0D) { +- this.outOfWorld(); ++ // Paper start - Configurable nether ceiling damage ++ ++ // Extracted to own function ++ /* ++ if (this.locY() < -64.0D) { ++ this.an(); + } ++ */ ++ this.performVoidDamage(); ++ // Paper end + + if (!this.level.isClientSide) { + this.setSharedFlag(0, this.remainingFireTicks > 0); +@@ -594,6 +601,17 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.setRemainingFireTicks(0); + } + ++ // Paper start ++ protected void performVoidDamage() { ++ if (this.getY() < -64.0D || (this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER ++ && level.paperConfig.doNetherTopVoidDamage() ++ && this.getY() >= level.paperConfig.netherVoidTopDamageHeight)) { ++ this.doVoidDamage(); ++ } ++ } ++ // Paper end ++ ++ protected final void doVoidDamage() { this.outOfWorld(); } // Paper - OBFHELPER + protected void outOfWorld() { + this.remove(); + } +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 9503376895d90e8db0d4f7b164e2d813dd1a4a3a..7ba74b0a9319e29077b5afe3019a463ed3004813 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -329,9 +329,15 @@ public abstract class AbstractMinecart extends Entity { + this.setDamage(this.getDamage() - 1.0F); + } + +- if (this.getY() < -64.0D) { +- this.outOfWorld(); ++ // Paper start - Configurable nether ceiling damage ++ // Extracted to own function ++ /* ++ if (this.locY() < -64.0D) { ++ this.an(); + } ++ */ ++ this.performVoidDamage(); ++ // Paper end + + // this.doPortalTick(); // CraftBukkit - handled in postTick + if (this.level.isClientSide) { diff --git a/patches/server-remapped/0029-Check-online-mode-before-converting-and-renaming-pla.patch b/patches/server-remapped/0029-Check-online-mode-before-converting-and-renaming-pla.patch new file mode 100644 index 0000000000..56a96d8cfe --- /dev/null +++ b/patches/server-remapped/0029-Check-online-mode-before-converting-and-renaming-pla.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Mar 2016 00:03:55 -0600 +Subject: [PATCH] Check online mode before converting and renaming player data + + +diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +index 067c5acd4aad346ac9ccf6d1b5aa6691b0ccd348..60fe01e824e4657d2601797d7858d5de339ab255 100644 +--- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +@@ -56,7 +56,7 @@ public class PlayerDataStorage { + File file = new File(this.playerDir, entityhuman.getStringUUID() + ".dat"); + // Spigot Start + boolean usingWrongFile = false; +- if ( !file.exists() ) ++ if ( org.bukkit.Bukkit.getOnlineMode() && !file.exists() ) // Paper - Check online mode first + { + file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + entityhuman.getScoreboardName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); + if ( file.exists() ) diff --git a/patches/server-remapped/0030-Always-tick-falling-blocks.patch b/patches/server-remapped/0030-Always-tick-falling-blocks.patch new file mode 100644 index 0000000000..29eba4b28a --- /dev/null +++ b/patches/server-remapped/0030-Always-tick-falling-blocks.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Mar 2016 00:32:25 -0600 +Subject: [PATCH] Always tick falling blocks + + +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 9bb35ec64e1538aabec9ff7831706c4717239449..0a9bd85e0308e962df3b24a74bd5aac919744d6d 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -91,6 +91,7 @@ public class ActivationRange + || entity instanceof AbstractHurtingProjectile + || entity instanceof LightningBolt + || entity instanceof PrimedTnt ++ || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks + || entity instanceof EndCrystal + || entity instanceof FireworkRocketEntity + || entity instanceof ThrownTrident ) diff --git a/patches/server-remapped/0031-Configurable-end-credits.patch b/patches/server-remapped/0031-Configurable-end-credits.patch new file mode 100644 index 0000000000..201a2e7284 --- /dev/null +++ b/patches/server-remapped/0031-Configurable-end-credits.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DoctorDark +Date: Wed, 16 Mar 2016 02:21:39 -0500 +Subject: [PATCH] Configurable end credits + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4bba6977a0287837b8927718c040ac61463f0469..e6e18f309dc09ea9416ea37dcc697ddc2b571a96 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -149,4 +149,10 @@ public class PaperWorldConfig { + } + } + } ++ ++ public boolean disableEndCredits; ++ private void disableEndCredits() { ++ disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); ++ log("End credits disabled: " + disableEndCredits); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index ca647b3afbe8da5847dc8fa890ae9ca5c18e03d9..f3797bd761c2c6782cce3fca25bc9ef37e5c4978 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -188,7 +188,7 @@ public class ServerPlayer extends Player implements ContainerListener { + private long lastActionTime = Util.getMillis(); + private Entity camera; + public boolean isChangingDimension; +- private boolean seenCredits; ++ private boolean seenCredits; private void setHasSeenCredits(boolean has) { this.seenCredits = has; } // Paper - OBFHELPER + private final ServerRecipeBook recipeBook = new ServerRecipeBook(); + private Vec3 levitationStartPos; + private int levitationStartTime; +@@ -893,6 +893,7 @@ public class ServerPlayer extends Player implements ContainerListener { + this.unRide(); + this.getLevel().removePlayerImmediately(this); + if (!this.wonGame) { ++ if (level.paperConfig.disableEndCredits) this.setHasSeenCredits(true); // Paper - Toggle to always disable end credits + this.wonGame = true; + this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.WIN_GAME, this.seenCredits ? 0.0F : 1.0F)); + this.seenCredits = true; diff --git a/patches/server-remapped/0032-Fix-lag-from-explosions-processing-dead-entities.patch b/patches/server-remapped/0032-Fix-lag-from-explosions-processing-dead-entities.patch new file mode 100644 index 0000000000..a9fb2be3bd --- /dev/null +++ b/patches/server-remapped/0032-Fix-lag-from-explosions-processing-dead-entities.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Iceee +Date: Wed, 2 Mar 2016 01:39:52 -0600 +Subject: [PATCH] Fix lag from explosions processing dead entities + + +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 54c3bfead8497f64c183f5612676803d91fc557b..8d6cd2a5b16d99cb8e754ce04b2d12fee7ffb4d0 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -180,7 +180,7 @@ public class Explosion { + int i1 = Mth.floor(this.y + (double) f2 + 1.0D); + int j1 = Mth.floor(this.z - (double) f2 - 1.0D); + int k1 = Mth.floor(this.z + (double) f2 + 1.0D); +- List list = this.level.getEntities(this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1)); ++ List list = this.level.getEntities(this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1), (com.google.common.base.Predicate) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities + Vec3 vec3d = new Vec3(this.x, this.y, this.z); + + for (int l1 = 0; l1 < list.size(); ++l1) { diff --git a/patches/server-remapped/0033-Optimize-explosions.patch b/patches/server-remapped/0033-Optimize-explosions.patch new file mode 100644 index 0000000000..ec1e34fc38 --- /dev/null +++ b/patches/server-remapped/0033-Optimize-explosions.patch @@ -0,0 +1,148 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 2 Mar 2016 11:59:48 -0600 +Subject: [PATCH] Optimize explosions + +The process of determining an entity's exposure from explosions can be +expensive when there are hundreds or more entities in range. + +This patch adds a per-tick cache that is used for storing and retrieving +an entity's exposure during an explosion. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e6e18f309dc09ea9416ea37dcc697ddc2b571a96..4881b03d470646843bad1bc343eb6a6ab9072d8e 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -155,4 +155,10 @@ public class PaperWorldConfig { + disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); + log("End credits disabled: " + disableEndCredits); + } ++ ++ public boolean optimizeExplosions; ++ private void optimizeExplosions() { ++ optimizeExplosions = getBoolean("optimize-explosions", false); ++ log("Optimize explosions: " + optimizeExplosions); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 526d6c0fa45bfba92a3f964f72e4965fd5c841c1..901d5497667706c049718dc4fca37a1bc489c465 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1324,6 +1324,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop>> 32)); ++ temp = Double.doubleToLongBits(posY); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(posZ); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(minX); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(minY); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(minZ); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(maxX); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(maxY); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(maxZ); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ return result; ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 870843254d1c1fc49bc101a49cdf9d300ae3ca1b..f71b56fa079e2c7b2123061a8e1a7cb41935bab6 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -136,6 +136,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + private org.spigotmc.TickLimiter entityLimiter; + private org.spigotmc.TickLimiter tileLimiter; + private int tileTickPosition; ++ public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions + + public CraftWorld getWorld() { + return this.world; diff --git a/patches/server-remapped/0034-Disable-explosion-knockback.patch b/patches/server-remapped/0034-Disable-explosion-knockback.patch new file mode 100644 index 0000000000..d9f4ff9678 --- /dev/null +++ b/patches/server-remapped/0034-Disable-explosion-knockback.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 14:48:03 -0600 +Subject: [PATCH] Disable explosion knockback + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4881b03d470646843bad1bc343eb6a6ab9072d8e..2222c1bb5f8625eee4d88946e4bfdfa2fe598977 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -161,4 +161,9 @@ public class PaperWorldConfig { + optimizeExplosions = getBoolean("optimize-explosions", false); + log("Optimize explosions: " + optimizeExplosions); + } ++ ++ public boolean disableExplosionKnockback; ++ private void disableExplosionKnockback(){ ++ disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index e5f8cee6726ea9a90c540bb10fd8594a35bb5e40..afd114e1ce00db72534d470fed12101bb237f266 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1280,6 +1280,7 @@ public abstract class LivingEntity extends Entity { + } + } + ++ boolean knockbackCancelled = level.paperConfig.disableExplosionKnockback && source.isExplosion() && this instanceof net.minecraft.world.entity.player.Player; // Paper - Disable explosion knockback + if (flag1) { + if (flag) { + this.level.broadcastEntityEvent(this, (byte) 29); +@@ -1298,6 +1299,7 @@ public abstract class LivingEntity extends Entity { + b0 = 2; + } + ++ if (!knockbackCancelled) // Paper - Disable explosion knockback + this.level.broadcastEntityEvent(this, b0); + } + +@@ -1321,6 +1323,7 @@ public abstract class LivingEntity extends Entity { + } + } + ++ if (knockbackCancelled) this.level.broadcastEntityEvent(this, (byte) 2); // Paper - Disable explosion knockback + if (this.isDeadOrDying()) { + if (!this.checkTotemDeathProtection(source)) { + SoundEvent soundeffect = this.getDeathSound(); +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index db46caaa5ad5f129d313c65c5006cb24853768be..45a75f7be308678336e192828becf6cf5c9047bc 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -215,14 +215,14 @@ public class Explosion { + double d14 = d13; + + if (entity instanceof LivingEntity) { +- d14 = ProtectionEnchantment.getExplosionKnockbackAfterDampener((LivingEntity) entity, d13); ++ d14 = entity instanceof Player && level.paperConfig.disableExplosionKnockback ? 0 : ProtectionEnchantment.getExplosionKnockbackAfterDampener((LivingEntity) entity, d13); // Paper - Disable explosion knockback + } + + entity.setDeltaMovement(entity.getDeltaMovement().add(d8 * d14, d9 * d14, d10 * d14)); + if (entity instanceof Player) { + Player entityhuman = (Player) entity; + +- if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.flying)) { ++ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.flying) && !level.paperConfig.disableExplosionKnockback) { // Paper - Disable explosion knockback + this.hitPlayers.put(entityhuman, new Vec3(d8 * d13, d9 * d13, d10 * d13)); + } + } diff --git a/patches/server-remapped/0035-Disable-thunder.patch b/patches/server-remapped/0035-Disable-thunder.patch new file mode 100644 index 0000000000..d5971380bb --- /dev/null +++ b/patches/server-remapped/0035-Disable-thunder.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 14:52:43 -0600 +Subject: [PATCH] Disable thunder + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2222c1bb5f8625eee4d88946e4bfdfa2fe598977..083e421f8496b5336af473b108498ed28b984774 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -166,4 +166,9 @@ public class PaperWorldConfig { + private void disableExplosionKnockback(){ + disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); + } ++ ++ public boolean disableThunder; ++ private void disableThunder() { ++ disableThunder = getBoolean("disable-thunder", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index d2bb9385fbc21cdef6cef06680fac685d3da3570..3fc8fb197400c63bc85f57ff484803659619f775 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -580,7 +580,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + gameprofilerfiller.push("thunder"); + BlockPos blockposition; + +- if (flag && this.isThundering() && this.random.nextInt(100000) == 0) { ++ if (!this.paperConfig.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder + blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); + if (this.isRainingAt(blockposition)) { + DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); diff --git a/patches/server-remapped/0036-Disable-ice-and-snow.patch b/patches/server-remapped/0036-Disable-ice-and-snow.patch new file mode 100644 index 0000000000..9d2d87a6b0 --- /dev/null +++ b/patches/server-remapped/0036-Disable-ice-and-snow.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 14:57:24 -0600 +Subject: [PATCH] Disable ice and snow + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 083e421f8496b5336af473b108498ed28b984774..2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -171,4 +171,9 @@ public class PaperWorldConfig { + private void disableThunder() { + disableThunder = getBoolean("disable-thunder", false); + } ++ ++ public boolean disableIceAndSnow; ++ private void disableIceAndSnow(){ ++ disableIceAndSnow = getBoolean("disable-ice-and-snow", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 3fc8fb197400c63bc85f57ff484803659619f775..6c6098731752d61b5241710b075d4ffe3826daac 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -604,7 +604,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + gameprofilerfiller.popPush("iceandsnow"); +- if (this.random.nextInt(16) == 0) { ++ if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow + blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.getBlockRandomPos(j, 0, k, 15)); + BlockPos blockposition1 = blockposition.below(); + Biome biomebase = this.getBiome(blockposition); diff --git a/patches/server-remapped/0037-Configurable-mob-spawner-tick-rate.patch b/patches/server-remapped/0037-Configurable-mob-spawner-tick-rate.patch new file mode 100644 index 0000000000..454050d2c3 --- /dev/null +++ b/patches/server-remapped/0037-Configurable-mob-spawner-tick-rate.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 15:03:53 -0600 +Subject: [PATCH] Configurable mob spawner tick rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2..4de86b09c6bc3c1974ce61b550ccb73d37f6f170 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -176,4 +176,9 @@ public class PaperWorldConfig { + private void disableIceAndSnow(){ + disableIceAndSnow = getBoolean("disable-ice-and-snow", false); + } ++ ++ public int mobSpawnerTickRate; ++ private void mobSpawnerTickRate() { ++ mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 10058d3c3565382faa893b79119c5caf845bf29a..ed631d5bfba5d2543e8eed017a7c484ad3ddb453 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -41,6 +41,7 @@ public abstract class BaseSpawner { + public int maxNearbyEntities = 6; + public int requiredPlayerRange = 16; + public int spawnRange = 4; ++ private int tickDelay = 0; // Paper + + public BaseSpawner() {} + +@@ -70,6 +71,10 @@ public abstract class BaseSpawner { + } + + public void tick() { ++ // Paper start - Configurable mob spawner tick rate ++ if (spawnDelay > 0 && --tickDelay > 0) return; ++ tickDelay = this.getLevel().paperConfig.mobSpawnerTickRate; ++ // Paper end + if (!this.isNearPlayer()) { + this.oSpin = this.spin; + } else { +@@ -84,18 +89,18 @@ public abstract class BaseSpawner { + world.addParticle(ParticleTypes.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + world.addParticle(ParticleTypes.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D); + if (this.spawnDelay > 0) { +- --this.spawnDelay; ++ this.spawnDelay -= tickDelay; // Paper + } + + this.oSpin = this.spin; + this.spin = (this.spin + (double) (1000.0F / ((float) this.spawnDelay + 200.0F))) % 360.0D; + } else { +- if (this.spawnDelay == -1) { ++ if (this.spawnDelay < -tickDelay) { // Paper + this.delay(); + } + + if (this.spawnDelay > 0) { +- --this.spawnDelay; ++ this.spawnDelay -= tickDelay; // Paper + return; + } + diff --git a/patches/server-remapped/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch b/patches/server-remapped/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch new file mode 100644 index 0000000000..c77faa1999 --- /dev/null +++ b/patches/server-remapped/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Wed, 2 Mar 2016 23:13:07 -0600 +Subject: [PATCH] Send absolute position the first time an entity is seen + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 59a5f82c9f57d760ba4959a040ce8cbf0f49e4aa..d1bc927c8b429f43de2cdad98f8b329ff4c8b4db 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1301,10 +1301,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private final Entity entity; + private final int range; + private SectionPos lastSectionPos; +- public final Set seenBy = Sets.newHashSet(); ++ // Paper start ++ // Replace trackedPlayers Set with a Map. The value is true until the player receives ++ // their first update (which is forced to have absolute coordinates), false afterward. ++ public java.util.Map trackedPlayerMap = new java.util.HashMap<>(); ++ public Set seenBy = trackedPlayerMap.keySet(); + + public TrackedEntity(Entity entity, int i, int j, boolean flag) { +- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, seenBy); // CraftBukkit ++ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, trackedPlayerMap); // CraftBukkit // Paper + this.entity = entity; + this.range = i; + this.lastSectionPos = SectionPos.of(entity); +@@ -1386,7 +1390,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + player.entitiesToRemove.remove(Integer.valueOf(this.entity.getId())); + // CraftBukkit end + +- if (flag1 && this.seenBy.add(player)) { ++ if (flag1 && this.trackedPlayerMap.putIfAbsent(player, true) == null) { // Paper + this.serverEntity.addPairing(player); + } + } else if (this.seenBy.remove(player)) { +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index 3d386627b6d3d33da76372e4a14d0c5000eb8ffc..fa6893055fa5617742bfb4b7eff60c8139395cb6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -4,6 +4,7 @@ import com.google.common.collect.Lists; + import com.mojang.datafixers.util.Pair; + import java.util.Collection; + import java.util.Collections; ++import java.util.HashSet; + import java.util.Iterator; + import java.util.List; + import java.util.Set; +@@ -51,7 +52,7 @@ public class ServerEntity { + private final Entity entity; + private final int updateInterval; + private final boolean trackDelta; +- private final Consumer> broadcast; ++ private final Consumer> broadcast; private Consumer> getPacketConsumer() { return broadcast; } // Paper - OBFHELPER + private long xp; + private long yp; + private long zp; +@@ -66,8 +67,23 @@ public class ServerEntity { + private boolean wasOnGround; + // CraftBukkit start + private final Set trackedPlayers; ++ // Paper start ++ private java.util.Map trackedPlayerMap = null; ++ ++ /** ++ * Requested in https://github.com/PaperMC/Paper/issues/1537 to allow intercepting packets ++ */ ++ public void sendPlayerPacket(ServerPlayer player, Packet packet) { ++ player.connection.send(packet); ++ } ++ ++ public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, java.util.Map trackedPlayers) { ++ this(worldserver, entity, i, flag, consumer, trackedPlayers.keySet()); ++ trackedPlayerMap = trackedPlayers; ++ } + + public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { ++ // Paper end + this.trackedPlayers = trackedPlayers; + // CraftBukkit end + this.ap = Vec3.ZERO; +@@ -188,7 +204,25 @@ public class ServerEntity { + } + + if (packet1 != null) { +- this.broadcast.accept(packet1); ++ // paper start ++ if (trackedPlayerMap == null || packet1 instanceof ClientboundTeleportEntityPacket) { ++ this.broadcast.accept((packet1)); ++ } else { ++ ClientboundTeleportEntityPacket teleportPacket = null; ++ ++ for (java.util.Map.Entry viewer : trackedPlayerMap.entrySet()) { ++ if (viewer.getValue()) { ++ viewer.setValue(false); ++ if (teleportPacket == null) { ++ teleportPacket = new ClientboundTeleportEntityPacket(this.entity); ++ } ++ sendPlayerPacket(viewer.getKey(), teleportPacket); ++ } else { ++ sendPlayerPacket(viewer.getKey(), packet1); ++ } ++ } ++ } ++ // Paper end + } + + this.sendDirtyEntityData(); diff --git a/patches/server-remapped/0039-Add-BeaconEffectEvent.patch b/patches/server-remapped/0039-Add-BeaconEffectEvent.patch new file mode 100644 index 0000000000..d61c3cadc2 --- /dev/null +++ b/patches/server-remapped/0039-Add-BeaconEffectEvent.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 2 Mar 2016 23:30:53 -0600 +Subject: [PATCH] Add BeaconEffectEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +index c91f7bcfab2da6a23114a3cff63ca31dab443393..5f75c6d653a31f65fcf9c0e280d796e15d059c00 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -25,7 +25,6 @@ import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.inventory.BeaconMenu; + import net.minecraft.world.inventory.ContainerData; +@@ -41,6 +40,11 @@ import net.minecraft.world.phys.AABB; + import org.bukkit.craftbukkit.potion.CraftPotionUtil; + import org.bukkit.potion.PotionEffect; + // CraftBukkit end ++// Paper start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.Player; ++import com.destroystokyo.paper.event.block.BeaconEffectEvent; ++// Paper end + + public class BeaconBlockEntity extends BlockEntity implements MenuProvider, TickableBlockEntity { + +@@ -260,21 +264,37 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + double d0 = (double) (this.levels * 10 + 10); + + AABB axisalignedbb = (new AABB(this.worldPosition)).inflate(d0).expandTowards(0.0D, (double) this.level.getMaxBuildHeight(), 0.0D); +- List list = this.level.getEntitiesOfClass(Player.class, axisalignedbb); ++ List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.player.Player.class, axisalignedbb); + + return list; + } + } + + private void applyEffect(List list, MobEffect effects, int i, int b0) { ++ // Paper - BeaconEffectEvent ++ applyEffect(list, effects, i, b0, true); ++ } ++ ++ private void applyEffect(List list, MobEffect effects, int i, int b0, boolean isPrimary) { ++ // Paper - BeaconEffectEvent + { + Iterator iterator = list.iterator(); + +- Player entityhuman; ++ net.minecraft.world.entity.player.Player entityhuman; ++ ++ // Paper start - BeaconEffectEvent ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ PotionEffect effect = CraftPotionUtil.toBukkit(new MobEffectInstance(effects, i, b0, true, true)); ++ // Paper end + + while (iterator.hasNext()) { +- entityhuman = (Player) iterator.next(); +- entityhuman.addEffect(new MobEffectInstance(effects, i, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); ++ entityhuman = (net.minecraft.world.entity.player.Player) iterator.next(); ++ ++ // Paper start - BeaconEffectEvent ++ BeaconEffectEvent event = new BeaconEffectEvent(block, effect, (Player) entityhuman.getBukkitEntity(), isPrimary); ++ if (CraftEventFactory.callEvent(event).isCancelled()) continue; ++ entityhuman.addEffect(new MobEffectInstance(CraftPotionUtil.fromBukkit(event.getEffect())), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); ++ // Paper end + } + } + } +@@ -297,10 +317,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + int i = getLevelCb(); + List list = getHumansInRange(); + +- applyEffect(list, this.primaryPower, i, b0); ++ applyEffect(list, this.primaryPower, i, b0, true); // Paper - BeaconEffectEvent + + if (hasSecondaryEffect()) { +- applyEffect(list, this.secondaryPower, i, 0); ++ applyEffect(list, this.secondaryPower, i, 0, false); // Paper - BeaconEffectEvent + } + } + +@@ -308,7 +328,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + // CraftBukkit end + + public void playSound(SoundEvent soundeffect) { +- this.level.playSound((Player) null, this.worldPosition, soundeffect, SoundSource.BLOCKS, 1.0F, 1.0F); ++ this.level.playSound((net.minecraft.world.entity.player.Player) null, this.worldPosition, soundeffect, SoundSource.BLOCKS, 1.0F, 1.0F); + } + + public int getLevels() { +@@ -368,7 +388,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + + @Nullable + @Override +- public AbstractContainerMenu createMenu(int syncId, Inventory inv, Player player) { ++ public AbstractContainerMenu createMenu(int syncId, Inventory inv, net.minecraft.world.entity.player.Player player) { + return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName()) ? new BeaconMenu(syncId, inv, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; + } + diff --git a/patches/server-remapped/0040-Configurable-container-update-tick-rate.patch b/patches/server-remapped/0040-Configurable-container-update-tick-rate.patch new file mode 100644 index 0000000000..3344a83459 --- /dev/null +++ b/patches/server-remapped/0040-Configurable-container-update-tick-rate.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 23:34:44 -0600 +Subject: [PATCH] Configurable container update tick rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4de86b09c6bc3c1974ce61b550ccb73d37f6f170..5a4c3a8c511f22c8c3240c9c7cd83a65119c1054 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -181,4 +181,9 @@ public class PaperWorldConfig { + private void mobSpawnerTickRate() { + mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); + } ++ ++ public int containerUpdateTickRate; ++ private void containerUpdateTickRate() { ++ containerUpdateTickRate = getInt("container-update-tick-rate", 1); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index f3797bd761c2c6782cce3fca25bc9ef37e5c4978..ffad931c72e52855a3f139354f5e85c460e2a80b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -207,6 +207,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public boolean ignoreSlotUpdateHack; + public int latency; + public boolean wonGame; ++ private int containerUpdateDelay; // Paper + + // CraftBukkit start + public String displayName; +@@ -531,7 +532,12 @@ public class ServerPlayer extends Player implements ContainerListener { + --this.invulnerableTime; + } + +- this.containerMenu.broadcastChanges(); ++ // Paper start - Configurable container update tick rate ++ if (--containerUpdateDelay <= 0) { ++ this.containerMenu.broadcastChanges(); ++ containerUpdateDelay = level.paperConfig.containerUpdateTickRate; ++ } ++ // Paper end + if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { + this.closeContainer(); + this.containerMenu = this.inventoryMenu; diff --git a/patches/server-remapped/0041-Use-UserCache-for-player-heads.patch b/patches/server-remapped/0041-Use-UserCache-for-player-heads.patch new file mode 100644 index 0000000000..1c9a8dab7e --- /dev/null +++ b/patches/server-remapped/0041-Use-UserCache-for-player-heads.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Wed, 2 Mar 2016 23:42:37 -0600 +Subject: [PATCH] Use UserCache for player heads + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +index 11baf6fd5f7e408a570d5a48ae6b2fc05cd7e243..313ddd6b64e395a8caab77b3da005e52006ab2d7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +@@ -166,7 +166,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + if (name == null) { + setProfile(null); + } else { +- setProfile(new GameProfile(null, name)); ++ // Paper start - Use Online Players Skull ++ GameProfile newProfile = null; ++ net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); ++ if (player != null) newProfile = player.getProfile(); ++ if (newProfile == null) newProfile = new GameProfile(null, name); ++ setProfile(newProfile); ++ // Paper end + } + + return true; diff --git a/patches/server-remapped/0042-Disable-spigot-tick-limiters.patch b/patches/server-remapped/0042-Disable-spigot-tick-limiters.patch new file mode 100644 index 0000000000..703b1b0774 --- /dev/null +++ b/patches/server-remapped/0042-Disable-spigot-tick-limiters.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Mar 2016 23:45:17 -0600 +Subject: [PATCH] Disable spigot tick limiters + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index f71b56fa079e2c7b2123061a8e1a7cb41935bab6..e25666328dbf433b8358f2637d93b4128034bbaa 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -707,9 +707,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Spigot start + // Iterator iterator = this.tileEntityListTick.iterator(); + int tilesThisCycle = 0; +- for (tileLimiter.initTick(); +- tilesThisCycle < tickableBlockEntities.size() && (tilesThisCycle % 10 != 0 || tileLimiter.shouldContinue()); +- tileTickPosition++, tilesThisCycle++) { ++ for (tileTickPosition = 0; tileTickPosition < tickableBlockEntities.size(); tileTickPosition++) { // Paper - Disable tick limiters + tileTickPosition = (tileTickPosition < tickableBlockEntities.size()) ? tileTickPosition : 0; + BlockEntity tileentity = (BlockEntity) this.tickableBlockEntities.get(tileTickPosition); + // Spigot start diff --git a/patches/server-remapped/0043-Add-PlayerInitialSpawnEvent.patch b/patches/server-remapped/0043-Add-PlayerInitialSpawnEvent.patch new file mode 100644 index 0000000000..7e6b238460 --- /dev/null +++ b/patches/server-remapped/0043-Add-PlayerInitialSpawnEvent.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Steve Anton +Date: Thu, 3 Mar 2016 00:09:38 -0600 +Subject: [PATCH] Add PlayerInitialSpawnEvent + +For modifying a player's initial spawn location as they join the server + +This is a duplicate API from spigot, so use our duplicate subclass and +improve setPosition to use raw + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 8cdecaf2f63c78196e0c5046fe2431b40e072c8a..a63babe123fad398b07685ec57cd88756435457c 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -209,7 +209,7 @@ public abstract class PlayerList { + + // Spigot start - spawn location event + Player bukkitPlayer = player.getBukkitEntity(); +- org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(bukkitPlayer, bukkitPlayer.getLocation()); ++ org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(bukkitPlayer, bukkitPlayer.getLocation()); // Paper use our duplicate event + cserver.getPluginManager().callEvent(ev); + + Location loc = ev.getSpawnLocation(); +@@ -217,7 +217,10 @@ public abstract class PlayerList { + + player.setLevel(worldserver1); + player.gameMode.setLevel((ServerLevel) player.level); +- player.absMoveTo(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); ++ // Paper start - set raw so we aren't fully joined to the world (not added to chunk or world) ++ player.setPosRaw(loc.getX(), loc.getY(), loc.getZ()); ++ player.setRot(loc.getYaw(), loc.getPitch()); ++ // Paper end + // Spigot end + + // CraftBukkit - Moved message to after join +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index f3f48c268639937874dd39eea9bd8e119eebdce7..72eb40f748c33572c2828f48ebd1ca7d5d5712c8 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -397,7 +397,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return d1 * d1 + d2 * d2 + d3 * d3 < radius * radius; + } + +- protected void setRot(float yaw, float pitch) { ++ public void setRot(float yaw, float pitch) { // Paper - protected -> public + // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 + if (Float.isNaN(yaw)) { + yaw = 0; diff --git a/patches/server-remapped/0044-Configurable-Disabling-Cat-Chest-Detection.patch b/patches/server-remapped/0044-Configurable-Disabling-Cat-Chest-Detection.patch new file mode 100644 index 0000000000..88836aa6a1 --- /dev/null +++ b/patches/server-remapped/0044-Configurable-Disabling-Cat-Chest-Detection.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 01:13:45 -0600 +Subject: [PATCH] Configurable Disabling Cat Chest Detection + +Offers a gameplay feature to stop cats from blocking chests + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5a4c3a8c511f22c8c3240c9c7cd83a65119c1054..70e074cdf2087e638af8e0f3878d0ef8eb7305cc 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -186,4 +186,9 @@ public class PaperWorldConfig { + private void containerUpdateTickRate() { + containerUpdateTickRate = getInt("container-update-tick-rate", 1); + } ++ ++ public boolean disableChestCatDetection; ++ private void disableChestCatDetection() { ++ disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +index 1bda9a158eb4372b9ab7cf3097732e64810aefc6..6b95cd2e2af66eef324dfcc8f7642da2f9e39d4e 100644 +--- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +@@ -312,6 +312,11 @@ public class ChestBlock extends AbstractChestBlock implements + } + + private static boolean isCatSittingOnChest(LevelAccessor world, BlockPos pos) { ++ // Paper start - Option to disable chest cat detection ++ if (((Level) world).paperConfig.disableChestCatDetection) { ++ return false; ++ } ++ // Paper end + List list = world.getEntitiesOfClass(Cat.class, new AABB((double) pos.getX(), (double) (pos.getY() + 1), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 2), (double) (pos.getZ() + 1))); + + if (!list.isEmpty()) { diff --git a/patches/server-remapped/0045-Ensure-commands-are-not-ran-async.patch b/patches/server-remapped/0045-Ensure-commands-are-not-ran-async.patch new file mode 100644 index 0000000000..b0605d0e7a --- /dev/null +++ b/patches/server-remapped/0045-Ensure-commands-are-not-ran-async.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 01:17:12 -0600 +Subject: [PATCH] Ensure commands are not ran async + +Plugins calling Player.chat("/foo") or Server.dispatchCommand() could +trigger the server to execute a command while on another thread. + +These commands would then process EXPECTING to be on the main thread, leaving to +very hard to trace concurrency issues. + +This change will synchronize the command execution back to the main thread, causing a +big slowdown in execution but throwing an exception at same time to raise awareness +that it is happening so that plugin authors can fix their code to stop executing commands async. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 016e91a6ca1c8457e3e367ac0597b73e81919b68..00689dc07625a02781052c5df2e466e8abe85708 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1852,6 +1852,29 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + + if (!async && s.startsWith("/")) { ++ // Paper Start ++ if (!org.spigotmc.AsyncCatcher.shuttingDown && !org.bukkit.Bukkit.isPrimaryThread()) { ++ final String fCommandLine = s; ++ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Command Dispatched Async: " + fCommandLine); ++ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); ++ Waitable wait = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ chat(fCommandLine, false); ++ return null; ++ } ++ }; ++ server.processQueue.add(wait); ++ try { ++ wait.get(); ++ return; ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! ++ } catch (Exception e) { ++ throw new RuntimeException("Exception processing chat command", e.getCause()); ++ } ++ } ++ // Paper End + this.handleCommand(s); + } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { + // Do nothing, this is coming from a plugin +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 6fa31ca31128b1094eebd5f848c5b506dfeedeeb..783da25e189c0264ebf31e244677a6b653ff7b26 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -759,6 +759,29 @@ public final class CraftServer implements Server { + Validate.notNull(commandLine, "CommandLine cannot be null"); + org.spigotmc.AsyncCatcher.catchOp("command dispatch"); // Spigot + ++ // Paper Start ++ if (!org.spigotmc.AsyncCatcher.shuttingDown && !Bukkit.isPrimaryThread()) { ++ final CommandSender fSender = sender; ++ final String fCommandLine = commandLine; ++ Bukkit.getLogger().log(Level.SEVERE, "Command Dispatched Async: " + commandLine); ++ Bukkit.getLogger().log(Level.SEVERE, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); ++ org.bukkit.craftbukkit.util.Waitable wait = new org.bukkit.craftbukkit.util.Waitable() { ++ @Override ++ protected Boolean evaluate() { ++ return dispatchCommand(fSender, fCommandLine); ++ } ++ }; ++ net.minecraft.server.MinecraftServer.getServer().processQueue.add(wait); ++ try { ++ return wait.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! ++ } catch (Exception e) { ++ throw new RuntimeException("Exception processing dispatch command", e.getCause()); ++ } ++ } ++ // Paper End ++ + if (commandMap.dispatch(sender, commandLine)) { + return true; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +index ddef523ea8762c927f37f7d16d581e43367e8c6b..70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +@@ -13,6 +13,7 @@ public class ServerShutdownThread extends Thread { + public void run() { + try { + org.spigotmc.AsyncCatcher.enabled = false; // Spigot ++ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper + server.close(); + } finally { + try { +diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java +index aeed7697254af17ffefe8e578353ad216e15f9f3..9f7d2ef932ab41cef5d3d0736d20a7c7e4a2c888 100644 +--- a/src/main/java/org/spigotmc/AsyncCatcher.java ++++ b/src/main/java/org/spigotmc/AsyncCatcher.java +@@ -6,6 +6,7 @@ public class AsyncCatcher + { + + public static boolean enabled = true; ++ public static boolean shuttingDown = false; // Paper + + public static void catchOp(String reason) + { +diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java +index a4223094802a7e996cc57c617df92d23bc48f5b5..04ae5fec376af006ec828d1ae568338af5cfe6ce 100644 +--- a/src/main/java/org/spigotmc/RestartCommand.java ++++ b/src/main/java/org/spigotmc/RestartCommand.java +@@ -43,6 +43,7 @@ public class RestartCommand extends Command + private static void restart(final String restartScript) + { + AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us ++ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper + try + { + String[] split = restartScript.split( " " ); diff --git a/patches/server-remapped/0046-All-chunks-are-slime-spawn-chunks-toggle.patch b/patches/server-remapped/0046-All-chunks-are-slime-spawn-chunks-toggle.patch new file mode 100644 index 0000000000..cee1933ce4 --- /dev/null +++ b/patches/server-remapped/0046-All-chunks-are-slime-spawn-chunks-toggle.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: vemacs +Date: Thu, 3 Mar 2016 01:19:22 -0600 +Subject: [PATCH] All chunks are slime spawn chunks toggle + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 70e074cdf2087e638af8e0f3878d0ef8eb7305cc..416a6760883cb40367535c7c5acd779742bb8af5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -191,4 +191,9 @@ public class PaperWorldConfig { + private void disableChestCatDetection() { + disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); + } ++ ++ public boolean allChunksAreSlimeChunks; ++ private void allChunksAreSlimeChunks() { ++ allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java +index 8ff8c19f0b258623b9f0a3cfd0ad5595a92f5899..fc8f26e988f1e4826dcfdcf071293bb356163e62 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java +@@ -323,7 +323,7 @@ public class Slime extends Mob implements Enemy { + } + + ChunkPos chunkcoordintpair = new ChunkPos(pos); +- boolean flag = WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getLevel().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot ++ boolean flag = world.getLevel().paperConfig.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getLevel().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper + + if (random.nextInt(10) == 0 && flag && pos.getY() < 40) { + return checkMobSpawnRules(type, world, spawnReason, pos, random); diff --git a/patches/server-remapped/0047-Expose-server-CommandMap.patch b/patches/server-remapped/0047-Expose-server-CommandMap.patch new file mode 100644 index 0000000000..c633af2298 --- /dev/null +++ b/patches/server-remapped/0047-Expose-server-CommandMap.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Thu, 3 Mar 2016 02:15:57 -0600 +Subject: [PATCH] Expose server CommandMap + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 783da25e189c0264ebf31e244677a6b653ff7b26..95d32f37db663a37f8fde927bdf9d3d4802ba1b4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1760,6 +1760,7 @@ public final class CraftServer implements Server { + return helpMap; + } + ++ @Override // Paper - add override + public SimpleCommandMap getCommandMap() { + return commandMap; + } diff --git a/patches/server-remapped/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch b/patches/server-remapped/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch new file mode 100644 index 0000000000..b47fa12664 --- /dev/null +++ b/patches/server-remapped/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Thu, 3 Mar 2016 02:18:39 -0600 +Subject: [PATCH] Be a bit more informative in maxHealth exception + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index d8bfb0953f0b23c64f4e27fc84a6c5f3eb0cc8b8..3afdcb3013263a7e06876821d7d889fa48404041 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -99,7 +99,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setHealth(double health) { + health = (float) health; + if ((health < 0) || (health > getMaxHealth())) { +- throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + "(" + health + ")"); ++ // Paper - Be more informative ++ throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + ", but was " + health ++ + ". (attribute base value: " + this.getHandle().getAttribute(Attributes.MAX_HEALTH).getBaseValue() ++ + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); + } + + getHandle().setHealth((float) health); diff --git a/patches/server-remapped/0049-Player-Tab-List-and-Title-APIs.patch b/patches/server-remapped/0049-Player-Tab-List-and-Title-APIs.patch new file mode 100644 index 0000000000..c26e87ac6e --- /dev/null +++ b/patches/server-remapped/0049-Player-Tab-List-and-Title-APIs.patch @@ -0,0 +1,173 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Thu, 3 Mar 2016 02:32:10 -0600 +Subject: [PATCH] Player Tab List and Title APIs + + +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index 59788eaef0dae5ee01ceba1bf45e85cb07f88e53..b4542ce6a8c37ab31e6ecaeb4cbad4742cca0f9b 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -170,6 +170,11 @@ public class FriendlyByteBuf extends ByteBuf { + public FriendlyByteBuf writeComponent(final net.kyori.adventure.text.Component component) { + return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); + } ++ ++ @Deprecated ++ public FriendlyByteBuf writeComponent(final net.md_5.bungee.api.chat.BaseComponent[] component) { ++ return this.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(component), 262144); ++ } + // Paper end + + public FriendlyByteBuf writeComponent(Component text) { +diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java +index 54d186a195aca6d0a4c412ed609d8c86dcc76072..06e9246f05e130be6a63ebb0c9def10c6c9675b7 100644 +--- a/src/main/java/net/minecraft/network/chat/Component.java ++++ b/src/main/java/net/minecraft/network/chat/Component.java +@@ -363,6 +363,7 @@ public interface Component extends Message, FormattedText, Iterable { + return Component.Serializer.GSON.toJsonTree(text); + } + ++ @Nullable public static Component jsonToComponent(String json) { return fromJson(json);} // Paper - OBFHELPER + @Nullable + public static MutableComponent fromJson(String json) { + return (MutableComponent) GsonHelper.fromJson(Component.Serializer.GSON, json, MutableComponent.class, false); +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java +index 69ff8df7340e60c476803256750a48f0b43414d3..df444daeb181ff78170f7b92bd02f1f1862dfa2e 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java +@@ -47,6 +47,17 @@ public class ClientboundSetTitlesPacket implements Packet +Date: Thu, 3 Mar 2016 02:33:53 -0600 +Subject: [PATCH] Ensure inv drag is in bounds + + +diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index c377a425dc3274b8aa25f94ce8f76efda2652def..72b0cfcc5aab03e14e63440c734436e9c1432111 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -238,7 +238,7 @@ public abstract class AbstractContainerMenu { + this.resetQuickCraft(); + } + } else if (this.quickcraftStatus == 1) { +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = i < this.slots.size() ? this.slots.get(i) : null; // Paper - Ensure drag in bounds + + itemstack1 = playerinventory.getCarried(); + if (slot != null && canItemQuickReplace(slot, itemstack1, true) && slot.isAllowed(itemstack1) && (this.quickcraftType == 2 || itemstack1.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) { diff --git a/patches/server-remapped/0051-Change-implementation-of-tile-entity-removal-list.patch b/patches/server-remapped/0051-Change-implementation-of-tile-entity-removal-list.patch new file mode 100644 index 0000000000..6e0641f0dd --- /dev/null +++ b/patches/server-remapped/0051-Change-implementation-of-tile-entity-removal-list.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joseph Hirschfeld +Date: Thu, 3 Mar 2016 02:39:54 -0600 +Subject: [PATCH] Change implementation of (tile)entity removal list + +use sets for faster removal + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 6c6098731752d61b5241710b075d4ffe3826daac..89472b6e8f38921db50440d0213e40ac893892f1 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1122,7 +1122,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + } + // Spigot End +- this.blockEntitiesToUnload.addAll(chunk.getBlockEntities().values()); ++ this.tileEntityListUnload.addAll(chunk.getBlockEntities().values()); + List[] aentityslice = chunk.getEntitySlices(); // Spigot + int i = aentityslice.length; + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index e25666328dbf433b8358f2637d93b4128034bbaa..7b4475807cca0e92ea9ae6ea49a82a8634cc0ff5 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -89,7 +89,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public final List blockEntityList = Lists.newArrayList(); + public final List tickableBlockEntities = Lists.newArrayList(); + protected final List pendingBlockEntities = Lists.newArrayList(); +- protected final List blockEntitiesToUnload = Lists.newArrayList(); ++ protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); + public final Thread thread; + private final boolean isDebug; + private int skyDarken; +@@ -697,10 +697,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + gameprofilerfiller.push("blockEntities"); + timings.tileEntityTick.startTiming(); // Spigot +- if (!this.blockEntitiesToUnload.isEmpty()) { +- this.tickableBlockEntities.removeAll(this.blockEntitiesToUnload); +- this.blockEntityList.removeAll(this.blockEntitiesToUnload); +- this.blockEntitiesToUnload.clear(); ++ if (!this.tileEntityListUnload.isEmpty()) { ++ this.tickableBlockEntities.removeAll(this.tileEntityListUnload); ++ this.blockEntityList.removeAll(this.tileEntityListUnload); ++ this.tileEntityListUnload.clear(); + } + + this.updatingBlockEntities = true; diff --git a/patches/server-remapped/0052-Add-configurable-portal-search-radius.patch b/patches/server-remapped/0052-Add-configurable-portal-search-radius.patch new file mode 100644 index 0000000000..8bbb23e407 --- /dev/null +++ b/patches/server-remapped/0052-Add-configurable-portal-search-radius.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joseph Hirschfeld +Date: Thu, 3 Mar 2016 02:46:17 -0600 +Subject: [PATCH] Add configurable portal search radius + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 416a6760883cb40367535c7c5acd779742bb8af5..670efbe53241a0ae32d618c83da601ccc1f26e37 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -196,4 +196,13 @@ public class PaperWorldConfig { + private void allChunksAreSlimeChunks() { + allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); + } ++ ++ public int portalSearchRadius; ++ public int portalCreateRadius; ++ public boolean portalSearchVanillaDimensionScaling; ++ private void portalSearchRadius() { ++ portalSearchRadius = getInt("portal-search-radius", 128); ++ portalCreateRadius = getInt("portal-create-radius", 16); ++ portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 72eb40f748c33572c2828f48ebd1ca7d5d5712c8..a6f2e671cc9b2ef086dfa3d127a7b33272acbd56 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2617,7 +2617,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + double d4 = DimensionType.getTeleportationScale(this.level.dimensionType(), destination.dimensionType()); + BlockPos blockposition = new BlockPos(Mth.clamp(this.getX() * d4, d0, d2), this.getY(), Mth.clamp(this.getZ() * d4, d1, d3)); + // CraftBukkit start +- CraftPortalEvent event = callPortalEvent(this, destination, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); ++ // Paper start ++ int portalSearchRadius = destination.paperConfig.portalSearchRadius; ++ if (level.paperConfig.portalSearchVanillaDimensionScaling && flag2) { // == THE_NETHER ++ portalSearchRadius = (int) (portalSearchRadius / destination.dimensionType().coordinateScale()); ++ } ++ // Paper end ++ CraftPortalEvent event = callPortalEvent(this, destination, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, portalSearchRadius, destination.paperConfig.portalCreateRadius); // Paper start - configurable portal radius + if (event == null) { + return null; + } +diff --git a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java +index 948d031627435bfce442b1fe7d3eff4addc85bc4..21c01302635d23bc21e6bb373cbe277ea1eb6a56 100644 +--- a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java ++++ b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java +@@ -30,7 +30,7 @@ public class PortalForcer { + + public Optional findPortalAround(BlockPos blockposition, boolean flag) { + // CraftBukkit start +- return findPortalAround(blockposition, flag ? 16 : 128); // Search Radius ++ return findPortalAround(blockposition, flag ? level.paperConfig.portalCreateRadius : level.paperConfig.portalSearchRadius); // Paper - search Radius + } + + public Optional findPortal(BlockPos blockposition, int i) { diff --git a/patches/server-remapped/0053-Add-velocity-warnings.patch b/patches/server-remapped/0053-Add-velocity-warnings.patch new file mode 100644 index 0000000000..3a11078735 --- /dev/null +++ b/patches/server-remapped/0053-Add-velocity-warnings.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joseph Hirschfeld +Date: Thu, 3 Mar 2016 02:48:12 -0600 +Subject: [PATCH] Add velocity warnings + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 95d32f37db663a37f8fde927bdf9d3d4802ba1b4..35d3df7ded4904414a9a61895950b56be530d244 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -260,6 +260,7 @@ public final class CraftServer implements Server { + public boolean ignoreVanillaPermissions = false; + private final List playerView; + public int reloadCount; ++ public static Exception excessiveVelEx; // Paper - Velocity warnings + + static { + ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index e7a59a8e0424a0839dfa73fc65f44c5b04bd3dec..b028946de7c8f52091635fe154c816453f1ddc93 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -424,10 +424,41 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public void setVelocity(Vector velocity) { + Preconditions.checkArgument(velocity != null, "velocity"); + velocity.checkFinite(); ++ // Paper start - Warn server owners when plugins try to set super high velocities ++ if (!(this instanceof org.bukkit.entity.Projectile) && isUnsafeVelocity(velocity)) { ++ CraftServer.excessiveVelEx = new Exception("Excessive velocity set detected: tried to set velocity of entity " + entity.getScoreboardName() + " id #" + getEntityId() + " to (" + velocity.getX() + "," + velocity.getY() + "," + velocity.getZ() + ")."); ++ } ++ // Paper end ++ + entity.setDeltaMovement(CraftVector.toNMS(velocity)); + entity.hurtMarked = true; + } + ++ // Paper start ++ /** ++ * Checks if the given velocity is not necessarily safe in all situations. ++ * This function returning true does not mean the velocity is dangerous or to be avoided, only that it may be ++ * a detriment to performance on the server. ++ * ++ * It is not to be used as a hard rule of any sort. ++ * Paper only uses it to warn server owners in watchdog crashes. ++ * ++ * @param vel incoming velocity to check ++ * @return if the velocity has the potential to be a performance detriment ++ */ ++ private static boolean isUnsafeVelocity(Vector vel) { ++ final double x = vel.getX(); ++ final double y = vel.getY(); ++ final double z = vel.getZ(); ++ ++ if (x > 4 || x < -4 || y > 4 || y < -4 || z > 4 || z < -4) { ++ return true; ++ } ++ ++ return false; ++ } ++ // Paper end ++ + @Override + public double getHeight() { + return getHandle().getBbHeight(); +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 21d7b483920841456707fe3f08b180c1f072b7f7..0ed95268364ea7f6a92a39b726a1e03bc815be07 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -80,7 +80,19 @@ public class WatchdogThread extends Thread + log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" ); + log.log( Level.SEVERE, "near " + net.minecraft.world.level.Level.lastPhysicsProblem ); + } +- // ++ // Paper start - Warn in watchdog if an excessive velocity was ever set ++ if ( org.bukkit.craftbukkit.CraftServer.excessiveVelEx != null ) ++ { ++ log.log( Level.SEVERE, "------------------------------" ); ++ log.log( Level.SEVERE, "During the run of the server, a plugin set an excessive velocity on an entity" ); ++ log.log( Level.SEVERE, "This may be the cause of the issue, or it may be entirely unrelated" ); ++ log.log( Level.SEVERE, org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getMessage()); ++ for ( StackTraceElement stack : org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getStackTrace() ) ++ { ++ log.log( Level.SEVERE, "\t\t" + stack ); ++ } ++ } ++ // Paper end + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); diff --git a/patches/server-remapped/0054-Configurable-inter-world-teleportation-safety.patch b/patches/server-remapped/0054-Configurable-inter-world-teleportation-safety.patch new file mode 100644 index 0000000000..c0826d9b39 --- /dev/null +++ b/patches/server-remapped/0054-Configurable-inter-world-teleportation-safety.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Thu, 3 Mar 2016 02:50:31 -0600 +Subject: [PATCH] Configurable inter-world teleportation safety + +People are able to abuse the way Bukkit handles teleportation across worlds since it provides a built in teleportation +safety check. + +To abuse the safety check, players are required to get into a location deemed unsafe by Bukkit e.g. be within a chest +or door block. While they are in this block, they accept a teleport request from a player within a different world. Once +the player teleports, Minecraft will recursively search upwards for a safe location, this could eventually land within a +player's skybase. + +Example setup to perform the glitch: http://puu.sh/ng3PC/cf072dcbdb.png +The wanted destination was on top of the emerald block however the player ended on top of the diamond block. +This only is the case if the player is teleporting between worlds. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 670efbe53241a0ae32d618c83da601ccc1f26e37..abbbe1786eb68af02f9d39650aad730ac44aac8a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -205,4 +205,9 @@ public class PaperWorldConfig { + portalCreateRadius = getInt("portal-create-radius", 16); + portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); + } ++ ++ public boolean disableTeleportationSuffocationCheck; ++ private void disableTeleportationSuffocationCheck() { ++ disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 63933bd455ad72a772d4db160e946600b84a1791..3b9d61b524441f65646edf7d403b6c5b5345b1e5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -861,7 +861,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + if (fromWorld == toWorld) { + entity.connection.teleport(to); + } else { +- server.getHandle().moveToWorld(entity, toWorld, true, to, true); ++ server.getHandle().moveToWorld(entity, toWorld, true, to, !toWorld.paperConfig.disableTeleportationSuffocationCheck); // Paper + } + return true; + } diff --git a/patches/server-remapped/0055-Add-exception-reporting-event.patch b/patches/server-remapped/0055-Add-exception-reporting-event.patch new file mode 100644 index 0000000000..7b87e0d39f --- /dev/null +++ b/patches/server-remapped/0055-Add-exception-reporting-event.patch @@ -0,0 +1,264 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joseph Hirschfeld +Date: Thu, 3 Mar 2016 03:15:41 -0600 +Subject: [PATCH] Add exception reporting event + + +diff --git a/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f699ce18ca044f813e194ef2786b7ea853ea86e7 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java +@@ -0,0 +1,38 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Preconditions; ++import org.bukkit.craftbukkit.scheduler.CraftTask; ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerSchedulerException; ++ ++/** ++ * Reporting wrapper to catch exceptions not natively ++ */ ++public class ServerSchedulerReportingWrapper implements Runnable { ++ ++ private final CraftTask internalTask; ++ ++ public ServerSchedulerReportingWrapper(CraftTask internalTask) { ++ this.internalTask = Preconditions.checkNotNull(internalTask, "internalTask"); ++ } ++ ++ @Override ++ public void run() { ++ try { ++ internalTask.run(); ++ } catch (RuntimeException e) { ++ internalTask.getOwner().getServer().getPluginManager().callEvent( ++ new ServerExceptionEvent(new ServerSchedulerException(e, internalTask)) ++ ); ++ throw e; ++ } catch (Throwable t) { ++ internalTask.getOwner().getServer().getPluginManager().callEvent( ++ new ServerExceptionEvent(new ServerSchedulerException(t, internalTask)) ++ ); //Do not rethrow, since it is not permitted with Runnable#run ++ } ++ } ++ ++ public CraftTask getInternalTask() { ++ return internalTask; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index d1bc927c8b429f43de2cdad98f8b329ff4c8b4db..0597c0c3e881dd43cf91bd3088ed30dfecfe8098 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -813,6 +813,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return true; + } catch (Exception exception) { + ChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception); ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper + return false; + } + } +diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java +index c167d2fd99a7a352e69e2930551678bd9c9def83..09c5fa2dbcbed05da51ef2d63e6d6112d22d7877 100644 +--- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java ++++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java +@@ -1,5 +1,6 @@ + package net.minecraft.server.players; + ++import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.io.Files; +@@ -360,6 +361,7 @@ public class OldUsersConverter { + root = NbtIo.readCompressed(new java.io.FileInputStream(file5)); + } catch (Exception exception) { + exception.printStackTrace(); ++ ServerInternalException.reportInternalException(exception); // Paper + } + + if (root != null) { +@@ -373,6 +375,7 @@ public class OldUsersConverter { + NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2)); + } catch (Exception exception) { + exception.printStackTrace(); ++ ServerInternalException.reportInternalException(exception); // Paper + } + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java +index 78cea15142f9fd7988f5df397061b90625070eef..f50774f022c78813982bfe08f764b54bde779e04 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.entity.ai.village; + ++import com.destroystokyo.paper.exception.ServerInternalException; ++ + import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -119,6 +121,7 @@ public class VillageSiege implements CustomSpawner { + entityzombie.finalizeSpawn(world, world.getCurrentDifficultyAt(entityzombie.blockPosition()), MobSpawnType.EVENT, (SpawnGroupData) null, (CompoundTag) null); + } catch (Exception exception) { + VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception); ++ ServerInternalException.reportInternalException(exception); // Paper + return; + } + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 7b4475807cca0e92ea9ae6ea49a82a8634cc0ff5..94e268a05b4601c29b6d2845f0fc2311643a161f 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -1,5 +1,10 @@ + package net.minecraft.world.level; + ++import co.aikar.timings.Timing; ++import co.aikar.timings.Timings; ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerInternalException; ++import com.google.common.base.MoreObjects; + import com.google.common.collect.Lists; + import com.mojang.serialization.Codec; + import java.io.IOException; +@@ -737,8 +742,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + gameprofilerfiller.pop(); + } catch (Throwable throwable) { + // Paper start - Prevent tile entity and entity crashes +- System.err.println("TileEntity threw exception at " + tileentity.level.getWorld().getName() + ":" + tileentity.worldPosition.getX() + "," + tileentity.worldPosition.getY() + "," + tileentity.worldPosition.getZ()); ++ String msg = "TileEntity threw exception at " + tileentity.getLevel().getWorld().getName() + ":" + tileentity.getBlockPos().getX() + "," + tileentity.getBlockPos().getY() + "," + tileentity.getBlockPos().getZ(); ++ System.err.println(msg); + throwable.printStackTrace(); ++ getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); ++ // Paper end + tilesThisCycle--; + this.tickableBlockEntities.remove(tileTickPosition--); + continue; +@@ -808,8 +816,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + tickConsumer.accept(entity); + } catch (Throwable throwable) { + // Paper start - Prevent tile entity and entity crashes +- System.err.println("Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ()); ++ String msg = "Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ(); ++ System.err.println(msg); + throwable.printStackTrace(); ++ getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); + entity.removed = true; + return; + // Paper end +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index fc134b916e95231af8478a4f97bf11a0f37f7f0b..a19ac1cb7e4d8d478648a048b2bfa0daf85a80c9 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -299,6 +299,7 @@ public final class NaturalSpawner { + } + } catch (Exception exception) { + NaturalSpawner.LOGGER.warn("Failed to create mob", exception); ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper + return null; + } + } +@@ -405,6 +406,7 @@ public final class NaturalSpawner { + entity = biomesettingsmobs_c.type.create((Level) worldaccess.getLevel()); + } catch (Exception exception) { + NaturalSpawner.LOGGER.warn("Failed to create mob", exception); ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper + continue; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 300749822d52f9f973e71c6ec9c8bf29d6a6938e..9ca05aa06696883adc8b67a68ca6d2d850e95d25 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.chunk; + ++import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; + import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +@@ -654,10 +655,15 @@ public class LevelChunk implements ChunkAccess { + this.blockEntities.remove(pos); + // Paper end + } else { +- System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() +- + " (" + getBlockState(pos) + ") where there was no entity tile!"); +- System.out.println("Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); +- new Exception().printStackTrace(); ++ // Paper start ++ ServerInternalException e = new ServerInternalException( ++ "Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," ++ + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() ++ + " (" + getBlockState(pos) + ") where there was no entity tile!\n" + ++ "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); ++ e.printStackTrace(); ++ ServerInternalException.reportInternalException(e); ++ // Paper end + // CraftBukkit end + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 60f410a4f838048bbfd2cde52caa7c4c9434b0ba..1598da3449ee1c559cf503e1b20a0daaf6a033dd 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -265,6 +265,7 @@ public class RegionFile implements AutoCloseable { + return true; + } + } catch (IOException ioexception) { ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper + return false; + } + } +@@ -337,6 +338,7 @@ public class RegionFile implements AutoCloseable { + filechannel.write(bytebuffer); + } catch (Throwable throwable1) { + throwable = throwable1; ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper + throw throwable1; + } finally { + if (filechannel != null) { +diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +index 60b7fdf9c092e8105d41f4af02a08651624f3eb9..99cfd693ea705d45a5eab181cb80c354a2d1159f 100644 +--- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +@@ -150,6 +150,7 @@ public class DimensionDataStorage { + } + } catch (Throwable throwable6) { + throwable = throwable6; ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper + throw throwable6; + } finally { + if (fileinputstream != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index ffe9cc1011226d604dc5499e7692e9a9a5132b72..9b6d9373abb59a30c2835ca891282d07559281f5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -16,6 +16,9 @@ import java.util.concurrent.atomic.AtomicInteger; + import java.util.concurrent.atomic.AtomicReference; + import java.util.function.Consumer; + import java.util.logging.Level; ++import com.destroystokyo.paper.ServerSchedulerReportingWrapper; ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerSchedulerException; + import org.apache.commons.lang.Validate; + import org.bukkit.plugin.IllegalPluginAccessException; + import org.bukkit.plugin.Plugin; +@@ -419,6 +422,8 @@ public class CraftScheduler implements BukkitScheduler { + msg, + throwable); + } ++ org.bukkit.Bukkit.getServer().getPluginManager().callEvent( ++ new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task))); + // Paper end + } finally { + currentTask = null; +@@ -426,7 +431,7 @@ public class CraftScheduler implements BukkitScheduler { + parsePending(); + } else { + debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); +- executor.execute(task); ++ executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper + // We don't need to parse pending + // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) + } diff --git a/patches/server-remapped/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/patches/server-remapped/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch new file mode 100644 index 0000000000..f1642d7a3b --- /dev/null +++ b/patches/server-remapped/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Tue, 8 Mar 2016 18:28:43 -0800 +Subject: [PATCH] Don't nest if we don't need to when cerealising text + components + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +index e47102cadb40ed8a9c011386445f15fd30de7596..f13da9e7d014bc00fbabf0a495b548bba2f59468 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +@@ -40,7 +40,14 @@ public class ClientboundChatPacket implements Packet { + // Paper end + // Spigot start + if (components != null) { +- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(components)); ++ //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below ++ // Paper start - don't nest if we don't need to so that we can preserve formatting ++ if (this.components.length == 1) { ++ buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); ++ } else { ++ buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); ++ } ++ // Paper end + } else { + buf.writeComponent(this.message); + } diff --git a/patches/server-remapped/0057-Disable-Scoreboards-for-non-players-by-default.patch b/patches/server-remapped/0057-Disable-Scoreboards-for-non-players-by-default.patch new file mode 100644 index 0000000000..d1cae6e603 --- /dev/null +++ b/patches/server-remapped/0057-Disable-Scoreboards-for-non-players-by-default.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 8 Mar 2016 23:25:45 -0500 +Subject: [PATCH] Disable Scoreboards for non players by default + +Entities collision is checking for scoreboards setting. +This is very heavy to do map lookups for every collision to check +this setting. + +So avoid looking up scoreboards and short circuit to the "not on a team" +logic which is most likely to be true. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index abbbe1786eb68af02f9d39650aad730ac44aac8a..3ac2ac3db9b1c271b3c21930bb13716669ff64d3 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -210,4 +210,9 @@ public class PaperWorldConfig { + private void disableTeleportationSuffocationCheck() { + disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); + } ++ ++ public boolean nonPlayerEntitiesOnScoreboards = false; ++ private void nonPlayerEntitiesOnScoreboards() { ++ nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a6f2e671cc9b2ef086dfa3d127a7b33272acbd56..93d3408231a177cf6d2086594756adffe3efa702 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2288,6 +2288,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + @Nullable + public Team getTeam() { ++ if (!this.level.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof Player)) { return null; } // Paper + return this.level.getScoreboard().getPlayerTeam(this.getScoreboardName()); + } + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index afd114e1ce00db72534d470fed12101bb237f266..d483d552092c901fec262c43e488784d9cd8acb9 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -738,6 +738,7 @@ public abstract class LivingEntity extends Entity { + if (tag.contains("Team", 8)) { + String s = tag.getString("Team"); + PlayerTeam scoreboardteam = this.level.getScoreboard().getTeam(s); ++ if (!level.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof net.minecraft.world.entity.player.Player)) { scoreboardteam = null; } // Paper + boolean flag = scoreboardteam != null && this.level.getScoreboard().addPlayerToTeam(this.getStringUUID(), scoreboardteam); + + if (!flag) { diff --git a/patches/server-remapped/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/server-remapped/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch new file mode 100644 index 0000000000..e0d5759239 --- /dev/null +++ b/patches/server-remapped/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: mrapple +Date: Sun, 25 Nov 2012 13:43:39 -0600 +Subject: [PATCH] Add methods for working with arrows stuck in living entities + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 3afdcb3013263a7e06876821d7d889fa48404041..d8cd88d62f9abfc7960c187dd74239f61267ca57 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -677,4 +677,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + getHandle().persistentInvisibility = invisible; + getHandle().setSharedFlag(5, invisible); + } ++ ++ // Paper start ++ @Override ++ public int getArrowsStuck() { ++ return getHandle().getArrowCount(); ++ } ++ ++ @Override ++ public void setArrowsStuck(int arrows) { ++ getHandle().setArrowCount(arrows); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0059-Complete-resource-pack-API.patch b/patches/server-remapped/0059-Complete-resource-pack-API.patch new file mode 100644 index 0000000000..6be95196f1 --- /dev/null +++ b/patches/server-remapped/0059-Complete-resource-pack-API.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 4 Apr 2015 23:17:52 -0400 +Subject: [PATCH] Complete resource pack API + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 00689dc07625a02781052c5df2e466e8abe85708..73683ba59d0aff3a61f555b4ae15753e9e4e6141 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1603,7 +1603,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit start + public void handleResourcePackResponse(ServerboundResourcePackPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); +- this.craftServer.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()])); ++ // Paper start ++ PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()]; ++ player.getBukkitEntity().setResourcePackStatus(packStatus); ++ this.craftServer.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), packStatus)); ++ // Paper end + } + // CraftBukkit end + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 3b9d61b524441f65646edf7d403b6c5b5345b1e5..dd29038778d73fae84df360515f3c670915f1d48 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -136,6 +136,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + private double health = 20; + private boolean scaledHealth = false; + private double healthScale = 20; ++ // Paper start ++ private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; ++ private String resourcePackHash; ++ // Paper end + + public CraftPlayer(CraftServer server, ServerPlayer entity) { + super(server, entity); +@@ -1872,6 +1876,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public boolean getAffectsSpawning() { + return this.getHandle().affectsSpawning; + } ++ ++ @Override ++ public void setResourcePack(String url, String hash) { ++ Validate.notNull(url, "Resource pack URL cannot be null"); ++ Validate.notNull(hash, "Hash cannot be null"); ++ this.getHandle().sendTexturePack(url, hash); ++ } ++ ++ @Override ++ public org.bukkit.event.player.PlayerResourcePackStatusEvent.Status getResourcePackStatus() { ++ return this.resourcePackStatus; ++ } ++ ++ @Override ++ public String getResourcePackHash() { ++ return this.resourcePackHash; ++ } ++ ++ @Override ++ public boolean hasResourcePack() { ++ return this.resourcePackStatus == org.bukkit.event.player.PlayerResourcePackStatusEvent.Status.SUCCESSFULLY_LOADED; ++ } ++ ++ public void setResourcePackStatus(org.bukkit.event.player.PlayerResourcePackStatusEvent.Status status) { ++ this.resourcePackStatus = status; ++ } + // Paper end + + @Override diff --git a/patches/server-remapped/0060-Chunk-Save-Reattempt.patch b/patches/server-remapped/0060-Chunk-Save-Reattempt.patch new file mode 100644 index 0000000000..db35b14461 --- /dev/null +++ b/patches/server-remapped/0060-Chunk-Save-Reattempt.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 4 Mar 2013 23:46:10 -0500 +Subject: [PATCH] Chunk Save Reattempt + +We commonly have "Stream Closed" errors on chunk saving, so this code should re-try to save the chunk in the event of failure and hopefully prevent rollbacks. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 1598da3449ee1c559cf503e1b20a0daaf6a033dd..1aa4d342b97f8be71c108194a6f1e0e2828aa364 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -265,7 +265,7 @@ public class RegionFile implements AutoCloseable { + return true; + } + } catch (IOException ioexception) { +- com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioexception); // Paper - we want the upper try/catch to retry this + return false; + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index 1e49d17b54704e1b99c3ded458c4bc6842bd32bd..97a58da9d64d812942ceb71426d35b490bbbe817 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -11,6 +11,7 @@ import java.io.IOException; + import javax.annotation.Nullable; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtIo; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.util.ExceptionCollector; + import net.minecraft.world.level.ChunkPos; + +@@ -92,6 +93,7 @@ public final class RegionFileStorage implements AutoCloseable { + + protected void write(ChunkPos pos, CompoundTag tag) throws IOException { + RegionFile regionfile = this.getFile(pos, false); // CraftBukkit ++ int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper + DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(pos); + Throwable throwable = null; + +@@ -115,6 +117,18 @@ public final class RegionFileStorage implements AutoCloseable { + + } + ++ // Paper start ++ return; ++ } catch (Exception ex) { ++ laste = ex; ++ } ++ } ++ ++ if (laste != null) { ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(laste); ++ MinecraftServer.LOGGER.error("Failed to save chunk", laste); ++ } ++ // Paper end + } + + public void close() throws IOException { diff --git a/patches/server-remapped/0061-Default-loading-permissions.yml-before-plugins.patch b/patches/server-remapped/0061-Default-loading-permissions.yml-before-plugins.patch new file mode 100644 index 0000000000..3df2a1e2a2 --- /dev/null +++ b/patches/server-remapped/0061-Default-loading-permissions.yml-before-plugins.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 13:17:38 -0400 +Subject: [PATCH] Default loading permissions.yml before plugins + +Under previous behavior, plugins were not able to check if a player had a permission +if it was defined in permissions.yml. there is no clean way for a plugin to fix that either. + +This will change the order so that by default, permissions.yml loads BEFORE plugins instead of after. + +This gives plugins expected permission checks. + +It also helps improve the expected logic, as servers should set the initial defaults, and then let plugins +modify that. Under the previous logic, plugins were unable (cleanly) override permissions.yml. + +A config option has been added for those who depend on the previous behavior, but I don't expect that. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 429b74474ced04d8dd8f038b8590b8dfe178bf4d..716f285e67019b8a62922d09c15883c99f9421aa 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -222,4 +222,9 @@ public class PaperConfig { + private static void useDisplayNameInQuit() { + useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); + } ++ ++ public static boolean loadPermsBeforePlugins = true; ++ private static void loadPermsBeforePlugins() { ++ loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 35d3df7ded4904414a9a61895950b56be530d244..662fc88e2e118a57a6c35a8981d4622188adec3b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -397,6 +397,7 @@ public final class CraftServer implements Server { + if (type == PluginLoadOrder.STARTUP) { + helpMap.clear(); + helpMap.initializeGeneralTopics(); ++ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper + } + + Plugin[] plugins = pluginManager.getPlugins(); +@@ -416,7 +417,7 @@ public final class CraftServer implements Server { + commandMap.registerServerAliases(); + DefaultPermissions.registerCorePermissions(); + CraftDefaultPermissions.registerCorePermissions(); +- loadCustomPermissions(); ++ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper + helpMap.initializeCommands(); + syncCommands(); + } diff --git a/patches/server-remapped/0062-Allow-Reloading-of-Custom-Permissions.patch b/patches/server-remapped/0062-Allow-Reloading-of-Custom-Permissions.patch new file mode 100644 index 0000000000..e43351be69 --- /dev/null +++ b/patches/server-remapped/0062-Allow-Reloading-of-Custom-Permissions.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William +Date: Fri, 18 Mar 2016 03:30:17 -0400 +Subject: [PATCH] Allow Reloading of Custom Permissions + +https://github.com/PaperMC/Paper/issues/49 + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 662fc88e2e118a57a6c35a8981d4622188adec3b..50da8e292c131176c263f0bc140ff4f6d890c737 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2252,5 +2252,23 @@ public final class CraftServer implements Server { + } + return this.adventure$audiences; + } ++ ++ @Override ++ public void reloadPermissions() { ++ pluginManager.clearPermissions(); ++ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); ++ for (Plugin plugin : pluginManager.getPlugins()) { ++ for (Permission perm : plugin.getDescription().getPermissions()) { ++ try { ++ pluginManager.addPermission(perm); ++ } catch (IllegalArgumentException ex) { ++ getLogger().log(Level.WARNING, "Plugin " + plugin.getDescription().getFullName() + " tried to register permission '" + perm.getName() + "' but it's already registered", ex); ++ } ++ } ++ } ++ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); ++ DefaultPermissions.registerCorePermissions(); ++ CraftDefaultPermissions.registerCorePermissions(); ++ } + // Paper end + } diff --git a/patches/server-remapped/0063-Remove-Metadata-on-reload.patch b/patches/server-remapped/0063-Remove-Metadata-on-reload.patch new file mode 100644 index 0000000000..bad86d108d --- /dev/null +++ b/patches/server-remapped/0063-Remove-Metadata-on-reload.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 13:50:14 -0400 +Subject: [PATCH] Remove Metadata on reload + +Metadata is not meant to persist reload as things break badly with non primitive types +This will remove metadata on reload so it does not crash everything if a plugin uses it. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 50da8e292c131176c263f0bc140ff4f6d890c737..2828936fe294d9d6750a8838da49ec8398835214 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -870,8 +870,18 @@ public final class CraftServer implements Server { + world.paperConfig.init(); // Paper + } + ++ Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper + pluginManager.clearPlugins(); + commandMap.clearCommands(); ++ ++ // Paper start ++ for (Plugin plugin : pluginClone) { ++ entityMetadata.removeAll(plugin); ++ worldMetadata.removeAll(plugin); ++ playerMetadata.removeAll(plugin); ++ } ++ // Paper end ++ + resetRecipes(); + reloadData(); + org.spigotmc.SpigotConfig.registerCommands(); // Spigot diff --git a/patches/server-remapped/0064-Handle-Item-Meta-Inconsistencies.patch b/patches/server-remapped/0064-Handle-Item-Meta-Inconsistencies.patch new file mode 100644 index 0000000000..32698665bc --- /dev/null +++ b/patches/server-remapped/0064-Handle-Item-Meta-Inconsistencies.patch @@ -0,0 +1,339 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 28 May 2015 23:00:19 -0400 +Subject: [PATCH] Handle Item Meta Inconsistencies + +First, Enchantment order would blow away seeing 2 items as the same, +however the Client forces enchantment list in a certain order, as well +as does the /enchant command. Anvils can insert it into forced order, +causing 2 same items to be considered different. + +This change makes unhandled NBT Tags and Enchantments use a sorted tree map, +so they will always be in a consistent order. + +Additionally, the old enchantment API was never updated when ItemMeta +was added, resulting in 2 different ways to modify an items enchantments. + +For consistency, the old API methods now forward to use the +ItemMeta API equivalents, and should deprecate the old API's. + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 3faf52e7ac5e7e22d09cfb73cfda6b9f622137d4..123025c6dc9a2eea56c7db5cb508cdfd7c6cc97b 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -9,6 +9,8 @@ import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; + import java.text.DecimalFormat; + import java.text.DecimalFormatSymbols; ++import java.util.Collections; ++import java.util.Comparator; + import java.util.Locale; + import java.util.Objects; + import java.util.Optional; +@@ -118,6 +120,23 @@ public final class ItemStack { + private BlockInWorld cachedPlaceBlock; + private boolean cachedPlaceBlockResult; + ++ // Paper start ++ private static final java.util.Comparator enchantSorter = java.util.Comparator.comparing(o -> o.getString("id")); ++ private void processEnchantOrder(CompoundTag tag) { ++ if (tag == null || !tag.contains("Enchantments", 9)) { ++ return; ++ } ++ ListTag list = tag.getList("Enchantments", 10); ++ if (list.size() < 2) { ++ return; ++ } ++ try { ++ //noinspection unchecked ++ list.sort((Comparator) enchantSorter); // Paper ++ } catch (Exception ignored) {} ++ } ++ // Paper end ++ + public ItemStack(ItemLike item) { + this(item, 1); + } +@@ -160,6 +179,7 @@ public final class ItemStack { + if (nbttagcompound.contains("tag", 10)) { + // CraftBukkit start - make defensive copy as this data may be coming from the save thread + this.tag = (CompoundTag) nbttagcompound.getCompound("tag").copy(); ++ processEnchantOrder(this.tag); // Paper + this.getItem().verifyTagAfterLoad(this.tag); + // CraftBukkit end + } +@@ -678,6 +698,7 @@ public final class ItemStack { + // Paper end + public void setTag(@Nullable CompoundTag tag) { + this.tag = tag; ++ processEnchantOrder(this.tag); // Paper + if (this.getItem().canBeDepleted()) { + this.setDamageValue(this.getDamageValue()); + } +@@ -768,6 +789,7 @@ public final class ItemStack { + nbttagcompound.putString("id", String.valueOf(Registry.ENCHANTMENT.getKey(enchantment))); + nbttagcompound.putShort("lvl", (short) ((byte) level)); + nbttaglist.add(nbttagcompound); ++ processEnchantOrder(nbttagcompound); // Paper + } + + public boolean isEnchanted() { +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index 01df5263d77771a296ca091a0feec620e6e37229..5f0ccdeb8565505278caa591f7390047eab49cf4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -6,7 +6,6 @@ import java.util.Map; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.world.item.Item; +-import net.minecraft.world.item.enchantment.EnchantmentHelper; + import org.apache.commons.lang.Validate; + import org.bukkit.Material; + import org.bukkit.configuration.serialization.DelegateDeserialization; +@@ -178,28 +177,11 @@ public final class CraftItemStack extends ItemStack { + public void addUnsafeEnchantment(Enchantment ench, int level) { + Validate.notNull(ench, "Cannot add null enchantment"); + +- if (!makeTag(handle)) { +- return; +- } +- ListTag list = getEnchantmentList(handle); +- if (list == null) { +- list = new ListTag(); +- handle.getTag().put(ENCHANTMENTS.NBT, list); +- } +- int size = list.size(); +- +- for (int i = 0; i < size; i++) { +- CompoundTag tag = (CompoundTag) list.get(i); +- String id = tag.getString(ENCHANTMENTS_ID.NBT); +- if (id.equals(ench.getKey().toString())) { +- tag.putShort(ENCHANTMENTS_LVL.NBT, (short) level); +- return; +- } +- } +- CompoundTag tag = new CompoundTag(); +- tag.putString(ENCHANTMENTS_ID.NBT, ench.getKey().toString()); +- tag.putShort(ENCHANTMENTS_LVL.NBT, (short) level); +- list.add(tag); ++ // Paper start - Replace whole method ++ final ItemMeta itemMeta = getItemMeta(); ++ itemMeta.addEnchant(ench, level, true); ++ setItemMeta(itemMeta); ++ // Paper end + } + + static boolean makeTag(net.minecraft.world.item.ItemStack item) { +@@ -216,66 +198,33 @@ public final class CraftItemStack extends ItemStack { + + @Override + public boolean containsEnchantment(Enchantment ench) { +- return getEnchantmentLevel(ench) > 0; ++ return hasItemMeta() && getItemMeta().hasEnchant(ench); // Paper - use meta + } + + @Override + public int getEnchantmentLevel(Enchantment ench) { +- Validate.notNull(ench, "Cannot find null enchantment"); +- if (handle == null) { +- return 0; +- } +- return EnchantmentHelper.getItemEnchantmentLevel(CraftEnchantment.getRaw(ench), handle); ++ return hasItemMeta() ? getItemMeta().getEnchantLevel(ench) : 0; // Paper - replace entire method with meta + } + + @Override + public int removeEnchantment(Enchantment ench) { + Validate.notNull(ench, "Cannot remove null enchantment"); + +- ListTag list = getEnchantmentList(handle), listCopy; +- if (list == null) { +- return 0; +- } +- int index = Integer.MIN_VALUE; +- int level = Integer.MIN_VALUE; +- int size = list.size(); +- +- for (int i = 0; i < size; i++) { +- CompoundTag enchantment = (CompoundTag) list.get(i); +- String id = enchantment.getString(ENCHANTMENTS_ID.NBT); +- if (id.equals(ench.getKey().toString())) { +- index = i; +- level = 0xffff & enchantment.getShort(ENCHANTMENTS_LVL.NBT); +- break; +- } +- } +- +- if (index == Integer.MIN_VALUE) { +- return 0; +- } +- if (size == 1) { +- handle.getTag().remove(ENCHANTMENTS.NBT); +- if (handle.getTag().isEmpty()) { +- handle.setTag(null); +- } +- return level; +- } +- +- // This is workaround for not having an index removal +- listCopy = new ListTag(); +- for (int i = 0; i < size; i++) { +- if (i != index) { +- listCopy.add(list.get(i)); +- } ++ // Paper start - replace entire method ++ final ItemMeta itemMeta = getItemMeta(); ++ int level = itemMeta.getEnchantLevel(ench); ++ if (level > 0) { ++ itemMeta.removeEnchant(ench); ++ setItemMeta(itemMeta); + } +- handle.getTag().put(ENCHANTMENTS.NBT, listCopy); ++ // Paper end + + return level; + } + + @Override + public Map getEnchantments() { +- return getEnchantments(handle); ++ return hasItemMeta() ? getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta + } + + 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 cca04daf84e506382365c0ba945cb024bd4d4475..521699615778c4b724d10edfee1d3915e036eb2e 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; + import com.google.common.collect.ImmutableMap; + import com.google.common.collect.ImmutableMultimap; + import com.google.common.collect.LinkedHashMultimap; ++import com.google.common.collect.ImmutableSortedMap; // Paper + import com.google.common.collect.Lists; + import com.google.common.collect.Multimap; + import com.google.common.collect.SetMultimap; +@@ -22,6 +23,7 @@ import java.lang.reflect.InvocationTargetException; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collection; ++import java.util.Comparator; // Paper + import java.util.EnumSet; + import java.util.HashMap; + import java.util.Iterator; +@@ -32,6 +34,7 @@ import java.util.Map; + import java.util.NoSuchElementException; + import java.util.Objects; + import java.util.Set; ++import java.util.TreeMap; // Paper + import java.util.logging.Level; + import java.util.logging.Logger; + import javax.annotation.Nonnull; +@@ -270,7 +273,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + private List lore; // null and empty are two different states internally + private Integer customModelData; + private CompoundTag blockData; +- private Map enchantments; ++ private EnchantmentMap enchantments; // Paper + private Multimap attributeModifiers; + private int repairCost; + private int hideFlag; +@@ -281,7 +284,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); + + private CompoundTag internalTag; +- private final Map unhandledTags = new HashMap(); ++ private final Map unhandledTags = new TreeMap<>(); // Paper + private CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); + + private int version = CraftMagicNumbers.INSTANCE.getDataVersion(); // Internal use only +@@ -302,7 +305,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + this.blockData = meta.blockData; + + if (meta.enchantments != null) { // Spigot +- this.enchantments = new LinkedHashMap(meta.enchantments); ++ this.enchantments = new EnchantmentMap(meta.enchantments); // Paper + } + + if (meta.hasAttributeModifiers()) { +@@ -385,13 +388,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + } + +- static Map buildEnchantments(CompoundTag tag, ItemMetaKey key) { ++ static EnchantmentMap buildEnchantments(CompoundTag tag, ItemMetaKey key) { // Paper + if (!tag.contains(key.NBT)) { + return null; + } + + ListTag ench = tag.getList(key.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); +- Map enchantments = new LinkedHashMap(ench.size()); ++ EnchantmentMap enchantments = new EnchantmentMap(); // Paper + + for (int i = 0; i < ench.size(); i++) { + String id = ((CompoundTag) ench.get(i)).getString(ENCHANTMENTS_ID.NBT); +@@ -544,13 +547,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + } + +- static Map buildEnchantments(Map map, ItemMetaKey key) { ++ static EnchantmentMap buildEnchantments(Map map, ItemMetaKey key) { // Paper + Map ench = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); + if (ench == null) { + return null; + } + +- Map enchantments = new LinkedHashMap(ench.size()); ++ EnchantmentMap enchantments = new EnchantmentMap(); // Paper + for (Map.Entry entry : ench.entrySet()) { + // Doctor older enchants + String enchantKey = entry.getKey().toString(); +@@ -826,14 +829,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + + @Override + public Map getEnchants() { +- return hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); ++ return hasEnchants() ? ImmutableSortedMap.copyOfSorted(enchantments) : ImmutableMap.of(); // Paper + } + + @Override + public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { + Validate.notNull(ench, "Enchantment cannot be null"); + if (enchantments == null) { +- enchantments = new LinkedHashMap(4); ++ enchantments = new EnchantmentMap(); // Paper + } + + if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { +@@ -1214,7 +1217,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + clone.customModelData = this.customModelData; + clone.blockData = this.blockData; + if (this.enchantments != null) { +- clone.enchantments = new LinkedHashMap(this.enchantments); ++ clone.enchantments = new EnchantmentMap(this.enchantments); // Paper + } + if (this.hasAttributeModifiers()) { + clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); +@@ -1446,4 +1449,22 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return HANDLED_TAGS; + } + } ++ ++ // Paper start ++ private static class EnchantmentMap extends TreeMap { ++ private EnchantmentMap(Map enchantments) { ++ this(); ++ putAll(enchantments); ++ } ++ ++ private EnchantmentMap() { ++ super(Comparator.comparing(o -> o.getKey().toString())); ++ } ++ ++ public EnchantmentMap clone() { ++ return (EnchantmentMap) super.clone(); ++ } ++ } ++ // Paper end ++ + } diff --git a/patches/server-remapped/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/patches/server-remapped/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch new file mode 100644 index 0000000000..a940748e3b --- /dev/null +++ b/patches/server-remapped/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 15:12:22 -0400 +Subject: [PATCH] Configurable Non Player Arrow Despawn Rate + +Can set a much shorter despawn rate for arrows that players can not pick up. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3ac2ac3db9b1c271b3c21930bb13716669ff64d3..3c78d3234054ce2dc46ef77decb6adb0cbd10620 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -215,4 +215,19 @@ public class PaperWorldConfig { + private void nonPlayerEntitiesOnScoreboards() { + nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); + } ++ ++ public int nonPlayerArrowDespawnRate = -1; ++ public int creativeArrowDespawnRate = -1; ++ private void nonPlayerArrowDespawnRate() { ++ nonPlayerArrowDespawnRate = getInt("non-player-arrow-despawn-rate", -1); ++ if (nonPlayerArrowDespawnRate == -1) { ++ nonPlayerArrowDespawnRate = spigotConfig.arrowDespawnRate; ++ } ++ creativeArrowDespawnRate = getInt("creative-arrow-despawn-rate", -1); ++ if (creativeArrowDespawnRate == -1) { ++ creativeArrowDespawnRate = spigotConfig.arrowDespawnRate; ++ } ++ log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); ++ log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); ++ } + } +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 371fdcbf1f9c01f6a356393f6c3767511f230930..0dc5792d542658107c9c22c1f920986decd13920 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -281,7 +281,7 @@ public abstract class AbstractArrow extends Projectile { + + protected void tickDespawn() { + ++this.life; +- if (this.life >= ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)) { // Spigot ++ if (this.life >= (pickup == Pickup.CREATIVE_ONLY ? level.paperConfig.creativeArrowDespawnRate : (pickup == Pickup.DISALLOWED ? level.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? + this.remove(); + } + diff --git a/patches/server-remapped/0066-Add-World-Util-Methods.patch b/patches/server-remapped/0066-Add-World-Util-Methods.patch new file mode 100644 index 0000000000..83f43bb54a --- /dev/null +++ b/patches/server-remapped/0066-Add-World-Util-Methods.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 20:16:03 -0400 +Subject: [PATCH] Add World Util Methods + +Methods that can be used for other patches to help improve logic. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 89472b6e8f38921db50440d0213e40ac893892f1..e1f9a12c7fb4818a785b9a4819f94fccde02b6a2 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -191,7 +191,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; + +- public LevelChunk getChunkIfLoaded(int x, int z) { ++ @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkSource.getChunk(x, z, false); + } + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 94e268a05b4601c29b6d2845f0fc2311643a161f..799721ac63f0c08dd03a788b87eafa9a8cc976cc 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -297,11 +297,27 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + + @Override +- public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ public final FluidState getFluidIfLoaded(BlockPos blockposition) { + ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); + + return chunk == null ? null : chunk.getFluidState(blockposition); + } ++ ++ public final boolean isLoadedAndInBounds(BlockPos blockposition) { // Paper - final for inline ++ return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; ++ } ++ ++ public LevelChunk getChunkIfLoaded(int x, int z) { // Overridden in WorldServer for ABI compat which has final ++ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(x, z); ++ } ++ public final LevelChunk getChunkIfLoaded(BlockPos blockposition) { ++ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ } ++ ++ // reduces need to do isLoaded before getType ++ public final BlockState getTypeIfLoadedAndInBounds(BlockPos blockposition) { ++ return getWorldBorder().isInBounds(blockposition) ? getTypeIfLoaded(blockposition) : null; ++ } + // Paper end + + @Override +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index 31f17956b3b031d1a47bda4d282554c8a7853097..0846f649dca3422dbab3bb0a4826e27430cc8186 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -31,6 +31,7 @@ public class WorldBorder { + + public WorldBorder() {} + ++ public final boolean isInBounds(BlockPos blockposition) { return this.isWithinBounds(blockposition); } // Paper - OBFHELPER + public boolean isWithinBounds(BlockPos pos) { + return (double) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ(); + } diff --git a/patches/server-remapped/0067-Custom-replacement-for-eaten-items.patch b/patches/server-remapped/0067-Custom-replacement-for-eaten-items.patch new file mode 100644 index 0000000000..2e91f18d2b --- /dev/null +++ b/patches/server-remapped/0067-Custom-replacement-for-eaten-items.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sun, 21 Jun 2015 15:07:20 -0400 +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 d483d552092c901fec262c43e488784d9cd8acb9..3c707ca6b56e89b671db6316d4db90a2903f33b4 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3202,9 +3202,10 @@ public abstract class LivingEntity extends Entity { + this.triggerItemUseEffects(this.useItem, 16); + // CraftBukkit start - fire PlayerItemConsumeEvent + ItemStack itemstack; ++ PlayerItemConsumeEvent event = null; // Paper + if (this instanceof ServerPlayer) { + org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.useItem); +- PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); ++ event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); // Paper + level.getCraftServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { +@@ -3218,6 +3219,13 @@ public abstract class LivingEntity extends Entity { + } else { + itemstack = this.useItem.finishUsingItem(this.level, this); + } ++ ++ // Paper start - save the default replacement item and change it if necessary ++ final ItemStack defaultReplacement = itemstack; ++ if (event != null && event.getReplacement() != null) { ++ itemstack = CraftItemStack.asNMSCopy(event.getReplacement()); ++ } ++ // Paper end + // CraftBukkit end + + if (itemstack != this.useItem) { +@@ -3225,6 +3233,11 @@ public abstract class LivingEntity extends Entity { + } + + this.stopUsingItem(); ++ // Paper start - if the replacement is anything but the default, update the client inventory ++ if (this instanceof ServerPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { ++ ((ServerPlayer) this).getBukkitEntity().updateInventory(); ++ } ++ // Paper end + } + + } diff --git a/patches/server-remapped/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/patches/server-remapped/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch new file mode 100644 index 0000000000..0d5d5d19aa --- /dev/null +++ b/patches/server-remapped/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 27 Sep 2015 01:18:02 -0400 +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 3c707ca6b56e89b671db6316d4db90a2903f33b4..a326e5b4ac055f2f8a95c6eaccd8d0a97762da1f 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -699,7 +699,13 @@ public abstract class LivingEntity extends Entity { + + @Override + public void readAdditionalSaveData(CompoundTag tag) { +- this.setAbsorptionAmount(tag.getFloat("AbsorptionAmount")); ++ // Paper start - jvm keeps optimizing the setter ++ float absorptionAmount = tag.getFloat("AbsorptionAmount"); ++ if (Float.isNaN(absorptionAmount)) { ++ absorptionAmount = 0; ++ } ++ this.setAbsorptionAmount(absorptionAmount); ++ // Paper end + if (tag.contains("Attributes", 9) && this.level != null && !this.level.isClientSide) { + this.getAttributes().load(tag.getList("Attributes", 10)); + } +@@ -1148,6 +1154,10 @@ public abstract class LivingEntity extends Entity { + } + + public void setHealth(float health) { ++ // Paper start ++ if (Float.isNaN(health)) { health = getMaxHealth(); if (this.valid) { ++ System.err.println("[NAN-HEALTH] " + getScoreboardName() + " had NaN health set"); ++ } } // Paper end + // CraftBukkit start - Handle scaled health + if (this instanceof ServerPlayer) { + org.bukkit.craftbukkit.entity.CraftPlayer player = ((ServerPlayer) this).getBukkitEntity(); +@@ -3042,7 +3052,7 @@ public abstract class LivingEntity extends Entity { + } + + public void setAbsorptionAmount(float amount) { +- if (amount < 0.0F) { ++ if (amount < 0.0F || Float.isNaN(amount)) { // Paper + amount = 0.0F; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index dd29038778d73fae84df360515f3c670915f1d48..b7d5a718375083a4162df4bb41de3acd57b297fb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1678,6 +1678,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void setRealHealth(double health) { ++ if (Double.isNaN(health)) {return;} // Paper + this.health = health; + } + diff --git a/patches/server-remapped/0069-Use-a-Shared-Random-for-Entities.patch b/patches/server-remapped/0069-Use-a-Shared-Random-for-Entities.patch new file mode 100644 index 0000000000..ddca7a2d46 --- /dev/null +++ b/patches/server-remapped/0069-Use-a-Shared-Random-for-Entities.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 22 Mar 2016 00:33:47 -0400 +Subject: [PATCH] Use a Shared Random for Entities + +Reduces memory usage and provides ensures more randomness, Especially since a lot of garbage entity objects get created. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 93d3408231a177cf6d2086594756adffe3efa702..61048140cf0adca03bfb57193ada0adaee73b1bb 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -142,6 +142,21 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; + } + ++ // Paper start ++ public static Random SHARED_RANDOM = new Random() { ++ private boolean locked = false; ++ @Override ++ public synchronized void setSeed(long seed) { ++ if (locked) { ++ LogManager.getLogger().error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable()); ++ } else { ++ super.setSeed(seed); ++ locked = true; ++ } ++ } ++ }; ++ // Paper end ++ + private CraftEntity bukkitEntity; + + public CraftEntity getBukkitEntity() { +@@ -271,7 +286,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.stuckSpeedMultiplier = Vec3.ZERO; + this.nextStep = 1.0F; + this.nextFlap = 1.0F; +- this.random = new Random(); ++ this.random = SHARED_RANDOM; // Paper + this.remainingFireTicks = -this.getFireImmuneTicks(); + this.fluidHeight = new Object2DoubleArrayMap(2); + this.firstTick = true; diff --git a/patches/server-remapped/0070-Configurable-spawn-chances-for-skeleton-horses.patch b/patches/server-remapped/0070-Configurable-spawn-chances-for-skeleton-horses.patch new file mode 100644 index 0000000000..59b6c7f72a --- /dev/null +++ b/patches/server-remapped/0070-Configurable-spawn-chances-for-skeleton-horses.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 22 Mar 2016 12:04:28 -0500 +Subject: [PATCH] Configurable spawn chances for skeleton horses + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3c78d3234054ce2dc46ef77decb6adb0cbd10620..cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -230,4 +230,12 @@ public class PaperWorldConfig { + log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); + log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); + } ++ ++ public double skeleHorseSpawnChance; ++ private void skeleHorseSpawnChance() { ++ skeleHorseSpawnChance = getDouble("skeleton-horse-thunder-spawn-chance", 0.01D); ++ if (skeleHorseSpawnChance < 0) { ++ skeleHorseSpawnChance = 0.01D; // Vanilla value ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index e1f9a12c7fb4818a785b9a4819f94fccde02b6a2..22c687e3db79bcfbc512ce3993d6e8a6db062360 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -584,7 +584,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); + if (this.isRainingAt(blockposition)) { + DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); +- boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * 0.01D; ++ boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance; // Paper + + if (flag1) { + SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create((net.minecraft.world.level.Level) this); diff --git a/patches/server-remapped/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/patches/server-remapped/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch new file mode 100644 index 0000000000..2c0ed8f7cd --- /dev/null +++ b/patches/server-remapped/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch @@ -0,0 +1,206 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 02:07:55 -0600 +Subject: [PATCH] Optimize isValidLocation, getType and getBlockData for + inlining + +Hot methods, so reduce # of instructions for the method. + +Move is valid location test to the BlockPosition class so that it can access local variables. + +Replace all calls to the new place to the unnecessary forward. + +Optimize getType and getBlockData to manually inline and optimize the calls + +diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java +index 3e79b274b8e0406a3cbdd94c7cec091b583109ca..c22de593be404c4e921724bba6a69c13759a95fd 100644 +--- a/src/main/java/net/minecraft/core/Vec3i.java ++++ b/src/main/java/net/minecraft/core/Vec3i.java +@@ -22,6 +22,15 @@ public class Vec3i implements Comparable { + private int y;public final void setY(final int y) { this.y = y; } // Paper - OBFHELPER + private int z;public final void setZ(final int z) { this.z = z; } // Paper - OBFHELPER + ++ // Paper start ++ public boolean isValidLocation() { ++ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && getY() >= 0 && getY() < 256; ++ } ++ public boolean isInvalidYLocation() { ++ return y < 0 || y >= 256; ++ } ++ // Paper end ++ + public Vec3i(int x, int y, int z) { + this.x = x; + this.y = y; +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 799721ac63f0c08dd03a788b87eafa9a8cc976cc..24a6429059f58f51c97386ca2823ca0910288dec 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -239,7 +239,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + + public static boolean isInWorldBounds(BlockPos pos) { +- return !isOutsideBuildHeight(pos) && isInWorldBoundsHorizontal(pos); ++ return pos.isValidLocation(); // Paper - use better/optimized check + } + + public static boolean isInSpawnableBounds(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index 3ca6289ba4952b5036367451b50cd90a78c0f938..e6303cdb433ee2b6782e2a0bd6b03e4f6ecb18ba 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -25,6 +25,7 @@ import org.apache.logging.log4j.LogManager; + + public interface ChunkAccess extends BlockGetter, FeatureAccess { + ++ BlockState getType(final int x, final int y, final int z); // Paper + @Nullable + BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); + +diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +index a26de06252207cf333ea4a8d73f0af6ddc239103..e369730ac6909ff5343468bd685c9ea2b6b3cfed 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +@@ -23,7 +23,7 @@ import net.minecraft.world.phys.AABB; + + public class EmptyLevelChunk extends LevelChunk { + +- private static final Biome[] BIOMES = (Biome[]) Util.make((Object) (new Biome[ChunkBiomeContainer.BIOMES_SIZE]), (abiomebase) -> { ++ private static final Biome[] BIOMES = Util.make((new Biome[ChunkBiomeContainer.BIOMES_SIZE]), (abiomebase) -> { // Paper - decompile error + Arrays.fill(abiomebase, Biomes.PLAINS); + }); + +@@ -31,6 +31,11 @@ public class EmptyLevelChunk extends LevelChunk { + super(world, pos, new ChunkBiomeContainer(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), EmptyLevelChunk.BIOMES)); + } + ++ // Paper start ++ @Override public BlockState getType(int x, int y, int z) { ++ return Blocks.VOID_AIR.defaultBlockState(); ++ } ++ // Paper end + @Override + public BlockState getBlockState(BlockPos pos) { + return Blocks.VOID_AIR.defaultBlockState(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +index 04940ab2814cf39157d234dc4615646d7c760460..17fa8b23d1000ae53f2b4f1a6e8817c1005c1c81 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +@@ -42,6 +42,11 @@ public class ImposterProtoChunk extends ProtoChunk { + public BlockState getBlockState(BlockPos pos) { + return this.wrapped.getBlockState(pos); + } ++ // Paper start ++ public final BlockState getType(final int x, final int y, final int z) { ++ return this.wrapped.getBlockData(x, y, z); ++ } ++ // Paper end + + @Override + public FluidState getFluidState(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 9ca05aa06696883adc8b67a68ca6d2d850e95d25..546fb2f42e6bf333582b504d0a29991698505df3 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -347,12 +347,27 @@ public class LevelChunk implements ChunkAccess { + return this.sections; + } + +- @Override ++ // Paper start - Optimize getBlockData to reduce instructions ++ public final BlockState getBlockData(BlockPos pos) { return getBlockData(pos.getX(), pos.getY(), pos.getZ()); } // Paper + public BlockState getBlockState(BlockPos pos) { +- int i = pos.getX(); +- int j = pos.getY(); +- int k = pos.getZ(); ++ return this.getBlockData(pos.getX(), pos.getY(), pos.getZ()); ++ } + ++ public BlockState getType(final int x, final int y, final int z) { ++ return getBlockData(x, y, z); ++ } ++ public final BlockState getBlockData(final int x, final int y, final int z) { ++ // Method body / logic copied from below ++ final int i = y >> 4; ++ if (y < 0 || i >= this.sections.length || this.sections[i] == null || this.sections[i].nonEmptyBlockCount == 0) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) ++ return this.sections[i].states.get((y & 15) << 8 | (z & 15) << 4 | x & 15); ++ } ++ ++ public BlockState getBlockData_unused(int i, int j, int k) { ++ // Paper end + if (this.world.isDebug()) { + BlockState iblockdata = null; + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index b54d82e0f41a03c91e0de8df8249a91da3c04d0e..f5db97fb0dac78e1d9aa68d0417aa13f39914f52 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -13,10 +13,10 @@ public class LevelChunkSection { + + public static final Palette GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState()); + private final int bottomBlockY; +- private short nonEmptyBlockCount; ++ short nonEmptyBlockCount; // Paper - package-private + private short tickingBlockCount; + private short tickingFluidCount; +- private final PalettedContainer states; ++ final PalettedContainer states; // Paper - package-private + + public LevelChunkSection(int yOffset) { + this(yOffset, (short) 0, (short) 0, (short) 0); +@@ -30,8 +30,8 @@ public class LevelChunkSection { + this.states = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); + } + +- public BlockState getBlockState(int x, int y, int z) { +- return (BlockState) this.states.get(x, y, z); ++ public final BlockState getBlockState(int x, int y, int z) { // Paper ++ return this.states.get(y << 8 | z << 4 | x); // Paper - inline + } + + public FluidState getFluidState(int x, int y, int z) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index d4db27421736f665739436c1ac4d3c6d5cae95cd..6d3dcd19ce1abc9d502903b8008949b5174a13c3 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -133,7 +133,7 @@ public class PalettedContainer implements PaletteResize { + } + + public T get(int x, int y, int z) { +- return this.get(getIndex(x, y, z)); ++ return this.get(y << 8 | z << 4 | x); // Paper - inline + } + + protected T get(int index) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index 7cd3f89004b0a64772fc3dfbdd132ba5a850b63e..d8b7b210484079c9ca2c34831c84102cba6692f5 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -113,16 +113,18 @@ public class ProtoChunk implements ChunkAccess { + + @Override + public BlockState getBlockState(BlockPos pos) { +- int i = pos.getY(); +- +- if (Level.isOutsideBuildHeight(i)) { ++ return getType(pos.getX(), pos.getY(), pos.getZ()); ++ } ++ // Paper start ++ public BlockState getType(final int x, final int y, final int z) { ++ if (y < 0 || y >= 256) { + return Blocks.VOID_AIR.defaultBlockState(); + } else { +- LevelChunkSection chunksection = this.getSections()[i >> 4]; +- +- return LevelChunkSection.isEmpty(chunksection) ? Blocks.AIR.defaultBlockState() : chunksection.getBlockState(pos.getX() & 15, i & 15, pos.getZ() & 15); ++ LevelChunkSection chunksection = this.getSections()[y >> 4]; ++ return chunksection == LevelChunk.EMPTY_CHUNK_SECTION || chunksection.isEmpty() ? Blocks.AIR.defaultBlockState() : chunksection.getBlockState(x & 15, y & 15, z & 15); + } + } ++ // Paper end + + @Override + public FluidState getFluidState(BlockPos pos) { diff --git a/patches/server-remapped/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/patches/server-remapped/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch new file mode 100644 index 0000000000..1bc2cb3b6f --- /dev/null +++ b/patches/server-remapped/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 19:55:45 -0400 +Subject: [PATCH] Only process BlockPhysicsEvent if a plugin has a listener + +Saves on some object allocation and processing when no plugin listens to this + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 901d5497667706c049718dc4fca37a1bc489c465..f7763a773bce4d8d947c8c859fe84d8a601034c5 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1290,6 +1290,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper + + this.profiler.push(() -> { + return worldserver + " " + worldserver.dimension().location(); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 22c687e3db79bcfbc512ce3993d6e8a6db062360..8b0a384caa09848d61b3a6259dd56590cd52d0a0 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -190,6 +190,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + private int tickPosition; + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; ++ public boolean hasPhysicsEvent = true; // Paper + + @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkSource.getChunk(x, z, false); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 24a6429059f58f51c97386ca2823ca0910288dec..d47ed15382f98aabd509e32a3c202a91088adf6b 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -458,7 +458,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // CraftBukkit start + iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam + CraftWorld world = ((ServerLevel) this).getWorld(); +- if (world != null) { ++ if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper + BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); + this.getCraftServer().getPluginManager().callEvent(event); + +@@ -560,7 +560,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + try { + // CraftBukkit start + CraftWorld world = ((ServerLevel) this).getWorld(); +- if (world != null) { ++ if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper + BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(sourcePos.getX(), sourcePos.getY(), sourcePos.getZ()), CraftBlockData.fromData(iblockdata), world.getBlockAt(neighborPos.getX(), neighborPos.getY(), neighborPos.getZ())); + this.getCraftServer().getPluginManager().callEvent(event); + +diff --git a/src/main/java/net/minecraft/world/level/block/BushBlock.java b/src/main/java/net/minecraft/world/level/block/BushBlock.java +index d6cb341d4d8e20b77979a241dd2e4346455796d7..42635b6115187abeffb290ca040350fd97cf89f7 100644 +--- a/src/main/java/net/minecraft/world/level/block/BushBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BushBlock.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; + + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; +@@ -23,7 +24,7 @@ public class BushBlock extends Block { + public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { + // CraftBukkit start + if (!state.canSurvive(world, pos)) { +- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { ++ if (!(world instanceof ServerLevel && ((ServerLevel) world).hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper + return Blocks.AIR.defaultBlockState(); + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java +index db444689092f537dd736dc73c532bd540fadcf86..86c5025d1b21dc35782124eca66288c63626147a 100644 +--- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java +@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +@@ -83,7 +84,7 @@ public class DoublePlantBlock extends BushBlock { + + protected static void preventCreativeDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) { + // CraftBukkit start +- if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { ++ if (((ServerLevel)world).hasPhysicsEvent && org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper + return; + } + // CraftBukkit end diff --git a/patches/server-remapped/0073-Entity-AddTo-RemoveFrom-World-Events.patch b/patches/server-remapped/0073-Entity-AddTo-RemoveFrom-World-Events.patch new file mode 100644 index 0000000000..0b9b2867e9 --- /dev/null +++ b/patches/server-remapped/0073-Entity-AddTo-RemoveFrom-World-Events.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 20:32:58 -0400 +Subject: [PATCH] Entity AddTo/RemoveFrom World Events + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 8b0a384caa09848d61b3a6259dd56590cd52d0a0..f7eddb39985072afeb79ec0cbfc084d7e84638e6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1208,7 +1208,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (entity instanceof Mob) { + this.navigations.remove(((Mob) entity).getNavigation()); + } +- ++ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + entity.valid = false; // CraftBukkit + } + +@@ -1246,6 +1246,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + entity.origin = entity.getBukkitEntity().getLocation(); + } + // Paper end ++ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + } + + } diff --git a/patches/server-remapped/0074-Configurable-Chunk-Inhabited-Time.patch b/patches/server-remapped/0074-Configurable-Chunk-Inhabited-Time.patch new file mode 100644 index 0000000000..126102b49a --- /dev/null +++ b/patches/server-remapped/0074-Configurable-Chunk-Inhabited-Time.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 20:46:14 -0400 +Subject: [PATCH] Configurable Chunk Inhabited Time + +Vanilla stores how long a chunk has been active on a server, and dynamically scales some +aspects of vanilla gameplay to this factor. + +For people who want all chunks to be treated equally, you can chose a fixed value. + +This allows to fine-tune vanilla gameplay. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0..74ba5dbb83c13ce1721619b755036a7864a1fb90 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -238,4 +238,14 @@ public class PaperWorldConfig { + skeleHorseSpawnChance = 0.01D; // Vanilla value + } + } ++ ++ public int fixedInhabitedTime; ++ private void fixedInhabitedTime() { ++ if (PaperConfig.version < 16) { ++ if (!config.getBoolean("world-settings.default.use-chunk-inhabited-timer", true)) config.set("world-settings.default.fixed-chunk-inhabited-time", 0); ++ if (!config.getBoolean("world-settings." + worldName + ".use-chunk-inhabited-timer", true)) config.set("world-settings." + worldName + ".fixed-chunk-inhabited-time", 0); ++ set("use-chunk-inhabited-timer", null); ++ } ++ fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 546fb2f42e6bf333582b504d0a29991698505df3..70f5b025c2b803df3de8a51cbcfafbe915866f42 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -1021,7 +1021,7 @@ public class LevelChunk implements ChunkAccess { + + @Override + public long getInhabitedTime() { +- return this.inhabitedTime; ++ return world.paperConfig.fixedInhabitedTime < 0 ? this.inhabitedTime : world.paperConfig.fixedInhabitedTime; // Paper + } + + @Override diff --git a/patches/server-remapped/0075-EntityPathfindEvent.patch b/patches/server-remapped/0075-EntityPathfindEvent.patch new file mode 100644 index 0000000000..e784dacc5f --- /dev/null +++ b/patches/server-remapped/0075-EntityPathfindEvent.patch @@ -0,0 +1,125 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 21:22:26 -0400 +Subject: [PATCH] EntityPathfindEvent + +Fires when an Entity decides to start moving to a location. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java +index 0af2c5dde41043a6fb2fcd07db96288c7f96e0c7..5e7e678c4469e34c7ae39656f547243fbcf1d0da 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java +@@ -37,7 +37,7 @@ public class FlyingPathNavigation extends PathNavigation { + + @Override + public Path createPath(Entity entity, int distance) { +- return this.createPath(entity.blockPosition(), distance); ++ return this.a(entity.blockPosition(), entity, distance); // Paper - Forward target entity + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java +index cd7cb7cbe55a36282de394efc95f4ba7cc6a75cf..01be1de9d9ca0a86d69b2e82693bd0fea61a969f 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java +@@ -75,7 +75,7 @@ public class GroundPathNavigation extends PathNavigation { + + @Override + public Path createPath(Entity entity, int distance) { +- return this.createPath(entity.blockPosition(), distance); ++ return this.a(entity.blockPosition(), entity, distance); // Paper - Forward target entity + } + + private int getSurfaceY() { +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index 3cfd913e31236e35e7225ba19d292cacb8b4134a..ae8d430382b20ddd837c47e39515c7995f25312a 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -10,6 +10,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Position; + import net.minecraft.core.Vec3i; + import net.minecraft.network.protocol.game.DebugPackets; ++import net.minecraft.server.MCUtil; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.Mob; +@@ -28,7 +29,7 @@ import net.minecraft.world.phys.Vec3; + + public abstract class PathNavigation { + +- protected final Mob mob; ++ protected final Mob mob; public Entity getEntity() { return mob; } // Paper - OBFHELPER + protected final Level level; + @Nullable + protected Path path; +@@ -115,36 +116,63 @@ public abstract class PathNavigation { + + @Nullable + public Path createPath(BlockPos target, int distance) { +- return this.createPath(ImmutableSet.of(target), 8, false, distance); ++ // Paper start - add target parameter ++ return this.a(target, null, distance); ++ } ++ @Nullable public Path a(BlockPos blockposition, Entity target, int i) { ++ return this.a(ImmutableSet.of(blockposition), target, 8, false, i); ++ // Paper end + } + + @Nullable + public Path createPath(Entity entity, int distance) { +- return this.createPath(ImmutableSet.of(entity.blockPosition()), 16, true, distance); ++ return this.a(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper + } + + @Nullable ++ // Paper start - Add target + protected Path createPath(Set positions, int range, boolean flag, int distance) { +- if (positions.isEmpty()) { ++ return this.a(positions, null, range, flag, distance); ++ } ++ @Nullable protected Path a(Set set, Entity target, int i, boolean flag, int j) { ++ // Paper end ++ if (set.isEmpty()) { + return null; + } else if (this.mob.getY() < 0.0D) { + return null; + } else if (!this.canUpdatePath()) { + return null; +- } else if (this.path != null && !this.path.isDone() && positions.contains(this.targetPos)) { ++ } else if (this.path != null && !this.path.isDone() && set.contains(this.targetPos)) { + return this.path; + } else { ++ // Paper start - Pathfind event ++ boolean copiedSet = false; ++ for (BlockPos possibleTarget : set) { ++ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), ++ MCUtil.toLocation(getEntity().level, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { ++ if (!copiedSet) { ++ copiedSet = true; ++ set = new java.util.HashSet<>(set); ++ } ++ // note: since we copy the set this remove call is safe, since we're iterating over the old copy ++ set.remove(possibleTarget); ++ if (set.isEmpty()) { ++ return null; ++ } ++ } ++ } ++ // Paper end + this.level.getProfiler().push("pathfind"); + float f = (float) this.mob.getAttributeValue(Attributes.FOLLOW_RANGE); + BlockPos blockposition = flag ? this.mob.blockPosition().above() : this.mob.blockPosition(); +- int k = (int) (f + (float) range); ++ int k = (int) (f + (float) i); + PathNavigationRegion chunkcache = new PathNavigationRegion(this.level, blockposition.offset(-k, -k, -k), blockposition.offset(k, k, k)); +- Path pathentity = this.pathFinder.findPath(chunkcache, this.mob, positions, f, distance, this.maxVisitedNodesMultiplier); ++ Path pathentity = this.pathFinder.findPath(chunkcache, this.mob, set, f, j, this.maxVisitedNodesMultiplier); + + this.level.getProfiler().pop(); + if (pathentity != null && pathentity.getTarget() != null) { + this.targetPos = pathentity.getTarget(); +- this.reachRange = distance; ++ this.reachRange = j; + this.resetStuckTimeout(); + } + diff --git a/patches/server-remapped/0076-Sanitise-RegionFileCache-and-make-configurable.patch b/patches/server-remapped/0076-Sanitise-RegionFileCache-and-make-configurable.patch new file mode 100644 index 0000000000..95fc3262c8 --- /dev/null +++ b/patches/server-remapped/0076-Sanitise-RegionFileCache-and-make-configurable.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Antony Riley +Date: Tue, 29 Mar 2016 08:22:55 +0300 +Subject: [PATCH] Sanitise RegionFileCache and make configurable. + +RegionFileCache prior to this patch would close every single open region +file upon reaching a size of 256. +This patch modifies that behaviour so it closes the the least recently +used RegionFile. +The implementation uses a LinkedHashMap as an LRU cache (modified from HashMap). +The maximum size of the RegionFileCache is also made configurable. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 716f285e67019b8a62922d09c15883c99f9421aa..439dcc6effdc91830d2b7ede9063982998b37120 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -227,4 +227,9 @@ public class PaperConfig { + private static void loadPermsBeforePlugins() { + loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); + } ++ ++ public static int regionFileCacheSize = 256; ++ private static void regionFileCacheSize() { ++ regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index 97a58da9d64d812942ceb71426d35b490bbbe817..f33a5fc725d1d5e895f8878d82ebc4172237ad29 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -33,7 +33,7 @@ public final class RegionFileStorage implements AutoCloseable { + if (regionfile != null) { + return regionfile; + } else { +- if (this.regionCache.size() >= 256) { ++ if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable + ((RegionFile) this.regionCache.removeLast()).close(); + } + diff --git a/patches/server-remapped/0077-Do-not-load-chunks-for-Pathfinding.patch b/patches/server-remapped/0077-Do-not-load-chunks-for-Pathfinding.patch new file mode 100644 index 0000000000..dcc5c72d1e --- /dev/null +++ b/patches/server-remapped/0077-Do-not-load-chunks-for-Pathfinding.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 31 Mar 2016 19:17:58 -0400 +Subject: [PATCH] Do not load chunks for Pathfinding + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index ae8d430382b20ddd837c47e39515c7995f25312a..25bc3adfad956157cef0953e6e632b7b7e352f3a 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -48,7 +48,7 @@ public abstract class PathNavigation { + private BlockPos targetPos; + private int reachRange; + private float maxVisitedNodesMultiplier; +- private final PathFinder pathFinder; ++ private final PathFinder pathFinder; public PathFinder getPathfinder() { return this.pathFinder; } // Paper - OBFHELPER + private boolean isStuck; + + public PathNavigation(Mob mob, Level world) { +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +index 99f3f0b895295229b75d93e98141c0cd75789b69..ba8ee93032aabe7ec4ecf52d452e1a580d6ebc20 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +@@ -20,7 +20,7 @@ public class PathFinder { + + private final Node[] neighbors = new Node[32]; + private final int maxVisitedNodes; +- private final NodeEvaluator nodeEvaluator; ++ private final NodeEvaluator nodeEvaluator; public NodeEvaluator getPathfinder() { return this.nodeEvaluator; } // Paper - OBFHELPER + private final BinaryHeap openSet = new BinaryHeap(); + + public PathFinder(NodeEvaluator pathNodeMaker, int range) { +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +index 0b378348cb9e9576e2a209e651264e2caccfd182..7ae24381b91c282745b7fe5f6897865e74bc0acf 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +@@ -479,7 +479,12 @@ public class WalkNodeEvaluator extends NodeEvaluator { + for (int j1 = -1; j1 <= 1; ++j1) { + if (l != 0 || j1 != 0) { + blockposition_mutableblockposition.set(i + l, j + i1, k + j1); +- BlockState iblockdata = iblockaccess.getBlockState(blockposition_mutableblockposition); ++ // Paper start ++ BlockState iblockdata = iblockaccess.getTypeIfLoaded(blockposition_mutableblockposition); ++ if (iblockdata == null) { ++ pathtype = BlockPathTypes.BLOCKED; ++ } else { ++ // Paper end + + if (iblockdata.is(Blocks.CACTUS)) { + return BlockPathTypes.DANGER_CACTUS; +@@ -496,6 +501,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { + if (iblockaccess.getFluidState(blockposition_mutableblockposition).is((Tag) FluidTags.WATER)) { + return BlockPathTypes.WATER_BORDER; + } ++ } // Paper + } + } + } +@@ -505,7 +511,8 @@ public class WalkNodeEvaluator extends NodeEvaluator { + } + + protected static BlockPathTypes getBlockPathTypeRaw(BlockGetter iblockaccess, BlockPos blockposition) { +- BlockState iblockdata = iblockaccess.getBlockState(blockposition); ++ BlockState iblockdata = iblockaccess.getTypeIfLoaded(blockposition); // Paper ++ if (iblockdata == null) return BlockPathTypes.BLOCKED; // Paper + Block block = iblockdata.getBlock(); + Material material = iblockdata.getMaterial(); + diff --git a/patches/server-remapped/0078-Add-PlayerUseUnknownEntityEvent.patch b/patches/server-remapped/0078-Add-PlayerUseUnknownEntityEvent.patch new file mode 100644 index 0000000000..c91bb4d9ec --- /dev/null +++ b/patches/server-remapped/0078-Add-PlayerUseUnknownEntityEvent.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 2 Apr 2016 05:09:16 -0400 +Subject: [PATCH] Add PlayerUseUnknownEntityEvent + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java +index 9ff5b938f97da5ca1f13fd2bcbf3d13e8b8f760c..e1d219550006d22b0a8e949e820488c6ed96dc58 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java +@@ -11,7 +11,7 @@ import net.minecraft.world.phys.Vec3; + + public class ServerboundInteractPacket implements Packet { + +- private int entityId; ++ private int entityId; public int getEntityId() { return this.entityId; } // Paper - add accessor + private ServerboundInteractPacket.Action action; + private Vec3 location; + private InteractionHand hand; +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 73683ba59d0aff3a61f555b4ae15753e9e4e6141..e2bfe8e916c9e59af81627ea0ee449970527034d 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2198,6 +2198,16 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + } + } ++ // Paper start - fire event ++ else { ++ this.craftServer.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( ++ this.getPlayer(), ++ packet.getEntityId(), ++ packet.getAction() == ServerboundInteractPacket.Action.ATTACK, ++ packet.getHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND ++ )); ++ } ++ // Paper end + + } + diff --git a/patches/server-remapped/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch b/patches/server-remapped/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch new file mode 100644 index 0000000000..d10d109cb2 --- /dev/null +++ b/patches/server-remapped/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 2 Apr 2016 20:37:03 -0400 +Subject: [PATCH] Fix reducedDebugInfo not initialized on client + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index a63babe123fad398b07685ec57cd88756435457c..aa440a6341a6d30aba8fd5f6bcd122bd5d8760cd 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -242,6 +242,7 @@ public abstract class PlayerList { + playerconnection.send(new ClientboundSetCarriedItemPacket(player.inventory.selected)); + playerconnection.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); + playerconnection.send(new ClientboundUpdateTagsPacket(this.server.getTags())); ++ playerconnection.send(new ClientboundEntityEventPacket(player, (byte) (worldserver1.getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23))); // Paper - fix this rule not being initialized on the client + this.sendPlayerPermissionLevel(player); + player.getStats().markAllDirty(); + player.getRecipeBook().sendInitialRecipeBook(player); diff --git a/patches/server-remapped/0080-Configurable-Grass-Spread-Tick-Rate.patch b/patches/server-remapped/0080-Configurable-Grass-Spread-Tick-Rate.patch new file mode 100644 index 0000000000..8481cb94a1 --- /dev/null +++ b/patches/server-remapped/0080-Configurable-Grass-Spread-Tick-Rate.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 Apr 2016 16:28:17 -0400 +Subject: [PATCH] Configurable Grass Spread Tick Rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 74ba5dbb83c13ce1721619b755036a7864a1fb90..db2dddd12f54e6d15916c4cee623676541de37fb 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -248,4 +248,10 @@ public class PaperWorldConfig { + } + fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); + } ++ ++ public int grassUpdateRate = 1; ++ private void grassUpdateRate() { ++ grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); ++ log("Grass Spread Tick Rate: " + grassUpdateRate); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java +index d54f097afc455a01486d7f7459b0cfc4ab4f3970..813a5b0598eca28aa173cd6e34bc16381f313604 100644 +--- a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java +@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; + import java.util.Random; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.FluidTags; + import net.minecraft.tags.Tag; +@@ -41,6 +42,7 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock { + + @Override + public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) { ++ if (this instanceof GrassBlock && world.paperConfig.grassUpdateRate != 1 && (world.paperConfig.grassUpdateRate < 1 || (MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig.grassUpdateRate != 0)) { return; } // Paper + if (!canBeGrass(state, (LevelReader) world, pos)) { + // CraftBukkit start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { diff --git a/patches/server-remapped/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/patches/server-remapped/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch new file mode 100644 index 0000000000..5d706f6263 --- /dev/null +++ b/patches/server-remapped/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 Apr 2016 17:48:50 -0400 +Subject: [PATCH] Fix Cancelling BlockPlaceEvent triggering physics + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index d47ed15382f98aabd509e32a3c202a91088adf6b..89a6a0b4235cfcc1d3ad68ff59a21fa60df4508f 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -518,6 +518,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public void setBlocksDirty(BlockPos pos, BlockState old, BlockState updated) {} + + public void updateNeighborsAt(BlockPos pos, Block block) { ++ if (captureBlockStates) { return; } // Paper - Cancel all physics during placement + this.neighborChanged(pos.west(), block, pos); + this.neighborChanged(pos.east(), block, pos); + this.neighborChanged(pos.below(), block, pos); diff --git a/patches/server-remapped/0082-Optimize-DataBits.patch b/patches/server-remapped/0082-Optimize-DataBits.patch new file mode 100644 index 0000000000..7b5057a4e9 --- /dev/null +++ b/patches/server-remapped/0082-Optimize-DataBits.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Apr 2016 21:38:58 -0400 +Subject: [PATCH] Optimize DataBits + +Remove Debug checks as these are super hot and causing noticeable hits + +Before: http://i.imgur.com/nQsMzAE.png +After: http://i.imgur.com/nJ46crB.png + +Optimize redundant converting of static fields into an unsigned long each call by precomputing it in ctor + +diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java +index 97bde5f8402452e59b0da94edfe1b970cdb86748..dd84984f28484cf7129c294222696784e128221a 100644 +--- a/src/main/java/net/minecraft/util/BitStorage.java ++++ b/src/main/java/net/minecraft/util/BitStorage.java +@@ -13,8 +13,8 @@ public class BitStorage { + private final long mask; + private final int size; + private final int valuesPerLong; +- private final int divideMul; +- private final int divideAdd; ++ private final int divideMul;private final long g_unsigned; // Paper - referenced in b(int) with 2 Integer.toUnsignedLong calls ++ private final int divideAdd;private final long h_unsigned; // Paper + private final int divideShift; + + public BitStorage(int elementBits, int size) { +@@ -29,8 +29,8 @@ public class BitStorage { + this.valuesPerLong = (char) (64 / elementBits); + int k = 3 * (this.valuesPerLong - 1); + +- this.divideMul = BitStorage.MAGIC[k + 0]; +- this.divideAdd = BitStorage.MAGIC[k + 1]; ++ this.divideMul = BitStorage.MAGIC[k + 0]; this.g_unsigned = Integer.toUnsignedLong(this.divideMul); // Paper ++ this.divideAdd = BitStorage.MAGIC[k + 1]; this.h_unsigned = Integer.toUnsignedLong(this.divideAdd); // Paper + this.divideShift = BitStorage.MAGIC[k + 2]; + int l = (size + this.valuesPerLong - 1) / this.valuesPerLong; + +@@ -47,15 +47,15 @@ public class BitStorage { + } + + private int cellIndex(int i) { +- long j = Integer.toUnsignedLong(this.divideMul); +- long k = Integer.toUnsignedLong(this.divideAdd); ++ //long j = Integer.toUnsignedLong(this.g); // Paper ++ //long k = Integer.toUnsignedLong(this.h); // Paper + +- return (int) ((long) i * j + k >> 32 >> this.divideShift); ++ return (int) ((long) i * this.g_unsigned + this.h_unsigned >> 32 >> this.divideShift); // Paper + } + +- public int getAndSet(int index, int value) { +- Validate.inclusiveBetween(0L, (long) (this.size - 1), (long) index); +- Validate.inclusiveBetween(0L, this.mask, (long) value); ++ public final int getAndSet(int index, int value) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper ++ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper + int k = this.cellIndex(index); + long l = this.data[k]; + int i1 = (index - k * this.valuesPerLong) * this.bits; +@@ -65,9 +65,9 @@ public class BitStorage { + return j1; + } + +- public void set(int index, int value) { +- Validate.inclusiveBetween(0L, (long) (this.size - 1), (long) index); +- Validate.inclusiveBetween(0L, this.mask, (long) value); ++ public final void set(int index, int value) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper ++ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper + int k = this.cellIndex(index); + long l = this.data[k]; + int i1 = (index - k * this.valuesPerLong) * this.bits; +@@ -75,8 +75,8 @@ public class BitStorage { + this.data[k] = l & ~(this.mask << i1) | ((long) value & this.mask) << i1; + } + +- public int get(int index) { +- Validate.inclusiveBetween(0L, (long) (this.size - 1), (long) index); ++ public final int get(int index) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper + int j = this.cellIndex(index); + long k = this.data[j]; + int l = (index - j * this.valuesPerLong) * this.bits; diff --git a/patches/server-remapped/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/patches/server-remapped/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch new file mode 100644 index 0000000000..ac90c24b3a --- /dev/null +++ b/patches/server-remapped/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 6 Apr 2016 01:04:23 -0500 +Subject: [PATCH] Option to use vanilla per-world scoreboard coloring on names + +This change is basically a bandaid to fix CB's complete and utter lack +of support for vanilla scoreboard name modifications. + +In the future, finding a way to merge the vanilla expectations in with +bukkit's concept of a display name would be preferable. There was a PR +for this on CB at one point but I can't find it. We may need to do this +ourselves at some point in the future. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index db2dddd12f54e6d15916c4cee623676541de37fb..1942f5224aaebb18adb591d6f70a419cfc1a7bdd 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -254,4 +254,9 @@ public class PaperWorldConfig { + grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); + log("Grass Spread Tick Rate: " + grassUpdateRate); + } ++ ++ public boolean useVanillaScoreboardColoring; ++ private void useVanillaScoreboardColoring() { ++ useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); ++ } + } +diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +index a29b6aaafd529e56a83dd96c32211f21e4aad348..2039f83a718427d0969a1a2e2200f7922097449e 100644 +--- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java ++++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +@@ -16,7 +16,11 @@ import net.kyori.adventure.text.TextReplacementConfig; + import net.kyori.adventure.text.event.ClickEvent; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.scores.PlayerTeam; ++import net.minecraft.world.scores.Team; + import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; ++import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.entity.CraftPlayer; + import org.bukkit.craftbukkit.util.LazyPlayerSet; + import org.bukkit.craftbukkit.util.Waitable; +@@ -178,10 +182,22 @@ public final class ChatProcessor { + } + + private static String legacyDisplayName(final CraftPlayer player) { ++ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { ++ final ServerPlayer ep = player.getHandle(); ++ net.minecraft.network.chat.Component name = ep.getName(); ++ final Team team = ep.getTeam(); ++ if (team != null) { ++ name = team.getFormattedName(name); ++ } ++ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(PaperAdventure.asAdventure(name)) + ChatColor.RESET; ++ } + return player.getDisplayName(); + } + + private static Component displayName(final CraftPlayer player) { ++ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { ++ return PaperAdventure.asAdventure(PlayerTeam.formatNameForTeam(player.getHandle().getTeam(), player.getHandle().getName())); ++ } + return player.displayName(); + } + diff --git a/patches/server-remapped/0084-Workaround-for-setting-passengers-on-players.patch b/patches/server-remapped/0084-Workaround-for-setting-passengers-on-players.patch new file mode 100644 index 0000000000..c2fdc7667a --- /dev/null +++ b/patches/server-remapped/0084-Workaround-for-setting-passengers-on-players.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 10 Apr 2016 03:23:32 -0500 +Subject: [PATCH] Workaround for setting passengers on players + +SPIGOT-1915 & GH-114 + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index b7d5a718375083a4162df4bb41de3acd57b297fb..b264cbe5f91da9e31c5fd00ee285735a19aaad35 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -870,6 +870,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return true; + } + ++ // Paper start - Ugly workaround for SPIGOT-1915 & GH-114 ++ @Override ++ public boolean setPassenger(org.bukkit.entity.Entity passenger) { ++ boolean wasSet = super.setPassenger(passenger); ++ if (wasSet) { ++ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSetPassengersPacket(this.getHandle())); ++ } ++ return wasSet; ++ } ++ // Paper end ++ + @Override + public void setSneaking(boolean sneak) { + getHandle().setShiftKeyDown(sneak); diff --git a/patches/server-remapped/0085-Remove-unused-World-Tile-Entity-List.patch b/patches/server-remapped/0085-Remove-unused-World-Tile-Entity-List.patch new file mode 100644 index 0000000000..d96a9f686a --- /dev/null +++ b/patches/server-remapped/0085-Remove-unused-World-Tile-Entity-List.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 13 Apr 2016 00:25:28 -0400 +Subject: [PATCH] Remove unused World Tile Entity List + +Massive hit to performance and it is completely unnecessary. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index f7eddb39985072afeb79ec0cbfc084d7e84638e6..bb99d9fe5e274318d8480a6de2c45b0a57351f77 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1715,7 +1715,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + bufferedwriter.write(String.format("entities: %d\n", this.entitiesById.size())); +- bufferedwriter.write(String.format("block_entities: %d\n", this.blockEntityList.size())); ++ bufferedwriter.write(String.format("block_entities: %d\n", this.tickableBlockEntities.size())); // Paper - remove unused list + bufferedwriter.write(String.format("block_ticks: %d\n", this.getBlockTicks().size())); + bufferedwriter.write(String.format("fluid_ticks: %d\n", this.getLiquidTicks().size())); + bufferedwriter.write("distance_manager: " + playerchunkmap.getDistanceManager().getDebugStatus() + "\n"); +@@ -1854,7 +1854,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + private void dumpBlockEntities(Writer writer) throws IOException { + CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("type").build(writer); +- Iterator iterator = this.blockEntityList.iterator(); ++ Iterator iterator = this.tickableBlockEntities.iterator(); // Paper - remove unused list + + while (iterator.hasNext()) { + BlockEntity tileentity = (BlockEntity) iterator.next(); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 89a6a0b4235cfcc1d3ad68ff59a21fa60df4508f..8f0fec38b482465285057d3fd27d456cf036f2fd 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -91,7 +91,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public static final ResourceKey NETHER = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation("the_nether")); + public static final ResourceKey END = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation("the_end")); + private static final Direction[] DIRECTIONS = Direction.values(); +- public final List blockEntityList = Lists.newArrayList(); ++ //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list + public final List tickableBlockEntities = Lists.newArrayList(); + protected final List pendingBlockEntities = Lists.newArrayList(); + protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); +@@ -683,9 +683,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + }, blockEntity::getBlockPos}); + } + +- boolean flag = this.blockEntityList.add(blockEntity); ++ boolean flag = true; // Paper - remove unused list + +- if (flag && blockEntity instanceof TickableBlockEntity) { ++ if (flag && blockEntity instanceof TickableBlockEntity && !this.tickableBlockEntities.contains(blockEntity)) { // Paper + this.tickableBlockEntities.add(blockEntity); + } + +@@ -721,7 +721,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + timings.tileEntityTick.startTiming(); // Spigot + if (!this.tileEntityListUnload.isEmpty()) { + this.tickableBlockEntities.removeAll(this.tileEntityListUnload); +- this.blockEntityList.removeAll(this.tileEntityListUnload); ++ //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list + this.tileEntityListUnload.clear(); + } + +@@ -781,7 +781,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + tilesThisCycle--; + this.tickableBlockEntities.remove(tileTickPosition--); + // Spigot end +- this.blockEntityList.remove(tileentity); ++ //this.tileEntityList.remove(tileentity); // Paper - remove unused list + if (this.hasChunkAt(tileentity.getBlockPos())) { + this.getChunkAt(tileentity.getBlockPos()).removeBlockEntity(tileentity.getBlockPos()); + } +@@ -811,7 +811,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.sendBlockUpdated(tileentity1.getBlockPos(), iblockdata, iblockdata, 3); + // CraftBukkit start + // From above, don't screw this up - SPIGOT-1746 +- if (!this.blockEntityList.contains(tileentity1)) { ++ if (true) { // Paper - remove unused list + this.addBlockEntity(tileentity1); + } + // CraftBukkit end +@@ -957,7 +957,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } else { + if (tileentity != null) { + this.pendingBlockEntities.remove(tileentity); +- this.blockEntityList.remove(tileentity); ++ //this.tileEntityList.remove(tileentity); // Paper - remove unused list + this.tickableBlockEntities.remove(tileentity); + } + diff --git a/patches/server-remapped/0086-Don-t-tick-Skulls-unused-code.patch b/patches/server-remapped/0086-Don-t-tick-Skulls-unused-code.patch new file mode 100644 index 0000000000..42e534b702 --- /dev/null +++ b/patches/server-remapped/0086-Don-t-tick-Skulls-unused-code.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 13 Apr 2016 00:30:10 -0400 +Subject: [PATCH] Don't tick Skulls - unused code + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java +index 6a46517e4026971d8c050c685c710883b5976fa3..eebaeaccc3ba1a9ec089d84b8de6c9d36034868f 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java +@@ -31,7 +31,7 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.server.players.GameProfileCache; + import net.minecraft.util.StringUtil; + +-public class SkullBlockEntity extends BlockEntity implements TickableBlockEntity { ++public class SkullBlockEntity extends BlockEntity /*implements ITickable*/ { // Paper - remove tickable + + @Nullable + private static GameProfileCache profileCache; +@@ -134,7 +134,7 @@ public class SkullBlockEntity extends BlockEntity implements TickableBlockEntity + + } + +- @Override ++ // Paper - remove override + public void tick() { + BlockState iblockdata = this.getBlockState(); + diff --git a/patches/server-remapped/0087-Configurable-Player-Collision.patch b/patches/server-remapped/0087-Configurable-Player-Collision.patch new file mode 100644 index 0000000000..3ed6659147 --- /dev/null +++ b/patches/server-remapped/0087-Configurable-Player-Collision.patch @@ -0,0 +1,131 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 13 Apr 2016 02:10:49 -0400 +Subject: [PATCH] Configurable Player Collision + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 439dcc6effdc91830d2b7ede9063982998b37120..504efea7b6f50a0d17f4f353781953dfb18bdeca 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -232,4 +232,9 @@ public class PaperConfig { + private static void regionFileCacheSize() { + regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); + } ++ ++ public static boolean enablePlayerCollisions = true; ++ private static void enablePlayerCollisions() { ++ enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); ++ } + } +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java +index 53f284b720d97ba8ce8fac90bc26e7930dcec6b2..d70e7079ea2c84edbc2a8501f115194e2a4ef2e4 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java +@@ -112,7 +112,7 @@ public class ClientboundSetPlayerTeamPacket implements Packet toRemove = scoreboard.getTeams().stream().filter(team -> team.getName().startsWith("collideRule_")).map(PlayerTeam::getName).collect(java.util.stream.Collectors.toList()); ++ for (String teamName : toRemove) { ++ scoreboard.removeTeam(scoreboard.getTeam(teamName)); // Clean up after ourselves ++ } ++ ++ if (!com.destroystokyo.paper.PaperConfig.enablePlayerCollisions) { ++ this.getPlayerList().collideRuleTeamName = org.apache.commons.lang3.StringUtils.left("collideRule_" + java.util.concurrent.ThreadLocalRandom.current().nextInt(), 16); ++ PlayerTeam collideTeam = scoreboard.createTeam(this.getPlayerList().collideRuleTeamName); ++ collideTeam.setSeeFriendlyInvisibles(false); // Because we want to mimic them not being on a team at all ++ } ++ // Paper end ++ + this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); + this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); + this.connection.acceptConnections(); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index aa440a6341a6d30aba8fd5f6bcd122bd5d8760cd..59fb19cfebe4f488fd02f02db31029d44b65e408 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -79,6 +79,7 @@ import net.minecraft.world.level.storage.PlayerDataStorage; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.Objective; + import net.minecraft.world.scores.PlayerTeam; ++import net.minecraft.world.scores.Scoreboard; + import net.minecraft.world.scores.Team; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -141,6 +142,7 @@ public abstract class PlayerList { + // CraftBukkit start + private CraftServer cserver; + private final Map playersByName = new java.util.HashMap<>(); ++ public @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule + + public PlayerList(MinecraftServer server, RegistryAccess.RegistryHolder registryManager, PlayerDataStorage saveHandler, int maxPlayers) { + this.cserver = server.server = new CraftServer((DedicatedServer) server, this); +@@ -372,6 +374,13 @@ public abstract class PlayerList { + } + + player.initMenu(); ++ // Paper start - Add to collideRule team if needed ++ final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); ++ final PlayerTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName); ++ if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) { ++ scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); ++ } ++ // Paper end + // CraftBukkit - Moved from above, added world + PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.worldDataServer.getLevelName(), player.getX(), player.getY(), player.getZ()); + } +@@ -492,6 +501,16 @@ public abstract class PlayerList { + entityplayer.doTick(); // SPIGOT-924 + // CraftBukkit end + ++ // Paper start - Remove from collideRule team if needed ++ if (this.collideRuleTeamName != null) { ++ final Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard(); ++ final PlayerTeam team = scoreBoard.getTeam(this.collideRuleTeamName); ++ if (entityplayer.getTeam() == team && team != null) { ++ scoreBoard.removePlayerFromTeam(entityplayer.getScoreboardName(), team); ++ } ++ } ++ // Paper end ++ + this.save(entityplayer); + if (entityplayer.isPassenger()) { + Entity entity = entityplayer.getRootVehicle(); +@@ -1140,6 +1159,13 @@ public abstract class PlayerList { + } + // CraftBukkit end + ++ // Paper start - Remove collideRule team if it exists ++ if (this.collideRuleTeamName != null) { ++ final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); ++ final PlayerTeam team = scoreboard.getTeam(this.collideRuleTeamName); ++ if (team != null) scoreboard.removeTeam(team); ++ } ++ // Paper end + } + + // CraftBukkit start diff --git a/patches/server-remapped/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/patches/server-remapped/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch new file mode 100644 index 0000000000..56a3be043d --- /dev/null +++ b/patches/server-remapped/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 13 Apr 2016 20:21:38 -0700 +Subject: [PATCH] Add handshake event to allow plugins to handle client + handshaking logic themselves + + +diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 55b6412bb978abb6f8eaff83a7dd40fbc1ed8b9a..e56ab94ce65e81bb0383a1626a1790c43bd6920e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -29,7 +29,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + // CraftBukkit end + private static final Component IGNORE_STATUS_REASON = new TextComponent("Ignoring status request"); + private final MinecraftServer server; +- private final Connection connection; ++ private final Connection connection; final Connection getNetworkManager() { return this.connection; } // Paper - OBFHELPER + + public ServerHandshakePacketListenerImpl(MinecraftServer server, Connection connection) { + this.server = server; +@@ -88,8 +88,35 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + this.connection.disconnect(chatmessage); + } else { + this.connection.setListener(new ServerLoginPacketListenerImpl(this.server, this.connection)); ++ // Paper start - handshake event ++ boolean proxyLogicEnabled = org.spigotmc.SpigotConfig.bungee; ++ boolean handledByEvent = false; ++ // Try and handle the handshake through the event ++ if (com.destroystokyo.paper.event.player.PlayerHandshakeEvent.getHandlerList().getRegisteredListeners().length != 0) { // Hello? Can you hear me? ++ java.net.SocketAddress socketAddress = this.getNetworkManager().address; ++ String hostnameOfRemote = socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getHostString() : InetAddress.getLoopbackAddress().getHostAddress(); ++ com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packet.hostName, hostnameOfRemote, !proxyLogicEnabled); ++ if (event.callEvent()) { ++ // If we've failed somehow, let the client know so and go no further. ++ if (event.isFailed()) { ++ chatmessage = new TranslatableComponent(event.getFailMessage()); ++ this.getNetworkManager().send(new ClientboundLoginDisconnectPacket(chatmessage)); ++ this.getNetworkManager().disconnect(chatmessage); ++ return; ++ } ++ ++ if (event.getServerHostname() != null) packet.hostName = event.getServerHostname(); ++ if (event.getSocketAddressHostname() != null) this.getNetworkManager().address = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); ++ this.getNetworkManager().spoofedUUID = event.getUniqueId(); ++ this.getNetworkManager().spoofedProfile = gson.fromJson(event.getPropertiesJson(), com.mojang.authlib.properties.Property[].class); ++ handledByEvent = true; // Hooray, we did it! ++ } ++ } ++ // Don't try and handle default logic if it's been handled by the event. ++ if (!handledByEvent && proxyLogicEnabled) { ++ // Paper end + // Spigot Start +- if (org.spigotmc.SpigotConfig.bungee) { ++ //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! + String[] split = packet.hostName.split("\00"); + if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { + packet.hostName = split[0]; diff --git a/patches/server-remapped/0089-Configurable-RCON-IP-address.patch b/patches/server-remapped/0089-Configurable-RCON-IP-address.patch new file mode 100644 index 0000000000..4bc15f3f2f --- /dev/null +++ b/patches/server-remapped/0089-Configurable-RCON-IP-address.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 16 Apr 2016 00:39:33 -0400 +Subject: [PATCH] Configurable RCON IP address + +For servers with multiple IP's, ability to bind to a specific interface. + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +index d10f2e5a13a9e86c32ef5dd8c6732ad8b51ed6a0..545096d9ba403396b6aaa7bb6d912f2de08a967e 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +@@ -64,6 +64,8 @@ public class DedicatedServerProperties extends Settings.MutableValue whiteList; + public final WorldGenSettings worldGenSettings; + ++ public final String rconIp; // Paper - Add rcon ip ++ + // CraftBukkit start + public DedicatedServerProperties(Properties properties, RegistryAccess iregistrycustom, OptionSet optionset) { + super(properties, optionset); +@@ -115,6 +117,10 @@ public class DedicatedServerProperties extends Settings> { + }; + } + +- @Nullable +- private String getStringRaw(String key) { ++ @Nullable String getSettingIfExists(final String path) { return this.getStringRaw(path); } // Paper - OBFHELPER ++ @Nullable private String getStringRaw(String key) { // Paper - OBFHELPER + return (String) getOverride(key, this.properties.getProperty(key)); // CraftBukkit + } + +diff --git a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java b/src/main/java/net/minecraft/server/rcon/thread/RconThread.java +index f2a94e9d9b57ece16873972bc5292f7cf3928848..ef9f659ae5f53a8effa807ecb955ef47d53aacd2 100644 +--- a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java ++++ b/src/main/java/net/minecraft/server/rcon/thread/RconThread.java +@@ -62,7 +62,7 @@ public class RconThread extends GenericThread { + @Nullable + public static RconThread create(ServerInterface server) { + DedicatedServerProperties dedicatedserverproperties = server.getProperties(); +- String s = server.getServerIp(); ++ String s = dedicatedserverproperties.rconIp; // Paper - Configurable rcon ip + + if (s.isEmpty()) { + s = "0.0.0.0"; diff --git a/patches/server-remapped/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch b/patches/server-remapped/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch new file mode 100644 index 0000000000..04b43eed1b --- /dev/null +++ b/patches/server-remapped/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 17 Apr 2016 17:27:09 -0400 +Subject: [PATCH] Prevent Fire from loading chunks & wrongly spread + +This causes the nether to spam unload/reload chunks, plus overall +bad behavior. + +This also stops fire from spreading to illegal locations. + +diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java +index 700078c2fd536cc22351eadf51503efb9acd9df9..85170008de6e77cfb8e4f55ae440a8428d868af4 100644 +--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java +@@ -134,7 +134,7 @@ public class FireBlock extends BaseFireBlock { + BooleanProperty blockstateboolean = (BooleanProperty) FireBlock.PROPERTY_BY_DIRECTION.get(enumdirection); + + if (blockstateboolean != null) { +- iblockdata1 = (BlockState) iblockdata1.setValue(blockstateboolean, this.canBurn(world.getBlockState(pos.relative(enumdirection)))); ++ iblockdata1 = (BlockState) iblockdata1.setValue(blockstateboolean, this.canBurn(world.getTypeIfLoaded(pos.relative(enumdirection)))); // Paper - prevent chunk loads + } + } + +@@ -214,6 +214,7 @@ public class FireBlock extends BaseFireBlock { + } + + blockposition_mutableblockposition.setWithOffset((Vec3i) pos, l, j1, i1); ++ if (blockposition_mutableblockposition.isInvalidYLocation() || !world.hasChunkAt(blockposition_mutableblockposition)) continue; // Paper + int l1 = this.getFireOdds((LevelReader) world, (BlockPos) blockposition_mutableblockposition); + + if (l1 > 0) { +@@ -259,10 +260,16 @@ public class FireBlock extends BaseFireBlock { + } + + private void trySpread(Level world, BlockPos blockposition, int i, Random random, int j, BlockPos sourceposition) { // CraftBukkit add sourceposition +- int k = this.getBurnOdd(world.getBlockState(blockposition)); ++ // Paper start ++ final BlockState iblockdata = world.getTypeIfLoaded(blockposition); ++ if (iblockdata == null) { ++ return; ++ } ++ int k = this.getBurnOdd(iblockdata); ++ // Paper end + + if (random.nextInt(i) < k) { +- BlockState iblockdata = world.getBlockState(blockposition); ++ //IBlockData iblockdata = world.getType(blockposition); // Paper + + // CraftBukkit start + org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); +@@ -308,7 +315,7 @@ public class FireBlock extends BaseFireBlock { + for (int j = 0; j < i; ++j) { + Direction enumdirection = aenumdirection[j]; + +- if (this.canBurn(world.getBlockState(pos.relative(enumdirection)))) { ++ if (this.canBurn(world.getTypeIfLoaded(pos.relative(enumdirection)))) { // Paper - prevent chunk loads + return true; + } + } +@@ -326,7 +333,12 @@ public class FireBlock extends BaseFireBlock { + + for (int k = 0; k < j; ++k) { + Direction enumdirection = aenumdirection[k]; +- BlockState iblockdata = iworldreader.getBlockState(pos.relative(enumdirection)); ++ // Paper start ++ BlockState iblockdata = iworldreader.getTypeIfLoaded(pos.relative(enumdirection)); ++ if (iblockdata == null) { ++ continue; ++ } ++ // Paper end + + i = Math.max(this.getFlameOdds(iblockdata), i); + } +@@ -337,7 +349,7 @@ public class FireBlock extends BaseFireBlock { + + @Override + protected boolean canBurn(BlockState state) { +- return this.getFlameOdds(state) > 0; ++ return state != null && this.getFlameOdds(state) > 0; // Paper - iblockdata can be nullable if chunk is unloaded now + } + + @Override diff --git a/patches/server-remapped/0091-Implement-PlayerLocaleChangeEvent.patch b/patches/server-remapped/0091-Implement-PlayerLocaleChangeEvent.patch new file mode 100644 index 0000000000..c52d99a313 --- /dev/null +++ b/patches/server-remapped/0091-Implement-PlayerLocaleChangeEvent.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Isaac Moore +Date: Tue, 19 Apr 2016 14:09:31 -0500 +Subject: [PATCH] Implement PlayerLocaleChangeEvent + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index ffad931c72e52855a3f139354f5e85c460e2a80b..bd3d9182dfb2c0ae1d8c3b9aa360f94c33252592 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1692,7 +1692,7 @@ public class ServerPlayer extends Player implements ContainerListener { + return s; + } + +- public String locale = "en_us"; // CraftBukkit - add, lowercase ++ public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null + public java.util.Locale adventure$locale = java.util.Locale.US; // Paper + public void updateOptions(ServerboundClientInformationPacket packet) { + // CraftBukkit start +@@ -1700,9 +1700,10 @@ public class ServerPlayer extends Player implements ContainerListener { + PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); + this.server.server.getPluginManager().callEvent(event); + } +- if (!this.locale.equals(packet.language)) { ++ if (this.locale == null || !this.locale.equals(packet.language)) { // Paper - check for null + PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), packet.language); + this.server.server.getPluginManager().callEvent(event); ++ new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.locale, packet.language).callEvent(); // Paper + } + this.locale = packet.language; + // Paper start +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index b264cbe5f91da9e31c5fd00ee285735a19aaad35..fc19b4cacd223b928fbdf922b828beaed630bf2e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1875,8 +1875,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + @Override + public String getLocale() { +- return getHandle().locale; +- ++ // Paper start - Locale change event ++ final String locale = getHandle().locale; ++ return locale != null ? locale : "en_us"; ++ // Paper end + } + + // Paper start diff --git a/patches/server-remapped/0092-EntityRegainHealthEvent-isFastRegen-API.patch b/patches/server-remapped/0092-EntityRegainHealthEvent-isFastRegen-API.patch new file mode 100644 index 0000000000..386b74cf50 --- /dev/null +++ b/patches/server-remapped/0092-EntityRegainHealthEvent-isFastRegen-API.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 22 Apr 2016 01:43:11 -0500 +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 a326e5b4ac055f2f8a95c6eaccd8d0a97762da1f..1131d86080b3100437aa18a00c6277fcea4b7ea8 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1127,10 +1127,16 @@ public abstract class LivingEntity extends Entity { + } + + public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { ++ // Paper start - Forward ++ heal(f, regainReason, false); ++ } ++ ++ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason, boolean isFastRegen) { ++ // Paper end + float f1 = this.getHealth(); + + if (f1 > 0.0F) { +- EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason, isFastRegen); // Paper + // Suppress during worldgen + if (this.valid) { + this.level.getCraftServer().getPluginManager().callEvent(event); +diff --git a/src/main/java/net/minecraft/world/food/FoodData.java b/src/main/java/net/minecraft/world/food/FoodData.java +index 269392592f5271b1bb8c37661fbe685e76e32b74..d18b7d2c22312fc6ec3977ce38a1f04e0b5c8ad4 100644 +--- a/src/main/java/net/minecraft/world/food/FoodData.java ++++ b/src/main/java/net/minecraft/world/food/FoodData.java +@@ -84,7 +84,7 @@ public class FoodData { + if (this.tickTimer >= this.saturatedRegenRate) { // CraftBukkit + float f = Math.min(this.saturationLevel, 6.0F); + +- player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED, true); // CraftBukkit - added RegainReason // Paper - This is fast regen + // this.a(f); CraftBukkit - EntityExhaustionEvent + player.applyExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; diff --git a/patches/server-remapped/0093-Add-ability-to-configure-frosted_ice-properties.patch b/patches/server-remapped/0093-Add-ability-to-configure-frosted_ice-properties.patch new file mode 100644 index 0000000000..e5bee625dc --- /dev/null +++ b/patches/server-remapped/0093-Add-ability-to-configure-frosted_ice-properties.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Thu, 21 Apr 2016 23:51:55 -0700 +Subject: [PATCH] Add ability to configure frosted_ice properties + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1942f5224aaebb18adb591d6f70a419cfc1a7bdd..5baccb8d50c135ab20c38ffd0690f585514ce5af 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -259,4 +259,14 @@ public class PaperWorldConfig { + private void useVanillaScoreboardColoring() { + useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); + } ++ ++ public boolean frostedIceEnabled = true; ++ public int frostedIceDelayMin = 20; ++ public int frostedIceDelayMax = 40; ++ private void frostedIce() { ++ this.frostedIceEnabled = this.getBoolean("frosted-ice.enabled", this.frostedIceEnabled); ++ this.frostedIceDelayMin = this.getInt("frosted-ice.delay.min", this.frostedIceDelayMin); ++ this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); ++ log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +index 0727cc36c99cb5ca5019c71f4540de76b78c7a80..ae2f5acd008d5d7163b56cb4a2d29354299959ca 100644 +--- a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +@@ -30,6 +30,7 @@ public class FrostedIceBlock extends IceBlock { + + @Override + public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) { ++ if (!world.paperConfig.frostedIceEnabled) return; // Paper - add ability to disable frosted ice + if ((random.nextInt(3) == 0 || this.fewerNeigboursThan(world, pos, 4)) && world.getMaxLocalRawBrightness(pos) > 11 - (Integer) state.getValue(FrostedIceBlock.AGE) - state.getLightBlock((BlockGetter) world, pos) && this.slightlyMelt(state, (Level) world, pos)) { + BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + Direction[] aenumdirection = Direction.values(); +@@ -42,12 +43,12 @@ public class FrostedIceBlock extends IceBlock { + BlockState iblockdata1 = world.getBlockState(blockposition_mutableblockposition); + + if (iblockdata1.is((Block) this) && !this.slightlyMelt(iblockdata1, (Level) world, blockposition_mutableblockposition)) { +- world.getBlockTicks().scheduleTick(blockposition_mutableblockposition, this, Mth.nextInt(random, 20, 40)); ++ world.getBlockTicks().scheduleTick(blockposition_mutableblockposition, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay + } + } + + } else { +- world.getBlockTicks().scheduleTick(pos, this, Mth.nextInt(random, 20, 40)); ++ world.getBlockTicks().scheduleTick(pos, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay + } + } + diff --git a/patches/server-remapped/0094-remove-null-possibility-for-getServer-singleton.patch b/patches/server-remapped/0094-remove-null-possibility-for-getServer-singleton.patch new file mode 100644 index 0000000000..2a17e8f4af --- /dev/null +++ b/patches/server-remapped/0094-remove-null-possibility-for-getServer-singleton.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 28 Apr 2016 00:57:27 -0400 +Subject: [PATCH] remove null possibility for getServer singleton + +to stop IDE complaining about potential NPE + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index d639ead95c36985fa0f5a9c51898c4237e373f0e..4e468cb7ccf683b8fc9e04a48cfc25779775e25f 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -178,6 +178,7 @@ import org.spigotmc.SlackActivityAccountant; // Spigot + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { + ++ private static MinecraftServer SERVER; // Paper + public static final Logger LOGGER = LogManager.getLogger(); + public static final File USERID_CACHE_FILE = new File("usercache.json"); + public static final LevelSettings DEMO_SETTINGS = new LevelSettings("Demo World", GameType.SURVIVAL, false, Difficulty.NORMAL, false, new GameRules(), DataPackConfig.DEFAULT); +@@ -284,6 +285,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Fri, 29 Apr 2016 20:02:00 -0400 +Subject: [PATCH] Improve Maps (in item frames) performance and bug fixes + +Maps used a modified version of rendering to support plugin controlled +imaging on maps. The Craft Map Renderer is much slower than Vanilla, +causing maps in item frames to cause a noticeable hit on server performance. + +This updates the map system to not use the Craft system if we detect that no +custom renderers are in use, defaulting to the much simpler Vanilla system. + +Additionally, numerous issues to player position tracking on maps has been fixed. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index bb99d9fe5e274318d8480a6de2c45b0a57351f77..0a613f94d1c796267636e1a343aeee65a49ffed5 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1164,6 +1164,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + { + if ( iter.next().player == entity ) + { ++ map.decorations.remove(entity.getName().getString()); // Paper + iter.remove(); + } + } +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 3b451e75a7f49ea6b543aee9f0a51c0be3c4dfba..c11d5aa115d10e3c12863cf9d42c60194d63b690 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -85,6 +85,7 @@ import net.minecraft.world.item.ElytraItem; + import net.minecraft.world.item.ItemCooldowns; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; ++import net.minecraft.world.item.MapItem; + import net.minecraft.world.item.ProjectileWeaponItem; + import net.minecraft.world.item.SwordItem; + import net.minecraft.world.item.crafting.Recipe; +@@ -104,6 +105,7 @@ import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.entity.StructureBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.block.state.pattern.BlockInWorld; ++import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.PlayerTeam; +@@ -686,6 +688,12 @@ public abstract class Player extends LivingEntity { + return null; + } + // CraftBukkit end ++ // Paper start - remove player from map on drop ++ if (stack.getItem() == Items.FILLED_MAP) { ++ MapItemSavedData worldmap = MapItem.getOrCreateSavedData(stack, this.level); ++ worldmap.updateSeenPlayers(this, stack); ++ } ++ // Paper end + + return entityitem; + } +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +index d44505b3ee2a35422568e9bce0d868191e348fc0..7582c7cd4235d212a0cf66a4c59ce0cedaa360ad 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -57,6 +57,7 @@ public class MapItemSavedData extends SavedData { + private final Map bannerMarkers = Maps.newHashMap(); + public final Map decorations = Maps.newLinkedHashMap(); + private final Map frameMarkers = Maps.newHashMap(); ++ private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper + + // CraftBukkit start + public final CraftMapView mapView; +@@ -69,6 +70,7 @@ public class MapItemSavedData extends SavedData { + // CraftBukkit start + mapView = new CraftMapView(this); + server = (CraftServer) org.bukkit.Bukkit.getServer(); ++ vanillaRender.buffer = colors; // Paper + // CraftBukkit end + } + +@@ -136,6 +138,7 @@ public class MapItemSavedData extends SavedData { + this.bannerMarkers.put(mapiconbanner.getId(), mapiconbanner); + this.addDecoration(mapiconbanner.getDecoration(), (LevelAccessor) null, mapiconbanner.getId(), (double) mapiconbanner.getPos().getX(), (double) mapiconbanner.getPos().getZ(), 180.0D, mapiconbanner.getName()); + } ++ this.vanillaRender.buffer = colors; // Paper + + ListTag nbttaglist1 = tag.getList("frames", 10); + +@@ -216,6 +219,7 @@ public class MapItemSavedData extends SavedData { + this.setDirty(); + } + ++ public void updateSeenPlayers(Player entityhuman, ItemStack itemstack) { this.tickCarriedBy(entityhuman, itemstack); } // Paper - OBFHELPER + public void tickCarriedBy(Player player, ItemStack stack) { + if (!this.carriedByPlayers.containsKey(player)) { + MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = new MapItemSavedData.HoldingPlayer(player); +@@ -451,6 +455,21 @@ public class MapItemSavedData extends SavedData { + + public class HoldingPlayer { + ++ // Paper start ++ private void addSeenPlayers(java.util.Collection icons) { ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) player.getBukkitEntity(); ++ MapItemSavedData.this.decorations.forEach((name, mapIcon) -> { ++ // If this cursor is for a player check visibility with vanish system ++ org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayerExact(name); // Spigot ++ if (other == null || player.canSee(other)) { ++ icons.add(mapIcon); ++ } ++ }); ++ } ++ private boolean shouldUseVanillaMap() { ++ return mapView.getRenderers().size() == 1 && mapView.getRenderers().get(0).getClass() == org.bukkit.craftbukkit.map.CraftMapRenderer.class; ++ } ++ // Paper end + public final Player player; + private boolean dirtyData = true; + private int minDirtyX; +@@ -467,9 +486,12 @@ public class MapItemSavedData extends SavedData { + @Nullable + public Packet nextUpdatePacket(ItemStack stack) { + // CraftBukkit start +- org.bukkit.craftbukkit.map.RenderData render = MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit ++ if (!this.dirtyData && this.tick % 5 != 0) { this.tick++; return null; } // Paper - this won't end up sending, so don't render it! ++ boolean vanillaMaps = shouldUseVanillaMap(); // Paper ++ org.bukkit.craftbukkit.map.RenderData render = !vanillaMaps ? MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()) : MapItemSavedData.this.vanillaRender; // CraftBukkit // Paper + + java.util.Collection icons = new java.util.ArrayList(); ++ if (vanillaMaps) addSeenPlayers(icons); // Paper + + for ( org.bukkit.map.MapCursor cursor : render.cursors) { + +diff --git a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java +index 256a131781721c86dd6cdbc329335964570cbe8c..5768cd512ec166f1e8d1f4a28792015347297c3f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java ++++ b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java +@@ -5,7 +5,7 @@ import org.bukkit.map.MapCursor; + + public class RenderData { + +- public final byte[] buffer; ++ public byte[] buffer; // Paper + public final ArrayList cursors; + + public RenderData() { diff --git a/patches/server-remapped/0096-LootTable-API-Replenishable-Lootables-Feature.patch b/patches/server-remapped/0096-LootTable-API-Replenishable-Lootables-Feature.patch new file mode 100644 index 0000000000..4e9c15788b --- /dev/null +++ b/patches/server-remapped/0096-LootTable-API-Replenishable-Lootables-Feature.patch @@ -0,0 +1,739 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 1 May 2016 21:19:14 -0400 +Subject: [PATCH] LootTable API & Replenishable Lootables Feature + +Provides an API to control the loot table for an object. +Also provides a feature that any Lootable Inventory (Chests in Structures) +can automatically replenish after a given time. + +This feature is good for long term worlds so that newer players +do not suffer with "Every chest has been looted" + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5baccb8d50c135ab20c38ffd0690f585514ce5af..eb04fdb172a50ec1f5b7fe78fa0e7655246abd60 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -269,4 +269,26 @@ public class PaperWorldConfig { + this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); + log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); + } ++ ++ public boolean autoReplenishLootables; ++ public boolean restrictPlayerReloot; ++ public boolean changeLootTableSeedOnFill; ++ public int maxLootableRefills; ++ public int lootableRegenMin; ++ public int lootableRegenMax; ++ private void enhancedLootables() { ++ autoReplenishLootables = getBoolean("lootables.auto-replenish", false); ++ restrictPlayerReloot = getBoolean("lootables.restrict-player-reloot", true); ++ changeLootTableSeedOnFill = getBoolean("lootables.reset-seed-on-fill", true); ++ maxLootableRefills = getInt("lootables.max-refills", -1); ++ lootableRegenMin = PaperConfig.getSeconds(getString("lootables.refresh-min", "12h")); ++ lootableRegenMax = PaperConfig.getSeconds(getString("lootables.refresh-max", "2d")); ++ if (autoReplenishLootables) { ++ log("Lootables: Replenishing every " + ++ PaperConfig.timeSummary(lootableRegenMin) + " to " + ++ PaperConfig.timeSummary(lootableRegenMax) + ++ (restrictPlayerReloot ? " (restricting reloot)" : "") ++ ); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fda64b8860cb696e209eedcfb200e7193d216732 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java +@@ -0,0 +1,34 @@ ++package com.destroystokyo.paper.loottable; ++ ++import LootableInventory; ++import net.minecraft.core.BlockPos; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; ++import org.bukkit.Chunk; ++import org.bukkit.block.Block; ++ ++public interface PaperLootableBlockInventory extends LootableBlockInventory, PaperLootableInventory { ++ ++ RandomizableContainerBlockEntity getTileEntity(); ++ ++ @Override ++ default LootableInventory getAPILootableInventory() { ++ return this; ++ } ++ ++ @Override ++ default Level getNMSWorld() { ++ return getTileEntity().getLevel(); ++ } ++ ++ default Block getBlock() { ++ final BlockPos position = getTileEntity().getBlockPos(); ++ final Chunk bukkitChunk = getTileEntity().getLevel().getChunkAt(position).bukkitChunk; ++ return bukkitChunk.getBlock(position.getX(), position.getY(), position.getZ()); ++ } ++ ++ @Override ++ default PaperLootableInventoryData getLootableData() { ++ return getTileEntity().lootableData; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..292d5ef8a1c428893af729b298eecd32b4c4659a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java +@@ -0,0 +1,29 @@ ++package com.destroystokyo.paper.loottable; ++ ++import LootableInventory; ++import net.minecraft.world.level.Level; ++import org.bukkit.entity.Entity; ++ ++public interface PaperLootableEntityInventory extends LootableEntityInventory, PaperLootableInventory { ++ ++ net.minecraft.world.entity.Entity getHandle(); ++ ++ @Override ++ default LootableInventory getAPILootableInventory() { ++ return this; ++ } ++ ++ default Entity getEntity() { ++ return getHandle().getBukkitEntity(); ++ } ++ ++ @Override ++ default Level getNMSWorld() { ++ return getHandle().getCommandSenderWorld(); ++ } ++ ++ @Override ++ default PaperLootableInventoryData getLootableData() { ++ return getHandle().lootableData; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b3def19a50081cfa758b6e25707b2fc6fed8d3ca +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java +@@ -0,0 +1,71 @@ ++package com.destroystokyo.paper.loottable; ++ ++import org.bukkit.loot.Lootable; ++import LootableInventory; ++import java.util.UUID; ++import net.minecraft.world.level.Level; ++ ++public interface PaperLootableInventory extends LootableInventory, Lootable { ++ ++ PaperLootableInventoryData getLootableData(); ++ LootableInventory getAPILootableInventory(); ++ ++ Level getNMSWorld(); ++ ++ default org.bukkit.World getBukkitWorld() { ++ return getNMSWorld().getWorld(); ++ } ++ ++ @Override ++ default boolean isRefillEnabled() { ++ return getNMSWorld().paperConfig.autoReplenishLootables; ++ } ++ ++ @Override ++ default boolean hasBeenFilled() { ++ return getLastFilled() != -1; ++ } ++ ++ @Override ++ default boolean hasPlayerLooted(UUID player) { ++ return getLootableData().hasPlayerLooted(player); ++ } ++ ++ @Override ++ default Long getLastLooted(UUID player) { ++ return getLootableData().getLastLooted(player); ++ } ++ ++ @Override ++ default boolean setHasPlayerLooted(UUID player, boolean looted) { ++ final boolean hasLooted = hasPlayerLooted(player); ++ if (hasLooted != looted) { ++ getLootableData().setPlayerLootedState(player, looted); ++ } ++ return hasLooted; ++ } ++ ++ @Override ++ default boolean hasPendingRefill() { ++ long nextRefill = getLootableData().getNextRefill(); ++ return nextRefill != -1 && nextRefill > getLootableData().getLastFill(); ++ } ++ ++ @Override ++ default long getLastFilled() { ++ return getLootableData().getLastFill(); ++ } ++ ++ @Override ++ default long getNextRefill() { ++ return getLootableData().getNextRefill(); ++ } ++ ++ @Override ++ default long setNextRefill(long refillAt) { ++ if (refillAt < -1) { ++ refillAt = -1; ++ } ++ return getLootableData().setNextRefill(refillAt); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java +new file mode 100644 +index 0000000000000000000000000000000000000000..88542462d34ba24e8590294bd896d7e73932ef9c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java +@@ -0,0 +1,180 @@ ++package com.destroystokyo.paper.loottable; ++ ++import com.destroystokyo.paper.PaperWorldConfig; ++import org.bukkit.entity.Player; ++import org.bukkit.loot.LootTable; ++ ++import javax.annotation.Nullable; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import java.util.HashMap; ++import java.util.Map; ++import java.util.Random; ++import java.util.UUID; ++ ++public class PaperLootableInventoryData { ++ ++ private static final Random RANDOM = new Random(); ++ ++ private long lastFill = -1; ++ private long nextRefill = -1; ++ private int numRefills = 0; ++ private Map lootedPlayers; ++ private final PaperLootableInventory lootable; ++ ++ public PaperLootableInventoryData(PaperLootableInventory lootable) { ++ this.lootable = lootable; ++ } ++ ++ long getLastFill() { ++ return this.lastFill; ++ } ++ ++ long getNextRefill() { ++ return this.nextRefill; ++ } ++ ++ long setNextRefill(long nextRefill) { ++ long prev = this.nextRefill; ++ this.nextRefill = nextRefill; ++ return prev; ++ } ++ ++ public boolean shouldReplenish(@Nullable net.minecraft.world.entity.player.Player player) { ++ LootTable table = this.lootable.getLootTable(); ++ ++ // No Loot Table associated ++ if (table == null) { ++ return false; ++ } ++ ++ // ALWAYS process the first fill or if the feature is disabled ++ if (this.lastFill == -1 || !this.lootable.getNMSWorld().paperConfig.autoReplenishLootables) { ++ return true; ++ } ++ ++ // Only process refills when a player is set ++ if (player == null) { ++ return false; ++ } ++ ++ // Chest is not scheduled for refill ++ if (this.nextRefill == -1) { ++ return false; ++ } ++ ++ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; ++ ++ // Check if max refills has been hit ++ if (paperConfig.maxLootableRefills != -1 && this.numRefills >= paperConfig.maxLootableRefills) { ++ return false; ++ } ++ ++ // Refill has not been reached ++ if (this.nextRefill > System.currentTimeMillis()) { ++ return false; ++ } ++ ++ ++ final Player bukkitPlayer = (Player) player.getBukkitEntity(); ++ LootableInventoryReplenishEvent event = new LootableInventoryReplenishEvent(bukkitPlayer, lootable.getAPILootableInventory()); ++ if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUUID())) { ++ event.setCancelled(true); ++ } ++ return event.callEvent(); ++ } ++ public void processRefill(@Nullable net.minecraft.world.entity.player.Player player) { ++ this.lastFill = System.currentTimeMillis(); ++ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; ++ if (paperConfig.autoReplenishLootables) { ++ int min = paperConfig.lootableRegenMin; ++ int max = paperConfig.lootableRegenMax; ++ this.nextRefill = this.lastFill + (min + RANDOM.nextInt(max - min + 1)) * 1000L; ++ this.numRefills++; ++ if (paperConfig.changeLootTableSeedOnFill) { ++ this.lootable.setSeed(0); ++ } ++ if (player != null) { // This means that numRefills can be incremented without a player being in the lootedPlayers list - Seems to be EntityMinecartChest specific ++ this.setPlayerLootedState(player.getUUID(), true); ++ } ++ } else { ++ this.lootable.clearLootTable(); ++ } ++ } ++ ++ ++ public void loadNbt(CompoundTag base) { ++ if (!base.contains("Paper.LootableData", 10)) { // 10 = compound ++ return; ++ } ++ CompoundTag comp = base.getCompound("Paper.LootableData"); ++ if (comp.contains("lastFill")) { ++ this.lastFill = comp.getLong("lastFill"); ++ } ++ if (comp.contains("nextRefill")) { ++ this.nextRefill = comp.getLong("nextRefill"); ++ } ++ ++ if (comp.contains("numRefills")) { ++ this.numRefills = comp.getInt("numRefills"); ++ } ++ if (comp.contains("lootedPlayers", 9)) { // 9 = list ++ ListTag list = comp.getList("lootedPlayers", 10); // 10 = compound ++ final int size = list.size(); ++ if (size > 0) { ++ this.lootedPlayers = new HashMap<>(list.size()); ++ } ++ for (int i = 0; i < size; i++) { ++ final CompoundTag cmp = list.getCompound(i); ++ lootedPlayers.put(cmp.getUUID("UUID"), cmp.getLong("Time")); ++ } ++ } ++ } ++ public void saveNbt(CompoundTag base) { ++ CompoundTag comp = new CompoundTag(); ++ if (this.nextRefill != -1) { ++ comp.putLong("nextRefill", this.nextRefill); ++ } ++ if (this.lastFill != -1) { ++ comp.putLong("lastFill", this.lastFill); ++ } ++ if (this.numRefills != 0) { ++ comp.putInt("numRefills", this.numRefills); ++ } ++ if (this.lootedPlayers != null && !this.lootedPlayers.isEmpty()) { ++ ListTag list = new ListTag(); ++ for (Map.Entry entry : this.lootedPlayers.entrySet()) { ++ CompoundTag cmp = new CompoundTag(); ++ cmp.setUUID("UUID", entry.getKey()); ++ cmp.putLong("Time", entry.getValue()); ++ list.add(cmp); ++ } ++ comp.put("lootedPlayers", list); ++ } ++ ++ if (!comp.isEmpty()) { ++ base.put("Paper.LootableData", comp); ++ } ++ } ++ ++ void setPlayerLootedState(UUID player, boolean looted) { ++ if (looted && this.lootedPlayers == null) { ++ this.lootedPlayers = new HashMap<>(); ++ } ++ if (looted) { ++ if (!this.lootedPlayers.containsKey(player)) { ++ this.lootedPlayers.put(player, System.currentTimeMillis()); ++ } ++ } else if (this.lootedPlayers != null) { ++ this.lootedPlayers.remove(player); ++ } ++ } ++ ++ boolean hasPlayerLooted(UUID player) { ++ return this.lootedPlayers != null && this.lootedPlayers.containsKey(player); ++ } ++ ++ Long getLastLooted(UUID player) { ++ return lootedPlayers != null ? lootedPlayers.get(player) : null; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d9b31c8a21fdffb33d1f75b1a16606f218145b39 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java +@@ -0,0 +1,63 @@ ++package com.destroystokyo.paper.loottable; ++ ++import LootableInventory; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; ++import net.minecraft.world.level.Level; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++ ++public class PaperMinecartLootableInventory implements PaperLootableEntityInventory { ++ ++ private AbstractMinecartContainer entity; ++ ++ public PaperMinecartLootableInventory(AbstractMinecartContainer entity) { ++ this.entity = entity; ++ } ++ ++ @Override ++ public org.bukkit.loot.LootTable getLootTable() { ++ return entity.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.lootTable)) : null; ++ } ++ ++ @Override ++ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { ++ setLootTable(table); ++ setSeed(seed); ++ } ++ ++ @Override ++ public void setSeed(long seed) { ++ entity.lootTableSeed = seed; ++ } ++ ++ @Override ++ public long getSeed() { ++ return entity.lootTableSeed; ++ } ++ ++ @Override ++ public void setLootTable(org.bukkit.loot.LootTable table) { ++ entity.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); ++ } ++ ++ @Override ++ public PaperLootableInventoryData getLootableData() { ++ return entity.lootableData; ++ } ++ ++ @Override ++ public Entity getHandle() { ++ return entity; ++ } ++ ++ @Override ++ public LootableInventory getAPILootableInventory() { ++ return (LootableInventory) entity.getBukkitEntity(); ++ } ++ ++ @Override ++ public Level getNMSWorld() { ++ return entity.level; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6bc899ec4dc03b09cc978bc7a763a9755a3d2dc4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java +@@ -0,0 +1,66 @@ ++package com.destroystokyo.paper.loottable; ++ ++import LootableInventory; ++import net.minecraft.server.MCUtil; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++ ++public class PaperTileEntityLootableInventory implements PaperLootableBlockInventory { ++ private RandomizableContainerBlockEntity tileEntityLootable; ++ ++ public PaperTileEntityLootableInventory(RandomizableContainerBlockEntity tileEntityLootable) { ++ this.tileEntityLootable = tileEntityLootable; ++ } ++ ++ @Override ++ public org.bukkit.loot.LootTable getLootTable() { ++ return tileEntityLootable.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null; ++ } ++ ++ @Override ++ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { ++ setLootTable(table); ++ setSeed(seed); ++ } ++ ++ @Override ++ public void setLootTable(org.bukkit.loot.LootTable table) { ++ tileEntityLootable.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); ++ } ++ ++ @Override ++ public void setSeed(long seed) { ++ tileEntityLootable.lootTableSeed = seed; ++ } ++ ++ @Override ++ public long getSeed() { ++ return tileEntityLootable.lootTableSeed; ++ } ++ ++ @Override ++ public PaperLootableInventoryData getLootableData() { ++ return tileEntityLootable.lootableData; ++ } ++ ++ @Override ++ public RandomizableContainerBlockEntity getTileEntity() { ++ return tileEntityLootable; ++ } ++ ++ @Override ++ public LootableInventory getAPILootableInventory() { ++ Level world = tileEntityLootable.getLevel(); ++ if (world == null) { ++ return null; ++ } ++ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, tileEntityLootable.getBlockPos())).getState(); ++ } ++ ++ @Override ++ public Level getNMSWorld() { ++ return tileEntityLootable.getLevel(); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 61048140cf0adca03bfb57193ada0adaee73b1bb..171697e88f5a4d8c0be2a47b67b865bbdc4dfe8c 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -157,6 +157,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + }; + // Paper end + ++ public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper + private CraftEntity bukkitEntity; + + public CraftEntity getBukkitEntity() { +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +index f4758251e58fbb36526cea5c4825561d62c9665a..5b96b1e7428a43c8c5f4a96ea37d5189f0d84f56 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +@@ -45,6 +45,7 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme + public long lootTableSeed; + + // CraftBukkit start ++ { this.lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperMinecartLootableInventory(this)); } // Paper + public List transaction = new java.util.ArrayList(); + private int maxStack = MAX_STACK; + +@@ -202,12 +203,13 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme + @Override + protected void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); ++ this.lootableData.saveNbt(tag); // Paper + if (this.lootTable != null) { + tag.putString("LootTable", this.lootTable.toString()); + if (this.lootTableSeed != 0L) { + tag.putLong("LootTableSeed", this.lootTableSeed); + } +- } else { ++ } if (true) { // Paper - Always save the items, Table may stick around + ContainerHelper.saveAllItems(tag, this.itemStacks); + } + +@@ -216,11 +218,12 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme + @Override + protected void readAdditionalSaveData(CompoundTag tag) { + super.readAdditionalSaveData(tag); ++ this.lootableData.loadNbt(tag); // Paper + this.itemStacks = NonNullList.a(this.getContainerSize(), ItemStack.EMPTY); + if (tag.contains("LootTable", 8)) { + this.lootTable = new ResourceLocation(tag.getString("LootTable")); + this.lootTableSeed = tag.getLong("LootTableSeed"); +- } else { ++ } if (true) { // Paper - always load the items, table may still remain + ContainerHelper.loadAllItems(tag, this.itemStacks); + } + +@@ -251,14 +254,15 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme + } + + public void unpackLootTable(@Nullable Player player) { +- if (this.lootTable != null && this.level.getServer() != null) { ++ if (this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper + LootTable loottable = this.level.getServer().getLootTables().get(this.lootTable); + + if (player instanceof ServerPlayer) { + CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer) player, this.lootTable); + } + +- this.lootTable = null; ++ //this.lootTable = null; // Paper ++ this.lootableData.processRefill(player); // Paper + LootContext.Builder loottableinfo_builder = (new LootContext.Builder((ServerLevel) this.level)).withParameter(LootContextParams.ORIGIN, this.position()).withOptionalRandomSeed(this.lootTableSeed); + + if (player != null) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +index 9d33bc31c8088bfba66be1aecbf20e7ee86e4f83..5ad419941ff1113ef29b9a4593f44d8f35ba8424 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +@@ -27,6 +27,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + @Nullable + public ResourceLocation lootTable; + public long lootTableSeed; ++ public final com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperTileEntityLootableInventory(this)); // Paper + + protected RandomizableContainerBlockEntity(BlockEntityType type) { + super(type); +@@ -42,16 +43,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + } + + protected boolean tryLoadLootTable(CompoundTag nbttagcompound) { ++ this.lootableData.loadNbt(nbttagcompound); // Paper + if (nbttagcompound.contains("LootTable", 8)) { + this.lootTable = new ResourceLocation(nbttagcompound.getString("LootTable")); ++ try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate + this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); +- return true; ++ return false; // Paper - always load the items, table may still remain + } else { + return false; + } + } + + protected boolean trySaveLootTable(CompoundTag nbttagcompound) { ++ this.lootableData.saveNbt(nbttagcompound); // Paper + if (this.lootTable == null) { + return false; + } else { +@@ -60,19 +64,20 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + nbttagcompound.putLong("LootTableSeed", this.lootTableSeed); + } + +- return true; ++ return false; // Paper - always save the items, table may still remain + } + } + + public void unpackLootTable(@Nullable Player player) { +- if (this.lootTable != null && this.level.getServer() != null) { ++ if (this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper + LootTable loottable = this.level.getServer().getLootTables().get(this.lootTable); + + if (player instanceof ServerPlayer) { + CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer) player, this.lootTable); + } + +- this.lootTable = null; ++ //this.lootTable = null; // Paper ++ this.lootableData.processRefill(player); // Paper + LootContext.Builder loottableinfo_builder = (new LootContext.Builder((ServerLevel) this.level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf((Vec3i) this.worldPosition)).withOptionalRandomSeed(this.lootTableSeed); + + if (player != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +index 1e2e94b0cd2ede8fb7ae5902dcd0b639bd8dcf52..e89a93082fe07fdb14df8ffef5beca5bd52d7866 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +@@ -64,7 +64,7 @@ public class CraftBlockEntityState extends CraftBlockStat + } + + // gets the wrapped TileEntity +- protected T getTileEntity() { ++ public T getTileEntity() { // Paper - protected -> public + return tileEntity; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +index 20d9a192ff102e04687a8aa3eff1ba36a69b6c03..a821df3e13e2ddc479dc5f55540671f43563cdac 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +@@ -12,8 +12,9 @@ import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.inventory.CraftInventory; + import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest; + import org.bukkit.inventory.Inventory; ++import com.destroystokyo.paper.loottable.PaperLootableBlockInventory; // Paper + +-public class CraftChest extends CraftLootable implements Chest { ++public class CraftChest extends CraftLootable implements Chest, PaperLootableBlockInventory { // Paper + + public CraftChest(final Block block) { + super(block, ChestBlockEntity.class); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java +index 309650aad43d8b6ce4bb13f8c172028f3feab299..5babbcfcacb89e62f00f8184af2ceea227f9ff69 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java +@@ -10,7 +10,7 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; + import org.bukkit.loot.LootTable; + import org.bukkit.loot.Lootable; + +-public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable { ++public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable, com.destroystokyo.paper.loottable.PaperLootableBlockInventory { // Paper + + public CraftLootable(Block block, Class tileEntityClass) { + super(block, tileEntityClass); +@@ -54,7 +54,7 @@ public abstract class CraftLootable + setLootTable(getLootTable(), seed); + } + +- private void setLootTable(LootTable table, long seed) { ++ public void setLootTable(LootTable table, long seed) { // Paper - public + ResourceLocation key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); + getSnapshot().setLootTable(key, seed); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java +index f0a30acb0199e396d6863a473db433cbe112d8a5..293b222565d8e0592f9f355a2ee8cdfbc868a08e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java +@@ -8,7 +8,7 @@ import org.bukkit.entity.minecart.StorageMinecart; + import org.bukkit.inventory.Inventory; + + @SuppressWarnings("deprecation") +-public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart { ++public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper + private final CraftInventory inventory; + + public CraftMinecartChest(CraftServer server, MinecartChest entity) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java +index 12044062cb746bd5c77abacf8acddc67e08e78ce..ce14bc4791bd282d16af0ee91fc431acefa3b909 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java +@@ -47,7 +47,7 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo + return getHandle().lootTableSeed; + } + +- private void setLootTable(LootTable table, long seed) { ++ public void setLootTable(LootTable table, long seed) { // Paper + ResourceLocation newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); + getHandle().setLootTable(newKey, seed); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +index c1af739369715d8c628c466b269fdde99a2f6286..c8c5f60b6b32248696363d9b63bbbe43810743d3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +@@ -7,7 +7,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.minecart.HopperMinecart; + import org.bukkit.inventory.Inventory; + +-public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart { ++public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper + private final CraftInventory inventory; + + public CraftMinecartHopper(CraftServer server, MinecartHopper entity) { diff --git a/patches/server-remapped/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/patches/server-remapped/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch new file mode 100644 index 0000000000..f9fbbc4e75 --- /dev/null +++ b/patches/server-remapped/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 May 2016 23:33:08 -0400 +Subject: [PATCH] Don't save empty scoreboard teams to scoreboard.dat + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 504efea7b6f50a0d17f4f353781953dfb18bdeca..1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -237,4 +237,9 @@ public class PaperConfig { + private static void enablePlayerCollisions() { + enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); + } ++ ++ public static boolean saveEmptyScoreboardTeams = false; ++ private static void saveEmptyScoreboardTeams() { ++ saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java +index 36a922029687b9fa3ca3a986ae42a373ced87a0e..b9e14d1c54b690f0b975bda5733c4cb4f6449f77 100644 +--- a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java ++++ b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java +@@ -182,6 +182,7 @@ public class ScoreboardSaveData extends SavedData { + + while (iterator.hasNext()) { + PlayerTeam scoreboardteam = (PlayerTeam) iterator.next(); ++ if (!com.destroystokyo.paper.PaperConfig.saveEmptyScoreboardTeams && scoreboardteam.getPlayers().isEmpty()) continue; // Paper + CompoundTag nbttagcompound = new CompoundTag(); + + nbttagcompound.putString("Name", scoreboardteam.getName()); diff --git a/patches/server-remapped/0098-System-property-for-disabling-watchdoge.patch b/patches/server-remapped/0098-System-property-for-disabling-watchdoge.patch new file mode 100644 index 0000000000..d8a22a7f5f --- /dev/null +++ b/patches/server-remapped/0098-System-property-for-disabling-watchdoge.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 12 May 2016 23:02:58 -0500 +Subject: [PATCH] System property for disabling watchdoge + + +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 0ed95268364ea7f6a92a39b726a1e03bc815be07..ee0cca25ef458f2f0f7e450a2edea2b2adb7e846 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -61,7 +61,7 @@ public class WatchdogThread extends Thread + while ( !stopping ) + { + // +- if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime ) ++ if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable + { + Logger log = Bukkit.getServer().getLogger(); + log.log( Level.SEVERE, "------------------------------" ); diff --git a/patches/server-remapped/0099-Optimize-UserCache-Thread-Safe.patch b/patches/server-remapped/0099-Optimize-UserCache-Thread-Safe.patch new file mode 100644 index 0000000000..4b08a22748 --- /dev/null +++ b/patches/server-remapped/0099-Optimize-UserCache-Thread-Safe.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 16 May 2016 20:47:41 -0400 +Subject: [PATCH] Optimize UserCache / Thread Safe + +Because Techable keeps complaining about how this isn't thread safe, +easier to do this than replace the entire thing. + +Additionally, move Saving of the User cache to be done async, incase +the user never changed the default setting for Spigot's save on stop only. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 4e468cb7ccf683b8fc9e04a48cfc25779775e25f..211251fe7cd08074c040df2f4642f37d5f90d856 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -905,7 +905,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Paper + + try { + BufferedWriter bufferedwriter = Files.newWriter(this.file, StandardCharsets.UTF_8); +@@ -268,6 +270,14 @@ public class GameProfileCache { + } catch (IOException ioexception) { + ; + } ++ // Paper start ++ }; ++ if (asyncSave) { ++ MCUtil.scheduleAsyncTask(save); ++ } else { ++ save.run(); ++ } ++ // Paper end + + } + diff --git a/patches/server-remapped/0100-Avoid-blocking-on-Network-Manager-creation.patch b/patches/server-remapped/0100-Avoid-blocking-on-Network-Manager-creation.patch new file mode 100644 index 0000000000..ba69589d2f --- /dev/null +++ b/patches/server-remapped/0100-Avoid-blocking-on-Network-Manager-creation.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 16 May 2016 23:19:16 -0400 +Subject: [PATCH] Avoid blocking on Network Manager creation + +Per Paper issue 294 + +diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +index 9680b0b3879c72776d6225a6a5a89fdfa3520598..6cb51a4fe3c11f53fbb556ce6b0d64b735254d51 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +@@ -52,6 +52,15 @@ public class ServerConnectionListener { + public volatile boolean running; + private final List channels = Collections.synchronizedList(Lists.newArrayList()); + private final List connections = Collections.synchronizedList(Lists.newArrayList()); ++ // Paper start - prevent blocking on adding a new network manager while the server is ticking ++ private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ private void addPending() { ++ Connection manager = null; ++ while ((manager = pending.poll()) != null) { ++ connections.add(manager); ++ } ++ } ++ // Paper end + + public ServerConnectionListener(MinecraftServer server) { + this.server = server; +@@ -87,7 +96,8 @@ public class ServerConnectionListener { + int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); + Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); + +- ServerConnectionListener.this.connections.add((Connection) object); // CraftBukkit - decompile error ++ //ServerConnection.this.connectedChannels.add((NetworkManager) object); // CraftBukkit - decompile error ++ pending.add((Connection) object); // Paper + channel.pipeline().addLast("packet_handler", (ChannelHandler) object); + ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); + } +@@ -126,6 +136,7 @@ public class ServerConnectionListener { + + synchronized (this.connections) { + // Spigot Start ++ this.addPending(); // Paper + // This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order + if ( org.spigotmc.SpigotConfig.playerShuffle > 0 && MinecraftServer.currentTick % org.spigotmc.SpigotConfig.playerShuffle == 0 ) + { diff --git a/patches/server-remapped/0101-Optional-TNT-doesn-t-move-in-water.patch b/patches/server-remapped/0101-Optional-TNT-doesn-t-move-in-water.patch new file mode 100644 index 0000000000..cd8e56460f --- /dev/null +++ b/patches/server-remapped/0101-Optional-TNT-doesn-t-move-in-water.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 22 May 2016 20:20:55 -0500 +Subject: [PATCH] Optional TNT doesn't move in water + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index eb04fdb172a50ec1f5b7fe78fa0e7655246abd60..6eca3f300020006f02dd36253b522db442e3cc33 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -2,7 +2,6 @@ package com.destroystokyo.paper; + + import java.util.List; + +-import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; + +@@ -291,4 +290,14 @@ public class PaperWorldConfig { + ); + } + } ++ ++ public boolean preventTntFromMovingInWater; ++ private void preventTntFromMovingInWater() { ++ if (PaperConfig.version < 13) { ++ boolean oldVal = getBoolean("enable-old-tnt-cannon-behaviors", false); ++ set("prevent-tnt-from-moving-in-water", oldVal); ++ } ++ preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); ++ log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index fa6893055fa5617742bfb4b7eff60c8139395cb6..49c71b21b6b88bc41ca6ddf4c76186ce522ee456 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -66,7 +66,7 @@ public class ServerEntity { + private boolean wasRiding; + private boolean wasOnGround; + // CraftBukkit start +- private final Set trackedPlayers; ++ final Set trackedPlayers; // Paper - private -> package + // Paper start + private java.util.Map trackedPlayerMap = null; + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 171697e88f5a4d8c0be2a47b67b865bbdc4dfe8c..c3aece8e5001828edea304b2a8377e9a28b34cfe 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2770,6 +2770,11 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean isPushedByFluid() { ++ // Paper start ++ return this.pushedByWater(); ++ } ++ public boolean pushedByWater() { ++ // Paper end + return true; + } + +diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +index 661848084fd986321ef782317934dac19ed4dce3..347ac17643de8bcb0c8496c2ea5eb18c2e4d856b 100644 +--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +@@ -5,9 +5,13 @@ import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; ++import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; ++import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; +@@ -95,7 +99,27 @@ public class PrimedTnt extends Entity { + this.level.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D); + } + } +- ++ // Paper start - Optional prevent TNT from moving in water ++ if (!this.removed && this.wasTouchingWater && this.level.paperConfig.preventTntFromMovingInWater) { ++ /* ++ * Author: Jedediah Smith ++ */ ++ // Send position and velocity updates to nearby players on every tick while the TNT is in water. ++ // This does pretty well at keeping their clients in sync with the server. ++ ChunkMap.TrackedEntity ete = ((ServerLevel)this.level).getChunkSource().chunkMap.entityMap.get(this.getId()); ++ if (ete != null) { ++ ClientboundSetEntityMotionPacket velocityPacket = new ClientboundSetEntityMotionPacket(this); ++ ClientboundTeleportEntityPacket positionPacket = new ClientboundTeleportEntityPacket(this); ++ ++ ete.seenBy.stream() ++ .filter(viewer -> (viewer.getX() - this.getX()) * (viewer.getY() - this.getY()) * (viewer.getZ() - this.getZ()) < 16 * 16) ++ .forEach(viewer -> { ++ viewer.connection.send(velocityPacket); ++ viewer.connection.send(positionPacket); ++ }); ++ } ++ } ++ // Paper end + } + + private void explode() { +@@ -164,4 +188,11 @@ public class PrimedTnt extends Entity { + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this); + } ++ ++ // Paper start - Optional prevent TNT from moving in water ++ @Override ++ public boolean pushedByWater() { ++ return !level.paperConfig.preventTntFromMovingInWater && super.pushedByWater(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0102-Faster-redstone-torch-rapid-clock-removal.patch b/patches/server-remapped/0102-Faster-redstone-torch-rapid-clock-removal.patch new file mode 100644 index 0000000000..cc437e7353 --- /dev/null +++ b/patches/server-remapped/0102-Faster-redstone-torch-rapid-clock-removal.patch @@ -0,0 +1,98 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Panzer +Date: Mon, 23 May 2016 12:12:37 +0200 +Subject: [PATCH] Faster redstone torch rapid clock removal + +Only resize the the redstone torch list once, since resizing arrays / lists is costly + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 8f0fec38b482465285057d3fd27d456cf036f2fd..5f3d17cb247156fc8aaa7a763e402c2bbb42a7ec 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -48,6 +48,7 @@ import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.RedstoneTorchBlock; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.TickableBlockEntity; +@@ -142,6 +143,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + private org.spigotmc.TickLimiter tileLimiter; + private int tileTickPosition; + public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions ++ public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here + + public CraftWorld getWorld() { + return this.world; +diff --git a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java +index 7d71c99c2268174fbea4297f028b75a3a0f43c11..dd4391086aff05bdea81e62b950b88cfab5ac6b8 100644 +--- a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java +@@ -21,7 +21,7 @@ import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + public class RedstoneTorchBlock extends TorchBlock { + + public static final BooleanProperty LIT = BlockStateProperties.LIT; +- private static final Map> RECENT_TOGGLES = new WeakHashMap(); ++ // Paper - Move the mapped list to World + + protected RedstoneTorchBlock(BlockBehaviour.Properties settings) { + super(settings, DustParticleOptions.REDSTONE); +@@ -68,11 +68,15 @@ public class RedstoneTorchBlock extends TorchBlock { + @Override + public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) { + boolean flag = this.hasNeighborSignal((Level) world, pos, state); +- List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.get(world); +- +- while (list != null && !list.isEmpty() && world.getGameTime() - ((RedstoneTorchBlock.Toggle) list.get(0)).when > 60L) { +- list.remove(0); ++ // Paper start ++ java.util.ArrayDeque redstoneUpdateInfos = world.redstoneUpdateInfos; ++ if (redstoneUpdateInfos != null) { ++ RedstoneTorchBlock.Toggle curr; ++ while ((curr = redstoneUpdateInfos.peek()) != null && world.getGameTime() - curr.getTime() > 60L) { ++ redstoneUpdateInfos.poll(); ++ } + } ++ // Paper end + + // CraftBukkit start + org.bukkit.plugin.PluginManager manager = world.getCraftServer().getPluginManager(); +@@ -137,9 +141,12 @@ public class RedstoneTorchBlock extends TorchBlock { + } + + private static boolean isToggledTooFrequently(Level world, BlockPos pos, boolean addNew) { +- List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.computeIfAbsent(world, (iblockaccess) -> { +- return Lists.newArrayList(); +- }); ++ // Paper start ++ java.util.ArrayDeque list = world.redstoneUpdateInfos; ++ if (list == null) { ++ list = world.redstoneUpdateInfos = new java.util.ArrayDeque<>(); ++ } ++ + + if (addNew) { + list.add(new RedstoneTorchBlock.Toggle(pos.immutable(), world.getGameTime())); +@@ -147,9 +154,9 @@ public class RedstoneTorchBlock extends TorchBlock { + + int i = 0; + +- for (int j = 0; j < list.size(); ++j) { +- RedstoneTorchBlock.Toggle blockredstonetorch_redstoneupdateinfo = (RedstoneTorchBlock.Toggle) list.get(j); +- ++ for (java.util.Iterator iterator = list.iterator(); iterator.hasNext();) { ++ RedstoneTorchBlock.Toggle blockredstonetorch_redstoneupdateinfo = iterator.next(); ++ // Paper end + if (blockredstonetorch_redstoneupdateinfo.pos.equals(pos)) { + ++i; + if (i >= 8) { +@@ -164,7 +171,7 @@ public class RedstoneTorchBlock extends TorchBlock { + public static class Toggle { + + private final BlockPos pos; +- private final long when; ++ private final long when; final long getTime() { return this.when; } // Paper - OBFHELPER + + public Toggle(BlockPos pos, long time) { + this.pos = pos; diff --git a/patches/server-remapped/0103-Add-server-name-parameter.patch b/patches/server-remapped/0103-Add-server-name-parameter.patch new file mode 100644 index 0000000000..50ec621547 --- /dev/null +++ b/patches/server-remapped/0103-Add-server-name-parameter.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Panzer +Date: Sat, 28 May 2016 16:54:03 +0200 +Subject: [PATCH] Add server-name parameter + + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2..b849b2afd009da433fe6cea5837b3ee9bb5c52b4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -143,6 +143,14 @@ public class Main { + .defaultsTo(new File("paper.yml")) + .describedAs("Yml file"); + // Paper end ++ ++ // Paper start ++ acceptsAll(asList("server-name"), "Name of the server") ++ .withRequiredArg() ++ .ofType(String.class) ++ .defaultsTo("Unknown Server") ++ .describedAs("Name"); ++ // Paper end + } + }; + diff --git a/patches/server-remapped/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/patches/server-remapped/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch new file mode 100644 index 0000000000..e84fc6a07e --- /dev/null +++ b/patches/server-remapped/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 31 May 2016 22:53:50 -0400 +Subject: [PATCH] Only send Dragon/Wither Death sounds to same world + +Also fix view distance lookup + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index 8d1b3cbb21fe798c27ad2d39bccffa9cc983cf96..39298b69918da890c3faa516f80d1a69adb88fe2 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -619,8 +619,9 @@ public class EnderDragon extends Mob implements Enemy { + if (this.dragonDeathTime == 1 && !this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1028, this.getChunkCoordinates(), 0); +- int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; +- for (net.minecraft.server.level.ServerPlayer player : this.level.getServer().getPlayerList().players) { ++ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ for (net.minecraft.server.level.ServerPlayer player : (List) ((ServerLevel)level).players()) { ++ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch + double deltaX = this.getX() - player.getX(); + double deltaZ = this.getZ() - player.getZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +index 61c982ead18334a29438ef8e024d97ead178a2c8..3a80869dc3c16cb81ac87100f28d63eee722067f 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -46,7 +46,6 @@ import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerBossEvent; +-import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; +@@ -256,8 +255,9 @@ public class WitherBoss extends Monster implements RangedAttackMob { + if (!this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1023, new BlockPosition(this), 0); +- int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; +- for (ServerPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { ++ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ for (ServerPlayer player : (List)this.level.players()) { ++ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch + double deltaX = this.getX() - player.getX(); + double deltaZ = this.getZ() - player.getZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; diff --git a/patches/server-remapped/0105-Fix-Double-World-Add-issues.patch b/patches/server-remapped/0105-Fix-Double-World-Add-issues.patch new file mode 100644 index 0000000000..b412753ddd --- /dev/null +++ b/patches/server-remapped/0105-Fix-Double-World-Add-issues.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 21 Jun 2016 22:54:34 -0400 +Subject: [PATCH] Fix Double World Add issues + +Vanilla will double add Spider Jockeys to the world, so ignore already added. + +Also add debug if something else tries to, and abort before world gets bad state + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0a613f94d1c796267636e1a343aeee65a49ffed5..335928d60dbfc07644ffeab366900c5e77e99d56 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1032,6 +1032,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // CraftBukkit start + private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot ++ if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper + if (entity.removed) { + // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit + return false; diff --git a/patches/server-remapped/0106-Fix-Old-Sign-Conversion.patch b/patches/server-remapped/0106-Fix-Old-Sign-Conversion.patch new file mode 100644 index 0000000000..d08b9cb8ca --- /dev/null +++ b/patches/server-remapped/0106-Fix-Old-Sign-Conversion.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 17 Jun 2016 20:50:11 -0400 +Subject: [PATCH] Fix Old Sign Conversion + +1) Sign loading code was trying to parse the JSON before the check for oldSign. + That code could then skip the old sign converting code if it triggers a JSON parse exception. +2) New Mojang Schematic system has Tile Entities in the new converted format, but missing the Bukkit.isConverted flag + This causes Igloos and such to render broken signs. We fix this by ignoring sign conversion for Defined Structures + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 13115d1b28dfa2d87b45a50bd0feaa7f57769122..d08ed44884726ca2ba4578226b8aa6244778f4c7 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -34,6 +34,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + public CraftPersistentDataContainer persistentDataContainer; + // CraftBukkit end + private static final Logger LOGGER = LogManager.getLogger(); ++ public boolean isLoadingStructure = false; // Paper + private final BlockEntityType type; public BlockEntityType getTileEntityType() { return type; } // Paper - OBFHELPER + @Nullable + protected Level level; +diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +index e747f729326fb3bacfb3f983ac7701c0fb0f0e6a..e4eab82855649fec654c60b2e94ba7b71c2ac5a2 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -78,13 +78,14 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + } + + try { +- MutableComponent ichatmutablecomponent = Component.Serializer.fromJson(s.isEmpty() ? "\"\"" : s); ++ //IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); // Paper - move down - the old format might throw a json error + +- if (oldSign) { ++ if (oldSign && !isLoadingStructure) { // Paper - saved structures will be in the new format, but will not have isConverted + messages[i] = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s)[0]; + continue; + } + // CraftBukkit end ++ MutableComponent ichatmutablecomponent = Component.Serializer.fromJson(s.isEmpty() ? "\"\"" : s); // Paper - after old sign + + if (this.level instanceof ServerLevel) { + try { +diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java +index 8da00ee410e3f8f09b8ac273095a3d22d6c4d92b..d4cf5d3bdbe629081f6ec9d4ea94004560c93ebc 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java +@@ -278,9 +278,11 @@ public class StructureTemplate { + definedstructure_blockinfo.nbt.putLong("LootTableSeed", random.nextLong()); + } + ++ tileentity.isLoadingStructure = true; // Paper + tileentity.load(definedstructure_blockinfo.state, definedstructure_blockinfo.nbt); + tileentity.mirror(placementData.getMirror()); + tileentity.rotate(placementData.getRotation()); ++ tileentity.isLoadingStructure = false; // Paper + } + } + diff --git a/patches/server-remapped/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/patches/server-remapped/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch new file mode 100644 index 0000000000..51ddf3745d --- /dev/null +++ b/patches/server-remapped/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 16 Jul 2016 19:11:17 -0500 +Subject: [PATCH] Don't lookup game profiles that have no UUID and no name + + +diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java +index 9342fa6b28e805743b8e3a13007605934244d6cd..f3e05fac1b5248ca4ee2cac03263e96c166ed343 100644 +--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java ++++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +@@ -92,7 +92,7 @@ public class GameProfileCache { + repository.findProfilesByNames(new String[]{name}, Agent.MINECRAFT, profilelookupcallback); + GameProfile gameprofile = (GameProfile) atomicreference.get(); + +- if (!usesAuthentication() && gameprofile == null) { ++ if (!usesAuthentication() && gameprofile == null && !org.apache.commons.lang3.StringUtils.isBlank(name)) { // Paper - Don't lookup a profile with a blank name + UUID uuid = Player.createPlayerUUID(new GameProfile((UUID) null, name)); + + gameprofile = new GameProfile(uuid, name); diff --git a/patches/server-remapped/0108-Add-setting-for-proxy-online-mode-status.patch b/patches/server-remapped/0108-Add-setting-for-proxy-online-mode-status.patch new file mode 100644 index 0000000000..067e04850c --- /dev/null +++ b/patches/server-remapped/0108-Add-setting-for-proxy-online-mode-status.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gabriele C +Date: Fri, 5 Aug 2016 01:03:08 +0200 +Subject: [PATCH] Add setting for proxy online mode status + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2..c52dc0346f93527965ef29a0ccdc4bf3debe302e 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -23,6 +23,7 @@ import org.bukkit.configuration.InvalidConfigurationException; + import org.bukkit.configuration.file.YamlConfiguration; + import co.aikar.timings.Timings; + import co.aikar.timings.TimingsManager; ++import org.spigotmc.SpigotConfig; + + public class PaperConfig { + +@@ -242,4 +243,13 @@ public class PaperConfig { + private static void saveEmptyScoreboardTeams() { + saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); + } ++ ++ public static boolean bungeeOnlineMode = true; ++ private static void bungeeOnlineMode() { ++ bungeeOnlineMode = getBoolean("settings.bungee-online-mode", true); ++ } ++ ++ public static boolean isProxyOnlineMode() { ++ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); ++ } + } +diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java +index f3e05fac1b5248ca4ee2cac03263e96c166ed343..e8af352f813a5015d216fc590190ae8fdb03f77d 100644 +--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java ++++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +@@ -89,6 +89,7 @@ public class GameProfileCache { + } + }; + ++ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) // Paper - only run in online mode - 100 COL + repository.findProfilesByNames(new String[]{name}, Agent.MINECRAFT, profilelookupcallback); + GameProfile gameprofile = (GameProfile) atomicreference.get(); + +@@ -106,7 +107,7 @@ public class GameProfileCache { + } + + private static boolean usesAuthentication() { +- return GameProfileCache.usesAuthentication; ++ return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper + } + + public synchronized void add(GameProfile gameprofile) { // Paper - synchronize +diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java +index 09c5fa2dbcbed05da51ef2d63e6d6112d22d7877..e6a26c274616947329a6164e4648486452819b0c 100644 +--- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java ++++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java +@@ -63,7 +63,8 @@ public class OldUsersConverter { + return new String[i]; + }); + +- if (server.usesAuthentication() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. ++ if (server.usesAuthentication() ++ || (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode())) { // Spigot: bungee = online mode, for now. // Paper - Handle via setting + server.getProfileRepository().findProfilesByNames(astring, Agent.MINECRAFT, callback); + } else { + String[] astring1 = astring; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 2828936fe294d9d6750a8838da49ec8398835214..bbe0978f56d23b7defce765d381d4a7c20acd75c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1515,7 +1515,8 @@ public final class CraftServer implements Server { + // Spigot Start + GameProfile profile = null; + // Only fetch an online UUID in online mode +- if ( getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) ++ if ( getOnlineMode() ++ || com.destroystokyo.paper.PaperConfig.isProxyOnlineMode() ) // Paper - Handle via setting + { + profile = console.getProfileCache().get( name ); + } diff --git a/patches/server-remapped/0109-Optimise-BlockState-s-hashCode-equals.patch b/patches/server-remapped/0109-Optimise-BlockState-s-hashCode-equals.patch new file mode 100644 index 0000000000..6e9e140dc2 --- /dev/null +++ b/patches/server-remapped/0109-Optimise-BlockState-s-hashCode-equals.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Fri, 19 Aug 2016 01:52:56 +0100 +Subject: [PATCH] Optimise BlockState's hashCode/equals + +These are singleton "single instance" objects. We can rely on +object identity checks safely. + +Use a simpler optimized hashcode + +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java +index c5af36a0279d1e1c951e6f9b34857b0aa934f940..62f11a02e3f5c07e838f425cffb0a28b6d2bc138 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java +@@ -30,8 +30,7 @@ public class BooleanProperty extends Property { + return value.toString(); + } + +- @Override +- public boolean equals(Object object) { ++ public boolean equals_unused(Object object) { // Paper + if (this == object) { + return true; + } else if (object instanceof BooleanProperty && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +index b5817645727f2af2785e0987ba824f431d4e9e32..2fdfd7d2470ee9f1a96eda7418b104c960df8460 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +@@ -50,8 +50,7 @@ public class EnumProperty & StringRepresentable> extends Prope + return ((StringRepresentable) value).getSerializedName(); + } + +- @Override +- public boolean equals(Object object) { ++ public boolean equals_unused(Object object) { // Paper + if (this == object) { + return true; + } else if (object instanceof EnumProperty && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java +index c3ec7f91794d802e5b9ddac3fffccce378dace68..72f508321ebffcca31240fbdd068b4d185454cbc 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java +@@ -38,8 +38,7 @@ public class IntegerProperty extends Property { + return this.values; + } + +- @Override +- public boolean equals(Object object) { ++ public boolean equals_unused(Object object) { // Paper + if (this == object) { + return true; + } else if (object instanceof IntegerProperty && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java +index 8cc07c70fde81e44679f3ea7d9a4c6b2447885d4..80f8966ac56e8af4a6c7aa86b2d8dd0f319c7b5d 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java +@@ -60,23 +60,17 @@ public abstract class Property> { + } + + public boolean equals(Object object) { +- if (this == object) { +- return true; +- } else if (!(object instanceof Property)) { +- return false; +- } else { +- Property iblockstate = (Property) object; +- +- return this.clazz.equals(iblockstate.clazz) && this.name.equals(iblockstate.name); +- } ++ return this == object; // Paper - only one instance per configuration + } + ++ private static final java.util.concurrent.atomic.AtomicInteger hashId = new java.util.concurrent.atomic.AtomicInteger(1); // Paper - only one instance per configuration ++ private final int hashCode = 92821 * hashId.getAndIncrement(); // Paper - only one instance per configuration + public final int hashCode() { + if (this.hashCode == null) { + this.hashCode = this.generateHashCode(); + } + +- return this.hashCode; ++ return this.hashCode; // Paper - only one instance per configuration + } + + public int generateHashCode() { diff --git a/patches/server-remapped/0110-Configurable-packet-in-spam-threshold.patch b/patches/server-remapped/0110-Configurable-packet-in-spam-threshold.patch new file mode 100644 index 0000000000..bce5b61b0d --- /dev/null +++ b/patches/server-remapped/0110-Configurable-packet-in-spam-threshold.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 11 Sep 2016 14:30:57 -0500 +Subject: [PATCH] Configurable packet in spam threshold + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index c52dc0346f93527965ef29a0ccdc4bf3debe302e..64d7c9058ee757a6d3cf3b648596092a810e105c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -252,4 +252,13 @@ public class PaperConfig { + public static boolean isProxyOnlineMode() { + return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); + } ++ ++ public static int packetInSpamThreshold = 300; ++ private static void packetInSpamThreshold() { ++ if (version < 11) { ++ int oldValue = getInt("settings.play-in-use-item-spam-threshold", 300); ++ set("settings.incoming-packet-spam-threshold", oldValue); ++ } ++ packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index e2bfe8e916c9e59af81627ea0ee449970527034d..d6f4ccf06c919410e13409433bdfc3aa88a21c30 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1463,13 +1463,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // Spigot start - limit place/interactions + private int limitedPackets; + private long lastLimitedPacket = -1; ++ private static final int THRESHOLD = com.destroystokyo.paper.PaperConfig.packetInSpamThreshold; // Paper - Configurable threshold + + private boolean checkLimit(long timestamp) { +- if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < 30 && limitedPackets++ >= 4) { ++ if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < THRESHOLD && limitedPackets++ >= 8) { // Paper - Use threshold, raise packet limit to 8 + return false; + } + +- if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= 30) { ++ if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= THRESHOLD) { // Paper + lastLimitedPacket = timestamp; + limitedPackets = 0; + return true; diff --git a/patches/server-remapped/0111-Configurable-flying-kick-messages.patch b/patches/server-remapped/0111-Configurable-flying-kick-messages.patch new file mode 100644 index 0000000000..fc05cbc991 --- /dev/null +++ b/patches/server-remapped/0111-Configurable-flying-kick-messages.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Tue, 20 Sep 2016 00:58:01 +0000 +Subject: [PATCH] Configurable flying kick messages + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 64d7c9058ee757a6d3cf3b648596092a810e105c..4e2f243faa209925dcb7c3ef89df3ed875c5ff78 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -261,4 +261,11 @@ public class PaperConfig { + } + packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); + } ++ ++ public static String flyingKickPlayerMessage = "Flying is not enabled on this server"; ++ public static String flyingKickVehicleMessage = "Flying is not enabled on this server"; ++ private static void flyingKickMessages() { ++ flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); ++ flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index d6f4ccf06c919410e13409433bdfc3aa88a21c30..1b92c669bbe69bcc07a554b7b43ee99bfebc1af4 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -305,7 +305,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + if (this.clientIsFloating && !this.player.isSleeping()) { + if (++this.aboveGroundTickCount > 80) { + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.flying")); ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message + return; + } + } else { +@@ -324,7 +324,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) { + if (++this.aboveGroundVehicleTickCount > 80) { + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.flying")); ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message + return; + } + } else { diff --git a/patches/server-remapped/0112-Chunk-registration-fixes.patch b/patches/server-remapped/0112-Chunk-registration-fixes.patch new file mode 100644 index 0000000000..4d2da1cd83 --- /dev/null +++ b/patches/server-remapped/0112-Chunk-registration-fixes.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Sep 2016 22:54:28 -0400 +Subject: [PATCH] Chunk registration fixes + +World checks and the Chunk Add logic are inconsistent on how Y > 256, < 0, is treated + +Keep them consistent + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 335928d60dbfc07644ffeab366900c5e77e99d56..20650bfd10abfa010e71cfeede06c461d50d19a3 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -841,7 +841,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (entity.checkAndResetUpdateChunkPos()) { + this.getProfiler().push("chunkCheck"); + int i = Mth.floor(entity.getX() / 16.0D); +- int j = Mth.floor(entity.getY() / 16.0D); ++ int j = Math.min(15, Math.max(0, Mth.floor(entity.getY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior + int k = Mth.floor(entity.getZ() / 16.0D); + + if (!entity.inChunk || entity.xChunk != i || entity.yChunk != j || entity.zChunk != k) { diff --git a/patches/server-remapped/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/patches/server-remapped/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch new file mode 100644 index 0000000000..0d1bb6c9bb --- /dev/null +++ b/patches/server-remapped/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 16 Jun 2016 00:17:23 -0400 +Subject: [PATCH] Remove FishingHook reference on Craft Entity removal + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java +index 5668facc5bf5c56581c3ebd268f832d77ce5c05b..50322cfc07a7d93c32461faeb5e22e35ceead323 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java +@@ -119,4 +119,14 @@ public class CraftFishHook extends CraftProjectile implements FishHook { + public HookState getState() { + return HookState.values()[getHandle().currentState.ordinal()]; + } ++ ++ // Paper start ++ @Override ++ public void remove() { ++ super.remove(); ++ if (getHandle().getPlayerOwner() != null) { ++ getHandle().getPlayerOwner().fishing = null; ++ } ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0114-Auto-fix-bad-Y-levels-on-player-login.patch b/patches/server-remapped/0114-Auto-fix-bad-Y-levels-on-player-login.patch new file mode 100644 index 0000000000..a6a274fc00 --- /dev/null +++ b/patches/server-remapped/0114-Auto-fix-bad-Y-levels-on-player-login.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Sep 2016 23:48:39 -0400 +Subject: [PATCH] Auto fix bad Y levels on player login + +Bring down to a saner Y level if super high, as this can cause the server to crash + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index bd3d9182dfb2c0ae1d8c3b9aa360f94c33252592..3a2356b3e00098d100a179a05316f402390d4e9b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -337,6 +337,7 @@ public class ServerPlayer extends Player implements ContainerListener { + @Override + public void readAdditionalSaveData(CompoundTag tag) { + super.readAdditionalSaveData(tag); ++ if (this.getY() > 300) this.setPosRaw(getX(), 257, getZ()); // Paper - bring down to a saner Y level if out of world + if (tag.contains("playerGameType", 99)) { + if (this.getServer().getForceGameType()) { + this.gameMode.setGameModeForPlayer(this.getServer().getDefaultGameType(), GameType.NOT_SET); diff --git a/patches/server-remapped/0115-Option-to-remove-corrupt-tile-entities.patch b/patches/server-remapped/0115-Option-to-remove-corrupt-tile-entities.patch new file mode 100644 index 0000000000..d6b80297c0 --- /dev/null +++ b/patches/server-remapped/0115-Option-to-remove-corrupt-tile-entities.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 5 Oct 2016 16:27:36 -0500 +Subject: [PATCH] Option to remove corrupt tile entities + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6eca3f300020006f02dd36253b522db442e3cc33..622affa0dc3cc1eadaed400511f2ca2cde3fca2a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -300,4 +300,9 @@ public class PaperWorldConfig { + preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); + log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); + } ++ ++ public boolean removeCorruptTEs = false; ++ private void removeCorruptTEs() { ++ removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 70f5b025c2b803df3de8a51cbcfafbe915866f42..d69ccb1f31f31ebeee477df20ce1410f9e485eb7 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -678,6 +678,12 @@ public class LevelChunk implements ChunkAccess { + "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); + e.printStackTrace(); + ServerInternalException.reportInternalException(e); ++ ++ if (this.world.paperConfig.removeCorruptTEs) { ++ this.removeBlockEntity(blockEntity.getBlockPos()); ++ this.markUnsaved(); ++ org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); ++ } + // Paper end + // CraftBukkit end + } diff --git a/patches/server-remapped/0116-Add-EntityZapEvent.patch b/patches/server-remapped/0116-Add-EntityZapEvent.patch new file mode 100644 index 0000000000..20a798bf8d --- /dev/null +++ b/patches/server-remapped/0116-Add-EntityZapEvent.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaBlend +Date: Sun, 16 Oct 2016 23:19:30 -0700 +Subject: [PATCH] Add EntityZapEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.java +index 6ecf7afe5fd7c4c95a17eaed1445d034aa2d5f18..e512a38ccbba93266f0234e3b2fcf7f62693039b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Pig.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java +@@ -254,6 +254,11 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { + } + + entitypigzombie.setPersistenceRequired(); ++ // Paper start ++ if (CraftEventFactory.callEntityZapEvent(this, lightning, entitypigzombie).isCancelled()) { ++ return; ++ } ++ // Paper end + // CraftBukkit start + if (CraftEventFactory.callPigZapEvent(this, lightning, entitypigzombie).isCancelled()) { + return; +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 2f99bdaabe1c1a6a4e1a7e2bd533a63b12818be1..5648a4a4d8511ac8c46c61245a7ff83753a3e51f 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -786,6 +786,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); + Witch entitywitch = (Witch) EntityType.WITCH.create((Level) world); + ++ // Paper start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, lightning, entitywitch).isCancelled()) { ++ return; ++ } ++ // Paper end ++ + entitywitch.moveTo(this.getX(), this.getY(), this.getZ(), this.yRot, this.xRot); + entitywitch.finalizeSpawn(world, world.getCurrentDifficultyAt(entitywitch.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null, (CompoundTag) 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 7fde1bb7587e567270e3f936381c6d361870211f..81af3e2e0964b6e179f92a342efdae943be18b75 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1086,6 +1086,14 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start ++ public static com.destroystokyo.paper.event.entity.EntityZapEvent callEntityZapEvent (Entity entity, Entity lightning, Entity changedEntity) { ++ com.destroystokyo.paper.event.entity.EntityZapEvent event = new com.destroystokyo.paper.event.entity.EntityZapEvent(entity.getBukkitEntity(), (LightningStrike) lightning.getBukkitEntity(), changedEntity.getBukkitEntity()); ++ entity.getBukkitEntity().getServer().getPluginManager().callEvent(event); ++ return event; ++ } ++ // Paper end ++ + public static HorseJumpEvent callHorseJumpEvent(Entity horse, float power) { + HorseJumpEvent event = new HorseJumpEvent((AbstractHorse) horse.getBukkitEntity(), power); + horse.getBukkitEntity().getServer().getPluginManager().callEvent(event); diff --git a/patches/server-remapped/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/patches/server-remapped/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch new file mode 100644 index 0000000000..782f93006e --- /dev/null +++ b/patches/server-remapped/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 12 Nov 2016 23:25:22 -0600 +Subject: [PATCH] Filter bad data from ArmorStand and SpawnEgg items + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 622affa0dc3cc1eadaed400511f2ca2cde3fca2a..e83216be5a00d5b927d8c2fc364551bd3077c974 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -2,6 +2,7 @@ package com.destroystokyo.paper; + + import java.util.List; + ++import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; + +@@ -305,4 +306,12 @@ public class PaperWorldConfig { + private void removeCorruptTEs() { + removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); + } ++ ++ public boolean filterNBTFromSpawnEgg = true; ++ private void fitlerNBTFromSpawnEgg() { ++ filterNBTFromSpawnEgg = getBoolean("filter-nbt-data-from-spawn-eggs-and-related", true); ++ if (!filterNBTFromSpawnEgg) { ++ Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 1d87717cc9002ea202ee2ca614aaa8a4c7ea3cb2..ff8f7e4569a889ead1512b7c9908f9c5cad9eed5 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -270,6 +270,13 @@ public class FallingBlockEntity extends Entity { + @Override + protected void readAdditionalSaveData(CompoundTag tag) { + this.blockState = NbtUtils.readBlockState(tag.getCompound("BlockState")); ++ // Paper start - Block FallingBlocks with Command Blocks ++ // Check mappings on update - dc = "repeating_command_block" - dd = "chain_command_block" ++ final Block b = this.blockState.getBlock(); ++ if (this.level.paperConfig.filterNBTFromSpawnEgg && (b == Blocks.COMMAND_BLOCK || b == Blocks.REPEATING_COMMAND_BLOCK || b == Blocks.CHAIN_COMMAND_BLOCK)) { ++ this.blockState = Blocks.STONE.defaultBlockState(); ++ } ++ // Paper end + this.time = tag.getInt("Time"); + if (tag.contains("HurtEntities", 99)) { + this.hurtEntities = tag.getBoolean("HurtEntities"); diff --git a/patches/server-remapped/0118-Cache-user-authenticator-threads.patch b/patches/server-remapped/0118-Cache-user-authenticator-threads.patch new file mode 100644 index 0000000000..be4de8cb23 --- /dev/null +++ b/patches/server-remapped/0118-Cache-user-authenticator-threads.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: vemacs +Date: Wed, 23 Nov 2016 08:31:45 -0500 +Subject: [PATCH] Cache user authenticator threads + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0597c0c3e881dd43cf91bd3088ed30dfecfe8098..175bf535066afc42de8a3f0d11c46af66f3e3e52 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1388,7 +1388,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + } + +- player.entitiesToRemove.remove(Integer.valueOf(this.entity.getId())); ++ player.removeQueue.remove(Integer.valueOf(this.entity.getId())); + // CraftBukkit end + + if (flag1 && this.trackedPlayerMap.putIfAbsent(player, true) == null) { // Paper +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 3a2356b3e00098d100a179a05316f402390d4e9b..3cde25c2479adcc4ce3014e5ac2ec0710bffeea9 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -4,7 +4,9 @@ import com.google.common.collect.Lists; + import com.mojang.authlib.GameProfile; + import com.mojang.datafixers.util.Either; + import com.mojang.serialization.DataResult; ++import java.util.ArrayDeque; // Paper + import java.util.Collection; ++import java.util.Deque; // Paper + import java.util.Iterator; + import java.util.List; + import java.util.Optional; +@@ -169,7 +171,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public ServerGamePacketListenerImpl connection; + public final MinecraftServer server; + public final ServerPlayerGameMode gameMode; +- public final List entitiesToRemove = Lists.newLinkedList(); ++ public final Deque removeQueue = new ArrayDeque<>(); // Paper + private final PlayerAdvancements advancements; + private final ServerStatsCounter stats; + private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE; +@@ -544,16 +546,23 @@ public class ServerPlayer extends Player implements ContainerListener { + this.containerMenu = this.inventoryMenu; + } + +- while (!this.entitiesToRemove.isEmpty()) { +- int i = Math.min(this.entitiesToRemove.size(), Integer.MAX_VALUE); ++ while (!this.removeQueue.isEmpty()) { ++ int i = Math.min(this.removeQueue.size(), Integer.MAX_VALUE); + int[] aint = new int[i]; +- Iterator iterator = this.entitiesToRemove.iterator(); ++ //Iterator iterator = this.removeQueue.iterator(); // Paper + int j = 0; + +- while (iterator.hasNext() && j < i) { ++ // Paper start ++ /* while (iterator.hasNext() && j < i) { + aint[j++] = (Integer) iterator.next(); + iterator.remove(); ++ } */ ++ ++ Integer integer; ++ while (j < i && (integer = this.removeQueue.poll()) != null) { ++ aint[j++] = integer.intValue(); + } ++ // Paper end + + this.connection.send(new ClientboundRemoveEntitiesPacket(aint)); + } +@@ -1558,7 +1567,14 @@ public class ServerPlayer extends Player implements ContainerListener { + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; + // this.recipeBook.a((RecipeBook) entityplayer.recipeBook); // CraftBukkit +- this.entitiesToRemove.addAll(oldPlayer.entitiesToRemove); ++ // Paper start - Optimize remove queue - vanilla copies player objects, but CB doesn't. This method currently only ++ // Applies to the same player, so we need to not duplicate our removal queue. The rest of this method does "resetting" ++ // type logic so it does need to be called, maybe? This is silly. ++ // this.removeQueue.addAll(entityplayer.removeQueue); ++ if (this.removeQueue != oldPlayer.removeQueue) { ++ this.removeQueue.addAll(oldPlayer.removeQueue); ++ } ++ // Paper end + this.seenCredits = oldPlayer.seenCredits; + this.enteredNetherPosition = oldPlayer.enteredNetherPosition; + this.setShoulderEntityLeft(oldPlayer.getShoulderEntityLeft()); +@@ -1748,13 +1764,13 @@ public class ServerPlayer extends Player implements ContainerListener { + if (entity instanceof Player) { + this.connection.send(new ClientboundRemoveEntitiesPacket(new int[]{entity.getId()})); + } else { +- this.entitiesToRemove.add((Integer) entity.getId()); // CraftBukkit - decompile error ++ this.removeQueue.add((Integer) entity.getId()); // CraftBukkit - decompile error + } + + } + + public void cancelRemoveEntity(Entity entity) { +- this.entitiesToRemove.remove((Integer) entity.getId()); // CraftBukkit - decompile error ++ this.removeQueue.remove((Integer) entity.getId()); // CraftBukkit - decompile error + } + + @Override diff --git a/patches/server-remapped/0119-Optimise-removeQueue.patch b/patches/server-remapped/0119-Optimise-removeQueue.patch new file mode 100644 index 0000000000..f3b8068513 --- /dev/null +++ b/patches/server-remapped/0119-Optimise-removeQueue.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Fri, 25 Nov 2016 13:22:40 +0000 +Subject: [PATCH] Optimise removeQueue + + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 9dbb3bb79ae2de6635f71e5ee5bebeb5e57b624e..e3c1460c580ea348ee6d436018244441a5a1206e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -114,6 +114,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + + } + ++ // Paper start - Cache authenticator threads ++ private static final AtomicInteger threadId = new AtomicInteger(0); ++ private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool( ++ r -> new Thread(r, "User Authenticator #" + threadId.incrementAndGet()) ++ ); ++ // Paper end + // Spigot start + public void initUUID() + { +@@ -193,8 +199,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce)); + } else { + // Spigot start +- new Thread("User Authenticator #" + ServerLoginPacketListenerImpl.UNIQUE_THREAD_ID.incrementAndGet()) { +- ++ // Paper start - Cache authenticator threads ++ authenticatorPool.execute(new Runnable() { + @Override + public void run() { + try { +@@ -205,7 +211,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + gameProfile.getName(), ex); + } + } +- }.start(); ++ }); ++ // Paper end + // Spigot end + } + +@@ -234,7 +241,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + throw new IllegalStateException("Protocol error", cryptographyexception); + } + +- Thread thread = new Thread("User Authenticator #" + ServerLoginPacketListenerImpl.UNIQUE_THREAD_ID.incrementAndGet()) { ++ // Paper start - Cache authenticator threads ++ authenticatorPool.execute(new Runnable() { + public void run() { + GameProfile gameprofile = ServerLoginPacketListenerImpl.this.gameProfile; + +@@ -279,10 +287,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + + return ServerLoginPacketListenerImpl.this.server.getPreventProxyConnections() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; + } +- }; +- +- thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(ServerLoginPacketListenerImpl.LOGGER)); +- thread.start(); ++ }); ++ // Paper end + } + + // Spigot start diff --git a/patches/server-remapped/0120-Allow-Reloading-of-Command-Aliases.patch b/patches/server-remapped/0120-Allow-Reloading-of-Command-Aliases.patch new file mode 100644 index 0000000000..360a4a34cc --- /dev/null +++ b/patches/server-remapped/0120-Allow-Reloading-of-Command-Aliases.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: willies952002 +Date: Mon, 28 Nov 2016 10:21:52 -0500 +Subject: [PATCH] Allow Reloading of Command Aliases + +Reload the aliases stored in commands.yml + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index bbe0978f56d23b7defce765d381d4a7c20acd75c..9365fd2bcf74755c90c4ae9b550969e97a22c639 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2281,5 +2281,24 @@ public final class CraftServer implements Server { + DefaultPermissions.registerCorePermissions(); + CraftDefaultPermissions.registerCorePermissions(); + } ++ ++ @Override ++ public boolean reloadCommandAliases() { ++ Set removals = getCommandAliases().keySet().stream() ++ .map(key -> key.toLowerCase(java.util.Locale.ENGLISH)) ++ .collect(java.util.stream.Collectors.toSet()); ++ getCommandMap().getKnownCommands().keySet().removeIf(removals::contains); ++ File file = getCommandsConfigFile(); ++ try { ++ commandsConfiguration.load(file); ++ } catch (FileNotFoundException ex) { ++ return false; ++ } catch (IOException | org.bukkit.configuration.InvalidConfigurationException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex); ++ return false; ++ } ++ commandMap.registerServerAliases(); ++ return true; ++ } + // Paper end + } diff --git a/patches/server-remapped/0121-Add-source-to-PlayerExpChangeEvent.patch b/patches/server-remapped/0121-Add-source-to-PlayerExpChangeEvent.patch new file mode 100644 index 0000000000..0ab2cb875a --- /dev/null +++ b/patches/server-remapped/0121-Add-source-to-PlayerExpChangeEvent.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaBlend +Date: Thu, 8 Sep 2016 08:48:33 -0700 +Subject: [PATCH] Add source to PlayerExpChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index a4a1e836767d0b2b71c3277a28eb72418fa76210..f932fc4f8240b48f8e518af05d1521bc8ff9cbee 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -202,7 +202,7 @@ public class ExperienceOrb extends Entity { + } + + if (this.value > 0) { +- player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, this.value).getAmount()); // CraftBukkit - this.value -> event.getAmount() ++ player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object + } + + this.remove(); +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 81af3e2e0964b6e179f92a342efdae943be18b75..c85fcad33e17c8ae2e4ee5cb873dbd4166fcc7f5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -109,6 +109,7 @@ import org.bukkit.entity.ThrownPotion; + import org.bukkit.entity.Vehicle; + import org.bukkit.entity.Villager; + import org.bukkit.entity.Villager.Profession; ++import org.bukkit.entity.ExperienceOrb; // Paper + import org.bukkit.event.Cancellable; + import org.bukkit.event.Event; + import org.bukkit.event.Event.Result; +@@ -1045,6 +1046,17 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start - Add orb ++ public static PlayerExpChangeEvent callPlayerExpChangeEvent(net.minecraft.world.entity.player.Player entity, net.minecraft.world.entity.ExperienceOrb entityOrb) { ++ Player player = (Player) entity.getBukkitEntity(); ++ ExperienceOrb source = (ExperienceOrb) entityOrb.getBukkitEntity(); ++ int expAmount = source.getExperience(); ++ PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, source, expAmount); ++ Bukkit.getPluginManager().callEvent(event); ++ return event; ++ } ++ // Paper end ++ + public static boolean handleBlockGrowEvent(Level world, BlockPos pos, net.minecraft.world.level.block.state.BlockState block) { + return handleBlockGrowEvent(world, pos, block, 3); + } diff --git a/patches/server-remapped/0122-Don-t-let-fishinghooks-use-portals.patch b/patches/server-remapped/0122-Don-t-let-fishinghooks-use-portals.patch new file mode 100644 index 0000000000..6845784927 --- /dev/null +++ b/patches/server-remapped/0122-Don-t-let-fishinghooks-use-portals.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 16 Dec 2016 16:03:19 -0600 +Subject: [PATCH] Don't let fishinghooks use portals + + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +index 2f67c2065ef29f17f12190b25bd1ea53e1fb55b4..fa078167dd9e0cae80516549eef0e554c13938a3 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +@@ -237,6 +237,11 @@ public class FishingHook extends Projectile { + + this.setDeltaMovement(this.getDeltaMovement().scale(0.92D)); + this.reapplyPosition(); ++ // Paper start - These shouldn't be going through portals ++ if (this.isInsidePortal) { ++ this.remove(); ++ } ++ // Paper end + } + } + diff --git a/patches/server-remapped/0123-Add-ProjectileCollideEvent.patch b/patches/server-remapped/0123-Add-ProjectileCollideEvent.patch new file mode 100644 index 0000000000..0f4f99f50a --- /dev/null +++ b/patches/server-remapped/0123-Add-ProjectileCollideEvent.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Fri, 16 Dec 2016 21:25:39 -0600 +Subject: [PATCH] Add ProjectileCollideEvent + + +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 0dc5792d542658107c9c22c1f920986decd13920..3ce431c1fdf1f5bd62b49f26cca188e939e98efa 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -196,6 +196,17 @@ public abstract class AbstractArrow extends Projectile { + } + } + ++ // Paper start - Call ProjectileCollideEvent ++ // TODO: flag - noclip - call cancelled? ++ if (object instanceof EntityHitResult) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)object); ++ if (event.isCancelled()) { ++ object = null; ++ movingobjectpositionentity = null; ++ } ++ } ++ // Paper end ++ + if (object != null && !flag) { + this.preOnHit((HitResult) object); // CraftBukkit - projectile hit event + this.hasImpulse = true; +diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +index bdff1c57f64d1bf29f2050f06c8b585d395b2c5c..872ff430547276e2a41a48aa07ae63b87ab39e5d 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +@@ -12,6 +12,7 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.level.Level; ++import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit +@@ -71,7 +72,16 @@ public abstract class AbstractHurtingProjectile extends Projectile { + + HitResult movingobjectposition = ProjectileUtil.getHitResult((Entity) this, this::canHitEntity); + +- if (movingobjectposition.getType() != HitResult.Type.MISS) { ++ // Paper start - Call ProjectileCollideEvent ++ if (movingobjectposition instanceof EntityHitResult) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)movingobjectposition); ++ if (event.isCancelled()) { ++ movingobjectposition = null; ++ } ++ } ++ // Paper end ++ ++ if (movingobjectposition != null && movingobjectposition.getType() != HitResult.Type.MISS) { // Paper - add null check in case cancelled + this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + + // CraftBukkit start - Fire ProjectileHitEvent +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java +index 23f255bfa63cd16e2930fc932a2f4df8e522f2dc..becb07cda7388bcf2e987f06557894ae50d70dbf 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java +@@ -13,6 +13,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.BlockHitResult; ++import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + +@@ -57,7 +58,17 @@ public abstract class ThrowableProjectile extends Projectile { + } + + if (movingobjectposition.getType() != HitResult.Type.MISS && !flag) { ++ // Paper start - Call ProjectileCollideEvent ++ if (movingobjectposition instanceof EntityHitResult) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)movingobjectposition); ++ if (event.isCancelled()) { ++ movingobjectposition = null; ++ } ++ } ++ if (movingobjectposition != null) { ++ // Paper end + this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event ++ } // Paper + } + + this.checkInsideBlocks(); +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index c85fcad33e17c8ae2e4ee5cb873dbd4166fcc7f5..3f082b7fd50752728917a7da28cba4cb396a9fdf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1190,6 +1190,16 @@ public class CraftEventFactory { + return CraftItemStack.asNMSCopy(bitem); + } + ++ // Paper start ++ public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, EntityHitResult position) { ++ 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); ++ Bukkit.getPluginManager().callEvent(event); ++ return event; ++ } ++ // Paper end ++ + public static ProjectileLaunchEvent callProjectileLaunchEvent(Entity entity) { + Projectile bukkitEntity = (Projectile) entity.getBukkitEntity(); + ProjectileLaunchEvent event = new ProjectileLaunchEvent(bukkitEntity); diff --git a/patches/server-remapped/0124-Prevent-Pathfinding-out-of-World-Border.patch b/patches/server-remapped/0124-Prevent-Pathfinding-out-of-World-Border.patch new file mode 100644 index 0000000000..f8a0e7b1ea --- /dev/null +++ b/patches/server-remapped/0124-Prevent-Pathfinding-out-of-World-Border.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 19 Dec 2016 23:07:42 -0500 +Subject: [PATCH] Prevent Pathfinding out of World Border + +This prevents Entities from trying to run outside of the World Border + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index 25bc3adfad956157cef0953e6e632b7b7e352f3a..c3082f5dd64413a47421cb01538bec846bf21d2c 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -148,7 +148,7 @@ public abstract class PathNavigation { + // Paper start - Pathfind event + boolean copiedSet = false; + for (BlockPos possibleTarget : set) { +- if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), ++ if (!getEntity().getCommandSenderWorld().getWorldBorder().isInBounds(possibleTarget) || !new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), // Paper - don't path out of world border + MCUtil.toLocation(getEntity().level, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { + if (!copiedSet) { + copiedSet = true; diff --git a/patches/server-remapped/0125-Optimize-World.isLoaded-BlockPosition-Z.patch b/patches/server-remapped/0125-Optimize-World.isLoaded-BlockPosition-Z.patch new file mode 100644 index 0000000000..6a3d81e0fe --- /dev/null +++ b/patches/server-remapped/0125-Optimize-World.isLoaded-BlockPosition-Z.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 2 Dec 2016 00:11:43 -0500 +Subject: [PATCH] Optimize World.isLoaded(BlockPosition)Z + +Reduce method invocations for World.isLoaded(BlockPosition)Z + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 5f3d17cb247156fc8aaa7a763e402c2bbb42a7ec..ecb6378a285dff4b34170410387ebb7a8510a6dc 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -305,6 +305,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return chunk == null ? null : chunk.getFluidState(blockposition); + } + ++ public final boolean hasChunkAt(BlockPos pos) { ++ return getChunkIfLoaded(pos.getX() >> 4, pos.getZ() >> 4) != null; // Paper ++ } ++ + public final boolean isLoadedAndInBounds(BlockPos blockposition) { // Paper - final for inline + return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; + } diff --git a/patches/server-remapped/0126-Bound-Treasure-Maps-to-World-Border.patch b/patches/server-remapped/0126-Bound-Treasure-Maps-to-World-Border.patch new file mode 100644 index 0000000000..b839110284 --- /dev/null +++ b/patches/server-remapped/0126-Bound-Treasure-Maps-to-World-Border.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 20 Dec 2016 15:15:11 -0500 +Subject: [PATCH] Bound Treasure Maps to World Border + +Make it so a Treasure Map does not target a structure outside of the +World Border, where players are not even able to reach. + +This also would help the case where a players close to the border, and one +that is outside happens to be closer, but unreachable, yet another reachable +one is in border that would of been missed. + +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index 0846f649dca3422dbab3bb0a4826e27430cc8186..7a728ca96ee2eaf776c391ba8351196a526e18ec 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -36,6 +36,18 @@ public class WorldBorder { + return (double) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ(); + } + ++ // Paper start ++ private final BlockPos.MutableBlockPos mutPos = new BlockPos.MutableBlockPos(); ++ public boolean isBlockInBounds(int chunkX, int chunkZ) { ++ this.mutPos.setValues(chunkX, 64, chunkZ); ++ return this.isInBounds(this.mutPos); ++ } ++ public boolean isChunkInBounds(int chunkX, int chunkZ) { ++ this.mutPos.setValues(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15); ++ return this.isInBounds(this.mutPos); ++ } ++ // Paper end ++ + public boolean isWithinBounds(ChunkPos pos) { + return (double) pos.getMaxBlockX() > this.getMinX() && (double) pos.getMinBlockX() < this.getMaxX() && (double) pos.getMaxBlockZ() > this.getMinZ() && (double) pos.getMinBlockZ() < this.getMaxZ(); + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +index 9f60abfe0a37e30c5528a1ca0546295b00598798..0624b8270bc28c83c5479cd51fa4633ed5c36f44 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +@@ -175,6 +175,7 @@ public abstract class StructureFeature { + int i2 = l + k * k1; + int j2 = i1 + k * l1; + ChunkPos chunkcoordintpair = this.getPotentialFeatureChunk(config, worldSeed, seededrandom, i2, j2); ++ if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper + ChunkAccess ichunkaccess = world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); + StructureStart structurestart = structureAccessor.getStartForFeature(SectionPos.of(ichunkaccess.getPos(), 0), this, ichunkaccess); + diff --git a/patches/server-remapped/0127-Configurable-Cartographer-Treasure-Maps.patch b/patches/server-remapped/0127-Configurable-Cartographer-Treasure-Maps.patch new file mode 100644 index 0000000000..2eabafdf57 --- /dev/null +++ b/patches/server-remapped/0127-Configurable-Cartographer-Treasure-Maps.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 20 Dec 2016 15:26:27 -0500 +Subject: [PATCH] Configurable Cartographer Treasure Maps + +Allow configuring for cartographers to return the same map location + +Also allow turning off treasure maps all together as they can eat up Map ID's +which are limited in quantity. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e83216be5a00d5b927d8c2fc364551bd3077c974..2dc58b9f769ea43b737804456aafab47ecc143b8 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -314,4 +314,14 @@ public class PaperWorldConfig { + Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); + } + } ++ ++ public boolean enableTreasureMaps = true; ++ public boolean treasureMapsAlreadyDiscovered = false; ++ private void treasureMapsAlreadyDiscovered() { ++ enableTreasureMaps = getBoolean("enable-treasure-maps", true); ++ treasureMapsAlreadyDiscovered = getBoolean("treasure-maps-return-already-discovered", false); ++ if (treasureMapsAlreadyDiscovered) { ++ log("Treasure Maps will return already discovered locations"); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +index fd1b84baae5f333c58dbbdcbfaa9198328f0961d..7d490e1be772be22c3ab75c7e356465183a5c6b1 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java ++++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +@@ -124,7 +124,8 @@ public class VillagerTrades { + return null; + } else { + ServerLevel worldserver = (ServerLevel) entity.level; +- BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, entity.blockPosition(), 100, true); ++ if (!worldserver.paperConfig.enableTreasureMaps) return null; // Paper ++ BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, entity.blockPosition(), 100, !worldserver.paperConfig.treasureMapsAlreadyDiscovered); // Paper + + if (blockposition != null) { + ItemStack itemstack = MapItem.create(worldserver, blockposition.getX(), blockposition.getZ(), (byte) 2, true, true); +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java +index a3ce120b0da62f9be938c58c3414ce997f5d30ea..81a8331bfdf30da6ea69952ae42d3c77a2103bfd 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java +@@ -64,7 +64,16 @@ public class ExplorationMapFunction extends LootItemConditionalFunction { + + if (vec3d != null) { + ServerLevel worldserver = context.getLevel(); +- BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, new BlockPos(vec3d), this.searchRadius, this.skipKnownStructures); ++ // Paper start ++ if (!worldserver.paperConfig.enableTreasureMaps) { ++ /* ++ * NOTE: I fear users will just get a plain map as their "treasure" ++ * This is preferable to disrespecting the config. ++ */ ++ return stack; ++ } ++ // Paper end ++ BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, new BlockPos(vec3d), this.searchRadius, !worldserver.paperConfig.treasureMapsAlreadyDiscovered && this.skipKnownStructures); // Paper + + if (blockposition != null) { + ItemStack itemstack1 = MapItem.create(worldserver, blockposition.getX(), blockposition.getZ(), this.zoom, true, true); diff --git a/patches/server-remapped/0128-Optimize-ItemStack.isEmpty.patch b/patches/server-remapped/0128-Optimize-ItemStack.isEmpty.patch new file mode 100644 index 0000000000..329afa7401 --- /dev/null +++ b/patches/server-remapped/0128-Optimize-ItemStack.isEmpty.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Dec 2016 03:48:29 -0500 +Subject: [PATCH] Optimize ItemStack.isEmpty() + +Remove hashMap lookup every check, simplify code to remove ternary + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 123025c6dc9a2eea56c7db5cb508cdfd7c6cc97b..a0815c0d7f68f345dc48c73b8253de637c7a3e0f 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -206,7 +206,7 @@ public final class ItemStack { + } + + public boolean isEmpty() { +- return this == ItemStack.EMPTY ? true : (this.getItem() != null && this.getItem() != Items.AIR ? this.count <= 0 : true); ++ return this == ItemStack.NULL_ITEM || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper + } + + public ItemStack split(int amount) { diff --git a/patches/server-remapped/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch b/patches/server-remapped/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch new file mode 100644 index 0000000000..970e858ba4 --- /dev/null +++ b/patches/server-remapped/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 21 Dec 2016 11:47:25 -0600 +Subject: [PATCH] Add API methods to control if armour stands can move + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 09d39b73e8a3987e58a502bd914a6451b807421b..46f0ebfc99352ec8b64bdff2c6bb8d17ecfeb619 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -1,6 +1,5 @@ + package net.minecraft.world.entity; + +-import PathfinderGoalFloat; + import com.google.common.collect.Maps; + import java.util.Arrays; + import java.util.Iterator; +@@ -39,6 +38,7 @@ import net.minecraft.world.entity.ai.control.BodyRotationControl; + import net.minecraft.world.entity.ai.control.JumpControl; + import net.minecraft.world.entity.ai.control.LookControl; + import net.minecraft.world.entity.ai.control.MoveControl; ++import net.minecraft.world.entity.ai.goal.FloatGoal; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.goal.GoalSelector; + import net.minecraft.world.entity.ai.navigation.GroundPathNavigation; +@@ -47,6 +47,8 @@ import net.minecraft.world.entity.ai.sensing.Sensing; + import net.minecraft.world.entity.decoration.HangingEntity; + import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; + import net.minecraft.world.entity.item.ItemEntity; ++import net.minecraft.world.entity.monster.Blaze; ++import net.minecraft.world.entity.monster.EnderMan; + import net.minecraft.world.entity.monster.Enemy; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.Boat; +@@ -97,7 +99,7 @@ public abstract class Mob extends LivingEntity { + private final BodyRotationControl bodyRotationControl; + protected PathNavigation navigation; + public GoalSelector goalSelector; +- @Nullable public PathfinderGoalFloat goalFloat; // Paper ++ @Nullable public FloatGoal goalFloat; // Paper + public GoalSelector targetSelector; + private LivingEntity target; + private final Sensing sensing; +@@ -789,7 +791,7 @@ public abstract class Mob extends LivingEntity { + if (goalFloat.validConditions()) goalFloat.update(); + this.getJumpControl().jumpIfSet(); + } +- if ((this instanceof EntityBlaze || this instanceof EntityEnderman) && isInWaterOrRainOrBubble()) { ++ if ((this instanceof Blaze || this instanceof EnderMan) && isInWaterOrRainOrBubble()) { + hurt(DamageSource.DROWN, 1.0F); + } + return; +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 438dd75e3adffc395960b34b8bb26cbc07a4291e..8b6ec9ddf0d47bf4369b247e764f75893ab15781 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -26,6 +26,7 @@ import net.minecraft.world.entity.HumanoidArm; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.entity.vehicle.AbstractMinecart; +@@ -75,6 +76,7 @@ public class ArmorStand extends LivingEntity { + public Rotations rightArmPose; + public Rotations leftLegPose; + public Rotations rightLegPose; ++ public boolean canMove = true; // Paper + + public ArmorStand(EntityType type, Level world) { + super(type, world); +@@ -858,4 +860,13 @@ public class ArmorStand extends LivingEntity { + private EntityDimensions getDimensionsMarker(boolean flag) { + return flag ? ArmorStand.MARKER_DIMENSIONS : (this.isBaby() ? ArmorStand.BABY_DIMENSIONS : this.getType().getDimensions()); + } ++ ++ // Paper start ++ @Override ++ public void move(MoverType type, Vec3 movement) { ++ if (this.canMove) { ++ super.move(type, movement); ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +index 6b292162fb8c6416b1637b7b83e5113f6a35dbac..16f996d505b96da8a40c7709214ebbd2a0d0d9f3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +@@ -228,4 +228,15 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public boolean hasEquipmentLock(EquipmentSlot equipmentSlot, LockType lockType) { + return (getHandle().disabledSlots & (1 << CraftEquipmentSlot.getNMS(equipmentSlot).getFilterFlag() + lockType.ordinal() * 8)) != 0; + } ++ // Paper start ++ @Override ++ public boolean canMove() { ++ return getHandle().canMove; ++ } ++ ++ @Override ++ public void setCanMove(boolean move) { ++ getHandle().canMove = move; ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0130-Properly-fix-item-duplication-bug.patch b/patches/server-remapped/0130-Properly-fix-item-duplication-bug.patch new file mode 100644 index 0000000000..aa2398aa87 --- /dev/null +++ b/patches/server-remapped/0130-Properly-fix-item-duplication-bug.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Tue, 27 Dec 2016 01:57:57 +0000 +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 3cde25c2479adcc4ce3014e5ac2ec0710bffeea9..4ff66138fa43cf932b95d6d3dc050a9cd7b28ad4 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -2066,8 +2066,8 @@ public class ServerPlayer extends Player implements ContainerListener { + } + + @Override +- public boolean isImmobile() { +- return super.isImmobile() || !getBukkitEntity().isOnline(); ++ protected boolean isImmobile() { ++ return super.isImmobile() || (this.connection != null && this.connection.isDisconnected()); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 1b92c669bbe69bcc07a554b7b43ee99bfebc1af4..ecc393ad94332ec2a59d29f30bd60bade4e1f18e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2818,7 +2818,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + + public final boolean isDisconnected() { +- return !this.player.joining && !this.connection.isConnected(); ++ return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper + } + // CraftBukkit end + diff --git a/patches/server-remapped/0131-String-based-Action-Bar-API.patch b/patches/server-remapped/0131-String-based-Action-Bar-API.patch new file mode 100644 index 0000000000..416d50b18b --- /dev/null +++ b/patches/server-remapped/0131-String-based-Action-Bar-API.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 27 Dec 2016 15:02:42 -0500 +Subject: [PATCH] String based Action Bar API + + +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index 67fa685f4b8de3eae1431c0de399c246678b542a..7b36274718b7cce24ac00530697f145648d52590 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -58,7 +58,7 @@ public class Util { + private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main"); + private static final ExecutorService IO_POOL = makeIoExecutor(); + public static LongSupplier timeSource = System::nanoTime; +- public static final UUID NIL_UUID = new UUID(0L, 0L); ++ public static final UUID NIL_UUID = new UUID(0L, 0L); public static final UUID getNullUUID() {return NIL_UUID;} // Paper OBFHELPER + private static final Logger LOGGER = LogManager.getLogger(); + + public static Collector, ?, Map> toMap() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index fc19b4cacd223b928fbdf922b828beaed630bf2e..d6d4e5ab7551f802dc2d3ab055d340d471ed0bc2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -242,6 +242,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + // Paper start ++ @Override ++ public void sendActionBar(BaseComponent[] message) { ++ if (getHandle().connection == null) return; ++ getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.ACTIONBAR, message, -1, -1, -1)); ++ } ++ ++ @Override ++ public void sendActionBar(String message) { ++ if (getHandle().connection == null || message == null || message.isEmpty()) return; ++ getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.ACTIONBAR, CraftChatMessage.fromStringOrNull(message))); ++ } ++ ++ @Override ++ public void sendActionBar(char alternateChar, String message) { ++ if (message == null || message.isEmpty()) return; ++ sendActionBar(org.bukkit.ChatColor.translateAlternateColorCodes(alternateChar, message)); ++ } ++ + @Override + public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { + if (header != null) { diff --git a/patches/server-remapped/0132-Firework-API-s.patch b/patches/server-remapped/0132-Firework-API-s.patch new file mode 100644 index 0000000000..e3dc3d3182 --- /dev/null +++ b/patches/server-remapped/0132-Firework-API-s.patch @@ -0,0 +1,124 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 28 Dec 2016 07:18:33 +0100 +Subject: [PATCH] Firework API's + + +diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java +index 4c8f249e45e5deb7628997d4dbd9dab613ac5241..a91bf94ed9f2f353a685194fc91c4b101ccc1232 100644 +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -153,6 +153,7 @@ public class CompoundTag implements Tag { + return NbtUtils.loadUUID(this.get(key)); + } + ++ public final boolean hasUUID(String s) { return this.hasUUID(s); } // Paper - OBFHELPER + public boolean hasUUID(String key) { + Tag nbtbase = this.get(key); + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +index 28a2c6a0fbc8b4c38f3899698504d8ca0d7ba3af..5669be107b580075fdffbcbb490513593a57fc9f 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +@@ -37,7 +37,8 @@ public class FireworkRocketEntity extends Projectile { + public static final EntityDataAccessor DATA_SHOT_AT_ANGLE = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.BOOLEAN); + private int life; + public int lifetime; +- private LivingEntity attachedToEntity; ++ public LivingEntity attachedToEntity; // Paper - public ++ public java.util.UUID spawningEntity; // Paper + + public FireworkRocketEntity(EntityType type, Level world) { + super(type, world); +@@ -284,6 +285,11 @@ public class FireworkRocketEntity extends Projectile { + } + + tag.putBoolean("ShotAtAngle", (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE)); ++ // Paper start ++ if (this.spawningEntity != null) { ++ tag.setUUID("SpawningEntity", this.spawningEntity); ++ } ++ // Paper end + } + + @Override +@@ -300,7 +306,11 @@ public class FireworkRocketEntity extends Projectile { + if (tag.contains("ShotAtAngle")) { + this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, tag.getBoolean("ShotAtAngle")); + } +- ++ // Paper start ++ if (tag.hasUUID("SpawningEntity")) { ++ this.spawningEntity = tag.getUUID("SpawningEntity"); ++ } ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java +index 8a358872d3c8357775451e7dffe267cf9121f211..e1e58b7035e6dbafdad0a04cc5333464fc4febb8 100644 +--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java ++++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java +@@ -205,6 +205,7 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + + if (flag1) { + object = new FireworkRocketEntity(world, projectile, shooter, shooter.getX(), shooter.getEyeY() - 0.15000000596046448D, shooter.getZ(), true); ++ ((FireworkRocketEntity) object).spawningEntity = shooter.getUUID(); // Paper + } else { + object = getArrow(world, shooter, crossbow, projectile); + if (creative || simulated != 0.0F) { +diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index d3a045fc99ef77fa0905aac7c73a2e84772c73cf..dba52063d402eb2371441fa244b730a3313444fc 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -27,6 +27,7 @@ public class FireworkRocketItem extends Item { + Vec3 vec3d = context.getClickLocation(); + Direction enumdirection = context.getClickedFace(); + FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, context.getPlayer(), vec3d.x + (double) enumdirection.getStepX() * 0.15D, vec3d.y + (double) enumdirection.getStepY() * 0.15D, vec3d.z + (double) enumdirection.getStepZ() * 0.15D, itemstack); ++ entityfireworks.spawningEntity = context.getPlayer().getUUID(); // Paper + + world.addFreshEntity(entityfireworks); + itemstack.shrink(1); +@@ -41,7 +42,11 @@ public class FireworkRocketItem extends Item { + ItemStack itemstack = user.getItemInHand(hand); + + if (!world.isClientSide) { +- world.addFreshEntity(new FireworkRocketEntity(world, itemstack, user)); ++ // Paper start ++ final FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, itemstack, user); ++ entityfireworks.spawningEntity = user.getUUID(); ++ world.addFreshEntity(entityfireworks); ++ // Paper end + if (!user.abilities.instabuild) { + itemstack.shrink(1); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +index 5901a53b25449430ed02a80b022f83755f83a440..0fbbdd6e3fda3f834d0b0d68d868dbff1aebb673 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +@@ -1,6 +1,7 @@ + package org.bukkit.craftbukkit.entity; + + import java.util.Random; ++import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.projectile.FireworkRocketEntity; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -78,4 +79,17 @@ public class CraftFirework extends CraftProjectile implements Firework { + public void setShotAtAngle(boolean shotAtAngle) { + getHandle().getEntityData().set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, shotAtAngle); + } ++ ++ // Paper start ++ @Override ++ public java.util.UUID getSpawningEntity() { ++ return getHandle().spawningEntity; ++ } ++ ++ @Override ++ public org.bukkit.entity.LivingEntity getBoostedEntity() { ++ LivingEntity boostedEntity = getHandle().attachedToEntity; ++ return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null; ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0133-PlayerTeleportEndGatewayEvent.patch b/patches/server-remapped/0133-PlayerTeleportEndGatewayEvent.patch new file mode 100644 index 0000000000..98fb21f40b --- /dev/null +++ b/patches/server-remapped/0133-PlayerTeleportEndGatewayEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 31 Dec 2016 21:44:50 -0500 +Subject: [PATCH] PlayerTeleportEndGatewayEvent + +Allows you to access the Gateway being used in a teleport event + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +index 07d89af8111673087b0534ca9fac043d3e89662b..2c974f9801d209907733bed8e6c4c9ef46e2b610 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -10,6 +10,7 @@ import net.minecraft.data.worldgen.Features; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; +@@ -177,7 +178,7 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements + location.setPitch(player.getLocation().getPitch()); + location.setYaw(player.getLocation().getYaw()); + +- PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); ++ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(level, this.getBlockPos()).getBlock())); // Paper + Bukkit.getPluginManager().callEvent(teleEvent); + if (teleEvent.isCancelled()) { + return; diff --git a/patches/server-remapped/0134-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/server-remapped/0134-Provide-E-TE-Chunk-count-stat-methods.patch new file mode 100644 index 0000000000..7b2dc85ab1 --- /dev/null +++ b/patches/server-remapped/0134-Provide-E-TE-Chunk-count-stat-methods.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 Jan 2017 15:24:46 -0500 +Subject: [PATCH] Provide E/TE/Chunk count stat methods + +Provides counts without the ineffeciency of using .getEntities().size() +which creates copy of the collections. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index ca189e5d160d2655175c9fab9366ff93bded2fee..6782888f7df4eea4e6378ee850424e14c5136afd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -264,6 +264,48 @@ public class CraftWorld implements World { + private int waterAmbientSpawn = -1; + private int ambientSpawn = -1; + ++ // Paper start - Provide fast information methods ++ public int getEntityCount() { ++ int ret = 0; ++ for (net.minecraft.world.entity.Entity entity : world.entitiesById.values()) { ++ if (entity.isChunkLoaded()) { ++ ++ret; ++ } ++ } ++ return ret; ++ } ++ public int getTileEntityCount() { ++ // We don't use the full world tile entity list, so we must iterate chunks ++ Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; ++ int size = 0; ++ for (ChunkHolder playerchunk : chunks.values()) { ++ net.minecraft.world.level.chunk.LevelChunk chunk = playerchunk.getTickingChunk(); ++ if (chunk == null) { ++ continue; ++ } ++ size += chunk.blockEntities.size(); ++ } ++ return size; ++ } ++ public int getTickableTileEntityCount() { ++ return world.tickableBlockEntities.size(); ++ } ++ public int getChunkCount() { ++ int ret = 0; ++ ++ for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { ++ if (chunkHolder.getTickingChunk() != null) { ++ ++ret; ++ } ++ } ++ ++ return ret; ++ } ++ public int getPlayerCount() { ++ return world.players.size(); ++ } ++ // Paper end ++ + private static final Random rand = new Random(); + + public CraftWorld(ServerLevel world, ChunkGenerator gen, Environment env) { diff --git a/patches/server-remapped/0135-Enforce-Sync-Player-Saves.patch b/patches/server-remapped/0135-Enforce-Sync-Player-Saves.patch new file mode 100644 index 0000000000..09ab2be15a --- /dev/null +++ b/patches/server-remapped/0135-Enforce-Sync-Player-Saves.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 Jan 2017 15:41:58 -0500 +Subject: [PATCH] Enforce Sync Player Saves + +Saving players async is extremely dangerous. This will force it to main +the same way we handle async chunk loads. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 59fb19cfebe4f488fd02f02db31029d44b65e408..cebf536e9d16d44c4b2a91b5b4be053cd7f44045 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1043,11 +1043,13 @@ public abstract class PlayerList { + } + + public void saveAll() { ++ MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main + MinecraftTimings.savePlayers.startTiming(); // Paper + for (int i = 0; i < this.players.size(); ++i) { +- this.save((ServerPlayer) this.players.get(i)); ++ this.savePlayerFile((EntityPlayer) this.players.get(i)); + } + MinecraftTimings.savePlayers.stopTiming(); // Paper ++ return null; }); // Paper - ensure main + } + + public UserWhiteList getWhiteList() { diff --git a/patches/server-remapped/0136-Don-t-allow-entities-to-ride-themselves-572.patch b/patches/server-remapped/0136-Don-t-allow-entities-to-ride-themselves-572.patch new file mode 100644 index 0000000000..da9f57d585 --- /dev/null +++ b/patches/server-remapped/0136-Don-t-allow-entities-to-ride-themselves-572.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Sun, 8 Jan 2017 04:31:36 +0000 +Subject: [PATCH] Don't allow entities to ride themselves - #572 + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index c3aece8e5001828edea304b2a8377e9a28b34cfe..a9ed1c3ce6361a86dd58501f5b0ce5d6bbfb8adf 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2045,6 +2045,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + protected boolean addPassenger(Entity entity) { // CraftBukkit ++ if (entity == this) throw new IllegalArgumentException("Entities cannot become a passenger of themselves"); // Paper - issue 572 + if (entity.getVehicle() != this) { + throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)"); + } else { diff --git a/patches/server-remapped/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server-remapped/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch new file mode 100644 index 0000000000..44aa5bf7e5 --- /dev/null +++ b/patches/server-remapped/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch @@ -0,0 +1,332 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 16:31:46 -0500 +Subject: [PATCH] ExperienceOrbs API for Reason/Source/Triggering player + +Adds lots of information about why this orb exists. + +Replaces isFromBottle() with logic that persists entity reloads too. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index ed4309d5e567b20fd4aa025e7c82d8943bf1d8e1..26ce794cb8d089c03fab5dd0a0c910783d10b72e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -409,7 +409,7 @@ public class ServerPlayerGameMode { + + // Drop event experience + if (flag && event != null) { +- iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop()); ++ iblockdata.getBlock().dropExperience(this.level, pos, event.getExpToDrop(), this.player); // Paper + } + + return true; +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index f932fc4f8240b48f8e518af05d1521bc8ff9cbee..3ddb0a9f15c920c9a2080f76edfda0504c1e287a 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -30,13 +30,63 @@ public class ExperienceOrb extends Entity { + public int value; + private Player followingPlayer; + private int followingTime; ++ // Paper start ++ public java.util.UUID sourceEntityId; ++ public java.util.UUID triggerEntityId; ++ public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; ++ ++ private void loadPaperNBT(CompoundTag nbttagcompound) { ++ if (!nbttagcompound.contains("Paper.ExpData", 10)) { // 10 = compound ++ return; ++ } ++ CompoundTag comp = nbttagcompound.getCompound("Paper.ExpData"); ++ if (comp.hasUUID("source")) { ++ this.sourceEntityId = comp.getUUID("source"); ++ } ++ if (comp.hasUUID("trigger")) { ++ this.triggerEntityId = comp.getUUID("trigger"); ++ } ++ if (comp.contains("reason")) { ++ String reason = comp.getString("reason"); ++ try { ++ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason); ++ } catch (Exception e) { ++ this.level.getCraftServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason); ++ } ++ } ++ } ++ private void savePaperNBT(CompoundTag nbttagcompound) { ++ CompoundTag comp = new CompoundTag(); ++ if (this.sourceEntityId != null) { ++ comp.setUUID("source", this.sourceEntityId); ++ } ++ if (this.triggerEntityId != null) { ++ comp.setUUID("trigger", triggerEntityId); ++ } ++ if (this.spawnReason != null && this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) { ++ comp.putString("reason", this.spawnReason.name()); ++ } ++ nbttagcompound.put("Paper.ExpData", comp); ++ } + + public ExperienceOrb(Level world, double x, double y, double z, int amount) { ++ this(world, x, y, z, amount, null, null); ++ } ++ ++ public EntityExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { ++ this(world, d0, d1, d2, i, reason, triggerId, null); ++ } ++ ++ public EntityExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { + this(EntityType.EXPERIENCE_ORB, world); +- this.setPos(x, y, z); ++ this.sourceEntityId = sourceId != null ? sourceId.getUUID() : null; ++ this.triggerEntityId = triggerId != null ? triggerId.getUUID() : null; ++ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; ++ // Paper end ++ this.setPos(d0, d1, d2); + this.yRot = (float) (this.random.nextDouble() * 360.0D); + this.setDeltaMovement((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D); +- this.value = amount; ++ this.value = i; + } + + public ExperienceOrb(EntityType type, Level world) { +@@ -167,6 +217,7 @@ public class ExperienceOrb extends Entity { + tag.putShort("Health", (short) this.health); + tag.putShort("Age", (short) this.age); + tag.putShort("Value", (short) this.value); ++ this.savePaperNBT(tag); // Paper + } + + @Override +@@ -174,6 +225,7 @@ public class ExperienceOrb extends Entity { + this.health = tag.getShort("Health"); + this.age = tag.getShort("Age"); + this.value = tag.getShort("Value"); ++ this.loadPaperNBT(tag); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 1131d86080b3100437aa18a00c6277fcea4b7ea8..c6aa5328907f85cd210b1c20ff407e60d9b03349 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1591,7 +1591,8 @@ public abstract class LivingEntity extends Entity { + int j = ExperienceOrb.getExperienceValue(i); + + i -= j; +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); ++ LivingEntity attacker = lastHurtByPlayer != null ? lastHurtByPlayer : lastHurtByMob; // Paper ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this)); // Paper + } + this.expToDrop = 0; + } +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 ab2a19554aa1541e924104a70364f957ff8b33f9..e0f2a70870ff97ae2e8f216a202787bbcba6c6a9 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Animal.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java +@@ -260,7 +260,7 @@ public abstract class Animal extends AgableMob { + if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + // CraftBukkit start - use event experience + if (experience > 0) { +- worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience)); ++ worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper + } + // CraftBukkit end + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java +index 83fcfd888a335e3c054174e1f55e92fea878f7ab..c2d98222f575d7383e4c040730f6d531bdb0d7b6 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java +@@ -1306,7 +1306,7 @@ public class Fox extends Animal { + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + // CraftBukkit start - use event experience + if (experience > 0) { +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityfox)); // Paper + } + // CraftBukkit end + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +index 2ae59200ed67ab68645b569ba03839e8cedc9aa8..c54f4b83b9f2fdb15ddb363be0a179a05eb3693b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +@@ -561,7 +561,7 @@ public class Turtle extends Animal { + Random random = this.animal.getRandom(); + + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), random.nextInt(7) + 1)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), random.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper; + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index 39298b69918da890c3faa516f80d1a69adb88fe2..ae3cf71f14526e1f356216dfaa899c8f5083d46d 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -661,7 +661,7 @@ public class EnderDragon extends Mob implements Enemy { + int j = ExperienceOrb.getExperienceValue(amount); + + amount -= j; +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this)); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 5648a4a4d8511ac8c46c61245a7ff83753a3e51f..a66fab2e04a5d87ced139ed15d2434c5ffcec695 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -599,7 +599,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + } + + if (offer.shouldRewardExp()) { +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTradingPlayer(), this)); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +index 15570b9ba2443ce8c6f48dfbc13cdf45de8b45ac..69d92590d265abe8a04d8bf48bbe9a6ae606ae50 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -188,7 +188,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + if (offer.shouldRewardExp()) { + int i = 3 + this.random.nextInt(4); + +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTradingPlayer(), this)); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +index fa078167dd9e0cae80516549eef0e554c13938a3..7bff012f3cd4458673ee02e5f5f830fc0ef983a3 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +@@ -500,7 +500,7 @@ public class FishingHook extends Projectile { + this.level.addFreshEntity(entityitem); + // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() + if (playerFishEvent.getExpToDrop() > 0) { +- entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop())); ++ entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper + } + // CraftBukkit end + if (itemstack1.getItem().is((Tag) ItemTags.FISHES)) { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java +index 85b8f8f52c5035054ad9f665fce735260a54c270..42c7371355b6e36e31daf055317f015240761b8b 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java +@@ -54,7 +54,7 @@ public class ThrownExperienceBottle extends ThrowableItemProjectile { + int j = ExperienceOrb.getExperienceValue(i); + + i -= j; +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, getOwner(), this)); // Paper + } + + this.remove(); +diff --git a/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java b/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java +index ea6e1a96bd1fa9fbb87f65a169aa1e5af0589f34..5b9111d502bc12ab9e5c37e4d66c21aa37007b53 100644 +--- a/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java ++++ b/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java +@@ -7,7 +7,7 @@ import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; + + public class FurnaceResultSlot extends Slot { + +- private final Player player; ++ private final Player player; public final Player getPlayer() { return this.player; } // Paper OBFHELPER + private int removeCount; + + public FurnaceResultSlot(Player player, Container inventory, int index, int x, int y) { +diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +index e8bc37e1f7aebd192f048d7b056a41c50ceef9f5..e9e830117fe3e4e02a51eef8671a3d3b48c2858e 100644 +--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -93,7 +93,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { + int k = ExperienceOrb.getExperienceValue(j); + + j -= k; +- world.addFreshEntity(new ExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k)); ++ world.addFreshEntity(new ExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k, org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player)); // Paper + } + + world.levelEvent(1042, blockposition, 0); +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 2ae786b8fc6da19ca2a40252b0606f9e06d31ded..9d2e4adddae481735053c64eec0ee7259c61f1a4 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -267,13 +267,13 @@ public class Block extends BlockBehaviour implements ItemLike { + } + } + +- public void popExperience(ServerLevel world, BlockPos pos, int size) { +- if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { +- while (size > 0) { +- int j = ExperienceOrb.getExperienceValue(size); ++ public void dropExperience(ServerLevel worldserver, BlockPos blockposition, int i, net.minecraft.server.level.ServerPlayer player) { // Paper ++ if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { ++ while (i > 0) { ++ int j = ExperienceOrb.getExperienceValue(i); + +- size -= j; +- world.addFreshEntity(new ExperienceOrb(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, j)); ++ i -= j; ++ worldserver.addFreshEntity(new ExperienceOrb(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player)); // Paper + } + } + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 7a2554c5cd18e0c5e482ba8ba68a098d533b6a4f..8c55c1d88ef2e20e82bcdae0b9b3d381e562051f 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -601,7 +601,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + int k = ExperienceOrb.getExperienceValue(j); + + j -= k; +- world.addFreshEntity(new ExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k)); ++ world.addFreshEntity(new ExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman)); // Paper + } + + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 6782888f7df4eea4e6378ee850424e14c5136afd..88658d4deacc29128c537e2e02fdc8f684090a2c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1817,7 +1817,7 @@ public class CraftWorld implements World { + } else if (TNTPrimed.class.isAssignableFrom(clazz)) { + entity = new PrimedTnt(world, x, y, z, null); + } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { +- entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0); ++ entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper + } else if (LightningStrike.class.isAssignableFrom(clazz)) { + entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(world); + } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +index 3b450d97302bab30cdb975c8332b81318470503e..d5b8fd76ec3bd7d2621231480eb3e694a90aa037 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import SpawnReason; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.ExperienceOrb; +@@ -19,6 +20,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { + getHandle().value = value; + } + ++ // Paper start ++ public java.util.UUID getTriggerEntityId() { ++ return getHandle().triggerEntityId; ++ } ++ public java.util.UUID getSourceEntityId() { ++ return getHandle().sourceEntityId; ++ } ++ public SpawnReason getSpawnReason() { ++ return getHandle().spawnReason; ++ } ++ // Paper end ++ + @Override + public net.minecraft.world.entity.ExperienceOrb getHandle() { + return (net.minecraft.world.entity.ExperienceOrb) entity; diff --git a/patches/server-remapped/0138-Cap-Entity-Collisions.patch b/patches/server-remapped/0138-Cap-Entity-Collisions.patch new file mode 100644 index 0000000000..7b28bfe328 --- /dev/null +++ b/patches/server-remapped/0138-Cap-Entity-Collisions.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 22 Jan 2017 18:07:56 -0500 +Subject: [PATCH] Cap Entity Collisions + +Limit a single entity to colliding a max of configurable times per tick. +This will alleviate issues where living entities are hoarded in 1x1 pens + +This is not tied to the maxEntityCramming rule. Cramming will still apply +just as it does in Vanilla, but entity pushing logic will be capped. + +You can set this to 0 to disable collisions. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2dc58b9f769ea43b737804456aafab47ecc143b8..c611b5a63498f5ad1f50a75ccd5d7299e27df7e3 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -324,4 +324,10 @@ public class PaperWorldConfig { + log("Treasure Maps will return already discovered locations"); + } + } ++ ++ public int maxCollisionsPerEntity; ++ private void maxEntityCollision() { ++ maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); ++ log( "Max Entity Collisions: " + maxCollisionsPerEntity ); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a9ed1c3ce6361a86dd58501f5b0ce5d6bbfb8adf..a017fa55002d6674124befa3f6e81eb70c9ce8f7 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -267,6 +267,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; + public long activatedTick = Integer.MIN_VALUE; ++ protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index c6aa5328907f85cd210b1c20ff407e60d9b03349..3908f54e2216c635d47f8256bac455e7207a5bc6 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -2900,8 +2900,11 @@ public abstract class LivingEntity extends Entity { + } + } + +- for (j = 0; j < list.size(); ++j) { ++ numCollisions = Math.max(0, numCollisions - level.paperConfig.maxCollisionsPerEntity); // Paper ++ for (j = 0; j < list.size() && numCollisions < level.paperConfig.maxCollisionsPerEntity; ++j) { // Paper + Entity entity = (Entity) list.get(j); ++ entity.numCollisions++; // Paper ++ numCollisions++; // Paper + + this.doPush(entity); + } diff --git a/patches/server-remapped/0139-Remove-CraftScheduler-Async-Task-Debugger.patch b/patches/server-remapped/0139-Remove-CraftScheduler-Async-Task-Debugger.patch new file mode 100644 index 0000000000..db58842a96 --- /dev/null +++ b/patches/server-remapped/0139-Remove-CraftScheduler-Async-Task-Debugger.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 5 Feb 2017 00:04:04 -0500 +Subject: [PATCH] Remove CraftScheduler Async Task Debugger + +I have not once ever seen this system help debug a crash. +One report of a suspected memory leak with the system. + +This adds additional overhead to asynchronous task dispatching + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 9b6d9373abb59a30c2835ca891282d07559281f5..0e0f361c3af363539d5d1d865603114bdb84fd67 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -430,7 +430,7 @@ public class CraftScheduler implements BukkitScheduler { + } + parsePending(); + } else { +- debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); ++ //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper + executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper + // We don't need to parse pending + // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) +@@ -447,7 +447,7 @@ public class CraftScheduler implements BukkitScheduler { + pending.addAll(temp); + temp.clear(); + MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); +- debugHead = debugHead.getNextHead(currentTick); ++ //debugHead = debugHead.getNextHead(currentTick); // Paper + } + + private void addTask(final CraftTask task) { +@@ -507,10 +507,15 @@ public class CraftScheduler implements BukkitScheduler { + + @Override + public String toString() { ++ // Paper start ++ return ""; ++ /* + int debugTick = currentTick; + StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - RECENT_TICKS).append('-').append(debugTick).append('{'); + debugHead.debugTo(string); + return string.append('}').toString(); ++ */ ++ // Paper end + } + + @Deprecated diff --git a/patches/server-remapped/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/patches/server-remapped/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch new file mode 100644 index 0000000000..740c39b430 --- /dev/null +++ b/patches/server-remapped/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Tue, 7 Feb 2017 16:55:35 -0600 +Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 175bf535066afc42de8a3f0d11c46af66f3e3e52..3b6f35b695117bd2b0c71b994efc55fa1084eddc 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -119,7 +119,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private final PlayerMap playerMap; + public final Int2ObjectMap entityMap; + private final Long2ByteMap chunkTypeCache; +- private final Queue unloadQueue; ++ private final Queue unloadQueue; private final Queue getUnloadQueueTasks() { return this.unloadQueue; } // Paper - OBFHELPER + private int viewDistance; + + // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() +@@ -177,7 +177,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerMap = new PlayerMap(); + this.entityMap = new Int2ObjectOpenHashMap(); + this.chunkTypeCache = new Long2ByteOpenHashMap(); +- this.unloadQueue = Queues.newConcurrentLinkedQueue(); ++ this.unloadQueue = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size() + this.structureManager = definedstructuremanager; + this.storageFolder = convertable_conversionsession.getDimensionPath(worldserver.dimension()); + this.level = worldserver; +@@ -435,7 +435,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Spigot start + org.spigotmc.SlackActivityAccountant activityAccountant = this.level.getServer().slackActivityAccountant; + activityAccountant.startActivity(0.5); +- int targetSize = (int) (this.toDrop.size() * UNLOAD_QUEUE_RESIZE_FACTOR); ++ int targetSize = Math.min(this.toDrop.size() - 100, (int) (this.toDrop.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive + // Spigot end + while (longiterator.hasNext()) { // Spigot + long j = longiterator.nextLong(); +@@ -457,7 +457,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + Runnable runnable; + +- while ((shouldKeepTicking.getAsBoolean() || this.unloadQueue.size() > 2000) && (runnable = (Runnable) this.unloadQueue.poll()) != null) { ++ int queueTarget = Math.min(this.getUnloadQueueTasks().size() - 100, (int) (this.getUnloadQueueTasks().size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well ++ while ((shouldKeepTicking.getAsBoolean() || this.getUnloadQueueTasks().size() > queueTarget) && (runnable = (Runnable)this.getUnloadQueueTasks().poll()) != null) { // Paper - Target this queue as well + runnable.run(); + } + diff --git a/patches/server-remapped/0141-Do-not-let-armorstands-drown.patch b/patches/server-remapped/0141-Do-not-let-armorstands-drown.patch new file mode 100644 index 0000000000..d8f5fab54d --- /dev/null +++ b/patches/server-remapped/0141-Do-not-let-armorstands-drown.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 18 Feb 2017 19:29:58 -0600 +Subject: [PATCH] Do not let armorstands drown + + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 3908f54e2216c635d47f8256bac455e7207a5bc6..c1786fcabeaee5732e9197db04268c5c4e164339 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -335,6 +335,7 @@ public abstract class LivingEntity extends Entity { + super.checkFallDamage(heightDifference, onGround, landedState, landedPosition); + } + ++ public boolean canBreatheUnderwater() { return this.canBreatheUnderwater(); } // Paper - OBFHELPER + public boolean canBreatheUnderwater() { + return this.getMobType() == MobType.UNDEAD; + } +@@ -378,7 +379,7 @@ public abstract class LivingEntity extends Entity { + + if (this.isAlive()) { + if (this.isEyeInFluid((Tag) FluidTags.WATER) && !this.level.getBlockState(new BlockPos(this.getX(), this.getEyeY(), this.getZ())).is(Blocks.BUBBLE_COLUMN)) { +- if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { ++ if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { // Paper - use OBFHELPER so it can be overridden + this.setAirSupply(this.decreaseAirSupply(this.getAirSupply())); + if (this.getAirSupply() == -20) { + this.setAirSupply(0); +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 8b6ec9ddf0d47bf4369b247e764f75893ab15781..59239e202e8e99870ce3be515d2f040ad9786892 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -868,5 +868,10 @@ public class ArmorStand extends LivingEntity { + super.move(type, movement); + } + } ++ ++ @Override ++ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization ++ return true; ++ } + // Paper end + } diff --git a/patches/server-remapped/0142-Properly-handle-async-calls-to-restart-the-server.patch b/patches/server-remapped/0142-Properly-handle-async-calls-to-restart-the-server.patch new file mode 100644 index 0000000000..761e1f8b83 --- /dev/null +++ b/patches/server-remapped/0142-Properly-handle-async-calls-to-restart-the-server.patch @@ -0,0 +1,307 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 12 May 2017 23:34:11 -0500 +Subject: [PATCH] Properly handle async calls to restart the server + +The watchdog thread calls the server restart function asynchronously. Prior to +this change, it attempted to do several non-safe operations from the watchdog +thread, rather than the main. Specifically, because of a separate upstream change, +it causes player entities to be ticked asynchronously, among other things. + +This is dangerous. + +This patch moves the old handling into a synchronous variant, for calls from the +restart command, and adds separate handling for async calls, such as those from +the watchdog thread. + +When calling from the watchdog thread, we cannot assume the main thread is in a +tickable state; it may be completely deadlocked. In order to handle this, we mark +the server as stopping, in order to account for situations where the server should +complete a tick reasonbly soon, i.e. 99% of cases. + +Should the server not enter a state where it is stopping within 10 seconds, We +will assume that the server has in fact deadlocked and will proceed to force +kill the server. + +This modification does not force restart the server should we actually enter a +deadlocked state where the server is stopping, whereas this will in most cases +exit within a reasonable amount of time, to put a fixed limit on a process that +will have plugins and worlds saving to the disk has a high potential to result +in corruption/dataloss. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 211251fe7cd08074c040df2f4642f37d5f90d856..f41d79c6630fd8daae28476ffc854f7e65d841e6 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -199,6 +199,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop, ServerLevel> levels; + private PlayerList playerList; + private volatile boolean running; ++ private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart + private boolean stopped; + private int tickCount; + protected final Proxy proxy; +@@ -858,7 +859,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && new File( split[0] ).isFile() ) ++ // Paper - extract method and cleanup ++ boolean isRestarting = addShutdownHook( restartScript ); ++ if ( isRestarting ) + { +- System.out.println( "Attempting to restart with " + restartScript ); ++ System.out.println( "Attempting to restart with " + SpigotConfig.restartScript ); ++ } else ++ { ++ System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); ++ } ++ // Stop the watchdog ++ WatchdogThread.doStop(); + +- // Disable Watchdog +- WatchdogThread.doStop(); ++ shutdownServer( isRestarting ); ++ // Paper end ++ } catch ( Exception ex ) ++ { ++ ex.printStackTrace(); ++ } ++ } + +- // Kick all players +- for ( ServerPlayer p : (List) MinecraftServer.getServer().getPlayerList().players ) +- { +- p.connection.disconnect(SpigotConfig.restartMessage); +- } +- // Give the socket a chance to send the packets +- try +- { +- Thread.sleep( 100 ); +- } catch ( InterruptedException ex ) +- { +- } +- // Close the socket so we can rebind with the new process +- MinecraftServer.getServer().getConnection().stop(); ++ // Paper start - sync copied from above with minor changes, async added ++ private static void shutdownServer(boolean isRestarting) ++ { ++ if ( MinecraftServer.getServer().isSameThread() ) ++ { ++ // Kick all players ++ for ( ServerPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) ++ { ++ p.connection.disconnect(SpigotConfig.restartMessage); ++ } ++ // Give the socket a chance to send the packets ++ try ++ { ++ Thread.sleep( 100 ); ++ } catch ( InterruptedException ex ) ++ { ++ } + +- // Give time for it to kick in +- try +- { +- Thread.sleep( 100 ); +- } catch ( InterruptedException ex ) +- { +- } ++ closeSocket(); + +- // Actually shutdown +- try +- { +- MinecraftServer.getServer().close(); +- } catch ( Throwable t ) +- { +- } ++ // Actually shutdown ++ try ++ { ++ MinecraftServer.getServer().close(); // calls stop() ++ } catch ( Throwable t ) ++ { ++ } ++ ++ // Actually stop the JVM ++ System.exit( 0 ); + +- // This will be done AFTER the server has completely halted +- Thread shutdownHook = new Thread() ++ } else ++ { ++ // Mark the server to shutdown at the end of the tick ++ MinecraftServer.getServer().safeShutdown( false, isRestarting ); ++ ++ // wait 10 seconds to see if we're actually going to try shutdown ++ try ++ { ++ Thread.sleep( 10000 ); ++ } ++ catch (InterruptedException ignored) ++ { ++ } ++ ++ // Check if we've actually hit a state where the server is going to safely shutdown ++ // if we have, let the server stop as usual ++ if (MinecraftServer.getServer().isStopped()) return; ++ ++ // If the server hasn't stopped by now, assume worse case and kill ++ closeSocket(); ++ System.exit( 0 ); ++ } ++ } ++ // Paper end ++ ++ // Paper - Split from moved code ++ private static void closeSocket() ++ { ++ // Close the socket so we can rebind with the new process ++ MinecraftServer.getServer().getConnection().stop(); ++ ++ // Give time for it to kick in ++ try ++ { ++ Thread.sleep( 100 ); ++ } catch ( InterruptedException ex ) ++ { ++ } ++ } ++ // Paper end ++ ++ // Paper start - copied from above and modified to return if the hook registered ++ private static boolean addShutdownHook(String restartScript) ++ { ++ String[] split = restartScript.split( " " ); ++ if ( split.length > 0 && new File( split[0] ).isFile() ) ++ { ++ Thread shutdownHook = new Thread() ++ { ++ @Override ++ public void run() + { +- @Override +- public void run() ++ try + { +- try ++ String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); ++ if ( os.contains( "win" ) ) + { +- String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); +- if ( os.contains( "win" ) ) +- { +- Runtime.getRuntime().exec( "cmd /c start " + restartScript ); +- } else +- { +- Runtime.getRuntime().exec( "sh " + restartScript ); +- } +- } catch ( Exception e ) ++ Runtime.getRuntime().exec( "cmd /c start " + restartScript ); ++ } else + { +- e.printStackTrace(); ++ Runtime.getRuntime().exec( "sh " + restartScript ); + } ++ } catch ( Exception e ) ++ { ++ e.printStackTrace(); + } +- }; +- +- shutdownHook.setDaemon( true ); +- Runtime.getRuntime().addShutdownHook( shutdownHook ); +- } else +- { +- System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); +- +- // Actually shutdown +- try +- { +- MinecraftServer.getServer().close(); +- } catch ( Throwable t ) +- { + } +- } +- System.exit( 0 ); +- } catch ( Exception ex ) ++ }; ++ ++ shutdownHook.setDaemon( true ); ++ Runtime.getRuntime().addShutdownHook( shutdownHook ); ++ return true; ++ } else + { +- ex.printStackTrace(); ++ return false; + } + } ++ // Paper end ++ + } diff --git a/patches/server-remapped/0143-Add-system-property-to-disable-book-size-limits.patch b/patches/server-remapped/0143-Add-system-property-to-disable-book-size-limits.patch new file mode 100644 index 0000000000..ebfc39ca77 --- /dev/null +++ b/patches/server-remapped/0143-Add-system-property-to-disable-book-size-limits.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 13 May 2017 20:11:21 -0500 +Subject: [PATCH] Add system property to disable book size limits + +If anyone comes in with a watchdog crash related to books after this patch +you will not only be publicly shamed but also made an example of. + +Disables the security limits on books entirely, allowing plugins AND players +to make books with as much data as they want. Do not use this without +limiting incoming data from packets in some other way. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +index a592d4a286a775a61192dde2a4d21a0681090415..80397e223990f11c9aa413f3f4ebd7c1b8ce1cff 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +@@ -43,6 +43,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + static final int MAX_PAGES = 100; + static final int MAX_PAGE_LENGTH = 320; // 256 limit + 64 characters to allow for psuedo colour codes + static final int MAX_TITLE_LENGTH = 32; ++ private static final boolean OVERRIDE_CHECKS = Boolean.getBoolean("disable.book-limits"); // Paper - Add override + + protected String title; + protected String author; +@@ -245,7 +246,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + if (title == null) { + this.title = null; + return true; +- } else if (title.length() > MAX_TITLE_LENGTH) { ++ } else if (title.length() > MAX_TITLE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override + return false; + } + +@@ -442,7 +443,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + String validatePage(String page) { + if (page == null) { + page = ""; +- } else if (page.length() > MAX_PAGE_LENGTH) { ++ } else if (page.length() > MAX_PAGE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override + page = page.substring(0, MAX_PAGE_LENGTH); + } + return page; +@@ -452,7 +453,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + // asserted: page != null + if (this.pages == null) { + this.pages = new ArrayList(); +- } else if (this.pages.size() >= MAX_PAGES) { ++ } else if (this.pages.size() >= MAX_PAGES && !OVERRIDE_CHECKS) {// Paper - Add override + return; + } + this.pages.add(page); diff --git a/patches/server-remapped/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/patches/server-remapped/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch new file mode 100644 index 0000000000..0e3605cc72 --- /dev/null +++ b/patches/server-remapped/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 16 May 2017 21:29:08 -0500 +Subject: [PATCH] Add option to make parrots stay on shoulders despite movement + +Makes parrots not fall off whenever the player changes height, or touches water, or gets hit by a passing leaf. +Instead, switches the behavior so that players have to sneak to make the birds leave. + +I suspect Mojang may switch to this behavior before full release. + +To be converted into a Paper-API event at some point in the future? + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index c611b5a63498f5ad1f50a75ccd5d7299e27df7e3..9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -330,4 +330,10 @@ public class PaperWorldConfig { + maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); + log( "Max Entity Collisions: " + maxCollisionsPerEntity ); + } ++ ++ public boolean parrotsHangOnBetter; ++ private void parrotsHangOnBetter() { ++ parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); ++ log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index ecc393ad94332ec2a59d29f30bd60bade4e1f18e..6a922e3522ac99a8e317a5f5f51fbb597baaf63e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2051,6 +2051,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + switch (packet.getAction()) { + case PRESS_SHIFT_KEY: + this.player.setShiftKeyDown(true); ++ ++ // Paper start - Hang on! ++ if (this.player.level.paperConfig.parrotsHangOnBetter) { ++ this.player.removeEntitiesOnShoulder(); ++ } ++ // Paper end ++ + break; + 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 c11d5aa115d10e3c12863cf9d42c60194d63b690..ae10c531ae69eaf6b78a342dcedb89c39fd8dbcc 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -529,7 +529,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.removeEntitiesOnShoulder(); ++ if (!this.level.paperConfig.parrotsHangOnBetter) this.removeEntitiesOnShoulder(); // Paper - Hang on! + } + + } diff --git a/patches/server-remapped/0145-Add-configuration-option-to-prevent-player-names-fro.patch b/patches/server-remapped/0145-Add-configuration-option-to-prevent-player-names-fro.patch new file mode 100644 index 0000000000..2f0b8509ca --- /dev/null +++ b/patches/server-remapped/0145-Add-configuration-option-to-prevent-player-names-fro.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Fri, 9 Jun 2017 07:24:34 -0700 +Subject: [PATCH] Add configuration option to prevent player names from being + suggested + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 4e2f243faa209925dcb7c3ef89df3ed875c5ff78..48319aaf1c525c6fb7bdee5c2f570a0d056d4eae 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -268,4 +268,9 @@ public class PaperConfig { + flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); + flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); + } ++ ++ public static boolean suggestPlayersWhenNullTabCompletions = true; ++ private static void suggestPlayersWhenNull() { ++ suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 9365fd2bcf74755c90c4ae9b550969e97a22c639..d198dad80e0fb41a5bde66944d0e41509a9c1c43 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2300,5 +2300,10 @@ public final class CraftServer implements Server { + commandMap.registerServerAliases(); + return true; + } ++ ++ @Override ++ public boolean suggestPlayerNamesWhenNullTabCompletions() { ++ return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; ++ } + // Paper end + } diff --git a/patches/server-remapped/0146-Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server-remapped/0146-Use-TerminalConsoleAppender-for-console-improvements.patch new file mode 100644 index 0000000000..d43b61bcff --- /dev/null +++ b/patches/server-remapped/0146-Use-TerminalConsoleAppender-for-console-improvements.patch @@ -0,0 +1,558 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Fri, 9 Jun 2017 19:03:43 +0200 +Subject: [PATCH] Use TerminalConsoleAppender for console improvements + +Rewrite console improvements (console colors, tab completion, +persistent input line, ...) using JLine 3.x and TerminalConsoleAppender. + +New features: + - Support console colors for Vanilla commands + - Add console colors for warnings and errors + - Server can now be turned off safely using CTRL + C. JLine catches + the signal and the implementation shuts down the server cleanly. + - Support console colors and persistent input line when running in + IntelliJ IDEA + +Other changes: + - Server starts 1-2 seconds faster thanks to optimizations in Log4j + configuration + +diff --git a/pom.xml b/pom.xml +index a5d87d22cb1588d15e08da3b37e51c5e261c7799..3841fe3630c090f8a468333d43caeb2b5841329d 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -57,10 +57,26 @@ + compile + + +- jline +- jline +- 2.12.1 +- compile ++ net.minecrell ++ terminalconsoleappender ++ 1.2.0 ++ ++ ++ org.jline ++ jline-terminal-jansi ++ 3.12.1 ++ runtime ++ ++ ++ ++ org.apache.logging.log4j ++ log4j-core ++ runtime + + + org.apache.logging.log4j +@@ -334,10 +350,18 @@ + + META-INF/services/java.sql.Driver + ++ + + + + ++ ++ ++ com.github.edwgiz ++ maven-shade-plugin.log4j2-cachefile-transformer ++ 2.13.1 ++ ++ + + + org.apache.maven.plugins +diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a4070b59e261f0f1ac4beec47b11492f4724bf27 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.console; ++ ++import net.minecraft.server.dedicated.DedicatedServer; ++import net.minecrell.terminalconsole.SimpleTerminalConsole; ++import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; ++import org.jline.reader.LineReader; ++import org.jline.reader.LineReaderBuilder; ++ ++public final class PaperConsole extends SimpleTerminalConsole { ++ ++ private final DedicatedServer server; ++ ++ public PaperConsole(DedicatedServer server) { ++ this.server = server; ++ } ++ ++ @Override ++ protected LineReader buildReader(LineReaderBuilder builder) { ++ return super.buildReader(builder ++ .appName("Paper") ++ .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) ++ .completer(new ConsoleCommandCompleter(this.server)) ++ ); ++ } ++ ++ @Override ++ protected boolean isRunning() { ++ return !this.server.isStopped() && this.server.isRunning(); ++ } ++ ++ @Override ++ protected void runCommand(String command) { ++ this.server.handleConsoleInput(command, this.server.createCommandSourceStack()); ++ } ++ ++ @Override ++ protected void shutdown() { ++ this.server.halt(false); ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java +new file mode 100644 +index 0000000000000000000000000000000000000000..685deaa0e5d1ddc13e3a7c0471b1cfcf1710c869 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.console; ++ ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++import org.bukkit.craftbukkit.command.CraftConsoleCommandSender; ++ ++public class TerminalConsoleCommandSender extends CraftConsoleCommandSender { ++ ++ private static final Logger LOGGER = LogManager.getRootLogger(); ++ ++ @Override ++ public void sendRawMessage(String message) { ++ // TerminalConsoleAppender supports color codes directly in log messages ++ LOGGER.info(message); ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index f41d79c6630fd8daae28476ffc854f7e65d841e6..4b3341877629c7065496fb0f0b4d509f5a48db6d 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -12,6 +12,7 @@ import com.mojang.datafixers.DataFixer; + import io.netty.buffer.ByteBuf; + import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import it.unimi.dsi.fastutil.longs.LongIterator; + import java.awt.image.BufferedImage; + import java.io.BufferedWriter; +@@ -161,7 +162,7 @@ import org.apache.logging.log4j.Logger; + import com.mojang.serialization.DynamicOps; + import com.mojang.serialization.Lifecycle; + import com.google.common.collect.ImmutableSet; +-import jline.console.ConsoleReader; ++// import jline.console.ConsoleReader; // Paper + import joptsimple.OptionSet; + import net.minecraft.resources.RegistryReadOps; + import net.minecraft.server.bossevents.CustomBossEvents; +@@ -253,7 +254,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; +@@ -322,7 +323,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { // Trim to filter lines which are just spaces +- DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack()); ++ DedicatedServer.this.issueCommand(s, DedicatedServer.this.getServerCommandListener()); + } + // CraftBukkit end + } +@@ -138,6 +141,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + DedicatedServer.LOGGER.error("Exception handling console input", ioexception); + } + ++ */ ++ // Paper end + } + }; + +@@ -149,6 +154,9 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } + global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler()); + ++ // Paper start - Not needed with TerminalConsoleAppender ++ final org.apache.logging.log4j.Logger logger = LogManager.getRootLogger(); ++ /* + final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()); + for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) { + if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) { +@@ -157,6 +165,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } + + new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start(); ++ */ ++ // Paper end + + System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream()); + System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream()); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index d750bef20312cc97e3446bbb2d2dc03f90d47f1c..7d6256f65d369fcbcfe1fffe7ac264788a38540b 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -146,8 +146,7 @@ public abstract class PlayerList { + + public PlayerList(MinecraftServer server, RegistryAccess.RegistryHolder registryManager, PlayerDataStorage saveHandler, int maxPlayers) { + this.cserver = server.server = new CraftServer((DedicatedServer) server, this); +- server.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance(); +- server.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(server.server)); ++ server.console = new com.destroystokyo.paper.console.TerminalConsoleCommandSender(); // Paper + // CraftBukkit end + + this.bans = new UserBanList(PlayerList.USERBANLIST_FILE); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index d198dad80e0fb41a5bde66944d0e41509a9c1c43..7b2ece40c09ba336a0c2a84321401619801c64c8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -46,7 +46,6 @@ import java.util.function.Consumer; + import java.util.logging.Level; + import java.util.logging.Logger; + import javax.imageio.ImageIO; +-import jline.console.ConsoleReader; + import net.minecraft.advancements.Advancement; + import net.minecraft.commands.CommandSourceStack; + import net.minecraft.commands.Commands; +@@ -60,6 +59,7 @@ import net.minecraft.resources.RegistryReadOps; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.ConsoleInput; ++//import jline.console.ConsoleReader; // Paper + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.bossevents.CustomBossEvent; + import net.minecraft.server.commands.ReloadCommand; +@@ -1204,9 +1204,13 @@ public final class CraftServer implements Server { + return logger; + } + ++ // Paper start - JLine update ++ /* + public ConsoleReader getReader() { + return console.reader; + } ++ */ ++ // Paper end + + @Override + public PluginCommand getPluginCommand(String name) { +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index b849b2afd009da433fe6cea5837b3ee9bb5c52b4..60d9980ccca6f1ac55b70f7684b917ddceac380a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -12,7 +12,7 @@ import java.util.logging.Level; + import java.util.logging.Logger; + import joptsimple.OptionParser; + import joptsimple.OptionSet; +-import org.fusesource.jansi.AnsiConsole; ++import net.minecrell.terminalconsole.TerminalConsoleAppender; // Paper + + public class Main { + public static boolean useJline = true; +@@ -185,6 +185,8 @@ public class Main { + } + + try { ++ // Paper start - Handled by TerminalConsoleAppender ++ /* + // This trick bypasses Maven Shade's clever rewriting of our getProperty call when using String literals + String jline_UnsupportedTerminal = new String(new char[]{'j', 'l', 'i', 'n', 'e', '.', 'U', 'n', 's', 'u', 'p', 'p', 'o', 'r', 't', 'e', 'd', 'T', 'e', 'r', 'm', 'i', 'n', 'a', 'l'}); + String jline_terminal = new String(new char[]{'j', 'l', 'i', 'n', 'e', '.', 't', 'e', 'r', 'm', 'i', 'n', 'a', 'l'}); +@@ -202,9 +204,18 @@ public class Main { + // This ensures the terminal literal will always match the jline implementation + System.setProperty(jline.TerminalFactory.JLINE_TERMINAL, jline.UnsupportedTerminal.class.getName()); + } ++ */ ++ ++ if (options.has("nojline")) { ++ System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); ++ useJline = false; ++ } ++ // Paper end + + if (options.has("noconsole")) { + useConsole = false; ++ useJline = false; // Paper ++ System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper + } + + if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { +@@ -232,7 +243,7 @@ public class Main { + System.out.println("Unable to read system info"); + } + // Paper end +- ++ System.setProperty( "library.jansi.version", "Paper" ); // Paper - set meaningless jansi version to prevent git builds from crashing on Windows + System.out.println("Loading libraries, please wait..."); + net.minecraft.server.Main.main(options); + } catch (Throwable t) { +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java b/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java +index 4580642e0ee79e6d9c9bef0344e643bbc551205c..829c62b6d55cb5706be3ce6bdc758d6b204844ee 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java +@@ -5,15 +5,13 @@ import java.util.EnumMap; + import java.util.Map; + import java.util.regex.Matcher; + import java.util.regex.Pattern; +-import jline.Terminal; ++//import jline.Terminal; + import org.bukkit.Bukkit; + import org.bukkit.ChatColor; + import org.bukkit.command.ConsoleCommandSender; + import org.bukkit.craftbukkit.CraftServer; +-import org.fusesource.jansi.Ansi; +-import org.fusesource.jansi.Ansi.Attribute; + +-public class ColouredConsoleSender extends CraftConsoleCommandSender { ++public class ColouredConsoleSender /*extends CraftConsoleCommandSender */{/* // Paper - disable + private final Terminal terminal; + private final Map replacements = new EnumMap(ChatColor.class); + private final ChatColor[] colors = ChatColor.values(); +@@ -93,5 +91,5 @@ public class ColouredConsoleSender extends CraftConsoleCommandSender { + } else { + return new ColouredConsoleSender(); + } +- } ++ }*/ // Paper + } +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index befcc19f9b56df9096b98a23b0020f1db793ea5b..a957695457cf3252848ce6ef37069692841b8e28 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -4,20 +4,31 @@ import java.util.Collections; + import java.util.List; + import java.util.concurrent.ExecutionException; + import java.util.logging.Level; +-import jline.console.completer.Completer; ++import net.minecraft.server.dedicated.DedicatedServer; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.util.Waitable; ++ ++// Paper start - JLine update ++import org.jline.reader.Candidate; ++import org.jline.reader.Completer; ++import org.jline.reader.LineReader; ++import org.jline.reader.ParsedLine; ++// Paper end + import org.bukkit.event.server.TabCompleteEvent; + + public class ConsoleCommandCompleter implements Completer { +- private final CraftServer server; ++ private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer + +- public ConsoleCommandCompleter(CraftServer server) { ++ public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer + this.server = server; + } + ++ // Paper start - Change method signature for JLine update + @Override +- public int complete(final String buffer, final int cursor, final List candidates) { ++ public void complete(LineReader reader, ParsedLine line, List candidates) { ++ final CraftServer server = this.server.server; ++ final String buffer = line.line(); ++ // Paper end + Waitable> waitable = new Waitable>() { + @Override + protected List evaluate() { +@@ -29,25 +40,37 @@ public class ConsoleCommandCompleter implements Completer { + return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); + } + }; +- this.server.getServer().processQueue.add(waitable); ++ server.getServer().processQueue.add(waitable); // Paper - Remove "this." + try { + List offers = waitable.get(); + if (offers == null) { +- return cursor; ++ return; // Paper - Method returns void ++ } ++ ++ // Paper start - JLine update ++ for (String completion : offers) { ++ if (completion.isEmpty()) { ++ continue; ++ } ++ ++ candidates.add(new Candidate(completion)); + } +- candidates.addAll(offers); ++ // Paper end + ++ // Paper start - JLine handles cursor now ++ /* + final int lastSpace = buffer.lastIndexOf(' '); + if (lastSpace == -1) { + return cursor - buffer.length(); + } else { + return cursor - (buffer.length() - lastSpace - 1); + } ++ */ ++ // Paper end + } catch (ExecutionException e) { +- this.server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); ++ server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); // Paper - Remove "this." + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } +- return cursor; + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +index 70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe..449e99d1b673870ed6892f6ab2c715a2db35c35d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +@@ -17,7 +17,7 @@ public class ServerShutdownThread extends Thread { + server.close(); + } finally { + try { +- server.reader.getTerminal().restore(); ++ net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender + } catch (Exception e) { + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java +index 99564fed7ce77e29dbdc591bcfe656af741acf8a..9a2da548b8860b496e396564b2c8f6383f020193 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java +@@ -5,12 +5,12 @@ import java.io.IOException; + import java.io.OutputStream; + import java.util.logging.Level; + import java.util.logging.Logger; +-import jline.console.ConsoleReader; ++//import jline.console.ConsoleReader; + import org.bukkit.craftbukkit.Main; +-import org.fusesource.jansi.Ansi; +-import org.fusesource.jansi.Ansi.Erase; ++//import org.fusesource.jansi.Ansi; ++//import org.fusesource.jansi.Ansi.Erase; + +-public class TerminalConsoleWriterThread extends Thread { ++public class TerminalConsoleWriterThread /*extends Thread*/ {/* // Paper - disable + private final ConsoleReader reader; + private final OutputStream output; + +@@ -54,5 +54,5 @@ public class TerminalConsoleWriterThread extends Thread { + Logger.getLogger(TerminalConsoleWriterThread.class.getName()).log(Level.SEVERE, null, ex); + } + } +- } ++ }*/ + } +diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties +new file mode 100644 +index 0000000000000000000000000000000000000000..0694b21465fb9e4164e71862ff24b62241b191f2 +--- /dev/null ++++ b/src/main/resources/log4j2.component.properties +@@ -0,0 +1 @@ ++log4j.skipJansi=true +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 722ca84968cbbbdeffd09939abff0cccd0a84010..620b9490e5f159080e50289d127404a1b56adbef 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -1,17 +1,14 @@ + + + +- +- +- + + + +- +- +- ++ ++ ++ + +- ++ + + + +@@ -24,10 +21,9 @@ + + + +- + +- + ++ + + + diff --git a/patches/server-remapped/0147-provide-a-configurable-option-to-disable-creeper-lin.patch b/patches/server-remapped/0147-provide-a-configurable-option-to-disable-creeper-lin.patch new file mode 100644 index 0000000000..a511c4d919 --- /dev/null +++ b/patches/server-remapped/0147-provide-a-configurable-option-to-disable-creeper-lin.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 11 Jun 2017 21:01:18 +0100 +Subject: [PATCH] provide a configurable option to disable creeper lingering + effect spawns + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1..90ca51dfdbb3045dd528450225cba96f5834166e 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -336,4 +336,10 @@ public class PaperWorldConfig { + parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); + log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); + } ++ ++ public boolean disableCreeperLingeringEffect; ++ private void setDisableCreeperLingeringEffect() { ++ disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); ++ log("Creeper lingering effect: " + disableCreeperLingeringEffect); ++ } + } +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 bb3226310158139c9fcfe204554caffcbb62798c..8f8d0a23d011936150854a0606be3d63b18c57af 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +@@ -261,7 +261,7 @@ public class Creeper extends Monster { + private void spawnLingeringCloud() { + Collection collection = this.getActiveEffects(); + +- if (!collection.isEmpty()) { ++ if (!collection.isEmpty() && !level.paperConfig.disableCreeperLingeringEffect) { // Paper + AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level, this.getX(), this.getY(), this.getZ()); + + entityareaeffectcloud.setOwner(this); // CraftBukkit diff --git a/patches/server-remapped/0148-Item-canEntityPickup.patch b/patches/server-remapped/0148-Item-canEntityPickup.patch new file mode 100644 index 0000000000..569a928f31 --- /dev/null +++ b/patches/server-remapped/0148-Item-canEntityPickup.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 5 May 2017 03:57:17 -0500 +Subject: [PATCH] Item#canEntityPickup + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 46f0ebfc99352ec8b64bdff2c6bb8d17ecfeb619..eb35c69bb777ba8d83b2304ff9f862512643e745 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -605,6 +605,11 @@ public abstract class Mob extends LivingEntity { + ItemEntity entityitem = (ItemEntity) iterator.next(); + + if (!entityitem.removed && !entityitem.getItem().isEmpty() && !entityitem.hasPickUpDelay() && this.wantsToPickUp(entityitem.getItem())) { ++ // Paper Start ++ if (!entityitem.canMobPickup) { ++ continue; ++ } ++ // Paper End + this.pickUpItem(entityitem); + } + } +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 78dc5ac986afaba04176f64afbb035442cd41d38..7aba507e171f34e213b3c034e345e7397a44d2b5 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -46,6 +46,7 @@ public class ItemEntity extends Entity { + private UUID owner; + public final float bobOffs; + private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit ++ public boolean canMobPickup = true; // Paper + + public ItemEntity(EntityType type, Level world) { + super(type, world); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +index 6e394ce6ea4177e1758e27074a4fd54d716edc3d..9a410f557988d737c3b930a79ef2ccb2b5c8b406 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +@@ -49,6 +49,16 @@ public class CraftItem extends CraftEntity implements Item { + item.age = value; + } + ++ // Paper Start ++ public boolean canMobPickup() { ++ return item.canMobPickup; ++ } ++ ++ public void setCanMobPickup(boolean canMobPickup) { ++ item.canMobPickup = canMobPickup; ++ } ++ // Paper End ++ + @Override + public void setOwner(UUID uuid) { + item.setOwner(uuid); diff --git a/patches/server-remapped/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch b/patches/server-remapped/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch new file mode 100644 index 0000000000..a5081735fc --- /dev/null +++ b/patches/server-remapped/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 7 May 2017 06:26:09 -0500 +Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer + + +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 7aba507e171f34e213b3c034e345e7397a44d2b5..72d1e83ac5e4ae3c943ca5ec1058f0d7ad2903cd 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -362,6 +362,7 @@ public class ItemEntity extends Entity { + // CraftBukkit start - fire PlayerPickupItemEvent + int canHold = player.inventory.canHold(itemstack); + int remaining = i - canHold; ++ boolean flyAtPlayer = false; // Paper + + if (this.pickupDelay <= 0 && canHold > 0) { + itemstack.setCount(canHold); +@@ -369,8 +370,14 @@ public class ItemEntity extends Entity { + PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); + playerEvent.setCancelled(!player.canPickUpLoot); + this.level.getCraftServer().getPluginManager().callEvent(playerEvent); ++ flyAtPlayer = playerEvent.getFlyAtPlayer(); // Paper + if (playerEvent.isCancelled()) { + itemstack.setCount(i); // SPIGOT-5294 - restore count ++ // Paper Start ++ if (flyAtPlayer) { ++ player.take(this, i); ++ } ++ // Paper End + return; + } + +@@ -400,7 +407,11 @@ public class ItemEntity extends Entity { + // CraftBukkit end + + if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(player.getUUID())) && player.inventory.add(itemstack)) { +- player.take(this, i); ++ // Paper Start ++ if (flyAtPlayer) { ++ player.take(this, i); ++ } ++ // Paper End + if (itemstack.isEmpty()) { + this.remove(); + itemstack.setCount(i); diff --git a/patches/server-remapped/0150-PlayerAttemptPickupItemEvent.patch b/patches/server-remapped/0150-PlayerAttemptPickupItemEvent.patch new file mode 100644 index 0000000000..1c5b10dcee --- /dev/null +++ b/patches/server-remapped/0150-PlayerAttemptPickupItemEvent.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 11 Jun 2017 16:30:30 -0500 +Subject: [PATCH] PlayerAttemptPickupItemEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 72d1e83ac5e4ae3c943ca5ec1058f0d7ad2903cd..de69f7c3c0ee1e74682b0db91bdaae09175690e9 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -35,6 +35,7 @@ import net.minecraft.stats.Stats; + import org.bukkit.event.entity.EntityPickupItemEvent; + import org.bukkit.event.player.PlayerPickupItemEvent; + // CraftBukkit end ++import org.bukkit.event.player.PlayerAttemptPickupItemEvent; // Paper + + public class ItemEntity extends Entity { + +@@ -364,6 +365,22 @@ public class ItemEntity extends Entity { + int remaining = i - canHold; + boolean flyAtPlayer = false; // Paper + ++ // Paper start ++ if (this.pickupDelay <= 0) { ++ PlayerAttemptPickupItemEvent attemptEvent = new PlayerAttemptPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ this.level.getCraftServer().getPluginManager().callEvent(attemptEvent); ++ ++ flyAtPlayer = attemptEvent.getFlyAtPlayer(); ++ if (attemptEvent.isCancelled()) { ++ if (flyAtPlayer) { ++ player.take(this, i); ++ } ++ ++ return; ++ } ++ } ++ // Paper end ++ + if (this.pickupDelay <= 0 && canHold > 0) { + itemstack.setCount(canHold); + // Call legacy event diff --git a/patches/server-remapped/0151-Add-UnknownCommandEvent.patch b/patches/server-remapped/0151-Add-UnknownCommandEvent.patch new file mode 100644 index 0000000000..9979b7ace2 --- /dev/null +++ b/patches/server-remapped/0151-Add-UnknownCommandEvent.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sweepyoface +Date: Sat, 17 Jun 2017 18:48:21 -0400 +Subject: [PATCH] Add UnknownCommandEvent + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 7b2ece40c09ba336a0c2a84321401619801c64c8..b9e39a4c0aea3de96d1774ae0d0d23ff82162c7e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -790,7 +790,13 @@ public final class CraftServer implements Server { + + // Spigot start + if (!org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty()) { +- sender.sendMessage(org.spigotmc.SpigotConfig.unknownCommandMessage); ++ // Paper start ++ org.bukkit.event.command.UnknownCommandEvent event = new org.bukkit.event.command.UnknownCommandEvent(sender, commandLine, org.spigotmc.SpigotConfig.unknownCommandMessage); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.message() != null) { ++ sender.sendMessage(event.message()); ++ } ++ // Paper end + } + // Spigot end + diff --git a/patches/server-remapped/0152-Basic-PlayerProfile-API.patch b/patches/server-remapped/0152-Basic-PlayerProfile-API.patch new file mode 100644 index 0000000000..ce8cf66ee0 --- /dev/null +++ b/patches/server-remapped/0152-Basic-PlayerProfile-API.patch @@ -0,0 +1,577 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 15 Jan 2018 22:11:48 -0500 +Subject: [PATCH] Basic PlayerProfile API + +Establishes base extension of profile systems for future edits too + +diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8f559897e408eee8617af0bb77fa4635e07ccdce +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java +@@ -0,0 +1,303 @@ ++package com.destroystokyo.paper.profile; ++ ++import PlayerProfile; ++import ProfileProperty; ++import com.destroystokyo.paper.PaperConfig; ++import com.google.common.base.Charsets; ++import com.mojang.authlib.GameProfile; ++import com.mojang.authlib.properties.Property; ++import com.mojang.authlib.properties.PropertyMap; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.players.GameProfileCache; ++import org.apache.commons.lang3.Validate; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.spigotmc.SpigotConfig; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++import java.util.AbstractSet; ++import java.util.Collection; ++import java.util.Iterator; ++import java.util.Objects; ++import java.util.Set; ++import java.util.UUID; ++ ++public class CraftPlayerProfile implements PlayerProfile { ++ ++ private GameProfile profile; ++ private final PropertySet properties = new PropertySet(); ++ ++ public CraftPlayerProfile(CraftPlayer player) { ++ this.profile = player.getHandle().getGameProfile(); ++ } ++ ++ public CraftPlayerProfile(UUID id, String name) { ++ this.profile = new GameProfile(id, name); ++ } ++ ++ public CraftPlayerProfile(GameProfile profile) { ++ Validate.notNull(profile, "GameProfile cannot be null!"); ++ this.profile = profile; ++ } ++ ++ @Override ++ public boolean hasProperty(String property) { ++ return profile.getProperties().containsKey(property); ++ } ++ ++ @Override ++ public void setProperty(ProfileProperty property) { ++ String name = property.getName(); ++ PropertyMap properties = profile.getProperties(); ++ properties.removeAll(name); ++ properties.put(name, new Property(name, property.getValue(), property.getSignature())); ++ } ++ ++ public GameProfile getGameProfile() { ++ return profile; ++ } ++ ++ @Nullable ++ @Override ++ public UUID getId() { ++ return profile.getId(); ++ } ++ ++ @Override ++ public UUID setId(@Nullable UUID uuid) { ++ GameProfile prev = this.profile; ++ this.profile = new GameProfile(uuid, prev.getName()); ++ copyProfileProperties(prev, this.profile); ++ return prev.getId(); ++ } ++ ++ @Nullable ++ @Override ++ public String getName() { ++ return profile.getName(); ++ } ++ ++ @Override ++ public String setName(@Nullable String name) { ++ GameProfile prev = this.profile; ++ this.profile = new GameProfile(prev.getId(), name); ++ copyProfileProperties(prev, this.profile); ++ return prev.getName(); ++ } ++ ++ @Nonnull ++ @Override ++ public Set getProperties() { ++ return properties; ++ } ++ ++ @Override ++ public void setProperties(Collection properties) { ++ properties.forEach(this::setProperty); ++ } ++ ++ @Override ++ public void clearProperties() { ++ profile.getProperties().clear(); ++ } ++ ++ @Override ++ public boolean removeProperty(String property) { ++ return !profile.getProperties().removeAll(property).isEmpty(); ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ CraftPlayerProfile that = (CraftPlayerProfile) o; ++ return Objects.equals(profile, that.profile); ++ } ++ ++ @Override ++ public int hashCode() { ++ return profile.hashCode(); ++ } ++ ++ @Override ++ public String toString() { ++ return profile.toString(); ++ } ++ ++ @Override ++ public CraftPlayerProfile clone() { ++ CraftPlayerProfile clone = new CraftPlayerProfile(this.getId(), this.getName()); ++ clone.setProperties(getProperties()); ++ return clone; ++ } ++ ++ @Override ++ public boolean isComplete() { ++ return profile.isComplete(); ++ } ++ ++ @Override ++ public boolean completeFromCache() { ++ MinecraftServer server = MinecraftServer.getServer(); ++ return completeFromCache(false, PaperConfig.isProxyOnlineMode()); ++ } ++ ++ public boolean completeFromCache(boolean onlineMode) { ++ return completeFromCache(false, onlineMode); ++ } ++ ++ public boolean completeFromCache(boolean lookupUUID, boolean onlineMode) { ++ MinecraftServer server = MinecraftServer.getServer(); ++ String name = profile.getName(); ++ GameProfileCache userCache = server.getProfileCache(); ++ if (profile.getId() == null) { ++ final GameProfile profile; ++ if (onlineMode) { ++ profile = lookupUUID ? userCache.get(name) : userCache.getProfileIfCached(name); ++ } else { ++ // Make an OfflinePlayer using an offline mode UUID since the name has no profile ++ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); ++ } ++ if (profile != null) { ++ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't ++ copyProfileProperties(this.profile, profile); ++ this.profile = profile; ++ } ++ } ++ ++ if ((profile.getName() == null || !hasTextures()) && profile.getId() != null) { ++ GameProfile profile = userCache.get(this.profile.getId()); ++ if (profile != null) { ++ if (this.profile.getName() == null) { ++ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't ++ copyProfileProperties(this.profile, profile); ++ this.profile = profile; ++ } else { ++ copyProfileProperties(profile, this.profile); ++ } ++ } ++ } ++ return this.profile.isComplete(); ++ } ++ ++ public boolean complete(boolean textures) { ++ MinecraftServer server = MinecraftServer.getServer(); ++ return complete(textures, PaperConfig.isProxyOnlineMode()); ++ } ++ public boolean complete(boolean textures, boolean onlineMode) { ++ MinecraftServer server = MinecraftServer.getServer(); ++ ++ boolean isCompleteFromCache = this.completeFromCache(true, onlineMode); ++ if (onlineMode && (!isCompleteFromCache || textures && !hasTextures())) { ++ GameProfile result = server.getSessionService().fillProfileProperties(profile, true); ++ if (result != null) { ++ copyProfileProperties(result, this.profile, true); ++ } ++ if (this.profile.isComplete()) { ++ server.getProfileCache().saveProfile(this.profile); ++ } ++ } ++ return profile.isComplete() && (!onlineMode || !textures || hasTextures()); ++ } ++ ++ private static void copyProfileProperties(GameProfile source, GameProfile target) { ++ copyProfileProperties(source, target, false); ++ } ++ ++ private static void copyProfileProperties(GameProfile source, GameProfile target, boolean clearTarget) { ++ PropertyMap sourceProperties = source.getProperties(); ++ PropertyMap targetProperties = target.getProperties(); ++ if (clearTarget) targetProperties.clear(); ++ if (sourceProperties.isEmpty()) { ++ return; ++ } ++ ++ for (Property property : sourceProperties.values()) { ++ targetProperties.removeAll(property.getName()); ++ targetProperties.put(property.getName(), property); ++ } ++ } ++ ++ private static ProfileProperty toBukkit(Property property) { ++ return new ProfileProperty(property.getName(), property.getValue(), property.getSignature()); ++ } ++ ++ public static PlayerProfile asBukkitCopy(GameProfile gameProfile) { ++ CraftPlayerProfile profile = new CraftPlayerProfile(gameProfile.getId(), gameProfile.getName()); ++ copyProfileProperties(gameProfile, profile.profile); ++ return profile; ++ } ++ ++ public static PlayerProfile asBukkitMirror(GameProfile profile) { ++ return new CraftPlayerProfile(profile); ++ } ++ ++ public static Property asAuthlib(ProfileProperty property) { ++ return new Property(property.getName(), property.getValue(), property.getSignature()); ++ } ++ ++ public static GameProfile asAuthlibCopy(PlayerProfile profile) { ++ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); ++ return asAuthlib(craft.clone()); ++ } ++ ++ public static GameProfile asAuthlib(PlayerProfile profile) { ++ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); ++ return craft.getGameProfile(); ++ } ++ ++ private class PropertySet extends AbstractSet { ++ ++ @Override ++ @Nonnull ++ public Iterator iterator() { ++ return new ProfilePropertyIterator(profile.getProperties().values().iterator()); ++ } ++ ++ @Override ++ public int size() { ++ return profile.getProperties().size(); ++ } ++ ++ @Override ++ public boolean add(ProfileProperty property) { ++ setProperty(property); ++ return true; ++ } ++ ++ @Override ++ public boolean addAll(Collection c) { ++ //noinspection unchecked ++ setProperties((Collection) c); ++ return true; ++ } ++ ++ @Override ++ public boolean contains(Object o) { ++ return o instanceof ProfileProperty && profile.getProperties().containsKey(((ProfileProperty) o).getName()); ++ } ++ ++ private class ProfilePropertyIterator implements Iterator { ++ private final Iterator iterator; ++ ++ ProfilePropertyIterator(Iterator iterator) { ++ this.iterator = iterator; ++ } ++ ++ @Override ++ public boolean hasNext() { ++ return iterator.hasNext(); ++ } ++ ++ @Override ++ public ProfileProperty next() { ++ return toBukkit(iterator.next()); ++ } ++ ++ @Override ++ public void remove() { ++ iterator.remove(); ++ } ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d64d45eb01c65864fca1077982d89bc05e0f811b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java +@@ -0,0 +1,31 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.mojang.authlib.*; ++import com.mojang.authlib.minecraft.MinecraftSessionService; ++import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; ++import com.mojang.authlib.yggdrasil.YggdrasilEnvironment; ++ ++import java.net.Proxy; ++ ++public class PaperAuthenticationService extends YggdrasilAuthenticationService { ++ private final Environment environment; ++ public PaperAuthenticationService(Proxy proxy) { ++ super(proxy); ++ this.environment = (Environment)EnvironmentParser.getEnvironmentFromProperties().orElse(YggdrasilEnvironment.PROD);; ++ } ++ ++ @Override ++ public UserAuthentication createUserAuthentication(Agent agent) { ++ return new PaperUserAuthentication(this, agent); ++ } ++ ++ @Override ++ public MinecraftSessionService createMinecraftSessionService() { ++ return new PaperMinecraftSessionService(this, this.environment); ++ } ++ ++ @Override ++ public GameProfileRepository createProfileRepository() { ++ return new PaperGameProfileRepository(this, this.environment); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java +new file mode 100644 +index 0000000000000000000000000000000000000000..582c169c85ac66f1f9430f79042e4655f776c157 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java +@@ -0,0 +1,18 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.mojang.authlib.Agent; ++import com.mojang.authlib.Environment; ++import com.mojang.authlib.ProfileLookupCallback; ++import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; ++import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; ++ ++public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { ++ public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { ++ super(authenticationService, environment); ++ } ++ ++ @Override ++ public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { ++ super.findProfilesByNames(names, agent, callback); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java +new file mode 100644 +index 0000000000000000000000000000000000000000..93d73c27340645c7502acafdc0b2cfbc1a759dd8 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java +@@ -0,0 +1,30 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.mojang.authlib.Environment; ++import com.mojang.authlib.GameProfile; ++import com.mojang.authlib.minecraft.MinecraftProfileTexture; ++import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; ++import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; ++ ++import java.util.Map; ++ ++public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionService { ++ protected PaperMinecraftSessionService(YggdrasilAuthenticationService authenticationService, Environment environment) { ++ super(authenticationService, environment); ++ } ++ ++ @Override ++ public Map getTextures(GameProfile profile, boolean requireSecure) { ++ return super.getTextures(profile, requireSecure); ++ } ++ ++ @Override ++ public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { ++ return super.fillProfileProperties(profile, requireSecure); ++ } ++ ++ @Override ++ protected GameProfile fillGameProfile(GameProfile profile, boolean requireSecure) { ++ return super.fillGameProfile(profile, requireSecure); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3cdd06d3af7ff94f1fe1a11b9a9275e17c695a38 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java +@@ -0,0 +1,12 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.mojang.authlib.Agent; ++import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; ++import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; ++import java.util.UUID; ++ ++public class PaperUserAuthentication extends YggdrasilUserAuthentication { ++ public PaperUserAuthentication(YggdrasilAuthenticationService authenticationService, Agent agent) { ++ super(authenticationService, UUID.randomUUID().toString(), agent); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index d29fe67b7d39e368a873368a6be16042429e9209..68c3f069f8f832ab3d146748348aded69b5ad823 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -1,6 +1,8 @@ + package net.minecraft.server; + + import com.destroystokyo.paper.block.TargetBlockInfo; ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; + import com.google.common.util.concurrent.ThreadFactoryBuilder; + import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; + import net.minecraft.core.BlockPos; +@@ -11,6 +13,7 @@ import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.Level; + import org.apache.commons.lang.exception.ExceptionUtils; ++import com.mojang.authlib.GameProfile; + import org.bukkit.Location; + import org.bukkit.block.BlockFace; + import org.bukkit.craftbukkit.CraftWorld; +@@ -345,6 +348,10 @@ public final class MCUtil { + return run.get(); + } + ++ public static PlayerProfile toBukkit(GameProfile profile) { ++ return CraftPlayerProfile.asBukkitMirror(profile); ++ } ++ + /** + * Calculates distance between 2 entities + * @param e1 +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 5d83a8d4c69144219219877c521c364d912d2452..2bfc54941ec34c75c2d59bda748c75730b9951f7 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -124,7 +124,7 @@ public class Main { + } + + File file = (File) optionset.valueOf("universe"); // CraftBukkit +- YggdrasilAuthenticationService yggdrasilauthenticationservice = new YggdrasilAuthenticationService(Proxy.NO_PROXY); ++ YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper + MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); + GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); + GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName())); +diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java +index e8af352f813a5015d216fc590190ae8fdb03f77d..941b7e356c377fd8ad4e27409cd74c0046878396 100644 +--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java ++++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +@@ -45,7 +45,7 @@ public class GameProfileCache { + + private static final Logger LOGGER = LogManager.getLogger(); + private static boolean usesAuthentication; +- private final Map profilesByName = Maps.newConcurrentMap(); ++ private final Map profilesByName = Maps.newConcurrentMap();private final Map nameCache = profilesByName; // Paper - OBFHELPER // Paper + private final Map profilesByUUID = Maps.newConcurrentMap(); + private final GameProfileRepository profileRepository; + private final Gson gson = (new GsonBuilder()).create(); +@@ -110,6 +110,7 @@ public class GameProfileCache { + return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper + } + ++ public void saveProfile(GameProfile gameprofile) { add(gameprofile); } // Paper - OBFHELPER + public synchronized void add(GameProfile gameprofile) { // Paper - synchronize + Calendar calendar = Calendar.getInstance(); + +@@ -159,6 +160,13 @@ public class GameProfileCache { + return gameprofile; + } + ++ // Paper start ++ @Nullable public GameProfile getProfileIfCached(String name) { ++ GameProfileCache.GameProfileInfo entry = this.nameCache.get(name.toLowerCase(Locale.ROOT)); ++ return entry == null ? null : entry.getProfile(); ++ } ++ // Paper end ++ + @Nullable + public GameProfile get(UUID uuid) { + GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); +@@ -341,7 +349,7 @@ public class GameProfileCache { + + static class GameProfileInfo { + +- private final GameProfile profile; ++ private final GameProfile profile;public GameProfile getProfile() { return profile; } // Paper - OBFHELPER + private final Date expirationDate; + private volatile long lastAccess; + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index b9e39a4c0aea3de96d1774ae0d0d23ff82162c7e..df68599520189e2699c8521d6c6ab7235612af33 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -223,6 +223,9 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; + + import net.md_5.bungee.api.chat.BaseComponent; // Spigot + ++import javax.annotation.Nullable; // Paper ++import javax.annotation.Nonnull; // Paper ++ + public final class CraftServer implements Server { + private final String serverName = "Paper"; // Paper + private final String serverVersion; +@@ -2315,5 +2318,24 @@ public final class CraftServer implements Server { + public boolean suggestPlayerNamesWhenNullTabCompletions() { + return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; + } ++ ++ @Override ++ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { ++ return createProfile(uuid, null); ++ } ++ ++ @Override ++ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull String name) { ++ return createProfile(null, name); ++ } ++ ++ @Override ++ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { ++ Player player = uuid != null ? Bukkit.getPlayer(uuid) : (name != null ? Bukkit.getPlayerExact(name) : null); ++ if (player != null) { ++ return new com.destroystokyo.paper.profile.CraftPlayerProfile((CraftPlayer)player); ++ } ++ return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +index 313ddd6b64e395a8caab77b3da005e52006ab2d7..750661540f55d3c59119dcc909e706e571a2123b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +@@ -80,6 +80,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + } + + private void setProfile(GameProfile profile) { ++ // Paper start ++ if (profile != null) { ++ com.destroystokyo.paper.profile.CraftPlayerProfile paperProfile = new com.destroystokyo.paper.profile.CraftPlayerProfile(profile); ++ paperProfile.completeFromCache(false, true); ++ profile = paperProfile.getGameProfile(); ++ } ++ // Paper end + this.profile = profile; + this.serializedProfile = (profile == null) ? null : NbtUtils.writeGameProfile(new CompoundTag(), profile); + } diff --git a/patches/server-remapped/0153-Shoulder-Entities-Release-API.patch b/patches/server-remapped/0153-Shoulder-Entities-Release-API.patch new file mode 100644 index 0000000000..e71eeed527 --- /dev/null +++ b/patches/server-remapped/0153-Shoulder-Entities-Release-API.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 17 Jun 2017 15:18:30 -0400 +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 ae10c531ae69eaf6b78a342dcedb89c39fd8dbcc..3205bc2fb6c9031be68ff46dfca927e681163fa8 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1877,20 +1877,44 @@ public abstract class Player extends LivingEntity { + + } + ++ // Paper start ++ public Entity releaseLeftShoulderEntity() { ++ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityLeft()); ++ if (entity != null) { ++ this.setShoulderEntityLeft(new CompoundTag()); ++ } ++ return entity; ++ } ++ ++ public Entity releaseRightShoulderEntity() { ++ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityRight()); ++ if (entity != null) { ++ this.setShoulderEntityRight(new CompoundTag()); ++ } ++ return entity; ++ } ++ // Paper - maintain old signature + private boolean spawnEntityFromShoulder(CompoundTag nbttagcompound) { // CraftBukkit void->boolean +- if (!this.level.isClientSide && !nbttagcompound.isEmpty()) { ++ return spawnEntityFromShoulder0(nbttagcompound) != null; ++ } ++ ++ // Paper - return entity ++ private Entity spawnEntityFromShoulder0(@Nullable CompoundTag nbttagcompound) { ++ if (!this.level.isClientSide && nbttagcompound != null && !nbttagcompound.isEmpty()) { + return EntityType.create(nbttagcompound, this.level).map((entity) -> { // CraftBukkit + if (entity instanceof TamableAnimal) { + ((TamableAnimal) entity).setOwnerUUID(this.uuid); + } + + entity.setPos(this.getX(), this.getY() + 0.699999988079071D, this.getZ()); +- return ((ServerLevel) this.level).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit +- }).orElse(true); // CraftBukkit ++ boolean addedToWorld = ((ServerLevel) this.level).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit ++ return addedToWorld ? entity : null; ++ }).orElse(null); // CraftBukkit // Paper - false -> null + } + +- return true; // CraftBukkit ++ return null; // Paper - return null + } ++ // Paper end + + @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 b5c0f3d91cf451a972f0cf293db03a306073c493..c62d01719f21762aa10294815ab88e450e4dce3f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -494,6 +494,32 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + getHandle().getCooldowns().addCooldown(CraftMagicNumbers.getItem(material), ticks); + } + ++ // Paper start ++ @Override ++ public org.bukkit.entity.Entity releaseLeftShoulderEntity() { ++ if (!getHandle().getShoulderEntityLeft().isEmpty()) { ++ Entity entity = getHandle().releaseLeftShoulderEntity(); ++ if (entity != null) { ++ return entity.getBukkitEntity(); ++ } ++ } ++ ++ return null; ++ } ++ ++ @Override ++ public org.bukkit.entity.Entity releaseRightShoulderEntity() { ++ if (!getHandle().getShoulderEntityRight().isEmpty()) { ++ Entity entity = getHandle().releaseRightShoulderEntity(); ++ if (entity != null) { ++ return entity.getBukkitEntity(); ++ } ++ } ++ ++ return null; ++ } ++ // Paper end ++ + @Override + public boolean discoverRecipe(NamespacedKey recipe) { + return discoverRecipes(Arrays.asList(recipe)) != 0; diff --git a/patches/server-remapped/0154-Profile-Lookup-Events.patch b/patches/server-remapped/0154-Profile-Lookup-Events.patch new file mode 100644 index 0000000000..a9a4210f19 --- /dev/null +++ b/patches/server-remapped/0154-Profile-Lookup-Events.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 17 Jun 2017 17:00:32 -0400 +Subject: [PATCH] Profile Lookup Events + +Adds a Pre Lookup Event and a Post Lookup Event so that plugins may prefill in profile data, and cache the responses from +profiles that had to be looked up. + +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java +index 582c169c85ac66f1f9430f79042e4655f776c157..08fdb681a68e8be6e4062af0630957ce3e524806 100644 +--- a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java +@@ -1,11 +1,16 @@ + package com.destroystokyo.paper.profile; + ++import com.destroystokyo.paper.event.profile.LookupProfileEvent; ++import com.destroystokyo.paper.event.profile.PreLookupProfileEvent; ++import com.google.common.collect.Sets; + import com.mojang.authlib.Agent; + import com.mojang.authlib.Environment; ++import com.mojang.authlib.GameProfile; + import com.mojang.authlib.ProfileLookupCallback; + import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; + import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; + ++import java.util.Set; + public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { + public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { + super(authenticationService, environment); +@@ -13,6 +18,50 @@ public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { + + @Override + public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { +- super.findProfilesByNames(names, agent, callback); ++ Set unfoundNames = Sets.newHashSet(); ++ for (String name : names) { ++ PreLookupProfileEvent event = new PreLookupProfileEvent(name); ++ event.callEvent(); ++ if (event.getUUID() != null) { ++ // Plugin provided UUI, we can skip network call. ++ GameProfile gameprofile = new GameProfile(event.getUUID(), name); ++ // We might even have properties! ++ Set profileProperties = event.getProfileProperties(); ++ if (!profileProperties.isEmpty()) { ++ for (ProfileProperty property : profileProperties) { ++ gameprofile.getProperties().put(property.getName(), CraftPlayerProfile.asAuthlib(property)); ++ } ++ } ++ callback.onProfileLookupSucceeded(gameprofile); ++ } else { ++ unfoundNames.add(name); ++ } ++ } ++ ++ // Some things were not found.... Proceed to look up. ++ if (!unfoundNames.isEmpty()) { ++ String[] namesArr = unfoundNames.toArray(new String[unfoundNames.size()]); ++ super.findProfilesByNames(namesArr, agent, new PreProfileLookupCallback(callback)); ++ } ++ } ++ ++ private static class PreProfileLookupCallback implements ProfileLookupCallback { ++ private final ProfileLookupCallback callback; ++ ++ PreProfileLookupCallback(ProfileLookupCallback callback) { ++ this.callback = callback; ++ } ++ ++ @Override ++ public void onProfileLookupSucceeded(GameProfile gameProfile) { ++ PlayerProfile from = CraftPlayerProfile.asBukkitMirror(gameProfile); ++ new LookupProfileEvent(from).callEvent(); ++ callback.onProfileLookupSucceeded(gameProfile); ++ } ++ ++ @Override ++ public void onProfileLookupFailed(GameProfile gameProfile, Exception e) { ++ callback.onProfileLookupFailed(gameProfile, e); ++ } + } + } diff --git a/patches/server-remapped/0155-Block-player-logins-during-server-shutdown.patch b/patches/server-remapped/0155-Block-player-logins-during-server-shutdown.patch new file mode 100644 index 0000000000..f43b561da9 --- /dev/null +++ b/patches/server-remapped/0155-Block-player-logins-during-server-shutdown.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 2 Jul 2017 21:35:56 -0500 +Subject: [PATCH] Block player logins during server shutdown + + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index e3c1460c580ea348ee6d436018244441a5a1206e..fca291c34c67d552590320c6e6e9c08e21d19fa8 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -66,6 +66,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + + public void tick() { ++ // Paper start - Do not allow logins while the server is shutting down ++ if (!MinecraftServer.getServer().isRunning()) { ++ this.disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(org.spigotmc.SpigotConfig.restartMessage)[0]); ++ return; ++ } ++ // Paper end + if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) { + this.handleAcceptedLogin(); + } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { diff --git a/patches/server-remapped/0156-Entity-fromMobSpawner.patch b/patches/server-remapped/0156-Entity-fromMobSpawner.patch new file mode 100644 index 0000000000..10fa81134b --- /dev/null +++ b/patches/server-remapped/0156-Entity-fromMobSpawner.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 18 Jun 2017 18:17:05 -0500 +Subject: [PATCH] Entity#fromMobSpawner() + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a017fa55002d6674124befa3f6e81eb70c9ce8f7..7e70bae5bc54ad17980789fa965fd539a7f193ea 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -267,6 +267,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; + public long activatedTick = Integer.MIN_VALUE; ++ public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one + protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end +@@ -1665,6 +1666,10 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); + tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); + } ++ // Save entity's from mob spawner status ++ if (spawnedViaMobSpawner) { ++ tag.putBoolean("Paper.FromMobSpawner", true); ++ } + // Paper end + return tag; + } catch (Throwable throwable) { +@@ -1797,6 +1802,8 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); + } ++ ++ spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status + // Paper end + + } catch (Throwable throwable) { +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index ed631d5bfba5d2543e8eed017a7c484ad3ddb453..7541155048744a9af2017ec039cf99a246addb0b 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -160,6 +160,7 @@ public abstract class BaseSpawner { + } + // Spigot End + } ++ entity.spawnedViaMobSpawner = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { + Entity vehicle = entity.getVehicle(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index b028946de7c8f52091635fe154c816453f1ddc93..ecb5f5ca547930f91602d539e541964cd9f10287 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1100,5 +1100,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + Location origin = getHandle().origin; + return origin == null ? null : origin.clone(); + } ++ ++ @Override ++ public boolean fromMobSpawner() { ++ return getHandle().spawnedViaMobSpawner; ++ } + // Paper end + } diff --git a/patches/server-remapped/0157-Improve-the-Saddle-API-for-Horses.patch b/patches/server-remapped/0157-Improve-the-Saddle-API-for-Horses.patch new file mode 100644 index 0000000000..85d5e4f330 --- /dev/null +++ b/patches/server-remapped/0157-Improve-the-Saddle-API-for-Horses.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 10 Dec 2016 16:24:06 -0500 +Subject: [PATCH] Improve the Saddle API for Horses + +Not all horses with Saddles have armor. This lets us break up the horses with saddles +and access their saddle state separately from an interface shared with Armor. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +index 116553ea587ab5ff3bc8a1530f51cd6efb7ae8ca..6136b3322a340d506ce744bcd15f71a158e46ad1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +@@ -5,6 +5,7 @@ import net.minecraft.world.entity.ai.attributes.Attributes; + import org.apache.commons.lang.Validate; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.inventory.CraftInventoryAbstractHorse; ++import org.bukkit.craftbukkit.inventory.CraftSaddledInventory; + import org.bukkit.entity.AbstractHorse; + import org.bukkit.entity.AnimalTamer; + import org.bukkit.entity.Horse; +@@ -98,6 +99,6 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac + + @Override + public AbstractHorseInventory getInventory() { +- return new CraftInventoryAbstractHorse(getHandle().inventory); ++ return new CraftSaddledInventory(getHandle().inventory); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java +index 7013059856c2471dc34112a1a2068b96b809dd96..b72b4260fc1c0e9928d70f97589d8db00849b9e8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java +@@ -4,7 +4,7 @@ import net.minecraft.world.Container; + import org.bukkit.inventory.HorseInventory; + import org.bukkit.inventory.ItemStack; + +-public class CraftInventoryHorse extends CraftInventoryAbstractHorse implements HorseInventory { ++public class CraftInventoryHorse extends CraftSaddledInventory implements HorseInventory { + + public CraftInventoryHorse(Container inventory) { + super(inventory); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3a617c07d445bacf5a13e0e3ff6481823cfc8477 +--- /dev/null ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java +@@ -0,0 +1,12 @@ ++package org.bukkit.craftbukkit.inventory; ++ ++import net.minecraft.world.Container; ++import org.bukkit.inventory.SaddledHorseInventory; ++ ++public class CraftSaddledInventory extends CraftInventoryAbstractHorse implements SaddledHorseInventory { ++ ++ public CraftSaddledInventory(Container inventory) { ++ super(inventory); ++ } ++ ++} diff --git a/patches/server-remapped/0158-Implement-ensureServerConversions-API.patch b/patches/server-remapped/0158-Implement-ensureServerConversions-API.patch new file mode 100644 index 0000000000..bc3d68abd4 --- /dev/null +++ b/patches/server-remapped/0158-Implement-ensureServerConversions-API.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 May 2016 22:43:12 -0400 +Subject: [PATCH] Implement ensureServerConversions API + +This will take a Bukkit ItemStack and run it through any conversions a server process would perform on it, +to ensure it meets latest minecraft expectations. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index 32fa5ca0df07466e40817341d85d359b282f3078..41c8bbf93039add43695a52d2bfc0c2cef88463d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -346,5 +346,11 @@ public final class CraftItemFactory implements ItemFactory { + public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { + return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); + } ++ ++ // Paper start ++ @Override ++ public ItemStack ensureServerConversions(ItemStack item) { ++ return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); ++ } + // Paper end + } diff --git a/patches/server-remapped/0159-Implement-getI18NDisplayName.patch b/patches/server-remapped/0159-Implement-getI18NDisplayName.patch new file mode 100644 index 0000000000..c27fb916c9 --- /dev/null +++ b/patches/server-remapped/0159-Implement-getI18NDisplayName.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 May 2016 23:59:38 -0400 +Subject: [PATCH] Implement getI18NDisplayName + +Gets the Display name as seen in the Client. +Currently the server only supports the English language. To override this, +You must replace the language file embedded in the server jar. + +diff --git a/src/main/java/net/minecraft/locale/Language.java b/src/main/java/net/minecraft/locale/Language.java +index 8a0d2e510aee160ec3a817fd72c23bc9dfeb6287..756b78a7dc3d3e76dc0a37375b304db0b6ecf684 100644 +--- a/src/main/java/net/minecraft/locale/Language.java ++++ b/src/main/java/net/minecraft/locale/Language.java +@@ -30,7 +30,7 @@ public abstract class Language { + + private static Language loadDefault() { + Builder builder = ImmutableMap.builder(); +- BiConsumer biconsumer = builder::put; ++ BiConsumer biconsumer = builder::put; // Paper - decompile fix + + try { + InputStream inputstream = Language.class.getResourceAsStream("/assets/minecraft/lang/en_us.json"); +@@ -87,10 +87,12 @@ public abstract class Language { + + } + ++ public static Language getInstance() { return getInstance(); } // Paper - OBFHELPER + public static Language getInstance() { + return Language.instance; + } + ++ public String translateKey(String key) { return getOrDefault(key); } // Paper - OBFHELPER + public abstract String getOrDefault(String key); + + public abstract boolean has(String key); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index 41c8bbf93039add43695a52d2bfc0c2cef88463d..746755f76ae177b2eeccf66f8cd95e6ffd5acad9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -352,5 +352,18 @@ public final class CraftItemFactory implements ItemFactory { + public ItemStack ensureServerConversions(ItemStack item) { + return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); + } ++ ++ @Override ++ public String getI18NDisplayName(ItemStack item) { ++ net.minecraft.world.item.ItemStack nms = null; ++ if (item instanceof CraftItemStack) { ++ nms = ((CraftItemStack) item).handle; ++ } ++ if (nms == null) { ++ nms = CraftItemStack.asNMSCopy(item); ++ } ++ ++ return nms != null ? net.minecraft.locale.Language.getInstance().translateKey(nms.getItem().getDescriptionId()) : null; ++ } + // Paper end + } diff --git a/patches/server-remapped/0160-ProfileWhitelistVerifyEvent.patch b/patches/server-remapped/0160-ProfileWhitelistVerifyEvent.patch new file mode 100644 index 0000000000..5051a6a195 --- /dev/null +++ b/patches/server-remapped/0160-ProfileWhitelistVerifyEvent.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 3 Jul 2017 18:11:10 -0500 +Subject: [PATCH] ProfileWhitelistVerifyEvent + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7d6256f65d369fcbcfe1fffe7ac264788a38540b..ae60b233c4d56a4964b388f96e9cc66410774e8d 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -611,9 +611,9 @@ public abstract class PlayerList { + + // return chatmessage; + if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure +- } else if (!this.isWhiteListed(gameprofile)) { +- chatmessage = new TranslatableComponent("multiplayer.disconnect.not_whitelisted"); +- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure ++ } else if (!this.isWhitelisted(gameprofile, event)) { // Paper ++ //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper ++ //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted + } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { + IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); + +@@ -1005,9 +1005,25 @@ public abstract class PlayerList { + this.server.getCommands().sendCommands(player); + } + ++ // Paper start + public boolean isWhiteListed(GameProfile profile) { +- return !this.doWhiteList || this.ops.contains(profile) || this.whitelist.contains(profile); ++ return isWhitelisted(profile, null); + } ++ public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { ++ boolean isOp = this.ops.contains(gameprofile); ++ boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile); ++ final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; ++ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); ++ event.callEvent(); ++ if (!event.isWhitelisted()) { ++ if (loginEvent != null) { ++ loginEvent.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getKickMessage() == null ? org.spigotmc.SpigotConfig.whitelistMessage : event.getKickMessage())); ++ } ++ return false; ++ } ++ return true; ++ } ++ // Paper end + + public boolean isOp(GameProfile profile) { + return this.ops.contains(profile) || this.server.isSingleplayerOwner(profile) && this.server.getWorldData().getAllowCommands() || this.allowCheatsForAllPlayers; diff --git a/patches/server-remapped/0161-Fix-this-stupid-bullshit.patch b/patches/server-remapped/0161-Fix-this-stupid-bullshit.patch new file mode 100644 index 0000000000..8eacc81f8c --- /dev/null +++ b/patches/server-remapped/0161-Fix-this-stupid-bullshit.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DemonWav +Date: Sun, 6 Aug 2017 17:17:53 -0500 +Subject: [PATCH] Fix this stupid bullshit + +Disable the 15 second sleep when the server jar hasn't been rebuilt within a period of time. + +modified in order to prevent merge conflicts when Spigot changes/disables the warning, +and to provide some level of hint without being disruptive. + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 60d9980ccca6f1ac55b70f7684b917ddceac380a..808a7688ed81bdfef623ee0a151ff8f94df2a3d7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -224,10 +224,12 @@ public class Main { + Calendar deadline = Calendar.getInstance(); + deadline.add(Calendar.DAY_OF_YEAR, -28); + if (buildDate.before(deadline.getTime())) { +- System.err.println("*** Error, this build is outdated ***"); ++ // Paper start - This is some stupid bullshit ++ System.err.println("*** Warning, you've not updated in a while! ***"); + System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper +- System.err.println("*** Server will start in 20 seconds ***"); +- Thread.sleep(TimeUnit.SECONDS.toMillis(20)); ++ //System.err.println("*** Server will start in 20 seconds ***"); ++ //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); ++ // Paper End + } + } + diff --git a/patches/server-remapped/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch b/patches/server-remapped/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch new file mode 100644 index 0000000000..07571c80e4 --- /dev/null +++ b/patches/server-remapped/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 31 Jul 2017 01:54:40 -0500 +Subject: [PATCH] Ocelot despawns should honor nametags and leash + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java +index 1b820ca48845cbe4a668cc31582c2ddf6d50c96a..142025cfb75b24dc6df8160f4922086404efa6a7 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java +@@ -128,7 +128,7 @@ public class Ocelot extends Animal { + + @Override + public boolean removeWhenFarAway(double distanceSquared) { +- return !this.isTrusting() /*&& this.ticksLived > 2400*/; // CraftBukkit ++ return !this.isTrusting() && !this.hasCustomName() && !this.isLeashed() /*&& this.ticksLived > 2400*/; // CraftBukkit // Paper - honor name and leash + } + + public static AttributeSupplier.Builder createAttributes() { diff --git a/patches/server-remapped/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/patches/server-remapped/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch new file mode 100644 index 0000000000..3476f2d837 --- /dev/null +++ b/patches/server-remapped/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 31 Jul 2017 01:45:19 -0500 +Subject: [PATCH] Reset spawner timer when spawner event is cancelled + + +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 7541155048744a9af2017ec039cf99a246addb0b..4582fc1bb767214241568fbc22b0ee2cbf3322e0 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -161,6 +161,7 @@ public abstract class BaseSpawner { + // Spigot End + } + entity.spawnedViaMobSpawner = true; // Paper ++ flag = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { + Entity vehicle = entity.getVehicle(); +@@ -184,7 +185,7 @@ public abstract class BaseSpawner { + ((Mob) entity).spawnAnim(); + } + +- flag = true; ++ /*flag = true;*/ // Paper - moved up above cancellable event + } + } + } diff --git a/patches/server-remapped/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/patches/server-remapped/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch new file mode 100644 index 0000000000..01e55f74f0 --- /dev/null +++ b/patches/server-remapped/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: mezz +Date: Wed, 9 Aug 2017 17:51:22 -0500 +Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index ecb6378a285dff4b34170410387ebb7a8510a6dc..81713c97f35263f4ab8d14f8b707aac3d6afea11 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -726,7 +726,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + gameprofilerfiller.push("blockEntities"); + timings.tileEntityTick.startTiming(); // Spigot + if (!this.tileEntityListUnload.isEmpty()) { +- this.tickableBlockEntities.removeAll(this.tileEntityListUnload); ++ // Paper start - Use alternate implementation with faster contains ++ java.util.Set toRemove = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); ++ toRemove.addAll(tileEntityListUnload); ++ this.tickableBlockEntities.removeAll(toRemove); ++ // Paper end + //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list + this.tileEntityListUnload.clear(); + } diff --git a/patches/server-remapped/0165-Allow-specifying-a-custom-authentication-servers-dow.patch b/patches/server-remapped/0165-Allow-specifying-a-custom-authentication-servers-dow.patch new file mode 100644 index 0000000000..766b536512 --- /dev/null +++ b/patches/server-remapped/0165-Allow-specifying-a-custom-authentication-servers-dow.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Thu, 17 Aug 2017 16:08:20 -0700 +Subject: [PATCH] Allow specifying a custom "authentication servers down" kick + message + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 48319aaf1c525c6fb7bdee5c2f570a0d056d4eae..52954fc3bf932cfc9d5ce63e3d3cace351305790 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -1,5 +1,6 @@ + package com.destroystokyo.paper; + ++import com.google.common.base.Strings; + import com.google.common.base.Throwables; + + import java.io.File; +@@ -273,4 +274,9 @@ public class PaperConfig { + private static void suggestPlayersWhenNull() { + suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); + } ++ ++ public static String authenticationServersDownKickMessage = ""; // empty = use translatable message ++ private static void authenticationServersDownKickMessage() { ++ authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index fca291c34c67d552590320c6e6e9c08e21d19fa8..4b91699ddfa2ee298af5ba25447a85751facf4a4 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -275,6 +275,10 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + ServerLoginPacketListenerImpl.this.gameProfile = ServerLoginPacketListenerImpl.this.createFakeProfile(gameprofile); + ServerLoginPacketListenerImpl.this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT; + } else { ++ // Paper start ++ if (com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage != null) { ++ ServerLoginPacketListenerImpl.this.disconnect(new TextComponent(com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage)); ++ } else // Paper end + ServerLoginPacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.authservers_down")); + ServerLoginPacketListenerImpl.LOGGER.error("Couldn't verify username because servers are unavailable"); + } diff --git a/patches/server-remapped/0166-LivingEntity-setKiller.patch b/patches/server-remapped/0166-LivingEntity-setKiller.patch new file mode 100644 index 0000000000..fdb6acae74 --- /dev/null +++ b/patches/server-remapped/0166-LivingEntity-setKiller.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 31 Jul 2017 01:49:48 -0500 +Subject: [PATCH] LivingEntity#setKiller + + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index c1786fcabeaee5732e9197db04268c5c4e164339..d6b4fabd232958ae1fd5405c7129551951cd7765 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -177,7 +177,7 @@ public abstract class LivingEntity extends Entity { + public float flyingSpeed; + @Nullable + public net.minecraft.world.entity.player.Player lastHurtByPlayer; +- protected int lastHurtByPlayerTime; ++ public int lastHurtByPlayerTime; // Paper - protected -> public + protected boolean dead; + protected int noActionTime; + protected float oRun; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index d8cd88d62f9abfc7960c187dd74239f61267ca57..006f4c71bbcda61b55815e7ceab91731ab062da0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -8,6 +8,7 @@ import java.util.Iterator; + import java.util.List; + import java.util.Set; + import java.util.UUID; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.InteractionHand; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffect; +@@ -332,6 +333,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return getHandle().lastHurtByPlayer == null ? null : (Player) getHandle().lastHurtByPlayer.getBukkitEntity(); + } + ++ // Paper start ++ @Override ++ public void setKiller(Player killer) { ++ ServerPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle(); ++ getHandle().lastHurtByPlayer = entityPlayer; ++ getHandle().lastHurtByMob = entityPlayer; ++ getHandle().lastHurtByPlayerTime = entityPlayer == null ? 0 : 100; // 100 value taken from EntityLiving#damageEntity ++ } ++ // Paper end ++ + @Override + public boolean addPotionEffect(PotionEffect effect) { + return addPotionEffect(effect, false); diff --git a/patches/server-remapped/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch b/patches/server-remapped/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch new file mode 100644 index 0000000000..8c91986ef3 --- /dev/null +++ b/patches/server-remapped/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Thu, 21 Sep 2017 16:14:55 +0200 +Subject: [PATCH] Handle plugin prefixes using Log4J configuration + +Display logger name in the console for all loggers except the +root logger, Bukkit's logger ("Minecraft") and Minecraft loggers. +Since plugins now use the plugin name as logger name this will +restore the plugin prefixes without having to prepend them manually +to the log messages. + +Logger prefixes are shown by default for all loggers except for +the root logger, the Minecraft/Mojang loggers and the Bukkit loggers. +This may cause additional prefixes to be disabled for plugins bypassing +the plugin logger. + +diff --git a/pom.xml b/pom.xml +index 3841fe3630c090f8a468333d43caeb2b5841329d..f5429f2f1979542fd93956d2f436d20d0e3a66b8 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -76,7 +76,7 @@ + + org.apache.logging.log4j + log4j-core +- runtime ++ compile + + + org.apache.logging.log4j +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0083f979933d4a9035efb992ab0a2f250a56a979..3981ba5957fdc2929d54515f2b98bb7a4611e938 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -290,7 +290,7 @@ public class SpigotConfig + private static void playerSample() + { + playerSample = getInt( "settings.sample-count", 12 ); +- System.out.println( "Server Ping Player Sample Count: " + playerSample ); ++ Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger + } + + public static int playerShuffle; +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 620b9490e5f159080e50289d127404a1b56adbef..a8bdaaeaa1a9316848416f0533739b9b083ca151 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -5,10 +5,22 @@ + + + +- ++ ++ ++ ++ ++ ++ + + +- ++ ++ ++ ++ ++ ++ + + + diff --git a/patches/server-remapped/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch b/patches/server-remapped/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch new file mode 100644 index 0000000000..5afb9562c0 --- /dev/null +++ b/patches/server-remapped/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Sat, 23 Sep 2017 21:07:20 +0200 +Subject: [PATCH] Improve Log4J Configuration / Plugin Loggers + +Add full exceptions to log4j to not truncate stack traces + +Disable logger prefix for various plugins bypassing the plugin logger + +Some plugins bypass the plugin logger and add the plugin prefix +manually to the log message. Since they use other logger names +(e.g. qualified class names) these would now also appear in the +log. Disable the logger prefix for these plugins so the messages +show up correctly. + +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index a8bdaaeaa1a9316848416f0533739b9b083ca151..476f4a5cbe664ddd05474cb88553018bd334a5b8 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -6,19 +6,21 @@ + + + +- ++ + +- ++ ++ + + + + + +- ++ + +- ++ ++ + + + diff --git a/patches/server-remapped/0169-Add-PlayerJumpEvent.patch b/patches/server-remapped/0169-Add-PlayerJumpEvent.patch new file mode 100644 index 0000000000..9abed7291f --- /dev/null +++ b/patches/server-remapped/0169-Add-PlayerJumpEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 28 Sep 2017 17:21:44 -0400 +Subject: [PATCH] Add PlayerJumpEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 6a922e3522ac99a8e317a5f5f51fbb597baaf63e..f35a976de39f16d100bcbe411b64de357832c5df 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1166,7 +1166,34 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + boolean flag = d8 > 0.0D; + + if (this.player.isOnGround() && !packet.isOnGround() && flag) { +- this.player.jumpFromGround(); ++ // Paper start - Add player jump event ++ Player player = this.getPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ if (packet.hasPos) { ++ to.setX(packet.x); ++ to.setY(packet.y); ++ to.setZ(packet.z); ++ } ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ if (packet.hasRot) { ++ to.setYaw(packet.yRot); ++ to.setPitch(packet.xRot); ++ } ++ ++ com.destroystokyo.paper.event.player.PlayerJumpEvent event = new com.destroystokyo.paper.event.player.PlayerJumpEvent(player, from, to); ++ ++ if (event.callEvent()) { ++ this.player.jumpFromGround(); ++ } else { ++ from = event.getFrom(); ++ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet()); ++ return; ++ } ++ // Paper end + } + + this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9)); diff --git a/patches/server-remapped/0170-handle-PacketPlayInKeepAlive-async.patch b/patches/server-remapped/0170-handle-PacketPlayInKeepAlive-async.patch new file mode 100644 index 0000000000..1a0b7f3089 --- /dev/null +++ b/patches/server-remapped/0170-handle-PacketPlayInKeepAlive-async.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 5 Oct 2017 01:54:07 +0100 +Subject: [PATCH] handle PacketPlayInKeepAlive async + +In 1.12.2, Mojang moved the processing of PacketPlayInKeepAlive off the main +thread, while entirely correct for the server, this causes issues with +plugins which are expecting the PlayerQuitEvent on the main thread. + +In order to counteract some bad behavior, we will post handling of the +disconnection to the main thread, but leave the actual processing of the packet +off the main thread. + +also adding some additional logging in order to help work out what is causing +random disconnections for clients. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index f35a976de39f16d100bcbe411b64de357832c5df..f0aab8639c7d8440e4d70dd096200313d7958780 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2777,14 +2777,18 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + @Override + public void handleKeepAlive(ServerboundKeepAlivePacket packet) { +- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); // CraftBukkit ++ //PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit // Paper - This shouldn't be on the main thread + if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) { + int i = (int) (Util.getMillis() - this.keepAliveTime); + + this.player.latency = (this.player.latency * 3 + i) / 4; + this.keepAlivePending = false; + } else if (!this.isSingleplayerOwner()) { ++ // Paper start - This needs to be handled on the main thread for plugins ++ server.scheduleOnMain(() -> { + this.disconnect(new TranslatableComponent("disconnect.timeout")); ++ }); ++ // Paper end + } + + } diff --git a/patches/server-remapped/0171-Expose-client-protocol-version-and-virtual-host.patch b/patches/server-remapped/0171-Expose-client-protocol-version-and-virtual-host.patch new file mode 100644 index 0000000000..c18295ef08 --- /dev/null +++ b/patches/server-remapped/0171-Expose-client-protocol-version-and-virtual-host.patch @@ -0,0 +1,128 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Tue, 10 Oct 2017 18:45:20 +0200 +Subject: [PATCH] Expose client protocol version and virtual host + + +diff --git a/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a5a7624f1f372a26b982836cd31cff15e2589e9b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java +@@ -0,0 +1,49 @@ ++package com.destroystokyo.paper.network; ++ ++import java.net.InetSocketAddress; ++ ++import javax.annotation.Nullable; ++import net.minecraft.network.Connection; ++ ++public class PaperNetworkClient implements NetworkClient { ++ ++ private final Connection networkManager; ++ ++ PaperNetworkClient(Connection networkManager) { ++ this.networkManager = networkManager; ++ } ++ ++ @Override ++ public InetSocketAddress getAddress() { ++ return (InetSocketAddress) this.networkManager.getRemoteAddress(); ++ } ++ ++ @Override ++ public int getProtocolVersion() { ++ return this.networkManager.protocolVersion; ++ } ++ ++ @Nullable ++ @Override ++ public InetSocketAddress getVirtualHost() { ++ return this.networkManager.virtualHost; ++ } ++ ++ public static InetSocketAddress prepareVirtualHost(String host, int port) { ++ int len = host.length(); ++ ++ // FML appends a marker to the host to recognize FML clients (\0FML\0) ++ int pos = host.indexOf('\0'); ++ if (pos >= 0) { ++ len = pos; ++ } ++ ++ // When clients connect with a SRV record, their host contains a trailing '.' ++ if (len > 0 && host.charAt(len - 1) == '.') { ++ len--; ++ } ++ ++ return InetSocketAddress.createUnresolved(host.substring(0, len), port); ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 92c5c5bbcfe364475578b6a0eddfaa85858ace8a..3429c813a5b471cdfa561bd20849a303e5aacead 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -70,6 +70,10 @@ public class Connection extends SimpleChannelInboundHandler> { + private float averageSentPackets; + private int tickCount; + private boolean handlingFault; ++ // Paper start - NetworkClient implementation ++ public int protocolVersion; ++ public java.net.InetSocketAddress virtualHost; ++ // Paper end + + public Connection(PacketFlow side) { + this.receiving = side; +diff --git a/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java b/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java +index 1eae2999ecc57f68ac9cd1d745191cba617b0de2..9ad400b15a2eb2d80bc763de28d648e22432b8f2 100644 +--- a/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java +@@ -39,6 +39,7 @@ public class ClientIntentionPacket implements Packet +Date: Sun, 15 Oct 2017 00:29:07 +0100 +Subject: [PATCH] revert serverside behavior of keepalives + +This patch intends to bump up the time that a client has to reply to the +server back to 30 seconds as per pre 1.12.2, which allowed clients +more than enough time to reply potentially allowing them to be less +tempermental due to lag spikes on the network thread, e.g. that caused +by plugins that are interacting with netty. + +We also add a system property to allow people to tweak how long the server +will wait for a reply. There is a compromise here between lower and higher +values, lower values will mean that dead connections can be closed sooner, +whereas higher values will make this less sensitive to issues such as spikes +from networking or during connections flood of chunk packets on slower clients, + at the cost of dead connections being kept open for longer. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index f0aab8639c7d8440e4d70dd096200313d7958780..525728268f56470fdc24c4fd2f19d66943447778 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -221,7 +221,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private final MinecraftServer server; + public ServerPlayer player; + private int tickCount; +- private long keepAliveTime; private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER ++ private long keepAliveTime = Util.getMillis(); private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER + private boolean keepAlivePending; private void setPendingPing(boolean isPending) { this.keepAlivePending = isPending;}; private boolean isPendingPing() { return this.keepAlivePending;}; // Paper - OBFHELPER + private long keepAliveChallenge; private void setKeepAliveID(long keepAliveID) { this.keepAliveChallenge = keepAliveID;}; private long getKeepAliveID() {return this.keepAliveChallenge; }; // Paper - OBFHELPER + // CraftBukkit start - multithreaded fields +@@ -252,6 +252,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private int aboveGroundVehicleTickCount; + private int receivedMovePacketCount; + private int knownMovePacketCount; ++ private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit + + public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { + this.server = server; +@@ -338,18 +339,25 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + + this.server.getProfiler().push("keepAlive"); +- long i = Util.getMillis(); +- +- if (i - this.keepAliveTime >= 25000L) { // CraftBukkit +- if (this.keepAlivePending) { +- this.disconnect(new TranslatableComponent("disconnect.timeout")); +- } else { +- this.keepAlivePending = true; +- this.keepAliveTime = i; +- this.keepAliveChallenge = i; +- this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge)); ++ // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings ++ // This should effectively place the keepalive handling back to "as it was" before 1.12.2 ++ long currentTime = Util.getMillis(); ++ long elapsedTime = currentTime - this.getLastPing(); ++ ++ if (this.isPendingPing()) { ++ if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected ++ ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info ++ this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0])); ++ } ++ } else { ++ if (elapsedTime >= 15000L) { // 15 seconds ++ this.setPendingPing(true); ++ this.setLastPing(currentTime); ++ this.setKeepAliveID(currentTime); ++ this.send(new ClientboundKeepAlivePacket(this.getKeepAliveID())); + } + } ++ // Paper end + + this.server.getProfiler().pop(); + // CraftBukkit start diff --git a/patches/server-remapped/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch b/patches/server-remapped/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch new file mode 100644 index 0000000000..d30ac6d736 --- /dev/null +++ b/patches/server-remapped/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Tue, 31 Oct 2017 03:26:18 +0100 +Subject: [PATCH] Send attack SoundEffects only to players who can see the + attacker + + +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 3205bc2fb6c9031be68ff46dfca927e681163fa8..43868c1e2d2c858a4f02119c3238f615f9b1ee72 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -28,6 +28,7 @@ import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; ++import net.minecraft.network.protocol.game.ClientboundSoundPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; +@@ -1123,7 +1124,7 @@ public abstract class Player extends LivingEntity { + int i = b0 + EnchantmentHelper.getKnockbackBonus((LivingEntity) this); + + if (this.isSprinting() && flag) { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + ++i; + flag1 = true; + } +@@ -1198,7 +1199,7 @@ public abstract class Player extends LivingEntity { + } + } + +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + this.sweepAttack(); + } + +@@ -1226,15 +1227,15 @@ public abstract class Player extends LivingEntity { + } + + if (flag2) { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + this.crit(target); + } + + if (!flag2 && !flag3) { + if (flag) { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + } else { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + } + } + +@@ -1286,7 +1287,7 @@ public abstract class Player extends LivingEntity { + + this.applyExhaustion(level.spigotConfig.combatExhaustion, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value + } else { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + if (flag4) { + target.clearFire(); + } +@@ -1721,6 +1722,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); + } ++ // Paper start - send SoundEffect to everyone who can see fromEntity ++ private static void sendSoundEffect(Player fromEntity, double x, double y, double z, SoundEvent soundEffect, SoundSource soundCategory, float volume, float pitch) { ++ fromEntity.level.playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself ++ if (fromEntity instanceof ServerPlayer) { ++ ((ServerPlayer) fromEntity).connection.send(new ClientboundSoundPacket(soundEffect, soundCategory, x, y, z, volume, pitch)); ++ } ++ } ++ // Paper end + + // CraftBukkit start + public void causeFoodExhaustion(float exhaustion) { diff --git a/patches/server-remapped/0174-Option-for-maximum-exp-value-when-merging-orbs.patch b/patches/server-remapped/0174-Option-for-maximum-exp-value-when-merging-orbs.patch new file mode 100644 index 0000000000..c2626fdee4 --- /dev/null +++ b/patches/server-remapped/0174-Option-for-maximum-exp-value-when-merging-orbs.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 10 Nov 2017 23:03:12 -0500 +Subject: [PATCH] Option for maximum exp value when merging orbs + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 90ca51dfdbb3045dd528450225cba96f5834166e..6c692e58cde22003ecbf6dc5695799147c39905a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -342,4 +342,10 @@ public class PaperWorldConfig { + disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); + log("Creeper lingering effect: " + disableCreeperLingeringEffect); + } ++ ++ public int expMergeMaxValue; ++ private void expMergeMaxValue() { ++ expMergeMaxValue = getInt("experience-merge-max-value", -1); ++ log("Experience Merge Max Value: " + expMergeMaxValue); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 3f082b7fd50752728917a7da28cba4cb396a9fdf..7d6834796259e364196280ffa468b5bf999ec7b9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -587,16 +587,32 @@ public class CraftEventFactory { + net.minecraft.world.entity.ExperienceOrb xp = (net.minecraft.world.entity.ExperienceOrb) entity; + double radius = world.spigotConfig.expMerge; + if (radius > 0) { ++ // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics ++ final int maxValue = world.paperConfig.expMergeMaxValue; ++ final boolean mergeUnconditionally = world.paperConfig.expMergeMaxValue <= 0; ++ if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary ++ + List entities = world.getEntities(entity, entity.getBoundingBox().inflate(radius, radius, radius)); + for (Entity e : entities) { + if (e instanceof net.minecraft.world.entity.ExperienceOrb) { + net.minecraft.world.entity.ExperienceOrb loopItem = (net.minecraft.world.entity.ExperienceOrb) e; +- if (!loopItem.removed) { +- xp.value += loopItem.value; +- loopItem.remove(); ++ // Paper start ++ if (!loopItem.removed && !(maxValue > 0 && loopItem.value >= maxValue)) { ++ long newTotal = (long)xp.value + (long)loopItem.value; ++ if ((int) newTotal < 0) continue; // Overflow ++ if (maxValue > 0 && newTotal > (long)maxValue) { ++ loopItem.value = (int) (newTotal - maxValue); ++ xp.value = maxValue; ++ } else { ++ xp.value += loopItem.value; ++ loopItem.remove(); ++ } ++ // Paper end + } + } + } ++ ++ } // Paper end - End iteration skip check - All tweaking ends here + } + // Spigot end + } else if (!(entity instanceof ServerPlayer)) { diff --git a/patches/server-remapped/0175-Add-PlayerArmorChangeEvent.patch b/patches/server-remapped/0175-Add-PlayerArmorChangeEvent.patch new file mode 100644 index 0000000000..ae78b560ac --- /dev/null +++ b/patches/server-remapped/0175-Add-PlayerArmorChangeEvent.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: pkt77 +Date: Fri, 10 Nov 2017 23:46:34 -0500 +Subject: [PATCH] Add PlayerArmorChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/EquipmentSlot.java b/src/main/java/net/minecraft/world/entity/EquipmentSlot.java +index b686b7a2faa4fbce37dcc3598b3c956661b91aaa..17cd5f525a45058ce34c66c87f9c133033bb8f4b 100644 +--- a/src/main/java/net/minecraft/world/entity/EquipmentSlot.java ++++ b/src/main/java/net/minecraft/world/entity/EquipmentSlot.java +@@ -16,6 +16,7 @@ public enum EquipmentSlot { + this.name = s; + } + ++ public EquipmentSlot.Type getType() { return this.getType(); } // Paper - OBFHELPER + public EquipmentSlot.Type getType() { + return this.type; + } +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index d6b4fabd232958ae1fd5405c7129551951cd7765..8b0d1f4fbc43a6f37a5f9c453b5dd142a4f69745 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.entity; + ++import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; // Paper + import com.google.common.base.Objects; + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableMap; +@@ -2643,6 +2644,13 @@ public abstract class LivingEntity extends Entity { + ItemStack itemstack1 = this.getItemBySlot(enumitemslot); + + if (!ItemStack.matches(itemstack1, itemstack)) { ++ // Paper start - PlayerArmorChangeEvent ++ if (this instanceof ServerPlayer && enumitemslot.getType() == EquipmentSlot.Type.ARMOR) { ++ final org.bukkit.inventory.ItemStack oldItem = CraftItemStack.asBukkitCopy(itemstack); ++ final org.bukkit.inventory.ItemStack newItem = CraftItemStack.asBukkitCopy(itemstack1); ++ new PlayerArmorChangeEvent((Player) this.getBukkitEntity(), PlayerArmorChangeEvent.SlotType.valueOf(enumitemslot.name()), oldItem, newItem).callEvent(); ++ } ++ // Paper end + if (map == null) { + map = Maps.newEnumMap(EquipmentSlot.class); + } diff --git a/patches/server-remapped/0176-Prevent-logins-from-being-processed-when-the-player-.patch b/patches/server-remapped/0176-Prevent-logins-from-being-processed-when-the-player-.patch new file mode 100644 index 0000000000..c04d5e61cf --- /dev/null +++ b/patches/server-remapped/0176-Prevent-logins-from-being-processed-when-the-player-.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: killme +Date: Sun, 12 Nov 2017 19:40:01 +0100 +Subject: [PATCH] Prevent logins from being processed when the player has + disconnected + + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 4b91699ddfa2ee298af5ba25447a85751facf4a4..ff83fb15d0d0adb62c630fc7aafc134972bf15fc 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -73,7 +73,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + // Paper end + if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) { +- this.handleAcceptedLogin(); ++ // Paper start - prevent logins to be processed even though disconnect was called ++ if (connection.isConnected()) { ++ this.handleAcceptedLogin(); ++ } ++ // Paper end + } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { + ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); + diff --git a/patches/server-remapped/0177-use-CB-BlockState-implementations-for-captured-block.patch b/patches/server-remapped/0177-use-CB-BlockState-implementations-for-captured-block.patch new file mode 100644 index 0000000000..939a2fed54 --- /dev/null +++ b/patches/server-remapped/0177-use-CB-BlockState-implementations-for-captured-block.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 16 Nov 2017 12:12:41 +0000 +Subject: [PATCH] use CB BlockState implementations for captured blocks + +When modifying the world, CB will store a copy of the affected +blocks in order to restore their state in the case that the event +is cancelled. This change only modifies the collection of blocks +in the world by normal means, e.g. not during tree population, +as the potentially marginal overheads would serve no advantage. + +CB was using a CraftBlockState for all blocks, which causes issues +should any block that uses information beyond a data ID would suffer +from missing information, e.g. Skulls. + +By using CBs CraftBlock#getState(), we will maintain a proper copy of +the blockstate that will be valid for restoration, as opposed to dropping +information on restoration when the event is cancelled. + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 81713c97f35263f4ab8d14f8b707aac3d6afea11..b4248d46ccb1a95e21601bca1198512287edcabf 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -124,7 +124,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + public boolean captureBlockStates = false; + public boolean captureTreeGeneration = false; +- public Map capturedBlockStates = new java.util.LinkedHashMap<>(); ++ public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper + public Map capturedTileEntities = new HashMap<>(); + public List captureDrops; + public long ticksPerAnimalSpawns; +@@ -346,7 +346,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { + // CraftBukkit start - tree generation + if (this.captureTreeGeneration) { +- CapturedBlockState blockstate = capturedBlockStates.get(pos); ++ CraftBlockState blockstate = capturedBlockStates.get(pos); + if (blockstate == null) { + blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); + this.capturedBlockStates.put(pos.immutable(), blockstate); +@@ -366,7 +366,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // CraftBukkit start - capture blockstates + boolean captured = false; + if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) { +- CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, pos, flags); ++ CraftBlockState blockstate = (CraftBlockState) world.getBlockAt(pos.getX(), pos.getY(), pos.getZ()).getState(); // Paper - use CB getState to get a suitable snapshot ++ blockstate.setFlag(flags); // Paper - set flag + this.capturedBlockStates.put(pos.immutable(), blockstate); + captured = true; + } +@@ -624,7 +625,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public BlockState getBlockState(BlockPos pos) { + // CraftBukkit start - tree generation + if (captureTreeGeneration) { +- CapturedBlockState previous = capturedBlockStates.get(pos); ++ CraftBlockState previous = capturedBlockStates.get(pos); // Paper + if (previous != null) { + return previous.getHandle(); + } diff --git a/patches/server-remapped/0178-API-to-get-a-BlockState-without-a-snapshot.patch b/patches/server-remapped/0178-API-to-get-a-BlockState-without-a-snapshot.patch new file mode 100644 index 0000000000..d3837145f0 --- /dev/null +++ b/patches/server-remapped/0178-API-to-get-a-BlockState-without-a-snapshot.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 6 Nov 2017 21:08:22 -0500 +Subject: [PATCH] API to get a BlockState without a snapshot + +This allows you to get a BlockState without creating a snapshot, operating +on the real tile entity. + +This is useful for where performance is needed + +also Avoid NPE during CraftBlockEntityState load if could not get TE + +If Tile Entity was null, correct Sign to return empty lines instead of null + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index d08ed44884726ca2ba4578226b8aa6244778f4c7..84012c2d12817e657b046bc168cc8eddebcd3831 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -47,6 +47,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + public BlockEntity(BlockEntityType type) { + this.worldPosition = BlockPos.ZERO; + this.type = type; ++ persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init + } + + // Paper start +@@ -95,7 +96,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + public void load(BlockState state, CompoundTag tag) { + this.worldPosition = new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); + // CraftBukkit start - read container +- this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ this.persistentDataContainer.clear(); // Paper - clear instead of reinit + + net.minecraft.nbt.Tag persistentDataTag = tag.get("PublicBukkitValues"); + if (persistentDataTag instanceof CompoundTag) { +@@ -245,7 +246,12 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + } + + // CraftBukkit start - add method ++ // Paper start + public InventoryHolder getOwner() { ++ return getOwner(true); ++ } ++ public InventoryHolder getOwner(boolean useSnapshot) { ++ // Paper end + if (level == null) return null; + // Spigot start + org.bukkit.block.Block block = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); +@@ -254,7 +260,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + return null; + } + // Spigot end +- org.bukkit.block.BlockState state = block.getState(); ++ org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper + if (state instanceof InventoryHolder) return (InventoryHolder) state; + return null; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 9d5b3801205e2800b0bcf238c5656321e3654f03..d73086970db19531db66c2e8af52da91d0b1ea28 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -313,6 +313,20 @@ public class CraftBlock implements Block { + + @Override + public BlockState getState() { ++ // Paper start - allow disabling the use of snapshots ++ return getState(true); ++ } ++ public BlockState getState(boolean useSnapshot) { ++ boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT; ++ CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot; ++ try { ++ return getState0(); ++ } finally { ++ CraftBlockEntityState.DISABLE_SNAPSHOT = prev; ++ } ++ } ++ public BlockState getState0() { ++ // Paper end + Material material = getType(); + + switch (material) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +index e89a93082fe07fdb14df8ffef5beca5bd52d7866..730fda7f0bf02400d349959e9cc2aafaed000b21 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +@@ -26,20 +26,40 @@ public class CraftBlockEntityState extends CraftBlockStat + this.tileEntity = tileEntityClass.cast(world.getHandle().getBlockEntity(this.getPosition())); + Preconditions.checkState(this.tileEntity != null, "Tile is null, asynchronous access? %s", block); + ++ // Paper start ++ this.snapshotDisabled = DISABLE_SNAPSHOT; ++ if (DISABLE_SNAPSHOT) { ++ this.snapshot = this.tileEntity; ++ } else { ++ this.snapshot = this.createSnapshot(this.tileEntity); ++ } + // copy tile entity data: +- this.snapshot = this.createSnapshot(tileEntity); +- this.load(snapshot); ++ if(this.snapshot != null) { ++ this.load(this.snapshot); ++ } ++ // Paper end + } + ++ public final boolean snapshotDisabled; // Paper ++ public static boolean DISABLE_SNAPSHOT = false; // Paper ++ + public CraftBlockEntityState(Material material, T tileEntity) { + super(material); + + this.tileEntityClass = (Class) tileEntity.getClass(); + this.tileEntity = tileEntity; +- ++ // Paper start ++ this.snapshotDisabled = DISABLE_SNAPSHOT; ++ if (DISABLE_SNAPSHOT) { ++ this.snapshot = this.tileEntity; ++ } else { ++ this.snapshot = this.createSnapshot(this.tileEntity); ++ } + // copy tile entity data: +- this.snapshot = this.createSnapshot(tileEntity); +- this.load(snapshot); ++ if(this.snapshot != null) { ++ this.load(this.snapshot); ++ } ++ // Paper end + } + + private T createSnapshot(T tileEntity) { +diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java +index e3664110bef9315cfde5b61dde98dce77016600e..10ba8b810c1759adc439f753d36108e30cf70140 100644 +--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java ++++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java +@@ -155,4 +155,10 @@ public final class CraftPersistentDataContainer implements PersistentDataContain + public Map serialize() { + return (Map) CraftNBTTagConfigSerializer.serialize(toTagCompound()); + } ++ ++ // Paper start ++ public void clear() { ++ this.customDataTags.clear(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0179-AsyncTabCompleteEvent.patch b/patches/server-remapped/0179-AsyncTabCompleteEvent.patch new file mode 100644 index 0000000000..1bd4fdfc05 --- /dev/null +++ b/patches/server-remapped/0179-AsyncTabCompleteEvent.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 26 Nov 2017 13:19:58 -0500 +Subject: [PATCH] AsyncTabCompleteEvent + +Let plugins be able to control tab completion of commands and chat async. + +This will be useful for frameworks like ACF so we can define async safe completion handlers, +and avoid going to main for tab completions. + +Especially useful if you need to query a database in order to obtain the results for tab +completion, such as offline players. + +Also adds isCommand and getLocation to the sync TabCompleteEvent + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 525728268f56470fdc24c4fd2f19d66943447778..8d0c44b6c2c99d5161c5d4b79209b79ff6db75e4 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -711,10 +711,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + @Override + public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { +- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); ++ // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async + // CraftBukkit start + if (chatSpamField.addAndGet(this, 1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { +- this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0])); ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper + return; + } + // CraftBukkit end +@@ -724,12 +724,35 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + stringreader.skip(); + } + +- ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); ++ // Paper start - async tab completion ++ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; ++ java.util.List completions = new java.util.ArrayList<>(); ++ String buffer = packet.getCommand(); ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, ++ buffer, true, null); ++ event.callEvent(); ++ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); ++ // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server ++ if (!event.isHandled()) { ++ if (!event.isCancelled()) { + +- this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { +- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer +- this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); +- }); ++ this.server.scheduleOnMain(() -> { // Paper - This needs to be on main ++ ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); ++ ++ this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { ++ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer ++ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); ++ }); ++ }); ++ } ++ } else if (!completions.isEmpty()) { ++ com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); ++ ++ builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); ++ completions.forEach(builder::suggest); ++ player.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), builder.buildFuture().join())); ++ } ++ // Paper end - async tab completion + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index df68599520189e2699c8521d6c6ab7235612af33..10addb128a357e7719854bf4f9d75f5def32b27d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1850,7 +1850,7 @@ public final class CraftServer implements Server { + offers = tabCompleteChat(player, message); + } + +- TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers); ++ TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? net.minecraft.server.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), new BlockPos(pos)) : null); // Paper + getPluginManager().callEvent(tabEvent); + + return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index a957695457cf3252848ce6ef37069692841b8e28..c5e00bd9e2790992202aadf8eec2002fc88c78f1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -28,6 +28,39 @@ public class ConsoleCommandCompleter implements Completer { + public void complete(LineReader reader, ParsedLine line, List candidates) { + final CraftServer server = this.server.server; + final String buffer = line.line(); ++ // Async Tab Complete ++ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; ++ java.util.List completions = new java.util.ArrayList<>(); ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, ++ buffer, true, null); ++ event.callEvent(); ++ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); ++ ++ if (event.isCancelled() || event.isHandled()) { ++ // Still fire sync event with the provided completions, if someone is listening ++ if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { ++ List finalCompletions = completions; ++ Waitable> syncCompletions = new Waitable>() { ++ @Override ++ protected List evaluate() { ++ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); ++ return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); ++ } ++ }; ++ server.getServer().processQueue.add(syncCompletions); ++ try { ++ completions = syncCompletions.get(); ++ } catch (InterruptedException | ExecutionException e1) { ++ e1.printStackTrace(); ++ } ++ } ++ ++ if (!completions.isEmpty()) { ++ candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); ++ } ++ return; ++ } ++ + // Paper end + Waitable> waitable = new Waitable>() { + @Override diff --git a/patches/server-remapped/0180-Avoid-NPE-in-PathfinderGoalTempt.patch b/patches/server-remapped/0180-Avoid-NPE-in-PathfinderGoalTempt.patch new file mode 100644 index 0000000000..5d0147c515 --- /dev/null +++ b/patches/server-remapped/0180-Avoid-NPE-in-PathfinderGoalTempt.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 29 Nov 2017 22:18:54 -0500 +Subject: [PATCH] Avoid NPE in PathfinderGoalTempt + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java +index 186025458e923d153e9e47c2be147a9bb53db517..11ca6a752bac4ba4bc683bef844d204b739fab63 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java +@@ -63,7 +63,7 @@ public class TemptGoal extends Goal { + } + this.target = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle(); + } +- return tempt; ++ return tempt && this.target != null; // Paper - must have target - plugin might of cancelled + // CraftBukkit end + } + } diff --git a/patches/server-remapped/0181-PlayerPickupExperienceEvent.patch b/patches/server-remapped/0181-PlayerPickupExperienceEvent.patch new file mode 100644 index 0000000000..fe7129d330 --- /dev/null +++ b/patches/server-remapped/0181-PlayerPickupExperienceEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 22:02:53 -0500 +Subject: [PATCH] PlayerPickupExperienceEvent + +Allows plugins to cancel a player picking up an experience orb + +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 3ddb0a9f15c920c9a2080f76edfda0504c1e287a..885c5a920204a31b24c7d360390eaf4177c30698 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -5,6 +5,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.FluidTags; + import net.minecraft.tags.Tag; +@@ -231,7 +232,7 @@ public class ExperienceOrb extends Entity { + @Override + public void playerTouch(Player player) { + if (!this.level.isClientSide) { +- if (this.throwTime == 0 && player.takeXpDelay == 0) { ++ if (this.throwTime == 0 && player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((ServerPlayer) player).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper + player.takeXpDelay = 2; + player.take(this, 1); + Entry entry = EnchantmentHelper.getRandomItemWith(Enchantments.MENDING, (LivingEntity) player, ItemStack::isDamaged); diff --git a/patches/server-remapped/0182-ExperienceOrbMergeEvent.patch b/patches/server-remapped/0182-ExperienceOrbMergeEvent.patch new file mode 100644 index 0000000000..28b23c94bd --- /dev/null +++ b/patches/server-remapped/0182-ExperienceOrbMergeEvent.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 22:57:26 -0500 +Subject: [PATCH] ExperienceOrbMergeEvent + +Fired when the server is about to merge 2 experience orbs +Plugins can cancel this if they want to ensure experience orbs do not lose important +metadata such as spawn reason, or conditionally move data from source to target. + +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 7d6834796259e364196280ffa468b5bf999ec7b9..5e8ff18f98b03741ccbb927f87499ae36d775a86 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -597,7 +597,7 @@ public class CraftEventFactory { + if (e instanceof net.minecraft.world.entity.ExperienceOrb) { + net.minecraft.world.entity.ExperienceOrb loopItem = (net.minecraft.world.entity.ExperienceOrb) e; + // Paper start +- if (!loopItem.removed && !(maxValue > 0 && loopItem.value >= maxValue)) { ++ if (!loopItem.removed && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper + long newTotal = (long)xp.value + (long)loopItem.value; + if ((int) newTotal < 0) continue; // Overflow + if (maxValue > 0 && newTotal > (long)maxValue) { diff --git a/patches/server-remapped/0183-Ability-to-apply-mending-to-XP-API.patch b/patches/server-remapped/0183-Ability-to-apply-mending-to-XP-API.patch new file mode 100644 index 0000000000..24cf0a602e --- /dev/null +++ b/patches/server-remapped/0183-Ability-to-apply-mending-to-XP-API.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 20 Dec 2017 17:36:49 -0500 +Subject: [PATCH] Ability to apply mending to XP API + +This allows plugins that give players the ability to apply the experience +points to the Item Mending formula, which will repair an item instead +of giving the player experience points. + +Both an API To standalone mend, and apply mending logic to .giveExp has been added. + +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 885c5a920204a31b24c7d360390eaf4177c30698..52b90ef3a145325209d3d903a2b7c9a44c332cbe 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -264,10 +264,12 @@ public class ExperienceOrb extends Entity { + } + } + ++ public final int durToXp(int i) { return durabilityToXp(i); } // Paper OBFHELPER + private int durabilityToXp(int repairAmount) { + return repairAmount / 2; + } + ++ public final int xpToDur(int i) { return xpToDurability(i); } // Paper OBFHELPER + private int xpToDurability(int experienceAmount) { + return experienceAmount * 2; + } +diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java +index 045f937f0b7acd73469b65897bea2ca9036acf22..c82e1b6e3ec98530099fd6452fdaaefebfd99b33 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java +@@ -269,8 +269,8 @@ public class EnchantmentHelper { + return getItemEnchantmentLevel(Enchantments.CHANNELING, stack) > 0; + } + +- @Nullable +- public static Entry getRandomItemWith(Enchantment enchantment, LivingEntity entity) { ++ public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, LivingEntity entityliving) { Entry entry = getRandomItemWith(enchantment, entityliving); return entry != null ? entry.getValue() : ItemStack.NULL_ITEM; } // Paper - OBFHELPER ++ @Nullable public static Entry getRandomItemWith(Enchantment enchantment, LivingEntity entity) { + return getRandomItemWith(enchantment, entity, (itemstack) -> { + 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 8a5bf0b83c1e65f07e14da0e053a64c34976b91a..efdcb8dac8db15c4bbaed84a7861ce98339e516a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -58,11 +58,14 @@ import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.network.ServerGamePacketListenerImpl; + import net.minecraft.server.players.UserWhiteListEntry; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeMap; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.inventory.AbstractContainerMenu; ++import net.minecraft.world.item.enchantment.EnchantmentHelper; ++import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.GameType; + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.saveddata.maps.MapDecoration; +@@ -1176,8 +1179,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return GameMode.getByValue(getHandle().gameMode.getGameModeForPlayer().getId()); + } + ++ // Paper start + @Override +- public void giveExp(int exp) { ++ public int applyMending(int amount) { ++ ServerPlayer handle = getHandle(); ++ // Logic copied from EntityExperienceOrb and remapped to unobfuscated methods/properties ++ net.minecraft.world.item.ItemStack itemstack = EnchantmentHelper.getRandomEquippedItemWithEnchant(Enchantments.MENDING, handle); ++ if (!itemstack.isEmpty() && itemstack.getItem().canBeDepleted()) { ++ ++ ExperienceOrb orb = net.minecraft.world.entity.EntityType.EXPERIENCE_ORB.create(handle.level); ++ orb.value = amount; ++ orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM; ++ orb.setPosRaw(handle.getX(), handle.getY(), handle.getZ()); ++ ++ int i = Math.min(orb.xpToDur(amount), itemstack.getDamageValue()); ++ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, i); ++ i = event.getRepairAmount(); ++ orb.removed = true; ++ if (!event.isCancelled()) { ++ amount -= orb.durToXp(i); ++ itemstack.setDamageValue(itemstack.getDamageValue() - i); ++ } ++ } ++ return amount; ++ } ++ ++ @Override ++ public void giveExp(int exp, boolean applyMending) { ++ if (applyMending) { ++ exp = this.applyMending(exp); ++ } ++ // Paper end + getHandle().giveExperiencePoints(exp); + } + diff --git a/patches/server-remapped/0184-Make-max-squid-spawn-height-configurable.patch b/patches/server-remapped/0184-Make-max-squid-spawn-height-configurable.patch new file mode 100644 index 0000000000..94fb614365 --- /dev/null +++ b/patches/server-remapped/0184-Make-max-squid-spawn-height-configurable.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 11 Jan 2018 16:47:28 -0600 +Subject: [PATCH] Make max squid spawn height configurable + +I don't know why upstream made only the minimum height configurable but +whatever + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6c692e58cde22003ecbf6dc5695799147c39905a..3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -348,4 +348,9 @@ public class PaperWorldConfig { + expMergeMaxValue = getInt("experience-merge-max-value", -1); + log("Experience Merge Max Value: " + expMergeMaxValue); + } ++ ++ public double squidMaxSpawnHeight; ++ private void squidMaxSpawnHeight() { ++ squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java +index 0b782c77f6d93002c35b123044b5a3eb03e63672..5a7582fd4f8e883d2f08a0227932c17d7576b957 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java +@@ -196,7 +196,8 @@ public class Squid extends WaterAnimal { + } + + public static boolean checkSquidSpawnRules(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) { +- return pos.getY() > world.getLevel().spigotConfig.squidSpawnRangeMin && pos.getY() < world.getSeaLevel(); // Spigot ++ final double maxHeight = world.getLevel().paperConfig.squidMaxSpawnHeight > 0 ? world.getLevel().paperConfig.squidMaxSpawnHeight : world.getSeaLevel(); // Paper ++ return pos.getY() > world.getLevel().spigotConfig.squidSpawnRangeMin && pos.getY() < maxHeight; // Spigot // Paper + } + + public void setMovementVector(float x, float y, float z) { diff --git a/patches/server-remapped/0185-PreCreatureSpawnEvent.patch b/patches/server-remapped/0185-PreCreatureSpawnEvent.patch new file mode 100644 index 0000000000..341927c26e --- /dev/null +++ b/patches/server-remapped/0185-PreCreatureSpawnEvent.patch @@ -0,0 +1,215 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 14 Jan 2018 17:01:31 -0500 +Subject: [PATCH] PreCreatureSpawnEvent + +Adds an event to fire before an Entity is created, so that plugins that need to cancel +CreatureSpawnEvent can do so from this event instead. + +Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste +as it's done after the Entity object has been fully created. + +Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event +instead and save a lot of server resources. + +See: https://github.com/PaperMC/Paper/issues/917 + +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index e3d92d1d35911b2960a7ca82bd4f324d285d0533..e39d950783599b01271bdb7e67fe68b46af0c49c 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -17,6 +17,7 @@ import net.minecraft.nbt.ListTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.BlockTags; +@@ -317,6 +318,20 @@ public class EntityType { + + @Nullable + public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // Paper start - Call PreCreatureSpawnEvent ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath()); ++ if (type != null) { ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ MCUtil.toLocation(worldserver, blockposition), ++ type, ++ spawnReason ++ ); ++ if (!event.callEvent()) { ++ return null; ++ } ++ } ++ // Paper end + T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); + + if (t0 != null) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java +index f3a7807a20b279056d5640ab02aa77f7b1dabc2a..880d69bad933294a2cfdea9adb3e648e29eb42be 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java +@@ -33,8 +33,8 @@ public class GolemSensor extends Sensor { + Optional> optional = entityliving.getBrain().getMemory(MemoryModuleType.MOBS); + + if (optional.isPresent()) { +- boolean flag = ((List) optional.get()).stream().anyMatch((entityliving1) -> { +- return entityliving1.getEntityType().equals(EntityType.IRON_GOLEM); ++ boolean flag = optional.get().stream().anyMatch((entityliving1) -> { // Paper - decompile fixes ++ return entityliving1.getType().equals(EntityType.IRON_GOLEM); + }); + + if (flag) { +@@ -44,6 +44,7 @@ public class GolemSensor extends Sensor { + } + } + ++ public static void setDetectedRecently(LivingEntity entityLiving) { golemDetected(entityLiving); } // Paper - OBFHELPER + public static void golemDetected(LivingEntity entityliving) { + entityliving.getBrain().setMemoryWithExpiry(MemoryModuleType.GOLEM_DETECTED_RECENTLY, true, 600L); + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index a66fab2e04a5d87ced139ed15d2434c5ffcec695..eed6265dc8275921a18fc5f4970ba131ba782132 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.DebugPackets; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvent; +@@ -942,6 +943,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + BlockPos blockposition1 = this.findSpawnPositionForGolemInColumn(blockposition, d0, d1); + + if (blockposition1 != null) { ++ // Paper start - Call PreCreatureSpawnEvent ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ MCUtil.toLocation(level, blockposition1), ++ org.bukkit.entity.EntityType.IRON_GOLEM, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE ++ ); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ GolemSensor.golemDetected(this); // Set Golem Last Seen to stop it from spawning another one ++ return null; ++ } ++ break; ++ } ++ // Paper end + IronGolem entityirongolem = (IronGolem) EntityType.IRON_GOLEM.create(world, (CompoundTag) null, (Component) null, (Player) null, blockposition1, MobSpawnType.MOB_SUMMONED, false, false); + + if (entityirongolem != null) { +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 4582fc1bb767214241568fbc22b0ee2cbf3322e0..ac572eba10a7239d71dfae060f623b076d4252ce 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -12,6 +12,7 @@ import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.StringUtil; + import net.minecraft.util.WeighedRandom; +@@ -125,6 +126,27 @@ public abstract class BaseSpawner { + ServerLevel worldserver = (ServerLevel) world; + + if (SpawnPlacements.checkSpawnRules((EntityType) optional.get(), worldserver, MobSpawnType.SPAWNER, new BlockPos(d3, d4, d5), world.getRandom())) { ++ // Paper start ++ EntityType entityType = optional.get(); ++ String key = EntityType.getKey(entityType).getPath(); ++ ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); ++ if (type != null) { ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ MCUtil.toLocation(world, d3, d4, d5), ++ type, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER ++ ); ++ if (!event.callEvent()) { ++ flag = true; ++ if (event.shouldAbortSpawn()) { ++ break; ++ } ++ continue; ++ } ++ } ++ // Paper end + Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> { + entity1.moveTo(d3, d4, d5, entity1.yRot, entity1.xRot); + return entity1; +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index a19ac1cb7e4d8d478648a048b2bfa0daf85a80c9..8a71eaf2855be0d415d1f7b18dbec98353fe5b47 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -15,6 +15,7 @@ import net.minecraft.core.Direction; + import net.minecraft.core.Position; + import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.FluidTags; +@@ -214,9 +215,16 @@ public final class NaturalSpawner { + j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); + } + +- if (isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ // Paper start ++ Boolean doSpawning = a(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); ++ if (doSpawning == null) { ++ return; ++ } ++ if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ // Paper end + Mob entityinsentient = getMobForSpawn(world, biomesettingsmobs_c.type); + ++ + if (entityinsentient == null) { + return; + } +@@ -269,17 +277,33 @@ public final class NaturalSpawner { + } + } + +- private static boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { +- EntityType entitytypes = spawnEntry.type; ++ private static Boolean a(ServerLevel worldserver, MobCategory enumcreaturetype, StructureFeatureManager structuremanager, ChunkGenerator chunkgenerator, MobSpawnSettings.SpawnerData biomesettingsmobs_c, BlockPos.MutableBlockPos blockposition_mutableblockposition, double d0) { // Paper ++ EntityType entitytypes = biomesettingsmobs_c.type; ++ // Paper start ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(entitytypes).getPath()); ++ if (type != null) { ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ MCUtil.toLocation(worldserver, blockposition_mutableblockposition), ++ type, SpawnReason.NATURAL ++ ); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ return null; ++ } ++ return false; ++ } ++ } ++ // Paper end + + if (entitytypes.getCategory() == MobCategory.MISC) { + return false; +- } else if (!entitytypes.canSpawnFarFromPlayer() && squaredDistance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { ++ } else if (!entitytypes.canSpawnFarFromPlayer() && d0 > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { + return false; +- } else if (entitytypes.canSummon() && canSpawnMobAt(world, structureAccessor, chunkGenerator, group, spawnEntry, (BlockPos) pos)) { ++ } else if (entitytypes.canSummon() && canSpawnMobAt(worldserver, structuremanager, chunkgenerator, enumcreaturetype, biomesettingsmobs_c, (BlockPos) blockposition_mutableblockposition)) { + SpawnPlacements.Type entitypositiontypes_surface = SpawnPlacements.getPlacementType(entitytypes); + +- return !isSpawnPositionOk(entitypositiontypes_surface, (LevelReader) world, pos, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, world, MobSpawnType.NATURAL, pos, world.random) ? false : world.noCollision(entitytypes.getAABB((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D))); ++ return !isSpawnPositionOk(entitypositiontypes_surface, (LevelReader) worldserver, blockposition_mutableblockposition, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, worldserver, MobSpawnType.NATURAL, blockposition_mutableblockposition, worldserver.random) ? false : worldserver.noCollision(entitytypes.getAABB((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D))); + } else { + return false; + } diff --git a/patches/server-remapped/0186-PlayerNaturallySpawnCreaturesEvent.patch b/patches/server-remapped/0186-PlayerNaturallySpawnCreaturesEvent.patch new file mode 100644 index 0000000000..0b2a988e3b --- /dev/null +++ b/patches/server-remapped/0186-PlayerNaturallySpawnCreaturesEvent.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 14 Jan 2018 17:36:02 -0500 +Subject: [PATCH] PlayerNaturallySpawnCreaturesEvent + +This event can be used for when you want to exclude a certain player +from triggering monster spawns on a server. + +Also a highly more effecient way to blanket block spawns in a world + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 3b6f35b695117bd2b0c71b994efc55fa1084eddc..97d5437df10a6d0124e944404e88650547b7d8a8 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -964,12 +964,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; + chunkRange = (chunkRange > 8) ? 8 : chunkRange; + +- double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; ++ final int finalChunkRange = chunkRange; // Paper for lambda below ++ //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event + // Spigot end + long i = chunkcoordintpair.toLong(); + + return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { +- return !entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot ++ // Paper start - ++ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; ++ double blockRange = 16384.0D; ++ if (reducedRange) { ++ event = entityplayer.playerNaturallySpawnedEvent; ++ if (event == null || event.isCancelled()) return false; ++ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); ++ } ++ ++ return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot ++ // Paper end + }); + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index d0b0fdaf5451bcc7f7ac7dab28aa59ef77e6dd97..a7122a0411f4a8656efd4facde3403c8093bc8a6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -612,6 +612,15 @@ public class ServerChunkCache extends ChunkSource { + this.level.getProfiler().pop(); + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper ++ //Paper start - call player naturally spawn event ++ int chunkRange = level.spigotConfig.mobSpawnRange; ++ chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; ++ chunkRange = Math.min(chunkRange, 8); ++ for (ServerPlayer entityPlayer : this.level.players()) { ++ entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); ++ entityPlayer.playerNaturallySpawnedEvent.callEvent(); ++ }; ++ // Paper end + this.level.timings.chunkTicks.startTiming(); // Paper + this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 4ff66138fa43cf932b95d6d3dc050a9cd7b28ad4..0fa977a31cf945b74f3a046b6be302b10f494ad1 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1,5 +1,6 @@ + package net.minecraft.server.level; + ++import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent; + import com.google.common.collect.Lists; + import com.mojang.authlib.GameProfile; + import com.mojang.datafixers.util.Either; +@@ -225,6 +226,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public boolean sentListPacket = false; + public Integer clientViewDistance; + // CraftBukkit end ++ public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper + + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + diff --git a/patches/server-remapped/0187-Add-setPlayerProfile-API-for-Skulls.patch b/patches/server-remapped/0187-Add-setPlayerProfile-API-for-Skulls.patch new file mode 100644 index 0000000000..746bff56a9 --- /dev/null +++ b/patches/server-remapped/0187-Add-setPlayerProfile-API-for-Skulls.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 19 Jan 2018 00:36:25 -0500 +Subject: [PATCH] Add setPlayerProfile API for Skulls + +This allows you to create already filled textures on Skulls to avoid texture lookups +which commonly cause rate limit issues with Mojang API + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java +index 2047ea32489d03051783d18a0dbaf456bfdbb2a1..a06c51a56846750ce59a70e9698c2b57c3517aad 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java +@@ -1,5 +1,7 @@ + package org.bukkit.craftbukkit.block; + ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; + import com.google.common.base.Preconditions; + import com.mojang.authlib.GameProfile; + import net.minecraft.server.MinecraftServer; +@@ -15,6 +17,7 @@ import org.bukkit.block.data.BlockData; + import org.bukkit.block.data.Directional; + import org.bukkit.block.data.Rotatable; + import org.bukkit.craftbukkit.entity.CraftPlayer; ++import javax.annotation.Nullable; + + public class CraftSkull extends CraftBlockEntityState implements Skull { + +@@ -105,6 +108,20 @@ public class CraftSkull extends CraftBlockEntityState implemen + } + } + ++ // Paper start ++ @Override ++ public void setPlayerProfile(PlayerProfile profile) { ++ Preconditions.checkNotNull(profile, "profile"); ++ this.profile = CraftPlayerProfile.asAuthlibCopy(profile); ++ } ++ ++ @Nullable ++ @Override ++ public PlayerProfile getPlayerProfile() { ++ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; ++ } ++ // Paper end ++ + @Override + public BlockFace getRotation() { + BlockData blockData = getBlockData(); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +index 750661540f55d3c59119dcc909e706e571a2123b..aa64ffc23d8941ff05ea7791ddd628c3c6be90e4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +@@ -4,10 +4,8 @@ import com.google.common.collect.ImmutableMap.Builder; + import com.mojang.authlib.GameProfile; + import java.util.Map; + import java.util.UUID; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.nbt.NbtUtils; +-import net.minecraft.nbt.Tag; +-import net.minecraft.world.level.block.entity.SkullBlockEntity; ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; + import org.bukkit.Bukkit; + import org.bukkit.Material; + import org.bukkit.OfflinePlayer; +@@ -18,6 +16,11 @@ import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta; + import org.bukkit.craftbukkit.util.CraftMagicNumbers; + import org.bukkit.inventory.meta.SkullMeta; + ++import javax.annotation.Nullable; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtUtils; ++import net.minecraft.nbt.Tag; ++import net.minecraft.world.level.block.entity.SkullBlockEntity; + @DelegateDeserialization(SerializableMeta.class) + class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + +@@ -149,6 +152,19 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + return hasOwner() ? profile.getName() : null; + } + ++ // Paper start ++ @Override ++ public void setPlayerProfile(@Nullable PlayerProfile profile) { ++ setProfile((profile == null) ? null : CraftPlayerProfile.asAuthlibCopy(profile)); ++ } ++ ++ @Nullable ++ @Override ++ public PlayerProfile getPlayerProfile() { ++ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; ++ } ++ // Paper end ++ + @Override + public OfflinePlayer getOwningPlayer() { + if (hasOwner()) { +@@ -175,8 +191,8 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + } else { + // Paper start - Use Online Players Skull + GameProfile newProfile = null; +- net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); +- if (player != null) newProfile = player.getProfile(); ++ net.minecraft.server.level.ServerPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); ++ if (player != null) newProfile = player.getGameProfile(); + if (newProfile == null) newProfile = new GameProfile(null, name); + setProfile(newProfile); + // Paper end diff --git a/patches/server-remapped/0188-Fill-Profile-Property-Events.patch b/patches/server-remapped/0188-Fill-Profile-Property-Events.patch new file mode 100644 index 0000000000..30643d081c --- /dev/null +++ b/patches/server-remapped/0188-Fill-Profile-Property-Events.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 2 Jan 2018 00:31:26 -0500 +Subject: [PATCH] Fill Profile Property Events + +Allows plugins to populate profile properties from local sources to avoid calls out to Mojang API +to fill in textures for example. + +If Mojang API does need to be hit, event fire so you can get the results. + +This is useful for implementing a ProfileCache for Player Skulls + +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java +index 93d73c27340645c7502acafdc0b2cfbc1a759dd8..5c7d2ee19243d0911a3a00af3ae42078a2ccba94 100644 +--- a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java +@@ -1,6 +1,8 @@ + package com.destroystokyo.paper.profile; + + import com.mojang.authlib.Environment; ++import com.destroystokyo.paper.event.profile.FillProfileEvent; ++import com.destroystokyo.paper.event.profile.PreFillProfileEvent; + import com.mojang.authlib.GameProfile; + import com.mojang.authlib.minecraft.MinecraftProfileTexture; + import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; +@@ -20,7 +22,15 @@ public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionServi + + @Override + public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { +- return super.fillProfileProperties(profile, requireSecure); ++ CraftPlayerProfile playerProfile = (CraftPlayerProfile) CraftPlayerProfile.asBukkitMirror(profile); ++ new PreFillProfileEvent(playerProfile).callEvent(); ++ profile = playerProfile.getGameProfile(); ++ if (profile.isComplete() && profile.getProperties().containsKey("textures")) { ++ return profile; ++ } ++ GameProfile gameProfile = super.fillProfileProperties(profile, requireSecure); ++ new FillProfileEvent(CraftPlayerProfile.asBukkitMirror(gameProfile)).callEvent(); ++ return gameProfile; + } + + @Override diff --git a/patches/server-remapped/0189-PlayerAdvancementCriterionGrantEvent.patch b/patches/server-remapped/0189-PlayerAdvancementCriterionGrantEvent.patch new file mode 100644 index 0000000000..6190b30a26 --- /dev/null +++ b/patches/server-remapped/0189-PlayerAdvancementCriterionGrantEvent.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 19 Jan 2018 08:15:29 -0600 +Subject: [PATCH] PlayerAdvancementCriterionGrantEvent + + +diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index 8df1803754817707a5ad292f65276871dacc4508..5ab62fc74085bbbb0c81b2f4d16a35c9345cd1f1 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -297,6 +297,12 @@ public class PlayerAdvancements { + boolean flag1 = advancementprogress.isDone(); + + if (advancementprogress.a(criterionName)) { ++ // Paper start ++ if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.bukkit, criterionName).callEvent()) { ++ advancementprogress.b(criterionName); ++ return false; ++ } ++ // Paper end + this.unregisterListeners(advancement); + this.progressChanged.add(advancement); + flag = true; diff --git a/patches/server-remapped/0190-Add-ArmorStand-Item-Meta.patch b/patches/server-remapped/0190-Add-ArmorStand-Item-Meta.patch new file mode 100644 index 0000000000..14798cca5e --- /dev/null +++ b/patches/server-remapped/0190-Add-ArmorStand-Item-Meta.patch @@ -0,0 +1,296 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 27 Jan 2018 17:04:14 -0500 +Subject: [PATCH] Add ArmorStand Item Meta + +This is adds basic item meta for armor stands. It does not add all +possible metadata however. + +There are armor, hand, and equipment types, as well as position data +that can also be added here. This initial addition should serve a +starting point for future additions in this area. + +Fixes GH-559 + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java +index 783b9c7283492fb71776b61f9820c21a39868c47..6521f4f6f660885f59f024640239609fb67d691f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java +@@ -9,9 +9,22 @@ import org.bukkit.configuration.serialization.DelegateDeserialization; + import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey; + + @DelegateDeserialization(CraftMetaItem.SerializableMeta.class) +-public class CraftMetaArmorStand extends CraftMetaItem { ++public class CraftMetaArmorStand extends CraftMetaItem implements com.destroystokyo.paper.inventory.meta.ArmorStandMeta { // Paper + + static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag"); ++ // Paper start ++ static final ItemMetaKey INVISIBLE = new ItemMetaKey("Invisible", "invisible"); ++ static final ItemMetaKey NO_BASE_PLATE = new ItemMetaKey("NoBasePlate", "no-base-plate"); ++ static final ItemMetaKey SHOW_ARMS = new ItemMetaKey("ShowArms", "show-arms"); ++ static final ItemMetaKey SMALL = new ItemMetaKey("Small", "small"); ++ static final ItemMetaKey MARKER = new ItemMetaKey("Marker", "marker"); ++ ++ private boolean invisible; ++ private boolean noBasePlate; ++ private boolean showArms; ++ private boolean small; ++ private boolean marker; ++ // Paper end + CompoundTag entityTag; + + CraftMetaArmorStand(CraftMetaItem meta) { +@@ -22,6 +35,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { + } + + CraftMetaArmorStand armorStand = (CraftMetaArmorStand) meta; ++ // Paper start ++ this.invisible = armorStand.invisible; ++ this.noBasePlate = armorStand.noBasePlate; ++ this.showArms = armorStand.showArms; ++ this.small = armorStand.small; ++ this.marker = armorStand.marker; ++ // Paper end + this.entityTag = armorStand.entityTag; + } + +@@ -30,11 +50,47 @@ public class CraftMetaArmorStand extends CraftMetaItem { + + if (tag.contains(ENTITY_TAG.NBT)) { + entityTag = tag.getCompound(ENTITY_TAG.NBT); ++ ++ // Paper start ++ if (entityTag.contains(INVISIBLE.NBT)) { ++ invisible = entityTag.getBoolean(INVISIBLE.NBT); ++ } ++ ++ if (entityTag.contains(NO_BASE_PLATE.NBT)) { ++ noBasePlate = entityTag.getBoolean(NO_BASE_PLATE.NBT); ++ } ++ ++ if (entityTag.contains(SHOW_ARMS.NBT)) { ++ showArms = entityTag.getBoolean(SHOW_ARMS.NBT); ++ } ++ ++ if (entityTag.contains(SMALL.NBT)) { ++ small = entityTag.getBoolean(SMALL.NBT); ++ } ++ ++ if (entityTag.contains(MARKER.NBT)) { ++ marker = entityTag.getBoolean(MARKER.NBT); ++ } ++ // Paper end + } + } + + CraftMetaArmorStand(Map map) { + super(map); ++ ++ // Paper start ++ boolean invis = SerializableMeta.getBoolean(map, INVISIBLE.BUKKIT); ++ boolean noBase = SerializableMeta.getBoolean(map, NO_BASE_PLATE.BUKKIT); ++ boolean showArms = SerializableMeta.getBoolean(map, SHOW_ARMS.BUKKIT); ++ boolean small = SerializableMeta.getBoolean(map, SMALL.BUKKIT); ++ boolean marker = SerializableMeta.getBoolean(map, MARKER.BUKKIT); ++ ++ this.invisible = invis; ++ this.noBasePlate = noBase; ++ this.showArms = showArms; ++ this.small = small; ++ this.marker = marker; ++ // Paper end + } + + @Override +@@ -57,6 +113,32 @@ public class CraftMetaArmorStand extends CraftMetaItem { + void applyToItem(CompoundTag tag) { + super.applyToItem(tag); + ++ // Paper start ++ if (!isArmorStandEmpty() && entityTag == null) { ++ entityTag = new CompoundTag(); ++ } ++ ++ if (isInvisible()) { ++ entityTag.putBoolean(INVISIBLE.NBT, invisible); ++ } ++ ++ if (hasNoBasePlate()) { ++ entityTag.putBoolean(NO_BASE_PLATE.NBT, noBasePlate); ++ } ++ ++ if (shouldShowArms()) { ++ entityTag.putBoolean(SHOW_ARMS.NBT, showArms); ++ } ++ ++ if (isSmall()) { ++ entityTag.putBoolean(SMALL.NBT, small); ++ } ++ ++ if (isMarker()) { ++ entityTag.putBoolean(MARKER.NBT, marker); ++ } ++ // Paper end ++ + if (entityTag != null) { + tag.put(ENTITY_TAG.NBT, entityTag); + } +@@ -78,7 +160,7 @@ public class CraftMetaArmorStand extends CraftMetaItem { + } + + boolean isArmorStandEmpty() { +- return !(entityTag != null); ++ return !(isInvisible() || hasNoBasePlate() || shouldShowArms() || isSmall() || isMarker() || entityTag != null); + } + + @Override +@@ -89,7 +171,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { + if (meta instanceof CraftMetaArmorStand) { + CraftMetaArmorStand that = (CraftMetaArmorStand) meta; + +- return entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : entityTag == null; ++ // Paper start ++ return invisible == that.invisible && ++ noBasePlate == that.noBasePlate && ++ showArms == that.showArms && ++ small == that.small && ++ marker == that.marker; ++ // Paper end + } + return true; + } +@@ -104,9 +192,14 @@ public class CraftMetaArmorStand extends CraftMetaItem { + final int original; + int hash = original = super.applyHash(); + +- if (entityTag != null) { +- hash = 73 * hash + entityTag.hashCode(); +- } ++ // Paper start ++ hash += entityTag != null ? 73 * hash + entityTag.hashCode() : 0; ++ hash += isInvisible() ? 61 * hash + 1231 : 0; ++ hash += hasNoBasePlate() ? 61 * hash + 1231 : 0; ++ hash += shouldShowArms() ? 61 * hash + 1231 : 0; ++ hash += isSmall() ? 61 * hash + 1231 : 0; ++ hash += isMarker() ? 61 * hash + 1231 : 0; ++ // Paper end + + return original != hash ? CraftMetaArmorStand.class.hashCode() ^ hash : hash; + } +@@ -115,6 +208,28 @@ public class CraftMetaArmorStand extends CraftMetaItem { + Builder serialize(Builder builder) { + super.serialize(builder); + ++ // Paper start ++ if (isInvisible()) { ++ builder.put(INVISIBLE.BUKKIT, invisible); ++ } ++ ++ if (hasNoBasePlate()) { ++ builder.put(NO_BASE_PLATE.BUKKIT, noBasePlate); ++ } ++ ++ if (shouldShowArms()) { ++ builder.put(SHOW_ARMS.BUKKIT, showArms); ++ } ++ ++ if (isSmall()) { ++ builder.put(SMALL.BUKKIT, small); ++ } ++ ++ if (isMarker()) { ++ builder.put(MARKER.BUKKIT, marker); ++ } ++ // Paper end ++ + return builder; + } + +@@ -128,4 +243,56 @@ public class CraftMetaArmorStand extends CraftMetaItem { + + return clone; + } ++ ++ // Paper start ++ @Override ++ public boolean isInvisible() { ++ return invisible; ++ } ++ ++ @Override ++ public boolean hasNoBasePlate() { ++ return noBasePlate; ++ } ++ ++ @Override ++ public boolean shouldShowArms() { ++ return showArms; ++ } ++ ++ @Override ++ public boolean isSmall() { ++ return small; ++ } ++ ++ @Override ++ public boolean isMarker() { ++ return marker; ++ } ++ ++ @Override ++ public void setInvisible(boolean invisible) { ++ this.invisible = invisible; ++ } ++ ++ @Override ++ public void setNoBasePlate(boolean noBasePlate) { ++ this.noBasePlate = noBasePlate; ++ } ++ ++ @Override ++ public void setShowArms(boolean showArms) { ++ this.showArms = showArms; ++ } ++ ++ @Override ++ public void setSmall(boolean small) { ++ this.small = small; ++ } ++ ++ @Override ++ public void setMarker(boolean marker) { ++ this.marker = marker; ++ } ++ // 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 521699615778c4b724d10edfee1d3915e036eb2e..64f166fa93e998a58a895d785ff8c9e62dacb1bb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -1441,6 +1441,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + CraftMetaCrossbow.CHARGED.NBT, + CraftMetaCrossbow.CHARGED_PROJECTILES.NBT, + CraftMetaSuspiciousStew.EFFECTS.NBT, ++ // Paper start ++ CraftMetaArmorStand.ENTITY_TAG.NBT, ++ CraftMetaArmorStand.INVISIBLE.NBT, ++ CraftMetaArmorStand.NO_BASE_PLATE.NBT, ++ CraftMetaArmorStand.SHOW_ARMS.NBT, ++ CraftMetaArmorStand.SMALL.NBT, ++ CraftMetaArmorStand.MARKER.NBT, ++ // Paper end + CraftMetaCompass.LODESTONE_DIMENSION.NBT, + CraftMetaCompass.LODESTONE_POS.NBT, + CraftMetaCompass.LODESTONE_TRACKED.NBT +diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +index 9a351c137776ac622f4df7353bb353142b3a6ccc..42f577ed3508ba5a380648461e149f16ce97c9bd 100644 +--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java ++++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +@@ -313,6 +313,7 @@ public class ItemMetaTest extends AbstractTestingBase { + final CraftMetaArmorStand meta = (CraftMetaArmorStand) cleanStack.getItemMeta(); + meta.entityTag = new NBTTagCompound(); + meta.entityTag.setBoolean("Small", true); ++ meta.setInvisible(true); // Paper + cleanStack.setItemMeta(meta); + return cleanStack; + } diff --git a/patches/server-remapped/0191-Extend-Player-Interact-cancellation.patch b/patches/server-remapped/0191-Extend-Player-Interact-cancellation.patch new file mode 100644 index 0000000000..826fede56c --- /dev/null +++ b/patches/server-remapped/0191-Extend-Player-Interact-cancellation.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 11 Feb 2018 10:43:46 +0000 +Subject: [PATCH] Extend Player Interact cancellation + +GUIs are opened on the client, meaning that the server cannot block them from opening, +However, it is possible to close these GUIs from the server. + +Flower pots are also not updated on the client when interaction is cancelled, this patch +also resolves this. + +Update adjacent blocks of doors, double plants, pistons and beds +when cancelling interaction. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 26ce794cb8d089c03fab5dd0a0c910783d10b72e..b1a53093eb5b5f359eedb6c252cf6d0d1ae8e409 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -23,6 +23,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.network.protocol.game.ClientboundBlockBreakAckPacket; + import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; ++import net.minecraft.network.protocol.game.ClientboundContainerClosePacket; + import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket; + import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; + import net.minecraft.server.MinecraftServer; +@@ -180,6 +181,11 @@ public class ServerPlayerGameMode { + PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, direction, this.player.inventory.getSelected(), InteractionHand.MAIN_HAND); + if (event.isCancelled()) { + // Let the client know the block still exists ++ // Paper start - brute force neighbor blocks for any attached blocks ++ for (Direction dir : Direction.values()) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(level, pos.relative(dir))); ++ } ++ // Paper end + this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); + // Update any tile entity data for this block + BlockEntity tileentity = this.level.getBlockEntity(pos); +@@ -484,6 +490,7 @@ public class ServerPlayerGameMode { + interactItemStack = stack.copy(); + + if (event.useInteractedBlock() == Event.Result.DENY) { ++ + // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. + if (iblockdata.getBlock() instanceof DoorBlock) { + boolean bottom = iblockdata.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER; +@@ -496,7 +503,13 @@ public class ServerPlayerGameMode { + + // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) + player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.above())); ++ // Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method ++ } else if (iblockdata.getBlock() instanceof StructureBlock) { ++ player.connection.send(new ClientboundContainerClosePacket()); ++ } else if (iblockdata.getBlock() instanceof CommandBlock) { ++ player.connection.send(new ClientboundContainerClosePacket()); + } ++ // Paper end - extend Player Interact cancellation + player.getBukkitEntity().updateInventory(); // SPIGOT-2867 + enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS; + } else if (this.gameModeForPlayer == GameType.SPECTATOR) { diff --git a/patches/server-remapped/0192-Tameable-getOwnerUniqueId-API.patch b/patches/server-remapped/0192-Tameable-getOwnerUniqueId-API.patch new file mode 100644 index 0000000000..643044c740 --- /dev/null +++ b/patches/server-remapped/0192-Tameable-getOwnerUniqueId-API.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 24 Feb 2018 01:14:55 -0500 +Subject: [PATCH] Tameable#getOwnerUniqueId API + +This is faster if all you need is the UUID, as .getOwner() will cause +an OfflinePlayer to be loaded from disk. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +index 6136b3322a340d506ce744bcd15f71a158e46ad1..04b0b2449f20220c74892788080d40e3693151c5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +@@ -89,6 +89,9 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac + } + } + ++ public UUID getOwnerUniqueId() { ++ return getOwnerUUID(); ++ } + public UUID getOwnerUUID() { + return getHandle().getOwnerUUID(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java +index 35587fd6d90dfd1da2075c3268692eac7a2eaa25..85fe4f07d35c514f2a7c7920ec416fb651434c83 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java +@@ -17,6 +17,9 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat + return (TamableAnimal) super.getHandle(); + } + ++ public UUID getOwnerUniqueId() { ++ return getOwnerUUID(); ++ } + public UUID getOwnerUUID() { + try { + return getHandle().getOwnerUUID(); diff --git a/patches/server-remapped/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch b/patches/server-remapped/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch new file mode 100644 index 0000000000..671d7965cc --- /dev/null +++ b/patches/server-remapped/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Sat, 10 Mar 2018 00:50:24 +0100 +Subject: [PATCH] Toggleable player crits, helps mitigate hacked clients. + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2..48f0385c7203c7955de5a015f3dc42be2ab7b681 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -192,6 +192,11 @@ public class PaperWorldConfig { + disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); + } + ++ public boolean disablePlayerCrits; ++ private void disablePlayerCrits() { ++ disablePlayerCrits = getBoolean("game-mechanics.disable-player-crits", false); ++ } ++ + public boolean allChunksAreSlimeChunks; + private void allChunksAreSlimeChunks() { + allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", 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 43868c1e2d2c858a4f02119c3238f615f9b1ee72..63871a3a1981b2e8c7ad74214196e35684acb584 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1131,6 +1131,7 @@ public abstract class Player extends LivingEntity { + + boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; + ++ flag2 = flag2 && !level.paperConfig.disablePlayerCrits; // Paper + flag2 = flag2 && !this.isSprinting(); + if (flag2) { + f *= 1.5F; diff --git a/patches/server-remapped/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/patches/server-remapped/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch new file mode 100644 index 0000000000..4b912daff9 --- /dev/null +++ b/patches/server-remapped/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 10 Mar 2018 16:33:15 -0500 +Subject: [PATCH] Prevent Frosted Ice from loading/holding chunks + + +diff --git a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +index ae2f5acd008d5d7163b56cb4a2d29354299959ca..99843f1ca4737d40ae0626fce931c97bbf5ab81d 100644 +--- a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +@@ -40,7 +40,8 @@ public class FrostedIceBlock extends IceBlock { + Direction enumdirection = aenumdirection[j]; + + blockposition_mutableblockposition.setWithOffset((Vec3i) pos, enumdirection); +- BlockState iblockdata1 = world.getBlockState(blockposition_mutableblockposition); ++ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper ++ if (iblockdata1 == null) { continue; } // Paper + + if (iblockdata1.is((Block) this) && !this.slightlyMelt(iblockdata1, (Level) world, blockposition_mutableblockposition)) { + world.getBlockTicks().scheduleTick(blockposition_mutableblockposition, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay +@@ -83,7 +84,9 @@ public class FrostedIceBlock extends IceBlock { + Direction enumdirection = aenumdirection[l]; + + blockposition_mutableblockposition.setWithOffset((Vec3i) pos, enumdirection); +- if (world.getBlockState(blockposition_mutableblockposition).is((Block) this)) { ++ // Paper start ++ BlockState type = world.getTypeIfLoaded(blockposition_mutableblockposition); ++ if (type != null && type.is((Block) this)) { // Paper end + ++j; + if (j >= maxNeighbors) { + return false; diff --git a/patches/server-remapped/0195-Disable-Explicit-Network-Manager-Flushing.patch b/patches/server-remapped/0195-Disable-Explicit-Network-Manager-Flushing.patch new file mode 100644 index 0000000000..45eef88da2 --- /dev/null +++ b/patches/server-remapped/0195-Disable-Explicit-Network-Manager-Flushing.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 11 Mar 2018 14:13:33 -0400 +Subject: [PATCH] Disable Explicit Network Manager Flushing + +This seems completely pointless, as packet dispatch uses .writeAndFlush. + +Things seem to work fine without explicit flushing, but incase issues arise, +provide a System property to re-enable it using improved logic of doing the +flushing on the netty event loop, so it won't do the flush on the main thread. + +Renable flushing by passing -Dpaper.explicit-flush=true + +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 3429c813a5b471cdfa561bd20849a303e5aacead..7f4681910751047a26fdfc6b59bc460449c02001 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -73,6 +73,7 @@ public class Connection extends SimpleChannelInboundHandler> { + // Paper start - NetworkClient implementation + public int protocolVersion; + public java.net.InetSocketAddress virtualHost; ++ private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); + // Paper end + + public Connection(PacketFlow side) { +@@ -240,7 +241,7 @@ public class Connection extends SimpleChannelInboundHandler> { + } + + if (this.channel != null) { +- this.channel.flush(); ++ if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version + } + + if (this.tickCount++ % 20 == 0) { diff --git a/patches/server-remapped/0196-Implement-extended-PaperServerListPingEvent.patch b/patches/server-remapped/0196-Implement-extended-PaperServerListPingEvent.patch new file mode 100644 index 0000000000..762c35c3ad --- /dev/null +++ b/patches/server-remapped/0196-Implement-extended-PaperServerListPingEvent.patch @@ -0,0 +1,378 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Wed, 11 Oct 2017 15:56:26 +0200 +Subject: [PATCH] Implement extended PaperServerListPingEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4ecd0c5bbea55f68549c85aa27e80e2c7e6265d4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java +@@ -0,0 +1,31 @@ ++package com.destroystokyo.paper.network; ++ ++import com.destroystokyo.paper.event.server.PaperServerListPingEvent; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.entity.Player; ++import org.bukkit.util.CachedServerIcon; ++ ++import javax.annotation.Nullable; ++ ++class PaperServerListPingEventImpl extends PaperServerListPingEvent { ++ ++ private final MinecraftServer server; ++ ++ PaperServerListPingEventImpl(MinecraftServer server, StatusClient client, int protocolVersion, @Nullable CachedServerIcon icon) { ++ super(client, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers(), ++ server.getServerModName() + ' ' + server.getServerVersion(), protocolVersion, icon); ++ this.server = server; ++ } ++ ++ @Override ++ protected final Object[] getOnlinePlayers() { ++ return this.server.getPlayerList().players.toArray(); ++ } ++ ++ @Override ++ protected final Player getBukkitPlayer(Object player) { ++ return ((ServerPlayer) player).getBukkitEntity(); ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d926ad804355ee2fdc5910b2505e8671602acdab +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java +@@ -0,0 +1,11 @@ ++package com.destroystokyo.paper.network; ++ ++import net.minecraft.network.Connection; ++ ++class PaperStatusClient extends PaperNetworkClient implements StatusClient { ++ ++ PaperStatusClient(Connection networkManager) { ++ super(networkManager); ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4c2351b03b58511b80017b58ee9b20ab5193adc9 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java +@@ -0,0 +1,110 @@ ++package com.destroystokyo.paper.network; ++ ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; ++import com.google.common.base.MoreObjects; ++import com.google.common.base.Strings; ++import com.mojang.authlib.GameProfile; ++import io.papermc.paper.adventure.AdventureComponent; ++import java.util.List; ++import java.util.UUID; ++import javax.annotation.Nonnull; ++import net.minecraft.network.Connection; ++import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; ++import net.minecraft.network.protocol.status.ServerStatus; ++import net.minecraft.server.MinecraftServer; ++ ++public final class StandardPaperServerListPingEventImpl extends PaperServerListPingEventImpl { ++ ++ private static final GameProfile[] EMPTY_PROFILES = new GameProfile[0]; ++ private static final UUID FAKE_UUID = new UUID(0, 0); ++ ++ private GameProfile[] originalSample; ++ ++ private StandardPaperServerListPingEventImpl(MinecraftServer server, Connection networkManager, ServerStatus ping) { ++ super(server, new PaperStatusClient(networkManager), ping.getVersion() != null ? ping.getVersion().getProtocol() : -1, server.server.getServerIcon()); ++ this.originalSample = ping.getPlayers() == null ? null : ping.getPlayers().getSample(); // GH-1473 - pre-tick race condition NPE ++ } ++ ++ @Nonnull ++ @Override ++ public List getPlayerSample() { ++ List sample = super.getPlayerSample(); ++ ++ if (this.originalSample != null) { ++ for (GameProfile profile : this.originalSample) { ++ sample.add(CraftPlayerProfile.asBukkitCopy(profile)); ++ } ++ this.originalSample = null; ++ } ++ ++ return sample; ++ } ++ ++ private GameProfile[] getPlayerSampleHandle() { ++ if (this.originalSample != null) { ++ return this.originalSample; ++ } ++ ++ List entries = super.getPlayerSample(); ++ if (entries.isEmpty()) { ++ return EMPTY_PROFILES; ++ } ++ ++ GameProfile[] profiles = new GameProfile[entries.size()]; ++ for (int i = 0; i < profiles.length; i++) { ++ /* ++ * Avoid null UUIDs/names since that will make the response invalid ++ * on the client. ++ * Instead, fall back to a fake/empty UUID and an empty string as name. ++ * This can be used to create custom lines in the player list that do not ++ * refer to a specific player. ++ */ ++ ++ PlayerProfile profile = entries.get(i); ++ if (profile.getId() != null && profile.getName() != null) { ++ profiles[i] = CraftPlayerProfile.asAuthlib(profile); ++ } else { ++ profiles[i] = new GameProfile(MoreObjects.firstNonNull(profile.getId(), FAKE_UUID), Strings.nullToEmpty(profile.getName())); ++ } ++ } ++ ++ return profiles; ++ } ++ ++ @SuppressWarnings("deprecation") ++ public static void processRequest(MinecraftServer server, Connection networkManager) { ++ StandardPaperServerListPingEventImpl event = new StandardPaperServerListPingEventImpl(server, networkManager, server.getStatus()); ++ server.server.getPluginManager().callEvent(event); ++ ++ // Close connection immediately if event is cancelled ++ if (event.isCancelled()) { ++ networkManager.disconnect(null); ++ return; ++ } ++ ++ // Setup response ++ ServerStatus ping = new ServerStatus(); ++ ++ // Description ++ ping.setDescription(new AdventureComponent(event.motd())); ++ ++ // Players ++ if (!event.shouldHidePlayers()) { ++ ping.setPlayers(new ServerStatus.Players(event.getMaxPlayers(), event.getNumPlayers())); ++ ping.getPlayers().setSample(event.getPlayerSampleHandle()); ++ } ++ ++ // Version ++ ping.setVersion(new ServerStatus.Version(event.getVersion(), event.getProtocolVersion())); ++ ++ // Favicon ++ if (event.getServerIcon() != null) { ++ ping.setFavicon(event.getServerIcon().getData()); ++ } ++ ++ // Send response ++ networkManager.send(new ClientboundStatusResponsePacket(ping)); ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java +index b985d238eadf857602636ba5e5c277d4b1992d35..5b2081f920304244df96de78b2c66cf8a49a5b85 100644 +--- a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java ++++ b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java +@@ -2,6 +2,7 @@ package net.minecraft.network.protocol.status; + + import com.google.gson.Gson; + import com.google.gson.GsonBuilder; ++import io.papermc.paper.adventure.AdventureComponent; // Paper + import java.io.IOException; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.chat.Component; +@@ -12,7 +13,9 @@ import net.minecraft.util.LowerCaseEnumTypeAdapterFactory; + + public class ClientboundStatusResponsePacket implements Packet { + +- private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()).create(); ++ private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()) ++ .registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()) ++ .create(); + private ServerStatus status; + + public ClientboundStatusResponsePacket() {} +diff --git a/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java b/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java +index d6be3dd6cfed3f65325398fc33663cb251f87ac7..31d45cd635eae2ff406cb0441f2cd2aee833b945 100644 +--- a/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java ++++ b/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java +@@ -31,6 +31,7 @@ public class ServerStatus { + this.description = description; + } + ++ public Players getPlayers() { return getPlayers(); } // Paper - OBFHELPER + public ServerStatus.Players getPlayers() { + return this.players; + } +@@ -162,10 +163,12 @@ public class ServerStatus { + return this.numPlayers; + } + ++ public GameProfile[] getSample() { return getSample(); } // Paper - OBFHELPER + public GameProfile[] getSample() { + return this.sample; + } + ++ public void setSample(GameProfile[] sample) { setSample(sample); } // Paper - OBFHELPER + public void setSample(GameProfile[] sample) { + this.sample = sample; + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 4b3341877629c7065496fb0f0b4d509f5a48db6d..d34da1eb172a7dcda564680afecf3dc145bf09f3 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2,6 +2,9 @@ package net.minecraft.server; + + import com.google.common.base.Splitter; + import com.google.common.collect.ImmutableList; ++import co.aikar.timings.Timings; ++import com.destroystokyo.paper.event.server.PaperServerListPingEvent; ++import com.google.common.base.Stopwatch; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; +@@ -1238,7 +1241,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= 5000000000L) { + this.lastServerStatus = i; + this.status.setPlayers(new ServerStatus.Players(this.getMaxPlayers(), this.getPlayerCount())); +- GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), 12)]; ++ GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), org.spigotmc.SpigotConfig.playerSample)]; // Paper + int j = Mth.nextInt(this.random, 0, this.getPlayerCount() - agameprofile.length); + + for (int k = 0; k < agameprofile.length; ++k) { +diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +index 223df8d27c2ff1cbff634bca3dbde5cc24de7f98..f74e3cbdff8c2d83809f04f42717501d7b1a1ed2 100644 +--- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +@@ -1,7 +1,7 @@ + package net.minecraft.server.network; + + import net.minecraft.server.MinecraftServer; +-import net.minecraft.server.level.ServerPlayer; ++ + // CraftBukkit start + import com.mojang.authlib.GameProfile; + import java.net.InetSocketAddress; +@@ -11,8 +11,6 @@ import net.minecraft.network.Connection; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; +-import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; +-import net.minecraft.network.protocol.status.ServerStatus; + import net.minecraft.network.protocol.status.ServerStatusPacketListener; + import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; + import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; +@@ -47,15 +45,17 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON); + } else { + this.hasRequestedStatus = true; ++ // Paper start - Replace everything ++ /* + // CraftBukkit start + // this.networkManager.sendPacket(new PacketStatusOutServerInfo(this.minecraftServer.getServerPing())); +- final Object[] players = server.getPlayerList().players.toArray(); ++ final Object[] players = minecraftServer.getPlayerList().players.toArray(); + class ServerListPingEvent extends org.bukkit.event.server.ServerListPingEvent { + +- CraftIconCache icon = server.server.getServerIcon(); ++ CraftIconCache icon = minecraftServer.server.getServerIcon(); + + ServerListPingEvent() { +- super(((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.server.motd(), server.getPlayerList().getMaxPlayers()); // Paper - Adventure ++ super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.server.motd(), minecraftServer.getPlayerList().getMaxPlayers()); // Paper - Adventure + } + + @Override +@@ -71,7 +71,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + return new Iterator() { + int i; + int ret = Integer.MIN_VALUE; +- ServerPlayer player; ++ EntityPlayer player; + + @Override + public boolean hasNext() { +@@ -80,7 +80,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + } + final Object[] currentPlayers = players; + for (int length = currentPlayers.length, i = this.i; i < length; i++) { +- final ServerPlayer player = (ServerPlayer) currentPlayers[i]; ++ final EntityPlayer player = (EntityPlayer) currentPlayers[i]; + if (player != null) { + this.i = i + 1; + this.player = player; +@@ -95,7 +95,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + if (!hasNext()) { + throw new java.util.NoSuchElementException(); + } +- final ServerPlayer player = this.player; ++ final EntityPlayer player = this.player; + this.player = null; + this.ret = this.i - 1; + return player.getBukkitEntity(); +@@ -115,16 +115,16 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + } + + ServerListPingEvent event = new ServerListPingEvent(); +- this.server.server.getPluginManager().callEvent(event); ++ this.minecraftServer.server.getPluginManager().callEvent(event); + + java.util.List profiles = new java.util.ArrayList(players.length); + for (Object player : players) { + if (player != null) { +- profiles.add(((ServerPlayer) player).getGameProfile()); ++ profiles.add(((EntityPlayer) player).getProfile()); + } + } + +- ServerStatus.Players playerSample = new ServerStatus.Players(event.getMaxPlayers(), profiles.size()); ++ ServerPing.ServerPingPlayerSample playerSample = new ServerPing.ServerPingPlayerSample(event.getMaxPlayers(), profiles.size()); + // Spigot Start + if ( !profiles.isEmpty() ) + { +@@ -132,16 +132,19 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + profiles = profiles.subList( 0, Math.min( profiles.size(), org.spigotmc.SpigotConfig.playerSample ) ); // Cap the sample to n (or less) displayed players, ie: Vanilla behaviour + } + // Spigot End +- playerSample.setSample(profiles.toArray(new GameProfile[profiles.size()])); ++ playerSample.a(profiles.toArray(new GameProfile[profiles.size()])); + +- ServerStatus ping = new ServerStatus(); ++ ServerPing ping = new ServerPing(); + ping.setFavicon(event.icon.value); +- ping.setDescription(CraftChatMessage.fromString(event.getMotd(), true)[0]); +- ping.setPlayers(playerSample); +- int version = SharedConstants.getCurrentVersion().getProtocolVersion(); +- ping.setVersion(new ServerStatus.Version(server.getServerModName() + " " + server.getServerVersion(), version)); +- +- this.connection.send(new ClientboundStatusResponsePacket(ping)); ++ ping.setMOTD(CraftChatMessage.fromString(event.getMotd(), true)[0]); ++ ping.setPlayerSample(playerSample); ++ int version = SharedConstants.getGameVersion().getProtocolVersion(); ++ ping.setServerInfo(new ServerPing.ServerData(minecraftServer.getServerModName() + " " + minecraftServer.getVersion(), version)); ++ ++ this.networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); ++ */ ++ com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.server, this.connection); ++ // Paper end + } + // CraftBukkit end + } +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 3981ba5957fdc2929d54515f2b98bb7a4611e938..652b820a4c0bbf7b6bbb8200927a663665583606 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -289,7 +289,7 @@ public class SpigotConfig + public static int playerSample; + private static void playerSample() + { +- playerSample = getInt( "settings.sample-count", 12 ); ++ playerSample = Math.max( getInt( "settings.sample-count", 12 ), 0 ); // Paper - Avoid negative counts + Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger + } + diff --git a/patches/server-remapped/0197-Improved-Async-Task-Scheduler.patch b/patches/server-remapped/0197-Improved-Async-Task-Scheduler.patch new file mode 100644 index 0000000000..b0ae823221 --- /dev/null +++ b/patches/server-remapped/0197-Improved-Async-Task-Scheduler.patch @@ -0,0 +1,370 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 16 Mar 2018 22:59:43 -0400 +Subject: [PATCH] Improved Async Task Scheduler + +The Craft Scheduler still uses the primary thread for task scheduling. +This results in the main thread still having to do work as part of the +dispatching of async tasks. + +If plugins make use of lots of async tasks, such as particle emitters +that want to keep the logic off the main thread, the main thread still +receives quite a bit of load from processing all of these queued tasks. + +Additionally, resizing and managing the pending entries for all of +these asynchronous tasks takes up time on the main thread too. + +This commit replaces the implementation of the scheduler when working +with asynchronous tasks, by forwarding calls to the new scheduler. + +The Async Scheduler uses a single thread executor for "management" tasks. +The Management Thread is responsible for all adding and dispatching of +scheduled tasks. + +The mainThreadHeartbeat will send a heartbeat task to the management thread +with the currentTick value, so that it can find which tasks to execute. + +Scheduling of an async tasks also dispatches a management task, ensuring +that any Queue resizing operation occurs off of the main thread. + +The async queue uses a complete separate PriorityQueue, ensuring that resize +operations are decoupled from the sync tasks queue. + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3c1992e212a6d6f1db4d5b807b38d71913619fc0 +--- /dev/null ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java +@@ -0,0 +1,122 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package org.bukkit.craftbukkit.scheduler; ++ ++import com.destroystokyo.paper.ServerSchedulerReportingWrapper; ++import com.google.common.util.concurrent.ThreadFactoryBuilder; ++import org.bukkit.plugin.Plugin; ++ ++import java.util.ArrayList; ++import java.util.Iterator; ++import java.util.List; ++import java.util.concurrent.Executor; ++import java.util.concurrent.Executors; ++import java.util.concurrent.SynchronousQueue; ++import java.util.concurrent.ThreadPoolExecutor; ++import java.util.concurrent.TimeUnit; ++ ++public class CraftAsyncScheduler extends CraftScheduler { ++ ++ private final ThreadPoolExecutor executor = new ThreadPoolExecutor( ++ 4, Integer.MAX_VALUE,30L, TimeUnit.SECONDS, new SynchronousQueue<>(), ++ new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").build()); ++ private final Executor management = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder() ++ .setNameFormat("Craft Async Scheduler Management Thread").build()); ++ private final List temp = new ArrayList<>(); ++ ++ CraftAsyncScheduler() { ++ super(true); ++ executor.allowCoreThreadTimeOut(true); ++ executor.prestartAllCoreThreads(); ++ } ++ ++ @Override ++ public void cancelTask(int taskId) { ++ this.management.execute(() -> this.removeTask(taskId)); ++ } ++ ++ private synchronized void removeTask(int taskId) { ++ parsePending(); ++ this.pending.removeIf((task) -> { ++ if (task.getTaskId() == taskId) { ++ task.cancel0(); ++ return true; ++ } ++ return false; ++ }); ++ } ++ ++ @Override ++ public void mainThreadHeartbeat(int currentTick) { ++ this.currentTick = currentTick; ++ this.management.execute(() -> this.runTasks(currentTick)); ++ } ++ ++ private synchronized void runTasks(int currentTick) { ++ parsePending(); ++ while (!this.pending.isEmpty() && this.pending.peek().getNextRun() <= currentTick) { ++ CraftTask task = this.pending.remove(); ++ if (executeTask(task)) { ++ final long period = task.getPeriod(); ++ if (period > 0) { ++ task.setNextRun(currentTick + period); ++ temp.add(task); ++ } ++ } ++ parsePending(); ++ } ++ this.pending.addAll(temp); ++ temp.clear(); ++ } ++ ++ private boolean executeTask(CraftTask task) { ++ if (isValid(task)) { ++ this.runners.put(task.getTaskId(), task); ++ this.executor.execute(new ServerSchedulerReportingWrapper(task)); ++ return true; ++ } ++ return false; ++ } ++ ++ @Override ++ public synchronized void cancelTasks(Plugin plugin) { ++ parsePending(); ++ for (Iterator iterator = this.pending.iterator(); iterator.hasNext(); ) { ++ CraftTask task = iterator.next(); ++ if (task.getTaskId() != -1 && (plugin == null || task.getOwner().equals(plugin))) { ++ task.cancel0(); ++ iterator.remove(); ++ } ++ } ++ } ++ ++ /** ++ * Task is not cancelled ++ * @param runningTask ++ * @return ++ */ ++ static boolean isValid(CraftTask runningTask) { ++ return runningTask.getPeriod() >= CraftTask.NO_REPEATING; ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483ca3c7c2a8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -63,7 +63,7 @@ public class CraftScheduler implements BukkitScheduler { + /** + * Main thread logic only + */ +- private final PriorityQueue pending = new PriorityQueue(10, ++ final PriorityQueue pending = new PriorityQueue(10, // Paper + new Comparator() { + @Override + public int compare(final CraftTask o1, final CraftTask o2) { +@@ -80,12 +80,13 @@ public class CraftScheduler implements BukkitScheduler { + /** + * These are tasks that are currently active. It's provided for 'viewing' the current state. + */ +- private final ConcurrentHashMap runners = new ConcurrentHashMap(); ++ final ConcurrentHashMap runners = new ConcurrentHashMap(); // Paper + /** + * The sync task that is currently running on the main thread. + */ + private volatile CraftTask currentTask = null; +- private volatile int currentTick = -1; ++ // Paper start - Improved Async Task Scheduler ++ volatile int currentTick = -1;/* + private final Executor executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %d").build()); + private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) { + @Override +@@ -94,12 +95,31 @@ public class CraftScheduler implements BukkitScheduler { + } + }; + private CraftAsyncDebugger debugTail = debugHead; ++ ++ */ // Paper end + private static final int RECENT_TICKS; + + static { + RECENT_TICKS = 30; + } + ++ ++ // Paper start ++ private final CraftScheduler asyncScheduler; ++ private final boolean isAsyncScheduler; ++ public CraftScheduler() { ++ this(false); ++ } ++ ++ public CraftScheduler(boolean isAsync) { ++ this.isAsyncScheduler = isAsync; ++ if (isAsync) { ++ this.asyncScheduler = this; ++ } else { ++ this.asyncScheduler = new CraftAsyncScheduler(); ++ } ++ } ++ // Paper end + @Override + public int scheduleSyncDelayedTask(final Plugin plugin, final Runnable task) { + return this.scheduleSyncDelayedTask(plugin, task, 0L); +@@ -222,7 +242,7 @@ public class CraftScheduler implements BukkitScheduler { + } else if (period < CraftTask.NO_REPEATING) { + period = CraftTask.NO_REPEATING; + } +- return handle(new CraftAsyncTask(runners, plugin, runnable, nextId(), period), delay); ++ return handle(new CraftAsyncTask(this.asyncScheduler.runners, plugin, runnable, nextId(), period), delay); // Paper + } + + @Override +@@ -238,6 +258,11 @@ public class CraftScheduler implements BukkitScheduler { + if (taskId <= 0) { + return; + } ++ // Paper start ++ if (!this.isAsyncScheduler) { ++ this.asyncScheduler.cancelTask(taskId); ++ } ++ // Paper end + CraftTask task = runners.get(taskId); + if (task != null) { + task.cancel0(); +@@ -280,6 +305,11 @@ public class CraftScheduler implements BukkitScheduler { + @Override + public void cancelTasks(final Plugin plugin) { + Validate.notNull(plugin, "Cannot cancel tasks of null plugin"); ++ // Paper start ++ if (!this.isAsyncScheduler) { ++ this.asyncScheduler.cancelTasks(plugin); ++ } ++ // Paper end + final CraftTask task = new CraftTask( + new Runnable() { + @Override +@@ -319,6 +349,13 @@ public class CraftScheduler implements BukkitScheduler { + + @Override + public boolean isCurrentlyRunning(final int taskId) { ++ // Paper start ++ if (!isAsyncScheduler) { ++ if (this.asyncScheduler.isCurrentlyRunning(taskId)) { ++ return true; ++ } ++ } ++ // Paper end + final CraftTask task = runners.get(taskId); + if (task == null) { + return false; +@@ -337,6 +374,11 @@ public class CraftScheduler implements BukkitScheduler { + if (taskId <= 0) { + return false; + } ++ // Paper start ++ if (!this.isAsyncScheduler && this.asyncScheduler.isQueued(taskId)) { ++ return true; ++ } ++ // Paper end + for (CraftTask task = head.getNext(); task != null; task = task.getNext()) { + if (task.getTaskId() == taskId) { + return task.getPeriod() >= CraftTask.NO_REPEATING; // The task will run +@@ -348,6 +390,12 @@ public class CraftScheduler implements BukkitScheduler { + + @Override + public List getActiveWorkers() { ++ // Paper start ++ if (!isAsyncScheduler) { ++ //noinspection TailRecursion ++ return this.asyncScheduler.getActiveWorkers(); ++ } ++ // Paper end + final ArrayList workers = new ArrayList(); + for (final CraftTask taskObj : runners.values()) { + // Iterator will be a best-effort (may fail to grab very new values) if called from an async thread +@@ -385,6 +433,11 @@ public class CraftScheduler implements BukkitScheduler { + pending.add(task); + } + } ++ // Paper start ++ if (!this.isAsyncScheduler) { ++ pending.addAll(this.asyncScheduler.getPendingTasks()); ++ } ++ // Paper end + return pending; + } + +@@ -392,6 +445,11 @@ public class CraftScheduler implements BukkitScheduler { + * This method is designed to never block or wait for locks; an immediate execution of all current tasks. + */ + public void mainThreadHeartbeat(final int currentTick) { ++ // Paper start ++ if (!this.isAsyncScheduler) { ++ this.asyncScheduler.mainThreadHeartbeat(currentTick); ++ } ++ // Paper end + this.currentTick = currentTick; + final List temp = this.temp; + parsePending(); +@@ -431,7 +489,7 @@ public class CraftScheduler implements BukkitScheduler { + parsePending(); + } else { + //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper +- executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper ++ task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Paper"); // Paper + // We don't need to parse pending + // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) + } +@@ -450,7 +508,7 @@ public class CraftScheduler implements BukkitScheduler { + //debugHead = debugHead.getNextHead(currentTick); // Paper + } + +- private void addTask(final CraftTask task) { ++ protected void addTask(final CraftTask task) { + final AtomicReference tail = this.tail; + CraftTask tailTask = tail.get(); + while (!tail.compareAndSet(tailTask, task)) { +@@ -459,7 +517,13 @@ public class CraftScheduler implements BukkitScheduler { + tailTask.setNext(task); + } + +- private CraftTask handle(final CraftTask task, final long delay) { ++ protected CraftTask handle(final CraftTask task, final long delay) { // Paper ++ // Paper start ++ if (!this.isAsyncScheduler && !task.isSync()) { ++ this.asyncScheduler.handle(task, delay); ++ return task; ++ } ++ // Paper end + task.setNextRun(currentTick + delay); + addTask(task); + return task; +@@ -478,8 +542,8 @@ public class CraftScheduler implements BukkitScheduler { + return ids.incrementAndGet(); + } + +- private void parsePending() { +- MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); ++ void parsePending() { // Paper ++ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); // Paper + CraftTask head = this.head; + CraftTask task = head.getNext(); + CraftTask lastTask = head; +@@ -498,7 +562,7 @@ public class CraftScheduler implements BukkitScheduler { + task.setNext(null); + } + this.head = lastTask; +- MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); ++ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); // Paper + } + + private boolean isReady(final int currentTick) { diff --git a/patches/server-remapped/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/patches/server-remapped/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch new file mode 100644 index 0000000000..f400637138 --- /dev/null +++ b/patches/server-remapped/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 18 Mar 2018 11:45:57 -0400 +Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent + +This will allow you to change the players name or skin on login. + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index ff83fb15d0d0adb62c630fc7aafc134972bf15fc..e5be45ac86907c1f8cc154bd38fd624a2320180f 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -1,5 +1,7 @@ + package net.minecraft.server.network; + ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; + import com.mojang.authlib.GameProfile; + import com.mojang.authlib.exceptions.AuthenticationUnavailableException; + import java.math.BigInteger; +@@ -36,6 +38,7 @@ import org.apache.commons.lang3.Validate; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import io.papermc.paper.adventure.PaperAdventure; // Paper ++import org.bukkit.Bukkit; + import org.bukkit.craftbukkit.util.Waitable; + import org.bukkit.event.player.AsyncPlayerPreLoginEvent; + import org.bukkit.event.player.PlayerPreLoginEvent; +@@ -314,8 +317,16 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + java.util.UUID uniqueId = gameProfile.getId(); + final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; + +- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); ++ // Paper start ++ PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); ++ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); + server.getPluginManager().callEvent(asyncEvent); ++ profile = asyncEvent.getPlayerProfile(); ++ profile.complete(); ++ gameProfile = CraftPlayerProfile.asAuthlibCopy(profile); ++ playerName = gameProfile.getName(); ++ uniqueId = gameProfile.getId(); ++ // Paper end + + if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { + final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); diff --git a/patches/server-remapped/0199-Player.setPlayerProfile-API.patch b/patches/server-remapped/0199-Player.setPlayerProfile-API.patch new file mode 100644 index 0000000000..f35f170d57 --- /dev/null +++ b/patches/server-remapped/0199-Player.setPlayerProfile-API.patch @@ -0,0 +1,142 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 18 Mar 2018 12:29:48 -0400 +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/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index e5be45ac86907c1f8cc154bd38fd624a2320180f..0aa3a154d68f00edcc09b947a24b2b59b1e135e6 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -54,7 +54,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + public final Connection connection; + private ServerLoginPacketListenerImpl.State state; + private int tick; +- private GameProfile gameProfile; ++ private GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } private GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER + private final String serverId; + private SecretKey secretKey; + private ServerPlayer delayedAcceptPlayer; +@@ -318,12 +318,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; + + // Paper start +- PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); ++ PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); + AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); + server.getPluginManager().callEvent(asyncEvent); + profile = asyncEvent.getPlayerProfile(); +- profile.complete(); +- gameProfile = CraftPlayerProfile.asAuthlibCopy(profile); ++ profile.complete(true); ++ setGameProfile(CraftPlayerProfile.asAuthlib(profile)); + playerName = gameProfile.getName(); + uniqueId = gameProfile.getId(); + // Paper end +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 63871a3a1981b2e8c7ad74214196e35684acb584..c4aa824d03de952fe6b306e539baa47af979add1 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -159,7 +159,7 @@ public abstract class Player extends LivingEntity { + protected int enchantmentSeed; + protected final float defaultFlySpeed = 0.02F; + private int lastLevelUpTime; +- private final GameProfile gameProfile; ++ private GameProfile gameProfile; public final void setProfile(final GameProfile profile) { this.gameProfile = profile; } // Paper - OBFHELPER + private ItemStack lastItemInMainHand; + private final ItemCooldowns cooldowns; + @Nullable +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index efdcb8dac8db15c4bbaed84a7861ce98339e516a..9d853733ff9054cc48925e22c8bb3c8d9b898808 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -67,6 +67,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.GameType; ++import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.saveddata.maps.MapDecoration; + import net.minecraft.world.phys.Vec3; +@@ -1307,8 +1308,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + hiddenPlayers.put(player.getUniqueId(), hidingPlugins); + + // Remove this player from the hidden player's EntityTrackerEntry +- ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; ++ // Paper start + ServerPlayer other = ((CraftPlayer) player).getHandle(); ++ unregisterPlayer(other); ++ } ++ private void unregisterPlayer(ServerPlayer other) { ++ ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; ++ // Paper end + ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId()); + if (entry != null) { + entry.removePlayer(getHandle()); +@@ -1349,8 +1355,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + hiddenPlayers.remove(player.getUniqueId()); + +- ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; ++ // Paper start + ServerPlayer other = ((CraftPlayer) player).getHandle(); ++ registerPlayer(other); ++ } ++ private void registerPlayer(ServerPlayer other) { ++ ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; ++ // Paper end + + getHandle().connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, other)); + +@@ -1359,6 +1370,50 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + entry.updatePlayer(getHandle()); + } + } ++ // Paper start ++ private void reregisterPlayer(ServerPlayer player) { ++ if (!hiddenPlayers.containsKey(player.getUUID())) { ++ unregisterPlayer(player); ++ registerPlayer(player); ++ } ++ } ++ public void setPlayerProfile(com.destroystokyo.paper.profile.PlayerProfile profile) { ++ ServerPlayer self = getHandle(); ++ self.setProfile(com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile)); ++ if (!self.sentListPacket) { ++ return; ++ } ++ List players = server.getServer().getPlayerList().players; ++ for (ServerPlayer player : players) { ++ player.getBukkitEntity().reregisterPlayer(self); ++ } ++ refreshPlayer(); ++ } ++ public com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile() { ++ return new com.destroystokyo.paper.profile.CraftPlayerProfile(this).clone(); ++ } ++ ++ private void refreshPlayer() { ++ ServerPlayer handle = getHandle(); ++ ++ Location loc = getLocation(); ++ ++ ServerGamePacketListenerImpl connection = handle.connection; ++ reregisterPlayer(handle); ++ ++ //Respawn the player then update their position and selected slot ++ ServerLevel worldserver = handle.getLevel(); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundRespawnPacket(worldserver.dimensionType(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), handle.gameMode.getGameModeForPlayer(), handle.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), true)); ++ handle.onUpdateAbilities(); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), new HashSet<>(), 0)); ++ net.minecraft.server.MinecraftServer.getServer().getPlayerList().sendAllPlayerInfo(handle); ++ ++ if (this.isOp()) { ++ this.setOp(false); ++ this.setOp(true); ++ } ++ } ++ // Paper end + + public void removeDisconnectingPlayer(Player player) { + hiddenPlayers.remove(player.getUniqueId()); diff --git a/patches/server-remapped/0200-Fix-Dragon-Server-Crashes.patch b/patches/server-remapped/0200-Fix-Dragon-Server-Crashes.patch new file mode 100644 index 0000000000..334aa02f71 --- /dev/null +++ b/patches/server-remapped/0200-Fix-Dragon-Server-Crashes.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Mar 2018 20:52:07 -0400 +Subject: [PATCH] Fix Dragon Server Crashes + +If the dragon tries to find "ground" and hits a hole, or off edge, +it will infinitely keep looking for non air and eventually crash. + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java +index 5e701b02e464889fe433b08018d13e63b24506eb..0c2a5f5c4d7d7516793eba20205b5703fe1450d5 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java +@@ -63,7 +63,7 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { + double d3 = d2; + BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(d0, d2, d1); + +- while (this.dragon.level.isEmptyBlock(blockposition_mutableblockposition)) { ++ while (this.dragon.level.isEmptyBlock(blockposition_mutableblockposition ) && d2 > 0) { // Paper + --d3; + if (d3 < 0.0D) { + d3 = d2; diff --git a/patches/server-remapped/0201-getPlayerUniqueId-API.patch b/patches/server-remapped/0201-getPlayerUniqueId-API.patch new file mode 100644 index 0000000000..64d63b916e --- /dev/null +++ b/patches/server-remapped/0201-getPlayerUniqueId-API.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 22 Mar 2018 01:40:24 -0400 +Subject: [PATCH] getPlayerUniqueId API + +Gets the unique ID of the player currently known as the specified player name +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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 10addb128a357e7719854bf4f9d75f5def32b27d..20915e40fbcf28faed603d449a99bf2157fcf972 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1517,6 +1517,25 @@ public final class CraftServer implements Server { + return recipients.size(); + } + ++ // Paper start ++ @Nullable ++ public UUID getPlayerUniqueId(String name) { ++ Player player = Bukkit.getPlayerExact(name); ++ if (player != null) { ++ return player.getUniqueId(); ++ } ++ GameProfile profile; ++ // Only fetch an online UUID in online mode ++ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) { ++ profile = console.getProfileCache().get( name ); ++ } else { ++ // Make an OfflinePlayer using an offline mode UUID since the name has no profile ++ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); ++ } ++ return profile != null ? profile.getId() : null; ++ } ++ // Paper end ++ + @Override + @Deprecated + public OfflinePlayer getOfflinePlayer(String name) { diff --git a/patches/server-remapped/0202-Make-player-data-saving-configurable.patch b/patches/server-remapped/0202-Make-player-data-saving-configurable.patch new file mode 100644 index 0000000000..7a7b4d1993 --- /dev/null +++ b/patches/server-remapped/0202-Make-player-data-saving-configurable.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Mon, 26 Mar 2018 18:30:53 +0300 +Subject: [PATCH] Make player data saving configurable + +Upstream has added a patch which negates the need for this patch, +however, we should still migrate our configuration back upstream, +to prevent unexpected situations + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 52954fc3bf932cfc9d5ce63e3d3cace351305790..05a5abb951abe37f30a719cb75376d2d43c0d252 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -279,4 +279,13 @@ public class PaperConfig { + private static void authenticationServersDownKickMessage() { + authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); + } ++ ++ private static void savePlayerData() { ++ Object val = config.get("settings.save-player-data"); ++ if (val instanceof Boolean) { ++ SpigotConfig.disablePlayerDataSaving = !(Boolean) val; ++ SpigotConfig.config.set("players.disable-saving", SpigotConfig.disableAdvancementSaving); ++ SpigotConfig.save(); ++ } ++ } + } diff --git a/patches/server-remapped/0203-Make-legacy-ping-handler-more-reliable.patch b/patches/server-remapped/0203-Make-legacy-ping-handler-more-reliable.patch new file mode 100644 index 0000000000..72dfa9fd8e --- /dev/null +++ b/patches/server-remapped/0203-Make-legacy-ping-handler-more-reliable.patch @@ -0,0 +1,181 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Wed, 11 Oct 2017 18:22:50 +0200 +Subject: [PATCH] Make legacy ping handler more reliable + +The Minecraft server often fails to respond to old ("legacy") pings +from old Minecraft versions using the protocol used before the switch +to Netty in Minecraft 1.7. + +Due to packet fragmentation[1], we might not have all needed bytes +available when the LegacyPingHandler is called. In this case, it will +run into an error, remove the handler and continue using the modern +protocol. + +This is unlikely to happen for the first two revisions of the legacy +ping protocol (used in Minecraft 1.5.x and older) since the request +consists of only one or two bytes, but happens frequently for the +last/third revision introduced in Minecraft 1.6. + +It has much larger, variable packet sizes due to the inclusion of +the virtual host (the hostname/port used to connect to the server). + +The solution[2] is simple: If we find more than two matching bytes, +we buffer the remaining bytes until we have enough to fully read and +respond to the request. + +[1]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h3-11 +[2]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h4-13 + +diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java +index e2867a3de87a778a897b4963212fa4aab566a643..1d11802876c1a94ecf991cd8249bd6a911c0ac20 100644 +--- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java ++++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java +@@ -15,6 +15,7 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + + private static final Logger LOGGER = LogManager.getLogger(); + private final ServerConnectionListener serverConnectionListener; ++ private ByteBuf buf; // Paper + + public LegacyQueryHandler(ServerConnectionListener networkIo) { + this.serverConnectionListener = networkIo; +@@ -23,6 +24,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) throws Exception { + ByteBuf bytebuf = (ByteBuf) object; + ++ // Paper start - Make legacy ping handler more reliable ++ if (this.buf != null) { ++ try { ++ readLegacy1_6(channelhandlercontext, bytebuf); ++ } finally { ++ bytebuf.release(); ++ } ++ return; ++ } ++ // Paper end + bytebuf.markReaderIndex(); + boolean flag = true; + +@@ -53,6 +64,10 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); + break; + default: ++ // Paper start - Replace with improved version below ++ if (bytebuf.readUnsignedByte() != 0x01 || bytebuf.readUnsignedByte() != 0xFA) return; ++ readLegacy1_6(channelhandlercontext, bytebuf); ++ /* + boolean flag1 = bytebuf.readUnsignedByte() == 1; + + flag1 &= bytebuf.readUnsignedByte() == 250; +@@ -67,15 +82,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + return; + } + +- LegacyQueryHandler.LOGGER.debug("Ping: (1.6) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); +- String s1 = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit +- ByteBuf bytebuf1 = this.createReply(s1); ++ LegacyPingHandler.LOGGER.debug("Ping: (1.6) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); ++ String s1 = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit ++ ByteBuf bytebuf1 = this.a(s1); + + try { +- this.sendFlushAndClose(channelhandlercontext, bytebuf1); ++ this.a(channelhandlercontext, bytebuf1); + } finally { + bytebuf1.release(); + } ++ */ // Paper end - Replace with improved version below + } + + bytebuf.release(); +@@ -93,6 +109,90 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + + } + ++ // Paper start ++ private static String readLegacyString(ByteBuf buf) { ++ int size = buf.readShort() * Character.BYTES; ++ if (!buf.isReadable(size)) { ++ return null; ++ } ++ ++ String result = buf.toString(buf.readerIndex(), size, StandardCharsets.UTF_16BE); ++ buf.skipBytes(size); // toString doesn't increase readerIndex automatically ++ return result; ++ } ++ ++ private void readLegacy1_6(ChannelHandlerContext ctx, ByteBuf part) { ++ ByteBuf buf = this.buf; ++ ++ if (buf == null) { ++ this.buf = buf = ctx.alloc().buffer(); ++ buf.markReaderIndex(); ++ } else { ++ buf.resetReaderIndex(); ++ } ++ ++ buf.writeBytes(part); ++ ++ if (!buf.isReadable(Short.BYTES + Short.BYTES + Byte.BYTES + Short.BYTES + Integer.BYTES)) { ++ return; ++ } ++ ++ String s = readLegacyString(buf); ++ if (s == null) { ++ return; ++ } ++ ++ if (!s.equals("MC|PingHost")) { ++ removeHandler(ctx); ++ return; ++ } ++ ++ if (!buf.isReadable(Short.BYTES) || !buf.isReadable(buf.readShort())) { ++ return; ++ } ++ ++ MinecraftServer server = this.serverConnectionListener.getServer(); ++ int protocolVersion = buf.readByte(); ++ String host = readLegacyString(buf); ++ if (host == null) { ++ removeHandler(ctx); ++ return; ++ } ++ int port = buf.readInt(); ++ ++ if (buf.isReadable()) { ++ removeHandler(ctx); ++ return; ++ } ++ ++ buf.release(); ++ this.buf = null; ++ ++ LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); ++ ++ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", ++ Byte.MAX_VALUE, server.getServerVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); ++ this.sendFlushAndClose(ctx, this.createReply(response)); ++ } ++ ++ private void removeHandler(ChannelHandlerContext ctx) { ++ ByteBuf buf = this.buf; ++ this.buf = null; ++ ++ buf.resetReaderIndex(); ++ ctx.pipeline().remove(this); ++ ctx.fireChannelRead(buf); ++ } ++ ++ @Override ++ public void handlerRemoved(ChannelHandlerContext ctx) { ++ if (this.buf != null) { ++ this.buf.release(); ++ this.buf = null; ++ } ++ } ++ // Paper end ++ + private void sendFlushAndClose(ChannelHandlerContext ctx, ByteBuf buf) { + ctx.pipeline().firstContext().writeAndFlush(buf).addListener(ChannelFutureListener.CLOSE); + } diff --git a/patches/server-remapped/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch b/patches/server-remapped/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch new file mode 100644 index 0000000000..90d915afd6 --- /dev/null +++ b/patches/server-remapped/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch @@ -0,0 +1,154 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Wed, 11 Oct 2017 19:30:51 +0200 +Subject: [PATCH] Call PaperServerListPingEvent for legacy pings + + +diff --git a/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java +new file mode 100644 +index 0000000000000000000000000000000000000000..74c012fd40491f1d870fbc1aa8c318a2197eb106 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java +@@ -0,0 +1,73 @@ ++package com.destroystokyo.paper.network; ++ ++import com.destroystokyo.paper.event.server.PaperServerListPingEvent; ++import net.minecraft.server.MinecraftServer; ++import org.apache.commons.lang3.StringUtils; ++import org.bukkit.ChatColor; ++ ++import java.net.InetSocketAddress; ++ ++import javax.annotation.Nullable; ++ ++public final class PaperLegacyStatusClient implements StatusClient { ++ ++ private final InetSocketAddress address; ++ private final int protocolVersion; ++ @Nullable private final InetSocketAddress virtualHost; ++ ++ private PaperLegacyStatusClient(InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { ++ this.address = address; ++ this.protocolVersion = protocolVersion; ++ this.virtualHost = virtualHost; ++ } ++ ++ @Override ++ public InetSocketAddress getAddress() { ++ return this.address; ++ } ++ ++ @Override ++ public int getProtocolVersion() { ++ return this.protocolVersion; ++ } ++ ++ @Nullable ++ @Override ++ public InetSocketAddress getVirtualHost() { ++ return this.virtualHost; ++ } ++ ++ @Override ++ public boolean isLegacy() { ++ return true; ++ } ++ ++ public static PaperServerListPingEvent processRequest(MinecraftServer server, ++ InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { ++ ++ PaperServerListPingEvent event = new PaperServerListPingEventImpl(server, ++ new PaperLegacyStatusClient(address, protocolVersion, virtualHost), Byte.MAX_VALUE, null); ++ server.server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return null; ++ } ++ ++ return event; ++ } ++ ++ public static String getMotd(PaperServerListPingEvent event) { ++ return getFirstLine(event.getMotd()); ++ } ++ ++ public static String getUnformattedMotd(PaperServerListPingEvent event) { ++ // Strip color codes and all other occurrences of the color char (because it's used as delimiter) ++ return getFirstLine(StringUtils.remove(ChatColor.stripColor(event.getMotd()), ChatColor.COLOR_CHAR)); ++ } ++ ++ private static String getFirstLine(String s) { ++ int pos = s.indexOf('\n'); ++ return pos >= 0 ? s.substring(0, pos) : s; ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java +index 1d11802876c1a94ecf991cd8249bd6a911c0ac20..dfe2cd46f2432dca2028b7436c4108e3f190787f 100644 +--- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java ++++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java +@@ -1,5 +1,7 @@ + package net.minecraft.server.network; + ++import com.destroystokyo.paper.network.PaperLegacyStatusClient; ++ + import io.netty.buffer.ByteBuf; + import io.netty.buffer.Unpooled; + import io.netty.channel.ChannelFutureListener; +@@ -46,12 +48,19 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + MinecraftServer minecraftserver = this.serverConnectionListener.getServer(); + int i = bytebuf.readableBytes(); + String s; +- org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit ++ //org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit // Paper ++ com.destroystokyo.paper.event.server.PaperServerListPingEvent event; // Paper + + switch (i) { + case 0: + LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); +- s = String.format("%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit ++ // Paper start - Call PaperServerListPingEvent and use results ++ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 39, null); ++ if (event == null) { ++ channelhandlercontext.close(); ++ break; ++ } ++ s = String.format("%s\u00a7%d\u00a7%d", PaperLegacyStatusClient.getUnformattedMotd(event), event.getNumPlayers(), event.getMaxPlayers()); + this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); + break; + case 1: +@@ -60,7 +69,14 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + } + + LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); +- s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit ++ // Paper start - Call PaperServerListPingEvent and use results ++ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 127, null); // Paper ++ if (event == null) { ++ channelhandlercontext.close(); ++ break; ++ } ++ s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", new Object[] { event.getProtocolVersion(), minecraftserver.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()}); // CraftBukkit ++ // Paper end + this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); + break; + default: +@@ -170,8 +186,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + + LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); + +- String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", +- Byte.MAX_VALUE, server.getServerVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); ++ InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port); ++ com.destroystokyo.paper.event.server.PaperServerListPingEvent event = PaperLegacyStatusClient.processRequest( ++ server, (InetSocketAddress) ctx.channel().remoteAddress(), protocolVersion, virtualHost); ++ if (event == null) { ++ ctx.close(); ++ return; ++ } ++ ++ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", event.getProtocolVersion(), event.getVersion(), ++ PaperLegacyStatusClient.getMotd(event), event.getNumPlayers(), event.getMaxPlayers()); + this.sendFlushAndClose(ctx, this.createReply(response)); + } + diff --git a/patches/server-remapped/0205-Flag-to-disable-the-channel-limit.patch b/patches/server-remapped/0205-Flag-to-disable-the-channel-limit.patch new file mode 100644 index 0000000000..467dda42a9 --- /dev/null +++ b/patches/server-remapped/0205-Flag-to-disable-the-channel-limit.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 31 Mar 2018 17:04:26 +0100 +Subject: [PATCH] Flag to disable the channel limit + +In some enviroments, the channel limit set by spigot can cause issues, +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 9d853733ff9054cc48925e22c8bb3c8d9b898808..46338fe5693003698de9c7b37a860c3481e06233 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -143,6 +143,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + // Paper start + private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; + private String resourcePackHash; ++ private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit + // Paper end + + public CraftPlayer(CraftServer server, ServerPlayer entity) { +@@ -1576,7 +1577,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void addChannel(String channel) { +- Preconditions.checkState(channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); ++ Preconditions.checkState(DISABLE_CHANNEL_LIMIT || channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); // Paper - flag to disable channel limit + channel = StandardMessenger.validateAndCorrectChannel(channel); + if (channels.add(channel)) { + server.getPluginManager().callEvent(new PlayerRegisterChannelEvent(this, channel)); diff --git a/patches/server-remapped/0206-Add-method-to-open-already-placed-sign.patch b/patches/server-remapped/0206-Add-method-to-open-already-placed-sign.patch new file mode 100644 index 0000000000..9a923369d1 --- /dev/null +++ b/patches/server-remapped/0206-Add-method-to-open-already-placed-sign.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 1 Apr 2018 02:29:37 +0300 +Subject: [PATCH] Add method to open already placed sign + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index c62d01719f21762aa10294815ab88e450e4dce3f..4aec1c2b26d48cb5bea3dfb9e183526763bdb98f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -28,6 +28,7 @@ import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CraftingTableBlock; + import net.minecraft.world.level.block.EnchantmentTableBlock; + import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import org.bukkit.GameMode; + import org.bukkit.Location; +@@ -604,6 +605,17 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + } + } + ++ // Paper start - Add method to open already placed sign ++ @Override ++ public void openSign(org.bukkit.block.Sign sign) { ++ org.apache.commons.lang.Validate.isTrue(sign.getWorld().equals(this.getWorld()), "Sign must be in the same world as player is in"); ++ org.bukkit.craftbukkit.block.CraftSign craftSign = (org.bukkit.craftbukkit.block.CraftSign) sign; ++ SignBlockEntity teSign = craftSign.getTileEntity(); ++ // Make sign editable temporarily, will be set back to false in PlayerConnection later ++ teSign.isEditable = true; ++ getHandle().openTextEdit(teSign); ++ } ++ // Paper end + @Override + public boolean dropItem(boolean dropAll) { + return getHandle().drop(dropAll); diff --git a/patches/server-remapped/0207-Configurable-sprint-interruption-on-attack.patch b/patches/server-remapped/0207-Configurable-sprint-interruption-on-attack.patch new file mode 100644 index 0000000000..dfe307fc2f --- /dev/null +++ b/patches/server-remapped/0207-Configurable-sprint-interruption-on-attack.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Sat, 14 Apr 2018 20:20:46 +0200 +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/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 48f0385c7203c7955de5a015f3dc42be2ab7b681..cebf1a623a9bec72d60fdd23dda01868ef6431d4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -358,4 +358,9 @@ public class PaperWorldConfig { + private void squidMaxSpawnHeight() { + squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); + } ++ ++ public boolean disableSprintInterruptionOnAttack; ++ private void disableSprintInterruptionOnAttack() { ++ disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", 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 c4aa824d03de952fe6b306e539baa47af979add1..552920f59aae9de2cad3edcdc8c48a91dff49093 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1180,7 +1180,11 @@ public abstract class Player extends LivingEntity { + } + + this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); +- this.setSprinting(false); ++ // Paper start - Configuration option to disable automatic sprint interruption ++ if (!level.paperConfig.disableSprintInterruptionOnAttack) { ++ this.setSprinting(false); ++ } ++ // Paper end + } + + if (flag3) { diff --git a/patches/server-remapped/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/patches/server-remapped/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch new file mode 100644 index 0000000000..68cdac63bd --- /dev/null +++ b/patches/server-remapped/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 0x22 <0x22@futureclient.net> +Date: Thu, 26 Apr 2018 04:41:11 -0400 +Subject: [PATCH] Fix exploit that allowed colored signs to be created + + +diff --git a/src/main/java/net/minecraft/SharedConstants.java b/src/main/java/net/minecraft/SharedConstants.java +index a70c3d25930e7414fc9e897de8d2e0c12f11c0e4..04b8783417bbcd826d6d1c302551fbad9c48bd01 100644 +--- a/src/main/java/net/minecraft/SharedConstants.java ++++ b/src/main/java/net/minecraft/SharedConstants.java +@@ -20,6 +20,7 @@ public class SharedConstants { + return chr != 167 && chr >= ' ' && chr != 127; + } + ++ public static String filterAllowedChatCharacters(String input) { return filterText(input); } // Paper - OBFHELPER + public static String filterText(String s) { + StringBuilder stringbuilder = new StringBuilder(); + char[] achar = s.toCharArray(); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 8d0c44b6c2c99d5161c5d4b79209b79ff6db75e4..fb36aa08cd2fbe3f7262dccb8cf0f7cae55aea9c 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2786,7 +2786,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + List lines = new java.util.ArrayList<>(); + + for (int i = 0; i < list.size(); ++i) { +- lines.add(net.kyori.adventure.text.Component.text(list.get(i))); ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. + } + SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); + this.craftServer.getPluginManager().callEvent(event); diff --git a/patches/server-remapped/0209-EndermanEscapeEvent.patch b/patches/server-remapped/0209-EndermanEscapeEvent.patch new file mode 100644 index 0000000000..038bdea2df --- /dev/null +++ b/patches/server-remapped/0209-EndermanEscapeEvent.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 13:15:55 -0400 +Subject: [PATCH] EndermanEscapeEvent + +Fires an event anytime an enderman intends to teleport away from the player + +You may cancel this, enabling ranged attacks to damage the enderman for example. + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index 1c2998c89fd660d6b26b7ff48cddd1862b9b1828..1b9c77666204765a3ed5648b0f8eaa820f578e58 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster; + + import java.util.EnumSet; + import java.util.Optional; ++import com.destroystokyo.paper.event.entity.EndermanEscapeEvent; // Paper + import java.util.Random; + import java.util.UUID; + import java.util.function.Predicate; +@@ -109,6 +110,12 @@ public class EnderMan extends Monster implements NeutralMob { + setGoalTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, true); + } + ++ // Paper start ++ private boolean tryEscape(EndermanEscapeEvent.Reason reason) { ++ return new EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent(); ++ } ++ // Paper end ++ + @Override + public boolean setGoalTarget(LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { + if (!super.setGoalTarget(entityliving, reason, fireEvent)) { +@@ -262,7 +269,7 @@ public class EnderMan extends Monster implements NeutralMob { + if (this.level.isDay() && this.tickCount >= this.targetChangeTime + 600) { + float f = this.getBrightness(); + +- if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) { ++ if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper + this.setTarget((LivingEntity) null); + this.teleport(); + } +@@ -360,17 +367,19 @@ public class EnderMan extends Monster implements NeutralMob { + if (this.isInvulnerableTo(source)) { + return false; + } else if (source instanceof IndirectEntityDamageSource) { ++ if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start + for (int i = 0; i < 64; ++i) { + if (this.teleport()) { + return true; + } + } ++ } // Paper end + + return false; + } else { + boolean flag = super.hurt(source, amount); + +- if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) { ++ if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0 && this.tryEscape(source == DamageSource.DROWN ? EndermanEscapeEvent.Reason.DROWN : EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - use to be critical hits as else, but mojang removed critical hits in 1.16.2 due to MC-185684 + this.teleport(); + } + +@@ -515,7 +524,7 @@ public class EnderMan extends Monster implements NeutralMob { + + static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal { + +- private final EnderMan enderman; ++ private final EnderMan enderman; public final EnderMan getEnderman() { return this.enderman; } // Paper - OBFHELPER + private Player pendingTarget; + private int aggroTime; + private int teleportTime; +@@ -578,7 +587,7 @@ public class EnderMan extends Monster implements NeutralMob { + } else { + if (this.target != null && !this.enderman.isPassenger()) { + if (this.enderman.isLookingAtMe((Player) this.target)) { +- if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D) { ++ if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D && this.getEnderman().tryEscape(EndermanEscapeEvent.Reason.STARE)) { // Paper + this.enderman.teleport(); + } + diff --git a/patches/server-remapped/0210-Enderman.teleportRandomly.patch b/patches/server-remapped/0210-Enderman.teleportRandomly.patch new file mode 100644 index 0000000000..f76f4023f9 --- /dev/null +++ b/patches/server-remapped/0210-Enderman.teleportRandomly.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 13:29:44 -0400 +Subject: [PATCH] Enderman.teleportRandomly() + +Ability to trigger the vanilla "teleport randomly" mechanic of an enderman. + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index 1b9c77666204765a3ed5648b0f8eaa820f578e58..1981c08af85b16d45531ffae4fe790bb31edec04 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -278,6 +278,7 @@ public class EnderMan extends Monster implements NeutralMob { + super.customServerAiStep(); + } + ++ public final boolean teleportRandomly() { return this.teleport(); } // Paper - OBFHELPER + protected boolean teleport() { + if (!this.level.isClientSide() && this.isAlive()) { + double d0 = this.getX() + (this.random.nextDouble() - 0.5D) * 64.0D; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java +index d17ed71e800ebcd12b69745f239fa7dbc8a0c808..1edb45490b35b6517201acc8551da8d3c5a489de 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java +@@ -16,6 +16,7 @@ public class CraftEnderman extends CraftMonster implements Enderman { + super(server, entity); + } + ++ @Override public boolean teleportRandomly() { return getHandle().teleportRandomly(); } // Paper + @Override + public MaterialData getCarriedMaterial() { + BlockState blockData = getHandle().getCarriedBlock(); diff --git a/patches/server-remapped/0211-Block-Enderpearl-Travel-Exploit.patch b/patches/server-remapped/0211-Block-Enderpearl-Travel-Exploit.patch new file mode 100644 index 0000000000..47a535288c --- /dev/null +++ b/patches/server-remapped/0211-Block-Enderpearl-Travel-Exploit.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 17:15:26 -0400 +Subject: [PATCH] Block Enderpearl Travel Exploit + +Players are able to use alt accounts and enderpearls to travel +long distances utilizing the pearls in unloaded chunks and loading +the chunk later when convenient. + +This disables that by not saving the thrower when the chunk is unloaded. + +This is mainly useful for survival servers that do not allow freeform teleporting. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index cebf1a623a9bec72d60fdd23dda01868ef6431d4..e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -363,4 +363,10 @@ public class PaperWorldConfig { + private void disableSprintInterruptionOnAttack() { + disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); + } ++ ++ public boolean disableEnderpearlExploit = true; ++ private void disableEnderpearlExploit() { ++ disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); ++ log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index 14ed4f212a9c9c3128c4ddbef7b2e243c925b509..16b554675a276471851846d4f2bea06fdcc166d9 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -62,6 +62,7 @@ public abstract class Projectile extends Entity { + protected void readAdditionalSaveData(CompoundTag tag) { + if (tag.hasUUID("Owner")) { + this.ownerUUID = tag.getUUID("Owner"); ++ if (this instanceof ThrownEnderpearl && this.level != null && this.level.paperConfig.disableEnderpearlExploit) { this.ownerUUID = null; } // Paper - Don't store shooter name for pearls to block enderpearl travel exploit + } + + this.leftOwner = tag.getBoolean("LeftOwner"); diff --git a/patches/server-remapped/0212-Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/server-remapped/0212-Expand-World.spawnParticle-API-and-add-Builder.patch new file mode 100644 index 0000000000..e2c16b5648 --- /dev/null +++ b/patches/server-remapped/0212-Expand-World.spawnParticle-API-and-add-Builder.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 15 Aug 2017 22:29:12 -0400 +Subject: [PATCH] Expand World.spawnParticle API and add Builder + +Adds ability to control who receives it and who is the source/sender (vanish API) +the standard API is to send the packet to everyone in the world, which is ineffecient. +Adds an option to control the force mode of the particle. + +This adds a new Builder API which is much friendlier to use. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 20650bfd10abfa010e71cfeede06c461d50d19a3..5110f2c70d96284e8e7592b3d89266b867b9a466 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -164,7 +164,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final Int2ObjectMap entitiesById = new Int2ObjectLinkedOpenHashMap(); + private final Map entitiesByUuid = Maps.newHashMap(); + private final Queue toAddAfterTick = Queues.newArrayDeque(); +- private final List players = Lists.newArrayList(); ++ public final List players = Lists.newArrayList(); // Paper - private -> public + public final ServerChunkCache chunkSource; // Paper - public + boolean tickingEntities; + private final MinecraftServer server; +@@ -1472,12 +1472,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + public int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { ++ // Paper start - Particle API Expansion ++ return sendParticles(players, sender, t0, d0, d1, d2, i, d3, d4, d5, d6, force); ++ } ++ public int sendParticles(List receivers, ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { ++ // Paper end + ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); + // CraftBukkit end + int j = 0; + +- for (int k = 0; k < this.players.size(); ++k) { +- ServerPlayer entityplayer = (ServerPlayer) this.players.get(k); ++ for (Player entityhuman : receivers) { // Paper - Particle API Expansion ++ ServerPlayer entityplayer = (ServerPlayer) entityhuman; // Paper - Particle API Expansion + if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit + + if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 88658d4deacc29128c537e2e02fdc8f684090a2c..beb7219312be5143a50b0841c25efea5dbcc1267 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2334,11 +2334,17 @@ public class CraftWorld implements World { + + @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) { ++ // Paper start - Particle API Expansion ++ spawnParticle(particle, null, null, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, force); ++ } ++ public void spawnParticle(Particle particle, List receivers, Player sender, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) { ++ // Paper end + if (data != null && !particle.getDataType().isInstance(data)) { + throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); + } + getHandle().sendParticles( +- null, // Sender ++ receivers == null ? getHandle().players : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API Expansion ++ sender != null ? ((CraftPlayer) sender).getHandle() : null, // Sender // Paper - Particle API Expansion + CraftParticle.toNMS(particle, data), // Particle + x, y, z, // Position + count, // Count diff --git a/patches/server-remapped/0213-EndermanAttackPlayerEvent.patch b/patches/server-remapped/0213-EndermanAttackPlayerEvent.patch new file mode 100644 index 0000000000..3341055b48 --- /dev/null +++ b/patches/server-remapped/0213-EndermanAttackPlayerEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 1 May 2018 20:18:54 -0400 +Subject: [PATCH] EndermanAttackPlayerEvent + +Allow control over whether or not an enderman aggros a player. + +This allows you to override/extend the pumpkin/stare logic. + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index 1981c08af85b16d45531ffae4fe790bb31edec04..d190b58bea310f4006ea3deaf0d42c502d441284 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -221,20 +221,28 @@ public class EnderMan extends Monster implements NeutralMob { + this.readPersistentAngerSaveData((ServerLevel) this.level, tag); + } + ++ // Paper start - OBFHELPER - ok not really, but verify this on updates + private boolean isLookingAtMe(Player player) { +- ItemStack itemstack = (ItemStack) player.inventory.armor.get(3); ++ boolean shouldAttack = g_real(player); ++ com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) player.getBukkitEntity()); ++ event.setCancelled(!shouldAttack); ++ return event.callEvent(); ++ } ++ private boolean g_real(Player entityhuman) { ++ // Paper end ++ ItemStack itemstack = (ItemStack) entityhuman.inventory.armor.get(3); + + if (itemstack.getItem() == Blocks.CARVED_PUMPKIN.asItem()) { + return false; + } else { +- Vec3 vec3d = player.getViewVector(1.0F).normalize(); +- Vec3 vec3d1 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ()); ++ Vec3 vec3d = entityhuman.getViewVector(1.0F).normalize(); ++ Vec3 vec3d1 = new Vec3(this.getX() - entityhuman.getX(), this.getEyeY() - entityhuman.getEyeY(), this.getZ() - entityhuman.getZ()); + double d0 = vec3d1.length(); + + vec3d1 = vec3d1.normalize(); + double d1 = vec3d.dot(vec3d1); + +- return d1 > 1.0D - 0.025D / d0 ? player.canSee(this) : false; ++ return d1 > 1.0D - 0.025D / d0 ? entityhuman.canSee(this) : false; + } + } + diff --git a/patches/server-remapped/0214-WitchConsumePotionEvent.patch b/patches/server-remapped/0214-WitchConsumePotionEvent.patch new file mode 100644 index 0000000000..b17791b352 --- /dev/null +++ b/patches/server-remapped/0214-WitchConsumePotionEvent.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 16 May 2018 20:35:16 -0400 +Subject: [PATCH] WitchConsumePotionEvent + +Fires when a witch consumes the potion in their hand + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java +index 9b0269bdd25123f5c0662187de49a869ead3ee81..dd5976d81ff57e8691ba60f425af37572edd26e7 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java +@@ -124,7 +124,11 @@ public class Witch extends Raider implements RangedAttackMob { + + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + if (itemstack.getItem() == Items.POTION) { +- List list = PotionUtils.getMobEffects(itemstack); ++ // Paper start ++ com.destroystokyo.paper.event.entity.WitchConsumePotionEvent event = new com.destroystokyo.paper.event.entity.WitchConsumePotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); ++ ++ List list = event.callEvent() ? PotionUtils.getMobEffects(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion())) : null; ++ // Paper end + + if (list != null) { + Iterator iterator = list.iterator(); diff --git a/patches/server-remapped/0215-WitchThrowPotionEvent.patch b/patches/server-remapped/0215-WitchThrowPotionEvent.patch new file mode 100644 index 0000000000..0630f7d920 --- /dev/null +++ b/patches/server-remapped/0215-WitchThrowPotionEvent.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 16 May 2018 20:44:58 -0400 +Subject: [PATCH] WitchThrowPotionEvent + +Fired when a witch throws a potion at a player + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java +index dd5976d81ff57e8691ba60f425af37572edd26e7..7cefabfb0d8a264cae24f23c06f1c5f552ff0158 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java +@@ -224,9 +224,16 @@ public class Witch extends Raider implements RangedAttackMob { + potionregistry = Potions.WEAKNESS; + } + ++ // Paper start ++ ItemStack potion = PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potionregistry); ++ com.destroystokyo.paper.event.entity.WitchThrowPotionEvent event = new com.destroystokyo.paper.event.entity.WitchThrowPotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), (org.bukkit.entity.LivingEntity) target.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++ if (!event.callEvent()) { ++ return; ++ } ++ potion = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion()); + ThrownPotion entitypotion = new ThrownPotion(this.level, this); +- +- entitypotion.setItem(PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potionregistry)); ++ entitypotion.setItem(potion); ++ // Paper end + entitypotion.xRot -= -20.0F; + entitypotion.shoot(d0, d1 + (double) (f1 * 0.2F), d2, 0.75F, 8.0F); + if (!this.isSilent()) { diff --git a/patches/server-remapped/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/patches/server-remapped/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch new file mode 100644 index 0000000000..7e80925cf5 --- /dev/null +++ b/patches/server-remapped/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 4 Jun 2018 20:39:20 -0400 +Subject: [PATCH] Allow spawning Item entities with World.spawnEntity + +This API has more capabilities than .dropItem with the Consumer function + +Item can be set inside of the Consumer pre spawn function. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index beb7219312be5143a50b0841c25efea5dbcc1267..2dc9daaeea600fff1f2efddf74b6849fd745a28c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1497,6 +1497,10 @@ public class CraftWorld implements World { + if (Boat.class.isAssignableFrom(clazz)) { + entity = new net.minecraft.world.entity.vehicle.Boat(world, x, y, z); + entity.moveTo(x, y, z, yaw, pitch); ++ // Paper start ++ } else if (org.bukkit.entity.Item.class.isAssignableFrom(clazz)) { ++ entity = new ItemEntity(world, x, y, z, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Item.byBlock(net.minecraft.world.level.block.Blocks.DIRT))); ++ // Paper end + } else if (FallingBlock.class.isAssignableFrom(clazz)) { + entity = new FallingBlockEntity(world, x, y, z, world.getBlockState(new BlockPos(x, y, z))); + } else if (Projectile.class.isAssignableFrom(clazz)) { diff --git a/patches/server-remapped/0217-WitchReadyPotionEvent.patch b/patches/server-remapped/0217-WitchReadyPotionEvent.patch new file mode 100644 index 0000000000..2177cecc8f --- /dev/null +++ b/patches/server-remapped/0217-WitchReadyPotionEvent.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Jun 2018 22:47:26 -0400 +Subject: [PATCH] WitchReadyPotionEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java +index 7cefabfb0d8a264cae24f23c06f1c5f552ff0158..a37ee32b46aa87be6e3eeca2892b4e7294fd1aef 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java +@@ -157,7 +157,11 @@ public class Witch extends Raider implements RangedAttackMob { + } + + if (potionregistry != null) { +- this.setItemSlot(EquipmentSlot.MAINHAND, PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry)); ++ // Paper start ++ ItemStack potion = PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry); ++ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++ this.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++ // Paper end + this.usingTime = this.getMainHandItem().getUseDuration(); + this.setUsingItem(true); + if (!this.isSilent()) { diff --git a/patches/server-remapped/0218-ItemStack-getMaxItemUseDuration.patch b/patches/server-remapped/0218-ItemStack-getMaxItemUseDuration.patch new file mode 100644 index 0000000000..2b415bf929 --- /dev/null +++ b/patches/server-remapped/0218-ItemStack-getMaxItemUseDuration.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Jun 2018 23:00:29 -0400 +Subject: [PATCH] ItemStack#getMaxItemUseDuration + +Allows you to determine how long it takes to use a usable/consumable item + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index a0815c0d7f68f345dc48c73b8253de637c7a3e0f..34187197efd5ceff0503682dc6ce313220ca916f 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -604,6 +604,7 @@ public final class ItemStack { + this.getItem().onCraftedBy(this, world, player); + } + ++ public int getItemUseMaxDuration() { return getUseDuration(); } // Paper - OBFHELPER + public int getUseDuration() { + return this.getItem().getUseDuration(this); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index 5f0ccdeb8565505278caa591f7390047eab49cf4..44caf00330e4f4f74745973dbe709980f0b61269 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -173,6 +173,13 @@ public final class CraftItemStack extends ItemStack { + return (handle == null) ? Material.AIR.getMaxStackSize() : handle.getItem().getMaxStackSize(); + } + ++ // Paper start ++ @Override ++ public int getMaxItemUseDuration() { ++ return handle == null ? 0 : handle.getItemUseMaxDuration(); ++ } ++ // Paper end ++ + @Override + public void addUnsafeEnchantment(Enchantment ench, int level) { + Validate.notNull(ench, "Cannot add null enchantment"); diff --git a/patches/server-remapped/0219-Implement-EntityTeleportEndGatewayEvent.patch b/patches/server-remapped/0219-Implement-EntityTeleportEndGatewayEvent.patch new file mode 100644 index 0000000000..007bf52a29 --- /dev/null +++ b/patches/server-remapped/0219-Implement-EntityTeleportEndGatewayEvent.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 9 Jun 2018 14:08:39 +0200 +Subject: [PATCH] Implement EntityTeleportEndGatewayEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +index 2c974f9801d209907733bed8e6c4c9ef46e2b610..b70e0633435a272ae1e9fbd12d7f18862de0b951 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -191,9 +191,20 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements + + } + // CraftBukkit end ++ // Paper start - EntityTeleportEndGatewayEvent - replicated from above ++ org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity = entity.getBukkitEntity(); ++ org.bukkit.Location location = new Location(level.getWorld(), (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); ++ location.setPitch(bukkitEntity.getLocation().getPitch()); ++ location.setYaw(bukkitEntity.getLocation().getYaw()); ++ ++ com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent event = new com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent(bukkitEntity, bukkitEntity.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(level, this.getBlockPos()).getBlock())); ++ if (!event.callEvent()) { ++ return; ++ } ++ // Paper end + + entity1.setPortalCooldown(); +- entity1.teleportToWithTicket((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D); ++ entity1.teleportToWithTicket(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); // Paper + } + + this.triggerCooldown(); diff --git a/patches/server-remapped/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/patches/server-remapped/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch new file mode 100644 index 0000000000..1bda08648d --- /dev/null +++ b/patches/server-remapped/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 Jun 2018 01:18:49 -0400 +Subject: [PATCH] Unset Ignited flag on cancel of Explosion Event + +Otherwise the creeper infinite explodes + +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 8f8d0a23d011936150854a0606be3d63b18c57af..d9b5cf8ac01289801ded01d928fa7ead96551be5 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +@@ -47,7 +47,7 @@ public class Creeper extends Monster { + + private static final EntityDataAccessor DATA_SWELL_DIR = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_IS_POWERED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); +- private static final EntityDataAccessor DATA_IS_IGNITED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); ++ private static final EntityDataAccessor DATA_IS_IGNITED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); private static final EntityDataAccessor isIgnitedDW = DATA_IS_IGNITED; // Paper OBFHELPER + private int oldSwell; + public int swell; // PAIL + public int maxSwell = 30; +@@ -252,6 +252,7 @@ public class Creeper extends Monster { + this.spawnLingeringCloud(); + } else { + swell = 0; ++ this.entityData.set(isIgnitedDW, Boolean.valueOf(false)); // Paper + } + // CraftBukkit end + } diff --git a/patches/server-remapped/0221-Fix-CraftEntity-hashCode.patch b/patches/server-remapped/0221-Fix-CraftEntity-hashCode.patch new file mode 100644 index 0000000000..dbc0942196 --- /dev/null +++ b/patches/server-remapped/0221-Fix-CraftEntity-hashCode.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 Jun 2018 20:20:15 -0400 +Subject: [PATCH] Fix CraftEntity hashCode + +hashCodes are not allowed to change, however bukkit used a value +that does change, the entityId. + +When an entity is teleported dimensions, the entity reference is +replaced with a new one with a new entity ID. + +For hashCode, we can simply use the UUID's hashCode to keep +the hashCode from changing. + +equals() is ok to use getEntityId() because equals() should only +be true if both the left and right are the same reference. + +Since entity ids can not duplicate during runtime, this +check is essentially the same as this.getHandle() == other.getHandle() + +However, replaced it too to make it clearer of intent. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index ecb5f5ca547930f91602d539e541964cd9f10287..e1bbaf620f3ed2a6cb9ce8007a78c4cee47b653e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -745,14 +745,15 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return false; + } + final CraftEntity other = (CraftEntity) obj; +- return (this.getEntityId() == other.getEntityId()); ++ return (this.getHandle() == other.getHandle()); // Paper - while logically the same, this is clearer + } + ++ // Paper - Fix hashCode. entity ID's are not static. ++ // A CraftEntity can change reference to a new entity with a new ID, and hash codes should never change + @Override + public int hashCode() { +- int hash = 7; +- hash = 29 * hash + this.getEntityId(); +- return hash; ++ return getUniqueId().hashCode(); ++ // Paper end + } + + @Override diff --git a/patches/server-remapped/0222-Configurable-Alternative-LootPool-Luck-Formula.patch b/patches/server-remapped/0222-Configurable-Alternative-LootPool-Luck-Formula.patch new file mode 100644 index 0000000000..5a10f8c4d8 --- /dev/null +++ b/patches/server-remapped/0222-Configurable-Alternative-LootPool-Luck-Formula.patch @@ -0,0 +1,118 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 15 Jun 2018 00:30:32 -0400 +Subject: [PATCH] Configurable Alternative LootPool Luck Formula + +Rewrites the Vanilla luck application formula so that luck can be +applied to items that do not have any quality defined. + +See: https://luckformula.emc.gs for data and details +----------- + +The rough summary is: +My goal was that in a pool, when luck was applied, the pool +rebalances so the percentages for bigger items is +lowered and smaller items is boosted. + +Do this by boosting and then reducing the weight value, +so that larger numbers are penalized more than smaller numbers. +resulting in a larger reduction of entries for more common +items than the reduction on small weights, +giving smaller weights more of a chance + +----------- + +This work kind of obsoletes quality, but quality would be useful +for 2 items with same weight that you want luck to impact +in varying directions. + +Fishing still falls into that as the weights are closer, so luck +will invalidate junk more. + +This change will result in some major changes to fishing formulas. + +----------- + +I would love to see this change in Vanilla, so Mojang please pull :) + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 05a5abb951abe37f30a719cb75376d2d43c0d252..77a03abd59db4a43f6f2d59d4c7ef176e782f205 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -288,4 +288,12 @@ public class PaperConfig { + SpigotConfig.save(); + } + } ++ ++ public static boolean useAlternativeLuckFormula = false; ++ private static void useAlternativeLuckFormula() { ++ useAlternativeLuckFormula = getBoolean("settings.use-alternative-luck-formula", false); ++ if (useAlternativeLuckFormula) { ++ Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java +index ceb5e5405ed20c8de954847bbb269109107a43fc..d99bc0b8a1e9c4749b176a823b879ced9efdd7d6 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java +@@ -8,7 +8,6 @@ import java.util.List; + import java.util.function.BiFunction; + import java.util.function.Consumer; + import net.minecraft.util.GsonHelper; +-import net.minecraft.util.Mth; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.storage.loot.LootContext; + import net.minecraft.world.level.storage.loot.ValidationContext; +@@ -20,8 +19,8 @@ import org.apache.commons.lang3.ArrayUtils; + + public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer { + +- protected final int weight; +- protected final int quality; ++ protected final int weight; public int getWeight() { return weight; } // Paper - OBFHELPER ++ protected final int quality; public int getQuality() { return quality; } // Paper - OBFHELPER + protected final LootItemFunction[] functions; + private final BiFunction compositeFunction; + private final LootPoolEntry entry = new LootPoolSingletonContainer.EntryBase() { +@@ -152,11 +151,38 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer + + public abstract class EntryBase implements LootPoolEntry { + +- protected EntryBase() {} ++ protected EntryBase() { ++ } + + @Override + public int getWeight(float luck) { +- return Math.max(Mth.floor((float) LootPoolSingletonContainer.this.weight + (float) LootPoolSingletonContainer.this.quality * luck), 0); ++ // Paper start - Offer an alternative loot formula to refactor how luck bonus applies ++ // SEE: https://luckformula.emc.gs for details and data ++ if (lastLuck != null && lastLuck == luck) { ++ return lastWeight; ++ } ++ // This is vanilla ++ float qualityModifer = (float) getQuality() * luck; ++ double baseWeight = (getWeight() + qualityModifer); ++ if (com.destroystokyo.paper.PaperConfig.useAlternativeLuckFormula) { ++ // Random boost to avoid losing precision in the final int cast on return ++ final int weightBoost = 100; ++ baseWeight *= weightBoost; ++ // If we have vanilla 1, bump that down to 0 so nothing is is impacted ++ // vanilla 3 = 300, 200 basis = impact 2% ++ // =($B2*(($B2-100)/100/100)) ++ double impacted = baseWeight * ((baseWeight - weightBoost) / weightBoost / 100); ++ // =($B$7/100) ++ float luckModifier = Math.min(100, luck * 10) / 100; ++ // =B2 - (C2 *($B$7/100)) ++ baseWeight = Math.ceil(baseWeight - (impacted * luckModifier)); ++ } ++ lastLuck = luck; ++ lastWeight = (int) Math.max(0, Math.floor(baseWeight)); ++ return lastWeight; + } + } ++ private Float lastLuck = null; ++ private int lastWeight = 0; ++ // Paper end + } diff --git a/patches/server-remapped/0223-Print-Error-details-when-failing-to-save-player-data.patch b/patches/server-remapped/0223-Print-Error-details-when-failing-to-save-player-data.patch new file mode 100644 index 0000000000..368773ef81 --- /dev/null +++ b/patches/server-remapped/0223-Print-Error-details-when-failing-to-save-player-data.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 15 Jun 2018 20:37:03 -0400 +Subject: [PATCH] Print Error details when failing to save player data + + +diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +index 60fe01e824e4657d2601797d7858d5de339ab255..5b2a558d4d357d0de033ec2d7a9b4686f202c903 100644 +--- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +@@ -43,7 +43,7 @@ public class PlayerDataStorage { + + Util.safeReplaceFile(file1, file, file2); + } catch (Exception exception) { +- PlayerDataStorage.LOGGER.warn("Failed to save player data for {}", entityhuman.getName().getString()); ++ PlayerDataStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getScoreboardName(), exception); // Paper + } + + } diff --git a/patches/server-remapped/0224-Make-shield-blocking-delay-configurable.patch b/patches/server-remapped/0224-Make-shield-blocking-delay-configurable.patch new file mode 100644 index 0000000000..9472536ee6 --- /dev/null +++ b/patches/server-remapped/0224-Make-shield-blocking-delay-configurable.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 16 Jun 2018 01:18:16 -0500 +Subject: [PATCH] Make shield blocking delay configurable + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec..3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -369,4 +369,9 @@ public class PaperWorldConfig { + disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); + log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); + } ++ ++ public int shieldBlockingDelay = 5; ++ private void shieldBlockingDelay() { ++ shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 8b0d1f4fbc43a6f37a5f9c453b5dd142a4f69745..af2e81137d9c686f8d94a1d0d7241619fa1f352c 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3308,7 +3308,7 @@ public abstract class LivingEntity extends Entity { + if (this.isUsingItem() && !this.useItem.isEmpty()) { + Item item = this.useItem.getItem(); + +- return item.getUseAnimation(this.useItem) != UseAnim.BLOCK ? false : item.getUseDuration(this.useItem) - this.useItemRemaining >= 5; ++ return item.getUseAnimation(this.useItem) != UseAnim.BLOCK ? false : item.getUseDuration(this.useItem) - this.useItemRemaining >= getShieldBlockingDelay(); // Paper - shieldBlockingDelay + } else { + return false; + } +@@ -3587,4 +3587,15 @@ public abstract class LivingEntity extends Entity { + public void broadcastBreakEvent(InteractionHand hand) { + this.broadcastBreakEvent(hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); + } ++ // Paper start ++ public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; ++ ++ public int getShieldBlockingDelay() { ++ return shieldBlockingDelay; ++ } ++ ++ public void setShieldBlockingDelay(int shieldBlockingDelay) { ++ this.shieldBlockingDelay = shieldBlockingDelay; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 006f4c71bbcda61b55815e7ceab91731ab062da0..663887d9aecc2823fe7d02a9b108a291cd27102c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -699,5 +699,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setArrowsStuck(int arrows) { + getHandle().setArrowCount(arrows); + } ++ ++ @Override ++ public int getShieldBlockingDelay() { ++ return getHandle().getShieldBlockingDelay(); ++ } ++ ++ @Override ++ public void setShieldBlockingDelay(int delay) { ++ getHandle().setShieldBlockingDelay(delay); ++ } + // Paper end + } diff --git a/patches/server-remapped/0225-Improve-EntityShootBowEvent.patch b/patches/server-remapped/0225-Improve-EntityShootBowEvent.patch new file mode 100644 index 0000000000..4fc5ab999a --- /dev/null +++ b/patches/server-remapped/0225-Improve-EntityShootBowEvent.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 15 Jun 2013 19:51:17 -0400 +Subject: [PATCH] Improve EntityShootBowEvent + +Adds missing call to Illagers and also adds Arrow ItemStack to skeltons + +diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +index e8ad820b11dd1b89e442bb057d5761c90c4b1923..76027a7c9615495af64102744e264d7ba7c9b87e 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -197,7 +197,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + + entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level.getDifficulty().getId() * 4)); + // CraftBukkit start +- org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), null, entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getOriginalItemStack(), entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper + if (event.isCancelled()) { + event.getProjectile().remove(); + return; +diff --git a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +index ab8c41e72c15ee9e5256eba2ba2681a33ce8a8d9..2d07e9cf4c84bc32a7624f65173c4e8a6dc07165 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +@@ -171,8 +171,18 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { + double d3 = (double) Mth.sqrt(d0 * d0 + d2 * d2); + + entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level.getDifficulty().getId() * 4)); ++ // Paper start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getOriginalItemStack(), entityarrow, target.getUsedItemHand(), 0.8F, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ this.level.addFreshEntity(entityarrow); ++ } + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level.addFreshEntity(entityarrow); ++ // Paper end + } + + class IllusionerBlindnessSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { diff --git a/patches/server-remapped/0226-PlayerReadyArrowEvent.patch b/patches/server-remapped/0226-PlayerReadyArrowEvent.patch new file mode 100644 index 0000000000..1250005dcb --- /dev/null +++ b/patches/server-remapped/0226-PlayerReadyArrowEvent.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 18 Jun 2018 01:12:53 -0400 +Subject: [PATCH] PlayerReadyArrowEvent + +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 552920f59aae9de2cad3edcdc8c48a91dff49093..b88d8f2c377322290002e84e217f3f2f6e4e71e8 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -2139,6 +2139,17 @@ public abstract class Player extends LivingEntity { + return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING); + } + ++ // Paper start ++ protected boolean tryReadyArrow(ItemStack bow, ItemStack itemstack) { ++ return !(this instanceof ServerPlayer) || ++ new com.destroystokyo.paper.event.player.PlayerReadyArrowEvent( ++ ((ServerPlayer) this).getBukkitEntity(), ++ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(bow), ++ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack) ++ ).callEvent(); ++ // Paper end ++ } ++ + @Override + public ItemStack getProjectile(ItemStack stack) { + if (!(stack.getItem() instanceof ProjectileWeaponItem)) { +@@ -2155,7 +2166,7 @@ public abstract class Player extends LivingEntity { + for (int i = 0; i < this.inventory.getContainerSize(); ++i) { + ItemStack itemstack2 = this.inventory.getItem(i); + +- if (predicate.test(itemstack2)) { ++ if (predicate.test(itemstack2) && tryReadyArrow(stack, itemstack2)) { // Paper + return itemstack2; + } + } diff --git a/patches/server-remapped/0227-Implement-EntityKnockbackByEntityEvent.patch b/patches/server-remapped/0227-Implement-EntityKnockbackByEntityEvent.patch new file mode 100644 index 0000000000..79e858a274 --- /dev/null +++ b/patches/server-remapped/0227-Implement-EntityKnockbackByEntityEvent.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Mon, 18 Jun 2018 15:46:23 +0200 +Subject: [PATCH] Implement EntityKnockbackByEntityEvent + +This event is called when an entity receives knockback by another entity. + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index af2e81137d9c686f8d94a1d0d7241619fa1f352c..04489a915d11ba970a5188a5a913432ab4ef9faa 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1336,7 +1336,7 @@ public abstract class LivingEntity extends Entity { + } + + this.hurtDir = (float) (Mth.atan2(d1, d0) * 57.2957763671875D - (double) this.yRot); +- this.knockback(0.4F, d0, d1); ++ this.doKnockback(0.4F, d0, d1, entity1); // Paper + } else { + this.hurtDir = (float) ((int) (Math.random() * 2.0D) * 180); + } +@@ -1384,7 +1384,7 @@ public abstract class LivingEntity extends Entity { + } + + protected void blockedByShield(LivingEntity target) { +- target.knockback(0.5F, target.getX() - this.getX(), target.getZ() - this.getZ()); ++ target.doKnockback(0.5F, target.getX() - this.getX(), target.getZ() - this.getZ(), this); // Paper + } + + private boolean checkTotemDeathProtection(DamageSource source) { +@@ -1627,6 +1627,11 @@ public abstract class LivingEntity extends Entity { + } + + public void knockback(float f, double d0, double d1) { ++ // Paper start - add knockbacking entity parameter ++ this.doKnockback(f, d0, d1, null); ++ } ++ public void doKnockback(float f, double d0, double d1, Entity knockingBackEntity) { ++ // Paper end - add knockbacking entity parameter + f = (float) ((double) f * (1.0D - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE))); + if (f > 0.0F) { + this.hasImpulse = true; +@@ -1634,6 +1639,16 @@ public abstract class LivingEntity extends Entity { + Vec3 vec3d1 = (new Vec3(d0, 0.0D, d1)).normalize().scale((double) f); + + this.setDeltaMovement(vec3d.x / 2.0D - vec3d1.x, this.onGround ? Math.min(0.4D, vec3d.y / 2.0D + (double) f) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); ++ ++ // Paper start - call EntityKnockbackByEntityEvent ++ Vec3 currentMot = this.getDeltaMovement(); ++ org.bukkit.util.Vector delta = new org.bukkit.util.Vector(currentMot.x - vec3d.x, currentMot.y - vec3d.y, currentMot.z - vec3d.z); ++ // Restore old velocity to be able to access it in the event ++ this.setDeltaMovement(vec3d); ++ if (knockingBackEntity == null || new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent((org.bukkit.entity.LivingEntity) getBukkitEntity(), knockingBackEntity.getBukkitEntity(), f, delta).callEvent()) { ++ this.setDeltaMovement(vec3d.x + delta.getX(), vec3d.y + delta.getY(), vec3d.z + delta.getZ()); ++ } ++ // Paper end + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index eb35c69bb777ba8d83b2304ff9f862512643e745..f3690ea49cf90c816b8b3554b47d6f2d9dfbe016 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -1566,7 +1566,7 @@ public abstract class Mob extends LivingEntity { + + if (flag) { + if (f1 > 0.0F && target instanceof LivingEntity) { +- ((LivingEntity) target).knockback(f1 * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F))); ++ ((LivingEntity) target).doKnockback(f1 * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)), this); // Paper + this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); + } + +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 b88d8f2c377322290002e84e217f3f2f6e4e71e8..5e6a86b0b8999a5c47d2f9bdd9857ab5f0772033 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1174,7 +1174,7 @@ public abstract class Player extends LivingEntity { + if (flag5) { + if (i > 0) { + if (target instanceof LivingEntity) { +- ((LivingEntity) target).knockback((float) i * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F))); ++ ((LivingEntity) target).doKnockback((float) i * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)), this); // Paper + } else { + target.push((double) (-Mth.sin(this.yRot * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.yRot * 0.017453292F) * (float) i * 0.5F)); + } +@@ -1198,7 +1198,7 @@ public abstract class Player extends LivingEntity { + if (entityliving != this && entityliving != target && !this.isAlliedTo(entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) { + // CraftBukkit start - Only apply knockback if the damage hits + if (entityliving.hurt(DamageSource.playerAttack(this).sweep(), f4)) { +- entityliving.knockback(0.4F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F))); ++ entityliving.doKnockback(0.4F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)), this); // Paper + } + // CraftBukkit end + } diff --git a/patches/server-remapped/0228-Expand-Explosions-API.patch b/patches/server-remapped/0228-Expand-Explosions-API.patch new file mode 100644 index 0000000000..01be1df09c --- /dev/null +++ b/patches/server-remapped/0228-Expand-Explosions-API.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 20 Jun 2018 23:17:24 -0400 +Subject: [PATCH] Expand Explosions API + +Add Entity as a Source capability, and add more API choices, and on Location. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 2dc9daaeea600fff1f2efddf74b6849fd745a28c..9b5a1c3ab8ffde524e194fdeaa8eaef6b286b57b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -871,6 +871,11 @@ public class CraftWorld implements World { + public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) { + return !world.explode(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; + } ++ // Paper start ++ public boolean createExplosion(Entity source, Location loc, float power, boolean setFire, boolean breakBlocks) { ++ return !world.explode(source != null ? ((org.bukkit.craftbukkit.entity.CraftEntity) source).getHandle() : null, loc.getX(), loc.getY(), loc.getZ(), power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; ++ } ++ // Paper end + + @Override + public boolean createExplosion(Location loc, float power) { diff --git a/patches/server-remapped/0229-LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/server-remapped/0229-LivingEntity-Hand-Raised-Item-Use-API.patch new file mode 100644 index 0000000000..181103a79c --- /dev/null +++ b/patches/server-remapped/0229-LivingEntity-Hand-Raised-Item-Use-API.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 Jun 2018 00:21:28 -0400 +Subject: [PATCH] LivingEntity Hand Raised/Item Use API + +How long an entity has raised hands to charge an attack or use an item + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 04489a915d11ba970a5188a5a913432ab4ef9faa..205c639d26652befebae925fc6e40976c370710f 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -209,7 +209,7 @@ public abstract class LivingEntity extends Entity { + private float speed; + private int noJumpDelay; + private float absorptionAmount; +- protected ItemStack useItem; ++ public ItemStack useItem; // Paper - public + protected int useItemRemaining; + protected int fallFlyTicks; + private BlockPos lastPos; +@@ -3291,10 +3291,12 @@ public abstract class LivingEntity extends Entity { + return this.useItem; + } + ++ public int getItemUseRemainingTime() { return this.getUseItemRemainingTicks(); } // Paper - OBFHELPER + public int getUseItemRemainingTicks() { + return this.useItemRemaining; + } + ++ public int getHandRaisedTime() { return this.getTicksUsingItem(); } // Paper - OBFHELPER + public int getTicksUsingItem() { + return this.isUsingItem() ? this.useItem.getUseDuration() - this.getUseItemRemainingTicks() : 0; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 663887d9aecc2823fe7d02a9b108a291cd27102c..6dd7a722e10a2727f68318b880f2726bb816f198 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -709,5 +709,30 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setShieldBlockingDelay(int delay) { + getHandle().setShieldBlockingDelay(delay); + } ++ ++ @Override ++ public ItemStack getActiveItem() { ++ return getHandle().useItem.asBukkitMirror(); ++ } ++ ++ @Override ++ public int getItemUseRemainingTime() { ++ return getHandle().getItemUseRemainingTime(); ++ } ++ ++ @Override ++ public int getHandRaisedTime() { ++ return getHandle().getHandRaisedTime(); ++ } ++ ++ @Override ++ public boolean isHandRaised() { ++ return getHandle().isUsingItem(); ++ } ++ ++ @Override ++ public org.bukkit.inventory.EquipmentSlot getHandRaised() { ++ return getHandle().getUsedItemHand() == net.minecraft.world.InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; ++ } + // Paper end + } diff --git a/patches/server-remapped/0230-RangedEntity-API.patch b/patches/server-remapped/0230-RangedEntity-API.patch new file mode 100644 index 0000000000..40db6f9590 --- /dev/null +++ b/patches/server-remapped/0230-RangedEntity-API.patch @@ -0,0 +1,171 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 26 Jun 2018 22:00:49 -0400 +Subject: [PATCH] RangedEntity API + +Allows you to determine if an entity is capable of ranged attacks, +and to perform an attack. + +diff --git a/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e75e1d0d833c96af139fd955b2585ec24281b294 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java +@@ -0,0 +1,19 @@ ++package com.destroystokyo.paper.entity; ++ ++import net.minecraft.world.entity.monster.RangedAttackMob; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.LivingEntity; ++ ++public interface CraftRangedEntity extends RangedEntity { ++ T getHandle(); ++ ++ @Override ++ default void rangedAttack(LivingEntity target, float charge) { ++ getHandle().rangedAttack(((CraftLivingEntity) target).getHandle(), charge); ++ } ++ ++ @Override ++ default void setChargingAttack(boolean raiseHands) { ++ getHandle().setChargingAttack(raiseHands); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java b/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java +index b3ad4d54eeb1b894c24a5a76e8b12b8d9568cd56..ae10f3933fe78f74995952a6a8acf09ef4e99823 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java ++++ b/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java +@@ -4,5 +4,8 @@ import net.minecraft.world.entity.LivingEntity; + + public interface RangedAttackMob { + +- void performRangedAttack(LivingEntity target, float pullProgress); ++ void performRangedAttack(LivingEntity target, float pullProgress); default void rangedAttack(LivingEntity entityliving, float f) { performRangedAttack(entityliving, f); } // Paper - OBFHELPER ++ ++ // - see EntitySkeletonAbstract melee goal ++ void setAggressive(boolean flag); default void setChargingAttack(boolean charging) { setAggressive(charging); }; // Paper + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java +index 34cb8062168258bfd168826ceeb2fde669f6d1a8..03e2acd4829da449a471b0fa1a311e74aee114d3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java +@@ -4,7 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.Drowned; + import org.bukkit.entity.EntityType; + +-public class CraftDrowned extends CraftZombie implements Drowned { ++public class CraftDrowned extends CraftZombie implements Drowned, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftDrowned(CraftServer server, net.minecraft.world.entity.monster.Drowned entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java +index 59b866e54e0d7e1dd8815ffa85275e36271113da..bbf7189a0fc9921e7a6007494f91229d9fba0846 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java +@@ -4,7 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Illusioner; + +-public class CraftIllusioner extends CraftSpellcaster implements Illusioner { ++public class CraftIllusioner extends CraftSpellcaster implements Illusioner, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftIllusioner(CraftServer server, net.minecraft.world.entity.monster.Illusioner entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java +index 04f716af67939b2dc34875f722816dd1ffdc4966..ed3b8fcc221d6c0789eb92eb4716d640ba0fec9f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import com.destroystokyo.paper.entity.CraftRangedEntity; + import com.google.common.base.Preconditions; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.inventory.CraftInventoryLlama; +@@ -9,7 +10,7 @@ import org.bukkit.entity.Llama; + import org.bukkit.entity.Llama.Color; + import org.bukkit.inventory.LlamaInventory; + +-public class CraftLlama extends CraftChestedHorse implements Llama { ++public class CraftLlama extends CraftChestedHorse implements Llama, CraftRangedEntity { // Paper + + public CraftLlama(CraftServer server, net.minecraft.world.entity.animal.horse.Llama entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java +index 12bce49fcb164b6311a81024d1749a582ab1be25..c06fea6e0eaf58b8e7441ccf8595d6ca8417526a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java +@@ -13,7 +13,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.Piglin; + import org.bukkit.inventory.Inventory; + +-public class CraftPiglin extends CraftPiglinAbstract implements Piglin { ++public class CraftPiglin extends CraftPiglinAbstract implements Piglin, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftPiglin(CraftServer server, net.minecraft.world.entity.monster.piglin.Piglin entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java +index fc86b8ecc349ed59c9eb6de03086d4027cb4e08d..949260d6750e71f148229955c94bcbaad9d54a2d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java +@@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.Pillager; + import org.bukkit.inventory.Inventory; + +-public class CraftPillager extends CraftIllager implements Pillager { ++public class CraftPillager extends CraftIllager implements Pillager, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftPillager(CraftServer server, net.minecraft.world.entity.monster.Pillager entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +index 4cd3dfd3466f384aab06dacd388e8053b045b046..b2d3244cca4d9d108159f3537d8a9aace3f8e77f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +@@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.Skeleton; + import org.bukkit.entity.Skeleton.SkeletonType; + +-public class CraftSkeleton extends CraftMonster implements Skeleton { ++public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftSkeleton(CraftServer server, AbstractSkeleton entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java +index fcce4aa391d0c448531815e99e0e32c84203c1b8..a7164a921f479c928049d4e812eab50567e96fc2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java +@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Snowman; + +-public class CraftSnowman extends CraftGolem implements Snowman { ++public class CraftSnowman extends CraftGolem implements Snowman, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftSnowman(CraftServer server, SnowGolem entity) { + super(server, entity); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +index 60e00e539d214eb8854a53364c92c3cf55ca1062..d4eeb071dbbfca3ecea256228853bcb5c11f49ee 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +@@ -4,7 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Witch; + +-public class CraftWitch extends CraftRaider implements Witch { ++public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftWitch(CraftServer server, net.minecraft.world.entity.monster.Witch entity) { + super(server, entity); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +index 728a8c0f5781f33bdb096aefb569e9509dda8c89..fdcd680b972da54f9cdb41dff5563e42bd12d8e3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +@@ -7,7 +7,7 @@ import org.bukkit.craftbukkit.boss.CraftBossBar; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Wither; + +-public class CraftWither extends CraftMonster implements Wither { ++public class CraftWither extends CraftMonster implements Wither, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + private BossBar bossBar; + diff --git a/patches/server-remapped/0231-Add-config-to-disable-ender-dragon-legacy-check.patch b/patches/server-remapped/0231-Add-config-to-disable-ender-dragon-legacy-check.patch new file mode 100644 index 0000000000..1ba8695871 --- /dev/null +++ b/patches/server-remapped/0231-Add-config-to-disable-ender-dragon-legacy-check.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 22 Jun 2018 10:38:31 -0500 +Subject: [PATCH] Add config to disable ender dragon legacy check + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77..4813f62d1e382d5ac6971b2244df3f13c80d1950 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -374,4 +374,9 @@ public class PaperWorldConfig { + private void shieldBlockingDelay() { + shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); + } ++ ++ public boolean scanForLegacyEnderDragon = true; ++ private void scanForLegacyEnderDragon() { ++ scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 2386ffeec60851ba192b89bc6fd7ffff9c56aff5..4b18931225ef60dbcffd7fcc20d0e9ce62348a07 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -73,7 +73,7 @@ public class EndDragonFight { + private boolean dragonKilled; + private boolean previouslyKilled; + public UUID dragonUUID; +- private boolean needsStateScanning; ++ private boolean needsStateScanning; private void setScanForLegacyFight(boolean scanForLegacyFight) { this.needsStateScanning = scanForLegacyFight; } private boolean scanForLegacyFight() { return this.needsStateScanning; } // Paper - OBFHELPER + public BlockPos portalLocation; + public DragonRespawnAnimation respawnStage; + private int respawnTime; diff --git a/patches/server-remapped/0232-Implement-World.getEntity-UUID-API.patch b/patches/server-remapped/0232-Implement-World.getEntity-UUID-API.patch new file mode 100644 index 0000000000..6bcd99431d --- /dev/null +++ b/patches/server-remapped/0232-Implement-World.getEntity-UUID-API.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Tue, 3 Jul 2018 16:08:14 +0200 +Subject: [PATCH] Implement World.getEntity(UUID) API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 9b5a1c3ab8ffde524e194fdeaa8eaef6b286b57b..3a3466cd9bbd34dbc0b79567f5579e84a81d6009 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1286,6 +1286,15 @@ public class CraftWorld implements World { + return list; + } + ++ // Paper start - getEntity by UUID API ++ @Override ++ public Entity getEntity(UUID uuid) { ++ Validate.notNull(uuid, "UUID cannot be null"); ++ net.minecraft.world.entity.Entity entity = world.getEntity(uuid); ++ return entity == null ? null : entity.getBukkitEntity(); ++ } ++ // Paper end ++ + @Override + public void save() { + org.spigotmc.AsyncCatcher.catchOp("world save"); // Spigot diff --git a/patches/server-remapped/0233-InventoryCloseEvent-Reason-API.patch b/patches/server-remapped/0233-InventoryCloseEvent-Reason-API.patch new file mode 100644 index 0000000000..c1daa66bf3 --- /dev/null +++ b/patches/server-remapped/0233-InventoryCloseEvent-Reason-API.patch @@ -0,0 +1,228 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 3 Jul 2018 21:56:23 -0400 +Subject: [PATCH] InventoryCloseEvent Reason API + +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/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 5110f2c70d96284e8e7592b3d89266b867b9a466..ea1b15495481157912140bf5de9bf4a949c16910 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1119,7 +1119,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + for (BlockEntity tileentity : chunk.getBlockEntities().values()) { + if (tileentity instanceof net.minecraft.world.Container) { + for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((net.minecraft.world.Container) tileentity).getViewers())) { +- h.closeInventory(); ++ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper + } + } + } +@@ -1177,7 +1177,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // Spigot Start + if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder) { + for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) { +- h.closeInventory(); ++ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper + } + } + // 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 0fa977a31cf945b74f3a046b6be302b10f494ad1..1441a461e749dbfa303095f6b51d655c45f68ce0 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -544,7 +544,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + // Paper end + if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.containerMenu = this.inventoryMenu; + } + +@@ -717,7 +717,7 @@ public class ServerPlayer extends Player implements ContainerListener { + + // SPIGOT-943 - only call if they have an inventory open + if (this.containerMenu != this.inventoryMenu) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DEATH); // Paper + } + + net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure +@@ -1290,7 +1290,7 @@ public class ServerPlayer extends Player implements ContainerListener { + return OptionalInt.empty(); + } else { + if (this.containerMenu != this.inventoryMenu) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + this.nextContainerCounter(); +@@ -1350,7 +1350,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + // CraftBukkit end + if (this.containerMenu != this.inventoryMenu) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + // this.nextContainerCounter(); // CraftBukkit - moved up +@@ -1414,7 +1414,12 @@ public class ServerPlayer extends Player implements ContainerListener { + + @Override + public void closeContainer() { +- CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit ++ // Paper start ++ closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); ++ } ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit ++ // Paper end + this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); + this.doCloseContainer(); + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index fb36aa08cd2fbe3f7262dccb8cf0f7cae55aea9c..d322e99170b3cb6594efc824a879ab9a538ea1eb 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -188,6 +188,7 @@ import org.bukkit.event.inventory.ClickType; + import org.bukkit.event.inventory.CraftItemEvent; + import org.bukkit.event.inventory.InventoryAction; + import org.bukkit.event.inventory.InventoryClickEvent; ++import org.bukkit.event.inventory.InventoryCloseEvent; // Paper + import org.bukkit.event.inventory.InventoryCreativeEvent; + import org.bukkit.event.inventory.InventoryType.SlotType; + import org.bukkit.event.inventory.SmithItemEvent; +@@ -2309,10 +2310,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + @Override + public void handleContainerClose(ServerboundContainerClosePacket packet) { +- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); ++ // Paper start ++ handleContainerClose(packet, InventoryCloseEvent.Reason.PLAYER); ++ } ++ public void handleContainerClose(ServerboundContainerClosePacket packetplayinclosewindow, InventoryCloseEvent.Reason reason) { ++ // Paper end ++ PacketUtils.ensureRunningOnSameThread(packetplayinclosewindow, this, this.player.getLevel()); + + if (this.player.isImmobile()) return; // CraftBukkit +- CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit ++ CraftEventFactory.handleInventoryCloseEvent(this.player, reason); // CraftBukkit // Paper + + this.player.doCloseContainer(); + } +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index ae60b233c4d56a4964b388f96e9cc66410774e8d..51b1ce465d23b971f7e08a3175319a33183d0398 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -490,7 +490,7 @@ public abstract class PlayerList { + // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it + // See SPIGOT-5799, SPIGOT-6145 + if (entityplayer.containerMenu != entityplayer.inventoryMenu) { +- entityplayer.closeContainer(); ++ entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper + } + + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); +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 5e6a86b0b8999a5c47d2f9bdd9857ab5f0772033..709e930eef7bae5694238ed8c4d0ef59316bb715 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -249,7 +249,7 @@ public abstract class Player extends LivingEntity { + this.updateIsUnderwater(); + super.tick(); + if (!this.level.isClientSide && this.containerMenu != null && !this.containerMenu.stillValid(this)) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.containerMenu = this.inventoryMenu; + } + +@@ -444,6 +444,13 @@ public abstract class Player extends LivingEntity { + return 20; + } + ++ // Paper start - unused code, but to keep signatures aligned ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ closeContainer(); ++ this.containerMenu = this.inventoryMenu; ++ } ++ // Paper end ++ + public void closeContainer() { + 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 4aec1c2b26d48cb5bea3dfb9e183526763bdb98f..a73c6ddd6bf66cc21ae5b25daacdece8cbfeeeac 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -374,7 +374,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + if (((ServerPlayer) getHandle()).connection == null) return; + if (getHandle().containerMenu != getHandle().inventoryMenu) { + // fire INVENTORY_CLOSE if one already open +- ((ServerPlayer) getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(getHandle().containerMenu.containerId)); ++ ((ServerPlayer) getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(getHandle().containerMenu.containerId), org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + ServerPlayer player = (ServerPlayer) getHandle(); + AbstractContainerMenu container; +@@ -444,8 +444,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + + @Override + public void closeInventory() { +- getHandle().closeContainer(); ++ // Paper start ++ getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); + } ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ getHandle().closeContainer(reason); ++ } ++ // Paper end + + @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 46338fe5693003698de9c7b37a860c3481e06233..c7f66dddf0a0850ca4048dd47cd2ded114caa07e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -895,7 +895,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + // Close any foreign inventory + if (getHandle().containerMenu != getHandle().inventoryMenu) { +- getHandle().closeContainer(); ++ getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper + } + + // 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 5e8ff18f98b03741ccbb927f87499ae36d775a86..c2f58b95db41b2205fbf2728c6a99419c6a63dfa 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1175,7 +1175,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 +- player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId)); ++ player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + CraftServer server = player.level.getCraftServer(); +@@ -1341,8 +1341,18 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start ++ /** ++ * Incase plugins hooked into this or Spigot adds a new inventory close event. Prefer to pass a reason ++ * @param human ++ */ ++ @Deprecated + public static void handleInventoryCloseEvent(net.minecraft.world.entity.player.Player human) { +- InventoryCloseEvent event = new InventoryCloseEvent(human.containerMenu.getBukkitView()); ++ handleInventoryCloseEvent(human, org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); ++ } ++ public static void handleInventoryCloseEvent(net.minecraft.world.entity.player.Player human, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ // Paper end ++ InventoryCloseEvent event = new InventoryCloseEvent(human.containerMenu.getBukkitView(), reason); // Paper + human.level.getCraftServer().getPluginManager().callEvent(event); + human.containerMenu.transferTo(human.inventoryMenu, human.getBukkitEntity()); + } diff --git a/patches/server-remapped/0234-Vex-getSummoner-API.patch b/patches/server-remapped/0234-Vex-getSummoner-API.patch new file mode 100644 index 0000000000..0689023cf1 --- /dev/null +++ b/patches/server-remapped/0234-Vex-getSummoner-API.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 15:30:22 -0400 +Subject: [PATCH] Vex#getSummoner API + +Get's the NPC that summoned this Vex + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java +index 3204ae9a9243818727bedfa060c07bc34d3b4c66..ec4f6d96360e759ffc19de838fdbf3027164a424 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vex.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java +@@ -124,6 +124,7 @@ public class Vex extends Monster { + + } + ++ public Mob getOwner() { return getOwner(); } // Paper - OBFHELPER + public Mob getOwner() { + return this.owner; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +index 2b4e9ddca5c6429c01d780d65a64ef6a59446c69..56bec4350f36a94d4dfa71a234872a795c2dcb3f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +@@ -15,6 +15,13 @@ public class CraftVex extends CraftMonster implements Vex { + return (net.minecraft.world.entity.monster.Vex) super.getHandle(); + } + ++ // Paper start ++ public org.bukkit.entity.Mob getSummoner() { ++ net.minecraft.world.entity.Mob owner = getHandle().getOwner(); ++ return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; ++ } ++ // Paper end ++ + @Override + public String toString() { + return "CraftVex"; diff --git a/patches/server-remapped/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/patches/server-remapped/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch new file mode 100644 index 0000000000..5cab7fe140 --- /dev/null +++ b/patches/server-remapped/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Fri, 13 Jul 2018 14:54:43 +0200 +Subject: [PATCH] Refresh player inventory when cancelling + PlayerInteractEntityEvent + +When interacting with entities with an item, the client will assume +the interaction is successful, and update the held item on the +client. However, if the interaction is cancelled on the server side, +the client will still mistakenly remove/replace the item in hand. + +Examples for this are milking cows with a bucket or dyeing sheep. +The bucket is replaced with milk and the dye removed from inventory. + +Refresh the player inventory when PlayerInteractEntityEvent is +cancelled to avoid this problem. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index d322e99170b3cb6594efc824a879ab9a538ea1eb..645f7b7c862acf77d70ca0b05308945424bc4d32 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2222,6 +2222,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + + if (event.isCancelled()) { ++ this.player.refreshContainer(this.player.containerMenu); // Paper - Refresh player inventory + return; + } + // CraftBukkit end diff --git a/patches/server-remapped/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch b/patches/server-remapped/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch new file mode 100644 index 0000000000..4887c3dd7e --- /dev/null +++ b/patches/server-remapped/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 19 Jul 2018 01:05:00 -0400 +Subject: [PATCH] Don't change the Entity Random seed for squids + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java +index 5a7582fd4f8e883d2f08a0227932c17d7576b957..2e5a35565b6b7c4d3f7fdab45095f789c33f8937 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java +@@ -48,7 +48,7 @@ public class Squid extends WaterAnimal { + + public Squid(EntityType type, Level world) { + super(type, world); +- this.random.setSeed((long) this.getId()); ++ //this.random.setSeed((long) this.getId()); // Paper + this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; + } + diff --git a/patches/server-remapped/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch b/patches/server-remapped/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch new file mode 100644 index 0000000000..4deb8f2bc2 --- /dev/null +++ b/patches/server-remapped/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 19 Jul 2018 01:08:05 -0400 +Subject: [PATCH] Re-add vanilla entity warnings for duplicates + +These are a critical sign that somethin went wrong, and you've lost some data.... + +We should kind of know about these things you know. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index ea1b15495481157912140bf5de9bf4a949c16910..914241a57c304fde220bc546261d6e959445772a 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1071,7 +1071,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (entity1 == null) { + return false; + } else { +- // WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit ++ ServerLevel.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityType.getKey(entity1.getType()), entity1.getId(), EntityType.getKey(entity.getType()), entity.getId()); // CraftBukkit // Paper + return true; + } + } diff --git a/patches/server-remapped/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch b/patches/server-remapped/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch new file mode 100644 index 0000000000..b47c9efed4 --- /dev/null +++ b/patches/server-remapped/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Mon, 16 Jul 2018 12:42:20 +0200 +Subject: [PATCH] Avoid item merge if stack size above max stack size + + +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index de69f7c3c0ee1e74682b0db91bdaae09175690e9..70f719ba3c68c8e9414e6b4bc68002f7c962e2b9 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -208,6 +208,10 @@ public class ItemEntity extends Entity { + + private void mergeWithNeighbours() { + if (this.isMergable()) { ++ // Paper start - avoid item merge if stack size above max stack size ++ ItemStack stack = getItem(); ++ if (stack.getCount() >= stack.getMaxStackSize()) return; ++ // Paper end + // Spigot start + double radius = level.spigotConfig.itemMerge; + List list = this.level.getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(radius, radius, radius), (entityitem) -> { diff --git a/patches/server-remapped/0239-Use-asynchronous-Log4j-2-loggers.patch b/patches/server-remapped/0239-Use-asynchronous-Log4j-2-loggers.patch new file mode 100644 index 0000000000..fd4a4b705a --- /dev/null +++ b/patches/server-remapped/0239-Use-asynchronous-Log4j-2-loggers.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Tue, 17 Jul 2018 16:42:17 +0200 +Subject: [PATCH] Use asynchronous Log4j 2 loggers + + +diff --git a/pom.xml b/pom.xml +index f5429f2f1979542fd93956d2f436d20d0e3a66b8..4c8a057e790c96b0ab5123549d0566371acacb46 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -88,6 +88,13 @@ + log4j-iostreams + compile + ++ ++ ++ com.lmax ++ disruptor ++ 3.4.2 ++ runtime ++ + + org.ow2.asm + asm +diff --git a/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java +new file mode 100644 +index 0000000000000000000000000000000000000000..db652a1f7abc80bc751fd94925abaec58ab1a563 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.log; ++ ++import org.apache.logging.log4j.Level; ++import org.apache.logging.log4j.core.async.AsyncQueueFullPolicy; ++import org.apache.logging.log4j.core.async.EventRoute; ++ ++public final class LogFullPolicy implements AsyncQueueFullPolicy { ++ ++ /* ++ * Prevents log calls being logged out of order when the log queue is full. ++ */ ++ ++ @Override ++ public EventRoute getRoute(final long backgroundThreadId, final Level level) { ++ return EventRoute.ENQUEUE; ++ } ++} +diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties +index 0694b21465fb9e4164e71862ff24b62241b191f2..30efeb5faf8e7faccf1b252fa0ed6a9fc31c40a7 100644 +--- a/src/main/resources/log4j2.component.properties ++++ b/src/main/resources/log4j2.component.properties +@@ -1 +1,3 @@ ++Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector ++log4j2.AsyncQueueFullPolicy="com.destroystokyo.paper.log.LogFullPolicy" + log4j.skipJansi=true diff --git a/patches/server-remapped/0240-add-more-information-to-Entity.toString.patch b/patches/server-remapped/0240-add-more-information-to-Entity.toString.patch new file mode 100644 index 0000000000..b0de783dec --- /dev/null +++ b/patches/server-remapped/0240-add-more-information-to-Entity.toString.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 19 Jul 2018 01:13:28 -0400 +Subject: [PATCH] add more information to Entity.toString() + +UUID, ticks lived, valid, dead + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 7e70bae5bc54ad17980789fa965fd539a7f193ea..e49fe2de6a53bdd16f0cd09b691f01f1866ffb4f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2526,7 +2526,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public String toString() { +- return String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getName().getString(), this.id, this.level == null ? "~NULL~" : this.level.toString(), this.getX(), this.getY(), this.getZ()); ++ return String.format(Locale.ROOT, "%s['%s'/%d, uuid='%s', l='%s', x=%.2f, y=%.2f, z=%.2f, cx=%d, cz=%d, tl=%d, v=%b, d=%b]", new Object[] { this.getClass().getSimpleName(), this.getName().getString(), Integer.valueOf(this.id), this.uuid.toString(), this.level == null ? "~NULL~" : this.level.toString(), Double.valueOf(this.getX()), Double.valueOf(this.getY()), Double.valueOf(this.getZ()), xChunk, zChunk, this.tickCount, this.valid, this.removed}); // Paper - add more information + } + + public boolean isInvulnerableTo(DamageSource damageSource) { diff --git a/patches/server-remapped/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/patches/server-remapped/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch new file mode 100644 index 0000000000..be88eeb2df --- /dev/null +++ b/patches/server-remapped/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch @@ -0,0 +1,131 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 21 Jul 2018 08:25:40 -0400 +Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues + +Add -Ddebug.entities=true to your JVM flags to gain more information + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 97d5437df10a6d0124e944404e88650547b7d8a8..083db6c1899b5391231b6d5d5044a334212f148c 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1145,6 +1145,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } else { + ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas()); + ++ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker + this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); + playerchunkmap_entitytracker.updatePlayers(this.level.players()); + if (entity instanceof ServerPlayer) { +@@ -1186,7 +1187,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (playerchunkmap_entitytracker1 != null) { + playerchunkmap_entitytracker1.broadcastRemoved(); + } +- ++ entity.tracker = null; // Paper - We're no longer tracked + } + + protected void tick() { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 914241a57c304fde220bc546261d6e959445772a..a5d7781b13a6d61238d026f064512f7162e1e868 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -191,6 +191,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper ++ private static Throwable getAddToWorldStackTrace(Entity entity) { ++ return new Throwable(entity + " Added to world at " + new java.util.Date()); ++ } + + @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkSource.getChunk(x, z, false); +@@ -1032,8 +1035,28 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // CraftBukkit start + private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot +- if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper ++ // Paper start ++ if (entity.valid) { ++ MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); ++ ++ if (DEBUG_ENTITIES) { ++ Throwable thr = entity.addedToWorldStack; ++ if (thr == null) { ++ MinecraftServer.LOGGER.error("Double add entity has no add stacktrace"); ++ } else { ++ MinecraftServer.LOGGER.error("Double add stacktrace: ", thr); ++ } ++ } ++ return true; ++ } ++ // Paper end + if (entity.removed) { ++ // Paper start ++ if (DEBUG_ENTITIES) { ++ new Throwable("Tried to add entity " + entity + " but it was marked as removed already").printStackTrace(); // CraftBukkit ++ getAddToWorldStackTrace(entity).printStackTrace(); ++ } ++ // Paper end + // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit + return false; + } else if (this.isUUIDUsed(entity)) { +@@ -1231,7 +1254,24 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + } + +- this.entitiesByUuid.put(entity.getUUID(), entity); ++ if (DEBUG_ENTITIES) { ++ entity.addedToWorldStack = getAddToWorldStackTrace(entity); ++ } ++ ++ Entity old = this.entitiesByUuid.put(entity.getUUID(), entity); ++ if (old != null && old.getId() != entity.getId() && old.valid) { ++ Logger logger = LogManager.getLogger(); ++ logger.error("Overwrote an existing entity " + old + " with " + entity); ++ if (DEBUG_ENTITIES) { ++ if (old.addedToWorldStack != null) { ++ old.addedToWorldStack.printStackTrace(); ++ } else { ++ logger.error("Oddly, the old entity was not added to the world in the normal way. Plugins?"); ++ } ++ entity.addedToWorldStack.printStackTrace(); ++ } ++ } ++ + this.getChunkSource().addEntity(entity); + // CraftBukkit start - SPIGOT-5278 + if (entity instanceof Drowned) { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index e49fe2de6a53bdd16f0cd09b691f01f1866ffb4f..9d8682d367522bd85894947ad2f2a53cf0aa123a 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -47,6 +47,7 @@ import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.level.TicketType; +@@ -160,6 +161,8 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper + private CraftEntity bukkitEntity; + ++ ChunkMap.TrackedEntity tracker; // Paper ++ public Throwable addedToWorldStack; // Paper - entity debug + public CraftEntity getBukkitEntity() { + if (bukkitEntity == null) { + bukkitEntity = CraftEntity.getEntity(level.getCraftServer(), this); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index b4248d46ccb1a95e21601bca1198512287edcabf..0c6c3b211b05eda8f9ab47ef0a01cc520ae28201 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -121,6 +121,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean pvpMode; + public boolean keepSpawnInMemory = true; + public org.bukkit.generator.ChunkGenerator generator; ++ public static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper + + public boolean captureBlockStates = false; + public boolean captureTreeGeneration = false; diff --git a/patches/server-remapped/0242-EnderDragon-Events.patch b/patches/server-remapped/0242-EnderDragon-Events.patch new file mode 100644 index 0000000000..14fc4f84c6 --- /dev/null +++ b/patches/server-remapped/0242-EnderDragon-Events.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 01:51:27 -0500 +Subject: [PATCH] EnderDragon Events + + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java +index 0c2a5f5c4d7d7516793eba20205b5703fe1450d5..6b28cfb1e79903c43702f6e78e226dc78e3ccec2 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java +@@ -80,7 +80,11 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { + this.flame.setDuration(200); + this.flame.setParticle(ParticleTypes.DRAGON_BREATH); + this.flame.addEffect(new MobEffectInstance(MobEffects.HARM)); ++ if (new com.destroystokyo.paper.event.entity.EnderDragonFlameEvent((org.bukkit.entity.EnderDragon) this.dragon.getBukkitEntity(), (org.bukkit.entity.AreaEffectCloud) this.flame.getBukkitEntity()).callEvent()) { // Paper + this.dragon.level.addFreshEntity(this.flame); ++ } else { ++ this.removeAreaEffect(); ++ } + } + + } +@@ -91,8 +95,8 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { + ++this.flameCount; + } + +- @Override +- public void end() { ++ public final void removeAreaEffect() { this.end(); } // Paper - OBFHELPER ++ @Override public void end() { + if (this.flame != null) { + this.flame.remove(); + this.flame = null; +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java +index 01442af7b0c7340f0ece2fa0faa0f783b1b81c48..a43ef94f8a5c7a9d1581667beb4516cc26f30a0d 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java +@@ -81,7 +81,9 @@ public class DragonStrafePlayerPhase extends AbstractDragonPhaseInstance { + DragonFireball entitydragonfireball = new DragonFireball(this.dragon.level, this.dragon, d9, d10, d11); + + entitydragonfireball.moveTo(d6, d7, d8, 0.0F, 0.0F); ++ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) dragon.getBukkitEntity(), (org.bukkit.entity.DragonFireball) entitydragonfireball.getBukkitEntity()).callEvent()) // Paper + this.dragon.level.addFreshEntity(entitydragonfireball); ++ else entitydragonfireball.remove(); // Paper + this.fireballCharge = 0; + if (this.currentPath != null) { + while (!this.currentPath.isDone()) { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java +index 76dc15e07ce9ef01ad7908e289a0d695b65b2fc9..1629e409a83b11b76e1627247a838c9ebd11a648 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java +@@ -58,8 +58,10 @@ public class DragonFireball extends AbstractHurtingProjectile { + } + } + ++ if (new com.destroystokyo.paper.event.entity.EnderDragonFireballHitEvent((org.bukkit.entity.DragonFireball) this.getBukkitEntity(), list.stream().map(LivingEntity::getBukkitLivingEntity).collect(java.util.stream.Collectors.toList()), (org.bukkit.entity.AreaEffectCloud) entityareaeffectcloud.getBukkitEntity()).callEvent()) { // Paper + this.level.levelEvent(2006, this.blockPosition(), this.isSilent() ? -1 : 1); + this.level.addFreshEntity(entityareaeffectcloud); ++ } else entityareaeffectcloud.remove(); // Paper + this.remove(); + } + diff --git a/patches/server-remapped/0243-PlayerElytraBoostEvent.patch b/patches/server-remapped/0243-PlayerElytraBoostEvent.patch new file mode 100644 index 0000000000..be2454e01e --- /dev/null +++ b/patches/server-remapped/0243-PlayerElytraBoostEvent.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 01:59:59 -0500 +Subject: [PATCH] PlayerElytraBoostEvent + + +diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index dba52063d402eb2371441fa244b730a3313444fc..28cffbe299acccc59c34d5dbd2cf458704be5ee5 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -45,11 +45,16 @@ public class FireworkRocketItem extends Item { + // Paper start + final FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, itemstack, user); + entityfireworks.spawningEntity = user.getUUID(); +- world.addFreshEntity(entityfireworks); +- // Paper end +- if (!user.abilities.instabuild) { +- itemstack.shrink(1); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entityfireworks)) { ++ if (event.shouldConsume() && !user.abilities.instabuild) { ++ itemstack.shrink(1); ++ } else ((EntityPlayer) user).getBukkitEntity().updateInventory(); ++ } else if (user instanceof EntityPlayer) { ++ ((EntityPlayer) user).getBukkitEntity().updateInventory(); + } ++ // Paper end + } + + return InteractionResultHolder.sidedSuccess(user.getItemInHand(hand), world.isClientSide()); diff --git a/patches/server-remapped/0244-Improve-BlockPosition-inlining.patch b/patches/server-remapped/0244-Improve-BlockPosition-inlining.patch new file mode 100644 index 0000000000..675f0c0360 --- /dev/null +++ b/patches/server-remapped/0244-Improve-BlockPosition-inlining.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Wed, 30 Nov 2016 20:56:58 -0600 +Subject: [PATCH] Improve BlockPosition inlining + +Normally the JVM can inline virtual getters by having two sets of code, one is the 'optimized' code and the other is the 'deoptimized' code. +If a single type is used 99% of the time, then its worth it to inline, and to revert to 'deoptimized' the 1% of the time we encounter other types. +But if two types are encountered commonly, then the JVM can't inline them both, and the call overhead remains. + +This scenario also occurs with BlockPos and MutableBlockPos. +The variables in BlockPos are final, so MutableBlockPos can't modify them. +MutableBlockPos fixes this by adding custom mutable variables, and overriding the getters to access them. + +This approach with utility methods that operate on MutableBlockPos and BlockPos. +Specific examples are BlockPosition.up(), and World.isValidLocation(). +It makes these simple methods much slower than they need to be. + +This should result in an across the board speedup in anything that accesses blocks or does logic with positions. + +This is based upon conclusions drawn from inspecting the assenmbly generated bythe JIT compiler on my microbenchmarks. +They had 'callq' (invoke) instead of 'mov' (get from memory) instructions. + +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 6a58059a05e16d96894b67a544c2f595d9546c78..c5089b0da33a68e7cadbc4841b07f9d772d224a0 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -88,6 +88,7 @@ public class BlockPos extends Vec3i { + return asLong(this.getX(), this.getY(), this.getZ()); + } + ++ public static long asLong(int x, int y, int z) { return asLong(x, y, z); } // Paper - OBFHELPER + public static long asLong(int x, int y, int z) { + long l = 0L; + +diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java +index c22de593be404c4e921724bba6a69c13759a95fd..fc4e652ada7b228cb99a3c8fb372ae9af5ddfba4 100644 +--- a/src/main/java/net/minecraft/core/Vec3i.java ++++ b/src/main/java/net/minecraft/core/Vec3i.java +@@ -41,7 +41,7 @@ public class Vec3i implements Comparable { + this(Mth.floor(x), Mth.floor(y), Mth.floor(z)); + } + +- public boolean equals(Object object) { ++ public final boolean equals(Object object) { // Paper + if (this == object) { + return true; + } else if (!(object instanceof Vec3i)) { +@@ -53,7 +53,7 @@ public class Vec3i implements Comparable { + } + } + +- public int hashCode() { ++ public final int hashCode() { // Paper + return (this.getY() + this.getZ() * 31) * 31 + this.getX(); + } + +@@ -61,15 +61,15 @@ public class Vec3i implements Comparable { + return this.getY() == baseblockposition.getY() ? (this.getZ() == baseblockposition.getZ() ? this.getX() - baseblockposition.getX() : this.getZ() - baseblockposition.getZ()) : this.getY() - baseblockposition.getY(); + } + +- public int getX() { ++ public final int getX() { // Paper + return this.x; + } + +- public int getY() { ++ public final int getY() { // Paper + return this.y; + } + +- public int getZ() { ++ public final int getZ() { // Paper + return this.z; + } + diff --git a/patches/server-remapped/0245-Optimize-RegistryID.c.patch b/patches/server-remapped/0245-Optimize-RegistryID.c.patch new file mode 100644 index 0000000000..e8d895a808 --- /dev/null +++ b/patches/server-remapped/0245-Optimize-RegistryID.c.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Mon, 23 Jul 2018 13:08:19 -0400 +Subject: [PATCH] Optimize RegistryID.c() + +This is a frequent hotspot for world loading/saving. + +diff --git a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java +index 66ad412e4368a8615cc66a97ac442c572813a3dd..fa4a2d29b3b4c20d7396e973801d69c4acadddda 100644 +--- a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java ++++ b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java +@@ -15,12 +15,14 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + private K[] byId; + private int nextId; + private int size; ++ private java.util.BitSet usedIds; // Paper + + public CrudeIncrementalIntIdentityHashBiMap(int size) { + size = (int) ((float) size / 0.8F); + this.keys = (K[]) (new Object[size]); // Paper - decompile fix + this.values = new int[size]; + this.byId = (K[]) (new Object[size]); // Paper - decompile fix ++ this.usedIds = new java.util.BitSet(); // Paper + } + + // Paper start - decompile fix +@@ -52,9 +54,14 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + } + + private int nextId() { +- while (this.nextId < this.byId.length && this.byId[this.nextId] != null) { +- ++this.nextId; ++ // Paper start ++ /* ++ while (this.e < this.d.length && this.d[this.e] != null) { ++ ++this.e; + } ++ */ ++ this.nextId = this.usedIds.nextClearBit(0); ++ // Paper end + + return this.nextId; + } +@@ -68,6 +75,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + this.byId = (K[]) (new Object[newSize]); // Paper - decompile fix + this.nextId = 0; + this.size = 0; ++ this.usedIds.clear(); // Paper + + for (int j = 0; j < ak.length; ++j) { + if (ak[j] != null) { +@@ -93,6 +101,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + this.keys[k] = value; + this.values[k] = id; + this.byId[id] = value; ++ this.usedIds.set(id); // Paper + ++this.size; + if (id == this.nextId) { + ++this.nextId; +@@ -157,6 +166,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + Arrays.fill(this.byId, (Object) null); + this.nextId = 0; + this.size = 0; ++ this.usedIds.clear(); // Paper + } + + public int size() { diff --git a/patches/server-remapped/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/patches/server-remapped/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch new file mode 100644 index 0000000000..f39334e396 --- /dev/null +++ b/patches/server-remapped/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Mon, 23 Jul 2018 12:57:39 +0200 +Subject: [PATCH] Option to prevent armor stands from doing entity lookups + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4813f62d1e382d5ac6971b2244df3f13c80d1950..3562950df4868b1393790b1a1ff1fe0dc589c155 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -379,4 +379,9 @@ public class PaperWorldConfig { + private void scanForLegacyEnderDragon() { + scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); + } ++ ++ public boolean armorStandEntityLookups = true; ++ private void armorStandEntityLookups() { ++ armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 59239e202e8e99870ce3be515d2f040ad9786892..7fc69adc8afa971ee3cf815c6002628ae2149a5b 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -352,6 +352,7 @@ public class ArmorStand extends LivingEntity { + + @Override + protected void pushEntities() { ++ if (!level.paperConfig.armorStandEntityLookups) return; // Paper + List list = this.level.getEntities(this, this.getBoundingBox(), ArmorStand.RIDABLE_MINECARTS); + + for (int i = 0; i < list.size(); ++i) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0c6c3b211b05eda8f9ab47ef0a01cc520ae28201..7b135a3951bc168ccebdbb4e3acdc07397a820d3 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -39,6 +39,7 @@ import net.minecraft.world.DifficultyInstance; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.decoration.ArmorStand; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +@@ -854,6 +855,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Paper end + } + } ++ // Paper start - Prevent armor stands from doing entity lookups ++ @Override ++ public boolean noCollision(@Nullable Entity entity, AABB box) { ++ if (entity instanceof ArmorStand && !entity.level.paperConfig.armorStandEntityLookups) return false; ++ return LevelAccessor.super.noCollision(entity, box); ++ } ++ // Paper end + + public Explosion explode(@Nullable Entity entity, double x, double y, double z, float power, Explosion.BlockInteraction destructionType) { + return this.explode(entity, (DamageSource) null, (ExplosionDamageCalculator) null, x, y, z, power, false, destructionType); diff --git a/patches/server-remapped/0247-Vanished-players-don-t-have-rights.patch b/patches/server-remapped/0247-Vanished-players-don-t-have-rights.patch new file mode 100644 index 0000000000..f0b596c503 --- /dev/null +++ b/patches/server-remapped/0247-Vanished-players-don-t-have-rights.patch @@ -0,0 +1,194 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Mon, 23 Jul 2018 14:22:26 +0200 +Subject: [PATCH] Vanished players don't have rights + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 9d8682d367522bd85894947ad2f2a53cf0aa123a..a2cc3e58d59ed3d9f443b77c44d8200cc09b4da9 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -183,7 +183,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + private static double viewScale = 1.0D; + private final EntityType type; + private int id; +- public boolean blocksBuilding; ++ public boolean blocksBuilding; public final boolean blocksEntitySpawning() { return this.blocksBuilding; } // Paper - OBFHELPER + public final List passengers; + protected int boardingCooldown; + @Nullable +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index 16b554675a276471851846d4f2bea06fdcc166d9..d1dd173c11d751b15c3afd4309e386931fd9cf8d 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -5,6 +5,7 @@ import java.util.UUID; + import javax.annotation.Nullable; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -157,8 +158,14 @@ public abstract class Projectile extends Entity { + protected boolean canHitEntity(Entity entity) { + if (!entity.isSpectator() && entity.isAlive() && entity.isPickable()) { + Entity entity1 = this.getOwner(); +- ++ // Paper start - Cancel hit for vanished players ++ if (entity1 instanceof ServerPlayer && entity instanceof ServerPlayer) { ++ org.bukkit.entity.Player collided = (org.bukkit.entity.Player) entity.getBukkitEntity(); ++ org.bukkit.entity.Player shooter = (org.bukkit.entity.Player) entity1.getBukkitEntity(); ++ if (!shooter.canSee(collided)) return false; ++ } + return entity1 == null || this.leftOwner || !entity1.isPassengerOfSameVehicle(entity); ++ // Paper end + } else { + return false; + } +diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java +index 1ba89fa106dc24abf68d5d13c39a8d80f5582f1f..59522e367327224e5fe0fe2307858077ed812ba6 100644 +--- a/src/main/java/net/minecraft/world/item/BlockItem.java ++++ b/src/main/java/net/minecraft/world/item/BlockItem.java +@@ -174,7 +174,8 @@ public class BlockItem extends Item { + Player entityhuman = context.getPlayer(); + CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of((Entity) entityhuman); + // CraftBukkit start - store default return +- boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision); ++ Level world = context.getLevel(); // Paper ++ boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && world.checkEntityCollision(state, entityhuman, voxelshapecollision, context.getClickedPos(), true); // Paper + org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; + + BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 7b135a3951bc168ccebdbb4e3acdc07397a820d3..7a9ccd203885b9b369767d1fb8c53783201d0f0f 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -30,6 +30,7 @@ import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.TagContainer; +@@ -69,6 +70,10 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + import net.minecraft.world.level.storage.LevelData; + import net.minecraft.world.level.storage.WritableLevelData; + import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.shapes.BooleanOp; ++import net.minecraft.world.phys.shapes.CollisionContext; ++import net.minecraft.world.phys.shapes.Shapes; ++import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.scores.Scoreboard; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -232,6 +237,46 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + } + ++ // Paper start ++ // ret true if no collision ++ public final boolean checkEntityCollision(BlockState data, Entity source, CollisionContext voxelshapedcollision, ++ BlockPos position, boolean checkCanSee) { ++ // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape) ++ VoxelShape voxelshape = data.getCollisionShape(this, position, voxelshapedcollision); ++ if (voxelshape.isEmpty()) { ++ return true; ++ } ++ ++ voxelshape = voxelshape.offset((double) position.getX(), (double) position.getY(), (double) position.getZ()); ++ if (voxelshape.isEmpty()) { ++ return true; ++ } ++ ++ List entities = this.getEntities(null, voxelshape.bounds()); ++ for (int i = 0, len = entities.size(); i < len; ++i) { ++ Entity entity = entities.get(i); ++ ++ if (checkCanSee && source instanceof ServerPlayer && entity instanceof ServerPlayer ++ && !((ServerPlayer) source).getBukkitEntity().canSee(((ServerPlayer) entity).getBukkitEntity())) { ++ continue; ++ } ++ ++ // !entity1.dead && entity1.i && (entity == null || !entity1.x(entity)); ++ // elide the last check since vanilla calls with entity = null ++ // only we care about the source for the canSee check ++ if (entity.removed || !entity.blocksEntitySpawning()) { ++ continue; ++ } ++ ++ if (Shapes.applyOperation(voxelshape, Shapes.of(entity.getBoundingBox()), BooleanOp.AND)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ // Paper end ++ + @Override + public boolean isClientSide() { + return this.isClientSide; +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index e6928557a79f51302975f2832ec911c2692eaaeb..5d7794c9533bd37193f196bda616adaaace2bbde 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -504,6 +504,7 @@ public abstract class BlockBehaviour { + return this.cache != null ? this.cache.collisionShape : this.getCollisionShape(world, pos, CollisionContext.empty()); + } + ++ public final VoxelShape getCollisionShape(BlockGetter iblockaccess, BlockPos blockposition, CollisionContext voxelshapecollision) { return this.getCollisionShape(iblockaccess, blockposition, voxelshapecollision); } // Paper - OBFHELPER + public VoxelShape getCollisionShape(BlockGetter world, BlockPos pos, CollisionContext context) { + return this.getBlock().getCollisionShape(this.asState(), world, pos, context); + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index 2371b52b450e2b43fa9b9549a91f853c702a9dc0..fa2942d0b0424390daee2121f8959034c5352e0b 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -45,6 +45,7 @@ public final class Shapes { + return create(new AABB(xMin, yMin, zMin, xMax, yMax, zMax)); + } + ++ public static final VoxelShape of(AABB axisAlignedbb) { return Shapes.create(axisAlignedbb); } // Paper - OBFHELPER + public static VoxelShape create(AABB box) { + int i = findBits(box.minX, box.maxX); + int j = findBits(box.minY, box.maxY); +@@ -139,6 +140,7 @@ public final class Shapes { + } + } + ++ public static final boolean applyOperation(VoxelShape voxelshape, VoxelShape voxelshape1, BooleanOp operatorboolean) { return Shapes.joinIsNotEmpty(voxelshape, voxelshape1, operatorboolean); } // Paper - OBFHELPER + public static boolean joinIsNotEmpty(VoxelShape shape1, VoxelShape shape2, BooleanOp predicate) { + if (predicate.apply(false, false)) { + throw (IllegalArgumentException) Util.pauseInIde((Throwable) (new IllegalArgumentException())); +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +index 026759567c58b5e7687ed1eec26fb4ffc60f9fa7..67ecdaada9f87304a9ae83d7917c7aca4676d195 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +@@ -54,6 +54,7 @@ public abstract class VoxelShape { + return this.shape.isEmpty(); + } + ++ public final VoxelShape offset(double x, double y, double z) { return this.move(x, y, z); } // Paper - OBFHELPER + public VoxelShape move(double x, double y, double z) { + return (VoxelShape) (this.isEmpty() ? Shapes.empty() : new ArrayVoxelShape(this.shape, new OffsetDoubleList(this.getCoords(Direction.Axis.X), x), new OffsetDoubleList(this.getCoords(Direction.Axis.Y), y), new OffsetDoubleList(this.getCoords(Direction.Axis.Z), z))); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index c2f58b95db41b2205fbf2728c6a99419c6a63dfa..4cd08821305590e21a01cc4dda05370c2b721ac2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1211,6 +1211,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); ++ ++ if (projectile.getShooter() instanceof Player && collided instanceof Player) { ++ if (!((Player) projectile.getShooter()).canSee((Player) collided)) { ++ event.setCancelled(true); ++ return event; ++ } ++ } ++ + Bukkit.getPluginManager().callEvent(event); + return event; + } diff --git a/patches/server-remapped/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch b/patches/server-remapped/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch new file mode 100644 index 0000000000..a8a2ab7437 --- /dev/null +++ b/patches/server-remapped/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 23 Jul 2018 22:18:31 -0400 +Subject: [PATCH] Mark chunk dirty anytime entities change to guarantee it + saves + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index d69ccb1f31f31ebeee477df20ce1410f9e485eb7..bd9b19d988ecf72e099efeff6ec3483a352174ec 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -559,6 +559,7 @@ public class LevelChunk implements ChunkAccess { + entity.zChunk = this.chunkPos.z; + this.entities.add(entity); // Paper - per chunk entity list + this.entitySlices[k].add(entity); ++ this.markUnsaved(); // Paper + } + + @Override +@@ -587,6 +588,7 @@ public class LevelChunk implements ChunkAccess { + return; + } + entityCounts.decrement(entity.getMinecraftKeyString()); ++ this.markUnsaved(); // Paper + // Paper end + this.entities.remove(entity); // Paper + } diff --git a/patches/server-remapped/0249-Add-some-Debug-to-Chunk-Entity-slices.patch b/patches/server-remapped/0249-Add-some-Debug-to-Chunk-Entity-slices.patch new file mode 100644 index 0000000000..1978f629cd --- /dev/null +++ b/patches/server-remapped/0249-Add-some-Debug-to-Chunk-Entity-slices.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 23 Jul 2018 22:44:23 -0400 +Subject: [PATCH] Add some Debug to Chunk Entity slices + +If we detect unexpected state, log and try to recover + +This should hopefully avoid duplicate entities ever being created +if the entity was to end up in 2 different chunk slices + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a2cc3e58d59ed3d9f443b77c44d8200cc09b4da9..7847078c54154e28ab066ea8a329f929df1e1a37 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -156,6 +156,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + } + }; ++ public List entitySlice = null; + // Paper end + + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index bd9b19d988ecf72e099efeff6ec3483a352174ec..09aa608bd303b618ae2c0ebd237bcbdba60a37a8 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -26,7 +26,9 @@ import net.minecraft.ReportedException; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; +@@ -550,6 +552,25 @@ public class LevelChunk implements ChunkAccess { + if (k >= this.entitySlices.length) { + k = this.entitySlices.length - 1; + } ++ // Paper - remove from any old list if its in one ++ List nextSlice = this.entitySlices[k]; // the next list to be added to ++ List currentSlice = entity.entitySlice; ++ if (nextSlice == currentSlice) { ++ if (Level.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity was already in this chunk!" + entity, new Throwable()); ++ return; // ??? silly plugins ++ } ++ if (currentSlice != null && currentSlice.contains(entity)) { ++ // Still in an old chunk... ++ if (Level.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity is still in another chunk!" + entity, new Throwable()); ++ LevelChunk chunk = entity.getCurrentChunk(); ++ if (chunk != null) { ++ chunk.removeEntity(entity); ++ } else { ++ removeEntity(entity); ++ } ++ currentSlice.remove(entity); // Just incase the above did not remove from the previous slice ++ } ++ // Paper end + + if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper + entity.inChunk = true; +@@ -559,6 +580,7 @@ public class LevelChunk implements ChunkAccess { + entity.zChunk = this.chunkPos.z; + this.entities.add(entity); // Paper - per chunk entity list + this.entitySlices[k].add(entity); ++ entity.entitySlice = this.entitySlices[k]; // Paper + this.markUnsaved(); // Paper + } + +@@ -584,6 +606,10 @@ public class LevelChunk implements ChunkAccess { + + // Paper start + if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); ++ if (entitySlices[section] == entity.entitySlice) { ++ entity.entitySlice = null; ++ entity.inChunk = false; ++ } + if (!this.entitySlices[section].remove(entity)) { + return; + } +@@ -742,7 +768,7 @@ public class LevelChunk implements ChunkAccess { + // Paper start - neighbour cache + int chunkX = this.chunkPos.x; + int chunkZ = this.chunkPos.z; +- ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); ++ ServerChunkCache chunkProvider = ((ServerLevel)this.world).getChunkSource(); + for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { + for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { + LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); +@@ -802,7 +828,7 @@ public class LevelChunk implements ChunkAccess { + // Paper start - neighbour cache + int chunkX = this.chunkPos.x; + int chunkZ = this.chunkPos.z; +- ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); ++ ServerChunkCache chunkProvider = ((ServerLevel)this.world).getChunkSource(); + for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { + for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { + LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); diff --git a/patches/server-remapped/0250-SkeletonHorse-Additions.patch b/patches/server-remapped/0250-SkeletonHorse-Additions.patch new file mode 100644 index 0000000000..6599e06859 --- /dev/null +++ b/patches/server-remapped/0250-SkeletonHorse-Additions.patch @@ -0,0 +1,152 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 27 Jul 2018 22:36:31 -0500 +Subject: [PATCH] SkeletonHorse Additions + + +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index a3bad391a719363077740aa810c9412df34b4ae5..e92a8c4c49c452e1f3f0c06398f2a74e3432262f 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -25,6 +25,7 @@ public final class EntitySelector { + public static final Predicate ATTACK_ALLOWED = (entity) -> { + return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative() && entity.level.getDifficulty() != Difficulty.PEACEFUL; + }; ++ public static Predicate notSpectator() { return NO_SPECTATORS; } // Paper - OBFHELPER + public static final Predicate NO_SPECTATORS = (entity) -> { + return !entity.isSpectator(); + }; +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java +index 7ef99acaa24525c68b1528bd3232738baab8e1c6..eaab482ae341ddda0754e726357cd845121fb043 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java +@@ -26,7 +26,7 @@ public class SkeletonHorse extends AbstractHorse { + + private final SkeletonTrapGoal skeletonTrapGoal = new SkeletonTrapGoal(this); + private boolean isTrap; +- private int trapTime; ++ private int trapTime; public int getTrapTime() { return this.trapTime; } // Paper - OBFHELPER + + public SkeletonHorse(EntityType type, Level world) { + super(type, world); +@@ -145,10 +145,12 @@ public class SkeletonHorse extends AbstractHorse { + return 0.96F; + } + ++ public boolean isTrap() { return this.isTrap(); } // Paper - OBFHELPER + public boolean isTrap() { + return this.isTrap; + } + ++ public void setTrap(boolean trap) { this.setTrap(trap); } // Paper - OBFHELPER + public void setTrap(boolean trapped) { + if (trapped != this.isTrap) { + this.isTrap = trapped; +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java +index 6c2cbaae2afe076c8b7bc53ffa91fe37e423d120..7f5fb28a7deabe1b62ed21e5ed1ea1ecca0d15b8 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java +@@ -14,10 +14,14 @@ import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.level.Level; ++import org.bukkit.entity.HumanEntity; ++ ++import java.util.List; + + public class SkeletonTrapGoal extends Goal { + + private final SkeletonHorse horse; ++ private List eligiblePlayers; // Paper + + public SkeletonTrapGoal(SkeletonHorse skeletonHorse) { + this.horse = skeletonHorse; +@@ -25,12 +29,13 @@ public class SkeletonTrapGoal extends Goal { + + @Override + public boolean canUse() { +- return this.horse.level.hasNearbyAlivePlayer(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D); ++ return !(eligiblePlayers = this.horse.level.findNearbyBukkitPlayers(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D, false)).isEmpty(); // Paper + } + + @Override + public void tick() { + ServerLevel worldserver = (ServerLevel) this.horse.level; ++ if (!new com.destroystokyo.paper.event.entity.SkeletonHorseTrapEvent((org.bukkit.entity.SkeletonHorse) this.horse.getBukkitEntity(), eligiblePlayers).callEvent()) return; // Paper + DifficultyInstance difficultydamagescaler = worldserver.getCurrentDifficultyAt(this.horse.blockPosition()); + + this.horse.setTrap(false); +diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java +index 66681b9f0e2531d3da25629e44180417b32b4d66..6a5430fe54a5c8ad119a0f3842961825a54d8d7a 100644 +--- a/src/main/java/net/minecraft/world/level/EntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/EntityGetter.java +@@ -1,6 +1,9 @@ + package net.minecraft.world.level; + ++import com.google.common.collect.ImmutableList; + import com.google.common.collect.Lists; ++import org.bukkit.entity.HumanEntity; ++ + import java.util.Iterator; + import java.util.List; + import java.util.UUID; +@@ -115,6 +118,28 @@ public interface EntityGetter { + return entityhuman; + } + ++ // Paper start ++ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, boolean notSpectator) { ++ return findNearbyBukkitPlayers(x, y, z, radius, notSpectator ? EntitySelector.notSpectator() : EntitySelector.canAITarget()); ++ } ++ ++ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate predicate) { ++ ImmutableList.Builder builder = ImmutableList.builder(); ++ ++ for (Player human : this.players()) { ++ if (predicate == null || predicate.test(human)) { ++ double distanceSquared = human.getDistanceSquared(x, y, z); ++ ++ if (radius < 0.0D || distanceSquared < radius * radius) { ++ builder.add(human.getBukkitEntity()); ++ } ++ } ++ } ++ ++ return builder.build(); ++ } ++ // Paper end ++ + @Nullable + default Player getNearestPlayer(Entity entity, double maxDistance) { + return this.getNearestPlayer(entity.getX(), entity.getY(), entity.getZ(), maxDistance, false); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java +index b52ca4a612e30542ef4029cb1340f616bc4c36e6..7f984639fc2697cad9d0393467b0cb896d1e55a4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java +@@ -25,4 +25,26 @@ public class CraftSkeletonHorse extends CraftAbstractHorse implements SkeletonHo + public Variant getVariant() { + return Variant.SKELETON_HORSE; + } ++ ++ // Paper start ++ @Override ++ public net.minecraft.world.entity.animal.horse.SkeletonHorse getHandle() { ++ return (net.minecraft.world.entity.animal.horse.SkeletonHorse) super.getHandle(); ++ } ++ ++ @Override ++ public int getTrapTime() { ++ return getHandle().getTrapTime(); ++ } ++ ++ @Override ++ public boolean isTrap() { ++ return getHandle().isTrap(); ++ } ++ ++ @Override ++ public void setTrap(boolean trap) { ++ getHandle().setTrap(trap); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0251-Prevent-Saving-Bad-entities-to-chunks.patch b/patches/server-remapped/0251-Prevent-Saving-Bad-entities-to-chunks.patch new file mode 100644 index 0000000000..946c608327 --- /dev/null +++ b/patches/server-remapped/0251-Prevent-Saving-Bad-entities-to-chunks.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 26 Jul 2018 00:11:12 -0400 +Subject: [PATCH] Prevent Saving Bad entities to chunks + +See https://github.com/PaperMC/Paper/issues/1223 + +Minecraft is saving invalid entities to the chunk files. + +Avoid saving bad data, and also make improvements to handle +loading these chunks. Any invalid entity will be instant killed, +so lets avoid adding it to the world... + +This lets us be safer about the dupe UUID resolver too, as now +we can ignore instant killed entities and avoid risk of duplicating +an invalid entity. + +This should reduce log occurrences of dupe uuid messages. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index a5d7781b13a6d61238d026f064512f7162e1e868..8e8e5f30c512ed7d8ee987550c22d3e9df845043 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1151,6 +1151,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + List[] aentityslice = chunk.getEntitySlices(); // Spigot + int i = aentityslice.length; + ++ java.util.List toMoveChunks = new java.util.ArrayList<>(); // Paper + for (int j = 0; j < i; ++j) { + List entityslice = aentityslice[j]; // Spigot + Iterator iterator = entityslice.iterator(); +@@ -1163,11 +1164,25 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + throw (IllegalStateException) Util.pauseInIde((Throwable) (new IllegalStateException("Removing entity while ticking!"))); + } + ++ // Paper start - move out entities that shouldn't be in this chunk before it unloads ++ if (!entity.removed && (int) Math.floor(entity.getX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk.getPos().z) { ++ toMoveChunks.add(entity); ++ continue; ++ } ++ // Paper end ++ + this.entitiesById.remove(entity.getId()); + this.onEntityRemoved(entity); ++ ++ if (entity.removed) iterator.remove(); // Paper - don't save dead entities during unload + } + } + } ++ // Paper start - move out entities that shouldn't be in this chunk before it unloads ++ for (Entity entity : toMoveChunks) { ++ this.updateChunkPos(entity); ++ } ++ // Paper end + + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 0efaf4d0f58bcf38b427e76bf09b96e354294159..542d6f322df5f44ad9f504c8e14c88e3fa540657 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -27,6 +27,7 @@ import net.minecraft.nbt.LongArrayTag; + import net.minecraft.nbt.ShortTag; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.level.ThreadedLevelLightEngine; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -349,6 +350,7 @@ public class ChunkSerializer { + nbttagcompound1.put("TileEntities", nbttaglist1); + ListTag nbttaglist2 = new ListTag(); + ++ java.util.List toUpdate = new java.util.ArrayList<>(); // Paper + if (chunk.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { + LevelChunk chunk1 = (LevelChunk) chunk; + +@@ -366,13 +368,28 @@ public class ChunkSerializer { + while (iterator1.hasNext()) { + Entity entity = (Entity) iterator1.next(); + CompoundTag nbttagcompound4 = new CompoundTag(); +- ++ // Paper start ++ if ((int) Math.floor(entity.getX()) >> 4 != chunk1.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk1.getPos().z) { ++ toUpdate.add(entity); ++ continue; ++ } ++ if (entity.removed || hasPlayerPassenger(entity)) { ++ continue; ++ } ++ // Paper end + if (entity.save(nbttagcompound4)) { + chunk1.setLastSaveHadEntities(true); + nbttaglist2.add(nbttagcompound4); + } + } + } ++ ++ // Paper start - move entities to the correct chunk ++ for (Entity entity : toUpdate) { ++ world.updateChunkPos(entity); ++ } ++ // Paper end ++ + } else { + ProtoChunk protochunk = (ProtoChunk) chunk; + +@@ -431,6 +448,19 @@ public class ChunkSerializer { + nbttagcompound1.put("Structures", packStructureData(chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences())); + return nbttagcompound; + } ++ // Paper start - this is saved with the player ++ private static boolean hasPlayerPassenger(Entity entity) { ++ for (Entity passenger : entity.passengers) { ++ if (passenger instanceof ServerPlayer) { ++ return true; ++ } ++ if (hasPlayerPassenger(passenger)) { ++ return true; ++ } ++ } ++ return false; ++ } ++ // Paper end + + public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag tag) { + if (tag != null) { diff --git a/patches/server-remapped/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch b/patches/server-remapped/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch new file mode 100644 index 0000000000..0133184a69 --- /dev/null +++ b/patches/server-remapped/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Thu, 26 Jul 2018 14:10:23 +0200 +Subject: [PATCH] Don't call getItemMeta on hasItemMeta + +Spigot 1.13 checks if any field (which are manually copied from the ItemStack's "tag" NBT tag) on the ItemMeta class of an ItemStack is set. + +We could just check if the "tag" NBT tag is empty, albeit that would break some plugins. The only general tag added on 1.13 is "Damage", and we can just check if the "tag" NBT tag contains any other tag that's not "Damage" (https://minecraft.gamepedia.com/Player.dat_format#Item_structure) making the `hasItemStack` method behave as before. + +Returns true if getDamage() == 0 or has damage tag or other tag is set. +Check the `ItemMetaTest#testTaggedButNotMeta` method to see how this method behaves. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index 44caf00330e4f4f74745973dbe709980f0b61269..9e06912b0c13c3d61bc95e526acaa28f96b46fb9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -569,7 +569,7 @@ public final class CraftItemStack extends ItemStack { + + @Override + public boolean hasItemMeta() { +- return hasItemMeta(handle) && !CraftItemFactory.instance().equals(getItemMeta(), null); ++ return hasItemMeta(handle) && (handle.getDamageValue() != 0 || (handle.getTag() != null && handle.getTag().tags.size() >= (handle.getTag().contains(CraftMetaItem.DAMAGE.NBT) ? 2 : 1))); // Paper - keep 1.12 CraftBukkit behavior without calling getItemMeta + } + + static boolean hasItemMeta(net.minecraft.world.item.ItemStack item) { +diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +index 42f577ed3508ba5a380648461e149f16ce97c9bd..b85a0a4c4f134dd6012d9141244ecf97b4300b65 100644 +--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java ++++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +@@ -96,6 +96,34 @@ public class ItemMetaTest extends AbstractTestingBase { + assertThat(itemMeta.hasConflictingEnchant(null), is(false)); + } + ++ // Paper start ++ private void testItemMeta(ItemStack stack) { ++ assertThat("Should not have ItemMeta", stack.hasItemMeta(), is(false)); ++ ++ stack.setDurability((short) 0); ++ assertThat("ItemStack with zero durability should not have ItemMeta", stack.hasItemMeta(), is(false)); ++ ++ stack.setDurability((short) 2); ++ assertThat("ItemStack with non-zero durability should have ItemMeta", stack.hasItemMeta(), is(true)); ++ ++ stack.setLore(java.util.Collections.singletonList("Lore")); ++ assertThat("ItemStack with lore and durability should have ItemMeta", stack.hasItemMeta(), is(true)); ++ ++ stack.setDurability((short) 0); ++ assertThat("ItemStack with lore should have ItemMeta", stack.hasItemMeta(), is(true)); ++ ++ stack.setLore(null); ++ } ++ ++ @Test ++ public void testHasItemMeta() { ++ ItemStack itemStack = new ItemStack(Material.SHEARS); ++ ++ testItemMeta(itemStack); ++ testItemMeta(CraftItemStack.asCraftCopy(itemStack)); ++ } ++ // Paper end ++ + @Test + public void testConflictingStoredEnchantment() { + EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) Bukkit.getItemFactory().getItemMeta(Material.ENCHANTED_BOOK); diff --git a/patches/server-remapped/0253-Ignore-Dead-Entities-in-entityList-iteration.patch b/patches/server-remapped/0253-Ignore-Dead-Entities-in-entityList-iteration.patch new file mode 100644 index 0000000000..ae6ea8935e --- /dev/null +++ b/patches/server-remapped/0253-Ignore-Dead-Entities-in-entityList-iteration.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 28 Jul 2018 12:18:27 -0400 +Subject: [PATCH] Ignore Dead Entities in entityList iteration + +A spigot change delays removal of entities from the entity list. +This causes a change in behavior from Vanilla where getEntities type +methods will return dead entities that they shouldn't otherwise be doing. + +This will ensure that dead entities are skipped from iteration since +they shouldn't of been in the list in the first place. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index e95b91cefb0374bd5bb57cc090f5ecd566d7a618..8fd716bf2e1402694798b8be03fd85821153be44 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -209,6 +209,7 @@ public class PaperCommand extends Command { + Collection entities = world.entitiesById.values(); + entities.forEach(e -> { + ResourceLocation key = e.getMinecraftKey(); ++ if (e.shouldBeRemoved) return; // Paper + + MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); + ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 8e8e5f30c512ed7d8ee987550c22d3e9df845043..84b2cd661697545186677ab7966556d9288c650b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1303,6 +1303,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + entity.origin = entity.getBukkitEntity().getLocation(); + } + // Paper end ++ entity.shouldBeRemoved = false; // Paper - shouldn't be removed after being re-added + new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + } + +@@ -1315,6 +1316,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.removeFromChunk(entity); + this.entitiesById.remove(entity.getId()); + this.onEntityRemoved(entity); ++ entity.shouldBeRemoved = true; // Paper + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 7847078c54154e28ab066ea8a329f929df1e1a37..5bf6bc6a01ccde8a4d67b49293bb326cb09248d8 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -275,6 +275,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end ++ public boolean shouldBeRemoved; // Paper + + public float getBukkitYaw() { + return this.yRot; +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 09aa608bd303b618ae2c0ebd237bcbdba60a37a8..db28bfe95c885cdefa855c7aaa3bcf92bc52df26 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -862,6 +862,7 @@ public class LevelChunk implements ChunkAccess { + + for (int i1 = 0; i1 < l; ++i1) { + Entity entity1 = (Entity) list1.get(i1); ++ if (entity1.shouldBeRemoved) continue; // Paper + + if (entity1.getBoundingBox().intersects(box) && entity1 != except) { + if (predicate == null || predicate.test(entity1)) { +@@ -899,6 +900,7 @@ public class LevelChunk implements ChunkAccess { + + while (iterator.hasNext()) { + T entity = (T) iterator.next(); // CraftBukkit - decompile error ++ if (entity.shouldBeRemoved) continue; // Paper + + if ((type == null || entity.getType() == type) && entity.getBoundingBox().intersects(box) && predicate.test(entity)) { + result.add(entity); +@@ -921,6 +923,7 @@ public class LevelChunk implements ChunkAccess { + + while (iterator.hasNext()) { + T t0 = (T) iterator.next(); // CraftBukkit - decompile error ++ if (t0.shouldBeRemoved) continue; // Paper + + if (entityClass.isInstance(t0) && t0.getBoundingBox().intersects(box) && (predicate == null || predicate.test(t0))) { // Spigot - instance check + result.add(t0); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 3a3466cd9bbd34dbc0b79567f5579e84a81d6009..9807612aed6c4393cbe1f4b6078e45bf1ba3deb2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1022,6 +1022,7 @@ public class CraftWorld implements World { + for (Object o : world.entitiesById.values()) { + if (o instanceof net.minecraft.world.entity.Entity) { + net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; ++ if (mcEnt.shouldBeRemoved) continue; // Paper + Entity bukkitEntity = mcEnt.getBukkitEntity(); + + // Assuming that bukkitEntity isn't null +@@ -1041,6 +1042,7 @@ public class CraftWorld implements World { + for (Object o : world.entitiesById.values()) { + if (o instanceof net.minecraft.world.entity.Entity) { + net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; ++ if (mcEnt.shouldBeRemoved) continue; // Paper + Entity bukkitEntity = mcEnt.getBukkitEntity(); + + // Assuming that bukkitEntity isn't null +@@ -1067,6 +1069,7 @@ public class CraftWorld implements World { + + for (Object entity: world.entitiesById.values()) { + if (entity instanceof net.minecraft.world.entity.Entity) { ++ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper + Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); + + if (bukkitEntity == null) { +@@ -1090,6 +1093,7 @@ public class CraftWorld implements World { + + for (Object entity: world.entitiesById.values()) { + if (entity instanceof net.minecraft.world.entity.Entity) { ++ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper + Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); + + if (bukkitEntity == null) { diff --git a/patches/server-remapped/0254-Implement-Expanded-ArmorStand-API.patch b/patches/server-remapped/0254-Implement-Expanded-ArmorStand-API.patch new file mode 100644 index 0000000000..4909987c8f --- /dev/null +++ b/patches/server-remapped/0254-Implement-Expanded-ArmorStand-API.patch @@ -0,0 +1,104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: willies952002 +Date: Thu, 26 Jul 2018 02:25:46 -0400 +Subject: [PATCH] Implement Expanded ArmorStand API + +Add the following: +- Add proper methods for getting and setting items in both hands. Deprecates old methods +- Enable/Disable slot interactions + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 7fc69adc8afa971ee3cf815c6002628ae2149a5b..06e52a0c5decf717e35c605d6bcb46c3c7b29656 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -426,6 +426,7 @@ public class ArmorStand extends LivingEntity { + return enumitemslot; + } + ++ public final boolean isSlotDisabled(net.minecraft.world.entity.EquipmentSlot slot) { return this.isDisabled(slot); } // Paper - OBFHELPER + private boolean isDisabled(net.minecraft.world.entity.EquipmentSlot slot) { + return (this.disabledSlots & 1 << slot.getFilterFlag()) != 0 || slot.getType() == net.minecraft.world.entity.EquipmentSlot.Type.HAND && !this.isShowArms(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +index 16f996d505b96da8a40c7709214ebbd2a0d0d9f3..d4da5214a39b718671dcaf687cb0ff8668ce9728 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +@@ -238,5 +238,78 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public void setCanMove(boolean move) { + getHandle().canMove = move; + } ++ ++ @Override ++ public ItemStack getItem(org.bukkit.inventory.EquipmentSlot slot) { ++ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); ++ return getHandle().getItemBySlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)).asBukkitMirror(); ++ } ++ ++ @Override ++ public void setItem(org.bukkit.inventory.EquipmentSlot slot, ItemStack item) { ++ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); ++ switch (slot) { ++ case HAND: ++ getEquipment().setItemInMainHand(item); ++ return; ++ case OFF_HAND: ++ getEquipment().setItemInOffHand(item); ++ return; ++ case FEET: ++ setBoots(item); ++ return; ++ case LEGS: ++ setLeggings(item); ++ return; ++ case CHEST: ++ setChestplate(item); ++ return; ++ case HEAD: ++ setHelmet(item); ++ return; ++ } ++ throw new UnsupportedOperationException(slot.name()); ++ } ++ ++ @Override ++ public java.util.Set getDisabledSlots() { ++ java.util.Set disabled = new java.util.HashSet<>(); ++ for (org.bukkit.inventory.EquipmentSlot slot : org.bukkit.inventory.EquipmentSlot.values()) { ++ if (this.isSlotDisabled(slot)) { ++ disabled.add(slot); ++ } ++ } ++ return disabled; ++ } ++ ++ @Override ++ public void setDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { ++ int disabled = 0; ++ for (org.bukkit.inventory.EquipmentSlot slot : slots) { ++ if (slot == org.bukkit.inventory.EquipmentSlot.OFF_HAND) continue; ++ net.minecraft.world.entity.EquipmentSlot nmsSlot = org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot); ++ disabled += (1 << nmsSlot.getFilterFlag()) + (1 << (nmsSlot.getFilterFlag() + 8)) + (1 << (nmsSlot.getFilterFlag() + 16)); ++ } ++ getHandle().disabledSlots = disabled; ++ } ++ ++ @Override ++ public void addDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { ++ java.util.Set disabled = getDisabledSlots(); ++ java.util.Collections.addAll(disabled, slots); ++ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); ++ } ++ ++ @Override ++ public void removeDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { ++ java.util.Set disabled = getDisabledSlots(); ++ for (final org.bukkit.inventory.EquipmentSlot slot : slots) disabled.remove(slot); ++ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); ++ } ++ ++ @Override ++ public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { ++ return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); ++ } + // Paper end + } diff --git a/patches/server-remapped/0255-AnvilDamageEvent.patch b/patches/server-remapped/0255-AnvilDamageEvent.patch new file mode 100644 index 0000000000..8e4a474184 --- /dev/null +++ b/patches/server-remapped/0255-AnvilDamageEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 20 Jul 2018 23:37:03 -0500 +Subject: [PATCH] AnvilDamageEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +index aa4b03dc9a0d6b3f387f081a1887672b90c60ef9..3d53edae7e3d5bb00913384ad0eb67551a65750e 100644 +--- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +@@ -80,7 +80,16 @@ public class AnvilMenu extends ItemCombinerMenu { + + if (!player.abilities.instabuild && iblockdata.is((Tag) BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { + BlockState iblockdata1 = AnvilBlock.damage(iblockdata); +- ++ // Paper start ++ com.destroystokyo.paper.event.block.AnvilDamagedEvent event = new com.destroystokyo.paper.event.block.AnvilDamagedEvent(getBukkitView(), iblockdata1 != null ? org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(iblockdata1) : null); ++ if (!event.callEvent()) { ++ return; ++ } else if (event.getDamageState() == com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState.BROKEN) { ++ iblockdata1 = null; ++ } else { ++ iblockdata1 = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getDamageState().getMaterial().createBlockData()).getState().setValue(AnvilBlock.FACING, iblockdata.getValue(AnvilBlock.FACING)); ++ } ++ // Paper end + if (iblockdata1 == null) { + world.removeBlock(blockposition, false); + world.levelEvent(1029, blockposition, 0); diff --git a/patches/server-remapped/0256-Add-TNTPrimeEvent.patch b/patches/server-remapped/0256-Add-TNTPrimeEvent.patch new file mode 100644 index 0000000000..812624262a --- /dev/null +++ b/patches/server-remapped/0256-Add-TNTPrimeEvent.patch @@ -0,0 +1,148 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Mon, 16 Jul 2018 00:05:05 +0300 +Subject: [PATCH] Add TNTPrimeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index ae3cf71f14526e1f356216dfaa899c8f5083d46d..37a9e9df7f7f816c214c37e545288bf9329626ed 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -61,6 +61,7 @@ import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.event.entity.EntityExplodeEvent; + import org.bukkit.event.entity.EntityRegainHealthEvent; + // CraftBukkit end ++import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent + + public class EnderDragon extends Mob implements Enemy { + +@@ -515,6 +516,11 @@ public class EnderDragon extends Mob implements Enemy { + }); + craftBlock.getNMS().spawnAfterBreak((ServerLevel) level, blockposition, ItemStack.EMPTY); + } ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = level.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, explosionSource.getSourceMob().getBukkitEntity()).callEvent()) ++ continue; ++ // Paper end + nmsBlock.wasExploded(level, blockposition, explosionSource); + + this.level.removeBlock(blockposition, false); +diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java +index 85170008de6e77cfb8e4f55ae440a8428d868af4..31b6c1333c7d0af28385e804e94348cef398748b 100644 +--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java +@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; + import com.google.common.collect.ImmutableMap; + import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent + import java.util.Map; + import java.util.Random; + import java.util.function.Function; +@@ -11,6 +12,7 @@ import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.Vec3i; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.BlockGetter; +@@ -288,7 +290,7 @@ public class FireBlock extends BaseFireBlock { + + world.setBlock(blockposition, this.getStateWithAge(world, blockposition, l), 3); + } else { +- world.removeBlock(blockposition, false); ++ if(iblockdata.getBlock() != Blocks.TNT) world.removeBlock(blockposition, false); // Paper - TNTPrimeEvent - We might be cancelling it below, move the setAir down + } + + Block block = iblockdata.getBlock(); +@@ -296,6 +298,13 @@ public class FireBlock extends BaseFireBlock { + if (block instanceof TntBlock) { + TntBlock blocktnt = (TntBlock) block; + ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = MCUtil.toBukkitBlock(world, blockposition); ++ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.FIRE, null).callEvent()) { ++ return; ++ } ++ world.setAir(blockposition, false); ++ // Paper end + TntBlock.explode(world, blockposition); + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/TntBlock.java b/src/main/java/net/minecraft/world/level/block/TntBlock.java +index 5c06e2f69f6c0a03f12fab6accc5f9a79ae37118..76665be4b3f2e2821c35d3d6d6407c4da4f224e7 100644 +--- a/src/main/java/net/minecraft/world/level/block/TntBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TntBlock.java +@@ -22,6 +22,7 @@ import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.phys.BlockHitResult; ++import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent + + public class TntBlock extends Block { + +@@ -36,6 +37,11 @@ public class TntBlock extends Block { + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + if (!oldState.is(state.getBlock())) { + if (world.hasNeighborSignal(pos)) { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos);; ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) ++ return; ++ // Paper end + explode(world, pos); + world.removeBlock(pos, false); + } +@@ -46,6 +52,11 @@ public class TntBlock extends Block { + @Override + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { + if (world.hasNeighborSignal(pos)) { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos);; ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) ++ return; ++ // Paper end + explode(world, pos); + world.removeBlock(pos, false); + } +@@ -64,6 +75,12 @@ public class TntBlock extends Block { + @Override + public void wasExploded(Level world, BlockPos pos, Explosion explosion) { + if (!world.isClientSide) { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos); ++ org.bukkit.entity.Entity source = explosion.source != null ? explosion.source.getBukkitEntity() : null; ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) ++ return; ++ // Paper end + PrimedTnt entitytntprimed = new PrimedTnt(world, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, explosion.getSourceMob()); + + entitytntprimed.setFuse((short) (world.random.nextInt(entitytntprimed.getLife() / 4) + entitytntprimed.getLife() / 8)); +@@ -92,6 +109,11 @@ public class TntBlock extends Block { + if (item != Items.FLINT_AND_STEEL && item != Items.FIRE_CHARGE) { + return super.use(state, world, pos, player, hand, hit); + } else { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos); ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.ITEM, player.getBukkitEntity()).callEvent()) ++ return InteractionResult.FAIL; ++ // Paper end + explode(world, pos, (LivingEntity) player); + world.setBlock(pos, Blocks.AIR.defaultBlockState(), 11); + if (!player.isCreative()) { +@@ -121,6 +143,13 @@ public class TntBlock extends Block { + } + // CraftBukkit end + ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); ++ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.PROJECTILE, projectile.getBukkitEntity()).callEvent()) { ++ return; ++ } ++ // Paper end ++ + explode(world, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null); + world.removeBlock(blockposition, false); + } diff --git a/patches/server-remapped/0257-Break-up-and-make-tab-spam-limits-configurable.patch b/patches/server-remapped/0257-Break-up-and-make-tab-spam-limits-configurable.patch new file mode 100644 index 0000000000..a6f013522a --- /dev/null +++ b/patches/server-remapped/0257-Break-up-and-make-tab-spam-limits-configurable.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 29 Jul 2018 05:02:15 +0100 +Subject: [PATCH] Break up and make tab spam limits configurable + +Due to the changes in 1.13, clients will send a tab completion request +for all bukkit commands in order to factor in the lack of support for +brigadier and provide backwards support in the API. + +Craftbukkit, however; has moved the chat spam limiter to also interact +with the tab completion request, which while good for avoiding abuse, +causes 1.13 clients to easilly be kicked from a server in bukkit due +to this. Removing the spam limit could cause issues for servers, however, +there is no way for servers to manipulate this without blindly cancelling +kick events, which only causes additional complications. This also causes +issues in that the tab spam limit and chat share the same field but different +limits, meaning that a player having typed a long command may be kicked from +the server. + +Splitting the field up and making it configurable allows for server owners +to take the burden of this into their own hand without having to rely on +plugins doing unsafe things. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 77a03abd59db4a43f6f2d59d4c7ef176e782f205..bd508025b771424c942fd856c31d520b6f548082 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -296,4 +296,18 @@ public class PaperConfig { + Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); + } + } ++ ++ public static int tabSpamIncrement = 1; ++ public static int tabSpamLimit = 500; ++ private static void tabSpamLimiters() { ++ tabSpamIncrement = getInt("settings.spam-limiter.tab-spam-increment", tabSpamIncrement); ++ // Older versions used a smaller limit, which is too low for 1.13, we'll bump this up if default ++ if (version < 14) { ++ if (tabSpamIncrement == 10) { ++ set("settings.spam-limiter.tab-spam-increment", 2); ++ tabSpamIncrement = 2; ++ } ++ } ++ tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 645f7b7c862acf77d70ca0b05308945424bc4d32..900c9b1106a153bc386f6c3d9c11226f8ac69f86 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -228,6 +228,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit start - multithreaded fields + private volatile int chatSpamTickCount; + private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(ServerGamePacketListenerImpl.class, "chatThrottle"); ++ private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits + // CraftBukkit end + private int dropSpamTickCount; + private final Int2ShortMap expectedAcks = new Int2ShortOpenHashMap(); +@@ -363,6 +364,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.server.getProfiler().pop(); + // CraftBukkit start + for (int spam; (spam = this.chatSpamTickCount) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; ++ if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable + /* Use thread-safe field access instead + if (this.chatThrottle > 0) { + --this.chatThrottle; +@@ -714,7 +716,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { + // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async + // CraftBukkit start +- if (chatSpamField.addAndGet(this, 1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable + server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper + return; + } diff --git a/patches/server-remapped/0258-Add-hand-to-bucket-events.patch b/patches/server-remapped/0258-Add-hand-to-bucket-events.patch new file mode 100644 index 0000000000..80b6896fe7 --- /dev/null +++ b/patches/server-remapped/0258-Add-hand-to-bucket-events.patch @@ -0,0 +1,341 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Thu, 2 Aug 2018 08:44:35 -0500 +Subject: [PATCH] Add hand to bucket events + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index d34da1eb172a7dcda564680afecf3dc145bf09f3..125a75576442eaa4f1ff6dd153bdb31097497a3f 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -724,7 +724,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop cachedSingleHashSet; // Paper + + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { +- super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); ++ super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); + this.respawnDimension = Level.OVERWORLD; + interactionManager.player = this; + this.gameMode = interactionManager; +@@ -254,7 +254,7 @@ public class ServerPlayer extends Player implements ContainerListener { + // Yes, this doesn't match Vanilla, but it's the best we can do for now. + // If this is an issue, PRs are welcome + public final BlockPos getSpawnPoint(ServerLevel worldserver) { +- BlockPos blockposition = worldserver.getSharedSpawnPos(); ++ BlockPos blockposition = worldserver.getSpawn(); + + if (worldserver.dimensionType().hasSkyLight() && worldserver.worldDataServer.getGameType() != GameType.ADVENTURE) { + int i = Math.max(0, this.server.getSpawnRadius(worldserver)); +@@ -291,7 +291,7 @@ public class ServerPlayer extends Player implements ContainerListener { + // CraftBukkit end + + private void fudgeSpawnLocation(ServerLevel world) { +- BlockPos blockposition = world.getSharedSpawnPos(); ++ BlockPos blockposition = world.getSpawn(); + + if (world.dimensionType().hasSkyLight() && world.worldDataServer.getGameType() != GameType.ADVENTURE) { // CraftBukkit + int i = Math.max(0, this.server.getSpawnRadius(world)); +@@ -464,7 +464,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + if (world == null || position == null) { + world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(); +- position = Vec3.atCenterOf(((ServerLevel) world).getSharedSpawnPos()); ++ position = Vec3.atCenterOf(((ServerLevel) world).getSpawn()); + } + this.level = world; + this.setPos(position.x(), position.y(), position.z()); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 51b1ce465d23b971f7e08a3175319a33183d0398..0bb397407b55bd1c464ac603ec4c189045aabbb2 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -808,7 +808,7 @@ public abstract class PlayerList { + entityplayer1.setShiftKeyDown(false); + + // entityplayer1.playerConnection.a(entityplayer1.locX(), entityplayer1.locY(), entityplayer1.locZ(), entityplayer1.yaw, entityplayer1.pitch); +- entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSharedSpawnPos(), worldserver1.getSharedSpawnAngle())); ++ entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSpawn(), worldserver1.getSharedSpawnAngle())); + entityplayer1.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); + entityplayer1.connection.send(new ClientboundSetExperiencePacket(entityplayer1.experienceProgress, entityplayer1.totalExperience, entityplayer1.experienceLevel)); + this.sendLevelInfo(entityplayer1, worldserver1); +@@ -1090,7 +1090,7 @@ public abstract class PlayerList { + + player.connection.send(new ClientboundSetBorderPacket(worldborder, ClientboundSetBorderPacket.Type.INITIALIZE)); + player.connection.send(new ClientboundSetTimePacket(world.getGameTime(), world.getDayTime(), world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); +- player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(world.getSharedSpawnPos(), world.getSharedSpawnAngle())); ++ player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(world.getSpawn(), world.getSharedSpawnAngle())); + if (world.isRaining()) { + // CraftBukkit start - handle player weather + // entityplayer.playerConnection.sendPacket(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.b, 0.0F)); +diff --git a/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java b/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java +index c283ea9528493fb95088870c84c6d6e3963aabb7..2633aca30601682a53b0236b94a12f0f18a87fc2 100644 +--- a/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java ++++ b/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java +@@ -33,7 +33,7 @@ public class RconConsoleSource implements CommandSource { + public CommandSourceStack createCommandSourceStack() { + ServerLevel worldserver = this.server.overworld(); + +- return new CommandSourceStack(this, Vec3.atLowerCornerOf((Vec3i) worldserver.getSharedSpawnPos()), Vec2.ZERO, worldserver, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null); ++ return new CommandSourceStack(this, Vec3.atLowerCornerOf((Vec3i) worldserver.getSpawn()), Vec2.ZERO, worldserver, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null); + } + + // CraftBukkit start - Send a String +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 5bf6bc6a01ccde8a4d67b49293bb326cb09248d8..4503bd65b3454bad94bb7b869f4e72e3121d8a3d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2688,7 +2688,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + if (flag1) { + blockposition1 = ServerLevel.END_SPAWN_POINT; + } else { +- blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos()); ++ blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSpawn()); + } + // CraftBukkit start + CraftPortalEvent event = callPortalEvent(this, destination, blockposition1, PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); +diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java +index 90393bb196c0895f387259c2dccbb29e2ca11c87..9c67b603d4d0ee5cb7f86b25ed8754afaf9cf7b3 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Cow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Cow.java +@@ -87,7 +87,7 @@ public class Cow extends Animal { + + if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) { + // CraftBukkit start - Got milk? +- org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET); ++ org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); // Paper - add enumHand + + if (event.isCancelled()) { + return InteractionResult.PASS; +diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java +index b426e155d13a1b2eb5ddb24a2d83cd7d1e92026b..d0e847e58483695d2af1c1410826bb25231cd6f6 100644 +--- a/src/main/java/net/minecraft/world/item/BucketItem.java ++++ b/src/main/java/net/minecraft/world/item/BucketItem.java +@@ -69,7 +69,7 @@ public class BucketItem extends Item { + if (iblockdata.getBlock() instanceof BucketPickup) { + // CraftBukkit start + Fluid dummyFluid = ((BucketPickup) iblockdata.getBlock()).takeLiquid(DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); +- PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getBucket()); ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getBucket(), hand); // Paper - add enumhand + + if (event.isCancelled()) { + ((ServerPlayer) user).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) +@@ -97,7 +97,7 @@ public class BucketItem extends Item { + iblockdata = world.getBlockState(blockposition); + BlockPos blockposition2 = iblockdata.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockposition : blockposition1; + +- if (this.a(user, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack)) { // CraftBukkit ++ if (this.a(user, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack, hand)) { // CraftBukkit // Paper - add enumhand + this.checkExtraContent(world, itemstack, blockposition2); + if (user instanceof ServerPlayer) { + CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) user, blockposition2, itemstack); +@@ -122,10 +122,12 @@ public class BucketItem extends Item { + public void checkExtraContent(Level world, ItemStack stack, BlockPos pos) {} + + public boolean emptyBucket(@Nullable Player player, Level world, BlockPos pos, @Nullable BlockHitResult movingobjectpositionblock) { +- return a(player, world, pos, movingobjectpositionblock, null, null, null); ++ // Paper start - add enumHand ++ return a(player, world, pos, movingobjectpositionblock, null, null, null, null); + } + +- public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack) { ++ public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, InteractionHand enumhand) { ++ // Paper end + // CraftBukkit end + if (!(this.content instanceof FlowingFluid)) { + return false; +@@ -138,7 +140,7 @@ public class BucketItem extends Item { + + // CraftBukkit start + if (flag1 && entityhuman != null) { +- PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack); ++ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); // Paper - add enumhand + if (event.isCancelled()) { + ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity + ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 +@@ -147,7 +149,7 @@ public class BucketItem extends Item { + } + // CraftBukkit end + if (!flag1) { +- return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack); // CraftBukkit ++ return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit // Paper - add enumhand + } else if (world.dimensionType().ultraWarm() && this.content.is((Tag) FluidTags.WATER)) { + int i = blockposition.getX(); + int j = blockposition.getY(); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 7a9ccd203885b9b369767d1fb8c53783201d0f0f..b75ffafb6840b6acab6e5b0ef5e222c4fa130977 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -277,6 +277,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + // Paper end + ++ // Paper start - moved up from WorldServer ++ public BlockPos getSpawn() { ++ BlockPos blockposition = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn()); ++ ++ if (!this.getWorldBorder().isWithinBounds(blockposition)) { ++ blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, new BlockPos(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); ++ } ++ ++ return blockposition; ++ } ++ // Paper end + @Override + public boolean isClientSide() { + return this.isClientSide; +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index 8a71eaf2855be0d415d1f7b18dbec98353fe5b47..b90a275a0dc2913809ce16659eed445501e486de 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -268,7 +268,7 @@ public final class NaturalSpawner { + private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) { + if (squaredDistance <= 576.0D) { + return false; +- } else if (world.getSharedSpawnPos().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D)) { ++ } else if (world.getSpawn().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D)) { + return false; + } else { + ChunkPos chunkcoordintpair = new ChunkPos(pos); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 9807612aed6c4393cbe1f4b6078e45bf1ba3deb2..159c32d6678e83f2d98ea6a1ad48346c9de017e1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -327,7 +327,7 @@ public class CraftWorld implements World { + + @Override + public Location getSpawnLocation() { +- BlockPos spawn = world.getSharedSpawnPos(); ++ BlockPos spawn = world.getSpawn(); + return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); + } + +@@ -1926,7 +1926,7 @@ public class CraftWorld implements World { + public void setKeepSpawnInMemory(boolean keepLoaded) { + world.keepSpawnInMemory = keepLoaded; + // Grab the worlds spawn chunk +- BlockPos chunkcoordinates = this.world.getSharedSpawnPos(); ++ BlockPos chunkcoordinates = this.world.getSpawn(); + if (keepLoaded) { + world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); + } else { +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 4cd08821305590e21a01cc4dda05370c2b721ac2..1877267344df1ff5b4de6a4e0c239f488cd52c1f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -222,7 +222,7 @@ public class CraftEventFactory { + public static Entity entityDamage; // For use in EntityDamageByEntityEvent + + // helper methods +- private static boolean canBuild(ServerLevel world, Player player, int x, int z) { ++ private static boolean canBuild(Level world, Player player, int x, int z) { + int spawnSize = Bukkit.getServer().getSpawnRadius(); + + if (world.dimension() != Level.OVERWORLD) return true; +@@ -230,7 +230,7 @@ public class CraftEventFactory { + if (((CraftServer) Bukkit.getServer()).getHandle().getOps().isEmpty()) return true; + if (player.isOp()) return true; + +- BlockPos chunkcoordinates = world.getSharedSpawnPos(); ++ BlockPos chunkcoordinates = world.getSpawn(); + + int distanceFromSpawn = Math.max(Math.abs(x - chunkcoordinates.getX()), Math.abs(z - chunkcoordinates.getZ())); + return distanceFromSpawn > spawnSize; +@@ -412,6 +412,20 @@ public class CraftEventFactory { + } + + private static PlayerEvent getPlayerBucketEvent(boolean isFilling, ServerLevel world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item) { ++ // Paper start - add enumHand ++ return getPlayerBucketEvent(isFilling, world, who, changed, clicked, clickedFace, itemstack, item, null); ++ } ++ ++ public static PlayerBucketEmptyEvent callPlayerBucketEmptyEvent(Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, InteractionHand enumHand) { ++ return (PlayerBucketEmptyEvent) getPlayerBucketEvent(false, world, who, changed, clicked, clickedFace, itemstack, Items.BUCKET, enumHand); ++ } ++ ++ public static PlayerBucketFillEvent callPlayerBucketFillEvent(Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemInHand, net.minecraft.world.item.Item bucket, InteractionHand enumHand) { ++ return (PlayerBucketFillEvent) getPlayerBucketEvent(true, world, who, clicked, changed, clickedFace, itemInHand, bucket, enumHand); ++ } ++ ++ private static PlayerEvent getPlayerBucketEvent(boolean isFilling, Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item, InteractionHand enumHand) { ++ // Paper end + Player player = (Player) who.getBukkitEntity(); + CraftItemStack itemInHand = CraftItemStack.asNewCraftStack(item); + Material bucket = CraftMagicNumbers.getMaterial(itemstack.getItem()); +@@ -424,10 +438,10 @@ public class CraftEventFactory { + + PlayerEvent event; + if (isFilling) { +- event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand); ++ event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand + ((PlayerBucketFillEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); + } else { +- event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand); ++ event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand + ((PlayerBucketEmptyEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); + } + diff --git a/patches/server-remapped/0259-MC-135506-Experience-should-save-as-Integers.patch b/patches/server-remapped/0259-MC-135506-Experience-should-save-as-Integers.patch new file mode 100644 index 0000000000..07dc1c1b3f --- /dev/null +++ b/patches/server-remapped/0259-MC-135506-Experience-should-save-as-Integers.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 3 Aug 2018 00:04:54 -0400 +Subject: [PATCH] MC-135506: Experience should save as Integers + + +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 52b90ef3a145325209d3d903a2b7c9a44c332cbe..37758cff3c4a8406c2f1496ae827ecdc953cf9f4 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -217,7 +217,7 @@ public class ExperienceOrb extends Entity { + public void addAdditionalSaveData(CompoundTag tag) { + tag.putShort("Health", (short) this.health); + tag.putShort("Age", (short) this.age); +- tag.putShort("Value", (short) this.value); ++ tag.putInt("Value", this.value); // Paper - save as Integer + this.savePaperNBT(tag); // Paper + } + +@@ -225,7 +225,7 @@ public class ExperienceOrb extends Entity { + public void readAdditionalSaveData(CompoundTag tag) { + this.health = tag.getShort("Health"); + this.age = tag.getShort("Age"); +- this.value = tag.getShort("Value"); ++ this.value = tag.getInt("Value"); // Paper - load as Integer + this.loadPaperNBT(tag); // Paper + } + diff --git a/patches/server-remapped/0260-Fix-client-rendering-skulls-from-same-user.patch b/patches/server-remapped/0260-Fix-client-rendering-skulls-from-same-user.patch new file mode 100644 index 0000000000..057731ba61 --- /dev/null +++ b/patches/server-remapped/0260-Fix-client-rendering-skulls-from-same-user.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 22 Nov 2016 00:40:42 -0500 +Subject: [PATCH] Fix client rendering skulls from same user + +See: https://github.com/PaperMC/Paper/issues/1304 + +Changes the UUID sent to client to be based on either +the texture payload, or random. + +This allows the client to render multiple skull textures from the same user, +for when different skins were used when skull was made. + +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index b4542ce6a8c37ab31e6ecaeb4cbad4742cca0f9b..10f1e3d761af83507bf71a00092641e22d0c8049 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -37,6 +37,7 @@ import net.minecraft.network.chat.Component; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.block.entity.SkullBlockEntity; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit +@@ -310,9 +311,18 @@ public class FriendlyByteBuf extends ByteBuf { + if (item.canBeDepleted() || item.shouldOverrideMultiplayerNbt()) { + // Spigot start - filter + itemstack = itemstack.copy(); +- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ //CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported + // Spigot end + nbttagcompound = itemstack.getTag(); ++ // Paper start ++ if (nbttagcompound != null && nbttagcompound.contains("SkullOwner", 10)) { ++ CompoundTag owner = nbttagcompound.getCompound("SkullOwner"); ++ if (owner.hasUUID("Id")) { ++ nbttagcompound.setUUID("SkullOwnerOrig", owner.getUUID("Id")); ++ SkullBlockEntity.sanitizeUUID(owner); ++ } ++ } ++ // Paper end + } + + this.writeNbt(nbttagcompound); +@@ -332,7 +342,16 @@ public class FriendlyByteBuf extends ByteBuf { + itemstack.setTag(this.readNbt()); + // CraftBukkit start + if (itemstack.getTag() != null) { +- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ // Paper start - Fix skulls of same owner - restore orig ID since we changed it on send to client ++ if (itemstack.tag.contains("SkullOwnerOrig")) { ++ CompoundTag owner = itemstack.tag.getCompound("SkullOwner"); ++ if (itemstack.tag.contains("SkullOwnerOrig")) { ++ owner.tags.put("Id", itemstack.tag.tags.get("SkullOwnerOrig")); ++ itemstack.tag.remove("SkullOwnerOrig"); ++ } ++ } ++ // Paper end ++ // CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported + } + // CraftBukkit end + return itemstack; +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index e5d4363edb8c494d2db69d2e0223a2db1519f64b..4fe15aa331ca18319ca46d1b426f0d6fd24341f0 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -15,6 +15,7 @@ import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.entity.SkullBlockEntity; + import net.minecraft.world.level.chunk.ChunkBiomeContainer; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.chunk.LevelChunkSection; +@@ -69,6 +70,7 @@ public class ClientboundLevelChunkPacket implements Packet public + private boolean emptyCacheFlag; + private Entity entityRepresentation; + private BlockInWorld cachedBreakBlock; +diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java +index eebaeaccc3ba1a9ec089d84b8de6c9d36034868f..6a1289424421083876d1808b7328cd3f01063a7e 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java +@@ -25,6 +25,7 @@ import java.util.concurrent.Executors; + import java.util.concurrent.Future; + import java.util.concurrent.TimeUnit; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; + import net.minecraft.server.MinecraftServer; +@@ -152,9 +153,37 @@ public class SkullBlockEntity extends BlockEntity /*implements ITickable*/ { // + @Nullable + @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { +- return new ClientboundBlockEntityDataPacket(this.worldPosition, 4, this.getUpdateTag()); ++ return new ClientboundBlockEntityDataPacket(this.worldPosition, 4, sanitizeTileEntityUUID(this.getUpdateTag())); // Paper + } + ++ // Paper start ++ public static CompoundTag sanitizeTileEntityUUID(CompoundTag cmp) { ++ CompoundTag owner = cmp.getCompound("Owner"); ++ if (!owner.isEmpty()) { ++ sanitizeUUID(owner); ++ } ++ return cmp; ++ } ++ ++ public static void sanitizeUUID(CompoundTag owner) { ++ CompoundTag properties = owner.getCompound("Properties"); ++ ListTag list = null; ++ if (!properties.isEmpty()) { ++ list = properties.getList("textures", 10); ++ } ++ ++ if (list != null && !list.isEmpty()) { ++ String textures = ((CompoundTag)list.get(0)).getString("Value"); ++ if (textures != null && textures.length() > 3) { ++ UUID uuid = UUID.nameUUIDFromBytes(textures.getBytes()); ++ owner.setUUID("Id", uuid); ++ return; ++ } ++ } ++ owner.setUUID("Id", UUID.randomUUID()); ++ } ++ // Paper end ++ + @Override + public CompoundTag getUpdateTag() { + return this.save(new CompoundTag()); diff --git a/patches/server-remapped/0261-Add-Early-Warning-Feature-to-WatchDog.patch b/patches/server-remapped/0261-Add-Early-Warning-Feature-to-WatchDog.patch new file mode 100644 index 0000000000..4f9ee3cc3e --- /dev/null +++ b/patches/server-remapped/0261-Add-Early-Warning-Feature-to-WatchDog.patch @@ -0,0 +1,184 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: miclebrick +Date: Wed, 8 Aug 2018 15:30:52 -0400 +Subject: [PATCH] Add Early Warning Feature to WatchDog + +Detect when the server has been hung for a long duration, and start printing +thread dumps at an interval until the point of crash. + +This will help diagnose what was going on in that time before the crash. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index bd508025b771424c942fd856c31d520b6f548082..62621562137cba4804f0465c58d25ca2786328e5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -25,6 +25,7 @@ import org.bukkit.configuration.file.YamlConfiguration; + import co.aikar.timings.Timings; + import co.aikar.timings.TimingsManager; + import org.spigotmc.SpigotConfig; ++import org.spigotmc.WatchdogThread; + + public class PaperConfig { + +@@ -297,6 +298,14 @@ public class PaperConfig { + } + } + ++ public static int watchdogPrintEarlyWarningEvery = 5000; ++ public static int watchdogPrintEarlyWarningDelay = 10000; ++ private static void watchdogEarlyWarning() { ++ watchdogPrintEarlyWarningEvery = getInt("settings.watchdog.early-warning-every", 5000); ++ watchdogPrintEarlyWarningDelay = getInt("settings.watchdog.early-warning-delay", 10000); ++ WatchdogThread.doStart(SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash ); ++ } ++ + public static int tabSpamIncrement = 1; + public static int tabSpamLimit = 500; + private static void tabSpamLimiters() { +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 125a75576442eaa4f1ff6dd153bdb31097497a3f..5a76ca77b974ff6fe862c9e05a88b507a34b44be 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1017,6 +1017,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable ++ // Paper start ++ Logger log = Bukkit.getServer().getLogger(); ++ long currentTime = monotonicMillis(); ++ if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) + { +- Logger log = Bukkit.getServer().getLogger(); ++ boolean isLongTimeout = currentTime > lastTick + timeoutTime; ++ // Don't spam early warning dumps ++ if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; ++ if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... ++ lastEarlyWarning = currentTime; ++ if (isLongTimeout) { ++ // Paper end + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper + log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); +@@ -93,29 +108,46 @@ public class WatchdogThread extends Thread + } + } + // Paper end ++ } else ++ { ++ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); ++ log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump"); ++ } ++ // Paper end - Different message for short timeout + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // ++ // Paper start - Only print full dump on long timeouts ++ if ( isLongTimeout ) ++ { + log.log( Level.SEVERE, "Entire Thread Dump:" ); + ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); + for ( ThreadInfo thread : threads ) + { + dumpThread( thread, log ); + } ++ } else { ++ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---"); ++ } ++ ++ + log.log( Level.SEVERE, "------------------------------" ); + ++ if ( isLongTimeout ) ++ { + if ( restart && !MinecraftServer.getServer().hasStopped() ) + { + RestartCommand.restart(); + } + break; ++ } // Paper end + } + + try + { +- sleep( 10000 ); ++ sleep( 1000 ); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout + } catch ( InterruptedException ex ) + { + interrupt(); diff --git a/patches/server-remapped/0262-Make-EnderDragon-implement-Mob.patch b/patches/server-remapped/0262-Make-EnderDragon-implement-Mob.patch new file mode 100644 index 0000000000..8392dc7bad --- /dev/null +++ b/patches/server-remapped/0262-Make-EnderDragon-implement-Mob.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 10 Aug 2018 22:11:49 -0400 +Subject: [PATCH] Make EnderDragon implement Mob + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java +index bba2e3152ee7073b75ecce1a4792178db20344db..aea39a6cb778d2ef88f66b632aebd824aaef2ea6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java +@@ -1,17 +1,17 @@ + package org.bukkit.craftbukkit.entity; + +-import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.Mob; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.ComplexLivingEntity; + +-public abstract class CraftComplexLivingEntity extends CraftLivingEntity implements ComplexLivingEntity { +- public CraftComplexLivingEntity(CraftServer server, LivingEntity entity) { ++public abstract class CraftComplexLivingEntity extends CraftMob implements ComplexLivingEntity { // Paper ++ public CraftComplexLivingEntity(CraftServer server, Mob entity) { // Paper + super(server, entity); + } + + @Override +- public LivingEntity getHandle() { +- return (LivingEntity) entity; ++ public Mob getHandle() { // Paper ++ return (Mob) entity; // Paper + } + + @Override diff --git a/patches/server-remapped/0263-Use-ConcurrentHashMap-in-JsonList.patch b/patches/server-remapped/0263-Use-ConcurrentHashMap-in-JsonList.patch new file mode 100644 index 0000000000..b981b8b044 --- /dev/null +++ b/patches/server-remapped/0263-Use-ConcurrentHashMap-in-JsonList.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: egg82 +Date: Tue, 7 Aug 2018 01:24:23 -0600 +Subject: [PATCH] Use ConcurrentHashMap in JsonList + +This is specifically aimed at fixing #471 + +Using a ConcurrentHashMap because thread safety +The performance benefit of Map over ConcurrentMap is negligabe at best in this scenaio, as most operations will be get and not add or remove +Even without considering the use-case the benefits are still negligable + +Original ideas for the system included an expiration policy and/or handler +The simpler solution was to use a computeIfPresent in the get method +This will simultaneously have an O(1) lookup time and automatically expire any values +Since the get method (nor other similar methods) don't seem to have a critical need to flush the map to disk at any of these points further processing is simply wasteful +Meaning the original function expired values unrelated to the current value without actually having any explicit need to + +The h method was heavily modified to be much more efficient in its processing +Also instead of being called on every get, it's now called just before a save +This will eliminate stale values being flushed to disk + +Modified isEmpty to use the isEmpty() method instead of the slightly confusing size() < 1 +The point of this is readability, but does have a side-benefit of a small microptimization + +Finally, added a couple obfhelpers for the modified code + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 0bb397407b55bd1c464ac603ec4c189045aabbb2..7c307a16ca3962db65be09a0ddd058a4ce81c7be 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -614,7 +614,7 @@ public abstract class PlayerList { + } else if (!this.isWhitelisted(gameprofile, event)) { // Paper + //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper + //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted +- } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { ++ } else if (getIpBans().isBanned(socketaddress) && getIpBans().get(socketaddress) != null && !getIpBans().get(socketaddress).hasExpired()) { // Paper - fix NPE with temp ip bans + IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); + + chatmessage = new TranslatableComponent("multiplayer.disconnect.banned_ip.reason", new Object[]{ipbanentry.getReason()}); +diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java +index 2cb235d695c244863a37454df22d5d94a291524d..e2982a8ac5448110378bc92247952332bdffe12c 100644 +--- a/src/main/java/net/minecraft/server/players/StoredUserList.java ++++ b/src/main/java/net/minecraft/server/players/StoredUserList.java +@@ -12,6 +12,8 @@ import java.io.BufferedReader; + import java.io.BufferedWriter; + import java.io.File; + import java.io.IOException; ++import java.lang.reflect.ParameterizedType; // Paper ++import java.lang.reflect.Type; // Paper + import java.nio.charset.StandardCharsets; + import java.util.Collection; + import java.util.Iterator; +@@ -28,7 +30,22 @@ public abstract class StoredUserList> { + protected static final Logger LOGGER = LogManager.getLogger(); + private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create(); + private final File file; +- private final Map map = Maps.newHashMap(); ++ // Paper - replace HashMap is ConcurrentHashMap ++ private final Map map = Maps.newConcurrentMap(); private final Map getBackingMap() { return this.map; } // Paper - OBFHELPER ++ private boolean e = true; ++ private static final ParameterizedType f = new ParameterizedType() { ++ public Type[] getActualTypeArguments() { ++ return new Type[]{StoredUserEntry.class}; ++ } ++ ++ public Type getRawType() { ++ return List.class; ++ } ++ ++ public Type getOwnerType() { ++ return null; ++ } ++ }; + + public StoredUserList(File file) { + this.file = file; +@@ -51,8 +68,13 @@ public abstract class StoredUserList> { + + @Nullable + public V get(K key) { +- this.removeExpired(); +- return (V) this.map.get(this.getKeyForUser(key)); // CraftBukkit - fix decompile error ++ // Paper start ++ // this.g(); ++ // return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error ++ return (V) this.getBackingMap().computeIfPresent(this.getMappingKey(key), (k, v) -> { ++ return v.hasExpired() ? null : v; ++ }); ++ // Paper end + } + + public void remove(K key) { +@@ -81,9 +103,11 @@ public abstract class StoredUserList> { + // CraftBukkit end + + public boolean isEmpty() { +- return this.map.size() < 1; ++ // return this.d.size() < 1; // Paper ++ return this.getBackingMap().isEmpty(); // Paper - readability is the goal. As an aside, isEmpty() uses only sumCount() and a comparison. size() uses sumCount(), casts, and boolean logic + } + ++ protected final String getMappingKey(K k0) { return getKeyForUser(k0); } // Paper - OBFHELPER + protected String getKeyForUser(K profile) { + return profile.toString(); + } +@@ -92,15 +116,16 @@ public abstract class StoredUserList> { + return this.map.containsKey(this.getKeyForUser(k0)); + } + ++ private void removeStaleEntries() { removeExpired(); } // Paper - OBFHELPER + private void removeExpired() { +- List list = Lists.newArrayList(); +- Iterator iterator = this.map.values().iterator(); ++ /*List list = Lists.newArrayList(); ++ Iterator iterator = this.d.values().iterator(); + + while (iterator.hasNext()) { + V v0 = (V) iterator.next(); // CraftBukkit - decompile error + + if (v0.hasExpired()) { +- list.add(v0.getUser()); ++ list.add(v0.getKey()); + } + } + +@@ -109,9 +134,11 @@ public abstract class StoredUserList> { + while (iterator.hasNext()) { + K k0 = (K) iterator.next(); // CraftBukkit - decompile error + +- this.map.remove(this.getKeyForUser(k0)); +- } ++ this.d.remove(this.a(k0)); ++ }*/ + ++ this.getBackingMap().values().removeIf(StoredUserEntry::hasExpired); ++ // Paper end + } + + protected abstract StoredUserEntry createEntry(JsonObject json); +@@ -121,6 +148,7 @@ public abstract class StoredUserList> { + } + + public void save() throws IOException { ++ this.removeStaleEntries(); // Paper - remove expired values before saving + JsonArray jsonarray = new JsonArray(); + + this.map.values().stream().map((jsonlistentry) -> { diff --git a/patches/server-remapped/0264-Use-a-Queue-for-Queueing-Commands.patch b/patches/server-remapped/0264-Use-a-Queue-for-Queueing-Commands.patch new file mode 100644 index 0000000000..b220fa4eb9 --- /dev/null +++ b/patches/server-remapped/0264-Use-a-Queue-for-Queueing-Commands.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 12 Aug 2018 02:33:39 -0400 +Subject: [PATCH] Use a Queue for Queueing Commands + +Lists are bad as Queues mmmkay. + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 9143fe99e43236bf65e6f098a30d522302ad78b7..4862a9519d4ba5f05b634a0335837bea9812edee 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -72,7 +72,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + + private static final Logger LOGGER = LogManager.getLogger(); + private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$"); +- private final List consoleInput = Collections.synchronizedList(Lists.newArrayList()); ++ private final java.util.Queue serverCommandQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Paper - use a proper queue + private QueryThreadGs4 queryThreadGs4; + public final RconConsoleSource rconConsoleSource; + private RconThread rconThread; +@@ -426,13 +426,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } + + public void handleConsoleInput(String command, CommandSourceStack commandSource) { +- this.consoleInput.add(new ConsoleInput(command, commandSource)); ++ this.serverCommandQueue.add(new ConsoleInput(command, commandSource)); + } + + public void handleConsoleInputs() { + MinecraftTimings.serverCommandTimer.startTiming(); // Spigot +- while (!this.consoleInput.isEmpty()) { +- ConsoleInput servercommand = (ConsoleInput) this.consoleInput.remove(0); ++ // Paper start - use proper queue ++ ConsoleInput servercommand; ++ while ((servercommand = this.serverCommandQueue.poll()) != null) { ++ // Paper end + + // CraftBukkit start - ServerCommand for preprocessing + ServerCommandEvent event = new ServerCommandEvent(console, servercommand.msg); diff --git a/patches/server-remapped/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/patches/server-remapped/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch new file mode 100644 index 0000000000..52dbc8ee7e --- /dev/null +++ b/patches/server-remapped/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 15 Aug 2018 01:16:34 -0400 +Subject: [PATCH] Ability to get Tile Entities from a chunk without snapshots + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +index 93b9e9d5932764f7e946dd3f8ab8191189c5d38f..423594177fe78600755d913f169f28dd1bfa2b37 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +@@ -3,8 +3,10 @@ package org.bukkit.craftbukkit; + import com.google.common.base.Preconditions; + import com.google.common.base.Predicates; + import java.lang.ref.WeakReference; ++import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collection; ++import java.util.List; + import java.util.function.Predicate; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Registry; +@@ -129,9 +131,16 @@ public class CraftChunk implements Chunk { + + @Override + public BlockState[] getTileEntities() { ++ // Paper start ++ return getTileEntities(true); ++ } ++ ++ @Override ++ public BlockState[] getTileEntities(boolean useSnapshot) { + if (!isLoaded()) { + getWorld().getChunkAt(x, z); // Transient load for this tick + } ++ // Paper end + int index = 0; + net.minecraft.world.level.chunk.LevelChunk chunk = getHandle(); + +@@ -143,11 +152,33 @@ public class CraftChunk implements Chunk { + } + + BlockPos position = (BlockPos) obj; +- entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(); ++ entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(useSnapshot); // Paper ++ } ++ ++ return entities; ++ } ++ ++ // Paper start ++ @Override ++ public Collection getTileEntities(Predicate blockPredicate, boolean useSnapshot) { ++ Preconditions.checkNotNull(blockPredicate, "blockPredicate"); ++ if (!isLoaded()) { ++ getWorld().getChunkAt(x, z); // Transient load for this tick ++ } ++ net.minecraft.world.level.chunk.LevelChunk chunk = getHandle(); ++ ++ List entities = new ArrayList<>(); ++ ++ for (BlockPos position : chunk.blockEntities.keySet()) { ++ Block block = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); ++ if (blockPredicate.test(block)) { ++ entities.add(block.getState(useSnapshot)); ++ } + } + + return entities; + } ++ // Paper end + + @Override + public boolean isLoaded() { diff --git a/patches/server-remapped/0266-Allow-disabling-armour-stand-ticking.patch b/patches/server-remapped/0266-Allow-disabling-armour-stand-ticking.patch new file mode 100644 index 0000000000..b471e98ef0 --- /dev/null +++ b/patches/server-remapped/0266-Allow-disabling-armour-stand-ticking.patch @@ -0,0 +1,159 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 15 Aug 2018 01:26:09 -0700 +Subject: [PATCH] Allow disabling armour stand ticking + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3562950df4868b1393790b1a1ff1fe0dc589c155..5ab0e7183e48134b7a0f736462516b1a8a333b04 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -384,4 +384,10 @@ public class PaperWorldConfig { + private void armorStandEntityLookups() { + armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); + } ++ ++ public boolean armorStandTick = true; ++ private void armorStandTick() { ++ this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); ++ log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 06e52a0c5decf717e35c605d6bcb46c3c7b29656..2994eee1d381af2c9ff3649dd48a2ae14c38c9d7 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -77,9 +77,16 @@ public class ArmorStand extends LivingEntity { + public Rotations leftLegPose; + public Rotations rightLegPose; + public boolean canMove = true; // Paper ++ // Paper start - Allow ArmorStands not to tick ++ public boolean canTick = true; ++ public boolean canTickSetByAPI = false; ++ private boolean noTickPoseDirty = false; ++ private boolean noTickEquipmentDirty = false; ++ // Paper end + + public ArmorStand(EntityType type, Level world) { + super(type, world); ++ if (world != null) this.canTick = world.paperConfig.armorStandTick; // Paper - armour stand ticking + this.handItems = NonNullList.a(2, ItemStack.EMPTY); + this.armorItems = NonNullList.a(4, ItemStack.EMPTY); + this.headPose = ArmorStand.DEFAULT_HEAD_POSE; +@@ -175,6 +182,7 @@ public class ArmorStand extends LivingEntity { + this.armorItems.set(enumitemslot.getIndex(), itemstack); + } + ++ this.noTickEquipmentDirty = true; // Paper - Allow equipment to be updated even when tick disabled + } + + @Override +@@ -255,6 +263,7 @@ public class ArmorStand extends LivingEntity { + } + + tag.put("Pose", this.writePose()); ++ if (this.canTickSetByAPI) tag.putBoolean("Paper.CanTickOverride", this.canTick); // Paper - persist no tick setting + } + + @Override +@@ -286,6 +295,12 @@ public class ArmorStand extends LivingEntity { + this.setNoBasePlate(tag.getBoolean("NoBasePlate")); + this.setMarker(tag.getBoolean("Marker")); + this.noPhysics = !this.hasPhysics(); ++ // Paper start - persist no tick ++ if (tag.contains("Paper.CanTickOverride")) { ++ this.canTick = tag.getBoolean("Paper.CanTickOverride"); ++ this.canTickSetByAPI = true; ++ } ++ // Paper end + CompoundTag nbttagcompound1 = tag.getCompound("Pose"); + + this.readPose(nbttagcompound1); +@@ -641,7 +656,29 @@ public class ArmorStand extends LivingEntity { + + @Override + public void tick() { ++ // Paper start ++ if (!this.canTick) { ++ if (this.noTickPoseDirty) { ++ this.noTickPoseDirty = false; ++ this.updatePose(); ++ } ++ ++ if (this.noTickEquipmentDirty) { ++ this.noTickEquipmentDirty = false; ++ this.detectEquipmentUpdates(); ++ } ++ ++ return; ++ } ++ // Paper end ++ + super.tick(); ++ // Paper start - Split into separate method ++ updatePose(); ++ } ++ ++ public void updatePose() { ++ // Paper end + Rotations vector3f = (Rotations) this.entityData.get(ArmorStand.DATA_HEAD_POSE); + + if (!this.headPose.equals(vector3f)) { +@@ -764,29 +801,36 @@ public class ArmorStand extends LivingEntity { + public void setHeadPose(Rotations vector3f) { + this.headPose = vector3f; + this.entityData.set(ArmorStand.DATA_HEAD_POSE, vector3f); ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + } + + public void setBodyPose(Rotations vector3f) { + this.bodyPose = vector3f; + this.entityData.set(ArmorStand.DATA_BODY_POSE, vector3f); ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + } + + public void setLeftArmPose(Rotations vector3f) { + this.leftArmPose = vector3f; + this.entityData.set(ArmorStand.DATA_LEFT_ARM_POSE, vector3f); ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + } + + public void setRightArmPose(Rotations vector3f) { + this.rightArmPose = vector3f; + this.entityData.set(ArmorStand.DATA_RIGHT_ARM_POSE, vector3f); ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + } + + public void setLeftLegPose(Rotations vector3f) { ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + this.leftLegPose = vector3f; + this.entityData.set(ArmorStand.DATA_LEFT_LEG_POSE, vector3f); ++ + } + + public void setRightLegPose(Rotations vector3f) { ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + this.rightLegPose = vector3f; + this.entityData.set(ArmorStand.DATA_RIGHT_LEG_POSE, vector3f); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +index d4da5214a39b718671dcaf687cb0ff8668ce9728..8363b1b2267da30cda2fb8ea4e844598e20e1422 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +@@ -311,5 +311,16 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { + return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); + } ++ ++ @Override ++ public boolean canTick() { ++ return this.getHandle().canTick; ++ } ++ ++ @Override ++ public void setCanTick(final boolean tick) { ++ this.getHandle().canTick = tick; ++ this.getHandle().canTickSetByAPI = true; ++ } + // Paper end + } diff --git a/patches/server-remapped/0267-Optimize-BlockPosition-helper-methods.patch b/patches/server-remapped/0267-Optimize-BlockPosition-helper-methods.patch new file mode 100644 index 0000000000..fa154eb153 --- /dev/null +++ b/patches/server-remapped/0267-Optimize-BlockPosition-helper-methods.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Aug 2018 12:05:12 -0700 +Subject: [PATCH] Optimize BlockPosition helper methods + +Resolves #1338 + +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index c5089b0da33a68e7cadbc4841b07f9d772d224a0..b13e5d05d862ea8c6031b8071f525f00bc48f7e7 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -121,58 +121,75 @@ public class BlockPos extends Vec3i { + + @Override + public BlockPos above() { +- return this.relative(Direction.UP); ++ return new BlockPos(this.getX(), this.getY() + 1, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos above(int distance) { +- return this.relative(Direction.UP, distance); ++ return distance == 0 ? this : new BlockPos(this.getX(), this.getY() + distance, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos below() { +- return this.relative(Direction.DOWN); ++ return new BlockPos(this.getX(), this.getY() - 1, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos below(int distance) { +- return this.relative(Direction.DOWN, distance); ++ return distance == 0 ? this : new BlockPos(this.getX(), this.getY() - distance, this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPos north() { +- return this.relative(Direction.NORTH); ++ return new BlockPos(this.getX(), this.getY(), this.getZ() - 1); // Paper - Optimize BlockPosition + } + + public BlockPos north(int distance) { +- return this.relative(Direction.NORTH, distance); ++ return distance == 0 ? this : new BlockPos(this.getX(), this.getY(), this.getZ() - distance); // Paper - Optimize BlockPosition + } + + public BlockPos south() { +- return this.relative(Direction.SOUTH); ++ return new BlockPos(this.getX(), this.getY(), this.getZ() + 1); // Paper - Optimize BlockPosition + } + + public BlockPos south(int distance) { +- return this.relative(Direction.SOUTH, distance); ++ return distance == 0 ? this : new BlockPos(this.getX(), this.getY(), this.getZ() + distance); // Paper - Optimize BlockPosition + } + + public BlockPos west() { +- return this.relative(Direction.WEST); ++ return new BlockPos(this.getX() - 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPos west(int distance) { +- return this.relative(Direction.WEST, distance); ++ return distance == 0 ? this : new BlockPos(this.getX() - distance, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPos east() { +- return this.relative(Direction.EAST); ++ return new BlockPos(this.getX() + 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPos east(int distance) { +- return this.relative(Direction.EAST, distance); ++ return distance == 0 ? this : new BlockPos(this.getX() + distance, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPos relative(Direction direction) { +- return new BlockPos(this.getX() + direction.getStepX(), this.getY() + direction.getStepY(), this.getZ() + direction.getStepZ()); ++ // Paper Start - Optimize BlockPosition ++ switch(direction) { ++ case UP: ++ return new BlockPos(this.getX(), this.getY() + 1, this.getZ()); ++ case DOWN: ++ return new BlockPos(this.getX(), this.getY() - 1, this.getZ()); ++ case NORTH: ++ return new BlockPos(this.getX(), this.getY(), this.getZ() - 1); ++ case SOUTH: ++ return new BlockPos(this.getX(), this.getY(), this.getZ() + 1); ++ case WEST: ++ return new BlockPos(this.getX() - 1, this.getY(), this.getZ()); ++ case EAST: ++ return new BlockPos(this.getX() + 1, this.getY(), this.getZ()); ++ default: ++ return new BlockPos(this.getX() + direction.getStepX(), this.getY() + direction.getStepY(), this.getZ() + direction.getStepZ()); ++ } ++ // Paper End + } + + @Override diff --git a/patches/server-remapped/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/patches/server-remapped/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch new file mode 100644 index 0000000000..50cfc368af --- /dev/null +++ b/patches/server-remapped/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 18 Aug 2018 12:43:16 -0400 +Subject: [PATCH] Restore vanlla default mob-spawn-range and water animals + limit + + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0efcbab8f8806aeb8dd8bd6384e5a7cee375d100..34ee684901906fc2ef5f0d09680d2686b813e52b 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -165,7 +165,7 @@ public class SpigotWorldConfig + public byte mobSpawnRange; + private void mobSpawnRange() + { +- mobSpawnRange = (byte) getInt( "mob-spawn-range", 6 ); ++ mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla + log( "Mob Spawn Range: " + mobSpawnRange ); + } + +diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml +index 6474a7fb738e1238cc272afc5ff14b645947e688..6d71bd0db752e6f523364ca5351579b6bcb434c8 100644 +--- a/src/main/resources/configurations/bukkit.yml ++++ b/src/main/resources/configurations/bukkit.yml +@@ -26,7 +26,7 @@ settings: + spawn-limits: + monsters: 70 + animals: 10 +- water-animals: 15 ++ water-animals: 5 + water-ambient: 20 + ambient: 15 + chunk-gc: diff --git a/patches/server-remapped/0269-Slime-Pathfinder-Events.patch b/patches/server-remapped/0269-Slime-Pathfinder-Events.patch new file mode 100644 index 0000000000..1156074828 --- /dev/null +++ b/patches/server-remapped/0269-Slime-Pathfinder-Events.patch @@ -0,0 +1,229 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 24 Aug 2018 08:18:42 -0500 +Subject: [PATCH] Slime Pathfinder Events + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java +index fc8f26e988f1e4826dcfdcf071293bb356163e62..120ceb28ee3aee8a09cf67b45ac95d3d6613c133 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java +@@ -24,7 +24,6 @@ import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.Pose; +@@ -43,6 +42,13 @@ import net.minecraft.world.level.WorldGenLevel; + import net.minecraft.world.level.biome.Biomes; + import net.minecraft.world.level.levelgen.WorldgenRandom; + import net.minecraft.world.phys.Vec3; ++// Paper start ++import com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent; ++import com.destroystokyo.paper.event.entity.SlimeSwimEvent; ++import com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent; ++import com.destroystokyo.paper.event.entity.SlimeWanderEvent; ++import org.bukkit.entity.LivingEntity; ++// Paper end + // CraftBukkit start + import java.util.ArrayList; + import java.util.List; +@@ -103,6 +109,7 @@ public class Slime extends Mob implements Enemy { + @Override + public void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); ++ tag.putBoolean("Paper.canWander", this.canWander); // Paper + tag.putInt("Size", this.getSize() - 1); + tag.putBoolean("wasOnGround", this.wasOnGround); + } +@@ -117,6 +124,11 @@ public class Slime extends Mob implements Enemy { + + this.setSize(i + 1, false); + super.readAdditionalSaveData(tag); ++ // Paper start - check exists before loading or this will be loaded as false ++ if (tag.contains("Paper.canWander")) { ++ this.canWander = tag.getBoolean("Paper.canWander"); ++ } ++ // Paper end + this.wasOnGround = tag.getBoolean("wasOnGround"); + } + +@@ -218,7 +230,7 @@ public class Slime extends Mob implements Enemy { + super.remove(); + return; + } +- List slimes = new ArrayList<>(j); ++ List slimes = new ArrayList<>(j); + // CraftBukkit end + + for (int l = 0; l < k; ++l) { +@@ -242,7 +254,7 @@ public class Slime extends Mob implements Enemy { + if (CraftEventFactory.callEntityTransformEvent(this, slimes, EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { + return; + } +- for (LivingEntity living : slimes) { ++ for (net.minecraft.world.entity.LivingEntity living : slimes) { + this.level.addEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason + } + // CraftBukkit end +@@ -255,7 +267,7 @@ public class Slime extends Mob implements Enemy { + public void push(Entity entity) { + super.push(entity); + if (entity instanceof IronGolem && this.isDealsDamage()) { +- this.dealDamage((LivingEntity) entity); ++ this.dealDamage((net.minecraft.world.entity.LivingEntity) entity); + } + + } +@@ -263,18 +275,18 @@ public class Slime extends Mob implements Enemy { + @Override + public void playerTouch(Player player) { + if (this.isDealsDamage()) { +- this.dealDamage((LivingEntity) player); ++ this.dealDamage((net.minecraft.world.entity.LivingEntity) player); + } + + } + +- protected void dealDamage(LivingEntity target) { ++ protected void dealDamage(net.minecraft.world.entity.LivingEntity target) { + if (this.isAlive()) { + int i = this.getSize(); + + if (this.distanceToSqr((Entity) target) < 0.6D * (double) i * 0.6D * (double) i && this.canSee(target) && target.hurt(DamageSource.mobAttack(this), this.getAttackDamage())) { + this.playSound(SoundEvents.SLIME_ATTACK, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); +- this.doEnchantDamageEffects((LivingEntity) this, (Entity) target); ++ this.doEnchantDamageEffects((net.minecraft.world.entity.LivingEntity) this, (Entity) target); + } + } + +@@ -396,7 +408,7 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- return !this.slime.isPassenger(); ++ return !this.slime.isPassenger() && this.slime.canWander && new SlimeWanderEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper + } + + @Override +@@ -417,7 +429,7 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; ++ return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new SlimeSwimEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper + } + + @Override +@@ -443,14 +455,18 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- return this.slime.getTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; ++ return this.slime.getTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander; // Paper - add canWander + } + + @Override + public void tick() { + if (--this.nextRandomizeTime <= 0) { + this.nextRandomizeTime = 40 + this.slime.getRandom().nextInt(60); +- this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); ++ // Paper start ++ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (float) this.slime.getRandom().nextInt(360)); ++ if (!this.slime.canWander || !event.callEvent()) return; ++ this.chosenDegrees = event.getNewYaw(); ++ // Paper end + } + + ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.chosenDegrees, false); +@@ -469,9 +485,17 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- LivingEntity entityliving = this.slime.getTarget(); ++ net.minecraft.world.entity.LivingEntity entityliving = this.slime.getTarget(); + +- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable ? false : this.slime.getMoveControl() instanceof Slime.SlimeMoveControl)); ++ // Paper start ++ if (entityliving == null || !entityliving.isAlive()) { ++ return false; ++ } ++ if (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable) { ++ return false; ++ } ++ return this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); ++ // Paper end + } + + @Override +@@ -482,9 +506,17 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canContinueToUse() { +- LivingEntity entityliving = this.slime.getTarget(); ++ net.minecraft.world.entity.LivingEntity entityliving = this.slime.getTarget(); + +- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable ? false : --this.growTiredTimer > 0)); ++ // Paper start ++ if (entityliving == null || !entityliving.isAlive()) { ++ return false; ++ } ++ if (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable) { ++ return false; ++ } ++ return --this.growTiredTimer > 0 && this.slime.canWander && new SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); ++ // Paper end + } + + @Override +@@ -492,6 +524,13 @@ public class Slime extends Mob implements Enemy { + this.slime.lookAt((Entity) this.slime.getTarget(), 10.0F, 10.0F); + ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.slime.yRot, this.slime.isDealsDamage()); + } ++ ++ // Paper start - clear timer and target when goal resets ++ public void stop() { ++ this.growTiredTimer = 0; ++ this.slime.setTarget(null); ++ } ++ // Paper end + } + + static class SlimeMoveControl extends MoveControl { +@@ -550,4 +589,15 @@ public class Slime extends Mob implements Enemy { + } + } + } ++ ++ // Paper start ++ private boolean canWander = true; ++ public boolean canWander() { ++ return canWander; ++ } ++ ++ public void setWander(boolean canWander) { ++ this.canWander = canWander; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +index 93af0fd9e15954d7d9f28d7dc29ee18055908348..340036135588d06e43cbd229dd3a6613b04bb9ab 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +@@ -34,4 +34,14 @@ public class CraftSlime extends CraftMob implements Slime { + public EntityType getType() { + return EntityType.SLIME; + } ++ ++ // Paper start ++ public boolean canWander() { ++ return getHandle().canWander(); ++ } ++ ++ public void setWander(boolean canWander) { ++ getHandle().setWander(canWander); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0270-Configurable-speed-for-water-flowing-over-lava.patch b/patches/server-remapped/0270-Configurable-speed-for-water-flowing-over-lava.patch new file mode 100644 index 0000000000..c8fef8a86f --- /dev/null +++ b/patches/server-remapped/0270-Configurable-speed-for-water-flowing-over-lava.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 8 Aug 2018 16:33:21 -0600 +Subject: [PATCH] Configurable speed for water flowing over lava + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5ab0e7183e48134b7a0f736462516b1a8a333b04..f280dbff4a09bc611a9ca565c6d697d08801f53b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -390,4 +390,10 @@ public class PaperWorldConfig { + this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); + log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); + } ++ ++ public int waterOverLavaFlowSpeed; ++ private void waterOverLavaFlowSpeed() { ++ waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); ++ log("Water over lava flow speed: " + waterOverLavaFlowSpeed); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java +index f99b90e4b3210747077f2bf3adbcf7b5fb9821ec..97f2d9082e49010fb8780c5fdd8957f71b31e43e 100644 +--- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java +@@ -23,6 +23,7 @@ import net.minecraft.world.level.material.FlowingFluid; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; ++import net.minecraft.world.level.material.Material; + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.level.storage.loot.LootContext; + import net.minecraft.world.phys.shapes.CollisionContext; +@@ -100,11 +101,28 @@ public class LiquidBlock extends Block implements BucketPickup { + @Override + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + if (this.shouldSpreadLiquid(world, pos, state)) { +- world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); ++ world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper + } + + } + ++ // Paper start - Get flow speed. Throttle if its water and flowing adjacent to lava ++ public int getFlowSpeed(Level world, BlockPos blockposition) { ++ if (this.material == Material.WATER) { ++ if ( ++ world.getMaterialIfLoaded(blockposition.north(1)) == Material.LAVA || ++ world.getMaterialIfLoaded(blockposition.south(1)) == Material.LAVA || ++ world.getMaterialIfLoaded(blockposition.west(1)) == Material.LAVA || ++ world.getMaterialIfLoaded(blockposition.east(1)) == Material.LAVA ++ ) { ++ return world.paperConfig.waterOverLavaFlowSpeed; ++ } ++ } ++ return this.fluid.getTickDelay(world); ++ } ++ // Paper end ++ ++ + @Override + public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { + if (state.getFluidState().isSource() || newState.getFluidState().isSource()) { +@@ -117,7 +135,7 @@ public class LiquidBlock extends Block implements BucketPickup { + @Override + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { + if (this.shouldSpreadLiquid(world, pos, state)) { +- world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); ++ world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper + } + + } diff --git a/patches/server-remapped/0271-Optimize-CraftBlockData-Creation.patch b/patches/server-remapped/0271-Optimize-CraftBlockData-Creation.patch new file mode 100644 index 0000000000..b9e1c45f8f --- /dev/null +++ b/patches/server-remapped/0271-Optimize-CraftBlockData-Creation.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: miclebrick +Date: Thu, 23 Aug 2018 11:45:32 -0400 +Subject: [PATCH] Optimize CraftBlockData Creation + +Avoids a hashmap lookup by cacheing a reference to the CraftBlockData +and cloning it when one is needed. + +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index 5d7794c9533bd37193f196bda616adaaace2bbde..57eedaeedaa24bd274fb55c6e4521f1305382645 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -374,6 +374,14 @@ public abstract class BlockBehaviour { + this.hasPostProcess = blockbase_info.hasPostProcess; + this.emissiveRendering = blockbase_info.emissiveRendering; + } ++ // Paper start - impl cached craft block data, lazy load to fix issue with loading at the wrong time ++ private org.bukkit.craftbukkit.block.data.CraftBlockData cachedCraftBlockData; ++ ++ public org.bukkit.craftbukkit.block.data.CraftBlockData createCraftBlockData() { ++ if (cachedCraftBlockData == null) cachedCraftBlockData = org.bukkit.craftbukkit.block.data.CraftBlockData.createData(getBlockData()); ++ return (org.bukkit.craftbukkit.block.data.CraftBlockData) cachedCraftBlockData.clone(); ++ } ++ // Paper end + + public void initCache() { + if (!this.getBlock().hasDynamicShape()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +index 3a90b504ebbe86350f5fee5baa818e40d884d24f..0b6c6dfc380cea87bd88c3eb8a199e072dcbf56c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +@@ -509,7 +509,17 @@ public class CraftBlockData implements BlockData { + return craft; + } + ++ // Paper start - optimize creating BlockData to not need a map lookup ++ static { ++ // Initialize cached data for all IBlockData instances after registration ++ Block.BLOCK_STATE_REGISTRY.iterator().forEachRemaining(BlockState::createCraftBlockData); ++ } + public static CraftBlockData fromData(BlockState data) { ++ return data.createCraftBlockData(); ++ } ++ ++ public static CraftBlockData createData(BlockState data) { ++ // Paper end + return MAP.getOrDefault(data.getBlock().getClass(), CraftBlockData::new).apply(data); + } + diff --git a/patches/server-remapped/0272-Optimize-RegistryMaterials.patch b/patches/server-remapped/0272-Optimize-RegistryMaterials.patch new file mode 100644 index 0000000000..9ee9585d10 --- /dev/null +++ b/patches/server-remapped/0272-Optimize-RegistryMaterials.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 26 Aug 2018 20:49:50 -0400 +Subject: [PATCH] Optimize RegistryMaterials + +Use larger initial sizes to increase bucket capacity on the BiMap + +BiMap.get was seen to be using a good bit of CPU time. + +diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java +index 928d4b980a1f703915454ffb304dc329fa4223df..da3733db4a5817673703f6c0cf37b5ee3bf91a99 100644 +--- a/src/main/java/net/minecraft/core/MappedRegistry.java ++++ b/src/main/java/net/minecraft/core/MappedRegistry.java +@@ -30,6 +30,7 @@ import net.minecraft.Util; + import net.minecraft.resources.RegistryDataPackCodec; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; ++import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; // Paper + import org.apache.commons.lang3.Validate; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -38,7 +39,7 @@ public class MappedRegistry extends WritableRegistry { + + protected static final Logger LOGGER = LogManager.getLogger(); + private final ObjectList byId = new ObjectArrayList(256); +- private final Object2IntMap toId = new Object2IntOpenCustomHashMap(Util.identityStrategy()); ++ private final Reference2IntOpenHashMap bg = new Reference2IntOpenHashMap(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map + private final BiMap storage; + private final BiMap, T> keyStorage; + private final Map lifecycles; +@@ -48,10 +49,10 @@ public class MappedRegistry extends WritableRegistry { + + public MappedRegistry(ResourceKey> key, Lifecycle lifecycle) { + super(key, lifecycle); +- this.toId.defaultReturnValue(-1); +- this.storage = HashBiMap.create(); +- this.keyStorage = HashBiMap.create(); +- this.lifecycles = Maps.newIdentityHashMap(); ++ this.bg.defaultReturnValue(-1); ++ this.storage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions ++ this.keyStorage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions ++ this.lifecycles = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions + this.elementsLifecycle = lifecycle; + } + +@@ -77,7 +78,7 @@ public class MappedRegistry extends WritableRegistry { + Validate.notNull(entry); + this.byId.size(Math.max(this.byId.size(), rawId + 1)); + this.byId.set(rawId, entry); +- this.toId.put(entry, rawId); ++ this.bg.put(entry, rawId); + this.randomCache = null; + if (checkDuplicateKeys && this.keyStorage.containsKey(key)) { + MappedRegistry.LOGGER.debug("Adding duplicate key '{}' to registry", key); +@@ -113,12 +114,12 @@ public class MappedRegistry extends WritableRegistry { + if (t0 == null) { + i = rawId.isPresent() ? rawId.getAsInt() : this.nextId; + } else { +- i = this.toId.getInt(t0); ++ i = this.bg.getInt(t0); + if (rawId.isPresent() && rawId.getAsInt() != i) { + throw new IllegalStateException("ID mismatch"); + } + +- this.toId.removeInt(t0); ++ this.bg.removeInt(t0); + this.lifecycles.remove(t0); + } + +@@ -138,7 +139,7 @@ public class MappedRegistry extends WritableRegistry { + + @Override + public int getId(@Nullable T entry) { +- return this.toId.getInt(entry); ++ return this.bg.getInt(entry); + } + + @Nullable +@@ -195,7 +196,7 @@ public class MappedRegistry extends WritableRegistry { + this.randomCache = collection.toArray(new Object[collection.size()]); + } + +- return Util.getRandom(this.randomCache, random); ++ return (T) Util.getRandom(this.randomCache, random); // Paper - Decompile fix + } + + public static Codec> networkCodec(ResourceKey> resourcekey, Lifecycle lifecycle, Codec entryCodec) { +@@ -215,7 +216,7 @@ public class MappedRegistry extends WritableRegistry { + Iterator iterator = registrymaterials.iterator(); + + while (iterator.hasNext()) { +- T t0 = iterator.next(); ++ T t0 = (T) iterator.next(); // Paper - Decompile fix + + builder.add(new MappedRegistry.RegistryEntry<>((ResourceKey) registrymaterials.getResourceKey(t0).get(), registrymaterials.getId(t0), t0)); + } diff --git a/patches/server-remapped/0273-Add-PhantomPreSpawnEvent.patch b/patches/server-remapped/0273-Add-PhantomPreSpawnEvent.patch new file mode 100644 index 0000000000..a3b507be83 --- /dev/null +++ b/patches/server-remapped/0273-Add-PhantomPreSpawnEvent.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 25 Aug 2018 19:56:51 -0500 +Subject: [PATCH] Add PhantomPreSpawnEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index 4a2fecdfbda34d6360d50e2ac017907a62b4a043..e37137a2890330b92e05d6f76c46ffc99a527803 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -161,6 +161,11 @@ public class Phantom extends FlyingMob implements Enemy { + } + + this.setPhantomSize(tag.getInt("Size")); ++ // Paper start ++ if (tag.hasUUID("Paper.SpawningEntity")) { ++ this.spawningEntity = tag.getUUID("Paper.SpawningEntity"); ++ } ++ // Paper end + } + + @Override +@@ -170,6 +175,11 @@ public class Phantom extends FlyingMob implements Enemy { + tag.putInt("AY", this.anchorPoint.getY()); + tag.putInt("AZ", this.anchorPoint.getZ()); + tag.putInt("Size", this.getPhantomSize()); ++ // Paper start ++ if (this.spawningEntity != null) { ++ tag.setUUID("Paper.SpawningEntity", this.spawningEntity); ++ } ++ // Paper end + } + + @Override +@@ -216,6 +226,15 @@ public class Phantom extends FlyingMob implements Enemy { + return entitysize.scale(f); + } + ++ // Paper start ++ java.util.UUID spawningEntity; ++ ++ public java.util.UUID getSpawningEntity() { ++ return spawningEntity; ++ } ++ public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } ++ // Paper end ++ + class PhantomAttackPlayerTargetGoal extends Goal { + + private final TargetingConditions attackTargeting; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +index ee18e2826f6390ef5a29557b733fd00db5bc409f..42effcbd3ca7c38a4e8b1aa835543ad243112a33 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +@@ -4,6 +4,7 @@ import java.util.Iterator; + import java.util.Random; + import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.stats.ServerStatsCounter; +@@ -73,8 +74,17 @@ public class PhantomSpawner implements CustomSpawner { + int k = 1 + random.nextInt(difficultydamagescaler.getDifficulty().getId() + 1); + + for (int l = 0; l < k; ++l) { ++ // Paper start ++ com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(MCUtil.toLocation(world, blockposition1), ((ServerPlayer) entityhuman).getBukkitEntity(), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ break; ++ } ++ continue; ++ } ++ // Paper end + Phantom entityphantom = (Phantom) EntityType.PHANTOM.create((Level) world); +- ++ entityphantom.setSpawningEntity(entityhuman.getUUID()); // Paper + entityphantom.moveTo(blockposition1, 0.0F, 0.0F); + groupdataentity = entityphantom.finalizeSpawn(world, difficultydamagescaler, MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); + world.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +index 15eb09595dad996314c169f9dd7d381e43f77be9..92162fa22f5e98b7837bde5830bd47c31b8b52d8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +@@ -34,4 +34,10 @@ public class CraftPhantom extends CraftFlying implements Phantom { + public EntityType getType() { + return EntityType.PHANTOM; + } ++ ++ // Paper start ++ public java.util.UUID getSpawningEntity() { ++ return getHandle().getSpawningEntity(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0274-Add-More-Creeper-API.patch b/patches/server-remapped/0274-Add-More-Creeper-API.patch new file mode 100644 index 0000000000..3a4091fe8d --- /dev/null +++ b/patches/server-remapped/0274-Add-More-Creeper-API.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 24 Aug 2018 11:50:26 -0500 +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 d9b5cf8ac01289801ded01d928fa7ead96551be5..336736fae0b49a05e48c1c70a225da316bb73e66 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +@@ -289,7 +289,18 @@ public class Creeper extends Monster { + } + + public void ignite() { +- this.entityData.set(Creeper.DATA_IS_IGNITED, true); ++ // Paper start ++ setIgnited(true); ++ } ++ ++ public void setIgnited(boolean ignited) { ++ if (isIgnited() != ignited) { ++ com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited); ++ if (event.callEvent()) { ++ this.entityData.set(Creeper.DATA_IS_IGNITED, event.isIgnited()); ++ } ++ } ++ // Paper end + } + + 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 ded0b7c1619aada95492e7ec25c0e0f3d008d0ad..9f68beb8c79ed1c429ee9f9efab8b8604258293b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java +@@ -100,4 +100,14 @@ public class CraftCreeper extends CraftMonster implements Creeper { + public EntityType getType() { + return EntityType.CREEPER; + } ++ ++ // Paper start ++ public void setIgnited(boolean ignited) { ++ getHandle().setIgnited(ignited); ++ } ++ ++ public boolean isIgnited() { ++ return getHandle().isIgnited(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0275-Inventory-removeItemAnySlot.patch b/patches/server-remapped/0275-Inventory-removeItemAnySlot.patch new file mode 100644 index 0000000000..b542a82e8a --- /dev/null +++ b/patches/server-remapped/0275-Inventory-removeItemAnySlot.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 28 Aug 2018 23:04:15 -0400 +Subject: [PATCH] Inventory#removeItemAnySlot + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +index 9d70ef8c3967596491a804e4d66f2ec1b13992c9..ef2d18d19a86b3701855aa1ac126462e663f8fcd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +@@ -222,10 +222,16 @@ public class CraftInventory implements Inventory { + } + + private int first(ItemStack item, boolean withAmount) { ++ // Paper start ++ return first(item, withAmount, getStorageContents()); ++ } ++ ++ private int first(ItemStack item, boolean withAmount, ItemStack[] inventory) { ++ // Paper end + if (item == null) { + return -1; + } +- ItemStack[] inventory = getStorageContents(); ++ //ItemStack[] inventory = getStorageContents(); // Paper - let param deal + for (int i = 0; i < inventory.length; i++) { + if (inventory[i] == null) continue; + +@@ -348,6 +354,17 @@ public class CraftInventory implements Inventory { + + @Override + public HashMap removeItem(ItemStack... items) { ++ // Paper start ++ return removeItem(false, items); ++ } ++ ++ @Override ++ public HashMap removeItemAnySlot(ItemStack... items) { ++ return removeItem(true, items); ++ } ++ ++ private HashMap removeItem(boolean searchEntire, ItemStack... items) { ++ // Paper end + Validate.notNull(items, "Items cannot be null"); + HashMap leftover = new HashMap(); + +@@ -358,7 +375,10 @@ public class CraftInventory implements Inventory { + int toDelete = item.getAmount(); + + while (true) { +- int first = first(item, false); ++ // Paper start - Allow searching entire contents ++ ItemStack[] toSearch = searchEntire ? getContents() : getStorageContents(); ++ int first = first(item, false, toSearch); ++ // Paper end + + // Drat! we don't have this type in the inventory + if (first == -1) { diff --git a/patches/server-remapped/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/patches/server-remapped/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch new file mode 100644 index 0000000000..3b436ea5af --- /dev/null +++ b/patches/server-remapped/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 2 Sep 2018 19:34:33 -0700 +Subject: [PATCH] Make CraftWorld#loadChunk(int, int, false) load unconverted + chunks + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 159c32d6678e83f2d98ea6a1ad48346c9de017e1..57a2af56b53567371fdb6d0a55866e1e4e37cf3b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -490,7 +490,7 @@ public class CraftWorld implements World { + @Override + public boolean loadChunk(int x, int z, boolean generate) { + org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot +- ChunkAccess chunk = world.getChunkSource().getChunk(x, z, generate ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); ++ ChunkAccess chunk = world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper + + // If generate = false, but the chunk already exists, we will get this back. + if (chunk instanceof ImposterProtoChunk) { diff --git a/patches/server-remapped/0277-Add-ray-tracing-methods-to-LivingEntity.patch b/patches/server-remapped/0277-Add-ray-tracing-methods-to-LivingEntity.patch new file mode 100644 index 0000000000..f1edc62517 --- /dev/null +++ b/patches/server-remapped/0277-Add-ray-tracing-methods-to-LivingEntity.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 3 Sep 2018 18:20:03 -0500 +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 205c639d26652befebae925fc6e40976c370710f..2e25cb2a04d150d3154bf0d7f0eccb97e65ff53e 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3605,6 +3605,23 @@ public abstract class LivingEntity extends Entity { + this.broadcastBreakEvent(hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); + } + // Paper start ++ public HitResult getRayTrace(int maxDistance) { ++ return getRayTrace(maxDistance, ClipContext.Fluid.NONE); ++ } ++ ++ public HitResult getRayTrace(int maxDistance, ClipContext.Fluid fluidCollisionOption) { ++ if (maxDistance < 1 || maxDistance > 120) { ++ throw new IllegalArgumentException("maxDistance must be between 1-120"); ++ } ++ ++ Vec3 start = new Vec3(getX(), getY() + getEyeHeight(), getZ()); ++ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance); ++ Vec3 end = new Vec3(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ()); ++ ClipContext raytrace = new ClipContext(start, end, ClipContext.Block.OUTLINE, fluidCollisionOption, this); ++ ++ return level.clip(raytrace); ++ } ++ + public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; + + public int getShieldBlockingDelay() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 6dd7a722e10a2727f68318b880f2726bb816f198..7e3a215f1592bed9f35e22076d9e35a5a49a430e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import com.destroystokyo.paper.block.TargetBlockInfo; + import com.google.common.base.Preconditions; + import com.google.common.collect.Sets; + import java.util.ArrayList; +@@ -8,6 +9,7 @@ import java.util.Iterator; + import java.util.List; + import java.util.Set; + import java.util.UUID; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.InteractionHand; + import net.minecraft.world.damagesource.DamageSource; +@@ -28,6 +30,8 @@ import net.minecraft.world.entity.projectile.ThrownEgg; + import net.minecraft.world.entity.projectile.ThrownEnderpearl; + import net.minecraft.world.entity.projectile.ThrownExperienceBottle; + import net.minecraft.world.entity.projectile.ThrownTrident; ++import net.minecraft.world.phys.BlockHitResult; ++import net.minecraft.world.phys.HitResult; + import org.apache.commons.lang.Validate; + import org.bukkit.FluidCollisionMode; + import org.bukkit.Location; +@@ -37,6 +41,7 @@ import org.bukkit.attribute.AttributeInstance; + import org.bukkit.block.Block; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.entity.memory.CraftMemoryKey; + import org.bukkit.craftbukkit.entity.memory.CraftMemoryMapper; + import org.bukkit.craftbukkit.inventory.CraftEntityEquipment; +@@ -190,6 +195,28 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return blocks.get(0); + } + ++ // Paper start ++ @Override ++ public Block getTargetBlock(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { ++ HitResult rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof BlockHitResult) ? null : CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()); ++ } ++ ++ @Override ++ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { ++ HitResult rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof BlockHitResult) ? null : MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection()); ++ } ++ ++ @Override ++ public TargetBlockInfo getTargetBlockInfo(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { ++ HitResult rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof BlockHitResult) ? null : ++ new TargetBlockInfo(CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()), ++ MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection())); ++ } ++ // Paper end ++ + @Override + public List getLastTwoTargetBlocks(Set transparent, int maxDistance) { + return getLineOfSight(transparent, maxDistance, 2); diff --git a/patches/server-remapped/0278-Expose-attack-cooldown-methods-for-Player.patch b/patches/server-remapped/0278-Expose-attack-cooldown-methods-for-Player.patch new file mode 100644 index 0000000000..bfe6717c67 --- /dev/null +++ b/patches/server-remapped/0278-Expose-attack-cooldown-methods-for-Player.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 4 Sep 2018 15:02:00 -0500 +Subject: [PATCH] Expose attack cooldown methods for Player + + +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 709e930eef7bae5694238ed8c4d0ef59316bb715..14d5acff198338c68162e33d4a90f74be77cb15f 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -2100,6 +2100,7 @@ public abstract class Player extends LivingEntity { + this.entityData.set(Player.DATA_SHOULDER_RIGHT, entityTag); + } + ++ public float getCooldownPeriod() { return this.getCurrentItemAttackStrengthDelay(); } // Paper - OBFHELPER + public float getCurrentItemAttackStrengthDelay() { + return (float) (1.0D / this.getAttributeValue(Attributes.ATTACK_SPEED) * 20.0D); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index c7f66dddf0a0850ca4048dd47cd2ded114caa07e..ee823c4ed5b9fcfaa900b470c582435f0b909ebc 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2186,6 +2186,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND)); + connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, inventory.getSelected())); + } ++ ++ public float getCooldownPeriod() { ++ return getHandle().getCooldownPeriod(); ++ } ++ ++ public float getCooledAttackStrength(float adjustTicks) { ++ return getHandle().getAttackStrengthScale(adjustTicks); ++ } ++ ++ public void resetCooldown() { ++ getHandle().resetAttackStrengthTicker(); ++ } + // Paper end + + // Spigot start diff --git a/patches/server-remapped/0279-Improve-death-events.patch b/patches/server-remapped/0279-Improve-death-events.patch new file mode 100644 index 0000000000..15db46e30d --- /dev/null +++ b/patches/server-remapped/0279-Improve-death-events.patch @@ -0,0 +1,458 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Tue, 21 Aug 2018 01:39:35 +0100 +Subject: [PATCH] Improve death events + +This adds the ability to cancel the death events and to modify the sound +an entity makes when dying. (In cases were no sound should it will be +called with shouldPlaySound set to false allowing unsilencing of silent +entities) + +It makes handling of entity deaths a lot nicer as you no longer need +to listen on the damage event and calculate if the entity dies yourself +to cancel the death which has the benefit of also receiving the dropped +items and experience which is otherwise only properly possible by using +internal code. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 5664e292046d4fcdb81340df8cee8d04aa27ca55..75419c866641ab654349cde6ca3fbdef701dd8d9 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -211,6 +211,10 @@ public class ServerPlayer extends Player implements ContainerListener { + public int latency; + public boolean wonGame; + private int containerUpdateDelay; // Paper ++ // Paper start - cancellable death event ++ public boolean queueHealthUpdatePacket = false; ++ public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; ++ // Paper end + + // CraftBukkit start + public String displayName; +@@ -714,6 +718,15 @@ public class ServerPlayer extends Player implements ContainerListener { + Component defaultMessage = this.getCombatTracker().getDeathMessage(); + + org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure ++ // Paper start - cancellable death event ++ if (event.isCancelled()) { ++ // make compatible with plugins that might have already set the health in an event listener ++ if (this.getHealth() <= 0) { ++ this.setHealth((float) event.getReviveHealth()); ++ } ++ return; ++ } ++ // Paper end + + // SPIGOT-943 - only call if they have an inventory open + if (this.containerMenu != this.inventoryMenu) { +@@ -860,8 +873,17 @@ public class ServerPlayer extends Player implements ContainerListener { + } + } + } +- +- return super.hurt(source, amount); ++ // Paper start - cancellable death events ++ //return super.damageEntity(damagesource, f); ++ this.queueHealthUpdatePacket = true; ++ boolean damaged = super.hurt(source, amount); ++ this.queueHealthUpdatePacket = false; ++ if (this.queuedHealthUpdatePacket != null) { ++ this.connection.send(this.queuedHealthUpdatePacket); ++ this.queuedHealthUpdatePacket = null; ++ } ++ return damaged; ++ // Paper end + } + } + } +diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java +index 8a0863a695bb33698fb3fe6e06599f6f6f47011f..36e665009418d5177016a744eb920fbf99f534fc 100644 +--- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java ++++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java +@@ -203,6 +203,7 @@ public class CombatTracker { + this.nextLocation = null; + } + ++ public final void reset() { this.recheckStatus(); } // Paper - OBFHELPER + public void recheckStatus() { + int i = this.inCombat ? 300 : 100; + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 4503bd65b3454bad94bb7b869f4e72e3121d8a3d..e7fed1f8bb8ffb164ddcdab51f41c369d6e3103d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1537,6 +1537,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + // CraftBukkit end + ++ public final void runKillTrigger(Entity entity, int kills, DamageSource damageSource) { this.awardKillScore(entity, kills, damageSource); } // Paper - OBFHELPER + public void awardKillScore(Entity killer, int score, DamageSource damageSource) { + if (killer instanceof ServerPlayer) { + CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer) killer, this, damageSource); +@@ -2441,6 +2442,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.fallDistance = 0.0F; + } + ++ public final void onKill(ServerLevel worldserver, net.minecraft.world.entity.LivingEntity entityLiving) { this.killed(worldserver, entityLiving); } // Paper - OBFHELPER + public void killed(ServerLevel worldserver, net.minecraft.world.entity.LivingEntity entityliving) {} + + protected void moveTowardsClosestSpace(double x, double y, double z) { +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 2e25cb2a04d150d3154bf0d7f0eccb97e65ff53e..7a2292e6907a2ae2026bd7243e864bd8300ecafa 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -186,7 +186,7 @@ public abstract class LivingEntity extends Entity { + protected float animStep; + protected float animStepO; + protected float rotOffs; +- protected int deathScore; ++ protected int deathScore;protected int getKillCount() { return this.deathScore; } // Paper - OBFHELPER + public float lastHurt; + protected boolean jumping; + public float xxa; +@@ -230,6 +230,7 @@ public abstract class LivingEntity extends Entity { + public Set collidableExemptions = new HashSet<>(); + public boolean canPickUpLoot; + public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper ++ public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event + + @Override + public float getBukkitYaw() { +@@ -1345,13 +1346,17 @@ public abstract class LivingEntity extends Entity { + if (knockbackCancelled) this.level.broadcastEntityEvent(this, (byte) 2); // Paper - Disable explosion knockback + if (this.isDeadOrDying()) { + if (!this.checkTotemDeathProtection(source)) { +- SoundEvent soundeffect = this.getDeathSound(); ++ // Paper start - moved into CraftEventFactory event caller for cancellable death event ++ //SoundEffect soundeffect = this.getSoundDeath(); + +- if (flag1 && soundeffect != null) { +- this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); +- } ++// if (flag1 && soundeffect != null) { ++// this.playSound(soundeffect, this.getSoundVolume(), this.dH()); ++// } ++ this.silentDeath = !flag1; // mark entity as dying silently ++ // Paper end + + this.die(source); ++ this.silentDeath = false; // Paper - cancellable death event - reset to default + } + } else if (flag1) { + this.playHurtSound(source); +@@ -1490,27 +1495,48 @@ public abstract class LivingEntity extends Entity { + Entity entity = source.getEntity(); + LivingEntity entityliving = this.getKillCredit(); + +- if (this.deathScore >= 0 && entityliving != null) { +- entityliving.awardKillScore(this, this.deathScore, source); ++ /* // Paper - move down to make death event cancellable - this is the runKillTrigger below ++ if (this.aO >= 0 && entityliving != null) { ++ entityliving.a(this, this.aO, damagesource); + } + + if (this.isSleeping()) { +- this.stopSleeping(); ++ this.entityWakeup(); + } ++ */ // Paper + + this.dead = true; +- this.getCombatTracker().recheckStatus(); ++ // this.getCombatTracker().g(); // Paper - moved into if below as .reset() + if (this.level instanceof ServerLevel) { + if (entity != null) { +- entity.killed((ServerLevel) this.level, this); ++ // entity.a((WorldServer) this.world, this); // Paper - move below into if for onKill + } + +- this.dropAllDeathLoot(source); ++ // Paper start ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.d(source); ++ if (deathEvent == null || !deathEvent.isCancelled()) { ++ if (this.getKillCount() >= 0 && entityliving != null) { ++ entityliving.runKillTrigger(this, this.getKillCount(), source); ++ } ++ if (this.isSleeping()) { ++ this.stopSleeping(); ++ } ++ this.getCombatTracker().reset(); ++ if (entity != null) { ++ entity.onKill((ServerLevel) this.level, this); ++ } ++ } else { ++ this.dead = false; ++ this.setHealth((float) deathEvent.getReviveHealth()); ++ } ++ // Paper end + this.createWitherRose(entityliving); + } + ++ if (this.dead) { // Paper + this.level.broadcastEntityEvent(this, (byte) 3); + this.setPose(Pose.DYING); ++ } // Paper + } + } + +@@ -1518,7 +1544,7 @@ public abstract class LivingEntity extends Entity { + if (!this.level.isClientSide) { + boolean flag = false; + +- if (adversary instanceof WitherBoss) { ++ if (this.dead && adversary instanceof WitherBoss) { // Paper + if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + BlockPos blockposition = this.blockPosition(); + BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState(); +@@ -1546,8 +1572,9 @@ public abstract class LivingEntity extends Entity { + } + } + +- protected void dropAllDeathLoot(DamageSource source) { +- Entity entity = source.getEntity(); ++ protected org.bukkit.event.entity.EntityDeathEvent processDeath(DamageSource damagesource) { return d(damagesource); } // Paper - OBFHELPER ++ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper ++ Entity entity = damagesource.getEntity(); + int i; + + if (entity instanceof net.minecraft.world.entity.player.Player) { +@@ -1560,19 +1587,22 @@ public abstract class LivingEntity extends Entity { + + this.dropEquipment(); // CraftBukkit - from below + if (this.shouldDropLoot() && this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.dropFromLootTable(source, flag); +- this.dropCustomDeathLoot(source, i, flag); ++ this.dropFromLootTable(damagesource, flag); ++ this.dropCustomDeathLoot(damagesource, i, flag); + } + // CraftBukkit start - Call death event +- CraftEventFactory.callEntityDeathEvent(this, this.drops); ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper ++ this.postDeathDropItems(deathEvent); // Paper + this.drops = new ArrayList<>(); + // CraftBukkit end + + // this.dropInventory();// CraftBukkit - moved up + this.dropExperience(); ++ return deathEvent; // Paper + } + + protected void dropEquipment() {} ++ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled + + // CraftBukkit start + public int getExpReward() { +@@ -1657,6 +1687,7 @@ public abstract class LivingEntity extends Entity { + return SoundEvents.GENERIC_HURT; + } + ++ public final SoundEvent getDeathSoundEffect() { return this.getDeathSound(); } // Paper - OBFHELPER + @Nullable + protected SoundEvent getDeathSound() { + return SoundEvents.GENERIC_DEATH; +@@ -2193,10 +2224,12 @@ public abstract class LivingEntity extends Entity { + + } + ++ public final float getDeathSoundVolume() { return this.getSoundVolume(); } // Paper - OBFHELPER + protected float getSoundVolume() { + return 1.0F; + } + ++ public float getSoundPitch() { return getVoicePitch();} // Paper - OBFHELPER + protected float getVoicePitch() { + return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.5F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java +index c2d98222f575d7383e4c040730f6d531bdb0d7b6..46792914f574800c893eb197fa7b3b87ce7e500b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java +@@ -647,15 +647,25 @@ public class Fox extends Animal { + } + + @Override +- protected void dropAllDeathLoot(DamageSource source) { +- ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND); ++ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND).copy(); // Paper ++ ++ // Paper start - Cancellable death event ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.d(damagesource); ++ ++ // Below is code to drop ++ ++ if (deathEvent == null || deathEvent.isCancelled()) { ++ return deathEvent; ++ } ++ // Paper end + + if (!itemstack.isEmpty()) { + this.spawnAtLocation(itemstack); + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + } + +- super.dropAllDeathLoot(source); ++ return deathEvent; // Paper + } + + public static boolean isPathClear(Fox fox, LivingEntity chasedEntity) { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java +index 34a9843267ef739e5889791fb4899fabe1f864bc..63723044ae6c607e6d36bc0b0c6b525037df34b2 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java +@@ -68,11 +68,19 @@ public abstract class AbstractChestedHorse extends AbstractHorse { + this.spawnAtLocation((ItemLike) Blocks.CHEST); + } + +- this.setChest(false); ++ //this.setCarryingChest(false); // Paper - moved to post death logic + } + + } + ++ // Paper start ++ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) { ++ if (this.hasChest() && (event == null || !event.isCancelled())) { ++ this.setChest(false); ++ } ++ } ++ // Paper end ++ + @Override + public void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 2994eee1d381af2c9ff3649dd48a2ae14c38c9d7..33d51852ed6fe3f5adcdecf8f405a23689f4265a 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -610,7 +610,7 @@ public class ArmorStand extends LivingEntity { + this.armorItems.set(i, ItemStack.EMPTY); + } + } +- this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above ++ this.d(damageSource); // CraftBukkit - moved from above + + } + +@@ -742,7 +742,8 @@ public class ArmorStand extends LivingEntity { + + @Override + public void kill() { +- org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event ++ org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event // Paper - make cancellable ++ if (event.isCancelled()) return; // Paper - make cancellable + this.remove(); + } + +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 14d5acff198338c68162e33d4a90f74be77cb15f..3aadc4ab5fe7b2ee9e20e0789ddcfe750599972f 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -581,7 +581,7 @@ public abstract class Player extends LivingEntity { + super.die(source); + this.reapplyPosition(); + if (!this.isSpectator()) { +- this.dropAllDeathLoot(source); ++ this.d(source); + } + + if (source != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index ee823c4ed5b9fcfaa900b470c582435f0b909ebc..a3e65028d3e0c09a65cd9c28b037fe01a2ed1d76 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1836,7 +1836,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void sendHealthUpdate() { +- getHandle().connection.send(new ClientboundSetHealthPacket(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); ++ // Paper start - cancellable death event ++ //getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); ++ ClientboundSetHealthPacket packet = new ClientboundSetHealthPacket(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel()); ++ if (this.getHandle().queueHealthUpdatePacket) { ++ this.getHandle().queuedHealthUpdatePacket = packet; ++ } else { ++ this.getHandle().connection.send(packet); ++ } ++ // Paper end + } + + 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 1877267344df1ff5b4de6a4e0c239f488cd52c1f..e696d2e52532df25d74a1f559e2c9ca0f3d5058d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -18,6 +18,8 @@ import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundSource; + import net.minecraft.util.Unit; + import net.minecraft.world.Container; + import net.minecraft.world.InteractionHand; +@@ -793,9 +795,16 @@ public class CraftEventFactory { + public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, List drops) { + CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); + EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward()); ++ populateFields(victim, event); // Paper - make cancellable + CraftWorld world = (CraftWorld) entity.getWorld(); + Bukkit.getServer().getPluginManager().callEvent(event); + ++ // Paper start - make cancellable ++ if (event.isCancelled()) { ++ return event; ++ } ++ playDeathSound(victim, event); ++ // Paper end + victim.expToDrop = event.getDroppedExp(); + + for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { +@@ -811,8 +820,15 @@ public class CraftEventFactory { + CraftPlayer entity = victim.getBukkitEntity(); + PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure + event.setKeepInventory(keepInventory); ++ populateFields(victim, event); // Paper - make cancellable + org.bukkit.World world = entity.getWorld(); + Bukkit.getServer().getPluginManager().callEvent(event); ++ // Paper start - make cancellable ++ if (event.isCancelled()) { ++ return event; ++ } ++ playDeathSound(victim, event); ++ // Paper end + + victim.keepLevel = event.getKeepLevel(); + victim.newLevel = event.getNewLevel(); +@@ -829,6 +845,31 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start - helper methods for making death event cancellable ++ // Add information to death event ++ private static void populateFields(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) { ++ event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue()); ++ event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent()); ++ SoundEvent soundEffect = victim.getDeathSoundEffect(); ++ event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null); ++ event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundSource().name())); ++ event.setDeathSoundVolume(victim.getDeathSoundVolume()); ++ event.setDeathSoundPitch(victim.getSoundPitch()); ++ } ++ ++ // Play death sound manually ++ private static void playDeathSound(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) { ++ if (event.shouldPlayDeathSound() && event.getDeathSound() != null && event.getDeathSoundCategory() != null) { ++ net.minecraft.world.entity.player.Player source = victim instanceof net.minecraft.world.entity.player.Player ? (net.minecraft.world.entity.player.Player) victim : null; ++ double x = event.getEntity().getLocation().getX(); ++ double y = event.getEntity().getLocation().getY(); ++ double z = event.getEntity().getLocation().getZ(); ++ SoundEvent soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound()); ++ SoundSource soundCategory = SoundSource.valueOf(event.getDeathSoundCategory().name()); ++ victim.level.playSound(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch()); ++ } ++ } ++ // Paper end + /** + * Server methods + */ diff --git a/patches/server-remapped/0280-Allow-chests-to-be-placed-with-NBT-data.patch b/patches/server-remapped/0280-Allow-chests-to-be-placed-with-NBT-data.patch new file mode 100644 index 0000000000..59c2f88e09 --- /dev/null +++ b/patches/server-remapped/0280-Allow-chests-to-be-placed-with-NBT-data.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 8 Sep 2018 18:43:31 -0500 +Subject: [PATCH] Allow chests to be placed with NBT data + + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 79a7c37f15840dbd97510874ac12437d2b854999..02bfa4fb8055e60a84e878ffbf18303c0ee25b1d 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -296,6 +296,7 @@ public final class ItemStack { + enuminteractionresult = InteractionResult.FAIL; // cancel placement + // PAIL: Remove this when MC-99075 fixed + placeEvent.getPlayer().updateInventory(); ++ world.capturedTileEntities.clear(); // Paper - clear out tile entities as chests and such will pop loot + // revert back all captured blocks + for (BlockState blockstate : blocks) { + blockstate.update(true, false); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java +index 17289d28b6d0023279a573715ee3d182988dd651..ab11c7a5a397047a35245b149d77bf035e718a0c 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java +@@ -326,7 +326,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity { // Pape + // CraftBukkit start + @Override + public boolean onlyOpCanSetNbt() { +- return true; ++ return false; // Paper + } + // CraftBukkit end + } diff --git a/patches/server-remapped/0281-Mob-Pathfinding-API.patch b/patches/server-remapped/0281-Mob-Pathfinding-API.patch new file mode 100644 index 0000000000..8ae73987bc --- /dev/null +++ b/patches/server-remapped/0281-Mob-Pathfinding-API.patch @@ -0,0 +1,290 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 9 Sep 2018 13:30:00 -0400 +Subject: [PATCH] Mob Pathfinding API + +Implements Pathfinding API for mobs + +diff --git a/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3e7971b7ca5be0442378c9e7482775e05918d0ac +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java +@@ -0,0 +1,141 @@ ++package com.destroystokyo.paper.entity; ++ ++import org.apache.commons.lang.Validate; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Mob; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++import net.minecraft.world.level.pathfinder.Node; ++import net.minecraft.world.level.pathfinder.Path; ++import PathResult; ++import java.util.ArrayList; ++import java.util.List; ++ ++public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder { ++ ++ private final net.minecraft.world.entity.Mob entity; ++ ++ public PaperPathfinder(net.minecraft.world.entity.Mob entity) { ++ this.entity = entity; ++ } ++ ++ @Override ++ public Mob getEntity() { ++ return entity.getBukkitMob(); ++ } ++ ++ @Override ++ public void stopPathfinding() { ++ entity.getNavigation().stopPathfinding(); ++ } ++ ++ @Override ++ public boolean hasPath() { ++ return entity.getNavigation().getPathEntity() != null; ++ } ++ ++ @Nullable ++ @Override ++ public PathResult getCurrentPath() { ++ Path path = entity.getNavigation().getPathEntity(); ++ return path != null ? new PaperPathResult(path) : null; ++ } ++ ++ @Nullable ++ @Override ++ public PathResult findPath(Location loc) { ++ Validate.notNull(loc, "Location can not be null"); ++ Path path = entity.getNavigation().calculateDestination(loc.getX(), loc.getY(), loc.getZ()); ++ return path != null ? new PaperPathResult(path) : null; ++ } ++ ++ @Nullable ++ @Override ++ public PathResult findPath(LivingEntity target) { ++ Validate.notNull(target, "Target can not be null"); ++ Path path = entity.getNavigation().calculateDestination(((CraftLivingEntity) target).getHandle()); ++ return path != null ? new PaperPathResult(path) : null; ++ } ++ ++ @Override ++ public boolean moveTo(@Nonnull PathResult path, double speed) { ++ Validate.notNull(path, "PathResult can not be null"); ++ Path pathEntity = ((PaperPathResult) path).path; ++ return entity.getNavigation().setDestination(pathEntity, speed); ++ } ++ ++ @Override ++ public boolean canOpenDoors() { ++ return entity.getNavigation().getPathfinder().getPathfinder().shouldOpenDoors(); ++ } ++ ++ @Override ++ public void setCanOpenDoors(boolean canOpenDoors) { ++ entity.getNavigation().getPathfinder().getPathfinder().setShouldOpenDoors(canOpenDoors); ++ } ++ ++ @Override ++ public boolean canPassDoors() { ++ return entity.getNavigation().getPathfinder().getPathfinder().shouldPassDoors(); ++ } ++ ++ @Override ++ public void setCanPassDoors(boolean canPassDoors) { ++ entity.getNavigation().getPathfinder().getPathfinder().setShouldPassDoors(canPassDoors); ++ } ++ ++ @Override ++ public boolean canFloat() { ++ return entity.getNavigation().getPathfinder().getPathfinder().shouldFloat(); ++ } ++ ++ @Override ++ public void setCanFloat(boolean canFloat) { ++ entity.getNavigation().getPathfinder().getPathfinder().setShouldFloat(canFloat); ++ } ++ ++ public class PaperPathResult implements com.destroystokyo.paper.entity.PaperPathfinder.PathResult { ++ ++ private final Path path; ++ PaperPathResult(Path path) { ++ this.path = path; ++ } ++ ++ @Nullable ++ @Override ++ public Location getFinalPoint() { ++ Node point = path.getFinalPoint(); ++ return point != null ? toLoc(point) : null; ++ } ++ ++ @Override ++ public List getPoints() { ++ List points = new ArrayList<>(); ++ for (Node point : path.getPoints()) { ++ points.add(toLoc(point)); ++ } ++ return points; ++ } ++ ++ @Override ++ public int getNextPointIndex() { ++ return path.getNextIndex(); ++ } ++ ++ @Nullable ++ @Override ++ public Location getNextPoint() { ++ if (!path.hasNext()) { ++ return null; ++ } ++ return toLoc(path.getPoints().get(path.getNextIndex())); ++ } ++ } ++ ++ private Location toLoc(Node point) { ++ return new Location(entity.level.getWorld(), point.getX(), point.getY(), point.getZ()); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index c3082f5dd64413a47421cb01538bec846bf21d2c..a362506f38e8d30543b6cd6d215db561290dac76 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -100,7 +100,7 @@ public abstract class PathNavigation { + } + + @Nullable +- public final Path createPath(double x, double y, double z, int distance) { ++ public final Path calculateDestination(double d0, double d1, double d2) { return createPath(d0, d1, d2, 0); } public final Path createPath(double x, double y, double z, int distance) { // Paper - OBFHELPER + return this.createPath(new BlockPos(x, y, z), distance); + } + +@@ -125,7 +125,7 @@ public abstract class PathNavigation { + } + + @Nullable +- public Path createPath(Entity entity, int distance) { ++ public final Path calculateDestination(Entity entity) { return createPath(entity, 0); } public Path createPath(Entity entity, int distance) { + return this.a(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper + } + +@@ -190,6 +190,7 @@ public abstract class PathNavigation { + return pathentity != null && this.moveTo(pathentity, speed); + } + ++ public boolean setDestination(@Nullable Path pathentity, double speed) { return moveTo(pathentity, speed); } // Paper - OBFHELPER + public boolean moveTo(@Nullable Path path, double speed) { + if (path == null) { + this.path = null; +@@ -217,7 +218,7 @@ public abstract class PathNavigation { + } + } + +- @Nullable ++ @Nullable public Path getPathEntity() { return getPath(); } @Nullable // Paper - OBFHELPER + public Path getPath() { + return this.path; + } +@@ -341,6 +342,7 @@ public abstract class PathNavigation { + return !this.isDone(); + } + ++ public void stopPathfinding() { stop(); } // Paper - OBFHELPER + public void stop() { + this.path = null; + } +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Node.java b/src/main/java/net/minecraft/world/level/pathfinder/Node.java +index c1ac95d784935f5d3d827e2e390162f594991d2c..27b5d3d02d1f3aa048fefc3ef2222c8031e7661f 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/Node.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/Node.java +@@ -5,9 +5,9 @@ import net.minecraft.util.Mth; + + public class Node { + +- public final int x; +- public final int y; +- public final int z; ++ public final int x; public final int getX() { return x; } // Paper - OBFHELPER ++ public final int y; public final int getY() { return y; } // Paper - OBFHELPER ++ public final int z; public final int getZ() { return z; } // Paper - OBFHELPER + private final int hash; + public int heapIdx = -1; + public float g; +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java +index 0941bd177f65abfed3991267448df7df259d7f04..ddc9a9ececf44ce5524fd98a872e8a53cd7cc4f5 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java +@@ -16,9 +16,9 @@ public abstract class NodeEvaluator { + protected int entityWidth; + protected int entityHeight; + protected int entityDepth; +- protected boolean canPassDoors; +- protected boolean canOpenDoors; +- protected boolean canFloat; ++ protected boolean canPassDoors; public boolean shouldPassDoors() { return canPassDoors; } public void setShouldPassDoors(boolean b) { canPassDoors = b; } // Paper - obfhelper ++ protected boolean canOpenDoors; public boolean shouldOpenDoors() { return canOpenDoors; } public void setShouldOpenDoors(boolean b) { canOpenDoors = b; } // Paper - obfhelper ++ protected boolean canFloat; public boolean shouldFloat() { return canFloat; } public void setShouldFloat(boolean b) { canFloat = b; } // Paper - obfhelper + + public NodeEvaluator() {} + +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Path.java b/src/main/java/net/minecraft/world/level/pathfinder/Path.java +index 7bc0787634e3c5a6f76181b166793fb7591767e4..fd5b369b59669b893aaaec17aef1a526fd23d8c0 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/Path.java +@@ -8,13 +8,14 @@ import net.minecraft.world.phys.Vec3; + + public class Path { + +- private final List nodes; ++ private final List nodes; public List getPoints() { return nodes; } // Paper - OBFHELPER + private Node[] openSet = new Node[0]; + private Node[] closedSet = new Node[0]; +- private int nextNodeIndex; ++ private int nextNodeIndex; public int getNextIndex() { return this.nextNodeIndex; } // Paper - OBFHELPER + private final BlockPos target; + private final float distToTarget; + private final boolean reached; ++ public boolean hasNext() { return getNextIndex() < getPoints().size(); } // Paper + + public Path(List nodes, BlockPos target, boolean reachesTarget) { + this.nodes = nodes; +@@ -36,7 +37,7 @@ public class Path { + } + + @Nullable +- public Node getEndNode() { ++ public Node getFinalPoint() { return getEndNode(); } @Nullable public Node getEndNode() { // Paper - OBFHELPER + return !this.nodes.isEmpty() ? (Node) this.nodes.get(this.nodes.size() - 1) : null; + } + +@@ -84,7 +85,7 @@ public class Path { + return this.getEntityPosAtNode(entity, this.nextNodeIndex); + } + +- public BlockPos getNextNodePos() { ++ public BlockPos getNext() { return getNextNodePos(); } public BlockPos getNextNodePos() { // Paper - OBFHELPER + return ((Node) this.nodes.get(this.nextNodeIndex)).asBlockPos(); + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +index fd2c5a4e245647f51c1191991dc315b773ff73d4..b5fe55a77c8558cf2ea32689ff57911530df75f9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +@@ -11,8 +11,11 @@ import org.bukkit.loot.LootTable; + public abstract class CraftMob extends CraftLivingEntity implements Mob { + public CraftMob(CraftServer server, net.minecraft.world.entity.Mob entity) { + super(server, entity); ++ paperPathfinder = new com.destroystokyo.paper.entity.PaperPathfinder(entity); // Paper + } + ++ private final com.destroystokyo.paper.entity.PaperPathfinder paperPathfinder; // Paper ++ @Override public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { return paperPathfinder; } // Paper + @Override + public void setTarget(LivingEntity target) { + net.minecraft.world.entity.Mob entity = getHandle(); diff --git a/patches/server-remapped/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch b/patches/server-remapped/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch new file mode 100644 index 0000000000..9234ee7b61 --- /dev/null +++ b/patches/server-remapped/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 10 Sep 2018 23:36:16 -0400 +Subject: [PATCH] Prevent chunk loading from Fluid Flowing + + +diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java +index 967123992ee86f13f4ca6e336eaf8cebed086a1a..7544bf227b1dded0f854cc1b30d246d120f65b20 100644 +--- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java ++++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java +@@ -175,7 +175,8 @@ public abstract class FlowingFluid extends Fluid { + Direction enumdirection = (Direction) entry.getKey(); + FluidState fluid1 = (FluidState) entry.getValue(); + BlockPos blockposition1 = pos.relative(enumdirection); +- BlockState iblockdata1 = world.getBlockState(blockposition1); ++ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); // Paper ++ if (iblockdata1 == null) continue; // Paper + + if (this.canSpreadTo(world, pos, blockState, enumdirection, blockposition1, iblockdata1, world.getFluidState(blockposition1), fluid1.getType())) { + // CraftBukkit start +@@ -202,7 +203,8 @@ public abstract class FlowingFluid extends Fluid { + while (iterator.hasNext()) { + Direction enumdirection = (Direction) iterator.next(); + BlockPos blockposition1 = pos.relative(enumdirection); +- BlockState iblockdata1 = world.getBlockState(blockposition1); ++ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); // Paper ++ if (iblockdata1 == null) continue; // Paper + FluidState fluid = iblockdata1.getFluidState(); + + if (fluid.getType().isSame((Fluid) this) && this.canPassThroughWall(enumdirection, (BlockGetter) world, pos, state, blockposition1, iblockdata1)) { +@@ -319,11 +321,18 @@ public abstract class FlowingFluid extends Fluid { + if (enumdirection1 != enumdirection) { + BlockPos blockposition2 = blockposition.relative(enumdirection1); + short short0 = getCacheKey(blockposition1, blockposition2); +- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (k) -> { +- BlockState iblockdata1 = world.getBlockState(blockposition2); ++ // Paper start - avoid loading chunks ++ Pair pair = short2objectmap.get(short0); ++ if (pair == null) { ++ BlockState iblockdatax = world.getTypeIfLoaded(blockposition2); ++ if (iblockdatax == null) { ++ continue; ++ } + +- return Pair.of(iblockdata1, iblockdata1.getFluidState()); +- }); ++ pair = Pair.of(iblockdatax, iblockdatax.getFluidState()); ++ short2objectmap.put(short0, pair); ++ } ++ // Paper end + BlockState iblockdata1 = (BlockState) pair.getFirst(); + FluidState fluid = (FluidState) pair.getSecond(); + +@@ -395,11 +404,16 @@ public abstract class FlowingFluid extends Fluid { + Direction enumdirection = (Direction) iterator.next(); + BlockPos blockposition1 = pos.relative(enumdirection); + short short0 = getCacheKey(pos, blockposition1); +- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (j) -> { +- BlockState iblockdata1 = world.getBlockState(blockposition1); +- +- return Pair.of(iblockdata1, iblockdata1.getFluidState()); +- }); ++ // Paper start ++ Pair pair = (Pair) short2objectmap.get(short0); ++ if (pair == null) { ++ BlockState iblockdatax = world.getTypeIfLoaded(blockposition1); ++ if (iblockdatax == null) continue; ++ ++ pair = Pair.of(iblockdatax, iblockdatax.getFluidState()); ++ short2objectmap.put(short0, pair); ++ } ++ // Paper end + BlockState iblockdata1 = (BlockState) pair.getFirst(); + FluidState fluid = (FluidState) pair.getSecond(); + FluidState fluid1 = this.getNewLiquid(world, blockposition1, iblockdata1); diff --git a/patches/server-remapped/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/patches/server-remapped/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch new file mode 100644 index 0000000000..30b7b72f6c --- /dev/null +++ b/patches/server-remapped/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch @@ -0,0 +1,446 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Wed, 12 Sep 2018 18:53:55 +0300 +Subject: [PATCH] Implement an API for CanPlaceOn and CanDestroy NBT values + + +diff --git a/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java b/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java +index 9175c74c2119e7052d744db77badcae6be05f3b4..52f8ad848a22ddca856f6f256276ea59416f9664 100644 +--- a/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java ++++ b/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java +@@ -57,7 +57,7 @@ public class BlockStateParser { + private final boolean forTesting; + private final Map, Comparable> properties = Maps.newLinkedHashMap(); // CraftBukkit - stable + private final Map vagueProperties = Maps.newHashMap(); +- private ResourceLocation id = new ResourceLocation(""); ++ private ResourceLocation id = new ResourceLocation(""); public final ResourceLocation getBlockKey() { return this.id; } // Paper - OBFHELPER + private StateDefinition definition; + private BlockState state; + @Nullable +@@ -86,11 +86,13 @@ public class BlockStateParser { + return this.nbt; + } + ++ public final @Nullable ResourceLocation getTagKey() { return getTag(); } // Paper - OBFHELPER + @Nullable + public ResourceLocation getTag() { + return this.tag; + } + ++ public final BlockStateParser parse(boolean parseTile) throws CommandSyntaxException { return this.parse(parseTile); } // Paper - OBFHELPER + public BlockStateParser parse(boolean allowNbt) throws CommandSyntaxException { + this.suggestions = this::suggestBlockIdOrTag; + if (this.reader.canRead() && this.reader.peek() == '#') { +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba918f044e51 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -39,12 +39,14 @@ import java.util.logging.Level; + import java.util.logging.Logger; + import javax.annotation.Nonnull; + import javax.annotation.Nullable; ++import net.minecraft.commands.arguments.blocks.BlockStateParser; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtIo; + import net.minecraft.nbt.StringTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.TextComponent; ++import net.minecraft.resources.ResourceLocation; + import net.minecraft.world.item.BlockItem; + import org.apache.commons.codec.binary.Base64; + import org.apache.commons.lang.Validate; +@@ -83,6 +85,12 @@ import org.bukkit.persistence.PersistentDataContainer; + import static org.spigotmc.ValidateUtils.*; + // Spigot end + ++// Paper start ++import com.destroystokyo.paper.Namespaced; ++import com.destroystokyo.paper.NamespacedTag; ++import java.util.Collections; ++// Paper end ++ + /** + * Children must include the following: + * +@@ -266,6 +274,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + @Specific(Specific.To.NBT) + static final ItemMetaKey BLOCK_DATA = new ItemMetaKey("BlockStateTag"); + static final ItemMetaKey BUKKIT_CUSTOM_TAG = new ItemMetaKey("PublicBukkitValues"); ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ static final ItemMetaKey CAN_DESTROY = new ItemMetaKey("CanDestroy"); ++ static final ItemMetaKey CAN_PLACE_ON = new ItemMetaKey("CanPlaceOn"); ++ // Paper end + + // We store the raw original JSON representation of all text data. See SPIGOT-5063, SPIGOT-5656, SPIGOT-5304 + private String displayName; +@@ -279,6 +291,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + private int hideFlag; + private boolean unbreakable; + private int damage; ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ private Set placeableKeys = Sets.newHashSet(); ++ private Set destroyableKeys = Sets.newHashSet(); ++ // Paper end + + private static final Set HANDLED_TAGS = Sets.newHashSet(); + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); +@@ -316,6 +332,15 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + this.hideFlag = meta.hideFlag; + this.unbreakable = meta.unbreakable; + this.damage = meta.damage; ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (meta.hasPlaceableKeys()) { ++ this.placeableKeys = new java.util.HashSet<>(meta.placeableKeys); ++ } ++ ++ if (meta.hasDestroyableKeys()) { ++ this.destroyableKeys = new java.util.HashSet<>(meta.destroyableKeys); ++ } ++ // Paper end + this.unhandledTags.putAll(meta.unhandledTags); + this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw()); + +@@ -379,6 +404,31 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + persistentDataContainer.put(key, compound.get(key)); + } + } ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (tag.contains(CAN_DESTROY.NBT)) { ++ ListTag list = tag.getList(CAN_DESTROY.NBT, CraftMagicNumbers.NBT.TAG_STRING); ++ for (int i = 0; i < list.size(); i++) { ++ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); ++ if (namespaced == null) { ++ continue; ++ } ++ ++ this.destroyableKeys.add(namespaced); ++ } ++ } ++ ++ if (tag.contains(CAN_PLACE_ON.NBT)) { ++ ListTag list = tag.getList(CAN_PLACE_ON.NBT, CraftMagicNumbers.NBT.TAG_STRING); ++ for (int i = 0; i < list.size(); i++) { ++ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); ++ if (namespaced == null) { ++ continue; ++ } ++ ++ this.placeableKeys.add(namespaced); ++ } ++ } ++ // Paper end + + Set keys = tag.getAllKeys(); + for (String key : keys) { +@@ -517,6 +567,34 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + setDamage(damage); + } + ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ Iterable canPlaceOnSerialized = SerializableMeta.getObject(Iterable.class, map, CAN_PLACE_ON.BUKKIT, true); ++ if (canPlaceOnSerialized != null) { ++ for (Object canPlaceOnElement : canPlaceOnSerialized) { ++ String canPlaceOnRaw = (String) canPlaceOnElement; ++ Namespaced value = this.deserializeNamespaced(canPlaceOnRaw); ++ if (value == null) { ++ continue; ++ } ++ ++ this.placeableKeys.add(value); ++ } ++ } ++ ++ Iterable canDestroySerialized = SerializableMeta.getObject(Iterable.class, map, CAN_DESTROY.BUKKIT, true); ++ if (canDestroySerialized != null) { ++ for (Object canDestroyElement : canDestroySerialized) { ++ String canDestroyRaw = (String) canDestroyElement; ++ Namespaced value = this.deserializeNamespaced(canDestroyRaw); ++ if (value == null) { ++ continue; ++ } ++ ++ this.destroyableKeys.add(value); ++ } ++ } ++ // Paper end ++ + String internal = SerializableMeta.getString(map, "internal", true); + if (internal != null) { + ByteArrayInputStream buf = new ByteArrayInputStream(Base64.decodeBase64(internal)); +@@ -645,6 +723,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + if (hasDamage()) { + itemTag.putInt(DAMAGE.NBT, damage); + } ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (hasPlaceableKeys()) { ++ List items = this.placeableKeys.stream() ++ .map(this::serializeNamespaced) ++ .collect(java.util.stream.Collectors.toList()); ++ ++ itemTag.put(CAN_PLACE_ON.NBT, createNonComponentStringList(items)); ++ } ++ ++ if (hasDestroyableKeys()) { ++ List items = this.destroyableKeys.stream() ++ .map(this::serializeNamespaced) ++ .collect(java.util.stream.Collectors.toList()); ++ ++ itemTag.put(CAN_DESTROY.NBT, createNonComponentStringList(items)); ++ } ++ // Paper end + + for (Map.Entry e : unhandledTags.entrySet()) { + itemTag.put(e.getKey(), e.getValue()); +@@ -661,6 +756,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + } + ++ // Paper start ++ static ListTag createNonComponentStringList(List list) { ++ if (list == null || list.isEmpty()) { ++ return null; ++ } ++ ++ ListTag tagList = new ListTag(); ++ for (String value : list) { ++ tagList.add(StringTag.valueOf(value)); // Paper - NBTTagString.of(String str) ++ } ++ ++ return tagList; ++ } ++ // Paper end ++ + ListTag createStringList(List list) { + if (list == null) { + return null; +@@ -744,7 +854,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + + @Overridden + boolean isEmpty() { +- return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); ++ return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers() || hasPlaceableKeys() || hasDestroyableKeys()); // Paper - Implement an API for CanPlaceOn and CanDestroy NBT values + } + + // Paper start +@@ -1168,7 +1278,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + && (this.hideFlag == that.hideFlag) + && (this.isUnbreakable() == that.isUnbreakable()) + && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) +- && (this.version == that.version); ++ && (this.version == that.version) ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ && (this.hasPlaceableKeys() ? that.hasPlaceableKeys() && this.placeableKeys.equals(that.placeableKeys) : !that.hasPlaceableKeys()) ++ && (this.hasDestroyableKeys() ? that.hasDestroyableKeys() && this.destroyableKeys.equals(that.destroyableKeys) : !that.hasDestroyableKeys()); ++ // Paper end + } + + /** +@@ -1203,6 +1317,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + hash = 61 * hash + (hasDamage() ? this.damage : 0); + hash = 61 * hash + (hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); + hash = 61 * hash + version; ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ hash = 61 * hash + (hasPlaceableKeys() ? this.placeableKeys.hashCode() : 0); ++ hash = 61 * hash + (hasDestroyableKeys() ? this.destroyableKeys.hashCode() : 0); ++ // Paper end + return hash; + } + +@@ -1227,6 +1345,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + clone.unbreakable = this.unbreakable; + clone.damage = this.damage; + clone.version = this.version; ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (this.placeableKeys != null) { ++ clone.placeableKeys = Sets.newHashSet(this.placeableKeys); ++ } ++ if (this.destroyableKeys != null) { ++ clone.destroyableKeys = Sets.newHashSet(this.destroyableKeys); ++ } ++ // Paper end + return clone; + } catch (CloneNotSupportedException e) { + throw new Error(e); +@@ -1284,6 +1410,24 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + builder.put(DAMAGE.BUKKIT, damage); + } + ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (hasPlaceableKeys()) { ++ List cerealPlaceable = this.placeableKeys.stream() ++ .map(this::serializeNamespaced) ++ .collect(java.util.stream.Collectors.toList()); ++ ++ builder.put(CAN_PLACE_ON.BUKKIT, cerealPlaceable); ++ } ++ ++ if (hasDestroyableKeys()) { ++ List cerealDestroyable = this.destroyableKeys.stream() ++ .map(this::serializeNamespaced) ++ .collect(java.util.stream.Collectors.toList()); ++ ++ builder.put(CAN_DESTROY.BUKKIT, cerealDestroyable); ++ } ++ // Paper end ++ + final Map internalTags = new HashMap(unhandledTags); + serializeInternal(internalTags); + if (!internalTags.isEmpty()) { +@@ -1448,6 +1592,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + CraftMetaArmorStand.SHOW_ARMS.NBT, + CraftMetaArmorStand.SMALL.NBT, + CraftMetaArmorStand.MARKER.NBT, ++ CAN_DESTROY.NBT, ++ CAN_PLACE_ON.NBT, + // Paper end + CraftMetaCompass.LODESTONE_DIMENSION.NBT, + CraftMetaCompass.LODESTONE_POS.NBT, +@@ -1475,4 +1621,147 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + // Paper end + ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ @Override ++ @SuppressWarnings("deprecation") ++ public Set getCanDestroy() { ++ return !hasDestroyableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.destroyableKeys); ++ } ++ ++ @Override ++ @SuppressWarnings("deprecation") ++ public void setCanDestroy(Set canDestroy) { ++ Validate.notNull(canDestroy, "Cannot replace with null set!"); ++ legacyClearAndReplaceKeys(this.destroyableKeys, canDestroy); ++ } ++ ++ @Override ++ @SuppressWarnings("deprecation") ++ public Set getCanPlaceOn() { ++ return !hasPlaceableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.placeableKeys); ++ } ++ ++ @Override ++ @SuppressWarnings("deprecation") ++ public void setCanPlaceOn(Set canPlaceOn) { ++ Validate.notNull(canPlaceOn, "Cannot replace with null set!"); ++ legacyClearAndReplaceKeys(this.placeableKeys, canPlaceOn); ++ } ++ ++ @Override ++ public Set getDestroyableKeys() { ++ return !hasDestroyableKeys() ? Collections.emptySet() : Sets.newHashSet(this.destroyableKeys); ++ } ++ ++ @Override ++ public void setDestroyableKeys(Collection canDestroy) { ++ Validate.notNull(canDestroy, "Cannot replace with null collection!"); ++ Validate.isTrue(ofAcceptableType(canDestroy), "Can only use NamespacedKey or NamespacedTag objects!"); ++ this.destroyableKeys.clear(); ++ this.destroyableKeys.addAll(canDestroy); ++ } ++ ++ @Override ++ public Set getPlaceableKeys() { ++ return !hasPlaceableKeys() ? Collections.emptySet() : Sets.newHashSet(this.placeableKeys); ++ } ++ ++ @Override ++ public void setPlaceableKeys(Collection canPlaceOn) { ++ Validate.notNull(canPlaceOn, "Cannot replace with null collection!"); ++ Validate.isTrue(ofAcceptableType(canPlaceOn), "Can only use NamespacedKey or NamespacedTag objects!"); ++ this.placeableKeys.clear(); ++ this.placeableKeys.addAll(canPlaceOn); ++ } ++ ++ @Override ++ public boolean hasPlaceableKeys() { ++ return this.placeableKeys != null && !this.placeableKeys.isEmpty(); ++ } ++ ++ @Override ++ public boolean hasDestroyableKeys() { ++ return this.destroyableKeys != null && !this.destroyableKeys.isEmpty(); ++ } ++ ++ @Deprecated ++ private void legacyClearAndReplaceKeys(Collection toUpdate, Collection beingSet) { ++ if (beingSet.stream().anyMatch(Material::isLegacy)) { ++ throw new IllegalArgumentException("Set must not contain any legacy materials!"); ++ } ++ ++ toUpdate.clear(); ++ toUpdate.addAll(beingSet.stream().map(Material::getKey).collect(java.util.stream.Collectors.toSet())); ++ } ++ ++ @Deprecated ++ private Set legacyGetMatsFromKeys(Collection names) { ++ Set mats = Sets.newHashSet(); ++ for (Namespaced key : names) { ++ if (!(key instanceof org.bukkit.NamespacedKey)) { ++ continue; ++ } ++ ++ Material material = Material.matchMaterial(key.toString(), false); ++ if (material != null) { ++ mats.add(material); ++ } ++ } ++ ++ return mats; ++ } ++ ++ private @Nullable Namespaced deserializeNamespaced(String raw) { ++ boolean isTag = raw.length() > 0 && raw.codePointAt(0) == '#'; ++ BlockStateParser blockParser = new BlockStateParser(new com.mojang.brigadier.StringReader(raw), true); ++ try { ++ blockParser = blockParser.parse(false); ++ } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) { ++ e.printStackTrace(); ++ return null; ++ } ++ ++ ResourceLocation key; ++ if (isTag) { ++ key = blockParser.getTagKey(); ++ } else { ++ key = blockParser.getBlockKey(); ++ } ++ ++ if (key == null) { ++ return null; ++ } ++ ++ // don't DC the player if something slips through somehow ++ Namespaced resource = null; ++ try { ++ if (isTag) { ++ resource = new NamespacedTag(key.getNamespace(), key.getPath()); ++ } else { ++ resource = CraftNamespacedKey.fromMinecraft(key); ++ } ++ } catch (IllegalArgumentException ex) { ++ org.bukkit.Bukkit.getLogger().warning("Namespaced resource does not validate: " + key.toString()); ++ ex.printStackTrace(); ++ } ++ ++ return resource; ++ } ++ ++ private @Nonnull String serializeNamespaced(Namespaced resource) { ++ return resource.toString(); ++ } ++ ++ // not a fan of this ++ private boolean ofAcceptableType(Collection namespacedResources) { ++ ++ for (Namespaced resource : namespacedResources) { ++ if (!(resource instanceof org.bukkit.NamespacedKey || resource instanceof com.destroystokyo.paper.NamespacedTag)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/patches/server-remapped/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch new file mode 100644 index 0000000000..dff6bf782c --- /dev/null +++ b/patches/server-remapped/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 10 Sep 2018 23:56:36 -0400 +Subject: [PATCH] Prevent Mob AI Rules from Loading Chunks + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +index 415661c61eb85ac57dd2ba81fb62f8d9df54153f..c9825bc1894904fab34bec8223adf8e343bb6623 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +@@ -29,11 +29,13 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + private final Block blockToRemove; + private final Mob removerMob; + private int ticksSinceReachedGoal; ++ private Level world; // Paper + + public RemoveBlockGoal(Block targetBlock, PathfinderMob mob, double speed, int maxYDifference) { + super(mob, speed, 24, maxYDifference); + this.blockToRemove = targetBlock; + this.removerMob = mob; ++ this.world = mob.level; // Paper + } + + @Override +@@ -131,7 +133,9 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + + @Nullable + private BlockPos getPosWithBlock(BlockPos pos, BlockGetter world) { +- if (world.getBlockState(pos).is(this.blockToRemove)) { ++ Block block = world.getBlockIfLoaded(pos); // Paper ++ if (block == null) return null; // Paper ++ if (block.is(this.blockToRemove)) { // Paper + return pos; + } else { + BlockPos[] ablockposition = new BlockPos[]{pos.below(), pos.west(), pos.east(), pos.north(), pos.south(), pos.below().below()}; +@@ -141,7 +145,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + for (int j = 0; j < i; ++j) { + BlockPos blockposition1 = ablockposition1[j]; + +- if (world.getBlockState(blockposition1).is(this.blockToRemove)) { ++ if (world.getBlockIfLoaded(blockposition1).is(this.blockToRemove)) { // Paper + return blockposition1; + } + } +@@ -152,7 +156,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + + @Override + protected boolean isValidTarget(LevelReader world, BlockPos pos) { +- ChunkAccess ichunkaccess = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, false); ++ ChunkAccess ichunkaccess = world.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4); // Paper + + return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).is(this.blockToRemove) && ichunkaccess.getBlockState(pos.above()).isAir() && ichunkaccess.getBlockState(pos.above(2)).isAir(); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java b/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java +index 246cbddb23781e323d022db2fbeef72c9eeaad2b..55d484fd4774cfad8f8ba3263b387243540e31b1 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java ++++ b/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java +@@ -13,6 +13,7 @@ import net.minecraft.util.Mth; + import net.minecraft.world.entity.PathfinderMob; + import net.minecraft.world.entity.ai.navigation.PathNavigation; + import net.minecraft.world.level.BlockGetter; ++import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; + import net.minecraft.world.phys.Vec3; +@@ -128,6 +129,7 @@ public class RandomPos { + } + + blockposition2 = new BlockPos((double) k1 + mob.getX(), (double) l1 + mob.getY(), (double) i2 + mob.getZ()); ++ if (!mob.level.hasChunkAt(blockposition2)) continue; // Paper + if (blockposition2.getY() >= 0 && blockposition2.getY() <= mob.level.getMaxBuildHeight() && (!flag3 || mob.isWithinRestriction(blockposition2)) && (!validPositionsOnly || navigationabstract.isStableDestination(blockposition2))) { + if (aboveGround) { + blockposition2 = moveUpToAboveSolid(blockposition2, random.nextInt(distanceAboveGroundRange + 1) + minDistanceAboveGround, mob.level.getMaxBuildHeight(), (blockposition3) -> { +@@ -135,7 +137,8 @@ public class RandomPos { + }); + } + +- if (notInWater || !mob.level.getFluidState(blockposition2).is((Tag) FluidTags.WATER)) { ++ FluidState fluid = mob.level.getFluidIfLoaded(blockposition2); // Paper ++ if (notInWater || (fluid != null && !fluid.is((Tag) FluidTags.WATER))) { // Paper + BlockPathTypes pathtype = WalkNodeEvaluator.getBlockPathTypeStatic((BlockGetter) mob.level, blockposition2.mutable()); + + if (mob.getPathfindingMalus(pathtype) == 0.0F) { diff --git a/patches/server-remapped/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch b/patches/server-remapped/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch new file mode 100644 index 0000000000..759560db06 --- /dev/null +++ b/patches/server-remapped/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 12 Sep 2018 21:12:57 -0400 +Subject: [PATCH] Prevent mob spawning from loading/generating chunks + +also prevents if out of world border bounds + +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index b90a275a0dc2913809ce16659eed445501e486de..e23875ae07c23fed1161ea070e63bbc3a30168a0 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -174,9 +174,9 @@ public final class NaturalSpawner { + StructureFeatureManager structuremanager = world.structureFeatureManager(); + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); + int i = pos.getY(); +- BlockState iblockdata = chunk.getBlockState(pos); ++ BlockState iblockdata = world.getTypeIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn + +- if (!iblockdata.isRedstoneConductor(chunk, pos)) { ++ if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn + BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + int j = 0; + int k = 0; +@@ -205,7 +205,7 @@ public final class NaturalSpawner { + if (entityhuman != null) { + double d2 = entityhuman.distanceToSqr(d0, (double) i, d1); + +- if (isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2)) { ++ if (isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2) && world.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn + if (biomesettingsmobs_c == null) { + biomesettingsmobs_c = getRandomSpawnMobAt(world, structuremanager, chunkgenerator, group, world.random, (BlockPos) blockposition_mutableblockposition); + if (biomesettingsmobs_c == null) { diff --git a/patches/server-remapped/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/server-remapped/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch new file mode 100644 index 0000000000..db7b1e6312 --- /dev/null +++ b/patches/server-remapped/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch @@ -0,0 +1,97 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 12 Sep 2018 21:47:01 -0400 +Subject: [PATCH] Optimize Biome Mob Lookups for Mob Spawning + +Uses an EnumMap as well as a Set paired List for O(1) contains calls. + +diff --git a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java +index 58ee27a994b4cd845b8bb28e80cc2102c860f097..528f42c63a1186b8827bfe7cf6193e14da938cb3 100644 +--- a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java ++++ b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java +@@ -30,19 +30,28 @@ public class MobSpawnSettings { + }, (enumcreaturetype) -> { + return ImmutableList.of(); + })), ImmutableMap.of(), false); ++ // Paper start- decompile error workaround ++ private static class bProxy extends MobSpawnSettings.MobSpawnCost { ++ private bProxy(double gravityLimit, double mass) { ++ super(gravityLimit, mass); ++ } ++ } ++ private static class cProxy extends MobSpawnSettings.SpawnerData { ++ public cProxy(EntityType type, int weight, int minGroupSize, int maxGroupSize) { ++ super(type, weight, minGroupSize, maxGroupSize); ++ } ++ }; ++ // Paper end + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { +- return biomesettingsmobs.d; ++ RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { // Paper - add type to builder ++ return biomesettingsmobs.creatureGenerationProbability; + }); +- Codec codec = MobCategory.CODEC; +- Codec codec1 = BiomeSettingsMobs.c.b.listOf(); +- Logger logger = MobSpawnSettings.LOGGER; +- +- logger.getClass(); +- return instance.group(recordcodecbuilder, Codec.simpleMap(codec, codec1.promotePartial(Util.prefix("Spawn data: ", logger::error)), StringRepresentable.keys(MobCategory.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { +- return biomesettingsmobs.e; +- }), Codec.simpleMap(Registry.ENTITY_TYPE, BiomeSettingsMobs.b.a, Registry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { +- return biomesettingsmobs.f; ++ // Paper - remove unused vars ++ ++ return instance.group(recordcodecbuilder, Codec.simpleMap(MobCategory.CODEC, cProxy.CODEC.listOf().promotePartial(Util.prefix("Spawn data: ", MobSpawnSettings.LOGGER::error)), StringRepresentable.keys(MobCategory.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { // Paper - inline codec, cProxy, LOGGER ++ return biomesettingsmobs.spawners; ++ }), Codec.simpleMap(Registry.ENTITY_TYPE, bProxy.CODEC, Registry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { // Paper - decompile error - bProxy ++ return biomesettingsmobs.mobSpawnCosts; + }), Codec.BOOL.fieldOf("player_spawn_friendly").orElse(false).forGetter(MobSpawnSettings::playerSpawnFriendly)).apply(instance, MobSpawnSettings::new); + }); + private final float creatureGenerationProbability; +@@ -76,11 +85,43 @@ public class MobSpawnSettings { + + public static class Builder { + +- private final Map> spawners = (Map) Stream.of(MobCategory.values()).collect(ImmutableMap.toImmutableMap((enumcreaturetype) -> { ++ // Paper start - keep track of data in a pair set to give O(1) contains calls - we have to hook removals incase plugins mess with it ++ public static class MobList extends java.util.ArrayList { ++ java.util.Set biomes = new java.util.HashSet<>(); ++ ++ @Override ++ public boolean contains(Object o) { ++ return biomes.contains(o); ++ } ++ ++ @Override ++ public boolean add(MobSpawnSettings.SpawnerData BiomeSettingsMobs) { ++ biomes.add(BiomeSettingsMobs); ++ return super.add(BiomeSettingsMobs); ++ } ++ ++ @Override ++ public MobSpawnSettings.SpawnerData remove(int index) { ++ MobSpawnSettings.SpawnerData removed = super.remove(index); ++ if (removed != null) { ++ biomes.remove(removed); ++ } ++ return removed; ++ } ++ ++ @Override ++ public void clear() { ++ biomes.clear(); ++ super.clear(); ++ } ++ } ++ // use toImmutableEnumMap collector ++ private final Map> spawners = (Map) Stream.of(MobCategory.values()).collect(Maps.toImmutableEnumMap((enumcreaturetype) -> { + return enumcreaturetype; + }, (enumcreaturetype) -> { +- return Lists.newArrayList(); ++ return new MobList(); // Use MobList instead of ArrayList + })); ++ // Paper end + private final Map, MobSpawnSettings.MobSpawnCost> mobSpawnCosts = Maps.newLinkedHashMap(); + private float creatureGenerationProbability = 0.1F; + private boolean playerCanSpawn; diff --git a/patches/server-remapped/0287-Implement-furnace-cook-speed-multiplier-API.patch b/patches/server-remapped/0287-Implement-furnace-cook-speed-multiplier-API.patch new file mode 100644 index 0000000000..4b104b38ec --- /dev/null +++ b/patches/server-remapped/0287-Implement-furnace-cook-speed-multiplier-API.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tassu +Date: Thu, 13 Sep 2018 08:45:21 +0300 +Subject: [PATCH] Implement furnace cook speed multiplier API + +Signed-off-by: Tassu + +Fixed an issue where a furnace's cook-speed multiplier rounds down +to the nearest Integer when updating its current cook time. + +Modified by: Eric Su + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 8c55c1d88ef2e20e82bcdae0b9b3d381e562051f..4126a36dbc7750108a883f0be14dcb0d2e6d7ae8 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -38,6 +38,7 @@ import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.Vec3; + // CraftBukkit start ++import java.util.List; + import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.craftbukkit.inventory.CraftItemStack; +@@ -56,6 +57,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + protected NonNullList items; + public int litTime; + private int litDuration; ++ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API + public int cookingProgress; + public int cookingTotalTime; + protected final ContainerData dataAccess; +@@ -256,6 +258,11 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + this.recipesUsed.put(new ResourceLocation(s), nbttagcompound1.getInt(s)); + } + ++ // Paper start - cook speed API ++ if (tag.contains("Paper.CookSpeedMultiplier")) { ++ this.cookSpeedMultiplier = tag.getDouble("Paper.CookSpeedMultiplier"); ++ } ++ // Paper end + } + + @Override +@@ -264,6 +271,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + tag.putShort("BurnTime", (short) this.litTime); + tag.putShort("CookTime", (short) this.cookingProgress); + tag.putShort("CookTimeTotal", (short) this.cookingTotalTime); ++ tag.putDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API + ContainerHelper.saveAllItems(tag, this.items); + CompoundTag nbttagcompound1 = new CompoundTag(); + +@@ -324,7 +332,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + + if (this.isLit() && this.canBurn(irecipe)) { + ++this.cookingProgress; +- if (this.cookingProgress == this.cookingTotalTime) { ++ if (this.cookingProgress >= this.cookingTotalTime) { // Paper - cook speed multiplier API + this.cookingProgress = 0; + this.cookingTotalTime = this.getTotalCookTime(); + this.burn(irecipe); +@@ -424,9 +432,13 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + } + } + +- protected int getTotalCookTime() { +- return (this.hasLevel()) ? (Integer) this.level.getRecipeManager().getRecipeFor((RecipeType) this.recipeType, this, this.level).map(AbstractCookingRecipe::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail ++ // Paper begin - Expose this function so CraftFurnace can correctly scale the total cooking time to a new multiplier ++ public int getTotalCookTime() { ++ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */ ++ int cookTime = (this.hasLevel()) ? (Integer) this.level.getRecipeManager().getRecipeFor((RecipeType) this.recipeType, this, this.level).map(AbstractCookingRecipe::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail ++ return (int) Math.ceil (cookTime / this.cookSpeedMultiplier); + } ++ // Paper end + + public static boolean isFuel(ItemStack stack) { + return getFuel().containsKey(stack.getItem()); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java +index 5028a6388f95a14df8d1590cddd7414d8de5bf78..a69785c331c6cee34ba4e93f47865ab8e29ec9b8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java +@@ -63,4 +63,20 @@ public abstract class CraftFurnace extends + public void setCookTimeTotal(int cookTimeTotal) { + this.getSnapshot().cookingTotalTime = cookTimeTotal; + } ++ ++ // Paper start - cook speed multiplier API ++ @Override ++ public double getCookSpeedMultiplier() { ++ return this.getSnapshot().cookSpeedMultiplier; ++ } ++ ++ @Override ++ public void setCookSpeedMultiplier(double multiplier) { ++ com.google.common.base.Preconditions.checkArgument(multiplier >= 0, "Furnace speed multiplier cannot be negative"); ++ com.google.common.base.Preconditions.checkArgument(multiplier <= 200, "Furnace speed multiplier cannot more than 200"); ++ T snapshot = this.getSnapshot(); ++ snapshot.cookSpeedMultiplier = multiplier; ++ snapshot.cookingTotalTime = snapshot.getTotalCookTime(); // Update the snapshot's current total cook time to scale with the newly set multiplier ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0288-PreSpawnerSpawnEvent.patch b/patches/server-remapped/0288-PreSpawnerSpawnEvent.patch new file mode 100644 index 0000000000..cb777e4c22 --- /dev/null +++ b/patches/server-remapped/0288-PreSpawnerSpawnEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Tue, 18 Sep 2018 23:53:23 +0100 +Subject: [PATCH] PreSpawnerSpawnEvent + +This adds a separate event before an entity is spawned by a spawner +which contains the location of the spawner too similarly to how the +SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for +spawners. + +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index ac572eba10a7239d71dfae060f623b076d4252ce..1ce675d0d24ceb5724f5ac2d8f671e38f2735f74 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -132,11 +132,11 @@ public abstract class BaseSpawner { + + org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); + if (type != null) { +- com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; +- event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent( + MCUtil.toLocation(world, d3, d4, d5), + type, +- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER ++ MCUtil.toLocation(world, blockposition) + ); + if (!event.callEvent()) { + flag = true; diff --git a/patches/server-remapped/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch b/patches/server-remapped/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch new file mode 100644 index 0000000000..a418dc54d3 --- /dev/null +++ b/patches/server-remapped/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 22 Sep 2018 15:56:59 -0400 +Subject: [PATCH] Catch JsonParseException in Entity and TE names + +As a result, data that no longer parses correctly will not crash the server +instead just logging the exception and continuing (and in most cases should +fix the data) + +Player data is fixed pretty much immediately but some block data (like +Shulkers) may need to be changed in order for it to re-save properly + +No more crashing though. + +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 68c3f069f8f832ab3d146748348aded69b5ad823..1fecc81b25109592907623741225a6222a8c5ccc 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -7,6 +7,8 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; + import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.chat.Component; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkPos; +@@ -514,4 +516,19 @@ public final class MCUtil { + return null; + } + } ++ ++ @Nullable ++ public static Component getBaseComponentFromNbt(String key, CompoundTag compound) { ++ if (!compound.contains(key)) { ++ return null; ++ } ++ String string = compound.getString(key); ++ try { ++ return Component.Serializer.jsonToComponent(string); ++ } catch (com.google.gson.JsonParseException e) { ++ org.bukkit.Bukkit.getLogger().warning("Unable to parse " + key + " from " + compound +": " + e.getMessage()); ++ } ++ ++ return null; ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +index 9ad077259563a3d960d32a59d4b6fc3cfbe3440c..00dc4cd436023b946d7005f17a7ba983a4bbdfb6 100644 +--- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java ++++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +@@ -12,6 +12,7 @@ import net.minecraft.commands.CommandSourceStack; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TextComponent; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.StringUtil; +@@ -72,7 +73,7 @@ public abstract class BaseCommandBlock implements CommandSource { + this.command = tag.getString("Command"); + this.successCount = tag.getInt("SuccessCount"); + if (tag.contains("CustomName", 8)) { +- this.setName(Component.Serializer.fromJson(tag.getString("CustomName"))); ++ this.setName(MCUtil.getBaseComponentFromNbt("CustomName", tag)); // Paper - Catch ParseException + } + + if (tag.contains("TrackOutput", 1)) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java +index 2e3ec85e7bd1c375db0662dba2617d8924dbd2a6..2c885be67b9c992b96f5caf78130d46abb455ceb 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java +@@ -9,6 +9,7 @@ import net.minecraft.nbt.ListTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; ++import net.minecraft.server.MCUtil; + import net.minecraft.world.Nameable; + import net.minecraft.world.item.DyeColor; + import net.minecraft.world.item.ItemStack; +@@ -70,7 +71,7 @@ public class BannerBlockEntity extends BlockEntity implements Nameable { + public void load(BlockState state, CompoundTag tag) { + super.load(state, tag); + if (tag.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(tag.getString("CustomName")); ++ this.name = MCUtil.getBaseComponentFromNbt("CustomName", tag); // Paper - Catch ParseException + } + + if (this.hasLevel()) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +index a7358274fe367a113b304a5ce332b8dcf721b7af..2b420109e9bed184aaa4ffbcee666b4c325c5a28 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +@@ -4,6 +4,7 @@ import javax.annotation.Nullable; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.Container; +@@ -30,7 +31,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co + super.load(state, tag); + this.lockKey = LockCode.fromTag(tag); + if (tag.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(tag.getString("CustomName")); ++ this.name = MCUtil.getBaseComponentFromNbt("CustomName", tag); // Paper - Catch ParseException + } + + } diff --git a/patches/server-remapped/0290-Honor-EntityAgeable.ageLock.patch b/patches/server-remapped/0290-Honor-EntityAgeable.ageLock.patch new file mode 100644 index 0000000000..a2b0c4fa76 --- /dev/null +++ b/patches/server-remapped/0290-Honor-EntityAgeable.ageLock.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Sep 2018 20:59:53 -0500 +Subject: [PATCH] Honor EntityAgeable.ageLock + + +diff --git a/src/main/java/net/minecraft/world/entity/AgableMob.java b/src/main/java/net/minecraft/world/entity/AgableMob.java +index d7c19e5607bcf92c874b3656c2742f4c84dceb12..354311dc541588212a2eacba38e60c7e34aa4c2b 100644 +--- a/src/main/java/net/minecraft/world/entity/AgableMob.java ++++ b/src/main/java/net/minecraft/world/entity/AgableMob.java +@@ -82,6 +82,7 @@ public abstract class AgableMob extends PathfinderMob { + } + + public void ageUp(int age, boolean overGrow) { ++ if (ageLocked) return; // Paper - GH-1459 + int j = this.getAge(); + int k = j; + diff --git a/patches/server-remapped/0291-Configurable-connection-throttle-kick-message.patch b/patches/server-remapped/0291-Configurable-connection-throttle-kick-message.patch new file mode 100644 index 0000000000..354aa4e66c --- /dev/null +++ b/patches/server-remapped/0291-Configurable-connection-throttle-kick-message.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 2 Oct 2018 09:57:50 +0100 +Subject: [PATCH] Configurable connection throttle kick message + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 62621562137cba4804f0465c58d25ca2786328e5..7178b37f7978c7e9031a22726005c5099fd78fe0 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -281,6 +281,11 @@ public class PaperConfig { + authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); + } + ++ public static String connectionThrottleKickMessage = "Connection throttled! Please wait before reconnecting."; ++ private static void connectionThrottleKickMessage() { ++ connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); ++ } ++ + private static void savePlayerData() { + Object val = config.get("settings.save-player-data"); + if (val instanceof Boolean) { +diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 45c9dc9c2a580a5cd57fd4e891fbaa2b1336f5c5..6f98be2b9b00f71dd041e7511c70166fdecf0749 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -50,7 +50,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + synchronized (throttleTracker) { + if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { + throttleTracker.put(address, currentTime); +- TranslatableComponent chatmessage = new TranslatableComponent("Connection throttled! Please wait before reconnecting."); ++ TranslatableComponent chatmessage = new TranslatableComponent(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message + this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); + this.connection.disconnect(chatmessage); + return; diff --git a/patches/server-remapped/0292-Hook-into-CB-plugin-rewrites.patch b/patches/server-remapped/0292-Hook-into-CB-plugin-rewrites.patch new file mode 100644 index 0000000000..06025aa8c5 --- /dev/null +++ b/patches/server-remapped/0292-Hook-into-CB-plugin-rewrites.patch @@ -0,0 +1,184 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 3 Oct 2018 20:09:18 -0400 +Subject: [PATCH] Hook into CB plugin rewrites + +Allows us to do fun stuff like rewrite the OBC util fastutil location to +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 45cbdcfc131bbc0e2bf23cc30a572df72eecd51c..49e5a86c223f1b28ce7da6ced276b2f880777856 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java +@@ -6,7 +6,9 @@ import java.io.FileOutputStream; + import java.io.InputStream; + import java.util.Arrays; + import java.util.Enumeration; ++import java.util.HashMap; + import java.util.HashSet; ++import java.util.Map; + import java.util.Set; + import java.util.jar.JarEntry; + import java.util.jar.JarFile; +@@ -20,10 +22,15 @@ import org.bukkit.plugin.AuthorNagException; + import org.objectweb.asm.ClassReader; + import org.objectweb.asm.ClassVisitor; + import org.objectweb.asm.ClassWriter; ++import org.objectweb.asm.FieldVisitor; ++import org.objectweb.asm.Handle; ++import org.objectweb.asm.Label; + import org.objectweb.asm.MethodVisitor; + import org.objectweb.asm.Opcodes; + import org.objectweb.asm.Type; + ++import javax.annotation.Nonnull; ++ + /** + * This file is imported from Commodore. + * +@@ -46,6 +53,42 @@ public class Commodore + "org/bukkit/inventory/ItemStack (I)V setTypeId" + ) ); + ++ // Paper start - Plugin rewrites ++ private static final Map SEARCH_AND_REMOVE = initReplacementsMap(); ++ private static Map initReplacementsMap() ++ { ++ Map getAndRemove = new HashMap<>(); ++ // Be wary of maven shade's relocations ++ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/libs/it/unimi/dsi/fastutil/" ), "org/bukkit/".concat( "craftbukkit/libs/" ) ); // Remap fastutil to our location ++ ++ if ( Boolean.getBoolean( "debug.rewriteForIde" ) ) ++ { ++ // unversion incoming calls for pre-relocate debug work ++ final String NMS_REVISION_PACKAGE = "v1_16_R3/"; ++ ++ getAndRemove.put( "net/minecraft/".concat( "server/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); ++ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); ++ } ++ ++ return getAndRemove; ++ } ++ ++ @Nonnull ++ private static String getOriginalOrRewrite(@Nonnull String original) ++ { ++ String rewrite = null; ++ for ( Map.Entry entry : SEARCH_AND_REMOVE.entrySet() ) ++ { ++ if ( original.contains( entry.getKey() ) ) ++ { ++ rewrite = original.replace( entry.getValue(), "" ); ++ } ++ } ++ ++ return rewrite != null ? rewrite : original; ++ } ++ // Paper end ++ + public static void main(String[] args) + { + OptionParser parser = new OptionParser(); +@@ -130,15 +173,86 @@ public class Commodore + + cr.accept( new ClassVisitor( Opcodes.ASM9, cw ) + { ++ // Paper start - Rewrite plugins ++ @Override ++ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) ++ { ++ desc = getOriginalOrRewrite( desc ); ++ if ( signature != null ) { ++ signature = getOriginalOrRewrite( signature ); ++ } ++ ++ return super.visitField( access, name, desc, signature, value) ; ++ } ++ // Paper end ++ + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) + { + return new MethodVisitor( api, super.visitMethod( access, name, desc, signature, exceptions ) ) + { ++ // Paper start - Plugin rewrites ++ @Override ++ public void visitInvokeDynamicInsn(String name, String desc, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) ++ { ++ // Paper start - Rewrite plugins ++ name = getOriginalOrRewrite( name ); ++ if ( desc != null ) ++ { ++ desc = getOriginalOrRewrite( desc ); ++ } ++ // Paper end ++ ++ super.visitInvokeDynamicInsn( name, desc, bootstrapMethodHandle, bootstrapMethodArguments ); ++ } ++ ++ @Override ++ public void visitTypeInsn(int opcode, String type) ++ { ++ type = getOriginalOrRewrite( type ); ++ ++ super.visitTypeInsn( opcode, type ); ++ } ++ ++ @Override ++ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { ++ for ( int i = 0; i < local.length; i++ ) ++ { ++ if ( !( local[i] instanceof String ) ) { continue; } ++ ++ local[i] = getOriginalOrRewrite( (String) local[i] ); ++ } ++ ++ for ( int i = 0; i < stack.length; i++ ) ++ { ++ if ( !( stack[i] instanceof String ) ) { continue; } ++ ++ stack[i] = getOriginalOrRewrite( (String) stack[i] ); ++ } ++ ++ super.visitFrame( type, nLocal, local, nStack, stack ); ++ } ++ ++ @Override ++ public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) ++ { ++ descriptor = getOriginalOrRewrite( descriptor ); ++ ++ super.visitLocalVariable( name, descriptor, signature, start, end, index ); ++ } ++ // Paper end + + @Override + public void visitFieldInsn(int opcode, String owner, String name, String desc) + { ++ // Paper start - Rewrite plugins ++ owner = getOriginalOrRewrite( owner ); ++ if ( desc != null ) ++ { ++ desc = getOriginalOrRewrite( desc ); ++ } ++ // Paper end ++ + if ( owner.equals( "org/bukkit/block/Biome" ) ) + { + switch ( name ) +@@ -270,6 +384,14 @@ public class Commodore + return; + } + ++ // Paper start - Rewrite plugins ++ owner = getOriginalOrRewrite( owner) ; ++ if (desc != null) ++ { ++ desc = getOriginalOrRewrite(desc); ++ } ++ // Paper end ++ + if ( modern ) + { + if ( owner.equals( "org/bukkit/Material" ) ) diff --git a/patches/server-remapped/0293-Allow-setting-the-vex-s-summoner.patch b/patches/server-remapped/0293-Allow-setting-the-vex-s-summoner.patch new file mode 100644 index 0000000000..ee472ab644 --- /dev/null +++ b/patches/server-remapped/0293-Allow-setting-the-vex-s-summoner.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 6 Oct 2018 21:47:44 -0500 +Subject: [PATCH] Allow setting the vex's summoner + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java +index ec4f6d96360e759ffc19de838fdbf3027164a424..a4be2bddc5f51601d419647a280c89f7101371f2 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vex.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java +@@ -165,6 +165,7 @@ public class Vex extends Monster { + this.setVexFlag(1, charging); + } + ++ public void setOwner(Mob entityinsentient) { setOwner(entityinsentient); } // Paper - OBFHELPER + public void setOwner(Mob owner) { + this.owner = owner; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +index 56bec4350f36a94d4dfa71a234872a795c2dcb3f..07c470f8b049bea930337abc1cc87f4669d2f11a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +@@ -20,6 +20,10 @@ public class CraftVex extends CraftMonster implements Vex { + net.minecraft.world.entity.Mob owner = getHandle().getOwner(); + return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; + } ++ ++ public void setSummoner(org.bukkit.entity.Mob summoner) { ++ getHandle().setOwner(summoner == null ? null : ((CraftMob) summoner).getHandle()); ++ } + // Paper end + + @Override diff --git a/patches/server-remapped/0294-Add-sun-related-API.patch b/patches/server-remapped/0294-Add-sun-related-API.patch new file mode 100644 index 0000000000..32037c620c --- /dev/null +++ b/patches/server-remapped/0294-Add-sun-related-API.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 7 Oct 2018 00:54:21 -0500 +Subject: [PATCH] Add sun related API + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index f3690ea49cf90c816b8b3554b47d6f2d9dfbe016..29a2eeee9f2011ed6fcc44f19041f616decfdb38 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -1595,6 +1595,7 @@ public abstract class Mob extends LivingEntity { + + } + ++ public boolean isInDaylight() { return this.isSunBurnTick(); } // Paper - OBFHELPER + protected boolean isSunBurnTick() { + if (this.level.isDay() && !this.level.isClientSide) { + float f = this.getBrightness(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 57a2af56b53567371fdb6d0a55866e1e4e37cf3b..7b5abccac9793811bd56340c8f9d23806e832365 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -847,6 +847,13 @@ public class CraftWorld implements World { + } + } + ++ // Paper start ++ @Override ++ public boolean isDayTime() { ++ return getHandle().isDay(); ++ } ++ // Paper end ++ + @Override + public long getGameTime() { + return world.levelData.getGameTime(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +index b5fe55a77c8558cf2ea32689ff57911530df75f9..1e3a0851c75d8067d2699f00bb3f6621d1d739d8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +@@ -77,4 +77,11 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { + public long getSeed() { + return getHandle().lootTableSeed; + } ++ ++ // Paper start ++ @Override ++ public boolean isInDaylight() { ++ return getHandle().isInDaylight(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0295-Turtle-API.patch b/patches/server-remapped/0295-Turtle-API.patch new file mode 100644 index 0000000000..042449088a --- /dev/null +++ b/patches/server-remapped/0295-Turtle-API.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 29 Sep 2018 16:08:23 -0500 +Subject: [PATCH] Turtle API + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +index 4584fad16a65f06e77e97a0804d88dbe83f7c5c1..c8680e795deeb68e0662eac7c760a103d1c767b4 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +@@ -14,7 +14,7 @@ public abstract class MoveToBlockGoal extends Goal { + protected int nextStartTick; + protected int tryTicks; + private int maxStayTicks; +- protected BlockPos blockPos; ++ protected BlockPos blockPos;public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER + private boolean reachedTarget; + private final int searchRange; + private final int verticalSearchRange; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +index c54f4b83b9f2fdb15ddb363be0a179a05eb3693b..42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +@@ -14,6 +14,7 @@ import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; +@@ -93,7 +94,7 @@ public class Turtle extends Animal { + this.entityData.set(Turtle.HOME_POS, pos); + } + +- private BlockPos getHomePos() { ++ public BlockPos getHomePos() { // Paper - public + return (BlockPos) this.entityData.get(Turtle.HOME_POS); + } + +@@ -109,31 +110,37 @@ public class Turtle extends Animal { + return (Boolean) this.entityData.get(Turtle.HAS_EGG); + } + +- private void setHasEgg(boolean hasEgg) { ++ public void setHasEgg(boolean hasEgg) { // Paper + this.entityData.set(Turtle.HAS_EGG, hasEgg); + } + ++ public final boolean isDigging() { return this.isLayingEgg(); } // Paper - OBFHELPER + public boolean isLayingEgg() { + return (Boolean) this.entityData.get(Turtle.LAYING_EGG); + } + ++ public final void setDigging(boolean digging) { this.setLayingEgg(digging); } // Paper - OBFHELPER + private void setLayingEgg(boolean diggingSand) { + this.layEggCounter = diggingSand ? 1 : 0; + this.entityData.set(Turtle.LAYING_EGG, diggingSand); + } + ++ public final boolean isGoingHome() { return this.isGoingHome(); } // Paper - OBFHELPER + private boolean isGoingHome() { + return (Boolean) this.entityData.get(Turtle.GOING_HOME); + } + ++ public final void setGoingHome(boolean goingHome) { this.setGoingHome(goingHome); } // Paper - OBFHELPER + private void setGoingHome(boolean landBound) { + this.entityData.set(Turtle.GOING_HOME, landBound); + } + ++ public final boolean isTravelling() { return this.isTravelling(); } // Paper - OBFHELPER + private boolean isTravelling() { + return (Boolean) this.entityData.get(Turtle.TRAVELLING); + } + ++ public final void setTravelling(boolean travelling) { this.setTravelling(travelling); } // Paper - OBFHELPER + private void setTravelling(boolean travelling) { + this.entityData.set(Turtle.TRAVELLING, travelling); + } +@@ -500,14 +507,17 @@ public class Turtle extends Animal { + + if (!this.turtle.isInWater() && this.isReachedTarget()) { + if (this.turtle.layEggCounter < 1) { +- this.turtle.setLayingEgg(true); ++ this.turtle.setDigging(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), MCUtil.toLocation(this.turtle.level, this.getTargetPosition())).callEvent()); // Paper + } else if (this.turtle.layEggCounter > 200) { + Level world = this.turtle.level; + + // CraftBukkit start +- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1)).isCancelled()) { ++ // Paper start ++ int eggCount = this.turtle.random.nextInt(4) + 1; ++ com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), MCUtil.toLocation(this.turtle.level, this.blockPos.above()), eggCount); ++ if (layEggEvent.callEvent() && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount())).isCancelled()) { + world.playSound((Player) null, blockposition, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); +- world.setBlock(this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1), 3); ++ world.setBlock(this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()), 3); + } + // CraftBukkit end + this.turtle.setHasEgg(false); +@@ -636,7 +646,7 @@ public class Turtle extends Animal { + + @Override + public boolean canUse() { +- return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(700) != 0 ? false : !this.turtle.getHomePos().closerThan((Position) this.turtle.position(), 64.0D))); ++ return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(700) != 0 ? false : !this.turtle.getHomePos().closerThan((Position) this.turtle.position(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity()).callEvent(); // Paper + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java +index ed08089f21c8958fc9fc7e6e73a2b6ff9108242c..e50f6051baf34981707adce56ab2d3e1f341fb4c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java +@@ -24,4 +24,36 @@ public class CraftTurtle extends CraftAnimals implements Turtle { + public EntityType getType() { + return EntityType.TURTLE; + } ++ ++ // Paper start ++ @Override ++ public org.bukkit.Location getHome() { ++ return net.minecraft.server.MCUtil.toLocation(getHandle().level, getHandle().getHomePos()); ++ } ++ ++ @Override ++ public void setHome(org.bukkit.Location location) { ++ getHandle().setHomePos(net.minecraft.server.MCUtil.toBlockPosition(location)); ++ } ++ ++ @Override ++ public boolean isGoingHome() { ++ return getHandle().isGoingHome(); ++ } ++ ++ @Override ++ public boolean isDigging() { ++ return getHandle().isDigging(); ++ } ++ ++ @Override ++ public boolean hasEgg() { ++ return getHandle().hasEgg(); ++ } ++ ++ @Override ++ public void setHasEgg(boolean hasEgg) { ++ getHandle().setHasEgg(hasEgg); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/patches/server-remapped/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch new file mode 100644 index 0000000000..685d458bbb --- /dev/null +++ b/patches/server-remapped/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 17 Oct 2018 19:17:27 -0400 +Subject: [PATCH] MC-50319: Check other worlds for shooter of projectiles + +Say a player shoots an arrow through a nether portal, the game +would lose the shooter for determining things such as Player Kills, +because the entity is in another world. + +If the projectile fails to find the shooter in the current world, check +other worlds. + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index d1dd173c11d751b15c3afd4309e386931fd9cf8d..d385fb6eee5000951c350b6ced5669dc3dcce725 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -44,7 +44,18 @@ public abstract class Projectile extends Entity { + + @Nullable + public Entity getOwner() { +- return this.ownerUUID != null && this.level instanceof ServerLevel ? ((ServerLevel) this.level).getEntity(this.ownerUUID) : (this.ownerNetworkId != 0 ? this.level.getEntity(this.ownerNetworkId) : null); ++ // Paper start - MC-50319 - shooter might be in another world (arrows through portals) ++ Entity entity = this.ownerUUID != null && this.level instanceof ServerLevel ? ((ServerLevel) this.level).getEntity(this.ownerUUID) : (this.ownerNetworkId != 0 ? this.level.getEntity(this.ownerNetworkId) : null); ++ if (entity == null) { ++ for (ServerLevel world : level.getServer().getAllLevels()) { ++ entity = world.getEntity(this.ownerUUID); ++ if (entity != null) { ++ break; ++ } ++ } ++ } ++ return entity; ++ // Paper end + } + + @Override diff --git a/patches/server-remapped/0297-Call-player-spectator-target-events-and-improve-impl.patch b/patches/server-remapped/0297-Call-player-spectator-target-events-and-improve-impl.patch new file mode 100644 index 0000000000..4b6ccafcaa --- /dev/null +++ b/patches/server-remapped/0297-Call-player-spectator-target-events-and-improve-impl.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Caleb Bassham +Date: Fri, 28 Sep 2018 02:32:19 -0500 +Subject: [PATCH] Call player spectator target events and improve + implementation + +Use a proper teleport for teleporting to entities in different +worlds. + +Implementation improvements authored by Spottedleaf +Validate that the target entity is valid and deny spectate +requests from frozen players. + +Also, make sure the entity is spawned to the client before +sending the camera packet. If the entity isn't spawned clientside +when it receives the camera packet, then the client will not +spectate the target entity. + +Co-authored-by: Spottedleaf + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 75419c866641ab654349cde6ca3fbdef701dd8d9..92139b271eb6c305787662ef8c7d221fb42296f7 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1818,14 +1818,58 @@ public class ServerPlayer extends Player implements ContainerListener { + } + + public void setCamera(Entity entity) { ++ // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event and improve implementation + Entity entity1 = this.getCamera(); + +- this.camera = (Entity) (entity == null ? this : entity); +- if (entity1 != this.camera) { +- this.connection.send(new ClientboundSetCameraPacket(this.camera)); +- this.connection.a(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.yRot, this.xRot, TeleportCause.SPECTATE); // CraftBukkit ++ if (entity == null) { ++ entity = this; + } + ++ if (entity1 == entity) return; // new spec target is the current spec target ++ ++ if (entity == this) { ++ com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent playerStopSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity()); ++ ++ if (!playerStopSpectatingEntityEvent.callEvent()) { ++ return; ++ } ++ } else { ++ com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent playerStartSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity(), entity.getBukkitEntity()); ++ ++ if (!playerStartSpectatingEntityEvent.callEvent()) { ++ return; ++ } ++ } ++ // Validate ++ if (entity != this) { ++ if (entity.removed || entity.shouldBeRemoved || !entity.valid || entity.level == null) { ++ MinecraftServer.LOGGER.info("Blocking player " + this.toString() + " from spectating invalid entity " + entity.toString()); ++ return; ++ } ++ if (this.isImmobile()) { ++ // use debug: clients might maliciously spam this ++ MinecraftServer.LOGGER.debug("Blocking frozen player " + this.toString() + " from spectating entity " + entity.toString()); ++ return; ++ } ++ } ++ ++ this.camera = entity; // only set after validating state ++ ++ if (entity != this) { ++ // Make sure we're in the right place ++ this.ejectPassengers(); // teleport can fail if we have passengers... ++ this.getBukkitEntity().teleport(new Location(entity.getCommandSenderWorld().getWorld(), entity.getX(), entity.getY(), entity.getZ(), this.yRot, this.xRot), TeleportCause.SPECTATE); // Correctly handle cross-world entities from api calls by using CB teleport ++ ++ // Make sure we're tracking the entity before sending ++ ChunkMap.TrackedEntity tracker = ((ServerLevel)entity.level).getChunkSource().chunkMap.entityMap.get(entity.getId()); ++ if (tracker != null) { // dumb plugins... ++ tracker.updatePlayer(this); ++ } ++ } else { ++ this.connection.teleport(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.yRot, this.xRot, TeleportCause.SPECTATE); // CraftBukkit ++ } ++ this.connection.send(new ClientboundSetCameraPacket(entity)); ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 900c9b1106a153bc386f6c3d9c11226f8ac69f86..4fd8d775790c037e82f9b0d29ed0eccf03c2dc66 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1353,6 +1353,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + + // CraftBukkit start - Delegate to teleport(Location) ++ public final void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { this.a(d0, d1, d2, f, f1, cause); } // Paper - OBFHELPER + public void a(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { + this.a(d0, d1, d2, f, f1, Collections.emptySet(), cause); + } diff --git a/patches/server-remapped/0298-Add-Velocity-IP-Forwarding-Support.patch b/patches/server-remapped/0298-Add-Velocity-IP-Forwarding-Support.patch new file mode 100644 index 0000000000..f1b44575c0 --- /dev/null +++ b/patches/server-remapped/0298-Add-Velocity-IP-Forwarding-Support.patch @@ -0,0 +1,303 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Mon, 8 Oct 2018 14:36:14 -0400 +Subject: [PATCH] Add Velocity IP Forwarding Support + +While Velocity supports BungeeCord-style IP forwarding, it is not secure. Users +have a lot of problems setting up firewalls or setting up plugins like IPWhitelist. +Further, the BungeeCord IP forwarding protocol still retains essentially its original +form, when there is brand new support for custom login plugin messages in 1.13. + +Velocity's modern IP forwarding uses an HMAC-SHA256 code to ensure authenticity +of messages, is packed into a binary format that is smaller than BungeeCord's +forwarding, and is integrated into the Minecraft login process by using the 1.13 +login plugin message packet. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 7178b37f7978c7e9031a22726005c5099fd78fe0..3139c194f9b1bc3510d51a81f13ae43d00a3dc29 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -8,6 +8,7 @@ import java.io.IOException; + import java.lang.reflect.InvocationTargetException; + import java.lang.reflect.Method; + import java.lang.reflect.Modifier; ++import java.nio.charset.StandardCharsets; + import java.util.HashMap; + import java.util.List; + import java.util.Map; +@@ -252,7 +253,7 @@ public class PaperConfig { + } + + public static boolean isProxyOnlineMode() { +- return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); ++ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode) || (velocitySupport && velocityOnlineMode); + } + + public static int packetInSpamThreshold = 300; +@@ -324,4 +325,18 @@ public class PaperConfig { + } + tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); + } ++ ++ public static boolean velocitySupport; ++ public static boolean velocityOnlineMode; ++ public static byte[] velocitySecretKey; ++ private static void velocitySupport() { ++ velocitySupport = getBoolean("settings.velocity-support.enabled", false); ++ velocityOnlineMode = getBoolean("settings.velocity-support.online-mode", false); ++ String secret = getString("settings.velocity-support.secret", ""); ++ if (velocitySupport && secret.isEmpty()) { ++ fatal("Velocity support is enabled, but no secret key was specified. A secret key is required!"); ++ } else { ++ velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5490ddb9f2ff1fc3e6088e703c246a06594076bc +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java +@@ -0,0 +1,66 @@ ++package com.destroystokyo.paper.proxy; ++ ++import com.destroystokyo.paper.PaperConfig; ++import com.google.common.net.InetAddresses; ++import com.mojang.authlib.GameProfile; ++import com.mojang.authlib.properties.Property; ++import java.net.InetAddress; ++import java.security.InvalidKeyException; ++import java.security.MessageDigest; ++import java.security.NoSuchAlgorithmException; ++ ++import javax.crypto.Mac; ++import javax.crypto.spec.SecretKeySpec; ++import net.minecraft.network.FriendlyByteBuf; ++import net.minecraft.resources.ResourceLocation; ++ ++public class VelocityProxy { ++ private static final int SUPPORTED_FORWARDING_VERSION = 1; ++ public static final ResourceLocation PLAYER_INFO_CHANNEL = new ResourceLocation("velocity", "player_info"); ++ ++ public static boolean checkIntegrity(final FriendlyByteBuf buf) { ++ final byte[] signature = new byte[32]; ++ buf.readBytes(signature); ++ ++ final byte[] data = new byte[buf.readableBytes()]; ++ buf.getBytes(buf.readerIndex(), data); ++ ++ try { ++ final Mac mac = Mac.getInstance("HmacSHA256"); ++ mac.init(new SecretKeySpec(PaperConfig.velocitySecretKey, "HmacSHA256")); ++ final byte[] mySignature = mac.doFinal(data); ++ if (!MessageDigest.isEqual(signature, mySignature)) { ++ return false; ++ } ++ } catch (final InvalidKeyException | NoSuchAlgorithmException e) { ++ throw new AssertionError(e); ++ } ++ ++ int version = buf.readVarInt(); ++ if (version != SUPPORTED_FORWARDING_VERSION) { ++ throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted " + SUPPORTED_FORWARDING_VERSION); ++ } ++ ++ return true; ++ } ++ ++ public static InetAddress readAddress(final FriendlyByteBuf buf) { ++ return InetAddresses.forString(buf.readUTF(Short.MAX_VALUE)); ++ } ++ ++ public static GameProfile createProfile(final FriendlyByteBuf buf) { ++ final GameProfile profile = new GameProfile(buf.readUUID(), buf.readUTF(16)); ++ readProperties(buf, profile); ++ return profile; ++ } ++ ++ private static void readProperties(final FriendlyByteBuf buf, final GameProfile profile) { ++ final int properties = buf.readVarInt(); ++ for (int i1 = 0; i1 < properties; i1++) { ++ final String name = buf.readUTF(Short.MAX_VALUE); ++ final String value = buf.readUTF(Short.MAX_VALUE); ++ final String signature = buf.readBoolean() ? buf.readUTF(Short.MAX_VALUE) : null; ++ profile.getProperties().put(name, new Property(name, value, signature)); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index 10f1e3d761af83507bf71a00092641e22d0c8049..a295845409824b930992426451ef26856d6e7c36 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -191,6 +191,7 @@ public class FriendlyByteBuf extends ByteBuf { + return this.writeVarInt(oenum.ordinal()); + } + ++ public int readVarInt() { return readVarInt(); } // Paper - OBFHELPER + public int readVarInt() { + int i = 0; + int j = 0; +@@ -231,6 +232,7 @@ public class FriendlyByteBuf extends ByteBuf { + return this; + } + ++ public UUID readUUID() { return readUUID(); } // Paper - OBFHELPER + public UUID readUUID() { + return new UUID(this.readLong(), this.readLong()); + } +@@ -358,6 +360,7 @@ public class FriendlyByteBuf extends ByteBuf { + } + } + ++ public String readUTF(int maxLength) { return this.readUtf(maxLength); } // Paper - OBFHELPER + public String readUtf(int i) { + int j = this.readVarInt(); + +diff --git a/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java b/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java +index 8a0301cc4a411c4f9384331d68794ca73b797f5f..88a63635d73983afe58406c66f4ea81cd823c627 100644 +--- a/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java +@@ -13,6 +13,14 @@ public class ClientboundCustomQueryPacket implements Packet { + +- private int transactionId; +- private FriendlyByteBuf data; ++ private int transactionId; public int getId() { return transactionId; } // Paper - OBFHELPER ++ private FriendlyByteBuf data; public FriendlyByteBuf getBuf() { return data; } // Paper - OBFHELPER + + public ServerboundCustomQueryPacket() {} + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 0aa3a154d68f00edcc09b947a24b2b59b1e135e6..22d6f41001977917ec75046252cbf7157b92396d 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -18,9 +18,11 @@ import javax.crypto.Cipher; + import javax.crypto.SecretKey; + import net.minecraft.DefaultUncaughtExceptionHandler; + import net.minecraft.network.Connection; ++import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.chat.TranslatableComponent; ++import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; + import net.minecraft.network.protocol.login.ClientboundGameProfilePacket; + import net.minecraft.network.protocol.login.ClientboundHelloPacket; + import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; +@@ -43,6 +45,7 @@ import org.bukkit.craftbukkit.util.Waitable; + import org.bukkit.event.player.AsyncPlayerPreLoginEvent; + import org.bukkit.event.player.PlayerPreLoginEvent; + // CraftBukkit end ++import io.netty.buffer.Unpooled; // Paper + + public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener { + +@@ -59,6 +62,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + private SecretKey secretKey; + private ServerPlayer delayedAcceptPlayer; + public String hostname = ""; // CraftBukkit - add field ++ private int velocityLoginMessageId = -1; // Paper - Velocity support + + public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection) { + this.state = ServerLoginPacketListenerImpl.State.HELLO; +@@ -211,6 +215,14 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + this.state = ServerLoginPacketListenerImpl.State.KEY; + this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce)); + } else { ++ // Paper start - Velocity support ++ if (com.destroystokyo.paper.PaperConfig.velocitySupport) { ++ this.velocityLoginMessageId = java.util.concurrent.ThreadLocalRandom.current().nextInt(); ++ ClientboundCustomQueryPacket packet1 = new ClientboundCustomQueryPacket(this.velocityLoginMessageId, com.destroystokyo.paper.proxy.VelocityProxy.PLAYER_INFO_CHANNEL, new FriendlyByteBuf(Unpooled.EMPTY_BUFFER)); ++ this.connection.send(packet1); ++ return; ++ } ++ // Paper end + // Spigot start + // Paper start - Cache authenticator threads + authenticatorPool.execute(new Runnable() { +@@ -312,6 +324,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + public class LoginHandler { + + public void fireEvents() throws Exception { ++ // Paper start - Velocity support ++ if (ServerLoginPacketListenerImpl.this.velocityLoginMessageId == -1 && com.destroystokyo.paper.PaperConfig.velocitySupport) { ++ disconnect("This server requires you to connect with Velocity."); ++ return; ++ } ++ // Paper end + String playerName = gameProfile.getName(); + java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); + java.util.UUID uniqueId = gameProfile.getId(); +@@ -359,6 +377,40 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + // Spigot end + + public void handleCustomQueryPacket(ServerboundCustomQueryPacket packet) { ++ // Paper start - Velocity support ++ if (com.destroystokyo.paper.PaperConfig.velocitySupport && packet.getId() == this.velocityLoginMessageId) { ++ FriendlyByteBuf buf = packet.getBuf(); ++ if (buf == null) { ++ this.disconnect("This server requires you to connect with Velocity."); ++ return; ++ } ++ ++ if (!com.destroystokyo.paper.proxy.VelocityProxy.checkIntegrity(buf)) { ++ this.disconnect("Unable to verify player details"); ++ return; ++ } ++ ++ java.net.SocketAddress listening = this.connection.getRemoteAddress(); ++ int port = 0; ++ if (listening instanceof java.net.InetSocketAddress) { ++ port = ((java.net.InetSocketAddress) listening).getPort(); ++ } ++ this.connection.address = new java.net.InetSocketAddress(com.destroystokyo.paper.proxy.VelocityProxy.readAddress(buf), port); ++ ++ this.setGameProfile(com.destroystokyo.paper.proxy.VelocityProxy.createProfile(buf)); ++ ++ // Proceed with login ++ authenticatorPool.execute(() -> { ++ try { ++ new LoginHandler().fireEvents(); ++ } catch (Exception ex) { ++ disconnect("Failed to verify username!"); ++ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + gameProfile.getName(), ex); ++ } ++ }); ++ return; ++ } ++ // Paper end + this.disconnect(new TranslatableComponent("multiplayer.disconnect.unexpected_query_response")); + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 5e36d705c56384f507fd85f704eae634379a27f1..c06b35f114a8d243198b66c44ef57d8c2b201361 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -680,7 +680,7 @@ public final class CraftServer implements Server { + @Override + public long getConnectionThrottle() { + // Spigot Start - Automatically set connection throttle for bungee configurations +- if (org.spigotmc.SpigotConfig.bungee) { ++ if (org.spigotmc.SpigotConfig.bungee || com.destroystokyo.paper.PaperConfig.velocitySupport) { // Paper - Velocity support + return -1; + } else { + return this.configuration.getInt("settings.connection-throttle"); diff --git a/patches/server-remapped/0299-Add-more-Witch-API.patch b/patches/server-remapped/0299-Add-more-Witch-API.patch new file mode 100644 index 0000000000..099a0f9cff --- /dev/null +++ b/patches/server-remapped/0299-Add-more-Witch-API.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 12 Oct 2018 14:10:46 -0500 +Subject: [PATCH] Add more Witch API + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java +index a37ee32b46aa87be6e3eeca2892b4e7294fd1aef..bc9380782c2afba359852542837e7154c4c6cf8b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java +@@ -1,5 +1,8 @@ + package net.minecraft.world.entity.monster; + ++// Paper start ++import com.destroystokyo.paper.event.entity.WitchReadyPotionEvent; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; + import java.util.Iterator; + import java.util.List; + import java.util.UUID; +@@ -49,7 +52,7 @@ public class Witch extends Raider implements RangedAttackMob { + private static final UUID SPEED_MODIFIER_DRINKING_UUID = UUID.fromString("5CD17E52-A79A-43D3-A529-90FDE04B181E"); + private static final AttributeModifier SPEED_MODIFIER_DRINKING = new AttributeModifier(Witch.SPEED_MODIFIER_DRINKING_UUID, "Drinking speed penalty", -0.25D, AttributeModifier.Operation.ADDITION); + private static final EntityDataAccessor DATA_USING_ITEM = SynchedEntityData.defineId(Witch.class, EntityDataSerializers.BOOLEAN); +- private int usingTime; ++ private int usingTime; public int getPotionUseTimeLeft() { return usingTime; } public void setPotionUseTimeLeft(int timeLeft) { usingTime = timeLeft; } // Paper - OBFHELPER + private NearestHealableRaiderTargetGoal healRaidersGoal; + private NearestAttackableWitchTargetGoal attackPlayersGoal; + +@@ -95,10 +98,12 @@ public class Witch extends Raider implements RangedAttackMob { + return SoundEvents.WITCH_DEATH; + } + ++ public void setDrinkingPotion(boolean drinkingPotion) { setUsingItem(drinkingPotion); } // Paper - OBFHELPER + public void setUsingItem(boolean drinking) { + this.getEntityData().set(Witch.DATA_USING_ITEM, drinking); + } + ++ public boolean isDrinkingPotion() { return isDrinkingPotion(); } // Paper - OBFHELPER + public boolean isDrinkingPotion() { + return (Boolean) this.getEntityData().get(Witch.DATA_USING_ITEM); + } +@@ -157,21 +162,24 @@ public class Witch extends Raider implements RangedAttackMob { + } + + if (potionregistry != null) { +- // Paper start + ItemStack potion = PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry); +- org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); +- this.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++ // Paper start - logic moved into setDrinkingPotion, copy exact impl into the method and then comment out ++ this.setDrinkingPotion(potion); ++// org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++// this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++// // Paper end ++// this.bq = this.getItemInMainHand().k(); ++// this.v(true); ++// if (!this.isSilent()) { ++// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); ++// } ++// ++// AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); ++// ++// attributemodifiable.removeModifier(EntityWitch.bo); ++// attributemodifiable.b(EntityWitch.bo); + // Paper end +- this.usingTime = this.getMainHandItem().getUseDuration(); +- this.setUsingItem(true); +- if (!this.isSilent()) { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); +- } +- +- AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING); +- attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); + } + } + +@@ -183,6 +191,24 @@ public class Witch extends Raider implements RangedAttackMob { + super.aiStep(); + } + ++ // Paper start - moved to its own method ++ public void setDrinkingPotion(ItemStack potion) { ++ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++ this.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++ // Paper end ++ this.usingTime = this.getMainHandItem().getUseDuration(); ++ this.setUsingItem(true); ++ if (!this.isSilent()) { ++ this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); ++ } ++ ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING); ++ attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); ++ } ++ // Paper end ++ + @Override + public SoundEvent getCelebrateSound() { + return SoundEvents.WITCH_CELEBRATE; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +index d4eeb071dbbfca3ecea256228853bcb5c11f49ee..bb40b5af0f2a6a971f78350394099e3a48d5d04a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +@@ -3,6 +3,13 @@ package org.bukkit.craftbukkit.entity; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Witch; ++// Paper start ++import com.destroystokyo.paper.entity.CraftRangedEntity; ++import com.google.common.base.Preconditions; ++import org.bukkit.Material; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.inventory.ItemStack; ++// Paper end + + public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftWitch(CraftServer server, net.minecraft.world.entity.monster.Witch entity) { +@@ -23,4 +30,28 @@ public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo. + public EntityType getType() { + return EntityType.WITCH; + } ++ ++ // Paper start ++ public boolean isDrinkingPotion() { ++ return getHandle().isDrinkingPotion(); ++ } ++ ++ public int getPotionUseTimeLeft() { ++ return getHandle().getPotionUseTimeLeft(); ++ } ++ ++ @Override ++ public void setPotionUseTimeLeft(int ticks) { ++ getHandle().setPotionUseTimeLeft(ticks); ++ } ++ ++ public ItemStack getDrinkingPotion() { ++ return CraftItemStack.asCraftMirror(getHandle().getMainHandItem()); ++ } ++ ++ public void setDrinkingPotion(ItemStack potion) { ++ Preconditions.checkArgument(potion == null || potion.getType().isEmpty() || potion.getType() == Material.POTION, "must be potion, air, or null"); ++ getHandle().setDrinkingPotion(CraftItemStack.asNMSCopy(potion)); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0300-Check-Drowned-for-Villager-Aggression-Config.patch b/patches/server-remapped/0300-Check-Drowned-for-Villager-Aggression-Config.patch new file mode 100644 index 0000000000..cbace85cba --- /dev/null +++ b/patches/server-remapped/0300-Check-Drowned-for-Villager-Aggression-Config.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Wed, 10 Oct 2018 21:22:44 -0500 +Subject: [PATCH] Check Drowned for Villager Aggression Config + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java +index cc9cd34f77e1f568572f312655fb2fe8e83bd733..0addfd6a1421fc99840d9229bad3ba04e524317b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java +@@ -82,7 +82,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D)); + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Drowned.class})).setAlertOthers(ZombifiedPiglin.class)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::okTarget)); +- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); ++ if ( level.spigotConfig.zombieAggressiveTowardsVillager ) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Paper + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); + this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); + } diff --git a/patches/server-remapped/0301-Here-s-Johnny.patch b/patches/server-remapped/0301-Here-s-Johnny.patch new file mode 100644 index 0000000000..e6a6846d1e --- /dev/null +++ b/patches/server-remapped/0301-Here-s-Johnny.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 12 Oct 2018 01:37:22 -0500 +Subject: [PATCH] Here's Johnny! + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +index a41f61daf6cbbb13d0b86cdbad8a4cae00368653..623de661f3b56062792e3a7dbc508637aa58aca5 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +@@ -51,7 +51,7 @@ public class Vindicator extends AbstractIllager { + private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { + return enumdifficulty == Difficulty.NORMAL || enumdifficulty == Difficulty.HARD; + }; +- private boolean isJohnny; ++ private boolean isJohnny; public boolean isJohnny() { return isJohnny; } public void setJohnny(boolean johnny) { isJohnny = johnny; } // Paper - OBFHELPER + + public Vindicator(EntityType type, Level world) { + super(type, world); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java +index 3c5994e9862e5caa257ee6a21f8fba2df39c98c5..6c1569340317f7bed39eaf6e858d602234993eb3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java +@@ -24,4 +24,14 @@ public class CraftVindicator extends CraftIllager implements Vindicator { + public EntityType getType() { + return EntityType.VINDICATOR; + } ++ ++ // Paper start ++ public boolean isJohnny() { ++ return getHandle().isJohnny(); ++ } ++ ++ public void setJohnny(boolean johnny) { ++ getHandle().setJohnny(johnny); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch b/patches/server-remapped/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch new file mode 100644 index 0000000000..565724bd30 --- /dev/null +++ b/patches/server-remapped/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gabriele C +Date: Mon, 22 Oct 2018 17:34:10 +0200 +Subject: [PATCH] Add option to prevent players from moving into unloaded + chunks #1551 + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index f280dbff4a09bc611a9ca565c6d697d08801f53b..fbf3ccfb347a5ba6e895339e9576629d940d1aa4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -396,4 +396,9 @@ public class PaperWorldConfig { + waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); + log("Water over lava flow speed: " + waterOverLavaFlowSpeed); + } ++ ++ public boolean preventMovingIntoUnloadedChunks = false; ++ private void preventMovingIntoUnloadedChunks() { ++ preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 4fd8d775790c037e82f9b0d29ed0eccf03c2dc66..b5593300516fad767f603084aca4abcda4424db3 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -541,6 +541,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + speed *= 2f; // TODO: Get the speed of the vehicle instead of the player + ++ // Paper start - Prevent moving into unloaded chunks ++ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && worldserver.getChunkIfLoadedImmediately((int) Math.floor(packet.getX()) >> 4, (int) Math.floor(packet.getZ()) >> 4) == null) { ++ this.connection.send(new ClientboundMoveVehiclePacket(entity)); ++ return; ++ } ++ // Paper end ++ + if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { + // CraftBukkit end + ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getName().getString(), this.player.getName().getString(), d6, d7, d8); +@@ -1139,9 +1146,9 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + double d1 = this.player.getY(); + double d2 = this.player.getZ(); + double d3 = this.player.getY(); +- double d4 = packet.getX(this.player.getX()); ++ double d4 = packet.getX(this.player.getX());double toX = d4; // Paper - OBFHELPER + double d5 = packet.getY(this.player.getY()); +- double d6 = packet.getZ(this.player.getZ()); ++ double d6 = packet.getZ(this.player.getZ());double toZ = d6; // Paper - OBFHELPER + float f = packet.getYRot(this.player.yRot); + float f1 = packet.getXRot(this.player.xRot); + double d7 = d4 - this.firstGoodX; +@@ -1180,6 +1187,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } else { + speed = player.abilities.walkingSpeed * 10f; + } ++ // Paper start - Prevent moving into unloaded chunks ++ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.hasChunk((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { ++ this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.yRot, this.player.xRot, Collections.emptySet()); ++ return; ++ } ++ // Paper end + + if (!this.player.isChangingDimension() && (!this.player.getLevel().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying())) { + float f2 = this.player.isFallFlying() ? 300.0F : 100.0F; diff --git a/patches/server-remapped/0303-Reset-players-airTicks-on-respawn.patch b/patches/server-remapped/0303-Reset-players-airTicks-on-respawn.patch new file mode 100644 index 0000000000..b3525e04cd --- /dev/null +++ b/patches/server-remapped/0303-Reset-players-airTicks-on-respawn.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: GreenMeanie +Date: Sat, 20 Oct 2018 22:34:02 -0400 +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 92139b271eb6c305787662ef8c7d221fb42296f7..b68acf219fc61e2ea811d0c732393824fa44db2d 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -2159,6 +2159,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + + this.setHealth(this.getMaxHealth()); ++ this.setAirSupply(this.getMaxAirTicks()); // Paper + this.remainingFireTicks = 0; + this.fallDistance = 0; + this.foodData = new FoodData(this); +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index e7fed1f8bb8ffb164ddcdab51f41c369d6e3103d..460c6fd61bb45247715d99445821e15e98e4c465 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2354,6 +2354,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + } + ++ public final int getMaxAirTicks() { return getMaxAirSupply(); } // Paper - OBFHELPER + public int getMaxAirSupply() { + return 300; + } diff --git a/patches/server-remapped/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch b/patches/server-remapped/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch new file mode 100644 index 0000000000..01be147e24 --- /dev/null +++ b/patches/server-remapped/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 23 Oct 2018 20:25:05 -0400 +Subject: [PATCH] Don't sleep after profile lookups if not needed + +Mojang was sleeping even if we had no more requests to go after +the current one finished, resulting in 100ms lost per profile lookup + +diff --git a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java +index a3ab666b5fa89aad7ee167d9aeff2f62019a4a78..8e182fdd69dba6e1c52e2f6a893534d77fb3bfaa 100644 +--- a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java ++++ b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java +@@ -43,6 +43,7 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { + } + + final int page = 0; ++ boolean hasRequested = false; // Paper + + for (final List request : Iterables.partition(criteria, ENTRIES_PER_PAGE)) { + int failCount = 0; +@@ -68,6 +69,12 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { + LOGGER.debug("Couldn't find profile {}", name); + callback.onProfileLookupFailed(new GameProfile(null, name), new ProfileNotFoundException("Server did not find the requested profile")); + } ++ // Paper start ++ if (!hasRequested) { ++ hasRequested = true; ++ continue; ++ } ++ // Paper end + + try { + Thread.sleep(DELAY_BETWEEN_PAGES); diff --git a/patches/server-remapped/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/patches/server-remapped/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch new file mode 100644 index 0000000000..04594148fc --- /dev/null +++ b/patches/server-remapped/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 23 Oct 2018 23:14:38 -0400 +Subject: [PATCH] Improve Server Thread Pool and Thread Priorities + +Use a simple executor since Fork join is a much more complex pool +type and we are not using its capabilities. + +Set thread priorities so main thread has above normal priority over +server threads + +Allow usage of a single thread executor by not using ForkJoin so single core CPU's. + +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index 7b36274718b7cce24ac00530697f145648d52590..cec5ad5052c8cf6059e9b117117846bdb217748f 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -45,7 +45,7 @@ import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.Bootstrap; +-import net.minecraft.util.Mth; ++import net.minecraft.server.ServerWorkerThread; + import net.minecraft.util.datafix.DataFixers; + import net.minecraft.world.level.block.state.properties.Property; + import org.apache.logging.log4j.LogManager; +@@ -54,8 +54,8 @@ import org.apache.logging.log4j.Logger; + public class Util { + + private static final AtomicInteger WORKER_COUNT = new AtomicInteger(1); +- private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap"); +- private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main"); ++ private static final ExecutorService BOOTSTRAP_EXECUTOR = a("Bootstrap", -2); // Paper - add -2 priority ++ private static final ExecutorService BACKGROUND_EXECUTOR = a("Main", -1); // Paper - add -1 priority + private static final ExecutorService IO_POOL = makeIoExecutor(); + public static LongSupplier timeSource = System::nanoTime; + public static final UUID NIL_UUID = new UUID(0L, 0L); public static final UUID getNullUUID() {return NIL_UUID;} // Paper OBFHELPER +@@ -85,30 +85,34 @@ public class Util { + return Instant.now().toEpochMilli(); + } + +- private static ExecutorService makeExecutor(String name) { +- int i = Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, 7); +- Object object; ++ private static ExecutorService a(String s, int priorityModifier) { // Paper - add priority ++ // Paper start - use simpler thread pool that allows 1 thread ++ int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1)); ++ i = Integer.getInteger("Paper.WorkerThreadCount", i); ++ ExecutorService object; + + if (i <= 0) { + object = MoreExecutors.newDirectExecutorService(); + } else { +- object = new ForkJoinPool(i, (forkjoinpool) -> { +- ForkJoinWorkerThread forkjoinworkerthread = new ForkJoinWorkerThread(forkjoinpool) { ++ object = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue(), target -> new ServerWorkerThread(target, s, priorityModifier)); ++ } ++ /* + protected void onTermination(Throwable throwable) { + if (throwable != null) { +- Util.LOGGER.warn("{} died", this.getName(), throwable); ++ SystemUtils.LOGGER.warn("{} died", this.getName(), throwable); + } else { +- Util.LOGGER.debug("{} shutdown", this.getName()); ++ SystemUtils.LOGGER.debug("{} shutdown", this.getName()); + } + + super.onTermination(throwable); + } + }; + +- forkjoinworkerthread.setName("Worker-" + name + "-" + Util.WORKER_COUNT.getAndIncrement()); ++ forkjoinworkerthread.setName("Worker-" + s + "-" + SystemUtils.c.getAndIncrement()); + return forkjoinworkerthread; +- }, Util::onThreadException, true); ++ }, SystemUtils::a, true); + } ++ }*/ // Paper end + + return (ExecutorService) object; + } +@@ -157,6 +161,7 @@ public class Util { + }); + } + ++ public static void onThreadError(Thread thread, Throwable throwable) { onThreadException(thread, throwable); } // Paper - OBFHELPER + private static void onThreadException(Thread thread, Throwable throwable) { + pauseInIde(throwable); + if (throwable instanceof CompletionException) { +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 5a76ca77b974ff6fe862c9e05a88b507a34b44be..5faa8f3cc251b6687e33e40009db98d2aee48f2c 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -284,6 +284,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Fri, 2 Nov 2018 23:11:51 -0400 +Subject: [PATCH] Optimize World Time Updates + +Splits time updates into incremental updates as well as does +the updates per world, so that we can re-use the same packet +object for every player unless they have per-player time enabled. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 5faa8f3cc251b6687e33e40009db98d2aee48f2c..6ccc0be795e3ac7689de0eff6f9142d13161a29c 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1314,12 +1314,24 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Mon, 5 Nov 2018 04:23:51 +0000 +Subject: [PATCH] Restore custom InventoryHolder support + +Upstream removed the ability to consistently use a custom InventoryHolder, +However, the implementation does not use an InventoryHolder in any form +outside of custom inventories. + +We can take that knowledge and apply some expected behavior, if we're given +an inventory holder, we should use it and return a custom inventory with the +holder, otherwise, create an inventory backed by the intended inventory, as +per upstream behavior. + +This provides a "best of both worlds" scenario: plugins with InventoryHolder's +will always work as intended in the past, those without will create implementation +based inventories. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +index 94d807c5d09f165c6eedd0a1c4026c2b833806a0..3e56de295be0d03dddd3e54fcd7b05d4b9c74dc4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +@@ -40,6 +40,11 @@ public final class CraftInventoryCreator { + } + + public Inventory createInventory(InventoryHolder holder, InventoryType type) { ++ // Paper start ++ if (holder != null) { ++ return DEFAULT_CONVERTER.createInventory(holder, type); ++ } ++ //noinspection ConstantConditions // Paper end + return converterMap.get(type).createInventory(holder, type); + } + +@@ -55,6 +60,11 @@ public final class CraftInventoryCreator { + // Paper end + + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { ++ // Paper start ++ if (holder != null) { ++ return DEFAULT_CONVERTER.createInventory(holder, type, title); ++ } ++ //noinspection ConstantConditions // Paper end + return converterMap.get(type).createInventory(holder, type, title); + } + diff --git a/patches/server-remapped/0308-Use-Vanilla-Minecart-Speeds.patch b/patches/server-remapped/0308-Use-Vanilla-Minecart-Speeds.patch new file mode 100644 index 0000000000..1eeb5272ca --- /dev/null +++ b/patches/server-remapped/0308-Use-Vanilla-Minecart-Speeds.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 8 Nov 2018 21:33:09 -0500 +Subject: [PATCH] Use Vanilla Minecart Speeds + +CraftBukkit changed the values on flying speed, restore back to vanilla + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 7ba74b0a9319e29077b5afe3019a463ed3004813..1257a740a4ab79870fe89057782e8ffc6c658c14 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -99,9 +99,9 @@ public abstract class AbstractMinecart extends Entity { + private double derailedX = 0.5; + private double derailedY = 0.5; + private double derailedZ = 0.5; +- private double flyingX = 0.95; +- private double flyingY = 0.95; +- private double flyingZ = 0.95; ++ private double flyingX = 0.949999988079071D; // Paper - restore vanilla precision ++ private double flyingY = 0.949999988079071D; // Paper - restore vanilla precision ++ private double flyingZ = 0.949999988079071D; // Paper - restore vanilla precision + public double maxSpeed = 0.4D; + // CraftBukkit end + diff --git a/patches/server-remapped/0309-Fix-SpongeAbsortEvent-handling.patch b/patches/server-remapped/0309-Fix-SpongeAbsortEvent-handling.patch new file mode 100644 index 0000000000..169c739faa --- /dev/null +++ b/patches/server-remapped/0309-Fix-SpongeAbsortEvent-handling.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 10 Nov 2018 05:15:21 +0000 +Subject: [PATCH] Fix SpongeAbsortEvent handling + +Only process drops when the block is actually going to be removed + +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 9d2e4adddae481735053c64eec0ee7259c61f1a4..fca5d175cbef24fb0ee2d0bbedc8d1c0af3eb528 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -228,6 +228,7 @@ public class Block extends BlockBehaviour implements ItemLike { + + } + ++ public static void dropNaturally(BlockState iblockdata, LevelAccessor generatoraccess, BlockPos blockposition, @Nullable BlockEntity tileentity) { dropResources(iblockdata, generatoraccess, blockposition, tileentity); } + public static void dropResources(BlockState state, LevelAccessor world, BlockPos pos, @Nullable BlockEntity blockEntity) { + if (world instanceof ServerLevel) { + getDrops(state, (ServerLevel) world, pos, blockEntity).forEach((itemstack) -> { +diff --git a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java +index c453963ec90cd4eeec845fd0c2137e60dfdd6225..1895c75deee8da40624ba3abbd08ba7cd4f0f503 100644 +--- a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java +@@ -128,8 +128,11 @@ public class SpongeBlock extends Block { + // NOP + } else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) { + BlockEntity tileentity = iblockdata.getBlock().isEntityBlock() ? world.getBlockEntity(blockposition2) : null; +- +- dropResources(iblockdata, world, blockposition2, tileentity); ++ // Paper start ++ if (block.getHandle().getMaterial() == Material.AIR) { ++ dropNaturally(iblockdata, world, blockposition2, tileentity); ++ } ++ // Paper end + } + } + world.setBlock(blockposition2, block.getHandle(), block.getFlag()); diff --git a/patches/server-remapped/0310-Don-t-allow-digging-into-unloaded-chunks.patch b/patches/server-remapped/0310-Don-t-allow-digging-into-unloaded-chunks.patch new file mode 100644 index 0000000000..f5420a15fd --- /dev/null +++ b/patches/server-remapped/0310-Don-t-allow-digging-into-unloaded-chunks.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 11 Nov 2018 21:01:09 +0000 +Subject: [PATCH] Don't allow digging into unloaded chunks + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index b1a53093eb5b5f359eedb6c252cf6d0d1ae8e409..d97607f2ded4977b253d3afa3bafcbe6d7f98837 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -113,8 +113,8 @@ public class ServerPlayerGameMode { + BlockState iblockdata; + + if (this.hasDelayedDestroy) { +- iblockdata = this.level.getBlockState(this.delayedDestroyPos); +- if (iblockdata.isAir()) { ++ iblockdata = this.level.getTypeIfLoaded(this.delayedDestroyPos); // Paper ++ if (iblockdata == null || iblockdata.isAir()) { // Paper + this.hasDelayedDestroy = false; + } else { + float f = this.incrementDestroyProgress(iblockdata, this.delayedDestroyPos, this.delayedTickStart); +@@ -125,7 +125,13 @@ public class ServerPlayerGameMode { + } + } + } else if (this.isDestroyingBlock) { +- iblockdata = this.level.getBlockState(this.destroyPos); ++ // Paper start - don't want to do same logic as above, return instead ++ iblockdata = this.level.getTypeIfLoaded(this.destroyPos); ++ if (iblockdata == null) { ++ this.isDestroyingBlock = false; ++ return; ++ } ++ // Paper end + if (iblockdata.isAir()) { + this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); + this.lastSentState = -1; +@@ -289,10 +295,12 @@ public class ServerPlayerGameMode { + this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, "stopped destroying")); + } else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) { + this.isDestroyingBlock = false; +- if (!Objects.equals(this.destroyPos, pos)) { ++ if (!Objects.equals(this.destroyPos, pos) && !BlockPos.ZERO.equals(this.destroyPos)) { + ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: " + this.destroyPos + " " + pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled +- this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); +- this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, this.level.getBlockState(this.destroyPos), action, true, "aborted mismatched destroying")); ++ BlockState type = this.level.getTypeIfLoaded(this.destroyPos); // Paper - don't load unloaded chunks for stale records here ++ if (type != null) this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); // Paper ++ if (type != null) this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, type, action, true, "aborted mismatched destroying")); // Paper ++ this.destroyPos = BlockPos.ZERO; // Paper + } + + this.level.destroyBlockProgress(this.player.getId(), pos, -1); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index b5593300516fad767f603084aca4abcda4424db3..a6ad7747396f94def688b4d2783137180dc2bb84 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1518,6 +1518,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + case START_DESTROY_BLOCK: + case ABORT_DESTROY_BLOCK: + case STOP_DESTROY_BLOCK: ++ // Paper start - Don't allow digging in unloaded chunks ++ if (this.player.level.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { ++ return; ++ } ++ // Paper end - Don't allow digging in unloaded chunks + this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packet.getDirection(), this.server.getMaxBuildHeight()); + return; + default: diff --git a/patches/server-remapped/0311-Book-Size-Limits.patch b/patches/server-remapped/0311-Book-Size-Limits.patch new file mode 100644 index 0000000000..ef45bdd8d0 --- /dev/null +++ b/patches/server-remapped/0311-Book-Size-Limits.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 16 Nov 2018 23:08:50 -0500 +Subject: [PATCH] Book Size Limits + +Puts some limits on the size of books. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 3139c194f9b1bc3510d51a81f13ae43d00a3dc29..13edb435b3fa65b4980bd7472aa5a5196f4d5b2b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -339,4 +339,11 @@ public class PaperConfig { + velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); + } + } ++ ++ public static int maxBookPageSize = 2560; ++ public static double maxBookTotalSizeMultiplier = 0.98D; ++ private static void maxBookSize() { ++ maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); ++ maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index a6ad7747396f94def688b4d2783137180dc2bb84..b1c505d3fdcc2fb3496f80bee85e4895b9069dcb 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -999,6 +999,52 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + @Override + public void handleEditBook(ServerboundEditBookPacket packet) { ++ // Paper start ++ ItemStack testStack = packet.getBook(); ++ if (!craftServer.isPrimaryThread() && !testStack.isEmpty() && testStack.getTag() != null) { ++ ListTag pageList = testStack.getTag().getList("pages", 8); ++ if (pageList.size() > 100) { ++ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with too many pages"); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ return; ++ } ++ long byteTotal = 0; ++ int maxBookPageSize = com.destroystokyo.paper.PaperConfig.maxBookPageSize; ++ double multiplier = Math.max(0.3D, Math.min(1D, com.destroystokyo.paper.PaperConfig.maxBookTotalSizeMultiplier)); ++ long byteAllowed = maxBookPageSize; ++ for (int i = 0; i < pageList.size(); ++i) { ++ String testString = pageList.getString(i); ++ int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; ++ if (byteLength > 256 * 4) { ++ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!"); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ return; ++ } ++ byteTotal += byteLength; ++ int length = testString.length(); ++ int multibytes = 0; ++ if (byteLength != length) { ++ for (char c : testString.toCharArray()) { ++ if (c > 127) { ++ multibytes++; ++ } ++ } ++ } ++ byteAllowed += (maxBookPageSize * Math.min(1, Math.max(0.1D, (double) length / 255D))) * multiplier; ++ ++ if (multibytes > 1) { ++ // penalize MB ++ byteAllowed -= multibytes; ++ } ++ } ++ ++ if (byteTotal > byteAllowed) { ++ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ return; ++ } ++ } ++ // Paper end + // CraftBukkit start + if (this.lastBookTick + 20 > MinecraftServer.currentTick) { + this.disconnect("Book edited too quickly!"); diff --git a/patches/server-remapped/0312-Make-the-default-permission-message-configurable.patch b/patches/server-remapped/0312-Make-the-default-permission-message-configurable.patch new file mode 100644 index 0000000000..8d9bfec2a6 --- /dev/null +++ b/patches/server-remapped/0312-Make-the-default-permission-message-configurable.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 18 Nov 2018 19:49:56 +0000 +Subject: [PATCH] Make the default permission message configurable + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 13edb435b3fa65b4980bd7472aa5a5196f4d5b2b..469f78775b03cf363d88e35c69c0dc185c22547c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -19,6 +19,7 @@ import java.util.regex.Pattern; + import com.google.common.collect.Lists; + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; + import org.bukkit.command.Command; + import org.bukkit.configuration.ConfigurationSection; + import org.bukkit.configuration.InvalidConfigurationException; +@@ -287,6 +288,11 @@ public class PaperConfig { + connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); + } + ++ public static String noPermissionMessage = "&cI'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error."; ++ private static void noPermissionMessage() { ++ noPermissionMessage = ChatColor.translateAlternateColorCodes('&', getString("messages.no-permission", noPermissionMessage)); ++ } ++ + private static void savePlayerData() { + Object val = config.get("settings.save-player-data"); + if (val instanceof Boolean) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index c06b35f114a8d243198b66c44ef57d8c2b201361..590687d5941cbed3a330bcd749f8d52cd4b5e3ae 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2340,6 +2340,11 @@ public final class CraftServer implements Server { + return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; + } + ++ @Override ++ public String getPermissionMessage() { ++ return com.destroystokyo.paper.PaperConfig.noPermissionMessage; ++ } ++ + @Override + public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { + return createProfile(uuid, null); diff --git a/patches/server-remapped/0313-Prevent-rayTrace-from-loading-chunks.patch b/patches/server-remapped/0313-Prevent-rayTrace-from-loading-chunks.patch new file mode 100644 index 0000000000..d300ff7c9e --- /dev/null +++ b/patches/server-remapped/0313-Prevent-rayTrace-from-loading-chunks.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 26 Nov 2018 19:21:58 -0500 +Subject: [PATCH] Prevent rayTrace from loading chunks + +ray tracing into an unloaded chunk should be treated as a miss +this saves a ton of lag for when AI tries to raytrace near unloaded chunks. + +diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java +index 2feb187f62be5cf5d354a1e806087417cc189ab1..07fe8e72a7ff01d872dd5b04ccbc435e82ebe990 100644 +--- a/src/main/java/net/minecraft/world/level/BlockGetter.java ++++ b/src/main/java/net/minecraft/world/level/BlockGetter.java +@@ -58,7 +58,15 @@ public interface BlockGetter { + + // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace + default BlockHitResult rayTraceBlock(ClipContext raytrace1, BlockPos blockposition) { +- BlockState iblockdata = this.getBlockState(blockposition); ++ // Paper start - Prevent raytrace from loading chunks ++ BlockState iblockdata = this.getTypeIfLoaded(blockposition); ++ if (iblockdata == null) { ++ // copied the last function parameter (listed below) ++ Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo()); ++ ++ return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), new BlockPos(raytrace1.getTo())); ++ } ++ // Paper end + FluidState fluid = this.getFluidState(blockposition); + Vec3 vec3d = raytrace1.getFrom(); + Vec3 vec3d1 = raytrace1.getTo(); diff --git a/patches/server-remapped/0314-Handle-Large-Packets-disconnecting-client.patch b/patches/server-remapped/0314-Handle-Large-Packets-disconnecting-client.patch new file mode 100644 index 0000000000..3b9703f204 --- /dev/null +++ b/patches/server-remapped/0314-Handle-Large-Packets-disconnecting-client.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 27 Nov 2018 21:18:06 -0500 +Subject: [PATCH] Handle Large Packets disconnecting client + +If a players inventory is too big to send in a single packet, +split the inventory set into multiple packets instead. + +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 7f4681910751047a26fdfc6b59bc460449c02001..35191d968fd30db16213540ef7121f4dede68e68 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -12,6 +12,7 @@ import io.netty.channel.epoll.EpollEventLoopGroup; + import io.netty.channel.local.LocalChannel; + import io.netty.channel.local.LocalServerChannel; + import io.netty.channel.nio.NioEventLoopGroup; ++import io.netty.handler.codec.EncoderException; // Paper + import io.netty.handler.timeout.TimeoutException; + import io.netty.util.AttributeKey; + import io.netty.util.concurrent.Future; +@@ -107,6 +108,15 @@ public class Connection extends SimpleChannelInboundHandler> { + } + + public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { ++ // Paper start ++ if (throwable instanceof EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) { ++ if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) { ++ return; ++ } else { ++ throwable = throwable.getCause(); ++ } ++ } ++ // Paper end + if (throwable instanceof SkipPacketException) { + Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause()); + } else { +diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java +index d36d0424bcd4811af892f5f76fdcefda2af1ad33..a58c4fa8be7193b8acae5ea18a9780866312d768 100644 +--- a/src/main/java/net/minecraft/network/PacketEncoder.java ++++ b/src/main/java/net/minecraft/network/PacketEncoder.java +@@ -53,7 +53,31 @@ public class PacketEncoder extends MessageToByteEncoder> { + throw throwable; + } + } ++ ++ // Paper start ++ int packetLength = bytebuf.readableBytes(); ++ if (packetLength > MAX_PACKET_SIZE) { ++ throw new PacketTooLargeException(packet, packetLength); ++ } ++ // Paper end + } + } + } ++ ++ // Paper start ++ private static int MAX_PACKET_SIZE = 2097152; ++ ++ public static class PacketTooLargeException extends RuntimeException { ++ private final Packet packet; ++ ++ PacketTooLargeException(Packet packet, int packetLength) { ++ super("PacketTooLarge - " + packet.getClass().getSimpleName() + " is " + packetLength + ". Max is " + MAX_PACKET_SIZE); ++ this.packet = packet; ++ } ++ ++ public Packet getPacket() { ++ return packet; ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java +index 29f10af7feabe2765f576586db4e3dba320dceda..9914a82ba0ec146ab13fe94c4dbf0ebf64926536 100644 +--- a/src/main/java/net/minecraft/network/protocol/Packet.java ++++ b/src/main/java/net/minecraft/network/protocol/Packet.java +@@ -12,6 +12,12 @@ public interface Packet { + + void handle(T listener); + ++ // Paper start ++ default boolean packetTooLarge(NetworkManager manager) { ++ return false; ++ } ++ // Paper end ++ + default boolean isSkippable() { + return false; + } +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java +index 70684318c562a9c3ce566b16cd0e68cfe95cbd50..64a15dcaef40c4e16458ab71d648f9fff169a3b2 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java +@@ -4,6 +4,7 @@ import java.io.IOException; + import java.util.Iterator; + import java.util.List; + import net.minecraft.core.NonNullList; ++import net.minecraft.network.Connection; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; + import net.minecraft.world.item.ItemStack; +@@ -13,6 +14,15 @@ public class ClientboundContainerSetContentPacket implements Packet items; + ++ //Paper start ++ @Override ++ public boolean packetTooLarge(Connection manager) { ++ for (int i = 0 ; i < this.items.size() ; i++) { ++ manager.send(new ClientboundContainerSetSlotPacket(this.containerId, i, this.items.get(i))); ++ } ++ return true; ++ } ++ // Paper end + public ClientboundContainerSetContentPacket() {} + + public ClientboundContainerSetContentPacket(int syncId, NonNullList contents) { +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index 4fe15aa331ca18319ca46d1b426f0d6fd24341f0..b7d303b5f51a35504888933efef74564fa01e59d 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -91,7 +91,7 @@ public class ClientboundLevelChunkPacket implements Packet 2097152) { ++ if (i > 2097152) { // Paper - if this changes, update PacketEncoder + throw new RuntimeException("Chunk Packet trying to allocate too much memory on read."); + } else { + this.buffer = new byte[i]; diff --git a/patches/server-remapped/0315-force-entity-dismount-during-teleportation.patch b/patches/server-remapped/0315-force-entity-dismount-during-teleportation.patch new file mode 100644 index 0000000000..abee5b71e8 --- /dev/null +++ b/patches/server-remapped/0315-force-entity-dismount-during-teleportation.patch @@ -0,0 +1,134 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 15 Nov 2018 13:38:37 +0000 +Subject: [PATCH] force entity dismount during teleportation + +Entities must be dismounted before teleportation in order to avoid +multiple issues in the server with regards to teleportation, shamefully, +too many plugins rely on the events firing, which means that not firing +these events caues more issues than it solves; + +In order to counteract this, Entity dismount/exit vehicle events have +been modified to supress cancellation (and has a method to allow plugins +to check if this has been set), noting that cancellation will be silently +surpressed given that plugins are not expecting this event to not be cancellable. + +This is a far from ideal scenario, however: given the current state of this +event and other alternatives causing issues elsewhere, I believe that +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 b68acf219fc61e2ea811d0c732393824fa44db2d..416c21f0a6be8d71a654e18f7ea0fa074f8fc5ff 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1258,11 +1258,13 @@ public class ServerPlayer extends Player implements ContainerListener { + } + } + +- @Override +- public void stopRiding() { ++ // Paper start ++ @Override public void stopRiding() { stopRiding(false); } ++ @Override public void stopRiding(boolean suppressCancellation) { ++ // paper end + Entity entity = this.getVehicle(); + +- super.stopRiding(); ++ super.stopRiding(suppressCancellation); // Paper + Entity entity1 = this.getVehicle(); + + if (entity1 != entity && this.connection != null) { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 460c6fd61bb45247715d99445821e15e98e4c465..c5d6235a132818dfc78105e9d03d0687f697bb00 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2044,12 +2044,15 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + } + +- public void removeVehicle() { ++ // Paper start ++ public void removeVehicle() { stopRiding(false); } ++ public void stopRiding(boolean suppressCancellation) { ++ // Paper end + if (this.vehicle != null) { + Entity entity = this.vehicle; + + this.vehicle = null; +- if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit ++ if (!entity.removePassenger(this, suppressCancellation)) this.vehicle = entity; // CraftBukkit // Paper + } + + } +@@ -2104,7 +2107,10 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return true; // CraftBukkit + } + +- protected boolean removePassenger(Entity entity) { // CraftBukkit ++ // Paper start ++ protected boolean removePassenger(Entity entity) { return removePassenger(entity, false);} ++ protected boolean removePassenger(Entity entity, boolean suppressCancellation) { // CraftBukkit ++ // Paper end + if (entity.getVehicle() == this) { + throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); + } else { +@@ -2114,7 +2120,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { + VehicleExitEvent event = new VehicleExitEvent( + (Vehicle) getBukkitEntity(), +- (LivingEntity) entity.getBukkitEntity() ++ (LivingEntity) entity.getBukkitEntity(), !suppressCancellation // Paper + ); + // Suppress during worldgen + if (this.valid) { +@@ -2128,7 +2134,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + // CraftBukkit end + // Spigot start +- org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity()); ++ org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity(), !suppressCancellation); // Paper + // Suppress during worldgen + 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 7a2292e6907a2ae2026bd7243e864bd8300ecafa..29d4ed42e5d763639a50d849ef274c4d848bc9c9 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3012,11 +3012,13 @@ public abstract class LivingEntity extends Entity { + return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 4) != 0; + } + +- @Override +- public void stopRiding() { ++ // Paper start ++ @Override public void stopRiding() { stopRiding(false); } ++ @Override public void stopRiding(boolean suppressCancellation) { ++ // Paper end + Entity entity = this.getVehicle(); + +- super.stopRiding(); ++ super.stopRiding(suppressCancellation); // Paper - suppress + if (entity != null && entity != this.getVehicle() && !this.level.isClientSide) { + this.dismountVehicle(entity); + } +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 3aadc4ab5fe7b2ee9e20e0789ddcfe750599972f..0685920073a6a2b2c6a80018d0c9009b2ef860c4 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1036,9 +1036,11 @@ public abstract class Player extends LivingEntity { + return -0.35D; + } + +- @Override +- public void removeVehicle() { +- super.removeVehicle(); ++ // Paper start ++ @Override public void removeVehicle() { stopRiding(false); } ++ @Override public void stopRiding(boolean suppressCancellation) { ++ // Paper end ++ super.stopRiding(suppressCancellation); // Paper - suppress + this.boardingCooldown = 0; + } + diff --git a/patches/server-remapped/0316-Add-more-Zombie-API.patch b/patches/server-remapped/0316-Add-more-Zombie-API.patch new file mode 100644 index 0000000000..324b101062 --- /dev/null +++ b/patches/server-remapped/0316-Add-more-Zombie-API.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 7 Oct 2018 04:29:59 -0500 +Subject: [PATCH] Add more Zombie API + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 94e2a8f74e74d68d4a9b82b667fbff24b7e9e629..ad4eeb15771750193a28116117992270c72a3644 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -91,6 +91,7 @@ public class Zombie extends Monster { + private int inWaterTime; + public int conversionTime; + private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field ++ private boolean shouldBurnInDay = true; // Paper + + public Zombie(EntityType type, Level world) { + super(type, world); +@@ -259,6 +260,12 @@ public class Zombie extends Monster { + super.aiStep(); + } + ++ // Paper start ++ public void stopDrowning() { ++ this.conversionTime = -1; ++ this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, false); ++ } ++ // Paper end + public void startUnderWaterConversion(int ticksUntilWaterConversion) { + this.lastTick = MinecraftServer.currentTick; // CraftBukkit + this.conversionTime = ticksUntilWaterConversion; +@@ -287,9 +294,16 @@ public class Zombie extends Monster { + + } + ++ public boolean shouldBurnInDay() { return isSunSensitive(); } // Paper - OBFHELPER + protected boolean isSunSensitive() { +- return true; ++ return this.shouldBurnInDay; // Paper - use api value instead ++ } ++ ++ // Paper start ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { ++ this.shouldBurnInDay = shouldBurnInDay; + } ++ // Paper end + + @Override + public boolean hurt(DamageSource source, float amount) { +@@ -410,6 +424,7 @@ public class Zombie extends Monster { + tag.putBoolean("CanBreakDoors", this.canBreakDoors()); + tag.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1); + tag.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1); ++ tag.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); // Paper + } + + @Override +@@ -421,7 +436,11 @@ public class Zombie extends Monster { + if (tag.contains("DrownedConversionTime", 99) && tag.getInt("DrownedConversionTime") > -1) { + this.startUnderWaterConversion(tag.getInt("DrownedConversionTime")); + } +- ++ // Paper start ++ if (tag.contains("Paper.ShouldBurnInDay")) { ++ shouldBurnInDay = tag.getBoolean("Paper.ShouldBurnInDay"); ++ } ++ // Paper end + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +index 038793987338c2e4b73784a10836f85c7061175a..86f65c07806a118c49e900c59be86c2bd2eb124c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +@@ -93,6 +93,42 @@ public class CraftZombie extends CraftMonster implements Zombie { + @Override + public void setAgeLock(boolean b) { + } ++ // Paper start ++ @Override ++ public boolean isDrowning() { ++ return getHandle().isUnderWaterConverting(); ++ } ++ ++ @Override ++ public void startDrowning(int drownedConversionTime) { ++ getHandle().startUnderWaterConversion(drownedConversionTime); ++ } ++ ++ @Override ++ public void stopDrowning() { ++ getHandle().stopDrowning(); ++ } ++ ++ @Override ++ public boolean shouldBurnInDay() { ++ return getHandle().shouldBurnInDay(); ++ } ++ ++ @Override ++ public boolean isArmsRaised() { ++ return getHandle().isAggressive(); ++ } ++ ++ @Override ++ public void setArmsRaised(final boolean raised) { ++ getHandle().setAggressive(raised); ++ } ++ ++ @Override ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { ++ getHandle().setShouldBurnInDay(shouldBurnInDay); ++ } ++ // Paper end + + @Override + public boolean getAgeLock() { diff --git a/patches/server-remapped/0317-Add-PlayerConnectionCloseEvent.patch b/patches/server-remapped/0317-Add-PlayerConnectionCloseEvent.patch new file mode 100644 index 0000000000..12d0a9084e --- /dev/null +++ b/patches/server-remapped/0317-Add-PlayerConnectionCloseEvent.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 7 Oct 2018 12:05:28 -0700 +Subject: [PATCH] Add PlayerConnectionCloseEvent + +This event is invoked when a player has disconnected. It is guaranteed that, +if the server is in online-mode, that the provided uuid and username have been +validated. + +The event is invoked for players who have not yet logged into the world, whereas +PlayerQuitEvent is only invoked on players who have logged into the world. + +The event is invoked for players who have already logged into the world, +although whether or not the player exists in the world at the time of +firing is undefined. (That is, whether the plugin can retrieve a Player object +using the event parameters is undefined). However, it is guaranteed that this +event is invoked AFTER PlayerQuitEvent, if the player has already logged into +the world. + +This event is guaranteed to never fire unless AsyncPlayerPreLoginEvent has +been called beforehand, and this event may not be called in parallel with +AsyncPlayerPreLoginEvent for the same connection. + +Cancelling the AsyncPlayerPreLoginEvent guarantees the corresponding +PlayerConnectionCloseEvent is never called. + +The event may be invoked asynchronously or synchronously. As it stands, +it is never invoked asynchronously. However, plugins should check +Event#isAsynchronous to be future-proof. + +On purpose, the deprecated PlayerPreLoginEvent event is left out of the +API spec for this event. Plugins should not be using that event, and +how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent +is undefined. + +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 35191d968fd30db16213540ef7121f4dede68e68..3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -350,6 +350,26 @@ public class Connection extends SimpleChannelInboundHandler> { + this.getPacketListener().a(new TranslatableComponent("multiplayer.disconnect.generic")); + } + this.queue.clear(); // Free up packet queue. ++ // Paper start - Add PlayerConnectionCloseEvent ++ final PacketListener packetListener = this.getPacketListener(); ++ if (packetListener instanceof ServerGamePacketListenerImpl) { ++ /* Player was logged in */ ++ final ServerGamePacketListenerImpl playerConnection = (ServerGamePacketListenerImpl) packetListener; ++ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(playerConnection.player.getUUID(), ++ playerConnection.player.getScoreboardName(), ((java.net.InetSocketAddress)address).getAddress(), false).callEvent(); ++ } else if (packetListener instanceof ServerLoginPacketListenerImpl) { ++ /* Player is login stage */ ++ final ServerLoginPacketListenerImpl loginListener = (ServerLoginPacketListenerImpl) packetListener; ++ switch (loginListener.getLoginState()) { ++ case READY_TO_ACCEPT: ++ case DELAY_ACCEPT: ++ case ACCEPTED: ++ final com.mojang.authlib.GameProfile profile = loginListener.getGameProfile(); /* Should be non-null at this stage */ ++ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(profile.getId(), profile.getName(), ++ ((java.net.InetSocketAddress)address).getAddress(), false).callEvent(); ++ } ++ } ++ // Paper end + } + + } +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 22d6f41001977917ec75046252cbf7157b92396d..9631fa93b821c7f6bc6dc707c2c82cce2ae8291e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -55,9 +55,9 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + private final byte[] nonce = new byte[4]; + private final MinecraftServer server; + public final Connection connection; +- private ServerLoginPacketListenerImpl.State state; ++ private ServerLoginPacketListenerImpl.State state; public final ServerLoginPacketListenerImpl.State getLoginState() { return this.state; }; // Paper - OBFHELPER + private int tick; +- private GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } private GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER ++ private GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } public GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER + private final String serverId; + private SecretKey secretKey; + private ServerPlayer delayedAcceptPlayer; diff --git a/patches/server-remapped/0318-Prevent-Enderman-from-loading-chunks.patch b/patches/server-remapped/0318-Prevent-Enderman-from-loading-chunks.patch new file mode 100644 index 0000000000..b1074d223b --- /dev/null +++ b/patches/server-remapped/0318-Prevent-Enderman-from-loading-chunks.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 18 Dec 2018 02:15:08 +0000 +Subject: [PATCH] Prevent Enderman from loading chunks + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index d190b58bea310f4006ea3deaf0d42c502d441284..dae35d3f758e40c1edf31b11c6e11f1b7bb2dfae 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -434,7 +434,8 @@ public class EnderMan extends Monster implements NeutralMob { + int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 3.0D); + int k = Mth.floor(this.enderman.getZ() - 2.0D + random.nextDouble() * 4.0D); + BlockPos blockposition = new BlockPos(i, j, k); +- BlockState iblockdata = world.getBlockState(blockposition); ++ BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper ++ if (iblockdata == null) return; // Paper + Block block = iblockdata.getBlock(); + Vec3 vec3d = new Vec3((double) Mth.floor(this.enderman.getX()) + 0.5D, (double) j + 0.5D, (double) Mth.floor(this.enderman.getZ()) + 0.5D); + Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); +@@ -474,7 +475,8 @@ public class EnderMan extends Monster implements NeutralMob { + int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 2.0D); + int k = Mth.floor(this.enderman.getZ() - 1.0D + random.nextDouble() * 2.0D); + BlockPos blockposition = new BlockPos(i, j, k); +- BlockState iblockdata = world.getBlockState(blockposition); ++ BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper ++ if (iblockdata == null) return; // Paper + BlockPos blockposition1 = blockposition.below(); + BlockState iblockdata1 = world.getBlockState(blockposition1); + BlockState iblockdata2 = this.enderman.getCarriedBlock(); diff --git a/patches/server-remapped/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/patches/server-remapped/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch new file mode 100644 index 0000000000..491b5bd0f8 --- /dev/null +++ b/patches/server-remapped/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch @@ -0,0 +1,164 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Jan 2019 00:35:43 -0600 +Subject: [PATCH] Add APIs to replace OfflinePlayer#getLastPlayed + +Currently OfflinePlayer#getLastPlayed could more accurately be described +as "OfflinePlayer#getLastTimeTheirDataWasSaved". + +The API doc says it should return the last time the server "witnessed" +the player, whilst also saying it should return the last time they +logged in. The current implementation does neither. + +Given this interesting contradiction in the API documentation and the +current defacto implementation, I've elected to deprecate (with no +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 416c21f0a6be8d71a654e18f7ea0fa074f8fc5ff..1fa4f58658ff98396eb5abfc27e19e5832d56f5a 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -211,6 +211,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public int latency; + public boolean wonGame; + private int containerUpdateDelay; // Paper ++ public long loginTime; // Paper + // Paper start - cancellable death event + public boolean queueHealthUpdatePacket = false; + public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7c307a16ca3962db65be09a0ddd058a4ce81c7be..5b71b487836cdd2ddc75b2039f4dc0177719d345 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -164,6 +164,7 @@ public abstract class PlayerList { + } + + public void placeNewPlayer(Connection connection, ServerPlayer player) { ++ player.loginTime = System.currentTimeMillis(); // Paper + GameProfile gameprofile = player.getGameProfile(); + GameProfileCache usercache = this.server.getProfileCache(); + GameProfile gameprofile1 = usercache.get(gameprofile.getId()); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +index 1eeb1d1fe54eba68652be8dba52dce8ca91d948d..19aee8c6d0989bcf263e27adab42b3e6e411b66f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +@@ -244,6 +244,61 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa + return getData() != null; + } + ++ // Paper start ++ @Override ++ public long getLastLogin() { ++ Player player = getPlayer(); ++ if (player != null) return player.getLastLogin(); ++ ++ CompoundTag data = getPaperData(); ++ ++ if (data != null) { ++ if (data.contains("LastLogin")) { ++ return data.getLong("LastLogin"); ++ } else { ++ // if the player file cannot provide accurate data, this is probably the closest we can approximate ++ File file = getDataFile(); ++ return file.lastModified(); ++ } ++ } else { ++ return 0; ++ } ++ } ++ ++ @Override ++ public long getLastSeen() { ++ Player player = getPlayer(); ++ if (player != null) return player.getLastSeen(); ++ ++ CompoundTag data = getPaperData(); ++ ++ if (data != null) { ++ if (data.contains("LastSeen")) { ++ return data.getLong("LastSeen"); ++ } else { ++ // if the player file cannot provide accurate data, this is probably the closest we can approximate ++ File file = getDataFile(); ++ return file.lastModified(); ++ } ++ } else { ++ return 0; ++ } ++ } ++ ++ private CompoundTag getPaperData() { ++ CompoundTag result = getData(); ++ ++ if (result != null) { ++ if (!result.contains("Paper")) { ++ result.put("Paper", new CompoundTag()); ++ } ++ result = result.getCompound("Paper"); ++ } ++ ++ return result; ++ } ++ // Paper end ++ + @Override + public Location getBedSpawnLocation() { + CompoundTag data = getData(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index a3e65028d3e0c09a65cd9c28b037fe01a2ed1d76..ba03a1cdac68dc08ed878e311adeebc531e8f2f1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -144,6 +144,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; + private String resourcePackHash; + private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit ++ private long lastSaveTime; + // Paper end + + public CraftPlayer(CraftServer server, ServerPlayer entity) { +@@ -1480,6 +1481,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + this.firstPlayed = firstPlayed; + } + ++ // Paper start ++ @Override ++ public long getLastLogin() { ++ return getHandle().loginTime; ++ } ++ ++ @Override ++ public long getLastSeen() { ++ return isOnline() ? System.currentTimeMillis() : this.lastSaveTime; ++ } ++ // Paper end ++ + public void readExtraData(CompoundTag nbttagcompound) { + hasPlayedBefore = true; + if (nbttagcompound.contains("bukkit")) { +@@ -1502,6 +1515,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void setExtraData(CompoundTag nbttagcompound) { ++ this.lastSaveTime = System.currentTimeMillis(); // Paper ++ + if (!nbttagcompound.contains("bukkit")) { + nbttagcompound.put("bukkit", new CompoundTag()); + } +@@ -1516,6 +1531,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + data.putLong("firstPlayed", getFirstPlayed()); + data.putLong("lastPlayed", System.currentTimeMillis()); + data.putString("lastKnownName", handle.getScoreboardName()); ++ ++ // Paper start - persist for use in offline save data ++ if (!nbttagcompound.contains("Paper")) { ++ nbttagcompound.put("Paper", new CompoundTag()); ++ } ++ ++ CompoundTag paper = nbttagcompound.getCompound("Paper"); ++ paper.putLong("LastLogin", handle.loginTime); ++ paper.putLong("LastSeen", System.currentTimeMillis()); ++ // Paper end + } + + @Override diff --git a/patches/server-remapped/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/patches/server-remapped/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch new file mode 100644 index 0000000000..4645205240 --- /dev/null +++ b/patches/server-remapped/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: connorhartley +Date: Mon, 7 Jan 2019 14:43:48 -0600 +Subject: [PATCH] Workaround for vehicle tracking issue on disconnect + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 1fa4f58658ff98396eb5abfc27e19e5832d56f5a..fd2717a00a85f91ee23a1c0f929f856972892a9b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1524,6 +1524,13 @@ public class ServerPlayer extends Player implements ContainerListener { + public void disconnect() { + this.disconnected = true; + this.ejectPassengers(); ++ ++ // Paper start - Workaround an issue where the vehicle doesn't track the passenger disconnection dismount. ++ if (this.isPassenger() && this.getVehicle() instanceof ServerPlayer) { ++ this.stopRiding(); ++ } ++ // Paper end ++ + if (this.isSleeping()) { + this.stopSleepInBed(true, false); + } diff --git a/patches/server-remapped/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/patches/server-remapped/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch new file mode 100644 index 0000000000..7b22e86252 --- /dev/null +++ b/patches/server-remapped/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 31 Jan 2019 16:33:36 -0500 +Subject: [PATCH] Fire BlockPistonRetractEvent for all empty pistons + +There is an explicit check in the handling code for empty pistons that +prevents sticky pistons from firing the event. However when we look back +at the history we see that this check was originally added so that ONLY +sticky pistons would fire the retract event. I'm not sure why. +https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1092acbddf07edfa4100bc6824504ac75088e913 + +Over the course of several updates, the meaning of that field appears to +have changed from "is NOT sticky" to "is sticky". So now its having the +opposite effect. Only normal pistons fire the retraction event. And like +all things in CB, it's just been carried around since. + +If we are to believe the history, the correct fix for this issue is to +flip it so it only fires for sticky pistons, but that puts us in a +bind. It's already firing for non-sticky pistons, changing it now would +likely result in breakage. Furthermore, there is little documentation as +to WHY that was ever intended to be the case. + +Instead we opt to remove the check entirely so that the event fires for +all piston types. + +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +index 878cec21b52fb62369310c2f85001e859a270dd8..dc9584a30c18d964afd9cc118c81c24a80beba63 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -140,7 +140,7 @@ public class PistonBaseBlock extends DirectionalBlock { + } + + // CraftBukkit start +- if (!this.isSticky) { ++ //if (!this.sticky) { // Paper - Prevents empty sticky pistons from firing retract - history behind is odd + org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); + BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); + world.getCraftServer().getPluginManager().callEvent(event); +@@ -148,7 +148,7 @@ public class PistonBaseBlock extends DirectionalBlock { + if (event.isCancelled()) { + return; + } +- } ++ //} // Paper + // PAIL: checkME - what happened to setTypeAndData? + // CraftBukkit end + world.blockEvent(pos, this, b0, enumdirection.get3DDataValue()); diff --git a/patches/server-remapped/0322-Block-Entity-remove-from-being-called-on-Players.patch b/patches/server-remapped/0322-Block-Entity-remove-from-being-called-on-Players.patch new file mode 100644 index 0000000000..8ac3978e9f --- /dev/null +++ b/patches/server-remapped/0322-Block-Entity-remove-from-being-called-on-Players.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 4 Feb 2019 23:33:24 -0500 +Subject: [PATCH] Block Entity#remove from being called on Players + +This doesn't result in the same behavior as other entities and causes +several problems. Anyone ever complain about the "Cannot send chat +message" thing? That's one of the issues this causes, among others. + +If a plugin developer can come up with a valid reason to call this on a +Player we will look at limiting the scope of this change. It appears to +be unintentional in the few cases we've seen so far. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index ba03a1cdac68dc08ed878e311adeebc531e8f2f1..c2c6eb54096ef85b01c0b700cbe6a8054b62729f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2231,6 +2231,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public void resetCooldown() { + getHandle().resetAttackStrengthTicker(); + } ++ ++ @Override ++ public void remove() { ++ if (this.getHandle().getClass().equals(ServerPlayer.class)) { // special case for NMS plugins inheriting ++ throw new UnsupportedOperationException("Calling Entity#remove on players produces undefined (bad) behavior"); ++ } else { ++ super.remove(); ++ } ++ } + // Paper end + + // Spigot start diff --git a/patches/server-remapped/0323-BlockDestroyEvent.patch b/patches/server-remapped/0323-BlockDestroyEvent.patch new file mode 100644 index 0000000000..497abbdeb1 --- /dev/null +++ b/patches/server-remapped/0323-BlockDestroyEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 Feb 2019 00:20:33 -0500 +Subject: [PATCH] BlockDestroyEvent + +Adds an event for when the server is going to destroy a current block, +potentially causing it to drop. This event can be cancelled to avoid +the block destruction, such as preventing signs from popping when +floating in the air. + +This can replace many uses of BlockPhysicsEvent + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index b75ffafb6840b6acab6e5b0ef5e222c4fa130977..c8542636e89748699d608eb29569cacb6321d334 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -27,6 +27,7 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundSetBorderPacket; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerLevel; +@@ -559,8 +560,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return false; + } else { + FluidState fluid = this.getFluidState(pos); ++ // Paper start - while the above setAir method is named same and looks very similar ++ // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent, ++ // it doesn't imply destruction of a block that plays a sound effect / drops an item. ++ boolean playEffect = true; ++ if (com.destroystokyo.paper.event.block.BlockDestroyEvent.getHandlerList().getRegisteredListeners().length > 0) { ++ com.destroystokyo.paper.event.block.BlockDestroyEvent event = new com.destroystokyo.paper.event.block.BlockDestroyEvent(MCUtil.toBukkitBlock(this, pos), fluid.createLegacyBlock().createCraftBlockData(), drop); ++ if (!event.callEvent()) { ++ return false; ++ } ++ playEffect = event.playEffect(); ++ } ++ // Paper end + +- if (!(iblockdata.getBlock() instanceof BaseFireBlock)) { ++ if (playEffect && !(iblockdata.getBlock() instanceof BaseFireBlock)) { // Paper + this.levelEvent(2001, pos, Block.getId(iblockdata)); + } + diff --git a/patches/server-remapped/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/patches/server-remapped/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch new file mode 100644 index 0000000000..941fce8c3e --- /dev/null +++ b/patches/server-remapped/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Jan 2019 00:08:15 -0500 +Subject: [PATCH] Fix Custom Shapeless Custom Crafting Recipes + +Mojang implemented Shapeless different than Shaped + +This made the Bukkit RecipeChoice API not work for Shapeless. + +This reimplements vanilla logic using the same test logic as Shaped + +diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java +index 7bd62f598f3fff7520c276bdc45e538bd3260bc9..a8d0a90d36d58515bb6f6128de1ef15b72c20c17 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java ++++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java +@@ -71,16 +71,49 @@ public class ShapelessRecipe implements CraftingRecipe { + StackedContents autorecipestackmanager = new StackedContents(); + int i = 0; + ++ // Paper start ++ java.util.List providedItems = new java.util.ArrayList<>(); ++ co.aikar.util.Counter matchedProvided = new co.aikar.util.Counter<>(); ++ co.aikar.util.Counter matchedIngredients = new co.aikar.util.Counter<>(); ++ // Paper end + for (int j = 0; j < inv.getContainerSize(); ++j) { + ItemStack itemstack = inv.getItem(j); + + if (!itemstack.isEmpty()) { +- ++i; +- autorecipestackmanager.accountStack(itemstack, 1); ++ // Paper start ++ itemstack = itemstack.copy(); ++ providedItems.add(itemstack); ++ for (Ingredient ingredient : ingredients) { ++ if (ingredient.test(itemstack)) { ++ matchedProvided.increment(itemstack); ++ matchedIngredients.increment(ingredient); ++ } ++ } ++ // Paper end + } + } + +- return i == this.ingredients.size() && autorecipestackmanager.canCraft(this, (IntList) null); ++ // Paper start ++ if (matchedProvided.isEmpty() || matchedIngredients.isEmpty()) { ++ return false; ++ } ++ java.util.List ingredients = new java.util.ArrayList<>(this.ingredients); ++ providedItems.sort(java.util.Comparator.comparingInt((ItemStack c) -> (int) matchedProvided.getCount(c)).reversed()); ++ ingredients.sort(java.util.Comparator.comparingInt((Ingredient c) -> (int) matchedIngredients.getCount(c))); ++ ++ PROVIDED: ++ for (ItemStack provided : providedItems) { ++ for (Iterator itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) { ++ Ingredient ingredient = itIngredient.next(); ++ if (ingredient.test(provided)) { ++ itIngredient.remove(); ++ continue PROVIDED; ++ } ++ } ++ return false; ++ } ++ return ingredients.isEmpty(); ++ // Paper end + } + + public ItemStack assemble(CraftingContainer inv) { diff --git a/patches/server-remapped/0325-Fix-sign-edit-memory-leak.patch b/patches/server-remapped/0325-Fix-sign-edit-memory-leak.patch new file mode 100644 index 0000000000..cdc4ad71f6 --- /dev/null +++ b/patches/server-remapped/0325-Fix-sign-edit-memory-leak.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 28 Feb 2019 00:15:28 -0500 +Subject: [PATCH] Fix sign edit memory leak + +when a player edits a sign, a reference to their Entity is never cleand up. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index b1c505d3fdcc2fb3496f80bee85e4895b9069dcb..276773e17149f57038cd21485fd9d9061670ff2d 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2850,7 +2850,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; + +- if (!tileentitysign.isEditable() || tileentitysign.getPlayerWhoMayEdit() != this.player) { ++ if (!tileentitysign.isEditable() || tileentitysign.signEditor == null || !tileentitysign.signEditor.equals(this.player.getUUID())) { + ServerGamePacketListenerImpl.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getName().getString()); + this.send(tileentity.getUpdatePacket()); // CraftBukkit + return; +diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +index e4eab82855649fec654c60b2e94ba7b71c2ac5a2..0b26d3ab2db66d6baaa95d1d5f6c756595d31495 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -30,6 +30,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + private Player playerWhoMayEdit; + private final FormattedCharSequence[] renderMessages; + private DyeColor color; ++ public java.util.UUID signEditor; // Paper + + public SignBlockEntity() { + super(BlockEntityType.SIGN); +@@ -131,7 +132,10 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + } + + public void setAllowedPlayerEditor(Player player) { +- this.playerWhoMayEdit = player; ++ // Paper start ++ //this.c = entityhuman; ++ signEditor = player != null ? player.getUUID() : null; ++ // Paper end + } + + public Player getPlayerWhoMayEdit() { diff --git a/patches/server-remapped/0326-Limit-Client-Sign-length-more.patch b/patches/server-remapped/0326-Limit-Client-Sign-length-more.patch new file mode 100644 index 0000000000..da033509aa --- /dev/null +++ b/patches/server-remapped/0326-Limit-Client-Sign-length-more.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 27 Feb 2019 22:18:40 -0500 +Subject: [PATCH] Limit Client Sign length more + +modified clients can send more data from the client +to the server and it would get stored on the sign as sent. + +Mojang has a limit of 384 which is much higher than reasonable. + +the client can barely render around 16 characters as-is, but formatting +codes can get it to be more than 16 actual length. + +Set a limit of 80 which should give an average of 16 characters 2 +sets of legacy formatting codes which should be plenty for all uses. + +This does not strip any existing data from the NBT as plugins +may use this for storing data out of the rendered area. + +it only impacts data sent from the client. + +Set -DPaper.maxSignLength=XX to change limit or -1 to disable + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 276773e17149f57038cd21485fd9d9061670ff2d..d6d8d83bc16572474d56a278dd119eacc2c52476 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -254,6 +254,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private int aboveGroundVehicleTickCount; + private int receivedMovePacketCount; + private int knownMovePacketCount; ++ private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); + private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit + + public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { +@@ -2860,7 +2861,17 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + List lines = new java.util.ArrayList<>(); + + for (int i = 0; i < list.size(); ++i) { +- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. ++ // Paper start - cap line length - modified clients can send longer data than normal ++ String currentLine = list.get(i); ++ if (MAX_SIGN_LINE_LENGTH > 0 && currentLine.length() > MAX_SIGN_LINE_LENGTH) { ++ // This handles multibyte characters as 1 ++ int offset = currentLine.codePoints().limit(MAX_SIGN_LINE_LENGTH).map(Character::charCount).sum(); ++ if (offset < currentLine.length()) { ++ list.set(i, currentLine = currentLine.substring(0, offset)); ++ } ++ } ++ // Paper end ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(currentLine))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. + } + SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); + this.craftServer.getPluginManager().callEvent(event); diff --git a/patches/server-remapped/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/patches/server-remapped/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch new file mode 100644 index 0000000000..e847f69596 --- /dev/null +++ b/patches/server-remapped/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 2 Mar 2019 11:11:29 -0500 +Subject: [PATCH] Don't check ConvertSigns boolean every sign save + +property lookups arent super cheap. they synchronize, validate +and check security managers. + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +index 0b26d3ab2db66d6baaa95d1d5f6c756595d31495..8d619e0bf8bcf7d6d4e7f23f11d648ccfb65cac4 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -31,6 +31,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + private final FormattedCharSequence[] renderMessages; + private DyeColor color; + public java.util.UUID signEditor; // Paper ++ private static final boolean CONVERT_LEGACY_SIGNS = Boolean.getBoolean("convertLegacySigns"); // Paper + + public SignBlockEntity() { + super(BlockEntityType.SIGN); +@@ -51,7 +52,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + } + + // CraftBukkit start +- if (Boolean.getBoolean("convertLegacySigns")) { ++ if (CONVERT_LEGACY_SIGNS) { // Paper + tag.putBoolean("Bukkit.isConverted", true); + } + // CraftBukkit end diff --git a/patches/server-remapped/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server-remapped/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch new file mode 100644 index 0000000000..0dc4b2e085 --- /dev/null +++ b/patches/server-remapped/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch @@ -0,0 +1,394 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 May 2020 04:53:35 -0400 +Subject: [PATCH] Optimize Network Manager and add advanced packet support + +Adds ability for 1 packet to bundle other packets to follow it +Adds ability for a packet to delay sending more packets until a state is ready. + +Removes synchronization from sending packets +Removes processing packet queue off of main thread + - for the few cases where it is allowed, order is not necessary nor + should it even be happening concurrently in first place (handshaking/login/status) + +Ensures packets sent asynchronously are dispatched on main thread + +This helps ensure safety for ProtocolLib as packet listeners +are commonly accessing world state. This will allow you to schedule +a packet to be sent async, but itll be dispatched sync for packet +listeners to process. + +This should solve some deadlock risks + +Also adds Netty Channel Flush Consolidation to reduce the amount of flushing + +Also avoids spamming closed channel exception by rechecking closed state in dispatch +and then catch exceptions and close if they fire. + +Part of this commit was authored by: Spottedleaf + +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed0b562c1b 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -25,8 +25,15 @@ import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketFlow; ++import net.minecraft.network.protocol.game.ClientboundBossEventPacket; ++import net.minecraft.network.protocol.game.ClientboundChatPacket; ++import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket; + import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; ++import net.minecraft.network.protocol.game.ClientboundKeepAlivePacket; ++import net.minecraft.network.protocol.game.ClientboundSetTitlesPacket; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.RunningOnDifferentThreadException; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.network.ServerGamePacketListenerImpl; + import net.minecraft.server.network.ServerLoginPacketListenerImpl; + import net.minecraft.util.LazyLoadedValue; +@@ -75,6 +82,10 @@ public class Connection extends SimpleChannelInboundHandler> { + public int protocolVersion; + public java.net.InetSocketAddress virtualHost; + private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); ++ // Optimize network ++ public boolean isPending = true; ++ public boolean queueImmunity = false; ++ public ConnectionProtocol protocol; + // Paper end + + public Connection(PacketFlow side) { +@@ -98,6 +109,7 @@ public class Connection extends SimpleChannelInboundHandler> { + } + + public void setProtocol(ConnectionProtocol state) { ++ protocol = state; // Paper + this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).set(state); + this.channel.config().setAutoRead(true); + Connection.LOGGER.debug("Enabled auto read"); +@@ -168,19 +180,84 @@ public class Connection extends SimpleChannelInboundHandler> { + Validate.notNull(listener, "packetListener", new Object[0]); + this.packetListener = listener; + } ++ // Paper start ++ public ServerPlayer getPlayer() { ++ if (packetListener instanceof ServerGamePacketListenerImpl) { ++ return ((ServerGamePacketListenerImpl) packetListener).player; ++ } else { ++ return null; ++ } ++ } ++ private static class InnerUtil { // Attempt to hide these methods from ProtocolLib so it doesn't accidently pick them up. ++ private static java.util.List buildExtraPackets(Packet packet) { ++ java.util.List extra = packet.getExtraPackets(); ++ if (extra == null || extra.isEmpty()) { ++ return null; ++ } ++ java.util.List ret = new java.util.ArrayList<>(1 + extra.size()); ++ buildExtraPackets0(extra, ret); ++ return ret; ++ } ++ ++ private static void buildExtraPackets0(java.util.List extraPackets, java.util.List into) { ++ for (Packet extra : extraPackets) { ++ into.add(extra); ++ java.util.List extraExtra = extra.getExtraPackets(); ++ if (extraExtra != null && !extraExtra.isEmpty()) { ++ buildExtraPackets0(extraExtra, into); ++ } ++ } ++ } ++ // Paper start ++ private static boolean canSendImmediate(Connection networkManager, Packet packet) { ++ return networkManager.isPending || networkManager.protocol != ConnectionProtocol.PLAY || ++ packet instanceof ClientboundKeepAlivePacket || ++ packet instanceof ClientboundChatPacket || ++ packet instanceof ClientboundCommandSuggestionsPacket || ++ packet instanceof ClientboundSetTitlesPacket || ++ packet instanceof ClientboundBossEventPacket; ++ } ++ // Paper end ++ } ++ // Paper end + + public void send(Packet packet) { + this.send(packet, (GenericFutureListener) null); + } + + public void send(Packet packet, @Nullable GenericFutureListener> callback) { +- if (this.isConnected()) { +- this.flushQueue(); +- this.sendPacket(packet, callback); +- } else { +- this.queue.add(new Connection.PacketHolder(packet, callback)); ++ // Paper start - handle oversized packets better ++ boolean connected = this.isConnected(); ++ if (!connected && !preparing) { ++ return; // Do nothing ++ } ++ packet.onPacketDispatch(getPlayer()); ++ if (connected && (InnerUtil.canSendImmediate(this, packet) || ( ++ MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() && ++ (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) ++ ))) { ++ this.dispatchPacket(packet, callback); ++ return; + } ++ // write the packets to the queue, then flush - antixray hooks there already ++ java.util.List extraPackets = InnerUtil.buildExtraPackets(packet); ++ boolean hasExtraPackets = extraPackets != null && !extraPackets.isEmpty(); ++ if (!hasExtraPackets) { ++ this.queue.add(new Connection.PacketHolder(packet, callback)); ++ } else { ++ java.util.List packets = new java.util.ArrayList<>(1 + extraPackets.size()); ++ packets.add(new Connection.PacketHolder(packet, null)); // delay the future listener until the end of the extra packets ++ ++ for (int i = 0, len = extraPackets.size(); i < len;) { ++ Packet extra = extraPackets.get(i); ++ boolean end = ++i == len; ++ packets.add(new Connection.PacketHolder(extra, end ? callback : null)); // append listener to the end ++ } + ++ this.queue.addAll(packets); // atomic ++ } ++ this.sendPacketQueue(); ++ // Paper end + } + + private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.sendPacket(packet, genericFutureListener); } // Paper - OBFHELPER +@@ -194,54 +271,119 @@ public class Connection extends SimpleChannelInboundHandler> { + this.channel.config().setAutoRead(false); + } + ++ ServerPlayer player = getPlayer(); // Paper + if (this.channel.eventLoop().inEventLoop()) { + if (enumprotocol != enumprotocol1) { + this.setProtocol(enumprotocol); + } ++ // Paper start ++ if (!isConnected()) { ++ packet.onPacketDispatchFinish(player, null); ++ return; ++ } ++ try { ++ // Paper end + + ChannelFuture channelfuture = this.channel.writeAndFlush(packet); + + if (callback != null) { + channelfuture.addListener(callback); + } ++ // Paper start ++ if (packet.hasFinishListener()) { ++ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); ++ } ++ // Paper end + + channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); ++ // Paper start ++ } catch (Exception e) { ++ LOGGER.error("NetworkException: " + player, e); ++ disconnect(new TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; ++ packet.onPacketDispatchFinish(player, null); ++ } ++ // Paper end + } else { + this.channel.eventLoop().execute(() -> { + if (enumprotocol != enumprotocol1) { + this.setProtocol(enumprotocol); + } + ++ // Paper start ++ if (!isConnected()) { ++ packet.onPacketDispatchFinish(player, null); ++ return; ++ } ++ try { ++ // Paper end + ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet); + ++ + if (callback != null) { + channelfuture1.addListener(callback); + } ++ // Paper start ++ if (packet.hasFinishListener()) { ++ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); ++ } ++ // Paper end + + channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); ++ // Paper start ++ } catch (Exception e) { ++ LOGGER.error("NetworkException: " + player, e); ++ disconnect(new TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; ++ packet.onPacketDispatchFinish(player, null); ++ } ++ // Paper end + }); + } + + } + +- private void sendPacketQueue() { this.flushQueue(); } // Paper - OBFHELPER +- private void flushQueue() { +- if (this.channel != null && this.channel.isOpen()) { +- Queue queue = this.queue; +- ++ // Paper start - rewrite this to be safer if ran off main thread ++ private boolean sendPacketQueue() { return this.p(); } // OBFHELPER // void -> boolean ++ private boolean p() { // void -> boolean ++ if (!isConnected()) { ++ return true; ++ } ++ if (MCUtil.isMainThread()) { ++ return processQueue(); ++ } else if (isPending) { ++ // Should only happen during login/status stages + synchronized (this.queue) { +- Connection.PacketHolder networkmanager_queuedpacket; +- +- while ((networkmanager_queuedpacket = (Connection.PacketHolder) this.queue.poll()) != null) { +- this.sendPacket(networkmanager_queuedpacket.packet, networkmanager_queuedpacket.listener); +- } ++ return this.processQueue(); ++ } ++ } ++ return false; ++ } ++ private boolean processQueue() { ++ if (this.queue.isEmpty()) return true; ++ // If we are on main, we are safe here in that nothing else should be processing queue off main anymore ++ // But if we are not on main due to login/status, the parent is synchronized on packetQueue ++ java.util.Iterator iterator = this.queue.iterator(); ++ while (iterator.hasNext()) { ++ Connection.PacketHolder queued = iterator.next(); // poll -> peek ++ ++ // Fix NPE (Spigot bug caused by handleDisconnection()) ++ if (queued == null) { ++ return true; ++ } + ++ Packet packet = queued.getPacket(); ++ if (!packet.isReady()) { ++ return false; ++ } else { ++ iterator.remove(); ++ this.dispatchPacket(packet, queued.getGenericFutureListener()); + } + } ++ return true; + } ++ // Paper end + + public void tick() { +- this.flushQueue(); ++ this.p(); + if (this.packetListener instanceof ServerLoginPacketListenerImpl) { + ((ServerLoginPacketListenerImpl) this.packetListener).tick(); + } +@@ -271,9 +413,21 @@ public class Connection extends SimpleChannelInboundHandler> { + return this.address; + } + ++ // Paper start ++ public void clearPacketQueue() { ++ ServerPlayer player = getPlayer(); ++ queue.forEach(queuedPacket -> { ++ Packet packet = queuedPacket.getPacket(); ++ if (packet.hasFinishListener()) { ++ packet.onPacketDispatchFinish(player, null); ++ } ++ }); ++ queue.clear(); ++ } // Paper end + public void disconnect(Component disconnectReason) { + // Spigot Start + this.preparing = false; ++ clearPacketQueue(); // Paper + // Spigot End + if (this.channel.isOpen()) { + this.channel.close(); // We can't wait as this may be called from an event loop. +@@ -341,7 +495,7 @@ public class Connection extends SimpleChannelInboundHandler> { + public void handleDisconnection() { + if (this.channel != null && !this.channel.isOpen()) { + if (this.disconnectionHandled) { +- Connection.LOGGER.warn("handleDisconnection() called twice"); ++ //NetworkManager.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message + } else { + this.disconnectionHandled = true; + if (this.getDisconnectedReason() != null) { +@@ -349,7 +503,7 @@ public class Connection extends SimpleChannelInboundHandler> { + } else if (this.getPacketListener() != null) { + this.getPacketListener().a(new TranslatableComponent("multiplayer.disconnect.generic")); + } +- this.queue.clear(); // Free up packet queue. ++ clearPacketQueue(); // Paper + // Paper start - Add PlayerConnectionCloseEvent + final PacketListener packetListener = this.getPacketListener(); + if (packetListener instanceof ServerGamePacketListenerImpl) { +diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java +index 9914a82ba0ec146ab13fe94c4dbf0ebf64926536..22db5d0d2cc33498ca40162c66aa3b5fbf2f569f 100644 +--- a/src/main/java/net/minecraft/network/protocol/Packet.java ++++ b/src/main/java/net/minecraft/network/protocol/Packet.java +@@ -1,5 +1,6 @@ + package net.minecraft.network.protocol; + ++import io.netty.channel.ChannelFuture; // Paper + import java.io.IOException; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.PacketListener; +@@ -13,6 +14,20 @@ public interface Packet { + void handle(T listener); + + // Paper start ++ ++ /** ++ * @param player Null if not at PLAY stage yet ++ */ ++ default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} ++ ++ /** ++ * @param player Null if not at PLAY stage yet ++ * @param future Can be null if packet was cancelled ++ */ ++ default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} ++ default boolean hasFinishListener() { return false; } ++ default boolean isReady() { return true; } ++ default java.util.List getExtraPackets() { return null; } + default boolean packetTooLarge(NetworkManager manager) { + return false; + } +diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +index 6cb51a4fe3c11f53fbb556ce6b0d64b735254d51..d46910cfdc0aef046a0c79731a85d381953c328a 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +@@ -16,6 +16,7 @@ import io.netty.channel.epoll.EpollServerSocketChannel; + import io.netty.channel.nio.NioEventLoopGroup; + import io.netty.channel.socket.ServerSocketChannel; + import io.netty.channel.socket.nio.NioServerSocketChannel; ++import io.netty.handler.flush.FlushConsolidationHandler; // Paper + import io.netty.handler.timeout.ReadTimeoutHandler; + import java.io.IOException; + import java.net.InetAddress; +@@ -54,10 +55,12 @@ public class ServerConnectionListener { + private final List connections = Collections.synchronizedList(Lists.newArrayList()); + // Paper start - prevent blocking on adding a new network manager while the server is ticking + private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ private static final boolean disableFlushConsolidation = Boolean.getBoolean("Paper.disableFlushConsolidate"); // Paper + private void addPending() { + Connection manager = null; + while ((manager = pending.poll()) != null) { + connections.add(manager); ++ manager.isPending = false; + } + } + // Paper end +@@ -92,6 +95,7 @@ public class ServerConnectionListener { + ; + } + ++ if (!disableFlushConsolidation) channel.pipeline().addFirst(new FlushConsolidationHandler()); // Paper + channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyQueryHandler(ServerConnectionListener.this)).addLast("splitter", new Varint21FrameDecoder()).addLast("decoder", new PacketDecoder(PacketFlow.SERVERBOUND)).addLast("prepender", new Varint21LengthFieldPrepender()).addLast("encoder", new PacketEncoder(PacketFlow.CLIENTBOUND)); + int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); + Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); diff --git a/patches/server-remapped/0329-Handle-Oversized-Tile-Entities-in-chunks.patch b/patches/server-remapped/0329-Handle-Oversized-Tile-Entities-in-chunks.patch new file mode 100644 index 0000000000..83303e9b30 --- /dev/null +++ b/patches/server-remapped/0329-Handle-Oversized-Tile-Entities-in-chunks.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 May 2020 05:00:57 -0400 +Subject: [PATCH] Handle Oversized Tile Entities in chunks + +Splits out Extra Packets if too many TE's are encountered to prevent +creating too large of a packet to sed. + +Co authored by Spottedleaf + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index b7d303b5f51a35504888933efef74564fa01e59d..b587f774c8f88f2a1c3ea489f7e4fe0bbdeb5a41 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -34,7 +34,15 @@ public class ClientboundLevelChunkPacket implements Packet extraPackets = new java.util.ArrayList<>(); ++ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); + ++ @Override ++ public java.util.List getExtraPackets() { ++ return extraPackets; ++ } ++ // Paper end + public ClientboundLevelChunkPacket(LevelChunk chunk, int includedSectionsMask) { + ChunkPos chunkcoordintpair = chunk.getPos(); + +@@ -61,6 +69,7 @@ public class ClientboundLevelChunkPacket implements Packet> 4; + + if (this.isFullChunk() || (includedSectionsMask & 1 << j) != 0) { ++ // Paper start - improve oversized chunk data packet handling ++ if (++totalTileEntities > TE_LIMIT) { ++ ClientboundBlockEntityDataPacket updatePacket = tileentity.getUpdatePacket(); ++ if (updatePacket != null) { ++ this.extraPackets.add(updatePacket); ++ continue; ++ } ++ } ++ // Paper end + CompoundTag nbttagcompound = tileentity.getUpdateTag(); + if (tileentity instanceof SkullBlockEntity) { SkullBlockEntity.sanitizeTileEntityUUID(nbttagcompound); } // Paper + diff --git a/patches/server-remapped/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/patches/server-remapped/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch new file mode 100644 index 0000000000..1209aa99ea --- /dev/null +++ b/patches/server-remapped/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 2 Mar 2019 16:12:35 -0500 +Subject: [PATCH] MC-145260: Fix Whitelist On/Off inconsistency + +mojang stored whitelist state in 2 places (Whitelist Object, PlayerList) + +some things checked PlayerList, some checked object. This moves +everything to the Whitelist object. + +https://github.com/PaperMC/Paper/issues/1880 + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 5b71b487836cdd2ddc75b2039f4dc0177719d345..8d133d3c825f7747081de99ee67d4556e5c19cdd 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -55,6 +55,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.PlayerAdvancements; + import net.minecraft.server.ServerScoreboard; +@@ -1012,9 +1013,9 @@ public abstract class PlayerList { + } + public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { + boolean isOp = this.ops.contains(gameprofile); +- boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile); ++ boolean isWhitelisted = !this.isUsingWhitelist() || isOp || this.whitelist.contains(gameprofile); + final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; +- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); ++ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.isUsingWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); + event.callEvent(); + if (!event.isWhitelisted()) { + if (loginEvent != null) { +@@ -1062,7 +1063,7 @@ public abstract class PlayerList { + MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main + MinecraftTimings.savePlayers.startTiming(); // Paper + for (int i = 0; i < this.players.size(); ++i) { +- this.savePlayerFile((EntityPlayer) this.players.get(i)); ++ this.save((ServerPlayer) this.players.get(i)); + } + MinecraftTimings.savePlayers.stopTiming(); // Paper + return null; }); // Paper - ensure main diff --git a/patches/server-remapped/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/patches/server-remapped/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch new file mode 100644 index 0000000000..eb4f5ff56c --- /dev/null +++ b/patches/server-remapped/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 4 Mar 2019 02:23:28 -0500 +Subject: [PATCH] Set Zombie last tick at start of drowning process + +Fixes GH-1887 + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index ad4eeb15771750193a28116117992270c72a3644..6fecf4188fc0247143edc688c03e645376960687 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -220,6 +220,7 @@ public class Zombie extends Monster { + ++this.inWaterTime; + if (this.inWaterTime >= 600) { + this.startUnderWaterConversion(300); ++ this.lastTick = MinecraftServer.currentTick; // Paper - Make sure this is set at start of process - GH-1887 + } + } else { + this.inWaterTime = -1; diff --git a/patches/server-remapped/0332-Allow-Saving-of-Oversized-Chunks.patch b/patches/server-remapped/0332-Allow-Saving-of-Oversized-Chunks.patch new file mode 100644 index 0000000000..c23cb450e8 --- /dev/null +++ b/patches/server-remapped/0332-Allow-Saving-of-Oversized-Chunks.patch @@ -0,0 +1,271 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 15 Feb 2019 01:08:19 -0500 +Subject: [PATCH] Allow Saving of Oversized Chunks + +The Minecraft World Region File format has a hard cap of 1MB per chunk. +This is due to the fact that the header of the file format only allocates +a single byte for sector count, meaning a maximum of 256 sectors, at 4k per sector. + +This limit can be reached fairly easily with books, resulting in the chunk being unable +to save to the world. Worse off, is that nothing printed when this occured, and silently +performed a chunk rollback on next load. + +This leads to security risk with duplication and is being actively exploited. + +This patch catches the too large scenario, falls back and moves any large Entity +or Tile Entity into a new compound, and this compound is saved into a different file. + +On Chunk Load, we check for oversized status, and if so, we load the extra file and +merge the Entities and Tile Entities from the oversized chunk back into the level to +then be loaded as normal. + +Once a chunk is returned back to normal size, the oversized flag will clear, and no +extra data file will exist. + +This fix maintains compatability with all existing Anvil Region Format tools as it +does not alter the save format. They will just not know about the extra entities. + +This fix also maintains compatability if someone switches server jars to one without +this fix, as the data will remain in the oversized file. Once the server returns +to a jar with this fix, the data will be restored. + +diff --git a/src/main/java/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java +index c4fbc0bc8b80d16f09d3c6642acc7476a0817868..b3838e709c1581c25da7738c9a03a827761845b1 100644 +--- a/src/main/java/net/minecraft/nbt/NbtIo.java ++++ b/src/main/java/net/minecraft/nbt/NbtIo.java +@@ -132,6 +132,7 @@ public class NbtIo { + + } + ++ public static CompoundTag readNBT(DataInput datainput) throws IOException { return read(datainput); } // Paper - OBFHELPER + public static CompoundTag read(DataInput input) throws IOException { + return read(input, NbtAccounter.UNLIMITED); + } +@@ -152,6 +153,7 @@ public class NbtIo { + } + } + ++ public static void writeNBT(CompoundTag nbttagcompound, DataOutput dataoutput) throws IOException { write(nbttagcompound, dataoutput); } // Paper - OBFHELPER + public static void write(CompoundTag tag, DataOutput output) throws IOException { + writeUnnamedTag((Tag) tag, output); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 1aa4d342b97f8be71c108194a6f1e0e2828aa364..424628c9588c02454558bc7e7c5bad3a3e75ec9f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -20,8 +20,12 @@ import java.nio.file.LinkOption; + import java.nio.file.Path; + import java.nio.file.StandardCopyOption; + import java.nio.file.StandardOpenOption; ++import java.util.zip.InflaterInputStream; // Paper ++ + import javax.annotation.Nullable; + import net.minecraft.Util; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtIo; + import net.minecraft.world.level.ChunkPos; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -38,6 +42,7 @@ public class RegionFile implements AutoCloseable { + private final IntBuffer timestamps; + @VisibleForTesting + protected final RegionBitmap usedSectors; ++ public final File file; // Paper + + public RegionFile(File file, File directory, boolean dsync) throws IOException { + this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); +@@ -45,6 +50,8 @@ public class RegionFile implements AutoCloseable { + + public RegionFile(Path file, Path directory, RegionFileVersion outputChunkStreamVersion, boolean dsync) throws IOException { + this.header = ByteBuffer.allocateDirect(8192); ++ this.file = file.toFile(); // Paper ++ initOversizedState(); // Paper + this.usedSectors = new RegionBitmap(); + this.version = outputChunkStreamVersion; + if (!Files.isDirectory(directory, new LinkOption[0])) { +@@ -408,6 +415,74 @@ public class RegionFile implements AutoCloseable { + void run() throws IOException; + } + ++ // Paper start ++ private final byte[] oversized = new byte[1024]; ++ private int oversizedCount = 0; ++ ++ private synchronized void initOversizedState() throws IOException { ++ File metaFile = getOversizedMetaFile(); ++ if (metaFile.exists()) { ++ final byte[] read = java.nio.file.Files.readAllBytes(metaFile.toPath()); ++ System.arraycopy(read, 0, oversized, 0, oversized.length); ++ for (byte temp : oversized) { ++ oversizedCount += temp; ++ } ++ } ++ } ++ ++ private static int getChunkIndex(int x, int z) { ++ return (x & 31) + (z & 31) * 32; ++ } ++ synchronized boolean isOversized(int x, int z) { ++ return this.oversized[getChunkIndex(x, z)] == 1; ++ } ++ synchronized void setOversized(int x, int z, boolean oversized) throws IOException { ++ final int offset = getChunkIndex(x, z); ++ boolean previous = this.oversized[offset] == 1; ++ this.oversized[offset] = (byte) (oversized ? 1 : 0); ++ if (!previous && oversized) { ++ oversizedCount++; ++ } else if (!oversized && previous) { ++ oversizedCount--; ++ } ++ if (previous && !oversized) { ++ File oversizedFile = getOversizedFile(x, z); ++ if (oversizedFile.exists()) { ++ oversizedFile.delete(); ++ } ++ } ++ if (oversizedCount > 0) { ++ if (previous != oversized) { ++ writeOversizedMeta(); ++ } ++ } else if (previous) { ++ File oversizedMetaFile = getOversizedMetaFile(); ++ if (oversizedMetaFile.exists()) { ++ oversizedMetaFile.delete(); ++ } ++ } ++ } ++ ++ private void writeOversizedMeta() throws IOException { ++ java.nio.file.Files.write(getOversizedMetaFile().toPath(), oversized); ++ } ++ ++ private File getOversizedMetaFile() { ++ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + ".oversized.nbt"); ++ } ++ ++ private File getOversizedFile(int x, int z) { ++ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); ++ } ++ ++ synchronized CompoundTag getOversizedData(int x, int z) throws IOException { ++ File file = getOversizedFile(x, z); ++ try (DataInputStream out = new DataInputStream(new BufferedInputStream(new InflaterInputStream(new java.io.FileInputStream(file))))) { ++ return NbtIo.readNBT((java.io.DataInput) out); ++ } ++ ++ } ++ // Paper end + class ChunkBuffer extends ByteArrayOutputStream { + + private final ChunkPos pos; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index f33a5fc725d1d5e895f8878d82ebc4172237ad29..6d3e1bb20d1ab8ce5c9ea613322042d80550761a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -10,7 +10,9 @@ import java.io.File; + import java.io.IOException; + import javax.annotation.Nullable; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtIo; ++import net.minecraft.nbt.Tag; + import net.minecraft.server.MinecraftServer; + import net.minecraft.util.ExceptionCollector; + import net.minecraft.world.level.ChunkPos; +@@ -50,6 +52,74 @@ public final class RegionFileStorage implements AutoCloseable { + } + } + ++ // Paper start ++ private static void printOversizedLog(String msg, File file, int x, int z) { ++ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); ++ } ++ ++ private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 8; ++ private static final int OVERZEALOUS_TOTAL_THRESHOLD = 1024 * 64; ++ private static final int OVERZEALOUS_THRESHOLD = 1024; ++ private static int SIZE_THRESHOLD = DEFAULT_SIZE_THRESHOLD; ++ private static void resetFilterThresholds() { ++ SIZE_THRESHOLD = Math.max(1024 * 4, Integer.getInteger("Paper.FilterThreshhold", DEFAULT_SIZE_THRESHOLD)); ++ } ++ static { ++ resetFilterThresholds(); ++ } ++ ++ static boolean isOverzealous() { ++ return SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD; ++ } ++ ++ ++ private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException { ++ synchronized (regionfile) { ++ try (DataInputStream datainputstream = regionfile.getReadStream(chunkCoordinate)) { ++ CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); ++ CompoundTag chunk = NbtIo.readNBT((DataInput) datainputstream); ++ if (oversizedData == null) { ++ return chunk; ++ } ++ CompoundTag oversizedLevel = oversizedData.getCompound("Level"); ++ CompoundTag level = chunk.getCompound("Level"); ++ ++ mergeChunkList(level, oversizedLevel, "Entities"); ++ mergeChunkList(level, oversizedLevel, "TileEntities"); ++ ++ chunk.put("Level", level); ++ ++ return chunk; ++ } catch (Throwable throwable) { ++ throwable.printStackTrace(); ++ throw throwable; ++ } ++ } ++ } ++ ++ private static void mergeChunkList(CompoundTag level, CompoundTag oversizedLevel, String key) { ++ ListTag levelList = level.getList(key, 10); ++ ListTag oversizedList = oversizedLevel.getList(key, 10); ++ ++ if (!oversizedList.isEmpty()) { ++ levelList.addAll(oversizedList); ++ level.put(key, levelList); ++ } ++ } ++ ++ private static int getNBTSize(Tag nbtBase) { ++ DataOutputStream test = new DataOutputStream(new org.apache.commons.io.output.NullOutputStream()); ++ try { ++ nbtBase.write(test); ++ return test.size(); ++ } catch (IOException e) { ++ e.printStackTrace(); ++ return 0; ++ } ++ } ++ ++ // Paper End ++ + @Nullable + public CompoundTag read(ChunkPos pos) throws IOException { + // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing +@@ -59,6 +129,12 @@ public final class RegionFileStorage implements AutoCloseable { + } + // CraftBukkit end + DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); ++ // Paper start ++ if (regionfile.isOversized(pos.x, pos.z)) { ++ printOversizedLog("Loading Oversized Chunk!", regionfile.file, pos.x, pos.z); ++ return readOversizedChunk(regionfile, pos); ++ } ++ // Paper end + Throwable throwable = null; + + CompoundTag nbttagcompound; +@@ -99,6 +175,7 @@ public final class RegionFileStorage implements AutoCloseable { + + try { + NbtIo.write(tag, (DataOutput) dataoutputstream); ++ regionfile.setOversized(pos.x, pos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone + } catch (Throwable throwable1) { + throwable = throwable1; + throw throwable1; diff --git a/patches/server-remapped/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/patches/server-remapped/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch new file mode 100644 index 0000000000..5fcbc4df8c --- /dev/null +++ b/patches/server-remapped/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Wed, 13 Mar 2019 20:08:09 +0200 +Subject: [PATCH] Call WhitelistToggleEvent when whitelist is toggled + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 8d133d3c825f7747081de99ee67d4556e5c19cdd..728eaadd3dc619e414ec30feb38c7d4a84b2e539 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1131,6 +1131,7 @@ public abstract class PlayerList { + } + + public void setUsingWhiteList(boolean whitelistEnabled) { ++ new com.destroystokyo.paper.event.server.WhitelistToggleEvent(whitelistEnabled).callEvent(); + this.doWhiteList = whitelistEnabled; + } + diff --git a/patches/server-remapped/0334-Add-LivingEntity-getTargetEntity.patch b/patches/server-remapped/0334-Add-LivingEntity-getTargetEntity.patch new file mode 100644 index 0000000000..d02aab104b --- /dev/null +++ b/patches/server-remapped/0334-Add-LivingEntity-getTargetEntity.patch @@ -0,0 +1,187 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 22 Sep 2018 00:33:08 -0500 +Subject: [PATCH] Add LivingEntity#getTargetEntity + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index c5d6235a132818dfc78105e9d03d0687f697bb00..d106118dbf4fb270f8526e40a767dd4c563a333f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1503,6 +1503,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.calculateViewVector(pitch - 90.0F, yaw); + } + ++ public final Vec3 getEyePosition(float partialTicks) { return getEyePosition(partialTicks); } // Paper - OBFHELPER + public final Vec3 getEyePosition(float tickDelta) { + if (tickDelta == 1.0F) { + return new Vec3(this.getX(), this.getEyeY(), this.getZ()); +@@ -2153,6 +2154,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.getPassengers().size() < 1; + } + ++ public final float getCollisionBorderSize() { return getPickRadius(); } // Paper - OBFHELPER + public float getPickRadius() { + return 0.0F; + } +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index e92a8c4c49c452e1f3f0c06398f2a74e3432262f..d3640975c5a33b4911428760691215905b987385 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -22,6 +22,7 @@ public final class EntitySelector { + public static final Predicate NO_CREATIVE_OR_SPECTATOR = (entity) -> { + return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative(); + }; ++ public static Predicate canAITarget() { return ATTACK_ALLOWED; } // Paper - OBFHELPER + public static final Predicate ATTACK_ALLOWED = (entity) -> { + return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative() && entity.level.getDifficulty() != Difficulty.PEACEFUL; + }; +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 29d4ed42e5d763639a50d849ef274c4d848bc9c9..046a05925739005080af35c4be984303b575bf68 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -108,6 +108,7 @@ import net.minecraft.world.level.storage.loot.LootTable; + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.PlayerTeam; +@@ -3657,6 +3658,37 @@ public abstract class LivingEntity extends Entity { + return level.clip(raytrace); + } + ++ public EntityHitResult getTargetEntity(int maxDistance) { ++ if (maxDistance < 1 || maxDistance > 120) { ++ throw new IllegalArgumentException("maxDistance must be between 1-120"); ++ } ++ ++ Vec3 start = this.getEyePosition(1.0F); ++ Vec3 direction = this.getLookAngle(); ++ Vec3 end = start.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance); ++ ++ List entityList = level.getEntities(this, getBoundingBox().expand(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance).inflate(1.0D, 1.0D, 1.0D), EntitySelector.canAITarget().and(Entity::isPickable)); ++ ++ double distance = 0.0D; ++ EntityHitResult result = null; ++ ++ for (Entity entity : entityList) { ++ AABB aabb = entity.getBoundingBox().grow((double) entity.getCollisionBorderSize()); ++ Optional rayTraceResult = aabb.calculateIntercept(start, end); ++ ++ if (rayTraceResult.isPresent()) { ++ Vec3 rayTrace = rayTraceResult.get(); ++ double distanceTo = start.distanceToSqr(rayTrace); ++ if (distanceTo < distance || distance == 0.0D) { ++ result = new EntityHitResult(entity, rayTrace); ++ distance = distanceTo; ++ } ++ } ++ } ++ ++ return result; ++ } ++ + public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; + + public int getShieldBlockingDelay() { +diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java +index 983d0495ec35128ca3ef68566ada065bc4b21efc..143a160a7577e9e34d34a9f3b900db03d3f297af 100644 +--- a/src/main/java/net/minecraft/world/phys/AABB.java ++++ b/src/main/java/net/minecraft/world/phys/AABB.java +@@ -116,6 +116,7 @@ public class AABB { + return this.expandTowards(scale.x, scale.y, scale.z); + } + ++ public final AABB expand(double x, double y, double z) { return expandTowards(x, y, z); } // Paper - OBFHELPER + public AABB expandTowards(double x, double y, double z) { + double d3 = this.minX; + double d4 = this.minY; +@@ -145,6 +146,12 @@ public class AABB { + return new AABB(d3, d4, d5, d6, d7, d8); + } + ++ // Paper start ++ public AABB grow(double d0) { ++ return inflate(d0, d0, d0); ++ } ++ // Paper end ++ + public AABB inflate(double x, double y, double z) { + double d3 = this.minX - x; + double d4 = this.minY - y; +@@ -204,6 +211,7 @@ public class AABB { + return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ; + } + ++ public final boolean contains(Vec3 vec3d) { return contains(vec3d); } // Paper - OBFHELPER + public boolean contains(Vec3 vec) { + return this.contains(vec.x, vec.y, vec.z); + } +@@ -237,6 +245,7 @@ public class AABB { + return this.inflate(-value); + } + ++ public final Optional calculateIntercept(Vec3 vec3d, Vec3 vec3d1) { return clip(vec3d, vec3d1); } // Paper - OBFHELPER + public Optional clip(Vec3 min, Vec3 max) { + double[] adouble = new double[]{1.0D}; + double d0 = max.x - min.x; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 7e3a215f1592bed9f35e22076d9e35a5a49a430e..a01bd035846df0e2e28dc55e2ef2f5f35b83f905 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -1,6 +1,7 @@ + package org.bukkit.craftbukkit.entity; + + import com.destroystokyo.paper.block.TargetBlockInfo; ++import com.destroystokyo.paper.entity.TargetEntityInfo; + import com.google.common.base.Preconditions; + import com.google.common.collect.Sets; + import java.util.ArrayList; +@@ -30,8 +31,11 @@ import net.minecraft.world.entity.projectile.ThrownEgg; + import net.minecraft.world.entity.projectile.ThrownEnderpearl; + import net.minecraft.world.entity.projectile.ThrownExperienceBottle; + import net.minecraft.world.entity.projectile.ThrownTrident; ++import net.minecraft.world.level.ClipContext; + import net.minecraft.world.phys.BlockHitResult; ++import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang.Validate; + import org.bukkit.FluidCollisionMode; + import org.bukkit.Location; +@@ -215,6 +219,33 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + new TargetBlockInfo(CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()), + MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection())); + } ++ ++ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks) { ++ EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); ++ return rayTrace == null ? null : rayTrace.getEntity().getBukkitEntity(); ++ } ++ ++ public TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks) { ++ EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); ++ return rayTrace == null ? null : new TargetEntityInfo(rayTrace.getEntity().getBukkitEntity(), new org.bukkit.util.Vector(rayTrace.getLocation().x, rayTrace.getLocation().y, rayTrace.getLocation().z)); ++ } ++ ++ public EntityHitResult rayTraceEntity(int maxDistance, boolean ignoreBlocks) { ++ EntityHitResult rayTrace = getHandle().getTargetEntity(maxDistance); ++ if (rayTrace == null) { ++ return null; ++ } ++ if (!ignoreBlocks) { ++ HitResult rayTraceBlocks = getHandle().getRayTrace(maxDistance, ClipContext.Fluid.NONE); ++ if (rayTraceBlocks != null) { ++ Vec3 eye = getHandle().getEyePosition(1.0F); ++ if (eye.distanceToSqr(rayTraceBlocks.getLocation()) <= eye.distanceToSqr(rayTrace.getLocation())) { ++ return null; ++ } ++ } ++ } ++ return rayTrace; ++ } + // Paper end + + @Override diff --git a/patches/server-remapped/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/patches/server-remapped/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch new file mode 100644 index 0000000000..c6e42c264d --- /dev/null +++ b/patches/server-remapped/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 20 Mar 2019 21:19:29 -0700 +Subject: [PATCH] Use proper max length when serialising BungeeCord text + component + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +index f13da9e7d014bc00fbabf0a495b548bba2f59468..002a6c7933f64405707d7d34d3e5c17584539623 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +@@ -9,7 +9,7 @@ import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.Packet; + + public class ClientboundChatPacket implements Packet { +- ++ private static final int MAX_LENGTH = Short.MAX_VALUE * 8 + 8; // Paper + private Component message; + public net.kyori.adventure.text.Component adventure$message; // Paper + public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot +@@ -43,9 +43,9 @@ public class ClientboundChatPacket implements Packet { + //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below + // Paper start - don't nest if we don't need to so that we can preserve formatting + if (this.components.length == 1) { +- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); ++ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]), MAX_LENGTH); // Paper - use proper max length + } else { +- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); ++ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components), MAX_LENGTH); // Paper - use proper max length + } + // Paper end + } else { diff --git a/patches/server-remapped/0336-Entity-getEntitySpawnReason.patch b/patches/server-remapped/0336-Entity-getEntitySpawnReason.patch new file mode 100644 index 0000000000..18095e343f --- /dev/null +++ b/patches/server-remapped/0336-Entity-getEntitySpawnReason.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Mar 2019 00:24:52 -0400 +Subject: [PATCH] Entity#getEntitySpawnReason + +Allows you to return the SpawnReason for why an Entity Spawned + +Pre existing entities will return NATURAL if it was a non +persistenting Living Entity, SPAWNER for spawners, +or DEFAULT since data was not stored. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 2ab221e5315dde4e556ee49a6962ae0091ccf616..d03b4f97102dfb88927a94ee5a5d397ac493eaa1 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1035,6 +1035,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // CraftBukkit start + private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot ++ if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper + // Paper start + if (entity.valid) { + MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 728eaadd3dc619e414ec30feb38c7d4a84b2e539..4d813b6556030354f51c1ee5f18eac2166b44576 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -331,7 +331,7 @@ public abstract class PlayerList { + // CraftBukkit start + ServerLevel finalWorldServer = worldserver1; + Entity entity = EntityType.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { +- return !finalWorldServer.addWithUUID(entity1) ? null : entity1; ++ return !finalWorldServer.addEntitySerialized(entity1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity1; // Paper + // CraftBukkit end + }); + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f311e197f6e 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -63,6 +63,8 @@ import net.minecraft.world.InteractionHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.Nameable; + import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.animal.AbstractFish; ++import net.minecraft.world.entity.animal.Animal; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.Boat; +@@ -157,6 +159,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + }; + public List entitySlice = null; ++ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; + // Paper end + + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper +@@ -1673,6 +1676,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); + tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); + } ++ if (spawnReason != null) { ++ tag.putString("Paper.SpawnReason", spawnReason.name()); ++ } + // Save entity's from mob spawner status + if (spawnedViaMobSpawner) { + tag.putBoolean("Paper.FromMobSpawner", true); +@@ -1811,6 +1817,26 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ if (tag.contains("Paper.SpawnReason")) { ++ String spawnReasonName = tag.getString("Paper.SpawnReason"); ++ try { ++ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName); ++ } catch (Exception ignored) { ++ LogManager.getLogger().error("Unknown SpawnReason " + spawnReasonName + " for " + this); ++ } ++ } ++ if (spawnReason == null) { ++ if (spawnedViaMobSpawner) { ++ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; ++ } else if (this instanceof Mob && (this instanceof Animal || this instanceof AbstractFish) && !((Mob) this).removeWhenFarAway(0.0)) { ++ if (!tag.getBoolean("PersistenceRequired")) { ++ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL; ++ } ++ } ++ } ++ if (spawnReason == null) { ++ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; ++ } + // Paper end + + } catch (Throwable throwable) { +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 1ce675d0d24ceb5724f5ac2d8f671e38f2735f74..3a7aec9bd2f3fd1b4a1981fb6a8c64b69e4875f8 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -183,6 +183,7 @@ public abstract class BaseSpawner { + // Spigot End + } + entity.spawnedViaMobSpawner = true; // Paper ++ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper + flag = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index e1bbaf620f3ed2a6cb9ce8007a78c4cee47b653e..7ad4fb57af32cc1b8278688381e1b058ed8437db 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1106,5 +1106,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public boolean fromMobSpawner() { + return getHandle().spawnedViaMobSpawner; + } ++ ++ @Override ++ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { ++ return getHandle().spawnReason; ++ } + // Paper end + } diff --git a/patches/server-remapped/0337-Update-entity-Metadata-for-all-tracked-players.patch b/patches/server-remapped/0337-Update-entity-Metadata-for-all-tracked-players.patch new file mode 100644 index 0000000000..8f0ddb740c --- /dev/null +++ b/patches/server-remapped/0337-Update-entity-Metadata-for-all-tracked-players.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AgentTroll +Date: Fri, 22 Mar 2019 22:24:03 -0700 +Subject: [PATCH] Update entity Metadata for all tracked players + + +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index 49c71b21b6b88bc41ca6ddf4c76186ce522ee456..1609ab94c86e964421f996d4d46aef30f8b8e696 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -420,6 +420,12 @@ public class ServerEntity { + return ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp); + } + ++ // Paper start - Add broadcast method ++ void broadcast(Packet packet) { ++ this.getPacketConsumer().accept(packet); ++ } ++ // Paper end ++ + private void broadcastAndSend(Packet packet) { + this.broadcast.accept(packet); + if (this.entity instanceof ServerPlayer) { +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index d6d8d83bc16572474d56a278dd119eacc2c52476..ed4129a51351aff16455960d71a0add1b8209c02 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2286,7 +2286,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + if (event.isCancelled() || this.player.inventory.getSelected() == null || this.player.inventory.getSelected().getItem() != origItem) { + // Refresh the current entity metadata +- this.send(new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true)); ++ // Paper start - update entity for all players ++ ClientboundSetEntityDataPacket packet1 = new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true); ++ if (entity.tracker != null) { ++ entity.tracker.broadcast(packet1); ++ } else { ++ this.send(packet1); ++ } ++ // Paper end + } + + if (event.isCancelled()) { diff --git a/patches/server-remapped/0338-Implement-PlayerPostRespawnEvent.patch b/patches/server-remapped/0338-Implement-PlayerPostRespawnEvent.patch new file mode 100644 index 0000000000..dbfcbf2e3f --- /dev/null +++ b/patches/server-remapped/0338-Implement-PlayerPostRespawnEvent.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MisterVector +Date: Fri, 26 Oct 2018 21:31:00 -0700 +Subject: [PATCH] Implement PlayerPostRespawnEvent + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 4d813b6556030354f51c1ee5f18eac2166b44576..7412765020854caabd32fb6f4fffcf7f4bf6dba7 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -737,9 +737,14 @@ public abstract class PlayerList { + // this.a(entityplayer1, entityplayer, worldserver1); // CraftBukkit - removed + boolean flag2 = false; + ++ // Paper start ++ boolean isBedSpawn = false; ++ boolean isRespawn = false; ++ // Paper end ++ + // CraftBukkit start - fire PlayerRespawnEvent + if (location == null) { +- boolean isBedSpawn = false; ++ // boolean isBedSpawn = false; // Paper - moved up + ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); + if (worldserver1 != null) { + Optional optional; +@@ -790,6 +795,7 @@ public abstract class PlayerList { + + location = respawnEvent.getRespawnLocation(); + if (!flag) entityplayer.reset(); // SPIGOT-4785 ++ isRespawn = true; // Paper + } else { + location.setWorld(worldserver.getWorld()); + } +@@ -847,6 +853,13 @@ public abstract class PlayerList { + if (entityplayer.connection.isDisconnected()) { + this.save(entityplayer); + } ++ ++ // Paper start ++ if (isRespawn) { ++ cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(entityplayer.getBukkitEntity(), location, isBedSpawn)); ++ } ++ // Paper end ++ + // CraftBukkit end + return entityplayer1; + } diff --git a/patches/server-remapped/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/patches/server-remapped/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch new file mode 100644 index 0000000000..df8e4e2e9a --- /dev/null +++ b/patches/server-remapped/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Mar 2019 18:09:20 -0400 +Subject: [PATCH] don't go below 0 for pickupDelay, breaks picking up items + +vanilla checks for == 0 + +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 70f719ba3c68c8e9414e6b4bc68002f7c962e2b9..281f5646980afc70890bdafd358ff9b20d32420d 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -86,6 +86,7 @@ public class ItemEntity extends Entity { + // CraftBukkit start - Use wall time for pickup and despawn timers + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; ++ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 + if (this.age != -32768) this.age += elapsedTicks; + this.lastTick = MinecraftServer.currentTick; + // CraftBukkit end +@@ -178,6 +179,7 @@ public class ItemEntity extends Entity { + // CraftBukkit start - Use wall time for pickup and despawn timers + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; ++ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 + if (this.age != -32768) this.age += elapsedTicks; + this.lastTick = MinecraftServer.currentTick; + // CraftBukkit end diff --git a/patches/server-remapped/0340-Server-Tick-Events.patch b/patches/server-remapped/0340-Server-Tick-Events.patch new file mode 100644 index 0000000000..9fb3057ffc --- /dev/null +++ b/patches/server-remapped/0340-Server-Tick-Events.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 27 Mar 2019 22:48:45 -0400 +Subject: [PATCH] Server Tick Events + +Fires event at start and end of a server tick + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 6ccc0be795e3ac7689de0eff6f9142d13161a29c..35984c7e994570a909ed4ffaabe64ae941b15e71 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1237,6 +1237,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Wed, 27 Mar 2019 23:01:33 -0400 +Subject: [PATCH] PlayerDeathEvent#getItemsToKeep + +Exposes a mutable array on items a player should keep on death + +Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4 + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index fd2717a00a85f91ee23a1c0f929f856972892a9b..d6cfe68be1a944ff5d5780666467f5fd8e2794e3 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -692,6 +692,46 @@ public class ServerPlayer extends Player implements ContainerListener { + }); + } + ++ // Paper start - process inventory ++ private static void processKeep(org.bukkit.event.entity.PlayerDeathEvent event, NonNullList inv) { ++ List itemsToKeep = event.getItemsToKeep(); ++ if (inv == null) { ++ // remainder of items left in toKeep - plugin added stuff on death that wasn't in the initial loot? ++ if (!itemsToKeep.isEmpty()) { ++ for (org.bukkit.inventory.ItemStack itemStack : itemsToKeep) { ++ event.getEntity().getInventory().addItem(itemStack); ++ } ++ } ++ ++ return; ++ } ++ ++ for (int i = 0; i < inv.size(); ++i) { ++ ItemStack item = inv.get(i); ++ if (EnchantmentHelper.hasVanishingCurse(item) || itemsToKeep.isEmpty() || item.isEmpty()) { ++ inv.set(i, ItemStack.NULL_ITEM); ++ continue; ++ } ++ ++ final org.bukkit.inventory.ItemStack bukkitStack = item.getBukkitStack(); ++ boolean keep = false; ++ final Iterator iterator = itemsToKeep.iterator(); ++ while (iterator.hasNext()) { ++ final org.bukkit.inventory.ItemStack itemStack = iterator.next(); ++ if (bukkitStack.equals(itemStack)) { ++ iterator.remove(); ++ keep = true; ++ break; ++ } ++ } ++ ++ if (!keep) { ++ inv.set(i, ItemStack.NULL_ITEM); ++ } ++ } ++ } ++ // Paper end ++ + @Override + public void die(DamageSource source) { + boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); +@@ -775,7 +815,12 @@ public class ServerPlayer extends Player implements ContainerListener { + this.dropExperience(); + // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. + if (!event.getKeepInventory()) { +- this.inventory.clearContent(); ++ // Paper start - replace logic ++ for (NonNullList inv : this.inventory.getComponents()) { ++ processKeep(event, inv); ++ } ++ processKeep(event, null); ++ // Paper end + } + + this.setCamera(this); // Remove spectated target diff --git a/patches/server-remapped/0342-Optimize-Captured-TileEntity-Lookup.patch b/patches/server-remapped/0342-Optimize-Captured-TileEntity-Lookup.patch new file mode 100644 index 0000000000..5c22ff496a --- /dev/null +++ b/patches/server-remapped/0342-Optimize-Captured-TileEntity-Lookup.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 6 Apr 2019 10:16:48 -0400 +Subject: [PATCH] Optimize Captured TileEntity Lookup + +upstream was doing a containsKey/get pattern, and always doing it at that. +that scenario is only even valid if were in the middle of a block place. + +Optimize to check if the captured list even has values in it, and also to +just do a get call since the value can never be null. + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index c8542636e89748699d608eb29569cacb6321d334..5193271bc257248e0d2bc9d9a477e999a97deada 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -968,12 +968,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return null; + } else { + // CraftBukkit start +- if (capturedTileEntities.containsKey(blockposition)) { +- return capturedTileEntities.get(blockposition); ++ BlockEntity tileentity = null; // Paper ++ if (!capturedTileEntities.isEmpty() && (tileentity = capturedTileEntities.get(blockposition)) != null) { // Paper ++ return tileentity; // Paper + } + // CraftBukkit end + +- BlockEntity tileentity = null; ++ //TileEntity tileentity = null; // Paper - move up + + if (this.updatingBlockEntities) { + tileentity = this.getPendingBlockEntityAt(blockposition); diff --git a/patches/server-remapped/0343-Add-Heightmap-API.patch b/patches/server-remapped/0343-Add-Heightmap-API.patch new file mode 100644 index 0000000000..2926bb8ee6 --- /dev/null +++ b/patches/server-remapped/0343-Add-Heightmap-API.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 1 Jan 2019 02:22:01 -0800 +Subject: [PATCH] Add Heightmap API + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 5193271bc257248e0d2bc9d9a477e999a97deada..eb88d830fb45a6b8c990e8bdc1943d80f63c8b93 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -670,8 +670,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + } + +- @Override +- public int getHeight(Heightmap.Types heightmap, int x, int z) { ++ public final int getHighestBlockY(final Heightmap.Types heightmap, final int x, final int z) { return this.getHeight(heightmap, x, z); } // Paper - OBFHELPER ++ @Override public int getHeight(Heightmap.Types heightmap, int x, int z) { // Paper - OBFHELPER + int k; + + if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 7b5abccac9793811bd56340c8f9d23806e832365..a4231e1c3d468355c0b55ac9d2c239f1b4c54594 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -325,6 +325,29 @@ public class CraftWorld implements World { + return getHighestBlockYAt(x, z, org.bukkit.HeightMap.MOTION_BLOCKING); + } + ++ // Paper start - Implement heightmap api ++ @Override ++ public int getHighestBlockYAt(final int x, final int z, final com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { ++ this.getChunkAt(x >> 4, z >> 4); // heightmap will ret 0 on unloaded areas ++ ++ switch (heightmap) { ++ case LIGHT_BLOCKING: ++ throw new UnsupportedOperationException(); // TODO ++ //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z); ++ case ANY: ++ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE, x, z); ++ case SOLID: ++ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR, x, z); ++ case SOLID_OR_LIQUID: ++ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING, x, z); ++ case SOLID_OR_LIQUID_NO_LEAVES: ++ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z); ++ default: ++ throw new UnsupportedOperationException(); ++ } ++ } ++ // Paper end ++ + @Override + public Location getSpawnLocation() { + BlockPos spawn = world.getSpawn(); diff --git a/patches/server-remapped/0344-Mob-Spawner-API-Enhancements.patch b/patches/server-remapped/0344-Mob-Spawner-API-Enhancements.patch new file mode 100644 index 0000000000..b3ee864737 --- /dev/null +++ b/patches/server-remapped/0344-Mob-Spawner-API-Enhancements.patch @@ -0,0 +1,139 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 19 Apr 2019 12:41:13 -0500 +Subject: [PATCH] Mob Spawner API Enhancements + + +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 3a7aec9bd2f3fd1b4a1981fb6a8c64b69e4875f8..6ca378ec7868b855d46c749910c656f82ddb009f 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -65,6 +65,7 @@ public abstract class BaseSpawner { + this.spawnPotentials.clear(); // CraftBukkit - SPIGOT-3496, MC-92282 + } + ++ public boolean isActivated() { return isNearPlayer(); } // Paper - OBFHELPER + private boolean isNearPlayer() { + BlockPos blockposition = this.getPos(); + +@@ -221,6 +222,7 @@ public abstract class BaseSpawner { + } + } + ++ public void resetTimer() { delay(); } // Paper - OBFHELPER + private void delay() { + if (this.maxSpawnDelay <= this.minSpawnDelay) { + this.spawnDelay = this.minSpawnDelay; +@@ -238,7 +240,13 @@ public abstract class BaseSpawner { + } + + public void load(CompoundTag tag) { ++ // Paper start - use larger int if set ++ if (tag.contains("Paper.Delay")) { ++ this.spawnDelay = tag.getInt("Paper.Delay"); ++ } else { + this.spawnDelay = tag.getShort("Delay"); ++ } ++ // Paper end + this.spawnPotentials.clear(); + if (tag.contains("SpawnPotentials", 9)) { + ListTag nbttaglist = tag.getList("SpawnPotentials", 10); +@@ -253,10 +261,15 @@ public abstract class BaseSpawner { + } else if (!this.spawnPotentials.isEmpty()) { + this.setNextSpawnData((SpawnData) WeighedRandom.getRandomItem(this.getLevel().random, this.spawnPotentials)); + } +- ++ // Paper start - use ints if set ++ if (tag.contains("Paper.MinSpawnDelay", 99)) { ++ this.minSpawnDelay = tag.getInt("Paper.MinSpawnDelay"); ++ this.maxSpawnDelay = tag.getInt("Paper.MaxSpawnDelay"); ++ this.spawnCount = tag.getShort("SpawnCount"); ++ } else // Paper end + if (tag.contains("MinSpawnDelay", 99)) { +- this.minSpawnDelay = tag.getShort("MinSpawnDelay"); +- this.maxSpawnDelay = tag.getShort("MaxSpawnDelay"); ++ this.minSpawnDelay = tag.getInt("MinSpawnDelay"); ++ this.maxSpawnDelay = tag.getInt("MaxSpawnDelay"); + this.spawnCount = tag.getShort("SpawnCount"); + } + +@@ -281,9 +294,20 @@ public abstract class BaseSpawner { + if (minecraftkey == null) { + return tag; + } else { +- tag.putShort("Delay", (short) this.spawnDelay); +- tag.putShort("MinSpawnDelay", (short) this.minSpawnDelay); +- tag.putShort("MaxSpawnDelay", (short) this.maxSpawnDelay); ++ // Paper start ++ if (spawnDelay > Short.MAX_VALUE) { ++ tag.putInt("Paper.Delay", this.spawnDelay); ++ } ++ tag.putShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay)); ++ ++ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) { ++ tag.putInt("Paper.MinSpawnDelay", this.minSpawnDelay); ++ tag.putInt("Paper.MaxSpawnDelay", this.maxSpawnDelay); ++ } ++ ++ tag.putShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay)); ++ tag.putShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay)); ++ // Paper end + tag.putShort("SpawnCount", (short) this.spawnCount); + tag.putShort("MaxNearbyEntities", (short) this.maxNearbyEntities); + tag.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 daaf861041cf7c8f59c85535ecb99e402ab4f658..a5b88b545e08eaabf894305a9bee31c55c5b1b87 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java +@@ -1,12 +1,20 @@ + package org.bukkit.craftbukkit.block; + + import com.google.common.base.Preconditions; ++import net.minecraft.core.Registry; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.world.level.SpawnData; + import net.minecraft.world.level.block.entity.SpawnerBlockEntity; + import org.bukkit.Material; + import org.bukkit.block.Block; + import org.bukkit.block.CreatureSpawner; + import org.bukkit.entity.EntityType; ++// Paper start ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.inventory.ItemStack; ++// Paper end + + public class CraftCreatureSpawner extends CraftBlockEntityState implements CreatureSpawner { + +@@ -120,4 +128,30 @@ public class CraftCreatureSpawner extends CraftBlockEntityState +Date: Mon, 6 May 2019 01:29:25 -0400 +Subject: [PATCH] Per-Player View Distance API placeholders + +I hope to look at this more in-depth soon. It appears doable. +However this should not block the update. + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index 37a9e9df7f7f816c214c37e545288bf9329626ed..ec9436005a3a6fdfb4783d1092bb361224eb6414 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -625,9 +625,10 @@ public class EnderDragon extends Mob implements Enemy { + if (this.dragonDeathTime == 1 && !this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1028, this.getChunkCoordinates(), 0); +- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API + for (net.minecraft.server.level.ServerPlayer player : (List) ((ServerLevel)level).players()) { +- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch ++ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch ++ // Paper end + double deltaX = this.getX() - player.getX(); + double deltaZ = this.getZ() - player.getZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +index 3a80869dc3c16cb81ac87100f28d63eee722067f..edd231568b75330d0cffbecb03a7e9dbc55d5f94 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -46,6 +46,7 @@ import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerBossEvent; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; +@@ -255,9 +256,9 @@ public class WitherBoss extends Monster implements RangedAttackMob { + if (!this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1023, new BlockPosition(this), 0); +- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API + for (ServerPlayer player : (List)this.level.players()) { +- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch ++ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch + double deltaX = this.getX() - player.getX(); + double deltaZ = this.getZ() - player.getZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index c2c6eb54096ef85b01c0b700cbe6a8054b62729f..20de8e358789d05bb5ac15e4cdd7dda85b61b7f8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2240,6 +2240,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + super.remove(); + } + } ++ ++ @Override ++ public int getViewDistance() { ++ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO ++ } ++ ++ @Override ++ public void setViewDistance(int viewDistance) { ++ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO ++ } + // Paper end + + // Spigot start diff --git a/patches/server-remapped/0346-Fix-CB-call-to-changed-postToMainThread-method.patch b/patches/server-remapped/0346-Fix-CB-call-to-changed-postToMainThread-method.patch new file mode 100644 index 0000000000..5853bd79ee --- /dev/null +++ b/patches/server-remapped/0346-Fix-CB-call-to-changed-postToMainThread-method.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Fri, 10 May 2019 18:38:19 +0100 +Subject: [PATCH] Fix CB call to changed postToMainThread method + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index ed4129a51351aff16455960d71a0add1b8209c02..4f99c3d06e3b994708c699395adf481a6828e097 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -443,7 +443,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + this.connection.getClass(); + // CraftBukkit - Don't wait +- minecraftserver.wrapRunnable(networkmanager::handleDisconnection); ++ minecraftserver.scheduleOnMain(networkmanager::handleDisconnection); // Paper + } + + private void filterTextPacket(T text, Consumer consumer, BiFunction>> backingFilterer) { diff --git a/patches/server-remapped/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/patches/server-remapped/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch new file mode 100644 index 0000000000..262820c228 --- /dev/null +++ b/patches/server-remapped/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Sat, 27 Apr 2019 20:00:43 +0100 +Subject: [PATCH] Fix sounds when item frames are modified (MC-123450) + +This also fixes the adding sound playing when the item frame direction is changed. + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java +index d6e6846a12a889222ced67937c09d184a64c60b9..429d8a50a35f07bfc16dbedf28560fa6df817644 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java +@@ -277,7 +277,7 @@ public class ItemFrame extends HangingEntity { + } + + this.getEntityData().set(ItemFrame.DATA_ITEM, itemstack); +- if (!itemstack.isEmpty() && playSound) { // CraftBukkit ++ if (!itemstack.isEmpty() && flag && playSound) { // CraftBukkit // Paper - only play sound when update flag is set + this.playSound(SoundEvents.ITEM_FRAME_ADD_ITEM, 1.0F, 1.0F); + } + diff --git a/patches/server-remapped/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/patches/server-remapped/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch new file mode 100644 index 0000000000..367d2e18c9 --- /dev/null +++ b/patches/server-remapped/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 13 May 2019 21:10:59 -0700 +Subject: [PATCH] Fix CraftServer#isPrimaryThread and MinecraftServer + isMainThread + +md_5 changed it so he could shut down the server asynchronously +from watchdog, although we have patches that prevent that type +of behavior for this exact reason. + +md_5 also placed code in PlayerConnectionUtils that would have +solved https://bugs.mojang.com/browse/MC-142590, making the change +to MinecraftServer#isMainThread irrelevant. +By reverting his change to MinecraftServer#isMainThread packet +handling that should have been handled synchronously will be handled +synchronously when the server gets shut down. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 35984c7e994570a909ed4ffaabe64ae941b15e71..9beda5e429b5c520a41d9c7f536dc48dbb6f6f9e 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2190,7 +2190,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Fri, 28 Sep 2018 21:49:53 -0400 +Subject: [PATCH] Fix issues with entity loss due to unloaded chunks + +Vanilla has risk of losing entities by causing them to be +removed from all chunks if they try to move into an unloaded chunk. + +This pretty much means high chance this entity will be lost in this +scenario. + +There is another case that adding an entity to the world can fail if +the chunk isn't loaded. + +Lots of the server is designed around addEntity never expecting to fail +for these reasons, nor is it really logical. + +This change ensures the chunks are always loaded when entities are +added to the world, or a valid entity moves between chunks. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index d03b4f97102dfb88927a94ee5a5d397ac493eaa1..99883c83c126405fc93becefed8a1d0727b94aa7 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -848,11 +848,18 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + int k = Mth.floor(entity.getZ() / 16.0D); + + if (!entity.inChunk || entity.xChunk != i || entity.yChunk != j || entity.zChunk != k) { ++ // Paper start - remove entity if its in a chunk more correctly. ++ LevelChunk currentChunk = entity.getCurrentChunk(); ++ if (currentChunk != null) { ++ currentChunk.removeEntity(entity); ++ } ++ // Paper end ++ + if (entity.inChunk && this.hasChunk(entity.xChunk, entity.zChunk)) { + this.getChunk(entity.xChunk, entity.zChunk).removeEntity(entity, entity.yChunk); + } + +- if (!entity.checkAndResetForcedChunkAdditionFlag() && !this.hasChunk(i, k)) { ++ if (!entity.valid && !entity.checkAndResetForcedChunkAdditionFlag() && !this.hasChunk(i, k)) { // Paper - always load chunks to register valid entities location + if (entity.inChunk) { + ServerLevel.LOGGER.warn("Entity {} left loaded chunk area", entity); + } +@@ -1067,7 +1074,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return false; + } + // CraftBukkit end +- ChunkAccess ichunkaccess = this.getChunk(Mth.floor(entity.getX() / 16.0D), Mth.floor(entity.getZ() / 16.0D), ChunkStatus.FULL, entity.forcedLoading); ++ ChunkAccess ichunkaccess = this.getChunk(Mth.floor(entity.getX() / 16.0D), Mth.floor(entity.getZ() / 16.0D), ChunkStatus.FULL, true); // Paper - always load chunks for entity adds + + if (!(ichunkaccess instanceof LevelChunk)) { + return false; diff --git a/patches/server-remapped/0350-Duplicate-UUID-Resolve-Option.patch b/patches/server-remapped/0350-Duplicate-UUID-Resolve-Option.patch new file mode 100644 index 0000000000..29914b85b0 --- /dev/null +++ b/patches/server-remapped/0350-Duplicate-UUID-Resolve-Option.patch @@ -0,0 +1,249 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 21 Jul 2018 14:27:34 -0400 +Subject: [PATCH] Duplicate UUID Resolve Option + +Due to a bug in https://github.com/PaperMC/Paper/commit/2e29af3df05ec0a383f48be549d1c03200756d24 +which was added all the way back in March of 2016, it was unknown (potentially not at the time) +that an entity might actually change the seed of the random object. + +At some point, EntitySquid did start setting the seed. Due to this shared random, this caused +every entity to use a Random object with a predictable seed. + +This has caused entities to potentially generate with the same UUID.... + +Over the years, servers have had entities disappear, but no sign of trouble +because CraftBukkit removed the log lines indicating that something was wrong. + +We have fixed the root issue causing duplicate UUID's, however we now have chunk +files full of entities that have the same UUID as another entity! + +When these chunks load, the 2nd entity will not be added to the world correctly. + +If that chunk loads in a different order in the future, then it will reverse and the +missing one is now the one added to the world and not the other. This results in very +inconsistent entity behavior. + +This change allows you to recover any duplicate entity by generating a new UUID for it. +This also lets you delete them instead if you don't want to risk having new entities added to +the world that you previously did not see. + +But for those who are ok with leaving this inconsistent behavior, you may use WARN or NOTHING options. + +It is recommended you regenerate the entities, as these were legit entities, and deserve your love. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index fbf3ccfb347a5ba6e895339e9576629d940d1aa4..38d25a12c6a52d8a83214e2a0f43a218cf15ceac 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -401,4 +401,43 @@ public class PaperWorldConfig { + private void preventMovingIntoUnloadedChunks() { + preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); + } ++ ++ public enum DuplicateUUIDMode { ++ SAFE_REGEN, DELETE, NOTHING, WARN ++ } ++ public DuplicateUUIDMode duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; ++ public int duplicateUUIDDeleteRange = 32; ++ private void repairDuplicateUUID() { ++ String desiredMode = getString("duplicate-uuid-resolver", "saferegen").toLowerCase().trim(); ++ duplicateUUIDDeleteRange = getInt("duplicate-uuid-saferegen-delete-range", duplicateUUIDDeleteRange); ++ switch (desiredMode.toLowerCase()) { ++ case "regen": ++ case "regenerate": ++ case "saferegen": ++ case "saferegenerate": ++ duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; ++ log("Duplicate UUID Resolve: Regenerate New UUID if distant (Delete likely duplicates within " + duplicateUUIDDeleteRange + " blocks)"); ++ break; ++ case "remove": ++ case "delete": ++ duplicateUUIDMode = DuplicateUUIDMode.DELETE; ++ log("Duplicate UUID Resolve: Delete Entity"); ++ break; ++ case "silent": ++ case "nothing": ++ duplicateUUIDMode = DuplicateUUIDMode.NOTHING; ++ logError("Duplicate UUID Resolve: Do Nothing (no logs) - Warning, may lose indication of bad things happening"); ++ break; ++ case "log": ++ case "warn": ++ duplicateUUIDMode = DuplicateUUIDMode.WARN; ++ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); ++ break; ++ default: ++ duplicateUUIDMode = DuplicateUUIDMode.WARN; ++ logError("Warning: Invalid duplicate-uuid-resolver config " + desiredMode + " - must be one of: regen, delete, nothing, warn"); ++ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); ++ break; ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 083db6c1899b5391231b6d5d5044a334212f148c..5d87a282042d7112415b7d7175031f734219f2c9 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1,6 +1,7 @@ + package net.minecraft.server.level; + + import co.aikar.timings.Timing; // Paper ++import com.destroystokyo.paper.PaperWorldConfig; // Paper + import com.google.common.collect.ImmutableList; + import com.google.common.collect.Iterables; + import com.google.common.collect.ComparisonChain; // Paper +@@ -23,14 +24,17 @@ import it.unimi.dsi.fastutil.objects.ObjectIterator; + import java.io.File; + import java.io.IOException; + import java.io.Writer; ++import java.util.HashMap; // Paper + import java.util.Collection; + import java.util.Iterator; + import java.util.List; ++import java.util.Map; // Paper + import java.util.Objects; + import java.util.Optional; + import java.util.Queue; + import java.util.Set; + import java.util.concurrent.CancellationException; ++import java.util.UUID; // Paper + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.CompletionException; + import java.util.concurrent.Executor; +@@ -71,6 +75,7 @@ import net.minecraft.world.entity.ai.village.poi.PoiManager; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.GameRules; ++import net.minecraft.world.level.Level; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.ChunkStatus; +@@ -697,18 +702,18 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (chunk.needsDecoration) { + net.minecraft.server.dedicated.DedicatedServer server = this.level.getCraftServer().getServer(); + if (!server.areNpcsEnabled() && entity instanceof net.minecraft.world.entity.npc.Npc) { +- entity.remove(); ++ entity.removed = true; // Paper + needsRemoval = true; + } + + if (!server.isSpawningAnimals() && (entity instanceof net.minecraft.world.entity.animal.Animal || entity instanceof net.minecraft.world.entity.animal.WaterAnimal)) { +- entity.remove(); ++ entity.removed = true; // Paper + needsRemoval = true; + } + } +- +- if (!(entity instanceof net.minecraft.world.entity.player.Player) && (needsRemoval || !this.level.loadFromChunk(entity))) { +- // CraftBukkit end ++ // CraftBukkit end ++ checkDupeUUID(entity); // Paper ++ if (!(entity instanceof net.minecraft.world.entity.player.Player) && (entity.removed || !this.level.loadFromChunk(entity))) { // Paper + if (list == null) { + list = Lists.newArrayList(new Entity[]{entity}); + } else { +@@ -735,6 +740,44 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }); + } + ++ // Paper start ++ private void checkDupeUUID(Entity entity) { ++ PaperWorldConfig.DuplicateUUIDMode mode = level.paperConfig.duplicateUUIDMode; ++ if (mode != PaperWorldConfig.DuplicateUUIDMode.WARN ++ && mode != PaperWorldConfig.DuplicateUUIDMode.DELETE ++ && mode != PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN) { ++ return; ++ } ++ Entity other = level.getEntity(entity.getUUID()); ++ ++ if (mode == PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN && other != null && !other.removed ++ && Objects.equals(other.getEncodeId(), entity.getEncodeId()) ++ && entity.getBukkitEntity().getLocation().distance(other.getBukkitEntity().getLocation()) < level.paperConfig.duplicateUUIDDeleteRange ++ ) { ++ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + " because it was near the duplicate and likely an actual duplicate. See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ entity.removed = true; ++ return; ++ } ++ if (other != null && !other.removed) { ++ switch (mode) { ++ case SAFE_REGEN: { ++ entity.setUUID(UUID.randomUUID()); ++ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", regenerated UUID for " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ break; ++ } ++ case DELETE: { ++ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ entity.removed = true; ++ break; ++ } ++ default: ++ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", doing nothing to " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ break; ++ } ++ } ++ } ++ // Paper end ++ + public CompletableFuture> postProcess(ChunkHolder holder) { + ChunkPos chunkcoordintpair = holder.getPos(); + CompletableFuture, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkRangeFuture(chunkcoordintpair, 1, (i) -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 99883c83c126405fc93becefed8a1d0727b94aa7..20b74fc8e1273fcd07ea4417eaedc8bd9aba93b3 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -4,6 +4,8 @@ import com.google.common.annotations.VisibleForTesting; + import com.google.common.collect.Iterables; + import co.aikar.timings.TimingHistory; // Paper + import co.aikar.timings.Timings; // Paper ++ ++import com.destroystokyo.paper.PaperWorldConfig; // Paper + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Queues; +@@ -1102,7 +1104,22 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (entity1 == null) { + return false; + } else { ++ // Paper start ++ if (entity1.removed) { ++ onEntityRemoved(entity1); // remove the existing entity ++ return false; ++ } ++ // Paper end + ServerLevel.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityType.getKey(entity1.getType()), entity1.getId(), EntityType.getKey(entity.getType()), entity.getId()); // CraftBukkit // Paper ++ // Paper start ++ if (DEBUG_ENTITIES && entity.level.paperConfig.duplicateUUIDMode != PaperWorldConfig.DuplicateUUIDMode.NOTHING) { ++ if (entity1.addedToWorldStack != null) { ++ entity1.addedToWorldStack.printStackTrace(); ++ } ++ ++ getAddToWorldStackTrace(entity).printStackTrace(); ++ } ++ // Paper end + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 6faac8773136412ca129dfa884178f311e197f6e..af86c370c6f834514115a8e40659f5e1aaabec75 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2803,6 +2803,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + }); + } + ++ public final void setUUID(UUID uuid) { setUUID(uuid); } // Paper - OBFHELPER + public void setUUID(UUID uuid) { + this.uuid = uuid; + this.stringUUID = this.uuid.toString(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index db28bfe95c885cdefa855c7aaa3bcf92bc52df26..55872a17060a35b727a597bc414fecec3ada3515 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -541,6 +541,7 @@ public class LevelChunk implements ChunkAccess { + if (i != this.chunkPos.x || j != this.chunkPos.z) { + LevelChunk.LOGGER.warn("Wrong location! ({}, {}) should be ({}, {}), {}", i, j, this.chunkPos.x, this.chunkPos.z, entity); + entity.removed = true; ++ return; // Paper + } + + int k = Mth.floor(entity.getY() / 16.0D); diff --git a/patches/server-remapped/0351-improve-CraftWorld-isChunkLoaded.patch b/patches/server-remapped/0351-improve-CraftWorld-isChunkLoaded.patch new file mode 100644 index 0000000000..40d4c9c49d --- /dev/null +++ b/patches/server-remapped/0351-improve-CraftWorld-isChunkLoaded.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 21 May 2019 02:34:04 +0100 +Subject: [PATCH] improve CraftWorld#isChunkLoaded + +getChunkAt will request the chunk using vanillas chunk loading system, +which while we're not going to load the chunk, does involve the server +waiting for the execution queue to get to our request; We can just query +the chunk status and get a response now, vs having to wait + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index a4231e1c3d468355c0b55ac9d2c239f1b4c54594..6e9e2149d854f26826d030ee6e655ca8fa7b5141 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -396,13 +396,13 @@ public class CraftWorld implements World { + + @Override + public boolean isChunkLoaded(int x, int z) { +- return world.getChunkSource().isChunkLoaded(x, z); ++ return world.getChunkSource().getChunkAtIfLoadedImmediately(x, z) != null; // Paper + } + + @Override + public boolean isChunkGenerated(int x, int z) { + try { +- return isChunkLoaded(x, z) || world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; ++ return world.getChunkSource().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; // Paper (TODO check if the first part can be removed) + } catch (IOException ex) { + throw new RuntimeException(ex); + } diff --git a/patches/server-remapped/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server-remapped/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch new file mode 100644 index 0000000000..ad03456870 --- /dev/null +++ b/patches/server-remapped/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -0,0 +1,260 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 13 Sep 2014 23:14:43 -0400 +Subject: [PATCH] Configurable Keep Spawn Loaded range per world + +This lets you disable it for some worlds and lower it for others. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 38d25a12c6a52d8a83214e2a0f43a218cf15ceac..ffe9b1a63d78925e1d77b9e730aef42fed6d58fa 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -440,4 +440,10 @@ public class PaperWorldConfig { + break; + } + } ++ ++ public short keepLoadedRange; ++ private void keepLoadedRange() { ++ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); ++ log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 9beda5e429b5c520a41d9c7f536dc48dbb6f6f9e..0efe7024493f96bb54e7d8c1ea7b233a1b481a04 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -716,35 +716,36 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> 4).forEach(pair -> { ++ getChunkSource().getChunkAtMainThread(pair.x, pair.z); ++ }); ++ } ++ public void removeTicketsForSpawn(int radiusInBlocks, BlockPos spawn) { ++ // In order to respect vanilla behavior, which is ensuring everything but the spawn border can tick, we added tickets ++ // with level 31 for the non-border spawn chunks ++ ServerChunkCache chunkproviderserver = this.getChunkSource(); ++ int tickRadius = radiusInBlocks - 16; ++ ++ // remove ticking chunks ++ for (int x = -tickRadius; x <= tickRadius; x += 16) { ++ for (int z = -tickRadius; z <= tickRadius; z += 16) { ++ // radius of 2 will have the current chunk be level 31 ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(x, 0, z)), 2, Unit.INSTANCE); ++ } ++ } ++ ++ // remove border chunks ++ ++ // remove border along x axis (including corner chunks) ++ for (int x = -radiusInBlocks; x <= radiusInBlocks; x += 16) { ++ // top ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32 ++ // bottom ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(x, 0, -radiusInBlocks)), 1, Unit.INSTANCE); // level 32 ++ } ++ ++ // remove border along z axis (excluding corner chunks) ++ for (int z = -radiusInBlocks + 16; z < radiusInBlocks; z += 16) { ++ // right ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 ++ // left ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 ++ } ++ } ++ // Paper end ++ + public void setDefaultSpawnPos(BlockPos pos, float angle) { +- ChunkPos chunkcoordintpair = new ChunkPos(new BlockPos(this.levelData.getXSpawn(), 0, this.levelData.getZSpawn())); ++ // Paper - configurable spawn radius ++ BlockPos prevSpawn = this.getSpawn(); ++ //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); + + this.levelData.setSpawn(pos, angle); +- this.getChunkSource().removeRegionTicket(TicketType.START, chunkcoordintpair, 11, Unit.INSTANCE); +- this.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(pos), 11, Unit.INSTANCE); ++ if (this.keepSpawnInMemory) { ++ // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add ++ this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); ++ this.addTicketsForSpawn(this.paperConfig.keepLoadedRange, pos); ++ } + this.getServer().getPlayerList().broadcastAll(new ClientboundSetDefaultSpawnPositionPacket(pos, angle)); + } + +diff --git a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java +index 2860a16c80e56edb333115f6f64f65d0e56feb11..85863211a666b299cae8a3791c182ae5094b94d9 100644 +--- a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java ++++ b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java +@@ -11,4 +11,6 @@ public interface ChunkProgressListener { + void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status); + + void stop(); ++ ++ void setChunkRadius(int radius); // Paper - allow changing chunk radius + } +diff --git a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java +index 4a541f0b2582430abda6e5ff8f492e37fc903483..e810843fae13d3e83e8f509810b781859217c48b 100644 +--- a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java ++++ b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java +@@ -12,16 +12,24 @@ import org.apache.logging.log4j.Logger; + public class LoggerChunkProgressListener implements ChunkProgressListener { + + private static final Logger LOGGER = LogManager.getLogger(); +- private final int maxCount; ++ private int maxCount; // Paper - remove final + private int count; + private long startTime; + private long nextTickTime = Long.MAX_VALUE; + + public LoggerChunkProgressListener(int radius) { ++ // Paper start - Allow changing radius later for configurable spawn patch ++ this.setChunkRadius(radius); // Move to method ++ } ++ ++ @Override ++ public void setChunkRadius(int radius) { ++ // Paper - copied from above + int j = radius * 2 + 1; + + this.maxCount = j * j; + } ++ // Paper end + + @Override + public void updateSpawnPos(ChunkPos spawnPos) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 6e9e2149d854f26826d030ee6e655ca8fa7b5141..0cb0021fac211996c5bdbb2cfc8f54addc3b49f6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1954,15 +1954,21 @@ public class CraftWorld implements World { + + @Override + public void setKeepSpawnInMemory(boolean keepLoaded) { ++ // Paper start - Configurable spawn radius ++ if (keepLoaded == world.keepSpawnInMemory) { ++ // do nothing, nothing has changed ++ return; ++ } + world.keepSpawnInMemory = keepLoaded; + // Grab the worlds spawn chunk +- BlockPos chunkcoordinates = this.world.getSpawn(); ++ BlockPos prevSpawn = this.world.getSpawn(); + if (keepLoaded) { +- world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); ++ world.addTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); + } else { +- // TODO: doesn't work well if spawn changed.... +- world.getChunkSource().removeRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); ++ // TODO: doesn't work well if spawn changed.... // paper - resolved ++ world.removeTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); + } ++ // Paper end + } + + @Override diff --git a/patches/server-remapped/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch b/patches/server-remapped/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch new file mode 100644 index 0000000000..3475c01271 --- /dev/null +++ b/patches/server-remapped/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Mon, 27 May 2019 17:35:39 -0500 +Subject: [PATCH] MC-114618 - Fix EntityAreaEffectCloud from going negative + size + + +diff --git a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java +index 949553229a55f8c8b9a5c0141409d1520eff22c7..fe4312a58b0b2ffd63db14068d99c5391e0eb0a0 100644 +--- a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java ++++ b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java +@@ -194,6 +194,12 @@ public class AreaEffectCloud extends Entity { + super.tick(); + boolean flag = this.isWaiting(); + float f = this.getRadius(); ++ // Paper start - fix MC-114618 ++ if (f < 0.0F) { ++ this.remove(); ++ return; ++ } ++ // Paper end + + if (this.level.isClientSide) { + ParticleOptions particleparam = this.getParticle(); diff --git a/patches/server-remapped/0354-ChunkMapDistance-CME.patch b/patches/server-remapped/0354-ChunkMapDistance-CME.patch new file mode 100644 index 0000000000..09a7ae7ee7 --- /dev/null +++ b/patches/server-remapped/0354-ChunkMapDistance-CME.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Wed, 29 May 2019 04:01:22 +0100 +Subject: [PATCH] ChunkMapDistance CME + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 0b8cbf75ff01b9825141be00d63679f7bcc58a9f..89e90806b78d94d5c1d781113da420dafa47930a 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -44,6 +44,7 @@ public class ChunkHolder { + private static final CompletableFuture> UNLOADED_LEVEL_CHUNK_FUTURE = CompletableFuture.completedFuture(ChunkHolder.UNLOADED_LEVEL_CHUNK); + private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); + private static final ChunkHolder.FullChunkStatus[] FULL_CHUNK_STATUSES = ChunkHolder.FullChunkStatus.values(); ++ boolean isUpdateQueued = false; // Paper + private final AtomicReferenceArray>> futures; + private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage + private volatile CompletableFuture> tickingChunkFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 8f993f15ae02c2e4af9cc732cd1b040cce0a67e8..71a51cc99e26579e765f88340588e23956888929 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -39,7 +39,16 @@ public abstract class DistanceManager { + private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); + private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); + private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); +- private final Set chunksToUpdateFutures = Sets.newHashSet(); ++ // Paper start use a queue, but still keep unique requirement ++ public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { ++ @Override ++ public boolean add(ChunkHolder o) { ++ if (o.isUpdateQueued) return true; ++ o.isUpdateQueued = true; ++ return super.add(o); ++ } ++ }; ++ // Paper end + private final ChunkTaskPriorityQueueSorter ticketThrottler; + private final ProcessorHandle> ticketThrottlerInput; + private final ProcessorHandle ticketThrottlerReleaser; +@@ -100,26 +109,14 @@ public abstract class DistanceManager { + ; + } + +- if (!this.chunksToUpdateFutures.isEmpty()) { +- // CraftBukkit start +- // Iterate pending chunk updates with protection against concurrent modification exceptions +- java.util.Iterator iter = this.chunksToUpdateFutures.iterator(); +- int expectedSize = this.chunksToUpdateFutures.size(); +- do { +- ChunkHolder playerchunk = iter.next(); +- iter.remove(); +- expectedSize--; +- +- playerchunk.updateFutures(chunkStorage); +- +- // Reset iterator if set was modified using add() +- if (this.chunksToUpdateFutures.size() != expectedSize) { +- expectedSize = this.chunksToUpdateFutures.size(); +- iter = this.chunksToUpdateFutures.iterator(); +- } +- } while (iter.hasNext()); +- // CraftBukkit end +- ++ // Paper start ++ if (!this.pendingChunkUpdates.isEmpty()) { ++ while(!this.pendingChunkUpdates.isEmpty()) { ++ ChunkHolder remove = this.pendingChunkUpdates.remove(); ++ remove.isUpdateQueued = false; ++ remove.updateFutures(chunkStorage); ++ } ++ // Paper end + return true; + } else { + if (!this.ticketsToRelease.isEmpty()) { +@@ -342,7 +339,7 @@ public abstract class DistanceManager { + if (k != level) { + playerchunk = DistanceManager.this.updateChunkScheduling(id, level, playerchunk, k); + if (playerchunk != null) { +- DistanceManager.this.chunksToUpdateFutures.add(playerchunk); ++ DistanceManager.this.pendingChunkUpdates.add(playerchunk); + } + + } +@@ -373,7 +370,7 @@ public abstract class DistanceManager { + ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); + + while (objectiterator.hasNext()) { +- it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); ++ Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix + byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); + long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); + diff --git a/patches/server-remapped/0355-Implement-CraftBlockSoundGroup.patch b/patches/server-remapped/0355-Implement-CraftBlockSoundGroup.patch new file mode 100644 index 0000000000..0fd2f20b1d --- /dev/null +++ b/patches/server-remapped/0355-Implement-CraftBlockSoundGroup.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: simpleauthority +Date: Tue, 28 May 2019 03:48:51 -0700 +Subject: [PATCH] Implement CraftBlockSoundGroup + + +diff --git a/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9a516520d975f52169e346adc4ec6d9db843db2f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java +@@ -0,0 +1,38 @@ ++package com.destroystokyo.paper.block; ++ ++import net.minecraft.world.level.block.SoundType; ++import org.bukkit.Sound; ++import org.bukkit.craftbukkit.CraftSound; ++ ++public class CraftBlockSoundGroup implements BlockSoundGroup { ++ private final SoundType soundEffectType; ++ ++ public CraftBlockSoundGroup(SoundType soundEffectType) { ++ this.soundEffectType = soundEffectType; ++ } ++ ++ @Override ++ public Sound getBreakSound() { ++ return CraftSound.getBukkit(soundEffectType.getBreakSound()); ++ } ++ ++ @Override ++ public Sound getStepSound() { ++ return CraftSound.getBukkit(soundEffectType.getStepSound()); ++ } ++ ++ @Override ++ public Sound getPlaceSound() { ++ return CraftSound.getBukkit(soundEffectType.getPlaceSound()); ++ } ++ ++ @Override ++ public Sound getHitSound() { ++ return CraftSound.getBukkit(soundEffectType.getHitSound()); ++ } ++ ++ @Override ++ public Sound getFallSound() { ++ return CraftSound.getBukkit(soundEffectType.getFallSound()); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/level/block/SoundType.java b/src/main/java/net/minecraft/world/level/block/SoundType.java +index 1d3acbbc80a38998fb38e0ce37af52103f677721..44394adbe60b5e9c4654ee2f437d465bef5909a8 100644 +--- a/src/main/java/net/minecraft/world/level/block/SoundType.java ++++ b/src/main/java/net/minecraft/world/level/block/SoundType.java +@@ -54,10 +54,10 @@ public class SoundType { + public static final SoundType GILDED_BLACKSTONE = new SoundType(1.0F, 1.0F, SoundEvents.GILDED_BLACKSTONE_BREAK, SoundEvents.GILDED_BLACKSTONE_STEP, SoundEvents.GILDED_BLACKSTONE_PLACE, SoundEvents.GILDED_BLACKSTONE_HIT, SoundEvents.GILDED_BLACKSTONE_FALL); + public final float volume; + public final float pitch; +- public final SoundEvent breakSound; ++ public final SoundEvent breakSound; public final SoundEvent getBreakSound() { return this.breakSound; } // Paper - OBFHELPER // PAIL private -> public, rename breakSound + private final SoundEvent stepSound; + private final SoundEvent placeSound; +- public final SoundEvent hitSound; ++ public final SoundEvent hitSound; public final SoundEvent getHitSound() { return this.hitSound; } // Paper - OBFHELPER // PAIL private -> public, rename hitSound + private final SoundEvent fallSound; + + public SoundType(float volume, float pitch, SoundEvent breakSound, SoundEvent stepSound, SoundEvent placeSound, SoundEvent hitSound, SoundEvent fallSound) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index d73086970db19531db66c2e8af52da91d0b1ea28..5bff313dbbb3049105874846d995883e827fbc00 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -747,4 +747,11 @@ public class CraftBlock implements Block { + AABB aabb = shape.bounds(); + return new BoundingBox(getX() + aabb.minX, getY() + aabb.minY, getZ() + aabb.minZ, getX() + aabb.maxX, getY() + aabb.maxY, getZ() + aabb.maxZ); + } ++ ++ // Paper start ++ @Override ++ public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { ++ return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().defaultBlockState().getSoundType()); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0356-Chunk-debug-command.patch b/patches/server-remapped/0356-Chunk-debug-command.patch new file mode 100644 index 0000000000..a8a34d2b86 --- /dev/null +++ b/patches/server-remapped/0356-Chunk-debug-command.patch @@ -0,0 +1,490 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 1 Jun 2019 13:00:55 -0700 +Subject: [PATCH] Chunk debug command + +Prints all chunk information to a text file into the debug +folder in the root server folder. The format is in JSON, and +the data format is described in MCUtil#dumpChunks(File) + +The command will output server version and all online players to the +file as well. We do not log anything but the location, world and +username of the player. + +Also logs the value of these config values (note not all are paper's): +- keep spawn loaded value +- spawn radius +- view distance + +Each chunk has the following logged: +- Coordinate +- Ticket level & its corresponding state +- Whether it is queued for unload +- Chunk status (may be unloaded) +- All tickets on the chunk + +Example log: +https://gist.githubusercontent.com/Spottedleaf/0131e7710ffd5d531e5fd246c3367380/raw/169ae1b2e240485f99bc7a6bd8e78d90e3af7397/chunks-2019-06-01_19.57.05.txt + +For references on certain keywords (ticket, status, etc), please see: + +https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528273&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528273 +https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528577&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528577 + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 8fd716bf2e1402694798b8be03fd85821153be44..53dd6c18de8e80378852bbb141016d9574d42162 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -6,13 +6,15 @@ import com.google.common.collect.ImmutableSet; + import com.google.common.collect.Iterables; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; +-import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import org.apache.commons.lang3.tuple.MutablePair; + import org.apache.commons.lang3.tuple.Pair; + import org.bukkit.Bukkit; +@@ -41,7 +43,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); + + public PaperCommand(String name) { + super(name); +@@ -69,6 +71,21 @@ public class PaperCommand extends Command { + if (args.length == 3) + return getListMatchingLast(sender, args, EntityType.getEntityNameList().stream().map(ResourceLocation::toString).sorted().toArray(String[]::new)); + break; ++ case "debug": ++ if (args.length == 2) { ++ return getListMatchingLast(sender, args, "help", "chunks"); ++ } ++ break; ++ case "chunkinfo": ++ List worldNames = new ArrayList<>(); ++ worldNames.add("*"); ++ for (org.bukkit.World world : Bukkit.getWorlds()) { ++ worldNames.add(world.getName()); ++ } ++ if (args.length == 2) { ++ return getListMatchingLast(sender, args, worldNames); ++ } ++ break; + } + return Collections.emptyList(); + } +@@ -135,6 +152,12 @@ public class PaperCommand extends Command { + case "reload": + doReload(sender); + break; ++ case "debug": ++ doDebug(sender, args); ++ break; ++ case "chunkinfo": ++ doChunkInfo(sender, args); ++ break; + case "ver": + if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) + case "version": +@@ -152,6 +175,114 @@ public class PaperCommand extends Command { + return true; + } + ++ private void doChunkInfo(CommandSender sender, String[] args) { ++ List worlds; ++ if (args.length < 2 || args[1].equals("*")) { ++ worlds = Bukkit.getWorlds(); ++ } else { ++ worlds = new ArrayList<>(args.length - 1); ++ for (int i = 1; i < args.length; ++i) { ++ org.bukkit.World world = Bukkit.getWorld(args[i]); ++ if (world == null) { ++ sender.sendMessage(ChatColor.RED + "World '" + args[i] + "' is invalid"); ++ return; ++ } ++ worlds.add(world); ++ } ++ } ++ ++ int accumulatedTotal = 0; ++ int accumulatedInactive = 0; ++ int accumulatedBorder = 0; ++ int accumulatedTicking = 0; ++ int accumulatedEntityTicking = 0; ++ ++ for (org.bukkit.World bukkitWorld : worlds) { ++ ServerLevel world = ((CraftWorld)bukkitWorld).getHandle(); ++ ++ int total = 0; ++ int inactive = 0; ++ int border = 0; ++ int ticking = 0; ++ int entityTicking = 0; ++ ++ for (ChunkHolder chunk : world.getChunkSource().chunkMap.updatingChunkMap.values()) { ++ if (chunk.getFullChunkIfCached() == null) { ++ continue; ++ } ++ ++ ++total; ++ ++ ChunkHolder.FullChunkStatus state = ChunkHolder.getFullChunkStatus(chunk.getTicketLevel()); ++ ++ switch (state) { ++ case INACCESSIBLE: ++ ++inactive; ++ continue; ++ case BORDER: ++ ++border; ++ continue; ++ case TICKING: ++ ++ticking; ++ continue; ++ case ENTITY_TICKING: ++ ++entityTicking; ++ continue; ++ } ++ } ++ ++ accumulatedTotal += total; ++ accumulatedInactive += inactive; ++ accumulatedBorder += border; ++ accumulatedTicking += ticking; ++ accumulatedEntityTicking += entityTicking; ++ ++ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + bukkitWorld.getName() + ChatColor.DARK_AQUA + ":"); ++ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + total + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA ++ + inactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + border + ChatColor.BLUE + " Ticking: " ++ + ChatColor.DARK_AQUA + ticking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + entityTicking); ++ } ++ if (worlds.size() > 1) { ++ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + "all listed worlds" + ChatColor.DARK_AQUA + ":"); ++ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + accumulatedTotal + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA ++ + accumulatedInactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + accumulatedBorder + ChatColor.BLUE + " Ticking: " ++ + ChatColor.DARK_AQUA + accumulatedTicking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + accumulatedEntityTicking); ++ } ++ } ++ ++ private void doDebug(CommandSender sender, String[] args) { ++ if (args.length < 2) { ++ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); ++ return; ++ } ++ ++ String debugType = args[1].toLowerCase(Locale.ENGLISH); ++ switch (debugType) { ++ case "chunks": ++ if (args.length >= 3 && args[2].toLowerCase(Locale.ENGLISH).equals("help")) { ++ sender.sendMessage(ChatColor.RED + "Use /paper debug chunks to dump loaded chunk information to a file"); ++ break; ++ } ++ File file = new File(new File(new File("."), "debug"), ++ "chunks-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); ++ sender.sendMessage(ChatColor.GREEN + "Writing chunk information dump to " + file.toString()); ++ try { ++ MCUtil.dumpChunks(file); ++ sender.sendMessage(ChatColor.GREEN + "Successfully written chunk information!"); ++ } catch (Throwable thr) { ++ MinecraftServer.LOGGER.warn("Failed to dump chunk information to file " + file.toString(), thr); ++ sender.sendMessage(ChatColor.RED + "Failed to dump chunk information, see console"); ++ } ++ ++ break; ++ case "help": ++ // fall through to default ++ default: ++ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); ++ return; ++ } ++ } ++ + /* + * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 + */ +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 1fecc81b25109592907623741225a6222a8c5ccc..a16551c81a444685f6337a65b6d7862b8c0dc684 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -9,13 +9,27 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; ++import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.DistanceManager; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.Ticket; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.Level; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.ChunkStatus; + import org.apache.commons.lang.exception.ExceptionUtils; ++import com.google.gson.JsonArray; ++import com.google.gson.JsonObject; ++import com.google.gson.internal.Streams; ++import com.google.gson.stream.JsonWriter; + import com.mojang.authlib.GameProfile; ++import com.mojang.datafixers.util.Either; ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; + import org.bukkit.Location; + import org.bukkit.block.BlockFace; + import org.bukkit.craftbukkit.CraftWorld; +@@ -24,8 +38,11 @@ import org.spigotmc.AsyncCatcher; + + import javax.annotation.Nonnull; + import javax.annotation.Nullable; ++import java.io.*; ++import java.util.ArrayList; + import java.util.List; + import java.util.Queue; ++import java.util.Set; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.ExecutionException; + import java.util.concurrent.LinkedBlockingQueue; +@@ -531,4 +548,170 @@ public final class MCUtil { + + return null; + } ++ ++ public static ChunkStatus getChunkStatus(ChunkHolder chunk) { ++ List statuses = ServerChunkCache.getPossibleChunkStatuses(); ++ for (int i = statuses.size() - 1; i >= 0; --i) { ++ ChunkStatus curr = statuses.get(i); ++ CompletableFuture> future = chunk.getFutureIfPresentUnchecked(curr); ++ if (future != ChunkHolder.UNLOADED_CHUNK_FUTURE) { ++ return curr; ++ } ++ } ++ return null; // unloaded ++ } ++ ++ public static void dumpChunks(File file) throws IOException { ++ file.getParentFile().mkdirs(); ++ file.createNewFile(); ++ /* ++ * Json format: ++ * ++ * Main data format: ++ * -server-version: ++ * -data-version: ++ * -worlds: ++ * -name: ++ * -view-distance: ++ * -keep-spawn-loaded: ++ * -keep-spawn-loaded-range: ++ * -visible-chunk-count: ++ * -loaded-chunk-count: ++ * -verified-fully-loaded-chunks: ++ * -players: ++ * -chunk-data: ++ * ++ * Player format: ++ * -name: ++ * -x: ++ * -y: ++ * -z: ++ * ++ * Chunk Format: ++ * -x: ++ * -z: ++ * -ticket-level: ++ * -state: ++ * -queued-for-unload: ++ * -status: ++ * -tickets: ++ * ++ * ++ * Ticket format: ++ * -ticket-type: ++ * -ticket-level: ++ * -add-tick: ++ * -object-reason: // This depends on the type of ticket. ie POST_TELEPORT -> entity id ++ */ ++ List worlds = org.bukkit.Bukkit.getWorlds(); ++ JsonObject data = new JsonObject(); ++ ++ data.addProperty("server-version", org.bukkit.Bukkit.getVersion()); ++ data.addProperty("data-version", 0); ++ ++ JsonArray worldsData = new JsonArray(); ++ ++ for (org.bukkit.World bukkitWorld : worlds) { ++ JsonObject worldData = new JsonObject(); ++ ++ ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); ++ ChunkMap chunkMap = world.getChunkSource().chunkMap; ++ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunkMap; ++ DistanceManager chunkMapDistance = chunkMap.distanceManager; ++ List allChunks = new ArrayList<>(visibleChunks.values()); ++ List players = world.players; ++ ++ int fullLoadedChunks = 0; ++ ++ for (ChunkHolder chunk : allChunks) { ++ if (chunk.getFullChunkIfCached() != null) { ++ ++fullLoadedChunks; ++ } ++ } ++ ++ // sorting by coordinate makes the log easier to read ++ allChunks.sort((ChunkHolder v1, ChunkHolder v2) -> { ++ if (v1.location.x != v2.location.x) { ++ return Integer.compare(v1.location.x, v2.location.x); ++ } ++ return Integer.compare(v1.location.z, v2.location.z); ++ }); ++ ++ worldData.addProperty("name", world.getWorld().getName()); ++ worldData.addProperty("view-distance", world.spigotConfig.viewDistance); ++ worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); ++ worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); ++ worldData.addProperty("visible-chunk-count", visibleChunks.size()); ++ worldData.addProperty("loaded-chunk-count", chunkMap.entitiesInLevel.size()); ++ worldData.addProperty("verified-fully-loaded-chunks", fullLoadedChunks); ++ ++ JsonArray playersData = new JsonArray(); ++ ++ for (ServerPlayer player : players) { ++ JsonObject playerData = new JsonObject(); ++ ++ playerData.addProperty("name", player.getScoreboardName()); ++ playerData.addProperty("x", player.getX()); ++ playerData.addProperty("y", player.getY()); ++ playerData.addProperty("z", player.getZ()); ++ ++ playersData.add(playerData); ++ ++ } ++ ++ worldData.add("players", playersData); ++ ++ JsonArray chunksData = new JsonArray(); ++ ++ for (ChunkHolder playerChunk : allChunks) { ++ JsonObject chunkData = new JsonObject(); ++ ++ Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.pair()); ++ ChunkStatus status = getChunkStatus(playerChunk); ++ ++ chunkData.addProperty("x", playerChunk.location.x); ++ chunkData.addProperty("z", playerChunk.location.z); ++ chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); ++ chunkData.addProperty("state", ChunkHolder.getFullChunkStatus(playerChunk.getTicketLevel()).toString()); ++ chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.pair())); ++ chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); ++ ++ JsonArray ticketsData = new JsonArray(); ++ ++ if (tickets != null) { ++ for (Ticket ticket : tickets) { ++ JsonObject ticketData = new JsonObject(); ++ ++ ticketData.addProperty("ticket-type", ticket.getType().toString()); ++ ticketData.addProperty("ticket-level", ticket.getTicketLevel()); ++ ticketData.addProperty("object-reason", String.valueOf(ticket.getObjectReason())); ++ ticketData.addProperty("add-tick", ticket.getCreationTick()); ++ ++ ticketsData.add(ticketData); ++ } ++ } ++ ++ chunkData.add("tickets", ticketsData); ++ chunksData.add(chunkData); ++ } ++ ++ ++ worldData.add("chunk-data", chunksData); ++ worldsData.add(worldData); ++ } ++ ++ data.add("worlds", worldsData); ++ ++ StringWriter stringWriter = new StringWriter(); ++ JsonWriter jsonWriter = new JsonWriter(stringWriter); ++ jsonWriter.setIndent(" "); ++ jsonWriter.setLenient(false); ++ Streams.write(data, jsonWriter); ++ ++ String fileData = stringWriter.toString(); ++ ++ try (PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) { ++ out.print(fileData); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 89e90806b78d94d5c1d781113da420dafa47930a..a89b9dab043ad4536014141d5a942670b4152a95 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -53,7 +53,7 @@ public class ChunkHolder { + public int oldTicketLevel; + private int ticketLevel; + private int queueLevel; +- private final ChunkPos pos; ++ final ChunkPos pos; // Paper - private -> package + private boolean hasChangedSections; + private final ShortSet[] changedBlocksPerSection; + private int blockChangedLightSectionFilter; +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 5d87a282042d7112415b7d7175031f734219f2c9..7585b6f87b72f53deccbcb8627a13503921fc682 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -104,7 +104,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); + public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; + private final Long2ObjectLinkedOpenHashMap pendingUnloads; +- private final LongSet entitiesInLevel; ++ public final LongSet entitiesInLevel; // Paper - private -> public + public final ServerLevel level; + private final ThreadedLevelLightEngine lightEngine; + private final BlockableEventLoop mainThreadExecutor; +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index a7122a0411f4a8656efd4facde3403c8093bc8a6..6d33c1ee44bc732b58d18a8f6b0fd4bbdcb2dcd6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -46,7 +46,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper + + public class ServerChunkCache extends ChunkSource { + +- private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); ++ private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); public static final List getPossibleChunkStatuses() { return ServerChunkCache.CHUNK_STATUSES; } // Paper - OBFHELPER + private final DistanceManager distanceManager; + public final ChunkGenerator generator; + private final ServerLevel level; +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index 0c118d482e304c567fe7fe778c6ff386f960bdde..c6b5f32153b63ac92df9c4b31b8de168481f79f2 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -6,8 +6,8 @@ public final class Ticket implements Comparable> { + + private final TicketType type; + private final int ticketLevel; +- public final T key; +- private long createdTick; ++ public final T key; public final T getObjectReason() { return this.key; } // Paper - OBFHELPER ++ private long createdTick; public final long getCreationTick() { return this.createdTick; } // Paper - OBFHELPER + + protected Ticket(TicketType type, int level, T argument) { + this.type = type; +@@ -51,6 +51,7 @@ public final class Ticket implements Comparable> { + return this.type; + } + ++ public final int getTicketLevel() { return this.getTicketLevel(); } // Paper - OBFHELPER + public int getTicketLevel() { + return this.ticketLevel; + } diff --git a/patches/server-remapped/0357-Catch-exceptions-from-dispenser-entity-spawns.patch b/patches/server-remapped/0357-Catch-exceptions-from-dispenser-entity-spawns.patch new file mode 100644 index 0000000000..0a15b5e432 --- /dev/null +++ b/patches/server-remapped/0357-Catch-exceptions-from-dispenser-entity-spawns.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Mon, 10 Jun 2019 09:36:40 +0100 +Subject: [PATCH] Catch exceptions from dispenser entity spawns + + +diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +index dccf689d17bb5a77abf97779663413d01e840c23..67a894a185a3d4a53b3c7f90174b2604dff18257 100644 +--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +@@ -8,6 +8,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.BlockSource; + import net.minecraft.core.Direction; + import net.minecraft.core.Position; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; +@@ -235,7 +236,14 @@ public interface DispenseItemBehavior { + } + } + ++ try { // Paper + entitytypes.spawn(pointer.getLevel(), stack, (Player) null, pointer.getPos().relative(enumdirection), MobSpawnType.DISPENSER, enumdirection != Direction.UP, false); ++ // Paper start ++ } catch (Exception ex){ ++ MinecraftServer.LOGGER.warn("An exception occurred dispensing entity at {}[{}]", worldserver.getWorld().getName(), pointer.getPos(), ex); ++ } ++ // Paper end ++ + // itemstack.subtract(1); // Handled during event processing + // CraftBukkit end + return stack; diff --git a/patches/server-remapped/0358-Fix-World-isChunkGenerated-calls.patch b/patches/server-remapped/0358-Fix-World-isChunkGenerated-calls.patch new file mode 100644 index 0000000000..6f00b2b7ac --- /dev/null +++ b/patches/server-remapped/0358-Fix-World-isChunkGenerated-calls.patch @@ -0,0 +1,390 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 15 Jun 2019 08:54:33 -0700 +Subject: [PATCH] Fix World#isChunkGenerated calls + +Optimize World#loadChunk() too +This patch also adds a chunk status cache on region files (note that +its only purpose is to cache the status on DISK) + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index a89b9dab043ad4536014141d5a942670b4152a95..7010e0a970462d2b2e1b5696a1a49dba9ea60935 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -141,6 +141,19 @@ public class ChunkHolder { + Either either = (Either) statusFuture.getNow(null); + return either == null ? null : (LevelChunk) either.left().orElse(null); + } ++ ++ public ChunkAccess getAvailableChunkNow() { ++ // TODO can we just getStatusFuture(EMPTY)? ++ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) { ++ CompletableFuture> future = this.getFutureIfPresentUnchecked(curr); ++ Either either = future.getNow(null); ++ if (either == null || !either.left().isPresent()) { ++ continue; ++ } ++ return either.left().get(); ++ } ++ return null; ++ } + // Paper end + + public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 7585b6f87b72f53deccbcb8627a13503921fc682..0aac29de933c84c34cb24e204e8fcc7010060d8f 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -991,12 +991,61 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + @Nullable +- private CompoundTag readChunk(ChunkPos pos) throws IOException { ++ public CompoundTag readChunk(ChunkPos pos) throws IOException { // Paper - private -> public + CompoundTag nbttagcompound = this.read(pos); ++ // Paper start - Cache chunk status on disk ++ if (nbttagcompound == null) { ++ return null; ++ } ++ ++ nbttagcompound = this.getChunkData(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, pos, level); // CraftBukkit ++ if (nbttagcompound == null) { ++ return null; ++ } ++ ++ this.updateChunkStatusOnDisk(pos, nbttagcompound); ++ ++ return nbttagcompound; ++ // Paper end ++ } ++ ++ // Paper start - chunk status cache "api" ++ public ChunkStatus getChunkStatusOnDiskIfCached(ChunkPos chunkPos) { ++ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); ++ ++ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ } ++ ++ public ChunkStatus getChunkStatusOnDisk(ChunkPos chunkPos) throws IOException { ++ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); ++ ++ if (regionFile == null || !regionFile.chunkExists(chunkPos)) { ++ return null; ++ } ++ ++ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ ++ if (status != null) { ++ return status; ++ } ++ ++ this.readChunk(chunkPos); + +- return nbttagcompound == null ? null : this.getChunkData(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, pos, level); // CraftBukkit ++ return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); + } + ++ public void updateChunkStatusOnDisk(ChunkPos chunkPos, @Nullable CompoundTag compound) throws IOException { ++ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); ++ ++ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); ++ } ++ ++ public ChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { ++ ChunkHolder chunkHolder = this.pendingUnloads.get(ChunkPos.asLong(chunkX, chunkZ)); ++ return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow(); ++ } ++ // Paper end ++ + boolean noPlayersCloseForSpawning(ChunkPos chunkcoordintpair) { + // Spigot start + return isOutsideOfRange(chunkcoordintpair, false); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 6d33c1ee44bc732b58d18a8f6b0fd4bbdcb2dcd6..1e8ac0110badbf2d1c2336168c3e11991667c782 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -52,7 +52,7 @@ public class ServerChunkCache extends ChunkSource { + private final ServerLevel level; + public final Thread mainThread; // Paper - private -> public + private final ThreadedLevelLightEngine lightEngine; +- private final ServerChunkCache.MainThreadExecutor mainThreadProcessor; ++ public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; // Paper private -> public + public final ChunkMap chunkMap; + private final DimensionDataStorage dataStorage; + private long lastInhabitedUpdate; +@@ -317,6 +317,21 @@ public class ServerChunkCache extends ChunkSource { + + return ret; + } ++ ++ @Nullable ++ public ChunkAccess getChunkAtImmediately(int x, int z) { ++ long k = ChunkPos.asLong(x, z); ++ ++ // Note: Bypass cache to make this MT-Safe ++ ++ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(k); ++ if (playerChunk == null) { ++ return null; ++ } ++ ++ return playerChunk.getAvailableChunkNow(); ++ ++ } + // Paper end + + @Nullable +@@ -771,7 +786,7 @@ public class ServerChunkCache extends ChunkSource { + return this.lastSpawnState; + } + +- final class MainThreadExecutor extends BlockableEventLoop { ++ public final class MainThreadExecutor extends BlockableEventLoop { // Paper - package -> public + + private MainThreadExecutor(Level world) { + super("Chunk source main thread executor for " + world.dimension().location()); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +index ae84dc310c076e3212d3cdbca77a1ab06a11d479..46d5a24332c1fd3c164b760ec2a2d5bf859b1ab6 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +@@ -193,6 +193,7 @@ public class ChunkStatus { + return this.name; + } + ++ public ChunkStatus getPreviousStatus() { return this.getParent(); } // Paper - OBFHELPER + public ChunkStatus getParent() { + return this.parent; + } +@@ -213,6 +214,17 @@ public class ChunkStatus { + return this.chunkType; + } + ++ // Paper start ++ public static ChunkStatus getStatus(String name) { ++ try { ++ // We need this otherwise we return EMPTY for invalid names ++ ResourceLocation key = new ResourceLocation(name); ++ return Registry.CHUNK_STATUS.getOptional(key).orElse(null); ++ } catch (Exception ex) { ++ return null; // invalid name ++ } ++ } ++ // Paper end + public static ChunkStatus byName(String id) { + return (ChunkStatus) Registry.CHUNK_STATUS.get(ResourceLocation.tryParse(id)); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 542d6f322df5f44ad9f504c8e14c88e3fa540657..969130442b529eaac6f708107ff129f89cc0af90 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -462,6 +462,17 @@ public class ChunkSerializer { + } + // Paper end + ++ // Paper start ++ public static ChunkStatus getStatus(CompoundTag compound) { ++ if (compound == null) { ++ return null; ++ } ++ ++ // Note: Copied from below ++ return ChunkStatus.getStatus(compound.getCompound("Level").getString("Status")); ++ } ++ // Paper end ++ + public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag tag) { + if (tag != null) { + ChunkStatus chunkstatus = ChunkStatus.byName(tag.getCompound("Level").getString("Status")); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +index 637274532b01bb7b4cdb7d7b1b58181b98ac7e98..9cffef2098fbfba89ddd88a45bde33c07660497a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -21,7 +21,7 @@ import net.minecraft.world.level.storage.DimensionDataStorage; + + public class ChunkStorage implements AutoCloseable { + +- private final IOWorker worker; ++ private final IOWorker worker; public IOWorker getIOWorker() { return worker; } // Paper - OBFHELPER + protected final DataFixer fixerUpper; + @Nullable + private LegacyStructureDataHandler legacyStructureHandler; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 424628c9588c02454558bc7e7c5bad3a3e75ec9f..4d96e5ed28c910387c0a4238c9036c7a12458f57 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -27,6 +27,7 @@ import net.minecraft.Util; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtIo; + import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.chunk.ChunkStatus; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +@@ -44,6 +45,30 @@ public class RegionFile implements AutoCloseable { + protected final RegionBitmap usedSectors; + public final File file; // Paper + ++ // Paper start - Cache chunk status ++ private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; ++ ++ private boolean closed; ++ ++ // invoked on write/read ++ public void setStatus(int x, int z, ChunkStatus status) { ++ if (this.closed) { ++ // We've used an invalid region file. ++ throw new IllegalStateException("RegionFile is closed"); ++ } ++ this.statuses[getChunkLocation(x, z)] = status; ++ } ++ ++ public ChunkStatus getStatusIfCached(int x, int z) { ++ if (this.closed) { ++ // We've used an invalid region file. ++ throw new IllegalStateException("RegionFile is closed"); ++ } ++ final int location = getChunkLocation(x, z); ++ return this.statuses[location]; ++ } ++ // Paper end ++ + public RegionFile(File file, File directory, boolean dsync) throws IOException { + this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); + } +@@ -380,11 +405,13 @@ public class RegionFile implements AutoCloseable { + return this.getOffset(pos) != 0; + } + ++ private static int getChunkLocation(int x, int z) { return (x & 31) + (z & 31) * 32; } // Paper - OBFHELPER - sort of, mirror of logic below + private static int getOffsetIndex(ChunkPos pos) { + return pos.getRegionLocalX() + pos.getRegionLocalZ() * 32; + } + + public void close() throws IOException { ++ this.closed = true; // Paper + try { + this.padToFullSector(); + } finally { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index 6d3e1bb20d1ab8ce5c9ea613322042d80550761a..6f1c96e4325caf6b4762700ad2286d9ea41515c9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -28,7 +28,14 @@ public final class RegionFileStorage implements AutoCloseable { + this.sync = dsync; + } + +- private RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit ++ ++ // Paper start ++ public RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { ++ return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); ++ } ++ ++ // Paper end ++ public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public + long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); + RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); + +@@ -175,6 +182,7 @@ public final class RegionFileStorage implements AutoCloseable { + + try { + NbtIo.write(tag, (DataOutput) dataoutputstream); ++ regionfile.setStatus(pos.x, pos.z, ChunkSerializer.getStatus(tag)); // Paper - cache status on disk + regionfile.setOversized(pos.x, pos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone + } catch (Throwable throwable1) { + throwable = throwable1; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 0cb0021fac211996c5bdbb2cfc8f54addc3b49f6..a0615e4ba015cca4fe074de63b87d0bff84b1a14 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -19,6 +19,7 @@ import java.util.Objects; + import java.util.Random; + import java.util.Set; + import java.util.UUID; ++import java.util.concurrent.CompletableFuture; + import java.util.function.Predicate; + import java.util.stream.Collectors; + import net.minecraft.core.BlockPos; +@@ -401,8 +402,22 @@ public class CraftWorld implements World { + + @Override + public boolean isChunkGenerated(int x, int z) { ++ // Paper start - Fix this method ++ if (!Bukkit.isPrimaryThread()) { ++ return CompletableFuture.supplyAsync(() -> { ++ return CraftWorld.this.isChunkGenerated(x, z); ++ }, world.getChunkSource().mainThreadProcessor).join(); ++ } ++ ChunkAccess chunk = world.getChunkSource().getChunkAtImmediately(x, z); ++ if (chunk == null) { ++ chunk = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); ++ } ++ if (chunk != null) { ++ return chunk instanceof ImposterProtoChunk || chunk instanceof net.minecraft.world.level.chunk.LevelChunk; ++ } + try { +- return world.getChunkSource().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; // Paper (TODO check if the first part can be removed) ++ return world.getChunkSource().chunkMap.getChunkStatusOnDisk(new ChunkPos(x, z)) == ChunkStatus.FULL; ++ // Paper end + } catch (IOException ex) { + throw new RuntimeException(ex); + } +@@ -513,20 +528,48 @@ public class CraftWorld implements World { + @Override + public boolean loadChunk(int x, int z, boolean generate) { + org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot +- ChunkAccess chunk = world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper ++ // Paper start - Optimize this method ++ ChunkPos chunkPos = new ChunkPos(x, z); + +- // If generate = false, but the chunk already exists, we will get this back. +- if (chunk instanceof ImposterProtoChunk) { +- // We then cycle through again to get the full chunk immediately, rather than after the ticket addition +- chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); +- } ++ if (!generate) { ++ ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z); ++ if (immediate == null) { ++ immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); ++ } ++ if (immediate != null) { ++ if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) { ++ return false; // not full status ++ } ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunk(x, z); // make sure we're at ticket level 32 or lower ++ return true; ++ } + +- if (chunk instanceof net.minecraft.world.level.chunk.LevelChunk) { +- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); +- return true; ++ net.minecraft.world.level.chunk.storage.RegionFile file; ++ try { ++ file = world.getChunkSource().chunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); ++ } catch (IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ ChunkStatus status = file.getStatusIfCached(x, z); ++ if (!file.hasChunk(chunkPos) || (status != null && status != ChunkStatus.FULL)) { ++ return false; ++ } ++ ++ ChunkAccess chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.EMPTY, true); ++ if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof net.minecraft.world.level.chunk.LevelChunk)) { ++ return false; ++ } ++ ++ // fall through to load ++ // we do this so we do not re-read the chunk data on disk + } + +- return false; ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); ++ return true; ++ // Paper end + } + + @Override diff --git a/patches/server-remapped/0359-Show-blockstate-location-if-we-failed-to-read-it.patch b/patches/server-remapped/0359-Show-blockstate-location-if-we-failed-to-read-it.patch new file mode 100644 index 0000000000..873d34715d --- /dev/null +++ b/patches/server-remapped/0359-Show-blockstate-location-if-we-failed-to-read-it.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 15 Jun 2019 10:28:25 -0700 +Subject: [PATCH] Show blockstate location if we failed to read it + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +index 730fda7f0bf02400d349959e9cc2aafaed000b21..66aee7635cd9260d97ae9dd2e9a2a0590fe3c433 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +@@ -19,6 +19,8 @@ public class CraftBlockEntityState extends CraftBlockStat + public CraftBlockEntityState(Block block, Class tileEntityClass) { + super(block); + ++ try {// Paper - show location on failure ++ + this.tileEntityClass = tileEntityClass; + + // get tile entity from block: +@@ -38,6 +40,14 @@ public class CraftBlockEntityState extends CraftBlockStat + this.load(this.snapshot); + } + // Paper end ++ // Paper start - show location on failure ++ } catch (Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ throw new RuntimeException("Failed to read BlockState at: world: " + block.getWorld().getName() + " location: (" + block.getX() + ", " + block.getY() + ", " + block.getZ() + ")", thr); ++ } ++ // Paper end + } + + public final boolean snapshotDisabled; // Paper diff --git a/patches/server-remapped/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch b/patches/server-remapped/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch new file mode 100644 index 0000000000..9769725fb1 --- /dev/null +++ b/patches/server-remapped/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 May 2020 20:29:02 -0400 +Subject: [PATCH] Synchronize DataPaletteBlock instead of ReentrantLock + +Mojang has flaws in their logic about chunks being concurrently +wrote to. So we constantly see crashes around multiple threads writing. + +Additionally, java has optimized synchronization so well that its +in many times faster than trying to manage read wrote locks for low +contention situations. + +And this is extremely a low contention situation. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index 6d3dcd19ce1abc9d502903b8008949b5174a13c3..917b0a64083ebbe24321089b784b91f3af4918b9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -8,7 +8,6 @@ import java.util.function.Function; + import java.util.function.Predicate; + import java.util.stream.Collectors; + import net.minecraft.CrashReport; +-import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; + import net.minecraft.core.IdMapper; + import net.minecraft.nbt.CompoundTag; +@@ -32,23 +31,23 @@ public class PalettedContainer implements PaletteResize { + private int bits; private int getBitsPerObject() { return this.bits; } // Paper - OBFHELPER + private final ReentrantLock lock = new ReentrantLock(); + +- public void acquire() { +- if (this.lock.isLocked() && !this.lock.isHeldByCurrentThread()) { ++ public void acquire() { /* // Paper start - disable this - use proper synchronization ++ if (this.j.isLocked() && !this.j.isHeldByCurrentThread()) { + String s = (String) Thread.getAllStackTraces().keySet().stream().filter(Objects::nonNull).map((thread) -> { + return thread.getName() + ": \n\tat " + (String) Arrays.stream(thread.getStackTrace()).map(Object::toString).collect(Collectors.joining("\n\tat ")); + }).collect(Collectors.joining("\n")); + CrashReport crashreport = new CrashReport("Writing into PalettedContainer from multiple threads", new IllegalStateException()); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Thread dumps"); ++ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Thread dumps"); + +- crashreportsystemdetails.setDetail("Thread dumps", (Object) s); ++ crashreportsystemdetails.a("Thread dumps", (Object) s); + throw new ReportedException(crashreport); + } else { +- this.lock.lock(); +- } ++ this.j.lock(); ++ } */ // Paper end + } + + public void release() { +- this.lock.unlock(); ++ //this.j.unlock(); // Paper - disable this + } + + public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { +@@ -84,7 +83,7 @@ public class PalettedContainer implements PaletteResize { + } + + @Override +- public int onResize(int newSize, T objectAdded) { ++ public synchronized int onResize(int newSize, T objectAdded) { // Paper - synchronize + this.acquire(); + BitStorage databits = this.storage; + Palette datapalette = this.palette; +@@ -107,18 +106,18 @@ public class PalettedContainer implements PaletteResize { + } + + public T getAndSet(int x, int y, int z, T value) { +- this.acquire(); +- T t1 = this.getAndSet(getIndex(x, y, z), value); ++ //this.a(); // Paper - remove to reduce ops - synchronize handled below ++ return this.getAndSet(getIndex(x, y, z), value); // Paper + +- this.release(); +- return t1; ++ //this.b(); // Paper ++ //return t1; // PAper + } + + public T getAndSetUnchecked(int x, int y, int z, T value) { + return this.getAndSet(getIndex(x, y, z), value); + } + +- protected T getAndSet(int index, T value) { ++ protected synchronized T getAndSet(int index, T value) { // Paper - synchronize - writes + int j = this.palette.idFor(value); + int k = this.storage.getAndSet(index, j); + T t1 = this.palette.valueFor(k); +@@ -143,7 +142,7 @@ public class PalettedContainer implements PaletteResize { + } + + public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER +- public void write(FriendlyByteBuf buf) { ++ public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize + this.acquire(); + buf.writeByte(this.bits); + this.palette.write(buf); +@@ -151,7 +150,7 @@ public class PalettedContainer implements PaletteResize { + this.release(); + } + +- public void read(ListTag paletteTag, long[] data) { ++ public synchronized void read(ListTag paletteTag, long[] data) { // Paper - synchronize + this.acquire(); + int i = Math.max(4, Mth.ceillog2(paletteTag.size())); + +@@ -184,7 +183,7 @@ public class PalettedContainer implements PaletteResize { + this.release(); + } + +- public void write(CompoundTag nbttagcompound, String s, String s1) { ++ public synchronized void write(CompoundTag nbttagcompound, String s, String s1) { // Paper - synchronize + this.acquire(); + HashMapPalette datapalettehash = new HashMapPalette<>(this.registry, this.bits, this.dummyPaletteResize, this.reader, this.writer); + T t0 = this.defaultValue; diff --git a/patches/server-remapped/0361-incremental-chunk-saving.patch b/patches/server-remapped/0361-incremental-chunk-saving.patch new file mode 100644 index 0000000000..1600ad9506 --- /dev/null +++ b/patches/server-remapped/0361-incremental-chunk-saving.patch @@ -0,0 +1,317 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 9 Jun 2019 03:53:22 +0100 +Subject: [PATCH] incremental chunk saving + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index ffe9b1a63d78925e1d77b9e730aef42fed6d58fa..1278d09f70c1e97607ef20d87a178dc252c7f723 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -446,4 +446,19 @@ public class PaperWorldConfig { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); + log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); + } ++ ++ public int autoSavePeriod = -1; ++ private void autoSavePeriod() { ++ autoSavePeriod = getInt("auto-save-interval", -1); ++ if (autoSavePeriod > 0) { ++ log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)"); ++ } else if (autoSavePeriod < 0) { ++ autoSavePeriod = net.minecraft.server.MinecraftServer.getServer().autosavePeriod; ++ } ++ } ++ ++ public int maxAutoSaveChunksPerTick = 24; ++ private void maxAutoSaveChunksPerTick() { ++ maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0efe7024493f96bb54e7d8c1ea7b233a1b481a04..aab1a055c065d1f1a92461e4442ec2cdd8e0b347 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -261,6 +261,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; ++ public boolean serverAutoSave = false; // Paper + public Commands vanillaCommandDispatcher; + private boolean forceTicks; + // CraftBukkit end +@@ -1256,14 +1257,24 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % autosavePeriod == 0) { // CraftBukkit +- MinecraftServer.LOGGER.debug("Autosave started"); ++ //if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down ++ //MinecraftServer.LOGGER.debug("Autosave started"); // Paper ++ serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper + this.profiler.push("save"); ++ if (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0) { // Paper + this.playerList.saveAll(); +- this.saveAllChunks(true, false, false); ++ }// Paper ++ // Paper start ++ for (ServerLevel world : getAllLevels()) { ++ if (world.paperConfig.autoSavePeriod > 0) { ++ world.saveIncrementally(serverAutoSave); ++ } ++ } ++ // Paper end ++ + this.profiler.pop(); +- MinecraftServer.LOGGER.debug("Autosave finished"); +- } ++ //MinecraftServer.LOGGER.debug("Autosave finished"); // Paper ++ //} // Paper + + this.profiler.push("snooper"); + if (((DedicatedServer) this).getProperties().snooperEnabled && !this.snooper.isStarted() && this.tickCount > 100) { // Spigot +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 7010e0a970462d2b2e1b5696a1a49dba9ea60935..491a9e78fdcec8c211499e8f48cceb829f1e5c8b 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -66,6 +66,9 @@ public class ChunkHolder { + + private final ChunkMap chunkMap; // Paper + ++ long lastAutoSaveTime; // Paper - incremental autosave ++ long inactiveTimeStart; // Paper - incremental autosave ++ + public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +@@ -421,7 +424,19 @@ public class ChunkHolder { + boolean flag2 = playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER); + boolean flag3 = playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER); + ++ boolean prevHasBeenLoaded = this.wasAccessibleSinceLastSave; // Paper + this.wasAccessibleSinceLastSave |= flag3; ++ // Paper start - incremental autosave ++ if (this.wasAccessibleSinceLastSave & !prevHasBeenLoaded) { ++ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; ++ if (timeSinceAutoSave < 0) { ++ // safest bet is to assume autosave is needed here ++ timeSinceAutoSave = this.chunkMap.level.paperConfig.autoSavePeriod; ++ } ++ this.lastAutoSaveTime = this.chunkMap.level.getGameTime() - timeSinceAutoSave; ++ this.chunkMap.autoSaveQueue.add(this); ++ } ++ // Paper end + if (!flag2 && flag3) { + // Paper start - cache ticking ready status + int expectCreateCount = ++this.fullChunkCreateCount; +@@ -541,8 +556,32 @@ public class ChunkHolder { + } + + public void refreshAccessibility() { ++ boolean prev = this.wasAccessibleSinceLastSave; // Paper ++ this.wasAccessibleSinceLastSave = getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER); ++ // Paper start - incremental autosave ++ if (prev != this.wasAccessibleSinceLastSave) { ++ if (this.wasAccessibleSinceLastSave) { ++ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; ++ if (timeSinceAutoSave < 0) { ++ // safest bet is to assume autosave is needed here ++ timeSinceAutoSave = this.chunkMap.level.paperConfig.autoSavePeriod; ++ } ++ this.lastAutoSaveTime = this.chunkMap.level.getGameTime() - timeSinceAutoSave; ++ this.chunkMap.autoSaveQueue.add(this); ++ } else { ++ this.inactiveTimeStart = this.chunkMap.level.getGameTime(); ++ this.chunkMap.autoSaveQueue.remove(this); ++ } ++ } ++ // Paper end ++ } ++ ++ // Paper start - incremental autosave ++ public boolean setHasBeenLoaded() { + this.wasAccessibleSinceLastSave = getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER); ++ return this.wasAccessibleSinceLastSave; + } ++ // Paper end + + public void replaceProtoChunk(ImposterProtoChunk protochunkextension) { + for (int i = 0; i < this.futures.length(); ++i) { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0aac29de933c84c34cb24e204e8fcc7010060d8f..cfec04e12dfaeb8852dc129a6a7e68c61dac54b6 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -91,6 +91,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelStorageSource; + import net.minecraft.world.phys.Vec3; ++import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper + import org.apache.commons.lang3.mutable.MutableBoolean; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -378,6 +379,64 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + } + ++ // Paper start - incremental autosave ++ final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((playerchunk1, playerchunk2) -> { ++ int timeCompare = Long.compare(playerchunk1.lastAutoSaveTime, playerchunk2.lastAutoSaveTime); ++ if (timeCompare != 0) { ++ return timeCompare; ++ } ++ ++ return Long.compare(MCUtil.getCoordinateKey(playerchunk1.pos), MCUtil.getCoordinateKey(playerchunk2.pos)); ++ }); ++ ++ protected void saveIncrementally() { ++ int savedThisTick = 0; ++ // optimized since we search far less chunks to hit ones that need to be saved ++ List reschedule = new java.util.ArrayList<>(this.level.paperConfig.maxAutoSaveChunksPerTick); ++ long currentTick = this.level.getGameTime(); ++ long maxSaveTime = currentTick - this.level.paperConfig.autoSavePeriod; ++ ++ for (Iterator iterator = this.autoSaveQueue.iterator(); iterator.hasNext();) { ++ ChunkHolder playerchunk = iterator.next(); ++ if (playerchunk.lastAutoSaveTime > maxSaveTime) { ++ break; ++ } ++ ++ iterator.remove(); ++ ++ ChunkAccess ichunkaccess = playerchunk.getChunkToSave().getNow(null); ++ if (ichunkaccess instanceof LevelChunk) { ++ boolean shouldSave = ((LevelChunk)ichunkaccess).lastSaveTime <= maxSaveTime; ++ ++ if (shouldSave && this.save(ichunkaccess)) { ++ ++savedThisTick; ++ ++ if (!playerchunk.setHasBeenLoaded()) { ++ // do not fall through to reschedule logic ++ playerchunk.inactiveTimeStart = currentTick; ++ if (savedThisTick >= this.level.paperConfig.maxAutoSaveChunksPerTick) { ++ break; ++ } ++ continue; ++ } ++ } ++ } ++ ++ reschedule.add(playerchunk); ++ ++ if (savedThisTick >= this.level.paperConfig.maxAutoSaveChunksPerTick) { ++ break; ++ } ++ } ++ ++ for (int i = 0, len = reschedule.size(); i < len; ++i) { ++ ChunkHolder playerchunk = reschedule.get(i); ++ playerchunk.lastAutoSaveTime = this.level.getGameTime(); ++ this.autoSaveQueue.add(playerchunk); ++ } ++ } ++ // Paper end ++ + protected void saveAllChunks(boolean flush) { + if (flush) { + List list = (List) this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); +@@ -488,6 +547,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + this.level.unload(chunk); + } ++ this.autoSaveQueue.remove(playerchunk); // Paper + + this.lightEngine.updateChunkStatus(ichunkaccess.getPos()); + this.lightEngine.tryScheduleUpdate(); +@@ -680,6 +740,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + playerchunk.replaceProtoChunk(new ImposterProtoChunk(chunk)); + } + ++ chunk.setLastSaveTime(this.level.getGameTime() - 1); // Paper - avoid autosaving newly generated/loaded chunks ++ + chunk.setFullStatus(() -> { + return ChunkHolder.getFullChunkStatus(playerchunk.getTicketLevel()); + }); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 1e8ac0110badbf2d1c2336168c3e11991667c782..c1aa40c01a80a8870478193b8cd7354b0d71045c 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -558,6 +558,15 @@ public class ServerChunkCache extends ChunkSource { + } // Paper - Timings + } + ++ // Paper start - duplicate save, but call incremental ++ public void saveIncrementally() { ++ this.runDistanceManagerUpdates(); ++ try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings ++ this.chunkMap.saveIncrementally(); ++ } // Paper - Timings ++ } ++ // Paper end ++ + @Override + public void close() throws IOException { + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index b2ddf145ae9f581ec6820deb9cb6a98be87658d7..fd7ee4badb383ffb4347d62c00ea2dfa3d76fd12 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -882,6 +882,38 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos); + } + ++ // Paper start - derived from below ++ public void saveIncrementally(boolean doFull) { ++ ServerChunkCache chunkproviderserver = this.getChunkSource(); ++ ++ if (doFull) { ++ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); ++ } ++ ++ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { ++ if (doFull) { ++ this.saveData(); ++ } ++ ++ timings.worldSaveChunks.startTiming(); // Paper ++ if (!this.noSave()) chunkproviderserver.saveIncrementally(); ++ timings.worldSaveChunks.stopTiming(); // Paper ++ ++ ++ // Copied from save() ++ // CraftBukkit start - moved from MinecraftServer.saveChunks ++ if (doFull) { // Paper ++ ServerLevel worldserver1 = this; ++ ++ worldDataServer.setWorldBorder(worldserver1.getWorldBorder().createSettings()); ++ worldDataServer.setCustomBossEvents(this.server.getCustomBossEvents().save()); ++ convertable.saveDataTag(this.server.registryHolder, this.worldDataServer, this.server.getPlayerList().getSingleplayerData()); ++ } ++ // CraftBukkit end ++ } ++ } ++ // Paper end ++ + public void save(@Nullable ProgressListener progressListener, boolean flush, boolean flag1) { + ServerChunkCache chunkproviderserver = this.getChunkSource(); + +@@ -912,6 +944,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // CraftBukkit end + } + ++ private void saveData() { this.saveLevelData(); } // Paper - OBFHELPER + private void saveLevelData() { + if (this.dragonFight != null) { + this.worldDataServer.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 55872a17060a35b727a597bc414fecec3ada3515..419b4bf0549d798d52d73fbbd9de59313fc05eb1 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -80,7 +80,7 @@ public class LevelChunk implements ChunkAccess { + private TickList blockTicks; + private TickList liquidTicks; + private boolean lastSaveHadEntities; +- private long lastSaveTime; ++ public long lastSaveTime; // Paper + private volatile boolean unsaved; + private long inhabitedTime; + @Nullable diff --git a/patches/server-remapped/0362-Anti-Xray.patch b/patches/server-remapped/0362-Anti-Xray.patch new file mode 100644 index 0000000000..95ed9fdc2a --- /dev/null +++ b/patches/server-remapped/0362-Anti-Xray.patch @@ -0,0 +1,1624 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: stonar96 +Date: Mon, 20 Aug 2018 03:03:58 +0200 +Subject: [PATCH] Anti-Xray + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1278d09f70c1e97607ef20d87a178dc252c7f723..c45493e88bf7e8811be2759ff9ac19e3fe9d938a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -1,7 +1,9 @@ + package com.destroystokyo.paper; + ++import java.util.Arrays; + import java.util.List; + ++import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; + import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; +@@ -461,4 +463,38 @@ public class PaperWorldConfig { + private void maxAutoSaveChunksPerTick() { + maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); + } ++ ++ public boolean antiXray; ++ public EngineMode engineMode; ++ public int maxChunkSectionIndex; ++ public int updateRadius; ++ public boolean lavaObscures; ++ public boolean usePermission; ++ public List hiddenBlocks; ++ public List replacementBlocks; ++ private void antiXray() { ++ antiXray = getBoolean("anti-xray.enabled", false); ++ engineMode = EngineMode.getById(getInt("anti-xray.engine-mode", EngineMode.HIDE.getId())); ++ engineMode = engineMode == null ? EngineMode.HIDE : engineMode; ++ maxChunkSectionIndex = getInt("anti-xray.max-chunk-section-index", 3); ++ maxChunkSectionIndex = maxChunkSectionIndex > 15 ? 15 : maxChunkSectionIndex; ++ updateRadius = getInt("anti-xray.update-radius", 2); ++ lavaObscures = getBoolean("anti-xray.lava-obscures", false); ++ usePermission = getBoolean("anti-xray.use-permission", false); ++ hiddenBlocks = getList("anti-xray.hidden-blocks", Arrays.asList("gold_ore", "iron_ore", "coal_ore", "lapis_ore", "mossy_cobblestone", "obsidian", "chest", "diamond_ore", "redstone_ore", "clay", "emerald_ore", "ender_chest")); ++ replacementBlocks = getList("anti-xray.replacement-blocks", Arrays.asList("stone", "oak_planks")); ++ if (PaperConfig.version < 19) { ++ hiddenBlocks.remove("lit_redstone_ore"); ++ int index = replacementBlocks.indexOf("planks"); ++ if (index != -1) { ++ replacementBlocks.set(index, "oak_planks"); ++ } ++ set("anti-xray.hidden-blocks", hiddenBlocks); ++ set("anti-xray.replacement-blocks", replacementBlocks); ++ } ++ log("Anti-Xray: " + (antiXray ? "enabled" : "disabled") + " / Engine Mode: " + engineMode.getDescription() + " / Up to " + ((maxChunkSectionIndex + 1) * 16) + " blocks / Update Radius: " + updateRadius); ++ if (antiXray && usePermission) { ++ Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8fb63441fbf9afb6f11e1185a9f29528e1950546 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java +@@ -0,0 +1,45 @@ ++package com.destroystokyo.paper.antixray; ++ ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.ServerPlayerGameMode; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.LevelChunkSection; ++ ++public class ChunkPacketBlockController { ++ ++ public static final ChunkPacketBlockController NO_OPERATION_INSTANCE = new ChunkPacketBlockController(); ++ ++ protected ChunkPacketBlockController() { ++ ++ } ++ ++ public BlockState[] getPredefinedBlockData(Level world, ChunkAccess chunk, LevelChunkSection chunkSection, boolean initializeBlocks) { ++ return null; ++ } ++ ++ public boolean shouldModify(ServerPlayer entityPlayer, LevelChunk chunk, int chunkSectionSelector) { ++ return false; ++ } ++ ++ public ChunkPacketInfo getChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector) { ++ return null; ++ } ++ ++ public void modifyBlocks(ClientboundLevelChunkPacket packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { ++ packetPlayOutMapChunk.setReady(true); ++ } ++ ++ public void onBlockChange(Level world, BlockPos blockPosition, BlockState newBlockData, BlockState oldBlockData, int flag) { ++ ++ } ++ ++ public void onPlayerLeftClickBlock(ServerPlayerGameMode playerInteractManager, BlockPos blockPosition, Direction enumDirection) { ++ ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6d41628444e880dea5c96ad5caf557f4c56dea46 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java +@@ -0,0 +1,649 @@ ++package com.destroystokyo.paper.antixray; ++ ++import java.util.ArrayList; ++import java.util.LinkedHashSet; ++import java.util.LinkedList; ++import java.util.List; ++import java.util.Set; ++import java.util.concurrent.Executor; ++import java.util.concurrent.ThreadLocalRandom; ++import java.util.function.IntSupplier; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.core.Registry; ++import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.ServerPlayerGameMode; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.EmptyLevelChunk; ++import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.LevelChunkSection; ++import net.minecraft.world.level.chunk.Palette; ++import org.bukkit.Bukkit; ++import org.bukkit.World.Environment; ++ ++import com.destroystokyo.paper.PaperWorldConfig; ++ ++public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockController { ++ ++ private final Executor executor; ++ private final EngineMode engineMode; ++ private final int maxChunkSectionIndex; ++ private final int updateRadius; ++ private final boolean usePermission; ++ private final BlockState[] predefinedBlockData; ++ private final BlockState[] predefinedBlockDataFull; ++ private final BlockState[] predefinedBlockDataStone; ++ private final BlockState[] predefinedBlockDataNetherrack; ++ private final BlockState[] predefinedBlockDataEndStone; ++ private final int[] predefinedBlockDataBitsGlobal; ++ private final int[] predefinedBlockDataBitsStoneGlobal; ++ private final int[] predefinedBlockDataBitsNetherrackGlobal; ++ private final int[] predefinedBlockDataBitsEndStoneGlobal; ++ private final boolean[] solidGlobal = new boolean[Block.BLOCK_STATE_REGISTRY.size()]; ++ private final boolean[] obfuscateGlobal = new boolean[Block.BLOCK_STATE_REGISTRY.size()]; ++ private final LevelChunkSection[] emptyNearbyChunkSections = {LevelChunk.EMPTY_CHUNK_SECTION, LevelChunk.EMPTY_CHUNK_SECTION, LevelChunk.EMPTY_CHUNK_SECTION, LevelChunk.EMPTY_CHUNK_SECTION}; ++ private final int maxBlockYUpdatePosition; ++ ++ public ChunkPacketBlockControllerAntiXray(Level world, Executor executor) { ++ PaperWorldConfig paperWorldConfig = world.paperConfig; ++ engineMode = paperWorldConfig.engineMode; ++ maxChunkSectionIndex = paperWorldConfig.maxChunkSectionIndex; ++ updateRadius = paperWorldConfig.updateRadius; ++ usePermission = paperWorldConfig.usePermission; ++ ++ this.executor = executor; ++ ++ List toObfuscate; ++ ++ if (engineMode == EngineMode.HIDE) { ++ toObfuscate = paperWorldConfig.hiddenBlocks; ++ predefinedBlockData = null; ++ predefinedBlockDataFull = null; ++ predefinedBlockDataStone = new BlockState[] {Blocks.STONE.defaultBlockState()}; ++ predefinedBlockDataNetherrack = new BlockState[] {Blocks.NETHERRACK.defaultBlockState()}; ++ predefinedBlockDataEndStone = new BlockState[] {Blocks.END_STONE.defaultBlockState()}; ++ predefinedBlockDataBitsGlobal = null; ++ predefinedBlockDataBitsStoneGlobal = new int[] {LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(Blocks.STONE.defaultBlockState())}; ++ predefinedBlockDataBitsNetherrackGlobal = new int[] {LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(Blocks.NETHERRACK.defaultBlockState())}; ++ predefinedBlockDataBitsEndStoneGlobal = new int[] {LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(Blocks.END_STONE.defaultBlockState())}; ++ } else { ++ toObfuscate = new ArrayList<>(paperWorldConfig.replacementBlocks); ++ List predefinedBlockDataList = new LinkedList(); ++ ++ for (String id : paperWorldConfig.hiddenBlocks) { ++ Block block = Registry.BLOCK.getOptional(new ResourceLocation(id)).orElse(null); ++ ++ if (block != null && !block.isEntityBlock()) { ++ toObfuscate.add(id); ++ predefinedBlockDataList.add(block.defaultBlockState()); ++ } ++ } ++ ++ // The doc of the LinkedHashSet(Collection c) constructor doesn't specify that the insertion order is the predictable iteration order of the specified Collection, although it is in the implementation ++ Set predefinedBlockDataSet = new LinkedHashSet(); ++ // Therefore addAll(Collection c) is used, which guarantees this order in the doc ++ predefinedBlockDataSet.addAll(predefinedBlockDataList); ++ predefinedBlockData = predefinedBlockDataSet.size() == 0 ? new BlockState[] {Blocks.DIAMOND_ORE.defaultBlockState()} : predefinedBlockDataSet.toArray(new BlockState[0]); ++ predefinedBlockDataFull = predefinedBlockDataSet.size() == 0 ? new BlockState[] {Blocks.DIAMOND_ORE.defaultBlockState()} : predefinedBlockDataList.toArray(new BlockState[0]); ++ predefinedBlockDataStone = null; ++ predefinedBlockDataNetherrack = null; ++ predefinedBlockDataEndStone = null; ++ predefinedBlockDataBitsGlobal = new int[predefinedBlockDataFull.length]; ++ ++ for (int i = 0; i < predefinedBlockDataFull.length; i++) { ++ predefinedBlockDataBitsGlobal[i] = LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(predefinedBlockDataFull[i]); ++ } ++ ++ predefinedBlockDataBitsStoneGlobal = null; ++ predefinedBlockDataBitsNetherrackGlobal = null; ++ predefinedBlockDataBitsEndStoneGlobal = null; ++ } ++ ++ for (String id : toObfuscate) { ++ Block block = Registry.BLOCK.getOptional(new ResourceLocation(id)).orElse(null); ++ ++ // Don't obfuscate air because air causes unnecessary block updates and causes block updates to fail in the void ++ if (block != null && !block.defaultBlockState().isAir()) { ++ // Replace all block states of a specified block ++ // No OBFHELPER for nms.BlockStateList#a() due to too many decompile errors ++ // The OBFHELPER should be getBlockDataList() ++ for (BlockState blockData : block.getStateDefinition().getPossibleStates()) { ++ obfuscateGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(blockData)] = true; ++ } ++ } ++ } ++ ++ EmptyLevelChunk emptyChunk = new EmptyLevelChunk(world, new ChunkPos(0, 0)); ++ BlockPos zeroPos = new BlockPos(0, 0, 0); ++ ++ for (int i = 0; i < solidGlobal.length; i++) { ++ BlockState blockData = LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getObject(i); ++ ++ if (blockData != null) { ++ solidGlobal[i] = blockData.isRedstoneConductor(emptyChunk, zeroPos) ++ && blockData.getBlock() != Blocks.SPAWNER && blockData.getBlock() != Blocks.BARRIER && blockData.getBlock() != Blocks.SHULKER_BOX && blockData.getBlock() != Blocks.SLIME_BLOCK || paperWorldConfig.lavaObscures && blockData == Blocks.LAVA.defaultBlockState(); ++ // Comparing blockData == Blocks.LAVA.getBlockData() instead of blockData.getBlock() == Blocks.LAVA ensures that only "stationary lava" is used ++ // shulker box checks TE. ++ } ++ } ++ ++ this.maxBlockYUpdatePosition = (maxChunkSectionIndex + 1) * 16 + updateRadius - 1; ++ } ++ ++ private int getPredefinedBlockDataFullLength() { ++ return engineMode == EngineMode.HIDE ? 1 : predefinedBlockDataFull.length; ++ } ++ ++ @Override ++ public BlockState[] getPredefinedBlockData(Level world, ChunkAccess chunk, LevelChunkSection chunkSection, boolean initializeBlocks) { ++ // Return the block data which should be added to the data palettes so that they can be used for the obfuscation ++ if (chunkSection.bottomBlockY() >> 4 <= maxChunkSectionIndex) { ++ switch (engineMode) { ++ case HIDE: ++ switch (world.getWorld().getEnvironment()) { ++ case NETHER: ++ return predefinedBlockDataNetherrack; ++ case THE_END: ++ return predefinedBlockDataEndStone; ++ default: ++ return predefinedBlockDataStone; ++ } ++ default: ++ return predefinedBlockData; ++ } ++ } ++ ++ return null; ++ } ++ ++ @Override ++ public boolean shouldModify(ServerPlayer entityPlayer, LevelChunk chunk, int chunkSectionSelector) { ++ return !usePermission || !entityPlayer.getBukkitEntity().hasPermission("paper.antixray.bypass"); ++ } ++ ++ @Override ++ public ChunkPacketInfoAntiXray getChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector) { ++ // Return a new instance to collect data and objects in the right state while creating the chunk packet for thread safe access later ++ // Note: As of 1.14 this has to be moved later due to the chunk system. ++ ChunkPacketInfoAntiXray chunkPacketInfoAntiXray = new ChunkPacketInfoAntiXray(packetPlayOutMapChunk, chunk, chunkSectionSelector, this); ++ return chunkPacketInfoAntiXray; ++ } ++ ++ @Override ++ public void modifyBlocks(ClientboundLevelChunkPacket packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { ++ if (chunkPacketInfo == null) { ++ packetPlayOutMapChunk.setReady(true); ++ return; ++ } ++ ++ if (!Bukkit.isPrimaryThread()) { ++ // plugins? ++ MinecraftServer.getServer().scheduleOnMain(() -> { ++ this.modifyBlocks(packetPlayOutMapChunk, chunkPacketInfo); ++ }); ++ return; ++ } ++ ++ LevelChunk chunk = chunkPacketInfo.getChunk(); ++ int x = chunk.getPos().x; ++ int z = chunk.getPos().z; ++ ServerLevel world = (ServerLevel)chunk.world; ++ ((ChunkPacketInfoAntiXray) chunkPacketInfo).setNearbyChunks( ++ (LevelChunk) world.getChunkIfLoadedImmediately(x - 1, z), ++ (LevelChunk) world.getChunkIfLoadedImmediately(x + 1, z), ++ (LevelChunk) world.getChunkIfLoadedImmediately(x, z - 1), ++ (LevelChunk) world.getChunkIfLoadedImmediately(x, z + 1)); ++ ++ executor.execute((ChunkPacketInfoAntiXray) chunkPacketInfo); ++ } ++ ++ // Actually these fields should be variables inside the obfuscate method but in sync mode or with SingleThreadExecutor in async mode it's okay (even without ThreadLocal) ++ // If an ExecutorService with multiple threads is used, ThreadLocal must be used here ++ private final ThreadLocal predefinedBlockDataBits = ThreadLocal.withInitial(() -> new int[getPredefinedBlockDataFullLength()]); ++ private static final ThreadLocal solid = ThreadLocal.withInitial(() -> new boolean[Block.BLOCK_STATE_REGISTRY.size()]); ++ private static final ThreadLocal obfuscate = ThreadLocal.withInitial(() -> new boolean[Block.BLOCK_STATE_REGISTRY.size()]); ++ // These boolean arrays represent chunk layers, true means don't obfuscate, false means obfuscate ++ private static final ThreadLocal current = ThreadLocal.withInitial(() -> new boolean[16][16]); ++ private static final ThreadLocal next = ThreadLocal.withInitial(() -> new boolean[16][16]); ++ private static final ThreadLocal nextNext = ThreadLocal.withInitial(() -> new boolean[16][16]); ++ ++ public void obfuscate(ChunkPacketInfoAntiXray chunkPacketInfoAntiXray) { ++ int[] predefinedBlockDataBits = this.predefinedBlockDataBits.get(); ++ boolean[] solid = this.solid.get(); ++ boolean[] obfuscate = this.obfuscate.get(); ++ boolean[][] current = this.current.get(); ++ boolean[][] next = this.next.get(); ++ boolean[][] nextNext = this.nextNext.get(); ++ // dataBitsReader, dataBitsWriter and nearbyChunkSections could also be reused (with ThreadLocal if necessary) but it's not worth it ++ DataBitsReader dataBitsReader = new DataBitsReader(); ++ DataBitsWriter dataBitsWriter = new DataBitsWriter(); ++ LevelChunkSection[] nearbyChunkSections = new LevelChunkSection[4]; ++ boolean[] solidTemp = null; ++ boolean[] obfuscateTemp = null; ++ dataBitsReader.setDataBits(chunkPacketInfoAntiXray.getData()); ++ dataBitsWriter.setDataBits(chunkPacketInfoAntiXray.getData()); ++ int numberOfBlocks = predefinedBlockDataBits.length; ++ // Keep the lambda expressions as simple as possible. They are used very frequently. ++ IntSupplier random = numberOfBlocks == 1 ? (() -> 0) : new IntSupplier() { ++ private int state; ++ ++ { ++ while ((state = ThreadLocalRandom.current().nextInt()) == 0); ++ } ++ ++ @Override ++ public int getAsInt() { ++ // https://en.wikipedia.org/wiki/Xorshift ++ state ^= state << 13; ++ state ^= state >>> 17; ++ state ^= state << 5; ++ // https://www.pcg-random.org/posts/bounded-rands.html ++ return (int) ((Integer.toUnsignedLong(state) * numberOfBlocks) >>> 32); ++ } ++ }; ++ ++ for (int chunkSectionIndex = 0; chunkSectionIndex <= maxChunkSectionIndex; chunkSectionIndex++) { ++ if (chunkPacketInfoAntiXray.isWritten(chunkSectionIndex) && chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) != null) { ++ int[] predefinedBlockDataBitsTemp; ++ ++ if (chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex) == LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE) { ++ predefinedBlockDataBitsTemp = engineMode == EngineMode.HIDE ? chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.NETHER ? predefinedBlockDataBitsNetherrackGlobal : chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.THE_END ? predefinedBlockDataBitsEndStoneGlobal : predefinedBlockDataBitsStoneGlobal : predefinedBlockDataBitsGlobal; ++ } else { ++ // If it's this.predefinedBlockData, use this.predefinedBlockDataFull instead ++ BlockState[] predefinedBlockDataFull = chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) == predefinedBlockData ? this.predefinedBlockDataFull : chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex); ++ predefinedBlockDataBitsTemp = predefinedBlockDataBits; ++ ++ for (int i = 0; i < predefinedBlockDataBitsTemp.length; i++) { ++ predefinedBlockDataBitsTemp[i] = chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex).getOrCreateIdFor(predefinedBlockDataFull[i]); ++ } ++ } ++ ++ dataBitsWriter.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); ++ ++ // Check if the chunk section below was not obfuscated ++ if (chunkSectionIndex == 0 || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex - 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex - 1) == null) { ++ // If so, initialize some stuff ++ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); ++ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); ++ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), solid, solidGlobal); ++ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), obfuscate, obfuscateGlobal); ++ // Read the blocks of the upper layer of the chunk section below if it exists ++ LevelChunkSection belowChunkSection = null; ++ boolean skipFirstLayer = chunkSectionIndex == 0 || (belowChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex - 1]) == LevelChunk.EMPTY_CHUNK_SECTION; ++ ++ for (int z = 0; z < 16; z++) { ++ for (int x = 0; x < 16; x++) { ++ current[z][x] = true; ++ next[z][x] = skipFirstLayer || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(belowChunkSection.getBlockState(x, 15, z))]; ++ } ++ } ++ ++ // Abuse the obfuscateLayer method to read the blocks of the first layer of the current chunk section ++ dataBitsWriter.setBitsPerObject(0); ++ obfuscateLayer(-1, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, emptyNearbyChunkSections, random); ++ } ++ ++ dataBitsWriter.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); ++ nearbyChunkSections[0] = chunkPacketInfoAntiXray.getNearbyChunks()[0] == null ? LevelChunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[0].getSections()[chunkSectionIndex]; ++ nearbyChunkSections[1] = chunkPacketInfoAntiXray.getNearbyChunks()[1] == null ? LevelChunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[1].getSections()[chunkSectionIndex]; ++ nearbyChunkSections[2] = chunkPacketInfoAntiXray.getNearbyChunks()[2] == null ? LevelChunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[2].getSections()[chunkSectionIndex]; ++ nearbyChunkSections[3] = chunkPacketInfoAntiXray.getNearbyChunks()[3] == null ? LevelChunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[3].getSections()[chunkSectionIndex]; ++ ++ // Obfuscate all layers of the current chunk section except the upper one ++ for (int y = 0; y < 15; y++) { ++ boolean[][] temp = current; ++ current = next; ++ next = nextNext; ++ nextNext = temp; ++ obfuscateLayer(y, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); ++ } ++ ++ // Check if the chunk section above doesn't need obfuscation ++ if (chunkSectionIndex == maxChunkSectionIndex || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex + 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex + 1) == null) { ++ // If so, obfuscate the upper layer of the current chunk section by reading blocks of the first layer from the chunk section above if it exists ++ LevelChunkSection aboveChunkSection; ++ ++ if (chunkSectionIndex != 15 && (aboveChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex + 1]) != LevelChunk.EMPTY_CHUNK_SECTION) { ++ boolean[][] temp = current; ++ current = next; ++ next = nextNext; ++ nextNext = temp; ++ ++ for (int z = 0; z < 16; z++) { ++ for (int x = 0; x < 16; x++) { ++ if (!solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(aboveChunkSection.getBlockState(x, 0, z))]) { ++ current[z][x] = true; ++ } ++ } ++ } ++ ++ // There is nothing to read anymore ++ dataBitsReader.setBitsPerObject(0); ++ solid[0] = true; ++ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solid, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); ++ } ++ } else { ++ // If not, initialize the reader and other stuff for the chunk section above to obfuscate the upper layer of the current chunk section ++ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex + 1)); ++ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex + 1)); ++ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), solid, solidGlobal); ++ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), obfuscate, obfuscateGlobal); ++ boolean[][] temp = current; ++ current = next; ++ next = nextNext; ++ nextNext = temp; ++ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); ++ } ++ ++ dataBitsWriter.finish(); ++ } ++ } ++ ++ chunkPacketInfoAntiXray.getPacketPlayOutMapChunk().setReady(true); ++ } ++ ++ private void obfuscateLayer(int y, DataBitsReader dataBitsReader, DataBitsWriter dataBitsWriter, boolean[] solid, boolean[] obfuscate, int[] predefinedBlockDataBits, boolean[][] current, boolean[][] next, boolean[][] nextNext, LevelChunkSection[] nearbyChunkSections, IntSupplier random) { ++ // First block of first line ++ int dataBits = dataBitsReader.read(); ++ ++ if (nextNext[0][0] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[0][1] = true; ++ next[1][0] = true; ++ } else { ++ if (nearbyChunkSections[2] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getBlockState(0, y, 15))] || nearbyChunkSections[0] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getBlockState(15, y, 0))] || current[0][0]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[0][0] = true; ++ } ++ ++ // First line ++ for (int x = 1; x < 15; x++) { ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[0][x] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[0][x - 1] = true; ++ next[0][x + 1] = true; ++ next[1][x] = true; ++ } else { ++ if (nearbyChunkSections[2] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getBlockState(x, y, 15))] || current[0][x]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[0][x] = true; ++ } ++ } ++ ++ // Last block of first line ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[0][15] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[0][14] = true; ++ next[1][15] = true; ++ } else { ++ if (nearbyChunkSections[2] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getBlockState(15, y, 15))] || nearbyChunkSections[1] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getBlockState(0, y, 0))] || current[0][15]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[0][15] = true; ++ } ++ ++ // All inner lines ++ for (int z = 1; z < 15; z++) { ++ // First block ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[z][0] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[z][1] = true; ++ next[z - 1][0] = true; ++ next[z + 1][0] = true; ++ } else { ++ if (nearbyChunkSections[0] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getBlockState(15, y, z))] || current[z][0]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[z][0] = true; ++ } ++ ++ // All inner blocks ++ for (int x = 1; x < 15; x++) { ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[z][x] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[z][x - 1] = true; ++ next[z][x + 1] = true; ++ next[z - 1][x] = true; ++ next[z + 1][x] = true; ++ } else { ++ if (current[z][x]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[z][x] = true; ++ } ++ } ++ ++ // Last block ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[z][15] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[z][14] = true; ++ next[z - 1][15] = true; ++ next[z + 1][15] = true; ++ } else { ++ if (nearbyChunkSections[1] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getBlockState(0, y, z))] || current[z][15]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[z][15] = true; ++ } ++ } ++ ++ // First block of last line ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[15][0] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[15][1] = true; ++ next[14][0] = true; ++ } else { ++ if (nearbyChunkSections[3] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getBlockState(0, y, 0))] || nearbyChunkSections[0] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getBlockState(15, y, 15))] || current[15][0]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[15][0] = true; ++ } ++ ++ // Last line ++ for (int x = 1; x < 15; x++) { ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[15][x] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[15][x - 1] = true; ++ next[15][x + 1] = true; ++ next[14][x] = true; ++ } else { ++ if (nearbyChunkSections[3] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getBlockState(x, y, 0))] || current[15][x]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[15][x] = true; ++ } ++ } ++ ++ // Last block of last line ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[15][15] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[15][14] = true; ++ next[14][15] = true; ++ } else { ++ if (nearbyChunkSections[3] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getBlockState(15, y, 0))] || nearbyChunkSections[1] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getBlockState(0, y, 15))] || current[15][15]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[15][15] = true; ++ } ++ } ++ ++ private boolean[] readDataPalette(Palette dataPalette, boolean[] temp, boolean[] global) { ++ if (dataPalette == LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE) { ++ return global; ++ } ++ ++ BlockState blockData; ++ ++ for (int i = 0; (blockData = dataPalette.getObject(i)) != null; i++) { ++ temp[i] = global[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(blockData)]; ++ } ++ ++ return temp; ++ } ++ ++ @Override ++ public void onBlockChange(Level world, BlockPos blockPosition, BlockState newBlockData, BlockState oldBlockData, int flag) { ++ if (oldBlockData != null && solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(oldBlockData)] && !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(newBlockData)] && blockPosition.getY() <= maxBlockYUpdatePosition) { ++ updateNearbyBlocks(world, blockPosition); ++ } ++ } ++ ++ @Override ++ public void onPlayerLeftClickBlock(ServerPlayerGameMode playerInteractManager, BlockPos blockPosition, Direction enumDirection) { ++ if (blockPosition.getY() <= maxBlockYUpdatePosition) { ++ updateNearbyBlocks(playerInteractManager.level, blockPosition); ++ } ++ } ++ ++ private void updateNearbyBlocks(Level world, BlockPos blockPosition) { ++ if (updateRadius >= 2) { ++ BlockPos temp = blockPosition.west(); ++ updateBlock(world, temp); ++ updateBlock(world, temp.west()); ++ updateBlock(world, temp.below()); ++ updateBlock(world, temp.above()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.east()); ++ updateBlock(world, temp.east()); ++ updateBlock(world, temp.below()); ++ updateBlock(world, temp.above()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.below()); ++ updateBlock(world, temp.below()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.above()); ++ updateBlock(world, temp.above()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.north()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp = blockPosition.south()); ++ updateBlock(world, temp.south()); ++ } else if (updateRadius == 1) { ++ updateBlock(world, blockPosition.west()); ++ updateBlock(world, blockPosition.east()); ++ updateBlock(world, blockPosition.below()); ++ updateBlock(world, blockPosition.above()); ++ updateBlock(world, blockPosition.north()); ++ updateBlock(world, blockPosition.south()); ++ } else { ++ // Do nothing if updateRadius <= 0 (test mode) ++ } ++ } ++ ++ private void updateBlock(Level world, BlockPos blockPosition) { ++ BlockState blockData = world.getTypeIfLoaded(blockPosition); ++ ++ if (blockData != null && obfuscateGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(blockData)]) { ++ // world.notify(blockPosition, blockData, blockData, 3); ++ ((ServerLevel)world).getChunkSource().blockChanged(blockPosition); // We only need to re-send to client ++ } ++ } ++ ++ public enum EngineMode { ++ ++ HIDE(1, "hide ores"), ++ OBFUSCATE(2, "obfuscate"); ++ ++ private final int id; ++ private final String description; ++ ++ EngineMode(int id, String description) { ++ this.id = id; ++ this.description = description; ++ } ++ ++ public static EngineMode getById(int id) { ++ for (EngineMode engineMode : values()) { ++ if (engineMode.id == id) { ++ return engineMode; ++ } ++ } ++ ++ return null; ++ } ++ ++ public int getId() { ++ return id; ++ } ++ ++ public String getDescription() { ++ return description; ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java +new file mode 100644 +index 0000000000000000000000000000000000000000..dc04ffc76e11ab63cd98a84cf95c58dc5cd1efdb +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java +@@ -0,0 +1,81 @@ ++package com.destroystokyo.paper.antixray; ++ ++import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; ++import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.Palette; ++ ++public class ChunkPacketInfo { ++ ++ private final ClientboundLevelChunkPacket packetPlayOutMapChunk; ++ private final LevelChunk chunk; ++ private final int chunkSectionSelector; ++ private byte[] data; ++ private final int[] bitsPerObject = new int[16]; ++ private final Object[] dataPalettes = new Object[16]; ++ private final int[] dataBitsIndexes = new int[16]; ++ private final Object[][] predefinedObjects = new Object[16][]; ++ ++ public ChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector) { ++ this.packetPlayOutMapChunk = packetPlayOutMapChunk; ++ this.chunk = chunk; ++ this.chunkSectionSelector = chunkSectionSelector; ++ } ++ ++ public ClientboundLevelChunkPacket getPacketPlayOutMapChunk() { ++ return packetPlayOutMapChunk; ++ } ++ ++ public LevelChunk getChunk() { ++ return chunk; ++ } ++ ++ public int getChunkSectionSelector() { ++ return chunkSectionSelector; ++ } ++ ++ public byte[] getData() { ++ return data; ++ } ++ ++ public void setData(byte[] data) { ++ this.data = data; ++ } ++ ++ public int getBitsPerObject(int chunkSectionIndex) { ++ return bitsPerObject[chunkSectionIndex]; ++ } ++ ++ public void setBitsPerObject(int chunkSectionIndex, int bitsPerObject) { ++ this.bitsPerObject[chunkSectionIndex] = bitsPerObject; ++ } ++ ++ @SuppressWarnings("unchecked") ++ public Palette getDataPalette(int chunkSectionIndex) { ++ return (Palette) dataPalettes[chunkSectionIndex]; ++ } ++ ++ public void setDataPalette(int chunkSectionIndex, Palette dataPalette) { ++ dataPalettes[chunkSectionIndex] = dataPalette; ++ } ++ ++ public int getDataBitsIndex(int chunkSectionIndex) { ++ return dataBitsIndexes[chunkSectionIndex]; ++ } ++ ++ public void setDataBitsIndex(int chunkSectionIndex, int dataBitsIndex) { ++ dataBitsIndexes[chunkSectionIndex] = dataBitsIndex; ++ } ++ ++ @SuppressWarnings("unchecked") ++ public T[] getPredefinedObjects(int chunkSectionIndex) { ++ return (T[]) predefinedObjects[chunkSectionIndex]; ++ } ++ ++ public void setPredefinedObjects(int chunkSectionIndex, T[] predefinedObjects) { ++ this.predefinedObjects[chunkSectionIndex] = predefinedObjects; ++ } ++ ++ public boolean isWritten(int chunkSectionIndex) { ++ return bitsPerObject[chunkSectionIndex] != 0; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7345f1dc7c5c05f2e1ee09b94f4ebf56dd59bc55 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java +@@ -0,0 +1,30 @@ ++package com.destroystokyo.paper.antixray; ++ ++import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.LevelChunk; ++ ++public final class ChunkPacketInfoAntiXray extends ChunkPacketInfo implements Runnable { ++ ++ private LevelChunk[] nearbyChunks; ++ private final ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray; ++ ++ public ChunkPacketInfoAntiXray(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector, ++ ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray) { ++ super(packetPlayOutMapChunk, chunk, chunkSectionSelector); ++ this.chunkPacketBlockControllerAntiXray = chunkPacketBlockControllerAntiXray; ++ } ++ ++ public LevelChunk[] getNearbyChunks() { ++ return nearbyChunks; ++ } ++ ++ public void setNearbyChunks(LevelChunk... nearbyChunks) { ++ this.nearbyChunks = nearbyChunks; ++ } ++ ++ @Override ++ public void run() { ++ chunkPacketBlockControllerAntiXray.obfuscate(this); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..298ea423084dbcc1b61f991bcd82b8ae51bf0977 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java +@@ -0,0 +1,51 @@ ++package com.destroystokyo.paper.antixray; ++ ++public final class DataBitsReader { ++ ++ private byte[] dataBits; ++ private int bitsPerObject; ++ private int mask; ++ private int longInDataBitsIndex; ++ private int bitInLongIndex; ++ private long current; ++ ++ public void setDataBits(byte[] dataBits) { ++ this.dataBits = dataBits; ++ } ++ ++ public void setBitsPerObject(int bitsPerObject) { ++ this.bitsPerObject = bitsPerObject; ++ mask = (1 << bitsPerObject) - 1; ++ } ++ ++ public void setIndex(int index) { ++ this.longInDataBitsIndex = index; ++ bitInLongIndex = 0; ++ init(); ++ } ++ ++ private void init() { ++ if (dataBits.length > longInDataBitsIndex + 7) { ++ current = ((((long) dataBits[longInDataBitsIndex]) << 56) ++ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) ++ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) ++ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) ++ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) ++ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) ++ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) ++ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); ++ } ++ } ++ ++ public int read() { ++ if (bitInLongIndex + bitsPerObject > 64) { ++ bitInLongIndex = 0; ++ longInDataBitsIndex += 8; ++ init(); ++ } ++ ++ int value = (int) (current >>> bitInLongIndex) & mask; ++ bitInLongIndex += bitsPerObject; ++ return value; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..333763936897befda5bb6c077944d2667f922799 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java +@@ -0,0 +1,79 @@ ++package com.destroystokyo.paper.antixray; ++ ++public final class DataBitsWriter { ++ ++ private byte[] dataBits; ++ private int bitsPerObject; ++ private long mask; ++ private int longInDataBitsIndex; ++ private int bitInLongIndex; ++ private long current; ++ private boolean dirty; ++ ++ public void setDataBits(byte[] dataBits) { ++ this.dataBits = dataBits; ++ } ++ ++ public void setBitsPerObject(int bitsPerObject) { ++ this.bitsPerObject = bitsPerObject; ++ mask = (1 << bitsPerObject) - 1; ++ } ++ ++ public void setIndex(int index) { ++ this.longInDataBitsIndex = index; ++ bitInLongIndex = 0; ++ init(); ++ } ++ ++ private void init() { ++ if (dataBits.length > longInDataBitsIndex + 7) { ++ current = ((((long) dataBits[longInDataBitsIndex]) << 56) ++ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) ++ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) ++ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) ++ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) ++ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) ++ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) ++ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); ++ } ++ ++ dirty = false; ++ } ++ ++ public void finish() { ++ if (dirty && dataBits.length > longInDataBitsIndex + 7) { ++ dataBits[longInDataBitsIndex] = (byte) (current >> 56 & 0xff); ++ dataBits[longInDataBitsIndex + 1] = (byte) (current >> 48 & 0xff); ++ dataBits[longInDataBitsIndex + 2] = (byte) (current >> 40 & 0xff); ++ dataBits[longInDataBitsIndex + 3] = (byte) (current >> 32 & 0xff); ++ dataBits[longInDataBitsIndex + 4] = (byte) (current >> 24 & 0xff); ++ dataBits[longInDataBitsIndex + 5] = (byte) (current >> 16 & 0xff); ++ dataBits[longInDataBitsIndex + 6] = (byte) (current >> 8 & 0xff); ++ dataBits[longInDataBitsIndex + 7] = (byte) (current & 0xff); ++ } ++ } ++ ++ public void write(int value) { ++ if (bitInLongIndex + bitsPerObject > 64) { ++ finish(); ++ bitInLongIndex = 0; ++ longInDataBitsIndex += 8; ++ init(); ++ } ++ ++ current = current & ~(mask << bitInLongIndex) | (value & mask) << bitInLongIndex; ++ dirty = true; ++ bitInLongIndex += bitsPerObject; ++ } ++ ++ public void skip() { ++ bitInLongIndex += bitsPerObject; ++ ++ if (bitInLongIndex > 64) { ++ finish(); ++ bitInLongIndex = bitsPerObject; ++ longInDataBitsIndex += 8; ++ init(); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index b587f774c8f88f2a1c3ea489f7e4fe0bbdeb5a41..10dd582b0fff4df27f1113e41c8ee3e274c6fb65 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -1,5 +1,6 @@ + package net.minecraft.network.protocol.game; + ++import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info + import com.google.common.collect.Lists; + import io.netty.buffer.ByteBuf; + import io.netty.buffer.Unpooled; +@@ -16,6 +17,7 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.SkullBlockEntity; ++import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.chunk.ChunkBiomeContainer; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.chunk.LevelChunkSection; +@@ -33,7 +35,13 @@ public class ClientboundLevelChunkPacket implements Packet blockEntitiesTags; + private boolean fullChunk; + +- public ClientboundLevelChunkPacket() {} ++ // Paper start - Async-Anti-Xray - Set the ready flag to true ++ private volatile boolean ready; // Paper - Async-Anti-Xray - Ready flag for the network manager ++ public ClientboundLevelChunkPacket() { ++ this.ready = true; ++ } ++ // Paper end ++ + // Paper start + private final java.util.List extraPackets = new java.util.ArrayList<>(); + private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); +@@ -43,12 +51,16 @@ public class ClientboundLevelChunkPacket implements Packet chunkPacketInfo = modifyBlocks ? chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i) : null; ++ // Paper end + ChunkPos chunkcoordintpair = chunk.getPos(); + + this.x = chunkcoordintpair.x; + this.z = chunkcoordintpair.z; +- this.fullChunk = includedSectionsMask == 65535; ++ this.fullChunk = i == 65535; + this.heightmaps = new CompoundTag(); + Iterator iterator = chunk.getHeightmaps().iterator(); + +@@ -65,8 +77,13 @@ public class ClientboundLevelChunkPacket implements Packet> 4; + +- if (this.isFullChunk() || (includedSectionsMask & 1 << j) != 0) { ++ if (this.isFullChunk() || (i & 1 << j) != 0) { + // Paper start - improve oversized chunk data packet handling + if (++totalTileEntities > TE_LIMIT) { + ClientboundBlockEntityDataPacket updatePacket = tileentity.getUpdatePacket(); +@@ -93,8 +110,19 @@ public class ClientboundLevelChunkPacket implements Packet chunkPacketInfo) { return this.a(packetDataSerializer, chunk, chunkSectionSelector, chunkPacketInfo); } // OBFHELPER ++ public int a(FriendlyByteBuf packetdataserializer, LevelChunk chunk, int i, ChunkPacketInfo chunkPacketInfo) { ++ // Paper end + int j = 0; + LevelChunkSection[] achunksection = chunk.getSections(); + int k = 0; +@@ -169,9 +201,9 @@ public class ClientboundLevelChunkPacket implements Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER + private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { + if (packets[0] == null) { +- packets[0] = new ClientboundLevelChunkPacket(chunk, 65535); ++ packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass + packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, true); + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index fd7ee4badb383ffb4347d62c00ea2dfa3d76fd12..7a09bc921827958f58290bd3d6f19984bb34a8f6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -204,7 +204,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + // Add env and gen to constructor, WorldData -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { +- super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env); ++ super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor + this.pvpMode = minecraftserver.isPvpAllowed(); + convertable = convertable_conversionsession; + uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile()); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index d97607f2ded4977b253d3afa3bafcbe6d7f98837..af048ab682612233c01f7087d7b8afbf7e58945b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -308,6 +308,8 @@ public class ServerPlayerGameMode { + } + + } ++ ++ this.level.chunkPacketBlockController.onPlayerLeftClickBlock(this, pos, direction); // Paper - Anti-Xray + } + + public void destroyAndAck(BlockPos pos, ServerboundPlayerActionPacket.Action action, String reason) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index eb88d830fb45a6b8c990e8bdc1943d80f63c8b93..1377465e3dc062f34be25cac10aa018776fb22e7 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -2,6 +2,8 @@ package net.minecraft.world.level; + + import co.aikar.timings.Timing; + import co.aikar.timings.Timings; ++import com.destroystokyo.paper.antixray.ChunkPacketBlockController; // Paper - Anti-Xray ++import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray; // Paper - Anti-Xray + import com.destroystokyo.paper.event.server.ServerExceptionEvent; + import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.base.MoreObjects; +@@ -144,6 +146,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + + public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper ++ public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray + + public final co.aikar.timings.WorldTimingsHandler timings; // Paper + public static BlockPos lastPhysicsProblem; // Spigot +@@ -165,9 +168,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return typeKey; + } + +- protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { ++ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot + this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper ++ this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray + this.generator = gen; + this.world = new CraftWorld((ServerLevel) this, gen, env); + this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns(); // CraftBukkit +@@ -433,6 +437,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // CraftBukkit end + + BlockState iblockdata1 = chunk.setType(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag ++ this.chunkPacketBlockController.onBlockChange(this, pos, state, iblockdata1, flags); // Paper - Anti-Xray + + if (iblockdata1 == null) { + // CraftBukkit start - remove blockstate if failed (or the same) +diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +index e369730ac6909ff5343468bd685c9ea2b6b3cfed..2c19d147710a3bbe2e980114161f1cdf81760947 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +@@ -8,6 +8,7 @@ import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Registry; + import net.minecraft.data.worldgen.biome.Biomes; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkPos; +@@ -28,7 +29,7 @@ public class EmptyLevelChunk extends LevelChunk { + }); + + public EmptyLevelChunk(Level world, ChunkPos pos) { +- super(world, pos, new ChunkBiomeContainer(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), EmptyLevelChunk.BIOMES)); ++ super(world, pos, new ChunkBiomeContainer(MinecraftServer.getServer().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), EmptyLevelChunk.BIOMES)); // Paper - world isnt ready yet for anti xray use here, use server singleton for registry + } + + // Paper start +diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +index 17fa8b23d1000ae53f2b4f1a6e8817c1005c1c81..56ab660e29a0dc7d22eeaa41cc8f50e8a96717ef 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +@@ -27,7 +27,7 @@ public class ImposterProtoChunk extends ProtoChunk { + private final LevelChunk wrapped; + + public ImposterProtoChunk(LevelChunk wrapped) { +- super(wrapped.getPos(), UpgradeData.EMPTY); ++ super(wrapped.getPos(), UpgradeData.EMPTY, wrapped.world); // Paper - Anti-Xray - Add parameter + this.wrapped = wrapped; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 419b4bf0549d798d52d73fbbd9de59313fc05eb1..85861545ec4620a6cfd06876dad091637bd29b0b 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -464,7 +464,7 @@ public class LevelChunk implements ChunkAccess { + return null; + } + +- chunksection = new LevelChunkSection(j >> 4 << 4); ++ chunksection = new LevelChunkSection(j >> 4 << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters + this.sections[j >> 4] = chunksection; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index f5db97fb0dac78e1d9aa68d0417aa13f39914f52..38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -1,9 +1,11 @@ + package net.minecraft.world.level.chunk; + + import java.util.function.Predicate; ++import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info + import javax.annotation.Nullable; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.network.FriendlyByteBuf; ++import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; +@@ -18,16 +20,22 @@ public class LevelChunkSection { + private short tickingFluidCount; + final PalettedContainer states; // Paper - package-private + +- public LevelChunkSection(int yOffset) { +- this(yOffset, (short) 0, (short) 0, (short) 0); ++ // Paper start - Anti-Xray - Add parameters ++ @Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public LevelChunkSection(int i, ChunkAccess chunk, Level world, boolean initializeBlocks) { ++ this(i, (short) 0, (short) 0, (short) 0, chunk, world, initializeBlocks); ++ // Paper end + } + +- public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount) { +- this.bottomBlockY = yOffset; +- this.nonEmptyBlockCount = nonEmptyBlockCount; +- this.tickingBlockCount = randomTickableBlockCount; +- this.tickingFluidCount = nonEmptyFluidCount; +- this.states = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); ++ // Paper start - Anti-Xray - Add parameters ++ @Deprecated public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount) { this(yOffset, nonEmptyBlockCount, randomTickableBlockCount, nonEmptyFluidCount, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public LevelChunkSection(int i, short short0, short short1, short short2, ChunkAccess chunk, Level world, boolean initializeBlocks) { ++ // Paper end ++ this.bottomBlockY = i; ++ this.nonEmptyBlockCount = short0; ++ this.tickingBlockCount = short1; ++ this.tickingFluidCount = short2; ++ this.states = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState(), world == null ? null : world.chunkPacketBlockController.getPredefinedBlockData(world, chunk, this, initializeBlocks), initializeBlocks); // Paper - Anti-Xray - Add predefined block data + } + + public final BlockState getBlockState(int x, int y, int z) { // Paper +@@ -139,10 +147,14 @@ public class LevelChunkSection { + return this.states; + } + +- public void writeChunkSection(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER +- public void write(FriendlyByteBuf packetdataserializer) { ++ // Paper start - Anti-Xray - Add chunk packet info ++ @Deprecated public final void writeChunkSection(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere ++ @Deprecated public final void write(FriendlyByteBuf packetdataserializer) { this.writeChunkSection(packetdataserializer, null); } // Notice for updates: Please make sure this method isn't used anywhere ++ public final void writeChunkSection(FriendlyByteBuf packetDataSerializer, ChunkPacketInfo chunkPacketInfo) { this.b(packetDataSerializer, chunkPacketInfo); } // OBFHELPER ++ public void b(FriendlyByteBuf packetdataserializer, ChunkPacketInfo chunkPacketInfo) { ++ // Paper end + packetdataserializer.writeShort(this.nonEmptyBlockCount); +- this.states.write(packetdataserializer); ++ this.states.writeDataPaletteBlock(packetdataserializer, chunkPacketInfo, this.bottomBlockY >> 4); // Paper - Anti-Xray - Add chunk packet info + } + + public int getSerializedSize() { +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index 917b0a64083ebbe24321089b784b91f3af4918b9..dd252372e1e380674b1191e9ea265cbb10de437b 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.chunk; + + import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; ++import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info + import java.util.Arrays; + import java.util.Objects; + import java.util.concurrent.locks.ReentrantLock; +@@ -26,6 +27,7 @@ public class PalettedContainer implements PaletteResize { + private final Function reader; + private final Function writer; + private final T defaultValue; ++ private final T[] predefinedObjects; // Paper - Anti-Xray - Add predefined objects + protected BitStorage storage; public final BitStorage getDataBits() { return this.storage; } // Paper - OBFHELPER + private Palette palette; private Palette getDataPalette() { return this.palette; } // Paper - OBFHELPER + private int bits; private int getBitsPerObject() { return this.bits; } // Paper - OBFHELPER +@@ -50,14 +52,47 @@ public class PalettedContainer implements PaletteResize { + //this.j.unlock(); // Paper - disable this + } + +- public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { +- this.globalPalette = fallbackPalette; +- this.registry = idList; +- this.reader = elementDeserializer; +- this.writer = elementSerializer; +- this.defaultValue = defaultElement; +- this.setBits(4); ++ // Paper start - Anti-Xray - Add predefined objects ++ @Deprecated public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { this(fallbackPalette, idList, elementDeserializer, elementSerializer, defaultElement, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public PalettedContainer(Palette datapalette, IdMapper registryblockid, Function function, Function function1, T t0, T[] predefinedObjects, boolean initialize) { ++ // Paper end ++ this.globalPalette = datapalette; ++ this.registry = registryblockid; ++ this.reader = function; ++ this.writer = function1; ++ this.defaultValue = t0; ++ // Paper start - Anti-Xray - Add predefined objects ++ this.predefinedObjects = predefinedObjects; ++ ++ if (initialize) { ++ if (predefinedObjects == null) { ++ // Default ++ this.initialize(4); ++ } else { ++ // MathHelper.d() is trailingBits(roundCeilPow2(n)), alternatively; (int)ceil(log2(n)); however it's trash, use numberOfLeadingZeros instead ++ // Count the bits of the maximum array index to initialize a data palette with enough space from the beginning ++ // The length of the array is used because air is also added to the data palette from the beginning ++ // Start with at least 4 ++ int maxIndex = predefinedObjects.length >> 4; ++ int bitCount = (32 - Integer.numberOfLeadingZeros(Math.max(16, maxIndex) - 1)); ++ ++ // Initialize with at least 15 free indixes ++ this.initialize((1 << bitCount) - predefinedObjects.length < 16 ? bitCount + 1 : bitCount); ++ this.addPredefinedObjects(); ++ } ++ } ++ // Paper end ++ } ++ ++ // Paper start - Anti-Xray - Add predefined objects ++ private void addPredefinedObjects() { ++ if (this.predefinedObjects != null && this.getDataPalette() != this.getDataPaletteGlobal()) { ++ for (int i = 0; i < this.predefinedObjects.length; i++) { ++ this.getDataPalette().getOrCreateIdFor(this.predefinedObjects[i]); ++ } ++ } + } ++ // Paper end + + private static int getIndex(int x, int y, int z) { + return y << 8 | z << 4 | x; +@@ -92,6 +127,7 @@ public class PalettedContainer implements PaletteResize { + + int j; + ++ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects + for (j = 0; j < databits.getSize(); ++j) { + T t1 = datapalette.valueFor(databits.get(j)); + +@@ -141,24 +177,38 @@ public class PalettedContainer implements PaletteResize { + return t0 == null ? this.defaultValue : t0; + } + +- public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER +- public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize ++ // Paper start - Anti-Xray - Add chunk packet info ++ @Deprecated public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere ++ @Deprecated public void write(FriendlyByteBuf buf) { this.writeDataPaletteBlock(buf, null, 0); } // Notice for updates: Please make sure this method isn't used anywhere ++ public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { this.b(packetDataSerializer, chunkPacketInfo, chunkSectionIndex); } // OBFHELPER ++ public synchronized void b(FriendlyByteBuf packetdataserializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { // Paper - synchronize ++ // Paper end + this.acquire(); +- buf.writeByte(this.bits); +- this.palette.write(buf); +- buf.writeLongArray(this.storage.getRaw()); ++ packetdataserializer.writeByte(this.bits); ++ this.palette.write(packetdataserializer); ++ // Paper start - Anti-Xray - Add chunk packet info ++ if (chunkPacketInfo != null) { ++ chunkPacketInfo.setBitsPerObject(chunkSectionIndex, this.getBitsPerObject()); ++ chunkPacketInfo.setDataPalette(chunkSectionIndex, this.getDataPalette()); ++ chunkPacketInfo.setDataBitsIndex(chunkSectionIndex, packetdataserializer.writerIndex() + FriendlyByteBuf.countBytes(this.getDataBits().getDataBits().length)); ++ chunkPacketInfo.setPredefinedObjects(chunkSectionIndex, this.predefinedObjects); ++ } ++ // Paper end ++ packetdataserializer.writeLongArray(this.storage.getRaw()); + this.release(); + } + + public synchronized void read(ListTag paletteTag, long[] data) { // Paper - synchronize + this.acquire(); +- int i = Math.max(4, Mth.ceillog2(paletteTag.size())); ++ // Paper - Anti-Xray - TODO: Should this.predefinedObjects.length just be added here (faster) or should the contents be compared to calculate the size (less RAM)? ++ int i = Math.max(4, Mth.ceillog2(paletteTag.size() + (this.predefinedObjects == null ? 0 : this.predefinedObjects.length))); // Paper - Anti-Xray - Calculate the size with predefined objects + +- if (i != this.bits) { ++ if (true || i != this.bits) { // Paper - Anti-Xray - Not initialized yet + this.setBits(i); + } + + this.palette.read(paletteTag); ++ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects + int j = data.length * 64 / 4096; + + if (this.palette == this.globalPalette) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index d8b7b210484079c9ca2c34831c84102cba6692f5..87fd585141ad9818fca0b697cb4c87248fe7ce11 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -64,16 +64,24 @@ public class ProtoChunk implements ChunkAccess { + private long inhabitedTime; + private final Map carvingMasks; + private volatile boolean isLightCorrect; ++ private final Level world; // Paper - Anti-Xray - Add world + +- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { +- this(pos, upgradeData, (LevelChunkSection[]) null, new ProtoTickList<>((block) -> { ++ // Paper start - Anti-Xray - Add world ++ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { this(pos, upgradeData, null); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public ProtoChunk(ChunkPos chunkcoordintpair, UpgradeData chunkconverter, Level world) { ++ // Paper end ++ this(chunkcoordintpair, chunkconverter, (LevelChunkSection[]) null, new ProtoTickList<>((block) -> { + return block == null || block.defaultBlockState().isAir(); +- }, pos), new ProtoTickList<>((fluidtype) -> { ++ }, chunkcoordintpair), new ProtoTickList<>((fluidtype) -> { + return fluidtype == null || fluidtype == Fluids.EMPTY; +- }, pos)); ++ }, chunkcoordintpair), world); // Paper - Anti-Xray - Add world + } + +- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] sections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler) { ++ // Paper start - Anti-Xray - Add world ++ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] sections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler) { this(pos, upgradeData, sections, blockTickScheduler, fluidTickScheduler, null); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public ProtoChunk(ChunkPos chunkcoordintpair, UpgradeData chunkconverter, @Nullable LevelChunkSection[] achunksection, ProtoTickList protochunkticklist, ProtoTickList protochunkticklist1, Level world) { ++ this.world = world; ++ // Paper end + this.heightmaps = Maps.newEnumMap(Heightmap.Types.class); + this.status = ChunkStatus.EMPTY; + this.blockEntities = Maps.newHashMap(); +@@ -85,15 +93,15 @@ public class ProtoChunk implements ChunkAccess { + this.structureStarts = Maps.newHashMap(); + this.structuresRefences = Maps.newHashMap(); + this.carvingMasks = new Object2ObjectArrayMap(); +- this.chunkPos = pos; +- this.upgradeData = upgradeData; +- this.blockTicks = blockTickScheduler; +- this.liquidTicks = fluidTickScheduler; +- if (sections != null) { +- if (this.sections.length == sections.length) { +- System.arraycopy(sections, 0, this.sections, 0, this.sections.length); ++ this.chunkPos = chunkcoordintpair; ++ this.upgradeData = chunkconverter; ++ this.blockTicks = protochunkticklist; ++ this.liquidTicks = protochunkticklist1; ++ if (achunksection != null) { ++ if (this.sections.length == achunksection.length) { ++ System.arraycopy(achunksection, 0, this.sections, 0, this.sections.length); + } else { +- ProtoChunk.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", sections.length, this.sections.length); ++ ProtoChunk.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", achunksection.length, this.sections.length); + } + } + +@@ -228,7 +236,7 @@ public class ProtoChunk implements ChunkAccess { + + public LevelChunkSection getOrCreateSection(int y) { + if (this.sections[y] == LevelChunk.EMPTY_SECTION) { +- this.sections[y] = new LevelChunkSection(y << 4); ++ this.sections[y] = new LevelChunkSection(y << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters + } + + return this.sections[y]; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 969130442b529eaac6f708107ff129f89cc0af90..8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -101,7 +101,7 @@ public class ChunkSerializer { + byte b0 = nbttagcompound2.getByte("Y"); + + if (nbttagcompound2.contains("Palette", 9) && nbttagcompound2.contains("BlockStates", 12)) { +- LevelChunkSection chunksection = new LevelChunkSection(b0 << 4); ++ LevelChunkSection chunksection = new LevelChunkSection(b0 << 4, null, world, false); // Paper - Anti-Xray - Add parameters + + chunksection.getStates().read(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); + chunksection.recalcBlockCounts(); +@@ -165,7 +165,7 @@ public class ChunkSerializer { + // CraftBukkit end + }); + } else { +- ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1); ++ ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world); // Paper - Anti-Xray - Add parameter + + protochunk.setBiomes(biomestorage); + object = protochunk; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +index 423594177fe78600755d913f169f28dd1bfa2b37..74bad15034d9d55fb70931f38868f812160c6305 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +@@ -43,7 +43,7 @@ public class CraftChunk implements Chunk { + private final ServerLevel worldServer; + private final int x; + private final int z; +- private static final PalettedContainer emptyBlockIDs = new LevelChunkSection(0).getStates(); ++ private static final PalettedContainer emptyBlockIDs = new LevelChunkSection(0, null, null, true).getStates(); // Paper - Anti-Xray - Add parameters + private static final byte[] emptyLight = new byte[2048]; + + public CraftChunk(net.minecraft.world.level.chunk.LevelChunk chunk) { +@@ -287,7 +287,7 @@ public class CraftChunk implements Chunk { + CompoundTag data = new CompoundTag(); + cs[i].getStates().write(data, "Palette", "BlockStates"); + +- PalettedContainer blockids = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, net.minecraft.world.level.block.Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); // TODO: snapshot whole ChunkSection ++ PalettedContainer blockids = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, net.minecraft.world.level.block.Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState(), null, false); // TODO: snapshot whole ChunkSection // Paper - Anti-Xray - Add no predefined block data and don't initialize because it's done in the line below internally + blockids.read(data.getList("Palette", CraftMagicNumbers.NBT.TAG_COMPOUND), data.getLongArray("BlockStates")); + + sectionBlockIDs[i] = blockids; +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +index a94c65f4d63a06be099fd67b0b7756c5b45b84a0..8d72cd6a44cf462cfe3adac9bf99a16883a587df 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +@@ -21,9 +21,11 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + private final int maxHeight; + private final LevelChunkSection[] sections; + private Set tiles; ++ private World world; // Paper - Anti-Xray - Add world + + public CraftChunkData(World world) { + this(world.getMaxHeight()); ++ this.world = world; // Paper - Anti-Xray - Add world + } + + /* pp for tests */ CraftChunkData(int maxHeight) { +@@ -157,7 +159,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + private LevelChunkSection getChunkSection(int y, boolean create) { + LevelChunkSection section = sections[y >> 4]; + if (create && section == null) { +- sections[y >> 4] = section = new LevelChunkSection(y >> 4 << 4); ++ sections[y >> 4] = section = new LevelChunkSection(y >> 4 << 4, null, world instanceof org.bukkit.craftbukkit.CraftWorld ? ((org.bukkit.craftbukkit.CraftWorld) world).getHandle() : null, true); // Paper - Anti-Xray - Add parameters + } + return section; + } diff --git a/patches/server-remapped/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/patches/server-remapped/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch new file mode 100644 index 0000000000..0d019759ff --- /dev/null +++ b/patches/server-remapped/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Mar 2019 01:01:32 -0400 +Subject: [PATCH] Only count Natural Spawned mobs towards natural spawn mob + limit + +This resolves the super common complaint about mobs not spawning. + +This was ultimately a flaw in the vanilla count algorithim that allows +spawners and other misc mobs to count against the mob limit, which are +not bounded, and can prevent the entire world from spawning new. + +I believe Bukkits changes around persistence may of actually made it +worse than vanilla. + +This should fully solve all of the issues around it so that only natural +influences natural spawns. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index c45493e88bf7e8811be2759ff9ac19e3fe9d938a..384cb363eed794551bee6b0ec11ba1be92a3d7ac 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -464,6 +464,16 @@ public class PaperWorldConfig { + maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); + } + ++ public boolean countAllMobsForSpawning = false; ++ private void countAllMobsForSpawning() { ++ countAllMobsForSpawning = getBoolean("count-all-mobs-for-spawning", false); ++ if (countAllMobsForSpawning) { ++ log("Counting all mobs for spawning. Mob farms may reduce natural spawns elsewhere in world."); ++ } else { ++ log("Using improved mob spawn limits (Only Natural Spawns impact spawn limits for more natural spawns)"); ++ } ++ } ++ + public boolean antiXray; + public EngineMode engineMode; + public int maxChunkSectionIndex; +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index e23875ae07c23fed1161ea070e63bbc3a30168a0..0fb69f9194078e5e05e36ed909eb48424b6465b4 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -79,6 +79,13 @@ public final class NaturalSpawner { + MobCategory enumcreaturetype = entity.getType().getCategory(); + + if (enumcreaturetype != MobCategory.MISC) { ++ // Paper start - Only count natural spawns ++ if (!entity.level.paperConfig.countAllMobsForSpawning && ++ !(entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL || ++ entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { ++ continue; ++ } ++ // Paper end + BlockPos blockposition = entity.blockPosition(); + long j = ChunkPos.asLong(blockposition.getX() >> 4, blockposition.getZ() >> 4); + diff --git a/patches/server-remapped/0364-Configurable-projectile-relative-velocity.patch b/patches/server-remapped/0364-Configurable-projectile-relative-velocity.patch new file mode 100644 index 0000000000..111827bdd8 --- /dev/null +++ b/patches/server-remapped/0364-Configurable-projectile-relative-velocity.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lucavon +Date: Tue, 23 Jul 2019 20:29:20 -0500 +Subject: [PATCH] Configurable projectile relative velocity + +This patch adds an option "disable relative projectile velocity", which, when +nabled, will cause projectiles to ignore the shooter's current velocity, +like they did in Minecraft 1.8 and prior. +If a player is falling, for example, their shooting range will be drastically +reduced, as a downwards velocity is applied to the projectile. This prevents +players from saving themselves from falling off floating islands, for example, +as a thrown ender pearl will not make it back to the island, while it would +have in 1.8. + +While this could easily be done with plugins, too, there are multiple problems: +P1) If multiple plugins cancel the velocity by subtracting the shooter's velocity +from the projectile's velocity, the projectile's velocity would be different. +As there's no way to detect whether the projectile's velocity has already been +adjusted to ignore the player's velocity, plugins can't not do it if it's not +necessary. +P2) I've noticed some inconsistencies, e.g. weird velocity when shooting while +using an elytra. Checking for those inconsistencies is possible, but not as +efficient as just not applying the velocity in the first place. +P3) Solutions for 1) and especially 2) might not be future-proof, while this +server-internal fix makes this change future-proof. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 384cb363eed794551bee6b0ec11ba1be92a3d7ac..1ee2cced100626e48eb36ee14f84b9257c79a2f8 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -507,4 +507,9 @@ public class PaperWorldConfig { + Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); + } + } ++ ++ public boolean disableRelativeProjectileVelocity; ++ private void disableRelativeProjectileVelocity() { ++ disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index d385fb6eee5000951c350b6ced5669dc3dcce725..ca3d936433cd47caa4e0335e41246b1c4ce0eb99 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -129,7 +129,7 @@ public abstract class Projectile extends Entity { + this.shoot((double) f5, (double) f6, (double) f7, modifierZ, modifierXYZ); + Vec3 vec3d = user.getDeltaMovement(); + +- this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, user.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); ++ if (!user.level.paperConfig.disableRelativeProjectileVelocity) this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, user.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); // Paper - allow disabling relative velocity + } + + // CraftBukkit start - call projectile hit event diff --git a/patches/server-remapped/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch b/patches/server-remapped/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch new file mode 100644 index 0000000000..17630cf486 --- /dev/null +++ b/patches/server-remapped/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 28 Jul 2019 00:51:11 +0100 +Subject: [PATCH] Mark entities as being ticked when notifying navigation + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 7a09bc921827958f58290bd3d6f19984bb34a8f6..a811ced17721b70bb51837f47e466c2261db2466 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1469,6 +1469,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + VoxelShape voxelshape1 = newState.getCollisionShape(this, pos); + + if (Shapes.joinIsNotEmpty(voxelshape, voxelshape1, BooleanOp.NOT_SAME)) { ++ boolean wasTicking = this.tickingEntities; this.tickingEntities = true; // Paper + Iterator iterator = this.navigations.iterator(); + + while (iterator.hasNext()) { +@@ -1490,6 +1491,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + } + ++ this.tickingEntities = wasTicking; // Paper + } + } + diff --git a/patches/server-remapped/0366-offset-item-frame-ticking.patch b/patches/server-remapped/0366-offset-item-frame-ticking.patch new file mode 100644 index 0000000000..32966f397f --- /dev/null +++ b/patches/server-remapped/0366-offset-item-frame-ticking.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Tue, 30 Jul 2019 03:17:16 +0500 +Subject: [PATCH] offset item frame ticking + + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java +index e0bf8c6c838b18a0c55b6f3317033e892b631f5c..3277a56bcf3831f8d3c9fa9168c608b369eed7e4 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java +@@ -35,7 +35,7 @@ public abstract class HangingEntity extends Entity { + protected static final Predicate HANGING_ENTITY = (entity) -> { + return entity instanceof HangingEntity; + }; +- private int checkInterval; ++ private int checkInterval; { this.checkInterval = this.getId() % this.level.spigotConfig.hangingTickFrequency; } // Paper + public BlockPos pos; + protected Direction direction; + diff --git a/patches/server-remapped/0367-Avoid-hopper-searches-if-there-are-no-items.patch b/patches/server-remapped/0367-Avoid-hopper-searches-if-there-are-no-items.patch new file mode 100644 index 0000000000..ee50904042 --- /dev/null +++ b/patches/server-remapped/0367-Avoid-hopper-searches-if-there-are-no-items.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: CullanP +Date: Thu, 3 Mar 2016 02:13:38 -0600 +Subject: [PATCH] Avoid hopper searches if there are no items + +Hoppers searching for items and minecarts is the most expensive part of hopper ticking. +We keep track of the number of minecarts and items in a chunk. +If there are no items in the chunk, we skip searching for items. +If there are no minecarts in the chunk, we skip searching for them. + +Usually hoppers aren't near items, so we can skip most item searches. +And since minecart hoppers are used _very_ rarely near we can avoid alot of searching there. + +Combined, this adds up a lot. + +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index d3640975c5a33b4911428760691215905b987385..e7facd849e3511c64b4ae44b34382f4a4985f2a4 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -16,6 +16,7 @@ public final class EntitySelector { + public static final Predicate ENTITY_NOT_BEING_RIDDEN = (entity) -> { + return entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); + }; ++ public static final Predicate isInventory() { return CONTAINER_ENTITY_SELECTOR; } // Paper - OBFHELPER + public static final Predicate CONTAINER_ENTITY_SELECTOR = (entity) -> { + return entity instanceof Container && entity.isAlive(); + }; +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 85861545ec4620a6cfd06876dad091637bd29b0b..4fef3abe4b416cbebe1b456468b5c3e162de18f1 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -31,10 +31,13 @@ import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.Mth; ++import net.minecraft.world.Container; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.ChunkTickList; + import net.minecraft.world.level.EmptyTickList; +@@ -122,6 +125,10 @@ public class LevelChunk implements ChunkAccess { + return removed; + } + } ++ // Track the number of minecarts and items ++ // Keep this synced with entitySlices.add() and entitySlices.remove() ++ private final int[] itemCounts = new int[16]; ++ private final int[] inventoryEntityCounts = new int[16]; + // Paper end + + public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes, UpgradeData upgradeData, TickList blockTickScheduler, TickList fluidTickScheduler, long inhabitedTime, @Nullable LevelChunkSection[] sections, @Nullable Consumer loadToWorldConsumer) { +@@ -581,6 +588,13 @@ public class LevelChunk implements ChunkAccess { + entity.zChunk = this.chunkPos.z; + this.entities.add(entity); // Paper - per chunk entity list + this.entitySlices[k].add(entity); ++ // Paper start ++ if (entity instanceof ItemEntity) { ++ itemCounts[k]++; ++ } else if (entity instanceof Container) { ++ inventoryEntityCounts[k]++; ++ } ++ // Paper end + entity.entitySlice = this.entitySlices[k]; // Paper + this.markUnsaved(); // Paper + } +@@ -614,6 +628,11 @@ public class LevelChunk implements ChunkAccess { + if (!this.entitySlices[section].remove(entity)) { + return; + } ++ if (entity instanceof ItemEntity) { ++ itemCounts[section]--; ++ } else if (entity instanceof Container) { ++ inventoryEntityCounts[section]--; ++ } + entityCounts.decrement(entity.getMinecraftKeyString()); + this.markUnsaved(); // Paper + // Paper end +@@ -899,6 +918,14 @@ public class LevelChunk implements ChunkAccess { + for (int k = i; k <= j; ++k) { + Iterator iterator = this.entitySlices[k].iterator(); // Spigot + ++ // Paper start - Don't search for inventories if we have none, and that is all we want ++ /* ++ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` ++ * ++ * Make sure the inventory selector stays in sync. ++ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` ++ */ ++ if (predicate == EntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; + while (iterator.hasNext()) { + T entity = (T) iterator.next(); // CraftBukkit - decompile error + if (entity.shouldBeRemoved) continue; // Paper +@@ -919,9 +946,29 @@ public class LevelChunk implements ChunkAccess { + i = Mth.clamp(i, 0, this.entitySlices.length - 1); + j = Mth.clamp(j, 0, this.entitySlices.length - 1); + ++ // Paper start ++ int[] counts; ++ if (ItemEntity.class.isAssignableFrom(entityClass)) { ++ counts = itemCounts; ++ } else if (Container.class.isAssignableFrom(entityClass)) { ++ counts = inventoryEntityCounts; ++ } else { ++ counts = null; ++ } ++ // Paper end + for (int k = i; k <= j; ++k) { ++ if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for + Iterator iterator = this.entitySlices[k].iterator(); // Spigot + ++ // Paper start - Don't search for inventories if we have none, and that is all we want ++ /* ++ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` ++ * ++ * Make sure the inventory selector stays in sync. ++ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` ++ */ ++ if (predicate == EntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; ++ // Paper end + while (iterator.hasNext()) { + T t0 = (T) iterator.next(); // CraftBukkit - decompile error + if (t0.shouldBeRemoved) continue; // Paper diff --git a/patches/server-remapped/0368-Asynchronous-chunk-IO-and-loading.patch b/patches/server-remapped/0368-Asynchronous-chunk-IO-and-loading.patch new file mode 100644 index 0000000000..c4fd709325 --- /dev/null +++ b/patches/server-remapped/0368-Asynchronous-chunk-IO-and-loading.patch @@ -0,0 +1,4410 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 13 Jul 2019 09:23:10 -0700 +Subject: [PATCH] Asynchronous chunk IO and loading + +This patch re-adds a file IO thread as well as shoving de-serializing +chunk NBT data onto worker threads. This patch also will shove +chunk data serialization onto the same worker threads when the chunk +is unloaded - this cannot be done for regular saves since that's unsafe. + +The file IO Thread + +Unlike 1.13 and below, the file IO thread is prioritized - IO tasks can +be reoredered, however they are "stuck" to a world & coordinate. + +Scheduling IO tasks works as follows, given a world & coordinate - location: + +The IO thread has been designed to ensure that reads and writes appear to +occur synchronously for a given location, however the implementation also +has the unfortunate side-effect of making every write appear as if +they occur without failure. + +The IO thread has also been designed to accomodate Mojang's decision to +store chunk data and POI data separately. It can independently schedule +tasks for each. + +However threads can wait for writes to complete and check if: + - The write was overwriten by another scheduler + - The write failed (however it does not indicate whether it was overwritten by another scheduler) + +Scheduling reads: + + - If a write task is in progress, the task is not scheduled and returns the in-progress write data + This means that readers cannot modify the NBTTagCompound returned and must clone if it they wish to write + - If a write task is not in progress but a read task is in progress, then the read task is simply chained + This means that again, readers cannot modify the NBTTagCompound returned + +Scheduling writes: + + - If a read task is in progress, ignore the read task and schedule the write + We cannot complete the read task since we assume it wants old data - not current + - If a write task is pending, overwrite the write data + The file IO thread does correctly handle cases where the data is overwritten when it + is writing data (before completing a task it will check if the data was overwritten and + will retry). + +When the file IO thread executes a task for a location, the it will +execute the read task first (if it exists), then it will execute the +write task. This ensures that, even when scheduling at different +priorities, that reads/writes for a location act synchronously. + +The downside of the file IO thread is that write failure can only be +indicated to the scheduling thread if: + +- No other thread decides to schedule another write for the location +concurrently +- The scheduling thread blocks on the write to complete (however the +current implementation can be modified to indicate success +asynchronously) + +The file io thread can be modified easily to provide indications +of write failure and write overwriting if needed. + +The upside of the file IO thread is that if a write failures, then +chunk data is not lost until server restart. This leaves more room +for spurious failure. + +Finally, the io thread will indicate to the console when reads +or writes fail - with relevant detail. + +Asynchronous chunk data serialization for unloading chunks + +When chunks unload they make a call to PlayerChunkMap#saveChunk(IChunkAccess). +Even if I make the IO asynchronous for this call, the data serialization +still hits pretty hard. And given that now the chunk system will +aggressively unload chunks more often (queued immediately at +ticket level 45 or higher), unloads occur more often, and +combined with our changes to the unload queue to make it +significantly more aggresive - chunk unloads can hit pretty hard. +Especially players running around with elytras and fireworks. + +For serializing chunk data off main, there are some tasks which cannot be +done asynchronously. Lighting data must be saved beforehand as well as +potentially some tick lists. These are completed before scheduling the +asynchronous save. + +However serializing chunk data off of the main thread is still risky. +Even though this patch schedules the save to occur after ALL references +of the chunk are removed from the world, plugins can still technically +access entities inside the chunks. For this, if the serialization task +fails for any reason, it will be re-scheduled to be serialized on the +main thread - with the hopes that the reason it failed was due to a plugin +and not an error with the save code itself. Like vanilla code - if the +serialization fails, the chunk data is lost. + +Asynchronous chunk io/loading + +Mojang's current implementation for loading chunk data off disk is +to return a CompletableFuture that will be completed by scheduling a +task to be executed on the world's chunk queue (which is only drained +on the main thread). This task will read the IO off disk and it will +apply data conversions & deserialization synchronously. Obviously +all 3 of these operations are expensive however all can be completed +asynchronously instead. + +The solution this patch uses is as follows: + +0. If an asynchronous chunk save is in progress (see above), wait +for that task to complete. It will use the serialized NBTTagCompound +created by the task. If the task fails to complete, then we would continue +with step 1. If it does not, we skip step 1. (Note: We actually load +POI data no matter what in this case). +1. Schedule an IO task to read chunk & poi data off disk. +2. The IO task will schedule a chunk load task. +3. The chunk load task executes on the async chunk loader threads +and will apply datafixers & de-serialize the chunk into a ProtoChunk +or ProtoChunkExtension. +4. The in progress chunk is then passed on to the world's chunk queue +to complete the ComletableFuture and execute any of the synchronous +tasks required to be executed by the chunk load task (i.e lighting +and some poi tasks). + +diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +index 79ede25e4fe7a648b1d29c49d876482a2158f892..24eac9400fbf971742e89bbf47b0ba52b587c4eb 100644 +--- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java ++++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +@@ -59,6 +59,17 @@ public class WorldTimingsHandler { + + public final Timing miscMobSpawning; + ++ public final Timing poiUnload; ++ public final Timing chunkUnload; ++ public final Timing poiSaveDataSerialization; ++ public final Timing chunkSave; ++ public final Timing chunkSaveOverwriteCheck; ++ public final Timing chunkSaveDataSerialization; ++ public final Timing chunkSaveIOWait; ++ public final Timing chunkUnloadPrepareSave; ++ public final Timing chunkUnloadPOISerialization; ++ public final Timing chunkUnloadDataSave; ++ + public WorldTimingsHandler(Level server) { + String name = ((PrimaryLevelData) server.getLevelData()).getLevelName() + " - "; + +@@ -112,6 +123,17 @@ public class WorldTimingsHandler { + + + miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); ++ ++ poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); ++ chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); ++ poiSaveDataSerialization = Timings.ofSafe(name + "Chunk save - POI Data serialization"); ++ chunkSave = Timings.ofSafe(name + "Chunk save - Chunk"); ++ chunkSaveOverwriteCheck = Timings.ofSafe(name + "Chunk save - Chunk Overwrite Check"); ++ chunkSaveDataSerialization = Timings.ofSafe(name + "Chunk save - Chunk Data serialization"); ++ chunkSaveIOWait = Timings.ofSafe(name + "Chunk save - Chunk IO Wait"); ++ chunkUnloadPrepareSave = Timings.ofSafe(name + "Chunk unload - Async Save Prepare"); ++ chunkUnloadPOISerialization = Timings.ofSafe(name + "Chunk unload - POI Data Serialization"); ++ chunkUnloadDataSave = Timings.ofSafe(name + "Chunk unload - Data Serialization"); + } + + public static Timing getTickList(ServerLevel worldserver, String timingsType) { +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 53dd6c18de8e80378852bbb141016d9574d42162..62711d95db62221a2e4e6423c518afe13a6c7dbe 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -1,5 +1,6 @@ + package com.destroystokyo.paper; + ++import com.destroystokyo.paper.io.chunk.ChunkTaskManager; + import com.google.common.base.Functions; + import com.google.common.base.Joiner; + import com.google.common.collect.ImmutableSet; +@@ -43,7 +44,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); + + public PaperCommand(String name) { + super(name); +@@ -155,6 +156,9 @@ public class PaperCommand extends Command { + case "debug": + doDebug(sender, args); + break; ++ case "dumpwaiting": ++ ChunkTaskManager.dumpAllChunkLoadInfo(); ++ break; + case "chunkinfo": + doChunkInfo(sender, args); + break; +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 469f78775b03cf363d88e35c69c0dc185c22547c..8bf4d2b8c38c02d6a5b2fea37113689a252f1571 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -1,5 +1,6 @@ + package com.destroystokyo.paper; + ++import com.destroystokyo.paper.io.chunk.ChunkTaskManager; + import com.google.common.base.Strings; + import com.google.common.base.Throwables; + +@@ -352,4 +353,54 @@ public class PaperConfig { + maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); + maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); + } ++ ++ public static boolean asyncChunks = false; ++ private static void asyncChunks() { ++ ConfigurationSection section; ++ if (version < 15) { ++ section = config.createSection("settings.async-chunks"); ++ section.set("threads", -1); ++ } else { ++ section = config.getConfigurationSection("settings.async-chunks"); ++ if (section == null) { ++ section = config.createSection("settings.async-chunks"); ++ } ++ } ++ // Clean up old configs ++ if (section.contains("load-threads")) { ++ if (!section.contains("threads")) { ++ section.set("threads", section.get("load-threads")); ++ } ++ section.set("load-threads", null); ++ } ++ section.set("generation", null); ++ section.set("enabled", null); ++ section.set("thread-per-world-generation", null); ++ ++ int threads = getInt("settings.async-chunks.threads", -1); ++ int cpus = Runtime.getRuntime().availableProcessors(); ++ if (threads <= 0) { ++ threads = (int) Math.min(Integer.getInteger("paper.maxChunkThreads", 8), Math.max(1, cpus - 1)); ++ } ++ if (cpus == 1 && !Boolean.getBoolean("Paper.allowAsyncChunksSingleCore")) { ++ asyncChunks = false; ++ } else { ++ asyncChunks = true; ++ } ++ ++ // Let Shared Host set some limits ++ String sharedHostThreads = System.getenv("PAPER_ASYNC_CHUNKS_SHARED_HOST_THREADS"); ++ if (sharedHostThreads != null) { ++ try { ++ threads = Math.max(1, Math.min(threads, Integer.parseInt(sharedHostThreads))); ++ } catch (NumberFormatException ignored) {} ++ } ++ ++ if (!asyncChunks) { ++ log("Async Chunks: Disabled - Chunks will be managed synchronously, and will cause tremendous lag."); ++ } else { ++ ChunkTaskManager.initGlobalLoadThreads(threads); ++ log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/io/IOUtil.java b/src/main/java/com/destroystokyo/paper/io/IOUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5af0ac3d9e87c06053e65433060f15779c156c2a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/IOUtil.java +@@ -0,0 +1,62 @@ ++package com.destroystokyo.paper.io; ++ ++import org.bukkit.Bukkit; ++ ++public final class IOUtil { ++ ++ /* Copied from concrete or concurrentutil */ ++ ++ public static long getCoordinateKey(final int x, final int z) { ++ return ((long)z << 32) | (x & 0xFFFFFFFFL); ++ } ++ ++ public static int getCoordinateX(final long key) { ++ return (int)key; ++ } ++ ++ public static int getCoordinateZ(final long key) { ++ return (int)(key >>> 32); ++ } ++ ++ public static int getRegionCoordinate(final int chunkCoordinate) { ++ return chunkCoordinate >> 5; ++ } ++ ++ public static int getChunkInRegion(final int chunkCoordinate) { ++ return chunkCoordinate & 31; ++ } ++ ++ public static String genericToString(final Object object) { ++ return object == null ? "null" : object.getClass().getName() + ":" + object.toString(); ++ } ++ ++ public static T notNull(final T obj) { ++ if (obj == null) { ++ throw new NullPointerException(); ++ } ++ return obj; ++ } ++ ++ public static T notNull(final T obj, final String msgIfNull) { ++ if (obj == null) { ++ throw new NullPointerException(msgIfNull); ++ } ++ return obj; ++ } ++ ++ public static void arrayBounds(final int off, final int len, final int arrayLength, final String msgPrefix) { ++ if (off < 0 || len < 0 || (arrayLength - off) < len) { ++ throw new ArrayIndexOutOfBoundsException(msgPrefix + ": off: " + off + ", len: " + len + ", array length: " + arrayLength); ++ } ++ } ++ ++ public static int getPriorityForCurrentThread() { ++ return Bukkit.isPrimaryThread() ? PrioritizedTaskQueue.HIGHEST_PRIORITY : PrioritizedTaskQueue.NORMAL_PRIORITY; ++ } ++ ++ @SuppressWarnings("unchecked") ++ public static void rethrow(final Throwable throwable) throws T { ++ throw (T)throwable; ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a630a84b60b4517e3bc330d4983b914bd064efa4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java +@@ -0,0 +1,606 @@ ++package com.destroystokyo.paper.io; ++ ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.chunk.storage.RegionFile; ++import org.apache.logging.log4j.Logger; ++ ++import java.io.IOException; ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.atomic.AtomicLong; ++import java.util.function.Consumer; ++import java.util.function.Function; ++ ++/** ++ * Prioritized singleton thread responsible for all chunk IO that occurs in a minecraft server. ++ * ++ *

    ++ * Singleton access: {@link Holder#INSTANCE} ++ *

    ++ * ++ *

    ++ * All functions provided are MT-Safe, however certain ordering constraints are (but not enforced): ++ *

  • ++ * Chunk saves may not occur for unloaded chunks. ++ *
  • ++ *
  • ++ * Tasks must be scheduled on the main thread. ++ *
  • ++ *

    ++ * ++ * @see Holder#INSTANCE ++ * @see #scheduleSave(ServerLevel, int, int, CompoundTag, CompoundTag, int) ++ * @see #loadChunkDataAsync(ServerLevel, int, int, int, Consumer, boolean, boolean, boolean) ++ */ ++public final class PaperFileIOThread extends QueueExecutorThread { ++ ++ public static final Logger LOGGER = MinecraftServer.LOGGER; ++ public static final CompoundTag FAILURE_VALUE = new CompoundTag(); ++ ++ public static final class Holder { ++ ++ public static final PaperFileIOThread INSTANCE = new PaperFileIOThread(); ++ ++ static { ++ INSTANCE.start(); ++ } ++ } ++ ++ private final AtomicLong writeCounter = new AtomicLong(); ++ ++ private PaperFileIOThread() { ++ super(new PrioritizedTaskQueue<>(), (int)(1.0e6)); // 1.0ms spinwait time ++ this.setName("Paper RegionFile IO Thread"); ++ this.setPriority(Thread.NORM_PRIORITY - 1); // we keep priority close to normal because threads can wait on us ++ this.setUncaughtExceptionHandler((final Thread unused, final Throwable thr) -> { ++ LOGGER.fatal("Uncaught exception thrown from IO thread, report this!", thr); ++ }); ++ } ++ ++ /* run() is implemented by superclass */ ++ ++ /* ++ * ++ * IO thread will perform reads before writes ++ * ++ * How reads/writes are scheduled: ++ * ++ * If read in progress while scheduling write, ignore read and schedule write ++ * If read in progress while scheduling read (no write in progress), chain the read task ++ * ++ * ++ * If write in progress while scheduling read, use the pending write data and ret immediately ++ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data ++ * ++ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however ++ * it fails to properly propagate write failures. When writes fail the data is kept so future reads will actually ++ * read the failed write data. This should hopefully act as a way to prevent data loss for spurious fails for writing data. ++ * ++ */ ++ ++ /** ++ * Attempts to bump the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. ++ * @param world Chunk's world ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority level to try to bump to ++ */ ++ public void bumpPriority(final ServerLevel world, final int chunkX, final int chunkZ, final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority: " + priority); ++ } ++ ++ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); ++ ++ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); ++ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); ++ ++ if (poiTask != null) { ++ poiTask.raisePriority(priority); ++ } ++ if (chunkTask != null) { ++ chunkTask.raisePriority(priority); ++ } ++ } ++ ++ public CompoundTag getPendingWrite(final ServerLevel world, final int chunkX, final int chunkZ, final boolean poiData) { ++ final ChunkDataController taskController = poiData ? world.poiDataController : world.chunkDataController; ++ ++ final ChunkDataTask dataTask = taskController.tasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); ++ ++ if (dataTask == null) { ++ return null; ++ } ++ ++ final ChunkDataController.InProgressWrite write = dataTask.inProgressWrite; ++ ++ if (write == null) { ++ return null; ++ } ++ ++ return write.data; ++ } ++ ++ /** ++ * Sets the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. ++ * @param world Chunk's world ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority level to set to ++ */ ++ public void setPriority(final ServerLevel world, final int chunkX, final int chunkZ, final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority: " + priority); ++ } ++ ++ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); ++ ++ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); ++ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); ++ ++ if (poiTask != null) { ++ poiTask.updatePriority(priority); ++ } ++ if (chunkTask != null) { ++ chunkTask.updatePriority(priority); ++ } ++ } ++ ++ /** ++ * Schedules the chunk data to be written asynchronously. ++ *

    ++ * Impl notes: ++ *

    ++ *
  • ++ * This function presumes a chunk load for the coordinates is not called during this function (anytime after is OK). This means ++ * saves must be scheduled before a chunk is unloaded. ++ *
  • ++ *
  • ++ * Writes may be called concurrently, although only the "later" write will go through. ++ *
  • ++ * @param world Chunk's world ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param poiData Chunk point of interest data. If {@code null}, then no poi data is saved. ++ * @param chunkData Chunk data. If {@code null}, then no chunk data is saved. ++ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} ++ * @throws IllegalArgumentException If both {@code poiData} and {@code chunkData} are {@code null}. ++ * @throws IllegalStateException If the file io thread has shutdown. ++ */ ++ public void scheduleSave(final ServerLevel world, final int chunkX, final int chunkZ, ++ final CompoundTag poiData, final CompoundTag chunkData, ++ final int priority) throws IllegalArgumentException { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority: " + priority); ++ } ++ ++ final long writeCounter = this.writeCounter.getAndIncrement(); ++ ++ if (poiData != null) { ++ this.scheduleWrite(world.poiDataController, world, chunkX, chunkZ, poiData, priority, writeCounter); ++ } ++ if (chunkData != null) { ++ this.scheduleWrite(world.chunkDataController, world, chunkX, chunkZ, chunkData, priority, writeCounter); ++ } ++ } ++ ++ private void scheduleWrite(final ChunkDataController dataController, final ServerLevel world, ++ final int chunkX, final int chunkZ, final CompoundTag data, final int priority, final long writeCounter) { ++ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask taskRunning) -> { ++ if (taskRunning == null) { ++ // no task is scheduled ++ ++ // create task ++ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); ++ newTask.inProgressWrite = new ChunkDataController.InProgressWrite(); ++ newTask.inProgressWrite.writeCounter = writeCounter; ++ newTask.inProgressWrite.data = data; ++ ++ PaperFileIOThread.this.queueTask(newTask); // schedule ++ return newTask; ++ } ++ ++ taskRunning.raisePriority(priority); ++ ++ if (taskRunning.inProgressWrite == null) { ++ taskRunning.inProgressWrite = new ChunkDataController.InProgressWrite(); ++ } ++ ++ boolean reschedule = taskRunning.inProgressWrite.writeCounter == -1L; ++ ++ // synchronize for readers ++ //noinspection SynchronizationOnLocalVariableOrMethodParameter ++ synchronized (taskRunning) { ++ taskRunning.inProgressWrite.data = data; ++ taskRunning.inProgressWrite.writeCounter = writeCounter; ++ } ++ ++ if (reschedule) { ++ // We need to reschedule this task since the previous one is not currently scheduled since it failed ++ taskRunning.reschedule(priority); ++ } ++ ++ return taskRunning; ++ }); ++ } ++ ++ /** ++ * Same as {@link #loadChunkDataAsync(ServerLevel, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns ++ * a {@link CompletableFuture} which is potentially completed ASYNCHRONOUSLY ON THE FILE IO THREAD when the load task ++ * has completed. ++ *

    ++ * Note that if the chunk fails to load the returned future is completed with {@code null}. ++ *

    ++ */ ++ public CompletableFuture loadChunkDataAsyncFuture(final ServerLevel world, final int chunkX, final int chunkZ, ++ final int priority, final boolean readPoiData, final boolean readChunkData, ++ final boolean intendingToBlock) { ++ final CompletableFuture future = new CompletableFuture<>(); ++ this.loadChunkDataAsync(world, chunkX, chunkZ, priority, future::complete, readPoiData, readChunkData, intendingToBlock); ++ return future; ++ } ++ ++ /** ++ * Schedules a load to be executed asynchronously. ++ *

    ++ * Impl notes: ++ *

    ++ *
  • ++ * If a chunk fails to load, the {@code onComplete} parameter is completed with {@code null}. ++ *
  • ++ *
  • ++ * It is possible for the {@code onComplete} parameter to be given {@link ChunkData} containing data ++ * this call did not request. ++ *
  • ++ *
  • ++ * The {@code onComplete} parameter may be completed during the execution of this function synchronously or it may ++ * be completed asynchronously on this file io thread. Interacting with the file IO thread in the completion of ++ * data is undefined behaviour, and can cause deadlock. ++ *
  • ++ * @param world Chunk's world ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} ++ * @param onComplete Consumer to execute once this task has completed ++ * @param readPoiData Whether to read point of interest data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. ++ * @param readChunkData Whether to read chunk data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. ++ * @return The {@link PrioritizedTaskQueue.PrioritizedTask} associated with this task. Note that this task does not support ++ * cancellation. ++ */ ++ public void loadChunkDataAsync(final ServerLevel world, final int chunkX, final int chunkZ, ++ final int priority, final Consumer onComplete, ++ final boolean readPoiData, final boolean readChunkData, ++ final boolean intendingToBlock) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority: " + priority); ++ } ++ ++ if (!(readPoiData | readChunkData)) { ++ throw new IllegalArgumentException("Must read chunk data or poi data"); ++ } ++ ++ final ChunkData complete = new ChunkData(); ++ final boolean[] requireCompletion = new boolean[] { readPoiData, readChunkData }; ++ ++ if (readPoiData) { ++ this.scheduleRead(world.poiDataController, world, chunkX, chunkZ, (final CompoundTag poiData) -> { ++ complete.poiData = poiData; ++ ++ final boolean finished; ++ ++ // avoid a race condition where the file io thread completes and we complete synchronously ++ // Note: Synchronization can be elided if both of the accesses are volatile ++ synchronized (requireCompletion) { ++ requireCompletion[0] = false; // 0 -> poi data ++ finished = !requireCompletion[1]; // 1 -> chunk data ++ } ++ ++ if (finished) { ++ onComplete.accept(complete); ++ } ++ }, priority, intendingToBlock); ++ } ++ ++ if (readChunkData) { ++ this.scheduleRead(world.chunkDataController, world, chunkX, chunkZ, (final CompoundTag chunkData) -> { ++ complete.chunkData = chunkData; ++ ++ final boolean finished; ++ ++ // avoid a race condition where the file io thread completes and we complete synchronously ++ // Note: Synchronization can be elided if both of the accesses are volatile ++ synchronized (requireCompletion) { ++ requireCompletion[1] = false; // 1 -> chunk data ++ finished = !requireCompletion[0]; // 0 -> poi data ++ } ++ ++ if (finished) { ++ onComplete.accept(complete); ++ } ++ }, priority, intendingToBlock); ++ } ++ ++ } ++ ++ // Note: the onComplete may be called asynchronously or synchronously here. ++ private void scheduleRead(final ChunkDataController dataController, final ServerLevel world, ++ final int chunkX, final int chunkZ, final Consumer onComplete, final int priority, ++ final boolean intendingToBlock) { ++ ++ Function tryLoadFunction = (final RegionFile file) -> { ++ if (file == null) { ++ return Boolean.TRUE; ++ } ++ return Boolean.valueOf(file.hasChunk(new ChunkPos(chunkX, chunkZ))); ++ }; ++ ++ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask running) -> { ++ if (running == null) { ++ // not scheduled ++ ++ final Boolean shouldSchedule = intendingToBlock ? dataController.computeForRegionFile(chunkX, chunkZ, tryLoadFunction) : ++ dataController.computeForRegionFileIfLoaded(chunkX, chunkZ, tryLoadFunction); ++ ++ if (shouldSchedule == Boolean.FALSE) { ++ // not on disk ++ onComplete.accept(null); ++ return null; ++ } ++ ++ // set up task ++ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); ++ newTask.inProgressRead = new ChunkDataController.InProgressRead(); ++ newTask.inProgressRead.readFuture.thenAccept(onComplete); ++ ++ PaperFileIOThread.this.queueTask(newTask); // schedule task ++ return newTask; ++ } ++ ++ running.raisePriority(priority); ++ ++ if (running.inProgressWrite == null) { ++ // chain to the read future ++ running.inProgressRead.readFuture.thenAccept(onComplete); ++ return running; ++ } ++ ++ // at this stage we have to use the in progress write's data to avoid an order issue ++ // we don't synchronize since all writes to data occur in the compute() call ++ onComplete.accept(running.inProgressWrite.data); ++ return running; ++ }); ++ } ++ ++ /** ++ * Same as {@link #loadChunkDataAsync(ServerLevel, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns ++ * the {@link ChunkData} associated with the specified chunk when the task is complete. ++ * @return The chunk data, or {@code null} if the chunk failed to load. ++ */ ++ public ChunkData loadChunkData(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, ++ final boolean readPoiData, final boolean readChunkData) { ++ return this.loadChunkDataAsyncFuture(world, chunkX, chunkZ, priority, readPoiData, readChunkData, true).join(); ++ } ++ ++ /** ++ * Schedules the given task at the specified priority to be executed on the IO thread. ++ *

    ++ * Internal api. Do not use. ++ *

    ++ */ ++ public void runTask(final int priority, final Runnable runnable) { ++ this.queueTask(new GeneralTask(priority, runnable)); ++ } ++ ++ static final class GeneralTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { ++ ++ private final Runnable run; ++ ++ public GeneralTask(final int priority, final Runnable run) { ++ super(priority); ++ this.run = IOUtil.notNull(run, "Task may not be null"); ++ } ++ ++ @Override ++ public void run() { ++ try { ++ this.run.run(); ++ } catch (final Throwable throwable) { ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath)throwable; ++ } ++ LOGGER.fatal("Failed to execute general task on IO thread " + IOUtil.genericToString(this.run), throwable); ++ } ++ } ++ } ++ ++ public static final class ChunkData { ++ ++ public CompoundTag poiData; ++ public CompoundTag chunkData; ++ ++ public ChunkData() {} ++ ++ public ChunkData(final CompoundTag poiData, final CompoundTag chunkData) { ++ this.poiData = poiData; ++ this.chunkData = chunkData; ++ } ++ } ++ ++ public static abstract class ChunkDataController { ++ ++ // ConcurrentHashMap synchronizes per chain, so reduce the chance of task's hashes colliding. ++ public final ConcurrentHashMap tasks = new ConcurrentHashMap<>(64, 0.5f); ++ ++ public abstract void writeData(final int x, final int z, final CompoundTag compound) throws IOException; ++ public abstract CompoundTag readData(final int x, final int z) throws IOException; ++ ++ public abstract T computeForRegionFile(final int chunkX, final int chunkZ, final Function function); ++ public abstract T computeForRegionFileIfLoaded(final int chunkX, final int chunkZ, final Function function); ++ ++ public static final class InProgressWrite { ++ public long writeCounter; ++ public CompoundTag data; ++ } ++ ++ public static final class InProgressRead { ++ public final CompletableFuture readFuture = new CompletableFuture<>(); ++ } ++ } ++ ++ public static final class ChunkDataTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { ++ ++ public ChunkDataController.InProgressWrite inProgressWrite; ++ public ChunkDataController.InProgressRead inProgressRead; ++ ++ private final ServerLevel world; ++ private final int x; ++ private final int z; ++ private final ChunkDataController taskController; ++ ++ public ChunkDataTask(final int priority, final ServerLevel world, final int x, final int z, final ChunkDataController taskController) { ++ super(priority); ++ this.world = world; ++ this.x = x; ++ this.z = z; ++ this.taskController = taskController; ++ } ++ ++ @Override ++ public String toString() { ++ return "Task for world: '" + this.world.getWorld().getName() + "' at " + this.x + "," + this.z + ++ " poi: " + (this.taskController == this.world.poiDataController) + ", hash: " + this.hashCode(); ++ } ++ ++ /* ++ * ++ * IO thread will perform reads before writes ++ * ++ * How reads/writes are scheduled: ++ * ++ * If read in progress while scheduling write, ignore read and schedule write ++ * If read in progress while scheduling read (no write in progress), chain the read task ++ * ++ * ++ * If write in progress while scheduling read, use the pending write data and ret immediately ++ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data ++ * ++ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however ++ * it fails to properly propagate write failures ++ * ++ */ ++ ++ void reschedule(final int priority) { ++ // priority is checked before this stage // TODO what ++ this.queue.lazySet(null); ++ this.priority.lazySet(priority); ++ PaperFileIOThread.Holder.INSTANCE.queueTask(this); ++ } ++ ++ @Override ++ public void run() { ++ ChunkDataController.InProgressRead read = this.inProgressRead; ++ if (read != null) { ++ CompoundTag compound = PaperFileIOThread.FAILURE_VALUE; ++ try { ++ compound = this.taskController.readData(this.x, this.z); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ LOGGER.fatal("Failed to read chunk data for task: " + this.toString(), thr); ++ // fall through to complete with null data ++ } ++ read.readFuture.complete(compound); ++ } ++ ++ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(this.x, this.z)); ++ ++ ChunkDataController.InProgressWrite write = this.inProgressWrite; ++ ++ if (write == null) { ++ // IntelliJ warns this is invalid, however it does not consider that writes to the task map & the inProgress field can occur concurrently. ++ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { ++ if (valueInMap == null) { ++ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); ++ } ++ if (valueInMap != ChunkDataTask.this) { ++ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); ++ } ++ return valueInMap.inProgressWrite == null ? null : valueInMap; ++ }); ++ ++ if (inMap == null) { ++ return; // set the task value to null, indicating we're done ++ } ++ ++ // not null, which means there was a concurrent write ++ write = this.inProgressWrite; ++ } ++ ++ // check if another process is writing ++ /*try { TODO: Can we restore this? ++ ((WorldServer)this.world).checkSession(); ++ } catch (final Exception ex) { ++ LOGGER.fatal("Couldn't save chunk; already in use by another instance of Minecraft?", ex); ++ // we don't need to set the write counter to -1 as we know at this stage there's no point in re-scheduling ++ // writes since they'll fail anyways. ++ return; ++ } ++*/ ++ for (;;) { ++ final long writeCounter; ++ final CompoundTag data; ++ ++ //noinspection SynchronizationOnLocalVariableOrMethodParameter ++ synchronized (write) { ++ writeCounter = write.writeCounter; ++ data = write.data; ++ } ++ ++ boolean failedWrite = false; ++ ++ try { ++ this.taskController.writeData(this.x, this.z, data); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ LOGGER.fatal("Failed to write chunk data for task: " + this.toString(), thr); ++ failedWrite = true; ++ } ++ ++ boolean finalFailWrite = failedWrite; ++ ++ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { ++ if (valueInMap == null) { ++ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); ++ } ++ if (valueInMap != ChunkDataTask.this) { ++ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); ++ } ++ if (valueInMap.inProgressWrite.writeCounter == writeCounter) { ++ if (finalFailWrite) { ++ valueInMap.inProgressWrite.writeCounter = -1L; ++ } ++ ++ return null; ++ } ++ return valueInMap; ++ // Hack end ++ }); ++ ++ if (inMap == null) { ++ // write counter matched, so we wrote the most up-to-date pending data, we're done here ++ // or we failed to write and successfully set the write counter to -1 ++ return; // we're done here ++ } ++ ++ // fetch & write new data ++ continue; ++ } ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java +new file mode 100644 +index 0000000000000000000000000000000000000000..97f2e433c483f1ebd7500ae142269e144ef5fda4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java +@@ -0,0 +1,277 @@ ++package com.destroystokyo.paper.io; ++ ++import java.util.concurrent.ConcurrentLinkedQueue; ++import java.util.concurrent.atomic.AtomicBoolean; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.concurrent.atomic.AtomicReference; ++ ++public class PrioritizedTaskQueue { ++ ++ // lower numbers are a higher priority (except < 0) ++ // higher priorities are always executed before lower priorities ++ ++ /** ++ * Priority value indicating the task has completed or is being completed. ++ */ ++ public static final int COMPLETING_PRIORITY = -1; ++ ++ /** ++ * Highest priority, should only be used for main thread tasks or tasks that are blocking the main thread. ++ */ ++ public static final int HIGHEST_PRIORITY = 0; ++ ++ /** ++ * Should be only used in an IO task so that chunk loads do not wait on other IO tasks. ++ * This only exists because IO tasks are scheduled before chunk load tasks to decrease IO waiting times. ++ */ ++ public static final int HIGHER_PRIORITY = 1; ++ ++ /** ++ * Should be used for scheduling chunk loads/generation that would increase response times to users. ++ */ ++ public static final int HIGH_PRIORITY = 2; ++ ++ /** ++ * Default priority. ++ */ ++ public static final int NORMAL_PRIORITY = 3; ++ ++ /** ++ * Use for tasks not at all critical and can potentially be delayed. ++ */ ++ public static final int LOW_PRIORITY = 4; ++ ++ /** ++ * Use for tasks that should "eventually" execute. ++ */ ++ public static final int LOWEST_PRIORITY = 5; ++ ++ private static final int TOTAL_PRIORITIES = 6; ++ ++ final ConcurrentLinkedQueue[] queues = (ConcurrentLinkedQueue[])new ConcurrentLinkedQueue[TOTAL_PRIORITIES]; ++ ++ private final AtomicBoolean shutdown = new AtomicBoolean(); ++ ++ { ++ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { ++ this.queues[i] = new ConcurrentLinkedQueue<>(); ++ } ++ } ++ ++ /** ++ * Returns whether the specified priority is valid ++ */ ++ public static boolean validPriority(final int priority) { ++ return priority >= 0 && priority < TOTAL_PRIORITIES; ++ } ++ ++ /** ++ * Queues a task. ++ * @throws IllegalStateException If the task has already been queued. Use {@link PrioritizedTask#raisePriority(int)} to ++ * raise a task's priority. ++ * This can also be thrown if the queue has shutdown. ++ */ ++ public void add(final T task) throws IllegalStateException { ++ int priority = task.getPriority(); ++ if (priority != COMPLETING_PRIORITY) { ++ task.setQueue(this); ++ this.queues[priority].add(task); ++ } ++ if (this.shutdown.get()) { ++ // note: we're not actually sure at this point if our task will go through ++ throw new IllegalStateException("Queue has shutdown, refusing to execute task " + IOUtil.genericToString(task)); ++ } ++ } ++ ++ /** ++ * Polls the highest priority task currently available. {@code null} if none. ++ */ ++ public T poll() { ++ T task; ++ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { ++ final ConcurrentLinkedQueue queue = this.queues[i]; ++ ++ while ((task = queue.poll()) != null) { ++ final int prevPriority = task.tryComplete(i); ++ if (prevPriority != COMPLETING_PRIORITY && prevPriority <= i) { ++ // if the prev priority was greater-than or equal to our current priority ++ return task; ++ } ++ } ++ } ++ ++ return null; ++ } ++ ++ /** ++ * Returns whether this queue may have tasks queued. ++ *

    ++ * This operation is not atomic, but is MT-Safe. ++ *

    ++ * @return {@code true} if tasks may be queued, {@code false} otherwise ++ */ ++ public boolean hasTasks() { ++ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { ++ final ConcurrentLinkedQueue queue = this.queues[i]; ++ ++ if (queue.peek() != null) { ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ /** ++ * Prevent further additions to this queue. Attempts to add after this call has completed (potentially during) will ++ * result in {@link IllegalStateException} being thrown. ++ *

    ++ * This operation is atomic with respect to other shutdown calls ++ *

    ++ *

    ++ * After this call has completed, regardless of return value, this queue will be shutdown. ++ *

    ++ * @return {@code true} if the queue was shutdown, {@code false} if it has shut down already ++ */ ++ public boolean shutdown() { ++ return this.shutdown.getAndSet(false); ++ } ++ ++ public abstract static class PrioritizedTask { ++ ++ protected final AtomicReference queue = new AtomicReference<>(); ++ ++ protected final AtomicInteger priority; ++ ++ protected PrioritizedTask() { ++ this(PrioritizedTaskQueue.NORMAL_PRIORITY); ++ } ++ ++ protected PrioritizedTask(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority " + priority); ++ } ++ this.priority = new AtomicInteger(priority); ++ } ++ ++ /** ++ * Returns the current priority. Note that {@link PrioritizedTaskQueue#COMPLETING_PRIORITY} will be returned ++ * if this task is completing or has completed. ++ */ ++ public final int getPriority() { ++ return this.priority.get(); ++ } ++ ++ /** ++ * Returns whether this task is scheduled to execute, or has been already executed. ++ */ ++ public boolean isScheduled() { ++ return this.queue.get() != null; ++ } ++ ++ final int tryComplete(final int minPriority) { ++ for (int curr = this.getPriorityVolatile();;) { ++ if (curr == COMPLETING_PRIORITY) { ++ return COMPLETING_PRIORITY; ++ } ++ if (curr > minPriority) { ++ // curr is lower priority ++ return curr; ++ } ++ ++ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, COMPLETING_PRIORITY))) { ++ return curr; ++ } ++ continue; ++ } ++ } ++ ++ /** ++ * Forces this task to be completed. ++ * @return {@code true} if the task was cancelled, {@code false} if the task has already completed or is being completed. ++ */ ++ public boolean cancel() { ++ return this.exchangePriorityVolatile(PrioritizedTaskQueue.COMPLETING_PRIORITY) != PrioritizedTaskQueue.COMPLETING_PRIORITY; ++ } ++ ++ /** ++ * Attempts to raise the priority to the priority level specified. ++ * @param priority Priority specified ++ * @return {@code true} if successful, {@code false} otherwise. ++ */ ++ public boolean raisePriority(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority"); ++ } ++ ++ for (int curr = this.getPriorityVolatile();;) { ++ if (curr == COMPLETING_PRIORITY) { ++ return false; ++ } ++ if (priority >= curr) { ++ return true; ++ } ++ ++ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { ++ PrioritizedTaskQueue queue = this.queue.get(); ++ if (queue != null) { ++ //noinspection unchecked ++ queue.queues[priority].add(this); // silently fail on shutdown ++ } ++ return true; ++ } ++ continue; ++ } ++ } ++ ++ /** ++ * Attempts to set this task's priority level to the level specified. ++ * @param priority Specified priority level. ++ * @return {@code true} if successful, {@code false} if this task is completing or has completed. ++ */ ++ public boolean updatePriority(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority"); ++ } ++ ++ for (int curr = this.getPriorityVolatile();;) { ++ if (curr == COMPLETING_PRIORITY) { ++ return false; ++ } ++ if (curr == priority) { ++ return true; ++ } ++ ++ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { ++ PrioritizedTaskQueue queue = this.queue.get(); ++ if (queue != null) { ++ //noinspection unchecked ++ queue.queues[priority].add(this); // silently fail on shutdown ++ } ++ return true; ++ } ++ continue; ++ } ++ } ++ ++ void setQueue(final PrioritizedTaskQueue queue) { ++ this.queue.set(queue); ++ } ++ ++ /* priority */ ++ ++ protected final int getPriorityVolatile() { ++ return this.priority.get(); ++ } ++ ++ protected final int compareAndExchangePriorityVolatile(final int expect, final int update) { ++ if (this.priority.compareAndSet(expect, update)) { ++ return expect; ++ } ++ return this.priority.get(); ++ } ++ ++ protected final int exchangePriorityVolatile(final int value) { ++ return this.priority.getAndSet(value); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ee906b594b306906c170180a29a8b61997d05168 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java +@@ -0,0 +1,241 @@ ++package com.destroystokyo.paper.io; ++ ++import net.minecraft.server.MinecraftServer; ++import org.apache.logging.log4j.Logger; ++ ++import java.util.concurrent.ConcurrentLinkedQueue; ++import java.util.concurrent.atomic.AtomicBoolean; ++import java.util.concurrent.locks.LockSupport; ++ ++public class QueueExecutorThread extends Thread { ++ ++ private static final Logger LOGGER = MinecraftServer.LOGGER; ++ ++ protected final PrioritizedTaskQueue queue; ++ protected final long spinWaitTime; ++ ++ protected volatile boolean closed; ++ ++ protected final AtomicBoolean parked = new AtomicBoolean(); ++ ++ protected volatile ConcurrentLinkedQueue flushQueue = new ConcurrentLinkedQueue<>(); ++ protected volatile long flushCycles; ++ ++ public QueueExecutorThread(final PrioritizedTaskQueue queue) { ++ this(queue, (int)(1.e6)); // 1.0ms ++ } ++ ++ public QueueExecutorThread(final PrioritizedTaskQueue queue, final long spinWaitTime) { // in ms ++ this.queue = queue; ++ this.spinWaitTime = spinWaitTime; ++ } ++ ++ @Override ++ public void run() { ++ final long spinWaitTime = this.spinWaitTime; ++ main_loop: ++ for (;;) { ++ this.pollTasks(true); ++ ++ // spinwait ++ ++ final long start = System.nanoTime(); ++ ++ for (;;) { ++ // If we are interrpted for any reason, park() will always return immediately. Clear so that we don't needlessly use cpu in such an event. ++ Thread.interrupted(); ++ LockSupport.parkNanos("Spinwaiting on tasks", 1000L); // 1us ++ ++ if (this.pollTasks(true)) { ++ // restart loop, found tasks ++ continue main_loop; ++ } ++ ++ if (this.handleClose()) { ++ return; // we're done ++ } ++ ++ if ((System.nanoTime() - start) >= spinWaitTime) { ++ break; ++ } ++ } ++ ++ if (this.handleClose()) { ++ return; ++ } ++ ++ this.parked.set(true); ++ ++ // We need to parse here to avoid a race condition where a thread queues a task before we set parked to true ++ // (i.e it will not notify us) ++ if (this.pollTasks(true)) { ++ this.parked.set(false); ++ continue; ++ } ++ ++ if (this.handleClose()) { ++ return; ++ } ++ ++ // we don't need to check parked before sleeping, but we do need to check parked in a do-while loop ++ // LockSupport.park() can fail for any reason ++ do { ++ Thread.interrupted(); ++ LockSupport.park("Waiting on tasks"); ++ } while (this.parked.get()); ++ } ++ } ++ ++ protected boolean handleClose() { ++ if (this.closed) { ++ this.pollTasks(true); // this ensures we've emptied the queue ++ this.handleFlushThreads(true); ++ return true; ++ } ++ return false; ++ } ++ ++ protected boolean pollTasks(boolean flushTasks) { ++ Runnable task; ++ boolean ret = false; ++ ++ while ((task = this.queue.poll()) != null) { ++ ret = true; ++ try { ++ task.run(); ++ } catch (final Throwable throwable) { ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath)throwable; ++ } ++ LOGGER.fatal("Exception thrown from prioritized runnable task in thread '" + this.getName() + "': " + IOUtil.genericToString(task), throwable); ++ } ++ } ++ ++ if (flushTasks) { ++ this.handleFlushThreads(false); ++ } ++ ++ return ret; ++ } ++ ++ protected void handleFlushThreads(final boolean shutdown) { ++ Thread parking; ++ ConcurrentLinkedQueue flushQueue = this.flushQueue; ++ do { ++ ++flushCycles; // may be plain read opaque write ++ while ((parking = flushQueue.poll()) != null) { ++ LockSupport.unpark(parking); ++ } ++ } while (this.pollTasks(false)); ++ ++ if (shutdown) { ++ this.flushQueue = null; ++ ++ // defend against a race condition where a flush thread double-checks right before we set to null ++ while ((parking = flushQueue.poll()) != null) { ++ LockSupport.unpark(parking); ++ } ++ } ++ } ++ ++ /** ++ * Notify's this thread that a task has been added to its queue ++ * @return {@code true} if this thread was waiting for tasks, {@code false} if it is executing tasks ++ */ ++ public boolean notifyTasks() { ++ if (this.parked.get() && this.parked.getAndSet(false)) { ++ LockSupport.unpark(this); ++ return true; ++ } ++ return false; ++ } ++ ++ protected void queueTask(final T task) { ++ this.queue.add(task); ++ this.notifyTasks(); ++ } ++ ++ /** ++ * Waits until this thread's queue is empty. ++ * ++ * @throws IllegalStateException If the current thread is {@code this} thread. ++ */ ++ public void flush() { ++ final Thread currentThread = Thread.currentThread(); ++ ++ if (currentThread == this) { ++ // avoid deadlock ++ throw new IllegalStateException("Cannot flush the queue executor thread while on the queue executor thread"); ++ } ++ ++ // order is important ++ ++ int successes = 0; ++ long lastCycle = -1L; ++ ++ do { ++ final ConcurrentLinkedQueue flushQueue = this.flushQueue; ++ if (flushQueue == null) { ++ return; ++ } ++ ++ flushQueue.add(currentThread); ++ ++ // double check flush queue ++ if (this.flushQueue == null) { ++ return; ++ } ++ ++ final long currentCycle = this.flushCycles; // may be opaque read ++ ++ if (currentCycle == lastCycle) { ++ Thread.yield(); ++ continue; ++ } ++ ++ // force response ++ this.parked.set(false); ++ LockSupport.unpark(this); ++ ++ LockSupport.park("flushing queue executor thread"); ++ ++ // returns whether there are tasks queued, does not return whether there are tasks executing ++ // this is why we cycle twice twice through flush (we know a pollTask call is made after a flush cycle) ++ // we really only need to guarantee that the tasks this thread has queued has gone through, and can leave ++ // tasks queued concurrently that are unsychronized with this thread as undefined behavior ++ if (this.queue.hasTasks()) { ++ successes = 0; ++ } else { ++ ++successes; ++ } ++ ++ } while (successes != 2); ++ ++ } ++ ++ /** ++ * Closes this queue executor's queue and optionally waits for it to empty. ++ *

    ++ * If wait is {@code true}, then the queue will be empty by the time this call completes. ++ *

    ++ *

    ++ * This function is MT-Safe. ++ *

    ++ * @param wait If this call is to wait until the queue is empty ++ * @param killQueue Whether to shutdown this thread's queue ++ * @return whether this thread shut down the queue ++ */ ++ public boolean close(final boolean wait, final boolean killQueue) { ++ boolean ret = !killQueue ? false : this.queue.shutdown(); ++ this.closed = true; ++ ++ // force thread to respond to the shutdown ++ this.parked.set(false); ++ LockSupport.unpark(this); ++ ++ if (wait) { ++ this.flush(); ++ } ++ return ret; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java +new file mode 100644 +index 0000000000000000000000000000000000000000..26a5da48c87674f320aa9f7382217cde2c93e08c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java +@@ -0,0 +1,145 @@ ++package com.destroystokyo.paper.io.chunk; ++ ++import co.aikar.timings.Timing; ++import com.destroystokyo.paper.io.PaperFileIOThread; ++import com.destroystokyo.paper.io.IOUtil; ++import java.util.ArrayDeque; ++import java.util.function.Consumer; ++import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.chunk.storage.ChunkSerializer; ++ ++public final class ChunkLoadTask extends ChunkTask { ++ ++ public boolean cancelled; ++ ++ Consumer onComplete; ++ public PaperFileIOThread.ChunkData chunkData; ++ ++ private boolean hasCompleted; ++ ++ public ChunkLoadTask(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, ++ final ChunkTaskManager taskManager, ++ final Consumer onComplete) { ++ super(world, chunkX, chunkZ, priority, taskManager); ++ this.onComplete = onComplete; ++ } ++ ++ private static final ArrayDeque EMPTY_QUEUE = new ArrayDeque<>(); ++ ++ private static ChunkSerializer.InProgressChunkHolder createEmptyHolder() { ++ return new ChunkSerializer.InProgressChunkHolder(null, EMPTY_QUEUE); ++ } ++ ++ @Override ++ public void run() { ++ try { ++ this.executeTask(); ++ } catch (final Throwable ex) { ++ PaperFileIOThread.LOGGER.error("Failed to execute chunk load task: " + this.toString(), ex); ++ if (!this.hasCompleted) { ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ } ++ } ++ } ++ ++ private boolean checkCancelled() { ++ if (this.cancelled) { ++ // IntelliJ does not understand writes may occur to cancelled concurrently. ++ return this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap != ChunkLoadTask.this) { ++ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); ++ } ++ ++ if (valueInMap.cancelled) { ++ return null; ++ } ++ return valueInMap; ++ }) == null; ++ } ++ return false; ++ } ++ ++ public void executeTask() { ++ if (this.checkCancelled()) { ++ return; ++ } ++ ++ // either executed synchronously or asynchronously ++ final PaperFileIOThread.ChunkData chunkData = this.chunkData; ++ ++ if (chunkData.poiData == PaperFileIOThread.FAILURE_VALUE || chunkData.chunkData == PaperFileIOThread.FAILURE_VALUE) { ++ PaperFileIOThread.LOGGER.error("Could not load chunk for task: " + this.toString() + ", file IO thread has dumped the relevant exception above"); ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ return; ++ } ++ ++ if (chunkData.chunkData == null) { ++ // not on disk ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ return; ++ } ++ ++ final ChunkPos chunkPos = new ChunkPos(this.chunkX, this.chunkZ); ++ ++ final ChunkMap chunkManager = this.world.getChunkSource().chunkMap; ++ ++ try (Timing ignored = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { ++ final ChunkSerializer.InProgressChunkHolder chunkHolder; ++ ++ // apply fixes ++ ++ try { ++ chunkData.chunkData = chunkManager.getChunkData(this.world.getTypeKey(), ++ chunkManager.getWorldPersistentDataSupplier(), chunkData.chunkData, chunkPos, this.world); // clone data for safety, file IO thread does not clone ++ } catch (final Throwable ex) { ++ PaperFileIOThread.LOGGER.error("Could not apply datafixers for chunk task: " + this.toString(), ex); ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ } ++ ++ if (this.checkCancelled()) { ++ return; ++ } ++ ++ try { ++ this.world.getChunkSource().chunkMap.updateChunkStatusOnDisk(chunkPos, chunkData.chunkData); ++ } catch (final Throwable ex) { ++ PaperFileIOThread.LOGGER.warn("Failed to update chunk status cache for task: " + this.toString(), ex); ++ // non-fatal, continue ++ } ++ ++ try { ++ chunkHolder = ChunkSerializer.loadChunk(this.world, ++ chunkManager.structureManager, chunkManager.getVillagePlace(), chunkPos, ++ chunkData.chunkData, true); ++ } catch (final Throwable ex) { ++ PaperFileIOThread.LOGGER.error("Could not de-serialize chunk data for task: " + this.toString(), ex); ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ return; ++ } ++ ++ this.complete(chunkHolder); ++ } ++ } ++ ++ private void complete(final ChunkSerializer.InProgressChunkHolder holder) { ++ this.hasCompleted = true; ++ holder.poiData = this.chunkData == null ? null : this.chunkData.poiData; ++ ++ this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap != ChunkLoadTask.this) { ++ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); ++ } ++ if (valueInMap.cancelled) { ++ return null; ++ } ++ try { ++ ChunkLoadTask.this.onComplete.accept(holder); ++ } catch (final Throwable thr) { ++ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); ++ } ++ return null; ++ }); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java +new file mode 100644 +index 0000000000000000000000000000000000000000..69ebbfa171385c46a84d1a0d241d168a8c2af145 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java +@@ -0,0 +1,111 @@ ++package com.destroystokyo.paper.io.chunk; ++ ++import co.aikar.timings.Timing; ++import com.destroystokyo.paper.io.PaperFileIOThread; ++import com.destroystokyo.paper.io.IOUtil; ++import com.destroystokyo.paper.io.PrioritizedTaskQueue; ++ ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.atomic.AtomicInteger; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.storage.ChunkSerializer; ++ ++public final class ChunkSaveTask extends ChunkTask { ++ ++ public final ChunkSerializer.AsyncSaveData asyncSaveData; ++ public final ChunkAccess chunk; ++ public final CompletableFuture onComplete = new CompletableFuture<>(); ++ ++ private final AtomicInteger attemptedPriority; ++ ++ public ChunkSaveTask(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, ++ final ChunkTaskManager taskManager, final ChunkSerializer.AsyncSaveData asyncSaveData, ++ final ChunkAccess chunk) { ++ super(world, chunkX, chunkZ, priority, taskManager); ++ this.chunk = chunk; ++ this.asyncSaveData = asyncSaveData; ++ this.attemptedPriority = new AtomicInteger(priority); ++ } ++ ++ @Override ++ public void run() { ++ // can be executed asynchronously or synchronously ++ final CompoundTag compound; ++ ++ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTimingIfSync()) { ++ compound = ChunkSerializer.saveChunk(this.world, this.chunk, this.asyncSaveData); ++ } catch (final Throwable ex) { ++ // has a plugin modified something it should not have and made us CME? ++ PaperFileIOThread.LOGGER.error("Failed to serialize unloading chunk data for task: " + this.toString() + ", falling back to a synchronous execution", ex); ++ ++ // Note: We add to the server thread queue here since this is what the server will drain tasks from ++ // when waiting for chunks ++ ChunkTaskManager.queueChunkWaitTask(() -> { ++ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTiming()) { ++ CompoundTag data = PaperFileIOThread.FAILURE_VALUE; ++ ++ try { ++ data = ChunkSerializer.saveChunk(this.world, this.chunk, this.asyncSaveData); ++ PaperFileIOThread.LOGGER.info("Successfully serialized chunk data for task: " + this.toString() + " synchronously"); ++ } catch (final Throwable ex1) { ++ PaperFileIOThread.LOGGER.fatal("Failed to synchronously serialize unloading chunk data for task: " + this.toString() + "! Chunk data will be lost", ex1); ++ } ++ ++ ChunkSaveTask.this.complete(data); ++ } ++ }); ++ ++ return; // the main thread will now complete the data ++ } ++ ++ this.complete(compound); ++ } ++ ++ @Override ++ public boolean raisePriority(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalStateException("Invalid priority: " + priority); ++ } ++ ++ // we know priority is valid here ++ for (int curr = this.attemptedPriority.get();;) { ++ if (curr <= priority) { ++ break; // curr is higher/same priority ++ } ++ if (this.attemptedPriority.compareAndSet(curr, priority)) { ++ break; ++ } ++ curr = this.attemptedPriority.get(); ++ } ++ ++ return super.raisePriority(priority); ++ } ++ ++ @Override ++ public boolean updatePriority(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalStateException("Invalid priority: " + priority); ++ } ++ this.attemptedPriority.set(priority); ++ return super.updatePriority(priority); ++ } ++ ++ private void complete(final CompoundTag compound) { ++ try { ++ this.onComplete.complete(compound); ++ } catch (final Throwable thr) { ++ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); ++ } ++ if (compound != PaperFileIOThread.FAILURE_VALUE) { ++ PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, this.chunkX, this.chunkZ, null, compound, this.attemptedPriority.get()); ++ } ++ this.taskManager.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { ++ if (valueInMap != ChunkSaveTask.this) { ++ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", this: " + ChunkSaveTask.this); ++ } ++ return null; ++ }); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java +new file mode 100644 +index 0000000000000000000000000000000000000000..058fb5a41565e6ce2acbd1f4d071a1b8be449f5d +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java +@@ -0,0 +1,40 @@ ++package com.destroystokyo.paper.io.chunk; ++ ++import com.destroystokyo.paper.io.PaperFileIOThread; ++import com.destroystokyo.paper.io.PrioritizedTaskQueue; ++import net.minecraft.server.level.ServerLevel; ++ ++abstract class ChunkTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { ++ ++ public final ServerLevel world; ++ public final int chunkX; ++ public final int chunkZ; ++ public final ChunkTaskManager taskManager; ++ ++ public ChunkTask(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, ++ final ChunkTaskManager taskManager) { ++ super(priority); ++ this.world = world; ++ this.chunkX = chunkX; ++ this.chunkZ = chunkZ; ++ this.taskManager = taskManager; ++ } ++ ++ @Override ++ public String toString() { ++ return "Chunk task: class:" + this.getClass().getName() + ", for world '" + this.world.getWorld().getName() + ++ "', (" + this.chunkX + "," + this.chunkZ + "), hashcode:" + this.hashCode() + ", priority: " + this.getPriority(); ++ } ++ ++ @Override ++ public boolean raisePriority(final int priority) { ++ PaperFileIOThread.Holder.INSTANCE.bumpPriority(this.world, this.chunkX, this.chunkZ, priority); ++ return super.raisePriority(priority); ++ } ++ ++ @Override ++ public boolean updatePriority(final int priority) { ++ PaperFileIOThread.Holder.INSTANCE.setPriority(this.world, this.chunkX, this.chunkZ, priority); ++ return super.updatePriority(priority); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..499aff1f1e1ffc01ba8f9de43ca17899525a306f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +@@ -0,0 +1,513 @@ ++package com.destroystokyo.paper.io.chunk; ++ ++import com.destroystokyo.paper.io.PaperFileIOThread; ++import com.destroystokyo.paper.io.IOUtil; ++import com.destroystokyo.paper.io.PrioritizedTaskQueue; ++import com.destroystokyo.paper.io.QueueExecutorThread; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.util.thread.BlockableEventLoop; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.chunk.storage.ChunkSerializer; ++import org.apache.commons.lang.StringUtils; ++import org.apache.logging.log4j.Level; ++import org.bukkit.Bukkit; ++import org.spigotmc.AsyncCatcher; ++ ++import java.util.ArrayDeque; ++import java.util.HashSet; ++import java.util.Set; ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.ConcurrentLinkedQueue; ++import java.util.function.Consumer; ++ ++public final class ChunkTaskManager { ++ ++ private final QueueExecutorThread[] workers; ++ private final ServerLevel world; ++ ++ private final PrioritizedTaskQueue queue; ++ private final boolean perWorldQueue; ++ ++ final ConcurrentHashMap chunkLoadTasks = new ConcurrentHashMap<>(64, 0.5f); ++ final ConcurrentHashMap chunkSaveTasks = new ConcurrentHashMap<>(64, 0.5f); ++ ++ private final PrioritizedTaskQueue chunkTasks = new PrioritizedTaskQueue<>(); // used if async chunks are disabled in config ++ ++ protected static QueueExecutorThread[] globalWorkers; ++ protected static QueueExecutorThread globalUrgentWorker; ++ protected static PrioritizedTaskQueue globalQueue; ++ protected static PrioritizedTaskQueue globalUrgentQueue; ++ ++ protected static final ConcurrentLinkedQueue CHUNK_WAIT_QUEUE = new ConcurrentLinkedQueue<>(); ++ ++ public static final ArrayDeque WAITING_CHUNKS = new ArrayDeque<>(); // stack ++ ++ private static final class ChunkInfo { ++ ++ public final int chunkX; ++ public final int chunkZ; ++ public final ServerLevel world; ++ ++ public ChunkInfo(final int chunkX, final int chunkZ, final ServerLevel world) { ++ this.chunkX = chunkX; ++ this.chunkZ = chunkZ; ++ this.world = world; ++ } ++ ++ @Override ++ public String toString() { ++ return "[( " + this.chunkX + "," + this.chunkZ + ") in '" + this.world.getWorld().getName() + "']"; ++ } ++ } ++ ++ public static void pushChunkWait(final ServerLevel world, final int chunkX, final int chunkZ) { ++ synchronized (WAITING_CHUNKS) { ++ WAITING_CHUNKS.push(new ChunkInfo(chunkX, chunkZ, world)); ++ } ++ } ++ ++ public static void popChunkWait() { ++ synchronized (WAITING_CHUNKS) { ++ WAITING_CHUNKS.pop(); ++ } ++ } ++ ++ private static ChunkInfo[] getChunkInfos() { ++ ChunkInfo[] chunks; ++ synchronized (WAITING_CHUNKS) { ++ chunks = WAITING_CHUNKS.toArray(new ChunkInfo[0]); ++ } ++ return chunks; ++ } ++ ++ public static void dumpAllChunkLoadInfo() { ++ ChunkInfo[] chunks = getChunkInfos(); ++ if (chunks.length > 0) { ++ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk wait task info below: "); ++ ++ for (final ChunkInfo chunkInfo : chunks) { ++ final long key = IOUtil.getCoordinateKey(chunkInfo.chunkX, chunkInfo.chunkZ); ++ final ChunkLoadTask loadTask = chunkInfo.world.asyncChunkTaskManager.chunkLoadTasks.get(key); ++ final ChunkSaveTask saveTask = chunkInfo.world.asyncChunkTaskManager.chunkSaveTasks.get(key); ++ ++ PaperFileIOThread.LOGGER.log(Level.ERROR, chunkInfo.chunkX + "," + chunkInfo.chunkZ + " in '" + chunkInfo.world.getWorld().getName() + ":"); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, "Load Task - " + (loadTask == null ? "none" : loadTask.toString())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, "Save Task - " + (saveTask == null ? "none" : saveTask.toString())); ++ // log current status of chunk to indicate whether we're waiting on generation or loading ++ ChunkHolder chunkHolder = chunkInfo.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(key); ++ ++ dumpChunkInfo(new HashSet<>(), chunkHolder, chunkInfo.chunkX, chunkInfo.chunkZ); ++ } ++ } ++ } ++ ++ static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z) { ++ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); ++ } ++ ++ static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z, int indent, int maxDepth) { ++ if (seenChunks.contains(chunkHolder)) { ++ return; ++ } ++ if (indent > maxDepth) { ++ return; ++ } ++ seenChunks.add(chunkHolder); ++ String indentStr = StringUtils.repeat(" ", indent); ++ if (chunkHolder == null) { ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - null for (" + x +"," + z +")"); ++ } else { ++ ChunkAccess chunk = chunkHolder.getAvailableChunkNow(); ++ ChunkStatus holderStatus = chunkHolder.getChunkHolderStatus(); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - non-null"); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); ++ } ++ } ++ ++ public static void initGlobalLoadThreads(int threads) { ++ if (threads <= 0 || globalWorkers != null) { ++ return; ++ } ++ ++ globalWorkers = new QueueExecutorThread[threads]; ++ globalQueue = new PrioritizedTaskQueue<>(); ++ globalUrgentQueue = new PrioritizedTaskQueue<>(); ++ ++ for (int i = 0; i < threads; ++i) { ++ globalWorkers[i] = new QueueExecutorThread<>(globalQueue, (long)0.10e6); //0.1ms ++ globalWorkers[i].setName("Paper Async Chunk Task Thread #" + i); ++ globalWorkers[i].setPriority(Thread.NORM_PRIORITY - 1); ++ globalWorkers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { ++ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); ++ }); ++ ++ globalWorkers[i].start(); ++ } ++ ++ globalUrgentWorker = new QueueExecutorThread<>(globalUrgentQueue, (long)0.10e6); //0.1ms ++ globalUrgentWorker.setName("Paper Async Chunk Urgent Task Thread"); ++ globalUrgentWorker.setPriority(Thread.NORM_PRIORITY+1); ++ globalUrgentWorker.setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { ++ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); ++ }); ++ ++ globalUrgentWorker.start(); ++ } ++ ++ /** ++ * Creates this chunk task manager to operate off the specified number of threads. If the specified number of threads is ++ * less-than or equal to 0, then this chunk task manager will operate off of the world's chunk task queue. ++ * @param world Specified world. ++ * @param threads Specified number of threads. ++ * @see ServerChunkCache#mainThreadProcessor ++ */ ++ public ChunkTaskManager(final ServerLevel world, final int threads) { ++ this.world = world; ++ this.workers = threads <= 0 ? null : new QueueExecutorThread[threads]; ++ this.queue = new PrioritizedTaskQueue<>(); ++ this.perWorldQueue = true; ++ ++ for (int i = 0; i < threads; ++i) { ++ this.workers[i] = new QueueExecutorThread<>(this.queue, (long)0.10e6); //0.1ms ++ this.workers[i].setName("Async chunk loader thread #" + i + " for world: " + world.getWorld().getName()); ++ this.workers[i].setPriority(Thread.NORM_PRIORITY - 1); ++ this.workers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { ++ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); ++ }); ++ ++ this.workers[i].start(); ++ } ++ } ++ ++ /** ++ * Creates the chunk task manager to work from the global workers. When {@link #close(boolean)} is invoked, ++ * the global queue is not shutdown. If the global workers is configured to be disabled or use 0 threads, then ++ * this chunk task manager will operate off of the world's chunk task queue. ++ * @param world The world that this task manager is responsible for ++ * @see ServerChunkCache#mainThreadProcessor ++ */ ++ public ChunkTaskManager(final ServerLevel world) { ++ this.world = world; ++ this.workers = globalWorkers; ++ this.queue = globalQueue; ++ this.perWorldQueue = false; ++ } ++ ++ public boolean pollNextChunkTask() { ++ final ChunkTask task = this.chunkTasks.poll(); ++ ++ if (task != null) { ++ task.run(); ++ return true; ++ } ++ return false; ++ } ++ ++ /** ++ * Polls and runs the next available chunk wait queue task. This is to be used when the server is waiting on a chunk queue. ++ * (per-world can cause issues if all the worker threads are blocked waiting for a response from the main thread) ++ */ ++ public static boolean pollChunkWaitQueue() { ++ final Runnable run = CHUNK_WAIT_QUEUE.poll(); ++ if (run != null) { ++ run.run(); ++ return true; ++ } ++ return false; ++ } ++ ++ /** ++ * Queues a chunk wait task. Note that this will execute out of order with respect to tasks scheduled on a world's ++ * chunk task queue, since this is the global chunk wait queue. ++ */ ++ public static void queueChunkWaitTask(final Runnable runnable) { ++ CHUNK_WAIT_QUEUE.add(runnable); ++ } ++ ++ private static void drainChunkWaitQueue() { ++ Runnable run; ++ while ((run = CHUNK_WAIT_QUEUE.poll()) != null) { ++ run.run(); ++ } ++ } ++ ++ /** ++ * The exact same as {@link #scheduleChunkLoad(int, int, int, Consumer, boolean)}, except that the chunk data is provided as ++ * the {@code data} parameter. ++ */ ++ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, ++ final Consumer onComplete, ++ final boolean intendingToBlock, final CompletableFuture dataFuture) { ++ final ServerLevel world = this.world; ++ ++ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap != null) { ++ if (!valueInMap.cancelled) { ++ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); ++ } ++ valueInMap.cancelled = false; ++ valueInMap.onComplete = onComplete; ++ return valueInMap; ++ } ++ ++ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); ++ ++ dataFuture.thenAccept((final CompoundTag data) -> { ++ final boolean failed = data == PaperFileIOThread.FAILURE_VALUE; ++ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { ++ ret.chunkData = chunkData; ++ if (!failed) { ++ chunkData.chunkData = data; ++ } ++ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here ++ }, true, failed, intendingToBlock); // read data off disk if the future fails ++ }); ++ ++ return ret; ++ }); ++ } ++ ++ public void cancelChunkLoad(final int chunkX, final int chunkZ) { ++ this.chunkLoadTasks.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap == null) { ++ return null; ++ } ++ ++ if (valueInMap.cancelled) { ++ PaperFileIOThread.LOGGER.warn("Task " + valueInMap.toString() + " is already cancelled!"); ++ } ++ valueInMap.cancelled = true; ++ if (valueInMap.cancel()) { ++ return null; ++ } ++ ++ return valueInMap; ++ }); ++ } ++ ++ /** ++ * Schedules an asynchronous chunk load for the specified coordinates. The onComplete parameter may be invoked asynchronously ++ * on a worker thread or on the world's chunk executor queue. As such the code that is executed for the parameter should be ++ * carefully chosen. ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority for this task ++ * @param onComplete The consumer to invoke with the {@link ChunkSerializer.InProgressChunkHolder} object once this task is complete ++ * @param intendingToBlock Whether the caller is intending to block on this task completing (this is a performance tune, and has no adverse side-effects) ++ * @return The {@link ChunkLoadTask} associated with ++ */ ++ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, ++ final Consumer onComplete, ++ final boolean intendingToBlock) { ++ final ServerLevel world = this.world; ++ ++ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap != null) { ++ if (!valueInMap.cancelled) { ++ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); ++ } ++ valueInMap.cancelled = false; ++ valueInMap.onComplete = onComplete; ++ return valueInMap; ++ } ++ ++ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); ++ ++ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { ++ ret.chunkData = chunkData; ++ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here ++ }, true, true, intendingToBlock); ++ ++ return ret; ++ }); ++ } ++ ++ /** ++ * Schedules an async save for the specified chunk. The chunk, at the beginning of this call, must be completely unloaded ++ * from the world. ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority for this task ++ * @param asyncSaveData Async save data. See {@link ChunkSerializer#getAsyncSaveData(ServerLevel, ChunkAccess)} ++ * @param chunk Chunk to save ++ * @return The {@link ChunkSaveTask} associated with the save task. ++ */ ++ public ChunkSaveTask scheduleChunkSave(final int chunkX, final int chunkZ, final int priority, ++ final ChunkSerializer.AsyncSaveData asyncSaveData, ++ final ChunkAccess chunk) { ++ AsyncCatcher.catchOp("chunk save schedule"); ++ ++ final ServerLevel world = this.world; ++ ++ return this.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { ++ if (valueInMap != null) { ++ throw new IllegalStateException("Double scheduling chunk save for task: " + valueInMap.toString()); ++ } ++ ++ final ChunkSaveTask ret = new ChunkSaveTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, asyncSaveData, chunk); ++ ++ ChunkTaskManager.this.internalSchedule(ret); ++ ++ return ret; ++ }); ++ } ++ ++ /** ++ * Returns a completable future which will be completed with the un-copied chunk data for an in progress async save. ++ * Returns {@code null} if no save is in progress. ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ */ ++ public CompletableFuture getChunkSaveFuture(final int chunkX, final int chunkZ) { ++ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); ++ if (chunkSaveTask == null) { ++ return null; ++ } ++ return chunkSaveTask.onComplete; ++ } ++ ++ /** ++ * Returns the chunk object being used to serialize data async for an unloaded chunk. Note that modifying this chunk ++ * is not safe to do as another thread is handling its save. The chunk is also not loaded into the world. ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @return Chunk object for an in-progress async save, or {@code null} if no save is in progress ++ */ ++ public ChunkAccess getChunkInSaveProgress(final int chunkX, final int chunkZ) { ++ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); ++ if (chunkSaveTask == null) { ++ return null; ++ } ++ return chunkSaveTask.chunk; ++ } ++ ++ public void flush() { ++ // flush here since we schedule tasks on the IO thread that can schedule tasks here ++ drainChunkWaitQueue(); ++ PaperFileIOThread.Holder.INSTANCE.flush(); ++ drainChunkWaitQueue(); ++ ++ if (this.workers == null) { ++ if (Bukkit.isPrimaryThread() || MinecraftServer.getServer().hasStopped()) { ++ ((BlockableEventLoop)this.world.getChunkSource().mainThreadProcessor).runAllTasks(); ++ } else { ++ CompletableFuture wait = new CompletableFuture<>(); ++ MinecraftServer.getServer().scheduleOnMain(() -> { ++ ((BlockableEventLoop)this.world.getChunkSource().mainThreadProcessor).runAllTasks(); ++ }); ++ wait.join(); ++ } ++ } else { ++ for (final QueueExecutorThread worker : this.workers) { ++ worker.flush(); ++ } ++ } ++ if (globalUrgentWorker != null) globalUrgentWorker.flush(); ++ ++ // flush again since tasks we execute async saves ++ drainChunkWaitQueue(); ++ PaperFileIOThread.Holder.INSTANCE.flush(); ++ } ++ ++ public void close(final boolean wait) { ++ // flush here since we schedule tasks on the IO thread that can schedule tasks to this task manager ++ // we do this regardless of the wait param since after we invoke close no tasks can be queued ++ PaperFileIOThread.Holder.INSTANCE.flush(); ++ ++ if (this.workers == null) { ++ if (wait) { ++ this.flush(); ++ } ++ return; ++ } ++ ++ if (this.workers != globalWorkers) { ++ for (final QueueExecutorThread worker : this.workers) { ++ worker.close(false, this.perWorldQueue); ++ } ++ } ++ ++ if (wait) { ++ this.flush(); ++ } ++ } ++ ++ public void raisePriority(final int chunkX, final int chunkZ, final int priority) { ++ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); ++ ++ ChunkTask chunkSaveTask = this.chunkSaveTasks.get(chunkKey); ++ if (chunkSaveTask != null) { ++ // don't bump save into urgent queue ++ raiseTaskPriority(chunkSaveTask, priority != PrioritizedTaskQueue.HIGHEST_PRIORITY ? priority : PrioritizedTaskQueue.HIGH_PRIORITY); ++ } ++ ++ ChunkLoadTask chunkLoadTask = this.chunkLoadTasks.get(chunkKey); ++ if (chunkLoadTask != null) { ++ raiseTaskPriority(chunkLoadTask, priority); ++ } ++ } ++ ++ private void raiseTaskPriority(ChunkTask task, int priority) { ++ final boolean raised = task.raisePriority(priority); ++ if (task.isScheduled() && raised && this.workers != null) { ++ // only notify if we're in queue to be executed ++ if (priority == PrioritizedTaskQueue.HIGHEST_PRIORITY) { ++ // was in another queue but became urgent later, add to urgent queue and the previous ++ // queue will just have to ignore this task if it has already been started. ++ // Ultimately, we now have 2 potential queues that can pull it out whoever gets it first ++ // but the urgent queue has dedicated thread(s) so it's likely to win.... ++ globalUrgentQueue.add(task); ++ this.internalScheduleNotifyUrgent(); ++ } else { ++ this.internalScheduleNotify(); ++ } ++ } ++ } ++ ++ protected void internalSchedule(final ChunkTask task) { ++ if (this.workers == null) { ++ this.chunkTasks.add(task); ++ return; ++ } ++ ++ // It's important we order the task to be executed before notifying. Avoid a race condition where the worker thread ++ // wakes up and goes to sleep before we actually schedule (or it's just about to sleep) ++ if (task.getPriority() == PrioritizedTaskQueue.HIGHEST_PRIORITY) { ++ globalUrgentQueue.add(task); ++ this.internalScheduleNotifyUrgent(); ++ } else { ++ this.queue.add(task); ++ this.internalScheduleNotify(); ++ } ++ ++ } ++ ++ protected void internalScheduleNotify() { ++ if (this.workers == null) { ++ return; ++ } ++ for (final QueueExecutorThread worker : this.workers) { ++ if (worker.notifyTasks()) { ++ // break here since we only want to wake up one worker for scheduling one task ++ break; ++ } ++ } ++ } ++ ++ ++ protected void internalScheduleNotifyUrgent() { ++ if (globalUrgentWorker == null) { ++ return; ++ } ++ globalUrgentWorker.notifyTasks(); ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java +index 354783f862986bf939639a86a9076ac0f5ed97e3..c171860bc117199ca00085bf37507f867d51fb62 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java +@@ -14,7 +14,7 @@ public class ServerboundCommandSuggestionPacket implements Packet { + DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataFixers.getDataFixer(), minecraftsessionservice, gameprofilerepository, usercache, LoggerChunkProgressListener::new); + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index aab1a055c065d1f1a92461e4442ec2cdd8e0b347..643d75b999c3da006eaaab11f4acd77e807683d4 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -920,7 +920,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> future = this.getFutureIfPresentUnchecked(curr); ++ Either either = future.getNow(null); ++ if (either == null || !either.left().isPresent()) { ++ continue; ++ } ++ return curr; ++ } ++ return null; ++ } + // Paper end + + public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { +@@ -375,7 +387,7 @@ public class ChunkHolder { + ChunkStatus chunkstatus = getStatus(this.oldTicketLevel); + ChunkStatus chunkstatus1 = getStatus(this.ticketLevel); + boolean flag = this.oldTicketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; +- boolean flag1 = this.ticketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; ++ boolean flag1 = this.ticketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; // Paper - diff on change: (flag1 = new ticket level is in loadable range) + ChunkHolder.FullChunkStatus playerchunk_state = getFullChunkStatus(this.oldTicketLevel); + ChunkHolder.FullChunkStatus playerchunk_state1 = getFullChunkStatus(this.ticketLevel); + // CraftBukkit start +@@ -411,6 +423,12 @@ public class ChunkHolder { + } + }); + ++ // Paper start ++ if (!flag1) { ++ chunkStorage.level.asyncChunkTaskManager.cancelChunkLoad(this.pos.x, this.pos.z); ++ } ++ // Paper end ++ + for (int i = flag1 ? chunkstatus1.getIndex() + 1 : 0; i <= chunkstatus.getIndex(); ++i) { + completablefuture = (CompletableFuture) this.futures.get(i); + if (completablefuture != null) { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f327e2113 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -86,6 +86,7 @@ import net.minecraft.world.level.chunk.ProtoChunk; + import net.minecraft.world.level.chunk.UpgradeData; + import net.minecraft.world.level.chunk.storage.ChunkSerializer; + import net.minecraft.world.level.chunk.storage.ChunkStorage; ++import net.minecraft.world.level.chunk.storage.RegionFile; + import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; + import net.minecraft.world.level.storage.DimensionDataStorage; +@@ -110,7 +111,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private final ThreadedLevelLightEngine lightEngine; + private final BlockableEventLoop mainThreadExecutor; + public final ChunkGenerator generator; +- private final Supplier overworldDataStorage; ++ private final Supplier overworldDataStorage; public final Supplier getWorldPersistentDataSupplier() { return this.overworldDataStorage; } // Paper - OBFHELPER + private final PoiManager poiManager; + public final LongSet toDrop; + private boolean modified; +@@ -120,7 +121,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final ChunkProgressListener progressListener; + public final ChunkMap.ChunkDistanceManager distanceManager; + private final AtomicInteger tickingGenerated; +- private final StructureManager structureManager; ++ public final StructureManager structureManager; // Paper - private -> public + private final File storageFolder; + private final PlayerMap playerMap; + public final Int2ObjectMap entityMap; +@@ -203,7 +204,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); + this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); + this.overworldDataStorage = supplier; +- this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag); ++ this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper + this.setViewDistance(i); + } + +@@ -245,12 +246,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + @Nullable +- protected ChunkHolder getUpdatingChunkIfPresent(long pos) { ++ public ChunkHolder getUpdatingChunkIfPresent(long pos) { // Paper + return (ChunkHolder) this.updatingChunkMap.get(pos); + } + + @Nullable +- protected ChunkHolder getVisibleChunkIfPresent(long pos) { ++ public ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public + return (ChunkHolder) this.visibleChunkMap.get(pos); + } + +@@ -372,6 +373,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public void close() throws IOException { + try { + this.queueSorter.close(); ++ this.level.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line + this.poiManager.close(); + } finally { + super.close(); +@@ -463,7 +465,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.processUnloads(() -> { + return true; + }); +- this.flushWorker(); ++ this.level.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour ++// this.i(); // Paper - nuke IOWorker + ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); + } else { + this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { +@@ -479,16 +482,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + } + +- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot ++ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more + + protected void tick(BooleanSupplier shouldKeepTicking) { + ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + ++ try (Timing ignored = this.level.timings.poiUnload.startTiming()) { // Paper + gameprofilerfiller.push("poi"); + this.poiManager.tick(shouldKeepTicking); ++ } // Paper + gameprofilerfiller.popPush("chunk_unload"); + if (!this.level.noSave()) { ++ try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper + this.processUnloads(shouldKeepTicking); ++ }// Paper + } + + gameprofilerfiller.pop(); +@@ -509,12 +516,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (playerchunk != null) { + this.pendingUnloads.put(j, playerchunk); + this.modified = true; ++ this.scheduleUnload(j, playerchunk); // Paper - Move up - don't leak chunks + // Spigot start + if (!shouldKeepTicking.getAsBoolean() && this.toDrop.size() <= targetSize && activityAccountant.activityTimeIsExhausted()) { + break; + } + // Spigot end +- this.scheduleUnload(j, playerchunk); ++ //this.a(j, playerchunk); // Paper - move up because spigot did a dumb + } + } + activityAccountant.endActivity(); // Spigot +@@ -528,6 +536,60 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + } + ++ // Paper start - async chunk save for unload ++ // Note: This is very unsafe to call if the chunk is still in use. ++ // This is also modeled after PlayerChunkMap#saveChunk(IChunkAccess, boolean), with the intentional difference being ++ // serializing the chunk is left to a worker thread. ++ private void asyncSave(ChunkAccess chunk) { ++ ChunkPos chunkPos = chunk.getPos(); ++ CompoundTag poiData; ++ try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) { ++ poiData = this.getVillagePlace().getData(chunk.getPos()); ++ } ++ ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkPos.x, chunkPos.z, ++ poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); ++ ++ if (!chunk.isUnsaved()) { ++ return; ++ } ++ ++ ChunkStatus chunkstatus = chunk.getStatus(); ++ ++ // Copied from PlayerChunkMap#saveChunk(IChunkAccess, boolean) ++ if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { ++ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper ++ // Paper start - Optimize save by using status cache ++ try { ++ ChunkStatus statusOnDisk = this.getChunkStatusOnDisk(chunkPos); ++ if (statusOnDisk != null && statusOnDisk.getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { ++ // Paper end ++ return; ++ } ++ ++ if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::e)) { ++ return; ++ } ++ } catch (IOException ex) { ++ ex.printStackTrace(); ++ return; ++ } ++ } ++ } ++ ++ ChunkSerializer.AsyncSaveData asyncSaveData; ++ try (Timing ignored = this.level.timings.chunkUnloadPrepareSave.startTiming()) { ++ asyncSaveData = ChunkSerializer.getAsyncSaveData(this.level, chunk); ++ } ++ ++ this.level.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY, ++ asyncSaveData, chunk); ++ ++ chunk.setLastSaveTime(this.level.getGameTime()); ++ chunk.setUnsaved(false); ++ } ++ // Paper end ++ + private void scheduleUnload(long pos, ChunkHolder playerchunk) { + CompletableFuture completablefuture = playerchunk.getChunkToSave(); + Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error +@@ -541,7 +603,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ((LevelChunk) ichunkaccess).setLoaded(false); + } + +- this.save(ichunkaccess); ++ //this.saveChunk(ichunkaccess);// Paper - delay + if (this.entitiesInLevel.remove(pos) && ichunkaccess instanceof LevelChunk) { + LevelChunk chunk = (LevelChunk) ichunkaccess; + +@@ -549,6 +611,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + this.autoSaveQueue.remove(playerchunk); // Paper + ++ try { ++ this.asyncSave(ichunkaccess); // Paper - async chunk saving ++ } catch (Throwable ex) { ++ LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex); ++ this.save(ichunkaccess); ++ } ++ + this.lightEngine.updateChunkStatus(ichunkaccess.getPos()); + this.lightEngine.tryScheduleUpdate(); + this.progressListener.onStatusChange(ichunkaccess.getPos(), (ChunkStatus) null); +@@ -619,19 +688,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + private CompletableFuture> scheduleChunkLoad(ChunkPos pos) { +- return CompletableFuture.supplyAsync(() -> { ++ // Paper start - Async chunk io ++ final java.util.function.BiFunction> syncLoadComplete = (chunkHolder, ioThrowable) -> { + try (Timing ignored = this.level.timings.chunkLoad.startTimingIfSync()) { // Paper + this.level.getProfiler().incrementCounter("chunkLoad"); +- CompoundTag nbttagcompound; // Paper +- try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings +- nbttagcompound = this.readChunk(pos); +- } // Paper end ++ // Paper start ++ if (ioThrowable != null) { ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable); ++ } ++ ++ this.getVillagePlace().loadInData(pos, chunkHolder.poiData); ++ chunkHolder.tasks.forEach(Runnable::run); ++ // Paper end + +- if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings +- boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8); ++ if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async + +- if (flag) { +- ProtoChunk protochunk = ChunkSerializer.read(this.level, this.structureManager, this.poiManager, pos, nbttagcompound); ++ if (true) { ++ ProtoChunk protochunk = chunkHolder.protoChunk; + + protochunk.setLastSaveTime(this.level.getGameTime()); + this.markPosition(pos, protochunk.getStatus().getChunkType()); +@@ -655,7 +728,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + this.markPositionReplaceable(pos); + return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level)); // Paper - Anti-Xray - Add parameter +- }, this.mainThreadExecutor); ++ // Paper start - Async chunk io ++ }; ++ CompletableFuture> ret = new CompletableFuture<>(); ++ ++ Consumer chunkHolderConsumer = (ChunkSerializer.InProgressChunkHolder holder) -> { ++ // Go into the chunk load queue and not server task queue so we can be popped out even faster. ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.queueChunkWaitTask(() -> { ++ try { ++ ret.complete(syncLoadComplete.apply(holder, null)); ++ } catch (Exception e) { ++ ret.completeExceptionally(e); ++ } ++ }); ++ }; ++ ++ CompletableFuture chunkSaveFuture = this.level.asyncChunkTaskManager.getChunkSaveFuture(pos.x, pos.z); ++ if (chunkSaveFuture != null) { ++ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, ++ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); ++ this.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); ++ } else { ++ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, ++ com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); ++ } ++ return ret; ++ // Paper end + } + + private void markPositionReplaceable(ChunkPos chunkcoordintpair) { +@@ -890,6 +988,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + public boolean save(ChunkAccess chunk) { ++ try (co.aikar.timings.Timing ignored = this.level.timings.chunkSave.startTiming()) { // Paper + this.poiManager.flush(chunk.getPos()); + if (!chunk.isUnsaved()) { + return false; +@@ -902,6 +1001,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkStatus chunkstatus = chunk.getStatus(); + + if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { ++ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper + if (this.isExistingChunkFull(chunkcoordintpair)) { + return false; + } +@@ -909,12 +1009,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::e)) { + return false; + } ++ } // Paper + } + + this.level.getProfiler().incrementCounter("chunkSave"); +- CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk); ++ CompoundTag nbttagcompound; ++ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper ++ nbttagcompound = ChunkSerializer.write(this.level, chunk); ++ } // Paper + +- this.write(chunkcoordintpair, nbttagcompound); ++ ++ // Paper start - async chunk io ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z, ++ null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); ++ // Paper end - async chunk io + this.markPosition(chunkcoordintpair, chunkstatus.getChunkType()); + return true; + } catch (Exception exception) { +@@ -923,6 +1031,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return false; + } + } ++ } // Paper + } + + private boolean isExistingChunkFull(ChunkPos chunkcoordintpair) { +@@ -1052,6 +1161,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + } + ++ // Paper start - Asynchronous chunk io ++ @Nullable ++ @Override ++ public CompoundTag read(ChunkPos chunkcoordintpair) throws IOException { ++ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { ++ CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .loadChunkDataAsyncFuture(this.level, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), ++ false, true, true).join().chunkData; ++ ++ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { ++ throw new IOException("See logs for further detail"); ++ } ++ return ret; ++ } ++ return super.read(chunkcoordintpair); ++ } ++ ++ @Override ++ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { ++ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( ++ this.level, chunkcoordintpair.x, chunkcoordintpair.z, null, nbttagcompound, ++ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); ++ return; ++ } ++ super.write(chunkcoordintpair, nbttagcompound); ++ } ++ // Paper end ++ + @Nullable + public CompoundTag readChunk(ChunkPos pos) throws IOException { // Paper - private -> public + CompoundTag nbttagcompound = this.read(pos); +@@ -1073,33 +1211,55 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + // Paper start - chunk status cache "api" + public ChunkStatus getChunkStatusOnDiskIfCached(ChunkPos chunkPos) { +- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); ++ synchronized (this) { // Paper ++ RegionFile regionFile = this.regionFileCache.getRegionFileIfLoaded(chunkPos); + + return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ } // Paper + } + + public ChunkStatus getChunkStatusOnDisk(ChunkPos chunkPos) throws IOException { +- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); ++ // Paper start - async chunk save for unload ++ ChunkAccess unloadingChunk = this.level.asyncChunkTaskManager.getChunkInSaveProgress(chunkPos.x, chunkPos.z); ++ if (unloadingChunk != null) { ++ return unloadingChunk.getStatus(); ++ } ++ // Paper end ++ // Paper start - async io ++ CompoundTag inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .getPendingWrite(this.level, chunkPos.x, chunkPos.z, false); + +- if (regionFile == null || !regionFile.chunkExists(chunkPos)) { +- return null; ++ if (inProgressWrite != null) { ++ return ChunkSerializer.getStatus(inProgressWrite); + } ++ // Paper end ++ synchronized (this) { // Paper - async io ++ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, true); ++ ++ if (regionFile == null || !regionFile.hasChunk(chunkPos)) { ++ return null; ++ } + +- ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); + +- if (status != null) { +- return status; ++ if (status != null) { ++ return status; ++ } ++ // Paper start - async io + } + +- this.readChunk(chunkPos); ++ CompoundTag compound = this.readChunk(chunkPos); + +- return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ return ChunkSerializer.getStatus(compound); ++ // Paper end + } + + public void updateChunkStatusOnDisk(ChunkPos chunkPos, @Nullable CompoundTag compound) throws IOException { +- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); ++ synchronized (this) { ++ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, false); + +- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); ++ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); ++ } + } + + public ChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { +@@ -1108,6 +1268,39 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + // Paper end + ++ ++ // Paper start - async io ++ // this function will not load chunk data off disk to check for status ++ // ret null for unknown, empty for empty status on disk or absent from disk ++ public ChunkStatus getStatusOnDiskNoLoad(int x, int z) { ++ // Paper start - async chunk save for unload ++ ChunkAccess unloadingChunk = this.level.asyncChunkTaskManager.getChunkInSaveProgress(x, z); ++ if (unloadingChunk != null) { ++ return unloadingChunk.getStatus(); ++ } ++ // Paper end ++ // Paper start - async io ++ CompoundTag inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .getPendingWrite(this.level, x, z, false); ++ ++ if (inProgressWrite != null) { ++ return ChunkSerializer.getStatus(inProgressWrite); ++ } ++ // Paper end ++ // variant of PlayerChunkMap#getChunkStatusOnDisk that does not load data off disk, but loads the region file ++ ChunkPos chunkPos = new ChunkPos(x, z); ++ synchronized (level.getChunkSource().chunkMap) { ++ RegionFile file; ++ try { ++ file = level.getChunkSource().chunkMap.regionFileCache.getFile(chunkPos, false); ++ } catch (IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return !file.hasChunk(chunkPos) ? ChunkStatus.EMPTY : file.getStatusIfCached(x, z); ++ } ++ } ++ + boolean noPlayersCloseForSpawning(ChunkPos chunkcoordintpair) { + // Spigot start + return isOutsideOfRange(chunkcoordintpair, false); +@@ -1454,6 +1647,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + } + ++ public PoiManager getVillagePlace() { return this.getPoiManager(); } // Paper - OBFHELPER + protected PoiManager getPoiManager() { + return this.poiManager; + } +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index c1aa40c01a80a8870478193b8cd7354b0d71045c..120b604d91643248ab375969f95f62a74cbf6be7 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -37,6 +37,7 @@ import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.ChunkSource; + import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.chunk.ImposterProtoChunk; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; + import net.minecraft.world.level.storage.DimensionDataStorage; +@@ -332,11 +333,138 @@ public class ServerChunkCache extends ChunkSource { + return playerChunk.getAvailableChunkNow(); + + } ++ ++ private long asyncLoadSeqCounter; ++ ++ public CompletableFuture> getChunkAtAsynchronously(int x, int z, boolean gen, boolean isUrgent) { ++ if (Thread.currentThread() != this.mainThread) { ++ CompletableFuture> future = new CompletableFuture>(); ++ this.mainThreadProcessor.execute(() -> { ++ this.getChunkAtAsynchronously(x, z, gen, isUrgent).whenComplete((chunk, ex) -> { ++ if (ex != null) { ++ future.completeExceptionally(ex); ++ } else { ++ future.complete(chunk); ++ } ++ }); ++ }); ++ return future; ++ } ++ ++ if (!com.destroystokyo.paper.PaperConfig.asyncChunks) { ++ level.getWorld().loadChunk(x, z, gen); ++ LevelChunk chunk = getChunkAtIfLoadedMainThread(x, z); ++ return CompletableFuture.completedFuture(chunk != null ? Either.left(chunk) : ChunkHolder.UNLOADED_CHUNK); ++ } ++ ++ long k = ChunkPos.asLong(x, z); ++ ChunkPos chunkPos = new ChunkPos(x, z); ++ ++ ChunkAccess ichunkaccess; ++ ++ // try cache ++ for (int l = 0; l < 4; ++l) { ++ if (k == this.lastChunkPos[l] && ChunkStatus.FULL == this.lastChunkStatus[l]) { ++ ichunkaccess = this.lastChunk[l]; ++ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime ++ ++ // move to first in cache ++ ++ for (int i1 = 3; i1 > 0; --i1) { ++ this.lastChunkPos[i1] = this.lastChunkPos[i1 - 1]; ++ this.lastChunkStatus[i1] = this.lastChunkStatus[i1 - 1]; ++ this.lastChunk[i1] = this.lastChunk[i1 - 1]; ++ } ++ ++ this.lastChunkPos[0] = k; ++ this.lastChunkStatus[0] = ChunkStatus.FULL; ++ this.lastChunk[0] = ichunkaccess; ++ ++ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); ++ } ++ } ++ } ++ ++ if (gen) { ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ } ++ ++ ChunkAccess current = this.getChunkAtImmediately(x, z); // we want to bypass ticket restrictions ++ if (current != null) { ++ if (!(current instanceof ImposterProtoChunk) && !(current instanceof LevelChunk)) { ++ return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); ++ } ++ // we know the chunk is at full status here (either in read-only mode or the real thing) ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ } ++ ++ ChunkStatus status = level.getChunkSource().chunkMap.getStatusOnDiskNoLoad(x, z); ++ ++ if (status != null && status != ChunkStatus.FULL) { ++ // does not exist on disk ++ return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); ++ } ++ ++ if (status == ChunkStatus.FULL) { ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ } ++ ++ // status is null here ++ ++ // here we don't know what status it is and we're not supposed to generate ++ // so we asynchronously load empty status ++ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.EMPTY, isUrgent).thenCompose((either) -> { ++ ChunkAccess chunk = either.left().orElse(null); ++ if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof LevelChunk)) { ++ // the chunk on disk was not a full status chunk ++ return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); ++ } ++ ; // bring to full status if required ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ }); ++ } ++ ++ private CompletableFuture> bringToFullStatusAsync(int x, int z, ChunkPos chunkPos, boolean isUrgent) { ++ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.FULL, isUrgent); ++ } ++ ++ private CompletableFuture> bringToStatusAsync(int x, int z, ChunkPos chunkPos, ChunkStatus status, boolean isUrgent) { ++ CompletableFuture> future = this.getChunkFutureMainThread(x, z, status, true, isUrgent); ++ Long identifier = Long.valueOf(this.asyncLoadSeqCounter++); ++ int ticketLevel = MCUtil.getTicketLevelFor(status); ++ this.addTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); ++ ++ return future.thenComposeAsync((Either either) -> { ++ // either left -> success ++ // either right -> failure ++ ++ this.removeTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); ++ this.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); // allow unloading ++ ++ Optional failure = either.right(); ++ ++ if (failure.isPresent()) { ++ // failure ++ throw new IllegalStateException("Chunk failed to load: " + failure.get().toString()); ++ } ++ ++ return CompletableFuture.completedFuture(either); ++ }, this.mainThreadProcessor); ++ } ++ ++ public void addTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { ++ this.distanceManager.addTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); ++ } ++ ++ public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { ++ this.distanceManager.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); ++ } + // Paper end + + @Nullable + @Override + public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) { ++ final int x1 = x; final int z1 = z; // Paper - conflict on variable change + if (Thread.currentThread() != this.mainThread) { + return (ChunkAccess) CompletableFuture.supplyAsync(() -> { + return this.getChunk(x, z, leastStatus, create); +@@ -359,11 +487,16 @@ public class ServerChunkCache extends ChunkSource { + } + + gameprofilerfiller.incrementCounter("getChunkCacheMiss"); +- CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); ++ CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper + + if (!completablefuture.isDone()) { // Paper ++ // Paper start - async chunk io/loading ++ this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); ++ // Paper end + this.level.timings.syncChunkLoad.startTiming(); // Paper + this.mainThreadProcessor.managedBlock(completablefuture::isDone); ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug + this.level.timings.syncChunkLoad.stopTiming(); // Paper + } // Paper + ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { +@@ -429,9 +562,14 @@ public class ServerChunkCache extends ChunkSource { + } + + private CompletableFuture> getChunkFutureMainThread(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { +- ChunkPos chunkcoordintpair = new ChunkPos(chunkX, chunkZ); ++ // Paper start - add isUrgent - old sig left in place for dirty nms plugins ++ return getChunkFutureMainThread(chunkX, chunkZ, leastStatus, create, false); ++ } ++ private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag, boolean isUrgent) { ++ // Paper end ++ ChunkPos chunkcoordintpair = new ChunkPos(i, j); + long k = chunkcoordintpair.toLong(); +- int l = 33 + ChunkStatus.getDistance(leastStatus); ++ int l = 33 + ChunkStatus.getDistance(chunkstatus); + ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); + + // CraftBukkit start - don't add new ticket for currently unloading chunk +@@ -441,7 +579,7 @@ public class ServerChunkCache extends ChunkSource { + ChunkHolder.FullChunkStatus currentChunkState = ChunkHolder.getFullChunkStatus(playerchunk.getTicketLevel()); + currentlyUnloading = (oldChunkState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !currentChunkState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)); + } +- if (create && !currentlyUnloading) { ++ if (flag && !currentlyUnloading) { + // CraftBukkit end + this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); + if (this.chunkAbsent(playerchunk, l)) { +@@ -457,7 +595,7 @@ public class ServerChunkCache extends ChunkSource { + } + } + +- return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(leastStatus, this.chunkMap); ++ return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkstatus, this.chunkMap); + } + + private boolean chunkAbsent(@Nullable ChunkHolder holder, int maxLevel) { +@@ -831,11 +969,12 @@ public class ServerChunkCache extends ChunkSource { + protected boolean pollTask() { + // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task + try { ++ boolean execChunkTask = com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ServerChunkCache.this.level.asyncChunkTaskManager.pollNextChunkTask(); // Paper + if (ServerChunkCache.this.runDistanceManagerUpdates()) { + return true; + } else { + ServerChunkCache.this.lightEngine.tryScheduleUpdate(); +- return super.pollTask(); ++ return super.pollTask() || execChunkTask; // Paper + } + } finally { + chunkMap.callbackExecutor.run(); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index a811ced17721b70bb51837f47e466c2261db2466..95eff4f6165024d21e5c4268a9ae1b7a4268de4b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -51,6 +51,7 @@ import net.minecraft.core.RegistryAccess; + import net.minecraft.core.SectionPos; + import net.minecraft.core.Vec3i; + import net.minecraft.core.particles.ParticleOptions; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.Packet; +@@ -122,6 +123,7 @@ import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.chunk.LevelChunkSection; ++import net.minecraft.world.level.chunk.storage.RegionFile; + import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.level.dimension.end.EndDragonFight; + import net.minecraft.world.level.levelgen.Heightmap; +@@ -202,6 +204,79 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return this.chunkSource.getChunk(x, z, false); + } + ++ // Paper start - Asynchronous IO ++ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController poiDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { ++ @Override ++ public void writeData(int x, int z, CompoundTag compound) throws java.io.IOException { ++ ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().write(new ChunkPos(x, z), compound); ++ } ++ ++ @Override ++ public CompoundTag readData(int x, int z) throws java.io.IOException { ++ return ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().read(new ChunkPos(x, z)); ++ } ++ ++ @Override ++ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (ServerLevel.this.getChunkSource().chunkMap.getVillagePlace()) { ++ RegionFile file; ++ ++ try { ++ file = ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().getFile(new ChunkPos(chunkX, chunkZ), false); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return function.apply(file); ++ } ++ } ++ ++ @Override ++ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (ServerLevel.this.getChunkSource().chunkMap.getVillagePlace()) { ++ RegionFile file = ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().getRegionFileIfLoaded(new ChunkPos(chunkX, chunkZ)); ++ return function.apply(file); ++ } ++ } ++ }; ++ ++ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController chunkDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { ++ @Override ++ public void writeData(int x, int z, CompoundTag compound) throws java.io.IOException { ++ ServerLevel.this.getChunkSource().chunkMap.write(new ChunkPos(x, z), compound); ++ } ++ ++ @Override ++ public CompoundTag readData(int x, int z) throws java.io.IOException { ++ return ServerLevel.this.getChunkSource().chunkMap.read(new ChunkPos(x, z)); ++ } ++ ++ @Override ++ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (ServerLevel.this.getChunkSource().chunkMap) { ++ RegionFile file; ++ ++ try { ++ file = ServerLevel.this.getChunkSource().chunkMap.regionFileCache.getFile(new ChunkPos(chunkX, chunkZ), false); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return function.apply(file); ++ } ++ } ++ ++ @Override ++ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (ServerLevel.this.getChunkSource().chunkMap) { ++ RegionFile file = ServerLevel.this.getChunkSource().chunkMap.regionFileCache.getRegionFileIfLoaded(new ChunkPos(chunkX, chunkZ)); ++ return function.apply(file); ++ } ++ } ++ }; ++ public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; ++ // Paper end ++ + // Add env and gen to constructor, WorldData -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor +@@ -249,6 +324,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.dragonFight = null; + } + this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit ++ ++ this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper + } + + // CraftBukkit start +@@ -1737,7 +1814,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + MCUtil.getSpiralOutChunks(spawn, radiusInBlocks >> 4).forEach(pair -> { +- getChunkSource().getChunkAtMainThread(pair.x, pair.z); ++ getChunkSource().getChunkAtAsynchronously(pair.x, pair.z, true, false).exceptionally((ex) -> { ++ ex.printStackTrace(); ++ return null; ++ }); + }); + } + public void removeTicketsForSpawn(int radiusInBlocks, BlockPos spawn) { +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index cf3ced15c9a87e7a4dbccba17c57a7b32b77566c..d09e4857b6c40410d134fa81b48e95919a7373bd 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -26,6 +26,7 @@ public class TicketType { + public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit + public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper ++ public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper + + public static TicketType create(String name, Comparator comparator) { + return new TicketType<>(name, comparator, 0L); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 4f99c3d06e3b994708c699395adf481a6828e097..5dd99709d6b0ed15bbcee184fe33a28bc1c19dac 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -728,6 +728,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper + return; + } ++ // Paper start ++ String str = packet.getCommand(); int index = -1; ++ if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ return; ++ } ++ // Paper end + // CraftBukkit end + StringReader stringreader = new StringReader(packet.getCommand()); + +diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +index e48fcfe2e4ff151258ae1d84cc0995d2cd54e9a6..a5ce61be7d6e85ac289730d9671e66a7190529f9 100644 +--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java ++++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +@@ -91,7 +91,7 @@ public abstract class BlockableEventLoop implements Processo + + } + +- protected void runAllTasks() { ++ public void runAllTasks() { // Paper - protected -> public + while (this.pollTask()) { + ; + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +index 33a8604fa6c6431ccc5f61e484c163e09f1625a0..d082af8cf4c0c7ca434598aa370712c62e05bb24 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +@@ -22,7 +22,9 @@ import java.util.stream.Stream; + import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.SectionTracker; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.LevelReader; +@@ -36,8 +38,16 @@ public class PoiManager extends SectionStorage { + private final PoiManager.DistanceTracker distanceTracker = new PoiManager.DistanceTracker(); + private final LongSet loadedChunks = new LongOpenHashSet(); + ++ private final ServerLevel world; // Paper ++ + public PoiManager(File directory, DataFixer datafixer, boolean flag) { +- super(directory, PoiSection::codec, PoiSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); ++ // Paper start - add world parameter ++ this(directory, datafixer, flag, null); ++ } ++ public PoiManager(File file, DataFixer datafixer, boolean flag, ServerLevel world) { ++ super(file, PoiSection::codec, PoiSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); ++ this.world = world; ++ // Paper end - add world parameter + } + + public void add(BlockPos pos, PoiType type) { +@@ -155,7 +165,23 @@ public class PoiManager extends SectionStorage { + + @Override + public void tick(BooleanSupplier shouldKeepTicking) { +- super.tick(shouldKeepTicking); ++ // Paper start - async chunk io ++ if (this.world == null) { ++ super.tick(shouldKeepTicking); ++ } else { ++ //super.a(booleansupplier); // re-implement below ++ while (!((SectionStorage)this).dirty.isEmpty() && shouldKeepTicking.getAsBoolean()) { ++ ChunkPos chunkcoordintpair = SectionPos.of(((SectionStorage)this).dirty.firstLong()).chunk(); ++ ++ CompoundTag data; ++ try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) { ++ data = this.getData(chunkcoordintpair); ++ } ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, ++ chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); ++ } ++ } ++ // Paper end + this.distanceTracker.runAllUpdates(); + } + +@@ -255,6 +281,35 @@ public class PoiManager extends SectionStorage { + } + } + ++ // Paper start - Asynchronous chunk io ++ @javax.annotation.Nullable ++ @Override ++ public CompoundTag read(ChunkPos chunkcoordintpair) throws java.io.IOException { ++ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { ++ CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), ++ true, false, true).join().poiData; ++ ++ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { ++ throw new java.io.IOException("See logs for further detail"); ++ } ++ return ret; ++ } ++ return super.read(chunkcoordintpair); ++ } ++ ++ @Override ++ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws java.io.IOException { ++ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( ++ this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, ++ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); ++ return; ++ } ++ super.write(chunkcoordintpair, nbttagcompound); ++ } ++ // Paper end ++ + public static enum Occupancy { + + HAS_SPACE(PoiRecord::hasSpace), IS_OCCUPIED(PoiRecord::isOccupied), ANY((villageplacerecord) -> { +diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java +index d97e266b83bb331fcd4031046a5843d29ce53164..90833389022d7412bdda8868a356b84f62a00e03 100644 +--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java ++++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java +@@ -5,7 +5,7 @@ import net.minecraft.core.BlockPos; + + public class TickNextTickData { + +- private static long counter; ++ private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading + private final T type; + public final BlockPos pos; + public final long triggerTick; +@@ -17,7 +17,7 @@ public class TickNextTickData { + } + + public TickNextTickData(BlockPos pos, T t, long time, TickPriority priority) { +- this.c = (long) (TickNextTickData.counter++); ++ this.c = (long) (TickNextTickData.COUNTER.getAndIncrement()); // Paper - async chunk loading + this.pos = pos.immutable(); + this.type = t; + this.triggerTick = time; +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +index 46d5a24332c1fd3c164b760ec2a2d5bf859b1ab6..3c85b0d39a3fc5c8ec073d92f48b360c0b0be245 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +@@ -170,6 +170,7 @@ public class ChunkStatus { + return ChunkStatus.STATUS_BY_RANGE.size(); + } + ++ public static int getTicketLevelOffset(ChunkStatus status) { return ChunkStatus.getDistance(status); } // Paper - OBFHELPER + public static int getDistance(ChunkStatus status) { + return ChunkStatus.RANGE_BY_STATUS.getInt(status.getIndex()); + } +@@ -185,6 +186,7 @@ public class ChunkStatus { + this.index = previous == null ? 0 : previous.getIndex() + 1; + } + ++ public final int getStatusIndex() { return getIndex(); } // Paper - OBFHELPER + public int getIndex() { + return this.index; + } +@@ -193,7 +195,7 @@ public class ChunkStatus { + return this.name; + } + +- public ChunkStatus getPreviousStatus() { return this.getParent(); } // Paper - OBFHELPER ++ public final ChunkStatus getPreviousStatus() { return this.getParent(); } // Paper - OBFHELPER + public ChunkStatus getParent() { + return this.parent; + } +@@ -206,6 +208,7 @@ public class ChunkStatus { + return this.loadingTask.doWork(this, world, structureManager, lightingProvider, function, chunk); + } + ++ public final int getNeighborRadius() { return this.getRange(); } // Paper - OBFHELPER + public int getRange() { + return this.range; + } +@@ -233,6 +236,7 @@ public class ChunkStatus { + return this.heightmapsAfter; + } + ++ public final boolean isAtLeastStatus(ChunkStatus chunkstatus) { return isOrAfter(chunkstatus); } // Paper - OBFHELPER + public boolean isOrAfter(ChunkStatus chunk) { + return this.getIndex() >= chunk.getIndex(); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java +index 808f69a10589a4a7d6c238c05f6d3e0f272681d3..2b798f4e556302f6f79d54182a309f4716a84f04 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java +@@ -73,6 +73,7 @@ public class DataLayer { + return this.data; + } + ++ public DataLayer copy() { return this.copy(); } // Paper - OBFHELPER + public DataLayer copy() { + return this.data == null ? new DataLayer() : new DataLayer((byte[]) this.data.clone()); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2..be67dc16bf70e4517efd213ca9002f116f60b57c 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet; + import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.shorts.ShortList; + import it.unimi.dsi.fastutil.shorts.ShortListIterator; ++import java.util.ArrayDeque; // Paper + import java.util.Arrays; + import java.util.BitSet; + import java.util.EnumSet; +@@ -66,34 +67,58 @@ public class ChunkSerializer { + + private static final Logger LOGGER = LogManager.getLogger(); + ++ // Paper start ++ public static final class InProgressChunkHolder { ++ ++ public final ProtoChunk protoChunk; ++ public final ArrayDeque tasks; ++ ++ public CompoundTag poiData; ++ ++ public InProgressChunkHolder(final ProtoChunk protoChunk, final ArrayDeque tasks) { ++ this.protoChunk = protoChunk; ++ this.tasks = tasks; ++ } ++ } ++ + public static ProtoChunk read(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag tag) { +- ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); ++ InProgressChunkHolder holder = loadChunk(world, structureManager, poiStorage, pos, tag, true); ++ holder.tasks.forEach(Runnable::run); ++ return holder.protoChunk; ++ } ++ ++ public static InProgressChunkHolder loadChunk(ServerLevel worldserver, StructureManager definedstructuremanager, PoiManager villageplace, ChunkPos chunkcoordintpair, CompoundTag nbttagcompound, boolean distinguish) { ++ ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); ++ // Paper end ++ ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); + BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); +- CompoundTag nbttagcompound1 = tag.getCompound("Level"); ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); + ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); + +- if (!Objects.equals(pos, chunkcoordintpair1)) { +- ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", pos, pos, chunkcoordintpair1); ++ if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { ++ ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); + } + +- ChunkBiomeContainer biomestorage = new ChunkBiomeContainer(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), pos, worldchunkmanager, nbttagcompound1.contains("Biomes", 11) ? nbttagcompound1.getIntArray("Biomes") : null); ++ ChunkBiomeContainer biomestorage = new ChunkBiomeContainer(worldserver.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunkcoordintpair, worldchunkmanager, nbttagcompound1.contains("Biomes", 11) ? nbttagcompound1.getIntArray("Biomes") : null); + UpgradeData chunkconverter = nbttagcompound1.contains("UpgradeData", 10) ? new UpgradeData(nbttagcompound1.getCompound("UpgradeData")) : UpgradeData.EMPTY; + ProtoTickList protochunkticklist = new ProtoTickList<>((block) -> { + return block == null || block.defaultBlockState().isAir(); +- }, pos, nbttagcompound1.getList("ToBeTicked", 9)); ++ }, chunkcoordintpair, nbttagcompound1.getList("ToBeTicked", 9)); + ProtoTickList protochunkticklist1 = new ProtoTickList<>((fluidtype) -> { + return fluidtype == null || fluidtype == Fluids.EMPTY; +- }, pos, nbttagcompound1.getList("LiquidsToBeTicked", 9)); ++ }, chunkcoordintpair, nbttagcompound1.getList("LiquidsToBeTicked", 9)); + boolean flag = nbttagcompound1.getBoolean("isLightOn"); + ListTag nbttaglist = nbttagcompound1.getList("Sections", 10); + boolean flag1 = true; + LevelChunkSection[] achunksection = new LevelChunkSection[16]; +- boolean flag2 = world.dimensionType().hasSkyLight(); +- ServerChunkCache chunkproviderserver = world.getChunkSource(); ++ boolean flag2 = worldserver.dimensionType().hasSkyLight(); ++ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); + LevelLightEngine lightengine = chunkproviderserver.getLightEngine(); + + if (flag) { +- lightengine.retainData(pos, true); ++ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main ++ lightengine.retainData(chunkcoordintpair, true); ++ }); // Paper - delay this task since we're executing off-main + } + + for (int i = 0; i < nbttaglist.size(); ++i) { +@@ -101,7 +126,7 @@ public class ChunkSerializer { + byte b0 = nbttagcompound2.getByte("Y"); + + if (nbttagcompound2.contains("Palette", 9) && nbttagcompound2.contains("BlockStates", 12)) { +- LevelChunkSection chunksection = new LevelChunkSection(b0 << 4, null, world, false); // Paper - Anti-Xray - Add parameters ++ LevelChunkSection chunksection = new LevelChunkSection(b0 << 4, null, worldserver, false); // Paper - Anti-Xray - Add parameters + + chunksection.getStates().read(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); + chunksection.recalcBlockCounts(); +@@ -109,22 +134,34 @@ public class ChunkSerializer { + achunksection[b0] = chunksection; + } + +- poiStorage.checkConsistencyWithBlocks(pos, chunksection); ++ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main ++ villageplace.checkConsistencyWithBlocks(chunkcoordintpair, chunksection); ++ }); // Paper - delay this task since we're executing off-main + } + + if (flag) { + if (nbttagcompound2.contains("BlockLight", 7)) { +- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("BlockLight")), true); ++ // Paper start - delay this task since we're executing off-main ++ DataLayer blockLight = new DataLayer(nbttagcompound2.getByteArray("BlockLight")); ++ tasksToExecuteOnMain.add(() -> { ++ lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair, b0), blockLight, true); ++ }); ++ // Paper end - delay this task since we're executing off-main + } + + if (flag2 && nbttagcompound2.contains("SkyLight", 7)) { +- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("SkyLight")), true); ++ // Paper start - delay this task since we're executing off-main ++ DataLayer skyLight = new DataLayer(nbttagcompound2.getByteArray("SkyLight")); ++ tasksToExecuteOnMain.add(() -> { ++ lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkcoordintpair, b0), skyLight, true); ++ }); ++ // Paper end - delay this task since we're executing off-main + } + } + } + + long j = nbttagcompound1.getLong("InhabitedTime"); +- ChunkStatus.ChunkType chunkstatus_type = getChunkTypeFromTag(tag); ++ ChunkStatus.ChunkType chunkstatus_type = getChunkTypeFromTag(nbttagcompound); + Object object; + + if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) { +@@ -155,7 +192,7 @@ public class ChunkSerializer { + object2 = protochunkticklist1; + } + +- object = new LevelChunk(world.getLevel(), pos, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { ++ object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { + postLoadChunk(nbttagcompound1, chunk); + // CraftBukkit start - load chunk persistent data from nbt + net.minecraft.nbt.Tag persistentBase = nbttagcompound1.get("ChunkBukkitValues"); +@@ -165,7 +202,7 @@ public class ChunkSerializer { + // CraftBukkit end + }); + } else { +- ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world); // Paper - Anti-Xray - Add parameter ++ ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter + + protochunk.setBiomes(biomestorage); + object = protochunk; +@@ -176,7 +213,7 @@ public class ChunkSerializer { + } + + if (!flag && protochunk.getStatus().isOrAfter(ChunkStatus.LIGHT)) { +- Iterator iterator = BlockPos.betweenClosed(pos.getMinBlockX(), 0, pos.getMinBlockZ(), pos.getMaxBlockX(), 255, pos.getMaxBlockZ()).iterator(); ++ Iterator iterator = BlockPos.betweenClosed(chunkcoordintpair.getMinBlockX(), 0, chunkcoordintpair.getMinBlockZ(), chunkcoordintpair.getMaxBlockX(), 255, chunkcoordintpair.getMaxBlockZ()).iterator(); + + while (iterator.hasNext()) { + BlockPos blockposition = (BlockPos) iterator.next(); +@@ -207,8 +244,8 @@ public class ChunkSerializer { + Heightmap.primeHeightmaps((ChunkAccess) object, enumset); + CompoundTag nbttagcompound4 = nbttagcompound1.getCompound("Structures"); + +- ((ChunkAccess) object).setAllStarts(unpackStructureStart(structureManager, nbttagcompound4, world.getSeed())); +- ((ChunkAccess) object).setAllReferences(unpackStructureReferences(pos, nbttagcompound4)); ++ ((ChunkAccess) object).setAllStarts(unpackStructureStart(definedstructuremanager, nbttagcompound4, worldserver.getSeed())); ++ ((ChunkAccess) object).setAllReferences(unpackStructureReferences(chunkcoordintpair, nbttagcompound4)); + if (nbttagcompound1.getBoolean("shouldSave")) { + ((ChunkAccess) object).setUnsaved(true); + } +@@ -227,7 +264,7 @@ public class ChunkSerializer { + } + + if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) { +- return new ImposterProtoChunk((LevelChunk) object); ++ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading + } else { + ProtoChunk protochunk1 = (ProtoChunk) object; + +@@ -266,12 +303,84 @@ public class ChunkSerializer { + protochunk1.setCarvingMask(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1))); + } + +- return protochunk1; ++ return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading + } + } + ++ // Paper start - async chunk save for unload ++ public static final class AsyncSaveData { ++ public final DataLayer[] blockLight; // null or size of 17 (for indices -1 through 15) ++ public final DataLayer[] skyLight; ++ ++ public final ListTag blockTickList; // non-null if we had to go to the server's tick list ++ public final ListTag fluidTickList; // non-null if we had to go to the server's tick list ++ ++ public final long worldTime; ++ ++ public AsyncSaveData(DataLayer[] blockLight, DataLayer[] skyLight, ListTag blockTickList, ListTag fluidTickList, ++ long worldTime) { ++ this.blockLight = blockLight; ++ this.skyLight = skyLight; ++ this.blockTickList = blockTickList; ++ this.fluidTickList = fluidTickList; ++ this.worldTime = worldTime; ++ } ++ } ++ ++ // must be called sync ++ public static AsyncSaveData getAsyncSaveData(ServerLevel world, ChunkAccess chunk) { ++ org.spigotmc.AsyncCatcher.catchOp("preparation of chunk data for async save"); ++ ChunkPos chunkPos = chunk.getPos(); ++ ++ ThreadedLevelLightEngine lightenginethreaded = world.getChunkSource().getLightEngine(); ++ ++ DataLayer[] blockLight = new DataLayer[17 - (-1)]; ++ DataLayer[] skyLight = new DataLayer[17 - (-1)]; ++ ++ for (int i = -1; i < 17; ++i) { ++ DataLayer blockArray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkPos, i)); ++ DataLayer skyArray = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkPos, i)); ++ ++ // copy data for safety ++ if (blockArray != null) { ++ blockArray = blockArray.copy(); ++ } ++ if (skyArray != null) { ++ skyArray = skyArray.copy(); ++ } ++ ++ // apply offset of 1 for -1 starting index ++ blockLight[i + 1] = blockArray; ++ skyLight[i + 1] = skyArray; ++ } ++ ++ TickList blockTickList = chunk.getBlockTicks(); ++ ++ ListTag blockTickListSerialized; ++ if (blockTickList instanceof ProtoTickList || blockTickList instanceof ChunkTickList) { ++ blockTickListSerialized = null; ++ } else { ++ blockTickListSerialized = world.getBlockTicks().save(chunkPos); ++ } ++ ++ TickList fluidTickList = chunk.getLiquidTicks(); ++ ++ ListTag fluidTickListSerialized; ++ if (fluidTickList instanceof ProtoTickList || fluidTickList instanceof ChunkTickList) { ++ fluidTickListSerialized = null; ++ } else { ++ fluidTickListSerialized = world.getLiquidTicks().save(chunkPos); ++ } ++ ++ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, world.getGameTime()); ++ } ++ + public static CompoundTag write(ServerLevel world, ChunkAccess chunk) { +- ChunkPos chunkcoordintpair = chunk.getPos(); ++ return saveChunk(world, chunk, null); ++ } ++ public static CompoundTag saveChunk(ServerLevel worldserver, ChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { ++ // Paper end ++ ChunkPos chunkcoordintpair = ichunkaccess.getPos(); + CompoundTag nbttagcompound = new CompoundTag(); + CompoundTag nbttagcompound1 = new CompoundTag(); + +@@ -279,30 +388,38 @@ public class ChunkSerializer { + nbttagcompound.put("Level", nbttagcompound1); + nbttagcompound1.putInt("xPos", chunkcoordintpair.x); + nbttagcompound1.putInt("zPos", chunkcoordintpair.z); +- nbttagcompound1.putLong("LastUpdate", world.getGameTime()); +- nbttagcompound1.putLong("InhabitedTime", chunk.getInhabitedTime()); +- nbttagcompound1.putString("Status", chunk.getStatus().getName()); +- UpgradeData chunkconverter = chunk.getUpgradeData(); ++ nbttagcompound1.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getGameTime()); // Paper - async chunk unloading ++ nbttagcompound1.putLong("InhabitedTime", ichunkaccess.getInhabitedTime()); ++ nbttagcompound1.putString("Status", ichunkaccess.getStatus().getName()); ++ UpgradeData chunkconverter = ichunkaccess.getUpgradeData(); + + if (!chunkconverter.isEmpty()) { + nbttagcompound1.put("UpgradeData", chunkconverter.write()); + } + +- LevelChunkSection[] achunksection = chunk.getSections(); ++ LevelChunkSection[] achunksection = ichunkaccess.getSections(); + ListTag nbttaglist = new ListTag(); +- ThreadedLevelLightEngine lightenginethreaded = world.getChunkSource().getLightEngine(); +- boolean flag = chunk.isLightCorrect(); ++ ThreadedLevelLightEngine lightenginethreaded = worldserver.getChunkSource().getLightEngine(); ++ boolean flag = ichunkaccess.isLightCorrect(); + + CompoundTag nbttagcompound2; + +- for (int i = -1; i < 17; ++i) { ++ for (int i = -1; i < 17; ++i) { // Paper - conflict on loop parameter change + int finalI = i; // CraftBukkit - decompile errors + LevelChunkSection chunksection = (LevelChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { + return chunksection1 != null && chunksection1.bottomBlockY() >> 4 == finalI; // CraftBukkit - decompile errors + }).findFirst().orElse(LevelChunk.EMPTY_SECTION); +- DataLayer nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); +- DataLayer nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); +- ++ // Paper start - async chunk save for unload ++ DataLayer nibblearray; // block light ++ DataLayer nibblearray1; // sky light ++ if (asyncsavedata == null) { ++ nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); /// Paper - diff on method change (see getAsyncSaveData) ++ nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); // Paper - diff on method change (see getAsyncSaveData) ++ } else { ++ nibblearray = asyncsavedata.blockLight[i + 1]; // +1 to offset the -1 starting index ++ nibblearray1 = asyncsavedata.skyLight[i + 1]; // +1 to offset the -1 starting index ++ } ++ // Paper end + if (chunksection != LevelChunk.EMPTY_SECTION || nibblearray != null || nibblearray1 != null) { + nbttagcompound2 = new CompoundTag(); + nbttagcompound2.putByte("Y", (byte) (i & 255)); +@@ -327,21 +444,21 @@ public class ChunkSerializer { + nbttagcompound1.putBoolean("isLightOn", true); + } + +- ChunkBiomeContainer biomestorage = chunk.getBiomes(); ++ ChunkBiomeContainer biomestorage = ichunkaccess.getBiomes(); + + if (biomestorage != null) { + nbttagcompound1.putIntArray("Biomes", biomestorage.writeBiomes()); + } + + ListTag nbttaglist1 = new ListTag(); +- Iterator iterator = chunk.getBlockEntitiesPos().iterator(); ++ Iterator iterator = ichunkaccess.getBlockEntitiesPos().iterator(); + + CompoundTag nbttagcompound3; + + while (iterator.hasNext()) { + BlockPos blockposition = (BlockPos) iterator.next(); + +- nbttagcompound3 = chunk.getBlockEntityNbtForSaving(blockposition); ++ nbttagcompound3 = ichunkaccess.getBlockEntityNbtForSaving(blockposition); + if (nbttagcompound3 != null) { + nbttaglist1.add(nbttagcompound3); + } +@@ -351,25 +468,25 @@ public class ChunkSerializer { + ListTag nbttaglist2 = new ListTag(); + + java.util.List toUpdate = new java.util.ArrayList<>(); // Paper +- if (chunk.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { +- LevelChunk chunk1 = (LevelChunk) chunk; ++ if (ichunkaccess.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { ++ LevelChunk chunk = (LevelChunk) ichunkaccess; + + // CraftBukkit start - store chunk persistent data in nbt +- if (!chunk1.persistentDataContainer.isEmpty()) { +- nbttagcompound1.put("ChunkBukkitValues", chunk1.persistentDataContainer.toTagCompound()); ++ if (!chunk.persistentDataContainer.isEmpty()) { ++ nbttagcompound1.put("ChunkBukkitValues", chunk.persistentDataContainer.toTagCompound()); + } + // CraftBukkit end + +- chunk1.setLastSaveHadEntities(false); ++ chunk.setLastSaveHadEntities(false); + +- for (int j = 0; j < chunk1.getEntitySlices().length; ++j) { +- Iterator iterator1 = chunk1.getEntitySlices()[j].iterator(); ++ for (int j = 0; j < chunk.getEntitySlices().length; ++j) { ++ Iterator iterator1 = chunk.getEntitySlices()[j].iterator(); + + while (iterator1.hasNext()) { + Entity entity = (Entity) iterator1.next(); + CompoundTag nbttagcompound4 = new CompoundTag(); + // Paper start +- if ((int) Math.floor(entity.getX()) >> 4 != chunk1.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk1.getPos().z) { ++ if (asyncsavedata == null && !entity.removed && (int) Math.floor(entity.getX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk.getPos().z) { + toUpdate.add(entity); + continue; + } +@@ -378,7 +495,7 @@ public class ChunkSerializer { + } + // Paper end + if (entity.save(nbttagcompound4)) { +- chunk1.setLastSaveHadEntities(true); ++ chunk.setLastSaveHadEntities(true); + nbttaglist2.add(nbttagcompound4); + } + } +@@ -386,12 +503,12 @@ public class ChunkSerializer { + + // Paper start - move entities to the correct chunk + for (Entity entity : toUpdate) { +- world.updateChunkPos(entity); ++ worldserver.updateChunkPos(entity); + } + // Paper end + + } else { +- ProtoChunk protochunk = (ProtoChunk) chunk; ++ ProtoChunk protochunk = (ProtoChunk) ichunkaccess; + + nbttaglist2.addAll(protochunk.getEntities()); + nbttagcompound1.put("Lights", packOffsets(protochunk.getPackedLights())); +@@ -412,40 +529,48 @@ public class ChunkSerializer { + } + + nbttagcompound1.put("Entities", nbttaglist2); +- TickList ticklist = chunk.getBlockTicks(); ++ TickList ticklist = ichunkaccess.getBlockTicks(); // Paper - diff on method change (see getAsyncSaveData) + + if (ticklist instanceof ProtoTickList) { + nbttagcompound1.put("ToBeTicked", ((ProtoTickList) ticklist).save()); + } else if (ticklist instanceof ChunkTickList) { + nbttagcompound1.put("TileTicks", ((ChunkTickList) ticklist).save()); ++ // Paper start - async chunk save for unload ++ } else if (asyncsavedata != null) { ++ nbttagcompound1.put("TileTicks", asyncsavedata.blockTickList); ++ // Paper end + } else { +- nbttagcompound1.put("TileTicks", world.getBlockTicks().save(chunkcoordintpair)); ++ nbttagcompound1.put("TileTicks", worldserver.getBlockTicks().save(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) + } + +- TickList ticklist1 = chunk.getLiquidTicks(); ++ TickList ticklist1 = ichunkaccess.getLiquidTicks(); // Paper - diff on method change (see getAsyncSaveData) + + if (ticklist1 instanceof ProtoTickList) { + nbttagcompound1.put("LiquidsToBeTicked", ((ProtoTickList) ticklist1).save()); + } else if (ticklist1 instanceof ChunkTickList) { + nbttagcompound1.put("LiquidTicks", ((ChunkTickList) ticklist1).save()); ++ // Paper start - async chunk save for unload ++ } else if (asyncsavedata != null) { ++ nbttagcompound1.put("LiquidTicks", asyncsavedata.fluidTickList); ++ // Paper end + } else { +- nbttagcompound1.put("LiquidTicks", world.getLiquidTicks().save(chunkcoordintpair)); ++ nbttagcompound1.put("LiquidTicks", worldserver.getLiquidTicks().save(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) + } + +- nbttagcompound1.put("PostProcessing", packOffsets(chunk.getPostProcessing())); ++ nbttagcompound1.put("PostProcessing", packOffsets(ichunkaccess.getPostProcessing())); + nbttagcompound2 = new CompoundTag(); +- Iterator iterator2 = chunk.getHeightmaps().iterator(); ++ Iterator iterator2 = ichunkaccess.getHeightmaps().iterator(); + + while (iterator2.hasNext()) { + Entry entry = (Entry) iterator2.next(); + +- if (chunk.getStatus().heightmapsAfter().contains(entry.getKey())) { ++ if (ichunkaccess.getStatus().heightmapsAfter().contains(entry.getKey())) { + nbttagcompound2.put(((Heightmap.Types) entry.getKey()).getSerializationKey(), new LongArrayTag(((Heightmap) entry.getValue()).getRawData())); + } + } + + nbttagcompound1.put("Heightmaps", nbttagcompound2); +- nbttagcompound1.put("Structures", packStructureData(chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences())); ++ nbttagcompound1.put("Structures", packStructureData(chunkcoordintpair, ichunkaccess.getAllStarts(), ichunkaccess.getAllReferences())); + return nbttagcompound; + } + // Paper start - this is saved with the player +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +index 9cffef2098fbfba89ddd88a45bde33c07660497a..684442b7175e30b6d4cafb2f7d2d4c10517cc33d 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -3,6 +3,10 @@ package net.minecraft.world.level.chunk.storage; + import com.mojang.datafixers.DataFixer; + import java.io.File; + import java.io.IOException; ++// Paper start ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.CompletionException; ++// Paper end + import java.util.function.Supplier; + import javax.annotation.Nullable; + import net.minecraft.SharedConstants; +@@ -21,32 +25,41 @@ import net.minecraft.world.level.storage.DimensionDataStorage; + + public class ChunkStorage implements AutoCloseable { + +- private final IOWorker worker; public IOWorker getIOWorker() { return worker; } // Paper - OBFHELPER ++ // Paper - OBFHELPER - nuke IOWorker + protected final DataFixer fixerUpper; + @Nullable +- private LegacyStructureDataHandler legacyStructureHandler; ++ private volatile LegacyStructureDataHandler legacyStructureHandler; // Paper - async chunk loading ++ ++ private final Object persistentDataLock = new Object(); // Paper ++ public final RegionFileStorage regionFileCache; + + public ChunkStorage(File file, DataFixer datafixer, boolean flag) { ++ this.regionFileCache = new RegionFileStorage(file, flag); // Paper - nuke IOWorker + this.fixerUpper = datafixer; +- this.worker = new IOWorker(file, flag, "chunk"); ++ // Paper - nuke IOWorker + } + + // CraftBukkit start + private boolean check(ServerChunkCache cps, int x, int z) throws IOException { + ChunkPos pos = new ChunkPos(x, z); + if (cps != null) { +- com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); +- if (cps.hasChunk(x, z)) { ++ //com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe ++ if (cps.getChunkAtIfCachedImmediately(x, z) != null) { // Paper - isLoaded is a ticket level check, not a chunk loaded check! + return true; + } + } + +- CompoundTag nbt = read(pos); +- if (nbt != null) { +- CompoundTag level = nbt.getCompound("Level"); +- if (level.getBoolean("TerrainPopulated")) { +- return true; +- } ++ ++ // Paper start - prioritize ++ CompoundTag nbt = cps == null ? read(pos) : ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.loadChunkData((ServerLevel)cps.getLevel(), x, z, ++ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHER_PRIORITY, false, true).chunkData; ++ // Paper end ++ if (nbt != null) { ++ CompoundTag level = nbt.getCompound("Level"); ++ if (level.getBoolean("TerrainPopulated")) { ++ return true; ++ } + + ChunkStatus status = ChunkStatus.byName(level.getString("Status")); + if (status != null && status.isOrAfter(ChunkStatus.FEATURES)) { +@@ -77,11 +90,13 @@ public class ChunkStorage implements AutoCloseable { + if (i < 1493) { + nbttagcompound = NbtUtils.update(this.fixerUpper, DataFixTypes.CHUNK, nbttagcompound, i, 1493); + if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { ++ synchronized (this.persistentDataLock) { // Paper - Async chunk loading + if (this.legacyStructureHandler == null) { + this.legacyStructureHandler = LegacyStructureDataHandler.getLegacyStructureHandler(resourcekey, (DimensionDataStorage) supplier.get()); + } + + nbttagcompound = this.legacyStructureHandler.updateFromLegacy(nbttagcompound); ++ } // Paper - Async chunk loading + } + } + +@@ -99,22 +114,20 @@ public class ChunkStorage implements AutoCloseable { + + @Nullable + public CompoundTag read(ChunkPos chunkcoordintpair) throws IOException { +- return this.worker.load(chunkcoordintpair); ++ return this.regionFileCache.read(chunkcoordintpair); + } + +- public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) { +- this.worker.store(chunkcoordintpair, nbttagcompound); ++ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER ++ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) ++ this.regionFileCache.write(chunkcoordintpair, nbttagcompound); + if (this.legacyStructureHandler != null) { ++ synchronized (this.persistentDataLock) { // Paper - Async chunk loading + this.legacyStructureHandler.removeIndex(chunkcoordintpair.toLong()); ++ } // Paper - Async chunk loading} + } +- +- } +- +- public void flushWorker() { +- this.worker.synchronize().join(); + } + + public void close() throws IOException { +- this.worker.close(); ++ this.regionFileCache.close(); + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 4d96e5ed28c910387c0a4238c9036c7a12458f57..7ecde2cb15fa0b1b5195fc560c559f2c367e336f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -45,6 +45,8 @@ public class RegionFile implements AutoCloseable { + protected final RegionBitmap usedSectors; + public final File file; // Paper + ++ public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper ++ + // Paper start - Cache chunk status + private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; + +@@ -251,7 +253,7 @@ public class RegionFile implements AutoCloseable { + return (byteCount + 4096 - 1) / 4096; + } + +- public boolean doesChunkExist(ChunkPos pos) { ++ public synchronized boolean doesChunkExist(ChunkPos pos) { // Paper - synchronized + int i = this.getOffset(pos); + + if (i == 0) { +@@ -411,6 +413,11 @@ public class RegionFile implements AutoCloseable { + } + + public void close() throws IOException { ++ // Paper start - Prevent regionfiles from being closed during use ++ this.fileLock.lock(); ++ synchronized (this) { ++ try { ++ // Paper end + this.closed = true; // Paper + try { + this.padToFullSector(); +@@ -421,6 +428,10 @@ public class RegionFile implements AutoCloseable { + this.file.close(); + } + } ++ } finally { // Paper start - Prevent regionfiles from being closed during use ++ this.fileLock.unlock(); ++ } ++ } // Paper end + + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index 6f1c96e4325caf6b4762700ad2286d9ea41515c9..0498982ac14f20145d68dbf64a46bcaacf5516ef 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -17,7 +17,7 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.util.ExceptionCollector; + import net.minecraft.world.level.ChunkPos; + +-public final class RegionFileStorage implements AutoCloseable { ++public class RegionFileStorage implements AutoCloseable { // Paper - no final + + public final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap(); + private final File folder; +@@ -30,16 +30,27 @@ public final class RegionFileStorage implements AutoCloseable { + + + // Paper start +- public RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { ++ public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { // Paper - synchronize for async io + return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); + } + + // Paper end +- public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public ++ public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public, synchronize ++ // Paper start - add lock parameter ++ return this.getFile(chunkcoordintpair, existingOnly, false); ++ } ++ public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly, boolean lock) throws IOException { ++ // Paper end + long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); + RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); + + if (regionfile != null) { ++ // Paper start ++ if (lock) { ++ // must be in this synchronized block ++ regionfile.fileLock.lock(); ++ } ++ // Paper end + return regionfile; + } else { + if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable +@@ -55,6 +66,12 @@ public final class RegionFileStorage implements AutoCloseable { + RegionFile regionfile1 = new RegionFile(file, this.folder, this.sync); + + this.regionCache.putAndMoveToFirst(i, regionfile1); ++ // Paper start ++ if (lock) { ++ // must be in this synchronized block ++ regionfile1.fileLock.lock(); ++ } ++ // Paper end + return regionfile1; + } + } +@@ -130,11 +147,12 @@ public final class RegionFileStorage implements AutoCloseable { + @Nullable + public CompoundTag read(ChunkPos pos) throws IOException { + // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing +- RegionFile regionfile = this.getFile(pos, true); ++ RegionFile regionfile = this.getFile(pos, true, true); // Paper + if (regionfile == null) { + return null; + } + // CraftBukkit end ++ try { // Paper + DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); + // Paper start + if (regionfile.isOversized(pos.x, pos.z)) { +@@ -172,10 +190,14 @@ public final class RegionFileStorage implements AutoCloseable { + } + + return nbttagcompound; ++ } finally { // Paper start ++ regionfile.fileLock.unlock(); ++ } // Paper end + } + + protected void write(ChunkPos pos, CompoundTag tag) throws IOException { +- RegionFile regionfile = this.getFile(pos, false); // CraftBukkit ++ RegionFile regionfile = this.getFile(pos, false, true); // CraftBukkit // Paper ++ try { // Paper + int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper + DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(pos); + Throwable throwable = null; +@@ -214,9 +236,12 @@ public final class RegionFileStorage implements AutoCloseable { + MinecraftServer.LOGGER.error("Failed to save chunk", laste); + } + // Paper end ++ } finally { // Paper start ++ regionfile.fileLock.unlock(); ++ } // Paper end + } + +- public void close() throws IOException { ++ public synchronized void close() throws IOException { // Paper -> synchronized + ExceptionCollector exceptionsuppressor = new ExceptionCollector<>(); + ObjectIterator objectiterator = this.regionCache.values().iterator(); + +@@ -243,4 +268,12 @@ public final class RegionFileStorage implements AutoCloseable { + } + + } ++ ++ // CraftBukkit start ++ public synchronized boolean chunkExists(ChunkPos pos) throws IOException { // Paper - synchronize ++ RegionFile regionfile = getFile(pos, true); ++ ++ return regionfile != null ? regionfile.hasChunk(pos) : false; ++ } ++ // CraftBukkit end + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java +index 059a658aa87d19025daa66d98f78112d5f5be4e3..bb30fb085a6c5edb717ad006c0ab481723ca1b6b 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java +@@ -30,28 +30,29 @@ import net.minecraft.world.level.Level; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +-public class SectionStorage implements AutoCloseable { ++public class SectionStorage extends RegionFileStorage implements AutoCloseable { // Paper - nuke IOWorker + + private static final Logger LOGGER = LogManager.getLogger(); +- private final IOWorker worker; ++ // Paper - nuke IOWorker + private final Long2ObjectMap> storage = new Long2ObjectOpenHashMap(); +- private final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet(); ++ public final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet(); // Paper - private -> public + private final Function> codec; + private final Function factory; + private final DataFixer fixerUpper; + private final DataFixTypes type; + + public SectionStorage(File directory, Function> codecFactory, Function factory, DataFixer datafixer, DataFixTypes datafixtypes, boolean flag) { ++ super(directory, flag); // Paper - nuke IOWorker + this.codec = codecFactory; + this.factory = factory; + this.fixerUpper = datafixer; + this.type = datafixtypes; +- this.worker = new IOWorker(directory, flag, directory.getName()); ++ //this.b = new IOWorker(file, flag, file.getName()); // Paper - nuke IOWorker + } + + protected void tick(BooleanSupplier shouldKeepTicking) { + while (!this.dirty.isEmpty() && shouldKeepTicking.getAsBoolean()) { +- ChunkPos chunkcoordintpair = SectionPos.of(this.dirty.firstLong()).chunk(); ++ ChunkPos chunkcoordintpair = SectionPos.of(this.dirty.firstLong()).chunk(); // Paper - conflict here to avoid obfhelpers + + this.writeColumn(chunkcoordintpair); + } +@@ -105,13 +106,18 @@ public class SectionStorage implements AutoCloseable { + } + + private void readColumn(ChunkPos chunkcoordintpair) { +- this.readColumn(chunkcoordintpair, NbtOps.INSTANCE, this.tryRead(chunkcoordintpair)); ++ // Paper start - load data in function ++ this.loadInData(chunkcoordintpair, this.tryRead(chunkcoordintpair)); ++ } ++ public void loadInData(ChunkPos chunkPos, CompoundTag compound) { ++ this.readColumn(chunkPos, NbtOps.INSTANCE, compound); ++ // Paper end + } + + @Nullable + private CompoundTag tryRead(ChunkPos pos) { + try { +- return this.worker.load(pos); ++ return this.read(pos); // Paper - nuke IOWorker + } catch (IOException ioexception) { + SectionStorage.LOGGER.error("Error reading chunk {} data from disk", pos, ioexception); + return null; +@@ -157,17 +163,31 @@ public class SectionStorage implements AutoCloseable { + } + + private void writeColumn(ChunkPos chunkcoordintpair) { +- Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); ++ Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); // Paper - conflict here to avoid adding obfhelpers :) + Tag nbtbase = (Tag) dynamic.getValue(); + + if (nbtbase instanceof CompoundTag) { +- this.worker.store(chunkcoordintpair, (CompoundTag) nbtbase); ++ try { this.write(chunkcoordintpair, (CompoundTag) nbtbase); } catch (IOException ioexception) { SectionStorage.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker // TODO make this write async + } else { + SectionStorage.LOGGER.error("Expected compound tag, got {}", nbtbase); + } + + } + ++ // Paper start - internal get data function, copied from above ++ private CompoundTag getDataInternal(ChunkPos chunkcoordintpair) { ++ Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); ++ Tag nbtbase = (Tag) dynamic.getValue(); ++ ++ if (nbtbase instanceof CompoundTag) { ++ return (CompoundTag)nbtbase; ++ } else { ++ SectionStorage.LOGGER.error("Expected compound tag, got {}", nbtbase); ++ } ++ return null; ++ } ++ // Paper end ++ + private Dynamic writeColumn(ChunkPos chunkcoordintpair, DynamicOps dynamicops) { + Map map = Maps.newHashMap(); + +@@ -213,9 +233,9 @@ public class SectionStorage implements AutoCloseable { + public void flush(ChunkPos chunkcoordintpair) { + if (!this.dirty.isEmpty()) { + for (int i = 0; i < 16; ++i) { +- long j = SectionPos.of(chunkcoordintpair, i).asLong(); ++ long j = SectionPos.of(chunkcoordintpair, i).asLong(); // Paper - conflict here to avoid obfhelpers + +- if (this.dirty.contains(j)) { ++ if (this.dirty.contains(j)) { // Paper - conflict here to avoid obfhelpers + this.writeColumn(chunkcoordintpair); + return; + } +@@ -224,7 +244,26 @@ public class SectionStorage implements AutoCloseable { + + } + +- public void close() throws IOException { +- this.worker.close(); ++// Paper start - nuke IOWorker ++// public void close() throws IOException { ++// this.b.close(); ++// } ++// Paper end ++ ++ // Paper start - get data function ++ public CompoundTag getData(ChunkPos chunkcoordintpair) { ++ // Note: Copied from above ++ // This is checking if the data exists, then it builds it later in getDataInternal(ChunkCoordIntPair) ++ if (!this.dirty.isEmpty()) { ++ for (int i = 0; i < 16; ++i) { ++ long j = SectionPos.of(chunkcoordintpair, i).asLong(); ++ ++ if (this.dirty.contains(j)) { ++ return this.getDataInternal(chunkcoordintpair); ++ } ++ } ++ } ++ return null; + } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index a0615e4ba015cca4fe074de63b87d0bff84b1a14..52444619a4bae80a12bf296fbe07fa811adf806e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -545,22 +545,23 @@ public class CraftWorld implements World { + return true; + } + +- net.minecraft.world.level.chunk.storage.RegionFile file; +- try { +- file = world.getChunkSource().chunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); +- } catch (IOException ex) { +- throw new RuntimeException(ex); +- } ++ ChunkStatus status = world.getChunkSource().chunkMap.getStatusOnDiskNoLoad(x, z); // Paper - async io - move to own method + +- ChunkStatus status = file.getStatusIfCached(x, z); +- if (!file.hasChunk(chunkPos) || (status != null && status != ChunkStatus.FULL)) { ++ // Paper start - async io ++ if (status == ChunkStatus.EMPTY) { ++ // does not exist on disk + return false; + } + ++ if (status == null) { // at this stage we don't know what it is on disk + ChunkAccess chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.EMPTY, true); + if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof net.minecraft.world.level.chunk.LevelChunk)) { + return false; + } ++ } else if (status != ChunkStatus.FULL) { ++ return false; // not full status on disk ++ } ++ // Paper end + + // fall through to load + // we do this so we do not re-read the chunk data on disk +@@ -2483,6 +2484,34 @@ public class CraftWorld implements World { + public DragonBattle getEnderDragonBattle() { + return (getHandle().dragonFight() == null) ? null : new CraftDragonBattle(getHandle().dragonFight()); + } ++ // Paper start ++ @Override ++ public CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { ++ if (Bukkit.isPrimaryThread()) { ++ net.minecraft.world.level.chunk.LevelChunk immediate = this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); ++ if (immediate != null) { ++ return CompletableFuture.completedFuture(immediate.getBukkitChunk()); ++ } ++ } else { ++ CompletableFuture future = new CompletableFuture(); ++ world.getServer().execute(() -> { ++ getChunkAtAsync(x, z, gen, urgent).whenComplete((chunk, err) -> { ++ if (err != null) { ++ future.completeExceptionally(err); ++ } else { ++ future.complete(chunk); ++ } ++ }); ++ }); ++ return future; ++ } ++ ++ return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { ++ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); ++ return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); ++ }, net.minecraft.server.MinecraftServer.getServer()); ++ } ++ // Paper end + + // Spigot start + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 7ad4fb57af32cc1b8278688381e1b058ed8437db..76d652386806fd11961611486a1d0a12fe9616a4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -11,7 +11,9 @@ import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.Component; ++import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.TicketType; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AreaEffectCloud; + import net.minecraft.world.entity.Entity; +@@ -508,6 +510,28 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + entity.setYHeadRot(yaw); + } + ++ @Override// Paper start ++ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ ChunkMap playerChunkMap = ((CraftWorld) loc.getWorld()).getHandle().getChunkSource().chunkMap; ++ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); ++ ++ loc.getWorld().getChunkAtAsyncUrgently(loc).thenCompose(chunk -> { ++ ChunkCoordIntPair pair = new ChunkCoordIntPair(chunk.getX(), chunk.getZ()); ++ ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().addTicketAtLevel(TicketType.POST_TELEPORT, pair, 31, 0); ++ PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pair.pair()); ++ if (updatingChunk != null) { ++ return updatingChunk.getEntityTickingFuture(); ++ } else { ++ return java.util.concurrent.CompletableFuture.completedFuture(com.mojang.datafixers.util.Either.left(((org.bukkit.craftbukkit.CraftChunk)chunk).getHandle())); ++ } ++ }).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { ++ future.completeExceptionally(ex); ++ return null; ++ }); ++ return future; ++ } ++ // Paper end ++ + @Override + public boolean teleport(Location location) { + return teleport(location, TeleportCause.PLUGIN); +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 16f6163bb53e73aa4ab6e22365342613b6b38118..33a66322d253c7562ae5acbdbc6cc87f7d72a9af 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -6,6 +6,7 @@ import java.lang.management.ThreadInfo; + import java.util.logging.Level; + import java.util.logging.Logger; + import com.destroystokyo.paper.PaperConfig; ++import com.destroystokyo.paper.io.chunk.ChunkTaskManager; // Paper + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; + +@@ -116,6 +117,7 @@ public class WatchdogThread extends Thread + // Paper end - Different message for short timeout + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper ++ ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // diff --git a/patches/server-remapped/0369-Use-getChunkIfLoadedImmediately-in-places.patch b/patches/server-remapped/0369-Use-getChunkIfLoadedImmediately-in-places.patch new file mode 100644 index 0000000000..3becb4b6e9 --- /dev/null +++ b/patches/server-remapped/0369-Use-getChunkIfLoadedImmediately-in-places.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 8 Jul 2019 00:13:36 -0700 +Subject: [PATCH] Use getChunkIfLoadedImmediately in places + +This prevents us from hitting chunk loads for chunks at or less-than +ticket level 33 (yes getChunkIfLoaded will actually perform a chunk +load in that case). + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 95eff4f6165024d21e5c4268a9ae1b7a4268de4b..9d4c81a4964317a0726171dc6d490d12bd959cc4 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -201,7 +201,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI +- return this.chunkSource.getChunk(x, z, false); ++ return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper + } + + // Paper start - Asynchronous IO +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 5dd99709d6b0ed15bbcee184fe33a28bc1c19dac..e45690b6197335ed1c07fa04c39b311b401724d7 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1242,7 +1242,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + speed = player.abilities.walkingSpeed * 10f; + } + // Paper start - Prevent moving into unloaded chunks +- if (player.level.paperConfig.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.hasChunk((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { ++ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && worldserver.getChunkIfLoadedImmediately((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4) == null) { // Paper - use getIfLoadedImmediately + this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.yRot, this.player.xRot, Collections.emptySet()); + return; + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +index d082af8cf4c0c7ca434598aa370712c62e05bb24..b9d32e3322c2cce1aca2a90df71b6175a6f8c548 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +@@ -284,10 +284,10 @@ public class PoiManager extends SectionStorage { + // Paper start - Asynchronous chunk io + @javax.annotation.Nullable + @Override +- public CompoundTag read(ChunkPos chunkcoordintpair) throws java.io.IOException { ++ public CompoundTag read(ChunkPos pos) throws java.io.IOException { + if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { + CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE +- .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), ++ .loadChunkDataAsyncFuture(this.world, pos.x, pos.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), + true, false, true).join().poiData; + + if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { +@@ -295,18 +295,18 @@ public class PoiManager extends SectionStorage { + } + return ret; + } +- return super.read(chunkcoordintpair); ++ return super.read(pos); + } + + @Override +- public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws java.io.IOException { ++ public void write(ChunkPos pos, CompoundTag tag) throws java.io.IOException { + if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( +- this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, ++ this.world, pos.x, pos.z, tag, null, + com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); + return; + } +- super.write(chunkcoordintpair, nbttagcompound); ++ super.write(pos, tag); + } + // Paper end + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 1377465e3dc062f34be25cac10aa018776fb22e7..3a1b9f1ba19b28cebdafeb3b2476217d47213862 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -164,6 +164,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return (CraftServer) Bukkit.getServer(); + } + ++ // Paper start ++ @Override ++ public boolean hasChunk(int chunkX, int chunkZ) { ++ return ((ServerLevel)this).getChunkIfLoaded(chunkX, chunkZ) != null; ++ } ++ // Paper end ++ + public ResourceKey getTypeKey() { + return typeKey; + } +@@ -1190,7 +1197,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + for (int i1 = i; i1 < j; ++i1) { + for (int j1 = k; j1 < l; ++j1) { +- LevelChunk chunk = ichunkprovider.getChunkNow(i1, j1); ++ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { + chunk.getEntitiesOfClass(entityClass, box, list, predicate); +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 0a9bd85e0308e962df3b24a74bd5aac919744d6d..61f180a7c95d83bb88c7df4910c498d9bdf6785a 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -140,9 +140,10 @@ public class ActivationRange + { + for ( int j1 = k; j1 <= l; ++j1 ) + { +- if ( world.getWorld().isChunkLoaded( i1, j1 ) ) ++ LevelChunk chunk = (LevelChunk) world.getChunkIfLoadedImmediately( i1, j1 ); ++ if ( chunk != null ) + { +- activateChunkEntities( world.getChunk( i1, j1 ) ); ++ activateChunkEntities( chunk ); + } + } + } diff --git a/patches/server-remapped/0370-Reduce-sync-loads.patch b/patches/server-remapped/0370-Reduce-sync-loads.patch new file mode 100644 index 0000000000..5349d43158 --- /dev/null +++ b/patches/server-remapped/0370-Reduce-sync-loads.patch @@ -0,0 +1,350 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 19 Jul 2019 03:29:14 -0700 +Subject: [PATCH] Reduce sync loads + +This reduces calls to getChunkAt which would load chunks. + +This patch also adds a tool to find calls which are doing this, however +it must be enabled by setting the startup flag -Dpaper.debug-sync-loads=true + +To get a debug log for sync loads, the command is /paper syncloadinfo + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 62711d95db62221a2e4e6423c518afe13a6c7dbe..ff718bc7f521575e6a670e17fcf59a2d30841705 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -1,12 +1,18 @@ + package com.destroystokyo.paper; + + import com.destroystokyo.paper.io.chunk.ChunkTaskManager; ++import com.destroystokyo.paper.io.SyncLoadFinder; + import com.google.common.base.Functions; + import com.google.common.base.Joiner; + import com.google.common.collect.ImmutableSet; + import com.google.common.collect.Iterables; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; ++import com.google.gson.JsonObject; ++import com.google.gson.internal.Streams; ++import com.google.gson.stream.JsonWriter; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerChunkCache; +@@ -14,7 +20,6 @@ import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; +-import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MCUtil; + import org.apache.commons.lang3.tuple.MutablePair; + import org.apache.commons.lang3.tuple.Pair; +@@ -29,6 +34,9 @@ import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.entity.Player; + + import java.io.File; ++import java.io.FileOutputStream; ++import java.io.PrintStream; ++import java.io.StringWriter; + import java.time.LocalDateTime; + import java.time.format.DateTimeFormatter; + import java.util.ArrayList; +@@ -44,7 +52,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); + + public PaperCommand(String name) { + super(name); +@@ -162,6 +170,9 @@ public class PaperCommand extends Command { + case "chunkinfo": + doChunkInfo(sender, args); + break; ++ case "syncloadinfo": ++ this.doSyncLoadInfo(sender, args); ++ break; + case "ver": + if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) + case "version": +@@ -179,6 +190,40 @@ public class PaperCommand extends Command { + return true; + } + ++ private void doSyncLoadInfo(CommandSender sender, String[] args) { ++ if (!SyncLoadFinder.ENABLED) { ++ sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); ++ return; ++ } ++ File file = new File(new File(new File("."), "debug"), ++ "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); ++ file.getParentFile().mkdirs(); ++ sender.sendMessage(ChatColor.GREEN + "Writing sync load info to " + file.toString()); ++ ++ ++ try { ++ final JsonObject data = SyncLoadFinder.serialize(); ++ ++ StringWriter stringWriter = new StringWriter(); ++ JsonWriter jsonWriter = new JsonWriter(stringWriter); ++ jsonWriter.setIndent(" "); ++ jsonWriter.setLenient(false); ++ Streams.write(data, jsonWriter); ++ ++ String fileData = stringWriter.toString(); ++ ++ try ( ++ PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8") ++ ) { ++ out.print(fileData); ++ } ++ sender.sendMessage(ChatColor.GREEN + "Successfully written sync load information!"); ++ } catch (Throwable thr) { ++ sender.sendMessage(ChatColor.RED + "Failed to write sync load information"); ++ thr.printStackTrace(); ++ } ++ } ++ + private void doChunkInfo(CommandSender sender, String[] args) { + List worlds; + if (args.length < 2 || args[1].equals("*")) { +diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..524f33371b9de1d4dd6972fe59ffbe1804d7c5f3 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java +@@ -0,0 +1,171 @@ ++package com.destroystokyo.paper.io; ++ ++import com.google.gson.JsonArray; ++import com.google.gson.JsonObject; ++import com.mojang.datafixers.util.Pair; ++import it.unimi.dsi.fastutil.longs.Long2IntMap; ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++import java.util.WeakHashMap; ++import net.minecraft.world.level.Level; ++ ++public class SyncLoadFinder { ++ ++ public static final boolean ENABLED = Boolean.getBoolean("paper.debug-sync-loads"); ++ ++ private static final WeakHashMap> SYNC_LOADS = new WeakHashMap<>(); ++ ++ private static final class SyncLoadInformation { ++ ++ public int times; ++ ++ public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); ++ } ++ ++ public static void logSyncLoad(final Level world, final int chunkX, final int chunkZ) { ++ if (!ENABLED) { ++ return; ++ } ++ ++ final ThrowableWithEquals stacktrace = new ThrowableWithEquals(Thread.currentThread().getStackTrace()); ++ ++ SYNC_LOADS.compute(world, (final Level keyInMap, Object2ObjectOpenHashMap map) -> { ++ if (map == null) { ++ map = new Object2ObjectOpenHashMap<>(); ++ } ++ ++ map.compute(stacktrace, (ThrowableWithEquals keyInMap0, SyncLoadInformation valueInMap) -> { ++ if (valueInMap == null) { ++ valueInMap = new SyncLoadInformation(); ++ } ++ ++ ++valueInMap.times; ++ ++ valueInMap.coordinateTimes.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (Long keyInMap1, Integer valueInMap1) -> { ++ return valueInMap1 == null ? Integer.valueOf(1) : Integer.valueOf(valueInMap1.intValue() + 1); ++ }); ++ ++ return valueInMap; ++ }); ++ ++ return map; ++ }); ++ } ++ ++ public static JsonObject serialize() { ++ final JsonObject ret = new JsonObject(); ++ ++ final JsonArray worldsData = new JsonArray(); ++ ++ for (final Map.Entry> entry : SYNC_LOADS.entrySet()) { ++ final Level world = entry.getKey(); ++ ++ final JsonObject worldData = new JsonObject(); ++ ++ worldData.addProperty("name", world.getWorld().getName()); ++ ++ final List> data = new ArrayList<>(); ++ ++ entry.getValue().forEach((ThrowableWithEquals stacktrace, SyncLoadInformation times) -> { ++ data.add(new Pair<>(stacktrace, times)); ++ }); ++ ++ data.sort((Pair pair1, Pair pair2) -> { ++ return Integer.compare(pair2.getSecond().times, pair1.getSecond().times); // reverse order ++ }); ++ ++ final JsonArray stacktraces = new JsonArray(); ++ ++ for (Pair pair : data) { ++ final JsonObject stacktrace = new JsonObject(); ++ ++ stacktrace.addProperty("times", pair.getSecond().times); ++ ++ final JsonArray traces = new JsonArray(); ++ ++ for (StackTraceElement element : pair.getFirst().stacktrace) { ++ traces.add(String.valueOf(element)); ++ } ++ ++ stacktrace.add("stacktrace", traces); ++ ++ final JsonArray coordinates = new JsonArray(); ++ ++ for (Long2IntMap.Entry coordinate : pair.getSecond().coordinateTimes.long2IntEntrySet()) { ++ final long key = coordinate.getLongKey(); ++ final int times = coordinate.getIntValue(); ++ coordinates.add("(" + IOUtil.getCoordinateX(key) + "," + IOUtil.getCoordinateZ(key) + "): " + times); ++ } ++ ++ stacktrace.add("coordinates", coordinates); ++ ++ stacktraces.add(stacktrace); ++ } ++ ++ ++ worldData.add("stacktraces", stacktraces); ++ worldsData.add(worldData); ++ } ++ ++ ret.add("worlds", worldsData); ++ ++ return ret; ++ } ++ ++ static final class ThrowableWithEquals { ++ ++ private final StackTraceElement[] stacktrace; ++ private final int hash; ++ ++ public ThrowableWithEquals(final StackTraceElement[] stacktrace) { ++ this.stacktrace = stacktrace; ++ this.hash = ThrowableWithEquals.hash(stacktrace); ++ } ++ ++ public static int hash(final StackTraceElement[] stacktrace) { ++ int hash = 0; ++ ++ for (int i = 0; i < stacktrace.length; ++i) { ++ hash *= 31; ++ hash += stacktrace[i].hashCode(); ++ } ++ ++ return hash; ++ } ++ ++ @Override ++ public int hashCode() { ++ return this.hash; ++ } ++ ++ @Override ++ public boolean equals(final Object obj) { ++ if (obj == null || obj.getClass() != this.getClass()) { ++ return false; ++ } ++ ++ final ThrowableWithEquals other = (ThrowableWithEquals)obj; ++ final StackTraceElement[] otherStackTrace = other.stacktrace; ++ ++ if (this.stacktrace.length != otherStackTrace.length || this.hash != other.hash) { ++ return false; ++ } ++ ++ if (this == obj) { ++ return true; ++ } ++ ++ for (int i = 0; i < this.stacktrace.length; ++i) { ++ if (!this.stacktrace[i].equals(otherStackTrace[i])) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 120b604d91643248ab375969f95f62a74cbf6be7..5e0d55c3821b1769d20514a8a6c5c74477019778 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -494,6 +494,7 @@ public class ServerChunkCache extends ChunkSource { + this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); + // Paper end ++ com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x1, z1); // Paper - sync load info + this.level.timings.syncChunkLoad.startTiming(); // Paper + this.mainThreadProcessor.managedBlock(completablefuture::isDone); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 9d4c81a4964317a0726171dc6d490d12bd959cc4..01f879a8dd0e1ffec380e02072567330152eaceb 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -276,6 +276,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + }; + public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; + // Paper end ++ // Paper start ++ @Override ++ public boolean hasChunk(int chunkX, int chunkZ) { ++ return this.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ) != null; ++ } ++ // Paper end + + // Add env and gen to constructor, WorldData -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 3a1b9f1ba19b28cebdafeb3b2476217d47213862..3e2cd6c7a34c1a792d7346019a8b039d1f4a7c04 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -1130,7 +1130,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + for (int i1 = i; i1 <= j; ++i1) { + for (int j1 = k; j1 <= l; ++j1) { +- LevelChunk chunk = ichunkprovider.getChunk(i1, j1, false); ++ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { + chunk.getEntities(except, box, list, predicate); +@@ -1151,7 +1151,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + for (int i1 = i; i1 < j; ++i1) { + for (int j1 = k; j1 < l; ++j1) { +- LevelChunk chunk = this.getChunkSource().getChunk(i1, j1, false); ++ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { + chunk.getEntities(type, box, list, predicate); +@@ -1174,7 +1174,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + for (int i1 = i; i1 < j; ++i1) { + for (int j1 = k; j1 < l; ++j1) { +- LevelChunk chunk = ichunkprovider.getChunk(i1, j1, false); ++ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { + chunk.getEntitiesOfClass(entityClass, box, list, predicate); diff --git a/patches/server-remapped/0371-Implement-alternative-item-despawn-rate.patch b/patches/server-remapped/0371-Implement-alternative-item-despawn-rate.patch new file mode 100644 index 0000000000..21aa2f962b --- /dev/null +++ b/patches/server-remapped/0371-Implement-alternative-item-despawn-rate.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Mon, 3 Jun 2019 02:02:39 -0400 +Subject: [PATCH] Implement alternative item-despawn-rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1ee2cced100626e48eb36ee14f84b9257c79a2f8..b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -1,10 +1,15 @@ + package com.destroystokyo.paper; + + import java.util.Arrays; ++import java.util.EnumMap; ++import java.util.HashMap; + import java.util.List; ++import java.util.Map; + + import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; + import org.bukkit.Bukkit; ++import org.bukkit.Material; ++import org.bukkit.configuration.ConfigurationSection; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; + +@@ -512,4 +517,52 @@ public class PaperWorldConfig { + private void disableRelativeProjectileVelocity() { + disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); + } ++ ++ public boolean altItemDespawnRateEnabled; ++ public Map altItemDespawnRateMap; ++ private void altItemDespawnRate() { ++ String path = "alt-item-despawn-rate"; ++ ++ altItemDespawnRateEnabled = getBoolean(path + ".enabled", false); ++ ++ Map altItemDespawnRateMapDefault = new EnumMap<>(Material.class); ++ altItemDespawnRateMapDefault.put(Material.COBBLESTONE, 300); ++ for (Material key : altItemDespawnRateMapDefault.keySet()) { ++ config.addDefault("world-settings.default." + path + ".items." + key, altItemDespawnRateMapDefault.get(key)); ++ } ++ ++ Map rawMap = new HashMap<>(); ++ try { ++ ConfigurationSection mapSection = config.getConfigurationSection("world-settings." + worldName + "." + path + ".items"); ++ if (mapSection == null) { ++ mapSection = config.getConfigurationSection("world-settings.default." + path + ".items"); ++ } ++ for (String key : mapSection.getKeys(false)) { ++ int val = mapSection.getInt(key); ++ rawMap.put(key, val); ++ } ++ } ++ catch (Exception e) { ++ logError("alt-item-despawn-rate was malformatted"); ++ altItemDespawnRateEnabled = false; ++ } ++ ++ altItemDespawnRateMap = new EnumMap<>(Material.class); ++ if (!altItemDespawnRateEnabled) { ++ return; ++ } ++ ++ for(String key : rawMap.keySet()) { ++ try { ++ altItemDespawnRateMap.put(Material.valueOf(key), rawMap.get(key)); ++ } catch (Exception e) { ++ logError("Could not add item " + key + " to altItemDespawnRateMap: " + e.getMessage()); ++ } ++ } ++ if(altItemDespawnRateEnabled) { ++ for(Material key : altItemDespawnRateMap.keySet()) { ++ log("Alternative item despawn rate of " + key + ": " + altItemDespawnRateMap.get(key)); ++ } ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 281f5646980afc70890bdafd358ff9b20d32420d..96b8102773cbee2c3fe2711008ba1487084d67b0 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -32,6 +32,7 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.stats.Stats; ++import org.bukkit.Material; // Paper + import org.bukkit.event.entity.EntityPickupItemEvent; + import org.bukkit.event.player.PlayerPickupItemEvent; + // CraftBukkit end +@@ -160,7 +161,7 @@ public class ItemEntity extends Entity { + } + } + +- if (!this.level.isClientSide && this.age >= level.spigotConfig.itemDespawnRate) { // Spigot ++ if (!this.level.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper + // CraftBukkit start - fire ItemDespawnEvent + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { + this.age = 0; +@@ -184,7 +185,7 @@ public class ItemEntity extends Entity { + this.lastTick = MinecraftServer.currentTick; + // CraftBukkit end + +- if (!this.level.isClientSide && this.age >= level.spigotConfig.itemDespawnRate) { // Spigot ++ if (!this.level.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper + // CraftBukkit start - fire ItemDespawnEvent + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { + this.age = 0; +@@ -534,9 +535,16 @@ public class ItemEntity extends Entity { + + public void makeFakeItem() { + this.setNeverPickUp(); +- this.age = level.spigotConfig.itemDespawnRate - 1; // Spigot ++ this.age = this.getDespawnRate() - 1; // Spigot // Paper + } + ++ // Paper start ++ public int getDespawnRate(){ ++ Material material = this.getItem().getBukkitStack().getType(); ++ return level.paperConfig.altItemDespawnRateMap.getOrDefault(material, level.spigotConfig.itemDespawnRate); ++ } ++ // Paper end ++ + @Override + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this); diff --git a/patches/server-remapped/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/patches/server-remapped/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch new file mode 100644 index 0000000000..eab9bd3397 --- /dev/null +++ b/patches/server-remapped/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paul Sauve +Date: Sun, 14 Jul 2019 21:05:03 -0500 +Subject: [PATCH] Do less work if we have a custom Bukkit generator + +If the Bukkit generator already has a spawn, use it immediately instead +of spending time generating one that we won't use + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 643d75b999c3da006eaaab11f4acd77e807683d4..753e6f609189c589514739bea80007bace3c89d2 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -628,12 +628,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +- return biomebase.getMobSettings().playerSpawnFriendly(); +- }, random); +- ChunkPos chunkcoordintpair = blockposition == null ? new ChunkPos(0, 0) : new ChunkPos(blockposition); ++ // Paper start - moved down + // CraftBukkit start + if (world.generator != null) { + Random rand = new Random(world.getSeed()); +@@ -649,6 +644,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { ++ return biomebase.getMobSettings().playerSpawnFriendly(); ++ }, random); ++ ChunkPos chunkcoordintpair = blockposition == null ? new ChunkPos(0, 0) : new ChunkPos(blockposition); ++ // Paper end + + if (blockposition == null) { + MinecraftServer.LOGGER.warn("Unable to find spawn biome"); diff --git a/patches/server-remapped/0373-Fix-MC-158900.patch b/patches/server-remapped/0373-Fix-MC-158900.patch new file mode 100644 index 0000000000..585e674b4b --- /dev/null +++ b/patches/server-remapped/0373-Fix-MC-158900.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 13 Aug 2019 06:35:17 -0700 +Subject: [PATCH] Fix MC-158900 + +The problem was we were checking isExpired() on the entry, but if it +was expired at that point, then it would be null. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7412765020854caabd32fb6f4fffcf7f4bf6dba7..e6eebb8f6f48cc55fc8fb114c959b8fbec4b8472 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -603,8 +603,10 @@ public abstract class PlayerList { + Player player = entity.getBukkitEntity(); + PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.connection.getRawAddress()).getAddress()); + +- if (getBans().isBanned(gameprofile) && !getBans().get(gameprofile).hasExpired()) { +- UserBanListEntry gameprofilebanentry = (UserBanListEntry) this.bans.get(gameprofile); ++ // Paper start - Fix MC-158900 ++ UserBanListEntry gameprofilebanentry; ++ if (getBans().isBanned(gameprofile) && (gameprofilebanentry = getBans().get(gameprofile)) != null) { ++ // Paper end + + chatmessage = new TranslatableComponent("multiplayer.disconnect.banned.reason", new Object[]{gameprofilebanentry.getReason()}); + if (gameprofilebanentry.getExpires() != null) { diff --git a/patches/server-remapped/0374-implement-optional-per-player-mob-spawns.patch b/patches/server-remapped/0374-implement-optional-per-player-mob-spawns.patch new file mode 100644 index 0000000000..70bcd1b1bd --- /dev/null +++ b/patches/server-remapped/0374-implement-optional-per-player-mob-spawns.patch @@ -0,0 +1,924 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Mon, 19 Aug 2019 01:27:58 +0500 +Subject: [PATCH] implement optional per player mob spawns + + +diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +index 24eac9400fbf971742e89bbf47b0ba52b587c4eb..b818a7451d45d2ab7d4678f0065ada9017d8a631 100644 +--- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java ++++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +@@ -58,6 +58,7 @@ public class WorldTimingsHandler { + + + public final Timing miscMobSpawning; ++ public final Timing playerMobDistanceMapUpdate; + + public final Timing poiUnload; + public final Timing chunkUnload; +@@ -123,6 +124,7 @@ public class WorldTimingsHandler { + + + miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); ++ playerMobDistanceMapUpdate = Timings.ofSafe(name + "Per Player Mob Spawning - Distance Map Update"); + + poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); + chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920..6aec502eb529d4090306e12e837117cde7e114eb 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -565,4 +565,9 @@ public class PaperWorldConfig { + } + } + } ++ ++ public boolean perPlayerMobSpawns = false; ++ private void perPlayerMobSpawns() { ++ perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2a87599922d7075a9f888f48a2deb35ed3eb7c54 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java +@@ -0,0 +1,252 @@ ++package com.destroystokyo.paper.util; ++ ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; ++import java.util.List; ++import java.util.Map; ++import net.minecraft.core.SectionPos; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.level.ChunkPos; ++import org.spigotmc.AsyncCatcher; ++import java.util.HashMap; ++ ++/** @author Spottedleaf */ ++public final class PlayerMobDistanceMap { ++ ++ private static final PooledHashSets.PooledObjectLinkedOpenHashSet EMPTY_SET = new PooledHashSets.PooledObjectLinkedOpenHashSet<>(); ++ ++ private final Map players = new HashMap<>(); ++ // we use linked for better iteration. ++ private final Long2ObjectOpenHashMap> playerMap = new Long2ObjectOpenHashMap<>(32, 0.5f); ++ private int viewDistance; ++ ++ private final PooledHashSets pooledHashSets = new PooledHashSets<>(); ++ ++ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final ChunkPos chunkPos) { ++ return this.getPlayersInRange(chunkPos.x, chunkPos.z); ++ } ++ ++ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final int chunkX, final int chunkZ) { ++ return this.playerMap.getOrDefault(ChunkPos.asLong(chunkX, chunkZ), EMPTY_SET); ++ } ++ ++ public void update(final List currentPlayers, final int newViewDistance) { ++ AsyncCatcher.catchOp("Distance map update"); ++ final ObjectLinkedOpenHashSet gone = new ObjectLinkedOpenHashSet<>(this.players.keySet()); ++ ++ final int oldViewDistance = this.viewDistance; ++ this.viewDistance = newViewDistance; ++ ++ for (final ServerPlayer player : currentPlayers) { ++ if (player.isSpectator() || !player.affectsSpawning) { ++ continue; // will be left in 'gone' (or not added at all) ++ } ++ ++ gone.remove(player); ++ ++ final SectionPos newPosition = player.getPlayerMapSection(); ++ final SectionPos oldPosition = this.players.put(player, newPosition); ++ ++ if (oldPosition == null) { ++ this.addNewPlayer(player, newPosition, newViewDistance); ++ } else { ++ this.updatePlayer(player, oldPosition, newPosition, oldViewDistance, newViewDistance); ++ } ++ //this.validatePlayer(player, newViewDistance); // debug only ++ } ++ ++ for (final ServerPlayer player : gone) { ++ final SectionPos oldPosition = this.players.remove(player); ++ if (oldPosition != null) { ++ this.removePlayer(player, oldPosition, oldViewDistance); ++ } ++ } ++ } ++ ++ // expensive op, only for debug ++ private void validatePlayer(final ServerPlayer player, final int viewDistance) { ++ int entiesGot = 0; ++ int expectedEntries = (2 * viewDistance + 1); ++ expectedEntries *= expectedEntries; ++ ++ final SectionPos currPosition = player.getPlayerMapSection(); ++ ++ final int centerX = currPosition.getX(); ++ final int centerZ = currPosition.getZ(); ++ ++ for (final Long2ObjectLinkedOpenHashMap.Entry> entry : this.playerMap.long2ObjectEntrySet()) { ++ final long key = entry.getLongKey(); ++ final PooledHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); ++ ++ if (map.referenceCount == 0) { ++ throw new IllegalStateException("Invalid map"); ++ } ++ ++ if (map.set.contains(player)) { ++ ++entiesGot; ++ ++ final int chunkX = ChunkPos.getX(key); ++ final int chunkZ = ChunkPos.getZ(key); ++ ++ final int dist = Math.max(Math.abs(chunkX - centerX), Math.abs(chunkZ - centerZ)); ++ ++ if (dist > viewDistance) { ++ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); ++ } ++ } ++ } ++ ++ if (entiesGot != expectedEntries) { ++ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); ++ } ++ } ++ ++ private void addPlayerTo(final ServerPlayer player, final int chunkX, final int chunkZ) { ++ this.playerMap.compute(ChunkPos.asLong(chunkX, chunkZ), (final Long key, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { ++ if (players == null) { ++ return player.cachedSingleMobDistanceMap; ++ } else { ++ return PlayerMobDistanceMap.this.pooledHashSets.findMapWith(players, player); ++ } ++ }); ++ } ++ ++ private void removePlayerFrom(final ServerPlayer player, final int chunkX, final int chunkZ) { ++ this.playerMap.compute(ChunkPos.asLong(chunkX, chunkZ), (final Long keyInMap, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { ++ return PlayerMobDistanceMap.this.pooledHashSets.findMapWithout(players, player); // rets null instead of an empty map ++ }); ++ } ++ ++ private void updatePlayer(final ServerPlayer player, final SectionPos oldPosition, final SectionPos newPosition, final int oldViewDistance, final int newViewDistance) { ++ final int toX = newPosition.getX(); ++ final int toZ = newPosition.getZ(); ++ final int fromX = oldPosition.getX(); ++ final int fromZ = oldPosition.getZ(); ++ ++ final int dx = toX - fromX; ++ final int dz = toZ - fromZ; ++ ++ final int totalX = Math.abs(fromX - toX); ++ final int totalZ = Math.abs(fromZ - toZ); ++ ++ if (Math.max(totalX, totalZ) > (2 * oldViewDistance)) { ++ // teleported? ++ this.removePlayer(player, oldPosition, oldViewDistance); ++ this.addNewPlayer(player, newPosition, newViewDistance); ++ return; ++ } ++ ++ // x axis is width ++ // z axis is height ++ // right refers to the x axis of where we moved ++ // top refers to the z axis of where we moved ++ ++ if (oldViewDistance == newViewDistance) { ++ // same view distance ++ ++ // used for relative positioning ++ final int up = 1 | (dz >> (Integer.SIZE - 1)); // 1 if dz >= 0, -1 otherwise ++ final int right = 1 | (dx >> (Integer.SIZE - 1)); // 1 if dx >= 0, -1 otherwise ++ ++ // The area excluded by overlapping the two view distance squares creates four rectangles: ++ // Two on the left, and two on the right. The ones on the left we consider the "removed" section ++ // and on the right the "added" section. ++ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually ++ // exclusive to the regions they surround. ++ ++ // 4 points of the rectangle ++ int maxX; // exclusive ++ int minX; // inclusive ++ int maxZ; // exclusive ++ int minZ; // inclusive ++ ++ if (dx != 0) { ++ // handle right addition ++ ++ maxX = toX + (oldViewDistance * right) + right; // exclusive ++ minX = fromX + (oldViewDistance * right) + right; // inclusive ++ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive ++ minZ = toZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.addPlayerTo(player, currX, currZ); ++ } ++ } ++ } ++ ++ if (dz != 0) { ++ // handle up addition ++ ++ maxX = toX + (oldViewDistance * right) + right; // exclusive ++ minX = toX - (oldViewDistance * right); // inclusive ++ maxZ = toZ + (oldViewDistance * up) + up; // exclusive ++ minZ = fromZ + (oldViewDistance * up) + up; // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.addPlayerTo(player, currX, currZ); ++ } ++ } ++ } ++ ++ if (dx != 0) { ++ // handle left removal ++ ++ maxX = toX - (oldViewDistance * right); // exclusive ++ minX = fromX - (oldViewDistance * right); // inclusive ++ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive ++ minZ = toZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.removePlayerFrom(player, currX, currZ); ++ } ++ } ++ } ++ ++ if (dz != 0) { ++ // handle down removal ++ ++ maxX = fromX + (oldViewDistance * right) + right; // exclusive ++ minX = fromX - (oldViewDistance * right); // inclusive ++ maxZ = toZ - (oldViewDistance * up); // exclusive ++ minZ = fromZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.removePlayerFrom(player, currX, currZ); ++ } ++ } ++ } ++ } else { ++ // different view distance ++ // for now :) ++ this.removePlayer(player, oldPosition, oldViewDistance); ++ this.addNewPlayer(player, newPosition, newViewDistance); ++ } ++ } ++ ++ private void removePlayer(final ServerPlayer player, final SectionPos position, final int viewDistance) { ++ final int x = position.getX(); ++ final int z = position.getZ(); ++ ++ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { ++ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { ++ this.removePlayerFrom(player, x + xoff, z + zoff); ++ } ++ } ++ } ++ ++ private void addNewPlayer(final ServerPlayer player, final SectionPos position, final int viewDistance) { ++ final int x = position.getX(); ++ final int z = position.getZ(); ++ ++ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { ++ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { ++ this.addPlayerTo(player, x + xoff, z + zoff); ++ } ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4f13d3ff8391793a99f067189f854078334499c6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java +@@ -0,0 +1,241 @@ ++package com.destroystokyo.paper.util; ++ ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; ++import java.lang.ref.WeakReference; ++import java.util.Iterator; ++ ++/** @author Spottedleaf */ ++public class PooledHashSets { ++ ++ // we really want to avoid that equals() check as much as possible... ++ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(64, 0.25f); ++ ++ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { ++ if (current.referenceCount == 0) { ++ throw new IllegalStateException("Cannot decrement reference count for " + current); ++ } ++ if (current.referenceCount == -1 || --current.referenceCount > 0) { ++ return; ++ } ++ ++ this.mapPool.remove(current); ++ return; ++ } ++ ++ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { ++ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); ++ ++ if (cached != null) { ++ if (cached.referenceCount != -1) { ++ ++cached.referenceCount; ++ } ++ ++ decrementReferenceCount(current); ++ ++ return cached; ++ } ++ ++ if (!current.add(object)) { ++ return current; ++ } ++ ++ // we use get/put since we use a different key on put ++ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); ++ ++ if (ret == null) { ++ ret = new PooledObjectLinkedOpenHashSet<>(current); ++ current.remove(object); ++ this.mapPool.put(ret, ret); ++ ret.referenceCount = 1; ++ } else { ++ if (ret.referenceCount != -1) { ++ ++ret.referenceCount; ++ } ++ current.remove(object); ++ } ++ ++ current.updateAddCache(object, ret); ++ ++ decrementReferenceCount(current); ++ return ret; ++ } ++ ++ // rets null if current.size() == 1 ++ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { ++ if (current.set.size() == 1) { ++ decrementReferenceCount(current); ++ return null; ++ } ++ ++ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); ++ ++ if (cached != null) { ++ if (cached.referenceCount != -1) { ++ ++cached.referenceCount; ++ } ++ ++ decrementReferenceCount(current); ++ ++ return cached; ++ } ++ ++ if (!current.remove(object)) { ++ return current; ++ } ++ ++ // we use get/put since we use a different key on put ++ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); ++ ++ if (ret == null) { ++ ret = new PooledObjectLinkedOpenHashSet<>(current); ++ current.add(object); ++ this.mapPool.put(ret, ret); ++ ret.referenceCount = 1; ++ } else { ++ if (ret.referenceCount != -1) { ++ ++ret.referenceCount; ++ } ++ current.add(object); ++ } ++ ++ current.updateRemoveCache(object, ret); ++ ++ decrementReferenceCount(current); ++ return ret; ++ } ++ ++ public static final class PooledObjectLinkedOpenHashSet implements Iterable { ++ ++ private static final WeakReference NULL_REFERENCE = new WeakReference(null); ++ ++ final ObjectLinkedOpenHashSet set; ++ int referenceCount; // -1 if special ++ int hash; // optimize hashcode ++ ++ // add cache ++ WeakReference lastAddObject = NULL_REFERENCE; ++ WeakReference> lastAddMap = NULL_REFERENCE; ++ ++ // remove cache ++ WeakReference lastRemoveObject = NULL_REFERENCE; ++ WeakReference> lastRemoveMap = NULL_REFERENCE; ++ ++ public PooledObjectLinkedOpenHashSet() { ++ this.set = new ObjectLinkedOpenHashSet<>(2, 0.6f); ++ } ++ ++ public PooledObjectLinkedOpenHashSet(final E single) { ++ this(); ++ this.referenceCount = -1; ++ this.add(single); ++ } ++ ++ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { ++ this.set = other.set.clone(); ++ this.hash = other.hash; ++ } ++ ++ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java ++ // generated by https://github.com/skeeto/hash-prospector ++ static int hash0(int x) { ++ x *= 0x36935555; ++ x ^= x >>> 16; ++ return x; ++ } ++ ++ public PooledObjectLinkedOpenHashSet getAddCache(final E element) { ++ final E currentAdd = this.lastAddObject.get(); ++ ++ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { ++ return null; ++ } ++ ++ final PooledObjectLinkedOpenHashSet map = this.lastAddMap.get(); ++ if (map == null || map.referenceCount == 0) { ++ // we need to ret null if ref count is zero as calling code will assume the map is in use ++ return null; ++ } ++ ++ return map; ++ } ++ ++ public PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { ++ final E currentRemove = this.lastRemoveObject.get(); ++ ++ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { ++ return null; ++ } ++ ++ final PooledObjectLinkedOpenHashSet map = this.lastRemoveMap.get(); ++ if (map == null || map.referenceCount == 0) { ++ // we need to ret null if ref count is zero as calling code will assume the map is in use ++ return null; ++ } ++ ++ return map; ++ } ++ ++ public void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { ++ this.lastAddObject = new WeakReference<>(element); ++ this.lastAddMap = new WeakReference<>(map); ++ } ++ ++ public void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { ++ this.lastRemoveObject = new WeakReference<>(element); ++ this.lastRemoveMap = new WeakReference<>(map); ++ } ++ ++ boolean add(final E element) { ++ boolean added = this.set.add(element); ++ ++ if (added) { ++ this.hash += hash0(element.hashCode()); ++ } ++ ++ return added; ++ } ++ ++ boolean remove(Object element) { ++ boolean removed = this.set.remove(element); ++ ++ if (removed) { ++ this.hash -= hash0(element.hashCode()); ++ } ++ ++ return removed; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return this.set.iterator(); ++ } ++ ++ @Override ++ public int hashCode() { ++ return this.hash; ++ } ++ ++ @Override ++ public boolean equals(final Object other) { ++ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { ++ return false; ++ } ++ if (this.referenceCount == 0) { ++ return other == this; ++ } else { ++ if (other == this) { ++ // Unfortunately we are never equal to our own instance while in use! ++ return false; ++ } ++ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); ++ } ++ } ++ ++ @Override ++ public String toString() { ++ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + ++ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index c00f7c60ce7b497d697d1abdf230f91f327e2113..190ddd4d9ef3472c33d46c2ead72fa0dc918054a 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -71,6 +71,7 @@ import net.minecraft.util.thread.ProcessorMailbox; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.MobCategory; + import net.minecraft.world.entity.ai.village.poi.PoiManager; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.level.ChunkPos; +@@ -127,7 +128,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final Int2ObjectMap entityMap; + private final Long2ByteMap chunkTypeCache; + private final Queue unloadQueue; private final Queue getUnloadQueueTasks() { return this.unloadQueue; } // Paper - OBFHELPER +- private int viewDistance; ++ int viewDistance; // Paper - private -> package private ++ public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper + + // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() + public final CallbackExecutor callbackExecutor = new CallbackExecutor(); +@@ -206,6 +208,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.overworldDataStorage = supplier; + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper + this.setViewDistance(i); ++ this.playerMobDistanceMap = this.level.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper ++ } ++ ++ public void updatePlayerMobTypeMap(Entity entity) { ++ if (!this.level.paperConfig.perPlayerMobSpawns) { ++ return; ++ } ++ int chunkX = (int)Math.floor(entity.getX()) >> 4; ++ int chunkZ = (int)Math.floor(entity.getZ()) >> 4; ++ int index = entity.getType().getEnumCreatureType().ordinal(); ++ ++ for (ServerPlayer player : this.playerMobDistanceMap.getPlayersInRange(chunkX, chunkZ)) { ++ ++player.mobCounts[index]; ++ } ++ } ++ ++ public int getMobCountNear(ServerPlayer entityPlayer, MobCategory enumCreatureType) { ++ return entityPlayer.mobCounts[enumCreatureType.ordinal()]; + } + + private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 5e0d55c3821b1769d20514a8a6c5c74477019778..eac5e799c4d26e53286a27c54b56899ba0b9ffb2 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -768,7 +768,22 @@ public class ServerChunkCache extends ChunkSource { + this.level.getProfiler().push("naturalSpawnCount"); + this.level.timings.countNaturalMobs.startTiming(); // Paper - timings + int l = this.distanceManager.getNaturalSpawnChunkCount(); +- NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk); ++ // Paper start - per player mob spawning ++ NaturalSpawner.SpawnState spawnercreature_d; // moved down ++ if (this.chunkMap.playerMobDistanceMap != null) { ++ // update distance map ++ this.level.timings.playerMobDistanceMapUpdate.startTiming(); ++ this.chunkMap.playerMobDistanceMap.update(this.level.players, this.chunkMap.viewDistance); ++ this.level.timings.playerMobDistanceMapUpdate.stopTiming(); ++ // re-set mob counts ++ for (ServerPlayer player : this.level.players) { ++ Arrays.fill(player.mobCounts, 0); ++ } ++ spawnercreature_d = NaturalSpawner.countMobs(l, this.level.getAllEntities(), this::getFullChunk, true); ++ } else { ++ spawnercreature_d = NaturalSpawner.countMobs(l, this.level.getAllEntities(), this::getFullChunk, false); ++ } ++ // Paper end + this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings + + this.lastSpawnState = spawnercreature_d; +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index d6cfe68be1a944ff5d5780666467f5fd8e2794e3..b0eed4e18fc183856613c05f378576eb19985c46 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -93,6 +93,7 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.HumanoidArm; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.MobCategory; + import net.minecraft.world.entity.NeutralMob; + import net.minecraft.world.entity.animal.horse.AbstractHorse; + import net.minecraft.world.entity.item.ItemEntity; +@@ -216,6 +217,11 @@ public class ServerPlayer extends Player implements ContainerListener { + public boolean queueHealthUpdatePacket = false; + public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; + // Paper end ++ // Paper start - mob spawning rework ++ public static final int ENUMCREATURETYPE_TOTAL_ENUMS = MobCategory.values().length; ++ public final int[] mobCounts = new int[ENUMCREATURETYPE_TOTAL_ENUMS]; // Paper ++ public final com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet cachedSingleMobDistanceMap; ++ // Paper end + + // CraftBukkit start + public String displayName; +@@ -254,6 +260,7 @@ public class ServerPlayer extends Player implements ContainerListener { + this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper + this.canPickUpLoot = true; + this.maxHealthCache = this.getMaxHealth(); ++ this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper + } + + // Yes, this doesn't match Vanilla, but it's the best we can do for now. +@@ -2058,6 +2065,7 @@ public class ServerPlayer extends Player implements ContainerListener { + + } + ++ public final SectionPos getPlayerMapSection() { return this.getLastSectionPos(); } // Paper - OBFHELPER + public SectionPos getLastSectionPos() { + return this.lastSectionPos; + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index e39d950783599b01271bdb7e67fe68b46af0c49c..ae50030df7512c56c552e800b74ef4c69ec6d6d2 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -426,6 +426,7 @@ public class EntityType { + return this.canSpawnFarFromPlayer; + } + ++ public final MobCategory getEnumCreatureType() { return this.getCategory(); } // Paper - OBFHELPER + public MobCategory getCategory() { + return this.category; + } +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index 0fb69f9194078e5e05e36ed909eb48424b6465b4..df271598f6036c8cab8a8811151a376dda46e44d 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -17,6 +17,7 @@ import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.FluidTags; + import net.minecraft.tags.Tag; +@@ -60,9 +61,14 @@ public final class NaturalSpawner { + }); + + public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkSource) { ++ // Paper start - add countMobs parameter ++ return countMobs(spawningChunkCount, entities, chunkSource, false); ++ } ++ public static NaturalSpawner.SpawnState countMobs(int i, Iterable iterable, NaturalSpawner.ChunkGetter spawnercreature_b, boolean countMobs) { ++ // Paper end - add countMobs parameter + PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator(); + Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); +- Iterator iterator = entities.iterator(); ++ Iterator iterator = iterable.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +@@ -89,7 +95,7 @@ public final class NaturalSpawner { + BlockPos blockposition = entity.blockPosition(); + long j = ChunkPos.asLong(blockposition.getX() >> 4, blockposition.getZ() >> 4); + +- chunkSource.query(j, (chunk) -> { ++ spawnercreature_b.query(j, (chunk) -> { + MobSpawnSettings.MobSpawnCost biomesettingsmobs_b = getRoughBiome(blockposition, chunk).getMobSettings().getMobSpawnCost(entity.getType()); + + if (biomesettingsmobs_b != null) { +@@ -97,11 +103,16 @@ public final class NaturalSpawner { + } + + object2intopenhashmap.addTo(enumcreaturetype, 1); ++ // Paper start ++ if (countMobs) { ++ ((ServerLevel)chunk.world).getChunkSource().chunkMap.updatePlayerMobTypeMap(entity); ++ } ++ // Paper end + }); + } + } + +- return new NaturalSpawner.SpawnState(spawningChunkCount, object2intopenhashmap, spawnercreatureprobabilities); ++ return new NaturalSpawner.SpawnState(i, object2intopenhashmap, spawnercreatureprobabilities); + } + + private static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) { +@@ -155,13 +166,31 @@ public final class NaturalSpawner { + continue; + } + +- if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (shouldSpawnAnimals || !enumcreaturetype.isPersistent()) && info.a(enumcreaturetype, limit)) { ++ // Paper start - only allow spawns upto the limit per chunk and update count afterwards ++ int currEntityCount = info.getEntityCountsByType().getInt(enumcreaturetype); ++ int k1 = limit * info.getSpawnerChunks() / NaturalSpawner.MAGIC_NUMBER; ++ int difference = k1 - currEntityCount; ++ ++ if (world.paperConfig.perPlayerMobSpawns) { ++ int minDiff = Integer.MAX_VALUE; ++ for (ServerPlayer entityplayer : world.getChunkSource().chunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) { ++ minDiff = Math.min(limit - world.getChunkSource().chunkMap.getMobCountNear(entityplayer, enumcreaturetype), minDiff); ++ } ++ difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff; ++ } ++ // Paper end ++ ++ // Paper start - per player mob spawning ++ if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (shouldSpawnAnimals || !enumcreaturetype.isPersistent()) && difference > 0) { + // CraftBukkit end +- spawnCategoryForChunk(enumcreaturetype, world, chunk, (entitytypes, blockposition, ichunkaccess) -> { ++ int spawnCount = spawnMobs(enumcreaturetype, world, chunk, (entitytypes, blockposition, ichunkaccess) -> { + return info.canSpawn(entitytypes, blockposition, ichunkaccess); + }, (entityinsentient, ichunkaccess) -> { + info.afterSpawn(entityinsentient, ichunkaccess); +- }); ++ }, ++ difference, world.paperConfig.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null); ++ info.getEntityCountsByType().mergeInt(enumcreaturetype, spawnCount, Integer::sum); ++ // Paper end - per player mob spawning + } + } + +@@ -170,31 +199,43 @@ public final class NaturalSpawner { + } + + public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { +- BlockPos blockposition = getRandomPosWithin(world, chunk); ++ // Paper start - add parameters and int ret type ++ spawnMobs(group, world, chunk, checker, runner, Integer.MAX_VALUE, null); ++ } ++ public static int spawnMobs(MobCategory enumcreaturetype, ServerLevel worldserver, LevelChunk chunk, NaturalSpawner.SpawnPredicate spawnercreature_c, NaturalSpawner.AfterSpawnCallback spawnercreature_a, int maxSpawns, Consumer trackEntity) { ++ // Paper end - add parameters and int ret type ++ BlockPos blockposition = getRandomPosWithin(worldserver, chunk); + + if (blockposition.getY() >= 1) { +- spawnCategoryForPosition(group, world, (ChunkAccess) chunk, blockposition, checker, runner); ++ return spawnMobsInternal(enumcreaturetype, worldserver, (ChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a, maxSpawns, trackEntity); + } ++ return 0; // Paper + } + + public static void spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { +- StructureFeatureManager structuremanager = world.structureFeatureManager(); +- ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); +- int i = pos.getY(); +- BlockState iblockdata = world.getTypeIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn +- +- if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn ++ // Paper start - add maxSpawns parameter and return spawned mobs ++ spawnMobsInternal(group, world, chunk, pos, checker, runner, Integer.MAX_VALUE, null); ++ } ++ public static int spawnMobsInternal(MobCategory enumcreaturetype, ServerLevel worldserver, ChunkAccess ichunkaccess, BlockPos blockposition, NaturalSpawner.SpawnPredicate spawnercreature_c, NaturalSpawner.AfterSpawnCallback spawnercreature_a, int maxSpawns, Consumer trackEntity) { ++ // Paper end - add maxSpawns parameter and return spawned mobs ++ StructureFeatureManager structuremanager = worldserver.structureFeatureManager(); ++ ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); ++ int i = blockposition.getY(); ++ BlockState iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn ++ int j = 0; // Paper - moved up ++ ++ if (iblockdata != null && !iblockdata.isRedstoneConductor(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn + BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); +- int j = 0; ++ // Paper - moved up + int k = 0; + + while (k < 3) { +- int l = pos.getX(); +- int i1 = pos.getZ(); ++ int l = blockposition.getX(); ++ int i1 = blockposition.getZ(); + boolean flag = true; + MobSpawnSettings.SpawnerData biomesettingsmobs_c = null; + SpawnGroupData groupdataentity = null; +- int j1 = Mth.ceil(world.random.nextFloat() * 4.0F); ++ int j1 = Mth.ceil(worldserver.random.nextFloat() * 4.0F); + int k1 = 0; + int l1 = 0; + +@@ -202,53 +243,58 @@ public final class NaturalSpawner { + if (l1 < j1) { + label53: + { +- l += world.random.nextInt(6) - world.random.nextInt(6); +- i1 += world.random.nextInt(6) - world.random.nextInt(6); ++ l += worldserver.random.nextInt(6) - worldserver.random.nextInt(6); ++ i1 += worldserver.random.nextInt(6) - worldserver.random.nextInt(6); + blockposition_mutableblockposition.set(l, i, i1); + double d0 = (double) l + 0.5D; + double d1 = (double) i1 + 0.5D; +- Player entityhuman = world.getNearestPlayer(d0, (double) i, d1, -1.0D, false); ++ Player entityhuman = worldserver.getNearestPlayer(d0, (double) i, d1, -1.0D, false); + + if (entityhuman != null) { + double d2 = entityhuman.distanceToSqr(d0, (double) i, d1); + +- if (isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2) && world.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn ++ if (isRightDistanceToPlayerAndSpawnPoint(worldserver, ichunkaccess, blockposition_mutableblockposition, d2) && worldserver.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn + if (biomesettingsmobs_c == null) { +- biomesettingsmobs_c = getRandomSpawnMobAt(world, structuremanager, chunkgenerator, group, world.random, (BlockPos) blockposition_mutableblockposition); ++ biomesettingsmobs_c = getRandomSpawnMobAt(worldserver, structuremanager, chunkgenerator, enumcreaturetype, worldserver.random, (BlockPos) blockposition_mutableblockposition); + if (biomesettingsmobs_c == null) { + break label53; + } + +- j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); ++ j1 = biomesettingsmobs_c.minCount + worldserver.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); + } + + // Paper start +- Boolean doSpawning = a(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); ++ Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); + if (doSpawning == null) { +- return; ++ return j; // Paper + } +- if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, ichunkaccess)) { + // Paper end +- Mob entityinsentient = getMobForSpawn(world, biomesettingsmobs_c.type); ++ Mob entityinsentient = getMobForSpawn(worldserver, biomesettingsmobs_c.type); + + + if (entityinsentient == null) { +- return; ++ return j; // Paper + } + +- entityinsentient.moveTo(d0, (double) i, d1, world.random.nextFloat() * 360.0F, 0.0F); +- if (isValidPositionForMob(world, entityinsentient, d2)) { +- groupdataentity = entityinsentient.finalizeSpawn(world, world.getCurrentDifficultyAt(entityinsentient.blockPosition()), MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); ++ entityinsentient.moveTo(d0, (double) i, d1, worldserver.random.nextFloat() * 360.0F, 0.0F); ++ if (isValidPositionForMob(worldserver, entityinsentient, d2)) { ++ groupdataentity = entityinsentient.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(entityinsentient.blockPosition()), MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); + // CraftBukkit start +- world.addAllEntities(entityinsentient, SpawnReason.NATURAL); ++ worldserver.addAllEntities(entityinsentient, SpawnReason.NATURAL); + if (!entityinsentient.removed) { +- ++j; ++ ++j; // Paper - force diff on name change - we expect this to be the total amount spawned + ++k1; +- runner.run(entityinsentient, chunk); ++ spawnercreature_a.run(entityinsentient, ichunkaccess); ++ // Paper start ++ if (trackEntity != null) { ++ trackEntity.accept(entityinsentient); ++ } ++ // Paper end + } + // CraftBukkit end +- if (j >= entityinsentient.getMaxSpawnClusterSize()) { +- return; ++ if (j >= entityinsentient.getMaxSpawnClusterSize() || j >= maxSpawns) { // Paper ++ return j; // Paper + } + + if (entityinsentient.isMaxGroupSizeReached(k1)) { +@@ -270,6 +316,7 @@ public final class NaturalSpawner { + } + + } ++ return j; // Paper + } + + private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) { +@@ -510,8 +557,8 @@ public final class NaturalSpawner { + + public static class SpawnState { + +- private final int spawnableChunkCount; +- private final Object2IntOpenHashMap mobCategoryCounts; ++ private final int spawnableChunkCount; final int getSpawnerChunks() { return this.spawnableChunkCount; } // Paper - OBFHELPER ++ private final Object2IntOpenHashMap mobCategoryCounts; final Object2IntMap getEntityCountsByType() { return this.mobCategoryCounts; } // Paper - OBFHELPER + private final PotentialCalculator spawnPotential; + private final Object2IntMap unmodifiableMobCategoryCounts; + @Nullable +@@ -572,7 +619,7 @@ public final class NaturalSpawner { + + // CraftBukkit start + private boolean a(MobCategory enumcreaturetype, int limit) { +- int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; ++ int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; // Paper - diff on change, needed in the spawn method + // CraftBukkit end + + return this.mobCategoryCounts.getInt(enumcreaturetype) < i; diff --git a/patches/server-remapped/0375-Prevent-consuming-the-wrong-itemstack.patch b/patches/server-remapped/0375-Prevent-consuming-the-wrong-itemstack.patch new file mode 100644 index 0000000000..32aa3ddc1d --- /dev/null +++ b/patches/server-remapped/0375-Prevent-consuming-the-wrong-itemstack.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Mon, 19 Aug 2019 19:42:35 +0500 +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 046a05925739005080af35c4be984303b575bf68..f8917123547615dd624e3e428ec1bf6450c7b7d8 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3198,15 +3198,18 @@ public abstract class LivingEntity extends Entity { + this.entityData.set(LivingEntity.DATA_LIVING_ENTITY_FLAGS, (byte) j); + } + +- public void startUsingItem(InteractionHand hand) { +- ItemStack itemstack = this.getItemInHand(hand); ++ // Paper start -- OBFHELPER and forwarder to method with forceUpdate parameter ++ public void startUsingItem(InteractionHand hand) { this.updateActiveItem(hand, false); } ++ public void updateActiveItem(InteractionHand enumhand, boolean forceUpdate) { ++ // Paper end ++ ItemStack itemstack = this.getItemInHand(enumhand); + +- if (!itemstack.isEmpty() && !this.isUsingItem()) { ++ if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag + this.useItem = itemstack; + this.useItemRemaining = itemstack.getUseDuration(); + if (!this.level.isClientSide) { + this.setLivingEntityFlag(1, true); +- this.setLivingEntityFlag(2, hand == InteractionHand.OFF_HAND); ++ this.setLivingEntityFlag(2, enumhand == InteractionHand.OFF_HAND); + } + + } +@@ -3279,6 +3282,7 @@ public abstract class LivingEntity extends Entity { + this.releaseUsingItem(); + } else { + if (!this.useItem.isEmpty() && this.isUsingItem()) { ++ this.updateActiveItem(this.getUsedItemHand(), true); // Paper + this.triggerItemUseEffects(this.useItem, 16); + // CraftBukkit start - fire PlayerItemConsumeEvent + ItemStack itemstack; +@@ -3313,8 +3317,8 @@ public abstract class LivingEntity extends Entity { + } + + this.stopUsingItem(); +- // Paper start - if the replacement is anything but the default, update the client inventory +- if (this instanceof ServerPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { ++ // Paper start ++ if (this instanceof ServerPlayer) { + ((ServerPlayer) this).getBukkitEntity().updateInventory(); + } + // Paper end diff --git a/patches/server-remapped/0376-Generator-Settings.patch b/patches/server-remapped/0376-Generator-Settings.patch new file mode 100644 index 0000000000..fe0b780b55 --- /dev/null +++ b/patches/server-remapped/0376-Generator-Settings.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 2 Mar 2016 02:17:54 -0600 +Subject: [PATCH] Generator Settings + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6aec502eb529d4090306e12e837117cde7e114eb..290e49cf0077909ad7ab8127c01ef93cf7b70b51 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -570,4 +570,9 @@ public class PaperWorldConfig { + private void perPlayerMobSpawns() { + perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); + } ++ ++ public boolean generateFlatBedrock; ++ private void generatorSettings() { ++ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index e6303cdb433ee2b6782e2a0bd6b03e4f6ecb18ba..36c7ab3919d8818af96d50170aeb431051c5aabf 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -25,6 +25,18 @@ import org.apache.logging.log4j.LogManager; + + public interface ChunkAccess extends BlockGetter, FeatureAccess { + ++ // Paper start ++ default boolean generateFlatBedrock() { ++ if (this instanceof ProtoChunk) { ++ return ((ProtoChunk)this).world.paperConfig.generateFlatBedrock; ++ } else if (this instanceof LevelChunk) { ++ return ((LevelChunk)this).world.paperConfig.generateFlatBedrock; ++ } else { ++ return false; ++ } ++ } ++ // Paper end ++ + BlockState getType(final int x, final int y, final int z); // Paper + @Nullable + BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index 87fd585141ad9818fca0b697cb4c87248fe7ce11..5a94464b9628b74eefa1c1d8514cf267f4c8a11d 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -64,7 +64,7 @@ public class ProtoChunk implements ChunkAccess { + private long inhabitedTime; + private final Map carvingMasks; + private volatile boolean isLightCorrect; +- private final Level world; // Paper - Anti-Xray - Add world ++ final Level world; // Paper - Anti-Xray - Add world // Paper - private -> default + + // Paper start - Anti-Xray - Add world + @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { this(pos, upgradeData, null); } // Notice for updates: Please make sure this constructor isn't used anywhere +diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +index b38a9c87fc996bd3107c38f6446a687fd093c617..04adec255e4650ead8d80bee32a681c98686fb95 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +@@ -408,8 +408,8 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + int i = chunk.getPos().getMinBlockX(); + int j = chunk.getPos().getMinBlockZ(); + NoiseGeneratorSettings generatorsettingbase = (NoiseGeneratorSettings) this.settings.get(); +- int k = generatorsettingbase.getBedrockFloorPosition(); +- int l = this.height - 1 - generatorsettingbase.getBedrockRoofPosition(); ++ int k = generatorsettingbase.getBedrockFloorPosition(); final int floorHeight = k; // Paper ++ int l = this.height - 1 - generatorsettingbase.getBedrockRoofPosition(); final int roofHeight = l; // Paper + boolean flag = true; + boolean flag1 = l + 4 >= 0 && l < this.height; + boolean flag2 = k + 4 >= 0 && k < this.height; +@@ -423,7 +423,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + + if (flag1) { + for (i1 = 0; i1 < 5; ++i1) { +- if (i1 <= random.nextInt(5)) { ++ if (i1 <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof + chunk.setBlockState(blockposition_mutableblockposition.set(blockposition.getX(), l - i1, blockposition.getZ()), Blocks.BEDROCK.defaultBlockState(), false); + } + } +@@ -431,7 +431,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + + if (flag2) { + for (i1 = 4; i1 >= 0; --i1) { +- if (i1 <= random.nextInt(5)) { ++ if (i1 <= (chunk.generateFlatBedrock() ? floorHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor + chunk.setBlockState(blockposition_mutableblockposition.set(blockposition.getX(), k + i1, blockposition.getZ()), Blocks.BEDROCK.defaultBlockState(), false); + } + } diff --git a/patches/server-remapped/0377-Fix-MC-161754.patch b/patches/server-remapped/0377-Fix-MC-161754.patch new file mode 100644 index 0000000000..c50817dd4f --- /dev/null +++ b/patches/server-remapped/0377-Fix-MC-161754.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 24 Sep 2019 16:03:00 -0700 +Subject: [PATCH] Fix MC-161754 + +Fixes https://github.com/PaperMC/Paper/issues/2580 + +We can use an entity valid check since this method is invoked for +each inventory iteraction (thanks to CB) and on player tick (vanilla). + +diff --git a/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java b/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java +index 7246b3a84415e303591adb08d81362201deebfce..e0237e821b2c31ba68168fddf1c1a4ebfcf10ca7 100644 +--- a/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java +@@ -85,7 +85,7 @@ public class HorseInventoryMenu extends AbstractContainerMenu { + + @Override + public boolean stillValid(Player player) { +- return this.horseContainer.stillValid(player) && this.horse.isAlive() && this.horse.distanceTo((Entity) player) < 8.0F; ++ return this.horseContainer.stillValid(player) && (this.horse.isAlive() && this.horse.valid) && this.horse.distanceTo((Entity) player) < 8.0F; // Paper - Fix MC-161754 + } + + @Override diff --git a/patches/server-remapped/0378-Performance-improvement-for-Chunk.getEntities.patch b/patches/server-remapped/0378-Performance-improvement-for-Chunk.getEntities.patch new file mode 100644 index 0000000000..439bca032a --- /dev/null +++ b/patches/server-remapped/0378-Performance-improvement-for-Chunk.getEntities.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: wea_ondara +Date: Thu, 10 Oct 2019 11:29:42 +0200 +Subject: [PATCH] Performance improvement for Chunk.getEntities + +This patch aims to reduce performance cost used by collecting the +entities of a chunk. Previously the entitySlices were copied into an +extra array with List.toArray() with is a costly and unneccessary +operation. This patch will reduce the load of plugins which for example +implement custom moblimits and depend on Chunk.getEntities(). + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +index 74bad15034d9d55fb70931f38868f812160c6305..0f45f4b2486e910d11fd94b260bcd68e49eae31e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +@@ -116,14 +116,14 @@ public class CraftChunk implements Chunk { + Entity[] entities = new Entity[count]; + + for (int i = 0; i < 16; i++) { +- +- for (Object obj : chunk.entitySlices[i].toArray()) { +- if (!(obj instanceof net.minecraft.world.entity.Entity)) { ++ // Paper start - speed up (was with chunk.entitySlices[i].toArray() and cast checks which costs a lot of performance if called often) ++ for (net.minecraft.world.entity.Entity entity : chunk.entitySlices[i]) { ++ if (entity == null) { + continue; + } +- +- entities[index++] = ((net.minecraft.world.entity.Entity) obj).getBukkitEntity(); ++ entities[index++] = entity.getBukkitEntity(); + } ++ // Paper end + } + + return entities; diff --git a/patches/server-remapped/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/patches/server-remapped/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch new file mode 100644 index 0000000000..548deb2cdf --- /dev/null +++ b/patches/server-remapped/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MisterErwin +Date: Wed, 30 Oct 2019 16:57:54 +0100 +Subject: [PATCH] Fix spawning of hanging entities that are not ItemFrames and + can not face UP or DOWN + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 52444619a4bae80a12bf296fbe07fa811adf806e..fb74bdcf4c2935b56e92717cc5a1504fbc853d0a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1868,7 +1868,12 @@ public class CraftWorld implements World { + height = 9; + } + +- BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; ++ // Paper start - In addition to d65a2576e40e58c8e446b330febe6799d13a604f do not check UP/DOWN for non item frames ++ // BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; ++ BlockFace[] faces = (ItemFrame.class.isAssignableFrom(clazz)) ++ ? new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN} ++ : new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH}; ++ // Paper end + final BlockPos pos = new BlockPos(x, y, z); + for (BlockFace dir : faces) { + net.minecraft.world.level.block.state.BlockState nmsBlock = world.getBlockState(pos.relative(CraftBlock.blockFaceToNotch(dir))); diff --git a/patches/server-remapped/0380-Expose-the-internal-current-tick.patch b/patches/server-remapped/0380-Expose-the-internal-current-tick.patch new file mode 100644 index 0000000000..9cf110529d --- /dev/null +++ b/patches/server-remapped/0380-Expose-the-internal-current-tick.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 20 Apr 2019 19:47:34 -0500 +Subject: [PATCH] Expose the internal current tick + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 96a3a4d89df858d4e46a36f110dd9ad3a2061433..3c0ba80bbba19f3725013e118cecdbac5612deec 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2363,5 +2363,10 @@ public final class CraftServer implements Server { + } + return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); + } ++ ++ @Override ++ public int getCurrentTick() { ++ return net.minecraft.server.MinecraftServer.currentTick; ++ } + // Paper end + } diff --git a/patches/server-remapped/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/patches/server-remapped/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch new file mode 100644 index 0000000000..169ff964a9 --- /dev/null +++ b/patches/server-remapped/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 9 Oct 2019 21:51:43 -0500 +Subject: [PATCH] Fix stuck in sneak when changing worlds (MC-10657) + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index b0eed4e18fc183856613c05f378576eb19985c46..2ef273e3b917803f3e2ac3c6a22d92a15b9eb71a 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1070,6 +1070,8 @@ public class ServerPlayer extends Player implements ContainerListener { + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; + ++ setShiftKeyDown(false); // Paper - fix MC-10657 ++ + // CraftBukkit start + PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); + this.level.getCraftServer().getPluginManager().callEvent(changeEvent); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index e6eebb8f6f48cc55fc8fb114c959b8fbec4b8472..dfdde9722bc0d83916779014b7718eef2c01b3db 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -842,6 +842,8 @@ public abstract class PlayerList { + entityplayer.connection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobEffect)); + } + ++ entityplayer.setShiftKeyDown(false); // Paper - fix MC-10657 ++ + // Fire advancement trigger + entityplayer.triggerDimensionChangeTriggers(((CraftWorld) fromWorld).getHandle()); + diff --git a/patches/server-remapped/0382-Add-option-to-disable-pillager-patrols.patch b/patches/server-remapped/0382-Add-option-to-disable-pillager-patrols.patch new file mode 100644 index 0000000000..2e772d88a3 --- /dev/null +++ b/patches/server-remapped/0382-Add-option-to-disable-pillager-patrols.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 9 Oct 2019 21:46:15 -0500 +Subject: [PATCH] Add option to disable pillager patrols + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 290e49cf0077909ad7ab8127c01ef93cf7b70b51..e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -575,4 +575,9 @@ public class PaperWorldConfig { + private void generatorSettings() { + generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); + } ++ ++ public boolean disablePillagerPatrols = false; ++ private void pillagerSettings() { ++ disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +index caadd1a0fa6c4c446f84629088890a09e29622d9..48efe133d294bb1b17e8ac8b44eea8a29f15845f 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +@@ -26,6 +26,7 @@ public class PatrolSpawner implements CustomSpawner { + + @Override + public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { ++ if (world.paperConfig.disablePillagerPatrols) return 0; // Paper + if (!spawnMonsters) { + return 0; + } else if (!world.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) { diff --git a/patches/server-remapped/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/patches/server-remapped/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch new file mode 100644 index 0000000000..3d4d87429f --- /dev/null +++ b/patches/server-remapped/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lukasz Derlatka +Date: Mon, 11 Nov 2019 16:08:13 +0100 +Subject: [PATCH] Fix AssertionError when player hand set to empty type + +Fixes an AssertionError when setting the player's item in hand to null or a new ItemStack of Air in PlayerInteractEvent +Fixes GH-2718 + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index e45690b6197335ed1c07fa04c39b311b401724d7..2b79413bb8a592a7b7093e11d3a0cce895286c8f 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1706,6 +1706,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 + return; + } ++ // Paper start ++ itemstack = this.player.getItemInHand(enumhand); ++ if (itemstack.isEmpty()) return; ++ // Paper end + InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); + + if (enuminteractionresult.shouldSwing()) { +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index f8917123547615dd624e3e428ec1bf6450c7b7d8..b49d4772932a58852b3195f5f56ff93dbcabf766 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -2153,6 +2153,7 @@ public abstract class LivingEntity extends Entity { + return predicate.test(this.getMainHandItem().getItem()) || predicate.test(this.getOffhandItem().getItem()); + } + ++ public final ItemStack getItemInHand(InteractionHand enumhand) { return this.getItemInHand(enumhand); } // Paper - OBFHELPER + public ItemStack getItemInHand(InteractionHand hand) { + if (hand == InteractionHand.MAIN_HAND) { + return this.getItemBySlot(EquipmentSlot.MAINHAND); diff --git a/patches/server-remapped/0384-PlayerLaunchProjectileEvent.patch b/patches/server-remapped/0384-PlayerLaunchProjectileEvent.patch new file mode 100644 index 0000000000..886004a317 --- /dev/null +++ b/patches/server-remapped/0384-PlayerLaunchProjectileEvent.patch @@ -0,0 +1,351 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 03:11:03 -0500 +Subject: [PATCH] PlayerLaunchProjectileEvent + + +diff --git a/src/main/java/net/minecraft/world/InteractionResultHolder.java b/src/main/java/net/minecraft/world/InteractionResultHolder.java +index 3bc22b977e00c1901a9025112e354e59fcc08a74..c12e2a65d30ca22db0c522e4b245009bcc38c4f4 100644 +--- a/src/main/java/net/minecraft/world/InteractionResultHolder.java ++++ b/src/main/java/net/minecraft/world/InteractionResultHolder.java +@@ -10,6 +10,7 @@ public class InteractionResultHolder { + this.object = value; + } + ++ public InteractionResult getResult() { return this.getResult(); } // Paper - OBFHELPER + public InteractionResult getResult() { + return this.result; + } +diff --git a/src/main/java/net/minecraft/world/item/EggItem.java b/src/main/java/net/minecraft/world/item/EggItem.java +index d2c4241104343a2d2283c358ab2247e333cf0dbf..5d03dcaf79a14946934a6732c94a195d3d65c56d 100644 +--- a/src/main/java/net/minecraft/world/item/EggItem.java ++++ b/src/main/java/net/minecraft/world/item/EggItem.java +@@ -25,21 +25,35 @@ public class EggItem extends Item { + + entityegg.setItem(itemstack); + entityegg.shootFromRotation(user, user.xRot, user.yRot, 0.0F, 1.5F, 1.0F); +- // CraftBukkit start +- if (!world.addFreshEntity(entityegg)) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityegg.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entityegg)) { ++ if (event.shouldConsume() && !user.abilities.instabuild) { ++ itemstack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ } else { + if (user instanceof net.minecraft.server.level.ServerPlayer) { + ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); + } +- return InteractionResultHolder.fail(itemstack); ++ return new InteractionResultHolder(net.minecraft.world.InteractionResult.FAIL, itemstack); + } +- // CraftBukkit end ++ // Paper end ++ ++ + } + world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (EggItem.random.nextFloat() * 0.4F + 0.8F)); // CraftBukkit - from above + +- user.awardStat(Stats.ITEM_USED.get(this)); +- if (!user.abilities.instabuild) { +- itemstack.shrink(1); ++ /* // Paper start - moved up ++ entityhuman.b(StatisticList.ITEM_USED.b(this)); ++ if (!entityhuman.abilities.canInstantlyBuild) { ++ itemstack.subtract(1); + } ++ */ // Paper end + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/EnderpearlItem.java b/src/main/java/net/minecraft/world/item/EnderpearlItem.java +index 347e95cc393e773de98b74e18cebbe05f612bdf6..a57c59b330766a2c784ddb7431719e9c1cc2fca8 100644 +--- a/src/main/java/net/minecraft/world/item/EnderpearlItem.java ++++ b/src/main/java/net/minecraft/world/item/EnderpearlItem.java +@@ -25,22 +25,37 @@ public class EnderpearlItem extends Item { + + entityenderpearl.setItem(itemstack); + entityenderpearl.shootFromRotation(user, user.xRot, user.yRot, 0.0F, 1.5F, 1.0F); +- if (!world.addFreshEntity(entityenderpearl)) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityenderpearl.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entityenderpearl)) { ++ if (event.shouldConsume() && !user.abilities.instabuild) { ++ itemstack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ user.getCooldowns().addCooldown(this, 20); ++ } else { ++ // Paper end + if (user instanceof net.minecraft.server.level.ServerPlayer) { + ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); + } +- return InteractionResultHolder.fail(itemstack); ++ return new InteractionResultHolder(net.minecraft.world.InteractionResult.FAIL, itemstack); + } + } + +- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (EnderpearlItem.random.nextFloat() * 0.4F + 0.8F)); +- user.getCooldowns().addCooldown(this, 20); +- // CraftBukkit end +- +- user.awardStat(Stats.ITEM_USED.get(this)); +- if (!user.abilities.instabuild) { +- itemstack.shrink(1); +- } ++ // Paper start - moved up ++// world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F)); ++// entityhuman.getCooldownTracker().setCooldown(this, 20); ++// // CraftBukkit end ++// ++// entityhuman.b(StatisticList.ITEM_USED.b(this)); ++// if (!entityhuman.abilities.canInstantlyBuild) { ++// itemstack.subtract(1); ++// } ++ // Paper end - moved up + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java +index 032c476892c58a873242b00ca71fe084c719dcaa..0bd65165eacf6a54cdcc348991cf9adb44077bee 100644 +--- a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java ++++ b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java +@@ -1,10 +1,13 @@ + package net.minecraft.world.item; + ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.world.InteractionHand; ++import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.ThrownExperienceBottle; + import net.minecraft.world.level.Level; +@@ -24,19 +27,38 @@ public class ExperienceBottleItem extends Item { + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { + ItemStack itemstack = user.getItemInHand(hand); + +- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (ExperienceBottleItem.random.nextFloat() * 0.4F + 0.8F)); ++ //world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); // Paper - moved down + if (!world.isClientSide) { + ThrownExperienceBottle entitythrownexpbottle = new ThrownExperienceBottle(world, user); + + entitythrownexpbottle.setItem(itemstack); + entitythrownexpbottle.shootFromRotation(user, user.xRot, user.yRot, -20.0F, 0.7F, 1.0F); +- world.addFreshEntity(entitythrownexpbottle); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitythrownexpbottle.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entitythrownexpbottle)) { ++ if (event.shouldConsume() && !user.abilities.instabuild) { ++ itemstack.shrink(1); ++ } else if (user instanceof ServerPlayer) { ++ ((ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ } else { ++ if (user instanceof ServerPlayer) { ++ ((ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ return new InteractionResultHolder(InteractionResult.FAIL, itemstack); ++ } ++ // Paper end + } + +- user.awardStat(Stats.ITEM_USED.get(this)); +- if (!user.abilities.instabuild) { +- itemstack.shrink(1); ++ /* // Paper start - moved up ++ entityhuman.b(StatisticList.ITEM_USED.b(this)); ++ if (!entityhuman.abilities.canInstantlyBuild) { ++ itemstack.subtract(1); + } ++ */ // Paper end + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index 28cffbe299acccc59c34d5dbd2cf458704be5ee5..4a70582bada607e1efcd826d58d725a0cc95e3c3 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -3,6 +3,7 @@ package net.minecraft.world.item; + import java.util.Arrays; + import java.util.Comparator; + import net.minecraft.core.Direction; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.InteractionHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; +@@ -29,8 +30,12 @@ public class FireworkRocketItem extends Item { + FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, context.getPlayer(), vec3d.x + (double) enumdirection.getStepX() * 0.15D, vec3d.y + (double) enumdirection.getStepY() * 0.15D, vec3d.z + (double) enumdirection.getStepZ() * 0.15D, itemstack); + entityfireworks.spawningEntity = context.getPlayer().getUUID(); // Paper + +- world.addFreshEntity(entityfireworks); +- itemstack.shrink(1); ++ // Paper start - PlayerLaunchProjectileEvent ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) context.getPlayer().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); ++ if (!event.callEvent() || !world.addFreshEntity(entityfireworks)) return InteractionResult.PASS; ++ if (event.shouldConsume() && !context.getPlayer().abilities.instabuild) itemstack.shrink(1); ++ else if (context.getPlayer() instanceof ServerPlayer) ((ServerPlayer) context.getPlayer()).getBukkitEntity().updateInventory(); ++ // Paper end + } + + return InteractionResult.sidedSuccess(world.isClientSide); +@@ -50,9 +55,9 @@ public class FireworkRocketItem extends Item { + if (event.callEvent() && world.addFreshEntity(entityfireworks)) { + if (event.shouldConsume() && !user.abilities.instabuild) { + itemstack.shrink(1); +- } else ((EntityPlayer) user).getBukkitEntity().updateInventory(); +- } else if (user instanceof EntityPlayer) { +- ((EntityPlayer) user).getBukkitEntity().updateInventory(); ++ } else ((ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } else if (user instanceof ServerPlayer) { ++ ((ServerPlayer) user).getBukkitEntity().updateInventory(); + } + // Paper end + } +diff --git a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java +index 813a9c8464e253b9baa15af666111be104b4aa29..1957561f83645a57df5925b4b0b54153ebf4aeef 100644 +--- a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java ++++ b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java +@@ -3,6 +3,7 @@ package net.minecraft.world.item; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.InteractionHand; ++import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; +@@ -15,7 +16,12 @@ public class LingeringPotionItem extends ThrowablePotionItem { + + @Override + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { +- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.LINGERING_POTION_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (LingeringPotionItem.random.nextFloat() * 0.4F + 0.8F)); +- return super.use(world, user, hand); ++ // Paper start ++ InteractionResultHolder wrapper = super.use(world, user, hand); ++ if (wrapper.getResult() != InteractionResult.FAIL) { ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.LINGERING_POTION_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (LingeringPotionItem.random.nextFloat() * 0.4F + 0.8F)); ++ } ++ return wrapper; ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/item/SnowballItem.java b/src/main/java/net/minecraft/world/item/SnowballItem.java +index 50adbfc5d57b2b5f25c0efdc51da1701197c66e6..b053d105a1513a6b138972cdb9d28116fc6b8c81 100644 +--- a/src/main/java/net/minecraft/world/item/SnowballItem.java ++++ b/src/main/java/net/minecraft/world/item/SnowballItem.java +@@ -26,14 +26,20 @@ public class SnowballItem extends Item { + + entitysnowball.setItem(itemstack); + entitysnowball.shootFromRotation(user, user.xRot, user.yRot, 0.0F, 1.5F, 1.0F); +- if (world.addFreshEntity(entitysnowball)) { +- if (!user.abilities.instabuild) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entitysnowball)) { ++ if (event.shouldConsume() && !user.abilities.instabuild) { ++ // Paper end + itemstack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { // Paper ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper + } + + world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (SnowballItem.random.nextFloat() * 0.4F + 0.8F)); +- } else if (user instanceof net.minecraft.server.level.ServerPlayer) { +- ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } else { // Paper ++ if (user instanceof net.minecraft.server.level.ServerPlayer) ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper ++ return new InteractionResultHolder(net.minecraft.world.InteractionResult.FAIL, itemstack); // Paper + } + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/item/SplashPotionItem.java b/src/main/java/net/minecraft/world/item/SplashPotionItem.java +index 9c7547988fe90e9b87868636a1c1a7b4dff32622..6d3ab7fea3b5ebba4c304cdec5dd36dbea31f2c6 100644 +--- a/src/main/java/net/minecraft/world/item/SplashPotionItem.java ++++ b/src/main/java/net/minecraft/world/item/SplashPotionItem.java +@@ -3,6 +3,7 @@ package net.minecraft.world.item; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.InteractionHand; ++import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; +@@ -15,7 +16,12 @@ public class SplashPotionItem extends ThrowablePotionItem { + + @Override + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { ++ // Paper start ++ InteractionResultHolder wrapper = super.use(world, user, hand); ++ if (wrapper.getResult() != InteractionResult.FAIL) { + world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SPLASH_POTION_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (SplashPotionItem.random.nextFloat() * 0.4F + 0.8F)); +- return super.use(world, user, hand); ++ } ++ return wrapper; ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java +index 3615bc9222db4489189537f7f5d7a7d338053d6d..e12c7ebc0a4ff4f132512dc1677db7f79db41b03 100644 +--- a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java ++++ b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java +@@ -1,7 +1,9 @@ + package net.minecraft.world.item; + ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.stats.Stats; + import net.minecraft.world.InteractionHand; ++import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.ThrownPotion; +@@ -22,13 +24,31 @@ public class ThrowablePotionItem extends PotionItem { + + entitypotion.setItem(itemstack); + entitypotion.shootFromRotation(user, user.xRot, user.yRot, -20.0F, 0.5F, 1.0F); +- world.addFreshEntity(entitypotion); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitypotion.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entitypotion)) { ++ if (event.shouldConsume() && !user.abilities.instabuild) { ++ itemstack.shrink(1); ++ } else if (user instanceof ServerPlayer) { ++ ((ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ } else { ++ if (user instanceof ServerPlayer) { ++ ((ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ return new InteractionResultHolder(InteractionResult.FAIL, itemstack); ++ } ++ // Paper end + } + +- user.awardStat(Stats.ITEM_USED.get(this)); +- if (!user.abilities.instabuild) { +- itemstack.shrink(1); ++ /* // Paper start - moved up ++ entityhuman.b(StatisticList.ITEM_USED.b(this)); ++ if (!entityhuman.abilities.canInstantlyBuild) { ++ itemstack.subtract(1); + } ++ */ // Paper end + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } diff --git a/patches/server-remapped/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch b/patches/server-remapped/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch new file mode 100644 index 0000000000..509fc426f4 --- /dev/null +++ b/patches/server-remapped/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BlackHole +Date: Sun, 15 Dec 2019 19:12:39 +0100 +Subject: [PATCH] Add CraftMagicNumbers.isSupportedApiVersion() + + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 21052d0e88351b075733331d71e07b086354b820..86b319337fc41a09dd45df466df60cadaed1343f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -373,6 +373,11 @@ public final class CraftMagicNumbers implements UnsafeValues { + public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { + return new com.destroystokyo.paper.PaperVersionFetcher(); + } ++ ++ @Override ++ public boolean isSupportedApiVersion(String apiVersion) { ++ return apiVersion != null && SUPPORTED_API.contains(apiVersion); ++ } + // Paper end + + /** diff --git a/patches/server-remapped/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/patches/server-remapped/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch new file mode 100644 index 0000000000..32b045db49 --- /dev/null +++ b/patches/server-remapped/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Callahan +Date: Mon, 13 Jan 2020 23:47:28 -0600 +Subject: [PATCH] Prevent sync chunk loads when villagers try to find beds + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java +index 5151c794985a135d3bd794bbafdf524ab9f670de..9a582fb4b96b2d0406cc86e473e8bf8c4e488e37 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java +@@ -46,7 +46,8 @@ public class SleepInBed extends Behavior { + } + } + +- BlockState iblockdata = world.getBlockState(globalpos.getBlockPosition()); ++ BlockState iblockdata = world.getTypeIfLoaded(globalpos.getBlockPosition()); // Paper ++ if (iblockdata == null) { return false; } // Paper + + return globalpos.getBlockPosition().a((Position) entity.position(), 2.0D) && iblockdata.getBlock().is((Tag) BlockTags.BEDS) && !(Boolean) iblockdata.getValue(BedBlock.OCCUPIED); + } diff --git a/patches/server-remapped/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch b/patches/server-remapped/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch new file mode 100644 index 0000000000..27d343fa11 --- /dev/null +++ b/patches/server-remapped/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 18 Dec 2019 22:21:35 -0600 +Subject: [PATCH] MC-145656 Fix Follow Range Initial Target + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5..edda2121f8c1046478beaa77030ebb36d403b334 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -580,4 +580,9 @@ public class PaperWorldConfig { + private void pillagerSettings() { + disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); + } ++ ++ public boolean entitiesTargetWithFollowRange = false; ++ private void entitiesTargetWithFollowRange() { ++ entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java +index 7bba2ac71a3cd34a06ec865a3c1828b10decd644..93845edab0e1b0e2ad300cad051b0182cadd46e5 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java +@@ -32,6 +32,7 @@ public class NearestAttackableTargetGoal extends TargetG + this.randomInterval = reciprocalChance; + this.setFlags(EnumSet.of(Goal.Flag.TARGET)); + this.targetConditions = (new TargetingConditions()).range(this.getFollowDistance()).selector(targetPredicate); ++ if (mob.level.paperConfig.entitiesTargetWithFollowRange) this.targetConditions.useFollowRange(); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java +index 1714507fa744b2767e8a66cdb5db7f43c21f5c56..e1a0104a3b52990a83e7732491029d8a20976dc3 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java ++++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java +@@ -4,6 +4,8 @@ import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.ai.attributes.AttributeInstance; ++import net.minecraft.world.entity.ai.attributes.Attributes; + + public class TargetingConditions { + +@@ -82,7 +84,7 @@ public class TargetingConditions { + + if (this.range > 0.0D) { + double d0 = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D; +- double d1 = Math.max(this.range * d0, 2.0D); ++ double d1 = Math.max((useFollowRange ? getFollowRange(baseEntity) : this.range) * d0, 2.0D); // Paper + double d2 = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); + + if (d2 > d1 * d1) { +@@ -98,4 +100,18 @@ public class TargetingConditions { + return true; + } + } ++ ++ // Paper start ++ private boolean useFollowRange = false; ++ ++ public TargetingConditions useFollowRange() { ++ this.useFollowRange = true; ++ return this; ++ } ++ ++ private double getFollowRange(LivingEntity entityliving) { ++ AttributeInstance attributeinstance = entityliving.getAttribute(Attributes.FOLLOW_RANGE); ++ return attributeinstance == null ? 16.0D : attributeinstance.getValue(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0388-Optimize-Hoppers.patch b/patches/server-remapped/0388-Optimize-Hoppers.patch new file mode 100644 index 0000000000..5d342ad554 --- /dev/null +++ b/patches/server-remapped/0388-Optimize-Hoppers.patch @@ -0,0 +1,605 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 27 Apr 2016 22:09:52 -0400 +Subject: [PATCH] Optimize Hoppers + +* Removes unnecessary extra calls to .update() that are very expensive +* Lots of itemstack cloning removed. Only clone if the item is actually moved +* Return true when a plugin cancels inventory move item event instead of false, as false causes pulls to cycle through all items. + However, pushes do not exhibit the same behavior, so this is not something plugins could of been relying on. +* Add option (Default on) to cooldown hoppers when they fail to move an item due to full inventory +* Skip subsequent InventoryMoveItemEvents if a plugin does not use the item after first event fire for an iteration +* Don't check for Entities with Inventories if the block above us is also occluding (not just Inventoried) +* Remove Streams from Item Suck In and restore restore 1.12 AABB checks which is simpler and no voxel allocations (was doing TWO Item Suck ins) + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index edda2121f8c1046478beaa77030ebb36d403b334..7fbd501d70dccf869a4454e2789a5d68f2e15754 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -585,4 +585,13 @@ public class PaperWorldConfig { + private void entitiesTargetWithFollowRange() { + entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); + } ++ ++ public boolean cooldownHopperWhenFull = true; ++ public boolean disableHopperMoveEvents = false; ++ private void hopperOptimizations() { ++ cooldownHopperWhenFull = getBoolean("hopper.cooldown-when-full", cooldownHopperWhenFull); ++ log("Cooldown Hoppers when Full: " + (cooldownHopperWhenFull ? "enabled" : "disabled")); ++ disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); ++ log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 753e6f609189c589514739bea80007bace3c89d2..7038897b8fb4c18ca97b95a3b24c30b40b62b005 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -131,6 +131,7 @@ import net.minecraft.world.level.LevelSettings; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.biome.BiomeSource; + import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.entity.HopperBlockEntity; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.dimension.DimensionType; +@@ -1360,6 +1361,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper ++ HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + + this.profiler.push(() -> { + return worldserver + " " + worldserver.dimension().location(); +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 02bfa4fb8055e60a84e878ffbf18303c0ee25b1d..ac996d581925c8f92832009945c766962e5b51c5 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -538,11 +538,12 @@ public final class ItemStack { + return this.getItem().interactLivingEntity(this, user, entity, hand); + } + +- public ItemStack copy() { +- if (this.isEmpty()) { ++ public ItemStack copy() { return cloneItemStack(false); } // Paper ++ public ItemStack cloneItemStack(boolean origItem) { // Paper ++ if (!origItem && this.isEmpty()) { // Paper + return ItemStack.EMPTY; + } else { +- ItemStack itemstack = new ItemStack(this.getItem(), this.count); ++ ItemStack itemstack = new ItemStack(origItem ? this.item : this.getItem(), this.count); // Paper + + itemstack.setPopTime(this.getPopTime()); + if (this.tag != null) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 3e2cd6c7a34c1a792d7346019a8b039d1f4a7c04..6b79f8cd9258af47afa6efa7b1f97c3780be58b0 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -1162,8 +1162,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return list; + } + +- @Override +- public List getEntitiesOfClass(Class entityClass, AABB box, @Nullable Predicate predicate) { ++ public List getEntities(Class oclass, AABB axisalignedbb, @Nullable Predicate predicate) { return getEntitiesOfClass(oclass, axisalignedbb, predicate); } // Paper - OBFHELPER ++ @Override public List getEntitiesOfClass(Class entityClass, AABB box, @Nullable Predicate predicate) { + this.getProfiler().incrementCounter("getEntities"); + int i = Mth.floor((box.minX - 2.0D) / 16.0D); + int j = Mth.ceil((box.maxX + 2.0D) / 16.0D); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 84012c2d12817e657b046bc168cc8eddebcd3831..05fa76c02ce61e26891ad995fe89e925ea086557 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -77,6 +77,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + public void setCurrentChunk(LevelChunk chunk) { + this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; + } ++ static boolean IGNORE_TILE_UPDATES = false; + // Paper end + + @Nullable +@@ -155,6 +156,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + + public void setChanged() { + if (this.level != null) { ++ if (IGNORE_TILE_UPDATES) return; // Paper + this.blockState = this.level.getBlockState(this.worldPosition); + this.level.blockEntityChanged(this.worldPosition, this); + if (!this.blockState.isAir()) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java +index f8e4a42bed265822666141683e36e6696694925b..fc8bb72f7d677f65db505016ad6a4cd6146de29f 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block.entity; + + import javax.annotation.Nullable; ++import net.minecraft.core.BlockPos; + import net.minecraft.world.Container; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; +@@ -17,12 +18,13 @@ public interface Hopper extends Container { + return Hopper.SUCK; + } + +- @Nullable ++ //@Nullable // Paper - it's annoying + Level getLevel(); ++ default BlockPos getBlockPosition() { return new BlockPos(getX(), getY(), getZ()); } // Paper + +- double getLevelX(); ++ double getLevelX(); default double getX() { return this.getLevelX(); } // Paper - OBFHELPER + +- double getLevelY(); ++ double getLevelY(); default double getY() { return this.getLevelY(); } // Paper - OBFHELPER + +- double getLevelZ(); ++ double getLevelZ(); default double getZ() { return this.getLevelZ(); } // Paper - OBFHELPER + } +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 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f7639dab54b 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 +@@ -193,6 +193,160 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + return false; + } + ++ // Paper start - Optimize Hoppers ++ private static boolean skipPullModeEventFire = false; ++ private static boolean skipPushModeEventFire = false; ++ public static boolean skipHopperEvents = false; ++ ++ private boolean hopperPush(Container iinventory, Direction enumdirection) { ++ skipPushModeEventFire = skipHopperEvents; ++ boolean foundItem = false; ++ for (int i = 0; i < this.getContainerSize(); ++i) { ++ ItemStack item = this.getItem(i); ++ if (!item.isEmpty()) { ++ foundItem = true; ++ ItemStack origItemStack = item; ++ ItemStack itemstack = origItemStack; ++ ++ final int origCount = origItemStack.getCount(); ++ final int moved = Math.min(level.spigotConfig.hopperAmount, origCount); ++ origItemStack.setCount(moved); ++ ++ // We only need to fire the event once to give protection plugins a chance to cancel this event ++ // Because nothing uses getItem, every event call should end up the same result. ++ if (!skipPushModeEventFire) { ++ itemstack = callPushMoveEvent(iinventory, itemstack); ++ if (itemstack == null) { // cancelled ++ origItemStack.setCount(origCount); ++ return false; ++ } ++ } ++ final ItemStack itemstack2 = addItem(this, iinventory, itemstack, enumdirection); ++ final int remaining = itemstack2.getCount(); ++ if (remaining != moved) { ++ origItemStack = origItemStack.cloneItemStack(true); ++ origItemStack.setCount(origCount); ++ if (!origItemStack.isEmpty()) { ++ origItemStack.setCount(origCount - moved + remaining); ++ } ++ this.setItem(i, origItemStack); ++ iinventory.setChanged(); ++ return true; ++ } ++ origItemStack.setCount(origCount); ++ } ++ } ++ if (foundItem && level.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown ++ this.setCooldown(level.spigotConfig.hopperTransfer); ++ } ++ return false; ++ } ++ ++ private static boolean hopperPull(Hopper ihopper, Container iinventory, ItemStack origItemStack, int i) { ++ ItemStack itemstack = origItemStack; ++ final int origCount = origItemStack.getCount(); ++ final Level world = ihopper.getLevel(); ++ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); ++ itemstack.setCount(moved); ++ ++ if (!skipPullModeEventFire) { ++ itemstack = callPullMoveEvent(ihopper, iinventory, itemstack); ++ if (itemstack == null) { // cancelled ++ origItemStack.setCount(origCount); ++ // Drastically improve performance by returning true. ++ // No plugin could of relied on the behavior of false as the other call ++ // site for IMIE did not exhibit the same behavior ++ return true; ++ } ++ } ++ ++ final ItemStack itemstack2 = addItem(iinventory, ihopper, itemstack, null); ++ final int remaining = itemstack2.getCount(); ++ if (remaining != moved) { ++ origItemStack = origItemStack.cloneItemStack(true); ++ origItemStack.setCount(origCount); ++ if (!origItemStack.isEmpty()) { ++ origItemStack.setCount(origCount - moved + remaining); ++ } ++ IGNORE_TILE_UPDATES = true; ++ iinventory.setItem(i, origItemStack); ++ IGNORE_TILE_UPDATES = false; ++ iinventory.setChanged(); ++ return true; ++ } ++ origItemStack.setCount(origCount); ++ ++ if (world.paperConfig.cooldownHopperWhenFull) { ++ cooldownHopper(ihopper); ++ } ++ ++ return false; ++ } ++ ++ private ItemStack callPushMoveEvent(Container iinventory, ItemStack itemstack) { ++ Inventory destinationInventory = getInventory(iinventory); ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner(false).getInventory(), ++ CraftItemStack.asCraftMirror(itemstack), destinationInventory, true); ++ boolean result = event.callEvent(); ++ if (!event.calledGetItem && !event.calledSetItem) { ++ skipPushModeEventFire = true; ++ } ++ if (!result) { ++ cooldownHopper(this); ++ return null; ++ } ++ ++ if (event.calledSetItem) { ++ return CraftItemStack.asNMSCopy(event.getItem()); ++ } else { ++ return itemstack; ++ } ++ } ++ ++ private static ItemStack callPullMoveEvent(Hopper hopper, Container iinventory, ItemStack itemstack) { ++ Inventory sourceInventory = getInventory(iinventory); ++ Inventory destination = getInventory(hopper); ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, ++ // Mirror is safe as we no plugins ever use this item ++ CraftItemStack.asCraftMirror(itemstack), destination, false); ++ boolean result = event.callEvent(); ++ if (!event.calledGetItem && !event.calledSetItem) { ++ skipPullModeEventFire = true; ++ } ++ if (!result) { ++ cooldownHopper(hopper); ++ return null; ++ } ++ ++ if (event.calledSetItem) { ++ return CraftItemStack.asNMSCopy(event.getItem()); ++ } else { ++ return itemstack; ++ } ++ } ++ ++ private static Inventory getInventory(Container iinventory) { ++ Inventory sourceInventory;// Have to special case large chests as they work oddly ++ if (iinventory instanceof CompoundContainer) { ++ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); ++ } else if (iinventory instanceof BlockEntity) { ++ sourceInventory = ((BlockEntity) iinventory).getOwner(false).getInventory(); ++ } else { ++ sourceInventory = iinventory.getOwner().getInventory(); ++ } ++ return sourceInventory; ++ } ++ ++ private static void cooldownHopper(Hopper hopper) { ++ if (hopper instanceof HopperBlockEntity) { ++ ((HopperBlockEntity) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer); ++ } else if (hopper instanceof MinecartHopper) { ++ ((MinecartHopper) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer / 2); ++ } ++ } ++ // Paper end ++ + private boolean ejectItems() { + Container iinventory = this.getAttachedContainer(); + +@@ -204,27 +358,28 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + if (this.isFullContainer(iinventory, enumdirection)) { + return false; + } else { +- for (int i = 0; i < this.getContainerSize(); ++i) { ++ return hopperPush(iinventory, enumdirection); /* // Paper - disable rest ++ for (int i = 0; i < this.getSize(); ++i) { + if (!this.getItem(i).isEmpty()) { +- ItemStack itemstack = this.getItem(i).copy(); ++ ItemStack itemstack = this.getItem(i).cloneItemStack(); + // ItemStack itemstack1 = addItem(this, iinventory, this.splitStack(i, 1), enumdirection); + + // CraftBukkit start - Call event when pushing items into other inventories +- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.removeItem(i, level.spigotConfig.hopperAmount)); // Spigot ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.splitStack(i, world.spigotConfig.hopperAmount)); // Spigot + + Inventory destinationInventory; + // Have to special case large chests as they work oddly +- if (iinventory instanceof CompoundContainer) { +- destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); ++ if (iinventory instanceof InventoryLargeChest) { ++ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); + } else { + destinationInventory = iinventory.getOwner().getInventory(); + } + + InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); +- this.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ this.getWorld().getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.setItem(i, itemstack); +- this.setCooldown(level.spigotConfig.hopperTransfer); // Spigot ++ this.setCooldown(world.spigotConfig.hopperTransfer); // Spigot + return false; + } + int origCount = event.getItem().getAmount(); // Spigot +@@ -232,16 +387,16 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + // CraftBukkit end + + if (itemstack1.isEmpty()) { +- iinventory.setChanged(); ++ iinventory.update(); + return true; + } + +- itemstack.shrink(origCount - itemstack1.getCount()); // Spigot ++ itemstack.subtract(origCount - itemstack1.getCount()); // Spigot + this.setItem(i, itemstack); + } + } + +- return false; ++ return false;*/ // Paper - end commenting out replaced block for Hopper Optimizations + } + } + } +@@ -250,18 +405,54 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + return inventory instanceof WorldlyContainer ? IntStream.of(((WorldlyContainer) inventory).getSlotsForFace(side)) : IntStream.range(0, inventory.getContainerSize()); + } + +- private boolean isFullContainer(Container inv, Direction enumdirection) { +- return getSlots(inv, enumdirection).allMatch((i) -> { +- ItemStack itemstack = inv.getItem(i); ++ private static boolean allMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate test) { ++ if (iinventory instanceof WorldlyContainer) { ++ for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) { ++ if (!test.test(iinventory.getItem(i), i)) { ++ return false; ++ } ++ } ++ } else { ++ int size = iinventory.getContainerSize(); ++ for (int i = 0; i < size; i++) { ++ if (!test.test(iinventory.getItem(i), i)) { ++ return false; ++ } ++ } ++ } ++ return true; ++ } + +- return itemstack.getCount() >= itemstack.getMaxStackSize(); +- }); ++ private static boolean anyMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate test) { ++ if (iinventory instanceof WorldlyContainer) { ++ for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) { ++ if (test.test(iinventory.getItem(i), i)) { ++ return true; ++ } ++ } ++ } else { ++ int size = iinventory.getContainerSize(); ++ for (int i = 0; i < size; i++) { ++ if (test.test(iinventory.getItem(i), i)) { ++ return true; ++ } ++ } ++ } ++ return true; ++ } ++ private static final java.util.function.BiPredicate STACK_SIZE_TEST = (itemstack, i) -> itemstack.getCount() >= itemstack.getMaxStackSize(); ++ private static final java.util.function.BiPredicate IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty(); ++ ++ // Paper end ++ ++ private boolean isFullContainer(Container inv, Direction enumdirection) { ++ // Paper start - no streams ++ return allMatch(inv, enumdirection, STACK_SIZE_TEST); ++ // Paper end + } + + private static boolean isEmptyContainer(Container inv, Direction facing) { +- return getSlots(inv, facing).allMatch((i) -> { +- return inv.getItem(i).isEmpty(); +- }); ++ return allMatch(inv, facing, IS_EMPTY_TEST); + } + + public static boolean suckInItems(Hopper hopper) { +@@ -270,9 +461,17 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + if (iinventory != null) { + Direction enumdirection = Direction.DOWN; + +- return isEmptyContainer(iinventory, enumdirection) ? false : getSlots(iinventory, enumdirection).anyMatch((i) -> { +- return tryTakeInItemFromSlot(hopper, iinventory, i, enumdirection); ++ // Paper start - optimize hoppers and remove streams ++ skipPullModeEventFire = skipHopperEvents; ++ return !isEmptyContainer(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { ++ // Logic copied from below to avoid extra getItem calls ++ if (!item.isEmpty() && canTakeItem(iinventory, item, i, enumdirection)) { ++ return hopperPull(hopper, iinventory, item, i); ++ } else { ++ return false; ++ } + }); ++ // Paper end + } else { + Iterator iterator = getItemsAtAndAbove(hopper).iterator(); + +@@ -290,47 +489,48 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + } + +- private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) { ++ private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) {// Paper - method unused as logic is inlined above + ItemStack itemstack = inventory.getItem(slot); + +- if (!itemstack.isEmpty() && canTakeItemFromContainer(inventory, itemstack, slot, side)) { +- ItemStack itemstack1 = itemstack.copy(); ++ if (!itemstack.isEmpty() && canTakeItemFromContainer(inventory, itemstack, slot, side)) { // If this logic changes, update above. this is left inused incase reflective plugins ++ return hopperPull(hopper, inventory, itemstack, slot); /* // Paper - disable rest ++ ItemStack itemstack1 = itemstack.cloneItemStack(); + // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null); + // CraftBukkit start - Call event on collection of items from inventories into the hopper +- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(inventory.removeItem(slot, hopper.getLevel().spigotConfig.hopperAmount)); // Spigot ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.splitStack(i, ihopper.getWorld().spigotConfig.hopperAmount)); // Spigot + + Inventory sourceInventory; + // Have to special case large chests as they work oddly +- if (inventory instanceof CompoundContainer) { +- sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) inventory); ++ if (iinventory instanceof InventoryLargeChest) { ++ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); + } else { +- sourceInventory = inventory.getOwner().getInventory(); ++ sourceInventory = iinventory.getOwner().getInventory(); + } + +- InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), hopper.getOwner().getInventory(), false); ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), ihopper.getOwner().getInventory(), false); + +- hopper.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ ihopper.getWorld().getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { +- inventory.setItem(slot, itemstack1); ++ iinventory.setItem(i, itemstack1); + +- if (hopper instanceof HopperBlockEntity) { +- ((HopperBlockEntity) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer); // Spigot +- } else if (hopper instanceof MinecartHopper) { +- ((MinecartHopper) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer / 2); // Spigot ++ if (ihopper instanceof TileEntityHopper) { ++ ((TileEntityHopper) ihopper).setCooldown(ihopper.getWorld().spigotConfig.hopperTransfer); // Spigot ++ } else if (ihopper instanceof EntityMinecartHopper) { ++ ((EntityMinecartHopper) ihopper).setCooldown(ihopper.getWorld().spigotConfig.hopperTransfer / 2); // Spigot + } + return false; + } + int origCount = event.getItem().getAmount(); // Spigot +- ItemStack itemstack2 = addItem(inventory, hopper, CraftItemStack.asNMSCopy(event.getItem()), null); ++ ItemStack itemstack2 = addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null); + // CraftBukkit end + + if (itemstack2.isEmpty()) { +- inventory.setChanged(); ++ iinventory.update(); + return true; + } + +- itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot +- inventory.setItem(slot, itemstack1); ++ itemstack1.subtract(origCount - itemstack2.getCount()); // Spigot ++ iinventory.setItem(i, itemstack1);*/ // Paper - end commenting out replaced block for Hopper Optimizations + } + + return false; +@@ -339,7 +539,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + public static boolean addItem(Container inventory, ItemEntity itemEntity) { + boolean flag = false; + // CraftBukkit start +- InventoryPickupItemEvent event = new InventoryPickupItemEvent(inventory.getOwner().getInventory(), (org.bukkit.entity.Item) itemEntity.getBukkitEntity()); ++ InventoryPickupItemEvent event = new InventoryPickupItemEvent(getInventory(inventory), (org.bukkit.entity.Item) itemEntity.getBukkitEntity()); // Paper - use getInventory() to avoid snapshot creation + itemEntity.level.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; +@@ -381,6 +581,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + return !inventory.canPlaceItem(slot, stack) ? false : !(inventory instanceof WorldlyContainer) || ((WorldlyContainer) inventory).canPlaceItemThroughFace(slot, stack, side); + } + ++ private static boolean canTakeItem(Container iinventory, ItemStack itemstack, int i, Direction enumdirection) { return canTakeItemFromContainer(iinventory, itemstack, i, enumdirection); } // Paper - OBFHELPER + private static boolean canTakeItemFromContainer(Container inv, ItemStack stack, int slot, Direction facing) { + return !(inv instanceof WorldlyContainer) || ((WorldlyContainer) inv).canTakeItemThroughFace(slot, stack, facing); + } +@@ -393,7 +594,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + boolean flag1 = to.isEmpty(); + + if (itemstack1.isEmpty()) { ++ IGNORE_TILE_UPDATES = true; // Paper + to.setItem(slot, stack); ++ IGNORE_TILE_UPDATES = false; // Paper + stack = ItemStack.EMPTY; + flag = true; + } else if (canMergeItems(itemstack1, stack)) { +@@ -444,20 +647,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + + public static List getItemsAtAndAbove(Hopper ihopper) { +- return (List) ihopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> { +- return ihopper.getLevel().getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(ihopper.getLevelX() - 0.5D, ihopper.getLevelY() - 0.5D, ihopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream(); +- }).collect(Collectors.toList()); ++ // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?! ++ Level world = ihopper.getLevel(); ++ double d0 = ihopper.getX(); ++ double d1 = ihopper.getY(); ++ double d2 = ihopper.getZ(); ++ AABB bb = new AABB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); ++ return world.getEntities(ItemEntity.class, bb, Entity::isAlive); ++ // Paper end + } + + @Nullable + public static Container getContainerAt(Level world, BlockPos blockposition) { +- return getContainerAt(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); ++ return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, true); // Paper + } + + @Nullable +- public static Container getContainerAt(Level world, double x, double y, double z) { ++ public static Container getContainerAt(Level world, double x, double y, double z) { return a(world, x, y, z, false); } // Paper - overload to default false ++ public static Container a(Level world, double d0, double d1, double d2, boolean optimizeEntities) { // Paper + Object object = null; +- BlockPos blockposition = new BlockPos(x, y, z); ++ BlockPos blockposition = new BlockPos(d0, d1, d2); + if ( !world.hasChunkAt( blockposition ) ) return null; // Spigot + BlockState iblockdata = world.getBlockState(blockposition); + Block block = iblockdata.getBlock(); +@@ -475,8 +684,8 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + } + +- if (object == null) { +- List list = world.getEntities((Entity) null, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); ++ if (object == null && (!optimizeEntities || !org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(block).isOccluding())) { // Paper ++ List list = world.getEntities((Entity) null, new AABB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); + + if (!list.isEmpty()) { + object = (Container) list.get(world.random.nextInt(list.size())); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +index 5ad419941ff1113ef29b9a4593f44d8f35ba8424..4525032232b5a89de13c6a46dc489a07428e3f21 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +@@ -97,12 +97,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + @Override + public boolean isEmpty() { + this.unpackLootTable((Player) null); +- return this.getItems().stream().allMatch(ItemStack::isEmpty); ++ // Paper start ++ for (ItemStack itemStack : this.getItems()) { ++ if (!itemStack.isEmpty()) { ++ return false; ++ } ++ } ++ // Paper end ++ return true; + } + + @Override + public ItemStack getItem(int slot) { +- this.unpackLootTable((Player) null); ++ if (slot == 0) this.unpackLootTable((Player) null); // Paper + return (ItemStack) this.getItems().get(slot); + } + diff --git a/patches/server-remapped/0389-PlayerDeathEvent-shouldDropExperience.patch b/patches/server-remapped/0389-PlayerDeathEvent-shouldDropExperience.patch new file mode 100644 index 0000000000..4f453dc689 --- /dev/null +++ b/patches/server-remapped/0389-PlayerDeathEvent-shouldDropExperience.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 24 Dec 2019 00:35:42 +0000 +Subject: [PATCH] PlayerDeathEvent#shouldDropExperience + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 2ef273e3b917803f3e2ac3c6a22d92a15b9eb71a..7f4e81ee3339e90b8525541dccf6dea187853cf7 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -819,7 +819,7 @@ public class ServerPlayer extends Player implements ContainerListener { + this.tellNeutralMobsThatIDied(); + } + // SPIGOT-5478 must be called manually now +- this.dropExperience(); ++ if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event + // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. + if (!event.getKeepInventory()) { + // Paper start - replace logic diff --git a/patches/server-remapped/0390-Prevent-bees-loading-chunks-checking-hive-position.patch b/patches/server-remapped/0390-Prevent-bees-loading-chunks-checking-hive-position.patch new file mode 100644 index 0000000000..9a427d5aa2 --- /dev/null +++ b/patches/server-remapped/0390-Prevent-bees-loading-chunks-checking-hive-position.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 5 Jan 2020 17:24:34 -0600 +Subject: [PATCH] Prevent bees loading chunks checking hive position + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java +index 32ee38142a3053091ab7b3fb3d608d268b07d4e3..edd6d63f715acef1a77eba0cf46ff8267228f4c6 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -442,6 +442,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + if (!this.hasHive()) { + return false; + } else { ++ if (level.getChunkIfLoadedImmediately(hivePos.getX() >> 4, hivePos.getZ() >> 4) == null) return true; // Paper - just assume the hive is still there, no need to load the chunk(s) + BlockEntity tileentity = this.level.getBlockEntity(this.hivePos); + + return tileentity != null && tileentity.getType() == BlockEntityType.BEEHIVE; diff --git a/patches/server-remapped/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/patches/server-remapped/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch new file mode 100644 index 0000000000..f6952f6250 --- /dev/null +++ b/patches/server-remapped/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Nov 2016 20:28:12 -0400 +Subject: [PATCH] Don't load Chunks from Hoppers and other things + +Hoppers call this to I guess "get the primary side" of a double sided chest. + +If the double sided chest crosses chunk lines, it causes the chunk to load. +This will end up causing sync chunk loads, which will unload with Chunk GC, +only to be reloaded again the next tick. + +This of course is undesirable, so just return the loaded side as "primary" +and treat it as a single chest if the other sides are unloaded + +diff --git a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java +index a4f16b2093c867e9fd1c2e07b67c49c3c5ec7506..df20b3616929657d2e8061159ed97f500b33d192 100644 +--- a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java ++++ b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java +@@ -29,7 +29,12 @@ public class DoubleBlockCombiner { + return new DoubleBlockCombiner.NeighborCombineResult.Single<>(s0); + } else { + BlockPos blockposition1 = pos.relative((Direction) function1.apply(state)); +- BlockState iblockdata1 = world.getBlockState(blockposition1); ++ // Paper start ++ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); ++ if (iblockdata1 == null) { ++ return new DoubleBlockCombiner.NeighborCombineResult.Single<>(s0); ++ } ++ // Paper end + + if (iblockdata1.is(state.getBlock())) { + DoubleBlockCombiner.BlockType doubleblockfinder_blocktype1 = (DoubleBlockCombiner.BlockType) typeMapper.apply(iblockdata1); diff --git a/patches/server-remapped/0392-Guard-against-serializing-mismatching-chunk-coordina.patch b/patches/server-remapped/0392-Guard-against-serializing-mismatching-chunk-coordina.patch new file mode 100644 index 0000000000..37dc33fc4a --- /dev/null +++ b/patches/server-remapped/0392-Guard-against-serializing-mismatching-chunk-coordina.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 27 Dec 2019 09:42:26 -0800 +Subject: [PATCH] Guard against serializing mismatching chunk coordinate + +Should help if something dumb happens + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index be67dc16bf70e4517efd213ca9002f116f60b57c..6c28a611b9b79c3322ab07883972c07b3bfc3073 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -67,6 +67,13 @@ public class ChunkSerializer { + + private static final Logger LOGGER = LogManager.getLogger(); + ++ // Paper start - guard against serializing mismatching coordinates ++ // TODO Note: This needs to be re-checked each update ++ public static ChunkPos getChunkCoordinate(CompoundTag chunkData) { ++ CompoundTag levelData = chunkData.getCompound("Level"); ++ return new ChunkPos(levelData.getInt("xPos"), levelData.getInt("zPos")); ++ } ++ // Paper end + // Paper start + public static final class InProgressChunkHolder { + +@@ -92,8 +99,8 @@ public class ChunkSerializer { + // Paper end + ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); + BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); +- CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); +- ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate ++ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate + + if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { + ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +index 684442b7175e30b6d4cafb2f7d2d4c10517cc33d..1af804c5c6fb2b20ea3f020610763c1d7dcee110 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -13,6 +13,7 @@ import net.minecraft.SharedConstants; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.datafix.DataFixTypes; +@@ -119,6 +120,13 @@ public class ChunkStorage implements AutoCloseable { + + public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER + public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) ++ // Paper start ++ if (!chunkcoordintpair.equals(ChunkSerializer.getChunkCoordinate(nbttagcompound))) { ++ String world = (this instanceof ChunkMap) ? ((ChunkMap)this).level.getWorld().getName() : null; ++ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkcoordintpair.toString() ++ + " but compound says coordinate is " + ChunkSerializer.getChunkCoordinate(nbttagcompound).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); ++ } ++ // Paper end + this.regionFileCache.write(chunkcoordintpair, nbttagcompound); + if (this.legacyStructureHandler != null) { + synchronized (this.persistentDataLock) { // Paper - Async chunk loading diff --git a/patches/server-remapped/0393-Optimise-IEntityAccess-getPlayerByUUID.patch b/patches/server-remapped/0393-Optimise-IEntityAccess-getPlayerByUUID.patch new file mode 100644 index 0000000000..e478c7d039 --- /dev/null +++ b/patches/server-remapped/0393-Optimise-IEntityAccess-getPlayerByUUID.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 11 Jan 2020 21:50:56 -0800 +Subject: [PATCH] Optimise IEntityAccess#getPlayerByUUID + +Use the world entity map instead of iterating over all players + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 01f879a8dd0e1ffec380e02072567330152eaceb..40d7dbc4f1deda88d4a539b89d84b595217051b6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -283,6 +283,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + // Paper end + ++ // Paper start - optimise getPlayerByUUID ++ @Nullable ++ @Override ++ public Player getPlayerByUUID(UUID uuid) { ++ Entity player = this.entitiesByUuid.get(uuid); ++ return (player instanceof Player) ? (Player)player : null; ++ } ++ // Paper end ++ + // Add env and gen to constructor, WorldData -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor +diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java +index 6a5430fe54a5c8ad119a0f3842961825a54d8d7a..b9606465ace8b320eafbbad3d60c01b87a859c44 100644 +--- a/src/main/java/net/minecraft/world/level/EntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/EntityGetter.java +@@ -277,6 +277,12 @@ public interface EntityGetter { + + @Nullable + default Player getPlayerByUUID(UUID uuid) { ++ // Paper start - allow WorldServer to override ++ return this.getPlayerByUUID(uuid); ++ } ++ @Nullable ++ default Player getPlayerByUUID(UUID uuid) { ++ // Paper end + for (int i = 0; i < this.players().size(); ++i) { + Player entityhuman = (Player) this.players().get(i); + diff --git a/patches/server-remapped/0394-Fix-items-not-falling-correctly.patch b/patches/server-remapped/0394-Fix-items-not-falling-correctly.patch new file mode 100644 index 0000000000..f1ecdfe628 --- /dev/null +++ b/patches/server-remapped/0394-Fix-items-not-falling-correctly.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AJMFactsheets +Date: Fri, 17 Jan 2020 17:17:54 -0600 +Subject: [PATCH] Fix items not falling correctly + +Since 1.14, Mojang has added an optimization which skips checking if +an item should fall every fourth tick. + +However, Spigot's entity activation range class also has an +optimization which skips ticking active entities every fourth tick. +This can result in a state where an item will never properly fall +due to its move method never being called. + +This patch resolves the conflict by offsetting checking an item's +move method from Spigot's entity activation range check. + +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 96b8102773cbee2c3fe2711008ba1487084d67b0..9311f9f411d09d4460f0be8235957fab9e195b7a 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -115,7 +115,7 @@ public class ItemEntity extends Entity { + } + } + +- if (!this.onGround || getHorizontalDistanceSqr(this.getDeltaMovement()) > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) { ++ if (!this.onGround || getHorizontalDistanceSqr(this.getDeltaMovement()) > 9.999999747378752E-6D || this.tickCount % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check + this.move(MoverType.SELF, this.getDeltaMovement()); + float f1 = 0.98F; + diff --git a/patches/server-remapped/0395-Lag-compensate-eating.patch b/patches/server-remapped/0395-Lag-compensate-eating.patch new file mode 100644 index 0000000000..cc90ba9655 --- /dev/null +++ b/patches/server-remapped/0395-Lag-compensate-eating.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 14 Jan 2020 15:28:28 -0800 +Subject: [PATCH] Lag compensate eating + +When the server is lagging, players will wait longer when eating. +Change to also use a time check instead if it passes. + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index b49d4772932a58852b3195f5f56ff93dbcabf766..016fcc4ae20e1e48728a848be28633e624ae49a7 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -211,7 +211,7 @@ public abstract class LivingEntity extends Entity { + private int noJumpDelay; + private float absorptionAmount; + public ItemStack useItem; // Paper - public +- protected int useItemRemaining; ++ protected int useItemRemaining; protected final int getEatTimeTicks() { return this.useItemRemaining; } protected final void setEatTimeTicks(int value) { this.useItemRemaining = value; } // Paper - OBFHELPER + protected int fallFlyTicks; + private BlockPos lastPos; + private Optional lastClimbablePos; +@@ -3148,6 +3148,11 @@ public abstract class LivingEntity extends Entity { + return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; + } + ++ // Paper start - lag compensate eating ++ protected long eatStartTime; ++ protected int totalEatTimeTicks; ++ // Paper end ++ + private void updatingUsingItem() { + if (this.isUsingItem()) { + if (ItemStack.isSameIgnoreDurability(this.getItemInHand(this.getUsedItemHand()), this.useItem)) { +@@ -3157,7 +3162,12 @@ public abstract class LivingEntity extends Entity { + this.triggerItemUseEffects(this.useItem, 5); + } + +- if (--this.useItemRemaining == 0 && !this.level.isClientSide && !this.useItem.useOnRelease()) { ++ // Paper start - lag compensate eating ++ // we add 1 to the expected time to avoid lag compensating when we should not ++ boolean shouldLagCompensate = this.useItem.getItem().isEdible() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); ++ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level.isClientSide && !this.useItem.useOnRelease()) { ++ this.setEatTimeTicks(0); ++ // Paper end + this.completeUsingItem(); + } + } else { +@@ -3207,7 +3217,10 @@ public abstract class LivingEntity extends Entity { + + if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag + this.useItem = itemstack; +- this.useItemRemaining = itemstack.getUseDuration(); ++ // Paper start - lag compensate eating ++ this.useItemRemaining = this.totalEatTimeTicks = itemstack.getUseDuration(); ++ this.eatStartTime = System.nanoTime(); ++ // Paper end + if (!this.level.isClientSide) { + this.setLivingEntityFlag(1, true); + this.setLivingEntityFlag(2, enumhand == InteractionHand.OFF_HAND); +@@ -3231,7 +3244,10 @@ public abstract class LivingEntity extends Entity { + } + } else if (!this.isUsingItem() && !this.useItem.isEmpty()) { + this.useItem = ItemStack.EMPTY; +- this.useItemRemaining = 0; ++ // Paper start - lag compensate eating ++ this.useItemRemaining = this.totalEatTimeTicks = 0; ++ this.eatStartTime = -1L; ++ // Paper end + } + } + +@@ -3359,7 +3375,10 @@ public abstract class LivingEntity extends Entity { + } + + this.useItem = ItemStack.EMPTY; +- this.useItemRemaining = 0; ++ // Paper start - lag compensate eating ++ this.useItemRemaining = this.totalEatTimeTicks = 0; ++ this.eatStartTime = -1L; ++ // Paper end + } + + public boolean isBlocking() { diff --git a/patches/server-remapped/0396-Optimize-call-to-getFluid-for-explosions.patch b/patches/server-remapped/0396-Optimize-call-to-getFluid-for-explosions.patch new file mode 100644 index 0000000000..9e3f2b3479 --- /dev/null +++ b/patches/server-remapped/0396-Optimize-call-to-getFluid-for-explosions.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BrodyBeckwith +Date: Tue, 14 Jan 2020 17:49:03 -0500 +Subject: [PATCH] Optimize call to getFluid for explosions + + +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 45a75f7be308678336e192828becf6cf5c9047bc..667a6d645034c67639c01b8221591877bcb87b35 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -151,7 +151,7 @@ public class Explosion { + for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { + BlockPos blockposition = new BlockPos(d4, d5, d6); + BlockState iblockdata = this.level.getBlockState(blockposition); +- FluidState fluid = this.level.getFluidState(blockposition); ++ FluidState fluid = iblockdata.getFluidState(); // Paper + Optional optional = this.damageCalculator.a(this, this.level, blockposition, iblockdata, fluid); + + if (optional.isPresent()) { diff --git a/patches/server-remapped/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch b/patches/server-remapped/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch new file mode 100644 index 0000000000..63271d423f --- /dev/null +++ b/patches/server-remapped/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 17 Jan 2020 18:44:55 -0800 +Subject: [PATCH] Fix last firework in stack not having effects when dispensed + - #2871 + +CB used the resulting item in the dispenser rather than the item +dispensed. The resulting item would have size == 0 and therefore +be convertered to air, hence why the effects disappeared. + +diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +index 67a894a185a3d4a53b3c7f90174b2604dff18257..67d140dff483bfc654a0390e0cdcd13aa658a62d 100644 +--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +@@ -425,7 +425,7 @@ public interface DispenseItemBehavior { + } + + itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); +- FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.getLevel(), stack, pointer.x(), pointer.y(), pointer.x(), true); ++ FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.getLevel(), itemstack1, pointer.x(), pointer.y(), pointer.x(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed + + DispenseItemBehavior.setEntityPokingOutOfBlock(pointer, entityfireworks, enumdirection); + entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F); diff --git a/patches/server-remapped/0398-Add-effect-to-block-break-naturally.patch b/patches/server-remapped/0398-Add-effect-to-block-break-naturally.patch new file mode 100644 index 0000000000..e51ec69f45 --- /dev/null +++ b/patches/server-remapped/0398-Add-effect-to-block-break-naturally.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 2 Jan 2020 12:25:07 -0600 +Subject: [PATCH] Add effect to block break naturally + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 5bff313dbbb3049105874846d995883e827fbc00..05f0833f762436bf8f5f5875c7e3cfed1da11e1c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -630,6 +630,13 @@ public class CraftBlock implements Block { + + @Override + public boolean breakNaturally(ItemStack item) { ++ // Paper start ++ return breakNaturally(item, false); ++ } ++ ++ @Override ++ public boolean breakNaturally(ItemStack item, boolean triggerEffect) { ++ // Paper end + // Order matters here, need to drop before setting to air so skulls can get their data + net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS(); + net.minecraft.world.level.block.Block block = iblockdata.getBlock(); +@@ -639,6 +646,7 @@ public class CraftBlock implements Block { + // Modelled off EntityHuman#hasBlock + if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) { + net.minecraft.world.level.block.Block.dropResources(iblockdata, world.getLevel(), position, world.getBlockEntity(position), null, nmsItem); ++ if (triggerEffect) world.levelEvent(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.world.level.block.Block.getId(block.defaultBlockState())); // Paper + result = true; + } + diff --git a/patches/server-remapped/0399-Tracking-Range-Improvements.patch b/patches/server-remapped/0399-Tracking-Range-Improvements.patch new file mode 100644 index 0000000000..ec1d0a178d --- /dev/null +++ b/patches/server-remapped/0399-Tracking-Range-Improvements.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Sat, 21 Dec 2019 15:22:09 -0500 +Subject: [PATCH] Tracking Range Improvements + +Sets tracking range of watermobs to animals instead of misc and simplifies code + +Also ignores Enderdragon, defaulting it to Mojang's setting + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 190ddd4d9ef3472c33d46c2ead72fa0dc918054a..6da406c8403797a1cd9276ac06577c3c080a8a22 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1795,6 +1795,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + int j = entity.getType().clientTrackingRange() * 16; ++ j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper + + if (j > i) { + i = j; +diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java +index 8e3e36a8739a7dea1feb3785e96b7b9f19720446..b03fa9024c7f0238e1379f6ae4486db5300a70e9 100644 +--- a/src/main/java/org/spigotmc/TrackingRange.java ++++ b/src/main/java/org/spigotmc/TrackingRange.java +@@ -6,7 +6,6 @@ import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.decoration.ItemFrame; + import net.minecraft.world.entity.decoration.Painting; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.monster.Ghast; + + public class TrackingRange + { +@@ -25,26 +24,26 @@ public class TrackingRange + if ( entity instanceof ServerPlayer ) + { + return config.playerTrackingRange; +- } else if ( entity.activationType == ActivationRange.ActivationType.MONSTER || entity.activationType == ActivationRange.ActivationType.RAIDER ) +- { +- return config.monsterTrackingRange; +- } else if ( entity instanceof Ghast ) +- { +- if ( config.monsterTrackingRange > config.monsterActivationRange ) +- { ++ // Paper start - Simplify and set water mobs to animal tracking range ++ } ++ switch (entity.activationType) { ++ case RAIDER: ++ case MONSTER: ++ case FLYING_MONSTER: + return config.monsterTrackingRange; +- } else +- { +- return config.monsterActivationRange; +- } +- } else if ( entity.activationType == ActivationRange.ActivationType.ANIMAL ) +- { +- return config.animalTrackingRange; +- } else if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) ++ case WATER: ++ case VILLAGER: ++ case ANIMAL: ++ return config.animalTrackingRange; ++ case MISC: ++ } ++ if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) ++ // Paper end + { + return config.miscTrackingRange; + } else + { ++ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt + return config.otherTrackingRange; + } + } diff --git a/patches/server-remapped/0400-Entity-Activation-Range-2.0.patch b/patches/server-remapped/0400-Entity-Activation-Range-2.0.patch new file mode 100644 index 0000000000..ad4d829921 --- /dev/null +++ b/patches/server-remapped/0400-Entity-Activation-Range-2.0.patch @@ -0,0 +1,908 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 13 May 2016 01:38:06 -0400 +Subject: [PATCH] Entity Activation Range 2.0 + +Optimizes performance of Activation Range + +Adds many new configurations and a new wake up inactive system + +Fixes and adds new Immunities to improve gameplay behavior + +Adds water Mobs to activation range config and nerfs fish +Adds flying monsters to control ghast and phantoms +Adds villagers as separate config + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 40d7dbc4f1deda88d4a539b89d84b595217051b6..bf1bb1530037ebcacc8d5a491789909bddb8b697 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -855,17 +855,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + ++TimingHistory.entityTicks; // Paper - timings + // Spigot start + co.aikar.timings.Timing timer; // Paper +- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { +- entity.tickCount++; +- timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings ++ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below ++ entity.ticksLived++; ++ timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings + entity.inactiveTick(); + } finally { timer.stopTiming(); } // Paper + return; +- } ++ }*/ // Paper - comment out EAR 2 + // Spigot end + // Paper start- timings +- TimingHistory.activatedEntityTicks++; +- timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); ++ timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper + try { + // Paper end - timings + entity.setPosAndOldPos(entity.getX(), entity.getY(), entity.getZ()); +@@ -879,12 +879,16 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return Registry.ENTITY_TYPE.getKey(entity.getType()).toString(); + }); + gameprofilerfiller.incrementCounter("tickNonPassenger"); ++ if (isActive) { // Paper - EAR 2 ++ TimingHistory.activatedEntityTicks++; // Paper + entity.tick(); + entity.postTick(); // CraftBukkit ++ } else { entity.inactiveTick(); } // Paper - EAR 2 + gameprofilerfiller.pop(); + } + + this.updateChunkPos(entity); ++ } finally { timer.stopTiming(); } // Paper - timings + if (entity.inChunk) { + Iterator iterator = entity.getPassengers().iterator(); + +@@ -894,7 +898,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.tickPassenger(entity, entity1); + } + } +- } finally { timer.stopTiming(); } // Paper - timings ++ //} finally { timer.stopTiming(); } // Paper - timings - move up + + } + } +@@ -902,6 +906,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public void tickPassenger(Entity vehicle, Entity passenger) { + if (!passenger.removed && passenger.getVehicle() == vehicle) { + if (passenger instanceof Player || this.getChunkSource().isEntityTickingChunk(passenger)) { ++ // Paper - EAR 2 ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); ++ co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper ++ try { ++ // Paper end + passenger.setPosAndOldPos(passenger.getX(), passenger.getY(), passenger.getZ()); + passenger.yRotO = passenger.yRot; + passenger.xRotO = passenger.xRot; +@@ -913,8 +922,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return Registry.ENTITY_TYPE.getKey(passenger.getType()).toString(); + }); + gameprofilerfiller.incrementCounter("tickPassenger"); ++ // Paper start - EAR 2 ++ if (isActive) { + passenger.rideTick(); + passenger.postTick(); // CraftBukkit ++ } else { ++ passenger.setDeltaMovement(Vec3.ZERO); ++ passenger.inactiveTick(); ++ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary ++ vehicle.syncPositionOf(passenger); ++ } ++ // Paper end - EAR 2 + gameprofilerfiller.pop(); + } + +@@ -927,7 +945,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + this.tickPassenger(passenger, entity2); + } +- } ++ } } finally { timer.stopTiming(); } // Paper - EAR2 timings + + } + } else { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index af86c370c6f834514115a8e40659f5e1aaabec75..c6881a9a5da2caed77dea30e4906d2dd99a624c1 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -67,6 +67,7 @@ import net.minecraft.world.entity.animal.AbstractFish; + import net.minecraft.world.entity.animal.Animal; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; ++import net.minecraft.world.entity.vehicle.AbstractMinecart; + import net.minecraft.world.entity.vehicle.Boat; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.enchantment.EnchantmentHelper; +@@ -250,7 +251,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public boolean noCulling; + public boolean hasImpulse; + public int portalCooldown; +- protected boolean isInsidePortal; ++ public boolean isInsidePortal; // Paper - public + protected int portalTime; + protected BlockPos portalEntrancePos; + private boolean invulnerable; +@@ -274,6 +275,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; + public long activatedTick = Integer.MIN_VALUE; ++ public boolean isTemporarilyActive = false; // Paper + public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one + protected int numCollisions = 0; // Paper + public void inactiveTick() { } +@@ -664,6 +666,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.setLocationFromBoundingbox(); + } else { + if (type == MoverType.PISTON) { ++ this.activatedTick = MinecraftServer.currentTick + 20; // Paper + movement = this.limitPistonMovement(movement); + if (movement.equals(Vec3.ZERO)) { + return; +@@ -676,6 +679,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.stuckSpeedMultiplier = Vec3.ZERO; + this.setDeltaMovement(Vec3.ZERO); + } ++ // Paper start - ignore movement changes while inactive. ++ if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof AbstractMinecart) && movement == getDeltaMovement() && type == MoverType.SELF) { ++ setDeltaMovement(Vec3.ZERO); ++ this.level.getProfiler().pop(); ++ return; ++ } ++ // Paper end + + movement = this.maybeBackOffFromEdge(movement, type); + Vec3 vec3d1 = this.collide(movement); +@@ -2011,6 +2021,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + } + ++ public void syncPositionOf(Entity entity) { positionRider(entity); } // Paper - OBFHELPER + public void positionRider(Entity passenger) { + this.positionRider(passenger, Entity::setPos); + } +@@ -2821,6 +2832,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.stringUUID; + } + ++ public final boolean isPushedByWater() { return this.isPushedByFluid(); } // Paper - OBFHELPER - the below is not an obfhelper, don't use it! + public boolean isPushedByFluid() { + // Paper start + return this.pushedByWater(); +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 016fcc4ae20e1e48728a848be28633e624ae49a7..b84dab1043c56e2deb58aec8639226f98db165d1 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -189,7 +189,7 @@ public abstract class LivingEntity extends Entity { + protected float rotOffs; + protected int deathScore;protected int getKillCount() { return this.deathScore; } // Paper - OBFHELPER + public float lastHurt; +- protected boolean jumping; ++ public boolean jumping; // Paper protected -> public + public float xxa; + public float yya; + public float zza; +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 29a2eeee9f2011ed6fcc44f19041f616decfdb38..40ab66f888f30a5506e3aa96a4b32485452e8978 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -113,7 +113,7 @@ public abstract class Mob extends LivingEntity { + public ResourceLocation lootTable; + public long lootTableSeed; + @Nullable +- private Entity leashHolder; ++ public Entity leashHolder; // Paper - private -> public + private int delayedLeashHolderId; + @Nullable + private CompoundTag leashInfoTag; +@@ -194,6 +194,19 @@ public abstract class Mob extends LivingEntity { + return this.lookControl; + } + ++ // Paper start ++ @Override ++ public void inactiveTick() { ++ super.inactiveTick(); ++ if (this.goalSelector.inactiveTick()) { ++ this.goalSelector.tick(); ++ } ++ if (this.targetSelector.inactiveTick()) { ++ this.targetSelector.tick(); ++ } ++ } ++ // Paper end ++ + public MoveControl getMoveControl() { + if (this.isPassenger() && this.getVehicle() instanceof Mob) { + Mob entityinsentient = (Mob) this.getVehicle(); +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +index 920ae9af8985705a0ada7da5b7085a1ed8ca7f27..7c82d453388a27b69207d051dec316fc14715e2b 100644 +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -13,6 +13,7 @@ import org.bukkit.event.entity.EntityUnleashEvent; + public abstract class PathfinderMob extends Mob { + + public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper ++ public BlockPos movingTarget = null; public BlockPos getMovingTarget() { return movingTarget; } // Paper + + protected PathfinderMob(EntityType type, Level world) { + super(type, world); +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +index d44a5b7f6cf62d5e9acacad25d47cb0d44761cfa..558dd72c47930f6993952467f83b5a54ead95d92 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +@@ -20,7 +20,10 @@ public abstract class Goal { + + public void start() {} + +- public void stop() {} ++ public void stop() { ++ onTaskReset(); // Paper ++ } ++ public void onTaskReset() {} // Paper + + public void tick() {} + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +index 9066db5c9a76cfb9665bef77b36172f1ea6ba931..9bd2ee05a0de6678ad8933a8ffbe0ae66bd073b4 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +@@ -26,10 +26,11 @@ public class GoalSelector { + } + }; + private final Map lockedFlags = new EnumMap(Goal.Flag.class); +- private final Set availableGoals = Sets.newLinkedHashSet(); ++ private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER + private final Supplier profiler; + private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); +- private int newGoalRate = 3; ++ private int newGoalRate = 3;private int getTickRate() { return newGoalRate; } // Paper - OBFHELPER ++ private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO + + public GoalSelector(Supplier profiler) { + this.profiler = profiler; +@@ -39,6 +40,21 @@ public class GoalSelector { + this.availableGoals.add(new WrappedGoal(priority, goal)); + } + ++ // Paper start ++ public boolean inactiveTick() { ++ incRate(); ++ return getCurRate() % getTickRate() == 0; ++ } ++ public boolean hasTasks() { ++ for (WrappedGoal task : getTasks()) { ++ if (task.isRunning()) { ++ return true; ++ } ++ } ++ return false; ++ } ++ // Paper end ++ + public void removeGoal(Goal goal) { + this.availableGoals.stream().filter((pathfindergoalwrapped) -> { + return pathfindergoalwrapped.getGoal() == goal; +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +index c8680e795deeb68e0662eac7c760a103d1c767b4..e83cb412d8549b86d0348a2aa37c79201a5930be 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +@@ -9,12 +9,12 @@ import net.minecraft.world.level.LevelReader; + + public abstract class MoveToBlockGoal extends Goal { + +- protected final PathfinderMob mob; ++ protected final PathfinderMob mob;public PathfinderMob getEntity() { return mob; } // Paper - OBFHELPER + public final double speedModifier; + protected int nextStartTick; + protected int tryTicks; + private int maxStayTicks; +- protected BlockPos blockPos;public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER ++ protected BlockPos blockPos; public final BlockPos getTargetPosition() { return this.blockPos; } public void setTargetPosition(BlockPos pos) { this.blockPos = pos; getEntity().movingTarget = pos != BlockPos.ZERO ? pos : null; } // Paper - OBFHELPER + private boolean reachedTarget; + private final int searchRange; + private final int verticalSearchRange; +@@ -23,6 +23,13 @@ public abstract class MoveToBlockGoal extends Goal { + public MoveToBlockGoal(PathfinderMob mob, double speed, int range) { + this(mob, speed, range, 1); + } ++ // Paper start - activation range improvements ++ @Override ++ public void onTaskReset() { ++ super.onTaskReset(); ++ setTargetPosition(BlockPos.ZERO); ++ } ++ // Paper end + + public MoveToBlockGoal(PathfinderMob mob, double speed, int range, int maxYDifference) { + this.blockPos = BlockPos.ZERO; +@@ -111,6 +118,7 @@ public abstract class MoveToBlockGoal extends Goal { + blockposition_mutableblockposition.setWithOffset((Vec3i) blockposition, i1, k - 1, j1); + if (this.mob.isWithinRestriction((BlockPos) blockposition_mutableblockposition) && this.isValidTarget(this.mob.level, blockposition_mutableblockposition)) { + this.blockPos = blockposition_mutableblockposition; ++ setTargetPosition(blockposition_mutableblockposition.immutable()); // Paper + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +index 9921adf9292e0eff77515841d1b109a07b489367..81b4618a7979ee8dd25e1749c084de9262318ef4 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +@@ -64,6 +64,7 @@ public class WrappedGoal extends Goal { + return this.goal.getFlags(); + } + ++ public boolean isRunning() { return this.isRunning(); } // Paper - OBFHELPER + public boolean isRunning() { + return this.isRunning; + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java +index 5a7310bb48c1b8a72ad3c5d82c44fff8800995a2..a24af0600ad3e7d189581aa06a8e998f6a12e0fc 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java +@@ -454,6 +454,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { + return this.caravanTail != null; + } + ++ public final boolean inCaravan() { return this.inCaravan(); } // Paper - OBFHELPER + public boolean inCaravan() { + return this.caravanHead != null; + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +index ae8f850baa14a4f4277da5b6fdb1e5ccb44c4f35..9eee68a5a84e121698d26bd54212a72c75e16251 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -70,10 +70,12 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan + return super.finalizeSpawn(world, difficulty, spawnReason, (SpawnGroupData) entityData, entityTag); + } + ++ public final int getUnhappy() { return getUnhappyCounter(); } // Paper - OBFHELPER + public int getUnhappyCounter() { + return (Integer) this.entityData.get(AbstractVillager.DATA_UNHAPPY_COUNTER); + } + ++ public final void setUnhappy(int i) { setUnhappyCounter(i); } // Paper - OBFHELPER + public void setUnhappyCounter(int ticks) { + this.entityData.set(AbstractVillager.DATA_UNHAPPY_COUNTER, ticks); + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index eed6265dc8275921a18fc5f4970ba131ba782132..4aa34320ef7d6c62ccb17734bfa61d406190b919 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -212,17 +212,29 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + @Override + public void inactiveTick() { + // SPIGOT-3874, SPIGOT-3894, SPIGOT-3846, SPIGOT-5286 :( +- if (level.spigotConfig.tickInactiveVillagers && this.isEffectiveAi()) { +- this.customServerAiStep(); ++ // Paper start ++ if (this.getUnhappy() > 0) { ++ this.setUnhappy(this.getUnhappy() - 1); + } ++ if (this.isEffectiveAi()) { ++ if (level.spigotConfig.tickInactiveVillagers) { ++ this.customServerAiStep(); ++ } else { ++ this.mobTick(true); ++ } ++ } ++ doReputationTick(); ++ // Paper end ++ + super.inactiveTick(); + } + // Spigot End + + @Override +- protected void customServerAiStep() { ++ protected void customServerAiStep() { mobTick(false); } ++ protected void mobTick(boolean inactive) { + this.level.getProfiler().push("villagerBrain"); +- this.getBrain().tick((ServerLevel) this.level, this); // CraftBukkit - decompile error ++ if (!inactive) this.getBrain().tick((ServerLevel) this.level, this); // CraftBukkit - decompile error // Paper + this.level.getProfiler().pop(); + if (this.assignProfessionWhenSpawned) { + this.assignProfessionWhenSpawned = false; +@@ -246,7 +258,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + this.lastTradedPlayer = null; + } + +- if (!this.isNoAi() && this.random.nextInt(100) == 0) { ++ if (!inactive && !this.isNoAi() && this.random.nextInt(100) == 0) { // Paper + Raid raid = ((ServerLevel) this.level).getRaidAt(this.blockPosition()); + + if (raid != null && raid.isActive() && !raid.isOver()) { +@@ -257,6 +269,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.isTrading()) { + this.stopTrading(); + } ++ if (inactive) return; // Paper + + super.customServerAiStep(); + } +@@ -900,6 +913,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + } + } + ++ private void doReputationTick() { maybeDecayGossip(); } // Paper - OBFHELPER + private void maybeDecayGossip() { + long i = this.level.getGameTime(); + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 6b79f8cd9258af47afa6efa7b1f97c3780be58b0..1d536d77518a70bdc1a23924aea99df1042b3cd5 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -142,6 +142,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public long ticksPerWaterSpawns; + public long ticksPerWaterAmbientSpawns; + public long ticksPerAmbientSpawns; ++ // Paper start ++ public int wakeupInactiveRemainingAnimals; ++ public int wakeupInactiveRemainingFlying; ++ public int wakeupInactiveRemainingMonsters; ++ public int wakeupInactiveRemainingVillagers; ++ // Paper end + public boolean populating; + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3e4ac3eaf 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -1,41 +1,55 @@ + package org.spigotmc; + + import java.util.Collection; ++import net.minecraft.core.BlockPos; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.FlyingMob; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.PathfinderMob; ++import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ambient.AmbientCreature; + import net.minecraft.world.entity.animal.Animal; ++import net.minecraft.world.entity.animal.Bee; + import net.minecraft.world.entity.animal.Sheep; ++import net.minecraft.world.entity.animal.WaterAnimal; ++import net.minecraft.world.entity.animal.horse.Llama; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.entity.boss.enderdragon.EndCrystal; + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; + import net.minecraft.world.entity.boss.wither.WitherBoss; ++import net.minecraft.world.entity.item.FallingBlockEntity; + import net.minecraft.world.entity.item.PrimedTnt; + import net.minecraft.world.entity.monster.Creeper; +-import net.minecraft.world.entity.monster.Monster; +-import net.minecraft.world.entity.monster.Slime; ++import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.Pillager; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; ++import net.minecraft.world.entity.projectile.EyeOfEnder; + import net.minecraft.world.entity.projectile.FireworkRocketEntity; + import net.minecraft.world.entity.projectile.ThrowableProjectile; + import net.minecraft.world.entity.projectile.ThrownTrident; + import net.minecraft.world.entity.raid.Raider; ++import co.aikar.timings.MinecraftTimings; ++import net.minecraft.world.entity.schedule.Activity; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.phys.AABB; +-import co.aikar.timings.MinecraftTimings; + + public class ActivationRange + { + + public enum ActivationType + { ++ WATER, // Paper ++ FLYING_MONSTER, // Paper ++ VILLAGER, // Paper + MONSTER, + ANIMAL, + RAIDER, +@@ -43,6 +57,43 @@ public class ActivationRange + + AABB boundingBox = new AABB( 0, 0, 0, 0, 0, 0 ); + } ++ // Paper start ++ ++ static Activity[] VILLAGER_PANIC_IMMUNITIES = { ++ Activity.HIDE, ++ Activity.PRE_RAID, ++ Activity.RAID, ++ Activity.PANIC ++ }; ++ ++ private static int checkInactiveWakeup(Entity entity) { ++ Level world = entity.level; ++ SpigotWorldConfig config = world.spigotConfig; ++ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; ++ if (entity.activationType == ActivationType.VILLAGER) { ++ if (inactiveFor > config.wakeUpInactiveVillagersEvery && world.wakeupInactiveRemainingVillagers > 0) { ++ world.wakeupInactiveRemainingVillagers--; ++ return config.wakeUpInactiveVillagersFor; ++ } ++ } else if (entity.activationType == ActivationType.ANIMAL) { ++ if (inactiveFor > config.wakeUpInactiveAnimalsEvery && world.wakeupInactiveRemainingAnimals > 0) { ++ world.wakeupInactiveRemainingAnimals--; ++ return config.wakeUpInactiveAnimalsFor; ++ } ++ } else if (entity.activationType == ActivationType.FLYING_MONSTER) { ++ if (inactiveFor > config.wakeUpInactiveFlyingEvery && world.wakeupInactiveRemainingFlying > 0) { ++ world.wakeupInactiveRemainingFlying--; ++ return config.wakeUpInactiveFlyingFor; ++ } ++ } else if (entity.activationType == ActivationType.MONSTER || entity.activationType == ActivationType.RAIDER) { ++ if (inactiveFor > config.wakeUpInactiveMonstersEvery && world.wakeupInactiveRemainingMonsters > 0) { ++ world.wakeupInactiveRemainingMonsters--; ++ return config.wakeUpInactiveMonstersFor; ++ } ++ } ++ return -1; ++ } ++ // Paper end + + static AABB maxBB = new AABB( 0, 0, 0, 0, 0, 0 ); + +@@ -55,10 +106,13 @@ public class ActivationRange + */ + public static ActivationType initializeEntityActivationType(Entity entity) + { ++ if (entity instanceof WaterAnimal) { return ActivationType.WATER; } // Paper ++ else if (entity instanceof Villager) { return ActivationType.VILLAGER; } // Paper ++ else if (entity instanceof FlyingMob && entity instanceof Enemy) { return ActivationType.FLYING_MONSTER; } // Paper - doing & Monster incase Flying no longer includes monster in future + if ( entity instanceof Raider ) + { + return ActivationType.RAIDER; +- } else if ( entity instanceof Monster || entity instanceof Slime ) ++ } else if ( entity instanceof Enemy ) // Paper - correct monster check + { + return ActivationType.MONSTER; + } else if ( entity instanceof PathfinderMob || entity instanceof AmbientCreature ) +@@ -79,10 +133,14 @@ public class ActivationRange + */ + public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) + { +- if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange == 0 ) +- || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange == 0 ) +- || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange == 0 ) +- || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange == 0 ) ++ if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.VILLAGER && config.villagerActivationRange <= 0 ) // Paper ++ || ( entity.activationType == ActivationType.WATER && config.waterActivationRange <= 0 ) // Paper ++ || ( entity.activationType == ActivationType.FLYING_MONSTER && config.flyingMonsterActivationRange <= 0 ) // Paper ++ || entity instanceof EyeOfEnder // Paper + || entity instanceof Player + || entity instanceof ThrowableProjectile + || entity instanceof EnderDragon +@@ -91,7 +149,7 @@ public class ActivationRange + || entity instanceof AbstractHurtingProjectile + || entity instanceof LightningBolt + || entity instanceof PrimedTnt +- || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks ++ || entity instanceof FallingBlockEntity // Paper - Always tick falling blocks + || entity instanceof EndCrystal + || entity instanceof FireworkRocketEntity + || entity instanceof ThrownTrident ) +@@ -115,10 +173,25 @@ public class ActivationRange + final int raiderActivationRange = world.spigotConfig.raiderActivationRange; + final int animalActivationRange = world.spigotConfig.animalActivationRange; + final int monsterActivationRange = world.spigotConfig.monsterActivationRange; ++ // Paper start ++ final int waterActivationRange = world.spigotConfig.waterActivationRange; ++ final int flyingActivationRange = world.spigotConfig.flyingMonsterActivationRange; ++ final int villagerActivationRange = world.spigotConfig.villagerActivationRange; ++ world.wakeupInactiveRemainingAnimals = Math.min(world.wakeupInactiveRemainingAnimals + 1, world.spigotConfig.wakeUpInactiveAnimals); ++ world.wakeupInactiveRemainingVillagers = Math.min(world.wakeupInactiveRemainingVillagers + 1, world.spigotConfig.wakeUpInactiveVillagers); ++ world.wakeupInactiveRemainingMonsters = Math.min(world.wakeupInactiveRemainingMonsters + 1, world.spigotConfig.wakeUpInactiveMonsters); ++ world.wakeupInactiveRemainingFlying = Math.min(world.wakeupInactiveRemainingFlying + 1, world.spigotConfig.wakeUpInactiveFlying); ++ final ServerChunkCache chunkProvider = (ServerChunkCache) world.getChunkSource(); ++ // Paper end + + int maxRange = Math.max( monsterActivationRange, animalActivationRange ); + maxRange = Math.max( maxRange, raiderActivationRange ); + maxRange = Math.max( maxRange, miscActivationRange ); ++ // Paper start ++ maxRange = Math.max( maxRange, flyingActivationRange ); ++ maxRange = Math.max( maxRange, waterActivationRange ); ++ maxRange = Math.max( maxRange, villagerActivationRange ); ++ // Paper end + maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); + + for ( Player player : world.players() ) +@@ -130,6 +203,11 @@ public class ActivationRange + ActivationType.RAIDER.boundingBox = player.getBoundingBox().inflate( raiderActivationRange, 256, raiderActivationRange ); + ActivationType.ANIMAL.boundingBox = player.getBoundingBox().inflate( animalActivationRange, 256, animalActivationRange ); + ActivationType.MONSTER.boundingBox = player.getBoundingBox().inflate( monsterActivationRange, 256, monsterActivationRange ); ++ // Paper start ++ ActivationType.WATER.boundingBox = player.getBoundingBox().inflate( waterActivationRange, 256, waterActivationRange ); ++ ActivationType.FLYING_MONSTER.boundingBox = player.getBoundingBox().inflate( flyingActivationRange, 256, flyingActivationRange ); ++ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().inflate( villagerActivationRange, 256, waterActivationRange ); ++ // Paper end + + int i = Mth.floor( maxBB.minX / 16.0D ); + int j = Mth.floor( maxBB.maxX / 16.0D ); +@@ -140,7 +218,7 @@ public class ActivationRange + { + for ( int j1 = k; j1 <= l; ++j1 ) + { +- LevelChunk chunk = (LevelChunk) world.getChunkIfLoadedImmediately( i1, j1 ); ++ LevelChunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper + if ( chunk != null ) + { + activateChunkEntities( chunk ); +@@ -158,19 +236,15 @@ public class ActivationRange + */ + private static void activateChunkEntities(LevelChunk chunk) + { +- for ( java.util.List slice : chunk.entitySlices ) +- { +- for ( Entity entity : (Collection) slice ) ++ // Paper start ++ Entity[] rawData = chunk.entities.getRawData(); ++ for (int i = 0; i < chunk.entities.size(); i++) { ++ Entity entity = rawData[i]; ++ //for ( Entity entity : (Collection) slice ) ++ // Paper end + { +- if ( MinecraftServer.currentTick > entity.activatedTick ) +- { +- if ( entity.defaultActivationState ) +- { +- entity.activatedTick = MinecraftServer.currentTick; +- continue; +- } +- if ( entity.activationType.boundingBox.intersects( entity.getBoundingBox() ) ) +- { ++ if (MinecraftServer.currentTick > entity.activatedTick) { ++ if (entity.defaultActivationState || entity.activationType.boundingBox.intersects(entity.getBoundingBox())) { // Paper + entity.activatedTick = MinecraftServer.currentTick; + } + } +@@ -185,56 +259,105 @@ public class ActivationRange + * @param entity + * @return + */ +- public static boolean checkEntityImmunities(Entity entity) ++ public static int checkEntityImmunities(Entity entity) // Paper - return # of ticks to get immunity + { ++ // Paper start ++ SpigotWorldConfig config = entity.level.spigotConfig; ++ int inactiveWakeUpImmunity = checkInactiveWakeup(entity); ++ if (inactiveWakeUpImmunity > -1) { ++ return inactiveWakeUpImmunity; ++ } ++ if (entity.remainingFireTicks > 0) { ++ return 2; ++ } ++ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; ++ // Paper end + // quick checks. +- if ( entity.wasTouchingWater || entity.remainingFireTicks > 0 ) ++ if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByWater()) ) // Paper + { +- return true; ++ return 100; // Paper + } + if ( !( entity instanceof AbstractArrow ) ) + { +- if ( !entity.isOnGround() || !entity.passengers.isEmpty() || entity.isPassenger() ) ++ if ( (!entity.isOnGround() && !(entity instanceof FlyingMob)) ) // Paper - remove passengers logic + { +- return true; ++ return 10; // Paper + } + } else if ( !( (AbstractArrow) entity ).inGround ) + { +- return true; ++ return 1; // Paper + } + // special cases. + if ( entity instanceof LivingEntity ) + { + LivingEntity living = (LivingEntity) entity; +- if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTime > 0 || living.activeEffects.size() > 0 ) ++ if ( living.onClimbable() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 ) // Paper + { +- return true; ++ return 1; // Paper + } +- if ( entity instanceof PathfinderMob && ( (PathfinderMob) entity ).getTarget() != null ) ++ if ( entity instanceof Mob && ((Mob) entity ).getTarget() != null) // Paper + { +- return true; ++ return 20; // Paper ++ } ++ // Paper start ++ if (entity instanceof Bee) { ++ Bee bee = (Bee)entity; ++ BlockPos movingTarget = bee.getMovingTarget(); ++ if (bee.isAngry() || ++ (bee.getHivePos() != null && bee.getHivePos().equals(movingTarget)) || ++ (bee.getSavedFlowerPos() != null && bee.getSavedFlowerPos().equals(movingTarget)) ++ ) { ++ return 20; ++ } ++ } ++ if ( entity instanceof Villager ) { ++ Brain behaviorController = ((Villager) entity).getBrain(); ++ ++ if (config.villagersActiveForPanic) { ++ for (Activity activity : VILLAGER_PANIC_IMMUNITIES) { ++ if (behaviorController.isActive(activity)) { ++ return 20*5; ++ } ++ } ++ } ++ ++ if (config.villagersWorkImmunityAfter > 0 && inactiveFor >= config.villagersWorkImmunityAfter) { ++ if (behaviorController.isActive(Activity.WORK)) { ++ return config.villagersWorkImmunityFor; ++ } ++ } + } +- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() ) ++ if ( entity instanceof Llama && ( (Llama) entity ).inCaravan() ) + { +- return true; ++ return 1; + } ++ // Paper end + if ( entity instanceof Animal ) + { + Animal animal = (Animal) entity; + if ( animal.isBaby() || animal.isInLove() ) + { +- return true; ++ return 5; // Paper + } + if ( entity instanceof Sheep && ( (Sheep) entity ).isSheared() ) + { +- return true; ++ return 1; // Paper + } + } + if (entity instanceof Creeper && ((Creeper) entity).isIgnited()) { // isExplosive +- return true; ++ return 20; // Paper + } ++ // Paper start ++ if (entity instanceof Mob && ((Mob) entity).targetSelector.hasTasks() ) { ++ return 0; ++ } ++ if (entity instanceof Pillager) { ++ Pillager pillager = (Pillager) entity; ++ // TODO:? ++ } ++ // Paper end + } +- return false; ++ return -1; // Paper + } + + /** +@@ -249,8 +372,19 @@ public class ActivationRange + if ( !entity.inChunk || entity instanceof FireworkRocketEntity ) { + return true; + } ++ // Paper start - special case always immunities ++ // immunize brand new entities, dead entities, and portal scenarios ++ if (entity.defaultActivationState || entity.tickCount < 20*10 || !entity.isAlive() || entity.isInsidePortal || entity.portalCooldown > 0) { ++ return true; ++ } ++ // immunize leashed entities ++ if (entity instanceof Mob && ((Mob)entity).leashHolder instanceof Player) { ++ return true; ++ } ++ // Paper end + +- boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; ++ boolean isActive = entity.activatedTick >= MinecraftServer.currentTick; ++ entity.isTemporarilyActive = false; // Paper + + // Should this entity tick? + if ( !isActive ) +@@ -258,15 +392,19 @@ public class ActivationRange + if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) + { + // Check immunities every 20 ticks. +- if ( checkEntityImmunities( entity ) ) +- { +- // Triggered some sort of immunity, give 20 full ticks before we check again. +- entity.activatedTick = MinecraftServer.currentTick + 20; ++ // Paper start ++ int immunity = checkEntityImmunities(entity); ++ if (immunity >= 0) { ++ entity.activatedTick = MinecraftServer.currentTick + immunity; ++ } else { ++ entity.isTemporarilyActive = true; + } ++ // Paper end + isActive = true; ++ + } + // Add a little performance juice to active entities. Skip 1/4 if not immune. +- } else if ( !entity.defaultActivationState && entity.tickCount % 4 == 0 && !checkEntityImmunities( entity ) ) ++ } else if (entity.tickCount % 4 == 0 && checkEntityImmunities( entity) < 0 ) // Paper + { + isActive = false; + } +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 34ee684901906fc2ef5f0d09680d2686b813e52b..6b015c1f26facb4e82d75b252164dec05731ca6c 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -180,13 +180,59 @@ public class SpigotWorldConfig + public int monsterActivationRange = 32; + public int raiderActivationRange = 48; + public int miscActivationRange = 16; ++ // Paper start ++ public int flyingMonsterActivationRange = 32; ++ public int waterActivationRange = 16; ++ public int villagerActivationRange = 32; ++ public int wakeUpInactiveAnimals = 4; ++ public int wakeUpInactiveAnimalsEvery = 60*20; ++ public int wakeUpInactiveAnimalsFor = 5*20; ++ public int wakeUpInactiveMonsters = 8; ++ public int wakeUpInactiveMonstersEvery = 20*20; ++ public int wakeUpInactiveMonstersFor = 5*20; ++ public int wakeUpInactiveVillagers = 4; ++ public int wakeUpInactiveVillagersEvery = 30*20; ++ public int wakeUpInactiveVillagersFor = 5*20; ++ public int wakeUpInactiveFlying = 8; ++ public int wakeUpInactiveFlyingEvery = 10*20; ++ public int wakeUpInactiveFlyingFor = 5*20; ++ public int villagersWorkImmunityAfter = 5*20; ++ public int villagersWorkImmunityFor = 20; ++ public boolean villagersActiveForPanic = true; ++ // Paper end + public boolean tickInactiveVillagers = true; + private void activationRange() + { ++ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", animalActivationRange) != animalActivationRange; // Paper + animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange ); + monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange ); + raiderActivationRange = getInt( "entity-activation-range.raiders", raiderActivationRange ); + miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange ); ++ // Paper start ++ waterActivationRange = getInt( "entity-activation-range.water", waterActivationRange ); ++ villagerActivationRange = getInt( "entity-activation-range.villagers", hasAnimalsConfig ? animalActivationRange : villagerActivationRange ); ++ flyingMonsterActivationRange = getInt( "entity-activation-range.flying-monsters", flyingMonsterActivationRange ); ++ ++ wakeUpInactiveAnimals = getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", wakeUpInactiveAnimals); ++ wakeUpInactiveAnimalsEvery = getInt("entity-activation-range.wake-up-inactive.animals-every", wakeUpInactiveAnimalsEvery); ++ wakeUpInactiveAnimalsFor = getInt("entity-activation-range.wake-up-inactive.animals-for", wakeUpInactiveAnimalsFor); ++ ++ wakeUpInactiveMonsters = getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", wakeUpInactiveMonsters); ++ wakeUpInactiveMonstersEvery = getInt("entity-activation-range.wake-up-inactive.monsters-every", wakeUpInactiveMonstersEvery); ++ wakeUpInactiveMonstersFor = getInt("entity-activation-range.wake-up-inactive.monsters-for", wakeUpInactiveMonstersFor); ++ ++ wakeUpInactiveVillagers = getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", wakeUpInactiveVillagers); ++ wakeUpInactiveVillagersEvery = getInt("entity-activation-range.wake-up-inactive.villagers-every", wakeUpInactiveVillagersEvery); ++ wakeUpInactiveVillagersFor = getInt("entity-activation-range.wake-up-inactive.villagers-for", wakeUpInactiveVillagersFor); ++ ++ wakeUpInactiveFlying = getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", wakeUpInactiveFlying); ++ wakeUpInactiveFlyingEvery = getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", wakeUpInactiveFlyingEvery); ++ wakeUpInactiveFlyingFor = getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", wakeUpInactiveFlyingFor); ++ ++ villagersWorkImmunityAfter = getInt( "entity-activation-range.villagers-work-immunity-after", villagersWorkImmunityAfter ); ++ villagersWorkImmunityFor = getInt( "entity-activation-range.villagers-work-immunity-for", villagersWorkImmunityFor ); ++ villagersActiveForPanic = getBoolean( "entity-activation-range.villagers-active-for-panic", villagersActiveForPanic ); ++ // Paper end + tickInactiveVillagers = getBoolean( "entity-activation-range.tick-inactive-villagers", tickInactiveVillagers ); + log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Ra " + raiderActivationRange + " / Mi " + miscActivationRange + " / Tiv " + tickInactiveVillagers ); + } diff --git a/patches/server-remapped/0401-Fix-items-vanishing-through-end-portal.patch b/patches/server-remapped/0401-Fix-items-vanishing-through-end-portal.patch new file mode 100644 index 0000000000..283ad7000c --- /dev/null +++ b/patches/server-remapped/0401-Fix-items-vanishing-through-end-portal.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AJMFactsheets +Date: Wed, 22 Jan 2020 19:52:28 -0600 +Subject: [PATCH] Fix items vanishing through end portal + +If the Paper configuration option "keep-spawn-loaded" is set to false, +items entering the overworld from the end will spawn at Y = 0. + +This is due to logic in the getHighestBlockYAt method in World.java +only searching the heightmap if the chunk is loaded. + +Quickly loading the exact world spawn chunk before searching the +heightmap resolves the issue without having to load all spawn chunks. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index c6881a9a5da2caed77dea30e4906d2dd99a624c1..efc9cb6def2f4ee327329dc090d2918ff60d8e19 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2734,6 +2734,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + BlockPos blockposition1; + + if (flag1) { ++ // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate ++ this.level.getChunkAt(this.level.getSpawn()); ++ // Paper end + blockposition1 = ServerLevel.END_SPAWN_POINT; + } else { + blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSpawn()); diff --git a/patches/server-remapped/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server-remapped/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch new file mode 100644 index 0000000000..f19be75b52 --- /dev/null +++ b/patches/server-remapped/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 26 Jan 2020 16:30:19 -0600 +Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java +index 2c9e3dd1b9dd7bb8825a2eb9fecc2b2be348d055..868e9cdeb3c7effb398cef6f6f9c1e4fffa2db8c 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java +@@ -16,7 +16,7 @@ public class FlyingMoveControl extends MoveControl { + } + + @Override +- public void tick() { ++ public void tick() { tick(); } public void tick() { // Paper - OBFHELPER + if (this.operation == MoveControl.Operation.MOVE_TO) { + this.operation = MoveControl.Operation.WAIT; + this.mob.setNoGravity(true); +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java +index ab65f0327766463a5e53fdd723e243464319fdbe..f4984d601d14c684e75f887f5f5d2f5a29326b15 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java +@@ -16,7 +16,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; + + public class MoveControl { + +- protected final Mob mob; ++ protected final Mob mob; public final Mob getEntity() { return mob; } // Paper - OBFHELPER + protected double wantedX; + protected double wantedY; + protected double wantedZ; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java +index edd6d63f715acef1a77eba0cf46ff8267228f4c6..9b68809b91910d2bbb82cafe23d1de5dfff4221c 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -111,7 +111,17 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + + public Bee(EntityType type, Level world) { + super(type, world); +- this.moveControl = new FlyingMoveControl(this, 20, true); ++ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 ++ this.moveControl = new FlyingMoveControl(this, 20, true) { ++ @Override ++ public void tick() { ++ if (getEntity().getY() <= 0) { ++ getEntity().setNoGravity(false); ++ } ++ super.tick(); ++ } ++ }; ++ // Paper end + this.lookControl = new Bee.BeeLookControl(this); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); diff --git a/patches/server-remapped/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server-remapped/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch new file mode 100644 index 0000000000..009a0fad66 --- /dev/null +++ b/patches/server-remapped/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 25 Jan 2020 17:04:35 -0800 +Subject: [PATCH] Optimise getChunkAt calls for loaded chunks + +bypass the need to get a player chunk, then get the either, +then unwrap it... + +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index eac5e799c4d26e53286a27c54b56899ba0b9ffb2..3aeb8426b0461ec572c1499116be80f968bb4104 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -470,6 +470,12 @@ public class ServerChunkCache extends ChunkSource { + return this.getChunk(x, z, leastStatus, create); + }, this.mainThreadProcessor).join(); + } else { ++ // Paper start - optimise for loaded chunks ++ LevelChunk ifLoaded = this.getChunkAtIfLoadedMainThread(x, z); ++ if (ifLoaded != null) { ++ return ifLoaded; ++ } ++ // Paper end + ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + + gameprofilerfiller.incrementCounter("getChunk"); +@@ -520,39 +526,7 @@ public class ServerChunkCache extends ChunkSource { + if (Thread.currentThread() != this.mainThread) { + return null; + } else { +- this.level.getProfiler().incrementCounter("getChunkNow"); +- long k = ChunkPos.asLong(chunkX, chunkZ); +- +- for (int l = 0; l < 4; ++l) { +- if (k == this.lastChunkPos[l] && this.lastChunkStatus[l] == ChunkStatus.FULL) { +- ChunkAccess ichunkaccess = this.lastChunk[l]; +- +- return ichunkaccess instanceof LevelChunk ? (LevelChunk) ichunkaccess : null; +- } +- } +- +- ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); +- +- if (playerchunk == null) { +- return null; +- } else { +- Either either = (Either) playerchunk.getFutureIfPresent(ChunkStatus.FULL).getNow(null); // CraftBukkit - decompile error +- +- if (either == null) { +- return null; +- } else { +- ChunkAccess ichunkaccess1 = (ChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error +- +- if (ichunkaccess1 != null) { +- this.storeInCache(k, ichunkaccess1, ChunkStatus.FULL); +- if (ichunkaccess1 instanceof LevelChunk) { +- return (LevelChunk) ichunkaccess1; +- } +- } +- +- return null; +- } +- } ++ return this.getChunkAtIfLoadedMainThread(chunkX, chunkZ); // Paper - optimise for loaded chunks + } + } + diff --git a/patches/server-remapped/0404-Allow-overriding-the-java-version-check.patch b/patches/server-remapped/0404-Allow-overriding-the-java-version-check.patch new file mode 100644 index 0000000000..04082e9a36 --- /dev/null +++ b/patches/server-remapped/0404-Allow-overriding-the-java-version-check.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 8 Feb 2020 18:02:24 -0600 +Subject: [PATCH] Allow overriding the java version check + +-DPaper.IgnoreJavaVersion=true + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 808a7688ed81bdfef623ee0a151ff8f94df2a3d7..c519ceca6f7788ca7c5d74ad1001dbc09f62681c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -181,7 +181,7 @@ public class Main { + float javaVersion = Float.parseFloat(System.getProperty("java.class.version")); + if (javaVersion > 60.0) { + System.err.println("Unsupported Java detected (" + javaVersion + "). Only up to Java 16 is supported."); +- return; ++ if (!Boolean.getBoolean("Paper.IgnoreJavaVersion")) return; // Paper + } + + try { diff --git a/patches/server-remapped/0405-Add-ThrownEggHatchEvent.patch b/patches/server-remapped/0405-Add-ThrownEggHatchEvent.patch new file mode 100644 index 0000000000..5bc9d2e683 --- /dev/null +++ b/patches/server-remapped/0405-Add-ThrownEggHatchEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 9 Feb 2020 00:19:05 -0600 +Subject: [PATCH] Add ThrownEggHatchEvent + +Adds a new event similar to PlayerEggThrowEvent, but without the Player requirement +(dispensers can throw eggs to hatch them, too). + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java +index f3808a5e9155e1bf6c6219fc494864bb7dc61117..520eace73b569c2c77e76e0dfd18eb9c7188ec30 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java +@@ -63,6 +63,16 @@ public class ThrownEgg extends ThrowableItemProjectile { + hatchingType = event.getHatchingType(); + } + ++ // Paper start ++ com.destroystokyo.paper.event.entity.ThrownEggHatchEvent event = new com.destroystokyo.paper.event.entity.ThrownEggHatchEvent((org.bukkit.entity.Egg) getBukkitEntity(), hatching, b0, hatchingType); ++ event.callEvent(); ++ ++ b0 = event.getNumHatches(); ++ hatching = event.isHatching(); ++ hatchingType = event.getHatchingType(); ++ // Paper end ++ ++ + if (hatching) { + for (int i = 0; i < b0; ++i) { + Entity entity = level.getWorld().createEntity(new org.bukkit.Location(level.getWorld(), this.getX(), this.getY(), this.getZ(), this.yRot, 0.0F), hatchingType.getEntityClass()); diff --git a/patches/server-remapped/0406-Optimise-random-block-ticking.patch b/patches/server-remapped/0406-Optimise-random-block-ticking.patch new file mode 100644 index 0000000000..881f7be3f4 --- /dev/null +++ b/patches/server-remapped/0406-Optimise-random-block-ticking.patch @@ -0,0 +1,407 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 27 Jan 2020 21:28:00 -0800 +Subject: [PATCH] Optimise random block ticking + +Massive performance improvement for random block ticking. +The performance increase comes from the fact that the vast +majority of attempted block ticks (~95% in my testing) fail +because the randomly selected block is not tickable. + +Now only tickable blocks are targeted, however this means that +the maximum number of block ticks occurs per chunk. However, +not all chunks are going to be targeted. The percent chance +of a chunk being targeted is based on how many tickable blocks +are in the chunk. +This means that while block ticks are spread out less, the +total number of blocks ticked per world tick remains the same. +Therefore, the chance of a random tickable block being ticked +remains the same. + +diff --git a/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3edc8e52e06a62ce9f8cc734fd7458b37cfaad91 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java +@@ -0,0 +1,46 @@ ++package com.destroystokyo.paper.util.math; ++ ++import java.util.Random; ++ ++public final class ThreadUnsafeRandom extends Random { ++ ++ // See javadoc and internal comments for java.util.Random where these values come from, how they are used, and the author for them. ++ private static final long multiplier = 0x5DEECE66DL; ++ private static final long addend = 0xBL; ++ private static final long mask = (1L << 48) - 1; ++ ++ private static long initialScramble(long seed) { ++ return (seed ^ multiplier) & mask; ++ } ++ ++ private long seed; ++ ++ @Override ++ public void setSeed(long seed) { ++ // note: called by Random constructor ++ this.seed = initialScramble(seed); ++ } ++ ++ @Override ++ protected int next(int bits) { ++ // avoid the expensive CAS logic used by superclass ++ return (int) (((this.seed = this.seed * multiplier + addend) & mask) >>> (48 - bits)); ++ } ++ ++ // Taken from ++ // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ ++ // https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2016/06/25/fastrange.c ++ // Original license is public domain ++ public static int fastRandomBounded(final long randomInteger, final long limit) { ++ // randomInteger must be [0, pow(2, 32)) ++ // limit must be [0, pow(2, 32)) ++ return (int)((randomInteger * limit) >>> 32); ++ } ++ ++ @Override ++ public int nextInt(int bound) { ++ // yes this breaks random's spec ++ // however there's nothing that uses this class that relies on it ++ return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound); ++ } ++} +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index b13e5d05d862ea8c6031b8071f525f00bc48f7e7..3db77d9eda98eacb099135643aff5e94751f4c7c 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -468,6 +468,7 @@ public class BlockPos extends Vec3i { + return this.set(Mth.floor(x), Mth.floor(y), Mth.floor(z)); + } + ++ public final BlockPos.MutableBlockPos setValues(final Vec3i baseblockposition) { return this.set(baseblockposition); } // Paper - OBFHELPER + public BlockPos.MutableBlockPos set(Vec3i pos) { + return this.set(pos.getX(), pos.getY(), pos.getZ()); + } +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027ea23b400b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -669,7 +669,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + }); + } + +- public void tickChunk(LevelChunk chunk, int randomTickSpeed) { ++ // Paper start - optimise random block ticking ++ private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos(); ++ private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom(); ++ // Paper end ++ ++ public void tickChunk(LevelChunk chunk, int randomTickSpeed) { final int randomTickSpeed1 = randomTickSpeed; // Paper + ChunkPos chunkcoordintpair = chunk.getPos(); + boolean flag = this.isRaining(); + int j = chunkcoordintpair.getMinBlockX(); +@@ -677,10 +682,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + ProfilerFiller gameprofilerfiller = this.getProfiler(); + + gameprofilerfiller.push("thunder"); +- BlockPos blockposition; ++ final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change + + if (!this.paperConfig.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder +- blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); ++ blockposition.setValues(this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper + if (this.isRainingAt(blockposition)) { + DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); + boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance; // Paper +@@ -703,59 +708,77 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + gameprofilerfiller.popPush("iceandsnow"); +- if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow +- blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.getBlockRandomPos(j, 0, k, 15)); +- BlockPos blockposition1 = blockposition.below(); ++ if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking ++ // Paper start - optimise chunk ticking ++ this.getRandomBlockPosition(j, 0, k, 15, blockposition); ++ int normalY = chunk.getHighestBlockY(Heightmap.Types.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15); ++ int downY = normalY - 1; ++ blockposition.setY(normalY); ++ // Paper end + Biome biomebase = this.getBiome(blockposition); + +- if (biomebase.shouldFreeze(this, blockposition1)) { +- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.defaultBlockState(), null); // CraftBukkit ++ // Paper start - optimise chunk ticking ++ blockposition.setY(downY); ++ if (biomebase.shouldFreeze(this, blockposition)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.ICE.defaultBlockState(), null); // CraftBukkit ++ // Paper end + } + ++ blockposition.setY(normalY); // Paper + if (flag && biomebase.shouldSnow(this, blockposition)) { + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit + } + +- if (flag && this.getBiome(blockposition1).getPrecipitation() == Biome.Precipitation.RAIN) { +- this.getBlockState(blockposition1).getBlock().handleRain((net.minecraft.world.level.Level) this, blockposition1); ++ // Paper start - optimise chunk ticking ++ blockposition.setY(downY); ++ if (flag && this.getBiome(blockposition).getPrecipitation() == Biome.Precipitation.RAIN) { ++ chunk.getBlockState(blockposition).getBlock().handleRain((net.minecraft.world.level.Level) this, blockposition); ++ // Paper end + } + } + +- gameprofilerfiller.popPush("tickBlocks"); +- timings.chunkTicksBlocks.startTiming(); // Paper ++ // Paper start - optimise random block ticking ++ gameprofilerfiller.pop(); + if (randomTickSpeed > 0) { +- LevelChunkSection[] achunksection = chunk.getSections(); +- int l = achunksection.length; ++ gameprofilerfiller.push("randomTick"); ++ timings.chunkTicksBlocks.startTiming(); // Paper + +- for (int i1 = 0; i1 < l; ++i1) { +- LevelChunkSection chunksection = achunksection[i1]; ++ LevelChunkSection[] sections = chunk.getSections(); + +- if (chunksection != LevelChunk.EMPTY_SECTION && chunksection.isRandomlyTicking()) { +- int j1 = chunksection.bottomBlockY(); ++ for (int sectionIndex = 0; sectionIndex < 16; ++sectionIndex) { ++ LevelChunkSection section = sections[sectionIndex]; ++ if (section == null || section.tickingList.size() == 0) { ++ continue; ++ } + +- for (int k1 = 0; k1 < randomTickSpeed; ++k1) { +- BlockPos blockposition2 = this.getBlockRandomPos(j, j1, k, 15); ++ int yPos = sectionIndex << 4; + +- gameprofilerfiller.push("randomTick"); +- BlockState iblockdata = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); ++ for (int a = 0; a < randomTickSpeed1; ++a) { ++ int tickingBlocks = section.tickingList.size(); ++ int index = this.randomTickRandom.nextInt(16 * 16 * 16); ++ if (index >= tickingBlocks) { ++ continue; ++ } + +- if (iblockdata.isRandomlyTicking()) { +- iblockdata.randomTick(this, blockposition2, this.random); +- } ++ long raw = section.tickingList.getRaw(index); ++ int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); ++ int randomX = location & 15; ++ int randomY = ((location >>> (4 + 4)) & 255) | yPos; ++ int randomZ = (location >>> 4) & 15; + +- FluidState fluid = iblockdata.getFluidState(); ++ BlockPos blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ); ++ BlockState iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); + +- if (fluid.isRandomlyTicking()) { +- fluid.randomTick(this, blockposition2, this.random); +- } ++ iblockdata.randomTick(this, blockposition2, this.randomTickRandom); + +- gameprofilerfiller.pop(); +- } ++ // We drop the fluid tick since LAVA is ALREADY TICKED by the above method. ++ // TODO CHECK ON UPDATE + } + } ++ gameprofilerfiller.pop(); ++ timings.chunkTicksBlocks.stopTiming(); // Paper ++ // Paper end + } +- timings.chunkTicksBlocks.stopTiming(); // Paper +- gameprofilerfiller.pop(); + } + + protected BlockPos findLightingTargetAround(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java +index dd84984f28484cf7129c294222696784e128221a..9ea72751354e893cd3820befaa5df3e5e503de6e 100644 +--- a/src/main/java/net/minecraft/util/BitStorage.java ++++ b/src/main/java/net/minecraft/util/BitStorage.java +@@ -112,4 +112,32 @@ public class BitStorage { + } + + } ++ ++ // Paper start ++ public final void forEach(DataBitConsumer consumer) { ++ int i = 0; ++ long[] along = this.data; ++ int j = along.length; ++ ++ for (int k = 0; k < j; ++k) { ++ long l = along[k]; ++ ++ for (int i1 = 0; i1 < this.valuesPerLong; ++i1) { ++ consumer.accept(i, (int) (l & this.mask)); ++ l >>= this.bits; ++ ++i; ++ if (i >= this.size) { ++ return; ++ } ++ } ++ } ++ } ++ ++ @FunctionalInterface ++ public static interface DataBitConsumer { ++ ++ void accept(int location, int data); ++ ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +index 42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3..0e15ca2fb9cd1aeb4a075b8d50350dd7fd463c72 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +@@ -91,7 +91,7 @@ public class Turtle extends Animal { + } + + public void setHomePos(BlockPos pos) { +- this.entityData.set(Turtle.HOME_POS, pos); ++ this.entityData.set(Turtle.HOME_POS, pos.immutable()); // Paper - called with mutablepos... + } + + public BlockPos getHomePos() { // Paper - public +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 1d536d77518a70bdc1a23924aea99df1042b3cd5..632f32405053fbcff2fd26fa99f98c6add9f9dc7 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -1472,10 +1472,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public abstract TagContainer getTagManager(); + + public BlockPos getBlockRandomPos(int x, int y, int z, int l) { ++ // Paper start - allow use of mutable pos ++ BlockPos.MutableBlockPos ret = new BlockPos.MutableBlockPos(); ++ this.getRandomBlockPosition(x, y, z, l, ret); ++ return ret.immutable(); ++ } ++ public final BlockPos.MutableBlockPos getRandomBlockPosition(int i, int j, int k, int l, BlockPos.MutableBlockPos out) { ++ // Paper end + this.randValue = this.randValue * 3 + 1013904223; + int i1 = this.randValue >> 2; + +- return new BlockPos(x + (i1 & 15), y + (i1 >> 16 & l), z + (i1 >> 8 & 15)); ++ out.setValues(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); // Paper - change to setValues call ++ return out; // Paper + } + + public boolean noSave() { +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 4fef3abe4b416cbebe1b456468b5c3e162de18f1..87d7a87a2925f2c062658e960bb5128738828d9f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -639,8 +639,8 @@ public class LevelChunk implements ChunkAccess { + this.entities.remove(entity); // Paper + } + +- @Override +- public int getHeight(Heightmap.Types type, int x, int z) { ++ public final int getHighestBlockY(Heightmap.Types heightmap_type, int i, int j) { return this.getHeight(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1 ++ @Override public int getHeight(Heightmap.Types type, int x, int z) { // Paper + return ((Heightmap) this.heightmaps.get(type)).getFirstAvailable(x & 15, z & 15) - 1; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a71ad031d9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -14,12 +14,14 @@ import net.minecraft.world.level.material.FluidState; + public class LevelChunkSection { + + public static final Palette GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState()); +- private final int bottomBlockY; ++ final int bottomBlockY; // Paper - private -> package-private + short nonEmptyBlockCount; // Paper - package-private +- private short tickingBlockCount; ++ short tickingBlockCount; // Paper - private -> package-private + private short tickingFluidCount; + final PalettedContainer states; // Paper - package-private + ++ public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper ++ + // Paper start - Anti-Xray - Add parameters + @Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere + public LevelChunkSection(int i, ChunkAccess chunk, Level world, boolean initializeBlocks) { +@@ -74,6 +76,9 @@ public class LevelChunkSection { + --this.nonEmptyBlockCount; + if (iblockdata1.isRandomlyTicking()) { + --this.tickingBlockCount; ++ // Paper start ++ this.tickingList.remove(x, y, z); ++ // Paper end + } + } + +@@ -85,6 +90,9 @@ public class LevelChunkSection { + ++this.nonEmptyBlockCount; + if (state.isRandomlyTicking()) { + ++this.tickingBlockCount; ++ // Paper start ++ this.tickingList.add(x, y, z, state); ++ // Paper end + } + } + +@@ -120,23 +128,29 @@ public class LevelChunkSection { + } + + public void recalcBlockCounts() { ++ // Paper start ++ this.tickingList.clear(); ++ // Paper end + this.nonEmptyBlockCount = 0; + this.tickingBlockCount = 0; + this.tickingFluidCount = 0; +- this.states.count((iblockdata, i) -> { ++ this.states.forEachLocation((iblockdata, location) -> { // Paper + FluidState fluid = iblockdata.getFluidState(); + + if (!iblockdata.isAir()) { +- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); ++ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); + if (iblockdata.isRandomlyTicking()) { +- this.tickingBlockCount = (short) (this.tickingBlockCount + i); ++ this.tickingBlockCount = (short) (this.tickingBlockCount + 1); ++ // Paper start ++ this.tickingList.add(location, iblockdata); ++ // Paper end + } + } + + if (!fluid.isEmpty()) { +- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); ++ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); + if (fluid.isRandomlyTicking()) { +- this.tickingFluidCount = (short) (this.tickingFluidCount + i); ++ this.tickingFluidCount = (short) (this.tickingFluidCount + 1); + } + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index dd252372e1e380674b1191e9ea265cbb10de437b..f93316b3ae5cd5fb960fa24f8c921b5b9276d9f3 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -285,6 +285,14 @@ public class PalettedContainer implements PaletteResize { + }); + } + ++ // Paper start ++ public void forEachLocation(PalettedContainer.CountConsumer datapaletteblock_a) { ++ this.getDataBits().forEach((int location, int data) -> { ++ datapaletteblock_a.accept(this.getDataPalette().getObject(data), location); ++ }); ++ } ++ // Paper end ++ + @FunctionalInterface + public interface CountConsumer { + diff --git a/patches/server-remapped/0407-Entity-Jump-API.patch b/patches/server-remapped/0407-Entity-Jump-API.patch new file mode 100644 index 0000000000..15c22b27a5 --- /dev/null +++ b/patches/server-remapped/0407-Entity-Jump-API.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 8 Feb 2020 23:26:11 -0600 +Subject: [PATCH] Entity Jump API + + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index b84dab1043c56e2deb58aec8639226f98db165d1..43fbe7d220f61802ae0cb0620ad078c5df7b69bc 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -2873,8 +2873,10 @@ public abstract class LivingEntity extends Entity { + } else if (this.isInLava() && (!this.onGround || d7 > d8)) { + this.jumpInLiquid((Tag) FluidTags.LAVA); + } else if ((this.onGround || flag && d7 <= d8) && this.noJumpDelay == 0) { ++ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper + this.jumpFromGround(); + this.noJumpDelay = 10; ++ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop + } + } else { + this.noJumpDelay = 0; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java +index 1621d8748e96c6e1abb33b699a1273bb698f67d2..423bdbe25b6f2261cb5092378b0564a82faeecb4 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Panda.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java +@@ -489,7 +489,9 @@ public class Panda extends Animal { + Panda entitypanda = (Panda) iterator.next(); + + if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.canPerformAction()) { ++ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper + entitypanda.jumpFromGround(); ++ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop + } + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index a01bd035846df0e2e28dc55e2ef2f5f35b83f905..5dac3bf5a117bfbf57798238f0614558deafcd1b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -792,5 +792,19 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public org.bukkit.inventory.EquipmentSlot getHandRaised() { + return getHandle().getUsedItemHand() == net.minecraft.world.InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; + } ++ ++ @Override ++ public boolean isJumping() { ++ return getHandle().jumping; ++ } ++ ++ @Override ++ public void setJumping(boolean jumping) { ++ getHandle().setJumping(jumping); ++ if (jumping && getHandle() instanceof Mob) { ++ // this is needed to actually make a mob jump ++ ((Mob) getHandle()).getJumpControl().jump(); ++ } ++ } + // Paper end + } diff --git a/patches/server-remapped/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server-remapped/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch new file mode 100644 index 0000000000..d66918d012 --- /dev/null +++ b/patches/server-remapped/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 7 Feb 2020 14:36:56 -0600 +Subject: [PATCH] Add option to nerf pigmen from nether portals + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 7fbd501d70dccf869a4454e2789a5d68f2e15754..9e4591ddc4b755f4ff5a6f1078b51cb13db80480 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -594,4 +594,9 @@ public class PaperWorldConfig { + disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); + log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); + } ++ ++ public boolean nerfNetherPortalPigmen = false; ++ private void nerfNetherPortalPigmen() { ++ nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index efc9cb6def2f4ee327329dc090d2918ff60d8e19..43f77d01fceab107d3502d282205aa579d64cc4b 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -277,6 +277,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public long activatedTick = Integer.MIN_VALUE; + public boolean isTemporarilyActive = false; // Paper + public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one ++ public boolean fromNetherPortal; // Paper + protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end +@@ -1693,6 +1694,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + if (spawnedViaMobSpawner) { + tag.putBoolean("Paper.FromMobSpawner", true); + } ++ if (fromNetherPortal) { ++ tag.putBoolean("Paper.FromNetherPortal", true); ++ } + // Paper end + return tag; + } catch (Throwable throwable) { +@@ -1827,6 +1831,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ fromNetherPortal = tag.getBoolean("Paper.FromNetherPortal"); + if (tag.contains("Paper.SpawnReason")) { + String spawnReasonName = tag.getString("Paper.SpawnReason"); + try { +diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +index 805d83a93bce20910d17c3f419bc085251b6cfc1..ae58929886921d0714bf811de92f99dc0dc120dc 100644 +--- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -8,6 +8,7 @@ import net.minecraft.network.chat.Component; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; +@@ -61,6 +62,8 @@ public class NetherPortalBlock extends Block { + + if (entity != null) { + entity.setPortalCooldown(); ++ entity.fromNetherPortal = true; // Paper ++ if (world.paperConfig.nerfNetherPortalPigmen) ((Mob) entity).aware = false; // Paper + } + } + } diff --git a/patches/server-remapped/0409-Make-the-GUI-graph-fancier.patch b/patches/server-remapped/0409-Make-the-GUI-graph-fancier.patch new file mode 100644 index 0000000000..c98d2918e6 --- /dev/null +++ b/patches/server-remapped/0409-Make-the-GUI-graph-fancier.patch @@ -0,0 +1,439 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 2 Feb 2020 04:00:40 -0600 +Subject: [PATCH] Make the GUI graph fancier + + +diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphColor.java b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a4e641fdcccd3efcd1a2865dc6dc28d50671b995 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java +@@ -0,0 +1,44 @@ ++package com.destroystokyo.paper.gui; ++ ++import java.awt.Color; ++ ++public class GraphColor { ++ private static final Color[] colorLine = new Color[101]; ++ private static final Color[] colorFill = new Color[101]; ++ ++ static { ++ for (int i = 0; i < 101; i++) { ++ Color color = createColor(i); ++ colorLine[i] = new Color(color.getRed() / 2, color.getGreen() / 2, color.getBlue() / 2, 255); ++ colorFill[i] = new Color(colorLine[i].getRed(), colorLine[i].getGreen(), colorLine[i].getBlue(), 125); ++ } ++ } ++ ++ public static Color getLineColor(int percent) { ++ return colorLine[percent]; ++ } ++ ++ public static Color getFillColor(int percent) { ++ return colorFill[percent]; ++ } ++ ++ private static Color createColor(int percent) { ++ if (percent <= 50) { ++ return new Color(0X00FF00); ++ } ++ ++ int value = 510 - (int) (Math.min(Math.max(0, ((percent - 50) / 50F)), 1) * 510); ++ ++ int red, green; ++ if (value < 255) { ++ red = 255; ++ green = (int) (Math.sqrt(value) * 16); ++ } else { ++ green = 255; ++ value = value - 255; ++ red = 255 - (value * value / 255); ++ } ++ ++ return new Color(red, green, 0); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphData.java b/src/main/java/com/destroystokyo/paper/gui/GraphData.java +new file mode 100644 +index 0000000000000000000000000000000000000000..186fc722965e403f76b1480e1c2381fc34e29049 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/GraphData.java +@@ -0,0 +1,47 @@ ++package com.destroystokyo.paper.gui; ++ ++import java.awt.Color; ++ ++public class GraphData { ++ private long total; ++ private long free; ++ private long max; ++ private long usedMem; ++ private int usedPercent; ++ ++ public GraphData(long total, long free, long max) { ++ this.total = total; ++ this.free = free; ++ this.max = max; ++ this.usedMem = total - free; ++ this.usedPercent = usedMem == 0 ? 0 : (int) (usedMem * 100L / max); ++ } ++ ++ public long getTotal() { ++ return total; ++ } ++ ++ public long getFree() { ++ return free; ++ } ++ ++ public long getMax() { ++ return max; ++ } ++ ++ public long getUsedMem() { ++ return usedMem; ++ } ++ ++ public int getUsedPercent() { ++ return usedPercent; ++ } ++ ++ public Color getFillColor() { ++ return GraphColor.getFillColor(usedPercent); ++ } ++ ++ public Color getLineColor() { ++ return GraphColor.getLineColor(usedPercent); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0f29ad583e798c09b2fe3f568ed50cbc719e40e2 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.gui; ++ ++import net.minecraft.server.MinecraftServer; ++ ++import javax.swing.JPanel; ++import javax.swing.Timer; ++import java.awt.BorderLayout; ++import java.awt.Dimension; ++ ++public class GuiStatsComponent extends JPanel { ++ private final Timer timer; ++ private final RAMGraph ramGraph; ++ ++ public GuiStatsComponent(MinecraftServer server) { ++ super(new BorderLayout()); ++ ++ setOpaque(false); ++ ++ ramGraph = new RAMGraph(); ++ RAMDetails ramDetails = new RAMDetails(server); ++ ++ add(ramGraph, "North"); ++ add(ramDetails, "Center"); ++ ++ timer = new Timer(500, (event) -> { ++ ramGraph.update(); ++ ramDetails.update(); ++ }); ++ timer.start(); ++ } ++ ++ @Override ++ public Dimension getPreferredSize() { ++ return new Dimension(350, 200); ++ } ++ ++ public void stop() { a(); } public void a() { ++ timer.stop(); ++ ramGraph.stop(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c0923ec75ecced2e0a1c0d3ec2c046d69af3e9a9 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +@@ -0,0 +1,73 @@ ++package com.destroystokyo.paper.gui; ++ ++import net.minecraft.Util; ++import net.minecraft.server.MinecraftServer; ++ ++import javax.swing.DefaultListCellRenderer; ++import javax.swing.DefaultListSelectionModel; ++import javax.swing.JList; ++import javax.swing.border.EmptyBorder; ++import java.awt.Dimension; ++import java.text.DecimalFormat; ++import java.text.DecimalFormatSymbols; ++import java.util.Locale; ++import java.util.Vector; ++ ++public class RAMDetails extends JList { ++ public static final DecimalFormat DECIMAL_FORMAT = Util.peek(new DecimalFormat("########0.000"), (format) ++ -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT))); ++ ++ private final MinecraftServer server; ++ ++ public RAMDetails(MinecraftServer server) { ++ this.server = server; ++ ++ setBorder(new EmptyBorder(0, 10, 0, 0)); ++ setFixedCellHeight(20); ++ setOpaque(false); ++ ++ DefaultListCellRenderer renderer = new DefaultListCellRenderer(); ++ renderer.setOpaque(false); ++ setCellRenderer(renderer); ++ ++ setSelectionModel(new DefaultListSelectionModel() { ++ @Override ++ public void setAnchorSelectionIndex(final int anchorIndex) { ++ } ++ ++ @Override ++ public void setLeadAnchorNotificationEnabled(final boolean flag) { ++ } ++ ++ @Override ++ public void setLeadSelectionIndex(final int leadIndex) { ++ } ++ ++ @Override ++ public void setSelectionInterval(final int index0, final int index1) { ++ } ++ }); ++ } ++ ++ @Override ++ public Dimension getPreferredSize() { ++ return new Dimension(350, 100); ++ } ++ ++ public void update() { ++ GraphData data = RAMGraph.DATA.peekLast(); ++ Vector vector = new Vector<>(); ++ vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); ++ vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); ++ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); ++ setListData(vector); ++ } ++ ++ public double getAverage(long[] tickTimes) { ++ long total = 0L; ++ for (long value : tickTimes) { ++ total += value; ++ } ++ return ((double) total / (double) tickTimes.length) * 1.0E-6D; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c3e54da4ab6440811aab2f9dd1e218802ac13285 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java +@@ -0,0 +1,144 @@ ++package com.destroystokyo.paper.gui; ++ ++import javax.swing.JComponent; ++import javax.swing.SwingUtilities; ++import javax.swing.Timer; ++import javax.swing.ToolTipManager; ++import java.awt.Color; ++import java.awt.Dimension; ++import java.awt.Graphics; ++import java.awt.MouseInfo; ++import java.awt.Point; ++import java.awt.PointerInfo; ++import java.awt.event.MouseAdapter; ++import java.awt.event.MouseEvent; ++import java.text.SimpleDateFormat; ++import java.util.Date; ++import java.util.LinkedList; ++import java.util.concurrent.TimeUnit; ++ ++public class RAMGraph extends JComponent { ++ public static final LinkedList DATA = new LinkedList() { ++ @Override ++ public boolean add(GraphData data) { ++ if (size() >= 348) { ++ remove(); ++ } ++ return super.add(data); ++ } ++ }; ++ ++ static { ++ GraphData empty = new GraphData(0, 0, 0); ++ for (int i = 0; i < 350; i++) { ++ DATA.add(empty); ++ } ++ } ++ ++ private final Timer timer; ++ private final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); ++ ++ private int currentTick; ++ ++ public RAMGraph() { ++ ToolTipManager.sharedInstance().setInitialDelay(0); ++ ++ addMouseListener(new MouseAdapter() { ++ final int defaultDismissTimeout = ToolTipManager.sharedInstance().getDismissDelay(); ++ final int dismissDelayMinutes = (int) TimeUnit.MINUTES.toMillis(10); ++ ++ @Override ++ public void mouseEntered(MouseEvent me) { ++ ToolTipManager.sharedInstance().setDismissDelay(dismissDelayMinutes); ++ } ++ ++ @Override ++ public void mouseExited(MouseEvent me) { ++ ToolTipManager.sharedInstance().setDismissDelay(defaultDismissTimeout); ++ } ++ }); ++ ++ timer = new Timer(50, (event) -> repaint()); ++ timer.start(); ++ } ++ ++ @Override ++ public Dimension getPreferredSize() { ++ return new Dimension(350, 110); ++ } ++ ++ public void update() { ++ Runtime jvm = Runtime.getRuntime(); ++ DATA.add(new GraphData(jvm.totalMemory(), jvm.freeMemory(), jvm.maxMemory())); ++ ++ PointerInfo pointerInfo = MouseInfo.getPointerInfo(); ++ if (pointerInfo != null) { ++ Point point = pointerInfo.getLocation(); ++ if (point != null) { ++ Point loc = new Point(point); ++ SwingUtilities.convertPointFromScreen(loc, this); ++ if (this.contains(loc)) { ++ ToolTipManager.sharedInstance().mouseMoved( ++ new MouseEvent(this, -1, System.currentTimeMillis(), 0, loc.x, loc.y, ++ point.x, point.y, 0, false, 0)); ++ } ++ } ++ } ++ ++ currentTick++; ++ } ++ ++ @Override ++ public void paint(Graphics graphics) { ++ graphics.setColor(new Color(0xFFFFFFFF)); ++ graphics.fillRect(0, 0, 350, 100); ++ ++ graphics.setColor(new Color(0x888888)); ++ graphics.drawLine(1, 25, 348, 25); ++ graphics.drawLine(1, 50, 348, 50); ++ graphics.drawLine(1, 75, 348, 75); ++ ++ int i = 0; ++ for (GraphData data : DATA) { ++ i++; ++ if ((i + currentTick) % 120 == 0) { ++ graphics.setColor(new Color(0x888888)); ++ graphics.drawLine(i, 1, i, 99); ++ } ++ int used = data.getUsedPercent(); ++ if (used > 0) { ++ Color color = data.getLineColor(); ++ graphics.setColor(data.getFillColor()); ++ graphics.fillRect(i, 100 - used, 1, used); ++ graphics.setColor(color); ++ graphics.fillRect(i, 100 - used, 1, 1); ++ } ++ } ++ ++ graphics.setColor(new Color(0xFF000000)); ++ graphics.drawRect(0, 0, 348, 100); ++ ++ Point m = getMousePosition(); ++ if (m != null && m.x > 0 && m.x < 348 && m.y > 0 && m.y < 100) { ++ GraphData data = DATA.get(m.x); ++ int used = data.getUsedPercent(); ++ graphics.setColor(new Color(0x000000)); ++ graphics.drawLine(m.x, 1, m.x, 99); ++ graphics.drawOval(m.x - 2, 100 - used - 2, 5, 5); ++ graphics.setColor(data.getLineColor()); ++ graphics.fillOval(m.x - 2, 100 - used - 2, 5, 5); ++ setToolTipText(String.format("Used: %s mb (%s%%)
    %s", ++ Math.round(data.getUsedMem() / 1024F / 1024F), ++ used, getTime(m.x))); ++ } ++ } ++ ++ public String getTime(int halfSeconds) { ++ int millis = (348 - halfSeconds) / 2 * 1000; ++ return TIME_FORMAT.format(new Date((System.currentTimeMillis() - millis))); ++ } ++ ++ public void stop() { ++ timer.stop(); ++ } ++} +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index cec5ad5052c8cf6059e9b117117846bdb217748f..c2f747226f10479c826849af898538610a2dd659 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -259,6 +259,7 @@ public class Util { + return factory.get(); + } + ++ public static T peek(T t0, Consumer consumer) { return make(t0, consumer); } // Paper - OBFHELPER + public static T make(T object, Consumer initializer) { + initializer.accept(object); + return object; +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 7038897b8fb4c18ca97b95a3b24c30b40b62b005..e33189dc8375a3034910087654607fb531061636 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -216,7 +216,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { ++ private static final DecimalFormat DECIMAL_FORMAT = (DecimalFormat) Util.make(new DecimalFormat("########0.000"), (decimalformat) -> { // Paper - decompile error + decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); + }); + private final int[] values = new int[256]; diff --git a/patches/server-remapped/0410-add-hand-to-BlockMultiPlaceEvent.patch b/patches/server-remapped/0410-add-hand-to-BlockMultiPlaceEvent.patch new file mode 100644 index 0000000000..e93352bf03 --- /dev/null +++ b/patches/server-remapped/0410-add-hand-to-BlockMultiPlaceEvent.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Sun, 1 Mar 2020 22:43:24 +0100 +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 e696d2e52532df25d74a1f559e2c9ca0f3d5058d..7d9a3b65b2d6b294d3a11414289e64fac88665f0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -337,13 +337,18 @@ public class CraftEventFactory { + } + + org.bukkit.inventory.ItemStack item; ++ //Paper start - add hand to BlockMultiPlaceEvent ++ EquipmentSlot equipmentSlot; + if (hand == InteractionHand.MAIN_HAND) { + item = player.getInventory().getItemInMainHand(); ++ equipmentSlot = EquipmentSlot.HAND; + } else { + item = player.getInventory().getItemInOffHand(); ++ equipmentSlot = EquipmentSlot.OFF_HAND; + } + +- BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild); ++ BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild, equipmentSlot); ++ //Paper end + craftServer.getPluginManager().callEvent(event); + + return event; diff --git a/patches/server-remapped/0411-Prevent-teleporting-dead-entities.patch b/patches/server-remapped/0411-Prevent-teleporting-dead-entities.patch new file mode 100644 index 0000000000..ef6164bd27 --- /dev/null +++ b/patches/server-remapped/0411-Prevent-teleporting-dead-entities.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 3 Mar 2020 05:26:40 +0000 +Subject: [PATCH] Prevent teleporting dead entities + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 2b79413bb8a592a7b7093e11d3a0cce895286c8f..09a663cc53cdf8ae45352b280200c8170dbbcdfc 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1468,6 +1468,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + + private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { ++ if (player.removed) { ++ LOGGER.info("Attempt to teleport dead player {} restricted", player.getScoreboardName()); ++ return; ++ } + // CraftBukkit start + if (Float.isNaN(f)) { + f = 0; diff --git a/patches/server-remapped/0412-Validate-tripwire-hook-placement-before-update.patch b/patches/server-remapped/0412-Validate-tripwire-hook-placement-before-update.patch new file mode 100644 index 0000000000..8fbefb7aec --- /dev/null +++ b/patches/server-remapped/0412-Validate-tripwire-hook-placement-before-update.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 7 Mar 2020 00:07:51 +0000 +Subject: [PATCH] Validate tripwire hook placement before update + + +diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java +index f44d4809fe87c832e4d3bda429af2254e8c746d6..20428aff54527b664d988a6a0f54236b693fda89 100644 +--- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java +@@ -169,6 +169,7 @@ public class TripWireHookBlock extends Block { + + this.playSound(world, pos, flag4, flag5, flag2, flag3); + if (!beingRemoved) { ++ if (world.getBlockState(pos).getBlock() == Blocks.TRIPWIRE_HOOK) // Paper - validate + world.setBlock(pos, (BlockState) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection), 3); + if (flag1) { + this.notifyNeighbors(world, pos, enumdirection); diff --git a/patches/server-remapped/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server-remapped/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch new file mode 100644 index 0000000000..163f5b9240 --- /dev/null +++ b/patches/server-remapped/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 13 Apr 2019 16:50:58 -0500 +Subject: [PATCH] Add option to allow iron golems to spawn in air + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 9e4591ddc4b755f4ff5a6f1078b51cb13db80480..fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -387,6 +387,11 @@ public class PaperWorldConfig { + scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); + } + ++ public boolean ironGolemsCanSpawnInAir = false; ++ private void ironGolemsCanSpawnInAir() { ++ ironGolemsCanSpawnInAir = getBoolean("iron-golems-can-spawn-in-air", ironGolemsCanSpawnInAir); ++ } ++ + public boolean armorStandEntityLookups = true; + private void armorStandEntityLookups() { + armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); +diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +index 9cedac83304847bdc92c2e97c4e6e119664c3bd0..59f0224b6a743408a03b642dd7cbe545f406c57e 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java ++++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +@@ -297,7 +297,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { + BlockPos blockposition1 = blockposition.below(); + BlockState iblockdata = world.getBlockState(blockposition1); + +- if (!iblockdata.entityCanStandOn((BlockGetter) world, blockposition1, (Entity) this)) { ++ if (!iblockdata.entityCanStandOn((BlockGetter) world, blockposition1, (Entity) this) && !level.paperConfig.ironGolemsCanSpawnInAir) { // Paper + return false; + } else { + for (int i = 1; i < 3; ++i) { diff --git a/patches/server-remapped/0414-Configurable-chance-of-villager-zombie-infection.patch b/patches/server-remapped/0414-Configurable-chance-of-villager-zombie-infection.patch new file mode 100644 index 0000000000..1bf93843e4 --- /dev/null +++ b/patches/server-remapped/0414-Configurable-chance-of-villager-zombie-infection.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zero +Date: Sat, 22 Feb 2020 16:10:31 -0500 +Subject: [PATCH] Configurable chance of villager zombie infection + +This allows you to solve an issue in vanilla behavior where: +* On easy difficulty your villagers will NEVER get infected, meaning they will always die. +* On normal difficulty they will have a 50% of getting infected or dying. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f..525d702d78a609af987ebd2c32169b873e5c05ed 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -604,4 +604,9 @@ public class PaperWorldConfig { + private void nerfNetherPortalPigmen() { + nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); + } ++ ++ public double zombieVillagerInfectionChance = -1.0; ++ private void zombieVillagerInfectionChance() { ++ zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 6fecf4188fc0247143edc688c03e645376960687..1e7c2c603b967c8c606efd94ce95a17c856f78d7 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -447,10 +447,14 @@ public class Zombie extends Monster { + @Override + public void killed(ServerLevel worldserver, LivingEntity entityliving) { + super.killed(worldserver, entityliving); +- if ((worldserver.getDifficulty() == Difficulty.NORMAL || worldserver.getDifficulty() == Difficulty.HARD) && entityliving instanceof Villager) { +- if (worldserver.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { ++ // Paper start ++ if (level.paperConfig.zombieVillagerInfectionChance != 0.0 && (level.paperConfig.zombieVillagerInfectionChance != -1.0 || worldserver.getDifficulty() == Difficulty.NORMAL || worldserver.getDifficulty() == Difficulty.HARD) && entityliving instanceof Villager) { ++ if (level.paperConfig.zombieVillagerInfectionChance == -1.0 && worldserver.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { + return; + } ++ if (level.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > level.paperConfig.zombieVillagerInfectionChance) { ++ return; ++ } // Paper end + + Villager entityvillager = (Villager) entityliving; + // CraftBukkit start diff --git a/patches/server-remapped/0415-Optimise-Chunk-getFluid.patch b/patches/server-remapped/0415-Optimise-Chunk-getFluid.patch new file mode 100644 index 0000000000..2ba043c076 --- /dev/null +++ b/patches/server-remapped/0415-Optimise-Chunk-getFluid.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 14 Jan 2020 14:59:08 -0800 +Subject: [PATCH] Optimise Chunk#getFluid + +Removing the try catch and generally reducing ops should make it +faster on its own, however removing the try catch makes it +easier to inline due to code size + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 87d7a87a2925f2c062658e960bb5128738828d9f..8a14bdda4a408ec1e2b51efeb35467835f62b42c 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -430,25 +430,29 @@ public class LevelChunk implements ChunkAccess { + } + + public FluidState getFluidState(int x, int y, int z) { +- try { +- if (y >= 0 && y >> 4 < this.sections.length) { +- LevelChunkSection chunksection = this.sections[y >> 4]; +- +- if (!LevelChunkSection.isEmpty(chunksection)) { +- return chunksection.getFluidState(x & 15, y & 15, z & 15); ++ //try { // Paper - remove try catch ++ // Paper start - reduce the number of ops in this call ++ int index = y >> 4; ++ if (index >= 0 && index < this.sections.length) { ++ LevelChunkSection chunksection = this.sections[index]; ++ ++ if (chunksection != null) { ++ return chunksection.states.get((y & 15) << 8 | (z & 15) << 4 | x & 15).getFluidState(); + } ++ // Paper end + } + + return Fluids.EMPTY.defaultFluidState(); +- } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state"); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got"); ++ /*} catch (Throwable throwable) { // Paper - remove try catch ++ CrashReport crashreport = CrashReport.a(throwable, "Getting fluid state"); ++ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being got"); + +- crashreportsystemdetails.setDetail("Location", () -> { +- return CrashReportCategory.formatLocation(x, y, z); ++ crashreportsystemdetails.a("Location", () -> { ++ return CrashReportSystemDetails.a(i, j, k); + }); + throw new ReportedException(crashreport); + } ++ */ // Paper - remove try catch + } + + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index c44d32f966c61497b4a8892eb51da3a71ad031d9..5e7f6000df129100ef306703f325af9f60da8ae6 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -45,7 +45,7 @@ public class LevelChunkSection { + } + + public FluidState getFluidState(int x, int y, int z) { +- return ((BlockState) this.states.get(x, y, z)).getFluidState(); ++ return ((BlockState) this.states.get(x, y, z)).getFluidState(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid. + } + + public void acquire() { diff --git a/patches/server-remapped/0416-Optimise-TickListServer-by-rewriting-it.patch b/patches/server-remapped/0416-Optimise-TickListServer-by-rewriting-it.patch new file mode 100644 index 0000000000..6cf945010b --- /dev/null +++ b/patches/server-remapped/0416-Optimise-TickListServer-by-rewriting-it.patch @@ -0,0 +1,1301 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 14 Feb 2020 01:24:39 -0800 +Subject: [PATCH] Optimise TickListServer by rewriting it + +In my profiling TickListServer showed up as +~10% for saving chunks and ~5% for the scheduling +of items on a server with ~90 players at +view distance = 5. Most of the performance +loss is unneccessary. + +TickListServer has numerous performance issues: + 1. Handling scheduled items is O(nlogn) + 2. Getting scheduled items for a chunk is O(n), + with n being the the number of scheduled items + for all chunks (hits saving very hard) + 3. Checking if an item is scheduled for the current tick is O(n), + with n being the number of items scheduled for current tick + 4. Items not in ticking chunks are churned in the scheduler + +The biggest issues are 4 & 2. + +We solve 1 by splitting up scheduled items into short and long scheduled, +where we expect the vast majority of our entries to be in the short scheduled +set. Handling short scheduled items is O(n) due to how the comparison +process is reduced to mapping. See TickListServerInterval. However, +this isn't memory-efficient - which is why long scheduled exists. +Long scheduled is handled the same as TickListServer. + +2 is solved by mapping what entries are in what chunks. + +3 is solved by mapping what blocks have what scheduled for them. + +4 is solved by moving the items that are not in ticking chunks +into a map of entries for that chunk. Once the chunk is moved +to ticking, the items are re-scheduled. + +This patch has also added two flags to debug excessive tick delays: +-Dpaper.ticklist-warn-on-excessive-delay=true (false by default) +and -Dpaper.ticklist-excessive-delay-threshold=ticks which +sets the excessive tick delay to the specified ticks (defaults to +60 * 20 ticks, aka 60 seconds) + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 8bf4d2b8c38c02d6a5b2fea37113689a252f1571..da93d38fe63035e4ff198ada84a4431f52d97c01 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -354,6 +354,13 @@ public class PaperConfig { + maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); + } + ++ public static boolean useOptimizedTickList = true; ++ private static void useOptimizedTickList() { ++ if (config.contains("settings.use-optimized-ticklist")) { // don't add default, hopefully temporary config ++ useOptimizedTickList = config.getBoolean("settings.use-optimized-ticklist"); ++ } ++ } ++ + public static boolean asyncChunks = false; + private static void asyncChunks() { + ConfigurationSection section; +diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2d579909b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java +@@ -0,0 +1,628 @@ ++package com.destroystokyo.paper.server.ticklist; ++ ++import java.util.function.Function; ++import net.minecraft.CrashReport; ++import net.minecraft.CrashReportCategory; ++import net.minecraft.ReportedException; ++import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.ServerTickList; ++import net.minecraft.world.level.TickNextTickData; ++import net.minecraft.world.level.TickPriority; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.levelgen.structure.BoundingBox; ++import it.unimi.dsi.fastutil.longs.Long2ObjectMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; ++import java.util.ArrayDeque; ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.Comparator; ++import java.util.Iterator; ++import java.util.List; ++import java.util.function.Consumer; ++import java.util.function.Predicate; ++ ++public final class PaperTickList extends ServerTickList { // extend to avoid breaking ABI ++ ++ // in the order the state is expected to change (mostly) ++ public static final int STATE_UNSCHEDULED = 1 << 0; ++ public static final int STATE_SCHEDULED = 1 << 1; // scheduled for some tick ++ public static final int STATE_PENDING_TICK = 1 << 2; // for this tick ++ public static final int STATE_TICKING = 1 << 3; ++ public static final int STATE_TICKED = 1 << 4; // after this, it gets thrown back to unscheduled ++ public static final int STATE_CANCELLED_TICK = 1 << 5; // still gets moved to unscheduled after tick ++ ++ private static final int SHORT_SCHEDULE_TICK_THRESHOLD = 20 * 20 + 1; // 20 seconds ++ ++ private final ServerLevel world; ++ private final Predicate excludeFromScheduling; ++ private final Function getMinecraftKeyFrom; ++ //private final Function getObjectFronMinecraftKey; ++ private final Consumer> tickFunction; ++ ++ private final co.aikar.timings.Timing timingCleanup; // Paper ++ private final co.aikar.timings.Timing timingTicking; // Paper ++ private final co.aikar.timings.Timing timingFinished; ++ ++ // note: remove ops / add ops suck on fastutil, a chained hashtable implementation would work better, but Long... ++ // try to alleviate with a very small load factor ++ private final Long2ObjectOpenHashMap>> entriesByBlock = new Long2ObjectOpenHashMap<>(1024, 0.25f); ++ private final Long2ObjectOpenHashMap>> entriesByChunk = new Long2ObjectOpenHashMap<>(1024, 0.25f); ++ private final Long2ObjectOpenHashMap>> pendingChunkTickLoad = new Long2ObjectOpenHashMap<>(1024, 0.5f); ++ ++ // fastutil has O(1) first/last while TreeMap/TreeSet are log(n) ++ private final ObjectRBTreeSet> longScheduled = new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); ++ ++ private final ArrayDeque> toTickThisTick = new ArrayDeque<>(); ++ ++ private final TickListServerInterval[] shortScheduled = new TickListServerInterval[SHORT_SCHEDULE_TICK_THRESHOLD]; ++ { ++ for (int i = 0, len = this.shortScheduled.length; i < len; ++i) { ++ this.shortScheduled[i] = new TickListServerInterval<>(); ++ } ++ } ++ private int shortScheduledIndex; ++ ++ private long currentTick; ++ ++ private static final boolean WARN_ON_EXCESSIVE_DELAY = Boolean.getBoolean("paper.ticklist-warn-on-excessive-delay"); ++ private static final long EXCESSIVE_DELAY_THRESHOLD = Long.getLong("paper.ticklist-excessive-delay-threshold", 60 * 20).longValue(); // 1 min dfl ++ ++ // assume index < length ++ private static int getWrappedIndex(final int start, final int length, final int index) { ++ final int next = start + index; ++ return next < length ? next : next - length; ++ } ++ ++ private static int getNextIndex(final int curr, final int length) { ++ final int next = curr + 1; ++ return next < length ? next : 0; ++ } ++ ++ public PaperTickList(final ServerLevel world, final Predicate excludeFromScheduling, final Function getMinecraftKeyFrom, ++ final Consumer> tickFunction, final String timingsType) { ++ super(world, excludeFromScheduling, getMinecraftKeyFrom, tickFunction, timingsType); ++ this.world = world; ++ this.excludeFromScheduling = excludeFromScheduling; ++ this.getMinecraftKeyFrom = getMinecraftKeyFrom; ++ this.tickFunction = tickFunction; ++ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Cleanup"); // Paper ++ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Ticking"); // Paper ++ this.timingFinished = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Finish"); ++ this.currentTick = this.world.getGameTime(); ++ } ++ ++ private void queueEntryForTick(final TickNextTickData entry, final ServerChunkCache chunkProvider) { ++ if (entry.tickState == STATE_SCHEDULED) { ++ if (chunkProvider.isTickingReadyMainThread(entry.getPosition())) { ++ this.toTickThisTick.add(entry); ++ entry.tickState = STATE_PENDING_TICK; ++ } else { ++ // we dump them to a map to avoid constantly re-scheduling them ++ this.addToNotTickingReady(entry); ++ } ++ } ++ } ++ ++ private void addToNotTickingReady(final TickNextTickData entry) { ++ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (long keyInMap) -> { ++ return new ArrayList<>(); ++ }).add(entry); ++ } ++ ++ private void addToSchedule(final TickNextTickData entry) { ++ long delay = entry.getTargetTick() - (this.currentTick + 1); ++ if (delay < SHORT_SCHEDULE_TICK_THRESHOLD) { ++ if (delay < 0) { ++ // longScheduled orders by tick time, short scheduled does not ++ this.longScheduled.add(entry); ++ } else { ++ this.shortScheduled[getWrappedIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD, (int)delay)].addEntryLast(entry); ++ } ++ } else { ++ this.longScheduled.add(entry); ++ } ++ } ++ ++ private void removeEntry(final TickNextTickData entry) { ++ entry.tickState = STATE_CANCELLED_TICK; ++ // short/long scheduled will skip the entry ++ ++ final BlockPos pos = entry.getPosition(); ++ final long blockKey = MCUtil.getBlockKey(pos); ++ ++ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); ++ ++ if (currentEntries.size() == 1) { ++ // it should contain our entry ++ this.entriesByBlock.remove(blockKey); ++ } else { ++ // it's more likely that this entry is at the start of the list than the end ++ for (int i = 0, len = currentEntries.size(); i < len; ++i) { ++ final TickNextTickData currentEntry = currentEntries.get(i); ++ if (currentEntry == entry) { ++ currentEntries.remove(i); ++ break; ++ } ++ } ++ } ++ ++ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ ++ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); ++ ++ set.remove(entry); ++ ++ if (set.isEmpty()) { ++ this.entriesByChunk.remove(chunkKey); ++ } ++ ++ ArrayList> pendingTickingLoad = this.pendingChunkTickLoad.get(chunkKey); ++ ++ if (pendingTickingLoad != null) { ++ for (int i = 0, len = pendingTickingLoad.size(); i < len; ++i) { ++ if (pendingTickingLoad.get(i) == entry) { ++ pendingTickingLoad.remove(i); ++ break; ++ } ++ } ++ ++ if (pendingTickingLoad.isEmpty()) { ++ this.pendingChunkTickLoad.remove(chunkKey); ++ } ++ } ++ ++ long delay = entry.getTargetTick() - (this.currentTick + 1); ++ if (delay >= SHORT_SCHEDULE_TICK_THRESHOLD) { ++ this.longScheduled.remove(entry); ++ } ++ } ++ ++ public void onChunkSetTicking(final int chunkX, final int chunkZ) { ++ final ArrayList> pending = this.pendingChunkTickLoad.remove(MCUtil.getCoordinateKey(chunkX, chunkZ)); ++ if (pending == null) { ++ return; ++ } ++ ++ for (int i = 0, size = pending.size(); i < size; ++i) { ++ final TickNextTickData entry = pending.get(i); ++ // already in all the relevant reference maps, just need to add to longScheduled or shortScheduled ++ this.addToSchedule(entry); ++ } ++ } ++ ++ private void prepare() { ++ final long currentTick = this.currentTick; ++ ++ final ServerChunkCache chunkProvider = this.world.getChunkSource(); ++ ++ // here we setup what's going to tick ++ ++ // we don't remove items from shortScheduled (but do from longScheduled) because they're cleared at the end of ++ // this tick ++ if (this.longScheduled.isEmpty() || this.longScheduled.first().getTargetTick() > currentTick) { ++ // nothing in longScheduled to worry about ++ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; ++ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { ++ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { ++ this.queueEntryForTick(iterator.next(), chunkProvider); ++ } ++ } ++ } else { ++ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; ++ ++ // combine interval and longScheduled, keeping order ++ final Comparator> comparator = (Comparator)TickListServerInterval.ENTRY_COMPARATOR; ++ final Iterator> longScheduledIterator = this.longScheduled.iterator(); ++ TickNextTickData longCurrent = longScheduledIterator.next(); ++ ++ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { ++ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { ++ final TickNextTickData shortCurrent = iterator.next(); ++ if (longCurrent != null) { ++ // drain longCurrent until we can add shortCurrent ++ while (comparator.compare(longCurrent, shortCurrent) <= 0) { ++ this.queueEntryForTick(longCurrent, chunkProvider); ++ longScheduledIterator.remove(); ++ if (longScheduledIterator.hasNext()) { ++ longCurrent = longScheduledIterator.next(); ++ if (longCurrent.getTargetTick() > currentTick) { ++ longCurrent = null; ++ break; ++ } ++ } else { ++ longCurrent = null; ++ break; ++ } ++ } ++ } ++ this.queueEntryForTick(shortCurrent, chunkProvider); ++ } ++ } ++ ++ // add remaining from long scheduled ++ for (;;) { ++ if (longCurrent == null || longCurrent.getTargetTick() > currentTick) { ++ break; ++ } ++ longScheduledIterator.remove(); ++ this.queueEntryForTick(longCurrent, chunkProvider); ++ ++ if (longScheduledIterator.hasNext()) { ++ longCurrent = longScheduledIterator.next(); ++ } else { ++ break; ++ } ++ } ++ } ++ } ++ ++ private boolean warnedAboutDesync; ++ ++ @Override ++ public void nextTick() { ++ ++this.currentTick; ++ if (this.currentTick != this.world.getGameTime()) { ++ if (!this.warnedAboutDesync) { ++ this.warnedAboutDesync = true; ++ MinecraftServer.LOGGER.error("World tick desync detected! Expected " + this.currentTick + " ticks, but got " + this.world.getGameTime() + " ticks for world '" + this.world.getWorld().getName() + "'", new Throwable()); ++ MinecraftServer.LOGGER.error("Preventing redstone from breaking by refusing to accept new tick time"); ++ } ++ } ++ } ++ ++ @Override ++ public void tick() { ++ final ServerChunkCache chunkProvider = this.world.getChunkSource(); ++ ++ this.world.getProfiler().push("cleaning"); ++ this.timingCleanup.startTiming(); ++ ++ this.prepare(); ++ ++ // this must be done here in case something schedules in the tick code ++ this.shortScheduled[this.shortScheduledIndex].clear(); ++ this.shortScheduledIndex = getNextIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD); ++ ++ this.timingCleanup.stopTiming(); ++ this.world.getProfiler().popPush("ticking"); ++ this.timingTicking.startTiming(); ++ ++ for (final TickNextTickData toTick : this.toTickThisTick) { ++ if (toTick.tickState != STATE_PENDING_TICK) { ++ // onTickEnd gets called at end of tick ++ continue; ++ } ++ try { ++ if (chunkProvider.isTickingReadyMainThread(toTick.getPosition())) { ++ toTick.tickState = STATE_TICKING; ++ this.tickFunction.accept(toTick); ++ if (toTick.tickState == STATE_TICKING) { ++ toTick.tickState = STATE_TICKED; ++ } // else it's STATE_CANCELLED_TICK ++ } else { ++ // re-schedule eventually ++ toTick.tickState = STATE_SCHEDULED; ++ this.addToNotTickingReady(toTick); ++ } ++ } catch (final Throwable thr) { ++ // start copy from TickListServer // TODO check on update ++ CrashReport crashreport = CrashReport.forThrowable(thr, "Exception while ticking"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being ticked"); ++ ++ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, toTick.getPosition(), (BlockState) null); ++ throw new ReportedException(crashreport); ++ // end copy from TickListServer ++ } ++ } ++ ++ this.timingTicking.stopTiming(); ++ this.world.getProfiler().pop(); ++ this.timingFinished.startTiming(); ++ ++ // finished ticking, actual cleanup time ++ for (int i = 0, len = this.toTickThisTick.size(); i < len; ++i) { ++ final TickNextTickData entry = this.toTickThisTick.poll(); ++ if (entry.tickState != STATE_SCHEDULED) { ++ // some entries get re-scheduled due to their chunk not being loaded/at correct status, so do not ++ // call onTickEnd for them ++ this.onTickEnd(entry); ++ } ++ } ++ ++ this.timingFinished.stopTiming(); ++ } ++ ++ private void onTickEnd(final TickNextTickData entry) { ++ if (entry.tickState == STATE_CANCELLED_TICK) { ++ return; ++ } ++ entry.tickState = STATE_UNSCHEDULED; ++ ++ final BlockPos pos = entry.getPosition(); ++ final long blockKey = MCUtil.getBlockKey(pos); ++ ++ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); ++ ++ if (currentEntries.size() == 1) { ++ // it should contain our entry ++ this.entriesByBlock.remove(blockKey); ++ } else { ++ // it's more likely that this entry is at the start of the list than the end ++ for (int i = 0, len = currentEntries.size(); i < len; ++i) { ++ final TickNextTickData currentEntry = currentEntries.get(i); ++ if (currentEntry == entry) { ++ currentEntries.remove(i); ++ break; ++ } ++ } ++ } ++ ++ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ ++ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); ++ ++ set.remove(entry); ++ ++ if (set.isEmpty()) { ++ this.entriesByChunk.remove(chunkKey); ++ } ++ ++ // already removed from longScheduled or shortScheduled ++ } ++ ++ @Override ++ public boolean isPendingTickThisTick(final BlockPos blockposition, final T data) { ++ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); ++ ++ if (entries == null) { ++ return false; ++ } ++ ++ for (int i = 0, size = entries.size(); i < size; ++i) { ++ final TickNextTickData entry = entries.get(i); ++ if (entry.getData() == data && entry.tickState == STATE_PENDING_TICK) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ @Override ++ public boolean isScheduledForTick(final BlockPos blockposition, final T data) { ++ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); ++ ++ if (entries == null) { ++ return false; ++ } ++ ++ for (int i = 0, size = entries.size(); i < size; ++i) { ++ final TickNextTickData entry = entries.get(i); ++ if (entry.getData() == data && entry.tickState == STATE_SCHEDULED) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ @Override ++ public void schedule(BlockPos blockPosition, T t, int i, TickPriority tickListPriority) { ++ this.schedule(blockPosition, t, i + this.currentTick, tickListPriority); ++ } ++ ++ public void schedule(final TickNextTickData entry) { ++ this.schedule(entry.getPosition(), entry.getData(), entry.getTargetTick(), entry.getPriority()); ++ } ++ ++ public void schedule(final BlockPos pos, final T data, final long targetTick, final TickPriority priority) { ++ final TickNextTickData entry = new TickNextTickData<>(pos, data, targetTick, priority); ++ if (this.excludeFromScheduling.test(entry.getData())) { ++ return; ++ } ++ ++ if (WARN_ON_EXCESSIVE_DELAY) { ++ final long delay = entry.getTargetTick() - this.currentTick; ++ if (delay >= EXCESSIVE_DELAY_THRESHOLD) { ++ MinecraftServer.LOGGER.warn("Entry " + entry.toString() + " has been scheduled with an excessive delay of: " + delay, new Throwable()); ++ } ++ } ++ ++ final long blockKey = MCUtil.getBlockKey(pos); ++ ++ final ArrayList> currentEntries = this.entriesByBlock.computeIfAbsent(blockKey, (long keyInMap) -> new ArrayList<>(3)); ++ ++ if (currentEntries.isEmpty()) { ++ currentEntries.add(entry); ++ } else { ++ for (int i = 0, size = currentEntries.size(); i < size; ++i) { ++ final TickNextTickData currentEntry = currentEntries.get(i); ++ ++ // entries are only blocked from scheduling if currentEntry.equals(toSchedule) && currentEntry is scheduled to tick (NOT including pending) ++ if (currentEntry.getData() == entry.getData() && currentEntry.tickState == STATE_SCHEDULED) { ++ // can't add ++ return; ++ } ++ } ++ currentEntries.add(entry); ++ } ++ ++ entry.tickState = STATE_SCHEDULED; ++ ++ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (final long keyInMap) -> { ++ return new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); ++ }).add(entry); ++ ++ this.addToSchedule(entry); ++ } ++ ++ public void scheduleAll(final Iterator> iterator) { ++ while (iterator.hasNext()) { ++ this.schedule(iterator.next()); ++ } ++ } ++ ++ // this is not the standard interception calculation, but it's the one vanilla uses ++ // i.e the y value is ignored? the x, z calc isn't correct? ++ // however for the copy op they use the correct intersection, after using this one of course... ++ private static boolean isBlockInSortof(final BoundingBox boundingBox, final BlockPos pos) { ++ return pos.getX() >= boundingBox.getMinX() && pos.getX() < boundingBox.getMaxX() && pos.getZ() >= boundingBox.getMinZ() && pos.getZ() < boundingBox.getMaxZ(); ++ } ++ ++ @Override ++ public List> getEntriesInBoundingBox(final BoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { ++ if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) { ++ return Collections.emptyList(); // vanilla behaviour, check isBlockInSortof above ++ } ++ ++ final int lowerChunkX = structureboundingbox.getMinX() >> 4; ++ final int upperChunkX = (structureboundingbox.getMaxX() - 1) >> 4; // subtract 1 since maxX is exclusive ++ final int lowerChunkZ = structureboundingbox.getMinZ() >> 4; ++ final int upperChunkZ = (structureboundingbox.getMaxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive ++ ++ final int xChunksLength = (upperChunkX - lowerChunkX + 1); ++ final int zChunksLength = (upperChunkZ - lowerChunkZ + 1); ++ ++ final ObjectRBTreeSet>[] containingChunks = new ObjectRBTreeSet[xChunksLength * zChunksLength]; ++ ++ final int offset = (xChunksLength * -lowerChunkZ - lowerChunkX); ++ int totalEntries = 0; ++ for (int currChunkX = lowerChunkX; currChunkX <= upperChunkX; ++currChunkX) { ++ for (int currChunkZ = lowerChunkZ; currChunkZ <= upperChunkZ; ++currChunkZ) { ++ // todo optimize ++ //final int index = (currChunkX - lowerChunkX) + xChunksLength * (currChunkZ - lowerChunkZ); ++ final int index = offset + currChunkX + xChunksLength * currChunkZ; ++ final ObjectRBTreeSet> set = containingChunks[index] = this.entriesByChunk.get(MCUtil.getCoordinateKey(currChunkX, currChunkZ)); ++ if (set != null) { ++ totalEntries += set.size(); ++ } ++ } ++ } ++ ++ final List> ret = new ArrayList<>(totalEntries); ++ ++ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); ++ ++ MCUtil.mergeSortedSets((TickNextTickData entry) -> { ++ if (!isBlockInSortof(structureboundingbox, entry.getPosition())) { ++ return; ++ } ++ final int tickState = entry.tickState; ++ if ((tickState & matchOne) == 0) { ++ return; ++ } ++ ++ ret.add(entry); ++ return; ++ }, TickListServerInterval.ENTRY_COMPARATOR, containingChunks); ++ ++ if (removeReturned) { ++ for (TickNextTickData entry : ret) { ++ this.removeEntry(entry); ++ } ++ } ++ ++ return ret; ++ } ++ ++ @Override ++ public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { ++ // start copy from TickListServer // TODO check on update ++ List> list = this.getEntriesInBoundingBox(structureboundingbox, false, false); ++ Iterator> iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ TickNextTickData nextticklistentry = iterator.next(); ++ ++ if (structureboundingbox.hasPoint( nextticklistentry.getPosition())) { ++ BlockPos blockposition1 = nextticklistentry.getPosition().add(blockposition); ++ T t0 = nextticklistentry.getData(); ++ ++ this.schedule(new TickNextTickData<>(blockposition1, t0, nextticklistentry.getTargetTick(), nextticklistentry.getPriority())); ++ } ++ } ++ // end copy from TickListServer ++ } ++ ++ @Override ++ public List> getEntriesInChunk(ChunkPos chunkPos, boolean removeReturned, boolean excludeTicked) { ++ // Vanilla DOES get the entries 2 blocks out of the chunk too, but that doesn't matter since we ignore chunks ++ // not at ticking status, and ticking status requires neighbours loaded ++ // so with this method we will reduce scheduler churning ++ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); ++ ++ final ObjectRBTreeSet> entries = this.entriesByChunk.get(MCUtil.getCoordinateKey(chunkPos)); ++ ++ if (entries == null) { ++ return Collections.emptyList(); ++ } ++ ++ final List> ret = new ArrayList<>(entries.size()); ++ ++ for (TickNextTickData entry : entries) { ++ if ((entry.tickState & matchOne) == 0) { ++ continue; ++ } ++ ret.add(entry); ++ } ++ ++ if (removeReturned) { ++ for (TickNextTickData entry : ret) { ++ this.removeEntry(entry); ++ } ++ } ++ ++ return ret; ++ } ++ ++ @Override ++ public ListTag serialize(ChunkPos chunkcoordintpair) { ++ // start copy from TickListServer // TODO check on update ++ List> list = this.getEntriesInChunk(chunkcoordintpair, false, true); ++ ++ return ServerTickList.serialize(this.getMinecraftKeyFrom, list, this.currentTick); ++ // end copy from TickListServer ++ } ++ ++ @Override ++ public int getTotalScheduledEntries() { ++ // good thing this is only used in debug reports // TODO check on update ++ int ret = 0; ++ ++ for (TickNextTickData entry : this.longScheduled) { ++ if (entry.tickState == STATE_SCHEDULED) { ++ ++ret; ++ } ++ } ++ ++ for (Iterator>>> iterator = this.pendingChunkTickLoad.long2ObjectEntrySet().iterator(); iterator.hasNext();) { ++ ArrayList> list = iterator.next().getValue(); ++ ++ for (TickNextTickData entry : list) { ++ if (entry.tickState == STATE_SCHEDULED) { ++ ++ret; ++ } ++ } ++ } ++ ++ for (TickListServerInterval interval : this.shortScheduled) { ++ for (Iterable> set : interval.byPriority) { ++ for (TickNextTickData entry : set) { ++ if (entry.tickState == STATE_SCHEDULED) { ++ ++ret; ++ } ++ } ++ } ++ } ++ ++ return ret; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d40a7aff6c27883f3ae8ba878a94c97242619f2c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.server.ticklist; ++ ++import com.destroystokyo.paper.util.set.LinkedSortedSet; ++import java.util.Comparator; ++import net.minecraft.world.level.TickNextTickData; ++import net.minecraft.world.level.TickPriority; ++ ++// represents a set of entries to tick at a specified time ++public final class TickListServerInterval { ++ ++ public static final int TOTAL_PRIORITIES = TickPriority.values().length; ++ public static final Comparator> ENTRY_COMPARATOR_BY_ID = (entry1, entry2) -> { ++ return Long.compare(entry1.getId(), entry2.getId()); ++ }; ++ public static final Comparator> ENTRY_COMPARATOR = (Comparator)TickNextTickData.comparator(); ++ ++ // we do not record the interval, this class is meant to be used on a ring buffer ++ ++ // inlined enum map for TickListPriority ++ public final LinkedSortedSet>[] byPriority = new LinkedSortedSet[TOTAL_PRIORITIES]; ++ ++ { ++ for (int i = 0, len = this.byPriority.length; i < len; ++i) { ++ this.byPriority[i] = new LinkedSortedSet<>(ENTRY_COMPARATOR_BY_ID); ++ } ++ } ++ ++ public void addEntryLast(final TickNextTickData entry) { ++ this.byPriority[entry.getPriority().ordinal()].addLast(entry); ++ } ++ ++ public void addEntryFirst(final TickNextTickData entry) { ++ this.byPriority[entry.getPriority().ordinal()].addFirst(entry); ++ } ++ ++ public void clear() { ++ for (int i = 0, len = this.byPriority.length; i < len; ++i) { ++ this.byPriority[i].clear(); // O(1) clear ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..118988c39e58f28e8a2851792b9c014f341f06fc +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java +@@ -0,0 +1,142 @@ ++package com.destroystokyo.paper.util.set; ++ ++import java.util.Comparator; ++import java.util.Iterator; ++import java.util.NoSuchElementException; ++ ++public final class LinkedSortedSet implements Iterable { ++ ++ public final Comparator comparator; ++ ++ protected Link head; ++ protected Link tail; ++ ++ public LinkedSortedSet() { ++ this((Comparator)Comparator.naturalOrder()); ++ } ++ ++ public LinkedSortedSet(final Comparator comparator) { ++ this.comparator = comparator; ++ } ++ ++ public void clear() { ++ this.head = this.tail = null; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return new Iterator() { ++ ++ Link next = LinkedSortedSet.this.head; ++ ++ @Override ++ public boolean hasNext() { ++ return this.next != null; ++ } ++ ++ @Override ++ public E next() { ++ final Link next = this.next; ++ if (next == null) { ++ throw new NoSuchElementException(); ++ } ++ this.next = next.next; ++ return next.element; ++ } ++ }; ++ } ++ ++ public boolean addLast(final E element) { ++ final Comparator comparator = this.comparator; ++ ++ Link curr = this.tail; ++ if (curr != null) { ++ int compare; ++ ++ while ((compare = comparator.compare(element, curr.element)) < 0) { ++ Link prev = curr; ++ curr = curr.prev; ++ if (curr != null) { ++ continue; ++ } ++ this.head = prev.prev = new Link<>(element, null, prev); ++ return true; ++ } ++ ++ if (compare != 0) { ++ // insert after curr ++ final Link next = curr.next; ++ final Link insert = new Link<>(element, curr, next); ++ curr.next = insert; ++ ++ if (next == null) { ++ this.tail = insert; ++ } else { ++ next.prev = insert; ++ } ++ return true; ++ } ++ ++ return false; ++ } else { ++ this.head = this.tail = new Link<>(element); ++ return true; ++ } ++ } ++ ++ public boolean addFirst(final E element) { ++ final Comparator comparator = this.comparator; ++ ++ Link curr = this.head; ++ if (curr != null) { ++ int compare; ++ ++ while ((compare = comparator.compare(element, curr.element)) > 0) { ++ Link prev = curr; ++ curr = curr.next; ++ if (curr != null) { ++ continue; ++ } ++ this.tail = prev.next = new Link<>(element, prev, null); ++ return true; ++ } ++ ++ if (compare != 0) { ++ // insert before curr ++ final Link prev = curr.prev; ++ final Link insert = new Link<>(element, prev, curr); ++ curr.prev = insert; ++ ++ if (prev == null) { ++ this.head = insert; ++ } else { ++ prev.next = insert; ++ } ++ return true; ++ } ++ ++ return false; ++ } else { ++ this.head = this.tail = new Link<>(element); ++ return true; ++ } ++ } ++ ++ protected static final class Link { ++ public E element; ++ public Link prev; ++ public Link next; ++ ++ public Link() {} ++ ++ public Link(final E element) { ++ this.element = element; ++ } ++ ++ public Link(final E element, final Link prev, final Link next) { ++ this.element = element; ++ this.prev = prev; ++ this.next = next; ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 3db77d9eda98eacb099135643aff5e94751f4c7c..595abf528a7862478100770987906af1b13439fe 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -111,6 +111,7 @@ public class BlockPos extends Vec3i { + return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.getX() + x, this.getY() + y, this.getZ() + z); + } + ++ public final BlockPos add(Vec3i baseblockposition) { return this.offset(baseblockposition); } // Paper - OBFHELPER + public BlockPos offset(Vec3i pos) { + return this.offset(pos.getX(), pos.getY(), pos.getZ()); + } +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 77d3969200ac6f88f3af9add05def0b627ce6db3..d12d5459c847d3f0d655c85e31d81c27b7a2face 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -495,7 +495,9 @@ public class ChunkHolder { + ChunkHolder.this.isTickingReady = true; + + +- ++ // Paper start - rewrite ticklistserver ++ ChunkHolder.this.chunkMap.level.onChunkSetTicking(ChunkHolder.this.pos.x, ChunkHolder.this.pos.z); ++ // Paper end - rewrite ticklistserver + + } + }); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 3aeb8426b0461ec572c1499116be80f968bb4104..e2b1541042bceac965411e3176d08c61f217c07f 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -21,6 +21,7 @@ import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; + import net.minecraft.network.protocol.Packet; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.progress.ChunkProgressListener; + import net.minecraft.util.Mth; + import net.minecraft.util.profiling.ProfilerFiller; +@@ -217,6 +218,13 @@ public class ServerChunkCache extends ChunkSource { + } + // Paper end + ++ // Paper start - rewrite ticklistserver ++ public final boolean isTickingReadyMainThread(BlockPos pos) { ++ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(pos)); ++ return chunk != null && chunk.isTickingReady(); ++ } ++ // Paper end - rewrite ticklistserver ++ + public ServerChunkCache(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldloadlistener, Supplier supplier) { + this.level = worldserver; + this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(worldserver); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 5d85895456b5d65954889cadf932027ea23b400b..9da0d98bc2ed7876a00a734690ed42f01b9a9a9b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -292,6 +292,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + // Paper end + ++ // Paper start - rewrite ticklistserver ++ void onChunkSetTicking(int chunkX, int chunkZ) { ++ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { ++ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.blockTicks).onChunkSetTicking(chunkX, chunkZ); ++ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.liquidTicks).onChunkSetTicking(chunkX, chunkZ); ++ } ++ } ++ // Paper end - rewrite ticklistserver ++ + // Add env and gen to constructor, WorldData -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor +@@ -299,12 +308,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + convertable = convertable_conversionsession; + uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile()); + // CraftBukkit end +- this.blockTicks = new ServerTickList<>(this, (block) -> { +- return block == null || block.defaultBlockState().isAir(); +- }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings +- this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { +- return fluidtype == null || fluidtype == Fluids.EMPTY; +- }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings ++ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { ++ this.blockTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> { ++ return block == null || block.defaultBlockState().isAir(); ++ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings ++ this.liquidTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (fluidtype) -> { ++ return fluidtype == null || fluidtype == Fluids.EMPTY; ++ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings ++ } else { ++ this.blockTicks = new ServerTickList<>(this, (block) -> { ++ return block == null || block.defaultBlockState().isAir(); ++ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings ++ this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { ++ return fluidtype == null || fluidtype == Fluids.EMPTY; ++ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings ++ } + this.navigations = Sets.newHashSet(); + this.blockEvents = new ObjectLinkedOpenHashSet(); + this.tickTime = flag1; +@@ -639,7 +657,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (this.tickTime) { + long i = this.levelData.getGameTime() + 1L; + +- this.worldDataServer.setGameTime(i); ++ this.worldDataServer.setGameTime(i); // Paper - diff on change, we want the below to be ran right after this ++ this.blockTicks.nextTick(); // Paper ++ this.liquidTicks.nextTick(); // Paper + this.worldDataServer.getScheduledEvents().tick(this.server, i); + if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + this.setDayTime(this.levelData.getDayTime() + 1L); +diff --git a/src/main/java/net/minecraft/world/level/ChunkTickList.java b/src/main/java/net/minecraft/world/level/ChunkTickList.java +index 16757eb9c03c0dab51a7a1b569daff81cf9654f3..3008e0c42efe908e45dba1a1437928d4d4378f24 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkTickList.java ++++ b/src/main/java/net/minecraft/world/level/ChunkTickList.java +@@ -9,6 +9,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MinecraftServer; + + public class ChunkTickList implements TickList { + +@@ -61,6 +62,8 @@ public class ChunkTickList implements TickList { + return nbttaglist; + } + ++ private static final int MAX_TICK_DELAY = Integer.getInteger("paper.ticklist-max-tick-delay", -1).intValue(); // Paper - clean up broken entries ++ + public static ChunkTickList create(ListTag ticks, Function function, Function function1) { + List> list = Lists.newArrayList(); + +@@ -71,7 +74,14 @@ public class ChunkTickList implements TickList { + if (t0 != null) { + BlockPos blockposition = new BlockPos(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); + +- list.add(new ChunkTickList.ScheduledTick<>(t0, blockposition, nbttagcompound.getInt("t"), TickPriority.byValue(nbttagcompound.getInt("p")))); ++ // Paper start - clean up broken entries ++ int delay = nbttagcompound.getInt("t"); ++ if (MAX_TICK_DELAY > 0 && delay > MAX_TICK_DELAY) { ++ MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockposition + ", tick delay " + delay); ++ continue; ++ } ++ list.add(new ChunkTickList.ScheduledTick<>(t0, blockposition, delay, TickPriority.byValue(nbttagcompound.getInt("p")))); ++ // Paper end - clean up broken entries + } + } + +diff --git a/src/main/java/net/minecraft/world/level/ServerTickList.java b/src/main/java/net/minecraft/world/level/ServerTickList.java +index 10ac1ba0a3d192486f22c2127d5bc30353f0edb6..65b3a16f40a295c2916be2a9fd019b452fb65e4f 100644 +--- a/src/main/java/net/minecraft/world/level/ServerTickList.java ++++ b/src/main/java/net/minecraft/world/level/ServerTickList.java +@@ -50,7 +50,16 @@ public class ServerTickList implements TickList { + private final co.aikar.timings.Timing timingTicking; // Paper + // Paper end + ++ // Paper start ++ public void nextTick() {} ++ // Paper end ++ ++ public void tick() { ++ // Paper start - allow overriding ++ this.tick(); ++ } + public void tick() { ++ // Paper end + int i = this.tickNextTickList.size(); + + if (false) { // CraftBukkit +@@ -118,28 +127,43 @@ public class ServerTickList implements TickList { + + @Override + public boolean willTickThisTick(BlockPos pos, T object) { +- return this.currentlyTicking.contains(new TickNextTickData<>(pos, object)); ++ // Paper start - allow overriding ++ return this.isPendingTickThisTick(pos, object); ++ } ++ public boolean isPendingTickThisTick(BlockPos blockposition, T t0) { ++ // Paper end ++ return this.currentlyTicking.contains(new TickNextTickData<>(blockposition, t0)); + } + + public List> fetchTicksInChunk(ChunkPos chunkcoordintpair, boolean updateState, boolean getStaleTicks) { ++ // Paper start - allow overriding ++ return this.getEntriesInChunk(chunkcoordintpair, updateState, getStaleTicks); ++ } ++ public List> getEntriesInChunk(ChunkPos chunkcoordintpair, boolean flag, boolean flag1) { ++ // Paper end + int i = (chunkcoordintpair.x << 4) - 2; + int j = i + 16 + 2; + int k = (chunkcoordintpair.z << 4) - 2; + int l = k + 16 + 2; + +- return this.fetchTicksInArea(new BoundingBox(i, 0, k, j, 256, l), updateState, getStaleTicks); ++ return this.fetchTicksInArea(new BoundingBox(i, 0, k, j, 256, l), flag, flag1); + } + + public List> fetchTicksInArea(BoundingBox bounds, boolean updateState, boolean getStaleTicks) { +- List> list = this.fetchTicksInArea((List) null, this.tickNextTickList, bounds, updateState); ++ // Paper start - allow overriding ++ return this.getEntriesInBoundingBox(bounds, updateState, getStaleTicks); ++ } ++ public List> getEntriesInBoundingBox(BoundingBox structureboundingbox, boolean flag, boolean flag1) { ++ // Paper end ++ List> list = this.fetchTicksInArea((List) null, this.tickNextTickList, structureboundingbox, flag); + +- if (updateState && list != null) { ++ if (flag && list != null) { + this.tickNextTickSet.removeAll(list); + } + +- list = this.fetchTicksInArea(list, this.currentlyTicking, bounds, updateState); +- if (!getStaleTicks) { +- list = this.fetchTicksInArea(list, this.alreadyTicked, bounds, updateState); ++ list = this.fetchTicksInArea(list, this.currentlyTicking, structureboundingbox, flag); ++ if (!flag1) { ++ list = this.fetchTicksInArea(list, this.alreadyTicked, structureboundingbox, flag); + } + + return list == null ? Collections.emptyList() : list; +@@ -170,14 +194,19 @@ public class ServerTickList implements TickList { + } + + public void copy(BoundingBox box, BlockPos offset) { +- List> list = this.fetchTicksInArea(box, false, false); ++ // Paper start - allow overriding ++ this.copy(box, offset); ++ } ++ public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { ++ // Paper end ++ List> list = this.fetchTicksInArea(structureboundingbox, false, false); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { + TickNextTickData nextticklistentry = (TickNextTickData) iterator.next(); + +- if (box.isInside((Vec3i) nextticklistentry.pos)) { +- BlockPos blockposition1 = nextticklistentry.pos.offset((Vec3i) offset); ++ if (structureboundingbox.isInside((Vec3i) nextticklistentry.pos)) { ++ BlockPos blockposition1 = nextticklistentry.pos.offset((Vec3i) blockposition); + T t0 = nextticklistentry.getType(); + + this.addTickData(new TickNextTickData<>(blockposition1, t0, nextticklistentry.triggerTick, nextticklistentry.priority)); +@@ -187,11 +216,17 @@ public class ServerTickList implements TickList { + } + + public ListTag save(ChunkPos chunkcoordintpair) { ++ // Paper start - allow overriding ++ return this.serialize(chunkcoordintpair); ++ } ++ public ListTag serialize(ChunkPos chunkcoordintpair) { ++ // Paper end + List> list = this.fetchTicksInChunk(chunkcoordintpair, false, true); + + return saveTickList(this.toId, list, this.level.getGameTime()); + } + ++ public static ListTag serialize(Function function, Iterable> iterable, long i) { return ServerTickList.saveTickList(function, iterable, i); } // Paper - OBFHELPER + private static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { + ListTag nbttaglist = new ListTag(); + Iterator iterator = scheduledTicks.iterator(); +@@ -214,13 +249,23 @@ public class ServerTickList implements TickList { + + @Override + public boolean hasScheduledTick(BlockPos pos, T object) { +- return this.tickNextTickSet.contains(new TickNextTickData<>(pos, object)); ++ // Paper start - allow overriding ++ return this.isScheduledForTick(pos, object); ++ } ++ public boolean isScheduledForTick(BlockPos blockposition, T t0) { ++ // Paper end ++ return this.tickNextTickSet.contains(new TickNextTickData<>(blockposition, t0)); + } + + @Override + public void scheduleTick(BlockPos pos, T object, int delay, TickPriority priority) { +- if (!this.ignore.test(object)) { +- this.addTickData(new TickNextTickData<>(pos, object, (long) delay + this.level.getGameTime(), priority)); ++ // Paper start - allow overriding ++ this.schedule(pos, object, delay, priority); ++ } ++ public void schedule(BlockPos blockposition, T t0, int i, TickPriority ticklistpriority) { ++ // Paper end ++ if (!this.ignore.test(t0)) { ++ this.addTickData(new TickNextTickData<>(blockposition, t0, (long) i + this.level.getGameTime(), ticklistpriority)); + } + + } +@@ -234,6 +279,11 @@ public class ServerTickList implements TickList { + } + + public int size() { ++ // Paper start - allow overriding ++ return this.getTotalScheduledEntries(); ++ } ++ public int getTotalScheduledEntries() { ++ // Paper end + return this.tickNextTickSet.size(); + } + } +diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java +index 90833389022d7412bdda8868a356b84f62a00e03..61cdaf45368dcc40f3311e8b7f8637a6c93a2d76 100644 +--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java ++++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java +@@ -6,11 +6,13 @@ import net.minecraft.core.BlockPos; + public class TickNextTickData { + + private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading +- private final T type; +- public final BlockPos pos; +- public final long triggerTick; +- public final TickPriority priority; +- private final long c; ++ private final T type; public final T getData() { return this.type; } // Paper - OBFHELPER ++ public final BlockPos pos; public final BlockPos getPosition() { return this.pos; } // Paper - OBFHELPER ++ public final long triggerTick; public final long getTargetTick() { return this.triggerTick; } // Paper - OBFHELPER ++ public final TickPriority priority; public final TickPriority getPriority() { return this.priority; } // Paper - OBFHELPER ++ private final long c; public final long getId() { return this.c; } // Paper - OBFHELPER ++ private final int hash; // Paper ++ public int tickState; // Paper + + public TickNextTickData(BlockPos pos, T t) { + this(pos, t, 0L, TickPriority.NORMAL); +@@ -22,6 +24,7 @@ public class TickNextTickData { + this.type = t; + this.triggerTick = time; + this.priority = priority; ++ this.hash = this.computeHash(); // Paper + } + + public boolean equals(Object object) { +@@ -34,19 +37,31 @@ public class TickNextTickData { + } + } + ++ // Paper start - optimize hashcode ++ @Override + public int hashCode() { ++ return this.hash; ++ } ++ public final int computeHash() { ++ // Paper end - optimize hashcode + return this.pos.hashCode(); + } + +- public static Comparator createTimeComparator() { // Paper - decompile fix +- return Comparator.comparingLong((nextticklistentry) -> { +- return ((TickNextTickData) nextticklistentry).triggerTick; // Paper - decompile fix +- }).thenComparing((nextticklistentry) -> { +- return ((TickNextTickData) nextticklistentry).priority; // Paper - decompile fix +- }).thenComparingLong((nextticklistentry) -> { +- return ((TickNextTickData) nextticklistentry).c; // Paper - decompile fix +- }); ++ // Paper start - let's not use more functional code for no reason. ++ public static Comparator comparator() { return TickNextTickData.createTimeComparator(); } // Paper - OBFHELPER ++ public static Comparator createTimeComparator() { ++ return (Comparator)(Comparator)(TickNextTickData nextticklistentry, TickNextTickData nextticklistentry1) -> { ++ int i = Long.compare(nextticklistentry.getTargetTick(), nextticklistentry1.getTargetTick()); ++ ++ if (i != 0) { ++ return i; ++ } else { ++ i = nextticklistentry.getPriority().compareTo(nextticklistentry1.getPriority()); ++ return i != 0 ? i : Long.compare(nextticklistentry.getId(), nextticklistentry1.getId()); ++ } ++ }; + } ++ // Paper end - let's not use more functional code for no reason. + + public String toString() { + return this.type + ": " + this.pos + ", " + this.triggerTick + ", " + this.priority + ", " + this.c; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java b/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java +index 76bea58d35d352ee6f3d4bd0d10af3b6d615ae2c..4288fa253668196e6c32a876f18ec496fb3abad6 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java +@@ -8,12 +8,12 @@ import net.minecraft.nbt.IntArrayTag; + + public class BoundingBox { + +- public int x0; +- public int y0; +- public int z0; +- public int x1; +- public int y1; +- public int z1; ++ public int x0; public final int getMinX() { return this.x0; } // Paper - OBFHELPER ++ public int y0; public final int getMinY() { return this.y0; } // Paper - OBFHELPER ++ public int z0; public final int getMinZ() { return this.z0; } // Paper - OBFHELPER ++ public int x1; public final int getMaxX() { return this.x1; } // Paper - OBFHELPER ++ public int y1; public final int getMaxY() { return this.y1; } // Paper - OBFHELPER ++ public int z1; public final int getMaxZ() { return this.z1; } // Paper - OBFHELPER + + public BoundingBox() {} + +@@ -92,6 +92,7 @@ public class BoundingBox { + this.y1 = 512; + } + ++ public final boolean intersects(BoundingBox boundingBox) { return this.intersects(boundingBox); } // Paper - OBFHELPER + public boolean intersects(BoundingBox other) { + return this.x1 >= other.x0 && this.x0 <= other.x1 && this.z1 >= other.z0 && this.z0 <= other.z1 && this.y1 >= other.y0 && this.y0 <= other.y1; + } +@@ -126,6 +127,7 @@ public class BoundingBox { + this.move(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); + } + ++ public final boolean hasPoint(Vec3i baseblockposition) { return this.isInside(baseblockposition); } // Paper - OBFHELPER + public boolean isInside(Vec3i vec) { + return vec.getX() >= this.x0 && vec.getX() <= this.x1 && vec.getZ() >= this.z0 && vec.getZ() <= this.z1 && vec.getY() >= this.y0 && vec.getY() <= this.y1; + } diff --git a/patches/server-remapped/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server-remapped/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch new file mode 100644 index 0000000000..6e0269c7f2 --- /dev/null +++ b/patches/server-remapped/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch @@ -0,0 +1,155 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Sat, 1 Feb 2020 16:50:39 +0100 +Subject: [PATCH] Pillager patrol spawn settings and per player options + +This adds config options for defining the spawn chance, spawn delay and +spawn start day as well as toggles for handling the spawn delay and +start day per player. (Based on the time played statistic) +When not per player it will use the Vanilla mechanic of one delay per +world and the world age for the start day. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 525d702d78a609af987ebd2c32169b873e5c05ed..6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -582,10 +582,21 @@ public class PaperWorldConfig { + } + + public boolean disablePillagerPatrols = false; ++ public double patrolSpawnChance = 0.2; ++ public boolean patrolPerPlayerDelay = false; ++ public int patrolDelay = 12000; ++ public boolean patrolPerPlayerStart = false; ++ public int patrolStartDay = 5; + private void pillagerSettings() { + disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); ++ patrolSpawnChance = getDouble("game-mechanics.pillager-patrols.spawn-chance", patrolSpawnChance); ++ patrolPerPlayerDelay = getBoolean("game-mechanics.pillager-patrols.spawn-delay.per-player", patrolPerPlayerDelay); ++ patrolDelay = getInt("game-mechanics.pillager-patrols.spawn-delay.ticks", patrolDelay); ++ patrolPerPlayerStart = getBoolean("game-mechanics.pillager-patrols.start.per-player", patrolPerPlayerStart); ++ patrolStartDay = getInt("game-mechanics.pillager-patrols.start.day", patrolStartDay); + } + ++ + public boolean entitiesTargetWithFollowRange = false; + private void entitiesTargetWithFollowRange() { + entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 7f4e81ee3339e90b8525541dccf6dea187853cf7..a469016c43251f16913a365c4131b2448eaa4c48 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -213,6 +213,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public boolean wonGame; + private int containerUpdateDelay; // Paper + public long loginTime; // Paper ++ public int patrolSpawnDelay; // Paper - per player patrol spawns + // Paper start - cancellable death event + public boolean queueHealthUpdatePacket = false; + public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; +diff --git a/src/main/java/net/minecraft/stats/StatType.java b/src/main/java/net/minecraft/stats/StatType.java +index ba48795a7b7cbf4622e64273ab488e26d7a862e2..b85987910cf80b1d1a04a7b772e19200f4ce4372 100644 +--- a/src/main/java/net/minecraft/stats/StatType.java ++++ b/src/main/java/net/minecraft/stats/StatType.java +@@ -28,6 +28,7 @@ public class StatType implements Iterable> { + return this.map.values().iterator(); + } + ++ public final Stat get(T t) { return this.get(t); }; // Paper - OBFHELPER + public Stat get(T key) { + return this.get(key, StatFormatter.DEFAULT); + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +index 48efe133d294bb1b17e8ac8b44eea8a29f15845f..dcbe74bdb1b6e07f7b8845182576ef544493d377 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +@@ -4,11 +4,12 @@ import java.util.Random; + import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.stats.Stats; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.monster.PatrollingMonster; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.CustomSpawner; + import net.minecraft.world.level.GameRules; +@@ -20,13 +21,13 @@ import net.minecraft.world.level.block.state.BlockState; + + public class PatrolSpawner implements CustomSpawner { + +- private int nextTick; ++ private int nextTick;private int getSpawnDelay() { return nextTick; } private void setSpawnDelay(int spawnDelay) { this.nextTick = spawnDelay; } // Paper - OBFHELPER + + public PatrolSpawner() {} + + @Override + public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { +- if (world.paperConfig.disablePillagerPatrols) return 0; // Paper ++ if (world.paperConfig.disablePillagerPatrols || world.paperConfig.patrolSpawnChance == 0) return 0; // Paper + if (!spawnMonsters) { + return 0; + } else if (!world.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) { +@@ -34,23 +35,51 @@ public class PatrolSpawner implements CustomSpawner { + } else { + Random random = world.random; + +- --this.nextTick; +- if (this.nextTick > 0) { ++ // Paper start - Patrol settings ++ // Random player selection moved up for per player spawning and configuration ++ int j = world.players().size(); ++ if (j < 1) { + return 0; ++ } ++ ++ ServerPlayer entityhuman = world.players().get(random.nextInt(j)); ++ if (entityhuman.isSpectator()) { ++ return 0; ++ } ++ ++ int patrolSpawnDelay; ++ if (world.paperConfig.patrolPerPlayerDelay) { ++ --entityhuman.patrolSpawnDelay; ++ patrolSpawnDelay = entityhuman.patrolSpawnDelay; + } else { +- this.nextTick += 12000 + random.nextInt(1200); +- long i = world.getDayTime() / 24000L; ++ setSpawnDelay(getSpawnDelay() - 1); ++ patrolSpawnDelay = getSpawnDelay(); ++ } ++ ++ if (patrolSpawnDelay > 0) { ++ return 0; ++ } else { ++ long days; ++ if (world.paperConfig.patrolPerPlayerStart) { ++ days = entityhuman.getStats().getValue(Stats.CUSTOM.get(Stats.PLAY_ONE_MINUTE)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang ++ } else { ++ days = world.getDayTime() / 24000L; ++ } ++ if (world.paperConfig.patrolPerPlayerDelay) { ++ entityhuman.patrolSpawnDelay += world.paperConfig.patrolDelay + random.nextInt(1200); ++ } else { ++ setSpawnDelay(getSpawnDelay() + world.paperConfig.patrolDelay + random.nextInt(1200)); ++ } + +- if (i >= 5L && world.isDay()) { +- if (random.nextInt(5) != 0) { ++ if (days >= world.paperConfig.patrolStartDay && world.isDay()) { ++ if (random.nextDouble() >= world.paperConfig.patrolSpawnChance) { ++ // Paper end + return 0; + } else { +- int j = world.players().size(); + + if (j < 1) { + return 0; + } else { +- Player entityhuman = (Player) world.players().get(random.nextInt(j)); + + if (entityhuman.isSpectator()) { + return 0; diff --git a/patches/server-remapped/0418-Ensure-Entity-is-never-double-registered.patch b/patches/server-remapped/0418-Ensure-Entity-is-never-double-registered.patch new file mode 100644 index 0000000000..0c956bdb77 --- /dev/null +++ b/patches/server-remapped/0418-Ensure-Entity-is-never-double-registered.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 29 Mar 2020 18:26:14 -0400 +Subject: [PATCH] Ensure Entity is never double registered + +If something calls register twice, and the world is ticking, it could be +enqueued to add twice. + +Vs behavior of non ticking of just overwriting state. + +We will now simply log a warning when this happens instead of crashing the server. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 9da0d98bc2ed7876a00a734690ed42f01b9a9a9b..9898d5c8fab63c576831bd416ccf1854ed077b0d 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -643,6 +643,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + Entity entity2; + + while ((entity2 = (Entity) this.toAddAfterTick.poll()) != null) { ++ if (!entity2.isQueuedForRegister) continue; // Paper - ignore cancelled registers + this.add(entity2); + } + +@@ -1400,6 +1401,19 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + public void onEntityRemoved(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot ++ // Paper start - fix entity registration issues ++ if (entity instanceof EnderDragonPart) { ++ // Usually this is a no-op for complex parts, and ID's should be removed, but go ahead and remove it anyways ++ // Dragon parts are handled special in register. they don't receive a valid = true or register by UUID etc. ++ this.entitiesById.remove(entity.getId(), entity); ++ return; ++ } ++ if (!entity.valid) { ++ // Someone called remove before we ever got added, cancel the add. ++ entity.isQueuedForRegister = false; ++ return; ++ } ++ // Paper end + // Spigot start + if ( entity instanceof Player ) + { +@@ -1466,9 +1480,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + private void add(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot ++ // Paper start - don't double enqueue entity registration ++ //noinspection ObjectEquality ++ if (this.entitiesById.get(entity.getId()) == entity) { ++ LOGGER.error(entity + " was already registered!"); ++ new Throwable().printStackTrace(); ++ return; ++ } ++ // Paper end + if (this.tickingEntities) { +- this.toAddAfterTick.add(entity); ++ if (!entity.isQueuedForRegister) { // Paper ++ this.toAddAfterTick.add(entity); ++ entity.isQueuedForRegister = true; // Paper ++ } + } else { ++ entity.isQueuedForRegister = false; // Paper + this.entitiesById.put(entity.getId(), entity); + if (entity instanceof EnderDragon) { + EnderDragonPart[] aentitycomplexpart = ((EnderDragon) entity).getSubEntities(); +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 43f77d01fceab107d3502d282205aa579d64cc4b..7e198b94f349d4c4d61502f5ad8c60686800d88f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -147,6 +147,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + // Paper start ++ public boolean isQueuedForRegister = false; + public static Random SHARED_RANDOM = new Random() { + private boolean locked = false; + @Override diff --git a/patches/server-remapped/0419-Fix-unregistering-entities-from-unloading-chunks.patch b/patches/server-remapped/0419-Fix-unregistering-entities-from-unloading-chunks.patch new file mode 100644 index 0000000000..110790b17f --- /dev/null +++ b/patches/server-remapped/0419-Fix-unregistering-entities-from-unloading-chunks.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 31 Mar 2020 03:01:45 -0400 +Subject: [PATCH] Fix unregistering entities from unloading chunks + +CraftBukkit caused a regression here by making unloading chunks not +have a ticket added and returning unloaded future. + +This caused entities who were killed in same tick their chunk is unloading +to not be able to be removed from the chunk. + +This then results in dead entities lingering in the Chunk. + +Combine that with a buggy detail of the previous implementation of +the Dupe UUID patch, then this was the likely source of the "Ghost entities" + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 9898d5c8fab63c576831bd416ccf1854ed077b0d..c5dc41a3cf499038bd33451a189913cd3978b230 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1559,9 +1559,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + private void removeFromChunk(Entity entity) { +- ChunkAccess ichunkaccess = chunkSource.getChunkUnchecked(entity.xChunk, entity.zChunk); // CraftBukkit - SPIGOT-5228: getChunkAt won't find the entity's chunk if it has already been unloaded (i.e. if it switched to state INACCESSIBLE). ++ LevelChunk ichunkaccess = entity.getCurrentChunk(); // Paper - getChunkAt(x,z,full,false) is broken by CraftBukkit as it won't return an unloading chunk. Use our current chunk reference as this points to what chunk they need to be removed from anyways + +- if (ichunkaccess instanceof LevelChunk) { ++ if (ichunkaccess != null) { // Paper + ((LevelChunk) ichunkaccess).removeEntity(entity); + } + diff --git a/patches/server-remapped/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server-remapped/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch new file mode 100644 index 0000000000..a83d559354 --- /dev/null +++ b/patches/server-remapped/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 31 Mar 2020 03:50:42 -0400 +Subject: [PATCH] Remote Connections shouldn't hold up shutdown + +Bugs in the connection logic appears to leave stale connections even, preventing shutdown + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 4862a9519d4ba5f05b634a0335837bea9812edee..f8ddc0aa98874c7879a51e76d1a629cbdaf58812 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -397,11 +397,11 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } + + if (this.rconThread != null) { +- this.rconThread.stop(); ++ //this.remoteControlListener.b(); // Paper - don't wait for remote connections + } + + if (this.queryThreadGs4 != null) { +- this.queryThreadGs4.stop(); ++ //this.remoteStatusListener.b(); // Paper - don't wait for remote connections + } + + System.exit(0); // CraftBukkit diff --git a/patches/server-remapped/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server-remapped/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch new file mode 100644 index 0000000000..044507e1b4 --- /dev/null +++ b/patches/server-remapped/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Tue, 17 Mar 2020 14:18:50 -0500 +Subject: [PATCH] Do not allow bees to load chunks for beehives + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java +index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e99b45d887 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -358,6 +358,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + if (this.hivePos == null) { + return false; + } else { ++ if (!this.level.isLoadedAndInBounds(hivePos)) return false; // Paper + BlockEntity tileentity = this.level.getBlockEntity(this.hivePos); + + return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby(); +@@ -390,6 +391,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + } + + private boolean doesHiveHaveSpace(BlockPos pos) { ++ if (!this.level.isLoadedAndInBounds(pos)) return false; // Paper + BlockEntity tileentity = this.level.getBlockEntity(pos); + + return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false; +@@ -632,6 +634,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + @Override + public boolean canBeeUse() { + if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerThan((Position) Bee.this.position(), 2.0D)) { ++ if (!Bee.this.level.isLoadedAndInBounds(Bee.this.hivePos)) return false; // Paper + BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos); + + if (tileentity instanceof BeehiveBlockEntity) { +@@ -655,6 +658,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + + @Override + public void start() { ++ if (!Bee.this.level.isLoadedAndInBounds(Bee.this.hivePos)) return; // Paper + BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos); + + if (tileentity instanceof BeehiveBlockEntity) { diff --git a/patches/server-remapped/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server-remapped/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch new file mode 100644 index 0000000000..720e9dcff9 --- /dev/null +++ b/patches/server-remapped/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 01:42:39 -0400 +Subject: [PATCH] Prevent Double PlayerChunkMap adds crashing server + +Suspected case would be around the technique used in .stopRiding +Stack will identify any causer of this and warn instead of crashing. + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 6da406c8403797a1cd9276ac06577c3c080a8a22..e6eeca5834a164d87f5b0e564fe6237902edaa6a 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1501,6 +1501,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + protected void addEntity(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot ++ // Paper start - ignore and warn about illegal addEntity calls instead of crashing server ++ if (!entity.valid || entity.level != this.level || this.entityMap.containsKey(entity.getId())) { ++ new Throwable("[ERROR] Illegal PlayerChunkMap::addEntity for world " + this.level.getWorld().getName() ++ + ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : "")) ++ .printStackTrace(); ++ return; ++ } ++ // Paper end + if (!(entity instanceof EnderDragonPart)) { + EntityType entitytypes = entity.getType(); + int i = entitytypes.clientTrackingRange() * 16; +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index c5dc41a3cf499038bd33451a189913cd3978b230..5127bce423a83711cea94e387b3ae7866215ded5 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1525,7 +1525,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + } + +- this.getChunkSource().addEntity(entity); ++ // this.getChunkProvider().addEntity(entity); // Paper - moved down below valid=true + // CraftBukkit start - SPIGOT-5278 + if (entity instanceof Drowned) { + this.navigations.add(((Drowned) entity).waterNavigation); +@@ -1536,6 +1536,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.navigations.add(((Mob) entity).getNavigation()); + } + entity.valid = true; // CraftBukkit ++ this.getChunkSource().addEntity(entity); // Paper - from above to be below valid=true + // Paper start - Set origin location when the entity is being added to the world + if (entity.origin == null) { + entity.origin = entity.getBukkitEntity().getLocation(); diff --git a/patches/server-remapped/0423-Optimize-Collision-to-not-load-chunks.patch b/patches/server-remapped/0423-Optimize-Collision-to-not-load-chunks.patch new file mode 100644 index 0000000000..58edb5460d --- /dev/null +++ b/patches/server-remapped/0423-Optimize-Collision-to-not-load-chunks.patch @@ -0,0 +1,185 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 02:37:57 -0400 +Subject: [PATCH] Optimize Collision to not load chunks + +The collision code takes an AABB and generates a cuboid of checks rather +than a cylinder, so at high velocity this can generate a lot of chunk checks. + +Treat an unloaded chunk as a collision for entities, and also for players if +the "prevent moving into unloaded chunks" setting is enabled. + +If that serting is not enabled, collisions will be ignored for players, since +movement will load only the chunk the player enters anyways and avoids loading +massive amounts of surrounding chunks due to large AABB lookups. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index dfdde9722bc0d83916779014b7718eef2c01b3db..86c5549196a4e9011c5240e7918b466c299be4a3 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -59,12 +59,23 @@ import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.PlayerAdvancements; + import net.minecraft.server.ServerScoreboard; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.ServerPlayerGameMode; ++import net.minecraft.server.level.TicketType; ++import net.minecraft.server.network.ServerGamePacketListenerImpl; ++import net.minecraft.server.network.ServerLoginPacketListenerImpl; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.stats.ServerStatsCounter; ++import net.minecraft.stats.Stats; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.Tag; + import net.minecraft.util.Mth; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GameType; + import net.minecraft.world.level.Level; +@@ -90,15 +101,6 @@ import io.papermc.paper.adventure.PaperAdventure; // Paper + import com.google.common.base.Predicate; + import com.google.common.collect.Iterables; + import net.minecraft.server.dedicated.DedicatedServer; +-import net.minecraft.server.level.ServerLevel; +-import net.minecraft.server.level.ServerPlayer; +-import net.minecraft.server.level.ServerPlayerGameMode; +-import net.minecraft.server.network.ServerGamePacketListenerImpl; +-import net.minecraft.server.network.ServerLoginPacketListenerImpl; +-import net.minecraft.sounds.SoundEvents; +-import net.minecraft.sounds.SoundSource; +-import net.minecraft.stats.ServerStatsCounter; +-import net.minecraft.stats.Stats; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; + +@@ -805,6 +807,7 @@ public abstract class PlayerList { + entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + // CraftBukkit end + ++ worldserver1.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, new ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper + while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < 256.0D) { + entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 7e198b94f349d4c4d61502f5ad8c60686800d88f..b8dcc91a191f25ca578e0858abf6c1b874fee15d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -168,6 +168,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + private CraftEntity bukkitEntity; + + ChunkMap.TrackedEntity tracker; // Paper ++ public boolean collisionLoadChunks = false; // Paper + public Throwable addedToWorldStack; // Paper - entity debug + public CraftEntity getBukkitEntity() { + if (bukkitEntity == null) { +diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java +index d9e69195ee0af4dfb90bf0e8f4cc65e63f7ecf5b..1b52f2a0ce9cb847d7d57b38f4b8b6bed8de2cd9 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionGetter.java ++++ b/src/main/java/net/minecraft/world/level/CollisionGetter.java +@@ -54,7 +54,9 @@ public interface CollisionGetter extends BlockGetter { + } + + default boolean noCollision(@Nullable Entity entity, AABB axisalignedbb, Predicate predicate) { ++ try { if (entity != null) entity.collisionLoadChunks = true; // Paper + return this.getCollisions(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty); ++ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper + } + + Stream getEntityCollisions(@Nullable Entity entity, AABB axisalignedbb, Predicate predicate); +diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +index 7208c61da48ce5e735810b6268490584e1d5c260..feca9ff34936686c0665ae0dbc926869087df3a7 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java ++++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +@@ -7,6 +7,9 @@ import java.util.function.Consumer; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Cursor3D; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.WorldGenRegion; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.block.Blocks; +@@ -21,13 +24,13 @@ import net.minecraft.world.phys.shapes.VoxelShape; + public class CollisionSpliterator extends AbstractSpliterator { + + @Nullable +- private final Entity source; ++ private final Entity source; final Entity getEntity() { return this.source; } // Paper - OBFHELPER + private final AABB box; + private final CollisionContext context; + private final Cursor3D cursor; +- private final BlockPos.MutableBlockPos pos; ++ private final BlockPos.MutableBlockPos pos; final BlockPos.MutableBlockPos getMutablePos() { return this.pos; } // Paper - OBFHELPER + private final VoxelShape entityShape; +- private final CollisionGetter collisionGetter; ++ private final CollisionGetter collisionGetter; final CollisionGetter getCollisionAccess() { return this.collisionGetter; } // Paper - OBFHELPER + private boolean needsBorderCheck; + private final BiPredicate predicate; + +@@ -64,23 +67,37 @@ public class CollisionSpliterator extends AbstractSpliterator { + boolean collisionCheck(Consumer consumer) { + while (true) { + if (this.cursor.advance()) { +- int i = this.cursor.nextX(); +- int j = this.cursor.nextY(); +- int k = this.cursor.nextZ(); ++ int i = this.cursor.nextX(); final int x = i; ++ int j = this.cursor.nextY(); final int y = j; ++ int k = this.cursor.nextZ(); final int z = k; + int l = this.cursor.getNextType(); + + if (l == 3) { + continue; + } + +- BlockGetter iblockaccess = this.getChunk(i, k); +- +- if (iblockaccess == null) { ++ // Paper start - ensure we don't load chunks ++ Entity entity = this.getEntity(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getMutablePos(); ++ boolean far = entity != null && MCUtil.distanceSq(entity.getX(), y, entity.getZ(), x, y, z) > 14; ++ blockposition_mutableblockposition.setValues(x, y, z); ++ ++ boolean isRegionLimited = this.getCollisionAccess() instanceof WorldGenRegion; ++ BlockState iblockdata = isRegionLimited ? Blocks.VOID_AIR.defaultBlockState() : ((!far && entity instanceof ServerPlayer) || (entity != null && entity.collisionLoadChunks) ++ ? this.getCollisionAccess().getBlockState(blockposition_mutableblockposition) ++ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition) ++ ); ++ ++ if (iblockdata == null) { ++ if (!(entity instanceof ServerPlayer) || entity.level.paperConfig.preventMovingIntoUnloadedChunks) { ++ VoxelShape voxelshape3 = Shapes.of(far ? entity.getBoundingBox() : new AABB(new BlockPos(x, y, z))); ++ consumer.accept(voxelshape3); ++ return true; ++ } + continue; + } +- +- this.pos.set(i, j, k); +- BlockState iblockdata = iblockaccess.getBlockState(this.pos); ++ // Paper - moved up ++ // Paper end + + if (!this.predicate.test(iblockdata, this.pos) || l == 1 && !iblockdata.hasLargeCollisionShape() || l == 2 && !iblockdata.is(Blocks.MOVING_PISTON)) { + continue; +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index fa2942d0b0424390daee2121f8959034c5352e0b..c14d5ebe16a693834ed218af8f737714065b2e17 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -249,7 +249,8 @@ public final class Shapes { + + if (k2 < 3) { + blockposition_mutableblockposition.set(enumaxiscycle1, i2, j2, l1); +- BlockState iblockdata = world.getBlockState(blockposition_mutableblockposition); ++ BlockState iblockdata = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper ++ if (iblockdata == null) return 0.0D; // Paper + + if ((k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { + initial = iblockdata.getCollisionShape((BlockGetter) world, blockposition_mutableblockposition, context).collide(enumdirection_enumaxis2, box.move((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), initial); diff --git a/patches/server-remapped/0424-Don-t-tick-dead-players.patch b/patches/server-remapped/0424-Don-t-tick-dead-players.patch new file mode 100644 index 0000000000..b748ace1a1 --- /dev/null +++ b/patches/server-remapped/0424-Don-t-tick-dead-players.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 17:16:48 -0400 +Subject: [PATCH] Don't tick dead players + +Causes sync chunk loads and who knows what all else. +This is safe because Spectators are skipped in unloaded chunks too in vanilla. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index a469016c43251f16913a365c4131b2448eaa4c48..286b75a27103a084a9f9d79a90716ebcad65d813 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -606,7 +606,7 @@ public class ServerPlayer extends Player implements ContainerListener { + + public void doTick() { + try { +- if (!this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { ++ if (valid && !this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) + super.tick(); + } + diff --git a/patches/server-remapped/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server-remapped/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch new file mode 100644 index 0000000000..3e2b8e5352 --- /dev/null +++ b/patches/server-remapped/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 19:31:16 -0400 +Subject: [PATCH] Dead Player's shouldn't be able to move + +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 0685920073a6a2b2c6a80018d0c9009b2ef860c4..32f1b180e82f41f3ce1b49ea7d67b7d55d2b9ca7 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1046,7 +1046,7 @@ public abstract class Player extends LivingEntity { + + @Override + protected boolean isImmobile() { +- return super.isImmobile() || this.isSleeping(); ++ return super.isImmobile() || this.isSleeping() || removed || !valid; // Paper - player's who are dead or not in a world shouldn't move... + } + + @Override diff --git a/patches/server-remapped/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server-remapped/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch new file mode 100644 index 0000000000..a211d40a2c --- /dev/null +++ b/patches/server-remapped/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch @@ -0,0 +1,294 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 8 Apr 2020 03:06:30 -0400 +Subject: [PATCH] Optimize PlayerChunkMap memory use for visibleChunks + +No longer clones visible chunks which is causing massive memory +allocation issues, likely the source of Humongous Objects on large servers. + +Instead we just synchronize, clear and rebuild, reusing the same object buffers +as before with only 2 small objects created (FastIterator/MapEntry) + +This should result in siginificant memory use reduction and improved GC behavior. + +diff --git a/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f6ff4d8132a95895680f5bc81f8f873e78f0bbdb +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java +@@ -0,0 +1,39 @@ ++package com.destroystokyo.paper.util.map; ++ ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++ ++public class Long2ObjectLinkedOpenHashMapFastCopy extends Long2ObjectLinkedOpenHashMap { ++ ++ public void copyFrom(Long2ObjectLinkedOpenHashMapFastCopy map) { ++ if (key.length != map.key.length) { ++ key = null; ++ key = new long[map.key.length]; ++ } ++ if (value.length != map.value.length) { ++ value = null; ++ //noinspection unchecked ++ value = (V[]) new Object[map.value.length]; ++ } ++ if (link.length != map.link.length) { ++ link = null; ++ link = new long[map.link.length]; ++ } ++ System.arraycopy(map.key, 0, this.key, 0, map.key.length); ++ System.arraycopy(map.value, 0, this.value, 0, map.value.length); ++ System.arraycopy(map.link, 0, this.link, 0, map.link.length); ++ this.size = map.size; ++ this.mask = map.mask; ++ this.first = map.first; ++ this.last = map.last; ++ this.n = map.n; ++ this.maxFill = map.maxFill; ++ this.containsNullKey = map.containsNullKey; ++ } ++ ++ @Override ++ public Long2ObjectLinkedOpenHashMapFastCopy clone() { ++ Long2ObjectLinkedOpenHashMapFastCopy clone = (Long2ObjectLinkedOpenHashMapFastCopy) super.clone(); ++ clone.copyFrom(this); ++ return clone; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 99c3337eec552ba47d3b8b2d8feaaa80acf2a86f..9abef8550a89df5e15ac28de1a5549d064f29122 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -616,7 +616,7 @@ public final class MCUtil { + + ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); + ChunkMap chunkMap = world.getChunkSource().chunkMap; +- Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunkMap; ++ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.getVisibleChunks(); + DistanceManager chunkMapDistance = chunkMap.distanceManager; + List allChunks = new ArrayList<>(visibleChunks.values()); + List players = world.players; +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc08174003f4a 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -104,8 +104,33 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + private static final Logger LOGGER = LogManager.getLogger(); + public static final int MAX_CHUNK_DISTANCE = 33 + ChunkStatus.maxDistance(); +- public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); +- public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; ++ // Paper start - faster copying ++ public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<>(); // Paper - faster copying ++ public final Long2ObjectLinkedOpenHashMap visibleChunkMap = new ProtectedVisibleChunksMap(); // Paper - faster copying ++ ++ private class ProtectedVisibleChunksMap extends com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy { ++ @Override ++ public ChunkHolder put(long k, ChunkHolder playerChunk) { ++ throw new UnsupportedOperationException("Updating visible Chunks"); ++ } ++ ++ @Override ++ public ChunkHolder remove(long k) { ++ throw new UnsupportedOperationException("Removing visible Chunks"); ++ } ++ ++ @Override ++ public ChunkHolder get(long k) { ++ return ChunkMap.this.getVisibleChunkIfPresent(k); ++ } ++ ++ public ChunkHolder safeGet(long k) { ++ return super.get(k); ++ } ++ } ++ // Paper end ++ public final com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy pendingVisibleChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy(); // Paper - this is used if the visible chunks is updated while iterating only ++ public transient com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy visibleChunksClone; // Paper - used for async access of visible chunks, clone and cache only when needed + private final Long2ObjectLinkedOpenHashMap pendingUnloads; + public final LongSet entitiesInLevel; // Paper - private -> public + public final ServerLevel level; +@@ -178,7 +203,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier supplier, int i, boolean flag) { + super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag); +- this.visibleChunkMap = this.updatingChunkMap.clone(); ++ //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning + this.pendingUnloads = new Long2ObjectLinkedOpenHashMap(); + this.entitiesInLevel = new LongOpenHashSet(); + this.toDrop = new LongOpenHashSet(); +@@ -270,9 +295,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return (ChunkHolder) this.updatingChunkMap.get(pos); + } + ++ // Paper start - remove cloning of visible chunks unless accessed as a collection async ++ private static final boolean DEBUG_ASYNC_VISIBLE_CHUNKS = Boolean.getBoolean("paper.debug-async-visible-chunks"); ++ private boolean isIterating = false; ++ private boolean hasPendingVisibleUpdate = false; ++ public void forEachVisibleChunk(java.util.function.Consumer consumer) { ++ org.spigotmc.AsyncCatcher.catchOp("forEachVisibleChunk"); ++ boolean prev = isIterating; ++ isIterating = true; ++ try { ++ for (ChunkHolder value : this.visibleChunkMap.values()) { ++ consumer.accept(value); ++ } ++ } finally { ++ this.isIterating = prev; ++ if (!this.isIterating && this.hasPendingVisibleUpdate) { ++ ((ProtectedVisibleChunksMap)this.visibleChunkMap).copyFrom(this.pendingVisibleChunks); ++ this.pendingVisibleChunks.clear(); ++ this.hasPendingVisibleUpdate = false; ++ } ++ } ++ } ++ public Long2ObjectLinkedOpenHashMap getVisibleChunks() { ++ if (Thread.currentThread() == this.level.thread) { ++ return this.visibleChunkMap; ++ } else { ++ synchronized (this.visibleChunkMap) { ++ if (DEBUG_ASYNC_VISIBLE_CHUNKS) new Throwable("Async getVisibleChunks").printStackTrace(); ++ if (this.visibleChunksClone == null) { ++ this.visibleChunksClone = this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.clone() : ((ProtectedVisibleChunksMap)this.visibleChunkMap).clone(); ++ } ++ return this.visibleChunksClone; ++ } ++ } ++ } ++ // Paper end ++ + @Nullable + public ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public +- return (ChunkHolder) this.visibleChunkMap.get(pos); ++ // Paper start - mt safe get ++ if (Thread.currentThread() != this.level.thread) { ++ synchronized (this.visibleChunkMap) { ++ return (ChunkHolder) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(pos) : ((ProtectedVisibleChunksMap)this.visibleChunkMap).safeGet(pos)); ++ } ++ } ++ return (ChunkHolder) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(pos) : ((ProtectedVisibleChunksMap)this.visibleChunkMap).safeGet(pos)); ++ // Paper end + } + + protected IntSupplier getChunkQueueLevel(long pos) { +@@ -460,8 +528,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end + + protected void saveAllChunks(boolean flush) { ++ Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) + if (flush) { +- List list = (List) this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); ++ List list = (List) visibleChunks.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); // Paper - remove cloning of visible chunks + MutableBoolean mutableboolean = new MutableBoolean(); + + do { +@@ -489,7 +558,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // this.i(); // Paper - nuke IOWorker + ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); + } else { +- this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { ++ visibleChunks.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { + ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error + + if (ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk) { +@@ -660,7 +729,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (!this.modified) { + return false; + } else { +- this.visibleChunkMap = this.updatingChunkMap.clone(); ++ // Paper start - stop cloning visibleChunks ++ synchronized (this.visibleChunkMap) { ++ if (isIterating) { ++ hasPendingVisibleUpdate = true; ++ this.pendingVisibleChunks.copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunkMap); ++ } else { ++ hasPendingVisibleUpdate = false; ++ this.pendingVisibleChunks.clear(); ++ ((ProtectedVisibleChunksMap)this.visibleChunkMap).copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunkMap); ++ this.visibleChunksClone = null; ++ } ++ } ++ // Paper end ++ + this.modified = false; + return true; + } +@@ -1139,12 +1221,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + protected Iterable getChunks() { +- return Iterables.unmodifiableIterable(this.visibleChunkMap.values()); ++ return Iterables.unmodifiableIterable(this.getVisibleChunks().values()); // Paper + } + + void dumpChunks(Writer writer) throws IOException { + CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("entity_count").addColumn("block_entity_count").build(writer); +- ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunkMap.long2ObjectEntrySet().iterator(); ++ ObjectBidirectionalIterator objectbidirectionaliterator = this.getVisibleChunks().long2ObjectEntrySet().iterator(); // Paper + + while (objectbidirectionaliterator.hasNext()) { + Entry entry = (Entry) objectbidirectionaliterator.next(); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index e2b1541042bceac965411e3176d08c61f217c07f..f5de878020be9465739fba07fd7dea46b0a3ae34 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -782,7 +782,7 @@ public class ServerChunkCache extends ChunkSource { + }; + // Paper end + this.level.timings.chunkTicks.startTiming(); // Paper +- this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... ++ this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + + if (optional.isPresent()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index fb74bdcf4c2935b56e92717cc5a1504fbc853d0a..1a839242e359fa32f32d0e571c6e918ac39642e9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -276,6 +276,7 @@ public class CraftWorld implements World { + return ret; + } + public int getTileEntityCount() { ++ return net.minecraft.server.MCUtil.ensureMain(() -> { + // We don't use the full world tile entity list, so we must iterate chunks + Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; + int size = 0; +@@ -287,11 +288,13 @@ public class CraftWorld implements World { + size += chunk.blockEntities.size(); + } + return size; ++ }); + } + public int getTickableTileEntityCount() { + return world.tickableBlockEntities.size(); + } + public int getChunkCount() { ++ return net.minecraft.server.MCUtil.ensureMain(() -> { + int ret = 0; + + for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { +@@ -300,7 +303,7 @@ public class CraftWorld implements World { + } + } + +- return ret; ++ return ret; }); + } + public int getPlayerCount() { + return world.players.size(); +@@ -425,6 +428,14 @@ public class CraftWorld implements World { + + @Override + public Chunk[] getLoadedChunks() { ++ // Paper start ++ if (Thread.currentThread() != world.getLevel().thread) { ++ synchronized (world.getChunkSource().chunkMap.visibleChunkMap) { ++ Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; ++ return chunks.values().stream().map(ChunkHolder::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new); ++ } ++ } ++ // Paper end + Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; + return chunks.values().stream().map(ChunkHolder::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new); + } diff --git a/patches/server-remapped/0427-Increase-Light-Queue-Size.patch b/patches/server-remapped/0427-Increase-Light-Queue-Size.patch new file mode 100644 index 0000000000..f5ba659507 --- /dev/null +++ b/patches/server-remapped/0427-Increase-Light-Queue-Size.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 8 Apr 2020 21:24:05 -0400 +Subject: [PATCH] Increase Light Queue Size + +Wiz mentioned that large WorldEdit operations cause light to run on +main thread. The queue was small, set to 5.. this bumps it to 20 +but makes it configurable per-world. + +The main risk of increasing this higher is during shutdown, some +queued light updates may be lost because mojang did not flush the +light engine on shutdown... + +The queue size only puts a cap on max loss, doesn't solve that problem. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1..cd248eb6be663e8be33f2c3c6b06b77b6d5753a4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -620,4 +620,9 @@ public class PaperWorldConfig { + private void zombieVillagerInfectionChance() { + zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); + } ++ ++ public int lightQueueSize = 20; ++ private void lightQueueSize() { ++ lightQueueSize = getInt("light-queue-size", lightQueueSize); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index e33189dc8375a3034910087654607fb531061636..11c6e8ce10c53dcb639145fbda32c5426eb6b3d9 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -775,7 +775,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Thu, 9 Apr 2020 00:09:26 -0400 +Subject: [PATCH] Mid Tick Chunk Tasks - Speed up processing of chunk loads and + generation + +Credit to Spotted for the idea + +A lot of the new chunk system requires constant back and forth the main thread +to handle priority scheduling and ensuring conflicting tasks do not run at the +same time. + +The issue is, these queues are only checked at either: + +A) Sync Chunk Loads +B) End of Tick while sleeping + +This results in generating chunks sitting waiting for a full tick to +complete before it will even start the next unit of work to do. + +Additionally, this also delays loading of chunks until this same timing. + +We will now periodically poll the chunk task queues throughout the tick, +looking for work to do. +We do this in a fair method that considers all worlds, not just the one being +ticked, so that each world can get 1 task procesed each before the next pass. + +In a view distance of 15, chunk loading performance was visually faster on the client. + +Flying at high speed in spectator mode was able to keep up with chunk loading (as long as they are already generated) + +diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java +index be3a62f543a5fec4739c14821fe5a443c1fa3f5b..6bff5317939635b925bb41eb7a67d1fd95715078 100644 +--- a/src/main/java/co/aikar/timings/MinecraftTimings.java ++++ b/src/main/java/co/aikar/timings/MinecraftTimings.java +@@ -17,6 +17,7 @@ import java.util.Map; + public final class MinecraftTimings { + + public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); ++ public static final Timing midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks"); + public static final Timing playerListTimer = Timings.ofSafe("Player List"); + public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); + public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index da93d38fe63035e4ff198ada84a4431f52d97c01..ddbc8cb712c50038922eded75dd6ca85fe851078 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -410,4 +410,9 @@ public class PaperConfig { + log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); + } + } ++ ++ public static int midTickChunkTasks = 1000; ++ private static void midTickChunkTasks() { ++ midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b174dee62 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1055,6 +1055,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { ++ midTickLoadChunks(); // will only do loads since we are still considered !canSleepForTick + return !this.canOversleep(); + }); + isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); +@@ -1318,13 +1337,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Paper - safe iterator incase chunk loads, also no wrapping ++ final int[] chunksTicked = {0}; this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + + if (optional.isPresent()) { +@@ -806,6 +809,7 @@ public class ServerChunkCache extends ChunkSource { + //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper + this.level.tickChunk(chunk, k); + //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper ++ if (chunksTicked[0]++ % 10 == 0) this.level.getServer().midTickLoadChunks(); // Paper + } + } + } +@@ -963,6 +967,41 @@ public class ServerChunkCache extends ChunkSource { + super.doRunTask(task); + } + ++ // Paper start ++ private long lastMidTickChunkTask = 0; ++ public boolean pollChunkLoadTasks() { ++ if (com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ServerChunkCache.this.level.asyncChunkTaskManager.pollNextChunkTask()) { ++ try { ++ ServerChunkCache.this.runDistanceManagerUpdates(); ++ } finally { ++ // from below: process pending Chunk loadCallback() and unloadCallback() after each run task ++ chunkMap.callbackExecutor.run(); ++ } ++ return true; ++ } ++ return false; ++ } ++ public void midTickLoadChunks() { ++ MinecraftServer server = ServerChunkCache.this.level.getServer(); ++ // always try to load chunks, restrain generation/other updates only. don't count these towards tick count ++ //noinspection StatementWithEmptyBody ++ while (pollChunkLoadTasks()) {} ++ ++ if (System.nanoTime() - lastMidTickChunkTask < 200000) { ++ return; ++ } ++ ++ for (;server.midTickChunksTasksRan < com.destroystokyo.paper.PaperConfig.midTickChunkTasks && server.haveTime();) { ++ if (this.pollTask()) { ++ server.midTickChunksTasksRan++; ++ lastMidTickChunkTask = System.nanoTime(); ++ } else { ++ break; ++ } ++ } ++ } ++ // Paper end ++ + @Override + protected boolean pollTask() { + // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 5127bce423a83711cea94e387b3ae7866215ded5..4e75cc5e52a5295e32ccadb371702a405bb518bb 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -565,6 +565,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + timings.scheduledBlocks.stopTiming(); // Paper + ++ this.getServer().midTickLoadChunks(); // Paper + gameprofilerfiller.popPush("raid"); + this.timings.raids.startTiming(); // Paper - timings + this.raids.tick(); +@@ -573,6 +574,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + timings.doSounds.startTiming(); // Spigot + this.runBlockEvents(); + timings.doSounds.stopTiming(); // Spigot ++ this.getServer().midTickLoadChunks(); // Paper + this.handlingTick = false; + gameprofilerfiller.popPush("entities"); + boolean flag3 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players +@@ -639,6 +641,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + timings.entityTick.stopTiming(); // Spigot + + this.tickingEntities = false; ++ this.getServer().midTickLoadChunks(); // Paper + + Entity entity2; + +@@ -648,6 +651,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + timings.tickEntities.stopTiming(); // Spigot ++ this.getServer().midTickLoadChunks(); // Paper + this.tickBlockEntities(); + } + diff --git a/patches/server-remapped/0429-Don-t-move-existing-players-to-world-spawn.patch b/patches/server-remapped/0429-Don-t-move-existing-players-to-world-spawn.patch new file mode 100644 index 0000000000..02f8b575b0 --- /dev/null +++ b/patches/server-remapped/0429-Don-t-move-existing-players-to-world-spawn.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 9 Apr 2020 21:20:33 -0400 +Subject: [PATCH] Don't move existing players to world spawn + +This can cause a nasty server lag the spawn chunks are not kept loaded +or they aren't finished loading yet, or if the world spawn radius is +larger than the keep loaded range. + +By skipping this, we avoid potential for a large spike on server start. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 286b75a27103a084a9f9d79a90716ebcad65d813..162b1a8c6ab57aafa4f6deefc842755a8e14208e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -251,7 +251,7 @@ public class ServerPlayer extends Player implements ContainerListener { + this.stats = server.getPlayerList().getStatisticManager(this); + this.advancements = server.getPlayerList().getPlayerAdvancements(this); + this.maxUpStep = 1.0F; +- this.fudgeSpawnLocation(world); ++ //this.c(worldserver); // Paper - don't move to spawn on login, only first join + this.textFilter = server.createTextFilterForPlayer(this); + + this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper +@@ -303,6 +303,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + // CraftBukkit end + ++ public final void moveToSpawn(ServerLevel worldserver) { fudgeSpawnLocation(worldserver); } // Paper - OBFHELPER + private void fudgeSpawnLocation(ServerLevel world) { + BlockPos blockposition = world.getSpawn(); + +@@ -480,7 +481,7 @@ public class ServerPlayer extends Player implements ContainerListener { + position = Vec3.atCenterOf(((ServerLevel) world).getSpawn()); + } + this.level = world; +- this.setPos(position.x(), position.y(), position.z()); ++ this.setPosRaw(position.x(), position.y(), position.z()); // Paper - don't register to chunks yet + } + this.gameMode.setLevel((ServerLevel) world); + } +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 86c5549196a4e9011c5240e7918b466c299be4a3..30666fca36b683158ff60302684b5093f5536e24 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -204,6 +204,8 @@ public abstract class PlayerList { + worldserver1 = worldserver; + } + ++ if (nbttagcompound == null) player.moveToSpawn(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are.... ++ + player.setLevel(worldserver1); + player.gameMode.setLevel((ServerLevel) player.level); + String s1 = "local"; diff --git a/patches/server-remapped/0430-Add-tick-times-API-and-mspt-command.patch b/patches/server-remapped/0430-Add-tick-times-API-and-mspt-command.patch new file mode 100644 index 0000000000..0f2cf4005e --- /dev/null +++ b/patches/server-remapped/0430-Add-tick-times-API-and-mspt-command.patch @@ -0,0 +1,169 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 5 Apr 2020 22:23:14 -0500 +Subject: [PATCH] Add tick times API and /mspt command + + +diff --git a/src/main/java/com/destroystokyo/paper/MSPTCommand.java b/src/main/java/com/destroystokyo/paper/MSPTCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d0211d4f39f9d6af1d751ac66342b42cc6d7ba6d +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/MSPTCommand.java +@@ -0,0 +1,64 @@ ++package com.destroystokyo.paper; ++ ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.ChatColor; ++import org.bukkit.Location; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++ ++import java.text.DecimalFormat; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.List; ++ ++public class MSPTCommand extends Command { ++ private static final DecimalFormat DF = new DecimalFormat("########0.0"); ++ ++ public MSPTCommand(String name) { ++ super(name); ++ this.description = "View server tick times"; ++ this.usageMessage = "/mspt"; ++ this.setPermission("bukkit.command.mspt"); ++ } ++ ++ @Override ++ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { ++ return Collections.emptyList(); ++ } ++ ++ @Override ++ public boolean execute(CommandSender sender, String commandLabel, String[] args) { ++ if (!testPermission(sender)) return true; ++ ++ MinecraftServer server = MinecraftServer.getServer(); ++ ++ List times = new ArrayList<>(); ++ times.addAll(eval(server.tickTimes5s.getTimes())); ++ times.addAll(eval(server.tickTimes10s.getTimes())); ++ times.addAll(eval(server.tickTimes60s.getTimes())); ++ ++ sender.sendMessage("§6Server tick times §e(§7avg§e/§7min§e/§7max§e)§6 from last 5s§7,§6 10s§7,§6 1m§e:"); ++ sender.sendMessage(String.format("§6◴ %s§7/%s§7/%s§e, %s§7/%s§7/%s§e, %s§7/%s§7/%s", times.toArray())); ++ return true; ++ } ++ ++ private static List eval(long[] times) { ++ long min = Integer.MAX_VALUE; ++ long max = 0L; ++ long total = 0L; ++ for (long value : times) { ++ if (value > 0L && value < min) min = value; ++ if (value > max) max = value; ++ total += value; ++ } ++ double avgD = ((double) total / (double) times.length) * 1.0E-6D; ++ double minD = ((double) min) * 1.0E-6D; ++ double maxD = ((double) max) * 1.0E-6D; ++ return Arrays.asList(getColor(avgD), getColor(minD), getColor(maxD)); ++ } ++ ++ private static String getColor(double avg) { ++ return ChatColor.COLOR_CHAR + (avg >= 50 ? "c" : avg >= 40 ? "e" : "a") + DF.format(avg); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index ddbc8cb712c50038922eded75dd6ca85fe851078..78271b400c79578d043b20a5389a37b1bef9a70d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -69,6 +69,7 @@ public class PaperConfig { + + commands = new HashMap(); + commands.put("paper", new PaperCommand("paper")); ++ commands.put("mspt", new MSPTCommand("mspt")); + + version = getInt("config-version", 20); + set("config-version", 20); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 087f31ac0cc7816b1cbeffc45be6927b174dee62..99ee9de92264381a064066bc22bb66b4b2852a2e 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -217,6 +217,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Fri, 10 Apr 2020 21:24:12 -0400 +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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 4fa49b6bb26456d485f7f9193af560cb379e36f0..3f35e93b42efd03ff1002f09962fe3da51fb4c3f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2378,5 +2378,10 @@ public final class CraftServer implements Server { + public int getCurrentTick() { + return net.minecraft.server.MinecraftServer.currentTick; + } ++ ++ @Override ++ public boolean isStopping() { ++ return net.minecraft.server.MinecraftServer.getServer().hasStopped(); ++ } + // Paper end + } diff --git a/patches/server-remapped/0432-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server-remapped/0432-Add-Raw-Byte-ItemStack-Serialization.patch new file mode 100644 index 0000000000..4f867cd88c --- /dev/null +++ b/patches/server-remapped/0432-Add-Raw-Byte-ItemStack-Serialization.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Thu, 30 Apr 2020 16:56:54 +0200 +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/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java +index b3838e709c1581c25da7738c9a03a827761845b1..05ace1d046e32a261e67bff5afc18c2d32e1a8aa 100644 +--- a/src/main/java/net/minecraft/nbt/NbtIo.java ++++ b/src/main/java/net/minecraft/nbt/NbtIo.java +@@ -51,6 +51,7 @@ public class NbtIo { + return nbttagcompound; + } + ++ public static CompoundTag readNBT(InputStream inputstream) throws IOException { return readCompressed(inputstream); } // Paper - OBFHELPER + public static CompoundTag readCompressed(InputStream stream) throws IOException { + DataInputStream datainputstream = new DataInputStream(new BufferedInputStream(new GZIPInputStream(stream))); + Throwable throwable = null; +@@ -106,6 +107,7 @@ public class NbtIo { + + } + ++ public static void writeNBT(CompoundTag nbttagcompound, OutputStream outputstream) throws IOException { writeCompressed(nbttagcompound, outputstream); } // Paper - OBFHELPER + public static void writeCompressed(CompoundTag tag, OutputStream stream) throws IOException { + DataOutputStream dataoutputstream = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(stream))); + Throwable throwable = null; +diff --git a/src/main/java/net/minecraft/util/datafix/DataFixers.java b/src/main/java/net/minecraft/util/datafix/DataFixers.java +index 950a4b67f9091af551ec1036ebeb943e3b335e91..dc4e2fc26e1bc2c545f955d30c052bb86e3ef614 100644 +--- a/src/main/java/net/minecraft/util/datafix/DataFixers.java ++++ b/src/main/java/net/minecraft/util/datafix/DataFixers.java +@@ -78,6 +78,7 @@ public class DataFixers { + return datafixerbuilder.build(Util.bootstrapExecutor()); + } + ++ public static DataFixer getDataFixer() { return getDataFixer(); } // Paper - OBFHELPER + public static DataFixer getDataFixer() { + return DataFixers.DATA_FIXER; + } +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index ac996d581925c8f92832009945c766962e5b51c5..458cdfbeac9d757c9721acd4557a548affa0ede1 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -196,6 +196,7 @@ public final class ItemStack { + this.updateEmptyCacheFlag(); + } + ++ public static ItemStack fromCompound(CompoundTag nbttagcompound) { return of(nbttagcompound); } // Paper - OBFHELPER + public static ItemStack of(CompoundTag tag) { + try { + return new ItemStack(tag); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 86b319337fc41a09dd45df466df60cadaed1343f..a5a5038a84434e69fda8f6b41d2f00b4989e25ae 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -378,6 +378,46 @@ public final class CraftMagicNumbers implements UnsafeValues { + public boolean isSupportedApiVersion(String apiVersion) { + return apiVersion != null && SUPPORTED_API.contains(apiVersion); + } ++ ++ @Override ++ public byte[] serializeItem(ItemStack item) { ++ Preconditions.checkNotNull(item, "null cannot be serialized"); ++ Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized"); ++ ++ java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); ++ CompoundTag compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).getHandle() : CraftItemStack.asNMSCopy(item)).save(new CompoundTag()); ++ compound.putInt("DataVersion", getDataVersion()); ++ try { ++ net.minecraft.nbt.NbtIo.writeNBT( ++ compound, ++ outputStream ++ ); ++ } catch (IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return outputStream.toByteArray(); ++ } ++ ++ @Override ++ public ItemStack deserializeItem(byte[] data) { ++ Preconditions.checkNotNull(data, "null cannot be deserialized"); ++ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing"); ++ ++ try { ++ CompoundTag compound = net.minecraft.nbt.NbtIo.readNBT( ++ new java.io.ByteArrayInputStream(data) ++ ); ++ int dataVersion = compound.getInt("DataVersion"); ++ ++ Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); ++ Dynamic converted = DataFixers.getDataFixer().update(References.ITEM_STACK, new Dynamic(NbtOps.INSTANCE, compound), dataVersion, getDataVersion()); ++ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.fromCompound((CompoundTag) converted.getValue())); ++ } catch (IOException ex) { ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(ex); ++ throw new RuntimeException(); ++ } ++ } + // Paper end + + /** diff --git a/patches/server-remapped/0433-Remove-streams-from-Mob-AI-System.patch b/patches/server-remapped/0433-Remove-streams-from-Mob-AI-System.patch new file mode 100644 index 0000000000..019eef698e --- /dev/null +++ b/patches/server-remapped/0433-Remove-streams-from-Mob-AI-System.patch @@ -0,0 +1,253 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 17:53:29 -0700 +Subject: [PATCH] Remove streams from Mob AI System + +The streams hurt performance and allocate tons of garbage, so +replace them with the standard iterator. + +Also optimise the stream.anyMatch statement to move to a bitset +where we can replace the call with a single bitwise operation. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +index 558dd72c47930f6993952467f83b5a54ead95d92..acc6306d659cd65a043d12cd42dcbaf55aaf5250 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +@@ -1,10 +1,12 @@ + package net.minecraft.world.entity.ai.goal; + ++import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector + import java.util.EnumSet; + + public abstract class Goal { + +- private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); ++ private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. ++ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector + + public Goal() {} + +@@ -28,16 +30,20 @@ public abstract class Goal { + public void tick() {} + + public void setFlags(EnumSet controls) { +- this.flags.clear(); +- this.flags.addAll(controls); ++ // Paper start - remove streams from pathfindergoalselector ++ this.goalTypes.clear(); ++ this.goalTypes.addAllUnchecked(controls); ++ // Paper end - remove streams from pathfindergoalselector + } + + public String toString() { + return this.getClass().getSimpleName(); + } + +- public EnumSet getFlags() { +- return this.flags; ++ // Paper start - remove streams from pathfindergoalselector ++ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { ++ return this.goalTypes; ++ // Paper end - remove streams from pathfindergoalselector + } + + public static enum Flag { +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +index 9bd2ee05a0de6678ad8933a8ffbe0ae66bd073b4..5da2d780c17522e07c733a5e23b17ec760c7b342 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +@@ -1,8 +1,10 @@ + package net.minecraft.world.entity.ai.goal; + ++import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector + import com.google.common.collect.Sets; + import java.util.EnumMap; + import java.util.EnumSet; ++import java.util.Iterator; // Paper - remove streams from pathfindergoalselector + import java.util.Map; + import java.util.Set; + import java.util.function.Supplier; +@@ -28,7 +30,8 @@ public class GoalSelector { + private final Map lockedFlags = new EnumMap(Goal.Flag.class); + private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER + private final Supplier profiler; +- private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); ++ private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. ++ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector + private int newGoalRate = 3;private int getTickRate() { return newGoalRate; } // Paper - OBFHELPER + private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO + +@@ -56,35 +59,38 @@ public class GoalSelector { + // Paper end + + public void removeGoal(Goal goal) { +- this.availableGoals.stream().filter((pathfindergoalwrapped) -> { +- return pathfindergoalwrapped.getGoal() == goal; +- }).filter(WrappedGoal::isRunning).forEach(WrappedGoal::stop); +- this.availableGoals.removeIf((pathfindergoalwrapped) -> { +- return pathfindergoalwrapped.getGoal() == goal; +- }); ++ // Paper start - remove streams from pathfindergoalselector ++ for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal goalWrapped = iterator.next(); ++ if (goalWrapped.getGoal() != goal) { ++ continue; ++ } ++ if (goalWrapped.isRunning()) { ++ goalWrapped.stop(); ++ } ++ iterator.remove(); ++ } ++ // Paper end - remove streams from pathfindergoalselector + } + ++ private static final Goal.Flag[] PATHFINDER_GOAL_TYPES = Goal.Flag.values(); // Paper - remove streams from pathfindergoalselector ++ + public void tick() { + ProfilerFiller gameprofilerfiller = (ProfilerFiller) this.profiler.get(); + + gameprofilerfiller.push("goalCleanup"); +- this.getRunningGoals().filter((pathfindergoalwrapped) -> { +- boolean flag; +- +- if (pathfindergoalwrapped.isRunning()) { +- Stream stream = pathfindergoalwrapped.getFlags().stream(); +- EnumSet enumset = this.disabledFlags; +- +- this.disabledFlags.getClass(); +- if (!stream.anyMatch(enumset::contains) && pathfindergoalwrapped.canContinueToUse()) { +- flag = false; +- return flag; +- } ++ // Paper start - remove streams from pathfindergoalselector ++ for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal wrappedGoal = iterator.next(); ++ if (!wrappedGoal.isRunning()) { ++ continue; + } +- +- flag = true; +- return flag; +- }).forEach(Goal::stop); ++ if (!this.goalTypes.hasCommonElements(wrappedGoal.getGoalTypes()) && wrappedGoal.canContinueToUse()) { ++ continue; ++ } ++ wrappedGoal.stop(); ++ } ++ // Paper end - remove streams from pathfindergoalselector + this.lockedFlags.forEach((pathfindergoal_type, pathfindergoalwrapped) -> { + if (!pathfindergoalwrapped.isRunning()) { + this.lockedFlags.remove(pathfindergoal_type); +@@ -93,30 +99,58 @@ public class GoalSelector { + }); + gameprofilerfiller.pop(); + gameprofilerfiller.push("goalUpdate"); +- this.availableGoals.stream().filter((pathfindergoalwrapped) -> { +- return !pathfindergoalwrapped.isRunning(); +- }).filter((pathfindergoalwrapped) -> { +- Stream stream = pathfindergoalwrapped.getFlags().stream(); +- EnumSet enumset = this.disabledFlags; +- +- this.disabledFlags.getClass(); +- return stream.noneMatch(enumset::contains); +- }).filter((pathfindergoalwrapped) -> { +- return pathfindergoalwrapped.getFlags().stream().allMatch((pathfindergoal_type) -> { +- return ((WrappedGoal) this.lockedFlags.getOrDefault(pathfindergoal_type, GoalSelector.NO_GOAL)).canBeReplacedBy(pathfindergoalwrapped); +- }); +- }).filter(WrappedGoal::canUse).forEach((pathfindergoalwrapped) -> { +- pathfindergoalwrapped.getFlags().forEach((pathfindergoal_type) -> { +- WrappedGoal pathfindergoalwrapped1 = (WrappedGoal) this.lockedFlags.getOrDefault(pathfindergoal_type, GoalSelector.NO_GOAL); +- +- pathfindergoalwrapped1.stop(); +- this.lockedFlags.put(pathfindergoal_type, pathfindergoalwrapped); +- }); +- pathfindergoalwrapped.start(); +- }); ++ // Paper start - remove streams from pathfindergoalselector ++ goal_update_loop: for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal wrappedGoal = iterator.next(); ++ if (wrappedGoal.isRunning()) { ++ continue; ++ } ++ ++ OptimizedSmallEnumSet wrappedGoalSet = wrappedGoal.getGoalTypes(); ++ ++ if (this.goalTypes.hasCommonElements(wrappedGoalSet)) { ++ continue; ++ } ++ ++ long iterator1 = wrappedGoalSet.getBackingSet(); ++ int wrappedGoalSize = wrappedGoalSet.size(); ++ for (int i = 0; i < wrappedGoalSize; ++i) { ++ Goal.Flag type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; ++ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); ++ WrappedGoal wrapped = this.lockedFlags.getOrDefault(type, GoalSelector.NO_GOAL); ++ if (!wrapped.canBeReplacedBy(wrappedGoal)) { ++ continue goal_update_loop; ++ } ++ } ++ ++ if (!wrappedGoal.canUse()) { ++ continue; ++ } ++ ++ iterator1 = wrappedGoalSet.getBackingSet(); ++ wrappedGoalSize = wrappedGoalSet.size(); ++ for (int i = 0; i < wrappedGoalSize; ++i) { ++ Goal.Flag type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; ++ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); ++ WrappedGoal wrapped = this.lockedFlags.getOrDefault(type, GoalSelector.NO_GOAL); ++ ++ wrapped.stop(); ++ this.lockedFlags.put(type, wrappedGoal); ++ } ++ ++ wrappedGoal.start(); ++ } ++ // Paper end - remove streams from pathfindergoalselector + gameprofilerfiller.pop(); + gameprofilerfiller.push("goalTick"); +- this.getRunningGoals().forEach(WrappedGoal::tick); ++ // Paper start - remove streams from pathfindergoalselector ++ for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal wrappedGoal = iterator.next(); ++ if (wrappedGoal.isRunning()) { ++ wrappedGoal.tick(); ++ } ++ } ++ // Paper end - remove streams from pathfindergoalselector + gameprofilerfiller.pop(); + } + +@@ -125,11 +159,11 @@ public class GoalSelector { + } + + public void disableControlFlag(Goal.Flag control) { +- this.disabledFlags.add(control); ++ this.goalTypes.addUnchecked(control); // Paper - remove streams from pathfindergoalselector + } + + public void enableControlFlag(Goal.Flag control) { +- this.disabledFlags.remove(control); ++ this.goalTypes.removeUnchecked(control); // Paper - remove streams from pathfindergoalselector + } + + public void setControlFlag(Goal.Flag control, boolean enabled) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +index 81b4618a7979ee8dd25e1749c084de9262318ef4..984146b2b6eb3e498433b1c4971397848166d9c9 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +@@ -59,9 +59,10 @@ public class WrappedGoal extends Goal { + this.goal.setFlags(controls); + } + +- @Override +- public EnumSet getFlags() { +- return this.goal.getFlags(); ++ // Paper start - remove streams from pathfindergoalselector ++ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { ++ return this.goal.getGoalTypes(); ++ // Paper end - remove streams from pathfindergoalselector + } + + public boolean isRunning() { return this.isRunning(); } // Paper - OBFHELPER diff --git a/patches/server-remapped/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch b/patches/server-remapped/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch new file mode 100644 index 0000000000..9fb51d1e35 --- /dev/null +++ b/patches/server-remapped/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 11 Apr 2020 21:23:42 -0400 +Subject: [PATCH] Delay unsafe actions until after entity ticking is done + +This will help prevent many cases of unregistering entities during entity ticking + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 4e75cc5e52a5295e32ccadb371702a405bb518bb..b9978d296b83e73d3395b8254c0e8ccd9b36d0fa 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -172,6 +172,16 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final List players = Lists.newArrayList(); // Paper - private -> public + public final ServerChunkCache chunkSource; // Paper - public + boolean tickingEntities; ++ // Paper start ++ List afterEntityTickingTasks = Lists.newArrayList(); ++ public void doIfNotEntityTicking(java.lang.Runnable run) { ++ if (tickingEntities) { ++ afterEntityTickingTasks.add(run); ++ } else { ++ run.run(); ++ } ++ } ++ // Paper end + private final MinecraftServer server; + public final PrimaryLevelData worldDataServer; // CraftBukkit - type + public boolean noSave; +@@ -641,6 +651,16 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + timings.entityTick.stopTiming(); // Spigot + + this.tickingEntities = false; ++ // Paper start ++ for (java.lang.Runnable run : this.afterEntityTickingTasks) { ++ try { ++ run.run(); ++ } catch (Exception e) { ++ LOGGER.error("Error in After Entity Ticking Task", e); ++ } ++ } ++ this.afterEntityTickingTasks.clear(); ++ // Paper end + this.getServer().midTickLoadChunks(); // Paper + + Entity entity2; diff --git a/patches/server-remapped/0435-Async-command-map-building.patch b/patches/server-remapped/0435-Async-command-map-building.patch new file mode 100644 index 0000000000..87f32eb782 --- /dev/null +++ b/patches/server-remapped/0435-Async-command-map-building.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Callahan +Date: Wed, 8 Apr 2020 02:42:14 -0500 +Subject: [PATCH] Async command map building + + +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index 44f2e8a3741afc0e3c3bca3b0864e37ecf83e5d4..8154d9327c5411bbfea3bfa4d99d57feab764664 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -29,6 +29,7 @@ import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.game.ClientboundCommandsPacket; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.commands.AdvancementCommands; + import net.minecraft.server.commands.AttributeCommand; + import net.minecraft.server.commands.BanIpCommands; +@@ -328,25 +329,40 @@ public class Commands { + if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot + // CraftBukkit start + // Register Vanilla commands into builtRoot as before ++ // Paper start - Async command map building ++ java.util.concurrent.ForkJoinPool.commonPool().execute(() -> { ++ sendAsync(player); ++ }); ++ } ++ ++ private void sendAsync(ServerPlayer entityplayer) { ++ // Paper end - Async command map building + Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues + RootCommandNode vanillaRoot = new RootCommandNode(); + +- RootCommandNode vanilla = player.server.vanillaCommandDispatcher.getDispatcher().getRoot(); ++ RootCommandNode vanilla = entityplayer.server.vanillaCommandDispatcher.getDispatcher().getRoot(); + map.put(vanilla, vanillaRoot); +- this.fillUsableCommands(vanilla, vanillaRoot, player.createCommandSourceStack(), (Map) map); ++ this.fillUsableCommands(vanilla, vanillaRoot, entityplayer.createCommandSourceStack(), (Map) map); + + // Now build the global commands in a second pass + RootCommandNode rootcommandnode = new RootCommandNode(); + + map.put(this.dispatcher.getRoot(), rootcommandnode); +- this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, player.createCommandSourceStack(), (Map) map); ++ this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, entityplayer.createCommandSourceStack(), (Map) map); + + Collection bukkit = new LinkedHashSet<>(); + for (CommandNode node : rootcommandnode.getChildren()) { + bukkit.add(node.getName()); + } ++ // Paper start - Async command map building ++ MinecraftServer.getServer().execute(() -> { ++ runSync(entityplayer, bukkit, rootcommandnode); ++ }); ++ } + +- PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit)); ++ private void runSync(ServerPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { ++ // Paper end - Async command map building ++ PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); + event.getPlayer().getServer().getPluginManager().callEvent(event); + + // Remove labels that were removed during the event +@@ -356,7 +372,7 @@ public class Commands { + } + } + // CraftBukkit end +- player.connection.send(new ClientboundCommandsPacket(rootcommandnode)); ++ entityplayer.connection.send(new ClientboundCommandsPacket(rootcommandnode)); + } + + private void fillUsableCommands(CommandNode tree, CommandNode result, CommandSourceStack source, Map, CommandNode> resultNodes) { diff --git a/patches/server-remapped/0436-Improved-Watchdog-Support.patch b/patches/server-remapped/0436-Improved-Watchdog-Support.patch new file mode 100644 index 0000000000..928b62d524 --- /dev/null +++ b/patches/server-remapped/0436-Improved-Watchdog-Support.patch @@ -0,0 +1,608 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 12 Apr 2020 15:50:48 -0400 +Subject: [PATCH] Improved Watchdog Support + +Forced Watchdog Crash support and Improve Async Shutdown + +If the request to shut down the server is received while we are in +a watchdog hang, immediately treat it as a crash and begin the shutdown +process. Shutdown process is now improved to also shutdown cleanly when +not using restart scripts either. + +If a server is deadlocked, a server owner can send SIGUP (or any other signal +the JVM understands to shut down as it currently does) and the watchdog +will no longer need to wait until the full timeout, allowing you to trigger +a close process and try to shut the server down gracefully, saving player and +world data. + +Previously there was no way to trigger this outside of waiting for a full watchdog +timeout, which may be set to a really long time... + +Additionally, fix everything to do with shutting the server down asynchronously. + +Previously, nearly everything about the process was fragile and unsafe. Main might +not have actually been frozen, and might still be manipulating state. + +Or, some reuest might ask main to do something in the shutdown but main is dead. + +Or worse, other things might start closing down items such as the Console or Thread Pool +before we are fully shutdown. + +This change tries to resolve all of these issues by moving everything into the stop +method and guaranteeing only one thread is stopping the server. + +We then issue Thread Death to the main thread of another thread initiates the stop process. +We have to ensure Thread Death propagates correctly though to stop main completely. + +This is to ensure that if main isn't truely stuck, it's not manipulating state we are trying to save. + +This also moves all plugins who register "delayed init" tasks to occur just before "Done" so they +are properly accounted for and wont trip watchdog on init. + +diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java +index 0b9e689d57705965721b5c55bc45d36657f360e4..dee00aac05f1acf050f05d4db557a08dd0f301c8 100644 +--- a/src/main/java/com/destroystokyo/paper/Metrics.java ++++ b/src/main/java/com/destroystokyo/paper/Metrics.java +@@ -92,7 +92,12 @@ public class Metrics { + * Starts the Scheduler which submits our data every 30 minutes. + */ + private void startSubmitting() { +- final Runnable submitTask = this::submitData; ++ final Runnable submitTask = () -> { ++ if (MinecraftServer.getServer().hasStopped()) { ++ return; ++ } ++ submitData(); ++ }; + + // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the + // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. +diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java +index 4008fbe506e74f2c463dc7b12f5dd0f3b6fc342d..766ab2fe536a2acccaec28e922ccf8993b0790dc 100644 +--- a/src/main/java/net/minecraft/CrashReport.java ++++ b/src/main/java/net/minecraft/CrashReport.java +@@ -257,6 +257,7 @@ public class CrashReport { + } + + public static CrashReport forThrowable(Throwable cause, String title) { ++ if (cause instanceof ThreadDeath) com.destroystokyo.paper.util.SneakyThrow.sneaky(cause); // Paper + while (cause instanceof CompletionException && cause.getCause() != null) { + cause = cause.getCause(); + } +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index c2f747226f10479c826849af898538610a2dd659..83f9f97586f8c0e9d228923e4fec6f121a6702e2 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -129,6 +129,7 @@ public class Util { + return Util.IO_POOL; + } + ++ public static void shutdownServerThreadPool() { shutdownExecutors(); } // Paper - OBFHELPER + public static void shutdownExecutors() { + shutdownExecutor(Util.BACKGROUND_EXECUTOR); + shutdownExecutor(Util.IO_POOL); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 99ee9de92264381a064066bc22bb66b4b2852a2e..e5ad635a480d32e7a10ee92c65cfc18a98beafad 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -269,7 +269,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) { + AtomicReference atomicreference = new AtomicReference(); + Thread thread = new Thread(() -> { +@@ -851,6 +854,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { ++ world.tickingEntities = false; ++ }); ++ } ++ // Paper end + // CraftBukkit end + MinecraftServer.LOGGER.info("Stopping server"); + MinecraftTimings.stopServer(); // Paper +@@ -930,7 +951,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop {}; ++ } ++ // Paper end + return new TickTask(this.tickCount, runnable); + } + +@@ -1421,6 +1478,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { + CompletableFuture completablefuture; +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index b9978d296b83e73d3395b8254c0e8ccd9b36d0fa..bf4e50cd1d561456c033cda2d5c5487c5e3fe1eb 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -171,7 +171,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + private final Queue toAddAfterTick = Queues.newArrayDeque(); + public final List players = Lists.newArrayList(); // Paper - private -> public + public final ServerChunkCache chunkSource; // Paper - public +- boolean tickingEntities; ++ public boolean tickingEntities; // Paper - expose for watchdog + // Paper start + List afterEntityTickingTasks = Lists.newArrayList(); + public void doIfNotEntityTicking(java.lang.Runnable run) { +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 30666fca36b683158ff60302684b5093f5536e24..984ac19dcab446531c816e365c7c149e2c49d567 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -503,7 +503,7 @@ public abstract class PlayerList { + cserver.getPluginManager().callEvent(playerQuitEvent); + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + +- entityplayer.doTick(); // SPIGOT-924 ++ if (server.isSameThread()) entityplayer.doTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) + // CraftBukkit end + + // Paper start - Remove from collideRule team if needed +diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +index a5ce61be7d6e85ac289730d9671e66a7190529f9..add18ba4833686ff51fbb280b0a5759f142b3f91 100644 +--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java ++++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +@@ -135,6 +135,7 @@ public abstract class BlockableEventLoop implements Processo + try { + task.run(); + } catch (Exception exception) { ++ if (exception.getCause() instanceof ThreadDeath) throw exception; // Paper + BlockableEventLoop.LOGGER.fatal("Error executing task on {}", this.name(), exception); + } + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 632f32405053fbcff2fd26fa99f98c6add9f9dc7..5860e7866724abd35bde2a5710d9c92799e5de67 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -858,6 +858,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + gameprofilerfiller.pop(); + } catch (Throwable throwable) { ++ if (throwable instanceof ThreadDeath) throw throwable; // Paper + // Paper start - Prevent tile entity and entity crashes + String msg = "TileEntity threw exception at " + tileentity.getLevel().getWorld().getName() + ":" + tileentity.getBlockPos().getX() + "," + tileentity.getBlockPos().getY() + "," + tileentity.getBlockPos().getZ(); + System.err.println(msg); +@@ -932,6 +933,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + try { + tickConsumer.accept(entity); + } catch (Throwable throwable) { ++ if (throwable instanceof ThreadDeath) throw throwable; // Paper + // Paper start - Prevent tile entity and entity crashes + String msg = "Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ(); + System.err.println(msg); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 3f35e93b42efd03ff1002f09962fe3da51fb4c3f..43c37e660a8a7f9d326ad38e66f9aa7c53c7b87c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1839,7 +1839,7 @@ public final class CraftServer implements Server { + + @Override + public boolean isPrimaryThread() { +- return Thread.currentThread().equals(console.serverThread); // Paper - Fix issues with detecting main thread properly ++ return Thread.currentThread().equals(console.serverThread) || Thread.currentThread().equals(net.minecraft.server.MinecraftServer.getServer().shutdownThread); // Paper - Fix issues with detecting main thread properly, the only time Watchdog will be used is during a crash shutdown which is a "try our best" scenario + } + + // Paper start +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index c519ceca6f7788ca7c5d74ad1001dbc09f62681c..c288b89bf5a22269823ba1d18af217032d7c6a36 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -12,6 +12,8 @@ import java.util.logging.Level; + import java.util.logging.Logger; + import joptsimple.OptionParser; + import joptsimple.OptionSet; ++import net.minecraft.util.ExceptionCollector; ++import net.minecraft.world.level.lighting.LayerLightEventListener; + import net.minecrell.terminalconsole.TerminalConsoleAppender; // Paper + + public class Main { +@@ -156,6 +158,36 @@ public class Main { + + OptionSet options = null; + ++ // Paper start - preload logger classes to avoid plugins mixing versions ++ tryPreloadClass("com.destroystokyo.paper.log.LogFullPolicy"); ++ tryPreloadClass("org.apache.logging.log4j.core.Core"); ++ tryPreloadClass("org.apache.logging.log4j.core.Appender"); ++ tryPreloadClass("org.apache.logging.log4j.core.ContextDataInjector"); ++ tryPreloadClass("org.apache.logging.log4j.core.Filter"); ++ tryPreloadClass("org.apache.logging.log4j.core.ErrorHandler"); ++ tryPreloadClass("org.apache.logging.log4j.core.LogEvent"); ++ tryPreloadClass("org.apache.logging.log4j.core.Logger"); ++ tryPreloadClass("org.apache.logging.log4j.core.LoggerContext"); ++ tryPreloadClass("org.apache.logging.log4j.core.LogEventListener"); ++ tryPreloadClass("org.apache.logging.log4j.core.AbstractLogEvent"); ++ tryPreloadClass("org.apache.logging.log4j.message.AsynchronouslyFormattable"); ++ tryPreloadClass("org.apache.logging.log4j.message.FormattedMessage"); ++ tryPreloadClass("org.apache.logging.log4j.message.ParameterizedMessage"); ++ tryPreloadClass("org.apache.logging.log4j.message.Message"); ++ tryPreloadClass("org.apache.logging.log4j.message.MessageFactory"); ++ tryPreloadClass("org.apache.logging.log4j.message.TimestampMessage"); ++ tryPreloadClass("org.apache.logging.log4j.message.SimpleMessage"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.AsyncLogger"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.AsyncLoggerContext"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.AsyncQueueFullPolicy"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.AsyncLoggerDisruptor"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.RingBufferLogEvent"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.DisruptorUtil"); ++ tryPreloadClass("org.apache.logging.log4j.core.async.RingBufferLogEventHandler"); ++ tryPreloadClass("org.apache.logging.log4j.core.impl.ThrowableProxy"); ++ tryPreloadClass("org.apache.logging.log4j.core.impl.ExtendedClassInfo"); ++ tryPreloadClass("org.apache.logging.log4j.core.impl.ExtendedStackTraceElement"); ++ // Paper end + try { + options = parser.parse(args); + } catch (joptsimple.OptionException ex) { +@@ -251,8 +283,64 @@ public class Main { + } catch (Throwable t) { + t.printStackTrace(); + } ++ // Paper start ++ // load some required classes to avoid errors during shutdown if jar is replaced ++ // also to guarantee our version loads over plugins ++ tryPreloadClass("com.destroystokyo.paper.util.SneakyThrow"); ++ tryPreloadClass("com.google.common.collect.Iterators$PeekingImpl"); ++ tryPreloadClass("com.google.common.collect.MapMakerInternalMap$Values"); ++ tryPreloadClass("com.google.common.collect.MapMakerInternalMap$ValueIterator"); ++ tryPreloadClass("com.google.common.collect.MapMakerInternalMap$WriteThroughEntry"); ++ tryPreloadClass("com.google.common.collect.Iterables"); ++ for (int i = 1; i <= 15; i++) { ++ tryPreloadClass("com.google.common.collect.Iterables$" + i, false); ++ } ++ tryPreloadClass("org.apache.commons.lang3.mutable.MutableBoolean"); ++ tryPreloadClass("org.apache.commons.lang3.mutable.MutableInt"); ++ tryPreloadClass("org.jline.terminal.impl.MouseSupport"); ++ tryPreloadClass("org.jline.terminal.impl.MouseSupport$1"); ++ tryPreloadClass("org.jline.terminal.Terminal$MouseTracking"); ++ tryPreloadClass("co.aikar.timings.TimingHistory"); ++ tryPreloadClass("co.aikar.timings.TimingHistory$MinuteReport"); ++ tryPreloadClass("io.netty.channel.AbstractChannelHandlerContext"); ++ tryPreloadClass("io.netty.channel.AbstractChannelHandlerContext$11"); ++ tryPreloadClass("io.netty.channel.AbstractChannelHandlerContext$12"); ++ tryPreloadClass("io.netty.channel.AbstractChannel$AbstractUnsafe$8"); ++ tryPreloadClass("io.netty.util.concurrent.DefaultPromise"); ++ tryPreloadClass("io.netty.util.concurrent.DefaultPromise$1"); ++ tryPreloadClass("io.netty.util.internal.PromiseNotificationUtil"); ++ tryPreloadClass("io.netty.util.internal.SystemPropertyUtil"); ++ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler"); ++ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler$1"); ++ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler$2"); ++ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler$3"); ++ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler$4"); ++ tryPreloadClass("org.slf4j.helpers.MessageFormatter"); ++ tryPreloadClass("org.slf4j.helpers.FormattingTuple"); ++ tryPreloadClass("org.slf4j.helpers.BasicMarker"); ++ tryPreloadClass("org.slf4j.helpers.Util"); ++ tryPreloadClass("com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent"); ++ tryPreloadClass("com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent"); ++ // Minecraft, seen during saving ++ tryPreloadClass(LayerLightEventListener.DummyLightLayerEventListener.class.getName()); ++ tryPreloadClass(LayerLightEventListener.class.getName()); ++ tryPreloadClass(ExceptionCollector.class.getName()); ++ // Paper end ++ } ++ } ++ ++ // Paper start ++ private static void tryPreloadClass(String className) { ++ tryPreloadClass(className, true); ++ } ++ private static void tryPreloadClass(String className, boolean printError) { ++ try { ++ Class.forName(className); ++ } catch (ClassNotFoundException e) { ++ if (printError) System.err.println("An expected class " + className + " was not found for preloading: " + e.getMessage()); + } + } ++ // Paper end + + private static List asList(String... params) { + return Arrays.asList(params); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +index 449e99d1b673870ed6892f6ab2c715a2db35c35d..c7ed6e0f8a989cec97700df2b15198c9c481c549 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +@@ -12,12 +12,27 @@ public class ServerShutdownThread extends Thread { + @Override + public void run() { + try { ++ // Paper start - try to shutdown on main ++ server.safeShutdown(false, false); ++ for (int i = 1000; i > 0 && !server.hasStopped(); i -= 100) { ++ Thread.sleep(100); ++ } ++ if (server.hasStopped()) { ++ while (!server.hasFullyShutdown) Thread.sleep(1000); ++ return; ++ } ++ // Looks stalled, close async + org.spigotmc.AsyncCatcher.enabled = false; // Spigot + org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper ++ server.forceTicks = true; + server.close(); ++ while (!server.hasFullyShutdown) Thread.sleep(1000); ++ } catch (InterruptedException e) { ++ e.printStackTrace(); ++ // Paper end + } finally { + try { +- net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender ++ //net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Move into stop + } catch (Exception e) { + } + } +diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java +index 6dab105cd7cc4340c031c395c0346d4731355d79..6498dc4c6630bfef1a52edf74d8574e5e4876720 100644 +--- a/src/main/java/org/spigotmc/RestartCommand.java ++++ b/src/main/java/org/spigotmc/RestartCommand.java +@@ -139,7 +139,7 @@ public class RestartCommand extends Command + // Paper end + + // Paper start - copied from above and modified to return if the hook registered +- private static boolean addShutdownHook(String restartScript) ++ public static boolean addShutdownHook(String restartScript) + { + String[] split = restartScript.split( " " ); + if ( split.length > 0 && new File( split[0] ).isFile() ) +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 33a66322d253c7562ae5acbdbc6cc87f7d72a9af..26c9adf7af4328ce2d8e08568019c5b438e28b05 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -13,6 +13,7 @@ import org.bukkit.Bukkit; + public class WatchdogThread extends Thread + { + ++ public static final boolean DISABLE_WATCHDOG = Boolean.getBoolean("disable.watchdog"); // Paper + private static WatchdogThread instance; + private long timeoutTime; + private boolean restart; +@@ -41,6 +42,7 @@ public class WatchdogThread extends Thread + { + if ( instance == null ) + { ++ if (timeoutTime <= 0) timeoutTime = 300; // Paper + instance = new WatchdogThread( timeoutTime * 1000L, restart ); + instance.start(); + } else +@@ -71,12 +73,13 @@ public class WatchdogThread extends Thread + // Paper start + Logger log = Bukkit.getServer().getLogger(); + long currentTime = monotonicMillis(); +- if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) ++ MinecraftServer server = MinecraftServer.getServer(); ++ if (lastTick != 0 && timeoutTime > 0 && hasStarted && (!server.isRunning() || (currentTime > lastTick + earlyWarningEvery && !DISABLE_WATCHDOG) )) + { +- boolean isLongTimeout = currentTime > lastTick + timeoutTime; ++ boolean isLongTimeout = currentTime > lastTick + timeoutTime || (!server.isRunning() && !server.hasStopped() && currentTime > lastTick + 1000); + // Don't spam early warning dumps + if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; +- if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... ++ if ( !isLongTimeout && server.hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... + lastEarlyWarning = currentTime; + if (isLongTimeout) { + // Paper end +@@ -118,7 +121,7 @@ public class WatchdogThread extends Thread + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper +- dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); ++ dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // + // Paper start - Only print full dump on long timeouts +@@ -139,9 +142,25 @@ public class WatchdogThread extends Thread + + if ( isLongTimeout ) + { +- if ( restart && !MinecraftServer.getServer().hasStopped() ) ++ if ( !server.hasStopped() ) + { +- RestartCommand.restart(); ++ AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us ++ AsyncCatcher.shuttingDown = true; ++ server.forceTicks = true; ++ if (restart) { ++ RestartCommand.addShutdownHook( SpigotConfig.restartScript ); ++ } ++ // try one last chance to safe shutdown on main incase it 'comes back' ++ server.abnormalExit = true; ++ server.safeShutdown(false, restart); ++ try { ++ Thread.sleep(1000); ++ } catch (InterruptedException e) { ++ e.printStackTrace(); ++ } ++ if (!server.hasStopped()) { ++ server.close(); ++ } + } + break; + } // Paper end +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 476f4a5cbe664ddd05474cb88553018bd334a5b8..8af159abd3d0cc94cf155fec5b384c42f69551bf 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -1,5 +1,5 @@ + +- ++ + + + diff --git a/patches/server-remapped/0437-Optimize-Pathfinding.patch b/patches/server-remapped/0437-Optimize-Pathfinding.patch new file mode 100644 index 0000000000..9f2777798e --- /dev/null +++ b/patches/server-remapped/0437-Optimize-Pathfinding.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 02:02:07 -0600 +Subject: [PATCH] Optimize Pathfinding + +Prevents pathfinding from spamming failures for things such as +arrow attacks. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index a362506f38e8d30543b6cd6d215db561290dac76..c501e42b6fef4af065807182dc5b4c444e74e310 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -11,6 +11,7 @@ import net.minecraft.core.Position; + import net.minecraft.core.Vec3i; + import net.minecraft.network.protocol.game.DebugPackets; + import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.Mob; +@@ -32,7 +33,7 @@ public abstract class PathNavigation { + protected final Mob mob; public Entity getEntity() { return mob; } // Paper - OBFHELPER + protected final Level level; + @Nullable +- protected Path path; ++ protected Path path; protected final Path getCurrentPath() { return this.path; } // Paper - OBFHELPER + protected double speedModifier; + protected int tick; + protected int lastStuckCheck; +@@ -184,10 +185,30 @@ public abstract class PathNavigation { + return this.moveTo(this.createPath(x, y, z, 1), speed); + } + ++ // Paper start - optimise pathfinding ++ private int lastFailure = 0; ++ private int pathfindFailures = 0; ++ // Paper end ++ + public boolean moveTo(Entity entity, double speed) { ++ // Paper start - Pathfinding optimizations ++ if (this.pathfindFailures > 10 && this.getCurrentPath() == null && MinecraftServer.currentTick < this.lastFailure + 40) { ++ return false; ++ } ++ // Paper end + Path pathentity = this.createPath(entity, 1); + +- return pathentity != null && this.moveTo(pathentity, speed); ++ // Paper start - Pathfinding optimizations ++ if (pathentity != null && this.moveTo(pathentity, speed)) { ++ this.lastFailure = 0; ++ this.pathfindFailures = 0; ++ return true; ++ } else { ++ this.pathfindFailures++; ++ this.lastFailure = MinecraftServer.currentTick; ++ return false; ++ } ++ // Paper end + } + + public boolean setDestination(@Nullable Path pathentity, double speed) { return moveTo(pathentity, speed); } // Paper - OBFHELPER diff --git a/patches/server-remapped/0438-Reduce-Either-Optional-allocation.patch b/patches/server-remapped/0438-Reduce-Either-Optional-allocation.patch new file mode 100644 index 0000000000..991b0f903b --- /dev/null +++ b/patches/server-remapped/0438-Reduce-Either-Optional-allocation.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 18:35:09 -0700 +Subject: [PATCH] Reduce Either Optional allocation + +In order to get chunk values, we shouldn't need to create +an optional each time. + +diff --git a/src/main/java/com/mojang/datafixers/util/Either.java b/src/main/java/com/mojang/datafixers/util/Either.java +index fc8dbdf43833d76d8dc5f4e92575ca2965afa93a..ab71cdb3a8c2bec036ece630a0e0f088653e928f 100644 +--- a/src/main/java/com/mojang/datafixers/util/Either.java ++++ b/src/main/java/com/mojang/datafixers/util/Either.java +@@ -22,7 +22,7 @@ public abstract class Either implements App, L> { + } + + private static final class Left extends Either { +- private final L value; ++ private final L value; private Optional valueOptional; // Paper - reduce the optional allocation... + + public Left(final L value) { + this.value = value; +@@ -51,7 +51,7 @@ public abstract class Either implements App, L> { + + @Override + public Optional left() { +- return Optional.of(value); ++ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... + } + + @Override +@@ -83,7 +83,7 @@ public abstract class Either implements App, L> { + } + + private static final class Right extends Either { +- private final R value; ++ private final R value; private Optional valueOptional; // Paper - reduce the optional allocation... + + public Right(final R value) { + this.value = value; +@@ -117,7 +117,7 @@ public abstract class Either implements App, L> { + + @Override + public Optional right() { +- return Optional.of(value); ++ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... + } + + @Override diff --git a/patches/server-remapped/0439-Remove-streams-from-PairedQueue.patch b/patches/server-remapped/0439-Remove-streams-from-PairedQueue.patch new file mode 100644 index 0000000000..935abedc0d --- /dev/null +++ b/patches/server-remapped/0439-Remove-streams-from-PairedQueue.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 18:10:43 -0700 +Subject: [PATCH] Remove streams from PairedQueue + +We shouldn't be doing stream calls just to see if the queue is +empty. This creates loads of garbage thanks to how often it's called. + +diff --git a/src/main/java/net/minecraft/util/thread/StrictQueue.java b/src/main/java/net/minecraft/util/thread/StrictQueue.java +index cdc572b0261034248960fa13b8412e874fd20db5..07938519b699a31a280f3f419b34fb7cf6cf6883 100644 +--- a/src/main/java/net/minecraft/util/thread/StrictQueue.java ++++ b/src/main/java/net/minecraft/util/thread/StrictQueue.java +@@ -20,32 +20,30 @@ public interface StrictQueue { + + public static final class FixedPriorityQueue implements StrictQueue { + +- private final List> queueList; ++ private final List> queueList; private final List> getQueues() { return this.queueList; } // Paper - OBFHELPER + + public FixedPriorityQueue(int priorityCount) { +- this.queueList = (List) IntStream.range(0, priorityCount).mapToObj((j) -> { +- return Queues.newConcurrentLinkedQueue(); +- }).collect(Collectors.toList()); ++ // Paper start - remove streams ++ this.queueList = new java.util.ArrayList<>(priorityCount); // queues ++ for (int j = 0; j < priorityCount; ++j) { ++ this.getQueues().add(Queues.newConcurrentLinkedQueue()); ++ } ++ // Paper end - remove streams + } + + @Nullable + @Override + public Runnable pop() { +- Iterator iterator = this.queueList.iterator(); +- +- Runnable runnable; +- +- do { +- if (!iterator.hasNext()) { +- return null; ++ // Paper start - remove iterator creation ++ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { ++ Queue queue = this.getQueues().get(i); ++ Runnable ret = queue.poll(); ++ if (ret != null) { ++ return ret; + } +- +- Queue queue = (Queue) iterator.next(); +- +- runnable = (Runnable) queue.poll(); +- } while (runnable == null); +- +- return runnable; ++ } ++ return null; ++ // Paper end - remove iterator creation + } + + public boolean push(StrictQueue.IntRunnable message) { +@@ -57,7 +55,16 @@ public interface StrictQueue { + + @Override + public boolean isEmpty() { +- return this.queueList.stream().allMatch(Collection::isEmpty); ++ // Paper start - remove streams ++ // why are we doing streams every time we might want to execute a task? ++ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { ++ Queue queue = this.getQueues().get(i); ++ if (!queue.isEmpty()) { ++ return false; ++ } ++ } ++ return true; ++ // Paper end - remove streams + } + } + diff --git a/patches/server-remapped/0440-Reduce-memory-footprint-of-NBTTagCompound.patch b/patches/server-remapped/0440-Reduce-memory-footprint-of-NBTTagCompound.patch new file mode 100644 index 0000000000..dcba632a31 --- /dev/null +++ b/patches/server-remapped/0440-Reduce-memory-footprint-of-NBTTagCompound.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 17:39:25 -0700 +Subject: [PATCH] Reduce memory footprint of NBTTagCompound + +Fastutil maps are going to have a lower memory footprint - which +is important because we clone chunk data after reading it for safety. +So, reduce the impact of the clone on GC. + +diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java +index a91bf94ed9f2f353a685194fc91c4b101ccc1232..c856ca720a9329a94bb07eaa3060c034f95718b3 100644 +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -26,6 +26,7 @@ import net.minecraft.ReportedException; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.TextComponent; ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; // Paper + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +@@ -47,7 +48,7 @@ public class CompoundTag implements Tag { + if (i > 512) { + throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512"); + } else { +- HashMap hashmap = Maps.newHashMap(); ++ Object2ObjectOpenHashMap hashmap = new Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound + + byte b0; + +@@ -83,7 +84,7 @@ public class CompoundTag implements Tag { + } + + public CompoundTag() { +- this(Maps.newHashMap()); ++ this(new Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - reduce memory footprint of NBTTagCompound + } + + @Override +@@ -417,9 +418,17 @@ public class CompoundTag implements Tag { + + @Override + public CompoundTag copy() { +- Map map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy)); ++ // Paper start - reduce memory footprint of NBTTagCompound ++ Object2ObjectOpenHashMap ret = new Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f); + +- return new CompoundTag(map); ++ Iterator> iterator = (this.tags instanceof Object2ObjectOpenHashMap) ? ((Object2ObjectOpenHashMap)this.tags).object2ObjectEntrySet().fastIterator() : this.tags.entrySet().iterator(); ++ while (iterator.hasNext()) { ++ Map.Entry entry = iterator.next(); ++ ret.put(entry.getKey(), entry.getValue().copy()); ++ } ++ ++ return new CompoundTag(ret); ++ // Paper end - reduce memory footprint of NBTTagCompound + } + + public boolean equals(Object object) { diff --git a/patches/server-remapped/0441-Prevent-opening-inventories-when-frozen.patch b/patches/server-remapped/0441-Prevent-opening-inventories-when-frozen.patch new file mode 100644 index 0000000000..7b2a22a56b --- /dev/null +++ b/patches/server-remapped/0441-Prevent-opening-inventories-when-frozen.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Mon, 13 Apr 2020 07:31:44 +0100 +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 162b1a8c6ab57aafa4f6deefc842755a8e14208e..efacfcaab444270b985f3a7fe0ef97e33c18a9de 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -557,7 +557,7 @@ public class ServerPlayer extends Player implements ContainerListener { + containerUpdateDelay = level.paperConfig.containerUpdateTickRate; + } + // Paper end +- if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { ++ if (!this.level.isClientSide && this.containerMenu != this.inventoryMenu && (isImmobile() || !this.containerMenu.stillValid(this))) { // Paper - auto close while frozen + this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.containerMenu = this.inventoryMenu; + } +@@ -1404,7 +1404,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } else { + // CraftBukkit start + this.containerMenu = container; +- this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); ++ if (!isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper + // CraftBukkit end + container.addSlotListener(this); + return OptionalInt.of(this.containerCounter); +@@ -2206,7 +2206,7 @@ public class ServerPlayer extends Player implements ContainerListener { + } + + @Override +- protected boolean isImmobile() { ++ public boolean isImmobile() { // Paper - protected > public + return super.isImmobile() || (this.connection != null && this.connection.isDisconnected()); // Paper + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index a73c6ddd6bf66cc21ae5b25daacdece8cbfeeeac..ae6faa331fcbefd99ee1cd92c88926d767fc50ee 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -323,7 +323,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper + + //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment +- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper ++ if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + getHandle().containerMenu = container; + getHandle().containerMenu.addSlotListener(player); + } +@@ -397,7 +397,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper + if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper + //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment +- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper ++ if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + player.containerMenu = container; + player.containerMenu.addSlotListener(player); + } diff --git a/patches/server-remapped/0442-Optimise-ArraySetSorted-removeIf.patch b/patches/server-remapped/0442-Optimise-ArraySetSorted-removeIf.patch new file mode 100644 index 0000000000..dad03aa170 --- /dev/null +++ b/patches/server-remapped/0442-Optimise-ArraySetSorted-removeIf.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Apr 2020 18:23:28 -0700 +Subject: [PATCH] Optimise ArraySetSorted#removeIf + +Remove iterator allocation and ensure the call is always O(n) + +diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java +index 93813a508be1e1e600a8211f9822f2087328de70..8f03847eeb95ccdb69ad181b38b8724c9c72a76b 100644 +--- a/src/main/java/net/minecraft/util/SortedArraySet.java ++++ b/src/main/java/net/minecraft/util/SortedArraySet.java +@@ -10,8 +10,8 @@ import java.util.NoSuchElementException; + public class SortedArraySet extends AbstractSet { + + private final Comparator comparator; +- private T[] contents; +- private int size; ++ private T[] contents; private final T[] getBackingArray() { return this.contents; } // Paper - OBFHELPER ++ private int size; private final int getSize() { return this.size; } private final void setSize(int value) { this.size = value; } // Paper - OBFHELPER + + private SortedArraySet(int initialCapacity, Comparator comparator) { + this.comparator = comparator; +@@ -22,6 +22,42 @@ public class SortedArraySet extends AbstractSet { + } + } + ++ // Paper start - optimise removeIf ++ @Override ++ public boolean removeIf(java.util.function.Predicate filter) { ++ // prev. impl used an iterator, which could be n^2 and creates garbage ++ int i = 0, len = this.getSize(); ++ T[] backingArray = this.getBackingArray(); ++ ++ for (;;) { ++ if (i >= len) { ++ return false; ++ } ++ if (!filter.test(backingArray[i])) { ++ ++i; ++ continue; ++ } ++ break; ++ } ++ ++ // we only want to write back to backingArray if we really need to ++ ++ int lastIndex = i; // this is where new elements are shifted to ++ ++ for (; i < len; ++i) { ++ T curr = backingArray[i]; ++ if (!filter.test(curr)) { // if test throws we're screwed ++ backingArray[lastIndex++] = curr; ++ } ++ } ++ ++ // cleanup end ++ Arrays.fill(backingArray, lastIndex, len, null); ++ this.setSize(lastIndex); ++ return true; ++ } ++ // Paper end - optimise removeIf ++ + public static > SortedArraySet create(int initialCapacity) { + return new SortedArraySet<>(initialCapacity, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix + } diff --git a/patches/server-remapped/0443-Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server-remapped/0443-Don-t-run-entity-collision-code-if-not-needed.patch new file mode 100644 index 0000000000..474688a9b3 --- /dev/null +++ b/patches/server-remapped/0443-Don-t-run-entity-collision-code-if-not-needed.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Apr 2020 17:56:07 -0700 +Subject: [PATCH] Don't run entity collision code if not needed + +Will not run if max entity craming is disabled and +the max collisions per entity is less than or equal to 0 + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 43fbe7d220f61802ae0cb0620ad078c5df7b69bc..46b962183e2e27ed93054ad9fb6d8ecbf70bc5f9 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -2941,10 +2941,16 @@ public abstract class LivingEntity extends Entity { + protected void serverAiStep() {} + + protected void pushEntities() { ++ // Paper - start don't run getEntities if we're not going to use its result ++ int i = this.level.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); ++ if (i <= 0 && level.paperConfig.maxCollisionsPerEntity <= 0) { ++ return; ++ } ++ // Paper - end don't run getEntities if we're not going to use its result + List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); + + if (!list.isEmpty()) { +- int i = this.level.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); ++ // Paper - move up + int j; + + if (i > 0 && list.size() > i - 1 && this.random.nextInt(4) == 0) { diff --git a/patches/server-remapped/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch b/patches/server-remapped/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch new file mode 100644 index 0000000000..e6f6255656 --- /dev/null +++ b/patches/server-remapped/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Thu, 16 Apr 2020 16:13:59 -0700 +Subject: [PATCH] Optimize ChunkProviderServer's chunk level checking helper + methods + +These can be hot functions (i.e entity ticking and block ticking), +so inline where possible, and avoid the abstraction of the +Either class. + +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 3744cce8611ac01b1b6c76cd3c4890795c1f06a2..531fe1259a1d60ff69321c3fefbf97f7141e6475 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -24,7 +24,6 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.progress.ChunkProgressListener; +-import net.minecraft.util.Mth; + import net.minecraft.util.profiling.ProfilerFiller; + import net.minecraft.util.thread.BlockableEventLoop; + import net.minecraft.world.entity.Entity; +@@ -644,21 +643,29 @@ public class ServerChunkCache extends ChunkSource { + + public final boolean isInEntityTickingChunk(Entity entity) { return this.isEntityTickingChunk(entity); } // Paper - OBFHELPER + @Override public boolean isEntityTickingChunk(Entity entity) { +- long i = ChunkPos.asLong(Mth.floor(entity.getX()) >> 4, Mth.floor(entity.getZ()) >> 4); +- +- return this.checkChunkFuture(i, (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error ++ // Paper start - optimize is ticking ready type functions ++ // entity ticking ++ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(MCUtil.getCoordinateKey(entity)); ++ return playerChunk != null && playerChunk.isEntityTickingReady(); ++ // Paper end - optimize is ticking ready type functions + } + + public final boolean isEntityTickingChunk(ChunkPos chunkcoordintpair) { return this.isEntityTickingChunk(chunkcoordintpair); } // Paper - OBFHELPER + @Override public boolean isEntityTickingChunk(ChunkPos pos) { +- return this.checkChunkFuture(pos.toLong(), (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error ++ // Paper start - optimize is ticking ready type functions ++ // is entity ticking ready ++ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(MCUtil.getCoordinateKey(pos)); ++ return playerChunk != null && playerChunk.isEntityTickingReady(); ++ // Paper end - optimize is ticking ready type functions + } + + @Override + public boolean isTickingChunk(BlockPos pos) { +- long i = ChunkPos.asLong(pos.getX() >> 4, pos.getZ() >> 4); +- +- return this.checkChunkFuture(i, (Function>>) ChunkHolder::getTickingChunkFuture); // CraftBukkit - decompile error ++ // Paper start - optimize is ticking ready type functions ++ // is ticking ready ++ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(MCUtil.getCoordinateKey(pos)); ++ return playerChunk != null && playerChunk.isTickingReady(); ++ // Paper end - optimize is ticking ready type functions + } + + private boolean checkChunkFuture(long pos, Function>> futureFunction) { diff --git a/patches/server-remapped/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch b/patches/server-remapped/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch new file mode 100644 index 0000000000..bc23f71417 --- /dev/null +++ b/patches/server-remapped/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 16 Apr 2020 20:07:29 -0500 +Subject: [PATCH] Restrict vanilla teleport command to valid locations + +Fixes GH-3165, GH-3575 + +diff --git a/src/main/java/net/minecraft/server/commands/TeleportCommand.java b/src/main/java/net/minecraft/server/commands/TeleportCommand.java +index 774180d9e450199309fee65b1d10e1592f84548a..d04ce9a323b079b4556b8c341fb11186e8d3e05d 100644 +--- a/src/main/java/net/minecraft/server/commands/TeleportCommand.java ++++ b/src/main/java/net/minecraft/server/commands/TeleportCommand.java +@@ -141,6 +141,12 @@ public class TeleportCommand { + + private static void performTeleport(CommandSourceStack source, Entity target, ServerLevel world, double x, double y, double z, Set movementFlags, float yaw, float pitch, @Nullable TeleportCommand.LookAt facingLocation) throws CommandSyntaxException { + BlockPos blockposition = new BlockPos(x, y, z); ++ // Paper start - Don't allow teleport command to invalid locations ++ if (x <= -30000000 || z <= -30000000 || x > 30000000 || z > 30000000 || y > 30000000 || y <= -30000000) { // Copy/pasta from BaseBlockPosition#isValidLocation ++ org.bukkit.Bukkit.getLogger().warning("Refused to teleport " + target.getScoreboardName() + " to " + x + ", " + y + ", " + z); ++ return; ++ } ++ // Paper end + + if (!Level.isInSpawnableBounds(blockposition)) { + throw TeleportCommand.INVALID_POSITION.create(); diff --git a/patches/server-remapped/0446-Implement-Player-Client-Options-API.patch b/patches/server-remapped/0446-Implement-Player-Client-Options-API.patch new file mode 100644 index 0000000000..dcdbea5496 --- /dev/null +++ b/patches/server-remapped/0446-Implement-Player-Client-Options-API.patch @@ -0,0 +1,188 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Mon, 20 Jan 2020 21:38:15 +0100 +Subject: [PATCH] Implement Player Client Options API + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperSkinParts.java b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabba57885e1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java +@@ -0,0 +1,74 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Objects; ++ ++import java.util.StringJoiner; ++ ++public class PaperSkinParts implements SkinParts { ++ ++ private final int raw; ++ ++ public PaperSkinParts(int raw) { ++ this.raw = raw; ++ } ++ ++ public boolean hasCapeEnabled() { ++ return (raw & 1) == 1; ++ } ++ ++ public boolean hasJacketEnabled() { ++ return (raw >> 1 & 1) == 1; ++ } ++ ++ public boolean hasLeftSleeveEnabled() { ++ return (raw >> 2 & 1) == 1; ++ } ++ ++ public boolean hasRightSleeveEnabled() { ++ return (raw >> 3 & 1) == 1; ++ } ++ ++ public boolean hasLeftPantsEnabled() { ++ return (raw >> 4 & 1) == 1; ++ } ++ ++ public boolean hasRightPantsEnabled() { ++ return (raw >> 5 & 1) == 1; ++ } ++ ++ public boolean hasHatsEnabled() { ++ return (raw >> 6 & 1) == 1; ++ } ++ ++ @Override ++ public int getRaw() { ++ return raw; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ PaperSkinParts that = (PaperSkinParts) o; ++ return raw == that.raw; ++ } ++ ++ @Override ++ public int hashCode() { ++ return Objects.hashCode(raw); ++ } ++ ++ @Override ++ public String toString() { ++ return new StringJoiner(", ", PaperSkinParts.class.getSimpleName() + "[", "]") ++ .add("raw=" + raw) ++ .add("cape=" + hasCapeEnabled()) ++ .add("jacket=" + hasJacketEnabled()) ++ .add("leftSleeve=" + hasLeftSleeveEnabled()) ++ .add("rightSleeve=" + hasRightSleeveEnabled()) ++ .add("leftPants=" + hasLeftPantsEnabled()) ++ .add("rightPants=" + hasRightPantsEnabled()) ++ .add("hats=" + hasHatsEnabled()) ++ .toString(); ++ } ++} +diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java +index 1f486cfd77b49568540398b1b3fa6127b17ba6aa..4b43740f9ff4feab4f1cd2f8e91d55be3cf8eb50 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java +@@ -41,14 +41,17 @@ public class ServerboundClientInformationPacket implements Packet POSES = ImmutableMap.builder().put(Pose.STANDING, Player.STANDING_DIMENSIONS).put(Pose.SLEEPING, Player.SLEEPING_DIMENSIONS).put(Pose.FALL_FLYING, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.SWIMMING, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.SPIN_ATTACK, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.CROUCHING, EntityDimensions.scalable(0.6F, 1.5F)).put(Pose.DYING, EntityDimensions.fixed(0.2F, 0.2F)).build(); + private static final EntityDataAccessor DATA_PLAYER_ABSORPTION_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.FLOAT); + private static final EntityDataAccessor DATA_SCORE_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.INT); +- protected static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); ++ protected static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); public static EntityDataAccessor getSkinPartsWatcher() { return DATA_PLAYER_MODE_CUSTOMISATION; } // Paper - OBFHELPER + protected static final EntityDataAccessor DATA_PLAYER_MAIN_HAND = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); + protected static final EntityDataAccessor DATA_SHOULDER_LEFT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); + protected static final EntityDataAccessor DATA_SHOULDER_RIGHT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 20de8e358789d05bb5ac15e4cdd7dda85b61b7f8..eb366396820c9b6731469df4198e0884a431a77c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1,5 +1,8 @@ + package org.bukkit.craftbukkit.entity; + ++import com.destroystokyo.paper.ClientOption.ChatVisibility; ++import com.destroystokyo.paper.PaperSkinParts; ++import com.destroystokyo.paper.ClientOption; + import com.destroystokyo.paper.Title; + import com.google.common.base.Preconditions; + import com.google.common.collect.ImmutableSet; +@@ -2250,6 +2253,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public void setViewDistance(int viewDistance) { + throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO + } ++ ++ @Override ++ public T getClientOption(ClientOption type) { ++ if(ClientOption.SKIN_PARTS.equals(type)) { ++ return type.getType().cast(new PaperSkinParts(getHandle().getEntityData().get(net.minecraft.world.entity.player.Player.getSkinPartsWatcher()))); ++ } else if(ClientOption.CHAT_COLORS_ENABLED.equals(type)) { ++ return type.getType().cast(getHandle().hasChatColorsEnabled()); ++ } else if(ClientOption.CHAT_VISIBILITY.equals(type)) { ++ return type.getType().cast(getHandle().getChatVisibility() == null ? ChatVisibility.UNKNOWN : ChatVisibility.valueOf(getHandle().getChatVisibility().name())); ++ } else if(ClientOption.LOCALE.equals(type)) { ++ return type.getType().cast(getLocale()); ++ } else if(ClientOption.MAIN_HAND.equals(type)) { ++ return type.getType().cast(getMainHand()); ++ } else if(ClientOption.VIEW_DISTANCE.equals(type)) { ++ return type.getType().cast(getClientViewDistance()); ++ } ++ throw new RuntimeException("Unknown settings type"); ++ } + // Paper end + + // Spigot start diff --git a/patches/server-remapped/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server-remapped/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch new file mode 100644 index 0000000000..1d32694a1d --- /dev/null +++ b/patches/server-remapped/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 18 Apr 2020 04:36:11 -0400 +Subject: [PATCH] Fix Chunk Post Processing deadlock risk + +See: https://gist.github.com/aikar/dd22bbd2a3d78a2fd3d92e95e9f28dc6 + +as part of post processing a chunk, we can call ChunkConverter. + +ChunkConverter then kicks off major physics updates, and when blocks +that have connections across chunk boundries occur, a recursive risk +can occur where A updates a block that triggers a physics request. + +That physics request may trigger a chunk request, that then enqueues +a task into the Mailbox ChunkTaskQueueSorter. + +If anything requests that same chunk that is in the middle of conversion, +it's mailbox queue is going to be held up, so the subsequent chunk request +will be unable to proceed. + +We delay post processing of Chunk.A() 1 "pass" by re stuffing it back into +the executor so that the mailbox ChunkQueue is now considered empty. + +This successfully fixed a reoccurring and highly reproduceable crash +for heightmaps. + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 49728aab7512ea8486d277d34e80d3c6a4727aac..dbe60f5d24fb39be52c3cb8f933371b1626951df 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -181,6 +181,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }; + // CraftBukkit end + ++ final CallbackExecutor chunkLoadConversionCallbackExecutor = new CallbackExecutor(); // Paper ++ + // Paper start - distance maps + private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); + +@@ -1054,7 +1056,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return Either.left(chunk); + }); + }, (runnable) -> { +- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); ++ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, () -> ChunkMap.this.chunkLoadConversionCallbackExecutor.execute(runnable))); // Paper - delay running Chunk post processing until outside of the sorter to prevent a deadlock scenario when post processing causes another chunk request. + }); + + completablefuture1.thenAcceptAsync((either) -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 531fe1259a1d60ff69321c3fefbf97f7141e6475..b45fe750c8ca838e1beebff4077e5819eec2836c 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -1021,6 +1021,7 @@ public class ServerChunkCache extends ChunkSource { + return super.pollTask() || execChunkTask; // Paper + } + } finally { ++ chunkMap.chunkLoadConversionCallbackExecutor.run(); // Paper - Add chunk load conversion callback executor to prevent deadlock due to recursion in the chunk task queue sorter + chunkMap.callbackExecutor.run(); + } + // CraftBukkit end diff --git a/patches/server-remapped/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/patches/server-remapped/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch new file mode 100644 index 0000000000..1469edc105 --- /dev/null +++ b/patches/server-remapped/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 18 Apr 2020 15:59:41 -0400 +Subject: [PATCH] Don't crash if player is attempted to be removed from + untracked chunk. + +I suspect it deals with teleporting as it uses players current x/y/z + +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 71a51cc99e26579e765f88340588e23956888929..90429d3f5c5b725098cfb001d54c70608f3df7bb 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -245,8 +245,8 @@ public abstract class DistanceManager { + ObjectSet objectset = (ObjectSet) this.playersPerChunk.get(i); + if (objectset == null) return; // CraftBukkit - SPIGOT-6208 + +- objectset.remove(player); +- if (objectset.isEmpty()) { ++ if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully. ++ if (objectset == null || objectset.isEmpty()) { // Paper + this.playersPerChunk.remove(i); + this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); + this.playerTicketManager.update(i, Integer.MAX_VALUE, false); diff --git a/patches/server-remapped/0449-Broadcast-join-message-to-console.patch b/patches/server-remapped/0449-Broadcast-join-message-to-console.patch new file mode 100644 index 0000000000..de365413d4 --- /dev/null +++ b/patches/server-remapped/0449-Broadcast-join-message-to-console.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AvrooVulcan +Date: Fri, 17 Apr 2020 00:15:23 +0100 +Subject: [PATCH] Broadcast join message to console + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 984ac19dcab446531c816e365c7c149e2c49d567..e043722436492140162940770c22be47690fb47f 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -284,7 +284,9 @@ public abstract class PlayerList { + + if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure + joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure +- server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure ++ // Paper start - Removed sendAll for loop and broadcasted to console also ++ server.getPlayerList().sendMessage(joinMessage); // Paper - Adventure ++ // Paper end + } + // CraftBukkit end + diff --git a/patches/server-remapped/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/patches/server-remapped/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch new file mode 100644 index 0000000000..e4ac02eb91 --- /dev/null +++ b/patches/server-remapped/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch @@ -0,0 +1,149 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 19 Apr 2020 00:05:46 -0400 +Subject: [PATCH] Fix Longstanding Broken behavior of PlayerJoinEvent + +For years, plugin developers have had to delay many things they do +inside of the PlayerJoinEvent by 1 tick to make it actually work. + +This all boiled down to 1 reason why: The event fired before the +player was fully ready and joined to the world! + +Additionally, if that player logged out on a vehicle, the event +fired before the vehicle was even loaded, so that plugins had no +access to the vehicle during this event either. + +This change finally fixes this issue, fully preparing the player +into the world as a fully ready entity, vehicle included. + +There should be no plugins that break because of this change, but might +improve consistency with other plugins instead. + +For example, if 2 plugins listens to this event, and the first one +teleported the player in the event, then the 2nd plugin actually +would be getting a valid player! + +This was very non deterministic. This change will ensure every plugin +receives a deterministic result, and should no longer require 1 tick +delays anymore. + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index dbe60f5d24fb39be52c3cb8f933371b1626951df..b3ca4300b280a24f3ed2acaffdd6ae2cdffd140d 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1584,7 +1584,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }); + } + +- protected void addEntity(Entity entity) { ++ public void addEntity(Entity entity) { // Paper - protected -> public + org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot + // Paper start - ignore and warn about illegal addEntity calls instead of crashing server + if (!entity.valid || entity.level != this.level || this.entityMap.containsKey(entity.getId())) { +@@ -1593,6 +1593,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + .printStackTrace(); + return; + } ++ if (entity instanceof ServerPlayer && ((ServerPlayer) entity).supressTrackerForLogin) return; // Delay adding to tracker until after list packets + // Paper end + if (!(entity instanceof EnderDragonPart)) { + EntityType entitytypes = entity.getType(); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index aa979d17c264840ebd528708df3d6118e69fec68..75a095e0c2177dc1b46b080597ff8f12f1480acc 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -237,6 +237,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public double maxHealthCache; + public boolean joining = true; + public boolean sentListPacket = false; ++ public boolean supressTrackerForLogin = false; // Paper + public Integer clientViewDistance; + // CraftBukkit end + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index e043722436492140162940770c22be47690fb47f..454d60566743e02e7e55868c7bb45e30583dfa8f 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -272,6 +272,12 @@ public abstract class PlayerList { + this.playersByUUID.put(player.getUUID(), player); + // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below + ++ // Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks ++ player.supressTrackerForLogin = true; ++ worldserver1.addNewPlayer(player); ++ this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below worldserver.addPlayerJoin(entityplayer); ++ mountSavedVehicle(player, worldserver1, nbttagcompound); ++ // Paper end + // CraftBukkit start + PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + cserver.getPluginManager().callEvent(playerJoinEvent); +@@ -307,6 +313,8 @@ public abstract class PlayerList { + player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); + } + player.sentListPacket = true; ++ player.supressTrackerForLogin = false; // Paper ++ ((ServerLevel)player.level).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now + // CraftBukkit end + + player.connection.send(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn +@@ -332,6 +340,11 @@ public abstract class PlayerList { + playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect)); + } + ++ // Paper start - move vehicle into method so it can be called above - short circuit around that code ++ onPlayerJoinFinish(player, worldserver1, s1); ++ } ++ private void mountSavedVehicle(ServerPlayer entityplayer, ServerLevel worldserver1, CompoundTag nbttagcompound) { ++ // Paper end + if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) { + CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); + // CraftBukkit start +@@ -354,20 +367,20 @@ public abstract class PlayerList { + Entity entity1; + + if (entity.getUUID().equals(uuid)) { +- player.startRiding(entity, true); ++ entityplayer.startRiding(entity, true); + } else { + iterator1 = entity.getIndirectPassengers().iterator(); + + while (iterator1.hasNext()) { + entity1 = (Entity) iterator1.next(); + if (entity1.getUUID().equals(uuid)) { +- player.startRiding(entity1, true); ++ entityplayer.startRiding(entity1, true); + break; + } + } + } + +- if (!player.isPassenger()) { ++ if (!entityplayer.isPassenger()) { + PlayerList.LOGGER.warn("Couldn't reattach entity to player"); + worldserver1.despawn(entity); + iterator1 = entity.getIndirectPassengers().iterator(); +@@ -380,16 +393,20 @@ public abstract class PlayerList { + } + } + +- player.initMenu(); ++ // Paper start ++ } ++ public void onPlayerJoinFinish(ServerPlayer entityplayer, ServerLevel worldserver1, String s1) { ++ // Paper end ++ entityplayer.initMenu(); + // Paper start - Add to collideRule team if needed + final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); + final PlayerTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName); +- if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) { +- scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); ++ if (this.collideRuleTeamName != null && collideRuleTeam != null && entityplayer.getTeam() == null) { ++ scoreboard.addPlayerToTeam(entityplayer.getScoreboardName(), collideRuleTeam); + } + // Paper end + // CraftBukkit - Moved from above, added world +- PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.worldDataServer.getLevelName(), player.getX(), player.getY(), player.getZ()); ++ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getName().getString(), s1, entityplayer.getId(), worldserver1.worldDataServer.getLevelName(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()); + } + + public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) { diff --git a/patches/server-remapped/0451-Load-Chunks-for-Login-Asynchronously.patch b/patches/server-remapped/0451-Load-Chunks-for-Login-Asynchronously.patch new file mode 100644 index 0000000000..f02494b2a2 --- /dev/null +++ b/patches/server-remapped/0451-Load-Chunks-for-Login-Asynchronously.patch @@ -0,0 +1,416 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 19 Apr 2020 04:28:29 -0400 +Subject: [PATCH] Load Chunks for Login Asynchronously + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index b3ca4300b280a24f3ed2acaffdd6ae2cdffd140d..97a582614ad28f9fa864ae9be4860658e5979214 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -145,7 +145,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private final ProcessorHandle> worldgenMailbox; + private final ProcessorHandle> mainThreadMailbox; + public final ChunkProgressListener progressListener; +- public final ChunkMap.ChunkDistanceManager distanceManager; ++ public final ChunkMap.ChunkDistanceManager distanceManager; public final DistanceManager getChunkDistanceManager() { return this.distanceManager; } // Paper - OBFHELPER + private final AtomicInteger tickingGenerated; + public final StructureManager structureManager; // Paper - private -> public + private final File storageFolder; +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index b45fe750c8ca838e1beebff4077e5819eec2836c..79fb63c40dd0543a6f629e78f390f23f34992ba1 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -629,7 +629,7 @@ public class ServerChunkCache extends ChunkSource { + return this.mainThreadProcessor.pollTask(); + } + +- private boolean runDistanceManagerUpdates() { ++ public boolean runDistanceManagerUpdates() { // Paper - private -> public + boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); + boolean flag1 = this.chunkMap.promoteChunkMap(); + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 75a095e0c2177dc1b46b080597ff8f12f1480acc..24c508ade61a6ad90b0ef73cdc995f531ef18263 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -32,6 +32,7 @@ import net.minecraft.core.Vec3i; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; + import net.minecraft.nbt.Tag; ++import net.minecraft.network.Connection; + import net.minecraft.network.chat.ChatType; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.HoverEvent; +@@ -172,6 +173,7 @@ public class ServerPlayer extends Player implements ContainerListener { + + private static final Logger LOGGER = LogManager.getLogger(); + public ServerGamePacketListenerImpl connection; ++ public Connection networkManager; // Paper + public final MinecraftServer server; + public final ServerPlayerGameMode gameMode; + public final Deque removeQueue = new ArrayDeque<>(); // Paper +@@ -238,6 +240,7 @@ public class ServerPlayer extends Player implements ContainerListener { + public boolean joining = true; + public boolean sentListPacket = false; + public boolean supressTrackerForLogin = false; // Paper ++ public boolean didPlayerJoinEvent = false; // Paper + public Integer clientViewDistance; + // CraftBukkit end + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index d09e4857b6c40410d134fa81b48e95919a7373bd..583587457790df826a8a3239a4bd1d0f1dcab1da 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -21,6 +21,7 @@ public class TicketType { + public static final TicketType FORCED = create("forced", Comparator.comparingLong(ChunkPos::toLong)); + public static final TicketType LIGHT = create("light", Comparator.comparingLong(ChunkPos::toLong)); + public static final TicketType PORTAL = create("portal", Vec3i::compareTo, 300); ++ public static final TicketType LOGIN = create("login", Long::compareTo, 100); // Paper + public static final TicketType POST_TELEPORT = create("post_teleport", Integer::compareTo, 5); + public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); + public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 09a663cc53cdf8ae45352b280200c8170dbbcdfc..1bed6e69bf3cc1ab9b0c1259de4f643bf58371aa 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -220,6 +220,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private static final Logger LOGGER = LogManager.getLogger(); + public final Connection connection; + private final MinecraftServer server; ++ public Runnable playerJoinReady; // Paper + public ServerPlayer player; + private int tickCount; + private long keepAliveTime = Util.getMillis(); private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER +@@ -298,6 +299,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit end + + public void tick() { ++ // Paper start - login async ++ Runnable playerJoinReady = this.playerJoinReady; ++ if (playerJoinReady != null) { ++ this.playerJoinReady = null; ++ playerJoinReady.run(); ++ } ++ // Don't tick if not valid (dead), otherwise we load chunks below ++ if (this.player.valid) { ++ // Paper end + this.resetPosition(); + this.player.xo = this.player.getX(); + this.player.yo = this.player.getY(); +@@ -339,7 +349,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.lastVehicle = null; + this.clientVehicleIsFloating = false; + this.aboveGroundVehicleTickCount = 0; +- } ++ }} // Paper - end if (valid) + + this.server.getProfiler().push("keepAlive"); + // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 9631fa93b821c7f6bc6dc707c2c82cce2ae8291e..e229c7735ba88be3d8721440104958408a2a075e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -86,7 +86,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + // Paper end + } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { +- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); ++ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper + + if (entityplayer == null) { + this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT; +@@ -186,7 +186,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + + this.connection.send(new ClientboundGameProfilePacket(this.gameProfile)); +- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); ++ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper + + if (entityplayer != null) { + this.state = ServerLoginPacketListenerImpl.State.DELAY_ACCEPT; +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 454d60566743e02e7e55868c7bb45e30583dfa8f..ffc8c9ee8b1768dd809189858ee45658fb9bf1c5 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -36,6 +36,7 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; + import net.minecraft.network.protocol.game.ClientboundChatPacket; + import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; ++import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; + import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; + import net.minecraft.network.protocol.game.ClientboundGameEventPacket; + import net.minecraft.network.protocol.game.ClientboundLoginPacket; +@@ -59,6 +60,8 @@ import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.PlayerAdvancements; + import net.minecraft.server.ServerScoreboard; ++import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.level.ServerPlayerGameMode; +@@ -124,11 +127,12 @@ public abstract class PlayerList { + private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); + private final MinecraftServer server; + public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety +- private final Map playersByUUID = Maps.newHashMap(); ++ private final Map playersByUUID = Maps.newHashMap();Map getUUIDMap() { return playersByUUID; } // Paper - OBFHELPER + private final UserBanList bans; + private final IpBanList ipBans; + private final ServerOpList ops; + private final UserWhiteList whitelist; ++ private final Map pendingPlayers = Maps.newHashMap(); // Paper + // CraftBukkit start + // private final Map o; + // private final Map p; +@@ -167,6 +171,11 @@ public abstract class PlayerList { + } + + public void placeNewPlayer(Connection connection, ServerPlayer player) { ++ ServerPlayer prev = pendingPlayers.put(player.getUUID(), player);// Paper ++ if (prev != null) { ++ disconnectPendingPlayer(prev); ++ } ++ player.networkManager = connection; // Paper + player.loginTime = System.currentTimeMillis(); // Paper + GameProfile gameprofile = player.getGameProfile(); + GameProfileCache usercache = this.server.getProfileCache(); +@@ -180,7 +189,7 @@ public abstract class PlayerList { + if (nbttagcompound != null && nbttagcompound.contains("bukkit")) { + CompoundTag bukkit = nbttagcompound.getCompound("bukkit"); + s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; +- } ++ }String lastKnownName = s; // Paper + // CraftBukkit end + + if (nbttagcompound != null) { +@@ -255,34 +264,79 @@ public abstract class PlayerList { + player.getRecipeBook().sendInitialRecipeBook(player); + this.updateEntireScoreboard(worldserver1.getScoreboard(), player); + this.server.invalidateStatus(); ++ // Paper start - async load spawn in chunk ++ ServerLevel finalWorldserver = worldserver1; ++ int chunkX = loc.getBlockX() >> 4; ++ int chunkZ = loc.getBlockZ() >> 4; ++ final ChunkPos pos = new ChunkPos(chunkX, chunkZ); ++ ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; ++ playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.toLong()); ++ worldserver1.getChunkSource().runDistanceManagerUpdates(); ++ worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { ++ ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); ++ if (updatingChunk != null) { ++ return updatingChunk.getEntityTickingFuture(); ++ } else { ++ return java.util.concurrent.CompletableFuture.completedFuture(chunk); ++ } ++ }).thenAccept(chunk -> { ++ playerconnection.playerJoinReady = () -> { ++ postChunkLoadJoin( ++ player, finalWorldserver, connection, playerconnection, ++ nbttagcompound, connection.getRemoteAddress().toString(), lastKnownName ++ ); ++ }; ++ }); ++ } ++ ++ public ServerPlayer getActivePlayer(UUID uuid) { ++ ServerPlayer player = this.getUUIDMap().get(uuid); ++ return player != null ? player : pendingPlayers.get(uuid); ++ } ++ ++ void disconnectPendingPlayer(ServerPlayer entityplayer) { ++ TranslatableComponent msg = new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0]); ++ entityplayer.networkManager.send(new ClientboundDisconnectPacket(msg), (future) -> { ++ entityplayer.networkManager.disconnect(msg); ++ entityplayer.networkManager = null; ++ }); ++ } ++ ++ private void postChunkLoadJoin(ServerPlayer entityplayer, ServerLevel worldserver1, Connection networkmanager, ServerGamePacketListenerImpl playerconnection, CompoundTag nbttagcompound, String s1, String s) { ++ pendingPlayers.remove(entityplayer.getUUID(), entityplayer); ++ if (!networkmanager.isConnected()) { ++ return; ++ } ++ entityplayer.didPlayerJoinEvent = true; ++ // Paper end + TranslatableComponent chatmessage; + +- if (player.getGameProfile().getName().equalsIgnoreCase(s)) { +- chatmessage = new TranslatableComponent("multiplayer.player.joined", new Object[]{player.getDisplayName()}); ++ if (entityplayer.getGameProfile().getName().equalsIgnoreCase(s)) { ++ chatmessage = new TranslatableComponent("multiplayer.player.joined", new Object[]{entityplayer.getDisplayName()}); + } else { +- chatmessage = new TranslatableComponent("multiplayer.player.joined.renamed", new Object[]{player.getDisplayName(), s}); ++ chatmessage = new TranslatableComponent("multiplayer.player.joined.renamed", new Object[]{entityplayer.getDisplayName(), s}); + } + // CraftBukkit start + chatmessage.withStyle(ChatFormatting.YELLOW); + Component joinMessage = chatmessage; // Paper - Adventure + +- playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.yRot, player.xRot); +- this.players.add(player); +- this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot +- this.playersByUUID.put(player.getUUID(), player); ++ playerconnection.teleport(entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), entityplayer.yRot, entityplayer.xRot); ++ this.players.add(entityplayer); ++ this.playersByName.put(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT), entityplayer); // Spigot ++ this.playersByUUID.put(entityplayer.getUUID(), entityplayer); + // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below + + // Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks +- player.supressTrackerForLogin = true; +- worldserver1.addNewPlayer(player); +- this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below worldserver.addPlayerJoin(entityplayer); +- mountSavedVehicle(player, worldserver1, nbttagcompound); ++ entityplayer.supressTrackerForLogin = true; ++ worldserver1.addNewPlayer(entityplayer); ++ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); // see commented out section below worldserver.addPlayerJoin(entityplayer); ++ mountSavedVehicle(entityplayer, worldserver1, nbttagcompound); + // Paper end + // CraftBukkit start +- PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure ++ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + cserver.getPluginManager().callEvent(playerJoinEvent); + +- if (!player.connection.connection.isConnected()) { ++ if (!entityplayer.connection.connection.isConnected()) { + return; + } + +@@ -297,51 +351,51 @@ public abstract class PlayerList { + // CraftBukkit end + + // CraftBukkit start - sendAll above replaced with this loop +- ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, player); ++ ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, entityplayer); + + for (int i = 0; i < this.players.size(); ++i) { + ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i); + +- if (entityplayer1.getBukkitEntity().canSee(player.getBukkitEntity())) { ++ if (entityplayer1.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { + entityplayer1.connection.send(packet); + } + +- if (!player.getBukkitEntity().canSee(entityplayer1.getBukkitEntity())) { ++ if (!entityplayer.getBukkitEntity().canSee(entityplayer1.getBukkitEntity())) { + continue; + } + +- player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); ++ entityplayer.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); + } +- player.sentListPacket = true; +- player.supressTrackerForLogin = false; // Paper +- ((ServerLevel)player.level).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now ++ entityplayer.sentListPacket = true; ++ entityplayer.supressTrackerForLogin = false; // Paper ++ ((ServerLevel)entityplayer.level).getChunkSource().chunkMap.addEntity(entityplayer); // Paper - track entity now + // CraftBukkit end + +- player.connection.send(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn ++ entityplayer.connection.send(new ClientboundSetEntityDataPacket(entityplayer.getId(), entityplayer.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn + + // CraftBukkit start - Only add if the player wasn't moved in the event +- if (player.level == worldserver1 && !worldserver1.players().contains(player)) { +- worldserver1.addNewPlayer(player); +- this.server.getCustomBossEvents().onPlayerConnect(player); ++ if (entityplayer.level == worldserver1 && !worldserver1.players().contains(entityplayer)) { ++ worldserver1.addNewPlayer(entityplayer); ++ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); + } + +- worldserver1 = player.getLevel(); // CraftBukkit - Update in case join event changed it ++ worldserver1 = entityplayer.getLevel(); // CraftBukkit - Update in case join event changed it + // CraftBukkit end +- this.sendLevelInfo(player, worldserver1); ++ this.sendLevelInfo(entityplayer, worldserver1); + if (!this.server.getResourcePack().isEmpty()) { +- player.sendTexturePack(this.server.getResourcePack(), this.server.getResourcePackHash()); ++ entityplayer.sendTexturePack(this.server.getResourcePack(), this.server.getResourcePackHash()); + } + +- Iterator iterator = player.getActiveEffects().iterator(); ++ Iterator iterator = entityplayer.getActiveEffects().iterator(); + + while (iterator.hasNext()) { + MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect)); ++ playerconnection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobeffect)); + } + + // Paper start - move vehicle into method so it can be called above - short circuit around that code +- onPlayerJoinFinish(player, worldserver1, s1); ++ onPlayerJoinFinish(entityplayer, worldserver1, s1); + } + private void mountSavedVehicle(ServerPlayer entityplayer, ServerLevel worldserver1, CompoundTag nbttagcompound) { + // Paper end +@@ -492,6 +546,7 @@ public abstract class PlayerList { + + protected void save(ServerPlayer player) { + if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit ++ if (!player.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) + this.playerIo.save(player); + ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit + +@@ -519,7 +574,7 @@ public abstract class PlayerList { + } + + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); +- cserver.getPluginManager().callEvent(playerQuitEvent); ++ if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + + if (server.isSameThread()) entityplayer.doTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) +@@ -572,6 +627,13 @@ public abstract class PlayerList { + // this.p.remove(uuid); + // CraftBukkit end + } ++ // Paper start ++ entityplayer1 = pendingPlayers.get(uuid); ++ if (entityplayer1 == entityplayer) { ++ pendingPlayers.remove(uuid); ++ } ++ entityplayer.networkManager = null; ++ // Paper end + + // CraftBukkit start + // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[]{entityplayer})); +@@ -589,7 +651,7 @@ public abstract class PlayerList { + cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); + // CraftBukkit end + +- return playerQuitEvent.quitMessage(); // Paper - Adventure ++ return entityplayer.didPlayerJoinEvent ? playerQuitEvent.quitMessage() : null; // CraftBukkit // Paper - Adventure // Paper - don't print quit if we never printed join + } + + // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer +@@ -608,6 +670,13 @@ public abstract class PlayerList { + list.add(entityplayer); + } + } ++ // Paper start - check pending players too ++ entityplayer = pendingPlayers.get(uuid); ++ if (entityplayer != null) { ++ this.pendingPlayers.remove(uuid); ++ disconnectPendingPlayer(entityplayer); ++ } ++ // Paper end + + Iterator iterator = list.iterator(); + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index b8dcc91a191f25ca578e0858abf6c1b874fee15d..9f0371282f5829d26dc9618c3d466bccaa4cd3af 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1371,7 +1371,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.yo = y; + this.zo = d4; + this.setPos(d3, y, d4); +- level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit ++ if (valid) level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit // Paper + } + + public void moveTo(Vec3 vec3d) { diff --git a/patches/server-remapped/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/patches/server-remapped/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch new file mode 100644 index 0000000000..eeaa3a49f4 --- /dev/null +++ b/patches/server-remapped/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2277 <38501234+2277@users.noreply.github.com> +Date: Tue, 31 Mar 2020 10:33:55 +0100 +Subject: [PATCH] Move player to spawn point if spawn in unloaded world + +The code following this has better support for null worlds to move +them back to the world spawn. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 9f0371282f5829d26dc9618c3d466bccaa4cd3af..34226102c50a4353c42e68917d41c44d251e602f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1808,9 +1808,11 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + bworld = server.getWorld(worldName); + } + +- if (bworld == null) { +- bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getLevel(Level.OVERWORLD).getWorld(); +- } ++ // Paper start - Move player to spawn point if spawn in unloaded world ++// if (bworld == null) { ++// bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld(); ++// } ++ // Paper end - Move player to spawn point if spawn in unloaded world + + setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle()); + } diff --git a/patches/server-remapped/0453-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server-remapped/0453-Add-PlayerAttackEntityCooldownResetEvent.patch new file mode 100644 index 0000000000..f1eab97e33 --- /dev/null +++ b/patches/server-remapped/0453-Add-PlayerAttackEntityCooldownResetEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: nossr50 +Date: Thu, 26 Mar 2020 19:44:50 -0700 +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 46b962183e2e27ed93054ad9fb6d8ecbf70bc5f9..cec1e6105b8c2ac3d1482c00482d53d6be0d38d1 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1928,7 +1928,16 @@ public abstract class LivingEntity extends Entity { + + 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 ++ 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()) { ++ player.resetAttackStrengthTicker(); ++ } ++ } else { ++ ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); ++ } ++ // Paper end + } + if (event.isCancelled()) { + return false; diff --git a/patches/server-remapped/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/patches/server-remapped/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch new file mode 100644 index 0000000000..025b5a9d8e --- /dev/null +++ b/patches/server-remapped/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 21 Apr 2020 03:51:53 -0400 +Subject: [PATCH] Allow multiple callbacks to schedule for Callback Executor + +ChunkMapDistance polls multiple entries for pendingChunkUpdates + +Each of these have the potential to move a chunk in and out of +"Loaded" state, which will result in multiple callbacks being +needed within a single tick of ChunkMapDistance + +Use an ArrayDeque to store this Queue + +We make sure to also implement a pattern that is recursion safe too. + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 97a582614ad28f9fa864ae9be4860658e5979214..6c7af93cead523830d32b007cc69b313e59abef1 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -160,24 +160,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final CallbackExecutor callbackExecutor = new CallbackExecutor(); + public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { + +- private Runnable queued; ++ // Paper start - replace impl with recursive safe multi entry queue ++ // it's possible to schedule multiple tasks currently, so it's vital we change this impl ++ // If we recurse into the executor again, we will append to another queue, ensuring task order consistency ++ private java.util.ArrayDeque queued = new java.util.ArrayDeque<>(); + + @Override + public void execute(Runnable runnable) { +- if (queued != null) { +- throw new IllegalStateException("Already queued"); ++ if (queued == null) { ++ queued = new java.util.ArrayDeque<>(); + } +- queued = runnable; ++ queued.add(runnable); + } + + @Override + public void run() { +- Runnable task = queued; ++ if (queued == null) { ++ return; ++ } ++ java.util.ArrayDeque queue = queued; + queued = null; +- if (task != null) { ++ Runnable task; ++ while ((task = queue.pollFirst()) != null) { + task.run(); + } + } ++ // Paper end + }; + // CraftBukkit end + diff --git a/patches/server-remapped/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch b/patches/server-remapped/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch new file mode 100644 index 0000000000..8997a0897d --- /dev/null +++ b/patches/server-remapped/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 23 Apr 2020 01:36:39 -0400 +Subject: [PATCH] Don't fire BlockFade on worldgen threads + +Caused a deadlock + +diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java +index 31b6c1333c7d0af28385e804e94348cef398748b..ac63c5bef5b35b158e57835d765bbdd15fc60664 100644 +--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java +@@ -93,6 +93,7 @@ public class FireBlock extends BaseFireBlock { + @Override + public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { + // CraftBukkit start ++ if (!(world instanceof ServerLevel)) return this.canSurvive(state, world, pos) ? (BlockState) this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)) : Blocks.AIR.defaultBlockState(); // Paper - don't fire events in world generation + if (!this.canSurvive(state, world, pos)) { + // Suppress during worldgen + if (!(world instanceof Level)) { +@@ -108,7 +109,7 @@ public class FireBlock extends BaseFireBlock { + return blockState.getHandle(); + } + } +- return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)); ++ return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)); // Paper - diff on change, see "don't fire events in world generation" + // CraftBukkit end + } + diff --git a/patches/server-remapped/0456-Add-phantom-creative-and-insomniac-controls.patch b/patches/server-remapped/0456-Add-phantom-creative-and-insomniac-controls.patch new file mode 100644 index 0000000000..9a052de409 --- /dev/null +++ b/patches/server-remapped/0456-Add-phantom-creative-and-insomniac-controls.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 25 Apr 2020 15:13:41 -0500 +Subject: [PATCH] Add phantom creative and insomniac controls + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index cd248eb6be663e8be33f2c3c6b06b77b6d5753a4..46ac6d91422423f1e03b86d3efa3241f2599000d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -625,4 +625,11 @@ public class PaperWorldConfig { + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); + } ++ ++ public boolean phantomIgnoreCreative = true; ++ public boolean phantomOnlyAttackInsomniacs = true; ++ private void phantomSettings() { ++ phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); ++ phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index e7facd849e3511c64b4ae44b34382f4a4985f2a4..8ce62148ebaeac9988e7c9d4b2f7ee57f58d883e 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -3,6 +3,9 @@ package net.minecraft.world.entity; + import com.google.common.base.Predicates; + import java.util.function.Predicate; + import javax.annotation.Nullable; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.stats.Stats; ++import net.minecraft.util.Mth; + import net.minecraft.world.Container; + import net.minecraft.world.Difficulty; + import net.minecraft.world.entity.player.Player; +@@ -31,10 +34,11 @@ public final class EntitySelector { + public static final Predicate NO_SPECTATORS = (entity) -> { + return !entity.isSpectator(); + }; ++ public static Predicate isInsomniac = (player) -> Mth.clamp(((ServerPlayer) player).getStats().getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper + + // Paper start + public static final Predicate affectsSpawning = (entity) -> { +- return !entity.isSpectator() && entity.isAlive() && (entity instanceof EntityPlayer) && ((EntityPlayer) entity).affectsSpawning; ++ return !entity.isSpectator() && entity.isAlive() && (entity instanceof ServerPlayer) && ((ServerPlayer) entity).affectsSpawning; + }; + // Paper end + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index e37137a2890330b92e05d6f76c46ffc99a527803..a40c23e824652cff59633b7c314e27ec9a515c07 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -262,6 +262,7 @@ public class Phantom extends FlyingMob implements Enemy { + Player entityhuman = (Player) iterator.next(); + + if (Phantom.this.canAttack((LivingEntity) entityhuman, TargetingConditions.DEFAULT)) { ++ if (!level.paperConfig.phantomOnlyAttackInsomniacs || EntitySelector.isInsomniac.test(entityhuman)) // Paper + Phantom.this.setGoalTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason + return true; + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +index 42effcbd3ca7c38a4e8b1aa835543ad243112a33..79504dc3448402e73b09c4232b1fd0488872cf68 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +@@ -53,7 +53,7 @@ public class PhantomSpawner implements CustomSpawner { + while (iterator.hasNext()) { + Player entityhuman = (Player) iterator.next(); + +- if (!entityhuman.isSpectator()) { ++ if (!entityhuman.isSpectator() && (!world.paperConfig.phantomIgnoreCreative || !entityhuman.isCreative())) { // Paper + BlockPos blockposition = entityhuman.blockPosition(); + + if (!world.dimensionType().hasSkyLight() || blockposition.getY() >= world.getSeaLevel() && world.canSeeSky(blockposition)) { diff --git a/patches/server-remapped/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/patches/server-remapped/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch new file mode 100644 index 0000000000..9e378d1d32 --- /dev/null +++ b/patches/server-remapped/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 25 Apr 2020 06:46:35 -0400 +Subject: [PATCH] Fix numerous item duplication issues and teleport issues + +This notably fixes the newest "Donkey Dupe", but also fixes a lot +of dupe bugs in general around nether portals and entity world transfer + +We also fix item duplication generically by anytime we clone an item +to drop it on the ground, destroy the source item. + +This avoid an itemstack ever existing twice in the world state pre +clean up stage. + +So even if something NEW comes up, it would be impossible to drop the +same item twice because the source was destroyed. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 34226102c50a4353c42e68917d41c44d251e602f..2b48c4a2b512c42bed2c767db90a28898c74286a 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1973,11 +1973,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } else { + // CraftBukkit start - Capture drops for death event + if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) { +- ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(stack)); ++ ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack)); // Paper - mirror so we can destroy it later + return null; + } + // CraftBukkit end +- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY() + (double) yOffset, this.getZ(), stack); ++ ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY() + (double) yOffset, this.getZ(), stack.copy()); // Paper - clone so we can destroy original ++ stack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe + + entityitem.setDefaultPickUpDelay(); + // CraftBukkit start +@@ -2625,6 +2626,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + @Nullable + public Entity teleportTo(ServerLevel worldserver, BlockPos location) { + // CraftBukkit end ++ // Paper start - fix bad state entities causing dupes ++ if (!isAlive() || !valid) { ++ LOGGER.warn("Illegal Entity Teleport " + this + " to " + worldserver + ":" + location, new Throwable()); ++ return null; ++ } ++ // Paper end + if (this.level instanceof ServerLevel && !this.removed) { + this.level.getProfiler().push("changeDimension"); + // CraftBukkit start +@@ -2645,6 +2652,11 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + // CraftBukkit end + + this.level.getProfiler().popPush("reloading"); ++ // Paper start - Change lead drop timing to prevent dupe ++ if (this instanceof Mob) { ++ ((Mob) this).dropLeash(true, true); // Paper drop lead ++ } ++ // Paper end + Entity entity = this.getType().create((Level) worldserver); + + if (entity != null) { +@@ -2658,10 +2670,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + // CraftBukkit start - Forward the CraftEntity to the new entity + this.getBukkitEntity().setHandle(entity); + entity.bukkitEntity = this.getBukkitEntity(); +- +- if (this instanceof Mob) { +- ((Mob) this).dropLeash(true, false); // Unleash to prevent duping of leads. +- } + // CraftBukkit end + } + +@@ -2786,7 +2794,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean canChangeDimensions() { +- return true; ++ return isAlive() && valid; // Paper + } + + 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/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 33d51852ed6fe3f5adcdecf8f405a23689f4265a..5714aa450ac09788bcf1c2790d4f1581c9a7c28b 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -598,7 +598,7 @@ public class ArmorStand extends LivingEntity { + for (i = 0; i < this.handItems.size(); ++i) { + itemstack = (ItemStack) this.handItems.get(i); + if (!itemstack.isEmpty()) { +- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe + this.handItems.set(i, ItemStack.EMPTY); + } + } +@@ -606,7 +606,7 @@ public class ArmorStand extends LivingEntity { + for (i = 0; i < this.armorItems.size(); ++i) { + itemstack = (ItemStack) this.armorItems.get(i); + if (!itemstack.isEmpty()) { +- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe + this.armorItems.set(i, ItemStack.EMPTY); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 7d9a3b65b2d6b294d3a11414289e64fac88665f0..87fe7f4f5ed70bf1b3dc1e2a392ba42a1f8f568b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -815,7 +815,8 @@ public class CraftEventFactory { + for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { + if (stack == null || stack.getType() == Material.AIR || stack.getAmount() == 0) continue; + +- world.dropItem(entity.getLocation(), stack); ++ world.dropItem(entity.getLocation(), stack); // Paper - note: dropItem already clones due to this being bukkit -> NMS ++ if (stack instanceof CraftItemStack) stack.setAmount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe, but don't nuke bukkit stacks of manually added items + } + + return event; diff --git a/patches/server-remapped/0458-Implement-Brigadier-Mojang-API.patch b/patches/server-remapped/0458-Implement-Brigadier-Mojang-API.patch new file mode 100644 index 0000000000..5504aee900 --- /dev/null +++ b/patches/server-remapped/0458-Implement-Brigadier-Mojang-API.patch @@ -0,0 +1,139 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 19 Apr 2020 18:15:29 -0400 +Subject: [PATCH] Implement Brigadier Mojang API + +Adds AsyncPlayerSendCommandsEvent + - Allows modifying on a per command basis what command data they see. + +Adds CommandRegisteredEvent + - Allows manipulating the CommandNode to add more children/metadata for the client + +diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java +index f74765f31bc7272724ee7fac0cc5a8c852550006..e1f4ffaa36bfffb7741c74b7a094e26a03a9a1e6 100644 +--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java ++++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java +@@ -37,7 +37,7 @@ import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + import com.mojang.brigadier.tree.CommandNode; // CraftBukkit + +-public class CommandSourceStack implements SharedSuggestionProvider { ++public class CommandSourceStack implements SharedSuggestionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource { // Paper + + public static final SimpleCommandExceptionType ERROR_NOT_PLAYER = new SimpleCommandExceptionType(new TranslatableComponent("permissions.requires.player")); + public static final SimpleCommandExceptionType ERROR_NOT_ENTITY = new SimpleCommandExceptionType(new TranslatableComponent("permissions.requires.entity")); +@@ -149,6 +149,25 @@ public class CommandSourceStack implements SharedSuggestionProvider { + return this.textName; + } + ++ // Paper start ++ @Override ++ public org.bukkit.entity.Entity getBukkitEntity() { ++ return getEntity() != null ? getEntity().getBukkitEntity() : null; ++ } ++ ++ @Override ++ public org.bukkit.World getBukkitWorld() { ++ return getLevel() != null ? getLevel().getWorld() : null; ++ } ++ ++ @Override ++ public org.bukkit.Location getBukkitLocation() { ++ Vec3 pos = getPosition(); ++ org.bukkit.World world = getBukkitWorld(); ++ return world != null && pos != null ? new org.bukkit.Location(world, pos.x, pos.y, pos.z) : null; ++ } ++ // Paper end ++ + @Override + public boolean hasPermission(int level) { + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index 8154d9327c5411bbfea3bfa4d99d57feab764664..c63033e3eb50423a7c32acfc0e705623cc4bec68 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -355,6 +355,7 @@ public class Commands { + bukkit.add(node.getName()); + } + // Paper start - Async command map building ++ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper + MinecraftServer.getServer().execute(() -> { + runSync(entityplayer, bukkit, rootcommandnode); + }); +@@ -362,6 +363,7 @@ public class Commands { + + private void runSync(ServerPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { + // Paper end - Async command map building ++ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper + PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); + event.getPlayer().getServer().getPluginManager().callEvent(event); + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 1bed6e69bf3cc1ab9b0c1259de4f643bf58371aa..5f12987b93f1578624626c4e911d1757dee3d45f 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -768,8 +768,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); + + this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { +- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer +- this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); ++ // Paper start ++ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); ++ suggestEvent.setCancelled(suggestions.isEmpty()); ++ if (!suggestEvent.callEvent()) return; ++ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), (com.mojang.brigadier.suggestion.Suggestions) suggestEvent.getSuggestions())); // CraftBukkit - decompile error // Paper ++ // Paper end + }); + }); + } +@@ -778,7 +782,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); + completions.forEach(builder::suggest); +- player.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), builder.buildFuture().join())); ++ com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); ++ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); ++ suggestEvent.setCancelled(suggestions.isEmpty()); ++ if (!suggestEvent.callEvent()) return; ++ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestEvent.getSuggestions())); + } + // Paper end - async tab completion + } +diff --git a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java +index f9a245503c8982d1756503a6179f3715d919d910..b17002abdb43e74da4eb61e65e45c5e0e1dc0f95 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java +@@ -17,7 +17,7 @@ import net.minecraft.commands.CommandSourceStack; + import org.bukkit.command.Command; + import org.bukkit.craftbukkit.CraftServer; + +-public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider { ++public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommand { // Paper + + private final CraftServer server; + private final Command command; +@@ -28,10 +28,19 @@ public class BukkitCommandWrapper implements com.mojang.brigadier.Command register(CommandDispatcher dispatcher, String label) { +- return dispatcher.register( +- LiteralArgumentBuilder.literal(label).requires(this).executes(this) +- .then(RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this)) +- ); ++ // Paper start - Expose Brigadier to Paper-MojangAPI ++ com.mojang.brigadier.tree.RootCommandNode root = dispatcher.getRoot(); ++ LiteralCommandNode literal = LiteralArgumentBuilder.literal(label).requires(this).executes(this).build(); ++ com.mojang.brigadier.tree.ArgumentCommandNode defaultArgs = RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this).build(); ++ literal.addChild(defaultArgs); ++ com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent event = new com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent<>(label, this, this.command, root, literal, defaultArgs); ++ if (!event.callEvent()) { ++ return null; ++ } ++ literal = event.getLiteral(); ++ root.addChild(literal); ++ return literal; ++ // Paper end + } + + @Override diff --git a/patches/server-remapped/0459-Villager-Restocks-API.patch b/patches/server-remapped/0459-Villager-Restocks-API.patch new file mode 100644 index 0000000000..49b6ff50fa --- /dev/null +++ b/patches/server-remapped/0459-Villager-Restocks-API.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: zbk +Date: Sun, 26 Apr 2020 23:49:01 -0400 +Subject: [PATCH] Villager Restocks API + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 4aa34320ef7d6c62ccb17734bfa61d406190b919..a83a7d37f3d769535161fda46fca6f71dcc4d515 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -112,7 +112,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + private long lastGossipDecayTime; + private int villagerXp; + private long lastRestockGameTime; +- private int numberOfRestocksToday; ++ private int numberOfRestocksToday; public int getRestocksToday(){ return this.numberOfRestocksToday; } public void setRestocksToday(int restocksToday){ this.numberOfRestocksToday = restocksToday; } // Paper OBFHELPER + private long lastRestockCheckDayTime; + private boolean assignProfessionWhenSpawned; + private static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.MOBS, MemoryModuleType.VISIBLE_MOBS, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.WALK_TARGET, new MemoryModuleType[]{MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +index 5a21e9447c3e0225b07144eec83c277dd101bfd5..d0b933cfd02b237bfe85011831dab6e8e966496e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +@@ -83,6 +83,18 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { + getHandle().setVillagerXp(experience); + } + ++ // Paper start ++ @Override ++ public int getRestocksToday() { ++ return getHandle().getRestocksToday(); ++ } ++ ++ @Override ++ public void setRestocksToday(int restocksToday) { ++ getHandle().setRestocksToday(restocksToday); ++ } ++ // Paper end ++ + @Override + public boolean sleep(Location location) { + Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/patches/server-remapped/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch b/patches/server-remapped/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch new file mode 100644 index 0000000000..34909e54c5 --- /dev/null +++ b/patches/server-remapped/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 2 May 2020 03:09:46 -0400 +Subject: [PATCH] Validate PickItem Packet and kick for invalid + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 5f12987b93f1578624626c4e911d1757dee3d45f..3f416479e23c60ec5b4b779cce9ab62c74865ac8 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -881,7 +881,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + @Override + public void handlePickItem(ServerboundPickItemPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); +- this.player.inventory.pickSlot(packet.getSlot()); ++ // Paper start - validate pick item position ++ if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.inventory.items.size())) { ++ ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); ++ this.disconnect("Invalid hotbar selection (Hacking?)"); ++ return; ++ } ++ this.player.inventory.pickSlot(packet.getSlot()); // Paper - Diff above if changed ++ // Paper end + this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, this.player.inventory.selected, this.player.inventory.getItem(this.player.inventory.selected))); + this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, packet.getSlot(), this.player.inventory.getItem(packet.getSlot()))); + this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.inventory.selected)); diff --git a/patches/server-remapped/0461-Expose-game-version.patch b/patches/server-remapped/0461-Expose-game-version.patch new file mode 100644 index 0000000000..9e0cf63bd9 --- /dev/null +++ b/patches/server-remapped/0461-Expose-game-version.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Fri, 1 May 2020 17:39:26 +0300 +Subject: [PATCH] Expose game version + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 43c37e660a8a7f9d326ad38e66f9aa7c53c7b87c..1bfe96443877e460d22513d59ebc3b5988e8eb43 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -514,6 +514,13 @@ public final class CraftServer implements Server { + return bukkitVersion; + } + ++ // Paper start - expose game version ++ @Override ++ public String getMinecraftVersion() { ++ return console.getServerVersion(); ++ } ++ // Paper end ++ + @Override + public List getOnlinePlayers() { + return this.playerView; diff --git a/patches/server-remapped/0462-Optimize-Voxel-Shape-Merging.patch b/patches/server-remapped/0462-Optimize-Voxel-Shape-Merging.patch new file mode 100644 index 0000000000..935b12df1e --- /dev/null +++ b/patches/server-remapped/0462-Optimize-Voxel-Shape-Merging.patch @@ -0,0 +1,175 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 May 2020 22:35:09 -0400 +Subject: [PATCH] Optimize Voxel Shape Merging + +This method shows up as super hot in profiler, and also a high "self" time. + +Upon analyzing, it appears most usages of this method fall down to the final +else statement of the nasty ternary. + +Upon even further analyzation, it appears then the majority of those have a +consistent list 1.... One with Infinity head and Tails. + +First optimization is to detect these infinite states and immediately return that +VoxelShapeMergerList so we can avoid testing the rest for most cases. + +Break the method into 2 to help the JVM promote inlining of this fast path. + +Then it was also noticed that VoxelShapeMergerList constructor is also a hotspot +with a high self time... + +Well, knowing that in most cases our list 1 is actualy the same value, it allows +us to know that with an infinite list1, the result on the merger is essentially +list2 as the final values. + +This let us analyze the 2 potential states (Infinite with 2 sources or 4 sources) +and compute a deterministic result for the MergerList values. + +Additionally, this lets us avoid even allocating new objects for this too, further +reducing memory usage. + +diff --git a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java +index f0e74daa5bb9e88c028225e7c71deb04c481a7ac..abbe05b07831423eccf8779e854251dec5fbc2ae 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java +@@ -6,10 +6,16 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; + + public final class IndirectMerger implements IndexMerger { + +- private final DoubleArrayList result; ++ private final DoubleList a; // Paper + private final IntArrayList firstIndices; + private final IntArrayList secondIndices; + ++ // Paper start ++ private static final IntArrayList INFINITE_B_1 = new IntArrayList(new int[]{1, 1}); ++ private static final IntArrayList INFINITE_B_0 = new IntArrayList(new int[]{0, 0}); ++ private static final IntArrayList INFINITE_C = new IntArrayList(new int[]{0, 1}); ++ // Paper end ++ + protected IndirectMerger(DoubleList first, DoubleList second, boolean includeFirstOnly, boolean includeSecondOnly) { + int i = 0; + int j = 0; +@@ -18,7 +24,23 @@ public final class IndirectMerger implements IndexMerger { + int l = second.size(); + int i1 = k + l; + +- this.result = new DoubleArrayList(i1); ++ // Paper start - optimize common path of infinity doublelist ++ int size = first.size(); ++ double tail = first.getDouble(size - 1); ++ double head = first.getDouble(0); ++ if (head == Double.NEGATIVE_INFINITY && tail == Double.POSITIVE_INFINITY && !includeFirstOnly && !includeSecondOnly && (size == 2 || size == 4)) { ++ this.a = second; ++ if (size == 2) { ++ this.firstIndices = INFINITE_B_0; ++ } else { ++ this.firstIndices = INFINITE_B_1; ++ } ++ this.secondIndices = INFINITE_C; ++ return; ++ } ++ // Paper end ++ ++ this.a = new DoubleArrayList(i1); + this.firstIndices = new IntArrayList(i1); + this.secondIndices = new IntArrayList(i1); + +@@ -27,8 +49,8 @@ public final class IndirectMerger implements IndexMerger { + boolean flag3 = j < l; + + if (!flag2 && !flag3) { +- if (this.result.isEmpty()) { +- this.result.add(Math.min(first.getDouble(k - 1), second.getDouble(l - 1))); ++ if (this.a.isEmpty()) { ++ this.a.add(Math.min(first.getDouble(k - 1), second.getDouble(l - 1))); + } + + return; +@@ -41,9 +63,9 @@ public final class IndirectMerger implements IndexMerger { + if (!(d0 >= d1 - 1.0E-7D)) { // Paper - decompile error - welcome to hell + this.firstIndices.add(i - 1); + this.secondIndices.add(j - 1); +- this.result.add(d1); ++ this.a.add(d1); + d0 = d1; +- } else if (!this.result.isEmpty()) { ++ } else if (!this.a.isEmpty()) { + this.firstIndices.set(this.firstIndices.size() - 1, i - 1); + this.secondIndices.set(this.secondIndices.size() - 1, j - 1); + } +@@ -53,7 +75,7 @@ public final class IndirectMerger implements IndexMerger { + + @Override + public boolean forMergedIndexes(IndexMerger.IndexConsumer predicate) { +- for (int i = 0; i < this.result.size() - 1; ++i) { ++ for (int i = 0; i < this.a.size() - 1; ++i) { + if (!predicate.merge(this.firstIndices.getInt(i), this.secondIndices.getInt(i), i)) { + return false; + } +@@ -64,6 +86,6 @@ public final class IndirectMerger implements IndexMerger { + + @Override + public DoubleList getList() { +- return this.result; ++ return this.a; + } + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index c14d5ebe16a693834ed218af8f737714065b2e17..1603eb3f7d90a4b3a028b20776566db77d09c123 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -329,19 +329,46 @@ public final class Shapes { + } + + @VisibleForTesting +- protected static IndexMerger createIndexMerger(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { +- int j = first.size() - 1; +- int k = second.size() - 1; ++ private static IndexMerger createIndexMerger(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { // Paper - private ++ // Paper start - fast track the most common scenario ++ // doublelist is usually a DoubleArrayList with Infinite head/tails that falls to the final else clause ++ // This is actually the most common path, so jump to it straight away ++ if (first.getDouble(0) == Double.NEGATIVE_INFINITY && first.getDouble(first.size() - 1) == Double.POSITIVE_INFINITY) { ++ return new IndirectMerger(first, second, includeFirst, includeSecond); ++ } ++ // Split out rest to hopefully inline the above ++ return lessCommonMerge(size, first, second, includeFirst, includeSecond); ++ } ++ ++ private static IndexMerger lessCommonMerge(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { ++ int j = doublelist.size() - 1; ++ int k = doublelist1.size() - 1; ++ // Paper note - Rewrite below as optimized order if instead of nasty ternary + +- if (first instanceof CubePointRange && second instanceof CubePointRange) { ++ if (doublelist instanceof CubePointRange && doublelist1 instanceof CubePointRange) { + long l = lcm(j, k); + +- if ((long) size * l <= 256L) { ++ if ((long) i * l <= 256L) { + return new DiscreteCubeMerger(j, k); + } + } + +- return (IndexMerger) (first.getDouble(j) < second.getDouble(0) - 1.0E-7D ? new NonOverlappingMerger(first, second, false) : (second.getDouble(k) < first.getDouble(0) - 1.0E-7D ? new NonOverlappingMerger(second, first, true) : (j == k && Objects.equals(first, second) ? (first instanceof IdenticalMerger ? (IndexMerger) first : (second instanceof IdenticalMerger ? (IndexMerger) second : new IdenticalMerger(first))) : new IndirectMerger(first, second, includeFirst, includeSecond)))); ++ // Identical happens more often than Disjoint ++ if (j == k && Objects.equals(doublelist, doublelist1)) { ++ if (doublelist instanceof IdenticalMerger) { ++ return (IndexMerger) doublelist; ++ } else if (doublelist1 instanceof IdenticalMerger) { ++ return (IndexMerger) doublelist1; ++ } ++ return new IdenticalMerger(doublelist); ++ } else if (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-07) { ++ return new NonOverlappingMerger(doublelist, doublelist1, false); ++ } else if (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-07) { ++ return new NonOverlappingMerger(doublelist1, doublelist, true); ++ } else { ++ return new IndirectMerger(doublelist, doublelist1, flag, flag1); ++ } ++ // Paper end + } + + public interface DoubleLineConsumer { diff --git a/patches/server-remapped/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/patches/server-remapped/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch new file mode 100644 index 0000000000..d35e663567 --- /dev/null +++ b/patches/server-remapped/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 4 May 2020 01:08:56 -0400 +Subject: [PATCH] Set cap on JDK per-thread native byte buffer cache + +See: https://www.evanjones.ca/java-bytebuffer-leak.html + +This is potentially a source of lots of native memory usage. + +We are clearly seeing native usage upwards to 1-4GB which doesn't make sense. + +Region File usage fixed in previous patch should of tecnically only been somewhat +temporary until GC finally gets it some time later, but between all the various +plugins doing IO on various threads, this hidden detail of the JDK could be +keeping long lived large direct buffers in cache. + +Set system properly at server startup if not set already to help protect from this. + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index c288b89bf5a22269823ba1d18af217032d7c6a36..bd10345cb90f98b8af1519afd603a5244f3a5ca2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -28,6 +28,7 @@ public class Main { + } + // Paper end + // Todo: Installation script ++ if (System.getProperty("jdk.nio.maxCachedBufferSize") == null) System.setProperty("jdk.nio.maxCachedBufferSize", "262144"); // Paper - cap per-thread NIO cache size + OptionParser parser = new OptionParser() { + { + acceptsAll(asList("?", "help"), "Show the help"); diff --git a/patches/server-remapped/0464-Implement-Mob-Goal-API.patch b/patches/server-remapped/0464-Implement-Mob-Goal-API.patch new file mode 100644 index 0000000000..0aaed21f24 --- /dev/null +++ b/patches/server-remapped/0464-Implement-Mob-Goal-API.patch @@ -0,0 +1,1104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Fri, 3 Jan 2020 16:26:19 +0100 +Subject: [PATCH] Implement Mob Goal API + + +diff --git a/pom.xml b/pom.xml +index 4c8a057e790c96b0ab5123549d0566371acacb46..1a9204c869dd36e80932b1366352db15ebd70723 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -176,6 +176,13 @@ + 1.3 + test + ++ ++ ++ io.github.classgraph ++ classgraph ++ 4.8.47 ++ test ++ + + + +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6ddb198f86ccf3bc2471752d5fb2f59d9a7ab4df +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java +@@ -0,0 +1,462 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import GoalKey; ++import GoalType; ++import com.destroystokyo.paper.entity.RangedEntity; ++import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; ++import com.google.common.collect.BiMap; ++import com.google.common.collect.HashBiMap; ++import java.lang.reflect.Constructor; ++import java.util.EnumSet; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.Map; ++import java.util.Set; ++import net.minecraft.world.entity.AgableMob; ++import net.minecraft.world.entity.FlyingMob; ++import net.minecraft.world.entity.PathfinderMob; ++import net.minecraft.world.entity.TamableAnimal; ++import net.minecraft.world.entity.ai.goal.Goal; ++import net.minecraft.world.entity.ambient.AmbientCreature; ++import net.minecraft.world.entity.animal.AbstractFish; ++import net.minecraft.world.entity.animal.AbstractGolem; ++import net.minecraft.world.entity.animal.AbstractSchoolingFish; ++import net.minecraft.world.entity.animal.Animal; ++import net.minecraft.world.entity.animal.Pufferfish; ++import net.minecraft.world.entity.animal.ShoulderRidingEntity; ++import net.minecraft.world.entity.animal.SnowGolem; ++import net.minecraft.world.entity.animal.WaterAnimal; ++import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; ++import net.minecraft.world.entity.boss.wither.WitherBoss; ++import net.minecraft.world.entity.monster.AbstractIllager; ++import net.minecraft.world.entity.monster.AbstractSkeleton; ++import net.minecraft.world.entity.monster.EnderMan; ++import net.minecraft.world.entity.monster.PatrollingMonster; ++import net.minecraft.world.entity.monster.RangedAttackMob; ++import net.minecraft.world.entity.monster.SpellcasterIllager; ++import net.minecraft.world.entity.monster.ZombifiedPiglin; ++import net.minecraft.world.entity.monster.piglin.AbstractPiglin; ++import org.bukkit.NamespacedKey; ++import org.bukkit.entity.AbstractHorse; ++import org.bukkit.entity.AbstractVillager; ++import org.bukkit.entity.Ageable; ++import org.bukkit.entity.Ambient; ++import org.bukkit.entity.Animals; ++import org.bukkit.entity.Bat; ++import org.bukkit.entity.Bee; ++import org.bukkit.entity.Blaze; ++import org.bukkit.entity.Cat; ++import org.bukkit.entity.CaveSpider; ++import org.bukkit.entity.ChestedHorse; ++import org.bukkit.entity.Chicken; ++import org.bukkit.entity.Cod; ++import org.bukkit.entity.Cow; ++import org.bukkit.entity.Creature; ++import org.bukkit.entity.Creeper; ++import org.bukkit.entity.Dolphin; ++import org.bukkit.entity.Donkey; ++import org.bukkit.entity.Drowned; ++import org.bukkit.entity.ElderGuardian; ++import org.bukkit.entity.EnderDragon; ++import org.bukkit.entity.Enderman; ++import org.bukkit.entity.Endermite; ++import org.bukkit.entity.Evoker; ++import org.bukkit.entity.Fish; ++import org.bukkit.entity.Flying; ++import org.bukkit.entity.Fox; ++import org.bukkit.entity.Ghast; ++import org.bukkit.entity.Giant; ++import org.bukkit.entity.Golem; ++import org.bukkit.entity.Guardian; ++import org.bukkit.entity.Hoglin; ++import org.bukkit.entity.Horse; ++import org.bukkit.entity.Husk; ++import org.bukkit.entity.Illager; ++import org.bukkit.entity.Illusioner; ++import org.bukkit.entity.IronGolem; ++import org.bukkit.entity.Llama; ++import org.bukkit.entity.MagmaCube; ++import org.bukkit.entity.Mob; ++import org.bukkit.entity.Monster; ++import org.bukkit.entity.Mule; ++import org.bukkit.entity.MushroomCow; ++import org.bukkit.entity.Ocelot; ++import org.bukkit.entity.Panda; ++import org.bukkit.entity.Parrot; ++import org.bukkit.entity.Phantom; ++import org.bukkit.entity.Pig; ++import org.bukkit.entity.PigZombie; ++import org.bukkit.entity.Piglin; ++import org.bukkit.entity.PiglinAbstract; ++import org.bukkit.entity.PiglinBrute; ++import org.bukkit.entity.Pillager; ++import org.bukkit.entity.PolarBear; ++import org.bukkit.entity.PufferFish; ++import org.bukkit.entity.Rabbit; ++import org.bukkit.entity.Raider; ++import org.bukkit.entity.Ravager; ++import org.bukkit.entity.Salmon; ++import org.bukkit.entity.Sheep; ++import org.bukkit.entity.Shulker; ++import org.bukkit.entity.Silverfish; ++import org.bukkit.entity.Skeleton; ++import org.bukkit.entity.SkeletonHorse; ++import org.bukkit.entity.Slime; ++import org.bukkit.entity.Snowman; ++import org.bukkit.entity.Spellcaster; ++import org.bukkit.entity.Spider; ++import org.bukkit.entity.Squid; ++import org.bukkit.entity.Stray; ++import org.bukkit.entity.Strider; ++import org.bukkit.entity.Tameable; ++import org.bukkit.entity.TraderLlama; ++import org.bukkit.entity.TropicalFish; ++import org.bukkit.entity.Turtle; ++import org.bukkit.entity.Vex; ++import org.bukkit.entity.Villager; ++import org.bukkit.entity.Vindicator; ++import org.bukkit.entity.WanderingTrader; ++import org.bukkit.entity.WaterMob; ++import org.bukkit.entity.Witch; ++import org.bukkit.entity.Wither; ++import org.bukkit.entity.WitherSkeleton; ++import org.bukkit.entity.Wolf; ++import org.bukkit.entity.Zoglin; ++import org.bukkit.entity.Zombie; ++import org.bukkit.entity.ZombieHorse; ++import org.bukkit.entity.ZombieVillager; ++ ++public class MobGoalHelper { ++ ++ private static final BiMap deobfuscationMap = HashBiMap.create(); ++ private static final Map, Class> entityClassCache = new HashMap<>(); ++ private static final Map, Class> bukkitMap = new HashMap<>(); ++ ++ static final Set ignored = new HashSet<>(); ++ ++ static { ++ // TODO these kinda should be checked on each release, in case obfuscation changes ++ deobfuscationMap.put("bee_b", "bee_attack"); ++ deobfuscationMap.put("bee_c", "bee_become_angry"); ++ deobfuscationMap.put("bee_d", "bee_enter_hive"); ++ deobfuscationMap.put("bee_e", "bee_go_to_hive"); ++ deobfuscationMap.put("bee_f", "bee_go_to_known_flower"); ++ deobfuscationMap.put("bee_g", "bee_grow_crop"); ++ deobfuscationMap.put("bee_h", "bee_hurt_by_other"); ++ deobfuscationMap.put("bee_i", "bee_locate_hive"); ++ deobfuscationMap.put("bee_k", "bee_pollinate"); ++ deobfuscationMap.put("bee_l", "bee_wander"); ++ deobfuscationMap.put("cat_a", "cat_avoid_entity"); ++ deobfuscationMap.put("cat_b", "cat_relax_on_owner"); ++ deobfuscationMap.put("dolphin_b", "dolphin_swim_to_treasure"); ++ deobfuscationMap.put("dolphin_c", "dolphin_swim_with_player"); ++ deobfuscationMap.put("dolphin_d", "dolphin_play_with_items"); ++ deobfuscationMap.put("drowned_a", "drowned_attack"); ++ deobfuscationMap.put("drowned_b", "drowned_goto_beach"); ++ deobfuscationMap.put("drowned_c", "drowned_goto_water"); ++ deobfuscationMap.put("drowned_e", "drowned_swim_up"); ++ deobfuscationMap.put("drowned_f", "drowned_trident_attack"); ++ deobfuscationMap.put("enderman_a", "enderman_freeze_when_looked_at"); ++ deobfuscationMap.put("evoker_a", "evoker_attack_spell"); ++ deobfuscationMap.put("evoker_b", "evoker_cast_spell"); ++ deobfuscationMap.put("evoker_c", "evoker_summon_spell"); ++ deobfuscationMap.put("evoker_d", "evoker_wololo_spell"); ++ deobfuscationMap.put("fish_b", "fish_swim"); ++ deobfuscationMap.put("fox_a", "fox_defend_trusted"); ++ deobfuscationMap.put("fox_b", "fox_faceplant"); ++ deobfuscationMap.put("fox_e", "fox_breed"); ++ deobfuscationMap.put("fox_f", "fox_eat_berries"); ++ deobfuscationMap.put("fox_g", "fox_float"); ++ deobfuscationMap.put("fox_h", "fox_follow_parent"); ++ deobfuscationMap.put("fox_j", "fox_look_at_player"); ++ deobfuscationMap.put("fox_l", "fox_melee_attack"); ++ deobfuscationMap.put("fox_n", "fox_panic"); ++ deobfuscationMap.put("fox_o", "fox_pounce"); ++ deobfuscationMap.put("fox_p", "fox_search_for_items"); ++ deobfuscationMap.put("fox_q", "fox_stroll_through_village"); ++ deobfuscationMap.put("fox_r", "fox_perch_and_search"); ++ deobfuscationMap.put("fox_s", "fox_seek_shelter"); ++ deobfuscationMap.put("fox_t", "fox_sleep"); ++ deobfuscationMap.put("fox_u", "fox_stalk_prey"); ++ deobfuscationMap.put("illager_abstract_b", "raider_open_door"); ++ deobfuscationMap.put("illager_illusioner_a", "illusioner_blindness_spell"); ++ deobfuscationMap.put("illager_illusioner_b", "illusioner_mirror_spell"); ++ deobfuscationMap.put("illager_wizard_b", "spellcaster_cast_spell"); ++ deobfuscationMap.put("llama_a", "llama_attack_wolf"); ++ deobfuscationMap.put("llama_c", "llama_hurt_by"); ++ deobfuscationMap.put("llama_trader_a", "llamatrader_defended_wandering_trader"); ++ deobfuscationMap.put("monster_patrolling_a", "long_distance_patrol"); ++ deobfuscationMap.put("ocelot_a", "ocelot_avoid_entity"); ++ deobfuscationMap.put("ocelot_b", "ocelot_tempt"); ++ deobfuscationMap.put("panda_b", "panda_attack"); ++ deobfuscationMap.put("panda_c", "panda_avoid"); ++ deobfuscationMap.put("panda_d", "panda_breed"); ++ deobfuscationMap.put("panda_e", "panda_hurt_by_target"); ++ deobfuscationMap.put("panda_f", "panda_lie_on_back"); ++ deobfuscationMap.put("panda_g", "panda_look_at_player"); ++ deobfuscationMap.put("panda_i", "panda_panic"); ++ deobfuscationMap.put("panda_j", "panda_roll"); ++ deobfuscationMap.put("panda_k", "panda_sit"); ++ deobfuscationMap.put("panda_l", "panda_sneeze"); ++ deobfuscationMap.put("phantom_b", "phantom_attack_player"); ++ deobfuscationMap.put("phantom_c", "phantom_attack_strategy"); ++ deobfuscationMap.put("phantom_e", "phantom_circle_around_anchor"); ++ deobfuscationMap.put("phantom_i", "phantom_sweep_attack"); ++ deobfuscationMap.put("polar_bear_a", "polarbear_attack_players"); ++ deobfuscationMap.put("polar_bear_b", "polarbear_hurt_by"); ++ deobfuscationMap.put("polar_bear_c", "polarbear_melee"); ++ deobfuscationMap.put("polar_bear_d", "polarbear_panic"); ++ deobfuscationMap.put("puffer_fish_a", "pufferfish_puff"); ++ deobfuscationMap.put("raider_a", "raider_hold_ground"); ++ deobfuscationMap.put("raider_b", "raider_obtain_banner"); ++ deobfuscationMap.put("raider_c", "raider_celebration"); ++ deobfuscationMap.put("raider_d", "raider_move_through_village"); ++ deobfuscationMap.put("ravager_a", "ravager_melee_attack"); ++ deobfuscationMap.put("shulker_a", "shulker_attack"); ++ deobfuscationMap.put("shulker_c", "shulker_defense"); ++ deobfuscationMap.put("shulker_d", "shulker_nearest"); ++ deobfuscationMap.put("shulker_e", "shulker_peek"); ++ deobfuscationMap.put("squid_a", "squid_flee"); ++ deobfuscationMap.put("skeleton_abstract_1", "skeleton_melee"); ++ deobfuscationMap.put("strider_a", "strider_go_to_lava"); ++ deobfuscationMap.put("turtle_a", "turtle_breed"); ++ deobfuscationMap.put("turtle_b", "turtle_go_home"); ++ deobfuscationMap.put("turtle_c", "turtle_goto_water"); ++ deobfuscationMap.put("turtle_d", "turtle_lay_egg"); ++ deobfuscationMap.put("turtle_f", "turtle_panic"); ++ deobfuscationMap.put("turtle_h", "turtle_random_stroll"); ++ deobfuscationMap.put("turtle_i", "turtle_tempt"); ++ deobfuscationMap.put("turtle_j", "turtle_travel"); ++ deobfuscationMap.put("vex_a", "vex_charge_attack"); ++ deobfuscationMap.put("vex_b", "vex_copy_target_of_owner"); ++ deobfuscationMap.put("vex_d", "vex_random_move"); ++ deobfuscationMap.put("villager_trader_a", "villagertrader_wander_to_position"); ++ deobfuscationMap.put("vindicator_a", "vindicator_break_door"); ++ deobfuscationMap.put("vindicator_b", "vindicator_johnny_attack"); ++ deobfuscationMap.put("vindicator_c", "vindicator_melee_attack"); ++ deobfuscationMap.put("wither_a", "wither_do_nothing"); ++ deobfuscationMap.put("wolf_a", "wolf_avoid_entity"); ++ deobfuscationMap.put("zombie_a", "zombie_attack_turtle_egg"); ++ ++ ignored.add("selector_1"); ++ ignored.add("selector_2"); ++ ignored.add("wrapped"); ++ ++ bukkitMap.put(net.minecraft.world.entity.Mob.class, Mob.class); ++ bukkitMap.put(AgableMob.class, Ageable.class); ++ bukkitMap.put(AmbientCreature.class, Ambient.class); ++ bukkitMap.put(Animal.class, Animals.class); ++ bukkitMap.put(net.minecraft.world.entity.ambient.Bat.class, Bat.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Bee.class, Bee.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Blaze.class, Blaze.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Cat.class, Cat.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.CaveSpider.class, CaveSpider.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Chicken.class, Chicken.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Cod.class, Cod.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Cow.class, Cow.class); ++ bukkitMap.put(PathfinderMob.class, Creature.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Creeper.class, Creeper.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Dolphin.class, Dolphin.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Drowned.class, Drowned.class); ++ bukkitMap.put(net.minecraft.world.entity.boss.enderdragon.EnderDragon.class, EnderDragon.class); ++ bukkitMap.put(EnderMan.class, Enderman.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Endermite.class, Endermite.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Evoker.class, Evoker.class); ++ bukkitMap.put(AbstractFish.class, Fish.class); ++ bukkitMap.put(AbstractSchoolingFish.class, Fish.class); // close enough ++ bukkitMap.put(FlyingMob.class, Flying.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Fox.class, Fox.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Ghast.class, Ghast.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Giant.class, Giant.class); ++ bukkitMap.put(AbstractGolem.class, Golem.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Guardian.class, Guardian.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.ElderGuardian.class, ElderGuardian.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.Horse.class, Horse.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.AbstractHorse.class, AbstractHorse.class); ++ bukkitMap.put(AbstractChestedHorse.class, ChestedHorse.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.Donkey.class, Donkey.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.Mule.class, Mule.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.SkeletonHorse.class, SkeletonHorse.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.ZombieHorse.class, ZombieHorse.class); ++ bukkitMap.put(AbstractIllager.class, Illager.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Illusioner.class, Illusioner.class); ++ bukkitMap.put(SpellcasterIllager.class, Spellcaster.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.IronGolem.class, IronGolem.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.Llama.class, Llama.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.TraderLlama.class, TraderLlama.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.MagmaCube.class, MagmaCube.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Monster.class, Monster.class); ++ bukkitMap.put(PatrollingMonster.class, Monster.class); // close enough ++ bukkitMap.put(net.minecraft.world.entity.animal.MushroomCow.class, MushroomCow.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Ocelot.class, Ocelot.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Panda.class, Panda.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Parrot.class, Parrot.class); ++ bukkitMap.put(ShoulderRidingEntity.class, Parrot.class); // close enough ++ bukkitMap.put(net.minecraft.world.entity.monster.Phantom.class, Phantom.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Pig.class, Pig.class); ++ bukkitMap.put(ZombifiedPiglin.class, PigZombie.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Pillager.class, Pillager.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.PolarBear.class, PolarBear.class); ++ bukkitMap.put(Pufferfish.class, PufferFish.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Rabbit.class, Rabbit.class); ++ bukkitMap.put(net.minecraft.world.entity.raid.Raider.class, Raider.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Ravager.class, Ravager.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Salmon.class, Salmon.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Sheep.class, Sheep.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Shulker.class, Shulker.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Silverfish.class, Silverfish.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Skeleton.class, Skeleton.class); ++ bukkitMap.put(AbstractSkeleton.class, Skeleton.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Stray.class, Stray.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.WitherSkeleton.class, WitherSkeleton.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Slime.class, Slime.class); ++ bukkitMap.put(SnowGolem.class, Snowman.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Spider.class, Spider.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Squid.class, Squid.class); ++ bukkitMap.put(TamableAnimal.class, Tameable.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.TropicalFish.class, TropicalFish.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Turtle.class, Turtle.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Vex.class, Vex.class); ++ bukkitMap.put(net.minecraft.world.entity.npc.Villager.class, Villager.class); ++ bukkitMap.put(net.minecraft.world.entity.npc.AbstractVillager.class, AbstractVillager.class); ++ bukkitMap.put(net.minecraft.world.entity.npc.WanderingTrader.class, WanderingTrader.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Vindicator.class, Vindicator.class); ++ bukkitMap.put(WaterAnimal.class, WaterMob.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Witch.class, Witch.class); ++ bukkitMap.put(WitherBoss.class, Wither.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Wolf.class, Wolf.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Zombie.class, Zombie.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Husk.class, Husk.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.ZombieVillager.class, ZombieVillager.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.hoglin.Hoglin.class, Hoglin.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.piglin.Piglin.class, Piglin.class); ++ bukkitMap.put(AbstractPiglin.class, PiglinAbstract.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.piglin.PiglinBrute.class, PiglinBrute.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Strider.class, Strider.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Zoglin.class, Zoglin.class); ++ } ++ ++ public static String getUsableName(Class clazz) { ++ String name = clazz.getName(); ++ name = name.substring(name.lastIndexOf(".") + 1); ++ boolean flag = false; ++ // inner classes ++ if (name.contains("$")) { ++ String cut = name.substring(name.indexOf("$") + 1); ++ if (cut.length() <= 2) { ++ name = name.replace("Entity", ""); ++ name = name.replace("$", "_"); ++ flag = true; ++ } else { ++ // mapped, wooo ++ name = cut; ++ } ++ } ++ name = name.replace("PathfinderGoal", ""); ++ StringBuilder sb = new StringBuilder(); ++ for (char c : name.toCharArray()) { ++ if (c >= 'A' && c <= 'Z') { ++ sb.append("_"); ++ sb.append(Character.toLowerCase(c)); ++ } else { ++ sb.append(c); ++ } ++ } ++ name = sb.toString(); ++ name = name.replaceFirst("_", ""); ++ ++ if (flag && !deobfuscationMap.containsKey(name.toLowerCase()) && !ignored.contains(name)) { ++ System.out.println("need to map " + clazz.getName() + " (" + name.toLowerCase() + ")"); ++ } ++ ++ // did we rename this key? ++ return deobfuscationMap.getOrDefault(name, name); ++ } ++ ++ public static EnumSet vanillaToPaper(OptimizedSmallEnumSet types) { ++ EnumSet goals = EnumSet.noneOf(GoalType.class); ++ for (GoalType type : GoalType.values()) { ++ if (types.hasElement(paperToVanilla(type))) { ++ goals.add(type); ++ } ++ } ++ return goals; ++ } ++ ++ public static GoalType vanillaToPaper(Goal.Flag type) { ++ switch (type) { ++ case MOVE: ++ return GoalType.MOVE; ++ case LOOK: ++ return GoalType.LOOK; ++ case JUMP: ++ return GoalType.JUMP; ++ case UNKNOWN_BEHAVIOR: ++ return GoalType.UNKNOWN_BEHAVIOR; ++ case TARGET: ++ return GoalType.TARGET; ++ default: ++ throw new IllegalArgumentException("Unknown vanilla mob goal type " + type.name()); ++ } ++ } ++ ++ public static EnumSet paperToVanilla(EnumSet types) { ++ EnumSet goals = EnumSet.noneOf(Goal.Flag.class); ++ for (GoalType type : types) { ++ goals.add(paperToVanilla(type)); ++ } ++ return goals; ++ } ++ ++ public static Goal.Flag paperToVanilla(GoalType type) { ++ switch (type) { ++ case MOVE: ++ return Goal.Flag.MOVE; ++ case LOOK: ++ return Goal.Flag.LOOK; ++ case JUMP: ++ return Goal.Flag.JUMP; ++ case UNKNOWN_BEHAVIOR: ++ return Goal.Flag.UNKNOWN_BEHAVIOR; ++ case TARGET: ++ return Goal.Flag.TARGET; ++ default: ++ throw new IllegalArgumentException("Unknown paper mob goal type " + type.name()); ++ } ++ } ++ ++ public static GoalKey getKey(Class goalClass) { ++ String name = getUsableName(goalClass); ++ if (ignored.contains(name)) { ++ //noinspection unchecked ++ return (GoalKey) GoalKey.of(Mob.class, NamespacedKey.minecraft(name)); ++ } ++ return GoalKey.of(getEntity(goalClass), NamespacedKey.minecraft(name)); ++ } ++ ++ public static Class getEntity(Class goalClass) { ++ //noinspection unchecked ++ return (Class) entityClassCache.computeIfAbsent(goalClass, key -> { ++ for (Constructor ctor : key.getDeclaredConstructors()) { ++ for (int i = 0; i < ctor.getParameterCount(); i++) { ++ Class param = ctor.getParameterTypes()[i]; ++ if (net.minecraft.world.entity.Mob.class.isAssignableFrom(param)) { ++ //noinspection unchecked ++ return toBukkitClass((Class) param); ++ } else if (RangedAttackMob.class.isAssignableFrom(param)) { ++ return RangedEntity.class; ++ } ++ } ++ } ++ throw new RuntimeException("Can't figure out applicable entity for mob goal " + goalClass); // maybe just return EntityInsentient? ++ }); ++ } ++ ++ public static Class toBukkitClass(Class nmsClass) { ++ Class bukkitClass = bukkitMap.get(nmsClass); ++ if (bukkitClass == null) { ++ throw new RuntimeException("Can't figure out applicable bukkit entity for nms entity " + nmsClass); // maybe just return Mob? ++ } ++ return bukkitClass; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java +new file mode 100644 +index 0000000000000000000000000000000000000000..14ddf844be10c04522aa3ec125fa7a0f540b10c2 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java +@@ -0,0 +1,55 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import GoalKey; ++import net.minecraft.world.entity.ai.goal.Goal; ++import org.bukkit.entity.Mob; ++ ++/** ++ * Wraps api in vanilla ++ */ ++public class PaperCustomGoal extends Goal { ++ ++ private final Goal handle; ++ ++ public PaperCustomGoal(Goal handle) { ++ this.handle = handle; ++ ++ this.setTypes(MobGoalHelper.paperToVanilla(handle.getTypes())); ++ if (this.getGoalTypes().size() == 0) { ++ this.getGoalTypes().addUnchecked(Flag.UNKNOWN_BEHAVIOR); ++ } ++ } ++ ++ @Override ++ public boolean shouldActivate() { ++ return handle.shouldActivate(); ++ } ++ ++ @Override ++ public boolean shouldStayActive() { ++ return handle.shouldStayActive(); ++ } ++ ++ @Override ++ public void start() { ++ handle.start(); ++ } ++ ++ @Override ++ public void onTaskReset() { ++ handle.stop(); ++ } ++ ++ @Override ++ public void tick() { ++ handle.tick(); ++ } ++ ++ public Goal getHandle() { ++ return handle; ++ } ++ ++ public GoalKey getKey() { ++ return handle.getKey(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java +new file mode 100644 +index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959e82e4ab1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java +@@ -0,0 +1,222 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import java.util.Collection; ++import java.util.EnumSet; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.LinkedList; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import net.minecraft.world.entity.ai.goal.Goal; ++import net.minecraft.world.entity.ai.goal.GoalSelector; ++import net.minecraft.world.entity.ai.goal.WrappedGoal; ++import org.bukkit.craftbukkit.entity.CraftMob; ++import org.bukkit.entity.Mob; ++ ++public class PaperMobGoals implements MobGoals { ++ ++ private final Map> instanceCache = new HashMap<>(); ++ ++ @Override ++ public void addGoal(T mob, int priority, Goal goal) { ++ CraftMob craftMob = (CraftMob) mob; ++ getHandle(craftMob, goal.getTypes()).addGoal(priority, new PaperCustomGoal<>(goal)); ++ } ++ ++ @Override ++ public void removeGoal(T mob, Goal goal) { ++ CraftMob craftMob = (CraftMob) mob; ++ if (goal instanceof PaperCustomGoal) { ++ getHandle(craftMob, goal.getTypes()).removeGoal((Goal) goal); ++ } else if (goal instanceof PaperVanillaGoal) { ++ getHandle(craftMob, goal.getTypes()).removeGoal(((PaperVanillaGoal) goal).getHandle()); ++ } else { ++ List toRemove = new LinkedList<>(); ++ for (WrappedGoal item : getHandle(craftMob, goal.getTypes()).getTasks()) { ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ if (((PaperCustomGoal) item.getGoal()).getHandle() == goal) { ++ toRemove.add(item.getGoal()); ++ } ++ } ++ } ++ ++ for (Goal g : toRemove) { ++ getHandle(craftMob, goal.getTypes()).removeGoal(g); ++ } ++ } ++ } ++ ++ @Override ++ public void removeAllGoals(T mob) { ++ for (GoalType type : GoalType.values()) { ++ removeAllGoals(mob, type); ++ } ++ } ++ ++ @Override ++ public void removeAllGoals(T mob, GoalType type) { ++ for (Goal goal : getAllGoals(mob, type)) { ++ removeGoal(mob, goal); ++ } ++ } ++ ++ @Override ++ public void removeGoal(T mob, GoalKey key) { ++ for (Goal goal : getGoals(mob, key)) { ++ removeGoal(mob, goal); ++ } ++ } ++ ++ @Override ++ public boolean hasGoal(T mob, GoalKey key) { ++ for (Goal g : getAllGoals(mob)) { ++ if (g.getKey().equals(key)) { ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ @Override ++ public Goal getGoal(T mob, GoalKey key) { ++ for (Goal g : getAllGoals(mob)) { ++ if (g.getKey().equals(key)) { ++ return g; ++ } ++ } ++ return null; ++ } ++ ++ @Override ++ public Collection> getGoals(T mob, GoalKey key) { ++ Set> goals = new HashSet<>(); ++ for (Goal g : getAllGoals(mob)) { ++ if (g.getKey().equals(key)) { ++ goals.add(g); ++ } ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getAllGoals(T mob) { ++ Set> goals = new HashSet<>(); ++ for (GoalType type : GoalType.values()) { ++ goals.addAll(getAllGoals(mob, type)); ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getAllGoals(T mob, GoalType type) { ++ CraftMob craftMob = (CraftMob) mob; ++ Set> goals = new HashSet<>(); ++ for (WrappedGoal item : getHandle(craftMob, type).getTasks()) { ++ if (!item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { ++ continue; ++ } ++ ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); ++ } else { ++ //noinspection unchecked ++ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); ++ } ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getAllGoalsWithout(T mob, GoalType type) { ++ CraftMob craftMob = (CraftMob) mob; ++ Set> goals = new HashSet<>(); ++ for (GoalType internalType : GoalType.values()) { ++ if (internalType == type) { ++ continue; ++ } ++ for (WrappedGoal item : getHandle(craftMob, internalType).getTasks()) { ++ if (item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { ++ continue; ++ } ++ ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); ++ } else { ++ //noinspection unchecked ++ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); ++ } ++ } ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getRunningGoals(T mob) { ++ Set> goals = new HashSet<>(); ++ for (GoalType type : GoalType.values()) { ++ goals.addAll(getRunningGoals(mob, type)); ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getRunningGoals(T mob, GoalType type) { ++ CraftMob craftMob = (CraftMob) mob; ++ Set> goals = new HashSet<>(); ++ getHandle(craftMob, type).getExecutingGoals() ++ .filter(item -> item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) ++ .forEach(item -> { ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); ++ } else { ++ //noinspection unchecked ++ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); ++ } ++ }); ++ return goals; ++ } ++ ++ @Override ++ public Collection> getRunningGoalsWithout(T mob, GoalType type) { ++ CraftMob craftMob = (CraftMob) mob; ++ Set> goals = new HashSet<>(); ++ for (GoalType internalType : GoalType.values()) { ++ if (internalType == type) { ++ continue; ++ } ++ getHandle(craftMob, internalType).getExecutingGoals() ++ .filter(item -> !item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) ++ .forEach(item -> { ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); ++ } else { ++ //noinspection unchecked ++ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); ++ } ++ }); ++ } ++ return goals; ++ } ++ ++ private GoalSelector getHandle(CraftMob mob, EnumSet types) { ++ if (types.contains(GoalType.TARGET)) { ++ return mob.getHandle().targetSelector; ++ } else { ++ return mob.getHandle().goalSelector; ++ } ++ } ++ ++ private GoalSelector getHandle(CraftMob mob, GoalType type) { ++ if (type == GoalType.TARGET) { ++ return mob.getHandle().targetSelector; ++ } else { ++ return mob.getHandle().goalSelector; ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d4fe9d517a05f99c715ab73d5baf1deb6a732068 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java +@@ -0,0 +1,62 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import GoalKey; ++import java.util.EnumSet; ++import net.minecraft.world.entity.ai.goal.Goal; ++import org.bukkit.entity.Mob; ++ ++/** ++ * Wraps vanilla in api ++ */ ++public class PaperVanillaGoal implements VanillaGoal { ++ ++ private final Goal handle; ++ private final GoalKey key; ++ ++ private final EnumSet types; ++ ++ public PaperVanillaGoal(Goal handle) { ++ this.handle = handle; ++ this.key = MobGoalHelper.getKey(handle.getClass()); ++ this.types = MobGoalHelper.vanillaToPaper(handle.getGoalTypes()); ++ } ++ ++ public Goal getHandle() { ++ return handle; ++ } ++ ++ @Override ++ public boolean shouldActivate() { ++ return handle.shouldActivate2(); ++ } ++ ++ @Override ++ public boolean shouldStayActive() { ++ return handle.shouldStayActive2(); ++ } ++ ++ @Override ++ public void start() { ++ handle.start(); ++ } ++ ++ @Override ++ public void stop() { ++ handle.onTaskReset(); ++ } ++ ++ @Override ++ public void tick() { ++ handle.tick(); ++ } ++ ++ @Override ++ public GoalKey getKey() { ++ return key; ++ } ++ ++ @Override ++ public EnumSet getTypes() { ++ return types; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java +index 9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f..b3329c6fcd6758a781a51f5ba8f5052ac1c77b49 100644 +--- a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java ++++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java +@@ -64,4 +64,8 @@ public final class OptimizedSmallEnumSet> { + public boolean hasCommonElements(final OptimizedSmallEnumSet other) { + return (other.backingSet & this.backingSet) != 0; + } ++ ++ public boolean hasElement(final E element) { ++ return (this.backingSet & (1L << element.ordinal())) != 0; ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +index acc6306d659cd65a043d12cd42dcbaf55aaf5250..f85dfd8b57cf81ad7c6b12753fdd42e93f772f9e 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +@@ -8,11 +8,17 @@ public abstract class Goal { + private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. + private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector + +- public Goal() {} ++ // Paper start make sure goaltypes is never empty ++ public Goal() { ++ if (this.goalTypes.size() == 0) { ++ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR); ++ } ++ } ++ // paper end + +- public abstract boolean canUse(); ++ public boolean canUse() { return this.shouldActivate(); } public boolean shouldActivate() { return false;} public boolean shouldActivate2() { return canUse(); } // Paper - OBFHELPER, for both directions... + +- public boolean canContinueToUse() { ++ public boolean canContinueToUse() { return this.shouldStayActive(); } public boolean shouldStayActive2() { return canContinueToUse(); } public boolean shouldStayActive() { // Paper - OBFHELPER, for both directions... + return this.canUse(); + } + +@@ -20,19 +26,23 @@ public abstract class Goal { + return true; + } + +- public void start() {} ++ public void start() { this.start(); } public void start() {} // Paper - OBFHELPER + + public void stop() { + onTaskReset(); // Paper + } + public void onTaskReset() {} // Paper + +- public void tick() {} ++ public void tick() { this.tick(); } public void tick() {} // Paper OBFHELPER + +- public void setFlags(EnumSet controls) { ++ public void setFlags(EnumSet controls) { this.setTypes(controls); } public void setTypes(EnumSet enumset) { // Paper - OBFHELPER + // Paper start - remove streams from pathfindergoalselector + this.goalTypes.clear(); +- this.goalTypes.addAllUnchecked(controls); ++ this.goalTypes.addAllUnchecked(enumset); ++ // make sure its never empty ++ if (this.goalTypes.size() == 0) { ++ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR); ++ } + // Paper end - remove streams from pathfindergoalselector + } + +@@ -48,7 +58,7 @@ public abstract class Goal { + + public static enum Flag { + +- MOVE, LOOK, JUMP, TARGET; ++ MOVE, LOOK, JUMP, TARGET, UNKNOWN_BEHAVIOR; // Paper - add unknown + + private Flag() {} + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +index 5da2d780c17522e07c733a5e23b17ec760c7b342..a03f72f67948efab3b000dfa1d48061abf7cc02f 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +@@ -28,7 +28,7 @@ public class GoalSelector { + } + }; + private final Map lockedFlags = new EnumMap(Goal.Flag.class); +- private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER ++ private final Set availableGoals = Sets.newLinkedHashSet(); public final Set getTasks() { return availableGoals; }// Paper - OBFHELPER // Paper - private -> public + private final Supplier profiler; + private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. + private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector +@@ -39,7 +39,7 @@ public class GoalSelector { + this.profiler = profiler; + } + +- public void addGoal(int priority, Goal goal) { ++ public void addGoal(int priority, Goal goal) {addGoal(priority, goal);} public void addGoal(int priority, Goal goal) { // Paper - OBFHELPER + this.availableGoals.add(new WrappedGoal(priority, goal)); + } + +@@ -58,7 +58,7 @@ public class GoalSelector { + } + // Paper end + +- public void removeGoal(Goal goal) { ++ public void removeGoal(Goal goal) {removeGoal(goal);} public void removeGoal(Goal goal) { // Paper - OBFHELPER + // Paper start - remove streams from pathfindergoalselector + for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { + WrappedGoal goalWrapped = iterator.next(); +@@ -154,6 +154,7 @@ public class GoalSelector { + gameprofilerfiller.pop(); + } + ++ public final Stream getExecutingGoals() { return getRunningGoals(); } // Paper - OBFHELPER + public Stream getRunningGoals() { + return this.availableGoals.stream().filter(WrappedGoal::isRunning); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +index 984146b2b6eb3e498433b1c4971397848166d9c9..06fe2248a52c180ffabe0a6fe0cf155b78d4752d 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +@@ -5,8 +5,8 @@ import javax.annotation.Nullable; + + public class WrappedGoal extends Goal { + +- private final Goal goal; +- private final int priority; ++ private final Goal goal; public Goal getGoal() {return goal;} // Paper - OBFHELPER ++ private final int priority; public int getPriority() {return priority;} // Paper - OBFHELPER + private boolean isRunning; + + public WrappedGoal(int priority, Goal goal) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 1bfe96443877e460d22513d59ebc3b5988e8eb43..c6dc314a1735bf849ee1572e01335909bed9b455 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2390,5 +2390,11 @@ public final class CraftServer implements Server { + public boolean isStopping() { + return net.minecraft.server.MinecraftServer.getServer().hasStopped(); + } ++ ++ private com.destroystokyo.paper.entity.ai.MobGoals mobGoals = new com.destroystokyo.paper.entity.ai.PaperMobGoals(); ++ @Override ++ public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { ++ return mobGoals; ++ } + // Paper end + } +diff --git a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c0525216a8469613c3e0d4b5774a82f69e70fb16 +--- /dev/null ++++ b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java +@@ -0,0 +1,104 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.entity.ai.goal.PathfinderGoal; ++import org.junit.Assert; ++import org.junit.Test; ++ ++import java.lang.reflect.Field; ++import java.lang.reflect.Modifier; ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++import java.util.stream.Collectors; ++ ++import org.bukkit.entity.Mob; ++ ++import io.github.classgraph.ClassGraph; ++import io.github.classgraph.ScanResult; ++ ++public class VanillaMobGoalTest { ++ ++ @Test ++ public void testKeys() { ++ List> deprecated = new ArrayList<>(); ++ List> keys = new ArrayList<>(); ++ for (Field field : VanillaGoal.class.getFields()) { ++ if (field.getType().equals(GoalKey.class)) { ++ try { ++ GoalKey goalKey = (GoalKey) field.get(null); ++ if (field.getAnnotation(Deprecated.class) != null) { ++ deprecated.add(goalKey); ++ } else { ++ keys.add(goalKey); ++ } ++ } catch (IllegalAccessException e) { ++ System.out.println("Skipping " + field.getName() + ": " + e.getMessage()); ++ } ++ } ++ } ++ ++ List> classes; ++ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) { ++ classes = scanResult.getSubclasses(PathfinderGoal.class.getName()).loadClasses(); ++ } ++ ++ List> vanillaNames = classes.stream() ++ .filter(VanillaMobGoalTest::hasNoEnclosingClass) ++ .filter(clazz -> !Modifier.isAbstract(clazz.getModifiers())) ++ .map(goalClass -> MobGoalHelper.getKey((Class) goalClass)) ++ .collect(Collectors.toList()); ++ ++ List> missingFromAPI = new ArrayList<>(vanillaNames); ++ missingFromAPI.removeAll(keys); ++ missingFromAPI.removeIf(k -> MobGoalHelper.ignored.contains(k.getNamespacedKey().getKey())); ++ List> missingFromVanilla = new ArrayList<>(keys); ++ missingFromVanilla.removeAll(vanillaNames); ++ ++ boolean shouldFail = false; ++ if (missingFromAPI.size() != 0) { ++ System.out.println("Missing from API: "); ++ for (GoalKey key : missingFromAPI) { ++ System.out.println("GoalKey<" + key.getEntityClass().getSimpleName() + "> " + key.getNamespacedKey().getKey().toUpperCase() + ++ " = GoalKey.of(" + key.getEntityClass().getSimpleName() + ".class, NamespacedKey.minecraft(\"" + key.getNamespacedKey().getKey() + "\"));"); ++ } ++ shouldFail = true; ++ } ++ if (missingFromVanilla.size() != 0) { ++ System.out.println("Missing from vanilla: "); ++ missingFromVanilla.forEach(System.out::println); ++ shouldFail = true; ++ } ++ ++ if (deprecated.size() != 0) { ++ System.out.println("Deprecated (might want to remove them at some point): "); ++ deprecated.forEach(System.out::println); ++ } ++ ++ if (shouldFail) Assert.fail("See above"); ++ } ++ ++ private static boolean hasNoEnclosingClass(Class clazz) { ++ return clazz.getEnclosingClass() == null || hasNoEnclosingClass(clazz.getSuperclass()); ++ } ++ ++ @Test ++ public void testBukkitMap() { ++ List> classes; ++ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft.world.entity").scan()) { ++ classes = scanResult.getSubclasses("net.minecraft.world.entity.EntityInsentient").loadClasses(); ++ } ++ Assert.assertNotEquals("There are supposed to be more than 0 entity types!", Collections.emptyList(), classes); ++ ++ boolean shouldFail = false; ++ for (Class nmsClass : classes) { ++ Class bukkitClass = MobGoalHelper.toBukkitClass((Class) nmsClass); ++ if (bukkitClass == null) { ++ shouldFail = true; ++ System.out.println("Missing bukkitMap.put(" + nmsClass.getSimpleName() + ".class, " + nmsClass.getSimpleName().replace("Entity", "") + ".class);"); ++ } ++ } ++ ++ if (shouldFail) Assert.fail("See above"); ++ } ++} diff --git a/patches/server-remapped/0465-Use-distance-map-to-optimise-entity-tracker.patch b/patches/server-remapped/0465-Use-distance-map-to-optimise-entity-tracker.patch new file mode 100644 index 0000000000..16a647e328 --- /dev/null +++ b/patches/server-remapped/0465-Use-distance-map-to-optimise-entity-tracker.patch @@ -0,0 +1,413 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 5 May 2020 20:18:05 -0700 +Subject: [PATCH] Use distance map to optimise entity tracker + +Use the distance map to find candidate players for tracking. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index e5ad635a480d32e7a10ee92c65cfc18a98beafad..74f393ffa2ae2d0e25b3f0b674cef7a987e985d3 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1652,6 +1652,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); ++ // Paper start - use distance map to optimise tracker ++ public static boolean isLegacyTrackingEntity(Entity entity) { ++ return entity.isLegacyTrackingEntity; ++ } ++ ++ // inlined EnumMap, TrackingRange.TrackingRangeType ++ static final org.spigotmc.TrackingRange.TrackingRangeType[] TRACKING_RANGE_TYPES = org.spigotmc.TrackingRange.TrackingRangeType.values(); ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap[] playerEntityTrackerTrackMaps; ++ final int[] entityTrackerTrackRanges; ++ ++ private int convertSpigotRangeToVanilla(final int vanilla) { ++ return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); ++ } ++ // Paper end - use distance map to optimise tracker + + void addPlayerToDistanceMaps(ServerPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.getX()); + int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); + // Note: players need to be explicitly added to distance maps before they can be updated ++ // Paper start - use distance map to optimise entity tracker ++ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { ++ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; ++ int trackRange = this.entityTrackerTrackRanges[i]; ++ ++ trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); ++ } ++ // Paper end - use distance map to optimise entity tracker + } + + void removePlayerFromDistanceMaps(ServerPlayer player) { +- ++ // Paper start - use distance map to optimise tracker ++ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { ++ this.playerEntityTrackerTrackMaps[i].remove(player); ++ } ++ // Paper end - use distance map to optimise tracker + } + + void updateMaps(ServerPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.getX()); + int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); + // Note: players need to be explicitly added to distance maps before they can be updated ++ // Paper start - use distance map to optimise entity tracker ++ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { ++ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; ++ int trackRange = this.entityTrackerTrackRanges[i]; ++ ++ trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); ++ } ++ // Paper end - use distance map to optimise entity tracker + } + // Paper end + +@@ -244,6 +279,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper + this.setViewDistance(i); + this.playerMobDistanceMap = this.level.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper ++ // Paper start - use distance map to optimise entity tracker ++ this.playerEntityTrackerTrackMaps = new com.destroystokyo.paper.util.misc.PlayerAreaMap[TRACKING_RANGE_TYPES.length]; ++ this.entityTrackerTrackRanges = new int[TRACKING_RANGE_TYPES.length]; ++ ++ org.spigotmc.SpigotWorldConfig spigotWorldConfig = this.level.spigotConfig; ++ ++ for (int ordinal = 0, len = TRACKING_RANGE_TYPES.length; ordinal < len; ++ordinal) { ++ org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = TRACKING_RANGE_TYPES[ordinal]; ++ int configuredSpigotValue; ++ switch (trackingRangeType) { ++ case PLAYER: ++ configuredSpigotValue = spigotWorldConfig.playerTrackingRange; ++ break; ++ case ANIMAL: ++ configuredSpigotValue = spigotWorldConfig.animalTrackingRange; ++ break; ++ case MONSTER: ++ configuredSpigotValue = spigotWorldConfig.monsterTrackingRange; ++ break; ++ case MISC: ++ configuredSpigotValue = spigotWorldConfig.miscTrackingRange; ++ break; ++ case OTHER: ++ configuredSpigotValue = spigotWorldConfig.otherTrackingRange; ++ break; ++ case ENDERDRAGON: ++ configuredSpigotValue = EntityType.ENDER_DRAGON.clientTrackingRange() * 16; ++ break; ++ default: ++ throw new IllegalStateException("Missing case for enum " + trackingRangeType); ++ } ++ configuredSpigotValue = convertSpigotRangeToVanilla(configuredSpigotValue); ++ ++ int trackRange = (configuredSpigotValue >>> 4) + ((configuredSpigotValue & 15) != 0 ? 1 : 0); ++ this.entityTrackerTrackRanges[ordinal] = trackRange; ++ ++ this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); ++ } ++ // Paper end - use distance map to optimise entity tracker + } + + public void updatePlayerMobTypeMap(Entity entity) { +@@ -1490,17 +1564,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + public void move(ServerPlayer player) { +- ObjectIterator objectiterator = this.entityMap.values().iterator(); +- +- while (objectiterator.hasNext()) { +- ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); +- +- if (playerchunkmap_entitytracker.entity == player) { +- playerchunkmap_entitytracker.updatePlayers(this.level.players()); +- } else { +- playerchunkmap_entitytracker.updatePlayer(player); +- } +- } ++ // Paper - delay this logic for the entity tracker tick, no need to duplicate it + + int i = Mth.floor(player.getX()) >> 4; + int j = Mth.floor(player.getZ()) >> 4; +@@ -1616,7 +1680,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker + this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); +- playerchunkmap_entitytracker.updatePlayers(this.level.players()); ++ playerchunkmap_entitytracker.updatePlayers(entity.getPlayersInTrackRange()); // Paper - don't search all players + if (entity instanceof ServerPlayer) { + ServerPlayer entityplayer = (ServerPlayer) entity; + +@@ -1659,7 +1723,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + entity.tracker = null; // Paper - We're no longer tracked + } + ++ // Paper start - optimised tracker ++ private final void processTrackQueue() { ++ this.level.timings.tracker1.startTiming(); ++ try { ++ for (TrackedEntity tracker : this.entityMap.values()) { ++ // update tracker entry ++ tracker.updatePlayers(tracker.entity.getPlayersInTrackRange()); ++ } ++ } finally { ++ this.level.timings.tracker1.stopTiming(); ++ } ++ ++ ++ this.level.timings.tracker2.startTiming(); ++ try { ++ for (TrackedEntity tracker : this.entityMap.values()) { ++ tracker.serverEntity.tick(); ++ } ++ } finally { ++ this.level.timings.tracker2.stopTiming(); ++ } ++ } ++ // Paper end - optimised tracker ++ + protected void tick() { ++ // Paper start - optimized tracker ++ if (true) { ++ this.processTrackQueue(); ++ return; ++ } ++ // Paper end - optimized tracker + List list = Lists.newArrayList(); + List list1 = this.level.players(); + +@@ -1728,23 +1822,31 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos()); + List list = Lists.newArrayList(); + List list1 = Lists.newArrayList(); +- ObjectIterator objectiterator = this.entityMap.values().iterator(); ++ // Paper start - optimise entity tracker ++ // use the chunk entity list, not the whole trackedEntities map... ++ Entity[] entities = chunk.entities.getRawData(); ++ for (int i = 0, size = chunk.entities.size(); i < size; ++i) { ++ Entity entity = entities[i]; ++ if (entity == player) { ++ continue; ++ } ++ ChunkMap.TrackedEntity tracker = this.entityMap.get(entity.getId()); ++ if (tracker != null) { // dumb plugins... move on... ++ tracker.updatePlayer(player); ++ } + +- while (objectiterator.hasNext()) { +- ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); +- Entity entity = playerchunkmap_entitytracker.entity; ++ // keep the vanilla logic here - this is REQUIRED or else passengers and their vehicles disappear! ++ // (and god knows what the leash thing is) + +- if (entity != player && entity.xChunk == chunk.getPos().x && entity.zChunk == chunk.getPos().z) { +- playerchunkmap_entitytracker.updatePlayer(player); +- if (entity instanceof Mob && ((Mob) entity).getLeashHolder() != null) { +- list.add(entity); +- } ++ if (entity instanceof Mob && ((Mob)entity).getLeashHolder() != null) { ++ list.add(entity); ++ } + +- if (!entity.getPassengers().isEmpty()) { +- list1.add(entity); +- } ++ if (!entity.getPassengers().isEmpty()) { ++ list1.add(entity); + } + } ++ // Paper end - optimise entity tracker + + Iterator iterator; + Entity entity1; +@@ -1782,7 +1884,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + public class TrackedEntity { + +- private final ServerEntity serverEntity; ++ final ServerEntity serverEntity; // Paper - private -> package private + private final Entity entity; + private final int range; + private SectionPos lastSectionPos; +@@ -1799,6 +1901,42 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.lastSectionPos = SectionPos.of(entity); + } + ++ // Paper start - use distance map to optimise tracker ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet lastTrackerCandidates; ++ ++ final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet oldTrackerCandidates = this.lastTrackerCandidates; ++ this.lastTrackerCandidates = newTrackerCandidates; ++ ++ if (newTrackerCandidates != null) { ++ Object[] rawData = newTrackerCandidates.getBackingSet(); ++ for (int i = 0, len = rawData.length; i < len; ++i) { ++ Object raw = rawData[i]; ++ if (!(raw instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)raw; ++ this.updatePlayer(player); ++ } ++ } ++ ++ if (oldTrackerCandidates == newTrackerCandidates) { ++ // this is likely the case. ++ // means there has been no range changes, so we can just use the above for tracking. ++ return; ++ } ++ ++ // stuff could have been removed, so we need to check the trackedPlayers set ++ // for players that were removed ++ ++ for (ServerPlayer player : this.seenBy.toArray(new ServerPlayer[0])) { // avoid CME ++ if (newTrackerCandidates == null || !newTrackerCandidates.contains(player)) { ++ this.updatePlayer(player); ++ } ++ } ++ } ++ // Paper end - use distance map to optimise tracker ++ + public boolean equals(Object object) { + return object instanceof ChunkMap.TrackedEntity ? ((ChunkMap.TrackedEntity) object).entity.getId() == this.entity.getId() : false; + } +@@ -1899,7 +2037,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + int j = entity.getType().clientTrackingRange() * 16; + j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper + +- if (j > i) { ++ if (j < i) { // Paper - we need the lowest range thanks to the fact that our tracker doesn't account for passenger logic + i = j; + } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index 1609ab94c86e964421f996d4d46aef30f8b8e696..d797873db52ba265ac4478f9f3c6344badd4739e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -100,6 +100,7 @@ public class ServerEntity { + this.wasOnGround = entity.isOnGround(); + } + ++ public final void tick() { this.sendChanges(); } // Paper - OBFHELPER + public void sendChanges() { + List list = this.entity.getPassengers(); + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 2b48c4a2b512c42bed2c767db90a28898c74286a..d9bb00752ac81b2171d3ad25fd84904467a18e3b 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -46,6 +46,7 @@ import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.ServerLevel; +@@ -294,6 +295,21 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + // CraftBukkit end + ++ // Paper start - optimise entity tracking ++ final org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = org.spigotmc.TrackingRange.getTrackingRangeType(this); ++ ++ public boolean isLegacyTrackingEntity = false; ++ ++ public final void setLegacyTrackingEntity(final boolean isLegacyTrackingEntity) { ++ this.isLegacyTrackingEntity = isLegacyTrackingEntity; ++ } ++ ++ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayersInTrackRange() { ++ return ((ServerLevel)this.level).getChunkSource().chunkMap.playerEntityTrackerTrackMaps[this.trackingRangeType.ordinal()] ++ .getObjectsInRange(MCUtil.getCoordinateKey(this)); ++ } ++ // Paper end - optimise entity tracking ++ + public Entity(EntityType type, Level world) { + this.id = Entity.ENTITY_COUNTER.incrementAndGet(); + this.passengers = Lists.newArrayList(); +diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java +index b03fa9024c7f0238e1379f6ae4486db5300a70e9..7b6011be849ecffdd791d439f70ae5dffc96f264 100644 +--- a/src/main/java/org/spigotmc/TrackingRange.java ++++ b/src/main/java/org/spigotmc/TrackingRange.java +@@ -20,6 +20,7 @@ public class TrackingRange + */ + public static int getEntityTrackingRange(Entity entity, int defaultRange) + { ++ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return defaultRange; // Paper - enderdragon is exempt + SpigotWorldConfig config = entity.level.spigotConfig; + if ( entity instanceof ServerPlayer ) + { +@@ -43,8 +44,48 @@ public class TrackingRange + return config.miscTrackingRange; + } else + { +- if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt + return config.otherTrackingRange; + } + } ++ ++ // Paper start - optimise entity tracking ++ // copied from above, TODO check on update ++ public static TrackingRangeType getTrackingRangeType(Entity entity) ++ { ++ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return TrackingRangeType.ENDERDRAGON; // Paper - enderdragon is exempt ++ if ( entity instanceof ServerPlayer ) ++ { ++ return TrackingRangeType.PLAYER; ++ // Paper start - Simplify and set water mobs to animal tracking range ++ } ++ switch (entity.activationType) { ++ case RAIDER: ++ case MONSTER: ++ case FLYING_MONSTER: ++ return TrackingRangeType.MONSTER; ++ case WATER: ++ case VILLAGER: ++ case ANIMAL: ++ return TrackingRangeType.ANIMAL; ++ case MISC: ++ } ++ if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) ++ // Paper end ++ { ++ return TrackingRangeType.MISC; ++ } else ++ { ++ return TrackingRangeType.OTHER; ++ } ++ } ++ ++ public static enum TrackingRangeType { ++ PLAYER, ++ ANIMAL, ++ MONSTER, ++ MISC, ++ OTHER, ++ ENDERDRAGON; ++ } ++ // Paper end - optimise entity tracking + } diff --git a/patches/server-remapped/0466-Optimize-isOutsideRange-to-use-distance-maps.patch b/patches/server-remapped/0466-Optimize-isOutsideRange-to-use-distance-maps.patch new file mode 100644 index 0000000000..adc6c14065 --- /dev/null +++ b/patches/server-remapped/0466-Optimize-isOutsideRange-to-use-distance-maps.patch @@ -0,0 +1,384 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 5 May 2020 20:40:53 -0700 +Subject: [PATCH] Optimize isOutsideRange to use distance maps + +Use a distance map to find the players in range quickly + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index d12d5459c847d3f0d655c85e31d81c27b7a2face..0147798c0285f64b8d767dfb2709d92f66ac72ef 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -69,6 +69,18 @@ public class ChunkHolder { + long lastAutoSaveTime; // Paper - incremental autosave + long inactiveTimeStart; // Paper - incremental autosave + ++ // Paper start - optimise isOutsideOfRange ++ // cached here to avoid a map lookup ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInMobSpawnRange; ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInChunkTickRange; ++ ++ void updateRanges() { ++ long key = net.minecraft.server.MCUtil.getCoordinateKey(this.pos); ++ this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key); ++ this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); ++ } ++ // Paper end - optimise isOutsideOfRange ++ + public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +@@ -85,6 +97,7 @@ public class ChunkHolder { + this.queueLevel = this.oldTicketLevel; + this.setTicketLevel(level); + this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper ++ this.updateRanges(); // Paper - optimise isOutsideOfRange + } + + // Paper start +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c756a5be9 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -208,6 +208,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); + } + // Paper end - use distance map to optimise tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ // A note about the naming used here: ++ // Previously, mojang used a "spawn range" of 8 for controlling both ticking and ++ // mob spawn range. However, spigot makes the spawn range configurable by ++ // checking if the chunk is in the tick range (8) and the spawn range ++ // obviously this means a spawn range > 8 cannot be implemented ++ ++ // these maps are named after spigot's uses ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + + void addPlayerToDistanceMaps(ServerPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.getX()); +@@ -221,6 +232,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); + } + // Paper end - use distance map to optimise entity tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + } + + void removePlayerFromDistanceMaps(ServerPlayer player) { +@@ -229,6 +243,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerEntityTrackerTrackMaps[i].remove(player); + } + // Paper end - use distance map to optimise tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerMobSpawnMap.remove(player); ++ this.playerChunkTickRangeMap.remove(player); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + } + + void updateMaps(ServerPlayer player) { +@@ -243,6 +261,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); + } + // Paper end - use distance map to optimise entity tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + } + // Paper end + +@@ -274,7 +295,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); + this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); + this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); +- this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); ++ this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper + this.overworldDataStorage = supplier; + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper + this.setViewDistance(i); +@@ -318,6 +339,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); + } + // Paper end - use distance map to optimise entity tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerChunkTickRangeMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInChunkTickRange = newState; ++ } ++ }, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInChunkTickRange = newState; ++ } ++ }); ++ this.playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInMobSpawnRange = newState; ++ } ++ }, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInMobSpawnRange = newState; ++ } ++ }); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + } + + public void updatePlayerMobTypeMap(Entity entity) { +@@ -337,6 +390,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return entityPlayer.mobCounts[enumCreatureType.ordinal()]; + } + ++ private static double getDistanceSquaredFromChunk(ChunkPos chunkPos, Entity entity) { return euclideanDistanceSquared(chunkPos, entity); } // Paper - OBFHELPER + private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { + double d0 = (double) (pos.x * 16 + 8); + double d1 = (double) (pos.z * 16 + 8); +@@ -515,6 +569,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } else { + if (holder != null) { + holder.setTicketLevel(level); ++ holder.updateRanges(); // Paper - optimise isOutsideOfRange + } + + if (holder != null) { +@@ -1493,30 +1548,53 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return isOutsideOfRange(chunkcoordintpair, false); + } + +- boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) { +- int chunkRange = level.spigotConfig.mobSpawnRange; +- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; +- chunkRange = (chunkRange > 8) ? 8 : chunkRange; ++ // Paper start - optimise isOutsideOfRange ++ final boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) { ++ return this.isOutsideOfRange(this.getUpdatingChunkIfPresent(chunkcoordintpair.toLong()), chunkcoordintpair, reducedRange); ++ } + +- final int finalChunkRange = chunkRange; // Paper for lambda below +- //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event +- // Spigot end +- long i = chunkcoordintpair.toLong(); ++ final boolean isOutsideOfRange(ChunkHolder playerchunk, ChunkPos chunkcoordintpair, boolean reducedRange) { ++ // this function is so hot that removing the map lookup call can have an order of magnitude impact on its performance ++ // tested and confirmed via System.nanoTime() ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInRange = reducedRange ? playerchunk.playersInMobSpawnRange : playerchunk.playersInChunkTickRange; + +- return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { +- // Paper start - +- com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; +- double blockRange = 16384.0D; +- if (reducedRange) { +- event = entityplayer.playerNaturallySpawnedEvent; +- if (event == null || event.isCancelled()) return false; +- blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); +- } ++ if (playersInRange == null) { ++ return true; ++ } + +- return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot +- // Paper end +- }); ++ Object[] backingSet = playersInRange.getBackingSet(); ++ ++ if (reducedRange) { ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object raw = backingSet[i]; ++ if (!(raw instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer) raw; ++ // don't check spectator and whatnot, already handled by mob spawn map update ++ if (player.lastEntitySpawnRadiusSquared > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { ++ return false; // in range ++ } ++ } ++ } else { ++ final double range = (DistanceManager.MOB_SPAWN_RANGE * 16) * (DistanceManager.MOB_SPAWN_RANGE * 16); ++ // before spigot, mob spawn range was actually mob spawn range + tick range, but it was split ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object raw = backingSet[i]; ++ if (!(raw instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer) raw; ++ // don't check spectator and whatnot, already handled by mob spawn map update ++ if (range > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { ++ return false; // in range ++ } ++ } ++ } ++ // no players in range ++ return true; + } ++ // Paper end - optimise isOutsideOfRange + + private boolean skipPlayer(ServerPlayer player) { + return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5980d3467 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -37,7 +37,7 @@ public abstract class DistanceManager { + private final Long2ObjectMap> playersPerChunk = new Long2ObjectOpenHashMap(); + public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); + private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); +- private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); ++ public static final int MOB_SPAWN_RANGE = 8; // private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used + private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); + // Paper start use a queue, but still keep unique requirement + public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { +@@ -56,6 +56,8 @@ public abstract class DistanceManager { + private final Executor mainThreadExecutor; + private long ticketTickCounter; + ++ ChunkMap chunkMap; // Paper ++ + protected DistanceManager(Executor workerExecutor, Executor mainThreadExecutor) { + mainThreadExecutor.getClass(); + ProcessorHandle mailbox = ProcessorHandle.of("player ticket throttler", mainThreadExecutor::execute); +@@ -100,7 +102,7 @@ public abstract class DistanceManager { + protected abstract ChunkHolder updateChunkScheduling(long pos, int level, @Nullable ChunkHolder holder, int k); + + public boolean runAllUpdates(ChunkMap chunkStorage) { +- this.naturalSpawnChunkCounter.runAllUpdates(); ++ //this.f.a(); // Paper - no longer used + this.playerTicketManager.runAllUpdates(); + int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE); + boolean flag = i != 0; +@@ -236,7 +238,7 @@ public abstract class DistanceManager { + ((ObjectSet) this.playersPerChunk.computeIfAbsent(i, (j) -> { + return new ObjectOpenHashSet(); + })).add(player); +- this.naturalSpawnChunkCounter.update(i, 0, true); ++ //this.f.update(i, 0, true); // Paper - no longer used + this.playerTicketManager.update(i, 0, true); + } + +@@ -248,7 +250,7 @@ public abstract class DistanceManager { + if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully. + if (objectset == null || objectset.isEmpty()) { // Paper + this.playersPerChunk.remove(i); +- this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); ++ //this.f.update(i, Integer.MAX_VALUE, false); // Paper - no longer used + this.playerTicketManager.update(i, Integer.MAX_VALUE, false); + } + +@@ -272,13 +274,17 @@ public abstract class DistanceManager { + } + + public int getNaturalSpawnChunkCount() { +- this.naturalSpawnChunkCounter.runAllUpdates(); +- return this.naturalSpawnChunkCounter.chunks.size(); ++ // Paper start - use distance map to implement ++ // note: this is the spawn chunk count ++ return this.chunkMap.playerChunkTickRangeMap.size(); ++ // Paper end - use distance map to implement + } + + public boolean hasPlayersNearby(long i) { +- this.naturalSpawnChunkCounter.runAllUpdates(); +- return this.naturalSpawnChunkCounter.chunks.containsKey(i); ++ // Paper start - use distance map to implement ++ // note: this is the is spawn chunk method ++ return this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(i) != null; ++ // Paper end - use distance map to implement + } + + public String getDebugStatus() { +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 79fb63c40dd0543a6f629e78f390f23f34992ba1..52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -753,6 +753,37 @@ public class ServerChunkCache extends ChunkSource { + boolean flag1 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !level.players().isEmpty(); // CraftBukkit + + if (!flag) { ++ // Paper start - optimize isOutisdeRange ++ ChunkMap playerChunkMap = this.chunkMap; ++ for (ServerPlayer player : this.level.players) { ++ if (!player.affectsSpawning || player.isSpectator()) { ++ playerChunkMap.playerMobSpawnMap.remove(player); ++ continue; ++ } ++ ++ int viewDistance = this.chunkMap.getEffectiveViewDistance(); ++ ++ // copied and modified from isOutisdeRange ++ int chunkRange = level.spigotConfig.mobSpawnRange; ++ chunkRange = (chunkRange > viewDistance) ? (byte)viewDistance : chunkRange; ++ chunkRange = (chunkRange > DistanceManager.MOB_SPAWN_RANGE) ? DistanceManager.MOB_SPAWN_RANGE : chunkRange; ++ ++ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(player.getBukkitEntity(), (byte)chunkRange); ++ event.callEvent(); ++ if (event.isCancelled() || event.getSpawnRadius() < 0 || playerChunkMap.playerChunkTickRangeMap.getLastViewDistance(player) == -1) { ++ playerChunkMap.playerMobSpawnMap.remove(player); ++ continue; ++ } ++ ++ int range = Math.min(event.getSpawnRadius(), 32); // limit to max view distance ++ int chunkX = net.minecraft.server.MCUtil.getChunkCoordinate(player.getX()); ++ int chunkZ = net.minecraft.server.MCUtil.getChunkCoordinate(player.getZ()); ++ ++ playerChunkMap.playerMobSpawnMap.addOrUpdate(player, chunkX, chunkZ, range); ++ player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in isOutsideRange ++ player.playerNaturallySpawnedEvent = event; ++ } ++ // Paper end - optimize isOutisdeRange + this.level.getProfiler().push("pollingChunks"); + int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); + boolean flag2 = level.ticksPerAnimalSpawns != 0L && worlddata.getGameTime() % level.ticksPerAnimalSpawns == 0L; // CraftBukkit +@@ -782,15 +813,7 @@ public class ServerChunkCache extends ChunkSource { + this.level.getProfiler().pop(); + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper +- //Paper start - call player naturally spawn event +- int chunkRange = level.spigotConfig.mobSpawnRange; +- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; +- chunkRange = Math.min(chunkRange, 8); +- for (ServerPlayer entityPlayer : this.level.players()) { +- entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); +- entityPlayer.playerNaturallySpawnedEvent.callEvent(); +- }; +- // Paper end ++ // Paper - moved up + this.level.timings.chunkTicks.startTiming(); // Paper + final int[] chunksTicked = {0}; this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); +@@ -807,9 +830,9 @@ public class ServerChunkCache extends ChunkSource { + LevelChunk chunk = (LevelChunk) optional1.get(); + ChunkPos chunkcoordintpair = playerchunk.getPos(); + +- if (!this.chunkMap.noPlayersCloseForSpawning(chunkcoordintpair)) { ++ if (!this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange + chunk.setInhabitedTime(chunk.getInhabitedTime() + j); +- if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot ++ if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange + NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 24c508ade61a6ad90b0ef73cdc995f531ef18263..95f1f4727a8e2000931e6f36b862e3ad28334a69 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -247,6 +247,8 @@ public class ServerPlayer extends Player implements ContainerListener { + + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + ++ double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks ++ + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { + super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); + this.respawnDimension = Level.OVERWORLD; diff --git a/patches/server-remapped/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch b/patches/server-remapped/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch new file mode 100644 index 0000000000..e9e6a043fc --- /dev/null +++ b/patches/server-remapped/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch @@ -0,0 +1,320 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 27 Apr 2020 04:05:38 -0700 +Subject: [PATCH] Stop copy-on-write operations for updating light data + +Causes huge memory allocations + gc issues + +diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java +index 9f33fa8f84d10f8f4089030074ad6c0d81269ce8..a1ad4d73ddaf6afe97a1f1ff7e0622b52fac8761 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java +@@ -10,7 +10,7 @@ import net.minecraft.world.level.chunk.LightChunkGetter; + public class BlockLightSectionStorage extends LayerLightSectionStorage { + + protected BlockLightSectionStorage(LightChunkGetter chunkProvider) { +- super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new Long2ObjectOpenHashMap())); ++ super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data + } + + @Override +@@ -23,13 +23,13 @@ public class BlockLightSectionStorage extends LayerLightSectionStorage { + +- public BlockDataLayerStorageMap(Long2ObjectOpenHashMap arrays) { +- super(arrays); ++ public BlockDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data ++ super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data + } + + @Override + public BlockLightSectionStorage.BlockDataLayerStorageMap copy() { +- return new BlockLightSectionStorage.BlockDataLayerStorageMap(this.map.clone()); ++ return new BlockDataLayerStorageMap(this.data, true); // Paper - avoid copying light data + } + } + } +diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +index 01ae1c811862f56317a90e3811fe2ef4b593695f..4c9041f1c1cb4b3ec114fbd0c5d4db50a6f2526d 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java ++++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +@@ -9,10 +9,23 @@ public abstract class DataLayerStorageMap> { + private final long[] lastSectionKeys = new long[2]; + private final DataLayer[] lastSections = new DataLayer[2]; + private boolean cacheEnabled; +- protected final Long2ObjectOpenHashMap map; +- +- protected DataLayerStorageMap(Long2ObjectOpenHashMap arrays) { +- this.map = arrays; ++ protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data ++ protected final boolean isVisible; // Paper - avoid copying light data ++ java.util.function.Function lookup; // Paper - faster branchless lookup ++ ++ // Paper start - avoid copying light data ++ protected DataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { ++ if (isVisible) { ++ data.performUpdatesLockMap(); ++ } ++ this.data = data; ++ this.isVisible = isVisible; ++ if (isVisible) { ++ lookup = data::getVisibleAsync; ++ } else { ++ lookup = data::getUpdating; ++ } ++ // Paper end - avoid copying light data + this.clearCache(); + this.cacheEnabled = true; + } +@@ -20,16 +33,17 @@ public abstract class DataLayerStorageMap> { + public abstract M copy(); + + public void copyDataLayer(long pos) { +- this.map.put(pos, ((DataLayer) this.map.get(pos)).copy()); ++ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data ++ this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data + this.clearCache(); + } + + public boolean hasLayer(long chunkPos) { +- return this.map.containsKey(chunkPos); ++ return lookup.apply(chunkPos) != null; // Paper - avoid copying light data + } + + @Nullable +- public DataLayer getLayer(long chunkPos) { ++ public final DataLayer getLayer(long chunkPos) { // Paper - final + if (this.cacheEnabled) { + for (int j = 0; j < 2; ++j) { + if (chunkPos == this.lastSectionKeys[j]) { +@@ -38,7 +52,7 @@ public abstract class DataLayerStorageMap> { + } + } + +- DataLayer nibblearray = (DataLayer) this.map.get(chunkPos); ++ DataLayer nibblearray = lookup.apply(chunkPos); // Paper - avoid copying light data + + if (nibblearray == null) { + return null; +@@ -59,11 +73,13 @@ public abstract class DataLayerStorageMap> { + + @Nullable + public DataLayer removeLayer(long chunkPos) { +- return (DataLayer) this.map.remove(chunkPos); ++ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data ++ return (DataLayer) this.data.queueRemove(chunkPos); // Paper - avoid copying light data + } + + public void setLayer(long pos, DataLayer data) { +- this.map.put(pos, data); ++ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data ++ this.data.queueUpdate(pos, data); // Paper - avoid copying light data + } + + public void clearCache() { +@@ -71,7 +87,6 @@ public abstract class DataLayerStorageMap> { + this.lastSectionKeys[i] = Long.MAX_VALUE; + this.lastSections[i] = null; + } +- + } + + public void disableCache() { +diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +index 45be10a0d7c26e4b6e5738ba994ce343265210f5..177dae992d13674bb285a60b8427df9ea843dc99 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +@@ -26,8 +26,8 @@ public abstract class LayerLightSectionStorage> + protected final LongSet dataSectionSet = new LongOpenHashSet(); + protected final LongSet toMarkNoData = new LongOpenHashSet(); + protected final LongSet toMarkData = new LongOpenHashSet(); +- protected volatile M visibleSectionData; +- protected final M updatingSectionData; ++ protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change ++ protected final M updatingSectionData; // Paper - diff on change, should be "updating" + protected final LongSet changedSections = new LongOpenHashSet(); + protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet(); + protected final Long2ObjectMap queuedSections = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); +@@ -41,8 +41,8 @@ public abstract class LayerLightSectionStorage> + this.layer = lightType; + this.chunkSource = chunkProvider; + this.updatingSectionData = lightData; +- this.visibleSectionData = lightData.copy(); +- this.visibleSectionData.disableCache(); ++ this.e_visible = lightData.copy(); // Paper - avoid copying light data ++ this.e_visible.disableCache(); // Paper - avoid copying light data + } + + protected boolean storingLightForSection(long sectionPos) { +@@ -51,7 +51,15 @@ public abstract class LayerLightSectionStorage> + + @Nullable + protected DataLayer getDataLayer(long sectionPos, boolean cached) { +- return this.getDataLayer(cached ? this.updatingSectionData : this.visibleSectionData, sectionPos); ++ // Paper start - avoid copying light data ++ if (cached) { ++ return this.getDataLayer(this.updatingSectionData, sectionPos); ++ } else { ++ synchronized (this.visibleUpdateLock) { ++ return this.getDataLayer(this.e_visible, sectionPos); ++ } ++ } ++ // Paper end - avoid copying light data + } + + @Nullable +@@ -364,10 +372,12 @@ public abstract class LayerLightSectionStorage> + + protected void swapSectionMap() { + if (!this.changedSections.isEmpty()) { ++ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data + M m0 = this.updatingSectionData.copy(); + + m0.disableCache(); +- this.visibleSectionData = m0; ++ this.e_visible = m0; // Paper - avoid copying light data ++ } // Paper - avoid copying light data + this.changedSections.clear(); + } + +diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +index c304637ae8f80c65b58e8ba8a27609b532bb1184..410fcfa8c01b7e3d3e3829ebdb92a11badff16ea 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +@@ -23,15 +23,16 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data + } + + @Override + protected int getLightValue(long blockPos) { + long j = SectionPos.blockToSection(blockPos); + int k = SectionPos.y(j); +- SkyLightSectionStorage.SkyDataLayerStorageMap lightenginestoragesky_a = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.visibleSectionData; +- int l = lightenginestoragesky_a.topSections.get(SectionPos.getZeroNode(j)); ++ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data ++ SkyLightSectionStorage.SkyDataLayerStorageMap lightenginestoragesky_a = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.e_visible; // Paper - avoid copying light data - must be after lock acquire ++ int l = lightenginestoragesky_a.otherData.getVisibleAsync(SectionPos.getZeroNode(j)); // Paper - avoid copying light data + + if (l != lightenginestoragesky_a.currentLowestY && k < l) { + DataLayer nibblearray = this.getDataLayer(lightenginestoragesky_a, j); // Paper - decompile fix +@@ -52,6 +53,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage j) { + ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY = j; +- ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.defaultReturnValue(((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY); ++ ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.queueDefaultReturnValue(((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY); // Paper - avoid copying light data + } + + long k = SectionPos.getZeroNode(sectionPos); +- int l = ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.get(k); ++ int l = ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.getUpdating(k); // Paper - avoid copying light data + + if (l < j + 1) { +- ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.put(k, j + 1); ++ ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.queueUpdate(k, j + 1); // Paper - avoid copying light data + if (this.columnsWithSkySources.contains(k)) { + this.queueAddSource(sectionPos); + if (l > ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY) { +@@ -107,7 +109,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage= k; + } +@@ -327,18 +329,21 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage { + + private int currentLowestY; +- private final Long2IntOpenHashMap topSections; +- +- public SkyDataLayerStorageMap(Long2ObjectOpenHashMap arrays, Long2IntOpenHashMap columnToTopSection, int minSectionY) { +- super(arrays); +- this.topSections = columnToTopSection; +- columnToTopSection.defaultReturnValue(minSectionY); +- this.currentLowestY = minSectionY; ++ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data ++ ++ // Paper start - avoid copying light data ++ public SkyDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData, int i, boolean isVisible) { ++ super(data, isVisible); ++ this.otherData = otherData; ++ otherData.queueDefaultReturnValue(i); ++ // Paper end - avoid copying light data ++ this.currentLowestY = i; + } + + @Override + public SkyLightSectionStorage.SkyDataLayerStorageMap copy() { +- return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.map.clone(), this.topSections.clone(), this.currentLowestY); ++ this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data ++ return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.data, this.otherData, this.currentLowestY, true); // Paper - avoid copying light data + } + } + } diff --git a/patches/server-remapped/0468-No-Tick-view-distance-implementation.patch b/patches/server-remapped/0468-No-Tick-view-distance-implementation.patch new file mode 100644 index 0000000000..9fee42c2d0 --- /dev/null +++ b/patches/server-remapped/0468-No-Tick-view-distance-implementation.patch @@ -0,0 +1,819 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 5 May 2020 21:23:34 -0700 +Subject: [PATCH] No-Tick view distance implementation + +Implements world view distance getters/setters + +Per-Player is absent due to difficulty of maintaining +the diff required to make it happen. + +diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java +index 5bcf9cefc29eb20e2cfbfb49e2b2662ec394a87e..a696474b4bd0e32a26dadfbc1257580ee596f0c0 100644 +--- a/src/main/java/co/aikar/timings/TimingsExport.java ++++ b/src/main/java/co/aikar/timings/TimingsExport.java +@@ -156,7 +156,8 @@ public class TimingsExport extends Thread { + pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { + return pair(rule, world.getWorld().getGameRuleValue(rule)); + })), +- pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) ++ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()), ++ pair("notick-viewdistance", world.getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance()) + )); + })); + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 46ac6d91422423f1e03b86d3efa3241f2599000d..6463d3e4837d032a35654a035f42b8a805e0e286 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -632,4 +632,9 @@ public class PaperWorldConfig { + phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); + phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); + } ++ ++ public int noTickViewDistance; ++ private void viewDistance() { ++ this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 9abef8550a89df5e15ac28de1a5549d064f29122..d18497a33dc53f6b465e659967bf8c98731c46c0 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -638,7 +638,8 @@ public final class MCUtil { + }); + + worldData.addProperty("name", world.getWorld().getName()); +- worldData.addProperty("view-distance", world.spigotConfig.viewDistance); ++ worldData.addProperty("view-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance()); ++ worldData.addProperty("no-view-distance", world.getChunkSource().chunkMap.getRawNoTickViewDistance()); + worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); + worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); + worldData.addProperty("visible-chunk-count", visibleChunks.size()); +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 0147798c0285f64b8d767dfb2709d92f66ac72ef..9ebcfca10071cc42d4f1df02c25de5042c065f38 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -81,6 +81,18 @@ public class ChunkHolder { + } + // Paper end - optimise isOutsideOfRange + ++ // Paper start - no-tick view distance ++ public final LevelChunk getSendingChunk() { ++ // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used ++ // in Chunk's neighbour callback ++ LevelChunk ret = this.chunkMap.level.getChunkSource().getChunkAtIfLoadedImmediately(this.pos.x, this.pos.z); ++ if (ret != null && ret.areNeighboursLoaded(1)) { ++ return ret; ++ } ++ return null; ++ } ++ // Paper end - no-tick view distance ++ + public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +@@ -240,7 +252,7 @@ public class ChunkHolder { + } + + public void blockChanged(BlockPos blockposition) { +- LevelChunk chunk = this.getTickingChunk(); ++ LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { + byte b0 = (byte) SectionPos.blockToSectionCoord(blockposition.getY()); +@@ -256,7 +268,7 @@ public class ChunkHolder { + } + + public void sectionLightChanged(LightLayer type, int y) { +- LevelChunk chunk = this.getTickingChunk(); ++ LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { + chunk.setUnsaved(true); +@@ -338,9 +350,48 @@ public class ChunkHolder { + } + + private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { +- this.playerProvider.getPlayers(this.pos, onlyOnWatchDistanceEdge).forEach((entityplayer) -> { +- entityplayer.connection.send(packet); +- }); ++ // Paper start - per player view distance ++ // there can be potential desync with player's last mapped section and the view distance map, so use the ++ // view distance map here. ++ com.destroystokyo.paper.util.misc.PlayerAreaMap viewDistanceMap = this.chunkMap.playerViewDistanceBroadcastMap; ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = viewDistanceMap.getObjectsInRange(this.pos); ++ if (players == null) { ++ return; ++ } ++ ++ if (onlyOnWatchDistanceEdge) { // flag -> border only ++ Object[] backingSet = players.getBackingSet(); ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ ++ int viewDistance = viewDistanceMap.getLastViewDistance(player); ++ long lastPosition = viewDistanceMap.getLastCoordinate(player); ++ ++ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - this.pos.x); ++ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - this.pos.z); ++ ++ if (Math.max(distX, distZ) == viewDistance) { ++ player.connection.send(packet); ++ } ++ } ++ } else { ++ Object[] backingSet = players.getBackingSet(); ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ player.connection.send(packet); ++ } ++ } ++ ++ return; ++ // Paper end - per player view distance + } + + public CompletableFuture> getOrScheduleFuture(ChunkStatus targetStatus, ChunkMap chunkStorage) { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d3956c5f2efb 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -57,12 +57,14 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; + import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; + import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; ++import net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket; + import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; + import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; + import net.minecraft.network.protocol.game.DebugPackets; + import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.progress.ChunkProgressListener; ++import net.minecraft.server.network.ServerGamePacketListenerImpl; + import net.minecraft.util.CsvOutput; + import net.minecraft.util.Mth; + import net.minecraft.util.profiling.ProfilerFiller; +@@ -144,7 +146,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private boolean modified; + private final ChunkTaskPriorityQueueSorter queueSorter; + private final ProcessorHandle> worldgenMailbox; +- private final ProcessorHandle> mainThreadMailbox; ++ public final ProcessorHandle> mainThreadMailbox; // Paper - private -> public ++ // Paper start ++ final ProcessorHandle> mailboxLight; ++ public void addLightTask(ChunkHolder playerchunk, Runnable run) { ++ this.mailboxLight.tell(ChunkTaskPriorityQueueSorter.message(playerchunk, run)); ++ } ++ // Paper end + public final ChunkProgressListener progressListener; + public final ChunkMap.ChunkDistanceManager distanceManager; public final DistanceManager getChunkDistanceManager() { return this.distanceManager; } // Paper - OBFHELPER + private final AtomicInteger tickingGenerated; +@@ -219,6 +227,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick + public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ int noTickViewDistance; ++ public final int getRawNoTickViewDistance() { ++ return this.noTickViewDistance; ++ } ++ public final int getEffectiveNoTickViewDistance() { ++ return this.noTickViewDistance == -1 ? this.getEffectiveViewDistance() : this.noTickViewDistance; ++ } ++ public final int getLoadViewDistance() { ++ return Math.max(this.getEffectiveViewDistance(), this.getEffectiveNoTickViewDistance()); ++ } ++ ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceBroadcastMap; ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap; ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap; ++ // Paper end - no-tick view distance + + void addPlayerToDistanceMaps(ServerPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.getX()); +@@ -235,6 +259,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper start - optimise PlayerChunkMap#isOutsideRange + this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ int effectiveTickViewDistance = this.getEffectiveViewDistance(); ++ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); ++ ++ if (!this.cannotLoadChunks(player)) { ++ this.playerViewDistanceTickMap.add(player, chunkX, chunkZ, effectiveTickViewDistance); ++ this.playerViewDistanceNoTickMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) ++ } ++ ++ player.needsChunkCenterUpdate = true; ++ this.playerViewDistanceBroadcastMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured ++ player.needsChunkCenterUpdate = false; ++ // Paper end - no-tick view distance + } + + void removePlayerFromDistanceMaps(ServerPlayer player) { +@@ -247,6 +284,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerMobSpawnMap.remove(player); + this.playerChunkTickRangeMap.remove(player); + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ this.playerViewDistanceBroadcastMap.remove(player); ++ this.playerViewDistanceTickMap.remove(player); ++ this.playerViewDistanceNoTickMap.remove(player); ++ // Paper end - no-tick view distance + } + + void updateMaps(ServerPlayer player) { +@@ -264,6 +306,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper start - optimise PlayerChunkMap#isOutsideRange + this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ int effectiveTickViewDistance = this.getEffectiveViewDistance(); ++ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); ++ ++ if (!this.cannotLoadChunks(player)) { ++ this.playerViewDistanceTickMap.update(player, chunkX, chunkZ, effectiveTickViewDistance); ++ this.playerViewDistanceNoTickMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) ++ } ++ ++ player.needsChunkCenterUpdate = true; ++ this.playerViewDistanceBroadcastMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured ++ player.needsChunkCenterUpdate = false; ++ // Paper end - no-tick view distance + } + // Paper end + +@@ -371,6 +426,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + }); + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); ++ this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ if (newState.size() != 1) { ++ return; ++ } ++ LevelChunk chunk = ChunkMap.this.level.getChunkSource().getChunkAtIfLoadedMainThreadNoCache(rangeX, rangeZ); ++ if (chunk == null || !chunk.areNeighboursLoaded(2)) { ++ return; ++ } ++ ++ ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); ++ ChunkMap.this.level.getChunkSource().addTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update ++ }, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ if (newState != null) { ++ return; ++ } ++ ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); ++ ChunkMap.this.level.getChunkSource().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update ++ }); ++ this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); ++ this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ if (player.needsChunkCenterUpdate) { ++ player.needsChunkCenterUpdate = false; ++ player.connection.send(new ClientboundSetChunkCacheCenterPacket(currPosX, currPosZ)); ++ } ++ ChunkMap.this.updateChunkTracking(player, new ChunkPos(rangeX, rangeZ), new Packet[2], false, true); // unloaded, loaded ++ }, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkMap.this.updateChunkTracking(player, new ChunkPos(rangeX, rangeZ), null, true, false); // unloaded, loaded ++ }); ++ // Paper end - no-tick view distance + } + + public void updatePlayerMobTypeMap(Entity entity) { +@@ -1199,15 +1293,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + completablefuture1.thenAcceptAsync((either) -> { + either.mapLeft((chunk) -> { + this.tickingGenerated.getAndIncrement(); +- Packet[] apacket = new Packet[2]; +- +- this.getPlayers(chunkcoordintpair, false).forEach((entityplayer) -> { +- this.playerLoadedChunk(entityplayer, apacket, chunk); +- }); ++ // Paper - no-tick view distance - moved to Chunk neighbour update + return Either.left(chunk); + }); + }, (runnable) -> { +- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); ++ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); // Paper - diff on change, this is the scheduling method copied in Chunk used to schedule chunk broadcasts (on change it needs to be copied again) + }); + return completablefuture1; + } +@@ -1302,32 +1392,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + } + +- protected void setViewDistance(int watchDistance) { +- int j = Mth.clamp(watchDistance + 1, 3, 33); ++ public void setViewDistance(int watchDistance) { // Paper - public ++ int j = Mth.clamp(watchDistance + 1, 3, 33); // Paper - diff on change, these make the lower view distance limit 2 and the upper 32 + + if (j != this.viewDistance) { + int k = this.viewDistance; + + this.viewDistance = j; +- this.distanceManager.updatePlayerTickets(this.viewDistance); +- ObjectIterator objectiterator = this.updatingChunkMap.values().iterator(); ++ this.setNoTickViewDistance(this.getRawNoTickViewDistance()); //Paper - no-tick view distance - propagate changes to no-tick, which does the actual chunk loading/sending ++ } + +- while (objectiterator.hasNext()) { +- ChunkHolder playerchunk = (ChunkHolder) objectiterator.next(); +- ChunkPos chunkcoordintpair = playerchunk.getPos(); +- Packet[] apacket = new Packet[2]; ++ } + +- this.getPlayers(chunkcoordintpair, false).forEach((entityplayer) -> { +- int l = checkerboardDistance(chunkcoordintpair, entityplayer, true); +- boolean flag = l <= k; +- boolean flag1 = l <= this.viewDistance; ++ // Paper start - no-tick view distance ++ public final void setNoTickViewDistance(int viewDistance) { ++ viewDistance = viewDistance == -1 ? -1 : Mth.clamp(viewDistance, 2, 32); + +- this.updateChunkTracking(entityplayer, chunkcoordintpair, apacket, flag, flag1); +- }); ++ this.noTickViewDistance = viewDistance; ++ int loadViewDistance = this.getLoadViewDistance(); ++ this.distanceManager.setNoTickViewDistance(loadViewDistance + 2 + 2); // add 2 to account for the change to 31 -> 33 tickets // see notes in the distance map updating for the other + 2 ++ ++ if (this.level != null && this.level.players != null) { // this can be called from constructor, where these aren't set ++ for (ServerPlayer player : this.level.players) { ++ ServerGamePacketListenerImpl connection = player.connection; ++ if (connection != null) { ++ // moved in from PlayerList ++ connection.send(new ClientboundSetChunkCacheRadiusPacket(loadViewDistance)); ++ } ++ this.updateMaps(player); + } + } +- + } ++ // Paper end - no-tick view distance + + protected void updateChunkTracking(ServerPlayer player, ChunkPos pos, Packet[] packets, boolean withinMaxWatchDistance, boolean withinViewDistance) { + if (player.level == this.level) { +@@ -1335,7 +1431,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.toLong()); + + if (playerchunk != null) { +- LevelChunk chunk = playerchunk.getTickingChunk(); ++ LevelChunk chunk = playerchunk.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { + this.playerLoadedChunk(player, packets, chunk); +@@ -1596,6 +1692,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + // Paper end - optimise isOutsideOfRange + ++ private boolean cannotLoadChunks(ServerPlayer entityplayer) { return this.skipPlayer(entityplayer); } // Paper - OBFHELPER + private boolean skipPlayer(ServerPlayer player) { + return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); + } +@@ -1623,13 +1720,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.removePlayerFromDistanceMaps(player); // Paper - distance maps + } + +- for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { +- for (int l = j - this.viewDistance; l <= j + this.viewDistance; ++l) { +- ChunkPos chunkcoordintpair = new ChunkPos(k, l); +- +- this.updateChunkTracking(player, chunkcoordintpair, new Packet[2], !added, added); +- } +- } ++ // Paper - broadcast view distance map handles this (see remove/add calls above) + + } + +@@ -1637,7 +1728,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + SectionPos sectionposition = SectionPos.of((Entity) entityplayer); + + entityplayer.setLastSectionPos(sectionposition); +- entityplayer.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); ++ // Paper - distance map handles this now + return sectionposition; + } + +@@ -1682,6 +1773,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + int k1; + int l1; + ++ /* // Paper start - replaced by distance map + if (Math.abs(i1 - i) <= this.viewDistance * 2 && Math.abs(j1 - j) <= this.viewDistance * 2) { + k1 = Math.min(i, i1) - this.viewDistance; + l1 = Math.min(j, j1) - this.viewDistance; +@@ -1690,36 +1782,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + for (int k2 = k1; k2 <= i2; ++k2) { + for (int l2 = l1; l2 <= j2; ++l2) { +- ChunkPos chunkcoordintpair = new ChunkPos(k2, l2); +- boolean flag3 = checkerboardDistance(chunkcoordintpair, i1, j1) <= this.viewDistance; +- boolean flag4 = checkerboardDistance(chunkcoordintpair, i, j) <= this.viewDistance; ++ ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k2, l2); ++ boolean flag3 = a(chunkcoordintpair, i1, j1) <= this.viewDistance; ++ boolean flag4 = a(chunkcoordintpair, i, j) <= this.viewDistance; + +- this.updateChunkTracking(player, chunkcoordintpair, new Packet[2], flag3, flag4); ++ this.sendChunk(entityplayer, chunkcoordintpair, new Packet[2], flag3, flag4); + } + } + } else { +- ChunkPos chunkcoordintpair1; ++ ChunkCoordIntPair chunkcoordintpair1; + boolean flag5; + boolean flag6; + + for (k1 = i1 - this.viewDistance; k1 <= i1 + this.viewDistance; ++k1) { + for (l1 = j1 - this.viewDistance; l1 <= j1 + this.viewDistance; ++l1) { +- chunkcoordintpair1 = new ChunkPos(k1, l1); ++ chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1); + flag5 = true; + flag6 = false; +- this.updateChunkTracking(player, chunkcoordintpair1, new Packet[2], true, false); ++ this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], true, false); + } + } + + for (k1 = i - this.viewDistance; k1 <= i + this.viewDistance; ++k1) { + for (l1 = j - this.viewDistance; l1 <= j + this.viewDistance; ++l1) { +- chunkcoordintpair1 = new ChunkPos(k1, l1); ++ chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1); + flag5 = false; + flag6 = true; +- this.updateChunkTracking(player, chunkcoordintpair1, new Packet[2], false, true); ++ this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], false, true); + } + } +- } ++ }*/ // Paper end - replaced by distance map + + this.updateMaps(player); // Paper - distance maps + +@@ -1727,11 +1819,46 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + @Override + public Stream getPlayers(ChunkPos chunkPos, boolean onlyOnWatchDistanceEdge) { +- return this.playerMap.a(chunkPos.toLong()).filter((entityplayer) -> { +- int i = b(chunkcoordintpair, entityplayer, true); ++ // Paper start - per player view distance ++ // there can be potential desync with player's last mapped section and the view distance map, so use the ++ // view distance map here. ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = this.playerViewDistanceBroadcastMap.getObjectsInRange(chunkPos); + +- return i > this.viewDistance ? false : !flag || i == this.viewDistance; +- }); ++ if (inRange == null) { ++ return Stream.empty(); ++ } ++ // all current cases are inlined so we wont hit this code, it's just in case plugins or future updates use it ++ List players = new java.util.ArrayList<>(); ++ Object[] backingSet = inRange.getBackingSet(); ++ ++ if (onlyOnWatchDistanceEdge) { // flag -> border only ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ int viewDistance = this.playerViewDistanceBroadcastMap.getLastViewDistance(player); ++ long lastPosition = this.playerViewDistanceBroadcastMap.getLastCoordinate(player); ++ ++ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - chunkPos.x); ++ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - chunkPos.z); ++ if (Math.max(distX, distZ) == viewDistance) { ++ players.add(player); ++ } ++ } ++ } else { ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ players.add(player); ++ } ++ } ++ return players.stream(); ++ // Paper end - per player view distance + } + + public void addEntity(Entity entity) { // Paper - protected -> public +@@ -1889,7 +2016,48 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + } + +- private final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER ++ // Paper start ++ private static int getLightMask(final LevelChunk chunk) { ++ final ChunkSection[] chunkSections = chunk.getSections(); ++ int mask = 0; ++ ++ for (int i = 0; i < chunkSections.length; ++i) { ++ /* ++ ++ ++Lightmasks have 18 bits, from the -1 (void) section until the 17th (air) section. ++Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. ++ ++ */ ++ mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; ++ } ++ ++ return mask; ++ } ++ ++ private static int getCeilingLightMask(final LevelChunk chunk) { ++ int mask = getLightMask(chunk); ++ ++ /* ++ It is similar to get highest bit, it would turn an 001010 into an 001111 so basically the highest bit and all below. ++ We then invert this, so we'd have 110000 and compare that to the "main" chunk. ++ This is because the bug only appears when the current chunks lightmaps are higher than those of the neighbors, thus we can omit sending neighbors which are lower than the current chunks lights. ++ ++ so TLDR is that getCeilingLightMask returns a light mask with all bits set below the highest affected section. We could also count the number of leading zeros and invert them, somehow. ++ @TODO: Implement Leafs suggestion ++ either use Integer#numberOfLeadingZeros or document what this bithack is supposed to be doing then ++ */ ++ mask |= mask >> 1; ++ mask |= mask >> 2; ++ mask |= mask >> 4; ++ mask |= mask >> 8; ++ mask |= mask >> 16; ++ ++ return mask; ++ } ++ // Paper end ++ ++ public final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER + private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { + if (packets[0] == null) { + packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass +@@ -2075,7 +2243,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkPos chunkcoordintpair = new ChunkPos(this.entity.xChunk, this.entity.zChunk); + ChunkHolder playerchunk = ChunkMap.this.getVisibleChunkIfPresent(chunkcoordintpair.toLong()); + +- if (playerchunk != null && playerchunk.getTickingChunk() != null) { ++ if (playerchunk != null && playerchunk.getSendingChunk() != null) { // Paper - no-tick view distance + flag1 = ChunkMap.checkerboardDistance(chunkcoordintpair, player, false) <= ChunkMap.this.viewDistance; + } + } +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 91c672531087430c47365657a3219ab5980d3467..c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -269,8 +269,8 @@ public abstract class DistanceManager { + return s; + } + +- protected void updatePlayerTickets(int viewDistance) { +- this.playerTicketManager.updateViewDistance(viewDistance); ++ protected void setNoTickViewDistance(int i) { // Paper - force abi breakage on usage change ++ this.playerTicketManager.updateViewDistance(i); + } + + public int getNaturalSpawnChunkCount() { +@@ -388,7 +388,7 @@ public abstract class DistanceManager { + + private void onLevelChange(long pos, int distance, boolean oldWithinViewDistance, boolean withinViewDistance) { + if (oldWithinViewDistance != withinViewDistance) { +- Ticket ticket = new Ticket<>(TicketType.PLAYER, DistanceManager.PLAYER_TICKET_LEVEL, new ChunkPos(pos)); ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkPos(pos)); // Paper - no-tick view distance + + if (withinViewDistance) { + DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 95f1f4727a8e2000931e6f36b862e3ad28334a69..8e4cef60b760be385df81a74834d026f856a78c5 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -249,6 +249,8 @@ public class ServerPlayer extends Player implements ContainerListener { + + double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks + ++ boolean needsChunkCenterUpdate; // Paper - no-tick view distance ++ + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { + super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); + this.respawnDimension = Level.OVERWORLD; +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index ffc8c9ee8b1768dd809189858ee45658fb9bf1c5..8e00747c1a717836d12a43aa48d667bf801167b0 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -250,7 +250,7 @@ public abstract class PlayerList { + boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); + + // Spigot - view distance +- playerconnection.send(new ClientboundLoginPacket(player.getId(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), worlddata.isHardcore(), this.server.levelKeys(), this.registryHolder, worldserver1.dimensionType(), worldserver1.dimension(), this.getMaxPlayers(), worldserver1.spigotConfig.viewDistance, flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat())); ++ playerconnection.send(new ClientboundLoginPacket(player.getId(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), worlddata.isHardcore(), this.server.levelKeys(), this.registryHolder, worldserver1.dimensionType(), worldserver1.dimension(), this.getMaxPlayers(), worldserver1.getChunkSource().chunkMap.getLoadViewDistance(), flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat())); // Paper - no-tick view distance + player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit + playerconnection.send(new ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.BRAND, (new FriendlyByteBuf(Unpooled.buffer())).writeUtf(this.getServer().getServerModName()))); + playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); +@@ -904,7 +904,7 @@ public abstract class PlayerList { + // CraftBukkit start + LevelData worlddata = worldserver1.getLevelData(); + entityplayer1.connection.send(new ClientboundRespawnPacket(worldserver1.dimensionType(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), entityplayer1.gameMode.getGameModeForPlayer(), entityplayer1.gameMode.getPreviousGameModeForPlayer(), worldserver1.isDebug(), worldserver1.isFlat(), flag)); +- entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.spigotConfig.viewDistance)); // Spigot ++ entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.getChunkSource().chunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance + entityplayer1.setLevel(worldserver1); + entityplayer1.removed = false; + entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.yRot, entityplayer1.xRot)); +@@ -1372,7 +1372,7 @@ public abstract class PlayerList { + + public void setViewDistance(int viewDistance) { + this.viewDistance = viewDistance; +- this.broadcastAll(new ClientboundSetChunkCacheRadiusPacket(viewDistance)); ++ //this.sendAll(new PacketPlayOutViewDistance(i)); // Paper - move into setViewDistance + Iterator iterator = this.server.getAllLevels().iterator(); + + while (iterator.hasNext()) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 5860e7866724abd35bde2a5710d9c92799e5de67..67ab681a9c9157a420de5fd872bde1fc0de24561 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -525,8 +525,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); + } + +- if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement ++ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement // Paper - diff on change, see below + this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i); ++ // Paper start - per player view distance - allow block updates for non-ticking chunks in player view distance ++ // if copied from above ++ } else if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || ((ServerLevel)this).getChunkSource().chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.getCoordinateKey(blockposition)) != null)) { ++ ((ServerLevel)this).getChunkSource().blockChanged(blockposition); ++ // Paper end - per player view distance + } + + if ((i & 1) != 0) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 8a14bdda4a408ec1e2b51efeb35467835f62b42c..dbea2a4370ccf24a5084cdabeecbc81f206e910a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -27,9 +27,14 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.network.protocol.Packet; + import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.ChunkTaskPriorityQueueSorter; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.TicketType; + import net.minecraft.util.Mth; + import net.minecraft.world.Container; + import net.minecraft.world.entity.Entity; +@@ -242,7 +247,51 @@ public class LevelChunk implements ChunkAccess { + } + + protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { ++ // Paper start - no-tick view distance ++ ServerChunkCache chunkProviderServer = ((ServerLevel)this.world).getChunkSource(); ++ ChunkMap chunkMap = chunkProviderServer.chunkMap; ++ // this code handles the addition of ticking tickets - the distance map handles the removal ++ if (!areNeighboursLoaded(bitsetBefore, 2) && areNeighboursLoaded(bitsetAfter, 2)) { ++ if (chunkMap.playerViewDistanceTickMap.getObjectsInRange(this.coordinateKey) != null) { ++ // now we're ready for entity ticking ++ chunkProviderServer.mainThreadProcessor.execute(() -> { ++ // double check that this condition still holds. ++ if (LevelChunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(LevelChunk.this.coordinateKey) != null) { ++ chunkProviderServer.addTicketAtLevel(TicketType.PLAYER, LevelChunk.this.chunkPos, 31, LevelChunk.this.chunkPos); // 31 -> entity ticking, TODO check on update ++ } ++ }); ++ } ++ } + ++ // this code handles the chunk sending ++ if (!areNeighboursLoaded(bitsetBefore, 1) && areNeighboursLoaded(bitsetAfter, 1)) { ++ if (chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(this.coordinateKey) != null) { ++ // now we're ready to send ++ chunkMap.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(chunkMap.getUpdatingChunkIfPresent(this.coordinateKey), (() -> { // Copied frm PlayerChunkMap ++ // double check that this condition still holds. ++ if (!LevelChunk.this.areNeighboursLoaded(1)) { ++ return; ++ } ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(LevelChunk.this.coordinateKey); ++ if (inRange == null) { ++ return; ++ } ++ ++ // broadcast ++ Object[] backingSet = inRange.getBackingSet(); ++ Packet[] chunkPackets = new Packet[2]; ++ for (int index = 0, len = backingSet.length; index < len; ++index) { ++ Object temp = backingSet[index]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ chunkMap.sendChunk(player, chunkPackets, LevelChunk.this); ++ } ++ }))); ++ } ++ } ++ // Paper end - no-tick view distance + } + + public final boolean isAnyNeighborsLoaded() { +@@ -1131,7 +1180,7 @@ public class LevelChunk implements ChunkAccess { + BlockState iblockdata = this.getBlockState(blockposition); + BlockState iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, (LevelAccessor) this.world, blockposition); + +- this.world.setBlock(blockposition, iblockdata1, 20); ++ this.world.setBlock(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here + } + + this.postProcessing[i].clear(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 1a839242e359fa32f32d0e571c6e918ac39642e9..4fc44390f432ef13c9952aa22bbb29bc8bf47975 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -31,6 +31,7 @@ import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; + import net.minecraft.network.protocol.game.ClientboundSetTimePacket; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.DistanceManager; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.Ticket; +@@ -2532,10 +2533,39 @@ public class CraftWorld implements World { + // Spigot start + @Override + public int getViewDistance() { +- return world.spigotConfig.viewDistance; ++ return getHandle().getChunkSource().chunkMap.getEffectiveViewDistance(); // Paper - no-tick view distance + } + // Spigot end + ++ // Paper start - per player view distance ++ @Override ++ public void setViewDistance(int viewDistance) { ++ if (viewDistance < 2 || viewDistance > 32) { ++ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); ++ } ++ ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; ++ if (viewDistance != chunkMap.getEffectiveViewDistance()) { ++ chunkMap.setViewDistance(viewDistance); ++ } ++ } ++ ++ @Override ++ public int getNoTickViewDistance() { ++ return getHandle().getChunkSource().chunkMap.getEffectiveNoTickViewDistance(); ++ } ++ ++ @Override ++ public void setNoTickViewDistance(int viewDistance) { ++ if ((viewDistance < 2 || viewDistance > 32) && viewDistance != -1) { ++ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); ++ } ++ ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; ++ if (viewDistance != chunkMap.getRawNoTickViewDistance()) { ++ chunkMap.setNoTickViewDistance(viewDistance); ++ } ++ } ++ // Paper end - per player view distance ++ + // Spigot start + private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot() + { +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 8cbafad53d20366a36493f22160c4fa3e4ac3eaf..20d5da61fc0594e86c68ea8fb5ebe5517f27f126 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -4,6 +4,7 @@ import java.util.Collection; + import net.minecraft.core.BlockPos; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.FlyingMob; +@@ -192,7 +193,7 @@ public class ActivationRange + maxRange = Math.max( maxRange, waterActivationRange ); + maxRange = Math.max( maxRange, villagerActivationRange ); + // Paper end +- maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); ++ maxRange = Math.min( ( ((ServerLevel)world).getChunkSource().chunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance + + for ( Player player : world.players() ) + { diff --git a/patches/server-remapped/0469-Add-villager-reputation-API.patch b/patches/server-remapped/0469-Add-villager-reputation-API.patch new file mode 100644 index 0000000000..771a37b8cf --- /dev/null +++ b/patches/server-remapped/0469-Add-villager-reputation-API.patch @@ -0,0 +1,155 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 22 Apr 2020 23:29:20 +0200 +Subject: [PATCH] Add villager reputation API + + +diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c6072615e95bf51c83b2f728fc3288a7043a89af +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java +@@ -0,0 +1,11 @@ ++package com.destroystokyo.paper.entity.villager; ++// Must have own package due to package-level constructor. ++ ++import Reputation; ++ ++public final class ReputationConstructor { ++ // Abuse the package-level constructor. ++ public static Reputation construct(int[] values) { ++ return new Reputation(values); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +index c4ece3ac4863067b12c10772debd1b1454bec5b4..0204f05d989d45c0848f810d1953adf0992ce3c2 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +@@ -27,7 +27,7 @@ import net.minecraft.core.SerializableUUID; + + public class GossipContainer { + +- private final Map gossips = Maps.newHashMap(); ++ private final Map gossips = Maps.newHashMap(); public Map getReputations() { return this.gossips; } // Paper - add getter for reputations + + public GossipContainer() {} + +@@ -142,11 +142,11 @@ public class GossipContainer { + return k > type.max ? Math.max(type.max, left) : k; + } + +- static class EntityGossips { ++ public static class EntityGossips { // Paper - make public + + private final Object2IntMap entries; + +- private EntityGossips() { ++ public EntityGossips() { // Paper - make public - update CraftVillager setReputation on change + this.entries = new Object2IntOpenHashMap(); + } + +@@ -200,6 +200,28 @@ public class GossipContainer { + public void remove(GossipType gossipType) { + this.entries.removeInt(gossipType); + } ++ ++ // Paper start - Add villager reputation API ++ private static final com.destroystokyo.paper.entity.villager.ReputationType[] REPUTATION_TYPES = com.destroystokyo.paper.entity.villager.ReputationType.values(); ++ public com.destroystokyo.paper.entity.villager.Reputation getPaperReputation() { ++ int[] reputation = new int[REPUTATION_TYPES.length]; ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE.ordinal()] = entries.getOrDefault(GossipType.MAJOR_NEGATIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE.ordinal()] = entries.getOrDefault(GossipType.MAJOR_POSITIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE.ordinal()] = entries.getOrDefault(GossipType.MINOR_NEGATIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE.ordinal()] = entries.getOrDefault(GossipType.MINOR_POSITIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.TRADING.ordinal()] = entries.getOrDefault(GossipType.TRADING, 0); ++ return com.destroystokyo.paper.entity.villager.ReputationConstructor.construct(reputation); ++ } ++ ++ public void assignFromPaperReputation(com.destroystokyo.paper.entity.villager.Reputation rep) { ++ int val; ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE)) != 0) this.entries.put(GossipType.MAJOR_NEGATIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE)) != 0) this.entries.put(GossipType.MAJOR_POSITIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE)) != 0) this.entries.put(GossipType.MINOR_NEGATIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE)) != 0) this.entries.put(GossipType.MINOR_POSITIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.TRADING)) != 0) this.entries.put(GossipType.TRADING, val); ++ } ++ // Paper end + } + + static class GossipEntry { +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index a83a7d37f3d769535161fda46fca6f71dcc4d515..e9912551e6a19d6ad3b20fad1b716577b9d28f99 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -1037,6 +1037,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + this.numberOfRestocksToday = 0; + } + ++ public GossipContainer getReputation() { return this.getGossips(); } // Paper - OBFHELPER + public GossipContainer getGossips() { + return this.gossips; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +index d0b933cfd02b237bfe85011831dab6e8e966496e..e3d4214ef6360b4a9949a73ba3d665ad08733b43 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +@@ -16,6 +16,13 @@ import org.bukkit.entity.Villager; + import org.bukkit.entity.Villager.Profession; + import org.bukkit.entity.Villager.Type; + ++// Paper start ++import com.destroystokyo.paper.entity.villager.Reputation; ++import com.google.common.collect.Maps; ++import java.util.Map; ++import java.util.UUID; ++// Paper end ++ + public class CraftVillager extends CraftAbstractVillager implements Villager { + + public CraftVillager(CraftServer server, net.minecraft.world.entity.npc.Villager entity) { +@@ -125,4 +132,45 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { + public static VillagerProfession bukkitToNmsProfession(Profession bukkit) { + return Registry.VILLAGER_PROFESSION.get(CraftNamespacedKey.toMinecraft(bukkit.getKey())); + } ++ ++ // Paper start - Add villager reputation API ++ @Override ++ public Reputation getReputation(UUID uniqueId) { ++ net.minecraft.world.entity.ai.gossip.GossipContainer.EntityGossips rep = getHandle().getReputation().getReputations().get(uniqueId); ++ if (rep == null) { ++ return new Reputation(Maps.newHashMap()); ++ } ++ ++ return rep.getPaperReputation(); ++ } ++ ++ @Override ++ public Map getReputations() { ++ return getHandle().getReputation().getReputations().entrySet() ++ .stream() ++ .collect(java.util.stream.Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getPaperReputation())); ++ } ++ ++ @Override ++ public void setReputation(UUID uniqueId, Reputation reputation) { ++ net.minecraft.world.entity.ai.gossip.GossipContainer.EntityGossips nmsReputation = ++ getHandle().getReputation().getReputations().computeIfAbsent( ++ uniqueId, ++ key -> new net.minecraft.world.entity.ai.gossip.GossipContainer.EntityGossips() ++ ); ++ nmsReputation.assignFromPaperReputation(reputation); ++ } ++ ++ @Override ++ public void setReputations(Map reputations) { ++ for (Map.Entry entry : reputations.entrySet()) { ++ setReputation(entry.getKey(), entry.getValue()); ++ } ++ } ++ ++ @Override ++ public void clearReputations() { ++ getHandle().getReputation().getReputations().clear(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0470-Fix-Light-Command.patch b/patches/server-remapped/0470-Fix-Light-Command.patch new file mode 100644 index 0000000000..382b91a80f --- /dev/null +++ b/patches/server-remapped/0470-Fix-Light-Command.patch @@ -0,0 +1,182 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 7 May 2020 19:17:36 -0400 +Subject: [PATCH] Fix Light Command + +This lets you run /paper fixlight (max 5) to automatically +fix all light data in the chunks. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index ff718bc7f521575e6a670e17fcf59a2d30841705..528c860fc0c04431e0ebb2ae6bc96bf9c2d04789 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -11,16 +11,20 @@ import com.google.common.collect.Maps; + import com.google.gson.JsonObject; + import com.google.gson.internal.Streams; + import com.google.gson.stream.JsonWriter; ++import net.minecraft.core.BlockPos; ++import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.ThreadedLevelLightEngine; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; +-import net.minecraft.server.MCUtil; ++import net.minecraft.world.level.chunk.LevelChunk; + import org.apache.commons.lang3.tuple.MutablePair; + import org.apache.commons.lang3.tuple.Pair; + import org.bukkit.Bukkit; +@@ -31,6 +35,7 @@ import org.bukkit.command.Command; + import org.bukkit.command.CommandSender; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftPlayer; + import org.bukkit.entity.Player; + + import java.io.File; +@@ -39,10 +44,12 @@ import java.io.PrintStream; + import java.io.StringWriter; + import java.time.LocalDateTime; + import java.time.format.DateTimeFormatter; ++import java.util.ArrayDeque; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collection; + import java.util.Collections; ++import java.util.Deque; + import java.util.Iterator; + import java.util.List; + import java.util.Locale; +@@ -52,7 +59,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); + + public PaperCommand(String name) { + super(name); +@@ -173,6 +180,9 @@ public class PaperCommand extends Command { + case "syncloadinfo": + this.doSyncLoadInfo(sender, args); + break; ++ case "fixlight": ++ this.doFixLight(sender, args); ++ break; + case "ver": + if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) + case "version": +@@ -190,6 +200,77 @@ public class PaperCommand extends Command { + return true; + } + ++ private void doFixLight(CommandSender sender, String[] args) { ++ if (!(sender instanceof Player)) { ++ sender.sendMessage("Only players can use this command"); ++ return; ++ } ++ int radius = 2; ++ if (args.length > 1) { ++ try { ++ radius = Math.min(5, Integer.parseInt(args[1])); ++ } catch (Exception e) { ++ sender.sendMessage("Not a number"); ++ return; ++ } ++ ++ } ++ ++ CraftPlayer player = (CraftPlayer) sender; ++ ServerPlayer handle = player.getHandle(); ++ ServerLevel world = (ServerLevel) handle.level; ++ ThreadedLevelLightEngine lightengine = world.getChunkSource().getLightEngine(); ++ ++ BlockPos center = MCUtil.toBlockPosition(player.getLocation()); ++ Deque queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius)); ++ updateLight(sender, world, lightengine, queue); ++ } ++ ++ private void updateLight(CommandSender sender, ServerLevel world, ThreadedLevelLightEngine lightengine, Deque queue) { ++ ChunkPos coord = queue.poll(); ++ if (coord == null) { ++ sender.sendMessage("All Chunks Light updated"); ++ return; ++ } ++ world.getChunkSource().getChunkAtAsynchronously(coord.x, coord.z, false, false).whenCompleteAsync((either, ex) -> { ++ if (ex != null) { ++ sender.sendMessage("Error loading chunk " + coord); ++ updateLight(sender, world, lightengine, queue); ++ return; ++ } ++ LevelChunk chunk = (LevelChunk) either.left().orElse(null); ++ if (chunk == null) { ++ updateLight(sender, world, lightengine, queue); ++ return; ++ } ++ lightengine.setTaskPerBatch(world.paperConfig.lightQueueSize + 16 * 256); // ensure full chunk can fit into queue ++ sender.sendMessage("Updating Light " + coord); ++ int cx = chunk.getPos().x << 4; ++ int cz = chunk.getPos().z << 4; ++ for (int y = 0; y < world.getHeight(); y++) { ++ for (int x = 0; x < 16; x++) { ++ for (int z = 0; z < 16; z++) { ++ BlockPos pos = new BlockPos(cx + x, y, cz + z); ++ lightengine.checkBlock(pos); ++ } ++ } ++ } ++ lightengine.tryScheduleUpdate(); ++ ChunkHolder visibleChunk = world.getChunkSource().chunkMap.getVisibleChunkIfPresent(chunk.coordinateKey); ++ if (visibleChunk != null) { ++ world.getChunkSource().chunkMap.addLightTask(visibleChunk, () -> { ++ MinecraftServer.getServer().processQueue.add(() -> { ++ visibleChunk.sendPacketToTrackedPlayers(new ClientboundLightUpdatePacket(chunk.getPos(), lightengine, true), false); ++ updateLight(sender, world, lightengine, queue); ++ }); ++ }); ++ } else { ++ updateLight(sender, world, lightengine, queue); ++ } ++ lightengine.setTaskPerBatch(world.paperConfig.lightQueueSize); ++ }, MinecraftServer.getServer()); ++ } ++ + private void doSyncLoadInfo(CommandSender sender, String[] args) { + if (!SyncLoadFinder.ENABLED) { + sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 9ebcfca10071cc42d4f1df02c25de5042c065f38..d907872d80f840b343419f49a6708082da6f921b 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -349,6 +349,7 @@ public class ChunkHolder { + + } + ++ public void sendPacketToTrackedPlayers(Packet packet, boolean flag) { broadcast(packet, flag); } // Paper - OBFHELPER + private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { + // Paper start - per player view distance + // there can be potential desync with player's last mapped section and the view distance map, so use the +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 6b51a082cf42bc3ffc550614e385d3956c5f2efb..67f748d5955453ba4873b0c9bb741b5bfe52d655 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -344,11 +344,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ProcessorHandle mailbox = ProcessorHandle.of("main", mainThreadExecutor::tell); + + this.progressListener = worldGenerationProgressListener; +- ProcessorMailbox threadedmailbox1 = ProcessorMailbox.create(workerExecutor, "light"); ++ ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(workerExecutor, "light"); // Paper + + this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), workerExecutor, Integer.MAX_VALUE); + this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); + this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); ++ this.mailboxLight = this.queueSorter.getProcessor(lightthreaded, false);// Paper + this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); + this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper + this.overworldDataStorage = supplier; diff --git a/patches/server-remapped/0471-Fix-PotionEffect-ignores-icon-flag.patch b/patches/server-remapped/0471-Fix-PotionEffect-ignores-icon-flag.patch new file mode 100644 index 0000000000..5968f9b0c8 --- /dev/null +++ b/patches/server-remapped/0471-Fix-PotionEffect-ignores-icon-flag.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Fri, 8 May 2020 00:49:18 -0400 +Subject: [PATCH] Fix PotionEffect ignores icon flag + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 5dac3bf5a117bfbf57798238f0614558deafcd1b..067eaf1e05ced344eb168431403f3fe786eafddf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -408,7 +408,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + + @Override + public boolean addPotionEffect(PotionEffect effect, boolean force) { +- getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN); ++ getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon + return true; + } + diff --git a/patches/server-remapped/0472-Optimize-brigadier-child-sorting-performance.patch b/patches/server-remapped/0472-Optimize-brigadier-child-sorting-performance.patch new file mode 100644 index 0000000000..d213e040be --- /dev/null +++ b/patches/server-remapped/0472-Optimize-brigadier-child-sorting-performance.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: virustotalop +Date: Thu, 16 Apr 2020 20:51:32 -0700 +Subject: [PATCH] Optimize brigadier child sorting performance + + +diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +index 120234605433165d1c78986b5f0f130e64c5a20a..5c35cef42af4053332c02b4960c227fe95d4c197 100644 +--- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java ++++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +@@ -26,7 +26,7 @@ import java.util.stream.Collectors; + import net.minecraft.commands.CommandSourceStack; + + public abstract class CommandNode implements Comparable> { +- private Map> children = Maps.newLinkedHashMap(); ++ private Map> children = Maps.newTreeMap(); //Paper - Switch to tree map for automatic sorting + private Map> literals = Maps.newLinkedHashMap(); + private Map> arguments = Maps.newLinkedHashMap(); + private final Predicate requirement; +@@ -106,8 +106,7 @@ public abstract class CommandNode implements Comparable> { + arguments.put(node.getName(), (ArgumentCommandNode) node); + } + } +- +- children = children.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); ++ //Paper - Remove manual sorting, it is no longer needed + } + + public void findAmbiguities(final AmbiguityConsumer consumer) { diff --git a/patches/server-remapped/0473-Potential-bed-API.patch b/patches/server-remapped/0473-Potential-bed-API.patch new file mode 100644 index 0000000000..efd1703506 --- /dev/null +++ b/patches/server-remapped/0473-Potential-bed-API.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Sun, 10 May 2020 23:06:30 -0400 +Subject: [PATCH] Potential bed API + +Adds a new method to fetch the location of a player's bed without generating any sync loads. + +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/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index ae6faa331fcbefd99ee1cd92c88926d767fc50ee..878a62e04962aafeaf192075fbe08e319298a800 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -12,6 +12,7 @@ import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; + import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.MenuProvider; + import net.minecraft.world.entity.Entity; +@@ -126,6 +127,22 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + return getHandle().sleepCounter; + } + ++ // Paper start - Potential bed api ++ @Override ++ public Location getPotentialBedLocation() { ++ ServerPlayer handle = (ServerPlayer) getHandle(); ++ BlockPos bed = handle.getRespawnPosition(); ++ if (bed == null) { ++ return null; ++ } ++ ++ ServerLevel worldServer = handle.server.getLevel(handle.getRespawnDimension()); ++ if (worldServer == null) { ++ return null; ++ } ++ return new Location(worldServer.getWorld(), bed.getX(), bed.getY(), bed.getZ()); ++ } ++ // Paper end + @Override + public boolean sleep(Location location, boolean force) { + Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/patches/server-remapped/0474-Wait-for-Async-Tasks-during-shutdown.patch b/patches/server-remapped/0474-Wait-for-Async-Tasks-during-shutdown.patch new file mode 100644 index 0000000000..dea3aa2ef9 --- /dev/null +++ b/patches/server-remapped/0474-Wait-for-Async-Tasks-during-shutdown.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 May 2020 22:16:17 -0400 +Subject: [PATCH] Wait for Async Tasks during shutdown + +Server.reload() had this logic to give time for tasks to shutdown, +however shutdown did not... + +Adds a 5 second grace period for any async tasks to finish and warns +if any are still running after that delay just as reload does. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 74f393ffa2ae2d0e25b3f0b674cef7a987e985d3..f530c739b6aee3718eb5d0e0e6a09d882d817c68 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -892,6 +892,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { ++ try { ++ Thread.sleep(100); ++ } catch (InterruptedException e) {} ++ pollCount++; ++ } ++ ++ List overdueWorkers = getScheduler().getActiveWorkers(); ++ for (BukkitWorker worker : overdueWorkers) { ++ Plugin plugin = worker.getOwner(); ++ String author = ""; ++ if (plugin.getDescription().getAuthors().size() > 0) { ++ author = plugin.getDescription().getAuthors().get(0); ++ } ++ getLogger().log(Level.SEVERE, String.format( ++ "Nag author: '%s' of '%s' about the following: %s", ++ author, ++ plugin.getDescription().getName(), ++ "This plugin is not properly shutting down its async tasks when it is being shut down. This task may throw errors during the final shutdown logs and might not complete before process dies." ++ )); ++ } ++ } ++ // Paper end ++ + @Override + public void reloadData() { + ReloadCommand.reload(console); diff --git a/patches/server-remapped/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/patches/server-remapped/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch new file mode 100644 index 0000000000..99d8f1263a --- /dev/null +++ b/patches/server-remapped/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Sat, 9 May 2020 02:01:48 -0400 +Subject: [PATCH] Ensure EntityRaider respects game and entity rules for + picking up items + + +diff --git a/src/main/java/net/minecraft/world/entity/raid/Raider.java b/src/main/java/net/minecraft/world/entity/raid/Raider.java +index 6406b0a03b67ea61083b704cd24b9b25a0f33c87..5502615be430d9eba0c1c68e3f10826d75b08672 100644 +--- a/src/main/java/net/minecraft/world/entity/raid/Raider.java ++++ b/src/main/java/net/minecraft/world/entity/raid/Raider.java +@@ -523,7 +523,7 @@ public abstract class Raider extends PatrollingMonster { + + public class ObtainRaidLeaderBannerGoal extends Goal { + +- private final T mob; ++ private final T mob; private T getRaider() { return mob; } // Paper - obfhelper + + public ObtainRaidLeaderBannerGoal(T entityraider) { // CraftBukkit - decompile error + this.mob = entityraider; +@@ -532,6 +532,7 @@ public abstract class Raider extends PatrollingMonster { + + @Override + public boolean canUse() { ++ if (!getRaider().level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || !getRaider().canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items + Raid raid = this.mob.getCurrentRaid(); + + if (this.mob.hasActiveRaid() && !this.mob.getCurrentRaid().isOver() && this.mob.canBeLeader() && !ItemStack.matches(this.mob.getItemBySlot(EquipmentSlot.HEAD), Raid.getLeaderBannerInstance())) { diff --git a/patches/server-remapped/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server-remapped/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch new file mode 100644 index 0000000000..99a5355669 --- /dev/null +++ b/patches/server-remapped/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch @@ -0,0 +1,173 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 13 May 2020 23:01:26 -0400 +Subject: [PATCH] Protect Bedrock and End Portal/Frames from being destroyed + +This fixes exploits that let players destroy bedrock by Pistons, explosions +and Mushrooom/Tree generation. + +These blocks are designed to not be broken except by creative players/commands. +So protect them from a multitude of methods of destroying them. + +A config is provided if you rather let players use these exploits, and let +them destroy the worlds End Portals and get on top of the nether easy. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 78271b400c79578d043b20a5389a37b1bef9a70d..5f3b0d95cc7e6a0434d78ea7305a70689c41c71c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -416,4 +416,17 @@ public class PaperConfig { + private static void midTickChunkTasks() { + midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); + } ++ ++ public static boolean allowBlockPermanentBreakingExploits = false; ++ private static void allowBlockPermanentBreakingExploits() { ++ if (config.contains("allow-perm-block-break-exploits")) { ++ allowBlockPermanentBreakingExploits = config.getBoolean("allow-perm-block-break-exploits", false); ++ config.set("allow-perm-block-break-exploits", null); ++ } ++ ++ config.set("settings.unsupported-settings.allow-permanent-block-break-exploits-readme", "This setting controls if players should be able to break bedrock, end portals and other intended to be permanent blocks."); ++ allowBlockPermanentBreakingExploits = getBoolean("settings.unsupported-settings.allow-permanent-block-break-exploits", allowBlockPermanentBreakingExploits); ++ ++ } ++ + } +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 667a6d645034c67639c01b8221591877bcb87b35..0f0a5fa2be5a7c69291b593a04cad83e069ba5b1 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -151,6 +151,7 @@ public class Explosion { + for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { + BlockPos blockposition = new BlockPos(d4, d5, d6); + BlockState iblockdata = this.level.getBlockState(blockposition); ++ if (!iblockdata.isDestroyable()) continue; // Paper + FluidState fluid = iblockdata.getFluidState(); // Paper + Optional optional = this.damageCalculator.a(this, this.level, blockposition, iblockdata, fluid); + +@@ -304,7 +305,7 @@ public class Explosion { + BlockState iblockdata = this.level.getBlockState(blockposition); + Block block = iblockdata.getBlock(); + +- if (!iblockdata.isAir()) { ++ if (!iblockdata.isAir() && iblockdata.isDestroyable()) { // Paper + BlockPos blockposition1 = blockposition.immutable(); + + this.level.getProfiler().push("explosion_blocks"); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 67ab681a9c9157a420de5fd872bde1fc0de24561..9b50b8030174338c04b60d441b980131e1d593e4 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -422,6 +422,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { + // CraftBukkit start - tree generation + if (this.captureTreeGeneration) { ++ // Paper start ++ BlockState type = getBlockState(pos); ++ if (!type.isDestroyable()) return false; ++ // Paper end + CraftBlockState blockstate = capturedBlockStates.get(pos); + if (blockstate == null) { + blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index fca5d175cbef24fb0ee2d0bbedc8d1c0af3eb528..5b84ee4091e354c4b6500f58a31931f2a6827ffc 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -62,6 +62,19 @@ public class Block extends BlockBehaviour implements ItemLike { + protected final StateDefinition stateDefinition; + private BlockState defaultBlockState; + // Paper start ++ public final boolean isDestroyable() { ++ return com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || ++ this != Blocks.BEDROCK && ++ this != Blocks.END_PORTAL_FRAME && ++ this != Blocks.END_PORTAL && ++ this != Blocks.END_GATEWAY && ++ this != Blocks.COMMAND_BLOCK && ++ this != Blocks.REPEATING_COMMAND_BLOCK && ++ this != Blocks.CHAIN_COMMAND_BLOCK && ++ this != Blocks.BARRIER && ++ this != Blocks.STRUCTURE_BLOCK && ++ this != Blocks.JIGSAW; ++ } + public co.aikar.timings.Timing timing; + public co.aikar.timings.Timing getTiming() { + if (timing == null) { +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +index dc9584a30c18d964afd9cc118c81c24a80beba63..40a18302dd682e5ade4ec77ac7f316b6c0f8c112 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -193,6 +193,12 @@ public class PistonBaseBlock extends DirectionalBlock { + @Override + public boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) { + Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING); ++ // Paper start - prevent retracting when we're facing the wrong way (we were replaced before retraction could occur) ++ Direction directionQueuedAs = Direction.from3DDataValue(data & 7); // Paper - copied from below ++ if (!com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits && enumdirection != directionQueuedAs) { ++ return false; ++ } ++ // Paper end - prevent retracting when we're facing the wrong way + + if (!world.isClientSide) { + boolean flag = this.getNeighborSignal(world, pos, enumdirection); +@@ -224,7 +230,7 @@ public class PistonBaseBlock extends DirectionalBlock { + BlockState iblockdata1 = (BlockState) ((BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, enumdirection)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); + + world.setBlock(pos, iblockdata1, 20); +- world.setBlockEntity(pos, MovingPistonBlock.newMovingBlockEntity((BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); ++ world.setBlockEntity(pos, MovingPistonBlock.newMovingBlockEntity((BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - diff on change, j is facing direction - copy this above + world.blockUpdated(pos, iblockdata1.getBlock()); + iblockdata1.updateNeighbourShapes(world, pos, 2); + if (this.isSticky) { +@@ -253,7 +259,14 @@ public class PistonBaseBlock extends DirectionalBlock { + } + } + } else { +- world.removeBlock(pos.relative(enumdirection), false); ++ // Paper start - fix headless pistons breaking blocks ++ BlockPos headPos = pos.relative(enumdirection); ++ if (com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || world.getBlockState(headPos) == Blocks.PISTON_HEAD.defaultBlockState().setValue(FACING, enumdirection)) { // double check to make sure we're not a headless piston. ++ world.setAir(headPos, false); ++ } else { ++ ((ServerLevel)world).getChunkSource().blockChanged(headPos); // ... fix client desync ++ } ++ // Paper end - fix headless pistons breaking blocks + } + + world.playSound((Player) null, pos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F); +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index 57eedaeedaa24bd274fb55c6e4521f1305382645..df2836b071158729728411f5b228cc38dddd4d4e 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -189,7 +189,7 @@ public abstract class BlockBehaviour { + + @Deprecated + public boolean canBeReplaced(BlockState state, BlockPlaceContext context) { +- return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || context.getItemInHand().getItem() != this.asItem()); ++ return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || context.getItemInHand().getItem() != this.asItem()) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().abilities.instabuild)); // Paper + } + + @Deprecated +@@ -393,7 +393,11 @@ public abstract class BlockBehaviour { + public Block getBlock() { + return (Block) this.owner; + } +- ++ // Paper start ++ public final boolean isDestroyable() { ++ return getBlock().isDestroyable(); ++ } ++ // Paper end + public Material getMaterial() { + return this.material; + } +@@ -483,7 +487,7 @@ public abstract class BlockBehaviour { + } + + public PushReaction getPistonPushReaction() { +- return this.getBlock().getPistonPushReaction(this.asState()); ++ return !isDestroyable() ? PushReaction.BLOCK : this.getBlock().getPistonPushReaction(this.asState()); // Paper + } + + public boolean isSolidRender(BlockGetter world, BlockPos pos) { diff --git a/patches/server-remapped/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch b/patches/server-remapped/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch new file mode 100644 index 0000000000..9cdcec0403 --- /dev/null +++ b/patches/server-remapped/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch @@ -0,0 +1,394 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 May 2020 23:30:30 -0400 +Subject: [PATCH] Optimize NibbleArray to use pooled buffers + +Massively reduces memory allocation of 2048 byte buffers by using +an object pool for these. + +Uses lots of advanced new capabilities of the Paper codebase :) + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java +index bc1b4cc2e0a4181bde5ac05ce0a20a651cb0c4c3..902f14e2e5ac5aa11b545a68ac69e9b0282df7f4 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java +@@ -1,12 +1,16 @@ + package net.minecraft.network.protocol.game; + + import com.google.common.collect.Lists; ++import io.netty.channel.ChannelFuture; // Paper ++ + import java.io.IOException; + import java.util.Iterator; + import java.util.List; + import net.minecraft.core.SectionPos; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.chunk.DataLayer; +@@ -24,14 +28,43 @@ public class ClientboundLightUpdatePacket implements Packet blockUpdates; + private boolean trustEdges; + ++ // Paper start ++ java.lang.Runnable cleaner1; ++ java.lang.Runnable cleaner2; ++ java.util.concurrent.atomic.AtomicInteger remainingSends = new java.util.concurrent.atomic.AtomicInteger(0); ++ ++ @Override ++ public void onPacketDispatch(ServerPlayer player) { ++ remainingSends.incrementAndGet(); ++ } ++ ++ @Override ++ public void onPacketDispatchFinish(ServerPlayer player, ChannelFuture future) { ++ if (remainingSends.decrementAndGet() <= 0) { ++ // incase of any race conditions, schedule this delayed ++ MCUtil.scheduleTask(5, () -> { ++ if (remainingSends.get() == 0) { ++ cleaner1.run(); ++ cleaner2.run(); ++ } ++ }, "Light Packet Release"); ++ } ++ } ++ ++ @Override ++ public boolean hasFinishListener() { ++ return true; ++ } ++ ++ // Paper end + public ClientboundLightUpdatePacket() {} + + public ClientboundLightUpdatePacket(ChunkPos chunkcoordintpair, LevelLightEngine lightengine, boolean flag) { + this.x = chunkcoordintpair.x; + this.z = chunkcoordintpair.z; + this.trustEdges = flag; +- this.skyUpdates = Lists.newArrayList(); +- this.blockUpdates = Lists.newArrayList(); ++ this.skyUpdates = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.skyUpdates, DataLayer::releaseBytes); // Paper ++ this.blockUpdates = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.blockUpdates, DataLayer::releaseBytes); // Paper + + for (int i = 0; i < 18; ++i) { + DataLayer nibblearray = lightengine.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, -1 + i)); +@@ -42,7 +75,7 @@ public class ClientboundLightUpdatePacket implements Packet BYTE_2048 = new PooledObjects<>(() -> new byte[2048], maxPoolSize); ++ public static void releaseBytes(byte[] bytes) { ++ if (bytes != null && bytes != EMPTY_NIBBLE && bytes.length == 2048) { ++ System.arraycopy(EMPTY_NIBBLE, 0, bytes, 0, 2048); ++ BYTE_2048.release(bytes); ++ } ++ } ++ ++ public DataLayer markPoolSafe(byte[] bytes) { ++ if (bytes != EMPTY_NIBBLE) this.data = bytes; ++ return markPoolSafe(); ++ } ++ public DataLayer markPoolSafe() { ++ poolSafe = true; ++ return this; ++ } ++ public byte[] getIfSet() { ++ return this.data != null ? this.data : EMPTY_NIBBLE; ++ } ++ public byte[] getCloneIfSet() { ++ if (data == null) { ++ return EMPTY_NIBBLE; ++ } ++ byte[] ret = BYTE_2048.acquire(); ++ System.arraycopy(getIfSet(), 0, ret, 0, 2048); ++ return ret; ++ } ++ ++ public DataLayer cloneAndSet(byte[] bytes) { ++ if (bytes != null && bytes != EMPTY_NIBBLE) { ++ this.data = BYTE_2048.acquire(); ++ System.arraycopy(bytes, 0, this.data, 0, 2048); ++ } ++ return this; ++ } ++ boolean poolSafe = false; ++ public java.lang.Runnable cleaner; ++ private void registerCleaner() { ++ if (!poolSafe) { ++ cleaner = MCUtil.registerCleaner(this, this.data, DataLayer::releaseBytes); ++ } else { ++ cleaner = MCUtil.once(() -> DataLayer.releaseBytes(this.data)); ++ } ++ } ++ // Paper end ++ @Nullable protected byte[] data; ++ + + public DataLayer() {} + + public DataLayer(byte[] abyte) { ++ // Paper start ++ this(abyte, false); ++ } ++ public DataLayer(byte[] abyte, boolean isSafe) { + this.data = abyte; ++ if (!isSafe) this.data = getCloneIfSet(); // Paper - clone for safety ++ registerCleaner(); ++ // Paper end + if (abyte.length != 2048) { + throw (IllegalArgumentException) Util.pauseInIde((Throwable) (new IllegalArgumentException("ChunkNibbleArrays should be 2048 bytes not: " + abyte.length))); + } +@@ -46,7 +106,8 @@ public class DataLayer { + + public void set(int index, int value) { // PAIL: private -> public + if (this.data == null) { +- this.data = new byte[2048]; ++ this.data = BYTE_2048.acquire(); // Paper ++ registerCleaner();// Paper + } + + int k = this.getPosition(index); +@@ -68,14 +129,36 @@ public class DataLayer { + public byte[] getData() { + if (this.data == null) { + this.data = new byte[2048]; ++ } else { // Paper start ++ // Accessor may need this object past garbage collection so need to clone it and return pooled value ++ // If we know its safe for pre GC access, use asBytesPoolSafe(). If you just need read, use getIfSet() ++ Runnable cleaner = this.cleaner; ++ if (cleaner != null) { ++ this.data = this.data.clone(); ++ cleaner.run(); // release the previously pooled value ++ this.cleaner = null; ++ } ++ } ++ // Paper end ++ ++ return this.data; ++ } ++ ++ @Nonnull ++ public byte[] asBytesPoolSafe() { ++ if (this.data == null) { ++ this.data = BYTE_2048.acquire(); // Paper ++ registerCleaner(); // Paper + } + ++ //noinspection ConstantConditions + return this.data; + } ++ // Paper end + + public DataLayer copy() { return this.copy(); } // Paper - OBFHELPER + public DataLayer copy() { +- return this.data == null ? new DataLayer() : new DataLayer((byte[]) this.data.clone()); ++ return this.data == null ? new DataLayer() : new DataLayer(this.data); // Paper - clone in ctor + } + + public String toString() { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 6c28a611b9b79c3322ab07883972c07b3bfc3073..1e58958c3d7b10da5a5f22fc9591d9183e53e3cc 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -435,11 +435,11 @@ public class ChunkSerializer { + } + + if (nibblearray != null && !nibblearray.isEmpty()) { +- nbttagcompound2.putByteArray("BlockLight", nibblearray.getData()); ++ nbttagcompound2.putByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper + } + + if (nibblearray1 != null && !nibblearray1.isEmpty()) { +- nbttagcompound2.putByteArray("SkyLight", nibblearray1.getData()); ++ nbttagcompound2.putByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper + } + + nbttaglist.add(nbttagcompound2); +diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +index 4c9041f1c1cb4b3ec114fbd0c5d4db50a6f2526d..54cca3b376e5ce02936edc8b9c17e67e17f07147 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java ++++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.lighting; + + import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; + import javax.annotation.Nullable; ++import net.minecraft.server.MCUtil; + import net.minecraft.world.level.chunk.DataLayer; + + public abstract class DataLayerStorageMap> { +@@ -34,7 +35,9 @@ public abstract class DataLayerStorageMap> { + + public void copyDataLayer(long pos) { + if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data +- this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data ++ DataLayer updating = this.data.getUpdating(pos); // Paper - pool nibbles ++ this.data.queueUpdate(pos, new DataLayer().markPoolSafe(updating.getCloneIfSet())); // Paper - avoid copying light data - pool safe clone ++ if (updating.cleaner != null) MCUtil.scheduleTask(2, updating.cleaner, "Light Engine Release"); // Paper - delay clean incase anything holding ref was still using it + this.clearCache(); + } + +diff --git a/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java b/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java +index 9b95ae0ff193d7f52650f406c70e76e3f7e07e1c..c0d356ac4d54b952fe9ddaf5125b07177ac44d1f 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java ++++ b/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java +@@ -10,7 +10,7 @@ public class FlatDataLayer extends DataLayer { + + public FlatDataLayer(DataLayer nibblearray, int i) { + super(128); +- System.arraycopy(nibblearray.getData(), i * 128, this.data, 0, 128); ++ System.arraycopy(nibblearray.getIfSet(), i * 128, this.data, 0, 128); // Paper + } + + @Override +@@ -20,7 +20,7 @@ public class FlatDataLayer extends DataLayer { + + @Override + public byte[] getData() { +- byte[] abyte = new byte[2048]; ++ byte[] abyte = BYTE_2048.acquire(); // Paper + + for (int i = 0; i < 16; ++i) { + System.arraycopy(this.data, 0, abyte, i * 128, 128); +diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +index 177dae992d13674bb285a60b8427df9ea843dc99..5757bcfded35f112d52a7c81586850ba50e0d8dd 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +@@ -156,7 +156,7 @@ public abstract class LayerLightSectionStorage> + protected DataLayer createDataLayer(long sectionPos) { + DataLayer nibblearray = (DataLayer) this.queuedSections.get(sectionPos); + +- return nibblearray != null ? nibblearray : new DataLayer(); ++ return nibblearray != null ? nibblearray : new DataLayer().markPoolSafe(); // Paper + } + + protected void clearQueuedSectionBlocks(LayerLightEngine storage, long sectionPos) { +@@ -338,12 +338,12 @@ public abstract class LayerLightSectionStorage> + + protected void queueSectionData(long sectionPos, @Nullable DataLayer array, boolean flag) { + if (array != null) { +- this.queuedSections.put(sectionPos, array); ++ DataLayer remove = this.queuedSections.put(sectionPos, array); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed + if (!flag) { + this.untrustedSections.add(sectionPos); + } + } else { +- this.queuedSections.remove(sectionPos); ++ DataLayer remove = this.queuedSections.remove(sectionPos); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed + } + + } +diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +index 410fcfa8c01b7e3d3e3829ebdb92a11badff16ea..88f168f9d4c29cfc93500227bf8a60de4b6e4d8a 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +@@ -172,9 +172,9 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage +Date: Mon, 27 Apr 2020 02:48:06 -0700 +Subject: [PATCH] Reduce MutableInt allocations from light engine + +We can abuse the fact light is single threaded and share an instance +per light engine instance + +diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java +index 8979101a52537f4ec03a5f43030264b8e72fcea4..709fc42057f8a0282c3c942067e63abb874d9042 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java ++++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java +@@ -16,6 +16,7 @@ public final class BlockLightEngine extends LayerLightEngine= 15) { +diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java +index d99890121bdf1e499e364bdc953e628c04d69b95..ff1fbc46776b26ca56c3293e40ed55028230ec46 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java +@@ -15,6 +15,7 @@ public final class SkyLightEngine extends LayerLightEngine= 15) { + return level; + } else { +- MutableInt mutableint = new MutableInt(); ++ //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded + BlockState iblockdata = this.getStateAndOpacity(targetId, mutableint); + + if (mutableint.getValue() >= 15) { diff --git a/patches/server-remapped/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/patches/server-remapped/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch new file mode 100644 index 0000000000..6751467281 --- /dev/null +++ b/patches/server-remapped/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 27 Apr 2020 00:04:16 -0700 +Subject: [PATCH] Reduce allocation of Vec3D by entity tracker + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 67f748d5955453ba4873b0c9bb741b5bfe52d655..738f1183ce663db7c67d2f0289823390a7f06a0e 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -95,7 +95,6 @@ import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelStorageSource; +-import net.minecraft.world.phys.Vec3; + import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper + import org.apache.commons.lang3.mutable.MutableBoolean; + import org.apache.logging.log4j.LogManager; +@@ -2233,9 +2232,14 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + public void updatePlayer(ServerPlayer player) { + org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot + if (player != this.entity) { +- Vec3 vec3d = player.position().subtract(this.entity.position()); // MC-155077, SPIGOT-5113 ++ // Paper start - remove allocation of Vec3D here ++ //Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 ++ double vec3d_dx = player.getX() - this.entity.getX(); ++ double vec3d_dy = player.getY() - this.entity.getY(); ++ double vec3d_dz = player.getZ() - this.entity.getZ(); ++ // Paper end - remove allocation of Vec3D here + int i = Math.min(this.getEffectiveRange(), (ChunkMap.this.viewDistance - 1) * 16); +- boolean flag = vec3d.x >= (double) (-i) && vec3d.x <= (double) i && vec3d.z >= (double) (-i) && vec3d.z <= (double) i && this.entity.broadcastToPlayer(player); ++ boolean flag = vec3d_dx >= (double) (-i) && vec3d_dx <= (double) i && vec3d_dz >= (double) (-i) && vec3d_dz <= (double) i && this.entity.broadcastToPlayer(player); // Paper - remove allocation of Vec3D here + + if (flag) { + boolean flag1 = this.entity.forcedLoading; +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index d797873db52ba265ac4478f9f3c6344badd4739e..75e2274578c2c28de3d786372df0b4102337a2cc 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -154,8 +154,12 @@ public class ServerEntity { + ++this.teleportDelay; + i = Mth.floor(this.entity.yRot * 256.0F / 360.0F); + j = Mth.floor(this.entity.xRot * 256.0F / 360.0F); +- Vec3 vec3d = this.entity.position().subtract(ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp)); +- boolean flag1 = vec3d.lengthSqr() >= 7.62939453125E-6D; ++ // Paper start - reduce allocation of Vec3D here ++ double vec3d_dx = this.entity.getX() - 2.44140625E-4D*(this.xp); ++ double vec3d_dy = this.entity.getY() - 2.44140625E-4D*(this.yp); ++ double vec3d_dz = this.entity.getZ() - 2.44140625E-4D*(this.zp); ++ boolean flag1 = (vec3d_dx * vec3d_dx + vec3d_dy * vec3d_dy + vec3d_dz * vec3d_dz) >= 7.62939453125E-6D; ++ // Paper end - reduce allocation of Vec3D here + Packet packet1 = null; + boolean flag2 = flag1 || this.tickCount % 60 == 0; + boolean flag3 = Math.abs(i - this.yRotp) >= 1 || Math.abs(j - this.xRotp) >= 1; +@@ -172,9 +176,11 @@ public class ServerEntity { + // CraftBukkit end + + if (this.tickCount > 0 || this.entity instanceof AbstractArrow) { +- long k = ClientboundMoveEntityPacket.entityToPacket(vec3d.x); +- long l = ClientboundMoveEntityPacket.entityToPacket(vec3d.y); +- long i1 = ClientboundMoveEntityPacket.entityToPacket(vec3d.z); ++ // Paper start - remove allocation of Vec3D here ++ long k = ClientboundMoveEntityPacket.entityToPacket(vec3d_dx); ++ long l = ClientboundMoveEntityPacket.entityToPacket(vec3d_dy); ++ long i1 = ClientboundMoveEntityPacket.entityToPacket(vec3d_dz); ++ // Paper end - remove allocation of Vec3D here + boolean flag4 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L; + + if (!flag4 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.isOnGround()) { diff --git a/patches/server-remapped/0480-Ensure-safe-gateway-teleport.patch b/patches/server-remapped/0480-Ensure-safe-gateway-teleport.patch new file mode 100644 index 0000000000..3ca91f50a5 --- /dev/null +++ b/patches/server-remapped/0480-Ensure-safe-gateway-teleport.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Fri, 15 May 2020 01:10:03 -0400 +Subject: [PATCH] Ensure safe gateway teleport + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +index b70e0633435a272ae1e9fbd12d7f18862de0b951..3491956cb09b825bbfc99667b058d67cef127332 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -86,9 +86,14 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements + } else if (!this.level.isClientSide) { + List list = this.level.getEntitiesOfClass(Entity.class, new AABB(this.getBlockPos()), TheEndGatewayBlockEntity::canEntityTeleport); + +- if (!list.isEmpty()) { +- this.teleportEntity((Entity) list.get(this.level.random.nextInt(list.size()))); ++ // Paper start ++ for (Entity entity : list) { ++ if (entity.canChangeDimensions()) { ++ this.teleportEntity(entity); ++ break; ++ } + } ++ // Paper end + + if (this.age % 2400L == 0L) { + this.triggerCooldown(); diff --git a/patches/server-remapped/0481-Add-option-for-console-having-all-permissions.patch b/patches/server-remapped/0481-Add-option-for-console-having-all-permissions.patch new file mode 100644 index 0000000000..61d650c223 --- /dev/null +++ b/patches/server-remapped/0481-Add-option-for-console-having-all-permissions.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 16 May 2020 10:12:15 +0200 +Subject: [PATCH] Add option for console having all permissions + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 5f3b0d95cc7e6a0434d78ea7305a70689c41c71c..7f140333c2e62012fa572c1a061d84432426997f 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -429,4 +429,9 @@ public class PaperConfig { + + } + ++ public static boolean consoleHasAllPermissions = false; ++ private static void consoleHasAllPermissions() { ++ consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); ++ } ++ + } +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 525cd44411b344bc4b5d43c087094fea88fa41a6..4817b8ab259d348b48bc325d34ba9351ffe951df 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1886,7 +1886,7 @@ public abstract class Player extends LivingEntity { + } + } + +- protected void removeEntitiesOnShoulder() { ++ public void removeEntitiesOnShoulder() { // Paper - protected -> public + if (this.timeEntitySatOnShoulder + 20L < this.level.getGameTime()) { + // CraftBukkit start + if (this.spawnEntityFromShoulder(this.getShoulderEntityLeft())) { +diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +index af986adfdb547cb61fbd52f0f89858f1a9e52cc3..80a67deaeaae3b3f0ceb9a298de5bb38b8ee707b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +@@ -86,5 +86,15 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co + public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { + this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); + } ++ ++ @Override ++ public boolean hasPermission(String name) { ++ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); ++ } ++ ++ @Override ++ public boolean hasPermission(org.bukkit.permissions.Permission perm) { ++ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java +index d0757d116ee689041c0e64e622d2c36e0b0bcaf1..7b53b5a0857fc0ce0463db319f86a1f79833ab93 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java +@@ -39,4 +39,16 @@ public class CraftRemoteConsoleCommandSender extends ServerCommandSender impleme + public void setOp(boolean value) { + throw new UnsupportedOperationException("Cannot change operator status of remote controller."); + } ++ ++ // Paper start ++ @Override ++ public boolean hasPermission(String name) { ++ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); ++ } ++ ++ @Override ++ public boolean hasPermission(org.bukkit.permissions.Permission perm) { ++ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/patches/server-remapped/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch new file mode 100644 index 0000000000..1346418468 --- /dev/null +++ b/patches/server-remapped/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 23 May 2020 01:31:06 -0400 +Subject: [PATCH] Fix Non Full Status Chunk NBT Memory Leak + +Any full status chunk that was requested for any status less than full +would hold onto their entire nbt tree and every variable in that function. + +This was due to use of a lambda that persists on the Chunk object +until that chunk reaches FULL status. + +With introduction of no tick, we greatly increased the number of non +full chunks so this was really starting to hurt. + +We further improve it by making a copy of the nbt tag with only the memory +it needs, so that we dont have to hold a copy to the entire compound. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 1e58958c3d7b10da5a5f22fc9591d9183e53e3cc..0adf14af9841cd3a20a8b2c0c320eb06794ef261 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -26,6 +26,7 @@ import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.LongArrayTag; + import net.minecraft.nbt.ShortTag; ++import net.minecraft.nbt.Tag; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; +@@ -199,15 +200,9 @@ public class ChunkSerializer { + object2 = protochunkticklist1; + } + +- object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { +- postLoadChunk(nbttagcompound1, chunk); +- // CraftBukkit start - load chunk persistent data from nbt +- net.minecraft.nbt.Tag persistentBase = nbttagcompound1.get("ChunkBukkitValues"); +- if (persistentBase instanceof CompoundTag) { +- chunk.persistentDataContainer.putAll((CompoundTag) persistentBase); +- } +- // CraftBukkit end +- }); ++ object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. ++ createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities", "ChunkBukkitValues")) // Paper - move CB Chunk PDC into here ++ );// Paper end + } else { + ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter + +@@ -313,6 +308,50 @@ public class ChunkSerializer { + return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading + } + } ++ // Paper start ++ ++ /** ++ * This wrapper will error out if any key is accessed that wasn't copied so we can catch it easy on an update ++ */ ++ private static class SafeNBTCopy extends CompoundTag { ++ private final java.util.Set keys = new java.util.HashSet(); ++ public SafeNBTCopy(CompoundTag base, String... keys) { ++ for (String key : keys) { ++ this.keys.add(key); ++ final Tag nbtBase = base.get(key); ++ if (nbtBase != null) { ++ this.put(key, nbtBase); ++ } ++ } ++ } ++ ++ @Override ++ public boolean contains(String key) { ++ if (super.contains(key)) { ++ return true; ++ } else if (keys.contains(key)) { ++ return false; ++ } ++ throw new IllegalStateException("Missing Key " + key + " in SafeNBTCopy"); ++ } ++ ++ @Override ++ public boolean contains(String key, int type) { ++ return contains(key) && super.contains(key, type); ++ } ++ } ++ private static java.util.function.Consumer createLoadEntitiesConsumer(CompoundTag nbt) { ++ return (chunk) -> { ++ postLoadChunk(nbt, chunk); ++ // CraftBukkit start - load chunk persistent data from nbt ++ Tag persistentBase = nbt.get("ChunkBukkitValues"); ++ if (persistentBase instanceof CompoundTag) { ++ chunk.persistentDataContainer.putAll((CompoundTag) persistentBase); ++ } ++ // CraftBukkit end ++ }; ++ } ++ // Paper end + + // Paper start - async chunk save for unload + public static final class AsyncSaveData { diff --git a/patches/server-remapped/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch b/patches/server-remapped/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch new file mode 100644 index 0000000000..7918002d5e --- /dev/null +++ b/patches/server-remapped/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch @@ -0,0 +1,137 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Tue, 12 May 2020 23:02:43 +0200 +Subject: [PATCH] Workaround for Client Lag Spikes (MC-162253) + +When crossing certain chunk boundaries, the client needlessly +calculates light maps for chunk neighbours. In some specific map +configurations, these calculations cause a 500ms+ freeze on the Client. + +This patch basically serves as a workaround by sending light maps +to the client, so that it doesn't attempt to calculate them. +This mitigates the frametime impact to a minimum (but it's still there). + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 738f1183ce663db7c67d2f0289823390a7f06a0e..8070acde38c47c364c1d26ec3b7d65da037554a5 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -85,6 +85,7 @@ import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.ImposterProtoChunk; + import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.LevelChunkSection; + import net.minecraft.world.level.chunk.LightChunkGetter; + import net.minecraft.world.level.chunk.ProtoChunk; + import net.minecraft.world.level.chunk.UpgradeData; +@@ -2018,7 +2019,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + // Paper start + private static int getLightMask(final LevelChunk chunk) { +- final ChunkSection[] chunkSections = chunk.getSections(); ++ final LevelChunkSection[] chunkSections = chunk.getSections(); + int mask = 0; + + for (int i = 0; i < chunkSections.length; ++i) { +@@ -2029,7 +2030,7 @@ Lightmasks have 18 bits, from the -1 (void) section until the 17th (air) section + Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. + + */ +- mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; ++ mask |= (LevelChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; + } + + return mask; +@@ -2060,9 +2061,68 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + public final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER + private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { + if (packets[0] == null) { ++ // Paper start - add 8 for light fix workaround ++ if (packets.length != 10) { // in case Plugins call sendChunk, resize ++ packets = new Packet[10]; ++ } ++ // Paper end + packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass + packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, true); ++ ++ // Paper start - Fix MC-162253 ++ final int lightMask = getLightMask(chunk); ++ int i = 1; ++ for (int x = -1; x <= 1; x++) { ++ for (int z = -1; z <= 1; z++) { ++ if (x == 0 && z == 0) { ++ continue; ++ } ++ ++ ++i; ++ ++ if (!chunk.isNeighbourLoaded(x, z)) { ++ continue; ++ } ++ ++ final LevelChunk neighbor = chunk.getRelativeNeighbourIfLoaded(x, z); ++ final int updateLightMask = lightMask & ~getCeilingLightMask(neighbor); ++ ++ if (updateLightMask == 0) { ++ continue; ++ } ++ ++ packets[i] = new ClientboundLightUpdatePacket(new ChunkPos(chunk.getPos().x + x, chunk.getPos().z + z), lightEngine, updateLightMask, 0, true); ++ } ++ } ++ } ++ ++ final int viewDistance = playerViewDistanceBroadcastMap.getLastViewDistance(player); ++ final long lastPosition = playerViewDistanceBroadcastMap.getLastCoordinate(player); ++ ++ int j = 1; ++ for (int x = -1; x <= 1; x++) { ++ for (int z = -1; z <= 1; z++) { ++ if (x == 0 && z == 0) { ++ continue; ++ } ++ ++ ++j; ++ ++ Packet packet = packets[j]; ++ if (packet == null) { ++ continue; ++ } ++ ++ final int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - (chunk.getPos().x + x)); ++ final int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - (chunk.getPos().z + z)); ++ ++ if (Math.max(distX, distZ) > viewDistance) { ++ continue; ++ } ++ player.connection.send(packet); ++ } + } ++ // Paper end - Fix MC-162253 + + player.trackChunk(chunk.getPos(), packets[0], packets[1]); + DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos()); +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index dbea2a4370ccf24a5084cdabeecbc81f206e910a..9b76dc15417eef420804e5184a6d684e1137a746 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -279,7 +279,7 @@ public class LevelChunk implements ChunkAccess { + + // broadcast + Object[] backingSet = inRange.getBackingSet(); +- Packet[] chunkPackets = new Packet[2]; ++ Packet[] chunkPackets = new Packet[10]; + for (int index = 0, len = backingSet.length; index < len; ++index) { + Object temp = backingSet[index]; + if (!(temp instanceof ServerPlayer)) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index 5e7f6000df129100ef306703f325af9f60da8ae6..cc7d930c1fcd7157efc181d766e1639669f6eab9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -107,6 +107,7 @@ public class LevelChunkSection { + return this.nonEmptyBlockCount == 0; + } + ++ public static boolean isEmpty(@Nullable LevelChunkSection chunksection) { return isEmpty(chunksection) ; } // Paper - OBFHELPER + public static boolean isEmpty(@Nullable LevelChunkSection section) { + return section == LevelChunk.EMPTY_SECTION || section.isEmpty(); + } diff --git a/patches/server-remapped/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server-remapped/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch new file mode 100644 index 0000000000..c64155c42a --- /dev/null +++ b/patches/server-remapped/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch @@ -0,0 +1,1352 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 11 Apr 2020 03:56:07 -0400 +Subject: [PATCH] Implement Chunk Priority / Urgency System for Chunks + +Mark chunks that are blocking main thread for world generation as urgent + +Implements a general priority system so that chunks that are sorted in +the generator queues can prioritize certain chunks over another. + +Urgent chunks will jump to the front of the line, ensuring that a +sync chunk load on an ungenerated chunk does not lag the server for +a long period of time if the servers generator queues are filled with +lots of chunks already. + +This massively reduces the lag spikes from sync chunk gens. + +Then we further prioritize loading order so nearby chunks have higher +priority than distant chunks, reducing the pressure a high no tick +view distance holds on you. + +Chunks in front of the player have higher priority, to help with +fast traveling players keep up with their movement. + +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +index 499aff1f1e1ffc01ba8f9de43ca17899525a306f..97b85587525ddb62af9bfc8785b48727a6135599 100644 +--- a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +@@ -108,7 +108,7 @@ public final class ChunkTaskManager { + } + + static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z) { +- dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); ++ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 4); + } + + static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z, int indent, int maxDepth) { +@@ -129,6 +129,30 @@ public final class ChunkTaskManager { + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Priority - " + chunkHolder.getCurrentPriority()); ++ ++ if (!chunkHolder.neighbors.isEmpty()) { ++ if (indent >= maxDepth) { ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: (Can't show, too deeply nested)"); ++ return; ++ } ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: "); ++ for (ChunkHolder neighbor : chunkHolder.neighbors.keySet()) { ++ ChunkStatus status = neighbor.getChunkHolderStatus(); ++ if (status != null && status.isAtLeastStatus(ChunkHolder.getStatus(neighbor.getTicketLevel()))) { ++ continue; ++ } ++ int nx = neighbor.pos.x; ++ int nz = neighbor.pos.z; ++ if (seenChunks.contains(neighbor)) { ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + " (CIRCULAR)"); ++ continue; ++ } ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + ":"); ++ dumpChunkInfo(seenChunks, neighbor, nx, nz, indent + 1, maxDepth); ++ } ++ } ++ + } + } + +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index d18497a33dc53f6b465e659967bf8c98731c46c0..9a5737caf250dd2cc7f244248226f69117b27bad 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -631,10 +631,10 @@ public final class MCUtil { + + // sorting by coordinate makes the log easier to read + allChunks.sort((ChunkHolder v1, ChunkHolder v2) -> { +- if (v1.location.x != v2.location.x) { +- return Integer.compare(v1.location.x, v2.location.x); ++ if (v1.pos.x != v2.pos.x) { ++ return Integer.compare(v1.pos.x, v2.pos.x); + } +- return Integer.compare(v1.location.z, v2.location.z); ++ return Integer.compare(v1.pos.z, v2.pos.z); + }); + + worldData.addProperty("name", world.getWorld().getName()); +@@ -667,14 +667,15 @@ public final class MCUtil { + for (ChunkHolder playerChunk : allChunks) { + JsonObject chunkData = new JsonObject(); + +- Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.pair()); ++ Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.toLong()); + ChunkStatus status = getChunkStatus(playerChunk); + +- chunkData.addProperty("x", playerChunk.location.x); +- chunkData.addProperty("z", playerChunk.location.z); ++ chunkData.addProperty("x", playerChunk.pos.x); ++ chunkData.addProperty("z", playerChunk.pos.z); + chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); ++ chunkData.addProperty("priority", playerChunk.getCurrentPriority()); + chunkData.addProperty("state", ChunkHolder.getFullChunkStatus(playerChunk.getTicketLevel()).toString()); +- chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.pair())); ++ chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.toLong())); + chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); + + JsonArray ticketsData = new JsonArray(); +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index d907872d80f840b343419f49a6708082da6f921b..ce320672d7602c94dd75ad857435dca6ac3bab56 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -1,6 +1,7 @@ + package net.minecraft.server.level; + + import com.mojang.datafixers.util.Either; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper + import it.unimi.dsi.fastutil.shorts.ShortArraySet; + import it.unimi.dsi.fastutil.shorts.ShortSet; + import java.util.List; +@@ -19,6 +20,7 @@ import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; + import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; + import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; + import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; ++import net.minecraft.server.MCUtil; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LightLayer; +@@ -52,8 +54,8 @@ public class ChunkHolder { + private CompletableFuture chunkToSave; + public int oldTicketLevel; + private int ticketLevel; +- private int queueLevel; +- final ChunkPos pos; // Paper - private -> package ++ volatile int queueLevel; public final int getCurrentPriority() { return queueLevel; } // Paper - OBFHELPER - make volatile since this is concurrently accessed ++ public final ChunkPos pos; // Paper - private -> public + private boolean hasChangedSections; + private final ShortSet[] changedBlocksPerSection; + private int blockChangedLightSectionFilter; +@@ -65,6 +67,7 @@ public class ChunkHolder { + private boolean resendLight; + + private final ChunkMap chunkMap; // Paper ++ public ServerLevel getWorld() { return chunkMap.level; } // Paper + + long lastAutoSaveTime; // Paper - incremental autosave + long inactiveTimeStart; // Paper - incremental autosave +@@ -92,6 +95,120 @@ public class ChunkHolder { + return null; + } + // Paper end - no-tick view distance ++ // Paper start - Chunk gen/load priority system ++ volatile int neighborPriority = -1; ++ volatile int priorityBoost = 0; ++ public final java.util.concurrent.ConcurrentHashMap neighbors = new java.util.concurrent.ConcurrentHashMap<>(); ++ public final Long2ObjectOpenHashMap neighborPriorities = new Long2ObjectOpenHashMap<>(); ++ ++ private int getDemandedPriority() { ++ int priority = neighborPriority; // if we have a neighbor priority, use it ++ int myPriority = getMyPriority(); ++ ++ if (priority == -1 || (ticketLevel <= 33 && priority > myPriority)) { ++ priority = myPriority; ++ } ++ ++ return Math.max(1, Math.min(Math.max(ticketLevel, ChunkMap.MAX_CHUNK_DISTANCE), priority)); ++ } ++ ++ private int getMyPriority() { ++ if (priorityBoost == DistanceManager.URGENT_PRIORITY) { ++ return 2; // Urgent - ticket level isn't always 31 so 33-30 = 3, but allow 1 more tasks to go below this for dependents ++ } ++ return ticketLevel - priorityBoost; ++ } ++ ++ private int getNeighborsPriority() { ++ return (neighborPriorities.isEmpty() ? getMyPriority() : getDemandedPriority()) + 1; ++ } ++ ++ public void onNeighborRequest(ChunkHolder neighbor, ChunkStatus status) { ++ neighbor.setNeighborPriority(this, getNeighborsPriority()); ++ this.neighbors.compute(neighbor, (playerChunk, currentWantedStatus) -> { ++ if (currentWantedStatus == null || !currentWantedStatus.isAtLeastStatus(status)) { ++ //System.out.println(this + " request " + neighbor + " at " + status + " currently " + currentWantedStatus); ++ return status; ++ } else { ++ //System.out.println(this + " requested " + neighbor + " at " + status + " but thats lower than other wanted status " + currentWantedStatus); ++ return currentWantedStatus; ++ } ++ }); ++ ++ } ++ ++ public void onNeighborDone(ChunkHolder neighbor, ChunkStatus chunkstatus, ChunkAccess chunk) { ++ this.neighbors.compute(neighbor, (playerChunk, wantedStatus) -> { ++ if (wantedStatus != null && chunkstatus.isAtLeastStatus(wantedStatus)) { ++ //System.out.println(this + " neighbor done at " + neighbor + " for status " + chunkstatus + " wanted " + wantedStatus); ++ neighbor.removeNeighborPriority(this); ++ return null; ++ } else { ++ //System.out.println(this + " neighbor finished our previous request at " + neighbor + " for status " + chunkstatus + " but we now want instead " + wantedStatus); ++ return wantedStatus; ++ } ++ }); ++ } ++ ++ private void removeNeighborPriority(ChunkHolder requester) { ++ synchronized (neighborPriorities) { ++ neighborPriorities.remove(requester.pos.toLong()); ++ recalcNeighborPriority(); ++ } ++ checkPriority(); ++ } ++ ++ ++ private void setNeighborPriority(ChunkHolder requester, int priority) { ++ synchronized (neighborPriorities) { ++ neighborPriorities.put(requester.pos.toLong(), Integer.valueOf(priority)); ++ recalcNeighborPriority(); ++ } ++ checkPriority(); ++ } ++ ++ private void recalcNeighborPriority() { ++ neighborPriority = -1; ++ if (!neighborPriorities.isEmpty()) { ++ synchronized (neighborPriorities) { ++ for (Integer neighbor : neighborPriorities.values()) { ++ if (neighbor < neighborPriority || neighborPriority == -1) { ++ neighborPriority = neighbor; ++ } ++ } ++ } ++ } ++ } ++ private void checkPriority() { ++ if (getCurrentPriority() != getDemandedPriority()) this.chunkMap.queueHolderUpdate(this); ++ } ++ ++ public final double getDistance(ServerPlayer player) { ++ return getDistance(player.getX(), player.getZ()); ++ } ++ public final double getDistance(double blockX, double blockZ) { ++ int cx = MCUtil.fastFloor(blockX) >> 4; ++ int cz = MCUtil.fastFloor(blockZ) >> 4; ++ final double x = pos.x - cx; ++ final double z = pos.z - cz; ++ return (x * x) + (z * z); ++ } ++ ++ public final double getDistanceFrom(BlockPos pos) { ++ return getDistance(pos.getX(), pos.getZ()); ++ } ++ ++ @Override ++ public String toString() { ++ return "PlayerChunk{" + ++ "location=" + pos + ++ ", ticketLevel=" + ticketLevel + "/" + getStatus(this.ticketLevel) + ++ ", chunkHolderStatus=" + getChunkHolderStatus() + ++ ", neighborPriority=" + getNeighborsPriority() + ++ ", priority=(" + ticketLevel + " - " + priorityBoost +" vs N " + neighborPriority + ") = " + getDemandedPriority() + " A " + getCurrentPriority() + ++ '}'; ++ } ++ // Paper end + + public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); +@@ -194,6 +311,18 @@ public class ChunkHolder { + } + return null; + } ++ public static ChunkStatus getNextStatus(ChunkStatus status) { ++ if (status == ChunkStatus.FULL) { ++ return status; ++ } ++ return CHUNK_STATUSES.get(status.getStatusIndex() + 1); ++ } ++ public CompletableFuture> getStatusFutureUncheckedMain(ChunkStatus chunkstatus) { ++ return ensureMain(getFutureIfPresentUnchecked(chunkstatus)); ++ } ++ public CompletableFuture ensureMain(CompletableFuture future) { ++ return future.thenApplyAsync(r -> r, chunkMap.mainInvokingExecutor); ++ } + // Paper end + + public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { +@@ -440,6 +569,7 @@ public class ChunkHolder { + return this.queueLevel; + } + ++ private void setPriority(int i) { setQueueLevel(i); } // Paper - OBFHELPER + private void setQueueLevel(int level) { + this.queueLevel = level; + } +@@ -458,7 +588,7 @@ public class ChunkHolder { + // CraftBukkit start + // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. + if (playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { +- this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main + LevelChunk chunk = (LevelChunk)either.left().orElse(null); + if (chunk != null) { + chunkStorage.callbackExecutor.execute(() -> { +@@ -523,12 +653,13 @@ public class ChunkHolder { + if (!flag2 && flag3) { + // Paper start - cache ticking ready status + int expectCreateCount = ++this.fullChunkCreateCount; +- this.fullChunkFuture = chunkStorage.unpackTicks(this); this.fullChunkFuture.thenAccept((either) -> { ++ this.fullChunkFuture = chunkStorage.unpackTicks(this); ensureMain(this.fullChunkFuture).thenAccept((either) -> { // Paper - ensure main + if (either.left().isPresent() && ChunkHolder.this.fullChunkCreateCount == expectCreateCount) { + // note: Here is a very good place to add callbacks to logic waiting on this. + LevelChunk fullChunk = either.left().get(); + ChunkHolder.this.isFullChunkReady = true; + fullChunk.playerChunk = ChunkHolder.this; ++ this.chunkMap.distanceManager.clearPriorityTickets(pos); + + + } +@@ -553,7 +684,7 @@ public class ChunkHolder { + + if (!flag4 && flag5) { + // Paper start - cache ticking ready status +- this.tickingChunkFuture = chunkStorage.postProcess(this); this.tickingChunkFuture.thenAccept((either) -> { ++ this.tickingChunkFuture = chunkStorage.postProcess(this); ensureMain(this.tickingChunkFuture).thenAccept((either) -> { // Paper - ensure main + if (either.left().isPresent()) { + // note: Here is a very good place to add callbacks to logic waiting on this. + LevelChunk tickingChunk = either.left().get(); +@@ -584,7 +715,7 @@ public class ChunkHolder { + } + + // Paper start - cache ticking ready status +- this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); this.entityTickingChunkFuture.thenAccept((either) -> { ++ this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); ensureMain(this.entityTickingChunkFuture).thenAccept((either) -> { // Paper ensureMain + if (either.left().isPresent()) { + // note: Here is a very good place to add callbacks to logic waiting on this. + LevelChunk entityTickingChunk = either.left().get(); +@@ -604,12 +735,29 @@ public class ChunkHolder { + this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + } + +- this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); ++ // Paper start - raise IO/load priority if priority changes, use our preferred priority ++ priorityBoost = chunkMap.distanceManager.getChunkPriority(pos); ++ int priority = getDemandedPriority(); ++ if (getCurrentPriority() > priority) { ++ int ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; ++ if (priority <= 10) { ++ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; ++ } else if (priority <= 20) { ++ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; ++ } ++ chunkMap.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, ioPriority); ++ } ++ if (getCurrentPriority() != priority) { ++ this.onLevelChange.onLevelChange(this.pos, this::getCurrentPriority, priority, this::setPriority); // use preferred priority ++ int neighborsPriority = getNeighborsPriority(); ++ this.neighbors.forEach((neighbor, neighborDesired) -> neighbor.setNeighborPriority(this, neighborsPriority)); ++ } ++ // Paper end + this.oldTicketLevel = this.ticketLevel; + // CraftBukkit start + // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. + if (!playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { +- this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main + LevelChunk chunk = (LevelChunk)either.left().orElse(null); + if (chunk != null) { + chunkStorage.callbackExecutor.execute(() -> { +@@ -691,6 +839,7 @@ public class ChunkHolder { + + public interface LevelChangeListener { + ++ default void changePriority(ChunkPos chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer) { onLevelChange(chunkcoordintpair, intsupplier, i, intconsumer); } // Paper - OBFHELPER + void onLevelChange(ChunkPos pos, IntSupplier levelGetter, int targetLevel, IntConsumer levelSetter); + } + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c06720820 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -14,6 +14,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; + import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + import it.unimi.dsi.fastutil.longs.Long2ByteMap; + import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; // Paper + import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; + import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; + import it.unimi.dsi.fastutil.longs.LongIterator; +@@ -51,6 +52,7 @@ import net.minecraft.CrashReport; + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; + import net.minecraft.Util; ++import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.protocol.Packet; +@@ -102,6 +104,7 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + import org.bukkit.entity.Player; // CraftBukkit ++import org.spigotmc.AsyncCatcher; + + public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider { + +@@ -139,6 +142,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final ServerLevel level; + private final ThreadedLevelLightEngine lightEngine; + private final BlockableEventLoop mainThreadExecutor; ++ final java.util.concurrent.Executor mainInvokingExecutor; // Paper + public final ChunkGenerator generator; + private final Supplier overworldDataStorage; public final Supplier getWorldPersistentDataSupplier() { return this.overworldDataStorage; } // Paper - OBFHELPER + private final PoiManager poiManager; +@@ -176,6 +180,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + @Override + public void execute(Runnable runnable) { ++ AsyncCatcher.catchOp("Callback Executor execute"); + if (queued == null) { + queued = new java.util.ArrayDeque<>(); + } +@@ -184,6 +189,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + @Override + public void run() { ++ AsyncCatcher.catchOp("Callback Executor run"); + if (queued == null) { + return; + } +@@ -338,6 +344,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.level = worldserver; + this.generator = chunkGenerator; + this.mainThreadExecutor = mainThreadExecutor; ++ // Paper start ++ this.mainInvokingExecutor = (run) -> { ++ if (MCUtil.isMainThread()) { ++ run.run(); ++ } else { ++ mainThreadExecutor.execute(run); ++ } ++ }; ++ // Paper end + ProcessorMailbox threadedmailbox = ProcessorMailbox.create(workerExecutor, "worldgen"); + + mainThreadExecutor.getClass(); +@@ -432,6 +447,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, + (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ checkHighPriorityChunks(player); + if (newState.size() != 1) { + return; + } +@@ -450,7 +466,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); + ChunkMap.this.level.getChunkSource().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update +- }); ++ ChunkMap.this.level.getChunkSource().clearPriorityTickets(chunkPos); ++ }, (player, prevPos, newPos) -> { ++ player.lastHighPriorityChecked = -1; // reset and recheck ++ checkHighPriorityChunks(player); ++ }); + this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); + this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, + (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, +@@ -467,6 +487,115 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }); + // Paper end - no-tick view distance + } ++ // Paper start - Chunk Prioritization ++ public void queueHolderUpdate(ChunkHolder playerchunk) { ++ Runnable runnable = () -> { ++ if (isUnloading(playerchunk)) { ++ return; // unloaded ++ } ++ distanceManager.pendingChunkUpdates.add(playerchunk); ++ if (!distanceManager.pollingPendingChunkUpdates) { ++ level.getChunkSource().runDistanceManagerUpdates(); ++ } ++ }; ++ if (MCUtil.isMainThread()) { ++ // We can't use executor here because it will not execute tasks if its currently in the middle of executing tasks... ++ runnable.run(); ++ } else { ++ mainThreadExecutor.execute(runnable); ++ } ++ } ++ ++ private boolean isUnloading(ChunkHolder playerchunk) { ++ return playerchunk == null || toDrop.contains(playerchunk.pos.toLong()); ++ } ++ ++ private void updateChunkPriorityMap(Long2IntOpenHashMap map, long chunk, int level) { ++ int prev = map.getOrDefault(chunk, -1); ++ if (level > prev) { ++ map.put(chunk, level); ++ } ++ } ++ ++ public void checkHighPriorityChunks(ServerPlayer player) { ++ int currentTick = MinecraftServer.currentTick; ++ if (currentTick - player.lastHighPriorityChecked < 20 || !player.isRealPlayer) { // weed out fake players ++ return; ++ } ++ player.lastHighPriorityChecked = currentTick; ++ Long2IntOpenHashMap priorities = new Long2IntOpenHashMap(); ++ ++ int viewDistance = getEffectiveNoTickViewDistance(); ++ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); ++ ++ // Prioritize circular near ++ double playerChunkX = Mth.floor(player.getX()) >> 4; ++ double playerChunkZ = Mth.floor(player.getZ()) >> 4; ++ pos.setValues(player.getX(), 0, player.getZ()); ++ double twoThirdModifier = 2D / 3D; ++ MCUtil.getSpiralOutChunks(pos, Math.min(6, viewDistance)).forEach(coord -> { ++ if (shouldSkipPrioritization(coord)) return; ++ ++ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); ++ // Prioritize immediate ++ if (dist <= 4) { ++ updateChunkPriorityMap(priorities, coord.toLong(), (int) (27 - dist)); ++ return; ++ } ++ ++ // Prioritize nearby chunks ++ updateChunkPriorityMap(priorities, coord.toLong(), (int) (20 - dist * twoThirdModifier)); ++ }); ++ ++ // Prioritize Frustum near 3 ++ ChunkPos front3 = player.getChunkInFront(3); ++ pos.setValues(front3.x << 4, 0, front3.z << 4); ++ MCUtil.getSpiralOutChunks(pos, Math.min(5, viewDistance)).forEach(coord -> { ++ if (shouldSkipPrioritization(coord)) return; ++ ++ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); ++ updateChunkPriorityMap(priorities, coord.toLong(), (int) (25 - dist * twoThirdModifier)); ++ }); ++ ++ // Prioritize Frustum near 5 ++ if (viewDistance > 4) { ++ ChunkPos front5 = player.getChunkInFront(5); ++ pos.setValues(front5.x << 4, 0, front5.z << 4); ++ MCUtil.getSpiralOutChunks(pos, 4).forEach(coord -> { ++ if (shouldSkipPrioritization(coord)) return; ++ ++ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); ++ updateChunkPriorityMap(priorities, coord.toLong(), (int) (25 - dist * twoThirdModifier)); ++ }); ++ } ++ ++ // Prioritize Frustum far 7 ++ if (viewDistance > 6) { ++ ChunkPos front7 = player.getChunkInFront(7); ++ pos.setValues(front7.x << 4, 0, front7.z << 4); ++ MCUtil.getSpiralOutChunks(pos, 3).forEach(coord -> { ++ if (shouldSkipPrioritization(coord)) { ++ return; ++ } ++ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); ++ updateChunkPriorityMap(priorities, coord.toLong(), (int) (25 - dist * twoThirdModifier)); ++ }); ++ } ++ ++ if (priorities.isEmpty()) return; ++ distanceManager.delayDistanceManagerTick = true; ++ priorities.long2IntEntrySet().fastForEach(entry -> distanceManager.markHighPriority(new ChunkPos(entry.getLongKey()), entry.getIntValue())); ++ distanceManager.delayDistanceManagerTick = false; ++ level.getChunkSource().runDistanceManagerUpdates(); ++ ++ } ++ ++ private boolean shouldSkipPrioritization(ChunkPos coord) { ++ if (playerViewDistanceNoTickMap.getObjectsInRange(coord.toLong()) == null) return true; ++ ChunkHolder chunk = getUpdatingChunkIfPresent(coord.toLong()); ++ return chunk != null && (chunk.isFullChunkReady()); ++ } ++ // Paper end + + public void updatePlayerMobTypeMap(Entity entity) { + if (!this.level.paperConfig.perPlayerMobSpawns) { +@@ -596,6 +725,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + List>> list = Lists.newArrayList(); + int j = centerChunk.x; + int k = centerChunk.z; ++ ChunkHolder requestingNeighbor = getUpdatingChunkIfPresent(centerChunk.toLong()); // Paper + + for (int l = -margin; l <= margin; ++l) { + for (int i1 = -margin; i1 <= margin; ++i1) { +@@ -614,6 +744,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + ChunkStatus chunkstatus = (ChunkStatus) distanceToStatus.apply(j1); + CompletableFuture> completablefuture = playerchunk.getOrScheduleFuture(chunkstatus, this); ++ // Paper start ++ if (requestingNeighbor != null && requestingNeighbor != playerchunk && !completablefuture.isDone()) { ++ requestingNeighbor.onNeighborRequest(playerchunk, chunkstatus); ++ completablefuture.thenAccept(either -> { ++ requestingNeighbor.onNeighborDone(playerchunk, chunkstatus, either.left().orElse(null)); ++ }); ++ } ++ // Paper end + + list.add(completablefuture); + } +@@ -1081,14 +1219,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }; + + CompletableFuture chunkSaveFuture = this.level.asyncChunkTaskManager.getChunkSaveFuture(pos.x, pos.z); ++ ChunkHolder playerChunk = getUpdatingChunkIfPresent(pos.toLong()); ++ int chunkPriority = playerChunk != null ? playerChunk.getCurrentPriority() : 33; ++ int priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; ++ ++ if (chunkPriority <= 10) { ++ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; ++ } else if (chunkPriority <= 20) { ++ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; ++ } ++ boolean isHighestPriority = priority == com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; + if (chunkSaveFuture != null) { +- this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, +- com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); +- this.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); ++ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, priority, chunkHolderConsumer, isHighestPriority, chunkSaveFuture); + } else { +- this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, +- com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); ++ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, priority, chunkHolderConsumer, isHighestPriority); + } ++ this.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, priority); + return ret; + // Paper end + } +@@ -1233,7 +1379,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + long i = playerchunk.getPos().toLong(); + + playerchunk.getClass(); +- mailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, playerchunk::getTicketLevel)); ++ mailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, () -> 1)); // Paper - final loads are always urgent! + }); + } + +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a906f07e97 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -21,7 +21,10 @@ import java.util.Set; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.Executor; + import javax.annotation.Nullable; ++import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.util.SortedArraySet; + import net.minecraft.util.thread.ProcessorHandle; + import net.minecraft.world.level.ChunkPos; +@@ -29,6 +32,7 @@ import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.LevelChunk; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import org.spigotmc.AsyncCatcher; // Paper + + public abstract class DistanceManager { + +@@ -52,7 +56,7 @@ public abstract class DistanceManager { + private final ChunkTaskPriorityQueueSorter ticketThrottler; + private final ProcessorHandle> ticketThrottlerInput; + private final ProcessorHandle ticketThrottlerReleaser; +- private final LongSet ticketsToRelease = new LongOpenHashSet(); ++ private final LongSet ticketsToRelease = new LongOpenHashSet(); public final LongSet getOnPlayerTicketAddQueue() { return ticketsToRelease; } // Paper - OBFHELPER + private final Executor mainThreadExecutor; + private long ticketTickCounter; + +@@ -90,6 +94,7 @@ public abstract class DistanceManager { + } + + private static int getTicketLevelAt(SortedArraySet> arraysetsorted) { ++ AsyncCatcher.catchOp("ChunkMapDistance::getLowestTicketLevel"); // Paper + return !arraysetsorted.isEmpty() ? ((Ticket) arraysetsorted.first()).getTicketLevel() : ChunkMap.MAX_CHUNK_DISTANCE + 1; + } + +@@ -103,6 +108,7 @@ public abstract class DistanceManager { + + public boolean runAllUpdates(ChunkMap chunkStorage) { + //this.f.a(); // Paper - no longer used ++ AsyncCatcher.catchOp("DistanceManagerTick"); // Paper + this.playerTicketManager.runAllUpdates(); + int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE); + boolean flag = i != 0; +@@ -113,11 +119,13 @@ public abstract class DistanceManager { + + // Paper start + if (!this.pendingChunkUpdates.isEmpty()) { ++ this.pollingPendingChunkUpdates = true; try { + while(!this.pendingChunkUpdates.isEmpty()) { + ChunkHolder remove = this.pendingChunkUpdates.remove(); + remove.isUpdateQueued = false; + remove.updateFutures(chunkStorage); + } ++ } finally { this.pollingPendingChunkUpdates = false; } + // Paper end + return true; + } else { +@@ -153,8 +161,10 @@ public abstract class DistanceManager { + return flag; + } + } ++ boolean pollingPendingChunkUpdates = false; // Paper + + private boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ AsyncCatcher.catchOp("ChunkMapDistance::addTicket"); // Paper + SortedArraySet> arraysetsorted = this.getTickets(i); + int j = getTicketLevelAt(arraysetsorted); + Ticket ticket1 = (Ticket) arraysetsorted.addOrGet(ticket); // CraftBukkit - decompile error +@@ -168,7 +178,9 @@ public abstract class DistanceManager { + } + + private boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ AsyncCatcher.catchOp("ChunkMapDistance::removeTicket"); // Paper + SortedArraySet> arraysetsorted = this.getTickets(i); ++ int oldLevel = getTicketLevelAt(arraysetsorted); // Paper + + boolean removed = false; // CraftBukkit + if (arraysetsorted.remove(ticket)) { +@@ -179,7 +191,8 @@ public abstract class DistanceManager { + this.tickets.remove(i); + } + +- this.ticketTracker.update(i, getTicketLevelAt(arraysetsorted), false); ++ int newLevel = getTicketLevelAt(arraysetsorted); // Paper ++ if (newLevel > oldLevel) this.ticketTracker.update(i, newLevel, false); // Paper + return removed; // CraftBukkit + } + +@@ -188,6 +201,135 @@ public abstract class DistanceManager { + this.addTicketAtLevel(type, pos, level, argument); + } + ++ // Paper start ++ public static final int PRIORITY_TICKET_LEVEL = ChunkMap.MAX_CHUNK_DISTANCE; ++ public static final int URGENT_PRIORITY = 29; ++ public boolean delayDistanceManagerTick = false; ++ public boolean markUrgent(ChunkPos coords) { ++ return addPriorityTicket(coords, TicketType.URGENT, URGENT_PRIORITY); ++ } ++ public boolean markHighPriority(ChunkPos coords, int priority) { ++ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); ++ return addPriorityTicket(coords, TicketType.PRIORITY, priority); ++ } ++ ++ public void markAreaHighPriority(ChunkPos center, int priority, int radius) { ++ delayDistanceManagerTick = true; ++ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); ++ int finalPriority = priority; ++ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { ++ addPriorityTicket(coords, TicketType.PRIORITY, finalPriority); ++ }); ++ delayDistanceManagerTick = false; ++ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); ++ } ++ ++ public void clearAreaPriorityTickets(ChunkPos center, int radius) { ++ delayDistanceManagerTick = true; ++ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { ++ this.removeTicket(coords.toLong(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); ++ }); ++ delayDistanceManagerTick = false; ++ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); ++ } ++ ++ private boolean hasPlayerTicket(ChunkPos coords, int level) { ++ SortedArraySet> tickets = this.tickets.get(coords.toLong()); ++ if (tickets == null || tickets.isEmpty()) { ++ return false; ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getType() == TicketType.PLAYER && ticket.getTicketLevel() == level) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ private boolean addPriorityTicket(ChunkPos coords, TicketType ticketType, int priority) { ++ AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket"); ++ long pair = coords.toLong(); ++ ChunkHolder chunk = chunkMap.getUpdatingChunkIfPresent(pair); ++ boolean needsTicket = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(pair) != null && !hasPlayerTicket(coords, 33); ++ ++ if (needsTicket) { ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); ++ getOnPlayerTicketAddQueue().add(pair); ++ addTicket(pair, ticket); ++ } ++ if ((chunk != null && chunk.isFullChunkReady())) { ++ if (needsTicket) { ++ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); ++ } ++ return needsTicket; ++ } ++ ++ boolean success; ++ if (!(success = updatePriorityTicket(coords, ticketType, priority))) { ++ Ticket ticket = new Ticket(ticketType, PRIORITY_TICKET_LEVEL, coords); ++ ticket.priority = priority; ++ success = this.addTicket(pair, ticket); ++ } else { ++ if (chunk == null) { ++ chunk = chunkMap.getUpdatingChunkIfPresent(pair); ++ } ++ chunkMap.queueHolderUpdate(chunk); ++ } ++ ++ //chunkMap.world.getWorld().spawnParticle(priority <= 15 ? org.bukkit.Particle.EXPLOSION_HUGE : org.bukkit.Particle.EXPLOSION_NORMAL, chunkMap.world.getWorld().getPlayers(), null, coords.x << 4, 70, coords.z << 4, 2, 0, 0, 0, 1, null, true); ++ ++ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); ++ ++ return success; ++ } ++ ++ private boolean updatePriorityTicket(ChunkPos coords, TicketType type, int priority) { ++ SortedArraySet> tickets = this.tickets.get(coords.toLong()); ++ if (tickets == null) { ++ return false; ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getType() == type) { ++ // We only support increasing, not decreasing, too complicated ++ ticket.setCurrentTick(this.ticketTickCounter); ++ ticket.priority = Math.max(ticket.priority, priority); ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ public int getChunkPriority(ChunkPos coords) { ++ AsyncCatcher.catchOp("ChunkMapDistance::getChunkPriority"); ++ SortedArraySet> tickets = this.tickets.get(coords.toLong()); ++ if (tickets == null) { ++ return 0; ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getType() == TicketType.URGENT) { ++ return URGENT_PRIORITY; ++ } ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getType() == TicketType.PRIORITY && ticket.priority > 0) { ++ return ticket.priority; ++ } ++ } ++ return 0; ++ } ++ ++ public void clearPriorityTickets(ChunkPos coords) { ++ AsyncCatcher.catchOp("ChunkMapDistance::clearPriority"); ++ this.removeTicket(coords.toLong(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); ++ } ++ ++ public void clearUrgent(ChunkPos coords) { ++ AsyncCatcher.catchOp("ChunkMapDistance::clearUrgent"); ++ this.removeTicket(coords.toLong(), new Ticket(TicketType.URGENT, PRIORITY_TICKET_LEVEL, coords)); ++ } ++ // Paper end + public boolean addTicketAtLevel(TicketType ticketType, ChunkPos chunkcoordintpair, int level, T identifier) { + return this.addTicket(chunkcoordintpair.toLong(), new Ticket<>(ticketType, level, identifier)); + // CraftBukkit end +@@ -358,7 +500,7 @@ public abstract class DistanceManager { + + class PlayerTicketTracker extends DistanceManager.FixedPlayerDistanceChunkTracker { + +- private int viewDistance = 0; ++ private int viewDistance = 0; private int getViewDistance() { return viewDistance; } private void setViewDistance(int value) { this.viewDistance = value; } // Paper - OBFHELPER + private final Long2IntMap queueLevels = Long2IntMaps.synchronize(new Long2IntOpenHashMap()); + private final LongSet toUpdate = new LongOpenHashSet(); + +@@ -374,41 +516,68 @@ public abstract class DistanceManager { + + public void updateViewDistance(int watchDistance) { + ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); ++ // Paper start - set the view distance before scheduling chunk loads/unloads ++ int lastViewDistance = getViewDistance(); ++ setViewDistance(watchDistance); ++ // Paper end + + while (objectiterator.hasNext()) { + Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix + byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); + long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); + +- this.onLevelChange(j, b0, this.haveTicketFor(b0), b0 <= watchDistance - 2); ++ this.onLevelChange(j, b0, b0 <= lastViewDistance - 2, this.haveTicketFor(b0)); // Paper + } + +- this.viewDistance = watchDistance; ++ //this.e = i; // Paper - view distance is now set further up + } + + private void onLevelChange(long pos, int distance, boolean oldWithinViewDistance, boolean withinViewDistance) { + if (oldWithinViewDistance != withinViewDistance) { +- Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkPos(pos)); // Paper - no-tick view distance ++ ChunkPos coords = new ChunkPos(pos); // Paper ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); // Paper - no-tick view distance + + if (withinViewDistance) { +- DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { ++ scheduleChunkLoad(pos, MinecraftServer.currentTick, distance, (priority) -> { // Paper - smarter ticket delay based on frustum and distance ++ // Paper start - recheck its still valid if not cancel ++ if (!isChunkInRange(pos)) { ++ DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { ++ DistanceManager.this.mainThreadExecutor.execute(() -> { ++ DistanceManager.this.removeTicket(pos, ticket); ++ DistanceManager.this.clearPriorityTickets(coords); ++ }); ++ }, pos, false)); ++ return; ++ } ++ // abort early if we got a ticket already ++ if (hasPlayerTicket(coords, 33)) return; ++ // skip player ticket throttle for near chunks ++ if (priority <= 3) { ++ DistanceManager.this.addTicket(pos, ticket); ++ DistanceManager.this.ticketsToRelease.add(pos); ++ return; ++ } ++ // Paper end ++ DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { // CraftBukkit - decompile error + DistanceManager.this.mainThreadExecutor.execute(() -> { +- if (this.haveTicketFor(this.getLevel(pos))) { ++ if (isChunkInRange(pos)) { if (!hasPlayerTicket(coords, 33)) { // Paper - high priority might of already added it + DistanceManager.this.addTicket(pos, ticket); + DistanceManager.this.ticketsToRelease.add(pos); +- } else { +- DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { ++ }} else { // Paper ++ DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { // CraftBukkit - decompile error + }, pos, false)); + } + + }); + }, pos, () -> { +- return distance; ++ return Math.min(ChunkMap.MAX_CHUNK_DISTANCE, priority); // Paper + })); ++ }); // Paper + } else { + DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { + DistanceManager.this.mainThreadExecutor.execute(() -> { + DistanceManager.this.removeTicket(pos, ticket); ++ DistanceManager.this.clearPriorityTickets(coords); // Paper + }); + }, pos, true)); + } +@@ -416,6 +585,101 @@ public abstract class DistanceManager { + + } + ++ // Paper start - smart scheduling of player tickets ++ private boolean isChunkInRange(long i) { ++ return this.isLoadedChunkLevel(this.getChunkLevel(i)); ++ } ++ public void scheduleChunkLoad(long i, long startTick, int initialDistance, java.util.function.Consumer task) { ++ long elapsed = MinecraftServer.currentTick - startTick; ++ ChunkPos chunkPos = new ChunkPos(i); ++ ChunkHolder updatingChunk = chunkMap.getUpdatingChunkIfPresent(i); ++ if ((updatingChunk != null && updatingChunk.isFullChunkReady()) || !isChunkInRange(i) || getChunkPriority(chunkPos) > 0) { // Copied from above ++ // no longer needed ++ task.accept(1); ++ return; ++ } ++ ++ int desireDelay = 0; ++ double minDist = Double.MAX_VALUE; ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(i); ++ if (elapsed == 0 && initialDistance <= 4) { ++ // Aim for no delay on initial 6 chunk radius tickets save on performance of the below code to only > 6 ++ minDist = initialDistance; ++ } else if (players != null) { ++ Object[] backingSet = players.getBackingSet(); ++ ++ BlockPos blockPos = chunkPos.asPosition(); ++ ++ boolean isFront = false; ++ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); ++ for (int index = 0, len = backingSet.length; index < len; ++index) { ++ if (!(backingSet[index] instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer) backingSet[index]; ++ ++ ChunkPos pointInFront = player.getChunkInFront(5); ++ pos.setValues(pointInFront.x << 4, 0, pointInFront.z << 4); ++ double frontDist = MCUtil.distanceSq(pos, blockPos); ++ ++ pos.setValues(player.getX(), 0, player.getZ()); ++ double center = MCUtil.distanceSq(pos, blockPos); ++ ++ double dist = Math.min(frontDist, center); ++ if (!isFront) { ++ ChunkPos pointInBack = player.getChunkInFront(-7); ++ pos.setValues(pointInBack.x << 4, 0, pointInBack.z << 4); ++ double backDist = MCUtil.distanceSq(pos, blockPos); ++ if (frontDist < backDist) { ++ isFront = true; ++ } ++ } ++ if (dist < minDist) { ++ minDist = dist; ++ } ++ } ++ if (minDist == Double.MAX_VALUE) { ++ minDist = 15; ++ } else { ++ minDist = Math.sqrt(minDist) / 16; ++ } ++ if (minDist > 4) { ++ int desiredTimeDelayMax = isFront ? ++ (minDist < 10 ? 7 : 15) : // Front ++ (minDist < 10 ? 15 : 45); // Back ++ desireDelay += (desiredTimeDelayMax * 20) * (minDist / 32); ++ } ++ } else { ++ minDist = initialDistance; ++ desireDelay = 1; ++ } ++ long delay = desireDelay - elapsed; ++ if (delay <= 0 && minDist > 4 && minDist < Double.MAX_VALUE) { ++ boolean hasAnyNeighbor = false; ++ for (int x = -1; x <= 1; x++) { ++ for (int z = -1; z <= 1; z++) { ++ if (x == 0 && z == 0) continue; ++ long pair = ChunkPos.asLong(chunkPos.x + x, chunkPos.z + z); ++ ChunkHolder neighbor = chunkMap.getUpdatingChunkIfPresent(pair); ++ ChunkStatus current = neighbor != null ? neighbor.getChunkHolderStatus() : null; ++ if (current != null && current.isAtLeastStatus(ChunkStatus.LIGHT)) { ++ hasAnyNeighbor = true; ++ } ++ } ++ } ++ if (!hasAnyNeighbor) { ++ delay += 20; ++ } ++ } ++ if (delay <= 0) { ++ task.accept((int) minDist); ++ } else { ++ int taskDelay = (int) Math.min(delay, minDist >= 10 ? 40 : (minDist < 6 ? 5 : 20)); ++ MCUtil.scheduleTask(taskDelay, () -> scheduleChunkLoad(i, startTick, initialDistance, task), "Player Ticket Delayer"); ++ } ++ } ++ // Paper end ++ + @Override + public void runAllUpdates() { + super.runAllUpdates(); +@@ -447,6 +711,7 @@ public abstract class DistanceManager { + + } + ++ private boolean isLoadedChunkLevel(int i) { return haveTicketFor(i); } // Paper - OBFHELPER + private boolean haveTicketFor(int distance) { + return distance <= this.viewDistance - 2; + } +@@ -463,6 +728,7 @@ public abstract class DistanceManager { + this.chunks.defaultReturnValue((byte) (i + 2)); + } + ++ protected final int getChunkLevel(long i) { return getLevel(i); } // Paper - OBFHELPER + @Override + protected int getLevel(long id) { + return this.chunks.get(id); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd..f36badcafbad7fb4537ffdf54d9e266ae3d72459 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -467,6 +467,26 @@ public class ServerChunkCache extends ChunkSource { + public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { + this.distanceManager.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); + } ++ ++ public boolean markUrgent(ChunkPos coords) { ++ return this.distanceManager.markUrgent(coords); ++ } ++ ++ public boolean markHighPriority(ChunkPos coords, int priority) { ++ return this.distanceManager.markHighPriority(coords, priority); ++ } ++ ++ public void markAreaHighPriority(ChunkPos center, int priority, int radius) { ++ this.distanceManager.markAreaHighPriority(center, priority, radius); ++ } ++ ++ public void clearAreaPriorityTickets(ChunkPos center, int radius) { ++ this.distanceManager.clearAreaPriorityTickets(center, radius); ++ } ++ ++ public void clearPriorityTickets(ChunkPos coords) { ++ this.distanceManager.clearPriorityTickets(coords); ++ } + // Paper end + + @Nullable +@@ -505,6 +525,8 @@ public class ServerChunkCache extends ChunkSource { + + if (!completablefuture.isDone()) { // Paper + // Paper start - async chunk io/loading ++ ChunkPos pair = new ChunkPos(x1, z1); ++ this.distanceManager.markUrgent(pair); + this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); + // Paper end +@@ -513,6 +535,8 @@ public class ServerChunkCache extends ChunkSource { + this.mainThreadProcessor.managedBlock(completablefuture::isDone); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug + this.level.timings.syncChunkLoad.stopTiming(); // Paper ++ this.distanceManager.clearPriorityTickets(pair); // Paper ++ this.distanceManager.clearUrgent(pair); // Paper + } // Paper + ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { + return ichunkaccess1; +@@ -565,10 +589,12 @@ public class ServerChunkCache extends ChunkSource { + if (flag && !currentlyUnloading) { + // CraftBukkit end + this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); ++ if (isUrgent) this.distanceManager.markUrgent(chunkcoordintpair); // Paper + if (this.chunkAbsent(playerchunk, l)) { + ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + + gameprofilerfiller.push("chunkLoad"); ++ distanceManager.delayDistanceManagerTick = false; // Paper - ensure this is never false + this.runDistanceManagerUpdates(); + playerchunk = this.getVisibleChunkIfPresent(k); + gameprofilerfiller.pop(); +@@ -577,8 +603,13 @@ public class ServerChunkCache extends ChunkSource { + } + } + } +- +- return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkstatus, this.chunkMap); ++ // Paper start ++ CompletableFuture> future = this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkstatus, this.chunkMap); ++ if (isUrgent) { ++ future.thenAccept(either -> this.distanceManager.clearUrgent(chunkcoordintpair)); ++ } ++ return future; ++ // Paper end + } + + private boolean chunkAbsent(@Nullable ChunkHolder holder, int maxLevel) { +@@ -630,6 +661,7 @@ public class ServerChunkCache extends ChunkSource { + } + + public boolean runDistanceManagerUpdates() { // Paper - private -> public ++ if (distanceManager.delayDistanceManagerTick) return false; // Paper + boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); + boolean flag1 = this.chunkMap.promoteChunkMap(); + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 8e4cef60b760be385df81a74834d026f856a78c5..c5717f45a0110492aad41f21cc06fb8cbeb1f791 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -73,6 +73,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; + import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.PlayerAdvancements; + import net.minecraft.server.network.ServerGamePacketListenerImpl; +@@ -185,6 +186,12 @@ public class ServerPlayer extends Player implements ContainerListener { + private int lastRecordedArmor = Integer.MIN_VALUE; + private int lastRecordedLevel = Integer.MIN_VALUE; + private int lastRecordedExperience = Integer.MIN_VALUE; ++ public long lastHighPriorityChecked; // Paper ++ public void forceCheckHighPriority() { ++ lastHighPriorityChecked = -1; ++ getLevel().getChunkSource().chunkMap.checkHighPriorityChunks(this); ++ } ++ public boolean isRealPlayer; // Paper + private float lastSentHealth = -1.0E8F; + private int lastSentFood = -99999999; + private boolean lastFoodSaturationZero = true; +@@ -272,6 +279,21 @@ public class ServerPlayer extends Player implements ContainerListener { + this.maxHealthCache = this.getMaxHealth(); + this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper + } ++ // Paper start ++ public BlockPos getPointInFront(double inFront) { ++ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yRot+90)); // MC rotates yaw 90 for some odd reason ++ final double x = getX() + inFront * Math.cos(rads); ++ final double z = getZ() + inFront * Math.sin(rads); ++ return new BlockPos(x, getY(), z); ++ } ++ ++ public ChunkPos getChunkInFront(double inFront) { ++ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yRot+90)); // MC rotates yaw 90 for some odd reason ++ final double x = getX() + (inFront * 16) * Math.cos(rads); ++ final double z = getZ() + (inFront * 16) * Math.sin(rads); ++ return new ChunkPos(Mth.floor(x) >> 4, Mth.floor(z) >> 4); ++ } ++ // Paper end + + // Yes, this doesn't match Vanilla, but it's the best we can do for now. + // If this is an issue, PRs are welcome +@@ -619,6 +641,7 @@ public class ServerPlayer extends Player implements ContainerListener { + if (valid && !this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) + super.tick(); + } ++ if (valid && isAlive() && connection != null) ((ServerLevel)level).getChunkSource().chunkMap.checkHighPriorityChunks(this); // Paper + + for (int i = 0; i < this.inventory.getContainerSize(); ++i) { + ItemStack itemstack = this.inventory.getItem(i); +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index c6b5f32153b63ac92df9c4b31b8de168481f79f2..c0bfe136ccb9ad4fc0f8ccdd703254205213ec8e 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -8,6 +8,7 @@ public final class Ticket implements Comparable> { + private final int ticketLevel; + public final T key; public final T getObjectReason() { return this.key; } // Paper - OBFHELPER + private long createdTick; public final long getCreationTick() { return this.createdTick; } // Paper - OBFHELPER ++ public int priority = 0; // Paper + + protected Ticket(TicketType type, int level, T argument) { + this.type = type; +@@ -56,6 +57,7 @@ public final class Ticket implements Comparable> { + return this.ticketLevel; + } + ++ public final void setCurrentTick(long i) { this.setCreatedTick(i); } // Paper - OBFHELPER + protected void setCreatedTick(long tickCreated) { + this.createdTick = tickCreated; + } +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index 583587457790df826a8a3239a4bd1d0f1dcab1da..2444f6f676db543509b14e8c882491dc3f41b264 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -28,6 +28,8 @@ public class TicketType { + public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper + public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper ++ public static final TicketType PRIORITY = create("priority", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper ++ public static final TicketType URGENT = create("urgent", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper + + public static TicketType create(String name, Comparator comparator) { + return new TicketType<>(name, comparator, 0L); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 3f416479e23c60ec5b4b779cce9ab62c74865ac8..0625bc7ffd07b66b27176fe62ae3061aa7c67df2 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1528,6 +1528,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + this.awaitingTeleportTime = this.tickCount; + this.player.absMoveTo(d0, d1, d2, f, f1); ++ this.player.forceCheckHighPriority(); // Paper + this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); + } + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 8e00747c1a717836d12a43aa48d667bf801167b0..168895dab31a0d5356eb96f2642399a1c99fccab 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -271,8 +271,8 @@ public abstract class PlayerList { + final ChunkPos pos = new ChunkPos(chunkX, chunkZ); + ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; + playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.toLong()); +- worldserver1.getChunkSource().runDistanceManagerUpdates(); +- worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { ++ worldserver1.getChunkSource().markAreaHighPriority(pos, 28, 3); ++ worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, false).thenApply(chunk -> { + ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); + if (updatingChunk != null) { + return updatingChunk.getEntityTickingFuture(); +@@ -692,6 +692,7 @@ public abstract class PlayerList { + SocketAddress socketaddress = loginlistener.connection.getRemoteAddress(); + + ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameprofile, new ServerPlayerGameMode(this.server.getLevel(Level.OVERWORLD))); ++ entity.isRealPlayer = true; // Paper + Player player = entity.getBukkitEntity(); + PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.connection.getRawAddress()).getAddress()); + +@@ -898,6 +899,7 @@ public abstract class PlayerList { + // CraftBukkit end + + worldserver1.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, new ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper ++ entityplayer1.forceCheckHighPriority(); // Player + while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < 256.0D) { + entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } +diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java +index 7ccf830146c252cff8e22553d293e02d4b53dad8..4a5f318adf5bc2ca1c3fab5d173a99cddd77ab85 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkPos.java ++++ b/src/main/java/net/minecraft/world/level/ChunkPos.java +@@ -104,6 +104,7 @@ public class ChunkPos { + return "[" + this.x + ", " + this.z + "]"; + } + ++ public final BlockPos asPosition() { return getWorldPosition(); } // Paper - OBFHELPER + public BlockPos getWorldPosition() { + return new BlockPos(this.getMinBlockX(), 0, this.getMinBlockZ()); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 4fc44390f432ef13c9952aa22bbb29bc8bf47975..7261e22a71d219efe0949a08c5d3f10747759469 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2523,6 +2523,10 @@ public class CraftWorld implements World { + return future; + } + ++ if (!urgent) { ++ // if not urgent, at least use a slightly boosted priority ++ world.getChunkSource().markHighPriority(new ChunkPos(x, z), 1); ++ } + return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { + net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); + return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index eb366396820c9b6731469df4198e0884a431a77c..610eabd2e93f9efccee810c3b5a314bc3cc649d8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -60,6 +60,7 @@ import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.network.ServerGamePacketListenerImpl; + import net.minecraft.server.players.UserWhiteListEntry; ++import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.LivingEntity; +@@ -69,6 +70,7 @@ import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; ++import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.GameType; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.entity.SignBlockEntity; +@@ -848,6 +850,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + throw new UnsupportedOperationException("Cannot set rotation of players. Consider teleporting instead."); + } + ++ // Paper start ++ @Override ++ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull PlayerTeleportEvent.TeleportCause cause) { ++ ((CraftWorld)loc.getWorld()).getHandle().getChunkSource().markAreaHighPriority(new ChunkPos(Mth.floor(loc.getX()) >> 4, Mth.floor(loc.getZ()) >> 4), 28, 3); // Paper - load area high priority ++ return super.teleportAsync(loc, cause); ++ } ++ // Paper end ++ + @Override + public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) { + Preconditions.checkArgument(location != null, "location"); diff --git a/patches/server-remapped/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/patches/server-remapped/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch new file mode 100644 index 0000000000..e8add9864d --- /dev/null +++ b/patches/server-remapped/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 23 May 2020 17:03:41 -0400 +Subject: [PATCH] Optimize sending packets to nearby locations (sounds/effects) + +Instead of using the entire world or player list, use the distance +maps to only iterate players who are even seeing the chunk the packet +is originating from. + +This will drastically cut down on packet sending cost for worlds with +lots of players in them. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 168895dab31a0d5356eb96f2642399a1c99fccab..713cc88dd067c0d918f253b1845f42c0d9eb920f 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1149,16 +1149,40 @@ public abstract class PlayerList { + } + + public void broadcast(@Nullable net.minecraft.world.entity.player.Player player, double x, double y, double z, double distance, ResourceKey worldKey, Packet packet) { +- for (int i = 0; i < this.players.size(); ++i) { +- ServerPlayer entityplayer = (ServerPlayer) this.players.get(i); ++ ServerLevel world = null; ++ if (player != null && player.level instanceof ServerLevel) { ++ world = (ServerLevel) player.level; ++ } + +- // CraftBukkit start - Test if player receiving packet can see the source of the packet +- if (player != null && player instanceof ServerPlayer && !entityplayer.getBukkitEntity().canSee(((ServerPlayer) player).getBukkitEntity())) { +- continue; ++ // Paper start ++ if (world == null) { ++ world = server.getLevel(worldKey); ++ } ++ ChunkMap chunkMap = world != null ? world.getChunkSource().chunkMap : null; ++ Object[] backingSet; ++ if (chunkMap == null) { ++ // Really shouldn't happen... ++ backingSet = world != null ? world.players.toArray() : players.toArray(); ++ } else { ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.fastFloor(x) >> 4, MCUtil.fastFloor(z) >> 4); ++ if (nearbyPlayers == null) { ++ return; + } ++ backingSet = nearbyPlayers.getBackingSet(); ++ } ++ ++ for (Object object : backingSet) { ++ if (!(object instanceof ServerPlayer)) continue; ++ ServerPlayer entityplayer = (ServerPlayer) object; ++ // Paper end ++ ++ // CraftBukkit start - Test if player receiving packet can see the source of the packet ++ //if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { // Paper ++ //continue; // Paper ++ //} // Paper + // CraftBukkit end + +- if (entityplayer != player && entityplayer.level.dimension() == worldKey) { ++ if (entityplayer != player && entityplayer.level.dimension() == worldKey && (!(player instanceof ServerPlayer) || entityplayer.getBukkitEntity().canSee(((ServerPlayer) player).getBukkitEntity()))) { // Paper + double d4 = x - entityplayer.getX(); + double d5 = y - entityplayer.getY(); + double d6 = z - entityplayer.getZ(); diff --git a/patches/server-remapped/0486-Improve-Chunk-Status-Transition-Speed.patch b/patches/server-remapped/0486-Improve-Chunk-Status-Transition-Speed.patch new file mode 100644 index 0000000000..38e09f9701 --- /dev/null +++ b/patches/server-remapped/0486-Improve-Chunk-Status-Transition-Speed.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 May 2020 23:32:14 -0400 +Subject: [PATCH] Improve Chunk Status Transition Speed + +When a chunk is loaded from disk that has already been generated, +the server has to promote the chunk through the system to reach +it's current desired status level. + +This results in every single status transition going from the main thread +to the world gen threads, only to discover it has no work it actually +needs to do.... and then it returns back to main. + +This back and forth costs a lot of time and can really delay chunk loads +when the server is under high TPS due to their being a lot of time in +between chunk load times, as well as hogs up the chunk threads from doing +actual generation and light work. + +Additionally, the whole task system uses a lot of CPU on the server threads anyways. + +So by optimizing status transitions for status's that are already complete, +we can run them to the desired level while on main thread (where it has +to happen anyways) instead of ever jumping to world gen thread. + +This will improve chunk loading effeciency to be reduced down to the following +scenario / path: + +1) MAIN: Chunk Requested, Load Request sent to ChunkTaskManager / IO Queue +2) IO: Once position in queue comes, submit read IO data and schedule to chunk task thread +3) CHUNK: Once IO is loaded and position in queue comes, deserialize the chunk data, process conversions, submit to main queue +4) MAIN: next Chunk Task process (Mid Tick or End Of Tick), load chunk data into world (POI, main thread tasks) +5) MAIN: process status transitions all the way to LIGHT, light schedules Threaded task +6) SERVER: Light tasks register light enablement for chunk and any lighting needing to be done +7) MAIN: Task returns to main, finish processing to FULL/TICKING status + +Previously would have hopped to SERVER around 12+ times there extra. + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index ce320672d7602c94dd75ad857435dca6ac3bab56..8260636da673ef095728c208db2d6237bab2db19 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -83,6 +83,13 @@ public class ChunkHolder { + this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); + } + // Paper end - optimise isOutsideOfRange ++ // Paper start - optimize chunk status progression without jumping through thread pool ++ public boolean canAdvanceStatus() { ++ ChunkStatus status = getChunkHolderStatus(); ++ ChunkAccess chunk = getAvailableChunkNow(); ++ return chunk != null && (status == null || chunk.getStatus().isAtLeastStatus(getNextStatus(status))); ++ } ++ // Paper end + + // Paper start - no-tick view distance + public final LevelChunk getSendingChunk() { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 7a1f6d1807757a43a7aa471db651404c06720820..acc566d14926dcf9e88f3e0837884e4c823d777c 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -792,7 +792,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return either.mapLeft((list) -> { + return (LevelChunk) list.get(list.size() / 2); + }); +- }, this.mainThreadExecutor); ++ }, this.mainInvokingExecutor); // Paper + } + + @Nullable +@@ -1142,7 +1142,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkAccess ichunkaccess = (ChunkAccess) optional.get(); + + if (ichunkaccess.getStatus().isOrAfter(requiredStatus)) { +- CompletableFuture completablefuture1; ++ CompletableFuture> completablefuture1; // Paper + + if (requiredStatus == ChunkStatus.LIGHT) { + completablefuture1 = this.scheduleChunkGeneration(holder, requiredStatus); +@@ -1158,7 +1158,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return this.scheduleChunkGeneration(holder, requiredStatus); + } + } +- }, this.mainThreadExecutor); ++ }, this.mainInvokingExecutor).thenComposeAsync(CompletableFuture::completedFuture, this.mainInvokingExecutor); // Paper - optimize chunk status progression without jumping through thread pool - ensure main + } + } + +@@ -1279,6 +1279,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return CompletableFuture.completedFuture(Either.right(playerchunk_failure)); + }); + }, (runnable) -> { ++ // Paper start - optimize chunk status progression without jumping through thread pool ++ if (holder.canAdvanceStatus()) { ++ this.mainInvokingExecutor.execute(runnable); ++ return; ++ } ++ // Paper end + this.worldgenMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); + }); + } diff --git a/patches/server-remapped/0487-Fix-villager-trading-demand-MC-163962.patch b/patches/server-remapped/0487-Fix-villager-trading-demand-MC-163962.patch new file mode 100644 index 0000000000..65b79cf458 --- /dev/null +++ b/patches/server-remapped/0487-Fix-villager-trading-demand-MC-163962.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Fri, 5 Jun 2020 20:02:04 -0500 +Subject: [PATCH] Fix villager trading demand - MC-163962 + +Prevent demand from going negative and tending to negative infinity + +diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java +index 9ce1c1092970618a204f87c673144152afbade99..fa74813e0fe76612023830b2fc41d41aa0b4f10e 100644 +--- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java ++++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java +@@ -109,7 +109,7 @@ public class MerchantOffer { + } + + public void updateDemand() { +- this.demand = this.demand + this.uses - (this.maxUses - this.uses); ++ this.demand = Math.max(0, this.demand + this.uses - (this.maxUses - this.uses)); // Paper + } + + public ItemStack assemble() { diff --git a/patches/server-remapped/0488-Maps-shouldn-t-load-chunks.patch b/patches/server-remapped/0488-Maps-shouldn-t-load-chunks.patch new file mode 100644 index 0000000000..186fc75fa9 --- /dev/null +++ b/patches/server-remapped/0488-Maps-shouldn-t-load-chunks.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Sun, 7 Jun 2020 21:43:42 +0100 +Subject: [PATCH] Maps shouldn't load chunks + +Previously maps would load all chunks in a certain radius depending on + their scale when trying to update their content. This would result in + main thread chunk loads when they weren't really necessary, especially + on low view distances or "slow" async chunk loads after teleports or + other prioritisation. + + This changes it to only try to render already loaded chunks based on + the assumption that the chunks around the player will get loaded + eventually anyways and that maps will get checked for update every + five ticks that movement occur in anyways. + +diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java +index 1736d2eb33e5f2221210a0a4f3ceb8905555a162..05759dc6edaa790a5e3f2ca2e0ae27e53cfa4397 100644 +--- a/src/main/java/net/minecraft/world/item/MapItem.java ++++ b/src/main/java/net/minecraft/world/item/MapItem.java +@@ -119,9 +119,9 @@ public class MapItem extends ComplexItem { + int k2 = (j / i + k1 - 64) * i; + int l2 = (k / i + l1 - 64) * i; + Multiset multiset = LinkedHashMultiset.create(); +- LevelChunk chunk = world.getChunkAt(new BlockPos(k2, 0, l2)); ++ LevelChunk chunk = world.getChunkIfLoaded(new BlockPos(k2, 0, l2)); // Paper - Maps shouldn't load chunks + +- if (!chunk.isEmpty()) { ++ if (chunk != null && !chunk.isEmpty()) { // Paper - Maps shouldn't load chunks + ChunkPos chunkcoordintpair = chunk.getPos(); + int i3 = k2 & 15; + int j3 = l2 & 15; diff --git a/patches/server-remapped/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/patches/server-remapped/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch new file mode 100644 index 0000000000..356dcc464b --- /dev/null +++ b/patches/server-remapped/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 7 Jun 2020 19:25:13 -0400 +Subject: [PATCH] Use seed based lookup for Treasure Maps - Fixes lag from + carto/sunken maps + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index bf4e50cd1d561456c033cda2d5c5487c5e3fe1eb..61aee2c109614a014149ae5a15ad2a28c796cb9d 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -415,8 +415,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.worldDataServer.setThundering(thundering); + } + +- @Override +- public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { ++ public Biome getBiomeBySeed(int i, int j, int k) { return getUncachedNoiseBiome(i, j, k); } // Paper - OBFHELPER ++ @Override public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { + return this.getChunkSource().getGenerator().getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ); + } + +diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java +index 05759dc6edaa790a5e3f2ca2e0ae27e53cfa4397..550892bc769a58991583b16295a72a162ceea788 100644 +--- a/src/main/java/net/minecraft/world/item/MapItem.java ++++ b/src/main/java/net/minecraft/world/item/MapItem.java +@@ -252,7 +252,7 @@ public class MapItem extends ComplexItem { + + for (l = 0; l < 128 * i; ++l) { + for (i1 = 0; i1 < 128 * i; ++i1) { +- abiomebase[l * 128 * i + i1] = worldserver.getBiome(new BlockPos((j / i - 64) * i + i1, 0, (k / i - 64) * i + l)); ++ abiomebase[l * 128 * i + i1] = worldserver.getBiomeBySeed((j / i - 64) * i + i1, 0, (k / i - 64) * i + l); // Paper + } + } + diff --git a/patches/server-remapped/0490-Optimize-Bit-Operations-by-inlining.patch b/patches/server-remapped/0490-Optimize-Bit-Operations-by-inlining.patch new file mode 100644 index 0000000000..f1615b3c0b --- /dev/null +++ b/patches/server-remapped/0490-Optimize-Bit-Operations-by-inlining.patch @@ -0,0 +1,220 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 4 Jun 2020 02:24:49 -0400 +Subject: [PATCH] Optimize Bit Operations by inlining + +Inline bit operations and reduce instruction count to make these hot +operations faster + +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 595abf528a7862478100770987906af1b13439fe..727af6ac84075db87615ebac51a024e6376fa3cb 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -31,14 +31,16 @@ public class BlockPos extends Vec3i { + }).stable(); + private static final Logger LOGGER = LogManager.getLogger(); + public static final BlockPos ZERO = new BlockPos(0, 0, 0); +- private static final int PACKED_X_LENGTH = 1 + Mth.log2(Mth.smallestEncompassingPowerOfTwo(30000000)); +- private static final int PACKED_Z_LENGTH = BlockPos.PACKED_X_LENGTH; +- private static final int PACKED_Y_LENGTH = 64 - BlockPos.PACKED_X_LENGTH - BlockPos.PACKED_Z_LENGTH; +- private static final long PACKED_X_MASK = (1L << BlockPos.PACKED_X_LENGTH) - 1L; +- private static final long PACKED_Y_MASK = (1L << BlockPos.PACKED_Y_LENGTH) - 1L; +- private static final long PACKED_Z_MASK = (1L << BlockPos.PACKED_Z_LENGTH) - 1L; +- private static final int Z_OFFSET = BlockPos.PACKED_Y_LENGTH; +- private static final int X_OFFSET = BlockPos.PACKED_Y_LENGTH + BlockPos.PACKED_Z_LENGTH; ++ // Paper start - static constants ++ private static final int PACKED_X_LENGTH = 26; ++ private static final int PACKED_Z_LENGTH = 26; ++ private static final int PACKED_Y_LENGTH = 12; ++ private static final long PACKED_X_MASK = 67108863; ++ private static final long PACKED_Y_MASK = 4095; ++ private static final long PACKED_Z_MASK = 67108863; ++ private static final int Z_OFFSET = 12; ++ private static final int X_OFFSET = 38; ++ // Paper end + + public BlockPos(int x, int y, int z) { + super(x, y, z); +@@ -60,28 +62,29 @@ public class BlockPos extends Vec3i { + this(pos.getX(), pos.getY(), pos.getZ()); + } + ++ public static long getAdjacent(int baseX, int baseY, int baseZ, Direction enumdirection) { return asLong(baseX + enumdirection.getStepX(), baseY + enumdirection.getStepY(), baseZ + enumdirection.getStepZ()); } // Paper + public static long offset(long value, Direction direction) { + return offset(value, direction.getStepX(), direction.getStepY(), direction.getStepZ()); + } + + public static long offset(long value, int x, int y, int z) { +- return asLong(getX(value) + x, getY(value) + y, getZ(value) + z); ++ return asLong((int) (value >> 38) + x, (int) ((value << 52) >> 52) + y, (int) ((value << 26) >> 38) + z); // Paper - simplify/inline + } + + public static int getX(long packedPos) { +- return (int) (packedPos << 64 - BlockPos.X_OFFSET - BlockPos.PACKED_X_LENGTH >> 64 - BlockPos.PACKED_X_LENGTH); ++ return (int) (packedPos >> 38); // Paper - simplify/inline + } + + public static int getY(long packedPos) { +- return (int) (packedPos << 64 - BlockPos.PACKED_Y_LENGTH >> 64 - BlockPos.PACKED_Y_LENGTH); ++ return (int) ((packedPos << 52) >> 52); // Paper - simplify/inline + } + + public static int getZ(long packedPos) { +- return (int) (packedPos << 64 - BlockPos.Z_OFFSET - BlockPos.PACKED_Z_LENGTH >> 64 - BlockPos.PACKED_Z_LENGTH); ++ return (int) ((packedPos << 26) >> 38); // Paper - simplify/inline + } + + public static BlockPos of(long packedPos) { +- return new BlockPos(getX(packedPos), getY(packedPos), getZ(packedPos)); ++ return new BlockPos((int) (packedPos >> 38), (int) ((packedPos << 52) >> 52), (int) ((packedPos << 26) >> 38)); // Paper - simplify/inline + } + + public long asLong() { +@@ -90,12 +93,7 @@ public class BlockPos extends Vec3i { + + public static long asLong(int x, int y, int z) { return asLong(x, y, z); } // Paper - OBFHELPER + public static long asLong(int x, int y, int z) { +- long l = 0L; +- +- l |= ((long) x & BlockPos.PACKED_X_MASK) << BlockPos.X_OFFSET; +- l |= ((long) y & BlockPos.PACKED_Y_MASK) << 0; +- l |= ((long) z & BlockPos.PACKED_Z_MASK) << BlockPos.Z_OFFSET; +- return l; ++ return (((long) x & (long) 67108863) << 38) | (((long) y & (long) 4095)) | (((long) z & (long) 67108863) << 12); // Paper - inline constants and simplify + } + + public static long getFlatIndex(long y) { +diff --git a/src/main/java/net/minecraft/core/SectionPos.java b/src/main/java/net/minecraft/core/SectionPos.java +index 700e0d7b132242bd65d13ec61c1f7036905b2767..c4bf1bc383fbdfb8ec997883aececde38206c7dd 100644 +--- a/src/main/java/net/minecraft/core/SectionPos.java ++++ b/src/main/java/net/minecraft/core/SectionPos.java +@@ -19,7 +19,7 @@ public class SectionPos extends Vec3i { + } + + public static SectionPos of(BlockPos pos) { +- return new SectionPos(blockToSectionCoord(pos.getX()), blockToSectionCoord(pos.getY()), blockToSectionCoord(pos.getZ())); ++ return new SectionPos(pos.getX() >> 4, pos.getY() >> 4, pos.getZ() >> 4); // Paper + } + + public static SectionPos of(ChunkPos chunkPos, int y) { +@@ -31,15 +31,23 @@ public class SectionPos extends Vec3i { + } + + public static SectionPos of(long packed) { +- return new SectionPos(x(packed), y(packed), z(packed)); ++ return new SectionPos((int) (packed >> 42), (int) (packed << 44 >> 44), (int) (packed << 22 >> 42)); // Paper + } + + public static long offset(long packed, Direction direction) { + return offset(packed, direction.getStepX(), direction.getStepY(), direction.getStepZ()); + } + ++ // Paper start ++ public static long getAdjacentFromBlockPos(int x, int y, int z, Direction enumdirection) { ++ return (((long) ((x >> 4) + enumdirection.getStepX()) & 4194303L) << 42) | (((long) ((y >> 4) + enumdirection.getStepY()) & 1048575L)) | (((long) ((z >> 4) + enumdirection.getStepZ()) & 4194303L) << 20); ++ } ++ public static long getAdjacentFromSectionPos(int x, int y, int z, Direction enumdirection) { ++ return (((long) (x + enumdirection.getStepX()) & 4194303L) << 42) | (((long) ((y) + enumdirection.getStepY()) & 1048575L)) | (((long) (z + enumdirection.getStepZ()) & 4194303L) << 20); ++ } ++ // Paper end + public static long offset(long packed, int x, int y, int z) { +- return asLong(x(packed) + x, y(packed) + y, z(packed) + z); ++ return (((long) ((int) (packed >> 42) + x) & 4194303L) << 42) | (((long) ((int) (packed << 44 >> 44) + y) & 1048575L)) | (((long) ((int) (packed << 22 >> 42) + z) & 4194303L) << 20); // Simplify to reduce instruction count + } + + public static int blockToSectionCoord(int coord) { +@@ -51,11 +59,7 @@ public class SectionPos extends Vec3i { + } + + public static short sectionRelativePos(BlockPos pos) { +- int i = sectionRelative(pos.getX()); +- int j = sectionRelative(pos.getY()); +- int k = sectionRelative(pos.getZ()); +- +- return (short) (i << 8 | k << 4 | j << 0); ++ return (short) ((pos.getX() & 15) << 8 | (pos.getZ() & 15) << 4 | pos.getY() & 15); // Paper - simplify/inline + } + + public static int sectionRelativeX(short packedLocalPos) { +@@ -114,16 +118,16 @@ public class SectionPos extends Vec3i { + return this.getZ(); + } + +- public int minBlockX() { +- return this.x() << 4; ++ public final int minBlockX() { // Paper ++ return this.getX() << 4; // Paper + } + +- public int minBlockY() { +- return this.y() << 4; ++ public final int minBlockY() { // Paper ++ return this.getY() << 4; // Paper + } + +- public int minBlockZ() { +- return this.z() << 4; ++ public final int minBlockZ() { // Paper ++ return this.getZ() << 4; // Paper + } + + public int maxBlockX() { +@@ -138,8 +142,10 @@ public class SectionPos extends Vec3i { + return (this.z() << 4) + 15; + } + ++ public static long blockToSection(long i) { return blockToSection(i); } // Paper - OBFHELPER + public static long blockToSection(long blockPos) { +- return asLong(blockToSectionCoord(BlockPos.getX(blockPos)), blockToSectionCoord(BlockPos.getY(blockPos)), blockToSectionCoord(BlockPos.getZ(blockPos))); ++ // b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); ++ return (((long) (int) (blockPos >> 42) & 4194303L) << 42) | (((long) (int) ((blockPos << 52) >> 56) & 1048575L)) | (((long) (int) ((blockPos << 26) >> 42) & 4194303L) << 20); // Simplify to reduce instruction count + } + + public static long getZeroNode(long pos) { +@@ -160,17 +166,18 @@ public class SectionPos extends Vec3i { + return new ChunkPos(this.x(), this.z()); + } + ++ // Paper start ++ public static long blockPosAsSectionLong(int i, int j, int k) { ++ return (((long) (i >> 4) & 4194303L) << 42) | (((long) (j >> 4) & 1048575L)) | (((long) (k >> 4) & 4194303L) << 20); ++ } ++ // Paper end ++ public static long asLong(int i, int j, int k) { return asLong(i, j, k); } // Paper - OBFHELPER + public static long asLong(int x, int y, int z) { +- long l = 0L; +- +- l |= ((long) x & 4194303L) << 42; +- l |= ((long) y & 1048575L) << 0; +- l |= ((long) z & 4194303L) << 20; +- return l; ++ return (((long) x & 4194303L) << 42) | (((long) y & 1048575L)) | (((long) z & 4194303L) << 20); // Paper - Simplify to reduce instruction count + } + + public long asLong() { +- return asLong(this.x(), this.y(), this.z()); ++ return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count + } + + public Stream blocksInside() { +@@ -178,18 +185,11 @@ public class SectionPos extends Vec3i { + } + + public static Stream cube(SectionPos center, int radius) { +- int j = center.x(); +- int k = center.y(); +- int l = center.z(); +- +- return betweenClosedStream(j - radius, k - radius, l - radius, j + radius, k + radius, l + radius); ++ return betweenClosedStream(center.getX() - radius, center.getY() - radius, center.getZ() - radius, center.getX() + radius, center.getY() + radius, center.getZ() + radius); // Paper - simplify/inline + } + + public static Stream aroundChunk(ChunkPos center, int radius) { +- int j = center.x; +- int k = center.z; +- +- return betweenClosedStream(j - radius, 0, k - radius, j + radius, 15, k + radius); ++ return betweenClosedStream(center.x - radius, 0, center.z - radius, center.x + radius, 15, center.z + radius); // Paper - simplify/inline + } + + public static Stream betweenClosedStream(final int minX, final int minY, final int minZ, final int maxX, final int maxY, final int maxZ) { diff --git a/patches/server-remapped/0491-Optimize-Light-Engine.patch b/patches/server-remapped/0491-Optimize-Light-Engine.patch new file mode 100644 index 0000000000..53f26fe554 --- /dev/null +++ b/patches/server-remapped/0491-Optimize-Light-Engine.patch @@ -0,0 +1,1464 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 4 Jun 2020 22:43:29 -0400 +Subject: [PATCH] Optimize Light Engine + +Massive update to light to improve performance and chunk loading/generation. + +1) Massive bit packing/unpacking optimizations and inlining. + A lot of performance has to do with constant packing and unpacking of bits. + We now inline a most bit operations, and re-use base x/y/z bits in many places. + This helps with cpu level processing to just do all the math at once instead + of having to jump in and out of function calls. + + This much logic also is likely over the JVM Inline limit for JIT too. +2) Applied a few of JellySquid's Phosphor mod optimizations such as + - ensuring we don't notify neighbor chunks when neighbor chunk doesn't need to be notified + - reduce hasLight checks in initializing light, and prob some more, they are tagged JellySquid where phosphor influence was used. +3) Optimize hot path accesses to getting updating chunk to have less branching +4) Optimize getBlock accesses to have less branching, and less unpacking +5) Have a separate urgent bucket for chunk light tasks. These tasks will always cut in line over non blocking light tasks. +6) Retain chunk priority while light tasks are enqueued. So if a task comes in at high priority but the queue is full + of tasks already at a lower priority, before the task was simply added to the end. Now it can cut in line to the front. + this applies for both urgent and non urgent tasks. +7) Buffer non urgent tasks even if queueUpdate is called multiple times to improve efficiency. +8) Fix NPE risk that crashes server in getting nibble data + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 8260636da673ef095728c208db2d6237bab2db19..9e3629884709126574a52ad44fe7523f01dbcce9 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -753,6 +753,7 @@ public class ChunkHolder { + ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; + } + chunkMap.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, ioPriority); ++ chunkMap.level.getChunkSource().getLightEngine().queue.changePriority(pos.toLong(), getCurrentPriority(), priority); + } + if (getCurrentPriority() != priority) { + this.onLevelChange.onLevelChange(this.pos, this::getCurrentPriority, priority, this::setPriority); // use preferred priority +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index acc566d14926dcf9e88f3e0837884e4c823d777c..f4dd30c8b3326db72d3b3068ee2291de6f15de7c 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -98,6 +98,7 @@ import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelStorageSource; ++import net.minecraft.world.level.storage.PrimaryLevelData; + import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper + import org.apache.commons.lang3.mutable.MutableBoolean; + import org.apache.logging.log4j.LogManager; +@@ -328,6 +329,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + // Paper end + ++ private final java.util.concurrent.ExecutorService lightThread; + public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier supplier, int i, boolean flag) { + super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag); + //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning +@@ -359,7 +361,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ProcessorHandle mailbox = ProcessorHandle.of("main", mainThreadExecutor::tell); + + this.progressListener = worldGenerationProgressListener; +- ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(workerExecutor, "light"); // Paper ++ // Paper start - use light thread ++ ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(lightThread = java.util.concurrent.Executors.newSingleThreadExecutor(r -> { ++ Thread thread = new Thread(r); ++ thread.setName(((PrimaryLevelData)level.getLevelData()).getLevelName() + " - Light"); ++ thread.setDaemon(true); ++ thread.setPriority(Thread.NORM_PRIORITY+1); ++ return thread; ++ }), "light"); ++ // Paper end + + this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), workerExecutor, Integer.MAX_VALUE); + this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); +@@ -705,6 +715,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end + } + ++ protected final IntSupplier getPrioritySupplier(long i) { return getChunkQueueLevel(i); } // Paper - OBFHELPER + protected IntSupplier getChunkQueueLevel(long pos) { + return () -> { + ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos); +@@ -832,6 +843,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + @Override + public void close() throws IOException { + try { ++ this.lightThread.shutdown(); // Paper + this.queueSorter.close(); + this.level.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line + this.poiManager.close(); +diff --git a/src/main/java/net/minecraft/server/level/SectionTracker.java b/src/main/java/net/minecraft/server/level/SectionTracker.java +index 125ae965bb539ae24c60cb992eb7cfc35fd65b25..9fa6c290373b0e0cc0e7ed84c0c2363c8ad14dd3 100644 +--- a/src/main/java/net/minecraft/server/level/SectionTracker.java ++++ b/src/main/java/net/minecraft/server/level/SectionTracker.java +@@ -1,6 +1,5 @@ + package net.minecraft.server.level; + +-import net.minecraft.core.SectionPos; + import net.minecraft.world.level.lighting.DynamicGraphMinFixedPoint; + + public abstract class SectionTracker extends DynamicGraphMinFixedPoint { +@@ -16,14 +15,20 @@ public abstract class SectionTracker extends DynamicGraphMinFixedPoint { + + @Override + protected void checkNeighborsAfterUpdate(long id, int level, boolean decrease) { ++ // Paper start ++ int x = (int) (id >> 42); ++ int y = (int) (id << 44 >> 44); ++ int z = (int) (id << 22 >> 42); ++ // Paper end + for (int k = -1; k <= 1; ++k) { + for (int l = -1; l <= 1; ++l) { + for (int i1 = -1; i1 <= 1; ++i1) { +- long j1 = SectionPos.offset(id, k, l, i1); ++ if (k == 0 && l == 0 && i1 == 0) continue; // Paper ++ long j1 = (((long) (x + k) & 4194303L) << 42) | (((long) (y + l) & 1048575L)) | (((long) (z + i1) & 4194303L) << 20); // Paper + +- if (j1 != id) { ++ //if (j1 != i) { // Paper - checked above + this.checkNeighbor(id, j1, level, decrease); +- } ++ //} // Paper + } + } + } +@@ -34,10 +39,15 @@ public abstract class SectionTracker extends DynamicGraphMinFixedPoint { + protected int getComputedLevel(long id, long excludedId, int maxLevel) { + int l = maxLevel; + ++ // Paper start ++ int x = (int) (id >> 42); ++ int y = (int) (id << 44 >> 44); ++ int z = (int) (id << 22 >> 42); ++ // Paper end + for (int i1 = -1; i1 <= 1; ++i1) { + for (int j1 = -1; j1 <= 1; ++j1) { + for (int k1 = -1; k1 <= 1; ++k1) { +- long l1 = SectionPos.offset(id, i1, j1, k1); ++ long l1 = (((long) (x + i1) & 4194303L) << 42) | (((long) (y + j1) & 1048575L)) | (((long) (z + k1) & 4194303L) << 20); // Paper + + if (l1 == id) { + l1 = Long.MAX_VALUE; +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index f36badcafbad7fb4537ffdf54d9e266ae3d72459..7a615a18f1f297adfe7e046407a019d8933e9ed9 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -1072,7 +1072,7 @@ public class ServerChunkCache extends ChunkSource { + if (ServerChunkCache.this.runDistanceManagerUpdates()) { + return true; + } else { +- ServerChunkCache.this.lightEngine.tryScheduleUpdate(); ++ ServerChunkCache.this.lightEngine.tryScheduleUpdate(); // Paper - not needed + return super.pollTask() || execChunkTask; // Paper + } + } finally { +diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java +index cc4190b3a8904d1eaae0f542a3b3090583f5ff82..14835bfab300d305faee2db705d7386dc16427f5 100644 +--- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java ++++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java +@@ -1,6 +1,7 @@ + package net.minecraft.server.level; + + import com.mojang.datafixers.util.Pair; ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; // Paper + import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import it.unimi.dsi.fastutil.objects.ObjectList; + import it.unimi.dsi.fastutil.objects.ObjectListIterator; +@@ -16,6 +17,7 @@ import net.minecraft.util.thread.ProcessorMailbox; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.DataLayer; + import net.minecraft.world.level.chunk.LevelChunkSection; + import net.minecraft.world.level.chunk.LightChunkGetter; +@@ -27,15 +29,149 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl + + private static final Logger LOGGER = LogManager.getLogger(); + private final ProcessorMailbox taskMailbox; +- private final ObjectList> lightTasks = new ObjectArrayList(); +- private final ChunkMap chunkMap; ++ // Paper start ++ private static final int MAX_PRIORITIES = ChunkMap.MAX_CHUNK_DISTANCE + 2; ++ ++ private boolean isChunkLightStatus(long pair) { ++ ChunkHolder playerChunk = playerChunkMap.getVisibleChunkIfPresent(pair); ++ if (playerChunk == null) { ++ return false; ++ } ++ ChunkStatus status = ChunkHolder.getStatus(playerChunk.getTicketLevel()); ++ return status != null && status.isAtLeastStatus(ChunkStatus.LIGHT); ++ } ++ ++ static class ChunkLightQueue { ++ public boolean shouldFastUpdate; ++ java.util.ArrayDeque pre = new java.util.ArrayDeque(); ++ java.util.ArrayDeque post = new java.util.ArrayDeque(); ++ ++ ChunkLightQueue(long chunk) {} ++ } ++ ++ static class PendingLightTask { ++ long chunkId; ++ IntSupplier priority; ++ Runnable pre; ++ Runnable post; ++ boolean fastUpdate; ++ ++ public PendingLightTask(long chunkId, IntSupplier priority, Runnable pre, Runnable post, boolean fastUpdate) { ++ this.chunkId = chunkId; ++ this.priority = priority; ++ this.pre = pre; ++ this.post = post; ++ this.fastUpdate = fastUpdate; ++ } ++ } ++ ++ ++ // Retain the chunks priority level for queued light tasks ++ class LightQueue { ++ private int size = 0; ++ private final Long2ObjectLinkedOpenHashMap[] buckets = new Long2ObjectLinkedOpenHashMap[MAX_PRIORITIES]; ++ private final java.util.concurrent.ConcurrentLinkedQueue pendingTasks = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ private final java.util.concurrent.ConcurrentLinkedQueue priorityChanges = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ ++ private LightQueue() { ++ for (int i = 0; i < buckets.length; i++) { ++ buckets[i] = new Long2ObjectLinkedOpenHashMap<>(); ++ } ++ } ++ ++ public void changePriority(long pair, int currentPriority, int priority) { ++ this.priorityChanges.add(() -> { ++ ChunkLightQueue remove = this.buckets[currentPriority].remove(pair); ++ if (remove != null) { ++ ChunkLightQueue existing = this.buckets[Math.max(1, priority)].put(pair, remove); ++ if (existing != null) { ++ remove.pre.addAll(existing.pre); ++ remove.post.addAll(existing.post); ++ } ++ } ++ }); ++ } ++ ++ public final void addChunk(long chunkId, IntSupplier priority, Runnable pre, Runnable post) { ++ pendingTasks.add(new PendingLightTask(chunkId, priority, pre, post, true)); ++ tryScheduleUpdate(); ++ } ++ ++ public final void add(long chunkId, IntSupplier priority, ThreadedLevelLightEngine.TaskType type, Runnable run) { ++ pendingTasks.add(new PendingLightTask(chunkId, priority, type == TaskType.PRE_UPDATE ? run : null, type == TaskType.POST_UPDATE ? run : null, false)); ++ } ++ public final void add(PendingLightTask update) { ++ int priority = update.priority.getAsInt(); ++ ChunkLightQueue lightQueue = this.buckets[priority].computeIfAbsent(update.chunkId, ChunkLightQueue::new); ++ ++ if (update.pre != null) { ++ this.size++; ++ lightQueue.pre.add(update.pre); ++ } ++ if (update.post != null) { ++ this.size++; ++ lightQueue.post.add(update.post); ++ } ++ if (update.fastUpdate) { ++ lightQueue.shouldFastUpdate = true; ++ } ++ } ++ ++ public final boolean isEmpty() { ++ return this.size == 0 && this.pendingTasks.isEmpty(); ++ } ++ ++ public final int size() { ++ return this.size; ++ } ++ ++ public boolean poll(java.util.List pre, java.util.List post) { ++ PendingLightTask pending; ++ while ((pending = pendingTasks.poll()) != null) { ++ add(pending); ++ } ++ Runnable run; ++ while ((run = priorityChanges.poll()) != null) { ++ run.run(); ++ } ++ boolean hasWork = false; ++ Long2ObjectLinkedOpenHashMap[] buckets = this.buckets; ++ int priority = 0; ++ while (priority < MAX_PRIORITIES && !isEmpty()) { ++ Long2ObjectLinkedOpenHashMap bucket = buckets[priority]; ++ if (bucket.isEmpty()) { ++ priority++; ++ if (hasWork) { ++ return true; ++ } else { ++ continue; ++ } ++ } ++ ChunkLightQueue queue = bucket.removeFirst(); ++ this.size -= queue.pre.size() + queue.post.size(); ++ pre.addAll(queue.pre); ++ post.addAll(queue.post); ++ queue.pre.clear(); ++ queue.post.clear(); ++ hasWork = true; ++ if (queue.shouldFastUpdate) { ++ return true; ++ } ++ } ++ return hasWork; ++ } ++ } ++ ++ final LightQueue queue = new LightQueue(); ++ // Paper end ++ private final ChunkMap chunkMap; private final ChunkMap playerChunkMap; // Paper + private final ProcessorHandle> sorterMailbox; + private volatile int taskPerBatch = 5; + private final AtomicBoolean scheduled = new AtomicBoolean(); + + public ThreadedLevelLightEngine(LightChunkGetter chunkProvider, ChunkMap chunkStorage, boolean hasBlockLight, ProcessorMailbox processor, ProcessorHandle> executor) { + super(chunkProvider, true, hasBlockLight); +- this.chunkMap = chunkStorage; ++ this.chunkMap = chunkStorage; this.playerChunkMap = chunkMap; // Paper + this.sorterMailbox = executor; + this.taskMailbox = processor; + } +@@ -122,13 +258,9 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl + } + + private void addTask(int x, int z, IntSupplier completedLevelSupplier, ThreadedLevelLightEngine.TaskType stage, Runnable task) { +- this.sorterMailbox.tell(ChunkTaskPriorityQueueSorter.message(() -> { +- this.lightTasks.add(Pair.of(stage, task)); +- if (this.lightTasks.size() >= this.taskPerBatch) { +- this.runUpdate(); +- } +- +- }, ChunkPos.asLong(x, z), completedLevelSupplier)); ++ // Paper start - replace method ++ this.queue.add(ChunkPos.asLong(x, z), completedLevelSupplier, stage, task); ++ // Paper end + } + + @Override +@@ -145,8 +277,19 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl + public CompletableFuture lightChunk(ChunkAccess chunk, boolean excludeBlocks) { + ChunkPos chunkcoordintpair = chunk.getPos(); + +- chunk.setLightCorrect(false); +- this.addTask(chunkcoordintpair.x, chunkcoordintpair.z, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> { ++ // Paper start ++ //ichunkaccess.b(false); // Don't need to disable this ++ long pair = chunkcoordintpair.toLong(); ++ CompletableFuture future = new CompletableFuture<>(); ++ IntSupplier prioritySupplier = playerChunkMap.getPrioritySupplier(pair); ++ boolean[] skippedPre = {false}; ++ this.queue.addChunk(pair, prioritySupplier, Util.name(() -> { ++ if (!isChunkLightStatus(pair)) { ++ future.complete(chunk); ++ skippedPre[0] = true; ++ return; ++ } ++ // Paper end + LevelChunkSection[] achunksection = chunk.getSections(); + + for (int i = 0; i < 16; ++i) { +@@ -164,55 +307,48 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl + }); + } + +- this.chunkMap.releaseLightTicket(chunkcoordintpair); ++ // this.d.c(chunkcoordintpair); // Paper - move into post task below + }, () -> { + return "lightChunk " + chunkcoordintpair + " " + excludeBlocks; +- })); +- return CompletableFuture.supplyAsync(() -> { ++ // Paper start - merge the 2 together ++ }), () -> { ++ this.chunkMap.releaseLightTicket(chunkcoordintpair); // Paper - release light tickets as post task to ensure they stay loaded until fully done ++ if (skippedPre[0]) return; // Paper - future's already complete + chunk.setLightCorrect(true); + super.retainData(chunkcoordintpair, false); +- return chunk; +- }, (runnable) -> { +- this.addTask(chunkcoordintpair.x, chunkcoordintpair.z, ThreadedLevelLightEngine.TaskType.POST_UPDATE, runnable); ++ // Paper start ++ future.complete(chunk); + }); ++ return future; ++ // Paper end + } + + public void tryScheduleUpdate() { +- if ((!this.lightTasks.isEmpty() || super.hasLightWork()) && this.scheduled.compareAndSet(false, true)) { ++ if ((!this.queue.isEmpty() || super.hasLightWork()) && this.scheduled.compareAndSet(false, true)) { // Paper + this.taskMailbox.tell((() -> { // Paper - decompile error + this.runUpdate(); + this.scheduled.set(false); ++ tryScheduleUpdate(); // Paper - if we still have work to do, do it! + })); + } + + } + ++ // Paper start - replace impl ++ private final java.util.List pre = new java.util.ArrayList<>(); ++ private final java.util.List post = new java.util.ArrayList<>(); + private void runUpdate() { +- int i = Math.min(this.lightTasks.size(), this.taskPerBatch); +- ObjectListIterator> objectlistiterator = this.lightTasks.iterator(); +- +- Pair pair; +- int j; +- +- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { +- pair = (Pair) objectlistiterator.next(); +- if (pair.getFirst() == ThreadedLevelLightEngine.TaskType.PRE_UPDATE) { +- ((Runnable) pair.getSecond()).run(); +- } ++ if (queue.poll(pre, post)) { ++ pre.forEach(Runnable::run); ++ pre.clear(); ++ super.runUpdates(Integer.MAX_VALUE, true, true); ++ post.forEach(Runnable::run); ++ post.clear(); ++ } else { ++ // might have level updates to go still ++ super.runUpdates(Integer.MAX_VALUE, true, true); + } +- +- objectlistiterator.back(j); +- super.runUpdates(Integer.MAX_VALUE, true, true); +- +- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { +- pair = (Pair) objectlistiterator.next(); +- if (pair.getFirst() == ThreadedLevelLightEngine.TaskType.POST_UPDATE) { +- ((Runnable) pair.getSecond()).run(); +- } +- +- objectlistiterator.remove(); +- } +- ++ // Paper end + } + + public void setTaskPerBatch(int taskBatchSize) { +diff --git a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java +index c763aa0c0cf49dd844af94a820103258b49021ae..195535835bdc63f7cfdebeaa957dde590262ea42 100644 +--- a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java ++++ b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java +@@ -110,7 +110,8 @@ public class ProcessorMailbox implements ProcessorHandle, AutoCloseable, R + + } + +- @Override ++ ++ public final void queue(T t0) { tell(t0); } @Override // Paper - OBFHELPER + public void tell(T message) { + this.queue.push(message); + this.registerForExecution(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java +index 83e9d8bff9a31fe13a0e22445cd6eecb7abe8561..1e8ce9894fd0a121da83020c6064b7833af1c5f2 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java +@@ -11,6 +11,13 @@ import net.minecraft.server.MCUtil; + public class DataLayer { + + // Paper start ++ public static final DataLayer EMPTY_NIBBLE_ARRAY = new DataLayer() { ++ @Override ++ public byte[] getData() { ++ throw new IllegalStateException(); ++ } ++ }; ++ public long lightCacheKey = Long.MIN_VALUE; + public static byte[] EMPTY_NIBBLE = new byte[2048]; + private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072); + private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8)); +diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java +index 709fc42057f8a0282c3c942067e63abb874d9042..eaaaecb67966e5e366cf59f92674c82d1d87552e 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java ++++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java +@@ -23,9 +23,11 @@ public final class BlockLightEngine extends LayerLightEngine> 38); ++ int k = (int) ((blockPos << 52) >> 52); ++ int l = (int) ((blockPos << 26) >> 38); ++ // Paper end + BlockGetter iblockaccess = this.chunkSource.getChunkForLighting(j >> 4, l >> 4); + + return iblockaccess != null ? iblockaccess.getLightEmission(this.pos.set(j, k, l)) : 0; +@@ -40,25 +42,33 @@ public final class BlockLightEngine extends LayerLightEngine= 15) { + return level; + } else { +- int l = Integer.signum(BlockPos.getX(targetId) - BlockPos.getX(sourceId)); +- int i1 = Integer.signum(BlockPos.getY(targetId) - BlockPos.getY(sourceId)); +- int j1 = Integer.signum(BlockPos.getZ(targetId) - BlockPos.getZ(sourceId)); ++ // Paper start - reuse math - credit to JellySquid for idea ++ int jx = (int) (targetId >> 38); ++ int jy = (int) ((targetId << 52) >> 52); ++ int jz = (int) ((targetId << 26) >> 38); ++ int ix = (int) (sourceId >> 38); ++ int iy = (int) ((sourceId << 52) >> 52); ++ int iz = (int) ((sourceId << 26) >> 38); ++ int l = Integer.signum(jx - ix); ++ int i1 = Integer.signum(jy - iy); ++ int j1 = Integer.signum(jz - iz); ++ // Paper end + Direction enumdirection = Direction.fromNormal(l, i1, j1); + + if (enumdirection == null) { + return 15; + } else { + //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded +- BlockState iblockdata = this.getStateAndOpacity(targetId, mutableint); +- +- if (mutableint.getValue() >= 15) { ++ BlockState iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); // Paper ++ int blockedLight = mutableint.getValue(); // Paper ++ if (blockedLight >= 15) { // Paper + return 15; + } else { +- BlockState iblockdata1 = this.getStateAndOpacity(sourceId, (MutableInt) null); ++ BlockState iblockdata1 = this.getBlockOptimized(ix, iy, iz); // Paper + VoxelShape voxelshape = this.getShape(iblockdata1, sourceId, enumdirection); + VoxelShape voxelshape1 = this.getShape(iblockdata, targetId, enumdirection.getOpposite()); + +- return Shapes.faceShapeOccludes(voxelshape, voxelshape1) ? 15 : level + Math.max(1, mutableint.getValue()); ++ return Shapes.faceShapeOccludes(voxelshape, voxelshape1) ? 15 : level + Math.max(1, blockedLight); // Paper + } + } + } +@@ -66,14 +76,19 @@ public final class BlockLightEngine extends LayerLightEngine> 38); ++ int y = (int) ((id << 52) >> 52); ++ int z = (int) ((id << 26) >> 38); ++ long k = SectionPos.blockPosAsSectionLong(x, y, z); ++ // Paper end + Direction[] aenumdirection = BlockLightEngine.DIRECTIONS; + int l = aenumdirection.length; + + for (int i1 = 0; i1 < l; ++i1) { + Direction enumdirection = aenumdirection[i1]; +- long j1 = BlockPos.offset(id, enumdirection); +- long k1 = SectionPos.blockToSection(j1); ++ long j1 = BlockPos.getAdjacent(x, y, z, enumdirection); // Paper ++ long k1 = SectionPos.blockToSection(j1); // Paper + + if (k == k1 || ((BlockLightSectionStorage) this.storage).storingLightForSection(k1)) { + this.checkNeighbor(id, j1, level, decrease); +@@ -98,27 +113,37 @@ public final class BlockLightEngine extends LayerLightEngine> 38); ++ int baseY = (int) ((id << 52) >> 52); ++ int baseZ = (int) ((id << 26) >> 38); ++ long j1 = SectionPos.blockPosAsSectionLong(baseX, baseY, baseZ); ++ DataLayer nibblearray = this.storage.updating.getUpdatingOptimized(j1); ++ // Paper end + Direction[] aenumdirection = BlockLightEngine.DIRECTIONS; + int k1 = aenumdirection.length; + + for (int l1 = 0; l1 < k1; ++l1) { + Direction enumdirection = aenumdirection[l1]; +- long i2 = BlockPos.offset(id, enumdirection); ++ // Paper start ++ int newX = baseX + enumdirection.getStepX(); ++ int newY = baseY + enumdirection.getStepY(); ++ int newZ = baseZ + enumdirection.getStepZ(); ++ long i2 = BlockPos.asLong(newX, newY, newZ); + + if (i2 != excludedId) { +- long j2 = SectionPos.blockToSection(i2); ++ long j2 = SectionPos.blockPosAsSectionLong(newX, newY, newZ); ++ // Paper end + DataLayer nibblearray1; + + if (j1 == j2) { + nibblearray1 = nibblearray; + } else { +- nibblearray1 = ((BlockLightSectionStorage) this.storage).getDataLayer(j2, true); ++ nibblearray1 = ((BlockLightSectionStorage) this.storage).updating.getUpdatingOptimized(j2); // Paper + } + + if (nibblearray1 != null) { +- int k2 = this.computeLevelFromNeighbor(i2, id, this.getLevel(nibblearray1, i2)); ++ int k2 = this.computeLevelFromNeighbor(i2, id, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper + + if (l > k2) { + l = k2; +diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java +index a1ad4d73ddaf6afe97a1f1ff7e0622b52fac8761..f771ef8d841567b421b6c0529af3f0713c79eb7c 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java +@@ -1,8 +1,6 @@ + package net.minecraft.world.level.lighting; + + import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +-import net.minecraft.core.BlockPos; +-import net.minecraft.core.SectionPos; + import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.chunk.DataLayer; + import net.minecraft.world.level.chunk.LightChunkGetter; +@@ -15,10 +13,14 @@ public class BlockLightSectionStorage extends LayerLightSectionStorage> 38); ++ int baseY = (int) ((blockPos << 52) >> 52); ++ int baseZ = (int) ((blockPos << 26) >> 38); ++ long j = (((long) (baseX >> 4) & 4194303L) << 42) | (((long) (baseY >> 4) & 1048575L)) | (((long) (baseZ >> 4) & 4194303L) << 20); ++ DataLayer nibblearray = this.e_visible.lookup.apply(j); ++ return nibblearray == null ? 0 : nibblearray.get(baseX & 15, baseY & 15, baseZ & 15); ++ // Paper end + } + + public static final class BlockDataLayerStorageMap extends DataLayerStorageMap { +diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +index 54cca3b376e5ce02936edc8b9c17e67e17f07147..ed2ed6194670016086be580dc4514d5d3d1b235b 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java ++++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +@@ -7,13 +7,18 @@ import net.minecraft.world.level.chunk.DataLayer; + + public abstract class DataLayerStorageMap> { + +- private final long[] lastSectionKeys = new long[2]; +- private final DataLayer[] lastSections = new DataLayer[2]; ++ // private final long[] b = new long[2]; // Paper - unused ++ private final DataLayer[] lastSections = new DataLayer[]{DataLayer.EMPTY_NIBBLE_ARRAY, DataLayer.EMPTY_NIBBLE_ARRAY}; private final DataLayer[] cache = lastSections; // Paper - OBFHELPER + private boolean cacheEnabled; + protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data + protected final boolean isVisible; // Paper - avoid copying light data +- java.util.function.Function lookup; // Paper - faster branchless lookup + ++ // Paper start - faster lookups with less branching, use interface to avoid boxing instead of Function ++ public final NibbleArrayAccess lookup; ++ public interface NibbleArrayAccess { ++ DataLayer apply(long id); ++ } ++ // Paper end + // Paper start - avoid copying light data + protected DataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { + if (isVisible) { +@@ -21,12 +26,14 @@ public abstract class DataLayerStorageMap> { + } + this.data = data; + this.isVisible = isVisible; ++ // Paper end - avoid copying light data ++ // Paper start - faster lookups with less branching + if (isVisible) { + lookup = data::getVisibleAsync; + } else { +- lookup = data::getUpdating; ++ lookup = data.getUpdatingMap()::get; // jump straight the sub map + } +- // Paper end - avoid copying light data ++ // Paper end + this.clearCache(); + this.cacheEnabled = true; + } +@@ -36,7 +43,9 @@ public abstract class DataLayerStorageMap> { + public void copyDataLayer(long pos) { + if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data + DataLayer updating = this.data.getUpdating(pos); // Paper - pool nibbles +- this.data.queueUpdate(pos, new DataLayer().markPoolSafe(updating.getCloneIfSet())); // Paper - avoid copying light data - pool safe clone ++ DataLayer nibblearray = new DataLayer().markPoolSafe(updating.getCloneIfSet()); // Paper ++ nibblearray.lightCacheKey = pos; // Paper ++ this.data.queueUpdate(pos, nibblearray); // Paper - avoid copying light data - pool safe clone + if (updating.cleaner != null) MCUtil.scheduleTask(2, updating.cleaner, "Light Engine Release"); // Paper - delay clean incase anything holding ref was still using it + this.clearCache(); + } +@@ -45,34 +54,34 @@ public abstract class DataLayerStorageMap> { + return lookup.apply(chunkPos) != null; // Paper - avoid copying light data + } + +- @Nullable +- public final DataLayer getLayer(long chunkPos) { // Paper - final +- if (this.cacheEnabled) { +- for (int j = 0; j < 2; ++j) { +- if (chunkPos == this.lastSectionKeys[j]) { +- return this.lastSections[j]; +- } +- } +- } +- +- DataLayer nibblearray = lookup.apply(chunkPos); // Paper - avoid copying light data ++ // Paper start - less branching as we know we are using cache and updating ++ public final DataLayer getUpdatingOptimized(final long i) { // Paper - final ++ final DataLayer[] cache = this.cache; ++ if (cache[0].lightCacheKey == i) return cache[0]; ++ if (cache[1].lightCacheKey == i) return cache[1]; + ++ final DataLayer nibblearray = this.lookup.apply(i); // Paper - avoid copying light data + if (nibblearray == null) { + return null; + } else { +- if (this.cacheEnabled) { +- for (int k = 1; k > 0; --k) { +- this.lastSectionKeys[k] = this.lastSectionKeys[k - 1]; +- this.lastSections[k] = this.lastSections[k - 1]; +- } +- +- this.lastSectionKeys[0] = chunkPos; +- this.lastSections[0] = nibblearray; +- } +- ++ cache[1] = cache[0]; ++ cache[0] = nibblearray; + return nibblearray; + } + } ++ // Paper end ++ ++ @Nullable ++ public final DataLayer getLayer(final long chunkPos) { // Paper - final ++ // Paper start - optimize visible case or missed updating cases ++ if (this.cacheEnabled) { ++ // short circuit to optimized ++ return getUpdatingOptimized(chunkPos); ++ } ++ ++ return this.lookup.apply(chunkPos); ++ // Paper end ++ } + + @Nullable + public DataLayer removeLayer(long chunkPos) { +@@ -82,13 +91,14 @@ public abstract class DataLayerStorageMap> { + + public void setLayer(long pos, DataLayer data) { + if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data ++ data.lightCacheKey = pos; // Paper + this.data.queueUpdate(pos, data); // Paper - avoid copying light data + } + + public void clearCache() { + for (int i = 0; i < 2; ++i) { +- this.lastSectionKeys[i] = Long.MAX_VALUE; +- this.lastSections[i] = null; ++ // this.b[i] = Long.MAX_VALUE; // Paper - Unused ++ this.lastSections[i] = DataLayer.EMPTY_NIBBLE_ARRAY; // Paper + } + } + +diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightEngine.java +index 53f38fa95f4ffad12c73d94ab1d7ecf7ee78af09..088ea8a14f1bb264b59fcec626b1a28d7f6d7c47 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightEngine.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightEngine.java +@@ -10,6 +10,7 @@ import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.DataLayer; + import net.minecraft.world.level.chunk.LightChunkGetter; + import net.minecraft.world.phys.shapes.Shapes; +@@ -23,10 +24,37 @@ public abstract class LayerLightEngine, S exten + protected final LightLayer layer; + protected final S storage; + private boolean runningLightUpdates; +- protected final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); ++ protected final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); protected final BlockPos.MutableBlockPos pos = pos; // Paper + private final long[] lastChunkPos = new long[2]; +- private final BlockGetter[] lastChunk = new BlockGetter[2]; ++ private final ChunkAccess[] h = new ChunkAccess[2]; // Paper + ++ // Paper start - see fully commented out method below (look for Bedrock) ++ // optimized method with less branching for when scenarios arent needed. ++ // avoid using mutable version if can ++ protected final BlockState getBlockOptimized(int x, int y, int z, MutableInt mutableint) { ++ ChunkAccess iblockaccess = this.a(x >> 4, z >> 4); ++ ++ if (iblockaccess == null) { ++ mutableint.setValue(16); ++ return Blocks.BEDROCK.defaultBlockState(); ++ } else { ++ this.pos.setValues(x, y, z); ++ BlockState iblockdata = iblockaccess.getType(x, y, z); ++ mutableint.setValue(iblockdata.getLightBlock(this.chunkSource.getLevel(), this.pos)); ++ return iblockdata.canOcclude() && iblockdata.useShapeForLightOcclusion() ? iblockdata : Blocks.AIR.defaultBlockState(); ++ } ++ } ++ protected final BlockState getBlockOptimized(int x, int y, int z) { ++ ChunkAccess iblockaccess = this.a(x >> 4, z >> 4); ++ ++ if (iblockaccess == null) { ++ return Blocks.BEDROCK.defaultBlockState(); ++ } else { ++ BlockState iblockdata = iblockaccess.getType(x, y, z); ++ return iblockdata.canOcclude() && iblockdata.useShapeForLightOcclusion() ? iblockdata : Blocks.AIR.defaultBlockState(); ++ } ++ } ++ // Paper end + public LayerLightEngine(LightChunkGetter chunkProvider, LightLayer type, S lightStorage) { + super(16, 256, 8192); + this.chunkSource = chunkProvider; +@@ -45,63 +73,65 @@ public abstract class LayerLightEngine, S exten + } + + @Nullable +- private BlockGetter getChunk(int chunkX, int chunkZ) { +- long k = ChunkPos.asLong(chunkX, chunkZ); ++ private ChunkAccess a(int i, int j) { // Paper ++ long k = ChunkPos.asLong(i, j); + + for (int l = 0; l < 2; ++l) { + if (k == this.lastChunkPos[l]) { +- return this.lastChunk[l]; ++ return this.h[l]; + } + } + +- BlockGetter iblockaccess = this.chunkSource.getChunkForLighting(chunkX, chunkZ); ++ ChunkAccess iblockaccess = (ChunkAccess) this.chunkSource.getChunkForLighting(i, j); // Paper + + for (int i1 = 1; i1 > 0; --i1) { + this.lastChunkPos[i1] = this.lastChunkPos[i1 - 1]; +- this.lastChunk[i1] = this.lastChunk[i1 - 1]; ++ this.h[i1] = this.h[i1 - 1]; + } + + this.lastChunkPos[0] = k; +- this.lastChunk[0] = iblockaccess; ++ this.h[0] = iblockaccess; + return iblockaccess; + } + + private void clearCache() { + Arrays.fill(this.lastChunkPos, ChunkPos.INVALID_CHUNK_POS); +- Arrays.fill(this.lastChunk, (Object) null); ++ Arrays.fill(this.h, (Object) null); + } + +- protected BlockState getStateAndOpacity(long pos, @Nullable MutableInt mutableint) { +- if (pos == Long.MAX_VALUE) { +- if (mutableint != null) { +- mutableint.setValue(0); +- } +- +- return Blocks.AIR.defaultBlockState(); +- } else { +- int j = SectionPos.blockToSectionCoord(BlockPos.getX(pos)); +- int k = SectionPos.blockToSectionCoord(BlockPos.getZ(pos)); +- BlockGetter iblockaccess = this.getChunk(j, k); +- +- if (iblockaccess == null) { +- if (mutableint != null) { +- mutableint.setValue(16); +- } +- +- return Blocks.BEDROCK.defaultBlockState(); +- } else { +- this.pos.set(pos); +- BlockState iblockdata = iblockaccess.getBlockState(this.pos); +- boolean flag = iblockdata.canOcclude() && iblockdata.useShapeForLightOcclusion(); +- +- if (mutableint != null) { +- mutableint.setValue(iblockdata.getLightBlock(this.chunkSource.getLevel(), (BlockPos) this.pos)); +- } +- +- return flag ? iblockdata : Blocks.AIR.defaultBlockState(); +- } +- } +- } ++ // Paper start - comment out, see getBlockOptimized ++// protected IBlockData a(long i, @Nullable MutableInt mutableint) { ++// if (i == Long.MAX_VALUE) { ++// if (mutableint != null) { ++// mutableint.setValue(0); ++// } ++// ++// return Blocks.AIR.getBlockData(); ++// } else { ++// int j = SectionPosition.a(BlockPosition.b(i)); ++// int k = SectionPosition.a(BlockPosition.d(i)); ++// IBlockAccess iblockaccess = this.a(j, k); ++// ++// if (iblockaccess == null) { ++// if (mutableint != null) { ++// mutableint.setValue(16); ++// } ++// ++// return Blocks.BEDROCK.getBlockData(); ++// } else { ++// this.d.g(i); ++// IBlockData iblockdata = iblockaccess.getType(this.d); ++// boolean flag = iblockdata.l() && iblockdata.e(); ++// ++// if (mutableint != null) { ++// mutableint.setValue(iblockdata.b(this.a.getWorld(), (BlockPosition) this.d)); ++// } ++// ++// return flag ? iblockdata : Blocks.AIR.getBlockData(); ++// } ++// } ++// } ++ // Paper end + + protected VoxelShape getShape(BlockState world, long pos, Direction facing) { + return world.canOcclude() ? world.getFaceOcclusionShape(this.chunkSource.getLevel(), this.pos.set(pos), facing) : Shapes.empty(); +@@ -136,8 +166,9 @@ public abstract class LayerLightEngine, S exten + return id == Long.MAX_VALUE ? 0 : 15 - this.storage.getStoredLevel(id); + } + ++ protected int getNibbleLightInverse(DataLayer nibblearray, int x, int y, int z) { return 15 - nibblearray.get(x & 15, y & 15, z & 15); } // Paper - x/y/z version of below + protected int getLevel(DataLayer section, long blockPos) { +- return 15 - section.get(SectionPos.sectionRelative(BlockPos.getX(blockPos)), SectionPos.sectionRelative(BlockPos.getY(blockPos)), SectionPos.sectionRelative(BlockPos.getZ(blockPos))); ++ return 15 - section.get((int) (blockPos >> 38) & 15, (int) ((blockPos << 52) >> 52) & 15, (int) ((blockPos << 26) >> 38) & 15); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +index 5757bcfded35f112d52a7c81586850ba50e0d8dd..17a6610b352af5d3e2cbcdf9b4d9b0d4d356b5cf 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +@@ -27,9 +27,9 @@ public abstract class LayerLightSectionStorage> + protected final LongSet toMarkNoData = new LongOpenHashSet(); + protected final LongSet toMarkData = new LongOpenHashSet(); + protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change +- protected final M updatingSectionData; // Paper - diff on change, should be "updating" ++ protected final M updatingSectionData; protected final M updating; // Paper - diff on change, should be "updating" + protected final LongSet changedSections = new LongOpenHashSet(); +- protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet(); ++ protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet(); LongSet dirty = sectionsAffectedByLightUpdates; // Paper - OBFHELPER + protected final Long2ObjectMap queuedSections = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); + private final LongSet untrustedSections = new LongOpenHashSet(); + private final LongSet columnsToRetainQueuedDataFor = new LongOpenHashSet(); +@@ -37,33 +37,33 @@ public abstract class LayerLightSectionStorage> + protected volatile boolean hasToRemove; + + protected LayerLightSectionStorage(LightLayer lightType, LightChunkGetter chunkProvider, M lightData) { +- super(3, 16, 256); ++ super(3, 256, 256); // Paper - bump expected size of level sets to improve collisions and reduce rehashing (seen a lot of it) + this.layer = lightType; + this.chunkSource = chunkProvider; +- this.updatingSectionData = lightData; ++ this.updatingSectionData = lightData; updating = lightData; // Paper + this.e_visible = lightData.copy(); // Paper - avoid copying light data + this.e_visible.disableCache(); // Paper - avoid copying light data + } + +- protected boolean storingLightForSection(long sectionPos) { +- return this.getDataLayer(sectionPos, true) != null; ++ protected final boolean storingLightForSection(long sectionPos) { // Paper - final to help inlining ++ return this.updating.getUpdatingOptimized(sectionPos) != null; // Paper - inline to avoid branching + } + + @Nullable + protected DataLayer getDataLayer(long sectionPos, boolean cached) { + // Paper start - avoid copying light data + if (cached) { +- return this.getDataLayer(this.updatingSectionData, sectionPos); ++ return this.updating.getUpdatingOptimized(sectionPos); + } else { + synchronized (this.visibleUpdateLock) { +- return this.getDataLayer(this.e_visible, sectionPos); ++ return this.e_visible.lookup.apply(sectionPos); + } + } + // Paper end - avoid copying light data + } + + @Nullable +- protected DataLayer getDataLayer(M storage, long sectionPos) { ++ protected final DataLayer getDataLayer(M storage, long sectionPos) { // Paper + return storage.getLayer(sectionPos); + } + +@@ -77,27 +77,57 @@ public abstract class LayerLightSectionStorage> + protected abstract int getLightValue(long blockPos); + + protected int getStoredLevel(long blockPos) { +- long j = SectionPos.blockToSection(blockPos); +- DataLayer nibblearray = this.getDataLayer(j, true); ++ // Paper start - reuse and inline math, use Optimized Updating path ++ final int x = (int) (blockPos >> 38); ++ final int y = (int) ((blockPos << 52) >> 52); ++ final int z = (int) ((blockPos << 26) >> 38); ++ long j = SectionPos.blockPosAsSectionLong(x, y, z); ++ DataLayer nibblearray = this.updating.getUpdatingOptimized(j); ++ // BUG: Sometimes returns null and crashes, try to recover, but to prevent crash just return no light. ++ if (nibblearray == null) { ++ nibblearray = this.e_visible.lookup.apply(j); ++ } ++ if (nibblearray == null) { ++ System.err.println("Null nibble, preventing crash " + BlockPos.of(blockPos)); ++ return 0; ++ } + +- return nibblearray.get(SectionPos.sectionRelative(BlockPos.getX(blockPos)), SectionPos.sectionRelative(BlockPos.getY(blockPos)), SectionPos.sectionRelative(BlockPos.getZ(blockPos))); ++ return nibblearray.get(x & 15, y & 15, z & 15); // Paper - inline operations ++ // Paper end + } + + protected void setStoredLevel(long blockPos, int value) { +- long k = SectionPos.blockToSection(blockPos); ++ // Paper start - cache part of the math done in loop below ++ int x = (int) (blockPos >> 38); ++ int y = (int) ((blockPos << 52) >> 52); ++ int z = (int) ((blockPos << 26) >> 38); ++ long k = SectionPos.blockPosAsSectionLong(x, y, z); ++ // Paper end + + if (this.changedSections.add(k)) { + this.updatingSectionData.copyDataLayer(k); + } + + DataLayer nibblearray = this.getDataLayer(k, true); +- +- nibblearray.set(SectionPos.sectionRelative(BlockPos.getX(blockPos)), SectionPos.sectionRelative(BlockPos.getY(blockPos)), SectionPos.sectionRelative(BlockPos.getZ(blockPos)), value); +- +- for (int l = -1; l <= 1; ++l) { +- for (int i1 = -1; i1 <= 1; ++i1) { +- for (int j1 = -1; j1 <= 1; ++j1) { +- this.sectionsAffectedByLightUpdates.add(SectionPos.blockToSection(BlockPos.offset(blockPos, i1, j1, l))); ++ nibblearray.set(x & 15, y & 15, z & 15, value); // Paper - use already calculated x/y/z ++ ++ // Paper start - credit to JellySquid for a major optimization here: ++ /* ++ * An extremely important optimization is made here in regards to adding items to the pending notification set. The ++ * original implementation attempts to add the coordinate of every chunk which contains a neighboring block position ++ * even though a huge number of loop iterations will simply map to block positions within the same updating chunk. ++ * ++ * Our implementation here avoids this by pre-calculating the min/max chunk coordinates so we can iterate over only ++ * the relevant chunk positions once. This reduces what would always be 27 iterations to just 1-8 iterations. ++ * ++ * @reason Use faster implementation ++ * @author JellySquid ++ */ ++ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { ++ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { ++ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { ++ this.dirty.add(SectionPos.asLong(x2, y2, z2)); ++ // Paper end + } + } + } +@@ -129,17 +159,23 @@ public abstract class LayerLightSectionStorage> + } + + if (k >= 2 && level != 2) { +- if (this.toRemove.contains(id)) { +- this.toRemove.remove(id); +- } else { ++ if (!this.toRemove.remove(id)) { // Paper - remove useless contains - credit to JellySquid ++ //this.p.remove(i); // Paper ++ //} else { // Paper + this.updatingSectionData.setLayer(id, this.createDataLayer(id)); + this.changedSections.add(id); + this.onNodeAdded(id); + +- for (int l = -1; l <= 1; ++l) { +- for (int i1 = -1; i1 <= 1; ++i1) { +- for (int j1 = -1; j1 <= 1; ++j1) { +- this.sectionsAffectedByLightUpdates.add(SectionPos.blockToSection(BlockPos.offset(id, i1, j1, l))); ++ // Paper start - reuse x/y/z and only notify valid chunks - Credit to JellySquid (See above method for notes) ++ int x = (int) (id >> 38); ++ int y = (int) ((id << 52) >> 52); ++ int z = (int) ((id << 26) >> 38); ++ ++ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { ++ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { ++ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { ++ this.dirty.add(SectionPos.asLong(x2, y2, z2)); ++ // Paper end + } + } + } +@@ -165,9 +201,9 @@ public abstract class LayerLightSectionStorage> + return SectionPos.blockToSection(j) == sectionPos; + }); + } else { +- int j = SectionPos.sectionToBlockCoord(SectionPos.x(sectionPos)); +- int k = SectionPos.sectionToBlockCoord(SectionPos.y(sectionPos)); +- int l = SectionPos.sectionToBlockCoord(SectionPos.z(sectionPos)); ++ int j = (int) (sectionPos >> 42) << 4; // Paper - inline ++ int k = (int) (sectionPos << 44 >> 44) << 4; // Paper - inline ++ int l = (int) (sectionPos << 22 >> 42) << 4; // Paper - inline + + for (int i1 = 0; i1 < 16; ++i1) { + for (int j1 = 0; j1 < 16; ++j1) { +@@ -194,7 +230,7 @@ public abstract class LayerLightSectionStorage> + DataLayer nibblearray; + + while (longiterator.hasNext()) { +- i = (Long) longiterator.next(); ++ i = longiterator.nextLong(); // Paper + this.clearQueuedSectionBlocks(lightProvider, i); + DataLayer nibblearray1 = (DataLayer) this.queuedSections.remove(i); + +@@ -212,7 +248,7 @@ public abstract class LayerLightSectionStorage> + longiterator = this.toRemove.iterator(); + + while (longiterator.hasNext()) { +- i = (Long) longiterator.next(); ++ i = longiterator.nextLong(); // Paper + this.onNodeRemoved(i); + } + +@@ -223,12 +259,13 @@ public abstract class LayerLightSectionStorage> + Entry entry; + long j; + ++ DataLayer test = null; // Paper + while (objectiterator.hasNext()) { + entry = (Entry) objectiterator.next(); + j = entry.getLongKey(); +- if (this.storingLightForSection(j)) { ++ if ((test = this.updating.getUpdatingOptimized(j)) != null) { // Paper - dont look up nibble twice + nibblearray = (DataLayer) entry.getValue(); +- if (this.updatingSectionData.getLayer(j) != nibblearray) { ++ if (test != nibblearray) { // Paper + this.clearQueuedSectionBlocks(lightProvider, j); + this.updatingSectionData.setLayer(j, nibblearray); + this.changedSections.add(j); +@@ -241,14 +278,14 @@ public abstract class LayerLightSectionStorage> + longiterator = this.queuedSections.keySet().iterator(); + + while (longiterator.hasNext()) { +- i = (Long) longiterator.next(); ++ i = longiterator.nextLong(); // Paper + this.checkEdgesForSection(lightProvider, i); + } + } else { + longiterator = this.untrustedSections.iterator(); + + while (longiterator.hasNext()) { +- i = (Long) longiterator.next(); ++ i = longiterator.nextLong(); // Paper + this.checkEdgesForSection(lightProvider, i); + } + } +@@ -269,15 +306,20 @@ public abstract class LayerLightSectionStorage> + + private void checkEdgesForSection(LayerLightEngine lightProvider, long sectionPos) { + if (this.storingLightForSection(sectionPos)) { +- int j = SectionPos.sectionToBlockCoord(SectionPos.x(sectionPos)); +- int k = SectionPos.sectionToBlockCoord(SectionPos.y(sectionPos)); +- int l = SectionPos.sectionToBlockCoord(SectionPos.z(sectionPos)); ++ // Paper start ++ int secX = (int) (sectionPos >> 42); ++ int secY = (int) (sectionPos << 44 >> 44); ++ int secZ = (int) (sectionPos << 22 >> 42); ++ int j = secX << 4; // baseX ++ int k = secY << 4; // baseY ++ int l = secZ << 4; // baseZ ++ // Paper end + Direction[] aenumdirection = LayerLightSectionStorage.DIRECTIONS; + int i1 = aenumdirection.length; + + for (int j1 = 0; j1 < i1; ++j1) { + Direction enumdirection = aenumdirection[j1]; +- long k1 = SectionPos.offset(sectionPos, enumdirection); ++ long k1 = SectionPos.getAdjacentFromSectionPos(secX, secY, secZ, enumdirection); // Paper - avoid extra unpacking + + if (!this.queuedSections.containsKey(k1) && this.storingLightForSection(k1)) { + for (int l1 = 0; l1 < 16; ++l1) { +diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java +index ff1fbc46776b26ca56c3293e40ed55028230ec46..da4003aebc8d5ffce695071af9a27139568d773f 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java +@@ -4,6 +4,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.SectionPos; + import net.minecraft.world.level.LightLayer; ++import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.chunk.DataLayer; + import net.minecraft.world.level.chunk.LightChunkGetter; +@@ -38,21 +39,25 @@ public final class SkyLightEngine extends LayerLightEngine= 15) { ++ // Paper start - use x/y/z and optimized block lookup ++ int jx = (int) (targetId >> 38); ++ int jy = (int) ((targetId << 52) >> 52); ++ int jz = (int) ((targetId << 26) >> 38); ++ BlockState iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); ++ int blockedLight = mutableint.getValue(); ++ if (blockedLight >= 15) { ++ // Paper end + return 15; + } else { +- int l = BlockPos.getX(sourceId); +- int i1 = BlockPos.getY(sourceId); +- int j1 = BlockPos.getZ(sourceId); +- int k1 = BlockPos.getX(targetId); +- int l1 = BlockPos.getY(targetId); +- int i2 = BlockPos.getZ(targetId); +- boolean flag = l == k1 && j1 == i2; +- int j2 = Integer.signum(k1 - l); +- int k2 = Integer.signum(l1 - i1); +- int l2 = Integer.signum(i2 - j1); ++ // Paper start - inline math ++ int ix = (int) (sourceId >> 38); ++ int iy = (int) ((sourceId << 52) >> 52); ++ int iz = (int) ((sourceId << 26) >> 38); ++ boolean flag = ix == jx && iz == jz; ++ int j2 = Integer.signum(jx - ix); ++ int k2 = Integer.signum(jy - iy); ++ int l2 = Integer.signum(jz - iz); ++ // Paper end + Direction enumdirection; + + if (sourceId == Long.MAX_VALUE) { +@@ -61,7 +66,7 @@ public final class SkyLightEngine extends LayerLightEngine l1; ++ boolean flag1 = sourceId == Long.MAX_VALUE || flag && iy > jy; // Paper rename vars to iy > jy + +- return flag1 && level == 0 && mutableint.getValue() == 0 ? 0 : level + Math.max(1, mutableint.getValue()); ++ return flag1 && level == 0 && blockedLight == 0 ? 0 : level + Math.max(1, blockedLight); // Paper + } + } + } +@@ -101,10 +106,14 @@ public final class SkyLightEngine extends LayerLightEngine> 38); ++ int baseY = (int) ((id << 52) >> 52); ++ int baseZ = (int) ((id << 26) >> 38); ++ long k = SectionPos.blockPosAsSectionLong(baseX, baseY, baseZ); ++ int i1 = baseY & 15; ++ int j1 = baseY >> 4; ++ // Paper end + int k1; + + if (i1 != 0) { +@@ -119,15 +128,16 @@ public final class SkyLightEngine extends LayerLightEngine> 38); ++ int baseY = (int) ((id << 52) >> 52); ++ int baseZ = (int) ((id << 26) >> 38); ++ long j1 = SectionPos.blockPosAsSectionLong(baseX, baseY, baseZ); ++ DataLayer nibblearray = this.storage.updating.getUpdatingOptimized(j1); ++ // Paper end + Direction[] aenumdirection = SkyLightEngine.DIRECTIONS; + int k1 = aenumdirection.length; + + for (int l1 = 0; l1 < k1; ++l1) { + Direction enumdirection = aenumdirection[l1]; +- long i2 = BlockPos.offset(id, enumdirection); +- long j2 = SectionPos.blockToSection(i2); ++ // Paper start ++ int newX = baseX + enumdirection.getStepX(); ++ int newY = baseY + enumdirection.getStepY(); ++ int newZ = baseZ + enumdirection.getStepZ(); ++ long i2 = BlockPos.asLong(newX, newY, newZ); ++ long j2 = SectionPos.blockPosAsSectionLong(newX, newY, newZ); ++ // Paper end + DataLayer nibblearray1; + + if (j1 == j2) { + nibblearray1 = nibblearray; + } else { +- nibblearray1 = ((SkyLightSectionStorage) this.storage).getDataLayer(j2, true); ++ nibblearray1 = ((SkyLightSectionStorage) this.storage).updating.getUpdatingOptimized(j2); // Paper + } + + if (nibblearray1 != null) { + if (i2 != excludedId) { +- int k2 = this.computeLevelFromNeighbor(i2, id, this.getLevel(nibblearray1, i2)); ++ int k2 = this.computeLevelFromNeighbor(i2, id, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper + + if (l > k2) { + l = k2; +@@ -215,7 +235,7 @@ public final class SkyLightEngine extends LayerLightEngine> 38); ++ int baseY = (int) ((blockPos << 52) >> 52); ++ int baseZ = (int) ((blockPos << 26) >> 38); ++ long j = SectionPos.blockPosAsSectionLong(baseX, baseY, baseZ); ++ // Paper end + int k = SectionPos.y(j); + synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data + SkyLightSectionStorage.SkyDataLayerStorageMap lightenginestoragesky_a = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.e_visible; // Paper - avoid copying light data - must be after lock acquire +@@ -49,7 +54,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage> 52) & 15, (int) baseZ & 15); // Paper - y changed above + } else { + return 15; + } +@@ -168,7 +173,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage> 42) << 4; // Paper ++ int baseY = (int) (i << 44 >> 44) << 4; // Paper ++ int baseZ = (int) (i << 22 >> 42) << 4; // Paper + j = this.getLevel(i); + if (j != 2 && !this.sectionsToRemoveSourcesFrom.contains(i) && this.sectionsWithSources.add(i)) { + int l; +@@ -203,10 +211,10 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage> 42) << 4; // Paper ++ int baseY = (int) (i << 44 >> 44) << 4; // Paper ++ int baseZ = (int) (i << 22 >> 42) << 4; // Paper + if (this.sectionsWithSources.remove(i) && this.storingLightForSection(i)) { + for (j = 0; j < 16; ++j) { + for (k = 0; k < 16; ++k) { +- long l3 = BlockPos.asLong(SectionPos.sectionToBlockCoord(SectionPos.x(i)) + j, SectionPos.sectionToBlockCoord(SectionPos.y(i)) + 16 - 1, SectionPos.sectionToBlockCoord(SectionPos.z(i)) + k); ++ long l3 = BlockPos.asLong(baseX + j, baseY + 16 - 1, baseZ + k); // Paper + + lightProvider.checkEdge(Long.MAX_VALUE, l3, 15, false); + } diff --git a/patches/server-remapped/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/patches/server-remapped/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch new file mode 100644 index 0000000000..a8c890b13a --- /dev/null +++ b/patches/server-remapped/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 18 Jun 2016 23:22:12 -0400 +Subject: [PATCH] Delay Chunk Unloads based on Player Movement + +When players are moving in the world, doing things such as building or exploring, +they will commonly go back and forth in a small area. This causes a ton of chunk load +and unload activity on the edge chunks of their view distance. + +A simple back and forth movement in 6 blocks could spam a chunk to thrash a +loading and unload cycle over and over again. + +This is very wasteful. This system introduces a delay of inactivity on a chunk +before it actually unloads, which will be handled by the ticket expiry process. + +This allows servers with smaller worlds who do less long distance exploring to stop +wasting cpu cycles on saving/unloading/reloading chunks repeatedly. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6463d3e4837d032a35654a035f42b8a805e0e286..1655bca0502e7b871de4addaa163536d86547a02 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -637,4 +637,13 @@ public class PaperWorldConfig { + private void viewDistance() { + this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); + } ++ ++ public long delayChunkUnloadsBy; ++ private void delayChunkUnloadsBy() { ++ delayChunkUnloadsBy = PaperConfig.getSeconds(getString("delay-chunk-unloads-by", "10s")); ++ if (delayChunkUnloadsBy > 0) { ++ log("Delaying chunk unloads by " + delayChunkUnloadsBy + " seconds"); ++ delayChunkUnloadsBy *= 20; ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index e41f388e8350010a471410436adf15a906f07e97..e0241b9d60cd2b72f8fb774f1ab4753dfd615184 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -185,6 +185,27 @@ public abstract class DistanceManager { + boolean removed = false; // CraftBukkit + if (arraysetsorted.remove(ticket)) { + removed = true; // CraftBukkit ++ // Paper start - delay chunk unloads for player tickets ++ long delayChunkUnloadsBy = chunkMap.level.paperConfig.delayChunkUnloadsBy; ++ if (ticket.getType() == TicketType.PLAYER && delayChunkUnloadsBy > 0) { ++ boolean hasPlayer = false; ++ for (Ticket ticket1 : arraysetsorted) { ++ if (ticket1.getType() == TicketType.PLAYER) { ++ hasPlayer = true; ++ break; ++ } ++ } ++ ChunkHolder playerChunk = chunkMap.getUpdatingChunkIfPresent(i); ++ if (!hasPlayer && playerChunk != null && playerChunk.isFullChunkReady()) { ++ Ticket delayUnload = new Ticket(TicketType.DELAY_UNLOAD, 33, i); ++ delayUnload.delayUnloadBy = delayChunkUnloadsBy; ++ delayUnload.setCurrentTick(this.ticketTickCounter); ++ arraysetsorted.remove(delayUnload); ++ // refresh ticket ++ arraysetsorted.add(delayUnload); ++ } ++ } ++ // Paper end + } + + if (arraysetsorted.isEmpty()) { +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index c0bfe136ccb9ad4fc0f8ccdd703254205213ec8e..f7898bd7806684d2c068898cecbf835d834df461 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -9,11 +9,13 @@ public final class Ticket implements Comparable> { + public final T key; public final T getObjectReason() { return this.key; } // Paper - OBFHELPER + private long createdTick; public final long getCreationTick() { return this.createdTick; } // Paper - OBFHELPER + public int priority = 0; // Paper ++ public long delayUnloadBy; // Paper + + protected Ticket(TicketType type, int level, T argument) { + this.type = type; + this.ticketLevel = level; + this.key = argument; ++ this.delayUnloadBy = type.timeout; // Paper + } + + public int compareTo(Ticket ticket) { +@@ -63,7 +65,7 @@ public final class Ticket implements Comparable> { + } + + protected boolean timedOut(long currentTick) { +- long j = this.type.timeout(); ++ long j = delayUnloadBy; // Paper + + return j != 0L && currentTick - this.createdTick > j; + } +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index 2444f6f676db543509b14e8c882491dc3f41b264..531ebf1bafec2b295af9f6dfec8f4b6466688287 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -30,6 +30,7 @@ public class TicketType { + public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper + public static final TicketType PRIORITY = create("priority", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper + public static final TicketType URGENT = create("urgent", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper ++ public static final TicketType DELAY_UNLOAD = create("delay_unload", Long::compareTo, 300); // Paper + + public static TicketType create(String name, Comparator comparator) { + return new TicketType<>(name, comparator, 0L); diff --git a/patches/server-remapped/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/patches/server-remapped/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch new file mode 100644 index 0000000000..2d4cc183be --- /dev/null +++ b/patches/server-remapped/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch @@ -0,0 +1,129 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 9 Jun 2020 03:33:03 -0400 +Subject: [PATCH] Add Plugin Tickets to API Chunk Methods + +Like previous versions, plugins loading chunks kept them loaded until +they garbage collected to avoid constant spamming of chunk loads + +This adds tickets to a few more places so that they can be unloaded. + +Additionally, this drops their ticket level to BORDER so they wont be ticking +so they will just sit inactive instead. + +Using .loadChunk to keep a chunk ticking was a horrible idea for upstream +when we have TWO methods that are able to do that already in the API. + +Also reduce their collection count down to a maximum of 1 second. Barely +anyone knows what chunk-gc is in bukkit.yml as its less relevant now, and +since this wasn't spigot behavior, this is safe to mostly ignore (unless someone +wants it to collect even faster, they can restore that setting back to 1 instead of 20+) + +Not adding it to .getType() though to keep behavior consistent with vanilla for performance reasons. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 92f1a6d32a96fee682342e86c3ffd3c65292150b..2ec41cb87cec97780f1fa8abfbb756fca4dba1bf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -342,7 +342,7 @@ public final class CraftServer implements Server { + ambientSpawn = configuration.getInt("spawn-limits.ambient"); + console.autosavePeriod = configuration.getInt("ticks-per.autosave"); + warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); +- TicketType.PLUGIN.timeout = configuration.getInt("chunk-gc.period-in-ticks"); ++ TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + minimumAPI = configuration.getString("settings.minimum-api"); + loadIcon(); + } +@@ -832,7 +832,7 @@ public final class CraftServer implements Server { + waterAmbientSpawn = configuration.getInt("spawn-limits.water-ambient"); + ambientSpawn = configuration.getInt("spawn-limits.ambient"); + warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); +- TicketType.PLUGIN.timeout = configuration.getInt("chunk-gc.period-in-ticks"); ++ TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + minimumAPI = configuration.getString("settings.minimum-api"); + printSaveWarning = false; + console.autosavePeriod = configuration.getInt("ticks-per.autosave"); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 7261e22a71d219efe0949a08c5d3f10747759469..4436b3d23dc8f33925da1ec539ea16307e0785b9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.ClientboundCustomSoundPacket; + import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; + import net.minecraft.network.protocol.game.ClientboundSetTimePacket; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ChunkMap; + import net.minecraft.server.level.DistanceManager; +@@ -389,8 +390,21 @@ public class CraftWorld implements World { + + @Override + public Chunk getChunkAt(int x, int z) { +- return this.world.getChunkSource().getChunk(x, z, true).bukkitChunk; ++ // Paper start - add ticket to hold chunk for a little while longer if plugin accesses it ++ net.minecraft.world.level.chunk.LevelChunk chunk = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); ++ if (chunk == null) { ++ addTicket(x, z); ++ chunk = this.world.getChunkSource().getChunk(x, z, true); ++ } ++ return chunk.bukkitChunk; ++ // Paper end ++ } ++ ++ // Paper start ++ private void addTicket(int x, int z) { ++ MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE)); // Paper + } ++ // Paper end + + @Override + public Chunk getChunkAt(Block block) { +@@ -465,7 +479,7 @@ public class CraftWorld implements World { + public boolean unloadChunkRequest(int x, int z) { + org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot + if (isChunkLoaded(x, z)) { +- world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); ++ world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE); // Paper + } + + return true; +@@ -542,9 +556,12 @@ public class CraftWorld implements World { + org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot + // Paper start - Optimize this method + ChunkPos chunkPos = new ChunkPos(x, z); ++ ChunkAccess immediate = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); // Paper ++ if (immediate != null) return true; // Paper + + if (!generate) { +- ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z); ++ ++ //IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); // Paper + if (immediate == null) { + immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); + } +@@ -552,7 +569,7 @@ public class CraftWorld implements World { + if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) { + return false; // not full status + } +- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper + world.getChunk(x, z); // make sure we're at ticket level 32 or lower + return true; + } +@@ -579,7 +596,7 @@ public class CraftWorld implements World { + // we do this so we do not re-read the chunk data on disk + } + +- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper + world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); + return true; + // Paper end +@@ -2529,6 +2546,7 @@ public class CraftWorld implements World { + } + return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { + net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); ++ if (chunk != null) addTicket(x, z); // Paper + return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + }, net.minecraft.server.MinecraftServer.getServer()); + } diff --git a/patches/server-remapped/0494-Fix-missing-chunks-due-to-integer-overflow.patch b/patches/server-remapped/0494-Fix-missing-chunks-due-to-integer-overflow.patch new file mode 100644 index 0000000000..f86c4c1c6b --- /dev/null +++ b/patches/server-remapped/0494-Fix-missing-chunks-due-to-integer-overflow.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: David Slovikosky +Date: Tue, 9 Jun 2020 00:10:03 -0700 +Subject: [PATCH] Fix missing chunks due to integer overflow + +This patch fixes a bug in the WorldChunkManagerTheEnd class where the distance +from 0,0 squared overflows the maximum size of an integer. The overflow leads +to hard chunk borders around 370,000 blocks from 0,0. After this cutoff there +is a few hundred thousand block gap before end land resuming to generate at +530,000 blocks from spawn. This is due to the integer flipping back and forth. + +The fix for the issue is quite simple, casting chunk coordinates to longs +allows the distance calculation to avoid overflow and work as intended. + +diff --git a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +index af006c2e45e0a14367a0bc850c319024c6b82024..063369d3a64b4afc9cc6e1d20360900595e1a05f 100644 +--- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java ++++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +@@ -75,7 +75,9 @@ public class TheEndBiomeSource extends BiomeSource { + int l = j / 2; + int i1 = i % 2; + int j1 = j % 2; +- float f = 100.0F - Mth.sqrt((float) (i * i + j * j)) * 8.0F; ++ // Paper start - cast ints to long to avoid integer overflow ++ float f = 100.0F - Mth.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; ++ // Paper end + + f = Mth.clamp(f, -100.0F, 80.0F); + diff --git a/patches/server-remapped/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/patches/server-remapped/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch new file mode 100644 index 0000000000..423af0ebf9 --- /dev/null +++ b/patches/server-remapped/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ossi +Date: Fri, 12 Jun 2020 01:38:06 +0300 +Subject: [PATCH] Fix CraftScheduler#runTaskTimerAsynchronously(Plugin, + Consumer, long, long) scheduling a non-repeating task instead of + a repeating one. + + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index ca90237a53c9a026919d28adaedf483ca3c7c2a8..13e461ffb2ee2e7d0440c0f60809ea99629b843c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -184,7 +184,7 @@ public class CraftScheduler implements BukkitScheduler { + + @Override + public void runTaskTimerAsynchronously(Plugin plugin, Consumer task, long delay, long period) throws IllegalArgumentException { +- runTaskTimerAsynchronously(plugin, (Object) task, delay, CraftTask.NO_REPEATING); ++ runTaskTimerAsynchronously(plugin, (Object) task, delay, period); + } + + @Override diff --git a/patches/server-remapped/0496-Fix-piston-physics-inconsistency-MC-188840.patch b/patches/server-remapped/0496-Fix-piston-physics-inconsistency-MC-188840.patch new file mode 100644 index 0000000000..1d54c7bad6 --- /dev/null +++ b/patches/server-remapped/0496-Fix-piston-physics-inconsistency-MC-188840.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Thu, 11 Jun 2020 17:29:42 -0700 +Subject: [PATCH] Fix piston physics inconsistency - MC-188840 + +Pistons invoke physics when they move blocks. The physics can cause +tnt blocks to ignite. However, pistons (when storing the blocks they "moved") +don't actually go back to the world state sometimes to check if something +like that happened. As a result they end up moving the tnt like it was +never ignited. This resulted in the ability to create machines +that can duplicate tnt, called "world eaters". +This patch makes the piston logic retrieve the block state from the world +prevent this from occuring. + +This patch also sets the moved pos to air immediately after creating +the moving piston TE. This prevents the block from being updated from +other physics calls by the piston. + +Tested against the following tnt duper design: +https://www.youtube.com/watch?v=mS7xxNGhjxs + +This patch also affects every type of machine that utilises +this mechanic. For example, dead coral is removed by a physics +update when being moved while it is attached to slimeblocks. + +Standard piston machines that don't destroy or modify the +blocks they move by physics updates should be entirely +unaffected. + +This patch fixes https://bugs.mojang.com/browse/MC-188840 + +This patch also fixes rail duping and carpet duping. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 7f140333c2e62012fa572c1a061d84432426997f..b67ba8f75e4a3358d7c2462918b85b0bf9b5a922 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -434,4 +434,10 @@ public class PaperConfig { + consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); + } + ++ public static boolean allowPistonDuplication; ++ private static void allowPistonDuplication() { ++ config.set("settings.unsupported-settings.allow-piston-duplication-readme", "This setting controls if player should be able to use TNT duplication, but this also allows duplicating carpet, rails and potentially other items"); ++ allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); ++ set("settings.unsupported-settings.allow-tnt-duplication", null); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +index 40a18302dd682e5ade4ec77ac7f316b6c0f8c112..44876557515eaa6bbe33344b3d3ba03aee58409f 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -398,12 +398,24 @@ public class PistonBaseBlock extends DirectionalBlock { + } + + for (k = list.size() - 1; k >= 0; --k) { +- blockposition3 = (BlockPos) list.get(k); +- iblockdata1 = world.getBlockState(blockposition3); ++ // Paper start - fix a variety of piston desync dupes ++ boolean allowDesync = com.destroystokyo.paper.PaperConfig.allowPistonDuplication; ++ BlockPos oldPos = blockposition3 = (BlockPos) list.get(k); ++ iblockdata1 = allowDesync ? world.getBlockState(oldPos) : null; ++ // Paper end - fix a variety of piston desync dupes + blockposition3 = blockposition3.relative(enumdirection1); + map.remove(blockposition3); + world.setBlock(blockposition3, (BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, dir), 68); +- world.setBlockEntity(blockposition3, MovingPistonBlock.newMovingBlockEntity((BlockState) list1.get(k), dir, retract, false)); ++ // Paper start - fix a variety of piston desync dupes ++ if (!allowDesync) { ++ iblockdata1 = world.getBlockState(oldPos); ++ map.replace(oldPos, iblockdata1); ++ } ++ world.setBlockEntity(blockposition3, MovingPistonBlock.newMovingBlockEntity(allowDesync ? list1.get(k) : iblockdata1, dir, retract, false)); ++ if (!allowDesync) { ++ world.setBlock(oldPos, Blocks.AIR.defaultBlockState(), 2 | 4 | 16 | 1024); // set air to prevent later physics updates from seeing this block ++ } ++ // Paper end - fix a variety of piston desync dupes + aiblockdata[j++] = iblockdata1; + } + +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +index 73888713746e7ddd72ba9ac9d33d8e616eb3bd25..001e90da8b09e16b6df4849a5bac4f4821000c94 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +@@ -279,7 +279,7 @@ public class PistonMovingBlockEntity extends BlockEntity implements TickableBloc + BlockState iblockdata = Block.updateFromNeighbourShapes(this.movedState, (LevelAccessor) this.level, this.worldPosition); + + if (iblockdata.isAir()) { +- this.level.setBlock(this.worldPosition, this.movedState, 84); ++ this.level.setBlock(this.worldPosition, this.movedState, com.destroystokyo.paper.PaperConfig.allowPistonDuplication ? 84 : (84 | 2)); // Paper - force notify (flag 2), it's possible the set type by the piston block (which doesn't notify) set this block to air + Block.updateOrDestroy(this.movedState, iblockdata, this.level, this.worldPosition, 3); + } else { + if (iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) iblockdata.getValue(BlockStateProperties.WATERLOGGED)) { diff --git a/patches/server-remapped/0497-Fix-sand-duping.patch b/patches/server-remapped/0497-Fix-sand-duping.patch new file mode 100644 index 0000000000..d06a661655 --- /dev/null +++ b/patches/server-remapped/0497-Fix-sand-duping.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 12 Jun 2020 13:33:19 -0700 +Subject: [PATCH] Fix sand duping + +If the falling block dies during teleportation (entity#move), then we need +to detect that by placing a check after the move. + +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index ff8f7e4569a889ead1512b7c9908f9c5cad9eed5..2ba81e7179c7f9e2e1add1ad6bd6b96ee12c5da1 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -101,6 +101,11 @@ public class FallingBlockEntity extends Entity { + + @Override + public void tick() { ++ // Paper start - fix sand duping ++ if (this.removed) { ++ return; ++ } ++ // Paper end - fix sand duping + if (this.blockState.isAir()) { + this.remove(); + } else { +@@ -123,6 +128,12 @@ public class FallingBlockEntity extends Entity { + + this.move(MoverType.SELF, this.getDeltaMovement()); + ++ // Paper start - fix sand duping ++ if (this.removed) { ++ return; ++ } ++ // Paper end - fix sand duping ++ + // Paper start - Configurable EntityFallingBlock height nerf + if (this.level.paperConfig.fallingBlockHeightNerf != 0 && this.getY() > this.level.paperConfig.fallingBlockHeightNerf) { + if (this.dropItem && this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { diff --git a/patches/server-remapped/0498-Prevent-position-desync-in-playerconnection-causing-.patch b/patches/server-remapped/0498-Prevent-position-desync-in-playerconnection-causing-.patch new file mode 100644 index 0000000000..9994f830fa --- /dev/null +++ b/patches/server-remapped/0498-Prevent-position-desync-in-playerconnection-causing-.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 12 Jun 2020 16:51:39 -0700 +Subject: [PATCH] Prevent position desync in playerconnection causing tp + exploit + +Caused the server to revert to the player's overworld coordinates +after teleporting into the end. + +Sidenote: The underlying issue is that the move call can teleport +entities and do other things like kill the entity. In the future, +to fix all exploits derieved from this usually unexpected +behaviour, we need to move all of this dangerous logic outside +of the move call and into an appropriate place in the tick method. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0625bc7ffd07b66b27176fe62ae3061aa7c67df2..fbafb89cc63744d942933546026e272122bd9fba 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1324,6 +1324,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9)); + this.player.setOnGround(packet.isOnGround()); // CraftBukkit - SPIGOT-5810, SPIGOT-5835: reset by this.player.move ++ // Paper start - prevent position desync ++ if (this.awaitingPositionFromClient != null) { ++ return; // ... thanks Mojang for letting move calls teleport across dimensions. ++ } ++ // Paper end - prevent position desync + double d12 = d8; + + d7 = d4 - this.player.getX(); diff --git a/patches/server-remapped/0499-Fix-enderdragon-exp-dupe.patch b/patches/server-remapped/0499-Fix-enderdragon-exp-dupe.patch new file mode 100644 index 0000000000..38690afc49 --- /dev/null +++ b/patches/server-remapped/0499-Fix-enderdragon-exp-dupe.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 12 Jun 2020 22:25:11 -0700 +Subject: [PATCH] Fix enderdragon exp dupe + +Properly track death stage when unloading/loading in the +dragon + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index ec9436005a3a6fdfb4783d1092bb361224eb6414..b224a630f8adb1fa357c838e6b32c784aed0b15b 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -879,6 +879,7 @@ public class EnderDragon extends Mob implements Enemy { + public void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); + tag.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId()); ++ tag.putInt("Paper.DeathTick", this.dragonDeathTime); // Paper + } + + @Override +@@ -887,6 +888,7 @@ public class EnderDragon extends Mob implements Enemy { + if (tag.contains("DragonPhase")) { + this.phaseManager.setPhase(EnderDragonPhase.getById(tag.getInt("DragonPhase"))); + } ++ this.dragonDeathTime = tag.getInt("Paper.DeathTick"); // Paper + + } + diff --git a/patches/server-remapped/0500-Inventory-getHolder-method-without-block-snapshot.patch b/patches/server-remapped/0500-Inventory-getHolder-method-without-block-snapshot.patch new file mode 100644 index 0000000000..d25c9ffc5a --- /dev/null +++ b/patches/server-remapped/0500-Inventory-getHolder-method-without-block-snapshot.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Wed, 10 Jun 2020 23:55:15 +0100 +Subject: [PATCH] Inventory getHolder method without block snapshot + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +index ef2d18d19a86b3701855aa1ac126462e663f8fcd..7ccc085228f373e6eba55d809bed480d43d5c211 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +@@ -10,6 +10,7 @@ import net.minecraft.world.inventory.PlayerEnderChestContainer; + import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; + import net.minecraft.world.level.block.entity.BarrelBlockEntity; + import net.minecraft.world.level.block.entity.BlastFurnaceBlockEntity; ++import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BrewingStandBlockEntity; + import net.minecraft.world.level.block.entity.DispenserBlockEntity; + import net.minecraft.world.level.block.entity.DropperBlockEntity; +@@ -525,6 +526,13 @@ public class CraftInventory implements Inventory { + return inventory.getOwner(); + } + ++ // Paper start - getHolder without snapshot ++ @Override ++ public InventoryHolder getHolder(boolean useSnapshot) { ++ return inventory instanceof BlockEntity ? ((BlockEntity) inventory).getOwner(useSnapshot) : getHolder(); ++ } ++ // Paper end ++ + @Override + public int getMaxStackSize() { + return inventory.getMaxStackSize(); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java +index 3245dfa94410d319e53543c862c990e80ed3c72d..23dcf6e9332bd2b42ebb851497483e41948355d8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java +@@ -64,6 +64,13 @@ public class CraftInventoryDoubleChest extends CraftInventory implements DoubleC + return new DoubleChest(this); + } + ++ // Paper start - getHolder without snapshot ++ @Override ++ public DoubleChest getHolder(boolean useSnapshot) { ++ return getHolder(); ++ } ++ // Paper end ++ + @Override + public Location getLocation() { + return getLeftSide().getLocation().add(getRightSide().getLocation()).multiply(0.5); diff --git a/patches/server-remapped/0501-Expose-Arrow-getItemStack.patch b/patches/server-remapped/0501-Expose-Arrow-getItemStack.patch new file mode 100644 index 0000000000..cafd641bc1 --- /dev/null +++ b/patches/server-remapped/0501-Expose-Arrow-getItemStack.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nesaak <52047222+Nesaak@users.noreply.github.com> +Date: Sat, 23 May 2020 10:31:11 -0400 +Subject: [PATCH] Expose Arrow getItemStack + + +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 3ce431c1fdf1f5bd62b49f26cca188e939e98efa..6225f390b51733217a809910182f58acea1055e2 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -556,6 +556,7 @@ public abstract class AbstractArrow extends Projectile { + } + } + ++ public final ItemStack getOriginalItemStack() { return getPickupItem(); } // Paper - OBFHELPER - exists purely due to overrides all as protected and dont want to change them all + protected abstract ItemStack getPickupItem(); + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +index 5b898118a46007a85254931c7b5bd18d7cda99be..91d32aff07e81608a2f8ecb1301ef3c08533494b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +@@ -102,6 +102,13 @@ public class CraftArrow extends AbstractProjectile implements AbstractArrow { + getHandle().pickup = net.minecraft.world.entity.projectile.AbstractArrow.Pickup.byOrdinal(status.ordinal()); + } + ++ // Paper start ++ @Override ++ public org.bukkit.craftbukkit.inventory.CraftItemStack getItemStack() { ++ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(getHandle().getOriginalItemStack()); ++ } ++ //Paper end ++ + @Override + public void setTicksLived(int value) { + super.setTicksLived(value); diff --git a/patches/server-remapped/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/server-remapped/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch new file mode 100644 index 0000000000..412fc1c8ad --- /dev/null +++ b/patches/server-remapped/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Fri, 5 Jun 2020 18:24:06 -0400 +Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index fbafb89cc63744d942933546026e272122bd9fba..a0b2fc3fe59d97b9282a9451f35542b39df774e7 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2770,9 +2770,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + this.player.resetLastActionTime(); + if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu.isSynched(this.player) && this.player.containerMenu instanceof RecipeBookMenu) { +- this.server.getRecipeManager().byKey(packet.getRecipe()).ifPresent((irecipe) -> { +- ((RecipeBookMenu) this.player.containerMenu).handlePlacement(packet.isShiftDown(), irecipe, this.player); +- }); ++ // Paper start - fire event for clicking recipes in the recipe book ++ com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent event = new com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent( ++ player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(packet.getRecipe()), packet.isShiftDown()); ++ if (event.callEvent()) { ++ this.server.getRecipeManager().byKey(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getRecipe())).ifPresent((irecipe) -> { ++ ((ContainerRecipeBook) this.player.activeContainer).a(event.isMakeAll(), irecipe, this.player); ++ }); ++ } ++ // Paper end + } + } + diff --git a/patches/server-remapped/0503-Hide-sync-chunk-writes-behind-flag.patch b/patches/server-remapped/0503-Hide-sync-chunk-writes-behind-flag.patch new file mode 100644 index 0000000000..43a0839a47 --- /dev/null +++ b/patches/server-remapped/0503-Hide-sync-chunk-writes-behind-flag.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 26 Jun 2020 22:35:08 -0700 +Subject: [PATCH] Hide sync chunk writes behind flag + +Syncing writes on each write call has terrible performance +on harddrives. + +-DPaper.enable-sync-chunk-writes=true to enable + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +index 545096d9ba403396b6aaa7bb6d912f2de08a967e..3450a58fc02a472eb710aa1a31f6fecefc982b6f 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +@@ -108,7 +108,7 @@ public class DedicatedServerProperties extends Settings { + return Mth.clamp(integer, 1, 29999984); + }, 29999984); +- this.syncChunkWrites = this.get("sync-chunk-writes", true); ++ this.syncChunkWrites = this.get("sync-chunk-writes", true) && Boolean.getBoolean("Paper.enable-sync-chunk-writes"); // Paper - hide behind flag + this.enableJmxMonitoring = this.get("enable-jmx-monitoring", false); + this.enableStatus = this.get("enable-status", true); + this.entityBroadcastRangePercentage = this.get("entity-broadcast-range-percentage", (integer) -> { diff --git a/patches/server-remapped/0504-Limit-lightning-strike-effect-distance.patch b/patches/server-remapped/0504-Limit-lightning-strike-effect-distance.patch new file mode 100644 index 0000000000..1f74c2ced9 --- /dev/null +++ b/patches/server-remapped/0504-Limit-lightning-strike-effect-distance.patch @@ -0,0 +1,76 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Fri, 14 Sep 2018 17:42:08 +0200 +Subject: [PATCH] Limit lightning strike effect distance + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1655bca0502e7b871de4addaa163536d86547a02..978062774c1db286bfb9b0ffdef19d880b1f249b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -646,4 +646,26 @@ public class PaperWorldConfig { + delayChunkUnloadsBy *= 20; + } + } ++ ++ public double sqrMaxThunderDistance; ++ public double sqrMaxLightningImpactSoundDistance; ++ public double maxLightningFlashDistance; ++ private void lightningStrikeDistanceLimit() { ++ sqrMaxThunderDistance = getInt("lightning-strike-distance-limit.sound", -1); ++ if (sqrMaxThunderDistance > 0) { ++ sqrMaxThunderDistance *= sqrMaxThunderDistance; ++ } ++ ++ sqrMaxLightningImpactSoundDistance = getInt("lightning-strike-distance-limit.impact-sound", -1); ++ if (sqrMaxLightningImpactSoundDistance < 0) { ++ sqrMaxLightningImpactSoundDistance = 32 * 32; //Vanilla value ++ } else { ++ sqrMaxLightningImpactSoundDistance *= sqrMaxLightningImpactSoundDistance; ++ } ++ ++ maxLightningFlashDistance = getInt("lightning-strike-distance-limit.flash", -1); ++ if (maxLightningFlashDistance < 0) { ++ maxLightningFlashDistance = 512; // Vanilla value ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java +index e030e7f3d8bd9fe6578df0b560a237d494ec8a01..4b0dbeded2b8a475d32f518957909d3495a4b6fc 100644 +--- a/src/main/java/net/minecraft/world/entity/LightningBolt.java ++++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java +@@ -15,7 +15,6 @@ import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.Difficulty; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +@@ -74,6 +73,17 @@ public class LightningBolt extends Entity { + double deltaX = this.getX() - player.getX(); + double deltaZ = this.getZ() - player.getZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; ++ // Paper start - Limit lightning strike effect distance ++ if (distanceSquared <= this.level.paperConfig.sqrMaxLightningImpactSoundDistance) { ++ player.connection.send(new ClientboundSoundPacket(SoundEvents.LIGHTNING_BOLT_IMPACT, ++ SoundSource.WEATHER, this.getX(), this.getY(), this.getZ(), 2.0f, 0.5F + this.random.nextFloat() * 0.2F)); ++ } ++ ++ if (level.paperConfig.sqrMaxThunderDistance != -1 && distanceSquared >= level.paperConfig.sqrMaxThunderDistance) { ++ continue; ++ } ++ ++ // Paper end + if (distanceSquared > viewDistance * viewDistance) { + double deltaLength = Math.sqrt(distanceSquared); + double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance; +@@ -84,7 +94,7 @@ public class LightningBolt extends Entity { + } + } + // CraftBukkit end +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_IMPACT, SoundSource.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); ++// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); // Paper - Limit lightning strike effect distance (the packet is now sent from inside the loop) + } + + --this.life; diff --git a/patches/server-remapped/0505-Add-permission-for-command-blocks.patch b/patches/server-remapped/0505-Add-permission-for-command-blocks.patch new file mode 100644 index 0000000000..9e0fdeee13 --- /dev/null +++ b/patches/server-remapped/0505-Add-permission-for-command-blocks.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 16 May 2020 10:05:30 +0200 +Subject: [PATCH] Add permission for command blocks + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index af048ab682612233c01f7087d7b8afbf7e58945b..79f3e4176145c42debb9adc1e68175cf063c1f22 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -386,7 +386,7 @@ public class ServerPlayerGameMode { + BlockEntity tileentity = this.level.getBlockEntity(pos); + Block block = iblockdata.getBlock(); + +- if ((block instanceof CommandBlock || block instanceof StructureBlock || block instanceof JigsawBlock) && !this.player.canUseGameMasterBlocks()) { ++ if ((block instanceof CommandBlock || block instanceof StructureBlock || block instanceof JigsawBlock) && !this.player.canUseGameMasterBlocks() && !(block instanceof CommandBlock && (this.player.isCreative() && this.player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission + this.level.sendBlockUpdated(pos, iblockdata, iblockdata, 3); + return false; + } else if (this.player.blockActionRestricted((Level) this.level, pos, this.gameModeForPlayer)) { +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index a0b2fc3fe59d97b9282a9451f35542b39df774e7..471370a9aafa3eda83beb4097c6233650bd155ee 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -796,7 +796,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (!this.server.isCommandBlockEnabled()) { + this.player.sendMessage(new TranslatableComponent("advMode.notEnabled"), Util.NIL_UUID); +- } else if (!this.player.canUseGameMasterBlocks()) { ++ } else if (!this.player.canUseGameMasterBlocks() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission + this.player.sendMessage(new TranslatableComponent("advMode.notAllowed"), Util.NIL_UUID); + } else { + BaseCommandBlock commandblocklistenerabstract = null; +@@ -859,7 +859,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (!this.server.isCommandBlockEnabled()) { + this.player.sendMessage(new TranslatableComponent("advMode.notEnabled"), Util.NIL_UUID); +- } else if (!this.player.canUseGameMasterBlocks()) { ++ } else if (!this.player.canUseGameMasterBlocks() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission + this.player.sendMessage(new TranslatableComponent("advMode.notAllowed"), Util.NIL_UUID); + } else { + BaseCommandBlock commandblocklistenerabstract = packet.getCommandBlock(this.player.level); +diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +index 00dc4cd436023b946d7005f17a7ba983a4bbdfb6..23500428abf5e7daec19f8fb3c24e6c5361f0819 100644 +--- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java ++++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +@@ -192,7 +192,7 @@ public abstract class BaseCommandBlock implements CommandSource { + } + + public InteractionResult usedBy(Player player) { +- if (!player.canUseGameMasterBlocks()) { ++ if (!player.canUseGameMasterBlocks() && !player.isCreative() && !player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission + return InteractionResult.PASS; + } else { + if (player.getCommandSenderWorld().isClientSide) { +diff --git a/src/main/java/net/minecraft/world/level/block/CommandBlock.java b/src/main/java/net/minecraft/world/level/block/CommandBlock.java +index 088d78905732cacf69beb7a4b713dac4bec82220..c5e81e7d67504b1bc2a87c0b577bb93be4a57e9c 100644 +--- a/src/main/java/net/minecraft/world/level/block/CommandBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CommandBlock.java +@@ -128,7 +128,7 @@ public class CommandBlock extends BaseEntityBlock { + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { + BlockEntity tileentity = world.getBlockEntity(pos); + +- if (tileentity instanceof CommandBlockEntity && player.canUseGameMasterBlocks()) { ++ if (tileentity instanceof CommandBlockEntity && (player.canUseGameMasterBlocks() || (player.isCreative() && player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission + player.openCommandBlock((CommandBlockEntity) tileentity); + return InteractionResult.sidedSuccess(world.isClientSide); + } else { +diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java +index 525ebf961e5da0687183a5e2ead23ed92cbd9d79..a4a809f302c5ff9c76cde5fc0add2ceec1bdf9b5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java +@@ -16,6 +16,7 @@ public final class CraftDefaultPermissions { + DefaultPermissions.registerPermission(ROOT + ".nbt.copy", "Gives the user the ability to copy NBT in creative", org.bukkit.permissions.PermissionDefault.TRUE, parent); + DefaultPermissions.registerPermission(ROOT + ".debugstick", "Gives the user the ability to use the debug stick in creative", org.bukkit.permissions.PermissionDefault.OP, parent); + DefaultPermissions.registerPermission(ROOT + ".debugstick.always", "Gives the user the ability to use the debug stick in all game modes", org.bukkit.permissions.PermissionDefault.FALSE, parent); ++ DefaultPermissions.registerPermission(ROOT + ".commandblock", "Gives the user the ability to use command blocks.", org.bukkit.permissions.PermissionDefault.OP, parent); // Paper + // Spigot end + parent.recalculatePermissibles(); + } diff --git a/patches/server-remapped/0506-Ensure-Entity-AABB-s-are-never-invalid.patch b/patches/server-remapped/0506-Ensure-Entity-AABB-s-are-never-invalid.patch new file mode 100644 index 0000000000..f77fef5ea0 --- /dev/null +++ b/patches/server-remapped/0506-Ensure-Entity-AABB-s-are-never-invalid.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 May 2020 22:12:46 -0400 +Subject: [PATCH] Ensure Entity AABB's are never invalid + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d9bb00752ac81b2171d3ad25fd84904467a18e3b..728379292728cf58f5512feae3cdc74392980f68 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -66,6 +66,7 @@ import net.minecraft.world.Nameable; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.animal.AbstractFish; + import net.minecraft.world.entity.animal.Animal; ++import net.minecraft.world.entity.decoration.HangingEntity; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.AbstractMinecart; +@@ -478,7 +479,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + public void setPos(double x, double y, double z) { + this.setPosRaw(x, y, z); +- this.setBoundingBox(this.dimensions.makeBoundingBox(x, y, z)); ++ //this.a(this.size.a(d0, d1, d2)); // Paper - move into setPositionRaw + if (valid) ((ServerLevel) level).updateChunkPos(this); // CraftBukkit + } + +@@ -2998,6 +2999,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return new AABB(vec3d, vec3d1); + } + ++ public final void setBoundingBox(AABB axisalignedbb) { setBoundingBox(axisalignedbb); } // Paper - OBFHELPER + public void setBoundingBox(AABB boundingBox) { + // CraftBukkit start - block invalid bounding boxes + double minX = boundingBox.minX, +@@ -3436,6 +3438,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public void setPosRaw(double x, double y, double z) { ++ // Paper start - never allow AABB to become desynced from position ++ // hanging has its own special logic ++ if (!(this instanceof HangingEntity) && (this.position.x != x || this.position.y != y || this.position.z != z)) { ++ this.setBoundingBox(this.dimensions.makeBoundingBox(x, y, z)); ++ } ++ // Paper end + if (this.position.x != x || this.position.y != y || this.position.z != z) { + this.position = new Vec3(x, y, z); + int i = Mth.floor(x); diff --git a/patches/server-remapped/0507-Optimize-WorldBorder-collision-checks-and-air.patch b/patches/server-remapped/0507-Optimize-WorldBorder-collision-checks-and-air.patch new file mode 100644 index 0000000000..bc82f5847c --- /dev/null +++ b/patches/server-remapped/0507-Optimize-WorldBorder-collision-checks-and-air.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 10 May 2020 22:49:05 -0400 +Subject: [PATCH] Optimize WorldBorder collision checks and air + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 728379292728cf58f5512feae3cdc74392980f68..e9a658b11e2b6683831dc3f5bd20be9a7840ed69 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -102,7 +102,6 @@ import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; +-import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -908,7 +907,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + AABB axisalignedbb = this.getBoundingBox(); + CollisionContext voxelshapecollision = CollisionContext.of(this); + VoxelShape voxelshape = this.level.getWorldBorder().getCollisionShape(); +- Stream stream = Shapes.joinIsNotEmpty(voxelshape, Shapes.create(axisalignedbb.deflate(1.0E-7D)), BooleanOp.AND) ? Stream.empty() : Stream.of(voxelshape); ++ Stream stream = !this.level.getWorldBorder().isInBounds(axisalignedbb) ? Stream.empty() : Stream.of(voxelshape); // Paper + Stream stream1 = this.level.getEntityCollisions(this, axisalignedbb.expandTowards(movement), (entity) -> { + return true; + }); +diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +index feca9ff34936686c0665ae0dbc926869087df3a7..60f8585a736af5b654b8aaed89a39a8bf5e91301 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java ++++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +@@ -143,10 +143,10 @@ public class CollisionSpliterator extends AbstractSpliterator { + AABB axisalignedbb = this.source.getBoundingBox(); + + if (!isBoxFullyWithinWorldBorder(worldborder, axisalignedbb)) { +- VoxelShape voxelshape = worldborder.getCollisionShape(); +- +- if (!isOutsideBorder(voxelshape, axisalignedbb) && isCloseToBorder(voxelshape, axisalignedbb)) { +- consumer.accept(voxelshape); ++ // Paper start ++ if (worldborder.isInBounds(axisalignedbb.deflate(1.0E-7D)) && !worldborder.isInBounds(axisalignedbb.grow(1.0E-7D))) { ++ consumer.accept(worldborder.asVoxelShape()); ++ // Paper end + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index 7a728ca96ee2eaf776c391ba8351196a526e18ec..aaa6251838483de5c46913534413151b5cb1d3fe 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -52,6 +52,7 @@ public class WorldBorder { + return (double) pos.getMaxBlockX() > this.getMinX() && (double) pos.getMinBlockX() < this.getMaxX() && (double) pos.getMaxBlockZ() > this.getMinZ() && (double) pos.getMinBlockZ() < this.getMaxZ(); + } + ++ public final boolean isInBounds(AABB aabb) { return this.isWithinBounds(aabb); } // Paper - OBFHELPER + public boolean isWithinBounds(AABB box) { + return box.maxX > this.getMinX() && box.minX < this.getMaxX() && box.maxZ > this.getMinZ() && box.minZ < this.getMaxZ(); + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index 1603eb3f7d90a4b3a028b20776566db77d09c123..f28d2126bc29fad3971a32cf85a7a7c4803b36ab 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -252,7 +252,7 @@ public final class Shapes { + BlockState iblockdata = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper + if (iblockdata == null) return 0.0D; // Paper + +- if ((k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { ++ if (!iblockdata.isAir() && (k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { // Paper + initial = iblockdata.getCollisionShape((BlockGetter) world, blockposition_mutableblockposition, context).collide(enumdirection_enumaxis2, box.move((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), initial); + if (Math.abs(initial) < 1.0E-7D) { + return 0.0D; diff --git a/patches/server-remapped/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/patches/server-remapped/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch new file mode 100644 index 0000000000..568d1c34e6 --- /dev/null +++ b/patches/server-remapped/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 28 Jun 2020 03:59:10 -0400 +Subject: [PATCH] Fix Per World Difficulty / Remembering Difficulty + +Fixes per world difficulty with /difficulty command and also +makes it so that the server keeps the last difficulty used instead +of restoring the server.properties every single load. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index f530c739b6aee3718eb5d0e0e6a09d882d817c68..19544b794b5a46c129016172798ff7294fcfed33 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1645,11 +1645,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Sun, 28 Jun 2020 19:27:20 -0400 +Subject: [PATCH] Paper dumpitem command + +Let's you quickly view the item in your hands NBT data + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 528c860fc0c04431e0ebb2ae6bc96bf9c2d04789..6fad9329213e4e8a3ef9ce7fb568ad22484a11f3 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -12,6 +12,7 @@ import com.google.gson.JsonObject; + import com.google.gson.internal.Streams; + import com.google.gson.stream.JsonWriter; + import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MCUtil; +@@ -36,7 +37,9 @@ import org.bukkit.command.CommandSender; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.entity.Player; ++import org.bukkit.inventory.ItemStack; + + import java.io.File; + import java.io.FileOutputStream; +@@ -59,7 +62,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight", "dumpitem").build(); + + public PaperCommand(String name) { + super(name); +@@ -168,6 +171,9 @@ public class PaperCommand extends Command { + case "reload": + doReload(sender); + break; ++ case "dumpitem": ++ doDumpItem(sender); ++ break; + case "debug": + doDebug(sender, args); + break; +@@ -200,6 +206,19 @@ public class PaperCommand extends Command { + return true; + } + ++ private void doDumpItem(CommandSender sender) { ++ ItemStack itemInHand = ((CraftPlayer) sender).getItemInHand(); ++ net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(itemInHand); ++ CompoundTag tag = itemStack.getTag(); ++ if (tag != null) { ++ String nbt = org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(tag.getNbtPrettyComponent()); ++ Bukkit.getConsoleSender().sendMessage(nbt); ++ sender.sendMessage(nbt); ++ } else { ++ sender.sendMessage("Item does not have NBT"); ++ } ++ } ++ + private void doFixLight(CommandSender sender, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage("Only players can use this command"); +diff --git a/src/main/java/net/minecraft/nbt/Tag.java b/src/main/java/net/minecraft/nbt/Tag.java +index 85e9c5f4620fcf48cb3655fbb2db58b3fb31aa74..ba204cf135be333d4ac1c06ee6c2e961faadf8cb 100644 +--- a/src/main/java/net/minecraft/nbt/Tag.java ++++ b/src/main/java/net/minecraft/nbt/Tag.java +@@ -26,6 +26,7 @@ public interface Tag { + return this.toString(); + } + ++ default Component getNbtPrettyComponent() { return this.getPrettyDisplay(); } // Paper - OBFHELPER + default Component getPrettyDisplay() { + return this.getPrettyDisplay("", 0); + } diff --git a/patches/server-remapped/0510-Don-t-allow-null-UUID-s-for-chat.patch b/patches/server-remapped/0510-Don-t-allow-null-UUID-s-for-chat.patch new file mode 100644 index 0000000000..dfc52a21c5 --- /dev/null +++ b/patches/server-remapped/0510-Don-t-allow-null-UUID-s-for-chat.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 28 Jun 2020 19:36:55 -0400 +Subject: [PATCH] Don't allow null UUID's for chat + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +index 002a6c7933f64405707d7d34d3e5c17584539623..a983785bf3bc43f65bd0809870c14a9fd30a3fc1 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +@@ -3,6 +3,7 @@ package net.minecraft.network.protocol.game; + + import java.io.IOException; + import java.util.UUID; ++import net.minecraft.Util; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.chat.ChatType; + import net.minecraft.network.chat.Component; +@@ -21,7 +22,7 @@ public class ClientboundChatPacket implements Packet { + public ClientboundChatPacket(Component message, ChatType location, UUID senderUuid) { + this.message = message; + this.type = location; +- this.sender = senderUuid; ++ this.sender = senderUuid != null ? senderUuid : Util.getNullUUID(); // Paper + } + + @Override diff --git a/patches/server-remapped/0511-Improve-Legacy-Component-serialization-size.patch b/patches/server-remapped/0511-Improve-Legacy-Component-serialization-size.patch new file mode 100644 index 0000000000..2f031e9064 --- /dev/null +++ b/patches/server-remapped/0511-Improve-Legacy-Component-serialization-size.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 28 Jun 2020 19:08:41 -0400 +Subject: [PATCH] Improve Legacy Component serialization size + +Don't constantly send format: false for all formatting options when parent already +has it false + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +index b27af66795d902a2e95d692fa0ff18eccbef8a75..b89660244ffad484e3fbf69ccb9cdc1bc178d2ad 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +@@ -46,6 +46,7 @@ public final class CraftChatMessage { + // Separate pattern with no group 3, new lines are part of previous string + private static final Pattern INCREMENTAL_PATTERN_KEEP_NEWLINES = Pattern.compile("(" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + "[0-9a-fk-orx])|((?:(?:https?):\\/\\/)?(?:[-\\w_\\.]{2,}\\.[a-z]{2,4}.*?(?=[\\.\\?!,;:]?(?:[" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + " ]|$))))", Pattern.CASE_INSENSITIVE); + // ChatColor.b does not explicitly reset, its more of empty ++ private static final Style EMPTY = Style.EMPTY.withItalic(false); // Paper - OBFHELPER + private static final Style RESET = Style.EMPTY.withBold(false).withItalic(false).setUnderline(false).setStrikethrough(false).setRandom(false); + + private final List list = new ArrayList(); +@@ -67,6 +68,7 @@ public final class CraftChatMessage { + Matcher matcher = (keepNewlines ? INCREMENTAL_PATTERN_KEEP_NEWLINES : INCREMENTAL_PATTERN).matcher(message); + String match = null; + boolean needsAdd = false; ++ boolean hasReset = false; // Paper + while (matcher.find()) { + int groupId = 0; + while ((match = matcher.group(++groupId)) == null) { +@@ -112,7 +114,26 @@ public final class CraftChatMessage { + throw new AssertionError("Unexpected message format"); + } + } else { // Color resets formatting +- modifier = RESET.withColor(format); ++ // Paper start - improve legacy formatting ++ Style previous = modifier; ++ modifier = (!hasReset ? RESET : EMPTY).withColor(format); ++ hasReset = true; ++ if (previous.isBold()) { ++ modifier = modifier.withBold(false); ++ } ++ if (previous.isItalic()) { ++ modifier = modifier.withItalic(false); ++ } ++ if (previous.isObfuscated()) { ++ modifier = modifier.setRandom(false); ++ } ++ if (previous.isStrikethrough()) { ++ modifier = modifier.setStrikethrough(false); ++ } ++ if (previous.isUnderlined()) { ++ modifier = modifier.setUnderline(false); ++ } ++ // Paper end + } + needsAdd = true; + break; diff --git a/patches/server-remapped/0512-Support-old-UUID-format-for-NBT.patch b/patches/server-remapped/0512-Support-old-UUID-format-for-NBT.patch new file mode 100644 index 0000000000..ffba727ac3 --- /dev/null +++ b/patches/server-remapped/0512-Support-old-UUID-format-for-NBT.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 29 Jun 2020 03:26:17 -0400 +Subject: [PATCH] Support old UUID format for NBT + +We have stored UUID in plenty of places that did not get DFU'd + +So just look for old format and load it if it exists. + +diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java +index c856ca720a9329a94bb07eaa3060c034f95718b3..0b739b5f040697049893d311c99456dbc5470e93 100644 +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -142,6 +142,12 @@ public class CompoundTag implements Tag { + + public void setUUID(String prefix, UUID uuid) { putUUID(prefix, uuid); } // Paper - OBFHELPER + public void putUUID(String key, UUID value) { ++ // Paper start - support old format ++ if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { ++ this.tags.remove(key + "Most"); ++ this.tags.remove(key + "Least"); ++ } ++ // Paper end + this.tags.put(key, NbtUtils.createUUID(value)); + } + +@@ -151,11 +157,21 @@ public class CompoundTag implements Tag { + */ + public UUID getUUID(String prefix) { return getUUID(prefix); } // Paper - OBFHELPER + public UUID getUUID(String key) { ++ // Paper start - support old format ++ if (!contains(key, 11) && this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { ++ return new UUID(this.getLong(key + "Most"), this.getLong(key + "Least")); ++ } ++ // Paper end + return NbtUtils.loadUUID(this.get(key)); + } + + public final boolean hasUUID(String s) { return this.hasUUID(s); } // Paper - OBFHELPER + public boolean hasUUID(String key) { ++ // Paper start - support old format ++ if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { ++ return true; ++ } ++ // Paper end + Tag nbtbase = this.get(key); + + return nbtbase != null && nbtbase.getType() == IntArrayTag.TYPE && ((IntArrayTag) nbtbase).getAsIntArray().length == 4; +diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java +index bf0da04ec9db3ec8313bddb06c278c13073819d1..f57c5e441045a81072a2edfed0f199d90e6d7fde 100644 +--- a/src/main/java/net/minecraft/nbt/NbtUtils.java ++++ b/src/main/java/net/minecraft/nbt/NbtUtils.java +@@ -40,6 +40,11 @@ public final class NbtUtils { + s = tag.getString("Name"); + } + ++ // Paper start - support string UUID's ++ if (tag.contains("Id", 8)) { ++ uuid = UUID.fromString(tag.getString("Id")); ++ } ++ // Paper end + if (tag.hasUUID("Id")) { + uuid = tag.getUUID("Id"); + } diff --git a/patches/server-remapped/0513-Clean-up-duplicated-GameProfile-Properties.patch b/patches/server-remapped/0513-Clean-up-duplicated-GameProfile-Properties.patch new file mode 100644 index 0000000000..40c9060216 --- /dev/null +++ b/patches/server-remapped/0513-Clean-up-duplicated-GameProfile-Properties.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 1 Jul 2020 03:12:06 -0400 +Subject: [PATCH] Clean up duplicated GameProfile Properties + +We had a bug where we accidently cloned properties resulting in skulls +growing to large sizes and preventing login. + +This now automatically cleans up the extra properties. + +diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java +index f57c5e441045a81072a2edfed0f199d90e6d7fde..3abfd21ea84c54aec6256008b3b9e6bbc7ae694c 100644 +--- a/src/main/java/net/minecraft/nbt/NbtUtils.java ++++ b/src/main/java/net/minecraft/nbt/NbtUtils.java +@@ -59,8 +59,8 @@ public final class NbtUtils { + while (iterator.hasNext()) { + String s1 = (String) iterator.next(); + ListTag nbttaglist = nbttagcompound1.getList(s1, 10); +- +- for (int i = 0; i < nbttaglist.size(); ++i) { ++ if (nbttaglist.size() == 0) continue; // Paper - remove duplicate properties ++ for (int i = nbttaglist.size() - 1; i < nbttaglist.size(); ++i) { // Paper - remove duplicate properties + CompoundTag nbttagcompound2 = nbttaglist.getCompound(i); + String s2 = nbttagcompound2.getString("Value"); + +@@ -246,7 +246,7 @@ public final class NbtUtils { + Optional optional = property.getValue(propertiesTag.getString(key)); + + if (optional.isPresent()) { +- return (StateHolder) state.setValue(property, (Comparable) optional.get()); ++ return state.setValue(property, optional.get()); // Paper - decompile error + } else { + NbtUtils.LOGGER.warn("Unable to read property: {} with value: {} for blockstate: {}", key, propertiesTag.getString(key), mainTag.toString()); + return state; +@@ -276,8 +276,8 @@ public final class NbtUtils { + return nbttagcompound; + } + +- private static > String getName(net.minecraft.world.level.block.state.properties.Property property, Comparable value) { +- return property.value(value); ++ private static > String getName(net.minecraft.world.level.block.state.properties.Property property, Comparable value) {// Paper - decompile error ++ return property.getName((T) value);// Paper - decompile error + } + + public static CompoundTag update(DataFixer fixer, DataFixTypes fixTypes, CompoundTag tag, int oldVersion) { +diff --git a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java +index 1cb67832a849db96f1cce95c32b41574e990e5b7..d97be7a1dfa7ad413afb8ff7668189fd37baf264 100644 +--- a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java ++++ b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java +@@ -59,6 +59,18 @@ public class PlayerHeadItem extends StandingAndWallBlockItem { + return true; + } else { + // CraftBukkit start ++ // Paper start - clean up old duplicated properties ++ CompoundTag properties = tag.getCompound("SkullOwner").getCompound("Properties"); ++ for (String key : properties.getAllKeys()) { ++ net.minecraft.nbt.ListTag values = properties.getList(key, 10); ++ if (values.size() > 1) { ++ net.minecraft.nbt.Tag texture = values.get(values.size() - 1); ++ values = new net.minecraft.nbt.ListTag(); ++ values.add(texture); ++ properties.put(key, values); ++ } ++ } ++ // Paper end + net.minecraft.nbt.ListTag textures = tag.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts + for (int i = 0; i < textures.size(); i++) { + if (textures.get(i) instanceof CompoundTag && !((CompoundTag) textures.get(i)).contains("Signature", 8) && ((CompoundTag) textures.get(i)).getString("Value").trim().isEmpty()) { diff --git a/patches/server-remapped/0514-Convert-legacy-attributes-in-Item-Meta.patch b/patches/server-remapped/0514-Convert-legacy-attributes-in-Item-Meta.patch new file mode 100644 index 0000000000..9306e47d2d --- /dev/null +++ b/patches/server-remapped/0514-Convert-legacy-attributes-in-Item-Meta.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 1 Jul 2020 04:50:22 -0400 +Subject: [PATCH] Convert legacy attributes in Item Meta + + +diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +index 2d547810125f00680ef7e60dd791d0bddd9ebd3e..320fd6780af2fa99e4e4f4193cbc9338d492dc6d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java ++++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +@@ -11,6 +11,20 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; + public class CraftAttributeMap implements Attributable { + + private final AttributeMap handle; ++ // Paper start - convert legacy attributes ++ private static final com.google.common.collect.ImmutableMap legacyNMS = com.google.common.collect.ImmutableMap.builder().put("generic.maxHealth", "generic.max_health").put("Max Health", "generic.max_health").put("zombie.spawnReinforcements", "zombie.spawn_reinforcements").put("Spawn Reinforcements Chance", "zombie.spawn_reinforcements").put("horse.jumpStrength", "horse.jump_strength").put("Jump Strength", "horse.jump_strength").put("generic.followRange", "generic.follow_range").put("Follow Range", "generic.follow_range").put("generic.knockbackResistance", "generic.knockback_resistance").put("Knockback Resistance", "generic.knockback_resistance").put("generic.movementSpeed", "generic.movement_speed").put("Movement Speed", "generic.movement_speed").put("generic.flyingSpeed", "generic.flying_speed").put("Flying Speed", "generic.flying_speed").put("generic.attackDamage", "generic.attack_damage").put("generic.attackKnockback", "generic.attack_knockback").put("generic.attackSpeed", "generic.attack_speed").put("generic.armorToughness", "generic.armor_toughness").build(); ++ ++ public static String convertIfNeeded(String nms) { ++ if (nms == null) { ++ return null; ++ } ++ nms = legacyNMS.getOrDefault(nms, nms); ++ if (!nms.toLowerCase().equals(nms) || nms.indexOf(' ') != -1) { ++ return null; ++ } ++ return nms; ++ } ++ // Paper end + + public CraftAttributeMap(AttributeMap handle) { + this.handle = handle; +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 45abfebf3f947dcbd2e7b1d95be8ba918f044e51..cb66998dbaa9d93e92ef4045b83efbb0fd486234 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -480,7 +480,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + + AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); + +- String attributeName = entry.getString(ATTRIBUTES_IDENTIFIER.NBT); ++ String attributeName = CraftAttributeMap.convertIfNeeded(entry.getString(ATTRIBUTES_IDENTIFIER.NBT)); // Paper + if (attributeName == null || attributeName.isEmpty()) { + continue; + } diff --git a/patches/server-remapped/0515-Remove-some-streams-from-structures.patch b/patches/server-remapped/0515-Remove-some-streams-from-structures.patch new file mode 100644 index 0000000000..26f90fc29a --- /dev/null +++ b/patches/server-remapped/0515-Remove-some-streams-from-structures.patch @@ -0,0 +1,143 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Mon, 29 Jun 2020 17:03:06 -0400 +Subject: [PATCH] Remove some streams from structures + +This showed up a lot in the spark profiler, should have a low-medium performance improvement. + +diff --git a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java +index e842dbc586234799a05b6df213b686e17b8ed1ac..2f88e015708cadb43a348ba2b144c3dd92bb95a5 100644 +--- a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java ++++ b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java +@@ -2,21 +2,22 @@ + package net.minecraft.world.level; + + import com.mojang.datafixers.DataFixUtils; ++import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper + import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; +-import net.minecraft.core.Vec3i; + import net.minecraft.server.level.WorldGenRegion; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.FeatureAccess; + import net.minecraft.world.level.levelgen.WorldGenSettings; + import net.minecraft.world.level.levelgen.feature.StructureFeature; ++import net.minecraft.world.level.levelgen.structure.StructurePiece; + import net.minecraft.world.level.levelgen.structure.StructureStart; + + public class StructureFeatureManager { + +- private final LevelAccessor level; ++ private final LevelAccessor level; public LevelAccessor getLevel() { return level; } // Paper - OBFHELPER + private final WorldGenSettings worldGenSettings; + + public StructureFeatureManager(LevelAccessor world, WorldGenSettings options) { +@@ -42,6 +43,20 @@ public class StructureFeatureManager { + }); + } + ++ // Paper start - remove structure streams ++ public java.util.List> getFeatureStarts(SectionPos sectionPosition, StructureFeature structureGenerator) { ++ java.util.List> list = new ObjectArrayList<>(); ++ for (Long curLong: getLevel().getChunk(sectionPosition.x(), sectionPosition.z(), ChunkStatus.STRUCTURE_REFERENCES).getReferencesForFeature(structureGenerator)) { ++ SectionPos sectionPosition1 = SectionPos.of(new ChunkPos(curLong), 0); ++ StructureStart structurestart = getStartForFeature(sectionPosition1, structureGenerator, getLevel().getChunk(sectionPosition1.x(), sectionPosition1.z(), ChunkStatus.STRUCTURE_STARTS)); ++ if (structurestart != null && structurestart.e()) { ++ list.add(structurestart); ++ } ++ } ++ return list; ++ } ++ // Paper end ++ + @Nullable + public StructureStart getStartForFeature(SectionPos pos, StructureFeature feature, FeatureAccess holder) { + return holder.getStartForFeature(feature); +@@ -60,13 +75,21 @@ public class StructureFeatureManager { + } + + public StructureStart getStructureAt(BlockPos pos, boolean matchChildren, StructureFeature feature) { +- return (StructureStart) DataFixUtils.orElse(this.startsForFeature(SectionPos.of(pos), feature).filter((structurestart) -> { +- return structurestart.c().b((Vec3i) pos); +- }).filter((structurestart) -> { +- return !matchChildren || structurestart.d().stream().anyMatch((structurepiece) -> { +- return structurepiece.g().b((BaseBlockPosition) blockposition); +- }); +- }).findFirst(), StructureStart.a); ++ // Paper start - remove structure streams ++ for (StructureStart structurestart : getFeatureStarts(SectionPos.of(pos), feature)) { ++ if (structurestart.c().b(pos)) { ++ if (!matchChildren) { ++ return structurestart; ++ } ++ for (StructurePiece structurepiece : structurestart.d()) { ++ if (structurepiece.g().b(pos)) { ++ return structurestart; ++ } ++ } ++ } ++ } ++ return StructureStart.a; ++ // Paper end + } + + // Spigot start +diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java +index ed83335175bb882741dfaef251ab30ce1590f74c..2422dbb8691b8c45401a68602a33d4d7f1718dfb 100644 +--- a/src/main/java/net/minecraft/world/level/biome/Biome.java ++++ b/src/main/java/net/minecraft/world/level/biome/Biome.java +@@ -39,6 +39,7 @@ import net.minecraft.world.level.levelgen.WorldgenRandom; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.levelgen.feature.StructureFeature; + import net.minecraft.world.level.levelgen.structure.BoundingBox; ++import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder; + import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise; + import net.minecraft.world.level.material.FluidState; +@@ -238,9 +239,11 @@ public final class Biome { + int l1 = j1 << 4; + + try { +- structureAccessor.startsForFeature(SectionPos.of(pos), structuregenerator).forEach((structurestart) -> { +- structurestart.a(region, structureAccessor, chunkGenerator, random, new BoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkPos(i1, j1)); +- }); ++ // Paper start - remove structure streams ++ for (StructureStart structureStart : structureAccessor.getFeatureStarts(SectionPos.of(pos), structuregenerator)) { ++ structureStart.a(region, structureAccessor, chunkGenerator, random, new BoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkPos(i1, j1)); ++ } ++ // Paper end + } catch (Exception exception) { + CrashReport crashreport = CrashReport.forThrowable(exception, "Feature placement"); + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +index 04adec255e4650ead8d80bee32a681c98686fb95..20f3899b7e39033ebc0f833e75fbdba29777a168 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +@@ -41,6 +41,7 @@ import net.minecraft.world.level.levelgen.feature.structures.StructureTemplatePo + import net.minecraft.world.level.levelgen.structure.BoundingBox; + import net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece; + import net.minecraft.world.level.levelgen.structure.StructurePiece; ++import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.synth.ImprovedNoise; + import net.minecraft.world.level.levelgen.synth.PerlinNoise; + import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise; +@@ -455,7 +456,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + while (iterator.hasNext()) { + StructureFeature structuregenerator = (StructureFeature) iterator.next(); + +- accessor.startsForFeature(SectionPos.of(chunkcoordintpair, 0), structuregenerator).forEach((structurestart) -> { ++ for (StructureStart structurestart : accessor.getFeatureStarts(SectionPos.of(chunkcoordintpair, 0), structuregenerator)) { // Paper - remove structure streams + Iterator iterator1 = structurestart.d().iterator(); + + while (iterator1.hasNext()) { +@@ -487,7 +488,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + } + } + +- }); ++ } // Paper - remove structure streams + } + + double[][][] adouble = new double[2][this.chunkCountZ + 1][this.chunkCountY + 1]; diff --git a/patches/server-remapped/0516-Remove-streams-from-classes-related-villager-gossip.patch b/patches/server-remapped/0516-Remove-streams-from-classes-related-villager-gossip.patch new file mode 100644 index 0000000000..a3582192b3 --- /dev/null +++ b/patches/server-remapped/0516-Remove-streams-from-classes-related-villager-gossip.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 1 Jul 2020 18:01:49 -0400 +Subject: [PATCH] Remove streams from classes related villager gossip + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +index 0204f05d989d45c0848f810d1953adf0992ce3c2..57832c392910d22aa81ac2b4816d043dd7ac867a 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +@@ -9,6 +9,7 @@ import com.mojang.serialization.DynamicOps; + import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import java.util.Arrays; + import java.util.Collection; +@@ -51,8 +52,21 @@ public class GossipContainer { + }); + } + ++ // Paper start - Remove streams from reputation ++ private List decompress() { ++ List list = new ObjectArrayList<>(); ++ for (Map.Entry entry : getReputations().entrySet()) { ++ for (GossipContainer.GossipEntry cur : entry.getValue().decompress(entry.getKey())) { ++ if (cur.weightedValue() != 0) ++ list.add(cur); ++ } ++ } ++ return list; ++ } ++ // Paper end ++ + private Collection selectGossipsForTransfer(Random random, int count) { +- List list = (List) this.unpack().collect(Collectors.toList()); ++ List list = decompress(); // Paper - Remove streams from reputation + + if (list.isEmpty()) { + return Collections.emptyList(); +@@ -119,7 +133,7 @@ public class GossipContainer { + } + + public Dynamic store(DynamicOps dynamicops) { +- return new Dynamic(dynamicops, dynamicops.createList(this.unpack().map((reputation_b) -> { ++ return new Dynamic(dynamicops, dynamicops.createList(this.decompress().stream().map((reputation_b) -> { + return reputation_b.store(dynamicops); + }).map(Dynamic::getValue))); + } +@@ -144,18 +158,30 @@ public class GossipContainer { + + public static class EntityGossips { // Paper - make public + +- private final Object2IntMap entries; ++ private final Object2IntMap entries; private Object2IntMap getEntries() { return entries; } // Paper - OBFHELPER + + public EntityGossips() { // Paper - make public - update CraftVillager setReputation on change + this.entries = new Object2IntOpenHashMap(); + } + + public int weightedValue(Predicate gossipTypeFilter) { +- return this.entries.object2IntEntrySet().stream().filter((entry) -> { +- return gossipTypeFilter.test(entry.getKey()); +- }).mapToInt((entry) -> { +- return entry.getIntValue() * ((GossipType) entry.getKey()).weight; +- }).sum(); ++ // Paper start - Remove streams from reputation ++ int weight = 0; ++ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { ++ if (gossipTypeFilter.test(entry.getKey())) { ++ weight += entry.getIntValue() * entry.getKey().getWeight(); ++ } ++ } ++ return weight; ++ } ++ ++ public List decompress(UUID uuid) { ++ List list = new ObjectArrayList<>(); ++ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { ++ list.add(new GossipContainer.GossipEntry(uuid, entry.getKey(), entry.getIntValue())); ++ } ++ return list; ++ // Paper - end + } + + public Stream unpack(UUID target) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java +index 808eaaae5d534427d197c90c8e53494f4c3bfd82..c775d0df2a8f8a0fd32a8ffc26d6ea6978cbb595 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java +@@ -11,7 +11,7 @@ public enum GossipType { + MAJOR_NEGATIVE("major_negative", -5, 100, 10, 10), MINOR_NEGATIVE("minor_negative", -1, 200, 20, 20), MINOR_POSITIVE("minor_positive", 1, 200, 1, 5), MAJOR_POSITIVE("major_positive", 5, 100, 0, 100), TRADING("trading", 1, 25, 2, 20); + + public final String id; +- public final int weight; ++ public final int weight; public int getWeight() { return weight; } // Paper - OBFHELPER + public final int max; + public final int decayPerDay; + public final int decayPerTransfer; diff --git a/patches/server-remapped/0517-Support-components-in-ItemMeta.patch b/patches/server-remapped/0517-Support-components-in-ItemMeta.patch new file mode 100644 index 0000000000..66bda208cc --- /dev/null +++ b/patches/server-remapped/0517-Support-components-in-ItemMeta.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Sat, 6 Jun 2020 18:13:42 +0200 +Subject: [PATCH] Support components in ItemMeta + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index cb66998dbaa9d93e92ef4045b83efbb0fd486234..20e008277d1188fc7b31bfb2522ef9f6429cc3fb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -874,11 +874,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return CraftChatMessage.fromJSONComponent(displayName); + } + ++ // 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(displayName); ++ } ++ // Paper end + @Override + public final void setDisplayName(String name) { + this.displayName = CraftChatMessage.fromStringOrNullToJSON(name); + } + ++ // Paper start ++ @Override ++ public void setDisplayNameComponent(net.md_5.bungee.api.chat.BaseComponent[] component) { ++ this.displayName = net.md_5.bungee.chat.ComponentSerializer.toString(component); ++ } ++ // Paper end + @Override + public boolean hasDisplayName() { + return displayName != null; +@@ -1021,6 +1033,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return this.lore == null ? null : new ArrayList(Lists.transform(this.lore, CraftChatMessage::fromJSONComponent)); + } + ++ // 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(entry) ++ ).collect(java.util.stream.Collectors.toList())); ++ } ++ // Paper end + @Override + public void setLore(List lore) { + if (lore == null || lore.isEmpty()) { +@@ -1035,6 +1055,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + } + ++ // 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 customModelData != null; +@@ -1496,6 +1531,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + + for (Object object : addFrom) { ++ // Paper start - support components ++ if(object instanceof net.md_5.bungee.api.chat.BaseComponent[]) { ++ addTo.add(net.md_5.bungee.chat.ComponentSerializer.toString((net.md_5.bungee.api.chat.BaseComponent[]) object)); ++ } else ++ // Paper end + if (!(object instanceof String)) { + if (object != null) { + throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName()); diff --git a/patches/server-remapped/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/patches/server-remapped/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch new file mode 100644 index 0000000000..52cd27053f --- /dev/null +++ b/patches/server-remapped/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 3 Jul 2020 15:03:33 -0700 +Subject: [PATCH] Improve EntityTargetLivingEntityEvent for 1.16 mobs + +CraftBukkit has a bug in their implementation and is incorrectly handling forget +Also adds more target reasons for why it forgot target. + +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 738162a55eb186f66df4d31e017c9b9a7cc604c2..1b6f34c2a185368aac973e8a5316a03950e4314b 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 +@@ -33,15 +33,15 @@ public class StopAttackingIfTargetInvalid extends Behavior { + + protected void start(ServerLevel world, E entity, long time) { + if (isTiredOfTryingToReachTarget((LivingEntity) entity)) { +- this.clearAttackTarget(entity); ++ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // Paper + } else if (this.isCurrentTargetDeadOrRemoved(entity)) { +- this.clearAttackTarget(entity); ++ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_DIED); // Paper + } else if (this.isCurrentTargetInDifferentLevel(entity)) { +- this.clearAttackTarget(entity); ++ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_OTHER_LEVEL); // Paper + } else if (!EntitySelector.ATTACK_ALLOWED.test(this.getAttackTarget(entity))) { +- this.clearAttackTarget(entity); ++ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper + } else if (this.stopAttackingWhen.test(this.getAttackTarget(entity))) { +- this.clearAttackTarget(entity); ++ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper + } + } + +@@ -65,18 +65,21 @@ public class StopAttackingIfTargetInvalid extends Behavior { + return optional.isPresent() && !((LivingEntity) optional.get()).isAlive(); + } + +- private void clearAttackTarget(E entity) { ++ private void d(E e0, EntityTargetEvent.TargetReason reason) { + // CraftBukkit start +- LivingEntity old = entity.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); +- EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ // Paper start - fix this event ++ //EntityLiving old = e0.getBehaviorController().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(e0, null, reason); + if (event.isCancelled()) { + return; + } +- if (event.getTarget() != null) { +- entity.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); ++ // comment out, bad logic - bad ++ /*if (event.getTarget() != null) { ++ e0.getBehaviorController().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); + return; +- } ++ }*/ ++ // Paper end + // CraftBukkit end +- entity.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); ++ e0.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); + } + } diff --git a/patches/server-remapped/0519-Add-entity-liquid-API.patch b/patches/server-remapped/0519-Add-entity-liquid-API.patch new file mode 100644 index 0000000000..87da8f1dcb --- /dev/null +++ b/patches/server-remapped/0519-Add-entity-liquid-API.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 2 Jul 2020 18:11:43 -0500 +Subject: [PATCH] Add entity liquid API + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index e9a658b11e2b6683831dc3f5bd20be9a7840ed69..aea2457510c75214bbb925307155611e981f115f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1164,12 +1164,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.wasTouchingWater; + } + +- private boolean isInRain() { ++ public boolean isInRain() { // Paper - private -> public + BlockPos blockposition = this.blockPosition(); + + return this.level.isRainingAt(blockposition) || this.level.isRainingAt(new BlockPos((double) blockposition.getX(), this.getBoundingBox().maxY, (double) blockposition.getZ())); + } + ++ public final boolean isInBubbleColumn() { return isInBubbleColumn(); } // Paper - OBFHELPER + private boolean isInBubbleColumn() { + return this.level.getBlockState(this.blockPosition()).is(Blocks.BUBBLE_COLUMN); + } +@@ -1183,6 +1184,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.isInWater() || this.isInRain() || this.isInBubbleColumn(); + } + ++ public final boolean isInWaterOrBubbleColumn() { return isInWaterOrBubble(); } // Paper - OBFHELPER + public boolean isInWaterOrBubble() { + return this.isInWater() || this.isInBubbleColumn(); + } +@@ -1325,6 +1327,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + return this.fluidOnEyes == tag; + } + ++ public final boolean isInLava() { return isInLava(); } // Paper - OBFHELPER + public boolean isInLava() { + return !this.firstTick && this.fluidHeight.getDouble(FluidTags.LAVA) > 0.0D; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 76d652386806fd11961611486a1d0a12fe9616a4..deeae62e9926f9435907c68e7d35e7420f5e79dd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1135,5 +1135,29 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { + return getHandle().spawnReason; + } ++ ++ public boolean isInRain() { ++ return getHandle().isInRain(); ++ } ++ ++ public boolean isInBubbleColumn() { ++ return getHandle().isInBubbleColumn(); ++ } ++ ++ public boolean isInWaterOrRain() { ++ return getHandle().isInWaterOrRain(); ++ } ++ ++ public boolean isInWaterOrBubbleColumn() { ++ return getHandle().isInWaterOrBubbleColumn(); ++ } ++ ++ public boolean isInWaterOrRainOrBubbleColumn() { ++ return getHandle().isInWaterOrRainOrBubble(); ++ } ++ ++ public boolean isInLava() { ++ return getHandle().isInLava(); ++ } + // Paper end + } diff --git a/patches/server-remapped/0520-Update-itemstack-legacy-name-and-lore.patch b/patches/server-remapped/0520-Update-itemstack-legacy-name-and-lore.patch new file mode 100644 index 0000000000..1b999bcc30 --- /dev/null +++ b/patches/server-remapped/0520-Update-itemstack-legacy-name-and-lore.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 1 Jul 2020 11:57:40 -0500 +Subject: [PATCH] Update itemstack legacy name and lore + + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 458cdfbeac9d757c9721acd4557a548affa0ede1..04b717326524f400da3562655c25db59e72814ec 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -49,6 +49,7 @@ import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.StringTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.ComponentUtils; +@@ -135,6 +136,44 @@ public final class ItemStack { + list.sort((Comparator) enchantSorter); // Paper + } catch (Exception ignored) {} + } ++ ++ private void processText() { ++ CompoundTag display = getSubTag("display"); ++ if (display != null) { ++ if (display.contains("Name", 8)) { ++ String json = display.getString("Name"); ++ if (json != null && json.contains("\u00A7")) { ++ try { ++ display.put("Name", convert(json)); ++ } catch (JsonParseException jsonparseexception) { ++ display.remove("Name"); ++ } ++ } ++ } ++ if (display.contains("Lore", 9)) { ++ ListTag list = display.getList("Lore", 8); ++ for (int index = 0; index < list.size(); index++) { ++ String json = list.getString(index); ++ if (json != null && json.contains("\u00A7")) { // Only try if it has legacy in the unparsed json ++ try { ++ list.set(index, convert(json)); ++ } catch (JsonParseException e) { ++ list.set(index, StringTag.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(new TextComponent("")))); ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ private StringTag convert(String json) { ++ Component component = Component.Serializer.jsonToComponent(json); ++ if (component instanceof TextComponent && component.getContents().contains("\u00A7") && component.getSiblings().isEmpty()) { ++ // Only convert if the root component is a single comp with legacy in it, don't convert already normal components ++ component = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(component.getContents())[0]; ++ } ++ return StringTag.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(component)); ++ } + // Paper end + + public ItemStack(ItemLike item) { +@@ -180,6 +219,7 @@ public final class ItemStack { + // CraftBukkit start - make defensive copy as this data may be coming from the save thread + this.tag = (CompoundTag) nbttagcompound.getCompound("tag").copy(); + processEnchantOrder(this.tag); // Paper ++ processText(); // Paper + this.getItem().verifyTagAfterLoad(this.tag); + // CraftBukkit end + } +@@ -663,6 +703,7 @@ public final class ItemStack { + } + } + ++ @Nullable public CompoundTag getSubTag(String s) { return getTagElement(s); } // Paper - OBFHELPER + @Nullable + public CompoundTag getTagElement(String key) { + return this.tag != null && this.tag.contains(key, 10) ? this.tag.getCompound(key) : null; diff --git a/patches/server-remapped/0521-Spawn-player-in-correct-world-on-login.patch b/patches/server-remapped/0521-Spawn-player-in-correct-world-on-login.patch new file mode 100644 index 0000000000..5ec61b9dae --- /dev/null +++ b/patches/server-remapped/0521-Spawn-player-in-correct-world-on-login.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Wyatt Childers +Date: Fri, 3 Jul 2020 14:57:05 -0400 +Subject: [PATCH] Spawn player in correct world on login + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 713cc88dd067c0d918f253b1845f42c0d9eb920f..f36c92e42300c2056075610caf63f8bef0e7edda 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -192,7 +192,18 @@ public abstract class PlayerList { + }String lastKnownName = s; // Paper + // CraftBukkit end + +- if (nbttagcompound != null) { ++ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID. ++ if (nbttagcompound != null && nbttagcompound.contains("WorldUUIDMost") && nbttagcompound.contains("WorldUUIDLeast")) { ++ UUID uid = new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast")); ++ org.bukkit.World bWorld = org.bukkit.Bukkit.getServer().getWorld(uid); ++ if (bWorld != null) { ++ resourcekey = ((CraftWorld) bWorld).getHandle().dimension(); ++ } else { ++ resourcekey = Level.OVERWORLD; ++ } ++ } else if (nbttagcompound != null) { ++ // Vanilla migration support ++ // Paper end + DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension"))); + Logger logger = PlayerList.LOGGER; + diff --git a/patches/server-remapped/0522-Add-PrepareResultEvent.patch b/patches/server-remapped/0522-Add-PrepareResultEvent.patch new file mode 100644 index 0000000000..be0c76ca05 --- /dev/null +++ b/patches/server-remapped/0522-Add-PrepareResultEvent.patch @@ -0,0 +1,164 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 3 Jul 2020 11:58:56 -0500 +Subject: [PATCH] Add PrepareResultEvent + +Adds a new event for all crafting stations that generate a result slot item + +Anvil, Grindstone and Smithing now extend this event + +diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index 72b0cfcc5aab03e14e63440c734436e9c1432111..bc39e7464646d712b085251dc0277a5b1ec0a393 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -141,6 +141,7 @@ public abstract class AbstractContainerMenu { + return nonnulllist; + } + ++ public final void notifyListeners() { this.broadcastChanges(); } // Paper - OBFHELPER + public void broadcastChanges() { + int i; + +diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +index 3d53edae7e3d5bb00913384ad0eb67551a65750e..492a42ad5dc460717de8179d522d042cee11db60 100644 +--- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +@@ -307,6 +307,7 @@ public class AnvilMenu extends ItemCombinerMenu { + } + + this.createResult(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java +index 6183e33237a231be388a8ace0ca3b56720db13ee..464f27d3f0cc694257a550cf873a0ee4534e2189 100644 +--- a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java +@@ -146,6 +146,7 @@ public class CartographyTableMenu extends AbstractContainerMenu { + this.setupResultSlot(itemstack, itemstack1, itemstack2); + } + ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + private void setupResultSlot(ItemStack map, ItemStack item, ItemStack oldResult) { +diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +index e9e830117fe3e4e02a51eef8671a3d3b48c2858e..329a6d70d53c13cd554c64996f2ddc489bdc1e94 100644 +--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -156,6 +156,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { + super.slotsChanged(inventory); + if (inventory == this.repairSlots) { + this.createResult(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java +index d944cbcdf4d886d3b8b171edd8e2ac8a54dc19b9..8704c4dbead1ff661d84b751479babac5ebc5839 100644 +--- a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java +@@ -71,6 +71,7 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu { + super.slotsChanged(inventory); + if (inventory == this.inputSlots) { + this.createResult(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +index b33daf92752841e46f2fd9fa20dc1cfa79aa423a..3460fb2bb1451b8456a7fe42449ec4dbce641f40 100644 +--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +@@ -188,7 +188,8 @@ public class LoomMenu extends AbstractContainerMenu { + } + + this.setupResultSlot(); +- this.broadcastChanges(); ++ //this.c(); // Paper - done below ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 3); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/inventory/SmithingMenu.java b/src/main/java/net/minecraft/world/inventory/SmithingMenu.java +index befb2e6294c3d0a16ae4766c3804d04fd4e1bba5..44aa1f4f91ae9f84fc7ed38cc6b3c11f07d55ba1 100644 +--- a/src/main/java/net/minecraft/world/inventory/SmithingMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/SmithingMenu.java +@@ -78,6 +78,7 @@ public class SmithingMenu extends ItemCombinerMenu { + // CraftBukkit end + } + ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +index febf7fa112c470888af171e585ab6a052abb46ca..072bac443e7c54ac2b92e1d93b757bdacf230fbb 100644 +--- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +@@ -155,6 +155,7 @@ public class StonecutterMenu extends AbstractContainerMenu { + this.setupRecipeList(inventory, itemstack); + } + ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 1); // Paper + } + + private void setupRecipeList(Container input, ItemStack stack) { +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 87fe7f4f5ed70bf1b3dc1e2a392ba42a1f8f568b..64cfa14aa4e32430a6970fd4f3654a56146ba807 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1522,19 +1522,44 @@ public class CraftEventFactory { + return event; + } + +- public static PrepareAnvilEvent callPrepareAnvilEvent(InventoryView view, ItemStack item) { +- PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item).clone()); +- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); ++ // Paper start - disable this method, handled below ++ public static void callPrepareAnvilEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult ++ PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone ++ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // disable event + event.getInventory().setItem(2, event.getResult()); +- return event; ++ //return event; // Paper + } ++ // Paper end + +- public static PrepareSmithingEvent callPrepareSmithingEvent(InventoryView view, ItemStack item) { +- PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item).clone()); +- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); ++ // Paper start - disable this method, handled in callPrepareResultEvent ++ public static void callPrepareSmithingEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult ++ PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone ++ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // Paper - disable event + event.getInventory().setItem(2, event.getResult()); +- return event; ++ //return event; // Paper + } ++ // Paper end ++ ++ // Paper start - support specific overrides for prepare result ++ public static void callPrepareResultEvent(AbstractContainerMenu container, int resultSlot) { ++ com.destroystokyo.paper.event.inventory.PrepareResultEvent event; ++ InventoryView view = container.getBukkitView(); ++ org.bukkit.inventory.ItemStack origItem = view.getTopInventory().getItem(resultSlot); ++ CraftItemStack result = origItem != null ? CraftItemStack.asCraftCopy(origItem) : null; ++ if (view.getTopInventory() instanceof org.bukkit.inventory.AnvilInventory) { ++ event = new PrepareAnvilEvent(view, result); ++ } else if (view.getTopInventory() instanceof org.bukkit.inventory.GrindstoneInventory) { ++ event = new com.destroystokyo.paper.event.inventory.PrepareGrindstoneEvent(view, result); ++ } else if (view.getTopInventory() instanceof org.bukkit.inventory.SmithingInventory) { ++ event = new PrepareSmithingEvent(view, result); ++ } else { ++ event = new com.destroystokyo.paper.event.inventory.PrepareResultEvent(view, result); ++ } ++ event.callEvent(); ++ event.getInventory().setItem(resultSlot, event.getResult()); ++ container.notifyListeners(); ++ } ++ // Paper end + + /** + * Mob spawner event. diff --git a/patches/server-remapped/0523-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server-remapped/0523-Allow-delegation-to-vanilla-chunk-gen.patch new file mode 100644 index 0000000000..183e23a96c --- /dev/null +++ b/patches/server-remapped/0523-Allow-delegation-to-vanilla-chunk-gen.patch @@ -0,0 +1,104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Wed, 29 Apr 2020 02:10:32 +0200 +Subject: [PATCH] Allow delegation to vanilla chunk gen + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java +index aaa8d78b131c4095b36c6db6078f57f927c15374..54e560348836498f16dde017c6e7e3fcc263eeea 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java ++++ b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java +@@ -36,7 +36,7 @@ import org.apache.logging.log4j.Logger; + public class UpgradeData { + + private static final Logger LOGGER = LogManager.getLogger(); +- public static final UpgradeData EMPTY = new UpgradeData(); ++ public static final UpgradeData EMPTY = new UpgradeData(); public static UpgradeData getEmptyConverter() { return EMPTY; } // Paper - obfhelper + private static final Direction8[] DIRECTIONS = Direction8.values(); + private final EnumSet sides; + private final int[][] index; +@@ -322,7 +322,7 @@ public class UpgradeData { + if ((Integer) iblockdata.getValue(BlockStateProperties.DISTANCE) >= j) { + world.setBlock(blockposition, (BlockState) iblockdata.setValue(BlockStateProperties.DISTANCE, j), 18); + if (i != 7) { +- Direction[] aenumdirection = null.f; ++ Direction[] aenumdirection = DIRECTIONS; // Paper - decomp fix + int k = aenumdirection.length; + + for (int l = 0; l < k; ++l) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 2ec41cb87cec97780f1fa8abfbb756fca4dba1bf..e301aee53b19fc3f93a36d0ed03a649741123bfa 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2032,6 +2032,32 @@ public final class CraftServer implements Server { + return new CraftChunkData(world); + } + ++ // Paper start ++ @Override ++ public ChunkGenerator.ChunkData createVanillaChunkData(World world, int x, int z) { ++ // get empty object ++ CraftChunkData data = (CraftChunkData) createChunkData(world); ++ // do bunch of vanilla shit ++ net.minecraft.server.level.ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); ++ net.minecraft.world.level.chunk.ProtoChunk protoChunk = new net.minecraft.world.level.chunk.ProtoChunk(new net.minecraft.world.level.ChunkPos(x, z), net.minecraft.world.level.chunk.UpgradeData.getEmptyConverter(), nmsWorld); ++ List list = new ArrayList<>(); ++ list.add(protoChunk); ++ net.minecraft.server.level.WorldGenRegion genRegion = new net.minecraft.server.level.WorldGenRegion(nmsWorld, list); ++ // call vanilla generator, one feature after another. Order here is important! ++ net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator = nmsWorld.getChunkSource().generator; ++ if (chunkGenerator instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator) { ++ chunkGenerator = ((org.bukkit.craftbukkit.generator.CustomChunkGenerator) chunkGenerator).delegate; ++ } ++ chunkGenerator.createBiomes(nmsWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), protoChunk); ++ chunkGenerator.fillFromNoise(genRegion, nmsWorld.structureFeatureManager(), protoChunk); ++ chunkGenerator.buildSurfaceAndBedrock(genRegion, protoChunk); ++ // copy over generated sections ++ data.setRawChunkData(protoChunk.getSections()); ++ // hooray! ++ return data; ++ } ++ // Paper end ++ + @Override + public BossBar createBossBar(String title, BarColor color, BarStyle style, BarFlag... flags) { + return new CraftBossBar(title, color, style, flags); +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +index 8d72cd6a44cf462cfe3adac9bf99a16883a587df..fd2cb2a584fea360fcf8180338708f35c4e3dc1f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +@@ -19,7 +19,7 @@ import org.bukkit.material.MaterialData; + */ + public final class CraftChunkData implements ChunkGenerator.ChunkData { + private final int maxHeight; +- private final LevelChunkSection[] sections; ++ private LevelChunkSection[] sections; // Paper - remove final + private Set tiles; + private World world; // Paper - Anti-Xray - Add world + +@@ -168,6 +168,12 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + return sections; + } + ++ // Paper start ++ public void setRawChunkData(LevelChunkSection[] sections) { ++ this.sections = sections; ++ } ++ // Paper end ++ + Set getTiles() { + return tiles; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java +index eba3a6a2467116d93945ab2d5dc0a6f41d76f547..e25dc1c87752fcf73181cb02ddaf84b258ac4e9d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java +@@ -32,7 +32,7 @@ import org.bukkit.generator.ChunkGenerator.ChunkData; + + public class CustomChunkGenerator extends InternalChunkGenerator { + +- private final net.minecraft.world.level.chunk.ChunkGenerator delegate; ++ public final net.minecraft.world.level.chunk.ChunkGenerator delegate; // Paper - public + private final ChunkGenerator generator; + private final ServerLevel world; + private final Random random = new Random(); diff --git a/patches/server-remapped/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server-remapped/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch new file mode 100644 index 0000000000..253148a7ee --- /dev/null +++ b/patches/server-remapped/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 5 Jul 2020 14:59:31 -0400 +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 cec1e6105b8c2ac3d1482c00482d53d6be0d38d1..9724d4222311345a44aa101ec47523a1909fbe8f 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3038,7 +3038,7 @@ public abstract class LivingEntity extends Entity { + Entity entity = this.getVehicle(); + + super.stopRiding(suppressCancellation); // Paper - suppress +- if (entity != null && entity != this.getVehicle() && !this.level.isClientSide) { ++ if (entity != null && entity != this.getVehicle() && !this.level.isClientSide && entity.valid) { // Paper - don't process on world gen + this.dismountVehicle(entity); + } + diff --git a/patches/server-remapped/0525-Optimize-NetworkManager-Exception-Handling.patch b/patches/server-remapped/0525-Optimize-NetworkManager-Exception-Handling.patch new file mode 100644 index 0000000000..dc51ae715d --- /dev/null +++ b/patches/server-remapped/0525-Optimize-NetworkManager-Exception-Handling.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Sun, 5 Jul 2020 22:38:18 -0400 +Subject: [PATCH] Optimize NetworkManager Exception Handling + + +diff --git a/src/main/java/net/minecraft/network/ConnectionProtocol.java b/src/main/java/net/minecraft/network/ConnectionProtocol.java +index fca778d131aa10e88d5f7ed8d57eda6803318184..47a5ee9db64184f173af5984765e9b6d1a8ec367 100644 +--- a/src/main/java/net/minecraft/network/ConnectionProtocol.java ++++ b/src/main/java/net/minecraft/network/ConnectionProtocol.java +@@ -151,6 +151,7 @@ public enum ConnectionProtocol { + + @Nullable + public Packet createPacket(int id) { ++ if (id < 0 || id >= this.idToConstructor.size()) return null; // Paper + Supplier> supplier = (Supplier) this.idToConstructor.get(id); + + return supplier != null ? (Packet) supplier.get() : null; +diff --git a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java +index 8363b63f8dbd16948eeba3f912dc43605ad8db6a..fbebef6525a0872fecc081c7f63f27c1a04e11dc 100644 +--- a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java ++++ b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java +@@ -9,11 +9,21 @@ import java.util.List; + + public class Varint21FrameDecoder extends ByteToMessageDecoder { + ++ private final byte[] lenBuf = new byte[3]; // Paper + public Varint21FrameDecoder() {} + + protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { ++ // Paper start - if channel is not active just discard the packet ++ if (!channelhandlercontext.channel().isActive()) { ++ bytebuf.skipBytes(bytebuf.readableBytes()); ++ return; ++ } ++ // Paper end + bytebuf.markReaderIndex(); +- byte[] abyte = new byte[3]; ++ // Paper start - reuse temporary length buffer ++ byte[] abyte = lenBuf; ++ java.util.Arrays.fill(abyte, (byte) 0); ++ // Paper end + + for (int i = 0; i < abyte.length; ++i) { + if (!bytebuf.isReadable()) { +diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java +index 22db5d0d2cc33498ca40162c66aa3b5fbf2f569f..3163502cb9bbbb5a00e7f06cf0032b1ad93c354d 100644 +--- a/src/main/java/net/minecraft/network/protocol/Packet.java ++++ b/src/main/java/net/minecraft/network/protocol/Packet.java +@@ -2,8 +2,10 @@ package net.minecraft.network.protocol; + + import io.netty.channel.ChannelFuture; // Paper + import java.io.IOException; ++import net.minecraft.network.Connection; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.PacketListener; ++import net.minecraft.server.level.ServerPlayer; + + public interface Packet { + +@@ -18,17 +20,17 @@ public interface Packet { + /** + * @param player Null if not at PLAY stage yet + */ +- default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} ++ default void onPacketDispatch(@javax.annotation.Nullable ServerPlayer player) {} + + /** + * @param player Null if not at PLAY stage yet + * @param future Can be null if packet was cancelled + */ +- default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} ++ default void onPacketDispatchFinish(@javax.annotation.Nullable ServerPlayer player, @javax.annotation.Nullable ChannelFuture future) {} + default boolean hasFinishListener() { return false; } + default boolean isReady() { return true; } + default java.util.List getExtraPackets() { return null; } +- default boolean packetTooLarge(NetworkManager manager) { ++ default boolean packetTooLarge(Connection manager) { + return false; + } + // Paper end +diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java +index 4ae8201d7dcffeb3298a4e593f978e15ffc5ac15..5812e518222e419da141ab0f70d1e7a3939a0df0 100644 +--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java ++++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java +@@ -1,6 +1,9 @@ + package net.minecraft.network.protocol; + ++import net.minecraft.network.Connection; + import net.minecraft.network.PacketListener; ++import net.minecraft.network.chat.TextComponent; ++import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import co.aikar.timings.MinecraftTimings; // Paper +@@ -30,6 +33,21 @@ public class PacketUtils { + try (Timing ignored = timing.startTiming()) { // Paper - timings + packet.handle(listener); + } // Paper - timings ++ // Paper start ++ catch (Exception e) { ++ Connection networkmanager = listener.a(); ++ if (networkmanager.getPlayer() != null) { ++ LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), networkmanager.getRemoteAddress(), e); ++ } else { ++ LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getRemoteAddress(), e); ++ } ++ TextComponent error = new TextComponent("Packet processing error"); ++ networkmanager.send(new ClientboundDisconnectPacket(error), (future) -> { ++ networkmanager.disconnect(error); ++ }); ++ networkmanager.setReadOnly(); ++ } ++ // Paper end + } else { + PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); + } diff --git a/patches/server-remapped/0526-Fix-Concurrency-issue-in-WeightedList.patch b/patches/server-remapped/0526-Fix-Concurrency-issue-in-WeightedList.patch new file mode 100644 index 0000000000..7c0af04ac0 --- /dev/null +++ b/patches/server-remapped/0526-Fix-Concurrency-issue-in-WeightedList.patch @@ -0,0 +1,153 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 6 Jul 2020 18:36:41 -0400 +Subject: [PATCH] Fix Concurrency issue in WeightedList + +if multiple threads from worldgen sort at same time, it will crash. +So make a copy of the list for sorting purposes. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java +index 0a65e442ddc31c06f3bb0ff5aa152daee7a210af..a81ad258b39b7472312ab1bedeeacaf26ffae4f7 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java +@@ -17,7 +17,7 @@ public class GateBehavior extends Behavior { + private final Set> exitErasedMemories; + private final GateBehavior.OrderPolicy orderPolicy; + private final GateBehavior.RunningPolicy runningPolicy; +- private final WeightedList> behaviors = new WeightedList<>(); ++ private final WeightedList> behaviors = new WeightedList<>(false); // Paper - don't use a clone + + public GateBehavior(Map, MemoryStatus> requiredMemoryState, Set> memoriesToForgetWhenStopped, GateBehavior.OrderPolicy order, GateBehavior.RunningPolicy runMode, List, Integer>> tasks) { + super(requiredMemoryState); +@@ -65,10 +65,9 @@ public class GateBehavior extends Behavior { + }).forEach((behavior) -> { + behavior.g(world, entity, time); + }); +- Set set = this.exitErasedMemories; + Brain behaviorcontroller = entity.getBrain(); + +- set.forEach(behaviorcontroller::removeMemory); ++ this.exitErasedMemories.forEach(behaviorcontroller::eraseMemory); // Paper - decomp fix + } + + @Override +@@ -111,11 +110,11 @@ public class GateBehavior extends Behavior { + static enum OrderPolicy { + + ORDERED((weightedlist) -> { +- }), SHUFFLED(WeightedList::a); ++ }), SHUFFLED(WeightedList::shuffle); + + private final Consumer> consumer; + +- private OrderPolicy(Consumer consumer) { ++ private OrderPolicy(Consumer> consumer) { // Paper - decomp fix + this.consumer = consumer; + } + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java +index e4c1c58e9a9c744c7ebb9948a27766b84a081b9e..85df30ef7c03c2f8ae741a8cac8bf601490d2539 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java +@@ -6,7 +6,7 @@ import com.mojang.serialization.Codec; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import com.mojang.serialization.DynamicOps; +-import com.mojang.serialization.OptionalDynamic; ++ + import java.util.Comparator; + import java.util.List; + import java.util.Random; +@@ -14,26 +14,32 @@ import java.util.stream.Stream; + + public class WeightedList { + +- protected final List> entries; ++ protected final List> list; // Paper - decompile conflict + private final Random random; ++ private final boolean isUnsafe; // Paper + +- public WeightedList() { +- this(Lists.newArrayList()); ++ // Paper start - add useClone option ++ public WeightedList() { this(true); } ++ public WeightedList(boolean isUnsafe) { ++ this(Lists.newArrayList(), isUnsafe); + } + +- private WeightedList(List> entries) { ++ private WeightedList(List> entries) { this(entries, true); } ++ private WeightedList(List> list, boolean isUnsafe) { ++ this.isUnsafe = isUnsafe; ++ // Paper end + this.random = new Random(); +- this.entries = Lists.newArrayList(entries); ++ this.list = Lists.newArrayList(list); // Paper - decompile conflict + } + + public static Codec> codec(Codec codec) { +- return WeightedList.entries.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { +- return weightedlist.a; ++ return WeightedList.WeightedEntry.codec(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { // Paper - decompile conflict ++ return weightedlist.list; // Paper - decompile conflict + }); + } + + public WeightedList add(U item, int weight) { +- this.entries.add(new WeightedList.WeightedEntry<>(item, weight)); ++ this.list.add(new WeightedList.WeightedEntry<>(item, weight)); // Paper - decompile conflict + return this; + } + +@@ -42,21 +48,20 @@ public class WeightedList { + } + + public WeightedList shuffle(Random random) { +- this.entries.forEach((weightedlist_a) -> { +- weightedlist_a.setRandom(random.nextFloat()); +- }); +- this.entries.sort(Comparator.comparingDouble((object) -> { +- return ((WeightedList.WeightedEntry) object).getRandWeight(); +- })); +- return this; ++ // Paper start - make concurrent safe, work off a clone of the list ++ List> list = isUnsafe ? new java.util.ArrayList>(this.list) : this.list; ++ list.forEach((weightedlist_a) -> weightedlist_a.setRandom(random.nextFloat())); ++ list.sort(Comparator.comparingDouble(WeightedEntry::getRandWeight)); ++ return isUnsafe ? new WeightedList<>(list, isUnsafe) : this; ++ // Paper end + } + + public boolean isEmpty() { +- return this.entries.isEmpty(); ++ return this.list.isEmpty(); // Paper - decompile conflict + } + + public Stream stream() { +- return this.entries.stream().map(WeightedList.entries::a); ++ return this.list.stream().map(WeightedList.WeightedEntry::getData); // Paper - decompile conflict + } + + public U getOne(Random random) { +@@ -64,7 +69,7 @@ public class WeightedList { + } + + public String toString() { +- return "WeightedList[" + this.entries + "]"; ++ return "WeightedList[" + this.list + "]"; // Paper - decompile conflict + } + + public static class WeightedEntry { +@@ -98,11 +103,7 @@ public class WeightedList { + return new Codec>() { + public DataResult, T>> decode(DynamicOps dynamicops, T t0) { + Dynamic dynamic = new Dynamic(dynamicops, t0); +- OptionalDynamic optionaldynamic = dynamic.get("data"); +- Codec codec1 = codec; +- +- codec.getClass(); +- return optionaldynamic.flatMap(codec1::parse).map((object) -> { ++ return dynamic.get("data").flatMap(codec::parse).map((object) -> { // Paper - decompile error + return new WeightedList.WeightedEntry<>(object, dynamic.get("weight").asInt(1)); + }).map((weightedlist_a) -> { + return Pair.of(weightedlist_a, dynamicops.empty()); diff --git a/patches/server-remapped/0527-Optimize-the-advancement-data-player-iteration-to-be.patch b/patches/server-remapped/0527-Optimize-the-advancement-data-player-iteration-to-be.patch new file mode 100644 index 0000000000..a23f3a28c9 --- /dev/null +++ b/patches/server-remapped/0527-Optimize-the-advancement-data-player-iteration-to-be.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Wyatt Childers +Date: Sat, 4 Jul 2020 23:07:43 -0400 +Subject: [PATCH] Optimize the advancement data player iteration to be O(N) + rather than O(N^2) + + +diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index 5ab62fc74085bbbb0c81b2f4d16a35c9345cd1f1..af8553f1b22e24fbeb732937fbbffc95cb9dfe90 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -457,6 +457,16 @@ public class PlayerAdvancements { + } + + private void ensureVisibility(Advancement advancement) { ++ // Paper start ++ e(advancement, IterationEntryPoint.ROOT); ++ } ++ private enum IterationEntryPoint { ++ ROOT, ++ ITERATOR, ++ PARENT_OF_ITERATOR ++ } ++ private void e(Advancement advancement, IterationEntryPoint entryPoint) { ++ // Paper end + boolean flag = this.shouldBeVisible(advancement); + boolean flag1 = this.visible.contains(advancement); + +@@ -472,15 +482,23 @@ public class PlayerAdvancements { + } + + if (flag != flag1 && advancement.getParent() != null) { +- this.ensureVisibility(advancement.getParent()); ++ // Paper start - If we're not coming from an iterator consider this to be a root entry, otherwise ++ // market that we're entering from the parent of an iterator. ++ this.e(advancement.getParent(), entryPoint == IterationEntryPoint.ITERATOR ? IterationEntryPoint.PARENT_OF_ITERATOR : IterationEntryPoint.ROOT); + } + ++ // If this is true, we've went through a child iteration, entered the parent, processed the parent ++ // and are about to reprocess the children. Stop processing here to prevent O(N^2) processing. ++ if (entryPoint == IterationEntryPoint.PARENT_OF_ITERATOR) { ++ return; ++ } // Paper end ++ + Iterator iterator = advancement.getChildren().iterator(); + + while (iterator.hasNext()) { + Advancement advancement1 = (Advancement) iterator.next(); + +- this.ensureVisibility(advancement1); ++ this.e(advancement1, IterationEntryPoint.ITERATOR); // Paper - Mark this call as being from iteration + } + + } diff --git a/patches/server-remapped/0528-Fix-arrows-never-despawning-MC-125757.patch b/patches/server-remapped/0528-Fix-arrows-never-despawning-MC-125757.patch new file mode 100644 index 0000000000..677615b010 --- /dev/null +++ b/patches/server-remapped/0528-Fix-arrows-never-despawning-MC-125757.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 8 Jul 2020 11:24:30 -0500 +Subject: [PATCH] Fix arrows never despawning MC-125757 + +This forces the despawn counter to start ticking regardless of +state after the arrow has been alive for 200 ticks (10 seconds) +instead of getting stuck in a never despawn state (bubble columns, +etc). + +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 6225f390b51733217a809910182f58acea1055e2..73df844610530bbfb133bd59d00015117b59b215 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -169,6 +169,7 @@ public abstract class AbstractArrow extends Projectile { + + ++this.inGroundTime; + } else { ++ if (tickCount > 200) this.tickDespawnCounter(); // Paper - tick despawnCounter regardless after 10 seconds + this.inGroundTime = 0; + Vec3 vec3d2 = this.position(); + +@@ -290,6 +291,7 @@ public abstract class AbstractArrow extends Projectile { + + } + ++ protected final void tickDespawnCounter() { this.tickDespawn(); } // Paper - OBFHELPER + protected void tickDespawn() { + ++this.life; + if (this.life >= (pickup == Pickup.CREATIVE_ONLY ? level.paperConfig.creativeArrowDespawnRate : (pickup == Pickup.DISALLOWED ? level.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? diff --git a/patches/server-remapped/0529-Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server-remapped/0529-Thread-Safe-Vanilla-Command-permission-checking.patch new file mode 100644 index 0000000000..41cf790265 --- /dev/null +++ b/patches/server-remapped/0529-Thread-Safe-Vanilla-Command-permission-checking.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 11 Jul 2020 03:54:28 -0400 +Subject: [PATCH] Thread Safe Vanilla Command permission checking + +Datapacks check this on load and are built concurrently. This was breaking them badly due +to race conditions. + +Plus, .canUse we want to be safe for async anyways. + +diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +index 5c35cef42af4053332c02b4960c227fe95d4c197..757ed7a0887f4bdb187ca7c757db5c188362f1a0 100644 +--- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java ++++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +@@ -74,10 +74,10 @@ public abstract class CommandNode implements Comparable> { + public synchronized boolean canUse(final S source) { + if (source instanceof CommandSourceStack) { + try { +- ((CommandSourceStack) source).currentCommand = this; ++ ((CommandSourceStack) source).currentCommand.set(this); // Paper + return requirement.test(source); + } finally { +- ((CommandSourceStack) source).currentCommand = null; ++ ((CommandSourceStack) source).currentCommand.set(null); // Paper + } + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java +index e1f4ffaa36bfffb7741c74b7a094e26a03a9a1e6..2c024f8f8b949dc8cebd29a10415eeac6d50902e 100644 +--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java ++++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java +@@ -54,7 +54,7 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy + private final ResultConsumer consumer; + private final EntityAnchorArgument.Anchor anchor; + private final Vec2 rotation; +- public volatile CommandNode currentCommand; // CraftBukkit ++ public ThreadLocal currentCommand = new ThreadLocal<>(); // CraftBukkit // Paper + + public CommandSourceStack(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String simpleName, Component name, MinecraftServer server, @Nullable Entity entity) { + this(output, pos, rot, world, level, simpleName, name, server, entity, false, (commandcontext, flag, j) -> { +@@ -171,9 +171,11 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy + @Override + public boolean hasPermission(int level) { + // CraftBukkit start +- CommandNode currentCommand = this.currentCommand; ++ // Paper start - fix concurrency issue ++ CommandNode currentCommand = this.currentCommand.get(); + if (currentCommand != null) { + return hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); ++ // Paper end + } + // CraftBukkit end + diff --git a/patches/server-remapped/0530-Move-range-check-for-block-placing-up.patch b/patches/server-remapped/0530-Move-range-check-for-block-placing-up.patch new file mode 100644 index 0000000000..7fba765097 --- /dev/null +++ b/patches/server-remapped/0530-Move-range-check-for-block-placing-up.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Jul 2020 19:34:11 -0700 +Subject: [PATCH] Move range check for block placing up + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 773f2589c14e16d2f5b01a6dbd48e09d17d19c7e..d264fca2737f83a0860394f7bb6b269ffe669594 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1661,15 +1661,19 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + BlockPos blockposition = movingobjectpositionblock.getBlockPos(); + Direction enumdirection = movingobjectpositionblock.getDirection(); + ++ // Paper start - move check up ++ Location eyeLoc = this.getPlayer().getEyeLocation(); ++ double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); ++ if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { ++ return; ++ } ++ // Paper end - move check up ++ + this.player.resetLastActionTime(); + if (blockposition.getY() < this.server.getMaxBuildHeight()) { + if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition)) { + // CraftBukkit start - Check if we can actually do something over this large a distance +- Location eyeLoc = this.getPlayer().getEyeLocation(); +- double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); +- if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { +- return; +- } ++ // Paper - move check up + this.player.stopUsingItem(); // SPIGOT-4706 + // CraftBukkit end + InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); diff --git a/patches/server-remapped/0531-Fix-SPIGOT-5989.patch b/patches/server-remapped/0531-Fix-SPIGOT-5989.patch new file mode 100644 index 0000000000..84a6a9da90 --- /dev/null +++ b/patches/server-remapped/0531-Fix-SPIGOT-5989.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 15 Jul 2020 21:42:52 -0400 +Subject: [PATCH] Fix SPIGOT-5989 + +Before this fix, if a player was respawning to a respawn anchor and +the respawn location was modified away from the anchor with the +PlayerRespawnEvent, the anchor would still lose some charge. +This fixes that by checking if the modified spawn location is +still at a respawn anchor. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index f36c92e42300c2056075610caf63f8bef0e7edda..882cd25c9610f0b995c27291aa62846922ab531f 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -84,6 +84,7 @@ import net.minecraft.world.level.GameType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.RespawnAnchorBlock; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.border.BorderChangeListener; + import net.minecraft.world.level.border.WorldBorder; +@@ -846,6 +847,7 @@ public abstract class PlayerList { + // Paper start + boolean isBedSpawn = false; + boolean isRespawn = false; ++ boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 + // Paper end + + // CraftBukkit start - fire PlayerRespawnEvent +@@ -856,7 +858,7 @@ public abstract class PlayerList { + Optional optional; + + if (blockposition != null) { +- optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, flag); ++ optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, true); // Paper - Fix SPIGOT-5989 + } else { + optional = Optional.empty(); + } +@@ -899,7 +901,12 @@ public abstract class PlayerList { + } + // Spigot End + +- location = respawnEvent.getRespawnLocation(); ++ // Paper start - Fix SPIGOT-5989 ++ if (!location.equals(respawnEvent.getRespawnLocation()) ) { ++ location = respawnEvent.getRespawnLocation(); ++ isLocAltered = true; ++ } ++ // Paper end + if (!flag) entityplayer.reset(); // SPIGOT-4785 + isRespawn = true; // Paper + } else { +@@ -937,8 +944,12 @@ public abstract class PlayerList { + } + // entityplayer1.syncInventory(); + entityplayer1.setHealth(entityplayer1.getHealth()); +- if (flag2) { +- entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 1.0F, 1.0F)); ++ // Paper start - Fix SPIGOT-5989 ++ if (flag2 && !isLocAltered) { ++ BlockState data = worldserver1.getBlockState(blockposition); ++ worldserver1.setBlock(blockposition, data.setValue(RespawnAnchorBlock.CHARGE, data.getValue(RespawnAnchorBlock.CHARGE) - 1), 3); ++ entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) location.getX(), (double) location.getY(), (double) location.getZ(), 1.0F, 1.0F)); ++ // Paper end + } + // Added from changeDimension + sendAllPlayerInfo(entityplayer); // Update health, etc... diff --git a/patches/server-remapped/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/patches/server-remapped/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch new file mode 100644 index 0000000000..52bb1345ae --- /dev/null +++ b/patches/server-remapped/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 10 Jul 2020 13:12:33 -0500 +Subject: [PATCH] Fix SPIGOT-5824 Bukkit world-container is not used + + +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 855b3b4c90d84d4efa8395a76010b4b194591cbc..4e353432281a6dbbb49eaa4a6cb4eb051d1a08c5 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -124,11 +124,20 @@ public class Main { + return; + } + +- File file = (File) optionset.valueOf("universe"); // CraftBukkit ++ // Paper start - fix SPIGOT-5824 ++ File file; ++ File userCacheFile = new File("usercache.json"); ++ if (optionset.has("universe")) { ++ file = (File) optionset.valueOf("universe"); // CraftBukkit ++ userCacheFile = new File(file, "usercache.json"); ++ } else { ++ file = new File(bukkitConfiguration.getString("settings.world-container", ".")); ++ } ++ // Paper end - fix SPIGOT-5824 + YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper + MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); + GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); +- GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName())); ++ GameProfileCache usercache = new GameProfileCache(gameprofilerepository, userCacheFile); // Paper - only move usercache.json into folder if --universe is used, not world-container + // CraftBukkit start + String s = (String) Optional.ofNullable(optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); + LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath()); diff --git a/patches/server-remapped/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/patches/server-remapped/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch new file mode 100644 index 0000000000..fb2e14a9d3 --- /dev/null +++ b/patches/server-remapped/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 10 Jul 2020 12:38:12 -0500 +Subject: [PATCH] Fix SPIGOT-5885 Unable to disable advancements + + +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 4e353432281a6dbbb49eaa4a6cb4eb051d1a08c5..9dc9a5e6ad7f23c8bf3553c765ceeecd67a49ac1 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -124,6 +124,7 @@ public class Main { + return; + } + ++ org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init + // Paper start - fix SPIGOT-5824 + File file; + File userCacheFile = new File("usercache.json"); diff --git a/patches/server-remapped/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/patches/server-remapped/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch new file mode 100644 index 0000000000..8ec38751cb --- /dev/null +++ b/patches/server-remapped/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 13 Jul 2020 06:22:54 -0700 +Subject: [PATCH] Fix AdvancementDataPlayer leak due from quitting early in + login + +Move the criterion storage to the AdvancementDataPlayer object +itself, so the criterion object stores no references - and thus +needs no cleanup. + +diff --git a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java +index 31650e41b37e322d2e8a4d4a3deec95851e72675..a645c79af856d2484a4ce7aa2885a32358b9a480 100644 +--- a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java ++++ b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java +@@ -16,25 +16,25 @@ import net.minecraft.world.level.storage.loot.LootContext; + + public abstract class SimpleCriterionTrigger implements CriterionTrigger { + +- private final Map>> a = Maps.newIdentityHashMap(); ++ //private final Map>> a = Maps.newIdentityHashMap(); // Paper - moved into AdvancementDataPlayer to fix memory leak + + public SimpleCriterionTrigger() {} + + @Override + public final void a(PlayerAdvancements advancementdataplayer, CriterionTrigger.Listener criteriontrigger_a) { +- ((Set) this.a.computeIfAbsent(advancementdataplayer, (advancementdataplayer1) -> { ++ (advancementdataplayer.criterionData.computeIfAbsent(this, (advancementdataplayer1) -> { // Paper - fix AdvancementDataPlayer leak + return Sets.newHashSet(); + })).add(criteriontrigger_a); + } + + @Override + public final void b(PlayerAdvancements advancementdataplayer, CriterionTrigger.Listener criteriontrigger_a) { +- Set> set = (Set) this.a.get(advancementdataplayer); ++ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak + + if (set != null) { + set.remove(criteriontrigger_a); + if (set.isEmpty()) { +- this.a.remove(advancementdataplayer); ++ advancementdataplayer.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak + } + } + +@@ -42,7 +42,7 @@ public abstract class SimpleCriterionTrigger tester) { + PlayerAdvancements advancementdataplayer = player.getAdvancements(); +- Set> set = (Set) this.a.get(advancementdataplayer); ++ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak + + if (set != null && !set.isEmpty()) { + LootContext loottableinfo = EntityPredicate.createContext(player, player); +@@ -67,7 +67,7 @@ public abstract class SimpleCriterionTrigger> criterionData = Maps.newIdentityHashMap(); ++ // Paper end - fix advancement data player leakage ++ + public PlayerAdvancements(DataFixer datafixer, PlayerList playerlist, ServerAdvancementManager advancementdataworld, File file, ServerPlayer entityplayer) { + this.dataFixer = datafixer; + this.playerList = playerlist; diff --git a/patches/server-remapped/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/patches/server-remapped/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch new file mode 100644 index 0000000000..468888ab9b --- /dev/null +++ b/patches/server-remapped/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 26 Jul 2020 12:11:39 +0100 +Subject: [PATCH] Add missing strikeLighting call to + World#spigot()#strikeLightningEffect + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 4436b3d23dc8f33925da1ec539ea16307e0785b9..793b1309528671ce822d5a484ff9e40d6eba4e9d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2609,6 +2609,7 @@ public class CraftWorld implements World { + lightning.moveTo( loc.getX(), loc.getY(), loc.getZ() ); + lightning.visualOnly = true; + lightning.isSilent = isSilent; ++ world.strikeLightning( lightning ); + return (LightningStrike) lightning.getBukkitEntity(); + } + }; diff --git a/patches/server-remapped/0536-Fix-some-rails-connecting-improperly.patch b/patches/server-remapped/0536-Fix-some-rails-connecting-improperly.patch new file mode 100644 index 0000000000..a1593c3e27 --- /dev/null +++ b/patches/server-remapped/0536-Fix-some-rails-connecting-improperly.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 24 Jul 2020 15:56:05 -0700 +Subject: [PATCH] Fix some rails connecting improperly + + +diff --git a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java +index 1a44c8b41928a83a22b53d1b6f45ce39b4caf2b2..7cef6d1fc2045c62d4e96a0fd0a311d089cb1406 100644 +--- a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java +@@ -62,6 +62,7 @@ public abstract class BaseRailBlock extends Block { + state = this.updateDir(world, pos, state, true); + if (this.isStraight) { + state.neighborChanged(world, pos, this, pos, notify); ++ state = world.getBlockState(pos); // Paper - don't desync, update again + } + + return state; +diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +index 0ab1e15d8575c3e90a10b80b94030e15a01faac9..1854809e045300e84a713dc7c3a8264f53ec6c0f 100644 +--- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +@@ -70,6 +70,7 @@ public class DetectorRailBlock extends BaseRailBlock { + + private void checkPressed(Level world, BlockPos pos, BlockState state) { + if (this.canSurvive(state, world, pos)) { ++ if (state.getBlock() != this) { return; } // Paper - not our block, don't do anything + boolean flag = (Boolean) state.getValue(DetectorRailBlock.POWERED); + boolean flag1 = false; + List list = this.getInteractingMinecartOfType(world, pos, AbstractMinecart.class, (Predicate) null); +diff --git a/src/main/java/net/minecraft/world/level/block/RailState.java b/src/main/java/net/minecraft/world/level/block/RailState.java +index 0d824ab98dcdd6ea9dac025c37970fb4ec464131..4c17bec369fb19f47760e30b391b2128cee6b276 100644 +--- a/src/main/java/net/minecraft/world/level/block/RailState.java ++++ b/src/main/java/net/minecraft/world/level/block/RailState.java +@@ -12,13 +12,19 @@ import net.minecraft.world.level.block.state.properties.RailShape; + + public class RailState { + +- private final Level level; +- private final BlockPos pos; ++ private final Level level; public final Level getWorld() { return this.level; } // Paper - OBFHELPER ++ private final BlockPos pos; public final BlockPos getPos() { return this.pos; } // Paper - OBFHELPER + private final BaseRailBlock block; +- private BlockState state; ++ private BlockState state; public final BlockState getRailState() { return this.state; } // Paper - OBFHELPER + private final boolean isStraight; + private final List connections = Lists.newArrayList(); + ++ // Paper start - prevent desync ++ public boolean isValid() { ++ return this.getWorld().getBlockState(this.getPos()).getBlock() == this.getRailState().getBlock(); ++ } ++ // Paper end - prevent desync ++ + public RailState(Level world, BlockPos pos, BlockState state) { + this.level = world; + this.pos = pos; +@@ -153,6 +159,11 @@ public class RailState { + } + + private void connectTo(RailState placementHelper) { ++ // Paper start - prevent desync ++ if (!this.isValid() || !placementHelper.isValid()) { ++ return; ++ } ++ // Paper end - prevent desync + this.connections.add(placementHelper.pos); + BlockPos blockposition = this.pos.north(); + BlockPos blockposition1 = this.pos.south(); +@@ -347,11 +358,16 @@ public class RailState { + this.state = (BlockState) this.state.setValue(this.block.getShapeProperty(), blockpropertytrackposition1); + if (forceUpdate || this.level.getBlockState(this.pos) != this.state) { + this.level.setBlock(this.pos, this.state, 3); ++ // Paper start - prevent desync ++ if (!this.isValid()) { ++ return this; ++ } ++ // Paper end - prevent desync + + for (int i = 0; i < this.connections.size(); ++i) { + RailState minecarttracklogic = this.getRail((BlockPos) this.connections.get(i)); + +- if (minecarttracklogic != null) { ++ if (minecarttracklogic != null && minecarttracklogic.isValid()) { // Paper - prevent desync + minecarttracklogic.removeSoftConnections(); + if (minecarttracklogic.canConnectTo(this)) { + minecarttracklogic.connectTo(this); +@@ -364,6 +380,6 @@ public class RailState { + } + + public BlockState getState() { +- return this.state; ++ return this.getWorld().getBlockState(this.getPos()); // Paper - prevent desync + } + } diff --git a/patches/server-remapped/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/patches/server-remapped/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch new file mode 100644 index 0000000000..7f15a77054 --- /dev/null +++ b/patches/server-remapped/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch @@ -0,0 +1,159 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 4 Aug 2020 22:24:15 +0200 +Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections + +I utilized the IDE to convert streams to non streams code, so shouldn't +be any risk of behavior change. Only did minor optimization of the +generated code set to remove unnecessary things. + +I expect us to just drop this patch on next major update and re-apply +it with the IDE again and re-apply the collections optimization. + +Optimize collection by creating a list instead of a set of the key and value. + +This lets us get faster foreach iteration, as well as avoids map lookups on +the values when needed. + +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +index ba8ee93032aabe7ec4ecf52d452e1a580d6ebc20..2ef0e04af771e14f8d71aef4ccb81d3b81db7df5 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +@@ -33,28 +33,31 @@ public class PathFinder { + this.openSet.a(); + this.nodeEvaluator.prepare(world, mob); + Node pathpoint = this.nodeEvaluator.getStart(); +- Map map = (Map) positions.stream().collect(Collectors.toMap((blockposition) -> { +- return this.nodeEvaluator.getGoal((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); +- }, Function.identity())); +- Path pathentity = this.findPath(pathpoint, map, followRange, distance, rangeMultiplier); ++ // Paper start - remove streams - and optimize collection ++ List> map = Lists.newArrayList(); ++ for (BlockPos blockposition : positions) { ++ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal((double) blockposition.getX(), blockposition.getY(), blockposition.getZ()), blockposition)); ++ } ++ // Paper end ++ Path pathentity = this.a(pathpoint, map, followRange, distance, rangeMultiplier); + + this.nodeEvaluator.done(); + return pathentity; + } + + @Nullable +- private Path findPath(Node startNode, Map positions, float followRange, int distance, float rangeMultiplier) { +- Set set = positions.keySet(); ++ private Path a(Node pathpoint, List> list, float f, int i, float f1) { // Paper - optimize collection ++ //Set set = map.keySet(); // Paper + +- startNode.g = 0.0F; +- startNode.h = this.getBestH(startNode, set); +- startNode.f = startNode.h; ++ pathpoint.g = 0.0F; ++ pathpoint.h = this.a(pathpoint, list); // Paper - optimize collection ++ pathpoint.f = pathpoint.h; + this.openSet.a(); +- this.openSet.a(startNode); ++ this.openSet.a(pathpoint); + Set set1 = ImmutableSet.of(); + int j = 0; +- Set set2 = Sets.newHashSetWithExpectedSize(set.size()); +- int k = (int) ((float) this.maxVisitedNodes * rangeMultiplier); ++ List> set2 = Lists.newArrayListWithExpectedSize(list.size()); // Paper - optimize collection ++ int k = (int) ((float) this.maxVisitedNodes * f1); + + while (!this.openSet.e()) { + ++j; +@@ -65,14 +68,15 @@ public class PathFinder { + Node pathpoint1 = this.openSet.c(); + + pathpoint1.closed = true; +- Iterator iterator = set.iterator(); +- +- while (iterator.hasNext()) { +- Target pathdestination = (Target) iterator.next(); ++ // Paper start - optimize collection ++ for (int i1 = 0; i1 < list.size(); i1++) { ++ Map.Entry entry = list.get(i1); ++ Target pathdestination = entry.getKey(); + +- if (pathpoint1.distanceManhattan((Node) pathdestination) <= (float) distance) { ++ if (pathpoint1.distanceManhattan((Node) pathdestination) <= (float) i) { + pathdestination.setReached(); +- set2.add(pathdestination); ++ set2.add(entry); ++ // Paper end + } + } + +@@ -80,7 +84,7 @@ public class PathFinder { + break; + } + +- if (pathpoint1.distanceTo(startNode) < followRange) { ++ if (pathpoint1.distanceTo(pathpoint) < f) { + int l = this.nodeEvaluator.getNeighbors(this.neighbors, pathpoint1); + + for (int i1 = 0; i1 < l; ++i1) { +@@ -90,10 +94,10 @@ public class PathFinder { + pathpoint2.walkedDistance = pathpoint1.walkedDistance + f2; + float f3 = pathpoint1.g + f2 + pathpoint2.costMalus; + +- if (pathpoint2.walkedDistance < followRange && (!pathpoint2.inOpenSet() || f3 < pathpoint2.g)) { ++ if (pathpoint2.walkedDistance < f && (!pathpoint2.inOpenSet() || f3 < pathpoint2.g)) { + pathpoint2.cameFrom = pathpoint1; + pathpoint2.g = f3; +- pathpoint2.h = this.getBestH(pathpoint2, set) * 1.5F; ++ pathpoint2.h = this.a(pathpoint2, list) * 1.5F; // Paper - list instead of set + if (pathpoint2.inOpenSet()) { + this.openSet.a(pathpoint2, pathpoint2.g + pathpoint2.h); + } else { +@@ -105,31 +109,32 @@ public class PathFinder { + } + } + +- Optional optional = !set2.isEmpty() ? set2.stream().map((pathdestination1) -> { +- return this.reconstructPath(pathdestination1.getBestNode(), (BlockPos) positions.get(pathdestination1), true); +- }).min(Comparator.comparingInt(Path::getNodeCount)) : set.stream().map((pathdestination1) -> { +- return this.reconstructPath(pathdestination1.getBestNode(), (BlockPos) positions.get(pathdestination1), false); +- }).min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount)); +- +- if (!optional.isPresent()) { +- return null; +- } else { +- Path pathentity = (Path) optional.get(); +- +- return pathentity; ++ // Paper start - remove streams - and optimize collection ++ Path best = null; ++ boolean useSet1 = set2.isEmpty(); ++ Comparator comparator = useSet1 ? Comparator.comparingInt(Path::getNodeCount) ++ : Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount); ++ for (Map.Entry entry : useSet1 ? list : set2) { ++ Path pathEntity = this.reconstructPath(entry.getKey().getBestNode(), entry.getValue(), !useSet1); ++ if (best == null || comparator.compare(pathEntity, best) < 0) ++ best = pathEntity; + } ++ return best; ++ // Paper end + } + +- private float getBestH(Node node, Set targets) { ++ private float a(Node pathpoint, List> list) { // Paper - optimize collection + float f = Float.MAX_VALUE; + + float f1; + +- for (Iterator iterator = targets.iterator(); iterator.hasNext(); f = Math.min(f1, f)) { +- Target pathdestination = (Target) iterator.next(); ++ // Paper start - optimize collection ++ for (int i = 0, listSize = list.size(); i < listSize; f = Math.min(f1, f), i++) { // Paper ++ Target pathdestination = list.get(i).getKey(); // Paper ++ // Paper end + +- f1 = node.distanceTo(pathdestination); +- pathdestination.updateBest(f1, node); ++ f1 = pathpoint.distanceTo(pathdestination); ++ pathdestination.updateBest(f1, pathpoint); + } + + return f; diff --git a/patches/server-remapped/0538-Incremental-player-saving.patch b/patches/server-remapped/0538-Incremental-player-saving.patch new file mode 100644 index 0000000000..cd7713a510 --- /dev/null +++ b/patches/server-remapped/0538-Incremental-player-saving.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 9 Aug 2020 08:59:25 +0300 +Subject: [PATCH] Incremental player saving + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index b67ba8f75e4a3358d7c2462918b85b0bf9b5a922..fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -440,4 +440,15 @@ public class PaperConfig { + allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); + set("settings.unsupported-settings.allow-tnt-duplication", null); + } ++ ++ public static int playerAutoSaveRate = -1; ++ public static int maxPlayerAutoSavePerTick = 10; ++ private static void playerAutoSaveRate() { ++ playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1); ++ maxPlayerAutoSavePerTick = getInt("settings.max-player-auto-save-per-tick", -1); ++ if (maxPlayerAutoSavePerTick == -1) { // -1 Automatic / "Recommended" ++ // 10 should be safe for everyone unless you mass spamming player auto save ++ maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 19544b794b5a46c129016172798ff7294fcfed33..735c3c983e96e4e6f36de0975909fc48cb042081 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1347,9 +1347,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down + //MinecraftServer.LOGGER.debug("Autosave started"); // Paper + serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper ++ // Paper start ++ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate; ++ if (playerSaveInterval < 0) { ++ playerSaveInterval = autosavePeriod; ++ } ++ // Paper end + this.profiler.push("save"); +- if (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0) { // Paper +- this.playerList.saveAll(); ++ if (playerSaveInterval > 0) { // Paper ++ this.playerList.savePlayers(playerSaveInterval); // Paper + }// Paper + // Paper start + for (ServerLevel world : getAllLevels()) { +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index c5717f45a0110492aad41f21cc06fb8cbeb1f791..bd4d4ace35e966e819aa461d3962fe06ff402be7 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -173,6 +173,7 @@ import org.bukkit.inventory.MainHand; + public class ServerPlayer extends Player implements ContainerListener { + + private static final Logger LOGGER = LogManager.getLogger(); ++ public long lastSave = MinecraftServer.currentTick; // Paper + public ServerGamePacketListenerImpl connection; + public Connection networkManager; // Paper + public final MinecraftServer server; +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 882cd25c9610f0b995c27291aa62846922ab531f..b76735531ef96f9d4c870a5107feea01524a7670 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -559,6 +559,7 @@ public abstract class PlayerList { + protected void save(ServerPlayer player) { + if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit + if (!player.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) ++ player.lastSave = MinecraftServer.currentTick; // Paper + this.playerIo.save(player); + ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit + +@@ -1218,10 +1219,21 @@ public abstract class PlayerList { + } + + public void saveAll() { ++ // Paper start - incremental player saving ++ savePlayers(null); ++ } ++ public void savePlayers(Integer interval) { + MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main + MinecraftTimings.savePlayers.startTiming(); // Paper ++ int numSaved = 0; ++ long now = MinecraftServer.currentTick; + for (int i = 0; i < this.players.size(); ++i) { +- this.save((ServerPlayer) this.players.get(i)); ++ ServerPlayer entityplayer = this.players.get(i); ++ if (interval == null || now - entityplayer.lastSave >= interval) { ++ this.save(entityplayer); ++ if (interval != null && ++numSaved <= com.destroystokyo.paper.PaperConfig.maxPlayerAutoSavePerTick) { break; } ++ } ++ // Paper end + } + MinecraftTimings.savePlayers.stopTiming(); // Paper + return null; }); // Paper - ensure main diff --git a/patches/server-remapped/0539-Import-fastutil-classes.patch b/patches/server-remapped/0539-Import-fastutil-classes.patch new file mode 100644 index 0000000000..706c8236e3 --- /dev/null +++ b/patches/server-remapped/0539-Import-fastutil-classes.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 12 Aug 2020 11:33:04 +0200 +Subject: [PATCH] Import fastutil classes + + +diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java +index 95e166aa63f42c675df645a56e313bdffc2e8663..05f7d4a3835536f26f741d54a0884bd43fc82967 100644 +--- a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java ++++ b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java +@@ -16,6 +16,7 @@ import net.minecraft.CrashReport; + import net.minecraft.ReportedException; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.world.entity.Entity; ++import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; // Paper + import org.apache.commons.lang3.ObjectUtils; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -25,7 +26,7 @@ public class SynchedEntityData { + private static final Logger LOGGER = LogManager.getLogger(); + private static final Map, Integer> ENTITY_ID_POOL = Maps.newHashMap(); + private final Entity entity; +- private final it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap> entries = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL ++ private final Int2ObjectOpenHashMap> entries = new Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL + // private final ReadWriteLock lock = new ReentrantReadWriteLock(); // Spigot - not required + private boolean isEmpty = true; + private boolean isDirty; diff --git a/patches/server-remapped/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch b/patches/server-remapped/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch new file mode 100644 index 0000000000..3a19fd93b1 --- /dev/null +++ b/patches/server-remapped/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Fri, 14 Aug 2020 23:41:19 +0200 +Subject: [PATCH] Don't mark null chunk sections for block updates + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 9e3629884709126574a52ad44fe7523f01dbcce9..82205ad13ef0e987bd83979d06331545efe0a60a 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -449,6 +449,7 @@ public class ChunkHolder { + this.broadcastBlockEntityIfNeeded(world, blockposition, iblockdata); + } else { + LevelChunkSection chunksection = chunk.getSections()[sectionposition.getY()]; ++ if (chunksection == null) chunksection = new LevelChunkSection(sectionposition.getY(), chunk, world, true); // Paper - make a new chunk section if none was found + ClientboundSectionBlocksUpdatePacket packetplayoutmultiblockchange = new ClientboundSectionBlocksUpdatePacket(sectionposition, shortset, chunksection, this.resendLight); + + this.broadcast(packetplayoutmultiblockchange, false); diff --git a/patches/server-remapped/0541-Remove-armour-stand-double-add-to-world.patch b/patches/server-remapped/0541-Remove-armour-stand-double-add-to-world.patch new file mode 100644 index 0000000000..8e11c05922 --- /dev/null +++ b/patches/server-remapped/0541-Remove-armour-stand-double-add-to-world.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Fri, 14 Aug 2020 23:59:26 +0200 +Subject: [PATCH] Remove armour stand double add to world + + +diff --git a/src/main/java/net/minecraft/world/item/ArmorStandItem.java b/src/main/java/net/minecraft/world/item/ArmorStandItem.java +index a2dfcaac8a2a4a69e703de43be76d4fe369fd647..bed063497bb593683ea384605ae1a71a68f4fc1b 100644 +--- a/src/main/java/net/minecraft/world/item/ArmorStandItem.java ++++ b/src/main/java/net/minecraft/world/item/ArmorStandItem.java +@@ -53,7 +53,7 @@ public class ArmorStandItem extends Item { + return InteractionResult.FAIL; + } + +- worldserver.addFreshEntityWithPassengers(entityarmorstand); ++ // Paper - moved down + float f = (float) Mth.floor((Mth.wrapDegrees(context.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F; + + entityarmorstand.moveTo(entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), f, 0.0F); +@@ -63,7 +63,7 @@ public class ArmorStandItem extends Item { + return InteractionResult.FAIL; + } + // CraftBukkit end +- world.addFreshEntity(entityarmorstand); ++ worldserver.addFreshEntityWithPassengers(entityarmorstand); // Paper - moved down + world.playSound((Player) null, entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F); + } + diff --git a/patches/server-remapped/0542-Fix-MC-187716-Use-configured-height.patch b/patches/server-remapped/0542-Fix-MC-187716-Use-configured-height.patch new file mode 100644 index 0000000000..1e2cd52d5b --- /dev/null +++ b/patches/server-remapped/0542-Fix-MC-187716-Use-configured-height.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 15 Aug 2020 08:04:49 -0500 +Subject: [PATCH] Fix MC-187716 Use configured height + + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java +index 3f297ef7bde4159c77681574966446a0eba03f25..ff17c76f341028dd6d17f4c1f13f442c2e404532 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java +@@ -44,7 +44,7 @@ public abstract class NetherCappedSurfaceBuilder extends SurfaceBuilder= 0; --k2) { ++ for (int k2 = height; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height + blockposition_mutableblockposition.set(k1, k2, l1); + BlockState iblockdata5 = chunk.getBlockState(blockposition_mutableblockposition); + int l2; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java +index 4d6c03048022442dea467e1d9d018f150adc62c7..f64671b7359fb71e8af578d48d0a3c211e315057 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java +@@ -34,7 +34,7 @@ public class NetherForestSurfaceBuilder extends SurfaceBuilder= 0; --k2) { ++ for (int k2 = height; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height + blockposition_mutableblockposition.set(k1, k2, l1); + BlockState iblockdata3 = surfaceBlocks.getTopMaterial(); + BlockState iblockdata4 = chunk.getBlockState(blockposition_mutableblockposition); +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java +index c1e0fd7813786bf1cc03b08b204007711575f144..b222890e7bdff2c1470841677a99d4423f9c9d7f 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java +@@ -36,7 +36,7 @@ public class NetherSurfaceBuilder extends SurfaceBuilder= 0; --k2) { ++ for (int k2 = height; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height + blockposition_mutableblockposition.set(k1, k2, l1); + BlockState iblockdata4 = chunk.getBlockState(blockposition_mutableblockposition); + diff --git a/patches/server-remapped/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/patches/server-remapped/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch new file mode 100644 index 0000000000..c7a761474b --- /dev/null +++ b/patches/server-remapped/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: mbax +Date: Mon, 17 Aug 2020 12:17:37 -0400 +Subject: [PATCH] Fix regex mistake in CB NBT int deserialization + +The existing regex is too open and allows for the absence of any actual +number data, detecting an NBT entry of just the letter "i" in upper or +lower case. This causes a single-character NBT entry to be processed as +an integer ending in "i", passing an empty String to to Integer.parseInt, +triggering an exception in loading the item. + +This commit forces numbers to be present prior to the ending "i" +letter. + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java +index 94d46bc56b3bc4c4750fcfb1732eea0e49a04195..8ec09ff3b5aae4267b753bd715f0a9d4ef0381bd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java +@@ -19,7 +19,7 @@ import net.minecraft.nbt.TagParser; + public class CraftNBTTagConfigSerializer { + + private static final Pattern ARRAY = Pattern.compile("^\\[.*]"); +- private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)?i", Pattern.CASE_INSENSITIVE); ++ private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)i", Pattern.CASE_INSENSITIVE); // Paper - fix regex + private static final Pattern DOUBLE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", Pattern.CASE_INSENSITIVE); + private static final TagParser MOJANGSON_PARSER = new TagParser(new StringReader("")); + diff --git a/patches/server-remapped/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server-remapped/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch new file mode 100644 index 0000000000..d47ebc8c6e --- /dev/null +++ b/patches/server-remapped/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 23 Jul 2019 20:44:47 -0500 +Subject: [PATCH] Do not let the server load chunks from newer versions + +If the server attempts to load a chunk generated by a newer version of +the game, immediately stop the server to prevent data corruption. + +You can override this functionality at your own peril. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 0adf14af9841cd3a20a8b2c0c320eb06794ef261..f6a814f9305813eaafa56baa0327e0111cd4e38c 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -95,10 +95,24 @@ public class ChunkSerializer { + return holder.protoChunk; + } + ++ // Paper start ++ private static final int CURRENT_DATA_VERSION = SharedConstants.getCurrentVersion().getWorldVersion(); ++ private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion"); ++ // Paper end ++ + public static InProgressChunkHolder loadChunk(ServerLevel worldserver, StructureManager definedstructuremanager, PoiManager villageplace, ChunkPos chunkcoordintpair, CompoundTag nbttagcompound, boolean distinguish) { + ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); + // Paper end + ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); ++ // Paper start - Do NOT attempt to load chunks saved with newer versions ++ if (nbttagcompound.contains("DataVersion", 99)) { ++ int dataVersion = nbttagcompound.getInt("DataVersion"); ++ if (!JUST_CORRUPT_IT && dataVersion > CURRENT_DATA_VERSION) { ++ new RuntimeException("Server attempted to load chunk saved with newer version of minecraft! " + dataVersion + " > " + CURRENT_DATA_VERSION).printStackTrace(); ++ System.exit(1); ++ } ++ } ++ // Paper end + BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); + CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate + ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate diff --git a/patches/server-remapped/0545-Brand-support.patch b/patches/server-remapped/0545-Brand-support.patch new file mode 100644 index 0000000000..e134b27182 --- /dev/null +++ b/patches/server-remapped/0545-Brand-support.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DigitalRegent +Date: Sat, 11 Apr 2020 13:10:58 +0200 +Subject: [PATCH] Brand support + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index d264fca2737f83a0860394f7bb6b269ffe669594..ab6494f5a872bba5398bef0367b4d9257786f61e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -5,6 +5,7 @@ import com.google.common.primitives.Doubles; + import com.google.common.primitives.Floats; + import com.mojang.brigadier.ParseResults; + import com.mojang.brigadier.StringReader; ++import io.netty.buffer.Unpooled; + import io.netty.util.concurrent.Future; + import io.netty.util.concurrent.GenericFutureListener; + import it.unimi.dsi.fastutil.ints.Int2ShortMap; +@@ -37,6 +38,7 @@ import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.StringTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.Connection; ++import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.chat.ChatType; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.MutableComponent; +@@ -258,6 +260,8 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); + private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit + ++ private String clientBrandName = null; // Paper - Brand name ++ + public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { + this.server = server; + this.connection = connection; +@@ -2998,6 +3002,8 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register"); + private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister"); + ++ private static final ResourceLocation MINECRAFT_BRAND = new ResourceLocation("brand"); // Paper - Brand support ++ + @Override + public void handleCustomPayload(ServerboundCustomPayloadPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); +@@ -3025,6 +3031,16 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + try { + byte[] data = new byte[packet.data.readableBytes()]; + packet.data.readBytes(data); ++ ++ // Paper start - Brand support ++ if (packet.identifier.equals(MINECRAFT_BRAND)) { ++ try { ++ this.clientBrandName = new FriendlyByteBuf(Unpooled.copiedBuffer(data)).readUTF(256); ++ } catch (StringIndexOutOfBoundsException ex) { ++ this.clientBrandName = "illegal"; ++ } ++ } ++ // Paper end + craftServer.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packet.identifier.toString(), data); + } catch (Exception ex) { + ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); +@@ -3034,6 +3050,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + } + ++ // Paper start - brand support ++ public String getClientBrandName() { ++ return clientBrandName; ++ } ++ // Paper end ++ + public final boolean isDisconnected() { + return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 610eabd2e93f9efccee810c3b5a314bc3cc649d8..7aae63d22167dc1b3ec7e8bc8672855c2038007e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2385,6 +2385,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + // Paper end + }; + ++ // Paper start - brand support ++ @Override ++ public String getClientBrandName() { ++ return getHandle().connection != null ? getHandle().connection.getClientBrandName() : null; ++ } ++ // Paper end ++ + public Player.Spigot spigot() + { + return spigot; diff --git a/patches/server-remapped/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch b/patches/server-remapped/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch new file mode 100644 index 0000000000..d3257fe8be --- /dev/null +++ b/patches/server-remapped/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Thu, 20 Aug 2020 19:24:13 -0700 +Subject: [PATCH] Fix MC-99259 Wither Boss Bar doesn't update until + invulnerability period is over + + +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +index edd231568b75330d0cffbecb03a7e9dbc55d5f94..1f330d852eb9b3a36570542e10a88ae065798714 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -391,8 +391,9 @@ public class WitherBoss extends Monster implements RangedAttackMob { + this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + +- this.bossEvent.setPercent(this.getHealth() / this.getMaxHealth()); ++ //this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Moved down + } ++ this.bossEvent.setPercent(this.getHealth() / this.getMaxHealth()); // Paper - Fix MC-99259 (Boss bar does not update until Wither invulnerability period ends) + } + + public static boolean canDestroy(BlockState block) { diff --git a/patches/server-remapped/0547-Fix-MC-197271.patch b/patches/server-remapped/0547-Fix-MC-197271.patch new file mode 100644 index 0000000000..14ad3b04d2 --- /dev/null +++ b/patches/server-remapped/0547-Fix-MC-197271.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ishland +Date: Sun, 23 Aug 2020 10:57:44 +0200 +Subject: [PATCH] Fix MC-197271 + +This patch only fixes an issue for servers running OpenJ9. + +diff --git a/src/main/java/net/minecraft/data/BuiltinRegistries.java b/src/main/java/net/minecraft/data/BuiltinRegistries.java +index d64cebb4431664762a14670c7d9d782dd7894ed5..0c403ea85f7ea20f2f978e06313f8675abf204b6 100644 +--- a/src/main/java/net/minecraft/data/BuiltinRegistries.java ++++ b/src/main/java/net/minecraft/data/BuiltinRegistries.java +@@ -48,11 +48,11 @@ public class BuiltinRegistries { + public static final Registry PROCESSOR_LIST = registerSimple(Registry.PROCESSOR_LIST_REGISTRY, () -> { + return ProcessorLists.b; + }); +- public static final Registry TEMPLATE_POOL = registerSimple(Registry.TEMPLATE_POOL_REGISTRY, Pools::bootstrap); ++ public static final Registry TEMPLATE_POOL = registerSimple(Registry.TEMPLATE_POOL_REGISTRY, () -> Pools.bootstrap()); // Paper - MC-197271 + public static final Registry BIOME = registerSimple(Registry.BIOME_REGISTRY, () -> { + return Biomes.PLAINS; + }); +- public static final Registry NOISE_GENERATOR_SETTINGS = registerSimple(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY, NoiseGeneratorSettings::bootstrap); ++ public static final Registry NOISE_GENERATOR_SETTINGS = registerSimple(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY, () -> NoiseGeneratorSettings.bootstrap()); // Paper - MC-197271 + + private static Registry registerSimple(ResourceKey> registryRef, Supplier defaultValueSupplier) { + return registerSimple(registryRef, Lifecycle.stable(), defaultValueSupplier); +@@ -66,9 +66,9 @@ public class BuiltinRegistries { + ResourceLocation minecraftkey = registryRef.location(); + + BuiltinRegistries.LOADERS.put(minecraftkey, defaultValueSupplier); +- WritableRegistry iregistrywritable = BuiltinRegistries.WRITABLE_REGISTRY; ++ WritableRegistry iregistrywritable = (WritableRegistry) BuiltinRegistries.WRITABLE_REGISTRY; // Paper - decompile fix + +- return (WritableRegistry) iregistrywritable.register(registryRef, (Object) registry, lifecycle); ++ return (R) iregistrywritable.register((ResourceKey) registryRef, registry, lifecycle); // Paper - decompile fix + } + + public static T register(Registry registry, String id, T object) { +@@ -76,11 +76,11 @@ public class BuiltinRegistries { + } + + public static T register(Registry registry, ResourceLocation id, T object) { +- return ((WritableRegistry) registry).register(ResourceKey.create(registry.key(), id), object, Lifecycle.stable()); ++ return (T) ((WritableRegistry) registry).register(ResourceKey.create(registry.key(), id), object, Lifecycle.stable()); // Paper - decompile fix + } + + public static T registerMapping(Registry iregistry, int rawId, ResourceKey resourcekey, T object) { +- return ((WritableRegistry) iregistry).registerMapping(rawId, resourcekey, object, Lifecycle.stable()); ++ return (T) ((WritableRegistry) iregistry).registerMapping(rawId, resourcekey, object, Lifecycle.stable()); // Paper - decompile fix + } + + public static void bootstrap() {} diff --git a/patches/server-remapped/0548-MC-197883-Bandaid-decode-issue.patch b/patches/server-remapped/0548-MC-197883-Bandaid-decode-issue.patch new file mode 100644 index 0000000000..fd35ea34e4 --- /dev/null +++ b/patches/server-remapped/0548-MC-197883-Bandaid-decode-issue.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 21 Aug 2020 21:05:28 -0400 +Subject: [PATCH] MC-197883: Bandaid decode issue + +Mojang has a mix of type and name in the data sets, but you can only +use one. + +This will retry as name if type is asked for and not found. + +diff --git a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java +index de7d1e5e0319c65775d932144c268c2d55bb7dc7..bd6a0e1b5454e880a4f2a16be7dc8da64b73e11d 100644 +--- a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java ++++ b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java +@@ -48,7 +48,12 @@ public class KeyDispatchCodec extends MapCodec { + + @Override + public DataResult decode(final DynamicOps ops, final MapLike input) { +- final T elementName = input.get(typeKey); ++ // Paper start - bandaid MC-197883 ++ T elementName = input.get(typeKey); ++ if (elementName == null && "type".equals(typeKey)) { ++ elementName = input.get("name"); ++ } ++ // Paper end + if (elementName == null) { + return DataResult.error("Input does not contain a key [" + typeKey + "]: " + input); + } diff --git a/patches/server-remapped/0549-Add-setMaxPlayers-API.patch b/patches/server-remapped/0549-Add-setMaxPlayers-API.patch new file mode 100644 index 0000000000..bfd99ce60a --- /dev/null +++ b/patches/server-remapped/0549-Add-setMaxPlayers-API.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 22 Aug 2020 23:59:30 +0200 +Subject: [PATCH] Add #setMaxPlayers API + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index b76735531ef96f9d4c870a5107feea01524a7670..7e44c911f4abc5c7d0e89513bf2cfc3516f13492 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -141,7 +141,7 @@ public abstract class PlayerList { + public final PlayerDataStorage playerIo; + private boolean doWhiteList; + private final RegistryAccess.RegistryHolder registryHolder; +- protected final int maxPlayers; ++ protected int maxPlayers; public final void setMaxPlayers(int maxPlayers) { this.maxPlayers = maxPlayers; } // Paper - remove final and add setter + private int viewDistance; + private GameType overrideGameMode; + private boolean allowCheatsForAllPlayers; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index e301aee53b19fc3f93a36d0ed03a649741123bfa..e599be15af17e5e45d2b694c30140cc4a787a7f5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -613,6 +613,13 @@ public final class CraftServer implements Server { + return playerList.getMaxPlayers(); + } + ++ // Paper start ++ @Override ++ public void setMaxPlayers(int maxPlayers) { ++ this.playerList.setMaxPlayers(maxPlayers); ++ } ++ // Paper end ++ + // NOTE: These are dependent on the corresponding call in MinecraftServer + // so if that changes this will need to as well + @Override diff --git a/patches/server-remapped/0550-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server-remapped/0550-Add-playPickupItemAnimation-to-LivingEntity.patch new file mode 100644 index 0000000000..e3089f12ce --- /dev/null +++ b/patches/server-remapped/0550-Add-playPickupItemAnimation-to-LivingEntity.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 23 Aug 2020 19:36:22 +0200 +Subject: [PATCH] Add playPickupItemAnimation to LivingEntity + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 067eaf1e05ced344eb168431403f3fe786eafddf..eb136af0f99f5d7520ceabb98cefd5a01122872c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -806,5 +806,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + ((Mob) getHandle()).getJumpControl().jump(); + } + } ++ ++ @Override ++ public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { ++ getHandle().take(((CraftItem) item).getHandle(), quantity); ++ } + // Paper end + } diff --git a/patches/server-remapped/0551-Don-t-require-FACING-data.patch b/patches/server-remapped/0551-Don-t-require-FACING-data.patch new file mode 100644 index 0000000000..5ecdef5062 --- /dev/null +++ b/patches/server-remapped/0551-Don-t-require-FACING-data.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sun, 23 Aug 2020 19:01:04 +0200 +Subject: [PATCH] Don't require FACING data + + +diff --git a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +index f7e60cdfa0b3f5970a897b5d52aaa72210f2fa57..ab8e69f9fc38012844ce01bd0cc5be8de2fcf4ab 100644 +--- a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +@@ -14,20 +14,22 @@ import org.bukkit.event.block.BlockDispenseEvent; + // CraftBukkit end + + public class DefaultDispenseItemBehavior implements DispenseItemBehavior { ++ private Direction enumdirection; // Paper + + public DefaultDispenseItemBehavior() {} + + @Override + public final ItemStack dispense(BlockSource pointer, ItemStack stack) { ++ enumdirection = pointer.getBlockState().getValue(DispenserBlock.FACING); // Paper - cache facing direction + ItemStack itemstack1 = this.execute(pointer, stack); + + this.playSound(pointer); +- this.playAnimation(pointer, (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING)); ++ this.playAnimation(pointer, enumdirection); // Paper - cache facing direction + return itemstack1; + } + + protected ItemStack execute(BlockSource pointer, ItemStack stack) { +- Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING); ++ // Paper - cached enum direction + Position iposition = DispenserBlock.getDispensePosition(pointer); + ItemStack itemstack1 = stack.split(1); + diff --git a/patches/server-remapped/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server-remapped/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch new file mode 100644 index 0000000000..7947c73149 --- /dev/null +++ b/patches/server-remapped/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 22 Aug 2020 23:36:21 +0200 +Subject: [PATCH] Fix SpawnChangeEvent not firing for all use-cases + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 61aee2c109614a014149ae5a15ad2a28c796cb9d..22266fda4de9b5fbace3b8e55ce390b8d7e75a65 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1981,12 +1981,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + // Paper end + ++ public final void setSpawn(BlockPos blockposition, float f) { this.setDefaultSpawnPos(blockposition, f); } // Paper - OBFHELPER + public void setDefaultSpawnPos(BlockPos pos, float angle) { + // Paper - configurable spawn radius + BlockPos prevSpawn = this.getSpawn(); + //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); + + this.levelData.setSpawn(pos, angle); ++ new org.bukkit.event.world.SpawnChangeEvent(getWorld(), MCUtil.toLocation(this, prevSpawn)).callEvent(); // Paper + if (this.keepSpawnInMemory) { + // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add + this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 793b1309528671ce822d5a484ff9e40d6eba4e9d..37513a1774f5a6611338c1b90018b974238ddbf6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -371,11 +371,13 @@ public class CraftWorld implements World { + public boolean setSpawnLocation(int x, int y, int z, float angle) { + try { + Location previousLocation = getSpawnLocation(); +- world.levelData.setSpawn(new BlockPos(x, y, z), angle); ++ world.setSpawn(new BlockPos(x, y, z), angle); // Paper - use WorldServer#setSpawn + ++ // Paper start - move to nms.World + // Notify anyone who's listening. +- SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); +- server.getPluginManager().callEvent(event); ++ // SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); ++ // server.getPluginManager().callEvent(event); ++ // Paper end + + return true; + } catch (Exception e) { diff --git a/patches/server-remapped/0553-Add-moon-phase-API.patch b/patches/server-remapped/0553-Add-moon-phase-API.patch new file mode 100644 index 0000000000..bd3ee0c1e2 --- /dev/null +++ b/patches/server-remapped/0553-Add-moon-phase-API.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Aug 2020 16:32:11 +0200 +Subject: [PATCH] Add moon phase API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 37513a1774f5a6611338c1b90018b974238ddbf6..28bf53bc9fca21f57cd4851adf508d833ecdd33b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -310,6 +310,11 @@ public class CraftWorld implements World { + public int getPlayerCount() { + return world.players.size(); + } ++ ++ @Override ++ public io.papermc.paper.world.MoonPhase getMoonPhase() { ++ return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); ++ } + // Paper end + + private static final Random rand = new Random(); diff --git a/patches/server-remapped/0554-Prevent-headless-pistons-from-being-created.patch b/patches/server-remapped/0554-Prevent-headless-pistons-from-being-created.patch new file mode 100644 index 0000000000..15edeb8af6 --- /dev/null +++ b/patches/server-remapped/0554-Prevent-headless-pistons-from-being-created.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: commandblockguy +Date: Fri, 14 Aug 2020 14:44:14 -0500 +Subject: [PATCH] Prevent headless pistons from being created + +Prevent headless pistons from being created by explosions or tree/mushroom growth. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb..faa1b775e45563b93ac1d5b904938b1f5ad8d80c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -441,6 +441,12 @@ public class PaperConfig { + set("settings.unsupported-settings.allow-tnt-duplication", null); + } + ++ public static boolean allowHeadlessPistons; ++ private static void allowHeadlessPistons() { ++ config.set("settings.unsupported-settings.allow-headless-pistons-readme", "This setting controls if players should be able to create headless pistons."); ++ allowHeadlessPistons = getBoolean("settings.unsupported-settings.allow-headless-pistons", false); ++ } ++ + public static int playerAutoSaveRate = -1; + public static int maxPlayerAutoSavePerTick = 10; + private static void playerAutoSaveRate() { +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 0f0a5fa2be5a7c69291b593a04cad83e069ba5b1..f7ca5294fe571770e3b0036e92563c5a099f76b1 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -15,6 +15,7 @@ import java.util.Random; + import java.util.Set; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; + import net.minecraft.core.Vec3i; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.server.level.ServerLevel; +@@ -35,6 +36,8 @@ import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.piston.PistonHeadBlock; ++import net.minecraft.world.level.block.piston.PistonMovingBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.storage.loot.LootContext; +@@ -161,6 +164,15 @@ public class Explosion { + + if (f > 0.0F && this.damageCalculator.a(this, this.level, blockposition, iblockdata, f) && blockposition.getY() < 256 && blockposition.getY() >= 0) { // CraftBukkit - don't wrap explosions + set.add(blockposition); ++ // Paper start - prevent headless pistons from forming ++ if (!com.destroystokyo.paper.PaperConfig.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) { ++ BlockEntity extension = this.level.getBlockEntity(blockposition); ++ if (extension instanceof PistonMovingBlockEntity && ((PistonMovingBlockEntity) extension).isHead()) { ++ Direction direction = iblockdata.getValue(PistonHeadBlock.FACING); ++ set.add(blockposition.relative(direction.getOpposite())); ++ } ++ } ++ // Paper end + } + + d4 += d0 * 0.30000001192092896D; +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +index 001e90da8b09e16b6df4849a5bac4f4821000c94..81f3c6fb7bab9de364537d3f3b2ea0f32795e5f1 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +@@ -65,6 +65,8 @@ public class PistonMovingBlockEntity extends BlockEntity implements TickableBloc + return this.direction; + } + ++ public final boolean isHead() { return this.isSourcePiston(); } // Paper - OBFHELPER ++ + public boolean isSourcePiston() { + return this.isSourcePiston; + } diff --git a/patches/server-remapped/0555-Add-BellRingEvent.patch b/patches/server-remapped/0555-Add-BellRingEvent.patch new file mode 100644 index 0000000000..05dfb6c0bb --- /dev/null +++ b/patches/server-remapped/0555-Add-BellRingEvent.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Eearslya Sleiarion +Date: Sun, 23 Aug 2020 13:04:02 +0200 +Subject: [PATCH] Add BellRingEvent + +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/net/minecraft/world/level/block/BellBlock.java b/src/main/java/net/minecraft/world/level/block/BellBlock.java +index affae471e50354bfa9594e188e6dcea183b9b5c9..dc5dc9e533c71908b7a9a3cc9e614bd4a0dcde98 100644 +--- a/src/main/java/net/minecraft/world/level/block/BellBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BellBlock.java +@@ -1,8 +1,11 @@ + package net.minecraft.world.level.block; + ++import io.papermc.paper.event.block.BellRingEvent; ++ + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +@@ -89,7 +92,7 @@ public class BellBlock extends BaseEntityBlock { + boolean flag1 = !flag || this.isProperHit(state, enumdirection, movingobjectpositionblock.getLocation().y - (double) blockposition.getY()); + + if (flag1) { +- boolean flag2 = this.attemptToRing(world, blockposition, enumdirection); ++ boolean flag2 = this.handleBellRing(world, blockposition, enumdirection, entityhuman); // Paper + + if (flag2 && entityhuman != null) { + entityhuman.awardStat(Stats.BELL_RING); +@@ -123,15 +126,21 @@ public class BellBlock extends BaseEntityBlock { + } + + public boolean attemptToRing(Level world, BlockPos pos, @Nullable Direction enumdirection) { +- BlockEntity tileentity = world.getBlockEntity(pos); ++ // Paper start - add ringer param ++ return this.handleBellRing(world, pos, enumdirection, null); ++ } ++ public boolean handleBellRing(Level world, BlockPos blockposition, @Nullable Direction enumdirection, @Nullable Entity ringer) { ++ // Paper end ++ BlockEntity tileentity = world.getBlockEntity(blockposition); + + if (!world.isClientSide && tileentity instanceof BellBlockEntity) { + if (enumdirection == null) { +- enumdirection = (Direction) world.getBlockState(pos).getValue(BellBlock.FACING); ++ enumdirection = (Direction) world.getBlockState(blockposition).getValue(BellBlock.FACING); + } + ++ if (!new BellRingEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, blockposition)), ringer == null ? null : ringer.getBukkitEntity()).callEvent()) return false; // Paper - BellRingEvent + ((BellBlockEntity) tileentity).onHit(enumdirection); +- world.playSound((Player) null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); ++ world.playSound((Player) null, blockposition, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); + return true; + } else { + return false; diff --git a/patches/server-remapped/0556-Add-zombie-targets-turtle-egg-config.patch b/patches/server-remapped/0556-Add-zombie-targets-turtle-egg-config.patch new file mode 100644 index 0000000000..d46a54fd32 --- /dev/null +++ b/patches/server-remapped/0556-Add-zombie-targets-turtle-egg-config.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Aug 2020 15:47:34 +0200 +Subject: [PATCH] Add zombie targets turtle egg config + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 978062774c1db286bfb9b0ffdef19d880b1f249b..36ecdfce84141ac731b827e469ac842f5c666259 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -668,4 +668,9 @@ public class PaperWorldConfig { + maxLightningFlashDistance = 512; // Vanilla value + } + } ++ ++ public boolean zombiesTargetTurtleEggs = true; ++ private void zombiesTargetTurtleEggs() { ++ zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 1e7c2c603b967c8c606efd94ce95a17c856f78d7..4105c1763d25824aac35d305a793823c1604eee8 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -104,7 +104,7 @@ public class Zombie extends Monster { + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); ++ if (level.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); // Paper + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.addBehaviourGoals(); diff --git a/patches/server-remapped/0557-Buffer-joins-to-world.patch b/patches/server-remapped/0557-Buffer-joins-to-world.patch new file mode 100644 index 0000000000..b9f930aa4e --- /dev/null +++ b/patches/server-remapped/0557-Buffer-joins-to-world.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Wed, 19 Aug 2020 05:05:54 +0100 +Subject: [PATCH] Buffer joins to world + +This patch buffers the number of logins which will attempt to join +the world per tick, this attempts to reduce the impact that join floods +has on the server + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index faa1b775e45563b93ac1d5b904938b1f5ad8d80c..545948f20efd6c8dd42140b565af94cd6b52b661 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -457,4 +457,9 @@ public class PaperConfig { + maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; + } + } ++ ++ public static int maxJoinsPerTick; ++ private static void maxJoinsPerTick() { ++ maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); ++ } + } +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index fc63df21aecd4721efdb45d4744666ed0b562c1b..6f7cbce5a049d87d4a0ed7cc4517cb4e8694efb5 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -32,6 +32,7 @@ import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; + import net.minecraft.network.protocol.game.ClientboundKeepAlivePacket; + import net.minecraft.network.protocol.game.ClientboundSetTitlesPacket; + import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.RunningOnDifferentThreadException; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.network.ServerGamePacketListenerImpl; +@@ -382,10 +383,22 @@ public class Connection extends SimpleChannelInboundHandler> { + } + // Paper end + ++ private static final int MAX_PER_TICK = com.destroystokyo.paper.PaperConfig.maxJoinsPerTick; // Paper ++ private static int joinAttemptsThisTick; // Paper ++ private static int currTick; // Paper + public void tick() { + this.p(); ++ // Paper start ++ if (currTick != MinecraftServer.currentTick) { ++ currTick = MinecraftServer.currentTick; ++ joinAttemptsThisTick = 0; ++ } ++ // Paper end + if (this.packetListener instanceof ServerLoginPacketListenerImpl) { ++ if ( ((ServerLoginPacketListenerImpl) this.packetListener).getLoginState() != ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT // Paper ++ || (joinAttemptsThisTick++ < MAX_PER_TICK)) { // Paper - limit the number of joins which can be processed each tick + ((ServerLoginPacketListenerImpl) this.packetListener).tick(); ++ } // Paper + } + + if (this.packetListener instanceof ServerGamePacketListenerImpl) { +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index e229c7735ba88be3d8721440104958408a2a075e..659bf14cf3c949b896d0333f893a3d5e16ab9c92 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -420,7 +420,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + return new GameProfile(uuid, profile.getName()); + } + +- static enum State { ++ public enum State { // Paper - package private -> public + + HELLO, KEY, AUTHENTICATING, NEGOTIATING, READY_TO_ACCEPT, DELAY_ACCEPT, ACCEPTED; + diff --git a/patches/server-remapped/0558-Optimize-redstone-algorithm.patch b/patches/server-remapped/0558-Optimize-redstone-algorithm.patch new file mode 100644 index 0000000000..002eed1eeb --- /dev/null +++ b/patches/server-remapped/0558-Optimize-redstone-algorithm.patch @@ -0,0 +1,1157 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: theosib +Date: Thu, 27 Sep 2018 01:43:35 -0600 +Subject: [PATCH] Optimize redstone algorithm + +Author: theosib +Co-authored-by: egg82 + +Original license: MIT + +This patch implements theosib's redstone algorithms to completely overhaul the way redstone works. +The new algorithms should be many times faster than current vanilla ones. +From the original author's comments, it looks like it shouldn't interfere with any redstone save for very extreme edge-cases. + +Surprisingly, not a lot was touched aside from a few obfuscation helpers and BlockRedstoneWire. +A lot of this code is self-contained in a helper class. + +Aside from making the obvious class/function renames and obfhelpers I didn't need to modify much. +Just added Bukkit's event system and took a few liberties with dead code and comment misspellings. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 36ecdfce84141ac731b827e469ac842f5c666259..02bb85364560784adea47c877c13291c3d016b86 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -673,4 +673,14 @@ public class PaperWorldConfig { + private void zombiesTargetTurtleEggs() { + zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); + } ++ ++ public boolean useEigencraftRedstone = false; ++ private void useEigencraftRedstone() { ++ useEigencraftRedstone = this.getBoolean("use-faster-eigencraft-redstone", false); ++ if (useEigencraftRedstone) { ++ log("Using Eigencraft redstone algorithm by theosib."); ++ } else { ++ log("Using vanilla redstone algorithm."); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java +new file mode 100644 +index 0000000000000000000000000000000000000000..19604f4d2d0cdf65cb9f164258c4435a5a3450bc +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java +@@ -0,0 +1,913 @@ ++package com.destroystokyo.paper.util; ++ ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.ThreadLocalRandom; ++import net.minecraft.core.BlockPos; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.item.Items; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.RedStoneWireBlock; ++import net.minecraft.world.level.block.state.BlockState; ++import org.bukkit.event.block.BlockRedstoneEvent; ++ ++import com.google.common.collect.Lists; ++import com.google.common.collect.Maps; ++ ++/** ++ * Used for the faster redstone algorithm. ++ * Original author: theosib ++ * Original license: MIT ++ * ++ * Ported to Paper and updated to 1.13 by egg82 ++ */ ++public class RedstoneWireTurbo { ++ /* ++ * This is Helper class for BlockRedstoneWire. It implements a minimally-invasive ++ * bolt-on accelerator that performs a breadth-first search through redstone wire blocks ++ * in order to more efficiently and deterministically compute new redstone wire power levels ++ * and determine the order in which other blocks should be updated. ++ * ++ * Features: ++ * - Changes to BlockRedstoneWire are very limited, no other classes are affected, and the ++ * choice between old and new redstone wire update algorithms is switchable on-line. ++ * - The vanilla implementation relied on World.notifyNeighborsOfStateChange for redstone ++ * wire blocks to communicate power level changes to each other, generating 36 block ++ * updates per call. This improved implementation propagates power level changes directly ++ * between redstone wire blocks. Redstone wire power levels are therefore computed more quickly, ++ * and block updates are sent only to non-redstone blocks, many of which may perform an ++ * action when informed of a change in redstone power level. (Note: Block updates are not ++ * the same as state changes to redstone wire. Wire block states are updated as soon ++ * as they are computed.) ++ * - Of the 36 block updates generated by a call to World.notifyNeighborsOfStateChange, ++ * 12 of them are obviously redundant (e.g. the west neighbor of the east neighbor). ++ * These are eliminated. ++ * - Updates to redstone wire and other connected blocks are propagated in a breath-first ++ * manner, radiating out from the initial trigger (a block update to a redstone wire ++ * from something other than redstone wire). ++ * - Updates are scheduled both deterministically and in an intuitive order, addressing bug ++ * MC-11193. ++ * - All redstone behavior that used to be locational now works the same in all locations. ++ * - All behaviors of redstone wire that used to be orientational now work the same in all ++ * orientations, as long as orientation can be determined; random otherwise. Some other ++ * redstone components still update directionally (e.g. switches), and this code can't ++ * compensate for that. ++ * - Information that is otherwise computed over and over again or which is expensive to ++ * to compute is cached for faster lookup. This includes coordinates of block position ++ * neighbors and block states that won't change behind our backs during the execution of ++ * this search algorithm. ++ * - Redundant block updates (both to redstone wire and to other blocks) are heavily ++ * consolidated. For worst-case scenarios (depowering of redstone wire) this results ++ * in a reduction of block updates by as much as 95% (factor of 1/21). Due to overheads, ++ * empirical testing shows a speedup better than 10x. This addresses bug MC-81098. ++ * ++ * Extensive testing has been performed to ensure that existing redstone contraptions still ++ * behave as expected. Results of early testing that identified undesirable behavior changes ++ * were addressed. Additionally, real-time performance testing revealed compute inefficiencies ++ * With earlier implementations of this accelerator. Some compatibility adjustments and ++ * performance optimizations resulted in harmless increases in block updates above the ++ * theoretical minimum. ++ * ++ * Only a single redstone machine was found to break: An instant dropper line hack that ++ * relies on powered rails and quasi-connectivity but doesn't work in all directions. The ++ * replacement is to lay redstone wire directly on top of the dropper line, which now works ++ * reliably in any direction. ++ * ++ * There are numerous other optimization that can be made, but those will be provided later in ++ * separate updates. This version is designed to be minimalistic. ++ * ++ * Many thanks to the following individuals for their help in testing this functionality: ++ * - pokechu22, _MethodZz_, WARBEN, NarcolepticFrog, CommandHelper (nessie), ilmango, ++ * OreoLamp, Xcom6000, tryashtar, RedCMD, Smokey95Dog, EDDxample, Rays Works, ++ * Nodnam, BlockyPlays, Grumm, NeunEinser, HelVince. ++ */ ++ ++ /* Reference to BlockRedstoneWire object, which uses this accelerator */ ++ private final RedStoneWireBlock wire; ++ ++ /* ++ * Implementation: ++ * ++ * RedstoneWire Blocks are updated in concentric rings or "layers" radiating out from the ++ * initial block update that came from a call to BlockRedstoneWire.neighborChanged(). ++ * All nodes put in Layer N are those with Manhattan distance N from the trigger ++ * position, reachable through connected redstone wire blocks. ++ * ++ * Layer 0 represents the trigger block position that was input to neighborChanged. ++ * Layer 1 contains the immediate neighbors of that position. ++ * Layer N contains the neighbors of blocks in layer N-1, not including ++ * those in previous layers. ++ * ++ * Layers enforce an update order that is a function of Manhattan distance ++ * from the initial coordinates input to neighborChanged. The same ++ * coordinates may appear in multiple layers, but redundant updates are minimized. ++ * Block updates are sent layer-by-layer. If multiple of a block's neighbors experience ++ * redstone wire changes before its layer is processed, then those updates will be merged. ++ * If a block's update has been sent, but its neighboring redstone changes ++ * after that, then another update will be sent. This preserves compatibility with ++ * machines that rely on zero-tick behavior, except that the new functionality is non- ++ * locational. ++ * ++ * Within each layer, updates are ordered left-to-right relative to the direction of ++ * information flow. This makes the implementation non-orientational. Only when ++ * this direction is ambiguous is randomness applied (intentionally). ++ */ ++ private List updateQueue0 = Lists.newArrayList(); ++ private List updateQueue1 = Lists.newArrayList(); ++ private List updateQueue2 = Lists.newArrayList(); ++ ++ public RedstoneWireTurbo(RedStoneWireBlock wire) { ++ this.wire = wire; ++ } ++ ++ /* ++ * Compute neighbors of a block. When a redstone wire value changes, previously it called ++ * World.notifyNeighborsOfStateChange. That lists immediately neighboring blocks in ++ * west, east, down, up, north, south order. For each of those neighbors, their own ++ * neighbors are updated in the same order. This generates 36 updates, but 12 of them are ++ * redundant; for instance the west neighbor of a block's east neighbor. ++ * ++ * Note that this ordering is only used to create the initial list of neighbors. Once ++ * the direction of signal flow is identified, the ordering of updates is completely ++ * reorganized. ++ */ ++ public static BlockPos[] computeAllNeighbors(final BlockPos pos) { ++ final int x = pos.getX(); ++ final int y = pos.getY(); ++ final int z = pos.getZ(); ++ final BlockPos[] n = new BlockPos[24]; ++ ++ // Immediate neighbors, in the same order as ++ // World.notifyNeighborsOfStateChange, etc.: ++ // west, east, down, up, north, south ++ n[0] = new BlockPos(x - 1, y, z); ++ n[1] = new BlockPos(x + 1, y, z); ++ n[2] = new BlockPos(x, y - 1, z); ++ n[3] = new BlockPos(x, y + 1, z); ++ n[4] = new BlockPos(x, y, z - 1); ++ n[5] = new BlockPos(x, y, z + 1); ++ ++ // Neighbors of neighbors, in the same order, ++ // except that duplicates are not included ++ n[6] = new BlockPos(x - 2, y, z); ++ n[7] = new BlockPos(x - 1, y - 1, z); ++ n[8] = new BlockPos(x - 1, y + 1, z); ++ n[9] = new BlockPos(x - 1, y, z - 1); ++ n[10] = new BlockPos(x - 1, y, z + 1); ++ n[11] = new BlockPos(x + 2, y, z); ++ n[12] = new BlockPos(x + 1, y - 1, z); ++ n[13] = new BlockPos(x + 1, y + 1, z); ++ n[14] = new BlockPos(x + 1, y, z - 1); ++ n[15] = new BlockPos(x + 1, y, z + 1); ++ n[16] = new BlockPos(x, y - 2, z); ++ n[17] = new BlockPos(x, y - 1, z - 1); ++ n[18] = new BlockPos(x, y - 1, z + 1); ++ n[19] = new BlockPos(x, y + 2, z); ++ n[20] = new BlockPos(x, y + 1, z - 1); ++ n[21] = new BlockPos(x, y + 1, z + 1); ++ n[22] = new BlockPos(x, y, z - 2); ++ n[23] = new BlockPos(x, y, z + 2); ++ return n; ++ } ++ ++ /* ++ * We only want redstone wires to update redstone wires that are ++ * immediately adjacent. Some more distant updates can result ++ * in cross-talk that (a) wastes time and (b) can make the update ++ * order unintuitive. Therefore (relative to the neighbor order ++ * computed by computeAllNeighbors), updates are not scheduled ++ * for redstone wire in those non-connecting positions. On the ++ * other hand, updates will always be sent to *other* types of blocks ++ * in any of the 24 neighboring positions. ++ */ ++ private static final boolean[] update_redstone = { ++ true, true, false, false, true, true, // 0 to 5 ++ false, true, true, false, false, false, // 6 to 11 ++ true, true, false, false, false, true, // 12 to 17 ++ true, false, true, true, false, false // 18 to 23 ++ }; ++ ++ // Internal numbering for cardinal directions ++ private static final int North = 0; ++ private static final int East = 1; ++ private static final int South = 2; ++ private static final int West = 3; ++ ++ /* ++ * These lookup tables completely remap neighbor positions into a left-to-right ++ * ordering, based on the cardinal direction that is determined to be forward. ++ * See below for more explanation. ++ */ ++ private static final int[] forward_is_north = {2, 3, 16, 19, 0, 4, 1, 5, 7, 8, 17, 20, 12, 13, 18, 21, 6, 9, 22, 14, 11, 10, 23, 15}; ++ private static final int[] forward_is_east = {2, 3, 16, 19, 4, 1, 5, 0, 17, 20, 12, 13, 18, 21, 7, 8, 22, 14, 11, 15, 23, 9, 6, 10}; ++ private static final int[] forward_is_south = {2, 3, 16, 19, 1, 5, 0, 4, 12, 13, 18, 21, 7, 8, 17, 20, 11, 15, 23, 10, 6, 14, 22, 9}; ++ private static final int[] forward_is_west = {2, 3, 16, 19, 5, 0, 4, 1, 18, 21, 7, 8, 17, 20, 12, 13, 23, 10, 6, 9, 22, 15, 11, 14}; ++ ++ /* For any orientation, we end up with the update order defined below. This order is relative to any redstone wire block ++ * that is itself having an update computed, and this center position is marked with C. ++ * - The update position marked 0 is computed first, and the one marked 23 is last. ++ * - Forward is determined by the local direction of information flow into position C from prior updates. ++ * - The first updates are scheduled for the four positions below and above C. ++ * - Then updates are scheduled for the four horizontal neighbors of C, followed by the positions below and above those neighbors. ++ * - Finally, updates are scheduled for the remaining positions with Manhattan distance 2 from C (at the same Y coordinate). ++ * - For a given horizontal distance from C, updates are scheduled starting from directly left and stepping clockwise to directly ++ * right. The remaining positions behind C are scheduled counterclockwise so as to maintain the left-to-right ordering. ++ * - If C is in layer N of the update schedule, then all 24 positions may be scheduled for layer N+1. For redstone wire, no ++ * updates are scheduled for positions that cannot directly connect. Additionally, the four positions above and below C ++ * are ALSO scheduled for layer N+2. ++ * - This update order was selected after experimenting with a number of alternative schedules, based on its compatibility ++ * with existing redstone designs and behaviors that were considered to be intuitive by various testers. WARBEN in particular ++ * made some of the most challenging test cases, but the 3-tick clocks (made by RedCMD) were also challenging to fix, ++ * along with the rail-based instant dropper line built by ilmango. Numerous others made test cases as well, including ++ * NarcolepticFrog, nessie, and Pokechu22. ++ * ++ * - The forward direction is determined locally. So when there are branches in the redstone wire, the left one will get updated ++ * before the right one. Each branch can have its own relative forward direction, resulting in the left side of a left branch ++ * having priority over the right branch of a left branch, which has priority over the left branch of a right branch, followed ++ * by the right branch of a right branch. And so forth. Since redstone power reduces to zero after a path distance of 15, ++ * that imposes a practical limit on the branching. Note that the branching is not tracked explicitly -- relative forward ++ * directions dictate relative sort order, which maintains the proper global ordering. This also makes it unnecessary to be ++ * concerned about branches meeting up with each other. ++ * ++ * ^ ++ * | ++ * Forward ++ * <-- Left Right --> ++ * ++ * 18 ++ * 10 17 5 19 11 ++ * 2 8 0 12 16 4 C 6 20 9 1 13 3 ++ * 14 21 7 23 15 ++ * Further 22 Further ++ * Down Down Up Up ++ * ++ * Backward ++ * | ++ * V ++ */ ++ ++ // This allows the above remapping tables to be looked up by cardial direction index ++ private static final int[][] reordering = { forward_is_north, forward_is_east, forward_is_south, forward_is_west }; ++ ++ /* ++ * Input: Array of UpdateNode objects in an order corresponding to the positions ++ * computed by computeAllNeighbors above. ++ * Output: Array of UpdateNode objects oriented using the above remapping tables ++ * corresponding to the identified heading (direction of information flow). ++ */ ++ private static void orientNeighbors(final UpdateNode[] src, final UpdateNode[] dst, final int heading) { ++ final int[] re = reordering[heading]; ++ for (int i = 0; i < 24; i++) { ++ dst[i] = src[re[i]]; ++ } ++ } ++ ++ /* ++ * Structure to keep track of redstone wire blocks and ++ * neighbors that will receive updates. ++ */ ++ private static class UpdateNode { ++ public static enum Type { ++ UNKNOWN, REDSTONE, OTHER ++ } ++ ++ BlockState currentState; // Keep track of redstone wire value ++ UpdateNode[] neighbor_nodes; // References to neighbors (directed graph edges) ++ BlockPos self; // UpdateNode's own position ++ BlockPos parent; // Which block pos spawned/updated this node ++ Type type = Type.UNKNOWN; // unknown, redstone wire, other type of block ++ int layer; // Highest layer this node is scheduled in ++ boolean visited; // To keep track of information flow direction, visited restone wire is marked ++ int xbias, zbias; // Remembers directionality of ancestor nodes; helps eliminate directional ambiguities. ++ } ++ ++ /* ++ * Keep track of all block positions discovered during search and their current states. ++ * We want to remember one entry for each position. ++ */ ++ private final Map nodeCache = Maps.newHashMap(); ++ ++ /* ++ * For a newly created UpdateNode object, determine what type of block it is. ++ */ ++ private void identifyNode(final Level worldIn, final UpdateNode upd1) { ++ final BlockPos pos = upd1.self; ++ final BlockState oldState = worldIn.getBlockState(pos); ++ upd1.currentState = oldState; ++ ++ // Some neighbors of redstone wire are other kinds of blocks. ++ // These need to receive block updates to inform them that ++ // redstone wire values have changed. ++ final Block block = oldState.getBlock(); ++ if (block != wire) { ++ // Mark this block as not redstone wire and therefore ++ // requiring updates ++ upd1.type = UpdateNode.Type.OTHER; ++ ++ // Non-redstone blocks may propagate updates, but those updates ++ // are not handled by this accelerator. Therefore, we do not ++ // expand this position's neighbors. ++ return; ++ } ++ ++ // One job of BlockRedstoneWire.neighborChanged is to convert ++ // redstone wires to items if the block beneath was removed. ++ // With this accelerator, BlockRedstoneWire.neighborChanged ++ // is only typically called for a single wire block, while ++ // others are processed internally by the breadth first search ++ // algorithm. To preserve this game behavior, this check must ++ // be replicated here. ++ if (!wire.canSurvive(null, worldIn, pos)) { ++ // Pop off the redstone dust ++ Block.popResource(worldIn, pos, new ItemStack(Items.REDSTONE)); // TODO ++ worldIn.setAir(pos); ++ ++ // Mark this position as not being redstone wire ++ upd1.type = UpdateNode.Type.OTHER; ++ ++ // Note: Sending updates to air blocks leads to an empty method. ++ // Testing shows this to be faster than explicitly avoiding updates to ++ // air blocks. ++ return; ++ } ++ ++ // If the above conditions fail, then this is a redstone wire block. ++ upd1.type = UpdateNode.Type.REDSTONE; ++ } ++ ++ /* ++ * Given which redstone wire blocks have been visited and not visited ++ * around the position currently being updated, compute the cardinal ++ * direction that is "forward." ++ * ++ * rx is the forward direction along the West/East axis ++ * rz is the forward direction along the North/South axis ++ */ ++ static private int computeHeading(final int rx, final int rz) { ++ // rx and rz can only take on values -1, 0, and 1, so we can ++ // compute a code number that allows us to use a single switch ++ // to determine the heading. ++ final int code = (rx + 1) + 3 * (rz + 1); ++ switch (code) { ++ case 0: { ++ // Both rx and rz are -1 (northwest) ++ // Randomly choose one to be forward. ++ final int j = ThreadLocalRandom.current().nextInt(0, 1); ++ return (j == 0) ? North : West; ++ } ++ case 1: { ++ // rx=0, rz=-1 ++ // Definitively North ++ return North; ++ } ++ case 2: { ++ // rx=1, rz=-1 (northeast) ++ // Choose randomly between north and east ++ final int j = ThreadLocalRandom.current().nextInt(0, 1); ++ return (j == 0) ? North : East; ++ } ++ case 3: { ++ // rx=-1, rz=0 ++ // Definitively West ++ return West; ++ } ++ case 4: { ++ // rx=0, rz=0 ++ // Heading is completely ambiguous. Choose ++ // randomly among the four cardinal directions. ++ return ThreadLocalRandom.current().nextInt(0, 4); ++ } ++ case 5: { ++ // rx=1, rz=0 ++ // Definitively East ++ return East; ++ } ++ case 6: { ++ // rx=-1, rz=1 (southwest) ++ // Choose randomly between south and west ++ final int j = ThreadLocalRandom.current().nextInt(0, 1); ++ return (j == 0) ? South : West; ++ } ++ case 7: { ++ // rx=0, rz=1 ++ // Definitively South ++ return South; ++ } ++ case 8: { ++ // rx=1, rz=1 (southeast) ++ // Choose randomly between south and east ++ final int j = ThreadLocalRandom.current().nextInt(0, 1); ++ return (j == 0) ? South : East; ++ } ++ } ++ ++ // We should never get here ++ return ThreadLocalRandom.current().nextInt(0, 4); ++ } ++ ++ // Select whether to use updateSurroundingRedstone from BlockRedstoneWire (old) ++ // or this helper class (new) ++ private static final boolean old_current_change = false; ++ ++ /* ++ * Process a node whose neighboring redstone wire has experienced value changes. ++ */ ++ private void updateNode(final Level worldIn, final UpdateNode upd1, final int layer) { ++ final BlockPos pos = upd1.self; ++ ++ // Mark this redstone wire as having been visited so that it can be used ++ // to calculate direction of information flow. ++ upd1.visited = true; ++ ++ // Look up the last known state. ++ // Due to the way other redstone components are updated, we do not ++ // have to worry about a state changing behind our backs. The rare ++ // exception is handled by scheduleReentrantNeighborChanged. ++ final BlockState oldState = upd1.currentState; ++ ++ // Ask the wire block to compute its power level from its neighbors. ++ // This will also update the wire's power level and return a new ++ // state if it has changed. When a wire power level is changed, ++ // calculateCurrentChanges will immediately update the block state in the world ++ // and return the same value here to be cached in the corresponding ++ // UpdateNode object. ++ BlockState newState; ++ if (old_current_change) { ++ newState = wire.calculateCurrentChanges(worldIn, pos, pos, oldState); ++ } else { ++ // Looking up block state is slow. This accelerator includes a version of ++ // calculateCurrentChanges that uses cahed wire values for a ++ // significant performance boost. ++ newState = this.calculateCurrentChanges(worldIn, upd1); ++ } ++ ++ // Only inform neighbors if the state has changed ++ if (newState != oldState) { ++ // Store the new state ++ upd1.currentState = newState; ++ ++ // Inform neighbors of the change ++ propagateChanges(worldIn, upd1, layer); ++ } ++ } ++ ++ /* ++ * This identifies the neighboring positions of a new UpdateNode object, ++ * determines their types, and links those to into the graph. Then based on ++ * what nodes in the redstone wire graph have been visited, the neighbors ++ * are reordered left-to-right relative to the direction of information flow. ++ */ ++ private void findNeighbors(final Level worldIn, final UpdateNode upd1) { ++ final BlockPos pos = upd1.self; ++ ++ // Get the list of neighbor coordinates ++ final BlockPos[] neighbors = computeAllNeighbors(pos); ++ ++ // Temporary array of neighbors in cardinal ordering ++ final UpdateNode[] neighbor_nodes = new UpdateNode[24]; ++ ++ // Target array of neighbors sorted left-to-right ++ upd1.neighbor_nodes = new UpdateNode[24]; ++ ++ for (int i=0; i<24; i++) { ++ // Look up each neighbor in the node cache ++ final BlockPos pos2 = neighbors[i]; ++ UpdateNode upd2 = nodeCache.get(pos2); ++ if (upd2 == null) { ++ // If this is a previously unreached position, create ++ // a new update node, add it to the cache, and identify what it is. ++ upd2 = new UpdateNode(); ++ upd2.self = pos2; ++ upd2.parent = pos; ++ nodeCache.put(pos2, upd2); ++ identifyNode(worldIn, upd2); ++ } ++ ++ // For non-redstone blocks, any of the 24 neighboring positions ++ // should receive a block update. However, some block coordinates ++ // may contain a redstone wire that does not directly connect to the ++ // one being expanded. To avoid redundant calculations and confusing ++ // cross-talk, those neighboring positions are not included. ++ if (update_redstone[i] || upd2.type != UpdateNode.Type.REDSTONE) { ++ neighbor_nodes[i] = upd2; ++ } ++ } ++ ++ // Determine the directions from which the redstone signal may have come from. This ++ // checks for redstone wire at the same Y level and also Y+1 and Y-1, relative to the ++ // block being expanded. ++ final boolean fromWest = (neighbor_nodes[0].visited || neighbor_nodes[7].visited || neighbor_nodes[8].visited); ++ final boolean fromEast = (neighbor_nodes[1].visited || neighbor_nodes[12].visited || neighbor_nodes[13].visited); ++ final boolean fromNorth = (neighbor_nodes[4].visited || neighbor_nodes[17].visited || neighbor_nodes[20].visited); ++ final boolean fromSouth = (neighbor_nodes[5].visited || neighbor_nodes[18].visited || neighbor_nodes[21].visited); ++ ++ int cx = 0, cz = 0; ++ if (fromWest) cx += 1; ++ if (fromEast) cx -= 1; ++ if (fromNorth) cz += 1; ++ if (fromSouth) cz -= 1; ++ ++ int heading; ++ if (cx==0 && cz==0) { ++ // If there is no clear direction, try to inherit the heading from ancestor nodes. ++ heading = computeHeading(upd1.xbias, upd1.zbias); ++ ++ // Propagate that heading to descendant nodes. ++ for (int i=0; i<24; i++) { ++ final UpdateNode nn = neighbor_nodes[i]; ++ if (nn != null) { ++ nn.xbias = upd1.xbias; ++ nn.zbias = upd1.zbias; ++ } ++ } ++ } else { ++ if (cx != 0 && cz != 0) { ++ // If the heading is somewhat ambiguous, try to disambiguate based on ++ // ancestor nodes. ++ if (upd1.xbias != 0) cz = 0; ++ if (upd1.zbias != 0) cx = 0; ++ } ++ heading = computeHeading(cx, cz); ++ ++ // Propagate that heading to descendant nodes. ++ for (int i=0; i<24; i++) { ++ final UpdateNode nn = neighbor_nodes[i]; ++ if (nn != null) { ++ nn.xbias = cx; ++ nn.zbias = cz; ++ } ++ } ++ } ++ ++ // Reorder neighboring UpdateNode objects according to the forward direction ++ // determined above. ++ orientNeighbors(neighbor_nodes, upd1.neighbor_nodes, heading); ++ } ++ ++ /* ++ * For any redstone wire block in layer N, inform neighbors to recompute their states ++ * in layers N+1 and N+2; ++ */ ++ private void propagateChanges(final Level worldIn, final UpdateNode upd1, final int layer) { ++ if (upd1.neighbor_nodes == null) { ++ // If this node has not been expanded yet, find its neighbors ++ findNeighbors(worldIn, upd1); ++ } ++ ++ final BlockPos pos = upd1.self; ++ ++ // All neighbors may be scheduled for layer N+1 ++ final int layer1 = layer + 1; ++ ++ // If the node being updated (upd1) has already been expanded, then merely ++ // schedule updates to its neighbors. ++ for (int i = 0; i < 24; i++) { ++ final UpdateNode upd2 = upd1.neighbor_nodes[i]; ++ ++ // This test ensures that an UpdateNode is never scheduled to the same layer ++ // more than once. Also, skip non-connecting redstone wire blocks ++ if (upd2 != null && layer1 > upd2.layer) { ++ upd2.layer = layer1; ++ updateQueue1.add(upd2); ++ ++ // Keep track of which block updated this neighbor ++ upd2.parent = pos; ++ } ++ } ++ ++ // Nodes above and below are scheduled ALSO for layer N+2 ++ final int layer2 = layer + 2; ++ ++ // Repeat of the loop above, but only for the first four (above and below) neighbors ++ // and for layer N+2; ++ for (int i = 0; i < 4; i++) { ++ final UpdateNode upd2 = upd1.neighbor_nodes[i]; ++ if (upd2 != null && layer2 > upd2.layer) { ++ upd2.layer = layer2; ++ updateQueue2.add(upd2); ++ upd2.parent = pos; ++ } ++ } ++ } ++ ++ // The breadth-first search below will send block updates to blocks ++ // that are not redstone wire. If one of those updates results in ++ // a distant redstone wire getting an update, then this.neighborChanged ++ // will get called. This would be a reentrant call, and ++ // it is necessary to properly integrate those updates into the ++ // on-going search through redstone wire. Thus, we make the layer ++ // currently being processed visible at the object level. ++ ++ // The current layer being processed by the breadth-first search ++ private int currentWalkLayer = 0; ++ ++ private void shiftQueue() { ++ final List t = updateQueue0; ++ t.clear(); ++ updateQueue0 = updateQueue1; ++ updateQueue1 = updateQueue2; ++ updateQueue2 = t; ++ } ++ ++ /* ++ * Perform a breadth-first (layer by layer) traversal through redstone ++ * wire blocks, propagating value changes to neighbors in an order ++ * that is a function of distance from the initial call to ++ * this.neighborChanged. ++ */ ++ private void breadthFirstWalk(final Level worldIn) { ++ shiftQueue(); ++ currentWalkLayer = 1; ++ ++ // Loop over all layers ++ while (updateQueue0.size()>0 || updateQueue1.size()>0) { ++ // Get the set of blocks in this layer ++ final List thisLayer = updateQueue0; ++ ++ // Loop over all blocks in the layer. Recall that ++ // this is a List, preserving the insertion order of ++ // left-to-right based on direction of information flow. ++ for (UpdateNode upd : thisLayer) { ++ if (upd.type == UpdateNode.Type.REDSTONE) { ++ // If the node is is redstone wire, ++ // schedule updates to neighbors if its value ++ // has changed. ++ updateNode(worldIn, upd, currentWalkLayer); ++ } else { ++ // If this block is not redstone wire, send a block update. ++ // Redstone wire blocks get state updates, but they don't ++ // need block updates. Only non-redstone neighbors need updates. ++ ++ // World.neighborChanged is called from ++ // World.notifyNeighborsOfStateChange, and ++ // notifyNeighborsOfStateExcept. We don't use ++ // World.notifyNeighborsOfStateChange here, since we are ++ // already keeping track of all of the neighbor positions ++ // that need to be updated. All on its own, handling neighbors ++ // this way reduces block updates by 1/3 (24 instead of 36). ++ worldIn.neighborChanged(upd.self, wire, upd.parent); ++ } ++ } ++ ++ // Move on to the next layer ++ shiftQueue(); ++ currentWalkLayer++; ++ } ++ ++ currentWalkLayer = 0; ++ } ++ ++ /* ++ * Normally, when Minecraft is computing redstone wire power changes, and a wire power level ++ * change sends a block update to a neighboring functional component (e.g. piston, repeater, etc.), ++ * those updates are queued. Only once all redstone wire updates are complete will any component ++ * action generate any further block updates to redstone wire. Instant repeater lines, for instance, ++ * will process all wire updates for one redstone line, after which the pistons will zero-tick, ++ * after which the next redstone line performs all of its updates. Thus, each wire is processed in its ++ * own discrete wave. ++ * ++ * However, there are some corner cases where this pattern breaks, with a proof of concept discovered ++ * by Rays Works, which works the same in vanilla. The scenario is as follows: ++ * (1) A redstone wire is conducting a signal. ++ * (2) Part-way through that wave of updates, a neighbor is updated that causes an update to a completely ++ * separate redstone wire. ++ * (3) This results in a call to BlockRedstoneWire.neighborChanged for that other wire, in the middle of ++ * an already on-going propagation through the first wire. ++ * ++ * The vanilla code, being depth-first, would end up fully processing the second wire before going back ++ * to finish processing the first one. (Although technically, vanilla has no special concept of "being ++ * in the middle" of processing updates to a wire.) For the breadth-first algorithm, we give this ++ * situation special handling, where the updates for the second wire are incorporated into the schedule ++ * for the first wire, and then the callstack is allowed to unwind back to the on-going search loop in ++ * order to continue processing both the first and second wire in the order of distance from the initial ++ * trigger. ++ */ ++ private BlockState scheduleReentrantNeighborChanged(final Level worldIn, final BlockPos pos, final BlockState newState, final BlockPos source) { ++ if (source != null) { ++ // If the cause of the redstone wire update is known, we can use that to help determine ++ // direction of information flow. ++ UpdateNode src = nodeCache.get(source); ++ if (src == null) { ++ src = new UpdateNode(); ++ src.self = source; ++ src.parent = source; ++ src.visited = true; ++ identifyNode(worldIn, src); ++ nodeCache.put(source, src); ++ } ++ } ++ ++ // Find or generate a node for the redstone block position receiving the update ++ UpdateNode upd = nodeCache.get(pos); ++ if (upd == null) { ++ upd = new UpdateNode(); ++ upd.self = pos; ++ upd.parent = pos; ++ upd.visited = true; ++ identifyNode(worldIn, upd); ++ nodeCache.put(pos, upd); ++ } ++ upd.currentState = newState; ++ ++ // Receiving this block update may mean something in the world changed. ++ // Therefore we clear the cached block info about all neighbors of ++ // the position receiving the update and then re-identify what they are. ++ if (upd.neighbor_nodes != null) { ++ for (int i=0; i<24; i++) { ++ final UpdateNode upd2 = upd.neighbor_nodes[i]; ++ if (upd2 == null) continue; ++ upd2.type = UpdateNode.Type.UNKNOWN; ++ upd2.currentState = null; ++ identifyNode(worldIn, upd2); ++ } ++ } ++ ++ // The block at 'pos' is a redstone wire and has been updated already by calling ++ // wire.calculateCurrentChanges, so we don't schedule that. However, we do need ++ // to schedule its neighbors. By passing the current value of 'currentWalkLayer' to ++ // propagateChanges, the neighbors of 'pos' are scheduled for layers currentWalkLayer+1 ++ // and currentWalkLayer+2. ++ propagateChanges(worldIn, upd, currentWalkLayer); ++ ++ // Return here. The call stack will unwind back to the first call to ++ // updateSurroundingRedstone, whereupon the new updates just scheduled will ++ // be propagated. This also facilitates elimination of superfluous and ++ // redundant block updates. ++ return newState; ++ } ++ ++ /* ++ * New version of pre-existing updateSurroundingRedstone, which is called from ++ * wire.updateSurroundingRedstone, which is called from wire.neighborChanged and a ++ * few other methods in BlockRedstoneWire. This sets off the breadth-first ++ * walk through all redstone dust connected to the initial position triggered. ++ */ ++ public BlockState updateSurroundingRedstone(final Level worldIn, final BlockPos pos, final BlockState state, final BlockPos source) { ++ // Check this block's neighbors and see if its power level needs to change ++ // Use the calculateCurrentChanges method in BlockRedstoneWire since we have no ++ // cached block states at this point. ++ final BlockState newState = wire.calculateCurrentChanges(worldIn, pos, pos, state); ++ ++ // If no change, exit ++ if (newState == state) { ++ return state; ++ } ++ ++ // Check to see if this update was received during an on-going breadth first search ++ if (currentWalkLayer > 0 || nodeCache.size() > 0) { ++ // As breadthFirstWalk progresses, it sends block updates to neighbors. Some of those ++ // neighbors may affect the world so as to cause yet another redstone wire block to receive ++ // an update. If that happens, we need to integrate those redstone wire updates into the ++ // already on-going graph walk being performed by breadthFirstWalk. ++ return scheduleReentrantNeighborChanged(worldIn, pos, newState, source); ++ } ++ // If there are no on-going walks through redstone wire, then start a new walk. ++ ++ // If the source of the block update to the redstone wire at 'pos' is known, we can use ++ // that to help determine the direction of information flow. ++ if (source != null) { ++ final UpdateNode src = new UpdateNode(); ++ src.self = source; ++ src.parent = source; ++ src.visited = true; ++ nodeCache.put(source, src); ++ identifyNode(worldIn, src); ++ } ++ ++ // Create a node representing the block at 'pos', and then propagate updates ++ // to its neighbors. As stated above, the call to wire.calculateCurrentChanges ++ // already performs the update to the block at 'pos', so it is not added to the schedule. ++ final UpdateNode upd = new UpdateNode(); ++ upd.self = pos; ++ upd.parent = source!=null ? source : pos; ++ upd.currentState = newState; ++ upd.type = UpdateNode.Type.REDSTONE; ++ upd.visited = true; ++ nodeCache.put(pos, upd); ++ propagateChanges(worldIn, upd, 0); ++ ++ // Perform the walk over all directly reachable redstone wire blocks, propagating wire value ++ // updates in a breadth first order out from the initial update received for the block at 'pos'. ++ breadthFirstWalk(worldIn); ++ ++ // With the whole search completed, clear the list of all known blocks. ++ // We do not want to keep around state information that may be changed by other code. ++ // In theory, we could cache the neighbor block positions, but that is a separate ++ // optimization. ++ nodeCache.clear(); ++ ++ return newState; ++ } ++ ++ // For any array of neighbors in an UpdateNode object, these are always ++ // the indices of the four immediate neighbors at the same Y coordinate. ++ private static final int[] rs_neighbors = {4, 5, 6, 7}; ++ private static final int[] rs_neighbors_up = {9, 11, 13, 15}; ++ private static final int[] rs_neighbors_dn = {8, 10, 12, 14}; ++ ++ /* ++ * Updated calculateCurrentChanges that is optimized for speed and uses ++ * the UpdateNode's neighbor array to find the redstone states of neighbors ++ * that might power it. ++ */ ++ private BlockState calculateCurrentChanges(final Level worldIn, final UpdateNode upd) { ++ BlockState state = upd.currentState; ++ final int i = state.getValue(RedStoneWireBlock.POWER).intValue(); ++ int j = 0; ++ j = getMaxCurrentStrength(upd, j); ++ int l = 0; ++ ++ wire.setCanProvidePower(false); ++ // Unfortunately, World.isBlockIndirectlyGettingPowered is complicated, ++ // and I'm not ready to try to replicate even more functionality from ++ // elsewhere in Minecraft into this accelerator. So sadly, we must ++ // suffer the performance hit of this very expensive call. If there ++ // is consistency to what this call returns, we may be able to cache it. ++ final int k = worldIn.isBlockIndirectlyGettingPowered(upd.self); ++ wire.setCanProvidePower(true); ++ ++ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. ++ // If 'k' has the highest level of all neighbors, then the power level of this ++ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the ++ // following loop can affect the power level of the wire. Therefore, the loop is ++ // skipped if k is already 15. ++ if (k < 15) { ++ if (upd.neighbor_nodes == null) { ++ // If this node's neighbors are not known, expand the node ++ findNeighbors(worldIn, upd); ++ } ++ ++ // These remain constant, so pull them out of the loop. ++ // Regardless of which direction is forward, the UpdateNode for the ++ // position directly above the node being calculated is always ++ // at index 1. ++ UpdateNode center_up = upd.neighbor_nodes[1]; ++ boolean center_up_is_cube = center_up.currentState.isRedstoneConductor(worldIn, center_up.self); // TODO ++ ++ for (int m = 0; m < 4; m++) { ++ // Get the neighbor array index of each of the four cardinal ++ // neighbors. ++ int n = rs_neighbors[m]; ++ ++ // Get the max redstone power level of each of the cardinal ++ // neighbors ++ UpdateNode neighbor = upd.neighbor_nodes[n]; ++ l = getMaxCurrentStrength(neighbor, l); ++ ++ // Also check the positions above and below the cardinal ++ // neighbors ++ boolean neighbor_is_cube = neighbor.currentState.isRedstoneConductor(worldIn, neighbor.self); // TODO ++ if (!neighbor_is_cube) { ++ UpdateNode neighbor_down = upd.neighbor_nodes[rs_neighbors_dn[m]]; ++ l = getMaxCurrentStrength(neighbor_down, l); ++ } else ++ if (!center_up_is_cube) { ++ UpdateNode neighbor_up = upd.neighbor_nodes[rs_neighbors_up[m]]; ++ l = getMaxCurrentStrength(neighbor_up, l); ++ } ++ } ++ } ++ ++ // The new code sets this RedstoneWire block's power level to the highest neighbor ++ // minus 1. This usually results in wire power levels dropping by 2 at a time. ++ // This optimization alone has no impact on update order, only the number of updates. ++ j = l - 1; ++ ++ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will ++ // always be in the range of 0 to 15, the following if will correct that. ++ if (k > j) j = k; ++ ++ // egg82's amendment ++ // Adding Bukkit's BlockRedstoneEvent - er.. event. ++ if (i != j) { ++ BlockRedstoneEvent event = new BlockRedstoneEvent(worldIn.getWorld().getBlockAt(upd.self.getX(), upd.self.getY(), upd.self.getZ()), i, j); ++ worldIn.getCraftServer().getPluginManager().callEvent(event); ++ j = event.getNewCurrent(); ++ } ++ ++ if (i != j) { ++ // If the power level has changed from its previous value, compute a new state ++ // and set it in the world. ++ // Possible optimization: Don't commit state changes to the world until they ++ // need to be known by some nearby non-redstone-wire block. ++ BlockPos pos = new BlockPos(upd.self.getX(), upd.self.getY(), upd.self.getZ()); ++ if (wire.canSurvive(null, worldIn, pos)) { ++ state = state.setValue(RedStoneWireBlock.POWER, Integer.valueOf(j)); ++ worldIn.setBlock(upd.self, state, 2); ++ } ++ } ++ ++ return state; ++ } ++ ++ /* ++ * Optimized function to compute a redstone wire's power level based on cached ++ * state. ++ */ ++ private static int getMaxCurrentStrength(final UpdateNode upd, final int strength) { ++ if (upd.type != UpdateNode.Type.REDSTONE) return strength; ++ final int i = upd.currentState.getValue(RedStoneWireBlock.POWER).intValue(); ++ return i > strength ? i : strength; ++ } ++} +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 9b50b8030174338c04b60d441b980131e1d593e4..ebb92f88e0402681c47834bcf45e6b236748289a 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -659,6 +659,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + } + ++ public void neighborChanged(BlockPos pos, Block blockIn, BlockPos fromPos) { neighborChanged(pos, blockIn, fromPos); } // Paper - OBFHELPER + public void neighborChanged(BlockPos sourcePos, Block sourceBlock, BlockPos neighborPos) { + if (!this.isClientSide) { + BlockState iblockdata = this.getBlockState(sourcePos); +@@ -1287,6 +1288,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return this.getSignal(pos.below(), Direction.DOWN) > 0 ? true : (this.getSignal(pos.above(), Direction.UP) > 0 ? true : (this.getSignal(pos.north(), Direction.NORTH) > 0 ? true : (this.getSignal(pos.south(), Direction.SOUTH) > 0 ? true : (this.getSignal(pos.west(), Direction.WEST) > 0 ? true : this.getSignal(pos.east(), Direction.EAST) > 0)))); + } + ++ public int isBlockIndirectlyGettingPowered(BlockPos pos) { return this.getBestNeighborSignal(pos); } // Paper - OBFHELPER + public int getBestNeighborSignal(BlockPos pos) { + int i = 0; + Direction[] aenumdirection = Level.DIRECTIONS; +diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java +index 7318536fe89cddda305007a9ab115970bf18f65d..e5558b73c6159e4c1901d286535a7875924434e9 100644 +--- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.level.block; + ++import com.destroystokyo.paper.PaperConfig; ++import com.destroystokyo.paper.util.RedstoneWireTurbo; + import com.google.common.collect.ImmutableMap; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; +@@ -49,7 +51,7 @@ public class RedStoneWireBlock extends Block { + private final Map SHAPES_CACHE = Maps.newHashMap(); + private static final Vector3f[] COLORS = new Vector3f[16]; + private final BlockState crossState; +- private boolean shouldSignal = true; ++ private boolean shouldSignal = true; public final boolean canProvidePower() { return this.shouldSignal; } public final void setCanProvidePower(boolean value) { this.shouldSignal = value; } // Paper - OBFHELPER + + public RedStoneWireBlock(BlockBehaviour.Properties settings) { + super(settings); +@@ -236,6 +238,121 @@ public class RedStoneWireBlock extends Block { + return floor.isFaceSturdy(world, pos, Direction.UP) || floor.is(Blocks.HOPPER); + } + ++ // Paper start - Optimize redstone ++ // The bulk of the new functionality is found in RedstoneWireTurbo.java ++ RedstoneWireTurbo turbo = new RedstoneWireTurbo(this); ++ ++ /* ++ * Modified version of pre-existing updateSurroundingRedstone, which is called from ++ * this.neighborChanged and a few other methods in this class. ++ * Note: Added 'source' argument so as to help determine direction of information flow ++ */ ++ private void updateSurroundingRedstone(Level worldIn, BlockPos pos, BlockState state, BlockPos source) { ++ if (worldIn.paperConfig.useEigencraftRedstone) { ++ turbo.updateSurroundingRedstone(worldIn, pos, state, source); ++ return; ++ } ++ updatePowerStrength(worldIn, pos, state); ++ } ++ ++ /* ++ * Slightly modified method to compute redstone wire power levels from neighboring blocks. ++ * Modifications cut the number of power level changes by about 45% from vanilla, and this ++ * optimization synergizes well with the breadth-first search implemented in ++ * RedstoneWireTurbo. ++ * Note: RedstoneWireTurbo contains a faster version of this code. ++ * Note: Made this public so that RedstoneWireTurbo can access it. ++ */ ++ public BlockState calculateCurrentChanges(Level worldIn, BlockPos pos1, BlockPos pos2, BlockState state) { ++ BlockState iblockstate = state; ++ int i = state.getValue(POWER); ++ int j = 0; ++ j = this.getPower(j, worldIn.getBlockState(pos2)); ++ this.setCanProvidePower(false); ++ int k = worldIn.isBlockIndirectlyGettingPowered(pos1); ++ this.setCanProvidePower(true); ++ ++ if (!worldIn.paperConfig.useEigencraftRedstone) { ++ // This code is totally redundant to if statements just below the loop. ++ if (k > 0 && k > j - 1) { ++ j = k; ++ } ++ } ++ ++ int l = 0; ++ ++ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. ++ // If 'k' has the highest level of all neighbors, then the power level of this ++ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the ++ // following loop can affect the power level of the wire. Therefore, the loop is ++ // skipped if k is already 15. ++ if (!worldIn.paperConfig.useEigencraftRedstone || k < 15) { ++ for (Direction enumfacing : Direction.Plane.HORIZONTAL) { ++ BlockPos blockpos = pos1.relative(enumfacing); ++ boolean flag = blockpos.getX() != pos2.getX() || blockpos.getZ() != pos2.getZ(); ++ ++ if (flag) { ++ l = this.getPower(l, worldIn.getBlockState(blockpos)); ++ } ++ ++ if (worldIn.getBlockState(blockpos).isRedstoneConductor(worldIn, blockpos) && !worldIn.getBlockState(pos1.above()).isRedstoneConductor(worldIn, pos1)) { ++ if (flag && pos1.getY() >= pos2.getY()) { ++ l = this.getPower(l, worldIn.getBlockState(blockpos.above())); ++ } ++ } else if (!worldIn.getBlockState(blockpos).isRedstoneConductor(worldIn, blockpos) && flag && pos1.getY() <= pos2.getY()) { ++ l = this.getPower(l, worldIn.getBlockState(blockpos.below())); ++ } ++ } ++ } ++ ++ if (!worldIn.paperConfig.useEigencraftRedstone) { ++ // The old code would decrement the wire value only by 1 at a time. ++ if (l > j) { ++ j = l - 1; ++ } else if (j > 0) { ++ --j; ++ } else { ++ j = 0; ++ } ++ ++ if (k > j - 1) { ++ j = k; ++ } ++ } else { ++ // The new code sets this RedstoneWire block's power level to the highest neighbor ++ // minus 1. This usually results in wire power levels dropping by 2 at a time. ++ // This optimization alone has no impact on update order, only the number of updates. ++ j = l - 1; ++ ++ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will ++ // always be in the range of 0 to 15, the following if will correct that. ++ if (k > j) j = k; ++ } ++ ++ if (i != j) { ++ state = state.setValue(POWER, j); ++ ++ if (worldIn.getBlockState(pos1) == iblockstate) { ++ worldIn.setBlock(pos1, state, 2); ++ } ++ ++ // 1.16(.1?) dropped the need for blocks needing updates. ++ // Whether this is necessary after all is to be seen. ++// if (!worldIn.paperConfig.useEigencraftRedstone) { ++// // The new search algorithm keeps track of blocks needing updates in its own data structures, ++// // so only add anything to blocksNeedingUpdate if we're using the vanilla update algorithm. ++// this.getBlocksNeedingUpdate().add(pos1); ++// ++// for (EnumDirection enumfacing1 : EnumDirection.values()) { ++// this.getBlocksNeedingUpdate().add(pos1.shift(enumfacing1)); ++// } ++// } ++ } ++ ++ return state; ++ } ++ // Paper end ++ + private void updatePowerStrength(Level world, BlockPos pos, BlockState state) { + int i = this.calculateTargetStrength(world, pos); + +@@ -305,6 +422,8 @@ public class RedStoneWireBlock extends Block { + return Math.max(i, j - 1); + } + ++ private int getPower(int min, BlockState iblockdata) { return Math.max(min, getPower(iblockdata)); } // Paper - Optimize redstone ++ private int getPower(BlockState iblockdata) { return this.getWireSignal(iblockdata); } // Paper - OBFHELPER + private int getWireSignal(BlockState state) { + return state.is((Block) this) ? (Integer) state.getValue(RedStoneWireBlock.POWER) : 0; + } +@@ -327,7 +446,7 @@ public class RedStoneWireBlock extends Block { + @Override + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + if (!oldState.is(state.getBlock()) && !world.isClientSide) { +- this.updatePowerStrength(world, pos, state); ++ this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone + Iterator iterator = Direction.Plane.VERTICAL.iterator(); + + while (iterator.hasNext()) { +@@ -354,7 +473,7 @@ public class RedStoneWireBlock extends Block { + world.updateNeighborsAt(pos.relative(enumdirection), this); + } + +- this.updatePowerStrength(world, pos, state); ++ this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone + this.updateNeighborsOfNeighboringWires(world, pos); + } + } +@@ -389,7 +508,7 @@ public class RedStoneWireBlock extends Block { + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { + if (!world.isClientSide) { + if (state.canSurvive(world, pos)) { +- this.updatePowerStrength(world, pos, state); ++ this.updateSurroundingRedstone(world, pos, state, fromPos); // Paper - Optimize redstone + } else { + dropResources(state, world, pos); + world.removeBlock(pos, false); diff --git a/patches/server-remapped/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch b/patches/server-remapped/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch new file mode 100644 index 0000000000..dfda54388f --- /dev/null +++ b/patches/server-remapped/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Thu, 27 Aug 2020 16:57:25 -0400 +Subject: [PATCH] Fix hex colors not working in some kick messages + + +diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 6f98be2b9b00f71dd041e7511c70166fdecf0749..c648b73a4c478f9d8020274205d6684f7c7c416f 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -50,7 +50,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + synchronized (throttleTracker) { + if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { + throttleTracker.put(address, currentTime); +- TranslatableComponent chatmessage = new TranslatableComponent(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message ++ Component chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage, true)[0]; // Paper - Configurable connection throttle kick message // Paper - Fix hex colors not working in some kick messages + this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); + this.connection.disconnect(chatmessage); + return; +@@ -76,12 +76,12 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + } + // CraftBukkit end + if (packet.getProtocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { +- TranslatableComponent chatmessage; ++ Component chatmessage; // Paper - Fix hex colors not working in some kick messages + + if (packet.getProtocolVersion() < 754) { +- chatmessage = new TranslatableComponent( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) ); // Spigot ++ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages + } else { +- chatmessage = new TranslatableComponent( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) ); // Spigot ++ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages + } + + this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); +@@ -99,7 +99,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + if (event.callEvent()) { + // If we've failed somehow, let the client know so and go no further. + if (event.isFailed()) { +- chatmessage = new TranslatableComponent(event.getFailMessage()); ++ Component chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(event.getFailMessage(), true)[0]; // Paper - Fix hex colors not working in some kick messages + this.getNetworkManager().send(new ClientboundLoginDisconnectPacket(chatmessage)); + this.getNetworkManager().disconnect(chatmessage); + return; +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 659bf14cf3c949b896d0333f893a3d5e16ab9c92..573963a09f15046cfcaab83aef906801ce70d75a 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -104,14 +104,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + // CraftBukkit start + @Deprecated + public void disconnect(String s) { +- try { +- Component ichatbasecomponent = new TextComponent(s); +- ServerLoginPacketListenerImpl.LOGGER.info("Disconnecting {}: {}", this.getUserName(), s); +- this.connection.send(new ClientboundLoginDisconnectPacket(ichatbasecomponent)); +- this.connection.disconnect(ichatbasecomponent); +- } catch (Exception exception) { +- ServerLoginPacketListenerImpl.LOGGER.error("Error whilst disconnecting player", exception); +- } ++ disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s, true)[0]); // Paper - Fix hex colors not working in some kick messages + } + // CraftBukkit end + diff --git a/patches/server-remapped/0560-PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server-remapped/0560-PortalCreateEvent-needs-to-know-its-entity.patch new file mode 100644 index 0000000000..0287c9ed0f --- /dev/null +++ b/patches/server-remapped/0560-PortalCreateEvent-needs-to-know-its-entity.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Fri, 21 Aug 2020 20:57:54 +0200 +Subject: [PATCH] PortalCreateEvent needs to know its entity + + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 04b717326524f400da3562655c25db59e72814ec..a9256fc4a0bc3cd277cb372a9c090028e03482f5 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -366,7 +366,7 @@ public final class ItemStack { + net.minecraft.world.level.block.state.BlockState block = world.getBlockState(newblockposition); + + if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically +- block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); ++ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true, itemactioncontext); // Paper - pass itemactioncontext + } + + world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point +diff --git a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +index cd005f7dbfcaf3cebae3a92da36e0d40c93dbf79..ad37261e716b15d62fc2083d137cdac818308cdd 100644 +--- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +@@ -7,6 +7,7 @@ import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.BlockPlaceContext; ++import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; +@@ -66,20 +67,23 @@ public abstract class BaseFireBlock extends Block { + super.entityInside(state, world, pos, entity); + } + ++ // Paper start - ItemActionContext param ++ @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { this.onPlace(state, world, pos, oldState, notify, null); } + @Override +- public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { +- if (!oldState.is(state.getBlock())) { ++ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { ++ // Paper end ++ if (!iblockdata1.is(iblockdata.getBlock())) { + if (inPortalDimension(world)) { +- Optional optional = PortalShape.findEmptyPortalShape((LevelAccessor) world, pos, Direction.Axis.X); ++ Optional optional = PortalShape.findEmptyPortalShape((LevelAccessor) world, blockposition, Direction.Axis.X); + + if (optional.isPresent()) { +- ((PortalShape) optional.get()).createPortal(); ++ ((PortalShape) optional.get()).createPortal(itemActionContext); // Paper - pass ItemActionContext param + return; + } + } + +- if (!state.canSurvive(world, pos)) { +- fireExtinguished(world, pos); // CraftBukkit - fuel block broke ++ if (!iblockdata.canSurvive(world, blockposition)) { ++ fireExtinguished(world, blockposition); // CraftBukkit - fuel block broke + } + + } +diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java +index ac63c5bef5b35b158e57835d765bbdd15fc60664..e690e7c366fc087d3b28d61323dcc78bb7154aed 100644 +--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java +@@ -15,6 +15,7 @@ import net.minecraft.core.Vec3i; + import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.item.context.BlockPlaceContext; ++import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +@@ -363,9 +364,11 @@ public class FireBlock extends BaseFireBlock { + } + + @Override +- public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { +- super.onPlace(state, world, pos, oldState, notify); +- world.getBlockTicks().a(pos, this, getFireTickDelay(world.random)); ++ // Paper start - ItemActionContext param ++ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { ++ super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext); ++ // Paper end ++ world.getBlockTicks().a(blockposition, this, getFireTickDelay(world.random)); + } + + private static int getFireTickDelay(Random random) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index df2836b071158729728411f5b228cc38dddd4d4e..f2fefdad26057c722085e60ba837fe2c117f55f7 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -32,6 +32,7 @@ import net.minecraft.world.item.DyeColor; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockPlaceContext; ++import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.EmptyBlockGetter; + import net.minecraft.world.level.Level; +@@ -119,6 +120,12 @@ public abstract class BlockBehaviour { + DebugPackets.sendNeighborsUpdatePacket(world, pos); + } + ++ // Paper start - add ItemActionContext param ++ @Deprecated ++ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { ++ this.onPlace(iblockdata, world, blockposition, iblockdata1, flag); ++ } ++ // Paper end + @Deprecated + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot +diff --git a/src/main/java/net/minecraft/world/level/portal/PortalShape.java b/src/main/java/net/minecraft/world/level/portal/PortalShape.java +index 7a99adbe39ca2566d42ed67dc9d6f609005f3d6f..500744b6383390266efed9e35a000511210cb5b9 100644 +--- a/src/main/java/net/minecraft/world/level/portal/PortalShape.java ++++ b/src/main/java/net/minecraft/world/level/portal/PortalShape.java +@@ -11,6 +11,7 @@ import net.minecraft.tags.BlockTags; + import net.minecraft.tags.Tag; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.NetherPortalBlock; +@@ -181,7 +182,10 @@ public class PortalShape { + } + + // CraftBukkit start - return boolean +- public boolean createPortal() { ++ // Paper start - ItemActionContext param ++ @Deprecated public boolean createPortal() { return this.createPortal(null); } ++ public boolean createPortal(UseOnContext itemActionContext) { ++ // Paper end + org.bukkit.World bworld = this.level.getLevel().getWorld(); + + // Copy below for loop +@@ -190,8 +194,7 @@ public class PortalShape { + BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { + blocks.setBlock(blockposition, iblockdata, 18); + }); +- +- PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); ++ PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, itemActionContext == null || itemActionContext.getPlayer() == null ? null : itemActionContext.getPlayer().getBukkitEntity(), PortalCreateEvent.CreateReason.FIRE); // Paper - pass entity param + this.level.getLevel().getServer().server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { diff --git a/patches/server-remapped/0561-Fix-CraftTeam-null-check.patch b/patches/server-remapped/0561-Fix-CraftTeam-null-check.patch new file mode 100644 index 0000000000..d30a891285 --- /dev/null +++ b/patches/server-remapped/0561-Fix-CraftTeam-null-check.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: foss-mc <69294560+foss-mc@users.noreply.github.com> +Date: Sun, 30 Aug 2020 15:30:29 +0800 +Subject: [PATCH] Fix CraftTeam null check + + +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +index 7ebcba4ada42f5599d56cfdeb75dbf62f2a09b78..222e3d4e379fd5ca50c122f70e90ed11b2f5e1f7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +@@ -253,7 +253,7 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { + + @Override + public boolean hasEntry(String entry) throws IllegalArgumentException, IllegalStateException { +- Validate.notNull("Entry cannot be null"); ++ Validate.notNull(entry, "Entry cannot be null"); // Paper + + CraftScoreboard scoreboard = checkState(); + diff --git a/patches/server-remapped/0562-Add-more-Evoker-API.patch b/patches/server-remapped/0562-Add-more-Evoker-API.patch new file mode 100644 index 0000000000..af8a4c5513 --- /dev/null +++ b/patches/server-remapped/0562-Add-more-Evoker-API.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Aug 2020 15:28:35 +0200 +Subject: [PATCH] Add more Evoker API + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Evoker.java b/src/main/java/net/minecraft/world/entity/monster/Evoker.java +index c0a5b0074480aad717177c92b28fa27b8a1d707d..617075955506500dc2d9c734398c48b8fc10b69d 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Evoker.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Evoker.java +@@ -40,7 +40,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; + + public class Evoker extends SpellcasterIllager { + +- private Sheep wololoTarget; ++ private Sheep wololoTarget; public final Sheep getWololoTarget() { return this.wololoTarget; } public final void setWololoTarget(Sheep sheep) { this.wololoTarget = sheep; } // Paper - OBFHELPER + + public Evoker(EntityType type, Level world) { + super(type, world); +@@ -59,7 +59,7 @@ public class Evoker extends SpellcasterIllager { + this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); +- this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).canUse()); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers(new Class[0])); // Paper - decompile fix + this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); + this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, false)); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java +index 29fec87c938c4252cf5c9473ce9e5c1908ea9063..950e35f67f88138cc2ce923be1ea7976bd317d1f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import net.minecraft.world.entity.animal.Sheep; + import net.minecraft.world.entity.monster.SpellcasterIllager; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; +@@ -35,4 +36,17 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { + public void setCurrentSpell(Evoker.Spell spell) { + getHandle().setIsCastingSpell(spell == null ? SpellcasterIllager.IllagerSpell.NONE : SpellcasterIllager.IllagerSpell.byId(spell.ordinal())); + } ++ ++ // Paper start ++ @Override ++ public org.bukkit.entity.Sheep getWololoTarget() { ++ Sheep sheep = getHandle().getWololoTarget(); ++ return sheep == null ? null : (org.bukkit.entity.Sheep) sheep.getBukkitEntity(); ++ } ++ ++ @Override ++ public void setWololoTarget(org.bukkit.entity.Sheep sheep) { ++ getHandle().setWololoTarget(sheep == null ? null : ((org.bukkit.craftbukkit.entity.CraftSheep) sheep).getHandle()); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/server-remapped/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch new file mode 100644 index 0000000000..163eac24a0 --- /dev/null +++ b/patches/server-remapped/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch @@ -0,0 +1,126 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Tue, 11 Aug 2020 19:16:09 +0200 +Subject: [PATCH] Add a way to get translation keys for blocks, entities and + materials + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index ae50030df7512c56c552e800b74ef4c69ec6d6d2..d38828485d6deb08036e11d8bf16b3d63a60fbae 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -278,6 +278,7 @@ public class EntityType { + return Registry.ENTITY_TYPE.getKey(type); + } + ++ public static Optional> getByName(String name) { return byString(name); } // Paper - OBFHELPER + public static Optional> byString(String id) { + return Registry.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(id)); + } +@@ -431,6 +432,7 @@ public class EntityType { + return this.category; + } + ++ public String getDescriptionId() { return getDescriptionId(); } // Paper - OBFHELPER + public String getDescriptionId() { + if (this.descriptionId == null) { + this.descriptionId = Util.makeDescriptionId("entity", Registry.ENTITY_TYPE.getKey(this)); +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index 6fce16e89c5492654c891d5754714360a7649bca..58400e84830c93675b0a1fe632be5e217c19a932 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -56,7 +56,7 @@ public class Item implements ItemLike { + private final FoodProperties foodProperties; + + public static int getId(Item item) { +- return item == null ? 0 : Registry.ITEM.getId((Object) item); ++ return item == null ? 0 : Registry.ITEM.getId(item); // Paper - Fix Decompiler Issue + } + + public static Item byId(int id) { +@@ -152,6 +152,7 @@ public class Item implements ItemLike { + return Registry.ITEM.getKey(this).getPath(); + } + ++ public String getOrCreateDescriptionId() { return getOrCreateDescriptionId(); } // Paper - OBFHELPER + protected String getOrCreateDescriptionId() { + if (this.descriptionId == null) { + this.descriptionId = Util.makeDescriptionId("item", Registry.ITEM.getKey(this)); +@@ -164,6 +165,7 @@ public class Item implements ItemLike { + return this.getOrCreateDescriptionId(); + } + ++ public String getDescriptionId(ItemStack itemStack) { return getDescriptionId(itemStack); } // Paper - OBFHELPER + public String getDescriptionId(ItemStack stack) { + return this.getDescriptionId(); + } +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 5b84ee4091e354c4b6500f58a31931f2a6827ffc..baa587e73a71d6324bb7817fa4702a7c3a2db726 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -318,6 +318,7 @@ public class Block extends BlockBehaviour implements ItemLike { + return !this.material.isBuildable() && !this.material.isLiquid(); + } + ++ public String getOrCreateDescriptionId() { return getDescriptionId(); } // Paper - OBFHELPER + public String getDescriptionId() { + if (this.descriptionId == null) { + this.descriptionId = Util.makeDescriptionId("block", Registry.BLOCK.getKey(this)); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 05f0833f762436bf8f5f5875c7e3cfed1da11e1c..e09f65f0b06c8fb9a965b921c2c8e68ae2ac1e55 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -761,5 +761,10 @@ public class CraftBlock implements Block { + public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { + return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().defaultBlockState().getSoundType()); + } ++ ++ @Override ++ public String getTranslationKey() { ++ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); ++ } + // 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 a5a5038a84434e69fda8f6b41d2f00b4989e25ae..de5d02a1345f9886200f0540ac08be0df5878708 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -43,6 +43,7 @@ import org.bukkit.Registry; + import org.bukkit.UnsafeValues; + import org.bukkit.advancement.Advancement; + import org.bukkit.block.data.BlockData; ++import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.block.data.CraftBlockData; + import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.craftbukkit.legacy.CraftLegacy; +@@ -418,6 +419,30 @@ public final class CraftMagicNumbers implements UnsafeValues { + throw new RuntimeException(); + } + } ++ ++ @Override ++ public String getTranslationKey(Material mat) { ++ if (mat.isBlock()) { ++ return getBlock(mat).getOrCreateDescriptionId(); ++ } ++ return getItem(mat).getDescriptionId(); ++ } ++ ++ @Override ++ public String getTranslationKey(org.bukkit.block.Block block) { ++ return ((org.bukkit.craftbukkit.block.CraftBlock)block).getNMS().getBlock().getOrCreateDescriptionId(); ++ } ++ ++ @Override ++ public String getTranslationKey(org.bukkit.entity.EntityType type) { ++ return net.minecraft.world.entity.EntityType.getByName(type.getName()).map(net.minecraft.world.entity.EntityType::getDescriptionId).orElse(null); ++ } ++ ++ @Override ++ public String getTranslationKey(org.bukkit.inventory.ItemStack itemStack) { ++ net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); ++ return nmsItemStack.getItem().getDescriptionId(nmsItemStack); ++ } + // Paper end + + /** diff --git a/patches/server-remapped/0564-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server-remapped/0564-Create-HoverEvent-from-ItemStack-Entity.patch new file mode 100644 index 0000000000..a7252fed8a --- /dev/null +++ b/patches/server-remapped/0564-Create-HoverEvent-from-ItemStack-Entity.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ysl3000 +Date: Mon, 6 Jul 2020 22:18:04 +0200 +Subject: [PATCH] Create HoverEvent from ItemStack Entity + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index 746755f76ae177b2eeccf66f8cd95e6ffd5acad9..2e0be9771ca3511f5d9364c57235556b70f07ec6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -365,5 +365,40 @@ public final class CraftItemFactory implements ItemFactory { + + return nms != null ? net.minecraft.locale.Language.getInstance().translateKey(nms.getItem().getDescriptionId()) : null; + } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(ItemStack itemStack) { ++ net.md_5.bungee.api.chat.ItemTag itemTag = net.md_5.bungee.api.chat.ItemTag.ofNbt(CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString()); ++ return new net.md_5.bungee.api.chat.hover.content.Item( ++ itemStack.getType().getKey().toString(), ++ itemStack.getAmount(), ++ itemTag); ++ } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity) { ++ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(entity.getCustomName()) ? null : new net.md_5.bungee.api.chat.TextComponent(entity.getCustomName())); ++ } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, String customName) { ++ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(customName) ? null : new net.md_5.bungee.api.chat.TextComponent(customName)); ++ } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent customName) { ++ return new net.md_5.bungee.api.chat.hover.content.Entity( ++ entity.getType().getKey().toString(), ++ entity.getUniqueId().toString(), ++ customName); ++ } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent[] customName) { ++ return new net.md_5.bungee.api.chat.hover.content.Entity( ++ entity.getType().getKey().toString(), ++ entity.getUniqueId().toString(), ++ new net.md_5.bungee.api.chat.TextComponent(customName)); ++ } + // Paper end + } diff --git a/patches/server-remapped/0565-Cache-block-data-strings.patch b/patches/server-remapped/0565-Cache-block-data-strings.patch new file mode 100644 index 0000000000..b4924166cc --- /dev/null +++ b/patches/server-remapped/0565-Cache-block-data-strings.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: miclebrick +Date: Thu, 6 Dec 2018 19:52:50 -0500 +Subject: [PATCH] Cache block data strings + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 735c3c983e96e4e6f36de0975909fc48cb042081..5c5903867432894b47bc62d89989f78c36a84ca1 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1953,6 +1953,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop%s", nms, bukkit); + } + ++ // Paper start - cache block data strings ++ private static Map stringDataCache = new HashMap<>(); ++ ++ static { ++ // cache all of the default states at startup, will not cache ones with the custom states inside of the ++ // brackets in a different order, though ++ reloadCache(); ++ } ++ ++ public static void reloadCache() { ++ stringDataCache.clear(); ++ Block.BLOCK_STATE_REGISTRY.forEach(blockData -> stringDataCache.put(blockData.toString(), blockData.createCraftBlockData())); ++ } ++ // Paper end ++ + public static CraftBlockData newData(Material material, String data) { + Preconditions.checkArgument(material == null || material.isBlock(), "Cannot get data for not block %s", material); + ++ // Paper start - cache block data strings ++ if (material != null) { ++ Block block = CraftMagicNumbers.getBlock(material); ++ if (block != null) { ++ ResourceLocation key = Registry.BLOCK.getKey(block); ++ data = data == null ? key.toString() : key + data; ++ } ++ } ++ ++ CraftBlockData cached = stringDataCache.computeIfAbsent(data, s -> createNewData(null, s)); ++ return (CraftBlockData) cached.clone(); ++ } ++ ++ private static CraftBlockData createNewData(Material material, String data) { ++ // Paper end - cache block data strings + BlockState blockData; + Block block = CraftMagicNumbers.getBlock(material); + Map, Comparable> parsed = null; diff --git a/patches/server-remapped/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/patches/server-remapped/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch new file mode 100644 index 0000000000..1e30590a64 --- /dev/null +++ b/patches/server-remapped/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 25 Aug 2020 20:45:36 -0400 +Subject: [PATCH] Fix Entity Teleportation and cancel velocity if teleported + +Uses correct setPositionRotation for Entity teleporting instead of setLocation +as this is how Vanilla teleports entities. + +Cancel any pending motion when teleported. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index ab6494f5a872bba5398bef0367b4d9257786f61e..ab45497e8f7720c9d60626b32e9c95779af676b0 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -691,7 +691,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + public void handleAcceptTeleportPacket(ServerboundAcceptTeleportationPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (packet.getId() == this.awaitingTeleport && this.awaitingPositionFromClient != null) { // CraftBukkit +- this.player.absMoveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.yRot, this.player.xRot); ++ this.player.moveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.yRot, this.player.xRot); // Paper - use proper setPositionRotation for teleportation + this.lastGoodX = this.awaitingPositionFromClient.x; + this.lastGoodY = this.awaitingPositionFromClient.y; + this.lastGoodZ = this.awaitingPositionFromClient.z; +@@ -1536,7 +1536,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit end + + this.awaitingTeleportTime = this.tickCount; +- this.player.absMoveTo(d0, d1, d2, f, f1); ++ this.player.moveTo(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation + this.player.forceCheckHighPriority(); // Paper + this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index aea2457510c75214bbb925307155611e981f115f..d69981a1b5a40418c7d17de5f3bece30592ae586 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -143,6 +143,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + // CraftBukkit start + private static final int CURRENT_LEVEL = 2; ++ public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation + static boolean isLevelAtLeast(CompoundTag tag, int level) { + return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; + } +@@ -1406,6 +1407,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public void moveTo(double x, double y, double z, float yaw, float pitch) { ++ // Paper - cancel entity velocity if teleported ++ if (!preserveMotion) { ++ this.deltaMovement = Vec3.ZERO; ++ } else { ++ this.preserveMotion = false; ++ } ++ // Paper end + this.setPosAndOldPos(x, y, z); + this.yRot = yaw; + this.xRot = pitch; +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 6ca378ec7868b855d46c749910c656f82ddb009f..091e72474ac199c38fff979a5faf524e011d8d0a 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -165,6 +165,7 @@ public abstract class BaseSpawner { + return; + } + ++ entity.preserveMotion = true; // Paper - preserve entity motion from tag + entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), world.random.nextFloat() * 360.0F, 0.0F); + if (entity instanceof Mob) { + Mob entityinsentient = (Mob) entity; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index deeae62e9926f9435907c68e7d35e7420f5e79dd..1275768762884416fa3c68dab3a6671b24949976 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -556,7 +556,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + } + + // entity.setLocation() throws no event, and so cannot be cancelled +- entity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); ++ entity.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); // Paper - use proper setPosition, as per vanilla teleporting + // SPIGOT-619: Force sync head rotation also + entity.setYHeadRot(location.getYaw()); + ((net.minecraft.server.level.ServerLevel) entity.level).updateChunkPos(entity); // Spigot - register to new chunk diff --git a/patches/server-remapped/0567-Add-additional-open-container-api-to-HumanEntity.patch b/patches/server-remapped/0567-Add-additional-open-container-api-to-HumanEntity.patch new file mode 100644 index 0000000000..4f031f39de --- /dev/null +++ b/patches/server-remapped/0567-Add-additional-open-container-api-to-HumanEntity.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 26 Aug 2020 02:12:31 -0400 +Subject: [PATCH] Add additional open container api 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 878a62e04962aafeaf192075fbe08e319298a800..aceb57c93c91730345f49f78838780c41ce2dcef 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -459,6 +459,70 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + return this.getHandle().containerMenu.getBukkitView(); + } + ++ // Paper start - Add additional containers ++ @Override ++ public InventoryView openAnvil(Location location, boolean force) { ++ return openInventory(location, force, Material.ANVIL); ++ } ++ ++ @Override ++ public InventoryView openCartographyTable(Location location, boolean force) { ++ return openInventory(location, force, Material.CARTOGRAPHY_TABLE); ++ } ++ ++ @Override ++ public InventoryView openGrindstone(Location location, boolean force) { ++ return openInventory(location, force, Material.GRINDSTONE); ++ } ++ ++ @Override ++ public InventoryView openLoom(Location location, boolean force) { ++ return openInventory(location, force, Material.LOOM); ++ } ++ ++ @Override ++ public InventoryView openSmithingTable(Location location, boolean force) { ++ return openInventory(location, force, Material.SMITHING_TABLE); ++ } ++ ++ @Override ++ public InventoryView openStonecutter(Location location, boolean force) { ++ return openInventory(location, force, Material.STONECUTTER); ++ } ++ ++ private InventoryView openInventory(Location location, boolean force, Material material) { ++ org.spigotmc.AsyncCatcher.catchOp("open" + material); ++ if (location == null) { ++ location = getLocation(); ++ } ++ if (!force) { ++ Block block = location.getBlock(); ++ if (block.getType() != material) { ++ return null; ++ } ++ } ++ net.minecraft.world.level.block.Block block; ++ if (material == Material.ANVIL) { ++ block = Blocks.ANVIL; ++ } else if (material == Material.CARTOGRAPHY_TABLE) { ++ block = Blocks.CARTOGRAPHY_TABLE; ++ } else if (material == Material.GRINDSTONE) { ++ block = Blocks.GRINDSTONE; ++ } else if (material == Material.LOOM) { ++ block = Blocks.LOOM; ++ } else if (material == Material.SMITHING_TABLE) { ++ block = Blocks.SMITHING_TABLE; ++ } else if (material == Material.STONECUTTER) { ++ block = Blocks.STONECUTTER; ++ } else { ++ throw new IllegalArgumentException("Unsupported inventory type: " + material); ++ } ++ getHandle().openMenu(block.getMenuProvider(null, getHandle().level, new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()))); ++ getHandle().containerMenu.checkReachable = !force; ++ return getHandle().containerMenu.getBukkitView(); ++ } ++ // Paper end ++ + @Override + public void closeInventory() { + // Paper start diff --git a/patches/server-remapped/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/patches/server-remapped/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch new file mode 100644 index 0000000000..a02addc375 --- /dev/null +++ b/patches/server-remapped/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 12 Sep 2020 17:21:38 -0400 +Subject: [PATCH] Cache DataFixerUpper Rewrite Rules on demand + +Mojang precaches every single potential rewrite rule that could ever +exist on server startup. This includes rules from all the way back to versions from 6+ years ago. + +This is the source of why the server hogs every CPU core at 100% every start. + +For anyone who hard resets for updates or has force upgraded their entire world, this +results in completely wasted cpu cycles. + +This massive CPU usage also delays server startup time. + +We improve this by making "min version to precache" that defaults to a future version +so that no rewrite rules are precached. + +someone who expects to be converting a lot chunks could theoretically set +-DPaper.minPrecachedDatafixVersion= as a startup +parameter and only build from that point on. + +However this will likely never be needed as the server will still run +the same cache logic on demand when it's actually needed. The only +cost would be some delay on the FIRST chunk conversion, but paper already +runs chunk conversions on another thread so this will likely never be +a concern for TPS. + +This patch will significantly reduce CPU use on startup, reduce memory usage, +and improve server startup time. + +diff --git a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java +index edb77982d273e9492ab1a669ca1ad89da2ec3c3e..abc265b00044b14abb55c2628d454ee01fef467b 100644 +--- a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java ++++ b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java +@@ -26,8 +26,10 @@ public class DataFixerBuilder { + private final Int2ObjectSortedMap schemas = new Int2ObjectAVLTreeMap<>(); + private final List globalList = Lists.newArrayList(); + private final IntSortedSet fixerVersions = new IntAVLTreeSet(); ++ private final int minDataFixPrecacheVersion; // Paper + + public DataFixerBuilder(final int dataVersion) { ++ minDataFixPrecacheVersion = Integer.getInteger("Paper.minPrecachedDatafixVersion", dataVersion+1) * 10; // Paper - default to precache nothing - mojang stores versions * 10 to allow for 'sub versions' + this.dataVersion = dataVersion; + } + +@@ -65,6 +67,7 @@ public class DataFixerBuilder { + final IntBidirectionalIterator iterator = fixerUpper.fixerVersions().iterator(); + while (iterator.hasNext()) { + final int versionKey = iterator.nextInt(); ++ if (versionKey < minDataFixPrecacheVersion) continue; // Paper + final Schema schema = schemas.get(versionKey); + for (final String typeName : schema.types()) { + CompletableFuture.runAsync(() -> { diff --git a/patches/server-remapped/0569-Extend-block-drop-capture-to-capture-all-items-added.patch b/patches/server-remapped/0569-Extend-block-drop-capture-to-capture-all-items-added.patch new file mode 100644 index 0000000000..21f6d53f47 --- /dev/null +++ b/patches/server-remapped/0569-Extend-block-drop-capture-to-capture-all-items-added.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 17 Sep 2020 00:36:05 +0100 +Subject: [PATCH] Extend block drop capture to capture all items added to the + world + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 22266fda4de9b5fbace3b8e55ce390b8d7e75a65..fe7b71fbb3963beafe93a5d86bebdd629c7ec8f2 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -95,6 +95,7 @@ import net.minecraft.world.entity.ai.village.poi.PoiType; + import net.minecraft.world.entity.animal.horse.SkeletonHorse; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.monster.Drowned; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.raid.Raid; +@@ -1284,6 +1285,13 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } else if (this.isUUIDUsed(entity)) { + return false; + } else { ++ // Paper start - capture all item additions to the world ++ if (captureDrops != null && entity instanceof ItemEntity) { ++ captureDrops.add((ItemEntity) entity); ++ return true; ++ } ++ // Paper end ++ + if (!CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { + return false; + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 79f3e4176145c42debb9adc1e68175cf063c1f22..6269e37f2859417a80e6de16045f1c2325f9746f 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -6,6 +6,7 @@ import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.MenuProvider; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.DoubleHighBlockItem; + import net.minecraft.world.item.ItemStack; +@@ -418,10 +419,12 @@ public class ServerPlayerGameMode { + // return true; // CraftBukkit + } + // CraftBukkit start ++ java.util.List itemsToDrop = level.captureDrops; // Paper - store current list ++ level.captureDrops = null; // Paper - Remove this earlier so that we can actually drop stuff + if (event.isDropItems()) { +- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, level.captureDrops); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - use stored ref + } +- level.captureDrops = null; ++ //world.captureDrops = null; // Paper - move up + + // Drop event experience + if (flag && event != null) { diff --git a/patches/server-remapped/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server-remapped/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch new file mode 100644 index 0000000000..07195903cb --- /dev/null +++ b/patches/server-remapped/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sun, 27 Sep 2020 16:25:24 +0200 +Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086) + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 82205ad13ef0e987bd83979d06331545efe0a60a..50dc47e8c03ce274d558bc0dfa73ba3ab5fbae5c 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -388,6 +388,7 @@ public class ChunkHolder { + } + + public void blockChanged(BlockPos blockposition) { ++ if (!blockposition.isValidLocation()) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks + LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { diff --git a/patches/server-remapped/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server-remapped/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch new file mode 100644 index 0000000000..6eb1a44bc0 --- /dev/null +++ b/patches/server-remapped/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Fri, 28 Aug 2020 01:41:26 +0200 +Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and + non-conflicting Entity Ids + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d69981a1b5a40418c7d17de5f3bece30592ae586..fa22c0d7f676c96d34bf56d80181d6b047f2ff0b 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -3476,4 +3476,10 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + void accept(Entity entity, double x, double y, double z); + } ++ ++ // Paper start ++ public static int nextEntityId() { ++ return ENTITY_COUNTER.incrementAndGet(); ++ } ++ // 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 de5d02a1345f9886200f0540ac08be0df5878708..9a16882deee21faf78ea46e08b2f2ad3fbb6021b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -443,6 +443,10 @@ public final class CraftMagicNumbers implements UnsafeValues { + net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); + return nmsItemStack.getItem().getDescriptionId(nmsItemStack); + } ++ ++ public int nextEntityId() { ++ return net.minecraft.world.entity.Entity.nextEntityId(); ++ } + // Paper end + + /** diff --git a/patches/server-remapped/0572-Lazily-track-plugin-scoreboards-by-default.patch b/patches/server-remapped/0572-Lazily-track-plugin-scoreboards-by-default.patch new file mode 100644 index 0000000000..e06db589aa --- /dev/null +++ b/patches/server-remapped/0572-Lazily-track-plugin-scoreboards-by-default.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Sat, 3 Oct 2020 04:15:09 -0400 +Subject: [PATCH] Lazily track plugin scoreboards by default + +On servers with plugins that constantly churn through scoreboards, there is a risk of +degraded GC performance due to the number of scoreboards held on by weak references. +Most plugins don't even need the (vanilla) functionality that requires all plugin +scoreboards to be tracked by the server. Instead, only track scoreboards when an +objective is added with a non-dummy criteria. + +This is a breaking change, however the change is a much more sensible default. In case +this breaks your workflow you can always force all scoreboards to be tracked with +settings.track-plugin-scoreboards in paper.yml. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 545948f20efd6c8dd42140b565af94cd6b52b661..7d50aded88f5b7dfebaea1aebc86231f7b5c4e25 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -462,4 +462,9 @@ public class PaperConfig { + private static void maxJoinsPerTick() { + maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); + } ++ ++ public static boolean trackPluginScoreboards; ++ private static void trackPluginScoreboards() { ++ trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +index 4c93be31fd95d731327479519ecb34a08785c1ca..57537b8871dd5c54d97f3effe1802a3396644e46 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +@@ -18,6 +18,7 @@ import org.bukkit.scoreboard.Team; + + public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + final Scoreboard board; ++ boolean registeredGlobally = false; // Paper + + CraftScoreboard(Scoreboard board) { + this.board = board; +@@ -44,6 +45,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); + Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); + CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); ++ // Paper start - the block comment from the old registerNewObjective didnt cause a conflict when rebasing, so this block wasn't added to the adventure registerNewObjective ++ if (craftCriteria.criteria != net.minecraft.world.scores.criteria.ObjectiveCriteria.DUMMY && !registeredGlobally) { ++ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); ++ registeredGlobally = true; ++ } ++ // Paper end + net.minecraft.world.scores.Objective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); + return new CraftObjective(this, objective); + } +@@ -65,6 +72,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); + + CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); ++ // Paper start ++ if (craftCriteria.criteria != net.minecraft.server.IScoreboardCriteria.DUMMY && !registeredGlobally) { ++ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); ++ registeredGlobally = true; ++ } ++ // Paper end + ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); + return new CraftObjective(this, objective);*/ // Paper + return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +index 30b0d4986a7edcf324d94d9304d66d0567098855..8217e35f5a3093e63a165ee8c8b30bf3f28f3bd3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +@@ -30,6 +30,7 @@ public final class CraftScoreboardManager implements ScoreboardManager { + + public CraftScoreboardManager(MinecraftServer minecraftserver, net.minecraft.world.scores.Scoreboard scoreboardServer) { + mainScoreboard = new CraftScoreboard(scoreboardServer); ++ mainScoreboard.registeredGlobally = true; // Paper + server = minecraftserver; + scoreboards.add(mainScoreboard); + } +@@ -43,10 +44,22 @@ public final class CraftScoreboardManager implements ScoreboardManager { + public CraftScoreboard getNewScoreboard() { + org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot + CraftScoreboard scoreboard = new CraftScoreboard(new ServerScoreboard(server)); ++ // Paper start ++ if (com.destroystokyo.paper.PaperConfig.trackPluginScoreboards) { ++ scoreboard.registeredGlobally = true; + scoreboards.add(scoreboard); ++ } ++ // Paper end + return scoreboard; + } + ++ // Paper start ++ public void registerScoreboardForVanilla(CraftScoreboard scoreboard) { ++ org.spigotmc.AsyncCatcher.catchOp("scoreboard registration"); ++ scoreboards.add(scoreboard); ++ } ++ // Paper end ++ + // CraftBukkit method + public CraftScoreboard getPlayerBoard(CraftPlayer player) { + CraftScoreboard board = playerBoards.get(player); diff --git a/patches/server-remapped/0573-Entity-isTicking.patch b/patches/server-remapped/0573-Entity-isTicking.patch new file mode 100644 index 0000000000..22d5c7950d --- /dev/null +++ b/patches/server-remapped/0573-Entity-isTicking.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 3 Oct 2020 21:39:16 -0500 +Subject: [PATCH] Entity#isTicking + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index fa22c0d7f676c96d34bf56d80181d6b047f2ff0b..a623c22cd03ad92657e661851fddc76a30986755 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -49,6 +49,7 @@ import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.level.TicketType; +@@ -3481,5 +3482,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public static int nextEntityId() { + return ENTITY_COUNTER.incrementAndGet(); + } ++ ++ public boolean isTicking() { ++ return ((ServerChunkCache) level.getChunkSource()).isInEntityTickingChunk(this); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 1275768762884416fa3c68dab3a6671b24949976..502773ae60290125057fb342a3358ff55927d196 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1159,5 +1159,9 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public boolean isInLava() { + return getHandle().isInLava(); + } ++ ++ public boolean isTicking() { ++ return getHandle().isTicking(); ++ } + // Paper end + } diff --git a/patches/server-remapped/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/patches/server-remapped/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch new file mode 100644 index 0000000000..2d6ec97910 --- /dev/null +++ b/patches/server-remapped/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 3 Oct 2020 22:00:27 -0500 +Subject: [PATCH] Fix deop kicking non-whitelisted player when white list is + not enabled + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 5c5903867432894b47bc62d89989f78c36a84ca1..954dce690852da87a37e7797c6f9f549242e511a 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2018,6 +2018,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop list = Lists.newArrayList(playerlist.getPlayers()); + Iterator iterator = list.iterator(); + diff --git a/patches/server-remapped/0575-Fix-Not-a-string-Map-Conversion-spam.patch b/patches/server-remapped/0575-Fix-Not-a-string-Map-Conversion-spam.patch new file mode 100644 index 0000000000..5b9dbf362f --- /dev/null +++ b/patches/server-remapped/0575-Fix-Not-a-string-Map-Conversion-spam.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 8 Oct 2020 00:00:25 -0400 +Subject: [PATCH] Fix "Not a string" Map Conversion spam + +The maps did convert successfully, but had noisy logs due to Spigot +implementing this logic incorrectly. + +This stops the spam by converting the old format to new before +requesting the world. + +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +index 7582c7cd4235d212a0cf66a4c59ce0cedaa360ad..e7b178127228dea5a17ba0fbd6bae148d70e8eb5 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -12,6 +12,8 @@ import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.NumericTag; ++import net.minecraft.nbt.StringTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.Packet; +@@ -94,7 +96,26 @@ public class MapItemSavedData extends SavedData { + + @Override + public void load(CompoundTag tag) { +- DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, tag.get("dimension"))); // CraftBukkit - decompile error ++ // Paper start - fix "Not a string" spam ++ Tag dimension = tag.get("dimension"); ++ if (dimension instanceof NumericTag && ((NumericTag) dimension).getAsInt() >= CraftWorld.CUSTOM_DIMENSION_OFFSET) { ++ long least = tag.getLong("UUIDLeast"); ++ long most = tag.getLong("UUIDMost"); ++ ++ if (least != 0L && most != 0L) { ++ this.uniqueId = new UUID(most, least); ++ CraftWorld world = (CraftWorld) server.getWorld(this.uniqueId); ++ if (world != null) { ++ dimension = StringTag.create("minecraft:" + world.getName().toLowerCase(java.util.Locale.ENGLISH)); ++ } else { ++ dimension = StringTag.create("bukkit:_invalidworld_"); ++ } ++ } else { ++ dimension = StringTag.create("bukkit:_invalidworld_"); ++ } ++ } ++ DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, dimension)); // CraftBukkit - decompile error ++ // Paper end - fix "Not a string" spam + Logger logger = MapItemSavedData.LOGGER; + + logger.getClass(); diff --git a/patches/server-remapped/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/patches/server-remapped/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch new file mode 100644 index 0000000000..d952b410f0 --- /dev/null +++ b/patches/server-remapped/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Sun, 4 Oct 2020 19:55:25 -0700 +Subject: [PATCH] Fix CME on adding a passenger in CreatureSpawnEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a623c22cd03ad92657e661851fddc76a30986755..90e9797cc1f3a4aa0a2bee28dca364e6f6dd0c0b 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -3180,7 +3180,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public Stream getSelfAndPassengers() { +- return Stream.concat(Stream.of(this), this.passengers.stream().flatMap(Entity::getSelfAndPassengers)); ++ return Stream.concat(Stream.of(this), com.google.common.collect.ImmutableList.copyOf(this.passengers).stream().flatMap(Entity::getSelfAndPassengers)); // Paper + } + + public boolean hasOnePlayerPassenger() { diff --git a/patches/server-remapped/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch b/patches/server-remapped/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch new file mode 100644 index 0000000000..02442096a4 --- /dev/null +++ b/patches/server-remapped/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Wed, 18 Mar 2020 00:07:46 -0500 +Subject: [PATCH] MC-147729: Drop items that are extra from a crafting recipe + + +diff --git a/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java b/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java +index a18aa176850bef45afcaf5742e9afbfa39281e22..c6ba6aabf94c26cccbd14689ea32373c17bbccc4 100644 +--- a/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java ++++ b/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java +@@ -71,7 +71,12 @@ public class ServerPlaceRecipe implements PlaceRecipe +Date: Wed, 1 Jun 2016 23:29:17 -0400 +Subject: [PATCH] Reset Ender Crystals on Dragon Spawn + +Crystals can end up in a bad state in certain conditions which causes +an exception on the expected number of crystals going negative. + +This ensures the crystals/pillars are in expected state when the dragon spawns. + +See #3522 + +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 4b18931225ef60dbcffd7fcc20d0e9ce62348a07..590df3b93b897613cad74f9920aec62b33a2f7f7 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -441,6 +441,7 @@ public class EndDragonFight { + entityenderdragon.moveTo(0.0D, 128.0D, 0.0D, this.level.random.nextFloat() * 360.0F, 0.0F); + this.level.addFreshEntity(entityenderdragon); + this.dragonUUID = entityenderdragon.getUUID(); ++ this.resetSpikeCrystals(); // Paper + return entityenderdragon; + } + diff --git a/patches/server-remapped/0579-Fix-for-large-move-vectors-crashing-server.patch b/patches/server-remapped/0579-Fix-for-large-move-vectors-crashing-server.patch new file mode 100644 index 0000000000..42d90f77ee --- /dev/null +++ b/patches/server-remapped/0579-Fix-for-large-move-vectors-crashing-server.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 17 May 2020 23:47:33 -0700 +Subject: [PATCH] Fix for large move vectors crashing server + +Check movement distance also based on current position. + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index ab45497e8f7720c9d60626b32e9c95779af676b0..3a114bec14fcc6c1e1045e2b99178a6adb25f387 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -516,19 +516,24 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) { + ServerLevel worldserver = this.player.getLevel(); +- double d0 = entity.getX(); +- double d1 = entity.getY(); +- double d2 = entity.getZ(); +- double d3 = packet.getX(); +- double d4 = packet.getY(); +- double d5 = packet.getZ(); ++ double d0 = entity.getX();double fromX = d0; // Paper - OBFHELPER ++ double d1 = entity.getY();double fromY = d1; // Paper - OBFHELPER ++ double d2 = entity.getZ();double fromZ = d2; // Paper - OBFHELPER ++ double d3 = packet.getX();double toX = d3; // Paper - OBFHELPER ++ double d4 = packet.getY();double toY = d4; // Paper - OBFHELPER ++ double d5 = packet.getZ();double toZ = d5; // Paper - OBFHELPER + float f = packet.getYRot(); + float f1 = packet.getXRot(); + double d6 = d3 - this.vehicleFirstGoodX; + double d7 = d4 - this.vehicleFirstGoodY; + double d8 = d5 - this.vehicleFirstGoodZ; + double d9 = entity.getDeltaMovement().lengthSqr(); +- double d10 = d6 * d6 + d7 * d7 + d8 * d8; ++ // Paper start - fix large move vectors killing the server ++ double currDeltaX = toX - fromX; ++ double currDeltaY = toY - fromY; ++ double currDeltaZ = toZ - fromZ; ++ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); ++ // Paper end - fix large move vectors killing the server + + + // CraftBukkit start - handle custom speeds and skipped ticks +@@ -1230,7 +1235,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + double d2 = this.player.getZ(); + double d3 = this.player.getY(); + double d4 = packet.getX(this.player.getX());double toX = d4; // Paper - OBFHELPER +- double d5 = packet.getY(this.player.getY()); ++ double d5 = packet.getY(this.player.getY());double toY = d5; // Paper - OBFHELPER + double d6 = packet.getZ(this.player.getZ());double toZ = d6; // Paper - OBFHELPER + float f = packet.getYRot(this.player.yRot); + float f1 = packet.getXRot(this.player.xRot); +@@ -1238,7 +1243,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + double d8 = d5 - this.firstGoodY; + double d9 = d6 - this.firstGoodZ; + double d10 = this.player.getDeltaMovement().lengthSqr(); +- double d11 = d7 * d7 + d8 * d8 + d9 * d9; ++ // Paper start - fix large move vectors killing the server ++ double currDeltaX = toX - prevX; ++ double currDeltaY = toY - prevY; ++ double currDeltaZ = toZ - prevZ; ++ double d11 = Math.max(d7 * d7 + d8 * d8 + d9 * d9, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); ++ // Paper end - fix large move vectors killing the server + + if (this.player.isSleeping()) { + if (d11 > 1.0D) { diff --git a/patches/server-remapped/0580-Optimise-getType-calls.patch b/patches/server-remapped/0580-Optimise-getType-calls.patch new file mode 100644 index 0000000000..f1103a3993 --- /dev/null +++ b/patches/server-remapped/0580-Optimise-getType-calls.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 3 Jun 2020 11:37:13 -0700 +Subject: [PATCH] Optimise getType calls + +Remove the map lookup for converting from Block->Bukkit Material + +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockState.java b/src/main/java/net/minecraft/world/level/block/state/BlockState.java +index 9958cdf55cef2177fafd0cdae48da9db064af9f1..4263ac345d57e36e010e3dd009130c02799b249c 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockState.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockState.java +@@ -11,6 +11,19 @@ public class BlockState extends BlockBehaviour.BlockStateBase { + + public static final Codec CODEC = codec((Codec) Registry.BLOCK, Block::defaultBlockState).stable(); + ++ ++ // Paper start - optimise getType calls ++ org.bukkit.Material cachedMaterial; ++ ++ public final org.bukkit.Material getBukkitMaterial() { ++ if (this.cachedMaterial == null) { ++ this.cachedMaterial = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(this.getBlock()); ++ } ++ ++ return this.cachedMaterial; ++ } ++ // Paper end - optimise getType calls ++ + public BlockState(Block block, ImmutableMap, Comparable> propertyMap, MapCodec mapcodec) { + super(block, propertyMap, mapcodec); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java +index fe00c8fdacc28a68c732aac0b887ea107d87e979..227974a85a81c623311301e28e83e85424b05f3d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java +@@ -78,7 +78,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot { + public Material getBlockType(int x, int y, int z) { + CraftChunk.validateChunkCoordinates(x, y, z); + +- return CraftMagicNumbers.getMaterial(blockids[y >> 4].get(x, y & 0xF, z).getBlock()); ++ return blockids[y >> 4].get(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index e09f65f0b06c8fb9a965b921c2c8e68ae2ac1e55..37eceaef1212e2ee13aa763a5ede24ec170e5391 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -211,7 +211,7 @@ public class CraftBlock implements Block { + + @Override + public Material getType() { +- return CraftMagicNumbers.getMaterial(world.getBlockState(position).getBlock()); ++ return world.getBlockState(position).getBukkitMaterial(); // Paper - optimise getType calls + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +index 754559c9e47032845fdc94eedad0cece0e0ae4c7..7e4c522605cf04a38a7a0f54e7ac6ea0e372c98d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +@@ -134,7 +134,7 @@ public class CraftBlockState implements BlockState { + + @Override + public Material getType() { +- return CraftMagicNumbers.getMaterial(data.getBlock()); ++ return data.getBukkitMaterial(); // Paper - optimise getType calls + } + + public void setFlag(int flag) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +index 03e065bf92cafd376ad0f878584cdac6fd196245..d93f2373f3127462aa2f9b69f7cc808b58d47b61 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +@@ -45,7 +45,7 @@ public class CraftBlockData implements BlockData { + + @Override + public Material getMaterial() { +- return CraftMagicNumbers.getMaterial(state.getBlock()); ++ return state.getBukkitMaterial(); // Paper - optimise getType calls + } + + public BlockState getState() { +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +index fd2cb2a584fea360fcf8180338708f35c4e3dc1f..a463b89888460e5a894098c20eb4c4a78c04642c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +@@ -73,7 +73,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + + @Override + public Material getType(int x, int y, int z) { +- return CraftMagicNumbers.getMaterial(getTypeId(x, y, z).getBlock()); ++ return getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls + } + + @Override diff --git a/patches/server-remapped/0581-Villager-resetOffers.patch b/patches/server-remapped/0581-Villager-resetOffers.patch new file mode 100644 index 0000000000..2d03e1410f --- /dev/null +++ b/patches/server-remapped/0581-Villager-resetOffers.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Mon, 7 Oct 2019 00:15:37 -0500 +Subject: [PATCH] Villager#resetOffers + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +index 9eee68a5a84e121698d26bd54212a72c75e16251..407a68edf6408400f1a6c5bb1a6cbbfae08ac2cd 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -111,6 +111,13 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan + return this.tradingPlayer != null; + } + ++ // Paper start ++ public void resetOffers() { ++ this.offers = new MerchantOffers(); ++ this.updateTrades(); ++ } ++ // Paper end ++ + @Override + public MerchantOffers getOffers() { + if (this.offers == null) { +@@ -232,6 +239,7 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan + return this.level; + } + ++ protected final void updateTrades() { updateTrades(); } // Paper - OBFHELPER + protected abstract void updateTrades(); + + protected void addOffersFromItemListings(MerchantOffers recipeList, VillagerTrades.ItemListing[] pool, int count) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java +index 8ffdfe3e8229b556838eab18dcb6bfb0c05a6063..7f887e883a87f2df7ae428ffddb072724d602d62 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java +@@ -70,4 +70,11 @@ public class CraftAbstractVillager extends CraftAgeable implements AbstractVilla + public HumanEntity getTrader() { + return getMerchant().getTrader(); + } ++ ++ // Paper start ++ @Override ++ public void resetOffers() { ++ getHandle().resetOffers(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/patches/server-remapped/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch new file mode 100644 index 0000000000..fc2f46516c --- /dev/null +++ b/patches/server-remapped/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Jul 2020 20:46:50 -0700 +Subject: [PATCH] Improve inlinig for some hot IBlockData methods + + +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index f2fefdad26057c722085e60ba837fe2c117f55f7..17baae6b11f191f4738a107c7e62ea5bdac17a3c 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -390,7 +390,14 @@ public abstract class BlockBehaviour { + } + // Paper end + ++ // Paper start ++ protected boolean isTicking; ++ protected FluidState fluid; ++ // Paper end ++ + public void initCache() { ++ this.fluid = this.getBlock().getFluidState(this.asState()); // Paper - moved from getFluid() ++ this.isTicking = this.getBlock().isRandomlyTicking(this.asState()); // Paper - moved from isTicking() + if (!this.getBlock().hasDynamicShape()) { + this.cache = new BlockBehaviour.BlockStateBase.Cache(this.asState()); + } +@@ -429,19 +436,19 @@ public abstract class BlockBehaviour { + return this.getBlock().getOcclusionShape(this.asState(), world, pos); + } + +- public boolean hasLargeCollisionShape() { ++ public final boolean hasLargeCollisionShape() { // Paper + return this.cache == null || this.cache.largeCollisionShape; + } + +- public boolean useShapeForLightOcclusion() { ++ public final boolean useShapeForLightOcclusion() { // Paper + return this.useShapeForLightOcclusion; + } + +- public int getLightEmission() { ++ public final int getLightEmission() { // Paper + return this.lightEmission; + } + +- public boolean isAir() { ++ public final boolean isAir() { // Paper + return this.isAir; + } + +@@ -507,7 +514,7 @@ public abstract class BlockBehaviour { + } + } + +- public boolean canOcclude() { ++ public final boolean canOcclude() { // Paper + return this.canOcclude; + } + +@@ -679,12 +686,12 @@ public abstract class BlockBehaviour { + return this.getBlock().is(block); + } + +- public FluidState getFluidState() { +- return this.getBlock().getFluidState(this.asState()); ++ public final FluidState getFluidState() { // Paper ++ return this.fluid; // Paper - moved into init + } + +- public boolean isRandomlyTicking() { +- return this.getBlock().isRandomlyTicking(this.asState()); ++ public final boolean isRandomlyTicking() { // Paper ++ return this.isTicking; // Paper - moved into init + } + + public SoundType getSoundType() { +diff --git a/src/main/java/net/minecraft/world/level/material/FluidState.java b/src/main/java/net/minecraft/world/level/material/FluidState.java +index c077e4a7ce6a484956206eaab9dfde057b7e429a..69cf9e149c207336c537a00f08251a2252752df6 100644 +--- a/src/main/java/net/minecraft/world/level/material/FluidState.java ++++ b/src/main/java/net/minecraft/world/level/material/FluidState.java +@@ -20,8 +20,12 @@ public final class FluidState extends StateHolder { + + public static final Codec CODEC = codec((Codec) Registry.FLUID, Fluid::defaultFluidState).stable(); + ++ // Paper start ++ protected final boolean isEmpty; ++ // Paper end + public FluidState(Fluid fluid, ImmutableMap, Comparable> propertiesMap, MapCodec mapcodec) { + super(fluid, propertiesMap, mapcodec); ++ this.isEmpty = fluid.isEmpty(); // Paper - moved from isEmpty() + } + + public Fluid getType() { +@@ -33,7 +37,7 @@ public final class FluidState extends StateHolder { + } + + public boolean isEmpty() { +- return this.getType().isEmpty(); ++ return this.isEmpty; // Paper - moved into constructor + } + + public float getHeight(BlockGetter world, BlockPos pos) { diff --git a/patches/server-remapped/0583-Retain-block-place-order-when-capturing-blockstates.patch b/patches/server-remapped/0583-Retain-block-place-order-when-capturing-blockstates.patch new file mode 100644 index 0000000000..1d1bff4b34 --- /dev/null +++ b/patches/server-remapped/0583-Retain-block-place-order-when-capturing-blockstates.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 7 Aug 2020 04:27:56 -0700 +Subject: [PATCH] Retain block place order when capturing blockstates + +Fixes twisted vines not connecting properly when grown via +bonemeal by a player. + +In general, look at making this logic more robust (i.e properly handling +cases where a captured entry is overriden) - but for now this will do. + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index ebb92f88e0402681c47834bcf45e6b236748289a..2ad8a4558aa812885adebee8c05dab45f2bf5f90 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -135,7 +135,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean captureBlockStates = false; + public boolean captureTreeGeneration = false; + public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper +- public Map capturedTileEntities = new HashMap<>(); ++ public Map capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper + public List captureDrops; + public long ticksPerAnimalSpawns; + public long ticksPerMonsterSpawns; diff --git a/patches/server-remapped/0584-Reduce-blockpos-allocation-from-pathfinding.patch b/patches/server-remapped/0584-Reduce-blockpos-allocation-from-pathfinding.patch new file mode 100644 index 0000000000..9371d97aec --- /dev/null +++ b/patches/server-remapped/0584-Reduce-blockpos-allocation-from-pathfinding.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 25 Apr 2020 17:10:55 -0700 +Subject: [PATCH] Reduce blockpos allocation from pathfinding + + +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +index 7ae24381b91c282745b7fe5f6897865e74bc0acf..3c460682611969a5db136aa41ca0d230c6228d56 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +@@ -498,7 +498,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { + return BlockPathTypes.DANGER_FIRE; + } + +- if (iblockaccess.getFluidState(blockposition_mutableblockposition).is((Tag) FluidTags.WATER)) { ++ if (iblockdata.getFluidState().is((Tag) FluidTags.WATER)) { // Paper - remove another getType call + return BlockPathTypes.WATER_BORDER; + } + } // Paper +@@ -528,7 +528,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { + } else if (iblockdata.is(Blocks.COCOA)) { + return BlockPathTypes.COCOA; + } else { +- FluidState fluid = iblockaccess.getFluidState(blockposition); ++ FluidState fluid = iblockdata.getFluidState(); // Paper - remove another get type call + + return fluid.is((Tag) FluidTags.WATER) ? BlockPathTypes.WATER : (fluid.is((Tag) FluidTags.LAVA) ? BlockPathTypes.LAVA : (isBurningBlock(iblockdata) ? BlockPathTypes.DAMAGE_FIRE : (DoorBlock.isWoodenDoor(iblockdata) && !(Boolean) iblockdata.getValue(DoorBlock.OPEN) ? BlockPathTypes.DOOR_WOOD_CLOSED : (block instanceof DoorBlock && material == Material.ORE && !(Boolean) iblockdata.getValue(DoorBlock.OPEN) ? BlockPathTypes.DOOR_IRON_CLOSED : (block instanceof DoorBlock && (Boolean) iblockdata.getValue(DoorBlock.OPEN) ? BlockPathTypes.DOOR_OPEN : (block instanceof BaseRailBlock ? BlockPathTypes.RAIL : (block instanceof LeavesBlock ? BlockPathTypes.LEAVES : (!block.is((Tag) BlockTags.FENCES) && !block.is((Tag) BlockTags.WALLS) && (!(block instanceof FenceGateBlock) || (Boolean) iblockdata.getValue(FenceGateBlock.OPEN)) ? (!iblockdata.isPathfindable(iblockaccess, blockposition, PathComputationType.LAND) ? BlockPathTypes.BLOCKED : BlockPathTypes.OPEN) : BlockPathTypes.FENCE)))))))); + } diff --git a/patches/server-remapped/0585-Fix-item-locations-dropped-from-campfires.patch b/patches/server-remapped/0585-Fix-item-locations-dropped-from-campfires.patch new file mode 100644 index 0000000000..535e3ffd30 --- /dev/null +++ b/patches/server-remapped/0585-Fix-item-locations-dropped-from-campfires.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 3 Oct 2020 20:32:25 -0500 +Subject: [PATCH] Fix item locations dropped from campfires + +Fixes #4259 by not flooring the blockposition among other weirdness + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +index 0c90b1b13611843ba4402c8ccf0b15781b85e773..6c38361d744eae763b6c131ad314485f5a88fcfc 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +@@ -14,6 +14,7 @@ import net.minecraft.world.Clearable; + import net.minecraft.world.ContainerHelper; + import net.minecraft.world.Containers; + import net.minecraft.world.SimpleContainer; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.CampfireCookingRecipe; + import net.minecraft.world.item.crafting.RecipeType; +@@ -91,7 +92,11 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable, Ticka + result = blockCookEvent.getResult(); + itemstack1 = CraftItemStack.asNMSCopy(result); + // CraftBukkit end +- Containers.dropItemStack(this.level, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack1); ++ // Paper start ++ ItemEntity droppedItem = new ItemEntity(this.level, blockposition.getX() + 0.5D, blockposition.getY() + 0.5D, blockposition.getZ() + 0.5D, itemstack1.split(this.level.random.nextInt(21) + 10)); ++ droppedItem.setDeltaMovement(this.level.random.nextGaussian() * 0.05D, this.level.random.nextGaussian() * 0.05D + 0.2D, this.level.random.nextGaussian() * 0.05D); ++ this.level.addFreshEntity(droppedItem); ++ // Paper end + this.items.set(i, ItemStack.EMPTY); + this.markUpdated(); + } diff --git a/patches/server-remapped/0586-Player-elytra-boost-API.patch b/patches/server-remapped/0586-Player-elytra-boost-API.patch new file mode 100644 index 0000000000..92e087e79f --- /dev/null +++ b/patches/server-remapped/0586-Player-elytra-boost-API.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Tue, 14 Apr 2020 12:05:22 +0200 +Subject: [PATCH] Player elytra boost API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 7aae63d22167dc1b3ec7e8bc8672855c2038007e..94240b70e245bdc3dda60420f5787f8d5dcc1958 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -67,6 +67,7 @@ import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeMap; + import net.minecraft.world.entity.ai.attributes.Attributes; ++import net.minecraft.world.entity.projectile.FireworkRocketEntity; + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; +@@ -2281,6 +2282,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + throw new RuntimeException("Unknown settings type"); + } ++ ++ @Override ++ public org.bukkit.entity.Firework boostElytra(ItemStack firework) { ++ Validate.isTrue(isGliding(), "Player must be gliding"); ++ Validate.isTrue(firework != null, "firework == null"); ++ Validate.isTrue(firework.getType() == Material.FIREWORK_ROCKET, "Firework must be Material.FIREWORK_ROCKET"); ++ ++ net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(firework); ++ net.minecraft.world.level.Level world = ((CraftWorld) getWorld()).getHandle(); ++ FireworkRocketEntity entity = new FireworkRocketEntity(world, item, getHandle()); ++ return world.addFreshEntity(entity) ++ ? (org.bukkit.entity.Firework) entity.getBukkitEntity() ++ : null; ++ } + // Paper end + + // Spigot start diff --git a/patches/server-remapped/0587-Fixed-TileEntityBell-memory-leak.patch b/patches/server-remapped/0587-Fixed-TileEntityBell-memory-leak.patch new file mode 100644 index 0000000000..de814154fd --- /dev/null +++ b/patches/server-remapped/0587-Fixed-TileEntityBell-memory-leak.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: giacomo <32515303+giacomozama@users.noreply.github.com> +Date: Sat, 10 Oct 2020 12:15:33 +0200 +Subject: [PATCH] Fixed TileEntityBell memory leak + +TileEntityBell has a list of entities (entitiesAtRing) that was not being cleared at the right time, causing leaks whenever a bell would be rung near a crowd of entities. + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +index aa45a142aa11acc9fd08b4877891741f3cbd936d..3f9179a7678091875161a34d13b6ec0e78025c4c 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -27,8 +27,8 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity + public int ticks; + public boolean shaking; + public Direction clickDirection; +- private List nearbyEntities; +- private boolean resonating; ++ private List nearbyEntities; private List getEntitiesAtRing() { return this.nearbyEntities; } // Paper - OBFHELPER ++ private boolean resonating; private boolean getShouldReveal() { return this.resonating; } // Paper - OBFHELPER + private int resonationTicks; + + public BellBlockEntity() { +@@ -57,6 +57,11 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity + + if (this.ticks >= 50) { + this.shaking = false; ++ // Paper start ++ if (!this.getShouldReveal()) { ++ this.getEntitiesAtRing().clear(); ++ } ++ // Paper end + this.ticks = 0; + } + +@@ -71,6 +76,7 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity + } else { + this.makeRaidersGlow(this.level); + this.showBellParticles(this.level); ++ this.getEntitiesAtRing().clear(); // Paper + this.resonating = false; + } + } +@@ -111,11 +117,12 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity + LivingEntity entityliving = (LivingEntity) iterator.next(); + + if (entityliving.isAlive() && !entityliving.removed && blockposition.closerThan((Position) entityliving.position(), 32.0D)) { +- entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, (Object) this.level.getGameTime()); ++ entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.level.getGameTime()); // Paper - decompile fix + } + } + } + ++ this.getEntitiesAtRing().removeIf(e -> !e.isAlive()); // Paper + } + + private boolean areRaidersNearby() { diff --git a/patches/server-remapped/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/patches/server-remapped/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch new file mode 100644 index 0000000000..6072b2edd8 --- /dev/null +++ b/patches/server-remapped/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Toon Schoenmakers +Date: Fri, 23 Oct 2020 15:01:44 +0200 +Subject: [PATCH] Avoid error bubbling up when item stack is empty in fishing + loot + +This can realistically only happen if there's custom loot active on fishing +which can return 0 items. This would disconnect the player who's fishing. + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +index 7bff012f3cd4458673ee02e5f5f830fc0ef983a3..ef71cca9922ed134ec82fb2982d375bf16f47b17 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +@@ -481,9 +481,15 @@ public class FishingHook extends Projectile { + + while (iterator.hasNext()) { + ItemStack itemstack1 = (ItemStack) iterator.next(); +- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), itemstack1); ++ // Paper start, new EntityItem would throw if for whatever reason (mostly shitty datapacks) the itemstack1 turns out to be empty ++ // if the item stack is empty we instead just have our entityitem as null ++ ItemEntity entityitem = null; ++ if (!itemstack1.isEmpty()) { ++ entityitem = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), itemstack1); ++ } ++ // Paper end + // CraftBukkit start +- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null + playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); + this.level.getCraftServer().getPluginManager().callEvent(playerFishEvent); + +@@ -496,8 +502,12 @@ public class FishingHook extends Projectile { + double d2 = entityhuman.getZ() - this.getZ(); + double d3 = 0.1D; + +- entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); +- this.level.addFreshEntity(entityitem); ++ // Paper start, entity item can be null, so we need to check against this ++ if (entityitem != null) { ++ entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); ++ this.level.addFreshEntity(entityitem); ++ } ++ // Paper end + // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() + if (playerFishEvent.getExpToDrop() > 0) { + entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper diff --git a/patches/server-remapped/0589-Add-getOfflinePlayerIfCached-String.patch b/patches/server-remapped/0589-Add-getOfflinePlayerIfCached-String.patch new file mode 100644 index 0000000000..b581372702 --- /dev/null +++ b/patches/server-remapped/0589-Add-getOfflinePlayerIfCached-String.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: oxygencraft <21054297+oxygencraft@users.noreply.github.com> +Date: Sun, 25 Oct 2020 18:34:50 +1100 +Subject: [PATCH] Add getOfflinePlayerIfCached(String) + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index e599be15af17e5e45d2b694c30140cc4a787a7f5..046fbc646d2818bb2c7e08ff22093523e8246523 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1612,6 +1612,28 @@ public final class CraftServer implements Server { + return result; + } + ++ // Paper start ++ @Override ++ @Nullable ++ public OfflinePlayer getOfflinePlayerIfCached(String name) { ++ Validate.notNull(name, "Name cannot be null"); ++ Validate.notEmpty(name, "Name cannot be empty"); ++ ++ OfflinePlayer result = getPlayerExact(name); ++ if (result == null) { ++ GameProfile profile = console.getProfileCache().getProfileIfCached(name); ++ ++ if (profile != null) { ++ result = getOfflinePlayer(profile); ++ } ++ } else { ++ offlinePlayers.remove(result.getUniqueId()); ++ } ++ ++ return result; ++ } ++ // Paper end ++ + @Override + public OfflinePlayer getOfflinePlayer(UUID id) { + Validate.notNull(id, "UUID cannot be null"); diff --git a/patches/server-remapped/0590-Add-ignore-discounts-API.patch b/patches/server-remapped/0590-Add-ignore-discounts-API.patch new file mode 100644 index 0000000000..e20018337f --- /dev/null +++ b/patches/server-remapped/0590-Add-ignore-discounts-API.patch @@ -0,0 +1,143 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Mon, 9 Nov 2020 20:44:51 +0100 +Subject: [PATCH] Add ignore discounts API + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index e9912551e6a19d6ad3b20fad1b716577b9d28f99..415fa3591add1f1ab22dd5866e110dbfccd0ec93 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -459,6 +459,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + + while (iterator.hasNext()) { + MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); ++ if (merchantrecipe.ignoreDiscounts) continue; // Paper + + // CraftBukkit start + int bonus = -Mth.floor((float) i * merchantrecipe.getPriceMultiplier()); +@@ -478,6 +479,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + + while (iterator1.hasNext()) { + MerchantOffer merchantrecipe1 = (MerchantOffer) iterator1.next(); ++ if (merchantrecipe1.ignoreDiscounts) continue; // Paper + double d0 = 0.3D + 0.0625D * (double) j; + int k = (int) Math.floor(d0 * (double) merchantrecipe1.getBaseCostA().getCount()); + +diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java +index fa74813e0fe76612023830b2fc41d41aa0b4f10e..25a0f180967911d5916eb71334a94baec84eafbf 100644 +--- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java ++++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java +@@ -19,6 +19,7 @@ public class MerchantOffer { + private int demand; + public float priceMultiplier; + public int xp; ++ public boolean ignoreDiscounts; // Paper + // CraftBukkit start + private CraftMerchantRecipe bukkitHandle; + +@@ -27,7 +28,12 @@ public class MerchantOffer { + } + + public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { +- this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier); ++ // Paper start - add ignoreDiscounts param ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, false, bukkit); ++ } ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, ignoreDiscounts); ++ // Paper end + this.bukkitHandle = bukkit; + } + // CraftBukkit end +@@ -59,6 +65,7 @@ public class MerchantOffer { + + this.specialPriceDiff = nbttagcompound.getInt("specialPrice"); + this.demand = nbttagcompound.getInt("demand"); ++ this.ignoreDiscounts = nbttagcompound.getBoolean("Paper.IgnoreDiscounts"); // Paper + } + + public MerchantOffer(ItemStack buyItem, ItemStack sellItem, int maxUses, int rewardedExp, float priceMultiplier) { +@@ -70,10 +77,19 @@ public class MerchantOffer { + } + + public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int rewardedExp, float priceMultiplier) { +- this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, rewardedExp, priceMultiplier, 0); ++ // Paper start - add ignoreDiscounts param ++ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, rewardedExp, priceMultiplier, false); ++ } ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, boolean ignoreDiscounts) { ++ this(itemstack, itemstack1, itemstack2, i, j, k, f, 0, ignoreDiscounts); + } + + public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l) { ++ this(itemstack, itemstack1, itemstack2, i, j, k, f, l, false); ++ } ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l, boolean ignoreDiscounts) { ++ this.ignoreDiscounts = ignoreDiscounts; ++ // Paper end + this.rewardExp = true; + this.xp = 1; + this.baseCostA = itemstack; +@@ -189,6 +205,7 @@ public class MerchantOffer { + nbttagcompound.putFloat("priceMultiplier", this.priceMultiplier); + nbttagcompound.putInt("specialPrice", this.specialPriceDiff); + nbttagcompound.putInt("demand", this.demand); ++ nbttagcompound.putBoolean("Paper.IgnoreDiscounts", this.ignoreDiscounts); // Paper + return nbttagcompound; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java +index 212f9c7f3e73ffedf27b94abeac957b7d866a086..a6c8588f10c4c109833aea6a8b02c9048b6d9ea4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java +@@ -17,7 +17,12 @@ public class CraftMerchantRecipe extends MerchantRecipe { + } + + public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier) { +- super(result, uses, maxUses, experienceReward, experience, priceMultiplier); ++ // Paper start - add ignoreDiscounts param ++ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, false); ++ } ++ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, boolean ignoreDiscounts) { ++ super(result, uses, maxUses, experienceReward, experience, priceMultiplier, ignoreDiscounts); ++ // Paper end + this.handle = new net.minecraft.world.item.trading.MerchantOffer( + net.minecraft.world.item.ItemStack.EMPTY, + net.minecraft.world.item.ItemStack.EMPTY, +@@ -26,6 +31,7 @@ public class CraftMerchantRecipe extends MerchantRecipe { + maxUses, + experience, + priceMultiplier, ++ ignoreDiscounts, // Paper - add ignoreDiscounts param + this + ); + this.setExperienceReward(experienceReward); +@@ -81,6 +87,18 @@ public class CraftMerchantRecipe extends MerchantRecipe { + handle.priceMultiplier = priceMultiplier; + } + ++ // Paper start ++ @Override ++ public boolean shouldIgnoreDiscounts() { ++ return this.handle.ignoreDiscounts; ++ } ++ ++ @Override ++ public void setIgnoreDiscounts(boolean ignoreDiscounts) { ++ this.handle.ignoreDiscounts = ignoreDiscounts; ++ } ++ // Paper end ++ + public net.minecraft.world.item.trading.MerchantOffer toMinecraft() { + List ingredients = getIngredients(); + Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients"); +@@ -95,7 +113,7 @@ public class CraftMerchantRecipe extends MerchantRecipe { + if (recipe instanceof CraftMerchantRecipe) { + return (CraftMerchantRecipe) recipe; + } else { +- CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier()); ++ CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.shouldIgnoreDiscounts()); // Paper - shouldIgnoreDiscounts + craft.setIngredients(recipe.getIngredients()); + + return craft; diff --git a/patches/server-remapped/0591-Toggle-for-removing-existing-dragon.patch b/patches/server-remapped/0591-Toggle-for-removing-existing-dragon.patch new file mode 100644 index 0000000000..184345a27e --- /dev/null +++ b/patches/server-remapped/0591-Toggle-for-removing-existing-dragon.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 30 Sep 2020 22:49:14 +0200 +Subject: [PATCH] Toggle for removing existing dragon + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 02bb85364560784adea47c877c13291c3d016b86..424754a0183b071d20c86f0420cec784a8992e2b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -683,4 +683,12 @@ public class PaperWorldConfig { + log("Using vanilla redstone algorithm."); + } + } ++ ++ public boolean shouldRemoveDragon = false; ++ private void shouldRemoveDragon() { ++ shouldRemoveDragon = getBoolean("should-remove-dragon", shouldRemoveDragon); ++ if (shouldRemoveDragon) { ++ log("The Ender Dragon will be removed if she already exists without a portal."); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 590df3b93b897613cad74f9920aec62b33a2f7f7..84447e9845edad2d228b94184b35b4afb453a14b 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -210,7 +210,7 @@ public class EndDragonFight { + this.dragonUUID = entityenderdragon.getUUID(); + EndDragonFight.LOGGER.info("Found that there's a dragon still alive ({})", entityenderdragon); + this.dragonKilled = false; +- if (!flag) { ++ if (!flag && this.level.paperConfig.shouldRemoveDragon) { // Paper + EndDragonFight.LOGGER.info("But we didn't have a portal, let's remove it."); + entityenderdragon.remove(); + this.dragonUUID = null; diff --git a/patches/server-remapped/0592-Fix-client-lag-on-advancement-loading.patch b/patches/server-remapped/0592-Fix-client-lag-on-advancement-loading.patch new file mode 100644 index 0000000000..2affffb90a --- /dev/null +++ b/patches/server-remapped/0592-Fix-client-lag-on-advancement-loading.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Sat, 31 Oct 2020 11:49:01 -0700 +Subject: [PATCH] Fix client lag on advancement loading + +When new advancements are added via the UnsafeValues#loadAdvancement +API, it triggers a full datapack reload when this is not necessary. The +advancement is already loaded directly into the advancement registry, +and the point of saving the advancement to the Bukkit datapack seems to +be for persistence. By removing the call to reload datapacks when an +advancement is loaded, the client no longer completely freezes up when +adding a new advancement. +To ensure the client still receives the updated advancement data, we +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/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index acb41cc3965154c5b515cd8e808bf2cf5dc850e4..b8d3f2c59199e245e2035d6205dd1a042aa93f77 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -97,6 +97,7 @@ public class PlayerAdvancements { + + } + ++ public final void reload(ServerAdvancementManager advancementDataWorld) { this.reload(advancementDataWorld); } // Paper - OBFHELPER + public void reload(ServerAdvancementManager advancementLoader) { + this.stopListening(); + this.advancements.clear(); +@@ -393,6 +394,7 @@ public class PlayerAdvancements { + + } + ++ public final void sendUpdateIfNeeded(ServerPlayer entityPlayer) { this.flushDirty(entityPlayer); } // Paper - OBFHELPER + public void flushDirty(ServerPlayer player) { + if (this.isFirstPacket || !this.visibilityChanged.isEmpty() || !this.progressChanged.isEmpty()) { + Map map = Maps.newHashMap(); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 9a16882deee21faf78ea46e08b2f2ad3fbb6021b..ac94fd569bd4c79e30adef148e09e395ba8c1812 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -307,7 +307,13 @@ public final class CraftMagicNumbers implements UnsafeValues { + Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex); + } + +- MinecraftServer.getServer().getPlayerList().reloadResources(); ++ // Paper start ++ //MinecraftServer.getServer().getPlayerList().reload(); ++ MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> { ++ player.getAdvancements().reload(MinecraftServer.getServer().getAdvancements()); ++ player.getAdvancements().sendUpdateIfNeeded(player); ++ }); ++ // Paper end + + return bukkit; + } diff --git a/patches/server-remapped/0593-Item-no-age-no-player-pickup.patch b/patches/server-remapped/0593-Item-no-age-no-player-pickup.patch new file mode 100644 index 0000000000..0c17d7553d --- /dev/null +++ b/patches/server-remapped/0593-Item-no-age-no-player-pickup.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Smith +Date: Sat, 7 Nov 2020 01:20:33 +0000 +Subject: [PATCH] Item no age & no player pickup + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +index 9a410f557988d737c3b930a79ef2ccb2b5c8b406..aff17bb3bd22de492b9736d27b7f3e4bdb37134c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +@@ -10,6 +10,12 @@ import org.bukkit.entity.Item; + import org.bukkit.inventory.ItemStack; + + public class CraftItem extends CraftEntity implements Item { ++ ++ // Paper start ++ private final static int NO_AGE_TIME = (int) Short.MIN_VALUE; ++ private final static int NO_PICKUP_TIME = (int) Short.MAX_VALUE; ++ // Paper end ++ + private final ItemEntity item; + + public CraftItem(CraftServer server, Entity entity, ItemEntity item) { +@@ -57,6 +63,26 @@ public class CraftItem extends CraftEntity implements Item { + public void setCanMobPickup(boolean canMobPickup) { + item.canMobPickup = canMobPickup; + } ++ ++ @Override ++ public boolean canPlayerPickup() { ++ return item.pickupDelay != NO_PICKUP_TIME; ++ } ++ ++ @Override ++ public void setCanPlayerPickup(boolean canPlayerPickup) { ++ item.pickupDelay = canPlayerPickup ? 0 : NO_PICKUP_TIME; ++ } ++ ++ @Override ++ public boolean willAge() { ++ return item.age != NO_AGE_TIME; ++ } ++ ++ @Override ++ public void setWillAge(boolean willAge) { ++ item.age = willAge ? 0 : NO_AGE_TIME; ++ } + // Paper End + + @Override diff --git a/patches/server-remapped/0594-Beacon-API-custom-effect-ranges.patch b/patches/server-remapped/0594-Beacon-API-custom-effect-ranges.patch new file mode 100644 index 0000000000..78d729cb3e --- /dev/null +++ b/patches/server-remapped/0594-Beacon-API-custom-effect-ranges.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 24 Jun 2020 12:39:08 -0600 +Subject: [PATCH] Beacon API - custom effect ranges + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +index 5f75c6d653a31f65fcf9c0e280d796e15d059c00..fed29e5707e2a7f64159d284c52647dd91e1948e 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -71,6 +71,26 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + return (hasSecondaryEffect()) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, getLevelCb(), getAmplification(), true, true)) : null; + } + // CraftBukkit end ++ // Paper start - add field/methods for custom range ++ private final String PAPER_RANGE_TAG = "Paper.Range"; ++ private double effectRange = -1; ++ ++ public double getEffectRange() { ++ if (this.effectRange < 0) { ++ return this.levels * 10 + 10; ++ } else { ++ return effectRange; ++ } ++ } ++ ++ public void setEffectRange(double range) { ++ this.effectRange = range; ++ } ++ ++ public void resetEffectRange() { ++ this.effectRange = -1; ++ } ++ // Paper end + + public BeaconBlockEntity() { + super(BlockEntityType.BEACON); +@@ -261,7 +281,8 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + + public List getHumansInRange() { + { +- double d0 = (double) (this.levels * 10 + 10); ++ // Paper - custom beacon ranges ++ double d0 = this.getEffectRange(); + + AABB axisalignedbb = (new AABB(this.worldPosition)).inflate(d0).expandTowards(0.0D, (double) this.level.getMaxBuildHeight(), 0.0D); + List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.player.Player.class, axisalignedbb); +@@ -361,6 +382,9 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + this.secondaryPower = MobEffect.byId(tag.getInt("Secondary")); + this.levels = tag.getInt("Levels"); // SPIGOT-5053, use where available + // CraftBukkit end ++ // Paper ++ this.effectRange = tag.contains(PAPER_RANGE_TAG, 6) ? tag.getDouble(PAPER_RANGE_TAG) : -1; ++ + if (tag.contains("CustomName", 8)) { + this.name = Component.Serializer.fromJson(tag.getString("CustomName")); + } +@@ -377,6 +401,8 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + if (this.name != null) { + tag.putString("CustomName", Component.Serializer.toJson(this.name)); + } ++ // Paper ++ tag.putDouble(PAPER_RANGE_TAG, this.effectRange); + + this.lockKey.addToTag(tag); + return tag; +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +index 940fef58f14e06213c7f305f67dcb8918976c03d..2a10a9352fdb52f5cb27eae2b6d3baa9ff95e486 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +@@ -108,4 +108,19 @@ public class CraftBeacon extends CraftBlockEntityState implem + public void setLock(String key) { + this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key); + } ++ ++ @Override ++ public double getEffectRange() { ++ return this.getSnapshot().getEffectRange(); ++ } ++ ++ @Override ++ public void setEffectRange(double range) { ++ this.getSnapshot().setEffectRange(range); ++ } ++ ++ @Override ++ public void resetEffectRange() { ++ this.getSnapshot().resetEffectRange(); ++ } + } diff --git a/patches/server-remapped/0595-Add-API-for-quit-reason.patch b/patches/server-remapped/0595-Add-API-for-quit-reason.patch new file mode 100644 index 0000000000..988b77b058 --- /dev/null +++ b/patches/server-remapped/0595-Add-API-for-quit-reason.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 14 Nov 2020 16:19:52 +0100 +Subject: [PATCH] Add API for quit reason + + +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 6f7cbce5a049d87d4a0ed7cc4517cb4e8694efb5..3ba9c38fc44a8edba9b504112a383249052a0035 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -137,12 +137,15 @@ public class Connection extends SimpleChannelInboundHandler> { + + this.handlingFault = true; + if (this.channel.isOpen()) { ++ ServerPlayer player = this.getPlayer(); // Paper + if (throwable instanceof TimeoutException) { + Connection.LOGGER.debug("Timeout", throwable); ++ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper + this.disconnect(new TranslatableComponent("disconnect.timeout")); + } else { + TranslatableComponent chatmessage = new TranslatableComponent("disconnect.genericReason", new Object[]{"Internal Exception: " + throwable}); + ++ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper + if (flag) { + Connection.LOGGER.debug("Failed to sent packet", throwable); + this.send(new ClientboundDisconnectPacket(chatmessage), (future) -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index bd4d4ace35e966e819aa461d3962fe06ff402be7..1b5f24920c46cd238a79f5a2857d26fa1c12b983 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -258,6 +258,7 @@ public class ServerPlayer extends Player implements ContainerListener { + double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks + + boolean needsChunkCenterUpdate; // Paper - no-tick view distance ++ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event + + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { + super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 3a114bec14fcc6c1e1045e2b99178a6adb25f387..ccfe5a1ec1e9895f7462b7c676fee80903502a88 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -447,6 +447,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + final Component ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure + // CraftBukkit end + ++ this.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper + this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> { + this.connection.disconnect(ichatbasecomponent); + }); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7e44c911f4abc5c7d0e89513bf2cfc3516f13492..cda21726f4929b03191e912550d4e4b1232b3b0b 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -586,7 +586,7 @@ public abstract class PlayerList { + entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper + } + +- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName())), entityplayer.quitReason); // Paper - quit reason + if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + diff --git a/patches/server-remapped/0596-Seed-based-feature-search.patch b/patches/server-remapped/0596-Seed-based-feature-search.patch new file mode 100644 index 0000000000..40529ba82f --- /dev/null +++ b/patches/server-remapped/0596-Seed-based-feature-search.patch @@ -0,0 +1,115 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Mon, 13 Jan 2020 15:40:32 +0100 +Subject: [PATCH] Seed based feature search + +This tries to work around the issue where the server will load +surrounding chunks up to a radius of 100 chunks in order to search for +features e.g. when running the /locate command or for treasure maps +(issue #2312). +This is done by backporting Mojang's change in 1.17 which makes it so +that the biome (generated by the seed) is checked first if the feature +can be generated before actually to load the chunk. + +Additionally to that the center location of the target chunk is simply +returned if the chunk is not loaded to avoid the sync chunk load. +As this can lead to less precise locations a toggle is provided to +enable the sync loading of the target chunk again. + +The main downside of this is that it breaks once the seed or generator +changes but this should usually not happen. A config option to disable +this completely is added though in case that should ever be necessary. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 424754a0183b071d20c86f0420cec784a8992e2b..97870622e41cca36d9c7493bfad796f35f3831f4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -337,6 +337,14 @@ public class PaperWorldConfig { + } + } + ++ public boolean seedBasedFeatureSearch = true; ++ public boolean seedBasedFeatureSearchLoadsChunks = false; ++ private void seedBasedFeatureSearch() { ++ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch); ++ seedBasedFeatureSearchLoadsChunks = getBoolean("seed-based-feature-search-loads-chunks", seedBasedFeatureSearchLoadsChunks); ++ log("Feature search is based on seed: " + seedBasedFeatureSearch + ", loads chunks:" + seedBasedFeatureSearchLoadsChunks); ++ } ++ + public int maxCollisionsPerEntity; + private void maxEntityCollision() { + maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); +diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java +index 4a5f318adf5bc2ca1c3fab5d173a99cddd77ab85..f61a3eda40328922b95f166be4dc604500e000be 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkPos.java ++++ b/src/main/java/net/minecraft/world/level/ChunkPos.java +@@ -68,10 +68,12 @@ public class ChunkPos { + } + } + ++ public int getBlockX() { return getMinBlockX(); } // Paper - OBFHELPER + public int getMinBlockX() { + return this.x << 4; + } + ++ public int getBlockZ() { return getMinBlockZ(); } // Paper - OBFHELPER + public int getMinBlockZ() { + return this.z << 4; + } +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 2ad8a4558aa812885adebee8c05dab45f2bf5f90..066d5f7ee93351bff67c0d39ee9d940ac51515d8 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -1511,8 +1511,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return this.profiler; + } + +- @Override +- public BiomeManager getBiomeManager() { ++ public BiomeManager getBiomeManager() { return getBiomeManager(); } // Paper - OBFHELPER ++ @Override public BiomeManager getBiomeManager() { + return this.biomeManager; + } + +diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java +index d22ac114440d807a6cf5f286961bc63935fa7823..3a1909c0b198d89539f4351d70a39d16cfd84987 100644 +--- a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java ++++ b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java +@@ -23,6 +23,7 @@ public class BiomeManager { + return new BiomeManager(source, this.biomeZoomSeed, this.zoomer); + } + ++ public Biome getBiome(BlockPos blockposition) { return getBiome(blockposition); } // Paper - OBFHELPER + public Biome getBiome(BlockPos pos) { + return this.zoomer.getBiome(this.biomeZoomSeed, pos.getX(), pos.getY(), pos.getZ(), this.noiseBiomeSource); + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +index 0624b8270bc28c83c5479cd51fa4633ed5c36f44..6b24590a1ac460a7fd4bbc2c70d4a4981378e79c 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +@@ -176,7 +176,24 @@ public abstract class StructureFeature { + int j2 = i1 + k * l1; + ChunkPos chunkcoordintpair = this.getPotentialFeatureChunk(config, worldSeed, seededrandom, i2, j2); + if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper +- ChunkAccess ichunkaccess = world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); ++ // Paper start - seed based feature search ++ ChunkAccess ichunkaccess = null; ++ if (structureAccessor.getWorld().paperConfig.seedBasedFeatureSearch) { ++ Biome biomeBase = structureAccessor.getWorld().getBiomeManager().getBiome(new BlockPos(chunkcoordintpair.getBlockX() + 9, 0, chunkcoordintpair.getBlockZ() + 9)); ++ if (!biomeBase.getGenerationSettings().isValidStart(this)) { ++ continue; ++ } ++ if (!structureAccessor.getWorld().paperConfig.seedBasedFeatureSearchLoadsChunks) { ++ ichunkaccess = structureAccessor.getWorld().getChunkIfLoaded(chunkcoordintpair.x, chunkcoordintpair.z); ++ if (ichunkaccess == null) { ++ return chunkcoordintpair.asPosition().add(8, searchStartPos.getY(), 8); ++ } ++ } ++ } ++ if (ichunkaccess == null) { ++ ichunkaccess = world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); ++ } ++ // Paper end + StructureStart structurestart = structureAccessor.getStartForFeature(SectionPos.of(ichunkaccess.getPos(), 0), this, ichunkaccess); + + if (structurestart != null && structurestart.e()) { diff --git a/patches/server-remapped/0597-Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server-remapped/0597-Add-Wandering-Trader-spawn-rate-config-options.patch new file mode 100644 index 0000000000..2dbaff374a --- /dev/null +++ b/patches/server-remapped/0597-Add-Wandering-Trader-spawn-rate-config-options.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Thu, 20 Aug 2020 11:20:12 -0700 +Subject: [PATCH] Add Wandering Trader spawn rate config options + +Adds config options for modifying the spawn rates of Wandering Traders. +These values are all easy to understand and configure after a quick read of this +page on the Minecraft wiki: https://minecraft.gamepedia.com/Wandering_Trader#Spawning +Usages of the vanilla WanderingTraderSpawnDelay and WanderingTraderSpawnChance values +in IWorldServerData are removed as they were only used in certain places, with hardcoded +values used in other places. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 97870622e41cca36d9c7493bfad796f35f3831f4..5a451cc855de57f79a57670ba38e3af2343cb510 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -699,4 +699,17 @@ public class PaperWorldConfig { + log("The Ender Dragon will be removed if she already exists without a portal."); + } + } ++ ++ public int wanderingTraderSpawnMinuteTicks = 1200; ++ public int wanderingTraderSpawnDayTicks = 24000; ++ public int wanderingTraderSpawnChanceFailureIncrement = 25; ++ public int wanderingTraderSpawnChanceMin = 25; ++ public int wanderingTraderSpawnChanceMax = 75; ++ private void wanderingTraderSettings() { ++ wanderingTraderSpawnMinuteTicks = getInt("wandering-trader.spawn-minute-length", wanderingTraderSpawnMinuteTicks); ++ wanderingTraderSpawnDayTicks = getInt("wandering-trader.spawn-day-length", wanderingTraderSpawnDayTicks); ++ wanderingTraderSpawnChanceFailureIncrement = getInt("wandering-trader.spawn-chance-failure-increment", wanderingTraderSpawnChanceFailureIncrement); ++ wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); ++ wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +index c297051bc48ff20a6764496cbf11eef601761d13..9074d57e1576db2da3e4c76add4f7e07e5567879 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +@@ -30,49 +30,59 @@ public class WanderingTraderSpawner implements CustomSpawner { + + private final Random random = new Random(); + private final ServerLevelData serverLevelData; +- private int tickDelay; +- private int spawnDelay; +- private int spawnChance; ++ private int tickDelay; public final int getMinuteTimer() { return this.tickDelay; } public final void setMinuteTimer(int x) { this.tickDelay = x; } // Paper - OBFHELPER ++ private int spawnDelay; public final int getDayTimer() { return this.spawnDelay; } public final void setDayTimer(int x) { this.spawnDelay = x; } // Paper - OBFHELPER ++ private int spawnChance; public final int getSpawnChance() { return this.spawnChance; } public final void setSpawnChance(int x) { this.spawnChance = x; } // Paper - OBFHELPER + + public WanderingTraderSpawner(ServerLevelData properties) { + this.serverLevelData = properties; +- this.tickDelay = 1200; +- this.spawnDelay = properties.getWanderingTraderSpawnDelay(); +- this.spawnChance = properties.getWanderingTraderSpawnChance(); +- if (this.spawnDelay == 0 && this.spawnChance == 0) { +- this.spawnDelay = 24000; +- properties.setWanderingTraderSpawnDelay(this.spawnDelay); +- this.spawnChance = 25; +- properties.setWanderingTraderSpawnChance(this.spawnChance); +- } ++ // Paper start ++ this.setMinuteTimer(Integer.MIN_VALUE); ++ //this.d = iworlddataserver.v(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value ++ //this.e = iworlddataserver.w(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value ++ //if (this.d == 0 && this.e == 0) { ++ // this.d = 24000; ++ // iworlddataserver.g(this.d); ++ // this.e = 25; ++ // iworlddataserver.h(this.e); ++ //} ++ // Paper end + + } + + @Override + public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { ++ // Paper start ++ if (this.getMinuteTimer() == Integer.MIN_VALUE) { ++ this.setMinuteTimer(world.paperConfig.wanderingTraderSpawnMinuteTicks); ++ this.setDayTimer(world.paperConfig.wanderingTraderSpawnDayTicks); ++ this.setSpawnChance(world.paperConfig.wanderingTraderSpawnChanceMin); ++ } + if (!world.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) { + return 0; +- } else if (--this.tickDelay > 0) { ++ } else if (this.getMinuteTimer() - 1 > 0) { ++ this.setMinuteTimer(this.getMinuteTimer() - 1); + return 0; + } else { +- this.tickDelay = 1200; +- this.spawnDelay -= 1200; +- this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay); +- if (this.spawnDelay > 0) { ++ this.setMinuteTimer(world.paperConfig.wanderingTraderSpawnMinuteTicks); ++ this.setDayTimer(getDayTimer() - world.paperConfig.wanderingTraderSpawnMinuteTicks); ++ //this.b.g(this.d); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways ++ if (this.getDayTimer() > 0) { + return 0; + } else { +- this.spawnDelay = 24000; ++ this.setDayTimer(world.paperConfig.wanderingTraderSpawnDayTicks); + if (!world.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { + return 0; + } else { +- int i = this.spawnChance; ++ int i = this.getSpawnChance(); + +- this.spawnChance = Mth.clamp(this.spawnChance + 25, 25, 75); +- this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); ++ this.setSpawnChance(Mth.clamp(i + world.paperConfig.wanderingTraderSpawnChanceFailureIncrement, world.paperConfig.wanderingTraderSpawnChanceMin, world.paperConfig.wanderingTraderSpawnChanceMax)); ++ //this.b.h(this.e); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways + if (this.random.nextInt(100) > i) { + return 0; + } else if (this.spawn(world)) { +- this.spawnChance = 25; ++ this.setSpawnChance(world.paperConfig.wanderingTraderSpawnChanceMin); ++ // Paper end + return 1; + } else { + return 0; diff --git a/patches/server-remapped/0598-Significantly-improve-performance-of-the-end-generat.patch b/patches/server-remapped/0598-Significantly-improve-performance-of-the-end-generat.patch new file mode 100644 index 0000000000..22a13c79b6 --- /dev/null +++ b/patches/server-remapped/0598-Significantly-improve-performance-of-the-end-generat.patch @@ -0,0 +1,77 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com> +Date: Tue, 3 Nov 2020 23:48:05 -0600 +Subject: [PATCH] Significantly improve performance of the end generation + +This patch implements a noise cache for the end which significantly reduces the computation time of generation. This results in about a 3x improvement. + +Original code by SuperCoder7979 and Gegy in Lithium, licensed under LGPL-3.0 (Source: https://github.com/jellysquid3/lithium-fabric) + +Co-authored-by: Gegy +Co-authored-by: Dylan Xaldin +Co-authored-by: pop4959 + +diff --git a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +index 063369d3a64b4afc9cc6e1d20360900595e1a05f..f01d1b01ebc31f0967a73871f278aac9e414fb67 100644 +--- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java ++++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +@@ -3,10 +3,12 @@ package net.minecraft.world.level.biome; + import com.google.common.collect.ImmutableList; + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; ++import it.unimi.dsi.fastutil.HashCommon; // Paper + import java.util.List; + import net.minecraft.core.Registry; + import net.minecraft.resources.RegistryLookupCodec; + import net.minecraft.util.Mth; ++import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.levelgen.WorldgenRandom; + import net.minecraft.world.level.levelgen.synth.SimplexNoise; + +@@ -27,6 +29,16 @@ public class TheEndBiomeSource extends BiomeSource { + private final Biome midlands; + private final Biome islands; + private final Biome barrens; ++ // Paper start ++ private static final class NoiseCache { ++ public long[] keys = new long[8192]; ++ public float[] values = new float[8192]; ++ public NoiseCache() { ++ java.util.Arrays.fill(keys, Long.MIN_VALUE); ++ } ++ } ++ private static final ThreadLocal> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new); ++ // Paper end + + public TheEndBiomeSource(Registry biomeRegistry, long seed) { + this(biomeRegistry, seed, (Biome) biomeRegistry.lifecycle(Biomes.THE_END), (Biome) biomeRegistry.lifecycle(Biomes.END_HIGHLANDS), (Biome) biomeRegistry.lifecycle(Biomes.END_MIDLANDS), (Biome) biomeRegistry.lifecycle(Biomes.SMALL_END_ISLANDS), (Biome) biomeRegistry.lifecycle(Biomes.END_BARRENS)); +@@ -81,13 +93,27 @@ public class TheEndBiomeSource extends BiomeSource { + + f = Mth.clamp(f, -100.0F, 80.0F); + ++ NoiseCache cache = noiseCache.get().computeIfAbsent(noisegenerator3handler, m -> new NoiseCache()); // Paper + for (int k1 = -12; k1 <= 12; ++k1) { + for (int l1 = -12; l1 <= 12; ++l1) { + long i2 = (long) (k + k1); + long j2 = (long) (l + l1); + +- if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.getValue((double) i2, (double) j2) < -0.8999999761581421D) { +- float f1 = (Mth.abs((float) i2) * 3439.0F + Mth.abs((float) j2) * 147.0F) % 13.0F + 9.0F; ++ // Paper start - Significantly improve end generation performance by using a noise cache ++ long key = ChunkPos.asLong((int) i2, (int) j2); ++ int index = (int) HashCommon.mix(key) & 8191; ++ float f1 = Float.MIN_VALUE; ++ if (cache.keys[index] == key) { ++ f1 = cache.values[index]; ++ } else { ++ if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.getValue((double) i2, (double) j2) < -0.8999999761581421D) { ++ f1 = (Mth.abs((float) i2) * 3439.0F + Mth.abs((float) j2) * 147.0F) % 13.0F + 9.0F; ++ } ++ cache.keys[index] = key; ++ cache.values[index] = f1; ++ } ++ if (f1 != Float.MIN_VALUE) { ++ // Paper end + float f2 = (float) (i1 - k1 * 2); + float f3 = (float) (j1 - l1 * 2); + float f4 = 100.0F - Mth.sqrt(f2 * f2 + f3 * f3) * f1; diff --git a/patches/server-remapped/0599-Expose-world-spawn-angle.patch b/patches/server-remapped/0599-Expose-world-spawn-angle.patch new file mode 100644 index 0000000000..0086ded8da --- /dev/null +++ b/patches/server-remapped/0599-Expose-world-spawn-angle.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Tue, 17 Nov 2020 19:13:09 +0200 +Subject: [PATCH] Expose world spawn angle + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index cda21726f4929b03191e912550d4e4b1232b3b0b..7e07fd0c8dec9f9cdeda65dfa0ccf42b4dde010e 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -890,7 +890,7 @@ public abstract class PlayerList { + if (location == null) { + worldserver1 = this.server.getLevel(Level.OVERWORLD); + blockposition = entityplayer1.getSpawnPoint(worldserver1); +- location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F)); ++ location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F), worldserver1.levelData.getSpawnAngle(), 0.0F); // Paper - use world spawn angle + } + + Player respawnPlayer = cserver.getPlayer(entityplayer1); +diff --git a/src/main/java/net/minecraft/world/level/storage/LevelData.java b/src/main/java/net/minecraft/world/level/storage/LevelData.java +index 12a2371b15588ae84824d7a2d36a6d4c37e77013..078cee770a77b77d9b4a777754599d7b0b31f54b 100644 +--- a/src/main/java/net/minecraft/world/level/storage/LevelData.java ++++ b/src/main/java/net/minecraft/world/level/storage/LevelData.java +@@ -12,6 +12,7 @@ public interface LevelData { + + int getZSpawn(); + ++ default float getSpawnAngle() { return getSpawnAngle(); } // Paper - OBFHELPER + float getSpawnAngle(); + + long getGameTime(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 28bf53bc9fca21f57cd4851adf508d833ecdd33b..aaf97c13babce3b0ffc639ef950d59d1eba1398a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -362,7 +362,7 @@ public class CraftWorld implements World { + @Override + public Location getSpawnLocation() { + BlockPos spawn = world.getSpawn(); +- return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); ++ return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ(), world.levelData.getSpawnAngle(), 0.0F); // Paper - expose world spawn angle + } + + @Override diff --git a/patches/server-remapped/0600-Add-Destroy-Speed-API.patch b/patches/server-remapped/0600-Add-Destroy-Speed-API.patch new file mode 100644 index 0000000000..53910619a5 --- /dev/null +++ b/patches/server-remapped/0600-Add-Destroy-Speed-API.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ineusia +Date: Mon, 26 Oct 2020 11:48:06 -0500 +Subject: [PATCH] Add Destroy Speed API + +Co-authored-by: Jake Potrebic + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 37eceaef1212e2ee13aa763a5ede24ec170e5391..9defb202761296a825d035e27ddc51e17a311647 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -766,5 +766,23 @@ public class CraftBlock implements Block { + public String getTranslationKey() { + return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); + } ++ ++ @Override ++ public float getDestroySpeed(ItemStack itemStack, boolean considerEnchants) { ++ net.minecraft.world.item.ItemStack nmsItemStack; ++ if (itemStack instanceof CraftItemStack) { ++ nmsItemStack = ((CraftItemStack) itemStack).getHandle(); ++ } else { ++ nmsItemStack = CraftItemStack.asNMSCopy(itemStack); ++ } ++ float speed = nmsItemStack.getItem().getDestroySpeed(nmsItemStack, this.getNMSBlock().defaultBlockState()); ++ if (speed > 1.0F && considerEnchants) { ++ int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.BLOCK_EFFICIENCY, nmsItemStack); ++ if (enchantLevel > 0) { ++ speed += enchantLevel * enchantLevel + 1; ++ } ++ } ++ return speed; ++ } + // Paper end + } diff --git a/patches/server-remapped/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/patches/server-remapped/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch new file mode 100644 index 0000000000..95a480a03b --- /dev/null +++ b/patches/server-remapped/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Esophose +Date: Sat, 3 Oct 2020 18:57:47 -0600 +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 94240b70e245bdc3dda60420f5787f8d5dcc1958..40380fff222cc1f3340cf6a6c4afbe60aaa5d3a6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2008,7 +2008,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + if (data != null && !particle.getDataType().isInstance(data)) { + throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); + } +- ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.toNMS(particle, data), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); ++ ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.toNMS(particle, data), true, x, y, z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); // Paper - Fix x/y/z coordinate precision loss + getHandle().connection.send(packetplayoutworldparticles); + + } diff --git a/patches/server-remapped/0602-Add-LivingEntity-clearActiveItem.patch b/patches/server-remapped/0602-Add-LivingEntity-clearActiveItem.patch new file mode 100644 index 0000000000..308d4591ab --- /dev/null +++ b/patches/server-remapped/0602-Add-LivingEntity-clearActiveItem.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Anrza +Date: Wed, 15 Jul 2020 12:08:49 +0200 +Subject: [PATCH] Add LivingEntity#clearActiveItem + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index eb136af0f99f5d7520ceabb98cefd5a01122872c..170bb1124ee396a85dd64baed8110e39823ad849 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -773,6 +773,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return getHandle().useItem.asBukkitMirror(); + } + ++ // Paper start ++ @Override ++ public void clearActiveItem() { ++ getHandle().stopUsingItem(); ++ } ++ // Paper end ++ + @Override + public int getItemUseRemainingTime() { + return getHandle().getItemUseRemainingTime(); diff --git a/patches/server-remapped/0603-Add-PlayerItemCooldownEvent.patch b/patches/server-remapped/0603-Add-PlayerItemCooldownEvent.patch new file mode 100644 index 0000000000..4d8772cbb5 --- /dev/null +++ b/patches/server-remapped/0603-Add-PlayerItemCooldownEvent.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Tue, 25 Aug 2020 13:48:33 +0200 +Subject: [PATCH] Add PlayerItemCooldownEvent + + +diff --git a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java +index 93161583c215e1832570b39e72f7e7cfb94a700c..1983cdcefed60795e8c88737ae3459d5821cdcfa 100644 +--- a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java ++++ b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java +@@ -1,16 +1,27 @@ + package net.minecraft.world.item; + ++import io.papermc.paper.event.player.PlayerItemCooldownEvent; // Paper + import net.minecraft.network.protocol.game.ClientboundCooldownPacket; + import net.minecraft.server.level.ServerPlayer; + + public class ServerItemCooldowns extends ItemCooldowns { + +- private final ServerPlayer player; ++ private final ServerPlayer player; public ServerPlayer getEntityPlayer() { return player; } // Paper - OBFHELPER + + public ServerItemCooldowns(ServerPlayer player) { + this.player = player; + } + ++ // Paper start ++ @Override ++ public void addCooldown(Item item, int duration) { ++ PlayerItemCooldownEvent event = new PlayerItemCooldownEvent(getEntityPlayer().getBukkitEntity(), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(item), duration); ++ if (event.callEvent()) { ++ super.addCooldown(item, event.getCooldown()); ++ } ++ } ++ // Paper end ++ + @Override + protected void onCooldownStarted(Item item, int duration) { + super.onCooldownStarted(item, duration); diff --git a/patches/server-remapped/0604-More-lightning-API.patch b/patches/server-remapped/0604-More-lightning-API.patch new file mode 100644 index 0000000000..6c4c8bac10 --- /dev/null +++ b/patches/server-remapped/0604-More-lightning-API.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Sun, 26 Jul 2020 14:44:09 +0200 +Subject: [PATCH] More lightning API + + +diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java +index 4b0dbeded2b8a475d32f518957909d3495a4b6fc..3fdef4511e21e453b89e42a8f41e587fe300ba6b 100644 +--- a/src/main/java/net/minecraft/world/entity/LightningBolt.java ++++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java +@@ -28,7 +28,7 @@ public class LightningBolt extends Entity { + + private int life; + public long seed; +- private int flashes; ++ private int flashes; public int getFlashCount() { return flashes; } public void setFlashCount(int flashes) { this.flashes = flashes; } // Paper - OBFHELPER + public boolean visualOnly; + @Nullable + private ServerPlayer cause; +@@ -46,6 +46,16 @@ public class LightningBolt extends Entity { + this.visualOnly = cosmetic; + } + ++ // Paper start ++ public int getLifeTicks() { ++ return life; ++ } ++ ++ public void setLifeTicks(int lifeTicks) { ++ this.life = lifeTicks; ++ } ++ // Paper end ++ + @Override + public SoundSource getSoundSource() { + return SoundSource.WEATHER; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java +index 26506c22592b58b208487fb244985361d70988a8..c1593bb345b38deb4d8b28a73d8dc6246c17b873 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java +@@ -45,4 +45,27 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike + return spigot; + } + // Spigot end ++ ++ // Paper start ++ @Override ++ public int getFlashCount() { ++ return getHandle().getFlashCount(); ++ } ++ ++ @Override ++ public void setFlashCount(int flashes) { ++ com.google.common.base.Preconditions.checkArgument(flashes >= 0, "Flashes has to be a positive number!"); ++ getHandle().setFlashCount(flashes); ++ } ++ ++ @Override ++ public int getLifeTicks() { ++ return getHandle().getLifeTicks(); ++ } ++ ++ @Override ++ public void setLifeTicks(int lifeTicks) { ++ getHandle().setLifeTicks(lifeTicks); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0605-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server-remapped/0605-Climbing-should-not-bypass-cramming-gamerule.patch new file mode 100644 index 0000000000..c25768004e --- /dev/null +++ b/patches/server-remapped/0605-Climbing-should-not-bypass-cramming-gamerule.patch @@ -0,0 +1,179 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 23 Aug 2020 20:59:00 +0200 +Subject: [PATCH] Climbing should not bypass cramming gamerule + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5a451cc855de57f79a57670ba38e3af2343cb510..7d3207a9af8360ddad228281d6aa65e1a0d24157 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -712,4 +712,9 @@ public class PaperWorldConfig { + wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); + wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); + } ++ ++ public boolean fixClimbingBypassingCrammingRule = false; ++ private void fixClimbingBypassingCrammingRule() { ++ fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 90e9797cc1f3a4aa0a2bee28dca364e6f6dd0c0b..ec98f5f59ca2b4cb58eb00ed8cdfa364f8bacd88 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1573,6 +1573,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean isPushable() { ++ // Paper start ++ return isCollidable(false); ++ } ++ ++ public boolean isCollidable(boolean ignoreClimbing) { ++ // Paper end + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index 8ce62148ebaeac9988e7c9d4b2f7ee57f58d883e..8d1e24c2fa844971908ae7ac918a8950026b40a6 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -51,11 +51,17 @@ public final class EntitySelector { + } + + public static Predicate pushableBy(Entity entity) { ++ // Paper start - ignoreClimbing param ++ return pushable(entity, false); ++ } ++ ++ public static Predicate pushable(Entity entity, boolean ignoreClimbing) { ++ // Paper end + Team scoreboardteambase = entity.getTeam(); + Team.CollisionRule scoreboardteambase_enumteampush = scoreboardteambase == null ? Team.CollisionRule.ALWAYS : scoreboardteambase.getCollisionRule(); + + return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> { +- if (!entity1.canCollideWithCb(entity) || !entity.canCollideWithCb(entity1)) { // CraftBukkit - collidable API ++ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWithCb(entity) || !entity.canCollideWithCb(entity1)) { // CraftBukkit - collidable API // Paper - isCollidable + return false; + } 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 9724d4222311345a44aa101ec47523a1909fbe8f..57b933afdbb2136ed48170da6945eb2b92edb4db 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -134,7 +134,6 @@ import org.bukkit.event.entity.EntityTeleportEvent; + import org.bukkit.event.player.PlayerItemConsumeEvent; + // CraftBukkit end + +-import co.aikar.timings.MinecraftTimings; // Paper + + public abstract class LivingEntity extends Entity { + +@@ -2956,7 +2955,7 @@ public abstract class LivingEntity extends Entity { + return; + } + // Paper - end don't run getEntities if we're not going to use its result +- List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); ++ List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushable(this, level.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule + + if (!list.isEmpty()) { + // Paper - move up +@@ -3094,9 +3093,16 @@ public abstract class LivingEntity extends Entity { + return !this.removed && this.collides; // CraftBukkit + } + ++ // Paper start + @Override + public boolean isPushable() { +- return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit ++ return this.isCollidable(level.paperConfig.fixClimbingBypassingCrammingRule); ++ } ++ ++ @Override ++ public boolean isCollidable(boolean ignoreClimbing) { ++ return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.onClimbable()) && this.collides; // CraftBukkit ++ // Paper end + } + + // CraftBukkit start - collidable API +diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java +index e56c575d744e1efe9a7512f337b781dc3715f6be..8e02e3a4464ab4096637fc69c03d083988bb426e 100644 +--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java ++++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java +@@ -75,7 +75,7 @@ public class Bat extends AmbientCreature { + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java +index 918628c0ed8fb32d44c034fddf045f08659c10f8..d6a9d0e94d80f1924cedef913829d15762456537 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java +@@ -368,8 +368,8 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { + } + + @Override +- public boolean isPushable() { +- return super.isPushable(); // CraftBukkit - collidable API ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper ++ return super.isCollidable(ignoreClimbing); // CraftBukkit - collidable API // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +index d9bfc754d7544a54ff214b41b4f6c0a6bc66df28..b298bcfb665b1036cd21445cec1518069eb08f06 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +@@ -226,7 +226,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return !this.isVehicle(); + } + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 5714aa450ac09788bcf1c2790d4f1581c9a7c28b..a89573670f7dccfd8f0c81fcd95673b6faf3fc10 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -358,7 +358,7 @@ public class ArmorStand extends LivingEntity { + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 1257a740a4ab79870fe89057782e8ffc6c658c14..9cbde70787d8044f0edeb3d459231dd7fbb79584 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -144,7 +144,7 @@ public abstract class AbstractMinecart extends Entity { + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return true; + } + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +index bddc51c656f04f25744ec29cabab31d465cf8bce..4f82c6797fe9bbb1a29420ea15277be50e44808c 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +@@ -149,7 +149,7 @@ public class Boat extends Entity { + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return true; + } + diff --git a/patches/server-remapped/0606-Added-missing-default-perms-for-commands.patch b/patches/server-remapped/0606-Added-missing-default-perms-for-commands.patch new file mode 100644 index 0000000000..25843d00d1 --- /dev/null +++ b/patches/server-remapped/0606-Added-missing-default-perms-for-commands.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 16 Nov 2020 12:01:52 -0800 +Subject: [PATCH] Added missing default perms for commands + + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java +index d5f4ece060b61de9ca5292d1f2411c709de5ece2..f0a57d225b81a505ff12425155ba838d8fad990c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java +@@ -31,6 +31,59 @@ public final class CommandPermissions { + DefaultPermissions.registerPermission(PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands); ++ // Paper start ++ DefaultPermissions.registerPermission(PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "ban", "Allows the user to add players to banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "ban-ip", "Allows the user to add ip address to banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "banlist", "Allows the user to display banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "pardon", "Allows the user to remove entries from the banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "replaceitem", "Allows the user to replace items in inventories", PermissionDefault.OP, commands); // Remove in 1.17 (replaced by /item) ++ DefaultPermissions.registerPermission(PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands); ++ DefaultPermissions.registerPermission(PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands); ++ // Paper end + + DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands); + diff --git a/patches/server-remapped/0607-Add-PlayerShearBlockEvent.patch b/patches/server-remapped/0607-Add-PlayerShearBlockEvent.patch new file mode 100644 index 0000000000..c9ae36d161 --- /dev/null +++ b/patches/server-remapped/0607-Add-PlayerShearBlockEvent.patch @@ -0,0 +1,116 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Thu, 27 Aug 2020 15:02:48 -0400 +Subject: [PATCH] Add PlayerShearBlockEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java +index 1a01937f5250f3a529932dc2fdd9e1ebd9ae896a..125e646b39ef4a59be3989df16b5625c5504aac1 100644 +--- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.level.block; + ++import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts ++ + import java.util.Iterator; + import java.util.List; + import java.util.Random; +@@ -10,6 +12,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.Tag; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; +@@ -116,8 +119,19 @@ public class BeehiveBlock extends BaseEntityBlock { + + if (i >= 5) { + if (itemstack.getItem() == Items.SHEARS) { ++ // Paper start - Add PlayerShearBlockEvent ++ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); ++ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3))); ++ if (!event.callEvent()) { ++ return InteractionResult.PASS; ++ } ++ // Paper end + world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.NEUTRAL, 1.0F, 1.0F); +- dropHoneycomb(world, pos); ++ // Paper start - Add PlayerShearBlockEvent ++ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { ++ dropItem(world, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); ++ } ++ // Paper end + itemstack.hurtAndBreak(1, player, (entityhuman1) -> { + entityhuman1.broadcastBreakEvent(hand); + }); +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index baa587e73a71d6324bb7817fa4702a7c3a2db726..5f1853c3f22661809437bdb49f002482da7195f2 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -262,13 +262,13 @@ public class Block extends BlockBehaviour implements ItemLike { + + } + +- public static void popResource(Level world, BlockPos pos, ItemStack stack) { +- if (!world.isClientSide && !stack.isEmpty() && world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { ++ public static void popResource(Level world, BlockPos pos, ItemStack stack) { dropItem(world, pos, stack); } public static void dropItem(Level world, BlockPos blockposition, ItemStack itemstack) { // Paper - OBFHELPER ++ if (!world.isClientSide && !itemstack.isEmpty() && world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { + float f = 0.5F; + double d0 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; + double d1 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; + double d2 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; +- ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + d0, (double) pos.getY() + d1, (double) pos.getZ() + d2, stack); ++ ItemEntity entityitem = new ItemEntity(world, (double) blockposition.getX() + d0, (double) blockposition.getY() + d1, (double) blockposition.getZ() + d2, itemstack); + + entityitem.setDefaultPickUpDelay(); + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java +index fe528f7dee693982285ce035abd9929cb4e0cbdf..7cac13ad06ee7acfc3bdcbf79318dbfbd2a31e02 100644 +--- a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; + + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.InteractionHand; +@@ -14,6 +15,7 @@ import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.BlockHitResult; ++import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts + + public class PumpkinBlock extends StemGrownBlock { + +@@ -27,15 +29,26 @@ public class PumpkinBlock extends StemGrownBlock { + + if (itemstack.getItem() == Items.SHEARS) { + if (!world.isClientSide) { ++ // Paper start - Add PlayerShearBlockEvent ++ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); ++ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4))); ++ if (!event.callEvent()) { ++ return InteractionResult.PASS; ++ } ++ // Paper end + Direction enumdirection = hit.getDirection(); + Direction enumdirection1 = enumdirection.getAxis() == Direction.Axis.Y ? player.getDirection().getOpposite() : enumdirection; + + world.playSound((Player) null, pos, SoundEvents.PUMPKIN_CARVE, SoundSource.BLOCKS, 1.0F, 1.0F); + world.setBlock(pos, (BlockState) Blocks.CARVED_PUMPKIN.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, enumdirection1), 11); +- ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) enumdirection1.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) enumdirection1.getStepZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4)); ++ // Paper start - Add PlayerShearBlockEvent ++ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { ++ ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) enumdirection1.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) enumdirection1.getStepZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); ++ // Paper end + + entityitem.setDeltaMovement(0.05D * (double) enumdirection1.getStepX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double) enumdirection1.getStepZ() + world.random.nextDouble() * 0.02D); + world.addFreshEntity(entityitem); ++ } // Paper - Add PlayerShearBlockEvent + itemstack.hurtAndBreak(1, player, (entityhuman1) -> { + entityhuman1.broadcastBreakEvent(hand); + }); diff --git a/patches/server-remapped/0608-Add-warning-for-servers-not-running-on-Java-16.patch b/patches/server-remapped/0608-Add-warning-for-servers-not-running-on-Java-16.patch new file mode 100644 index 0000000000..ce4786d7fc --- /dev/null +++ b/patches/server-remapped/0608-Add-warning-for-servers-not-running-on-Java-16.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Wed, 2 Dec 2020 21:58:45 -0800 +Subject: [PATCH] Add warning for servers not running on Java 16 + + +diff --git a/src/main/java/io/papermc/paper/util/PaperJvmChecker.java b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fdf3ff8894e5e202229d1be52fe3c92ea039ef15 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java +@@ -0,0 +1,48 @@ ++package io.papermc.paper.util; ++ ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++ ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class PaperJvmChecker { ++ ++ private static int getJvmVersion() { ++ String javaVersion = System.getProperty("java.version"); ++ final Matcher matcher = Pattern.compile("(?:1\\.)?(\\d+)").matcher(javaVersion); ++ if (!matcher.find()) { ++ LogManager.getLogger().warn("Failed to determine Java version; Could not parse: {}", javaVersion); ++ return -1; ++ } ++ ++ final String version = matcher.group(1); ++ try { ++ return Integer.parseInt(version); ++ } catch (final NumberFormatException e) { ++ LogManager.getLogger().warn("Failed to determine Java version; Could not parse {} from {}", version, javaVersion, e); ++ return -1; ++ } ++ } ++ ++ public static void checkJvm() { ++ if (getJvmVersion() < 16) { ++ final Logger logger = LogManager.getLogger(); ++ logger.warn("************************************************************"); ++ logger.warn("* WARNING - YOU ARE RUNNING AN OUTDATED VERSION OF JAVA."); ++ logger.warn("* PAPER WILL STOP BEING COMPATIBLE WITH THIS VERSION OF"); ++ logger.warn("* JAVA WHEN MINECRAFT 1.17 IS RELEASED."); ++ logger.warn("*"); ++ logger.warn("* Please update the version of Java you use to run Paper"); ++ logger.warn("* to at least Java 16. When Paper for Minecraft 1.17 is"); ++ logger.warn("* released support for versions of Java before 16 will"); ++ logger.warn("* be dropped."); ++ logger.warn("*"); ++ logger.warn("* Current Java version: {}", System.getProperty("java.version")); ++ logger.warn("*"); ++ logger.warn("* Check this forum post for more information: "); ++ logger.warn("* https://papermc.io/java16"); ++ logger.warn("************************************************************"); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 954dce690852da87a37e7797c6f9f549242e511a..c83f2636ae93d92381e019d5b13ac82c5a1d30bf 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -180,6 +180,7 @@ import org.bukkit.event.server.ServerLoadEvent; + + import co.aikar.timings.MinecraftTimings; // Paper + import org.spigotmc.SlackActivityAccountant; // Spigot ++import io.papermc.paper.util.PaperJvmChecker; // Paper + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { + +@@ -1075,6 +1076,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Wed, 2 Dec 2020 20:17:54 -0800 +Subject: [PATCH] Set spigots verbose world setting to false by def + + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 6b015c1f26facb4e82d75b252164dec05731ca6c..094a934c168d232b0550c3efe722f2ebfbdf8e24 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -20,7 +20,7 @@ public class SpigotWorldConfig + + public void init() + { +- this.verbose = getBoolean( "verbose", true ); ++ this.verbose = getBoolean( "verbose", false ); // Paper + + log( "-------- World Settings For [" + worldName + "] --------" ); + SpigotConfig.readConfig( SpigotWorldConfig.class, this ); diff --git a/patches/server-remapped/0610-Fix-curing-zombie-villager-discount-exploit.patch b/patches/server-remapped/0610-Fix-curing-zombie-villager-discount-exploit.patch new file mode 100644 index 0000000000..852cffc989 --- /dev/null +++ b/patches/server-remapped/0610-Fix-curing-zombie-villager-discount-exploit.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 8 Dec 2020 20:14:20 -0600 +Subject: [PATCH] Fix curing zombie villager discount exploit + +This fixes the exploit used to gain absurd trading discounts with infecting +and curing a villager on repeat by simply resetting the relevant part of +the reputation when it is cured. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 7d3207a9af8360ddad228281d6aa65e1a0d24157..a3b3e3e04b7a5e3a351992e06870cc91fbd8adc8 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -717,4 +717,9 @@ public class PaperWorldConfig { + private void fixClimbingBypassingCrammingRule() { + fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); + } ++ ++ public boolean fixCuringZombieVillagerDiscountExploit = true; ++ private void fixCuringExploit() { ++ fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +index 57832c392910d22aa81ac2b4816d043dd7ac867a..9a68201bab4fcbad69c85e2469a103634b65d7b3 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +@@ -223,6 +223,7 @@ public class GossipContainer { + + } + ++ public final void removeReputationForType(GossipType reputationType) { this.remove(reputationType); } // Paper - OBFHELPER + public void remove(GossipType gossipType) { + this.entries.removeInt(gossipType); + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 415fa3591add1f1ab22dd5866e110dbfccd0ec93..7817071b1964b962c8f4017d5bb39d74ca0ca3e4 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -1013,6 +1013,15 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + @Override + public void onReputationEventFrom(ReputationEventType interaction, Entity entity) { + if (interaction == ReputationEventType.ZOMBIE_VILLAGER_CURED) { ++ // Paper start - fix MC-181190 ++ if (level.paperConfig.fixCuringZombieVillagerDiscountExploit) { ++ final GossipContainer.EntityGossips playerReputation = this.getReputation().getReputations().get(entity.getUUID()); ++ if (playerReputation != null) { ++ playerReputation.removeReputationForType(GossipType.MAJOR_POSITIVE); ++ playerReputation.removeReputationForType(GossipType.MINOR_POSITIVE); ++ } ++ } ++ // Paper end + this.gossips.add(entity.getUUID(), GossipType.MAJOR_POSITIVE, 20); + this.gossips.add(entity.getUUID(), GossipType.MINOR_POSITIVE, 25); + } else if (interaction == ReputationEventType.TRADE) { diff --git a/patches/server-remapped/0611-Limit-recipe-packets.patch b/patches/server-remapped/0611-Limit-recipe-packets.patch new file mode 100644 index 0000000000..dc1bd95672 --- /dev/null +++ b/patches/server-remapped/0611-Limit-recipe-packets.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 12 Dec 2020 23:45:28 +0000 +Subject: [PATCH] Limit recipe packets + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 7d50aded88f5b7dfebaea1aebc86231f7b5c4e25..652d87fc5d566dba8018c81676329f0e0bca471b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -334,6 +334,13 @@ public class PaperConfig { + tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); + } + ++ public static int autoRecipeIncrement = 1; ++ public static int autoRecipeLimit = 20; ++ private static void autoRecipieLimiters() { ++ autoRecipeIncrement = getInt("settings.spam-limiter.recipe-spam-increment", autoRecipeIncrement); ++ autoRecipeLimit = getInt("settings.spam-limiter.recipe-spam-limit", autoRecipeLimit); ++ } ++ + public static boolean velocitySupport; + public static boolean velocityOnlineMode; + public static byte[] velocitySecretKey; +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index ccfe5a1ec1e9895f7462b7c676fee80903502a88..e50e42cce60c725cdd981d8927e379c5760d9200 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1,5 +1,6 @@ + package net.minecraft.server.network; + ++import com.destroystokyo.paper.PaperConfig; + import com.google.common.collect.Lists; + import com.google.common.primitives.Doubles; + import com.google.common.primitives.Floats; +@@ -174,6 +175,7 @@ import io.papermc.paper.adventure.ChatProcessor; // Paper + import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.util.concurrent.ExecutionException; + import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; ++import org.bukkit.Bukkit; // Paper + import org.bukkit.Location; + import org.bukkit.craftbukkit.entity.CraftPlayer; + import org.bukkit.craftbukkit.event.CraftEventFactory; +@@ -232,6 +234,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private volatile int chatSpamTickCount; + private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(ServerGamePacketListenerImpl.class, "chatThrottle"); + private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits ++ private final java.util.concurrent.atomic.AtomicInteger recipeSpamPackets = new java.util.concurrent.atomic.AtomicInteger(); // Paper - auto recipe limit + // CraftBukkit end + private int dropSpamTickCount; + private final Int2ShortMap expectedAcks = new Int2ShortOpenHashMap(); +@@ -380,6 +383,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit start + for (int spam; (spam = this.chatSpamTickCount) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; + if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable ++ if (recipeSpamPackets.get() > 0) recipeSpamPackets.getAndDecrement(); // Paper + /* Use thread-safe field access instead + if (this.chatThrottle > 0) { + --this.chatThrottle; +@@ -2786,6 +2790,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + @Override + public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) { ++ // Paper start ++ if (!Bukkit.isPrimaryThread()) { ++ if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ return; ++ } ++ } ++ // Paper end + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + this.player.resetLastActionTime(); + if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu.isSynched(this.player) && this.player.containerMenu instanceof RecipeBookMenu) { diff --git a/patches/server-remapped/0612-Fix-CraftSound-backwards-compatibility.patch b/patches/server-remapped/0612-Fix-CraftSound-backwards-compatibility.patch new file mode 100644 index 0000000000..60e8ef1e6b --- /dev/null +++ b/patches/server-remapped/0612-Fix-CraftSound-backwards-compatibility.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Thu, 17 Dec 2020 15:25:49 -0600 +Subject: [PATCH] Fix CraftSound backwards compatibility + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java +index 266563e72b563fd9db85f17bca710bbe45e8a22d..b2667c5f0794d521766203fea3299f12e21f5c76 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java +@@ -26,4 +26,10 @@ public class CraftSound { + public static Sound getBukkit(SoundEvent soundEffect) { + return Registry.SOUNDS.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.Registry.SOUND_EVENT.getKey(soundEffect))); + } ++ ++ // Paper start ++ public static String getSound(Sound sound) { ++ return sound.getKey().getKey(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0613-MC-4-Fix-item-position-desync.patch b/patches/server-remapped/0613-MC-4-Fix-item-position-desync.patch new file mode 100644 index 0000000000..3d3624adc8 --- /dev/null +++ b/patches/server-remapped/0613-MC-4-Fix-item-position-desync.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 8 Dec 2020 20:24:52 -0600 +Subject: [PATCH] MC-4: Fix item position desync + +This fixes item position desync (MC-4) by running the item coordinates +through the encode/decode methods of the packet that causes the precision +loss, which forces the server to lose the same precision as the client +keeping them in sync. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 652d87fc5d566dba8018c81676329f0e0bca471b..c56e7fb18f9a56c8025eb70a524f028b5942da37 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -474,4 +474,9 @@ public class PaperConfig { + private static void trackPluginScoreboards() { + trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); + } ++ ++ public static boolean fixEntityPositionDesync = true; ++ private static void fixEntityPositionDesync() { ++ fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); ++ } + } +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java +index cb10c87728b5f9062c4bdd1fe5e4b2c7a558f323..6b97d60d923e772c7284e674bc3f2e9a5a0ddead 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java +@@ -19,11 +19,11 @@ public class ClientboundMoveEntityPacket implements Packet { ++ private static final float[] SIN = (float[]) Util.make((new float[65536]), (afloat) -> { // Paper - decompile error + for (int i = 0; i < afloat.length; ++i) { + afloat[i] = (float) Math.sin((double) i * 3.141592653589793D * 2.0D / 65536.0D); + } +@@ -49,6 +49,7 @@ public class Mth { + return d0 < (double) i ? i - 1 : i; + } + ++ public static long floorLong(double d0) { return lfloor(d0); } // Paper - OBFHELPER + public static long lfloor(double d0) { + long i = (long) d0; + +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 9311f9f411d09d4460f0be8235957fab9e195b7a..7476ae301fb4ee503944d39022cb25ccb19f1232 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -549,4 +549,16 @@ public class ItemEntity extends Entity { + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this); + } ++ ++ // Paper start - fix MC-4 ++ public void setPosRaw(double x, double y, double z) { ++ if (com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) { ++ // encode/decode from PacketPlayOutEntity ++ x = Mth.floorLong(x * 4096.0D) * (1 / 4096.0D); ++ y = Mth.floorLong(y * 4096.0D) * (1 / 4096.0D); ++ z = Mth.floorLong(z * 4096.0D) * (1 / 4096.0D); ++ } ++ super.setPosRaw(x, y, z); ++ } ++ // Paper end - fix MC-4 + } diff --git a/patches/server-remapped/0614-Player-Chunk-Load-Unload-Events.patch b/patches/server-remapped/0614-Player-Chunk-Load-Unload-Events.patch new file mode 100644 index 0000000000..d7abc567f0 --- /dev/null +++ b/patches/server-remapped/0614-Player-Chunk-Load-Unload-Events.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ysl3000 +Date: Mon, 5 Oct 2020 21:25:16 +0200 +Subject: [PATCH] Player Chunk Load/Unload Events + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 1b5f24920c46cd238a79f5a2857d26fa1c12b983..ff831ca0cbc0cabbf78178c609ccf70d78da7980 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -136,6 +136,8 @@ import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.level.portal.PortalInfo; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++import io.papermc.paper.event.packet.PlayerChunkLoadEvent; // Paper ++import io.papermc.paper.event.packet.PlayerChunkUnloadEvent; // Paper + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import net.minecraft.world.Container; +@@ -2095,11 +2097,21 @@ public class ServerPlayer extends Player implements ContainerListener { + public void trackChunk(ChunkPos chunkcoordintpair, Packet packet, Packet packet1) { + this.connection.send(packet1); + this.connection.send(packet); ++ // Paper start ++ if(PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0){ ++ new PlayerChunkLoadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); ++ } ++ // Paper end + } + + public void untrackChunk(ChunkPos chunkcoordintpair) { + if (this.isAlive()) { + this.connection.send(new ClientboundForgetLevelChunkPacket(chunkcoordintpair.x, chunkcoordintpair.z)); ++ // Paper start ++ if(PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0){ ++ new PlayerChunkUnloadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); ++ } ++ // Paper end + } + + } diff --git a/patches/server-remapped/0615-Optimize-Dynamic-get-Missing-Keys.patch b/patches/server-remapped/0615-Optimize-Dynamic-get-Missing-Keys.patch new file mode 100644 index 0000000000..5a4efe035c --- /dev/null +++ b/patches/server-remapped/0615-Optimize-Dynamic-get-Missing-Keys.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 21 Dec 2020 11:01:42 -0500 +Subject: [PATCH] Optimize Dynamic#get Missing Keys + +get was calling toString() on every NBT object that was ever asked for an optional +key from the object to build a string for the error text. + +When done on large NBT objects, this was using a ton of computation time building the +JSON representation of the NBT object. + +Now we will just skip the value when 99.9999% of the time the text is never even printed. + +diff --git a/src/main/java/com/mojang/serialization/Dynamic.java b/src/main/java/com/mojang/serialization/Dynamic.java +index a75d3db046dc985a03b4b870c91f41de1bd66bad..044facc9de9e8e582d7953d681c0c051578979c3 100644 +--- a/src/main/java/com/mojang/serialization/Dynamic.java ++++ b/src/main/java/com/mojang/serialization/Dynamic.java +@@ -17,6 +17,7 @@ import java.util.stream.Stream; + + @SuppressWarnings("unused") + public class Dynamic extends DynamicLike { ++ private static final boolean DEBUG_MISSING_KEYS = Boolean.getBoolean("Paper.debugDynamicMissingKeys"); // Paper + private final T value; + + public Dynamic(final DynamicOps ops) { +@@ -113,7 +114,7 @@ public class Dynamic extends DynamicLike { + return new OptionalDynamic<>(ops, ops.getMap(value).flatMap(m -> { + final T value = m.get(key); + if (value == null) { +- return DataResult.error("key missing: " + key + " in " + this.value); ++ return DataResult.error(DEBUG_MISSING_KEYS ? "key missing: " + key + " in " + this.value : "key missing: " + key); // Paper + } + return DataResult.success(new Dynamic<>(ops, value)); + })); diff --git a/patches/server-remapped/0616-Expose-LivingEntity-hurt-direction.patch b/patches/server-remapped/0616-Expose-LivingEntity-hurt-direction.patch new file mode 100644 index 0000000000..d179506896 --- /dev/null +++ b/patches/server-remapped/0616-Expose-LivingEntity-hurt-direction.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 13 Dec 2020 05:32:05 +0200 +Subject: [PATCH] Expose LivingEntity hurt direction + + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 57b933afdbb2136ed48170da6945eb2b92edb4db..02ddb84c563b3149c4f1b0e24899ce8a21ad61bb 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -160,7 +160,7 @@ public abstract class LivingEntity extends Entity { + public int removeStingerTime; + public int hurtTime; + public int hurtDuration; +- public float hurtDir; ++ public float hurtDir; public final float getHurtDirection() { return hurtDir; } public final void setHurtDirection(float hurtDirection) { this.hurtDir = hurtDirection; } // Paper - OBFHELPER + public int deathTime; + public float oAttackAnim; + public float attackAnim; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 170bb1124ee396a85dd64baed8110e39823ad849..a8d21382d5859edfd12e01a48924ce780790b4b7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -818,5 +818,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { + getHandle().take(((CraftItem) item).getHandle(), quantity); + } ++ ++ @Override ++ public float getHurtDirection() { ++ return getHandle().getHurtDirection(); ++ } ++ ++ @Override ++ public void setHurtDirection(float hurtDirection) { ++ getHandle().setHurtDirection(hurtDirection); ++ } + // Paper end + } diff --git a/patches/server-remapped/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server-remapped/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch new file mode 100644 index 0000000000..d2162d0415 --- /dev/null +++ b/patches/server-remapped/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 24 Dec 2020 12:43:39 -0800 +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 64cfa14aa4e32430a6970fd4f3654a56146ba807..34c7b1213b3f83ff1a1f2d606a9c25e57fea8ef3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -259,6 +259,10 @@ public class CraftEventFactory { + return BedEnterResult.TOO_FAR_AWAY; + case NOT_SAFE: + return BedEnterResult.NOT_SAFE; ++ // Paper start ++ case OBSTRUCTED: ++ return BedEnterResult.OBSTRUCTED; ++ // Paper end + default: + return BedEnterResult.OTHER_PROBLEM; + } diff --git a/patches/server-remapped/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server-remapped/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch new file mode 100644 index 0000000000..f57f5ee833 --- /dev/null +++ b/patches/server-remapped/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 27 Dec 2020 11:31:06 +0000 +Subject: [PATCH] Do not crash from invalid ingredient lists in + VillagerAcquireTradeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +index 407a68edf6408400f1a6c5bb1a6cbbfae08ac2cd..335000713279b7964c5172937483678c671bfed1 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -270,7 +270,11 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan + Bukkit.getPluginManager().callEvent(event); + } + if (!event.isCancelled()) { +- recipeList.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ // Paper start ++ final CraftMerchantRecipe craftMerchantRecipe = CraftMerchantRecipe.fromBukkit(event.getRecipe()); ++ if (craftMerchantRecipe.getIngredients().isEmpty()) return; ++ recipeList.add(craftMerchantRecipe.toMinecraft()); ++ // Paper end + } + // CraftBukkit end + } diff --git a/patches/server-remapped/0619-added-PlayerTradeEvent.patch b/patches/server-remapped/0619-added-PlayerTradeEvent.patch new file mode 100644 index 0000000000..3589365354 --- /dev/null +++ b/patches/server-remapped/0619-added-PlayerTradeEvent.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 2 Jul 2020 16:12:10 -0700 +Subject: [PATCH] added PlayerTradeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 40ab66f888f30a5506e3aa96a4b32485452e8978..87dd6c012bf1ca6a1e8df44dc0957c4c67d02adc 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -91,7 +91,7 @@ import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; + public abstract class Mob extends LivingEntity { + + private static final EntityDataAccessor DATA_MOB_FLAGS_ID = SynchedEntityData.defineId(Mob.class, EntityDataSerializers.BYTE); +- public int ambientSoundTime; ++ public int ambientSoundTime;public void setAmbientSoundTime(int time) { this.ambientSoundTime = time; } // Paper - OBFHELPER + protected int xpReward; + protected LookControl lookControl; + protected MoveControl moveControl; +@@ -293,6 +293,7 @@ public abstract class Mob extends LivingEntity { + this.entityData.define(Mob.DATA_MOB_FLAGS_ID, (byte) 0); + } + ++ public int getAmbientSoundInterval() { return getAmbientSoundInterval(); } // Paper - OBFHELPER + public int getAmbientSoundInterval() { + return 80; + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +index 335000713279b7964c5172937483678c671bfed1..d31b773f8aff09c9f214662aa3aa0c904119e12c 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -37,6 +37,9 @@ import org.bukkit.craftbukkit.inventory.CraftMerchant; + import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; + import org.bukkit.event.entity.VillagerAcquireTradeEvent; + // CraftBukkit end ++// Paper start ++import io.papermc.paper.event.player.PlayerTradeEvent; ++// Paper end + + public abstract class AbstractVillager extends AgableMob implements Npc, Merchant { + +@@ -133,16 +136,27 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan + + @Override + public void notifyTrade(MerchantOffer offer) { +- offer.increaseUses(); +- this.ambientSoundTime = -this.getAmbientSoundInterval(); +- this.rewardTradeXp(offer); ++ // Paper - moved down ++ // Paper start + if (this.tradingPlayer instanceof ServerPlayer) { +- CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, offer.getResult()); ++ PlayerTradeEvent event = new PlayerTradeEvent(((ServerPlayer) this.tradingPlayer).getBukkitEntity(), (org.bukkit.entity.AbstractVillager) this.getBukkitEntity(), offer.asBukkit(), true, true); ++ event.callEvent(); ++ if (!event.isCancelled()) { ++ MerchantOffer recipe = CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft(); ++ if (event.willIncreaseTradeUses()) recipe.increaseUses(); ++ this.setAmbientSoundTime(-getAmbientSoundInterval()); ++ if (event.isRewardingExp()) this.rewardTradeXp(recipe); ++ CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, recipe.getResult()); ++ } ++ } else { ++ offer.increaseUses(); ++ this.setAmbientSoundTime(-getAmbientSoundInterval()); ++ this.rewardTradeXp(offer); + } +- ++ // Paper end + } + +- protected abstract void rewardTradeXp(MerchantOffer offer); ++ protected abstract void rewardTradeXp(MerchantOffer offer); public void rewardTradeXp(MerchantOffer merchantrecipe) { this.rewardTradeXp(merchantrecipe); } // Paper - OBFHELPER + + @Override + public boolean showProgressBar() { diff --git a/patches/server-remapped/0620-Implement-TargetHitEvent.patch b/patches/server-remapped/0620-Implement-TargetHitEvent.patch new file mode 100644 index 0000000000..bc8c6c48be --- /dev/null +++ b/patches/server-remapped/0620-Implement-TargetHitEvent.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Wed, 25 Nov 2020 23:20:44 -0800 +Subject: [PATCH] Implement TargetHitEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/TargetBlock.java b/src/main/java/net/minecraft/world/level/block/TargetBlock.java +index bbaf90b30b07c97321541b8fe15d47975a34161d..a7215c9b9f0f191bbfe95cb1185c99a8d21ff785 100644 +--- a/src/main/java/net/minecraft/world/level/block/TargetBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TargetBlock.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.block; + ++import io.papermc.paper.event.block.TargetHitEvent; // Paper - Need to import because 'io' class exists in nms + import java.util.Random; + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.core.BlockPos; +@@ -34,13 +35,17 @@ public class TargetBlock extends Block { + @Override + public void onProjectileHit(Level world, BlockState state, BlockHitResult hit, Projectile projectile) { + int i = updateRedstoneOutput((LevelAccessor) world, state, hit, (Entity) projectile); +- Entity entity = projectile.getOwner(); ++ // Paper start ++ } ++ private static void awardTargetHitCriteria(Projectile iprojectile, BlockHitResult movingobjectpositionblock, int i) { ++ // Paper end ++ Entity entity = iprojectile.getOwner(); + + if (entity instanceof ServerPlayer) { + ServerPlayer entityplayer = (ServerPlayer) entity; + + entityplayer.awardStat(Stats.TARGET_HIT); +- CriteriaTriggers.TARGET_BLOCK_HIT.trigger(entityplayer, projectile, hit.getLocation(), i); ++ CriteriaTriggers.TARGET_BLOCK_HIT.trigger(entityplayer, iprojectile, movingobjectpositionblock.getLocation(), i); + } + + } +@@ -49,6 +54,20 @@ public class TargetBlock extends Block { + int i = getRedstoneStrength(movingobjectpositionblock, movingobjectpositionblock.getLocation()); + int j = entity instanceof AbstractArrow ? 20 : 8; + ++ // Paper start ++ if (entity instanceof Projectile) { ++ final Projectile projectile = (Projectile) entity; ++ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, movingobjectpositionblock.getBlockPos()); ++ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(movingobjectpositionblock.getDirection()); ++ final TargetHitEvent targetHitEvent = new TargetHitEvent((org.bukkit.entity.Projectile) projectile.getBukkitEntity(), craftBlock, blockFace, i); ++ if (targetHitEvent.callEvent()) { ++ i = targetHitEvent.getSignalStrength(); ++ awardTargetHitCriteria(projectile, movingobjectpositionblock, i); ++ } else { ++ return i; ++ } ++ } ++ // Paper end + if (!world.getBlockTicks().a(movingobjectpositionblock.getBlockPos(), state.getBlock())) { + setOutputPower(world, state, i, movingobjectpositionblock.getBlockPos(), j); + } diff --git a/patches/server-remapped/0621-Additional-Block-Material-API-s.patch b/patches/server-remapped/0621-Additional-Block-Material-API-s.patch new file mode 100644 index 0000000000..6aa789f4d3 --- /dev/null +++ b/patches/server-remapped/0621-Additional-Block-Material-API-s.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 30 Dec 2020 19:43:01 -0500 +Subject: [PATCH] Additional Block Material API's + +Faster version for isSolid() that utilizes NMS's state for isSolid instead of the slower +process to do this in the Bukkit API + +Adds API for buildable, replaceable, burnable too. + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 9defb202761296a825d035e27ddc51e17a311647..376b0497c28a35d7ea615397c87b2558b95c596a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -618,6 +618,25 @@ public class CraftBlock implements Block { + return getNMS().getMaterial().isLiquid(); + } + ++ // Paper start ++ @Override ++ public boolean isBuildable() { ++ return getNMS().getMaterial().isBuildable(); ++ } ++ @Override ++ public boolean isBurnable() { ++ return getNMS().getMaterial().isBurnable(); ++ } ++ @Override ++ public boolean isReplaceable() { ++ return getNMS().getMaterial().isReplaceable(); ++ } ++ @Override ++ public boolean isSolid() { ++ return getNMS().getMaterial().blocksMotion(); ++ } ++ // Paper end ++ + @Override + public PistonMoveReaction getPistonMoveReaction() { + return PistonMoveReaction.getById(getNMS().getPistonPushReaction().ordinal()); diff --git a/patches/server-remapped/0622-Fix-harming-potion-dupe.patch b/patches/server-remapped/0622-Fix-harming-potion-dupe.patch new file mode 100644 index 0000000000..e5c11d28d2 --- /dev/null +++ b/patches/server-remapped/0622-Fix-harming-potion-dupe.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> +Date: Thu, 23 Jul 2020 14:25:07 -0700 +Subject: [PATCH] Fix harming potion dupe + +EntityLiving#applyInstantEffect() immediately kills the player and drops their inventory. +Before this patch, instant effects would be applied before the potion ItemStack is removed and replaced with a glass bottle. This caused the potion ItemStack to be dropped before it was supposed to be removed from the inventory. It also caused the glass bottle to be put into a dead player's inventory. +This patch makes it so that instant effects are applied after the potion ItemStack is removed, and the glass bottle is only put into the player's inventory if the player is not dead. Otherwise, the glass bottle is dropped on the ground. + +diff --git a/src/main/java/net/minecraft/world/item/PotionItem.java b/src/main/java/net/minecraft/world/item/PotionItem.java +index 36ccec8ad2f605d5bceae476e26c2fbfbdae39d8..ba2bc044b259b0a5ba590d4ae6fd36e5c415ddff 100644 +--- a/src/main/java/net/minecraft/world/item/PotionItem.java ++++ b/src/main/java/net/minecraft/world/item/PotionItem.java +@@ -15,6 +15,7 @@ import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.alchemy.Potion; + import net.minecraft.world.item.alchemy.PotionUtils; + import net.minecraft.world.item.alchemy.Potions; ++import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; + + public class PotionItem extends Item { +@@ -36,6 +37,7 @@ public class PotionItem extends Item { + CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) entityhuman, stack); + } + ++ List instantLater = new java.util.ArrayList<>(); // Paper - Fix harming potion dupe + if (!world.isClientSide) { + List list = PotionUtils.getMobEffects(stack); + Iterator iterator = list.iterator(); +@@ -44,7 +46,7 @@ public class PotionItem extends Item { + MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + + if (mobeffect.getMobEffect().isInstant()) { +- mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D); ++ instantLater.add(mobeffect); // Paper - Fix harming potion dupe + } else { + user.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit + } +@@ -58,7 +60,20 @@ public class PotionItem extends Item { + } + } + ++ // Paper start - Fix harming potion dupe ++ for (MobEffectInstance mobeffect : instantLater) { ++ mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D); ++ } ++ // Paper end ++ + if (entityhuman == null || !entityhuman.abilities.instabuild) { ++ // Paper start - Fix harming potion dupe ++ if (user.getHealth() <= 0 && !user.level.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY)) { ++ user.dropItem(new ItemStack(Items.GLASS_BOTTLE), 0); ++ return ItemStack.NULL_ITEM; ++ } ++ // Paper end ++ + if (stack.isEmpty()) { + return new ItemStack(Items.GLASS_BOTTLE); + } diff --git a/patches/server-remapped/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/patches/server-remapped/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch new file mode 100644 index 0000000000..f956ace9fd --- /dev/null +++ b/patches/server-remapped/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Thu, 31 Dec 2020 12:48:19 +1000 +Subject: [PATCH] Implement API to get Material from Boats and Minecarts + + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +index 4f82c6797fe9bbb1a29420ea15277be50e44808c..6a9c18540886979b2212bf7917a21753c9a9db3c 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +@@ -259,6 +259,7 @@ public class Boat extends Entity { + + } + ++ public final Item getBoatItem() { return this.getDropItem(); } // Paper - OBFHELPER + public Item getDropItem() { + switch (this.getBoatType()) { + case OAK: +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java +index de8e9e8d18fb9cc6f49d98ab0c57faffec61e5b5..5928ab97b91062963e5cca0a8ec50f2bc3a7ff96 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java +@@ -1,7 +1,9 @@ + package org.bukkit.craftbukkit.entity; + ++import org.bukkit.Material; // Paper + import org.bukkit.TreeSpecies; + import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper + import org.bukkit.entity.Boat; + import org.bukkit.entity.EntityType; + +@@ -65,6 +67,13 @@ public class CraftBoat extends CraftVehicle implements Boat { + getHandle().landBoats = workOnLand; + } + ++ // Paper start ++ @Override ++ public Material getBoatMaterial() { ++ return CraftMagicNumbers.getMaterial(getHandle().getBoatItem()); ++ } ++ // Paper end ++ + @Override + public net.minecraft.world.entity.vehicle.Boat getHandle() { + return (net.minecraft.world.entity.vehicle.Boat) entity; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java +index 55df92a4661e13a9085f325db0572a265a89948c..fb26b6125ad4090d87b2326add94ffaded82c8ef 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java +@@ -1,8 +1,10 @@ + package org.bukkit.craftbukkit.entity; + + import net.minecraft.world.entity.vehicle.AbstractMinecart; ++import net.minecraft.world.item.Items; // Paper + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; ++import org.bukkit.Material; // Paper + import org.bukkit.block.data.BlockData; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.block.data.CraftBlockData; +@@ -68,6 +70,38 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart { + getHandle().setDerailedVelocityMod(derailed); + } + ++ // Paper start ++ @Override ++ public Material getMinecartMaterial() { ++ net.minecraft.world.item.Item minecartItem; ++ switch (getHandle().getMinecartType()) { ++ case CHEST: ++ minecartItem = Items.CHEST_MINECART; ++ break; ++ case FURNACE: ++ minecartItem = Items.FURNACE_MINECART; ++ break; ++ case TNT: ++ minecartItem = Items.TNT_MINECART; ++ break; ++ case HOPPER: ++ minecartItem = Items.HOPPER_MINECART; ++ break; ++ case COMMAND_BLOCK: ++ minecartItem = Items.COMMAND_BLOCK_MINECART; ++ break; ++ case RIDEABLE: ++ case SPAWNER: ++ minecartItem = Items.MINECART; ++ break; ++ default: ++ throw new IllegalStateException("Unexpected value: " + getHandle().getMinecartType()); ++ } ++ ++ return CraftMagicNumbers.getMaterial(minecartItem); ++ } ++ // Paper end ++ + @Override + public AbstractMinecart getHandle() { + return (AbstractMinecart) entity; diff --git a/patches/server-remapped/0624-Optimized-tick-ready-check.patch b/patches/server-remapped/0624-Optimized-tick-ready-check.patch new file mode 100644 index 0000000000..3dd32bb45a --- /dev/null +++ b/patches/server-remapped/0624-Optimized-tick-ready-check.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas +Date: Sun, 27 Dec 2020 17:19:51 +0100 +Subject: [PATCH] Optimized tick ready check + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 066d5f7ee93351bff67c0d39ee9d940ac51515d8..b89cefc8890774dbc64fd6bddeb038d2ee36d485 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -854,13 +854,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + if (!tileentity.isRemoved() && tileentity.hasLevel()) { + BlockPos blockposition = tileentity.getBlockPos(); + +- if (this.getChunkSource().isTickingChunk(blockposition) && this.getWorldBorder().isWithinBounds(blockposition)) { ++ LevelChunk chunk; ChunkHolder playerChunk; if ((chunk = tileentity.getCurrentChunk()) != null && (playerChunk = chunk.playerChunk) != null && playerChunk.isTickingReady() && this.getWorldBorder().isInBounds(blockposition)) { // Paper - optimized tick ready check by inlining ChunkProviderServer.a(BlockPosition). Chunk lookup is no longer required and we can use the PlayerChunk directly available through the tile entity + try { + gameprofilerfiller.push(() -> { + return String.valueOf(BlockEntityType.getKey(tileentity.getType())); + }); + tileentity.tickTimer.startTiming(); // Spigot +- if (tileentity.getType().isValid(this.getBlockState(blockposition).getBlock())) { ++ if (tileentity.getType().isValid(chunk.getBlockState(blockposition).getBlock())) { // Paper - reuse the chunk from above, do not look it up again + ((TickableBlockEntity) tileentity).tick(); + } else { + tileentity.logInvalidState(); +@@ -893,9 +893,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.tickableBlockEntities.remove(tileTickPosition--); + // Spigot end + //this.tileEntityList.remove(tileentity); // Paper - remove unused list +- if (this.hasChunkAt(tileentity.getBlockPos())) { +- this.getChunkAt(tileentity.getBlockPos()).removeBlockEntity(tileentity.getBlockPos()); ++ // Paper - prevent double chunk lookups ++ LevelChunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getBlockPos())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again ++ chunk.removeBlockEntity(tileentity.getBlockPos()); + } ++ // Paper end + } + } + +@@ -914,8 +916,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + // CraftBukkit end */ + +- if (this.hasChunkAt(tileentity1.getBlockPos())) { +- LevelChunk chunk = this.getChunkAt(tileentity1.getBlockPos()); ++ LevelChunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity1.getBlockPos())) != null) { // Paper - inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again ++ // Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); // Paper - already computed above + BlockState iblockdata = chunk.getBlockState(tileentity1.getBlockPos()); + + chunk.setBlockEntity(tileentity1.getBlockPos(), tileentity1); diff --git a/patches/server-remapped/0625-Cache-burn-durations.patch b/patches/server-remapped/0625-Cache-burn-durations.patch new file mode 100644 index 0000000000..4163e2cc84 --- /dev/null +++ b/patches/server-remapped/0625-Cache-burn-durations.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas +Date: Sun, 27 Dec 2020 16:47:00 +0100 +Subject: [PATCH] Cache burn durations + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 4126a36dbc7750108a883f0be14dcb0d2e6d7ae8..f47b46cebd43faa509b8139d2a51cc8f87615893 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.block.entity; + ++import com.google.common.collect.ImmutableMap; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; +@@ -111,7 +112,15 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + this.recipeType = recipeType; + } + ++ private static Map cachedBurnDurations = null; // Paper - cache burn durations ++ ++ public static Map getBurnDurations() { return getFuel(); } // Paper - OBFHELPER + public static Map getFuel() { ++ // Paper start - cache burn durations ++ if(cachedBurnDurations != null) { ++ return cachedBurnDurations; ++ } ++ // Paper end + Map map = Maps.newLinkedHashMap(); + + add(map, (ItemLike) Items.LAVA_BUCKET, 20000); +@@ -174,7 +183,10 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + add(map, (ItemLike) Blocks.FLETCHING_TABLE, 300); + add(map, (ItemLike) Blocks.SMITHING_TABLE, 300); + add(map, (ItemLike) Blocks.COMPOSTER, 300); +- return map; ++ // Paper start - cache burn durations ++ cachedBurnDurations = ImmutableMap.copyOf(map); ++ return cachedBurnDurations; ++ // Paper end + } + + // CraftBukkit start - add fields and methods +@@ -428,7 +440,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + } else { + Item item = fuel.getItem(); + +- return (Integer) getFuel().getOrDefault(item, 0); ++ return getBurnDurations().getOrDefault(item, 0); // Paper - cache burn durations + } + } + +@@ -441,7 +453,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + // Paper end + + public static boolean isFuel(ItemStack stack) { +- return getFuel().containsKey(stack.getItem()); ++ return getBurnDurations().containsKey(stack.getItem()); // Paper - cache burn durations + } + + @Override diff --git a/patches/server-remapped/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server-remapped/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch new file mode 100644 index 0000000000..efb245db2f --- /dev/null +++ b/patches/server-remapped/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BrodyBeckwith +Date: Fri, 9 Oct 2020 20:30:12 -0400 +Subject: [PATCH] Allow disabling mob spawner spawn egg transformation + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index a3b3e3e04b7a5e3a351992e06870cc91fbd8adc8..b48067c71f9de18ba40e970e2832f6245984a218 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -722,4 +722,9 @@ public class PaperWorldConfig { + private void fixCuringExploit() { + fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); + } ++ ++ public boolean disableMobSpawnerSpawnEggTransformation = false; ++ private void disableMobSpawnerSpawnEggTransformation() { ++ disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); ++ } + } +diff --git a/src/main/java/net/minecraft/world/item/SpawnEggItem.java b/src/main/java/net/minecraft/world/item/SpawnEggItem.java +index 9aae1435a271bb17d6355e4c75ccbce78cb9d449..7904a2176253eaf48b47e06dd2e19758a673873c 100644 +--- a/src/main/java/net/minecraft/world/item/SpawnEggItem.java ++++ b/src/main/java/net/minecraft/world/item/SpawnEggItem.java +@@ -60,7 +60,7 @@ public class SpawnEggItem extends Item { + Direction enumdirection = context.getClickedFace(); + BlockState iblockdata = world.getBlockState(blockposition); + +- if (iblockdata.is(Blocks.SPAWNER)) { ++ if (!world.paperConfig.disableMobSpawnerSpawnEggTransformation && iblockdata.is(Blocks.SPAWNER)) { // Paper + BlockEntity tileentity = world.getBlockEntity(blockposition); + + if (tileentity instanceof SpawnerBlockEntity) { diff --git a/patches/server-remapped/0627-Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server-remapped/0627-Implement-PlayerFlowerPotManipulateEvent.patch new file mode 100644 index 0000000000..2c81edd9ad --- /dev/null +++ b/patches/server-remapped/0627-Implement-PlayerFlowerPotManipulateEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MisterVector +Date: Tue, 13 Aug 2019 19:45:06 -0700 +Subject: [PATCH] Implement PlayerFlowerPotManipulateEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java b/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java +index ae74e70457f8f46ee71bf0902ade3468da272e81..a1d1f3416df8e313688fedad47dd264444d7c465 100644 +--- a/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java +@@ -20,6 +20,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent; // Paper + + public class FlowerPotBlock extends Block { + +@@ -52,6 +53,27 @@ public class FlowerPotBlock extends Block { + boolean flag1 = this.content == Blocks.AIR; + + if (flag != flag1) { ++ // Paper start ++ org.bukkit.entity.Player player1 = (org.bukkit.entity.Player) player.getBukkitEntity(); ++ boolean placing = flag1; ++ org.bukkit.block.Block bukkitblock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos); ++ org.bukkit.inventory.ItemStack bukkititemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack); ++ org.bukkit.Material mat = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(content); ++ org.bukkit.inventory.ItemStack bukkititemstack1 = new org.bukkit.inventory.ItemStack(mat, 1); ++ org.bukkit.inventory.ItemStack whichitem = placing ? bukkititemstack : bukkititemstack1; ++ ++ PlayerFlowerPotManipulateEvent event = new PlayerFlowerPotManipulateEvent(player1, bukkitblock, whichitem, placing); ++ player1.getServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ // Update client ++ player1.sendBlockChange(bukkitblock.getLocation(), bukkitblock.getBlockData()); ++ player1.updateInventory(); ++ ++ return InteractionResult.PASS; ++ } ++ // Paper end ++ + if (flag1) { + world.setBlock(pos, block.defaultBlockState(), 3); + player.awardStat(Stats.POT_FLOWER); diff --git a/patches/server-remapped/0628-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server-remapped/0628-Fix-interact-event-not-being-called-in-adventure.patch new file mode 100644 index 0000000000..5e69fe3a87 --- /dev/null +++ b/patches/server-remapped/0628-Fix-interact-event-not-being-called-in-adventure.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheMolkaPL +Date: Sun, 21 Jun 2020 17:21:46 +0200 +Subject: [PATCH] Fix interact event not being called in adventure + +Call PlayerInteractEvent when left-clicking on a block in adventure mode + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index e50e42cce60c725cdd981d8927e379c5760d9200..cb6568b622abeb939a1195f4656accc8a1c3f1fc 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1701,7 +1701,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + MutableComponent ichatmutablecomponent = (new TranslatableComponent("build.tooHigh", new Object[]{this.server.getMaxBuildHeight()})).withStyle(ChatFormatting.RED); + + this.player.connection.send(new ClientboundChatPacket(ichatmutablecomponent, ChatType.GAME_INFO, Util.NIL_UUID)); +- } else if (enuminteractionresult.shouldSwing()) { ++ } else if (enuminteractionresult.shouldSwing() && !this.player.gameMode.interactResult) { + this.player.swing(enumhand, true); + } + } +@@ -2202,7 +2202,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + Vec3 vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); + HitResult movingobjectposition = this.player.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)); + +- if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK) { ++ if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK || this.player.gameMode.getGameModeForPlayer() == GameType.ADVENTURE) { // Paper - call PlayerInteractEvent when left-clicking on a block in adventure mode + CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.inventory.getSelected(), InteractionHand.MAIN_HAND); + } + diff --git a/patches/server-remapped/0629-Zombie-API-breaking-doors.patch b/patches/server-remapped/0629-Zombie-API-breaking-doors.patch new file mode 100644 index 0000000000..63b6f1e733 --- /dev/null +++ b/patches/server-remapped/0629-Zombie-API-breaking-doors.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 18 Nov 2020 11:32:46 -0800 +Subject: [PATCH] Zombie API - breaking doors + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 4105c1763d25824aac35d305a793823c1604eee8..77634a1e8e7539000f7db0b96f4548137af1a819 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -137,10 +137,12 @@ public class Zombie extends Monster { + return (Boolean) this.getEntityData().get(Zombie.DATA_DROWNED_CONVERSION_ID); + } + ++ public boolean canBreakDoors() { return this.canBreakDoors(); } // Paper - OBFHELPER + public boolean canBreakDoors() { + return this.canBreakDoors; + } + ++ public void setCanBreakDoors(boolean canBreakDoors) { this.setCanBreakDoors(canBreakDoors); } // Paper - OBFHELPER + public void setCanBreakDoors(boolean canBreakDoors) { + if (this.supportsBreakDoorGoal() && GoalUtils.hasGroundPathNavigation(this)) { + if (this.canBreakDoors != canBreakDoors) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +index 86f65c07806a118c49e900c59be86c2bd2eb124c..44f21b3b1c2f2fbc1f3f53931349b9a9426e97f8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +@@ -128,6 +128,16 @@ public class CraftZombie extends CraftMonster implements Zombie { + public void setShouldBurnInDay(boolean shouldBurnInDay) { + getHandle().setShouldBurnInDay(shouldBurnInDay); + } ++ ++ @Override ++ public boolean canBreakDoors() { ++ return getHandle().canBreakDoors(); ++ } ++ ++ @Override ++ public void setCanBreakDoors(boolean canBreakDoors) { ++ getHandle().setCanBreakDoors(canBreakDoors); ++ } + // Paper end + + @Override diff --git a/patches/server-remapped/0630-Fix-nerfed-slime-when-splitting.patch b/patches/server-remapped/0630-Fix-nerfed-slime-when-splitting.patch new file mode 100644 index 0000000000..85d8576628 --- /dev/null +++ b/patches/server-remapped/0630-Fix-nerfed-slime-when-splitting.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 24 Aug 2020 08:39:06 -0700 +Subject: [PATCH] Fix nerfed slime when splitting + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java +index 120ceb28ee3aee8a09cf67b45ac95d3d6613c133..2f04543c1c0a197f22fb26b2a38c7c79e6b4a63a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java +@@ -242,6 +242,7 @@ public class Slime extends Mob implements Enemy { + entityslime.setPersistenceRequired(); + } + ++ entityslime.aware = this.aware; // Paper + entityslime.setCustomName(ichatbasecomponent); + entityslime.setNoAi(flag); + entityslime.setInvulnerable(this.isInvulnerable()); diff --git a/patches/server-remapped/0631-Add-EntityLoadCrossbowEvent.patch b/patches/server-remapped/0631-Add-EntityLoadCrossbowEvent.patch new file mode 100644 index 0000000000..6eea724442 --- /dev/null +++ b/patches/server-remapped/0631-Add-EntityLoadCrossbowEvent.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 7 Oct 2020 12:04:01 -0400 +Subject: [PATCH] Add EntityLoadCrossbowEvent + + +diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java +index e1e58b7035e6dbafdad0a04cc5333464fc4febb8..32e927375daeaf16f4ea763bc9f7c4a244797bba 100644 +--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java ++++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java +@@ -3,6 +3,8 @@ package net.minecraft.world.item; + import com.google.common.collect.Lists; + import com.mojang.math.Quaternion; + import com.mojang.math.Vector3f; ++import org.bukkit.inventory.EquipmentSlot; // Paper ++import io.papermc.paper.event.entity.EntityLoadCrossbowEvent; // Paper - EntityLoadCrossbowEvent namespace conflicts + import java.util.List; + import java.util.Random; + import java.util.function.Predicate; +@@ -73,7 +75,11 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + int j = this.getUseDuration(stack) - remainingUseTicks; + float f = getPowerForTime(j, stack); + +- if (f >= 1.0F && !isCharged(stack) && tryLoadProjectiles(user, stack)) { ++ // Paper start - EntityLoadCrossbowEvent ++ if (f >= 1.0F && !isCharged(stack) /*&& a(entityliving, itemstack)*/) { ++ final EntityLoadCrossbowEvent event = new EntityLoadCrossbowEvent(user.getBukkitLivingEntity(), stack.asBukkitMirror(), user.getUsedItemHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND); ++ if (!event.callEvent() || !attemptProjectileLoad(user, stack, event.shouldConsumeItem())) return; ++ // Paper end + setCharged(stack, true); + SoundSource soundcategory = user instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE; + +@@ -82,11 +88,14 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + + } + +- private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack projectile) { +- int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, projectile); ++ private static boolean attemptProjectileLoad(LivingEntity ent, ItemStack bow) { return tryLoadProjectiles(ent, bow); } // Paper - EntityLoadCrossbowEvent - OBFHELPER ++ private static boolean attemptProjectileLoad(LivingEntity ent, ItemStack bow, boolean consume) { return a(ent, bow, consume); } // Paper - EntityLoadCrossbowEvent - OBFHELPER ++ private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack projectile) { return a(shooter, projectile, true); };// Paper - add consume ++ private static boolean a(LivingEntity entityliving, ItemStack itemstack, boolean consume) { // Paper - add consume ++ int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, itemstack); + int j = i == 0 ? 1 : 3; +- boolean flag = shooter instanceof Player && ((Player) shooter).abilities.instabuild; +- ItemStack itemstack1 = shooter.getProjectile(projectile); ++ boolean flag = !consume || entityliving instanceof Player && ((Player) entityliving).abilities.instabuild; // Paper - add consme ++ ItemStack itemstack1 = entityliving.getProjectile(itemstack); + ItemStack itemstack2 = itemstack1.copy(); + + for (int k = 0; k < j; ++k) { +@@ -103,7 +112,7 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + // CraftBukkit end + } + +- if (!loadProjectile(shooter, projectile, itemstack1, k > 0, flag)) { ++ if (!loadProjectile(entityliving, itemstack, itemstack1, k > 0, flag)) { + return false; + } + } diff --git a/patches/server-remapped/0632-Guardian-beam-workaround.patch b/patches/server-remapped/0632-Guardian-beam-workaround.patch new file mode 100644 index 0000000000..c16b905697 --- /dev/null +++ b/patches/server-remapped/0632-Guardian-beam-workaround.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gabscap +Date: Sat, 19 Mar 2016 22:25:11 +0100 +Subject: [PATCH] Guardian beam workaround + +This patch is a workaround for MC-165595 + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java +index a02f492c279f4e859b44d52e150a2990cbe8275a..4f177e7396db00db56f2106068fc02b9c2618407 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java +@@ -6,7 +6,7 @@ import net.minecraft.network.protocol.Packet; + + public class ClientboundSetTimePacket implements Packet { + +- private long gameTime; ++ private long gameTime; private final void setWorldAge(final long age) { this.gameTime = age; } private final long getWorldAge() { return this.gameTime; } // Paper - OBFHELPER + private long dayTime; + + public ClientboundSetTimePacket() {} +@@ -21,6 +21,9 @@ public class ClientboundSetTimePacket implements Packet +Date: Sun, 20 Dec 2020 16:41:44 -0800 +Subject: [PATCH] Added WorldGameRuleChangeEvent + + +diff --git a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java +index 87b968019fa10647522121c7b29094ed3e0dcf6d..7f124784dd7876cdb26f16e83deddf07dd9a198e 100644 +--- a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java +@@ -31,7 +31,7 @@ public class GameRuleCommand { + CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); + T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(key); // CraftBukkit + +- t0.setFromArgument(context, "value"); ++ t0.setValue(context, "value", key); // Paper + commandlistenerwrapper.sendSuccess(new TranslatableComponent("commands.gamerule.set", new Object[]{key.getId(), t0.toString()}), true); + return t0.getCommandResult(); + } +diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java +index 6c996d34ef34879db1d65c39adf99ce2d64e5499..1e6f299571a25729dbf8c5b0cd115c1e842a8a3c 100644 +--- a/src/main/java/net/minecraft/world/level/GameRules.java ++++ b/src/main/java/net/minecraft/world/level/GameRules.java +@@ -25,6 +25,7 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerPlayer; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import io.papermc.paper.event.world.WorldGameRuleChangeEvent; // Paper + + public class GameRules { + +@@ -177,8 +178,11 @@ public class GameRules { + } + + @Override +- protected void updateFromArgument(CommandContext context, String name) { +- this.value = BoolArgumentType.getBool(context, name); ++ protected void a(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { // Paper start ++ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(commandcontext, s))); ++ if (!event.callEvent()) return; ++ this.value = Boolean.parseBoolean(event.getValue()); ++ // Paper end + } + + public boolean get() { +@@ -237,8 +241,11 @@ public class GameRules { + } + + @Override +- protected void updateFromArgument(CommandContext context, String name) { +- this.value = IntegerArgumentType.getInteger(context, name); ++ protected void a(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { // Paper start ++ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(commandcontext, s))); ++ if (!event.callEvent()) return; ++ this.value = Integer.parseInt(event.getValue()); ++ // Paper end + } + + public int get() { +@@ -291,11 +298,13 @@ public class GameRules { + this.type = type; + } + +- protected abstract void updateFromArgument(CommandContext context, String name); ++ protected void updateValue(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { this.a(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER ++ protected abstract void a(CommandContext commandcontext, String s, GameRules.Key gameRuleKey); // Paper + +- public void setFromArgument(CommandContext context, String name) { +- this.updateFromArgument(context, name); +- this.onChanged(((CommandSourceStack) context.getSource()).getServer()); ++ public void setValue(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { this.b(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER ++ public void b(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { // Paper ++ this.updateValue(commandcontext, s, gameRuleKey); // Paper ++ this.onChanged(((CommandSourceStack) commandcontext.getSource()).getServer()); + } + + public void onChanged(@Nullable MinecraftServer server) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index aaf97c13babce3b0ffc639ef950d59d1eba1398a..f497b9e11a075a84ff0a2117eb79d0532e4a326f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2345,8 +2345,13 @@ public class CraftWorld implements World { + + if (!isGameRule(rule)) return false; + ++ // Paper start ++ GameRule gameRule = GameRule.getByName(rule); ++ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, gameRule, value); ++ if (!event.callEvent()) return false; ++ // Paper end + GameRules.Value handle = getHandle().getGameRules().getRule(getGameRulesNMS().get(rule)); +- handle.deserialize(value); ++ handle.deserialize(event.getValue().toString()); // Paper + handle.onChanged(getHandle().getServer()); + return true; + } +@@ -2381,8 +2386,12 @@ public class CraftWorld implements World { + + if (!isGameRule(rule.getName())) return false; + ++ // Paper start ++ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, rule, String.valueOf(newValue)); ++ if (!event.callEvent()) return false; ++ // Paper end + GameRules.Value handle = getHandle().getGameRules().getRule(getGameRulesNMS().get(rule.getName())); +- handle.deserialize(newValue.toString()); ++ handle.deserialize(event.getValue().toString()); // Paper + handle.onChanged(getHandle().getServer()); + return true; + } diff --git a/patches/server-remapped/0634-Added-ServerResourcesReloadedEvent.patch b/patches/server-remapped/0634-Added-ServerResourcesReloadedEvent.patch new file mode 100644 index 0000000000..02aef6be64 --- /dev/null +++ b/patches/server-remapped/0634-Added-ServerResourcesReloadedEvent.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 2 Dec 2020 20:04:01 -0800 +Subject: [PATCH] Added ServerResourcesReloadedEvent + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index c83f2636ae93d92381e019d5b13ac82c5a1d30bf..892ca65d258b0745be95d7ef4886c49899b24d92 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2,9 +2,6 @@ package net.minecraft.server; + + import com.google.common.base.Splitter; + import com.google.common.collect.ImmutableList; +-import co.aikar.timings.Timings; +-import com.destroystokyo.paper.event.server.PaperServerListPingEvent; +-import com.google.common.base.Stopwatch; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; +@@ -181,6 +178,7 @@ import org.bukkit.event.server.ServerLoadEvent; + import co.aikar.timings.MinecraftTimings; // Paper + import org.spigotmc.SlackActivityAccountant; // Spigot + import io.papermc.paper.util.PaperJvmChecker; // Paper ++import io.papermc.paper.event.server.ServerResourcesReloadedEvent; // Paper + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { + +@@ -1934,9 +1932,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop reloadResources(Collection datapacks) { ++ return this.reloadServerResources(datapacks, ServerResourcesReloadedEvent.Cause.PLUGIN); ++ } ++ public CompletableFuture reloadServerResources(Collection collection, ServerResourcesReloadedEvent.Cause cause) { ++ // Paper end + CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { +- Stream stream = datapacks.stream(); // CraftBukkit - decompile error ++ Stream stream = collection.stream(); // CraftBukkit - decompile error + PackRepository resourcepackrepository = this.packRepository; + + this.packRepository.getClass(); +@@ -1947,9 +1951,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop collection, CommandSourceStack commandlistenerwrapper) { +- commandlistenerwrapper.getServer().reloadResources(collection).exceptionally((throwable) -> { +- ReloadCommand.LOGGER.warn("Failed to execute reload", throwable); +- commandlistenerwrapper.sendFailure(new TranslatableComponent("commands.reload.failure")); ++ commandlistenerwrapper.getServer().reloadServerResources(collection, ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally((throwable) -> { // Paper ++ CommandReload.LOGGER.warn("Failed to execute reload", throwable); ++ commandlistenerwrapper.sendFailureMessage(new ChatMessage("commands.reload.failure")); + return null; + }); + } +@@ -48,7 +49,7 @@ public class ReloadCommand { + WorldData savedata = minecraftserver.getWorldData(); + Collection collection = resourcepackrepository.getSelectedIds(); + Collection collection1 = discoverNewPacks(resourcepackrepository, savedata, collection); +- minecraftserver.reloadResources(collection1); ++ minecraftserver.reloadServerResources(collection1, ServerResourcesReloadedEvent.Cause.PLUGIN); // Paper + } + // CraftBukkit end + diff --git a/patches/server-remapped/0635-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server-remapped/0635-Added-world-settings-for-mobs-picking-up-loot.patch new file mode 100644 index 0000000000..ead34bbc60 --- /dev/null +++ b/patches/server-remapped/0635-Added-world-settings-for-mobs-picking-up-loot.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 28 Nov 2020 18:43:52 -0800 +Subject: [PATCH] Added world settings for mobs picking up loot + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index b48067c71f9de18ba40e970e2832f6245984a218..23a23e2ea133ce81d3dedc4ffd17435a995497ef 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -363,6 +363,14 @@ public class PaperWorldConfig { + log("Creeper lingering effect: " + disableCreeperLingeringEffect); + } + ++ public boolean zombiesAlwaysCanPickUpLoot; ++ public boolean skeletonsAlwaysCanPickUpLoot; ++ private void setMobsAlwaysCanPickUpLoot() { ++ zombiesAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.zombies", false); ++ skeletonsAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.skeletons", false); ++ log("Zombies can always pick up loot: " + zombiesAlwaysCanPickUpLoot + ". Skeletons can always pick up loot: " + skeletonsAlwaysCanPickUpLoot + "."); ++ } ++ + public int expMergeMaxValue; + private void expMergeMaxValue() { + expMergeMaxValue = getInt("experience-merge-max-value", -1); +diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +index 76027a7c9615495af64102744e264d7ba7c9b87e..68e52e3a31e70569d1a92602aff4b7b81c594757 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -149,7 +149,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + this.populateDefaultEquipmentSlots(difficulty); + this.populateDefaultEquipmentEnchantments(difficulty); + this.reassessWeaponGoal(); +- this.setCanPickUpLoot(this.random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); ++ this.setCanPickUpLoot(this.level.paperConfig.skeletonsAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper + if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { + LocalDate localdate = LocalDate.now(); + int i = localdate.get(ChronoField.DAY_OF_MONTH); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 77634a1e8e7539000f7db0b96f4548137af1a819..74fd175c4dc2d0d9832ee41efaf065b75a43f4b8 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -494,7 +494,7 @@ public class Zombie extends Monster { + Object object = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag); + float f = difficulty.getSpecialMultiplier(); + +- this.setCanPickUpLoot(this.random.nextFloat() < 0.55F * f); ++ this.setCanPickUpLoot(this.level.paperConfig.zombiesAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * f); // Paper + if (object == null) { + object = new Zombie.ZombieGroupData(getSpawnAsBabyOdds(world.getRandom()), true); + } diff --git a/patches/server-remapped/0636-Implemented-BlockFailedDispenseEvent.patch b/patches/server-remapped/0636-Implemented-BlockFailedDispenseEvent.patch new file mode 100644 index 0000000000..a7a4e49910 --- /dev/null +++ b/patches/server-remapped/0636-Implemented-BlockFailedDispenseEvent.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheViperShow <29604693+TheViperShow@users.noreply.github.com> +Date: Wed, 22 Apr 2020 09:40:38 +0200 +Subject: [PATCH] Implemented BlockFailedDispenseEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +index bfb2e21ccbcc67d6c9b4b329db1949d7d938bd2e..2a4cb76bdfcf55ba222b4976359c1b8efb165009 100644 +--- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +@@ -81,6 +81,7 @@ public class DispenserBlock extends BaseEntityBlock { + int i = tileentitydispenser.getRandomSlot(); + + if (i < 0) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, pos)) // Paper - BlockFailedDispenseEvent is called here + worldserver.levelEvent(1001, pos, 0); + } else { + ItemStack itemstack = tileentitydispenser.getItem(i); +diff --git a/src/main/java/net/minecraft/world/level/block/DropperBlock.java b/src/main/java/net/minecraft/world/level/block/DropperBlock.java +index 154ec671e9d741e536464b794783da859e8447c1..492b19b94e2e2439f72ed9478d75641b0f50451a 100644 +--- a/src/main/java/net/minecraft/world/level/block/DropperBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DropperBlock.java +@@ -45,6 +45,7 @@ public class DropperBlock extends DispenserBlock { + int i = tileentitydispenser.getRandomSlot(); + + if (i < 0) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, pos)) // Paper - BlockFailedDispenseEvent is called here + worldserver.levelEvent(1001, pos, 0); + } 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 34c7b1213b3f83ff1a1f2d606a9c25e57fea8ef3..8829ef03d0be16d8317aaf05bcd286b74f20656a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -4,6 +4,7 @@ import com.google.common.base.Function; + import com.google.common.base.Functions; + import com.google.common.collect.Lists; + import com.mojang.datafixers.util.Either; ++import io.papermc.paper.event.block.BlockFailedDispenseEvent; + import java.net.InetAddress; + import java.util.ArrayList; + import java.util.Collections; +@@ -111,7 +112,6 @@ import org.bukkit.entity.ThrownPotion; + import org.bukkit.entity.Vehicle; + import org.bukkit.entity.Villager; + import org.bukkit.entity.Villager.Profession; +-import org.bukkit.entity.ExperienceOrb; // Paper + import org.bukkit.event.Cancellable; + import org.bukkit.event.Event; + import org.bukkit.event.Event.Result; +@@ -1784,4 +1784,12 @@ public class CraftEventFactory { + Bukkit.getPluginManager().callEvent(event); + return event; + } ++ ++ // Paper start ++ public static boolean handleBlockFailedDispenseEvent(ServerLevel worldserver, BlockPos blockposition) { ++ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); ++ return event.callEvent(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0637-Added-PlayerLecternPageChangeEvent.patch b/patches/server-remapped/0637-Added-PlayerLecternPageChangeEvent.patch new file mode 100644 index 0000000000..b4eacbfa37 --- /dev/null +++ b/patches/server-remapped/0637-Added-PlayerLecternPageChangeEvent.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 23 Nov 2020 12:58:51 -0800 +Subject: [PATCH] Added PlayerLecternPageChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index bc39e7464646d712b085251dc0277a5b1ec0a393..b5d79635cd8b0eb6b17962450b347010aeb52654 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -561,6 +561,7 @@ public abstract class AbstractContainerMenu { + this.getSlot(slot).set(stack); + } + ++ public void setData(int index, int value) { this.setData(index, value); } // Paper - OBFHELPER + public void setData(int id, int value) { + ((DataSlot) this.dataSlots.get(id)).set(value); + } +diff --git a/src/main/java/net/minecraft/world/inventory/LecternMenu.java b/src/main/java/net/minecraft/world/inventory/LecternMenu.java +index 29e8dbc6be57faf50a8ca68eed6bf2e203b7e87a..a7be91a9336065899c409526a890e55f37b98751 100644 +--- a/src/main/java/net/minecraft/world/inventory/LecternMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/LecternMenu.java +@@ -11,6 +11,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryView; + import org.bukkit.entity.Player; + import org.bukkit.event.player.PlayerTakeLecternBookEvent; + // CraftBukkit end ++import io.papermc.paper.event.player.PlayerLecternPageChangeEvent; // Paper + + public class LecternMenu extends AbstractContainerMenu { + +@@ -58,6 +59,7 @@ public class LecternMenu extends AbstractContainerMenu { + @Override + public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + int j; ++ PlayerLecternPageChangeEvent playerLecternPageChangeEvent; CraftInventoryLectern bukkitView; // Paper + + if (id >= 100) { + j = id - 100; +@@ -67,11 +69,25 @@ public class LecternMenu extends AbstractContainerMenu { + switch (id) { + case 1: + j = this.lecternData.get(0); +- this.setData(0, j - 1); ++ // Paper start ++ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); ++ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, j, j - 1); ++ if (!playerLecternPageChangeEvent.callEvent()) { ++ return false; ++ } ++ this.setData(0, playerLecternPageChangeEvent.getNewPage()); ++ // Paper end + return true; + case 2: + j = this.lecternData.get(0); +- this.setData(0, j + 1); ++ // Paper start ++ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); ++ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, j, j + 1); ++ if (!playerLecternPageChangeEvent.callEvent()) { ++ return false; ++ } ++ this.setData(0, playerLecternPageChangeEvent.getNewPage()); ++ // Paper end + return true; + case 3: + if (!player.mayBuild()) { diff --git a/patches/server-remapped/0638-Fire-event-on-GS4-query.patch b/patches/server-remapped/0638-Fire-event-on-GS4-query.patch new file mode 100644 index 0000000000..a893ed5f5c --- /dev/null +++ b/patches/server-remapped/0638-Fire-event-on-GS4-query.patch @@ -0,0 +1,265 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 17 Mar 2019 21:46:56 +0200 +Subject: [PATCH] Fire event on GS4 query + + +diff --git a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java +index d10de580430d754204b36de809376538a14591e6..f6f0539a8e6edbeb1c412cee753a282b24a38046 100644 +--- a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java ++++ b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java +@@ -18,15 +18,27 @@ public class NetworkDataOutputStream { + this.dataOutputStream.write(abyte, 0, abyte.length); + } + ++ public void writeString(String string) throws IOException { this.writeString(string); } // Paper - OBFHELPER + public void writeString(String s) throws IOException { + this.dataOutputStream.writeBytes(s); + this.dataOutputStream.write(0); + } ++ // Paper start - unchecked exception variant to use in Stream API ++ public void writeStringUnchecked(String string) { ++ try { ++ writeString(string); ++ } catch (IOException e) { ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(e); ++ } ++ } ++ // Paper end + ++ public void writeInt(int i) throws IOException { this.write(i); } // Paper - OBFHELPER + public void write(int i) throws IOException { + this.dataOutputStream.write(i); + } + ++ public void writeShort(short i) throws IOException { this.writeShort(i); } // Paper - OBFHELPER + public void writeShort(short short0) throws IOException { + this.dataOutputStream.writeShort(Short.reverseBytes(short0)); + } +diff --git a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java +index 170d047463154bd6851199f06fe343ccb1896213..5562a3caff328bb08857b4f06a79b1e52f390fdd 100644 +--- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java ++++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java +@@ -16,6 +16,7 @@ import java.util.Random; + import javax.annotation.Nullable; + import net.minecraft.Util; + import net.minecraft.server.ServerInterface; ++import net.minecraft.server.dedicated.DedicatedServer; + import net.minecraft.server.rcon.NetworkDataOutputStream; + import net.minecraft.server.rcon.PktUtils; + import org.apache.logging.log4j.LogManager; +@@ -26,18 +27,18 @@ public class QueryThreadGs4 extends GenericThread { + private static final Logger LOGGER = LogManager.getLogger(); + private long lastChallengeCheck; + private final int port; +- private final int serverPort; +- private final int maxPlayers; +- private final String serverName; +- private final String worldName; ++ private final int serverPort; private final int getServerPort() { return this.serverPort; } // Paper - OBFHELPER ++ private final int maxPlayers; private final int getMaxPlayers() { return this.maxPlayers; } // Paper - OBFHELPER ++ private final String serverName; private final String getMotd() { return this.serverName; } // Paper - OBFHELPER ++ private final String worldName; private final String getWorldName() { return this.worldName; } // Paper - OBFHELPER + private DatagramSocket socket; + private final byte[] buffer = new byte[1460]; +- private String hostIp; ++ private String hostIp; public final String getServerHost() { return this.hostIp; } // Paper - OBFHELPER + private String serverIp; + private final Map validChallenges; +- private final NetworkDataOutputStream rulesResponse; ++ private final NetworkDataOutputStream rulesResponse; private final NetworkDataOutputStream getCachedFullResponse() { return this.rulesResponse; } // Paper - OBFHELPER + private long lastRulesResponse; +- private final ServerInterface serverInterface; ++ private final ServerInterface serverInterface; private final ServerInterface getServer() { return this.serverInterface; } // Paper - OBFHELPER + + private QueryThreadGs4(ServerInterface server, int queryPort) { + super("Query Listener"); +@@ -107,13 +108,39 @@ public class QueryThreadGs4 extends GenericThread { + + remotestatusreply.write((int) 0); + remotestatusreply.writeBytes(this.getIdentBytes(packet.getSocketAddress())); +- remotestatusreply.writeString(this.serverName); ++ /* Paper start - GS4 Query event ++ remotestatusreply.a(this.i); ++ remotestatusreply.a("SMP"); ++ remotestatusreply.a(this.j); ++ remotestatusreply.a(Integer.toString(this.r.getPlayerCount())); ++ remotestatusreply.a(Integer.toString(this.h)); ++ remotestatusreply.a((short) this.g); ++ remotestatusreply.a(this.m); ++ */ ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.BASIC; ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() ++ .motd(this.getMotd()) ++ .map(this.getWorldName()) ++ .currentPlayers(this.getServer().getPlayerCount()) ++ .maxPlayers(this.getMaxPlayers()) ++ .port(this.getServerPort()) ++ .hostname(this.getServerHost()) ++ .gameVersion(this.getServer().getServerVersion()) ++ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) ++ .build(); ++ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = ++ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, packet.getAddress(), queryResponse); ++ queryEvent.callEvent(); ++ queryResponse = queryEvent.getResponse(); ++ remotestatusreply.writeString(queryResponse.getMotd()); + remotestatusreply.writeString("SMP"); +- remotestatusreply.writeString(this.worldName); +- remotestatusreply.writeString(Integer.toString(this.serverInterface.getPlayerCount())); +- remotestatusreply.writeString(Integer.toString(this.maxPlayers)); +- remotestatusreply.writeShort((short) this.serverPort); +- remotestatusreply.writeString(this.hostIp); ++ remotestatusreply.writeString(queryResponse.getMap()); ++ remotestatusreply.writeString(Integer.toString(queryResponse.getCurrentPlayers())); ++ remotestatusreply.writeString(Integer.toString(queryResponse.getMaxPlayers())); ++ remotestatusreply.writeShort((short) queryResponse.getPort()); ++ remotestatusreply.writeString(queryResponse.getHostname()); ++ // Paper end + this.sendTo(remotestatusreply.toByteArray(), packet); + QueryThreadGs4.LOGGER.debug("Status [{}]", socketaddress); + } +@@ -150,41 +177,115 @@ public class QueryThreadGs4 extends GenericThread { + this.rulesResponse.writeString("splitnum"); + this.rulesResponse.write((int) 128); + this.rulesResponse.write((int) 0); +- this.rulesResponse.writeString("hostname"); +- this.rulesResponse.writeString(this.serverName); +- this.rulesResponse.writeString("gametype"); +- this.rulesResponse.writeString("SMP"); +- this.rulesResponse.writeString("game_id"); +- this.rulesResponse.writeString("MINECRAFT"); +- this.rulesResponse.writeString("version"); +- this.rulesResponse.writeString(this.serverInterface.getServerVersion()); +- this.rulesResponse.writeString("plugins"); +- this.rulesResponse.writeString(this.serverInterface.getPluginNames()); +- this.rulesResponse.writeString("map"); +- this.rulesResponse.writeString(this.worldName); +- this.rulesResponse.writeString("numplayers"); +- this.rulesResponse.writeString("" + this.serverInterface.getPlayerCount()); +- this.rulesResponse.writeString("maxplayers"); +- this.rulesResponse.writeString("" + this.maxPlayers); +- this.rulesResponse.writeString("hostport"); +- this.rulesResponse.writeString("" + this.serverPort); +- this.rulesResponse.writeString("hostip"); +- this.rulesResponse.writeString(this.hostIp); +- this.rulesResponse.write((int) 0); +- this.rulesResponse.write((int) 1); +- this.rulesResponse.writeString("player_"); +- this.rulesResponse.write((int) 0); +- String[] astring = this.serverInterface.getPlayerNames(); ++ /* Paper start - GS4 Query event ++ this.p.a("hostname"); ++ this.p.a(this.i); ++ this.p.a("gametype"); ++ this.p.a("SMP"); ++ this.p.a("game_id"); ++ this.p.a("MINECRAFT"); ++ this.p.a("version"); ++ this.p.a(this.r.getVersion()); ++ this.p.a("plugins"); ++ this.p.a(this.r.getPlugins()); ++ this.p.a("map"); ++ this.p.a(this.j); ++ this.p.a("numplayers"); ++ this.p.a("" + this.r.getPlayerCount()); ++ this.p.a("maxplayers"); ++ this.p.a("" + this.h); ++ this.p.a("hostport"); ++ this.p.a("" + this.g); ++ this.p.a("hostip"); ++ this.p.a(this.m); ++ this.p.a((int) 0); ++ this.p.a((int) 1); ++ this.p.a("player_"); ++ this.p.a((int) 0); ++ String[] astring = this.r.getPlayers(); + String[] astring1 = astring; + int j = astring.length; + + for (int k = 0; k < j; ++k) { + String s = astring1[k]; + +- this.rulesResponse.writeString(s); ++ this.p.a(s); + } + +- this.rulesResponse.write((int) 0); ++ this.p.a((int) 0); ++ */ ++ // Pack plugins ++ java.util.List plugins = java.util.Collections.emptyList(); ++ org.bukkit.plugin.Plugin[] bukkitPlugins; ++ if (((DedicatedServer) this.getServer()).server.getQueryPlugins() && (bukkitPlugins = org.bukkit.Bukkit.getPluginManager().getPlugins()).length > 0) { ++ plugins = java.util.stream.Stream.of(bukkitPlugins) ++ .map(plugin -> com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation.of(plugin.getName(), plugin.getDescription().getVersion())) ++ .collect(java.util.stream.Collectors.toList()); ++ } ++ ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() ++ .motd(this.getMotd()) ++ .map(this.getWorldName()) ++ .currentPlayers(this.getServer().getPlayerCount()) ++ .maxPlayers(this.getMaxPlayers()) ++ .port(this.getServerPort()) ++ .hostname(this.getServerHost()) ++ .plugins(plugins) ++ .players(this.getServer().getPlayerNames()) ++ .gameVersion(this.getServer().getServerVersion()) ++ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) ++ .build(); ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.FULL; ++ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = ++ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, packet.getAddress(), queryResponse); ++ queryEvent.callEvent(); ++ queryResponse = queryEvent.getResponse(); ++ this.getCachedFullResponse().writeString("hostname"); ++ this.getCachedFullResponse().writeString(queryResponse.getMotd()); ++ this.getCachedFullResponse().writeString("gametype"); ++ this.getCachedFullResponse().writeString("SMP"); ++ this.getCachedFullResponse().writeString("game_id"); ++ this.getCachedFullResponse().writeString("MINECRAFT"); ++ this.getCachedFullResponse().writeString("version"); ++ this.getCachedFullResponse().writeString(queryResponse.getGameVersion()); ++ this.getCachedFullResponse().writeString("plugins"); ++ java.lang.StringBuilder pluginsString = new java.lang.StringBuilder(); ++ pluginsString.append(queryResponse.getServerVersion()); ++ if (!queryResponse.getPlugins().isEmpty()) { ++ pluginsString.append(": "); ++ java.util.Iterator iter = queryResponse.getPlugins().iterator(); ++ while (iter.hasNext()) { ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation info = iter.next(); ++ pluginsString.append(info.getName()); ++ if (info.getVersion() != null) { ++ pluginsString.append(' ').append(info.getVersion().replace(";", ",")); ++ } ++ if (iter.hasNext()) { ++ pluginsString.append(';').append(' '); ++ } ++ } ++ } ++ this.getCachedFullResponse().writeString(pluginsString.toString()); ++ this.getCachedFullResponse().writeString("map"); ++ this.getCachedFullResponse().writeString(queryResponse.getMap()); ++ this.getCachedFullResponse().writeString("numplayers"); ++ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getCurrentPlayers())); ++ this.getCachedFullResponse().writeString("maxplayers"); ++ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getMaxPlayers())); ++ this.getCachedFullResponse().writeString("hostport"); ++ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getPort())); ++ this.getCachedFullResponse().writeString("hostip"); ++ this.getCachedFullResponse().writeString(queryResponse.getHostname()); ++ // The "meaningless data" start, copied from above ++ this.getCachedFullResponse().writeInt(0); ++ this.getCachedFullResponse().writeInt(1); ++ this.getCachedFullResponse().writeString("player_"); ++ this.getCachedFullResponse().writeInt(0); ++ // "Meaningless data" end ++ queryResponse.getPlayers().forEach(this.getCachedFullResponse()::writeStringUnchecked); ++ this.getCachedFullResponse().writeInt(0); ++ // Paper end + return this.rulesResponse.toByteArray(); + } + } diff --git a/patches/server-remapped/0639-Added-PlayerLoomPatternSelectEvent.patch b/patches/server-remapped/0639-Added-PlayerLoomPatternSelectEvent.patch new file mode 100644 index 0000000000..3c2cf5afe6 --- /dev/null +++ b/patches/server-remapped/0639-Added-PlayerLoomPatternSelectEvent.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 25 Nov 2020 16:33:27 -0800 +Subject: [PATCH] Added PlayerLoomPatternSelectEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +index 3460fb2bb1451b8456a7fe42449ec4dbce641f40..0dc1b0b7181c0f93dcf6213c63baffcd4694d70c 100644 +--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +@@ -20,6 +20,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; + import org.bukkit.craftbukkit.inventory.CraftInventoryView; + import org.bukkit.entity.Player; + // CraftBukkit end ++import io.papermc.paper.event.player.PlayerLoomPatternSelectEvent; // Paper + + public class LoomMenu extends AbstractContainerMenu { + +@@ -39,7 +40,7 @@ public class LoomMenu extends AbstractContainerMenu { + } + // CraftBukkit end + private final ContainerLevelAccess access; +- private final DataSlot selectedBannerPatternIndex; ++ private final DataSlot selectedBannerPatternIndex; public final DataSlot getSelectedBannerPattern() { return this.selectedBannerPatternIndex; }; // Paper - OBFHELPER + private Runnable slotUpdateListener; + private final Slot bannerSlot; + private final Slot dyeSlot; +@@ -158,7 +159,22 @@ public class LoomMenu extends AbstractContainerMenu { + @Override + public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + if (id > 0 && id <= BannerPattern.AVAILABLE_PATTERNS) { +- this.selectedBannerPatternIndex.set(id); ++ // Paper start ++ int enumBannerPatternTypeOrdinal = id; ++ PlayerLoomPatternSelectEvent event = new PlayerLoomPatternSelectEvent((Player) player.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.block.banner.PatternType.getByIdentifier(BannerPattern.values()[id].getIdentifier())); ++ if (!event.callEvent()) { ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ return false; ++ } ++ for (BannerPattern nms : BannerPattern.values()) { ++ if (event.getPatternType().getIdentifier().equals(nms.getIdentifier())) { ++ enumBannerPatternTypeOrdinal = nms.ordinal(); ++ break; ++ } ++ } ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ this.getSelectedBannerPattern().set(enumBannerPatternTypeOrdinal); ++ // Paper end + this.setupResultSlot(); + return true; + } else { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java b/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java +index 9ea01d5888a21b0dedb555d118a4dc07af2b50fd..9ee3f8bb2294fc552735a64efbddf661d39602c7 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java +@@ -33,6 +33,7 @@ public enum BannerPattern { + this.hasPatternItem = flag; + } + ++ public String getIdentifier() { return this.getHashname(); } // Paper - OBFHELPER + public String getHashname() { + return this.hashname; + } diff --git a/patches/server-remapped/0640-Configurable-door-breaking-difficulty.patch b/patches/server-remapped/0640-Configurable-door-breaking-difficulty.patch new file mode 100644 index 0000000000..c1c84edf4d --- /dev/null +++ b/patches/server-remapped/0640-Configurable-door-breaking-difficulty.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 3 Jan 2021 22:27:43 -0800 +Subject: [PATCH] Configurable door breaking difficulty + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 23a23e2ea133ce81d3dedc4ffd17435a995497ef..7ebc85264a2cbfb601dfe5472b561cac1a7cf8bf 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -5,7 +5,10 @@ import java.util.EnumMap; + import java.util.HashMap; + import java.util.List; + import java.util.Map; +- ++import java.util.stream.Collectors; ++import net.minecraft.world.Difficulty; ++import net.minecraft.world.entity.monster.Vindicator; ++import net.minecraft.world.entity.monster.Zombie; + import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; + import org.bukkit.Bukkit; + import org.bukkit.Material; +@@ -73,6 +76,11 @@ public class PaperWorldConfig { + return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); + } + ++ private > List getEnumList(String path, List def, Class type) { ++ config.addDefault("world-settings.default." + path, def.stream().map(Enum::name).collect(Collectors.toList())); ++ return ((List) (config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)))).stream().map(s -> Enum.valueOf(type, s)).collect(Collectors.toList()); ++ } ++ + public int cactusMaxHeight; + public int reedMaxHeight; + public int bambooMaxHeight; +@@ -735,4 +743,23 @@ public class PaperWorldConfig { + private void disableMobSpawnerSpawnEggTransformation() { + disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); + } ++ ++ public List zombieBreakDoors; ++ public List vindicatorBreakDoors; ++ private void setupEntityBreakingDoors() { ++ zombieBreakDoors = getEnumList( ++ "door-breaking-difficulty.zombie", ++ Arrays.stream(Difficulty.values()) ++ .filter(Zombie.getDoorBreakingPredicate()) ++ .collect(Collectors.toList()), ++ Difficulty.class ++ ); ++ vindicatorBreakDoors = getEnumList( ++ "door-breaking-difficulty.vindicator", ++ Arrays.stream(Difficulty.values()) ++ .filter(Vindicator.getDoorBreakingPredicate()) ++ .collect(Collectors.toList()), ++ Difficulty.class ++ ); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +index 623de661f3b56062792e3a7dbc508637aa58aca5..48700094da6e97610ccc652593a9e229ba7b1003 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +@@ -48,6 +48,7 @@ import net.minecraft.world.level.ServerLevelAccessor; + + public class Vindicator extends AbstractIllager { + ++ public static final Predicate getDoorBreakingPredicate() { return DOOR_BREAKING_PREDICATE; } // Paper - OBFHELPER + private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { + return enumdifficulty == Difficulty.NORMAL || enumdifficulty == Difficulty.HARD; + }; +@@ -204,7 +205,7 @@ public class Vindicator extends AbstractIllager { + static class VindicatorBreakDoorGoal extends BreakDoorGoal { + + public VindicatorBreakDoorGoal(Mob mob) { +- super(mob, 6, Vindicator.DOOR_BREAKING_PREDICATE); ++ super(mob, 6, com.google.common.base.Predicates.in(mob.level.paperConfig.vindicatorBreakDoors)); // Paper + this.setFlags(EnumSet.of(Goal.Flag.MOVE)); + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 74fd175c4dc2d0d9832ee41efaf065b75a43f4b8..caa99a2737598bd74ede54f1c35ce4b99ce1e6d3 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -83,6 +83,7 @@ public class Zombie extends Monster { + private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT); + public static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); ++ public static final Predicate getDoorBreakingPredicate() { return DOOR_BREAKING_PREDICATE; } // Paper - OBFHELPER + private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { + return enumdifficulty == Difficulty.HARD; + }; +@@ -95,7 +96,7 @@ public class Zombie extends Monster { + + public Zombie(EntityType type, Level world) { + super(type, world); +- this.breakDoorGoal = new BreakDoorGoal(this, Zombie.DOOR_BREAKING_PREDICATE); ++ this.breakDoorGoal = new BreakDoorGoal(this, com.google.common.base.Predicates.in(world.paperConfig.zombieBreakDoors)); // Paper + } + + public Zombie(Level world) { diff --git a/patches/server-remapped/0641-Empty-commands-shall-not-be-dispatched.patch b/patches/server-remapped/0641-Empty-commands-shall-not-be-dispatched.patch new file mode 100644 index 0000000000..a9abc78c3f --- /dev/null +++ b/patches/server-remapped/0641-Empty-commands-shall-not-be-dispatched.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 6 Jan 2021 23:38:43 +0100 +Subject: [PATCH] Empty commands shall not be dispatched + + +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index c63033e3eb50423a7c32acfc0e705623cc4bec68..5ed78383ce247ceb24cda0335dbeae293958055c 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -223,6 +223,7 @@ public class Commands { + command = event.getCommand(); + + String[] args = command.split(" "); ++ if (args.length == 0) return 0; // Paper - empty commands shall not be dispatched + + String cmd = args[0]; + if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); diff --git a/patches/server-remapped/0642-Implement-API-to-expose-exact-interaction-point.patch b/patches/server-remapped/0642-Implement-API-to-expose-exact-interaction-point.patch new file mode 100644 index 0000000000..4f115620e4 --- /dev/null +++ b/patches/server-remapped/0642-Implement-API-to-expose-exact-interaction-point.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Mon, 4 Jan 2021 16:40:27 +1000 +Subject: [PATCH] Implement API to expose exact interaction point + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 6269e37f2859417a80e6de16045f1c2325f9746f..37761176861027d0ee06f50d60584687fdac669b 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -495,7 +495,7 @@ public class ServerPlayerGameMode { + cancelledBlock = true; + } + +- PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand); ++ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand, hitResult.getLocation()); // Paper + firedInteract = true; + interactResult = event.useItemInHand() == Event.Result.DENY; + 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 8829ef03d0be16d8317aaf05bcd286b74f20656a..586d21eed8189adf696ca6d3642afebbe752d1b5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -58,7 +58,9 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import net.minecraft.world.phys.Vec3; + import org.bukkit.Bukkit; ++import org.bukkit.Location; // Paper + import org.bukkit.Material; + import org.bukkit.NamespacedKey; + import org.bukkit.Server; +@@ -475,7 +477,13 @@ public class CraftEventFactory { + return callPlayerInteractEvent(who, action, position, direction, itemstack, false, hand); + } + ++ // Paper start - Add interactionPoint + public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, InteractionHand hand) { ++ return callPlayerInteractEvent(who, action, position, direction, itemstack, cancelledBlock, hand, null); ++ } ++ ++ public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, InteractionHand hand, Vec3 hitVec) { ++ // Paper end + Player player = (who == null) ? null : (Player) who.getBukkitEntity(); + CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack); + +@@ -501,7 +509,10 @@ public class CraftEventFactory { + itemInHand = null; + } + +- PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); ++ // Paper start ++ Location interactionPoint = hitVec == null ? null : new Location(craftWorld, hitVec.x, hitVec.y, hitVec.z); ++ PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND), interactionPoint); ++ // Paper end + if (cancelledBlock) { + event.setUseInteractedBlock(Event.Result.DENY); + } diff --git a/patches/server-remapped/0643-Remove-stale-POIs.patch b/patches/server-remapped/0643-Remove-stale-POIs.patch new file mode 100644 index 0000000000..561ae57f81 --- /dev/null +++ b/patches/server-remapped/0643-Remove-stale-POIs.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 9 Jan 2021 14:17:07 +0100 +Subject: [PATCH] Remove stale POIs + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index fe7b71fbb3963beafe93a5d86bebdd629c7ec8f2..9f1838d12b13d64f10871eb672ed2aec78d9936e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -2071,6 +2071,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + }); + optional1.ifPresent((villageplacetype) -> { + this.getServer().execute(() -> { ++ // Paper start ++ if (!optional.isPresent() && this.getPoiStorage().test(blockposition1, com.google.common.base.Predicates.alwaysTrue())) { ++ this.getPoiStorage().remove(blockposition1); ++ } ++ // Paper end + this.getPoiManager().add(blockposition1, villageplacetype); + DebugPackets.sendPoiAddedPacket(this, blockposition1); + }); +@@ -2078,6 +2083,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + } + ++ public final PoiManager getPoiStorage() { return this.getPoiManager(); } // Paper - OBFHELPER + public PoiManager getPoiManager() { + return this.getChunkSource().getPoiManager(); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +index b9d32e3322c2cce1aca2a90df71b6175a6f8c548..25b26a78a55f98687ed22e986b54d5e9d47a16ea 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +@@ -54,6 +54,7 @@ public class PoiManager extends SectionStorage { + ((PoiSection) this.getOrCreate(SectionPos.of(pos).asLong())).add(pos, type); + } + ++ public void remove(BlockPos blockposition) { this.remove(blockposition); } // Paper - OBFHELPER + public void remove(BlockPos pos) { + ((PoiSection) this.getOrCreate(SectionPos.of(pos).asLong())).remove(pos); + } +@@ -138,6 +139,7 @@ public class PoiManager extends SectionStorage { + return ((PoiSection) this.getOrCreate(SectionPos.of(pos).asLong())).release(pos); + } + ++ public final boolean test(BlockPos blockposition, Predicate predicate) { return this.exists(blockposition, predicate); } // Paper - OBFHELPER + public boolean exists(BlockPos pos, Predicate predicate) { + return (Boolean) this.getOrLoad(SectionPos.of(pos).asLong()).map((villageplacesection) -> { + return villageplacesection.exists(pos, predicate); diff --git a/patches/server-remapped/0644-Fix-villager-boat-exploit.patch b/patches/server-remapped/0644-Fix-villager-boat-exploit.patch new file mode 100644 index 0000000000..bc4c9d15d6 --- /dev/null +++ b/patches/server-remapped/0644-Fix-villager-boat-exploit.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Mon, 11 Jan 2021 12:43:51 -0800 +Subject: [PATCH] Fix villager boat exploit + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7e07fd0c8dec9f9cdeda65dfa0ccf42b4dde010e..9d1116f601b79dabf7a0d9e5ecf5c2a0306f9aa4 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -78,6 +78,7 @@ import net.minecraft.util.Mth; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.npc.AbstractVillager; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GameType; +@@ -617,6 +618,15 @@ public abstract class PlayerList { + + for (Iterator iterator = entity.getIndirectPassengers().iterator(); iterator.hasNext(); entity1.removed = true) { + entity1 = (Entity) iterator.next(); ++ // Paper start ++ if (entity1 instanceof AbstractVillager) { ++ final AbstractVillager villager = (AbstractVillager) entity1; ++ final net.minecraft.world.entity.player.Player human = villager.getTradingPlayer(); ++ if (human != null) { ++ villager.setTradingPlayer(null); ++ } ++ } ++ // Paper end + worldserver.despawn(entity1); + } + diff --git a/patches/server-remapped/0645-Entity-load-save-limit-per-chunk.patch b/patches/server-remapped/0645-Entity-load-save-limit-per-chunk.patch new file mode 100644 index 0000000000..a9cb53ca69 --- /dev/null +++ b/patches/server-remapped/0645-Entity-load-save-limit-per-chunk.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Wed, 18 Nov 2020 20:52:25 -0800 +Subject: [PATCH] Entity load/save limit per chunk + +Adds a config option to limit the number of entities saved and loaded +to a chunk. The default values of -1 disable the limit. Although +defaults are only included for certain entites, this allows setting +limits for any entity type. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 7ebc85264a2cbfb601dfe5472b561cac1a7cf8bf..486e5438254348db68017228af131cba7defd637 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -7,6 +7,7 @@ import java.util.List; + import java.util.Map; + import java.util.stream.Collectors; + import net.minecraft.world.Difficulty; ++import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.monster.Vindicator; + import net.minecraft.world.entity.monster.Zombie; + import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; +@@ -762,4 +763,18 @@ public class PaperWorldConfig { + Difficulty.class + ); + } ++ ++ public Map, Integer> entityPerChunkSaveLimits = new HashMap<>(); ++ private void entityPerChunkSaveLimits() { ++ getInt("entity-per-chunk-save-limit.experience_orb", -1); ++ getInt("entity-per-chunk-save-limit.snowball", -1); ++ getInt("entity-per-chunk-save-limit.ender_pearl", -1); ++ getInt("entity-per-chunk-save-limit.arrow", -1); ++ EntityType.getEntityNameList().forEach(name -> { ++ final EntityType type = EntityType.getByName(name.getPath()).orElseThrow(() -> new IllegalStateException("Unknown Entity Type: " + name.toString())); ++ final String path = ".entity-per-chunk-save-limit." + name.getPath(); ++ final int value = config.getInt("world-settings." + worldName + path, config.getInt("world-settings.default" + path, -1)); // get without setting defaults ++ if (value != -1) entityPerChunkSaveLimits.put(type, value); ++ }); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index f6a814f9305813eaafa56baa0327e0111cd4e38c..30f80f8549c3236d6bfe594e323e4ca6e702005d 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -539,11 +539,22 @@ public class ChunkSerializer { + + chunk.setLastSaveHadEntities(false); + ++ // Paper start ++ final Map, Integer> savedEntityCounts = Maps.newHashMap(); + for (int j = 0; j < chunk.getEntitySlices().length; ++j) { + Iterator iterator1 = chunk.getEntitySlices()[j].iterator(); + + while (iterator1.hasNext()) { + Entity entity = (Entity) iterator1.next(); ++ final EntityType entityType = entity.getType(); ++ final int saveLimit = worldserver.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ continue; ++ } ++ savedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end + CompoundTag nbttagcompound4 = new CompoundTag(); + // Paper start + if (asyncsavedata == null && !entity.removed && (int) Math.floor(entity.getX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk.getPos().z) { +@@ -674,10 +685,21 @@ public class ChunkSerializer { + ListTag nbttaglist = tag.getList("Entities", 10); + Level world = chunk.getLevel(); + ++ // Paper start ++ final Map, Integer> loadedEntityCounts = Maps.newHashMap(); + for (int i = 0; i < nbttaglist.size(); ++i) { + CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); + + EntityType.loadEntityRecursive(nbttagcompound1, world, (entity) -> { ++ final EntityType entityType = entity.getType(); ++ final int saveLimit = world.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ return null; ++ } ++ loadedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end + chunk.addEntity(entity); + return entity; + }); diff --git a/patches/server-remapped/0646-Add-sendOpLevel-API.patch b/patches/server-remapped/0646-Add-sendOpLevel-API.patch new file mode 100644 index 0000000000..82ff3e57c1 --- /dev/null +++ b/patches/server-remapped/0646-Add-sendOpLevel-API.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Tue, 29 Dec 2020 15:03:03 +0100 +Subject: [PATCH] Add sendOpLevel API + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 9d1116f601b79dabf7a0d9e5ecf5c2a0306f9aa4..c962b6fc0c65dc5e2ea636220727bca63bf4b740 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1134,22 +1134,29 @@ public abstract class PlayerList { + } + + private void sendPlayerPermissionLevel(ServerPlayer player, int permissionLevel) { +- if (player.connection != null) { ++ // Paper start - add recalculatePermissions parameter ++ this.sendPlayerOperatorStatus(player, permissionLevel, true); ++ } ++ public void sendPlayerOperatorStatus(ServerPlayer entityplayer, int i, boolean recalculatePermissions) { ++ // Paper end ++ if (entityplayer.connection != null) { + byte b0; + +- if (permissionLevel <= 0) { ++ if (i <= 0) { + b0 = 24; +- } else if (permissionLevel >= 4) { ++ } else if (i >= 4) { + b0 = 28; + } else { +- b0 = (byte) (24 + permissionLevel); ++ b0 = (byte) (24 + i); + } + +- player.connection.send(new ClientboundEntityEventPacket(player, b0)); ++ entityplayer.connection.send(new ClientboundEntityEventPacket(entityplayer, b0)); + } + +- player.getBukkitEntity().recalculatePermissions(); // CraftBukkit +- this.server.getCommands().sendCommands(player); ++ if (recalculatePermissions) { // Paper ++ entityplayer.getBukkitEntity().recalculatePermissions(); // CraftBukkit ++ this.server.getCommands().sendCommands(entityplayer); ++ } // Paper + } + + // Paper start +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 40380fff222cc1f3340cf6a6c4afbe60aaa5d3a6..d2d179cdef8129653983b01d94928ba83f64f644 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2296,6 +2296,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + ? (org.bukkit.entity.Firework) entity.getBukkitEntity() + : null; + } ++ ++ @Override ++ public void sendOpLevel(byte level) { ++ Preconditions.checkArgument(level >= 0 && level <= 4, "Level must be within [0, 4]"); ++ ++ this.getHandle().getServer().getPlayerList().sendPlayerOperatorStatus(this.getHandle(), level, false); ++ } + // Paper end + + // Spigot start diff --git a/patches/server-remapped/0647-Add-StructureLocateEvent.patch b/patches/server-remapped/0647-Add-StructureLocateEvent.patch new file mode 100644 index 0000000000..6aaa2cdea9 --- /dev/null +++ b/patches/server-remapped/0647-Add-StructureLocateEvent.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: dfsek +Date: Wed, 16 Sep 2020 01:12:29 -0700 +Subject: [PATCH] Add StructureLocateEvent + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +index 860af116dbc7dd9d691ff27d28a2d10dbec83df4..29310d96eb562ead1e568a97b6f3019e43ca0a88 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.chunk; + + import com.google.common.collect.Lists; + import com.mojang.serialization.Codec; ++import io.papermc.paper.event.world.StructureLocateEvent; // Paper - Add import due to naming conflict. + import java.util.BitSet; + import java.util.Iterator; + import java.util.List; +@@ -160,6 +161,22 @@ public abstract class ChunkGenerator { + + @Nullable + public BlockPos findNearestMapFeature(ServerLevel world, StructureFeature feature, BlockPos center, int radius, boolean skipExistingChunks) { ++ // Paper start ++ org.bukkit.World world1 = world.getWorld(); ++ org.bukkit.Location originLocation = new org.bukkit.Location(world1, center.getX(), center.getY(), center.getZ()); ++ StructureLocateEvent event = new StructureLocateEvent(world1, originLocation, org.bukkit.StructureType.getStructureTypes().get(feature.getFeatureName()), radius, skipExistingChunks); ++ if(!event.callEvent()) return null; ++ // If event call set a final location, skip structure finding and just return set result. ++ if(event.getResult() != null) return new BlockPos(event.getResult().getBlockX(), event.getResult().getBlockY(), event.getResult().getBlockZ()); ++ // Get origin location (re)defined by event call. ++ center = new BlockPos(event.getOrigin().getBlockX(), event.getOrigin().getBlockY(), event.getOrigin().getBlockZ()); ++ // Get world (re)defined by event call. ++ world = ((org.bukkit.craftbukkit.CraftWorld) event.getOrigin().getWorld()).getHandle(); ++ // Get radius and whether to find unexplored structures (re)defined by event call. ++ radius = event.getRadius(); ++ skipExistingChunks = event.shouldFindUnexplored(); ++ feature = StructureFeature.STRUCTURES_REGISTRY.get(event.getType().getName()); ++ // Paper end + if (!this.biomeSource.canGenerateStructure(feature)) { + return null; + } else if (feature == StructureFeature.STRONGHOLD) { diff --git a/patches/server-remapped/0648-Collision-option-for-requiring-a-player-participant.patch b/patches/server-remapped/0648-Collision-option-for-requiring-a-player-participant.patch new file mode 100644 index 0000000000..33e77f9b2e --- /dev/null +++ b/patches/server-remapped/0648-Collision-option-for-requiring-a-player-participant.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 14 Nov 2020 16:48:37 +0100 +Subject: [PATCH] Collision option for requiring a player participant + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 486e5438254348db68017228af131cba7defd637..3dd228ae8071a747f2cd7b2b46a2215183f72cd0 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -717,6 +717,18 @@ public class PaperWorldConfig { + } + } + ++ public boolean onlyPlayersCollide = false; ++ public boolean allowVehicleCollisions = true; ++ private void onlyPlayersCollide() { ++ onlyPlayersCollide = getBoolean("only-players-collide", onlyPlayersCollide); ++ allowVehicleCollisions = getBoolean("allow-vehicle-collisions", allowVehicleCollisions); ++ if (onlyPlayersCollide && !allowVehicleCollisions) { ++ log("Collisions will only work if a player is one of the two entities colliding."); ++ } else if (onlyPlayersCollide) { ++ log("Collisions will only work if a player OR a vehicle is one of the two entities colliding."); ++ } ++ } ++ + public int wanderingTraderSpawnMinuteTicks = 1200; + public int wanderingTraderSpawnDayTicks = 24000; + public int wanderingTraderSpawnChanceFailureIncrement = 25; +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index ec98f5f59ca2b4cb58eb00ed8cdfa364f8bacd88..87c719caf796f54296ff7e412548062e02af270e 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1465,6 +1465,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public void push(Entity entity) { + if (!this.isPassengerOfSameVehicle(entity)) { + if (!entity.noPhysics && !this.noPhysics) { ++ if (this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer || this instanceof ServerPlayer)) return; // Paper + double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); + double d2 = Mth.absMax(d0, d1); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 9cbde70787d8044f0edeb3d459231dd7fbb79584..25df3ef6b96bec39847a732394af8eccdb4d5d45 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -21,6 +21,7 @@ import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.Tag; + import net.minecraft.util.Mth; +@@ -766,6 +767,7 @@ public abstract class AbstractMinecart extends Entity { + public void push(Entity entity) { + if (!this.level.isClientSide) { + if (!entity.noPhysics && !this.noPhysics) { ++ if (!this.level.paperConfig.allowVehicleCollisions && this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer)) return; // Paper + if (!this.hasPassenger(entity)) { + // CraftBukkit start + VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +index 6a9c18540886979b2212bf7917a21753c9a9db3c..e7ac3bff190c899397d6576fabbf4966878ea7e5 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +@@ -14,6 +14,7 @@ import net.minecraft.network.protocol.game.ServerboundPaddleBoatPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.FluidTags; +@@ -229,6 +230,7 @@ public class Boat extends Entity { + + @Override + public void push(Entity entity) { ++ if (!this.level.paperConfig.allowVehicleCollisions && this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer)) return; // Paper + if (entity instanceof Boat) { + if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { + // CraftBukkit start diff --git a/patches/server-remapped/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/patches/server-remapped/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch new file mode 100644 index 0000000000..ed43990f0e --- /dev/null +++ b/patches/server-remapped/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 16 Jan 2021 14:30:12 -0500 +Subject: [PATCH] Remove ProjectileHitEvent call when fireballs dead + +The duplicate ProjectileHitEvent in EntityFireball was removed. The +event was always called before the duplicate call. + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +index 872ff430547276e2a41a48aa07ae63b87ab39e5d..cba1b361162456cf297d88439f76586a2f61fc45 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +@@ -86,7 +86,7 @@ public abstract class AbstractHurtingProjectile extends Projectile { + + // CraftBukkit start - Fire ProjectileHitEvent + if (this.removed) { +- CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ // CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); // Paper - this is an undesired duplicate event + } + // CraftBukkit end + } diff --git a/patches/server-remapped/0650-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/server-remapped/0650-Return-chat-component-with-empty-text-instead-of-thr.patch new file mode 100644 index 0000000000..8f0e61039a --- /dev/null +++ b/patches/server-remapped/0650-Return-chat-component-with-empty-text-instead-of-thr.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: CDFN +Date: Tue, 7 Jul 2020 17:53:23 +0200 +Subject: [PATCH] Return chat component with empty text instead of throwing + exception + + +diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index b5d79635cd8b0eb6b17962450b347010aeb52654..d2f762371f82d54bcec8b1a0a02d0866e55fd174 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -12,6 +12,7 @@ import net.minecraft.ReportedException; + import net.minecraft.core.NonNullList; + import net.minecraft.core.Registry; + import net.minecraft.network.chat.Component; ++import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; +@@ -60,7 +61,12 @@ public abstract class AbstractContainerMenu { + } + private Component title; + public final Component getTitle() { +- Preconditions.checkState(this.title != null, "Title not set"); ++ // Paper start - return chat component with empty text instead of throwing error ++ // Preconditions.checkState(this.title != null, "Title not set"); ++ if(this.title == null){ ++ return new TextComponent(""); ++ } ++ // Paper end + return this.title; + } + public final void setTitle(Component title) { diff --git a/patches/server-remapped/0651-Make-schedule-command-per-world.patch b/patches/server-remapped/0651-Make-schedule-command-per-world.patch new file mode 100644 index 0000000000..24fcb77734 --- /dev/null +++ b/patches/server-remapped/0651-Make-schedule-command-per-world.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 4 Jan 2021 19:52:44 -0800 +Subject: [PATCH] Make schedule command per-world + + +diff --git a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java +index 122a790285734ecd95fe6817043a84cf1752dbe8..173ab97b01b2191d9d731a28f2690eb4f539880b 100644 +--- a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java ++++ b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java +@@ -32,7 +32,7 @@ public class ScheduleCommand { + return new TranslatableComponent("commands.schedule.cleared.failure", new Object[]{object}); + }); + private static final SuggestionProvider SUGGEST_SCHEDULE = (commandcontext, suggestionsbuilder) -> { +- return SharedSuggestionProvider.suggest((Iterable) ((CommandSourceStack) commandcontext.getSource()).getServer().getWorldData().overworldData().getScheduledEvents().getEventsIds(), suggestionsbuilder); ++ return SharedSuggestionProvider.suggest((Iterable) ((CommandSourceStack) commandcontext.getSource()).getLevel().worldDataServer.overworldData().getScheduledEvents().getEventsIds(), suggestionsbuilder); // Paper + }; + + public static void register(CommandDispatcher dispatcher) { +@@ -55,7 +55,7 @@ public class ScheduleCommand { + } else { + long j = source.getLevel().getGameTime() + (long) i; + ResourceLocation minecraftkey = (ResourceLocation) pair.getFirst(); +- TimerQueue customfunctioncallbacktimerqueue = source.getServer().getWorldData().overworldData().getScheduledEvents(); ++ TimerQueue customfunctioncallbacktimerqueue = source.getLevel().worldDataServer.overworldData().getScheduledEvents(); // Paper + + ((Either) pair.getSecond()).ifLeft((customfunction) -> { + String s = minecraftkey.toString(); +@@ -81,7 +81,7 @@ public class ScheduleCommand { + } + + private static int remove(CommandSourceStack commandlistenerwrapper, String s) throws CommandSyntaxException { +- int i = commandlistenerwrapper.getServer().getWorldData().overworldData().getScheduledEvents().remove(s); ++ int i = commandlistenerwrapper.getLevel().worldDataServer.overworldData().getScheduledEvents().remove(s); // Paper + + if (i == 0) { + throw ScheduleCommand.ERROR_CANT_REMOVE.create(s); diff --git a/patches/server-remapped/0652-Configurable-max-leash-distance.patch b/patches/server-remapped/0652-Configurable-max-leash-distance.patch new file mode 100644 index 0000000000..42d46d7655 --- /dev/null +++ b/patches/server-remapped/0652-Configurable-max-leash-distance.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 3 Jan 2021 21:04:03 -0800 +Subject: [PATCH] Configurable max leash distance + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3dd228ae8071a747f2cd7b2b46a2215183f72cd0..c4ca7ed5b251a2a3d64297351ef32541a4243c35 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -166,6 +166,12 @@ public class PaperWorldConfig { + } + } + ++ public float maxLeashDistance = 10f; ++ private void maxLeashDistance() { ++ maxLeashDistance = getFloat("max-leash-distance", maxLeashDistance); ++ log("Max leash distance: " + maxLeashDistance); ++ } ++ + public boolean disableEndCredits; + private void disableEndCredits() { + disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +index 7c82d453388a27b69207d051dec316fc14715e2b..a884940cc576704951d42c6b0d00f5a319297c29 100644 +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -46,7 +46,7 @@ public abstract class PathfinderMob extends Mob { + float f = this.distanceTo(entity); + + if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) { +- if (f > 10.0F) { ++ if (f > entity.level.paperConfig.maxLeashDistance) { // Paper + this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + } +@@ -55,7 +55,7 @@ public abstract class PathfinderMob extends Mob { + } + + this.onLeashDistance(f); +- if (f > 10.0F) { ++ if (f > entity.level.paperConfig.maxLeashDistance) { // Paper + this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + this.goalSelector.disableControlFlag(Goal.Flag.MOVE); diff --git a/patches/server-remapped/0653-Implement-BlockPreDispenseEvent.patch b/patches/server-remapped/0653-Implement-BlockPreDispenseEvent.patch new file mode 100644 index 0000000000..fea75084e5 --- /dev/null +++ b/patches/server-remapped/0653-Implement-BlockPreDispenseEvent.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Sun, 17 Jan 2021 13:16:09 +1000 +Subject: [PATCH] Implement BlockPreDispenseEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +index 2a4cb76bdfcf55ba222b4976359c1b8efb165009..08ce586f8d024b57a20031868ca2a3058bc500ee 100644 +--- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +@@ -88,6 +88,7 @@ public class DispenserBlock extends BaseEntityBlock { + DispenseItemBehavior idispensebehavior = this.getDispenseMethod(itemstack); + + if (idispensebehavior != DispenseItemBehavior.NOOP) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(worldserver, pos, itemstack, i)) return; // Paper - BlockPreDispenseEvent is called here + eventFired = false; // CraftBukkit - reset event status + tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 586d21eed8189adf696ca6d3642afebbe752d1b5..34c0216baa69206aca51821aec421484b18cb04c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -59,6 +59,7 @@ import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import io.papermc.paper.event.block.BlockPreDispenseEvent; // Paper + import org.bukkit.Bukkit; + import org.bukkit.Location; // Paper + import org.bukkit.Material; +@@ -1802,5 +1803,11 @@ public class CraftEventFactory { + BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); + return event.callEvent(); + } ++ ++ public static boolean handleBlockPreDispenseEvent(ServerLevel worldserver, BlockPos blockposition, ItemStack itemStack, int slot) { ++ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ BlockPreDispenseEvent event = new BlockPreDispenseEvent(block, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), slot); ++ return event.callEvent(); ++ } + // Paper end + } diff --git a/patches/server-remapped/0654-Added-Vanilla-Entity-Tags.patch b/patches/server-remapped/0654-Added-Vanilla-Entity-Tags.patch new file mode 100644 index 0000000000..fcf1ba26d8 --- /dev/null +++ b/patches/server-remapped/0654-Added-Vanilla-Entity-Tags.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 3 Jan 2021 20:03:35 -0800 +Subject: [PATCH] Added Vanilla Entity Tags + + +diff --git a/src/main/java/io/papermc/paper/CraftEntityTag.java b/src/main/java/io/papermc/paper/CraftEntityTag.java +new file mode 100644 +index 0000000000000000000000000000000000000000..687edf189871fc989174248dbf070bcba161f1a8 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/CraftEntityTag.java +@@ -0,0 +1,28 @@ ++package io.papermc.paper; ++ ++import org.bukkit.craftbukkit.tag.CraftTag; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.entity.EntityType; ++ ++import java.util.Collections; ++import java.util.Set; ++import java.util.stream.Collectors; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.tags.TagCollection; ++ ++public class CraftEntityTag extends CraftTag, EntityType> { ++ ++ public CraftEntityTag(TagCollection> registry, ResourceLocation tag) { ++ super(registry, tag); ++ } ++ ++ @Override ++ public boolean isTagged(EntityType item) { ++ return getHandle().isTagged(CraftMagicNumbers.getEntityTypes(item)); ++ } ++ ++ @Override ++ public Set getValues() { ++ return Collections.unmodifiableSet(getHandle().getTagged().stream().map(CraftMagicNumbers::getEntityType).collect(Collectors.toSet())); ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 046fbc646d2818bb2c7e08ff22093523e8246523..3d7cc98710bb925743e6fe8de1f154096334d46c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2221,6 +2221,11 @@ public final class CraftServer implements Server { + Preconditions.checkArgument(clazz == org.bukkit.Fluid.class, "Fluid namespace must have fluid type"); + + return (org.bukkit.Tag) new CraftFluidTag(console.getTags().getFluids(), key); ++ // Paper start ++ case org.bukkit.Tag.REGISTRY_ENTITIES: ++ Preconditions.checkArgument(clazz == org.bukkit.entity.EntityType.class, "Entity namespace must have entitytype type"); ++ return (org.bukkit.Tag) new io.papermc.paper.CraftEntityTag(console.getTags().getEntityTypes(), key); ++ // Paper end + default: + throw new IllegalArgumentException(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index ac94fd569bd4c79e30adef148e09e395ba8c1812..25a29d997f163ce2b11330d66a691601f514a9cb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -116,8 +116,17 @@ public final class CraftMagicNumbers implements UnsafeValues { + private static final Map MATERIAL_ITEM = new HashMap<>(); + private static final Map MATERIAL_BLOCK = new HashMap<>(); + private static final Map MATERIAL_FLUID = new HashMap<>(); ++ // Paper start ++ private static final Map> ENTITY_TYPE_ENTITY_TYPES = new HashMap<>(); ++ private static final Map, org.bukkit.entity.EntityType> ENTITY_TYPES_ENTITY_TYPE = new HashMap<>(); + + static { ++ for (org.bukkit.entity.EntityType type : org.bukkit.entity.EntityType.values()) { ++ if (type == org.bukkit.entity.EntityType.UNKNOWN) continue; ++ ENTITY_TYPE_ENTITY_TYPES.put(type, net.minecraft.core.Registry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey()))); ++ ENTITY_TYPES_ENTITY_TYPE.put(net.minecraft.core.Registry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey())), type); ++ } ++ // Paper end + for (Block block : net.minecraft.core.Registry.BLOCK) { + BLOCK_MATERIAL.put(block, Material.getMaterial(net.minecraft.core.Registry.BLOCK.getKey(block).getPath().toUpperCase(Locale.ROOT))); + } +@@ -183,6 +192,14 @@ public final class CraftMagicNumbers implements UnsafeValues { + public static ResourceLocation key(Material mat) { + return CraftNamespacedKey.toMinecraft(mat.getKey()); + } ++ // Paper start ++ public static net.minecraft.world.entity.EntityType getEntityTypes(org.bukkit.entity.EntityType type) { ++ return ENTITY_TYPE_ENTITY_TYPES.get(type); ++ } ++ public static org.bukkit.entity.EntityType getEntityType(net.minecraft.world.entity.EntityType entityTypes) { ++ return ENTITY_TYPES_ENTITY_TYPE.get(entityTypes); ++ } ++ // Paper end + // ======================================================================== + // Paper start + @Override diff --git a/patches/server-remapped/0655-added-Wither-API.patch b/patches/server-remapped/0655-added-Wither-API.patch new file mode 100644 index 0000000000..175023cea0 --- /dev/null +++ b/patches/server-remapped/0655-added-Wither-API.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 5 Jul 2020 15:39:19 -0700 +Subject: [PATCH] added Wither API + + +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +index 1f330d852eb9b3a36570542e10a88ae065798714..fd91c80cd6337b5fa41d6060ecdb44b8fa68a16a 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -80,6 +80,11 @@ public class WitherBoss extends Monster implements RangedAttackMob { + return entityliving.getMobType() != MobType.UNDEAD && entityliving.attackable(); + }; + private static final TargetingConditions TARGETING_CONDITIONS = (new TargetingConditions()).range(20.0D).selector(WitherBoss.LIVING_ENTITY_SELECTOR); ++ // Paper start ++ private boolean canPortal = false; ++ ++ public void setCanTravelThroughPortals(boolean canPortal) { this.canPortal = canPortal; } ++ // Paper end + + public WitherBoss(EntityType type, Level world) { + super(type, world); +@@ -578,6 +583,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { + this.entityData.set((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(headIndex), id); + } + ++ public final boolean isPowered() { return this.isPowered(); } // Paper - OBFHELPER + public boolean isPowered() { + return this.getHealth() <= this.getMaxHealth() / 2.0F; + } +@@ -594,7 +600,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { + + @Override + public boolean canChangeDimensions() { +- return false; ++ return super.canChangeDimensions() && canPortal; // Paper + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +index fdcd680b972da54f9cdb41dff5563e42bd12d8e3..a09f46c586416b77dda40067fe1639a9250af3f0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +@@ -38,4 +38,31 @@ public class CraftWither extends CraftMonster implements Wither, com.destroystok + public BossBar getBossBar() { + return bossBar; + } ++ ++ // Paper start ++ @Override ++ public boolean isCharged() { ++ return getHandle().isPowered(); ++ } ++ ++ @Override ++ public int getInvulnerableTicks() { ++ return getHandle().getInvulnerableTicks(); ++ } ++ ++ @Override ++ public void setInvulnerableTicks(int ticks) { ++ getHandle().setInvulnerableTicks(ticks); ++ } ++ ++ @Override ++ public boolean canTravelThroughPortals() { ++ return getHandle().canChangeDimensions(); ++ } ++ ++ @Override ++ public void setCanTravelThroughPortals(boolean value) { ++ getHandle().setCanTravelThroughPortals(value); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/patches/server-remapped/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch new file mode 100644 index 0000000000..e2d21ff095 --- /dev/null +++ b/patches/server-remapped/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 24 Jun 2020 15:14:51 -0600 +Subject: [PATCH] Added firing of PlayerChangeBeaconEffectEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java +index 1371bfe4a4b5bb065de4d2118b2b32f4ee0b78d9..20069eeece4e03827ed4b3b4e2b713c43b23a366 100644 +--- a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java +@@ -11,6 +11,10 @@ import net.minecraft.world.level.block.Blocks; + import org.bukkit.craftbukkit.inventory.CraftInventoryView; + // CraftBukkit end + ++// Paper start ++import io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent; ++// Paper end ++ + public class BeaconMenu extends AbstractContainerMenu { + + private final Container beacon; +@@ -137,9 +141,15 @@ public class BeaconMenu extends AbstractContainerMenu { + + public void updateEffects(int primaryEffectId, int secondaryEffectId) { + if (this.paymentSlot.hasItem()) { +- this.beaconData.set(1, primaryEffectId); +- this.beaconData.set(2, secondaryEffectId); ++ // Paper start ++ PlayerChangeBeaconEffectEvent event = new PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), org.bukkit.potion.PotionEffectType.getById(primaryEffectId), org.bukkit.potion.PotionEffectType.getById(secondaryEffectId), this.access.getLocation().getBlock()); ++ if (event.callEvent()) { ++ this.beaconData.set(1, event.getPrimary() == null ? 0 : event.getPrimary().getId()); ++ this.beaconData.set(2, event.getSecondary() == null ? 0 : event.getSecondary().getId()); ++ if (!event.willConsumeItem()) return; + this.paymentSlot.a(1); ++ } ++ // Paper end + } + + } diff --git a/patches/server-remapped/0657-Fix-console-spam-when-removing-chests-in-water.patch b/patches/server-remapped/0657-Fix-console-spam-when-removing-chests-in-water.patch new file mode 100644 index 0000000000..239c089fb6 --- /dev/null +++ b/patches/server-remapped/0657-Fix-console-spam-when-removing-chests-in-water.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Thu, 19 Nov 2020 02:07:10 +0000 +Subject: [PATCH] Fix console spam when removing chests in water + + +diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +index 6b95cd2e2af66eef324dfcc8f7642da2f9e39d4e..d061548b5490f441b91a2dd90e7668a05f7f2112 100644 +--- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +@@ -239,7 +239,7 @@ public class ChestBlock extends AbstractChestBlock implements + @Override + public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) { + if (!state.is(newState.getBlock())) { +- BlockEntity tileentity = world.getBlockEntity(pos); ++ BlockEntity tileentity = world.getTileEntity(pos, false); // Paper - Don't validate TE - Fix console spam when removing chests in water + + if (tileentity instanceof Container) { + Containers.dropContents(world, pos, (Container) tileentity); diff --git a/patches/server-remapped/0658-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server-remapped/0658-Add-toggle-for-always-placing-the-dragon-egg.patch new file mode 100644 index 0000000000..2dafd06172 --- /dev/null +++ b/patches/server-remapped/0658-Add-toggle-for-always-placing-the-dragon-egg.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 26 Nov 2020 11:47:24 +0000 +Subject: [PATCH] Add toggle for always placing the dragon egg + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index c4ca7ed5b251a2a3d64297351ef32541a4243c35..40939de88b1a8169dbfc7a0cd288c2fe9b706426 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -795,4 +795,9 @@ public class PaperWorldConfig { + if (value != -1) entityPerChunkSaveLimits.put(type, value); + }); + } ++ ++ public boolean enderDragonsDeathAlwaysPlacesDragonEgg = false; ++ private void enderDragonsDeathAlwaysPlacesDragonEgg() { ++ enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 84447e9845edad2d228b94184b35b4afb453a14b..e2f784b771b12bd646d519938c33b1c86cc2686d 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -396,7 +396,7 @@ public class EndDragonFight { + this.dragonEvent.setVisible(false); + this.spawnExitPortal(true); + this.spawnNewGateway(); +- if (!this.previouslyKilled) { ++ if (this.level.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg + this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.END_PODIUM_LOCATION), Blocks.DRAGON_EGG.defaultBlockState()); + } + diff --git a/patches/server-remapped/0659-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server-remapped/0659-Added-PlayerStonecutterRecipeSelectEvent.patch new file mode 100644 index 0000000000..aab6a1ebc8 --- /dev/null +++ b/patches/server-remapped/0659-Added-PlayerStonecutterRecipeSelectEvent.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 27 Nov 2020 17:14:27 -0800 +Subject: [PATCH] Added PlayerStonecutterRecipeSelectEvent + +Co-Authored-By: MiniDigger + +diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index d2f762371f82d54bcec8b1a0a02d0866e55fd174..b5eeb2749237d589eafdfbea073bfe90e609600b 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -117,7 +117,7 @@ public abstract class AbstractContainerMenu { + return slot; + } + +- protected DataSlot addDataSlot(DataSlot containerproperty) { ++ protected DataSlot addDataSlot(DataSlot containerproperty) { return addDataSlot(containerproperty); } protected DataSlot addDataSlot(DataSlot containerproperty) { // Paper - OBFHELPER + this.dataSlots.add(containerproperty); + return containerproperty; + } +diff --git a/src/main/java/net/minecraft/world/inventory/DataSlot.java b/src/main/java/net/minecraft/world/inventory/DataSlot.java +index 56d99e39f8cfe46a780bd17a0f99c3cbbe01c719..e851d6c8e5ad58091a58d489a48cd3ec379ce0da 100644 +--- a/src/main/java/net/minecraft/world/inventory/DataSlot.java ++++ b/src/main/java/net/minecraft/world/inventory/DataSlot.java +@@ -20,7 +20,7 @@ public abstract class DataSlot { + }; + } + +- public static DataSlot shared(final int[] array, final int index) { ++ public static DataSlot shared(final int[] aint, final int i) { return shared(aint, i); } public static DataSlot shared(final int[] array, final int index) { // Paper - OBFHELPER + return new DataSlot() { + @Override + public int get() { +@@ -54,7 +54,7 @@ public abstract class DataSlot { + + public abstract void set(int value); + +- public boolean checkAndClearUpdateFlag() { ++ public boolean checkAndClearUpdateFlag() { return checkAndClearUpdateFlag(); } public boolean checkAndClearUpdateFlag() { // Paper - OBFHELPER + int i = this.get(); + boolean flag = i != this.prevValue; + +diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +index 072bac443e7c54ac2b92e1d93b757bdacf230fbb..beb02f953719170d1668ada1c09d073d84bb7baf 100644 +--- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +@@ -21,13 +21,14 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; + import org.bukkit.craftbukkit.inventory.CraftInventoryView; + import org.bukkit.entity.Player; + // CraftBukkit end ++import io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent; // Paper + + public class StonecutterMenu extends AbstractContainerMenu { + + private final ContainerLevelAccess access; + private final DataSlot selectedRecipeIndex; + private final Level level; +- private List recipes; ++ private List recipes; public final List getRecipes() { return this.recipes; } // Paper - OBFHELPER + private ItemStack input; + private long lastSoundTime; + final Slot inputSlot; +@@ -57,7 +58,7 @@ public class StonecutterMenu extends AbstractContainerMenu { + + public StonecutterMenu(int syncId, Inventory playerInventory, final ContainerLevelAccess context) { + super(MenuType.STONECUTTER, syncId); +- this.selectedRecipeIndex = DataSlot.standalone(); ++ this.selectedRecipeIndex = addDataSlot(DataSlot.shared(new int[1], 0)); // Paper - allow replication + this.recipes = Lists.newArrayList(); + this.input = ItemStack.EMPTY; + this.slotUpdateListener = () -> { +@@ -135,13 +136,36 @@ public class StonecutterMenu extends AbstractContainerMenu { + @Override + public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + if (this.isValidRecipeIndex(id)) { +- this.selectedRecipeIndex.set(id); ++ // Paper start ++ int recipeIndex = id; ++ this.selectedRecipeIndex.set(recipeIndex); ++ this.selectedRecipeIndex.checkAndClearUpdateFlag(); // mark as changed ++ if (this.isValidRecipeIndex(id)) { ++ PlayerStonecutterRecipeSelectEvent event = new PlayerStonecutterRecipeSelectEvent((Player) player.getBukkitEntity(), (org.bukkit.inventory.StonecutterInventory) getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) this.getRecipes().get(id).toBukkitRecipe()); ++ if (!event.callEvent()) { ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ return false; ++ } ++ int newRecipeIndex; ++ if (!this.getRecipes().get(recipeIndex).getId().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { // If the recipe did NOT stay the same ++ for (newRecipeIndex = 0; newRecipeIndex < this.getRecipes().size(); newRecipeIndex++) { ++ if (this.getRecipes().get(newRecipeIndex).getId().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { ++ recipeIndex = newRecipeIndex; ++ break; ++ } ++ } ++ } ++ } ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ this.selectedRecipeIndex.set(recipeIndex); // set new index, so that listeners can read it ++ // Paper end + this.setupResultSlot(); + } + + return true; + } + ++ private boolean isValidRecipeIndex(int index) { return this.isValidRecipeIndex(index); } // Paper - OBFHELPER + private boolean isValidRecipeIndex(int i) { + return i >= 0 && i < this.recipes.size(); + } diff --git a/patches/server-remapped/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/server-remapped/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch new file mode 100644 index 0000000000..33a094ba1f --- /dev/null +++ b/patches/server-remapped/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch @@ -0,0 +1,156 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Fri, 29 Jan 2021 15:13:11 +0100 +Subject: [PATCH] Add dropLeash variable to EntityUnleashEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 87dd6c012bf1ca6a1e8df44dc0957c4c67d02adc..ea34306858116e5626383af408529091836c2752 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -86,6 +86,7 @@ import org.bukkit.event.entity.EntityTargetEvent; + import org.bukkit.event.entity.EntityTransformEvent; + import org.bukkit.event.entity.EntityUnleashEvent; + import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; ++import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper + // CraftBukkit end + + public abstract class Mob extends LivingEntity { +@@ -1205,12 +1206,15 @@ public abstract class Mob extends LivingEntity { + return InteractionResult.PASS; + } else if (this.getLeashHolder() == player) { + // CraftBukkit start - fire PlayerUnleashEntityEvent +- if (CraftEventFactory.callPlayerUnleashEntityEvent(this, player).isCancelled()) { ++ // Paper start - drop leash variable ++ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, player, !player.abilities.instabuild); ++ if (event.isCancelled()) { ++ // Paper end + ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); + return InteractionResult.PASS; + } + // CraftBukkit end +- this.dropLeash(true, !player.abilities.instabuild); ++ this.dropLeash(true, event.isDropLeash()); // Paper - drop leash variable + return InteractionResult.sidedSuccess(this.level.isClientSide); + } else { + InteractionResult enuminteractionresult = this.checkAndHandleImportantInteractions(player, hand); +@@ -1364,8 +1368,11 @@ public abstract class Mob extends LivingEntity { + + if (this.leashHolder != null) { + if (!this.isAlive() || !this.leashHolder.isAlive()) { +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit +- this.dropLeash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE, true); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + } + + } +@@ -1433,8 +1440,11 @@ public abstract class Mob extends LivingEntity { + boolean flag1 = super.startRiding(entity, force); + + if (flag1 && this.isLeashed()) { +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit +- this.dropLeash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, true); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + } + + return flag1; +@@ -1636,7 +1646,10 @@ public abstract class Mob extends LivingEntity { + @Override + protected void removeAfterChangingDimensions() { + super.removeAfterChangingDimensions(); +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit +- this.dropLeash(true, false); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, false); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +index a884940cc576704951d42c6b0d00f5a319297c29..d16a7bab5495d58ea9e6811d4b507667cfa3d264 100644 +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -47,8 +47,11 @@ public abstract class PathfinderMob extends Mob { + + if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) { + if (f > entity.level.paperConfig.maxLeashDistance) { // Paper +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit +- this.dropLeash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + } + + return; +@@ -56,8 +59,11 @@ public abstract class PathfinderMob extends Mob { + + this.onLeashDistance(f); + if (f > entity.level.paperConfig.maxLeashDistance) { // Paper +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit +- this.dropLeash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + this.goalSelector.disableControlFlag(Goal.Flag.MOVE); + } else if (f > 6.0F) { + double d0 = (entity.getX() - this.getX()) / (double) f; +diff --git a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java +index 465548de7e32028a2aed4b6e9543e1bd9b73700b..1f54c020cc2b1928b2e7edda9ddf7b9d61e6424b 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java +@@ -28,6 +28,8 @@ import net.minecraft.world.phys.AABB; + import org.bukkit.craftbukkit.event.CraftEventFactory; + // CraftBukkit end + ++import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper ++ + public class LeashFenceKnotEntity extends HangingEntity { + + public LeashFenceKnotEntity(EntityType type, Level world) { +@@ -123,11 +125,14 @@ public class LeashFenceKnotEntity extends HangingEntity { + entityinsentient = (Mob) iterator.next(); + if (entityinsentient.isLeashed() && entityinsentient.getLeashHolder() == this) { + // CraftBukkit start +- if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, player).isCancelled()) { ++ // Paper start - drop leash variable ++ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, player, !player.abilities.instabuild); ++ if (event.isCancelled()) { ++ // Paper end + die = false; + continue; + } +- entityinsentient.dropLeash(true, !player.abilities.instabuild); // false -> survival mode boolean ++ entityinsentient.dropLeash(true, event.isDropLeash()); // false -> survival mode boolean // Paper - drop leash variable + // CraftBukkit end + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 34c0216baa69206aca51821aec421484b18cb04c..ea7c30ef17fc66c1fb55d5909f94651c98b181be 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1460,8 +1460,10 @@ public class CraftEventFactory { + return itemInHand; + } + +- public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(Mob entity, net.minecraft.world.entity.player.Player player) { +- PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity()); ++ // Paper start - drop leash variable ++ public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(Mob entity, net.minecraft.world.entity.player.Player player, boolean dropLeash) { ++ PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), dropLeash); ++ // Paper end + entity.level.getCraftServer().getPluginManager().callEvent(event); + return event; + } diff --git a/patches/server-remapped/0661-Skip-distance-map-update-when-spawning-disabled.patch b/patches/server-remapped/0661-Skip-distance-map-update-when-spawning-disabled.patch new file mode 100644 index 0000000000..fac284074d --- /dev/null +++ b/patches/server-remapped/0661-Skip-distance-map-update-when-spawning-disabled.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Beech Horn +Date: Fri, 14 Feb 2020 19:39:59 +0000 +Subject: [PATCH] Skip distance map update when spawning disabled. + + +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 7a615a18f1f297adfe7e046407a019d8933e9ed9..8e27559a12ada05e0530c7fe5b0bfbc4422ccbd6 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -825,7 +825,7 @@ public class ServerChunkCache extends ChunkSource { + int l = this.distanceManager.getNaturalSpawnChunkCount(); + // Paper start - per player mob spawning + NaturalSpawner.SpawnState spawnercreature_d; // moved down +- if (this.chunkMap.playerMobDistanceMap != null) { ++ if ((this.spawnFriendlies || this.spawnEnemies) && this.chunkMap.playerMobDistanceMap != null) { // don't update when animals and monsters are disabled + // update distance map + this.level.timings.playerMobDistanceMapUpdate.startTiming(); + this.chunkMap.playerMobDistanceMap.update(this.level.players, this.chunkMap.viewDistance); diff --git a/patches/server-remapped/0662-Reset-shield-blocking-on-dimension-change.patch b/patches/server-remapped/0662-Reset-shield-blocking-on-dimension-change.patch new file mode 100644 index 0000000000..4349f8f4d8 --- /dev/null +++ b/patches/server-remapped/0662-Reset-shield-blocking-on-dimension-change.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Yive +Date: Sun, 24 Jan 2021 08:55:19 -0800 +Subject: [PATCH] Reset shield blocking on dimension change + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index ff831ca0cbc0cabbf78178c609ccf70d78da7980..314f168c9d17ab3654c9dda07e48839570f0d332 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1115,6 +1115,11 @@ public class ServerPlayer extends Player implements ContainerListener { + this.level.getCraftServer().getPluginManager().callEvent(changeEvent); + // CraftBukkit end + } ++ // Paper start ++ if (this.isBlocking()) { ++ this.stopUsingItem(); ++ } ++ // Paper end + + return this; + } diff --git a/patches/server-remapped/0663-add-DragonEggFormEvent.patch b/patches/server-remapped/0663-add-DragonEggFormEvent.patch new file mode 100644 index 0000000000..17cbf7f9ae --- /dev/null +++ b/patches/server-remapped/0663-add-DragonEggFormEvent.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Mon, 25 Jan 2021 14:53:57 +0100 +Subject: [PATCH] add DragonEggFormEvent + + +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index e2f784b771b12bd646d519938c33b1c86cc2686d..f32e2c71929a73258e4eb521c160c247690744d2 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -57,6 +57,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfigur + import net.minecraft.world.phys.AABB; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import io.papermc.paper.event.block.DragonEggFormEvent; // Paper - DragonEggFormEvent + + public class EndDragonFight { + +@@ -396,9 +397,24 @@ public class EndDragonFight { + this.dragonEvent.setVisible(false); + this.spawnExitPortal(true); + this.spawnNewGateway(); ++ // Paper start - DragonEggFormEvent ++ BlockPos eggPosition = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getPosition()); ++ org.bukkit.craftbukkit.block.CraftBlock eggBlock = org.bukkit.craftbukkit.block.CraftBlock.at(this.level, eggPosition); ++ org.bukkit.craftbukkit.block.CraftBlockState eggState = new org.bukkit.craftbukkit.block.CraftBlockState(eggBlock); ++ eggState.setData(Blocks.DRAGON_EGG.defaultBlockState()); ++ DragonEggFormEvent eggEvent = new DragonEggFormEvent(eggBlock, eggState, ++ new org.bukkit.craftbukkit.boss.CraftDragonBattle(this)); ++ // Paper end - DragonEggFormEvent + if (this.level.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg +- this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.END_PODIUM_LOCATION), Blocks.DRAGON_EGG.defaultBlockState()); ++ // Paper start - DragonEggFormEvent ++ //this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); ++ } else { ++ eggEvent.setCancelled(true); ++ } ++ if (eggEvent.callEvent()) { ++ eggEvent.getNewState().update(true); + } ++ // Paper end - DragonEggFormEvent + + this.previouslyKilled = true; + this.dragonKilled = true; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java +index cd24e9db1e9a490117716d4883376bb6b59c7c67..e085607f4033476e80b7dcd7b026449c12a47cf6 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java +@@ -14,7 +14,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConf + + public class EndPodiumFeature extends Feature { + +- public static final BlockPos END_PODIUM_LOCATION = BlockPos.ZERO; ++ public static final BlockPos END_PODIUM_LOCATION = BlockPos.ZERO; public static BlockPos getPosition() { return END_PODIUM_LOCATION; } // Paper - OBFHELPER + private final boolean active; + + public EndPodiumFeature(boolean open) { +@@ -22,43 +22,43 @@ public class EndPodiumFeature extends Feature { + this.active = open; + } + +- public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, NoneFeatureConfiguration config) { +- Iterator iterator = BlockPos.betweenClosed(new BlockPos(pos.getX() - 4, pos.getY() - 1, pos.getZ() - 4), new BlockPos(pos.getX() + 4, pos.getY() + 32, pos.getZ() + 4)).iterator(); ++ public boolean generate(WorldGenLevel generatoraccessseed, ChunkGenerator chunkgenerator, Random random, BlockPos blockposition, NoneFeatureConfiguration worldgenfeatureemptyconfiguration) { // Paper - decompile fix ++ Iterator iterator = BlockPos.betweenClosed(new BlockPos(blockposition.getX() - 4, blockposition.getY() - 1, blockposition.getZ() - 4), new BlockPos(blockposition.getX() + 4, blockposition.getY() + 32, blockposition.getZ() + 4)).iterator(); + + while (iterator.hasNext()) { + BlockPos blockposition1 = (BlockPos) iterator.next(); +- boolean flag = blockposition1.closerThan((Vec3i) pos, 2.5D); ++ boolean flag = blockposition1.closerThan((Vec3i) blockposition, 2.5D); + +- if (flag || blockposition1.closerThan((Vec3i) pos, 3.5D)) { +- if (blockposition1.getY() < pos.getY()) { ++ if (flag || blockposition1.closerThan((Vec3i) blockposition, 3.5D)) { ++ if (blockposition1.getY() < blockposition.getY()) { + if (flag) { +- this.setBlock(world, blockposition1, Blocks.BEDROCK.defaultBlockState()); +- } else if (blockposition1.getY() < pos.getY()) { +- this.setBlock(world, blockposition1, Blocks.END_STONE.defaultBlockState()); ++ this.setBlock(generatoraccessseed, blockposition1, Blocks.BEDROCK.defaultBlockState()); ++ } else if (blockposition1.getY() < blockposition.getY()) { ++ this.setBlock(generatoraccessseed, blockposition1, Blocks.END_STONE.defaultBlockState()); + } +- } else if (blockposition1.getY() > pos.getY()) { +- this.setBlock(world, blockposition1, Blocks.AIR.defaultBlockState()); ++ } else if (blockposition1.getY() > blockposition.getY()) { ++ this.setBlock(generatoraccessseed, blockposition1, Blocks.AIR.defaultBlockState()); + } else if (!flag) { +- this.setBlock(world, blockposition1, Blocks.BEDROCK.defaultBlockState()); ++ this.setBlock(generatoraccessseed, blockposition1, Blocks.BEDROCK.defaultBlockState()); + } else if (this.active) { +- this.setBlock(world, new BlockPos(blockposition1), Blocks.END_PORTAL.defaultBlockState()); ++ this.setBlock(generatoraccessseed, new BlockPos(blockposition1), Blocks.END_PORTAL.defaultBlockState()); + } else { +- this.setBlock(world, new BlockPos(blockposition1), Blocks.AIR.defaultBlockState()); ++ this.setBlock(generatoraccessseed, new BlockPos(blockposition1), Blocks.AIR.defaultBlockState()); + } + } + } + + for (int i = 0; i < 4; ++i) { +- this.setBlock(world, pos.above(i), Blocks.BEDROCK.defaultBlockState()); ++ this.setBlock(generatoraccessseed, blockposition.above(i), Blocks.BEDROCK.defaultBlockState()); + } + +- BlockPos blockposition2 = pos.above(2); ++ BlockPos blockposition2 = blockposition.above(2); + Iterator iterator1 = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator1.hasNext()) { + Direction enumdirection = (Direction) iterator1.next(); + +- this.setBlock(world, blockposition2.relative(enumdirection), (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, enumdirection)); ++ this.setBlock(generatoraccessseed, blockposition2.relative(enumdirection), (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, enumdirection)); + } + + return true; diff --git a/patches/server-remapped/0664-EntityMoveEvent.patch b/patches/server-remapped/0664-EntityMoveEvent.patch new file mode 100644 index 0000000000..eec865bf53 --- /dev/null +++ b/patches/server-remapped/0664-EntityMoveEvent.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Tue, 11 Feb 2020 21:56:48 -0600 +Subject: [PATCH] EntityMoveEvent + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 892ca65d258b0745be95d7ef4886c49899b24d92..bc44811f26076871848ba8f5c582ab26b1fd7170 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -13,6 +13,7 @@ import io.netty.buffer.ByteBuf; + import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; + import io.papermc.paper.adventure.PaperAdventure; // Paper ++import io.papermc.paper.event.entity.EntityMoveEvent; + import it.unimi.dsi.fastutil.longs.LongIterator; + import java.awt.image.BufferedImage; + import java.io.BufferedWriter; +@@ -1458,6 +1459,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper ++ worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper + HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + + this.profiler.push(() -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 9f1838d12b13d64f10871eb672ed2aec78d9936e..338b4c382fb8ea349ce81f2009e96de1df7ac5e2 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -207,6 +207,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper ++ public boolean hasEntityMoveEvent = false; // Paper + private static Throwable getAddToWorldStackTrace(Entity entity) { + return new Throwable(entity + " Added to world at " + new java.util.Date()); + } +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 02ddb84c563b3149c4f1b0e24899ce8a21ad61bb..8bc74878919ab7cf6a50d425da61f1b8a8b0ee44 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -10,6 +10,7 @@ import com.mojang.datafixers.util.Pair; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import com.mojang.serialization.DynamicOps; ++import io.papermc.paper.event.entity.EntityMoveEvent; + import java.util.Collection; + import java.util.ConcurrentModificationException; + import java.util.Iterator; +@@ -2909,6 +2910,20 @@ public abstract class LivingEntity extends Entity { + + this.pushEntities(); + this.level.getProfiler().pop(); ++ // Paper start ++ if (((ServerLevel) level).hasEntityMoveEvent) { ++ if (xo != getX() || yo != getY() || zo != getZ() || yRotO != yRot || xRotO != xRot) { ++ Location from = new Location(level.getWorld(), xo, yo, zo, yRotO, xRotO); ++ Location to = new Location (level.getWorld(), getX(), getY(), getZ(), yRot, xRot); ++ EntityMoveEvent event = new EntityMoveEvent(getBukkitLivingEntity(), from, to.clone()); ++ if (!event.callEvent()) { ++ absMoveTo(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); ++ } else if (!to.equals(event.getTo())) { ++ absMoveTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); ++ } ++ } ++ } ++ // Paper end + if (!this.level.isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { + this.hurt(DamageSource.DROWN, 1.0F); + } diff --git a/patches/server-remapped/0665-added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server-remapped/0665-added-option-to-disable-pathfinding-updates-on-block.patch new file mode 100644 index 0000000000..ca84c216d2 --- /dev/null +++ b/patches/server-remapped/0665-added-option-to-disable-pathfinding-updates-on-block.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas81298 +Date: Mon, 25 Jan 2021 14:37:57 +0100 +Subject: [PATCH] added option to disable pathfinding updates on block changes + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 40939de88b1a8169dbfc7a0cd288c2fe9b706426..bbb1d0ed9e76f414dc7d73b4f7786891425f55cd 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -800,4 +800,9 @@ public class PaperWorldConfig { + private void enderDragonsDeathAlwaysPlacesDragonEgg() { + enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); + } ++ ++ public boolean updatePathfindingOnBlockUpdate = true; ++ private void setUpdatePathfindingOnBlockUpdate() { ++ updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 338b4c382fb8ea349ce81f2009e96de1df7ac5e2..a7553a856b9c99bee8f75d514b97cfab952bfd33 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1678,6 +1678,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + @Override + public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) { + this.getChunkSource().blockChanged(pos); ++ if(this.paperConfig.updatePathfindingOnBlockUpdate) { // Paper - option to disable pathfinding updates + VoxelShape voxelshape = oldState.getCollisionShape(this, pos); + VoxelShape voxelshape1 = newState.getCollisionShape(this, pos); + +@@ -1706,6 +1707,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + this.tickingEntities = wasTicking; // Paper + } ++ } // Paper + } + + @Override diff --git a/patches/server-remapped/0666-Inline-shift-direction-fields.patch b/patches/server-remapped/0666-Inline-shift-direction-fields.patch new file mode 100644 index 0000000000..bf3e677ed6 --- /dev/null +++ b/patches/server-remapped/0666-Inline-shift-direction-fields.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Mon, 18 Jan 2021 20:45:25 -0500 +Subject: [PATCH] Inline shift direction fields + +Removes a layer of indirection for EnumDirection.getAdjacent(X|Y|Z)(), which is in the +critical section for much of the server, including the lighting engine. + +diff --git a/src/main/java/net/minecraft/core/Direction.java b/src/main/java/net/minecraft/core/Direction.java +index 3ebc62fe93a0cd0048e07b0343fc724f2c056010..51217f7e5288162b8e76c8717506b393cd262537 100644 +--- a/src/main/java/net/minecraft/core/Direction.java ++++ b/src/main/java/net/minecraft/core/Direction.java +@@ -53,6 +53,11 @@ public enum Direction implements StringRepresentable { + }, (enumdirection, enumdirection1) -> { + throw new IllegalArgumentException("Duplicate keys"); + }, Long2ObjectOpenHashMap::new)); ++ // Paper start ++ private final int adjX; ++ private final int adjY; ++ private final int adjZ; ++ // Paper end + + private Direction(int i, int j, int k, String s, Direction.AxisDirection enumdirection_enumaxisdirection, Direction.Axis enumdirection_enumaxis, Vec3i baseblockposition) { + this.data3d = i; +@@ -62,6 +67,11 @@ public enum Direction implements StringRepresentable { + this.axis = enumdirection_enumaxis; + this.axisDirection = enumdirection_enumaxisdirection; + this.normal = baseblockposition; ++ // Paper start ++ this.adjX = baseblockposition.getX(); ++ this.adjY = baseblockposition.getY(); ++ this.adjZ = baseblockposition.getZ(); ++ // Paper end + } + + public static Direction[] orderedByNearest(Entity entity) { +@@ -137,15 +147,15 @@ public enum Direction implements StringRepresentable { + } + + public int getStepX() { +- return this.normal.getX(); ++ return this.adjX; // Paper + } + + public int getStepY() { +- return this.normal.getY(); ++ return this.adjY; // Paper + } + + public int getStepZ() { +- return this.normal.getZ(); ++ return this.adjZ; // Paper + } + + public String getName() { diff --git a/patches/server-remapped/0667-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server-remapped/0667-Allow-adding-items-to-BlockDropItemEvent.patch new file mode 100644 index 0000000000..973fb6de6c --- /dev/null +++ b/patches/server-remapped/0667-Allow-adding-items-to-BlockDropItemEvent.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Wed, 20 Jan 2021 14:23:37 -0600 +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 ea7c30ef17fc66c1fb55d5909f94651c98b181be..5145968c9c6ccabfb15b91102f82e8a3a2d3cf82 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -389,13 +389,30 @@ public class CraftEventFactory { + } + + public static void handleBlockDropItemEvent(Block block, BlockState state, ServerPlayer player, List items) { +- BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), Lists.transform(items, (item) -> (org.bukkit.entity.Item) item.getBukkitEntity())); ++ // Paper start ++ List list = new ArrayList<>(); ++ for (ItemEntity item : items) { ++ list.add((Item) item.getBukkitEntity()); ++ } ++ BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), list); ++ // Paper end + Bukkit.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { +- for (ItemEntity item : items) { +- item.level.addFreshEntity(item); ++ // Paper start ++ for (Item bukkit : list) { ++ if (!bukkit.isValid()) { ++ Entity item = ((org.bukkit.craftbukkit.entity.CraftItem) bukkit).getHandle(); ++ item.level.addFreshEntity(item); ++ } ++ } ++ } else { ++ for (Item bukkit : list) { ++ if (bukkit.isValid()) { ++ bukkit.remove(); ++ } + } ++ // Paper end + } + } + diff --git a/patches/server-remapped/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/server-remapped/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch new file mode 100644 index 0000000000..f2acd9e212 --- /dev/null +++ b/patches/server-remapped/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aleksander Jagiello +Date: Sun, 24 Jan 2021 22:17:54 +0100 +Subject: [PATCH] Add getMainThreadExecutor to BukkitScheduler + + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 13e461ffb2ee2e7d0440c0f60809ea99629b843c..0be39dac4b9dd69d7d73d86d64cf1e33e4086e81 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -635,4 +635,15 @@ public class CraftScheduler implements BukkitScheduler { + public BukkitTask runTaskTimerAsynchronously(Plugin plugin, BukkitRunnable task, long delay, long period) throws IllegalArgumentException { + throw new UnsupportedOperationException("Use BukkitRunnable#runTaskTimerAsynchronously(Plugin, long, long)"); + } ++ ++ // Paper start - add getMainThreadExecutor ++ @Override ++ public Executor getMainThreadExecutor(Plugin plugin) { ++ Validate.notNull(plugin, "Plugin cannot be null"); ++ return command -> { ++ Validate.notNull(command, "Command cannot be null"); ++ this.runTask(plugin, command); ++ }; ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0669-living-entity-allow-attribute-registration.patch b/patches/server-remapped/0669-living-entity-allow-attribute-registration.patch new file mode 100644 index 0000000000..78a2270873 --- /dev/null +++ b/patches/server-remapped/0669-living-entity-allow-attribute-registration.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ysl3000 +Date: Sat, 24 Oct 2020 16:37:44 +0200 +Subject: [PATCH] living entity allow attribute registration + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java +index a501f334ce0bcc606dd2bb186cf7195102cd6c09..8acd102c0778e4e546e5191b6098eacbd15bd9f9 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java ++++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java +@@ -21,7 +21,7 @@ import org.apache.logging.log4j.Logger; + public class AttributeMap { + + private static final Logger LOGGER = LogManager.getLogger(); +- private final Map attributes = Maps.newHashMap(); ++ private final Map attributes = Maps.newHashMap(); private final Map attributeMap = attributes; // Paper - OBFHELPER + private final Set dirtyAttributes = Sets.newHashSet(); + private final AttributeSupplier supplier; + +@@ -135,4 +135,12 @@ public class AttributeMap { + } + + } ++ ++ // Paper - start ++ public void registerAttribute(Attribute attributeBase) { ++ AttributeInstance attributeModifiable = new AttributeInstance(attributeBase, AttributeInstance::getAttribute); ++ attributeMap.put(attributeBase, attributeModifiable); ++ } ++ // Paper - end ++ + } +diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +index 320fd6780af2fa99e4e4f4193cbc9338d492dc6d..a57b16679889f5b20c74712651f94d6796b8c661 100644 +--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java ++++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +@@ -38,6 +38,14 @@ public class CraftAttributeMap implements Attributable { + return (nms == null) ? null : new CraftAttributeInstance(nms, attribute); + } + ++ // Paper start ++ @Override ++ public void registerAttribute(Attribute attribute) { ++ Preconditions.checkArgument(attribute != null, "attribute"); ++ handle.registerAttribute(CraftAttributeMap.toMinecraft(attribute)); ++ } ++ // Paper end ++ + public static net.minecraft.world.entity.ai.attributes.Attribute toMinecraft(Attribute attribute) { + return net.minecraft.core.Registry.ATTRIBUTE.get(CraftNamespacedKey.toMinecraft(attribute.getKey())); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index a8d21382d5859edfd12e01a48924ce780790b4b7..eefb6bd580ea176c3a242695ab4af46e7c61b492 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -663,6 +663,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return getHandle().craftAttributes.getAttribute(attribute); + } + ++ // Paper start ++ @Override ++ public void registerAttribute(Attribute attribute) { ++ getHandle().craftAttributes.registerAttribute(attribute); ++ } ++ // Paper end ++ + @Override + public void setAI(boolean ai) { + if (this.getHandle() instanceof Mob) { diff --git a/patches/server-remapped/0670-fix-dead-slime-setSize-invincibility.patch b/patches/server-remapped/0670-fix-dead-slime-setSize-invincibility.patch new file mode 100644 index 0000000000..72df11355c --- /dev/null +++ b/patches/server-remapped/0670-fix-dead-slime-setSize-invincibility.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Fri, 5 Feb 2021 22:12:13 +0100 +Subject: [PATCH] fix dead slime setSize invincibility + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +index 340036135588d06e43cbd229dd3a6613b04bb9ab..d1bb7e1f7f7837774512e0af0c8b855d34d5a85b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +@@ -17,7 +17,7 @@ public class CraftSlime extends CraftMob implements Slime { + + @Override + public void setSize(int size) { +- getHandle().setSize(size, true); ++ getHandle().setSize(size, /* true */ getHandle().isAlive()); // Paper - fix dead slime setSize invincibility + } + + @Override diff --git a/patches/server-remapped/0671-Merchant-getRecipes-should-return-an-immutable-list.patch b/patches/server-remapped/0671-Merchant-getRecipes-should-return-an-immutable-list.patch new file mode 100644 index 0000000000..c4baf4a043 --- /dev/null +++ b/patches/server-remapped/0671-Merchant-getRecipes-should-return-an-immutable-list.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Wed, 10 Feb 2021 14:53:36 -0800 +Subject: [PATCH] Merchant#getRecipes should return an immutable list + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java +index 3437ec2c7c1a84debb7d7b7c90283d7e25208604..b4bcbd6329c67ea3deeeb1bf38233ebd15e922b7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java +@@ -24,7 +24,7 @@ public class CraftMerchant implements Merchant { + + @Override + public List getRecipes() { +- return Collections.unmodifiableList(Lists.transform(merchant.getOffers(), new Function() { ++ return com.google.common.collect.ImmutableList.copyOf(Lists.transform(merchant.getOffers(), new Function() { // Paper - javadoc says 'an immutable list of trades' - not 'an unmodifiable view of a list of trades'. fixes issue with setRecipes(getRecipes()) + @Override + public MerchantRecipe apply(net.minecraft.world.item.trading.MerchantOffer recipe) { + return recipe.asBukkit(); diff --git a/patches/server-remapped/0672-misc-debugging-dumps.patch b/patches/server-remapped/0672-misc-debugging-dumps.patch new file mode 100644 index 0000000000..f56af1f8b5 --- /dev/null +++ b/patches/server-remapped/0672-misc-debugging-dumps.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 18 Feb 2021 20:23:28 +0000 +Subject: [PATCH] misc debugging dumps + + +diff --git a/src/main/java/io/papermc/paper/util/TraceUtil.java b/src/main/java/io/papermc/paper/util/TraceUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2d5494d2813b773e60ddba6790b750a9a08f21f8 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/util/TraceUtil.java +@@ -0,0 +1,18 @@ ++package io.papermc.paper.util; ++ ++import org.bukkit.Bukkit; ++ ++public final class TraceUtil { ++ ++ public static void dumpTraceForThread(Thread thread, String reason) { ++ Bukkit.getLogger().warning(thread.getName() + ": " + reason); ++ StackTraceElement[] trace = thread.getStackTrace(); ++ for (StackTraceElement traceElement : trace) { ++ Bukkit.getLogger().warning("\tat " + traceElement); ++ } ++ } ++ ++ public static void dumpTraceForThread(String reason) { ++ new Throwable(reason).printStackTrace(); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index bc44811f26076871848ba8f5c582ab26b1fd7170..9b654fed2a00740cef84cf72258abfc7aeafc0c2 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -14,6 +14,7 @@ import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; + import io.papermc.paper.adventure.PaperAdventure; // Paper + import io.papermc.paper.event.entity.EntityMoveEvent; ++import io.papermc.paper.util.TraceUtil; + import it.unimi.dsi.fastutil.longs.LongIterator; + import java.awt.image.BufferedImage; + import java.io.BufferedWriter; +@@ -855,6 +856,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Sat, 20 Feb 2021 13:09:59 -0500 +Subject: [PATCH] Add support for hex color codes in console + +Converts upstream's hex color code legacy format into actual hex color codes in the console. + +diff --git a/src/main/java/io/papermc/paper/console/HexFormattingConverter.java b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a4315961b7a465fb4872a4d67e7c26d4b4ed1fb9 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java +@@ -0,0 +1,178 @@ ++package io.papermc.paper.console; ++ ++import net.minecrell.terminalconsole.TerminalConsoleAppender; ++import org.apache.logging.log4j.core.LogEvent; ++import org.apache.logging.log4j.core.config.Configuration; ++import org.apache.logging.log4j.core.config.plugins.Plugin; ++import org.apache.logging.log4j.core.layout.PatternLayout; ++import org.apache.logging.log4j.core.pattern.*; ++import org.apache.logging.log4j.util.PerformanceSensitive; ++import org.apache.logging.log4j.util.PropertiesUtil; ++ ++import java.util.List; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++import static net.minecrell.terminalconsole.MinecraftFormattingConverter.KEEP_FORMATTING_PROPERTY; ++ ++/** ++ * Modified version of ++ * TerminalConsoleAppender's MinecraftFormattingConverter to support hex color codes using the md_5 &x&r&r&g&g&b&b format. ++ */ ++@Plugin(name = "paperMinecraftFormatting", category = PatternConverter.CATEGORY) ++@ConverterKeys({ "paperMinecraftFormatting" }) ++@PerformanceSensitive("allocation") ++public final class HexFormattingConverter extends LogEventPatternConverter { ++ ++ private static final boolean KEEP_FORMATTING = PropertiesUtil.getProperties().getBooleanProperty(KEEP_FORMATTING_PROPERTY); ++ ++ private static final String ANSI_RESET = "\u001B[m"; ++ ++ private static final char COLOR_CHAR = '§'; ++ private static final String LOOKUP = "0123456789abcdefklmnor"; ++ ++ private static final String RGB_ANSI = "\u001B[38;2;%d;%d;%dm"; ++ private static final Pattern NAMED_PATTERN = Pattern.compile(COLOR_CHAR + "[0-9a-fk-orA-FK-OR]"); ++ private static final Pattern RGB_PATTERN = Pattern.compile(COLOR_CHAR + "x(" + COLOR_CHAR + "[0-9a-fA-F]){6}"); ++ ++ private static final String[] ansiCodes = new String[] { ++ "\u001B[0;30m", // Black §0 ++ "\u001B[0;34m", // Dark Blue §1 ++ "\u001B[0;32m", // Dark Green §2 ++ "\u001B[0;36m", // Dark Aqua §3 ++ "\u001B[0;31m", // Dark Red §4 ++ "\u001B[0;35m", // Dark Purple §5 ++ "\u001B[0;33m", // Gold §6 ++ "\u001B[0;37m", // Gray §7 ++ "\u001B[0;30;1m", // Dark Gray §8 ++ "\u001B[0;34;1m", // Blue §9 ++ "\u001B[0;32;1m", // Green §a ++ "\u001B[0;36;1m", // Aqua §b ++ "\u001B[0;31;1m", // Red §c ++ "\u001B[0;35;1m", // Light Purple §d ++ "\u001B[0;33;1m", // Yellow §e ++ "\u001B[0;37;1m", // White §f ++ "\u001B[5m", // Obfuscated §k ++ "\u001B[21m", // Bold §l ++ "\u001B[9m", // Strikethrough §m ++ "\u001B[4m", // Underline §n ++ "\u001B[3m", // Italic §o ++ ANSI_RESET, // Reset §r ++ }; ++ ++ private final boolean ansi; ++ private final List formatters; ++ ++ /** ++ * Construct the converter. ++ * ++ * @param formatters The pattern formatters to generate the text to manipulate ++ * @param strip If true, the converter will strip all formatting codes ++ */ ++ protected HexFormattingConverter(List formatters, boolean strip) { ++ super("paperMinecraftFormatting", null); ++ this.formatters = formatters; ++ this.ansi = !strip; ++ } ++ ++ @Override ++ public void format(LogEvent event, StringBuilder toAppendTo) { ++ int start = toAppendTo.length(); ++ //noinspection ForLoopReplaceableByForEach ++ for (int i = 0, size = formatters.size(); i < size; i++) { ++ formatters.get(i).format(event, toAppendTo); ++ } ++ ++ if (KEEP_FORMATTING || toAppendTo.length() == start) { ++ // Skip replacement if disabled or if the content is empty ++ return; ++ } ++ ++ boolean useAnsi = ansi && TerminalConsoleAppender.isAnsiSupported(); ++ String content = toAppendTo.substring(start); ++ content = useAnsi ? convertRGBColors(content) : stripRGBColors(content); ++ format(content, toAppendTo, start, useAnsi); ++ } ++ ++ private static String convertRGBColors(String input) { ++ Matcher matcher = RGB_PATTERN.matcher(input); ++ StringBuffer buffer = new StringBuffer(); ++ while (matcher.find()) { ++ String s = matcher.group().replace(String.valueOf(COLOR_CHAR), "").replace('x', '#'); ++ int hex = Integer.decode(s); ++ int red = (hex >> 16) & 0xFF; ++ int green = (hex >> 8) & 0xFF; ++ int blue = hex & 0xFF; ++ String replacement = String.format(RGB_ANSI, red, green, blue); ++ matcher.appendReplacement(buffer, replacement); ++ } ++ matcher.appendTail(buffer); ++ return buffer.toString(); ++ } ++ ++ private static String stripRGBColors(String input) { ++ Matcher matcher = RGB_PATTERN.matcher(input); ++ StringBuffer buffer = new StringBuffer(); ++ while (matcher.find()) { ++ matcher.appendReplacement(buffer, ""); ++ } ++ matcher.appendTail(buffer); ++ return buffer.toString(); ++ } ++ ++ static void format(String content, StringBuilder result, int start, boolean ansi) { ++ int next = content.indexOf(COLOR_CHAR); ++ int last = content.length() - 1; ++ if (next == -1 || next == last) { ++ result.setLength(start); ++ result.append(content); ++ if (ansi) { ++ result.append(ANSI_RESET); ++ } ++ return; ++ } ++ ++ Matcher matcher = NAMED_PATTERN.matcher(content); ++ StringBuffer buffer = new StringBuffer(); ++ while (matcher.find()) { ++ int format = LOOKUP.indexOf(Character.toLowerCase(matcher.group().charAt(1))); ++ if (format != -1) { ++ matcher.appendReplacement(buffer, ansi ? ansiCodes[format] : ""); ++ } ++ } ++ matcher.appendTail(buffer); ++ ++ result.setLength(start); ++ result.append(buffer.toString()); ++ if (ansi) { ++ result.append(ANSI_RESET); ++ } ++ } ++ ++ /** ++ * Gets a new instance of the {@link HexFormattingConverter} with the ++ * specified options. ++ * ++ * @param config The current configuration ++ * @param options The pattern options ++ * @return The new instance ++ * ++ * @see HexFormattingConverter ++ */ ++ public static HexFormattingConverter newInstance(Configuration config, String[] options) { ++ if (options.length < 1 || options.length > 2) { ++ LOGGER.error("Incorrect number of options on paperMinecraftFormatting. Expected at least 1, max 2 received " + options.length); ++ return null; ++ } ++ if (options[0] == null) { ++ LOGGER.error("No pattern supplied on paperMinecraftFormatting"); ++ return null; ++ } ++ ++ PatternParser parser = PatternLayout.createPatternParser(config); ++ List formatters = parser.parse(options[0]); ++ boolean strip = options.length > 1 && "strip".equals(options[1]); ++ return new HexFormattingConverter(formatters, strip); ++ } ++ ++} +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 8af159abd3d0cc94cf155fec5b384c42f69551bf..67da1aa7a21622fb231d19dede3775a282a4a12e 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -6,21 +6,21 @@ + + + +- ++ + + + ++ pattern="%highlightError{[%d{HH:mm:ss} %level]: %paperMinecraftFormatting{%msg}%n%xEx{full}}" /> + + + + + +- ++ + + + ++ pattern="[%d{HH:mm:ss}] [%t/%level]: %paperMinecraftFormatting{%msg}{strip}%n%xEx{full}" /> + + + diff --git a/patches/server-remapped/0674-Clear-SyncLoadInfo.patch b/patches/server-remapped/0674-Clear-SyncLoadInfo.patch new file mode 100644 index 0000000000..08d7212876 --- /dev/null +++ b/patches/server-remapped/0674-Clear-SyncLoadInfo.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tom +Date: Fri, 26 Feb 2021 16:10:53 -0600 +Subject: [PATCH] Clear SyncLoadInfo + +This patch merely adds the extra argument "clear" after /paper syncloadinfo to clear currently stored syncload info. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 6fad9329213e4e8a3ef9ce7fb568ad22484a11f3..a6b2b69a5a79fb8cea81e55018ee7f57c8820e56 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -295,6 +295,13 @@ public class PaperCommand extends Command { + sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); + return; + } ++ ++ if (args.length > 1 && args[1].equals("clear")) { ++ SyncLoadFinder.clear(); ++ sender.sendMessage(ChatColor.GRAY + "Sync load data cleared."); ++ return; ++ } ++ + File file = new File(new File(new File("."), "debug"), + "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); + file.getParentFile().mkdirs(); +diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java +index 524f33371b9de1d4dd6972fe59ffbe1804d7c5f3..0bb4aaa546939b67a5d22865190f30478a9337c1 100644 +--- a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java ++++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java +@@ -26,6 +26,10 @@ public class SyncLoadFinder { + public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); + } + ++ public static void clear() { ++ SYNC_LOADS.clear(); ++ } ++ + public static void logSyncLoad(final Level world, final int chunkX, final int chunkZ) { + if (!ENABLED) { + return; diff --git a/patches/server-remapped/0675-Expose-Tracked-Players.patch b/patches/server-remapped/0675-Expose-Tracked-Players.patch new file mode 100644 index 0000000000..7997af8fee --- /dev/null +++ b/patches/server-remapped/0675-Expose-Tracked-Players.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tom +Date: Fri, 26 Feb 2021 16:24:25 -0600 +Subject: [PATCH] Expose Tracked Players + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 87c719caf796f54296ff7e412548062e02af270e..ec30f886585d407fbd122e05107ebca44895c585 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -170,7 +170,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper + private CraftEntity bukkitEntity; + +- ChunkMap.TrackedEntity tracker; // Paper ++ public ChunkMap.TrackedEntity tracker; // Paper package private -> public + public boolean collisionLoadChunks = false; // Paper + public Throwable addedToWorldStack; // Paper - entity debug + public CraftEntity getBukkitEntity() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index d2d179cdef8129653983b01d94928ba83f64f644..ec8c7499662c0a810f1337ebc0fa24d2f3ca79e7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -16,6 +16,7 @@ import java.net.InetSocketAddress; + import java.net.SocketAddress; + import java.util.ArrayList; + import java.util.Collection; ++import java.util.Collections; // Paper + import java.util.HashMap; + import java.util.HashSet; + import java.util.LinkedHashMap; +@@ -2305,6 +2306,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + // Paper end + ++ // Paper start ++ @Override ++ public Set getTrackedPlayers() { ++ if (entity.tracker == null) { ++ return Collections.emptySet(); ++ } ++ ++ Set set = new HashSet<>(entity.tracker.seenBy.size()); ++ for (ServerPlayer entityPlayer : entity.tracker.seenBy) { ++ set.add(entityPlayer.getBukkitEntity().getPlayer()); ++ } ++ return set; ++ } ++ // Paper end ++ + // Spigot start + private final Player.Spigot spigot = new Player.Spigot() + { diff --git a/patches/server-remapped/0676-Remove-streams-from-SensorNearest.patch b/patches/server-remapped/0676-Remove-streams-from-SensorNearest.patch new file mode 100644 index 0000000000..f305e85937 --- /dev/null +++ b/patches/server-remapped/0676-Remove-streams-from-SensorNearest.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Bjarne Koll +Date: Wed, 3 Mar 2021 12:48:48 +0100 +Subject: [PATCH] Remove streams from SensorNearest + +The behavioural nearby sensors are validated every tick on the entities +that registered the respective sensors and are therefore a good subject +to performance improvements. + +More specifically this commit replaces the Stream#filter usage with +ArrayList#removeIf as the removeIf method on an array list is heavily +optimized towards a single internal array re-allocation without any +further overhead on the removeIf call. + +The only negative of this change is the rather agressive diff these +patches introduce as the methods are basically being reimplemented +compared to the previous stream-based implementation. + +See: https://nipafx.dev/java-stream-performance/ + +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java +index 91295b8501b1e9d60bf9a7e954ea7fbce9cdea7f..0cd5a19beeb6103dec454b9071cc2e40adf2d006 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java +@@ -27,18 +27,16 @@ public class NearestItemSensor extends Sensor { + List list = world.getEntitiesOfClass(ItemEntity.class, entity.getBoundingBox().inflate(8.0D, 4.0D, 8.0D), (entityitem) -> { + return true; + }); +- +- entity.getClass(); ++ // Paper start - remove streams in favour of lists + list.sort(Comparator.comparingDouble(entity::distanceToSqr)); +- Stream stream = list.stream().filter((entityitem) -> { +- return entity.wantsToPickUp(entityitem.getItem()); +- }).filter((entityitem) -> { +- return entityitem.closerThan((Entity) entity, 9.0D); +- }); +- +- entity.getClass(); +- Optional optional = stream.filter(entity::hasLineOfSight).findFirst(); +- +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); ++ ItemEntity nearest = null; ++ for (ItemEntity entityItem : list) { ++ if (entity.wantsToPickUp(entityItem.getItem()) && entityItem.closerThan(entity, 9.0D) && entity.canSee(entityItem)) { ++ nearest = entityItem; ++ break; ++ } ++ } ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +index bf38e8b465ae0f50e34b94e0d7830dfdc1be1d59..fa827377ef0ef7cb280d1d54e156e45579899e6c 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +@@ -26,10 +26,12 @@ public class NearestLivingEntitySensor extends Sensor { + list.sort(Comparator.comparingDouble(entity::distanceToSqr)); + Brain behaviorcontroller = entity.getBrain(); + +- behaviorcontroller.setMemory(MemoryModuleType.MOBS, (Object) list); +- behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, list.stream().filter((entityliving1) -> { +- return doTick(entity, entityliving1); +- }).collect(Collectors.toList())); ++ behaviorcontroller.setMemory(MemoryModuleType.MOBS, list); // Paper - decompile error ++ // Paper start - remove streams in favour of lists ++ List visibleMobs = new java.util.ArrayList<>(list); ++ visibleMobs.removeIf(otherEntityLiving -> !Sensor.a(entity, otherEntityLiving)); ++ behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, visibleMobs); ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +index 41a9db2cc4af26baa7072b3c4cebc5357ff43301..fe7414293f144656a938de42524841592c9f40d4 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +@@ -26,22 +26,26 @@ public class PlayerSensor extends Sensor { + + @Override + protected void doTick(ServerLevel world, LivingEntity entity) { +- Stream stream = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((entityplayer) -> { +- return entity.closerThan((Entity) entityplayer, 16.0D); +- }); ++ // Paper start - remove streams in favour of lists ++ List players = new java.util.ArrayList<>(world.players()); ++ players.removeIf(player -> !EntitySelector.notSpectator().test(player) || !entity.closerThan(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator ++ players.sort(Comparator.comparingDouble(entity::distanceToSqr)); + +- entity.getClass(); +- List list = (List) stream.sorted(Comparator.comparingDouble(entity::h)).collect(Collectors.toList()); + Brain behaviorcontroller = entity.getBrain(); +- +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, (Object) list); +- List list1 = (List) list.stream().filter((entityhuman) -> { +- return doTick(entity, (LivingEntity) entityhuman); +- }).collect(Collectors.toList()); +- +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, (Object) (list1.isEmpty() ? null : (Player) list1.get(0))); +- Optional optional = list1.stream().filter(EntitySelector.ATTACK_ALLOWED).findFirst(); +- +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, optional); ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); ++ ++ Player nearest = null, nearestTargetable = null; ++ for (Player player : players) { ++ if (Sensor.a(entity, player)) { ++ if (nearest == null) nearest = player; ++ if (EntitySelector.canAITarget().test(player)) { ++ nearestTargetable = player; ++ break; // Both variables are assigned, no reason to loop further ++ } ++ } ++ } ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, nearestTargetable); ++ // Paper end + } + } diff --git a/patches/server-remapped/0677-do-not-create-unnecessary-copies-of-passenger-list.patch b/patches/server-remapped/0677-do-not-create-unnecessary-copies-of-passenger-list.patch new file mode 100644 index 0000000000..e8d0daacfc --- /dev/null +++ b/patches/server-remapped/0677-do-not-create-unnecessary-copies-of-passenger-list.patch @@ -0,0 +1,239 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas81298 +Date: Sun, 13 Dec 2020 13:42:55 +0100 +Subject: [PATCH] do not create unnecessary copies of passenger list + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java +index a6ecb82d14ccab5d8229689a2a6cb67c579b1f71..cded79352dff0978e0d633eae9d9020b4dec1d4b 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java +@@ -15,7 +15,7 @@ public class ClientboundSetPassengersPacket implements Packet list = entity.getPassengers(); ++ List list = entity.passengers; // Paper - do not create a copy of the list + + this.passengers = new int[list.size()]; + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index f4dd30c8b3326db72d3b3068ee2291de6f15de7c..c17e827a976f509c8294df65335f12139cd36a9f 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -2312,7 +2312,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + list.add(entity); + } + +- if (!entity.getPassengers().isEmpty()) { ++ if (!entity.passengers.isEmpty()) { // Paper - do not copy list + list1.add(entity); + } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index 75e2274578c2c28de3d786372df0b4102337a2cc..e703233db7879c73378b3a06b2e89f7fcea97979 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -102,10 +102,10 @@ public class ServerEntity { + + public final void tick() { this.sendChanges(); } // Paper - OBFHELPER + public void sendChanges() { +- List list = this.entity.getPassengers(); ++ List list = this.entity.passengers; // Paper - do not copy list + + if (!list.equals(this.lastPassengers)) { +- this.lastPassengers = list; ++ this.lastPassengers = com.google.common.collect.ImmutableList.copyOf(list); // Paper - only copy list if something has changed + this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit + } + +@@ -375,7 +375,7 @@ public class ServerEntity { + } + } + +- if (!this.entity.getPassengers().isEmpty()) { ++ if (!this.entity.passengers.isEmpty()) { // Paper - do not create copy of list + consumer.accept(new ClientboundSetPassengersPacket(this.entity)); + } + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index ec30f886585d407fbd122e05107ebca44895c585..d055b362459e5b4658aa220e16118ee6174c0de4 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2233,7 +2233,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + protected boolean canAddPassenger(Entity passenger) { +- return this.getPassengers().size() < 1; ++ return this.passengers.size() < 1; // Paper - do not copy list + } + + public final float getCollisionBorderSize() { return getPickRadius(); } // Paper - OBFHELPER +@@ -2329,7 +2329,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean isVehicle() { +- return !this.getPassengers().isEmpty(); ++ return !this.passengers.isEmpty(); // Paper - do not copy list + } + + public boolean rideableUnderWater() { +@@ -3141,7 +3141,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean hasPassenger(Entity passenger) { +- Iterator iterator = this.getPassengers().iterator(); ++ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list + + Entity entity1; + +@@ -3157,7 +3157,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + public boolean hasPassenger(Class clazz) { +- Iterator iterator = this.getPassengers().iterator(); ++ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list + + Entity entity; + +@@ -3174,7 +3174,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + + public Collection getIndirectPassengers() { + Set set = Sets.newHashSet(); +- Iterator iterator = this.getPassengers().iterator(); ++ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +@@ -3200,7 +3200,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + private void fillIndirectPassengers(boolean playersOnly, Set output) { + Entity entity; + +- for (Iterator iterator = this.getPassengers().iterator(); iterator.hasNext(); entity.fillIndirectPassengers(playersOnly, output)) { ++ for (Iterator iterator = this.passengers.iterator(); iterator.hasNext(); entity.fillIndirectPassengers(playersOnly, output)) { // Paper - do not copy list + entity = (Entity) iterator.next(); + if (!playersOnly || ServerPlayer.class.isAssignableFrom(entity.getClass())) { + output.add(entity); +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java +index 3d919e878908e19d598d70011c44cf980676f4f8..debf53a8bf6f062a237160a7b7e0a251a9756ef6 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java +@@ -52,7 +52,7 @@ public class RunAroundLikeCrazyGoal extends Goal { + @Override + public void tick() { + if (!this.horse.isTamed() && this.horse.getRandom().nextInt(50) == 0) { +- Entity entity = (Entity) this.horse.getPassengers().get(0); ++ Entity entity = this.horse.passengers.isEmpty() ? null : this.horse.passengers.get(0); // Paper - do not copy list, fixed array out of bounds exception as well + + if (entity == null) { + return; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.java +index e512a38ccbba93266f0234e3b2fcf7f62693039b..7a60c0b2c301e8cb768c39ad20f273a5921428cb 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Pig.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java +@@ -85,7 +85,7 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { + @Nullable + @Override + public Entity getControllingPassenger() { +- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); ++ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +index b298bcfb665b1036cd21445cec1518069eb08f06..5901e92a749af50166c517bda575d541554756f5 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +@@ -971,7 +971,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, + @Nullable + @Override + public Entity getControllingPassenger() { +- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); ++ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list + } + + @Nullable +diff --git a/src/main/java/net/minecraft/world/entity/monster/Ravager.java b/src/main/java/net/minecraft/world/entity/monster/Ravager.java +index e50d72c98f2ee3cd3349d2df9a0cdc47b733f7cd..ccc9d941b28ee090436a5958e1b48589d48d9d6f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java +@@ -134,7 +134,7 @@ public class Ravager extends Raider { + @Nullable + @Override + public Entity getControllingPassenger() { +- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); ++ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 25df3ef6b96bec39847a732394af8eccdb4d5d45..23421c4964c67a963a55ce08595c8de112a2ba6e 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -560,7 +560,7 @@ public abstract class AbstractMinecart extends Entity { + + vec3d1 = new Vec3(d8 * d4 / d6, vec3d1.y, d8 * d5 / d6); + this.setDeltaMovement(vec3d1); +- Entity entity = this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); ++ Entity entity = this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list + + if (entity instanceof Player) { + Vec3 vec3d2 = entity.getDeltaMovement(); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +index e7ac3bff190c899397d6576fabbf4966878ea7e5..37f0e359ec858eebfa15d01f23a9ce0103816c8b 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +@@ -316,7 +316,7 @@ public class Boat extends Entity { + super.tick(); + this.tickLerp(); + if (this.isControlledByLocalInstance()) { +- if (this.getPassengers().isEmpty() || !(this.getPassengers().get(0) instanceof Player)) { ++ if (this.passengers.isEmpty() || !(this.passengers.get(0) instanceof Player)) { // Paper - do not copy list + this.setPaddleState(false, false); + } + +@@ -379,7 +379,7 @@ public class Boat extends Entity { + Entity entity = (Entity) list.get(j); + + if (!entity.hasPassenger(this)) { +- if (flag && this.getPassengers().size() < 2 && !entity.isPassenger() && entity.getBbWidth() < this.getBbWidth() && entity instanceof LivingEntity && !(entity instanceof WaterAnimal) && !(entity instanceof Player)) { ++ if (flag && this.passengers.size() < 2 && !entity.isPassenger() && entity.getBbWidth() < this.getBbWidth() && entity instanceof LivingEntity && !(entity instanceof WaterAnimal) && !(entity instanceof Player)) { // Paper - do not copy passenger list + entity.startRiding(this); + } else { + this.push(entity); +@@ -726,8 +726,8 @@ public class Boat extends Entity { + float f = 0.0F; + float f1 = (float) ((this.removed ? 0.009999999776482582D : this.getPassengersRidingOffset()) + passenger.getMyRidingOffset()); + +- if (this.getPassengers().size() > 1) { +- int i = this.getPassengers().indexOf(passenger); ++ if (this.passengers.size() > 1) { // Paper - do not copy list ++ int i = this.passengers.indexOf(passenger); // Paper - do not copy list + + if (i == 0) { + f = 0.2F; +@@ -746,7 +746,7 @@ public class Boat extends Entity { + passenger.yRot += this.deltaRotation; + passenger.setYHeadRot(passenger.getYHeadRot() + this.deltaRotation); + this.clampRotation(passenger); +- if (passenger instanceof Animal && this.getPassengers().size() > 1) { ++ if (passenger instanceof Animal && this.passengers.size() > 1) { // Paper - do not copy list + int j = passenger.getId() % 2 == 0 ? 90 : 270; + + passenger.setYBodyRot(((Animal) passenger).yBodyRot + (float) j); +@@ -906,13 +906,13 @@ public class Boat extends Entity { + + @Override + protected boolean canAddPassenger(Entity passenger) { +- return this.getPassengers().size() < 2 && !this.isEyeInFluid((Tag) FluidTags.WATER); ++ return this.passengers.size() < 2 && !this.isEyeInFluid((Tag) FluidTags.WATER); // Paper - do not copy list + } + + @Nullable + @Override + public Entity getControllingPassenger() { +- List list = this.getPassengers(); ++ List list = this.passengers; // Paper - do not copy list + + return list.isEmpty() ? null : (Entity) list.get(0); + } diff --git a/patches/server-remapped/0678-MC-29274-Fix-Wither-hostility-towards-players.patch b/patches/server-remapped/0678-MC-29274-Fix-Wither-hostility-towards-players.patch new file mode 100644 index 0000000000..ec43d966cb --- /dev/null +++ b/patches/server-remapped/0678-MC-29274-Fix-Wither-hostility-towards-players.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheShermanTanker +Date: Thu, 1 Oct 2020 01:11:03 +0800 +Subject: [PATCH] MC-29274: Fix Wither hostility towards players + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index bbb1d0ed9e76f414dc7d73b4f7786891425f55cd..eb367b8feda8219a97a547c3ef6ab82d278d2f25 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -805,4 +805,10 @@ public class PaperWorldConfig { + private void setUpdatePathfindingOnBlockUpdate() { + updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); + } ++ ++ public boolean fixWitherTargetingBug = false; ++ private void witherSettings() { ++ fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); ++ log("Withers properly target players: " + fixWitherTargetingBug); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +index fd91c80cd6337b5fa41d6060ecdb44b8fa68a16a..b364b442d4cb1f3351850140b85c62c30c888bed 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -102,6 +102,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); + this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); ++ if(this.level.paperConfig.fixWitherTargetingBug) this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 0, false, false, null)); // Paper - Fix MC-29274 + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Mob.class, 0, false, false, WitherBoss.LIVING_ENTITY_SELECTOR)); + } + diff --git a/patches/server-remapped/0679-Throw-proper-exception-on-empty-JsonList-file.patch b/patches/server-remapped/0679-Throw-proper-exception-on-empty-JsonList-file.patch new file mode 100644 index 0000000000..cdc493b6d3 --- /dev/null +++ b/patches/server-remapped/0679-Throw-proper-exception-on-empty-JsonList-file.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sun, 1 Nov 2020 16:43:11 +0100 +Subject: [PATCH] Throw proper exception on empty JsonList file + + +diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java +index e2982a8ac5448110378bc92247952332bdffe12c..71de59cadcbd214b9e3a91a6051f918d9b421b16 100644 +--- a/src/main/java/net/minecraft/server/players/StoredUserList.java ++++ b/src/main/java/net/minecraft/server/players/StoredUserList.java +@@ -189,6 +189,7 @@ public abstract class StoredUserList> { + + try { + JsonArray jsonarray = (JsonArray) StoredUserList.GSON.fromJson(bufferedreader, JsonArray.class); ++ com.google.common.base.Preconditions.checkState(jsonarray != null, "The file \"" + this.file.getName() + "\" is either empty or corrupt"); // Paper + + this.map.clear(); + Iterator iterator = jsonarray.iterator(); diff --git a/patches/server-remapped/0680-Improve-ServerGUI.patch b/patches/server-remapped/0680-Improve-ServerGUI.patch new file mode 100644 index 0000000000..46ebed8c68 --- /dev/null +++ b/patches/server-remapped/0680-Improve-ServerGUI.patch @@ -0,0 +1,400 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com> +Date: Sat, 3 Oct 2020 08:27:40 +0200 +Subject: [PATCH] Improve ServerGUI + +- Added logo to server frame +- Show tps in the server stats + +diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +index c0923ec75ecced2e0a1c0d3ec2c046d69af3e9a9..a3e17c1cb54938908d72d3e86e43f4655f1db194 100644 +--- a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java ++++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +@@ -57,9 +57,18 @@ public class RAMDetails extends JList { + public void update() { + GraphData data = RAMGraph.DATA.peekLast(); + Vector vector = new Vector<>(); ++ ++ double[] tps = new double[] {server.tps1.getAverage(), server.tps5.getAverage(), server.tps15.getAverage()}; ++ String[] tpsAvg = new String[tps.length]; ++ ++ for ( int g = 0; g < tps.length; g++) { ++ tpsAvg[g] = format( tps[g] ); ++ } + vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); + vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); + vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); ++ vector.add("TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg)); ++ + setListData(vector); + } + +@@ -70,4 +79,9 @@ public class RAMDetails extends JList { + } + return ((double) total / (double) tickTimes.length) * 1.0E-6D; + } ++ ++ private static String format(double tps) ++ { ++ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); ++ } + } +diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java +index 2567c588a1dcf732800e6cf87352b020c7bb84d6..ad912fae191777256dd88f6c863ec92f8b6a9c13 100644 +--- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java ++++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java +@@ -31,6 +31,11 @@ import net.minecraft.DefaultUncaughtExceptionHandler; + import net.minecraft.server.dedicated.DedicatedServer; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++// Paper start ++import java.io.IOException; ++import java.util.Objects; ++import javax.imageio.ImageIO; ++// Paper end + + public class MinecraftServerGui extends JComponent { + +@@ -56,6 +61,15 @@ public class MinecraftServerGui extends JComponent { + jframe.pack(); + jframe.setLocationRelativeTo((Component) null); + jframe.setVisible(true); ++ jframe.setName("Minecraft server"); // Paper ++ ++ // Paper start - Add logo as frame image ++ try { ++ jframe.setIconImage(ImageIO.read(Objects.requireNonNull(MinecraftServerGui.class.getClassLoader().getResourceAsStream("logo.png")))); ++ } catch (IOException ignore) { ++ } ++ // Paper end ++ + jframe.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent windowevent) { + if (!servergui.isClosing.getAndSet(true)) { +diff --git a/src/main/java/net/minecraft/server/gui/StatsComponent.java b/src/main/java/net/minecraft/server/gui/StatsComponent.java +index 09414d04208a843f8d337569b53f61b34e64ed92..d2583c762fe655dd1d7bed1061e41cd08ac0c092 100644 +--- a/src/main/java/net/minecraft/server/gui/StatsComponent.java ++++ b/src/main/java/net/minecraft/server/gui/StatsComponent.java +@@ -18,7 +18,7 @@ public class StatsComponent extends JComponent { + }); + private final int[] values = new int[256]; + private int vp; +- private final String[] msgs = new String[11]; ++ private final String[] msgs = new String[12]; public String[] getStatEntries() { return this.msgs; } // Paper - change size, OBFHELPER + private final MinecraftServer server; + private final Timer timer; + +@@ -37,8 +37,18 @@ public class StatsComponent extends JComponent { + private void tick() { + long i = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + ++ // Paper start - Add tps entry ++ double[] tps = org.bukkit.Bukkit.getTPS(); ++ String[] tpsAvg = new String[tps.length]; ++ ++ for ( int g = 0; g < tps.length; g++) { ++ tpsAvg[g] = format( tps[g] ); ++ } + this.msgs[0] = "Memory use: " + i / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)"; + this.msgs[1] = "Avg tick: " + StatsComponent.DECIMAL_FORMAT.format(this.getAverage(this.server.tickTimes) * 1.0E-6D) + " ms"; ++ getStatEntries()[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg); ++ // Paper end ++ + this.values[this.vp++ & 255] = (int) (i * 100L / Runtime.getRuntime().maxMemory()); + this.repaint(); + } +@@ -85,4 +95,10 @@ public class StatsComponent extends JComponent { + public void close() { + this.timer.stop(); + } ++ ++ // Paper - start Add tps entry ++ private static String format(double tps) { ++ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise ++ } ++ // Paper end + } +diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png +new file mode 100644 +index 0000000000000000000000000000000000000000..a7d785f60c884ee4ee487cc364402d66c3dc2ecc +GIT binary patch +literal 14310 +zcmXY21yoy2uugDycPmm{N^yd_Q`}vP7YOd|PH`>8wLo!q*HRn`6f5rV?*HD)IX5{c +zxpy-=`|Zxo_svGBD$Agwkf4A-AaprdNp;|J21vifLD%hMrT$lZeEex|7Xe0mqFAZArC{!qp)zJmbab@utqA`6 +z61Z~|e!k$IbXNT?PvGuuzT7G514$8e!}lsR>%nURMm+~pde``@(!O=ISt0%B93;Ez +za-qRi4n0Q>zQ2#2^_y08QOl3jT*!Ir5@<8VrFx(6f9sP|H8ttjftN;wrX>jP4BcG1;MfU5x^L`zc09u!bDBt#+ll=7@ +zB;}A$BKgu}V?#qfHvm`~pt%wG2y{MOc%B!8I`p|pc +zO#?sq!Zd&j8UPmvY4RQnfo>!6{a}GFV!}g@qu<3Wu$07X(O`vikNW$~q!ngF23Ls2 +z53p8js<-B_Qd?xX6rtq43Mdz(jOg2QXx#Wng_9^1^^~KqFNq{Kvb@Ap9}bf&xFA-C +z5+#cQ`#v$A=kd0O=agATcleBaxXf_(dnqbQz|cL9R&&Ni1omTs+6~YApmk)MCghxj +z1}mq&IU>1nEiF=q=PI`%jQbyRd=hVI83Sm{E-4uTc#w;NNwEW)C(C`xvWzY_%`_MmO +zD&g-sEaE)}6(&g)y-N&rNy;5@+{M`}!{60Y8wMgF5;HmO#B~hG`W$;7xLG*yF((rq +zxP6I#r#o`B3FppK{v(q1!C+YLFSfySDcHyoW!}EfzuCB1B|C5+oP}dtocnwkcNy1EZ6#5JX4=ePl&cu~0tMnt&79+I4%PaK>VqFx;r!QdNmnxlEqdU-QR%Nmu{aWP +zJxwXvt5fFTCOVgB)Zq +z%H0U=9q7Y0lu&1kc4zYT3*lHA@XJfoK>3WFM&WWf2u6^+wCm8##D$x@Gkw+t^HoO( +z4pxDRqg;$5S=t^k22H5^V3V0Qfy%Ogl8I%LD$52=7)J>Ki9Ej1HyEi_ujELlz8$-+?cdD1Zxi02kW0 +zaY=caFq4~s^R?zxcc3Z0X|az}Aww<{P$>6rk+5Di5J7$kWor0{Q&>+DWSBH^Gf`SP +zT{4}IOFh-hB7xwBdewq%de)q6QvxorV(()2>@j8i!kj)=^hN +zl_N{$9xTHHA;V&Zx#tX&1pOO;v^NiOP#_UK@J;;lp+OOhOOO2mlMdxM;Qv-mWG+^vzox|8t`w| +z=gPlM3)y6G*hfV1WwuMe>bO-vP9g`h5BqgO9x{ROBD;aPl>XDmvt(3PUxt|4RFRpK +z5OEtRz{(Oa_W_!Z4XHf#h;Z-~71XM7wlF*L!-#h_Uy2tGuy-rAZ)4{qE~feNkp}qf +zgvBtLkFPI~I7%C=OHZfPZz$j>L9)rb;l +z@J^dxncy52;wmHg=wC3|Xn6jPYCR7xc}~D0wNjoYxmoRh_zh=6@8coM1UQIa_z*1)cZPw4v40qoZQp-uy#DLv=oP +zX9b3vzFA2r8}|_AO8W1(OMG__0{1AUD&Z%&7-(>s+Z-X6Sv}G5QguIbZ3mYa--?09 +z;wNw?n=yAag4%m#w$$-YZ{(ZJUcwHfzu&!gykNjG)e}!=q8xy2_KS=ULsQwv45NK! +zVqqD8#S{vRjg4(Q6HM_F&tihNIQns<%DVjE$cv33ET>Dvc^#{z&#u&&9RgXO?ZLuebczKv#;! +zCS|2lIa37Bp#3RWj0$V3=I2>o40{(J^LD|EUH?!2;Z&HS*>7*V%{v1)wHaUP85mcX +z%q!K}Ntr*IzJD%++btJ;VQO*OjJL1t{GvR3cy@OC-~pe^bV?N`z0QKCr?Tom)4u%A +z3mi2k&eIgh0^rGI#Di+&3lrsy-r+}zwBkDQtswtPbkj!Y^l`{f!# +zLseC0M;DiifDa!({-G4{W$Wxsgv*(NX%HMyXhArVwY105dUHg?+=@6Sy8n@slS76x +zU7%PI8ToKm#qahfR;7kn#|t@9y(0EkooWBDqA1(mpO)>BBz))giBi8xVHlj#dR9U8 +zRo%`iBdlj8%_tRn^qa%T>{nsLLwTNld&WHLyfbPzv2W62m6q=Nsdxnk +z#{P==5!Lidx3bcr_qlUl%BX!xjywA?jv>FU^mJDa0zQT9Kw8RRHq>7B +zb~DXw0(oqBrOQunsm2ghWV2i1VmN{F?)U;0%*j{FEUxazAJ3)KSWomuhklkDi?5h*MTLDS5ma_Nk1sNZYzZ#$maGRyiXBzjG@(G__fuyBl(^A>s&{jF+J%5| +zv#7nD1XK806#_U_4#N2ANAxznk%;U$Y$z#{K*O07mADqx6LjACqwP<`HFV#C6Q*wx +z8JVP_qGF}V7B?^8)f*2F5AON7v$L~Kr?2}oPai_kG!_6MI(U`LS~+Mo*CSyrw>pPE +zllqxy +z^&rnDn4XA@AUY7~`1lwTCrm8KlVRqX&!kZFH&;i9@=R}UDxNSh*)Iq2U+#9}@ag1t +z%KUOEw0DXT)>hQoLTprY^z=BC=8NAyi3pZWT7A`?;rI<3%65Nqb93%pJ=!+dNtB>W +z7f3O-e-S7ZBgBntcyt~wOG_p$AU2zlGH8=%TEm+z8kLYReEMTkIo#2YiA=iKWrH); +zS%uT3xAyyY=!U)0Evpgx{{38MPR2nN<3913M<0O#YCO=TSt^4IzV3^D%2zC>t_OO} +z_h~AVOk+IIi$Ov;-g93a4j@WaekCC#HFm2_Vu9s)8-GbYtr{LgrxnSIN^PW9)!jYX +z?%-yssA~&R3F)C)wj5i|@!atCx?Qy%P1QEGSZm;iUNai`-F(8a%y+_a>CMzx$XEKx +z>sW|JbN36s+Y{4SZsrspH%UH=+Q6J`c&_-JLGL&5|$XUA1vFOC+rgoc&xT{dFT&pMaEBKwyD;plX0>2nla;jTlQ{!fn2M=Ak*=K*g% +zBm0-$ly1~}CT-5gv){jex9)7&b8u!a+vYHXU>=NF2>g3+_rN{(LUMGwRWKk49sS$v +zazyX8zZ1hwZ|U*5{fK@i@hRl*U%Q2cg+!iIfb)6W%S5F{91qinEZE%~4Gl>rBw9S< +zMP5$exl1jESyt}d~jo?hf`z^32b!}UGtJH+w9(0UrI#~Ei*ii&6z(AVE?(}k_A +zE9Z@mj7HF-ch46I0ipe3gapRj{=zk_J1E^b_JwdrhKi4ytBuwP)m>e$@9v`A{1N{h +zwUN6H=_W+h(a?rGaQ%%LP5C4)XiZ*`1uUwgqWvk`LyDD!Ps#Q5oI($KDJ%8n5kBi- +zghsLx`~mf<>WT)6-cJBbp|htk1NfkZ@e#B4@l?UH7!MDMpO?1NETGk_Eg{z!N3!D< +zWg8gtgS%b(0Bg7dw9u35xq)1vNdnM8iu7Eje*u?#sZ~%^q*HDaZC?5z4ZzhSA%ndS +z4&$M&7(|(9nWY%QShCnuN0 +z`n9&UeypypUgx;R+x;XM#8uDM{p`9~j<49)^dotHJVO*A@HL&g7F={FP#trj@{dzm +zeQUiqRWJ&pkKkA1O-|vOf8O1UQ$$0lIExffio|}F@ROV#MXcPH$ +z?$$kxAF@B#KT}u;R@SVyIO>1sw1!i?C(_013w9@?8$bKaLQi34zC$g*^}F&(%NEO6 +zQzD-^6}HQMnGJ{h$J*)HjSxjblWegsW&rLC8Ov_r_20jLjUS$Ptnm|p9fK%r0j+4; +z57^mjL&lISh8>DC;eB$B69$h4XxE3qU4T&zUpDeV@4g>or%D-x@qhie>6mqD959ck74(h?S0BA0}YQ18d?hr6}%}y{%ZNJ^-(?=Op~; +z#2-UNh)jH9>RXmvPJ(Y!8(uhyW|sFpyvv)AaNeljHj^Fx+RC +z!`@c->W1C^FUKHmG2w_atkdsMnzY+l!CV8havQ8-Gu)<8t{#V*2Pwp4h?ayXsi5Z> +zo!guta>TA~iv#iJpQkN>#)QF%As@2WgU&V_Y^qm#E*O}M_ijJfFWq}ts)-l4>D)kCqJJ@MG2$69ph0jzwI8ry1u8D@CyinC$oT?7S*Z}Eg +zYs}PWLqr4u@)w}#!{cMx;KxO6W2H6~3k$laJjAt+C{0mmCRnfs=OJYbh}HMh&e`#> +zj;jrpjqKCh41OK{FOS`@_sPP$iCm46G^EMNk8(l-1f>!gEV+4vMVRZ#8infUenP+k +zL^tBOHF^=)k&U-Tw{gfijqQ&^ +z-RHHII5yp}2|o8pTsf6x7$teW9Em!~iy2DN?D@|U)g%I6VG%JBO$|~;c~1Q^3|x`1 +z6HRbq1#~Ke)wWpALcc&@P;m+*sGavR0{aOx3=IwUE3YPWAwV45pzD$~02inxi7(6X +z$zk683M=_r#M*+6fQ)&FK0y|lm7JLwS)K=t&ZJk!U_-y%_o@fhr{s37MUEQOF*M)3 +zB$;4>Zx;Xk*(hwFjb>1iJ1f*D#nyWL{=>{2|9*^vCNN!%bF8Oe<`xz#s;jFz?;I}4M3lL;!fy_;J-E96Of+;sG%K=fZdR)99pJ}fM( +zq%(s8UrsEL{NrdF`!#RY+VjFyPpE_vtqPMM!MQ+QnE)+_g9Z^{4^;k&Sa^=w*yuxB_*Z!U%!3{_9Qr)Jfz4IeS#io4oj_Kqhq`HCUub|Ke!v$1-$v=kc+O#rlCej?%dhY +zxxKUTsFPG1nfoFp3%7@gh9S?vM0N27#*fpJyaX;Vy{!pt*}!9_mX9uC#J5RyjknW2Dm3dCvZYU +zSW?0kvI9!o2un}*%`AYhr^CQT1aZF=-Nt^atn@Kt%b2!hT(pK!|MclbBv3-<+6{>_ +z8toMfWc9rpOk(8|KW>Z-k>Fr(xc_+q9ocf`8!_n}XYUrW?Ax|*_|=5m*4F0V+46wJ +z1IGS^Z5t=0Zj86J2MfJc +zUq#WKCfhoB<;P2&&`*_G4^_0uqDR20m!>T8ay_rxSzA&9_v5##g6tzXTkx+KRfz32 +z9vvpp?+YxHTxDthCBu7)&Q052y4s9*$M4_2w-OdPyK?F-EBoUuSsIk@@(!gA*A_!0 +z2eu1y;-Q$Ut(M>8FCOtw?vZR-%*ly^x)<95vK@P0tJoZws@+M*NGhg_NU`!}DZnWBHQz%*@6))$BWN;EM0xAF+B4Mph#S??J?K+&viwPmes*n^HGDL9iBf +zCk|mDu46wwughN!isu&G((DO>Ws`(VLY?^#w=RONxUgFGby--Y=5NJ|(>qXOS`;lZhmXyMEyBdVM@jJh71E-})~`?t4w8^Kwy) +z<+KACjs!F^TS-;FT24_iWF+=l(nR}j7U#;Vd +z)IT3=b&}A}1PUKFa6DKfgHkJci!~7u?a%k9h7Rri^{y`|;;xNDoQbV}+oJ=LdApL}|77o@C= +z;~aed)XpbrMtt1x3gHPWxbliQH4nKBCew{9 +z*-_PTyn~`1VrwKcc4ZrhI^!MsZ{D0O0%O2!SHHi^Dfyr9*x*DGFKwc()b;q6nM*M7 +zvA$x_?$BMJJHN5HIn9Ps{_7-sn79~BZegaa5V;s(BA<5BnU?^AeJHXtd)cIj_UCjA +zW|N@MjV~vrJz{sE0Dzv}tXxUDQAXm)1(kX7C_ZVFX%!TlZ850i(P1A0BxaJu)#LcH +zoxMFRzxoxw$bM=B6gpuMD#vcsa^00?%=D+T9-dQqV*=zD|)W!3BLun2&^n)~$ +z2_^{i9~sGXOAsF_S=k&4mWJ@`mD+G%MiPTlhuomboeFNwHb(< +zVpVR!mwf;JmpO3JL|B%L-!;@7TG}+`HZA;-{VIlQGY|T=f|!9!S=!c?sq5|KeEQ*~ +zm!1xeZcJPbSsfjU9e>K|=Ni<+YgrIG!|5@|Z>4bjx+`1j^O-{QK8XARf +zUG$nLRiTEtt;)9F30rvw>nj)@vCF{$d7>o2n>}~Y2^^C79l@s`uXRZOcuy>^%2@t- +zRGv={pKlDXFUgvG_^DWGR==il1rIzn{$p4r(FVOQxZi!_*Ksfl2hR{Aj>01RbFAM= +zpr0wzMwlOwlkt4|JLK)$>VL+{4nv>^`yMa)T;(9f*B(9;{T+)_=M4dN>M&&hS-#(G +z)-sW(WxVkHR)`x#g)25Lu7qnN;~Q-bvKDZ=;^fyLy@okDpvt&ZU{!U)WVtmnp +zAN-CzM{jPFWep9NAKDDq@=kynkGi_GQ@Z2y_Wn)xc_q3-&+9`qdGy_{PF-2c^$)%x +zd0sonEJhtG*2|P*Q-f_3`Akk96HzBz2 +z!5tnJaCcA2hGQrSw*{F)epvfYX?7toP=O0dN +zizY2w`>O@4Vqff!dBhQ^><#TjMP}loM9ProiD-Og@$V=*zQ|Avg0D!+96lr^u(1fl +z3J52PHoJYDdvdiIW?q?JIC*r?88VruLx#bp0lys39v$(c6uC*j}2IFFh +zViOX|K+DH18cd9%Rgjs$*sXuoW<>p^Fv-7CV|zpgTUnj812pyyX-nhA4TZ^UyYY9; +z?}BOarTT1q;0xSTjV_DPWE11?Y2+wSA*ybzebDoy8JwhznKa6SvYxE$WswX7Z6pG$ +zsA2GgHFFL3^zA@XTYK{a+6$Q8di%@1-|q9U15y+~R-L7Kwx8*xr(FP{g*JDPa`e((jSl#~?Rx=3ne(nLfeP9k0grubJK +zU4euzZqt~$Cl%k^{-!e6YQZi|D3#+MUS}VsYZ)0S>y@)kyqRI?A_esvAu-{`1Uq@! +zC+b`wnMK&<_mitl+k@e*$*{&S>vayX*>D>Q5sw2FZ?l(8ff%(8lo<^mBMrwQXOXe+ +z*7sZdWzBTIwZO$y^F)qZL1XbOMY<@M_a56y{({Vg@YN<_y}toq41V%~w=+4ZQvg)X +zVw~l$z-sId^nKU%dlk7W(mG}eS&KV2BdYqNJnX-p=YrG&&`_m0fzA_|iKD${5?oL* +zdS$heR@%Q+(3!!T&k;tIN|v2j=UI))rgkvyC7MTTrKP3g>Fma@_R0`GE5(tL%sS$7 +zG41ag%(Y(xZ5cjlk=R~(3XC+$25r*Fo=G5OhGgR}i!nDoG?^sult?Eo*x$x6CH-3L@LtZ0dfq!Bbbw-S}RwlN%lpH8c=4l2qH +z1wRszHSPh~=esnWvXD8B{D4<}?}6cA+@Ob1760Is6`g!zl@WL(L&={LA}SxAt0>Tw +z%b7i^&yNKM;(vGcNwuxAK{g|S3Y1&pH_6U1G +z3M4zx5FU=O;=l_?VzQ-~bx~xN1axPgYI0am3d25BjYmfSTX7Q}==Vcryl6@Se0(Jv +zxKW_o%H`jdnC7QXlkFbCsACHN1Dx=0gf<~@PW-&<=`1Hd)@#ypH7%OpalDj-P=ts+3^~yWs~TV}BD20HjkW6zc1L +z0#HzMkn3JV%7N-18_@tgE82*YnmEzxirriDSx#_|<|q1vL{k}7>^mRzO(ueTSN2~H +zG}kxp)Qn!&)><3|e>62+GXSpQKcemfqU!&BHZ5Ca;DT<63bBM&uV1BDS?MM$M;x8w>gShAPMxJM^BbMZn}Unm{OC9^4x3%% +zlmX8!km-u$N4fQXQ>jRe`7)3+RFGjhz +z18zf(Fo2<>YV^7LJO^UTZ2Ivd#mpN}o?7pBV&q=f%ID>haV7M8R3jsF*@a%iwIy>| +zsZ!-y{!%&j7`B?W8TcF4NH-RHH1xZ{;7BsA<#APu!;cND)te)FhoXz$BIU}2&^7WP +zT}TX>ZO58$VNPuh6JV7~s(W$vAj`^%AtUamex3YdVl3~4+pqk?G)qUibNMrj0*M25 +zY>5Ac|Dnv6xBQmV#$3JA?&HTN(lYl~J}@$l{*TY^kORrCB)3dDO}^^v!dcLf^CHty +zanjllIQeSLmpuG+h&ae`r*v!C*0A&W^a&q>93?BAXzG7n +z2*3TGPIcN`-_hY9&oaiv#fiv~>}7`T`4=pInEqWX*3e8+yPm^9h-tr&ts55$l+388 +zW)~F}2JH!}VLbQ>?6~H@&k`MnSsTeVj0TRVP4jGbP*!!CwM6`Z11c)yI2w$+R0zxo +zT|obYS1&&`{>>Z9(jnVU&=yI*%PGe*f78ie*_9oap?sd7fx7{r^WT>=XHF +zl`f{=UJEn2?tRw`Fem?eRE6#*nOes(ebRcmaK3~a3{a3EyE1zXSF0p7I_iDJ&%;3V +zU;AS}e?*mH#Yh2P9E3QBigIqu2iXf=@t)2+I~f*_E^JtEP1@IR{CBfTj%T}E3e#n% +zUa{@vU?D$l4DEANwkkK@ruP4ta)E*e^KLGg%$PizyPmHvKNMWtuJQ6sPXY=(1m#>W +z7V?9E!Vj}>a|KfQx5ESpH+q6$@gAp-P#~lbz`aj1_?xinN>3o8b2-Z3w>UZ3QZ}W0 +zWg-!>p>AADDcU^4;0*L4UFgB0QLlXd^y1E&4>txV!T|!`RwjZGl`;-4ZgFf>luHIy +zZ8d8Rh{I3r!g-ht6mAZxMB6VxRqnA0UY`h|mJZy2 +z17BazT$jMKFL3J6Ue_HL1^)4s%$Jj~Qx~1HG#tS@kwL(KP_ZI3dWz0SH(sqj#-*TNGsIWqPj>cj?!GyWvfdEiNOu4$>MIqL=F&Cc0{g*~L5 +zA1wt)=_zMFUkCT5$l!G{1-Y9QtGQ#qm5E(3fYPms_EP*sSVI)bfXN|uNO`BqVuCvd +zv)z8IGRgtM1<_trndVhQ^xA)wn~*W~#d*X@E=W)jcQWI8+?kdzHe;DZ`%+JE%gE}m +z6H=FO8rJxM{N90S=Gi!Mel)TyanxPa;E}C?hJl@e9UWad->;S|v;axgFjrY$z3(rV{MiJ}3M)t;Q?P5wZy0e3G{dcDO7n}3slDXLMrB$;#*W@Qv)D$=?Xs$F(8eTcyGIQ~IWgD%Gn&E>F9y#o>cR-7spE;Rur<_E~Pu)e0I +z#&y1|@8D~8c55<|KMf;&x;hg!A%VOZ38_+uk`jH4#=b9M&xcpxV-7cMN{jXVRnKSe +zlKJJ%=VBV{$DNeI1QkiA;DfdVT?$;O#22z6v6bTK9)fjrfIh!Hq__l~KzuNqT{&kA +zKs@YV6^1ZLGjTgR%(=NHS-DvWnnP)NM#qbHINqmQdCE5??co$3nuikqgm=s7*#Kd*+j_weKrZjMeLeHEoiJm>zuDRU` +zh~ggr^knneWU!Nn}AQt=0Id6Hk; +z4bJqse|V$H`stT?NS0yreYvaZ9YF!fw+N}{3#yXRU!C7?exl35BDC%+!jDMGT^DN# +zN9FGd#5t#;$h}5UgQ?q-Gr15>C6=nLUszle9<+_!!oi_m@_L^-R>_Qty7_g|C%m|5 +z-7^5X5V_ARi?h9_LW%2vByD3X_IvUktqBv{%SYXO1&;e&O#Ll_cfC`Wv1u+l_#RI< +zQ5Kly0;P`%TXaQN(heOg~>V&L{d+ZDA%eq-UKo#1)$rkjSm=nzAE2r +z5--RyKhxfXoGVU3^ab{5XGlyL1+26foG)4HZvN +zG@&I3h0fnK5lIjcrg*XxPy1(gK3_TN`&VYnxP;C|j$~0rT$0f|*#=OzM^NbE-1T5D +z%Csnt)n!sx3N#b(8G&+G3W~Q_B#StA6jZZ=p#wuu`DrAMXm{T@#S;ku4Dme@{Njmk +zCtrh3z6O>o)~o{&Htx+6kn*)$NNBH-biu^aYtWUq +z(G>4rCEKr#tO>!x8A@%W@6g)Xs%2Hq!y#Mbb@9R2@GDWi&!{jhZvzQ1D9nMuPoOS+ +z+cj{9nx5X{jJOIavbFf)Kz5Jnbe5Bu#(XE-z$j&iaP%c9W59OoT0~|N#D*(N2kz={ +zs(|)nH!_+_g1)#ZH2xk>ZTG#6WN#qa3BxZM{NWxq`*#$H255k6Ky?hw*hSA6`c_fl +zT@Ua%E5Ez3;~`kQFmrC#$Nlvc_Uy3#yzhd-6UYuuIwgIBZZC-`dwOBJbfurL(FfhH +z{YkjE+9OrOveY`{t{sGw&51YO1@{iO4)Ki=!Z5#q=m_Hi)_j0`>?;t2j);vv%BUif +z;wpTZdLQLsGvZ()DCdxYudn^Pt;BZ}Rin$4F8h{R`HxT2z`uc&aMXIQOvwgA5%{&) +zFW52MiN!$!EXgx}Px~e1!EMp;#&kY65oDho95j~!qD%YJr`+aK4jCJ4UJ^;q>w@Lf +zvDfg|M`S^@DGxu+7aR3Cx#;%?advj&1~L-m +zJqCP9&TW3migV*`Z$#)Qa>3>Jf)g9D6Ki28P@iX(uso)hic8Dp1F< +zeF;(n8Po8A*~^T{De(J)Z2nqLl@Vv3yoSlGwq0aeOg4ymI(KIkTeur-=J-yp9z?qe)it6gq-wl@I +z0D-_I{|T<5kwD9uH3yf1GWXp5*8eOgJf*q0IRoK|+r{}Fug&0WpNDKMTC@(Xc)9K8 +zy`lByMn!1fnY)1KYP(0Je1)c~WilUuh<&Q8^OE?L9Q^xK*Y@M$`6D6TDCZ^@l8{|} +zxmmNw)mng$hYBii+&ZqedxWT0dnV#LG4zC%+kzcK+-??vEHT>Q-T8zu|s_1IbA#OV)^+1pg1OmmZn` + +literal 0 +HcmV?d00001 + diff --git a/patches/server-remapped/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/patches/server-remapped/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch new file mode 100644 index 0000000000..1099f41d55 --- /dev/null +++ b/patches/server-remapped/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Tue, 2 Feb 2021 09:17:59 +0100 +Subject: [PATCH] stop firing pressure plate EntityInteractEvent for ignored + entities + + +diff --git a/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java b/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java +index f12bf33aa8cc8043052aa1048087f61d9a6d4d52..ae5b052b80665bfba126f5ca5dcd78608cb27d48 100644 +--- a/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java +@@ -81,6 +81,7 @@ public class PressurePlateBlock extends BasePressurePlateBlock { + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); ++ if (entity.isIgnoringBlockTriggers()) continue; // Paper - don't call event for ignored entities + + // CraftBukkit start - Call interact event when turning on a pressure plate + if (this.getSignalForState(world.getBlockState(pos)) == 0) { diff --git a/patches/server-remapped/0682-fix-converting-txt-to-json-file.patch b/patches/server-remapped/0682-fix-converting-txt-to-json-file.patch new file mode 100644 index 0000000000..950227fe76 --- /dev/null +++ b/patches/server-remapped/0682-fix-converting-txt-to-json-file.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 4 Jan 2021 19:49:15 -0800 +Subject: [PATCH] fix converting txt to json file + + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java +index 603b4f841bcc276997d130f1545c4cf550dcac2d..2eafb7e27d06a975cee48cc18c7596d610483d16 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java +@@ -18,6 +18,11 @@ public class DedicatedPlayerList extends PlayerList { + + this.setViewDistance(dedicatedserverproperties.viewDistance); + super.setUsingWhiteList((Boolean) dedicatedserverproperties.whiteList.get()); ++ // Paper start - moved from constructor ++ } ++ @Override ++ public void loadAndSaveFiles() { ++ // Paper end + this.loadUserBanList(); + this.saveUserBanList(); + this.loadIpBanList(); +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 95f9863bbccaa23d08c409792314df4f2397a317..c2947313cc0eda3247fb4b20ddd1d0b86c37c50a 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -195,6 +195,12 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); + org.spigotmc.SpigotConfig.registerCommands(); + // Spigot end ++ // Paper start - moved up to right after PlayerList creation but before file load/save ++ if (this.convertOldUsers()) { ++ this.getProfileCache().save(false); // Paper ++ } ++ this.getPlayerList().loadAndSaveFiles(); // Must be after convertNames ++ // Paper end + // Paper start + try { + com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); +@@ -257,10 +263,6 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + DedicatedServer.LOGGER.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file."); + } + +- if (this.convertOldUsers()) { +- this.getProfileCache().b(false); // Paper +- } +- + if (!OldUsersConverter.serverReadyAfterUserconversion(this)) { + return false; + } else { +diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java +index 941b7e356c377fd8ad4e27409cd74c0046878396..f23ca6bebf2c0b7e02dc6aa51e384cee4e3d12c3 100644 +--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java ++++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +@@ -243,6 +243,7 @@ public class GameProfileCache { + return arraylist; + } + ++ public void save(boolean asyncSave) { b(asyncSave); } // Paper - OBFHELPER + public void b(boolean asyncSave) { // Paper + JsonArray jsonarray = new JsonArray(); + DateFormat dateformat = createDateFormat(); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index c962b6fc0c65dc5e2ea636220727bca63bf4b740..dd121ec8f779b3786eeb7fe85519cf9e472f5adf 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -171,6 +171,7 @@ public abstract class PlayerList { + this.maxPlayers = maxPlayers; + this.playerIo = saveHandler; + } ++ abstract public void loadAndSaveFiles(); // Paper - moved from DedicatedPlayerList constructor + + public void placeNewPlayer(Connection connection, ServerPlayer player) { + ServerPlayer prev = pendingPlayers.put(player.getUUID(), player);// Paper diff --git a/patches/server-remapped/0683-Add-worldborder-events.patch b/patches/server-remapped/0683-Add-worldborder-events.patch new file mode 100644 index 0000000000..33286aca0e --- /dev/null +++ b/patches/server-remapped/0683-Add-worldborder-events.patch @@ -0,0 +1,122 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 4 Jan 2021 22:40:34 -0800 +Subject: [PATCH] Add worldborder events + + +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index aaa6251838483de5c46913534413151b5cb1d3fe..4ad686f4fcd3a23c4230faa03946db1f338bc904 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -14,6 +14,9 @@ import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import io.papermc.paper.event.world.border.WorldBorderBoundsChangeFinishEvent; // Paper ++import io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent; // Paper ++import io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent; // Paper + + public class WorldBorder { + +@@ -102,15 +105,19 @@ public class WorldBorder { + } + + public void setCenter(double x, double z) { +- this.centerX = x; +- this.centerZ = z; ++ // Paper start ++ WorldBorderCenterChangeEvent event = new WorldBorderCenterChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), new org.bukkit.Location(world.getWorld(), this.getCenterX(), 0, this.getCenterZ()), new org.bukkit.Location(world.getWorld(), x, 0, z)); ++ if (!event.callEvent()) return; ++ this.centerX = event.getNewCenter().getX(); ++ this.centerZ = event.getNewCenter().getZ(); ++ // Paper end + this.extent.onCenterChange(); + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { + BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- iworldborderlistener.onBorderCenterSet(this, x, z); ++ iworldborderlistener.onBorderCenterSet(this, event.getNewCenter().getX(), event.getNewCenter().getZ()); // Paper + } + + } +@@ -128,25 +135,43 @@ public class WorldBorder { + } + + public void setSize(double size) { +- this.extent = new WorldBorder.StaticBorderExtent(size); ++ // Paper start ++ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE, getSize(), size, 0); ++ if (!event.callEvent()) return; ++ if (event.getType() == WorldBorderBoundsChangeEvent.Type.STARTED_MOVE && event.getDuration() > 0) { // If changed to a timed transition ++ lerpSizeBetween(event.getOldSize(), event.getNewSize(), event.getDuration()); ++ return; ++ } ++ this.extent = new WorldBorder.StaticBorderExtent(event.getNewSize()); ++ // Paper end + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { + BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- iworldborderlistener.onBorderSizeSet(this, size); ++ iworldborderlistener.onBorderSizeSet(this, event.getNewSize()); // Paper + } + + } + + public void lerpSizeBetween(double fromSize, double toSize, long time) { +- this.extent = (WorldBorder.BorderExtent) (fromSize == toSize ? new WorldBorder.StaticBorderExtent(toSize) : new WorldBorder.MovingBorderExtent(fromSize, toSize, time)); ++ // Paper start ++ WorldBorderBoundsChangeEvent.Type type; ++ if (fromSize == toSize) { // new size = old size ++ type = WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE; // Use INSTANT_MOVE because below it creates a Static border if they are equal. ++ } else { ++ type = WorldBorderBoundsChangeEvent.Type.STARTED_MOVE; ++ } ++ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), type, fromSize, toSize, time); ++ if (!event.callEvent()) return; ++ this.extent = (WorldBorder.BorderExtent) (fromSize == event.getNewSize() ? new WorldBorder.StaticBorderExtent(event.getNewSize()) : new WorldBorder.MovingBorderExtent(fromSize, event.getNewSize(), event.getDuration())); ++ // Paper end + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { + BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- iworldborderlistener.onBorderSizeLerping(this, fromSize, toSize, time); ++ iworldborderlistener.onBorderSizeLerping(this, fromSize, event.getNewSize(), event.getDuration()); // Paper + } + + } +@@ -434,11 +459,11 @@ public class WorldBorder { + + class MovingBorderExtent implements WorldBorder.BorderExtent { + +- private final double from; +- private final double to; ++ private final double from; public final double getOldSize() { return this.from; } // Paper - OBFHELPER ++ private final double to; public final double getNewSize() { return this.to; } // Paper - OBFHELPER + private final long lerpEnd; + private final long lerpBegin; +- private final double lerpDuration; ++ private final double lerpDuration; public final double getDuration() { return this.lerpDuration; } // Paper - OBFHELPER + + private MovingBorderExtent(double d0, double d1, long i) { + this.from = d0; +@@ -493,6 +518,7 @@ public class WorldBorder { + + @Override + public WorldBorder.BorderExtent update() { ++ if (this.getLerpTimeRemaining() <= 0L) new WorldBorderBoundsChangeFinishEvent(world.getWorld(), world.getWorld().getWorldBorder(), getOldSize(), getNewSize(), getDuration()).callEvent(); // Paper + return (WorldBorder.BorderExtent) (this.getLerpRemainingTime() <= 0L ? WorldBorder.this.new StaticBorderExtent(this.to) : this); + } + +@@ -514,6 +540,7 @@ public class WorldBorder { + + double getSize(); + ++ default long getLerpTimeRemaining() { return getLerpRemainingTime(); } // Paper - OBFHELPER + long getLerpRemainingTime(); + + double getLerpTarget(); diff --git a/patches/server-remapped/0684-added-PlayerNameEntityEvent.patch b/patches/server-remapped/0684-added-PlayerNameEntityEvent.patch new file mode 100644 index 0000000000..64f85dbc14 --- /dev/null +++ b/patches/server-remapped/0684-added-PlayerNameEntityEvent.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 5 Jul 2020 00:33:54 -0700 +Subject: [PATCH] added PlayerNameEntityEvent + + +diff --git a/src/main/java/net/minecraft/world/item/NameTagItem.java b/src/main/java/net/minecraft/world/item/NameTagItem.java +index 5e38077c3de0a40f3cfd856bf2e48f7061e39a9d..5c575798c20f15d28350f767ecf15bfc042ebc8c 100644 +--- a/src/main/java/net/minecraft/world/item/NameTagItem.java ++++ b/src/main/java/net/minecraft/world/item/NameTagItem.java +@@ -1,5 +1,10 @@ + package net.minecraft.world.item; + ++// Paper start ++import io.papermc.paper.adventure.PaperAdventure; ++import io.papermc.paper.event.player.PlayerNameEntityEvent; ++// Paper end ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.InteractionHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.LivingEntity; +@@ -16,11 +21,15 @@ public class NameTagItem extends Item { + public InteractionResult interactLivingEntity(ItemStack stack, Player user, LivingEntity entity, InteractionHand hand) { + if (stack.hasCustomHoverName() && !(entity instanceof Player)) { + if (!user.level.isClientSide && entity.isAlive()) { +- entity.setCustomName(stack.getHoverName()); +- if (entity instanceof Mob) { +- ((Mob) entity).setPersistenceRequired(); ++ // Paper start ++ PlayerNameEntityEvent event = new PlayerNameEntityEvent(((ServerPlayer) user).getBukkitEntity(), entity.getBukkitLivingEntity(), PaperAdventure.asAdventure(stack.getHoverName()), true); ++ if (!event.callEvent()) return InteractionResult.PASS; ++ LivingEntity newEntityLiving = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle(); ++ newEntityLiving.setCustomName(event.getName() != null ? PaperAdventure.asVanilla(event.getName()) : null); ++ if (event.isPersistent() && newEntityLiving instanceof Mob) { ++ ((Mob) newEntityLiving).setPersistenceRequired(); + } +- ++ // Paper end + stack.shrink(1); + } + diff --git a/patches/server-remapped/0685-Prevent-grindstones-from-overstacking-items.patch b/patches/server-remapped/0685-Prevent-grindstones-from-overstacking-items.patch new file mode 100644 index 0000000000..9f050a4e9b --- /dev/null +++ b/patches/server-remapped/0685-Prevent-grindstones-from-overstacking-items.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Tue, 16 Feb 2021 21:37:51 -0600 +Subject: [PATCH] Prevent grindstones from overstacking items + + +diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +index 329a6d70d53c13cd554c64996f2ddc489bdc1e94..445d408963538fbc01d61902805b2e35c861e4ce 100644 +--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -195,13 +195,13 @@ public class GrindstoneMenu extends AbstractContainerMenu { + i = Math.max(item.getMaxDamage() - l, 0); + itemstack2 = this.mergeEnchants(itemstack, itemstack1); + if (!itemstack2.isDamageableItem()) { +- if (!ItemStack.matches(itemstack, itemstack1)) { ++ if (!ItemStack.matches(itemstack, itemstack1) || itemstack2.getMaxStackSize() == 1) { // Paper - add max stack size check + this.resultSlots.setItem(0, ItemStack.EMPTY); + this.broadcastChanges(); + return; + } + +- b0 = 2; ++ b0 = 2; // Paper - the problem line for above change, causing over-stacking + } + } else { + boolean flag3 = !itemstack.isEmpty(); diff --git a/patches/server-remapped/0686-Add-recipe-to-cook-events.patch b/patches/server-remapped/0686-Add-recipe-to-cook-events.patch new file mode 100644 index 0000000000..e43e7804ac --- /dev/null +++ b/patches/server-remapped/0686-Add-recipe-to-cook-events.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> +Date: Wed, 6 Jan 2021 12:04:03 -0800 +Subject: [PATCH] Add recipe to cook events + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index f47b46cebd43faa509b8139d2a51cc8f87615893..2dcabfc765cbf6341546a7e2c48156fd921fcc82 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -393,7 +393,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); + org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); + +- FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()), source, result); ++ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()), source, result, (org.bukkit.inventory.CookingRecipe) recipe.toBukkitRecipe()); // Paper + this.level.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent); + + if (furnaceSmeltEvent.isCancelled()) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +index 6c38361d744eae763b6c131ad314485f5a88fcfc..39b4782df965c785be7946d6964e0b7a4381ff74 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +@@ -73,7 +73,10 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable, Ticka + + if (this.cookingProgress[i] >= this.cookingTime[i]) { + SimpleContainer inventorysubcontainer = new SimpleContainer(new ItemStack[]{itemstack}); +- ItemStack itemstack1 = (ItemStack) this.level.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, inventorysubcontainer, this.level).map((recipecampfire) -> { ++ // Paper start ++ Optional recipe = this.level.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, inventorysubcontainer, this.level); ++ ItemStack itemstack1 = (ItemStack) recipe.map((recipecampfire) -> { ++ // Paper end + return recipecampfire.assemble(inventorysubcontainer); + }).orElse(itemstack); + BlockPos blockposition = this.getBlockPos(); +@@ -82,7 +85,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable, Ticka + CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); + org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); + +- BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.level, this.worldPosition), source, result); ++ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.level, this.worldPosition), source, result, (org.bukkit.inventory.CookingRecipe) recipe.map(CampfireCookingRecipe::toBukkitRecipe).orElse(null)); // Paper + this.level.getCraftServer().getPluginManager().callEvent(blockCookEvent); + + if (blockCookEvent.isCancelled()) { diff --git a/patches/server-remapped/0687-Add-Block-isValidTool.patch b/patches/server-remapped/0687-Add-Block-isValidTool.patch new file mode 100644 index 0000000000..a9fe23e278 --- /dev/null +++ b/patches/server-remapped/0687-Add-Block-isValidTool.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 6 Jul 2020 12:44:31 -0700 +Subject: [PATCH] Add Block#isValidTool + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 376b0497c28a35d7ea615397c87b2558b95c596a..def19e23996b85e1e540cd5edc6821ae0ae37f91 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -803,5 +803,9 @@ public class CraftBlock implements Block { + } + return speed; + } ++ ++ public boolean isValidTool(ItemStack itemStack) { ++ return getDrops(itemStack).size() != 0; ++ } + // Paper end + } diff --git a/patches/server-remapped/0688-Allow-using-signs-inside-spawn-protection.patch b/patches/server-remapped/0688-Allow-using-signs-inside-spawn-protection.patch new file mode 100644 index 0000000000..fa0bc9f104 --- /dev/null +++ b/patches/server-remapped/0688-Allow-using-signs-inside-spawn-protection.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Anton Lindroth +Date: Wed, 15 Apr 2020 01:54:02 +0200 +Subject: [PATCH] Allow using signs inside spawn protection + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index eb367b8feda8219a97a547c3ef6ab82d278d2f25..108a005c296c4ed370de4af636163088971bed13 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -811,4 +811,9 @@ public class PaperWorldConfig { + fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); + log("Withers properly target players: " + fixWitherTargetingBug); + } ++ ++ public boolean allowUsingSignsInsideSpawnProtection = false; ++ private void allowUsingSignsInsideSpawnProtection() { ++ allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index cb6568b622abeb939a1195f4656accc8a1c3f1fc..1add53082ab9382cb2e90dc8305b8c71ef1c6a46 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -152,6 +152,7 @@ import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CommandBlock; ++import net.minecraft.world.level.block.SignBlock; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.CommandBlockEntity; + import net.minecraft.world.level.block.entity.JigsawBlockEntity; +@@ -1690,7 +1691,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + this.player.resetLastActionTime(); + if (blockposition.getY() < this.server.getMaxBuildHeight()) { +- if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition)) { ++ if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && (worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition) || (worldserver.paperConfig.allowUsingSignsInsideSpawnProtection && worldserver.getBlockState(blockposition).getBlock() instanceof SignBlock))) { // Paper + // CraftBukkit start - Check if we can actually do something over this large a distance + // Paper - move check up + this.player.stopUsingItem(); // SPIGOT-4706 diff --git a/patches/server-remapped/0689-Implement-Keyed-on-World.patch b/patches/server-remapped/0689-Implement-Keyed-on-World.patch new file mode 100644 index 0000000000..94fd5a3703 --- /dev/null +++ b/patches/server-remapped/0689-Implement-Keyed-on-World.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 6 Jan 2021 00:34:04 -0800 +Subject: [PATCH] Implement Keyed on World + + +diff --git a/src/main/java/net/minecraft/core/Registry.java b/src/main/java/net/minecraft/core/Registry.java +index 5a98bc1522c2035487ce0a048c236903dbfa816e..4924d8cd3004a6e1ce76cd5cf7520556c23fe20a 100644 +--- a/src/main/java/net/minecraft/core/Registry.java ++++ b/src/main/java/net/minecraft/core/Registry.java +@@ -130,7 +130,7 @@ public abstract class Registry implements Codec, Keyable, IdMap { + public static final ResourceKey> LOOT_FUNCTION_REGISTRY = createRegistryKey("loot_function_type"); + public static final ResourceKey> LOOT_ITEM_REGISTRY = createRegistryKey("loot_condition_type"); + public static final ResourceKey> DIMENSION_TYPE_REGISTRY = createRegistryKey("dimension_type"); +- public static final ResourceKey> DIMENSION_REGISTRY = createRegistryKey("dimension"); ++ public static final ResourceKey> DIMENSION_REGISTRY = createRegistryKey("dimension"); public static final ResourceKey> getWorldRegistry() { return DIMENSION_REGISTRY; } // Paper - OBFHELPER + public static final ResourceKey> LEVEL_STEM_REGISTRY = createRegistryKey("dimension"); + public static final Registry SOUND_EVENT = registerSimple(Registry.SOUND_EVENT_REGISTRY, () -> { + return SoundEvents.ITEM_PICKUP; +@@ -339,9 +339,9 @@ public abstract class Registry implements Codec, Keyable, IdMap { + ResourceLocation minecraftkey = resourcekey.location(); + + Registry.LOADERS.put(minecraftkey, defaultEntry); +- WritableRegistry iregistrywritable = Registry.WRITABLE_REGISTRY; ++ WritableRegistry iregistrywritable = Registry.WRITABLE_REGISTRY; // Paper - decompile fix + +- return (WritableRegistry) iregistrywritable.register(resourcekey, (Object) registry, lifecycle); ++ return (R) iregistrywritable.register(resourcekey, (Object) registry, lifecycle); // Paper - decompile fix + } + + protected Registry(ResourceKey> key, Lifecycle lifecycle) { +@@ -428,11 +428,11 @@ public abstract class Registry implements Codec, Keyable, IdMap { + } + + public static T register(Registry registry, ResourceLocation id, T entry) { +- return ((WritableRegistry) registry).register(ResourceKey.create(registry.key, id), entry, Lifecycle.stable()); ++ return ((WritableRegistry) registry).register(ResourceKey.create(registry.key, id), entry, Lifecycle.stable()); // Paper - decompile fix + } + + public static T registerMapping(Registry registry, int rawId, String id, T entry) { +- return ((WritableRegistry) registry).registerMapping(rawId, ResourceKey.create(registry.key, new ResourceLocation(id)), entry, Lifecycle.stable()); ++ return ((WritableRegistry) registry).registerMapping(rawId, ResourceKey.create(registry.key, new ResourceLocation(id)), entry, Lifecycle.stable()); // Paper - decompile fix + } + + static { +diff --git a/src/main/java/net/minecraft/resources/ResourceKey.java b/src/main/java/net/minecraft/resources/ResourceKey.java +index 2f39438ee9b23706efb2fd877fe223777b6968c7..3085ec1f20f4c945242697b809188a8c828cfb75 100644 +--- a/src/main/java/net/minecraft/resources/ResourceKey.java ++++ b/src/main/java/net/minecraft/resources/ResourceKey.java +@@ -12,6 +12,7 @@ public class ResourceKey { + private final ResourceLocation registryName; + private final ResourceLocation location; + ++ public static ResourceKey newResourceKey(ResourceKey> registryKey, ResourceLocation minecraftKey) { return create(registryKey, minecraftKey); } // Paper - OBFHELPER + public static ResourceKey create(ResourceKey> registry, ResourceLocation value) { + return create(registry.location, value); + } +@@ -41,6 +42,7 @@ public class ResourceKey { + return this.registryName.equals(registry.location()); + } + ++ public ResourceLocation getLocation() { return location(); } // Paper - OBFHELPER + public ResourceLocation location() { + return this.location; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 794b894ed24636aec60de9a28ba7613d7a917324..6905256147d9bd79e5f52bf86bdb21c89b8411a7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1156,7 +1156,7 @@ public final class CraftServer implements Server { + } else if (name.equals(levelName + "_the_end")) { + worldKey = net.minecraft.world.level.Level.END; + } else { +- worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(name.toLowerCase(java.util.Locale.ENGLISH))); ++ worldKey = ResourceKey.newResourceKey(Registry.getWorldRegistry(), new net.minecraft.resources.ResourceLocation(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper + } + + ServerLevel internal = (ServerLevel) new ServerLevel(console, console.executor, worldSession, worlddata, worldKey, dimensionmanager, getServer().progressListenerFactory.create(11), +@@ -1246,6 +1246,15 @@ public final class CraftServer implements Server { + return null; + } + ++ // Paper start ++ @Override ++ public World getWorld(NamespacedKey worldKey) { ++ ServerLevel worldServer = console.getLevel(ResourceKey.newResourceKey(Registry.getWorldRegistry(), CraftNamespacedKey.toMinecraft(worldKey))); ++ if (worldServer == null) return null; ++ return worldServer.getWorld(); ++ } ++ // Paper end ++ + public void addWorld(World world) { + // Check if a World already exists with the UID. + if (getWorld(world.getUID()) != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index f497b9e11a075a84ff0a2117eb79d0532e4a326f..b0212b2043ee5fd77c8876ef0b51ef91488712f0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2566,6 +2566,11 @@ public class CraftWorld implements World { + return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + }, net.minecraft.server.MinecraftServer.getServer()); + } ++ ++ @Override ++ public org.bukkit.NamespacedKey getKey() { ++ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(world.dimension().getLocation()); ++ } + // Paper end + + // Spigot start diff --git a/patches/server-remapped/0690-Add-fast-alternative-constructor-for-Vector3f.patch b/patches/server-remapped/0690-Add-fast-alternative-constructor-for-Vector3f.patch new file mode 100644 index 0000000000..b395761137 --- /dev/null +++ b/patches/server-remapped/0690-Add-fast-alternative-constructor-for-Vector3f.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Irmo van den Berge +Date: Wed, 10 Mar 2021 21:26:31 +0100 +Subject: [PATCH] Add fast alternative constructor for Vector3f + +Signed-off-by: Irmo van den Berge + +diff --git a/src/main/java/net/minecraft/core/Rotations.java b/src/main/java/net/minecraft/core/Rotations.java +index e3c2affb5dfaf2d78139e98c9e8a40b37c92bf2f..4782cbd9d86d8246954db76993741a8a749a7fe0 100644 +--- a/src/main/java/net/minecraft/core/Rotations.java ++++ b/src/main/java/net/minecraft/core/Rotations.java +@@ -19,6 +19,18 @@ public class Rotations { + this(serialized.getFloat(0), serialized.getFloat(1), serialized.getFloat(2)); + } + ++ // Paper start - faster alternative constructor ++ private Rotations(float x, float y, float z, Void dummy_var) { ++ this.x = x; ++ this.y = y; ++ this.z = z; ++ } ++ ++ public static Rotations createWithoutValidityChecks(float x, float y, float z) { ++ return new Rotations(x, y, z, null); ++ } ++ // Paper end ++ + public ListTag save() { + ListTag nbttaglist = new ListTag(); + diff --git a/patches/server-remapped/0691-Item-Rarity-API.patch b/patches/server-remapped/0691-Item-Rarity-API.patch new file mode 100644 index 0000000000..51a841f551 --- /dev/null +++ b/patches/server-remapped/0691-Item-Rarity-API.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 12 Mar 2021 17:09:42 -0800 +Subject: [PATCH] Item Rarity API + + +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index 58400e84830c93675b0a1fe632be5e217c19a932..cb079bfd5339b96ad372b0a3b483d02cd0636bfd 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -45,7 +45,7 @@ public class Item implements ItemLike { + protected static final UUID BASE_ATTACK_SPEED_UUID = UUID.fromString("FA233E1C-4180-4865-B01B-BCCE9785ACA3"); + protected static final Random random = new Random(); + protected final CreativeModeTab category; +- private final Rarity rarity; ++ private final Rarity rarity; public final Rarity getItemRarity() { return rarity; } // Paper - OBFHELPER + private final int maxStackSize; + private final int maxDamage; + private final boolean isFireResistant; +@@ -209,6 +209,7 @@ public class Item implements ItemLike { + return stack.isEnchanted(); + } + ++ public Rarity getItemStackRarity(ItemStack itemStack) { return getRarity(itemStack); } // Paper - OBFHELPER + public Rarity getRarity(ItemStack stack) { + if (!stack.isEnchanted()) { + return this.rarity; +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 25a29d997f163ce2b11330d66a691601f514a9cb..472b0615dcdc3c0c52bd377fd69752716f354262 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -470,6 +470,20 @@ public final class CraftMagicNumbers implements UnsafeValues { + public int nextEntityId() { + return net.minecraft.world.entity.Entity.nextEntityId(); + } ++ ++ @Override ++ public io.papermc.paper.inventory.ItemRarity getItemRarity(org.bukkit.Material material) { ++ Item item = getItem(material); ++ if (item == null) { ++ throw new IllegalArgumentException(material + " is not an item, and rarity does not apply to blocks"); ++ } ++ return io.papermc.paper.inventory.ItemRarity.values()[item.getItemRarity().ordinal()]; ++ } ++ ++ @Override ++ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { ++ return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; ++ } + // Paper end + + /** diff --git a/patches/server-remapped/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/patches/server-remapped/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch new file mode 100644 index 0000000000..c076df0076 --- /dev/null +++ b/patches/server-remapped/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Fri, 19 Mar 2021 16:07:21 -0700 +Subject: [PATCH] Only set despawnTimer for Wandering Traders spawned by + MobSpawnerTrader + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index d38828485d6deb08036e11d8bf16b3d63a60fbae..f6d2aca2fe3ee9b69a0b200c8b2ea35f222fb521 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -319,6 +319,12 @@ public class EntityType { + + @Nullable + public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // Paper start - add consumer to modify entity before spawn ++ return this.spawnCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1, spawnReason, null); ++ } ++ @Nullable ++ public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason, @Nullable java.util.function.Consumer op) { ++ // Paper end + // Paper start - Call PreCreatureSpawnEvent + org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath()); + if (type != null) { +@@ -334,6 +340,7 @@ public class EntityType { + } + // Paper end + T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); ++ if (t0 != null && op != null) op.accept(t0); // Paper + + if (t0 != null) { + worldserver.addAllEntities(t0, spawnReason); +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +index 69d92590d265abe8a04d8bf48bbe9a6ae606ae50..04c4cca4be8886feb59f180915977b77f9c7dde8 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -61,7 +61,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + public WanderingTrader(EntityType type, Level world) { + super(type, world); + this.forcedLoading = true; +- this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader ++ //this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set. + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +index 9074d57e1576db2da3e4c76add4f7e07e5567879..f861d83affbb0b5eaf7440a909ca3b5f7a604da7 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +@@ -114,7 +114,7 @@ public class WanderingTraderSpawner implements CustomSpawner { + return false; + } + +- WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawnCreature(worldserver, (CompoundTag) null, (Component) null, (Player) null, blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit ++ WanderingTrader entityvillagertrader = EntityType.WANDERING_TRADER.spawnCreature(worldserver, null, null, null, blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, trader -> trader.setDespawnDelay(48000)); // CraftBukkit // Paper - set despawnTimer before spawn events called + + if (entityvillagertrader != null) { + for (int i = 0; i < 2; ++i) { diff --git a/patches/server-remapped/0693-copy-TESign-isEditable-from-snapshots.patch b/patches/server-remapped/0693-copy-TESign-isEditable-from-snapshots.patch new file mode 100644 index 0000000000..862aed64d3 --- /dev/null +++ b/patches/server-remapped/0693-copy-TESign-isEditable-from-snapshots.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 23 Mar 2021 06:43:30 +0000 +Subject: [PATCH] copy TESign#isEditable from snapshots + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java +index 65e8a349c80a700f63dd27b11bb2099f65cbc069..eb0739c0927e821a5080d14e762225fd4936b82d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java +@@ -109,6 +109,7 @@ public class CraftSign extends CraftBlockEntityState implements + } + // Paper end + } ++ sign.isEditable = getSnapshot().isEditable; // Paper - copy manually + } + + // Paper start diff --git a/patches/server-remapped/0694-Drop-carried-item-when-player-has-disconnected.patch b/patches/server-remapped/0694-Drop-carried-item-when-player-has-disconnected.patch new file mode 100644 index 0000000000..4e8128fd64 --- /dev/null +++ b/patches/server-remapped/0694-Drop-carried-item-when-player-has-disconnected.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Thu, 4 Feb 2021 20:32:01 +0300 +Subject: [PATCH] Drop carried item when player has disconnected + +Fixes disappearance of held items, when a player gets disconnected and PlayerDropItemEvent is cancelled. +Closes #5036 + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index dd121ec8f779b3786eeb7fe85519cf9e472f5adf..23cfaf5c432221f2d1afe37ba657f723d6d21a73 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -79,6 +79,7 @@ import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.npc.AbstractVillager; ++import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GameType; +@@ -605,6 +606,14 @@ public abstract class PlayerList { + } + // Paper end + ++ // Paper - Drop carried item when player has disconnected ++ if (!entityplayer.inventory.getCarried().isEmpty()) { ++ ItemStack carried = entityplayer.inventory.getCarried(); ++ entityplayer.inventory.setCarried(ItemStack.NULL_ITEM); ++ entityplayer.drop(carried, false); ++ } ++ // Paper end ++ + this.save(entityplayer); + if (entityplayer.isPassenger()) { + Entity entity = entityplayer.getRootVehicle(); diff --git a/patches/server-remapped/0695-forced-whitelist-use-configurable-kick-message.patch b/patches/server-remapped/0695-forced-whitelist-use-configurable-kick-message.patch new file mode 100644 index 0000000000..4b433dc16c --- /dev/null +++ b/patches/server-remapped/0695-forced-whitelist-use-configurable-kick-message.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Sat, 27 Mar 2021 09:24:23 +0100 +Subject: [PATCH] forced whitelist: use configurable kick message + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 9b654fed2a00740cef84cf72258abfc7aeafc0c2..fd76d776c7003585c9efef44c6d7da0f6c3f574e 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -73,7 +73,6 @@ import net.minecraft.nbt.NbtOps; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TextComponent; +-import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; + import net.minecraft.network.protocol.game.ClientboundSetTimePacket; +@@ -2040,7 +2039,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Mon, 29 Mar 2021 09:07:25 +0200 +Subject: [PATCH] Make sure to remove correct TE during TE tick + +This looks like it can cause premature TE removal. + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index b89cefc8890774dbc64fd6bddeb038d2ee36d485..4523bc1f49e7be248a47eeb599fa7b6550dbb08d 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -895,7 +895,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + //this.tileEntityList.remove(tileentity); // Paper - remove unused list + // Paper - prevent double chunk lookups + LevelChunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getBlockPos())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again +- chunk.removeBlockEntity(tileentity.getBlockPos()); ++ chunk.removeTileEntity(tileentity.getBlockPos(), tileentity); // Paper - remove correct TE + } + // Paper end + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 9b76dc15417eef420804e5184a6d684e1137a746..a15c08be3e1bd0e7934175db6ae0684bbb05e249 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -818,10 +818,18 @@ public class LevelChunk implements ChunkAccess { + + @Override + public void removeBlockEntity(BlockPos pos) { ++ // Paper start - remove correct TE ++ removeTileEntity(pos, null); ++ } ++ public void removeTileEntity(BlockPos blockposition, BlockEntity match) { ++ // Paper end + if (this.loaded || this.world.isClientSide()) { +- BlockEntity tileentity = (BlockEntity) this.blockEntities.remove(pos); ++ // Paper start ++ BlockEntity tileentity = (BlockEntity) this.blockEntities.get(blockposition); + +- if (tileentity != null) { ++ if (tileentity != null && (match == null || match == tileentity)) { ++ this.blockEntities.remove(blockposition); ++ // Paper end + tileentity.setRemoved(); + } + } diff --git a/patches/server-remapped/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/patches/server-remapped/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch new file mode 100644 index 0000000000..930a7a71e6 --- /dev/null +++ b/patches/server-remapped/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Mon, 5 Apr 2021 18:35:15 -0700 +Subject: [PATCH] Don't ignore result of PlayerEditBookEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 1add53082ab9382cb2e90dc8305b8c71ef1c6a46..65afc23f4791aca19bff78ed86b3b0d31fa81977 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1144,7 +1144,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + list.stream().map(StringTag::valueOf).forEach(nbttaglist::add); + ItemStack old = itemstack.copy(); // CraftBukkit + itemstack.addTagElement("pages", (Tag) nbttaglist); +- CraftEventFactory.handleEditBookEvent(player, i, old, itemstack); // CraftBukkit ++ this.player.inventory.setItem(i, CraftEventFactory.handleEditBookEvent(player, i, old, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) + } + } + diff --git a/patches/server-remapped/0698-fix-cancelling-block-falling-causing-client-desync.patch b/patches/server-remapped/0698-fix-cancelling-block-falling-causing-client-desync.patch new file mode 100644 index 0000000000..00cd7e5d6c --- /dev/null +++ b/patches/server-remapped/0698-fix-cancelling-block-falling-causing-client-desync.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Sat, 27 Mar 2021 11:13:30 +0100 +Subject: [PATCH] fix cancelling block falling causing client desync + + +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 2ba81e7179c7f9e2e1add1ad6bd6b96ee12c5da1..718e20f83a9b510c095d7e12241616cdce33d2d6 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -13,6 +13,7 @@ import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.FluidTags; + import net.minecraft.tags.Tag; +@@ -41,6 +42,7 @@ import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class FallingBlockEntity extends Entity { +@@ -114,8 +116,18 @@ public class FallingBlockEntity extends Entity { + + if (this.time++ == 0) { + blockposition = this.blockPosition(); +- if (this.level.getBlockState(blockposition).is(block) && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { +- this.level.removeBlock(blockposition, false); ++ // Paper start - fix cancelling block falling causing client desync ++ if (this.level.getBlockState(blockposition).isSameInstance(block)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ if (this.level.getBlockState(blockposition).isSameInstance(block)) { //if listener didn't update the block ++ ((ServerLevel) level).getChunkSource().blockChanged(blockposition); ++ } ++ this.remove(); ++ return; ++ } else { ++ this.level.setAir(blockposition, false); ++ } ++ // Paper end - fix cancelling block falling causing client desync + } else if (!this.level.isClientSide) { + this.remove(); + return; +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index 17baae6b11f191f4738a107c7e62ea5bdac17a3c..32cda8c2e14cf8b218cb006a9b25330f0dab849a 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -682,6 +682,7 @@ public abstract class BlockBehaviour { + return this.getBlock().is(tag) && predicate.test(this); + } + ++ public final boolean isSameInstance(Block block) { return is(block); } // Paper - OBFHELPER + public boolean is(Block block) { + return this.getBlock().is(block); + } diff --git a/patches/server-remapped/0699-Expose-protocol-version.patch b/patches/server-remapped/0699-Expose-protocol-version.patch new file mode 100644 index 0000000000..0e4392f5f9 --- /dev/null +++ b/patches/server-remapped/0699-Expose-protocol-version.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Fri, 26 Mar 2021 11:23:17 +0100 +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 472b0615dcdc3c0c52bd377fd69752716f354262..402e5a98290a1701dd67d27c484c97e0a6067c4f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -484,6 +484,11 @@ public final class CraftMagicNumbers implements UnsafeValues { + public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { + return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; + } ++ ++ @Override ++ public int getProtocolVersion() { ++ return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion(); ++ } + // Paper end + + /** diff --git a/patches/server-remapped/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/server-remapped/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch new file mode 100644 index 0000000000..036bfe3e5a --- /dev/null +++ b/patches/server-remapped/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch @@ -0,0 +1,132 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Thu, 1 Apr 2021 00:34:02 -0700 +Subject: [PATCH] Allow for Component suggestion tooltips in + AsyncTabCompleteEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 65afc23f4791aca19bff78ed86b3b0d31fa81977..67defaf71752ed29fde483e8232aa358ffa53675 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -769,12 +769,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + // Paper start - async tab completion + com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; +- java.util.List completions = new java.util.ArrayList<>(); + String buffer = packet.getCommand(); +- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), + buffer, true, null); + event.callEvent(); +- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); ++ java.util.List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); + // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server + if (!event.isHandled()) { + if (!event.isCancelled()) { +@@ -793,10 +792,16 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + }); + } + } else if (!completions.isEmpty()) { +- com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); ++ com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); + +- builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); +- completions.forEach(builder::suggest); ++ final com.mojang.brigadier.suggestion.SuggestionsBuilder builder = builder0.createOffset(builder0.getInput().lastIndexOf(' ') + 1); ++ completions.forEach(completion -> { ++ if (completion.tooltip() == null) { ++ builder.suggest(completion.suggestion()); ++ } else { ++ builder.suggest(completion.suggestion(), PaperAdventure.asVanilla(completion.tooltip())); ++ } ++ }); + com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); + com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); + suggestEvent.setCancelled(suggestions.isEmpty()); +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index c5e00bd9e2790992202aadf8eec2002fc88c78f1..dd8e87ad192c19743577bb95253a127072ea196c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -29,34 +29,56 @@ public class ConsoleCommandCompleter implements Completer { + final CraftServer server = this.server.server; + final String buffer = line.line(); + // Async Tab Complete +- com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; +- java.util.List completions = new java.util.ArrayList<>(); +- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, +- buffer, true, null); ++ final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event = ++ new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), buffer, true, null); + event.callEvent(); +- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); ++ final List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); + + if (event.isCancelled() || event.isHandled()) { + // Still fire sync event with the provided completions, if someone is listening + if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { +- List finalCompletions = completions; ++ List finalCompletions = new java.util.ArrayList<>(completions); + Waitable> syncCompletions = new Waitable>() { + @Override + protected List evaluate() { +- org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); ++ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, ++ finalCompletions.stream() ++ .map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::suggestion) ++ .collect(java.util.stream.Collectors.toList())); + return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); + } + }; + server.getServer().processQueue.add(syncCompletions); + try { +- completions = syncCompletions.get(); ++ final List legacyCompletions = syncCompletions.get(); ++ completions.removeIf(it -> !legacyCompletions.contains(it.suggestion())); // remove any suggestions that were removed ++ // add any new suggestions ++ for (final String completion : legacyCompletions) { ++ if (notNewSuggestion(completions, completion)) { ++ continue; ++ } ++ completions.add(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion(completion)); ++ } + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } + } + + if (!completions.isEmpty()) { +- candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); ++ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { ++ if (completion.suggestion().isEmpty()) { ++ continue; ++ } ++ candidates.add(new Candidate( ++ completion.suggestion(), ++ completion.suggestion(), ++ null, ++ io.papermc.paper.adventure.PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null), ++ null, ++ null, ++ false ++ )); ++ } + } + return; + } +@@ -106,4 +128,15 @@ public class ConsoleCommandCompleter implements Completer { + Thread.currentThread().interrupt(); + } + } ++ ++ // Paper start ++ private boolean notNewSuggestion(final List completions, final String completion) { ++ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion it : completions) { ++ if (it.suggestion().equals(completion)) { ++ return true; ++ } ++ } ++ return false; ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0701-Enhance-console-tab-completions-for-brigadier-comman.patch b/patches/server-remapped/0701-Enhance-console-tab-completions-for-brigadier-comman.patch new file mode 100644 index 0000000000..f6416177a9 --- /dev/null +++ b/patches/server-remapped/0701-Enhance-console-tab-completions-for-brigadier-comman.patch @@ -0,0 +1,316 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Tue, 30 Mar 2021 16:06:08 -0700 +Subject: [PATCH] Enhance console tab completions for brigadier commands + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index c56e7fb18f9a56c8025eb70a524f028b5942da37..efc1e42d606e1c9feb1a4871c0714933ae92a1b2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -479,4 +479,11 @@ public class PaperConfig { + private static void fixEntityPositionDesync() { + fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); + } ++ ++ public static boolean enableBrigadierConsoleHighlighting = true; ++ public static boolean enableBrigadierConsoleCompletions = true; ++ private static void consoleSettings() { ++ enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); ++ enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +index a4070b59e261f0f1ac4beec47b11492f4724bf27..372a459bd08f79f10ffd1391ec492e37f1e8bb50 100644 +--- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java ++++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +@@ -1,5 +1,7 @@ + package com.destroystokyo.paper.console; + ++import com.destroystokyo.paper.PaperConfig; ++import io.papermc.paper.console.BrigadierCommandHighlighter; + import net.minecraft.server.dedicated.DedicatedServer; + import net.minecrell.terminalconsole.SimpleTerminalConsole; + import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; +@@ -16,11 +18,15 @@ public final class PaperConsole extends SimpleTerminalConsole { + + @Override + protected LineReader buildReader(LineReaderBuilder builder) { +- return super.buildReader(builder ++ builder + .appName("Paper") + .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) + .completer(new ConsoleCommandCompleter(this.server)) +- ); ++ .option(LineReader.Option.COMPLETE_IN_WORD, true); ++ if (PaperConfig.enableBrigadierConsoleHighlighting) { ++ builder.highlighter(new BrigadierCommandHighlighter(this.server, this.server.createCommandSourceStack())); ++ } ++ return super.buildReader(builder); + } + + @Override +diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2768028750fb9a95b3f3b409d047be14bb0083d5 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java +@@ -0,0 +1,95 @@ ++package io.papermc.paper.console; ++ ++import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion; ++import com.mojang.brigadier.CommandDispatcher; ++import com.mojang.brigadier.ParseResults; ++import com.mojang.brigadier.StringReader; ++import com.mojang.brigadier.suggestion.Suggestion; ++import io.papermc.paper.adventure.PaperAdventure; ++import net.minecraft.commands.CommandSourceStack; ++import net.minecraft.network.chat.ComponentUtils; ++import net.minecraft.server.dedicated.DedicatedServer; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jline.reader.Candidate; ++import org.jline.reader.LineReader; ++import org.jline.reader.ParsedLine; ++ ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++ ++import static com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion; ++ ++public final class BrigadierCommandCompleter { ++ private final CommandSourceStack commandSourceStack; ++ private final DedicatedServer server; ++ ++ public BrigadierCommandCompleter(final @NonNull DedicatedServer server, final @NonNull CommandSourceStack commandSourceStack) { ++ this.server = server; ++ this.commandSourceStack = commandSourceStack; ++ } ++ ++ public void complete(final @NonNull LineReader reader, final @NonNull ParsedLine line, final @NonNull List candidates, final @NonNull List existing) { ++ if (!com.destroystokyo.paper.PaperConfig.enableBrigadierConsoleCompletions) { ++ this.addCandidates(candidates, Collections.emptyList(), existing); ++ return; ++ } ++ final CommandDispatcher dispatcher = this.server.getCommands().dispatcher(); ++ final ParseResults results = dispatcher.parse(prepareStringReader(line.line()), this.commandSourceStack); ++ this.addCandidates( ++ candidates, ++ dispatcher.getCompletionSuggestions(results, line.cursor()).join().getList(), ++ existing ++ ); ++ } ++ ++ private void addCandidates( ++ final @NonNull List candidates, ++ final @NonNull List brigSuggestions, ++ final @NonNull List existing ++ ) { ++ final List completions = new ArrayList<>(); ++ brigSuggestions.forEach(it -> completions.add(toCompletion(it))); ++ for (final Completion completion : existing) { ++ if (completion.suggestion().isEmpty() || brigSuggestions.stream().anyMatch(it -> it.getText().equals(completion.suggestion()))) { ++ continue; ++ } ++ completions.add(completion); ++ } ++ for (final Completion completion : completions) { ++ if (completion.suggestion().isEmpty()) { ++ continue; ++ } ++ candidates.add(toCandidate(completion)); ++ } ++ } ++ ++ private static @NonNull Candidate toCandidate(final @NonNull Completion completion) { ++ final String suggestionText = completion.suggestion(); ++ final String suggestionTooltip = PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null); ++ return new Candidate( ++ suggestionText, ++ suggestionText, ++ null, ++ suggestionTooltip, ++ null, ++ null, ++ false ++ ); ++ } ++ ++ private static @NonNull Completion toCompletion(final @NonNull Suggestion suggestion) { ++ if (suggestion.getTooltip() == null) { ++ return completion(suggestion.getText()); ++ } ++ return completion(suggestion.getText(), PaperAdventure.asAdventure(ComponentUtils.fromMessage(suggestion.getTooltip()))); ++ } ++ ++ static @NonNull StringReader prepareStringReader(final @NonNull String line) { ++ final StringReader stringReader = new StringReader(line); ++ if (stringReader.canRead() && stringReader.peek() == '/') { ++ stringReader.skip(); ++ } ++ return stringReader; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..812027fb84e1b7825f2dd0fb6fa33831367c2dc0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java +@@ -0,0 +1,57 @@ ++package io.papermc.paper.console; ++ ++import com.mojang.brigadier.ParseResults; ++import com.mojang.brigadier.context.ParsedCommandNode; ++import com.mojang.brigadier.tree.LiteralCommandNode; ++import net.minecraft.commands.CommandSourceStack; ++import net.minecraft.server.dedicated.DedicatedServer; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jline.reader.Highlighter; ++import org.jline.reader.LineReader; ++import org.jline.utils.AttributedString; ++import org.jline.utils.AttributedStringBuilder; ++import org.jline.utils.AttributedStyle; ++ ++public final class BrigadierCommandHighlighter implements Highlighter { ++ private static final int[] COLORS = {AttributedStyle.CYAN, AttributedStyle.YELLOW, AttributedStyle.GREEN, AttributedStyle.MAGENTA, /* Client uses GOLD here, not BLUE, however there is no GOLD AttributedStyle. */ AttributedStyle.BLUE}; ++ private final CommandSourceStack commandSourceStack; ++ private final DedicatedServer server; ++ ++ public BrigadierCommandHighlighter(final @NonNull DedicatedServer server, final @NonNull CommandSourceStack commandSourceStack) { ++ this.server = server; ++ this.commandSourceStack = commandSourceStack; ++ } ++ ++ @Override ++ public AttributedString highlight(final @NonNull LineReader reader, final @NonNull String buffer) { ++ final AttributedStringBuilder builder = new AttributedStringBuilder(); ++ final ParseResults results = this.server.getCommands().dispatcher().parse(BrigadierCommandCompleter.prepareStringReader(buffer), this.commandSourceStack); ++ int pos = 0; ++ if (buffer.startsWith("/")) { ++ builder.append("/", AttributedStyle.DEFAULT); ++ pos = 1; ++ } ++ int component = -1; ++ for (final ParsedCommandNode node : results.getContext().getLastChild().getNodes()) { ++ if (node.getRange().getStart() >= buffer.length()) { ++ break; ++ } ++ final int start = node.getRange().getStart(); ++ final int end = Math.min(node.getRange().getEnd(), buffer.length()); ++ builder.append(buffer.substring(pos, start), AttributedStyle.DEFAULT); ++ if (node.getNode() instanceof LiteralCommandNode) { ++ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT); ++ } else { ++ if (++component >= COLORS.length) { ++ component = 0; ++ } ++ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT.foreground(COLORS[component])); ++ } ++ pos = end; ++ } ++ if (pos < buffer.length()) { ++ builder.append((buffer.substring(pos)), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)); ++ } ++ return builder.toAttributedString(); ++ } ++} +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index 5ed78383ce247ceb24cda0335dbeae293958055c..e2f18b5bf1e091fe5fd868520a6d1bcc2669c24c 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -440,7 +440,7 @@ public class Commands { + }; + } + +- public com.mojang.brigadier.CommandDispatcher getDispatcher() { ++ public com.mojang.brigadier.CommandDispatcher getDispatcher() { return this.dispatcher(); } public com.mojang.brigadier.CommandDispatcher dispatcher() { // Paper - OBFHELPER + return this.dispatcher; + } + +diff --git a/src/main/java/net/minecraft/network/chat/ComponentUtils.java b/src/main/java/net/minecraft/network/chat/ComponentUtils.java +index b5a59aed5d5cfbe0f75a8209b058b368b1f2b595..ed90c4348ca030d678251b0f9891d00153992f89 100644 +--- a/src/main/java/net/minecraft/network/chat/ComponentUtils.java ++++ b/src/main/java/net/minecraft/network/chat/ComponentUtils.java +@@ -90,7 +90,7 @@ public class ComponentUtils { + TextComponent chatcomponenttext = new TextComponent(""); + boolean flag = true; + +- for (Iterator iterator = elements.iterator(); iterator.hasNext(); flag = false) { ++ for (Iterator iterator = elements.iterator(); iterator.hasNext(); flag = false) { // Paper - decompile fix + T t0 = iterator.next(); + + if (!flag) { +@@ -108,7 +108,7 @@ public class ComponentUtils { + return new TranslatableComponent("chat.square_brackets", new Object[]{text}); + } + +- public static Component fromMessage(Message message) { ++ public static Component fromMessage(Message message) { return fromMessage(message); } public static Component fromMessage(final @org.checkerframework.checker.nullness.qual.NonNull Message message) { // Paper - OBFHELPER + return (Component) (message instanceof Component ? (Component) message : new TextComponent(message.getString())); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index dd8e87ad192c19743577bb95253a127072ea196c..eaad328d0d15ef450bb5a305828ce413d1eab53b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -18,9 +18,11 @@ import org.bukkit.event.server.TabCompleteEvent; + + public class ConsoleCommandCompleter implements Completer { + private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer ++ private final io.papermc.paper.console.BrigadierCommandCompleter brigadierCompleter; // Paper + + public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer + this.server = server; ++ this.brigadierCompleter = new io.papermc.paper.console.BrigadierCommandCompleter(this.server, this.server.createCommandSourceStack()); // Paper + } + + // Paper start - Change method signature for JLine update +@@ -64,7 +66,7 @@ public class ConsoleCommandCompleter implements Completer { + } + } + +- if (!completions.isEmpty()) { ++ if (false && !completions.isEmpty()) { + for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { + if (completion.suggestion().isEmpty()) { + continue; +@@ -80,6 +82,7 @@ public class ConsoleCommandCompleter implements Completer { + )); + } + } ++ this.addCompletions(reader, line, candidates, completions); + return; + } + +@@ -99,10 +102,12 @@ public class ConsoleCommandCompleter implements Completer { + try { + List offers = waitable.get(); + if (offers == null) { ++ this.addCompletions(reader, line, candidates, Collections.emptyList()); // Paper + return; // Paper - Method returns void + } + + // Paper start - JLine update ++ /* + for (String completion : offers) { + if (completion.isEmpty()) { + continue; +@@ -110,6 +115,8 @@ public class ConsoleCommandCompleter implements Completer { + + candidates.add(new Candidate(completion)); + } ++ */ ++ this.addCompletions(reader, line, candidates, offers.stream().map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::completion).collect(java.util.stream.Collectors.toList())); + // Paper end + + // Paper start - JLine handles cursor now +@@ -138,5 +145,9 @@ public class ConsoleCommandCompleter implements Completer { + } + return false; + } ++ ++ private void addCompletions(final LineReader reader, final ParsedLine line, final List candidates, final List existing) { ++ this.brigadierCompleter.complete(reader, line, candidates, existing); ++ } + // Paper end + } diff --git a/patches/server-remapped/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/patches/server-remapped/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch new file mode 100644 index 0000000000..a86a2c1b40 --- /dev/null +++ b/patches/server-remapped/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Fri, 19 Mar 2021 00:33:15 -0500 +Subject: [PATCH] Fix PlayerItemConsumeEvent cancelling properly + +When the active item is not cleared, the item is still readied +for use and will repeatedly trigger the PlayerItemConsumeEvent +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 8bc74878919ab7cf6a50d425da61f1b8a8b0ee44..37787a725725d22b0870dcab0f3bec8b94cfd130 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3348,6 +3348,7 @@ public abstract class LivingEntity extends Entity { + level.getCraftServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { ++ this.stopUsingItem(); // Paper - event is using an item, clear active item to reset its use + // Update client + ((ServerPlayer) this).getBukkitEntity().updateInventory(); + ((ServerPlayer) this).getBukkitEntity().updateScaledHealth(); diff --git a/patches/server-remapped/0703-Add-bypass-host-check.patch b/patches/server-remapped/0703-Add-bypass-host-check.patch new file mode 100644 index 0000000000..88f6d3d8dc --- /dev/null +++ b/patches/server-remapped/0703-Add-bypass-host-check.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 18 Apr 2021 21:27:01 +0100 +Subject: [PATCH] Add bypass host check + +Paper.bypassHostCheck + +Seriously, fix your firewalls. -.- + +diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index c648b73a4c478f9d8020274205d6684f7c7c416f..4e055a41de3ee410682cc05a3b883ac8babeb290 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -30,6 +30,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + private static final Component IGNORE_STATUS_REASON = new TextComponent("Ignoring status request"); + private final MinecraftServer server; + private final Connection connection; final Connection getNetworkManager() { return this.connection; } // Paper - OBFHELPER ++ private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper + + public ServerHandshakePacketListenerImpl(MinecraftServer server, Connection connection) { + this.server = server; +@@ -118,7 +119,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + // Spigot Start + //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! + String[] split = packet.hostName.split("\00"); +- if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { ++ if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper + packet.hostName = split[0]; + connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort()); + connection.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); diff --git a/patches/server-remapped/0704-don-t-throw-when-loading-invalid-TEs.patch b/patches/server-remapped/0704-don-t-throw-when-loading-invalid-TEs.patch new file mode 100644 index 0000000000..487cbc3ff9 --- /dev/null +++ b/patches/server-remapped/0704-don-t-throw-when-loading-invalid-TEs.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 20 Apr 2021 01:15:04 +0100 +Subject: [PATCH] don't throw when loading invalid TEs + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 05fa76c02ce61e26891ad995fe89e925ea086557..b7ebb213efd759253f0042f77e11f2a8102ea6ca 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.block.entity; + + import javax.annotation.Nullable; + import net.minecraft.CrashReportCategory; ++import net.minecraft.ResourceLocationException; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Registry; + import net.minecraft.nbt.CompoundTag; +@@ -133,7 +134,13 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + public static BlockEntity loadStatic(BlockState state, CompoundTag tag) { + String s = tag.getString("id"); + +- return (BlockEntity) Registry.BLOCK_ENTITY_TYPE.getOptional(new ResourceLocation(s)).map((tileentitytypes) -> { ++ // Paper ++ ResourceLocation minecraftKey = null; ++ try { ++ minecraftKey = new ResourceLocation(s); ++ } catch (ResourceLocationException ex) {} ++ // Paper end ++ return (BlockEntity) Registry.BLOCK_ENTITY_TYPE.getOptional(minecraftKey).map((tileentitytypes) -> { + try { + return tileentitytypes.create(); + } catch (Throwable throwable) { diff --git a/patches/server-remapped/0705-Set-area-affect-cloud-rotation.patch b/patches/server-remapped/0705-Set-area-affect-cloud-rotation.patch new file mode 100644 index 0000000000..f907ad7a6b --- /dev/null +++ b/patches/server-remapped/0705-Set-area-affect-cloud-rotation.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Mon, 5 Apr 2021 16:58:20 -0400 +Subject: [PATCH] Set area affect cloud rotation + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index b0212b2043ee5fd77c8876ef0b51ef91488712f0..b44e83d93bba579e439b93e5093350675137b070 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1959,6 +1959,7 @@ public class CraftWorld implements World { + entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(world); + } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { + entity = new net.minecraft.world.entity.AreaEffectCloud(world, x, y, z); ++ entity.moveTo(x, y, z, yaw, pitch); // Paper - Set area effect cloud Rotation + } else if (EvokerFangs.class.isAssignableFrom(clazz)) { + entity = new net.minecraft.world.entity.projectile.EvokerFangs(world, x, y, z, (float) Math.toRadians(yaw), 0, null); + } diff --git a/patches/server-remapped/0706-add-isDeeplySleeping-to-HumanEntity.patch b/patches/server-remapped/0706-add-isDeeplySleeping-to-HumanEntity.patch new file mode 100644 index 0000000000..75f3e9118b --- /dev/null +++ b/patches/server-remapped/0706-add-isDeeplySleeping-to-HumanEntity.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 8 Apr 2021 17:36:10 -0700 +Subject: [PATCH] add isDeeplySleeping 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 aceb57c93c91730345f49f78838780c41ce2dcef..0559f2cfab817e989c02ce2d13bcdabb8ad3b82b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -122,6 +122,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + } + } + ++ // Paper start ++ @Override ++ public boolean isDeeplySleeping() { ++ return getHandle().isSleepingLongEnough(); ++ } ++ // Paper end ++ + @Override + public int getSleepTicks() { + return getHandle().sleepCounter; diff --git a/patches/server-remapped/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch b/patches/server-remapped/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch new file mode 100644 index 0000000000..0672393254 --- /dev/null +++ b/patches/server-remapped/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch @@ -0,0 +1,113 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alphaesia +Date: Fri, 23 Apr 2021 09:57:56 +1200 +Subject: [PATCH] Fix duplicating /give items on item drop cancel + +Fixes SPIGOT-2942 (Give command fires PlayerDropItemEvent, cancelling it causes item duplication). + +For every stack of items to give, /give puts the item stack straight +into the player's inventory. However, it also summons a "fake item" +at the player's location. When the PlayerDropItemEvent for this fake +item is cancelled, the server attempts to put the item back into the +player's inventory. The result is that the fake item, which is never +meant to be obtained, is combined with the real items injected directly +into the player's inventory. This means more items than the amount +specified in /give are given to the player - one for every stack of +items given. (e.g. /give @s dirt 1 gives you 2 dirt). + +While this isn't a big issue for general building usage, it can affect +e.g. adventure maps where the number of items the player receives is +important (and you want to restrict the player from throwing items). + +If there are any overflow items that didn't make it into the inventory +(insufficient space), those items are dropped as a real item instead +of a fake one. While cancelling this drop would also result in the +server attempting to put those items into the inventory, since it is +full this has no effect. + +Just ignoring cancellation of the PlayerDropItemEvent seems like the +cleanest and least intrusive way to fix it. + +diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java +index a6259e9160f291cf527a4ea5533a2e5530471874..3b8a7b9bdd2445afa93e4f2dc971a1d252c1463a 100644 +--- a/src/main/java/net/minecraft/server/commands/GiveCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java +@@ -49,7 +49,7 @@ public class GiveCommand { + + if (flag && itemstack.isEmpty()) { + itemstack.setCount(1); +- entityitem = entityplayer.drop(itemstack, false); ++ entityitem = entityplayer.drop(itemstack, false, false, true); // Paper - Fix duplicating /give items on item drop cancel + if (entityitem != null) { + entityitem.makeFakeItem(); + } +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 4817b8ab259d348b48bc325d34ba9351ffe951df..cfb9bd6b9863a0f6f0f50181b7553adce90cfebe 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -639,7 +639,14 @@ public abstract class Player extends LivingEntity { + + @Nullable + public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership) { +- if (stack.isEmpty()) { ++ // Paper start - Fix duplicating /give items on item drop cancel ++ return this.drop(stack, throwRandomly, retainOwnership, false); ++ } ++ ++ @Nullable ++ public ItemEntity drop(ItemStack itemstack, boolean flag, boolean flag1, boolean alwaysSucceed) { ++ // Paper end ++ if (itemstack.isEmpty()) { + return null; + } else { + if (this.level.isClientSide) { +@@ -647,17 +654,17 @@ public abstract class Player extends LivingEntity { + } + + double d0 = this.getEyeY() - 0.30000001192092896D; +- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), d0, this.getZ(), stack); ++ ItemEntity entityitem = new ItemEntity(this.level, this.getX(), d0, this.getZ(), itemstack); + + entityitem.setPickUpDelay(40); +- if (retainOwnership) { ++ if (flag1) { + entityitem.setThrower(this.getUUID()); + } + + float f; + float f1; + +- if (throwRandomly) { ++ if (flag) { + f = this.random.nextFloat() * 0.5F; + f1 = this.random.nextFloat() * 6.2831855F; + entityitem.setDeltaMovement((double) (-Mth.sin(f1) * f), 0.20000000298023224D, (double) (Mth.cos(f1) * f)); +@@ -680,12 +687,12 @@ public abstract class Player extends LivingEntity { + PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); + this.level.getCraftServer().getPluginManager().callEvent(event); + +- if (event.isCancelled()) { ++ if (event.isCancelled() && !alwaysSucceed) { // Paper - Fix duplicating /give items on item drop cancel + org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); +- if (retainOwnership && (cur == null || cur.getAmount() == 0)) { ++ if (flag1 && (cur == null || cur.getAmount() == 0)) { + // The complete stack was dropped + player.getInventory().setItemInHand(drop.getItemStack()); +- } else if (retainOwnership && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { ++ } else if (flag1 && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { + // Only one item is dropped + cur.setAmount(cur.getAmount() + 1); + player.getInventory().setItemInHand(cur); +@@ -697,9 +704,9 @@ public abstract class Player extends LivingEntity { + } + // CraftBukkit end + // Paper start - remove player from map on drop +- if (stack.getItem() == Items.FILLED_MAP) { +- MapItemSavedData worldmap = MapItem.getOrCreateSavedData(stack, this.level); +- worldmap.updateSeenPlayers(this, stack); ++ if (itemstack.getItem() == Items.FILLED_MAP) { ++ MapItemSavedData worldmap = MapItem.getOrCreateSavedData(itemstack, this.level); ++ worldmap.updateSeenPlayers(this, itemstack); + } + // Paper end + diff --git a/patches/server-remapped/0708-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/server-remapped/0708-add-consumeFuel-to-FurnaceBurnEvent.patch new file mode 100644 index 0000000000..f9cc308842 --- /dev/null +++ b/patches/server-remapped/0708-add-consumeFuel-to-FurnaceBurnEvent.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 22 Apr 2021 16:45:28 -0700 +Subject: [PATCH] add consumeFuel to FurnaceBurnEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 2dcabfc765cbf6341546a7e2c48156fd921fcc82..6e4feb2280021c26dbbfb92feb08c95165e126fe 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -329,7 +329,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + if (this.isLit() && furnaceBurnEvent.isBurning()) { + // CraftBukkit end + flag1 = true; +- if (!itemstack.isEmpty()) { ++ if (!itemstack.isEmpty() && furnaceBurnEvent.willConsumeFuel()) { // Paper + Item item = itemstack.getItem(); + + itemstack.shrink(1); diff --git a/patches/server-remapped/0709-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/server-remapped/0709-add-get-set-drop-chance-to-EntityEquipment.patch new file mode 100644 index 0000000000..c18ac532d5 --- /dev/null +++ b/patches/server-remapped/0709-add-get-set-drop-chance-to-EntityEquipment.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 22 Apr 2021 00:28:11 -0700 +Subject: [PATCH] add get-set drop chance to EntityEquipment + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java +index e8d6e1abf29a5c50e1cafa01c602f36596d42ecf..9841b4ed648b95272feee45e6f1e8fd9399c322e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java +@@ -244,6 +244,17 @@ public class CraftEntityEquipment implements EntityEquipment { + public void setBootsDropChance(float chance) { + setDropChance(net.minecraft.world.entity.EquipmentSlot.FEET, chance); + } ++ // Paper start ++ @Override ++ public float getDropChance(EquipmentSlot slot) { ++ return getDropChance(CraftEquipmentSlot.getNMS(slot)); ++ } ++ ++ @Override ++ public void setDropChance(EquipmentSlot slot, float chance) { ++ setDropChance(CraftEquipmentSlot.getNMS(slot), chance); ++ } ++ // Paper end + + private void setDropChance(net.minecraft.world.entity.EquipmentSlot slot, float chance) { + if (slot == net.minecraft.world.entity.EquipmentSlot.MAINHAND || slot == net.minecraft.world.entity.EquipmentSlot.OFFHAND) { +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +index 7a8181f559cc3c92c3b3aa2ff8eda515719eba08..c326a75728fffbab301654afd94b6839c009fe93 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +@@ -354,4 +354,15 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i + public void setBootsDropChance(float chance) { + throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); + } ++ // Paper start ++ @Override ++ public float getDropChance(EquipmentSlot slot) { ++ return 1; ++ } ++ ++ @Override ++ public void setDropChance(EquipmentSlot slot, float chance) { ++ throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0710-fix-PigZombieAngerEvent-cancellation.patch b/patches/server-remapped/0710-fix-PigZombieAngerEvent-cancellation.patch new file mode 100644 index 0000000000..5d4feaac2c --- /dev/null +++ b/patches/server-remapped/0710-fix-PigZombieAngerEvent-cancellation.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Thu, 18 Mar 2021 21:38:01 +0100 +Subject: [PATCH] fix PigZombieAngerEvent cancellation + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +index f85dfd8b57cf81ad7c6b12753fdd42e93f772f9e..16f4dbfd21a287bad3e10c174fa77a1cac771afa 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +@@ -28,6 +28,7 @@ public abstract class Goal { + + public void start() { this.start(); } public void start() {} // Paper - OBFHELPER + ++ public final void onTaskResetObfHelper() { stop(); } // Paper - OBFHELPER + public void stop() { + onTaskReset(); // Paper + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +index d1cbbfbf9d3c5e65785aad00c2292245a5de1422..d67a50740b1c6d4ecd49a5541d24d1e4bacb8887 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +@@ -49,6 +49,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + private UUID persistentAngerTarget; + private static final IntRange ALERT_INTERVAL = TimeUtil.rangeOfSeconds(4, 6); + private int ticksUntilNextAlert; ++ private HurtByTargetGoal pathfinderGoalHurtByTarget; // Paper + + public ZombifiedPiglin(EntityType type, Level world) { + super(type, world); +@@ -69,7 +70,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + protected void addBehaviourGoals() { + this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers(new Class[0])); // CraftBukkit - decompile error ++ this.targetSelector.addGoal(1, pathfinderGoalHurtByTarget = new HurtByTargetGoal(this).setAlertOthers(new Class[0])); // CraftBukkit - decompile error // Paper - assign field + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); + this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true)); + } +@@ -172,6 +173,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + this.level.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.setPersistentAngerTarget(null); ++ pathfinderGoalHurtByTarget.onTaskResetObfHelper(); // Paper - clear goalTargets to fix cancellation + return; + } + this.setRemainingPersistentAngerTime(event.getNewAnger()); diff --git a/patches/server-remapped/0711-Fix-checkReach-check-for-Shulker-boxes.patch b/patches/server-remapped/0711-Fix-checkReach-check-for-Shulker-boxes.patch new file mode 100644 index 0000000000..38d7d768a3 --- /dev/null +++ b/patches/server-remapped/0711-Fix-checkReach-check-for-Shulker-boxes.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sun, 4 Apr 2021 14:25:04 -0400 +Subject: [PATCH] Fix checkReach check for Shulker boxes + + +diff --git a/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java b/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java +index c40518b0e4ad2b043a9acc858413648d6419f3a3..4b7814a31deeef31e877cee96f0d51b348e7a281 100644 +--- a/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java +@@ -65,6 +65,7 @@ public class ShulkerBoxMenu extends AbstractContainerMenu { + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // Paper - Add reachable override for ContainerShulkerBox + return this.container.stillValid(player); + } + diff --git a/patches/server-remapped/0712-fix-PlayerItemHeldEvent-firing-twice.patch b/patches/server-remapped/0712-fix-PlayerItemHeldEvent-firing-twice.patch new file mode 100644 index 0000000000..094351a8ff --- /dev/null +++ b/patches/server-remapped/0712-fix-PlayerItemHeldEvent-firing-twice.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Thu, 22 Apr 2021 19:02:07 -0700 +Subject: [PATCH] fix PlayerItemHeldEvent firing twice + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java +index 68026536cfc26f07ca99ee9e76fd74b4ed4a995c..848fb02988b0fb319655f790112274ac2a437d25 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java +@@ -24,6 +24,7 @@ public class ServerboundSetCarriedItemPacket implements Packet= 0 && packet.getSlot() < Inventory.getSelectionSize()) { ++ if (packet.getItemInHandIndex() == this.player.inventory.selected) { return; } // Paper - don't fire itemheldevent when there wasn't a slot change + PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.selected, packet.getSlot()); + this.craftServer.getPluginManager().callEvent(event); + if (event.isCancelled()) { diff --git a/patches/server-remapped/0713-Added-PlayerDeepSleepEvent.patch b/patches/server-remapped/0713-Added-PlayerDeepSleepEvent.patch new file mode 100644 index 0000000000..14d231bf04 --- /dev/null +++ b/patches/server-remapped/0713-Added-PlayerDeepSleepEvent.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 21 Apr 2021 15:58:19 -0700 +Subject: [PATCH] Added 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 cfb9bd6b9863a0f6f0f50181b7553adce90cfebe..c0d2ca1daca0c0c6f21334bc4d9d039440efc453 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -232,6 +232,11 @@ public abstract class Player extends LivingEntity { + + if (this.isSleeping()) { + ++this.sleepCounter; ++ // Paper start ++ if (this.sleepCounter == 100) { ++ if (!new io.papermc.paper.event.player.PlayerDeepSleepEvent((org.bukkit.entity.Player) getBukkitEntity()).callEvent()) { this.sleepCounter = Integer.MIN_VALUE; } ++ } ++ // Paper end + if (this.sleepCounter > 100) { + this.sleepCounter = 100; + } diff --git a/patches/server-remapped/0714-More-World-API.patch b/patches/server-remapped/0714-More-World-API.patch new file mode 100644 index 0000000000..37cb7379d4 --- /dev/null +++ b/patches/server-remapped/0714-More-World-API.patch @@ -0,0 +1,146 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 7 Jul 2020 10:52:34 -0700 +Subject: [PATCH] More World API + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index a7553a856b9c99bee8f75d514b97cfab952bfd33..511e6a941d441c55a4b38660f0f7f8c47fa689dd 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1863,6 +1863,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return !this.worldDataServer.worldGenSettings().generateFeatures() ? null : this.getChunkSource().getGenerator().findNearestMapFeature(this, feature, pos, radius, skipExistingChunks); // CraftBukkit + } + ++ public BlockPos getNearestBiome(Biome biomeBase, BlockPos blockPosition, int radius, int step) { return this.findNearestBiome(biomeBase, blockPosition, radius, step); } // Paper - OBFHELPER + @Nullable + public BlockPos findNearestBiome(Biome biome, BlockPos pos, int radius, int j) { + return this.getChunkSource().getGenerator().getBiomeSource().findBiomeHorizontal(pos.getX(), pos.getY(), pos.getZ(), radius, j, (biomebase1) -> { +@@ -1885,6 +1886,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return this.noSave; + } + ++ public RegistryAccess getWorldCustomRegistry() { return registryAccess(); } // Paper - OBFHELPER + @Override + public RegistryAccess registryAccess() { + return this.server.registryAccess(); +diff --git a/src/main/java/net/minecraft/world/level/dimension/DimensionType.java b/src/main/java/net/minecraft/world/level/dimension/DimensionType.java +index 7dead90a0d77e936816c2a54fe70c87d92dc8e5b..fb2bdfbeb44de6ce967af2deb4738972b44dcf44 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/DimensionType.java ++++ b/src/main/java/net/minecraft/world/level/dimension/DimensionType.java +@@ -142,10 +142,10 @@ public class DimensionType { + public static RegistryAccess.RegistryHolder registerBuiltin(RegistryAccess.RegistryHolder registryManager) { + WritableRegistry iregistrywritable = registryManager.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); + +- iregistrywritable.register(DimensionType.OVERWORLD_LOCATION, (Object) DimensionType.DEFAULT_OVERWORLD, Lifecycle.stable()); +- iregistrywritable.register(DimensionType.OVERWORLD_CAVES_LOCATION, (Object) DimensionType.DEFAULT_OVERWORLD_CAVES, Lifecycle.stable()); +- iregistrywritable.register(DimensionType.NETHER_LOCATION, (Object) DimensionType.DEFAULT_NETHER, Lifecycle.stable()); +- iregistrywritable.register(DimensionType.END_LOCATION, (Object) DimensionType.DEFAULT_END, Lifecycle.stable()); ++ iregistrywritable.register(DimensionType.OVERWORLD_LOCATION, DimensionType.DEFAULT_OVERWORLD, Lifecycle.stable()); // Paper - decompile fix ++ iregistrywritable.register(DimensionType.OVERWORLD_CAVES_LOCATION, DimensionType.DEFAULT_OVERWORLD_CAVES, Lifecycle.stable()); // Paper - decompile fix ++ iregistrywritable.register(DimensionType.NETHER_LOCATION, DimensionType.DEFAULT_NETHER, Lifecycle.stable()); // Paper - decompile fix ++ iregistrywritable.register(DimensionType.END_LOCATION, DimensionType.DEFAULT_END, Lifecycle.stable()); // Paper - decompile fix + return registryManager; + } + +@@ -164,10 +164,10 @@ public class DimensionType { + public static MappedRegistry defaultDimensions(Registry dimensionRegistry, Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed) { + MappedRegistry registrymaterials = new MappedRegistry<>(Registry.LEVEL_STEM_REGISTRY, Lifecycle.experimental()); + +- registrymaterials.register(LevelStem.NETHER, (Object) (new LevelStem(() -> { ++ registrymaterials.register(LevelStem.NETHER, (new LevelStem(() -> { // Paper - decompile fix + return (DimensionType) dimensionRegistry.getOrThrow(DimensionType.NETHER_LOCATION); + }, defaultNetherGenerator(biomeRegistry, chunkGeneratorSettingsRegistry, seed))), Lifecycle.stable()); +- registrymaterials.register(LevelStem.END, (Object) (new LevelStem(() -> { ++ registrymaterials.register(LevelStem.END, (new LevelStem(() -> { // Paper - decompile fix + return (DimensionType) dimensionRegistry.getOrThrow(DimensionType.END_LOCATION); + }, defaultEndGenerator(biomeRegistry, chunkGeneratorSettingsRegistry, seed))), Lifecycle.stable()); + return registrymaterials; +@@ -256,6 +256,7 @@ public class DimensionType { + return this.brightnessRamp[i]; + } + ++ public Tag getInfiniburnTag() { return infiniburn(); } // Paper - OBFHELPER + public Tag infiniburn() { + Tag tag = BlockTags.getAllTags().getTag(this.infiniburn); + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index b44e83d93bba579e439b93e5093350675137b070..a1fa2d5e00bd125abd38a00e0bc3936f2fb8186f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2515,6 +2515,75 @@ public class CraftWorld implements World { + return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); + } + ++ // Paper start ++ @Override ++ public Location locateNearestBiome(Location origin, Biome biome, int radius) { ++ return this.locateNearestBiome(origin, biome, radius, 8); ++ } ++ ++ @Override ++ public Location locateNearestBiome(Location origin, Biome biome, int radius, int step) { ++ BlockPos originPos = new BlockPos(origin.getX(), origin.getY(), origin.getZ()); ++ BlockPos nearest = getHandle().getNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().getWorldCustomRegistry().registryOrThrow(Registry.BIOME_REGISTRY), biome), originPos, radius, step); ++ return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); ++ } ++ ++ @Override ++ public boolean isUltrawarm() { ++ return getHandle().dimensionType().ultraWarm(); ++ } ++ ++ @Override ++ public boolean isNatural() { ++ return getHandle().dimensionType().natural(); ++ } ++ ++ @Override ++ public double getCoordinateScale() { ++ return getHandle().dimensionType().coordinateScale(); ++ } ++ ++ @Override ++ public boolean hasSkylight() { ++ return getHandle().dimensionType().hasSkyLight(); ++ } ++ ++ @Override ++ public boolean hasBedrockCeiling() { ++ return getHandle().dimensionType().hasSkyLight(); ++ } ++ ++ @Override ++ public boolean isPiglinSafe() { ++ return getHandle().dimensionType().piglinSafe(); ++ } ++ ++ @Override ++ public boolean doesBedWork() { ++ return getHandle().dimensionType().bedWorks(); ++ } ++ ++ @Override ++ public boolean doesRespawnAnchorWork() { ++ return getHandle().dimensionType().respawnAnchorWorks(); ++ } ++ ++ @Override ++ public boolean hasRaids() { ++ return getHandle().dimensionType().hasRaids(); ++ } ++ ++ @Override ++ public boolean isFixedTime() { ++ return getHandle().dimensionType().hasFixedTime(); ++ } ++ ++ @Override ++ public Collection getInfiniburn() { ++ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().dimensionType().getInfiniburnTag().getTagged().iterator(), CraftMagicNumbers::getMaterial)); ++ } ++ // Paper end ++ + @Override + public Raid locateNearestRaid(Location location, int radius) { + Validate.notNull(location, "Location cannot be null"); diff --git a/patches/server-remapped/0715-Added-PlayerBedFailEnterEvent.patch b/patches/server-remapped/0715-Added-PlayerBedFailEnterEvent.patch new file mode 100644 index 0000000000..87c355341c --- /dev/null +++ b/patches/server-remapped/0715-Added-PlayerBedFailEnterEvent.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 24 Dec 2020 12:27:41 -0800 +Subject: [PATCH] Added PlayerBedFailEnterEvent + + +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 c0d2ca1daca0c0c6f21334bc4d9d039440efc453..007d9476943f5a9c75554927df941bda0f7dd6d5 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -2230,6 +2230,7 @@ public abstract class Player extends LivingEntity { + this.message = ichatbasecomponent; + } + ++ public @Nullable Component getChatComponent() { return this.getMessage(); }; // Paper - OBFHELPER + @Nullable + public Component getMessage() { + return this.message; +diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java +index 9dcbc0f741f5980305ae031daac70c7933bc6862..9dcf145b6d1a93785150d268828bca4bb31984c8 100644 +--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java +@@ -43,6 +43,8 @@ import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; + import org.apache.commons.lang3.ArrayUtils; ++import io.papermc.paper.event.player.PlayerBedFailEnterEvent; // Paper ++import io.papermc.paper.adventure.PaperAdventure; // Paper + + public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock { + +@@ -101,14 +103,23 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock + BlockPos finalblockposition = pos; + // CraftBukkit end + player.startSleepInBed(pos).ifLeft((entityhuman_enumbedresult) -> { ++ // Paper start - PlayerBedFailEnterEvent ++ if (entityhuman_enumbedresult != null) { ++ PlayerBedFailEnterEvent event = new PlayerBedFailEnterEvent((org.bukkit.entity.Player) player.getBukkitEntity(), PlayerBedFailEnterEvent.FailReason.VALUES[entityhuman_enumbedresult.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(world, finalblockposition), entityhuman_enumbedresult == Player.BedSleepingProblem.NOT_POSSIBLE_HERE, PaperAdventure.asAdventure(entityhuman_enumbedresult.getChatComponent())); ++ if (!event.callEvent()) { ++ return; ++ } ++ // Paper end + // CraftBukkit start - handling bed explosion from below here +- if (entityhuman_enumbedresult == Player.BedSleepingProblem.NOT_POSSIBLE_HERE) { ++ if (event.getWillExplode()) { // Paper + this.explodeBed(finaliblockdata, world, finalblockposition); + } else + // CraftBukkit end + if (entityhuman_enumbedresult != null) { +- player.displayClientMessage(entityhuman_enumbedresult.getMessage(), true); ++ final net.kyori.adventure.text.Component message = event.getMessage(); // Paper ++ if(message != null) player.displayClientMessage(PaperAdventure.asVanilla(message), true); // Paper + } ++ } // Paper + + }); + return InteractionResult.SUCCESS; diff --git a/patches/server-remapped/0716-Implement-methods-to-convert-between-Component-and-B.patch b/patches/server-remapped/0716-Implement-methods-to-convert-between-Component-and-B.patch new file mode 100644 index 0000000000..e796b62074 --- /dev/null +++ b/patches/server-remapped/0716-Implement-methods-to-convert-between-Component-and-B.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Sat, 24 Apr 2021 02:09:32 -0700 +Subject: [PATCH] Implement methods to convert between Component and + Brigadier's Message + + +diff --git a/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..dd6012b6a097575b2d1471be5069eccee4537c0a +--- /dev/null ++++ b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java +@@ -0,0 +1,30 @@ ++package io.papermc.paper.brigadier; ++ ++import com.mojang.brigadier.Message; ++import io.papermc.paper.adventure.PaperAdventure; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.ComponentLike; ++import net.minecraft.network.chat.ComponentUtils; ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++import static java.util.Objects.requireNonNull; ++ ++public enum PaperBrigadierProviderImpl implements PaperBrigadierProvider { ++ INSTANCE; ++ ++ PaperBrigadierProviderImpl() { ++ PaperBrigadierProvider.initialize(this); ++ } ++ ++ @Override ++ public @NonNull Message message(final @NonNull ComponentLike componentLike) { ++ requireNonNull(componentLike, "componentLike"); ++ return PaperAdventure.asVanilla(componentLike.asComponent()); ++ } ++ ++ @Override ++ public @NonNull Component componentFromMessage(final @NonNull Message message) { ++ requireNonNull(message, "message"); ++ return PaperAdventure.asAdventure(ComponentUtils.fromMessage(message)); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index c2947313cc0eda3247fb4b20ddd1d0b86c37c50a..0198268bc614b190cd84f625a62f6c55247a01c8 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -210,6 +210,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } + com.destroystokyo.paper.PaperConfig.registerCommands(); + com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now ++ io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider + // Paper end + + this.setPvpAllowed(dedicatedserverproperties.pvp); diff --git a/patches/server-remapped/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/patches/server-remapped/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch new file mode 100644 index 0000000000..cf90fd18e8 --- /dev/null +++ b/patches/server-remapped/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Fri, 23 Apr 2021 22:42:42 +0100 +Subject: [PATCH] Fix anchor respawn acting as a bed respawn from the end + portal + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 23cfaf5c432221f2d1afe37ba657f723d6d21a73..a4e897171ce05736bcead319b7fda74d2b02fd2e 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -867,6 +867,7 @@ public abstract class PlayerList { + + // Paper start + boolean isBedSpawn = false; ++ boolean isAnchorSpawn = false; + boolean isRespawn = false; + boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 + // Paper end +@@ -887,6 +888,7 @@ public abstract class PlayerList { + if (optional.isPresent()) { + BlockState iblockdata = worldserver1.getBlockState(blockposition); + boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); ++ isAnchorSpawn = flag3; // Paper - Fix anchor respawn acting as a bed respawn from the end portal + Vec3 vec3d = (Vec3) optional.get(); + float f1; + +@@ -914,7 +916,7 @@ public abstract class PlayerList { + } + + Player respawnPlayer = cserver.getPlayer(entityplayer1); +- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag2, flag2); ++ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal + cserver.getPluginManager().callEvent(respawnEvent); + // Spigot Start + if (entityplayer.connection.isDisconnected()) { diff --git a/patches/server-remapped/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/server-remapped/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch new file mode 100644 index 0000000000..b0c5ab3263 --- /dev/null +++ b/patches/server-remapped/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 22 Apr 2021 17:17:47 -0700 +Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 5b0eb8744dba5df6f16bafd6d907cd1efd508fe6..a0e69cac7699ddc318057c8016e329850d3baa26 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2440,7 +2440,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + case PERFORM_RESPAWN: + if (this.player.wonGame) { + this.player.wonGame = false; +- this.player = this.server.getPlayerList().respawn(this.player, true); ++ this.player = this.server.getPlayerList().moveToWorld(this.player, this.server.getLevel(this.player.getRespawnDimension()), true, null, true, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); // Paper - add isEndCreditsRespawn argument + CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD); + } else { + if (this.player.getHealth() > 0.0F) { +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index a4e897171ce05736bcead319b7fda74d2b02fd2e..6011b43ae8a858f88b8fcf6dc0bf147024a4742c 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -816,7 +816,13 @@ public abstract class PlayerList { + return this.moveToWorld(player, this.server.getLevel(player.getRespawnDimension()), alive, null, true); + } + ++ // Paper start + public ServerPlayer moveToWorld(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation) { ++ return moveToWorld(entityplayer, worldserver, flag, location, avoidSuffocation, new org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag[0]); ++ } ++ ++ public ServerPlayer moveToWorld(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag...respawnFlags) { ++ // Paper end + entityplayer.stopRiding(); // CraftBukkit + this.players.remove(entityplayer); + this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot +@@ -916,7 +922,7 @@ public abstract class PlayerList { + } + + Player respawnPlayer = cserver.getPlayer(entityplayer1); +- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal ++ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn, com.google.common.collect.ImmutableSet.builder().add(respawnFlags)); // Paper - Fix anchor respawn acting as a bed respawn from the end portal + cserver.getPluginManager().callEvent(respawnEvent); + // Spigot Start + if (entityplayer.connection.isDisconnected()) { diff --git a/patches/server-remapped/0719-Introduce-beacon-activation-deactivation-events.patch b/patches/server-remapped/0719-Introduce-beacon-activation-deactivation-events.patch new file mode 100644 index 0000000000..57b84d6df6 --- /dev/null +++ b/patches/server-remapped/0719-Introduce-beacon-activation-deactivation-events.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spyridon Pagkalos +Date: Thu, 25 Mar 2021 20:28:04 +0200 +Subject: [PATCH] Introduce beacon activation/deactivation events + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +index fed29e5707e2a7f64159d284c52647dd91e1948e..7025a27c25f8640df06a3c65c2086059769870b5 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -199,6 +199,15 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + this.playSound(SoundEvents.BEACON_AMBIENT); + } + } ++ // Paper start - beacon activation/deactivation events ++ if (!(i1 > 0) && this.levels > 0) { ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); ++ new io.papermc.paper.event.block.BeaconActivatedEvent(block).callEvent(); ++ } else if (i1 > 0 && !(this.levels > 0)) { ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); ++ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); ++ } ++ // Paper end + + if (this.lastCheckY >= l) { + this.lastCheckY = -1; +@@ -255,6 +264,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + + @Override + public void setRemoved() { ++ // Paper start - BeaconDeactivatedEvent ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); ++ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); ++ // Paper end + this.playSound(SoundEvents.BEACON_DEACTIVATE); + super.setRemoved(); + } diff --git a/patches/server-remapped/0720-Add-Channel-initialization-listeners.patch b/patches/server-remapped/0720-Add-Channel-initialization-listeners.patch new file mode 100644 index 0000000000..72cbb09b5a --- /dev/null +++ b/patches/server-remapped/0720-Add-Channel-initialization-listeners.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Thu, 29 Apr 2021 21:19:33 +0200 +Subject: [PATCH] Add Channel initialization listeners + + +diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java +new file mode 100644 +index 0000000000000000000000000000000000000000..88099df34c2d74daba9645aadf65b446ca795a91 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java +@@ -0,0 +1,15 @@ ++package io.papermc.paper.network; ++ ++import io.netty.channel.Channel; ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++/** ++ * Internal API to register channel initialization listeners. ++ *

    ++ * This is not officially supported API and we make no guarantees to the existence or state of this interface. ++ */ ++@FunctionalInterface ++public interface ChannelInitializeListener { ++ ++ void afterInitChannel(@NonNull Channel channel); ++} +diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..30e62719e0a83525daa33cf41cb61df360c0e046 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java +@@ -0,0 +1,74 @@ ++package io.papermc.paper.network; ++ ++import io.netty.channel.Channel; ++import net.kyori.adventure.key.Key; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++ ++import java.util.Collections; ++import java.util.HashMap; ++import java.util.Map; ++ ++/** ++ * Internal API to register channel initialization listeners. ++ *

    ++ * This is not officially supported API and we make no guarantees to the existence or state of this class. ++ */ ++public final class ChannelInitializeListenerHolder { ++ ++ private static final Map LISTENERS = new HashMap<>(); ++ private static final Map IMMUTABLE_VIEW = Collections.unmodifiableMap(LISTENERS); ++ ++ private ChannelInitializeListenerHolder() { ++ } ++ ++ /** ++ * Registers whether an initialization listener is registered under the given key. ++ * ++ * @param key key ++ * @return whether an initialization listener is registered under the given key ++ */ ++ public static boolean hasListener(@NonNull Key key) { ++ return LISTENERS.containsKey(key); ++ } ++ ++ /** ++ * Registers a channel initialization listener called after ServerConnection is initialized. ++ * ++ * @param key key ++ * @param listener initialization listeners ++ */ ++ public static void addListener(@NonNull Key key, @NonNull ChannelInitializeListener listener) { ++ LISTENERS.put(key, listener); ++ } ++ ++ /** ++ * Removes and returns an initialization listener registered by the given key if present. ++ * ++ * @param key key ++ * @return removed initialization listener if present ++ */ ++ public static @Nullable ChannelInitializeListener removeListener(@NonNull Key key) { ++ return LISTENERS.remove(key); ++ } ++ ++ /** ++ * Returns an immutable map of registered initialization listeners. ++ * ++ * @return immutable map of registered initialization listeners ++ */ ++ public static @NonNull Map getListeners() { ++ return IMMUTABLE_VIEW; ++ } ++ ++ /** ++ * Calls the registered listeners with the given channel. ++ * ++ * @param channel channel ++ */ ++ public static void callListeners(@NonNull Channel channel) { ++ for (ChannelInitializeListener listener : LISTENERS.values()) { ++ listener.afterInitChannel(channel); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +index d46910cfdc0aef046a0c79731a85d381953c328a..bcc19d0a4b6c5f683dc416e27a13705b57213d21 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +@@ -104,6 +104,7 @@ public class ServerConnectionListener { + pending.add((Connection) object); // Paper + channel.pipeline().addLast("packet_handler", (ChannelHandler) object); + ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); ++ io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper + } + }).group((EventLoopGroup) lazyinitvar.get()).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit + } diff --git a/patches/server-remapped/0721-Send-empty-commands-if-tab-completion-is-disabled.patch b/patches/server-remapped/0721-Send-empty-commands-if-tab-completion-is-disabled.patch new file mode 100644 index 0000000000..de0a65c719 --- /dev/null +++ b/patches/server-remapped/0721-Send-empty-commands-if-tab-completion-is-disabled.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Mon, 26 Apr 2021 01:27:08 +0100 +Subject: [PATCH] Send empty commands if tab completion is disabled + + +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index e2f18b5bf1e091fe5fd868520a6d1bcc2669c24c..1d880a80348527d036b6f8b04f7dd1c4a479fcfd 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -327,7 +327,12 @@ public class Commands { + } + + public void sendCommands(ServerPlayer player) { +- if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot ++ // Paper start - Send empty commands if tab completion is disabled ++ if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) { //return; // Spigot ++ player.connection.send(new ClientboundCommandsPacket(new RootCommandNode<>())); ++ return; ++ } ++ // Paper end + // CraftBukkit start + // Register Vanilla commands into builtRoot as before + // Paper start - Async command map building diff --git a/patches/server-remapped/0722-Add-more-WanderingTrader-API.patch b/patches/server-remapped/0722-Add-more-WanderingTrader-API.patch new file mode 100644 index 0000000000..b99c0c4512 --- /dev/null +++ b/patches/server-remapped/0722-Add-more-WanderingTrader-API.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Thu, 6 May 2021 14:56:43 +0100 +Subject: [PATCH] Add more WanderingTrader API + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +index 04c4cca4be8886feb59f180915977b77f9c7dde8..22a695ee3f6c60d484285f1b441b809da61f2436 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -57,6 +57,10 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + @Nullable + private BlockPos wanderTarget; + private int despawnDelay; ++ // Paper start - Add more WanderingTrader API ++ public boolean canDrinkPotion = true; ++ public boolean canDrinkMilk = true; ++ // Paper end + + public WanderingTrader(EntityType type, Level world) { + super(type, world); +@@ -68,10 +72,10 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(0, new UseItemGoal<>(this, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEvents.WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { +- return this.world.isNight() && !entityvillagertrader.isInvisible(); ++ return canDrinkPotion && this.world.isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API + })); + this.goalSelector.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { +- return this.level.isDay() && entityvillagertrader.isInvisible(); ++ return canDrinkMilk && this.level.isDay() && entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API + })); + this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this)); + this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zombie.class, 8.0F, 0.5D, 0.5D)); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java +index a00b1ee5d80d3918ece2260dc1360aa90de16c8a..de58fc26bd811e87cd393bdecee796faf72e65e1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java +@@ -34,4 +34,26 @@ public class CraftWanderingTrader extends CraftAbstractVillager implements Wande + public void setDespawnDelay(int despawnDelay) { + getHandle().setDespawnDelay(despawnDelay); + } ++ ++ // Paper start - Add more WanderingTrader API ++ @Override ++ public void setCanDrinkPotion(boolean bool) { ++ getHandle().canDrinkPotion = bool; ++ } ++ ++ @Override ++ public boolean canDrinkPotion() { ++ return getHandle().canDrinkPotion; ++ } ++ ++ @Override ++ public void setCanDrinkMilk(boolean bool) { ++ getHandle().canDrinkMilk = bool; ++ } ++ ++ @Override ++ public boolean canDrinkMilk() { ++ return getHandle().canDrinkMilk; ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0723-Add-EntityBlockStorage-clearEntities.patch b/patches/server-remapped/0723-Add-EntityBlockStorage-clearEntities.patch new file mode 100644 index 0000000000..530ee44dcf --- /dev/null +++ b/patches/server-remapped/0723-Add-EntityBlockStorage-clearEntities.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Mon, 5 Apr 2021 18:12:29 -0400 +Subject: [PATCH] Add EntityBlockStorage#clearEntities() + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +index cbd0587eeecf14b1914bdb33f7a4584bd6b5c8d0..83e5367ee1126afe31e9f704a0daedd310339d15 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +@@ -120,6 +120,11 @@ public class BeehiveBlockEntity extends BlockEntity implements TickableBlockEnti + return this.stored.size(); + } + ++ // Paper start - Add EntityBlockStorage clearEntities ++ public void clearBees() { ++ this.stored.clear(); ++ } ++ // Paper end + public static int getHoneyLevel(BlockState state) { + return (Integer) state.getValue(BeehiveBlock.HONEY_LEVEL); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java +index e61ea9c7fb711e8335a5d0fd5a8bc0152a225038..3346a1962a992566fe840fd0a75cfa06f694833a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java +@@ -83,4 +83,10 @@ public class CraftBeehive extends CraftBlockEntityState impl + + getSnapshot().addOccupant(((CraftBee) entity).getHandle(), false); + } ++ // Paper start - Add EntityBlockStorage clearEntities ++ @Override ++ public void clearEntities() { ++ getSnapshot().clearBees(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/server-remapped/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch new file mode 100644 index 0000000000..9006bd8edb --- /dev/null +++ b/patches/server-remapped/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alvinn8 <42838560+Alvinn8@users.noreply.github.com> +Date: Fri, 8 Jan 2021 20:31:13 +0100 +Subject: [PATCH] Add Adventure message to PlayerAdvancementDoneEvent + + +diff --git a/src/main/java/net/minecraft/advancements/Advancement.java b/src/main/java/net/minecraft/advancements/Advancement.java +index 9d27b658d32297337fb367bae628a1cc3a78712a..4abbe45237667c08753c040ef1281af1b2f34f88 100644 +--- a/src/main/java/net/minecraft/advancements/Advancement.java ++++ b/src/main/java/net/minecraft/advancements/Advancement.java +@@ -76,6 +76,7 @@ public class Advancement { + return this.parent; + } + ++ public final @Nullable DisplayInfo getAdvancementDisplay() { return this.getDisplay(); } // Paper - OBFHELPER + @Nullable + public DisplayInfo getDisplay() { + return this.display; +@@ -125,6 +126,7 @@ public class Advancement { + return this.requirements; + } + ++ public final Component getChatComponent() { return this.getChatComponent(); } // Paper - OBFHELPER + public Component getChatComponent() { + return this.chatComponent; + } +diff --git a/src/main/java/net/minecraft/advancements/DisplayInfo.java b/src/main/java/net/minecraft/advancements/DisplayInfo.java +index 2bcf14826ec1c6a1654246844d03184ceae55d79..1b41578fed1da6d15a806a7200e53954f608b625 100644 +--- a/src/main/java/net/minecraft/advancements/DisplayInfo.java ++++ b/src/main/java/net/minecraft/advancements/DisplayInfo.java +@@ -54,10 +54,12 @@ public class DisplayInfo { + return this.description; + } + ++ public final FrameType getFrameType() { return this.getFrame(); } // Paper - OBFHELPER + public FrameType getFrame() { + return this.frame; + } + ++ public final boolean shouldAnnounceToChat() { return this.shouldAnnounceChat(); } // Paper - OBFHELPER + public boolean shouldAnnounceChat() { + return this.announceChat; + } +diff --git a/src/main/java/net/minecraft/advancements/FrameType.java b/src/main/java/net/minecraft/advancements/FrameType.java +index 0ccac480a760259412b525e66c43de3a209543f5..f6d4b876bdd25942763780f17c8bb69ac3d56031 100644 +--- a/src/main/java/net/minecraft/advancements/FrameType.java ++++ b/src/main/java/net/minecraft/advancements/FrameType.java +@@ -20,6 +20,7 @@ public enum FrameType { + this.displayName = new TranslatableComponent("advancements.toast." + s); + } + ++ public final String getId() { return this.getName(); } // Paper - OBFHELPER + public String getName() { + return this.name; + } +diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index b8d3f2c59199e245e2035d6205dd1a042aa93f77..fcb59f6538e66fa43d11d4998e6eeac2e33b0393 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -51,6 +51,7 @@ import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.level.GameRules; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + + public class PlayerAdvancements { + +@@ -313,10 +314,18 @@ public class PlayerAdvancements { + this.progressChanged.add(advancement); + flag = true; + if (!flag1 && advancementprogress.isDone()) { +- this.player.level.getCraftServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit)); // CraftBukkit ++ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent ++ boolean announceToChat = advancement.getAdvancementDisplay() != null && advancement.getAdvancementDisplay().shouldAnnounceToChat(); ++ net.kyori.adventure.text.Component message = announceToChat ? PaperAdventure.asAdventure(new TranslatableComponent("chat.type.advancement." + advancement.getAdvancementDisplay().getFrameType().getId(), this.player.getDisplayName(), advancement.getChatComponent())) : null; ++ org.bukkit.event.player.PlayerAdvancementDoneEvent event = new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit, message); ++ this.player.level.getCraftServer().getPluginManager().callEvent(event); ++ message = event.message(); ++ // Paper end + advancement.getRewards().a(this.player); +- if (advancement.getDisplay() != null && advancement.getDisplay().shouldAnnounceChat() && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { +- this.playerList.broadcastMessage(new TranslatableComponent("chat.type.advancement." + advancement.getDisplay().getFrame().getName(), new Object[]{this.player.getDisplayName(), advancement.getChatComponent()}), ChatType.SYSTEM, Util.NIL_UUID); ++ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent ++ if (message != null && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { ++ this.playerList.broadcastMessage(PaperAdventure.asVanilla(message), ChatType.SYSTEM, Util.getNullUUID()); ++ // Paper end + } + } + } diff --git a/patches/server-remapped/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/server-remapped/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch new file mode 100644 index 0000000000..a376cbbc19 --- /dev/null +++ b/patches/server-remapped/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Connor Linfoot +Date: Wed, 12 May 2021 08:09:19 +0100 +Subject: [PATCH] Add raw address to AsyncPlayerPreLoginEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 573963a09f15046cfcaab83aef906801ce70d75a..99275a8bc2e7bf242ff3c5b5c29924af5328327a 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -325,12 +325,13 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + // Paper end + String playerName = gameProfile.getName(); + java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); ++ java.net.InetAddress rawAddress = ((java.net.InetSocketAddress) connection.getRawAddress()).getAddress(); // Paper + java.util.UUID uniqueId = gameProfile.getId(); + final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; + + // Paper start + PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); +- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); ++ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile); + server.getPluginManager().callEvent(asyncEvent); + profile = asyncEvent.getPlayerProfile(); + profile.complete(true); diff --git a/patches/server-remapped/0726-Inventory-close.patch b/patches/server-remapped/0726-Inventory-close.patch new file mode 100644 index 0000000000..f206ea0fbd --- /dev/null +++ b/patches/server-remapped/0726-Inventory-close.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 11 May 2021 14:54:56 -0700 +Subject: [PATCH] Inventory#close + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +index 7ccc085228f373e6eba55d809bed480d43d5c211..16d34f44e92e26d13188417942f444952f98dfa1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +@@ -448,6 +448,14 @@ public class CraftInventory implements Inventory { + clear(i); + } + } ++ // Paper start ++ @Override ++ public int close() { ++ int count = this.inventory.getViewers().size(); ++ com.google.common.collect.Lists.newArrayList(this.inventory.getViewers()).forEach(HumanEntity::closeInventory); ++ return count; ++ } ++ // Paper end + + @Override + public ListIterator iterator() { diff --git a/patches/server-remapped/0727-call-PortalCreateEvent-players-and-end-platform.patch b/patches/server-remapped/0727-call-PortalCreateEvent-players-and-end-platform.patch new file mode 100644 index 0000000000..4776fc7a79 --- /dev/null +++ b/patches/server-remapped/0727-call-PortalCreateEvent-players-and-end-platform.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 12 May 2021 03:21:22 -0700 +Subject: [PATCH] call PortalCreateEvent players and end platform + + +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 727af6ac84075db87615ebac51a024e6376fa3cb..6e2a272075ead399004dabfb7d4f0ea5fd32ffc2 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -496,6 +496,7 @@ public class BlockPos extends Vec3i { + return this.set(this.getX() + direction.getStepX() * distance, this.getY() + direction.getStepY() * distance, this.getZ() + direction.getStepZ() * distance); + } + ++ public BlockPos.MutableBlockPos withOffset(int x, int y, int z) { return move(x, y, z); } // Paper - OBFHELPER + public BlockPos.MutableBlockPos move(int dx, int dy, int dz) { + return this.set(this.getX() + dx, this.getY() + dy, this.getZ() + dz); + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 314f168c9d17ab3654c9dda07e48839570f0d332..5d710a1f4e0c61d4be6efe8cebd9b80789868338 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1142,15 +1142,21 @@ public class ServerPlayer extends Player implements ContainerListener { + private void createEndPlatform(ServerLevel world, BlockPos centerPos) { + BlockPos.MutableBlockPos blockposition_mutableblockposition = centerPos.mutable(); + ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(world); // Paper + for (int i = -2; i <= 2; ++i) { + for (int j = -2; j <= 2; ++j) { + for (int k = -1; k < 3; ++k) { + BlockState iblockdata = k == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); + +- world.setBlockAndUpdate(blockposition_mutableblockposition.set(centerPos).move(j, k, i), iblockdata); ++ blockList.setBlock(blockposition_mutableblockposition.setValues(centerPos).withOffset(j, k, i), iblockdata, 3); // Paper + } + } + } ++ // Paper start ++ if (new org.bukkit.event.world.PortalCreateEvent((List< org.bukkit.block.BlockState>) (List) blockList.getList(), world.getWorld(), this.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM).callEvent()) { ++ blockList.updateList(); ++ } ++ // Paper end + + } + diff --git a/patches/server-remapped/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/server-remapped/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch new file mode 100644 index 0000000000..fb4c1ca38d --- /dev/null +++ b/patches/server-remapped/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch @@ -0,0 +1,126 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Tue, 11 May 2021 00:48:33 +0200 +Subject: [PATCH] Add a "should burn in sunlight" API for Phantoms and + Skeletons + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +index 68e52e3a31e70569d1a92602aff4b7b81c594757..a8a0dba43453b7ac73e8e0faf7728445d9bcc2cd 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -98,9 +98,15 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + return MobType.UNDEAD; + } + ++ // Paper start ++ private boolean shouldBurnInDay = true; ++ public boolean shouldBurnInDay() { return shouldBurnInDay; } ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } ++ // Paper end ++ + @Override + public void aiStep() { +- boolean flag = this.isSunBurnTick(); ++ boolean flag = shouldBurnInDay && this.isSunBurnTick(); // Paper - Configurable Burning + + if (flag) { + ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); +@@ -224,7 +230,16 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + public void readAdditionalSaveData(CompoundTag tag) { + super.readAdditionalSaveData(tag); + this.reassessWeaponGoal(); ++ this.shouldBurnInDay = tag.getBoolean("Paper.ShouldBurnInDay"); // Paper ++ } ++ ++ // Paper start ++ @Override ++ public void addAdditionalSaveData(CompoundTag tag) { ++ super.addAdditionalSaveData(tag); ++ tag.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); + } ++ // Paper end + + @Override + public void setItemSlot(EquipmentSlot slot, ItemStack stack) { +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index a40c23e824652cff59633b7c314e27ec9a515c07..8f4dd4540330966689e71568e9e9ef77f82a786a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -134,7 +134,7 @@ public class Phantom extends FlyingMob implements Enemy { + + @Override + public void aiStep() { +- if (this.isAlive() && this.isSunBurnTick()) { ++ if (this.isAlive() && shouldBurnInDay && this.isSunBurnTick()) { // Paper - Configurable Burning + this.setSecondsOnFire(8); + } + +@@ -165,6 +165,7 @@ public class Phantom extends FlyingMob implements Enemy { + if (tag.hasUUID("Paper.SpawningEntity")) { + this.spawningEntity = tag.getUUID("Paper.SpawningEntity"); + } ++ this.shouldBurnInDay = tag.getBoolean("Paper.ShouldBurnInDay"); + // Paper end + } + +@@ -179,6 +180,7 @@ public class Phantom extends FlyingMob implements Enemy { + if (this.spawningEntity != null) { + tag.setUUID("Paper.SpawningEntity", this.spawningEntity); + } ++ tag.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); + // Paper end + } + +@@ -233,6 +235,10 @@ public class Phantom extends FlyingMob implements Enemy { + return spawningEntity; + } + public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } ++ ++ private boolean shouldBurnInDay = true; ++ public boolean shouldBurnInDay() { return shouldBurnInDay; } ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } + // Paper end + + class PhantomAttackPlayerTargetGoal extends Goal { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +index 92162fa22f5e98b7837bde5830bd47c31b8b52d8..011ad2224a3a3a2d255b2498e406fbb047359240 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +@@ -39,5 +39,15 @@ public class CraftPhantom extends CraftFlying implements Phantom { + public java.util.UUID getSpawningEntity() { + return getHandle().getSpawningEntity(); + } ++ ++ @Override ++ public boolean shouldBurnInDay() { ++ return getHandle().shouldBurnInDay(); ++ } ++ ++ @Override ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { ++ getHandle().setShouldBurnInDay(shouldBurnInDay); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +index b2d3244cca4d9d108159f3537d8a9aace3f8e77f..28dda8beb1793fad47b2c9db815c0b6cf6ed781a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +@@ -36,4 +36,16 @@ public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroy + public void setSkeletonType(SkeletonType type) { + throw new UnsupportedOperationException("Not supported."); + } ++ ++ // Paper start ++ @Override ++ public boolean shouldBurnInDay() { ++ return getHandle().shouldBurnInDay(); ++ } ++ ++ @Override ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { ++ getHandle().setShouldBurnInDay(shouldBurnInDay); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0729-Fix-CraftPotionBrewer-cache.patch b/patches/server-remapped/0729-Fix-CraftPotionBrewer-cache.patch new file mode 100644 index 0000000000..140b30b682 --- /dev/null +++ b/patches/server-remapped/0729-Fix-CraftPotionBrewer-cache.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sceri +Date: Fri, 14 May 2021 19:06:51 +0500 +Subject: [PATCH] Fix CraftPotionBrewer cache + + +diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java +index e20d96ec67dcbe935357b4de7e0e9a6984dc3303..eb28a055ba60bb1da3412cf0dbbe5ce76a779f38 100644 +--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java ++++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java +@@ -15,12 +15,18 @@ import org.bukkit.potion.PotionEffectType; + import org.bukkit.potion.PotionType; + + public class CraftPotionBrewer implements PotionBrewer { +- private static final Map> cache = Maps.newHashMap(); ++ private static final Map> cache = Maps.newHashMap(); // Paper + + @Override + public Collection getEffects(PotionType damage, boolean upgraded, boolean extended) { +- if (cache.containsKey(damage)) +- return cache.get(damage); ++ // Paper start ++ int key = damage.ordinal() << 2; ++ key |= (upgraded ? 1 : 0) << 1; ++ key |= extended ? 1 : 0; ++ ++ if (cache.containsKey(key)) ++ return cache.get(key); ++ // Paper end + + List mcEffects = Potion.byName(CraftPotionUtil.fromBukkit(new PotionData(damage, extended, upgraded))).getEffects(); + +@@ -29,9 +35,9 @@ public class CraftPotionBrewer implements PotionBrewer { + builder.add(CraftPotionUtil.toBukkit(effect)); + } + +- cache.put(damage, builder.build()); ++ cache.put(key, builder.build()); // Paper + +- return cache.get(damage); ++ return cache.get(key); // Paper + } + + @Override diff --git a/patches/server-remapped/0730-Add-basic-Datapack-API.patch b/patches/server-remapped/0730-Add-basic-Datapack-API.patch new file mode 100644 index 0000000000..547e7cb557 --- /dev/null +++ b/patches/server-remapped/0730-Add-basic-Datapack-API.patch @@ -0,0 +1,174 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Connor Linfoot +Date: Sun, 16 May 2021 15:07:34 +0100 +Subject: [PATCH] Add basic Datapack API + + +diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java +new file mode 100644 +index 0000000000000000000000000000000000000000..66debefcd474e4dcc2a8889a82af6c1809c93f46 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java +@@ -0,0 +1,51 @@ ++package io.papermc.paper.datapack; ++ ++import Compatibility; ++import io.papermc.paper.event.server.ServerResourcesReloadedEvent; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.packs.repository.Pack; ++import java.util.List; ++import java.util.stream.Collectors; ++ ++public class PaperDatapack implements Datapack { ++ private final String name; ++ private final Compatibility compatibility; ++ private final boolean enabled; ++ ++ PaperDatapack(Pack loader, boolean enabled) { ++ this.name = loader.getName(); ++ this.compatibility = Compatibility.valueOf(loader.getVersion().name()); ++ this.enabled = enabled; ++ } ++ ++ @Override ++ public String getName() { ++ return name; ++ } ++ ++ @Override ++ public Compatibility getCompatibility() { ++ return compatibility; ++ } ++ ++ @Override ++ public boolean isEnabled() { ++ return enabled; ++ } ++ ++ @Override ++ public void setEnabled(boolean enabled) { ++ if (enabled == this.enabled) { ++ return; ++ } ++ ++ MinecraftServer server = MinecraftServer.getServer(); ++ List enabledKeys = server.getPackRepository().getEnabledPacks().stream().map(Pack::getName).collect(Collectors.toList()); ++ if (enabled) { ++ enabledKeys.add(this.name); ++ } else { ++ enabledKeys.remove(this.name); ++ } ++ server.reloadServerResources(enabledKeys, ServerResourcesReloadedEvent.Cause.PLUGIN); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ec221183bef1065bda0a37e1025958df0d1f6318 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java +@@ -0,0 +1,25 @@ ++package io.papermc.paper.datapack; ++ ++import java.util.Collection; ++import java.util.stream.Collectors; ++import net.minecraft.server.packs.repository.Pack; ++import net.minecraft.server.packs.repository.PackRepository; ++ ++public class PaperDatapackManager implements DatapackManager { ++ private final PackRepository repository; ++ ++ public PaperDatapackManager(PackRepository repository) { ++ this.repository = repository; ++ } ++ ++ @Override ++ public Collection getPacks() { ++ Collection enabledPacks = repository.getEnabledPacks(); ++ return repository.getPacks().stream().map(loader -> new PaperDatapack(loader, enabledPacks.contains(loader))).collect(Collectors.toList()); ++ } ++ ++ @Override ++ public Collection getEnabledPacks() { ++ return repository.getEnabledPacks().stream().map(loader -> new PaperDatapack(loader, true)).collect(Collectors.toList()); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/packs/repository/Pack.java b/src/main/java/net/minecraft/server/packs/repository/Pack.java +index df5d258b80e37077fa236e4190ad934853c88619..4120326e0d047347e5d7ab9521babe7bb6b6a7db 100644 +--- a/src/main/java/net/minecraft/server/packs/repository/Pack.java ++++ b/src/main/java/net/minecraft/server/packs/repository/Pack.java +@@ -101,6 +101,7 @@ public class Pack implements AutoCloseable { + }); + } + ++ public final PackCompatibility getVersion() { return this.getCompatibility(); } // Paper - OBFHELPER + public PackCompatibility getCompatibility() { + return this.compatibility; + } +@@ -109,6 +110,7 @@ public class Pack implements AutoCloseable { + return (PackResources) this.supplier.get(); + } + ++ public final String getName() { return this.getId(); } // Paper - OBFHELPER + public String getId() { + return this.id; + } +diff --git a/src/main/java/net/minecraft/server/packs/repository/PackRepository.java b/src/main/java/net/minecraft/server/packs/repository/PackRepository.java +index bce2fd67048bd1fd53865eef81bac262dbda2865..8d0ef3bdf9fa283f54628800768717181df28aa5 100644 +--- a/src/main/java/net/minecraft/server/packs/repository/PackRepository.java ++++ b/src/main/java/net/minecraft/server/packs/repository/PackRepository.java +@@ -88,6 +88,7 @@ public class PackRepository implements AutoCloseable { + return this.available.keySet(); + } + ++ public final Collection getPacks() { return this.getAvailablePacks(); } // Paper - OBFHELPER + public Collection getAvailablePacks() { + return this.available.values(); + } +@@ -96,6 +97,7 @@ public class PackRepository implements AutoCloseable { + return (Collection) this.selected.stream().map(Pack::getId).collect(ImmutableSet.toImmutableSet()); + } + ++ public final Collection getEnabledPacks() { return this.getSelectedPacks(); } // Paper - OBFHELPER + public Collection getSelectedPacks() { + return this.selected; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 6905256147d9bd79e5f52bf86bdb21c89b8411a7..63639923f7875d76f569b8c6e958782c6462d906 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -18,6 +18,7 @@ import com.mojang.serialization.Lifecycle; + import io.netty.buffer.ByteBuf; + import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; ++import io.papermc.paper.datapack.PaperDatapackManager; // Paper + import io.papermc.paper.util.TraceUtil; + import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; + import java.awt.image.BufferedImage; +@@ -264,6 +265,7 @@ public final class CraftServer implements Server { + public boolean ignoreVanillaPermissions = false; + private final List playerView; + public int reloadCount; ++ private final PaperDatapackManager datapackManager; // Paper + public static Exception excessiveVelEx; // Paper - Velocity warnings + + static { +@@ -346,6 +348,7 @@ public final class CraftServer implements Server { + TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + minimumAPI = configuration.getString("settings.minimum-api"); + loadIcon(); ++ datapackManager = new PaperDatapackManager(console.getPackRepository()); // Paper + } + + public boolean getCommandBlockOverride(String command) { +@@ -2496,5 +2499,11 @@ public final class CraftServer implements Server { + public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { + return mobGoals; + } ++ ++ @Override ++ public PaperDatapackManager getDatapackManager() { ++ return datapackManager; ++ } ++ + // Paper end + } diff --git a/patches/server-remapped/0731-Add-environment-variable-to-disable-server-gui.patch b/patches/server-remapped/0731-Add-environment-variable-to-disable-server-gui.patch new file mode 100644 index 0000000000..a1f57cca90 --- /dev/null +++ b/patches/server-remapped/0731-Add-environment-variable-to-disable-server-gui.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Riley Park +Date: Mon, 17 May 2021 00:34:55 -0700 +Subject: [PATCH] Add environment variable to disable server gui + + +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 9dc9a5e6ad7f23c8bf3553c765ceeecd67a49ac1..ba6c17da4875c3a342da99e354c9f07cc7f17326 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -225,6 +225,7 @@ public class Main { + */ + boolean flag1 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui"); + ++ if(!Boolean.parseBoolean(System.getenv().getOrDefault("PAPER_DISABLE_SERVER_GUI", String.valueOf(false)))) // Paper + if (flag1 && !GraphicsEnvironment.isHeadless()) { + dedicatedserver1.showGui(); + } diff --git a/patches/server-remapped/0732-additions-to-PlayerGameModeChangeEvent.patch b/patches/server-remapped/0732-additions-to-PlayerGameModeChangeEvent.patch new file mode 100644 index 0000000000..31a8669378 --- /dev/null +++ b/patches/server-remapped/0732-additions-to-PlayerGameModeChangeEvent.patch @@ -0,0 +1,138 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 10:04:43 -0700 +Subject: [PATCH] additions to PlayerGameModeChangeEvent + + +diff --git a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java +index c0098a8f8a9fa2671ff66cbcf50ac74b057d1446..ebbd6f2b0e7236b33d136ab2218c8eca4c5df03e 100644 +--- a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java ++++ b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java +@@ -43,7 +43,13 @@ public class DefaultGameModeCommands { + ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + + if (entityplayer.gameMode.getGameModeForPlayer() != defaultGameMode) { +- entityplayer.setGameMode(defaultGameMode); ++ // Paper start - handle event cancelling the change ++ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(defaultGameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getScoreboardName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); ++ if (event != null && event.isCancelled()) { ++ source.sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); ++ continue; ++ } ++ // Paper end + ++i; + } + } +diff --git a/src/main/java/net/minecraft/server/commands/GameModeCommand.java b/src/main/java/net/minecraft/server/commands/GameModeCommand.java +index 3e999090fb3b03b996a9790c53e5b4618c8891f7..3b17c81167f8e011e7f9c09bf42eb632f5a3c2f2 100644 +--- a/src/main/java/net/minecraft/server/commands/GameModeCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GameModeCommand.java +@@ -62,13 +62,13 @@ public class GameModeCommand { + ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + + if (entityplayer.gameMode.getGameModeForPlayer() != gameMode) { +- entityplayer.setGameMode(gameMode); +- // CraftBukkit start - handle event cancelling the change +- if (entityplayer.gameMode.getGameModeForPlayer() != gameMode) { +- context.getSource().sendFailure(new net.minecraft.network.chat.TextComponent("Failed to set the gamemode of '" + entityplayer.getScoreboardName() + "'")); ++ // Paper start - handle event cancelling the change ++ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getScoreboardName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); ++ if (event != null && event.isCancelled()) { ++ context.getSource().sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); + continue; + } +- // CraftBukkit end ++ // Paper end + logGamemodeChange((CommandSourceStack) context.getSource(), entityplayer, gameMode); + ++i; + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 5d710a1f4e0c61d4be6efe8cebd9b80789868338..779b926921fd435620cbbc69ed6f9931a422b652 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -393,7 +393,16 @@ public class ServerPlayer extends Player implements ContainerListener { + if (this.getY() > 300) this.setPosRaw(getX(), 257, getZ()); // Paper - bring down to a saner Y level if out of world + if (tag.contains("playerGameType", 99)) { + if (this.getServer().getForceGameType()) { ++ // Paper start - call PlayerGameModeChangeEvent on join for players that do not have the correct gamemode ++ if (this.getServer().getDefaultGameType() != GameType.byId(tag.getInt("playerGameType"))) { ++ if (new org.bukkit.event.player.PlayerGameModeChangeEvent(this.getBukkitEntity(), GameMode.getByValue(this.getServer().getDefaultGameType().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) { + this.gameMode.setGameModeForPlayer(this.getServer().getDefaultGameType(), GameType.NOT_SET); ++ } else { ++ this.gameMode.setGameModeForPlayer(GameType.byId(tag.getInt("playerGameType")), tag.contains("previousPlayerGameType", 3) ? GameType.byId(tag.getInt("previousPlayerGameType")) : GameType.NOT_SET); // copied from below; if cancelled, set gamemode normally ++ } ++ } else { ++ this.gameMode.setGameModeForPlayer(GameType.byId(tag.getInt("playerGameType")), tag.contains("previousPlayerGameType", 3) ? GameType.byId(tag.getInt("previousPlayerGameType")) : GameType.NOT_SET); // copied from below; if no change needed, set gamemode normally ++ } // Paper end + } else { + this.gameMode.setGameModeForPlayer(GameType.byId(tag.getInt("playerGameType")), tag.contains("previousPlayerGameType", 3) ? GameType.byId(tag.getInt("previousPlayerGameType")) : GameType.NOT_SET); + } +@@ -1789,21 +1798,27 @@ public class ServerPlayer extends Player implements ContainerListener { + + @Override + public void setGameMode(GameType gameMode) { ++ // Paper start - Add cause and nullable message to event ++ setGamemode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null); ++ } ++ ++ public PlayerGameModeChangeEvent setGamemode(GameType enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component message) { ++ // Paper end + // CraftBukkit start +- if (gameMode == this.gameMode.getGameModeForPlayer()) { +- return; ++ if (enumgamemode == this.gameMode.getGameModeForPlayer()) { ++ return null; // Paper + } + +- PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(gameMode.getId())); ++ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(enumgamemode.getId()), cause, message); // Paper + level.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { +- return; ++ return event; // Paper + } + // CraftBukkit end + +- this.gameMode.setGameModeForPlayer(gameMode); +- this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) gameMode.getId())); +- if (gameMode == GameType.SPECTATOR) { ++ this.gameMode.setGameModeForPlayer(enumgamemode); ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) enumgamemode.getId())); ++ if (enumgamemode == GameType.SPECTATOR) { + this.removeEntitiesOnShoulder(); + this.stopRiding(); + } else { +@@ -1812,6 +1827,7 @@ public class ServerPlayer extends Player implements ContainerListener { + + this.onUpdateAbilities(); + this.updateEffectVisibility(); ++ return event; // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index a0e69cac7699ddc318057c8016e329850d3baa26..c454908f23a436f66f8e64fc346186f113b6eefb 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2449,7 +2449,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + this.player = this.server.getPlayerList().respawn(this.player, false); + if (this.server.isHardcore()) { +- this.player.setGameMode(GameType.SPECTATOR); ++ this.player.setGamemode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper + ((GameRules.BooleanValue) this.player.getLevel().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, this.server); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index ec8c7499662c0a810f1337ebc0fa24d2f3ca79e7..3dbe94d9b9647f5cc1e27335b36042e50c652cea 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1189,7 +1189,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + throw new IllegalArgumentException("Mode cannot be null"); + } + +- getHandle().setGameMode(GameType.byId(mode.getValue())); ++ getHandle().setGamemode(GameType.byId(mode.getValue()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.PLUGIN, null); // Paper + } + + @Override diff --git a/patches/server-remapped/0733-ItemStack-repair-check-API.patch b/patches/server-remapped/0733-ItemStack-repair-check-API.patch new file mode 100644 index 0000000000..74dbd3c778 --- /dev/null +++ b/patches/server-remapped/0733-ItemStack-repair-check-API.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 22:11:11 -0700 +Subject: [PATCH] ItemStack repair check API + + +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index cb079bfd5339b96ad372b0a3b483d02cd0636bfd..42085d3f4ae5c6ceecaffde79fb3187712a2af00 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -269,6 +269,7 @@ public class Item implements ItemLike { + return this.category; + } + ++ public boolean canRepair(ItemStack toBeRepaired, ItemStack repairMaterial) { return isValidRepairItem(toBeRepaired, repairMaterial); } // Paper - OBFHELPER + public boolean isValidRepairItem(ItemStack stack, ItemStack ingredient) { + return false; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 402e5a98290a1701dd67d27c484c97e0a6067c4f..34eed57c7ed884e0d634ca403e38d25c95b6a038 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -485,6 +485,14 @@ public final class CraftMagicNumbers implements UnsafeValues { + return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; + } + ++ @Override ++ public boolean isValidRepairItemStack(org.bukkit.inventory.ItemStack itemToBeRepaired, org.bukkit.inventory.ItemStack repairMaterial) { ++ if (!itemToBeRepaired.getType().isItem() || !repairMaterial.getType().isItem()) { ++ return false; ++ } ++ return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); ++ } ++ + @Override + public int getProtocolVersion() { + return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion(); +diff --git a/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8d9c9b3bd53d407391d4fcb7fc773153d1a7b402 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java +@@ -0,0 +1,48 @@ ++package io.papermc.paper.util; ++ ++import org.bukkit.Material; ++import org.bukkit.inventory.ItemStack; ++import org.bukkit.support.AbstractTestingBase; ++import org.junit.Test; ++ ++import static org.junit.Assert.assertFalse; ++import static org.junit.Assert.assertThrows; ++import static org.junit.Assert.assertTrue; ++ ++public class ItemStackRepairCheckTest extends AbstractTestingBase { ++ ++ @Test ++ public void testIsRepariableBy() { ++ ItemStack diamondPick = new ItemStack(Material.DIAMOND_PICKAXE); ++ ++ assertTrue("diamond pick isn't repairable by a diamond", diamondPick.isRepairableBy(new ItemStack(Material.DIAMOND))); ++ } ++ ++ @Test ++ public void testCanRepair() { ++ ItemStack diamond = new ItemStack(Material.DIAMOND); ++ ++ assertTrue("diamond can't repair a diamond axe", diamond.canRepair(new ItemStack(Material.DIAMOND_AXE))); ++ } ++ ++ @Test ++ public void testIsNotRepairableBy() { ++ ItemStack notDiamondPick = new ItemStack(Material.ACACIA_SAPLING); ++ ++ assertFalse("acacia sapling is repairable by a diamond", notDiamondPick.isRepairableBy(new ItemStack(Material.DIAMOND))); ++ } ++ ++ @Test ++ public void testCanNotRepair() { ++ ItemStack diamond = new ItemStack(Material.DIAMOND); ++ ++ assertFalse("diamond can repair oak button", diamond.canRepair(new ItemStack(Material.OAK_BUTTON))); ++ } ++ ++ @Test ++ public void testInvalidItem() { ++ ItemStack badItemStack = new ItemStack(Material.ACACIA_WALL_SIGN); ++ ++ assertFalse("acacia wall sign is repairable by diamond", badItemStack.isRepairableBy(new ItemStack(Material.DIAMOND))); ++ } ++} diff --git a/patches/server-remapped/0734-More-Enchantment-API.patch b/patches/server-remapped/0734-More-Enchantment-API.patch new file mode 100644 index 0000000000..4bf44e22d8 --- /dev/null +++ b/patches/server-remapped/0734-More-Enchantment-API.patch @@ -0,0 +1,211 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 6 May 2021 19:57:58 -0700 +Subject: [PATCH] More Enchantment API + + +diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +index c23ec1b31950471905c65e46273ae105de853d9b..b994a7aca0ce01b5c0d44b9b126295ffcd2f795d 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +@@ -17,7 +17,7 @@ import net.minecraft.world.item.ItemStack; + + public abstract class Enchantment { + +- private final EquipmentSlot[] slots; ++ private final EquipmentSlot[] slots; public final EquipmentSlot[] getSlots() { return this.slots; } // Paper - OBFHELPER + private final Enchantment.Rarity rarity; + public final EnchantmentCategory category; + @Nullable +@@ -46,6 +46,7 @@ public abstract class Enchantment { + return map; + } + ++ public Enchantment.Rarity getRarity() { return getRarity(); } // Paper - OBFHELPER + public Enchantment.Rarity getRarity() { + return this.rarity; + } +@@ -70,6 +71,7 @@ public abstract class Enchantment { + return 0; + } + ++ public float getDamageIncrease(int level, MobType enumMonsterType) { return getDamageBonus(level, enumMonsterType); } // Paper - OBFHELPER + public float getDamageBonus(int level, MobType group) { + return 0.0F; + } +@@ -123,14 +125,17 @@ public abstract class Enchantment { + return false; + } + ++ public boolean isCursed() { return isCurse(); } // Paper - OBFHELPER + public boolean isCurse() { + return false; + } + ++ public boolean isTradeable() { return isTradeable(); } // Paper - OBFHELPER + public boolean isTradeable() { + return true; + } + ++ public boolean isDiscoverable() { return isDiscoverable(); } // Paper - OBFHELPER + public boolean isDiscoverable() { + return true; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +index b1ffe6c7a5915f00a476e88f3a38349b740b4910..20858bb8463ff86c96b5fcdeca455c20c696870f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java ++++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +@@ -1,8 +1,6 @@ + package org.bukkit.craftbukkit.enchantments; + + import net.minecraft.core.Registry; +-import net.minecraft.world.item.enchantment.BindingCurseEnchantment; +-import net.minecraft.world.item.enchantment.VanishingCurseEnchantment; + import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.craftbukkit.util.CraftNamespacedKey; + import org.bukkit.enchantments.Enchantment; +@@ -71,7 +69,7 @@ public class CraftEnchantment extends Enchantment { + + @Override + public boolean isCursed() { +- return target instanceof BindingCurseEnchantment || target instanceof VanishingCurseEnchantment; ++ return target.isCursed(); // Paper + } + + @Override +@@ -192,6 +190,45 @@ public class CraftEnchantment extends Enchantment { + public net.kyori.adventure.text.Component displayName(int level) { + return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); + } ++ ++ @Override ++ public boolean isTradeable() { ++ return target.isTradeable(); ++ } ++ ++ @Override ++ public boolean isDiscoverable() { ++ return target.isDiscoverable(); ++ } ++ ++ @Override ++ public io.papermc.paper.enchantments.EnchantmentRarity getRarity() { ++ return fromNMSRarity(target.getRarity()); ++ } ++ ++ @Override ++ public float getDamageIncrease(int level, org.bukkit.entity.EntityCategory entityCategory) { ++ return target.getDamageIncrease(level, org.bukkit.craftbukkit.entity.CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); ++ } ++ ++ @Override ++ public java.util.Set getActiveSlots() { ++ return java.util.stream.Stream.of(target.getSlots()).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet()); ++ } ++ ++ public static io.papermc.paper.enchantments.EnchantmentRarity fromNMSRarity(net.minecraft.world.item.enchantment.Enchantment.Rarity nmsRarity) { ++ if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.COMMON) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.COMMON; ++ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.UNCOMMON) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.UNCOMMON; ++ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.RARE) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.RARE; ++ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.VERY_RARE) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.VERY_RARE; ++ } ++ ++ throw new IllegalArgumentException(String.format("Unable to convert %s to a enum value of %s.", nmsRarity, io.papermc.paper.enchantments.EnchantmentRarity.class)); ++ } + // Paper end + + public net.minecraft.world.item.enchantment.Enchantment getHandle() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index eefb6bd580ea176c3a242695ab4af46e7c61b492..25ba7a26c951fc5e4638bdb0db36e94d3e08fb2e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -835,5 +835,21 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setHurtDirection(float hurtDirection) { + getHandle().setHurtDirection(hurtDirection); + } ++ ++ public static MobType fromBukkitEntityCategory(EntityCategory entityCategory) { ++ switch (entityCategory) { ++ case NONE: ++ return MobType.UNDEFINED; ++ case UNDEAD: ++ return MobType.UNDEAD; ++ case ARTHROPOD: ++ return MobType.ARTHROPOD; ++ case ILLAGER: ++ return MobType.ILLAGER; ++ case WATER: ++ return MobType.WATER; ++ } ++ throw new IllegalArgumentException(entityCategory + " is an unrecognized entity category"); ++ } + // Paper end + } +diff --git a/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..62b56b5b43696b03fc72cac59f986d006edc3f76 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java +@@ -0,0 +1,18 @@ ++package io.papermc.paper.enchantments; ++ ++import net.minecraft.world.item.enchantment.Enchantment.Rarity; ++import org.bukkit.craftbukkit.enchantments.CraftEnchantment; ++import org.junit.Test; ++ ++import static org.junit.Assert.assertNotNull; ++ ++public class EnchantmentRarityTest { ++ ++ @Test ++ public void test() { ++ for (Rarity nmsRarity : Rarity.values()) { ++ // Will throw exception if a bukkit counterpart is not found ++ CraftEnchantment.fromNMSRarity(nmsRarity); ++ } ++ } ++} +diff --git a/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..adb0e5b4268fa115b814143cf29d9a3688e4bc17 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java +@@ -0,0 +1,34 @@ ++package io.papermc.paper.entity; ++ ++import com.google.common.base.Joiner; ++import com.google.common.collect.Maps; ++import com.google.common.collect.Sets; ++import net.minecraft.world.entity.EnumMonsterType; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.EntityCategory; ++import org.junit.Test; ++ ++import java.lang.reflect.Field; ++import java.util.Map; ++import java.util.Set; ++ ++import static org.junit.Assert.assertTrue; ++ ++public class EntityCategoryTest { ++ ++ @Test ++ public void test() throws IllegalAccessException { ++ ++ Map enumMonsterTypeFieldMap = Maps.newHashMap(); ++ for (Field field : EnumMonsterType.class.getDeclaredFields()) { ++ if (field.getType() == EnumMonsterType.class) { ++ enumMonsterTypeFieldMap.put( (EnumMonsterType) field.get(null), field.getName()); ++ } ++ } ++ ++ for (EntityCategory entityCategory : EntityCategory.values()) { ++ enumMonsterTypeFieldMap.remove(CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); ++ } ++ assertTrue(EnumMonsterType.class.getName() + " instance(s): " + Joiner.on(", ").join(enumMonsterTypeFieldMap.values()) + " do not have bukkit equivalents", enumMonsterTypeFieldMap.size() == 0); ++ } ++} diff --git a/patches/server-remapped/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/server-remapped/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch new file mode 100644 index 0000000000..6c752cc24c --- /dev/null +++ b/patches/server-remapped/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Tue, 18 May 2021 14:39:44 -0700 +Subject: [PATCH] Add command line option to load extra plugin jars not in the + plugins folder + +ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 63639923f7875d76f569b8c6e958782c6462d906..f1e6d0050092ad51bf233c80b6a51a121e961b07 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -384,8 +384,13 @@ public final class CraftServer implements Server { + + File pluginFolder = (File) console.options.valueOf("plugins"); + +- if (pluginFolder.exists()) { +- Plugin[] plugins = pluginManager.loadPlugins(pluginFolder); ++ // Paper start ++ if (true || pluginFolder.exists()) { ++ if (!pluginFolder.exists()) { ++ pluginFolder.mkdirs(); ++ } ++ Plugin[] plugins = pluginManager.loadPlugins(pluginFolder, this.extraPluginJars()); ++ // Paper end + for (Plugin plugin : plugins) { + try { + String message = String.format("Loading %s", plugin.getDescription().getFullName()); +@@ -400,6 +405,18 @@ public final class CraftServer implements Server { + } + } + ++ // Paper start ++ private List extraPluginJars() { ++ @SuppressWarnings("unchecked") ++ final List jars = (List) this.console.options.valuesOf("add-plugin"); ++ return jars.stream() ++ .filter(File::exists) ++ .filter(File::isFile) ++ .filter(file -> file.getName().endsWith(".jar")) ++ .collect(java.util.stream.Collectors.toList()); ++ } ++ // Paper end ++ + public void enablePlugins(PluginLoadOrder type) { + if (type == PluginLoadOrder.STARTUP) { + helpMap.clear(); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index bd10345cb90f98b8af1519afd603a5244f3a5ca2..521542999b25b1da448fadb3fe6531e083f93e67 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -153,6 +153,12 @@ public class Main { + .ofType(String.class) + .defaultsTo("Unknown Server") + .describedAs("Name"); ++ ++ acceptsAll(asList("add-plugin", "add-extra-plugin-jar")) ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File[] {}) ++ .describedAs("Specify paths to extra plugin jars to be loaded in addition to those in the plugins folder. This argument can be specified multiple times, once for each extra plugin jar path."); + // Paper end + } + }; diff --git a/patches/server-remapped/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/patches/server-remapped/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch new file mode 100644 index 0000000000..7f7be61f7b --- /dev/null +++ b/patches/server-remapped/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 10 May 2021 15:46:57 -0700 +Subject: [PATCH] Fix incorrect status dataconverter for pre 1.13 chunks + +Vanilla was setting non-populated OR non-lit chunks to empty, but +really this is just completely wrong. It should be set to "carved" +at minmum, because pre 1.13 chunks went through 3 distinct stages +of generation: carving, population, and lighting - in this order. +There is no "empty" status, because a chunk was simply carved +or it didn't exist. So mapping any chunk data to empty is simply +invalid. + +If the chunk is terrain populated, then obviously it must be at +minmum "decorated." If the chunk is lit and populated, then it is marked +"mobs_spawned" (which is what Vanilla is doing, and this is the last +stage before moving to full so it looks correct). + +So now here is a table representing the new status conversion: + +Chunk is lit Chunk is populated Vanilla + F F empty + T F empty + F T empty + T T mobs_spawned + +Chunk is lit Chunk is populated Paper + F F carved + T F carved + F T decorated + T T mobs_spawned + +This should fix some problems converting old data, as the +changes here are going to prevent the chunk from being regenerated +incorrectly. + +diff --git a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java +index 16f6aa39385e2d278d4883a32c11ddd119d0d85d..3d262dcf6db0e395d2fa457f7197f24013037ac1 100644 +--- a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java ++++ b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java +@@ -43,13 +43,21 @@ public class ChunkToProtochunkFix extends DataFix { + return dynamic.asStreamOpt().result(); + }); + Dynamic dynamic = (Dynamic) typed1.get(DSL.remainderFinder()); +- boolean flag = dynamic.get("TerrainPopulated").asBoolean(false) && (!dynamic.get("LightPopulated").asNumber().result().isPresent() || dynamic.get("LightPopulated").asBoolean(false)); +- +- dynamic = dynamic.set("Status", dynamic.createString(flag ? "mobs_spawned" : "empty")); ++ // Paper start - fix incorrect status conversion ++ // Vanilla is setting chunks to incorrect status here, they should be using at minimum carved. ++ // for populated chunks, it should be at minimum decorated ++ // and for lit and populated, mobs_spawned is correct (technically mobs_spawned should be for populated, ++ // but if it's not lit then it can't be set above lit) ++ final boolean terrainPopulated = dynamic.get("TerrainPopulated").asBoolean(false); ++ final boolean lightPopulated = dynamic.get("LightPopulated").asBoolean(false) || dynamic.get("LightPopulated").asNumber().result().isPresent(); ++ final String newStatus = !terrainPopulated ? "carved" : (lightPopulated ? "mobs_spawned" : "decorated"); ++ ++ dynamic = dynamic.set("Status", dynamic.createString(newStatus)); + dynamic = dynamic.set("hasLegacyStructureData", dynamic.createBoolean(true)); +- Dynamic dynamic1; ++ // Paper end - fix incorrect status conversion ++ Dynamic dynamic1; // Paper - decompile fix + +- if (flag) { ++ if (true) { // Paper - fix incorrect status conversion + Optional optional1 = dynamic.get("Biomes").asByteBufferOpt().result(); + + if (optional1.isPresent()) { +@@ -70,7 +78,7 @@ public class ChunkToProtochunkFix extends DataFix { + }).collect(Collectors.toList()); + + if (optional.isPresent()) { +- ((Stream) optional.get()).forEach((dynamic2) -> { ++ optional.get().forEach((dynamic2) -> { // Paper - decompile fix + int j = dynamic2.get("x").asInt(0); + int k = dynamic2.get("y").asInt(0); + int l = dynamic2.get("z").asInt(0); +@@ -78,11 +86,11 @@ public class ChunkToProtochunkFix extends DataFix { + + ((ShortList) list.get(k >> 4)).add(short0); + }); ++ Dynamic finalDynamic = dynamic; // Paper - decompile fix + dynamic = dynamic.set("ToBeTicked", dynamic.createList(list.stream().map((shortlist) -> { +- Stream stream = shortlist.stream(); ++ Stream stream = shortlist.stream(); // Paper - decompile fix + +- dynamic.getClass(); +- return dynamic.createList(stream.map(dynamic::createShort)); ++ return finalDynamic.createList(stream.map(finalDynamic::createShort)); + }))); + } + diff --git a/patches/server-remapped/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch b/patches/server-remapped/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch new file mode 100644 index 0000000000..885e2d6ca3 --- /dev/null +++ b/patches/server-remapped/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SamB440 +Date: Fri, 21 May 2021 00:22:09 +0100 +Subject: [PATCH] Fix MC-148809: Increase structure block data length to 128 + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java +index 4c797dd82bb1989861e350a7e628eb847b58bbd8..4792aafd8d992cd64d05f8bbef5cbf30988949ed 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java +@@ -43,7 +43,7 @@ public class ServerboundSetStructureBlockPacket implements Packet +Date: Thu, 20 May 2021 07:02:22 -0700 +Subject: [PATCH] Fix and optimise world force upgrading + +The WorldUpgrader class was incorrectly modified by +CB. It will store an IChunkLoader instance for all +dimension types in the world, but obviously with how +CB shifts around worlds only one dimension type exists +per world. But this would be OK if CB did this +change correctly. All IChunkLoader instances +will point to the same regionfiles. And all +IChunkLoader instances are going to be read from. + +This problem hasn't really been reported because +it relies on the persistent legacy data to be converted +as well to cause corruption. Why? Because the legacy +data is also shared, it will result in different +outputs from conversion (as once conversion for legacy +persistent data takes place, it is REMOVED - so the next +convert will _not_ have the data). Which means different +sizes on disk. Which means different regionfile sector +allocations. Which means there are 3 different possible +regionfile sector allocations in memory, and none of them +are going to be correct. + +I've fixed this by writing a world upgrader suited to +CB's changes to world folder format. It was brain dead +easy to add threading, so I did. + +diff --git a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f476f21bcfd64d4eb2b690c9100275093c49c9d6 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java +@@ -0,0 +1,200 @@ ++package io.papermc.paper.world; ++ ++import com.mojang.datafixers.DataFixer; ++import net.minecraft.SharedConstants; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.resources.ResourceKey; ++import net.minecraft.util.worldupdate.WorldUpgrader; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.chunk.storage.ChunkStorage; ++import net.minecraft.world.level.chunk.storage.RegionFileStorage; ++import net.minecraft.world.level.dimension.DimensionType; ++import net.minecraft.world.level.dimension.LevelStem; ++import net.minecraft.world.level.storage.DimensionDataStorage; ++import net.minecraft.world.level.storage.LevelStorageSource; ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++import java.io.File; ++import java.io.IOException; ++import java.text.DecimalFormat; ++import java.util.concurrent.ExecutorService; ++import java.util.concurrent.Executors; ++import java.util.concurrent.ThreadFactory; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.concurrent.atomic.AtomicLong; ++import java.util.function.Supplier; ++ ++public class ThreadedWorldUpgrader { ++ ++ private static final Logger LOGGER = LogManager.getLogger(); ++ ++ private final ResourceKey dimensionType; ++ private final ResourceKey worldKey; ++ private final String worldName; ++ private final ExecutorService threadPool; ++ private final DataFixer dataFixer; ++ private final boolean removeCaches; ++ ++ public ThreadedWorldUpgrader(final ResourceKey dimensionType, final ResourceKey worldKey, final String worldName, final int threads, ++ final DataFixer dataFixer, final boolean removeCaches) { ++ this.dimensionType = dimensionType; ++ this.worldKey = worldKey; ++ this.worldName = worldName; ++ this.threadPool = Executors.newFixedThreadPool(Math.max(1, threads), new ThreadFactory() { ++ private final AtomicInteger threadCounter = new AtomicInteger(); ++ ++ @Override ++ public Thread newThread(final Runnable run) { ++ final Thread ret = new Thread(run); ++ ++ ret.setName("World upgrader thread for world " + ThreadedWorldUpgrader.this.worldName + " #" + this.threadCounter.getAndIncrement()); ++ ret.setUncaughtExceptionHandler((thread, throwable) -> { ++ LOGGER.fatal("Error upgrading world", throwable); ++ }); ++ ++ return ret; ++ } ++ }); ++ this.dataFixer = dataFixer; ++ this.removeCaches = removeCaches; ++ } ++ ++ public void convert() { ++ final File worldFolder = LevelStorageSource.getFolder(new File(this.worldName), this.dimensionType); ++ final DimensionDataStorage worldPersistentData = new DimensionDataStorage(new File(worldFolder, "data"), this.dataFixer); ++ ++ final File regionFolder = new File(worldFolder, "region"); ++ ++ LOGGER.info("Force upgrading " + this.worldName); ++ LOGGER.info("Counting regionfiles for " + this.worldName); ++ final File[] regionFiles = regionFolder.listFiles((final File dir, final String name) -> { ++ return WorldUpgrader.getRegionfileRegex().matcher(name).matches(); ++ }); ++ if (regionFiles == null) { ++ LOGGER.info("Found no regionfiles to convert for world " + this.worldName); ++ return; ++ } ++ LOGGER.info("Found " + regionFiles.length + " regionfiles to convert"); ++ LOGGER.info("Starting conversion now for world " + this.worldName); ++ ++ final WorldInfo info = new WorldInfo(() -> worldPersistentData, ++ new ChunkStorage(regionFolder, this.dataFixer, false), this.removeCaches, this.worldKey); ++ ++ long expectedChunks = (long)regionFiles.length * (32L * 32L); ++ ++ for (final File regionFile : regionFiles) { ++ final ChunkPos regionPos = RegionFileStorage.getRegionFileCoordinates(regionFile); ++ if (regionPos == null) { ++ expectedChunks -= (32L * 32L); ++ continue; ++ } ++ ++ this.threadPool.execute(new ConvertTask(info, regionPos.x >> 5, regionPos.z >> 5)); ++ } ++ this.threadPool.shutdown(); ++ ++ final DecimalFormat format = new DecimalFormat("#0.00"); ++ ++ final long start = System.nanoTime(); ++ ++ while (!this.threadPool.isTerminated()) { ++ final long current = info.convertedChunks.get(); ++ ++ LOGGER.info("{}% completed ({} / {} chunks)...", format.format((double)current / (double)expectedChunks * 100.0), current, expectedChunks); ++ ++ try { ++ Thread.sleep(1000L); ++ } catch (final InterruptedException ignore) {} ++ } ++ ++ final long end = System.nanoTime(); ++ ++ try { ++ info.loader.close(); ++ } catch (final IOException ex) { ++ LOGGER.fatal("Failed to close chunk loader", ex); ++ } ++ LOGGER.info("Completed conversion. Took {}s, {} out of {} chunks needed to be converted/modified ({}%)", ++ (int)Math.ceil((end - start) * 1.0e-9), info.modifiedChunks.get(), expectedChunks, format.format((double)info.modifiedChunks.get() / (double)expectedChunks * 100.0)); ++ } ++ ++ private static final class WorldInfo { ++ ++ public final Supplier persistentDataSupplier; ++ public final ChunkStorage loader; ++ public final boolean removeCaches; ++ public final ResourceKey worldKey; ++ public final AtomicLong convertedChunks = new AtomicLong(); ++ public final AtomicLong modifiedChunks = new AtomicLong(); ++ ++ private WorldInfo(final Supplier persistentDataSupplier, final ChunkStorage loader, final boolean removeCaches, ++ final ResourceKey worldKey) { ++ this.persistentDataSupplier = persistentDataSupplier; ++ this.loader = loader; ++ this.removeCaches = removeCaches; ++ this.worldKey = worldKey; ++ } ++ } ++ ++ private static final class ConvertTask implements Runnable { ++ ++ private final WorldInfo worldInfo; ++ private final int regionX; ++ private final int regionZ; ++ ++ public ConvertTask(final WorldInfo worldInfo, final int regionX, final int regionZ) { ++ this.worldInfo = worldInfo; ++ this.regionX = regionX; ++ this.regionZ = regionZ; ++ } ++ ++ @Override ++ public void run() { ++ final int regionCX = this.regionX << 5; ++ final int regionCZ = this.regionZ << 5; ++ ++ final Supplier persistentDataSupplier = this.worldInfo.persistentDataSupplier; ++ final ChunkStorage loader = this.worldInfo.loader; ++ final boolean removeCaches = this.worldInfo.removeCaches; ++ final ResourceKey worldKey = this.worldInfo.worldKey; ++ ++ for (int cz = regionCZ; cz < (regionCZ + 32); ++cz) { ++ for (int cx = regionCX; cx < (regionCX + 32); ++cx) { ++ final ChunkPos chunkPos = new ChunkPos(cx, cz); ++ try { ++ // no need to check the coordinate of the chunk, the regionfilecache does that for us ++ ++ CompoundTag chunkNBT = loader.read(chunkPos); ++ ++ if (chunkNBT == null) { ++ continue; ++ } ++ ++ final int versionBefore = ChunkStorage.getVersion(chunkNBT); ++ ++ chunkNBT = loader.getChunkData(worldKey, persistentDataSupplier, chunkNBT, chunkPos, null); ++ ++ boolean modified = versionBefore < SharedConstants.getCurrentVersion().getWorldVersion(); ++ ++ if (removeCaches) { ++ final CompoundTag level = chunkNBT.getCompound("Level"); ++ modified |= level.contains("Heightmaps"); ++ level.remove("Heightmaps"); ++ modified |= level.contains("isLightOn"); ++ level.remove("isLightOn"); ++ } ++ ++ if (modified) { ++ this.worldInfo.modifiedChunks.getAndIncrement(); ++ loader.write(chunkPos, chunkNBT); ++ } ++ } catch (final Exception ex) { ++ LOGGER.error("Error upgrading chunk {}", chunkPos, ex); ++ } finally { ++ this.worldInfo.convertedChunks.getAndIncrement(); ++ } ++ } ++ } ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index ba6c17da4875c3a342da99e354c9f07cc7f17326..d0105061c714af4403b3e14e96e54e17a82c172b 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -15,6 +15,7 @@ import java.nio.file.Paths; + import java.util.Optional; + import java.util.concurrent.CompletableFuture; + import java.util.function.BooleanSupplier; ++import io.papermc.paper.world.ThreadedWorldUpgrader; + import joptsimple.NonOptionArgumentSpec; + import joptsimple.OptionParser; + import joptsimple.OptionSet; +@@ -269,6 +270,15 @@ public class Main { + } + // Paper end + ++ // Paper start - fix and optimise world upgrading ++ public static void convertWorldButItWorks(ResourceKey dimensionType, ResourceKey worldKey, String worldName, ++ DataFixer dataFixer, boolean removeCaches) { ++ int threads = Runtime.getRuntime().availableProcessors() * 3 / 8; ++ final ThreadedWorldUpgrader worldUpgrader = new ThreadedWorldUpgrader(dimensionType, worldKey, worldName, threads, dataFixer, removeCaches); ++ worldUpgrader.convert(); ++ } ++ // Paper end - fix and optimise world upgrading ++ + public static void forceUpgrade(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, boolean eraseCache, BooleanSupplier booleansupplier, ImmutableSet> worlds) { // CraftBukkit + Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit + WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, worlds, eraseCache); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index fd76d776c7003585c9efef44c6d7da0f6c3f574e..9d7cebd703bd0171ca3e95d2985c1a52fdb59712 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -512,13 +512,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +- return true; +- }, worlddata.worldGenSettings().dimensions().entrySet().stream().map((entry1) -> { +- return ResourceKey.create(Registry.DIMENSION_TYPE_REGISTRY, ((ResourceKey) entry1.getKey()).location()); +- }).collect(ImmutableSet.toImmutableSet())); +- } ++ // Paper - move down + + ServerLevelData iworlddataserver = worlddata; + WorldGenSettings generatorsettings = worlddata.worldGenSettings(); +@@ -538,6 +532,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, dimensionKey.location()); + + if (dimensionKey == LevelStem.OVERWORLD) { +diff --git a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java +index 79491c5081dbc0cc479d6bc0329ff9b374559c9b..29c0fe698e91e232bcebfafdd853d222c83d5af8 100644 +--- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java ++++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java +@@ -52,7 +52,7 @@ public class WorldUpgrader { + private volatile int skipped; + private final Object2FloatMap> progressMap = Object2FloatMaps.synchronize(new Object2FloatOpenCustomHashMap(Util.identityStrategy())); // CraftBukkit + private volatile Component status = new TranslatableComponent("optimizeWorld.stage.counting"); +- private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); ++ private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); public static final Pattern getRegionfileRegex() { return REGEX; } // Paper - OBFHELPER + private final DimensionDataStorage overworldDataStorage; + + public WorldUpgrader(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, ImmutableSet> worlds, boolean eraseCache) { // CraftBukkit +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 4523bc1f49e7be248a47eeb599fa7b6550dbb08d..d155d00abf8f423e64e6e6d80ddadbc1cfb58a64 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -181,6 +181,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return typeKey; + } + ++ // Paper start - fix and optimise world upgrading ++ // copied from below ++ public static ResourceKey getDimensionKey(DimensionType manager) { ++ return ((org.bukkit.craftbukkit.CraftServer)org.bukkit.Bukkit.getServer()).getHandle().getServer().registryHolder.dimensionTypes().getResourceKey(manager).orElseThrow(() -> { ++ return new IllegalStateException("Unregistered dimension type: " + manager); ++ }); ++ } ++ // Paper end - fix and optimise world upgrading ++ + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot + this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +index 1af804c5c6fb2b20ea3f020610763c1d7dcee110..0e38f2f31d167c417b707f00aa68cacaef3d9f6c 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -109,6 +109,7 @@ public class ChunkStorage implements AutoCloseable { + return nbttagcompound; + } + ++ public static int getVersion(CompoundTag nbttagcompound) { return getVersion(nbttagcompound); } // Paper - OBFHELPER + public static int getVersion(CompoundTag tag) { + return tag.contains("DataVersion", 99) ? tag.getInt("DataVersion") : -1; + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index 0498982ac14f20145d68dbf64a46bcaacf5516ef..7a01f2fbe459e36cee5416455a049b25963e257a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -30,6 +30,28 @@ public class RegionFileStorage implements AutoCloseable { // Paper - no final + + + // Paper start ++ public static ChunkPos getRegionFileCoordinates(File file) { ++ String fileName = file.getName(); ++ if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) { ++ return null; ++ } ++ ++ String[] split = fileName.split("\\."); ++ ++ if (split.length != 4) { ++ return null; ++ } ++ ++ try { ++ int x = Integer.parseInt(split[1]); ++ int z = Integer.parseInt(split[2]); ++ ++ return new ChunkPos(x << 5, z << 5); ++ } catch (NumberFormatException ex) { ++ return null; ++ } ++ } ++ + public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { // Paper - synchronize for async io + return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index f1e6d0050092ad51bf233c80b6a51a121e961b07..831f187cde88e815c9a859e52ab45fbbe054f83e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1145,14 +1145,7 @@ public final class CraftServer implements Server { + } + worlddata.checkName(name); + worlddata.setModdedInfo(console.getServerModName(), console.getModdedStatus().isPresent()); +- +- if (console.options.has("forceUpgrade")) { +- net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), console.options.has("eraseCache"), () -> { +- return true; +- }, worlddata.worldGenSettings().dimensions().entrySet().stream().map((entry) -> { +- return ResourceKey.create(Registry.DIMENSION_TYPE_REGISTRY, ((ResourceKey) entry.getKey()).location()); +- }).collect(ImmutableSet.toImmutableSet())); +- } ++ // Paper - move down + + long j = BiomeManager.obfuscateSeed(creator.seed()); + List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata)); +@@ -1169,6 +1162,14 @@ public final class CraftServer implements Server { + chunkgenerator = worlddimension.generator(); + } + ++ // Paper start - fix and optimise world upgrading ++ if (console.options.has("forceUpgrade")) { ++ net.minecraft.server.Main.convertWorldButItWorks( ++ actualDimension, net.minecraft.world.level.Level.getDimensionKey(dimensionmanager), worldSession.getLevelId(), DataFixers.getDataFixer(), console.options.has("eraseCache") ++ ); ++ } ++ // Paper end - fix and optimise world upgrading ++ + ResourceKey worldKey; + String levelName = this.getServer().getProperties().levelName; + if (name.equals(levelName + "_nether")) { diff --git a/patches/server-remapped/0739-Add-Mob-lookAt-API.patch b/patches/server-remapped/0739-Add-Mob-lookAt-API.patch new file mode 100644 index 0000000000..ce42177784 --- /dev/null +++ b/patches/server-remapped/0739-Add-Mob-lookAt-API.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 14 May 2021 13:42:17 -0500 +Subject: [PATCH] Add Mob#lookAt API + + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index ea34306858116e5626383af408529091836c2752..5692b497875ba2ee455859bc8a88d7888afd86fc 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -850,14 +850,17 @@ public abstract class Mob extends LivingEntity { + + protected void customServerAiStep() {} + ++ public int getMaxHeadXRot() { return getMaxHeadXRot(); } // Paper - OBFHELPER + public int getMaxHeadXRot() { + return 40; + } + ++ public int getMaxHeadYRot() { return getMaxHeadYRot(); } // Paper - OBFHELPER + public int getMaxHeadYRot() { + return 75; + } + ++ public int getHeadRotSpeed() { return getHeadRotSpeed(); } // Paper - OBFHELPER + public int getHeadRotSpeed() { + return 10; + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java b/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java +index faba4a95883bb0fcfd4f65c3f62bd6f476ded249..3fe159c4bdc3ad3e95354e18e2921305af121725 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java +@@ -20,18 +20,28 @@ public class LookControl { + this.mob = entity; + } + ++ public void lookAt(Vec3 vec3d) { setLookAt(vec3d); } // Paper - OBFHELPER + public void setLookAt(Vec3 direction) { + this.setLookAt(direction.x, direction.y, direction.z); + } + ++ // Paper start ++ public void lookAt(Entity entity) { ++ this.lookAt(entity.getX(), getWantedY(entity), entity.getZ()); ++ } ++ // Paper end ++ ++ public void lookAt(Entity entity, float f, float f1) { setLookAt(entity, f, f1); } // Paper - OBFHELPER + public void setLookAt(Entity entity, float yawSpeed, float pitchSpeed) { + this.setLookAt(entity.getX(), getWantedY(entity), entity.getZ(), yawSpeed, pitchSpeed); + } + ++ public void lookAt(double d0, double d1, double d2) { setLookAt(d0, d1, d2); } // Paper - OBFHELPER + public void setLookAt(double x, double y, double z) { + this.setLookAt(x, y, z, (float) this.mob.getHeadRotSpeed(), (float) this.mob.getMaxHeadXRot()); + } + ++ public void lookAt(double d0, double d1, double d2, float f, float f1) { setLookAt(d0, d1, d2, f, f1); } // Paper - OBFHELPER + public void setLookAt(double x, double y, double z, float yawSpeed, float pitchSpeed) { + this.wantedX = x; + this.wantedY = y; +@@ -103,6 +113,7 @@ public class LookControl { + return from + f4; + } + ++ public static double getWantedY(Entity entity) { return getWantedY(entity); } // Paper - OBFHELPER + private static double getWantedY(Entity entity) { + return entity instanceof LivingEntity ? entity.getEyeY() : (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0D; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +index 1e3a0851c75d8067d2699f00bb3f6621d1d739d8..f597cf70779fde265cc45868aba3ae9db898fb6e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +@@ -83,5 +83,53 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { + public boolean isInDaylight() { + return getHandle().isInDaylight(); + } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location) { ++ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); ++ getHandle().getLookControl().lookAt(location.getX(), location.getY(), location.getZ()); ++ } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location, float headRotationSpeed, float maxHeadPitch) { ++ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); ++ getHandle().getLookControl().lookAt(location.getX(), location.getY(), location.getZ(), headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity) { ++ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); ++ getHandle().getLookControl().lookAt(((CraftEntity) entity).getHandle()); ++ } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity, float headRotationSpeed, float maxHeadPitch) { ++ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); ++ getHandle().getLookControl().lookAt(((CraftEntity) entity).getHandle(), headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public void lookAt(double x, double y, double z) { ++ getHandle().getLookControl().lookAt(x, y, z); ++ } ++ ++ @Override ++ public void lookAt(double x, double y, double z, float headRotationSpeed, float maxHeadPitch) { ++ getHandle().getLookControl().lookAt(x, y, z, headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public int getHeadRotationSpeed() { ++ return getHandle().getHeadRotSpeed(); ++ } ++ ++ @Override ++ public int getMaxHeadPitch() { ++ return getHandle().getMaxHeadXRot(); ++ } + // Paper end + } diff --git a/patches/server-remapped/0740-Add-Unix-domain-socket-support.patch b/patches/server-remapped/0740-Add-Unix-domain-socket-support.patch new file mode 100644 index 0000000000..83c74f604e --- /dev/null +++ b/patches/server-remapped/0740-Add-Unix-domain-socket-support.patch @@ -0,0 +1,141 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Tue, 11 May 2021 17:39:22 -0400 +Subject: [PATCH] Add Unix domain socket support + +For Windows and ARM support, JEP-380 is required: +https://inside.java/2021/02/03/jep380-unix-domain-sockets-channels/ +This will be possible as of the Minecraft 1.17 Java version bump. + +Tested-by: Mariell Hoversholm +Reviewed-by: Mariell Hoversholm + +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 3ba9c38fc44a8edba9b504112a383249052a0035..cc823a1337bea3ad552687add46706128311f26d 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -564,6 +564,11 @@ public class Connection extends SimpleChannelInboundHandler> { + // Spigot Start + public SocketAddress getRawAddress() + { ++ // Paper start - this can be nullable in the case of a Unix domain socket, so if it is, fake something ++ if (this.channel.remoteAddress() == null) { ++ return new java.net.InetSocketAddress(java.net.InetAddress.getLoopbackAddress(), 0); ++ } ++ // Paper end + return this.channel.remoteAddress(); + } + // Spigot End +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 0198268bc614b190cd84f625a62f6c55247a01c8..2821fa9505d6b5adc8e776219df024713fc1a486 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -222,6 +222,20 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist); + // this.saveData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading + DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode); ++ // Paper start - Unix domain socket support ++ java.net.SocketAddress bindAddress; ++ if (this.getLocalIp().startsWith("unix:")) { ++ if (!io.netty.channel.epoll.Epoll.isAvailable()) { ++ DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!"); ++ DedicatedServer.LOGGER.fatal("You are trying to use a Unix domain socket but you're not on a supported OS."); ++ return false; ++ } else if (!com.destroystokyo.paper.PaperConfig.velocitySupport && !org.spigotmc.SpigotConfig.bungee) { ++ DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!"); ++ DedicatedServer.LOGGER.fatal("Unix domain sockets require IPs to be forwarded from a proxy."); ++ return false; ++ } ++ bindAddress = new io.netty.channel.unix.DomainSocketAddress(this.getLocalIp().substring("unix:".length())); ++ } else { + InetAddress inetaddress = null; + + if (!this.getLocalIp().isEmpty()) { +@@ -231,12 +245,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + if (this.getPort() < 0) { + this.setPort(dedicatedserverproperties.serverPort); + } ++ bindAddress = new java.net.InetSocketAddress(inetaddress, this.getPort()); ++ } ++ // Paper end + + this.initializeKeyPair(); + DedicatedServer.LOGGER.info("Starting Minecraft server on {}:{}", this.getLocalIp().isEmpty() ? "*" : this.getLocalIp(), this.getPort()); + + try { +- this.getConnection().startTcpServerListener(inetaddress, this.getPort()); ++ this.getConnection().bind(bindAddress); // Paper - Unix domain socket support + } catch (IOException ioexception) { + DedicatedServer.LOGGER.warn("**** FAILED TO BIND TO PORT!"); + DedicatedServer.LOGGER.warn("The exception was: {}", ioexception.toString()); +diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +index bcc19d0a4b6c5f683dc416e27a13705b57213d21..67a17ced9460bc83a6f564b38fdb43b1a7f1b8a0 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +@@ -70,7 +70,12 @@ public class ServerConnectionListener { + this.running = true; + } + ++ // Paper start + public void startTcpServerListener(@Nullable InetAddress address, int port) throws IOException { ++ bind(new java.net.InetSocketAddress(address, port)); ++ } ++ public void bind(java.net.SocketAddress address) throws IOException { ++ // Paper end + List list = this.channels; + + synchronized (this.channels) { +@@ -78,7 +83,11 @@ public class ServerConnectionListener { + LazyLoadedValue lazyinitvar; + + if (Epoll.isAvailable() && this.server.isEpollEnabled()) { ++ if (address instanceof io.netty.channel.unix.DomainSocketAddress) { ++ oclass = io.netty.channel.epoll.EpollServerDomainSocketChannel.class; ++ } else { + oclass = EpollServerSocketChannel.class; ++ } + lazyinitvar = ServerConnectionListener.SERVER_EPOLL_EVENT_GROUP; + ServerConnectionListener.LOGGER.info("Using epoll channel type"); + } else { +@@ -106,7 +115,7 @@ public class ServerConnectionListener { + ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); + io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper + } +- }).group((EventLoopGroup) lazyinitvar.get()).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit ++ }).group((EventLoopGroup) lazyinitvar.get()).localAddress(address)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit // Paper + } + } + +diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 4e055a41de3ee410682cc05a3b883ac8babeb290..e1fbb207d6921516c7423e9a3cded8efb5676d49 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -44,6 +44,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + this.connection.setProtocol(ConnectionProtocol.LOGIN); + // CraftBukkit start - Connection throttle + try { ++ if (!(this.connection.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress)) { // Paper - the connection throttle is useless when you have a Unix domain socket + long currentTime = System.currentTimeMillis(); + long connectionThrottle = this.server.server.getConnectionThrottle(); + InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress(); +@@ -72,6 +73,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + } + } + } ++ } // Paper - add closing bracket for if check above + } catch (Throwable t) { + org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); + } +@@ -120,8 +122,11 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! + String[] split = packet.hostName.split("\00"); + if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper ++ // Paper start - Unix domain socket support ++ java.net.SocketAddress socketAddress = connection.getRemoteAddress(); + packet.hostName = split[0]; +- connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort()); ++ connection.address = new java.net.InetSocketAddress(split[1], socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); ++ // Paper end + connection.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); + } else + { diff --git a/patches/server-remapped/0741-Add-EntityInsideBlockEvent.patch b/patches/server-remapped/0741-Add-EntityInsideBlockEvent.patch new file mode 100644 index 0000000000..6380d78daa --- /dev/null +++ b/patches/server-remapped/0741-Add-EntityInsideBlockEvent.patch @@ -0,0 +1,222 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 8 May 2021 18:02:36 -0700 +Subject: [PATCH] Add EntityInsideBlockEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +index ad37261e716b15d62fc2083d137cdac818308cdd..58519e224a5005bf6468b99196acb7209b2e1398 100644 +--- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +@@ -48,6 +48,7 @@ public abstract class BaseFireBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!entity.fireImmune()) { + entity.setRemainingFireTicks(entity.getRemainingFireTicks() + 1); + if (entity.getRemainingFireTicks() == 0) { +diff --git a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java +index 6acb24f96591d555e550d399d2ed38036a0220fe..8d8fd646c9527852bfe9a2d3cd0a6bf1bfa9e4a2 100644 +--- a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java +@@ -65,6 +65,7 @@ public abstract class BasePressurePlateBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide) { + int i = this.getSignalForState(state); + +diff --git a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java +index f741980d0e1759e3fefe322b654760dab35200d6..faa1070aaf3fcc40bf7e36a0dda8ec7879c89dd6 100644 +--- a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java +@@ -33,6 +33,7 @@ public class BubbleColumnBlock extends Block implements BucketPickup { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + BlockState iblockdata1 = world.getBlockState(pos.above()); + + if (iblockdata1.isAir()) { +diff --git a/src/main/java/net/minecraft/world/level/block/ButtonBlock.java b/src/main/java/net/minecraft/world/level/block/ButtonBlock.java +index 52ca5dad75674b81b997f8a1cf3f5d52bf4313c1..2c4c5fc6d45225cc9f7f1c2038bd4d0ae20c9daa 100644 +--- a/src/main/java/net/minecraft/world/level/block/ButtonBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ButtonBlock.java +@@ -179,6 +179,7 @@ public abstract class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide && this.sensitive && !(Boolean) state.getValue(ButtonBlock.POWERED)) { + this.checkPressed(state, world, pos); + } +diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java +index de61393e3f702554817d81ff10693ec3fb63d492..28b083a8220856723b6169b5b13677b965a4dab6 100644 +--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java +@@ -115,6 +115,7 @@ public class CactusBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + CraftEventFactory.blockDamage = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit + entity.hurt(DamageSource.CACTUS, 1.0F); + CraftEventFactory.blockDamage = null; // CraftBukkit +diff --git a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java +index 87f106ad9139157af69a0ae1602c32ed372a04be..b0c6ac74daea347f4acb5da95e6b0cb013827509 100644 +--- a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java +@@ -88,6 +88,7 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!entity.fireImmune() && (Boolean) state.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { + entity.hurt(DamageSource.IN_FIRE, (float) this.fireDamage); + } +diff --git a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java +index 941061b50f7909278e962fb2aa080bb630862aa1..7d23adaa833c9c45708705294969fe268153b927 100644 +--- a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java +@@ -58,6 +58,7 @@ public class CauldronBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + int i = (Integer) state.getValue(CauldronBlock.LEVEL); + float f = (float) pos.getY() + (6.0F + (float) (3 * i)) / 16.0F; + +diff --git a/src/main/java/net/minecraft/world/level/block/CropBlock.java b/src/main/java/net/minecraft/world/level/block/CropBlock.java +index 4cd6f18e0a2ee8d0495b3c822b227e212a13b11f..8368a5911690a9abb26c0f381bda7a0633197548 100644 +--- a/src/main/java/net/minecraft/world/level/block/CropBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CropBlock.java +@@ -159,6 +159,7 @@ public class CropBlock extends BushBlock implements BonemealableBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (entity instanceof Ravager && !CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)).isCancelled()) { // CraftBukkit + world.destroyBlock(pos, true, entity); + } +diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +index 1854809e045300e84a713dc7c3a8264f53ec6c0f..d970fe7137f7dd37221b54e4025b98d15b950489 100644 +--- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +@@ -44,6 +44,7 @@ public class DetectorRailBlock extends BaseRailBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide) { + if (!(Boolean) state.getValue(DetectorRailBlock.POWERED)) { + this.checkPressed(world, pos, state); +diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +index a6d793478be8e2aab1f72b68a6a96c86642ad1fc..2231680140d0e3c4c10b6722fd13fe0ee55ce294 100644 +--- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +@@ -41,6 +41,7 @@ public class EndPortalBlock extends BaseEntityBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (world instanceof ServerLevel && !entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-pos.getX()), (double) (-pos.getY()), (double) (-pos.getZ()))), state.getShape(world, pos), BooleanOp.AND)) { + ResourceKey resourcekey = world.getTypeKey() == DimensionType.END_LOCATION ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends + ServerLevel worldserver = ((ServerLevel) world).getServer().getLevel(resourcekey); +diff --git a/src/main/java/net/minecraft/world/level/block/HoneyBlock.java b/src/main/java/net/minecraft/world/level/block/HoneyBlock.java +index 7d0206dc5ac46220970adad51863028840b4a9ad..ef74852a1677a4ec80149aa7eafca910fac5ee91 100644 +--- a/src/main/java/net/minecraft/world/level/block/HoneyBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/HoneyBlock.java +@@ -49,6 +49,7 @@ public class HoneyBlock extends HalfTransparentBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (this.isSlidingDown(pos, entity)) { + this.maybeDoSlideAchievement(entity, pos); + this.doSlideMovement(entity); +diff --git a/src/main/java/net/minecraft/world/level/block/HopperBlock.java b/src/main/java/net/minecraft/world/level/block/HopperBlock.java +index 1f50c2b4bebeb6a224eb0ac552d6ea693f7831a6..40b1bba69ae96e4cd652261e3f97850e2e7c51a3 100644 +--- a/src/main/java/net/minecraft/world/level/block/HopperBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/HopperBlock.java +@@ -197,6 +197,7 @@ public class HopperBlock extends BaseEntityBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + BlockEntity tileentity = world.getBlockEntity(pos); + + if (tileentity instanceof HopperBlockEntity) { +diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +index ae58929886921d0714bf811de92f99dc0dc120dc..53e7570cc2538e73f1cfe3d28ffc491f61cac372 100644 +--- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -81,6 +81,7 @@ public class NetherPortalBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions()) { + // CraftBukkit start - Entity in portal + EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); +diff --git a/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java b/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java +index 09122e2031e9ddfae4544911f8c25b937b03933f..6b5e8654ddd2c268627d0244b01dadeaeb4a7de4 100644 +--- a/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java +@@ -66,6 +66,7 @@ public class SweetBerryBushBlock extends BushBlock implements BonemealableBlock + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (entity instanceof LivingEntity && entity.getType() != EntityType.FOX && entity.getType() != EntityType.BEE) { + entity.makeStuckInBlock(state, new Vec3(0.800000011920929D, 0.75D, 0.800000011920929D)); + if (!world.isClientSide && (Integer) state.getValue(SweetBerryBushBlock.AGE) > 0 && (entity.xOld != entity.getX() || entity.zOld != entity.getZ())) { +diff --git a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java +index eaee409bc8fbf8c5541afd10d24975535556a7f6..a488a2a589126df617564d9278eb0496915b6f88 100644 +--- a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java +@@ -118,6 +118,7 @@ public class TripWireBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide) { + if (!(Boolean) state.getValue(TripWireBlock.POWERED)) { + this.checkPressed(world, pos); +diff --git a/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java b/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java +index 2b2a28d0383ccc8c0e7debd90331570b02b5e65f..bd4295f8d24ca9fd8c3af31abcd13da24db1c5d5 100644 +--- a/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java +@@ -25,6 +25,7 @@ public class WaterlilyBlock extends BushBlock { + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { + super.entityInside(state, world, pos, entity); ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (world instanceof ServerLevel && entity instanceof Boat && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { // CraftBukkit + world.destroyBlock(new BlockPos(pos), true, entity); + } +diff --git a/src/main/java/net/minecraft/world/level/block/WebBlock.java b/src/main/java/net/minecraft/world/level/block/WebBlock.java +index c368531420d464414de3661e1624e2a284976ab6..fc1c2e057e8b63048c919b5cbcc0a0e897f1dd01 100644 +--- a/src/main/java/net/minecraft/world/level/block/WebBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/WebBlock.java +@@ -15,6 +15,7 @@ public class WebBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + entity.makeStuckInBlock(state, new Vec3(0.25D, 0.05000000074505806D, 0.25D)); + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java b/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java +index c1648c28c761cdf31089d434f9cb896ddef41521..5cb4e1ec7ce3087163d2ecf26d043894310768d1 100644 +--- a/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java +@@ -26,6 +26,7 @@ public class WitherRoseBlock extends FlowerBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide && world.getDifficulty() != Difficulty.PEACEFUL) { + if (entity instanceof LivingEntity) { + LivingEntity entityliving = (LivingEntity) entity; diff --git a/patches/server-remapped/0742-Attributes-API-for-item-defaults.patch b/patches/server-remapped/0742-Attributes-API-for-item-defaults.patch new file mode 100644 index 0000000000..ce7b672b14 --- /dev/null +++ b/patches/server-remapped/0742-Attributes-API-for-item-defaults.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 8 May 2021 15:01:54 -0700 +Subject: [PATCH] Attributes API for item defaults + + +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index 42085d3f4ae5c6ceecaffde79fb3187712a2af00..3043378c3addf959e0ccf323c1cde8b300b5f237 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -274,6 +274,7 @@ public class Item implements ItemLike { + return false; + } + ++ public Multimap getAttributesForSlot(EquipmentSlot enumItemSlot) { return getDefaultAttributeModifiers(enumItemSlot); } // Paper - OBFHELPER + public Multimap getDefaultAttributeModifiers(EquipmentSlot slot) { + return ImmutableMultimap.of(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 34eed57c7ed884e0d634ca403e38d25c95b6a038..824111fc74bade75ce06b1f0b57498006d0a66cd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -493,6 +493,19 @@ public final class CraftMagicNumbers implements UnsafeValues { + return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); + } + ++ @Override ++ public com.google.common.collect.Multimap getItemAttributes(org.bukkit.Material material, org.bukkit.inventory.EquipmentSlot equipmentSlot) { ++ Item item = this.getItem(material); ++ if (item == null) { ++ throw new IllegalArgumentException(material + " is not an item and therefore does not have attributes"); ++ } ++ com.google.common.collect.ImmutableMultimap.Builder attributeMapBuilder = com.google.common.collect.ImmutableMultimap.builder(); ++ item.getAttributesForSlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(equipmentSlot)).forEach((attributeBase, attributeModifier) -> { ++ attributeMapBuilder.put(org.bukkit.Registry.ATTRIBUTE.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.Registry.ATTRIBUTE.getKey(attributeBase))), org.bukkit.craftbukkit.attribute.CraftAttributeInstance.convert(attributeModifier)); ++ }); ++ return attributeMapBuilder.build(); ++ } ++ + @Override + public int getProtocolVersion() { + return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion(); diff --git a/patches/server-remapped/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/patches/server-remapped/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch new file mode 100644 index 0000000000..339837dc3e --- /dev/null +++ b/patches/server-remapped/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexander +Date: Thu, 6 May 2021 13:01:25 +0100 +Subject: [PATCH] Have CraftMerchantCustom emit PlayerPurchaseEvent + + +diff --git a/src/main/java/net/minecraft/world/item/trading/Merchant.java b/src/main/java/net/minecraft/world/item/trading/Merchant.java +index 8298e667aa3a17d987bbc4cc2b63600af48beabc..334df355470bff98db63396b33c8db6a0abcc61a 100644 +--- a/src/main/java/net/minecraft/world/item/trading/Merchant.java ++++ b/src/main/java/net/minecraft/world/item/trading/Merchant.java +@@ -19,7 +19,7 @@ public interface Merchant { + + MerchantOffers getOffers(); + +- void notifyTrade(MerchantOffer offer); ++ void notifyTrade(MerchantOffer offer); default void handlePurchase(MerchantOffer merchantRecipe) { notifyTrade(merchantRecipe); } // Paper - OBFHELPER + + void notifyTradeUpdated(ItemStack stack); + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +index 306c6483708ae1b41bd16f122d36beec1916a776..d52192545c39734be3c97c7978652a54d7b9f029 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +@@ -81,6 +81,35 @@ public class CraftMerchantCustom extends CraftMerchant { + + @Override + public void notifyTrade(MerchantOffer offer) { ++ // Paper start ++ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerAbstract#b(MerchantRecipe)} */ ++ if (getTradingPlayer() instanceof net.minecraft.server.level.ServerPlayer) { ++ final net.minecraft.server.level.ServerPlayer trader = (net.minecraft.server.level.ServerPlayer) getTradingPlayer(); ++ final io.papermc.paper.event.player.PlayerPurchaseEvent event = new io.papermc.paper.event.player.PlayerPurchaseEvent( ++ trader.getBukkitEntity(), ++ offer.asBukkit(), ++ false, // reward xp? ++ true); // should increase uses? ++ event.callEvent(); ++ if (event.isCancelled()) { ++ return; ++ } ++ final org.bukkit.inventory.MerchantRecipe eventTrade = event.getTrade(); ++ if (event.willIncreaseTradeUses()) { ++ eventTrade.setUses(eventTrade.getUses() + 1); ++ } ++ if (event.isRewardingExp() && eventTrade.hasExperienceReward()) { ++ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerTrader#b(MerchantRecipe)} */ ++ final int xp = 3 + net.minecraft.world.entity.Entity.SHARED_RANDOM.nextInt(4); ++ final Level world = trader.getCommandSenderWorld(); ++ world.addFreshEntity(new net.minecraft.world.entity.ExperienceOrb( ++ world, trader.getX(), trader.getY() + 0.5d, trader.getZ(), xp, ++ org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, trader, null)); ++ } ++ return; ++ } ++ // Paper end ++ + // increase recipe's uses + offer.increaseUses(); + } diff --git a/patches/server-remapped/0744-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/server-remapped/0744-Add-cause-to-Weather-ThunderChangeEvents.patch new file mode 100644 index 0000000000..fb889a4693 --- /dev/null +++ b/patches/server-remapped/0744-Add-cause-to-Weather-ThunderChangeEvents.patch @@ -0,0 +1,136 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 2 Dec 2020 18:23:26 -0800 +Subject: [PATCH] Add cause to Weather/ThunderChangeEvents + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 511e6a941d441c55a4b38660f0f7f8c47fa689dd..85e62e3c52950a517c4dbae739d21d879cb467a4 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -413,8 +413,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.worldDataServer.setClearWeatherTime(clearDuration); + this.worldDataServer.setRainTime(rainDuration); + this.worldDataServer.setThunderTime(rainDuration); +- this.worldDataServer.setRaining(raining); +- this.worldDataServer.setThundering(thundering); ++ this.worldDataServer.setRaining(raining, org.bukkit.event.weather.WeatherChangeEvent.Cause.COMMAND); // Paper ++ this.worldDataServer.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.COMMAND); // Paper + } + + public Biome getBiomeBySeed(int i, int j, int k) { return getUncachedNoiseBiome(i, j, k); } // Paper - OBFHELPER +@@ -476,8 +476,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.worldDataServer.setThunderTime(j); + this.worldDataServer.setRainTime(k); + this.worldDataServer.setClearWeatherTime(i); +- this.worldDataServer.setThundering(flag1); +- this.worldDataServer.setRaining(flag2); ++ this.worldDataServer.setThundering(flag1, org.bukkit.event.weather.ThunderChangeEvent.Cause.NATURAL); // Paper ++ this.worldDataServer.setRaining(flag2, org.bukkit.event.weather.WeatherChangeEvent.Cause.NATURAL); // Paper + } + + this.oThunderLevel = this.thunderLevel; +@@ -879,14 +879,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + private void stopWeather() { + // CraftBukkit start +- this.worldDataServer.setRaining(false); ++ this.worldDataServer.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - when passing the night + // If we stop due to everyone sleeping we should reset the weather duration to some other random value. + // Not that everyone ever manages to get the whole server to sleep at the same time.... + if (!this.worldDataServer.isRaining()) { + this.worldDataServer.setRainTime(0); + } + // CraftBukkit end +- this.worldDataServer.setThundering(false); ++ this.worldDataServer.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - when passing the night + // CraftBukkit start + // If we stop due to everyone sleeping we should reset the weather duration to some other random value. + // Not that everyone ever manages to get the whole server to sleep at the same time.... +diff --git a/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java b/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java +index 83f2fdfa1ac2435f5199b5c33bfc409d2e94f4ed..e902534fd64f72e46feefa04f526e0dacd612627 100644 +--- a/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java ++++ b/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java +@@ -325,21 +325,26 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { + + @Override + public void setThundering(boolean thundering) { ++ // Paper start ++ this.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.UNKNOWN); ++ } ++ public void setThundering(boolean flag, org.bukkit.event.weather.ThunderChangeEvent.Cause cause) { ++ // Paper end + // CraftBukkit start +- if (this.thundering == thundering) { ++ if (this.thundering == flag) { + return; + } + + org.bukkit.World world = Bukkit.getWorld(getLevelName()); + if (world != null) { +- ThunderChangeEvent thunder = new ThunderChangeEvent(world, thundering); ++ ThunderChangeEvent thunder = new ThunderChangeEvent(world, flag, cause); // Paper + Bukkit.getServer().getPluginManager().callEvent(thunder); + if (thunder.isCancelled()) { + return; + } + } + // CraftBukkit end +- this.thundering = thundering; ++ this.thundering = flag; + } + + @Override +@@ -359,21 +364,27 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { + + @Override + public void setRaining(boolean raining) { ++ // Paper start ++ this.setRaining(raining, org.bukkit.event.weather.WeatherChangeEvent.Cause.UNKNOWN); ++ } ++ ++ public void setStorm(boolean flag, org.bukkit.event.weather.WeatherChangeEvent.Cause cause) { ++ // Paper end + // CraftBukkit start +- if (this.raining == raining) { ++ if (this.raining == flag) { + return; + } + + org.bukkit.World world = Bukkit.getWorld(getLevelName()); + if (world != null) { +- WeatherChangeEvent weather = new WeatherChangeEvent(world, raining); ++ WeatherChangeEvent weather = new WeatherChangeEvent(world, flag, cause); // Paper + Bukkit.getServer().getPluginManager().callEvent(weather); + if (weather.isCancelled()) { + return; + } + } + // CraftBukkit end +- this.raining = raining; ++ this.raining = flag; + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index a1fa2d5e00bd125abd38a00e0bc3936f2fb8186f..1c9321cef1a05c5e8a22dd52bc63a5103eaf7311 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1452,7 +1452,7 @@ public class CraftWorld implements World { + + @Override + public void setStorm(boolean hasStorm) { +- world.levelData.setRaining(hasStorm); ++ world.worldDataServer.setRaining(hasStorm, org.bukkit.event.weather.WeatherChangeEvent.Cause.PLUGIN); // Paper + setWeatherDuration(0); // Reset weather duration (legacy behaviour) + setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) + } +@@ -1474,7 +1474,7 @@ public class CraftWorld implements World { + + @Override + public void setThundering(boolean thundering) { +- world.worldDataServer.setThundering(thundering); ++ world.worldDataServer.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.PLUGIN); // Paper + setThunderDuration(0); // Reset weather duration (legacy behaviour) + setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) + } diff --git a/patches/server-remapped/0745-More-Lidded-Block-API.patch b/patches/server-remapped/0745-More-Lidded-Block-API.patch new file mode 100644 index 0000000000..5a3dcda899 --- /dev/null +++ b/patches/server-remapped/0745-More-Lidded-Block-API.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: LemonCaramel +Date: Sun, 23 May 2021 17:49:51 +0900 +Subject: [PATCH] More Lidded Block API + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java +index 8f0477d9620ef71e10855bbca07f9b6984d5d794..70ca456fad052ca6eeaf8c4242c78d15d81084a5 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java +@@ -10,8 +10,9 @@ public class EnderChestBlockEntity extends BlockEntity { // Paper - Remove ITick + + public float openness; + public float oOpenness; +- public int openCount; ++ public int openCount; public int getViewerCount() { return openCount; } // Paper - OBFHELPER + private int tickInterval; ++ public boolean opened; // Paper - More Lidded Block API + + public EnderChestBlockEntity() { + super(BlockEntityType.ENDER_CHEST); +@@ -106,12 +107,14 @@ public class EnderChestBlockEntity extends BlockEntity { // Paper - Remove ITick + + public void startOpen() { + ++this.openCount; ++ if (opened) return; // Paper - More Lidded Block API + this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); + doOpenLogic(); // Paper + } + + public void stopOpen() { + --this.openCount; ++ if (opened) return; // Paper - More Lidded Block API + this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); + doCloseLogic(); // Paper + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java +index a0eadcbcb2575eb18f7b4951ae9eadfbc2e8af6f..fc4397a48425a23d64e0a679ace9e58fbf9b770b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java +@@ -59,4 +59,11 @@ public class CraftBarrel extends CraftLootable implements Bar + } + getTileEntity().opened = false; + } ++ ++ // Paper start - More Lidded Block API ++ @Override ++ public boolean isOpen() { ++ return getTileEntity().opened; ++ } ++ // Paper end - More Lidded Block API + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +index a821df3e13e2ddc479dc5f55540671f43563cdac..9d7af8717085ba5c170a998aa863686d72840a40 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +@@ -78,4 +78,11 @@ public class CraftChest extends CraftLootable implements Chest + } + getTileEntity().opened = false; + } ++ ++ // Paper start - More Lidded Block API ++ @Override ++ public boolean isOpen() { ++ return getTileEntity().opened; ++ } ++ // Paper end - More Lidded Block API + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java +index 25add8bee6ea35beeb205dd828759304346e4f48..fabcb2b8dc950fd074d65fed95d6b371dcfbf842 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java +@@ -14,4 +14,33 @@ public class CraftEnderChest extends CraftBlockEntityState implem + if (getTileEntity().opened) { + Level world = getTileEntity().getLevel(); + world.blockEvent(getPosition(), getTileEntity().getBlockState().getBlock(), 1, 0); +- world.playSound(null, getPosition(), SoundEvents.SHULKER_BOX_OPEN, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); ++ world.playSound(null, getPosition(), SoundEvents.SHULKER_BOX_CLOSE, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); // Paper - More Lidded Block API (Wrong sound) + } + getTileEntity().opened = false; + } ++ ++ // Paper start - More Lidded Block API ++ @Override ++ public boolean isOpen() { ++ return getTileEntity().opened; ++ } ++ // Paper end - More Lidded Block API + } diff --git a/patches/server-remapped/0746-Add-PlayerKickEvent-causes.patch b/patches/server-remapped/0746-Add-PlayerKickEvent-causes.patch new file mode 100644 index 0000000000..82c7b23bb7 --- /dev/null +++ b/patches/server-remapped/0746-Add-PlayerKickEvent-causes.patch @@ -0,0 +1,393 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 20:30:45 -0700 +Subject: [PATCH] Add PlayerKickEvent causes + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 9d7cebd703bd0171ca3e95d2985c1a52fdb59712..9e3b8c7478d97bf65a875807a268d1c98389c1f8 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2041,7 +2041,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 80) { + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); +- this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_PLAYER); // Paper - use configurable kick message & kick event cause + return; + } + } else { +@@ -346,7 +346,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) { + if (++this.aboveGroundVehicleTickCount > 80) { + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); +- this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_VEHICLE); // Paper - use configurable kick message & kick event cause + return; + } + } else { +@@ -368,7 +368,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + if (this.isPendingPing()) { + if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info +- this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0])); ++ this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause + } + } else { + if (elapsedTime >= 15000L) { // 15 seconds +@@ -398,7 +398,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) (this.server.getPlayerIdleTimeout() * 1000 * 60)) { + this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause + } + + } +@@ -423,14 +423,22 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + public void disconnect(String s) { + // Paper start +- this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); ++ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); ++ } ++ ++ public void disconnect(String s, PlayerKickEvent.Cause cause) { ++ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s), cause); + } + + public void disconnect(final Component reason) { +- this.disconnect(PaperAdventure.asAdventure(reason)); ++ this.disconnect(PaperAdventure.asAdventure(reason), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); ++ } ++ ++ public void disconnect(final Component reason, PlayerKickEvent.Cause cause) { ++ this.disconnect(PaperAdventure.asAdventure(reason), cause); + } + +- public void disconnect(net.kyori.adventure.text.Component reason) { ++ public void disconnect(net.kyori.adventure.text.Component reason, org.bukkit.event.player.PlayerKickEvent.Cause cause) { + // Paper end + // CraftBukkit start - fire PlayerKickEvent + if (this.processedDisconnect) { +@@ -438,7 +446,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure + +- PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure ++ PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), reason, leaveMessage, cause); // Paper - Adventure & kick event reason + + if (this.craftServer.getServer().isRunning()) { + this.craftServer.getPluginManager().callEvent(event); +@@ -516,7 +524,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + public void handleMoveVehicle(ServerboundMoveVehiclePacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (containsInvalidValues(packet)) { +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_vehicle_movement")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_vehicle_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_VEHICLE_MOVEMENT); // Paper - kick event cause + } else { + Entity entity = this.player.getRootVehicle(); + +@@ -750,13 +758,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async + // CraftBukkit start + if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable +- server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause + return; + } + // Paper start + String str = packet.getCommand(); int index = -1; + if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { +- server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause + return; + } + // Paper end +@@ -904,7 +912,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // Paper start - validate pick item position + if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.inventory.items.size())) { + ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); +- this.disconnect("Invalid hotbar selection (Hacking?)"); ++ this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause + return; + } + this.player.inventory.pickSlot(packet.getSlot()); // Paper - Diff above if changed +@@ -1058,7 +1066,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + ListTag pageList = testStack.getTag().getList("pages", 8); + if (pageList.size() > 100) { + ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with too many pages"); +- server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause + return; + } + long byteTotal = 0; +@@ -1070,7 +1078,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; + if (byteLength > 256 * 4) { + ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!"); +- server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause + return; + } + byteTotal += byteLength; +@@ -1093,14 +1101,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + + if (byteTotal > byteAllowed) { + ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); +- server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause + return; + } + } + // Paper end + // CraftBukkit start + if (this.lastBookTick + 20 > MinecraftServer.currentTick) { +- this.disconnect("Book edited too quickly!"); ++ this.disconnect("Book edited too quickly!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause + return; + } + this.lastBookTick = MinecraftServer.currentTick; +@@ -1212,7 +1220,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + public void handleMovePlayer(ServerboundMovePlayerPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (containsInvalidValues(packet)) { +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause + } else { + ServerLevel worldserver = this.player.getLevel(); + +@@ -1611,7 +1619,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.dropCount++; + if (this.dropCount >= 20) { + LOGGER.warn(this.player.getScoreboardName() + " dropped their items too quickly!"); +- this.disconnect("You dropped your items too quickly (Hacking?)"); ++ this.disconnect("You dropped your items too quickly (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause + return; + } + } +@@ -1924,7 +1932,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.player.resetLastActionTime(); + } else { + ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); +- this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit ++ this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // CraftBukkit // Paper - kick event cause + } + } + +@@ -1961,7 +1969,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + Waitable waitable = new Waitable() { + @Override + protected Object evaluate() { +- ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters")); ++ ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause + return null; + } + }; +@@ -1976,7 +1984,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + throw new RuntimeException(e); + } + } else { +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause + } + // CraftBukkit end + return; +@@ -2030,7 +2038,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + Waitable waitable = new Waitable() { + @Override + protected Object evaluate() { +- ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("disconnect.spam")); ++ ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause + return null; + } + }; +@@ -2045,7 +2053,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + throw new RuntimeException(e); + } + } else { +- this.disconnect(new TranslatableComponent("disconnect.spam")); ++ this.disconnect(new TranslatableComponent("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause + } + // CraftBukkit end + } +@@ -2318,7 +2326,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // Spigot Start + if ( entity == player && !player.isSpectator() ) + { +- disconnect( "Cannot interact with self!" ); ++ disconnect( "Cannot interact with self!", org.bukkit.event.player.PlayerKickEvent.Cause.SELF_INTERACTION ); // Paper - kick event cause + return; + } + // Spigot End +@@ -2395,7 +2403,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // CraftBukkit end + } else if (packet.getAction() == ServerboundInteractPacket.Action.ATTACK) { + if (entity instanceof ItemEntity || entity instanceof ExperienceOrb || entity instanceof AbstractArrow || (entity == this.player && !player.isSpectator())) { // CraftBukkit +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_ENTITY_ATTACKED); // Paper - kick event cause + ServerGamePacketListenerImpl.LOGGER.warn("Player {} tried to attack an invalid entity", this.player.getName().getString()); + return; + } +@@ -2800,7 +2808,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + // Paper start + if (!Bukkit.isPrimaryThread()) { + if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { +- server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause + return; + } + } +@@ -2999,7 +3007,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } else if (!this.isSingleplayerOwner()) { + // Paper start - This needs to be handled on the main thread for plugins + server.scheduleOnMain(() -> { +- this.disconnect(new TranslatableComponent("disconnect.timeout")); ++ this.disconnect(new TranslatableComponent("disconnect.timeout"), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause + }); + // Paper end + } +@@ -3045,7 +3053,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + } catch (Exception ex) { + ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex); +- this.disconnect("Invalid payload REGISTER!"); ++ this.disconnect("Invalid payload REGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause + } + } else if (packet.identifier.equals(CUSTOM_UNREGISTER)) { + try { +@@ -3055,7 +3063,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + } + } catch (Exception ex) { + ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t unregister custom payload", ex); +- this.disconnect("Invalid payload UNREGISTER!"); ++ this.disconnect("Invalid payload UNREGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause + } + } else { + try { +@@ -3074,7 +3082,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + craftServer.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packet.identifier.toString(), data); + } catch (Exception ex) { + ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); +- this.disconnect("Invalid custom payload!"); ++ this.disconnect("Invalid custom payload!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause + } + } + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 6011b43ae8a858f88b8fcf6dc0bf147024a4742c..9e138bf9f9ee4efee462271d1a69a2126aa94946 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -716,7 +716,7 @@ public abstract class PlayerList { + while (iterator.hasNext()) { + entityplayer = (ServerPlayer) iterator.next(); + save(entityplayer); // CraftBukkit - Force the player's inventory to be saved +- entityplayer.connection.disconnect(new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0])); ++ entityplayer.connection.disconnect(new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause + } + + // Instead of kicking then returning, we need to store the kick reason +@@ -1385,8 +1385,8 @@ public abstract class PlayerList { + public void shutdown(boolean isRestarting) { + // CraftBukkit start - disconnect safely + for (ServerPlayer player : this.players) { +- if (isRestarting) player.connection.disconnect(org.spigotmc.SpigotConfig.restartMessage); else // Paper +- player.connection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure ++ if (isRestarting) player.connection.disconnect(org.spigotmc.SpigotConfig.restartMessage, org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); else // Paper - kick event cause (cause is never used here) ++ player.connection.disconnect(this.server.server.shutdownMessage(), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); // CraftBukkit - add custom shutdown message // Paper - Adventure & KickEventCause (cause is never used here) + } + // CraftBukkit end + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 3dbe94d9b9647f5cc1e27335b36042e50c652cea..97aec6370a8a24a13ae04443d03f250f8938b2e0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -495,16 +495,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + org.spigotmc.AsyncCatcher.catchOp("player kick"); // Spigot + if (getHandle().connection == null) return; + +- getHandle().connection.disconnect(message == null ? "" : message); ++ getHandle().connection.disconnect(message == null ? "" : message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause + } + + // Paper start + @Override + public void kick(final net.kyori.adventure.text.Component message) { ++ kick(message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); ++ } ++ ++ @Override ++ public void kick(net.kyori.adventure.text.Component message, org.bukkit.event.player.PlayerKickEvent.Cause cause) { + org.spigotmc.AsyncCatcher.catchOp("player kick"); + final ServerGamePacketListenerImpl connection = this.getHandle().connection; + if (connection != null) { +- connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); ++ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message, cause); + } + } + // Paper end +diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java +index 6498dc4c6630bfef1a52edf74d8574e5e4876720..ea1f088ac94616978af5e01a59c558cd2db4b619 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(SpigotConfig.restartMessage); ++ p.connection.disconnect(SpigotConfig.restartMessage, 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-remapped/0747-Limit-item-frame-cursors-on-maps.patch b/patches/server-remapped/0747-Limit-item-frame-cursors-on-maps.patch new file mode 100644 index 0000000000..276c9629f2 --- /dev/null +++ b/patches/server-remapped/0747-Limit-item-frame-cursors-on-maps.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Yive +Date: Wed, 26 May 2021 15:09:33 -0700 +Subject: [PATCH] Limit item frame cursors on maps + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 108a005c296c4ed370de4af636163088971bed13..9287dfcf29ce6f89a937f4e10b70be8faab9ab9e 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -816,4 +816,9 @@ public class PaperWorldConfig { + private void allowUsingSignsInsideSpawnProtection() { + allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); + } ++ ++ public int mapItemFrameCursorLimit = 128; ++ private void mapItemFrameCursorLimit() { ++ mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +index e7b178127228dea5a17ba0fbd6bae148d70e8eb5..e2f550c833030d8ad12b80d3d379f4731ddeb2ec 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -279,8 +279,12 @@ public class MapItemSavedData extends SavedData { + + MapFrame worldmapframe1 = new MapFrame(blockposition, entityitemframe.getDirection().get2DDataValue() * 90, entityitemframe.getId()); + ++ // Paper start ++ if (this.decorations.size() < player.level.paperConfig.mapItemFrameCursorLimit) { + this.addDecoration(MapDecoration.Type.FRAME, player.level, "frame-" + entityitemframe.getId(), (double) blockposition.getX(), (double) blockposition.getZ(), (double) (entityitemframe.getDirection().get2DDataValue() * 90), (Component) null); + this.frameMarkers.put(worldmapframe1.getId(), worldmapframe1); ++ } ++ // Paper end + } + + CompoundTag nbttagcompound = stack.getTag(); diff --git a/patches/server-remapped/0748-Add-PufferFishStateChangeEvent.patch b/patches/server-remapped/0748-Add-PufferFishStateChangeEvent.patch new file mode 100644 index 0000000000..58dca35d6b --- /dev/null +++ b/patches/server-remapped/0748-Add-PufferFishStateChangeEvent.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Mon, 10 May 2021 16:59:05 +0100 +Subject: [PATCH] Add PufferFishStateChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java +index eb80bde66fbb03dad845e36f1bd1a8eaf8592fbf..44b7b62622d65326aa3926764bb1bb1ed8694511 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java +@@ -89,25 +89,39 @@ public class Pufferfish extends AbstractFish { + public void tick() { + if (!this.level.isClientSide && this.isAlive() && this.isEffectiveAi()) { + if (this.inflateCounter > 0) { ++ boolean increase = true; // Paper - Add PufferFishStateChangeEvent + if (this.getPuffState() == 0) { ++ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent + this.playSound(SoundEvents.PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.getVoicePitch()); + this.setPuffState(1); ++ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent + } else if (this.inflateCounter > 40 && this.getPuffState() == 1) { ++ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 2).callEvent()) { // Paper - Add PufferFishStateChangeEvent + this.playSound(SoundEvents.PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.getVoicePitch()); + this.setPuffState(2); ++ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent + } + ++ if (increase) { // Paper - Add PufferFishStateChangeEvent + ++this.inflateCounter; ++ } // Paper - Add PufferFishStateChangeEvent + } else if (this.getPuffState() != 0) { ++ boolean increase = true; // Paper - Add PufferFishStateChangeEvent + if (this.deflateTimer > 60 && this.getPuffState() == 2) { ++ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent + this.playSound(SoundEvents.PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.getVoicePitch()); + this.setPuffState(1); ++ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent + } else if (this.deflateTimer > 100 && this.getPuffState() == 1) { ++ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 0).callEvent()) { // Paper - Add PufferFishStateChangeEvent + this.playSound(SoundEvents.PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.getVoicePitch()); + this.setPuffState(0); ++ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent + } + ++ if (increase) { // Paper - Add PufferFishStateChangeEvent + ++this.deflateTimer; ++ } // Paper - Add PufferFishStateChangeEvent + } + } + diff --git a/patches/server-remapped/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/patches/server-remapped/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch new file mode 100644 index 0000000000..85fe9b3b12 --- /dev/null +++ b/patches/server-remapped/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 20 May 2021 22:16:37 -0700 +Subject: [PATCH] Fix PlayerBucketEmptyEvent result itemstack + +Fixes SPIGOT-2560: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-2560 + +diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java +index d0e847e58483695d2af1c1410826bb25231cd6f6..08c00a084b2972420eae020e13480489b29aec64 100644 +--- a/src/main/java/net/minecraft/world/item/BucketItem.java ++++ b/src/main/java/net/minecraft/world/item/BucketItem.java +@@ -116,6 +116,13 @@ public class BucketItem extends Item { + } + + protected ItemStack getEmptySuccessItem(ItemStack stack, Player player) { ++ // Paper ++ if (itemLeftInHandAfterPlayerBucketEmptyEvent != null) { ++ ItemStack itemInHand = itemLeftInHandAfterPlayerBucketEmptyEvent; ++ itemLeftInHandAfterPlayerBucketEmptyEvent = null; ++ return itemInHand; ++ } ++ // Paper + return !player.abilities.instabuild ? new ItemStack(Items.BUCKET) : stack; + } + +@@ -126,6 +133,7 @@ public class BucketItem extends Item { + return a(player, world, pos, movingobjectpositionblock, null, null, null, null); + } + ++ private ItemStack itemLeftInHandAfterPlayerBucketEmptyEvent = null; // Paper + public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, InteractionHand enumhand) { + // Paper end + // CraftBukkit end +@@ -146,6 +154,9 @@ public class BucketItem extends Item { + ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 + return false; + } ++ // Paper start ++ itemLeftInHandAfterPlayerBucketEmptyEvent = event.getItemStack().equals(CraftItemStack.asNewCraftStack(net.minecraft.world.item.Items.BUCKET)) ? null : CraftItemStack.asNMSCopy(event.getItemStack()); ++ // Paper end + } + // CraftBukkit end + if (!flag1) { diff --git a/patches/server-remapped/0750-Add-option-to-fix-items-merging-through-walls.patch b/patches/server-remapped/0750-Add-option-to-fix-items-merging-through-walls.patch new file mode 100644 index 0000000000..3cd329efc6 --- /dev/null +++ b/patches/server-remapped/0750-Add-option-to-fix-items-merging-through-walls.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: GioSDA +Date: Wed, 10 Mar 2021 10:06:45 -0800 +Subject: [PATCH] Add option to fix items merging through walls + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 9287dfcf29ce6f89a937f4e10b70be8faab9ab9e..74f2413773fbe30597314e02a5284172e0fc40b2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -821,4 +821,9 @@ public class PaperWorldConfig { + private void mapItemFrameCursorLimit() { + mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); + } ++ ++ public boolean fixItemsMergingThroughWalls; ++ private void fixItemsMergingThroughWalls() { ++ fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 7476ae301fb4ee503944d39022cb25ccb19f1232..d937a74d2e822c8542286fb5bcdfcec7895d845c 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -227,6 +227,14 @@ public class ItemEntity extends Entity { + ItemEntity entityitem = (ItemEntity) iterator.next(); + + if (entityitem.isMergable()) { ++ // Paper Start - Fix items merging through walls ++ if (this.level.paperConfig.fixItemsMergingThroughWalls) { ++ net.minecraft.world.level.ClipContext rayTrace = new net.minecraft.world.level.ClipContext(this.position(), entityitem.position(), ++ net.minecraft.world.level.ClipContext.Block.COLLIDER, net.minecraft.world.level.ClipContext.Fluid.NONE, this); ++ net.minecraft.world.phys.BlockHitResult rayTraceResult = level.clip(rayTrace); ++ if (rayTraceResult.getType() == net.minecraft.world.phys.HitResult.Type.BLOCK) continue; ++ } ++ // Paper End + this.tryToMerge(entityitem); + if (this.removed) { + break; diff --git a/patches/server-remapped/0751-Add-BellRevealRaiderEvent.patch b/patches/server-remapped/0751-Add-BellRevealRaiderEvent.patch new file mode 100644 index 0000000000..78020871e6 --- /dev/null +++ b/patches/server-remapped/0751-Add-BellRevealRaiderEvent.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Wed, 26 May 2021 17:09:07 -0400 +Subject: [PATCH] Add BellRevealRaiderEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +index 3f9179a7678091875161a34d13b6ec0e78025c4c..03c2831a7c4f310936dad1ee72f402ed38f3c9e7 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -6,6 +6,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.Position; + import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.EntityTypeTags; +@@ -181,6 +182,7 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity + } + + private void glow(LivingEntity entity) { ++ if (!new io.papermc.paper.event.block.BellRevealRaiderEvent(level.getWorld().getBlockAt(MCUtil.toLocation(level, worldPosition)), entity.getBukkitEntity()).callEvent()) return; // Paper - BellRevealRaiderEvent + entity.addEffect(new MobEffectInstance(MobEffects.GLOWING, 60)); + } + } diff --git a/patches/server-remapped/0752-Fix-invulnerable-end-crystals.patch b/patches/server-remapped/0752-Fix-invulnerable-end-crystals.patch new file mode 100644 index 0000000000..d830a00fa4 --- /dev/null +++ b/patches/server-remapped/0752-Fix-invulnerable-end-crystals.patch @@ -0,0 +1,105 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Max Lee +Date: Thu, 27 May 2021 14:52:30 -0700 +Subject: [PATCH] Fix invulnerable end crystals + +MC-108513 + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 74f2413773fbe30597314e02a5284172e0fc40b2..dc5ebbb44238cb5928f385d2962c9057388575f8 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -826,4 +826,9 @@ public class PaperWorldConfig { + private void fixItemsMergingThroughWalls() { + fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); + } ++ ++ public boolean fixInvulnerableEndCrystalExploit = true; ++ private void fixInvulnerableEndCrystalExploit() { ++ fixInvulnerableEndCrystalExploit = getBoolean("unsupported-settings.fix-invulnerable-end-crystal-exploit", fixInvulnerableEndCrystalExploit); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +index 6292d04464950ac52fcd6d69345db5125d3127eb..8583209750e4bb70e86d7243a47c525f1726ee42 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +@@ -29,6 +29,7 @@ public class EndCrystal extends Entity { + private static final EntityDataAccessor> DATA_BEAM_TARGET = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.OPTIONAL_BLOCK_POS); + private static final EntityDataAccessor DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN); + public int time; ++ public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals + + public EndCrystal(EntityType type, Level world) { + super(type, world); +@@ -65,6 +66,17 @@ public class EndCrystal extends Entity { + } + // CraftBukkit end + } ++ // Paper start - Fix invulnerable end crystals ++ if (this.level.paperConfig.fixInvulnerableEndCrystalExploit && this.generatedByDragonFight && this.isInvulnerable()) { ++ if ((this.origin.getWorld() != null && !((ServerLevel) this.level).uuid.equals(this.origin.getWorld().getUID())) ++ || ((ServerLevel) this.level).dragonFight() == null ++ || ((ServerLevel) this.level).dragonFight().respawnStage == null ++ || ((ServerLevel) this.level).dragonFight().respawnStage.ordinal() > net.minecraft.world.level.dimension.end.DragonRespawnAnimation.SUMMONING_DRAGON.ordinal()) { ++ this.setInvulnerable(false); ++ this.setBeamTarget(null); ++ } ++ } ++ // Paper end + } + + } +@@ -76,6 +88,7 @@ public class EndCrystal extends Entity { + } + + tag.putBoolean("ShowBottom", this.showsBottom()); ++ if (this.generatedByDragonFight) tag.putBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals + } + + @Override +@@ -87,6 +100,7 @@ public class EndCrystal extends Entity { + if (tag.contains("ShowBottom", 1)) { + this.setShowBottom(tag.getBoolean("ShowBottom")); + } ++ if (tag.contains("Paper.GeneratedByDragonFight", 1)) this.generatedByDragonFight = tag.getBoolean("Paper.GeneratedByDragonFight"); // Paper - Fix invulnerable end crystals + + } + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java +index b99576b524a65cc1a0de88c49324d929503d655f..d51d2fb6d24bfee63b04f32f2cb157fec9d8ee6c 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java +@@ -42,11 +42,11 @@ public class SpikeFeature extends Feature { + return (List) SpikeFeature.SPIKE_CACHE.getUnchecked(i); + } + +- public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, SpikeConfiguration config) { +- List list = config.getSpikes(); ++ public boolean generate(WorldGenLevel generatoraccessseed, ChunkGenerator chunkgenerator, Random random, BlockPos blockposition, SpikeConfiguration worldgenfeatureendspikeconfiguration) { // Paper - decompile fix ++ List list = worldgenfeatureendspikeconfiguration.getSpikes(); + + if (list.isEmpty()) { +- list = getSpikesForLevel(world); ++ list = getSpikesForLevel(generatoraccessseed); + } + + Iterator iterator = list.iterator(); +@@ -54,8 +54,8 @@ public class SpikeFeature extends Feature { + while (iterator.hasNext()) { + SpikeFeature.EndSpike worldgenender_spike = (SpikeFeature.EndSpike) iterator.next(); + +- if (worldgenender_spike.isCenterWithinChunk(pos)) { +- this.placeSpike(world, random, config, worldgenender_spike); ++ if (worldgenender_spike.isCenterWithinChunk(blockposition)) { ++ this.placeSpike(generatoraccessseed, random, worldgenfeatureendspikeconfiguration, worldgenender_spike); + } + } + +@@ -106,6 +106,7 @@ public class SpikeFeature extends Feature { + entityendercrystal.setBeamTarget(config.getCrystalBeamTarget()); + entityendercrystal.setInvulnerable(config.isCrystalInvulnerable()); + entityendercrystal.moveTo((double) spike.getCenterX() + 0.5D, (double) (spike.getHeight() + 1), (double) spike.getCenterZ() + 0.5D, random.nextFloat() * 360.0F, 0.0F); ++ entityendercrystal.generatedByDragonFight = true; + world.addFreshEntity(entityendercrystal); + this.setBlock(world, new BlockPos(spike.getCenterX(), spike.getHeight(), spike.getCenterZ()), Blocks.BEDROCK.defaultBlockState()); + } diff --git a/patches/server-remapped/0753-Add-ElderGuardianAppearanceEvent.patch b/patches/server-remapped/0753-Add-ElderGuardianAppearanceEvent.patch new file mode 100644 index 0000000000..2e0af7d211 --- /dev/null +++ b/patches/server-remapped/0753-Add-ElderGuardianAppearanceEvent.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Fri, 19 Mar 2021 23:39:09 -0400 +Subject: [PATCH] Add ElderGuardianAppearanceEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +index b6a842f9a24634ff84f2f4f94c0f2838f10cddb0..0cf6a06f8bddac0a2a1a00f3a4b266116f7ae594 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java ++++ b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +@@ -77,10 +77,12 @@ public class ElderGuardian extends Guardian { + while (iterator.hasNext()) { + ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + ++ if (new io.papermc.paper.event.entity.ElderGuardianAppearanceEvent(getBukkitEntity(), entityplayer.getBukkitEntity()).callEvent()) { // Paper - Add Guardian Appearance Event + if (!entityplayer.hasEffect(mobeffectlist) || entityplayer.getEffect(mobeffectlist).getAmplifier() < 2 || entityplayer.getEffect(mobeffectlist).getDuration() < 1200) { + entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)); + entityplayer.addEffect(new MobEffectInstance(mobeffectlist, 6000, 2), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } ++ } // Paper - Add Guardian Appearance Event + } + } + diff --git a/patches/server-remapped/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch b/patches/server-remapped/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch new file mode 100644 index 0000000000..a6ef1d69fa --- /dev/null +++ b/patches/server-remapped/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 1 Jun 2021 22:05:08 -0500 +Subject: [PATCH] Reset villager inventory on cancelled pickup event + + +diff --git a/src/main/java/net/minecraft/world/SimpleContainer.java b/src/main/java/net/minecraft/world/SimpleContainer.java +index d6bb1d540e6dcbbad5e5bdf54803c495a4f3e771..3e639f5af83bea6760669696425dffd2d741cc16 100644 +--- a/src/main/java/net/minecraft/world/SimpleContainer.java ++++ b/src/main/java/net/minecraft/world/SimpleContainer.java +@@ -34,6 +34,16 @@ public class SimpleContainer implements Container, StackedContentsCompatible { + return this.items; + } + ++ // Paper start ++ public void setContents(List items) { ++ this.items.clear(); ++ for(int i = 0; i < items.size(); i++) { ++ this.items.set(i, items.get(i)); ++ } ++ this.setChanged(); ++ } ++ // Paper end ++ + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } +@@ -148,6 +158,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible { + return itemstack; + } + ++ public ItemStack addItem(ItemStack itemstack) { return addItem(itemstack); } // Paper - OBFHELPER + public ItemStack addItem(ItemStack stack) { + ItemStack itemstack1 = stack.copy(); + +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 7817071b1964b962c8f4017d5bb39d74ca0ca3e4..1fbb7a2db5c362a5fc9e3f81382f729c962e377b 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -844,15 +844,19 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + } + + // CraftBukkit start +- ItemStack remaining = new SimpleContainer(inventorysubcontainer).addItem(itemstack); +- if (CraftEventFactory.callEntityPickupItemEvent(this, item, remaining.getCount(), false).isCancelled()) { ++ // Paper start ++ List contentsSnapshot = new java.util.ArrayList<>(inventorysubcontainer.getContents()); ++ ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); ++ if (CraftEventFactory.callEntityPickupItemEvent(this, item, itemstack1.getCount(), false).isCancelled()) { ++ inventorysubcontainer.setContents(contentsSnapshot); ++ // Paper end + return; + } + // CraftBukkit end + + this.onItemPickup(item); + this.take(item, itemstack.getCount()); +- ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); ++ // ItemStack itemstack1 = inventorysubcontainer.a(itemstack); // Paper - moved up + + if (itemstack1.isEmpty()) { + item.remove(); diff --git a/patches/server-remapped/0755-Fix-dangerous-end-portal-logic.patch b/patches/server-remapped/0755-Fix-dangerous-end-portal-logic.patch new file mode 100644 index 0000000000..a1fbfe0408 --- /dev/null +++ b/patches/server-remapped/0755-Fix-dangerous-end-portal-logic.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 4 Jun 2021 17:06:52 -0400 +Subject: [PATCH] Fix dangerous end portal logic + +End portals could teleport entities during move calls. Stupid +logic given the caller will never expect that kind of thing, +and will result in all kinds of dupes. + +Move the tick logic into the post tick, where portaling was +designed to happen in the first place. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 779b926921fd435620cbbc69ed6f9931a422b652..25711ab723386db0f448c54e18ef069bfcd0dd99 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1020,6 +1020,7 @@ public class ServerPlayer extends Player implements ContainerListener { + return b(destination, TeleportCause.UNKNOWN); + } + ++ @Nullable public final Entity changeDimension(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { return this.b(worldserver, cause); } // Paper - OBFHELPER + @Nullable + public Entity b(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d055b362459e5b4658aa220e16118ee6174c0de4..2462a78d976937cf4737f1ce0bfde2b2b7d5b1f7 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -312,6 +312,37 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + // Paper end - optimise entity tracking + ++ // Paper start - make end portalling safe ++ public BlockPos portalBlock; ++ public ServerLevel portalWorld; ++ public void tickEndPortal() { ++ BlockPos pos = this.portalBlock; ++ ServerLevel world = this.portalWorld; ++ this.portalBlock = null; ++ this.portalWorld = null; ++ ++ if (pos == null || world == null || world != this.level) { ++ return; ++ } ++ ++ if (this.isPassenger() || this.isVehicle() || !this.canChangeDimensions() || this.removed || !this.valid || !this.isAlive()) { ++ return; ++ } ++ ++ ResourceKey resourcekey = world.getTypeKey() == DimensionType.END_LOCATION ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends ++ ServerLevel worldserver = world.getServer().getLevel(resourcekey); ++ ++ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(this.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); ++ event.callEvent(); ++ ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer)this).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); ++ return; ++ } ++ this.teleportTo(worldserver, null); ++ } ++ // Paper end - make end portalling safe ++ + public Entity(EntityType type, Level world) { + this.id = Entity.ENTITY_COUNTER.incrementAndGet(); + this.passengers = Lists.newArrayList(); +@@ -2297,6 +2328,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + } + + this.processPortalCooldown(); ++ this.tickEndPortal(); // Paper - make end portalling safe + } + } + +diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +index 2231680140d0e3c4c10b6722fd13fe0ee55ce294..52884b87b25bef8abfa824f40d02efe3f947f330 100644 +--- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +@@ -3,7 +3,6 @@ package net.minecraft.world.level.block; + import net.minecraft.core.BlockPos; + import net.minecraft.resources.ResourceKey; + import net.minecraft.server.level.ServerLevel; +-import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; +@@ -50,16 +49,10 @@ public class EndPortalBlock extends BaseEntityBlock { + // return; // CraftBukkit - always fire event in case plugins wish to change it + } + +- // CraftBukkit start - Entity in portal +- EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); +- world.getCraftServer().getPluginManager().callEvent(event); +- +- if (entity instanceof ServerPlayer) { +- ((ServerPlayer) entity).b(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); +- return; +- } +- // CraftBukkit end +- entity.changeDimension(worldserver); ++ // Paper start - move all of this logic into portal tick ++ entity.portalWorld = ((ServerLevel)world); ++ entity.portalBlock = pos.immutable(); ++ // Paper end - move all of this logic into portal tick + } + + } diff --git a/patches/server-remapped/0756-Make-item-validations-configurable.patch b/patches/server-remapped/0756-Make-item-validations-configurable.patch new file mode 100644 index 0000000000..964f15ad4b --- /dev/null +++ b/patches/server-remapped/0756-Make-item-validations-configurable.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 4 Jun 2021 12:12:35 -0700 +Subject: [PATCH] Make item validations configurable + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index efc1e42d606e1c9feb1a4871c0714933ae92a1b2..7acf077bc131af718c7548cc29deef558c04e463 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -486,4 +486,19 @@ public class PaperConfig { + enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); + enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); + } ++ ++ public static int itemValidationDisplayNameLength = 8192; ++ public static int itemValidationLocNameLength = 8192; ++ public static int itemValidationLoreLineLength = 8192; ++ public static int itemValidationBookTitleLength = 8192; ++ public static int itemValidationBookAuthorLength = 8192; ++ public static int itemValidationBookPageLength = 16384; ++ private static void itemValidationSettings() { ++ itemValidationDisplayNameLength = getInt("settings.item-validation.display-name", itemValidationDisplayNameLength); ++ itemValidationLocNameLength = getInt("settings.item-validation.loc-name", itemValidationLocNameLength); ++ itemValidationLoreLineLength = getInt("settings.item-validation.lore-line", itemValidationLoreLineLength); ++ itemValidationBookTitleLength = getInt("settings.item-validation.book.title", itemValidationBookTitleLength); ++ itemValidationBookAuthorLength = getInt("settings.item-validation.book.author", itemValidationBookAuthorLength); ++ itemValidationBookPageLength = getInt("settings.item-validation.book.page", itemValidationBookPageLength); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +index 80397e223990f11c9aa413f3f4ebd7c1b8ce1cff..2ff1619e6898add074481c7ca43bfbf9a8d163ca 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +@@ -94,11 +94,11 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + super(tag); + + if (tag.contains(BOOK_TITLE.NBT)) { +- this.title = limit( tag.getString(BOOK_TITLE.NBT), 8192 ); // Spigot ++ this.title = limit( tag.getString(BOOK_TITLE.NBT), com.destroystokyo.paper.PaperConfig.itemValidationBookTitleLength); // Spigot // Paper - make configurable + } + + if (tag.contains(BOOK_AUTHOR.NBT)) { +- this.author = limit( tag.getString(BOOK_AUTHOR.NBT), 8192 ); // Spigot ++ this.author = limit( tag.getString(BOOK_AUTHOR.NBT), com.destroystokyo.paper.PaperConfig.itemValidationBookAuthorLength ); // Spigot // Paper - make configurable + } + + if (tag.contains(RESOLVED.NBT)) { +@@ -126,7 +126,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + } else { + page = validatePage(page); + } +- this.pages.add( limit( page, 16384 ) ); // Spigot ++ this.pages.add( limit( page, com.destroystokyo.paper.PaperConfig.itemValidationBookPageLength ) ); // Spigot // Paper - make configurable + } + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 20e008277d1188fc7b31bfb2522ef9f6429cc3fb..99e18748b3cc4168b1d15c030f992a128b666d84 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -357,18 +357,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + CompoundTag display = tag.getCompound(DISPLAY.NBT); + + if (display.contains(NAME.NBT)) { +- displayName = limit( display.getString(NAME.NBT), 8192 ); // Spigot ++ displayName = limit( display.getString(NAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationDisplayNameLength); // Spigot // Paper - make configurable + } + + if (display.contains(LOCNAME.NBT)) { +- locName = limit( display.getString(LOCNAME.NBT), 8192 ); // Spigot ++ locName = limit( display.getString(LOCNAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationLocNameLength ); // Spigot // Paper - make configurable + } + + if (display.contains(LORE.NBT)) { + ListTag list = display.getList(LORE.NBT, CraftMagicNumbers.NBT.TAG_STRING); + lore = new ArrayList(list.size()); + for (int index = 0; index < list.size(); index++) { +- String line = limit( list.getString(index), 8192 ); // Spigot ++ String line = limit( list.getString(index), com.destroystokyo.paper.PaperConfig.itemValidationLoreLineLength ); // Spigot // Paper - make configurable + lore.add(line); + } + } diff --git a/patches/server-remapped/0757-Add-more-line-of-sight-methods.patch b/patches/server-remapped/0757-Add-more-line-of-sight-methods.patch new file mode 100644 index 0000000000..2961b16b07 --- /dev/null +++ b/patches/server-remapped/0757-Add-more-line-of-sight-methods.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TwoLeggedCat <80929284+TwoLeggedCat@users.noreply.github.com> +Date: Sat, 29 May 2021 14:33:25 -0500 +Subject: [PATCH] Add more line of sight methods + + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 37787a725725d22b0870dcab0f3bec8b94cfd130..79b43b1b0f8e223f256c2aaec1925426931a9a54 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3091,6 +3091,7 @@ public abstract class LivingEntity extends Entity { + Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); + Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); + ++ // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists + return this.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 1c9321cef1a05c5e8a22dd52bc63a5103eaf7311..312ed9c693cc5108d51ad90e15d6be4bb21904e1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -315,6 +315,17 @@ public class CraftWorld implements World { + public io.papermc.paper.world.MoonPhase getMoonPhase() { + return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); + } ++ ++ @Override ++ public boolean lineOfSightExists(Location from, Location to) { ++ Validate.notNull(from, "from parameter in lineOfSightExists cannot be null"); ++ Validate.notNull(to, "to parameter in lineOfSightExists cannot be null"); ++ if (from.getWorld() != to.getWorld()) return false; ++ Vec3 vec3d = new Vec3(from.getX(), from.getY(), from.getZ()); ++ Vec3 vec3d1 = new Vec3(to.getX(), to.getY(), to.getZ()); ++ ++ return this.getHandle().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, null)).getType() == HitResult.Type.MISS; ++ } + // Paper end + + private static final Random rand = new Random(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 25ba7a26c951fc5e4638bdb0db36e94d3e08fb2e..cd42edd8f36cea3acad76974c39eb0cd1585f73d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -549,6 +549,17 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return getHandle().canSee(((CraftEntity) other).getHandle()); + } + ++ // Paper start ++ @Override ++ public boolean hasLineOfSight(Location loc) { ++ if (this.getHandle().level != ((CraftWorld) loc.getWorld()).getHandle()) return false; ++ Vec3 vec3d = new Vec3(this.getHandle().getX(), this.getHandle().getEyeY(), this.getHandle().getZ()); ++ Vec3 vec3d1 = new Vec3(loc.getX(), loc.getY(), loc.getZ()); ++ ++ return this.getHandle().level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this.getHandle())).getType() == HitResult.Type.MISS; ++ } ++ // Paper end ++ + @Override + public boolean getRemoveWhenFarAway() { + return getHandle() instanceof Mob && !((Mob) getHandle()).persistenceRequired; diff --git a/patches/server-remapped/0758-add-per-world-spawn-limits.patch b/patches/server-remapped/0758-add-per-world-spawn-limits.patch new file mode 100644 index 0000000000..b4f5cd5335 --- /dev/null +++ b/patches/server-remapped/0758-add-per-world-spawn-limits.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chase +Date: Wed, 2 Dec 2020 22:43:39 -0800 +Subject: [PATCH] add per world spawn limits + +Taken from #2982. Credit to Chasewhip8 + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index dc5ebbb44238cb5928f385d2962c9057388575f8..f80186f663ff654ab6b69189941cd26815f65f09 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -652,6 +652,19 @@ public class PaperWorldConfig { + zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); + } + ++ public int spawnLimitMonsters = -1; ++ public int spawnLimitAnimals = -1; ++ public int spawnLimitWaterAnimals = -1; ++ public int spawnLimitWaterAmbient = -1; ++ public int spawnLimitAmbient = -1; ++ private void perWorldSpawnLimits() { ++ spawnLimitMonsters = getInt("spawn-limits.monsters", spawnLimitMonsters); ++ spawnLimitAnimals = getInt("spawn-limits.animals", spawnLimitAnimals); ++ spawnLimitWaterAnimals = getInt("spawn-limits.water-animals", spawnLimitWaterAnimals); ++ spawnLimitWaterAmbient = getInt("spawn-limits.water-ambient", spawnLimitWaterAmbient); ++ spawnLimitAmbient = getInt("spawn-limits.ambient", spawnLimitAmbient); ++ } ++ + public int lightQueueSize = 20; + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 312ed9c693cc5108d51ad90e15d6be4bb21904e1..89aac4214084bd72a83eaaf043b7d47cc0b748f5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -335,6 +335,13 @@ public class CraftWorld implements World { + this.generator = gen; + + environment = env; ++ // Paper start - per world spawn limits ++ this.monsterSpawn = this.world.paperConfig.spawnLimitMonsters; ++ this.animalSpawn = this.world.paperConfig.spawnLimitAnimals; ++ this.waterAnimalSpawn = this.world.paperConfig.spawnLimitWaterAnimals; ++ this.waterAmbientSpawn = this.world.paperConfig.spawnLimitWaterAmbient; ++ this.ambientSpawn = this.world.paperConfig.spawnLimitAmbient; ++ // Paper end + } + + @Override diff --git a/patches/server-remapped/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch b/patches/server-remapped/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch new file mode 100644 index 0000000000..f351ce4533 --- /dev/null +++ b/patches/server-remapped/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 20 May 2021 20:40:53 -0700 +Subject: [PATCH] Fix PotionSplashEvent for water splash potions + +Fixes SPIGOT-6221: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-6221 + +diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java +index ed81d2a306d28561370745bb3389c49012f677a7..fbdfab50af195d219f9745324c8924fc777f76ec 100644 +--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java ++++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java +@@ -99,6 +99,7 @@ public class DamageSource { + return (new IndirectEntityDamageSource("thrown", projectile, attacker)).setProjectile(); + } + ++ public static DamageSource indirectMagic(Entity target, Entity cause) { return indirectMagic(target, cause); } // Paper - OBFHELPER + public static DamageSource indirectMagic(Entity magic, @Nullable Entity attacker) { + return (new IndirectEntityDamageSource("indirectMagic", magic, attacker)).bypassArmor().setMagic(); + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java +index 2ff7e8dfc0a520fb330177c140a1ae5c729f14c0..8bf095bce9dfec6479185b6e60c2e9d76e3363eb 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java +@@ -122,6 +122,7 @@ public class ThrownPotion extends ThrowableItemProjectile { + private void applyWater() { + AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); + List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb, ThrownPotion.WATER_SENSITIVE); ++ Map affected = new HashMap<>(); // Paper + + if (!list.isEmpty()) { + Iterator iterator = list.iterator(); +@@ -131,11 +132,22 @@ public class ThrownPotion extends ThrowableItemProjectile { + double d0 = this.distanceToSqr(entityliving); + + if (d0 < 16.0D && entityliving.isSensitiveToWater()) { +- entityliving.hurt(DamageSource.indirectMagic(entityliving, this.getOwner()), 1.0F); ++ // Paper start ++ double intensity = 1.0D - Math.sqrt(d0) / 4.0D; ++ affected.put(entityliving.getBukkitLivingEntity(), intensity); ++ // entityliving.damageEntity(DamageSource.c(entityliving, this.getShooter()), 1.0F); // Paper - moved down + } + } + } + ++ org.bukkit.event.entity.PotionSplashEvent event = CraftEventFactory.callPotionSplashEvent(this, affected); ++ if (!event.isCancelled()) { ++ for (LivingEntity affectedEntity : event.getAffectedEntities()) { ++ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) affectedEntity).getHandle(); ++ entityliving.hurt(DamageSource.indirectMagic(entityliving, this.getOwner()), 1.0F); ++ } ++ } ++ // Paper end + } + + private void applySplash(List statusEffects, @Nullable Entity entity) { +@@ -153,6 +165,7 @@ public class ThrownPotion extends ThrowableItemProjectile { + double d0 = this.distanceToSqr(entityliving); + + if (d0 < 16.0D) { ++ // Paper - diff on change, used when calling the splash event for water splash potions + double d1 = 1.0D - Math.sqrt(d0) / 4.0D; + + if (entityliving == entity) { diff --git a/patches/server-unmapped/0001-POM-Changes.patch b/patches/server-unmapped/0001-POM-Changes.patch new file mode 100644 index 0000000000..8d0da0d549 --- /dev/null +++ b/patches/server-unmapped/0001-POM-Changes.patch @@ -0,0 +1,291 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 29 Feb 2016 20:40:33 -0600 +Subject: [PATCH] POM Changes + + +diff --git a/pom.xml b/pom.xml +index 3fc047371e8f8a626e69697fad549d689c5dce89..a5d87d22cb1588d15e08da3b37e51c5e261c7799 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -1,15 +1,14 @@ + + 4.0.0 +- org.spigotmc +- spigot ++ paper + jar + 1.16.5-R0.1-SNAPSHOT +- Spigot +- https://www.spigotmc.org/ ++ Paper ++ https://papermc.io + + +- true ++ + UTF-8 + unknown + git +@@ -20,21 +19,39 @@ + + + +- org.spigotmc +- spigot-parent ++ com.destroystokyo.paper ++ paper-parent + dev-SNAPSHOT + ../pom.xml + + ++ ++ ++ ++ org.apache.logging.log4j ++ log4j-bom ++ 2.11.2 ++ pom ++ import ++ ++ ++ ++ + + +- org.spigotmc +- spigot-api ++ com.destroystokyo.paper ++ paper-api ++ ${project.version} ++ compile ++ ++ ++ com.destroystokyo.paper ++ paper-mojangapi + ${project.version} + compile + + +- org.spigotmc ++ io.papermc + minecraft-server + ${minecraft.version}-SNAPSHOT + compile +@@ -45,18 +62,15 @@ + 2.12.1 + compile + ++ ++ org.apache.logging.log4j ++ log4j-api ++ compile ++ + + org.apache.logging.log4j + log4j-iostreams +- 2.8.1 + compile +- +- +- +- org.apache.logging.log4j +- log4j-api +- +- + + + org.ow2.asm +@@ -64,12 +78,23 @@ + 9.1 + compile + ++ ++ ++ co.aikar ++ cleaner ++ 1.0-SNAPSHOT ++ ++ ++ io.netty ++ netty-all ++ 4.1.50.Final ++ + + + com.googlecode.json-simple + json-simple + 1.1.1 +- runtime ++ compile + + + org.xerial +@@ -80,7 +105,7 @@ + + mysql + mysql-connector-java +- 5.1.49 ++ 8.0.23 + runtime + + +@@ -105,7 +130,7 @@ + + org.apache.logging.log4j + log4j-slf4j-impl +- 2.8.1 ++ + runtime + + +@@ -132,34 +157,22 @@ + + + ++ paper-${minecraft.version} ++ clean install + + +- net.md-5 +- scriptus +- 0.4.1 ++ com.lukegb.mojo ++ gitdescribe-maven-plugin ++ 1.3 ++ ++ git-Paper- ++ .. ++ + + +- ex-spigot +- +- ${bt.name}-Spigot-%s +- ../ +- spigot.desc +- +- initialize +- +- describe +- +- +- +- ex-craftbukkit +- +- -%s +- ../../CraftBukkit +- craftbukkit.desc +- +- initialize ++ compile + +- describe ++ gitdescribe + + + +@@ -169,6 +182,7 @@ + maven-jar-plugin + 3.2.0 + ++ true + + + false +@@ -176,11 +190,13 @@ + + org.bukkit.craftbukkit.Main + CraftBukkit +- ${spigot.desc}${craftbukkit.desc} +- ${project.build.outputTimestamp} ++ ++ ${describe} ++ ${maven.build.timestamp} + Bukkit + ${api.version} + Bukkit Team ++ true + + + +@@ -216,14 +232,24 @@ + shade + + ++ ${project.build.directory}/dependency-reduced-pom.xml + ${shadeSourcesJar} + + +- org.spigotmc:minecraft-server ++ io.papermc:minecraft-server + + com/google/common/** + com/google/gson/** + com/google/thirdparty/** ++ ++ io/netty/** ++ META-INF/native/libnetty* ++ com/mojang/brigadier/** ++ META-INF/MANIFEST.MF ++ com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.class ++ com/mojang/datafixers/util/Either* ++ org/apache/logging/log4j/** ++ META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat + + + +@@ -245,10 +271,11 @@ + jline + org.bukkit.craftbukkit.libs.jline + +- +- it.unimi +- org.bukkit.craftbukkit.libs.it.unimi +- ++ ++ ++ ++ ++ + + org.apache.commons.codec + org.bukkit.craftbukkit.libs.org.apache.commons.codec +@@ -316,10 +343,6 @@ + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 +- +- +- eclipse +- + + + org.codehaus.plexus +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 4452427d0a8298d119ca29ef397b7a94f19eec28..46a16e31775b28c44f95a8ac5545ebcb656c74b6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -186,7 +186,7 @@ public class Main { + } + + if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { +- Date buildDate = new Date(Integer.parseInt(Main.class.getPackage().getImplementationVendor()) * 1000L); ++ Date buildDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(Main.class.getPackage().getImplementationVendor()); // Paper + + Calendar deadline = Calendar.getInstance(); + deadline.add(Calendar.DAY_OF_YEAR, -28); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +index 93046379d0cefd5d3236fc59e698809acdc18f80..674096cab190d62622f9947853b056f57d43a2a5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +@@ -11,7 +11,7 @@ public final class Versioning { + public static String getBukkitVersion() { + String result = "Unknown-Version"; + +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties"); ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.destroystokyo.paper/paper-api/pom.properties"); + Properties properties = new Properties(); + + if (stream != null) { diff --git a/patches/server-unmapped/0002-Paper-config-files.patch b/patches/server-unmapped/0002-Paper-config-files.patch new file mode 100644 index 0000000000..59424f2288 --- /dev/null +++ b/patches/server-unmapped/0002-Paper-config-files.patch @@ -0,0 +1,820 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 29 Feb 2016 21:02:09 -0600 +Subject: [PATCH] Paper config files + +Loads each yml file for early init too so it can be used for early options + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..68cd4134cb6a00c1768100462f8e9e94f3fa6279 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -0,0 +1,286 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Functions; ++import com.google.common.base.Joiner; ++import com.google.common.collect.ImmutableSet; ++import com.google.common.collect.Iterables; ++import com.google.common.collect.Lists; ++import com.google.common.collect.Maps; ++import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ChunkProviderServer; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import org.apache.commons.lang3.tuple.MutablePair; ++import org.apache.commons.lang3.tuple.Pair; ++import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; ++import org.bukkit.Location; ++import org.bukkit.World; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.entity.Player; ++ ++import java.io.File; ++import java.time.LocalDateTime; ++import java.time.format.DateTimeFormatter; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collection; ++import java.util.Collections; ++import java.util.Iterator; ++import java.util.List; ++import java.util.Locale; ++import java.util.Map; ++import java.util.Set; ++import java.util.stream.Collectors; ++ ++public class PaperCommand extends Command { ++ private static final String BASE_PERM = "bukkit.command.paper."; ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); ++ ++ public PaperCommand(String name) { ++ super(name); ++ this.description = "Paper related commands"; ++ this.usageMessage = "/paper [" + Joiner.on(" | ").join(SUBCOMMANDS) + "]"; ++ this.setPermission("bukkit.command.paper;" + Joiner.on(';').join(SUBCOMMANDS.stream().map(s -> BASE_PERM + s).collect(Collectors.toSet()))); ++ } ++ ++ private static boolean testPermission(CommandSender commandSender, String permission) { ++ if (commandSender.hasPermission(BASE_PERM + permission) || commandSender.hasPermission("bukkit.command.paper")) return true; ++ commandSender.sendMessage(Bukkit.getPermissionMessage()); ++ return false; ++ } ++ ++ @Override ++ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { ++ if (args.length <= 1) ++ return getListMatchingLast(sender, args, SUBCOMMANDS); ++ ++ switch (args[0].toLowerCase(Locale.ENGLISH)) ++ { ++ case "entity": ++ if (args.length == 2) ++ return getListMatchingLast(sender, args, "help", "list"); ++ if (args.length == 3) ++ return getListMatchingLast(sender, args, EntityTypes.getEntityNameList().stream().map(MinecraftKey::toString).sorted().toArray(String[]::new)); ++ break; ++ } ++ return Collections.emptyList(); ++ } ++ ++ // Code from Mojang - copyright them ++ public static List getListMatchingLast(CommandSender sender, String[] args, String... matches) { ++ return getListMatchingLast(sender, args, (Collection) Arrays.asList(matches)); ++ } ++ ++ public static boolean matches(String s, String s1) { ++ return s1.regionMatches(true, 0, s, 0, s.length()); ++ } ++ ++ public static List getListMatchingLast(CommandSender sender, String[] strings, Collection collection) { ++ String last = strings[strings.length - 1]; ++ ArrayList results = Lists.newArrayList(); ++ ++ if (!collection.isEmpty()) { ++ Iterator iterator = Iterables.transform(collection, Functions.toStringFunction()).iterator(); ++ ++ while (iterator.hasNext()) { ++ String s1 = (String) iterator.next(); ++ ++ if (matches(last, s1) && (sender.hasPermission(BASE_PERM + s1) || sender.hasPermission("bukkit.command.paper"))) { ++ results.add(s1); ++ } ++ } ++ ++ if (results.isEmpty()) { ++ iterator = collection.iterator(); ++ ++ while (iterator.hasNext()) { ++ Object object = iterator.next(); ++ ++ if (object instanceof MinecraftKey && matches(last, ((MinecraftKey) object).getKey())) { ++ results.add(String.valueOf(object)); ++ } ++ } ++ } ++ } ++ ++ return results; ++ } ++ // end copy stuff ++ ++ @Override ++ public boolean execute(CommandSender sender, String commandLabel, String[] args) { ++ if (!testPermission(sender)) return true; ++ ++ if (args.length == 0) { ++ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); ++ return false; ++ } ++ if (SUBCOMMANDS.contains(args[0].toLowerCase(Locale.ENGLISH))) { ++ if (!testPermission(sender, args[0].toLowerCase(Locale.ENGLISH))) return true; ++ } ++ switch (args[0].toLowerCase(Locale.ENGLISH)) { ++ case "heap": ++ dumpHeap(sender); ++ break; ++ case "entity": ++ listEntities(sender, args); ++ break; ++ case "reload": ++ doReload(sender); ++ break; ++ case "ver": ++ if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) ++ case "version": ++ Command ver = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version"); ++ if (ver != null) { ++ ver.execute(sender, commandLabel, new String[0]); ++ break; ++ } ++ // else - fall through to default ++ default: ++ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); ++ return false; ++ } ++ ++ return true; ++ } ++ ++ /* ++ * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 ++ */ ++ private void listEntities(CommandSender sender, String[] args) { ++ if (args.length < 2 || args[1].toLowerCase(Locale.ENGLISH).equals("help")) { ++ sender.sendMessage(ChatColor.RED + "Use /paper entity [list] help for more information on a specific command."); ++ return; ++ } ++ ++ switch (args[1].toLowerCase(Locale.ENGLISH)) { ++ case "list": ++ String filter = "*"; ++ if (args.length > 2) { ++ if (args[2].toLowerCase(Locale.ENGLISH).equals("help")) { ++ sender.sendMessage(ChatColor.RED + "Use /paper entity list [filter] [worldName] to get entity info that matches the optional filter."); ++ return; ++ } ++ filter = args[2]; ++ } ++ final String cleanfilter = filter.replace("?", ".?").replace("*", ".*?"); ++ Set names = EntityTypes.getEntityNameList().stream() ++ .filter(n -> n.toString().matches(cleanfilter)) ++ .collect(Collectors.toSet()); ++ ++ if (names.isEmpty()) { ++ sender.sendMessage(ChatColor.RED + "Invalid filter, does not match any entities. Use /paper entity list for a proper list"); ++ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); ++ return; ++ } ++ ++ String worldName; ++ if (args.length > 3) { ++ worldName = args[3]; ++ } else if (sender instanceof Player) { ++ worldName = ((Player) sender).getWorld().getName(); ++ } else { ++ sender.sendMessage(ChatColor.RED + "Please specify the name of a world"); ++ sender.sendMessage(ChatColor.RED + "To do so without a filter, specify '*' as the filter"); ++ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); ++ return; ++ } ++ ++ Map>> list = Maps.newHashMap(); ++ World bukkitWorld = Bukkit.getWorld(worldName); ++ if (bukkitWorld == null) { ++ sender.sendMessage(ChatColor.RED + "Could not load world for " + worldName + ". Please select a valid world."); ++ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); ++ return; ++ } ++ WorldServer world = ((CraftWorld) Bukkit.getWorld(worldName)).getHandle(); ++ ++ Map nonEntityTicking = Maps.newHashMap(); ++ ChunkProviderServer chunkProviderServer = world.getChunkProvider(); ++ ++ Collection entities = world.entitiesById.values(); ++ entities.forEach(e -> { ++ MinecraftKey key = new MinecraftKey(""); // TODO: update in next patch ++ ++ MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); ++ ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); ++ info.left++; ++ info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1); ++ if (!chunkProviderServer.isInEntityTickingChunk(e)) { ++ nonEntityTicking.merge(key, Integer.valueOf(1), Integer::sum); ++ } ++ }); ++ ++ if (names.size() == 1) { ++ MinecraftKey name = names.iterator().next(); ++ Pair> info = list.get(name); ++ int nonTicking = nonEntityTicking.getOrDefault(name, Integer.valueOf(0)).intValue(); ++ if (info == null) { ++ sender.sendMessage(ChatColor.RED + "No entities found."); ++ return; ++ } ++ sender.sendMessage("Entity: " + name + " Total Ticking: " + (info.getLeft() - nonTicking) + ", Total Non-Ticking: " + nonTicking); ++ info.getRight().entrySet().stream() ++ .sorted((a, b) -> !a.getValue().equals(b.getValue()) ? b.getValue() - a.getValue() : a.getKey().toString().compareTo(b.getKey().toString())) ++ .limit(10).forEach(e -> sender.sendMessage(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z + (chunkProviderServer.isEntityTickingChunk(e.getKey()) ? " (Ticking)" : " (Non-Ticking)"))); ++ } else { ++ List> info = list.entrySet().stream() ++ .filter(e -> names.contains(e.getKey())) ++ .map(e -> Pair.of(e.getKey(), e.getValue().left)) ++ .sorted((a, b) -> !a.getRight().equals(b.getRight()) ? b.getRight() - a.getRight() : a.getKey().toString().compareTo(b.getKey().toString())) ++ .collect(Collectors.toList()); ++ ++ if (info == null || info.size() == 0) { ++ sender.sendMessage(ChatColor.RED + "No entities found."); ++ return; ++ } ++ ++ int count = info.stream().mapToInt(Pair::getRight).sum(); ++ int nonTickingCount = nonEntityTicking.values().stream().mapToInt(Integer::intValue).sum(); ++ sender.sendMessage("Total Ticking: " + (count - nonTickingCount) + ", Total Non-Ticking: " + nonTickingCount); ++ info.forEach(e -> { ++ int nonTicking = nonEntityTicking.getOrDefault(e.getKey(), Integer.valueOf(0)).intValue(); ++ sender.sendMessage(" " + (e.getValue() - nonTicking) + " (" + nonTicking + ") " + ": " + e.getKey()); ++ }); ++ sender.sendMessage("* First number is ticking entities, second number is non-ticking entities"); ++ } ++ break; ++ } ++ } ++ ++ private void dumpHeap(CommandSender sender) { ++ java.nio.file.Path dir = java.nio.file.Paths.get("./dumps"); ++ String name = "heap-dump-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()); ++ ++ Command.broadcastCommandMessage(sender, ChatColor.YELLOW + "Writing JVM heap data..."); ++ ++ java.nio.file.Path file = CraftServer.dumpHeap(dir, name); ++ if (file != null) { ++ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Heap dump saved to " + file); ++ } else { ++ Command.broadcastCommandMessage(sender, ChatColor.RED + "Failed to write heap dump, see sever log for details"); ++ } ++ } ++ ++ private void doReload(CommandSender sender) { ++ Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues."); ++ Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); ++ ++ MinecraftServer console = MinecraftServer.getServer(); ++ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); ++ for (WorldServer world : console.getWorlds()) { ++ world.paperConfig.init(); ++ } ++ console.server.reloadCount++; ++ ++ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete."); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2c0514892d3993bef57ecf677cf8bb0fbe0216e4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -0,0 +1,185 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Throwables; ++ ++import java.io.File; ++import java.io.IOException; ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.TimeUnit; ++import java.util.logging.Level; ++import java.util.regex.Pattern; ++ ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++import org.bukkit.command.Command; ++import org.bukkit.configuration.ConfigurationSection; ++import org.bukkit.configuration.InvalidConfigurationException; ++import org.bukkit.configuration.file.YamlConfiguration; ++ ++public class PaperConfig { ++ ++ private static File CONFIG_FILE; ++ private static final String HEADER = "This is the main configuration file for Paper.\n" ++ + "As you can see, there's tons to configure. Some options may impact gameplay, so use\n" ++ + "with caution, and make sure you know what each option does before configuring.\n" ++ + "\n" ++ + "If you need help with the configuration or have any questions related to Paper,\n" ++ + "join us in our Discord or IRC channel.\n" ++ + "\n" ++ + "Discord: https://discord.gg/papermc\n" ++ + "IRC: #paper @ irc.esper.net ( https://webchat.esper.net/?channels=paper ) \n" ++ + "Website: https://papermc.io/ \n" ++ + "Docs: https://paper.readthedocs.org/ \n"; ++ /*========================================================================*/ ++ public static YamlConfiguration config; ++ static int version; ++ static Map commands; ++ private static boolean verbose; ++ private static boolean fatalError; ++ /*========================================================================*/ ++ ++ public static void init(File configFile) { ++ CONFIG_FILE = configFile; ++ config = new YamlConfiguration(); ++ try { ++ config.load(CONFIG_FILE); ++ } catch (IOException ex) { ++ } catch (InvalidConfigurationException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not load paper.yml, please correct your syntax errors", ex); ++ throw Throwables.propagate(ex); ++ } ++ config.options().header(HEADER); ++ config.options().copyDefaults(true); ++ verbose = getBoolean("verbose", false); ++ ++ commands = new HashMap(); ++ commands.put("paper", new PaperCommand("paper")); ++ ++ version = getInt("config-version", 20); ++ set("config-version", 20); ++ readConfig(PaperConfig.class, null); ++ } ++ ++ protected static void logError(String s) { ++ Bukkit.getLogger().severe(s); ++ } ++ ++ protected static void fatal(String s) { ++ fatalError = true; ++ throw new RuntimeException("Fatal paper.yml config error: " + s); ++ } ++ ++ protected static void log(String s) { ++ if (verbose) { ++ Bukkit.getLogger().info(s); ++ } ++ } ++ ++ public static void registerCommands() { ++ for (Map.Entry entry : commands.entrySet()) { ++ MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); ++ } ++ } ++ ++ static void readConfig(Class clazz, Object instance) { ++ for (Method method : clazz.getDeclaredMethods()) { ++ if (Modifier.isPrivate(method.getModifiers())) { ++ if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) { ++ try { ++ method.setAccessible(true); ++ method.invoke(instance); ++ } catch (InvocationTargetException ex) { ++ throw Throwables.propagate(ex.getCause()); ++ } catch (Exception ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex); ++ } ++ } ++ } ++ } ++ ++ try { ++ config.save(CONFIG_FILE); ++ } catch (IOException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex); ++ } ++ } ++ ++ private static final Pattern SPACE = Pattern.compile(" "); ++ private static final Pattern NOT_NUMERIC = Pattern.compile("[^-\\d.]"); ++ public static int getSeconds(String str) { ++ str = SPACE.matcher(str).replaceAll(""); ++ final char unit = str.charAt(str.length() - 1); ++ str = NOT_NUMERIC.matcher(str).replaceAll(""); ++ double num; ++ try { ++ num = Double.parseDouble(str); ++ } catch (Exception e) { ++ num = 0D; ++ } ++ switch (unit) { ++ case 'd': num *= (double) 60*60*24; break; ++ case 'h': num *= (double) 60*60; break; ++ case 'm': num *= (double) 60; break; ++ default: case 's': break; ++ } ++ return (int) num; ++ } ++ ++ protected static String timeSummary(int seconds) { ++ String time = ""; ++ ++ if (seconds > 60 * 60 * 24) { ++ time += TimeUnit.SECONDS.toDays(seconds) + "d"; ++ seconds %= 60 * 60 * 24; ++ } ++ ++ if (seconds > 60 * 60) { ++ time += TimeUnit.SECONDS.toHours(seconds) + "h"; ++ seconds %= 60 * 60; ++ } ++ ++ if (seconds > 0) { ++ time += TimeUnit.SECONDS.toMinutes(seconds) + "m"; ++ } ++ return time; ++ } ++ ++ private static void set(String path, Object val) { ++ config.set(path, val); ++ } ++ ++ private static boolean getBoolean(String path, boolean def) { ++ config.addDefault(path, def); ++ return config.getBoolean(path, config.getBoolean(path)); ++ } ++ ++ private static double getDouble(String path, double def) { ++ config.addDefault(path, def); ++ return config.getDouble(path, config.getDouble(path)); ++ } ++ ++ private static float getFloat(String path, float def) { ++ // TODO: Figure out why getFloat() always returns the default value. ++ return (float) getDouble(path, (double) def); ++ } ++ ++ private static int getInt(String path, int def) { ++ config.addDefault(path, def); ++ return config.getInt(path, config.getInt(path)); ++ } ++ ++ private static List getList(String path, T def) { ++ config.addDefault(path, def); ++ return (List) config.getList(path, config.getList(path)); ++ } ++ ++ private static String getString(String path, String def) { ++ config.addDefault(path, def); ++ return config.getString(path, config.getString(path)); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b31109d2dadd29e8852468c19265066b773d2be0 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -0,0 +1,68 @@ ++package com.destroystokyo.paper; ++ ++import java.util.List; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.configuration.file.YamlConfiguration; ++import org.spigotmc.SpigotWorldConfig; ++ ++import static com.destroystokyo.paper.PaperConfig.log; ++import static com.destroystokyo.paper.PaperConfig.logError; ++ ++public class PaperWorldConfig { ++ ++ private final String worldName; ++ private final SpigotWorldConfig spigotConfig; ++ private YamlConfiguration config; ++ private boolean verbose; ++ ++ public PaperWorldConfig(String worldName, SpigotWorldConfig spigotConfig) { ++ this.worldName = worldName; ++ this.spigotConfig = spigotConfig; ++ this.config = PaperConfig.config; ++ init(); ++ } ++ ++ public void init() { ++ this.config = PaperConfig.config; // grab updated reference ++ log("-------- World Settings For [" + worldName + "] --------"); ++ PaperConfig.readConfig(PaperWorldConfig.class, this); ++ } ++ ++ private void set(String path, Object val) { ++ config.set("world-settings.default." + path, val); ++ if (config.get("world-settings." + worldName + "." + path) != null) { ++ config.set("world-settings." + worldName + "." + path, val); ++ } ++ } ++ ++ private boolean getBoolean(String path, boolean def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path)); ++ } ++ ++ private double getDouble(String path, double def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getDouble("world-settings." + worldName + "." + path, config.getDouble("world-settings.default." + path)); ++ } ++ ++ private int getInt(String path, int def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getInt("world-settings." + worldName + "." + path, config.getInt("world-settings.default." + path)); ++ } ++ ++ private float getFloat(String path, float def) { ++ // TODO: Figure out why getFloat() always returns the default value. ++ return (float) getDouble(path, (double) def); ++ } ++ ++ private List getList(String path, List def) { ++ config.addDefault("world-settings.default." + path, def); ++ return (List) config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)); ++ } ++ ++ private String getString(String path, String def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index b746e30e6fc5ea0c17465b510d737316f1ab7004..89db31061fcc3420bc8e668533a4051cdbd12253 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -103,6 +103,12 @@ public class Main { + DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(iregistrycustom_dimension, optionset); // CraftBukkit - CLI argument support + + dedicatedserversettings.save(); ++ // Paper start - load config files for access below if needed ++ org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = loadConfigFile((File) optionset.valueOf("bukkit-settings")); ++ org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = loadConfigFile((File) optionset.valueOf("spigot-settings")); ++ org.bukkit.configuration.file.YamlConfiguration paperConfiguration = loadConfigFile((File) optionset.valueOf("paper-settings")); ++ // Paper end ++ + java.nio.file.Path java_nio_file_path1 = Paths.get("eula.txt"); + EULA eula = new EULA(java_nio_file_path1); + +@@ -244,6 +250,20 @@ public class Main { + + } + ++ // Paper start - load config files ++ private static org.bukkit.configuration.file.YamlConfiguration loadConfigFile(File configFile) throws Exception { ++ org.bukkit.configuration.file.YamlConfiguration config = new org.bukkit.configuration.file.YamlConfiguration(); ++ if (configFile.exists()) { ++ try { ++ config.load(configFile); ++ } catch (Exception ex) { ++ throw new Exception("Failed to load configuration file: " + configFile.getName(), ex); ++ } ++ } ++ return config; ++ } ++ // Paper end ++ + public static void convertWorld(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, boolean flag, BooleanSupplier booleansupplier, ImmutableSet> immutableset) { // CraftBukkit + Main.LOGGER.info("Forcing world upgrade! {}", convertable_conversionsession.getLevelName()); // CraftBukkit + WorldUpgrader worldupgrader = new WorldUpgrader(convertable_conversionsession, datafixer, immutableset, flag); +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index d5628a0197125506f7aaeb89bab7bd8a811b3ad5..8e2e415a022ccd486465f19d9bbf1f287b21fb95 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -187,6 +187,15 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); + org.spigotmc.SpigotConfig.registerCommands(); + // Spigot end ++ // Paper start ++ try { ++ com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); ++ } catch (Exception e) { ++ DedicatedServer.LOGGER.error("Unable to load server configuration", e); ++ return false; ++ } ++ com.destroystokyo.paper.PaperConfig.registerCommands(); ++ // Paper end + + this.setPVP(dedicatedserverproperties.pvp); + this.setAllowFlight(dedicatedserverproperties.allowFlight); +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index e95f516756b2613972f20636443b3ff753342917..7fd6893c30fbb34367181620aa159ed79b803455 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -306,15 +306,15 @@ public class ChunkProviderServer extends IChunkProvider { + } + } + +- @Override +- public boolean a(Entity entity) { ++ public final boolean isInEntityTickingChunk(Entity entity) { return this.a(entity); } // Paper - OBFHELPER ++ @Override public boolean a(Entity entity) { + long i = ChunkCoordIntPair.pair(MathHelper.floor(entity.locX()) >> 4, MathHelper.floor(entity.locZ()) >> 4); + + return this.a(i, (Function>>) PlayerChunk::b); // CraftBukkit - decompile error + } + +- @Override +- public boolean a(ChunkCoordIntPair chunkcoordintpair) { ++ public final boolean isEntityTickingChunk(ChunkCoordIntPair chunkcoordintpair) { return this.a(chunkcoordintpair); } // Paper - OBFHELPER ++ @Override public boolean a(ChunkCoordIntPair chunkcoordintpair) { + return this.a(chunkcoordintpair.pair(), (Function>>) PlayerChunk::b); // CraftBukkit - decompile error + } + +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index 4b0b782ab19a6cea4412b5e9d8c0524aee1402e4..a32bc63ff1960bdb874d546ee42633063834da24 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -2,6 +2,7 @@ package net.minecraft.world.entity; + + import com.google.common.collect.ImmutableSet; + import java.util.Optional; ++import java.util.Set; // Paper + import java.util.UUID; + import java.util.function.Function; + import java.util.stream.Stream; +@@ -599,4 +600,10 @@ public class EntityTypes { + return new EntityTypes<>(this.a, this.b, this.d, this.e, this.f, this.g, this.c, this.j, this.h, this.i); + } + } ++ ++ // Paper start ++ public static Set getEntityNameList() { ++ return IRegistry.ENTITY_TYPE.keySet(); ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 344b7f52e85af3e543da0bb1dd14b68eb41ebb84..f794113e7cc5809d1da0c85648fb7311fb633f40 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -129,6 +129,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public boolean populating; + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + ++ public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper ++ + public final SpigotTimings.WorldTimingsHandler timings; // Spigot + public static BlockPosition lastPhysicsProblem; // Spigot + private org.spigotmc.TickLimiter entityLimiter; +@@ -149,6 +151,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName()); // Spigot ++ this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper + this.generator = gen; + this.world = new CraftWorld((WorldServer) this, gen, env); + this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index f03d83440291a329f5a1922c8710ed975025fdbb..82f5b3387f9e71ae258111b7196986623452dc02 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -807,6 +807,7 @@ public final class CraftServer implements Server { + } + + org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot ++ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper + for (WorldServer world : console.getWorlds()) { + world.worldDataServer.setDifficulty(config.difficulty); + world.setSpawnFlags(config.spawnMonsters, config.spawnAnimals); +@@ -840,6 +841,7 @@ public final class CraftServer implements Server { + world.ticksPerAmbientSpawns = this.getTicksPerAmbientSpawns(); + } + world.spigotConfig.init(); // Spigot ++ world.paperConfig.init(); // Paper + } + + pluginManager.clearPlugins(); +@@ -847,6 +849,7 @@ public final class CraftServer implements Server { + resetRecipes(); + reloadData(); + org.spigotmc.SpigotConfig.registerCommands(); // Spigot ++ com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper + overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); + ignoreVanillaPermissions = commandsConfiguration.getBoolean("ignore-vanilla-permissions"); + +@@ -2102,4 +2105,35 @@ public final class CraftServer implements Server { + return spigot; + } + // Spigot end ++ ++ // Paper start ++ @SuppressWarnings({"rawtypes", "unchecked"}) ++ public static java.nio.file.Path dumpHeap(java.nio.file.Path dir, String name) { ++ try { ++ java.nio.file.Files.createDirectories(dir); ++ ++ javax.management.MBeanServer server = java.lang.management.ManagementFactory.getPlatformMBeanServer(); ++ java.nio.file.Path file; ++ ++ try { ++ Class clazz = Class.forName("openj9.lang.management.OpenJ9DiagnosticsMXBean"); ++ Object openj9Mbean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "openj9.lang.management:type=OpenJ9Diagnostics", clazz); ++ java.lang.reflect.Method m = clazz.getMethod("triggerDumpToFile", String.class, String.class); ++ file = dir.resolve(name + ".phd"); ++ m.invoke(openj9Mbean, "heap", file.toString()); ++ } catch (ClassNotFoundException e) { ++ Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean"); ++ Object hotspotMBean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", clazz); ++ java.lang.reflect.Method m = clazz.getMethod("dumpHeap", String.class, boolean.class); ++ file = dir.resolve(name + ".hprof"); ++ m.invoke(hotspotMBean, file.toString(), true); ++ } ++ ++ return file; ++ } catch (Throwable t) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not write heap", t); ++ return null; ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 46a16e31775b28c44f95a8ac5545ebcb656c74b6..05aedca561919a12ced1925c5cc9af585bb04523 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -129,6 +129,14 @@ public class Main { + .defaultsTo(new File("spigot.yml")) + .describedAs("Yml file"); + // Spigot End ++ ++ // Paper Start ++ acceptsAll(asList("paper", "paper-settings"), "File for paper settings") ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File("paper.yml")) ++ .describedAs("Yml file"); ++ // Paper end + } + }; + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 83d83ff7ceffbb77723da721b869dfd0091e496d..0efcbab8f8806aeb8dd8bd6384e5a7cee375d100 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -39,36 +39,36 @@ public class SpigotWorldConfig + config.set( "world-settings.default." + path, val ); + } + +- private boolean getBoolean(String path, boolean def) ++ public boolean getBoolean(String path, boolean def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return config.getBoolean( "world-settings." + worldName + "." + path, config.getBoolean( "world-settings.default." + path ) ); + } + +- private double getDouble(String path, double def) ++ public double getDouble(String path, double def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return config.getDouble( "world-settings." + worldName + "." + path, config.getDouble( "world-settings.default." + path ) ); + } + +- private int getInt(String path) ++ public int getInt(String path) // Paper - private -> public + { + return config.getInt( "world-settings." + worldName + "." + path ); + } + +- private int getInt(String path, int def) ++ public int getInt(String path, int def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return config.getInt( "world-settings." + worldName + "." + path, config.getInt( "world-settings.default." + path ) ); + } + +- private List getList(String path, T def) ++ public List getList(String path, T def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return (List) config.getList( "world-settings." + worldName + "." + path, config.getList( "world-settings.default." + path ) ); + } + +- private String getString(String path, String def) ++ public String getString(String path, String def) // Paper - private -> public + { + config.addDefault( "world-settings.default." + path, def ); + return config.getString( "world-settings." + worldName + "." + path, config.getString( "world-settings.default." + path ) ); diff --git a/patches/server-unmapped/0003-MC-Dev-fixes.patch b/patches/server-unmapped/0003-MC-Dev-fixes.patch new file mode 100644 index 0000000000..1f1f3bab60 --- /dev/null +++ b/patches/server-unmapped/0003-MC-Dev-fixes.patch @@ -0,0 +1,893 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 30 Mar 2016 19:36:20 -0400 +Subject: [PATCH] MC Dev fixes + + +diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java +index 14b1a51b9b675aa175c32990402551fa43ec1599..bc7757b929ecce998094ddcdf51a4703e165a6d6 100644 +--- a/src/main/java/net/minecraft/SystemUtils.java ++++ b/src/main/java/net/minecraft/SystemUtils.java +@@ -65,8 +65,8 @@ public class SystemUtils { + return Collectors.toMap(Entry::getKey, Entry::getValue); + } + +- public static > String a(IBlockState iblockstate, Object object) { +- return iblockstate.a((Comparable) object); ++ public static > String a(IBlockState iblockstate, T object) { // Paper - decompile fix ++ return iblockstate.a(object); // Paper - decompile fix + } + + public static String a(String s, @Nullable MinecraftKey minecraftkey) { +@@ -234,8 +234,8 @@ public class SystemUtils { + public static T b(Iterable iterable, @Nullable T t0) { + Iterator iterator = iterable.iterator(); + +- Object object; +- Object object1; ++ T object; // Paper - decompile fix ++ T object1; // Paper - decompile fix + + for (object1 = null; iterator.hasNext(); object1 = object) { + object = iterator.next(); +@@ -260,7 +260,7 @@ public class SystemUtils { + } + + public static Strategy k() { +- return SystemUtils.IdentityHashingStrategy.INSTANCE; ++ return (Strategy) SystemUtils.IdentityHashingStrategy.INSTANCE; // Paper - decompile fix + } + + public static CompletableFuture> b(List> list) { +@@ -271,7 +271,7 @@ public class SystemUtils { + list.forEach((completablefuture1) -> { + int i = list1.size(); + +- list1.add((Object) null); ++ list1.add(null); // Paper - decompile fix + acompletablefuture[i] = completablefuture1.whenComplete((object, throwable) -> { + if (throwable != null) { + completablefuture.completeExceptionally(throwable); +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index f85889a232998520761731a17f3d293d3360fe2c..76675ad1633dbaebb180842b9914fac18741c62e 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -241,8 +241,8 @@ public class BlockPosition extends BaseBlockPosition { + }; + } + +- public static Iterable a(BlockPosition blockposition, int i, int j, int k) { +- int l = i + j + k; ++ public static Iterable a(BlockPosition blockposition, int p_i, int p_j, int p_k) { // Paper - decompile issues - variable name conflicts to inner class field refs ++ int l_decompiled = p_i + p_j + p_k; // Paper - decompile issues + int i1 = blockposition.getX(); + int j1 = blockposition.getY(); + int k1 = blockposition.getZ(); +@@ -270,15 +270,15 @@ public class BlockPosition extends BaseBlockPosition { + ++this.l; + if (this.l > this.j) { + ++this.i; +- if (this.i > l) { ++ if (this.i > l_decompiled) { // Paper - use proper l above (first line of this method) + return (BlockPosition) this.endOfData(); + } + +- this.j = Math.min(i, this.i); ++ this.j = Math.min(p_i, this.i); // Paper - decompile issues + this.l = -this.j; + } + +- this.k = Math.min(j, this.i - Math.abs(this.l)); ++ this.k = Math.min(p_j, this.i - Math.abs(this.l)); // Paper - decompile issues + this.m = -this.k; + } + +@@ -286,7 +286,7 @@ public class BlockPosition extends BaseBlockPosition { + int i2 = this.m; + int j2 = this.i - Math.abs(l1) - Math.abs(i2); + +- if (j2 <= k) { ++ if (j2 <= p_k) { // Paper - decompile issues + this.n = j2 != 0; + blockposition_mutableblockposition = this.h.d(i1 + l1, j1 + i2, k1 + j2); + } +@@ -355,13 +355,13 @@ public class BlockPosition extends BaseBlockPosition { + }; + } + +- public static Iterable a(BlockPosition blockposition, int i, EnumDirection enumdirection, EnumDirection enumdirection1) { ++ public static Iterable a(BlockPosition blockposition, int I, EnumDirection enumdirection, EnumDirection enumdirection1) { // Paper - decompile fix + Validate.validState(enumdirection.n() != enumdirection1.n(), "The two directions cannot be on the same axis", new Object[0]); + return () -> { + return new AbstractIterator() { + private final EnumDirection[] e = new EnumDirection[]{enumdirection, enumdirection1, enumdirection.opposite(), enumdirection1.opposite()}; + private final BlockPosition.MutableBlockPosition f = blockposition.i().c(enumdirection1); +- private final int g = 4 * i; ++ private final int g = 4 * I; + private int h = -1; + private int i; + private int j; +diff --git a/src/main/java/net/minecraft/core/RegistryBlockID.java b/src/main/java/net/minecraft/core/RegistryBlockID.java +index b173ed8a6abeee41ce48e03f6403f2eb4978155b..e543b6927280a14e1d1220534758289934e31282 100644 +--- a/src/main/java/net/minecraft/core/RegistryBlockID.java ++++ b/src/main/java/net/minecraft/core/RegistryBlockID.java +@@ -27,7 +27,7 @@ public class RegistryBlockID implements Registry { + this.b.put(t0, i); + + while (this.c.size() <= i) { +- this.c.add((Object) null); ++ this.c.add(null); // Paper - decompile fix + } + + this.c.set(i, t0); +@@ -41,6 +41,13 @@ public class RegistryBlockID implements Registry { + this.a(t0, this.a); + } + ++ // Paper start - decompile fix ++ @Override ++ public int a(T t) { ++ return getId(t); ++ } ++ // Paper end ++ + public int getId(T t0) { + Integer integer = (Integer) this.b.get(t0); + +diff --git a/src/main/java/net/minecraft/nbt/NBTBase.java b/src/main/java/net/minecraft/nbt/NBTBase.java +index 170a65cb13e7b87f64cd28331431ba55d53702cd..d6e51f82f6df2d7058806f3e483766e18398af77 100644 +--- a/src/main/java/net/minecraft/nbt/NBTBase.java ++++ b/src/main/java/net/minecraft/nbt/NBTBase.java +@@ -20,7 +20,7 @@ public interface NBTBase { + + NBTTagType b(); + +- NBTBase clone(); ++ public NBTBase clone(); // Paper - decompile fix + + default String asString() { + return this.toString(); +diff --git a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java +index be4d54099a0deb0e0275208ac61c8a172a48b398..850d3a7bb8ae4c43c0e2f737cfe69261f338b026 100644 +--- a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java ++++ b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java +@@ -18,6 +18,7 @@ import java.util.zip.GZIPOutputStream; + import net.minecraft.CrashReport; + import net.minecraft.CrashReportSystemDetails; + import net.minecraft.ReportedException; ++import io.netty.buffer.ByteBufInputStream; // Paper + + public class NBTCompressedStreamTools { + +@@ -137,7 +138,7 @@ public class NBTCompressedStreamTools { + + public static NBTTagCompound a(DataInput datainput, NBTReadLimiter nbtreadlimiter) throws IOException { + // Spigot start +- if ( datainput instanceof io.netty.buffer.ByteBufInputStream ) ++ if ( datainput instanceof ByteBufInputStream) // Paper + { + datainput = new DataInputStream(new org.spigotmc.LimitStream((InputStream) datainput, nbtreadlimiter)); + } +diff --git a/src/main/java/net/minecraft/nbt/NBTTagList.java b/src/main/java/net/minecraft/nbt/NBTTagList.java +index 35cca76fb7c7aa736e64185b44016e65cfaef6cd..4f6f6f51f9807bafa88482c0fe776c8b163107d7 100644 +--- a/src/main/java/net/minecraft/nbt/NBTTagList.java ++++ b/src/main/java/net/minecraft/nbt/NBTTagList.java +@@ -53,7 +53,7 @@ public class NBTTagList extends NBTList { + return "TAG_List"; + } + }; +- private static final ByteSet b = new ByteOpenHashSet(Arrays.asList(1, 2, 3, 4, 5, 6)); ++ private static final ByteSet b = new ByteOpenHashSet(Arrays.asList((byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6)); // Paper - decompiler fix + private final List list; + private byte type; + +diff --git a/src/main/java/net/minecraft/network/EnumProtocol.java b/src/main/java/net/minecraft/network/EnumProtocol.java +index ab08336043d4f558434ed1f38d25cc555ace1ac0..a892521db1197369bf6363bd2f5da24bf53643ab 100644 +--- a/src/main/java/net/minecraft/network/EnumProtocol.java ++++ b/src/main/java/net/minecraft/network/EnumProtocol.java +@@ -12,6 +12,8 @@ import javax.annotation.Nullable; + import net.minecraft.SystemUtils; + import net.minecraft.network.protocol.EnumProtocolDirection; + import net.minecraft.network.protocol.Packet; ++import net.minecraft.network.protocol.game.PacketListenerPlayIn; ++import net.minecraft.network.protocol.game.PacketListenerPlayOut; + import net.minecraft.network.protocol.game.PacketPlayInAbilities; + import net.minecraft.network.protocol.game.PacketPlayInAdvancements; + import net.minecraft.network.protocol.game.PacketPlayInArmAnimation; +@@ -146,24 +148,30 @@ import net.minecraft.network.protocol.game.PacketPlayOutWindowItems; + import net.minecraft.network.protocol.game.PacketPlayOutWorldBorder; + import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; + import net.minecraft.network.protocol.game.PacketPlayOutWorldParticles; ++import net.minecraft.network.protocol.handshake.PacketHandshakingInListener; + import net.minecraft.network.protocol.handshake.PacketHandshakingInSetProtocol; + import net.minecraft.network.protocol.login.PacketLoginInCustomPayload; + import net.minecraft.network.protocol.login.PacketLoginInEncryptionBegin; ++import net.minecraft.network.protocol.login.PacketLoginInListener; + import net.minecraft.network.protocol.login.PacketLoginInStart; + import net.minecraft.network.protocol.login.PacketLoginOutCustomPayload; + import net.minecraft.network.protocol.login.PacketLoginOutDisconnect; + import net.minecraft.network.protocol.login.PacketLoginOutEncryptionBegin; ++import net.minecraft.network.protocol.login.PacketLoginOutListener; + import net.minecraft.network.protocol.login.PacketLoginOutSetCompression; + import net.minecraft.network.protocol.login.PacketLoginOutSuccess; ++import net.minecraft.network.protocol.status.PacketStatusInListener; + import net.minecraft.network.protocol.status.PacketStatusInPing; + import net.minecraft.network.protocol.status.PacketStatusInStart; ++import net.minecraft.network.protocol.status.PacketStatusOutListener; + import net.minecraft.network.protocol.status.PacketStatusOutPong; + import net.minecraft.network.protocol.status.PacketStatusOutServerInfo; + import org.apache.logging.log4j.LogManager; + + public enum EnumProtocol { + +- HANDSHAKING(-1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketHandshakingInSetProtocol.class, PacketHandshakingInSetProtocol::new))), PLAY(0, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a<>()).a(PacketPlayOutSpawnEntity.class, PacketPlayOutSpawnEntity::new).a(PacketPlayOutSpawnEntityExperienceOrb.class, PacketPlayOutSpawnEntityExperienceOrb::new).a(PacketPlayOutSpawnEntityLiving.class, PacketPlayOutSpawnEntityLiving::new).a(PacketPlayOutSpawnEntityPainting.class, PacketPlayOutSpawnEntityPainting::new).a(PacketPlayOutNamedEntitySpawn.class, PacketPlayOutNamedEntitySpawn::new).a(PacketPlayOutAnimation.class, PacketPlayOutAnimation::new).a(PacketPlayOutStatistic.class, PacketPlayOutStatistic::new).a(PacketPlayOutBlockBreak.class, PacketPlayOutBlockBreak::new).a(PacketPlayOutBlockBreakAnimation.class, PacketPlayOutBlockBreakAnimation::new).a(PacketPlayOutTileEntityData.class, PacketPlayOutTileEntityData::new).a(PacketPlayOutBlockAction.class, PacketPlayOutBlockAction::new).a(PacketPlayOutBlockChange.class, PacketPlayOutBlockChange::new).a(PacketPlayOutBoss.class, PacketPlayOutBoss::new).a(PacketPlayOutServerDifficulty.class, PacketPlayOutServerDifficulty::new).a(PacketPlayOutChat.class, PacketPlayOutChat::new).a(PacketPlayOutTabComplete.class, PacketPlayOutTabComplete::new).a(PacketPlayOutCommands.class, PacketPlayOutCommands::new).a(PacketPlayOutTransaction.class, PacketPlayOutTransaction::new).a(PacketPlayOutCloseWindow.class, PacketPlayOutCloseWindow::new).a(PacketPlayOutWindowItems.class, PacketPlayOutWindowItems::new).a(PacketPlayOutWindowData.class, PacketPlayOutWindowData::new).a(PacketPlayOutSetSlot.class, PacketPlayOutSetSlot::new).a(PacketPlayOutSetCooldown.class, PacketPlayOutSetCooldown::new).a(PacketPlayOutCustomPayload.class, PacketPlayOutCustomPayload::new).a(PacketPlayOutCustomSoundEffect.class, PacketPlayOutCustomSoundEffect::new).a(PacketPlayOutKickDisconnect.class, PacketPlayOutKickDisconnect::new).a(PacketPlayOutEntityStatus.class, PacketPlayOutEntityStatus::new).a(PacketPlayOutExplosion.class, PacketPlayOutExplosion::new).a(PacketPlayOutUnloadChunk.class, PacketPlayOutUnloadChunk::new).a(PacketPlayOutGameStateChange.class, PacketPlayOutGameStateChange::new).a(PacketPlayOutOpenWindowHorse.class, PacketPlayOutOpenWindowHorse::new).a(PacketPlayOutKeepAlive.class, PacketPlayOutKeepAlive::new).a(PacketPlayOutMapChunk.class, PacketPlayOutMapChunk::new).a(PacketPlayOutWorldEvent.class, PacketPlayOutWorldEvent::new).a(PacketPlayOutWorldParticles.class, PacketPlayOutWorldParticles::new).a(PacketPlayOutLightUpdate.class, PacketPlayOutLightUpdate::new).a(PacketPlayOutLogin.class, PacketPlayOutLogin::new).a(PacketPlayOutMap.class, PacketPlayOutMap::new).a(PacketPlayOutOpenWindowMerchant.class, PacketPlayOutOpenWindowMerchant::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMove.class, PacketPlayOutEntity.PacketPlayOutRelEntityMove::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook.class, PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook::new).a(PacketPlayOutEntity.PacketPlayOutEntityLook.class, PacketPlayOutEntity.PacketPlayOutEntityLook::new).a(PacketPlayOutEntity.class, PacketPlayOutEntity::new).a(PacketPlayOutVehicleMove.class, PacketPlayOutVehicleMove::new).a(PacketPlayOutOpenBook.class, PacketPlayOutOpenBook::new).a(PacketPlayOutOpenWindow.class, PacketPlayOutOpenWindow::new).a(PacketPlayOutOpenSignEditor.class, PacketPlayOutOpenSignEditor::new).a(PacketPlayOutAutoRecipe.class, PacketPlayOutAutoRecipe::new).a(PacketPlayOutAbilities.class, PacketPlayOutAbilities::new).a(PacketPlayOutCombatEvent.class, PacketPlayOutCombatEvent::new).a(PacketPlayOutPlayerInfo.class, PacketPlayOutPlayerInfo::new).a(PacketPlayOutLookAt.class, PacketPlayOutLookAt::new).a(PacketPlayOutPosition.class, PacketPlayOutPosition::new).a(PacketPlayOutRecipes.class, PacketPlayOutRecipes::new).a(PacketPlayOutEntityDestroy.class, PacketPlayOutEntityDestroy::new).a(PacketPlayOutRemoveEntityEffect.class, PacketPlayOutRemoveEntityEffect::new).a(PacketPlayOutResourcePackSend.class, PacketPlayOutResourcePackSend::new).a(PacketPlayOutRespawn.class, PacketPlayOutRespawn::new).a(PacketPlayOutEntityHeadRotation.class, PacketPlayOutEntityHeadRotation::new).a(PacketPlayOutMultiBlockChange.class, PacketPlayOutMultiBlockChange::new).a(PacketPlayOutSelectAdvancementTab.class, PacketPlayOutSelectAdvancementTab::new).a(PacketPlayOutWorldBorder.class, PacketPlayOutWorldBorder::new).a(PacketPlayOutCamera.class, PacketPlayOutCamera::new).a(PacketPlayOutHeldItemSlot.class, PacketPlayOutHeldItemSlot::new).a(PacketPlayOutViewCentre.class, PacketPlayOutViewCentre::new).a(PacketPlayOutViewDistance.class, PacketPlayOutViewDistance::new).a(PacketPlayOutSpawnPosition.class, PacketPlayOutSpawnPosition::new).a(PacketPlayOutScoreboardDisplayObjective.class, PacketPlayOutScoreboardDisplayObjective::new).a(PacketPlayOutEntityMetadata.class, PacketPlayOutEntityMetadata::new).a(PacketPlayOutAttachEntity.class, PacketPlayOutAttachEntity::new).a(PacketPlayOutEntityVelocity.class, PacketPlayOutEntityVelocity::new).a(PacketPlayOutEntityEquipment.class, PacketPlayOutEntityEquipment::new).a(PacketPlayOutExperience.class, PacketPlayOutExperience::new).a(PacketPlayOutUpdateHealth.class, PacketPlayOutUpdateHealth::new).a(PacketPlayOutScoreboardObjective.class, PacketPlayOutScoreboardObjective::new).a(PacketPlayOutMount.class, PacketPlayOutMount::new).a(PacketPlayOutScoreboardTeam.class, PacketPlayOutScoreboardTeam::new).a(PacketPlayOutScoreboardScore.class, PacketPlayOutScoreboardScore::new).a(PacketPlayOutUpdateTime.class, PacketPlayOutUpdateTime::new).a(PacketPlayOutTitle.class, PacketPlayOutTitle::new).a(PacketPlayOutEntitySound.class, PacketPlayOutEntitySound::new).a(PacketPlayOutNamedSoundEffect.class, PacketPlayOutNamedSoundEffect::new).a(PacketPlayOutStopSound.class, PacketPlayOutStopSound::new).a(PacketPlayOutPlayerListHeaderFooter.class, PacketPlayOutPlayerListHeaderFooter::new).a(PacketPlayOutNBTQuery.class, PacketPlayOutNBTQuery::new).a(PacketPlayOutCollect.class, PacketPlayOutCollect::new).a(PacketPlayOutEntityTeleport.class, PacketPlayOutEntityTeleport::new).a(PacketPlayOutAdvancements.class, PacketPlayOutAdvancements::new).a(PacketPlayOutUpdateAttributes.class, PacketPlayOutUpdateAttributes::new).a(PacketPlayOutEntityEffect.class, PacketPlayOutEntityEffect::new).a(PacketPlayOutRecipeUpdate.class, PacketPlayOutRecipeUpdate::new).a(PacketPlayOutTags.class, PacketPlayOutTags::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketPlayInTeleportAccept.class, PacketPlayInTeleportAccept::new).a(PacketPlayInTileNBTQuery.class, PacketPlayInTileNBTQuery::new).a(PacketPlayInDifficultyChange.class, PacketPlayInDifficultyChange::new).a(PacketPlayInChat.class, PacketPlayInChat::new).a(PacketPlayInClientCommand.class, PacketPlayInClientCommand::new).a(PacketPlayInSettings.class, PacketPlayInSettings::new).a(PacketPlayInTabComplete.class, PacketPlayInTabComplete::new).a(PacketPlayInTransaction.class, PacketPlayInTransaction::new).a(PacketPlayInEnchantItem.class, PacketPlayInEnchantItem::new).a(PacketPlayInWindowClick.class, PacketPlayInWindowClick::new).a(PacketPlayInCloseWindow.class, PacketPlayInCloseWindow::new).a(PacketPlayInCustomPayload.class, PacketPlayInCustomPayload::new).a(PacketPlayInBEdit.class, PacketPlayInBEdit::new).a(PacketPlayInEntityNBTQuery.class, PacketPlayInEntityNBTQuery::new).a(PacketPlayInUseEntity.class, PacketPlayInUseEntity::new).a(PacketPlayInJigsawGenerate.class, PacketPlayInJigsawGenerate::new).a(PacketPlayInKeepAlive.class, PacketPlayInKeepAlive::new).a(PacketPlayInDifficultyLock.class, PacketPlayInDifficultyLock::new).a(PacketPlayInFlying.PacketPlayInPosition.class, PacketPlayInFlying.PacketPlayInPosition::new).a(PacketPlayInFlying.PacketPlayInPositionLook.class, PacketPlayInFlying.PacketPlayInPositionLook::new).a(PacketPlayInFlying.PacketPlayInLook.class, PacketPlayInFlying.PacketPlayInLook::new).a(PacketPlayInFlying.class, PacketPlayInFlying::new).a(PacketPlayInVehicleMove.class, PacketPlayInVehicleMove::new).a(PacketPlayInBoatMove.class, PacketPlayInBoatMove::new).a(PacketPlayInPickItem.class, PacketPlayInPickItem::new).a(PacketPlayInAutoRecipe.class, PacketPlayInAutoRecipe::new).a(PacketPlayInAbilities.class, PacketPlayInAbilities::new).a(PacketPlayInBlockDig.class, PacketPlayInBlockDig::new).a(PacketPlayInEntityAction.class, PacketPlayInEntityAction::new).a(PacketPlayInSteerVehicle.class, PacketPlayInSteerVehicle::new).a(PacketPlayInRecipeSettings.class, PacketPlayInRecipeSettings::new).a(PacketPlayInRecipeDisplayed.class, PacketPlayInRecipeDisplayed::new).a(PacketPlayInItemName.class, PacketPlayInItemName::new).a(PacketPlayInResourcePackStatus.class, PacketPlayInResourcePackStatus::new).a(PacketPlayInAdvancements.class, PacketPlayInAdvancements::new).a(PacketPlayInTrSel.class, PacketPlayInTrSel::new).a(PacketPlayInBeacon.class, PacketPlayInBeacon::new).a(PacketPlayInHeldItemSlot.class, PacketPlayInHeldItemSlot::new).a(PacketPlayInSetCommandBlock.class, PacketPlayInSetCommandBlock::new).a(PacketPlayInSetCommandMinecart.class, PacketPlayInSetCommandMinecart::new).a(PacketPlayInSetCreativeSlot.class, PacketPlayInSetCreativeSlot::new).a(PacketPlayInSetJigsaw.class, PacketPlayInSetJigsaw::new).a(PacketPlayInStruct.class, PacketPlayInStruct::new).a(PacketPlayInUpdateSign.class, PacketPlayInUpdateSign::new).a(PacketPlayInArmAnimation.class, PacketPlayInArmAnimation::new).a(PacketPlayInSpectate.class, PacketPlayInSpectate::new).a(PacketPlayInUseItem.class, PacketPlayInUseItem::new).a(PacketPlayInBlockPlace.class, PacketPlayInBlockPlace::new))), STATUS(1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketStatusInStart.class, PacketStatusInStart::new).a(PacketStatusInPing.class, PacketStatusInPing::new)).a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a<>()).a(PacketStatusOutServerInfo.class, PacketStatusOutServerInfo::new).a(PacketStatusOutPong.class, PacketStatusOutPong::new))), LOGIN(2, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a<>()).a(PacketLoginOutDisconnect.class, PacketLoginOutDisconnect::new).a(PacketLoginOutEncryptionBegin.class, PacketLoginOutEncryptionBegin::new).a(PacketLoginOutSuccess.class, PacketLoginOutSuccess::new).a(PacketLoginOutSetCompression.class, PacketLoginOutSetCompression::new).a(PacketLoginOutCustomPayload.class, PacketLoginOutCustomPayload::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketLoginInStart.class, PacketLoginInStart::new).a(PacketLoginInEncryptionBegin.class, PacketLoginInEncryptionBegin::new).a(PacketLoginInCustomPayload.class, PacketLoginInCustomPayload::new))); ++ // Paper - fix decompile error - add generic names to < > like PacketListenerPlayOut ++ HANDSHAKING(-1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketHandshakingInSetProtocol.class, PacketHandshakingInSetProtocol::new))), PLAY(0, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a()).a(PacketPlayOutSpawnEntity.class, PacketPlayOutSpawnEntity::new).a(PacketPlayOutSpawnEntityExperienceOrb.class, PacketPlayOutSpawnEntityExperienceOrb::new).a(PacketPlayOutSpawnEntityLiving.class, PacketPlayOutSpawnEntityLiving::new).a(PacketPlayOutSpawnEntityPainting.class, PacketPlayOutSpawnEntityPainting::new).a(PacketPlayOutNamedEntitySpawn.class, PacketPlayOutNamedEntitySpawn::new).a(PacketPlayOutAnimation.class, PacketPlayOutAnimation::new).a(PacketPlayOutStatistic.class, PacketPlayOutStatistic::new).a(PacketPlayOutBlockBreak.class, PacketPlayOutBlockBreak::new).a(PacketPlayOutBlockBreakAnimation.class, PacketPlayOutBlockBreakAnimation::new).a(PacketPlayOutTileEntityData.class, PacketPlayOutTileEntityData::new).a(PacketPlayOutBlockAction.class, PacketPlayOutBlockAction::new).a(PacketPlayOutBlockChange.class, PacketPlayOutBlockChange::new).a(PacketPlayOutBoss.class, PacketPlayOutBoss::new).a(PacketPlayOutServerDifficulty.class, PacketPlayOutServerDifficulty::new).a(PacketPlayOutChat.class, PacketPlayOutChat::new).a(PacketPlayOutTabComplete.class, PacketPlayOutTabComplete::new).a(PacketPlayOutCommands.class, PacketPlayOutCommands::new).a(PacketPlayOutTransaction.class, PacketPlayOutTransaction::new).a(PacketPlayOutCloseWindow.class, PacketPlayOutCloseWindow::new).a(PacketPlayOutWindowItems.class, PacketPlayOutWindowItems::new).a(PacketPlayOutWindowData.class, PacketPlayOutWindowData::new).a(PacketPlayOutSetSlot.class, PacketPlayOutSetSlot::new).a(PacketPlayOutSetCooldown.class, PacketPlayOutSetCooldown::new).a(PacketPlayOutCustomPayload.class, PacketPlayOutCustomPayload::new).a(PacketPlayOutCustomSoundEffect.class, PacketPlayOutCustomSoundEffect::new).a(PacketPlayOutKickDisconnect.class, PacketPlayOutKickDisconnect::new).a(PacketPlayOutEntityStatus.class, PacketPlayOutEntityStatus::new).a(PacketPlayOutExplosion.class, PacketPlayOutExplosion::new).a(PacketPlayOutUnloadChunk.class, PacketPlayOutUnloadChunk::new).a(PacketPlayOutGameStateChange.class, PacketPlayOutGameStateChange::new).a(PacketPlayOutOpenWindowHorse.class, PacketPlayOutOpenWindowHorse::new).a(PacketPlayOutKeepAlive.class, PacketPlayOutKeepAlive::new).a(PacketPlayOutMapChunk.class, PacketPlayOutMapChunk::new).a(PacketPlayOutWorldEvent.class, PacketPlayOutWorldEvent::new).a(PacketPlayOutWorldParticles.class, PacketPlayOutWorldParticles::new).a(PacketPlayOutLightUpdate.class, PacketPlayOutLightUpdate::new).a(PacketPlayOutLogin.class, PacketPlayOutLogin::new).a(PacketPlayOutMap.class, PacketPlayOutMap::new).a(PacketPlayOutOpenWindowMerchant.class, PacketPlayOutOpenWindowMerchant::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMove.class, PacketPlayOutEntity.PacketPlayOutRelEntityMove::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook.class, PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook::new).a(PacketPlayOutEntity.PacketPlayOutEntityLook.class, PacketPlayOutEntity.PacketPlayOutEntityLook::new).a(PacketPlayOutEntity.class, PacketPlayOutEntity::new).a(PacketPlayOutVehicleMove.class, PacketPlayOutVehicleMove::new).a(PacketPlayOutOpenBook.class, PacketPlayOutOpenBook::new).a(PacketPlayOutOpenWindow.class, PacketPlayOutOpenWindow::new).a(PacketPlayOutOpenSignEditor.class, PacketPlayOutOpenSignEditor::new).a(PacketPlayOutAutoRecipe.class, PacketPlayOutAutoRecipe::new).a(PacketPlayOutAbilities.class, PacketPlayOutAbilities::new).a(PacketPlayOutCombatEvent.class, PacketPlayOutCombatEvent::new).a(PacketPlayOutPlayerInfo.class, PacketPlayOutPlayerInfo::new).a(PacketPlayOutLookAt.class, PacketPlayOutLookAt::new).a(PacketPlayOutPosition.class, PacketPlayOutPosition::new).a(PacketPlayOutRecipes.class, PacketPlayOutRecipes::new).a(PacketPlayOutEntityDestroy.class, PacketPlayOutEntityDestroy::new).a(PacketPlayOutRemoveEntityEffect.class, PacketPlayOutRemoveEntityEffect::new).a(PacketPlayOutResourcePackSend.class, PacketPlayOutResourcePackSend::new).a(PacketPlayOutRespawn.class, PacketPlayOutRespawn::new).a(PacketPlayOutEntityHeadRotation.class, PacketPlayOutEntityHeadRotation::new).a(PacketPlayOutMultiBlockChange.class, PacketPlayOutMultiBlockChange::new).a(PacketPlayOutSelectAdvancementTab.class, PacketPlayOutSelectAdvancementTab::new).a(PacketPlayOutWorldBorder.class, PacketPlayOutWorldBorder::new).a(PacketPlayOutCamera.class, PacketPlayOutCamera::new).a(PacketPlayOutHeldItemSlot.class, PacketPlayOutHeldItemSlot::new).a(PacketPlayOutViewCentre.class, PacketPlayOutViewCentre::new).a(PacketPlayOutViewDistance.class, PacketPlayOutViewDistance::new).a(PacketPlayOutSpawnPosition.class, PacketPlayOutSpawnPosition::new).a(PacketPlayOutScoreboardDisplayObjective.class, PacketPlayOutScoreboardDisplayObjective::new).a(PacketPlayOutEntityMetadata.class, PacketPlayOutEntityMetadata::new).a(PacketPlayOutAttachEntity.class, PacketPlayOutAttachEntity::new).a(PacketPlayOutEntityVelocity.class, PacketPlayOutEntityVelocity::new).a(PacketPlayOutEntityEquipment.class, PacketPlayOutEntityEquipment::new).a(PacketPlayOutExperience.class, PacketPlayOutExperience::new).a(PacketPlayOutUpdateHealth.class, PacketPlayOutUpdateHealth::new).a(PacketPlayOutScoreboardObjective.class, PacketPlayOutScoreboardObjective::new).a(PacketPlayOutMount.class, PacketPlayOutMount::new).a(PacketPlayOutScoreboardTeam.class, PacketPlayOutScoreboardTeam::new).a(PacketPlayOutScoreboardScore.class, PacketPlayOutScoreboardScore::new).a(PacketPlayOutUpdateTime.class, PacketPlayOutUpdateTime::new).a(PacketPlayOutTitle.class, PacketPlayOutTitle::new).a(PacketPlayOutEntitySound.class, PacketPlayOutEntitySound::new).a(PacketPlayOutNamedSoundEffect.class, PacketPlayOutNamedSoundEffect::new).a(PacketPlayOutStopSound.class, PacketPlayOutStopSound::new).a(PacketPlayOutPlayerListHeaderFooter.class, PacketPlayOutPlayerListHeaderFooter::new).a(PacketPlayOutNBTQuery.class, PacketPlayOutNBTQuery::new).a(PacketPlayOutCollect.class, PacketPlayOutCollect::new).a(PacketPlayOutEntityTeleport.class, PacketPlayOutEntityTeleport::new).a(PacketPlayOutAdvancements.class, PacketPlayOutAdvancements::new).a(PacketPlayOutUpdateAttributes.class, PacketPlayOutUpdateAttributes::new).a(PacketPlayOutEntityEffect.class, PacketPlayOutEntityEffect::new).a(PacketPlayOutRecipeUpdate.class, PacketPlayOutRecipeUpdate::new).a(PacketPlayOutTags.class, PacketPlayOutTags::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketPlayInTeleportAccept.class, PacketPlayInTeleportAccept::new).a(PacketPlayInTileNBTQuery.class, PacketPlayInTileNBTQuery::new).a(PacketPlayInDifficultyChange.class, PacketPlayInDifficultyChange::new).a(PacketPlayInChat.class, PacketPlayInChat::new).a(PacketPlayInClientCommand.class, PacketPlayInClientCommand::new).a(PacketPlayInSettings.class, PacketPlayInSettings::new).a(PacketPlayInTabComplete.class, PacketPlayInTabComplete::new).a(PacketPlayInTransaction.class, PacketPlayInTransaction::new).a(PacketPlayInEnchantItem.class, PacketPlayInEnchantItem::new).a(PacketPlayInWindowClick.class, PacketPlayInWindowClick::new).a(PacketPlayInCloseWindow.class, PacketPlayInCloseWindow::new).a(PacketPlayInCustomPayload.class, PacketPlayInCustomPayload::new).a(PacketPlayInBEdit.class, PacketPlayInBEdit::new).a(PacketPlayInEntityNBTQuery.class, PacketPlayInEntityNBTQuery::new).a(PacketPlayInUseEntity.class, PacketPlayInUseEntity::new).a(PacketPlayInJigsawGenerate.class, PacketPlayInJigsawGenerate::new).a(PacketPlayInKeepAlive.class, PacketPlayInKeepAlive::new).a(PacketPlayInDifficultyLock.class, PacketPlayInDifficultyLock::new).a(PacketPlayInFlying.PacketPlayInPosition.class, PacketPlayInFlying.PacketPlayInPosition::new).a(PacketPlayInFlying.PacketPlayInPositionLook.class, PacketPlayInFlying.PacketPlayInPositionLook::new).a(PacketPlayInFlying.PacketPlayInLook.class, PacketPlayInFlying.PacketPlayInLook::new).a(PacketPlayInFlying.class, PacketPlayInFlying::new).a(PacketPlayInVehicleMove.class, PacketPlayInVehicleMove::new).a(PacketPlayInBoatMove.class, PacketPlayInBoatMove::new).a(PacketPlayInPickItem.class, PacketPlayInPickItem::new).a(PacketPlayInAutoRecipe.class, PacketPlayInAutoRecipe::new).a(PacketPlayInAbilities.class, PacketPlayInAbilities::new).a(PacketPlayInBlockDig.class, PacketPlayInBlockDig::new).a(PacketPlayInEntityAction.class, PacketPlayInEntityAction::new).a(PacketPlayInSteerVehicle.class, PacketPlayInSteerVehicle::new).a(PacketPlayInRecipeSettings.class, PacketPlayInRecipeSettings::new).a(PacketPlayInRecipeDisplayed.class, PacketPlayInRecipeDisplayed::new).a(PacketPlayInItemName.class, PacketPlayInItemName::new).a(PacketPlayInResourcePackStatus.class, PacketPlayInResourcePackStatus::new).a(PacketPlayInAdvancements.class, PacketPlayInAdvancements::new).a(PacketPlayInTrSel.class, PacketPlayInTrSel::new).a(PacketPlayInBeacon.class, PacketPlayInBeacon::new).a(PacketPlayInHeldItemSlot.class, PacketPlayInHeldItemSlot::new).a(PacketPlayInSetCommandBlock.class, PacketPlayInSetCommandBlock::new).a(PacketPlayInSetCommandMinecart.class, PacketPlayInSetCommandMinecart::new).a(PacketPlayInSetCreativeSlot.class, PacketPlayInSetCreativeSlot::new).a(PacketPlayInSetJigsaw.class, PacketPlayInSetJigsaw::new).a(PacketPlayInStruct.class, PacketPlayInStruct::new).a(PacketPlayInUpdateSign.class, PacketPlayInUpdateSign::new).a(PacketPlayInArmAnimation.class, PacketPlayInArmAnimation::new).a(PacketPlayInSpectate.class, PacketPlayInSpectate::new).a(PacketPlayInUseItem.class, PacketPlayInUseItem::new).a(PacketPlayInBlockPlace.class, PacketPlayInBlockPlace::new))), STATUS(1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketStatusInStart.class, PacketStatusInStart::new).a(PacketStatusInPing.class, PacketStatusInPing::new)).a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a()).a(PacketStatusOutServerInfo.class, PacketStatusOutServerInfo::new).a(PacketStatusOutPong.class, PacketStatusOutPong::new))), LOGIN(2, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a()).a(PacketLoginOutDisconnect.class, PacketLoginOutDisconnect::new).a(PacketLoginOutEncryptionBegin.class, PacketLoginOutEncryptionBegin::new).a(PacketLoginOutSuccess.class, PacketLoginOutSuccess::new).a(PacketLoginOutSetCompression.class, PacketLoginOutSetCompression::new).a(PacketLoginOutCustomPayload.class, PacketLoginOutCustomPayload::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketLoginInStart.class, PacketLoginInStart::new).a(PacketLoginInEncryptionBegin.class, PacketLoginInEncryptionBegin::new).a(PacketLoginInCustomPayload.class, PacketLoginInCustomPayload::new))); + + private static final EnumProtocol[] e = new EnumProtocol[4]; + private static final Map>, EnumProtocol> f = Maps.newHashMap(); +@@ -248,7 +256,7 @@ public enum EnumProtocol { + private final List>> b; + + private a() { +- this.a = (Object2IntMap) SystemUtils.a((Object) (new Object2IntOpenHashMap()), (object2intopenhashmap) -> { ++ this.a = (Object2IntMap) SystemUtils.a(new Object2IntOpenHashMap(), (object2intopenhashmap) -> { // Paper - fix decompile error + object2intopenhashmap.defaultReturnValue(-1); + }); + this.b = Lists.newArrayList(); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 6977255868dbc0a96973095fff2eb935ecf4f4fc..6d843bb69b1848ae77098dc3f45d85f405fc24cd 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1675,9 +1675,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrantmap(resourcepackrepository::a).filter(Objects::nonNull).map(ResourcePackLoader::d).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error + }, this).thenCompose((immutablelist) -> { +- return DataPackResources.a(immutablelist, this.j() ? CommandDispatcher.ServerType.DEDICATED : CommandDispatcher.ServerType.INTEGRATED, this.h(), this.executorService, this); ++ return DataPackResources.a(immutablelist, this.j() ? CommandDispatcher.ServerType.DEDICATED : CommandDispatcher.ServerType.INTEGRATED, this.h(), this.executorService, this); // Paper - decompile error + }).thenAcceptAsync((datapackresources) -> { + this.dataPackResources.close(); + this.dataPackResources = datapackresources; +diff --git a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java +index 5a51f47f747382ec2a30bb47bcb1f7c61dd4c369..e066848127cb9a42e8c39422691cc65132cac6bb 100644 +--- a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java ++++ b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java +@@ -179,7 +179,7 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { + + public void queueUpdate() { + if ((!this.c.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { +- this.b.a((Object) (() -> { ++ this.b.a((() -> { // Paper - decompile error + this.b(); + this.g.set(false); + })); +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index 1c500e1193296f92f03a94e2cf085b215daaad6c..51ef4adf66c1e21093e63ab46fa47e66c2425fdb 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -23,7 +23,7 @@ public final class Ticket implements Comparable> { + } else { + int j = Integer.compare(System.identityHashCode(this.a), System.identityHashCode(ticket.a)); + +- return j != 0 ? j : this.a.a().compare(this.identifier, ticket.identifier); ++ return j != 0 ? j : this.a.a().compare(this.identifier, (T)ticket.identifier); // Paper - decompile fix + } + } + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 144c80a4f3f827d5ee0a9220d12c49ee9aa3f096..7f9a1d64d123ce54608497a0e0a37d161d8c9d3c 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1919,7 +1919,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + // CraftBukkit - decompile error +- return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(it.unimi.dsi.fastutil.objects.Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { ++ return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { // Paper - decompile fix + return it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey() + ":" + it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue(); + }).collect(Collectors.joining(",")); + } catch (Exception exception) { +diff --git a/src/main/java/net/minecraft/stats/ServerStatisticManager.java b/src/main/java/net/minecraft/stats/ServerStatisticManager.java +index 322a4b584c6223b08581affb2e9919df19c0267b..1efab34e03199879f5e0dcee0ff79ce2c23c73bc 100644 +--- a/src/main/java/net/minecraft/stats/ServerStatisticManager.java ++++ b/src/main/java/net/minecraft/stats/ServerStatisticManager.java +@@ -203,7 +203,7 @@ public class ServerStatisticManager extends StatisticManager { + ObjectIterator objectiterator = this.a.object2IntEntrySet().iterator(); + + while (objectiterator.hasNext()) { +- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); ++ Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix + Statistic statistic = (Statistic) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); + + ((JsonObject) map.computeIfAbsent(statistic.getWrapper(), (statisticwrapper) -> { +diff --git a/src/main/java/net/minecraft/util/ArraySetSorted.java b/src/main/java/net/minecraft/util/ArraySetSorted.java +index e56b8e172d96c5508457fcf3f5a0cf0d2d2d8d7c..427daa94322f47b4eaf881d85a01fed239db549a 100644 +--- a/src/main/java/net/minecraft/util/ArraySetSorted.java ++++ b/src/main/java/net/minecraft/util/ArraySetSorted.java +@@ -23,11 +23,11 @@ public class ArraySetSorted extends AbstractSet { + } + + public static > ArraySetSorted a(int i) { +- return new ArraySetSorted<>(i, Comparator.naturalOrder()); ++ return new ArraySetSorted<>(i, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix + } + + private static T[] a(Object[] aobject) { +- return (Object[]) aobject; ++ return (T[])aobject; // Paper - decompile fix + } + + private int c(T t0) { +@@ -101,7 +101,7 @@ public class ArraySetSorted extends AbstractSet { + } + + public boolean remove(Object object) { +- int i = this.c(object); ++ int i = this.c((T)object); // Paper - decompile fix + + if (i >= 0) { + this.d(i); +@@ -116,7 +116,7 @@ public class ArraySetSorted extends AbstractSet { + } + + public boolean contains(Object object) { +- int i = this.c(object); ++ int i = this.c((T)object); // Paper - decompile fix + + return i >= 0; + } +@@ -135,7 +135,7 @@ public class ArraySetSorted extends AbstractSet { + + public U[] toArray(U[] au) { + if (au.length < this.c) { +- return (Object[]) Arrays.copyOf(this.b, this.c, au.getClass()); ++ return (U[])Arrays.copyOf(this.b, this.c, au.getClass()); // Paper - decompile fix + } else { + System.arraycopy(this.b, 0, au, 0, this.c); + if (au.length > this.c) { +diff --git a/src/main/java/net/minecraft/util/RegistryID.java b/src/main/java/net/minecraft/util/RegistryID.java +index d88e55c64f80707b4a9b1e271714c2dbdee9a38a..6150f7a5c5004ac79414ab22dbaa3439dc8afdb4 100644 +--- a/src/main/java/net/minecraft/util/RegistryID.java ++++ b/src/main/java/net/minecraft/util/RegistryID.java +@@ -18,11 +18,18 @@ public class RegistryID implements Registry { + + public RegistryID(int i) { + i = (int) ((float) i / 0.8F); +- this.b = (Object[]) (new Object[i]); ++ this.b = (K[]) (new Object[i]); // Paper - decompile fix + this.c = new int[i]; +- this.d = (Object[]) (new Object[i]); ++ this.d = (K[]) (new Object[i]); // Paper - decompile fix + } + ++ // Paper start - decompile fix ++ @Override ++ public int a(K k) { ++ return getId(k); ++ } ++ // Paper end ++ + public int getId(@Nullable K k0) { + return this.c(this.b(k0, this.d(k0))); + } +@@ -56,9 +63,9 @@ public class RegistryID implements Registry { + K[] ak = this.b; + int[] aint = this.c; + +- this.b = (Object[]) (new Object[i]); ++ this.b = (K[]) (new Object[i]); // Paper - decompile fix + this.c = new int[i]; +- this.d = (Object[]) (new Object[i]); ++ this.d = (K[]) (new Object[i]); // Paper - decompile fix + this.e = 0; + this.f = 0; + +diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java +index 6abf1459cc97c261daf3c116521574d31a77a338..2b2c03ab62816f3d21ef953c4a45f55e3997cca6 100644 +--- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java ++++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java +@@ -55,7 +55,7 @@ public abstract class IAsyncTaskHandler implements Mailbox implements Mailbox implements Mailbox, AutoCloseable, Runnable { + + public void run() { + try { +- this.a((i) -> { ++ this.a((int i) -> { // Paper - decompile fix + return i == 0; + }); + } finally { +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java +index fe5dcce3873ca2724ac9d416d6f5d3c65d0fdafe..aa1d948e6aebef25f0f4c4c07f5131d2e8387e59 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java +@@ -191,9 +191,9 @@ public class VillagePlace extends RegionFileSection { + } + + private static boolean a(ChunkSection chunksection) { +- Set set = VillagePlaceType.x; ++ Set set = VillagePlaceType.x; // Paper - decompile error + +- set.getClass(); ++ //set.getClass(); // Paper - decompile error + return chunksection.a(set::contains); + } + +@@ -211,7 +211,7 @@ public class VillagePlace extends RegionFileSection { + SectionPosition.b(new ChunkCoordIntPair(blockposition), Math.floorDiv(i, 16)).map((sectionposition) -> { + return Pair.of(sectionposition, this.d(sectionposition.s())); + }).filter((pair) -> { +- return !(Boolean) ((Optional) pair.getSecond()).map(VillagePlaceSection::a).orElse(false); ++ return !(Boolean) (pair.getSecond()).map(VillagePlaceSection::a).orElse(false); // Paper - decompile fix + }).map((pair) -> { + return ((SectionPosition) pair.getFirst()).r(); + }).filter((chunkcoordintpair) -> { +@@ -263,7 +263,7 @@ public class VillagePlace extends RegionFileSection { + + private final Predicate d; + +- private Occupancy(Predicate predicate) { ++ private Occupancy(Predicate predicate) { // Paper - decompile fix + this.d = predicate; + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java +index fc1f0cd4b70cdd0dda538d8867fab4cb8443120e..c181d5f5e6108ade54fc97c665897d1db5e90719 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java +@@ -65,7 +65,7 @@ public class EntityVindicator extends EntityIllagerAbstract { + this.goalSelector.a(2, new EntityIllagerAbstract.b(this)); + this.goalSelector.a(3, new EntityRaider.a(this, 10.0F)); + this.goalSelector.a(4, new EntityVindicator.c(this)); +- this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a()); ++ this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix + this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); + this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, true)); + this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, true)); +diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +index fe1dde99f758daa730acacc78237d92aa443ab6d..764ff5d9ffb541a356a6bc8b321e619849dde747 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java ++++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +@@ -47,12 +47,12 @@ import net.minecraft.world.level.saveddata.maps.WorldMap; + + public class VillagerTrades { + +- public static final Map> a = (Map) SystemUtils.a((Object) Maps.newHashMap(), (hashmap) -> { ++ public static final Map> a = SystemUtils.a(Maps.newHashMap(), (hashmap) -> { // Paper - decompile fix + hashmap.put(VillagerProfession.FARMER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WHEAT, 20, 16, 2), new VillagerTrades.b(Items.POTATO, 26, 16, 2), new VillagerTrades.b(Items.CARROT, 22, 16, 2), new VillagerTrades.b(Items.BEETROOT, 15, 16, 2), new VillagerTrades.h(Items.BREAD, 1, 6, 16, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Blocks.PUMPKIN, 6, 12, 10), new VillagerTrades.h(Items.PUMPKIN_PIE, 1, 4, 5), new VillagerTrades.h(Items.APPLE, 1, 4, 16, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.COOKIE, 3, 18, 10), new VillagerTrades.b(Blocks.MELON, 4, 12, 20)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Blocks.CAKE, 1, 1, 12, 15), new VillagerTrades.i(MobEffects.NIGHT_VISION, 100, 15), new VillagerTrades.i(MobEffects.JUMP, 160, 15), new VillagerTrades.i(MobEffects.WEAKNESS, 140, 15), new VillagerTrades.i(MobEffects.BLINDNESS, 120, 15), new VillagerTrades.i(MobEffects.POISON, 280, 15), new VillagerTrades.i(MobEffects.SATURATION, 7, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.GOLDEN_CARROT, 3, 3, 30), new VillagerTrades.h(Items.GLISTERING_MELON_SLICE, 4, 3, 30)}))); +- hashmap.put(VillagerProfession.FISHERMAN, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STRING, 20, 16, 2), new VillagerTrades.b(Items.COAL, 10, 16, 2), new VillagerTrades.g(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.h(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COD, 15, 16, 10), new VillagerTrades.g(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.h(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.SALMON, 13, 16, 20), new VillagerTrades.e(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.c(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); ++ hashmap.put(VillagerProfession.FISHERMAN, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STRING, 20, 16, 2), new VillagerTrades.b(Items.COAL, 10, 16, 2), new VillagerTrades.g(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.h(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COD, 15, 16, 10), new VillagerTrades.g(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.h(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.SALMON, 13, 16, 20), new VillagerTrades.e(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.c(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); // Paper - add to ImmutableMap..builder() + hashmap.put(VillagerProfession.SHEPHERD, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Blocks.WHITE_WOOL, 18, 16, 2), new VillagerTrades.b(Blocks.BROWN_WOOL, 18, 16, 2), new VillagerTrades.b(Blocks.BLACK_WOOL, 18, 16, 2), new VillagerTrades.b(Blocks.GRAY_WOOL, 18, 16, 2), new VillagerTrades.h(Items.SHEARS, 2, 1, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WHITE_DYE, 12, 16, 10), new VillagerTrades.b(Items.GRAY_DYE, 12, 16, 10), new VillagerTrades.b(Items.BLACK_DYE, 12, 16, 10), new VillagerTrades.b(Items.LIGHT_BLUE_DYE, 12, 16, 10), new VillagerTrades.b(Items.LIME_DYE, 12, 16, 10), new VillagerTrades.h(Blocks.WHITE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.ORANGE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.MAGENTA_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.LIGHT_BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.YELLOW_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.LIME_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.PINK_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.LIGHT_GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.CYAN_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.PURPLE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.BROWN_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.GREEN_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.RED_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.BLACK_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.WHITE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.ORANGE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.MAGENTA_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.LIGHT_BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.YELLOW_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.LIME_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.PINK_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.LIGHT_GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.CYAN_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.PURPLE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.BROWN_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.GREEN_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.RED_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.BLACK_CARPET, 1, 4, 16, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.YELLOW_DYE, 12, 16, 20), new VillagerTrades.b(Items.LIGHT_GRAY_DYE, 12, 16, 20), new VillagerTrades.b(Items.ORANGE_DYE, 12, 16, 20), new VillagerTrades.b(Items.RED_DYE, 12, 16, 20), new VillagerTrades.b(Items.PINK_DYE, 12, 16, 20), new VillagerTrades.h(Blocks.WHITE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.YELLOW_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.RED_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.BLACK_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.BLUE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.BROWN_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.CYAN_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.GRAY_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.GREEN_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.LIGHT_BLUE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.LIGHT_GRAY_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.LIME_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.MAGENTA_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.ORANGE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.PINK_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.PURPLE_BED, 3, 1, 12, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.BROWN_DYE, 12, 16, 30), new VillagerTrades.b(Items.PURPLE_DYE, 12, 16, 30), new VillagerTrades.b(Items.BLUE_DYE, 12, 16, 30), new VillagerTrades.b(Items.GREEN_DYE, 12, 16, 30), new VillagerTrades.b(Items.MAGENTA_DYE, 12, 16, 30), new VillagerTrades.b(Items.CYAN_DYE, 12, 16, 30), new VillagerTrades.h(Items.WHITE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.LIGHT_BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.RED_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.PINK_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.GREEN_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.LIME_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.GRAY_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.BLACK_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.PURPLE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.MAGENTA_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.CYAN_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.BROWN_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.YELLOW_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.ORANGE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.LIGHT_GRAY_BANNER, 3, 1, 12, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.PAINTING, 2, 3, 30)}))); + hashmap.put(VillagerProfession.FLETCHER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STICK, 32, 16, 2), new VillagerTrades.h(Items.ARROW, 1, 16, 1), new VillagerTrades.g(Blocks.GRAVEL, 10, Items.FLINT, 10, 12, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.FLINT, 26, 12, 10), new VillagerTrades.h(Items.BOW, 2, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STRING, 14, 16, 20), new VillagerTrades.h(Items.CROSSBOW, 3, 1, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.FEATHER, 24, 16, 30), new VillagerTrades.e(Items.BOW, 2, 3, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.es, 8, 12, 30), new VillagerTrades.e(Items.CROSSBOW, 3, 3, 15), new VillagerTrades.j(Items.ARROW, 5, Items.TIPPED_ARROW, 5, 2, 12, 30)}))); +- hashmap.put(VillagerProfession.LIBRARIAN, a(ImmutableMap.builder().put(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PAPER, 24, 16, 2), new VillagerTrades.d(1), new VillagerTrades.h(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.BOOK, 4, 12, 10), new VillagerTrades.d(5), new VillagerTrades.h(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.INK_SAC, 5, 12, 20), new VillagerTrades.d(10), new VillagerTrades.h(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.d(15), new VillagerTrades.h(Items.CLOCK, 5, 1, 15), new VillagerTrades.h(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.NAME_TAG, 20, 1, 30)}).build())); ++ hashmap.put(VillagerProfession.LIBRARIAN, a(ImmutableMap.builder().put(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PAPER, 24, 16, 2), new VillagerTrades.d(1), new VillagerTrades.h(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.BOOK, 4, 12, 10), new VillagerTrades.d(5), new VillagerTrades.h(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.INK_SAC, 5, 12, 20), new VillagerTrades.d(10), new VillagerTrades.h(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.d(15), new VillagerTrades.h(Items.CLOCK, 5, 1, 15), new VillagerTrades.h(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.NAME_TAG, 20, 1, 30)}).build())); // Paper - add to ImmutableMap..builder() + hashmap.put(VillagerProfession.CARTOGRAPHER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PAPER, 24, 16, 2), new VillagerTrades.h(Items.MAP, 7, 1, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.dP, 11, 16, 10), new VillagerTrades.k(13, StructureGenerator.MONUMENT, MapIcon.Type.MONUMENT, 12, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COMPASS, 1, 12, 20), new VillagerTrades.k(14, StructureGenerator.MANSION, MapIcon.Type.MANSION, 12, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.ITEM_FRAME, 7, 1, 15), new VillagerTrades.h(Items.WHITE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.BLUE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.LIGHT_BLUE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.RED_BANNER, 3, 1, 15), new VillagerTrades.h(Items.PINK_BANNER, 3, 1, 15), new VillagerTrades.h(Items.GREEN_BANNER, 3, 1, 15), new VillagerTrades.h(Items.LIME_BANNER, 3, 1, 15), new VillagerTrades.h(Items.GRAY_BANNER, 3, 1, 15), new VillagerTrades.h(Items.BLACK_BANNER, 3, 1, 15), new VillagerTrades.h(Items.PURPLE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.MAGENTA_BANNER, 3, 1, 15), new VillagerTrades.h(Items.CYAN_BANNER, 3, 1, 15), new VillagerTrades.h(Items.BROWN_BANNER, 3, 1, 15), new VillagerTrades.h(Items.YELLOW_BANNER, 3, 1, 15), new VillagerTrades.h(Items.ORANGE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.LIGHT_GRAY_BANNER, 3, 1, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.GLOBE_BANNER_PATTERN, 8, 1, 30)}))); + hashmap.put(VillagerProfession.CLERIC, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.ROTTEN_FLESH, 32, 16, 2), new VillagerTrades.h(Items.REDSTONE, 1, 2, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.GOLD_INGOT, 3, 12, 10), new VillagerTrades.h(Items.LAPIS_LAZULI, 1, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.RABBIT_FOOT, 2, 12, 20), new VillagerTrades.h(Blocks.GLOWSTONE, 4, 1, 12, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.SCUTE, 4, 12, 30), new VillagerTrades.b(Items.GLASS_BOTTLE, 9, 12, 30), new VillagerTrades.h(Items.ENDER_PEARL, 5, 1, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.NETHER_WART, 22, 12, 30), new VillagerTrades.h(Items.EXPERIENCE_BOTTLE, 3, 1, 30)}))); + hashmap.put(VillagerProfession.ARMORER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COAL, 15, 16, 2), new VillagerTrades.h(new ItemStack(Items.IRON_LEGGINGS), 7, 1, 12, 1, 0.2F), new VillagerTrades.h(new ItemStack(Items.IRON_BOOTS), 4, 1, 12, 1, 0.2F), new VillagerTrades.h(new ItemStack(Items.IRON_HELMET), 5, 1, 12, 1, 0.2F), new VillagerTrades.h(new ItemStack(Items.IRON_CHESTPLATE), 9, 1, 12, 1, 0.2F)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.IRON_INGOT, 4, 12, 10), new VillagerTrades.h(new ItemStack(Items.rj), 36, 1, 12, 5, 0.2F), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_BOOTS), 1, 1, 12, 5, 0.2F), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_LEGGINGS), 3, 1, 12, 5, 0.2F)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.LAVA_BUCKET, 1, 12, 20), new VillagerTrades.b(Items.DIAMOND, 1, 12, 20), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_HELMET), 1, 1, 12, 10, 0.2F), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_CHESTPLATE), 4, 1, 12, 10, 0.2F), new VillagerTrades.h(new ItemStack(Items.SHIELD), 5, 1, 12, 10, 0.2F)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.e(Items.DIAMOND_LEGGINGS, 14, 3, 15, 0.2F), new VillagerTrades.e(Items.DIAMOND_BOOTS, 8, 3, 15, 0.2F)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.e(Items.DIAMOND_HELMET, 8, 3, 30, 0.2F), new VillagerTrades.e(Items.DIAMOND_CHESTPLATE, 16, 3, 30, 0.2F)}))); +diff --git a/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java b/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java +index 54a636a3d5fdd0107cd0a41167ab1626469fe042..5ba58bf1a47c696235e6e7a4a6815104bc23de80 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java ++++ b/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java +@@ -75,7 +75,7 @@ public class CraftingManager extends ResourceDataJson { + } + + this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { +- return (entry1.getValue()); // CraftBukkit ++ return entry1.getValue(); // CraftBukkit // Paper - decompile fix - *shrugs internally* + })); + CraftingManager.LOGGER.info("Loaded {} recipes", map1.size()); + } +diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java +index d24f97593777d6929271520f7501a800f1aadaa6..4ece69851e7b05016f52c291ce911eb791cf3a23 100644 +--- a/src/main/java/net/minecraft/world/level/IEntityAccess.java ++++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java +@@ -167,22 +167,22 @@ public interface IEntityAccess { + + @Nullable + default T a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { +- return this.a(this.a(oclass, axisalignedbb, (Predicate) null), pathfindertargetcondition, entityliving, d0, d1, d2); ++ return this.a(this.a(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix + } + + @Nullable + default T b(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { +- return this.a(this.b(oclass, axisalignedbb, (Predicate) null), pathfindertargetcondition, entityliving, d0, d1, d2); ++ return this.a(this.b(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix + } + + @Nullable + default T a(List list, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2) { + double d3 = -1.0D; + T t0 = null; +- Iterator iterator = list.iterator(); ++ Iterator iterator = list.iterator(); // Paper - decompile fix + + while (iterator.hasNext()) { +- T t1 = (EntityLiving) iterator.next(); ++ T t1 = iterator.next(); // Paper - decompile fix + + if (pathfindertargetcondition.a(entityliving, t1)) { + double d4 = t1.h(d0, d1, d2); +@@ -215,10 +215,10 @@ public interface IEntityAccess { + default List a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, AxisAlignedBB axisalignedbb) { + List list = this.a(oclass, axisalignedbb, (Predicate) null); + List list1 = Lists.newArrayList(); +- Iterator iterator = list.iterator(); ++ Iterator iterator = list.iterator(); // Paper - decompile fix + + while (iterator.hasNext()) { +- T t0 = (EntityLiving) iterator.next(); ++ T t0 = iterator.next(); // Paper - decompile fix + + if (pathfindertargetcondition.a(entityliving, t0)) { + list1.add(t0); +diff --git a/src/main/java/net/minecraft/world/level/NextTickListEntry.java b/src/main/java/net/minecraft/world/level/NextTickListEntry.java +index 116a5e4ded3ccf935fd143f2512098c22ec2ad76..f3bcb96232d18abbcd86b079a7c5830bb30d75d2 100644 +--- a/src/main/java/net/minecraft/world/level/NextTickListEntry.java ++++ b/src/main/java/net/minecraft/world/level/NextTickListEntry.java +@@ -38,13 +38,13 @@ public class NextTickListEntry { + return this.a.hashCode(); + } + +- public static Comparator> a() { ++ public static Comparator a() { // Paper - decompile fix + return Comparator.comparingLong((nextticklistentry) -> { +- return nextticklistentry.b; ++ return ((NextTickListEntry) nextticklistentry).b; // Paper - decompile fix + }).thenComparing((nextticklistentry) -> { +- return nextticklistentry.c; ++ return ((NextTickListEntry) nextticklistentry).c; // Paper - decompile fix + }).thenComparingLong((nextticklistentry) -> { +- return nextticklistentry.f; ++ return ((NextTickListEntry) nextticklistentry).f; // Paper - decompile fix + }); + } + +diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java +index 6672d74426d6a334d52f641c48d3a352c2bb6605..7147cdda756ccb3d4f6880802128f68601783883 100644 +--- a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java ++++ b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java +@@ -49,8 +49,15 @@ import org.apache.logging.log4j.Logger; + public final class BiomeBase { + + public static final Logger LOGGER = LogManager.getLogger(); ++ // Paper start ++ private static class dProxy extends BiomeBase.d { ++ private dProxy(Precipitation biomebase_precipitation, float f, TemperatureModifier biomebase_temperaturemodifier, float f1) { ++ super(biomebase_precipitation, f, biomebase_temperaturemodifier, f1); ++ } ++ }; ++ // Paper end + public static final Codec b = RecordCodecBuilder.create((instance) -> { +- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { ++ return instance.group(dProxy.a.forGetter((biomebase) -> { // Paper + return biomebase.j; + }), BiomeBase.Geography.r.fieldOf("category").forGetter((biomebase) -> { + return biomebase.o; +@@ -67,7 +74,7 @@ public final class BiomeBase { + })).apply(instance, BiomeBase::new); + }); + public static final Codec c = RecordCodecBuilder.create((instance) -> { +- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { ++ return instance.group(dProxy.a.forGetter((biomebase) -> { // Paper + return biomebase.j; + }), BiomeBase.Geography.r.fieldOf("category").forGetter((biomebase) -> { + return biomebase.o; +diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java +index a549195e67236c0146861b896fb9e4907073af58..8d13e60f40e1b760e9e69969dc3f37bc6c70dbe9 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java +@@ -160,7 +160,7 @@ public class TileEntityPiston extends TileEntity implements ITickable { + private static void a(EnumDirection enumdirection, Entity entity, double d0, EnumDirection enumdirection1) { + TileEntityPiston.h.set(enumdirection); + entity.move(EnumMoveType.PISTON, new Vec3D(d0 * (double) enumdirection1.getAdjacentX(), d0 * (double) enumdirection1.getAdjacentY(), d0 * (double) enumdirection1.getAdjacentZ())); +- TileEntityPiston.h.set((Object) null); ++ TileEntityPiston.h.set(null); // Paper - decompile fix + } + + private void g(float f) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java +index 074bd5f060c6bb80568b72d23ce84c27ba774578..e4b59a85ee9b435b2e86d4c7d78b7224773f6967 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java ++++ b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java +@@ -28,11 +28,11 @@ public abstract class IBlockDataHolder { + } else { + IBlockState iblockstate = (IBlockState) entry.getKey(); + +- return iblockstate.getName() + "=" + this.a(iblockstate, (Comparable) entry.getValue()); ++ return iblockstate.getName() + "=" + this.a((IBlockState) iblockstate, (Comparable) entry.getValue()); // Paper - decompile fix + } + } + +- private > String a(IBlockState iblockstate, Comparable comparable) { ++ private > String a(IBlockState iblockstate, T comparable) { // Paper - decompile error + return iblockstate.a(comparable); + } + }; +@@ -48,11 +48,11 @@ public abstract class IBlockDataHolder { + } + + public > S a(IBlockState iblockstate) { +- return this.set(iblockstate, (Comparable) a(iblockstate.getValues(), (Object) this.get(iblockstate))); ++ return this.set(iblockstate, a(iblockstate.getValues(), this.get(iblockstate))); // Paper - decompile error + } + + protected static T a(Collection collection, T t0) { +- Iterator iterator = collection.iterator(); ++ Iterator iterator = collection.iterator(); // Paper + + do { + if (!iterator.hasNext()) { +@@ -94,7 +94,7 @@ public abstract class IBlockDataHolder { + if (comparable == null) { + throw new IllegalArgumentException("Cannot get property " + iblockstate + " as it does not exist in " + this.c); + } else { +- return (Comparable) iblockstate.getType().cast(comparable); ++ return iblockstate.getType().cast(comparable); // Paper - decompile error + } + } + +@@ -110,7 +110,7 @@ public abstract class IBlockDataHolder { + if (comparable == null) { + throw new IllegalArgumentException("Cannot set property " + iblockstate + " as it does not exist in " + this.c); + } else if (comparable == v0) { +- return this; ++ return (S) this; // Paper - decompile error + } else { + S s0 = this.e.get(iblockstate, v0); + +@@ -162,7 +162,7 @@ public abstract class IBlockDataHolder { + return codec.dispatch("Name", (iblockdataholder) -> { + return iblockdataholder.c; + }, (object) -> { +- S s0 = (IBlockDataHolder) function.apply(object); ++ S s0 = function.apply(object); // Paper - decompile error + + return s0.getStateMap().isEmpty() ? Codec.unit(s0) : s0.d.fieldOf("Properties").codec(); + }); +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java +index a6aaf0efed5a9c5e458ca04a80a7a5e71a31d886..de85894beae7ee7d276cf2af3daa77377ce131c3 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java +@@ -21,10 +21,10 @@ public class BlockStateEnum & INamable> extends IBlockState + protected BlockStateEnum(String s, Class oclass, Collection collection) { + super(s, oclass); + this.a = ImmutableSet.copyOf(collection); +- Iterator iterator = collection.iterator(); ++ Iterator iterator = collection.iterator(); // Paper - decompile fix + + while (iterator.hasNext()) { +- T t0 = (Enum) iterator.next(); ++ T t0 = iterator.next(); // Paper - Decompile fix + String s1 = ((INamable) t0).getName(); + + if (this.b.containsKey(s1)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java +index 3e6ba74027685c6190426c825736e84cda87ca63..e3969bad5be64bb41e2973751605d6820c16f021 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java +@@ -17,12 +17,10 @@ public abstract class IBlockState> { + private final Codec> e; + + protected IBlockState(String s, Class oclass) { +- this.d = Codec.STRING.comapFlatMap((s1) -> { +- return (DataResult) this.b(s1).map(DataResult::success).orElseGet(() -> { +- return DataResult.error("Unable to read property: " + this + " with value: " + s1); +- }); +- }, this::a); +- this.e = this.d.xmap(this::b, IBlockState.a::b); ++ this.d = Codec.STRING.comapFlatMap((s1) -> this.b(s1).map(DataResult::success).orElseGet(() -> { // Paper - decompile error ++ return DataResult.error("Unable to read property: " + this + " with value: " + s1); ++ }), this::a); ++ this.e = this.d.xmap(this::b, (IBlockState.a param) -> param.b()); // Paper - decompile fix + this.a = oclass; + this.b = s; + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +index 88c2643a18165bd7a9e6e056b926d6e894ff60d4..859561a5dccba6548967b685b20e8fcfc296db2a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +@@ -89,7 +89,7 @@ public class IOWorker implements AutoCloseable { + return this.a(() -> { + try { + this.d.a(); +- return Either.left((Object) null); ++ return Either.left(null); // Paper - decompile error + } catch (Exception exception) { + IOWorker.LOGGER.warn("Failed to synchronized chunks", exception); + return Either.right(exception); +@@ -123,13 +123,13 @@ public class IOWorker implements AutoCloseable { + } + + private void c() { +- this.c.a((Object) (new PairedQueue.b(IOWorker.Priority.LOW.ordinal(), this::b))); ++ this.c.a((new PairedQueue.b(IOWorker.Priority.LOW.ordinal(), this::b))); // Paper - decompile error + } + + private void a(ChunkCoordIntPair chunkcoordintpair, IOWorker.a ioworker_a) { + try { + this.d.write(chunkcoordintpair, ioworker_a.a); +- ioworker_a.b.complete((Object) null); ++ ioworker_a.b.complete(null); // Paper - decompile fix + } catch (Exception exception) { + IOWorker.LOGGER.error("Failed to store chunk {}", chunkcoordintpair, exception); + ioworker_a.b.completeExceptionally(exception); +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +index 6fb0c92e7cb6117d919af613dae87fa4e99f5081..f727cc456bd23816c4e70be83c395d1d8ca7d876 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +@@ -430,7 +430,7 @@ public class EnderDragonBattle { + } + } + +- worldgenendtrophy.b((WorldGenFeatureConfiguration) WorldGenFeatureConfiguration.k).a(this.world, this.world.getChunkProvider().getChunkGenerator(), new Random(), this.exitPortalLocation); ++ worldgenendtrophy.b(WorldGenFeatureConfiguration.k).a(this.world, this.world.getChunkProvider().getChunkGenerator(), new Random(), this.exitPortalLocation); // Paper - decompile fix + } + + private EntityEnderDragon o() { +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java +index 44ad3fb2551f681b58b82e7c4f56bbc5a3b4486e..6724927be178cb9a358a9276d01894a63154b7b3 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java +@@ -71,13 +71,13 @@ public abstract class StructureGenerator + public static final StructureGenerator BASTION_REMNANT = a("Bastion_Remnant", new WorldGenFeatureBastionRemnant(WorldGenFeatureVillageConfiguration.a), WorldGenStage.Decoration.SURFACE_STRUCTURES); + public static final List> t = ImmutableList.of(StructureGenerator.PILLAGER_OUTPOST, StructureGenerator.VILLAGE, StructureGenerator.NETHER_FOSSIL); + private static final MinecraftKey w = new MinecraftKey("jigsaw"); +- private static final Map x = ImmutableMap.builder().put(new MinecraftKey("nvi"), StructureGenerator.w).put(new MinecraftKey("pcp"), StructureGenerator.w).put(new MinecraftKey("bastionremnant"), StructureGenerator.w).put(new MinecraftKey("runtime"), StructureGenerator.w).build(); ++ private static final Map x = ImmutableMap.builder().put(new MinecraftKey("nvi"), StructureGenerator.w).put(new MinecraftKey("pcp"), StructureGenerator.w).put(new MinecraftKey("bastionremnant"), StructureGenerator.w).put(new MinecraftKey("runtime"), StructureGenerator.w).build(); // Paper - decompile fix + private final Codec>> y; + + private static > F a(String s, F f0, WorldGenStage.Decoration worldgenstage_decoration) { + StructureGenerator.a.put(s.toLowerCase(Locale.ROOT), f0); + StructureGenerator.u.put(f0, worldgenstage_decoration); +- return (StructureGenerator) IRegistry.a(IRegistry.STRUCTURE_FEATURE, s.toLowerCase(Locale.ROOT), (Object) f0); ++ return (F) IRegistry.>a(IRegistry.STRUCTURE_FEATURE, s.toLowerCase(Locale.ROOT), f0); // Paper - decomp fix + } + + public StructureGenerator(Codec codec) { +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java +index 52564cce4146f49a906729b3ed9488a7a829ea3f..befc8f846c772d58ee687ad427bb71206b4dc43e 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java +@@ -34,10 +34,10 @@ public class LightEngineStorageSky extends LightEngineStorage= l) { +diff --git a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java +index 45c1d79e0bb2fcffea31513c3d003d28140146b9..3910daeaa177639fa8055301304634c2014dc20f 100644 +--- a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java ++++ b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java +@@ -44,7 +44,7 @@ public class WorldPersistentData { + if (t0 != null) { + return t0; + } else { +- T t1 = (PersistentBase) supplier.get(); ++ T t1 = supplier.get(); // Paper - decompile fix + + this.a(t1); + return t1; +@@ -53,7 +53,7 @@ public class WorldPersistentData { + + @Nullable + public T b(Supplier supplier, String s) { +- PersistentBase persistentbase = (PersistentBase) this.data.get(s); ++ T persistentbase = (T) this.data.get(s); // Paper - decompile fix + + if (persistentbase == null && !this.data.containsKey(s)) { + persistentbase = this.c(supplier, s); +@@ -69,7 +69,7 @@ public class WorldPersistentData { + File file = this.a(s); + + if (file.exists()) { +- T t0 = (PersistentBase) supplier.get(); ++ T t0 = supplier.get(); // Paper - decompile fix + NBTTagCompound nbttagcompound = this.a(s, SharedConstants.getGameVersion().getWorldVersion()); + + t0.a(nbttagcompound.getCompound("data")); +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java +index 9421e175fffab7014461aa02e7e36d719837ec11..b6abbe9f1de66cd8e9d2e7127813ce56a0446faf 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java +@@ -43,7 +43,7 @@ public abstract class LootEntryAbstract implements LootEntryChildren { + + // CraftBukkit start + @Override +- public final void a(JsonObject jsonobject, T t0, JsonSerializationContext jsonserializationcontext) { ++ public void a(JsonObject jsonobject, T t0, JsonSerializationContext jsonserializationcontext) { // Paper - remove final + if (!org.apache.commons.lang3.ArrayUtils.isEmpty(t0.d)) { + jsonobject.add("conditions", jsonserializationcontext.serialize(t0.d)); + } +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java +index 0e3fe138fc11bd7e648296922c651cecaab8e71e..ceb9a1e1b1d55a0a8cd74189450f356b9ad4c46c 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java +@@ -132,7 +132,7 @@ public abstract class LootSelectorEntry extends LootEntryAbstract { + @Override + public T b(LootItemFunction.a lootitemfunction_a) { + this.c.add(lootitemfunction_a.b()); +- return (LootSelectorEntry.a) this.d(); ++ return this.d(); // Paper - decompile fix + } + + protected LootItemFunction[] a() { +@@ -141,12 +141,12 @@ public abstract class LootSelectorEntry extends LootEntryAbstract { + + public T a(int i) { + this.a = i; +- return (LootSelectorEntry.a) this.d(); ++ return this.d(); // Paper - decompile fix + } + + public T b(int i) { + this.b = i; +- return (LootSelectorEntry.a) this.d(); ++ return this.d(); // Paper - decompile fix + } + } + +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java +index f516e7440ed306b1ace9b35ae82f70ca69df51f3..38125a60bad4830db9de3580ab6d85fd122a0689 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java +@@ -89,7 +89,7 @@ public class LootItemFunctionExplorationMap extends LootItemFunctionConditional + public b() {} + + public void a(JsonObject jsonobject, LootItemFunctionExplorationMap lootitemfunctionexplorationmap, JsonSerializationContext jsonserializationcontext) { +- super.a(jsonobject, (LootItemFunctionConditional) lootitemfunctionexplorationmap, jsonserializationcontext); ++ super.a(jsonobject, lootitemfunctionexplorationmap, jsonserializationcontext); // Paper - decompile fix + if (!lootitemfunctionexplorationmap.e.equals(LootItemFunctionExplorationMap.a)) { + jsonobject.add("destination", jsonserializationcontext.serialize(lootitemfunctionexplorationmap.e.i())); + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java +index afd30320da51bf467d66e94f682936ed8db96d90..c58d380b96e81d65d7c254a9e53017e5157769b0 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java +@@ -38,7 +38,7 @@ public final class VoxelShapeMergerList implements VoxelShapeMerger { + double d1 = flag4 ? doublelist.getDouble(i++) : doublelist1.getDouble(j++); + + if ((i != 0 && flag2 || flag4 || flag1) && (j != 0 && flag3 || !flag4 || flag)) { +- if (d0 < d1 - 1.0E-7D) { ++ if (!(d0 >= d1 - 1.0E-7D)) { // Paper - decompile error - welcome to hell + this.b.add(i - 1); + this.c.add(j - 1); + this.a.add(d1); diff --git a/patches/server-unmapped/0004-MC-Utils.patch b/patches/server-unmapped/0004-MC-Utils.patch new file mode 100644 index 0000000000..fd72ff629d --- /dev/null +++ b/patches/server-unmapped/0004-MC-Utils.patch @@ -0,0 +1,4850 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 20:55:47 -0400 +Subject: [PATCH] MC Utils + + +diff --git a/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4029dc68cf35d63aa70c4a76c35bf65a7fc6358f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java +@@ -0,0 +1,68 @@ ++package com.destroystokyo.paper.util.concurrent; ++ ++import java.util.concurrent.atomic.AtomicLong; ++ ++/** ++ * copied from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/lock/WeakSeqLock.java ++ * @author Spottedleaf ++ */ ++public final class WeakSeqLock { ++ // TODO when the switch to J11 is made, nuke this class from orbit ++ ++ protected final AtomicLong lock = new AtomicLong(); ++ ++ public WeakSeqLock() { ++ //VarHandle.storeStoreFence(); // warn: usages must be checked to ensure this behaviour isn't needed ++ } ++ ++ public void acquireWrite() { ++ // must be release-type write ++ this.lock.lazySet(this.lock.get() + 1); ++ } ++ ++ public boolean canRead(final long read) { ++ return (read & 1) == 0; ++ } ++ ++ public boolean tryAcquireWrite() { ++ this.acquireWrite(); ++ return true; ++ } ++ ++ public void releaseWrite() { ++ // must be acquire-type write ++ final long lock = this.lock.get(); // volatile here acts as store-store ++ this.lock.lazySet(lock + 1); ++ } ++ ++ public void abortWrite() { ++ // must be acquire-type write ++ final long lock = this.lock.get(); // volatile here acts as store-store ++ this.lock.lazySet(lock ^ 1); ++ } ++ ++ public long acquireRead() { ++ int failures = 0; ++ long curr; ++ ++ for (curr = this.lock.get(); !this.canRead(curr); curr = this.lock.get()) { ++ // without j11, our only backoff is the yield() call... ++ ++ if (++failures > 5_000) { /* TODO determine a threshold */ ++ Thread.yield(); ++ } ++ /* Better waiting is beyond the scope of this lock; if it is needed the lock is being misused */ ++ } ++ ++ //VarHandle.loadLoadFence(); // volatile acts as the load-load barrier ++ return curr; ++ } ++ ++ public boolean tryReleaseRead(final long read) { ++ return this.lock.get() == read; // volatile acts as the load-load barrier ++ } ++ ++ public long getSequentialCounter() { ++ return this.lock.get(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java +new file mode 100644 +index 0000000000000000000000000000000000000000..59868f37d14bbc0ece0836095cdad148778995e6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java +@@ -0,0 +1,162 @@ ++package com.destroystokyo.paper.util.map; ++ ++import com.destroystokyo.paper.util.concurrent.WeakSeqLock; ++import it.unimi.dsi.fastutil.longs.Long2IntMap; ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; ++import it.unimi.dsi.fastutil.longs.LongIterator; ++import it.unimi.dsi.fastutil.longs.LongOpenHashSet; ++import it.unimi.dsi.fastutil.objects.ObjectIterator; ++ ++/** ++ * @author Spottedleaf ++ */ ++public class QueuedChangesMapLong2Int { ++ ++ protected final Long2IntOpenHashMap updatingMap; ++ protected final Long2IntOpenHashMap visibleMap; ++ protected final Long2IntOpenHashMap queuedPuts; ++ protected final LongOpenHashSet queuedRemove; ++ ++ protected int queuedDefaultReturnValue; ++ ++ // we use a seqlock as writes are not common. ++ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); ++ ++ public QueuedChangesMapLong2Int() { ++ this(16, 0.75f); ++ } ++ ++ public QueuedChangesMapLong2Int(final int capacity, final float loadFactor) { ++ this.updatingMap = new Long2IntOpenHashMap(capacity, loadFactor); ++ this.visibleMap = new Long2IntOpenHashMap(capacity, loadFactor); ++ this.queuedPuts = new Long2IntOpenHashMap(); ++ this.queuedRemove = new LongOpenHashSet(); ++ } ++ ++ public void queueDefaultReturnValue(final int dfl) { ++ this.queuedDefaultReturnValue = dfl; ++ this.updatingMap.defaultReturnValue(dfl); ++ } ++ ++ public int queueUpdate(final long k, final int v) { ++ this.queuedRemove.remove(k); ++ this.queuedPuts.put(k, v); ++ ++ return this.updatingMap.put(k, v); ++ } ++ ++ public int queueRemove(final long k) { ++ this.queuedPuts.remove(k); ++ this.queuedRemove.add(k); ++ ++ return this.updatingMap.remove(k); ++ } ++ ++ public int getUpdating(final long k) { ++ return this.updatingMap.get(k); ++ } ++ ++ public int getVisible(final long k) { ++ return this.visibleMap.get(k); ++ } ++ ++ public int getVisibleAsync(final long k) { ++ long readlock; ++ int ret = 0; ++ ++ do { ++ readlock = this.updatingMapSeqLock.acquireRead(); ++ try { ++ ret = this.visibleMap.get(k); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ // ignore... ++ continue; ++ } ++ ++ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ ++ public boolean performUpdates() { ++ this.updatingMapSeqLock.acquireWrite(); ++ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); ++ this.updatingMapSeqLock.releaseWrite(); ++ ++ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { ++ return false; ++ } ++ ++ // update puts ++ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); ++ while (iterator0.hasNext()) { ++ final Long2IntMap.Entry entry = iterator0.next(); ++ final long key = entry.getLongKey(); ++ final int val = entry.getIntValue(); ++ ++ this.updatingMapSeqLock.acquireWrite(); ++ try { ++ this.visibleMap.put(key, val); ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ } ++ ++ this.queuedPuts.clear(); ++ ++ final LongIterator iterator1 = this.queuedRemove.iterator(); ++ while (iterator1.hasNext()) { ++ final long key = iterator1.nextLong(); ++ ++ this.updatingMapSeqLock.acquireWrite(); ++ try { ++ this.visibleMap.remove(key); ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ } ++ ++ this.queuedRemove.clear(); ++ ++ return true; ++ } ++ ++ public boolean performUpdatesLockMap() { ++ this.updatingMapSeqLock.acquireWrite(); ++ try { ++ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); ++ ++ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { ++ return false; ++ } ++ ++ // update puts ++ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); ++ while (iterator0.hasNext()) { ++ final Long2IntMap.Entry entry = iterator0.next(); ++ final long key = entry.getLongKey(); ++ final int val = entry.getIntValue(); ++ ++ this.visibleMap.put(key, val); ++ } ++ ++ this.queuedPuts.clear(); ++ ++ final LongIterator iterator1 = this.queuedRemove.iterator(); ++ while (iterator1.hasNext()) { ++ final long key = iterator1.nextLong(); ++ ++ this.visibleMap.remove(key); ++ } ++ ++ this.queuedRemove.clear(); ++ ++ return true; ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7bab31a312463cc963d9621cdc543a281459bd32 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java +@@ -0,0 +1,202 @@ ++package com.destroystokyo.paper.util.map; ++ ++import com.destroystokyo.paper.util.concurrent.WeakSeqLock; ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectMap; ++import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator; ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.List; ++ ++/** ++ * @author Spottedleaf ++ */ ++public class QueuedChangesMapLong2Object { ++ ++ protected static final Object REMOVED = new Object(); ++ ++ protected final Long2ObjectLinkedOpenHashMap updatingMap; ++ protected final Long2ObjectLinkedOpenHashMap visibleMap; ++ protected final Long2ObjectLinkedOpenHashMap queuedChanges; ++ ++ // we use a seqlock as writes are not common. ++ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); ++ ++ public QueuedChangesMapLong2Object() { ++ this(16, 0.75f); // dfl for fastutil ++ } ++ ++ public QueuedChangesMapLong2Object(final int capacity, final float loadFactor) { ++ this.updatingMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); ++ this.visibleMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); ++ this.queuedChanges = new Long2ObjectLinkedOpenHashMap<>(); ++ } ++ ++ public V queueUpdate(final long k, final V value) { ++ this.queuedChanges.put(k, value); ++ return this.updatingMap.put(k, value); ++ } ++ ++ public V queueRemove(final long k) { ++ this.queuedChanges.put(k, REMOVED); ++ return this.updatingMap.remove(k); ++ } ++ ++ public V getUpdating(final long k) { ++ return this.updatingMap.get(k); ++ } ++ ++ public boolean updatingContainsKey(final long k) { ++ return this.updatingMap.containsKey(k); ++ } ++ ++ public V getVisible(final long k) { ++ return this.visibleMap.get(k); ++ } ++ ++ public boolean visibleContainsKey(final long k) { ++ return this.visibleMap.containsKey(k); ++ } ++ ++ public V getVisibleAsync(final long k) { ++ long readlock; ++ V ret = null; ++ ++ do { ++ readlock = this.updatingMapSeqLock.acquireRead(); ++ ++ try { ++ ret = this.visibleMap.get(k); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ // ignore... ++ continue; ++ } ++ ++ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ ++ public boolean visibleContainsKeyAsync(final long k) { ++ long readlock; ++ boolean ret = false; ++ ++ do { ++ readlock = this.updatingMapSeqLock.acquireRead(); ++ ++ try { ++ ret = this.visibleMap.containsKey(k); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ // ignore... ++ continue; ++ } ++ ++ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ ++ public Long2ObjectLinkedOpenHashMap getVisibleMap() { ++ return this.visibleMap; ++ } ++ ++ public Long2ObjectLinkedOpenHashMap getUpdatingMap() { ++ return this.updatingMap; ++ } ++ ++ public int getVisibleSize() { ++ return this.visibleMap.size(); ++ } ++ ++ public int getVisibleSizeAsync() { ++ long readlock; ++ int ret; ++ ++ do { ++ readlock = this.updatingMapSeqLock.acquireRead(); ++ ret = this.visibleMap.size(); ++ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ ++ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map ++ public Collection getUpdatingValues() { ++ return this.updatingMap.values(); ++ } ++ ++ public List getUpdatingValuesCopy() { ++ return new ArrayList<>(this.updatingMap.values()); ++ } ++ ++ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map ++ public Collection getVisibleValues() { ++ return this.visibleMap.values(); ++ } ++ ++ public List getVisibleValuesCopy() { ++ return new ArrayList<>(this.visibleMap.values()); ++ } ++ ++ public boolean performUpdates() { ++ if (this.queuedChanges.isEmpty()) { ++ return false; ++ } ++ ++ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); ++ while (iterator.hasNext()) { ++ final Long2ObjectMap.Entry entry = iterator.next(); ++ final long key = entry.getLongKey(); ++ final Object val = entry.getValue(); ++ ++ this.updatingMapSeqLock.acquireWrite(); ++ try { ++ if (val == REMOVED) { ++ this.visibleMap.remove(key); ++ } else { ++ this.visibleMap.put(key, (V)val); ++ } ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ } ++ ++ this.queuedChanges.clear(); ++ return true; ++ } ++ ++ public boolean performUpdatesLockMap() { ++ if (this.queuedChanges.isEmpty()) { ++ return false; ++ } ++ ++ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); ++ ++ try { ++ this.updatingMapSeqLock.acquireWrite(); ++ ++ while (iterator.hasNext()) { ++ final Long2ObjectMap.Entry entry = iterator.next(); ++ final long key = entry.getLongKey(); ++ final Object val = entry.getValue(); ++ ++ if (val == REMOVED) { ++ this.visibleMap.remove(key); ++ } else { ++ this.visibleMap.put(key, (V)val); ++ } ++ } ++ } finally { ++ this.updatingMapSeqLock.releaseWrite(); ++ } ++ ++ this.queuedChanges.clear(); ++ return true; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bf63a0e87f8c9529e473269c0626051c81bb04ea +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java +@@ -0,0 +1,128 @@ ++package com.destroystokyo.paper.util.maplist; ++ ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; ++import net.minecraft.world.level.chunk.Chunk; ++import java.util.Arrays; ++import java.util.Iterator; ++import java.util.NoSuchElementException; ++ ++// list with O(1) remove & contains ++/** ++ * @author Spottedleaf ++ */ ++public final class ChunkList implements Iterable { ++ ++ protected final Long2IntOpenHashMap chunkToIndex = new Long2IntOpenHashMap(2, 0.8f); ++ { ++ this.chunkToIndex.defaultReturnValue(Integer.MIN_VALUE); ++ } ++ ++ protected static final Chunk[] EMPTY_LIST = new Chunk[0]; ++ ++ protected Chunk[] chunks = EMPTY_LIST; ++ protected int count; ++ ++ public int size() { ++ return this.count; ++ } ++ ++ public boolean contains(final Chunk chunk) { ++ return this.chunkToIndex.containsKey(chunk.coordinateKey); ++ } ++ ++ public boolean remove(final Chunk chunk) { ++ final int index = this.chunkToIndex.remove(chunk.coordinateKey); ++ if (index == Integer.MIN_VALUE) { ++ return false; ++ } ++ ++ // move the entity at the end to this index ++ final int endIndex = --this.count; ++ final Chunk end = this.chunks[endIndex]; ++ if (index != endIndex) { ++ // not empty after this call ++ this.chunkToIndex.put(end.coordinateKey, index); // update index ++ } ++ this.chunks[index] = end; ++ this.chunks[endIndex] = null; ++ ++ return true; ++ } ++ ++ public boolean add(final Chunk chunk) { ++ final int count = this.count; ++ final int currIndex = this.chunkToIndex.putIfAbsent(chunk.coordinateKey, count); ++ ++ if (currIndex != Integer.MIN_VALUE) { ++ return false; // already in this list ++ } ++ ++ Chunk[] list = this.chunks; ++ ++ if (list.length == count) { ++ // resize required ++ list = this.chunks = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative ++ } ++ ++ list[count] = chunk; ++ this.count = count + 1; ++ ++ return true; ++ } ++ ++ public Chunk getChecked(final int index) { ++ if (index < 0 || index >= this.count) { ++ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); ++ } ++ return this.chunks[index]; ++ } ++ ++ public Chunk getUnchecked(final int index) { ++ return this.chunks[index]; ++ } ++ ++ public Chunk[] getRawData() { ++ return this.chunks; ++ } ++ ++ public void clear() { ++ this.chunkToIndex.clear(); ++ Arrays.fill(this.chunks, 0, this.count, null); ++ this.count = 0; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return new Iterator() { ++ ++ Chunk lastRet; ++ int current; ++ ++ @Override ++ public boolean hasNext() { ++ return this.current < ChunkList.this.count; ++ } ++ ++ @Override ++ public Chunk next() { ++ if (this.current >= ChunkList.this.count) { ++ throw new NoSuchElementException(); ++ } ++ return this.lastRet = ChunkList.this.chunks[this.current++]; ++ } ++ ++ @Override ++ public void remove() { ++ final Chunk lastRet = this.lastRet; ++ ++ if (lastRet == null) { ++ throw new IllegalStateException(); ++ } ++ this.lastRet = null; ++ ++ ChunkList.this.remove(lastRet); ++ --this.current; ++ } ++ }; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0133ea6feb1ab88f021f66855669f58367e7420b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java +@@ -0,0 +1,128 @@ ++package com.destroystokyo.paper.util.maplist; ++ ++import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; ++import net.minecraft.world.entity.Entity; ++import java.util.Arrays; ++import java.util.Iterator; ++import java.util.NoSuchElementException; ++ ++// list with O(1) remove & contains ++/** ++ * @author Spottedleaf ++ */ ++public final class EntityList implements Iterable { ++ ++ protected final Int2IntOpenHashMap entityToIndex = new Int2IntOpenHashMap(2, 0.8f); ++ { ++ this.entityToIndex.defaultReturnValue(Integer.MIN_VALUE); ++ } ++ ++ protected static final Entity[] EMPTY_LIST = new Entity[0]; ++ ++ protected Entity[] entities = EMPTY_LIST; ++ protected int count; ++ ++ public int size() { ++ return this.count; ++ } ++ ++ public boolean contains(final Entity entity) { ++ return this.entityToIndex.containsKey(entity.getId()); ++ } ++ ++ public boolean remove(final Entity entity) { ++ final int index = this.entityToIndex.remove(entity.getId()); ++ if (index == Integer.MIN_VALUE) { ++ return false; ++ } ++ ++ // move the entity at the end to this index ++ final int endIndex = --this.count; ++ final Entity end = this.entities[endIndex]; ++ if (index != endIndex) { ++ // not empty after this call ++ this.entityToIndex.put(end.getId(), index); // update index ++ } ++ this.entities[index] = end; ++ this.entities[endIndex] = null; ++ ++ return true; ++ } ++ ++ public boolean add(final Entity entity) { ++ final int count = this.count; ++ final int currIndex = this.entityToIndex.putIfAbsent(entity.getId(), count); ++ ++ if (currIndex != Integer.MIN_VALUE) { ++ return false; // already in this list ++ } ++ ++ Entity[] list = this.entities; ++ ++ if (list.length == count) { ++ // resize required ++ list = this.entities = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative ++ } ++ ++ list[count] = entity; ++ this.count = count + 1; ++ ++ return true; ++ } ++ ++ public Entity getChecked(final int index) { ++ if (index < 0 || index >= this.count) { ++ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); ++ } ++ return this.entities[index]; ++ } ++ ++ public Entity getUnchecked(final int index) { ++ return this.entities[index]; ++ } ++ ++ public Entity[] getRawData() { ++ return this.entities; ++ } ++ ++ public void clear() { ++ this.entityToIndex.clear(); ++ Arrays.fill(this.entities, 0, this.count, null); ++ this.count = 0; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return new Iterator() { ++ ++ Entity lastRet; ++ int current; ++ ++ @Override ++ public boolean hasNext() { ++ return this.current < EntityList.this.count; ++ } ++ ++ @Override ++ public Entity next() { ++ if (this.current >= EntityList.this.count) { ++ throw new NoSuchElementException(); ++ } ++ return this.lastRet = EntityList.this.entities[this.current++]; ++ } ++ ++ @Override ++ public void remove() { ++ final Entity lastRet = this.lastRet; ++ ++ if (lastRet == null) { ++ throw new IllegalStateException(); ++ } ++ this.lastRet = null; ++ ++ EntityList.this.remove(lastRet); ++ --this.current; ++ } ++ }; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d9fdc8196e53518ceac3aeb7bf3b98a0bd348f8f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java +@@ -0,0 +1,128 @@ ++package com.destroystokyo.paper.util.maplist; ++ ++import it.unimi.dsi.fastutil.longs.LongIterator; ++import it.unimi.dsi.fastutil.shorts.Short2LongOpenHashMap; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.chunk.ChunkSection; ++import net.minecraft.world.level.chunk.DataPaletteGlobal; ++import java.util.Arrays; ++ ++/** ++ * @author Spottedleaf ++ */ ++public final class IBlockDataList { ++ ++ static final DataPaletteGlobal GLOBAL_PALETTE = (DataPaletteGlobal) ChunkSection.GLOBAL_PALETTE; ++ ++ // map of location -> (index | (location << 16) | (palette id << 32)) ++ private final Short2LongOpenHashMap map = new Short2LongOpenHashMap(2, 0.8f); ++ { ++ this.map.defaultReturnValue(Long.MAX_VALUE); ++ } ++ ++ private static final long[] EMPTY_LIST = new long[0]; ++ ++ private long[] byIndex = EMPTY_LIST; ++ private int size; ++ ++ public static int getLocationKey(final int x, final int y, final int z) { ++ return (x & 15) | (((z & 15) << 4)) | ((y & 255) << (4 + 4)); ++ } ++ ++ public static IBlockData getBlockDataFromRaw(final long raw) { ++ return GLOBAL_PALETTE.getObject((int)(raw >>> 32)); ++ } ++ ++ public static int getIndexFromRaw(final long raw) { ++ return (int)(raw & 0xFFFF); ++ } ++ ++ public static int getLocationFromRaw(final long raw) { ++ return (int)((raw >>> 16) & 0xFFFF); ++ } ++ ++ public static long getRawFromValues(final int index, final int location, final IBlockData data) { ++ return (long)index | ((long)location << 16) | (((long)GLOBAL_PALETTE.getOrCreateIdFor(data)) << 32); ++ } ++ ++ public static long setIndexRawValues(final long value, final int index) { ++ return value & ~(0xFFFF) | (index); ++ } ++ ++ public long add(final int x, final int y, final int z, final IBlockData data) { ++ return this.add(getLocationKey(x, y, z), data); ++ } ++ ++ public long add(final int location, final IBlockData data) { ++ final long curr = this.map.get((short)location); ++ ++ if (curr == Long.MAX_VALUE) { ++ final int index = this.size++; ++ final long raw = getRawFromValues(index, location, data); ++ this.map.put((short)location, raw); ++ ++ if (index >= this.byIndex.length) { ++ this.byIndex = Arrays.copyOf(this.byIndex, (int)Math.max(4L, this.byIndex.length * 2L)); ++ } ++ ++ this.byIndex[index] = raw; ++ return raw; ++ } else { ++ final int index = getIndexFromRaw(curr); ++ final long raw = this.byIndex[index] = getRawFromValues(index, location, data); ++ ++ this.map.put((short)location, raw); ++ ++ return raw; ++ } ++ } ++ ++ public long remove(final int x, final int y, final int z) { ++ return this.remove(getLocationKey(x, y, z)); ++ } ++ ++ public long remove(final int location) { ++ final long ret = this.map.remove((short)location); ++ final int index = getIndexFromRaw(ret); ++ if (ret == Long.MAX_VALUE) { ++ return ret; ++ } ++ ++ // move the entry at the end to this index ++ final int endIndex = --this.size; ++ final long end = this.byIndex[endIndex]; ++ if (index != endIndex) { ++ // not empty after this call ++ this.map.put((short)getLocationFromRaw(end), setIndexRawValues(end, index)); ++ } ++ this.byIndex[index] = end; ++ this.byIndex[endIndex] = 0L; ++ ++ return ret; ++ } ++ ++ public int size() { ++ return this.size; ++ } ++ ++ public long getRaw(final int index) { ++ return this.byIndex[index]; ++ } ++ ++ public int getLocation(final int index) { ++ return getLocationFromRaw(this.getRaw(index)); ++ } ++ ++ public IBlockData getData(final int index) { ++ return getBlockDataFromRaw(this.getRaw(index)); ++ } ++ ++ public void clear() { ++ this.size = 0; ++ this.map.clear(); ++ } ++ ++ public LongIterator getRawIterator() { ++ return this.map.values().iterator(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c3b936f54b3fff418c265639ef223292ccc89356 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java +@@ -0,0 +1,230 @@ ++package com.destroystokyo.paper.util.math; ++ ++/** ++ * @author Spottedleaf ++ */ ++public final class IntegerUtil { ++ ++ public static final int HIGH_BIT_U32 = Integer.MIN_VALUE; ++ public static final long HIGH_BIT_U64 = Long.MIN_VALUE; ++ ++ public static int ceilLog2(final int value) { ++ return Integer.SIZE - Integer.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros ++ } ++ ++ public static long ceilLog2(final long value) { ++ return Long.SIZE - Long.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros ++ } ++ ++ public static int floorLog2(final int value) { ++ // xor is optimized subtract for 2^n -1 ++ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) ++ return (Integer.SIZE - 1) ^ Integer.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros ++ } ++ ++ public static int floorLog2(final long value) { ++ // xor is optimized subtract for 2^n -1 ++ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) ++ return (Long.SIZE - 1) ^ Long.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros ++ } ++ ++ public static int roundCeilLog2(final int value) { ++ // optimized variant of 1 << (32 - leading(val - 1)) ++ // given ++ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) ++ // 1 << (32 - leading(val - 1)) = HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) ++ // HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) ++ // HIGH_BIT_32 >>> (31 - 32 + leading(val - 1)) ++ // HIGH_BIT_32 >>> (-1 + leading(val - 1)) ++ return HIGH_BIT_U32 >>> (Integer.numberOfLeadingZeros(value - 1) - 1); ++ } ++ ++ public static long roundCeilLog2(final long value) { ++ // see logic documented above ++ return HIGH_BIT_U64 >>> (Long.numberOfLeadingZeros(value - 1) - 1); ++ } ++ ++ public static int roundFloorLog2(final int value) { ++ // optimized variant of 1 << (31 - leading(val)) ++ // given ++ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) ++ // 1 << (31 - leading(val)) = HIGH_BIT_32 >> (31 - (31 - leading(val))) ++ // HIGH_BIT_32 >> (31 - (31 - leading(val))) ++ // HIGH_BIT_32 >> (31 - 31 + leading(val)) ++ return HIGH_BIT_U32 >>> Integer.numberOfLeadingZeros(value); ++ } ++ ++ public static long roundFloorLog2(final long value) { ++ // see logic documented above ++ return HIGH_BIT_U64 >>> Long.numberOfLeadingZeros(value); ++ } ++ ++ public static boolean isPowerOfTwo(final int n) { ++ // 2^n has one bit ++ // note: this rets true for 0 still ++ return IntegerUtil.getTrailingBit(n) == n; ++ } ++ ++ public static boolean isPowerOfTwo(final long n) { ++ // 2^n has one bit ++ // note: this rets true for 0 still ++ return IntegerUtil.getTrailingBit(n) == n; ++ } ++ ++ ++ public static int getTrailingBit(final int n) { ++ return -n & n; ++ } ++ ++ public static long getTrailingBit(final long n) { ++ return -n & n; ++ } ++ ++ public static int trailingZeros(final int n) { ++ return Integer.numberOfTrailingZeros(n); ++ } ++ ++ public static long trailingZeros(final long n) { ++ return Long.numberOfTrailingZeros(n); ++ } ++ ++ // from hacker's delight (signed division magic value) ++ public static int getDivisorMultiple(final long numbers) { ++ return (int)(numbers >>> 32); ++ } ++ ++ // from hacker's delight (signed division magic value) ++ public static int getDivisorShift(final long numbers) { ++ return (int)numbers; ++ } ++ ++ // copied from hacker's delight (signed division magic value) ++ // http://www.hackersdelight.org/hdcodetxt/magic.c.txt ++ public static long getDivisorNumbers(final int d) { ++ final int ad = IntegerUtil.branchlessAbs(d); ++ ++ if (ad < 2) { ++ throw new IllegalArgumentException("|number| must be in [2, 2^31 -1], not: " + d); ++ } ++ ++ final int two31 = 0x80000000; ++ final long mask = 0xFFFFFFFFL; // mask for enforcing unsigned behaviour ++ ++ int p = 31; ++ ++ // all these variables are UNSIGNED! ++ int t = two31 + (d >>> 31); ++ int anc = t - 1 - t%ad; ++ int q1 = (int)((two31 & mask)/(anc & mask)); ++ int r1 = two31 - q1*anc; ++ int q2 = (int)((two31 & mask)/(ad & mask)); ++ int r2 = two31 - q2*ad; ++ int delta; ++ ++ do { ++ p = p + 1; ++ q1 = 2*q1; // Update q1 = 2**p/|nc|. ++ r1 = 2*r1; // Update r1 = rem(2**p, |nc|). ++ if ((r1 & mask) >= (anc & mask)) {// (Must be an unsigned comparison here) ++ q1 = q1 + 1; ++ r1 = r1 - anc; ++ } ++ q2 = 2*q2; // Update q2 = 2**p/|d|. ++ r2 = 2*r2; // Update r2 = rem(2**p, |d|). ++ if ((r2 & mask) >= (ad & mask)) {// (Must be an unsigned comparison here) ++ q2 = q2 + 1; ++ r2 = r2 - ad; ++ } ++ delta = ad - r2; ++ } while ((q1 & mask) < (delta & mask) || (q1 == delta && r1 == 0)); ++ ++ int magicNum = q2 + 1; ++ if (d < 0) { ++ magicNum = -magicNum; ++ } ++ int shift = p - 32; ++ return ((long)magicNum << 32) | shift; ++ } ++ ++ public static int branchlessAbs(final int val) { ++ // -n = -1 ^ n + 1 ++ final int mask = val >> (Integer.SIZE - 1); // -1 if < 0, 0 if >= 0 ++ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 ++ } ++ ++ public static long branchlessAbs(final long val) { ++ // -n = -1 ^ n + 1 ++ final long mask = val >> (Long.SIZE - 1); // -1 if < 0, 0 if >= 0 ++ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 ++ } ++ ++ //https://github.com/skeeto/hash-prospector for hash functions ++ ++ //score = ~590.47984224483832 ++ public static int hash0(int x) { ++ x *= 0x36935555; ++ x ^= x >>> 16; ++ return x; ++ } ++ ++ //score = ~310.01596637036749 ++ public static int hash1(int x) { ++ x ^= x >>> 15; ++ x *= 0x356aaaad; ++ x ^= x >>> 17; ++ return x; ++ } ++ ++ public static int hash2(int x) { ++ x ^= x >>> 16; ++ x *= 0x7feb352d; ++ x ^= x >>> 15; ++ x *= 0x846ca68b; ++ x ^= x >>> 16; ++ return x; ++ } ++ ++ public static int hash3(int x) { ++ x ^= x >>> 17; ++ x *= 0xed5ad4bb; ++ x ^= x >>> 11; ++ x *= 0xac4c1b51; ++ x ^= x >>> 15; ++ x *= 0x31848bab; ++ x ^= x >>> 14; ++ return x; ++ } ++ ++ //score = ~365.79959673201887 ++ public static long hash1(long x) { ++ x ^= x >>> 27; ++ x *= 0xb24924b71d2d354bL; ++ x ^= x >>> 28; ++ return x; ++ } ++ ++ //h2 hash ++ public static long hash2(long x) { ++ x ^= x >>> 32; ++ x *= 0xd6e8feb86659fd93L; ++ x ^= x >>> 32; ++ x *= 0xd6e8feb86659fd93L; ++ x ^= x >>> 32; ++ return x; ++ } ++ ++ public static long hash3(long x) { ++ x ^= x >>> 45; ++ x *= 0xc161abe5704b6c79L; ++ x ^= x >>> 41; ++ x *= 0xe3e5389aedbc90f7L; ++ x ^= x >>> 56; ++ x *= 0x1f9aba75a52db073L; ++ x ^= x >>> 53; ++ return x; ++ } ++ ++ private IntegerUtil() { ++ throw new RuntimeException(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..24407a3e653ba32ef6b921c346571ec734a72245 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java +@@ -0,0 +1,453 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import com.destroystokyo.paper.util.math.IntegerUtil; ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import javax.annotation.Nullable; ++import java.util.Iterator; ++ ++/** @author Spottedleaf */ ++public abstract class AreaMap { ++ ++ /* Tested via https://gist.github.com/Spottedleaf/520419c6f41ef348fe9926ce674b7217 */ ++ ++ protected final Object2LongOpenHashMap objectToLastCoordinate = new Object2LongOpenHashMap<>(); ++ protected final Object2IntOpenHashMap objectToViewDistance = new Object2IntOpenHashMap<>(); ++ ++ { ++ this.objectToViewDistance.defaultReturnValue(-1); ++ this.objectToLastCoordinate.defaultReturnValue(Long.MIN_VALUE); ++ } ++ ++ // we use linked for better iteration. ++ // map of: coordinate to set of objects in coordinate ++ protected final Long2ObjectOpenHashMap> areaMap = new Long2ObjectOpenHashMap<>(1024, 0.7f); ++ protected final PooledLinkedHashSets pooledHashSets; ++ ++ protected final ChangeCallback addCallback; ++ protected final ChangeCallback removeCallback; ++ protected final ChangeSourceCallback changeSourceCallback; ++ ++ public AreaMap() { ++ this(new PooledLinkedHashSets<>()); ++ } ++ ++ // let users define a "global" or "shared" pooled sets if they wish ++ public AreaMap(final PooledLinkedHashSets pooledHashSets) { ++ this(pooledHashSets, null, null); ++ } ++ ++ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback) { ++ this(pooledHashSets, addCallback, removeCallback, null); ++ } ++ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { ++ this.pooledHashSets = pooledHashSets; ++ this.addCallback = addCallback; ++ this.removeCallback = removeCallback; ++ this.changeSourceCallback = changeSourceCallback; ++ } ++ ++ @Nullable ++ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final long key) { ++ return this.areaMap.get(key); ++ } ++ ++ @Nullable ++ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final ChunkCoordIntPair chunkPos) { ++ return this.areaMap.get(MCUtil.getCoordinateKey(chunkPos)); ++ } ++ ++ @Nullable ++ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final int chunkX, final int chunkZ) { ++ return this.areaMap.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); ++ } ++ ++ // Long.MIN_VALUE indicates the object is not mapped ++ public final long getLastCoordinate(final E object) { ++ return this.objectToLastCoordinate.getOrDefault(object, Long.MIN_VALUE); ++ } ++ ++ // -1 indicates the object is not mapped ++ public final int getLastViewDistance(final E object) { ++ return this.objectToViewDistance.getOrDefault(object, -1); ++ } ++ ++ // returns the total number of mapped chunks ++ public final int size() { ++ return this.areaMap.size(); ++ } ++ ++ public final void addOrUpdate(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int oldViewDistance = this.objectToViewDistance.put(object, viewDistance); ++ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final long oldPos = this.objectToLastCoordinate.put(object, newPos); ++ ++ if (oldViewDistance == -1) { ++ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); ++ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); ++ } else { ++ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); ++ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); ++ } ++ //this.validate(object, viewDistance); ++ } ++ ++ public final boolean update(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int oldViewDistance = this.objectToViewDistance.replace(object, viewDistance); ++ if (oldViewDistance == -1) { ++ return false; ++ } else { ++ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final long oldPos = this.objectToLastCoordinate.put(object, newPos); ++ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); ++ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); ++ } ++ //this.validate(object, viewDistance); ++ return true; ++ } ++ ++ // called after the distance map updates ++ protected void updateObjectCallback(final E Object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { ++ if (newPosition != oldPosition && this.changeSourceCallback != null) { ++ this.changeSourceCallback.accept(Object, oldPosition, newPosition); ++ } ++ } ++ ++ public final boolean add(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int oldViewDistance = this.objectToViewDistance.putIfAbsent(object, viewDistance); ++ if (oldViewDistance != -1) { ++ return false; ++ } ++ ++ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ this.objectToLastCoordinate.put(object, newPos); ++ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); ++ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); ++ ++ //this.validate(object, viewDistance); ++ ++ return true; ++ } ++ ++ // called after the distance map updates ++ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} ++ ++ public final boolean remove(final E object) { ++ final long position = this.objectToLastCoordinate.removeLong(object); ++ final int viewDistance = this.objectToViewDistance.removeInt(object); ++ ++ if (viewDistance == -1) { ++ return false; ++ } ++ ++ final int currentX = MCUtil.getCoordinateX(position); ++ final int currentZ = MCUtil.getCoordinateZ(position); ++ ++ this.removeObject(object, currentX, currentZ, currentX, currentZ, viewDistance); ++ this.removeObjectCallback(object, currentX, currentZ, viewDistance); ++ //this.validate(object, -1); ++ return true; ++ } ++ ++ // called after the distance map updates ++ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} ++ ++ protected abstract PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final E object); ++ ++ // expensive op, only for debug ++ protected void validate(final E object, final int viewDistance) { ++ int entiesGot = 0; ++ int expectedEntries = (2 * viewDistance + 1); ++ expectedEntries *= expectedEntries; ++ if (viewDistance < 0) { ++ expectedEntries = 0; ++ } ++ ++ final long currPosition = this.objectToLastCoordinate.getLong(object); ++ ++ final int centerX = MCUtil.getCoordinateX(currPosition); ++ final int centerZ = MCUtil.getCoordinateZ(currPosition); ++ ++ for (Iterator>> iterator = this.areaMap.long2ObjectEntrySet().fastIterator(); ++ iterator.hasNext();) { ++ ++ final Long2ObjectLinkedOpenHashMap.Entry> entry = iterator.next(); ++ final long key = entry.getLongKey(); ++ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); ++ ++ if (map.referenceCount == 0) { ++ throw new IllegalStateException("Invalid map"); ++ } ++ ++ if (map.contains(object)) { ++ ++entiesGot; ++ ++ final int chunkX = MCUtil.getCoordinateX(key); ++ final int chunkZ = MCUtil.getCoordinateZ(key); ++ ++ final int dist = Math.max(IntegerUtil.branchlessAbs(chunkX - centerX), IntegerUtil.branchlessAbs(chunkZ - centerZ)); ++ ++ if (dist > viewDistance) { ++ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); ++ } ++ } ++ } ++ ++ if (entiesGot != expectedEntries) { ++ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); ++ } ++ } ++ ++ private void addObjectTo(final E object, final int chunkX, final int chunkZ, final int currChunkX, ++ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { ++ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet empty = this.getEmptySetFor(object); ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.putIfAbsent(key, empty); ++ ++ if (current != null) { ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWith(current, object); ++ if (next == current) { ++ throw new IllegalStateException("Expected different map: got " + next.toString()); ++ } ++ this.areaMap.put(key, next); ++ ++ current = next; ++ // fall through to callback ++ } else { ++ current = empty; ++ } ++ ++ if (this.addCallback != null) { ++ try { ++ this.addCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, current); ++ } catch (final Throwable ex) { ++ if (ex instanceof ThreadDeath) { ++ throw (ThreadDeath)ex; ++ } ++ MinecraftServer.LOGGER.error("Add callback for map threw exception ", ex); ++ } ++ } ++ } ++ ++ private void removeObjectFrom(final E object, final int chunkX, final int chunkZ, final int currChunkX, ++ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { ++ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.get(key); ++ ++ if (current == null) { ++ throw new IllegalStateException("Current map may not be null for " + object + ", (" + chunkX + "," + chunkZ + ")"); ++ } ++ ++ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWithout(current, object); ++ ++ if (next == current) { ++ throw new IllegalStateException("Current map [" + next.toString() + "] should have contained " + object + ", (" + chunkX + "," + chunkZ + ")"); ++ } ++ ++ if (next != null) { ++ this.areaMap.put(key, next); ++ } else { ++ this.areaMap.remove(key); ++ } ++ ++ if (this.removeCallback != null) { ++ try { ++ this.removeCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, next); ++ } catch (final Throwable ex) { ++ if (ex instanceof ThreadDeath) { ++ throw (ThreadDeath)ex; ++ } ++ MinecraftServer.LOGGER.error("Remove callback for map threw exception ", ex); ++ } ++ } ++ } ++ ++ private void addObject(final E object, final int chunkX, final int chunkZ, final int prevChunkX, final int prevChunkZ, final int viewDistance) { ++ final int maxX = chunkX + viewDistance; ++ final int maxZ = chunkZ + viewDistance; ++ final int minX = chunkX - viewDistance; ++ final int minZ = chunkZ - viewDistance; ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ this.addObjectTo(object, x, z, chunkX, chunkZ, prevChunkX, prevChunkZ); ++ } ++ } ++ } ++ ++ private void removeObject(final E object, final int chunkX, final int chunkZ, final int currentChunkX, final int currentChunkZ, final int viewDistance) { ++ final int maxX = chunkX + viewDistance; ++ final int maxZ = chunkZ + viewDistance; ++ final int minX = chunkX - viewDistance; ++ final int minZ = chunkZ - viewDistance; ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ this.removeObjectFrom(object, x, z, currentChunkX, currentChunkZ, chunkX, chunkZ); ++ } ++ } ++ } ++ ++ /* math sign function except 0 returns 1 */ ++ protected static int sign(int val) { ++ return 1 | (val >> (Integer.SIZE - 1)); ++ } ++ ++ private void updateObject(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { ++ final int toX = MCUtil.getCoordinateX(newPosition); ++ final int toZ = MCUtil.getCoordinateZ(newPosition); ++ final int fromX = MCUtil.getCoordinateX(oldPosition); ++ final int fromZ = MCUtil.getCoordinateZ(oldPosition); ++ ++ final int dx = toX - fromX; ++ final int dz = toZ - fromZ; ++ ++ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); ++ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); ++ ++ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { ++ // teleported? ++ this.removeObject(object, fromX, fromZ, fromX, fromZ, oldViewDistance); ++ this.addObject(object, toX, toZ, fromX, fromZ, newViewDistance); ++ return; ++ } ++ ++ if (oldViewDistance != newViewDistance) { ++ // remove loop ++ ++ final int oldMinX = fromX - oldViewDistance; ++ final int oldMinZ = fromZ - oldViewDistance; ++ final int oldMaxX = fromX + oldViewDistance; ++ final int oldMaxZ = fromZ + oldViewDistance; ++ for (int currX = oldMinX; currX <= oldMaxX; ++currX) { ++ for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) { ++ ++ // only remove if we're outside the new view distance... ++ if (Math.max(IntegerUtil.branchlessAbs(currX - toX), IntegerUtil.branchlessAbs(currZ - toZ)) > newViewDistance) { ++ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ // add loop ++ ++ final int newMinX = toX - newViewDistance; ++ final int newMinZ = toZ - newViewDistance; ++ final int newMaxX = toX + newViewDistance; ++ final int newMaxZ = toZ + newViewDistance; ++ for (int currX = newMinX; currX <= newMaxX; ++currX) { ++ for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) { ++ ++ // only add if we're outside the old view distance... ++ if (Math.max(IntegerUtil.branchlessAbs(currX - fromX), IntegerUtil.branchlessAbs(currZ - fromZ)) > oldViewDistance) { ++ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ return; ++ } ++ ++ // x axis is width ++ // z axis is height ++ // right refers to the x axis of where we moved ++ // top refers to the z axis of where we moved ++ ++ // same view distance ++ ++ // used for relative positioning ++ final int up = sign(dz); // 1 if dz >= 0, -1 otherwise ++ final int right = sign(dx); // 1 if dx >= 0, -1 otherwise ++ ++ // The area excluded by overlapping the two view distance squares creates four rectangles: ++ // Two on the left, and two on the right. The ones on the left we consider the "removed" section ++ // and on the right the "added" section. ++ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually ++ // exclusive to the regions they surround. ++ ++ // 4 points of the rectangle ++ int maxX; // exclusive ++ int minX; // inclusive ++ int maxZ; // exclusive ++ int minZ; // inclusive ++ ++ if (dx != 0) { ++ // handle right addition ++ ++ maxX = toX + (oldViewDistance * right) + right; // exclusive ++ minX = fromX + (oldViewDistance * right) + right; // inclusive ++ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive ++ minZ = toZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ if (dz != 0) { ++ // handle up addition ++ ++ maxX = toX + (oldViewDistance * right) + right; // exclusive ++ minX = toX - (oldViewDistance * right); // inclusive ++ maxZ = toZ + (oldViewDistance * up) + up; // exclusive ++ minZ = fromZ + (oldViewDistance * up) + up; // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ if (dx != 0) { ++ // handle left removal ++ ++ maxX = toX - (oldViewDistance * right); // exclusive ++ minX = fromX - (oldViewDistance * right); // inclusive ++ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive ++ minZ = toZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ ++ if (dz != 0) { ++ // handle down removal ++ ++ maxX = fromX + (oldViewDistance * right) + right; // exclusive ++ minX = fromX - (oldViewDistance * right); // inclusive ++ maxZ = toZ - (oldViewDistance * up); // exclusive ++ minZ = fromZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); ++ } ++ } ++ } ++ } ++ ++ @FunctionalInterface ++ public static interface ChangeCallback { ++ ++ // if there is no previous position, then prevPos = Integer.MIN_VALUE ++ void accept(final E object, final int rangeX, final int rangeZ, final int currPosX, final int currPosZ, final int prevPosX, final int prevPosZ, ++ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState); ++ ++ } ++ ++ @FunctionalInterface ++ public static interface ChangeSourceCallback { ++ void accept(final E object, final long prevPos, final long newPos); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..905b76d1d65744fe35f56bb78ef75f49178a6a24 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java +@@ -0,0 +1,175 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import com.destroystokyo.paper.util.math.IntegerUtil; ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; ++import net.minecraft.server.MCUtil; ++import net.minecraft.world.level.ChunkCoordIntPair; ++ ++/** @author Spottedleaf */ ++public abstract class DistanceTrackingAreaMap extends AreaMap { ++ ++ // use this map only if you need distance tracking, the tracking here is obviously going to hit harder. ++ ++ protected final Long2IntOpenHashMap chunkToNearestDistance = new Long2IntOpenHashMap(1024, 0.7f); ++ { ++ this.chunkToNearestDistance.defaultReturnValue(-1); ++ } ++ ++ protected final DistanceChangeCallback distanceChangeCallback; ++ ++ public DistanceTrackingAreaMap() { ++ this(new PooledLinkedHashSets<>()); ++ } ++ ++ // let users define a "global" or "shared" pooled sets if they wish ++ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { ++ this(pooledHashSets, null, null, null); ++ } ++ ++ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, ++ final DistanceChangeCallback distanceChangeCallback) { ++ super(pooledHashSets, addCallback, removeCallback); ++ this.distanceChangeCallback = distanceChangeCallback; ++ } ++ ++ // ret -1 if there is nothing mapped ++ public final int getNearestObjectDistance(final long key) { ++ return this.chunkToNearestDistance.get(key); ++ } ++ ++ // ret -1 if there is nothing mapped ++ public final int getNearestObjectDistance(final ChunkCoordIntPair chunkPos) { ++ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkPos)); ++ } ++ ++ // ret -1 if there is nothing mapped ++ public final int getNearestObjectDistance(final int chunkX, final int chunkZ) { ++ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); ++ } ++ ++ protected final void recalculateDistance(final int chunkX, final int chunkZ) { ++ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); ++ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state = this.areaMap.get(key); ++ if (state == null) { ++ final int oldDistance = this.chunkToNearestDistance.remove(key); ++ // nothing here. ++ if (oldDistance == -1) { ++ // nothing was here previously ++ return; ++ } ++ if (this.distanceChangeCallback != null) { ++ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, -1, null); ++ } ++ return; ++ } ++ ++ int newDistance = Integer.MAX_VALUE; ++ ++ final Object[] rawData = state.getBackingSet(); ++ for (int i = 0, len = rawData.length; i < len; ++i) { ++ final Object raw = rawData[i]; ++ ++ if (raw == null) { ++ continue; ++ } ++ ++ final E object = (E)raw; ++ final long location = this.objectToLastCoordinate.getLong(object); ++ ++ final int distance = Math.max(IntegerUtil.branchlessAbs(chunkX - MCUtil.getCoordinateX(location)), IntegerUtil.branchlessAbs(chunkZ - MCUtil.getCoordinateZ(location))); ++ ++ if (distance < newDistance) { ++ newDistance = distance; ++ } ++ } ++ ++ final int oldDistance = this.chunkToNearestDistance.put(key, newDistance); ++ ++ if (oldDistance != newDistance) { ++ if (this.distanceChangeCallback != null) { ++ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, newDistance, state); ++ } ++ } ++ } ++ ++ @Override ++ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int maxX = chunkX + viewDistance; ++ final int maxZ = chunkZ + viewDistance; ++ final int minX = chunkX - viewDistance; ++ final int minZ = chunkZ - viewDistance; ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ this.recalculateDistance(x, z); ++ } ++ } ++ } ++ ++ @Override ++ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { ++ final int maxX = chunkX + viewDistance; ++ final int maxZ = chunkZ + viewDistance; ++ final int minX = chunkX - viewDistance; ++ final int minZ = chunkZ - viewDistance; ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ this.recalculateDistance(x, z); ++ } ++ } ++ } ++ ++ @Override ++ protected void updateObjectCallback(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { ++ if (oldPosition == newPosition && newViewDistance == oldViewDistance) { ++ return; ++ } ++ ++ final int toX = MCUtil.getCoordinateX(newPosition); ++ final int toZ = MCUtil.getCoordinateZ(newPosition); ++ final int fromX = MCUtil.getCoordinateX(oldPosition); ++ final int fromZ = MCUtil.getCoordinateZ(oldPosition); ++ ++ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); ++ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); ++ ++ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { ++ // teleported? ++ this.removeObjectCallback(object, fromX, fromZ, oldViewDistance); ++ this.addObjectCallback(object, toX, toZ, newViewDistance); ++ return; ++ } ++ ++ final int minX = Math.min(fromX - oldViewDistance, toX - newViewDistance); ++ final int maxX = Math.max(fromX + oldViewDistance, toX + newViewDistance); ++ final int minZ = Math.min(fromZ - oldViewDistance, toZ - newViewDistance); ++ final int maxZ = Math.max(fromZ + oldViewDistance, toZ + newViewDistance); ++ ++ for (int x = minX; x <= maxX; ++x) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ final int distXOld = IntegerUtil.branchlessAbs(x - fromX); ++ final int distZOld = IntegerUtil.branchlessAbs(z - fromZ); ++ ++ if (Math.max(distXOld, distZOld) <= oldViewDistance) { ++ this.recalculateDistance(x, z); ++ continue; ++ } ++ ++ final int distXNew = IntegerUtil.branchlessAbs(x - toX); ++ final int distZNew = IntegerUtil.branchlessAbs(z - toZ); ++ ++ if (Math.max(distXNew, distZNew) <= newViewDistance) { ++ this.recalculateDistance(x, z); ++ continue; ++ } ++ } ++ } ++ } ++ ++ @FunctionalInterface ++ public static interface DistanceChangeCallback { ++ ++ void accept(final int posX, final int posZ, final int oldNearestDistance, final int newNearestDistance, ++ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state); ++ ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ed6133b07bc6c4662bd2099ea7dc8aabec37c853 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java +@@ -0,0 +1,32 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import net.minecraft.server.level.EntityPlayer; ++ ++/** ++ * @author Spottedleaf ++ */ ++public final class PlayerAreaMap extends AreaMap { ++ ++ public PlayerAreaMap() { ++ super(); ++ } ++ ++ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets) { ++ super(pooledHashSets); ++ } ++ ++ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, ++ final ChangeCallback removeCallback) { ++ this(pooledHashSets, addCallback, removeCallback, null); ++ } ++ ++ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, ++ final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { ++ super(pooledHashSets, addCallback, removeCallback, changeSourceCallback); ++ } ++ ++ @Override ++ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final EntityPlayer player) { ++ return player.cachedSingleHashSet; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..eca1fea17184076635563717bb32c81187e2f6f7 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java +@@ -0,0 +1,24 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import net.minecraft.server.level.EntityPlayer; ++ ++public class PlayerDistanceTrackingAreaMap extends DistanceTrackingAreaMap { ++ ++ public PlayerDistanceTrackingAreaMap() { ++ super(); ++ } ++ ++ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { ++ super(pooledHashSets); ++ } ++ ++ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, ++ final ChangeCallback removeCallback, final DistanceChangeCallback distanceChangeCallback) { ++ super(pooledHashSets, addCallback, removeCallback, distanceChangeCallback); ++ } ++ ++ @Override ++ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final EntityPlayer player) { ++ return player.cachedSingleHashSet; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e51104e65a07b6ea7bbbcbb6afb066ef6401cc5b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java +@@ -0,0 +1,287 @@ ++package com.destroystokyo.paper.util.misc; ++ ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; ++import java.lang.ref.WeakReference; ++ ++/** @author Spottedleaf */ ++public class PooledLinkedHashSets { ++ ++ /* Tested via https://gist.github.com/Spottedleaf/a93bb7a8993d6ce142d3efc5932bf573 */ ++ ++ // we really want to avoid that equals() check as much as possible... ++ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(128, 0.25f); ++ ++ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { ++ if (current.referenceCount == 0) { ++ throw new IllegalStateException("Cannot decrement reference count for " + current); ++ } ++ if (current.referenceCount == -1 || --current.referenceCount > 0) { ++ return; ++ } ++ ++ this.mapPool.remove(current); ++ return; ++ } ++ ++ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { ++ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); ++ ++ if (cached != null) { ++ decrementReferenceCount(current); ++ ++ if (cached.referenceCount == 0) { ++ // bring the map back from the dead ++ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); ++ if (contending != null) { ++ // a map already exists with the elements we want ++ if (contending.referenceCount != -1) { ++ ++contending.referenceCount; ++ } ++ current.updateAddCache(object, contending); ++ return contending; ++ } ++ ++ cached.referenceCount = 1; ++ } else if (cached.referenceCount != -1) { ++ ++cached.referenceCount; ++ } ++ ++ return cached; ++ } ++ ++ if (!current.add(object)) { ++ return current; ++ } ++ ++ // we use get/put since we use a different key on put ++ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); ++ ++ if (ret == null) { ++ ret = new PooledObjectLinkedOpenHashSet<>(current); ++ current.remove(object); ++ this.mapPool.put(ret, ret); ++ ret.referenceCount = 1; ++ } else { ++ if (ret.referenceCount != -1) { ++ ++ret.referenceCount; ++ } ++ current.remove(object); ++ } ++ ++ current.updateAddCache(object, ret); ++ ++ decrementReferenceCount(current); ++ return ret; ++ } ++ ++ // rets null if current.size() == 1 ++ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { ++ if (current.set.size() == 1) { ++ decrementReferenceCount(current); ++ return null; ++ } ++ ++ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); ++ ++ if (cached != null) { ++ decrementReferenceCount(current); ++ ++ if (cached.referenceCount == 0) { ++ // bring the map back from the dead ++ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); ++ if (contending != null) { ++ // a map already exists with the elements we want ++ if (contending.referenceCount != -1) { ++ ++contending.referenceCount; ++ } ++ current.updateRemoveCache(object, contending); ++ return contending; ++ } ++ ++ cached.referenceCount = 1; ++ } else if (cached.referenceCount != -1) { ++ ++cached.referenceCount; ++ } ++ ++ return cached; ++ } ++ ++ if (!current.remove(object)) { ++ return current; ++ } ++ ++ // we use get/put since we use a different key on put ++ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); ++ ++ if (ret == null) { ++ ret = new PooledObjectLinkedOpenHashSet<>(current); ++ current.add(object); ++ this.mapPool.put(ret, ret); ++ ret.referenceCount = 1; ++ } else { ++ if (ret.referenceCount != -1) { ++ ++ret.referenceCount; ++ } ++ current.add(object); ++ } ++ ++ current.updateRemoveCache(object, ret); ++ ++ decrementReferenceCount(current); ++ return ret; ++ } ++ ++ static final class RawSetObjectLinkedOpenHashSet extends ObjectOpenHashSet { ++ ++ public RawSetObjectLinkedOpenHashSet() { ++ super(); ++ } ++ ++ public RawSetObjectLinkedOpenHashSet(final int capacity) { ++ super(capacity); ++ } ++ ++ public RawSetObjectLinkedOpenHashSet(final int capacity, final float loadFactor) { ++ super(capacity, loadFactor); ++ } ++ ++ @Override ++ public RawSetObjectLinkedOpenHashSet clone() { ++ return (RawSetObjectLinkedOpenHashSet)super.clone(); ++ } ++ ++ public E[] getRawSet() { ++ return this.key; ++ } ++ } ++ ++ public static final class PooledObjectLinkedOpenHashSet { ++ ++ private static final WeakReference NULL_REFERENCE = new WeakReference<>(null); ++ ++ final RawSetObjectLinkedOpenHashSet set; ++ int referenceCount; // -1 if special ++ int hash; // optimize hashcode ++ ++ // add cache ++ WeakReference lastAddObject = NULL_REFERENCE; ++ WeakReference> lastAddMap = NULL_REFERENCE; ++ ++ // remove cache ++ WeakReference lastRemoveObject = NULL_REFERENCE; ++ WeakReference> lastRemoveMap = NULL_REFERENCE; ++ ++ public PooledObjectLinkedOpenHashSet(final PooledLinkedHashSets pooledSets) { ++ this.set = new RawSetObjectLinkedOpenHashSet<>(2, 0.8f); ++ } ++ ++ public PooledObjectLinkedOpenHashSet(final E single) { ++ this((PooledLinkedHashSets)null); ++ this.referenceCount = -1; ++ this.add(single); ++ } ++ ++ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { ++ this.set = other.set.clone(); ++ this.hash = other.hash; ++ } ++ ++ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java ++ // generated by https://github.com/skeeto/hash-prospector ++ private static int hash0(int x) { ++ x *= 0x36935555; ++ x ^= x >>> 16; ++ return x; ++ } ++ ++ PooledObjectLinkedOpenHashSet getAddCache(final E element) { ++ final E currentAdd = this.lastAddObject.get(); ++ ++ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { ++ return null; ++ } ++ ++ return this.lastAddMap.get(); ++ } ++ ++ PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { ++ final E currentRemove = this.lastRemoveObject.get(); ++ ++ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { ++ return null; ++ } ++ ++ return this.lastRemoveMap.get(); ++ } ++ ++ void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { ++ this.lastAddObject = new WeakReference<>(element); ++ this.lastAddMap = new WeakReference<>(map); ++ } ++ ++ void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { ++ this.lastRemoveObject = new WeakReference<>(element); ++ this.lastRemoveMap = new WeakReference<>(map); ++ } ++ ++ boolean add(final E element) { ++ boolean added = this.set.add(element); ++ ++ if (added) { ++ this.hash += hash0(element.hashCode()); ++ } ++ ++ return added; ++ } ++ ++ boolean remove(Object element) { ++ boolean removed = this.set.remove(element); ++ ++ if (removed) { ++ this.hash -= hash0(element.hashCode()); ++ } ++ ++ return removed; ++ } ++ ++ public boolean contains(final Object element) { ++ return this.set.contains(element); ++ } ++ ++ public E[] getBackingSet() { ++ return this.set.getRawSet(); ++ } ++ ++ public int size() { ++ return this.set.size(); ++ } ++ ++ @Override ++ public int hashCode() { ++ return this.hash; ++ } ++ ++ @Override ++ public boolean equals(final Object other) { ++ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { ++ return false; ++ } ++ if (this.referenceCount == 0) { ++ return other == this; ++ } else { ++ if (other == this) { ++ // Unfortunately we are never equal to our own instance while in use! ++ return false; ++ } ++ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); ++ } ++ } ++ ++ @Override ++ public String toString() { ++ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + ++ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d0c77068e9a53d1b8bbad0f3f6b420d6bc85f8c8 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java +@@ -0,0 +1,85 @@ ++package com.destroystokyo.paper.util.pooled; ++ ++import net.minecraft.server.MCUtil; ++import org.apache.commons.lang3.mutable.MutableInt; ++ ++import java.util.ArrayDeque; ++import java.util.function.Consumer; ++import java.util.function.Supplier; ++ ++public final class PooledObjects { ++ ++ /** ++ * Wrapper for an object that will be have a cleaner registered for it, and may be automatically returned to pool. ++ */ ++ public class AutoReleased { ++ private final E object; ++ private final Runnable cleaner; ++ ++ public AutoReleased(E object, Runnable cleaner) { ++ this.object = object; ++ this.cleaner = cleaner; ++ } ++ ++ public final E getObject() { ++ return object; ++ } ++ ++ public final Runnable getCleaner() { ++ return cleaner; ++ } ++ } ++ ++ public static final PooledObjects POOLED_MUTABLE_INTEGERS = new PooledObjects<>(MutableInt::new, 1024); ++ ++ private final Supplier creator; ++ private final Consumer releaser; ++ private final int maxPoolSize; ++ private final ArrayDeque queue; ++ ++ public PooledObjects(final Supplier creator, int maxPoolSize) { ++ this(creator, maxPoolSize, null); ++ } ++ public PooledObjects(final Supplier creator, int maxPoolSize, Consumer releaser) { ++ if (creator == null) { ++ throw new NullPointerException("Creator must not be null"); ++ } ++ if (maxPoolSize <= 0) { ++ throw new IllegalArgumentException("Max pool size must be greater-than 0"); ++ } ++ ++ this.queue = new ArrayDeque<>(maxPoolSize); ++ this.maxPoolSize = maxPoolSize; ++ this.creator = creator; ++ this.releaser = releaser; ++ } ++ ++ public AutoReleased acquireCleaner(Object holder) { ++ return acquireCleaner(holder, this::release); ++ } ++ ++ public AutoReleased acquireCleaner(Object holder, Consumer releaser) { ++ E resource = acquire(); ++ Runnable cleaner = MCUtil.registerCleaner(holder, resource, releaser); ++ return new AutoReleased(resource, cleaner); ++ } ++ ++ public final E acquire() { ++ E value; ++ synchronized (queue) { ++ value = this.queue.pollLast(); ++ } ++ return value != null ? value : this.creator.get(); ++ } ++ ++ public final void release(final E value) { ++ if (this.releaser != null) { ++ this.releaser.accept(value); ++ } ++ synchronized (this.queue) { ++ if (queue.size() < this.maxPoolSize) { ++ this.queue.addLast(value); ++ } ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java +@@ -0,0 +1,67 @@ ++package com.destroystokyo.paper.util.set; ++ ++import java.util.Collection; ++ ++/** ++ * @author Spottedleaf ++ */ ++public final class OptimizedSmallEnumSet> { ++ ++ private final Class enumClass; ++ private long backingSet; ++ ++ public OptimizedSmallEnumSet(final Class clazz) { ++ if (clazz == null) { ++ throw new IllegalArgumentException("Null class"); ++ } ++ if (!clazz.isEnum()) { ++ throw new IllegalArgumentException("Class must be enum, not " + clazz.getCanonicalName()); ++ } ++ this.enumClass = clazz; ++ } ++ ++ public boolean addUnchecked(final E element) { ++ final int ordinal = element.ordinal(); ++ final long key = 1L << ordinal; ++ ++ final long prev = this.backingSet; ++ this.backingSet = prev | key; ++ ++ return (prev & key) == 0; ++ } ++ ++ public boolean removeUnchecked(final E element) { ++ final int ordinal = element.ordinal(); ++ final long key = 1L << ordinal; ++ ++ final long prev = this.backingSet; ++ this.backingSet = prev & ~key; ++ ++ return (prev & key) != 0; ++ } ++ ++ public void clear() { ++ this.backingSet = 0L; ++ } ++ ++ public int size() { ++ return Long.bitCount(this.backingSet); ++ } ++ ++ public void addAllUnchecked(final Collection enums) { ++ for (final E element : enums) { ++ if (element == null) { ++ throw new NullPointerException("Null element"); ++ } ++ this.backingSet |= (1L << element.ordinal()); ++ } ++ } ++ ++ public long getBackingSet() { ++ return this.backingSet; ++ } ++ ++ public boolean hasCommonElements(final OptimizedSmallEnumSet other) { ++ return (other.backingSet & this.backingSet) != 0; ++ } ++} +diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java +index bc7757b929ecce998094ddcdf51a4703e165a6d6..c8bb06a31242089ad950713bd5f94abbfe12adc8 100644 +--- a/src/main/java/net/minecraft/SystemUtils.java ++++ b/src/main/java/net/minecraft/SystemUtils.java +@@ -78,7 +78,7 @@ public class SystemUtils { + } + + public static long getMonotonicNanos() { +- return SystemUtils.a.getAsLong(); ++ return System.nanoTime(); // Paper + } + + public static long getTimeMillis() { +diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java +index fe3a3ce150de0e689c452b67d480b9d69471b330..25fdd55a7548cfaa45a541ad77f22f33c33e7471 100644 +--- a/src/main/java/net/minecraft/core/BaseBlockPosition.java ++++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java +@@ -18,9 +18,9 @@ public class BaseBlockPosition implements Comparable { + return IntStream.of(new int[]{baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()}); + }); + public static final BaseBlockPosition ZERO = new BaseBlockPosition(0, 0, 0); +- private int a; +- private int b; +- private int e; ++ private int a;public final void setX(final int x) { this.a = x; } // Paper - OBFHELPER ++ private int b;public final void setY(final int y) { this.b = y; } // Paper - OBFHELPER ++ private int e;public final void setZ(final int z) { this.e = z; } // Paper - OBFHELPER + + public BaseBlockPosition(int i, int j, int k) { + this.a = i; +@@ -64,15 +64,15 @@ public class BaseBlockPosition implements Comparable { + return this.e; + } + +- protected void o(int i) { ++ public void o(int i) { // Paper - protected -> public + this.a = i; + } + +- protected void p(int i) { ++ public void p(int i) { // Paper - protected -> public + this.b = i; + } + +- protected void q(int i) { ++ public void q(int i) { // Paper - protected -> public + this.e = i; + } + +@@ -108,6 +108,7 @@ public class BaseBlockPosition implements Comparable { + return this.distanceSquared(iposition.getX(), iposition.getY(), iposition.getZ(), true) < d0 * d0; + } + ++ public final double distanceSquared(BaseBlockPosition baseblockposition) { return j(baseblockposition); } // Paper - OBFHELPER + public double j(BaseBlockPosition baseblockposition) { + return this.distanceSquared((double) baseblockposition.getX(), (double) baseblockposition.getY(), (double) baseblockposition.getZ(), true); + } +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index 76675ad1633dbaebb180842b9914fac18741c62e..9fb6db18c5c1f39b5a564c0f5f70498825defa97 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -105,6 +105,7 @@ public class BlockPosition extends BaseBlockPosition { + return d0 == 0.0D && d1 == 0.0D && d2 == 0.0D ? this : new BlockPosition((double) this.getX() + d0, (double) this.getY() + d1, (double) this.getZ() + d2); + } + ++ public final BlockPosition add(int i, int j, int k) {return b(i, j, k);} // Paper - OBFHELPER + public BlockPosition b(int i, int j, int k) { + return i == 0 && j == 0 && k == 0 ? this : new BlockPosition(this.getX() + i, this.getY() + j, this.getZ() + k); + } +@@ -436,6 +437,7 @@ public class BlockPosition extends BaseBlockPosition { + return super.a(enumblockrotation).immutableCopy(); + } + ++ public final BlockPosition.MutableBlockPosition setValues(int i, int j, int k) { return d(i, j, k);} // Paper - OBFHELPER + public BlockPosition.MutableBlockPosition d(int i, int j, int k) { + this.o(i); + this.p(j); +@@ -443,6 +445,7 @@ public class BlockPosition extends BaseBlockPosition { + return this; + } + ++ public final BlockPosition.MutableBlockPosition setValues(double d0, double d1, double d2) { return c(d0, d1, d2);} // Paper - OBFHELPER + public BlockPosition.MutableBlockPosition c(double d0, double d1, double d2) { + return this.d(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); + } +@@ -496,6 +499,7 @@ public class BlockPosition extends BaseBlockPosition { + } + } + ++ /* // Paper start - comment out useless overrides @Override + @Override + public void o(int i) { + super.o(i); +@@ -506,10 +510,10 @@ public class BlockPosition extends BaseBlockPosition { + super.p(i); + } + +- @Override + public void q(int i) { + super.q(i); + } ++ */ // Paper end + + @Override + public BlockPosition immutableCopy() { +diff --git a/src/main/java/net/minecraft/core/RegistryBlockID.java b/src/main/java/net/minecraft/core/RegistryBlockID.java +index e543b6927280a14e1d1220534758289934e31282..d5bec8b0e155ea5ae5746b6da571754a98e4125e 100644 +--- a/src/main/java/net/minecraft/core/RegistryBlockID.java ++++ b/src/main/java/net/minecraft/core/RegistryBlockID.java +@@ -64,6 +64,7 @@ public class RegistryBlockID implements Registry { + return Iterators.filter(this.c.iterator(), Predicates.notNull()); + } + ++ public int size() { return this.a(); } // Paper - OBFHELPER + public int a() { + return this.b.size(); + } +diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java +index b2fb24e9ae19ab6e7039a98fc0c265f801be8a99..bf4826e90976fed2ae95e84cadc7f29433af1ddf 100644 +--- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java ++++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java +@@ -76,7 +76,7 @@ public class NBTTagCompound implements NBTBase { + return "TAG_Compound"; + } + }; +- private final Map map; ++ public final Map map; // Paper + + protected NBTTagCompound(Map map) { + this.map = map; +@@ -139,10 +139,16 @@ public class NBTTagCompound implements NBTBase { + this.map.put(s, NBTTagLong.a(i)); + } + ++ public void setUUID(String prefix, UUID uuid) { a(prefix, uuid); } // Paper - OBFHELPER + public void a(String s, UUID uuid) { + this.map.put(s, GameProfileSerializer.a(uuid)); + } + ++ ++ /** ++ * You must use {@link #hasUUID(String)} before or else it will throw an NPE. ++ */ ++ public UUID getUUID(String prefix) { return a(prefix); } // Paper - OBFHELPER + public UUID a(String s) { + return GameProfileSerializer.a(this.get(s)); + } +diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +index 82d8a163df294e68b4db685b95553637f905db48..f093b465b868e6003bb2b5ee634a624b5b054493 100644 +--- a/src/main/java/net/minecraft/network/NetworkManager.java ++++ b/src/main/java/net/minecraft/network/NetworkManager.java +@@ -168,6 +168,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + + } + ++ private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER + private void b(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { + EnumProtocol enumprotocol = EnumProtocol.a(packet); + EnumProtocol enumprotocol1 = (EnumProtocol) this.channel.attr(NetworkManager.c).get(); +@@ -208,6 +209,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + + } + ++ private void sendPacketQueue() { this.p(); } // Paper - OBFHELPER + private void p() { + if (this.channel != null && this.channel.isOpen()) { + Queue queue = this.packetQueue; +@@ -344,9 +346,9 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + + static class QueuedPacket { + +- private final Packet a; ++ private final Packet a; private final Packet getPacket() { return this.a; } // Paper - OBFHELPER + @Nullable +- private final GenericFutureListener> b; ++ private final GenericFutureListener> b; private final GenericFutureListener> getGenericFutureListener() { return this.b; } // Paper - OBFHELPER + + public QueuedPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { + this.a = packet; +diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java +index f94e96406d6dc9c75091ae7563dd5b325f4f0c22..5413bf93f7f0f4491fca1f07c47a925fdace7751 100644 +--- a/src/main/java/net/minecraft/network/PacketDataSerializer.java ++++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java +@@ -49,6 +49,7 @@ public class PacketDataSerializer extends ByteBuf { + this.a = bytebuf; + } + ++ public static int countBytes(int i) { return PacketDataSerializer.a(i); } // Paper - OBFHELPER + public static int a(int i) { + for (int j = 1; j < 5; ++j) { + if ((i & -1 << j * 7) == 0) { +diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java +index 06098698e4adc31aa96f9592975e441f965b5558..dc8cc8d6c00176c8562086282f726dc1b24b2c65 100644 +--- a/src/main/java/net/minecraft/network/PacketEncoder.java ++++ b/src/main/java/net/minecraft/network/PacketEncoder.java +@@ -44,6 +44,7 @@ public class PacketEncoder extends MessageToByteEncoder> { + packet.b(packetdataserializer); + } catch (Throwable throwable) { + PacketEncoder.LOGGER.error(throwable); ++ throwable.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? + if (packet.a()) { + throw new SkipEncodeException(throwable); + } else { +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java +index d748e07f8870023e74796910a457d58ee0361ca6..2b8358995e4933d3fc3498407a7df7475d7b7e26 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java +@@ -7,7 +7,7 @@ import net.minecraft.world.item.ItemStack; + + public class PacketPlayInBEdit implements Packet { + +- private ItemStack a; ++ private ItemStack a; public ItemStack getBook() { return a; } // Paper - OBFHELPER + private boolean b; + private int c; + +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java +index 820ba7c59e7bc7b6f3311f1a4ec3d724e265a2af..b6b55d5baa5e8a6b69a3e4865c06bc8a4d61a4f3 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java +@@ -28,7 +28,7 @@ public class PacketPlayOutMapChunk implements Packet { + private NBTTagCompound d; + @Nullable + private int[] e; +- private byte[] f; ++ private byte[] f; private byte[] getData() { return this.f; } // Paper - OBFHELPER + private List g; + private boolean h; + +@@ -140,6 +140,7 @@ public class PacketPlayOutMapChunk implements Packet { + return bytebuf; + } + ++ public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, chunkSectionSelector); } // Paper - OBFHELPER + public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i) { + int j = 0; + ChunkSection[] achunksection = chunk.getSections(); +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..18b56b59fd6efd618e6ff6f9cf3a02f57588d244 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -0,0 +1,510 @@ ++package net.minecraft.server; ++ ++import com.destroystokyo.paper.block.TargetBlockInfo; ++import com.google.common.util.concurrent.ThreadFactoryBuilder; ++import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; ++import net.minecraft.core.BlockPosition; ++import net.minecraft.core.EnumDirection; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.level.RayTrace; ++import net.minecraft.world.level.World; ++import org.apache.commons.lang.exception.ExceptionUtils; ++import org.bukkit.Location; ++import org.bukkit.block.BlockFace; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.spigotmc.AsyncCatcher; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++import java.util.List; ++import java.util.Queue; ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.ExecutionException; ++import java.util.concurrent.LinkedBlockingQueue; ++import java.util.concurrent.ThreadPoolExecutor; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.TimeoutException; ++import java.util.concurrent.atomic.AtomicBoolean; ++import java.util.function.BiConsumer; ++import java.util.function.Consumer; ++import java.util.function.Supplier; ++ ++public final class MCUtil { ++ public static final ThreadPoolExecutor asyncExecutor = new ThreadPoolExecutor( ++ 0, 2, 60L, TimeUnit.SECONDS, ++ new LinkedBlockingQueue(), ++ new ThreadFactoryBuilder().setNameFormat("Paper Async Task Handler Thread - %1$d").build() ++ ); ++ public static final ThreadPoolExecutor cleanerExecutor = new ThreadPoolExecutor( ++ 1, 1, 0L, TimeUnit.SECONDS, ++ new LinkedBlockingQueue(), ++ new ThreadFactoryBuilder().setNameFormat("Paper Object Cleaner").build() ++ ); ++ ++ public static final long INVALID_CHUNK_KEY = getCoordinateKey(Integer.MAX_VALUE, Integer.MAX_VALUE); ++ ++ ++ public static Runnable once(Runnable run) { ++ AtomicBoolean ran = new AtomicBoolean(false); ++ return () -> { ++ if (ran.compareAndSet(false, true)) { ++ run.run(); ++ } ++ }; ++ } ++ ++ public static Runnable once(List list, Consumer cb) { ++ return once(() -> { ++ list.forEach(cb); ++ }); ++ } ++ ++ private static Runnable makeCleanerCallback(Runnable run) { ++ return once(() -> cleanerExecutor.execute(run)); ++ } ++ ++ /** ++ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! ++ * @param obj ++ * @param run ++ * @return ++ */ ++ public static Runnable registerCleaner(Object obj, Runnable run) { ++ // Wrap callback in its own method above or the lambda will leak object ++ Runnable cleaner = makeCleanerCallback(run); ++ co.aikar.cleaner.Cleaner.register(obj, cleaner); ++ return cleaner; ++ } ++ ++ /** ++ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! ++ * @param obj ++ * @param list ++ * @param cleaner ++ * @param ++ * @return ++ */ ++ public static Runnable registerListCleaner(Object obj, List list, Consumer cleaner) { ++ return registerCleaner(obj, () -> { ++ list.forEach(cleaner); ++ list.clear(); ++ }); ++ } ++ ++ /** ++ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! ++ * @param obj ++ * @param resource ++ * @param cleaner ++ * @param ++ * @return ++ */ ++ public static Runnable registerCleaner(Object obj, T resource, java.util.function.Consumer cleaner) { ++ return registerCleaner(obj, () -> cleaner.accept(resource)); ++ } ++ ++ public static List getSpiralOutChunks(BlockPosition blockposition, int radius) { ++ List list = com.google.common.collect.Lists.newArrayList(); ++ ++ list.add(new ChunkCoordIntPair(blockposition.getX() >> 4, blockposition.getZ() >> 4)); ++ for (int r = 1; r <= radius; r++) { ++ int x = -r; ++ int z = r; ++ ++ // Iterates the edge of half of the box; then negates for other half. ++ while (x <= r && z > -r) { ++ list.add(new ChunkCoordIntPair((blockposition.getX() + (x << 4)) >> 4, (blockposition.getZ() + (z << 4)) >> 4)); ++ list.add(new ChunkCoordIntPair((blockposition.getX() - (x << 4)) >> 4, (blockposition.getZ() - (z << 4)) >> 4)); ++ ++ if (x < r) { ++ x++; ++ } else { ++ z--; ++ } ++ } ++ } ++ return list; ++ } ++ ++ public static int fastFloor(double x) { ++ int truncated = (int)x; ++ return x < (double)truncated ? truncated - 1 : truncated; ++ } ++ ++ public static int fastFloor(float x) { ++ int truncated = (int)x; ++ return x < (double)truncated ? truncated - 1 : truncated; ++ } ++ ++ public static float normalizeYaw(float f) { ++ float f1 = f % 360.0F; ++ ++ if (f1 >= 180.0F) { ++ f1 -= 360.0F; ++ } ++ ++ if (f1 < -180.0F) { ++ f1 += 360.0F; ++ } ++ ++ return f1; ++ } ++ ++ /** ++ * Quickly generate a stack trace for current location ++ * ++ * @return Stacktrace ++ */ ++ public static String stack() { ++ return ExceptionUtils.getFullStackTrace(new Throwable()); ++ } ++ ++ /** ++ * Quickly generate a stack trace for current location with message ++ * ++ * @param str ++ * @return Stacktrace ++ */ ++ public static String stack(String str) { ++ return ExceptionUtils.getFullStackTrace(new Throwable(str)); ++ } ++ ++ public static long getCoordinateKey(final BlockPosition blockPos) { ++ return ((long)(blockPos.getZ() >> 4) << 32) | ((blockPos.getX() >> 4) & 0xFFFFFFFFL); ++ } ++ ++ public static long getCoordinateKey(final Entity entity) { ++ return ((long)(MCUtil.fastFloor(entity.locZ()) >> 4) << 32) | ((MCUtil.fastFloor(entity.locX()) >> 4) & 0xFFFFFFFFL); ++ } ++ ++ public static long getCoordinateKey(final ChunkCoordIntPair pair) { ++ return ((long)pair.z << 32) | (pair.x & 0xFFFFFFFFL); ++ } ++ ++ public static long getCoordinateKey(final int x, final int z) { ++ return ((long)z << 32) | (x & 0xFFFFFFFFL); ++ } ++ ++ public static int getCoordinateX(final long key) { ++ return (int)key; ++ } ++ ++ public static int getCoordinateZ(final long key) { ++ return (int)(key >>> 32); ++ } ++ ++ public static int getChunkCoordinate(final double coordinate) { ++ return MCUtil.fastFloor(coordinate) >> 4; ++ } ++ ++ public static int getBlockCoordinate(final double coordinate) { ++ return MCUtil.fastFloor(coordinate); ++ } ++ ++ public static long getBlockKey(final int x, final int y, final int z) { ++ return ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54); ++ } ++ ++ public static long getBlockKey(final BlockPosition pos) { ++ return ((long)pos.getX() & 0x7FFFFFF) | (((long)pos.getZ() & 0x7FFFFFF) << 27) | ((long)pos.getY() << 54); ++ } ++ ++ public static long getBlockKey(final Entity entity) { ++ return getBlockKey(getBlockCoordinate(entity.locX()), getBlockCoordinate(entity.locY()), getBlockCoordinate(entity.locZ())); ++ } ++ ++ // assumes the sets have the same comparator, and if this comparator is null then assume T is Comparable ++ public static void mergeSortedSets(final java.util.function.Consumer consumer, final java.util.Comparator comparator, final java.util.SortedSet...sets) { ++ final ObjectRBTreeSet all = new ObjectRBTreeSet<>(comparator); ++ // note: this is done in log(n!) ~ nlogn time. It could be improved if it were to mimic what mergesort does. ++ for (java.util.SortedSet set : sets) { ++ if (set != null) { ++ all.addAll(set); ++ } ++ } ++ all.forEach(consumer); ++ } ++ ++ private MCUtil() {} ++ ++ public static final java.util.concurrent.Executor MAIN_EXECUTOR = (run) -> { ++ if (!isMainThread()) { ++ MinecraftServer.getServer().execute(run); ++ } else { ++ run.run(); ++ } ++ }; ++ ++ public static CompletableFuture ensureMain(CompletableFuture future) { ++ return future.thenApplyAsync(r -> r, MAIN_EXECUTOR); ++ } ++ ++ public static void thenOnMain(CompletableFuture future, Consumer consumer) { ++ future.thenAcceptAsync(consumer, MAIN_EXECUTOR); ++ } ++ public static void thenOnMain(CompletableFuture future, BiConsumer consumer) { ++ future.whenCompleteAsync(consumer, MAIN_EXECUTOR); ++ } ++ ++ public static boolean isMainThread() { ++ return MinecraftServer.getServer().isMainThread(); ++ } ++ ++ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable) { ++ return scheduleTask(ticks, runnable, null); ++ } ++ ++ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable, String taskName) { ++ return MinecraftServer.getServer().server.getScheduler().scheduleInternalTask(runnable, ticks, taskName); ++ } ++ ++ public static void processQueue() { ++ Runnable runnable; ++ Queue processQueue = getProcessQueue(); ++ while ((runnable = processQueue.poll()) != null) { ++ try { ++ runnable.run(); ++ } catch (Exception e) { ++ MinecraftServer.LOGGER.error("Error executing task", e); ++ } ++ } ++ } ++ public static T processQueueWhileWaiting(CompletableFuture future) { ++ try { ++ if (isMainThread()) { ++ while (!future.isDone()) { ++ try { ++ return future.get(1, TimeUnit.MILLISECONDS); ++ } catch (TimeoutException ignored) { ++ processQueue(); ++ } ++ } ++ } ++ return future.get(); ++ } catch (Exception e) { ++ throw new RuntimeException(e); ++ } ++ } ++ ++ public static void ensureMain(Runnable run) { ++ ensureMain(null, run); ++ } ++ /** ++ * Ensures the target code is running on the main thread ++ * @param reason ++ * @param run ++ * @return ++ */ ++ public static void ensureMain(String reason, Runnable run) { ++ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { ++ if (reason != null) { ++ new IllegalStateException("Asynchronous " + reason + "!").printStackTrace(); ++ } ++ getProcessQueue().add(run); ++ return; ++ } ++ run.run(); ++ } ++ ++ private static Queue getProcessQueue() { ++ return MinecraftServer.getServer().processQueue; ++ } ++ ++ public static T ensureMain(Supplier run) { ++ return ensureMain(null, run); ++ } ++ /** ++ * Ensures the target code is running on the main thread ++ * @param reason ++ * @param run ++ * @param ++ * @return ++ */ ++ public static T ensureMain(String reason, Supplier run) { ++ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { ++ if (reason != null) { ++ new IllegalStateException("Asynchronous " + reason + "! Blocking thread until it returns ").printStackTrace(); ++ } ++ Waitable wait = new Waitable() { ++ @Override ++ protected T evaluate() { ++ return run.get(); ++ } ++ }; ++ getProcessQueue().add(wait); ++ try { ++ return wait.get(); ++ } catch (InterruptedException | ExecutionException e) { ++ e.printStackTrace(); ++ } ++ return null; ++ } ++ return run.get(); ++ } ++ ++ /** ++ * Calculates distance between 2 entities ++ * @param e1 ++ * @param e2 ++ * @return ++ */ ++ public static double distance(Entity e1, Entity e2) { ++ return Math.sqrt(distanceSq(e1, e2)); ++ } ++ ++ ++ /** ++ * Calculates distance between 2 block positions ++ * @param e1 ++ * @param e2 ++ * @return ++ */ ++ public static double distance(BlockPosition e1, BlockPosition e2) { ++ return Math.sqrt(distanceSq(e1, e2)); ++ } ++ ++ /** ++ * Gets the distance between 2 positions ++ * @param x1 ++ * @param y1 ++ * @param z1 ++ * @param x2 ++ * @param y2 ++ * @param z2 ++ * @return ++ */ ++ public static double distance(double x1, double y1, double z1, double x2, double y2, double z2) { ++ return Math.sqrt(distanceSq(x1, y1, z1, x2, y2, z2)); ++ } ++ ++ /** ++ * Get's the distance squared between 2 entities ++ * @param e1 ++ * @param e2 ++ * @return ++ */ ++ public static double distanceSq(Entity e1, Entity e2) { ++ return distanceSq(e1.locX(),e1.locY(),e1.locZ(), e2.locX(),e2.locY(),e2.locZ()); ++ } ++ ++ /** ++ * Gets the distance sqaured between 2 block positions ++ * @param pos1 ++ * @param pos2 ++ * @return ++ */ ++ public static double distanceSq(BlockPosition pos1, BlockPosition pos2) { ++ return distanceSq(pos1.getX(), pos1.getY(), pos1.getZ(), pos2.getX(), pos2.getY(), pos2.getZ()); ++ } ++ ++ /** ++ * Gets the distance squared between 2 positions ++ * @param x1 ++ * @param y1 ++ * @param z1 ++ * @param x2 ++ * @param y2 ++ * @param z2 ++ * @return ++ */ ++ public static double distanceSq(double x1, double y1, double z1, double x2, double y2, double z2) { ++ return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2); ++ } ++ ++ /** ++ * Converts a NMS World/BlockPosition to Bukkit Location ++ * @param world ++ * @param x ++ * @param y ++ * @param z ++ * @return ++ */ ++ public static Location toLocation(World world, double x, double y, double z) { ++ return new Location(world.getWorld(), x, y, z); ++ } ++ ++ /** ++ * Converts a NMS World/BlockPosition to Bukkit Location ++ * @param world ++ * @param pos ++ * @return ++ */ ++ public static Location toLocation(World world, BlockPosition pos) { ++ return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()); ++ } ++ ++ /** ++ * Converts an NMS entity's current location to a Bukkit Location ++ * @param entity ++ * @return ++ */ ++ public static Location toLocation(Entity entity) { ++ return new Location(entity.getWorld().getWorld(), entity.locX(), entity.locY(), entity.locZ()); ++ } ++ ++ public static org.bukkit.block.Block toBukkitBlock(World world, BlockPosition pos) { ++ return world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ } ++ ++ public static BlockPosition toBlockPosition(Location loc) { ++ return new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); ++ } ++ ++ public static boolean isEdgeOfChunk(BlockPosition pos) { ++ final int modX = pos.getX() & 15; ++ final int modZ = pos.getZ() & 15; ++ return (modX == 0 || modX == 15 || modZ == 0 || modZ == 15); ++ } ++ ++ /** ++ * Posts a task to be executed asynchronously ++ * @param run ++ */ ++ public static void scheduleAsyncTask(Runnable run) { ++ asyncExecutor.execute(run); ++ } ++ ++ @Nonnull ++ public static WorldServer getNMSWorld(@Nonnull org.bukkit.World world) { ++ return ((CraftWorld) world).getHandle(); ++ } ++ ++ public static WorldServer getNMSWorld(@Nonnull org.bukkit.entity.Entity entity) { ++ return getNMSWorld(entity.getWorld()); ++ } ++ ++ public static RayTrace.FluidCollisionOption getNMSFluidCollisionOption(TargetBlockInfo.FluidMode fluidMode) { ++ if (fluidMode == TargetBlockInfo.FluidMode.NEVER) { ++ return RayTrace.FluidCollisionOption.NONE; ++ } ++ if (fluidMode == TargetBlockInfo.FluidMode.SOURCE_ONLY) { ++ return RayTrace.FluidCollisionOption.SOURCE_ONLY; ++ } ++ if (fluidMode == TargetBlockInfo.FluidMode.ALWAYS) { ++ return RayTrace.FluidCollisionOption.ANY; ++ } ++ return null; ++ } ++ ++ public static BlockFace toBukkitBlockFace(EnumDirection enumDirection) { ++ switch (enumDirection) { ++ case DOWN: ++ return BlockFace.DOWN; ++ case UP: ++ return BlockFace.UP; ++ case NORTH: ++ return BlockFace.NORTH; ++ case SOUTH: ++ return BlockFace.SOUTH; ++ case WEST: ++ return BlockFace.WEST; ++ case EAST: ++ return BlockFace.EAST; ++ default: ++ return null; ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 6d843bb69b1848ae77098dc3f45d85f405fc24cd..5ce0dfade68257b51ad4a19a829e1fc0a0bbc3db 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -884,6 +884,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant public + private final LightEngineThreaded lightEngine; + private final ChunkProviderServer.a serverThreadQueue; + public final PlayerChunkMap playerChunkMap; +@@ -62,6 +63,158 @@ public class ChunkProviderServer extends IChunkProvider { + private final IChunkAccess[] cacheChunk = new IChunkAccess[4]; + @Nullable + private SpawnerCreature.d p; ++ // Paper start ++ final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock(); ++ final Long2ObjectOpenHashMap loadedChunkMap = new Long2ObjectOpenHashMap<>(8192, 0.5f); ++ ++ private final Chunk[] lastLoadedChunks = new Chunk[4 * 4]; ++ ++ private static int getChunkCacheKey(int x, int z) { ++ return x & 3 | ((z & 3) << 2); ++ } ++ ++ public void addLoadedChunk(Chunk chunk) { ++ this.loadedChunkMapSeqLock.acquireWrite(); ++ try { ++ this.loadedChunkMap.put(chunk.coordinateKey, chunk); ++ } finally { ++ this.loadedChunkMapSeqLock.releaseWrite(); ++ } ++ ++ // rewrite cache if we have to ++ // we do this since we also cache null chunks ++ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); ++ ++ this.lastLoadedChunks[cacheKey] = chunk; ++ } ++ ++ public void removeLoadedChunk(Chunk chunk) { ++ this.loadedChunkMapSeqLock.acquireWrite(); ++ try { ++ this.loadedChunkMap.remove(chunk.coordinateKey); ++ } finally { ++ this.loadedChunkMapSeqLock.releaseWrite(); ++ } ++ ++ // rewrite cache if we have to ++ // we do this since we also cache null chunks ++ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); ++ ++ Chunk cachedChunk = this.lastLoadedChunks[cacheKey]; ++ if (cachedChunk != null && cachedChunk.coordinateKey == chunk.coordinateKey) { ++ this.lastLoadedChunks[cacheKey] = null; ++ } ++ } ++ ++ public final Chunk getChunkAtIfLoadedMainThread(int x, int z) { ++ int cacheKey = getChunkCacheKey(x, z); ++ ++ Chunk cachedChunk = this.lastLoadedChunks[cacheKey]; ++ if (cachedChunk != null && cachedChunk.locX == x & cachedChunk.locZ == z) { ++ return this.lastLoadedChunks[cacheKey]; ++ } ++ ++ long chunkKey = ChunkCoordIntPair.pair(x, z); ++ ++ cachedChunk = this.loadedChunkMap.get(chunkKey); ++ // Skipping a null check to avoid extra instructions to improve inline capability ++ this.lastLoadedChunks[cacheKey] = cachedChunk; ++ return cachedChunk; ++ } ++ ++ public final Chunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) { ++ return this.loadedChunkMap.get(ChunkCoordIntPair.pair(x, z)); ++ } ++ ++ public final Chunk getChunkAtMainThread(int x, int z) { ++ Chunk ret = this.getChunkAtIfLoadedMainThread(x, z); ++ if (ret != null) { ++ return ret; ++ } ++ return (Chunk)this.getChunkAt(x, z, ChunkStatus.FULL, true); ++ } ++ ++ private long chunkFutureAwaitCounter; ++ ++ public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.serverThread) { ++ this.serverThreadQueue.execute(() -> { ++ ChunkProviderServer.this.getEntityTickingChunkAsync(x, z, onLoad); ++ }); ++ return; ++ } ++ this.getChunkFutureAsynchronously(x, z, 31, PlayerChunk::getEntityTickingFuture, onLoad); ++ } ++ ++ public void getTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.serverThread) { ++ this.serverThreadQueue.execute(() -> { ++ ChunkProviderServer.this.getTickingChunkAsync(x, z, onLoad); ++ }); ++ return; ++ } ++ this.getChunkFutureAsynchronously(x, z, 32, PlayerChunk::getTickingFuture, onLoad); ++ } ++ ++ public void getFullChunkAsync(int x, int z, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.serverThread) { ++ this.serverThreadQueue.execute(() -> { ++ ChunkProviderServer.this.getFullChunkAsync(x, z, onLoad); ++ }); ++ return; ++ } ++ this.getChunkFutureAsynchronously(x, z, 33, PlayerChunk::getFullChunkFuture, onLoad); ++ } ++ ++ private void getChunkFutureAsynchronously(int x, int z, int ticketLevel, Function>> futureGet, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.serverThread) { ++ throw new IllegalStateException(); ++ } ++ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); ++ Long identifier = this.chunkFutureAwaitCounter++; ++ this.chunkMapDistance.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); ++ this.tickDistanceManager(); ++ ++ PlayerChunk chunk = this.playerChunkMap.getUpdatingChunk(chunkPos.pair()); ++ ++ if (chunk == null) { ++ throw new IllegalStateException("Expected playerchunk " + chunkPos + " in world '" + this.world.getWorld().getName() + "'"); ++ } ++ ++ CompletableFuture> future = futureGet.apply(chunk); ++ ++ future.whenCompleteAsync((either, throwable) -> { ++ try { ++ if (throwable != null) { ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath)throwable; ++ } ++ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "'", throwable); ++ } else if (either.right().isPresent()) { ++ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "': " + either.right().get().toString()); ++ } ++ ++ try { ++ if (onLoad != null) { ++ playerChunkMap.callbackExecutor.execute(() -> { ++ onLoad.accept(either == null ? null : either.left().orElse(null)); // indicate failure to the callback. ++ }); ++ } ++ } catch (Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ net.minecraft.server.MinecraftServer.LOGGER.fatal("Load callback for future await failed " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "'", thr); ++ return; ++ } ++ } finally { ++ // due to odd behaviour with CB unload implementation we need to have these AFTER the load callback. ++ ChunkProviderServer.this.chunkMapDistance.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); ++ ChunkProviderServer.this.chunkMapDistance.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); ++ } ++ }, this.serverThreadQueue); ++ } ++ // Paper end + + public ChunkProviderServer(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, boolean flag, WorldLoadListener worldloadlistener, Supplier supplier) { + this.world = worldserver; +@@ -123,6 +276,49 @@ public class ChunkProviderServer extends IChunkProvider { + this.cacheChunk[0] = ichunkaccess; + } + ++ // Paper start - "real" get chunk if loaded ++ // Note: Partially copied from the getChunkAt method below ++ @Nullable ++ public Chunk getChunkAtIfCachedImmediately(int x, int z) { ++ long k = ChunkCoordIntPair.pair(x, z); ++ ++ // Note: Bypass cache since we need to check ticket level, and to make this MT-Safe ++ ++ PlayerChunk playerChunk = this.getChunk(k); ++ if (playerChunk == null) { ++ return null; ++ } ++ ++ return playerChunk.getFullChunkIfCached(); ++ } ++ ++ @Nullable ++ public Chunk getChunkAtIfLoadedImmediately(int x, int z) { ++ long k = ChunkCoordIntPair.pair(x, z); ++ ++ if (Thread.currentThread() == this.serverThread) { ++ return this.getChunkAtIfLoadedMainThread(x, z); ++ } ++ ++ Chunk ret = null; ++ long readlock; ++ do { ++ readlock = this.loadedChunkMapSeqLock.acquireRead(); ++ try { ++ ret = this.loadedChunkMap.get(k); ++ } catch (Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ // re-try, this means a CME occurred... ++ continue; ++ } ++ } while (!this.loadedChunkMapSeqLock.tryReleaseRead(readlock)); ++ ++ return ret; ++ } ++ // Paper end ++ + @Nullable + @Override + public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { +@@ -405,10 +601,9 @@ public class ChunkProviderServer extends IChunkProvider { + + this.p = spawnercreature_d; + this.world.getMethodProfiler().exit(); +- List list = Lists.newArrayList(this.playerChunkMap.f()); +- +- Collections.shuffle(list); +- list.forEach((playerchunk) -> { ++ //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper ++ //Collections.shuffle(list); // Paper ++ this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... + Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); + + if (optional.isPresent()) { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 2d297902e3b0f99a3d9f64606f9edcdabecbe83a..3fa2e077912949f6ca7b14da93c2206215ebcc7e 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -224,6 +224,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public Integer clientViewDistance; + // CraftBukkit end + ++ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper ++ + public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { + super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); + this.spawnDimension = World.OVERWORLD; +@@ -236,6 +238,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.c(worldserver); + this.co = minecraftserver.a(this); + ++ this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper ++ + // CraftBukkit start + this.displayName = this.getName(); + this.canPickUpLoot = true; +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index 254953c1d8ad80173bcc9ed703bacaf32ca89c9a..7dea5e783ce2a1f8ddd2b3ab7a19e03a56c36ba1 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -46,9 +46,9 @@ public class PlayerChunk { + private static final List CHUNK_STATUSES = ChunkStatus.a(); + private static final PlayerChunk.State[] CHUNK_STATES = PlayerChunk.State.values(); + private final AtomicReferenceArray>> statusFutures; +- private volatile CompletableFuture> fullChunkFuture; +- private volatile CompletableFuture> tickingFuture; +- private volatile CompletableFuture> entityTickingFuture; ++ private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage ++ private volatile CompletableFuture> tickingFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage ++ private volatile CompletableFuture> entityTickingFuture; private volatile boolean isEntityTickingReady; // Paper - cache chunk ticking stage + private CompletableFuture chunkSave; + public int oldTicketLevel; + private int ticketLevel; +@@ -64,6 +64,8 @@ public class PlayerChunk { + private boolean hasBeenLoaded; + private boolean x; + ++ private final PlayerChunkMap chunkMap; // Paper ++ + public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { + this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); + this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; +@@ -79,10 +81,49 @@ public class PlayerChunk { + this.ticketLevel = this.oldTicketLevel; + this.n = this.oldTicketLevel; + this.a(i); ++ this.chunkMap = (PlayerChunkMap)playerchunk_d; // Paper ++ } ++ ++ // Paper start ++ @Nullable ++ public final Chunk getEntityTickingChunk() { ++ CompletableFuture> completablefuture = this.entityTickingFuture; ++ Either either = completablefuture.getNow(null); ++ ++ return either == null ? null : either.left().orElse(null); ++ } ++ ++ @Nullable ++ public final Chunk getTickingChunk() { ++ CompletableFuture> completablefuture = this.tickingFuture; ++ Either either = completablefuture.getNow(null); ++ ++ return either == null ? null : either.left().orElse(null); ++ } ++ ++ @Nullable ++ public final Chunk getFullReadyChunk() { ++ CompletableFuture> completablefuture = this.fullChunkFuture; ++ Either either = completablefuture.getNow(null); ++ ++ return either == null ? null : either.left().orElse(null); ++ } ++ ++ public final boolean isEntityTickingReady() { ++ return this.isEntityTickingReady; ++ } ++ ++ public final boolean isTickingReady() { ++ return this.isTickingReady; ++ } ++ ++ public final boolean isFullChunkReady() { ++ return this.isFullChunkReady; + } ++ // Paper end + + // CraftBukkit start +- public Chunk getFullChunk() { ++ public final Chunk getFullChunk() { // Paper - final for inline + if (!getChunkState(this.oldTicketLevel).isAtLeast(PlayerChunk.State.BORDER)) return null; // note: using oldTicketLevel for isLoaded checks + return this.getFullChunkUnchecked(); + } +@@ -93,6 +134,14 @@ public class PlayerChunk { + return (either == null) ? null : (Chunk) either.left().orElse(null); + } + // CraftBukkit end ++ // Paper start - "real" get full chunk immediately ++ public final Chunk getFullChunkIfCached() { ++ // Note: Copied from above without ticket level check ++ CompletableFuture> statusFuture = this.getStatusFutureUnchecked(ChunkStatus.FULL); ++ Either either = (Either) statusFuture.getNow(null); ++ return either == null ? null : (Chunk) either.left().orElse(null); ++ } ++ // Paper end + + public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { + CompletableFuture> completablefuture = (CompletableFuture) this.statusFutures.get(chunkstatus.c()); +@@ -104,20 +153,23 @@ public class PlayerChunk { + return getChunkStatus(this.ticketLevel).b(chunkstatus) ? this.getStatusFutureUnchecked(chunkstatus) : PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE; + } + +- public CompletableFuture> a() { ++ public final CompletableFuture> getTickingFuture() { return this.a(); } // Paper - OBFHELPER ++ public final CompletableFuture> a() { // Paper - final for inline + return this.tickingFuture; + } + +- public CompletableFuture> b() { ++ public final CompletableFuture> getEntityTickingFuture() { return this.b(); } // Paper - OBFHELPER ++ public final CompletableFuture> b() { // Paper - final for inline + return this.entityTickingFuture; + } + +- public CompletableFuture> c() { ++ public final CompletableFuture> getFullChunkFuture() { return this.c(); } // Paper - OBFHELPER ++ public final CompletableFuture> c() { // Paper - final for inline + return this.fullChunkFuture; + } + + @Nullable +- public Chunk getChunk() { ++ public final Chunk getChunk() { // Paper - final for inline + CompletableFuture> completablefuture = this.a(); + Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error + +@@ -142,7 +194,7 @@ public class PlayerChunk { + return null; + } + +- public CompletableFuture getChunkSave() { ++ public final CompletableFuture getChunkSave() { // Paper - final for inline + return this.chunkSave; + } + +@@ -283,11 +335,11 @@ public class PlayerChunk { + }); + } + +- public ChunkCoordIntPair i() { ++ public final ChunkCoordIntPair i() { // Paper - final for inline + return this.location; + } + +- public int getTicketLevel() { ++ public final int getTicketLevel() { // Paper - final for inline + return this.ticketLevel; + } + +@@ -358,13 +410,27 @@ public class PlayerChunk { + + this.hasBeenLoaded |= flag3; + if (!flag2 && flag3) { +- this.fullChunkFuture = playerchunkmap.b(this); ++ // Paper start - cache ticking ready status ++ int expectCreateCount = ++this.fullChunkCreateCount; ++ this.fullChunkFuture = playerchunkmap.b(this); this.fullChunkFuture.thenAccept((either) -> { ++ if (either.left().isPresent() && PlayerChunk.this.fullChunkCreateCount == expectCreateCount) { ++ // note: Here is a very good place to add callbacks to logic waiting on this. ++ Chunk fullChunk = either.left().get(); ++ PlayerChunk.this.isFullChunkReady = true; ++ fullChunk.playerChunk = PlayerChunk.this; ++ ++ ++ } ++ }); ++ // Paper end + this.a(this.fullChunkFuture); + } + + if (flag2 && !flag3) { + completablefuture = this.fullChunkFuture; + this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; ++ ++this.fullChunkCreateCount; // Paper - cache ticking ready status ++ this.isFullChunkReady = false; // Paper - cache ticking ready status + this.a(((CompletableFuture>) completablefuture).thenApply((either1) -> { // CraftBukkit - decompile error + playerchunkmap.getClass(); + return either1.ifLeft(playerchunkmap::a); +@@ -375,12 +441,24 @@ public class PlayerChunk { + boolean flag5 = playerchunk_state1.isAtLeast(PlayerChunk.State.TICKING); + + if (!flag4 && flag5) { +- this.tickingFuture = playerchunkmap.a(this); ++ // Paper start - cache ticking ready status ++ this.tickingFuture = playerchunkmap.a(this); this.tickingFuture.thenAccept((either) -> { ++ if (either.left().isPresent()) { ++ // note: Here is a very good place to add callbacks to logic waiting on this. ++ Chunk tickingChunk = either.left().get(); ++ PlayerChunk.this.isTickingReady = true; ++ ++ ++ ++ ++ } ++ }); ++ // Paper end + this.a(this.tickingFuture); + } + + if (flag4 && !flag5) { +- this.tickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); ++ this.tickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isTickingReady = false; // Paper - cache chunk ticking stage + this.tickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; + } + +@@ -392,12 +470,24 @@ public class PlayerChunk { + throw (IllegalStateException) SystemUtils.c((Throwable) (new IllegalStateException())); + } + +- this.entityTickingFuture = playerchunkmap.b(this.location); ++ // Paper start - cache ticking ready status ++ this.entityTickingFuture = playerchunkmap.b(this.location); this.entityTickingFuture.thenAccept((either) -> { ++ if (either.left().isPresent()) { ++ // note: Here is a very good place to add callbacks to logic waiting on this. ++ Chunk entityTickingChunk = either.left().get(); ++ PlayerChunk.this.isEntityTickingReady = true; ++ ++ ++ ++ ++ } ++ }); ++ // Paper end + this.a(this.entityTickingFuture); + } + + if (flag6 && !flag7) { +- this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); ++ this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage + this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; + } + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 565aa1690d5427f5059ab117c4c15b0754e8830b..19856555793f742abb1178ede72dea5623f0e383 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -54,6 +54,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; + import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; + import net.minecraft.network.protocol.game.PacketPlayOutMount; + import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.progress.WorldLoadListener; + import net.minecraft.util.CSVWriter; + import net.minecraft.util.EntitySlice; +@@ -146,6 +147,26 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + }; + // CraftBukkit end + ++ // Paper start - distance maps ++ private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); ++ ++ void addPlayerToDistanceMaps(EntityPlayer player) { ++ int chunkX = MCUtil.getChunkCoordinate(player.locX()); ++ int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); ++ // Note: players need to be explicitly added to distance maps before they can be updated ++ } ++ ++ void removePlayerFromDistanceMaps(EntityPlayer player) { ++ ++ } ++ ++ void updateMaps(EntityPlayer player) { ++ int chunkX = MCUtil.getChunkCoordinate(player.locX()); ++ int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); ++ // Note: players need to be explicitly added to distance maps before they can be updated ++ } ++ // Paper end ++ + public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { + super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag); + this.visibleChunks = this.updatingChunks.clone(); +@@ -235,6 +256,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + }; + } + ++ // Paper start ++ public final int getEffectiveViewDistance() { ++ // TODO this needs to be checked on update ++ // Mojang currently sets it to +1 of the configured view distance. So subtract one to get the one we really want. ++ return this.viewDistance - 1; ++ } ++ // Paper end ++ + private CompletableFuture, PlayerChunk.Failure>> a(ChunkCoordIntPair chunkcoordintpair, int i, IntFunction intfunction) { + List>> list = Lists.newArrayList(); + int j = chunkcoordintpair.x; +@@ -953,6 +982,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + if (!flag1) { + this.chunkDistanceManager.a(SectionPosition.a((Entity) entityplayer), entityplayer); + } ++ this.addPlayerToDistanceMaps(entityplayer); // Paper - distance maps + } else { + SectionPosition sectionposition = entityplayer.O(); + +@@ -960,6 +990,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + if (!flag2) { + this.chunkDistanceManager.b(sectionposition, entityplayer); + } ++ this.removePlayerFromDistanceMaps(entityplayer); // Paper - distance maps + } + + for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { +@@ -1070,6 +1101,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + } + ++ this.updateMaps(entityplayer); // Paper - distance maps ++ + } + + @Override +diff --git a/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java b/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java +index 91d9e6b554964e1f4dd67deea220a738f2715aee..04006caeeb42b523d986efc313828557854718d7 100644 +--- a/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java ++++ b/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java +@@ -141,6 +141,26 @@ public class RegionLimitedWorldAccess implements GeneratorAccessSeed { + return i >= this.n.x && i <= this.o.x && j >= this.n.z && j <= this.o.z; + } + ++ // Paper start - if loaded util ++ @Nullable ++ @Override ++ public IChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ return this.getChunkAt(x, z, ChunkStatus.FULL, false); ++ } ++ ++ @Override ++ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { ++ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getType(blockposition); ++ } ++ ++ @Override ++ public Fluid getFluidIfLoaded(BlockPosition blockposition) { ++ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getFluid(blockposition); ++ } ++ // Paper end ++ + @Override + public IBlockData getType(BlockPosition blockposition) { + return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4).getType(blockposition); +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index 9cae7fed34df3ff81d75105b2fcbc4510f2a0e71..285a03b57431bd6a4d26bb84e916d2c6e1eb0213 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -25,6 +25,7 @@ public class TicketType { + public static final TicketType UNKNOWN = a("unknown", Comparator.comparingLong(ChunkCoordIntPair::pair), 1); + public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit + public static final TicketType PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit ++ public static final TicketType FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper + + public static TicketType a(String s, Comparator comparator) { + return new TicketType<>(s, comparator, 0L); +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 7f9a1d64d123ce54608497a0e0a37d161d8c9d3c..780e541b8d594a8a6dc3a8626a82218f2502a5c7 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -12,6 +12,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry; + import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.longs.LongSets; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; + import java.io.BufferedWriter; +@@ -169,7 +170,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + private final Map entitiesByUUID = Maps.newHashMap(); + private final Queue entitiesToAdd = Queues.newArrayDeque(); + private final List players = Lists.newArrayList(); +- private final ChunkProviderServer chunkProvider; ++ public final ChunkProviderServer chunkProvider; // Paper - public + boolean tickingEntities; + private final MinecraftServer server; + public final WorldDataServer worldDataServer; // CraftBukkit - type +@@ -1688,7 +1689,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + ObjectIterator objectiterator = spawnercreature_d.b().object2IntEntrySet().iterator(); + + while (objectiterator.hasNext()) { +- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); ++ Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix + + bufferedwriter.write(String.format("spawn_count.%s: %d\n", ((EnumCreatureType) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey()).b(), it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue())); + } +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 5ce4b27b329c242f48fd3b24c32403281895bda5..265004691f12b3476f3892f5555768717e9c6d19 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -220,9 +220,9 @@ public class PlayerConnection implements PacketListenerPlayIn { + private final MinecraftServer minecraftServer; + public EntityPlayer player; + private int e; +- private long lastKeepAlive; +- private boolean awaitingKeepAlive; +- private long h; ++ private long lastKeepAlive; private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER ++ private boolean awaitingKeepAlive; private void setPendingPing(boolean isPending) { this.awaitingKeepAlive = isPending;}; private boolean isPendingPing() { return this.awaitingKeepAlive;}; // Paper - OBFHELPER ++ private long h; private void setKeepAliveID(long keepAliveID) { this.h = keepAliveID;}; private long getKeepAliveID() {return this.h; }; // Paper - OBFHELPER + // CraftBukkit start - multithreaded fields + private volatile int chatThrottle; + private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); +diff --git a/src/main/java/net/minecraft/util/DataBits.java b/src/main/java/net/minecraft/util/DataBits.java +index 54974a941a334dc0c8e62ffb8ca094772888b8fa..0c0576c8730069fb5364d8383dec8ab7e698658d 100644 +--- a/src/main/java/net/minecraft/util/DataBits.java ++++ b/src/main/java/net/minecraft/util/DataBits.java +@@ -84,6 +84,7 @@ public class DataBits { + return (int) (k >> l & this.d); + } + ++ public final long[] getDataBits() { return this.a(); } // Paper - OBFHELPER + public long[] a() { + return this.b; + } +diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java +index 2b2c03ab62816f3d21ef953c4a45f55e3997cca6..e5641f2b41d89a57285fc072a48b951aa03a14a7 100644 +--- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java ++++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java +@@ -68,6 +68,15 @@ public abstract class IAsyncTaskHandler implements Mailbox entitytypes, World world) { + super(entitytypes, world); + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index b91bb7f562d5c43ec1d0d88ba417e43b07dbf0f3..dbfcdc3cc7c1dccf785f5e13634e84c5af088985 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -225,6 +225,7 @@ public abstract class EntityInsentient extends EntityLiving { + return this.goalTarget; + } + ++ public org.bukkit.craftbukkit.entity.CraftMob getBukkitMob() { return (org.bukkit.craftbukkit.entity.CraftMob) super.getBukkitEntity(); } // Paper + public void setGoalTarget(@Nullable EntityLiving entityliving) { + // CraftBukkit start - fire event + setGoalTarget(entityliving, EntityTargetEvent.TargetReason.UNKNOWN, true); +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 4e5f16882b4cef33411ed2bbe2b2ca67073e4f04..f88c3dfecdce58fbdb695103fd481e9cbd0c266c 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -231,6 +231,7 @@ public abstract class EntityLiving extends Entity { + public boolean collides = true; + public Set collidableExemptions = new HashSet<>(); + public boolean canPickUpLoot; ++ public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper + + @Override + public float getBukkitYaw() { +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index a32bc63ff1960bdb874d546ee42633063834da24..ac57ab9992e141c91cf48f033148ad78433b364c 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -3,6 +3,7 @@ package net.minecraft.world.entity; + import com.google.common.collect.ImmutableSet; + import java.util.Optional; + import java.util.Set; // Paper ++import java.util.Map; // Paper + import java.util.UUID; + import java.util.function.Function; + import java.util.stream.Stream; +@@ -441,8 +442,8 @@ public class EntityTypes { + return this.br.height; + } + +- @Nullable +- public T a(World world) { ++ public T create(World world) { return this.a(world); } // Paper - OBFHELPER ++ @Nullable public T a(World world) { // Paper - OBFHELPER + return this.bf.create(this, world); + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java b/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java +index acebee991eca1e19fc1094718dc40822b66756e1..c484e27650364b6537fe6b2e8e14de98382b86a3 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java +@@ -27,6 +27,7 @@ import net.minecraft.world.level.WorldAccess; + + public abstract class EntityMonster extends EntityCreature implements IMonster { + ++ public org.bukkit.craftbukkit.entity.CraftMonster getBukkitMonster() { return (org.bukkit.craftbukkit.entity.CraftMonster) super.getBukkitEntity(); } // Paper + protected EntityMonster(EntityTypes entitytypes, World world) { + super(entitytypes, world); + this.f = 5; +diff --git a/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java b/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java +index 97db41acf626eec3e587964d0e73c370e5695bf0..2df3ae0b72ccb5f816d55fed15396ba5a1affb7f 100644 +--- a/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java ++++ b/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java +@@ -38,7 +38,7 @@ public class PlayerInventory implements IInventory, INamableTileEntity { + public final NonNullList items; + public final NonNullList armor; + public final NonNullList extraSlots; +- private final List> f; ++ private final List> f; public final List> getComponents() { return f; } // Paper - OBFHELPER + public int itemInHandIndex; + public final EntityHuman player; + private ItemStack carried; +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index dee2714cd9fc930a1a13e97d752ab2df39cd31ed..4010152dccc93019f2e7f284d80b92bae0d91c34 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -103,7 +103,7 @@ public final class ItemStack { + })).apply(instance, ItemStack::new); + }); + private static final Logger LOGGER = LogManager.getLogger(); +- public static final ItemStack b = new ItemStack((Item) null); ++ public static final ItemStack b = new ItemStack((Item) null);public static final ItemStack NULL_ITEM = b; // Paper - OBFHELPER + public static final DecimalFormat c = (DecimalFormat) SystemUtils.a((new DecimalFormat("#.##")), (decimalformat) -> { // CraftBukkit - decompile error + decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); + }); +@@ -660,6 +660,24 @@ public final class ItemStack { + return this.tag != null ? this.tag.getList("Enchantments", 10) : new NBTTagList(); + } + ++ // Paper start - (this is just a good no conflict location) ++ public org.bukkit.inventory.ItemStack asBukkitMirror() { ++ return CraftItemStack.asCraftMirror(this); ++ } ++ public org.bukkit.inventory.ItemStack asBukkitCopy() { ++ return CraftItemStack.asCraftMirror(this.cloneItemStack()); ++ } ++ public static ItemStack fromBukkitCopy(org.bukkit.inventory.ItemStack itemstack) { ++ return CraftItemStack.asNMSCopy(itemstack); ++ } ++ private org.bukkit.craftbukkit.inventory.CraftItemStack bukkitStack; ++ public org.bukkit.inventory.ItemStack getBukkitStack() { ++ if (bukkitStack == null || bukkitStack.getHandle() != this) { ++ bukkitStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this); ++ } ++ return bukkitStack; ++ } ++ // Paper end + public void setTag(@Nullable NBTTagCompound nbttagcompound) { + this.tag = nbttagcompound; + if (this.getItem().usesDurability()) { +@@ -758,6 +776,7 @@ public final class ItemStack { + return this.tag != null && this.tag.hasKeyOfType("Enchantments", 9) ? !this.tag.getList("Enchantments", 10).isEmpty() : false; + } + ++ public void getOrCreateTagAndSet(String s, NBTBase nbtbase) { a(s, nbtbase);} // Paper - OBFHELPER + public void a(String s, NBTBase nbtbase) { + this.getOrCreateTag().set(s, nbtbase); + } +@@ -843,6 +862,7 @@ public final class ItemStack { + // CraftBukkit start + @Deprecated + public void setItem(Item item) { ++ this.bukkitStack = null; // Paper + this.item = item; + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java b/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java +index daad63e731008eddccd3f51418a2a9b2d587f77b..795bc60a73e1e628590803fd515ffb78302d4f97 100644 +--- a/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java ++++ b/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java +@@ -121,6 +121,7 @@ public class PotionUtil { + return nbttagcompound == null ? Potions.EMPTY : PotionRegistry.a(nbttagcompound.getString("Potion")); + } + ++ public static ItemStack addPotionToItemStack(ItemStack itemstack, PotionRegistry potionregistry) { return a(itemstack, potionregistry); } // Paper - OBFHELPER + public static ItemStack a(ItemStack itemstack, PotionRegistry potionregistry) { + MinecraftKey minecraftkey = IRegistry.POTION.getKey(potionregistry); + +diff --git a/src/main/java/net/minecraft/world/level/BlockAccessAir.java b/src/main/java/net/minecraft/world/level/BlockAccessAir.java +index 5f8022745f709b6d542182d2ac94147aefdd3f0f..543b13c1e43135c044f834c2a6231e174536b623 100644 +--- a/src/main/java/net/minecraft/world/level/BlockAccessAir.java ++++ b/src/main/java/net/minecraft/world/level/BlockAccessAir.java +@@ -20,6 +20,18 @@ public enum BlockAccessAir implements IBlockAccess { + return null; + } + ++ // Paper start - If loaded util ++ @Override ++ public Fluid getFluidIfLoaded(BlockPosition blockposition) { ++ return this.getFluid(blockposition); ++ } ++ ++ @Override ++ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { ++ return this.getType(blockposition); ++ } ++ // Paper end ++ + @Override + public IBlockData getType(BlockPosition blockposition) { + return Blocks.AIR.getBlockData(); +diff --git a/src/main/java/net/minecraft/world/level/ChunkCache.java b/src/main/java/net/minecraft/world/level/ChunkCache.java +index 8541e87a34612e8bc86cf5c291164e091641d1af..7a760ef0264c9041c38bdfb8fd31333052c26139 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkCache.java ++++ b/src/main/java/net/minecraft/world/level/ChunkCache.java +@@ -4,6 +4,7 @@ import java.util.function.Predicate; + import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPosition; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.TileEntity; +@@ -23,7 +24,7 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { + protected final int b; + protected final IChunkAccess[][] c; + protected boolean d; +- protected final World e; ++ protected final World e; protected final World getWorld() { return e; } // Paper - OBFHELPER + + public ChunkCache(World world, BlockPosition blockposition, BlockPosition blockposition1) { + this.e = world; +@@ -42,7 +43,7 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { + + for (k = this.a; k <= i; ++k) { + for (l = this.b; l <= j; ++l) { +- this.c[k - this.a][l - this.b] = ichunkprovider.a(k, l); ++ this.c[k - this.a][l - this.b] = ((WorldServer)world).getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(k, l); // Paper + } + } + +@@ -67,7 +68,7 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { + int k = i - this.a; + int l = j - this.b; + +- if (k >= 0 && k < this.c.length && l >= 0 && l < this.c[k].length) { ++ if (k >= 0 && k < this.c.length && l >= 0 && l < this.c[k].length) { // Paper - if this changes, update getChunkIfLoaded below + IChunkAccess ichunkaccess = this.c[k][l]; + + return (IChunkAccess) (ichunkaccess != null ? ichunkaccess : new ChunkEmpty(this.e, new ChunkCoordIntPair(i, j))); +@@ -86,6 +87,29 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { + return this.a(i, j); + } + ++ // Paper start - if loaded util ++ private IChunkAccess getChunkIfLoaded(int x, int z) { ++ int k = x - this.a; ++ int l = z - this.b; ++ ++ if (k >= 0 && k < this.c.length && l >= 0 && l < this.c[k].length) { ++ return this.c[k][l]; ++ } ++ return null; ++ } ++ @Override ++ public Fluid getFluidIfLoaded(BlockPosition blockposition) { ++ IChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getFluid(blockposition); ++ } ++ ++ @Override ++ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { ++ IChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getType(blockposition); ++ } ++ // Paper end ++ + @Nullable + @Override + public TileEntity getTileEntity(BlockPosition blockposition) { +diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java +index 14e55bf842e928d1e8e2137f9efdef0f7c336362..9a88791be443a5b18934e7d752aee6dcdb8aa38f 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java ++++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java +@@ -12,27 +12,32 @@ public class ChunkCoordIntPair { + public static final long a = pair(1875016, 1875016); + public final int x; + public final int z; ++ public final long longKey; // Paper + + public ChunkCoordIntPair(int i, int j) { + this.x = i; + this.z = j; ++ this.longKey = pair(this.x, this.z); // Paper + } + + public ChunkCoordIntPair(BlockPosition blockposition) { + this.x = blockposition.getX() >> 4; + this.z = blockposition.getZ() >> 4; ++ this.longKey = pair(this.x, this.z); // Paper + } + + public ChunkCoordIntPair(long i) { + this.x = (int) i; + this.z = (int) (i >> 32); ++ this.longKey = pair(this.x, this.z); // Paper + } + + public long pair() { +- return pair(this.x, this.z); ++ return longKey; // Paper + } + +- public static long pair(int i, int j) { ++ public static long pair(final BlockPosition pos) { return pair(pos.getX() >> 4, pos.getZ() >> 4); } // Paper - OBFHELPER ++ public static long pair(int i, int j) { + return (long) i & 4294967295L | ((long) j & 4294967295L) << 32; + } + +diff --git a/src/main/java/net/minecraft/world/level/IBlockAccess.java b/src/main/java/net/minecraft/world/level/IBlockAccess.java +index 25e50b57f42dde156443480d73c6c9985df6f0c6..e799765ecfada1eec78beb71651e52ad355a30aa 100644 +--- a/src/main/java/net/minecraft/world/level/IBlockAccess.java ++++ b/src/main/java/net/minecraft/world/level/IBlockAccess.java +@@ -8,9 +8,11 @@ import javax.annotation.Nullable; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; + import net.minecraft.util.MathHelper; ++import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.entity.TileEntity; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluid; ++import net.minecraft.world.level.material.Material; + import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.Vec3D; +@@ -22,6 +24,19 @@ public interface IBlockAccess { + TileEntity getTileEntity(BlockPosition blockposition); + + IBlockData getType(BlockPosition blockposition); ++ // Paper start - if loaded util ++ IBlockData getTypeIfLoaded(BlockPosition blockposition); ++ default Material getMaterialIfLoaded(BlockPosition blockposition) { ++ IBlockData type = this.getTypeIfLoaded(blockposition); ++ return type == null ? null : type.getMaterial(); ++ } ++ ++ default Block getBlockIfLoaded(BlockPosition blockposition) { ++ IBlockData type = this.getTypeIfLoaded(blockposition); ++ return type == null ? null : type.getBlock(); ++ } ++ Fluid getFluidIfLoaded(BlockPosition blockposition); ++ // Paper end + + Fluid getFluid(BlockPosition blockposition); + +diff --git a/src/main/java/net/minecraft/world/level/IWorldReader.java b/src/main/java/net/minecraft/world/level/IWorldReader.java +index d3d33e77ce09d485552076c5ab6faf08a16d90db..5f12b290d59e0b5e843d644bf7f608a946ef02c0 100644 +--- a/src/main/java/net/minecraft/world/level/IWorldReader.java ++++ b/src/main/java/net/minecraft/world/level/IWorldReader.java +@@ -18,6 +18,7 @@ import net.minecraft.world.phys.AxisAlignedBB; + + public interface IWorldReader extends IBlockLightAccess, ICollisionAccess, BiomeManager.Provider { + ++ @Nullable IChunkAccess getChunkIfLoadedImmediately(int x, int z); // Paper - ifLoaded api (we need this since current impl blocks if the chunk is loading) + @Nullable + IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag); + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index f794113e7cc5809d1da0c85648fb7311fb633f40..0cbebc2095489c240fecd3fd32f5373be2a3d684 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -74,6 +74,7 @@ import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.block.CapturedBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockState; + import org.bukkit.craftbukkit.block.data.CraftBlockData; + import org.bukkit.event.block.BlockPhysicsEvent; + // CraftBukkit end +@@ -255,17 +256,50 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return i < 0 || i >= 256; + } + +- public Chunk getChunkAtWorldCoords(BlockPosition blockposition) { ++ public final Chunk getChunkAtWorldCoords(BlockPosition blockposition) { // Paper - help inline + return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); + } + + @Override +- public Chunk getChunkAt(int i, int j) { +- return (Chunk) this.getChunkAt(i, j, ChunkStatus.FULL); ++ public final Chunk getChunkAt(int i, int j) { // Paper - final to help inline ++ return (Chunk) this.getChunkAt(i, j, ChunkStatus.FULL, true); // Paper - avoid a method jump ++ } ++ ++ // Paper start - if loaded ++ @Nullable ++ @Override ++ public final IChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ return ((WorldServer)this).chunkProvider.getChunkAtIfLoadedImmediately(x, z); + } + + @Override +- public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { ++ public final IBlockData getTypeIfLoaded(BlockPosition blockposition) { ++ // CraftBukkit start - tree generation ++ if (captureTreeGeneration) { ++ CraftBlockState previous = capturedBlockStates.get(blockposition); ++ if (previous != null) { ++ return previous.getHandle(); ++ } ++ } ++ // CraftBukkit end ++ if (!isValidLocation(blockposition)) { ++ return Blocks.AIR.getBlockData(); ++ } ++ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ ++ return chunk == null ? null : chunk.getType(blockposition); ++ } ++ ++ @Override ++ public Fluid getFluidIfLoaded(BlockPosition blockposition) { ++ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ ++ return chunk == null ? null : chunk.getFluid(blockposition); ++ } ++ // Paper end ++ ++ @Override ++ public final IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { // Paper - final for inline + IChunkAccess ichunkaccess = this.getChunkProvider().getChunkAt(i, j, chunkstatus, flag); + + if (ichunkaccess == null && flag) { +@@ -276,7 +310,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + } + + @Override +- public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) { ++ public final boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) { // Paper - final for inline + return this.a(blockposition, iblockdata, i, 512); + } + +@@ -422,8 +456,9 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + public void a(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1) {} + +- @Override +- public boolean a(BlockPosition blockposition, boolean flag) { ++ public boolean setAir(BlockPosition blockposition) { return this.a(blockposition, false); } // Paper - OBFHELPER ++ public boolean setAir(BlockPosition blockposition, boolean moved) { return this.a(blockposition, moved); } // Paper - OBFHELPER ++ @Override public boolean a(BlockPosition blockposition, boolean flag) { // Paper - OBFHELPER + Fluid fluid = this.getFluid(blockposition); + + return this.setTypeAndData(blockposition, fluid.getBlockData(), 3 | (flag ? 64 : 0)); +@@ -569,7 +604,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + if (isOutsideWorld(blockposition)) { + return Blocks.VOID_AIR.getBlockData(); + } else { +- Chunk chunk = this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ Chunk chunk = (Chunk) this.getChunkProvider().getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, true); // Paper - manually inline to reduce hops and avoid unnecessary null check to reduce total byte code size, this should never return null and if it does we will see it the next line but the real stack trace will matter in the chunk engine + + return chunk.getType(blockposition); + } +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +index ef652d8f3eb7371c9ddfc3afe67fd1bd669a77c0..2902117fd2803741b053a04fda7f4414fb8593cb 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +@@ -688,6 +688,7 @@ public abstract class BlockBase { + return this.a != null ? this.a.d : Block.a(this.getCollisionShape(iblockaccess, blockposition)); + } + ++ public final IBlockData getBlockData() { return p(); } // Paper - OBFHELPER + protected abstract IBlockData p(); + + public boolean isRequiresSpecialTool() { +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index 79f645ff1b6274bbdf5dc3f96a762b3b63397c82..2bb03f1cb9671a7754a68059219f783d4508eeb9 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -47,6 +47,7 @@ public class WorldBorder { + return this.b(entity.locX(), entity.locZ()); + } + ++ public final VoxelShape asVoxelShape(){ return c();} // Paper - OBFHELPER + public VoxelShape c() { + return this.j.m(); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index 4561cf94fe1dce51abad0ac8635749ed87c8b307..b15200c2a3923bd8be2ee5e73fdadfeea3e3a8dc 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -60,7 +60,7 @@ public class Chunk implements IChunkAccess { + + private static final Logger LOGGER = LogManager.getLogger(); + @Nullable +- public static final ChunkSection a = null; ++ public static final ChunkSection a = null; public static final ChunkSection EMPTY_CHUNK_SECTION = a; // Paper - OBFHELPER + private final ChunkSection[] sections; + private BiomeStorage d; + private final Map e; +@@ -83,7 +83,7 @@ public class Chunk implements IChunkAccess { + private Supplier u; + @Nullable + private Consumer v; +- private final ChunkCoordIntPair loc; ++ private final ChunkCoordIntPair loc; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key + private volatile boolean x; + + public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage) { +@@ -100,7 +100,8 @@ public class Chunk implements IChunkAccess { + this.n = new ShortList[16]; + this.entitySlices = (List[]) (new List[16]); // Spigot + this.world = (WorldServer) world; // CraftBukkit - type +- this.loc = chunkcoordintpair; ++ this.locX = chunkcoordintpair.x; this.locZ = chunkcoordintpair.z; // Paper - reduce need for field look ups ++ this.loc = chunkcoordintpair; this.coordinateKey = ChunkCoordIntPair.pair(locX, locZ); // Paper - cache long key + this.i = chunkconverter; + HeightMap.Type[] aheightmap_type = HeightMap.Type.values(); + int j = aheightmap_type.length; +@@ -146,6 +147,110 @@ public class Chunk implements IChunkAccess { + public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY); + // CraftBukkit end + ++ // Paper start ++ public final com.destroystokyo.paper.util.maplist.EntityList entities = new com.destroystokyo.paper.util.maplist.EntityList(); ++ public PlayerChunk playerChunk; ++ ++ static final int NEIGHBOUR_CACHE_RADIUS = 3; ++ public static int getNeighbourCacheRadius() { ++ return NEIGHBOUR_CACHE_RADIUS; ++ } ++ ++ boolean loadedTicketLevel; ++ private long neighbourChunksLoadedBitset; ++ private final Chunk[] loadedNeighbourChunks = new Chunk[(NEIGHBOUR_CACHE_RADIUS * 2 + 1) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)]; ++ ++ private static int getNeighbourIndex(final int relativeX, final int relativeZ) { ++ // index = (relativeX + NEIGHBOUR_CACHE_RADIUS) + (relativeZ + NEIGHBOUR_CACHE_RADIUS) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1) ++ // optimised variant of the above by moving some of the ops to compile time ++ return relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))); ++ } ++ ++ public final Chunk getRelativeNeighbourIfLoaded(final int relativeX, final int relativeZ) { ++ return this.loadedNeighbourChunks[getNeighbourIndex(relativeX, relativeZ)]; ++ } ++ ++ public final boolean isNeighbourLoaded(final int relativeX, final int relativeZ) { ++ return (this.neighbourChunksLoadedBitset & (1L << getNeighbourIndex(relativeX, relativeZ))) != 0; ++ } ++ ++ public final void setNeighbourLoaded(final int relativeX, final int relativeZ, final Chunk chunk) { ++ if (chunk == null) { ++ throw new IllegalArgumentException("Chunk must be non-null, neighbour: (" + relativeX + "," + relativeZ + "), chunk: " + this.loc); ++ } ++ final long before = this.neighbourChunksLoadedBitset; ++ final int index = getNeighbourIndex(relativeX, relativeZ); ++ this.loadedNeighbourChunks[index] = chunk; ++ this.neighbourChunksLoadedBitset |= (1L << index); ++ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); ++ } ++ ++ public final void setNeighbourUnloaded(final int relativeX, final int relativeZ) { ++ final long before = this.neighbourChunksLoadedBitset; ++ final int index = getNeighbourIndex(relativeX, relativeZ); ++ this.loadedNeighbourChunks[index] = null; ++ this.neighbourChunksLoadedBitset &= ~(1L << index); ++ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); ++ } ++ ++ public final void resetNeighbours() { ++ final long before = this.neighbourChunksLoadedBitset; ++ this.neighbourChunksLoadedBitset = 0L; ++ java.util.Arrays.fill(this.loadedNeighbourChunks, null); ++ this.onNeighbourChange(before, 0L); ++ } ++ ++ protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { ++ ++ } ++ ++ public final boolean isAnyNeighborsLoaded() { ++ return neighbourChunksLoadedBitset != 0; ++ } ++ public final boolean areNeighboursLoaded(final int radius) { ++ return Chunk.areNeighboursLoaded(this.neighbourChunksLoadedBitset, radius); ++ } ++ ++ public static boolean areNeighboursLoaded(final long bitset, final int radius) { ++ // index = relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))) ++ switch (radius) { ++ case 0: { ++ return (bitset & (1L << getNeighbourIndex(0, 0))) != 0; ++ } ++ case 1: { ++ long mask = 0L; ++ for (int dx = -1; dx <= 1; ++dx) { ++ for (int dz = -1; dz <= 1; ++dz) { ++ mask |= (1L << getNeighbourIndex(dx, dz)); ++ } ++ } ++ return (bitset & mask) == mask; ++ } ++ case 2: { ++ long mask = 0L; ++ for (int dx = -2; dx <= 2; ++dx) { ++ for (int dz = -2; dz <= 2; ++dz) { ++ mask |= (1L << getNeighbourIndex(dx, dz)); ++ } ++ } ++ return (bitset & mask) == mask; ++ } ++ case 3: { ++ long mask = 0L; ++ for (int dx = -3; dx <= 3; ++dx) { ++ for (int dz = -3; dz <= 3; ++dz) { ++ mask |= (1L << getNeighbourIndex(dx, dz)); ++ } ++ } ++ return (bitset & mask) == mask; ++ } ++ ++ default: ++ throw new IllegalArgumentException("Radius not recognized: " + radius); ++ } ++ } ++ // Paper end ++ + public Chunk(World world, ProtoChunk protochunk) { + this(world, protochunk.getPos(), protochunk.getBiomeIndex(), protochunk.p(), protochunk.n(), protochunk.o(), protochunk.getInhabitedTime(), protochunk.getSections(), (Consumer) null); + Iterator iterator = protochunk.y().iterator(); +@@ -251,6 +356,18 @@ public class Chunk implements IChunkAccess { + } + } + ++ // Paper start - If loaded util ++ @Override ++ public Fluid getFluidIfLoaded(BlockPosition blockposition) { ++ return this.getFluid(blockposition); ++ } ++ ++ @Override ++ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { ++ return this.getType(blockposition); ++ } ++ // Paper end ++ + @Override + public Fluid getFluid(BlockPosition blockposition) { + return this.a(blockposition.getX(), blockposition.getY(), blockposition.getZ()); +@@ -391,6 +508,7 @@ public class Chunk implements IChunkAccess { + entity.chunkX = this.loc.x; + entity.chunkY = k; + entity.chunkZ = this.loc.z; ++ this.entities.add(entity); // Paper - per chunk entity list + this.entitySlices[k].add(entity); + } + +@@ -414,6 +532,7 @@ public class Chunk implements IChunkAccess { + } + + this.entitySlices[i].remove(entity); ++ this.entities.remove(entity); // Paper + } + + @Override +@@ -435,6 +554,7 @@ public class Chunk implements IChunkAccess { + return this.a(blockposition, Chunk.EnumTileEntityState.CHECK); + } + ++ @Nullable public final TileEntity getTileEntityImmediately(BlockPosition pos) { return this.a(pos, EnumTileEntityState.IMMEDIATE); } // Paper - OBFHELPER + @Nullable + public TileEntity a(BlockPosition blockposition, Chunk.EnumTileEntityState chunk_enumtileentitystate) { + // CraftBukkit start +@@ -546,7 +666,25 @@ public class Chunk implements IChunkAccess { + + // CraftBukkit start + public void loadCallback() { ++ // Paper start - neighbour cache ++ int chunkX = this.loc.x; ++ int chunkZ = this.loc.z; ++ ChunkProviderServer chunkProvider = ((WorldServer)this.world).getChunkProvider(); ++ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { ++ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { ++ Chunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); ++ if (neighbour != null) { ++ neighbour.setNeighbourLoaded(-dx, -dz, this); ++ // should be in cached already ++ this.setNeighbourLoaded(dx, dz, neighbour); ++ } ++ } ++ } ++ this.setNeighbourLoaded(0, 0, this); ++ this.loadedTicketLevel = true; ++ // Paper end - neighbour cache + org.bukkit.Server server = this.world.getServer(); ++ ((WorldServer)this.world).getChunkProvider().addLoadedChunk(this); // Paper + if (server != null) { + /* + * If it's a new world, the first few chunks are generated inside +@@ -585,6 +723,22 @@ public class Chunk implements IChunkAccess { + server.getPluginManager().callEvent(unloadEvent); + // note: saving can be prevented, but not forced if no saving is actually required + this.mustNotSave = !unloadEvent.isSaveChunk(); ++ ((WorldServer)this.world).getChunkProvider().removeLoadedChunk(this); // Paper ++ // Paper start - neighbour cache ++ int chunkX = this.loc.x; ++ int chunkZ = this.loc.z; ++ ChunkProviderServer chunkProvider = ((WorldServer)this.world).getChunkProvider(); ++ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { ++ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { ++ Chunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); ++ if (neighbour != null) { ++ neighbour.setNeighbourUnloaded(-dx, -dz); ++ } ++ } ++ } ++ this.loadedTicketLevel = false; ++ this.resetNeighbours(); ++ // Paper end + } + // CraftBukkit end + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +index cf2dd6da5ce88aafdcc4db63af18eda9396a066a..a4e2eb1a753e8fcb48982d78fe80e505bce5c476 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +@@ -139,6 +139,7 @@ public class ChunkSection { + return this.blockIds; + } + ++ public void writeChunkSection(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER + public void b(PacketDataSerializer packetdataserializer) { + packetdataserializer.writeShort(this.nonEmptyBlockCount); + this.blockIds.b(packetdataserializer); +diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPalette.java b/src/main/java/net/minecraft/world/level/chunk/DataPalette.java +index f1dd62541187d007a69087f0279508b6b18d5166..44fe0ee179eebfa6c4c0403a7f06735d7da5c773 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/DataPalette.java ++++ b/src/main/java/net/minecraft/world/level/chunk/DataPalette.java +@@ -7,10 +7,12 @@ import net.minecraft.network.PacketDataSerializer; + + public interface DataPalette { + ++ default int getOrCreateIdFor(T object) { return this.a(object); } // Paper - OBFHELPER + int a(T t0); + + boolean a(Predicate predicate); + ++ @Nullable default T getObject(int dataBits) { return this.a(dataBits); } // Paper - OBFHELPER + @Nullable + T a(int i); + +diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +index fe441146757a4ac0562d5b493fb6430e33b9ee28..e397b871b846c3a90bc75d0e1cf0683b6a3d0ca9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java ++++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +@@ -19,7 +19,7 @@ import net.minecraft.util.MathHelper; + + public class DataPaletteBlock implements DataPaletteExpandable { + +- private final DataPalette b; ++ private final DataPalette b; private final DataPalette getDataPaletteGlobal() { return this.b; } // Paper - OBFHELPER + private final DataPaletteExpandable c = (i, object) -> { + return 0; + }; +@@ -27,9 +27,9 @@ public class DataPaletteBlock implements DataPaletteExpandable { + private final Function e; + private final Function f; + private final T g; +- protected DataBits a; +- private DataPalette h; +- private int i; ++ protected DataBits a; public final DataBits getDataBits() { return this.a; } // Paper - OBFHELPER ++ private DataPalette h; private DataPalette getDataPalette() { return this.h; } // Paper - OBFHELPER ++ private int i; private int getBitsPerObject() { return this.i; } // Paper - OBFHELPER + private final ReentrantLock j = new ReentrantLock(); + + public void a() { +@@ -64,6 +64,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { + return j << 8 | k << 4 | i; + } + ++ private void initialize(int bitsPerObject) { this.b(bitsPerObject); } // Paper - OBFHELPER + private void b(int i) { + if (i != this.i) { + this.i = i; +@@ -141,6 +142,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { + return t0 == null ? this.g : t0; + } + ++ public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER + public void b(PacketDataSerializer packetdataserializer) { + this.a(); + packetdataserializer.writeByte(this.i); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index 4192d30ad2117a12a4058b48581d6cf93b50088c..7572ca53a5cca8ca5085d18c24048b85dda4daa9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -99,6 +99,18 @@ public class ProtoChunk implements IChunkAccess { + + } + ++ // Paper start - If loaded util ++ @Override ++ public Fluid getFluidIfLoaded(BlockPosition blockposition) { ++ return this.getFluid(blockposition); ++ } ++ ++ @Override ++ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { ++ return this.getType(blockposition); ++ } ++ // Paper end ++ + @Override + public IBlockData getType(BlockPosition blockposition) { + int i = blockposition.getY(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +index 859561a5dccba6548967b685b20e8fcfc296db2a..9ebf2806122a308f7655cdbee1f642cd80c9932c 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +@@ -27,7 +27,7 @@ public class IOWorker implements AutoCloseable { + private static final Logger LOGGER = LogManager.getLogger(); + private final AtomicBoolean b = new AtomicBoolean(); + private final ThreadedMailbox c; +- private final RegionFileCache d; ++ private final RegionFileCache d;public RegionFileCache getRegionFileCache() { return d; } // Paper - OBFHELPER + private final Map e = Maps.newLinkedHashMap(); + + protected IOWorker(File file, boolean flag, String s) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 5e3bbc6d89794e23df7b60b13ae48c0f5136f20e..d1b761055c508a4b80436b50a832e00d0449d8cb 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -112,6 +112,7 @@ public class RegionFile implements AutoCloseable { + return this.e.resolve(s); + } + ++ @Nullable public synchronized DataInputStream getReadStream(ChunkCoordIntPair chunkCoordIntPair) throws IOException { return a(chunkCoordIntPair);} // Paper - OBFHELPER + @Nullable + public synchronized DataInputStream a(ChunkCoordIntPair chunkcoordintpair) throws IOException { + int i = this.getOffset(chunkcoordintpair); +diff --git a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java +index 633a484cebc99f4a2f071b7f84b0b63d0ec3f985..3941dd33da4b5c09d0087143f1d8a2d76fc18792 100644 +--- a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java ++++ b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java +@@ -194,10 +194,12 @@ public class AxisAlignedBB { + return this.d(vec3d.x, vec3d.y, vec3d.z); + } + ++ public final boolean intersects(AxisAlignedBB axisalignedbb) { return this.c(axisalignedbb); } // Paper - OBFHELPER + public boolean c(AxisAlignedBB axisalignedbb) { + return this.a(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ, axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ); + } + ++ public final boolean intersects(double d0, double d1, double d2, double d3, double d4, double d5) { return a(d0, d1, d2, d3, d4, d5); } // Paper - OBFHELPER + public boolean a(double d0, double d1, double d2, double d3, double d4, double d5) { + return this.minX < d3 && this.maxX > d0 && this.minY < d4 && this.maxY > d1 && this.minZ < d5 && this.maxZ > d2; + } +@@ -210,6 +212,7 @@ public class AxisAlignedBB { + return d0 >= this.minX && d0 < this.maxX && d1 >= this.minY && d1 < this.maxY && d2 >= this.minZ && d2 < this.maxZ; + } + ++ public final double getAverageSideLength(){return a();} // Paper - OBFHELPER + public double a() { + double d0 = this.b(); + double d1 = this.c(); +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +index 44d37272a337fee9606ebaa1b6f647c0fd392320..fdd9e37a8c90fc3311e515355af0a0593efbdacc 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +@@ -31,10 +31,12 @@ public final class VoxelShapes { + public static final VoxelShape a = create(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); + private static final VoxelShape c = new VoxelShapeArray(new VoxelShapeBitSet(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); + ++ public static final VoxelShape empty() {return a();} // Paper - OBFHELPER + public static VoxelShape a() { + return VoxelShapes.c; + } + ++ public static final VoxelShape fullCube() {return b();} // Paper - OBFHELPER + public static VoxelShape b() { + return VoxelShapes.b; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index 52fa8a38545be43a31363d1d57e42471bbb0c499..275b943a59ef28c831a068987e111e84ebba3bb7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -85,6 +85,7 @@ public final class CraftItemStack extends ItemStack { + } + + net.minecraft.world.item.ItemStack handle; ++ public net.minecraft.world.item.ItemStack getHandle() { return handle; } // Paper + + /** + * Mirror +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 9ad17c560c8d99a396543ab9f97c34de648f6544..4bf48f77f3f7cd62a91590543f5af441c8268029 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -43,6 +43,7 @@ import org.bukkit.scheduler.BukkitWorker; + */ + public class CraftScheduler implements BukkitScheduler { + ++ static Plugin MINECRAFT = new MinecraftInternalPlugin(); + /** + * Counter for IDs. Order doesn't matter, only uniqueness. + */ +@@ -177,6 +178,11 @@ public class CraftScheduler implements BukkitScheduler { + runTaskTimer(plugin, (Object) task, delay, period); + } + ++ public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { ++ final CraftTask task = new CraftTask(run, nextId(), taskName); ++ return handle(task, delay); ++ } ++ + public BukkitTask runTaskTimer(Plugin plugin, Object runnable, long delay, long period) { + validate(plugin, runnable); + if (delay < 0L) { +@@ -400,13 +406,20 @@ public class CraftScheduler implements BukkitScheduler { + task.run(); + task.timings.stopTiming(); // Spigot + } catch (final Throwable throwable) { +- task.getOwner().getLogger().log( ++ // Paper start ++ String msg = String.format( ++ "Task #%s for %s generated an exception", ++ task.getTaskId(), ++ task.getOwner().getDescription().getFullName()); ++ if (task.getOwner() == MINECRAFT) { ++ net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable); ++ } else { ++ task.getOwner().getLogger().log( + Level.WARNING, +- String.format( +- "Task #%s for %s generated an exception", +- task.getTaskId(), +- task.getOwner().getDescription().getFullName()), ++ msg, + throwable); ++ } ++ // Paper end + } finally { + currentTask = null; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +index 3c7066192ea4c05c101404bb56cbc839771f4200..09aa6809c5400ce8548ac902908b750ce7c964ec 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +@@ -39,6 +39,21 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + CraftTask(final Object task) { + this(null, task, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); + } ++ // Paper start ++ public String taskName = null; ++ boolean internal = false; ++ CraftTask(final Object task, int id, String taskName) { ++ this.rTask = (Runnable) task; ++ this.cTask = null; ++ this.plugin = CraftScheduler.MINECRAFT; ++ this.taskName = taskName; ++ this.internal = true; ++ this.id = id; ++ this.period = CraftTask.NO_REPEATING; ++ this.taskName = taskName; ++ this.timings = null; // Will be changed in later patch ++ } ++ // Paper end + + CraftTask(final Plugin plugin, final Object task, final int id, final long period) { + this.plugin = plugin; +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java +new file mode 100644 +index 0000000000000000000000000000000000000000..49dc0c441b9dd7e7745cf15ced67f383ebee1f99 +--- /dev/null ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java +@@ -0,0 +1,132 @@ ++package org.bukkit.craftbukkit.scheduler; ++ ++ ++import org.bukkit.Server; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.bukkit.configuration.file.FileConfiguration; ++import org.bukkit.generator.ChunkGenerator; ++import org.bukkit.plugin.PluginBase; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.bukkit.plugin.PluginLoader; ++import org.bukkit.plugin.PluginLogger; ++ ++import java.io.File; ++import java.io.InputStream; ++import java.util.List; ++ ++public class MinecraftInternalPlugin extends PluginBase { ++ private boolean enabled = true; ++ ++ private final String pluginName; ++ private PluginDescriptionFile pdf; ++ ++ public MinecraftInternalPlugin() { ++ this.pluginName = "Minecraft"; ++ pdf = new PluginDescriptionFile(pluginName, "1.0", "nms"); ++ } ++ ++ public void setEnabled(boolean enabled) { ++ this.enabled = enabled; ++ } ++ ++ @Override ++ public File getDataFolder() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginDescriptionFile getDescription() { ++ return pdf; ++ } ++ ++ @Override ++ public FileConfiguration getConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public InputStream getResource(String filename) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void saveConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void saveDefaultConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void saveResource(String resourcePath, boolean replace) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void reloadConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginLogger getLogger() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginLoader getPluginLoader() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public Server getServer() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public boolean isEnabled() { ++ return enabled; ++ } ++ ++ @Override ++ public void onDisable() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void onLoad() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void onEnable() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public boolean isNaggable() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void setNaggable(boolean canNag) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java +index f4ea5809f48fda39e32738529b4ae8f74acadb90..b2b14eada44231a619622a2baef27abdb798aa47 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java +@@ -168,7 +168,23 @@ public class DummyGeneratorAccess implements GeneratorAccess { + public Fluid getFluid(BlockPosition blockposition) { + throw new UnsupportedOperationException("Not supported yet."); + } ++ // Paper start - if loaded util ++ @javax.annotation.Nullable ++ @Override ++ public IChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ @Override ++ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } + ++ @Override ++ public Fluid getFluidIfLoaded(BlockPosition blockposition) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // Paper end + @Override + public WorldBorder getWorldBorder() { + throw new UnsupportedOperationException("Not supported yet."); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java +index 1aec70a1f1a9d8fd2cd06bde4033e19e769ab331..f72c13bedaa6fa45e26f5dcad564835bdd4af61f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java +@@ -17,7 +17,7 @@ import java.util.RandomAccess; + public class UnsafeList extends AbstractList implements List, RandomAccess, Cloneable, Serializable { + private static final long serialVersionUID = 8683452581112892191L; + +- private transient Object[] data; ++ private transient Object[] data; public final Object[] getRawDataArray() { return this.data; } // Paper - expose for raw get + private int size; + private int initialCapacity; + +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 724c6a47846f4266c858b783f68f162e0508d2fa..c04d912adf0da8f7a5b75dd2f58739a11ca31601 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -118,7 +118,11 @@ public class SpigotConfig + } + } + } +- ++ // Paper start ++ SpigotConfig.save(); ++ } ++ public static void save() { ++ // Paper end + try + { + config.save( CONFIG_FILE ); diff --git a/patches/server-unmapped/0005-Paper-Metrics.patch b/patches/server-unmapped/0005-Paper-Metrics.patch new file mode 100644 index 0000000000..45ad445357 --- /dev/null +++ b/patches/server-unmapped/0005-Paper-Metrics.patch @@ -0,0 +1,735 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 24 Mar 2017 23:56:01 -0500 +Subject: [PATCH] Paper Metrics + +Removes Spigot's mcstats metrics in favor of a system using bStats + +To disable for privacy or other reasons go to the bStats folder in your plugins folder +and edit the config.yml file present there. + +Please keep in mind the data collected is anonymous and collection should have no +tangible effect on server performance. The data is used to allow the authors of +PaperMC to track version and platform usage so that we can make better management +decisions on behalf of the project. + +diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0b9e689d57705965721b5c55bc45d36657f360e4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/Metrics.java +@@ -0,0 +1,670 @@ ++package com.destroystokyo.paper; ++ ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++import org.bukkit.configuration.file.YamlConfiguration; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.plugin.Plugin; ++ ++import org.json.simple.JSONArray; ++import org.json.simple.JSONObject; ++ ++import javax.net.ssl.HttpsURLConnection; ++import java.io.ByteArrayOutputStream; ++import java.io.DataOutputStream; ++import java.io.File; ++import java.io.IOException; ++import java.net.URL; ++import java.util.*; ++import java.util.concurrent.Callable; ++import java.util.concurrent.Executors; ++import java.util.concurrent.ScheduledExecutorService; ++import java.util.concurrent.TimeUnit; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++import java.util.zip.GZIPOutputStream; ++ ++/** ++ * bStats collects some data for plugin authors. ++ * ++ * Check out https://bStats.org/ to learn more about bStats! ++ */ ++public class Metrics { ++ ++ // Executor service for requests ++ // We use an executor service because the Bukkit scheduler is affected by server lags ++ private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); ++ ++ // The version of this bStats class ++ public static final int B_STATS_VERSION = 1; ++ ++ // The url to which the data is sent ++ private static final String URL = "https://bStats.org/submitData/server-implementation"; ++ ++ // Should failed requests be logged? ++ private static boolean logFailedRequests = false; ++ ++ // The logger for the failed requests ++ private static Logger logger = Logger.getLogger("bStats"); ++ ++ // The name of the server software ++ private final String name; ++ ++ // The uuid of the server ++ private final String serverUUID; ++ ++ // A list with all custom charts ++ private final List charts = new ArrayList<>(); ++ ++ /** ++ * Class constructor. ++ * ++ * @param name The name of the server software. ++ * @param serverUUID The uuid of the server. ++ * @param logFailedRequests Whether failed requests should be logged or not. ++ * @param logger The logger for the failed requests. ++ */ ++ public Metrics(String name, String serverUUID, boolean logFailedRequests, Logger logger) { ++ this.name = name; ++ this.serverUUID = serverUUID; ++ Metrics.logFailedRequests = logFailedRequests; ++ Metrics.logger = logger; ++ ++ // Start submitting the data ++ startSubmitting(); ++ } ++ ++ /** ++ * Adds a custom chart. ++ * ++ * @param chart The chart to add. ++ */ ++ public void addCustomChart(CustomChart chart) { ++ if (chart == null) { ++ throw new IllegalArgumentException("Chart cannot be null!"); ++ } ++ charts.add(chart); ++ } ++ ++ /** ++ * Starts the Scheduler which submits our data every 30 minutes. ++ */ ++ private void startSubmitting() { ++ final Runnable submitTask = this::submitData; ++ ++ // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the ++ // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. ++ // WARNING: You must not modify any part of this Metrics class, including the submit delay or frequency! ++ // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! ++ long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); ++ long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); ++ scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); ++ scheduler.scheduleAtFixedRate(submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); ++ } ++ ++ /** ++ * Gets the plugin specific data. ++ * ++ * @return The plugin specific data. ++ */ ++ private JSONObject getPluginData() { ++ JSONObject data = new JSONObject(); ++ ++ data.put("pluginName", name); // Append the name of the server software ++ JSONArray customCharts = new JSONArray(); ++ for (CustomChart customChart : charts) { ++ // Add the data of the custom charts ++ JSONObject chart = customChart.getRequestJsonObject(); ++ if (chart == null) { // If the chart is null, we skip it ++ continue; ++ } ++ customCharts.add(chart); ++ } ++ data.put("customCharts", customCharts); ++ ++ return data; ++ } ++ ++ /** ++ * Gets the server specific data. ++ * ++ * @return The server specific data. ++ */ ++ private JSONObject getServerData() { ++ // OS specific data ++ String osName = System.getProperty("os.name"); ++ String osArch = System.getProperty("os.arch"); ++ String osVersion = System.getProperty("os.version"); ++ int coreCount = Runtime.getRuntime().availableProcessors(); ++ ++ JSONObject data = new JSONObject(); ++ ++ data.put("serverUUID", serverUUID); ++ ++ data.put("osName", osName); ++ data.put("osArch", osArch); ++ data.put("osVersion", osVersion); ++ data.put("coreCount", coreCount); ++ ++ return data; ++ } ++ ++ /** ++ * Collects the data and sends it afterwards. ++ */ ++ private void submitData() { ++ final JSONObject data = getServerData(); ++ ++ JSONArray pluginData = new JSONArray(); ++ pluginData.add(getPluginData()); ++ data.put("plugins", pluginData); ++ ++ try { ++ // We are still in the Thread of the timer, so nothing get blocked :) ++ sendData(data); ++ } catch (Exception e) { ++ // Something went wrong! :( ++ if (logFailedRequests) { ++ logger.log(Level.WARNING, "Could not submit stats of " + name, e); ++ } ++ } ++ } ++ ++ /** ++ * Sends the data to the bStats server. ++ * ++ * @param data The data to send. ++ * @throws Exception If the request failed. ++ */ ++ private static void sendData(JSONObject data) throws Exception { ++ if (data == null) { ++ throw new IllegalArgumentException("Data cannot be null!"); ++ } ++ HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); ++ ++ // Compress the data to save bandwidth ++ byte[] compressedData = compress(data.toString()); ++ ++ // Add headers ++ connection.setRequestMethod("POST"); ++ connection.addRequestProperty("Accept", "application/json"); ++ connection.addRequestProperty("Connection", "close"); ++ connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request ++ connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); ++ connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format ++ connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); ++ ++ // Send data ++ connection.setDoOutput(true); ++ DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); ++ outputStream.write(compressedData); ++ outputStream.flush(); ++ outputStream.close(); ++ ++ connection.getInputStream().close(); // We don't care about the response - Just send our data :) ++ } ++ ++ /** ++ * Gzips the given String. ++ * ++ * @param str The string to gzip. ++ * @return The gzipped String. ++ * @throws IOException If the compression failed. ++ */ ++ private static byte[] compress(final String str) throws IOException { ++ if (str == null) { ++ return null; ++ } ++ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ++ GZIPOutputStream gzip = new GZIPOutputStream(outputStream); ++ gzip.write(str.getBytes("UTF-8")); ++ gzip.close(); ++ return outputStream.toByteArray(); ++ } ++ ++ /** ++ * Represents a custom chart. ++ */ ++ public static abstract class CustomChart { ++ ++ // The id of the chart ++ final String chartId; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ */ ++ CustomChart(String chartId) { ++ if (chartId == null || chartId.isEmpty()) { ++ throw new IllegalArgumentException("ChartId cannot be null or empty!"); ++ } ++ this.chartId = chartId; ++ } ++ ++ private JSONObject getRequestJsonObject() { ++ JSONObject chart = new JSONObject(); ++ chart.put("chartId", chartId); ++ try { ++ JSONObject data = getChartData(); ++ if (data == null) { ++ // If the data is null we don't send the chart. ++ return null; ++ } ++ chart.put("data", data); ++ } catch (Throwable t) { ++ if (logFailedRequests) { ++ logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t); ++ } ++ return null; ++ } ++ return chart; ++ } ++ ++ protected abstract JSONObject getChartData() throws Exception; ++ ++ } ++ ++ /** ++ * Represents a custom simple pie. ++ */ ++ public static class SimplePie extends CustomChart { ++ ++ private final Callable callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public SimplePie(String chartId, Callable callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ String value = callable.call(); ++ if (value == null || value.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("value", value); ++ return data; ++ } ++ } ++ ++ /** ++ * Represents a custom advanced pie. ++ */ ++ public static class AdvancedPie extends CustomChart { ++ ++ private final Callable> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public AdvancedPie(String chartId, Callable> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ boolean allSkipped = true; ++ for (Map.Entry entry : map.entrySet()) { ++ if (entry.getValue() == 0) { ++ continue; // Skip this invalid ++ } ++ allSkipped = false; ++ values.put(entry.getKey(), entry.getValue()); ++ } ++ if (allSkipped) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("values", values); ++ return data; ++ } ++ } ++ ++ /** ++ * Represents a custom drilldown pie. ++ */ ++ public static class DrilldownPie extends CustomChart { ++ ++ private final Callable>> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public DrilldownPie(String chartId, Callable>> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ public JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map> map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ boolean reallyAllSkipped = true; ++ for (Map.Entry> entryValues : map.entrySet()) { ++ JSONObject value = new JSONObject(); ++ boolean allSkipped = true; ++ for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { ++ value.put(valueEntry.getKey(), valueEntry.getValue()); ++ allSkipped = false; ++ } ++ if (!allSkipped) { ++ reallyAllSkipped = false; ++ values.put(entryValues.getKey(), value); ++ } ++ } ++ if (reallyAllSkipped) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("values", values); ++ return data; ++ } ++ } ++ ++ /** ++ * Represents a custom single line chart. ++ */ ++ public static class SingleLineChart extends CustomChart { ++ ++ private final Callable callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public SingleLineChart(String chartId, Callable callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ int value = callable.call(); ++ if (value == 0) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("value", value); ++ return data; ++ } ++ ++ } ++ ++ /** ++ * Represents a custom multi line chart. ++ */ ++ public static class MultiLineChart extends CustomChart { ++ ++ private final Callable> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public MultiLineChart(String chartId, Callable> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ boolean allSkipped = true; ++ for (Map.Entry entry : map.entrySet()) { ++ if (entry.getValue() == 0) { ++ continue; // Skip this invalid ++ } ++ allSkipped = false; ++ values.put(entry.getKey(), entry.getValue()); ++ } ++ if (allSkipped) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("values", values); ++ return data; ++ } ++ ++ } ++ ++ /** ++ * Represents a custom simple bar chart. ++ */ ++ public static class SimpleBarChart extends CustomChart { ++ ++ private final Callable> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public SimpleBarChart(String chartId, Callable> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ for (Map.Entry entry : map.entrySet()) { ++ JSONArray categoryValues = new JSONArray(); ++ categoryValues.add(entry.getValue()); ++ values.put(entry.getKey(), categoryValues); ++ } ++ data.put("values", values); ++ return data; ++ } ++ ++ } ++ ++ /** ++ * Represents a custom advanced bar chart. ++ */ ++ public static class AdvancedBarChart extends CustomChart { ++ ++ private final Callable> callable; ++ ++ /** ++ * Class constructor. ++ * ++ * @param chartId The id of the chart. ++ * @param callable The callable which is used to request the chart data. ++ */ ++ public AdvancedBarChart(String chartId, Callable> callable) { ++ super(chartId); ++ this.callable = callable; ++ } ++ ++ @Override ++ protected JSONObject getChartData() throws Exception { ++ JSONObject data = new JSONObject(); ++ JSONObject values = new JSONObject(); ++ Map map = callable.call(); ++ if (map == null || map.isEmpty()) { ++ // Null = skip the chart ++ return null; ++ } ++ boolean allSkipped = true; ++ for (Map.Entry entry : map.entrySet()) { ++ if (entry.getValue().length == 0) { ++ continue; // Skip this invalid ++ } ++ allSkipped = false; ++ JSONArray categoryValues = new JSONArray(); ++ for (int categoryValue : entry.getValue()) { ++ categoryValues.add(categoryValue); ++ } ++ values.put(entry.getKey(), categoryValues); ++ } ++ if (allSkipped) { ++ // Null = skip the chart ++ return null; ++ } ++ data.put("values", values); ++ return data; ++ } ++ ++ } ++ ++ static class PaperMetrics { ++ static void startMetrics() { ++ // Get the config file ++ File configFile = new File(new File((File) MinecraftServer.getServer().options.valueOf("plugins"), "bStats"), "config.yml"); ++ YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); ++ ++ // Check if the config file exists ++ if (!config.isSet("serverUuid")) { ++ ++ // Add default values ++ config.addDefault("enabled", true); ++ // Every server gets it's unique random id. ++ config.addDefault("serverUuid", UUID.randomUUID().toString()); ++ // Should failed request be logged? ++ config.addDefault("logFailedRequests", false); ++ ++ // Inform the server owners about bStats ++ config.options().header( ++ "bStats collects some data for plugin authors like how many servers are using their plugins.\n" + ++ "To honor their work, you should not disable it.\n" + ++ "This has nearly no effect on the server performance!\n" + ++ "Check out https://bStats.org/ to learn more :)" ++ ).copyDefaults(true); ++ try { ++ config.save(configFile); ++ } catch (IOException ignored) { ++ } ++ } ++ // Load the data ++ String serverUUID = config.getString("serverUuid"); ++ boolean logFailedRequests = config.getBoolean("logFailedRequests", false); ++ // Only start Metrics, if it's enabled in the config ++ if (config.getBoolean("enabled", true)) { ++ Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger()); ++ ++ metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { ++ String minecraftVersion = Bukkit.getVersion(); ++ minecraftVersion = minecraftVersion.substring(minecraftVersion.indexOf("MC: ") + 4, minecraftVersion.length() - 1); ++ return minecraftVersion; ++ })); ++ ++ metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); ++ metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() || PaperConfig.isProxyOnlineMode() ? "online" : "offline")); ++ metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); ++ ++ metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { ++ Map> map = new HashMap<>(); ++ String javaVersion = System.getProperty("java.version"); ++ Map entry = new HashMap<>(); ++ entry.put(javaVersion, 1); ++ ++ // http://openjdk.java.net/jeps/223 ++ // Java decided to change their versioning scheme and in doing so modified the java.version system ++ // property to return $major[.$minor][.$secuity][-ea], as opposed to 1.$major.0_$identifier ++ // we can handle pre-9 by checking if the "major" is equal to "1", otherwise, 9+ ++ String majorVersion = javaVersion.split("\\.")[0]; ++ String release; ++ ++ int indexOf = javaVersion.lastIndexOf('.'); ++ ++ if (majorVersion.equals("1")) { ++ release = "Java " + javaVersion.substring(0, indexOf); ++ } else { ++ // of course, it really wouldn't be all that simple if they didn't add a quirk, now would it ++ // valid strings for the major may potentially include values such as -ea to deannotate a pre release ++ Matcher versionMatcher = Pattern.compile("\\d+").matcher(majorVersion); ++ if (versionMatcher.find()) { ++ majorVersion = versionMatcher.group(0); ++ } ++ release = "Java " + majorVersion; ++ } ++ map.put(release, entry); ++ ++ return map; ++ })); ++ ++ metrics.addCustomChart(new Metrics.DrilldownPie("legacy_plugins", () -> { ++ Map> map = new HashMap<>(); ++ ++ // count legacy plugins ++ int legacy = 0; ++ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { ++ if (CraftMagicNumbers.isLegacy(plugin.getDescription())) { ++ legacy++; ++ } ++ } ++ ++ // insert real value as lower dimension ++ Map entry = new HashMap<>(); ++ entry.put(String.valueOf(legacy), 1); ++ ++ // create buckets as higher dimension ++ if (legacy == 0) { ++ map.put("0 \uD83D\uDE0E", entry); // :sunglasses: ++ } else if (legacy <= 5) { ++ map.put("1-5", entry); ++ } else if (legacy <= 10) { ++ map.put("6-10", entry); ++ } else if (legacy <= 25) { ++ map.put("11-25", entry); ++ } else if (legacy <= 50) { ++ map.put("26-50", entry); ++ } else { ++ map.put("50+ \uD83D\uDE2D", entry); // :cry: ++ } ++ ++ return map; ++ })); ++ } ++ ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 2c0514892d3993bef57ecf677cf8bb0fbe0216e4..da922f395f0fff0881ead893c900c5b2623f48f0 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -42,6 +42,7 @@ public class PaperConfig { + private static boolean verbose; + private static boolean fatalError; + /*========================================================================*/ ++ private static boolean metricsStarted; + + public static void init(File configFile) { + CONFIG_FILE = configFile; +@@ -84,6 +85,11 @@ public class PaperConfig { + for (Map.Entry entry : commands.entrySet()) { + MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); + } ++ ++ if (!metricsStarted) { ++ Metrics.PaperMetrics.startMetrics(); ++ metricsStarted = true; ++ } + } + + static void readConfig(Class clazz, Object instance) { +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index c04d912adf0da8f7a5b75dd2f58739a11ca31601..3c93a497a790b8d800852db2ac48feca41f45cef 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -83,6 +83,7 @@ public class SpigotConfig + MinecraftServer.getServer().server.getCommandMap().register( entry.getKey(), "Spigot", entry.getValue() ); + } + ++ /* // Paper - Replace with our own + if ( metrics == null ) + { + try +@@ -94,6 +95,7 @@ public class SpigotConfig + Bukkit.getServer().getLogger().log( Level.SEVERE, "Could not start metrics service", ex ); + } + } ++ */ // Paper end + } + + static void readConfig(Class clazz, Object instance) diff --git a/patches/server-unmapped/0006-Add-MinecraftKey-Information-to-Objects.patch b/patches/server-unmapped/0006-Add-MinecraftKey-Information-to-Objects.patch new file mode 100644 index 0000000000..a390f7960d --- /dev/null +++ b/patches/server-unmapped/0006-Add-MinecraftKey-Information-to-Objects.patch @@ -0,0 +1,144 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 01:40:13 -0400 +Subject: [PATCH] Add MinecraftKey Information to Objects + +Stores the reference to the objects respective MinecraftKey + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 68cd4134cb6a00c1768100462f8e9e94f3fa6279..6943524c2dd8b12691b8ac5b08daee823ce50c3d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -208,7 +208,7 @@ public class PaperCommand extends Command { + + Collection entities = world.entitiesById.values(); + entities.forEach(e -> { +- MinecraftKey key = new MinecraftKey(""); // TODO: update in next patch ++ MinecraftKey key = e.getMinecraftKey(); + + MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); + ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); +diff --git a/src/main/java/net/minecraft/server/KeyedObject.java b/src/main/java/net/minecraft/server/KeyedObject.java +new file mode 100644 +index 0000000000000000000000000000000000000000..500477f0d98a277145c2b0dbb4d1496e2a588542 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/KeyedObject.java +@@ -0,0 +1,11 @@ ++package net.minecraft.server; ++ ++import net.minecraft.resources.MinecraftKey; ++ ++public interface KeyedObject { ++ MinecraftKey getMinecraftKey(); ++ default String getMinecraftKeyString() { ++ MinecraftKey key = getMinecraftKey(); ++ return key != null ? key.toString() : null; ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 3c8767d5fab575e61ca179b517f0bff1a38405ce..ec553e7d7595ef3652bfa3325a07483bb3c32245 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -136,7 +136,7 @@ import org.bukkit.event.player.PlayerTeleportEvent; + import org.bukkit.plugin.PluginManager; + // CraftBukkit end + +-public abstract class Entity implements INamableTileEntity, ICommandListener { ++public abstract class Entity implements INamableTileEntity, ICommandListener, net.minecraft.server.KeyedObject { // Paper + + // CraftBukkit start + private static final int CURRENT_LEVEL = 2; +@@ -1762,12 +1762,31 @@ public abstract class Entity implements INamableTileEntity, ICommandListener { + return true; + } + ++ // Paper start ++ private MinecraftKey entityKey; ++ private String entityKeyString; ++ ++ @Override ++ public MinecraftKey getMinecraftKey() { ++ if (entityKey == null) { ++ this.entityKey = EntityTypes.getName(this.getEntityType()); ++ this.entityKeyString = this.entityKey != null ? this.entityKey.toString() : null; ++ } ++ return entityKey; ++ } ++ ++ @Override ++ public String getMinecraftKeyString() { ++ getMinecraftKey(); // Try to load if it doesn't exists. see: https://github.com/PaperMC/Paper/issues/1280 ++ return entityKeyString; ++ } + @Nullable + public final String getSaveID() { + EntityTypes entitytypes = this.getEntityType(); + MinecraftKey minecraftkey = EntityTypes.getName(entitytypes); + +- return entitytypes.a() && minecraftkey != null ? minecraftkey.toString() : null; ++ return entitytypes != null && entitytypes.isPersistable() ? getMinecraftKeyString() : null; ++ // Paper end + } + + protected abstract void loadData(NBTTagCompound nbttagcompound); +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index ac57ab9992e141c91cf48f033148ad78433b364c..dc92b112770955f9fa49a408262da2e5bbc4bf98 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -384,6 +384,7 @@ public class EntityTypes { + } + } + ++ public boolean isPersistable() { return a(); } // Paper - OBFHELPER + public boolean a() { + return this.bi; + } +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +index 72d43b38de3e797a509de6591874af12fa7b9ec0..2b58ae6d91fe0d0f36eedbb78a3c8a8a66d92405 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +@@ -23,7 +23,7 @@ import org.bukkit.inventory.InventoryHolder; + + import org.spigotmc.CustomTimingsHandler; // Spigot + +-public abstract class TileEntity { ++public abstract class TileEntity implements net.minecraft.server.KeyedObject { // Paper + + public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot + // CraftBukkit start - data containers +@@ -31,7 +31,7 @@ public abstract class TileEntity { + public CraftPersistentDataContainer persistentDataContainer; + // CraftBukkit end + private static final Logger LOGGER = LogManager.getLogger(); +- private final TileEntityTypes tileType; ++ private final TileEntityTypes tileType; public TileEntityTypes getTileEntityType() { return tileType; } // Paper - OBFHELPER + @Nullable + protected World world; + protected BlockPosition position; +@@ -45,6 +45,26 @@ public abstract class TileEntity { + this.tileType = tileentitytypes; + } + ++ // Paper start ++ private String tileEntityKeyString = null; ++ private MinecraftKey tileEntityKey = null; ++ ++ @Override ++ public MinecraftKey getMinecraftKey() { ++ if (tileEntityKey == null) { ++ tileEntityKey = TileEntityTypes.a(this.getTileEntityType()); ++ tileEntityKeyString = tileEntityKey != null ? tileEntityKey.toString() : null; ++ } ++ return tileEntityKey; ++ } ++ ++ @Override ++ public String getMinecraftKeyString() { ++ getMinecraftKey(); // Try to load if it doesn't exists. ++ return tileEntityKeyString; ++ } ++ // Paper end ++ + @Nullable + public World getWorld() { + return this.world; diff --git a/patches/server-unmapped/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch b/patches/server-unmapped/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch new file mode 100644 index 0000000000..873dc9de7e --- /dev/null +++ b/patches/server-unmapped/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch @@ -0,0 +1,171 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 02:10:36 -0400 +Subject: [PATCH] Store reference to current Chunk for Entity and Block + Entities + +This enables us a fast reference to the entities current chunk instead +of having to look it up by hashmap lookups. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index ec553e7d7595ef3652bfa3325a07483bb3c32245..2bea2f4748cadf479dd4f89792ef5ffdd88e9cab 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -261,7 +261,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public boolean isChunkLoaded() { +- return world.isChunkLoaded((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); ++ return getCurrentChunk() != null; + } + // CraftBukkit end + +@@ -1763,6 +1763,23 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + // Paper start ++ public java.lang.ref.WeakReference currentChunk = null; ++ ++ public void setCurrentChunk(net.minecraft.world.level.chunk.Chunk chunk) { ++ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; ++ } ++ /** ++ * Returns the entities current registered chunk. If the entity is not added to a chunk yet, it will return null ++ */ ++ public net.minecraft.world.level.chunk.Chunk getCurrentChunk() { ++ final net.minecraft.world.level.chunk.Chunk chunk = currentChunk != null ? currentChunk.get() : null; ++ if (chunk != null && chunk.loaded) { ++ return chunk; ++ } ++ ++ return !inChunk ? null : ((WorldServer)world).getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(chunkX, chunkZ); ++ } ++ + private MinecraftKey entityKey; + private String entityKeyString; + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +index 2b58ae6d91fe0d0f36eedbb78a3c8a8a66d92405..75110c41af3e0097aef65091a2497dd87d08b4b2 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +@@ -11,6 +11,7 @@ import net.minecraft.world.level.World; + import net.minecraft.world.level.block.EnumBlockMirror; + import net.minecraft.world.level.block.EnumBlockRotation; + import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.chunk.Chunk; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import org.apache.logging.log4j.util.Supplier; +@@ -63,6 +64,15 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / + getMinecraftKey(); // Try to load if it doesn't exists. + return tileEntityKeyString; + } ++ ++ private java.lang.ref.WeakReference currentChunk = null; ++ public Chunk getCurrentChunk() { ++ final Chunk chunk = currentChunk != null ? currentChunk.get() : null; ++ return chunk != null && chunk.loaded ? chunk : null; ++ } ++ public void setCurrentChunk(Chunk chunk) { ++ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; ++ } + // Paper end + + @Nullable +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index b15200c2a3923bd8be2ee5e73fdadfeea3e3a8dc..929f6fcd4b9f1b9a1488e170d6a77a5d64beecf3 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -90,11 +90,36 @@ public class Chunk implements IChunkAccess { + this(world, chunkcoordintpair, biomestorage, ChunkConverter.a, TickListEmpty.b(), TickListEmpty.b(), 0L, (ChunkSection[]) null, (Consumer) null); + } + ++ // Paper start ++ private class TileEntityHashMap extends java.util.HashMap { ++ @Override ++ public TileEntity put(BlockPosition key, TileEntity value) { ++ TileEntity replaced = super.put(key, value); ++ if (replaced != null) { ++ replaced.setCurrentChunk(null); ++ } ++ if (value != null) { ++ value.setCurrentChunk(Chunk.this); ++ } ++ return replaced; ++ } ++ ++ @Override ++ public TileEntity remove(Object key) { ++ TileEntity removed = super.remove(key); ++ if (removed != null) { ++ removed.setCurrentChunk(null); ++ } ++ return removed; ++ } ++ } ++ // Paper end ++ + public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList ticklist, TickList ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer consumer) { + this.sections = new ChunkSection[16]; + this.e = Maps.newHashMap(); + this.heightMap = Maps.newEnumMap(HeightMap.Type.class); +- this.tileEntities = Maps.newHashMap(); ++ this.tileEntities = new TileEntityHashMap(); // Paper + this.l = Maps.newHashMap(); + this.m = Maps.newHashMap(); + this.n = new ShortList[16]; +@@ -505,6 +530,7 @@ public class Chunk implements IChunkAccess { + } + + entity.inChunk = true; ++ entity.setCurrentChunk(this); // Paper + entity.chunkX = this.loc.x; + entity.chunkY = k; + entity.chunkZ = this.loc.z; +@@ -517,6 +543,7 @@ public class Chunk implements IChunkAccess { + ((HeightMap) this.heightMap.get(heightmap_type)).a(along); + } + ++ public final void removeEntity(Entity entity) { this.b(entity); } // Paper - OBFHELPER + public void b(Entity entity) { + this.a(entity, entity.chunkY); + } +@@ -531,7 +558,12 @@ public class Chunk implements IChunkAccess { + i = this.entitySlices.length - 1; + } + +- this.entitySlices[i].remove(entity); ++ // Paper start ++ if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); ++ if (!this.entitySlices[i].remove(entity)) { ++ return; ++ } ++ // Paper end + this.entities.remove(entity); // Paper + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index df7e5f1d17ddfeffc15df02906c3bf9f9461d82b..eea242af23825ad29ada6e997205e87edffb6bb9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -145,6 +145,7 @@ import net.minecraft.world.entity.vehicle.EntityMinecartMobSpawner; + import net.minecraft.world.entity.vehicle.EntityMinecartRideable; + import net.minecraft.world.entity.vehicle.EntityMinecartTNT; + import net.minecraft.world.phys.AxisAlignedBB; ++import org.bukkit.Chunk; // Paper + import org.bukkit.EntityEffect; + import org.bukkit.Location; + import org.bukkit.Server; +@@ -186,6 +187,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + this.entity = entity; + } + ++ @Override ++ public Chunk getChunk() { ++ net.minecraft.world.level.chunk.Chunk currentChunk = entity.getCurrentChunk(); ++ return currentChunk != null ? currentChunk.bukkitChunk : getLocation().getChunk(); ++ } ++ + public static CraftEntity getEntity(CraftServer server, Entity entity) { + /* + * Order is *EXTREMELY* important -- keep it right! =D diff --git a/patches/server-unmapped/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch b/patches/server-unmapped/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch new file mode 100644 index 0000000000..73d224306f --- /dev/null +++ b/patches/server-unmapped/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 02:13:59 -0400 +Subject: [PATCH] Store counts for each Entity/Block Entity Type + +Opens door for future patches to optimize performance + +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index 929f6fcd4b9f1b9a1488e170d6a77a5d64beecf3..acdcece38a4b30d6c89eb4342918ae8997db9f0b 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -91,15 +91,19 @@ public class Chunk implements IChunkAccess { + } + + // Paper start ++ public final co.aikar.util.Counter entityCounts = new co.aikar.util.Counter<>(); ++ public final co.aikar.util.Counter tileEntityCounts = new co.aikar.util.Counter<>(); + private class TileEntityHashMap extends java.util.HashMap { + @Override + public TileEntity put(BlockPosition key, TileEntity value) { + TileEntity replaced = super.put(key, value); + if (replaced != null) { + replaced.setCurrentChunk(null); ++ tileEntityCounts.decrement(replaced.getMinecraftKeyString()); + } + if (value != null) { + value.setCurrentChunk(Chunk.this); ++ tileEntityCounts.increment(value.getMinecraftKeyString()); + } + return replaced; + } +@@ -109,6 +113,7 @@ public class Chunk implements IChunkAccess { + TileEntity removed = super.remove(key); + if (removed != null) { + removed.setCurrentChunk(null); ++ tileEntityCounts.decrement(removed.getMinecraftKeyString()); + } + return removed; + } +@@ -529,6 +534,7 @@ public class Chunk implements IChunkAccess { + k = this.entitySlices.length - 1; + } + ++ if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper + entity.inChunk = true; + entity.setCurrentChunk(this); // Paper + entity.chunkX = this.loc.x; +@@ -563,6 +569,7 @@ public class Chunk implements IChunkAccess { + if (!this.entitySlices[i].remove(entity)) { + return; + } ++ entityCounts.decrement(entity.getMinecraftKeyString()); + // Paper end + this.entities.remove(entity); // Paper + } diff --git a/patches/server-unmapped/0009-Timings-v2.patch b/patches/server-unmapped/0009-Timings-v2.patch new file mode 100644 index 0000000000..6113ef6b52 --- /dev/null +++ b/patches/server-unmapped/0009-Timings-v2.patch @@ -0,0 +1,2309 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 04:00:11 -0600 +Subject: [PATCH] Timings v2 + + +diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fed920e5ec65409377f181d74dcf9274d45aadc1 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/MinecraftTimings.java +@@ -0,0 +1,151 @@ ++package co.aikar.timings; ++ ++import com.google.common.collect.MapMaker; ++import net.minecraft.commands.CustomFunction; ++import net.minecraft.network.protocol.Packet; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.entity.TileEntity; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.scheduler.BukkitTask; ++ ++import org.bukkit.craftbukkit.scheduler.CraftTask; ++ ++import java.util.Map; ++ ++// TODO: Re-implement missing timers ++public final class MinecraftTimings { ++ ++ public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); ++ public static final Timing playerListTimer = Timings.ofSafe("Player List"); ++ public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); ++ public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); ++ public static final Timing tickablesTimer = Timings.ofSafe("Tickables"); ++ public static final Timing minecraftSchedulerTimer = Timings.ofSafe("Minecraft Scheduler"); ++ public static final Timing bukkitSchedulerTimer = Timings.ofSafe("Bukkit Scheduler"); ++ public static final Timing bukkitSchedulerPendingTimer = Timings.ofSafe("Bukkit Scheduler - Pending"); ++ public static final Timing bukkitSchedulerFinishTimer = Timings.ofSafe("Bukkit Scheduler - Finishing"); ++ public static final Timing chunkIOTickTimer = Timings.ofSafe("ChunkIOTick"); ++ public static final Timing timeUpdateTimer = Timings.ofSafe("Time Update"); ++ public static final Timing serverCommandTimer = Timings.ofSafe("Server Command"); ++ public static final Timing savePlayers = Timings.ofSafe("Save Players"); ++ ++ public static final Timing tickEntityTimer = Timings.ofSafe("## tickEntity"); ++ public static final Timing tickTileEntityTimer = Timings.ofSafe("## tickTileEntity"); ++ public static final Timing packetProcessTimer = Timings.ofSafe("## Packet Processing"); ++ public static final Timing scheduledBlocksTimer = Timings.ofSafe("## Scheduled Blocks"); ++ public static final Timing structureGenerationTimer = Timings.ofSafe("Structure Generation"); ++ ++ public static final Timing processQueueTimer = Timings.ofSafe("processQueue"); ++ public static final Timing processTasksTimer = Timings.ofSafe("processTasks"); ++ ++ public static final Timing playerCommandTimer = Timings.ofSafe("playerCommand"); ++ ++ public static final Timing entityActivationCheckTimer = Timings.ofSafe("entityActivationCheck"); ++ ++ public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update"); ++ public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate"); ++ ++ private static final Map, String> taskNameCache = new MapMaker().weakKeys().makeMap(); ++ ++ private MinecraftTimings() {} ++ ++ public static Timing getInternalTaskName(String taskName) { ++ return Timings.ofSafe(taskName); ++ } ++ ++ /** ++ * Gets a timer associated with a plugins tasks. ++ * @param bukkitTask ++ * @param period ++ * @return ++ */ ++ public static Timing getPluginTaskTimings(BukkitTask bukkitTask, long period) { ++ if (!bukkitTask.isSync()) { ++ return NullTimingHandler.NULL; ++ } ++ Plugin plugin; ++ ++ CraftTask craftTask = (CraftTask) bukkitTask; ++ ++ final Class taskClass = craftTask.getTaskClass(); ++ if (bukkitTask.getOwner() != null) { ++ plugin = bukkitTask.getOwner(); ++ } else { ++ plugin = TimingsManager.getPluginByClassloader(taskClass); ++ } ++ ++ final String taskname = taskNameCache.computeIfAbsent(taskClass, clazz -> { ++ try { ++ String clsName = !clazz.isMemberClass() ++ ? clazz.getName() ++ : clazz.getCanonicalName(); ++ if (clsName != null && clsName.contains("$Lambda$")) { ++ clsName = clsName.replaceAll("(Lambda\\$.*?)/.*", "$1"); ++ } ++ return clsName != null ? clsName : "UnknownTask"; ++ } catch (Throwable ex) { ++ new Exception("Error occurred detecting class name", ex).printStackTrace(); ++ return "MangledClassFile"; ++ } ++ }); ++ ++ StringBuilder name = new StringBuilder(64); ++ name.append("Task: ").append(taskname); ++ if (period > 0) { ++ name.append(" (interval:").append(period).append(")"); ++ } else { ++ name.append(" (Single)"); ++ } ++ ++ if (plugin == null) { ++ return Timings.ofSafe(null, name.toString()); ++ } ++ ++ return Timings.ofSafe(plugin, name.toString()); ++ } ++ ++ /** ++ * Get a named timer for the specified entity type to track type specific timings. ++ * @param entityType ++ * @return ++ */ ++ public static Timing getEntityTimings(String entityType, String type) { ++ return Timings.ofSafe("Minecraft", "## tickEntity - " + entityType + " - " + type, tickEntityTimer); ++ } ++ ++ /** ++ * Get a named timer for the specified tile entity type to track type specific timings. ++ * @param entity ++ * @return ++ */ ++ public static Timing getTileEntityTimings(TileEntity entity) { ++ String entityType = entity.getClass().getName(); ++ return Timings.ofSafe("Minecraft", "## tickTileEntity - " + entityType, tickTileEntityTimer); ++ } ++ public static Timing getCancelTasksTimer() { ++ return Timings.ofSafe("Cancel Tasks"); ++ } ++ public static Timing getCancelTasksTimer(Plugin plugin) { ++ return Timings.ofSafe(plugin, "Cancel Tasks"); ++ } ++ ++ public static void stopServer() { ++ TimingsManager.stopServer(); ++ } ++ ++ public static Timing getBlockTiming(Block block) { ++ return Timings.ofSafe("## Scheduled Block: " + block.toString(), scheduledBlocksTimer); ++ } ++/* ++ public static Timing getStructureTiming(StructureGenerator structureGenerator) { ++ return Timings.ofSafe("Structure Generator - " + structureGenerator.getName(), structureGenerationTimer); ++ }*/ ++ ++ public static Timing getPacketTiming(Packet packet) { ++ return Timings.ofSafe("## Packet - " + packet.getClass().getName(), packetProcessTimer); ++ } ++ ++ public static Timing getCommandFunctionTiming(CustomFunction function) { ++ return Timings.ofSafe("Command Function - " + function.getMinecraftKey().toString()); ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d4ebcf8f66197299256bd6b65710a1488c90ea41 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingsExport.java +@@ -0,0 +1,377 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++package co.aikar.timings; ++ ++import com.google.common.collect.Sets; ++import net.minecraft.server.MinecraftServer; ++import org.apache.commons.lang.StringUtils; ++import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; ++import org.bukkit.Material; ++import org.bukkit.configuration.ConfigurationSection; ++import org.bukkit.configuration.MemorySection; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.entity.EntityType; ++import org.json.simple.JSONObject; ++import org.json.simple.JSONValue; ++ ++import java.io.ByteArrayOutputStream; ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.OutputStream; ++import java.lang.management.ManagementFactory; ++import java.lang.management.OperatingSystemMXBean; ++import java.lang.management.RuntimeMXBean; ++import java.net.HttpURLConnection; ++import java.net.InetAddress; ++import java.net.URL; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import java.util.logging.Level; ++import java.util.zip.GZIPOutputStream; ++ ++import static co.aikar.timings.TimingsManager.HISTORY; ++import static co.aikar.util.JSONUtil.appendObjectData; ++import static co.aikar.util.JSONUtil.createObject; ++import static co.aikar.util.JSONUtil.pair; ++import static co.aikar.util.JSONUtil.toArray; ++import static co.aikar.util.JSONUtil.toArrayMapper; ++import static co.aikar.util.JSONUtil.toObjectMapper; ++ ++@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) ++public class TimingsExport extends Thread { ++ ++ private final TimingsReportListener listeners; ++ private final Map out; ++ private final TimingHistory[] history; ++ private static long lastReport = 0; ++ ++ private TimingsExport(TimingsReportListener listeners, Map out, TimingHistory[] history) { ++ super("Timings paste thread"); ++ this.listeners = listeners; ++ this.out = out; ++ this.history = history; ++ } ++ ++ /** ++ * Checks if any pending reports are being requested, and builds one if needed. ++ */ ++ public static void reportTimings() { ++ if (Timings.requestingReport.isEmpty()) { ++ return; ++ } ++ TimingsReportListener listeners = new TimingsReportListener(Timings.requestingReport); ++ listeners.addConsoleIfNeeded(); ++ ++ Timings.requestingReport.clear(); ++ long now = System.currentTimeMillis(); ++ final long lastReportDiff = now - lastReport; ++ if (lastReportDiff < 60000) { ++ listeners.sendMessage(ChatColor.RED + "Please wait at least 1 minute in between Timings reports. (" + (int)((60000 - lastReportDiff) / 1000) + " seconds)"); ++ listeners.done(); ++ return; ++ } ++ final long lastStartDiff = now - TimingsManager.timingStart; ++ if (lastStartDiff < 180000) { ++ listeners.sendMessage(ChatColor.RED + "Please wait at least 3 minutes before generating a Timings report. Unlike Timings v1, v2 benefits from longer timings and is not as useful with short timings. (" + (int)((180000 - lastStartDiff) / 1000) + " seconds)"); ++ listeners.done(); ++ return; ++ } ++ listeners.sendMessage(ChatColor.GREEN + "Preparing Timings Report..."); ++ lastReport = now; ++ Map parent = createObject( ++ // Get some basic system details about the server ++ pair("version", Bukkit.getVersion()), ++ pair("maxplayers", Bukkit.getMaxPlayers()), ++ pair("start", TimingsManager.timingStart / 1000), ++ pair("end", System.currentTimeMillis() / 1000), ++ pair("online-mode", Bukkit.getServer().getOnlineMode()), ++ pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), ++ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().d(), pack -> { ++ // Don't feel like obf helper'ing these, non fatal if its temp missed. ++ return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); ++ })) ++ ); ++ if (!TimingsManager.privacy) { ++ appendObjectData(parent, ++ pair("server", Bukkit.getUnsafe().getTimingsServerName()), ++ pair("motd", Bukkit.getServer().getMotd()), ++ pair("icon", Bukkit.getServer().getServerIcon().getData()) ++ ); ++ } ++ ++ final Runtime runtime = Runtime.getRuntime(); ++ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); ++ ++ OperatingSystemMXBean osInfo = ManagementFactory.getOperatingSystemMXBean(); ++ ++ parent.put("system", createObject( ++ pair("timingcost", getCost()), ++ pair("loadavg", osInfo.getSystemLoadAverage()), ++ pair("name", System.getProperty("os.name")), ++ pair("version", System.getProperty("os.version")), ++ pair("jvmversion", System.getProperty("java.version")), ++ pair("arch", System.getProperty("os.arch")), ++ pair("maxmem", runtime.maxMemory()), ++ pair("memory", createObject( ++ pair("heap", ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().toString()), ++ pair("nonheap", ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().toString()), ++ pair("finalizing", ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount()) ++ )), ++ pair("cpu", runtime.availableProcessors()), ++ pair("runtime", runtimeBean.getUptime()), ++ pair("flags", StringUtils.join(runtimeBean.getInputArguments(), " ")), ++ pair("gc", toObjectMapper(ManagementFactory.getGarbageCollectorMXBeans(), input -> pair(input.getName(), toArray(input.getCollectionCount(), input.getCollectionTime())))) ++ ) ++ ); ++ ++ parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getWorlds(), world -> { ++ if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; ++ return pair(world.getWorldData().getName(), createObject( ++ pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { ++ return pair(rule, world.getWorld().getGameRuleValue(rule)); ++ })), ++ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) ++ )); ++ })); ++ ++ Set tileEntityTypeSet = Sets.newHashSet(); ++ Set entityTypeSet = Sets.newHashSet(); ++ ++ int size = HISTORY.size(); ++ TimingHistory[] history = new TimingHistory[size + 1]; ++ int i = 0; ++ for (TimingHistory timingHistory : HISTORY) { ++ tileEntityTypeSet.addAll(timingHistory.tileEntityTypeSet); ++ entityTypeSet.addAll(timingHistory.entityTypeSet); ++ history[i++] = timingHistory; ++ } ++ ++ history[i] = new TimingHistory(); // Current snapshot ++ tileEntityTypeSet.addAll(history[i].tileEntityTypeSet); ++ entityTypeSet.addAll(history[i].entityTypeSet); ++ ++ ++ Map handlers = createObject(); ++ Map groupData; ++ synchronized (TimingIdentifier.GROUP_MAP) { ++ for (TimingIdentifier.TimingGroup group : TimingIdentifier.GROUP_MAP.values()) { ++ synchronized (group.handlers) { ++ for (TimingHandler id : group.handlers) { ++ ++ if (!id.isTimed() && !id.isSpecial()) { ++ continue; ++ } ++ ++ String name = id.identifier.name; ++ if (name.startsWith("##")) { ++ name = name.substring(3); ++ } ++ handlers.put(id.id, toArray( ++ group.id, ++ name ++ )); ++ } ++ } ++ } ++ ++ groupData = toObjectMapper( ++ TimingIdentifier.GROUP_MAP.values(), group -> pair(group.id, group.name)); ++ } ++ ++ parent.put("idmap", createObject( ++ pair("groups", groupData), ++ pair("handlers", handlers), ++ pair("worlds", toObjectMapper(TimingHistory.worldMap.entrySet(), input -> pair(input.getValue(), input.getKey()))), ++ pair("tileentity", ++ toObjectMapper(tileEntityTypeSet, input -> pair(input.ordinal(), input.name()))), ++ pair("entity", ++ toObjectMapper(entityTypeSet, input -> pair(input.ordinal(), input.name()))) ++ )); ++ ++ // Information about loaded plugins ++ ++ parent.put("plugins", toObjectMapper(Bukkit.getPluginManager().getPlugins(), ++ plugin -> pair(plugin.getName(), createObject( ++ pair("version", plugin.getDescription().getVersion()), ++ pair("description", String.valueOf(plugin.getDescription().getDescription()).trim()), ++ pair("website", plugin.getDescription().getWebsite()), ++ pair("authors", StringUtils.join(plugin.getDescription().getAuthors(), ", ")) ++ )))); ++ ++ ++ ++ // Information on the users Config ++ ++ parent.put("config", createObject( ++ pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), ++ pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), ++ pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) ++ )); ++ ++ new TimingsExport(listeners, parent, history).start(); ++ } ++ ++ static long getCost() { ++ // Benchmark the users System.nanotime() for cost basis ++ int passes = 100; ++ TimingHandler SAMPLER1 = Timings.ofSafe("Timings Sampler 1"); ++ TimingHandler SAMPLER2 = Timings.ofSafe("Timings Sampler 2"); ++ TimingHandler SAMPLER3 = Timings.ofSafe("Timings Sampler 3"); ++ TimingHandler SAMPLER4 = Timings.ofSafe("Timings Sampler 4"); ++ TimingHandler SAMPLER5 = Timings.ofSafe("Timings Sampler 5"); ++ TimingHandler SAMPLER6 = Timings.ofSafe("Timings Sampler 6"); ++ ++ long start = System.nanoTime(); ++ for (int i = 0; i < passes; i++) { ++ SAMPLER1.startTiming(); ++ SAMPLER2.startTiming(); ++ SAMPLER3.startTiming(); ++ SAMPLER3.stopTiming(); ++ SAMPLER4.startTiming(); ++ SAMPLER5.startTiming(); ++ SAMPLER6.startTiming(); ++ SAMPLER6.stopTiming(); ++ SAMPLER5.stopTiming(); ++ SAMPLER4.stopTiming(); ++ SAMPLER2.stopTiming(); ++ SAMPLER1.stopTiming(); ++ } ++ long timingsCost = (System.nanoTime() - start) / passes / 6; ++ SAMPLER1.reset(true); ++ SAMPLER2.reset(true); ++ SAMPLER3.reset(true); ++ SAMPLER4.reset(true); ++ SAMPLER5.reset(true); ++ SAMPLER6.reset(true); ++ return timingsCost; ++ } ++ ++ private static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) { ++ ++ JSONObject object = new JSONObject(); ++ for (String key : config.getKeys(false)) { ++ String fullKey = (parentKey != null ? parentKey + "." + key : key); ++ if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld")) { ++ continue; ++ } ++ final Object val = config.get(key); ++ ++ object.put(key, valAsJSON(val, fullKey)); ++ } ++ return object; ++ } ++ ++ private static Object valAsJSON(Object val, final String parentKey) { ++ if (!(val instanceof MemorySection)) { ++ if (val instanceof List) { ++ Iterable v = (Iterable) val; ++ return toArrayMapper(v, input -> valAsJSON(input, parentKey)); ++ } else { ++ return String.valueOf(val); ++ } ++ } else { ++ return mapAsJSON((ConfigurationSection) val, parentKey); ++ } ++ } ++ ++ @Override ++ public void run() { ++ out.put("data", toArrayMapper(history, TimingHistory::export)); ++ ++ ++ String response = null; ++ String timingsURL = null; ++ try { ++ HttpURLConnection con = (HttpURLConnection) new URL("http://timings.aikar.co/post").openConnection(); ++ con.setDoOutput(true); ++ String hostName = "BrokenHost"; ++ try { ++ hostName = InetAddress.getLocalHost().getHostName(); ++ } catch (Exception ignored) {} ++ con.setRequestProperty("User-Agent", "Paper/" + Bukkit.getUnsafe().getTimingsServerName() + "/" + hostName); ++ con.setRequestMethod("POST"); ++ con.setInstanceFollowRedirects(false); ++ ++ OutputStream request = new GZIPOutputStream(con.getOutputStream()) {{ ++ this.def.setLevel(7); ++ }}; ++ ++ request.write(JSONValue.toJSONString(out).getBytes("UTF-8")); ++ request.close(); ++ ++ response = getResponse(con); ++ ++ if (con.getResponseCode() != 302) { ++ listeners.sendMessage( ++ ChatColor.RED + "Upload Error: " + con.getResponseCode() + ": " + con.getResponseMessage()); ++ listeners.sendMessage(ChatColor.RED + "Check your logs for more information"); ++ if (response != null) { ++ Bukkit.getLogger().log(Level.SEVERE, response); ++ } ++ return; ++ } ++ ++ timingsURL = con.getHeaderField("Location"); ++ listeners.sendMessage(ChatColor.GREEN + "View Timings Report: " + timingsURL); ++ ++ if (response != null && !response.isEmpty()) { ++ Bukkit.getLogger().log(Level.INFO, "Timing Response: " + response); ++ } ++ } catch (IOException ex) { ++ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); ++ if (response != null) { ++ Bukkit.getLogger().log(Level.SEVERE, response); ++ } ++ Bukkit.getLogger().log(Level.SEVERE, "Could not paste timings", ex); ++ } finally { ++ this.listeners.done(timingsURL); ++ } ++ } ++ ++ private String getResponse(HttpURLConnection con) throws IOException { ++ InputStream is = null; ++ try { ++ is = con.getInputStream(); ++ ByteArrayOutputStream bos = new ByteArrayOutputStream(); ++ ++ byte[] b = new byte[1024]; ++ int bytesRead; ++ while ((bytesRead = is.read(b)) != -1) { ++ bos.write(b, 0, bytesRead); ++ } ++ return bos.toString(); ++ ++ } catch (IOException ex) { ++ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); ++ Bukkit.getLogger().log(Level.WARNING, con.getResponseMessage(), ex); ++ return null; ++ } finally { ++ if (is != null) { ++ is.close(); ++ } ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fa154ed68187a2020e814db6345a8cc1119ab4ba +--- /dev/null ++++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +@@ -0,0 +1,119 @@ ++package co.aikar.timings; ++ ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.World; ++import net.minecraft.world.level.storage.WorldDataServer; ++ ++/** ++ * Set of timers per world, to track world specific timings. ++ */ ++// TODO: Re-implement missing timers ++public class WorldTimingsHandler { ++ public final Timing mobSpawn; ++ public final Timing doChunkUnload; ++ public final Timing doPortalForcer; ++ public final Timing scheduledBlocks; ++ public final Timing scheduledBlocksCleanup; ++ public final Timing scheduledBlocksTicking; ++ public final Timing chunkTicks; ++ public final Timing lightChunk; ++ public final Timing chunkTicksBlocks; ++ public final Timing doVillages; ++ public final Timing doChunkMap; ++ public final Timing doChunkMapUpdate; ++ public final Timing doChunkMapToUpdate; ++ public final Timing doChunkMapSortMissing; ++ public final Timing doChunkMapSortSendToPlayers; ++ public final Timing doChunkMapPlayersNeedingChunks; ++ public final Timing doChunkMapPendingSendToPlayers; ++ public final Timing doChunkMapUnloadChunks; ++ public final Timing doChunkGC; ++ public final Timing doSounds; ++ public final Timing entityRemoval; ++ public final Timing entityTick; ++ public final Timing tileEntityTick; ++ public final Timing tileEntityPending; ++ public final Timing tracker1; ++ public final Timing tracker2; ++ public final Timing doTick; ++ public final Timing tickEntities; ++ public final Timing chunks; ++ public final Timing newEntities; ++ public final Timing raids; ++ public final Timing chunkProviderTick; ++ public final Timing broadcastChunkUpdates; ++ public final Timing countNaturalMobs; ++ ++ public final Timing chunkLoad; ++ public final Timing chunkLoadPopulate; ++ public final Timing syncChunkLoad; ++ public final Timing chunkLoadLevelTimer; ++ public final Timing chunkIO; ++ public final Timing chunkPostLoad; ++ public final Timing worldSave; ++ public final Timing worldSaveChunks; ++ public final Timing worldSaveLevel; ++ public final Timing chunkSaveData; ++ ++ ++ public final Timing miscMobSpawning; ++ ++ public WorldTimingsHandler(World server) { ++ String name = ((WorldDataServer) server.getWorldData()).getName() + " - "; ++ ++ mobSpawn = Timings.ofSafe(name + "mobSpawn"); ++ doChunkUnload = Timings.ofSafe(name + "doChunkUnload"); ++ scheduledBlocks = Timings.ofSafe(name + "Scheduled Blocks"); ++ scheduledBlocksCleanup = Timings.ofSafe(name + "Scheduled Blocks - Cleanup"); ++ scheduledBlocksTicking = Timings.ofSafe(name + "Scheduled Blocks - Ticking"); ++ chunkTicks = Timings.ofSafe(name + "Chunk Ticks"); ++ lightChunk = Timings.ofSafe(name + "Light Chunk"); ++ chunkTicksBlocks = Timings.ofSafe(name + "Chunk Ticks - Blocks"); ++ doVillages = Timings.ofSafe(name + "doVillages"); ++ doChunkMap = Timings.ofSafe(name + "doChunkMap"); ++ doChunkMapUpdate = Timings.ofSafe(name + "doChunkMap - Update"); ++ doChunkMapToUpdate = Timings.ofSafe(name + "doChunkMap - To Update"); ++ doChunkMapSortMissing = Timings.ofSafe(name + "doChunkMap - Sort Missing"); ++ doChunkMapSortSendToPlayers = Timings.ofSafe(name + "doChunkMap - Sort Send To Players"); ++ doChunkMapPlayersNeedingChunks = Timings.ofSafe(name + "doChunkMap - Players Needing Chunks"); ++ doChunkMapPendingSendToPlayers = Timings.ofSafe(name + "doChunkMap - Pending Send To Players"); ++ doChunkMapUnloadChunks = Timings.ofSafe(name + "doChunkMap - Unload Chunks"); ++ doSounds = Timings.ofSafe(name + "doSounds"); ++ doChunkGC = Timings.ofSafe(name + "doChunkGC"); ++ doPortalForcer = Timings.ofSafe(name + "doPortalForcer"); ++ entityTick = Timings.ofSafe(name + "entityTick"); ++ entityRemoval = Timings.ofSafe(name + "entityRemoval"); ++ tileEntityTick = Timings.ofSafe(name + "tileEntityTick"); ++ tileEntityPending = Timings.ofSafe(name + "tileEntityPending"); ++ ++ chunkLoad = Timings.ofSafe(name + "Chunk Load"); ++ chunkLoadPopulate = Timings.ofSafe(name + "Chunk Load - Populate"); ++ syncChunkLoad = Timings.ofSafe(name + "Sync Chunk Load"); ++ chunkLoadLevelTimer = Timings.ofSafe(name + "Chunk Load - Load Level"); ++ chunkIO = Timings.ofSafe(name + "Chunk Load - DiskIO"); ++ chunkPostLoad = Timings.ofSafe(name + "Chunk Load - Post Load"); ++ worldSave = Timings.ofSafe(name + "World Save"); ++ worldSaveLevel = Timings.ofSafe(name + "World Save - Level"); ++ worldSaveChunks = Timings.ofSafe(name + "World Save - Chunks"); ++ chunkSaveData = Timings.ofSafe(name + "Chunk Save - Data"); ++ ++ tracker1 = Timings.ofSafe(name + "tracker stage 1"); ++ tracker2 = Timings.ofSafe(name + "tracker stage 2"); ++ doTick = Timings.ofSafe(name + "doTick"); ++ tickEntities = Timings.ofSafe(name + "tickEntities"); ++ ++ chunks = Timings.ofSafe(name + "Chunks"); ++ newEntities = Timings.ofSafe(name + "New entity registration"); ++ raids = Timings.ofSafe(name + "Raids"); ++ chunkProviderTick = Timings.ofSafe(name + "Chunk provider tick"); ++ broadcastChunkUpdates = Timings.ofSafe(name + "Broadcast chunk updates"); ++ countNaturalMobs = Timings.ofSafe(name + "Count natural mobs"); ++ ++ ++ miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); ++ } ++ ++ public static Timing getTickList(WorldServer worldserver, String timingsType) { ++ return Timings.ofSafe(((WorldDataServer) worldserver.getWorldData()).getName() + " - Scheduled " + timingsType); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index da922f395f0fff0881ead893c900c5b2623f48f0..1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -14,12 +14,15 @@ import java.util.concurrent.TimeUnit; + import java.util.logging.Level; + import java.util.regex.Pattern; + ++import com.google.common.collect.Lists; + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; + import org.bukkit.command.Command; + import org.bukkit.configuration.ConfigurationSection; + import org.bukkit.configuration.InvalidConfigurationException; + import org.bukkit.configuration.file.YamlConfiguration; ++import co.aikar.timings.Timings; ++import co.aikar.timings.TimingsManager; + + public class PaperConfig { + +@@ -188,4 +191,30 @@ public class PaperConfig { + config.addDefault(path, def); + return config.getString(path, config.getString(path)); + } ++ ++ public static String timingsServerName; ++ private static void timings() { ++ boolean timings = getBoolean("timings.enabled", true); ++ boolean verboseTimings = getBoolean("timings.verbose", true); ++ TimingsManager.privacy = getBoolean("timings.server-name-privacy", false); ++ TimingsManager.hiddenConfigs = getList("timings.hidden-config-entries", Lists.newArrayList("database", "settings.bungeecord-addresses", "settings.velocity-support.secret")); ++ if (!TimingsManager.hiddenConfigs.contains("settings.velocity-support.secret")) { ++ TimingsManager.hiddenConfigs.add("settings.velocity-support.secret"); ++ } ++ int timingHistoryInterval = getInt("timings.history-interval", 300); ++ int timingHistoryLength = getInt("timings.history-length", 3600); ++ timingsServerName = getString("timings.server-name", "Unknown Server"); ++ ++ ++ Timings.setVerboseTimingsEnabled(verboseTimings); ++ Timings.setTimingsEnabled(timings); ++ Timings.setHistoryInterval(timingHistoryInterval * 20); ++ Timings.setHistoryLength(timingHistoryLength * 20); ++ ++ log("Timings: " + timings + ++ " - Verbose: " + verboseTimings + ++ " - Interval: " + timeSummary(Timings.getHistoryInterval() / 20) + ++ " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + ++ " - Server Name: " + timingsServerName); ++ } + } +diff --git a/src/main/java/net/minecraft/commands/CustomFunction.java b/src/main/java/net/minecraft/commands/CustomFunction.java +index f96b132bb51c2d97703964a70fcb058f0649ac13..4c146ac041332230f6d9a01be28b6852c7624416 100644 +--- a/src/main/java/net/minecraft/commands/CustomFunction.java ++++ b/src/main/java/net/minecraft/commands/CustomFunction.java +@@ -15,12 +15,22 @@ public class CustomFunction { + + private final CustomFunction.c[] a; + private final MinecraftKey b; ++ // Paper start ++ public co.aikar.timings.Timing timing; ++ public co.aikar.timings.Timing getTiming() { ++ if (timing == null) { ++ timing = co.aikar.timings.MinecraftTimings.getCommandFunctionTiming(this); ++ } ++ return timing; ++ } ++ // Paper end + + public CustomFunction(MinecraftKey minecraftkey, CustomFunction.c[] acustomfunction_c) { + this.b = minecraftkey; + this.a = acustomfunction_c; + } + ++ public final MinecraftKey getMinecraftKey() { return this.a(); } // Paper - OBFHELPER + public MinecraftKey a() { + return this.b; + } +diff --git a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java +index 989683265a99fc51607aa130733e00033b444a6a..e47da20ab8ce4da34755e105bf55d8542fb50138 100644 +--- a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java ++++ b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java +@@ -6,6 +6,8 @@ import net.minecraft.server.level.WorldServer; + import net.minecraft.util.thread.IAsyncTaskHandler; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import co.aikar.timings.MinecraftTimings; // Paper ++import co.aikar.timings.Timing; // Paper + + // CraftBukkit start + import net.minecraft.server.MinecraftServer; +@@ -22,10 +24,13 @@ public class PlayerConnectionUtils { + + public static void ensureMainThread(Packet packet, T t0, IAsyncTaskHandler iasynctaskhandler) throws CancelledPacketHandleException { + if (!iasynctaskhandler.isMainThread()) { ++ Timing timing = MinecraftTimings.getPacketTiming(packet); // Paper - timings + iasynctaskhandler.execute(() -> { + if (MinecraftServer.getServer().hasStopped() || (t0 instanceof PlayerConnection && ((PlayerConnection) t0).processedDisconnect)) return; // CraftBukkit, MC-142590 + if (t0.a().isConnected()) { ++ try (Timing ignored = timing.startTiming()) { // Paper - timings + packet.a(t0); ++ } // Paper - timings + } else { + PlayerConnectionUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); + } +diff --git a/src/main/java/net/minecraft/server/CustomFunctionData.java b/src/main/java/net/minecraft/server/CustomFunctionData.java +index 21f5474a1cd60168ca059da542a432d40d88b514..07ca1234ad6ffa797003f7317fb88abf732bc159 100644 +--- a/src/main/java/net/minecraft/server/CustomFunctionData.java ++++ b/src/main/java/net/minecraft/server/CustomFunctionData.java +@@ -75,7 +75,7 @@ public class CustomFunctionData { + } else { + int j; + +- try { ++ try (co.aikar.timings.Timing timing = customfunction.getTiming().startTiming()) { // Paper + this.d = true; + int k = 0; + CustomFunction.c[] acustomfunction_c = customfunction.b(); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 5ce0dfade68257b51ad4a19a829e1fc0a0bbc3db..85c96e3f70a3ffecb6195a1d83053412eb180d78 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -174,7 +174,7 @@ import org.bukkit.craftbukkit.Main; + import org.bukkit.event.server.ServerLoadEvent; + // CraftBukkit end + +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper + import org.spigotmc.SlackActivityAccountant; // Spigot + + public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { +@@ -228,8 +228,8 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { +- return !this.canSleepForTick(); ++ return !this.canSleepForTickNoOversleep(); // Paper - move oversleep into full server tick + }); + } + +@@ -1122,10 +1135,18 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { ++ return !this.canOversleep(); ++ }); ++ isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); ++ // Paper end ++ + ++this.ticks; + this.b(booleansupplier); + if (i - this.T >= 5000000000L) { +@@ -1143,14 +1164,12 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit +- SpigotTimings.worldSaveTimer.startTiming(); // Spigot + MinecraftServer.LOGGER.debug("Autosave started"); + this.methodProfiler.enter("save"); + this.playerList.savePlayers(); + this.saveChunks(true, false, false); + this.methodProfiler.exit(); + MinecraftServer.LOGGER.debug("Autosave finished"); +- SpigotTimings.worldSaveTimer.stopTiming(); // Spigot + } + + this.methodProfiler.enter("snooper"); +@@ -1163,6 +1182,13 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { + // CraftBukkit start - fire RemoteServerCommandEvent +@@ -680,10 +682,39 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + if (event.isCancelled()) { + return; + } ++ // Paper start ++ if (s.toLowerCase().startsWith("timings") && s.toLowerCase().matches("timings (report|paste|get|merged|seperate)")) { ++ org.bukkit.command.BufferedCommandSender sender = new org.bukkit.command.BufferedCommandSender(); ++ Waitable waitable = new Waitable() { ++ @Override ++ protected String evaluate() { ++ return sender.getBuffer(); ++ } ++ }; ++ waitableArray[0] = waitable; ++ co.aikar.timings.Timings.generateReport(new co.aikar.timings.TimingsReportListener(sender, waitable)); ++ } else { ++ // Paper end + ServerCommand serverCommand = new ServerCommand(event.getCommand(), remoteControlCommandListener.getWrapper()); + server.dispatchServerCommand(remoteConsole, serverCommand); ++ } // Paper + // CraftBukkit end + }); ++ // Paper start ++ if (waitableArray[0] != null) { ++ //noinspection unchecked ++ Waitable waitable = waitableArray[0]; ++ try { ++ return waitable.get(); ++ } catch (java.util.concurrent.ExecutionException e) { ++ throw new RuntimeException("Exception processing rcon command " + s, e.getCause()); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // Maintain interrupted state ++ throw new RuntimeException("Interrupted processing rcon command " + s, e); ++ } ++ ++ } ++ // Paper end + return this.remoteControlCommandListener.getMessages(); + } + +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 0b5bcb60472c778574702a5ac26a6d02d54bfeac..3351c6bcc5244fd7565ba7af08f63ea4d999ce97 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -344,11 +344,13 @@ public class ChunkProviderServer extends IChunkProvider { + } + + gameprofilerfiller.c("getChunkCacheMiss"); +- world.timings.syncChunkLoadTimer.startTiming(); // Spigot + CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag); + ++ if (!completablefuture.isDone()) { // Paper ++ this.world.timings.syncChunkLoad.startTiming(); // Paper + this.serverThreadQueue.awaitTasks(completablefuture::isDone); +- world.timings.syncChunkLoadTimer.stopTiming(); // Spigot ++ this.world.timings.syncChunkLoad.stopTiming(); // Paper ++ } // Paper + ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { + return ichunkaccess1; + }, (playerchunk_failure) -> { +@@ -535,7 +537,9 @@ public class ChunkProviderServer extends IChunkProvider { + + public void save(boolean flag) { + this.tickDistanceManager(); ++ try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { // Paper - Timings + this.playerChunkMap.save(flag); ++ } // Paper - Timings + } + + @Override +@@ -572,7 +576,9 @@ public class ChunkProviderServer extends IChunkProvider { + this.tickDistanceManager(); + this.world.timings.doChunkMap.stopTiming(); // Spigot + this.world.getMethodProfiler().exitEnter("chunks"); ++ this.world.timings.chunks.startTiming(); // Paper - timings + this.tickChunks(); ++ this.world.timings.chunks.stopTiming(); // Paper - timings + this.world.timings.doChunkUnload.startTiming(); // Spigot + this.world.getMethodProfiler().exitEnter("unload"); + this.playerChunkMap.unloadChunks(booleansupplier); +@@ -596,19 +602,24 @@ public class ChunkProviderServer extends IChunkProvider { + boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit + + this.world.getMethodProfiler().enter("naturalSpawnCount"); ++ this.world.timings.countNaturalMobs.startTiming(); // Paper - timings + int l = this.chunkMapDistance.b(); + SpawnerCreature.d spawnercreature_d = SpawnerCreature.a(l, this.world.A(), this::a); ++ this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings + + this.p = spawnercreature_d; + this.world.getMethodProfiler().exit(); + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper ++ this.world.timings.chunkTicks.startTiming(); // Paper + this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... + Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); + + if (optional.isPresent()) { + this.world.getMethodProfiler().enter("broadcast"); ++ this.world.timings.broadcastChunkUpdates.startTiming(); // Paper - timings + playerchunk.a((Chunk) optional.get()); ++ this.world.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings + this.world.getMethodProfiler().exit(); + Optional optional1 = ((Either) playerchunk.b().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); + +@@ -622,25 +633,26 @@ public class ChunkProviderServer extends IChunkProvider { + SpawnerCreature.a(this.world, chunk, spawnercreature_d, this.allowAnimals, this.allowMonsters, flag2); + } + +- this.world.timings.doTickTiles.startTiming(); // Spigot ++ //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper + this.world.a(chunk, k); +- this.world.timings.doTickTiles.stopTiming(); // Spigot ++ //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper + } + } + } + }); ++ this.world.timings.chunkTicks.stopTiming(); // Paper + this.world.getMethodProfiler().enter("customSpawners"); + if (flag1) { ++ try (co.aikar.timings.Timing ignored = this.world.timings.miscMobSpawning.startTiming()) { // Paper - timings + this.world.doMobSpawning(this.allowMonsters, this.allowAnimals); ++ } // Paper - timings + } + + this.world.getMethodProfiler().exit(); + this.world.getMethodProfiler().exit(); + } + +- this.world.timings.tracker.startTiming(); // Spigot + this.playerChunkMap.g(); +- this.world.timings.tracker.stopTiming(); // Spigot + } + + private void a(long i, Consumer consumer) { +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 19856555793f742abb1178ede72dea5623f0e383..62245fa420390dc0a70ba9a95505dc46cd8aa64a 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -1,7 +1,9 @@ + package net.minecraft.server.level; + ++import co.aikar.timings.Timing; // Paper + import com.google.common.collect.ImmutableList; + import com.google.common.collect.Iterables; ++import com.google.common.collect.ComparisonChain; // Paper + import com.google.common.collect.Lists; + import com.google.common.collect.Queues; + import com.google.common.collect.Sets; +@@ -554,11 +556,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + private CompletableFuture> f(ChunkCoordIntPair chunkcoordintpair) { + return CompletableFuture.supplyAsync(() -> { +- try { ++ try (Timing ignored = this.world.timings.chunkLoad.startTimingIfSync()) { // Paper + this.world.getMethodProfiler().c("chunkLoad"); +- NBTTagCompound nbttagcompound = this.readChunkData(chunkcoordintpair); ++ NBTTagCompound nbttagcompound; // Paper ++ try (Timing ignored2 = this.world.timings.chunkIO.startTimingIfSync()) { // Paper start - timings ++ nbttagcompound = this.readChunkData(chunkcoordintpair); ++ } // Paper end + +- if (nbttagcompound != null) { ++ if (nbttagcompound != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings + boolean flag = nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8); + + if (flag) { +@@ -570,7 +575,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + PlayerChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", chunkcoordintpair); +- } ++ }} // Paper + } catch (ReportedException reportedexception) { + Throwable throwable = reportedexception.getCause(); + +@@ -607,7 +612,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return "chunkGenerate " + chunkstatus.d(); + }); + return completablefuture.thenComposeAsync((either) -> { +- return (CompletableFuture) either.map((list) -> { ++ return either.map((list) -> { // Paper - Shut up. + try { + CompletableFuture> completablefuture1 = chunkstatus.a(this.world, this.chunkGenerator, this.definedStructureManager, this.lightEngine, (ichunkaccess) -> { + return this.c(playerchunk); +@@ -660,6 +665,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + ChunkStatus chunkstatus = PlayerChunk.getChunkStatus(playerchunk.getTicketLevel()); + + return !chunkstatus.b(ChunkStatus.FULL) ? PlayerChunk.UNLOADED_CHUNK_ACCESS : either.mapLeft((ichunkaccess) -> { ++ try (Timing ignored = world.timings.chunkPostLoad.startTimingIfSync()) { // Paper + ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); + Chunk chunk; + +@@ -719,6 +725,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + return chunk; ++ } // Paper + }); + }, (runnable) -> { + Mailbox mailbox = this.mailboxMain; +@@ -1177,6 +1184,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + PlayerChunkMap.EntityTracker playerchunkmap_entitytracker; + ObjectIterator objectiterator; ++ world.timings.tracker1.startTiming(); // Paper + + for (objectiterator = this.trackedEntities.values().iterator(); objectiterator.hasNext(); playerchunkmap_entitytracker.trackerEntry.a()) { + playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); +@@ -1194,16 +1202,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + playerchunkmap_entitytracker.e = sectionposition1; + } + } ++ world.timings.tracker1.stopTiming(); // Paper + + if (!list.isEmpty()) { + objectiterator = this.trackedEntities.values().iterator(); + ++ world.timings.tracker2.startTiming(); // Paper + while (objectiterator.hasNext()) { + playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); + playerchunkmap_entitytracker.track(list); + } ++ world.timings.tracker2.stopTiming(); // Paper + } + ++ + } + + protected void broadcast(Entity entity, Packet packet) { +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 780e541b8d594a8a6dc3a8626a82218f2502a5c7..cf38d517821659e25e786a805e229ef2d626d75f 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -2,6 +2,8 @@ package net.minecraft.server.level; + + import com.google.common.annotations.VisibleForTesting; + import com.google.common.collect.Iterables; ++import co.aikar.timings.TimingHistory; // Paper ++import co.aikar.timings.Timings; // Paper + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Queues; +@@ -153,7 +155,6 @@ import net.minecraft.world.level.block.ITileEntity; + import net.minecraft.world.level.storage.WorldDataServer; + import org.bukkit.Bukkit; + import org.bukkit.WeatherType; +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.event.CraftEventFactory; + import org.bukkit.craftbukkit.util.WorldUUID; + import org.bukkit.event.entity.CreatureSpawnEvent; +@@ -209,10 +210,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { + // CraftBukkit end + this.nextTickListBlock = new TickListServer<>(this, (block) -> { + return block == null || block.getBlockData().isAir(); +- }, IRegistry.BLOCK::getKey, this::b); ++ }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings + this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { + return fluidtype == null || fluidtype == FluidTypes.EMPTY; +- }, IRegistry.FLUID::getKey, this::a); ++ }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings + this.navigators = Sets.newHashSet(); + this.L = new ObjectLinkedOpenHashSet(); + this.Q = flag1; +@@ -442,17 +443,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.Q(); + this.b(); + gameprofilerfiller.exitEnter("chunkSource"); ++ this.timings.chunkProviderTick.startTiming(); // Paper - timings + this.getChunkProvider().tick(booleansupplier); ++ this.timings.chunkProviderTick.stopTiming(); // Paper - timings + gameprofilerfiller.exitEnter("tickPending"); +- timings.doTickPending.startTiming(); // Spigot ++ timings.scheduledBlocks.startTiming(); // Paper + if (!this.isDebugWorld()) { + this.nextTickListBlock.b(); + this.nextTickListFluid.b(); + } +- timings.doTickPending.stopTiming(); // Spigot ++ timings.scheduledBlocks.stopTiming(); // Paper + + gameprofilerfiller.exitEnter("raid"); ++ this.timings.raids.startTiming(); // Paper - timings + this.persistentRaid.a(); ++ this.timings.raids.stopTiming(); // Paper - timings + gameprofilerfiller.exitEnter("blockEvents"); + timings.doSounds.startTiming(); // Spigot + this.ak(); +@@ -624,6 +629,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + gameprofilerfiller.exitEnter("tickBlocks"); ++ timings.chunkTicksBlocks.startTiming(); // Paper + if (i > 0) { + ChunkSection[] achunksection = chunk.getSections(); + int l = achunksection.length; +@@ -655,7 +661,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + } + } +- ++ timings.chunkTicksBlocks.stopTiming(); // Paper + gameprofilerfiller.exit(); + } + +@@ -753,14 +759,22 @@ public class WorldServer extends World implements GeneratorAccessSeed { + if (!(entity instanceof EntityHuman) && !this.getChunkProvider().a(entity)) { + this.chunkCheck(entity); + } else { ++ ++TimingHistory.entityTicks; // Paper - timings + // Spigot start ++ co.aikar.timings.Timing timer; // Paper + if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { + entity.ticksLived++; ++ timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings + entity.inactiveTick(); ++ } finally { timer.stopTiming(); } // Paper + return; + } + // Spigot end +- entity.tickTimer.startTiming(); // Spigot ++ // Paper start- timings ++ TimingHistory.activatedEntityTicks++; ++ timer = entity.getVehicle() != null ? entity.getEntityType().passengerTickTimer.startTiming() : entity.getEntityType().tickTimer.startTiming(); ++ try { ++ // Paper end - timings + entity.g(entity.locX(), entity.locY(), entity.locZ()); + entity.lastYaw = entity.yaw; + entity.lastPitch = entity.pitch; +@@ -787,7 +801,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.a(entity, entity1); + } + } +- entity.tickTimer.stopTiming(); // Spigot ++ } finally { timer.stopTiming(); } // Paper - timings + + } + } +@@ -865,6 +879,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + if (!flag1) { + org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit ++ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper + if (iprogressupdate != null) { + iprogressupdate.a(new ChatMessage("menu.savingLevel")); + } +@@ -874,7 +889,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { + iprogressupdate.c(new ChatMessage("menu.savingChunks")); + } + ++ timings.worldSaveChunks.startTiming(); // Paper + chunkproviderserver.save(flag); ++ timings.worldSaveChunks.stopTiming(); // Paper ++ } // Paper + } + + // CraftBukkit start - moved from MinecraftServer.saveChunks +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 265004691f12b3476f3892f5555768717e9c6d19..536a351e1879fcb8066546d1179ad1af034b95da 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -211,6 +211,7 @@ import org.bukkit.inventory.EquipmentSlot; + import org.bukkit.inventory.InventoryView; + import org.bukkit.inventory.SmithingInventory; + import org.bukkit.util.NumberConversions; ++import co.aikar.timings.MinecraftTimings; // Paper + // CraftBukkit end + + public class PlayerConnection implements PacketListenerPlayIn { +@@ -293,7 +294,6 @@ public class PlayerConnection implements PacketListenerPlayIn { + // CraftBukkit end + + public void tick() { +- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.startTiming(); // Spigot + this.syncPosition(); + this.player.lastX = this.player.locX(); + this.player.lastY = this.player.locY(); +@@ -369,7 +369,6 @@ public class PlayerConnection implements PacketListenerPlayIn { + this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854 + this.disconnect(new ChatMessage("multiplayer.disconnect.idling")); + } +- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.stopTiming(); // Spigot + + } + +@@ -1917,7 +1916,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + // CraftBukkit end + + private void handleCommand(String s) { +- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot ++ MinecraftTimings.playerCommandTimer.startTiming(); // Paper + // CraftBukkit start - whole method + if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot + this.LOGGER.info(this.player.getName() + " issued server command: " + s); +@@ -1928,7 +1927,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { +- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot ++ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper + return; + } + +@@ -1941,7 +1940,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + java.util.logging.Logger.getLogger(PlayerConnection.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); + return; + } finally { +- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot ++ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper + } + // this.minecraftServer.getCommandDispatcher().a(this.player.getCommandListener(), s); + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 5d1bbc42b4d65aa735570c53e4e6bc9e08899749..c601a5c577e438a3fa8dd4c5f36dbe9494b03d52 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1,5 +1,6 @@ + package net.minecraft.server.players; + ++import co.aikar.timings.MinecraftTimings; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; +@@ -1022,10 +1023,11 @@ public abstract class PlayerList { + } + + public void savePlayers() { ++ MinecraftTimings.savePlayers.startTiming(); // Paper + for (int i = 0; i < this.players.size(); ++i) { + this.savePlayerFile((EntityPlayer) this.players.get(i)); + } +- ++ MinecraftTimings.savePlayers.stopTiming(); // Paper + } + + public WhiteList getWhitelist() { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 2bea2f4748cadf479dd4f89792ef5ffdd88e9cab..306f6c0db2333cce5dfc4bf1c09bfef05119a28b 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -116,7 +116,6 @@ import org.bukkit.craftbukkit.event.CraftPortalEvent; + import org.bukkit.entity.Hanging; + import org.bukkit.entity.LivingEntity; + import org.bukkit.entity.Vehicle; +-import org.spigotmc.CustomTimingsHandler; // Spigot + import org.bukkit.event.entity.EntityCombustByEntityEvent; + import org.bukkit.event.hanging.HangingBreakByEntityEvent; + import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; +@@ -248,7 +247,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only + public boolean forceExplosionKnockback; // SPIGOT-949 + public boolean persistentInvisibility = false; +- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot + // Spigot start + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; +@@ -617,7 +615,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public void move(EnumMoveType enummovetype, Vec3D vec3d) { +- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot + if (this.noclip) { + this.a(this.getBoundingBox().c(vec3d)); + this.recalcPosition(); +@@ -753,7 +750,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + this.world.getMethodProfiler().exit(); + } +- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot + } + + protected BlockPosition ap() { +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index f88c3dfecdce58fbdb695103fd481e9cbd0c266c..e771d84c972cea4ca1b4b5d25cd573cfcbce4579 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -135,7 +135,7 @@ import org.bukkit.event.entity.EntityTeleportEvent; + import org.bukkit.event.player.PlayerItemConsumeEvent; + // CraftBukkit end + +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper + + public abstract class EntityLiving extends Entity { + +@@ -2458,7 +2458,6 @@ public abstract class EntityLiving extends Entity { + + @Override + public void tick() { +- SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot + super.tick(); + this.t(); + this.v(); +@@ -2507,9 +2506,7 @@ public abstract class EntityLiving extends Entity { + } + } + +- SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot + this.movementTick(); +- SpigotTimings.timerEntityTickRest.startTiming(); // Spigot + double d0 = this.locX() - this.lastX; + double d1 = this.locZ() - this.lastZ; + float f = (float) (d0 * d0 + d1 * d1); +@@ -2589,8 +2586,6 @@ public abstract class EntityLiving extends Entity { + if (this.isSleeping()) { + this.pitch = 0.0F; + } +- +- SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot + } + + public void updateEquipment() { +@@ -2772,7 +2767,6 @@ public abstract class EntityLiving extends Entity { + + this.setMot(d4, d5, d6); + this.world.getMethodProfiler().enter("ai"); +- SpigotTimings.timerEntityAI.startTiming(); // Spigot + if (this.isFrozen()) { + this.jumping = false; + this.aR = 0.0F; +@@ -2782,7 +2776,6 @@ public abstract class EntityLiving extends Entity { + this.doTick(); + this.world.getMethodProfiler().exit(); + } +- SpigotTimings.timerEntityAI.stopTiming(); // Spigot + + this.world.getMethodProfiler().exit(); + this.world.getMethodProfiler().enter("jump"); +@@ -2817,9 +2810,9 @@ public abstract class EntityLiving extends Entity { + this.r(); + AxisAlignedBB axisalignedbb = this.getBoundingBox(); + +- SpigotTimings.timerEntityAIMove.startTiming(); // Spigot ++ // SpigotTimings.timerEntityAIMove.startTiming(); // Spigot // Paper + this.g(new Vec3D((double) this.aR, (double) this.aS, (double) this.aT)); +- SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot ++ // SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot // Paper + this.world.getMethodProfiler().exit(); + this.world.getMethodProfiler().enter("push"); + if (this.bf > 0) { +@@ -2827,9 +2820,7 @@ public abstract class EntityLiving extends Entity { + this.a(axisalignedbb, this.getBoundingBox()); + } + +- SpigotTimings.timerEntityAICollision.startTiming(); // Spigot + this.collideNearby(); +- SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot + this.world.getMethodProfiler().exit(); + if (!this.world.isClientSide && this.dO() && this.aG()) { + this.damageEntity(DamageSource.DROWN, 1.0F); +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index dc92b112770955f9fa49a408262da2e5bbc4bf98..a707ba365e25ea15e2e9d22110696b6136aa0c6f 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -281,7 +281,9 @@ public class EntityTypes { + return IRegistry.ENTITY_TYPE.getOptional(MinecraftKey.a(s)); + } + +- public EntityTypes(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntitySize entitysize, int i, int j) { ++ public final String id; ++ public EntityTypes(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntitySize entitysize, int i, int j) { this(entitytypes_b, enumcreaturetype, flag, flag1, flag2, flag3, immutableset, entitysize, i, j, "custom"); } // Paper - old signature ++ public EntityTypes(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntitySize entitysize, int i, int j, String id) { // Paper - add id + this.bf = entitytypes_b; + this.bg = enumcreaturetype; + this.bl = flag3; +@@ -292,6 +294,14 @@ public class EntityTypes { + this.br = entitysize; + this.bm = i; + this.bn = j; ++ ++ // Paper start - timings ++ this.id = id; ++ this.tickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "tick"); ++ this.inactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "inactiveTick"); ++ this.passengerTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerTick"); ++ this.passengerInactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerInactiveTick"); ++ // Paper end + } + + @Nullable +@@ -512,6 +522,12 @@ public class EntityTypes { + return this.bn; + } + ++ // Paper start - timings ++ public final co.aikar.timings.Timing tickTimer; ++ public final co.aikar.timings.Timing inactiveTickTimer; ++ public final co.aikar.timings.Timing passengerTickTimer; ++ public final co.aikar.timings.Timing passengerInactiveTickTimer; ++ // Paper end + public boolean isDeltaTracking() { + return this != EntityTypes.PLAYER && this != EntityTypes.LLAMA_SPIT && this != EntityTypes.WITHER && this != EntityTypes.BAT && this != EntityTypes.ITEM_FRAME && this != EntityTypes.LEASH_KNOT && this != EntityTypes.PAINTING && this != EntityTypes.END_CRYSTAL && this != EntityTypes.EVOKER_FANGS; + } +@@ -599,7 +615,7 @@ public class EntityTypes { + SystemUtils.a(DataConverterTypes.ENTITY_TREE, s); + } + +- return new EntityTypes<>(this.a, this.b, this.d, this.e, this.f, this.g, this.c, this.j, this.h, this.i); ++ return new EntityTypes<>(this.a, this.b, this.d, this.e, this.f, this.g, this.c, this.j, this.h, this.i, s); // Paper - add id + } + } + +diff --git a/src/main/java/net/minecraft/world/level/TickListServer.java b/src/main/java/net/minecraft/world/level/TickListServer.java +index e7296b8684d6d8c2f256d4a9da87f408a198c331..c221e5caf518b8c588390e438346fa58fa8c5a38 100644 +--- a/src/main/java/net/minecraft/world/level/TickListServer.java ++++ b/src/main/java/net/minecraft/world/level/TickListServer.java +@@ -38,12 +38,17 @@ public class TickListServer implements TickList { + private final List> g = Lists.newArrayList(); + private final Consumer> h; + +- public TickListServer(WorldServer worldserver, Predicate predicate, Function function, Consumer> consumer) { ++ public TickListServer(WorldServer worldserver, Predicate predicate, Function function, Consumer> consumer, String timingsType) { // Paper + this.a = predicate; + this.b = function; + this.e = worldserver; + this.h = consumer; ++ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Cleanup"); ++ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Ticking"); + } ++ private final co.aikar.timings.Timing timingCleanup; // Paper ++ private final co.aikar.timings.Timing timingTicking; // Paper ++ // Paper end + + public void b() { + int i = this.nextTickList.size(); +@@ -66,6 +71,7 @@ public class TickListServer implements TickList { + + this.e.getMethodProfiler().enter("cleaning"); + ++ this.timingCleanup.startTiming(); // Paper + NextTickListEntry nextticklistentry; + + while (i > 0 && iterator.hasNext()) { +@@ -81,7 +87,9 @@ public class TickListServer implements TickList { + --i; + } + } ++ this.timingCleanup.stopTiming(); // Paper + ++ this.timingTicking.startTiming(); // Paper + this.e.getMethodProfiler().exitEnter("ticking"); + + while ((nextticklistentry = (NextTickListEntry) this.f.poll()) != null) { +@@ -101,6 +109,7 @@ public class TickListServer implements TickList { + } + } + ++ this.timingTicking.stopTiming(); // Paper + this.e.getMethodProfiler().exit(); + this.g.clear(); + this.f.clear(); +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 0cbebc2095489c240fecd3fd32f5373be2a3d684..1b03c69fa7ffeca4083470a179e18be828b0a957 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -70,7 +70,6 @@ import net.minecraft.server.level.WorldServer; + import net.minecraft.world.entity.item.EntityItem; + import net.minecraft.world.level.border.IWorldBorderListener; + import org.bukkit.Bukkit; +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.block.CapturedBlockState; +@@ -132,7 +131,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper + +- public final SpigotTimings.WorldTimingsHandler timings; // Spigot ++ public final co.aikar.timings.WorldTimingsHandler timings; // Paper + public static BlockPosition lastPhysicsProblem; // Spigot + private org.spigotmc.TickLimiter entityLimiter; + private org.spigotmc.TickLimiter tileLimiter; +@@ -217,7 +216,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public void c(WorldBorder worldborder, double d0) {} + }); + // CraftBukkit end +- timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings ++ timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings + this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + } +@@ -797,15 +796,14 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + } + + timings.tileEntityPending.stopTiming(); // Spigot ++ co.aikar.timings.TimingHistory.tileEntityTicks += this.tileEntityListTick.size(); // Paper + gameprofilerfiller.exit(); + spigotConfig.currentPrimedTnt = 0; // Spigot + } + + public void a(Consumer consumer, Entity entity) { + try { +- SpigotTimings.tickEntityTimer.startTiming(); // Spigot + consumer.accept(entity); +- SpigotTimings.tickEntityTimer.stopTiming(); // Spigot + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.a(throwable, "Ticking entity"); + CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being ticked"); +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index bab55395ba92d0f3788e798ae0e154d62c4ec2fa..d285c4e3d9f938973bf7fb904680044b414e6236 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -61,6 +61,15 @@ public class Block extends BlockBase implements IMaterial { + }); + protected final BlockStateList blockStateList; + private IBlockData blockData; ++ // Paper start ++ public co.aikar.timings.Timing timing; ++ public co.aikar.timings.Timing getTiming() { ++ if (timing == null) { ++ timing = co.aikar.timings.MinecraftTimings.getBlockTiming(this); ++ } ++ return timing; ++ } ++ // Paper end + @Nullable + private String name; + @Nullable +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +index 75110c41af3e0097aef65091a2497dd87d08b4b2..9ebd91e1309938f81583eb3d4dd97fd39bcc930a 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +@@ -23,10 +23,12 @@ import org.bukkit.inventory.InventoryHolder; + // CraftBukkit end + + import org.spigotmc.CustomTimingsHandler; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper ++import co.aikar.timings.Timing; // Paper + + public abstract class TileEntity implements net.minecraft.server.KeyedObject { // Paper + +- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot ++ public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper + // CraftBukkit start - data containers + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); + public CraftPersistentDataContainer persistentDataContainer; +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index acdcece38a4b30d6c89eb4342918ae8997db9f0b..ac576d268b23148089d404cb22d8c2f9d1a79d6e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -733,6 +733,7 @@ public class Chunk implements IChunkAccess { + server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(this.bukkitChunk, this.needsDecoration)); + + if (this.needsDecoration) { ++ try (co.aikar.timings.Timing ignored = this.world.timings.chunkLoadPopulate.startTiming()) { // Paper + this.needsDecoration = false; + java.util.Random random = new java.util.Random(); + random.setSeed(world.getSeed()); +@@ -752,6 +753,7 @@ public class Chunk implements IChunkAccess { + } + } + server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); ++ } // Paper + } + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index 27703b807735d52313b93f8f606aa263571525d2..f301c7ba4b17b92c6cf2fcee6da1e67081dad4fa 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.chunk.storage; + ++import co.aikar.timings.Timings; + import com.google.common.collect.Maps; + import it.unimi.dsi.fastutil.longs.LongOpenHashSet; + import it.unimi.dsi.fastutil.longs.LongSet; +@@ -446,7 +447,6 @@ public class ChunkRegionLoader { + private static void loadEntities(NBTTagCompound nbttagcompound, Chunk chunk) { + NBTTagList nbttaglist = nbttagcompound.getList("Entities", 10); + World world = chunk.getWorld(); +- world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot + + for (int i = 0; i < nbttaglist.size(); ++i) { + NBTTagCompound nbttagcompound1 = nbttaglist.getCompound(i); +@@ -458,8 +458,6 @@ public class ChunkRegionLoader { + chunk.d(true); + } + +- world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot +- world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot + NBTTagList nbttaglist1 = nbttagcompound.getList("TileEntities", 10); + + for (int j = 0; j < nbttaglist1.size(); ++j) { +@@ -477,8 +475,6 @@ public class ChunkRegionLoader { + } + } + } +- world.timings.syncChunkLoadTileEntitiesTimer.stopTiming(); // Spigot +- + } + + private static NBTTagCompound a(ChunkCoordIntPair chunkcoordintpair, Map, StructureStart> map, Map, LongSet> map1) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 82f5b3387f9e71ae258111b7196986623452dc02..0c1e12b0b43f949d4ace600b2ccdffe52faab1e6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2074,12 +2074,31 @@ public final class CraftServer implements Server { + private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() + { + ++ @Deprecated + @Override + public YamlConfiguration getConfig() + { + return org.spigotmc.SpigotConfig.config; + } + ++ @Override ++ public YamlConfiguration getBukkitConfig() ++ { ++ return configuration; ++ } ++ ++ @Override ++ public YamlConfiguration getSpigotConfig() ++ { ++ return org.spigotmc.SpigotConfig.config; ++ } ++ ++ @Override ++ public YamlConfiguration getPaperConfig() ++ { ++ return com.destroystokyo.paper.PaperConfig.config; ++ } ++ + @Override + public void restart() { + org.spigotmc.RestartCommand.restart(); +diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +index ebf2c62e9ea126577a6cbcbbeb3f3aba259a1f63..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 +--- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java ++++ b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +@@ -1,163 +0,0 @@ +-package org.bukkit.craftbukkit; +- +-import java.util.HashMap; +-import net.minecraft.world.entity.Entity; +-import net.minecraft.world.level.World; +-import net.minecraft.world.level.block.entity.TileEntity; +-import net.minecraft.world.level.storage.WorldDataServer; +-import org.bukkit.craftbukkit.scheduler.CraftTask; +-import org.bukkit.plugin.java.JavaPluginLoader; +-import org.bukkit.scheduler.BukkitTask; +-import org.spigotmc.CustomTimingsHandler; +- +-public class SpigotTimings { +- +- public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); +- public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); +- public static final CustomTimingsHandler commandFunctionsTimer = new CustomTimingsHandler("Command Functions"); +- public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler"); +- public static final CustomTimingsHandler playerConnectionTimer = new CustomTimingsHandler("** PlayerConnection"); +- public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); +- public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); +- public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update"); +- public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command"); +- public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save"); +- +- public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); +- public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); +- public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); +- public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); +- +- public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); +- public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); +- public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); +- public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); +- public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); +- +- public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue"); +- public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer); +- +- public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); +- +- public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); +- public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); +- +- public static final HashMap entityTypeTimingMap = new HashMap(); +- public static final HashMap tileEntityTypeTimingMap = new HashMap(); +- public static final HashMap pluginTaskTimingMap = new HashMap(); +- +- /** +- * Gets a timer associated with a plugins tasks. +- * @param task +- * @param period +- * @return +- */ +- public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { +- if (!task.isSync()) { +- return null; +- } +- String plugin; +- final CraftTask ctask = (CraftTask) task; +- +- if (task.getOwner() != null) { +- plugin = task.getOwner().getDescription().getFullName(); +- } else { +- plugin = "Unknown"; +- } +- String taskname = ctask.getTaskName(); +- +- String name = "Task: " + plugin + " Runnable: " + taskname; +- if (period > 0) { +- name += "(interval:" + period + ")"; +- } else { +- name += "(Single)"; +- } +- CustomTimingsHandler result = pluginTaskTimingMap.get(name); +- if (result == null) { +- result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); +- pluginTaskTimingMap.put(name, result); +- } +- return result; +- } +- +- /** +- * Get a named timer for the specified entity type to track type specific timings. +- * @param entity +- * @return +- */ +- public static CustomTimingsHandler getEntityTimings(Entity entity) { +- String entityType = entity.getClass().getName(); +- CustomTimingsHandler result = entityTypeTimingMap.get(entityType); +- if (result == null) { +- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), activatedEntityTimer); +- entityTypeTimingMap.put(entityType, result); +- } +- return result; +- } +- +- /** +- * Get a named timer for the specified tile entity type to track type specific timings. +- * @param entity +- * @return +- */ +- public static CustomTimingsHandler getTileEntityTimings(TileEntity entity) { +- String entityType = entity.getClass().getName(); +- CustomTimingsHandler result = tileEntityTypeTimingMap.get(entityType); +- if (result == null) { +- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), tickTileEntityTimer); +- tileEntityTypeTimingMap.put(entityType, result); +- } +- return result; +- } +- +- /** +- * Set of timers per world, to track world specific timings. +- */ +- public static class WorldTimingsHandler { +- public final CustomTimingsHandler mobSpawn; +- public final CustomTimingsHandler doChunkUnload; +- public final CustomTimingsHandler doTickPending; +- public final CustomTimingsHandler doTickTiles; +- public final CustomTimingsHandler doChunkMap; +- public final CustomTimingsHandler doSounds; +- public final CustomTimingsHandler entityTick; +- public final CustomTimingsHandler tileEntityTick; +- public final CustomTimingsHandler tileEntityPending; +- public final CustomTimingsHandler tracker; +- public final CustomTimingsHandler doTick; +- public final CustomTimingsHandler tickEntities; +- +- public final CustomTimingsHandler syncChunkLoadTimer; +- public final CustomTimingsHandler syncChunkLoadStructuresTimer; +- public final CustomTimingsHandler syncChunkLoadEntitiesTimer; +- public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer; +- public final CustomTimingsHandler syncChunkLoadTileTicksTimer; +- public final CustomTimingsHandler syncChunkLoadPostTimer; +- +- public WorldTimingsHandler(World server) { +- String name = ((WorldDataServer) server.worldData).getName() + " - "; +- +- mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); +- doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); +- doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); +- doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); +- doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); +- doSounds = new CustomTimingsHandler("** " + name + "doSounds"); +- entityTick = new CustomTimingsHandler("** " + name + "entityTick"); +- tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); +- tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending"); +- +- syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); +- syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); +- syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); +- syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); +- syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); +- syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); +- +- +- tracker = new CustomTimingsHandler(name + "tracker"); +- doTick = new CustomTimingsHandler(name + "doTick"); +- tickEntities = new CustomTimingsHandler(name + "tickEntities"); +- } +- } +-} +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index c3a06eabbff3c37c88b1f09fe4bf806418e3a4d4..b51a874e4665f977a154792e6216e03e04525f39 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1808,6 +1808,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + packet.components = components; + getHandle().playerConnection.sendPacket(packet); + } ++ ++ // Paper start ++ @Override ++ public int getPing() ++ { ++ return getHandle().ping; ++ } ++ // Paper end + }; + + public Player.Spigot spigot() +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 4bf48f77f3f7cd62a91590543f5af441c8268029..ffe9cc1011226d604dc5499e7692e9a9a5132b72 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.scheduler; + ++import co.aikar.timings.MinecraftTimings; // Paper + import com.google.common.util.concurrent.ThreadFactoryBuilder; + import java.util.ArrayList; + import java.util.Comparator; +@@ -179,7 +180,8 @@ public class CraftScheduler implements BukkitScheduler { + } + + public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { +- final CraftTask task = new CraftTask(run, nextId(), taskName); ++ final CraftTask task = new CraftTask(run, nextId(), "Internal - " + (taskName != null ? taskName : "Unknown")); ++ task.internal = true; + return handle(task, delay); + } + +@@ -260,7 +262,7 @@ public class CraftScheduler implements BukkitScheduler { + } + return false; + } +- }); ++ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer();}}; // Paper + handle(task, 0L); + for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { + if (taskPending == task) { +@@ -295,7 +297,7 @@ public class CraftScheduler implements BukkitScheduler { + } + } + } +- }); ++ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer(plugin);}}; // Paper + handle(task, 0L); + for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { + if (taskPending == task) { +@@ -402,9 +404,7 @@ public class CraftScheduler implements BukkitScheduler { + if (task.isSync()) { + currentTask = task; + try { +- task.timings.startTiming(); // Spigot + task.run(); +- task.timings.stopTiming(); // Spigot + } catch (final Throwable throwable) { + // Paper start + String msg = String.format( +@@ -438,8 +438,10 @@ public class CraftScheduler implements BukkitScheduler { + runners.remove(task.getTaskId()); + } + } ++ MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); + pending.addAll(temp); + temp.clear(); ++ MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); + debugHead = debugHead.getNextHead(currentTick); + } + +@@ -472,6 +474,7 @@ public class CraftScheduler implements BukkitScheduler { + } + + private void parsePending() { ++ MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); + CraftTask head = this.head; + CraftTask task = head.getNext(); + CraftTask lastTask = head; +@@ -490,6 +493,7 @@ public class CraftScheduler implements BukkitScheduler { + task.setNext(null); + } + this.head = lastTask; ++ MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); + } + + private boolean isReady(final int currentTick) { +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +index 09aa6809c5400ce8548ac902908b750ce7c964ec..3c96807e97657502849093e4371e9fef3584a346 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +@@ -1,12 +1,15 @@ + package org.bukkit.craftbukkit.scheduler; + + import java.util.function.Consumer; ++ ++import co.aikar.timings.NullTimingHandler; + import org.bukkit.Bukkit; + import org.bukkit.plugin.Plugin; + import org.bukkit.scheduler.BukkitTask; + +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.spigotmc.CustomTimingsHandler; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper ++import co.aikar.timings.Timing; // Paper + + public class CraftTask implements BukkitTask, Runnable { // Spigot + +@@ -26,12 +29,12 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + */ + private volatile long period; + private long nextRun; +- private final Runnable rTask; +- private final Consumer cTask; ++ public final Runnable rTask; // Paper ++ public final Consumer cTask; // Paper ++ public Timing timings; // Paper + private final Plugin plugin; + private final int id; + +- final CustomTimingsHandler timings; // Spigot + CraftTask() { + this(null, null, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); + } +@@ -51,7 +54,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + this.id = id; + this.period = CraftTask.NO_REPEATING; + this.taskName = taskName; +- this.timings = null; // Will be changed in later patch ++ this.timings = MinecraftTimings.getInternalTaskName(taskName); + } + // Paper end + +@@ -72,7 +75,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + } + this.id = id; + this.period = period; +- this.timings = this.isSync() ? SpigotTimings.getPluginTaskTimings(this, period) : null; // Spigot ++ timings = task != null ? MinecraftTimings.getPluginTaskTimings(this, period) : NullTimingHandler.NULL; // Paper + } + + @Override +@@ -92,11 +95,13 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + + @Override + public void run() { ++ try (Timing ignored = timings.startTiming()) { // Paper + if (rTask != null) { + rTask.run(); + } else { + cTask.accept(this); + } ++ } // Paper + } + + long getPeriod() { +@@ -123,7 +128,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + this.next = next; + } + +- Class getTaskClass() { ++ public Class getTaskClass() { + return (rTask != null) ? rTask.getClass() : ((cTask != null) ? cTask.getClass() : null); + } + +@@ -147,9 +152,4 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + return true; + } + +- // Spigot start +- public String getTaskName() { +- return (getTaskClass() == null) ? "Unknown" : getTaskClass().getName(); +- } +- // Spigot end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java +index e52ef47b783785dc214746b678e7b549aea9a274..3d90b3426873a3528af14f7f1ab0adae0027da2e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java +@@ -5,6 +5,7 @@ import org.bukkit.util.CachedServerIcon; + public class CraftIconCache implements CachedServerIcon { + public final String value; + ++ public String getData() { return value; } // Paper + public CraftIconCache(final String value) { + this.value = value; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 972840fd32cd4b6cb73b7f97d06dcd5699c28ba4..65131f0977fa55c4761c34ce52720170feb61a72 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -158,6 +158,12 @@ public final class CraftMagicNumbers implements UnsafeValues { + return CraftNamespacedKey.toMinecraft(mat.getKey()); + } + // ======================================================================== ++ // Paper start ++ @Override ++ public void reportTimings() { ++ co.aikar.timings.TimingsExport.reportTimings(); ++ } ++ // Paper end + + public static byte toLegacyData(IBlockData data) { + return CraftLegacy.toLegacyData(data); +@@ -332,6 +338,13 @@ public final class CraftMagicNumbers implements UnsafeValues { + return clazz; + } + ++ // Paper start ++ @Override ++ public String getTimingsServerName() { ++ return com.destroystokyo.paper.PaperConfig.timingsServerName; ++ } ++ // Paper end ++ + /** + * This helper class represents the different NBT Tags. + *

    +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 44a7323ffbdf91f8e0672e0fadf0d3d26ed9a290..69c5d4e51ebf747d931fadc819973e36f001f5bc 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -29,7 +29,7 @@ import net.minecraft.world.entity.raid.EntityRaider; + import net.minecraft.world.level.World; + import net.minecraft.world.level.chunk.Chunk; + import net.minecraft.world.phys.AxisAlignedBB; +-import org.bukkit.craftbukkit.SpigotTimings; ++import co.aikar.timings.MinecraftTimings; + + public class ActivationRange + { +@@ -73,8 +73,8 @@ public class ActivationRange + /** + * These entities are excluded from Activation range checks. + * +- * @param entity +- * @param config ++ * @param entity Entity to initialize ++ * @param config Spigot config to determine ranges + * @return boolean If it should always tick. + */ + public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) +@@ -109,7 +109,7 @@ public class ActivationRange + */ + public static void activateEntities(World world) + { +- SpigotTimings.entityActivationCheckTimer.startTiming(); ++ MinecraftTimings.entityActivationCheckTimer.startTiming(); + final int miscActivationRange = world.spigotConfig.miscActivationRange; + final int raiderActivationRange = world.spigotConfig.raiderActivationRange; + final int animalActivationRange = world.spigotConfig.animalActivationRange; +@@ -146,7 +146,7 @@ public class ActivationRange + } + } + } +- SpigotTimings.entityActivationCheckTimer.stopTiming(); ++ MinecraftTimings.entityActivationCheckTimer.stopTiming(); + } + + /** +@@ -243,10 +243,8 @@ public class ActivationRange + */ + public static boolean checkIfActive(Entity entity) + { +- SpigotTimings.checkIfActiveTimer.startTiming(); + // Never safe to skip fireworks or entities not yet added to chunk + if ( !entity.inChunk || entity instanceof EntityFireworks ) { +- SpigotTimings.checkIfActiveTimer.stopTiming(); + return true; + } + +@@ -270,7 +268,6 @@ public class ActivationRange + { + isActive = false; + } +- SpigotTimings.checkIfActiveTimer.stopTiming(); + return isActive; + } + } diff --git a/patches/server-unmapped/0010-Adventure.patch b/patches/server-unmapped/0010-Adventure.patch new file mode 100644 index 0000000000..51208a5517 --- /dev/null +++ b/patches/server-unmapped/0010-Adventure.patch @@ -0,0 +1,3278 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Riley Park +Date: Fri, 29 Jan 2021 17:54:03 +0100 +Subject: [PATCH] Adventure + +Co-authored-by: zml +Co-authored-by: Jake Potrebic + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7..429b74474ced04d8dd8f038b8590b8dfe178bf4d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -217,4 +217,9 @@ public class PaperConfig { + " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + + " - Server Name: " + timingsServerName); + } ++ ++ public static boolean useDisplayNameInQuit = false; ++ private static void useDisplayNameInQuit() { ++ useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); ++ } + } +diff --git a/src/main/java/io/papermc/paper/adventure/AdventureComponent.java b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..89597b4a3064c3c6001c7e927a848ee73a1b1fd9 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java +@@ -0,0 +1,77 @@ ++package io.papermc.paper.adventure; ++ ++import com.google.gson.JsonElement; ++import com.google.gson.JsonSerializationContext; ++import com.google.gson.JsonSerializer; ++import java.lang.reflect.Type; ++import java.util.List; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.TextComponent; ++import net.minecraft.network.chat.ChatModifier; ++import net.minecraft.network.chat.IChatBaseComponent; ++import net.minecraft.network.chat.IChatMutableComponent; ++import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++ ++public final class AdventureComponent implements IChatBaseComponent { ++ final Component wrapped; ++ private @MonotonicNonNull IChatBaseComponent converted; ++ ++ public AdventureComponent(final Component wrapped) { ++ this.wrapped = wrapped; ++ } ++ ++ public IChatBaseComponent deepConverted() { ++ IChatBaseComponent converted = this.converted; ++ if (converted == null) { ++ converted = PaperAdventure.WRAPPER_AWARE_SERIALIZER.serialize(this.wrapped); ++ this.converted = converted; ++ } ++ return converted; ++ } ++ ++ public @Nullable IChatBaseComponent deepConvertedIfPresent() { ++ return this.converted; ++ } ++ ++ @Override ++ public ChatModifier getChatModifier() { ++ return this.deepConverted().getChatModifier(); ++ } ++ ++ @Override ++ public String getText() { ++ if (this.wrapped instanceof TextComponent) { ++ return ((TextComponent) this.wrapped).content(); ++ } else { ++ return this.deepConverted().getText(); ++ } ++ } ++ ++ @Override ++ public String getString() { ++ return PaperAdventure.PLAIN.serialize(this.wrapped); ++ } ++ ++ @Override ++ public List getSiblings() { ++ return this.deepConverted().getSiblings(); ++ } ++ ++ @Override ++ public IChatMutableComponent g() { ++ return this.deepConverted().g(); ++ } ++ ++ @Override ++ public IChatMutableComponent mutableCopy() { ++ return this.deepConverted().mutableCopy(); ++ } ++ ++ public static class Serializer implements JsonSerializer { ++ @Override ++ public JsonElement serialize(final AdventureComponent src, final Type type, final JsonSerializationContext context) { ++ return PaperAdventure.GSON.serializer().toJsonTree(src.wrapped, Component.class); ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..909968952a7ae2aa0196f12d1b3177cade380db2 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +@@ -0,0 +1,215 @@ ++package io.papermc.paper.adventure; ++ ++import io.papermc.paper.chat.ChatRenderer; ++import io.papermc.paper.event.player.AbstractChatEvent; ++import io.papermc.paper.event.player.AsyncChatEvent; ++import io.papermc.paper.event.player.ChatEvent; ++import java.util.Set; ++import java.util.concurrent.ExecutionException; ++import java.util.function.Consumer; ++import java.util.regex.Pattern; ++ ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.audience.MessageType; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.TextReplacementConfig; ++import net.kyori.adventure.text.event.ClickEvent; ++import net.minecraft.network.chat.IChatBaseComponent; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.LazyPlayerSet; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.AsyncPlayerChatEvent; ++import org.bukkit.event.player.PlayerChatEvent; ++ ++public final class ChatProcessor { ++ // <-- copied from adventure-text-serializer-legacy ++ private static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?"); ++ private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("^[a-z][a-z0-9+\\-.]*:"); ++ private static final TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder() ++ .match(DEFAULT_URL_PATTERN) ++ .replacement(url -> { ++ String clickUrl = url.content(); ++ if (!URL_SCHEME_PATTERN.matcher(clickUrl).find()) { ++ clickUrl = "http://" + clickUrl; ++ } ++ return url.clickEvent(ClickEvent.openUrl(clickUrl)); ++ }) ++ .build(); ++ // copied from adventure-text-serializer-legacy --> ++ final MinecraftServer server; ++ final EntityPlayer player; ++ final String message; ++ final boolean async; ++ final Component originalMessage; ++ ++ public ChatProcessor(final MinecraftServer server, final EntityPlayer player, final String message, final boolean async) { ++ this.server = server; ++ this.player = player; ++ this.message = message; ++ this.async = async; ++ this.originalMessage = Component.text(message); ++ } ++ ++ @SuppressWarnings({"CodeBlock2Expr", "deprecated"}) ++ public void process() { ++ this.processingLegacyFirst( ++ // continuing from AsyncPlayerChatEvent (without PlayerChatEvent) ++ event -> { ++ this.processModern( ++ legacyRenderer(event.getFormat()), ++ event.getRecipients(), ++ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), ++ event.isCancelled() ++ ); ++ }, ++ // continuing from AsyncPlayerChatEvent and PlayerChatEvent ++ event -> { ++ this.processModern( ++ legacyRenderer(event.getFormat()), ++ event.getRecipients(), ++ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), ++ event.isCancelled() ++ ); ++ }, ++ // no legacy events called, all nice and fresh! ++ () -> { ++ this.processModern( ++ ChatRenderer.defaultRenderer(), ++ new LazyPlayerSet(this.server), ++ Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG), ++ false ++ ); ++ } ++ ); ++ } ++ ++ @SuppressWarnings("deprecation") ++ private void processingLegacyFirst( ++ final Consumer continueAfterAsync, ++ final Consumer continueAfterAsyncAndSync, ++ final Runnable modernOnly ++ ) { ++ final boolean listenersOnAsyncEvent = anyListeners(AsyncPlayerChatEvent.getHandlerList()); ++ final boolean listenersOnSyncEvent = anyListeners(PlayerChatEvent.getHandlerList()); ++ if (listenersOnAsyncEvent || listenersOnSyncEvent) { ++ final CraftPlayer player = this.player.getBukkitEntity(); ++ final AsyncPlayerChatEvent ae = new AsyncPlayerChatEvent(this.async, player, this.message, new LazyPlayerSet(this.server)); ++ post(ae); ++ if (listenersOnSyncEvent) { ++ final PlayerChatEvent se = new PlayerChatEvent(player, ae.getMessage(), ae.getFormat(), ae.getRecipients()); ++ se.setCancelled(ae.isCancelled()); // propagate cancelled state ++ this.queueIfAsyncOrRunImmediately(new Waitable() { ++ @Override ++ protected Void evaluate() { ++ post(se); ++ return null; ++ } ++ }); ++ continueAfterAsyncAndSync.accept(se); ++ } else { ++ continueAfterAsync.accept(ae); ++ } ++ } else { ++ modernOnly.run(); ++ } ++ } ++ ++ private void processModern(final ChatRenderer renderer, final Set recipients, final Component message, final boolean cancelled) { ++ final AsyncChatEvent ae = this.createAsync(renderer, recipients, new LazyChatAudienceSet(), message); ++ ae.setCancelled(cancelled); // propagate cancelled state ++ post(ae); ++ final boolean listenersOnSyncEvent = anyListeners(ChatEvent.getHandlerList()); ++ if (listenersOnSyncEvent) { ++ this.continueWithSyncFromWhereAsyncLeftOff(ae); ++ } else { ++ this.complete(ae); ++ } ++ } ++ ++ private void continueWithSyncFromWhereAsyncLeftOff(final AsyncChatEvent ae) { ++ this.queueIfAsyncOrRunImmediately(new Waitable() { ++ @Override ++ protected Void evaluate() { ++ final ChatEvent se = ChatProcessor.this.createSync(ae.renderer(), ae.recipients(), ae.viewers(), ae.message()); ++ se.setCancelled(ae.isCancelled()); // propagate cancelled state ++ post(se); ++ ChatProcessor.this.complete(se); ++ return null; ++ } ++ }); ++ } ++ ++ private void complete(final AbstractChatEvent event) { ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ final CraftPlayer player = this.player.getBukkitEntity(); ++ final Component displayName = displayName(player); ++ final Component message = event.message(); ++ final ChatRenderer renderer = event.renderer(); ++ ++ final Set viewers = event.viewers(); ++ final Set recipients = event.recipients(); ++ if (viewers instanceof LazyChatAudienceSet && recipients instanceof LazyPlayerSet && ++ (!((LazyChatAudienceSet) viewers).isLazy() || ((LazyPlayerSet) recipients).isLazy())) { ++ for (final Audience viewer : viewers) { ++ viewer.sendMessage(player, renderer.render(player, displayName, message, viewer), MessageType.CHAT); ++ } ++ } else { ++ this.server.console.sendMessage(player, renderer.render(player, displayName, message, this.server.console), MessageType.CHAT); ++ for (final Player recipient : recipients) { ++ recipient.sendMessage(player, renderer.render(player, displayName, message, recipient), MessageType.CHAT); ++ } ++ } ++ } ++ ++ private AsyncChatEvent createAsync(final ChatRenderer renderer, final Set recipients, final Set viewers, final Component message) { ++ return new AsyncChatEvent(this.async, this.player.getBukkitEntity(), recipients, viewers, renderer, message, this.originalMessage); ++ } ++ ++ private ChatEvent createSync(final ChatRenderer renderer, final Set recipients, final Set viewers, final Component message) { ++ return new ChatEvent(this.player.getBukkitEntity(), recipients, viewers, renderer, message, this.originalMessage); ++ } ++ ++ private static String legacyDisplayName(final CraftPlayer player) { ++ return player.getDisplayName(); ++ } ++ ++ private static Component displayName(final CraftPlayer player) { ++ return player.displayName(); ++ } ++ ++ private static ChatRenderer legacyRenderer(final String format) { ++ return (player, displayName, message, recipient) -> PaperAdventure.LEGACY_SECTION_UXRC.deserialize(String.format(format, legacyDisplayName((CraftPlayer) player), PaperAdventure.LEGACY_SECTION_UXRC.serialize(message))).replaceText(URL_REPLACEMENT_CONFIG); ++ } ++ ++ private void queueIfAsyncOrRunImmediately(final Waitable waitable) { ++ if (this.async) { ++ this.server.processQueue.add(waitable); ++ } else { ++ waitable.run(); ++ } ++ try { ++ waitable.get(); ++ } catch (final InterruptedException e) { ++ Thread.currentThread().interrupt(); // tag, you're it ++ } catch (final ExecutionException e) { ++ throw new RuntimeException("Exception processing chat", e.getCause()); ++ } ++ } ++ ++ private static void post(final Event event) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ ++ private static boolean anyListeners(final HandlerList handlers) { ++ return handlers.getRegisteredListeners().length > 0; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/DisplayNames.java b/src/main/java/io/papermc/paper/adventure/DisplayNames.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b1d9d6276eb577ed3c66df1f89b3266d2c48eaf2 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/DisplayNames.java +@@ -0,0 +1,22 @@ ++package io.papermc.paper.adventure; ++ ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.ChatColor; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++ ++public final class DisplayNames { ++ private DisplayNames() { ++ } ++ ++ public static String getLegacy(final CraftPlayer player) { ++ return getLegacy(player.getHandle()); ++ } ++ ++ public static String getLegacy(final EntityPlayer player) { ++ final String legacy = player.displayName; ++ if (legacy != null) { ++ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName) + ChatColor.getLastColors(player.displayName); ++ } ++ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..10f08e2b73610ab06928d1f63348920fef8e91fa +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java +@@ -0,0 +1,21 @@ ++package io.papermc.paper.adventure; ++ ++import net.kyori.adventure.audience.Audience; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.util.LazyHashSet; ++import org.bukkit.craftbukkit.util.LazyPlayerSet; ++import org.bukkit.entity.Player; ++ ++import java.util.HashSet; ++import java.util.Set; ++ ++final class LazyChatAudienceSet extends LazyHashSet { ++ @Override ++ protected Set makeReference() { ++ final Set playerSet = LazyPlayerSet.makePlayerSet(MinecraftServer.getServer()); ++ final HashSet audiences = new HashSet<>(playerSet); ++ audiences.add(Bukkit.getConsoleSender()); ++ return audiences; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..caa9708f321f04cd02534161231c05999bda4acd +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java +@@ -0,0 +1,88 @@ ++package io.papermc.paper.adventure; ++ ++import com.mojang.brigadier.exceptions.CommandSyntaxException; ++import java.io.IOException; ++import java.util.UUID; ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.nbt.api.BinaryTagHolder; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.event.HoverEvent; ++import net.kyori.adventure.text.serializer.gson.LegacyHoverEventSerializer; ++import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; ++import net.kyori.adventure.util.Codec; ++import net.minecraft.nbt.MojangsonParser; ++import net.minecraft.nbt.NBTBase; ++import net.minecraft.nbt.NBTTagCompound; ++ ++final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer { ++ public static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer(); ++ private static final Codec SNBT_CODEC = Codec.of(MojangsonParser::parse, NBTBase::toString); ++ ++ static final String ITEM_TYPE = "id"; ++ static final String ITEM_COUNT = "Count"; ++ static final String ITEM_TAG = "tag"; ++ ++ static final String ENTITY_NAME = "name"; ++ static final String ENTITY_TYPE = "type"; ++ static final String ENTITY_ID = "id"; ++ ++ NBTLegacyHoverEventSerializer() { ++ } ++ ++ @Override ++ public HoverEvent.ShowItem deserializeShowItem(final Component input) throws IOException { ++ final String raw = PlainComponentSerializer.plain().serialize(input); ++ try { ++ final NBTTagCompound contents = SNBT_CODEC.decode(raw); ++ final NBTTagCompound tag = contents.getCompound(ITEM_TAG); ++ return HoverEvent.ShowItem.of( ++ Key.key(contents.getString(ITEM_TYPE)), ++ contents.hasKey(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1, ++ tag.isEmpty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC) ++ ); ++ } catch (final CommandSyntaxException ex) { ++ throw new IOException(ex); ++ } ++ } ++ ++ @Override ++ public HoverEvent.ShowEntity deserializeShowEntity(final Component input, final Codec.Decoder componentCodec) throws IOException { ++ final String raw = PlainComponentSerializer.plain().serialize(input); ++ try { ++ final NBTTagCompound contents = SNBT_CODEC.decode(raw); ++ return HoverEvent.ShowEntity.of( ++ Key.key(contents.getString(ENTITY_TYPE)), ++ UUID.fromString(contents.getString(ENTITY_ID)), ++ componentCodec.decode(contents.getString(ENTITY_NAME)) ++ ); ++ } catch (final CommandSyntaxException ex) { ++ throw new IOException(ex); ++ } ++ } ++ ++ @Override ++ public Component serializeShowItem(final HoverEvent.ShowItem input) throws IOException { ++ final NBTTagCompound tag = new NBTTagCompound(); ++ tag.setString(ITEM_TYPE, input.item().asString()); ++ tag.setByte(ITEM_COUNT, (byte) input.count()); ++ if (input.nbt() != null) { ++ try { ++ tag.set(ITEM_TAG, input.nbt().get(SNBT_CODEC)); ++ } catch (final CommandSyntaxException ex) { ++ throw new IOException(ex); ++ } ++ } ++ return Component.text(SNBT_CODEC.encode(tag)); ++ } ++ ++ @Override ++ public Component serializeShowEntity(final HoverEvent.ShowEntity input, final Codec.Encoder componentCodec) throws IOException { ++ final NBTTagCompound tag = new NBTTagCompound(); ++ tag.setString(ENTITY_ID, input.id().toString()); ++ tag.setString(ENTITY_TYPE, input.type().asString()); ++ if (input.name() != null) { ++ tag.setString(ENTITY_NAME, componentCodec.encode(input.name())); ++ } ++ return Component.text(SNBT_CODEC.encode(tag)); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7b14b3c2486f03778d4673cf9684aa576dc2724a +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java +@@ -0,0 +1,344 @@ ++package io.papermc.paper.adventure; ++ ++import com.mojang.brigadier.exceptions.CommandSyntaxException; ++import io.netty.util.AttributeKey; ++import java.io.IOException; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Locale; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++import net.kyori.adventure.bossbar.BossBar; ++import net.kyori.adventure.inventory.Book; ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.nbt.api.BinaryTagHolder; ++import net.kyori.adventure.sound.Sound; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.TranslatableComponent; ++import net.kyori.adventure.text.flattener.ComponentFlattener; ++import net.kyori.adventure.text.format.TextColor; ++import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; ++import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; ++import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; ++import net.kyori.adventure.translation.GlobalTranslator; ++import net.kyori.adventure.util.Codec; ++import net.minecraft.EnumChatFormat; ++import net.minecraft.locale.LocaleLanguage; ++import net.minecraft.nbt.MojangsonParser; ++import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.nbt.NBTTagList; ++import net.minecraft.nbt.NBTTagString; ++import net.minecraft.network.chat.IChatBaseComponent; ++import net.minecraft.resources.MinecraftKey; ++import net.minecraft.sounds.SoundCategory; ++import net.minecraft.world.BossBattle; ++import net.minecraft.world.item.ItemStack; ++import org.bukkit.ChatColor; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++ ++public final class PaperAdventure { ++ public static final AttributeKey LOCALE_ATTRIBUTE = AttributeKey.valueOf("adventure:locale"); ++ private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s"); ++ public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder() ++ .complexMapper(TranslatableComponent.class, (translatable, consumer) -> { ++ final @NonNull String translated = LocaleLanguage.a().a(translatable.key()); ++ ++ final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated); ++ final List args = translatable.args(); ++ int argPosition = 0; ++ int lastIdx = 0; ++ while (matcher.find()) { ++ // append prior ++ if (lastIdx < matcher.start()) { ++ consumer.accept(Component.text(translated.substring(lastIdx, matcher.start()))); ++ } ++ lastIdx = matcher.end(); ++ ++ final @Nullable String argIdx = matcher.group(1); ++ // calculate argument position ++ if (argIdx != null) { ++ try { ++ final int idx = Integer.parseInt(argIdx) - 1; ++ if (idx < args.size()) { ++ consumer.accept(args.get(idx)); ++ } ++ } catch (final NumberFormatException ex) { ++ // ignore, drop the format placeholder ++ } ++ } else { ++ final int idx = argPosition++; ++ if (idx < args.size()) { ++ consumer.accept(args.get(idx)); ++ } ++ } ++ } ++ ++ // append tail ++ if (lastIdx < translated.length()) { ++ consumer.accept(Component.text(translated.substring(lastIdx))); ++ } ++ }) ++ .build(); ++ public static final LegacyComponentSerializer LEGACY_SECTION_UXRC = LegacyComponentSerializer.builder().flattener(FLATTENER).hexColors().useUnusualXRepeatedCharacterHexFormat().build(); ++ public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build(); ++ public static final GsonComponentSerializer GSON = GsonComponentSerializer.builder() ++ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) ++ .build(); ++ public static final GsonComponentSerializer COLOR_DOWNSAMPLING_GSON = GsonComponentSerializer.builder() ++ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) ++ .downsampleColors() ++ .build(); ++ private static final Codec NBT_CODEC = new Codec() { ++ @Override ++ public @NonNull NBTTagCompound decode(final @NonNull String encoded) throws IOException { ++ try { ++ return MojangsonParser.parse(encoded); ++ } catch (final CommandSyntaxException e) { ++ throw new IOException(e); ++ } ++ } ++ ++ @Override ++ public @NonNull String encode(final @NonNull NBTTagCompound decoded) { ++ return decoded.toString(); ++ } ++ }; ++ static final WrapperAwareSerializer WRAPPER_AWARE_SERIALIZER = new WrapperAwareSerializer(); ++ ++ private PaperAdventure() { ++ } ++ ++ // Key ++ ++ public static MinecraftKey asVanilla(final Key key) { ++ return new MinecraftKey(key.namespace(), key.value()); ++ } ++ ++ public static MinecraftKey asVanillaNullable(final Key key) { ++ if (key == null) { ++ return null; ++ } ++ return new MinecraftKey(key.namespace(), key.value()); ++ } ++ ++ // Component ++ ++ public static Component asAdventure(final IChatBaseComponent component) { ++ return component == null ? Component.empty() : GSON.serializer().fromJson(IChatBaseComponent.ChatSerializer.toJsonTree(component), Component.class); ++ } ++ ++ public static ArrayList asAdventure(final List vanillas) { ++ final ArrayList adventures = new ArrayList<>(vanillas.size()); ++ for (final IChatBaseComponent vanilla : vanillas) { ++ adventures.add(asAdventure(vanilla)); ++ } ++ return adventures; ++ } ++ ++ public static ArrayList asAdventureFromJson(final List jsonStrings) { ++ final ArrayList adventures = new ArrayList<>(jsonStrings.size()); ++ for (final String json : jsonStrings) { ++ adventures.add(GsonComponentSerializer.gson().deserialize(json)); ++ } ++ return adventures; ++ } ++ ++ public static List asJson(final List adventures) { ++ final List jsons = new ArrayList<>(adventures.size()); ++ for (final Component component : adventures) { ++ jsons.add(GsonComponentSerializer.gson().serialize(component)); ++ } ++ return jsons; ++ } ++ ++ public static IChatBaseComponent asVanilla(final Component component) { ++ if (true) return new AdventureComponent(component); ++ return IChatBaseComponent.ChatSerializer.fromJsonTree(GSON.serializer().toJsonTree(component)); ++ } ++ ++ public static List asVanilla(final List adventures) { ++ final List vanillas = new ArrayList<>(adventures.size()); ++ for (final Component adventure : adventures) { ++ vanillas.add(asVanilla(adventure)); ++ } ++ return vanillas; ++ } ++ ++ public static String asJsonString(final Component component, final Locale locale) { ++ return GSON.serialize( ++ GlobalTranslator.render( ++ component, ++ // play it safe ++ locale != null ++ ? locale ++ : Locale.US ++ ) ++ ); ++ } ++ ++ public static String asJsonString(final IChatBaseComponent component, final Locale locale) { ++ if (component instanceof AdventureComponent) { ++ return asJsonString(((AdventureComponent) component).wrapped, locale); ++ } ++ return IChatBaseComponent.ChatSerializer.componentToJson(component); ++ } ++ ++ // thank you for being worse than wet socks, Bukkit ++ public static String superHackyLegacyRepresentationOfComponent(final Component component, final String string) { ++ return LEGACY_SECTION_UXRC.serialize(component) + ChatColor.getLastColors(string); ++ } ++ ++ // BossBar ++ ++ public static BossBattle.BarColor asVanilla(final BossBar.Color color) { ++ if (color == BossBar.Color.PINK) { ++ return BossBattle.BarColor.PINK; ++ } else if (color == BossBar.Color.BLUE) { ++ return BossBattle.BarColor.BLUE; ++ } else if (color == BossBar.Color.RED) { ++ return BossBattle.BarColor.RED; ++ } else if (color == BossBar.Color.GREEN) { ++ return BossBattle.BarColor.GREEN; ++ } else if (color == BossBar.Color.YELLOW) { ++ return BossBattle.BarColor.YELLOW; ++ } else if (color == BossBar.Color.PURPLE) { ++ return BossBattle.BarColor.PURPLE; ++ } else if (color == BossBar.Color.WHITE) { ++ return BossBattle.BarColor.WHITE; ++ } ++ throw new IllegalArgumentException(color.name()); ++ } ++ ++ public static BossBar.Color asAdventure(final BossBattle.BarColor color) { ++ if(color == BossBattle.BarColor.PINK) { ++ return BossBar.Color.PINK; ++ } else if(color == BossBattle.BarColor.BLUE) { ++ return BossBar.Color.BLUE; ++ } else if(color == BossBattle.BarColor.RED) { ++ return BossBar.Color.RED; ++ } else if(color == BossBattle.BarColor.GREEN) { ++ return BossBar.Color.GREEN; ++ } else if(color == BossBattle.BarColor.YELLOW) { ++ return BossBar.Color.YELLOW; ++ } else if(color == BossBattle.BarColor.PURPLE) { ++ return BossBar.Color.PURPLE; ++ } else if(color == BossBattle.BarColor.WHITE) { ++ return BossBar.Color.WHITE; ++ } ++ throw new IllegalArgumentException(color.name()); ++ } ++ ++ public static BossBattle.BarStyle asVanilla(final BossBar.Overlay overlay) { ++ if (overlay == BossBar.Overlay.PROGRESS) { ++ return BossBattle.BarStyle.PROGRESS; ++ } else if (overlay == BossBar.Overlay.NOTCHED_6) { ++ return BossBattle.BarStyle.NOTCHED_6; ++ } else if (overlay == BossBar.Overlay.NOTCHED_10) { ++ return BossBattle.BarStyle.NOTCHED_10; ++ } else if (overlay == BossBar.Overlay.NOTCHED_12) { ++ return BossBattle.BarStyle.NOTCHED_12; ++ } else if (overlay == BossBar.Overlay.NOTCHED_20) { ++ return BossBattle.BarStyle.NOTCHED_20; ++ } ++ throw new IllegalArgumentException(overlay.name()); ++ } ++ ++ public static BossBar.Overlay asAdventure(final BossBattle.BarStyle overlay) { ++ if (overlay == BossBattle.BarStyle.PROGRESS) { ++ return BossBar.Overlay.PROGRESS; ++ } else if (overlay == BossBattle.BarStyle.NOTCHED_6) { ++ return BossBar.Overlay.NOTCHED_6; ++ } else if (overlay == BossBattle.BarStyle.NOTCHED_10) { ++ return BossBar.Overlay.NOTCHED_10; ++ } else if (overlay == BossBattle.BarStyle.NOTCHED_12) { ++ return BossBar.Overlay.NOTCHED_12; ++ } else if (overlay == BossBattle.BarStyle.NOTCHED_20) { ++ return BossBar.Overlay.NOTCHED_20; ++ } ++ throw new IllegalArgumentException(overlay.name()); ++ } ++ ++ public static void setFlag(final BossBar bar, final BossBar.Flag flag, final boolean value) { ++ if (value) { ++ bar.addFlag(flag); ++ } else { ++ bar.removeFlag(flag); ++ } ++ } ++ ++ // Book ++ ++ public static ItemStack asItemStack(final Book book, final Locale locale) { ++ final ItemStack item = new ItemStack(net.minecraft.world.item.Items.WRITTEN_BOOK, 1); ++ final NBTTagCompound tag = item.getOrCreateTag(); ++ tag.setString("title", asJsonString(book.title(), locale)); ++ tag.setString("author", asJsonString(book.author(), locale)); ++ final NBTTagList pages = new NBTTagList(); ++ for (final Component page : book.pages()) { ++ pages.add(NBTTagString.create(asJsonString(page, locale))); ++ } ++ tag.set("pages", pages); ++ return item; ++ } ++ ++ // Sounds ++ ++ public static SoundCategory asVanilla(final Sound.Source source) { ++ if (source == Sound.Source.MASTER) { ++ return SoundCategory.MASTER; ++ } else if (source == Sound.Source.MUSIC) { ++ return SoundCategory.MUSIC; ++ } else if (source == Sound.Source.RECORD) { ++ return SoundCategory.RECORDS; ++ } else if (source == Sound.Source.WEATHER) { ++ return SoundCategory.WEATHER; ++ } else if (source == Sound.Source.BLOCK) { ++ return SoundCategory.BLOCKS; ++ } else if (source == Sound.Source.HOSTILE) { ++ return SoundCategory.HOSTILE; ++ } else if (source == Sound.Source.NEUTRAL) { ++ return SoundCategory.NEUTRAL; ++ } else if (source == Sound.Source.PLAYER) { ++ return SoundCategory.PLAYERS; ++ } else if (source == Sound.Source.AMBIENT) { ++ return SoundCategory.AMBIENT; ++ } else if (source == Sound.Source.VOICE) { ++ return SoundCategory.VOICE; ++ } ++ throw new IllegalArgumentException(source.name()); ++ } ++ ++ public static @Nullable SoundCategory asVanillaNullable(final Sound.@Nullable Source source) { ++ if (source == null) { ++ return null; ++ } ++ return asVanilla(source); ++ } ++ ++ // NBT ++ ++ public static @Nullable BinaryTagHolder asBinaryTagHolder(final @Nullable NBTTagCompound tag) { ++ if (tag == null) { ++ return null; ++ } ++ try { ++ return BinaryTagHolder.encode(tag, NBT_CODEC); ++ } catch (final IOException e) { ++ return null; ++ } ++ } ++ ++ // Colors ++ ++ public static @NonNull TextColor asAdventure(EnumChatFormat minecraftColor) { ++ if (minecraftColor.e() == null) { ++ throw new IllegalArgumentException("Not a valid color"); ++ } ++ return TextColor.color(minecraftColor.e()); ++ } ++ ++ public static @Nullable EnumChatFormat asVanilla(TextColor color) { ++ return EnumChatFormat.getByHexValue(color.value()); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3a4158781e464d9a860bab72ed719a41929c8add +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java +@@ -0,0 +1,41 @@ ++package io.papermc.paper.adventure; ++ ++import java.util.Set; ++import java.util.function.Consumer; ++import net.kyori.adventure.bossbar.BossBar; ++import net.kyori.adventure.text.Component; ++import net.minecraft.network.protocol.game.PacketPlayOutBoss; ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++public final class VanillaBossBarListener implements BossBar.Listener { ++ private final Consumer action; ++ ++ public VanillaBossBarListener(final Consumer action) { ++ this.action = action; ++ } ++ ++ @Override ++ public void bossBarNameChanged(final @NonNull BossBar bar, final @NonNull Component oldName, final @NonNull Component newName) { ++ this.action.accept(PacketPlayOutBoss.Action.UPDATE_NAME); ++ } ++ ++ @Override ++ public void bossBarProgressChanged(final @NonNull BossBar bar, final float oldProgress, final float newProgress) { ++ this.action.accept(PacketPlayOutBoss.Action.UPDATE_PCT); ++ } ++ ++ @Override ++ public void bossBarColorChanged(final @NonNull BossBar bar, final BossBar.@NonNull Color oldColor, final BossBar.@NonNull Color newColor) { ++ this.action.accept(PacketPlayOutBoss.Action.UPDATE_STYLE); ++ } ++ ++ @Override ++ public void bossBarOverlayChanged(final @NonNull BossBar bar, final BossBar.@NonNull Overlay oldOverlay, final BossBar.@NonNull Overlay newOverlay) { ++ this.action.accept(PacketPlayOutBoss.Action.UPDATE_STYLE); ++ } ++ ++ @Override ++ public void bossBarFlagsChanged(final @NonNull BossBar bar, final @NonNull Set flagsAdded, final @NonNull Set flagsRemoved) { ++ this.action.accept(PacketPlayOutBoss.Action.UPDATE_PROPERTIES); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..625b57a4274d6348a85897b92ff07fee7ae3a7ab +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java +@@ -0,0 +1,20 @@ ++package io.papermc.paper.adventure; ++ ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.serializer.ComponentSerializer; ++import net.minecraft.network.chat.IChatBaseComponent; ++ ++final class WrapperAwareSerializer implements ComponentSerializer { ++ @Override ++ public Component deserialize(final IChatBaseComponent input) { ++ if (input instanceof AdventureComponent) { ++ return ((AdventureComponent) input).wrapped; ++ } ++ return PaperAdventure.GSON.serializer().fromJson(IChatBaseComponent.ChatSerializer.toJsonTree(input), Component.class); ++ } ++ ++ @Override ++ public IChatBaseComponent serialize(final Component component) { ++ return IChatBaseComponent.ChatSerializer.fromJsonTree(PaperAdventure.GSON.serializer().toJsonTree(component)); ++ } ++} +diff --git a/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b3e26b9ecca7055760d05975d36c9ae74e0d7d4b +--- /dev/null ++++ b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java +@@ -0,0 +1,36 @@ ++package net.kyori.adventure.bossbar; ++ ++import io.papermc.paper.adventure.PaperAdventure; ++import io.papermc.paper.adventure.VanillaBossBarListener; ++import net.minecraft.server.level.BossBattleServer; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++ ++public abstract class HackyBossBarPlatformBridge { ++ public BossBattleServer vanilla$bar; ++ private VanillaBossBarListener vanilla$listener; ++ ++ public final void paper$playerShow(final CraftPlayer player) { ++ if (this.vanilla$bar == null) { ++ final BossBar $this = (BossBar) this; ++ this.vanilla$bar = new BossBattleServer( ++ PaperAdventure.asVanilla($this.name()), ++ PaperAdventure.asVanilla($this.color()), ++ PaperAdventure.asVanilla($this.overlay()) ++ ); ++ this.vanilla$bar.adventure = $this; ++ this.vanilla$listener = new VanillaBossBarListener(this.vanilla$bar::sendUpdate); ++ $this.addListener(this.vanilla$listener); ++ } ++ this.vanilla$bar.addPlayer(player.getHandle()); ++ } ++ ++ public final void paper$playerHide(final CraftPlayer player) { ++ if (this.vanilla$bar != null) { ++ this.vanilla$bar.removePlayer(player.getHandle()); ++ if (this.vanilla$bar.getPlayers().isEmpty()) { ++ ((BossBar) this).removeListener(this.vanilla$listener); ++ this.vanilla$bar = null; ++ } ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/EnumChatFormat.java b/src/main/java/net/minecraft/EnumChatFormat.java +index 75e38f05c10713f773a8763100dfc0777521dba6..cd93f99e939438c572a4258d299a6038ebfc60a8 100644 +--- a/src/main/java/net/minecraft/EnumChatFormat.java ++++ b/src/main/java/net/minecraft/EnumChatFormat.java +@@ -61,6 +61,7 @@ public enum EnumChatFormat { + return !this.A && this != EnumChatFormat.RESET; + } + ++ @Nullable public Integer getHexValue() { return this.e(); } // Paper - OBFHELPER + @Nullable + public Integer e() { + return this.D; +@@ -84,6 +85,18 @@ public enum EnumChatFormat { + return s == null ? null : (EnumChatFormat) EnumChatFormat.w.get(c(s)); + } + ++ // Paper start ++ @Nullable public static EnumChatFormat getByHexValue(int i) { ++ for (EnumChatFormat value : values()) { ++ if (value.getHexValue() != null && value.getHexValue() == i) { ++ return value; ++ } ++ } ++ ++ return null; ++ } ++ // Paper end ++ + @Nullable + public static EnumChatFormat a(int i) { + if (i < 0) { +diff --git a/src/main/java/net/minecraft/nbt/NBTTagString.java b/src/main/java/net/minecraft/nbt/NBTTagString.java +index e26ef49d9dde8ed0fb4267b48cb597563967f313..0e41fdb6ba711fbd2240d62e2030b3a12e14c8d6 100644 +--- a/src/main/java/net/minecraft/nbt/NBTTagString.java ++++ b/src/main/java/net/minecraft/nbt/NBTTagString.java +@@ -43,6 +43,7 @@ public class NBTTagString implements NBTBase { + this.data = s; + } + ++ public static NBTTagString create(final String value) { return a(value); } // Paper - OBFHELPER + public static NBTTagString a(String s) { + return s.isEmpty() ? NBTTagString.b : new NBTTagString(s); + } +diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java +index 5413bf93f7f0f4491fca1f07c47a925fdace7751..5f1c5dd7902f6cff5acae05e8c6bf58a1ba5bdf1 100644 +--- a/src/main/java/net/minecraft/network/PacketDataSerializer.java ++++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java +@@ -10,6 +10,7 @@ import io.netty.buffer.ByteBufOutputStream; + import io.netty.handler.codec.DecoderException; + import io.netty.handler.codec.EncoderException; + import io.netty.util.ByteProcessor; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.io.DataInput; + import java.io.DataOutput; + import java.io.IOException; +@@ -44,6 +45,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit + public class PacketDataSerializer extends ByteBuf { + + private final ByteBuf a; ++ public java.util.Locale adventure$locale; // Paper + + public PacketDataSerializer(ByteBuf bytebuf) { + this.a = bytebuf; +@@ -165,8 +167,15 @@ public class PacketDataSerializer extends ByteBuf { + return IChatBaseComponent.ChatSerializer.a(this.e(262144)); + } + ++ // Paper start ++ public PacketDataSerializer writeComponent(final net.kyori.adventure.text.Component component) { ++ return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); ++ } ++ // Paper end ++ + public PacketDataSerializer a(IChatBaseComponent ichatbasecomponent) { +- return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); ++ //return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); // Paper - comment ++ return this.writeUtf(PaperAdventure.asJsonString(ichatbasecomponent, this.adventure$locale), 262144); // Paper + } + + public > T a(Class oclass) { +@@ -349,6 +358,7 @@ public class PacketDataSerializer extends ByteBuf { + return this.a(s, 32767); + } + ++ public PacketDataSerializer writeUtf(final String string, final int maxLength) { return this.a(string, maxLength); } // Paper - OBFHELPER + public PacketDataSerializer a(String s, int i) { + byte[] abyte = s.getBytes(StandardCharsets.UTF_8); + +diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java +index dc8cc8d6c00176c8562086282f726dc1b24b2c65..2f6da89d6b25ba5144ec15b1bf0e8ed13278e85e 100644 +--- a/src/main/java/net/minecraft/network/PacketEncoder.java ++++ b/src/main/java/net/minecraft/network/PacketEncoder.java +@@ -3,6 +3,7 @@ package net.minecraft.network; + import io.netty.buffer.ByteBuf; + import io.netty.channel.ChannelHandlerContext; + import io.netty.handler.codec.MessageToByteEncoder; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.io.IOException; + import net.minecraft.network.protocol.EnumProtocolDirection; + import net.minecraft.network.protocol.Packet; +@@ -37,6 +38,7 @@ public class PacketEncoder extends MessageToByteEncoder> { + throw new IOException("Can't serialize unregistered packet"); + } else { + PacketDataSerializer packetdataserializer = new PacketDataSerializer(bytebuf); ++ packetdataserializer.adventure$locale = channelhandlercontext.channel().attr(PaperAdventure.LOCALE_ATTRIBUTE).get(); // Paper + + packetdataserializer.d(integer); + +diff --git a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java +index 85140d961722e86abfe7006a0ad752751e73c721..e96fa348a37a39c381b6659f612232933686c2a7 100644 +--- a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java ++++ b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java +@@ -1,5 +1,6 @@ + package net.minecraft.network.chat; + ++import io.papermc.paper.adventure.AdventureComponent; // Paper + import com.google.gson.Gson; + import com.google.gson.GsonBuilder; + import com.google.gson.JsonArray; +@@ -111,6 +112,7 @@ public interface IChatBaseComponent extends Message, IChatFormatted, Iterable { + + private IChatBaseComponent a; ++ public net.kyori.adventure.text.Component adventure$message; // Paper + public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot + private ChatMessageType b; + private UUID c; +@@ -32,6 +33,11 @@ public class PacketPlayOutChat implements Packet { + + @Override + public void b(PacketDataSerializer packetdataserializer) throws IOException { ++ // Paper start ++ if (this.adventure$message != null) { ++ packetdataserializer.writeComponent(this.adventure$message); ++ } else ++ // Paper end + // Spigot start + if (components != null) { + packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java +index 0268b8e6595ee919bcd55a74ba872a2b7d2a17d8..4ff73a4fc5e8a8739e57d2bac65076812cbe5132 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java +@@ -9,6 +9,10 @@ public class PacketPlayOutPlayerListHeaderFooter implements Packet 0 && flag) { // TODO: allow plugins to override? +- IChatBaseComponent ichatbasecomponent; +- if (deathMessage.equals(deathmessage)) { +- ichatbasecomponent = this.getCombatTracker().getDeathMessage(); +- } else { +- ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage); +- } ++ if (deathMessage != null && deathMessage != net.kyori.adventure.text.Component.empty() && flag) { // Paper - Adventure // TODO: allow plugins to override? ++ IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(deathMessage); // Paper - Adventure + + this.playerConnection.a((Packet) (new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, ichatbasecomponent)), (future) -> { + if (!future.isSuccess()) { +@@ -1669,6 +1666,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.a(ichatbasecomponent, ChatMessageType.SYSTEM, uuid); + } + ++ public void sendMessage(final IChatBaseComponent message, final ChatMessageType type, final UUID sender) { this.a(message, type, sender); } // Paper - OBFHELPER + public void a(IChatBaseComponent ichatbasecomponent, ChatMessageType chatmessagetype, UUID uuid) { + this.playerConnection.a((Packet) (new PacketPlayOutChat(ichatbasecomponent, chatmessagetype, uuid)), (future) -> { + if (!future.isSuccess() && (chatmessagetype == ChatMessageType.GAME_INFO || chatmessagetype == ChatMessageType.SYSTEM)) { +@@ -1691,6 +1689,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + + public String locale = "en_us"; // CraftBukkit - add, lowercase ++ public java.util.Locale adventure$locale = java.util.Locale.US; // Paper + public void a(PacketPlayInSettings packetplayinsettings) { + // CraftBukkit start + if (getMainHand() != packetplayinsettings.getMainHand()) { +@@ -1702,6 +1701,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.server.server.getPluginManager().callEvent(event); + } + this.locale = packetplayinsettings.locale; ++ // Paper start ++ this.adventure$locale = net.kyori.adventure.translation.Translator.parseLocale(this.locale); ++ this.playerConnection.networkManager.channel.attr(PaperAdventure.LOCALE_ATTRIBUTE).set(this.adventure$locale); ++ // Paper end + this.clientViewDistance = packetplayinsettings.viewDistance; + // CraftBukkit end + this.bY = packetplayinsettings.d(); +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index 16275208954bfc008115aa169c5bfc149f6a4eeb..49a0aefc7f9544b36175fdf3161b255e878952a6 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -37,6 +37,7 @@ import org.apache.logging.log4j.Logger; + + // CraftBukkit start + import net.minecraft.network.chat.ChatComponentText; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import org.bukkit.craftbukkit.util.Waitable; + import org.bukkit.event.player.AsyncPlayerPreLoginEvent; + import org.bukkit.event.player.PlayerPreLoginEvent; +@@ -301,7 +302,7 @@ public class LoginListener implements PacketLoginInListener { + if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { + final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); + if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { +- event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); ++ event.disallow(asyncEvent.getResult(), asyncEvent.kickMessage()); // Paper - Adventure + } + Waitable waitable = new Waitable() { + @Override +@@ -312,12 +313,12 @@ public class LoginListener implements PacketLoginInListener { + + LoginListener.this.server.processQueue.add(waitable); + if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { +- disconnect(event.getKickMessage()); ++ disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure + return; + } + } else { + if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { +- disconnect(asyncEvent.getKickMessage()); ++ disconnect(PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure + return; + } + } +diff --git a/src/main/java/net/minecraft/server/network/PacketStatusListener.java b/src/main/java/net/minecraft/server/network/PacketStatusListener.java +index 2a96564c1656d42a74c331a6178e511cd5347a66..d219eda271a71f786808a6958b829fca40a1aaba 100644 +--- a/src/main/java/net/minecraft/server/network/PacketStatusListener.java ++++ b/src/main/java/net/minecraft/server/network/PacketStatusListener.java +@@ -56,7 +56,7 @@ public class PacketStatusListener implements PacketStatusInListener { + CraftIconCache icon = minecraftServer.server.getServerIcon(); + + ServerListPingEvent() { +- super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.getMotd(), minecraftServer.getPlayerList().getMaxPlayers()); ++ super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.server.motd(), minecraftServer.getPlayerList().getMaxPlayers()); // Paper - Adventure + } + + @Override +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 536a351e1879fcb8066546d1179ad1af034b95da..5db09e60c2ac1f4cb0da3190e57896ccae7c58a3 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -159,6 +159,8 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + // CraftBukkit start ++import io.papermc.paper.adventure.ChatProcessor; // Paper ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.util.concurrent.ExecutionException; + import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + import net.minecraft.network.protocol.game.PacketPlayOutAttachEntity; +@@ -390,21 +392,24 @@ public class PlayerConnection implements PacketListenerPlayIn { + return this.minecraftServer.a(this.player.getProfile()); + } + +- // CraftBukkit start +- @Deprecated +- public void disconnect(IChatBaseComponent ichatbasecomponent) { +- disconnect(CraftChatMessage.fromComponent(ichatbasecomponent)); ++ public void disconnect(String s) { ++ // Paper start ++ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); + } +- // CraftBukkit end + +- public void disconnect(String s) { ++ public void disconnect(final IChatBaseComponent reason) { ++ this.disconnect(PaperAdventure.asAdventure(reason)); ++ } ++ ++ public void disconnect(net.kyori.adventure.text.Component reason) { ++ // Paper end + // CraftBukkit start - fire PlayerKickEvent + if (this.processedDisconnect) { + return; + } +- String leaveMessage = EnumChatFormat.YELLOW + this.player.getName() + " left the game."; ++ net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure + +- PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), s, leaveMessage); ++ PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure + + if (this.server.getServer().isRunning()) { + this.server.getPluginManager().callEvent(event); +@@ -415,8 +420,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + return; + } + // Send the possibly modified leave message +- s = event.getReason(); +- final IChatBaseComponent ichatbasecomponent = CraftChatMessage.fromString(s, true)[0]; ++ final IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure + // CraftBukkit end + + this.networkManager.sendPacket(new PacketPlayOutKickDisconnect(ichatbasecomponent), (future) -> { +@@ -1633,9 +1637,11 @@ public class PlayerConnection implements PacketListenerPlayIn { + */ + + this.player.p(); +- String quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); +- if ((quitMessage != null) && (quitMessage.length() > 0)) { +- this.minecraftServer.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); ++ // Paper start - Adventure ++ net.kyori.adventure.text.Component quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); ++ if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) { ++ this.minecraftServer.getPlayerList().sendMessage(PaperAdventure.asVanilla(quitMessage)); ++ // Paper end + } + // CraftBukkit end + ITextFilter itextfilter = this.player.Q(); +@@ -1851,8 +1857,13 @@ public class PlayerConnection implements PacketListenerPlayIn { + this.handleCommand(s); + } else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) { + // Do nothing, this is coming from a plugin +- } else { +- Player player = this.getPlayer(); ++ // Paper start ++ } else if (true) { ++ final ChatProcessor cp = new ChatProcessor(this.minecraftServer, this.player, s, async); ++ cp.process(); ++ // Paper end ++ } else if (false) { // Paper ++ Player player = this.getPlayer(); // Paper + AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(minecraftServer)); + this.server.getPluginManager().callEvent(event); + +@@ -2670,21 +2681,20 @@ public class PlayerConnection implements PacketListenerPlayIn { + return; + } + +- // CraftBukkit start +- Player player = this.server.getPlayer(this.player); +- int x = packetplayinupdatesign.b().getX(); +- int y = packetplayinupdatesign.b().getY(); +- int z = packetplayinupdatesign.b().getZ(); +- String[] lines = new String[4]; ++ // CraftBukkit start // Paper start - Adventure ++ List lines = new java.util.ArrayList<>(); + + for (int i = 0; i < list.size(); ++i) { +- lines[i] = EnumChatFormat.a(new ChatComponentText(EnumChatFormat.a((String) list.get(i))).getString()); ++ lines.add(net.kyori.adventure.text.Component.text(list.get(i))); + } +- SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.server.getPlayer(this.player), lines); ++ SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); + this.server.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { +- System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.lines, 0, 4); ++ for (int i = 0; i < 4; i++) { ++ tileentitysign.a(i, PaperAdventure.asVanilla(event.line(i))); ++ } ++ // Paper end + tileentitysign.isEditable = false; + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index c601a5c577e438a3fa8dd4c5f36dbe9494b03d52..6ebd4ec781aa215c2b941261250c15c87c223cab 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -8,6 +8,7 @@ import com.mojang.authlib.GameProfile; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import io.netty.buffer.Unpooled; ++import io.papermc.paper.adventure.PaperAdventure; + import java.io.File; + import java.net.SocketAddress; + import java.text.SimpleDateFormat; +@@ -92,6 +93,7 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + // CraftBukkit start ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import com.google.common.base.Predicate; + import com.google.common.collect.Iterables; + +@@ -255,7 +257,7 @@ public abstract class PlayerList { + } + // CraftBukkit start + chatmessage.a(EnumChatFormat.YELLOW); +- String joinMessage = CraftChatMessage.fromComponent(chatmessage); ++ IChatBaseComponent joinMessage = chatmessage; // Paper - Adventure + + playerconnection.a(entityplayer.locX(), entityplayer.locY(), entityplayer.locZ(), entityplayer.yaw, entityplayer.pitch); + this.players.add(entityplayer); +@@ -264,19 +266,18 @@ public abstract class PlayerList { + // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below + + // CraftBukkit start +- PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(cserver.getPlayer(entityplayer), joinMessage); ++ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + cserver.getPluginManager().callEvent(playerJoinEvent); + + if (!entityplayer.playerConnection.networkManager.isConnected()) { + return; + } + +- joinMessage = playerJoinEvent.getJoinMessage(); ++ final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); + +- if (joinMessage != null && joinMessage.length() > 0) { +- for (IChatBaseComponent line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { +- server.getPlayerList().sendAll(new PacketPlayOutChat(line, ChatMessageType.SYSTEM, SystemUtils.b)); +- } ++ if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure ++ joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure ++ server.getPlayerList().sendAll(new PacketPlayOutChat(joinMessage, ChatMessageType.SYSTEM, SystemUtils.b)); // Paper - Adventure + } + // CraftBukkit end + +@@ -473,7 +474,7 @@ public abstract class PlayerList { + + } + +- public String disconnect(EntityPlayer entityplayer) { // CraftBukkit - return string ++ public net.kyori.adventure.text.Component disconnect(EntityPlayer entityplayer) { // Paper - return Component + WorldServer worldserver = entityplayer.getWorldServer(); + + entityplayer.a(StatisticList.LEAVE_GAME); +@@ -484,7 +485,7 @@ public abstract class PlayerList { + entityplayer.closeInventory(); + } + +- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getName() + " left the game"); ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); + cserver.getPluginManager().callEvent(playerQuitEvent); + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + +@@ -545,7 +546,7 @@ public abstract class PlayerList { + cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); + // CraftBukkit end + +- return playerQuitEvent.getQuitMessage(); // CraftBukkit ++ return playerQuitEvent.quitMessage(); // Paper - Adventure + } + + // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer +@@ -591,10 +592,10 @@ public abstract class PlayerList { + } + + // return chatmessage; +- if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); // Spigot ++ if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure + } else if (!this.isWhitelisted(gameprofile)) { + chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); +- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot ++ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure + } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { + IpBanEntry ipbanentry = this.l.get(socketaddress); + +@@ -604,17 +605,17 @@ public abstract class PlayerList { + } + + // return chatmessage; +- event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); ++ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + } else { + // return this.players.size() >= this.maxPlayers && !this.f(gameprofile) ? new ChatMessage("multiplayer.disconnect.server_full") : null; + if (this.players.size() >= this.maxPlayers && !this.f(gameprofile)) { +- event.disallow(PlayerLoginEvent.Result.KICK_FULL, org.spigotmc.SpigotConfig.serverFullMessage); // Spigot ++ event.disallow(PlayerLoginEvent.Result.KICK_FULL, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure + } + } + + cserver.getPluginManager().callEvent(event); + if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { +- loginlistener.disconnect(event.getKickMessage()); ++ loginlistener.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure + return null; + } + return entity; +@@ -1135,7 +1136,7 @@ public abstract class PlayerList { + public void shutdown() { + // CraftBukkit start - disconnect safely + for (EntityPlayer player : this.players) { +- player.playerConnection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message ++ player.playerConnection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure + } + // CraftBukkit end + +diff --git a/src/main/java/net/minecraft/world/BossBattle.java b/src/main/java/net/minecraft/world/BossBattle.java +index f9154b306379c45f15fe55406aaa00351b0471e8..1fb9fea7683075f427edfa411c7747d60928d537 100644 +--- a/src/main/java/net/minecraft/world/BossBattle.java ++++ b/src/main/java/net/minecraft/world/BossBattle.java +@@ -1,5 +1,6 @@ + package net.minecraft.world; + ++import io.papermc.paper.adventure.PaperAdventure; + import java.util.UUID; + import net.minecraft.EnumChatFormat; + import net.minecraft.network.chat.IChatBaseComponent; +@@ -14,6 +15,7 @@ public abstract class BossBattle { + protected boolean e; + protected boolean f; + protected boolean g; ++ public net.kyori.adventure.bossbar.BossBar adventure; // Paper + + public BossBattle(UUID uuid, IChatBaseComponent ichatbasecomponent, BossBattle.BarColor bossbattle_barcolor, BossBattle.BarStyle bossbattle_barstyle) { + this.h = uuid; +@@ -28,61 +30,75 @@ public abstract class BossBattle { + } + + public IChatBaseComponent j() { ++ if(this.adventure != null) return PaperAdventure.asVanilla(this.adventure.name()); // Paper + return this.title; + } + + public void a(IChatBaseComponent ichatbasecomponent) { ++ if (this.adventure != null) this.adventure.name(PaperAdventure.asAdventure(ichatbasecomponent)); // Paper + this.title = ichatbasecomponent; + } + + public float getProgress() { ++ if (this.adventure != null) return this.adventure.progress(); // Paper + return this.b; + } + + public void a(float f) { ++ if (this.adventure != null) this.adventure.progress(f); // Paper + this.b = f; + } + + public BossBattle.BarColor l() { ++ if (this.adventure != null) return PaperAdventure.asVanilla(this.adventure.color()); // Paper + return this.color; + } + + public void a(BossBattle.BarColor bossbattle_barcolor) { ++ if(this.adventure != null) this.adventure.color(PaperAdventure.asAdventure(bossbattle_barcolor)); // Paper + this.color = bossbattle_barcolor; + } + + public BossBattle.BarStyle m() { ++ if(this.adventure != null) return PaperAdventure.asVanilla(this.adventure.overlay()); // Paper + return this.style; + } + + public void a(BossBattle.BarStyle bossbattle_barstyle) { ++ if(this.adventure != null) this.adventure.overlay(PaperAdventure.asAdventure(bossbattle_barstyle)); // Paper + this.style = bossbattle_barstyle; + } + + public boolean isDarkenSky() { ++ if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.DARKEN_SCREEN); // Paper + return this.e; + } + + public BossBattle a(boolean flag) { ++ if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.DARKEN_SCREEN, flag); // Paper + this.e = flag; + return this; + } + + public boolean isPlayMusic() { ++ if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.PLAY_BOSS_MUSIC); // Paper + return this.f; + } + + public BossBattle b(boolean flag) { ++ if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.PLAY_BOSS_MUSIC, flag); // Paper + this.f = flag; + return this; + } + + public BossBattle c(boolean flag) { ++ if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.CREATE_WORLD_FOG, flag); // Paper + this.g = flag; + return this; + } + + public boolean isCreateFog() { ++ if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.CREATE_WORLD_FOG); // Paper + return this.g; + } + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 4010152dccc93019f2e7f284d80b92bae0d91c34..f1a780768e3f4bdb43a7ca6d7850befefb71bf57 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -867,6 +867,7 @@ public final class ItemStack { + } + // CraftBukkit end + ++ public IChatBaseComponent displayName() { return this.C(); } // Paper - OBFHELPER + public IChatBaseComponent C() { + IChatMutableComponent ichatmutablecomponent = (new ChatComponentText("")).addSibling(this.getName()); + +diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +index 0134bbda9e6fc900b7eefa05442e25539bab3431..b76ef55145336cc8dc4857b79767f5a738ad5144 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +@@ -94,6 +94,7 @@ public abstract class Enchantment { + return this.f(); + } + ++ public final IChatBaseComponent getTranslationComponentForLevel(int level) { return this.d(level); } // Paper - OBFHELPER + public IChatBaseComponent d(int i) { + ChatMessage chatmessage = new ChatMessage(this.g()); + +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java +index 7ec93ddd7e7c9dc54e3e4dcfe0d1654c0b0a8536..3f057f0bd23bc1c693c8f04ee8acd6626c620008 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java +@@ -32,6 +32,7 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + // CraftBukkit start ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import java.util.UUID; + + import org.bukkit.craftbukkit.CraftServer; +@@ -473,7 +474,7 @@ public class WorldMap extends PersistentBase { + for ( org.bukkit.map.MapCursor cursor : render.cursors) { + + if (cursor.isVisible()) { +- icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); ++ icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure + } + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0c1e12b0b43f949d4ace600b2ccdffe52faab1e6..2ad09749f3005c3eff143d83580e25910341aa6b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -562,8 +562,10 @@ public final class CraftServer implements Server { + } + + @Override ++ @Deprecated // Paper start + public int broadcastMessage(String message) { +- return broadcast(message, BROADCAST_CHANNEL_USERS); ++ return this.broadcast(message, BROADCAST_CHANNEL_USERS); ++ // Paper end + } + + public Player getPlayer(final EntityPlayer entity) { +@@ -1307,7 +1309,15 @@ public final class CraftServer implements Server { + return configuration.getInt("settings.spawn-radius", -1); + } + ++ // Paper start + @Override ++ public net.kyori.adventure.text.Component shutdownMessage() { ++ String msg = getShutdownMessage(); ++ return msg != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(msg) : null; ++ } ++ // Paper end ++ @Override ++ @Deprecated // Paper + public String getShutdownMessage() { + return configuration.getString("settings.shutdown-message"); + } +@@ -1423,7 +1433,20 @@ public final class CraftServer implements Server { + } + + @Override ++ @Deprecated // Paper + public int broadcast(String message, String permission) { ++ // Paper start - Adventure ++ return this.broadcast(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(message), permission); ++ } ++ ++ @Override ++ public int broadcast(net.kyori.adventure.text.Component message) { ++ return this.broadcast(message, BROADCAST_CHANNEL_USERS); ++ } ++ ++ @Override ++ public int broadcast(net.kyori.adventure.text.Component message, String permission) { ++ // Paper end + Set recipients = new HashSet<>(); + for (Permissible permissible : getPluginManager().getPermissionSubscriptions(permission)) { + if (permissible instanceof CommandSender && permissible.hasPermission(permission)) { +@@ -1431,14 +1454,14 @@ public final class CraftServer implements Server { + } + } + +- BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); ++ BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); // Paper - Adventure + getPluginManager().callEvent(broadcastMessageEvent); + + if (broadcastMessageEvent.isCancelled()) { + return 0; + } + +- message = broadcastMessageEvent.getMessage(); ++ message = broadcastMessageEvent.message(); // Paper - Adventure + + for (CommandSender recipient : recipients) { + recipient.sendMessage(message); +@@ -1664,6 +1687,14 @@ public final class CraftServer implements Server { + return CraftInventoryCreator.INSTANCE.createInventory(owner, type); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); ++ return CraftInventoryCreator.INSTANCE.createInventory(owner, type, title); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { + Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); +@@ -1676,13 +1707,28 @@ public final class CraftServer implements Server { + return CraftInventoryCreator.INSTANCE.createInventory(owner, size); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) throws IllegalArgumentException { ++ Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); ++ return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder owner, int size, String title) throws IllegalArgumentException { + Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); + return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); + } + ++ // Paper start ++ @Override ++ public Merchant createMerchant(net.kyori.adventure.text.Component title) { ++ return new org.bukkit.craftbukkit.inventory.CraftMerchantCustom(title == null ? InventoryType.MERCHANT.defaultTitle() : title); ++ } ++ // Paper end + @Override ++ @Deprecated // Paper + public Merchant createMerchant(String title) { + return new CraftMerchantCustom(title == null ? InventoryType.MERCHANT.getDefaultTitle() : title); + } +@@ -1726,6 +1772,12 @@ public final class CraftServer implements Server { + return Thread.currentThread().equals(console.serverThread) || console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog) + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component motd() { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(new net.minecraft.network.chat.ChatComponentText(console.getMotd())); ++ } ++ // Paper end + @Override + public String getMotd() { + return console.getMotd(); +@@ -2154,5 +2206,15 @@ public final class CraftServer implements Server { + return null; + } + } ++ ++ // Paper start ++ private Iterable adventure$audiences; ++ @Override ++ public Iterable audiences() { ++ if (this.adventure$audiences == null) { ++ this.adventure$audiences = com.google.common.collect.Iterables.concat(java.util.Collections.singleton(this.getConsoleSender()), this.getOnlinePlayers()); ++ } ++ return this.adventure$audiences; ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 05aedca561919a12ced1925c5cc9af585bb04523..ce9f10f890a5866ab6208c7253b15b09fe323a81 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -19,6 +19,12 @@ public class Main { + public static boolean useConsole = true; + + public static void main(String[] args) { ++ // Paper start ++ final String warnWhenLegacyFormattingDetected = String.join(".", "net", "kyori", "adventure", "text", "warnWhenLegacyFormattingDetected"); ++ if (false && System.getProperty(warnWhenLegacyFormattingDetected) == null) { ++ System.setProperty(warnWhenLegacyFormattingDetected, String.valueOf(true)); ++ } ++ // Paper end + // Todo: Installation script + OptionParser parser = new OptionParser() { + { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +index ae735836accc6bf6f0831f72ff882720b69df792..d3ae5cadd88f9012203d2c04cbe38af9b215ef0b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +@@ -70,6 +70,19 @@ public class CraftBeacon extends CraftBlockEntityState impleme + this.getSnapshot().secondaryEffect = (effect != null) ? MobEffectList.fromId(effect.getId()) : null; + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component customName() { ++ final TileEntityBeacon be = this.getSnapshot(); ++ return be.customName != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.customName) : null; ++ } ++ ++ @Override ++ public void customName(final net.kyori.adventure.text.Component customName) { ++ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); ++ } ++ // Paper end ++ + @Override + public String getCustomName() { + TileEntityBeacon beacon = this.getSnapshot(); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java +index e8ce890c551c9b809e8ba3f7449dc33f3a3a6b80..c99a59573653ee5d14e780137c769116bf781ea7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java +@@ -32,6 +32,19 @@ public abstract class CraftContainer extends Craf + this.getSnapshot().chestLock = (key == null) ? ChestLock.a : new ChestLock(key); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component customName() { ++ final T be = this.getSnapshot(); ++ return be.hasCustomName() ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.getCustomName()) : null; ++ } ++ ++ @Override ++ public void customName(final net.kyori.adventure.text.Component customName) { ++ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); ++ } ++ // Paper end ++ + @Override + public String getCustomName() { + T container = this.getSnapshot(); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java +index a559a77aae870988f4dd5e6f5f1f08feb3fad054..75ee5cc96c0e54f99e2ce820289bb74f57c426a2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java +@@ -16,6 +16,19 @@ public class CraftEnchantingTable extends CraftBlockEntityState implements Sign { + + // Lazily initialized only if requested: +- private String[] originalLines = null; +- private String[] lines = null; ++ // Paper start ++ private java.util.ArrayList originalLines = null; // ArrayList for RandomAccess ++ private java.util.ArrayList lines = null; // ArrayList for RandomAccess ++ // Paper end + + public CraftSign(final Block block) { + super(block, TileEntitySign.class); +@@ -24,27 +26,52 @@ public class CraftSign extends CraftBlockEntityState implements + super(material, te); + } + ++ // Paper start + @Override +- public String[] getLines() { +- if (lines == null) { +- // Lazy initialization: +- TileEntitySign sign = this.getSnapshot(); +- lines = new String[sign.lines.length]; +- System.arraycopy(revertComponents(sign.lines), 0, lines, 0, lines.length); +- originalLines = new String[lines.length]; +- System.arraycopy(lines, 0, originalLines, 0, originalLines.length); ++ public java.util.List lines() { ++ this.loadLines(); ++ return this.lines; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.Component line(int index) { ++ this.loadLines(); ++ return this.lines.get(index); ++ } ++ ++ @Override ++ public void line(int index, net.kyori.adventure.text.Component line) { ++ this.loadLines(); ++ this.lines.set(index, line); ++ } ++ ++ private void loadLines() { ++ if (lines != null) { ++ return; + } +- return lines; ++ ++ // Lazy initialization: ++ TileEntitySign sign = this.getSnapshot(); ++ lines = io.papermc.paper.adventure.PaperAdventure.asAdventure(com.google.common.collect.Lists.newArrayList(sign.lines)); ++ originalLines = new java.util.ArrayList<>(lines); ++ } ++ // Paper end ++ @Override ++ public String[] getLines() { ++ this.loadLines(); ++ return this.lines.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).toArray(String[]::new); // Paper + } + + @Override + public String getLine(int index) throws IndexOutOfBoundsException { +- return getLines()[index]; ++ this.loadLines(); ++ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(this.lines.get(index)); // Paper + } + + @Override + public void setLine(int index, String line) throws IndexOutOfBoundsException { +- getLines()[index] = line; ++ this.loadLines(); ++ this.lines.set(index, line != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(line) : net.kyori.adventure.text.Component.empty()); // Paper + } + + @Override +@@ -72,16 +99,32 @@ public class CraftSign extends CraftBlockEntityState implements + super.applyTo(sign); + + if (lines != null) { +- for (int i = 0; i < lines.length; i++) { +- String line = (lines[i] == null) ? "" : lines[i]; +- if (line.equals(originalLines[i])) { ++ // Paper start ++ for (int i = 0; i < this.lines.size(); ++i) { ++ net.kyori.adventure.text.Component component = this.lines.get(i); ++ net.kyori.adventure.text.Component origComp = this.originalLines.get(i); ++ if (component.equals(origComp)) { + continue; // The line contents are still the same, skip. + } +- sign.lines[i] = CraftChatMessage.fromString(line)[0]; ++ sign.lines[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(component); + } ++ // Paper end + } + } + ++ // Paper start ++ public static IChatBaseComponent[] sanitizeLines(java.util.List lines) { ++ IChatBaseComponent[] components = new IChatBaseComponent[4]; ++ for (int i = 0; i < 4; i++) { ++ if (i < lines.size() && lines.get(i) != null) { ++ components[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(lines.get(i)); ++ } else { ++ components[i] = new ChatComponentText(""); ++ } ++ } ++ return components; ++ } ++ // Paper end + public static IChatBaseComponent[] sanitizeLines(String[] lines) { + IChatBaseComponent[] components = new IChatBaseComponent[4]; + +diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +index 089fe4a3458ed3106fa214f89a7004a5d3c6bb95..af986adfdb547cb61fbd52f0f89858f1a9e52cc3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +@@ -80,4 +80,11 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co + public boolean isConversing() { + return conversationTracker.isConversing(); + } ++ ++ // Paper start ++ @Override ++ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { ++ this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); ++ } ++ // 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 8f694de2fb3827b9be0dd768ad90eb72c7d708e4..5a14430f63894bbe9daa42900cf5a6519bea4f45 100644 +--- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java ++++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +@@ -187,6 +187,12 @@ public class CraftEnchantment extends Enchantment { + CraftEnchantment ench = (CraftEnchantment) other; + return !target.isCompatible(ench.target); + } ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName(int level) { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); ++ } ++ // Paper end + + public net.minecraft.world.item.enchantment.Enchantment getHandle() { + return target; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index eea242af23825ad29ada6e997205e87edffb6bb9..3cf81734c8580f4d88ea97b6ac737a370b413c84 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -768,6 +768,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return getHandle().getVehicle().getBukkitEntity(); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component customName() { ++ final IChatBaseComponent name = this.getHandle().getCustomName(); ++ return name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(name) : null; ++ } ++ ++ @Override ++ public void customName(final net.kyori.adventure.text.Component customName) { ++ this.getHandle().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); ++ } ++ // Paper end ++ + @Override + public void setCustomName(String name) { + // sane limit for name length +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index 816f2cbebe849a9d9533f985298bcd5d36f660eb..24e856473a0050c0b097c179776350379d464d0c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -318,9 +318,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + container = CraftEventFactory.callInventoryOpenEvent(player, container); + if (container == null) return; + +- String title = container.getBukkitView().getTitle(); ++ //String title = container.getBukkitView().getTitle(); // Paper - comment ++ net.kyori.adventure.text.Component adventure$title = container.getBukkitView().title(); // Paper ++ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper + +- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); ++ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment ++ player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + getHandle().activeContainer = container; + getHandle().activeContainer.addSlotListener(player); + } +@@ -389,8 +392,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + + // Now open the window + Containers windowType = CraftContainer.getNotchInventoryType(inventory.getTopInventory()); +- String title = inventory.getTitle(); +- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); ++ ++ //String title = inventory.getTitle(); // Paper - comment ++ net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper ++ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper ++ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment ++ player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + player.activeContainer = container; + player.activeContainer.addSlotListener(player); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index b51a874e4665f977a154792e6216e03e04525f39..6ab14bccb1fcd108931bf7ec331e60f652e0b42d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -240,14 +240,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + @Override + public String getDisplayName() { ++ if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper + return getHandle().displayName; + } + + @Override + public void setDisplayName(final String name) { ++ this.getHandle().adventure$displayName = name != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(name) : net.kyori.adventure.text.Component.text(this.getName()); // Paper + getHandle().displayName = name == null ? getName() : name; + } + ++ // Paper start ++ @Override ++ public void playerListName(net.kyori.adventure.text.Component name) { ++ getHandle().listName = name == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(name); ++ for (EntityPlayer player : server.getHandle().players) { ++ if (player.getBukkitEntity().canSee(this)) { ++ player.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, getHandle())); ++ } ++ } ++ } ++ @Override ++ public net.kyori.adventure.text.Component playerListName() { ++ return getHandle().listName == null ? net.kyori.adventure.text.Component.text(getName()) : io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().listName); ++ } ++ @Override ++ public net.kyori.adventure.text.Component playerListHeader() { ++ return playerListHeader; ++ } ++ @Override ++ public net.kyori.adventure.text.Component playerListFooter() { ++ return playerListFooter; ++ } ++ // Paper end + @Override + public String getPlayerListName() { + return getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(getHandle().listName); +@@ -266,35 +291,35 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + } + +- private IChatBaseComponent playerListHeader; +- private IChatBaseComponent playerListFooter; ++ private net.kyori.adventure.text.Component playerListHeader; // Paper - Adventure ++ private net.kyori.adventure.text.Component playerListFooter; // Paper - Adventure + + @Override + public String getPlayerListHeader() { +- return (playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader); ++ return (playerListHeader == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListHeader); // Paper - Adventure + } + + @Override + public String getPlayerListFooter() { +- return (playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter); ++ return (playerListFooter == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListFooter); // Paper - Adventure + } + + @Override + public void setPlayerListHeader(String header) { +- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); ++ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure + updatePlayerListHeaderFooter(); + } + + @Override + public void setPlayerListFooter(String footer) { +- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); ++ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure + updatePlayerListHeaderFooter(); + } + + @Override + public void setPlayerListHeaderFooter(String header, String footer) { +- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); +- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); ++ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure ++ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure + updatePlayerListHeaderFooter(); + } + +@@ -302,8 +327,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + if (getHandle().playerConnection == null) return; + + PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); +- packet.header = (this.playerListHeader == null) ? new ChatComponentText("") : this.playerListHeader; +- packet.footer = (this.playerListFooter == null) ? new ChatComponentText("") : this.playerListFooter; ++ packet.header = (this.playerListHeader == null) ? new ChatComponentText("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListHeader); // Paper - Adventure ++ packet.footer = (this.playerListFooter == null) ? new ChatComponentText("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListFooter); // Paper - Adventure + getHandle().playerConnection.sendPacket(packet); + } + +@@ -335,6 +360,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + getHandle().playerConnection.disconnect(message == null ? "" : message); + } + ++ // Paper start ++ @Override ++ public void kick(final net.kyori.adventure.text.Component message) { ++ org.spigotmc.AsyncCatcher.catchOp("player kick"); ++ final PlayerConnection connection = this.getHandle().playerConnection; ++ if (connection != null) { ++ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); ++ } ++ } ++ // Paper end ++ + @Override + public void setCompassTarget(Location loc) { + if (getHandle().playerConnection == null) return; +@@ -561,6 +597,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + getHandle().playerConnection.sendPacket(packet); + } + ++ // Paper start ++ @Override ++ public void sendSignChange(Location loc, List lines) { ++ this.sendSignChange(loc, lines, org.bukkit.DyeColor.BLACK); ++ } ++ @Override ++ public void sendSignChange(Location loc, List lines, DyeColor dyeColor) { ++ if (getHandle().playerConnection == null) { ++ return; ++ } ++ if (lines == null) { ++ lines = new java.util.ArrayList<>(4); ++ } ++ Validate.notNull(loc, "Location cannot be null"); ++ Validate.notNull(dyeColor, "DyeColor cannot be null"); ++ if (lines.size() < 4) { ++ throw new IllegalArgumentException("Must have at least 4 lines"); ++ } ++ IChatBaseComponent[] components = CraftSign.sanitizeLines(lines); ++ this.sendSignChange0(components, loc, dyeColor); ++ } ++ ++ private void sendSignChange0(IChatBaseComponent[] components, Location loc, DyeColor dyeColor) { ++ TileEntitySign sign = new TileEntitySign(); ++ sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); ++ sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); ++ System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); ++ ++ getHandle().playerConnection.sendPacket(sign.getUpdatePacket()); ++ } ++ // Paper end + @Override + public void sendSignChange(Location loc, String[] lines) { + sendSignChange(loc, lines, DyeColor.BLACK); +@@ -583,12 +650,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + IChatBaseComponent[] components = CraftSign.sanitizeLines(lines); +- TileEntitySign sign = new TileEntitySign(); ++ /*TileEntitySign sign = new TileEntitySign(); // Paper + sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); + sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); + System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); + +- getHandle().playerConnection.sendPacket(sign.getUpdatePacket()); ++ getHandle().playerConnection.sendPacket(sign.getUpdatePacket());*/ // Paper ++ this.sendSignChange0(components, loc, dyeColor); // Paper + } + + @Override +@@ -1688,6 +1756,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return (getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : getHandle().clientViewDistance; + } + ++ // Paper start ++ @Override ++ public java.util.Locale locale() { ++ return getHandle().adventure$locale; ++ } ++ // Paper end + @Override + public int getPing() { + return getHandle().ping; +@@ -1716,6 +1790,138 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + getInventory().setItemInMainHand(hand); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() { ++ return this.getHandle().adventure$displayName; ++ } ++ ++ @Override ++ public void displayName(final net.kyori.adventure.text.Component displayName) { ++ this.getHandle().adventure$displayName = displayName != null ? displayName : net.kyori.adventure.text.Component.text(this.getName()); ++ this.getHandle().displayName = null; ++ } ++ ++ @Override ++ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { ++ final PacketPlayOutChat packet = new PacketPlayOutChat(null, type == net.kyori.adventure.audience.MessageType.CHAT ? net.minecraft.network.chat.ChatMessageType.CHAT : net.minecraft.network.chat.ChatMessageType.SYSTEM, identity.uuid()); ++ packet.adventure$message = message; ++ this.getHandle().playerConnection.sendPacket(packet); ++ } ++ ++ @Override ++ public void sendActionBar(final net.kyori.adventure.text.Component message) { ++ final PacketPlayOutTitle packet = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, null); ++ packet.adventure$text = message; ++ this.getHandle().playerConnection.sendPacket(packet); ++ } ++ ++ @Override ++ public void sendPlayerListHeader(final net.kyori.adventure.text.Component header) { ++ this.playerListHeader = header; ++ this.adventure$sendPlayerListHeaderAndFooter(); ++ } ++ ++ @Override ++ public void sendPlayerListFooter(final net.kyori.adventure.text.Component footer) { ++ this.playerListFooter = footer; ++ this.adventure$sendPlayerListHeaderAndFooter(); ++ } ++ ++ @Override ++ public void sendPlayerListHeaderAndFooter(final net.kyori.adventure.text.Component header, final net.kyori.adventure.text.Component footer) { ++ this.playerListHeader = header; ++ this.playerListFooter = footer; ++ this.adventure$sendPlayerListHeaderAndFooter(); ++ } ++ ++ private void adventure$sendPlayerListHeaderAndFooter() { ++ final PlayerConnection connection = this.getHandle().playerConnection; ++ if (connection == null) return; ++ final PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); ++ packet.adventure$header = (this.playerListHeader == null) ? net.kyori.adventure.text.Component.empty() : this.playerListHeader; ++ packet.adventure$footer = (this.playerListFooter == null) ? net.kyori.adventure.text.Component.empty() : this.playerListFooter; ++ connection.sendPacket(packet); ++ } ++ ++ @Override ++ public void showTitle(final net.kyori.adventure.title.Title title) { ++ final PlayerConnection connection = this.getHandle().playerConnection; ++ final net.kyori.adventure.title.Title.Times times = title.times(); ++ if (times != null) { ++ connection.sendPacket(new PacketPlayOutTitle(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut()))); ++ } ++ final PacketPlayOutTitle sp = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, null); ++ sp.adventure$text = title.subtitle(); ++ connection.sendPacket(sp); ++ final PacketPlayOutTitle tp = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, null); ++ tp.adventure$text = title.title(); ++ connection.sendPacket(tp); ++ } ++ ++ private static int ticks(final java.time.Duration duration) { ++ if (duration == null) { ++ return -1; ++ } ++ return (int) (duration.toMillis() / 50L); ++ } ++ ++ @Override ++ public void clearTitle() { ++ this.getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.CLEAR, null)); ++ } ++ ++ // resetTitle implemented above ++ ++ @Override ++ public void showBossBar(final net.kyori.adventure.bossbar.BossBar bar) { ++ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerShow(this); ++ } ++ ++ @Override ++ public void hideBossBar(final net.kyori.adventure.bossbar.BossBar bar) { ++ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerHide(this); ++ } ++ ++ @Override ++ public void playSound(final net.kyori.adventure.sound.Sound sound) { ++ final Vec3D pos = this.getHandle().getPositionVector(); ++ this.playSound(sound, pos.x, pos.y, pos.z); ++ } ++ ++ @Override ++ public void playSound(final net.kyori.adventure.sound.Sound sound, final double x, final double y, final double z) { ++ final MinecraftKey name = io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.name()); ++ final java.util.Optional event = net.minecraft.core.IRegistry.SOUND_EVENT.getOptional(name); ++ if (event.isPresent()) { ++ this.getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(event.get(), io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), x, y, z, sound.volume(), sound.pitch())); ++ } else { ++ this.getHandle().playerConnection.sendPacket(new PacketPlayOutCustomSoundEffect(name, io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), new Vec3D(x, y, z), sound.volume(), sound.pitch())); ++ } ++ } ++ ++ @Override ++ public void stopSound(final net.kyori.adventure.sound.SoundStop stop) { ++ this.getHandle().playerConnection.sendPacket(new PacketPlayOutStopSound( ++ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.sound()), ++ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.source()) ++ )); ++ } ++ ++ @Override ++ public void openBook(final net.kyori.adventure.inventory.Book book) { ++ final java.util.Locale locale = this.getHandle().adventure$locale; ++ final net.minecraft.world.item.ItemStack item = io.papermc.paper.adventure.PaperAdventure.asItemStack(book, locale); ++ final EntityPlayer player = this.getHandle(); ++ final PlayerConnection connection = player.playerConnection; ++ final net.minecraft.world.entity.player.PlayerInventory inventory = player.inventory; ++ final int slot = inventory.items.size() + inventory.itemInHandIndex; ++ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutSetSlot(0, slot, item)); ++ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutOpenBook(net.minecraft.world.EnumHand.MAIN_HAND)); ++ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutSetSlot(0, slot, inventory.getItemInHand())); ++ } ++ // Paper end ++ + // Spigot start + private final Player.Spigot spigot = new Player.Spigot() + { +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 5df71cbc9d5b7a481fd087623a0d02c98e5fefc4..8a7511fc1876dc6761826dd2636bce19d177d2e8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -788,9 +788,9 @@ public class CraftEventFactory { + return event; + } + +- public static PlayerDeathEvent callPlayerDeathEvent(EntityPlayer victim, List drops, String deathMessage, boolean keepInventory) { ++ public static PlayerDeathEvent callPlayerDeathEvent(EntityPlayer victim, List drops, net.kyori.adventure.text.Component deathMessage, String stringDeathMessage, boolean keepInventory) { // Paper - Adventure + CraftPlayer entity = victim.getBukkitEntity(); +- PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage); ++ PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure + event.setKeepInventory(keepInventory); + org.bukkit.World world = entity.getWorld(); + Bukkit.getServer().getPluginManager().callEvent(event); +@@ -814,7 +814,7 @@ public class CraftEventFactory { + * Server methods + */ + public static ServerListPingEvent callServerListPingEvent(Server craftServer, InetAddress address, String motd, int numPlayers, int maxPlayers) { +- ServerListPingEvent event = new ServerListPingEvent(address, motd, numPlayers, maxPlayers); ++ ServerListPingEvent event = new ServerListPingEvent(address, craftServer.motd(), numPlayers, maxPlayers); // Paper - Adventure + craftServer.getPluginManager().callEvent(event); + return event; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +index 384520dd734449d4e4f5243fbaad5f666b0c965c..614ab2d73db2293116f2272f6cd5c16da446132d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +@@ -39,6 +39,7 @@ public class CraftContainer extends Container { + + private final InventoryView view; + private InventoryType cachedType; ++ private net.kyori.adventure.text.Component adventure$title; // Paper + private String cachedTitle; + private Container delegate; + private final int cachedSize; +@@ -50,7 +51,9 @@ public class CraftContainer extends Container { + IInventory top = ((CraftInventory) view.getTopInventory()).getInventory(); + PlayerInventory bottom = (PlayerInventory) ((CraftInventory) view.getBottomInventory()).getInventory(); + cachedType = view.getType(); +- cachedTitle = view.getTitle(); ++ this.adventure$title = view.title(); // Paper ++ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper ++ //cachedTitle = view.getTitle(); // Paper - comment + cachedSize = getSize(); + setupSlots(top, bottom, player); + } +@@ -77,6 +80,13 @@ public class CraftContainer extends Container { + return inventory.getType(); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component title() { ++ return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).title() : net.kyori.adventure.text.Component.text(inventory.getType().getDefaultTitle()); ++ } ++ // Paper end ++ + @Override + public String getTitle() { + return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).getTitle() : inventory.getType().getDefaultTitle(); +@@ -95,7 +105,8 @@ public class CraftContainer extends Container { + + @Override + public boolean c(EntityHuman entityhuman) { +- if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { ++ if (cachedType == view.getType() && cachedSize == getSize() && this.adventure$title.equals(view.title())) { // Paper ++ //if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { // Paper - comment + return true; + } + // If the window type has changed for some reason, update the player +@@ -103,7 +114,9 @@ public class CraftContainer extends Container { + // as good a place as any to put something like this. + boolean typeChanged = (cachedType != view.getType()); + cachedType = view.getType(); +- cachedTitle = view.getTitle(); ++ this.adventure$title = view.title(); // Paper ++ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper ++ //cachedTitle = view.getTitle(); // Paper - comment + if (view.getPlayer() instanceof CraftPlayer) { + CraftPlayer player = (CraftPlayer) view.getPlayer(); + Containers type = getNotchInventoryType(view.getTopInventory()); +@@ -115,7 +128,8 @@ public class CraftContainer extends Container { + setupSlots(top, bottom, player.getHandle()); + } + int size = getSize(); +- player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, new ChatComponentText(cachedTitle))); ++ player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, io.papermc.paper.adventure.PaperAdventure.asVanilla(this.adventure$title))); // Paper ++ //player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, new ChatComponentText(cachedTitle))); // Paper - comment + player.updateInventory(); + } + return true; +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java +index a537cc4ac5d052168f96a1ae73b6b17a380436ab..21347cf02cc01c90a81e7dd8264ef11968d9f145 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java +@@ -19,6 +19,12 @@ public class CraftInventoryCustom extends CraftInventory { + super(new MinecraftInventory(owner, type)); + } + ++ // Paper start ++ public CraftInventoryCustom(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ super(new MinecraftInventory(owner, type, title)); ++ } ++ // Paper end ++ + public CraftInventoryCustom(InventoryHolder owner, InventoryType type, String title) { + super(new MinecraftInventory(owner, type, title)); + } +@@ -27,6 +33,12 @@ public class CraftInventoryCustom extends CraftInventory { + super(new MinecraftInventory(owner, size)); + } + ++ // Paper start ++ public CraftInventoryCustom(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { ++ super(new MinecraftInventory(owner, size, title)); ++ } ++ // Paper end ++ + public CraftInventoryCustom(InventoryHolder owner, int size, String title) { + super(new MinecraftInventory(owner, size, title)); + } +@@ -36,9 +48,17 @@ public class CraftInventoryCustom extends CraftInventory { + private int maxStack = MAX_STACK; + private final List viewers; + private final String title; ++ private final net.kyori.adventure.text.Component adventure$title; // Paper + private InventoryType type; + private final InventoryHolder owner; + ++ // Paper start ++ public MinecraftInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ this(owner, type.getDefaultSize(), title); ++ this.type = type; ++ } ++ // Paper end ++ + public MinecraftInventory(InventoryHolder owner, InventoryType type) { + this(owner, type.getDefaultSize(), type.getDefaultTitle()); + this.type = type; +@@ -57,11 +77,24 @@ public class CraftInventoryCustom extends CraftInventory { + Validate.notNull(title, "Title cannot be null"); + this.items = NonNullList.a(size, ItemStack.b); + this.title = title; ++ this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(title); + this.viewers = new ArrayList(); + this.owner = owner; + this.type = InventoryType.CHEST; + } + ++ // Paper start ++ public MinecraftInventory(final InventoryHolder owner, final int size, final net.kyori.adventure.text.Component title) { ++ Validate.notNull(title, "Title cannot be null"); ++ this.items = NonNullList.a(size, ItemStack.b); ++ this.title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); ++ this.adventure$title = title; ++ this.viewers = new ArrayList(); ++ this.owner = owner; ++ this.type = InventoryType.CHEST; ++ } ++ // Paper end ++ + @Override + public int getSize() { + return items.size(); +@@ -183,6 +216,12 @@ public class CraftInventoryCustom extends CraftInventory { + return null; + } + ++ // Paper start ++ public net.kyori.adventure.text.Component title() { ++ return this.adventure$title; ++ } ++ // Paper end ++ + public String getTitle() { + return title; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java +index 04073ed45f8068d80e58d3927b5ebc3160c6a8c6..9949bb8cac73b2f1f02b51079c0e244f923af8e9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java +@@ -64,6 +64,13 @@ public class CraftInventoryView extends InventoryView { + return CraftItemStack.asCraftMirror(container.getSlot(slot).getItem()); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component title() { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.container.getTitle()); ++ } ++ // Paper end ++ + @Override + public String getTitle() { + return CraftChatMessage.fromComponent(container.getTitle()); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index 89a3617068421bb86baf4e8bfd9df2d0626adff7..ccd27aa93b4ab1dc09a8d684b43b5ecb69100ed8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -334,4 +334,17 @@ public final class CraftItemFactory implements ItemFactory { + public Material updateMaterial(ItemMeta meta, Material material) throws IllegalArgumentException { + return ((CraftMetaItem) meta).updateMaterial(material); + } ++ ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final ItemStack item, final java.util.function.UnaryOperator op) { ++ final net.minecraft.nbt.NBTTagCompound tag = CraftItemStack.asNMSCopy(item).getTag(); ++ return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowItem.of(item.getType().getKey(), item.getAmount(), io.papermc.paper.adventure.PaperAdventure.asBinaryTagHolder(tag)))); ++ } ++ ++ @Override ++ public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +index ef10c7ab1d615cdba182eca63eb14309339a5314..206c133ebc6c44038585236b0628543b8bed278c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +@@ -14,10 +14,17 @@ import org.apache.commons.lang.Validate; + + public class CraftMerchantCustom extends CraftMerchant { + ++ @Deprecated // Paper - Adventure + public CraftMerchantCustom(String title) { + super(new MinecraftMerchant(title)); + getMerchant().craftMerchant = this; + } ++ // Paper start ++ public CraftMerchantCustom(net.kyori.adventure.text.Component title) { ++ super(new MinecraftMerchant(title)); ++ getMerchant().craftMerchant = this; ++ } ++ // Paper end + + @Override + public String toString() { +@@ -37,10 +44,17 @@ public class CraftMerchantCustom extends CraftMerchant { + private World tradingWorld; + protected CraftMerchant craftMerchant; + ++ @Deprecated // Paper - Adventure + public MinecraftMerchant(String title) { + Validate.notNull(title, "Title cannot be null"); + this.title = new ChatComponentText(title); + } ++ // Paper start ++ public MinecraftMerchant(net.kyori.adventure.text.Component title) { ++ Validate.notNull(title, "Title cannot be null"); ++ this.title = io.papermc.paper.adventure.PaperAdventure.asVanilla(title); ++ } ++ // Paper end + + @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 4cdc504df4cad6f7725f6d18482e88433523943a..65b6d32e3e1130a64df33082f3292cb1ce6f500a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +@@ -1,8 +1,9 @@ + package org.bukkit.craftbukkit.inventory; + + import com.google.common.collect.ImmutableList; +-import com.google.common.collect.ImmutableMap.Builder; + import com.google.common.collect.Lists; ++ ++import com.google.common.collect.ImmutableMap; // Paper + import java.util.ArrayList; + import java.util.Arrays; + import java.util.List; +@@ -21,6 +22,7 @@ import org.bukkit.craftbukkit.util.CraftChatMessage; + import org.bukkit.craftbukkit.util.CraftMagicNumbers; + import org.bukkit.inventory.meta.BookMeta; + import org.bukkit.inventory.meta.BookMeta.Generation; ++import org.checkerframework.checker.nullness.qual.NonNull; + + // Spigot start + import static org.spigotmc.ValidateUtils.*; +@@ -269,6 +271,141 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + this.generation = (generation == null) ? null : generation.ordinal(); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component title() { ++ return this.title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.title); ++ } ++ ++ @Override ++ public org.bukkit.inventory.meta.BookMeta title(net.kyori.adventure.text.Component title) { ++ this.setTitle(title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title)); ++ return this; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.Component author() { ++ return this.author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.author); ++ } ++ ++ @Override ++ public org.bukkit.inventory.meta.BookMeta author(net.kyori.adventure.text.Component author) { ++ this.setAuthor(author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author)); ++ return this; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.Component page(final int page) { ++ Validate.isTrue(isValidPage(page), "Invalid page number"); ++ return this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(pages.get(page - 1)) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(pages.get(page - 1)); ++ } ++ ++ @Override ++ public void page(final int page, net.kyori.adventure.text.Component data) { ++ if (!isValidPage(page)) { ++ throw new IllegalArgumentException("Invalid page number " + page + "/" + pages.size()); ++ } ++ if (data == null) { ++ data = net.kyori.adventure.text.Component.empty(); ++ } ++ pages.set(page - 1, this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(data) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(data)); ++ } ++ ++ @Override ++ public List pages() { ++ if (this.pages == null) return ImmutableList.of(); ++ if (this instanceof CraftMetaBookSigned) ++ return pages.stream().map(net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson()::deserialize).collect(ImmutableList.toImmutableList()); ++ else ++ return pages.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::deserialize).collect(ImmutableList.toImmutableList()); ++ } ++ ++ @Override ++ public BookMeta pages(List pages) { ++ if (this.pages != null) this.pages.clear(); ++ for (net.kyori.adventure.text.Component page : pages) { ++ addPages(page); ++ } ++ return this; ++ } ++ ++ @Override ++ public BookMeta pages(net.kyori.adventure.text.Component... pages) { ++ if (this.pages != null) this.pages.clear(); ++ addPages(pages); ++ return this; ++ } ++ ++ @Override ++ public void addPages(net.kyori.adventure.text.Component... pages) { ++ if (this.pages == null) this.pages = new ArrayList<>(); ++ for (net.kyori.adventure.text.Component page : pages) { ++ if (this.pages.size() >= MAX_PAGES) { ++ return; ++ } ++ ++ if (page == null) { ++ page = net.kyori.adventure.text.Component.empty(); ++ } ++ ++ this.pages.add(this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(page) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(page)); ++ } ++ } ++ ++ private CraftMetaBook(net.kyori.adventure.text.Component title, net.kyori.adventure.text.Component author, List pages) { ++ super((org.bukkit.craftbukkit.inventory.CraftMetaItem) org.bukkit.Bukkit.getItemFactory().getItemMeta(org.bukkit.Material.WRITABLE_BOOK)); ++ this.title = title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); ++ this.author = author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author); ++ this.pages = pages.subList(0, Math.min(MAX_PAGES, pages.size())).stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).collect(java.util.stream.Collectors.toList()); ++ } ++ ++ static final class CraftMetaBookBuilder implements BookMetaBuilder { ++ private net.kyori.adventure.text.Component title = null; ++ private net.kyori.adventure.text.Component author = null; ++ private final List pages = new java.util.ArrayList<>(); ++ ++ @Override ++ public BookMetaBuilder title(net.kyori.adventure.text.Component title) { ++ this.title = title; ++ return this; ++ } ++ ++ @Override ++ public BookMetaBuilder author(net.kyori.adventure.text.Component author) { ++ this.author = author; ++ return this; ++ } ++ ++ @Override ++ public BookMetaBuilder addPage(net.kyori.adventure.text.Component page) { ++ this.pages.add(page); ++ return this; ++ } ++ ++ @Override ++ public BookMetaBuilder pages(net.kyori.adventure.text.Component... pages) { ++ java.util.Collections.addAll(this.pages, pages); ++ return this; ++ } ++ ++ @Override ++ public BookMetaBuilder pages(java.util.Collection pages) { ++ this.pages.addAll(pages); ++ return this; ++ } ++ ++ @Override ++ public BookMeta build() { ++ return new CraftMetaBook(title, author, pages); ++ } ++ } ++ ++ @Override ++ public BookMetaBuilder toBuilder() { ++ return new CraftMetaBookBuilder(); ++ } ++ ++ // Paper end + @Override + public String getPage(final int page) { + Validate.isTrue(isValidPage(page), "Invalid page number"); +@@ -413,7 +550,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + } + + @Override +- Builder serialize(Builder builder) { ++ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { + super.serialize(builder); + + if (hasTitle()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java +index 0835541f51e643ae824c197be7100d5849b5e92a..0d58ec9834797ad7b9acaae6353dcf0385c53fd4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java +@@ -1,6 +1,6 @@ + package org.bukkit.craftbukkit.inventory; + +-import com.google.common.collect.ImmutableMap.Builder; ++import com.google.common.collect.ImmutableMap; // Paper + import java.util.Map; + import net.minecraft.nbt.NBTTagCompound; + import org.bukkit.Material; +@@ -84,7 +84,7 @@ class CraftMetaBookSigned extends CraftMetaBook implements BookMeta { + } + + @Override +- Builder serialize(Builder builder) { ++ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { + super.serialize(builder); + return builder; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 928328c292a1322cab478bc748761baf8608e4b0..7a11b2ddfa4244459253c918315aaab78ef2eb4a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -745,6 +745,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() { ++ return displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(displayName); ++ } ++ ++ @Override ++ public void displayName(final net.kyori.adventure.text.Component displayName) { ++ this.displayName = displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(displayName); ++ } ++ // Paper end ++ + @Override + public String getDisplayName() { + return CraftChatMessage.fromJSONComponent(displayName); +@@ -780,6 +792,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return this.lore != null && !this.lore.isEmpty(); + } + ++ // Paper start ++ @Override ++ public List lore() { ++ return this.lore != null ? io.papermc.paper.adventure.PaperAdventure.asAdventureFromJson(this.lore) : null; ++ } ++ ++ @Override ++ public void lore(final List lore) { ++ this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asJson(lore) : null; ++ } ++ // Paper end ++ + @Override + public boolean hasRepairCost() { + return repairCost > 0; +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java +index ed4415f6dd588c08c922efd5beebb3b124beb9d6..78a7ac47f20e84ccd67ff44d0bc7a2f2faa0d476 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java +@@ -12,6 +12,13 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve + return new CraftInventoryCustom(holder, type); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ return new CraftInventoryCustom(owner, type, title); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { + return new CraftInventoryCustom(owner, type, title); +@@ -21,6 +28,12 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve + return new CraftInventoryCustom(owner, size); + } + ++ // Paper start ++ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { ++ return new CraftInventoryCustom(owner, size, title); ++ } ++ // Paper end ++ + public Inventory createInventory(InventoryHolder owner, int size, String title) { + return new CraftInventoryCustom(owner, size, title); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b833806a0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +@@ -43,6 +43,17 @@ public final class CraftInventoryCreator { + return converterMap.get(type).createInventory(holder, type); + } + ++ // Paper start ++ public Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title) { ++ // Paper start ++ if (holder != null) { ++ return DEFAULT_CONVERTER.createInventory(holder, type, title); ++ } ++ //noinspection ConstantConditions // Paper end ++ return converterMap.get(type).createInventory(holder, type, title); ++ } ++ // Paper end ++ + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { + return converterMap.get(type).createInventory(holder, type, title); + } +@@ -51,6 +62,12 @@ public final class CraftInventoryCreator { + return DEFAULT_CONVERTER.createInventory(holder, size); + } + ++ // Paper start ++ public Inventory createInventory(InventoryHolder holder, int size, net.kyori.adventure.text.Component title) { ++ return DEFAULT_CONVERTER.createInventory(holder, size, title); ++ } ++ // Paper end ++ + public Inventory createInventory(InventoryHolder holder, int size, String title) { + return DEFAULT_CONVERTER.createInventory(holder, size, title); + } +@@ -59,6 +76,10 @@ public final class CraftInventoryCreator { + + Inventory createInventory(InventoryHolder holder, InventoryType type); + ++ // Paper start ++ Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title); ++ // Paper end ++ + Inventory createInventory(InventoryHolder holder, InventoryType type, String title); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java +index f35e66dab9ff63ca05d7e303c71106c0e9971309..2bd4e644ffbde2e1133b25824a2829bc6b33fa84 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java +@@ -31,6 +31,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat + return getInventory(getTileEntity()); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ IInventory te = getTileEntity(); ++ if (te instanceof TileEntityLootable) { ++ ((TileEntityLootable) te).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); ++ } ++ ++ return getInventory(te); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { + IInventory te = getTileEntity(); +@@ -54,6 +66,15 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat + return furnace; + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ IInventory tileEntity = getTileEntity(); ++ ((TileEntityFurnace) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); ++ return getInventory(tileEntity); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { + IInventory tileEntity = getTileEntity(); +@@ -74,6 +95,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat + return new TileEntityBrewingStand(); + } + ++ // Paper start ++ @Override ++ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { ++ // BrewingStand does not extend TileEntityLootable ++ IInventory tileEntity = getTileEntity(); ++ if (tileEntity instanceof TileEntityBrewingStand) { ++ ((TileEntityBrewingStand) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); ++ } ++ return getInventory(tileEntity); ++ } ++ // Paper end ++ + @Override + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { + // BrewingStand does not extend TileEntityLootable +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java +index 8fedca656af0783f3d97a7ccde3a113f97911084..df3deee12b11508b76c5f8f927fac8db54a7e397 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java +@@ -31,6 +31,21 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective + return objective.getName(); + } + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(objective.getDisplayName()); ++ } ++ @Override ++ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { ++ if (displayName == null) { ++ displayName = net.kyori.adventure.text.Component.empty(); ++ } ++ CraftScoreboard scoreboard = checkState(); ++ objective.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); ++ } ++ // Paper end + @Override + public String getDisplayName() throws IllegalStateException { + CraftScoreboard scoreboard = checkState(); +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +index 954389b818de93cf0ab046edc5dc032fceea391b..6ea491f6308317059c4bc6735abbdce370df0f34 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +@@ -28,6 +28,27 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + public CraftObjective registerNewObjective(String name, String criteria) throws IllegalArgumentException { + return registerNewObjective(name, criteria, name); + } ++ // Paper start ++ @Override ++ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName) { ++ return registerNewObjective(name, criteria, displayName, org.bukkit.scoreboard.RenderType.INTEGER); ++ } ++ @Override ++ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName, RenderType renderType) { ++ if (displayName == null) { ++ displayName = net.kyori.adventure.text.Component.empty(); ++ } ++ Validate.notNull(name, "Objective name cannot be null"); ++ Validate.notNull(criteria, "Criteria cannot be null"); ++ Validate.notNull(displayName, "Display name cannot be null"); ++ Validate.notNull(renderType, "RenderType cannot be null"); ++ Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); ++ Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); ++ CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); ++ ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); ++ return new CraftObjective(this, objective); ++ } ++ // Paper end + + @Override + public CraftObjective registerNewObjective(String name, String criteria, String displayName) throws IllegalArgumentException { +@@ -36,7 +57,7 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + + @Override + public CraftObjective registerNewObjective(String name, String criteria, String displayName, RenderType renderType) throws IllegalArgumentException { +- Validate.notNull(name, "Objective name cannot be null"); ++ /*Validate.notNull(name, "Objective name cannot be null"); // Paper + Validate.notNull(criteria, "Criteria cannot be null"); + Validate.notNull(displayName, "Display name cannot be null"); + Validate.notNull(renderType, "RenderType cannot be null"); +@@ -46,7 +67,8 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + + CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); + ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); +- return new CraftObjective(this, objective); ++ return new CraftObjective(this, objective);*/ // Paper ++ return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +index a213c2e3b2680c6d1bd38853580cbdb52ae7779e..c631934fe9d205a06956c900d5b58a1d8a781c19 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +@@ -29,6 +29,55 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { + + return team.getName(); + } ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getDisplayName()); ++ } ++ @Override ++ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { ++ if (displayName == null) displayName = net.kyori.adventure.text.Component.empty(); ++ CraftScoreboard scoreboard = checkState(); ++ team.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); ++ } ++ @Override ++ public net.kyori.adventure.text.Component prefix() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPrefix()); ++ } ++ @Override ++ public void prefix(net.kyori.adventure.text.Component prefix) throws IllegalStateException, IllegalArgumentException { ++ if (prefix == null) prefix = net.kyori.adventure.text.Component.empty(); ++ CraftScoreboard scoreboard = checkState(); ++ team.setPrefix(io.papermc.paper.adventure.PaperAdventure.asVanilla(prefix)); ++ } ++ @Override ++ public net.kyori.adventure.text.Component suffix() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getSuffix()); ++ } ++ @Override ++ public void suffix(net.kyori.adventure.text.Component suffix) throws IllegalStateException, IllegalArgumentException { ++ if (suffix == null) suffix = net.kyori.adventure.text.Component.empty(); ++ CraftScoreboard scoreboard = checkState(); ++ team.setSuffix(io.papermc.paper.adventure.PaperAdventure.asVanilla(suffix)); ++ } ++ @Override ++ public net.kyori.adventure.text.format.TextColor color() throws IllegalStateException { ++ CraftScoreboard scoreboard = checkState(); ++ if (team.getColor().getHexValue() == null) throw new IllegalStateException("Team colors must have hex values"); ++ net.kyori.adventure.text.format.TextColor color = net.kyori.adventure.text.format.TextColor.color(team.getColor().getHexValue()); ++ if (!(color instanceof net.kyori.adventure.text.format.NamedTextColor)) throw new IllegalStateException("Team doesn't have a NamedTextColor"); ++ return (net.kyori.adventure.text.format.NamedTextColor) color; ++ } ++ @Override ++ public void color(net.kyori.adventure.text.format.NamedTextColor color) { ++ if (color == null) color = net.kyori.adventure.text.format.NamedTextColor.WHITE; ++ CraftScoreboard scoreboard = checkState(); ++ team.setColor(io.papermc.paper.adventure.PaperAdventure.asVanilla(color)); ++ } ++ // Paper end + + @Override + public String getDisplayName() throws IllegalStateException { +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +index 6a0b4cd36ac54df41642e8499c50e59f2b347b48..666af6cc91bd12ba5d5a846d663a5aabf861fbc4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +@@ -290,6 +290,7 @@ public final class CraftChatMessage { + + public static String fromComponent(IChatBaseComponent component) { + if (component == null) return ""; ++ if (component instanceof io.papermc.paper.adventure.AdventureComponent) component = ((io.papermc.paper.adventure.AdventureComponent) component).deepConverted(); + StringBuilder out = new StringBuilder(); + + 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 65131f0977fa55c4761c34ce52720170feb61a72..8f737f63f280c00c1276bd1dc3ecf60448732ca8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -59,6 +59,33 @@ public final class CraftMagicNumbers implements UnsafeValues { + + private CraftMagicNumbers() {} + ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener() { ++ return io.papermc.paper.adventure.PaperAdventure.FLATTENER; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer() { ++ return io.papermc.paper.adventure.PaperAdventure.COLOR_DOWNSAMPLING_GSON; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer() { ++ return io.papermc.paper.adventure.PaperAdventure.GSON; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer() { ++ return io.papermc.paper.adventure.PaperAdventure.PLAIN; ++ } ++ ++ @Override ++ public net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer() { ++ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC; ++ } ++ // Paper end ++ + public static IBlockData getBlock(MaterialData material) { + return getBlock(material.getItemType(), material.getData()); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java +index f194cf2663919ea18309a0501ddfab5e2ed639dd..4b110d6c6f22ff7c2fa0fd4b459820797066199d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java +@@ -80,7 +80,7 @@ public abstract class LazyHashSet implements Set { + return this.reference = makeReference(); + } + +- abstract Set makeReference(); ++ protected abstract Set makeReference(); // Paper - protected + + public boolean isLazy() { + return reference == null; +diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java +index e7b9250ebdd0d9034ef18a96a6cacc83e6db69c2..20ee8468bcf305139a51da61f5f9026794da27f6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java +@@ -15,10 +15,15 @@ public class LazyPlayerSet extends LazyHashSet { + } + + @Override +- HashSet makeReference() { ++ protected HashSet makeReference() { // Paper - protected + if (reference != null) { + throw new IllegalStateException("Reference already created!"); + } ++ // Paper start ++ return makePlayerSet(this.server); ++ } ++ public static HashSet makePlayerSet(final MinecraftServer server) { ++ // Paper end + List players = server.getPlayerList().players; + HashSet reference = new HashSet(players.size()); + for (EntityPlayer player : players) { diff --git a/patches/server-unmapped/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch b/patches/server-unmapped/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch new file mode 100644 index 0000000000..d184572c6b --- /dev/null +++ b/patches/server-unmapped/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch @@ -0,0 +1,114 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 13:02:51 -0600 +Subject: [PATCH] Configurable cactus bamboo and reed growth heights + +Bamboo - Both the minimum fully-grown heights and the maximum are configurable +- Machine_Maker + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index b31109d2dadd29e8852468c19265066b773d2be0..3618cc017feb60e257a28f67cbddca3f792a9833 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -65,4 +65,17 @@ public class PaperWorldConfig { + config.addDefault("world-settings.default." + path, def); + return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); + } ++ ++ public int cactusMaxHeight; ++ public int reedMaxHeight; ++ public int bambooMaxHeight; ++ public int bambooMinHeight; ++ private void blockGrowthHeight() { ++ cactusMaxHeight = getInt("max-growth-height.cactus", 3); ++ reedMaxHeight = getInt("max-growth-height.reeds", 3); ++ bambooMaxHeight = getInt("max-growth-height.bamboo.max", 16); ++ bambooMinHeight = getInt("max-growth-height.bamboo.min", 11); ++ log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); ++ ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockBamboo.java b/src/main/java/net/minecraft/world/level/block/BlockBamboo.java +index 6d10a7cb48627f37dc91b73064edc5f18c2b5ce9..cd132eff3f82349518555d1d5a16778ca08a521b 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockBamboo.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockBamboo.java +@@ -124,7 +124,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { + if (random.nextInt(Math.max(1, (int) (100.0F / worldserver.spigotConfig.bambooModifier) * 3)) == 0 && worldserver.isEmpty(blockposition.up()) && worldserver.getLightLevel(blockposition.up(), 0) >= 9) { // Spigot + int i = this.b(worldserver, blockposition) + 1; + +- if (i < 16) { ++ if (i < worldserver.paperConfig.bambooMaxHeight) { // Paper + this.a(iblockdata, (World) worldserver, blockposition, random, i); + } + } +@@ -155,7 +155,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { + int i = this.a(iblockaccess, blockposition); + int j = this.b(iblockaccess, blockposition); + +- return i + j + 1 < 16 && (Integer) iblockaccess.getType(blockposition.up(i)).get(BlockBamboo.f) != 1; ++ return i + j + 1 < ((World) iblockaccess).paperConfig.bambooMaxHeight && (Integer) iblockaccess.getType(blockposition.up(i)).get(BlockBamboo.f) != 1; // Paper + } + + @Override +@@ -174,7 +174,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { + BlockPosition blockposition1 = blockposition.up(i); + IBlockData iblockdata1 = worldserver.getType(blockposition1); + +- if (k >= 16 || !iblockdata1.a(Blocks.BAMBOO) || (Integer) iblockdata1.get(BlockBamboo.f) == 1 || !worldserver.isEmpty(blockposition1.up())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here ++ if (k >= worldserver.paperConfig.bambooMaxHeight || !iblockdata1.a(Blocks.BAMBOO) || (Integer) iblockdata1.get(BlockBamboo.f) == 1 || !worldserver.isEmpty(blockposition1.up())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here // Paper - Configurable cactus bamboo and reed growth heights + return; + } + +@@ -215,7 +215,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { + } + + int j = (Integer) iblockdata.get(BlockBamboo.d) != 1 && !iblockdata2.a(Blocks.BAMBOO) ? 0 : 1; +- int k = (i < 11 || random.nextFloat() >= 0.25F) && i != 15 ? 0 : 1; ++ int k = (i < world.paperConfig.bambooMinHeight || random.nextFloat() >= 0.25F) && i != (world.paperConfig.bambooMaxHeight - 1) ? 0 : 1; // Paper + + // CraftBukkit start + if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, blockposition, blockposition.up(), (IBlockData) ((IBlockData) ((IBlockData) this.getBlockData().set(BlockBamboo.d, j)).set(BlockBamboo.e, blockpropertybamboosize)).set(BlockBamboo.f, k), 3)) { +@@ -230,7 +230,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { + protected int a(IBlockAccess iblockaccess, BlockPosition blockposition) { + int i; + +- for (i = 0; i < 16 && iblockaccess.getType(blockposition.up(i + 1)).a(Blocks.BAMBOO); ++i) { ++ for (i = 0; i < ((World) iblockaccess).paperConfig.bambooMaxHeight && iblockaccess.getType(blockposition.up(i + 1)).a(Blocks.BAMBOO); ++i) { // Paper + ; + } + +@@ -240,7 +240,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { + protected int b(IBlockAccess iblockaccess, BlockPosition blockposition) { + int i; + +- for (i = 0; i < 16 && iblockaccess.getType(blockposition.down(i + 1)).a(Blocks.BAMBOO); ++i) { ++ for (i = 0; i < ((World) iblockaccess).paperConfig.bambooMaxHeight && iblockaccess.getType(blockposition.down(i + 1)).a(Blocks.BAMBOO); ++i) { // Paper + ; + } + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockCactus.java b/src/main/java/net/minecraft/world/level/block/BlockCactus.java +index c2316e346f9b647edae4c9709defa4531e04eaa6..9f1e9fc5361cd051b909e2e1b2095722064185da 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockCactus.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockCactus.java +@@ -55,7 +55,7 @@ public class BlockCactus extends Block { + ; + } + +- if (i < 3) { ++ if (i < worldserver.paperConfig.cactusMaxHeight) { // Paper - Configurable growth height + int j = (Integer) iblockdata.get(BlockCactus.AGE); + + if (j >= (byte) range(3, ((100.0F / worldserver.spigotConfig.cactusModifier) * 15) + 0.5F, 15)) { // Spigot +diff --git a/src/main/java/net/minecraft/world/level/block/BlockReed.java b/src/main/java/net/minecraft/world/level/block/BlockReed.java +index eb95d65e1a37b91a71a9ad8968710ba9047f3980..a4ede7968ba0134f0d2cf880a6b4a6b9a81f2fcd 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockReed.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockReed.java +@@ -51,7 +51,7 @@ public class BlockReed extends Block { + ; + } + +- if (i < 3) { ++ if (i < worldserver.paperConfig.reedMaxHeight) { // Paper - Configurable growth height + int j = (Integer) iblockdata.get(BlockReed.AGE); + + if (j >= (byte) range(3, ((100.0F / worldserver.spigotConfig.caneModifier) * 15) + 0.5F, 15)) { // Spigot diff --git a/patches/server-unmapped/0012-Configurable-baby-zombie-movement-speed.patch b/patches/server-unmapped/0012-Configurable-baby-zombie-movement-speed.patch new file mode 100644 index 0000000000..060f23376f --- /dev/null +++ b/patches/server-unmapped/0012-Configurable-baby-zombie-movement-speed.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 13:09:16 -0600 +Subject: [PATCH] Configurable baby zombie movement speed + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3618cc017feb60e257a28f67cbddca3f792a9833..796c17e0941922a9716212c6eae91643d8360418 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -78,4 +78,15 @@ public class PaperWorldConfig { + log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); + + } ++ ++ public double babyZombieMovementModifier; ++ private void babyZombieMovementModifier() { ++ babyZombieMovementModifier = getDouble("baby-zombie-movement-modifier", 0.5D); ++ if (PaperConfig.version < 20) { ++ babyZombieMovementModifier = getDouble("baby-zombie-movement-speed", 0.5D); ++ set("baby-zombie-movement-modifier", babyZombieMovementModifier); ++ } ++ ++ log("Baby zombies will move at the speed of " + babyZombieMovementModifier); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index daa6d1ca20f952971a2ad6a0c4cba0bef6e43bf6..219e3b1626d68ede57b08a706d24bb6bc4b13fac 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -82,7 +82,7 @@ import org.bukkit.event.entity.EntityTransformEvent; + public class EntityZombie extends EntityMonster { + + private static final UUID b = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836"); +- private static final AttributeModifier c = new AttributeModifier(EntityZombie.b, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); ++ private final AttributeModifier c = new AttributeModifier(EntityZombie.b, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); private final AttributeModifier babyModifier = this.c; // Paper - remove static - Make baby speed configurable + private static final DataWatcherObject d = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); + private static final DataWatcherObject bo = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.b); + public static final DataWatcherObject DROWN_CONVERTING = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); +@@ -185,9 +185,9 @@ public class EntityZombie extends EntityMonster { + if (this.world != null && !this.world.isClientSide) { + AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); + +- attributemodifiable.removeModifier(EntityZombie.c); ++ attributemodifiable.removeModifier(this.babyModifier); // Paper + if (flag) { +- attributemodifiable.b(EntityZombie.c); ++ attributemodifiable.b(this.babyModifier); // Paper + } + } + diff --git a/patches/server-unmapped/0013-Configurable-fishing-time-ranges.patch b/patches/server-unmapped/0013-Configurable-fishing-time-ranges.patch new file mode 100644 index 0000000000..b516f276ef --- /dev/null +++ b/patches/server-unmapped/0013-Configurable-fishing-time-ranges.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 13:14:11 -0600 +Subject: [PATCH] Configurable fishing time ranges + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 796c17e0941922a9716212c6eae91643d8360418..78948c42b13194005bdbbbc69c2b7ae0732a78c5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -89,4 +89,12 @@ public class PaperWorldConfig { + + log("Baby zombies will move at the speed of " + babyZombieMovementModifier); + } ++ ++ public int fishingMinTicks; ++ public int fishingMaxTicks; ++ private void fishingTickRange() { ++ fishingMinTicks = getInt("fishing-time-range.MinimumTicks", 100); ++ fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); ++ log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +index 382b40a2a030993e1e98f34bc91befdd45c16895..7402e3b305d9bb7b27b97ff2078c26dd578232a1 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +@@ -85,6 +85,10 @@ public class EntityFishingHook extends IProjectile { + entityhuman.hookedFish = this; + this.an = Math.max(0, i); + this.lureLevel = Math.max(0, j); ++ // Paper start ++ minWaitTime = world.paperConfig.fishingMinTicks; ++ maxWaitTime = world.paperConfig.fishingMaxTicks; ++ // paper end + } + + public EntityFishingHook(EntityHuman entityhuman, World world, int i, int j) { diff --git a/patches/server-unmapped/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/patches/server-unmapped/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch new file mode 100644 index 0000000000..3c4047985e --- /dev/null +++ b/patches/server-unmapped/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch @@ -0,0 +1,98 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 13:24:16 -0600 +Subject: [PATCH] Allow nerfed mobs to jump and take water damage + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 78948c42b13194005bdbbbc69c2b7ae0732a78c5..b41e7922dd96c3358eb849ab39982a75736e3476 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -97,4 +97,9 @@ public class PaperWorldConfig { + fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); + log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); + } ++ ++ public boolean nerfedMobsShouldJump; ++ private void nerfedMobsShouldJump() { ++ nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 306f6c0db2333cce5dfc4bf1c09bfef05119a28b..f823763a2f7f40d0be8d058a1bd61386bcd951e6 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1105,6 +1105,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return this.isInWater() || this.isInRain(); + } + ++ public final boolean isInWaterOrRainOrBubble() { return aG(); } // Paper - OBFHELPER + public boolean aG() { + return this.isInWater() || this.isInRain() || this.k(); + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index dbfcdc3cc7c1dccf785f5e13634e84c5af088985..28aa0a9361e8a32763d7fe1af060f0016e8c1e50 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -98,6 +98,7 @@ public abstract class EntityInsentient extends EntityLiving { + private final EntityAIBodyControl c; + protected NavigationAbstract navigation; + public PathfinderGoalSelector goalSelector; ++ @Nullable public PathfinderGoalFloat goalFloat; // Paper + public PathfinderGoalSelector targetSelector; + private EntityLiving goalTarget; + private final EntitySenses bo; +@@ -784,7 +785,17 @@ public abstract class EntityInsentient extends EntityLiving { + @Override + protected final void doTick() { + ++this.ticksFarFromPlayer; +- if (!this.aware) return; // CraftBukkit ++ if (!this.aware) { // Paper start - Allow nerfed mobs to jump, float and take water damage ++ if (goalFloat != null) { ++ if (goalFloat.validConditions()) goalFloat.update(); ++ this.getControllerJump().jumpIfSet(); ++ } ++ if ((this instanceof EntityBlaze || this instanceof EntityEnderman) && isInWaterOrRainOrBubble()) { ++ damageEntity(DamageSource.DROWN, 1.0F); ++ } ++ return; ++ } ++ // Paper end + this.world.getMethodProfiler().enter("sensing"); + this.bo.a(); + this.world.getMethodProfiler().exit(); +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java +index 9767ac416fcd60a8a57b648dcb3f1e427bacd54d..1a9b3e0e0c090683e332dfa53708f8a62c8f14e0 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java +@@ -15,6 +15,7 @@ public class ControllerJump { + this.a = true; + } + ++ public final void jumpIfSet() { this.b(); } // Paper - OBFHELPER + public void b() { + this.b.setJumping(this.a); + this.a = false; +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java +index 8dfa1a6ade7f51e5d68b290f5376d999bb4c60ab..a6c8763139ed18fe73b2d6f6ec511e59666dc843 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java +@@ -11,15 +11,18 @@ public class PathfinderGoalFloat extends PathfinderGoal { + + public PathfinderGoalFloat(EntityInsentient entityinsentient) { + this.a = entityinsentient; ++ if (entityinsentient.getWorld().paperConfig.nerfedMobsShouldJump) entityinsentient.goalFloat = this; // Paper + this.a(EnumSet.of(PathfinderGoal.Type.JUMP)); + entityinsentient.getNavigation().d(true); + } + ++ public final boolean validConditions() { return this.a(); } // Paper - OBFHELPER + @Override + public boolean a() { + return this.a.isInWater() && this.a.b((Tag) TagsFluid.WATER) > this.a.cx() || this.a.aQ(); + } + ++ public void update() { this.e(); } // Paper - OBFHELPER + @Override + public void e() { + if (this.a.getRandom().nextFloat() < 0.8F) { diff --git a/patches/server-unmapped/0015-Add-configurable-despawn-distances-for-living-entiti.patch b/patches/server-unmapped/0015-Add-configurable-despawn-distances-for-living-entiti.patch new file mode 100644 index 0000000000..0c901ddac3 --- /dev/null +++ b/patches/server-unmapped/0015-Add-configurable-despawn-distances-for-living-entiti.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Suddenly +Date: Tue, 1 Mar 2016 13:51:54 -0600 +Subject: [PATCH] Add configurable despawn distances for living entities + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index b41e7922dd96c3358eb849ab39982a75736e3476..2f0d582baf0eb2bb477944d0cb1369db6ca33956 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -102,4 +102,20 @@ public class PaperWorldConfig { + private void nerfedMobsShouldJump() { + nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); + } ++ ++ public int softDespawnDistance; ++ public int hardDespawnDistance; ++ private void despawnDistances() { ++ softDespawnDistance = getInt("despawn-ranges.soft", 32); // 32^2 = 1024, Minecraft Default ++ hardDespawnDistance = getInt("despawn-ranges.hard", 128); // 128^2 = 16384, Minecraft Default ++ ++ if (softDespawnDistance > hardDespawnDistance) { ++ softDespawnDistance = hardDespawnDistance; ++ } ++ ++ log("Living Entity Despawn Ranges: Soft: " + softDespawnDistance + " Hard: " + hardDespawnDistance); ++ ++ softDespawnDistance = softDespawnDistance*softDespawnDistance; ++ hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index 28aa0a9361e8a32763d7fe1af060f0016e8c1e50..6e30fc88fa7a3ff00c9b4b78842c3a533649bd50 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -763,16 +763,16 @@ public abstract class EntityInsentient extends EntityLiving { + int i = this.getEntityType().e().f(); + int j = i * i; + +- if (d0 > (double) j) { // CraftBukkit - remove isTypeNotPersistent() check ++ if (d0 > (double) world.paperConfig.hardDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances + this.die(); + } + + int k = this.getEntityType().e().g(); + int l = k * k; + +- if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d0 > (double) l) { // CraftBukkit - remove isTypeNotPersistent() check ++ if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d0 > world.paperConfig.softDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances + this.die(); +- } else if (d0 < (double) l) { ++ } else if (d0 < world.paperConfig.softDespawnDistance) { // Paper - custom despawn distances + this.ticksFarFromPlayer = 0; + } + } diff --git a/patches/server-unmapped/0016-Allow-for-toggling-of-spawn-chunks.patch b/patches/server-unmapped/0016-Allow-for-toggling-of-spawn-chunks.patch new file mode 100644 index 0000000000..126f048726 --- /dev/null +++ b/patches/server-unmapped/0016-Allow-for-toggling-of-spawn-chunks.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 3 Mar 2016 03:53:43 -0600 +Subject: [PATCH] Allow for toggling of spawn chunks + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2f0d582baf0eb2bb477944d0cb1369db6ca33956..89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -118,4 +118,10 @@ public class PaperWorldConfig { + softDespawnDistance = softDespawnDistance*softDespawnDistance; + hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; + } ++ ++ public boolean keepSpawnInMemory; ++ private void keepSpawnInMemory() { ++ keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); ++ log("Keep spawn chunk loaded: " + keepSpawnInMemory); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 1b03c69fa7ffeca4083470a179e18be828b0a957..62735e7908f86e31f7a89ce2071ddebe176c0385 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -217,6 +217,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + }); + // CraftBukkit end + timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings ++ this.keepSpawnInMemory = this.paperConfig.keepSpawnInMemory; // Paper + this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + } diff --git a/patches/server-unmapped/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch b/patches/server-unmapped/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch new file mode 100644 index 0000000000..ec9ba5059c --- /dev/null +++ b/patches/server-unmapped/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Tue, 1 Mar 2016 14:14:15 -0600 +Subject: [PATCH] Drop falling block and tnt entities at the specified height + +* Dec 2, 2020 Added tnt nerf for tnt minecarts - Machine_Maker + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75..d16ae924bcbe31c964f7fb448757c748e5c4418c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -124,4 +124,14 @@ public class PaperWorldConfig { + keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); + log("Keep spawn chunk loaded: " + keepSpawnInMemory); + } ++ ++ public int fallingBlockHeightNerf; ++ public int entityTNTHeightNerf; ++ private void heightNerfs() { ++ fallingBlockHeightNerf = getInt("falling-block-height-nerf", 0); ++ entityTNTHeightNerf = getInt("tnt-entity-height-nerf", 0); ++ ++ if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); ++ if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index f823763a2f7f40d0be8d058a1bd61386bcd951e6..20e4ff812960a54872f2fea8fe6baf7bb1ef077d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1850,6 +1850,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return this.a(itemstack, 0.0F); + } + ++ @Nullable public final EntityItem dropItem(ItemStack itemstack, float offset) { return this.a(itemstack, offset); } // Paper - OBFHELPER + @Nullable + public EntityItem a(ItemStack itemstack, float f) { + if (itemstack.isEmpty()) { +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java +index b3dea8d65c3d1e27e59be142ec9e2ebb4164aed0..901522f24b8bc58861e46eda400dbab92bb6401d 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java +@@ -124,6 +124,17 @@ public class EntityFallingBlock extends Entity { + } + + this.move(EnumMoveType.SELF, this.getMot()); ++ ++ // Paper start - Configurable EntityFallingBlock height nerf ++ if (this.world.paperConfig.fallingBlockHeightNerf != 0 && this.locY() > this.world.paperConfig.fallingBlockHeightNerf) { ++ if (this.dropItem && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) { ++ this.a(block); ++ } ++ ++ this.die(); ++ return; ++ } ++ // Paper end + if (!this.world.isClientSide) { + blockposition = this.getChunkCoordinates(); + boolean flag = this.block.getBlock() instanceof BlockConcretePowder; +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java +index c2e7161dc103c971908ff217eaf972e9f175d044..4f4b2b8d58223fa22d6a7af5c94cfb36399b9641 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java +@@ -70,6 +70,12 @@ public class EntityTNTPrimed extends Entity { + } + + this.move(EnumMoveType.SELF, this.getMot()); ++ // Paper start - Configurable TNT entity height nerf ++ if (this.world.paperConfig.entityTNTHeightNerf != 0 && this.locY() > this.world.paperConfig.entityTNTHeightNerf) { ++ this.die(); ++ return; ++ } ++ // Paper end + this.setMot(this.getMot().a(0.98D)); + if (this.onGround) { + this.setMot(this.getMot().d(0.7D, -0.5D, 0.7D)); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java +index ee31704ffb88ab68702657554d386e8ebfa05d03..4bec5c1d504b9456dafe1b76bdbb523d0a324abe 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java +@@ -47,6 +47,12 @@ public class EntityMinecartTNT extends EntityMinecartAbstract { + public void tick() { + super.tick(); + if (this.b > 0) { ++ // Paper start - Configurable TNT entity height nerf ++ if (this.world.paperConfig.entityTNTHeightNerf != 0 && this.locY() > this.world.paperConfig.entityTNTHeightNerf) { ++ this.die(); ++ return; ++ } ++ // Paper end + --this.b; + this.world.addParticle(Particles.SMOKE, this.locX(), this.locY() + 0.5D, this.locZ(), 0.0D, 0.0D, 0.0D); + } else if (this.b == 0) { diff --git a/patches/server-unmapped/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/patches/server-unmapped/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch new file mode 100644 index 0000000000..6ff3ad51f7 --- /dev/null +++ b/patches/server-unmapped/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 14:32:43 -0600 +Subject: [PATCH] Show 'Paper' in client crashes, server lists, and Mojang + stats + + +diff --git a/src/main/java/net/minecraft/server/EULA.java b/src/main/java/net/minecraft/server/EULA.java +index a5171d28b960b12c2743ea68a36d747bc967697d..a0f53c9eff04a40780b3ba568dbfc5bbe9bd8504 100644 +--- a/src/main/java/net/minecraft/server/EULA.java ++++ b/src/main/java/net/minecraft/server/EULA.java +@@ -72,7 +72,7 @@ public class EULA { + Properties properties = new Properties(); + + properties.setProperty("eula", "false"); +- properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula)."); ++ properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\nYou also agree that tacos are tasty, and the best food in the world."); // Paper - fix lag; + } catch (Throwable throwable1) { + throwable = throwable1; + throw throwable1; +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 85c96e3f70a3ffecb6195a1d83053412eb180d78..c21790b4de698aa6f7fc4dadab64d791cd0562b6 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1342,7 +1342,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant // CraftBukkit - cb > vanilla! ++ return "Paper"; //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! + } + + public CrashReport b(CrashReport crashreport) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 2ad09749f3005c3eff143d83580e25910341aa6b..462633df2af43959fddf5b7a8ec43063abf7b14b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -225,7 +225,7 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; + import net.md_5.bungee.api.chat.BaseComponent; // Spigot + + public final class CraftServer implements Server { +- private final String serverName = "CraftBukkit"; ++ private final String serverName = "Paper"; // Paper + private final String serverVersion; + private final String bukkitVersion = Versioning.getBukkitVersion(); + private final Logger logger = Logger.getLogger("Minecraft"); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index ce9f10f890a5866ab6208c7253b15b09fe323a81..e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -206,12 +206,25 @@ public class Main { + deadline.add(Calendar.DAY_OF_YEAR, -28); + 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 ***"); ++ System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper + System.err.println("*** Server will start in 20 seconds ***"); + Thread.sleep(TimeUnit.SECONDS.toMillis(20)); + } + } + ++ // Paper start - Log Java and OS versioning to help with debugging plugin issues ++ java.lang.management.RuntimeMXBean runtimeMX = java.lang.management.ManagementFactory.getRuntimeMXBean(); ++ java.lang.management.OperatingSystemMXBean osMX = java.lang.management.ManagementFactory.getOperatingSystemMXBean(); ++ if (runtimeMX != null && osMX != null) { ++ String javaInfo = "Java " + runtimeMX.getSpecVersion() + " (" + runtimeMX.getVmName() + " " + runtimeMX.getVmVersion() + ")"; ++ String osInfo = "Host: " + osMX.getName() + " " + osMX.getVersion() + " (" + osMX.getArch() + ")"; ++ ++ System.out.println("System Info: " + javaInfo + " " + osInfo); ++ } else { ++ System.out.println("Unable to read system info"); ++ } ++ // Paper end ++ + System.out.println("Loading libraries, please wait..."); + net.minecraft.server.Main.main(options); + } catch (Throwable t) { +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index b4eeeb0d001e692180874bd26385a0e786a8b752..1b3a14784cac8e855633fae6172ad5479ebe9877 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -19,7 +19,7 @@ public class WatchdogThread extends Thread + + private WatchdogThread(long timeoutTime, boolean restart) + { +- super( "Spigot Watchdog Thread" ); ++ super( "Paper Watchdog Thread" ); + this.timeoutTime = timeoutTime; + this.restart = restart; + } +@@ -65,14 +65,14 @@ public class WatchdogThread extends Thread + { + Logger log = Bukkit.getServer().getLogger(); + log.log( Level.SEVERE, "------------------------------" ); +- log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Spigot bug." ); ++ log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper + log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); + log.log( Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring" ); + log.log( Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once" ); + log.log( Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes" ); +- log.log( Level.SEVERE, "If you are unsure or still think this is a Spigot bug, please report to https://www.spigotmc.org/" ); ++ log.log( Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues" ); + log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); +- log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() ); ++ log.log( Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion() ); + // + if ( net.minecraft.world.level.World.lastPhysicsProblem != null ) + { +@@ -82,7 +82,7 @@ public class WatchdogThread extends Thread + } + // + log.log( Level.SEVERE, "------------------------------" ); +- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" ); ++ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // diff --git a/patches/server-unmapped/0019-Implement-Paper-VersionChecker.patch b/patches/server-unmapped/0019-Implement-Paper-VersionChecker.patch new file mode 100644 index 0000000000..34f3da9b88 --- /dev/null +++ b/patches/server-unmapped/0019-Implement-Paper-VersionChecker.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 27 May 2019 03:40:05 -0500 +Subject: [PATCH] Implement Paper VersionChecker + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1a1b50e475b9ede544b2f6d0d36632b24b68898c +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +@@ -0,0 +1,122 @@ ++package com.destroystokyo.paper; ++ ++import com.destroystokyo.paper.util.VersionFetcher; ++import com.google.common.base.Charsets; ++import com.google.common.io.Resources; ++import com.google.gson.*; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.format.NamedTextColor; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++import java.io.*; ++import java.net.HttpURLConnection; ++import java.net.URL; ++import java.util.stream.StreamSupport; ++ ++public class PaperVersionFetcher implements VersionFetcher { ++ private static final java.util.regex.Pattern VER_PATTERN = java.util.regex.Pattern.compile("^([0-9\\.]*)\\-.*R"); // R is an anchor, will always give '-R' at end ++ private static final String GITHUB_BRANCH_NAME = "master"; ++ private static @Nullable String mcVer; ++ ++ @Override ++ public long getCacheTime() { ++ return 720000; ++ } ++ ++ @Nonnull ++ @Override ++ public Component getVersionMessage(@Nonnull String serverVersion) { ++ String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); ++ return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); ++ } ++ ++ private static @Nullable String getMinecraftVersion() { ++ if (mcVer == null) { ++ java.util.regex.Matcher matcher = VER_PATTERN.matcher(org.bukkit.Bukkit.getBukkitVersion()); ++ if (matcher.find()) { ++ String result = matcher.group(); ++ mcVer = result.substring(0, result.length() - 2); // strip 'R' anchor and trailing '-' ++ } else { ++ org.bukkit.Bukkit.getLogger().warning("Unable to match version to pattern! Report to PaperMC!"); ++ org.bukkit.Bukkit.getLogger().warning("Pattern: " + VER_PATTERN.toString()); ++ org.bukkit.Bukkit.getLogger().warning("Version: " + org.bukkit.Bukkit.getBukkitVersion()); ++ } ++ } ++ ++ return mcVer; ++ } ++ ++ private static Component getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) { ++ int distance; ++ try { ++ int jenkinsBuild = Integer.parseInt(versionInfo); ++ distance = fetchDistanceFromSiteApi(jenkinsBuild, getMinecraftVersion()); ++ } catch (NumberFormatException ignored) { ++ versionInfo = versionInfo.replace("\"", ""); ++ distance = fetchDistanceFromGitHub(repo, branch, versionInfo); ++ } ++ ++ switch (distance) { ++ case -1: ++ return Component.text("Error obtaining version information", NamedTextColor.YELLOW); ++ case 0: ++ return Component.text("You are running the latest version", NamedTextColor.GREEN); ++ case -2: ++ return Component.text("Unknown version", NamedTextColor.YELLOW); ++ default: ++ return Component.text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW); ++ } ++ } ++ ++ private static int fetchDistanceFromSiteApi(int jenkinsBuild, @Nullable String siteApiVersion) { ++ if (siteApiVersion == null) { return -1; } ++ try { ++ try (BufferedReader reader = Resources.asCharSource( ++ new URL("https://papermc.io/api/v2/projects/paper/versions/" + siteApiVersion), ++ Charsets.UTF_8 ++ ).openBufferedStream()) { ++ JsonObject json = new Gson().fromJson(reader, JsonObject.class); ++ JsonArray builds = json.getAsJsonArray("builds"); ++ int latest = StreamSupport.stream(builds.spliterator(), false) ++ .mapToInt(e -> e.getAsInt()) ++ .max() ++ .getAsInt(); ++ return latest - jenkinsBuild; ++ } catch (JsonSyntaxException ex) { ++ ex.printStackTrace(); ++ return -1; ++ } ++ } catch (IOException e) { ++ e.printStackTrace(); ++ return -1; ++ } ++ } ++ ++ // Contributed by Techcable in GH-65 ++ private static int fetchDistanceFromGitHub(@Nonnull String repo, @Nonnull String branch, @Nonnull String hash) { ++ try { ++ HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + repo + "/compare/" + branch + "..." + hash).openConnection(); ++ connection.connect(); ++ if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return -2; // Unknown commit ++ try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) { ++ JsonObject obj = new Gson().fromJson(reader, JsonObject.class); ++ String status = obj.get("status").getAsString(); ++ switch (status) { ++ case "identical": ++ return 0; ++ case "behind": ++ return obj.get("behind_by").getAsInt(); ++ default: ++ return -1; ++ } ++ } catch (JsonSyntaxException | NumberFormatException e) { ++ e.printStackTrace(); ++ return -1; ++ } ++ } catch (IOException e) { ++ e.printStackTrace(); ++ return -1; ++ } ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 8f737f63f280c00c1276bd1dc3ecf60448732ca8..8aa9e7796ea39c09a965750d06c3d358250f33b8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -370,6 +370,11 @@ public final class CraftMagicNumbers implements UnsafeValues { + public String getTimingsServerName() { + return com.destroystokyo.paper.PaperConfig.timingsServerName; + } ++ ++ @Override ++ public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { ++ return new com.destroystokyo.paper.PaperVersionFetcher(); ++ } + // Paper end + + /** diff --git a/patches/server-unmapped/0020-Add-version-history-to-version-command.patch b/patches/server-unmapped/0020-Add-version-history-to-version-command.patch new file mode 100644 index 0000000000..a115cf4943 --- /dev/null +++ b/patches/server-unmapped/0020-Add-version-history-to-version-command.patch @@ -0,0 +1,215 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Thu, 1 Mar 2018 19:37:52 -0600 +Subject: [PATCH] Add version history to version command + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +index 1a1b50e475b9ede544b2f6d0d36632b24b68898c..580bae0d414d371a07a6bfeefc41fdd989dc0083 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java ++++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +@@ -5,7 +5,9 @@ import com.google.common.base.Charsets; + import com.google.common.io.Resources; + import com.google.gson.*; + import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.TextComponent; + import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.format.TextDecoration; + + import javax.annotation.Nonnull; + import javax.annotation.Nullable; +@@ -28,7 +30,10 @@ public class PaperVersionFetcher implements VersionFetcher { + @Override + public Component getVersionMessage(@Nonnull String serverVersion) { + String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); +- return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); ++ final Component updateMessage = getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); ++ final Component history = getHistory(); ++ ++ return history != null ? TextComponent.ofChildren(updateMessage, Component.newline(), history) : updateMessage; + } + + private static @Nullable String getMinecraftVersion() { +@@ -119,4 +124,19 @@ public class PaperVersionFetcher implements VersionFetcher { + return -1; + } + } ++ ++ @Nullable ++ private Component getHistory() { ++ final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); ++ if (data == null) { ++ return null; ++ } ++ ++ final String oldVersion = data.getOldVersion(); ++ if (oldVersion == null) { ++ return null; ++ } ++ ++ return Component.text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC); ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..aac3f66cb23d260729c2a48d8710a9de2346aa22 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java +@@ -0,0 +1,145 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.MoreObjects; ++import com.google.gson.Gson; ++import com.google.gson.JsonSyntaxException; ++import java.io.BufferedReader; ++import java.io.BufferedWriter; ++import java.io.IOException; ++import java.nio.charset.StandardCharsets; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.nio.file.Paths; ++import java.nio.file.StandardOpenOption; ++import java.util.Objects; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++import org.bukkit.Bukkit; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++ ++public enum VersionHistoryManager { ++ INSTANCE; ++ ++ private final Gson gson = new Gson(); ++ ++ private final Logger logger = Bukkit.getLogger(); ++ ++ private VersionData currentData = null; ++ ++ VersionHistoryManager() { ++ final Path path = Paths.get("version_history.json"); ++ ++ if (Files.exists(path)) { ++ // Basic file santiy checks ++ if (!Files.isRegularFile(path)) { ++ if (Files.isDirectory(path)) { ++ logger.severe(path + " is a directory, cannot be used for version history"); ++ } else { ++ logger.severe(path + " is not a regular file, cannot be used for version history"); ++ } ++ // We can't continue ++ return; ++ } ++ ++ try (final BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { ++ currentData = gson.fromJson(reader, VersionData.class); ++ } catch (final IOException e) { ++ logger.log(Level.SEVERE, "Failed to read version history file '" + path + "'", e); ++ return; ++ } catch (final JsonSyntaxException e) { ++ logger.log(Level.SEVERE, "Invalid json syntax for file '" + path + "'", e); ++ return; ++ } ++ ++ final String version = Bukkit.getVersion(); ++ if (version == null) { ++ logger.severe("Failed to retrieve current version"); ++ return; ++ } ++ ++ if (!version.equals(currentData.getCurrentVersion())) { ++ // The version appears to have changed ++ currentData.setOldVersion(currentData.getCurrentVersion()); ++ currentData.setCurrentVersion(version); ++ writeFile(path); ++ } ++ } else { ++ // File doesn't exist, start fresh ++ currentData = new VersionData(); ++ // oldVersion is null ++ currentData.setCurrentVersion(Bukkit.getVersion()); ++ writeFile(path); ++ } ++ } ++ ++ private void writeFile(@Nonnull final Path path) { ++ try (final BufferedWriter writer = Files.newBufferedWriter( ++ path, ++ StandardCharsets.UTF_8, ++ StandardOpenOption.WRITE, ++ StandardOpenOption.CREATE, ++ StandardOpenOption.TRUNCATE_EXISTING ++ )) { ++ gson.toJson(currentData, writer); ++ } catch (final IOException e) { ++ logger.log(Level.SEVERE, "Failed to write to version history file", e); ++ } ++ } ++ ++ @Nullable ++ public VersionData getVersionData() { ++ return currentData; ++ } ++ ++ public static class VersionData { ++ private String oldVersion; ++ ++ private String currentVersion; ++ ++ @Nullable ++ public String getOldVersion() { ++ return oldVersion; ++ } ++ ++ public void setOldVersion(@Nullable String oldVersion) { ++ this.oldVersion = oldVersion; ++ } ++ ++ @Nullable ++ public String getCurrentVersion() { ++ return currentVersion; ++ } ++ ++ public void setCurrentVersion(@Nullable String currentVersion) { ++ this.currentVersion = currentVersion; ++ } ++ ++ @Override ++ public String toString() { ++ return MoreObjects.toStringHelper(this) ++ .add("oldVersion", oldVersion) ++ .add("currentVersion", currentVersion) ++ .toString(); ++ } ++ ++ @Override ++ public boolean equals(@Nullable Object o) { ++ if (this == o) { ++ return true; ++ } ++ if (o == null || getClass() != o.getClass()) { ++ return false; ++ } ++ final VersionData versionData = (VersionData) o; ++ return Objects.equals(oldVersion, versionData.oldVersion) && ++ Objects.equals(currentVersion, versionData.currentVersion); ++ } ++ ++ @Override ++ public int hashCode() { ++ return Objects.hash(oldVersion, currentVersion); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 59942eb6bb6e8e1e9a988bce0d09757e575018b9..faf4d00bf288359db806913c4d2964324e8706b7 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -196,6 +196,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + return false; + } + com.destroystokyo.paper.PaperConfig.registerCommands(); ++ com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now + // Paper end + + this.setPVP(dedicatedserverproperties.pvp); diff --git a/patches/server-unmapped/0021-Player-affects-spawning-API.patch b/patches/server-unmapped/0021-Player-affects-spawning-API.patch new file mode 100644 index 0000000000..0ccd83d4e5 --- /dev/null +++ b/patches/server-unmapped/0021-Player-affects-spawning-API.patch @@ -0,0 +1,157 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Tue, 1 Mar 2016 14:47:52 -0600 +Subject: [PATCH] Player affects spawning API + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 20e4ff812960a54872f2fea8fe6baf7bb1ef077d..cae9da158f54438d2a397665c7ce964f6f755469 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1354,6 +1354,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return MathHelper.c(f * f + f1 * f1 + f2 * f2); + } + ++ public double getDistanceSquared(double x, double y, double z) { return h(x, y, z); } // Paper - OBFHELPER + public double h(double d0, double d1, double d2) { + double d3 = this.locX() - d0; + double d4 = this.locY() - d1; +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index 6e30fc88fa7a3ff00c9b4b78842c3a533649bd50..31bb5df7bc63c993230bf595bd9b66bfaadb4d50 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -756,7 +756,7 @@ public abstract class EntityInsentient extends EntityLiving { + if (this.world.getDifficulty() == EnumDifficulty.PEACEFUL && this.L()) { + this.die(); + } else if (!this.isPersistent() && !this.isSpecialPersistence()) { +- EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D); ++ EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D, IEntitySelector.affectsSpawning); // Paper + + if (entityhuman != null) { + double d0 = entityhuman.h((Entity) this); // CraftBukkit - decompile error +diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +index 6e78192a5898df017d96acba845a288011d24e35..dfcfdb31ca9531913d705aaaf85fb67399cfdc8c 100644 +--- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +@@ -29,6 +29,12 @@ public final class IEntitySelector { + return !entity.isSpectator(); + }; + ++ // Paper start ++ public static final Predicate affectsSpawning = (entity) -> { ++ return !entity.isSpectator() && entity.isAlive() && (entity instanceof EntityPlayer) && ((EntityPlayer) entity).affectsSpawning; ++ }; ++ // Paper end ++ + public static Predicate a(double d0, double d1, double d2, double d3) { + double d4 = d3 * d3; + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java +index 0b3b430766fba602e74727f78173567ca10fabc6..e1fcb1be102822e87eaf7757fbd64a516b2f58ac 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java +@@ -122,7 +122,7 @@ public class EntitySilverfish extends EntityMonster { + if (c(entitytypes, generatoraccess, enummobspawn, blockposition, random)) { + EntityHuman entityhuman = generatoraccess.a((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, 5.0D, true); + +- return entityhuman == null; ++ return !(entityhuman != null && !entityhuman.affectsSpawning) && entityhuman == null; // Paper - Affects Spawning API + } else { + return false; + } +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 1017ee73b8617ce2b6734469fa49aaff7563c2b1..f42e16589476c1bd10b13214dda5ac7bb3e52131 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -164,6 +164,9 @@ public abstract class EntityHuman extends EntityLiving { + private final ItemCooldown bM; + @Nullable + public EntityFishingHook hookedFish; ++ // Paper start ++ public boolean affectsSpawning = true; ++ // Paper end + + // CraftBukkit start + public boolean fauxSleeping; +diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java +index 4ece69851e7b05016f52c291ce911eb791cf3a23..6d5d4c3df65995b9a13b66d070ba08d553cc98a2 100644 +--- a/src/main/java/net/minecraft/world/level/IEntityAccess.java ++++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java +@@ -92,8 +92,9 @@ public interface IEntityAccess { + } + } + +- @Nullable +- default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { ++ default EntityHuman findNearbyPlayer(Entity entity, double d0, @Nullable Predicate predicate) { return this.findNearbyPlayer(entity.locX(), entity.locY(), entity.locZ(), d0, predicate); } // Paper ++ @Nullable default EntityHuman findNearbyPlayer(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { return a(d0, d1, d2, d3, predicate); } // Paper - OBFHELPER ++ @Nullable default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { // Paper + double d4 = -1.0D; + EntityHuman entityhuman = null; + Iterator iterator = this.getPlayers().iterator(); +@@ -126,6 +127,27 @@ public interface IEntityAccess { + return this.a(d0, d1, d2, d3, predicate); + } + ++ // Paper end ++ default boolean isAffectsSpawningPlayerNearby(double d0, double d1, double d2, double d3) { ++ Iterator iterator = this.getPlayers().iterator(); ++ double d4; ++ do { ++ EntityHuman entityhuman; ++ do { ++ if (!iterator.hasNext()) { ++ return false; ++ } ++ ++ entityhuman = (EntityHuman) iterator.next(); ++ } while (!IEntitySelector.affectsSpawning.test(entityhuman)); ++ ++ d4 = entityhuman.getDistanceSquared(d0, d1, d2); ++ } while (d3 >= 0.0D && d4 >= d3 * d3); ++ ++ return true; ++ } ++ // Paper end ++ + default boolean isPlayerNearby(double d0, double d1, double d2, double d3) { + Iterator iterator = this.getPlayers().iterator(); + +diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +index 33cba4e475edc0573b901f70c61d3659fd63ad62..8d8b03074df1635946f81bec0feae18d2f3e20aa 100644 +--- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java ++++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +@@ -66,7 +66,7 @@ public abstract class MobSpawnerAbstract { + private boolean h() { + BlockPosition blockposition = this.b(); + +- return this.a().isPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); ++ return this.a().isAffectsSpawningPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper + } + + public void c() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 6ab14bccb1fcd108931bf7ec331e60f652e0b42d..cc471418b37a745ecea1af964e81bc0362cf7d94 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1770,8 +1770,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + @Override + public String getLocale() { + return getHandle().locale; ++ ++ } ++ ++ // Paper start ++ public void setAffectsSpawning(boolean affects) { ++ this.getHandle().affectsSpawning = affects; + } + ++ @Override ++ public boolean getAffectsSpawning() { ++ return this.getHandle().affectsSpawning; ++ } ++ // Paper end ++ + @Override + public void updateCommands() { + if (getHandle().playerConnection == null) return; diff --git a/patches/server-unmapped/0022-Remove-invalid-mob-spawner-tile-entities.patch b/patches/server-unmapped/0022-Remove-invalid-mob-spawner-tile-entities.patch new file mode 100644 index 0000000000..2aeae2d5b4 --- /dev/null +++ b/patches/server-unmapped/0022-Remove-invalid-mob-spawner-tile-entities.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Tue, 1 Mar 2016 15:08:03 -0600 +Subject: [PATCH] Remove invalid mob spawner tile entities + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index ac576d268b23148089d404cb22d8c2f9d1a79d6e..a2d80c2c8e4f080f60746548f75631c5946ba8e2 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -40,9 +40,11 @@ import net.minecraft.world.level.TickListChunk; + import net.minecraft.world.level.TickListEmpty; + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.BlockMobSpawner; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.ITileEntity; + import net.minecraft.world.level.block.entity.TileEntity; ++import net.minecraft.world.level.block.entity.TileEntityMobSpawner; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.levelgen.ChunkProviderDebug; + import net.minecraft.world.level.levelgen.HeightMap; +@@ -648,6 +650,10 @@ public class Chunk implements IChunkAccess { + } + + // CraftBukkit start ++ // Paper start - Remove invalid mob spawner tile entities ++ } else if (tileentity instanceof TileEntityMobSpawner && !(getBlockData(blockposition.getX(), blockposition.getY(), blockposition.getZ()).getBlock() instanceof BlockMobSpawner)) { ++ this.tileEntities.remove(blockposition); ++ // Paper end + } else { + System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ() + + " (" + getType(blockposition) + ") where there was no entity tile!"); diff --git a/patches/server-unmapped/0023-Optimize-TileEntity-Ticking.patch b/patches/server-unmapped/0023-Optimize-TileEntity-Ticking.patch new file mode 100644 index 0000000000..a556c9c8da --- /dev/null +++ b/patches/server-unmapped/0023-Optimize-TileEntity-Ticking.patch @@ -0,0 +1,248 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 8 Mar 2015 22:55:25 -0600 +Subject: [PATCH] Optimize TileEntity Ticking + + +diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java +index d4ebcf8f66197299256bd6b65710a1488c90ea41..c9164dfdb27ddf3709129c8aec54903a1df121ff 100644 +--- a/src/main/java/co/aikar/timings/TimingsExport.java ++++ b/src/main/java/co/aikar/timings/TimingsExport.java +@@ -109,7 +109,7 @@ public class TimingsExport extends Thread { + pair("end", System.currentTimeMillis() / 1000), + pair("online-mode", Bukkit.getServer().getOnlineMode()), + pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), +- pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().d(), pack -> { ++ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().e(), pack -> { + // Don't feel like obf helper'ing these, non fatal if its temp missed. + return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); + })) +@@ -148,8 +148,8 @@ public class TimingsExport extends Thread { + ); + + parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getWorlds(), world -> { +- if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; +- return pair(world.getWorldData().getName(), createObject( ++ if (world.getWorld().getName().equals("worldeditregentempworld")) return null; ++ return pair(world.getWorld().getName(), createObject( + pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { + return pair(rule, world.getWorld().getGameRuleValue(rule)); + })), +diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java +index 60e7dc1910ae9214d84d65b011cfec278b6b32ae..b229faad99120c67b089f7680d800fbe594fe7da 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockChest.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java +@@ -54,8 +54,8 @@ import net.minecraft.world.phys.shapes.VoxelShapeCollision; + public class BlockChest extends BlockChestAbstract implements IBlockWaterlogged { + + public static final BlockStateDirection FACING = BlockFacingHorizontal.FACING; +- public static final BlockStateEnum c = BlockProperties.aF; +- public static final BlockStateBoolean d = BlockProperties.C; ++ public static final BlockStateEnum c = BlockProperties.aF; public static final BlockStateEnum CHEST_TYPE_PROPERTY = c; // Paper - OBFHELPER ++ public static final BlockStateBoolean d = BlockProperties.C; public static final BlockStateBoolean waterlogged() { return d; } // Paper OBFHELPER + protected static final VoxelShape e = Block.a(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D); + protected static final VoxelShape f = Block.a(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D); + protected static final VoxelShape g = Block.a(0.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java +index eed95b370d1d624ffc6b7a35357b7028ec58c584..51167d776c710decb0107bebcb35bdf43103772b 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java +@@ -8,6 +8,7 @@ import net.minecraft.core.NonNullList; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.IChatBaseComponent; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; +@@ -33,7 +34,7 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.entity.HumanEntity; + // CraftBukkit end + +-public class TileEntityChest extends TileEntityLootable implements ITickable { ++public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITickable + + private NonNullList items; + protected float a; +@@ -111,14 +112,20 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { + return nbttagcompound; + } + +- @Override + public void tick() { + int i = this.position.getX(); + int j = this.position.getY(); + int k = this.position.getZ(); + + ++this.j; +- this.viewingCount = a(this.world, this, this.j, i, j, k, this.viewingCount); ++ } ++ ++ public void doOpenLogic() { ++ int i = this.position.getX(); ++ int j = this.position.getY(); ++ int k = this.position.getZ(); ++ ++ //this.viewingCount = a(this.world, this, this.j, i, j, k, this.viewingCount); // Paper - check is faulty given our logic is called before active container set + this.b = this.a; + float f = 0.1F; + +@@ -132,8 +139,11 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { + if (this.viewingCount > 0 && this.a == 0.0F) { + this.playOpenSound(SoundEffects.BLOCK_CHEST_OPEN); + } ++ } + +- if (this.viewingCount == 0 && this.a > 0.0F || this.viewingCount > 0 && this.a < 1.0F) { ++ public void doCloseLogic() { ++ if (this.viewingCount == 0 /* && this.a > 0.0F || this.viewingCount > 0 && this.a < 1.0F */) { // Paper - disable all but player count check ++ /* // Paper - disable animation stuff + float f1 = this.a; + + if (this.viewingCount > 0) { +@@ -149,8 +159,11 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { + float f2 = 0.5F; + + if (this.a < 0.5F && f1 >= 0.5F) { ++ */ ++ MCUtil.scheduleTask(10, () -> { + this.playOpenSound(SoundEffects.BLOCK_CHEST_CLOSE); +- } ++ }, "Chest Sounds"); ++ //} // Paper end + + if (this.a < 0.0F) { + this.a = 0.0F; +@@ -189,6 +202,7 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { + } + + public void playOpenSound(SoundEffect soundeffect) { ++ if (!this.getBlock().contains(BlockChest.CHEST_TYPE_PROPERTY)) { return; } // Paper - this can be delayed, double check exists - Fixes GH-2074 + BlockPropertyChestType blockpropertychesttype = (BlockPropertyChestType) this.getBlock().get(BlockChest.c); + + if (blockpropertychesttype != BlockPropertyChestType.LEFT) { +@@ -227,6 +241,7 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { + + ++this.viewingCount; + if (this.world == null) return; // CraftBukkit ++ doOpenLogic(); // Paper + + // CraftBukkit start - Call redstone event + if (this.getBlock().getBlock() == Blocks.TRAPPED_CHEST) { +@@ -249,6 +264,7 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { + --this.viewingCount; + + // CraftBukkit start - Call redstone event ++ doCloseLogic(); // Paper + if (this.getBlock().getBlock() == Blocks.TRAPPED_CHEST) { + int newPower = Math.max(0, Math.min(15, this.viewingCount)); + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java +index 930f1bd091d9754f7ca5d9e36cdf49b2be03eb23..2bc4213c70be47ca8bbc24898cc92e43f4228821 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java +@@ -1,11 +1,12 @@ + package net.minecraft.world.level.block.entity; + ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.level.block.Blocks; + +-public class TileEntityEnderChest extends TileEntity implements ITickable { ++public class TileEntityEnderChest extends TileEntity { // Paper - Remove ITickable + + public float a; + public float b; +@@ -16,18 +17,28 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { + super(TileEntityTypes.ENDER_CHEST); + } + +- @Override + public void tick() { + if (++this.g % 20 * 4 == 0) { + this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); + } + + this.b = this.a; ++ /* // Paper + int i = this.position.getX(); + int j = this.position.getY(); + int k = this.position.getZ(); + float f = 0.1F; + double d0; ++ // Paper start ++ */ ++ } ++ ++ private void doOpenLogic() { ++ int i = this.position.getX(); ++ int j = this.position.getY(); ++ int k = this.position.getZ(); ++ double d0; ++ // Paper end + + if (this.c > 0 && this.a == 0.0F) { + double d1 = (double) i + 0.5D; +@@ -35,8 +46,17 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { + d0 = (double) k + 0.5D; + this.world.playSound((EntityHuman) null, d1, (double) j + 0.5D, d0, SoundEffects.BLOCK_ENDER_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); + } ++ // Paper start ++ } + +- if (this.c == 0 && this.a > 0.0F || this.c > 0 && this.a < 1.0F) { ++ private void doCloseLogic() { ++ int i = this.position.getX(); ++ int j = this.position.getY(); ++ int k = this.position.getZ(); ++ double d0; ++ ++ if (this.c == 0) { /* && this.a > 0.0F || this.c > 0 && this.a < 1.0F) { ++ // Paper end + float f1 = this.a; + + if (this.c > 0) { +@@ -52,11 +72,14 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { + float f2 = 0.5F; + + if (this.a < 0.5F && f1 >= 0.5F) { ++ // Paper start ++ */ + d0 = (double) i + 0.5D; + double d2 = (double) k + 0.5D; + ++ MCUtil.scheduleTask(10, () -> { + this.world.playSound((EntityHuman) null, d0, (double) j + 0.5D, d2, SoundEffects.BLOCK_ENDER_CHEST_CLOSE, SoundCategory.BLOCKS, 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); +- } ++ }, "Chest Sounds"); + + if (this.a < 0.0F) { + this.a = 0.0F; +@@ -84,11 +107,13 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { + public void d() { + ++this.c; + this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); ++ doOpenLogic(); // Paper + } + + public void f() { + --this.c; + this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); ++ doCloseLogic(); // Paper + } + + public boolean a(EntityHuman entityhuman) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java +index e4b59a85ee9b435b2e86d4c7d78b7224773f6967..ba046cffdd8331c7e0427f19fa54d0c7a99077d9 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java ++++ b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java +@@ -84,6 +84,7 @@ public abstract class IBlockDataHolder { + return Collections.unmodifiableCollection(this.b.keySet()); + } + ++ public > boolean contains(IBlockState iblockstate) { return this.b(iblockstate); } // Paper - OBFHELPER + public > boolean b(IBlockState iblockstate) { + return this.b.containsKey(iblockstate); + } diff --git a/patches/server-unmapped/0024-Further-improve-server-tick-loop.patch b/patches/server-unmapped/0024-Further-improve-server-tick-loop.patch new file mode 100644 index 0000000000..4ac7537099 --- /dev/null +++ b/patches/server-unmapped/0024-Further-improve-server-tick-loop.patch @@ -0,0 +1,208 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 1 Mar 2016 23:09:29 -0600 +Subject: [PATCH] Further improve server tick loop + +Improves how the catchup buffer is handled, allowing it to roll both ways +increasing the effeciency of the thread sleep so it only will sleep once. + +Also increases the buffer of the catchup to ensure server stays at 20 TPS unless extreme conditions + +Previous implementation did not calculate TPS correctly. +Switch to a realistic rolling average and factor in std deviation as an extra reporting variable + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index c21790b4de698aa6f7fc4dadab64d791cd0562b6..fb0d985b5c977a7c63701484678b75928d9ee382 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -253,7 +253,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; + public CommandDispatcher vanillaCommandDispatcher; +@@ -262,7 +262,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 5000L && this.nextTick - this.lastOverloadTime >= 30000L) { // CraftBukkit + long j = i / 50L; + + if (server.getWarnOnOverload()) // CraftBukkit +- MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); ++ MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); + this.nextTick += j * 50L; + this.lastOverloadTime = this.nextTick; + } + +- if ( tickCount++ % SAMPLE_INTERVAL == 0 ) ++ if ( ++MinecraftServer.currentTick % SAMPLE_INTERVAL == 0 ) + { +- double currentTps = 1E3 / ( curTime - tickSection ) * SAMPLE_INTERVAL; +- recentTps[0] = calcTps( recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min) +- recentTps[1] = calcTps( recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min) +- recentTps[2] = calcTps( recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min) ++ final long diff = curTime - tickSection; ++ java.math.BigDecimal currentTps = TPS_BASE.divide(new java.math.BigDecimal(diff), 30, java.math.RoundingMode.HALF_UP); ++ tps1.add(currentTps, diff); ++ tps5.add(currentTps, diff); ++ tps15.add(currentTps, diff); ++ // Backwards compat with bad plugins ++ recentTps[0] = tps1.getAverage(); ++ recentTps[1] = tps5.getAverage(); ++ recentTps[2] = tps15.getAverage(); ++ // Paper end + tickSection = curTime; + } + // Spigot end + +- MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit ++ //MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit // Paper - don't overwrite current tick time ++ lastTick = curTime; + this.nextTick += 50L; + GameProfilerTick gameprofilertick = GameProfilerTick.a("Server"); + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 462633df2af43959fddf5b7a8ec43063abf7b14b..b4b592faaa699b6e62f77ddf57b239c5e15948ff 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2122,6 +2122,17 @@ public final class CraftServer implements Server { + return CraftMagicNumbers.INSTANCE; + } + ++ // Paper - Add getTPS API - Further improve tick loop ++ @Override ++ public double[] getTPS() { ++ return new double[] { ++ net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(), ++ net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(), ++ net.minecraft.server.MinecraftServer.getServer().tps15.getAverage() ++ }; ++ } ++ // Paper end ++ + // Spigot start + private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() + { +diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java +index f5b6dec1cbe7501ce2ee9125920e810bc94670cc..e62890433ffbe0b4e48942fe6c38b599a19e58fd 100644 +--- a/src/main/java/org/spigotmc/TicksPerSecondCommand.java ++++ b/src/main/java/org/spigotmc/TicksPerSecondCommand.java +@@ -24,22 +24,30 @@ public class TicksPerSecondCommand extends Command + return true; + } + +- StringBuilder sb = new StringBuilder( ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " ); +- for ( double tps : MinecraftServer.getServer().recentTps ) +- { +- sb.append( format( tps ) ); +- sb.append( ", " ); ++ // Paper start - Further improve tick handling ++ double[] tps = org.bukkit.Bukkit.getTPS(); ++ String[] tpsAvg = new String[tps.length]; ++ ++ for ( int i = 0; i < tps.length; i++) { ++ tpsAvg[i] = format( tps[i] ); ++ } ++ sender.sendMessage(ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " + org.apache.commons.lang.StringUtils.join(tpsAvg, ", ")); ++ if (args.length > 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) { ++ sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); ++ if (!hasShownMemoryWarning) { ++ sender.sendMessage(ChatColor.RED + "Warning: " + ChatColor.GOLD + " Memory usage on modern garbage collectors is not a stable value and it is perfectly normal to see it reach max. Please do not pay it much attention."); ++ hasShownMemoryWarning = true; ++ } + } +- sender.sendMessage( sb.substring( 0, sb.length() - 2 ) ); +- sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " +- + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); ++ // Paper end + + return true; + } + +- private String format(double tps) ++ private boolean hasShownMemoryWarning; // Paper ++ private static String format(double tps) // Paper - Made static + { + return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString() +- + ( ( tps > 20.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); ++ + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise + } + } diff --git a/patches/server-unmapped/0025-Only-refresh-abilities-if-needed.patch b/patches/server-unmapped/0025-Only-refresh-abilities-if-needed.patch new file mode 100644 index 0000000000..ae353e8f8a --- /dev/null +++ b/patches/server-unmapped/0025-Only-refresh-abilities-if-needed.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 23:12:03 -0600 +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 cc471418b37a745ecea1af964e81bc0362cf7d94..fb792de46ff80a6bad77a47954861cddfd17f2d9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1439,12 +1439,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + @Override + public void setFlying(boolean value) { ++ boolean needsUpdate = getHandle().abilities.isFlying != value; // Paper - Only refresh abilities if needed + if (!getAllowFlight() && value) { + throw new IllegalArgumentException("Cannot make player fly if getAllowFlight() is false"); + } + + getHandle().abilities.isFlying = value; +- getHandle().updateAbilities(); ++ if (needsUpdate) getHandle().updateAbilities(); // Paper - Only refresh abilities if needed + } + + @Override diff --git a/patches/server-unmapped/0026-Entity-Origin-API.patch b/patches/server-unmapped/0026-Entity-Origin-API.patch new file mode 100644 index 0000000000..bf9cbb5345 --- /dev/null +++ b/patches/server-unmapped/0026-Entity-Origin-API.patch @@ -0,0 +1,140 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Tue, 1 Mar 2016 23:45:08 -0600 +Subject: [PATCH] Entity Origin API + + +diff --git a/src/main/java/net/minecraft/nbt/NBTTagList.java b/src/main/java/net/minecraft/nbt/NBTTagList.java +index 4f6f6f51f9807bafa88482c0fe776c8b163107d7..ce6572df63c4e7341708aee60330fb214a3fe416 100644 +--- a/src/main/java/net/minecraft/nbt/NBTTagList.java ++++ b/src/main/java/net/minecraft/nbt/NBTTagList.java +@@ -190,6 +190,7 @@ public class NBTTagList extends NBTList { + return new int[0]; + } + ++ public final double getDoubleAt(int i) { return this.h(i); } // Paper - OBFHELPER + public double h(int i) { + if (i >= 0 && i < this.list.size()) { + NBTBase nbtbase = (NBTBase) this.list.get(i); +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index cf38d517821659e25e786a805e229ef2d626d75f..26d461196b4a998b445f8c6e67fd7ec0606344f6 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1246,6 +1246,11 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.navigators.add(((EntityInsentient) entity).getNavigation()); + } + entity.valid = true; // CraftBukkit ++ // Paper start - Set origin location when the entity is being added to the world ++ if (entity.origin == null) { ++ entity.origin = entity.getBukkitEntity().getLocation(); ++ } ++ // Paper end + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index cae9da158f54438d2a397665c7ce964f6f755469..f6f0d551e22ff085935c1543bf84392de0368214 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -247,6 +247,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only + public boolean forceExplosionKnockback; // SPIGOT-949 + public boolean persistentInvisibility = false; ++ public org.bukkit.Location origin; // Paper + // Spigot start + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; +@@ -1625,6 +1626,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.bukkitEntity.storeBukkitValues(nbttagcompound); + } + // CraftBukkit end ++ // Paper start - Save the entity's origin location ++ if (this.origin != null) { ++ nbttagcompound.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); ++ nbttagcompound.set("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); ++ } ++ // Paper end + return nbttagcompound; + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.a(throwable, "Saving entity NBT"); +@@ -1747,6 +1754,17 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + // CraftBukkit end + ++ // Paper start - Restore the entity's origin location ++ NBTTagList originTag = nbttagcompound.getList("Paper.Origin", 6); ++ if (!originTag.isEmpty()) { ++ org.bukkit.World originWorld = world.getWorld(); ++ if (nbttagcompound.hasKey("Paper.OriginWorld")) { ++ originWorld = Bukkit.getWorld(nbttagcompound.getUUID("Paper.OriginWorld")); ++ } ++ origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); ++ } ++ // Paper end ++ + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.a(throwable, "Loading entity NBT"); + CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being loaded"); +@@ -1808,6 +1826,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + protected abstract void saveData(NBTTagCompound nbttagcompound); + ++ protected final NBTTagList createList(double... adouble) { return a(adouble); } // Paper - OBFHELPER + protected NBTTagList a(double... adouble) { + NBTTagList nbttaglist = new NBTTagList(); + double[] adouble1 = adouble; +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java +index 901522f24b8bc58861e46eda400dbab92bb6401d..3f10e41b18e09186635fd6f7c653b04db7b39d8e 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java +@@ -293,6 +293,14 @@ public class EntityFallingBlock extends Entity { + this.block = Blocks.SAND.getBlockData(); + } + ++ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility ++ if (nbttagcompound.hasKey("SourceLoc_x")) { ++ int srcX = nbttagcompound.getInt("SourceLoc_x"); ++ int srcY = nbttagcompound.getInt("SourceLoc_y"); ++ int srcZ = nbttagcompound.getInt("SourceLoc_z"); ++ origin = new org.bukkit.Location(world.getWorld(), srcX, srcY, srcZ); ++ } ++ // Paper end + } + + public void a(boolean flag) { +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java +index 4f4b2b8d58223fa22d6a7af5c94cfb36399b9641..535e7d7297d81026b8586d5049b72fa65519b464 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java +@@ -120,6 +120,14 @@ public class EntityTNTPrimed extends Entity { + @Override + protected void loadData(NBTTagCompound nbttagcompound) { + this.setFuseTicks(nbttagcompound.getShort("Fuse")); ++ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility ++ if (nbttagcompound.hasKey("SourceLoc_x")) { ++ int srcX = nbttagcompound.getInt("SourceLoc_x"); ++ int srcY = nbttagcompound.getInt("SourceLoc_y"); ++ int srcZ = nbttagcompound.getInt("SourceLoc_z"); ++ origin = new org.bukkit.Location(world.getWorld(), srcX, srcY, srcZ); ++ } ++ // Paper end + } + + @Nullable +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 3cf81734c8580f4d88ea97b6ac737a370b413c84..220bad90bbb9a90c3f23562bf0fb109fce379682 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1062,4 +1062,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return spigot; + } + // Spigot end ++ ++ // Paper start ++ @Override ++ public Location getOrigin() { ++ Location origin = getHandle().origin; ++ return origin == null ? null : origin.clone(); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0027-Prevent-tile-entity-and-entity-crashes.patch b/patches/server-unmapped/0027-Prevent-tile-entity-and-entity-crashes.patch new file mode 100644 index 0000000000..7abd9f5960 --- /dev/null +++ b/patches/server-unmapped/0027-Prevent-tile-entity-and-entity-crashes.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 1 Mar 2016 23:52:34 -0600 +Subject: [PATCH] Prevent tile entity and entity crashes + + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 62735e7908f86e31f7a89ce2071ddebe176c0385..87e37c38825ad20fc11f41ea2a4512753266d2b4 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -737,11 +737,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + gameprofilerfiller.exit(); + } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.a(throwable, "Ticking block entity"); +- CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block entity being ticked"); +- +- tileentity.a(crashreportsystemdetails); +- throw new ReportedException(crashreport); ++ // Paper start - Prevent tile entity and entity crashes ++ System.err.println("TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ()); ++ throwable.printStackTrace(); ++ tilesThisCycle--; ++ this.tileEntityListTick.remove(tileTickPosition--); ++ continue; ++ // Paper end + // Spigot start + } finally { + tileentity.tickTimer.stopTiming(); +@@ -806,11 +808,12 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + try { + consumer.accept(entity); + } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.a(throwable, "Ticking entity"); +- CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being ticked"); +- +- entity.appendEntityCrashDetails(crashreportsystemdetails); +- throw new ReportedException(crashreport); ++ // Paper start - Prevent tile entity and entity crashes ++ System.err.println("Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ()); ++ throwable.printStackTrace(); ++ entity.dead = true; ++ return; ++ // Paper end + } + } + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +index 9ebd91e1309938f81583eb3d4dd97fd39bcc930a..58789a6e285c31947508deae37caefe7e182278c 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +@@ -208,7 +208,12 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / + return IRegistry.BLOCK_ENTITY_TYPE.getKey(this.getTileType()) + " // " + this.getClass().getCanonicalName(); + }); + if (this.world != null) { +- CrashReportSystemDetails.a(crashreportsystemdetails, this.position, this.getBlock()); ++ // Paper start - Prevent TileEntity and Entity crashes ++ IBlockData block = this.getBlock(); ++ if (block != null) { ++ CrashReportSystemDetails.a(crashreportsystemdetails, this.position, block); ++ } ++ // Paper end + CrashReportSystemDetails.a(crashreportsystemdetails, this.position, this.world.getType(this.position)); + } + } diff --git a/patches/server-unmapped/0028-Configurable-top-of-nether-void-damage.patch b/patches/server-unmapped/0028-Configurable-top-of-nether-void-damage.patch new file mode 100644 index 0000000000..a06ff56c4c --- /dev/null +++ b/patches/server-unmapped/0028-Configurable-top-of-nether-void-damage.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 23:58:50 -0600 +Subject: [PATCH] Configurable top of nether void damage + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index d16ae924bcbe31c964f7fb448757c748e5c4418c..4bba6977a0287837b8927718c040ac61463f0469 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -134,4 +134,19 @@ public class PaperWorldConfig { + if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); + if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); + } ++ ++ public int netherVoidTopDamageHeight; ++ public boolean doNetherTopVoidDamage() { return netherVoidTopDamageHeight > 0; } ++ private void netherVoidTopDamageHeight() { ++ netherVoidTopDamageHeight = getInt("nether-ceiling-void-damage-height", 0); ++ log("Top of the nether void damage height: " + netherVoidTopDamageHeight); ++ ++ if (PaperConfig.version < 18) { ++ boolean legacy = getBoolean("nether-ceiling-void-damage", false); ++ if (legacy) { ++ netherVoidTopDamageHeight = 128; ++ set("nether-ceiling-void-damage-height", netherVoidTopDamageHeight); ++ } ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index f6f0d551e22ff085935c1543bf84392de0368214..df2582c3b00977d799b189214d7d4f30ded5b66d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -500,9 +500,16 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.fallDistance *= 0.5F; + } + ++ // Paper start - Configurable nether ceiling damage ++ ++ // Extracted to own function ++ /* + if (this.locY() < -64.0D) { + this.an(); + } ++ */ ++ this.performVoidDamage(); ++ // Paper end + + if (!this.world.isClientSide) { + this.setFlag(0, this.fireTicks > 0); +@@ -595,6 +602,17 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.setFireTicks(0); + } + ++ // Paper start ++ protected void performVoidDamage() { ++ if (this.locY() < -64.0D || (this.world.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER ++ && world.paperConfig.doNetherTopVoidDamage() ++ && this.locY() >= world.paperConfig.netherVoidTopDamageHeight)) { ++ this.doVoidDamage(); ++ } ++ } ++ // Paper end ++ ++ protected final void doVoidDamage() { this.an(); } // Paper - OBFHELPER + protected void an() { + this.die(); + } +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +index 37785b27c3d9ffd010f09f53b2ca09941f609872..1f94cc096d95129d85a6278b1e369729df93d27d 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +@@ -330,9 +330,15 @@ public abstract class EntityMinecartAbstract extends Entity { + this.setDamage(this.getDamage() - 1.0F); + } + ++ // Paper start - Configurable nether ceiling damage ++ // Extracted to own function ++ /* + if (this.locY() < -64.0D) { + this.an(); + } ++ */ ++ this.performVoidDamage(); ++ // Paper end + + // this.doPortalTick(); // CraftBukkit - handled in postTick + if (this.world.isClientSide) { diff --git a/patches/server-unmapped/0029-Check-online-mode-before-converting-and-renaming-pla.patch b/patches/server-unmapped/0029-Check-online-mode-before-converting-and-renaming-pla.patch new file mode 100644 index 0000000000..386f7f1615 --- /dev/null +++ b/patches/server-unmapped/0029-Check-online-mode-before-converting-and-renaming-pla.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Mar 2016 00:03:55 -0600 +Subject: [PATCH] Check online mode before converting and renaming player data + + +diff --git a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java +index c3a1b5943b0dad8701d566c45b9b474dac7e5c8a..191c9e9a00b9871038f60d54bc22620322f6bdbd 100644 +--- a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java +@@ -56,7 +56,7 @@ public class WorldNBTStorage { + File file = new File(this.playerDir, entityhuman.getUniqueIDString() + ".dat"); + // Spigot Start + boolean usingWrongFile = false; +- if ( !file.exists() ) ++ if ( org.bukkit.Bukkit.getOnlineMode() && !file.exists() ) // Paper - Check online mode first + { + file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + entityhuman.getName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); + if ( file.exists() ) diff --git a/patches/server-unmapped/0030-Always-tick-falling-blocks.patch b/patches/server-unmapped/0030-Always-tick-falling-blocks.patch new file mode 100644 index 0000000000..4352384dba --- /dev/null +++ b/patches/server-unmapped/0030-Always-tick-falling-blocks.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Mar 2016 00:32:25 -0600 +Subject: [PATCH] Always tick falling blocks + + +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 69c5d4e51ebf747d931fadc819973e36f001f5bc..58d22363124a9343188d8c19476e5a92f2f0b80b 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -91,6 +91,7 @@ public class ActivationRange + || entity instanceof EntityFireball + || entity instanceof EntityLightning + || entity instanceof EntityTNTPrimed ++ || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks + || entity instanceof EntityEnderCrystal + || entity instanceof EntityFireworks + || entity instanceof EntityThrownTrident ) diff --git a/patches/server-unmapped/0031-Configurable-end-credits.patch b/patches/server-unmapped/0031-Configurable-end-credits.patch new file mode 100644 index 0000000000..202de91202 --- /dev/null +++ b/patches/server-unmapped/0031-Configurable-end-credits.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DoctorDark +Date: Wed, 16 Mar 2016 02:21:39 -0500 +Subject: [PATCH] Configurable end credits + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4bba6977a0287837b8927718c040ac61463f0469..e6e18f309dc09ea9416ea37dcc697ddc2b571a96 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -149,4 +149,10 @@ public class PaperWorldConfig { + } + } + } ++ ++ public boolean disableEndCredits; ++ private void disableEndCredits() { ++ disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); ++ log("End credits disabled: " + disableEndCredits); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 5ef8b66cf266488df75ce7399596f75273b90761..808bb68b3c5115b1219a65d0dd253bd60d543652 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -191,7 +191,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + private long ca = SystemUtils.getMonotonicMillis(); + private Entity spectatedEntity; + public boolean worldChangeInvuln; +- private boolean cd; ++ private boolean cd; private void setHasSeenCredits(boolean has) { this.cd = has; } // Paper - OBFHELPER + private final RecipeBookServer recipeBook = new RecipeBookServer(); + private Vec3D cf; + private int cg; +@@ -896,6 +896,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.decouple(); + this.getWorldServer().removePlayer(this); + if (!this.viewingCredits) { ++ if (world.paperConfig.disableEndCredits) this.setHasSeenCredits(true); // Paper - Toggle to always disable end credits + this.viewingCredits = true; + this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.e, this.cd ? 0.0F : 1.0F)); + this.cd = true; diff --git a/patches/server-unmapped/0032-Fix-lag-from-explosions-processing-dead-entities.patch b/patches/server-unmapped/0032-Fix-lag-from-explosions-processing-dead-entities.patch new file mode 100644 index 0000000000..85ee818286 --- /dev/null +++ b/patches/server-unmapped/0032-Fix-lag-from-explosions-processing-dead-entities.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Iceee +Date: Wed, 2 Mar 2016 01:39:52 -0600 +Subject: [PATCH] Fix lag from explosions processing dead entities + + +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 9c1ad56e4362cd86e7ffe2aef7fd9ec301cf9002..7786a06ba09aacaa70c346e85a9eeed9f2ffec6e 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -182,7 +182,7 @@ public class Explosion { + int i1 = MathHelper.floor(this.posY + (double) f2 + 1.0D); + int j1 = MathHelper.floor(this.posZ - (double) f2 - 1.0D); + int k1 = MathHelper.floor(this.posZ + (double) f2 + 1.0D); +- List list = this.world.getEntities(this.source, new AxisAlignedBB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1)); ++ List list = this.world.getEntities(this.source, new AxisAlignedBB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1), (com.google.common.base.Predicate) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities + Vec3D vec3d = new Vec3D(this.posX, this.posY, this.posZ); + + for (int l1 = 0; l1 < list.size(); ++l1) { diff --git a/patches/server-unmapped/0033-Optimize-explosions.patch b/patches/server-unmapped/0033-Optimize-explosions.patch new file mode 100644 index 0000000000..d539442720 --- /dev/null +++ b/patches/server-unmapped/0033-Optimize-explosions.patch @@ -0,0 +1,148 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 2 Mar 2016 11:59:48 -0600 +Subject: [PATCH] Optimize explosions + +The process of determining an entity's exposure from explosions can be +expensive when there are hundreds or more entities in range. + +This patch adds a per-tick cache that is used for storing and retrieving +an entity's exposure during an explosion. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e6e18f309dc09ea9416ea37dcc697ddc2b571a96..4881b03d470646843bad1bc343eb6a6ab9072d8e 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -155,4 +155,10 @@ public class PaperWorldConfig { + disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); + log("End credits disabled: " + disableEndCredits); + } ++ ++ public boolean optimizeExplosions; ++ private void optimizeExplosions() { ++ optimizeExplosions = getBoolean("optimize-explosions", false); ++ log("Optimize explosions: " + optimizeExplosions); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index fb0d985b5c977a7c63701484678b75928d9ee382..ed71de473d461528d74ca5b95c33b97e98128aff 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1326,6 +1326,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant>> 32)); ++ temp = Double.doubleToLongBits(posY); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(posZ); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(minX); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(minY); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(minZ); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(maxX); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(maxY); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(maxZ); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ return result; ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 87e37c38825ad20fc11f41ea2a4512753266d2b4..06455fb3916e347c075c6aa84977dca7e25760c2 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -136,6 +136,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + private org.spigotmc.TickLimiter entityLimiter; + private org.spigotmc.TickLimiter tileLimiter; + private int tileTickPosition; ++ public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions + + public CraftWorld getWorld() { + return this.world; diff --git a/patches/server-unmapped/0034-Disable-explosion-knockback.patch b/patches/server-unmapped/0034-Disable-explosion-knockback.patch new file mode 100644 index 0000000000..1e714c3621 --- /dev/null +++ b/patches/server-unmapped/0034-Disable-explosion-knockback.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 14:48:03 -0600 +Subject: [PATCH] Disable explosion knockback + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4881b03d470646843bad1bc343eb6a6ab9072d8e..2222c1bb5f8625eee4d88946e4bfdfa2fe598977 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -161,4 +161,9 @@ public class PaperWorldConfig { + optimizeExplosions = getBoolean("optimize-explosions", false); + log("Optimize explosions: " + optimizeExplosions); + } ++ ++ public boolean disableExplosionKnockback; ++ private void disableExplosionKnockback(){ ++ disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index e771d84c972cea4ca1b4b5d25cd573cfcbce4579..49e95369882847c90ee7417abea6270386cd622f 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -1283,6 +1283,7 @@ public abstract class EntityLiving extends Entity { + } + } + ++ boolean knockbackCancelled = world.paperConfig.disableExplosionKnockback && damagesource.isExplosion() && this instanceof EntityHuman; // Paper - Disable explosion knockback + if (flag1) { + if (flag) { + this.world.broadcastEntityEffect(this, (byte) 29); +@@ -1301,6 +1302,7 @@ public abstract class EntityLiving extends Entity { + b0 = 2; + } + ++ if (!knockbackCancelled) // Paper - Disable explosion knockback + this.world.broadcastEntityEffect(this, b0); + } + +@@ -1324,6 +1326,7 @@ public abstract class EntityLiving extends Entity { + } + } + ++ if (knockbackCancelled) this.world.broadcastEntityEffect(this, (byte) 2); // Paper - Disable explosion knockback + if (this.dl()) { + if (!this.f(damagesource)) { + SoundEffect soundeffect = this.getSoundDeath(); +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 6a7af2c0c3c294b10c6ddbf98babb0f30d7d5f56..618cf4e0d71b4b04085807314e79a02785f8a498 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -217,14 +217,14 @@ public class Explosion { + double d14 = d13; + + if (entity instanceof EntityLiving) { +- d14 = EnchantmentProtection.a((EntityLiving) entity, d13); ++ d14 = entity instanceof EntityHuman && world.paperConfig.disableExplosionKnockback ? 0 : EnchantmentProtection.a((EntityLiving) entity, d13); // Paper - Disable explosion knockback + } + + entity.setMot(entity.getMot().add(d8 * d14, d9 * d14, d10 * d14)); + if (entity instanceof EntityHuman) { + EntityHuman entityhuman = (EntityHuman) entity; + +- if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.isFlying)) { ++ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.isFlying) && !world.paperConfig.disableExplosionKnockback) { // Paper - Disable explosion knockback + this.n.put(entityhuman, new Vec3D(d8 * d13, d9 * d13, d10 * d13)); + } + } diff --git a/patches/server-unmapped/0035-Disable-thunder.patch b/patches/server-unmapped/0035-Disable-thunder.patch new file mode 100644 index 0000000000..9c0e1d9856 --- /dev/null +++ b/patches/server-unmapped/0035-Disable-thunder.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 14:52:43 -0600 +Subject: [PATCH] Disable thunder + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2222c1bb5f8625eee4d88946e4bfdfa2fe598977..083e421f8496b5336af473b108498ed28b984774 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -166,4 +166,9 @@ public class PaperWorldConfig { + private void disableExplosionKnockback(){ + disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); + } ++ ++ public boolean disableThunder; ++ private void disableThunder() { ++ disableThunder = getBoolean("disable-thunder", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 26d461196b4a998b445f8c6e67fd7ec0606344f6..8845b5c6dc9ebff30e8aa3abd3c905addaeb3e1d 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -586,7 +586,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + gameprofilerfiller.enter("thunder"); + BlockPosition blockposition; + +- if (flag && this.W() && this.random.nextInt(100000) == 0) { ++ if (!this.paperConfig.disableThunder && flag && this.W() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder + blockposition = this.a(this.a(j, 0, k, 15)); + if (this.isRainingAt(blockposition)) { + DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); diff --git a/patches/server-unmapped/0036-Disable-ice-and-snow.patch b/patches/server-unmapped/0036-Disable-ice-and-snow.patch new file mode 100644 index 0000000000..0ce64ee502 --- /dev/null +++ b/patches/server-unmapped/0036-Disable-ice-and-snow.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 14:57:24 -0600 +Subject: [PATCH] Disable ice and snow + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 083e421f8496b5336af473b108498ed28b984774..2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -171,4 +171,9 @@ public class PaperWorldConfig { + private void disableThunder() { + disableThunder = getBoolean("disable-thunder", false); + } ++ ++ public boolean disableIceAndSnow; ++ private void disableIceAndSnow(){ ++ disableIceAndSnow = getBoolean("disable-ice-and-snow", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 8845b5c6dc9ebff30e8aa3abd3c905addaeb3e1d..a1769df6a3f6150d322f145199caba3839871dff 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -610,7 +610,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + gameprofilerfiller.exitEnter("iceandsnow"); +- if (this.random.nextInt(16) == 0) { ++ if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow + blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, this.a(j, 0, k, 15)); + BlockPosition blockposition1 = blockposition.down(); + BiomeBase biomebase = this.getBiome(blockposition); diff --git a/patches/server-unmapped/0037-Configurable-mob-spawner-tick-rate.patch b/patches/server-unmapped/0037-Configurable-mob-spawner-tick-rate.patch new file mode 100644 index 0000000000..0ced9bb837 --- /dev/null +++ b/patches/server-unmapped/0037-Configurable-mob-spawner-tick-rate.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 15:03:53 -0600 +Subject: [PATCH] Configurable mob spawner tick rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2..4de86b09c6bc3c1974ce61b550ccb73d37f6f170 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -176,4 +176,9 @@ public class PaperWorldConfig { + private void disableIceAndSnow(){ + disableIceAndSnow = getBoolean("disable-ice-and-snow", false); + } ++ ++ public int mobSpawnerTickRate; ++ private void mobSpawnerTickRate() { ++ mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +index 8d8b03074df1635946f81bec0feae18d2f3e20aa..76c98d576d3e567ec4482b30219f5a9107cb9703 100644 +--- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java ++++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +@@ -41,6 +41,7 @@ public abstract class MobSpawnerAbstract { + public int maxNearbyEntities = 6; + public int requiredPlayerRange = 16; + public int spawnRange = 4; ++ private int tickDelay = 0; // Paper + + public MobSpawnerAbstract() {} + +@@ -70,6 +71,10 @@ public abstract class MobSpawnerAbstract { + } + + public void c() { ++ // Paper start - Configurable mob spawner tick rate ++ if (spawnDelay > 0 && --tickDelay > 0) return; ++ tickDelay = this.a().paperConfig.mobSpawnerTickRate; ++ // Paper end + if (!this.h()) { + this.f = this.e; + } else { +@@ -84,18 +89,18 @@ public abstract class MobSpawnerAbstract { + world.addParticle(Particles.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + world.addParticle(Particles.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D); + if (this.spawnDelay > 0) { +- --this.spawnDelay; ++ this.spawnDelay -= tickDelay; // Paper + } + + this.f = this.e; + this.e = (this.e + (double) (1000.0F / ((float) this.spawnDelay + 200.0F))) % 360.0D; + } else { +- if (this.spawnDelay == -1) { ++ if (this.spawnDelay < -tickDelay) { // Paper + this.i(); + } + + if (this.spawnDelay > 0) { +- --this.spawnDelay; ++ this.spawnDelay -= tickDelay; // Paper + return; + } + diff --git a/patches/server-unmapped/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch b/patches/server-unmapped/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch new file mode 100644 index 0000000000..c6d0215417 --- /dev/null +++ b/patches/server-unmapped/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Wed, 2 Mar 2016 23:13:07 -0600 +Subject: [PATCH] Send absolute position the first time an entity is seen + + +diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +index 9ad74b380a92e3a563e1a891e81401d8b4707bcf..beb0beb716869978be6bc5a78ce3b6cf785c5aee 100644 +--- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java ++++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +@@ -4,6 +4,7 @@ import com.google.common.collect.Lists; + import com.mojang.datafixers.util.Pair; + import java.util.Collection; + import java.util.Collections; ++import java.util.HashSet; + import java.util.Iterator; + import java.util.List; + import java.util.Set; +@@ -52,7 +53,7 @@ public class EntityTrackerEntry { + private final Entity tracker; + private final int d; + private final boolean e; +- private final Consumer> f; ++ private final Consumer> f; private Consumer> getPacketConsumer() { return f; } // Paper - OBFHELPER + private long xLoc; + private long yLoc; + private long zLoc; +@@ -67,8 +68,23 @@ public class EntityTrackerEntry { + private boolean r; + // CraftBukkit start + private final Set trackedPlayers; ++ // Paper start ++ private java.util.Map trackedPlayerMap = null; ++ ++ /** ++ * Requested in https://github.com/PaperMC/Paper/issues/1537 to allow intercepting packets ++ */ ++ public void sendPlayerPacket(EntityPlayer player, Packet packet) { ++ player.playerConnection.sendPacket(packet); ++ } ++ ++ public EntityTrackerEntry(WorldServer worldserver, Entity entity, int i, boolean flag, Consumer> consumer, java.util.Map trackedPlayers) { ++ this(worldserver, entity, i, flag, consumer, trackedPlayers.keySet()); ++ trackedPlayerMap = trackedPlayers; ++ } + + public EntityTrackerEntry(WorldServer worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { ++ // Paper end + this.trackedPlayers = trackedPlayers; + // CraftBukkit end + this.m = Vec3D.ORIGIN; +@@ -189,7 +205,25 @@ public class EntityTrackerEntry { + } + + if (packet1 != null) { +- this.f.accept(packet1); ++ // paper start ++ if (trackedPlayerMap == null || packet1 instanceof PacketPlayOutEntityTeleport) { ++ this.f.accept((packet1)); ++ } else { ++ PacketPlayOutEntityTeleport teleportPacket = null; ++ ++ for (java.util.Map.Entry viewer : trackedPlayerMap.entrySet()) { ++ if (viewer.getValue()) { ++ viewer.setValue(false); ++ if (teleportPacket == null) { ++ teleportPacket = new PacketPlayOutEntityTeleport(this.tracker); ++ } ++ sendPlayerPacket(viewer.getKey(), teleportPacket); ++ } else { ++ sendPlayerPacket(viewer.getKey(), packet1); ++ } ++ } ++ } ++ // Paper end + } + + this.c(); +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 62245fa420390dc0a70ba9a95505dc46cd8aa64a..788a45d5426f0752509442aec2d28b1f32f63cb1 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -1303,10 +1303,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + private final Entity tracker; + private final int trackingDistance; + private SectionPosition e; +- public final Set trackedPlayers = Sets.newHashSet(); ++ // Paper start ++ // Replace trackedPlayers Set with a Map. The value is true until the player receives ++ // their first update (which is forced to have absolute coordinates), false afterward. ++ public java.util.Map trackedPlayerMap = new java.util.HashMap<>(); ++ public Set trackedPlayers = trackedPlayerMap.keySet(); + + public EntityTracker(Entity entity, int i, int j, boolean flag) { +- this.trackerEntry = new EntityTrackerEntry(PlayerChunkMap.this.world, entity, j, flag, this::broadcast, trackedPlayers); // CraftBukkit ++ this.trackerEntry = new EntityTrackerEntry(PlayerChunkMap.this.world, entity, j, flag, this::broadcast, trackedPlayerMap); // CraftBukkit // Paper + this.tracker = entity; + this.trackingDistance = i; + this.e = SectionPosition.a(entity); +@@ -1388,7 +1392,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + entityplayer.removeQueue.remove(Integer.valueOf(this.tracker.getId())); + // CraftBukkit end + +- if (flag1 && this.trackedPlayers.add(entityplayer)) { ++ if (flag1 && this.trackedPlayerMap.putIfAbsent(entityplayer, true) == null) { // Paper + this.trackerEntry.b(entityplayer); + } + } else if (this.trackedPlayers.remove(entityplayer)) { diff --git a/patches/server-unmapped/0039-Add-BeaconEffectEvent.patch b/patches/server-unmapped/0039-Add-BeaconEffectEvent.patch new file mode 100644 index 0000000000..9ca515c4b7 --- /dev/null +++ b/patches/server-unmapped/0039-Add-BeaconEffectEvent.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 2 Mar 2016 23:30:53 -0600 +Subject: [PATCH] Add BeaconEffectEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java +index c6914c8d2a3d1057c98537a3538097d3ac6149e0..4098357d60165a4c670a7bc5134abf66178124c6 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java +@@ -42,6 +42,11 @@ import net.minecraft.world.phys.AxisAlignedBB; + import org.bukkit.craftbukkit.potion.CraftPotionUtil; + import org.bukkit.potion.PotionEffect; + // CraftBukkit end ++// Paper start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.Player; ++import com.destroystokyo.paper.event.block.BeaconEffectEvent; ++// Paper end + + public class TileEntityBeacon extends TileEntity implements ITileInventory, ITickable { + +@@ -268,14 +273,30 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic + } + + private void applyEffect(List list, MobEffectList effects, int i, int b0) { ++ // Paper - BeaconEffectEvent ++ applyEffect(list, effects, i, b0, true); ++ } ++ ++ private void applyEffect(List list, MobEffectList effects, int i, int b0, boolean isPrimary) { ++ // Paper - BeaconEffectEvent + { + Iterator iterator = list.iterator(); + + EntityHuman entityhuman; + ++ // Paper start - BeaconEffectEvent ++ org.bukkit.block.Block block = world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); ++ PotionEffect effect = CraftPotionUtil.toBukkit(new MobEffect(effects, i, b0, true, true)); ++ // Paper end ++ + while (iterator.hasNext()) { + entityhuman = (EntityHuman) iterator.next(); +- entityhuman.addEffect(new MobEffect(effects, i, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); ++ ++ // Paper start - BeaconEffectEvent ++ BeaconEffectEvent event = new BeaconEffectEvent(block, effect, (Player) entityhuman.getBukkitEntity(), isPrimary); ++ if (CraftEventFactory.callEvent(event).isCancelled()) continue; ++ entityhuman.addEffect(new MobEffect(CraftPotionUtil.fromBukkit(event.getEffect())), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); ++ // Paper end + } + } + } +@@ -298,10 +319,10 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic + int i = getLevel(); + List list = getHumansInRange(); + +- applyEffect(list, this.primaryEffect, i, b0); ++ applyEffect(list, this.primaryEffect, i, b0, true); // Paper - BeaconEffectEvent + + if (hasSecondaryEffect()) { +- applyEffect(list, this.secondaryEffect, i, 0); ++ applyEffect(list, this.secondaryEffect, i, 0, false); // Paper - BeaconEffectEvent + } + } + diff --git a/patches/server-unmapped/0040-Configurable-container-update-tick-rate.patch b/patches/server-unmapped/0040-Configurable-container-update-tick-rate.patch new file mode 100644 index 0000000000..75bd09e685 --- /dev/null +++ b/patches/server-unmapped/0040-Configurable-container-update-tick-rate.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 23:34:44 -0600 +Subject: [PATCH] Configurable container update tick rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4de86b09c6bc3c1974ce61b550ccb73d37f6f170..5a4c3a8c511f22c8c3240c9c7cd83a65119c1054 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -181,4 +181,9 @@ public class PaperWorldConfig { + private void mobSpawnerTickRate() { + mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); + } ++ ++ public int containerUpdateTickRate; ++ private void containerUpdateTickRate() { ++ containerUpdateTickRate = getInt("container-update-tick-rate", 1); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 808bb68b3c5115b1219a65d0dd253bd60d543652..cda0e7f8f9a9d66ac4e5a3f52609a4271bf0c4b5 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -210,6 +210,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public boolean e; + public int ping; + public boolean viewingCredits; ++ private int containerUpdateDelay; // Paper + + // CraftBukkit start + public String displayName; +@@ -534,7 +535,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + --this.noDamageTicks; + } + +- this.activeContainer.c(); ++ // Paper start - Configurable container update tick rate ++ if (--containerUpdateDelay <= 0) { ++ this.activeContainer.c(); ++ containerUpdateDelay = world.paperConfig.containerUpdateTickRate; ++ } ++ // Paper end + if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { + this.closeInventory(); + this.activeContainer = this.defaultContainer; diff --git a/patches/server-unmapped/0041-Use-UserCache-for-player-heads.patch b/patches/server-unmapped/0041-Use-UserCache-for-player-heads.patch new file mode 100644 index 0000000000..1def3bad81 --- /dev/null +++ b/patches/server-unmapped/0041-Use-UserCache-for-player-heads.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Wed, 2 Mar 2016 23:42:37 -0600 +Subject: [PATCH] Use UserCache for player heads + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +index b8cac55c9fdcebe7703f179d25ad8cfb15c78a0e..dff67a48961399f3746f99b4f2363724bfe51c36 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +@@ -166,7 +166,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + if (name == null) { + setProfile(null); + } else { +- setProfile(new GameProfile(null, name)); ++ // Paper start - Use Online Players Skull ++ GameProfile newProfile = null; ++ net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayer(name); ++ if (player != null) newProfile = player.getProfile(); ++ if (newProfile == null) newProfile = new GameProfile(null, name); ++ setProfile(newProfile); ++ // Paper end + } + + return true; diff --git a/patches/server-unmapped/0042-Disable-spigot-tick-limiters.patch b/patches/server-unmapped/0042-Disable-spigot-tick-limiters.patch new file mode 100644 index 0000000000..54851e5ccf --- /dev/null +++ b/patches/server-unmapped/0042-Disable-spigot-tick-limiters.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Mar 2016 23:45:17 -0600 +Subject: [PATCH] Disable spigot tick limiters + + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 06455fb3916e347c075c6aa84977dca7e25760c2..26d9388badb0328735abf0319a42bd633c90dc4b 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -707,9 +707,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + // Spigot start + // Iterator iterator = this.tileEntityListTick.iterator(); + int tilesThisCycle = 0; +- for (tileLimiter.initTick(); +- tilesThisCycle < tileEntityListTick.size() && (tilesThisCycle % 10 != 0 || tileLimiter.shouldContinue()); +- tileTickPosition++, tilesThisCycle++) { ++ for (tileTickPosition = 0; tileTickPosition < tileEntityListTick.size(); tileTickPosition++) { // Paper - Disable tick limiters + tileTickPosition = (tileTickPosition < tileEntityListTick.size()) ? tileTickPosition : 0; + TileEntity tileentity = (TileEntity) this.tileEntityListTick.get(tileTickPosition); + // Spigot start diff --git a/patches/server-unmapped/0043-Add-PlayerInitialSpawnEvent.patch b/patches/server-unmapped/0043-Add-PlayerInitialSpawnEvent.patch new file mode 100644 index 0000000000..f3fdc63315 --- /dev/null +++ b/patches/server-unmapped/0043-Add-PlayerInitialSpawnEvent.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Steve Anton +Date: Thu, 3 Mar 2016 00:09:38 -0600 +Subject: [PATCH] Add PlayerInitialSpawnEvent + +For modifying a player's initial spawn location as they join the server + +This is a duplicate API from spigot, so use our duplicate subclass and +improve setPosition to use raw + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 6ebd4ec781aa215c2b941261250c15c87c223cab..46c516b9ff089a3c885d635244942fd5a6ecf132 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -213,7 +213,7 @@ public abstract class PlayerList { + + // Spigot start - spawn location event + Player bukkitPlayer = entityplayer.getBukkitEntity(); +- org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(bukkitPlayer, bukkitPlayer.getLocation()); ++ org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(bukkitPlayer, bukkitPlayer.getLocation()); // Paper use our duplicate event + cserver.getPluginManager().callEvent(ev); + + Location loc = ev.getSpawnLocation(); +@@ -221,7 +221,10 @@ public abstract class PlayerList { + + entityplayer.spawnIn(worldserver1); + entityplayer.playerInteractManager.a((WorldServer) entityplayer.world); +- entityplayer.setLocation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); ++ // Paper start - set raw so we aren't fully joined to the world (not added to chunk or world) ++ entityplayer.setPositionRaw(loc.getX(), loc.getY(), loc.getZ()); ++ entityplayer.setYawPitch(loc.getYaw(), loc.getPitch()); ++ // Paper end + // Spigot end + + // CraftBukkit - Moved message to after join +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index df2582c3b00977d799b189214d7d4f30ded5b66d..77cc0aeb979369df2156f8fb916067f608b61ebf 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -398,7 +398,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return d1 * d1 + d2 * d2 + d3 * d3 < d0 * d0; + } + +- protected void setYawPitch(float f, float f1) { ++ public void setYawPitch(float f, float f1) { // Paper - protected -> public + // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 + if (Float.isNaN(f)) { + f = 0; diff --git a/patches/server-unmapped/0044-Configurable-Disabling-Cat-Chest-Detection.patch b/patches/server-unmapped/0044-Configurable-Disabling-Cat-Chest-Detection.patch new file mode 100644 index 0000000000..9c34c4ef30 --- /dev/null +++ b/patches/server-unmapped/0044-Configurable-Disabling-Cat-Chest-Detection.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 01:13:45 -0600 +Subject: [PATCH] Configurable Disabling Cat Chest Detection + +Offers a gameplay feature to stop cats from blocking chests + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5a4c3a8c511f22c8c3240c9c7cd83a65119c1054..70e074cdf2087e638af8e0f3878d0ef8eb7305cc 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -186,4 +186,9 @@ public class PaperWorldConfig { + private void containerUpdateTickRate() { + containerUpdateTickRate = getInt("container-update-tick-rate", 1); + } ++ ++ public boolean disableChestCatDetection; ++ private void disableChestCatDetection() { ++ disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java +index b229faad99120c67b089f7680d800fbe594fe7da..b2c29cff5883868cb56a4e376ab946ac929abc94 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockChest.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java +@@ -312,6 +312,11 @@ public class BlockChest extends BlockChestAbstract implements I + } + + private static boolean b(GeneratorAccess generatoraccess, BlockPosition blockposition) { ++ // Paper start - Option to disable chest cat detection ++ if (((World) generatoraccess).paperConfig.disableChestCatDetection) { ++ return false; ++ } ++ // Paper end + List list = generatoraccess.a(EntityCat.class, new AxisAlignedBB((double) blockposition.getX(), (double) (blockposition.getY() + 1), (double) blockposition.getZ(), (double) (blockposition.getX() + 1), (double) (blockposition.getY() + 2), (double) (blockposition.getZ() + 1))); + + if (!list.isEmpty()) { diff --git a/patches/server-unmapped/0045-Ensure-commands-are-not-ran-async.patch b/patches/server-unmapped/0045-Ensure-commands-are-not-ran-async.patch new file mode 100644 index 0000000000..f0a462da4a --- /dev/null +++ b/patches/server-unmapped/0045-Ensure-commands-are-not-ran-async.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 01:17:12 -0600 +Subject: [PATCH] Ensure commands are not ran async + +Plugins calling Player.chat("/foo") or Server.dispatchCommand() could +trigger the server to execute a command while on another thread. + +These commands would then process EXPECTING to be on the main thread, leaving to +very hard to trace concurrency issues. + +This change will synchronize the command execution back to the main thread, causing a +big slowdown in execution but throwing an exception at same time to raise awareness +that it is happening so that plugin authors can fix their code to stop executing commands async. + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 5db09e60c2ac1f4cb0da3190e57896ccae7c58a3..865d8efa2d480ae7edc286e3e79f2997a191ee5c 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1854,6 +1854,29 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + + if (!async && s.startsWith("/")) { ++ // Paper Start ++ if (!org.spigotmc.AsyncCatcher.shuttingDown && !org.bukkit.Bukkit.isPrimaryThread()) { ++ final String fCommandLine = s; ++ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Command Dispatched Async: " + fCommandLine); ++ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); ++ Waitable wait = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ chat(fCommandLine, false); ++ return null; ++ } ++ }; ++ minecraftServer.processQueue.add(wait); ++ try { ++ wait.get(); ++ return; ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! ++ } catch (Exception e) { ++ throw new RuntimeException("Exception processing chat command", e.getCause()); ++ } ++ } ++ // Paper End + this.handleCommand(s); + } else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) { + // Do nothing, this is coming from a plugin +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index b4b592faaa699b6e62f77ddf57b239c5e15948ff..b7de5049dfd6807de1c84a9454b9097141399660 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -760,6 +760,29 @@ public final class CraftServer implements Server { + Validate.notNull(commandLine, "CommandLine cannot be null"); + org.spigotmc.AsyncCatcher.catchOp("command dispatch"); // Spigot + ++ // Paper Start ++ if (!org.spigotmc.AsyncCatcher.shuttingDown && !Bukkit.isPrimaryThread()) { ++ final CommandSender fSender = sender; ++ final String fCommandLine = commandLine; ++ Bukkit.getLogger().log(Level.SEVERE, "Command Dispatched Async: " + commandLine); ++ Bukkit.getLogger().log(Level.SEVERE, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); ++ org.bukkit.craftbukkit.util.Waitable wait = new org.bukkit.craftbukkit.util.Waitable() { ++ @Override ++ protected Boolean evaluate() { ++ return dispatchCommand(fSender, fCommandLine); ++ } ++ }; ++ net.minecraft.server.MinecraftServer.getServer().processQueue.add(wait); ++ try { ++ return wait.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! ++ } catch (Exception e) { ++ throw new RuntimeException("Exception processing dispatch command", e.getCause()); ++ } ++ } ++ // Paper End ++ + if (commandMap.dispatch(sender, commandLine)) { + return true; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +index ddef523ea8762c927f37f7d16d581e43367e8c6b..70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +@@ -13,6 +13,7 @@ public class ServerShutdownThread extends Thread { + public void run() { + try { + org.spigotmc.AsyncCatcher.enabled = false; // Spigot ++ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper + server.close(); + } finally { + try { +diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java +index aeed7697254af17ffefe8e578353ad216e15f9f3..9f7d2ef932ab41cef5d3d0736d20a7c7e4a2c888 100644 +--- a/src/main/java/org/spigotmc/AsyncCatcher.java ++++ b/src/main/java/org/spigotmc/AsyncCatcher.java +@@ -6,6 +6,7 @@ public class AsyncCatcher + { + + public static boolean enabled = true; ++ public static boolean shuttingDown = false; // Paper + + public static void catchOp(String reason) + { +diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java +index d76e01d73da7413f192132134caf201d7780e3f1..a45155cdd7d7a302c119f75bfe2b428ae5e8ab47 100644 +--- a/src/main/java/org/spigotmc/RestartCommand.java ++++ b/src/main/java/org/spigotmc/RestartCommand.java +@@ -43,6 +43,7 @@ public class RestartCommand extends Command + private static void restart(final String restartScript) + { + AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us ++ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper + try + { + String[] split = restartScript.split( " " ); diff --git a/patches/server-unmapped/0046-All-chunks-are-slime-spawn-chunks-toggle.patch b/patches/server-unmapped/0046-All-chunks-are-slime-spawn-chunks-toggle.patch new file mode 100644 index 0000000000..48622f89ba --- /dev/null +++ b/patches/server-unmapped/0046-All-chunks-are-slime-spawn-chunks-toggle.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: vemacs +Date: Thu, 3 Mar 2016 01:19:22 -0600 +Subject: [PATCH] All chunks are slime spawn chunks toggle + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 70e074cdf2087e638af8e0f3878d0ef8eb7305cc..416a6760883cb40367535c7c5acd779742bb8af5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -191,4 +191,9 @@ public class PaperWorldConfig { + private void disableChestCatDetection() { + disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); + } ++ ++ public boolean allChunksAreSlimeChunks; ++ private void allChunksAreSlimeChunks() { ++ allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java +index 292789d76da400d15d0742e2e0979f4ac6ec4b75..01d5b0db9a34d88172e8c7c84c4e1d0b2562217c 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java +@@ -325,7 +325,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { + } + + ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(blockposition); +- boolean flag = SeededRandom.a(chunkcoordintpair.x, chunkcoordintpair.z, ((GeneratorAccessSeed) generatoraccess).getSeed(), generatoraccess.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot ++ boolean flag = generatoraccess.getMinecraftWorld().paperConfig.allChunksAreSlimeChunks || SeededRandom.a(chunkcoordintpair.x, chunkcoordintpair.z, ((GeneratorAccessSeed) generatoraccess).getSeed(), generatoraccess.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper + + if (random.nextInt(10) == 0 && flag && blockposition.getY() < 40) { + return a(entitytypes, generatoraccess, enummobspawn, blockposition, random); diff --git a/patches/server-unmapped/0047-Expose-server-CommandMap.patch b/patches/server-unmapped/0047-Expose-server-CommandMap.patch new file mode 100644 index 0000000000..60c4376ef8 --- /dev/null +++ b/patches/server-unmapped/0047-Expose-server-CommandMap.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Thu, 3 Mar 2016 02:15:57 -0600 +Subject: [PATCH] Expose server CommandMap + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index b7de5049dfd6807de1c84a9454b9097141399660..f78f5e4f2c04b64dff1d2229a137c600f18e7051 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1761,6 +1761,7 @@ public final class CraftServer implements Server { + return helpMap; + } + ++ @Override // Paper - add override + public SimpleCommandMap getCommandMap() { + return commandMap; + } diff --git a/patches/server-unmapped/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch b/patches/server-unmapped/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch new file mode 100644 index 0000000000..6f72badc91 --- /dev/null +++ b/patches/server-unmapped/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Thu, 3 Mar 2016 02:18:39 -0600 +Subject: [PATCH] Be a bit more informative in maxHealth exception + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index da0a7a60cbabe0dafa9630b8dcba98e64dcc8d3a..d863fc9fa6b932b76a89871a09378a9c0697c108 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -111,7 +111,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setHealth(double health) { + health = (float) health; + if ((health < 0) || (health > getMaxHealth())) { +- throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + "(" + health + ")"); ++ // Paper - Be more informative ++ throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + ", but was " + health ++ + ". (attribute base value: " + this.getHandle().getAttributeInstance(GenericAttributes.MAX_HEALTH).getBaseValue() ++ + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); + } + + getHandle().setHealth((float) health); diff --git a/patches/server-unmapped/0049-Player-Tab-List-and-Title-APIs.patch b/patches/server-unmapped/0049-Player-Tab-List-and-Title-APIs.patch new file mode 100644 index 0000000000..9eeb0fdfdd --- /dev/null +++ b/patches/server-unmapped/0049-Player-Tab-List-and-Title-APIs.patch @@ -0,0 +1,142 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Thu, 3 Mar 2016 02:32:10 -0600 +Subject: [PATCH] Player Tab List and Title APIs + + +diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java +index 5f1c5dd7902f6cff5acae05e8c6bf58a1ba5bdf1..df459918c14589155a574730205cb35d463b8079 100644 +--- a/src/main/java/net/minecraft/network/PacketDataSerializer.java ++++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java +@@ -171,6 +171,11 @@ public class PacketDataSerializer extends ByteBuf { + public PacketDataSerializer writeComponent(final net.kyori.adventure.text.Component component) { + return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); + } ++ ++ @Deprecated ++ public PacketDataSerializer writeComponent(final net.md_5.bungee.api.chat.BaseComponent[] component) { ++ return this.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(component), 262144); ++ } + // Paper end + + public PacketDataSerializer a(IChatBaseComponent ichatbasecomponent) { +diff --git a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java +index e96fa348a37a39c381b6659f612232933686c2a7..a002125e454f8a86924e9010e0b20a95742fa04b 100644 +--- a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java ++++ b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java +@@ -364,6 +364,7 @@ public interface IChatBaseComponent extends Message, IChatFormatted, Iterable +Date: Thu, 3 Mar 2016 02:33:53 -0600 +Subject: [PATCH] Ensure inv drag is in bounds + + +diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java +index 2410214a300407ef20ea14244db5db2ebede2759..e9733fd9dac89d31dbad391cb22a8c84216045db 100644 +--- a/src/main/java/net/minecraft/world/inventory/Container.java ++++ b/src/main/java/net/minecraft/world/inventory/Container.java +@@ -239,7 +239,7 @@ public abstract class Container { + this.d(); + } + } else if (this.h == 1) { +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = i < this.slots.size() ? this.slots.get(i) : null; // Paper - Ensure drag in bounds + + itemstack1 = playerinventory.getCarried(); + if (slot != null && a(slot, itemstack1, true) && slot.isAllowed(itemstack1) && (this.dragType == 2 || itemstack1.getCount() > this.i.size()) && this.b(slot)) { diff --git a/patches/server-unmapped/0051-Change-implementation-of-tile-entity-removal-list.patch b/patches/server-unmapped/0051-Change-implementation-of-tile-entity-removal-list.patch new file mode 100644 index 0000000000..05bc8dac6d --- /dev/null +++ b/patches/server-unmapped/0051-Change-implementation-of-tile-entity-removal-list.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joseph Hirschfeld +Date: Thu, 3 Mar 2016 02:39:54 -0600 +Subject: [PATCH] Change implementation of (tile)entity removal list + +use sets for faster removal + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 26d9388badb0328735abf0319a42bd633c90dc4b..33469b719d679c65d4bcb8366008e6e107eb3a0b 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -89,7 +89,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public final List tileEntityList = Lists.newArrayList(); + public final List tileEntityListTick = Lists.newArrayList(); + protected final List tileEntityListPending = Lists.newArrayList(); +- protected final List tileEntityListUnload = Lists.newArrayList(); ++ protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); + public final Thread serverThread; + private final boolean debugWorld; + private int d; diff --git a/patches/server-unmapped/0052-Add-configurable-portal-search-radius.patch b/patches/server-unmapped/0052-Add-configurable-portal-search-radius.patch new file mode 100644 index 0000000000..e6151a7682 --- /dev/null +++ b/patches/server-unmapped/0052-Add-configurable-portal-search-radius.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joseph Hirschfeld +Date: Thu, 3 Mar 2016 02:46:17 -0600 +Subject: [PATCH] Add configurable portal search radius + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 416a6760883cb40367535c7c5acd779742bb8af5..670efbe53241a0ae32d618c83da601ccc1f26e37 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -196,4 +196,13 @@ public class PaperWorldConfig { + private void allChunksAreSlimeChunks() { + allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); + } ++ ++ public int portalSearchRadius; ++ public int portalCreateRadius; ++ public boolean portalSearchVanillaDimensionScaling; ++ private void portalSearchRadius() { ++ portalSearchRadius = getInt("portal-search-radius", 128); ++ portalCreateRadius = getInt("portal-create-radius", 16); ++ portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 77cc0aeb979369df2156f8fb916067f608b61ebf..caae8bdae592a1ae4f99861088458d7461f4c97a 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2618,7 +2618,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + double d4 = DimensionManager.a(this.world.getDimensionManager(), worldserver.getDimensionManager()); + BlockPosition blockposition = new BlockPosition(MathHelper.a(this.locX() * d4, d0, d2), this.locY(), MathHelper.a(this.locZ() * d4, d1, d3)); + // CraftBukkit start +- CraftPortalEvent event = callPortalEvent(this, worldserver, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); ++ // Paper start ++ int portalSearchRadius = worldserver.paperConfig.portalSearchRadius; ++ if (world.paperConfig.portalSearchVanillaDimensionScaling && flag2) { // == THE_NETHER ++ portalSearchRadius = (int) (portalSearchRadius / worldserver.getDimensionManager().getCoordinateScale()); ++ } ++ // Paper end ++ CraftPortalEvent event = callPortalEvent(this, worldserver, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, portalSearchRadius, worldserver.paperConfig.portalCreateRadius); // Paper start - configurable portal radius + if (event == null) { + return null; + } +diff --git a/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java b/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java +index 7b8e8a7dae47ecc42a57e3f9444caa2ee5b1ef3b..77dfa7eaf178baa55041a829c9dec4851efeedfc 100644 +--- a/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java ++++ b/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java +@@ -31,7 +31,7 @@ public class PortalTravelAgent { + + public Optional findPortal(BlockPosition blockposition, boolean flag) { + // CraftBukkit start +- return findPortal(blockposition, flag ? 16 : 128); // Search Radius ++ return findPortal(blockposition, flag ? world.paperConfig.portalCreateRadius : world.paperConfig.portalSearchRadius); // Paper - search Radius + } + + public Optional findPortal(BlockPosition blockposition, int i) { diff --git a/patches/server-unmapped/0053-Add-velocity-warnings.patch b/patches/server-unmapped/0053-Add-velocity-warnings.patch new file mode 100644 index 0000000000..41c25af3bd --- /dev/null +++ b/patches/server-unmapped/0053-Add-velocity-warnings.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joseph Hirschfeld +Date: Thu, 3 Mar 2016 02:48:12 -0600 +Subject: [PATCH] Add velocity warnings + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index f78f5e4f2c04b64dff1d2229a137c600f18e7051..22b4dec4944b7f823996645af95fbef2d1d8a83b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -261,6 +261,7 @@ public final class CraftServer implements Server { + public boolean ignoreVanillaPermissions = false; + private final List playerView; + public int reloadCount; ++ public static Exception excessiveVelEx; // Paper - Velocity warnings + + static { + ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 220bad90bbb9a90c3f23562bf0fb109fce379682..a58626b1a0160983a738a45c8a1d411eb347e6a2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -424,10 +424,41 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public void setVelocity(Vector velocity) { + Preconditions.checkArgument(velocity != null, "velocity"); + velocity.checkFinite(); ++ // Paper start - Warn server owners when plugins try to set super high velocities ++ if (!(this instanceof org.bukkit.entity.Projectile) && isUnsafeVelocity(velocity)) { ++ CraftServer.excessiveVelEx = new Exception("Excessive velocity set detected: tried to set velocity of entity " + entity.getName() + " id #" + getEntityId() + " to (" + velocity.getX() + "," + velocity.getY() + "," + velocity.getZ() + ")."); ++ } ++ // Paper end ++ + entity.setMot(CraftVector.toNMS(velocity)); + entity.velocityChanged = true; + } + ++ // Paper start ++ /** ++ * Checks if the given velocity is not necessarily safe in all situations. ++ * This function returning true does not mean the velocity is dangerous or to be avoided, only that it may be ++ * a detriment to performance on the server. ++ * ++ * It is not to be used as a hard rule of any sort. ++ * Paper only uses it to warn server owners in watchdog crashes. ++ * ++ * @param vel incoming velocity to check ++ * @return if the velocity has the potential to be a performance detriment ++ */ ++ private static boolean isUnsafeVelocity(Vector vel) { ++ final double x = vel.getX(); ++ final double y = vel.getY(); ++ final double z = vel.getZ(); ++ ++ if (x > 4 || x < -4 || y > 4 || y < -4 || z > 4 || z < -4) { ++ return true; ++ } ++ ++ return false; ++ } ++ // Paper end ++ + @Override + public double getHeight() { + return getHandle().getHeight(); +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 1b3a14784cac8e855633fae6172ad5479ebe9877..69e5054886b5858664fed333aca8c25a76e5cb11 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -80,7 +80,19 @@ public class WatchdogThread extends Thread + log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" ); + log.log( Level.SEVERE, "near " + net.minecraft.world.level.World.lastPhysicsProblem ); + } +- // ++ // Paper start - Warn in watchdog if an excessive velocity was ever set ++ if ( org.bukkit.craftbukkit.CraftServer.excessiveVelEx != null ) ++ { ++ log.log( Level.SEVERE, "------------------------------" ); ++ log.log( Level.SEVERE, "During the run of the server, a plugin set an excessive velocity on an entity" ); ++ log.log( Level.SEVERE, "This may be the cause of the issue, or it may be entirely unrelated" ); ++ log.log( Level.SEVERE, org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getMessage()); ++ for ( StackTraceElement stack : org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getStackTrace() ) ++ { ++ log.log( Level.SEVERE, "\t\t" + stack ); ++ } ++ } ++ // Paper end + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); diff --git a/patches/server-unmapped/0054-Configurable-inter-world-teleportation-safety.patch b/patches/server-unmapped/0054-Configurable-inter-world-teleportation-safety.patch new file mode 100644 index 0000000000..789bab195f --- /dev/null +++ b/patches/server-unmapped/0054-Configurable-inter-world-teleportation-safety.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Thu, 3 Mar 2016 02:50:31 -0600 +Subject: [PATCH] Configurable inter-world teleportation safety + +People are able to abuse the way Bukkit handles teleportation across worlds since it provides a built in teleportation +safety check. + +To abuse the safety check, players are required to get into a location deemed unsafe by Bukkit e.g. be within a chest +or door block. While they are in this block, they accept a teleport request from a player within a different world. Once +the player teleports, Minecraft will recursively search upwards for a safe location, this could eventually land within a +player's skybase. + +Example setup to perform the glitch: http://puu.sh/ng3PC/cf072dcbdb.png +The wanted destination was on top of the emerald block however the player ended on top of the diamond block. +This only is the case if the player is teleporting between worlds. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 670efbe53241a0ae32d618c83da601ccc1f26e37..abbbe1786eb68af02f9d39650aad730ac44aac8a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -205,4 +205,9 @@ public class PaperWorldConfig { + portalCreateRadius = getInt("portal-create-radius", 16); + portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); + } ++ ++ public boolean disableTeleportationSuffocationCheck; ++ private void disableTeleportationSuffocationCheck() { ++ disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 1ad5863dc12b2288a38efed71b7fa4b84296d96d..f2228933719a2325a518be15237fedf56c994d1f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -863,7 +863,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + if (fromWorld == toWorld) { + entity.playerConnection.teleport(to); + } else { +- server.getHandle().moveToWorld(entity, toWorld, true, to, true); ++ server.getHandle().moveToWorld(entity, toWorld, true, to, !toWorld.paperConfig.disableTeleportationSuffocationCheck); // Paper + } + return true; + } diff --git a/patches/server-unmapped/0055-Add-exception-reporting-event.patch b/patches/server-unmapped/0055-Add-exception-reporting-event.patch new file mode 100644 index 0000000000..b032c03199 --- /dev/null +++ b/patches/server-unmapped/0055-Add-exception-reporting-event.patch @@ -0,0 +1,264 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joseph Hirschfeld +Date: Thu, 3 Mar 2016 03:15:41 -0600 +Subject: [PATCH] Add exception reporting event + + +diff --git a/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f699ce18ca044f813e194ef2786b7ea853ea86e7 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java +@@ -0,0 +1,38 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Preconditions; ++import org.bukkit.craftbukkit.scheduler.CraftTask; ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerSchedulerException; ++ ++/** ++ * Reporting wrapper to catch exceptions not natively ++ */ ++public class ServerSchedulerReportingWrapper implements Runnable { ++ ++ private final CraftTask internalTask; ++ ++ public ServerSchedulerReportingWrapper(CraftTask internalTask) { ++ this.internalTask = Preconditions.checkNotNull(internalTask, "internalTask"); ++ } ++ ++ @Override ++ public void run() { ++ try { ++ internalTask.run(); ++ } catch (RuntimeException e) { ++ internalTask.getOwner().getServer().getPluginManager().callEvent( ++ new ServerExceptionEvent(new ServerSchedulerException(e, internalTask)) ++ ); ++ throw e; ++ } catch (Throwable t) { ++ internalTask.getOwner().getServer().getPluginManager().callEvent( ++ new ServerExceptionEvent(new ServerSchedulerException(t, internalTask)) ++ ); //Do not rethrow, since it is not permitted with Runnable#run ++ } ++ } ++ ++ public CraftTask getInternalTask() { ++ return internalTask; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 788a45d5426f0752509442aec2d28b1f32f63cb1..2511fbe7aa5ff1ace71b513d2938975e388295c6 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -815,6 +815,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return true; + } catch (Exception exception) { + PlayerChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception); ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper + return false; + } + } +diff --git a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java +index 107979178e8be5ee6cf885d42f992fabf3bd00b0..8a343a857dc4661ba256e39cf391dd2c7a1cc970 100644 +--- a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java ++++ b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java +@@ -1,5 +1,6 @@ + package net.minecraft.server.players; + ++import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.io.Files; +@@ -363,6 +364,7 @@ public class NameReferencingFileConverter { + root = NBTCompressedStreamTools.a(new java.io.FileInputStream(file5)); + } catch (Exception exception) { + exception.printStackTrace(); ++ ServerInternalException.reportInternalException(exception); // Paper + } + + if (root != null) { +@@ -376,6 +378,7 @@ public class NameReferencingFileConverter { + NBTCompressedStreamTools.a(root, new java.io.FileOutputStream(file2)); + } catch (Exception exception) { + exception.printStackTrace(); ++ ServerInternalException.reportInternalException(exception); // Paper + } + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java +index 928ca3189af1ddaba797628a087cd6c6a9016f5c..eaa97eb11d893266253fb108249ced1e0e96a4dc 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.entity.ai.village; + ++import com.destroystokyo.paper.exception.ServerInternalException; ++ + import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.core.BaseBlockPosition; +@@ -119,6 +121,7 @@ public class VillageSiege implements MobSpawner { + entityzombie.prepare(worldserver, worldserver.getDamageScaler(entityzombie.getChunkCoordinates()), EnumMobSpawn.EVENT, (GroupDataEntity) null, (NBTTagCompound) null); + } catch (Exception exception) { + VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception); ++ ServerInternalException.reportInternalException(exception); // Paper + return; + } + +diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +index 2d02b2fc502a0f7e541f7943ed647ff7177acee8..fd0595fd584046326eccacdf0a6afe40c5e84eed 100644 +--- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java ++++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +@@ -301,6 +301,7 @@ public final class SpawnerCreature { + } + } catch (Exception exception) { + SpawnerCreature.LOGGER.warn("Failed to create mob", exception); ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper + return null; + } + } +@@ -407,6 +408,7 @@ public final class SpawnerCreature { + entity = biomesettingsmobs_c.c.a((World) worldaccess.getMinecraftWorld()); + } catch (Exception exception) { + SpawnerCreature.LOGGER.warn("Failed to create mob", exception); ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper + continue; + } + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 33469b719d679c65d4bcb8366008e6e107eb3a0b..01cb0c8dd9875986e0c08371e876f0dba3f0cf5a 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -1,5 +1,10 @@ + package net.minecraft.world.level; + ++import co.aikar.timings.Timing; ++import co.aikar.timings.Timings; ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerInternalException; ++import com.google.common.base.MoreObjects; + import com.google.common.collect.Lists; + import com.mojang.serialization.Codec; + import java.io.IOException; +@@ -737,8 +742,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + gameprofilerfiller.exit(); + } catch (Throwable throwable) { + // Paper start - Prevent tile entity and entity crashes +- System.err.println("TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ()); ++ String msg = "TileEntity threw exception at " + tileentity.getWorld().getWorld().getName() + ":" + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ(); ++ System.err.println(msg); + throwable.printStackTrace(); ++ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); ++ // Paper end + tilesThisCycle--; + this.tileEntityListTick.remove(tileTickPosition--); + continue; +@@ -808,8 +816,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + consumer.accept(entity); + } catch (Throwable throwable) { + // Paper start - Prevent tile entity and entity crashes +- System.err.println("Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ()); ++ String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ(); ++ System.err.println(msg); + throwable.printStackTrace(); ++ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); + entity.dead = true; + return; + // Paper end +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index a2d80c2c8e4f080f60746548f75631c5946ba8e2..4b3de29b1a6e9d75b28962073c62bbe8d666165f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.chunk; + ++import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; + import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +@@ -655,10 +656,15 @@ public class Chunk implements IChunkAccess { + this.tileEntities.remove(blockposition); + // Paper end + } else { +- System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ() +- + " (" + getType(blockposition) + ") where there was no entity tile!"); +- System.out.println("Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16)); +- new Exception().printStackTrace(); ++ // Paper start ++ ServerInternalException e = new ServerInternalException( ++ "Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getPosition().getX() + "," ++ + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ() ++ + " (" + getType(blockposition) + ") where there was no entity tile!\n" + ++ "Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16)); ++ e.printStackTrace(); ++ ServerInternalException.reportInternalException(e); ++ // Paper end + // CraftBukkit end + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index d1b761055c508a4b80436b50a832e00d0449d8cb..1638f7902290e1bb233f11e5d0bbf83a9e863939 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -265,6 +265,7 @@ public class RegionFile implements AutoCloseable { + return true; + } + } catch (IOException ioexception) { ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper + return false; + } + } +@@ -337,6 +338,7 @@ public class RegionFile implements AutoCloseable { + filechannel.write(bytebuffer); + } catch (Throwable throwable1) { + throwable = throwable1; ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper + throw throwable1; + } finally { + if (filechannel != null) { +diff --git a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java +index 3910daeaa177639fa8055301304634c2014dc20f..d61960d80599dc5e7b70cc990e4b0b174eb6e34e 100644 +--- a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java ++++ b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java +@@ -150,6 +150,7 @@ public class WorldPersistentData { + } + } catch (Throwable throwable6) { + throwable = throwable6; ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper + throw throwable6; + } finally { + if (fileinputstream != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index ffe9cc1011226d604dc5499e7692e9a9a5132b72..9b6d9373abb59a30c2835ca891282d07559281f5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -16,6 +16,9 @@ import java.util.concurrent.atomic.AtomicInteger; + import java.util.concurrent.atomic.AtomicReference; + import java.util.function.Consumer; + import java.util.logging.Level; ++import com.destroystokyo.paper.ServerSchedulerReportingWrapper; ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerSchedulerException; + import org.apache.commons.lang.Validate; + import org.bukkit.plugin.IllegalPluginAccessException; + import org.bukkit.plugin.Plugin; +@@ -419,6 +422,8 @@ public class CraftScheduler implements BukkitScheduler { + msg, + throwable); + } ++ org.bukkit.Bukkit.getServer().getPluginManager().callEvent( ++ new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task))); + // Paper end + } finally { + currentTask = null; +@@ -426,7 +431,7 @@ public class CraftScheduler implements BukkitScheduler { + parsePending(); + } else { + debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); +- executor.execute(task); ++ executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper + // We don't need to parse pending + // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) + } diff --git a/patches/server-unmapped/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/patches/server-unmapped/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch new file mode 100644 index 0000000000..e8a68b30bb --- /dev/null +++ b/patches/server-unmapped/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Tue, 8 Mar 2016 18:28:43 -0800 +Subject: [PATCH] Don't nest if we don't need to when cerealising text + components + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java +index edae451a54bfcd6b54e89c1619fb112a7763eb3b..f6a1c5ac9acb34b1ef2262721adbbb1a5b0feaf7 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java +@@ -40,7 +40,14 @@ public class PacketPlayOutChat implements Packet { + // Paper end + // Spigot start + if (components != null) { +- packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); ++ //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below ++ // Paper start - don't nest if we don't need to so that we can preserve formatting ++ if (this.components.length == 1) { ++ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); ++ } else { ++ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); ++ } ++ // Paper end + } else { + packetdataserializer.a(this.a); + } diff --git a/patches/server-unmapped/0057-Disable-Scoreboards-for-non-players-by-default.patch b/patches/server-unmapped/0057-Disable-Scoreboards-for-non-players-by-default.patch new file mode 100644 index 0000000000..60640fef2b --- /dev/null +++ b/patches/server-unmapped/0057-Disable-Scoreboards-for-non-players-by-default.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 8 Mar 2016 23:25:45 -0500 +Subject: [PATCH] Disable Scoreboards for non players by default + +Entities collision is checking for scoreboards setting. +This is very heavy to do map lookups for every collision to check +this setting. + +So avoid looking up scoreboards and short circuit to the "not on a team" +logic which is most likely to be true. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index abbbe1786eb68af02f9d39650aad730ac44aac8a..3ac2ac3db9b1c271b3c21930bb13716669ff64d3 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -210,4 +210,9 @@ public class PaperWorldConfig { + private void disableTeleportationSuffocationCheck() { + disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); + } ++ ++ public boolean nonPlayerEntitiesOnScoreboards = false; ++ private void nonPlayerEntitiesOnScoreboards() { ++ nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index caae8bdae592a1ae4f99861088458d7461f4c97a..bfced192c1e8fd3fa0250a0f93adfc061d7e71e5 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2289,6 +2289,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + @Nullable + public ScoreboardTeamBase getScoreboardTeam() { ++ if (!this.world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { return null; } // Paper + return this.world.getScoreboard().getPlayerTeam(this.getName()); + } + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 49e95369882847c90ee7417abea6270386cd622f..70211129e6ab2f7cdb975adcb532be595bc3834f 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -741,6 +741,7 @@ public abstract class EntityLiving extends Entity { + if (nbttagcompound.hasKeyOfType("Team", 8)) { + String s = nbttagcompound.getString("Team"); + ScoreboardTeam scoreboardteam = this.world.getScoreboard().getTeam(s); ++ if (!world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { scoreboardteam = null; } // Paper + boolean flag = scoreboardteam != null && this.world.getScoreboard().addPlayerToTeam(this.getUniqueIDString(), scoreboardteam); + + if (!flag) { diff --git a/patches/server-unmapped/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/server-unmapped/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch new file mode 100644 index 0000000000..6885002825 --- /dev/null +++ b/patches/server-unmapped/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: mrapple +Date: Sun, 25 Nov 2012 13:43:39 -0600 +Subject: [PATCH] Add methods for working with arrows stuck in living entities + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index d863fc9fa6b932b76a89871a09378a9c0697c108..c654026587bc9bf77b39f59a0c89991ac581da1e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -689,4 +689,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + getHandle().persistentInvisibility = invisible; + getHandle().setFlag(5, invisible); + } ++ ++ // Paper start ++ @Override ++ public int getArrowsStuck() { ++ return getHandle().getArrowCount(); ++ } ++ ++ @Override ++ public void setArrowsStuck(int arrows) { ++ getHandle().setArrowCount(arrows); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0059-Complete-resource-pack-API.patch b/patches/server-unmapped/0059-Complete-resource-pack-API.patch new file mode 100644 index 0000000000..396e787eb7 --- /dev/null +++ b/patches/server-unmapped/0059-Complete-resource-pack-API.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 4 Apr 2015 23:17:52 -0400 +Subject: [PATCH] Complete resource pack API + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 865d8efa2d480ae7edc286e3e79f2997a191ee5c..af0a7dc9464e1acf1451f45464bab8546207950e 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1605,7 +1605,11 @@ public class PlayerConnection implements PacketListenerPlayIn { + // CraftBukkit start + public void a(PacketPlayInResourcePackStatus packetplayinresourcepackstatus) { + PlayerConnectionUtils.ensureMainThread(packetplayinresourcepackstatus, this, this.player.getWorldServer()); +- this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()])); ++ // Paper start ++ PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()]; ++ player.getBukkitEntity().setResourcePackStatus(packStatus); ++ this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), packStatus)); ++ // Paper end + } + // CraftBukkit end + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index f2228933719a2325a518be15237fedf56c994d1f..ed5680e6e0fcfbaf948bdede98d206cff2b26467 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -138,6 +138,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + private double health = 20; + private boolean scaledHealth = false; + private double healthScale = 20; ++ // Paper start ++ private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; ++ private String resourcePackHash; ++ // Paper end + + public CraftPlayer(CraftServer server, EntityPlayer entity) { + super(server, entity); +@@ -1874,6 +1878,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public boolean getAffectsSpawning() { + return this.getHandle().affectsSpawning; + } ++ ++ @Override ++ public void setResourcePack(String url, String hash) { ++ Validate.notNull(url, "Resource pack URL cannot be null"); ++ Validate.notNull(hash, "Hash cannot be null"); ++ this.getHandle().setResourcePack(url, hash); ++ } ++ ++ @Override ++ public org.bukkit.event.player.PlayerResourcePackStatusEvent.Status getResourcePackStatus() { ++ return this.resourcePackStatus; ++ } ++ ++ @Override ++ public String getResourcePackHash() { ++ return this.resourcePackHash; ++ } ++ ++ @Override ++ public boolean hasResourcePack() { ++ return this.resourcePackStatus == org.bukkit.event.player.PlayerResourcePackStatusEvent.Status.SUCCESSFULLY_LOADED; ++ } ++ ++ public void setResourcePackStatus(org.bukkit.event.player.PlayerResourcePackStatusEvent.Status status) { ++ this.resourcePackStatus = status; ++ } + // Paper end + + @Override diff --git a/patches/server-unmapped/0060-Chunk-Save-Reattempt.patch b/patches/server-unmapped/0060-Chunk-Save-Reattempt.patch new file mode 100644 index 0000000000..03f01b1583 --- /dev/null +++ b/patches/server-unmapped/0060-Chunk-Save-Reattempt.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 4 Mar 2013 23:46:10 -0500 +Subject: [PATCH] Chunk Save Reattempt + +We commonly have "Stream Closed" errors on chunk saving, so this code should re-try to save the chunk in the event of failure and hopefully prevent rollbacks. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 1638f7902290e1bb233f11e5d0bbf83a9e863939..4bf3e0cb4602d33a2e00c502b1dd212032b22a8f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -265,7 +265,7 @@ public class RegionFile implements AutoCloseable { + return true; + } + } catch (IOException ioexception) { +- com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioexception); // Paper - we want the upper try/catch to retry this + return false; + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +index de125077656f249d5cf9b76f07981b55e690e015..8310dd6bfc04b8ac0a51545baa3a264e6cb42eac 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +@@ -11,6 +11,7 @@ import java.io.IOException; + import javax.annotation.Nullable; + import net.minecraft.nbt.NBTCompressedStreamTools; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.util.ExceptionSuppressor; + import net.minecraft.world.level.ChunkCoordIntPair; + +@@ -92,6 +93,7 @@ public final class RegionFileCache implements AutoCloseable { + + protected void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { + RegionFile regionfile = this.getFile(chunkcoordintpair, false); // CraftBukkit ++ int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper + DataOutputStream dataoutputstream = regionfile.c(chunkcoordintpair); + Throwable throwable = null; + +@@ -115,6 +117,18 @@ public final class RegionFileCache implements AutoCloseable { + + } + ++ // Paper start ++ return; ++ } catch (Exception ex) { ++ laste = ex; ++ } ++ } ++ ++ if (laste != null) { ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(laste); ++ MinecraftServer.LOGGER.error("Failed to save chunk", laste); ++ } ++ // Paper end + } + + public void close() throws IOException { diff --git a/patches/server-unmapped/0061-Default-loading-permissions.yml-before-plugins.patch b/patches/server-unmapped/0061-Default-loading-permissions.yml-before-plugins.patch new file mode 100644 index 0000000000..6ae4874a0a --- /dev/null +++ b/patches/server-unmapped/0061-Default-loading-permissions.yml-before-plugins.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 13:17:38 -0400 +Subject: [PATCH] Default loading permissions.yml before plugins + +Under previous behavior, plugins were not able to check if a player had a permission +if it was defined in permissions.yml. there is no clean way for a plugin to fix that either. + +This will change the order so that by default, permissions.yml loads BEFORE plugins instead of after. + +This gives plugins expected permission checks. + +It also helps improve the expected logic, as servers should set the initial defaults, and then let plugins +modify that. Under the previous logic, plugins were unable (cleanly) override permissions.yml. + +A config option has been added for those who depend on the previous behavior, but I don't expect that. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 429b74474ced04d8dd8f038b8590b8dfe178bf4d..716f285e67019b8a62922d09c15883c99f9421aa 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -222,4 +222,9 @@ public class PaperConfig { + private static void useDisplayNameInQuit() { + useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); + } ++ ++ public static boolean loadPermsBeforePlugins = true; ++ private static void loadPermsBeforePlugins() { ++ loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 22b4dec4944b7f823996645af95fbef2d1d8a83b..6eec60b5739edb8f7278608e525b38bdac15bba8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -398,6 +398,7 @@ public final class CraftServer implements Server { + if (type == PluginLoadOrder.STARTUP) { + helpMap.clear(); + helpMap.initializeGeneralTopics(); ++ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper + } + + Plugin[] plugins = pluginManager.getPlugins(); +@@ -417,7 +418,7 @@ public final class CraftServer implements Server { + commandMap.registerServerAliases(); + DefaultPermissions.registerCorePermissions(); + CraftDefaultPermissions.registerCorePermissions(); +- loadCustomPermissions(); ++ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper + helpMap.initializeCommands(); + syncCommands(); + } diff --git a/patches/server-unmapped/0062-Allow-Reloading-of-Custom-Permissions.patch b/patches/server-unmapped/0062-Allow-Reloading-of-Custom-Permissions.patch new file mode 100644 index 0000000000..46a0159c74 --- /dev/null +++ b/patches/server-unmapped/0062-Allow-Reloading-of-Custom-Permissions.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William +Date: Fri, 18 Mar 2016 03:30:17 -0400 +Subject: [PATCH] Allow Reloading of Custom Permissions + +https://github.com/PaperMC/Paper/issues/49 + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 6eec60b5739edb8f7278608e525b38bdac15bba8..6d66a899912bfab2ce610fb6fb2dbec87cbb5790 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2253,5 +2253,23 @@ public final class CraftServer implements Server { + } + return this.adventure$audiences; + } ++ ++ @Override ++ public void reloadPermissions() { ++ pluginManager.clearPermissions(); ++ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); ++ for (Plugin plugin : pluginManager.getPlugins()) { ++ for (Permission perm : plugin.getDescription().getPermissions()) { ++ try { ++ pluginManager.addPermission(perm); ++ } catch (IllegalArgumentException ex) { ++ getLogger().log(Level.WARNING, "Plugin " + plugin.getDescription().getFullName() + " tried to register permission '" + perm.getName() + "' but it's already registered", ex); ++ } ++ } ++ } ++ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); ++ DefaultPermissions.registerCorePermissions(); ++ CraftDefaultPermissions.registerCorePermissions(); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0063-Remove-Metadata-on-reload.patch b/patches/server-unmapped/0063-Remove-Metadata-on-reload.patch new file mode 100644 index 0000000000..54d6959b3b --- /dev/null +++ b/patches/server-unmapped/0063-Remove-Metadata-on-reload.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 13:50:14 -0400 +Subject: [PATCH] Remove Metadata on reload + +Metadata is not meant to persist reload as things break badly with non primitive types +This will remove metadata on reload so it does not crash everything if a plugin uses it. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 6d66a899912bfab2ce610fb6fb2dbec87cbb5790..e670f484d454f7c706a0ec92c98087fa1373c492 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -871,8 +871,18 @@ public final class CraftServer implements Server { + world.paperConfig.init(); // Paper + } + ++ Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper + pluginManager.clearPlugins(); + commandMap.clearCommands(); ++ ++ // Paper start ++ for (Plugin plugin : pluginClone) { ++ entityMetadata.removeAll(plugin); ++ worldMetadata.removeAll(plugin); ++ playerMetadata.removeAll(plugin); ++ } ++ // Paper end ++ + resetRecipes(); + reloadData(); + org.spigotmc.SpigotConfig.registerCommands(); // Spigot diff --git a/patches/server-unmapped/0064-Handle-Item-Meta-Inconsistencies.patch b/patches/server-unmapped/0064-Handle-Item-Meta-Inconsistencies.patch new file mode 100644 index 0000000000..777dfb5014 --- /dev/null +++ b/patches/server-unmapped/0064-Handle-Item-Meta-Inconsistencies.patch @@ -0,0 +1,331 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 28 May 2015 23:00:19 -0400 +Subject: [PATCH] Handle Item Meta Inconsistencies + +First, Enchantment order would blow away seeing 2 items as the same, +however the Client forces enchantment list in a certain order, as well +as does the /enchant command. Anvils can insert it into forced order, +causing 2 same items to be considered different. + +This change makes unhandled NBT Tags and Enchantments use a sorted tree map, +so they will always be in a consistent order. + +Additionally, the old enchantment API was never updated when ItemMeta +was added, resulting in 2 different ways to modify an items enchantments. + +For consistency, the old API methods now forward to use the +ItemMeta API equivalents, and should deprecate the old API's. + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index f1a780768e3f4bdb43a7ca6d7850befefb71bf57..201ba7250b298f4a91bc45f5954f54ae557305f2 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -9,6 +9,8 @@ import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; + import java.text.DecimalFormat; + import java.text.DecimalFormatSymbols; ++import java.util.Collections; ++import java.util.Comparator; + import java.util.Locale; + import java.util.Objects; + import java.util.Optional; +@@ -120,6 +122,23 @@ public final class ItemStack { + private ShapeDetectorBlock n; + private boolean o; + ++ // Paper start ++ private static final java.util.Comparator enchantSorter = java.util.Comparator.comparing(o -> o.getString("id")); ++ private void processEnchantOrder(NBTTagCompound tag) { ++ if (tag == null || !tag.hasKeyOfType("Enchantments", 9)) { ++ return; ++ } ++ NBTTagList list = tag.getList("Enchantments", 10); ++ if (list.size() < 2) { ++ return; ++ } ++ try { ++ //noinspection unchecked ++ list.sort((Comparator) enchantSorter); // Paper ++ } catch (Exception ignored) {} ++ } ++ // Paper end ++ + public ItemStack(IMaterial imaterial) { + this(imaterial, 1); + } +@@ -162,6 +181,7 @@ public final class ItemStack { + if (nbttagcompound.hasKeyOfType("tag", 10)) { + // CraftBukkit start - make defensive copy as this data may be coming from the save thread + this.tag = (NBTTagCompound) nbttagcompound.getCompound("tag").clone(); ++ processEnchantOrder(this.tag); // Paper + this.getItem().b(this.tag); + // CraftBukkit end + } +@@ -680,6 +700,7 @@ public final class ItemStack { + // Paper end + public void setTag(@Nullable NBTTagCompound nbttagcompound) { + this.tag = nbttagcompound; ++ processEnchantOrder(this.tag); // Paper + if (this.getItem().usesDurability()) { + this.setDamage(this.getDamage()); + } +@@ -770,6 +791,7 @@ public final class ItemStack { + nbttagcompound.setString("id", String.valueOf(IRegistry.ENCHANTMENT.getKey(enchantment))); + nbttagcompound.setShort("lvl", (short) ((byte) i)); + nbttaglist.add(nbttagcompound); ++ processEnchantOrder(nbttagcompound); // Paper + } + + public boolean hasEnchantments() { +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index 275b943a59ef28c831a068987e111e84ebba3bb7..7221ac52c9f66ae0af6f6cbf15c8d47f9c0291a0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -178,28 +178,11 @@ public final class CraftItemStack extends ItemStack { + public void addUnsafeEnchantment(Enchantment ench, int level) { + Validate.notNull(ench, "Cannot add null enchantment"); + +- if (!makeTag(handle)) { +- return; +- } +- NBTTagList list = getEnchantmentList(handle); +- if (list == null) { +- list = new NBTTagList(); +- handle.getTag().set(ENCHANTMENTS.NBT, list); +- } +- int size = list.size(); +- +- for (int i = 0; i < size; i++) { +- NBTTagCompound tag = (NBTTagCompound) list.get(i); +- String id = tag.getString(ENCHANTMENTS_ID.NBT); +- if (id.equals(ench.getKey().toString())) { +- tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level); +- return; +- } +- } +- NBTTagCompound tag = new NBTTagCompound(); +- tag.setString(ENCHANTMENTS_ID.NBT, ench.getKey().toString()); +- tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level); +- list.add(tag); ++ // Paper start - Replace whole method ++ final ItemMeta itemMeta = getItemMeta(); ++ itemMeta.addEnchant(ench, level, true); ++ setItemMeta(itemMeta); ++ // Paper end + } + + static boolean makeTag(net.minecraft.world.item.ItemStack item) { +@@ -216,66 +199,33 @@ public final class CraftItemStack extends ItemStack { + + @Override + public boolean containsEnchantment(Enchantment ench) { +- return getEnchantmentLevel(ench) > 0; ++ return hasItemMeta() && getItemMeta().hasEnchant(ench); // Paper - use meta + } + + @Override + public int getEnchantmentLevel(Enchantment ench) { +- Validate.notNull(ench, "Cannot find null enchantment"); +- if (handle == null) { +- return 0; +- } +- return EnchantmentManager.getEnchantmentLevel(CraftEnchantment.getRaw(ench), handle); ++ return hasItemMeta() ? getItemMeta().getEnchantLevel(ench) : 0; // Paper - replace entire method with meta + } + + @Override + public int removeEnchantment(Enchantment ench) { + Validate.notNull(ench, "Cannot remove null enchantment"); + +- NBTTagList list = getEnchantmentList(handle), listCopy; +- if (list == null) { +- return 0; +- } +- int index = Integer.MIN_VALUE; +- int level = Integer.MIN_VALUE; +- int size = list.size(); +- +- for (int i = 0; i < size; i++) { +- NBTTagCompound enchantment = (NBTTagCompound) list.get(i); +- String id = enchantment.getString(ENCHANTMENTS_ID.NBT); +- if (id.equals(ench.getKey().toString())) { +- index = i; +- level = 0xffff & enchantment.getShort(ENCHANTMENTS_LVL.NBT); +- break; +- } +- } +- +- if (index == Integer.MIN_VALUE) { +- return 0; +- } +- if (size == 1) { +- handle.getTag().remove(ENCHANTMENTS.NBT); +- if (handle.getTag().isEmpty()) { +- handle.setTag(null); +- } +- return level; +- } +- +- // This is workaround for not having an index removal +- listCopy = new NBTTagList(); +- for (int i = 0; i < size; i++) { +- if (i != index) { +- listCopy.add(list.get(i)); +- } ++ // Paper start - replace entire method ++ final ItemMeta itemMeta = getItemMeta(); ++ int level = itemMeta.getEnchantLevel(ench); ++ if (level > 0) { ++ itemMeta.removeEnchant(ench); ++ setItemMeta(itemMeta); + } +- handle.getTag().set(ENCHANTMENTS.NBT, listCopy); ++ // Paper end + + return level; + } + + @Override + public Map getEnchantments() { +- return getEnchantments(handle); ++ return hasItemMeta() ? getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta + } + + 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 7a11b2ddfa4244459253c918315aaab78ef2eb4a..57a6e66866ea82caccbbbfd55948a081f50f6bbe 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; + import com.google.common.collect.ImmutableMap; + import com.google.common.collect.ImmutableMultimap; + import com.google.common.collect.LinkedHashMultimap; ++import com.google.common.collect.ImmutableSortedMap; // Paper + import com.google.common.collect.Lists; + import com.google.common.collect.Multimap; + import com.google.common.collect.SetMultimap; +@@ -22,6 +23,7 @@ import java.lang.reflect.InvocationTargetException; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collection; ++import java.util.Comparator; // Paper + import java.util.EnumSet; + import java.util.HashMap; + import java.util.Iterator; +@@ -32,6 +34,7 @@ import java.util.Map; + import java.util.NoSuchElementException; + import java.util.Objects; + import java.util.Set; ++import java.util.TreeMap; // Paper + import java.util.logging.Level; + import java.util.logging.Logger; + import javax.annotation.Nonnull; +@@ -271,7 +274,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + private List lore; // null and empty are two different states internally + private Integer customModelData; + private NBTTagCompound blockData; +- private Map enchantments; ++ private EnchantmentMap enchantments; // Paper + private Multimap attributeModifiers; + private int repairCost; + private int hideFlag; +@@ -282,7 +285,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); + + private NBTTagCompound internalTag; +- private final Map unhandledTags = new HashMap(); ++ private final Map unhandledTags = new TreeMap<>(); // Paper + private CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); + + private int version = CraftMagicNumbers.INSTANCE.getDataVersion(); // Internal use only +@@ -303,7 +306,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + this.blockData = meta.blockData; + + if (meta.enchantments != null) { // Spigot +- this.enchantments = new LinkedHashMap(meta.enchantments); ++ this.enchantments = new EnchantmentMap(meta.enchantments); // Paper + } + + if (meta.hasAttributeModifiers()) { +@@ -386,13 +389,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + } + +- static Map buildEnchantments(NBTTagCompound tag, ItemMetaKey key) { ++ static EnchantmentMap buildEnchantments(NBTTagCompound tag, ItemMetaKey key) { // Paper + if (!tag.hasKey(key.NBT)) { + return null; + } + + NBTTagList ench = tag.getList(key.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); +- Map enchantments = new LinkedHashMap(ench.size()); ++ EnchantmentMap enchantments = new EnchantmentMap(); // Paper + + for (int i = 0; i < ench.size(); i++) { + String id = ((NBTTagCompound) ench.get(i)).getString(ENCHANTMENTS_ID.NBT); +@@ -545,13 +548,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + } + +- static Map buildEnchantments(Map map, ItemMetaKey key) { ++ static EnchantmentMap buildEnchantments(Map map, ItemMetaKey key) { // Paper + Map ench = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); + if (ench == null) { + return null; + } + +- Map enchantments = new LinkedHashMap(ench.size()); ++ EnchantmentMap enchantments = new EnchantmentMap(); // Paper + for (Map.Entry entry : ench.entrySet()) { + // Doctor older enchants + String enchantKey = entry.getKey().toString(); +@@ -827,14 +830,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + + @Override + public Map getEnchants() { +- return hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); ++ return hasEnchants() ? ImmutableSortedMap.copyOfSorted(enchantments) : ImmutableMap.of(); // Paper + } + + @Override + public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { + Validate.notNull(ench, "Enchantment cannot be null"); + if (enchantments == null) { +- enchantments = new LinkedHashMap(4); ++ enchantments = new EnchantmentMap(); // Paper + } + + if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { +@@ -1215,7 +1218,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + clone.customModelData = this.customModelData; + clone.blockData = this.blockData; + if (this.enchantments != null) { +- clone.enchantments = new LinkedHashMap(this.enchantments); ++ clone.enchantments = new EnchantmentMap(this.enchantments); // Paper + } + if (this.hasAttributeModifiers()) { + clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); +@@ -1447,4 +1450,22 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return HANDLED_TAGS; + } + } ++ ++ // Paper start ++ private static class EnchantmentMap extends TreeMap { ++ private EnchantmentMap(Map enchantments) { ++ this(); ++ putAll(enchantments); ++ } ++ ++ private EnchantmentMap() { ++ super(Comparator.comparing(o -> o.getKey().toString())); ++ } ++ ++ public EnchantmentMap clone() { ++ return (EnchantmentMap) super.clone(); ++ } ++ } ++ // Paper end ++ + } diff --git a/patches/server-unmapped/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/patches/server-unmapped/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch new file mode 100644 index 0000000000..1aea311bfb --- /dev/null +++ b/patches/server-unmapped/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 15:12:22 -0400 +Subject: [PATCH] Configurable Non Player Arrow Despawn Rate + +Can set a much shorter despawn rate for arrows that players can not pick up. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3ac2ac3db9b1c271b3c21930bb13716669ff64d3..3c78d3234054ce2dc46ef77decb6adb0cbd10620 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -215,4 +215,19 @@ public class PaperWorldConfig { + private void nonPlayerEntitiesOnScoreboards() { + nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); + } ++ ++ public int nonPlayerArrowDespawnRate = -1; ++ public int creativeArrowDespawnRate = -1; ++ private void nonPlayerArrowDespawnRate() { ++ nonPlayerArrowDespawnRate = getInt("non-player-arrow-despawn-rate", -1); ++ if (nonPlayerArrowDespawnRate == -1) { ++ nonPlayerArrowDespawnRate = spigotConfig.arrowDespawnRate; ++ } ++ creativeArrowDespawnRate = getInt("creative-arrow-despawn-rate", -1); ++ if (creativeArrowDespawnRate == -1) { ++ creativeArrowDespawnRate = spigotConfig.arrowDespawnRate; ++ } ++ log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); ++ log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +index 04af85e0ccb7a98e0796afcdcce33f8595b1db8c..7868259a94766a6100d7b278c4296dde0a7f9397 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +@@ -283,7 +283,7 @@ public abstract class EntityArrow extends IProjectile { + + protected void h() { + ++this.despawnCounter; +- if (this.despawnCounter >= ((this instanceof EntityThrownTrident) ? world.spigotConfig.tridentDespawnRate : world.spigotConfig.arrowDespawnRate)) { // Spigot ++ if (this.despawnCounter >= (fromPlayer == PickupStatus.CREATIVE_ONLY ? world.paperConfig.creativeArrowDespawnRate : (fromPlayer == PickupStatus.DISALLOWED ? world.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof EntityThrownTrident) ? world.spigotConfig.tridentDespawnRate : world.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? + this.die(); + } + diff --git a/patches/server-unmapped/0066-Add-World-Util-Methods.patch b/patches/server-unmapped/0066-Add-World-Util-Methods.patch new file mode 100644 index 0000000000..ff0b627ecc --- /dev/null +++ b/patches/server-unmapped/0066-Add-World-Util-Methods.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Mar 2016 20:16:03 -0400 +Subject: [PATCH] Add World Util Methods + +Methods that can be used for other patches to help improve logic. + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index a1769df6a3f6150d322f145199caba3839871dff..3ea4ec748c229031a5f0d973988bb20e55679971 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -197,7 +197,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + public final Convertable.ConversionSession convertable; + public final UUID uuid; + +- public Chunk getChunkIfLoaded(int x, int z) { ++ @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkProvider.getChunkAt(x, z, false); + } + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 01cb0c8dd9875986e0c08371e876f0dba3f0cf5a..a570998e4ef6c3ff83403881bf1d24c8cbcfcf67 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -297,11 +297,27 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + } + + @Override +- public Fluid getFluidIfLoaded(BlockPosition blockposition) { ++ public final Fluid getFluidIfLoaded(BlockPosition blockposition) { + IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); + + return chunk == null ? null : chunk.getFluid(blockposition); + } ++ ++ public final boolean isLoadedAndInBounds(BlockPosition blockposition) { // Paper - final for inline ++ return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; ++ } ++ ++ public Chunk getChunkIfLoaded(int x, int z) { // Overridden in WorldServer for ABI compat which has final ++ return ((WorldServer) this).getChunkProvider().getChunkAtIfLoadedImmediately(x, z); ++ } ++ public final Chunk getChunkIfLoaded(BlockPosition blockposition) { ++ return ((WorldServer) this).getChunkProvider().getChunkAtIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ } ++ ++ // reduces need to do isLoaded before getType ++ public final IBlockData getTypeIfLoadedAndInBounds(BlockPosition blockposition) { ++ return getWorldBorder().isInBounds(blockposition) ? getTypeIfLoaded(blockposition) : null; ++ } + // Paper end + + @Override +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index 2bb03f1cb9671a7754a68059219f783d4508eeb9..f16c76df5d7b184d57f4cc397f069eac9cc430cb 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -31,6 +31,7 @@ public class WorldBorder { + + public WorldBorder() {} + ++ public final boolean isInBounds(BlockPosition blockposition) { return this.a(blockposition); } // Paper - OBFHELPER + public boolean a(BlockPosition blockposition) { + return (double) (blockposition.getX() + 1) > this.e() && (double) blockposition.getX() < this.g() && (double) (blockposition.getZ() + 1) > this.f() && (double) blockposition.getZ() < this.h(); + } diff --git a/patches/server-unmapped/0067-Custom-replacement-for-eaten-items.patch b/patches/server-unmapped/0067-Custom-replacement-for-eaten-items.patch new file mode 100644 index 0000000000..bf2af97bfc --- /dev/null +++ b/patches/server-unmapped/0067-Custom-replacement-for-eaten-items.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sun, 21 Jun 2015 15:07:20 -0400 +Subject: [PATCH] Custom replacement for eaten items + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 70211129e6ab2f7cdb975adcb532be595bc3834f..759592fc6a4654c0760ff8a1d7f3b87c364b045a 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -3205,9 +3205,10 @@ public abstract class EntityLiving extends Entity { + this.b(this.activeItem, 16); + // CraftBukkit start - fire PlayerItemConsumeEvent + ItemStack itemstack; ++ PlayerItemConsumeEvent event = null; // Paper + if (this instanceof EntityPlayer) { + org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.activeItem); +- PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); ++ event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); // Paper + world.getServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { +@@ -3221,6 +3222,13 @@ public abstract class EntityLiving extends Entity { + } else { + itemstack = this.activeItem.a(this.world, this); + } ++ ++ // Paper start - save the default replacement item and change it if necessary ++ final ItemStack defaultReplacement = itemstack; ++ if (event != null && event.getReplacement() != null) { ++ itemstack = CraftItemStack.asNMSCopy(event.getReplacement()); ++ } ++ // Paper end + // CraftBukkit end + + if (itemstack != this.activeItem) { +@@ -3228,6 +3236,11 @@ public abstract class EntityLiving extends Entity { + } + + this.clearActiveItem(); ++ // Paper start - if the replacement is anything but the default, update the client inventory ++ if (this instanceof EntityPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { ++ ((EntityPlayer) this).getBukkitEntity().updateInventory(); ++ } ++ // Paper end + } + + } diff --git a/patches/server-unmapped/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/patches/server-unmapped/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch new file mode 100644 index 0000000000..a64c157fce --- /dev/null +++ b/patches/server-unmapped/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 27 Sep 2015 01:18:02 -0400 +Subject: [PATCH] handle NaN health/absorb values and repair bad data + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 759592fc6a4654c0760ff8a1d7f3b87c364b045a..375284b7e321cb03a7a30aedea165ca7a2fd1091 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -702,7 +702,13 @@ public abstract class EntityLiving extends Entity { + + @Override + public void loadData(NBTTagCompound nbttagcompound) { +- this.setAbsorptionHearts(nbttagcompound.getFloat("AbsorptionAmount")); ++ // Paper start - jvm keeps optimizing the setter ++ float absorptionAmount = nbttagcompound.getFloat("AbsorptionAmount"); ++ if (Float.isNaN(absorptionAmount)) { ++ absorptionAmount = 0; ++ } ++ this.setAbsorptionHearts(absorptionAmount); ++ // Paper end + if (nbttagcompound.hasKeyOfType("Attributes", 9) && this.world != null && !this.world.isClientSide) { + this.getAttributeMap().a(nbttagcompound.getList("Attributes", 10)); + } +@@ -1151,6 +1157,10 @@ public abstract class EntityLiving extends Entity { + } + + public void setHealth(float f) { ++ // Paper start ++ if (Float.isNaN(f)) { f = getMaxHealth(); if (this.valid) { ++ System.err.println("[NAN-HEALTH] " + getName() + " had NaN health set"); ++ } } // Paper end + // CraftBukkit start - Handle scaled health + if (this instanceof EntityPlayer) { + org.bukkit.craftbukkit.entity.CraftPlayer player = ((EntityPlayer) this).getBukkitEntity(); +@@ -3045,7 +3055,7 @@ public abstract class EntityLiving extends Entity { + } + + public void setAbsorptionHearts(float f) { +- if (f < 0.0F) { ++ if (f < 0.0F || Float.isNaN(f)) { // Paper + f = 0.0F; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index ed5680e6e0fcfbaf948bdede98d206cff2b26467..ab7e731cb04a75b829f0cd24d7b94f7ddad166e8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1680,6 +1680,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void setRealHealth(double health) { ++ if (Double.isNaN(health)) {return;} // Paper + this.health = health; + } + diff --git a/patches/server-unmapped/0069-Use-a-Shared-Random-for-Entities.patch b/patches/server-unmapped/0069-Use-a-Shared-Random-for-Entities.patch new file mode 100644 index 0000000000..23a114a451 --- /dev/null +++ b/patches/server-unmapped/0069-Use-a-Shared-Random-for-Entities.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 22 Mar 2016 00:33:47 -0400 +Subject: [PATCH] Use a Shared Random for Entities + +Reduces memory usage and provides ensures more randomness, Especially since a lot of garbage entity objects get created. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index bfced192c1e8fd3fa0250a0f93adfc061d7e71e5..415935739716df3b8b3319aac19519d29aaa5776 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -143,6 +143,21 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; + } + ++ // Paper start ++ public static Random SHARED_RANDOM = new Random() { ++ private boolean locked = false; ++ @Override ++ public synchronized void setSeed(long seed) { ++ if (locked) { ++ LogManager.getLogger().error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable()); ++ } else { ++ super.setSeed(seed); ++ locked = true; ++ } ++ } ++ }; ++ // Paper end ++ + private CraftEntity bukkitEntity; + + public CraftEntity getBukkitEntity() { +@@ -272,7 +287,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.x = Vec3D.ORIGIN; + this.am = 1.0F; + this.an = 1.0F; +- this.random = new Random(); ++ this.random = SHARED_RANDOM; // Paper + this.fireTicks = -this.getMaxFireTicks(); + this.M = new Object2DoubleArrayMap(2); + this.justCreated = true; diff --git a/patches/server-unmapped/0070-Configurable-spawn-chances-for-skeleton-horses.patch b/patches/server-unmapped/0070-Configurable-spawn-chances-for-skeleton-horses.patch new file mode 100644 index 0000000000..768d4bc95d --- /dev/null +++ b/patches/server-unmapped/0070-Configurable-spawn-chances-for-skeleton-horses.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 22 Mar 2016 12:04:28 -0500 +Subject: [PATCH] Configurable spawn chances for skeleton horses + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3c78d3234054ce2dc46ef77decb6adb0cbd10620..cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -230,4 +230,12 @@ public class PaperWorldConfig { + log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); + log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); + } ++ ++ public double skeleHorseSpawnChance; ++ private void skeleHorseSpawnChance() { ++ skeleHorseSpawnChance = getDouble("skeleton-horse-thunder-spawn-chance", 0.01D); ++ if (skeleHorseSpawnChance < 0) { ++ skeleHorseSpawnChance = 0.01D; // Vanilla value ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 3ea4ec748c229031a5f0d973988bb20e55679971..5cd864e58b85fa163489557437f5c2eec9f008b7 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -590,7 +590,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + blockposition = this.a(this.a(j, 0, k, 15)); + if (this.isRainingAt(blockposition)) { + DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); +- boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * 0.01D; ++ boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper + + if (flag1) { + EntityHorseSkeleton entityhorseskeleton = (EntityHorseSkeleton) EntityTypes.SKELETON_HORSE.a((World) this); diff --git a/patches/server-unmapped/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/patches/server-unmapped/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch new file mode 100644 index 0000000000..9f9e1ddd60 --- /dev/null +++ b/patches/server-unmapped/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch @@ -0,0 +1,206 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 02:07:55 -0600 +Subject: [PATCH] Optimize isValidLocation, getType and getBlockData for + inlining + +Hot methods, so reduce # of instructions for the method. + +Move is valid location test to the BlockPosition class so that it can access local variables. + +Replace all calls to the new place to the unnecessary forward. + +Optimize getType and getBlockData to manually inline and optimize the calls + +diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java +index 25fdd55a7548cfaa45a541ad77f22f33c33e7471..4b56683336fdab06804efdc8ca1f7c130b77291f 100644 +--- a/src/main/java/net/minecraft/core/BaseBlockPosition.java ++++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java +@@ -22,6 +22,15 @@ public class BaseBlockPosition implements Comparable { + private int b;public final void setY(final int y) { this.b = y; } // Paper - OBFHELPER + private int e;public final void setZ(final int z) { this.e = z; } // Paper - OBFHELPER + ++ // Paper start ++ public boolean isValidLocation() { ++ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && getY() >= 0 && getY() < 256; ++ } ++ public boolean isInvalidYLocation() { ++ return b < 0 || b >= 256; ++ } ++ // Paper end ++ + public BaseBlockPosition(int i, int j, int k) { + this.a = i; + this.b = j; +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index a570998e4ef6c3ff83403881bf1d24c8cbcfcf67..a22be13b097052b2a88707c9436b88c84298e46b 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -239,7 +239,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + } + + public static boolean isValidLocation(BlockPosition blockposition) { +- return !isOutsideWorld(blockposition) && D(blockposition); ++ return blockposition.isValidLocation(); // Paper - use better/optimized check + } + + public static boolean l(BlockPosition blockposition) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index 4b3de29b1a6e9d75b28962073c62bbe8d666165f..fdc491f978560c394eec22116572585f9bbdec9f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -348,12 +348,27 @@ public class Chunk implements IChunkAccess { + return this.sections; + } + +- @Override ++ // Paper start - Optimize getBlockData to reduce instructions ++ public final IBlockData getBlockData(BlockPosition pos) { return getBlockData(pos.getX(), pos.getY(), pos.getZ()); } // Paper + public IBlockData getType(BlockPosition blockposition) { +- int i = blockposition.getX(); +- int j = blockposition.getY(); +- int k = blockposition.getZ(); ++ return this.getBlockData(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ } ++ ++ public IBlockData getType(final int x, final int y, final int z) { ++ return getBlockData(x, y, z); ++ } ++ public final IBlockData getBlockData(final int x, final int y, final int z) { ++ // Method body / logic copied from below ++ final int i = y >> 4; ++ if (y < 0 || i >= this.sections.length || this.sections[i] == null || this.sections[i].nonEmptyBlockCount == 0) { ++ return Blocks.AIR.getBlockData(); ++ } ++ // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) ++ return this.sections[i].blockIds.a((y & 15) << 8 | (z & 15) << 4 | x & 15); ++ } + ++ public IBlockData getBlockData_unused(int i, int j, int k) { ++ // Paper end + if (this.world.isDebugWorld()) { + IBlockData iblockdata = null; + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java +index 395d21afaabcbd99f9ce0551d647f5db9507a518..89efd0b68b04457e1cd617dcc8bb1a6ea1c4717c 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java +@@ -23,7 +23,7 @@ import net.minecraft.world.phys.AxisAlignedBB; + + public class ChunkEmpty extends Chunk { + +- private static final BiomeBase[] b = (BiomeBase[]) SystemUtils.a((Object) (new BiomeBase[BiomeStorage.a]), (abiomebase) -> { ++ private static final BiomeBase[] b = SystemUtils.a((new BiomeBase[BiomeStorage.a]), (abiomebase) -> { // Paper - decompile error + Arrays.fill(abiomebase, BiomeRegistry.a); + }); + +@@ -31,6 +31,11 @@ public class ChunkEmpty extends Chunk { + super(world, chunkcoordintpair, new BiomeStorage(world.r().b(IRegistry.ay), ChunkEmpty.b)); + } + ++ // Paper start ++ @Override public IBlockData getType(int x, int y, int z) { ++ return Blocks.VOID_AIR.getBlockData(); ++ } ++ // Paper end + @Override + public IBlockData getType(BlockPosition blockposition) { + return Blocks.VOID_AIR.getBlockData(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +index a4e2eb1a753e8fcb48982d78fe80e505bce5c476..eea4a30428293eaf7afbe303a37adec60b44c2b4 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +@@ -13,10 +13,10 @@ public class ChunkSection { + + public static final DataPalette GLOBAL_PALETTE = new DataPaletteGlobal<>(Block.REGISTRY_ID, Blocks.AIR.getBlockData()); + private final int yPos; +- private short nonEmptyBlockCount; ++ short nonEmptyBlockCount; // Paper - package-private + private short tickingBlockCount; + private short e; +- private final DataPaletteBlock blockIds; ++ final DataPaletteBlock blockIds; // Paper - package-private + + public ChunkSection(int i) { + this(i, (short) 0, (short) 0, (short) 0); +@@ -30,8 +30,8 @@ public class ChunkSection { + this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); + } + +- public IBlockData getType(int i, int j, int k) { +- return (IBlockData) this.blockIds.a(i, j, k); ++ public final IBlockData getType(int i, int j, int k) { // Paper ++ return this.blockIds.a(j << 8 | k << 4 | i); // Paper - inline + } + + public Fluid b(int i, int j, int k) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +index e397b871b846c3a90bc75d0e1cf0683b6a3d0ca9..8928157b01bb4f0dfe043732777b33708c23cda7 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java ++++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +@@ -133,7 +133,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { + } + + public T a(int i, int j, int k) { +- return this.a(b(i, j, k)); ++ return this.a(j << 8 | k << 4 | i); // Paper - inline + } + + protected T a(int i) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java +index 2cd04abd72f1135446182ad6294003e526f99a4b..e570dc58efa56bd0aa5ada5575b4054ee38d505e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java +@@ -25,6 +25,7 @@ import org.apache.logging.log4j.LogManager; + + public interface IChunkAccess extends IBlockAccess, IStructureAccess { + ++ IBlockData getType(final int x, final int y, final int z); // Paper + @Nullable + IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag); + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index 7572ca53a5cca8ca5085d18c24048b85dda4daa9..9eeb99a21a6ed7f71ff64cf4cfdff646d31abbcf 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -113,16 +113,18 @@ public class ProtoChunk implements IChunkAccess { + + @Override + public IBlockData getType(BlockPosition blockposition) { +- int i = blockposition.getY(); +- +- if (World.b(i)) { ++ return getType(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ } ++ // Paper start ++ public IBlockData getType(final int x, final int y, final int z) { ++ if (y < 0 || y >= 256) { + return Blocks.VOID_AIR.getBlockData(); + } else { +- ChunkSection chunksection = this.getSections()[i >> 4]; +- +- return ChunkSection.a(chunksection) ? Blocks.AIR.getBlockData() : chunksection.getType(blockposition.getX() & 15, i & 15, blockposition.getZ() & 15); ++ ChunkSection chunksection = this.getSections()[y >> 4]; ++ return chunksection == Chunk.EMPTY_CHUNK_SECTION || chunksection.c() ? Blocks.AIR.getBlockData() : chunksection.getType(x & 15, y & 15, z & 15); + } + } ++ // Paper end + + @Override + public Fluid getFluid(BlockPosition blockposition) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java +index c059d3d055c35b492680556e8605966e2caaf7fd..9351e6ba541d440c485b6e4a3209170c5756e31e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java +@@ -42,6 +42,11 @@ public class ProtoChunkExtension extends ProtoChunk { + public IBlockData getType(BlockPosition blockposition) { + return this.a.getType(blockposition); + } ++ // Paper start ++ public final IBlockData getType(final int x, final int y, final int z) { ++ return this.a.getBlockData(x, y, z); ++ } ++ // Paper end + + @Override + public Fluid getFluid(BlockPosition blockposition) { diff --git a/patches/server-unmapped/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/patches/server-unmapped/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch new file mode 100644 index 0000000000..b10153a490 --- /dev/null +++ b/patches/server-unmapped/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 19:55:45 -0400 +Subject: [PATCH] Only process BlockPhysicsEvent if a plugin has a listener + +Saves on some object allocation and processing when no plugin listens to this + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index ed71de473d461528d74ca5b95c33b97e98128aff..b141c744b8ffbc37b09cb4347c4051a77bb7049e 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1292,6 +1292,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper + + this.methodProfiler.a(() -> { + return worldserver + " " + worldserver.getDimensionKey().a(); +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 5cd864e58b85fa163489557437f5c2eec9f008b7..a82affb9ffd0b2a513dcbf29402e99b49ed95d63 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -196,6 +196,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + private int tickPosition; + public final Convertable.ConversionSession convertable; + public final UUID uuid; ++ public boolean hasPhysicsEvent = true; // Paper + + @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkProvider.getChunkAt(x, z, false); +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index a22be13b097052b2a88707c9436b88c84298e46b..9236e480d21340d4295caa16dae34363e182f483 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -458,7 +458,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + // CraftBukkit start + iblockdata1.b(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam + CraftWorld world = ((WorldServer) this).getWorld(); +- if (world != null) { ++ if (world != null && ((WorldServer)this).hasPhysicsEvent) { // Paper + BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); + this.getServer().getPluginManager().callEvent(event); + +@@ -560,7 +560,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + try { + // CraftBukkit start + CraftWorld world = ((WorldServer) this).getWorld(); +- if (world != null) { ++ if (world != null && ((WorldServer)this).hasPhysicsEvent) { // Paper + BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata), world.getBlockAt(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ())); + this.getServer().getPluginManager().callEvent(event); + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockPlant.java b/src/main/java/net/minecraft/world/level/block/BlockPlant.java +index 33a5c5a4dc1478ab211dbb2e09df87570b06644f..97dfe5c5e3ea1d9691de87ffbf4b1a29a83a65b4 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockPlant.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockPlant.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; + + import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.IBlockAccess; + import net.minecraft.world.level.IWorldReader; +@@ -23,7 +24,7 @@ public class BlockPlant extends Block { + public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { + // CraftBukkit start + if (!iblockdata.canPlace(generatoraccess, blockposition)) { +- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(generatoraccess, blockposition).isCancelled()) { ++ if (!(generatoraccess instanceof WorldServer && ((WorldServer) generatoraccess).hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(generatoraccess, blockposition).isCancelled()) { // Paper + return Blocks.AIR.getBlockData(); + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java b/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java +index ca22187625f7ac6c43b663fd4d66cbf0c943c655..1a5d29ecc9edc52bac14ed5d05ef5376fd5b8a9c 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java +@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; +@@ -83,7 +84,7 @@ public class BlockTallPlant extends BlockPlant { + + protected static void b(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman) { + // CraftBukkit start +- if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { ++ if (((WorldServer)world).hasPhysicsEvent && org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { // Paper + return; + } + // CraftBukkit end diff --git a/patches/server-unmapped/0073-Entity-AddTo-RemoveFrom-World-Events.patch b/patches/server-unmapped/0073-Entity-AddTo-RemoveFrom-World-Events.patch new file mode 100644 index 0000000000..61e53caa2c --- /dev/null +++ b/patches/server-unmapped/0073-Entity-AddTo-RemoveFrom-World-Events.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 20:32:58 -0400 +Subject: [PATCH] Entity AddTo/RemoveFrom World Events + + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index a82affb9ffd0b2a513dcbf29402e99b49ed95d63..24a45e5ac9b17feb528e9a047d1ad1761569ebfa 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1214,7 +1214,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + if (entity instanceof EntityInsentient) { + this.navigators.remove(((EntityInsentient) entity).getNavigation()); + } +- ++ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + entity.valid = false; // CraftBukkit + } + +@@ -1252,6 +1252,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + entity.origin = entity.getBukkitEntity().getLocation(); + } + // Paper end ++ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + } + + } diff --git a/patches/server-unmapped/0074-Configurable-Chunk-Inhabited-Time.patch b/patches/server-unmapped/0074-Configurable-Chunk-Inhabited-Time.patch new file mode 100644 index 0000000000..aec9c86c64 --- /dev/null +++ b/patches/server-unmapped/0074-Configurable-Chunk-Inhabited-Time.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 20:46:14 -0400 +Subject: [PATCH] Configurable Chunk Inhabited Time + +Vanilla stores how long a chunk has been active on a server, and dynamically scales some +aspects of vanilla gameplay to this factor. + +For people who want all chunks to be treated equally, you can chose a fixed value. + +This allows to fine-tune vanilla gameplay. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0..74ba5dbb83c13ce1721619b755036a7864a1fb90 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -238,4 +238,14 @@ public class PaperWorldConfig { + skeleHorseSpawnChance = 0.01D; // Vanilla value + } + } ++ ++ public int fixedInhabitedTime; ++ private void fixedInhabitedTime() { ++ if (PaperConfig.version < 16) { ++ if (!config.getBoolean("world-settings.default.use-chunk-inhabited-timer", true)) config.set("world-settings.default.fixed-chunk-inhabited-time", 0); ++ if (!config.getBoolean("world-settings." + worldName + ".use-chunk-inhabited-timer", true)) config.set("world-settings." + worldName + ".fixed-chunk-inhabited-time", 0); ++ set("use-chunk-inhabited-timer", null); ++ } ++ fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index fdc491f978560c394eec22116572585f9bbdec9f..b6898cd6e6117fef65198db32b98a64c806811d4 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -1022,7 +1022,7 @@ public class Chunk implements IChunkAccess { + + @Override + public long getInhabitedTime() { +- return this.inhabitedTime; ++ return world.paperConfig.fixedInhabitedTime < 0 ? this.inhabitedTime : world.paperConfig.fixedInhabitedTime; // Paper + } + + @Override diff --git a/patches/server-unmapped/0075-EntityPathfindEvent.patch b/patches/server-unmapped/0075-EntityPathfindEvent.patch new file mode 100644 index 0000000000..84caa9a7de --- /dev/null +++ b/patches/server-unmapped/0075-EntityPathfindEvent.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 21:22:26 -0400 +Subject: [PATCH] EntityPathfindEvent + +Fires when an Entity decides to start moving to a location. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java +index 942e03578836524ba746bc37699677eb06cc7803..703d06b2b29f1500301d82df78dc377141085145 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java +@@ -75,7 +75,7 @@ public class Navigation extends NavigationAbstract { + + @Override + public PathEntity a(Entity entity, int i) { +- return this.a(entity.getChunkCoordinates(), i); ++ return this.a(entity.getChunkCoordinates(), entity, i); // Paper - Forward target entity + } + + private int u() { +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +index 8848a7552a0ef3944560a71f71620c6bd0f08c10..58225877ce4f2533c19d34e143ae374dc289bce5 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +@@ -10,6 +10,7 @@ import net.minecraft.core.BaseBlockPosition; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.IPosition; + import net.minecraft.network.protocol.game.PacketDebug; ++import net.minecraft.server.MCUtil; + import net.minecraft.util.MathHelper; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityInsentient; +@@ -28,7 +29,7 @@ import net.minecraft.world.phys.Vec3D; + + public abstract class NavigationAbstract { + +- protected final EntityInsentient a; ++ protected final EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER + protected final World b; + @Nullable + protected PathEntity c; +@@ -115,16 +116,26 @@ public abstract class NavigationAbstract { + + @Nullable + public PathEntity a(BlockPosition blockposition, int i) { +- return this.a(ImmutableSet.of(blockposition), 8, false, i); ++ // Paper start - add target parameter ++ return this.a(blockposition, null, i); ++ } ++ @Nullable public PathEntity a(BlockPosition blockposition, Entity target, int i) { ++ return this.a(ImmutableSet.of(blockposition), target, 8, false, i); ++ // Paper end + } + + @Nullable + public PathEntity a(Entity entity, int i) { +- return this.a(ImmutableSet.of(entity.getChunkCoordinates()), 16, true, i); ++ return this.a(ImmutableSet.of(entity.getChunkCoordinates()), entity, 16, true, i); // Paper + } + + @Nullable ++ // Paper start - Add target + protected PathEntity a(Set set, int i, boolean flag, int j) { ++ return this.a(set, null, i, flag, j); ++ } ++ @Nullable protected PathEntity a(Set set, Entity target, int i, boolean flag, int j) { ++ // Paper end + if (set.isEmpty()) { + return null; + } else if (this.a.locY() < 0.0D) { +@@ -134,6 +145,23 @@ public abstract class NavigationAbstract { + } else if (this.c != null && !this.c.c() && set.contains(this.p)) { + return this.c; + } else { ++ // Paper start - Pathfind event ++ boolean copiedSet = false; ++ for (BlockPosition possibleTarget : set) { ++ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), ++ MCUtil.toLocation(getEntity().world, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { ++ if (!copiedSet) { ++ copiedSet = true; ++ set = new java.util.HashSet<>(set); ++ } ++ // note: since we copy the set this remove call is safe, since we're iterating over the old copy ++ set.remove(possibleTarget); ++ if (set.isEmpty()) { ++ return null; ++ } ++ } ++ } ++ // Paper end + this.b.getMethodProfiler().enter("pathfind"); + float f = (float) this.a.b(GenericAttributes.FOLLOW_RANGE); + BlockPosition blockposition = flag ? this.a.getChunkCoordinates().up() : this.a.getChunkCoordinates(); +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java +index 2e1efe7a048f64d494260d10a4ae5dba86af5e6c..f5664b8c0762f775f3cd106d156eb74b48bcedc2 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java +@@ -37,7 +37,7 @@ public class NavigationFlying extends NavigationAbstract { + + @Override + public PathEntity a(Entity entity, int i) { +- return this.a(entity.getChunkCoordinates(), i); ++ return this.a(entity.getChunkCoordinates(), entity, i); // Paper - Forward target entity + } + + @Override diff --git a/patches/server-unmapped/0076-Sanitise-RegionFileCache-and-make-configurable.patch b/patches/server-unmapped/0076-Sanitise-RegionFileCache-and-make-configurable.patch new file mode 100644 index 0000000000..d60c778cea --- /dev/null +++ b/patches/server-unmapped/0076-Sanitise-RegionFileCache-and-make-configurable.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Antony Riley +Date: Tue, 29 Mar 2016 08:22:55 +0300 +Subject: [PATCH] Sanitise RegionFileCache and make configurable. + +RegionFileCache prior to this patch would close every single open region +file upon reaching a size of 256. +This patch modifies that behaviour so it closes the the least recently +used RegionFile. +The implementation uses a LinkedHashMap as an LRU cache (modified from HashMap). +The maximum size of the RegionFileCache is also made configurable. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 716f285e67019b8a62922d09c15883c99f9421aa..439dcc6effdc91830d2b7ede9063982998b37120 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -227,4 +227,9 @@ public class PaperConfig { + private static void loadPermsBeforePlugins() { + loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); + } ++ ++ public static int regionFileCacheSize = 256; ++ private static void regionFileCacheSize() { ++ regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +index 8310dd6bfc04b8ac0a51545baa3a264e6cb42eac..75b10a3755392870d8f5b51239a09a0e7fd75a42 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +@@ -33,7 +33,7 @@ public final class RegionFileCache implements AutoCloseable { + if (regionfile != null) { + return regionfile; + } else { +- if (this.cache.size() >= 256) { ++ if (this.cache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable + ((RegionFile) this.cache.removeLast()).close(); + } + diff --git a/patches/server-unmapped/0077-Do-not-load-chunks-for-Pathfinding.patch b/patches/server-unmapped/0077-Do-not-load-chunks-for-Pathfinding.patch new file mode 100644 index 0000000000..6086fc3ad7 --- /dev/null +++ b/patches/server-unmapped/0077-Do-not-load-chunks-for-Pathfinding.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 31 Mar 2016 19:17:58 -0400 +Subject: [PATCH] Do not load chunks for Pathfinding + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +index 58225877ce4f2533c19d34e143ae374dc289bce5..d71a6e5991629ce59c8529d7cc8064960e385236 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +@@ -48,7 +48,7 @@ public abstract class NavigationAbstract { + private BlockPosition p; + private int q; + private float r; +- private final Pathfinder s; ++ private final Pathfinder s; public Pathfinder getPathfinder() { return this.s; } // Paper - OBFHELPER + private boolean t; + + public NavigationAbstract(EntityInsentient entityinsentient, World world) { +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java +index 39cd22a820fdc4c75aefb625b45b0c8c6ce1f199..5784be69098805e4d550a0923ac8daa5aada73f9 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java +@@ -20,7 +20,7 @@ public class Pathfinder { + + private final PathPoint[] a = new PathPoint[32]; + private final int b; +- private final PathfinderAbstract c; ++ private final PathfinderAbstract c; public PathfinderAbstract getPathfinder() { return this.c; } // Paper - OBFHELPER + private final Path d = new Path(); + + public Pathfinder(PathfinderAbstract pathfinderabstract, int i) { +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java +index ed9c1dfbc84b9573784e6531186b3cd9513ddf75..d14f2800237c2a80912bf6f2d418a9ba9031070d 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java +@@ -479,7 +479,12 @@ public class PathfinderNormal extends PathfinderAbstract { + for (int j1 = -1; j1 <= 1; ++j1) { + if (l != 0 || j1 != 0) { + blockposition_mutableblockposition.d(i + l, j + i1, k + j1); +- IBlockData iblockdata = iblockaccess.getType(blockposition_mutableblockposition); ++ // Paper start ++ IBlockData iblockdata = iblockaccess.getTypeIfLoaded(blockposition_mutableblockposition); ++ if (iblockdata == null) { ++ pathtype = PathType.BLOCKED; ++ } else { ++ // Paper end + + if (iblockdata.a(Blocks.CACTUS)) { + return PathType.DANGER_CACTUS; +@@ -496,6 +501,7 @@ public class PathfinderNormal extends PathfinderAbstract { + if (iblockaccess.getFluid(blockposition_mutableblockposition).a((Tag) TagsFluid.WATER)) { + return PathType.WATER_BORDER; + } ++ } // Paper + } + } + } +@@ -505,7 +511,8 @@ public class PathfinderNormal extends PathfinderAbstract { + } + + protected static PathType b(IBlockAccess iblockaccess, BlockPosition blockposition) { +- IBlockData iblockdata = iblockaccess.getType(blockposition); ++ IBlockData iblockdata = iblockaccess.getTypeIfLoaded(blockposition); // Paper ++ if (iblockdata == null) return PathType.BLOCKED; // Paper + Block block = iblockdata.getBlock(); + Material material = iblockdata.getMaterial(); + diff --git a/patches/server-unmapped/0078-Add-PlayerUseUnknownEntityEvent.patch b/patches/server-unmapped/0078-Add-PlayerUseUnknownEntityEvent.patch new file mode 100644 index 0000000000..5eeb9183da --- /dev/null +++ b/patches/server-unmapped/0078-Add-PlayerUseUnknownEntityEvent.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 2 Apr 2016 05:09:16 -0400 +Subject: [PATCH] Add PlayerUseUnknownEntityEvent + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java +index 9f3f8568ef9484ba226deaa6429f819c325b7a26..ce63f3e5ac4d1a4311c0ebeb7574d999d45987d9 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java +@@ -11,7 +11,7 @@ import net.minecraft.world.phys.Vec3D; + + public class PacketPlayInUseEntity implements Packet { + +- private int a; ++ private int a; public int getEntityId() { return this.a; } // Paper - add accessor + private PacketPlayInUseEntity.EnumEntityUseAction action; + private Vec3D c; + private EnumHand d; +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index af0a7dc9464e1acf1451f45464bab8546207950e..d3938e1fbab0a01ae5045858b1f421e041b768e2 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2200,6 +2200,16 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + } + } ++ // Paper start - fire event ++ else { ++ this.server.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( ++ this.getPlayer(), ++ packetplayinuseentity.getEntityId(), ++ packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK, ++ packetplayinuseentity.c() == EnumHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND ++ )); ++ } ++ // Paper end + + } + diff --git a/patches/server-unmapped/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch b/patches/server-unmapped/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch new file mode 100644 index 0000000000..c5364da582 --- /dev/null +++ b/patches/server-unmapped/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 2 Apr 2016 20:37:03 -0400 +Subject: [PATCH] Fix reducedDebugInfo not initialized on client + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 46c516b9ff089a3c885d635244942fd5a6ecf132..9d327f1255dd9d6b11840f7bb8ffc302bc33dbcf 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -246,6 +246,7 @@ public abstract class PlayerList { + playerconnection.sendPacket(new PacketPlayOutHeldItemSlot(entityplayer.inventory.itemInHandIndex)); + playerconnection.sendPacket(new PacketPlayOutRecipeUpdate(this.server.getCraftingManager().b())); + playerconnection.sendPacket(new PacketPlayOutTags(this.server.getTagRegistry())); ++ playerconnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, (byte) (worldserver1.getGameRules().getBoolean(GameRules.REDUCED_DEBUG_INFO) ? 22 : 23))); // Paper - fix this rule not being initialized on the client + this.d(entityplayer); + entityplayer.getStatisticManager().c(); + entityplayer.getRecipeBook().a(entityplayer); diff --git a/patches/server-unmapped/0080-Configurable-Grass-Spread-Tick-Rate.patch b/patches/server-unmapped/0080-Configurable-Grass-Spread-Tick-Rate.patch new file mode 100644 index 0000000000..78ce2d0001 --- /dev/null +++ b/patches/server-unmapped/0080-Configurable-Grass-Spread-Tick-Rate.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 Apr 2016 16:28:17 -0400 +Subject: [PATCH] Configurable Grass Spread Tick Rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 74ba5dbb83c13ce1721619b755036a7864a1fb90..db2dddd12f54e6d15916c4cee623676541de37fb 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -248,4 +248,10 @@ public class PaperWorldConfig { + } + fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); + } ++ ++ public int grassUpdateRate = 1; ++ private void grassUpdateRate() { ++ grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); ++ log("Grass Spread Tick Rate: " + grassUpdateRate); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java b/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java +index a98392f06e66959ec1b75df8d2ecf3b5267980af..712596420af83e6e1b9d147ae2fd8d8a1f36e1b9 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java +@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; + import java.util.Random; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsFluid; +@@ -41,6 +42,7 @@ public abstract class BlockDirtSnowSpreadable extends BlockDirtSnow { + + @Override + public void tick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { ++ if (this instanceof BlockGrass && worldserver.paperConfig.grassUpdateRate != 1 && (worldserver.paperConfig.grassUpdateRate < 1 || (MinecraftServer.currentTick + blockposition.hashCode()) % worldserver.paperConfig.grassUpdateRate != 0)) { return; } // Paper + if (!b(iblockdata, (IWorldReader) worldserver, blockposition)) { + // CraftBukkit start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, Blocks.DIRT.getBlockData()).isCancelled()) { diff --git a/patches/server-unmapped/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/patches/server-unmapped/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch new file mode 100644 index 0000000000..d855eabdf8 --- /dev/null +++ b/patches/server-unmapped/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 Apr 2016 17:48:50 -0400 +Subject: [PATCH] Fix Cancelling BlockPlaceEvent triggering physics + + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 9236e480d21340d4295caa16dae34363e182f483..8da8141c2320c0c1a9b95826a9be2dbe22e11c14 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -518,6 +518,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public void b(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1) {} + + public void applyPhysics(BlockPosition blockposition, Block block) { ++ if (captureBlockStates) { return; } // Paper - Cancel all physics during placement + this.a(blockposition.west(), block, blockposition); + this.a(blockposition.east(), block, blockposition); + this.a(blockposition.down(), block, blockposition); diff --git a/patches/server-unmapped/0082-Optimize-DataBits.patch b/patches/server-unmapped/0082-Optimize-DataBits.patch new file mode 100644 index 0000000000..61a9ac3f61 --- /dev/null +++ b/patches/server-unmapped/0082-Optimize-DataBits.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Apr 2016 21:38:58 -0400 +Subject: [PATCH] Optimize DataBits + +Remove Debug checks as these are super hot and causing noticeable hits + +Before: http://i.imgur.com/nQsMzAE.png +After: http://i.imgur.com/nJ46crB.png + +Optimize redundant converting of static fields into an unsigned long each call by precomputing it in ctor + +diff --git a/src/main/java/net/minecraft/util/DataBits.java b/src/main/java/net/minecraft/util/DataBits.java +index 0c0576c8730069fb5364d8383dec8ab7e698658d..c4f3b680512fb15cea01ad12d0a00c6e60bf34b7 100644 +--- a/src/main/java/net/minecraft/util/DataBits.java ++++ b/src/main/java/net/minecraft/util/DataBits.java +@@ -13,8 +13,8 @@ public class DataBits { + private final long d; + private final int e; + private final int f; +- private final int g; +- private final int h; ++ private final int g;private final long g_unsigned; // Paper - referenced in b(int) with 2 Integer.toUnsignedLong calls ++ private final int h;private final long h_unsigned; // Paper + private final int i; + + public DataBits(int i, int j) { +@@ -29,8 +29,8 @@ public class DataBits { + this.f = (char) (64 / i); + int k = 3 * (this.f - 1); + +- this.g = DataBits.a[k + 0]; +- this.h = DataBits.a[k + 1]; ++ this.g = DataBits.a[k + 0]; this.g_unsigned = Integer.toUnsignedLong(this.g); // Paper ++ this.h = DataBits.a[k + 1]; this.h_unsigned = Integer.toUnsignedLong(this.h); // Paper + this.i = DataBits.a[k + 2]; + int l = (j + this.f - 1) / this.f; + +@@ -47,15 +47,15 @@ public class DataBits { + } + + private int b(int i) { +- long j = Integer.toUnsignedLong(this.g); +- long k = Integer.toUnsignedLong(this.h); ++ //long j = Integer.toUnsignedLong(this.g); // Paper ++ //long k = Integer.toUnsignedLong(this.h); // Paper + +- return (int) ((long) i * j + k >> 32 >> this.i); ++ return (int) ((long) i * this.g_unsigned + this.h_unsigned >> 32 >> this.i); // Paper + } + +- public int a(int i, int j) { +- Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); +- Validate.inclusiveBetween(0L, this.d, (long) j); ++ public final int a(int i, int j) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper ++ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper + int k = this.b(i); + long l = this.b[k]; + int i1 = (i - k * this.f) * this.c; +@@ -65,9 +65,9 @@ public class DataBits { + return j1; + } + +- public void b(int i, int j) { +- Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); +- Validate.inclusiveBetween(0L, this.d, (long) j); ++ public final void b(int i, int j) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper ++ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper + int k = this.b(i); + long l = this.b[k]; + int i1 = (i - k * this.f) * this.c; +@@ -75,8 +75,8 @@ public class DataBits { + this.b[k] = l & ~(this.d << i1) | ((long) j & this.d) << i1; + } + +- public int a(int i) { +- Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); ++ public final int a(int i) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper + int j = this.b(i); + long k = this.b[j]; + int l = (i - j * this.f) * this.c; diff --git a/patches/server-unmapped/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/patches/server-unmapped/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch new file mode 100644 index 0000000000..1cdc8fed9c --- /dev/null +++ b/patches/server-unmapped/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 6 Apr 2016 01:04:23 -0500 +Subject: [PATCH] Option to use vanilla per-world scoreboard coloring on names + +This change is basically a bandaid to fix CB's complete and utter lack +of support for vanilla scoreboard name modifications. + +In the future, finding a way to merge the vanilla expectations in with +bukkit's concept of a display name would be preferable. There was a PR +for this on CB at one point but I can't find it. We may need to do this +ourselves at some point in the future. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index db2dddd12f54e6d15916c4cee623676541de37fb..1942f5224aaebb18adb591d6f70a419cfc1a7bdd 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -254,4 +254,9 @@ public class PaperWorldConfig { + grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); + log("Grass Spread Tick Rate: " + grassUpdateRate); + } ++ ++ public boolean useVanillaScoreboardColoring; ++ private void useVanillaScoreboardColoring() { ++ useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); ++ } + } +diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +index 909968952a7ae2aa0196f12d1b3177cade380db2..1fcb01abc93c3c6ad172f209f55421d8b98629d5 100644 +--- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java ++++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +@@ -17,7 +17,11 @@ import net.kyori.adventure.text.event.ClickEvent; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.world.scores.ScoreboardTeam; ++import net.minecraft.world.scores.ScoreboardTeamBase; + import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; ++import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.entity.CraftPlayer; + import org.bukkit.craftbukkit.util.LazyPlayerSet; + import org.bukkit.craftbukkit.util.Waitable; +@@ -179,10 +183,22 @@ public final class ChatProcessor { + } + + private static String legacyDisplayName(final CraftPlayer player) { ++ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { ++ final EntityPlayer ep = player.getHandle(); ++ IChatBaseComponent name = ep.getDisplayName(); ++ final ScoreboardTeamBase team = ep.getScoreboardTeam(); ++ if (team != null) { ++ name = team.getFormattedName(name); ++ } ++ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(PaperAdventure.asAdventure(name)) + ChatColor.RESET; ++ } + return player.getDisplayName(); + } + + private static Component displayName(final CraftPlayer player) { ++ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { ++ return PaperAdventure.asAdventure(ScoreboardTeam.a(player.getHandle().getScoreboardTeam(), player.getHandle().getDisplayName())); ++ } + return player.displayName(); + } + diff --git a/patches/server-unmapped/0084-Workaround-for-setting-passengers-on-players.patch b/patches/server-unmapped/0084-Workaround-for-setting-passengers-on-players.patch new file mode 100644 index 0000000000..ec42a6a21a --- /dev/null +++ b/patches/server-unmapped/0084-Workaround-for-setting-passengers-on-players.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 10 Apr 2016 03:23:32 -0500 +Subject: [PATCH] Workaround for setting passengers on players + +SPIGOT-1915 & GH-114 + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index ab7e731cb04a75b829f0cd24d7b94f7ddad166e8..4bb57229c045956bab631982e12c0fc420db450e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -872,6 +872,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return true; + } + ++ // Paper start - Ugly workaround for SPIGOT-1915 & GH-114 ++ @Override ++ public boolean setPassenger(org.bukkit.entity.Entity passenger) { ++ boolean wasSet = super.setPassenger(passenger); ++ if (wasSet) { ++ this.getHandle().playerConnection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutMount(this.getHandle())); ++ } ++ return wasSet; ++ } ++ // Paper end ++ + @Override + public void setSneaking(boolean sneak) { + getHandle().setSneaking(sneak); diff --git a/patches/server-unmapped/0085-Remove-unused-World-Tile-Entity-List.patch b/patches/server-unmapped/0085-Remove-unused-World-Tile-Entity-List.patch new file mode 100644 index 0000000000..8cdf182378 --- /dev/null +++ b/patches/server-unmapped/0085-Remove-unused-World-Tile-Entity-List.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 13 Apr 2016 00:25:28 -0400 +Subject: [PATCH] Remove unused World Tile Entity List + +Massive hit to performance and it is completely unnecessary. + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 24a45e5ac9b17feb528e9a047d1ad1761569ebfa..75424a5dd6db57dded3b6d895e6b5b102e91c77e 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1721,7 +1721,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + bufferedwriter.write(String.format("entities: %d\n", this.entitiesById.size())); +- bufferedwriter.write(String.format("block_entities: %d\n", this.tileEntityList.size())); ++ bufferedwriter.write(String.format("block_entities: %d\n", this.tileEntityListTick.size())); // Paper - remove unused list + bufferedwriter.write(String.format("block_ticks: %d\n", this.getBlockTickList().a())); + bufferedwriter.write(String.format("fluid_ticks: %d\n", this.getFluidTickList().a())); + bufferedwriter.write("distance_manager: " + playerchunkmap.e().c() + "\n"); +@@ -1860,7 +1860,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + private void a(Writer writer) throws IOException { + CSVWriter csvwriter = CSVWriter.a().a("x").a("y").a("z").a("type").a(writer); +- Iterator iterator = this.tileEntityList.iterator(); ++ Iterator iterator = this.tileEntityListTick.iterator(); // Paper - remove unused list + + while (iterator.hasNext()) { + TileEntity tileentity = (TileEntity) iterator.next(); +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 8da8141c2320c0c1a9b95826a9be2dbe22e11c14..cad86b0273c05767f78bcb3bdfaa9ea01e26af4e 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -91,7 +91,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public static final ResourceKey THE_NETHER = ResourceKey.a(IRegistry.L, new MinecraftKey("the_nether")); + public static final ResourceKey THE_END = ResourceKey.a(IRegistry.L, new MinecraftKey("the_end")); + private static final EnumDirection[] a = EnumDirection.values(); +- public final List tileEntityList = Lists.newArrayList(); ++ //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list + public final List tileEntityListTick = Lists.newArrayList(); + protected final List tileEntityListPending = Lists.newArrayList(); + protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); +@@ -683,9 +683,9 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + }, tileentity::getPosition}); + } + +- boolean flag = this.tileEntityList.add(tileentity); ++ boolean flag = true; // Paper - remove unused list + +- if (flag && tileentity instanceof ITickable) { ++ if (flag && tileentity instanceof ITickable && !this.tileEntityListTick.contains(tileentity)) { // Paper + this.tileEntityListTick.add(tileentity); + } + +@@ -721,7 +721,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + timings.tileEntityTick.startTiming(); // Spigot + if (!this.tileEntityListUnload.isEmpty()) { + this.tileEntityListTick.removeAll(this.tileEntityListUnload); +- this.tileEntityList.removeAll(this.tileEntityListUnload); ++ //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list + this.tileEntityListUnload.clear(); + } + +@@ -781,7 +781,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + tilesThisCycle--; + this.tileEntityListTick.remove(tileTickPosition--); + // Spigot end +- this.tileEntityList.remove(tileentity); ++ //this.tileEntityList.remove(tileentity); // Paper - remove unused list + if (this.isLoaded(tileentity.getPosition())) { + this.getChunkAtWorldCoords(tileentity.getPosition()).removeTileEntity(tileentity.getPosition()); + } +@@ -811,7 +811,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + this.notify(tileentity1.getPosition(), iblockdata, iblockdata, 3); + // CraftBukkit start + // From above, don't screw this up - SPIGOT-1746 +- if (!this.tileEntityList.contains(tileentity1)) { ++ if (true) { // Paper - remove unused list + this.a(tileentity1); + } + // CraftBukkit end +@@ -957,7 +957,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + } else { + if (tileentity != null) { + this.tileEntityListPending.remove(tileentity); +- this.tileEntityList.remove(tileentity); ++ //this.tileEntityList.remove(tileentity); // Paper - remove unused list + this.tileEntityListTick.remove(tileentity); + } + diff --git a/patches/server-unmapped/0086-Don-t-tick-Skulls-unused-code.patch b/patches/server-unmapped/0086-Don-t-tick-Skulls-unused-code.patch new file mode 100644 index 0000000000..26489896ab --- /dev/null +++ b/patches/server-unmapped/0086-Don-t-tick-Skulls-unused-code.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 13 Apr 2016 00:30:10 -0400 +Subject: [PATCH] Don't tick Skulls - unused code + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java +index 87a5f352c8a6336c65008d6e21a771fd6332773c..22217f24b4a87f10b6d5a3e37d23a1164af84ace 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java +@@ -33,7 +33,7 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.world.entity.player.EntityHuman; + // Spigot end + +-public class TileEntitySkull extends TileEntity implements ITickable { ++public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Paper - remove tickable + + @Nullable + private static UserCache userCache; +@@ -136,7 +136,7 @@ public class TileEntitySkull extends TileEntity implements ITickable { + + } + +- @Override ++ // Paper - remove override + public void tick() { + IBlockData iblockdata = this.getBlock(); + diff --git a/patches/server-unmapped/0087-Configurable-Player-Collision.patch b/patches/server-unmapped/0087-Configurable-Player-Collision.patch new file mode 100644 index 0000000000..ceaba1942c --- /dev/null +++ b/patches/server-unmapped/0087-Configurable-Player-Collision.patch @@ -0,0 +1,131 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 13 Apr 2016 02:10:49 -0400 +Subject: [PATCH] Configurable Player Collision + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 439dcc6effdc91830d2b7ede9063982998b37120..504efea7b6f50a0d17f4f353781953dfb18bdeca 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -232,4 +232,9 @@ public class PaperConfig { + private static void regionFileCacheSize() { + regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); + } ++ ++ public static boolean enablePlayerCollisions = true; ++ private static void enablePlayerCollisions() { ++ enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); ++ } + } +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java +index bc40f2cbe1645fd60c4cee106b90f17cd043d32d..c1bb5c325286119891e8d68ce8f7328c99edb486 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java +@@ -112,7 +112,7 @@ public class PacketPlayOutScoreboardTeam implements Packet toRemove = scoreboard.getTeams().stream().filter(team -> team.getName().startsWith("collideRule_")).map(ScoreboardTeam::getName).collect(java.util.stream.Collectors.toList()); ++ for (String teamName : toRemove) { ++ scoreboard.removeTeam(scoreboard.getTeam(teamName)); // Clean up after ourselves ++ } ++ ++ if (!com.destroystokyo.paper.PaperConfig.enablePlayerCollisions) { ++ this.getPlayerList().collideRuleTeamName = org.apache.commons.lang3.StringUtils.left("collideRule_" + java.util.concurrent.ThreadLocalRandom.current().nextInt(), 16); ++ ScoreboardTeam collideTeam = scoreboard.createTeam(this.getPlayerList().collideRuleTeamName); ++ collideTeam.setCanSeeFriendlyInvisibles(false); // Because we want to mimic them not being on a team at all ++ } ++ // Paper end ++ + this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); + this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); + this.serverConnection.acceptConnections(); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 9d327f1255dd9d6b11840f7bb8ffc302bc33dbcf..49f1aed92fd5fa46b74a979f317a2eb0672991e9 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -86,6 +86,7 @@ import net.minecraft.world.level.storage.SavedFile; + import net.minecraft.world.level.storage.WorldData; + import net.minecraft.world.level.storage.WorldNBTStorage; + import net.minecraft.world.phys.Vec3D; ++import net.minecraft.world.scores.Scoreboard; + import net.minecraft.world.scores.ScoreboardObjective; + import net.minecraft.world.scores.ScoreboardTeam; + import net.minecraft.world.scores.ScoreboardTeamBase; +@@ -145,6 +146,7 @@ public abstract class PlayerList { + // CraftBukkit start + private CraftServer cserver; + private final Map playersByName = new java.util.HashMap<>(); ++ public @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule + + public PlayerList(MinecraftServer minecraftserver, IRegistryCustom.Dimension iregistrycustom_dimension, WorldNBTStorage worldnbtstorage, int i) { + this.cserver = minecraftserver.server = new CraftServer((DedicatedServer) minecraftserver, this); +@@ -376,6 +378,13 @@ public abstract class PlayerList { + } + + entityplayer.syncInventory(); ++ // Paper start - Add to collideRule team if needed ++ final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); ++ final ScoreboardTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName); ++ if (this.collideRuleTeamName != null && collideRuleTeam != null && entityplayer.getScoreboardTeam() == null) { ++ scoreboard.addPlayerToTeam(entityplayer.getName(), collideRuleTeam); ++ } ++ // Paper end + // CraftBukkit - Moved from above, added world + PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getDisplayName().getString(), s1, entityplayer.getId(), worldserver1.worldDataServer.getName(), entityplayer.locX(), entityplayer.locY(), entityplayer.locZ()); + } +@@ -496,6 +505,16 @@ public abstract class PlayerList { + entityplayer.playerTick(); // SPIGOT-924 + // CraftBukkit end + ++ // Paper start - Remove from collideRule team if needed ++ if (this.collideRuleTeamName != null) { ++ final Scoreboard scoreBoard = this.server.getWorldServer(World.OVERWORLD).getScoreboard(); ++ final ScoreboardTeam team = scoreBoard.getTeam(this.collideRuleTeamName); ++ if (entityplayer.getScoreboardTeam() == team && team != null) { ++ scoreBoard.removePlayerFromTeam(entityplayer.getName(), team); ++ } ++ } ++ // Paper end ++ + this.savePlayerFile(entityplayer); + if (entityplayer.isPassenger()) { + Entity entity = entityplayer.getRootVehicle(); +@@ -1144,6 +1163,13 @@ public abstract class PlayerList { + } + // CraftBukkit end + ++ // Paper start - Remove collideRule team if it exists ++ if (this.collideRuleTeamName != null) { ++ final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); ++ final ScoreboardTeam team = scoreboard.getTeam(this.collideRuleTeamName); ++ if (team != null) scoreboard.removeTeam(team); ++ } ++ // Paper end + } + + // CraftBukkit start diff --git a/patches/server-unmapped/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/patches/server-unmapped/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch new file mode 100644 index 0000000000..0648fd73b6 --- /dev/null +++ b/patches/server-unmapped/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 13 Apr 2016 20:21:38 -0700 +Subject: [PATCH] Add handshake event to allow plugins to handle client + handshaking logic themselves + + +diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java +index 9b24afa4f4fe41d2261b16aaecec2144ac7d049f..1164782be686c91379494b236ebded817a002a6f 100644 +--- a/src/main/java/net/minecraft/server/network/HandshakeListener.java ++++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java +@@ -29,7 +29,7 @@ public class HandshakeListener implements PacketHandshakingInListener { + // CraftBukkit end + private static final IChatBaseComponent a = new ChatComponentText("Ignoring status request"); + private final MinecraftServer b; +- private final NetworkManager c; ++ private final NetworkManager c; final NetworkManager getNetworkManager() { return this.c; } // Paper - OBFHELPER + + public HandshakeListener(MinecraftServer minecraftserver, NetworkManager networkmanager) { + this.b = minecraftserver; +@@ -88,8 +88,35 @@ public class HandshakeListener implements PacketHandshakingInListener { + this.c.close(chatmessage); + } else { + this.c.setPacketListener(new LoginListener(this.b, this.c)); ++ // Paper start - handshake event ++ boolean proxyLogicEnabled = org.spigotmc.SpigotConfig.bungee; ++ boolean handledByEvent = false; ++ // Try and handle the handshake through the event ++ if (com.destroystokyo.paper.event.player.PlayerHandshakeEvent.getHandlerList().getRegisteredListeners().length != 0) { // Hello? Can you hear me? ++ java.net.SocketAddress socketAddress = this.getNetworkManager().socketAddress; ++ String hostnameOfRemote = socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getHostString() : InetAddress.getLoopbackAddress().getHostAddress(); ++ com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packethandshakinginsetprotocol.hostname, hostnameOfRemote, !proxyLogicEnabled); ++ if (event.callEvent()) { ++ // If we've failed somehow, let the client know so and go no further. ++ if (event.isFailed()) { ++ chatmessage = new ChatMessage(event.getFailMessage()); ++ this.getNetworkManager().sendPacket(new PacketLoginOutDisconnect(chatmessage)); ++ this.getNetworkManager().close(chatmessage); ++ return; ++ } ++ ++ if (event.getServerHostname() != null) packethandshakinginsetprotocol.hostname = event.getServerHostname(); ++ if (event.getSocketAddressHostname() != null) this.getNetworkManager().socketAddress = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); ++ this.getNetworkManager().spoofedUUID = event.getUniqueId(); ++ this.getNetworkManager().spoofedProfile = gson.fromJson(event.getPropertiesJson(), com.mojang.authlib.properties.Property[].class); ++ handledByEvent = true; // Hooray, we did it! ++ } ++ } ++ // Don't try and handle default logic if it's been handled by the event. ++ if (!handledByEvent && proxyLogicEnabled) { ++ // Paper end + // Spigot Start +- if (org.spigotmc.SpigotConfig.bungee) { ++ //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! + String[] split = packethandshakinginsetprotocol.hostname.split("\00"); + if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { + packethandshakinginsetprotocol.hostname = split[0]; diff --git a/patches/server-unmapped/0089-Configurable-RCON-IP-address.patch b/patches/server-unmapped/0089-Configurable-RCON-IP-address.patch new file mode 100644 index 0000000000..05f3461032 --- /dev/null +++ b/patches/server-unmapped/0089-Configurable-RCON-IP-address.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 16 Apr 2016 00:39:33 -0400 +Subject: [PATCH] Configurable RCON IP address + +For servers with multiple IP's, ability to bind to a specific interface. + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +index 0ecff9f5e2ba444b196d80da341ff851dd5ce26f..b7cf02301c02ed0a6b696384e656426762ae2105 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +@@ -67,6 +67,8 @@ public class DedicatedServerProperties extends PropertyManager.EditableProperty whiteList; + public final GeneratorSettings generatorSettings; + ++ public final String rconIp; // Paper - Add rcon ip ++ + // CraftBukkit start + public DedicatedServerProperties(Properties properties, IRegistryCustom iregistrycustom, OptionSet optionset) { + super(properties, optionset); +@@ -118,6 +120,10 @@ public class DedicatedServerProperties extends PropertyManager> { + }; + } + +- @Nullable +- private String c(String s) { ++ @Nullable String getSettingIfExists(final String path) { return this.c(path); } // Paper - OBFHELPER ++ @Nullable private String c(String s) { // Paper - OBFHELPER + return (String) getOverride(s, this.properties.getProperty(s)); // CraftBukkit + } + +diff --git a/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java b/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java +index 797a450a08da1b799e32fae2a71a7a50bb90d127..3b3e21d1d86629d6c5e06108e53d1c5e807074d8 100644 +--- a/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java ++++ b/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java +@@ -62,7 +62,7 @@ public class RemoteControlListener extends RemoteConnectionThread { + @Nullable + public static RemoteControlListener a(IMinecraftServer iminecraftserver) { + DedicatedServerProperties dedicatedserverproperties = iminecraftserver.getDedicatedServerProperties(); +- String s = iminecraftserver.h_(); ++ String s = dedicatedserverproperties.rconIp; // Paper - Configurable rcon ip + + if (s.isEmpty()) { + s = "0.0.0.0"; diff --git a/patches/server-unmapped/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch b/patches/server-unmapped/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch new file mode 100644 index 0000000000..c379b25eba --- /dev/null +++ b/patches/server-unmapped/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 17 Apr 2016 17:27:09 -0400 +Subject: [PATCH] Prevent Fire from loading chunks & wrongly spread + +This causes the nether to spam unload/reload chunks, plus overall +bad behavior. + +This also stops fire from spreading to illegal locations. + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java +index ee5400fd3e493e1f0518a9e47ddbc997e7a0fb92..c22fad0038fdb0769e23db782e3341206fbd80f9 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockFire.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java +@@ -135,7 +135,7 @@ public class BlockFire extends BlockFireAbstract { + BlockStateBoolean blockstateboolean = (BlockStateBoolean) BlockFire.h.get(enumdirection); + + if (blockstateboolean != null) { +- iblockdata1 = (IBlockData) iblockdata1.set(blockstateboolean, this.e(iblockaccess.getType(blockposition.shift(enumdirection)))); ++ iblockdata1 = (IBlockData) iblockdata1.set(blockstateboolean, this.e(iblockaccess.getTypeIfLoaded(blockposition.shift(enumdirection)))); // Paper - prevent chunk loads + } + } + +@@ -215,6 +215,7 @@ public class BlockFire extends BlockFireAbstract { + } + + blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, l, j1, i1); ++ if (blockposition_mutableblockposition.isInvalidYLocation() || !worldserver.isLoaded(blockposition_mutableblockposition)) continue; // Paper + int l1 = this.a((IWorldReader) worldserver, (BlockPosition) blockposition_mutableblockposition); + + if (l1 > 0) { +@@ -260,10 +261,16 @@ public class BlockFire extends BlockFireAbstract { + } + + private void trySpread(World world, BlockPosition blockposition, int i, Random random, int j, BlockPosition sourceposition) { // CraftBukkit add sourceposition +- int k = this.getBurnChance(world.getType(blockposition)); ++ // Paper start ++ final IBlockData iblockdata = world.getTypeIfLoaded(blockposition); ++ if (iblockdata == null) { ++ return; ++ } ++ int k = this.getBurnChance(iblockdata); ++ // Paper end + + if (random.nextInt(i) < k) { +- IBlockData iblockdata = world.getType(blockposition); ++ //IBlockData iblockdata = world.getType(blockposition); // Paper + + // CraftBukkit start + org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); +@@ -309,7 +316,7 @@ public class BlockFire extends BlockFireAbstract { + for (int j = 0; j < i; ++j) { + EnumDirection enumdirection = aenumdirection[j]; + +- if (this.e(iblockaccess.getType(blockposition.shift(enumdirection)))) { ++ if (this.e(iblockaccess.getTypeIfLoaded(blockposition.shift(enumdirection)))) { // Paper - prevent chunk loads + return true; + } + } +@@ -327,7 +334,12 @@ public class BlockFire extends BlockFireAbstract { + + for (int k = 0; k < j; ++k) { + EnumDirection enumdirection = aenumdirection[k]; +- IBlockData iblockdata = iworldreader.getType(blockposition.shift(enumdirection)); ++ // Paper start ++ IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition.shift(enumdirection)); ++ if (iblockdata == null) { ++ continue; ++ } ++ // Paper end + + i = Math.max(this.getFlameChance(iblockdata), i); + } +@@ -338,7 +350,7 @@ public class BlockFire extends BlockFireAbstract { + + @Override + protected boolean e(IBlockData iblockdata) { +- return this.getFlameChance(iblockdata) > 0; ++ return iblockdata != null && this.getFlameChance(iblockdata) > 0; // Paper - iblockdata can be nullable if chunk is unloaded now + } + + @Override diff --git a/patches/server-unmapped/0091-Implement-PlayerLocaleChangeEvent.patch b/patches/server-unmapped/0091-Implement-PlayerLocaleChangeEvent.patch new file mode 100644 index 0000000000..56e55d42db --- /dev/null +++ b/patches/server-unmapped/0091-Implement-PlayerLocaleChangeEvent.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Isaac Moore +Date: Tue, 19 Apr 2016 14:09:31 -0500 +Subject: [PATCH] Implement PlayerLocaleChangeEvent + + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index cda0e7f8f9a9d66ac4e5a3f52609a4271bf0c4b5..3f1f8f7fe9452f66b18a08ef480d50ef78ad3351 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1695,7 +1695,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + return s; + } + +- public String locale = "en_us"; // CraftBukkit - add, lowercase ++ public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null + public java.util.Locale adventure$locale = java.util.Locale.US; // Paper + public void a(PacketPlayInSettings packetplayinsettings) { + // CraftBukkit start +@@ -1703,9 +1703,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT); + this.server.server.getPluginManager().callEvent(event); + } +- if (!this.locale.equals(packetplayinsettings.locale)) { ++ if (this.locale == null || !this.locale.equals(packetplayinsettings.locale)) { // Paper - check for null + PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), packetplayinsettings.locale); + this.server.server.getPluginManager().callEvent(event); ++ new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.locale, packetplayinsettings.locale).callEvent(); // Paper + } + this.locale = packetplayinsettings.locale; + // Paper start +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 4bb57229c045956bab631982e12c0fc420db450e..5698ef90bfeceec37eaf7f23361246ef125b3cd1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1877,8 +1877,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + @Override + public String getLocale() { +- return getHandle().locale; +- ++ // Paper start - Locale change event ++ final String locale = getHandle().locale; ++ return locale != null ? locale : "en_us"; ++ // Paper end + } + + // Paper start diff --git a/patches/server-unmapped/0092-EntityRegainHealthEvent-isFastRegen-API.patch b/patches/server-unmapped/0092-EntityRegainHealthEvent-isFastRegen-API.patch new file mode 100644 index 0000000000..43f4080f06 --- /dev/null +++ b/patches/server-unmapped/0092-EntityRegainHealthEvent-isFastRegen-API.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 22 Apr 2016 01:43:11 -0500 +Subject: [PATCH] EntityRegainHealthEvent isFastRegen API + +Don't even get me started + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 375284b7e321cb03a7a30aedea165ca7a2fd1091..db5c0d2da9ed9993ee83adccfa74e77f4e364f2a 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -1130,10 +1130,16 @@ public abstract class EntityLiving extends Entity { + } + + public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { ++ // Paper start - Forward ++ heal(f, regainReason, false); ++ } ++ ++ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason, boolean isFastRegen) { ++ // Paper end + float f1 = this.getHealth(); + + if (f1 > 0.0F) { +- EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason, isFastRegen); // Paper + // Suppress during worldgen + if (this.valid) { + this.world.getServer().getPluginManager().callEvent(event); +diff --git a/src/main/java/net/minecraft/world/food/FoodMetaData.java b/src/main/java/net/minecraft/world/food/FoodMetaData.java +index 7ed321acba6d46159f7d67b8d10a0a3e06ac88a9..e455b25b0809af15f6fde957121d0110da7eb08f 100644 +--- a/src/main/java/net/minecraft/world/food/FoodMetaData.java ++++ b/src/main/java/net/minecraft/world/food/FoodMetaData.java +@@ -87,7 +87,7 @@ public class FoodMetaData { + if (this.foodTickTimer >= this.saturatedRegenRate) { // CraftBukkit + float f = Math.min(this.saturationLevel, 6.0F); + +- entityhuman.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ entityhuman.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED, true); // CraftBukkit - added RegainReason // Paper - This is fast regen + // this.a(f); CraftBukkit - EntityExhaustionEvent + entityhuman.applyExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.foodTickTimer = 0; diff --git a/patches/server-unmapped/0093-Add-ability-to-configure-frosted_ice-properties.patch b/patches/server-unmapped/0093-Add-ability-to-configure-frosted_ice-properties.patch new file mode 100644 index 0000000000..c48a22b74f --- /dev/null +++ b/patches/server-unmapped/0093-Add-ability-to-configure-frosted_ice-properties.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Thu, 21 Apr 2016 23:51:55 -0700 +Subject: [PATCH] Add ability to configure frosted_ice properties + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1942f5224aaebb18adb591d6f70a419cfc1a7bdd..5baccb8d50c135ab20c38ffd0690f585514ce5af 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -259,4 +259,14 @@ public class PaperWorldConfig { + private void useVanillaScoreboardColoring() { + useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); + } ++ ++ public boolean frostedIceEnabled = true; ++ public int frostedIceDelayMin = 20; ++ public int frostedIceDelayMax = 40; ++ private void frostedIce() { ++ this.frostedIceEnabled = this.getBoolean("frosted-ice.enabled", this.frostedIceEnabled); ++ this.frostedIceDelayMin = this.getInt("frosted-ice.delay.min", this.frostedIceDelayMin); ++ this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); ++ log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java +index 7239a30bd4a5dc4ed09802eea8f7126485ebb635..e32e94868386ff06ff29254e6cc3bee9b446a293 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java +@@ -30,6 +30,7 @@ public class BlockIceFrost extends BlockIce { + + @Override + public void tickAlways(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { ++ if (!worldserver.paperConfig.frostedIceEnabled) return; // Paper - add ability to disable frosted ice + if ((random.nextInt(3) == 0 || this.a(worldserver, blockposition, 4)) && worldserver.getLightLevel(blockposition) > 11 - (Integer) iblockdata.get(BlockIceFrost.a) - iblockdata.b((IBlockAccess) worldserver, blockposition) && this.e(iblockdata, (World) worldserver, blockposition)) { + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); + EnumDirection[] aenumdirection = EnumDirection.values(); +@@ -42,12 +43,12 @@ public class BlockIceFrost extends BlockIce { + IBlockData iblockdata1 = worldserver.getType(blockposition_mutableblockposition); + + if (iblockdata1.a((Block) this) && !this.e(iblockdata1, (World) worldserver, blockposition_mutableblockposition)) { +- worldserver.getBlockTickList().a(blockposition_mutableblockposition, this, MathHelper.nextInt(random, 20, 40)); ++ worldserver.getBlockTickList().a(blockposition_mutableblockposition, this, MathHelper.nextInt(random, worldserver.paperConfig.frostedIceDelayMin, worldserver.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay + } + } + + } else { +- worldserver.getBlockTickList().a(blockposition, this, MathHelper.nextInt(random, 20, 40)); ++ worldserver.getBlockTickList().a(blockposition, this, MathHelper.nextInt(random, worldserver.paperConfig.frostedIceDelayMin, worldserver.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay + } + } + diff --git a/patches/server-unmapped/0094-remove-null-possibility-for-getServer-singleton.patch b/patches/server-unmapped/0094-remove-null-possibility-for-getServer-singleton.patch new file mode 100644 index 0000000000..a59d0ec3f4 --- /dev/null +++ b/patches/server-unmapped/0094-remove-null-possibility-for-getServer-singleton.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 28 Apr 2016 00:57:27 -0400 +Subject: [PATCH] remove null possibility for getServer singleton + +to stop IDE complaining about potential NPE + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 8df60cedc1198916dfce8fcea7ca4a49f98429ba..ed00ee8e56e6ca38a1ac689458c4675eff6e3eea 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -180,6 +180,7 @@ import org.spigotmc.SlackActivityAccountant; // Spigot + + public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { + ++ private static MinecraftServer SERVER; // Paper + public static final Logger LOGGER = LogManager.getLogger(); + public static final File b = new File("usercache.json"); + public static final WorldSettings c = new WorldSettings("Demo World", EnumGamemode.SURVIVAL, false, EnumDifficulty.NORMAL, false, new GameRules(), DataPackConfiguration.a); +@@ -286,6 +287,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant +Date: Fri, 29 Apr 2016 20:02:00 -0400 +Subject: [PATCH] Improve Maps (in item frames) performance and bug fixes + +Maps used a modified version of rendering to support plugin controlled +imaging on maps. The Craft Map Renderer is much slower than Vanilla, +causing maps in item frames to cause a noticeable hit on server performance. + +This updates the map system to not use the Craft system if we detect that no +custom renderers are in use, defaulting to the much simpler Vanilla system. + +Additionally, numerous issues to player position tracking on maps has been fixed. + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 75424a5dd6db57dded3b6d895e6b5b102e91c77e..c7652d6bff7630e2eefbb4c3b0deb6e17b9c98d0 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1170,6 +1170,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + { + if ( iter.next().trackee == entity ) + { ++ map.decorations.remove(entity.getDisplayName().getString()); // Paper + iter.remove(); + } + } +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index f42e16589476c1bd10b13214dda5ac7bb3e52131..e3e3426a00128b56d523bb43a59b814b915ad0ff 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -86,6 +86,7 @@ import net.minecraft.world.item.ItemElytra; + import net.minecraft.world.item.ItemProjectileWeapon; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.ItemSword; ++import net.minecraft.world.item.ItemWorldMap; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.IRecipe; + import net.minecraft.world.item.enchantment.EnchantmentManager; +@@ -104,6 +105,7 @@ import net.minecraft.world.level.block.entity.TileEntitySign; + import net.minecraft.world.level.block.entity.TileEntityStructure; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.pattern.ShapeDetectorBlock; ++import net.minecraft.world.level.saveddata.maps.WorldMap; + import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.Vec3D; + import net.minecraft.world.scores.Scoreboard; +@@ -689,6 +691,12 @@ public abstract class EntityHuman extends EntityLiving { + return null; + } + // CraftBukkit end ++ // Paper start - remove player from map on drop ++ if (itemstack.getItem() == Items.FILLED_MAP) { ++ WorldMap worldmap = ItemWorldMap.getSavedMap(itemstack, this.world); ++ worldmap.updateSeenPlayers(this, itemstack); ++ } ++ // Paper end + + return entityitem; + } +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java +index 3f057f0bd23bc1c693c8f04ee8acd6626c620008..d470af1814af332595c1c0beb1cdc552e186a6bb 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java +@@ -57,6 +57,7 @@ public class WorldMap extends PersistentBase { + private final Map m = Maps.newHashMap(); + public final Map decorations = Maps.newLinkedHashMap(); + private final Map n = Maps.newHashMap(); ++ private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper + + // CraftBukkit start + public final CraftMapView mapView; +@@ -69,6 +70,7 @@ public class WorldMap extends PersistentBase { + // CraftBukkit start + mapView = new CraftMapView(this); + server = (CraftServer) org.bukkit.Bukkit.getServer(); ++ vanillaRender.buffer = colors; // Paper + // CraftBukkit end + } + +@@ -136,6 +138,7 @@ public class WorldMap extends PersistentBase { + this.m.put(mapiconbanner.f(), mapiconbanner); + this.a(mapiconbanner.c(), (GeneratorAccess) null, mapiconbanner.f(), (double) mapiconbanner.a().getX(), (double) mapiconbanner.a().getZ(), 180.0D, mapiconbanner.d()); + } ++ this.vanillaRender.buffer = colors; // Paper + + NBTTagList nbttaglist1 = nbttagcompound.getList("frames", 10); + +@@ -216,6 +219,7 @@ public class WorldMap extends PersistentBase { + this.b(); + } + ++ public void updateSeenPlayers(EntityHuman entityhuman, ItemStack itemstack) { this.a(entityhuman, itemstack); } // Paper - OBFHELPER + public void a(EntityHuman entityhuman, ItemStack itemstack) { + if (!this.humans.containsKey(entityhuman)) { + WorldMap.WorldMapHumanTracker worldmap_worldmaphumantracker = new WorldMap.WorldMapHumanTracker(entityhuman); +@@ -451,6 +455,21 @@ public class WorldMap extends PersistentBase { + + public class WorldMapHumanTracker { + ++ // Paper start ++ private void addSeenPlayers(java.util.Collection icons) { ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) trackee.getBukkitEntity(); ++ WorldMap.this.decorations.forEach((name, mapIcon) -> { ++ // If this cursor is for a player check visibility with vanish system ++ org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayerExact(name); // Spigot ++ if (other == null || player.canSee(other)) { ++ icons.add(mapIcon); ++ } ++ }); ++ } ++ private boolean shouldUseVanillaMap() { ++ return mapView.getRenderers().size() == 1 && mapView.getRenderers().get(0).getClass() == org.bukkit.craftbukkit.map.CraftMapRenderer.class; ++ } ++ // Paper end + public final EntityHuman trackee; + private boolean d = true; + private int e; +@@ -467,9 +486,12 @@ public class WorldMap extends PersistentBase { + @Nullable + public Packet a(ItemStack itemstack) { + // CraftBukkit start +- org.bukkit.craftbukkit.map.RenderData render = WorldMap.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.trackee.getBukkitEntity()); // CraftBukkit ++ if (!this.d && this.i % 5 != 0) { this.i++; return null; } // Paper - this won't end up sending, so don't render it! ++ boolean vanillaMaps = shouldUseVanillaMap(); // Paper ++ org.bukkit.craftbukkit.map.RenderData render = !vanillaMaps ? WorldMap.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.trackee.getBukkitEntity()) : WorldMap.this.vanillaRender; // CraftBukkit // Paper + + java.util.Collection icons = new java.util.ArrayList(); ++ if (vanillaMaps) addSeenPlayers(icons); // Paper + + for ( org.bukkit.map.MapCursor cursor : render.cursors) { + +diff --git a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java +index 256a131781721c86dd6cdbc329335964570cbe8c..5768cd512ec166f1e8d1f4a28792015347297c3f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java ++++ b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java +@@ -5,7 +5,7 @@ import org.bukkit.map.MapCursor; + + public class RenderData { + +- public final byte[] buffer; ++ public byte[] buffer; // Paper + public final ArrayList cursors; + + public RenderData() { diff --git a/patches/server-unmapped/0096-LootTable-API-Replenishable-Lootables-Feature.patch b/patches/server-unmapped/0096-LootTable-API-Replenishable-Lootables-Feature.patch new file mode 100644 index 0000000000..52eb70b9df --- /dev/null +++ b/patches/server-unmapped/0096-LootTable-API-Replenishable-Lootables-Feature.patch @@ -0,0 +1,736 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 1 May 2016 21:19:14 -0400 +Subject: [PATCH] LootTable API & Replenishable Lootables Feature + +Provides an API to control the loot table for an object. +Also provides a feature that any Lootable Inventory (Chests in Structures) +can automatically replenish after a given time. + +This feature is good for long term worlds so that newer players +do not suffer with "Every chest has been looted" + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5baccb8d50c135ab20c38ffd0690f585514ce5af..eb04fdb172a50ec1f5b7fe78fa0e7655246abd60 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -269,4 +269,26 @@ public class PaperWorldConfig { + this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); + log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); + } ++ ++ public boolean autoReplenishLootables; ++ public boolean restrictPlayerReloot; ++ public boolean changeLootTableSeedOnFill; ++ public int maxLootableRefills; ++ public int lootableRegenMin; ++ public int lootableRegenMax; ++ private void enhancedLootables() { ++ autoReplenishLootables = getBoolean("lootables.auto-replenish", false); ++ restrictPlayerReloot = getBoolean("lootables.restrict-player-reloot", true); ++ changeLootTableSeedOnFill = getBoolean("lootables.reset-seed-on-fill", true); ++ maxLootableRefills = getInt("lootables.max-refills", -1); ++ lootableRegenMin = PaperConfig.getSeconds(getString("lootables.refresh-min", "12h")); ++ lootableRegenMax = PaperConfig.getSeconds(getString("lootables.refresh-max", "2d")); ++ if (autoReplenishLootables) { ++ log("Lootables: Replenishing every " + ++ PaperConfig.timeSummary(lootableRegenMin) + " to " + ++ PaperConfig.timeSummary(lootableRegenMax) + ++ (restrictPlayerReloot ? " (restricting reloot)" : "") ++ ); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5dfc3c8008d64ad4ed71b4904c897f5005491349 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java +@@ -0,0 +1,33 @@ ++package com.destroystokyo.paper.loottable; ++ ++import net.minecraft.core.BlockPosition; ++import net.minecraft.world.level.World; ++import net.minecraft.world.level.block.entity.TileEntityLootable; ++import org.bukkit.Chunk; ++import org.bukkit.block.Block; ++ ++public interface PaperLootableBlockInventory extends LootableBlockInventory, PaperLootableInventory { ++ ++ TileEntityLootable getTileEntity(); ++ ++ @Override ++ default LootableInventory getAPILootableInventory() { ++ return this; ++ } ++ ++ @Override ++ default World getNMSWorld() { ++ return getTileEntity().getWorld(); ++ } ++ ++ default Block getBlock() { ++ final BlockPosition position = getTileEntity().getPosition(); ++ final Chunk bukkitChunk = getTileEntity().getWorld().getChunkAtWorldCoords(position).bukkitChunk; ++ return bukkitChunk.getBlock(position.getX(), position.getY(), position.getZ()); ++ } ++ ++ @Override ++ default PaperLootableInventoryData getLootableData() { ++ return getTileEntity().lootableData; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..019a06fa2b43cacd3bbd4d58aba71b3728f37581 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java +@@ -0,0 +1,28 @@ ++package com.destroystokyo.paper.loottable; ++ ++import net.minecraft.world.level.World; ++import org.bukkit.entity.Entity; ++ ++public interface PaperLootableEntityInventory extends LootableEntityInventory, PaperLootableInventory { ++ ++ net.minecraft.world.entity.Entity getHandle(); ++ ++ @Override ++ default LootableInventory getAPILootableInventory() { ++ return this; ++ } ++ ++ default Entity getEntity() { ++ return getHandle().getBukkitEntity(); ++ } ++ ++ @Override ++ default World getNMSWorld() { ++ return getHandle().getWorld(); ++ } ++ ++ @Override ++ default PaperLootableInventoryData getLootableData() { ++ return getHandle().lootableData; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..59e8aea749bbba079e3304d9a5854280db2692e9 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java +@@ -0,0 +1,71 @@ ++package com.destroystokyo.paper.loottable; ++ ++import net.minecraft.world.level.World; ++import org.bukkit.loot.Lootable; ++ ++import java.util.UUID; ++ ++public interface PaperLootableInventory extends LootableInventory, Lootable { ++ ++ PaperLootableInventoryData getLootableData(); ++ LootableInventory getAPILootableInventory(); ++ ++ World getNMSWorld(); ++ ++ default org.bukkit.World getBukkitWorld() { ++ return getNMSWorld().getWorld(); ++ } ++ ++ @Override ++ default boolean isRefillEnabled() { ++ return getNMSWorld().paperConfig.autoReplenishLootables; ++ } ++ ++ @Override ++ default boolean hasBeenFilled() { ++ return getLastFilled() != -1; ++ } ++ ++ @Override ++ default boolean hasPlayerLooted(UUID player) { ++ return getLootableData().hasPlayerLooted(player); ++ } ++ ++ @Override ++ default Long getLastLooted(UUID player) { ++ return getLootableData().getLastLooted(player); ++ } ++ ++ @Override ++ default boolean setHasPlayerLooted(UUID player, boolean looted) { ++ final boolean hasLooted = hasPlayerLooted(player); ++ if (hasLooted != looted) { ++ getLootableData().setPlayerLootedState(player, looted); ++ } ++ return hasLooted; ++ } ++ ++ @Override ++ default boolean hasPendingRefill() { ++ long nextRefill = getLootableData().getNextRefill(); ++ return nextRefill != -1 && nextRefill > getLootableData().getLastFill(); ++ } ++ ++ @Override ++ default long getLastFilled() { ++ return getLootableData().getLastFill(); ++ } ++ ++ @Override ++ default long getNextRefill() { ++ return getLootableData().getNextRefill(); ++ } ++ ++ @Override ++ default long setNextRefill(long refillAt) { ++ if (refillAt < -1) { ++ refillAt = -1; ++ } ++ return getLootableData().setNextRefill(refillAt); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java +new file mode 100644 +index 0000000000000000000000000000000000000000..904332454ede006f4ee33337d46b11674d78bef7 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java +@@ -0,0 +1,181 @@ ++package com.destroystokyo.paper.loottable; ++ ++import com.destroystokyo.paper.PaperWorldConfig; ++import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.nbt.NBTTagList; ++import net.minecraft.world.entity.player.EntityHuman; ++import org.bukkit.entity.Player; ++import org.bukkit.loot.LootTable; ++ ++import javax.annotation.Nullable; ++import java.util.HashMap; ++import java.util.Map; ++import java.util.Random; ++import java.util.UUID; ++ ++public class PaperLootableInventoryData { ++ ++ private static final Random RANDOM = new Random(); ++ ++ private long lastFill = -1; ++ private long nextRefill = -1; ++ private int numRefills = 0; ++ private Map lootedPlayers; ++ private final PaperLootableInventory lootable; ++ ++ public PaperLootableInventoryData(PaperLootableInventory lootable) { ++ this.lootable = lootable; ++ } ++ ++ long getLastFill() { ++ return this.lastFill; ++ } ++ ++ long getNextRefill() { ++ return this.nextRefill; ++ } ++ ++ long setNextRefill(long nextRefill) { ++ long prev = this.nextRefill; ++ this.nextRefill = nextRefill; ++ return prev; ++ } ++ ++ public boolean shouldReplenish(@Nullable EntityHuman player) { ++ LootTable table = this.lootable.getLootTable(); ++ ++ // No Loot Table associated ++ if (table == null) { ++ return false; ++ } ++ ++ // ALWAYS process the first fill or if the feature is disabled ++ if (this.lastFill == -1 || !this.lootable.getNMSWorld().paperConfig.autoReplenishLootables) { ++ return true; ++ } ++ ++ // Only process refills when a player is set ++ if (player == null) { ++ return false; ++ } ++ ++ // Chest is not scheduled for refill ++ if (this.nextRefill == -1) { ++ return false; ++ } ++ ++ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; ++ ++ // Check if max refills has been hit ++ if (paperConfig.maxLootableRefills != -1 && this.numRefills >= paperConfig.maxLootableRefills) { ++ return false; ++ } ++ ++ // Refill has not been reached ++ if (this.nextRefill > System.currentTimeMillis()) { ++ return false; ++ } ++ ++ ++ final Player bukkitPlayer = (Player) player.getBukkitEntity(); ++ LootableInventoryReplenishEvent event = new LootableInventoryReplenishEvent(bukkitPlayer, lootable.getAPILootableInventory()); ++ if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUniqueID())) { ++ event.setCancelled(true); ++ } ++ return event.callEvent(); ++ } ++ public void processRefill(@Nullable EntityHuman player) { ++ this.lastFill = System.currentTimeMillis(); ++ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; ++ if (paperConfig.autoReplenishLootables) { ++ int min = paperConfig.lootableRegenMin; ++ int max = paperConfig.lootableRegenMax; ++ this.nextRefill = this.lastFill + (min + RANDOM.nextInt(max - min + 1)) * 1000L; ++ this.numRefills++; ++ if (paperConfig.changeLootTableSeedOnFill) { ++ this.lootable.setSeed(0); ++ } ++ if (player != null) { // This means that numRefills can be incremented without a player being in the lootedPlayers list - Seems to be EntityMinecartChest specific ++ this.setPlayerLootedState(player.getUniqueID(), true); ++ } ++ } else { ++ this.lootable.clearLootTable(); ++ } ++ } ++ ++ ++ public void loadNbt(NBTTagCompound base) { ++ if (!base.hasKeyOfType("Paper.LootableData", 10)) { // 10 = compound ++ return; ++ } ++ NBTTagCompound comp = base.getCompound("Paper.LootableData"); ++ if (comp.hasKey("lastFill")) { ++ this.lastFill = comp.getLong("lastFill"); ++ } ++ if (comp.hasKey("nextRefill")) { ++ this.nextRefill = comp.getLong("nextRefill"); ++ } ++ ++ if (comp.hasKey("numRefills")) { ++ this.numRefills = comp.getInt("numRefills"); ++ } ++ if (comp.hasKeyOfType("lootedPlayers", 9)) { // 9 = list ++ NBTTagList list = comp.getList("lootedPlayers", 10); // 10 = compound ++ final int size = list.size(); ++ if (size > 0) { ++ this.lootedPlayers = new HashMap<>(list.size()); ++ } ++ for (int i = 0; i < size; i++) { ++ final NBTTagCompound cmp = list.getCompound(i); ++ lootedPlayers.put(cmp.getUUID("UUID"), cmp.getLong("Time")); ++ } ++ } ++ } ++ public void saveNbt(NBTTagCompound base) { ++ NBTTagCompound comp = new NBTTagCompound(); ++ if (this.nextRefill != -1) { ++ comp.setLong("nextRefill", this.nextRefill); ++ } ++ if (this.lastFill != -1) { ++ comp.setLong("lastFill", this.lastFill); ++ } ++ if (this.numRefills != 0) { ++ comp.setInt("numRefills", this.numRefills); ++ } ++ if (this.lootedPlayers != null && !this.lootedPlayers.isEmpty()) { ++ NBTTagList list = new NBTTagList(); ++ for (Map.Entry entry : this.lootedPlayers.entrySet()) { ++ NBTTagCompound cmp = new NBTTagCompound(); ++ cmp.setUUID("UUID", entry.getKey()); ++ cmp.setLong("Time", entry.getValue()); ++ list.add(cmp); ++ } ++ comp.set("lootedPlayers", list); ++ } ++ ++ if (!comp.isEmpty()) { ++ base.set("Paper.LootableData", comp); ++ } ++ } ++ ++ void setPlayerLootedState(UUID player, boolean looted) { ++ if (looted && this.lootedPlayers == null) { ++ this.lootedPlayers = new HashMap<>(); ++ } ++ if (looted) { ++ if (!this.lootedPlayers.containsKey(player)) { ++ this.lootedPlayers.put(player, System.currentTimeMillis()); ++ } ++ } else if (this.lootedPlayers != null) { ++ this.lootedPlayers.remove(player); ++ } ++ } ++ ++ boolean hasPlayerLooted(UUID player) { ++ return this.lootedPlayers != null && this.lootedPlayers.containsKey(player); ++ } ++ ++ Long getLastLooted(UUID player) { ++ return lootedPlayers != null ? lootedPlayers.get(player) : null; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c682bd7700d8103533026d46cfc63a7abde5a5f4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java +@@ -0,0 +1,62 @@ ++package com.destroystokyo.paper.loottable; ++ ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.vehicle.EntityMinecartContainer; ++import net.minecraft.world.level.World; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++ ++public class PaperMinecartLootableInventory implements PaperLootableEntityInventory { ++ ++ private EntityMinecartContainer entity; ++ ++ public PaperMinecartLootableInventory(EntityMinecartContainer entity) { ++ this.entity = entity; ++ } ++ ++ @Override ++ public org.bukkit.loot.LootTable getLootTable() { ++ return entity.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.lootTable)) : null; ++ } ++ ++ @Override ++ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { ++ setLootTable(table); ++ setSeed(seed); ++ } ++ ++ @Override ++ public void setSeed(long seed) { ++ entity.lootTableSeed = seed; ++ } ++ ++ @Override ++ public long getSeed() { ++ return entity.lootTableSeed; ++ } ++ ++ @Override ++ public void setLootTable(org.bukkit.loot.LootTable table) { ++ entity.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); ++ } ++ ++ @Override ++ public PaperLootableInventoryData getLootableData() { ++ return entity.lootableData; ++ } ++ ++ @Override ++ public Entity getHandle() { ++ return entity; ++ } ++ ++ @Override ++ public LootableInventory getAPILootableInventory() { ++ return (LootableInventory) entity.getBukkitEntity(); ++ } ++ ++ @Override ++ public World getNMSWorld() { ++ return entity.world; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9dae34370d014a291f025f83b55e18bff4619a23 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java +@@ -0,0 +1,65 @@ ++package com.destroystokyo.paper.loottable; ++ ++import net.minecraft.server.MCUtil; ++import net.minecraft.world.level.World; ++import net.minecraft.world.level.block.entity.TileEntityLootable; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++ ++public class PaperTileEntityLootableInventory implements PaperLootableBlockInventory { ++ private TileEntityLootable tileEntityLootable; ++ ++ public PaperTileEntityLootableInventory(TileEntityLootable tileEntityLootable) { ++ this.tileEntityLootable = tileEntityLootable; ++ } ++ ++ @Override ++ public org.bukkit.loot.LootTable getLootTable() { ++ return tileEntityLootable.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null; ++ } ++ ++ @Override ++ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { ++ setLootTable(table); ++ setSeed(seed); ++ } ++ ++ @Override ++ public void setLootTable(org.bukkit.loot.LootTable table) { ++ tileEntityLootable.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); ++ } ++ ++ @Override ++ public void setSeed(long seed) { ++ tileEntityLootable.lootTableSeed = seed; ++ } ++ ++ @Override ++ public long getSeed() { ++ return tileEntityLootable.lootTableSeed; ++ } ++ ++ @Override ++ public PaperLootableInventoryData getLootableData() { ++ return tileEntityLootable.lootableData; ++ } ++ ++ @Override ++ public TileEntityLootable getTileEntity() { ++ return tileEntityLootable; ++ } ++ ++ @Override ++ public LootableInventory getAPILootableInventory() { ++ World world = tileEntityLootable.getWorld(); ++ if (world == null) { ++ return null; ++ } ++ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, tileEntityLootable.getPosition())).getState(); ++ } ++ ++ @Override ++ public World getNMSWorld() { ++ return tileEntityLootable.getWorld(); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 415935739716df3b8b3319aac19519d29aaa5776..092ee75f9527af25a48ab052659e3304986b50e0 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -158,6 +158,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + }; + // Paper end + ++ public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper + private CraftEntity bukkitEntity; + + public CraftEntity getBukkitEntity() { +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java +index c4b970c37b1792ac0022936f2df4740183621a0d..0166d11cb540a536390f486e1069d6119d8d23d6 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java +@@ -46,6 +46,7 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp + public long lootTableSeed; + + // CraftBukkit start ++ { this.lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperMinecartLootableInventory(this)); } // Paper + public List transaction = new java.util.ArrayList(); + private int maxStack = MAX_STACK; + +@@ -203,12 +204,13 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp + @Override + protected void saveData(NBTTagCompound nbttagcompound) { + super.saveData(nbttagcompound); ++ this.lootableData.saveNbt(nbttagcompound); // Paper + if (this.lootTable != null) { + nbttagcompound.setString("LootTable", this.lootTable.toString()); + if (this.lootTableSeed != 0L) { + nbttagcompound.setLong("LootTableSeed", this.lootTableSeed); + } +- } else { ++ } if (true) { // Paper - Always save the items, Table may stick around + ContainerUtil.a(nbttagcompound, this.items); + } + +@@ -217,11 +219,12 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp + @Override + protected void loadData(NBTTagCompound nbttagcompound) { + super.loadData(nbttagcompound); ++ this.lootableData.loadNbt(nbttagcompound); // Paper + this.items = NonNullList.a(this.getSize(), ItemStack.b); + if (nbttagcompound.hasKeyOfType("LootTable", 8)) { + this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable")); + this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); +- } else { ++ } if (true) { // Paper - always load the items, table may still remain + ContainerUtil.b(nbttagcompound, this.items); + } + +@@ -252,14 +255,15 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp + } + + public void d(@Nullable EntityHuman entityhuman) { +- if (this.lootTable != null && this.world.getMinecraftServer() != null) { ++ if (this.lootableData.shouldReplenish(entityhuman) && this.world.getMinecraftServer() != null) { // Paper + LootTable loottable = this.world.getMinecraftServer().getLootTableRegistry().getLootTable(this.lootTable); + + if (entityhuman instanceof EntityPlayer) { + CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable); + } + +- this.lootTable = null; ++ //this.lootTable = null; // Paper ++ this.lootableData.processRefill(entityhuman); // Paper + LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).set(LootContextParameters.ORIGIN, this.getPositionVector()).a(this.lootTableSeed); + + if (entityhuman != null) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java +index 62e6833a90d7adae3c7df33e3bc73b4288e0370b..1508e267a38555820e2d31f3075adca185fbd4b6 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java +@@ -27,6 +27,7 @@ public abstract class TileEntityLootable extends TileEntityContainer { + @Nullable + public MinecraftKey lootTable; + public long lootTableSeed; ++ public final com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperTileEntityLootableInventory(this)); // Paper + + protected TileEntityLootable(TileEntityTypes tileentitytypes) { + super(tileentitytypes); +@@ -42,16 +43,19 @@ public abstract class TileEntityLootable extends TileEntityContainer { + } + + protected boolean b(NBTTagCompound nbttagcompound) { ++ this.lootableData.loadNbt(nbttagcompound); // Paper + if (nbttagcompound.hasKeyOfType("LootTable", 8)) { + this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable")); ++ try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate + this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); +- return true; ++ return false; // Paper - always load the items, table may still remain + } else { + return false; + } + } + + protected boolean c(NBTTagCompound nbttagcompound) { ++ this.lootableData.saveNbt(nbttagcompound); // Paper + if (this.lootTable == null) { + return false; + } else { +@@ -60,19 +64,20 @@ public abstract class TileEntityLootable extends TileEntityContainer { + nbttagcompound.setLong("LootTableSeed", this.lootTableSeed); + } + +- return true; ++ return false; // Paper - always save the items, table may still remain + } + } + + public void d(@Nullable EntityHuman entityhuman) { +- if (this.lootTable != null && this.world.getMinecraftServer() != null) { ++ if (this.lootableData.shouldReplenish(entityhuman) && this.world.getMinecraftServer() != null) { // Paper + LootTable loottable = this.world.getMinecraftServer().getLootTableRegistry().getLootTable(this.lootTable); + + if (entityhuman instanceof EntityPlayer) { + CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable); + } + +- this.lootTable = null; ++ //this.lootTable = null; // Paper ++ this.lootableData.processRefill(entityhuman); // Paper + LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).set(LootContextParameters.ORIGIN, Vec3D.a((BaseBlockPosition) this.position)).a(this.lootTableSeed); + + if (entityhuman != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +index 524f27830752f424493c3ae8d793b871f6495594..dcf3f9265b0b00a7bbb9ff428e10da3c198ba08a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +@@ -64,7 +64,7 @@ public class CraftBlockEntityState extends CraftBlockState + } + + // gets the wrapped TileEntity +- protected T getTileEntity() { ++ public T getTileEntity() { // Paper - protected -> public + return tileEntity; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +index 486fa8937d644f59a770db163482259525a7e465..54eb170fd533b0e91572601268fcbc167ed9bb5c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +@@ -12,8 +12,9 @@ import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.inventory.CraftInventory; + import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest; + import org.bukkit.inventory.Inventory; ++import com.destroystokyo.paper.loottable.PaperLootableBlockInventory; // Paper + +-public class CraftChest extends CraftLootable implements Chest { ++public class CraftChest extends CraftLootable implements Chest, PaperLootableBlockInventory { // Paper + + public CraftChest(final Block block) { + super(block, TileEntityChest.class); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java +index f0a7e61a26c4668a9aa823d641f29bdecd42dd1f..3512054ede5fd1dd7605444e827e30a0be47f935 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java +@@ -10,7 +10,7 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; + import org.bukkit.loot.LootTable; + import org.bukkit.loot.Lootable; + +-public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable { ++public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable, com.destroystokyo.paper.loottable.PaperLootableBlockInventory { // Paper + + public CraftLootable(Block block, Class tileEntityClass) { + super(block, tileEntityClass); +@@ -54,7 +54,7 @@ public abstract class CraftLootable extends CraftC + setLootTable(getLootTable(), seed); + } + +- private void setLootTable(LootTable table, long seed) { ++ public void setLootTable(LootTable table, long seed) { // Paper - public + MinecraftKey key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); + getSnapshot().setLootTable(key, seed); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java +index cbd121c21adfaf098dadca33de16a2e68d83c19a..d9a2552782c9242fb84cc0c8309a614a44777509 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java +@@ -8,7 +8,7 @@ import org.bukkit.entity.minecart.StorageMinecart; + import org.bukkit.inventory.Inventory; + + @SuppressWarnings("deprecation") +-public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart { ++public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper + private final CraftInventory inventory; + + public CraftMinecartChest(CraftServer server, EntityMinecartChest entity) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java +index 5ffb8108f456c2f7f3ed1a25249baccb4cbf4add..bf8b5b25d1af0c5129261e10abf2866521b2c375 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java +@@ -47,7 +47,7 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo + return getHandle().lootTableSeed; + } + +- private void setLootTable(LootTable table, long seed) { ++ public void setLootTable(LootTable table, long seed) { // Paper + MinecraftKey newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); + getHandle().setLootTable(newKey, seed); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +index 17a42aec76f32a28b0c9885c60d1ed50c6727161..bfdcf01d2c6570493e86330d56500427dbb23146 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +@@ -7,7 +7,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.minecart.HopperMinecart; + import org.bukkit.inventory.Inventory; + +-public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart { ++public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper + private final CraftInventory inventory; + + public CraftMinecartHopper(CraftServer server, EntityMinecartHopper entity) { diff --git a/patches/server-unmapped/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/patches/server-unmapped/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch new file mode 100644 index 0000000000..a61442ff71 --- /dev/null +++ b/patches/server-unmapped/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 May 2016 23:33:08 -0400 +Subject: [PATCH] Don't save empty scoreboard teams to scoreboard.dat + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 504efea7b6f50a0d17f4f353781953dfb18bdeca..1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -237,4 +237,9 @@ public class PaperConfig { + private static void enablePlayerCollisions() { + enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); + } ++ ++ public static boolean saveEmptyScoreboardTeams = false; ++ private static void saveEmptyScoreboardTeams() { ++ saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java b/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java +index 3998565ccd87c966c0fb9e6757cd1861faa5bc15..52f27bdbd0df8bbbf2ad5144bc262b5093d83413 100644 +--- a/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java ++++ b/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java +@@ -182,6 +182,7 @@ public class PersistentScoreboard extends PersistentBase { + + while (iterator.hasNext()) { + ScoreboardTeam scoreboardteam = (ScoreboardTeam) iterator.next(); ++ if (!com.destroystokyo.paper.PaperConfig.saveEmptyScoreboardTeams && scoreboardteam.getPlayerNameSet().isEmpty()) continue; // Paper + NBTTagCompound nbttagcompound = new NBTTagCompound(); + + nbttagcompound.setString("Name", scoreboardteam.getName()); diff --git a/patches/server-unmapped/0098-System-property-for-disabling-watchdoge.patch b/patches/server-unmapped/0098-System-property-for-disabling-watchdoge.patch new file mode 100644 index 0000000000..1cbedf26ca --- /dev/null +++ b/patches/server-unmapped/0098-System-property-for-disabling-watchdoge.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 12 May 2016 23:02:58 -0500 +Subject: [PATCH] System property for disabling watchdoge + + +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 69e5054886b5858664fed333aca8c25a76e5cb11..4e0291be4bd5876bb5b5f62ebfa156635d4c758f 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -61,7 +61,7 @@ public class WatchdogThread extends Thread + while ( !stopping ) + { + // +- if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime ) ++ if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable + { + Logger log = Bukkit.getServer().getLogger(); + log.log( Level.SEVERE, "------------------------------" ); diff --git a/patches/server-unmapped/0099-Optimize-UserCache-Thread-Safe.patch b/patches/server-unmapped/0099-Optimize-UserCache-Thread-Safe.patch new file mode 100644 index 0000000000..a7c61c2859 --- /dev/null +++ b/patches/server-unmapped/0099-Optimize-UserCache-Thread-Safe.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 16 May 2016 20:47:41 -0400 +Subject: [PATCH] Optimize UserCache / Thread Safe + +Because Techable keeps complaining about how this isn't thread safe, +easier to do this than replace the entire thing. + +Additionally, move Saving of the User cache to be done async, incase +the user never changed the default setting for Spigot's save on stop only. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index ed00ee8e56e6ca38a1ac689458c4675eff6e3eea..20dffd9dc4cb3868638151b70535f353a3bf1a44 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -907,7 +907,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { // Paper + + try { + BufferedWriter bufferedwriter = Files.newWriter(this.g, StandardCharsets.UTF_8); +@@ -268,6 +270,14 @@ public class UserCache { + } catch (IOException ioexception) { + ; + } ++ // Paper start ++ }; ++ if (asyncSave) { ++ MCUtil.scheduleAsyncTask(save); ++ } else { ++ save.run(); ++ } ++ // Paper end + + } + diff --git a/patches/server-unmapped/0100-Avoid-blocking-on-Network-Manager-creation.patch b/patches/server-unmapped/0100-Avoid-blocking-on-Network-Manager-creation.patch new file mode 100644 index 0000000000..dd0b2f44b9 --- /dev/null +++ b/patches/server-unmapped/0100-Avoid-blocking-on-Network-Manager-creation.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 16 May 2016 23:19:16 -0400 +Subject: [PATCH] Avoid blocking on Network Manager creation + +Per Paper issue 294 + +diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java +index f66a5ba901601c1d359a287861a2edd8e3a106a7..d992cb5cd827e0fe655809e1088939cdad9c2301 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnection.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnection.java +@@ -52,6 +52,15 @@ public class ServerConnection { + public volatile boolean c; + private final List listeningChannels = Collections.synchronizedList(Lists.newArrayList()); + private final List connectedChannels = Collections.synchronizedList(Lists.newArrayList()); ++ // Paper start - prevent blocking on adding a new network manager while the server is ticking ++ private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ private void addPending() { ++ NetworkManager manager = null; ++ while ((manager = pending.poll()) != null) { ++ connectedChannels.add(manager); ++ } ++ } ++ // Paper end + + public ServerConnection(MinecraftServer minecraftserver) { + this.e = minecraftserver; +@@ -87,7 +96,8 @@ public class ServerConnection { + int j = ServerConnection.this.e.k(); + Object object = j > 0 ? new NetworkManagerServer(j) : new NetworkManager(EnumProtocolDirection.SERVERBOUND); + +- ServerConnection.this.connectedChannels.add((NetworkManager) object); // CraftBukkit - decompile error ++ //ServerConnection.this.connectedChannels.add((NetworkManager) object); // CraftBukkit - decompile error ++ pending.add((NetworkManager) object); // Paper + channel.pipeline().addLast("packet_handler", (ChannelHandler) object); + ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object)); + } +@@ -126,6 +136,7 @@ public class ServerConnection { + + synchronized (this.connectedChannels) { + // Spigot Start ++ this.addPending(); // Paper + // This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order + if ( org.spigotmc.SpigotConfig.playerShuffle > 0 && MinecraftServer.currentTick % org.spigotmc.SpigotConfig.playerShuffle == 0 ) + { diff --git a/patches/server-unmapped/0101-Optional-TNT-doesn-t-move-in-water.patch b/patches/server-unmapped/0101-Optional-TNT-doesn-t-move-in-water.patch new file mode 100644 index 0000000000..8f5d535c75 --- /dev/null +++ b/patches/server-unmapped/0101-Optional-TNT-doesn-t-move-in-water.patch @@ -0,0 +1,122 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 22 May 2016 20:20:55 -0500 +Subject: [PATCH] Optional TNT doesn't move in water + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index eb04fdb172a50ec1f5b7fe78fa0e7655246abd60..6eca3f300020006f02dd36253b522db442e3cc33 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -2,7 +2,6 @@ package com.destroystokyo.paper; + + import java.util.List; + +-import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; + +@@ -291,4 +290,14 @@ public class PaperWorldConfig { + ); + } + } ++ ++ public boolean preventTntFromMovingInWater; ++ private void preventTntFromMovingInWater() { ++ if (PaperConfig.version < 13) { ++ boolean oldVal = getBoolean("enable-old-tnt-cannon-behaviors", false); ++ set("prevent-tnt-from-moving-in-water", oldVal); ++ } ++ preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); ++ log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +index beb0beb716869978be6bc5a78ce3b6cf785c5aee..e3cdea3c85d762af6984f3dbe544fdfe101f6ff6 100644 +--- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java ++++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +@@ -67,7 +67,7 @@ public class EntityTrackerEntry { + private boolean q; + private boolean r; + // CraftBukkit start +- private final Set trackedPlayers; ++ final Set trackedPlayers; // Paper - private -> package + // Paper start + private java.util.Map trackedPlayerMap = null; + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 092ee75f9527af25a48ab052659e3304986b50e0..d314cdd9341e6aa5748a5b1afdd9569bec956c74 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2771,6 +2771,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public boolean bV() { ++ // Paper start ++ return this.pushedByWater(); ++ } ++ public boolean pushedByWater() { ++ // Paper end + return true; + } + +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java +index 535e7d7297d81026b8586d5049b72fa65519b464..63b35feac07f01b200dd68c4836ceb419e951660 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java +@@ -4,10 +4,14 @@ import javax.annotation.Nullable; + import net.minecraft.core.particles.Particles; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.protocol.Packet; ++import net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport; ++import net.minecraft.network.protocol.game.PacketPlayOutEntityVelocity; + import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.level.PlayerChunkMap; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.EntityPose; +@@ -96,7 +100,27 @@ public class EntityTNTPrimed extends Entity { + this.world.addParticle(Particles.SMOKE, this.locX(), this.locY() + 0.5D, this.locZ(), 0.0D, 0.0D, 0.0D); + } + } +- ++ // Paper start - Optional prevent TNT from moving in water ++ if (!this.dead && this.inWater && this.world.paperConfig.preventTntFromMovingInWater) { ++ /* ++ * Author: Jedediah Smith ++ */ ++ // Send position and velocity updates to nearby players on every tick while the TNT is in water. ++ // This does pretty well at keeping their clients in sync with the server. ++ PlayerChunkMap.EntityTracker ete = ((WorldServer)this.world).getChunkProvider().playerChunkMap.trackedEntities.get(this.getId()); ++ if (ete != null) { ++ PacketPlayOutEntityVelocity velocityPacket = new PacketPlayOutEntityVelocity(this); ++ PacketPlayOutEntityTeleport positionPacket = new PacketPlayOutEntityTeleport(this); ++ ++ ete.trackedPlayers.stream() ++ .filter(viewer -> (viewer.locX() - this.locX()) * (viewer.locY() - this.locY()) * (viewer.locZ() - this.locZ()) < 16 * 16) ++ .forEach(viewer -> { ++ viewer.playerConnection.sendPacket(velocityPacket); ++ viewer.playerConnection.sendPacket(positionPacket); ++ }); ++ } ++ } ++ // Paper end + } + + private void explode() { +@@ -165,4 +189,11 @@ public class EntityTNTPrimed extends Entity { + public Packet P() { + return new PacketPlayOutSpawnEntity(this); + } ++ ++ // Paper start - Optional prevent TNT from moving in water ++ @Override ++ public boolean pushedByWater() { ++ return !world.paperConfig.preventTntFromMovingInWater && super.pushedByWater(); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0102-Faster-redstone-torch-rapid-clock-removal.patch b/patches/server-unmapped/0102-Faster-redstone-torch-rapid-clock-removal.patch new file mode 100644 index 0000000000..7aa9554cd7 --- /dev/null +++ b/patches/server-unmapped/0102-Faster-redstone-torch-rapid-clock-removal.patch @@ -0,0 +1,98 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Panzer +Date: Mon, 23 May 2016 12:12:37 +0200 +Subject: [PATCH] Faster redstone torch rapid clock removal + +Only resize the the redstone torch list once, since resizing arrays / lists is costly + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index cad86b0273c05767f78bcb3bdfaa9ea01e26af4e..d8ab2e22a5c0144decb5c657a123cc61722fcbf5 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -44,6 +44,7 @@ import net.minecraft.world.level.biome.BiomeBase; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.BlockFireAbstract; ++import net.minecraft.world.level.block.BlockRedstoneTorch; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.ITickable; + import net.minecraft.world.level.block.entity.TileEntity; +@@ -142,6 +143,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + private org.spigotmc.TickLimiter tileLimiter; + private int tileTickPosition; + public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions ++ public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here + + public CraftWorld getWorld() { + return this.world; +diff --git a/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java b/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java +index 8142c0be2978d8975612488b17da9c2e25f3b5dd..6771c16b4228c1495950484422b73928f6184929 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java +@@ -22,7 +22,7 @@ import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + public class BlockRedstoneTorch extends BlockTorch { + + public static final BlockStateBoolean LIT = BlockProperties.r; +- private static final Map> b = new WeakHashMap(); ++ // Paper - Move the mapped list to World + + protected BlockRedstoneTorch(BlockBase.Info blockbase_info) { + super(blockbase_info, ParticleParamRedstone.a); +@@ -69,11 +69,15 @@ public class BlockRedstoneTorch extends BlockTorch { + @Override + public void tickAlways(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { + boolean flag = this.a((World) worldserver, blockposition, iblockdata); +- List list = (List) BlockRedstoneTorch.b.get(worldserver); +- +- while (list != null && !list.isEmpty() && worldserver.getTime() - ((BlockRedstoneTorch.RedstoneUpdateInfo) list.get(0)).b > 60L) { +- list.remove(0); ++ // Paper start ++ java.util.ArrayDeque redstoneUpdateInfos = worldserver.redstoneUpdateInfos; ++ if (redstoneUpdateInfos != null) { ++ BlockRedstoneTorch.RedstoneUpdateInfo curr; ++ while ((curr = redstoneUpdateInfos.peek()) != null && worldserver.getTime() - curr.getTime() > 60L) { ++ redstoneUpdateInfos.poll(); ++ } + } ++ // Paper end + + // CraftBukkit start + org.bukkit.plugin.PluginManager manager = worldserver.getServer().getPluginManager(); +@@ -138,9 +142,12 @@ public class BlockRedstoneTorch extends BlockTorch { + } + + private static boolean a(World world, BlockPosition blockposition, boolean flag) { +- List list = (List) BlockRedstoneTorch.b.computeIfAbsent(world, (iblockaccess) -> { +- return Lists.newArrayList(); +- }); ++ // Paper start ++ java.util.ArrayDeque list = world.redstoneUpdateInfos; ++ if (list == null) { ++ list = world.redstoneUpdateInfos = new java.util.ArrayDeque<>(); ++ } ++ + + if (flag) { + list.add(new BlockRedstoneTorch.RedstoneUpdateInfo(blockposition.immutableCopy(), world.getTime())); +@@ -148,9 +155,9 @@ public class BlockRedstoneTorch extends BlockTorch { + + int i = 0; + +- for (int j = 0; j < list.size(); ++j) { +- BlockRedstoneTorch.RedstoneUpdateInfo blockredstonetorch_redstoneupdateinfo = (BlockRedstoneTorch.RedstoneUpdateInfo) list.get(j); +- ++ for (java.util.Iterator iterator = list.iterator(); iterator.hasNext();) { ++ BlockRedstoneTorch.RedstoneUpdateInfo blockredstonetorch_redstoneupdateinfo = iterator.next(); ++ // Paper end + if (blockredstonetorch_redstoneupdateinfo.a.equals(blockposition)) { + ++i; + if (i >= 8) { +@@ -165,7 +172,7 @@ public class BlockRedstoneTorch extends BlockTorch { + public static class RedstoneUpdateInfo { + + private final BlockPosition a; +- private final long b; ++ private final long b; final long getTime() { return this.b; } // Paper - OBFHELPER + + public RedstoneUpdateInfo(BlockPosition blockposition, long i) { + this.a = blockposition; diff --git a/patches/server-unmapped/0103-Add-server-name-parameter.patch b/patches/server-unmapped/0103-Add-server-name-parameter.patch new file mode 100644 index 0000000000..50ec621547 --- /dev/null +++ b/patches/server-unmapped/0103-Add-server-name-parameter.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Panzer +Date: Sat, 28 May 2016 16:54:03 +0200 +Subject: [PATCH] Add server-name parameter + + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2..b849b2afd009da433fe6cea5837b3ee9bb5c52b4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -143,6 +143,14 @@ public class Main { + .defaultsTo(new File("paper.yml")) + .describedAs("Yml file"); + // Paper end ++ ++ // Paper start ++ acceptsAll(asList("server-name"), "Name of the server") ++ .withRequiredArg() ++ .ofType(String.class) ++ .defaultsTo("Unknown Server") ++ .describedAs("Name"); ++ // Paper end + } + }; + diff --git a/patches/server-unmapped/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/patches/server-unmapped/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch new file mode 100644 index 0000000000..0b6b3e6fdb --- /dev/null +++ b/patches/server-unmapped/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 31 May 2016 22:53:50 -0400 +Subject: [PATCH] Only send Dragon/Wither Death sounds to same world + +Also fix view distance lookup + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +index 6c58cf9d39cc0f0eb0dc7ddb126b8a3cf6a08fe7..74802de01dba30e38e09f6fc1f61e7bb64cf5f09 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +@@ -619,8 +619,9 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + if (this.deathAnimationTicks == 1 && !this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1028, this.getChunkCoordinates(), 0); +- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; +- for (net.minecraft.server.level.EntityPlayer player : this.world.getMinecraftServer().getPlayerList().players) { ++ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ for (net.minecraft.server.level.EntityPlayer player : (List) ((WorldServer)world).getPlayers()) { ++ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch + double deltaX = this.locX() - player.locX(); + double deltaZ = this.locZ() - player.locZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +index f74949c855aea32ceb16d8cb07f266d50045b57e..145767e8b0fc4105a0afa47af17dcdbb75e952bc 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +@@ -258,8 +258,9 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + if (!this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1023, new BlockPosition(this), 0); +- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; +- for (EntityPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { ++ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ for (EntityPlayer player : (List)this.world.getPlayers()) { ++ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch + double deltaX = this.locX() - player.locX(); + double deltaZ = this.locZ() - player.locZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; diff --git a/patches/server-unmapped/0105-Fix-Double-World-Add-issues.patch b/patches/server-unmapped/0105-Fix-Double-World-Add-issues.patch new file mode 100644 index 0000000000..45f6cacfcf --- /dev/null +++ b/patches/server-unmapped/0105-Fix-Double-World-Add-issues.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 21 Jun 2016 22:54:34 -0400 +Subject: [PATCH] Fix Double World Add issues + +Vanilla will double add Spider Jockeys to the world, so ignore already added. + +Also add debug if something else tries to, and abort before world gets bad state + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index c7652d6bff7630e2eefbb4c3b0deb6e17b9c98d0..811e80ebb65715b7cdd1443aa33186c3ce2ec70c 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1038,6 +1038,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + // CraftBukkit start + private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot ++ if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper + if (entity.dead) { + // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit + return false; diff --git a/patches/server-unmapped/0106-Fix-Old-Sign-Conversion.patch b/patches/server-unmapped/0106-Fix-Old-Sign-Conversion.patch new file mode 100644 index 0000000000..e06e531049 --- /dev/null +++ b/patches/server-unmapped/0106-Fix-Old-Sign-Conversion.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 17 Jun 2016 20:50:11 -0400 +Subject: [PATCH] Fix Old Sign Conversion + +1) Sign loading code was trying to parse the JSON before the check for oldSign. + That code could then skip the old sign converting code if it triggers a JSON parse exception. +2) New Mojang Schematic system has Tile Entities in the new converted format, but missing the Bukkit.isConverted flag + This causes Igloos and such to render broken signs. We fix this by ignoring sign conversion for Defined Structures + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +index 58789a6e285c31947508deae37caefe7e182278c..9b44ca96669ce423e5649f11743226dfdd9ce746 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +@@ -34,6 +34,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / + public CraftPersistentDataContainer persistentDataContainer; + // CraftBukkit end + private static final Logger LOGGER = LogManager.getLogger(); ++ public boolean isLoadingStructure = false; // Paper + private final TileEntityTypes tileType; public TileEntityTypes getTileEntityType() { return tileType; } // Paper - OBFHELPER + @Nullable + protected World world; +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java +index 29db550d91cf9e5a23052772df6e482a5e2b0b90..ec550aaa4e7943af4ecdd2275f1f32c21edf770a 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java +@@ -78,13 +78,14 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // + } + + try { +- IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); ++ //IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); // Paper - move down - the old format might throw a json error + +- if (oldSign) { ++ if (oldSign && !isLoadingStructure) { // Paper - saved structures will be in the new format, but will not have isConverted + lines[i] = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s)[0]; + continue; + } + // CraftBukkit end ++ IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); // Paper - after old sign + + if (this.world instanceof WorldServer) { + try { +diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java +index a2bc771df054923a9a96c0024a426ef707624359..9b82ff37faaafc3a799413f6949fb88a993aa9a0 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java +@@ -278,9 +278,11 @@ public class DefinedStructure { + definedstructure_blockinfo.c.setLong("LootTableSeed", random.nextLong()); + } + ++ tileentity.isLoadingStructure = true; // Paper + tileentity.load(definedstructure_blockinfo.b, definedstructure_blockinfo.c); + tileentity.a(definedstructureinfo.c()); + tileentity.a(definedstructureinfo.d()); ++ tileentity.isLoadingStructure = false; // Paper + } + } + diff --git a/patches/server-unmapped/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/patches/server-unmapped/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch new file mode 100644 index 0000000000..60ded56167 --- /dev/null +++ b/patches/server-unmapped/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 16 Jul 2016 19:11:17 -0500 +Subject: [PATCH] Don't lookup game profiles that have no UUID and no name + + +diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java +index 39d1c379b781c08bfdd720cd6810a9c0bb9f0d09..4ad084e7cea3b341ca0dbaa6e853cfc685a555ff 100644 +--- a/src/main/java/net/minecraft/server/players/UserCache.java ++++ b/src/main/java/net/minecraft/server/players/UserCache.java +@@ -92,7 +92,7 @@ public class UserCache { + gameprofilerepository.findProfilesByNames(new String[]{s}, Agent.MINECRAFT, profilelookupcallback); + GameProfile gameprofile = (GameProfile) atomicreference.get(); + +- if (!c() && gameprofile == null) { ++ if (!c() && gameprofile == null && !org.apache.commons.lang3.StringUtils.isBlank(s)) { // Paper - Don't lookup a profile with a blank name + UUID uuid = EntityHuman.a(new GameProfile((UUID) null, s)); + + gameprofile = new GameProfile(uuid, s); diff --git a/patches/server-unmapped/0108-Add-setting-for-proxy-online-mode-status.patch b/patches/server-unmapped/0108-Add-setting-for-proxy-online-mode-status.patch new file mode 100644 index 0000000000..0cec0451f3 --- /dev/null +++ b/patches/server-unmapped/0108-Add-setting-for-proxy-online-mode-status.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gabriele C +Date: Fri, 5 Aug 2016 01:03:08 +0200 +Subject: [PATCH] Add setting for proxy online mode status + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2..c52dc0346f93527965ef29a0ccdc4bf3debe302e 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -23,6 +23,7 @@ import org.bukkit.configuration.InvalidConfigurationException; + import org.bukkit.configuration.file.YamlConfiguration; + import co.aikar.timings.Timings; + import co.aikar.timings.TimingsManager; ++import org.spigotmc.SpigotConfig; + + public class PaperConfig { + +@@ -242,4 +243,13 @@ public class PaperConfig { + private static void saveEmptyScoreboardTeams() { + saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); + } ++ ++ public static boolean bungeeOnlineMode = true; ++ private static void bungeeOnlineMode() { ++ bungeeOnlineMode = getBoolean("settings.bungee-online-mode", true); ++ } ++ ++ public static boolean isProxyOnlineMode() { ++ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); ++ } + } +diff --git a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java +index 8a343a857dc4661ba256e39cf391dd2c7a1cc970..8c1f328ca1ba12ed63ec7bd7efad54ff633ba802 100644 +--- a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java ++++ b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java +@@ -66,7 +66,8 @@ public class NameReferencingFileConverter { + return new String[i]; + }); + +- if (minecraftserver.getOnlineMode() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. ++ if (minecraftserver.getOnlineMode() ++ || (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode())) { // Spigot: bungee = online mode, for now. // Paper - Handle via setting + minecraftserver.getGameProfileRepository().findProfilesByNames(astring, Agent.MINECRAFT, profilelookupcallback); + } else { + String[] astring1 = astring; +diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java +index 4ad084e7cea3b341ca0dbaa6e853cfc685a555ff..b9f94f957dd5372c8b02d785204690e4ade36a98 100644 +--- a/src/main/java/net/minecraft/server/players/UserCache.java ++++ b/src/main/java/net/minecraft/server/players/UserCache.java +@@ -89,6 +89,7 @@ public class UserCache { + } + }; + ++ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) // Paper - only run in online mode - 100 COL + gameprofilerepository.findProfilesByNames(new String[]{s}, Agent.MINECRAFT, profilelookupcallback); + GameProfile gameprofile = (GameProfile) atomicreference.get(); + +@@ -106,7 +107,7 @@ public class UserCache { + } + + private static boolean c() { +- return UserCache.b; ++ return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper + } + + public synchronized void a(GameProfile gameprofile) { // Paper - synchronize +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index e670f484d454f7c706a0ec92c98087fa1373c492..b392f7703222dbba30cdd81ac83e93da36ec043f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1516,7 +1516,8 @@ public final class CraftServer implements Server { + // Spigot Start + GameProfile profile = null; + // Only fetch an online UUID in online mode +- if ( getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) ++ if ( getOnlineMode() ++ || com.destroystokyo.paper.PaperConfig.isProxyOnlineMode() ) // Paper - Handle via setting + { + profile = console.getUserCache().getProfile( name ); + } diff --git a/patches/server-unmapped/0109-Optimise-BlockState-s-hashCode-equals.patch b/patches/server-unmapped/0109-Optimise-BlockState-s-hashCode-equals.patch new file mode 100644 index 0000000000..909f6b5273 --- /dev/null +++ b/patches/server-unmapped/0109-Optimise-BlockState-s-hashCode-equals.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Fri, 19 Aug 2016 01:52:56 +0100 +Subject: [PATCH] Optimise BlockState's hashCode/equals + +These are singleton "single instance" objects. We can rely on +object identity checks safely. + +Use a simpler optimized hashcode + +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java +index 0701c1a178852345b6bf01bce8b1d0559c535d45..f2f94950681b198ae7a4c31a044fd62e98e448ab 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java +@@ -30,8 +30,7 @@ public class BlockStateBoolean extends IBlockState { + return obool.toString(); + } + +- @Override +- public boolean equals(Object object) { ++ public boolean equals_unused(Object object) { // Paper + if (this == object) { + return true; + } else if (object instanceof BlockStateBoolean && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java +index de85894beae7ee7d276cf2af3daa77377ce131c3..3079cd13ea1465f4221fde4fec7df639f7c1eb49 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java +@@ -50,8 +50,7 @@ public class BlockStateEnum & INamable> extends IBlockState + return ((INamable) t0).getName(); + } + +- @Override +- public boolean equals(Object object) { ++ public boolean equals_unused(Object object) { // Paper + if (this == object) { + return true; + } else if (object instanceof BlockStateEnum && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java +index 518c2ebe4cdfe4704bbec2abe81522cbca38da55..190978c889222185b47065e9e5f96a82e59c7b4e 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java +@@ -38,8 +38,7 @@ public class BlockStateInteger extends IBlockState { + return this.a; + } + +- @Override +- public boolean equals(Object object) { ++ public boolean equals_unused(Object object) { // Paper + if (this == object) { + return true; + } else if (object instanceof BlockStateInteger && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java +index e3969bad5be64bb41e2973751605d6820c16f021..759d6a4adaa511488ace5e2650eb685cbb6c4c16 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java +@@ -60,23 +60,17 @@ public abstract class IBlockState> { + } + + public boolean equals(Object object) { +- if (this == object) { +- return true; +- } else if (!(object instanceof IBlockState)) { +- return false; +- } else { +- IBlockState iblockstate = (IBlockState) object; +- +- return this.a.equals(iblockstate.a) && this.b.equals(iblockstate.b); +- } ++ return this == object; // Paper - only one instance per configuration + } + ++ private static final java.util.concurrent.atomic.AtomicInteger hashId = new java.util.concurrent.atomic.AtomicInteger(1); // Paper - only one instance per configuration ++ private final int hashCode = 92821 * hashId.getAndIncrement(); // Paper - only one instance per configuration + public final int hashCode() { + if (this.c == null) { + this.c = this.b(); + } + +- return this.c; ++ return this.hashCode; // Paper - only one instance per configuration + } + + public int b() { diff --git a/patches/server-unmapped/0110-Configurable-packet-in-spam-threshold.patch b/patches/server-unmapped/0110-Configurable-packet-in-spam-threshold.patch new file mode 100644 index 0000000000..e9da45ba0e --- /dev/null +++ b/patches/server-unmapped/0110-Configurable-packet-in-spam-threshold.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 11 Sep 2016 14:30:57 -0500 +Subject: [PATCH] Configurable packet in spam threshold + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index c52dc0346f93527965ef29a0ccdc4bf3debe302e..64d7c9058ee757a6d3cf3b648596092a810e105c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -252,4 +252,13 @@ public class PaperConfig { + public static boolean isProxyOnlineMode() { + return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); + } ++ ++ public static int packetInSpamThreshold = 300; ++ private static void packetInSpamThreshold() { ++ if (version < 11) { ++ int oldValue = getInt("settings.play-in-use-item-spam-threshold", 300); ++ set("settings.incoming-packet-spam-threshold", oldValue); ++ } ++ packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index d3938e1fbab0a01ae5045858b1f421e041b768e2..09fa4bd7899ad01c43ce35ed2306eec434ebc0fe 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1465,13 +1465,14 @@ public class PlayerConnection implements PacketListenerPlayIn { + // Spigot start - limit place/interactions + private int limitedPackets; + private long lastLimitedPacket = -1; ++ private static final int THRESHOLD = com.destroystokyo.paper.PaperConfig.packetInSpamThreshold; // Paper - Configurable threshold + + private boolean checkLimit(long timestamp) { +- if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < 30 && limitedPackets++ >= 4) { ++ if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < THRESHOLD && limitedPackets++ >= 8) { // Paper - Use threshold, raise packet limit to 8 + return false; + } + +- if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= 30) { ++ if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= THRESHOLD) { // Paper + lastLimitedPacket = timestamp; + limitedPackets = 0; + return true; diff --git a/patches/server-unmapped/0111-Configurable-flying-kick-messages.patch b/patches/server-unmapped/0111-Configurable-flying-kick-messages.patch new file mode 100644 index 0000000000..22c865ee62 --- /dev/null +++ b/patches/server-unmapped/0111-Configurable-flying-kick-messages.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Tue, 20 Sep 2016 00:58:01 +0000 +Subject: [PATCH] Configurable flying kick messages + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 64d7c9058ee757a6d3cf3b648596092a810e105c..4e2f243faa209925dcb7c3ef89df3ed875c5ff78 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -261,4 +261,11 @@ public class PaperConfig { + } + packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); + } ++ ++ public static String flyingKickPlayerMessage = "Flying is not enabled on this server"; ++ public static String flyingKickVehicleMessage = "Flying is not enabled on this server"; ++ private static void flyingKickMessages() { ++ flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); ++ flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 09fa4bd7899ad01c43ce35ed2306eec434ebc0fe..15daf87d6a6d80b5ebce5360e6999fd604c66cb5 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -307,7 +307,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + if (this.B && !this.player.isSleeping()) { + if (++this.C > 80) { + PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", this.player.getDisplayName().getString()); +- this.disconnect(new ChatMessage("multiplayer.disconnect.flying")); ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message + return; + } + } else { +@@ -326,7 +326,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + if (this.D && this.player.getRootVehicle().getRidingPassenger() == this.player) { + if (++this.E > 80) { + PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getDisplayName().getString()); +- this.disconnect(new ChatMessage("multiplayer.disconnect.flying")); ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message + return; + } + } else { diff --git a/patches/server-unmapped/0112-Chunk-registration-fixes.patch b/patches/server-unmapped/0112-Chunk-registration-fixes.patch new file mode 100644 index 0000000000..ada089c700 --- /dev/null +++ b/patches/server-unmapped/0112-Chunk-registration-fixes.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Sep 2016 22:54:28 -0400 +Subject: [PATCH] Chunk registration fixes + +World checks and the Chunk Add logic are inconsistent on how Y > 256, < 0, is treated + +Keep them consistent + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 811e80ebb65715b7cdd1443aa33186c3ce2ec70c..744ec6f09a1b3ccdf0d74fe50f1e1c913ee2df86 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -847,7 +847,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + if (entity.cl()) { + this.getMethodProfiler().enter("chunkCheck"); + int i = MathHelper.floor(entity.locX() / 16.0D); +- int j = MathHelper.floor(entity.locY() / 16.0D); ++ int j = Math.min(15, Math.max(0, MathHelper.floor(entity.locY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior + int k = MathHelper.floor(entity.locZ() / 16.0D); + + if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) { diff --git a/patches/server-unmapped/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/patches/server-unmapped/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch new file mode 100644 index 0000000000..ea0d507b64 --- /dev/null +++ b/patches/server-unmapped/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 16 Jun 2016 00:17:23 -0400 +Subject: [PATCH] Remove FishingHook reference on Craft Entity removal + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java +index 4dd3deaabfdb383ded92920e1a313b61a1b9262b..4805bce05f2856289608f45df4fca322de161b31 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java +@@ -119,4 +119,14 @@ public class CraftFishHook extends CraftProjectile implements FishHook { + public HookState getState() { + return HookState.values()[getHandle().hookState.ordinal()]; + } ++ ++ // Paper start ++ @Override ++ public void remove() { ++ super.remove(); ++ if (getHandle().getOwner() != null) { ++ getHandle().getOwner().hookedFish = null; ++ } ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0114-Auto-fix-bad-Y-levels-on-player-login.patch b/patches/server-unmapped/0114-Auto-fix-bad-Y-levels-on-player-login.patch new file mode 100644 index 0000000000..b4d980555f --- /dev/null +++ b/patches/server-unmapped/0114-Auto-fix-bad-Y-levels-on-player-login.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Sep 2016 23:48:39 -0400 +Subject: [PATCH] Auto fix bad Y levels on player login + +Bring down to a saner Y level if super high, as this can cause the server to crash + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 3f1f8f7fe9452f66b18a08ef480d50ef78ad3351..3fca9c3566b5d9a1fafeb0700942d7658cd5a279 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -340,6 +340,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + @Override + public void loadData(NBTTagCompound nbttagcompound) { + super.loadData(nbttagcompound); ++ if (this.locY() > 300) this.setPositionRaw(locX(), 257, locZ()); // Paper - bring down to a saner Y level if out of world + if (nbttagcompound.hasKeyOfType("playerGameType", 99)) { + if (this.getMinecraftServer().getForceGamemode()) { + this.playerInteractManager.a(this.getMinecraftServer().getGamemode(), EnumGamemode.NOT_SET); diff --git a/patches/server-unmapped/0115-Option-to-remove-corrupt-tile-entities.patch b/patches/server-unmapped/0115-Option-to-remove-corrupt-tile-entities.patch new file mode 100644 index 0000000000..c9e047b2c4 --- /dev/null +++ b/patches/server-unmapped/0115-Option-to-remove-corrupt-tile-entities.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 5 Oct 2016 16:27:36 -0500 +Subject: [PATCH] Option to remove corrupt tile entities + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6eca3f300020006f02dd36253b522db442e3cc33..622affa0dc3cc1eadaed400511f2ca2cde3fca2a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -300,4 +300,9 @@ public class PaperWorldConfig { + preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); + log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); + } ++ ++ public boolean removeCorruptTEs = false; ++ private void removeCorruptTEs() { ++ removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index b6898cd6e6117fef65198db32b98a64c806811d4..7918dd4ad3e8cbb905b3929062a70fb7961b7d68 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -679,6 +679,12 @@ public class Chunk implements IChunkAccess { + "Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16)); + e.printStackTrace(); + ServerInternalException.reportInternalException(e); ++ ++ if (this.world.paperConfig.removeCorruptTEs) { ++ this.removeTileEntity(tileentity.getPosition()); ++ this.markDirty(); ++ org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); ++ } + // Paper end + // CraftBukkit end + } diff --git a/patches/server-unmapped/0116-Add-EntityZapEvent.patch b/patches/server-unmapped/0116-Add-EntityZapEvent.patch new file mode 100644 index 0000000000..40404fd392 --- /dev/null +++ b/patches/server-unmapped/0116-Add-EntityZapEvent.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaBlend +Date: Sun, 16 Oct 2016 23:19:30 -0700 +Subject: [PATCH] Add EntityZapEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java +index cc31c8f31a385f3a8bfe334e75c3553689397750..d6e1697f64e60f2a567288c604a1690159955f37 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java +@@ -255,6 +255,11 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { + } + + entitypigzombie.setPersistent(); ++ // Paper start ++ if (CraftEventFactory.callEntityZapEvent(this, entitylightning, entitypigzombie).isCancelled()) { ++ return; ++ } ++ // Paper end + // CraftBukkit start + if (CraftEventFactory.callPigZapEvent(this, entitylightning, entitypigzombie).isCancelled()) { + return; +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index ef838bbcc23145ebd5203963923030a8f971cd6e..72ed4de72c87e9c241507838ddb42eaa4c05ef32 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -787,6 +787,12 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + EntityVillager.LOGGER.info("Villager {} was struck by lightning {}.", this, entitylightning); + EntityWitch entitywitch = (EntityWitch) EntityTypes.WITCH.a((World) worldserver); + ++ // Paper start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, entitylightning, entitywitch).isCancelled()) { ++ return; ++ } ++ // Paper end ++ + entitywitch.setPositionRotation(this.locX(), this.locY(), this.locZ(), this.yaw, this.pitch); + entitywitch.prepare(worldserver, worldserver.getDamageScaler(entitywitch.getChunkCoordinates()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (NBTTagCompound) 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 8a7511fc1876dc6761826dd2636bce19d177d2e8..aa484fb733e87c17cc77e56b36f6e1126e8ca4cf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1098,6 +1098,14 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start ++ public static com.destroystokyo.paper.event.entity.EntityZapEvent callEntityZapEvent (Entity entity, Entity lightning, Entity changedEntity) { ++ com.destroystokyo.paper.event.entity.EntityZapEvent event = new com.destroystokyo.paper.event.entity.EntityZapEvent(entity.getBukkitEntity(), (LightningStrike) lightning.getBukkitEntity(), changedEntity.getBukkitEntity()); ++ entity.getBukkitEntity().getServer().getPluginManager().callEvent(event); ++ return event; ++ } ++ // Paper end ++ + public static HorseJumpEvent callHorseJumpEvent(Entity horse, float power) { + HorseJumpEvent event = new HorseJumpEvent((AbstractHorse) horse.getBukkitEntity(), power); + horse.getBukkitEntity().getServer().getPluginManager().callEvent(event); diff --git a/patches/server-unmapped/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/patches/server-unmapped/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch new file mode 100644 index 0000000000..4ed73d0d74 --- /dev/null +++ b/patches/server-unmapped/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 12 Nov 2016 23:25:22 -0600 +Subject: [PATCH] Filter bad data from ArmorStand and SpawnEgg items + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 622affa0dc3cc1eadaed400511f2ca2cde3fca2a..e83216be5a00d5b927d8c2fc364551bd3077c974 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -2,6 +2,7 @@ package com.destroystokyo.paper; + + import java.util.List; + ++import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; + +@@ -305,4 +306,12 @@ public class PaperWorldConfig { + private void removeCorruptTEs() { + removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); + } ++ ++ public boolean filterNBTFromSpawnEgg = true; ++ private void fitlerNBTFromSpawnEgg() { ++ filterNBTFromSpawnEgg = getBoolean("filter-nbt-data-from-spawn-eggs-and-related", true); ++ if (!filterNBTFromSpawnEgg) { ++ Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java +index 3f10e41b18e09186635fd6f7c653b04db7b39d8e..411e3915c0aa00249aacb6658ed04309665d2fb4 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java +@@ -272,6 +272,13 @@ public class EntityFallingBlock extends Entity { + @Override + protected void loadData(NBTTagCompound nbttagcompound) { + this.block = GameProfileSerializer.c(nbttagcompound.getCompound("BlockState")); ++ // Paper start - Block FallingBlocks with Command Blocks ++ // Check mappings on update - dc = "repeating_command_block" - dd = "chain_command_block" ++ final Block b = this.block.getBlock(); ++ if (this.world.paperConfig.filterNBTFromSpawnEgg && (b == Blocks.COMMAND_BLOCK || b == Blocks.REPEATING_COMMAND_BLOCK || b == Blocks.CHAIN_COMMAND_BLOCK)) { ++ this.block = Blocks.STONE.getBlockData(); ++ } ++ // Paper end + this.ticksLived = nbttagcompound.getInt("Time"); + if (nbttagcompound.hasKeyOfType("HurtEntities", 99)) { + this.hurtEntities = nbttagcompound.getBoolean("HurtEntities"); diff --git a/patches/server-unmapped/0118-Cache-user-authenticator-threads.patch b/patches/server-unmapped/0118-Cache-user-authenticator-threads.patch new file mode 100644 index 0000000000..48d9a082cd --- /dev/null +++ b/patches/server-unmapped/0118-Cache-user-authenticator-threads.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: vemacs +Date: Wed, 23 Nov 2016 08:31:45 -0500 +Subject: [PATCH] Cache user authenticator threads + + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 3fca9c3566b5d9a1fafeb0700942d7658cd5a279..e6dacf68cd678d64547dcdc23b1175a4cfd279d1 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -4,7 +4,9 @@ import com.google.common.collect.Lists; + import com.mojang.authlib.GameProfile; + import com.mojang.datafixers.util.Either; + import com.mojang.serialization.DataResult; ++import java.util.ArrayDeque; // Paper + import java.util.Collection; ++import java.util.Deque; // Paper + import java.util.Iterator; + import java.util.List; + import java.util.Optional; +@@ -172,7 +174,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public PlayerConnection playerConnection; + public final MinecraftServer server; + public final PlayerInteractManager playerInteractManager; +- public final List removeQueue = Lists.newLinkedList(); ++ public final Deque removeQueue = new ArrayDeque<>(); // Paper + private final AdvancementDataPlayer advancementDataPlayer; + private final ServerStatisticManager serverStatisticManager; + private float lastHealthScored = Float.MIN_VALUE; +@@ -550,13 +552,20 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + while (!this.removeQueue.isEmpty()) { + int i = Math.min(this.removeQueue.size(), Integer.MAX_VALUE); + int[] aint = new int[i]; +- Iterator iterator = this.removeQueue.iterator(); ++ //Iterator iterator = this.removeQueue.iterator(); // Paper + int j = 0; + +- while (iterator.hasNext() && j < i) { ++ // Paper start ++ /* while (iterator.hasNext() && j < i) { + aint[j++] = (Integer) iterator.next(); + iterator.remove(); ++ } */ ++ ++ Integer integer; ++ while (j < i && (integer = this.removeQueue.poll()) != null) { ++ aint[j++] = integer.intValue(); + } ++ // Paper end + + this.playerConnection.sendPacket(new PacketPlayOutEntityDestroy(aint)); + } +@@ -1561,7 +1570,14 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.lastHealthSent = -1.0F; + this.lastFoodSent = -1; + // this.recipeBook.a((RecipeBook) entityplayer.recipeBook); // CraftBukkit +- this.removeQueue.addAll(entityplayer.removeQueue); ++ // Paper start - Optimize remove queue - vanilla copies player objects, but CB doesn't. This method currently only ++ // Applies to the same player, so we need to not duplicate our removal queue. The rest of this method does "resetting" ++ // type logic so it does need to be called, maybe? This is silly. ++ // this.removeQueue.addAll(entityplayer.removeQueue); ++ if (this.removeQueue != entityplayer.removeQueue) { ++ this.removeQueue.addAll(entityplayer.removeQueue); ++ } ++ // Paper end + this.cd = entityplayer.cd; + this.ci = entityplayer.ci; + this.setShoulderEntityLeft(entityplayer.getShoulderEntityLeft()); diff --git a/patches/server-unmapped/0119-Optimise-removeQueue.patch b/patches/server-unmapped/0119-Optimise-removeQueue.patch new file mode 100644 index 0000000000..c45413d9b2 --- /dev/null +++ b/patches/server-unmapped/0119-Optimise-removeQueue.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Fri, 25 Nov 2016 13:22:40 +0000 +Subject: [PATCH] Optimise removeQueue + + +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index 49a0aefc7f9544b36175fdf3161b255e878952a6..c45647f2d05ed6b170aad10c0a3fb94570d2dd90 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -116,6 +116,12 @@ public class LoginListener implements PacketLoginInListener { + + } + ++ // Paper start - Cache authenticator threads ++ private static final AtomicInteger threadId = new AtomicInteger(0); ++ private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool( ++ r -> new Thread(r, "User Authenticator #" + threadId.incrementAndGet()) ++ ); ++ // Paper end + // Spigot start + public void initUUID() + { +@@ -195,8 +201,8 @@ public class LoginListener implements PacketLoginInListener { + this.networkManager.sendPacket(new PacketLoginOutEncryptionBegin("", this.server.getKeyPair().getPublic().getEncoded(), this.e)); + } else { + // Spigot start +- new Thread("User Authenticator #" + LoginListener.b.incrementAndGet()) { +- ++ // Paper start - Cache authenticator threads ++ authenticatorPool.execute(new Runnable() { + @Override + public void run() { + try { +@@ -207,7 +213,8 @@ public class LoginListener implements PacketLoginInListener { + server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + i.getName(), ex); + } + } +- }.start(); ++ }); ++ // Paper end + // Spigot end + } + +@@ -236,7 +243,8 @@ public class LoginListener implements PacketLoginInListener { + throw new IllegalStateException("Protocol error", cryptographyexception); + } + +- Thread thread = new Thread("User Authenticator #" + LoginListener.b.incrementAndGet()) { ++ // Paper start - Cache authenticator threads ++ authenticatorPool.execute(new Runnable() { + public void run() { + GameProfile gameprofile = LoginListener.this.i; + +@@ -281,10 +289,8 @@ public class LoginListener implements PacketLoginInListener { + + return LoginListener.this.server.W() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; + } +- }; +- +- thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LoginListener.LOGGER)); +- thread.start(); ++ }); ++ // Paper end + } + + // Spigot start diff --git a/patches/server-unmapped/0120-Allow-Reloading-of-Command-Aliases.patch b/patches/server-unmapped/0120-Allow-Reloading-of-Command-Aliases.patch new file mode 100644 index 0000000000..24d1829ae5 --- /dev/null +++ b/patches/server-unmapped/0120-Allow-Reloading-of-Command-Aliases.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: willies952002 +Date: Mon, 28 Nov 2016 10:21:52 -0500 +Subject: [PATCH] Allow Reloading of Command Aliases + +Reload the aliases stored in commands.yml + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index b392f7703222dbba30cdd81ac83e93da36ec043f..539577a0378754cbe0942a79140f6d137eb825ed 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2282,5 +2282,24 @@ public final class CraftServer implements Server { + DefaultPermissions.registerCorePermissions(); + CraftDefaultPermissions.registerCorePermissions(); + } ++ ++ @Override ++ public boolean reloadCommandAliases() { ++ Set removals = getCommandAliases().keySet().stream() ++ .map(key -> key.toLowerCase(java.util.Locale.ENGLISH)) ++ .collect(java.util.stream.Collectors.toSet()); ++ getCommandMap().getKnownCommands().keySet().removeIf(removals::contains); ++ File file = getCommandsConfigFile(); ++ try { ++ commandsConfiguration.load(file); ++ } catch (FileNotFoundException ex) { ++ return false; ++ } catch (IOException | org.bukkit.configuration.InvalidConfigurationException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex); ++ return false; ++ } ++ commandMap.registerServerAliases(); ++ return true; ++ } + // Paper end + } diff --git a/patches/server-unmapped/0121-Add-source-to-PlayerExpChangeEvent.patch b/patches/server-unmapped/0121-Add-source-to-PlayerExpChangeEvent.patch new file mode 100644 index 0000000000..3fac6707a6 --- /dev/null +++ b/patches/server-unmapped/0121-Add-source-to-PlayerExpChangeEvent.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaBlend +Date: Thu, 8 Sep 2016 08:48:33 -0700 +Subject: [PATCH] Add source to PlayerExpChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java +index a52cd6d0318e0fee28fc5d252a4b596b92860320..a17812943b5402684c68ddeac5408dc939e42cf6 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java +@@ -203,7 +203,7 @@ public class EntityExperienceOrb extends Entity { + } + + if (this.value > 0) { +- entityhuman.giveExp(CraftEventFactory.callPlayerExpChangeEvent(entityhuman, this.value).getAmount()); // CraftBukkit - this.value -> event.getAmount() ++ entityhuman.giveExp(CraftEventFactory.callPlayerExpChangeEvent(entityhuman, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object + } + + this.die(); +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index aa484fb733e87c17cc77e56b36f6e1126e8ca4cf..6bee8bcd653737748c442b03a8ce3bedc57dff20 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -121,6 +121,7 @@ import org.bukkit.entity.ThrownPotion; + import org.bukkit.entity.Vehicle; + import org.bukkit.entity.Villager; + import org.bukkit.entity.Villager.Profession; ++import org.bukkit.entity.ExperienceOrb; // Paper + import org.bukkit.event.Cancellable; + import org.bukkit.event.Event; + import org.bukkit.event.Event.Result; +@@ -1057,6 +1058,17 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start - Add orb ++ public static PlayerExpChangeEvent callPlayerExpChangeEvent(EntityHuman entity, EntityExperienceOrb entityOrb) { ++ Player player = (Player) entity.getBukkitEntity(); ++ ExperienceOrb source = (ExperienceOrb) entityOrb.getBukkitEntity(); ++ int expAmount = source.getExperience(); ++ PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, source, expAmount); ++ Bukkit.getPluginManager().callEvent(event); ++ return event; ++ } ++ // Paper end ++ + public static boolean handleBlockGrowEvent(World world, BlockPosition pos, IBlockData block) { + return handleBlockGrowEvent(world, pos, block, 3); + } diff --git a/patches/server-unmapped/0122-Don-t-let-fishinghooks-use-portals.patch b/patches/server-unmapped/0122-Don-t-let-fishinghooks-use-portals.patch new file mode 100644 index 0000000000..34efb26a3c --- /dev/null +++ b/patches/server-unmapped/0122-Don-t-let-fishinghooks-use-portals.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 16 Dec 2016 16:03:19 -0600 +Subject: [PATCH] Don't let fishinghooks use portals + + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +index 7402e3b305d9bb7b27b97ff2078c26dd578232a1..2067af9b13c7ce28cd8ad6c785e2d0a7ff013430 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +@@ -240,6 +240,11 @@ public class EntityFishingHook extends IProjectile { + + this.setMot(this.getMot().a(0.92D)); + this.af(); ++ // Paper start - These shouldn't be going through portals ++ if (this.inPortal) { ++ this.die(); ++ } ++ // Paper end + } + } + diff --git a/patches/server-unmapped/0123-Add-ProjectileCollideEvent.patch b/patches/server-unmapped/0123-Add-ProjectileCollideEvent.patch new file mode 100644 index 0000000000..ad461a95e3 --- /dev/null +++ b/patches/server-unmapped/0123-Add-ProjectileCollideEvent.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Fri, 16 Dec 2016 21:25:39 -0600 +Subject: [PATCH] Add ProjectileCollideEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +index 7868259a94766a6100d7b278c4296dde0a7f9397..c325c9fe680d9033b20909bcd6100ecc4b0195f6 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +@@ -198,6 +198,17 @@ public abstract class EntityArrow extends IProjectile { + } + } + ++ // Paper start - Call ProjectileCollideEvent ++ // TODO: flag - noclip - call cancelled? ++ if (object instanceof MovingObjectPositionEntity) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)object); ++ if (event.isCancelled()) { ++ object = null; ++ movingobjectpositionentity = null; ++ } ++ } ++ // Paper end ++ + if (object != null && !flag) { + this.preOnHit((MovingObjectPosition) object); // CraftBukkit - projectile hit event + this.impulse = true; +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java +index 2ceae34365c437f2a15ae8587fa9517ea47ad6f2..9660dc2263c48a5818b767843658eeb9ee1748ea 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java +@@ -13,6 +13,7 @@ import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.level.World; + import net.minecraft.world.phys.MovingObjectPosition; ++import net.minecraft.world.phys.MovingObjectPositionEntity; + import net.minecraft.world.phys.Vec3D; + + import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit +@@ -72,7 +73,16 @@ public abstract class EntityFireball extends IProjectile { + + MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); + +- if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { ++ // Paper start - Call ProjectileCollideEvent ++ if (movingobjectposition instanceof MovingObjectPositionEntity) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)movingobjectposition); ++ if (event.isCancelled()) { ++ movingobjectposition = null; ++ } ++ } ++ // Paper end ++ ++ if (movingobjectposition != null && movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { // Paper - add null check in case cancelled + this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + + // CraftBukkit start - Fire ProjectileHitEvent +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java +index 149588433cd0ea0f71b45267e39b28697ccfd2c0..8bc65e9c0fa5e134a8eb4e03f0da5b2ccd06cd7c 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java +@@ -14,6 +14,7 @@ import net.minecraft.world.level.block.entity.TileEntityEndGateway; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionBlock; ++import net.minecraft.world.phys.MovingObjectPositionEntity; + import net.minecraft.world.phys.Vec3D; + + public abstract class EntityProjectile extends IProjectile { +@@ -57,7 +58,17 @@ public abstract class EntityProjectile extends IProjectile { + } + + if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS && !flag) { ++ // Paper start - Call ProjectileCollideEvent ++ if (movingobjectposition instanceof MovingObjectPositionEntity) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)movingobjectposition); ++ if (event.isCancelled()) { ++ movingobjectposition = null; ++ } ++ } ++ if (movingobjectposition != null) { ++ // Paper end + this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event ++ } // Paper + } + + this.checkBlockCollisions(); +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 6bee8bcd653737748c442b03a8ce3bedc57dff20..d07c146119980358aeaf8f9dc5f419fd1385ced5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1202,6 +1202,16 @@ public class CraftEventFactory { + return CraftItemStack.asNMSCopy(bitem); + } + ++ // Paper start ++ public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, MovingObjectPositionEntity position) { ++ 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); ++ Bukkit.getPluginManager().callEvent(event); ++ return event; ++ } ++ // Paper end ++ + public static ProjectileLaunchEvent callProjectileLaunchEvent(Entity entity) { + Projectile bukkitEntity = (Projectile) entity.getBukkitEntity(); + ProjectileLaunchEvent event = new ProjectileLaunchEvent(bukkitEntity); diff --git a/patches/server-unmapped/0124-Prevent-Pathfinding-out-of-World-Border.patch b/patches/server-unmapped/0124-Prevent-Pathfinding-out-of-World-Border.patch new file mode 100644 index 0000000000..d30b0eae33 --- /dev/null +++ b/patches/server-unmapped/0124-Prevent-Pathfinding-out-of-World-Border.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 19 Dec 2016 23:07:42 -0500 +Subject: [PATCH] Prevent Pathfinding out of World Border + +This prevents Entities from trying to run outside of the World Border + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +index d71a6e5991629ce59c8529d7cc8064960e385236..d134333c736dc1ee1c722d680d7a9c22c1b265bd 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +@@ -148,7 +148,7 @@ public abstract class NavigationAbstract { + // Paper start - Pathfind event + boolean copiedSet = false; + for (BlockPosition possibleTarget : set) { +- if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), ++ if (!getEntity().getWorld().getWorldBorder().isInBounds(possibleTarget) || !new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), // Paper - don't path out of world border + MCUtil.toLocation(getEntity().world, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { + if (!copiedSet) { + copiedSet = true; diff --git a/patches/server-unmapped/0125-Optimize-World.isLoaded-BlockPosition-Z.patch b/patches/server-unmapped/0125-Optimize-World.isLoaded-BlockPosition-Z.patch new file mode 100644 index 0000000000..2bc6bb0583 --- /dev/null +++ b/patches/server-unmapped/0125-Optimize-World.isLoaded-BlockPosition-Z.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 2 Dec 2016 00:11:43 -0500 +Subject: [PATCH] Optimize World.isLoaded(BlockPosition)Z + +Reduce method invocations for World.isLoaded(BlockPosition)Z + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index d8ab2e22a5c0144decb5c657a123cc61722fcbf5..bd08ff18d8d7dbe63ed33c1efb6099b58aa02caa 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -305,6 +305,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return chunk == null ? null : chunk.getFluid(blockposition); + } + ++ public final boolean isLoaded(BlockPosition blockposition) { ++ return getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; // Paper ++ } ++ + public final boolean isLoadedAndInBounds(BlockPosition blockposition) { // Paper - final for inline + return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; + } diff --git a/patches/server-unmapped/0126-Bound-Treasure-Maps-to-World-Border.patch b/patches/server-unmapped/0126-Bound-Treasure-Maps-to-World-Border.patch new file mode 100644 index 0000000000..212f2d89eb --- /dev/null +++ b/patches/server-unmapped/0126-Bound-Treasure-Maps-to-World-Border.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 20 Dec 2016 15:15:11 -0500 +Subject: [PATCH] Bound Treasure Maps to World Border + +Make it so a Treasure Map does not target a structure outside of the +World Border, where players are not even able to reach. + +This also would help the case where a players close to the border, and one +that is outside happens to be closer, but unreachable, yet another reachable +one is in border that would of been missed. + +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index f16c76df5d7b184d57f4cc397f069eac9cc430cb..50e2085766caabec1125ca24a2117549efd1a354 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -36,6 +36,18 @@ public class WorldBorder { + return (double) (blockposition.getX() + 1) > this.e() && (double) blockposition.getX() < this.g() && (double) (blockposition.getZ() + 1) > this.f() && (double) blockposition.getZ() < this.h(); + } + ++ // Paper start ++ private final BlockPosition.MutableBlockPosition mutPos = new BlockPosition.MutableBlockPosition(); ++ public boolean isBlockInBounds(int chunkX, int chunkZ) { ++ this.mutPos.setValues(chunkX, 64, chunkZ); ++ return this.isInBounds(this.mutPos); ++ } ++ public boolean isChunkInBounds(int chunkX, int chunkZ) { ++ this.mutPos.setValues(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15); ++ return this.isInBounds(this.mutPos); ++ } ++ // Paper end ++ + public boolean isInBounds(ChunkCoordIntPair chunkcoordintpair) { + return (double) chunkcoordintpair.f() > this.e() && (double) chunkcoordintpair.d() < this.g() && (double) chunkcoordintpair.g() > this.f() && (double) chunkcoordintpair.e() < this.h(); + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java +index 6724927be178cb9a358a9276d01894a63154b7b3..ea7e3e15fa778c573d24f956f72f60579ea0b1a1 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java +@@ -175,6 +175,7 @@ public abstract class StructureGenerator + int i2 = l + k * k1; + int j2 = i1 + k * l1; + ChunkCoordIntPair chunkcoordintpair = this.a(structuresettingsfeature, j, seededrandom, i2, j2); ++ if (!iworldreader.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper + IChunkAccess ichunkaccess = iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); + StructureStart structurestart = structuremanager.a(SectionPosition.a(ichunkaccess.getPos(), 0), this, ichunkaccess); + diff --git a/patches/server-unmapped/0127-Configurable-Cartographer-Treasure-Maps.patch b/patches/server-unmapped/0127-Configurable-Cartographer-Treasure-Maps.patch new file mode 100644 index 0000000000..82ccdd75a9 --- /dev/null +++ b/patches/server-unmapped/0127-Configurable-Cartographer-Treasure-Maps.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 20 Dec 2016 15:26:27 -0500 +Subject: [PATCH] Configurable Cartographer Treasure Maps + +Allow configuring for cartographers to return the same map location + +Also allow turning off treasure maps all together as they can eat up Map ID's +which are limited in quantity. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e83216be5a00d5b927d8c2fc364551bd3077c974..2dc58b9f769ea43b737804456aafab47ecc143b8 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -314,4 +314,14 @@ public class PaperWorldConfig { + Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); + } + } ++ ++ public boolean enableTreasureMaps = true; ++ public boolean treasureMapsAlreadyDiscovered = false; ++ private void treasureMapsAlreadyDiscovered() { ++ enableTreasureMaps = getBoolean("enable-treasure-maps", true); ++ treasureMapsAlreadyDiscovered = getBoolean("treasure-maps-return-already-discovered", false); ++ if (treasureMapsAlreadyDiscovered) { ++ log("Treasure Maps will return already discovered locations"); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +index 764ff5d9ffb541a356a6bc8b321e619849dde747..0a34e319998a95a9654822e55a22eb964b2d626b 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java ++++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +@@ -124,7 +124,8 @@ public class VillagerTrades { + return null; + } else { + WorldServer worldserver = (WorldServer) entity.world; +- BlockPosition blockposition = worldserver.a(this.b, entity.getChunkCoordinates(), 100, true); ++ if (!worldserver.paperConfig.enableTreasureMaps) return null; // Paper ++ BlockPosition blockposition = worldserver.a(this.b, entity.getChunkCoordinates(), 100, !worldserver.paperConfig.treasureMapsAlreadyDiscovered); // Paper + + if (blockposition != null) { + ItemStack itemstack = ItemWorldMap.createFilledMapView(worldserver, blockposition.getX(), blockposition.getZ(), (byte) 2, true, true); +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java +index 38125a60bad4830db9de3580ab6d85fd122a0689..7bf16c5a3f2bb5525ce1ca0c0190c7671fc94797 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java +@@ -64,7 +64,16 @@ public class LootItemFunctionExplorationMap extends LootItemFunctionConditional + + if (vec3d != null) { + WorldServer worldserver = loottableinfo.getWorld(); +- BlockPosition blockposition = worldserver.a(this.e, new BlockPosition(vec3d), this.h, this.i); ++ // Paper start ++ if (!worldserver.paperConfig.enableTreasureMaps) { ++ /* ++ * NOTE: I fear users will just get a plain map as their "treasure" ++ * This is preferable to disrespecting the config. ++ */ ++ return itemstack; ++ } ++ // Paper end ++ BlockPosition blockposition = worldserver.a(this.e, new BlockPosition(vec3d), this.h, !worldserver.paperConfig.treasureMapsAlreadyDiscovered && this.i); // Paper + + if (blockposition != null) { + ItemStack itemstack1 = ItemWorldMap.createFilledMapView(worldserver, blockposition.getX(), blockposition.getZ(), this.g, true, true); diff --git a/patches/server-unmapped/0128-Optimize-ItemStack.isEmpty.patch b/patches/server-unmapped/0128-Optimize-ItemStack.isEmpty.patch new file mode 100644 index 0000000000..011e094dc5 --- /dev/null +++ b/patches/server-unmapped/0128-Optimize-ItemStack.isEmpty.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Dec 2016 03:48:29 -0500 +Subject: [PATCH] Optimize ItemStack.isEmpty() + +Remove hashMap lookup every check, simplify code to remove ternary + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 201ba7250b298f4a91bc45f5954f54ae557305f2..cac92ccacc9d5ff17c70ee266cf12bacce6242ea 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -208,7 +208,7 @@ public final class ItemStack { + } + + public boolean isEmpty() { +- return this == ItemStack.b ? true : (this.getItem() != null && this.getItem() != Items.AIR ? this.count <= 0 : true); ++ return this == ItemStack.NULL_ITEM || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper + } + + public ItemStack cloneAndSubtract(int i) { diff --git a/patches/server-unmapped/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch b/patches/server-unmapped/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch new file mode 100644 index 0000000000..8d198833bc --- /dev/null +++ b/patches/server-unmapped/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 21 Dec 2016 11:47:25 -0600 +Subject: [PATCH] Add API methods to control if armour stands can move + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index 31bb5df7bc63c993230bf595bd9b66bfaadb4d50..ccdfc8068a8205d6e66ab9458764b1440f8c4b97 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -38,6 +38,7 @@ import net.minecraft.world.entity.ai.control.ControllerLook; + import net.minecraft.world.entity.ai.control.ControllerMove; + import net.minecraft.world.entity.ai.control.EntityAIBodyControl; + import net.minecraft.world.entity.ai.goal.PathfinderGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; + import net.minecraft.world.entity.ai.goal.PathfinderGoalSelector; + import net.minecraft.world.entity.ai.navigation.Navigation; + import net.minecraft.world.entity.ai.navigation.NavigationAbstract; +@@ -45,6 +46,8 @@ import net.minecraft.world.entity.ai.sensing.EntitySenses; + import net.minecraft.world.entity.decoration.EntityHanging; + import net.minecraft.world.entity.decoration.EntityLeash; + import net.minecraft.world.entity.item.EntityItem; ++import net.minecraft.world.entity.monster.EntityBlaze; ++import net.minecraft.world.entity.monster.EntityEnderman; + import net.minecraft.world.entity.monster.IMonster; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.vehicle.EntityBoat; +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +index 72e53968c5fb03301ddec7a0cf937ac2f8cf0901..2ef991aa7f739d3577fbbf4386064557e8f7c904 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +@@ -28,6 +28,7 @@ import net.minecraft.world.entity.EntitySize; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumItemSlot; + import net.minecraft.world.entity.EnumMainHand; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.projectile.EntityArrow; + import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; +@@ -79,6 +80,7 @@ public class EntityArmorStand extends EntityLiving { + public Vector3f rightArmPose; + public Vector3f leftLegPose; + public Vector3f rightLegPose; ++ public boolean canMove = true; // Paper + + public EntityArmorStand(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -862,4 +864,13 @@ public class EntityArmorStand extends EntityLiving { + private EntitySize s(boolean flag) { + return flag ? EntityArmorStand.bp : (this.isBaby() ? EntityArmorStand.bq : this.getEntityType().l()); + } ++ ++ // Paper start ++ @Override ++ public void move(EnumMoveType moveType, Vec3D vec3d) { ++ if (this.canMove) { ++ super.move(moveType, vec3d); ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +index 86c8662b3864b264e26f8c63474fdd39bd6c873c..6f922e4cbb095439fcd76ee0d0c08bc4160b8107 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +@@ -229,4 +229,15 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public boolean hasEquipmentLock(EquipmentSlot equipmentSlot, LockType lockType) { + return (getHandle().disabledSlots & (1 << CraftEquipmentSlot.getNMS(equipmentSlot).getSlotFlag() + lockType.ordinal() * 8)) != 0; + } ++ // Paper start ++ @Override ++ public boolean canMove() { ++ return getHandle().canMove; ++ } ++ ++ @Override ++ public void setCanMove(boolean move) { ++ getHandle().canMove = move; ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0130-Properly-fix-item-duplication-bug.patch b/patches/server-unmapped/0130-Properly-fix-item-duplication-bug.patch new file mode 100644 index 0000000000..6cb65771f2 --- /dev/null +++ b/patches/server-unmapped/0130-Properly-fix-item-duplication-bug.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Tue, 27 Dec 2016 01:57:57 +0000 +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/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index e6dacf68cd678d64547dcdc23b1175a4cfd279d1..5b2ae94ed7d499e401a058691eb6ed413b626150 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -2069,8 +2069,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + + @Override +- public boolean isFrozen() { +- return super.isFrozen() || !getBukkitEntity().isOnline(); ++ protected boolean isFrozen() { ++ return super.isFrozen() || (this.playerConnection != null && this.playerConnection.isDisconnected()); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 15daf87d6a6d80b5ebce5360e6999fd604c66cb5..d507d050f9a1ebd65383adb2b21699a01d9b0385 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2820,7 +2820,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + + public final boolean isDisconnected() { +- return !this.player.joining && !this.networkManager.isConnected(); ++ return (!this.player.joining && !this.networkManager.isConnected()) || this.processedDisconnect; // Paper + } + // CraftBukkit end + diff --git a/patches/server-unmapped/0131-String-based-Action-Bar-API.patch b/patches/server-unmapped/0131-String-based-Action-Bar-API.patch new file mode 100644 index 0000000000..08c66ad7f1 --- /dev/null +++ b/patches/server-unmapped/0131-String-based-Action-Bar-API.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 27 Dec 2016 15:02:42 -0500 +Subject: [PATCH] String based Action Bar API + + +diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java +index c8bb06a31242089ad950713bd5f94abbfe12adc8..68ce7605bd63ea280b96db8230463d2afb0a6cb1 100644 +--- a/src/main/java/net/minecraft/SystemUtils.java ++++ b/src/main/java/net/minecraft/SystemUtils.java +@@ -58,7 +58,7 @@ public class SystemUtils { + private static final ExecutorService e = a("Main"); + private static final ExecutorService f = n(); + public static LongSupplier a = System::nanoTime; +- public static final UUID b = new UUID(0L, 0L); ++ public static final UUID b = new UUID(0L, 0L); public static final UUID getNullUUID() {return b;} // Paper OBFHELPER + private static final Logger LOGGER = LogManager.getLogger(); + + public static Collector, ?, Map> a() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 5698ef90bfeceec37eaf7f23361246ef125b3cd1..3ab71629699f4978cd2dab36ec7e3b32a1681f91 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -244,6 +244,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + // Paper start ++ @Override ++ public void sendActionBar(BaseComponent[] message) { ++ if (getHandle().playerConnection == null) return; ++ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, message, -1, -1, -1)); ++ } ++ ++ @Override ++ public void sendActionBar(String message) { ++ if (getHandle().playerConnection == null || message == null || message.isEmpty()) return; ++ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, CraftChatMessage.fromStringOrNull(message))); ++ } ++ ++ @Override ++ public void sendActionBar(char alternateChar, String message) { ++ if (message == null || message.isEmpty()) return; ++ sendActionBar(org.bukkit.ChatColor.translateAlternateColorCodes(alternateChar, message)); ++ } ++ + @Override + public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { + if (header != null) { diff --git a/patches/server-unmapped/0132-Firework-API-s.patch b/patches/server-unmapped/0132-Firework-API-s.patch new file mode 100644 index 0000000000..c220b785aa --- /dev/null +++ b/patches/server-unmapped/0132-Firework-API-s.patch @@ -0,0 +1,124 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 28 Dec 2016 07:18:33 +0100 +Subject: [PATCH] Firework API's + + +diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java +index bf4826e90976fed2ae95e84cadc7f29433af1ddf..d5508deff819309034554abc7b36aac40fa33503 100644 +--- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java ++++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java +@@ -153,6 +153,7 @@ public class NBTTagCompound implements NBTBase { + return GameProfileSerializer.a(this.get(s)); + } + ++ public final boolean hasUUID(String s) { return this.b(s); } // Paper - OBFHELPER + public boolean b(String s) { + NBTBase nbtbase = this.get(s); + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java +index 6ca5c8a4308c56d35bddbabc0be724325a8a73e3..ca7a10c4b04766d7eb55be9252e96ef939e76df3 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java +@@ -38,7 +38,8 @@ public class EntityFireworks extends IProjectile { + public static final DataWatcherObject SHOT_AT_ANGLE = DataWatcher.a(EntityFireworks.class, DataWatcherRegistry.i); + private int ticksFlown; + public int expectedLifespan; +- private EntityLiving ridingEntity; ++ public EntityLiving ridingEntity; // Paper - public ++ public java.util.UUID spawningEntity; // Paper + + public EntityFireworks(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -285,6 +286,11 @@ public class EntityFireworks extends IProjectile { + } + + nbttagcompound.setBoolean("ShotAtAngle", (Boolean) this.datawatcher.get(EntityFireworks.SHOT_AT_ANGLE)); ++ // Paper start ++ if (this.spawningEntity != null) { ++ nbttagcompound.setUUID("SpawningEntity", this.spawningEntity); ++ } ++ // Paper end + } + + @Override +@@ -301,7 +307,11 @@ public class EntityFireworks extends IProjectile { + if (nbttagcompound.hasKey("ShotAtAngle")) { + this.datawatcher.set(EntityFireworks.SHOT_AT_ANGLE, nbttagcompound.getBoolean("ShotAtAngle")); + } +- ++ // Paper start ++ if (nbttagcompound.hasUUID("SpawningEntity")) { ++ this.spawningEntity = nbttagcompound.getUUID("SpawningEntity"); ++ } ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/item/ItemCrossbow.java b/src/main/java/net/minecraft/world/item/ItemCrossbow.java +index d52f3cb5d76bde1cf29c654dade6d8379b44c2e5..ec6c0836f02e7ac5b72fd224a3022a844dce55cb 100644 +--- a/src/main/java/net/minecraft/world/item/ItemCrossbow.java ++++ b/src/main/java/net/minecraft/world/item/ItemCrossbow.java +@@ -205,6 +205,7 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable + + if (flag1) { + object = new EntityFireworks(world, itemstack1, entityliving, entityliving.locX(), entityliving.getHeadY() - 0.15000000596046448D, entityliving.locZ(), true); ++ ((EntityFireworks) object).spawningEntity = entityliving.getUniqueID(); // Paper + } else { + object = a(world, entityliving, itemstack, itemstack1); + if (flag || f3 != 0.0F) { +diff --git a/src/main/java/net/minecraft/world/item/ItemFireworks.java b/src/main/java/net/minecraft/world/item/ItemFireworks.java +index 9153945c2e245b9a2a098bdf58b0dcab052084ff..a2950faa48021782f10db0673d12d178443f7ccc 100644 +--- a/src/main/java/net/minecraft/world/item/ItemFireworks.java ++++ b/src/main/java/net/minecraft/world/item/ItemFireworks.java +@@ -27,6 +27,7 @@ public class ItemFireworks extends Item { + Vec3D vec3d = itemactioncontext.getPos(); + EnumDirection enumdirection = itemactioncontext.getClickedFace(); + EntityFireworks entityfireworks = new EntityFireworks(world, itemactioncontext.getEntity(), vec3d.x + (double) enumdirection.getAdjacentX() * 0.15D, vec3d.y + (double) enumdirection.getAdjacentY() * 0.15D, vec3d.z + (double) enumdirection.getAdjacentZ() * 0.15D, itemstack); ++ entityfireworks.spawningEntity = itemactioncontext.getEntity().getUniqueID(); // Paper + + world.addEntity(entityfireworks); + itemstack.subtract(1); +@@ -41,7 +42,11 @@ public class ItemFireworks extends Item { + ItemStack itemstack = entityhuman.b(enumhand); + + if (!world.isClientSide) { +- world.addEntity(new EntityFireworks(world, itemstack, entityhuman)); ++ // Paper start ++ final EntityFireworks entityfireworks = new EntityFireworks(world, itemstack, entityhuman); ++ entityfireworks.spawningEntity = entityhuman.getUniqueID(); ++ world.addEntity(entityfireworks); ++ // Paper end + if (!entityhuman.abilities.canInstantlyBuild) { + itemstack.subtract(1); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +index 33162fd419ab9a7b650ca9d4270a0c03f06f19f6..73c2da316e41329114fcb3d30cb009d9cc7de7b9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +@@ -1,6 +1,7 @@ + package org.bukkit.craftbukkit.entity; + + import java.util.Random; ++import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.projectile.EntityFireworks; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -78,4 +79,17 @@ public class CraftFirework extends CraftProjectile implements Firework { + public void setShotAtAngle(boolean shotAtAngle) { + getHandle().getDataWatcher().set(EntityFireworks.SHOT_AT_ANGLE, shotAtAngle); + } ++ ++ // Paper start ++ @Override ++ public java.util.UUID getSpawningEntity() { ++ return getHandle().spawningEntity; ++ } ++ ++ @Override ++ public org.bukkit.entity.LivingEntity getBoostedEntity() { ++ EntityLiving boostedEntity = getHandle().ridingEntity; ++ return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null; ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0133-PlayerTeleportEndGatewayEvent.patch b/patches/server-unmapped/0133-PlayerTeleportEndGatewayEvent.patch new file mode 100644 index 0000000000..6e0a520b62 --- /dev/null +++ b/patches/server-unmapped/0133-PlayerTeleportEndGatewayEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 31 Dec 2016 21:44:50 -0500 +Subject: [PATCH] PlayerTeleportEndGatewayEvent + +Allows you to access the Gateway being used in a teleport event + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java +index 0c5d9600eadc0a550cc2d5e7b4ee665c030faa89..2808cd0b100bd65a730aba315ab47a59a4621b30 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java +@@ -10,6 +10,7 @@ import net.minecraft.data.worldgen.BiomeDecoratorGroups; + import net.minecraft.nbt.GameProfileSerializer; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.util.MathHelper; +@@ -180,7 +181,7 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick + location.setPitch(player.getLocation().getPitch()); + location.setYaw(player.getLocation().getYaw()); + +- PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); ++ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(world, this.getPosition()).getBlock())); // Paper + Bukkit.getPluginManager().callEvent(teleEvent); + if (teleEvent.isCancelled()) { + return; diff --git a/patches/server-unmapped/0134-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/server-unmapped/0134-Provide-E-TE-Chunk-count-stat-methods.patch new file mode 100644 index 0000000000..753735ecac --- /dev/null +++ b/patches/server-unmapped/0134-Provide-E-TE-Chunk-count-stat-methods.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 Jan 2017 15:24:46 -0500 +Subject: [PATCH] Provide E/TE/Chunk count stat methods + +Provides counts without the ineffeciency of using .getEntities().size() +which creates copy of the collections. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index b50ed67714fea93fc6708f2680ae909f403deb00..29f5311260d0d5ee321db94031ffc3ed528d6b02 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -282,6 +282,48 @@ public class CraftWorld implements World { + private int waterAmbientSpawn = -1; + private int ambientSpawn = -1; + ++ // Paper start - Provide fast information methods ++ public int getEntityCount() { ++ int ret = 0; ++ for (net.minecraft.world.entity.Entity entity : world.entitiesById.values()) { ++ if (entity.isChunkLoaded()) { ++ ++ret; ++ } ++ } ++ return ret; ++ } ++ public int getTileEntityCount() { ++ // We don't use the full world tile entity list, so we must iterate chunks ++ Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; ++ int size = 0; ++ for (PlayerChunk playerchunk : chunks.values()) { ++ net.minecraft.world.level.chunk.Chunk chunk = playerchunk.getChunk(); ++ if (chunk == null) { ++ continue; ++ } ++ size += chunk.tileEntities.size(); ++ } ++ return size; ++ } ++ public int getTickableTileEntityCount() { ++ return world.tileEntityListTick.size(); ++ } ++ public int getChunkCount() { ++ int ret = 0; ++ ++ for (PlayerChunk chunkHolder : world.getChunkProvider().playerChunkMap.visibleChunks.values()) { ++ if (chunkHolder.getChunk() != null) { ++ ++ret; ++ } ++ } ++ ++ return ret; ++ } ++ public int getPlayerCount() { ++ return world.players.size(); ++ } ++ // Paper end ++ + private static final Random rand = new Random(); + + public CraftWorld(WorldServer world, ChunkGenerator gen, Environment env) { diff --git a/patches/server-unmapped/0135-Enforce-Sync-Player-Saves.patch b/patches/server-unmapped/0135-Enforce-Sync-Player-Saves.patch new file mode 100644 index 0000000000..92ee3f9334 --- /dev/null +++ b/patches/server-unmapped/0135-Enforce-Sync-Player-Saves.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 Jan 2017 15:41:58 -0500 +Subject: [PATCH] Enforce Sync Player Saves + +Saving players async is extremely dangerous. This will force it to main +the same way we handle async chunk loads. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 49f1aed92fd5fa46b74a979f317a2eb0672991e9..f0928684f2bb56b490bea7cd80eb9300d2647f0c 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1047,11 +1047,13 @@ public abstract class PlayerList { + } + + public void savePlayers() { ++ MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main + MinecraftTimings.savePlayers.startTiming(); // Paper + for (int i = 0; i < this.players.size(); ++i) { + this.savePlayerFile((EntityPlayer) this.players.get(i)); + } + MinecraftTimings.savePlayers.stopTiming(); // Paper ++ return null; }); // Paper - ensure main + } + + public WhiteList getWhitelist() { diff --git a/patches/server-unmapped/0136-Don-t-allow-entities-to-ride-themselves-572.patch b/patches/server-unmapped/0136-Don-t-allow-entities-to-ride-themselves-572.patch new file mode 100644 index 0000000000..1b3ac3e9b4 --- /dev/null +++ b/patches/server-unmapped/0136-Don-t-allow-entities-to-ride-themselves-572.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Sun, 8 Jan 2017 04:31:36 +0000 +Subject: [PATCH] Don't allow entities to ride themselves - #572 + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d314cdd9341e6aa5748a5b1afdd9569bec956c74..00e79363b3f961111595c50758332f6c1c1b31bb 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2046,6 +2046,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + protected boolean addPassenger(Entity entity) { // CraftBukkit ++ if (entity == this) throw new IllegalArgumentException("Entities cannot become a passenger of themselves"); // Paper - issue 572 + if (entity.getVehicle() != this) { + throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)"); + } else { diff --git a/patches/server-unmapped/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server-unmapped/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch new file mode 100644 index 0000000000..1fd6d1e437 --- /dev/null +++ b/patches/server-unmapped/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch @@ -0,0 +1,315 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 16:31:46 -0500 +Subject: [PATCH] ExperienceOrbs API for Reason/Source/Triggering player + +Adds lots of information about why this orb exists. + +Replaces isFromBottle() with logic that persists entity reloads too. + +diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +index 164fd6b867bc68f6aba3fa2c17371e87495baea3..74b4b127f39a0ad06e8f9add6861763724ab70ba 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java ++++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +@@ -409,7 +409,7 @@ public class PlayerInteractManager { + + // Drop event experience + if (flag && event != null) { +- iblockdata.getBlock().dropExperience(this.world, blockposition, event.getExpToDrop()); ++ iblockdata.getBlock().dropExperience(this.world, blockposition, event.getExpToDrop(), this.player); // Paper + } + + return true; +diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java +index a17812943b5402684c68ddeac5408dc939e42cf6..f4da22b33c704e675510b4b1a3aa7c180088be29 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java +@@ -31,9 +31,59 @@ public class EntityExperienceOrb extends Entity { + public int value; + private EntityHuman targetPlayer; + private int targetTime; ++ // Paper start ++ public java.util.UUID sourceEntityId; ++ public java.util.UUID triggerEntityId; ++ public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; ++ ++ private void loadPaperNBT(NBTTagCompound nbttagcompound) { ++ if (!nbttagcompound.hasKeyOfType("Paper.ExpData", 10)) { // 10 = compound ++ return; ++ } ++ NBTTagCompound comp = nbttagcompound.getCompound("Paper.ExpData"); ++ if (comp.hasUUID("source")) { ++ this.sourceEntityId = comp.getUUID("source"); ++ } ++ if (comp.hasUUID("trigger")) { ++ this.triggerEntityId = comp.getUUID("trigger"); ++ } ++ if (comp.hasKey("reason")) { ++ String reason = comp.getString("reason"); ++ try { ++ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason); ++ } catch (Exception e) { ++ this.world.getServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason); ++ } ++ } ++ } ++ private void savePaperNBT(NBTTagCompound nbttagcompound) { ++ NBTTagCompound comp = new NBTTagCompound(); ++ if (this.sourceEntityId != null) { ++ comp.setUUID("source", this.sourceEntityId); ++ } ++ if (this.triggerEntityId != null) { ++ comp.setUUID("trigger", triggerEntityId); ++ } ++ if (this.spawnReason != null && this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) { ++ comp.setString("reason", this.spawnReason.name()); ++ } ++ nbttagcompound.set("Paper.ExpData", comp); ++ } + + public EntityExperienceOrb(World world, double d0, double d1, double d2, int i) { ++ this(world, d0, d1, d2, i, null, null); ++ } ++ ++ public EntityExperienceOrb(World world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { ++ this(world, d0, d1, d2, i, reason, triggerId, null); ++ } ++ ++ public EntityExperienceOrb(World world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { + this(EntityTypes.EXPERIENCE_ORB, world); ++ this.sourceEntityId = sourceId != null ? sourceId.getUniqueID() : null; ++ this.triggerEntityId = triggerId != null ? triggerId.getUniqueID() : null; ++ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; ++ // Paper end + this.setPosition(d0, d1, d2); + this.yaw = (float) (this.random.nextDouble() * 360.0D); + this.setMot((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D); +@@ -168,6 +218,7 @@ public class EntityExperienceOrb extends Entity { + nbttagcompound.setShort("Health", (short) this.e); + nbttagcompound.setShort("Age", (short) this.c); + nbttagcompound.setShort("Value", (short) this.value); ++ this.savePaperNBT(nbttagcompound); // Paper + } + + @Override +@@ -175,6 +226,7 @@ public class EntityExperienceOrb extends Entity { + this.e = nbttagcompound.getShort("Health"); + this.c = nbttagcompound.getShort("Age"); + this.value = nbttagcompound.getShort("Value"); ++ this.loadPaperNBT(nbttagcompound); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index db5c0d2da9ed9993ee83adccfa74e77f4e364f2a..f26f02856e7cca0ca62325adf992619dd15b3885 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -1594,7 +1594,8 @@ public abstract class EntityLiving extends Entity { + int j = EntityExperienceOrb.getOrbValue(i); + + i -= j; +- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j)); ++ EntityLiving attacker = killer != null ? killer : lastDamager; // Paper ++ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j, this instanceof EntityPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this)); // Paper + } + this.expToDrop = 0; + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java +index b9a681c2f7435c38dda074fbabbf53974ebbc705..4de0a733819d408e8b9a55b604f455281d7732c5 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java +@@ -262,7 +262,7 @@ public abstract class EntityAnimal extends EntityAgeable { + if (worldserver.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { + // CraftBukkit start - use event experience + if (experience > 0) { +- worldserver.addEntity(new EntityExperienceOrb(worldserver, this.locX(), this.locY(), this.locZ(), experience)); ++ worldserver.addEntity(new EntityExperienceOrb(worldserver, this.locX(), this.locY(), this.locZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper + } + // CraftBukkit end + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +index c1e3b90098605cf809aa2ecfb5edc0ad78f2257c..77de0706aaa32b565cb1e14754e93a1c4a6e15bd 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +@@ -1306,7 +1306,7 @@ public class EntityFox extends EntityAnimal { + if (this.b.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { + // CraftBukkit start - use event experience + if (experience > 0) { +- this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), experience)); ++ this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityfox)); // Paper + } + // CraftBukkit end + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java +index 5d08b83e2832cad2c8726ae817e003d970bc52a0..bf224c97854daa379c61affff6a0ac9524c2c35d 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java +@@ -561,7 +561,7 @@ public class EntityTurtle extends EntityAnimal { + Random random = this.animal.getRandom(); + + if (this.b.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { +- this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), random.nextInt(7) + 1)); ++ this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), random.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper; + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +index 74802de01dba30e38e09f6fc1f61e7bb64cf5f09..97ef4c65c8cc569a99d9697f56bd44d32b151328 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +@@ -661,7 +661,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + int j = EntityExperienceOrb.getOrbValue(i); + + i -= j; +- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j)); ++ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.killer, this)); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index 72ed4de72c87e9c241507838ddb42eaa4c05ef32..881bca30d2271560e2f2063f7d50753ec67a23f6 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -600,7 +600,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + } + + if (merchantrecipe.isRewardExp()) { +- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i)); ++ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTrader(), this)); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +index 46da22aeef6132a96e413301935c4fef7a96e0ee..4f81a97b1451fec0bb5fd1479acad97846c40c7c 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +@@ -189,7 +189,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { + if (merchantrecipe.isRewardExp()) { + int i = 3 + this.random.nextInt(4); + +- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i)); ++ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTrader(), this)); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +index 2067af9b13c7ce28cd8ad6c785e2d0a7ff013430..38bcc5a4435c4018b3233cc5e4c9142259e4396d 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +@@ -503,7 +503,7 @@ public class EntityFishingHook extends IProjectile { + this.world.addEntity(entityitem); + // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() + if (playerFishEvent.getExpToDrop() > 0) { +- entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop())); ++ entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getOwner(), this)); // Paper + } + // CraftBukkit end + if (itemstack1.getItem().a((Tag) TagsItem.FISHES)) { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java b/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java +index 87fe16c81b57ba07399f5566ab8bd77d71db36a1..e07353a6b34196e3d275ba482fbef7e4d209c31d 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java +@@ -54,7 +54,7 @@ public class EntityThrownExpBottle extends EntityProjectileThrowable { + int j = EntityExperienceOrb.getOrbValue(i); + + i -= j; +- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j)); ++ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, getShooter(), this)); // Paper + } + + this.die(); +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java +index cba1de50f3035ae1b9366f474745d50a1f8fc014..fad7355a549aef811bca43be198af3d1c0a53980 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java +@@ -94,7 +94,7 @@ public class ContainerGrindstone extends Container { + int k = EntityExperienceOrb.getOrbValue(j); + + j -= k; +- world.addEntity(new EntityExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k)); ++ world.addEntity(new EntityExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k, org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, entityhuman)); // Paper + } + + world.triggerEffect(1042, blockposition, 0); +diff --git a/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java b/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java +index 48324295913dd9a9bd31332b5b811a729b621dfb..a114e576e5d80c25cc7f2b17f0dc3ad706a1b877 100644 +--- a/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java ++++ b/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java +@@ -7,7 +7,7 @@ import net.minecraft.world.level.block.entity.TileEntityFurnace; + + public class SlotFurnaceResult extends Slot { + +- private final EntityHuman a; ++ private final EntityHuman a; public final EntityHuman getPlayer() { return this.a; } // Paper OBFHELPER + private int b; + + public SlotFurnaceResult(EntityHuman entityhuman, IInventory iinventory, int i, int j, int k) { +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index d285c4e3d9f938973bf7fb904680044b414e6236..615a4418fd276cd3e0b3686d962ebaf13ef5d4be 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -267,13 +267,13 @@ public class Block extends BlockBase implements IMaterial { + } + } + +- public void dropExperience(WorldServer worldserver, BlockPosition blockposition, int i) { ++ public void dropExperience(WorldServer worldserver, BlockPosition blockposition, int i, net.minecraft.server.level.EntityPlayer player) { // Paper + if (worldserver.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) { + while (i > 0) { + int j = EntityExperienceOrb.getOrbValue(i); + + i -= j; +- worldserver.addEntity(new EntityExperienceOrb(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j)); ++ worldserver.addEntity(new EntityExperienceOrb(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player)); // Paper + } + } + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +index 9744d51a52c5eb99c4cf9e36d9380c49674dd136..deaa4c136c23dc6c258cc1ce68523b3c007c80f9 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +@@ -603,7 +603,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + int k = EntityExperienceOrb.getOrbValue(j); + + j -= k; +- world.addEntity(new EntityExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k)); ++ world.addEntity(new EntityExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman)); // Paper + } + + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 29f5311260d0d5ee321db94031ffc3ed528d6b02..d7d58a0feac2d0b4303c625b7952103613e8c33e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1835,7 +1835,7 @@ public class CraftWorld implements World { + } else if (TNTPrimed.class.isAssignableFrom(clazz)) { + entity = new EntityTNTPrimed(world, x, y, z, null); + } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { +- entity = new EntityExperienceOrb(world, x, y, z, 0); ++ entity = new EntityExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper + } else if (LightningStrike.class.isAssignableFrom(clazz)) { + entity = EntityTypes.LIGHTNING_BOLT.a(world); + } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +index da14f59aec2b6854c3a47fb531aadc9ddb74954c..c6880830720baa2723ab003e51be1b48574d7319 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +@@ -20,6 +20,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { + getHandle().value = value; + } + ++ // Paper start ++ public java.util.UUID getTriggerEntityId() { ++ return getHandle().triggerEntityId; ++ } ++ public java.util.UUID getSourceEntityId() { ++ return getHandle().sourceEntityId; ++ } ++ public SpawnReason getSpawnReason() { ++ return getHandle().spawnReason; ++ } ++ // Paper end ++ + @Override + public EntityExperienceOrb getHandle() { + return (EntityExperienceOrb) entity; diff --git a/patches/server-unmapped/0138-Cap-Entity-Collisions.patch b/patches/server-unmapped/0138-Cap-Entity-Collisions.patch new file mode 100644 index 0000000000..d620a07721 --- /dev/null +++ b/patches/server-unmapped/0138-Cap-Entity-Collisions.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 22 Jan 2017 18:07:56 -0500 +Subject: [PATCH] Cap Entity Collisions + +Limit a single entity to colliding a max of configurable times per tick. +This will alleviate issues where living entities are hoarded in 1x1 pens + +This is not tied to the maxEntityCramming rule. Cramming will still apply +just as it does in Vanilla, but entity pushing logic will be capped. + +You can set this to 0 to disable collisions. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2dc58b9f769ea43b737804456aafab47ecc143b8..c611b5a63498f5ad1f50a75ccd5d7299e27df7e3 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -324,4 +324,10 @@ public class PaperWorldConfig { + log("Treasure Maps will return already discovered locations"); + } + } ++ ++ public int maxCollisionsPerEntity; ++ private void maxEntityCollision() { ++ maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); ++ log( "Max Entity Collisions: " + maxCollisionsPerEntity ); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 00e79363b3f961111595c50758332f6c1c1b31bb..dcaf5c107bb77b63333f924a33961f9e5cad7082 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -268,6 +268,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; + public long activatedTick = Integer.MIN_VALUE; ++ protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index f26f02856e7cca0ca62325adf992619dd15b3885..dd9c51b28e32389429887e9c9cef0a554eff8a40 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -2903,8 +2903,11 @@ public abstract class EntityLiving extends Entity { + } + } + +- for (j = 0; j < list.size(); ++j) { ++ numCollisions = Math.max(0, numCollisions - world.paperConfig.maxCollisionsPerEntity); // Paper ++ for (j = 0; j < list.size() && numCollisions < world.paperConfig.maxCollisionsPerEntity; ++j) { // Paper + Entity entity = (Entity) list.get(j); ++ entity.numCollisions++; // Paper ++ numCollisions++; // Paper + + this.C(entity); + } diff --git a/patches/server-unmapped/0139-Remove-CraftScheduler-Async-Task-Debugger.patch b/patches/server-unmapped/0139-Remove-CraftScheduler-Async-Task-Debugger.patch new file mode 100644 index 0000000000..db58842a96 --- /dev/null +++ b/patches/server-unmapped/0139-Remove-CraftScheduler-Async-Task-Debugger.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 5 Feb 2017 00:04:04 -0500 +Subject: [PATCH] Remove CraftScheduler Async Task Debugger + +I have not once ever seen this system help debug a crash. +One report of a suspected memory leak with the system. + +This adds additional overhead to asynchronous task dispatching + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 9b6d9373abb59a30c2835ca891282d07559281f5..0e0f361c3af363539d5d1d865603114bdb84fd67 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -430,7 +430,7 @@ public class CraftScheduler implements BukkitScheduler { + } + parsePending(); + } else { +- debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); ++ //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper + executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper + // We don't need to parse pending + // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) +@@ -447,7 +447,7 @@ public class CraftScheduler implements BukkitScheduler { + pending.addAll(temp); + temp.clear(); + MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); +- debugHead = debugHead.getNextHead(currentTick); ++ //debugHead = debugHead.getNextHead(currentTick); // Paper + } + + private void addTask(final CraftTask task) { +@@ -507,10 +507,15 @@ public class CraftScheduler implements BukkitScheduler { + + @Override + public String toString() { ++ // Paper start ++ return ""; ++ /* + int debugTick = currentTick; + StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - RECENT_TICKS).append('-').append(debugTick).append('{'); + debugHead.debugTo(string); + return string.append('}').toString(); ++ */ ++ // Paper end + } + + @Deprecated diff --git a/patches/server-unmapped/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/patches/server-unmapped/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch new file mode 100644 index 0000000000..3d1bc3912d --- /dev/null +++ b/patches/server-unmapped/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Tue, 7 Feb 2017 16:55:35 -0600 +Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue + + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 2511fbe7aa5ff1ace71b513d2938975e388295c6..1d71a19a7bbe463f537861531113dd1ed3e5b977 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -121,7 +121,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + private final PlayerMap playerMap; + public final Int2ObjectMap trackedEntities; + private final Long2ByteMap z; +- private final Queue A; ++ private final Queue A; private final Queue getUnloadQueueTasks() { return this.A; } // Paper - OBFHELPER + private int viewDistance; + + // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() +@@ -179,7 +179,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.playerMap = new PlayerMap(); + this.trackedEntities = new Int2ObjectOpenHashMap(); + this.z = new Long2ByteOpenHashMap(); +- this.A = Queues.newConcurrentLinkedQueue(); ++ this.A = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size() + this.definedStructureManager = definedstructuremanager; + this.w = convertable_conversionsession.a(worldserver.getDimensionKey()); + this.world = worldserver; +@@ -437,7 +437,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + // Spigot start + org.spigotmc.SlackActivityAccountant activityAccountant = this.world.getMinecraftServer().slackActivityAccountant; + activityAccountant.startActivity(0.5); +- int targetSize = (int) (this.unloadQueue.size() * UNLOAD_QUEUE_RESIZE_FACTOR); ++ int targetSize = Math.min(this.unloadQueue.size() - 100, (int) (this.unloadQueue.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive + // Spigot end + while (longiterator.hasNext()) { // Spigot + long j = longiterator.nextLong(); +@@ -459,7 +459,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + Runnable runnable; + +- while ((booleansupplier.getAsBoolean() || this.A.size() > 2000) && (runnable = (Runnable) this.A.poll()) != null) { ++ int queueTarget = Math.min(this.getUnloadQueueTasks().size() - 100, (int) (this.getUnloadQueueTasks().size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well ++ while ((booleansupplier.getAsBoolean() || this.getUnloadQueueTasks().size() > queueTarget) && (runnable = (Runnable)this.getUnloadQueueTasks().poll()) != null) { // Paper - Target this queue as well + runnable.run(); + } + diff --git a/patches/server-unmapped/0141-Do-not-let-armorstands-drown.patch b/patches/server-unmapped/0141-Do-not-let-armorstands-drown.patch new file mode 100644 index 0000000000..4141d9b9b2 --- /dev/null +++ b/patches/server-unmapped/0141-Do-not-let-armorstands-drown.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 18 Feb 2017 19:29:58 -0600 +Subject: [PATCH] Do not let armorstands drown + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index dd9c51b28e32389429887e9c9cef0a554eff8a40..036577b0237e9c8a7ab22ede7477eefa1abecf96 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -338,6 +338,7 @@ public abstract class EntityLiving extends Entity { + super.a(d0, flag, iblockdata, blockposition); + } + ++ public boolean canBreatheUnderwater() { return this.cM(); } // Paper - OBFHELPER + public boolean cM() { + return this.getMonsterType() == EnumMonsterType.UNDEAD; + } +@@ -381,7 +382,7 @@ public abstract class EntityLiving extends Entity { + + if (this.isAlive()) { + if (this.a((Tag) TagsFluid.WATER) && !this.world.getType(new BlockPosition(this.locX(), this.getHeadY(), this.locZ())).a(Blocks.BUBBLE_COLUMN)) { +- if (!this.cM() && !MobEffectUtil.c(this) && !flag1) { ++ if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { // Paper - use OBFHELPER so it can be overridden + this.setAirTicks(this.l(this.getAirTicks())); + if (this.getAirTicks() == -20) { + this.setAirTicks(0); +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +index 2ef991aa7f739d3577fbbf4386064557e8f7c904..57e0ea95df34fab22d6c5868ab839d56a3fa85fc 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +@@ -872,5 +872,10 @@ public class EntityArmorStand extends EntityLiving { + super.move(moveType, vec3d); + } + } ++ ++ @Override ++ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization ++ return true; ++ } + // Paper end + } diff --git a/patches/server-unmapped/0142-Properly-handle-async-calls-to-restart-the-server.patch b/patches/server-unmapped/0142-Properly-handle-async-calls-to-restart-the-server.patch new file mode 100644 index 0000000000..108fec7080 --- /dev/null +++ b/patches/server-unmapped/0142-Properly-handle-async-calls-to-restart-the-server.patch @@ -0,0 +1,307 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Fri, 12 May 2017 23:34:11 -0500 +Subject: [PATCH] Properly handle async calls to restart the server + +The watchdog thread calls the server restart function asynchronously. Prior to +this change, it attempted to do several non-safe operations from the watchdog +thread, rather than the main. Specifically, because of a separate upstream change, +it causes player entities to be ticked asynchronously, among other things. + +This is dangerous. + +This patch moves the old handling into a synchronous variant, for calls from the +restart command, and adds separate handling for async calls, such as those from +the watchdog thread. + +When calling from the watchdog thread, we cannot assume the main thread is in a +tickable state; it may be completely deadlocked. In order to handle this, we mark +the server as stopping, in order to account for situations where the server should +complete a tick reasonbly soon, i.e. 99% of cases. + +Should the server not enter a state where it is stopping within 10 seconds, We +will assume that the server has in fact deadlocked and will proceed to force +kill the server. + +This modification does not force restart the server should we actually enter a +deadlocked state where the server is stopping, whereas this will in most cases +exit within a reasonable amount of time, to put a fixed limit on a process that +will have plugins and worlds saving to the disk has a high potential to result +in corruption/dataloss. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 20dffd9dc4cb3868638151b70535f353a3bf1a44..fae7e4a7adcc930a7252634dc535339b5a5bd3b9 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -201,6 +201,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant, WorldServer> worldServer; + private PlayerList playerList; + private volatile boolean isRunning; ++ private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart + private boolean isStopped; + private int ticks; + protected final Proxy proxy; +@@ -860,7 +861,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && new File( split[0] ).isFile() ) ++ // Paper - extract method and cleanup ++ boolean isRestarting = addShutdownHook( restartScript ); ++ if ( isRestarting ) + { +- System.out.println( "Attempting to restart with " + restartScript ); ++ System.out.println( "Attempting to restart with " + SpigotConfig.restartScript ); ++ } else ++ { ++ System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); ++ } ++ // Stop the watchdog ++ WatchdogThread.doStop(); + +- // Disable Watchdog +- WatchdogThread.doStop(); ++ shutdownServer( isRestarting ); ++ // Paper end ++ } catch ( Exception ex ) ++ { ++ ex.printStackTrace(); ++ } ++ } + +- // Kick all players +- for ( EntityPlayer p : (List) MinecraftServer.getServer().getPlayerList().players ) +- { +- p.playerConnection.disconnect(SpigotConfig.restartMessage); +- } +- // Give the socket a chance to send the packets +- try +- { +- Thread.sleep( 100 ); +- } catch ( InterruptedException ex ) +- { +- } +- // Close the socket so we can rebind with the new process +- MinecraftServer.getServer().getServerConnection().b(); ++ // Paper start - sync copied from above with minor changes, async added ++ private static void shutdownServer(boolean isRestarting) ++ { ++ if ( MinecraftServer.getServer().isMainThread() ) ++ { ++ // Kick all players ++ for ( EntityPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) ++ { ++ p.playerConnection.disconnect(SpigotConfig.restartMessage); ++ } ++ // Give the socket a chance to send the packets ++ try ++ { ++ Thread.sleep( 100 ); ++ } catch ( InterruptedException ex ) ++ { ++ } + +- // Give time for it to kick in +- try +- { +- Thread.sleep( 100 ); +- } catch ( InterruptedException ex ) +- { +- } ++ closeSocket(); + +- // Actually shutdown +- try +- { +- MinecraftServer.getServer().close(); +- } catch ( Throwable t ) +- { +- } ++ // Actually shutdown ++ try ++ { ++ MinecraftServer.getServer().close(); // calls stop() ++ } catch ( Throwable t ) ++ { ++ } ++ ++ // Actually stop the JVM ++ System.exit( 0 ); + +- // This will be done AFTER the server has completely halted +- Thread shutdownHook = new Thread() ++ } else ++ { ++ // Mark the server to shutdown at the end of the tick ++ MinecraftServer.getServer().safeShutdown( false, isRestarting ); ++ ++ // wait 10 seconds to see if we're actually going to try shutdown ++ try ++ { ++ Thread.sleep( 10000 ); ++ } ++ catch (InterruptedException ignored) ++ { ++ } ++ ++ // Check if we've actually hit a state where the server is going to safely shutdown ++ // if we have, let the server stop as usual ++ if (MinecraftServer.getServer().isStopped()) return; ++ ++ // If the server hasn't stopped by now, assume worse case and kill ++ closeSocket(); ++ System.exit( 0 ); ++ } ++ } ++ // Paper end ++ ++ // Paper - Split from moved code ++ private static void closeSocket() ++ { ++ // Close the socket so we can rebind with the new process ++ MinecraftServer.getServer().getServerConnection().b(); ++ ++ // Give time for it to kick in ++ try ++ { ++ Thread.sleep( 100 ); ++ } catch ( InterruptedException ex ) ++ { ++ } ++ } ++ // Paper end ++ ++ // Paper start - copied from above and modified to return if the hook registered ++ private static boolean addShutdownHook(String restartScript) ++ { ++ String[] split = restartScript.split( " " ); ++ if ( split.length > 0 && new File( split[0] ).isFile() ) ++ { ++ Thread shutdownHook = new Thread() ++ { ++ @Override ++ public void run() + { +- @Override +- public void run() ++ try + { +- try ++ String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); ++ if ( os.contains( "win" ) ) + { +- String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); +- if ( os.contains( "win" ) ) +- { +- Runtime.getRuntime().exec( "cmd /c start " + restartScript ); +- } else +- { +- Runtime.getRuntime().exec( "sh " + restartScript ); +- } +- } catch ( Exception e ) ++ Runtime.getRuntime().exec( "cmd /c start " + restartScript ); ++ } else + { +- e.printStackTrace(); ++ Runtime.getRuntime().exec( "sh " + restartScript ); + } ++ } catch ( Exception e ) ++ { ++ e.printStackTrace(); + } +- }; +- +- shutdownHook.setDaemon( true ); +- Runtime.getRuntime().addShutdownHook( shutdownHook ); +- } else +- { +- System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); +- +- // Actually shutdown +- try +- { +- MinecraftServer.getServer().close(); +- } catch ( Throwable t ) +- { + } +- } +- System.exit( 0 ); +- } catch ( Exception ex ) ++ }; ++ ++ shutdownHook.setDaemon( true ); ++ Runtime.getRuntime().addShutdownHook( shutdownHook ); ++ return true; ++ } else + { +- ex.printStackTrace(); ++ return false; + } + } ++ // Paper end ++ + } diff --git a/patches/server-unmapped/0143-Add-system-property-to-disable-book-size-limits.patch b/patches/server-unmapped/0143-Add-system-property-to-disable-book-size-limits.patch new file mode 100644 index 0000000000..dd733c5fb3 --- /dev/null +++ b/patches/server-unmapped/0143-Add-system-property-to-disable-book-size-limits.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 13 May 2017 20:11:21 -0500 +Subject: [PATCH] Add system property to disable book size limits + +If anyone comes in with a watchdog crash related to books after this patch +you will not only be publicly shamed but also made an example of. + +Disables the security limits on books entirely, allowing plugins AND players +to make books with as much data as they want. Do not use this without +limiting incoming data from packets in some other way. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +index 65b6d32e3e1130a64df33082f3292cb1ce6f500a..1a4c1763e883e445433b3780fe20db7f62b780e8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +@@ -41,6 +41,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + static final int MAX_PAGES = 100; + static final int MAX_PAGE_LENGTH = 320; // 256 limit + 64 characters to allow for psuedo colour codes + static final int MAX_TITLE_LENGTH = 32; ++ private static final boolean OVERRIDE_CHECKS = Boolean.getBoolean("disable.book-limits"); // Paper - Add override + + protected String title; + protected String author; +@@ -243,7 +244,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + if (title == null) { + this.title = null; + return true; +- } else if (title.length() > MAX_TITLE_LENGTH) { ++ } else if (title.length() > MAX_TITLE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override + return false; + } + +@@ -440,7 +441,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + String validatePage(String page) { + if (page == null) { + page = ""; +- } else if (page.length() > MAX_PAGE_LENGTH) { ++ } else if (page.length() > MAX_PAGE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override + page = page.substring(0, MAX_PAGE_LENGTH); + } + return page; +@@ -450,7 +451,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + // asserted: page != null + if (this.pages == null) { + this.pages = new ArrayList(); +- } else if (this.pages.size() >= MAX_PAGES) { ++ } else if (this.pages.size() >= MAX_PAGES && !OVERRIDE_CHECKS) {// Paper - Add override + return; + } + this.pages.add(page); diff --git a/patches/server-unmapped/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/patches/server-unmapped/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch new file mode 100644 index 0000000000..bc90566e9b --- /dev/null +++ b/patches/server-unmapped/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 16 May 2017 21:29:08 -0500 +Subject: [PATCH] Add option to make parrots stay on shoulders despite movement + +Makes parrots not fall off whenever the player changes height, or touches water, or gets hit by a passing leaf. +Instead, switches the behavior so that players have to sneak to make the birds leave. + +I suspect Mojang may switch to this behavior before full release. + +To be converted into a Paper-API event at some point in the future? + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index c611b5a63498f5ad1f50a75ccd5d7299e27df7e3..9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -330,4 +330,10 @@ public class PaperWorldConfig { + maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); + log( "Max Entity Collisions: " + maxCollisionsPerEntity ); + } ++ ++ public boolean parrotsHangOnBetter; ++ private void parrotsHangOnBetter() { ++ parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); ++ log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index d507d050f9a1ebd65383adb2b21699a01d9b0385..8c39dc4f05becea92f3ec86c4103be4e34f2b835 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2053,6 +2053,13 @@ public class PlayerConnection implements PacketListenerPlayIn { + switch (packetplayinentityaction.c()) { + case PRESS_SHIFT_KEY: + this.player.setSneaking(true); ++ ++ // Paper start - Hang on! ++ if (this.player.world.paperConfig.parrotsHangOnBetter) { ++ this.player.releaseShoulderEntities(); ++ } ++ // Paper end ++ + break; + case RELEASE_SHIFT_KEY: + this.player.setSneaking(false); +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index e3e3426a00128b56d523bb43a59b814b915ad0ff..ba26fc2405e17d582da971d03147fb1865e9b546 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -532,7 +532,7 @@ public abstract class EntityHuman extends EntityLiving { + this.j(this.getShoulderEntityLeft()); + this.j(this.getShoulderEntityRight()); + if (!this.world.isClientSide && (this.fallDistance > 0.5F || this.isInWater()) || this.abilities.isFlying || this.isSleeping()) { +- this.releaseShoulderEntities(); ++ if (!this.world.paperConfig.parrotsHangOnBetter) this.releaseShoulderEntities(); // Paper - Hang on! + } + + } diff --git a/patches/server-unmapped/0145-Add-configuration-option-to-prevent-player-names-fro.patch b/patches/server-unmapped/0145-Add-configuration-option-to-prevent-player-names-fro.patch new file mode 100644 index 0000000000..1d7d21727e --- /dev/null +++ b/patches/server-unmapped/0145-Add-configuration-option-to-prevent-player-names-fro.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Fri, 9 Jun 2017 07:24:34 -0700 +Subject: [PATCH] Add configuration option to prevent player names from being + suggested + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 4e2f243faa209925dcb7c3ef89df3ed875c5ff78..48319aaf1c525c6fb7bdee5c2f570a0d056d4eae 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -268,4 +268,9 @@ public class PaperConfig { + flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); + flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); + } ++ ++ public static boolean suggestPlayersWhenNullTabCompletions = true; ++ private static void suggestPlayersWhenNull() { ++ suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 539577a0378754cbe0942a79140f6d137eb825ed..0ed8e95d464cf17dc0355056775a9a375a4e7a86 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2301,5 +2301,10 @@ public final class CraftServer implements Server { + commandMap.registerServerAliases(); + return true; + } ++ ++ @Override ++ public boolean suggestPlayerNamesWhenNullTabCompletions() { ++ return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; ++ } + // Paper end + } diff --git a/patches/server-unmapped/0146-Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server-unmapped/0146-Use-TerminalConsoleAppender-for-console-improvements.patch new file mode 100644 index 0000000000..80016ae985 --- /dev/null +++ b/patches/server-unmapped/0146-Use-TerminalConsoleAppender-for-console-improvements.patch @@ -0,0 +1,549 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Fri, 9 Jun 2017 19:03:43 +0200 +Subject: [PATCH] Use TerminalConsoleAppender for console improvements + +Rewrite console improvements (console colors, tab completion, +persistent input line, ...) using JLine 3.x and TerminalConsoleAppender. + +New features: + - Support console colors for Vanilla commands + - Add console colors for warnings and errors + - Server can now be turned off safely using CTRL + C. JLine catches + the signal and the implementation shuts down the server cleanly. + - Support console colors and persistent input line when running in + IntelliJ IDEA + +Other changes: + - Server starts 1-2 seconds faster thanks to optimizations in Log4j + configuration + +diff --git a/pom.xml b/pom.xml +index a5d87d22cb1588d15e08da3b37e51c5e261c7799..3841fe3630c090f8a468333d43caeb2b5841329d 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -57,10 +57,26 @@ + compile + + +- jline +- jline +- 2.12.1 +- compile ++ net.minecrell ++ terminalconsoleappender ++ 1.2.0 ++ ++ ++ org.jline ++ jline-terminal-jansi ++ 3.12.1 ++ runtime ++ ++ ++ ++ org.apache.logging.log4j ++ log4j-core ++ runtime + + + org.apache.logging.log4j +@@ -334,10 +350,18 @@ + + META-INF/services/java.sql.Driver + ++ + + + + ++ ++ ++ com.github.edwgiz ++ maven-shade-plugin.log4j2-cachefile-transformer ++ 2.13.1 ++ ++ + + + org.apache.maven.plugins +diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +new file mode 100644 +index 0000000000000000000000000000000000000000..89eeb9d202405747409e65fcf226d95379987e29 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.console; ++ ++import net.minecraft.server.dedicated.DedicatedServer; ++import net.minecrell.terminalconsole.SimpleTerminalConsole; ++import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; ++import org.jline.reader.LineReader; ++import org.jline.reader.LineReaderBuilder; ++ ++public final class PaperConsole extends SimpleTerminalConsole { ++ ++ private final DedicatedServer server; ++ ++ public PaperConsole(DedicatedServer server) { ++ this.server = server; ++ } ++ ++ @Override ++ protected LineReader buildReader(LineReaderBuilder builder) { ++ return super.buildReader(builder ++ .appName("Paper") ++ .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) ++ .completer(new ConsoleCommandCompleter(this.server)) ++ ); ++ } ++ ++ @Override ++ protected boolean isRunning() { ++ return !this.server.isStopped() && this.server.isRunning(); ++ } ++ ++ @Override ++ protected void runCommand(String command) { ++ this.server.issueCommand(command, this.server.getServerCommandListener()); ++ } ++ ++ @Override ++ protected void shutdown() { ++ this.server.safeShutdown(false); ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java +new file mode 100644 +index 0000000000000000000000000000000000000000..685deaa0e5d1ddc13e3a7c0471b1cfcf1710c869 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.console; ++ ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++import org.bukkit.craftbukkit.command.CraftConsoleCommandSender; ++ ++public class TerminalConsoleCommandSender extends CraftConsoleCommandSender { ++ ++ private static final Logger LOGGER = LogManager.getRootLogger(); ++ ++ @Override ++ public void sendRawMessage(String message) { ++ // TerminalConsoleAppender supports color codes directly in log messages ++ LOGGER.info(message); ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index fae7e4a7adcc930a7252634dc535339b5a5bd3b9..71496fff9faeb72e28dfc2842ed8105a9cb835c1 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -12,6 +12,7 @@ import com.mojang.datafixers.DataFixer; + import io.netty.buffer.ByteBuf; + import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + import it.unimi.dsi.fastutil.longs.LongIterator; + import java.awt.image.BufferedImage; + import java.io.BufferedWriter; +@@ -160,7 +161,7 @@ import org.apache.logging.log4j.Logger; + import com.mojang.serialization.DynamicOps; + import com.mojang.serialization.Lifecycle; + import com.google.common.collect.ImmutableSet; +-import jline.console.ConsoleReader; ++// import jline.console.ConsoleReader; // Paper + import joptsimple.OptionSet; + import net.minecraft.nbt.DynamicOpsNBT; + import net.minecraft.nbt.NBTBase; +@@ -255,7 +256,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; +@@ -324,7 +325,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant replacements = new EnumMap(ChatColor.class); + private final ChatColor[] colors = ChatColor.values(); +@@ -93,5 +91,5 @@ public class ColouredConsoleSender extends CraftConsoleCommandSender { + } else { + return new ColouredConsoleSender(); + } +- } ++ }*/ // Paper + } +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index befcc19f9b56df9096b98a23b0020f1db793ea5b..a957695457cf3252848ce6ef37069692841b8e28 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -4,20 +4,31 @@ import java.util.Collections; + import java.util.List; + import java.util.concurrent.ExecutionException; + import java.util.logging.Level; +-import jline.console.completer.Completer; ++import net.minecraft.server.dedicated.DedicatedServer; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.util.Waitable; ++ ++// Paper start - JLine update ++import org.jline.reader.Candidate; ++import org.jline.reader.Completer; ++import org.jline.reader.LineReader; ++import org.jline.reader.ParsedLine; ++// Paper end + import org.bukkit.event.server.TabCompleteEvent; + + public class ConsoleCommandCompleter implements Completer { +- private final CraftServer server; ++ private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer + +- public ConsoleCommandCompleter(CraftServer server) { ++ public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer + this.server = server; + } + ++ // Paper start - Change method signature for JLine update + @Override +- public int complete(final String buffer, final int cursor, final List candidates) { ++ public void complete(LineReader reader, ParsedLine line, List candidates) { ++ final CraftServer server = this.server.server; ++ final String buffer = line.line(); ++ // Paper end + Waitable> waitable = new Waitable>() { + @Override + protected List evaluate() { +@@ -29,25 +40,37 @@ public class ConsoleCommandCompleter implements Completer { + return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); + } + }; +- this.server.getServer().processQueue.add(waitable); ++ server.getServer().processQueue.add(waitable); // Paper - Remove "this." + try { + List offers = waitable.get(); + if (offers == null) { +- return cursor; ++ return; // Paper - Method returns void ++ } ++ ++ // Paper start - JLine update ++ for (String completion : offers) { ++ if (completion.isEmpty()) { ++ continue; ++ } ++ ++ candidates.add(new Candidate(completion)); + } +- candidates.addAll(offers); ++ // Paper end + ++ // Paper start - JLine handles cursor now ++ /* + final int lastSpace = buffer.lastIndexOf(' '); + if (lastSpace == -1) { + return cursor - buffer.length(); + } else { + return cursor - (buffer.length() - lastSpace - 1); + } ++ */ ++ // Paper end + } catch (ExecutionException e) { +- this.server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); ++ server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); // Paper - Remove "this." + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } +- return cursor; + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +index 70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe..449e99d1b673870ed6892f6ab2c715a2db35c35d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +@@ -17,7 +17,7 @@ public class ServerShutdownThread extends Thread { + server.close(); + } finally { + try { +- server.reader.getTerminal().restore(); ++ net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender + } catch (Exception e) { + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java +index 99564fed7ce77e29dbdc591bcfe656af741acf8a..9a2da548b8860b496e396564b2c8f6383f020193 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java +@@ -5,12 +5,12 @@ import java.io.IOException; + import java.io.OutputStream; + import java.util.logging.Level; + import java.util.logging.Logger; +-import jline.console.ConsoleReader; ++//import jline.console.ConsoleReader; + import org.bukkit.craftbukkit.Main; +-import org.fusesource.jansi.Ansi; +-import org.fusesource.jansi.Ansi.Erase; ++//import org.fusesource.jansi.Ansi; ++//import org.fusesource.jansi.Ansi.Erase; + +-public class TerminalConsoleWriterThread extends Thread { ++public class TerminalConsoleWriterThread /*extends Thread*/ {/* // Paper - disable + private final ConsoleReader reader; + private final OutputStream output; + +@@ -54,5 +54,5 @@ public class TerminalConsoleWriterThread extends Thread { + Logger.getLogger(TerminalConsoleWriterThread.class.getName()).log(Level.SEVERE, null, ex); + } + } +- } ++ }*/ + } +diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties +new file mode 100644 +index 0000000000000000000000000000000000000000..0694b21465fb9e4164e71862ff24b62241b191f2 +--- /dev/null ++++ b/src/main/resources/log4j2.component.properties +@@ -0,0 +1 @@ ++log4j.skipJansi=true +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 722ca84968cbbbdeffd09939abff0cccd0a84010..620b9490e5f159080e50289d127404a1b56adbef 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -1,17 +1,14 @@ + + + +- +- +- + + + +- +- +- ++ ++ ++ + +- ++ + + + +@@ -24,10 +21,9 @@ + + + +- + +- + ++ + + + diff --git a/patches/server-unmapped/0147-provide-a-configurable-option-to-disable-creeper-lin.patch b/patches/server-unmapped/0147-provide-a-configurable-option-to-disable-creeper-lin.patch new file mode 100644 index 0000000000..d2c710ef94 --- /dev/null +++ b/patches/server-unmapped/0147-provide-a-configurable-option-to-disable-creeper-lin.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 11 Jun 2017 21:01:18 +0100 +Subject: [PATCH] provide a configurable option to disable creeper lingering + effect spawns + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1..90ca51dfdbb3045dd528450225cba96f5834166e 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -336,4 +336,10 @@ public class PaperWorldConfig { + parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); + log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); + } ++ ++ public boolean disableCreeperLingeringEffect; ++ private void setDisableCreeperLingeringEffect() { ++ disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); ++ log("Creeper lingering effect: " + disableCreeperLingeringEffect); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +index 4106cce3071ac8bfe33e94b0fc7f67cfeef214b4..08292753f925f33d75f3aca835c1fd19494b22ec 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +@@ -262,7 +262,7 @@ public class EntityCreeper extends EntityMonster { + private void createEffectCloud() { + Collection collection = this.getEffects(); + +- if (!collection.isEmpty()) { ++ if (!collection.isEmpty() && !world.paperConfig.disableCreeperLingeringEffect) { // Paper + EntityAreaEffectCloud entityareaeffectcloud = new EntityAreaEffectCloud(this.world, this.locX(), this.locY(), this.locZ()); + + entityareaeffectcloud.setSource(this); // CraftBukkit diff --git a/patches/server-unmapped/0148-Item-canEntityPickup.patch b/patches/server-unmapped/0148-Item-canEntityPickup.patch new file mode 100644 index 0000000000..1bb1f6f355 --- /dev/null +++ b/patches/server-unmapped/0148-Item-canEntityPickup.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 5 May 2017 03:57:17 -0500 +Subject: [PATCH] Item#canEntityPickup + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index ccdfc8068a8205d6e66ab9458764b1440f8c4b97..2cc15ac22000343dc540454ba971993bf5b2f5a3 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -607,6 +607,11 @@ public abstract class EntityInsentient extends EntityLiving { + EntityItem entityitem = (EntityItem) iterator.next(); + + if (!entityitem.dead && !entityitem.getItemStack().isEmpty() && !entityitem.p() && this.i(entityitem.getItemStack())) { ++ // Paper Start ++ if (!entityitem.canMobPickup) { ++ continue; ++ } ++ // Paper End + this.b(entityitem); + } + } +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index 38b91b450c6bdc25efaed495ce26d909a52531bf..c486c07a358c0b444e1a1372b6d0fa2901840eac 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -47,6 +47,7 @@ public class EntityItem extends Entity { + private UUID owner; + public final float b; + private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit ++ public boolean canMobPickup = true; // Paper + + public EntityItem(EntityTypes entitytypes, World world) { + super(entitytypes, world); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +index f333dd2726f554a3137a3a78d162905f4ed1435e..5988cdd18b7e4bfca0075fd2356cfe9c4e673954 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +@@ -49,6 +49,16 @@ public class CraftItem extends CraftEntity implements Item { + item.age = value; + } + ++ // Paper Start ++ public boolean canMobPickup() { ++ return item.canMobPickup; ++ } ++ ++ public void setCanMobPickup(boolean canMobPickup) { ++ item.canMobPickup = canMobPickup; ++ } ++ // Paper End ++ + @Override + public void setOwner(UUID uuid) { + item.setOwner(uuid); diff --git a/patches/server-unmapped/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch b/patches/server-unmapped/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch new file mode 100644 index 0000000000..2bbbc7656e --- /dev/null +++ b/patches/server-unmapped/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 7 May 2017 06:26:09 -0500 +Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer + + +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index c486c07a358c0b444e1a1372b6d0fa2901840eac..3b72032f6f4f4bd64d1202658cc0c6ee4fb76ea9 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -363,6 +363,7 @@ public class EntityItem extends Entity { + // CraftBukkit start - fire PlayerPickupItemEvent + int canHold = entityhuman.inventory.canHold(itemstack); + int remaining = i - canHold; ++ boolean flyAtPlayer = false; // Paper + + if (this.pickupDelay <= 0 && canHold > 0) { + itemstack.setCount(canHold); +@@ -370,8 +371,14 @@ public class EntityItem extends Entity { + PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); + playerEvent.setCancelled(!entityhuman.canPickUpLoot); + this.world.getServer().getPluginManager().callEvent(playerEvent); ++ flyAtPlayer = playerEvent.getFlyAtPlayer(); // Paper + if (playerEvent.isCancelled()) { + itemstack.setCount(i); // SPIGOT-5294 - restore count ++ // Paper Start ++ if (flyAtPlayer) { ++ entityhuman.receive(this, i); ++ } ++ // Paper End + return; + } + +@@ -401,7 +408,11 @@ public class EntityItem extends Entity { + // CraftBukkit end + + if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(entityhuman.getUniqueID())) && entityhuman.inventory.pickup(itemstack)) { +- entityhuman.receive(this, i); ++ // Paper Start ++ if (flyAtPlayer) { ++ entityhuman.receive(this, i); ++ } ++ // Paper End + if (itemstack.isEmpty()) { + this.die(); + itemstack.setCount(i); diff --git a/patches/server-unmapped/0150-PlayerAttemptPickupItemEvent.patch b/patches/server-unmapped/0150-PlayerAttemptPickupItemEvent.patch new file mode 100644 index 0000000000..13d2f54354 --- /dev/null +++ b/patches/server-unmapped/0150-PlayerAttemptPickupItemEvent.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 11 Jun 2017 16:30:30 -0500 +Subject: [PATCH] PlayerAttemptPickupItemEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index 3b72032f6f4f4bd64d1202658cc0c6ee4fb76ea9..de11fd9772f30ac72c3ca52ec4efc3fef4091425 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -36,6 +36,7 @@ import net.minecraft.server.MinecraftServer; + import org.bukkit.event.entity.EntityPickupItemEvent; + import org.bukkit.event.player.PlayerPickupItemEvent; + // CraftBukkit end ++import org.bukkit.event.player.PlayerAttemptPickupItemEvent; // Paper + + public class EntityItem extends Entity { + +@@ -365,6 +366,22 @@ public class EntityItem extends Entity { + int remaining = i - canHold; + boolean flyAtPlayer = false; // Paper + ++ // Paper start ++ if (this.pickupDelay <= 0) { ++ PlayerAttemptPickupItemEvent attemptEvent = new PlayerAttemptPickupItemEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ this.world.getServer().getPluginManager().callEvent(attemptEvent); ++ ++ flyAtPlayer = attemptEvent.getFlyAtPlayer(); ++ if (attemptEvent.isCancelled()) { ++ if (flyAtPlayer) { ++ entityhuman.receive(this, i); ++ } ++ ++ return; ++ } ++ } ++ // Paper end ++ + if (this.pickupDelay <= 0 && canHold > 0) { + itemstack.setCount(canHold); + // Call legacy event diff --git a/patches/server-unmapped/0151-Add-UnknownCommandEvent.patch b/patches/server-unmapped/0151-Add-UnknownCommandEvent.patch new file mode 100644 index 0000000000..b03b0cc9b6 --- /dev/null +++ b/patches/server-unmapped/0151-Add-UnknownCommandEvent.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sweepyoface +Date: Sat, 17 Jun 2017 18:48:21 -0400 +Subject: [PATCH] Add UnknownCommandEvent + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 2a05ef7553e3b05d5757e69e69c247e24ba29249..9e974159476e7a359f59c0cdf5aae1be4422d1c0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -791,7 +791,13 @@ public final class CraftServer implements Server { + + // Spigot start + if (!org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty()) { +- sender.sendMessage(org.spigotmc.SpigotConfig.unknownCommandMessage); ++ // Paper start ++ org.bukkit.event.command.UnknownCommandEvent event = new org.bukkit.event.command.UnknownCommandEvent(sender, commandLine, org.spigotmc.SpigotConfig.unknownCommandMessage); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.message() != null) { ++ sender.sendMessage(event.message()); ++ } ++ // Paper end + } + // Spigot end + diff --git a/patches/server-unmapped/0152-Basic-PlayerProfile-API.patch b/patches/server-unmapped/0152-Basic-PlayerProfile-API.patch new file mode 100644 index 0000000000..5a9faa7622 --- /dev/null +++ b/patches/server-unmapped/0152-Basic-PlayerProfile-API.patch @@ -0,0 +1,575 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 15 Jan 2018 22:11:48 -0500 +Subject: [PATCH] Basic PlayerProfile API + +Establishes base extension of profile systems for future edits too + +diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3d9452892a4077e64f37424052a9e52d76dd7a6d +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java +@@ -0,0 +1,301 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.destroystokyo.paper.PaperConfig; ++import com.google.common.base.Charsets; ++import com.mojang.authlib.GameProfile; ++import com.mojang.authlib.properties.Property; ++import com.mojang.authlib.properties.PropertyMap; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.players.UserCache; ++import org.apache.commons.lang3.Validate; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.spigotmc.SpigotConfig; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++import java.util.AbstractSet; ++import java.util.Collection; ++import java.util.Iterator; ++import java.util.Objects; ++import java.util.Set; ++import java.util.UUID; ++ ++public class CraftPlayerProfile implements PlayerProfile { ++ ++ private GameProfile profile; ++ private final PropertySet properties = new PropertySet(); ++ ++ public CraftPlayerProfile(CraftPlayer player) { ++ this.profile = player.getHandle().getProfile(); ++ } ++ ++ public CraftPlayerProfile(UUID id, String name) { ++ this.profile = new GameProfile(id, name); ++ } ++ ++ public CraftPlayerProfile(GameProfile profile) { ++ Validate.notNull(profile, "GameProfile cannot be null!"); ++ this.profile = profile; ++ } ++ ++ @Override ++ public boolean hasProperty(String property) { ++ return profile.getProperties().containsKey(property); ++ } ++ ++ @Override ++ public void setProperty(ProfileProperty property) { ++ String name = property.getName(); ++ PropertyMap properties = profile.getProperties(); ++ properties.removeAll(name); ++ properties.put(name, new Property(name, property.getValue(), property.getSignature())); ++ } ++ ++ public GameProfile getGameProfile() { ++ return profile; ++ } ++ ++ @Nullable ++ @Override ++ public UUID getId() { ++ return profile.getId(); ++ } ++ ++ @Override ++ public UUID setId(@Nullable UUID uuid) { ++ GameProfile prev = this.profile; ++ this.profile = new GameProfile(uuid, prev.getName()); ++ copyProfileProperties(prev, this.profile); ++ return prev.getId(); ++ } ++ ++ @Nullable ++ @Override ++ public String getName() { ++ return profile.getName(); ++ } ++ ++ @Override ++ public String setName(@Nullable String name) { ++ GameProfile prev = this.profile; ++ this.profile = new GameProfile(prev.getId(), name); ++ copyProfileProperties(prev, this.profile); ++ return prev.getName(); ++ } ++ ++ @Nonnull ++ @Override ++ public Set getProperties() { ++ return properties; ++ } ++ ++ @Override ++ public void setProperties(Collection properties) { ++ properties.forEach(this::setProperty); ++ } ++ ++ @Override ++ public void clearProperties() { ++ profile.getProperties().clear(); ++ } ++ ++ @Override ++ public boolean removeProperty(String property) { ++ return !profile.getProperties().removeAll(property).isEmpty(); ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ CraftPlayerProfile that = (CraftPlayerProfile) o; ++ return Objects.equals(profile, that.profile); ++ } ++ ++ @Override ++ public int hashCode() { ++ return profile.hashCode(); ++ } ++ ++ @Override ++ public String toString() { ++ return profile.toString(); ++ } ++ ++ @Override ++ public CraftPlayerProfile clone() { ++ CraftPlayerProfile clone = new CraftPlayerProfile(this.getId(), this.getName()); ++ clone.setProperties(getProperties()); ++ return clone; ++ } ++ ++ @Override ++ public boolean isComplete() { ++ return profile.isComplete(); ++ } ++ ++ @Override ++ public boolean completeFromCache() { ++ MinecraftServer server = MinecraftServer.getServer(); ++ return completeFromCache(false, PaperConfig.isProxyOnlineMode()); ++ } ++ ++ public boolean completeFromCache(boolean onlineMode) { ++ return completeFromCache(false, onlineMode); ++ } ++ ++ public boolean completeFromCache(boolean lookupUUID, boolean onlineMode) { ++ MinecraftServer server = MinecraftServer.getServer(); ++ String name = profile.getName(); ++ UserCache userCache = server.getUserCache(); ++ if (profile.getId() == null) { ++ final GameProfile profile; ++ if (onlineMode) { ++ profile = lookupUUID ? userCache.getProfile(name) : userCache.getProfileIfCached(name); ++ } else { ++ // Make an OfflinePlayer using an offline mode UUID since the name has no profile ++ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); ++ } ++ if (profile != null) { ++ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't ++ copyProfileProperties(this.profile, profile); ++ this.profile = profile; ++ } ++ } ++ ++ if ((profile.getName() == null || !hasTextures()) && profile.getId() != null) { ++ GameProfile profile = userCache.getProfile(this.profile.getId()); ++ if (profile != null) { ++ if (this.profile.getName() == null) { ++ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't ++ copyProfileProperties(this.profile, profile); ++ this.profile = profile; ++ } else { ++ copyProfileProperties(profile, this.profile); ++ } ++ } ++ } ++ return this.profile.isComplete(); ++ } ++ ++ public boolean complete(boolean textures) { ++ MinecraftServer server = MinecraftServer.getServer(); ++ return complete(textures, PaperConfig.isProxyOnlineMode()); ++ } ++ public boolean complete(boolean textures, boolean onlineMode) { ++ MinecraftServer server = MinecraftServer.getServer(); ++ ++ boolean isCompleteFromCache = this.completeFromCache(true, onlineMode); ++ if (onlineMode && (!isCompleteFromCache || textures && !hasTextures())) { ++ GameProfile result = server.getMinecraftSessionService().fillProfileProperties(profile, true); ++ if (result != null) { ++ copyProfileProperties(result, this.profile, true); ++ } ++ if (this.profile.isComplete()) { ++ server.getUserCache().saveProfile(this.profile); ++ } ++ } ++ return profile.isComplete() && (!onlineMode || !textures || hasTextures()); ++ } ++ ++ private static void copyProfileProperties(GameProfile source, GameProfile target) { ++ copyProfileProperties(source, target, false); ++ } ++ ++ private static void copyProfileProperties(GameProfile source, GameProfile target, boolean clearTarget) { ++ PropertyMap sourceProperties = source.getProperties(); ++ PropertyMap targetProperties = target.getProperties(); ++ if (clearTarget) targetProperties.clear(); ++ if (sourceProperties.isEmpty()) { ++ return; ++ } ++ ++ for (Property property : sourceProperties.values()) { ++ targetProperties.removeAll(property.getName()); ++ targetProperties.put(property.getName(), property); ++ } ++ } ++ ++ private static ProfileProperty toBukkit(Property property) { ++ return new ProfileProperty(property.getName(), property.getValue(), property.getSignature()); ++ } ++ ++ public static PlayerProfile asBukkitCopy(GameProfile gameProfile) { ++ CraftPlayerProfile profile = new CraftPlayerProfile(gameProfile.getId(), gameProfile.getName()); ++ copyProfileProperties(gameProfile, profile.profile); ++ return profile; ++ } ++ ++ public static PlayerProfile asBukkitMirror(GameProfile profile) { ++ return new CraftPlayerProfile(profile); ++ } ++ ++ public static Property asAuthlib(ProfileProperty property) { ++ return new Property(property.getName(), property.getValue(), property.getSignature()); ++ } ++ ++ public static GameProfile asAuthlibCopy(PlayerProfile profile) { ++ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); ++ return asAuthlib(craft.clone()); ++ } ++ ++ public static GameProfile asAuthlib(PlayerProfile profile) { ++ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); ++ return craft.getGameProfile(); ++ } ++ ++ private class PropertySet extends AbstractSet { ++ ++ @Override ++ @Nonnull ++ public Iterator iterator() { ++ return new ProfilePropertyIterator(profile.getProperties().values().iterator()); ++ } ++ ++ @Override ++ public int size() { ++ return profile.getProperties().size(); ++ } ++ ++ @Override ++ public boolean add(ProfileProperty property) { ++ setProperty(property); ++ return true; ++ } ++ ++ @Override ++ public boolean addAll(Collection c) { ++ //noinspection unchecked ++ setProperties((Collection) c); ++ return true; ++ } ++ ++ @Override ++ public boolean contains(Object o) { ++ return o instanceof ProfileProperty && profile.getProperties().containsKey(((ProfileProperty) o).getName()); ++ } ++ ++ private class ProfilePropertyIterator implements Iterator { ++ private final Iterator iterator; ++ ++ ProfilePropertyIterator(Iterator iterator) { ++ this.iterator = iterator; ++ } ++ ++ @Override ++ public boolean hasNext() { ++ return iterator.hasNext(); ++ } ++ ++ @Override ++ public ProfileProperty next() { ++ return toBukkit(iterator.next()); ++ } ++ ++ @Override ++ public void remove() { ++ iterator.remove(); ++ } ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d64d45eb01c65864fca1077982d89bc05e0f811b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java +@@ -0,0 +1,31 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.mojang.authlib.*; ++import com.mojang.authlib.minecraft.MinecraftSessionService; ++import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; ++import com.mojang.authlib.yggdrasil.YggdrasilEnvironment; ++ ++import java.net.Proxy; ++ ++public class PaperAuthenticationService extends YggdrasilAuthenticationService { ++ private final Environment environment; ++ public PaperAuthenticationService(Proxy proxy) { ++ super(proxy); ++ this.environment = (Environment)EnvironmentParser.getEnvironmentFromProperties().orElse(YggdrasilEnvironment.PROD);; ++ } ++ ++ @Override ++ public UserAuthentication createUserAuthentication(Agent agent) { ++ return new PaperUserAuthentication(this, agent); ++ } ++ ++ @Override ++ public MinecraftSessionService createMinecraftSessionService() { ++ return new PaperMinecraftSessionService(this, this.environment); ++ } ++ ++ @Override ++ public GameProfileRepository createProfileRepository() { ++ return new PaperGameProfileRepository(this, this.environment); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java +new file mode 100644 +index 0000000000000000000000000000000000000000..582c169c85ac66f1f9430f79042e4655f776c157 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java +@@ -0,0 +1,18 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.mojang.authlib.Agent; ++import com.mojang.authlib.Environment; ++import com.mojang.authlib.ProfileLookupCallback; ++import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; ++import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; ++ ++public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { ++ public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { ++ super(authenticationService, environment); ++ } ++ ++ @Override ++ public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { ++ super.findProfilesByNames(names, agent, callback); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java +new file mode 100644 +index 0000000000000000000000000000000000000000..93d73c27340645c7502acafdc0b2cfbc1a759dd8 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java +@@ -0,0 +1,30 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.mojang.authlib.Environment; ++import com.mojang.authlib.GameProfile; ++import com.mojang.authlib.minecraft.MinecraftProfileTexture; ++import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; ++import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; ++ ++import java.util.Map; ++ ++public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionService { ++ protected PaperMinecraftSessionService(YggdrasilAuthenticationService authenticationService, Environment environment) { ++ super(authenticationService, environment); ++ } ++ ++ @Override ++ public Map getTextures(GameProfile profile, boolean requireSecure) { ++ return super.getTextures(profile, requireSecure); ++ } ++ ++ @Override ++ public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { ++ return super.fillProfileProperties(profile, requireSecure); ++ } ++ ++ @Override ++ protected GameProfile fillGameProfile(GameProfile profile, boolean requireSecure) { ++ return super.fillGameProfile(profile, requireSecure); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3cdd06d3af7ff94f1fe1a11b9a9275e17c695a38 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java +@@ -0,0 +1,12 @@ ++package com.destroystokyo.paper.profile; ++ ++import com.mojang.authlib.Agent; ++import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; ++import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; ++import java.util.UUID; ++ ++public class PaperUserAuthentication extends YggdrasilUserAuthentication { ++ public PaperUserAuthentication(YggdrasilAuthenticationService authenticationService, Agent agent) { ++ super(authenticationService, UUID.randomUUID().toString(), agent); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 18b56b59fd6efd618e6ff6f9cf3a02f57588d244..cd7dc7d90efddb8a1bb50cd964b43d18cf9c83d1 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -1,6 +1,8 @@ + package net.minecraft.server; + + import com.destroystokyo.paper.block.TargetBlockInfo; ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; + import com.google.common.util.concurrent.ThreadFactoryBuilder; + import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; + import net.minecraft.core.BlockPosition; +@@ -11,6 +13,7 @@ import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.RayTrace; + import net.minecraft.world.level.World; + import org.apache.commons.lang.exception.ExceptionUtils; ++import com.mojang.authlib.GameProfile; + import org.bukkit.Location; + import org.bukkit.block.BlockFace; + import org.bukkit.craftbukkit.CraftWorld; +@@ -345,6 +348,10 @@ public final class MCUtil { + return run.get(); + } + ++ public static PlayerProfile toBukkit(GameProfile profile) { ++ return CraftPlayerProfile.asBukkitMirror(profile); ++ } ++ + /** + * Calculates distance between 2 entities + * @param e1 +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 89db31061fcc3420bc8e668533a4051cdbd12253..191a74bd9b894f9d64d0a55747cb17e07ceef597 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -132,7 +132,7 @@ public class Main { + } + + File file = (File) optionset.valueOf("universe"); // CraftBukkit +- YggdrasilAuthenticationService yggdrasilauthenticationservice = new YggdrasilAuthenticationService(Proxy.NO_PROXY); ++ YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper + MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); + GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); + UserCache usercache = new UserCache(gameprofilerepository, new File(file, MinecraftServer.b.getName())); +diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java +index b9f94f957dd5372c8b02d785204690e4ade36a98..692d95c94df85d752a3ddc66e1f2af765565b160 100644 +--- a/src/main/java/net/minecraft/server/players/UserCache.java ++++ b/src/main/java/net/minecraft/server/players/UserCache.java +@@ -45,7 +45,7 @@ public class UserCache { + + private static final Logger LOGGER = LogManager.getLogger(); + private static boolean b; +- private final Map c = Maps.newConcurrentMap(); ++ private final Map c = Maps.newConcurrentMap();private final Map nameCache = c; // Paper - OBFHELPER // Paper + private final Map d = Maps.newConcurrentMap(); + private final GameProfileRepository e; + private final Gson f = (new GsonBuilder()).create(); +@@ -110,6 +110,7 @@ public class UserCache { + return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper + } + ++ public void saveProfile(GameProfile gameprofile) { a(gameprofile); } // Paper - OBFHELPER + public synchronized void a(GameProfile gameprofile) { // Paper - synchronize + Calendar calendar = Calendar.getInstance(); + +@@ -159,6 +160,13 @@ public class UserCache { + return gameprofile; + } + ++ // Paper start ++ @Nullable public GameProfile getProfileIfCached(String name) { ++ UserCache.UserCacheEntry entry = this.nameCache.get(name.toLowerCase(Locale.ROOT)); ++ return entry == null ? null : entry.getProfile(); ++ } ++ // Paper end ++ + @Nullable + public GameProfile getProfile(UUID uuid) { + UserCache.UserCacheEntry usercache_usercacheentry = (UserCache.UserCacheEntry) this.d.get(uuid); +@@ -341,7 +349,7 @@ public class UserCache { + + static class UserCacheEntry { + +- private final GameProfile a; ++ private final GameProfile a;public GameProfile getProfile() { return a; } // Paper - OBFHELPER + private final Date b; + private volatile long c; + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 9e974159476e7a359f59c0cdf5aae1be4422d1c0..bda96a2f64ae27d53e5a5c6d36ffb5441fee112f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -224,6 +224,9 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; + + import net.md_5.bungee.api.chat.BaseComponent; // Spigot + ++import javax.annotation.Nullable; // Paper ++import javax.annotation.Nonnull; // Paper ++ + public final class CraftServer implements Server { + private final String serverName = "Paper"; // Paper + private final String serverVersion; +@@ -2316,5 +2319,24 @@ public final class CraftServer implements Server { + public boolean suggestPlayerNamesWhenNullTabCompletions() { + return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; + } ++ ++ @Override ++ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { ++ return createProfile(uuid, null); ++ } ++ ++ @Override ++ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull String name) { ++ return createProfile(null, name); ++ } ++ ++ @Override ++ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { ++ Player player = uuid != null ? Bukkit.getPlayer(uuid) : (name != null ? Bukkit.getPlayerExact(name) : null); ++ if (player != null) { ++ return new com.destroystokyo.paper.profile.CraftPlayerProfile((CraftPlayer)player); ++ } ++ return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +index dff67a48961399f3746f99b4f2363724bfe51c36..8298ae9bf1c5635f08552c15f004b3d0f6e9f19b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +@@ -80,6 +80,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + } + + private void setProfile(GameProfile profile) { ++ // Paper start ++ if (profile != null) { ++ com.destroystokyo.paper.profile.CraftPlayerProfile paperProfile = new com.destroystokyo.paper.profile.CraftPlayerProfile(profile); ++ paperProfile.completeFromCache(false, true); ++ profile = paperProfile.getGameProfile(); ++ } ++ // Paper end + this.profile = profile; + this.serializedProfile = (profile == null) ? null : GameProfileSerializer.serialize(new NBTTagCompound(), profile); + } diff --git a/patches/server-unmapped/0153-Shoulder-Entities-Release-API.patch b/patches/server-unmapped/0153-Shoulder-Entities-Release-API.patch new file mode 100644 index 0000000000..af2c2b7c23 --- /dev/null +++ b/patches/server-unmapped/0153-Shoulder-Entities-Release-API.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 17 Jun 2017 15:18:30 -0400 +Subject: [PATCH] Shoulder Entities Release API + + +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index ba26fc2405e17d582da971d03147fb1865e9b546..63e8062ae3f3407b92b72b5fccaa958c39282fb8 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -1880,20 +1880,44 @@ public abstract class EntityHuman extends EntityLiving { + + } + ++ // Paper start ++ public Entity releaseLeftShoulderEntity() { ++ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityLeft()); ++ if (entity != null) { ++ this.setShoulderEntityLeft(new NBTTagCompound()); ++ } ++ return entity; ++ } ++ ++ public Entity releaseRightShoulderEntity() { ++ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityRight()); ++ if (entity != null) { ++ this.setShoulderEntityRight(new NBTTagCompound()); ++ } ++ return entity; ++ } ++ // Paper - maintain old signature + private boolean spawnEntityFromShoulder(NBTTagCompound nbttagcompound) { // CraftBukkit void->boolean +- if (!this.world.isClientSide && !nbttagcompound.isEmpty()) { ++ return spawnEntityFromShoulder0(nbttagcompound) != null; ++ } ++ ++ // Paper - return entity ++ private Entity spawnEntityFromShoulder0(@Nullable NBTTagCompound nbttagcompound) { ++ if (!this.world.isClientSide && nbttagcompound != null && !nbttagcompound.isEmpty()) { + return EntityTypes.a(nbttagcompound, this.world).map((entity) -> { // CraftBukkit + if (entity instanceof EntityTameableAnimal) { + ((EntityTameableAnimal) entity).setOwnerUUID(this.uniqueID); + } + + entity.setPosition(this.locX(), this.locY() + 0.699999988079071D, this.locZ()); +- return ((WorldServer) this.world).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit +- }).orElse(true); // CraftBukkit ++ boolean addedToWorld = ((WorldServer) this.world).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit ++ return addedToWorld ? entity : null; ++ }).orElse(null); // CraftBukkit // Paper - false -> null + } + +- return true; // CraftBukkit ++ return null; // Paper - return null + } ++ // Paper end + + @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 24e856473a0050c0b097c179776350379d464d0c..893cea754ea1858d2b08ba377bbbc90e7c0efd6d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -495,6 +495,32 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + getHandle().getCooldownTracker().setCooldown(CraftMagicNumbers.getItem(material), ticks); + } + ++ // Paper start ++ @Override ++ public org.bukkit.entity.Entity releaseLeftShoulderEntity() { ++ if (!getHandle().getShoulderEntityLeft().isEmpty()) { ++ Entity entity = getHandle().releaseLeftShoulderEntity(); ++ if (entity != null) { ++ return entity.getBukkitEntity(); ++ } ++ } ++ ++ return null; ++ } ++ ++ @Override ++ public org.bukkit.entity.Entity releaseRightShoulderEntity() { ++ if (!getHandle().getShoulderEntityRight().isEmpty()) { ++ Entity entity = getHandle().releaseRightShoulderEntity(); ++ if (entity != null) { ++ return entity.getBukkitEntity(); ++ } ++ } ++ ++ return null; ++ } ++ // Paper end ++ + @Override + public boolean discoverRecipe(NamespacedKey recipe) { + return discoverRecipes(Arrays.asList(recipe)) != 0; diff --git a/patches/server-unmapped/0154-Profile-Lookup-Events.patch b/patches/server-unmapped/0154-Profile-Lookup-Events.patch new file mode 100644 index 0000000000..a9a4210f19 --- /dev/null +++ b/patches/server-unmapped/0154-Profile-Lookup-Events.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 17 Jun 2017 17:00:32 -0400 +Subject: [PATCH] Profile Lookup Events + +Adds a Pre Lookup Event and a Post Lookup Event so that plugins may prefill in profile data, and cache the responses from +profiles that had to be looked up. + +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java +index 582c169c85ac66f1f9430f79042e4655f776c157..08fdb681a68e8be6e4062af0630957ce3e524806 100644 +--- a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java +@@ -1,11 +1,16 @@ + package com.destroystokyo.paper.profile; + ++import com.destroystokyo.paper.event.profile.LookupProfileEvent; ++import com.destroystokyo.paper.event.profile.PreLookupProfileEvent; ++import com.google.common.collect.Sets; + import com.mojang.authlib.Agent; + import com.mojang.authlib.Environment; ++import com.mojang.authlib.GameProfile; + import com.mojang.authlib.ProfileLookupCallback; + import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; + import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; + ++import java.util.Set; + public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { + public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { + super(authenticationService, environment); +@@ -13,6 +18,50 @@ public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { + + @Override + public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { +- super.findProfilesByNames(names, agent, callback); ++ Set unfoundNames = Sets.newHashSet(); ++ for (String name : names) { ++ PreLookupProfileEvent event = new PreLookupProfileEvent(name); ++ event.callEvent(); ++ if (event.getUUID() != null) { ++ // Plugin provided UUI, we can skip network call. ++ GameProfile gameprofile = new GameProfile(event.getUUID(), name); ++ // We might even have properties! ++ Set profileProperties = event.getProfileProperties(); ++ if (!profileProperties.isEmpty()) { ++ for (ProfileProperty property : profileProperties) { ++ gameprofile.getProperties().put(property.getName(), CraftPlayerProfile.asAuthlib(property)); ++ } ++ } ++ callback.onProfileLookupSucceeded(gameprofile); ++ } else { ++ unfoundNames.add(name); ++ } ++ } ++ ++ // Some things were not found.... Proceed to look up. ++ if (!unfoundNames.isEmpty()) { ++ String[] namesArr = unfoundNames.toArray(new String[unfoundNames.size()]); ++ super.findProfilesByNames(namesArr, agent, new PreProfileLookupCallback(callback)); ++ } ++ } ++ ++ private static class PreProfileLookupCallback implements ProfileLookupCallback { ++ private final ProfileLookupCallback callback; ++ ++ PreProfileLookupCallback(ProfileLookupCallback callback) { ++ this.callback = callback; ++ } ++ ++ @Override ++ public void onProfileLookupSucceeded(GameProfile gameProfile) { ++ PlayerProfile from = CraftPlayerProfile.asBukkitMirror(gameProfile); ++ new LookupProfileEvent(from).callEvent(); ++ callback.onProfileLookupSucceeded(gameProfile); ++ } ++ ++ @Override ++ public void onProfileLookupFailed(GameProfile gameProfile, Exception e) { ++ callback.onProfileLookupFailed(gameProfile, e); ++ } + } + } diff --git a/patches/server-unmapped/0155-Block-player-logins-during-server-shutdown.patch b/patches/server-unmapped/0155-Block-player-logins-during-server-shutdown.patch new file mode 100644 index 0000000000..389a5de905 --- /dev/null +++ b/patches/server-unmapped/0155-Block-player-logins-during-server-shutdown.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 2 Jul 2017 21:35:56 -0500 +Subject: [PATCH] Block player logins during server shutdown + + +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index c45647f2d05ed6b170aad10c0a3fb94570d2dd90..401833b7aeb9955fad2a3f1fe51d195cf0131094 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -68,6 +68,12 @@ public class LoginListener implements PacketLoginInListener { + } + + public void tick() { ++ // Paper start - Do not allow logins while the server is shutting down ++ if (!MinecraftServer.getServer().isRunning()) { ++ this.disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(org.spigotmc.SpigotConfig.restartMessage)[0]); ++ return; ++ } ++ // Paper end + if (this.g == LoginListener.EnumProtocolState.READY_TO_ACCEPT) { + this.c(); + } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { diff --git a/patches/server-unmapped/0156-Entity-fromMobSpawner.patch b/patches/server-unmapped/0156-Entity-fromMobSpawner.patch new file mode 100644 index 0000000000..92e16b769b --- /dev/null +++ b/patches/server-unmapped/0156-Entity-fromMobSpawner.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 18 Jun 2017 18:17:05 -0500 +Subject: [PATCH] Entity#fromMobSpawner() + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index dcaf5c107bb77b63333f924a33961f9e5cad7082..43039c14e087259e3ce4b5091b887759b66fe52d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -268,6 +268,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; + public long activatedTick = Integer.MIN_VALUE; ++ public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one + protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end +@@ -1666,6 +1667,10 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + nbttagcompound.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); + nbttagcompound.set("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); + } ++ // Save entity's from mob spawner status ++ if (spawnedViaMobSpawner) { ++ nbttagcompound.setBoolean("Paper.FromMobSpawner", true); ++ } + // Paper end + return nbttagcompound; + } catch (Throwable throwable) { +@@ -1798,6 +1803,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); + } ++ ++ spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status + // Paper end + + } catch (Throwable throwable) { +diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +index 76c98d576d3e567ec4482b30219f5a9107cb9703..43fcc001bb9815b352cb74af10290b2a4ccaa540 100644 +--- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java ++++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +@@ -160,6 +160,7 @@ public abstract class MobSpawnerAbstract { + } + // Spigot End + } ++ entity.spawnedViaMobSpawner = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { + Entity vehicle = entity.getVehicle(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index a58626b1a0160983a738a45c8a1d411eb347e6a2..4c2a35fb33da19a15a220dc5e0c9fa3233d657fb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1100,5 +1100,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + Location origin = getHandle().origin; + return origin == null ? null : origin.clone(); + } ++ ++ @Override ++ public boolean fromMobSpawner() { ++ return getHandle().spawnedViaMobSpawner; ++ } + // Paper end + } diff --git a/patches/server-unmapped/0157-Improve-the-Saddle-API-for-Horses.patch b/patches/server-unmapped/0157-Improve-the-Saddle-API-for-Horses.patch new file mode 100644 index 0000000000..5587fd6b92 --- /dev/null +++ b/patches/server-unmapped/0157-Improve-the-Saddle-API-for-Horses.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 10 Dec 2016 16:24:06 -0500 +Subject: [PATCH] Improve the Saddle API for Horses + +Not all horses with Saddles have armor. This lets us break up the horses with saddles +and access their saddle state separately from an interface shared with Armor. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +index 00b97d9ee7a3dd622c87e8efa288795d34db8fc7..62ccef35e4b4238c50faf778fbf3ea9a494ca387 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +@@ -6,6 +6,7 @@ import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; + import org.apache.commons.lang.Validate; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.inventory.CraftInventoryAbstractHorse; ++import org.bukkit.craftbukkit.inventory.CraftSaddledInventory; + import org.bukkit.entity.AbstractHorse; + import org.bukkit.entity.AnimalTamer; + import org.bukkit.entity.Horse; +@@ -99,6 +100,6 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac + + @Override + public AbstractHorseInventory getInventory() { +- return new CraftInventoryAbstractHorse(getHandle().inventoryChest); ++ return new CraftSaddledInventory(getHandle().inventoryChest); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java +index c3599b29c0b32d6fcf18a4a0adfbe8454c37834d..0389d15f8e0b6bb68316eaed0cf91acab8951cc7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java +@@ -4,7 +4,7 @@ import net.minecraft.world.IInventory; + import org.bukkit.inventory.HorseInventory; + import org.bukkit.inventory.ItemStack; + +-public class CraftInventoryHorse extends CraftInventoryAbstractHorse implements HorseInventory { ++public class CraftInventoryHorse extends CraftSaddledInventory implements HorseInventory { + + public CraftInventoryHorse(IInventory inventory) { + super(inventory); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8c2674ca1be1346ea84bcd7c9c5d6ea540802a5f +--- /dev/null ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java +@@ -0,0 +1,12 @@ ++package org.bukkit.craftbukkit.inventory; ++ ++import net.minecraft.world.IInventory; ++import org.bukkit.inventory.SaddledHorseInventory; ++ ++public class CraftSaddledInventory extends CraftInventoryAbstractHorse implements SaddledHorseInventory { ++ ++ public CraftSaddledInventory(IInventory inventory) { ++ super(inventory); ++ } ++ ++} diff --git a/patches/server-unmapped/0158-Implement-ensureServerConversions-API.patch b/patches/server-unmapped/0158-Implement-ensureServerConversions-API.patch new file mode 100644 index 0000000000..f7c4a06144 --- /dev/null +++ b/patches/server-unmapped/0158-Implement-ensureServerConversions-API.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 May 2016 22:43:12 -0400 +Subject: [PATCH] Implement ensureServerConversions API + +This will take a Bukkit ItemStack and run it through any conversions a server process would perform on it, +to ensure it meets latest minecraft expectations. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index ccd27aa93b4ab1dc09a8d684b43b5ecb69100ed8..8206e85cefb0b02b1ac9b370808c06019211cdb1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -346,5 +346,11 @@ public final class CraftItemFactory implements ItemFactory { + public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { + return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); + } ++ ++ // Paper start ++ @Override ++ public ItemStack ensureServerConversions(ItemStack item) { ++ return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0159-Implement-getI18NDisplayName.patch b/patches/server-unmapped/0159-Implement-getI18NDisplayName.patch new file mode 100644 index 0000000000..17848eb001 --- /dev/null +++ b/patches/server-unmapped/0159-Implement-getI18NDisplayName.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 May 2016 23:59:38 -0400 +Subject: [PATCH] Implement getI18NDisplayName + +Gets the Display name as seen in the Client. +Currently the server only supports the English language. To override this, +You must replace the language file embedded in the server jar. + +diff --git a/src/main/java/net/minecraft/locale/LocaleLanguage.java b/src/main/java/net/minecraft/locale/LocaleLanguage.java +index 9b8d5e7e4c86a699e26b1b4d0b82e88887a44054..5218214225b50ac4059ab704086a457318e93e00 100644 +--- a/src/main/java/net/minecraft/locale/LocaleLanguage.java ++++ b/src/main/java/net/minecraft/locale/LocaleLanguage.java +@@ -30,7 +30,7 @@ public abstract class LocaleLanguage { + + private static LocaleLanguage c() { + Builder builder = ImmutableMap.builder(); +- BiConsumer biconsumer = builder::put; ++ BiConsumer biconsumer = builder::put; // Paper - decompile fix + + try { + InputStream inputstream = LocaleLanguage.class.getResourceAsStream("/assets/minecraft/lang/en_us.json"); +@@ -87,10 +87,12 @@ public abstract class LocaleLanguage { + + } + ++ public static LocaleLanguage getInstance() { return a(); } // Paper - OBFHELPER + public static LocaleLanguage a() { + return LocaleLanguage.d; + } + ++ public String translateKey(String key) { return a(key); } // Paper - OBFHELPER + public abstract String a(String s); + + public abstract boolean b(String s); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index 8206e85cefb0b02b1ac9b370808c06019211cdb1..910c6109783dfef86e127a0a5b7d7d3865150d89 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -352,5 +352,18 @@ public final class CraftItemFactory implements ItemFactory { + public ItemStack ensureServerConversions(ItemStack item) { + return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); + } ++ ++ @Override ++ public String getI18NDisplayName(ItemStack item) { ++ net.minecraft.world.item.ItemStack nms = null; ++ if (item instanceof CraftItemStack) { ++ nms = ((CraftItemStack) item).handle; ++ } ++ if (nms == null) { ++ nms = CraftItemStack.asNMSCopy(item); ++ } ++ ++ return nms != null ? net.minecraft.locale.LocaleLanguage.getInstance().translateKey(nms.getItem().getName()) : null; ++ } + // Paper end + } diff --git a/patches/server-unmapped/0160-ProfileWhitelistVerifyEvent.patch b/patches/server-unmapped/0160-ProfileWhitelistVerifyEvent.patch new file mode 100644 index 0000000000..a0dfecf59f --- /dev/null +++ b/patches/server-unmapped/0160-ProfileWhitelistVerifyEvent.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 3 Jul 2017 18:11:10 -0500 +Subject: [PATCH] ProfileWhitelistVerifyEvent + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 8348dfa43c1f6e07c01024b40f4b3ebc05c10035..bd8bcc3891b29d31742bcfd6080a3972e4a9bee7 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -615,9 +615,9 @@ public abstract class PlayerList { + + // return chatmessage; + if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure +- } else if (!this.isWhitelisted(gameprofile)) { +- chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); +- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure ++ } else if (!this.isWhitelisted(gameprofile, event)) { // Paper ++ //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper ++ //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted + } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { + IpBanEntry ipbanentry = this.l.get(socketaddress); + +@@ -1009,9 +1009,25 @@ public abstract class PlayerList { + this.server.getCommandDispatcher().a(entityplayer); + } + ++ // Paper start + public boolean isWhitelisted(GameProfile gameprofile) { +- return !this.hasWhitelist || this.operators.d(gameprofile) || this.whitelist.d(gameprofile); ++ return isWhitelisted(gameprofile, null); + } ++ public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { ++ boolean isOp = this.operators.d(gameprofile); ++ boolean isWhitelisted = !this.hasWhitelist || isOp || this.whitelist.d(gameprofile); ++ final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; ++ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.hasWhitelist, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); ++ event.callEvent(); ++ if (!event.isWhitelisted()) { ++ if (loginEvent != null) { ++ loginEvent.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getKickMessage() == null ? org.spigotmc.SpigotConfig.whitelistMessage : event.getKickMessage())); ++ } ++ return false; ++ } ++ return true; ++ } ++ // Paper end + + public boolean isOp(GameProfile gameprofile) { + return this.operators.d(gameprofile) || this.server.a(gameprofile) && this.server.getSaveData().o() || this.v; diff --git a/patches/server-unmapped/0161-Fix-this-stupid-bullshit.patch b/patches/server-unmapped/0161-Fix-this-stupid-bullshit.patch new file mode 100644 index 0000000000..8eacc81f8c --- /dev/null +++ b/patches/server-unmapped/0161-Fix-this-stupid-bullshit.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DemonWav +Date: Sun, 6 Aug 2017 17:17:53 -0500 +Subject: [PATCH] Fix this stupid bullshit + +Disable the 15 second sleep when the server jar hasn't been rebuilt within a period of time. + +modified in order to prevent merge conflicts when Spigot changes/disables the warning, +and to provide some level of hint without being disruptive. + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 60d9980ccca6f1ac55b70f7684b917ddceac380a..808a7688ed81bdfef623ee0a151ff8f94df2a3d7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -224,10 +224,12 @@ public class Main { + Calendar deadline = Calendar.getInstance(); + deadline.add(Calendar.DAY_OF_YEAR, -28); + if (buildDate.before(deadline.getTime())) { +- System.err.println("*** Error, this build is outdated ***"); ++ // Paper start - This is some stupid bullshit ++ System.err.println("*** Warning, you've not updated in a while! ***"); + System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper +- System.err.println("*** Server will start in 20 seconds ***"); +- Thread.sleep(TimeUnit.SECONDS.toMillis(20)); ++ //System.err.println("*** Server will start in 20 seconds ***"); ++ //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); ++ // Paper End + } + } + diff --git a/patches/server-unmapped/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch b/patches/server-unmapped/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch new file mode 100644 index 0000000000..e460482610 --- /dev/null +++ b/patches/server-unmapped/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 31 Jul 2017 01:54:40 -0500 +Subject: [PATCH] Ocelot despawns should honor nametags and leash + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java +index b0296cef410aa5af42dcf89217dd8853f3800663..f3e9c73f28584bcccd6f82d8974eabe4b4a892fa 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java +@@ -128,7 +128,7 @@ public class EntityOcelot extends EntityAnimal { + + @Override + public boolean isTypeNotPersistent(double d0) { +- return !this.isTrusting() /*&& this.ticksLived > 2400*/; // CraftBukkit ++ return !this.isTrusting() && !this.hasCustomName() && !this.isLeashed() /*&& this.ticksLived > 2400*/; // CraftBukkit // Paper - honor name and leash + } + + public static AttributeProvider.Builder eK() { diff --git a/patches/server-unmapped/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/patches/server-unmapped/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch new file mode 100644 index 0000000000..442ca85737 --- /dev/null +++ b/patches/server-unmapped/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 31 Jul 2017 01:45:19 -0500 +Subject: [PATCH] Reset spawner timer when spawner event is cancelled + + +diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +index 43fcc001bb9815b352cb74af10290b2a4ccaa540..883c724fbb86a84ee903b5e7127f14726fe4cf24 100644 +--- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java ++++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +@@ -161,6 +161,7 @@ public abstract class MobSpawnerAbstract { + // Spigot End + } + entity.spawnedViaMobSpawner = true; // Paper ++ flag = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { + Entity vehicle = entity.getVehicle(); +@@ -184,7 +185,7 @@ public abstract class MobSpawnerAbstract { + ((EntityInsentient) entity).doSpawnEffect(); + } + +- flag = true; ++ /*flag = true;*/ // Paper - moved up above cancellable event + } + } + } diff --git a/patches/server-unmapped/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/patches/server-unmapped/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch new file mode 100644 index 0000000000..3dbcb05b98 --- /dev/null +++ b/patches/server-unmapped/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: mezz +Date: Wed, 9 Aug 2017 17:51:22 -0500 +Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike + + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index bd08ff18d8d7dbe63ed33c1efb6099b58aa02caa..8d4a28f98bd9c8a2dd1262f0f640909a456897fa 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -726,7 +726,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + gameprofilerfiller.enter("blockEntities"); + timings.tileEntityTick.startTiming(); // Spigot + if (!this.tileEntityListUnload.isEmpty()) { +- this.tileEntityListTick.removeAll(this.tileEntityListUnload); ++ // Paper start - Use alternate implementation with faster contains ++ java.util.Set toRemove = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); ++ toRemove.addAll(tileEntityListUnload); ++ this.tileEntityListTick.removeAll(toRemove); ++ // Paper end + //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list + this.tileEntityListUnload.clear(); + } diff --git a/patches/server-unmapped/0165-Allow-specifying-a-custom-authentication-servers-dow.patch b/patches/server-unmapped/0165-Allow-specifying-a-custom-authentication-servers-dow.patch new file mode 100644 index 0000000000..1ac2a8b392 --- /dev/null +++ b/patches/server-unmapped/0165-Allow-specifying-a-custom-authentication-servers-dow.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Thu, 17 Aug 2017 16:08:20 -0700 +Subject: [PATCH] Allow specifying a custom "authentication servers down" kick + message + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 48319aaf1c525c6fb7bdee5c2f570a0d056d4eae..52954fc3bf932cfc9d5ce63e3d3cace351305790 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -1,5 +1,6 @@ + package com.destroystokyo.paper; + ++import com.google.common.base.Strings; + import com.google.common.base.Throwables; + + import java.io.File; +@@ -273,4 +274,9 @@ public class PaperConfig { + private static void suggestPlayersWhenNull() { + suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); + } ++ ++ public static String authenticationServersDownKickMessage = ""; // empty = use translatable message ++ private static void authenticationServersDownKickMessage() { ++ authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index 401833b7aeb9955fad2a3f1fe51d195cf0131094..9e175747e110e32be80498ed27a71d21e8c01c5e 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -277,6 +277,10 @@ public class LoginListener implements PacketLoginInListener { + LoginListener.this.i = LoginListener.this.a(gameprofile); + LoginListener.this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT; + } else { ++ // Paper start ++ if (com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage != null) { ++ LoginListener.this.disconnect(new ChatComponentText(com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage)); ++ } else // Paper end + LoginListener.this.disconnect(new ChatMessage("multiplayer.disconnect.authservers_down")); + LoginListener.LOGGER.error("Couldn't verify username because servers are unavailable"); + } diff --git a/patches/server-unmapped/0166-LivingEntity-setKiller.patch b/patches/server-unmapped/0166-LivingEntity-setKiller.patch new file mode 100644 index 0000000000..db8677912c --- /dev/null +++ b/patches/server-unmapped/0166-LivingEntity-setKiller.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 31 Jul 2017 01:49:48 -0500 +Subject: [PATCH] LivingEntity#setKiller + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 036577b0237e9c8a7ab22ede7477eefa1abecf96..752cd55d8eb9e2e26e7cbfb9ce18b4ba56538002 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -180,7 +180,7 @@ public abstract class EntityLiving extends Entity { + public float aE; + @Nullable + public EntityHuman killer; +- protected int lastDamageByPlayerTime; ++ public int lastDamageByPlayerTime; // Paper - protected -> public + protected boolean killed; + protected int ticksFarFromPlayer; + protected float aJ; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index c654026587bc9bf77b39f59a0c89991ac581da1e..c43c300963bae9bca6ab9c9389dd53e42318715c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -8,6 +8,7 @@ import java.util.Iterator; + import java.util.List; + import java.util.Set; + import java.util.UUID; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.world.EnumHand; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffect; +@@ -344,6 +345,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return getHandle().killer == null ? null : (Player) getHandle().killer.getBukkitEntity(); + } + ++ // Paper start ++ @Override ++ public void setKiller(Player killer) { ++ EntityPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle(); ++ getHandle().killer = entityPlayer; ++ getHandle().lastDamager = entityPlayer; ++ getHandle().lastDamageByPlayerTime = entityPlayer == null ? 0 : 100; // 100 value taken from EntityLiving#damageEntity ++ } ++ // Paper end ++ + @Override + public boolean addPotionEffect(PotionEffect effect) { + return addPotionEffect(effect, false); diff --git a/patches/server-unmapped/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch b/patches/server-unmapped/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch new file mode 100644 index 0000000000..25a1431c58 --- /dev/null +++ b/patches/server-unmapped/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Thu, 21 Sep 2017 16:14:55 +0200 +Subject: [PATCH] Handle plugin prefixes using Log4J configuration + +Display logger name in the console for all loggers except the +root logger, Bukkit's logger ("Minecraft") and Minecraft loggers. +Since plugins now use the plugin name as logger name this will +restore the plugin prefixes without having to prepend them manually +to the log messages. + +Logger prefixes are shown by default for all loggers except for +the root logger, the Minecraft/Mojang loggers and the Bukkit loggers. +This may cause additional prefixes to be disabled for plugins bypassing +the plugin logger. + +diff --git a/pom.xml b/pom.xml +index 3841fe3630c090f8a468333d43caeb2b5841329d..f5429f2f1979542fd93956d2f436d20d0e3a66b8 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -76,7 +76,7 @@ + + org.apache.logging.log4j + log4j-core +- runtime ++ compile + + + org.apache.logging.log4j +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 3c93a497a790b8d800852db2ac48feca41f45cef..e8e5e5b568ba53dd006f1461cb4f027ceeae5528 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -290,7 +290,7 @@ public class SpigotConfig + private static void playerSample() + { + playerSample = getInt( "settings.sample-count", 12 ); +- System.out.println( "Server Ping Player Sample Count: " + playerSample ); ++ Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger + } + + public static int playerShuffle; +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 620b9490e5f159080e50289d127404a1b56adbef..a8bdaaeaa1a9316848416f0533739b9b083ca151 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -5,10 +5,22 @@ + + + +- ++ ++ ++ ++ ++ ++ + + +- ++ ++ ++ ++ ++ ++ + + + diff --git a/patches/server-unmapped/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch b/patches/server-unmapped/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch new file mode 100644 index 0000000000..5afb9562c0 --- /dev/null +++ b/patches/server-unmapped/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Sat, 23 Sep 2017 21:07:20 +0200 +Subject: [PATCH] Improve Log4J Configuration / Plugin Loggers + +Add full exceptions to log4j to not truncate stack traces + +Disable logger prefix for various plugins bypassing the plugin logger + +Some plugins bypass the plugin logger and add the plugin prefix +manually to the log message. Since they use other logger names +(e.g. qualified class names) these would now also appear in the +log. Disable the logger prefix for these plugins so the messages +show up correctly. + +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index a8bdaaeaa1a9316848416f0533739b9b083ca151..476f4a5cbe664ddd05474cb88553018bd334a5b8 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -6,19 +6,21 @@ + + + +- ++ + +- ++ ++ + + + + + +- ++ + +- ++ ++ + + + diff --git a/patches/server-unmapped/0169-Add-PlayerJumpEvent.patch b/patches/server-unmapped/0169-Add-PlayerJumpEvent.patch new file mode 100644 index 0000000000..edf45162bd --- /dev/null +++ b/patches/server-unmapped/0169-Add-PlayerJumpEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 28 Sep 2017 17:21:44 -0400 +Subject: [PATCH] Add PlayerJumpEvent + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 8c39dc4f05becea92f3ec86c4103be4e34f2b835..156acc9e1f3bb9d7663009530220a3958a1ff94d 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1168,7 +1168,34 @@ public class PlayerConnection implements PacketListenerPlayIn { + boolean flag = d8 > 0.0D; + + if (this.player.isOnGround() && !packetplayinflying.b() && flag) { +- this.player.jump(); ++ // Paper start - Add player jump event ++ Player player = this.getPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ if (packetplayinflying.hasPos) { ++ to.setX(packetplayinflying.x); ++ to.setY(packetplayinflying.y); ++ to.setZ(packetplayinflying.z); ++ } ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ if (packetplayinflying.hasLook) { ++ to.setYaw(packetplayinflying.yaw); ++ to.setPitch(packetplayinflying.pitch); ++ } ++ ++ com.destroystokyo.paper.event.player.PlayerJumpEvent event = new com.destroystokyo.paper.event.player.PlayerJumpEvent(player, from, to); ++ ++ if (event.callEvent()) { ++ this.player.jump(); ++ } else { ++ from = event.getFrom(); ++ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet()); ++ return; ++ } ++ // Paper end + } + + this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9)); diff --git a/patches/server-unmapped/0170-handle-PacketPlayInKeepAlive-async.patch b/patches/server-unmapped/0170-handle-PacketPlayInKeepAlive-async.patch new file mode 100644 index 0000000000..236692cc75 --- /dev/null +++ b/patches/server-unmapped/0170-handle-PacketPlayInKeepAlive-async.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 5 Oct 2017 01:54:07 +0100 +Subject: [PATCH] handle PacketPlayInKeepAlive async + +In 1.12.2, Mojang moved the processing of PacketPlayInKeepAlive off the main +thread, while entirely correct for the server, this causes issues with +plugins which are expecting the PlayerQuitEvent on the main thread. + +In order to counteract some bad behavior, we will post handling of the +disconnection to the main thread, but leave the actual processing of the packet +off the main thread. + +also adding some additional logging in order to help work out what is causing +random disconnections for clients. + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 156acc9e1f3bb9d7663009530220a3958a1ff94d..f0e4737377ae99afca5b624a1367d95c42ab4fa0 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2779,14 +2779,18 @@ public class PlayerConnection implements PacketListenerPlayIn { + + @Override + public void a(PacketPlayInKeepAlive packetplayinkeepalive) { +- PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit ++ //PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit // Paper - This shouldn't be on the main thread + if (this.awaitingKeepAlive && packetplayinkeepalive.b() == this.h) { + int i = (int) (SystemUtils.getMonotonicMillis() - this.lastKeepAlive); + + this.player.ping = (this.player.ping * 3 + i) / 4; + this.awaitingKeepAlive = false; + } else if (!this.isExemptPlayer()) { ++ // Paper start - This needs to be handled on the main thread for plugins ++ minecraftServer.scheduleOnMain(() -> { + this.disconnect(new ChatMessage("disconnect.timeout")); ++ }); ++ // Paper end + } + + } diff --git a/patches/server-unmapped/0171-Expose-client-protocol-version-and-virtual-host.patch b/patches/server-unmapped/0171-Expose-client-protocol-version-and-virtual-host.patch new file mode 100644 index 0000000000..370d5ecde6 --- /dev/null +++ b/patches/server-unmapped/0171-Expose-client-protocol-version-and-virtual-host.patch @@ -0,0 +1,129 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Tue, 10 Oct 2017 18:45:20 +0200 +Subject: [PATCH] Expose client protocol version and virtual host + + +diff --git a/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8a716c1647aa29906be26ac262e93ebd2c1adfaa +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java +@@ -0,0 +1,50 @@ ++package com.destroystokyo.paper.network; ++ ++import net.minecraft.network.NetworkManager; ++ ++import java.net.InetSocketAddress; ++ ++import javax.annotation.Nullable; ++ ++public class PaperNetworkClient implements NetworkClient { ++ ++ private final NetworkManager networkManager; ++ ++ PaperNetworkClient(NetworkManager networkManager) { ++ this.networkManager = networkManager; ++ } ++ ++ @Override ++ public InetSocketAddress getAddress() { ++ return (InetSocketAddress) this.networkManager.getSocketAddress(); ++ } ++ ++ @Override ++ public int getProtocolVersion() { ++ return this.networkManager.protocolVersion; ++ } ++ ++ @Nullable ++ @Override ++ public InetSocketAddress getVirtualHost() { ++ return this.networkManager.virtualHost; ++ } ++ ++ public static InetSocketAddress prepareVirtualHost(String host, int port) { ++ int len = host.length(); ++ ++ // FML appends a marker to the host to recognize FML clients (\0FML\0) ++ int pos = host.indexOf('\0'); ++ if (pos >= 0) { ++ len = pos; ++ } ++ ++ // When clients connect with a SRV record, their host contains a trailing '.' ++ if (len > 0 && host.charAt(len - 1) == '.') { ++ len--; ++ } ++ ++ return InetSocketAddress.createUnresolved(host.substring(0, len), port); ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +index f093b465b868e6003bb2b5ee634a624b5b054493..60e4a4aa3854aaeb250d1318f2f25cf3591ea1d3 100644 +--- a/src/main/java/net/minecraft/network/NetworkManager.java ++++ b/src/main/java/net/minecraft/network/NetworkManager.java +@@ -70,6 +70,10 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + private float s; + private int t; + private boolean u; ++ // Paper start - NetworkClient implementation ++ public int protocolVersion; ++ public java.net.InetSocketAddress virtualHost; ++ // Paper end + + public NetworkManager(EnumProtocolDirection enumprotocoldirection) { + this.h = enumprotocoldirection; +diff --git a/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java b/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java +index b290ddfbc19aed3e44169281c3dae5429dac0062..14c002376540d2039fc2fe2ef746e53471a9cb08 100644 +--- a/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java ++++ b/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java +@@ -39,6 +39,7 @@ public class PacketHandshakingInSetProtocol implements Packet +Date: Sun, 15 Oct 2017 00:29:07 +0100 +Subject: [PATCH] revert serverside behavior of keepalives + +This patch intends to bump up the time that a client has to reply to the +server back to 30 seconds as per pre 1.12.2, which allowed clients +more than enough time to reply potentially allowing them to be less +tempermental due to lag spikes on the network thread, e.g. that caused +by plugins that are interacting with netty. + +We also add a system property to allow people to tweak how long the server +will wait for a reply. There is a compromise here between lower and higher +values, lower values will mean that dead connections can be closed sooner, +whereas higher values will make this less sensitive to issues such as spikes +from networking or during connections flood of chunk packets on slower clients, + at the cost of dead connections being kept open for longer. + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index f0e4737377ae99afca5b624a1367d95c42ab4fa0..301b63db3abc348441c3580a6606b65f550d8a78 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -223,7 +223,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + private final MinecraftServer minecraftServer; + public EntityPlayer player; + private int e; +- private long lastKeepAlive; private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER ++ private long lastKeepAlive = SystemUtils.getMonotonicMillis(); private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER + private boolean awaitingKeepAlive; private void setPendingPing(boolean isPending) { this.awaitingKeepAlive = isPending;}; private boolean isPendingPing() { return this.awaitingKeepAlive;}; // Paper - OBFHELPER + private long h; private void setKeepAliveID(long keepAliveID) { this.h = keepAliveID;}; private long getKeepAliveID() {return this.h; }; // Paper - OBFHELPER + // CraftBukkit start - multithreaded fields +@@ -254,6 +254,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + private int E; + private int receivedMovePackets; + private int processedMovePackets; ++ private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit + + public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { + this.minecraftServer = minecraftserver; +@@ -340,18 +341,25 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + + this.minecraftServer.getMethodProfiler().enter("keepAlive"); +- long i = SystemUtils.getMonotonicMillis(); +- +- if (i - this.lastKeepAlive >= 25000L) { // CraftBukkit +- if (this.awaitingKeepAlive) { +- this.disconnect(new ChatMessage("disconnect.timeout")); +- } else { +- this.awaitingKeepAlive = true; +- this.lastKeepAlive = i; +- this.h = i; +- this.sendPacket(new PacketPlayOutKeepAlive(this.h)); ++ // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings ++ // This should effectively place the keepalive handling back to "as it was" before 1.12.2 ++ long currentTime = SystemUtils.getMonotonicMillis(); ++ long elapsedTime = currentTime - this.getLastPing(); ++ ++ if (this.isPendingPing()) { ++ if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected ++ PlayerConnection.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getName()); // more info ++ this.disconnect(new ChatMessage("disconnect.timeout", new Object[0])); ++ } ++ } else { ++ if (elapsedTime >= 15000L) { // 15 seconds ++ this.setPendingPing(true); ++ this.setLastPing(currentTime); ++ this.setKeepAliveID(currentTime); ++ this.sendPacket(new PacketPlayOutKeepAlive(this.getKeepAliveID())); + } + } ++ // Paper end + + this.minecraftServer.getMethodProfiler().exit(); + // CraftBukkit start diff --git a/patches/server-unmapped/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch b/patches/server-unmapped/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch new file mode 100644 index 0000000000..5c3d2d05c3 --- /dev/null +++ b/patches/server-unmapped/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Tue, 31 Oct 2017 03:26:18 +0100 +Subject: [PATCH] Send attack SoundEffects only to players who can see the + attacker + + +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 63e8062ae3f3407b92b72b5fccaa958c39282fb8..f9d0623a3ed5f49758cd5e97fe9f63a5b3198e58 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -28,6 +28,7 @@ import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.network.chat.IChatMutableComponent; + import net.minecraft.network.protocol.game.PacketPlayOutEntityVelocity; ++import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; +@@ -1126,7 +1127,7 @@ public abstract class EntityHuman extends EntityLiving { + int i = b0 + EnchantmentManager.b((EntityLiving) this); + + if (this.isSprinting() && flag) { +- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_KNOCKBACK, this.getSoundCategory(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_KNOCKBACK, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility + ++i; + flag1 = true; + } +@@ -1201,7 +1202,7 @@ public abstract class EntityHuman extends EntityLiving { + } + } + +- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_SWEEP, this.getSoundCategory(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_SWEEP, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility + this.ex(); + } + +@@ -1229,15 +1230,15 @@ public abstract class EntityHuman extends EntityLiving { + } + + if (flag2) { +- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_CRIT, this.getSoundCategory(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_CRIT, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility + this.a(entity); + } + + if (!flag2 && !flag3) { + if (flag) { +- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_STRONG, this.getSoundCategory(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_STRONG, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility + } else { +- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_WEAK, this.getSoundCategory(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_WEAK, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility + } + } + +@@ -1289,7 +1290,7 @@ public abstract class EntityHuman extends EntityLiving { + + this.applyExhaustion(world.spigotConfig.combatExhaustion, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value + } else { +- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_NODAMAGE, this.getSoundCategory(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_NODAMAGE, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility + if (flag4) { + entity.extinguish(); + } +@@ -1724,6 +1725,14 @@ public abstract class EntityHuman extends EntityLiving { + public int getExpToLevel() { + return this.expLevel >= 30 ? 112 + (this.expLevel - 30) * 9 : (this.expLevel >= 15 ? 37 + (this.expLevel - 15) * 5 : 7 + this.expLevel * 2); + } ++ // Paper start - send SoundEffect to everyone who can see fromEntity ++ private static void sendSoundEffect(EntityHuman fromEntity, double x, double y, double z, SoundEffect soundEffect, SoundCategory soundCategory, float volume, float pitch) { ++ fromEntity.world.playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself ++ if (fromEntity instanceof EntityPlayer) { ++ ((EntityPlayer) fromEntity).playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(soundEffect, soundCategory, x, y, z, volume, pitch)); ++ } ++ } ++ // Paper end + + // CraftBukkit start + public void applyExhaustion(float f) { diff --git a/patches/server-unmapped/0174-Option-for-maximum-exp-value-when-merging-orbs.patch b/patches/server-unmapped/0174-Option-for-maximum-exp-value-when-merging-orbs.patch new file mode 100644 index 0000000000..3edec22afc --- /dev/null +++ b/patches/server-unmapped/0174-Option-for-maximum-exp-value-when-merging-orbs.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 10 Nov 2017 23:03:12 -0500 +Subject: [PATCH] Option for maximum exp value when merging orbs + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 90ca51dfdbb3045dd528450225cba96f5834166e..6c692e58cde22003ecbf6dc5695799147c39905a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -342,4 +342,10 @@ public class PaperWorldConfig { + disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); + log("Creeper lingering effect: " + disableCreeperLingeringEffect); + } ++ ++ public int expMergeMaxValue; ++ private void expMergeMaxValue() { ++ expMergeMaxValue = getInt("experience-merge-max-value", -1); ++ log("Experience Merge Max Value: " + expMergeMaxValue); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index d07c146119980358aeaf8f9dc5f419fd1385ced5..aa984540917e363438cc38cdb3004d3fc4987ab4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -599,16 +599,32 @@ public class CraftEventFactory { + EntityExperienceOrb xp = (EntityExperienceOrb) entity; + double radius = world.spigotConfig.expMerge; + if (radius > 0) { ++ // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics ++ final int maxValue = world.paperConfig.expMergeMaxValue; ++ final boolean mergeUnconditionally = world.paperConfig.expMergeMaxValue <= 0; ++ if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary ++ + List entities = world.getEntities(entity, entity.getBoundingBox().grow(radius, radius, radius)); + for (Entity e : entities) { + if (e instanceof EntityExperienceOrb) { + EntityExperienceOrb loopItem = (EntityExperienceOrb) e; +- if (!loopItem.dead) { +- xp.value += loopItem.value; +- loopItem.die(); ++ // Paper start ++ if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { ++ long newTotal = (long)xp.value + (long)loopItem.value; ++ if ((int) newTotal < 0) continue; // Overflow ++ if (maxValue > 0 && newTotal > (long)maxValue) { ++ loopItem.value = (int) (newTotal - maxValue); ++ xp.value = maxValue; ++ } else { ++ xp.value += loopItem.value; ++ loopItem.die(); ++ } ++ // Paper end + } + } + } ++ ++ } // Paper end - End iteration skip check - All tweaking ends here + } + // Spigot end + } else if (!(entity instanceof EntityPlayer)) { diff --git a/patches/server-unmapped/0175-Add-PlayerArmorChangeEvent.patch b/patches/server-unmapped/0175-Add-PlayerArmorChangeEvent.patch new file mode 100644 index 0000000000..2a23c19157 --- /dev/null +++ b/patches/server-unmapped/0175-Add-PlayerArmorChangeEvent.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: pkt77 +Date: Fri, 10 Nov 2017 23:46:34 -0500 +Subject: [PATCH] Add PlayerArmorChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 752cd55d8eb9e2e26e7cbfb9ce18b4ba56538002..91be4df855a0a249518f0b562d05d9647169aa92 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.entity; + ++import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; // Paper + import com.google.common.base.Objects; + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableMap; +@@ -2646,6 +2647,13 @@ public abstract class EntityLiving extends Entity { + ItemStack itemstack1 = this.getEquipment(enumitemslot); + + if (!ItemStack.matches(itemstack1, itemstack)) { ++ // Paper start - PlayerArmorChangeEvent ++ if (this instanceof EntityPlayer && enumitemslot.getType() == EnumItemSlot.Function.ARMOR) { ++ final org.bukkit.inventory.ItemStack oldItem = CraftItemStack.asBukkitCopy(itemstack); ++ final org.bukkit.inventory.ItemStack newItem = CraftItemStack.asBukkitCopy(itemstack1); ++ new PlayerArmorChangeEvent((Player) this.getBukkitEntity(), PlayerArmorChangeEvent.SlotType.valueOf(enumitemslot.name()), oldItem, newItem).callEvent(); ++ } ++ // Paper end + if (map == null) { + map = Maps.newEnumMap(EnumItemSlot.class); + } +diff --git a/src/main/java/net/minecraft/world/entity/EnumItemSlot.java b/src/main/java/net/minecraft/world/entity/EnumItemSlot.java +index 8e7673c6072c3f8ddcebd7a719304ea41d809a36..59ad7d8dc1c8ee00d142dc6063c3416ccdce4ff8 100644 +--- a/src/main/java/net/minecraft/world/entity/EnumItemSlot.java ++++ b/src/main/java/net/minecraft/world/entity/EnumItemSlot.java +@@ -16,6 +16,7 @@ public enum EnumItemSlot { + this.j = s; + } + ++ public EnumItemSlot.Function getType() { return this.a(); } // Paper - OBFHELPER + public EnumItemSlot.Function a() { + return this.g; + } diff --git a/patches/server-unmapped/0176-Prevent-logins-from-being-processed-when-the-player-.patch b/patches/server-unmapped/0176-Prevent-logins-from-being-processed-when-the-player-.patch new file mode 100644 index 0000000000..ad5a02fae5 --- /dev/null +++ b/patches/server-unmapped/0176-Prevent-logins-from-being-processed-when-the-player-.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: killme +Date: Sun, 12 Nov 2017 19:40:01 +0100 +Subject: [PATCH] Prevent logins from being processed when the player has + disconnected + + +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index 9e175747e110e32be80498ed27a71d21e8c01c5e..f95f5a8b30f42c8f5b6cee3ef6adb1f4e09832dc 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -75,7 +75,11 @@ public class LoginListener implements PacketLoginInListener { + } + // Paper end + if (this.g == LoginListener.EnumProtocolState.READY_TO_ACCEPT) { +- this.c(); ++ // Paper start - prevent logins to be processed even though disconnect was called ++ if (networkManager.isConnected()) { ++ this.c(); ++ } ++ // Paper end + } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { + EntityPlayer entityplayer = this.server.getPlayerList().getPlayer(this.i.getId()); + diff --git a/patches/server-unmapped/0177-use-CB-BlockState-implementations-for-captured-block.patch b/patches/server-unmapped/0177-use-CB-BlockState-implementations-for-captured-block.patch new file mode 100644 index 0000000000..4dc684be75 --- /dev/null +++ b/patches/server-unmapped/0177-use-CB-BlockState-implementations-for-captured-block.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 16 Nov 2017 12:12:41 +0000 +Subject: [PATCH] use CB BlockState implementations for captured blocks + +When modifying the world, CB will store a copy of the affected +blocks in order to restore their state in the case that the event +is cancelled. This change only modifies the collection of blocks +in the world by normal means, e.g. not during tree population, +as the potentially marginal overheads would serve no advantage. + +CB was using a CraftBlockState for all blocks, which causes issues +should any block that uses information beyond a data ID would suffer +from missing information, e.g. Skulls. + +By using CBs CraftBlock#getState(), we will maintain a proper copy of +the blockstate that will be valid for restoration, as opposed to dropping +information on restoration when the event is cancelled. + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 8d4a28f98bd9c8a2dd1262f0f640909a456897fa..a9e7da1c848a6fe08fc112e445ceec1b7715d682 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -124,7 +124,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + public boolean captureBlockStates = false; + public boolean captureTreeGeneration = false; +- public Map capturedBlockStates = new java.util.LinkedHashMap<>(); ++ public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper + public Map capturedTileEntities = new HashMap<>(); + public List captureDrops; + public long ticksPerAnimalSpawns; +@@ -346,7 +346,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) { + // CraftBukkit start - tree generation + if (this.captureTreeGeneration) { +- CapturedBlockState blockstate = capturedBlockStates.get(blockposition); ++ CraftBlockState blockstate = capturedBlockStates.get(blockposition); + if (blockstate == null) { + blockstate = CapturedBlockState.getTreeBlockState(this, blockposition, i); + this.capturedBlockStates.put(blockposition.immutableCopy(), blockstate); +@@ -366,7 +366,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + // CraftBukkit start - capture blockstates + boolean captured = false; + if (this.captureBlockStates && !this.capturedBlockStates.containsKey(blockposition)) { +- CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, blockposition, i); ++ CraftBlockState blockstate = (CraftBlockState) world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()).getState(); // Paper - use CB getState to get a suitable snapshot ++ blockstate.setFlag(i); // Paper - set flag + this.capturedBlockStates.put(blockposition.immutableCopy(), blockstate); + captured = true; + } +@@ -624,7 +625,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public IBlockData getType(BlockPosition blockposition) { + // CraftBukkit start - tree generation + if (captureTreeGeneration) { +- CapturedBlockState previous = capturedBlockStates.get(blockposition); ++ CraftBlockState previous = capturedBlockStates.get(blockposition); // Paper + if (previous != null) { + return previous.getHandle(); + } diff --git a/patches/server-unmapped/0178-API-to-get-a-BlockState-without-a-snapshot.patch b/patches/server-unmapped/0178-API-to-get-a-BlockState-without-a-snapshot.patch new file mode 100644 index 0000000000..5fe5db1a81 --- /dev/null +++ b/patches/server-unmapped/0178-API-to-get-a-BlockState-without-a-snapshot.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 6 Nov 2017 21:08:22 -0500 +Subject: [PATCH] API to get a BlockState without a snapshot + +This allows you to get a BlockState without creating a snapshot, operating +on the real tile entity. + +This is useful for where performance is needed + +also Avoid NPE during CraftBlockEntityState load if could not get TE + +If Tile Entity was null, correct Sign to return empty lines instead of null + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +index 9b44ca96669ce423e5649f11743226dfdd9ce746..48daa039ffa8ccb7b6f3ca47bdc56394addf9254 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +@@ -47,6 +47,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / + public TileEntity(TileEntityTypes tileentitytypes) { + this.position = BlockPosition.ZERO; + this.tileType = tileentitytypes; ++ persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init + } + + // Paper start +@@ -95,7 +96,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / + public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) { + this.position = new BlockPosition(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); + // CraftBukkit start - read container +- this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ this.persistentDataContainer.clear(); // Paper - clear instead of reinit + + net.minecraft.nbt.NBTBase persistentDataTag = nbttagcompound.get("PublicBukkitValues"); + if (persistentDataTag instanceof NBTTagCompound) { +@@ -245,7 +246,12 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / + } + + // CraftBukkit start - add method ++ // Paper start + public InventoryHolder getOwner() { ++ return getOwner(true); ++ } ++ public InventoryHolder getOwner(boolean useSnapshot) { ++ // Paper end + if (world == null) return null; + // Spigot start + org.bukkit.block.Block block = world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); +@@ -254,7 +260,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / + return null; + } + // Spigot end +- org.bukkit.block.BlockState state = block.getState(); ++ org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper + if (state instanceof InventoryHolder) return (InventoryHolder) state; + return null; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 255aac0803b436434bc00822f3698c4f3ba7e0ac..8a6d8f21937ce7e2ac4623a3083421ed5ef9aa63 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -316,6 +316,20 @@ public class CraftBlock implements Block { + + @Override + public BlockState getState() { ++ // Paper start - allow disabling the use of snapshots ++ return getState(true); ++ } ++ public BlockState getState(boolean useSnapshot) { ++ boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT; ++ CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot; ++ try { ++ return getState0(); ++ } finally { ++ CraftBlockEntityState.DISABLE_SNAPSHOT = prev; ++ } ++ } ++ public BlockState getState0() { ++ // Paper end + Material material = getType(); + + switch (material) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +index dcf3f9265b0b00a7bbb9ff428e10da3c198ba08a..2f0b48869077c27d0cacea81a99c9e34ff59c684 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +@@ -26,20 +26,40 @@ public class CraftBlockEntityState extends CraftBlockState + this.tileEntity = tileEntityClass.cast(world.getHandle().getTileEntity(this.getPosition())); + Preconditions.checkState(this.tileEntity != null, "Tile is null, asynchronous access? %s", block); + ++ // Paper start ++ this.snapshotDisabled = DISABLE_SNAPSHOT; ++ if (DISABLE_SNAPSHOT) { ++ this.snapshot = this.tileEntity; ++ } else { ++ this.snapshot = this.createSnapshot(this.tileEntity); ++ } + // copy tile entity data: +- this.snapshot = this.createSnapshot(tileEntity); +- this.load(snapshot); ++ if(this.snapshot != null) { ++ this.load(this.snapshot); ++ } ++ // Paper end + } + ++ public final boolean snapshotDisabled; // Paper ++ public static boolean DISABLE_SNAPSHOT = false; // Paper ++ + public CraftBlockEntityState(Material material, T tileEntity) { + super(material); + + this.tileEntityClass = (Class) tileEntity.getClass(); + this.tileEntity = tileEntity; +- ++ // Paper start ++ this.snapshotDisabled = DISABLE_SNAPSHOT; ++ if (DISABLE_SNAPSHOT) { ++ this.snapshot = this.tileEntity; ++ } else { ++ this.snapshot = this.createSnapshot(this.tileEntity); ++ } + // copy tile entity data: +- this.snapshot = this.createSnapshot(tileEntity); +- this.load(snapshot); ++ if(this.snapshot != null) { ++ this.load(this.snapshot); ++ } ++ // Paper end + } + + private T createSnapshot(T tileEntity) { +diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java +index f342feee4e2274cdc51fef6caace52cc31eefb18..a4c888236bf09a25f234831a041ca5a4a2c972ef 100644 +--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java ++++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java +@@ -155,4 +155,10 @@ public final class CraftPersistentDataContainer implements PersistentDataContain + public Map serialize() { + return (Map) CraftNBTTagConfigSerializer.serialize(toTagCompound()); + } ++ ++ // Paper start ++ public void clear() { ++ this.customDataTags.clear(); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0179-AsyncTabCompleteEvent.patch b/patches/server-unmapped/0179-AsyncTabCompleteEvent.patch new file mode 100644 index 0000000000..1eefab71c5 --- /dev/null +++ b/patches/server-unmapped/0179-AsyncTabCompleteEvent.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 26 Nov 2017 13:19:58 -0500 +Subject: [PATCH] AsyncTabCompleteEvent + +Let plugins be able to control tab completion of commands and chat async. + +This will be useful for frameworks like ACF so we can define async safe completion handlers, +and avoid going to main for tab completions. + +Especially useful if you need to query a database in order to obtain the results for tab +completion, such as offline players. + +Also adds isCommand and getLocation to the sync TabCompleteEvent + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 301b63db3abc348441c3580a6606b65f550d8a78..1860def3971d1e17429bdde51c2bc336887da233 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -713,10 +713,10 @@ public class PlayerConnection implements PacketListenerPlayIn { + + @Override + public void a(PacketPlayInTabComplete packetplayintabcomplete) { +- PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); ++ // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async + // CraftBukkit start + if (chatSpamField.addAndGet(this, 1) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { +- this.disconnect(new ChatMessage("disconnect.spam", new Object[0])); ++ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper + return; + } + // CraftBukkit end +@@ -726,12 +726,35 @@ public class PlayerConnection implements PacketListenerPlayIn { + stringreader.skip(); + } + +- ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); ++ // Paper start - async tab completion ++ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; ++ java.util.List completions = new java.util.ArrayList<>(); ++ String buffer = packetplayintabcomplete.c(); ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, ++ buffer, true, null); ++ event.callEvent(); ++ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); ++ // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server ++ if (!event.isHandled()) { ++ if (!event.isCancelled()) { + +- this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { +- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer +- this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); +- }); ++ this.minecraftServer.scheduleOnMain(() -> { // Paper - This needs to be on main ++ ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); ++ ++ this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { ++ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer ++ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); ++ }); ++ }); ++ } ++ } else if (!completions.isEmpty()) { ++ com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); ++ ++ builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); ++ completions.forEach(builder::suggest); ++ player.playerConnection.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), builder.buildFuture().join())); ++ } ++ // Paper end - async tab completion + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index bda96a2f64ae27d53e5a5c6d36ffb5441fee112f..3aed540b6359df9940a26901c55f0306743ad085 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1851,7 +1851,7 @@ public final class CraftServer implements Server { + offers = tabCompleteChat(player, message); + } + +- TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers); ++ TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? net.minecraft.server.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), new BlockPosition(pos)) : null); // Paper + getPluginManager().callEvent(tabEvent); + + return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index a957695457cf3252848ce6ef37069692841b8e28..c5e00bd9e2790992202aadf8eec2002fc88c78f1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -28,6 +28,39 @@ public class ConsoleCommandCompleter implements Completer { + public void complete(LineReader reader, ParsedLine line, List candidates) { + final CraftServer server = this.server.server; + final String buffer = line.line(); ++ // Async Tab Complete ++ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; ++ java.util.List completions = new java.util.ArrayList<>(); ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, ++ buffer, true, null); ++ event.callEvent(); ++ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); ++ ++ if (event.isCancelled() || event.isHandled()) { ++ // Still fire sync event with the provided completions, if someone is listening ++ if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { ++ List finalCompletions = completions; ++ Waitable> syncCompletions = new Waitable>() { ++ @Override ++ protected List evaluate() { ++ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); ++ return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); ++ } ++ }; ++ server.getServer().processQueue.add(syncCompletions); ++ try { ++ completions = syncCompletions.get(); ++ } catch (InterruptedException | ExecutionException e1) { ++ e1.printStackTrace(); ++ } ++ } ++ ++ if (!completions.isEmpty()) { ++ candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); ++ } ++ return; ++ } ++ + // Paper end + Waitable> waitable = new Waitable>() { + @Override diff --git a/patches/server-unmapped/0180-Avoid-NPE-in-PathfinderGoalTempt.patch b/patches/server-unmapped/0180-Avoid-NPE-in-PathfinderGoalTempt.patch new file mode 100644 index 0000000000..22279d4515 --- /dev/null +++ b/patches/server-unmapped/0180-Avoid-NPE-in-PathfinderGoalTempt.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 29 Nov 2017 22:18:54 -0500 +Subject: [PATCH] Avoid NPE in PathfinderGoalTempt + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java +index 54b345b5d2fc8d3c511533281f6d387f046f8000..9a120ab9c5c6c858bf3d1690196fe657e76cc1b7 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java +@@ -65,7 +65,7 @@ public class PathfinderGoalTempt extends PathfinderGoal { + } + this.target = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle(); + } +- return tempt; ++ return tempt && this.target != null; // Paper - must have target - plugin might of cancelled + // CraftBukkit end + } + } diff --git a/patches/server-unmapped/0181-PlayerPickupExperienceEvent.patch b/patches/server-unmapped/0181-PlayerPickupExperienceEvent.patch new file mode 100644 index 0000000000..994fed3ea2 --- /dev/null +++ b/patches/server-unmapped/0181-PlayerPickupExperienceEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 22:02:53 -0500 +Subject: [PATCH] PlayerPickupExperienceEvent + +Allows plugins to cancel a player picking up an experience orb + +diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java +index f4da22b33c704e675510b4b1a3aa7c180088be29..e3dfb018b06c0139594ddbb88fab2ca8d43ab12f 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java +@@ -5,6 +5,7 @@ import net.minecraft.core.BlockPosition; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityExperienceOrb; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsFluid; +@@ -232,7 +233,7 @@ public class EntityExperienceOrb extends Entity { + @Override + public void pickup(EntityHuman entityhuman) { + if (!this.world.isClientSide) { +- if (this.d == 0 && entityhuman.bu == 0) { ++ if (this.d == 0 && entityhuman.bu == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((EntityPlayer) entityhuman).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper + entityhuman.bu = 2; + entityhuman.receive(this, 1); + Entry entry = EnchantmentManager.a(Enchantments.MENDING, (EntityLiving) entityhuman, ItemStack::f); diff --git a/patches/server-unmapped/0182-ExperienceOrbMergeEvent.patch b/patches/server-unmapped/0182-ExperienceOrbMergeEvent.patch new file mode 100644 index 0000000000..41f53d153e --- /dev/null +++ b/patches/server-unmapped/0182-ExperienceOrbMergeEvent.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 22:57:26 -0500 +Subject: [PATCH] ExperienceOrbMergeEvent + +Fired when the server is about to merge 2 experience orbs +Plugins can cancel this if they want to ensure experience orbs do not lose important +metadata such as spawn reason, or conditionally move data from source to target. + +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index aa984540917e363438cc38cdb3004d3fc4987ab4..69b5c76b312d055603ce62ad7b0c88cd01272ba9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -609,7 +609,7 @@ public class CraftEventFactory { + if (e instanceof EntityExperienceOrb) { + EntityExperienceOrb loopItem = (EntityExperienceOrb) e; + // Paper start +- if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { ++ if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper + long newTotal = (long)xp.value + (long)loopItem.value; + if ((int) newTotal < 0) continue; // Overflow + if (maxValue > 0 && newTotal > (long)maxValue) { diff --git a/patches/server-unmapped/0183-Ability-to-apply-mending-to-XP-API.patch b/patches/server-unmapped/0183-Ability-to-apply-mending-to-XP-API.patch new file mode 100644 index 0000000000..d494effb54 --- /dev/null +++ b/patches/server-unmapped/0183-Ability-to-apply-mending-to-XP-API.patch @@ -0,0 +1,104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 20 Dec 2017 17:36:49 -0500 +Subject: [PATCH] Ability to apply mending to XP API + +This allows plugins that give players the ability to apply the experience +points to the Item Mending formula, which will repair an item instead +of giving the player experience points. + +Both an API To standalone mend, and apply mending logic to .giveExp has been added. + +diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java +index e3dfb018b06c0139594ddbb88fab2ca8d43ab12f..3387a19044b3ee2a1ef549c328c8bc354a5b6d23 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java +@@ -265,10 +265,12 @@ public class EntityExperienceOrb extends Entity { + } + } + ++ public final int durToXp(int i) { return b(i); } // Paper OBFHELPER + private int b(int i) { + return i / 2; + } + ++ public final int xpToDur(int i) { return c(i); } // Paper OBFHELPER + private int c(int i) { + return i * 2; + } +diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java +index d313b02f41e4f4a90676cbb37afce4e92dd4d664..72afbf8f537770540e90a2880ea81de137ea10f5 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java +@@ -269,8 +269,8 @@ public class EnchantmentManager { + return getEnchantmentLevel(Enchantments.CHANNELING, itemstack) > 0; + } + +- @Nullable +- public static Entry b(Enchantment enchantment, EntityLiving entityliving) { ++ public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, EntityLiving entityliving) { Entry entry = b(enchantment, entityliving); return entry != null ? entry.getValue() : ItemStack.NULL_ITEM; } // Paper - OBFHELPER ++ @Nullable public static Entry b(Enchantment enchantment, EntityLiving entityliving) { + return a(enchantment, entityliving, (itemstack) -> { + 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 b9a12d59e0144becc7e9c06d9a3c3079d006b583..e00b33493208865c0bd1bd11a96dd2ed1348da7c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -58,13 +58,17 @@ import net.minecraft.server.level.WorldServer; + import net.minecraft.server.network.PlayerConnection; + import net.minecraft.server.players.WhiteListEntry; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityExperienceOrb; + import net.minecraft.world.entity.EntityLiving; ++import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.ai.attributes.AttributeMapBase; + import net.minecraft.world.entity.ai.attributes.AttributeModifiable; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.inventory.Container; + import net.minecraft.world.item.EnumColor; ++import net.minecraft.world.item.enchantment.EnchantmentManager; ++import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.EnumGamemode; + import net.minecraft.world.level.block.entity.TileEntitySign; + import net.minecraft.world.level.saveddata.maps.MapIcon; +@@ -1178,8 +1182,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return GameMode.getByValue(getHandle().playerInteractManager.getGameMode().getId()); + } + ++ // Paper start + @Override +- public void giveExp(int exp) { ++ public int applyMending(int amount) { ++ EntityPlayer handle = getHandle(); ++ // Logic copied from EntityExperienceOrb and remapped to unobfuscated methods/properties ++ net.minecraft.world.item.ItemStack itemstack = EnchantmentManager.getRandomEquippedItemWithEnchant(Enchantments.MENDING, handle); ++ if (!itemstack.isEmpty() && itemstack.getItem().usesDurability()) { ++ ++ EntityExperienceOrb orb = EntityTypes.EXPERIENCE_ORB.create(handle.world); ++ orb.value = amount; ++ orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM; ++ orb.setPositionRaw(handle.locX(), handle.locY(), handle.locZ()); ++ ++ int i = Math.min(orb.xpToDur(amount), itemstack.getDamage()); ++ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, i); ++ i = event.getRepairAmount(); ++ orb.dead = true; ++ if (!event.isCancelled()) { ++ amount -= orb.durToXp(i); ++ itemstack.setDamage(itemstack.getDamage() - i); ++ } ++ } ++ return amount; ++ } ++ ++ @Override ++ public void giveExp(int exp, boolean applyMending) { ++ if (applyMending) { ++ exp = this.applyMending(exp); ++ } ++ // Paper end + getHandle().giveExp(exp); + } + diff --git a/patches/server-unmapped/0184-Make-max-squid-spawn-height-configurable.patch b/patches/server-unmapped/0184-Make-max-squid-spawn-height-configurable.patch new file mode 100644 index 0000000000..d6706377d7 --- /dev/null +++ b/patches/server-unmapped/0184-Make-max-squid-spawn-height-configurable.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 11 Jan 2018 16:47:28 -0600 +Subject: [PATCH] Make max squid spawn height configurable + +I don't know why upstream made only the minimum height configurable but +whatever + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6c692e58cde22003ecbf6dc5695799147c39905a..3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -348,4 +348,9 @@ public class PaperWorldConfig { + expMergeMaxValue = getInt("experience-merge-max-value", -1); + log("Experience Merge Max Value: " + expMergeMaxValue); + } ++ ++ public double squidMaxSpawnHeight; ++ private void squidMaxSpawnHeight() { ++ squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java +index 3cc9af925aaf116140d5f36cfc56aa001ffb4e35..7ce5e2597b34d3a4d2a79d73c15e893c064fc88c 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java +@@ -196,7 +196,8 @@ public class EntitySquid extends EntityWaterAnimal { + } + + public static boolean b(EntityTypes entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { +- return blockposition.getY() > generatoraccess.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && blockposition.getY() < generatoraccess.getSeaLevel(); // Spigot ++ final double maxHeight = generatoraccess.getMinecraftWorld().paperConfig.squidMaxSpawnHeight > 0 ? generatoraccess.getMinecraftWorld().paperConfig.squidMaxSpawnHeight : generatoraccess.getSeaLevel(); // Paper ++ return blockposition.getY() > generatoraccess.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && blockposition.getY() < maxHeight; // Spigot // Paper + } + + public void a(float f, float f1, float f2) { diff --git a/patches/server-unmapped/0185-PreCreatureSpawnEvent.patch b/patches/server-unmapped/0185-PreCreatureSpawnEvent.patch new file mode 100644 index 0000000000..bd4df8d022 --- /dev/null +++ b/patches/server-unmapped/0185-PreCreatureSpawnEvent.patch @@ -0,0 +1,200 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 14 Jan 2018 17:01:31 -0500 +Subject: [PATCH] PreCreatureSpawnEvent + +Adds an event to fire before an Entity is created, so that plugins that need to cancel +CreatureSpawnEvent can do so from this event instead. + +Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste +as it's done after the Entity object has been fully created. + +Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event +instead and save a lot of server resources. + +See: https://github.com/PaperMC/Paper/issues/917 + +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index a707ba365e25ea15e2e9d22110696b6136aa0c6f..1355c074353611669c947cb0f06c67be0ab418aa 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -17,6 +17,7 @@ import net.minecraft.nbt.NBTTagList; + import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.tags.Tag; +@@ -317,6 +318,20 @@ public class EntityTypes { + + @Nullable + public T spawnCreature(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // Paper start - Call PreCreatureSpawnEvent ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(this).getKey()); ++ if (type != null) { ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ MCUtil.toLocation(worldserver, blockposition), ++ type, ++ spawnReason ++ ); ++ if (!event.callEvent()) { ++ return null; ++ } ++ } ++ // Paper end + T t0 = this.createCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); + + if (t0 != null) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java +index 41f1aecbf6b506231a1b3b525fe0ce23b35c7840..6c01e460d3a1ff7f865ebc34dfd28d55b16aab98 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java +@@ -33,7 +33,7 @@ public class SensorGolemLastSeen extends Sensor { + Optional> optional = entityliving.getBehaviorController().getMemory(MemoryModuleType.MOBS); + + if (optional.isPresent()) { +- boolean flag = ((List) optional.get()).stream().anyMatch((entityliving1) -> { ++ boolean flag = optional.get().stream().anyMatch((entityliving1) -> { // Paper - decompile fixes + return entityliving1.getEntityType().equals(EntityTypes.IRON_GOLEM); + }); + +@@ -44,6 +44,7 @@ public class SensorGolemLastSeen extends Sensor { + } + } + ++ public static void setDetectedRecently(EntityLiving entityLiving) { b(entityLiving); } // Paper - OBFHELPER + public static void b(EntityLiving entityliving) { + entityliving.getBehaviorController().a(MemoryModuleType.GOLEM_DETECTED_RECENTLY, true, 600L); + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index 881bca30d2271560e2f2063f7d50753ec67a23f6..29957e79161db862c3eee5d0ed0cb8edb5dceb1c 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.PacketDebug; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundEffect; +@@ -943,6 +944,21 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + BlockPosition blockposition1 = this.a(blockposition, d0, d1); + + if (blockposition1 != null) { ++ // Paper start - Call PreCreatureSpawnEvent ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ MCUtil.toLocation(world, blockposition1), ++ org.bukkit.entity.EntityType.IRON_GOLEM, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE ++ ); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ SensorGolemLastSeen.b(this); // Set Golem Last Seen to stop it from spawning another one ++ return null; ++ } ++ break; ++ } ++ // Paper end + EntityIronGolem entityirongolem = (EntityIronGolem) EntityTypes.IRON_GOLEM.createCreature(worldserver, (NBTTagCompound) null, (IChatBaseComponent) null, (EntityHuman) null, blockposition1, EnumMobSpawn.MOB_SUMMONED, false, false); + + if (entityirongolem != null) { +diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +index 883c724fbb86a84ee903b5e7127f14726fe4cf24..d4b8126f12fdf7d9b4f882d3ed7d8da544ed9e8a 100644 +--- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java ++++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +@@ -12,6 +12,7 @@ import net.minecraft.core.particles.Particles; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.nbt.NBTTagList; + import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.WorldServer; + import net.minecraft.util.UtilColor; + import net.minecraft.util.WeightedRandom; +@@ -125,6 +126,27 @@ public abstract class MobSpawnerAbstract { + WorldServer worldserver = (WorldServer) world; + + if (EntityPositionTypes.a((EntityTypes) optional.get(), worldserver, EnumMobSpawn.SPAWNER, new BlockPosition(d3, d4, d5), world.getRandom())) { ++ // Paper start ++ EntityTypes entityType = optional.get(); ++ String key = EntityTypes.getName(entityType).getKey(); ++ ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); ++ if (type != null) { ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ MCUtil.toLocation(world, d3, d4, d5), ++ type, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER ++ ); ++ if (!event.callEvent()) { ++ flag = true; ++ if (event.shouldAbortSpawn()) { ++ break; ++ } ++ continue; ++ } ++ } ++ // Paper end + Entity entity = EntityTypes.a(nbttagcompound, world, (entity1) -> { + entity1.setPositionRotation(d3, d4, d5, entity1.yaw, entity1.pitch); + return entity1; +diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +index fd0595fd584046326eccacdf0a6afe40c5e84eed..1969d1002b3182338614a2be0519fcdc385b7a44 100644 +--- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java ++++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +@@ -15,6 +15,7 @@ import net.minecraft.core.EnumDirection; + import net.minecraft.core.IPosition; + import net.minecraft.core.IRegistry; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.WorldServer; + import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsBlock; +@@ -216,9 +217,16 @@ public final class SpawnerCreature { + j1 = biomesettingsmobs_c.d + worldserver.random.nextInt(1 + biomesettingsmobs_c.e - biomesettingsmobs_c.d); + } + +- if (a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { ++ // Paper start ++ Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); ++ if (doSpawning == null) { ++ return; ++ } ++ if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { ++ // Paper end + EntityInsentient entityinsentient = a(worldserver, biomesettingsmobs_c.c); + ++ + if (entityinsentient == null) { + return; + } +@@ -271,8 +279,24 @@ public final class SpawnerCreature { + } + } + +- private static boolean a(WorldServer worldserver, EnumCreatureType enumcreaturetype, StructureManager structuremanager, ChunkGenerator chunkgenerator, BiomeSettingsMobs.c biomesettingsmobs_c, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { ++ private static Boolean a(WorldServer worldserver, EnumCreatureType enumcreaturetype, StructureManager structuremanager, ChunkGenerator chunkgenerator, BiomeSettingsMobs.c biomesettingsmobs_c, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { // Paper + EntityTypes entitytypes = biomesettingsmobs_c.c; ++ // Paper start ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(entitytypes).getKey()); ++ if (type != null) { ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ MCUtil.toLocation(worldserver, blockposition_mutableblockposition), ++ type, SpawnReason.NATURAL ++ ); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ return null; ++ } ++ return false; ++ } ++ } ++ // Paper end + + if (entitytypes.e() == EnumCreatureType.MISC) { + return false; diff --git a/patches/server-unmapped/0186-PlayerNaturallySpawnCreaturesEvent.patch b/patches/server-unmapped/0186-PlayerNaturallySpawnCreaturesEvent.patch new file mode 100644 index 0000000000..e413709840 --- /dev/null +++ b/patches/server-unmapped/0186-PlayerNaturallySpawnCreaturesEvent.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 14 Jan 2018 17:36:02 -0500 +Subject: [PATCH] PlayerNaturallySpawnCreaturesEvent + +This event can be used for when you want to exclude a certain player +from triggering monster spawns on a server. + +Also a highly more effecient way to blanket block spawns in a world + +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 3351c6bcc5244fd7565ba7af08f63ea4d999ce97..677c185aca2cdd64bead9dbed147a87c5bcf1678 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -611,6 +611,15 @@ public class ChunkProviderServer extends IChunkProvider { + this.world.getMethodProfiler().exit(); + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper ++ //Paper start - call player naturally spawn event ++ int chunkRange = world.spigotConfig.mobSpawnRange; ++ chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; ++ chunkRange = Math.min(chunkRange, 8); ++ for (EntityPlayer entityPlayer : this.world.getPlayers()) { ++ entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); ++ entityPlayer.playerNaturallySpawnedEvent.callEvent(); ++ }; ++ // Paper end + this.world.timings.chunkTicks.startTiming(); // Paper + this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... + Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 5b2ae94ed7d499e401a058691eb6ed413b626150..de7167ddf7b36ef266e511187789f99244401c21 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1,5 +1,6 @@ + package net.minecraft.server.level; + ++import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent; + import com.google.common.collect.Lists; + import com.mojang.authlib.GameProfile; + import com.mojang.datafixers.util.Either; +@@ -228,6 +229,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public boolean sentListPacket = false; + public Integer clientViewDistance; + // CraftBukkit end ++ public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper + + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 1d71a19a7bbe463f537861531113dd1ed3e5b977..d1e45dfb99074ec027d4f943391a024c726d93b2 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -966,12 +966,23 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; + chunkRange = (chunkRange > 8) ? 8 : chunkRange; + +- double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; ++ final int finalChunkRange = chunkRange; // Paper for lambda below ++ //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event + // Spigot end + long i = chunkcoordintpair.pair(); + + return !this.chunkDistanceManager.d(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { +- return !entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot ++ // Paper start - ++ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; ++ double blockRange = 16384.0D; ++ if (reducedRange) { ++ event = entityplayer.playerNaturallySpawnedEvent; ++ if (event == null || event.isCancelled()) return false; ++ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); ++ } ++ ++ return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot ++ // Paper end + }); + } + diff --git a/patches/server-unmapped/0187-Add-setPlayerProfile-API-for-Skulls.patch b/patches/server-unmapped/0187-Add-setPlayerProfile-API-for-Skulls.patch new file mode 100644 index 0000000000..da897bd972 --- /dev/null +++ b/patches/server-unmapped/0187-Add-setPlayerProfile-API-for-Skulls.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 19 Jan 2018 00:36:25 -0500 +Subject: [PATCH] Add setPlayerProfile API for Skulls + +This allows you to create already filled textures on Skulls to avoid texture lookups +which commonly cause rate limit issues with Mojang API + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java +index 80ee7ab69ff70431d51321d403e5e3400a24bd67..00fb749f4d181d8d830496cf741d589e10af5098 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java +@@ -1,5 +1,7 @@ + package org.bukkit.craftbukkit.block; + ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; + import com.google.common.base.Preconditions; + import com.mojang.authlib.GameProfile; + import net.minecraft.server.MinecraftServer; +@@ -15,6 +17,7 @@ import org.bukkit.block.data.BlockData; + import org.bukkit.block.data.Directional; + import org.bukkit.block.data.Rotatable; + import org.bukkit.craftbukkit.entity.CraftPlayer; ++import javax.annotation.Nullable; + + public class CraftSkull extends CraftBlockEntityState implements Skull { + +@@ -105,6 +108,20 @@ public class CraftSkull extends CraftBlockEntityState implement + } + } + ++ // Paper start ++ @Override ++ public void setPlayerProfile(PlayerProfile profile) { ++ Preconditions.checkNotNull(profile, "profile"); ++ this.profile = CraftPlayerProfile.asAuthlibCopy(profile); ++ } ++ ++ @Nullable ++ @Override ++ public PlayerProfile getPlayerProfile() { ++ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; ++ } ++ // Paper end ++ + @Override + public BlockFace getRotation() { + BlockData blockData = getBlockData(); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +index 8298ae9bf1c5635f08552c15f004b3d0f6e9f19b..6db0d35eba647a0e81ca464fa52dc4a404ddd2ab 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +@@ -8,6 +8,8 @@ import net.minecraft.nbt.GameProfileSerializer; + import net.minecraft.nbt.NBTBase; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.world.level.block.entity.TileEntitySkull; ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; + import org.bukkit.Bukkit; + import org.bukkit.Material; + import org.bukkit.OfflinePlayer; +@@ -18,6 +20,7 @@ import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta; + import org.bukkit.craftbukkit.util.CraftMagicNumbers; + import org.bukkit.inventory.meta.SkullMeta; + ++import javax.annotation.Nullable; + @DelegateDeserialization(SerializableMeta.class) + class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + +@@ -149,6 +152,19 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + return hasOwner() ? profile.getName() : null; + } + ++ // Paper start ++ @Override ++ public void setPlayerProfile(@Nullable PlayerProfile profile) { ++ setProfile((profile == null) ? null : CraftPlayerProfile.asAuthlibCopy(profile)); ++ } ++ ++ @Nullable ++ @Override ++ public PlayerProfile getPlayerProfile() { ++ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; ++ } ++ // Paper end ++ + @Override + public OfflinePlayer getOwningPlayer() { + if (hasOwner()) { +@@ -175,7 +191,7 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { + } else { + // Paper start - Use Online Players Skull + GameProfile newProfile = null; +- net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayer(name); ++ net.minecraft.server.level.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayer(name); + if (player != null) newProfile = player.getProfile(); + if (newProfile == null) newProfile = new GameProfile(null, name); + setProfile(newProfile); diff --git a/patches/server-unmapped/0188-Fill-Profile-Property-Events.patch b/patches/server-unmapped/0188-Fill-Profile-Property-Events.patch new file mode 100644 index 0000000000..30643d081c --- /dev/null +++ b/patches/server-unmapped/0188-Fill-Profile-Property-Events.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 2 Jan 2018 00:31:26 -0500 +Subject: [PATCH] Fill Profile Property Events + +Allows plugins to populate profile properties from local sources to avoid calls out to Mojang API +to fill in textures for example. + +If Mojang API does need to be hit, event fire so you can get the results. + +This is useful for implementing a ProfileCache for Player Skulls + +diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java +index 93d73c27340645c7502acafdc0b2cfbc1a759dd8..5c7d2ee19243d0911a3a00af3ae42078a2ccba94 100644 +--- a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java ++++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java +@@ -1,6 +1,8 @@ + package com.destroystokyo.paper.profile; + + import com.mojang.authlib.Environment; ++import com.destroystokyo.paper.event.profile.FillProfileEvent; ++import com.destroystokyo.paper.event.profile.PreFillProfileEvent; + import com.mojang.authlib.GameProfile; + import com.mojang.authlib.minecraft.MinecraftProfileTexture; + import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; +@@ -20,7 +22,15 @@ public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionServi + + @Override + public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { +- return super.fillProfileProperties(profile, requireSecure); ++ CraftPlayerProfile playerProfile = (CraftPlayerProfile) CraftPlayerProfile.asBukkitMirror(profile); ++ new PreFillProfileEvent(playerProfile).callEvent(); ++ profile = playerProfile.getGameProfile(); ++ if (profile.isComplete() && profile.getProperties().containsKey("textures")) { ++ return profile; ++ } ++ GameProfile gameProfile = super.fillProfileProperties(profile, requireSecure); ++ new FillProfileEvent(CraftPlayerProfile.asBukkitMirror(gameProfile)).callEvent(); ++ return gameProfile; + } + + @Override diff --git a/patches/server-unmapped/0189-PlayerAdvancementCriterionGrantEvent.patch b/patches/server-unmapped/0189-PlayerAdvancementCriterionGrantEvent.patch new file mode 100644 index 0000000000..e919ba3032 --- /dev/null +++ b/patches/server-unmapped/0189-PlayerAdvancementCriterionGrantEvent.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 19 Jan 2018 08:15:29 -0600 +Subject: [PATCH] PlayerAdvancementCriterionGrantEvent + + +diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java +index d832cc2f3cc1ee73299a7f07eb2ccc3d392d5cf8..7d37626277823d5db05189c20bb1ebf91aa2a286 100644 +--- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java ++++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java +@@ -297,6 +297,12 @@ public class AdvancementDataPlayer { + boolean flag1 = advancementprogress.isDone(); + + if (advancementprogress.a(s)) { ++ // Paper start ++ if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.bukkit, s).callEvent()) { ++ advancementprogress.b(s); ++ return false; ++ } ++ // Paper end + this.d(advancement); + this.j.add(advancement); + flag = true; diff --git a/patches/server-unmapped/0190-Add-ArmorStand-Item-Meta.patch b/patches/server-unmapped/0190-Add-ArmorStand-Item-Meta.patch new file mode 100644 index 0000000000..658b0384d9 --- /dev/null +++ b/patches/server-unmapped/0190-Add-ArmorStand-Item-Meta.patch @@ -0,0 +1,296 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 27 Jan 2018 17:04:14 -0500 +Subject: [PATCH] Add ArmorStand Item Meta + +This is adds basic item meta for armor stands. It does not add all +possible metadata however. + +There are armor, hand, and equipment types, as well as position data +that can also be added here. This initial addition should serve a +starting point for future additions in this area. + +Fixes GH-559 + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java +index c593499aee3a2737cd80739ce61e7fba133d11ec..6b460841a8428727dd55a841fe5af06de9b1bdd1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java +@@ -9,9 +9,22 @@ import org.bukkit.configuration.serialization.DelegateDeserialization; + import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey; + + @DelegateDeserialization(CraftMetaItem.SerializableMeta.class) +-public class CraftMetaArmorStand extends CraftMetaItem { ++public class CraftMetaArmorStand extends CraftMetaItem implements com.destroystokyo.paper.inventory.meta.ArmorStandMeta { // Paper + + static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag"); ++ // Paper start ++ static final ItemMetaKey INVISIBLE = new ItemMetaKey("Invisible", "invisible"); ++ static final ItemMetaKey NO_BASE_PLATE = new ItemMetaKey("NoBasePlate", "no-base-plate"); ++ static final ItemMetaKey SHOW_ARMS = new ItemMetaKey("ShowArms", "show-arms"); ++ static final ItemMetaKey SMALL = new ItemMetaKey("Small", "small"); ++ static final ItemMetaKey MARKER = new ItemMetaKey("Marker", "marker"); ++ ++ private boolean invisible; ++ private boolean noBasePlate; ++ private boolean showArms; ++ private boolean small; ++ private boolean marker; ++ // Paper end + NBTTagCompound entityTag; + + CraftMetaArmorStand(CraftMetaItem meta) { +@@ -22,6 +35,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { + } + + CraftMetaArmorStand armorStand = (CraftMetaArmorStand) meta; ++ // Paper start ++ this.invisible = armorStand.invisible; ++ this.noBasePlate = armorStand.noBasePlate; ++ this.showArms = armorStand.showArms; ++ this.small = armorStand.small; ++ this.marker = armorStand.marker; ++ // Paper end + this.entityTag = armorStand.entityTag; + } + +@@ -30,11 +50,47 @@ public class CraftMetaArmorStand extends CraftMetaItem { + + if (tag.hasKey(ENTITY_TAG.NBT)) { + entityTag = tag.getCompound(ENTITY_TAG.NBT); ++ ++ // Paper start ++ if (entityTag.hasKey(INVISIBLE.NBT)) { ++ invisible = entityTag.getBoolean(INVISIBLE.NBT); ++ } ++ ++ if (entityTag.hasKey(NO_BASE_PLATE.NBT)) { ++ noBasePlate = entityTag.getBoolean(NO_BASE_PLATE.NBT); ++ } ++ ++ if (entityTag.hasKey(SHOW_ARMS.NBT)) { ++ showArms = entityTag.getBoolean(SHOW_ARMS.NBT); ++ } ++ ++ if (entityTag.hasKey(SMALL.NBT)) { ++ small = entityTag.getBoolean(SMALL.NBT); ++ } ++ ++ if (entityTag.hasKey(MARKER.NBT)) { ++ marker = entityTag.getBoolean(MARKER.NBT); ++ } ++ // Paper end + } + } + + CraftMetaArmorStand(Map map) { + super(map); ++ ++ // Paper start ++ boolean invis = SerializableMeta.getBoolean(map, INVISIBLE.BUKKIT); ++ boolean noBase = SerializableMeta.getBoolean(map, NO_BASE_PLATE.BUKKIT); ++ boolean showArms = SerializableMeta.getBoolean(map, SHOW_ARMS.BUKKIT); ++ boolean small = SerializableMeta.getBoolean(map, SMALL.BUKKIT); ++ boolean marker = SerializableMeta.getBoolean(map, MARKER.BUKKIT); ++ ++ this.invisible = invis; ++ this.noBasePlate = noBase; ++ this.showArms = showArms; ++ this.small = small; ++ this.marker = marker; ++ // Paper end + } + + @Override +@@ -57,6 +113,32 @@ public class CraftMetaArmorStand extends CraftMetaItem { + void applyToItem(NBTTagCompound tag) { + super.applyToItem(tag); + ++ // Paper start ++ if (!isArmorStandEmpty() && entityTag == null) { ++ entityTag = new NBTTagCompound(); ++ } ++ ++ if (isInvisible()) { ++ entityTag.setBoolean(INVISIBLE.NBT, invisible); ++ } ++ ++ if (hasNoBasePlate()) { ++ entityTag.setBoolean(NO_BASE_PLATE.NBT, noBasePlate); ++ } ++ ++ if (shouldShowArms()) { ++ entityTag.setBoolean(SHOW_ARMS.NBT, showArms); ++ } ++ ++ if (isSmall()) { ++ entityTag.setBoolean(SMALL.NBT, small); ++ } ++ ++ if (isMarker()) { ++ entityTag.setBoolean(MARKER.NBT, marker); ++ } ++ // Paper end ++ + if (entityTag != null) { + tag.set(ENTITY_TAG.NBT, entityTag); + } +@@ -78,7 +160,7 @@ public class CraftMetaArmorStand extends CraftMetaItem { + } + + boolean isArmorStandEmpty() { +- return !(entityTag != null); ++ return !(isInvisible() || hasNoBasePlate() || shouldShowArms() || isSmall() || isMarker() || entityTag != null); + } + + @Override +@@ -89,7 +171,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { + if (meta instanceof CraftMetaArmorStand) { + CraftMetaArmorStand that = (CraftMetaArmorStand) meta; + +- return entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : entityTag == null; ++ // Paper start ++ return invisible == that.invisible && ++ noBasePlate == that.noBasePlate && ++ showArms == that.showArms && ++ small == that.small && ++ marker == that.marker; ++ // Paper end + } + return true; + } +@@ -104,9 +192,14 @@ public class CraftMetaArmorStand extends CraftMetaItem { + final int original; + int hash = original = super.applyHash(); + +- if (entityTag != null) { +- hash = 73 * hash + entityTag.hashCode(); +- } ++ // Paper start ++ hash += entityTag != null ? 73 * hash + entityTag.hashCode() : 0; ++ hash += isInvisible() ? 61 * hash + 1231 : 0; ++ hash += hasNoBasePlate() ? 61 * hash + 1231 : 0; ++ hash += shouldShowArms() ? 61 * hash + 1231 : 0; ++ hash += isSmall() ? 61 * hash + 1231 : 0; ++ hash += isMarker() ? 61 * hash + 1231 : 0; ++ // Paper end + + return original != hash ? CraftMetaArmorStand.class.hashCode() ^ hash : hash; + } +@@ -115,6 +208,28 @@ public class CraftMetaArmorStand extends CraftMetaItem { + Builder serialize(Builder builder) { + super.serialize(builder); + ++ // Paper start ++ if (isInvisible()) { ++ builder.put(INVISIBLE.BUKKIT, invisible); ++ } ++ ++ if (hasNoBasePlate()) { ++ builder.put(NO_BASE_PLATE.BUKKIT, noBasePlate); ++ } ++ ++ if (shouldShowArms()) { ++ builder.put(SHOW_ARMS.BUKKIT, showArms); ++ } ++ ++ if (isSmall()) { ++ builder.put(SMALL.BUKKIT, small); ++ } ++ ++ if (isMarker()) { ++ builder.put(MARKER.BUKKIT, marker); ++ } ++ // Paper end ++ + return builder; + } + +@@ -128,4 +243,56 @@ public class CraftMetaArmorStand extends CraftMetaItem { + + return clone; + } ++ ++ // Paper start ++ @Override ++ public boolean isInvisible() { ++ return invisible; ++ } ++ ++ @Override ++ public boolean hasNoBasePlate() { ++ return noBasePlate; ++ } ++ ++ @Override ++ public boolean shouldShowArms() { ++ return showArms; ++ } ++ ++ @Override ++ public boolean isSmall() { ++ return small; ++ } ++ ++ @Override ++ public boolean isMarker() { ++ return marker; ++ } ++ ++ @Override ++ public void setInvisible(boolean invisible) { ++ this.invisible = invisible; ++ } ++ ++ @Override ++ public void setNoBasePlate(boolean noBasePlate) { ++ this.noBasePlate = noBasePlate; ++ } ++ ++ @Override ++ public void setShowArms(boolean showArms) { ++ this.showArms = showArms; ++ } ++ ++ @Override ++ public void setSmall(boolean small) { ++ this.small = small; ++ } ++ ++ @Override ++ public void setMarker(boolean marker) { ++ this.marker = marker; ++ } ++ // 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 57a6e66866ea82caccbbbfd55948a081f50f6bbe..7f790c484fec77e1d1f1dc6abe0daa19d009ae46 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -1442,6 +1442,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + CraftMetaCrossbow.CHARGED.NBT, + CraftMetaCrossbow.CHARGED_PROJECTILES.NBT, + CraftMetaSuspiciousStew.EFFECTS.NBT, ++ // Paper start ++ CraftMetaArmorStand.ENTITY_TAG.NBT, ++ CraftMetaArmorStand.INVISIBLE.NBT, ++ CraftMetaArmorStand.NO_BASE_PLATE.NBT, ++ CraftMetaArmorStand.SHOW_ARMS.NBT, ++ CraftMetaArmorStand.SMALL.NBT, ++ CraftMetaArmorStand.MARKER.NBT, ++ // Paper end + CraftMetaCompass.LODESTONE_DIMENSION.NBT, + CraftMetaCompass.LODESTONE_POS.NBT, + CraftMetaCompass.LODESTONE_TRACKED.NBT +diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +index 9a351c137776ac622f4df7353bb353142b3a6ccc..42f577ed3508ba5a380648461e149f16ce97c9bd 100644 +--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java ++++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +@@ -313,6 +313,7 @@ public class ItemMetaTest extends AbstractTestingBase { + final CraftMetaArmorStand meta = (CraftMetaArmorStand) cleanStack.getItemMeta(); + meta.entityTag = new NBTTagCompound(); + meta.entityTag.setBoolean("Small", true); ++ meta.setInvisible(true); // Paper + cleanStack.setItemMeta(meta); + return cleanStack; + } diff --git a/patches/server-unmapped/0191-Extend-Player-Interact-cancellation.patch b/patches/server-unmapped/0191-Extend-Player-Interact-cancellation.patch new file mode 100644 index 0000000000..d3407a908a --- /dev/null +++ b/patches/server-unmapped/0191-Extend-Player-Interact-cancellation.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 11 Feb 2018 10:43:46 +0000 +Subject: [PATCH] Extend Player Interact cancellation + +GUIs are opened on the client, meaning that the server cannot block them from opening, +However, it is possible to close these GUIs from the server. + +Flower pots are also not updated on the client when interaction is cancelled, this patch +also resolves this. + +Update adjacent blocks of doors, double plants, pistons and beds +when cancelling interaction. + +diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +index 74b4b127f39a0ad06e8f9add6861763724ab70ba..14f287d30c9a141f78f6311bef02a6fc4fa17564 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java ++++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +@@ -6,6 +6,7 @@ import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; + import net.minecraft.network.protocol.game.PacketPlayInBlockDig; + import net.minecraft.network.protocol.game.PacketPlayOutBlockBreak; ++import net.minecraft.network.protocol.game.PacketPlayOutCloseWindow; + import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo; + import net.minecraft.world.EnumHand; + import net.minecraft.world.EnumInteractionResult; +@@ -18,6 +19,7 @@ import net.minecraft.world.level.EnumGamemode; + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.BlockCommand; ++import net.minecraft.world.level.block.BlockFlowerPot; + import net.minecraft.world.level.block.BlockJigsaw; + import net.minecraft.world.level.block.BlockStructure; + import net.minecraft.world.level.block.entity.TileEntity; +@@ -180,6 +182,11 @@ public class PlayerInteractManager { + PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, enumdirection, this.player.inventory.getItemInHand(), EnumHand.MAIN_HAND); + if (event.isCancelled()) { + // Let the client know the block still exists ++ // Paper start - brute force neighbor blocks for any attached blocks ++ for (EnumDirection dir : EnumDirection.values()) { ++ this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition.shift(dir))); ++ } ++ // Paper end + this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(this.world, blockposition)); + // Update any tile entity data for this block + TileEntity tileentity = this.world.getTileEntity(blockposition); +@@ -484,6 +491,7 @@ public class PlayerInteractManager { + interactItemStack = itemstack.cloneItemStack(); + + if (event.useInteractedBlock() == Event.Result.DENY) { ++ + // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. + if (iblockdata.getBlock() instanceof BlockDoor) { + boolean bottom = iblockdata.get(BlockDoor.HALF) == BlockPropertyDoubleBlockHalf.LOWER; +@@ -496,7 +504,13 @@ public class PlayerInteractManager { + + // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) + entityplayer.playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition.up())); ++ // Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method ++ } else if (iblockdata.getBlock() instanceof BlockStructure) { ++ entityplayer.playerConnection.sendPacket(new PacketPlayOutCloseWindow()); ++ } else if (iblockdata.getBlock() instanceof BlockCommand) { ++ entityplayer.playerConnection.sendPacket(new PacketPlayOutCloseWindow()); + } ++ // Paper end - extend Player Interact cancellation + entityplayer.getBukkitEntity().updateInventory(); // SPIGOT-2867 + enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? EnumInteractionResult.SUCCESS : EnumInteractionResult.PASS; + } else if (this.gamemode == EnumGamemode.SPECTATOR) { diff --git a/patches/server-unmapped/0192-Tameable-getOwnerUniqueId-API.patch b/patches/server-unmapped/0192-Tameable-getOwnerUniqueId-API.patch new file mode 100644 index 0000000000..eae20f237a --- /dev/null +++ b/patches/server-unmapped/0192-Tameable-getOwnerUniqueId-API.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 24 Feb 2018 01:14:55 -0500 +Subject: [PATCH] Tameable#getOwnerUniqueId API + +This is faster if all you need is the UUID, as .getOwner() will cause +an OfflinePlayer to be loaded from disk. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +index 62ccef35e4b4238c50faf778fbf3ea9a494ca387..5b66165471197aad57e23f9a6669b11f25a5e4f2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +@@ -90,6 +90,9 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac + } + } + ++ public UUID getOwnerUniqueId() { ++ return getOwnerUUID(); ++ } + public UUID getOwnerUUID() { + return getHandle().getOwnerUUID(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java +index 3ac6623199f991ba16dbd62f4d6eed9982b22bcb..73a8ae346fb2ca5af172d96fa6b28e4d41a8c294 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java +@@ -17,6 +17,9 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat + return (EntityTameableAnimal) super.getHandle(); + } + ++ public UUID getOwnerUniqueId() { ++ return getOwnerUUID(); ++ } + public UUID getOwnerUUID() { + try { + return getHandle().getOwnerUUID(); diff --git a/patches/server-unmapped/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch b/patches/server-unmapped/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch new file mode 100644 index 0000000000..70c6b6d3e1 --- /dev/null +++ b/patches/server-unmapped/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Sat, 10 Mar 2018 00:50:24 +0100 +Subject: [PATCH] Toggleable player crits, helps mitigate hacked clients. + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2..48f0385c7203c7955de5a015f3dc42be2ab7b681 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -192,6 +192,11 @@ public class PaperWorldConfig { + disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); + } + ++ public boolean disablePlayerCrits; ++ private void disablePlayerCrits() { ++ disablePlayerCrits = getBoolean("game-mechanics.disable-player-crits", false); ++ } ++ + public boolean allChunksAreSlimeChunks; + private void allChunksAreSlimeChunks() { + allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index f9d0623a3ed5f49758cd5e97fe9f63a5b3198e58..18b0020d184e46c8957e82100681c8c66b1c3b62 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -1134,6 +1134,7 @@ public abstract class EntityHuman extends EntityLiving { + + boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.isClimbing() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && entity instanceof EntityLiving; + ++ flag2 = flag2 && !world.paperConfig.disablePlayerCrits; // Paper + flag2 = flag2 && !this.isSprinting(); + if (flag2) { + f *= 1.5F; diff --git a/patches/server-unmapped/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/patches/server-unmapped/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch new file mode 100644 index 0000000000..8ea2e3bb74 --- /dev/null +++ b/patches/server-unmapped/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 10 Mar 2018 16:33:15 -0500 +Subject: [PATCH] Prevent Frosted Ice from loading/holding chunks + + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java +index e32e94868386ff06ff29254e6cc3bee9b446a293..cbe8a6db356396f9fd9ce7cc61a5845bb8e6499d 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java +@@ -40,7 +40,8 @@ public class BlockIceFrost extends BlockIce { + EnumDirection enumdirection = aenumdirection[j]; + + blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, enumdirection); +- IBlockData iblockdata1 = worldserver.getType(blockposition_mutableblockposition); ++ IBlockData iblockdata1 = worldserver.getTypeIfLoaded(blockposition_mutableblockposition); // Paper ++ if (iblockdata1 == null) { continue; } // Paper + + if (iblockdata1.a((Block) this) && !this.e(iblockdata1, (World) worldserver, blockposition_mutableblockposition)) { + worldserver.getBlockTickList().a(blockposition_mutableblockposition, this, MathHelper.nextInt(random, worldserver.paperConfig.frostedIceDelayMin, worldserver.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay +@@ -83,7 +84,9 @@ public class BlockIceFrost extends BlockIce { + EnumDirection enumdirection = aenumdirection[l]; + + blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, enumdirection); +- if (iblockaccess.getType(blockposition_mutableblockposition).a((Block) this)) { ++ // Paper start ++ IBlockData type = iblockaccess.getTypeIfLoaded(blockposition_mutableblockposition); ++ if (type != null && type.a((Block) this)) { // Paper end + ++j; + if (j >= i) { + return false; diff --git a/patches/server-unmapped/0195-Disable-Explicit-Network-Manager-Flushing.patch b/patches/server-unmapped/0195-Disable-Explicit-Network-Manager-Flushing.patch new file mode 100644 index 0000000000..c5919e14be --- /dev/null +++ b/patches/server-unmapped/0195-Disable-Explicit-Network-Manager-Flushing.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 11 Mar 2018 14:13:33 -0400 +Subject: [PATCH] Disable Explicit Network Manager Flushing + +This seems completely pointless, as packet dispatch uses .writeAndFlush. + +Things seem to work fine without explicit flushing, but incase issues arise, +provide a System property to re-enable it using improved logic of doing the +flushing on the netty event loop, so it won't do the flush on the main thread. + +Renable flushing by passing -Dpaper.explicit-flush=true + +diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +index 60e4a4aa3854aaeb250d1318f2f25cf3591ea1d3..297820baef99e97e1216a64c527219e9ccc3e320 100644 +--- a/src/main/java/net/minecraft/network/NetworkManager.java ++++ b/src/main/java/net/minecraft/network/NetworkManager.java +@@ -73,6 +73,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + // Paper start - NetworkClient implementation + public int protocolVersion; + public java.net.InetSocketAddress virtualHost; ++ private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); + // Paper end + + public NetworkManager(EnumProtocolDirection enumprotocoldirection) { +@@ -240,7 +241,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } + + if (this.channel != null) { +- this.channel.flush(); ++ if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version + } + + if (this.t++ % 20 == 0) { diff --git a/patches/server-unmapped/0196-Implement-extended-PaperServerListPingEvent.patch b/patches/server-unmapped/0196-Implement-extended-PaperServerListPingEvent.patch new file mode 100644 index 0000000000..a0c59c93c8 --- /dev/null +++ b/patches/server-unmapped/0196-Implement-extended-PaperServerListPingEvent.patch @@ -0,0 +1,283 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Wed, 11 Oct 2017 15:56:26 +0200 +Subject: [PATCH] Implement extended PaperServerListPingEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e7f1efd0466a5d7bb9584ffbd6fbac1ecc6153a5 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java +@@ -0,0 +1,31 @@ ++package com.destroystokyo.paper.network; ++ ++import com.destroystokyo.paper.event.server.PaperServerListPingEvent; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.entity.Player; ++import org.bukkit.util.CachedServerIcon; ++ ++import javax.annotation.Nullable; ++ ++class PaperServerListPingEventImpl extends PaperServerListPingEvent { ++ ++ private final MinecraftServer server; ++ ++ PaperServerListPingEventImpl(MinecraftServer server, StatusClient client, int protocolVersion, @Nullable CachedServerIcon icon) { ++ super(client, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers(), ++ server.getServerModName() + ' ' + server.getVersion(), protocolVersion, icon); ++ this.server = server; ++ } ++ ++ @Override ++ protected final Object[] getOnlinePlayers() { ++ return this.server.getPlayerList().players.toArray(); ++ } ++ ++ @Override ++ protected final Player getBukkitPlayer(Object player) { ++ return ((EntityPlayer) player).getBukkitEntity(); ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java +new file mode 100644 +index 0000000000000000000000000000000000000000..46e84ac6ba5d32d030267fb0c991c281a673c716 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java +@@ -0,0 +1,11 @@ ++package com.destroystokyo.paper.network; ++ ++import net.minecraft.network.NetworkManager; ++ ++class PaperStatusClient extends PaperNetworkClient implements StatusClient { ++ ++ PaperStatusClient(NetworkManager networkManager) { ++ super(networkManager); ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..174326871df9b61beec51ef6a1e5f26932404b6a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java +@@ -0,0 +1,110 @@ ++package com.destroystokyo.paper.network; ++ ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; ++import com.google.common.base.MoreObjects; ++import com.google.common.base.Strings; ++import com.mojang.authlib.GameProfile; ++import io.papermc.paper.adventure.AdventureComponent; ++import java.util.List; ++import java.util.UUID; ++import javax.annotation.Nonnull; ++import net.minecraft.network.NetworkManager; ++import net.minecraft.network.protocol.status.PacketStatusOutServerInfo; ++import net.minecraft.network.protocol.status.ServerPing; ++import net.minecraft.server.MinecraftServer; ++ ++public final class StandardPaperServerListPingEventImpl extends PaperServerListPingEventImpl { ++ ++ private static final GameProfile[] EMPTY_PROFILES = new GameProfile[0]; ++ private static final UUID FAKE_UUID = new UUID(0, 0); ++ ++ private GameProfile[] originalSample; ++ ++ private StandardPaperServerListPingEventImpl(MinecraftServer server, NetworkManager networkManager, ServerPing ping) { ++ super(server, new PaperStatusClient(networkManager), ping.getServerData() != null ? ping.getServerData().getProtocolVersion() : -1, server.server.getServerIcon()); ++ this.originalSample = ping.getPlayers() == null ? null : ping.getPlayers().getSample(); // GH-1473 - pre-tick race condition NPE ++ } ++ ++ @Nonnull ++ @Override ++ public List getPlayerSample() { ++ List sample = super.getPlayerSample(); ++ ++ if (this.originalSample != null) { ++ for (GameProfile profile : this.originalSample) { ++ sample.add(CraftPlayerProfile.asBukkitCopy(profile)); ++ } ++ this.originalSample = null; ++ } ++ ++ return sample; ++ } ++ ++ private GameProfile[] getPlayerSampleHandle() { ++ if (this.originalSample != null) { ++ return this.originalSample; ++ } ++ ++ List entries = super.getPlayerSample(); ++ if (entries.isEmpty()) { ++ return EMPTY_PROFILES; ++ } ++ ++ GameProfile[] profiles = new GameProfile[entries.size()]; ++ for (int i = 0; i < profiles.length; i++) { ++ /* ++ * Avoid null UUIDs/names since that will make the response invalid ++ * on the client. ++ * Instead, fall back to a fake/empty UUID and an empty string as name. ++ * This can be used to create custom lines in the player list that do not ++ * refer to a specific player. ++ */ ++ ++ PlayerProfile profile = entries.get(i); ++ if (profile.getId() != null && profile.getName() != null) { ++ profiles[i] = CraftPlayerProfile.asAuthlib(profile); ++ } else { ++ profiles[i] = new GameProfile(MoreObjects.firstNonNull(profile.getId(), FAKE_UUID), Strings.nullToEmpty(profile.getName())); ++ } ++ } ++ ++ return profiles; ++ } ++ ++ @SuppressWarnings("deprecation") ++ public static void processRequest(MinecraftServer server, NetworkManager networkManager) { ++ StandardPaperServerListPingEventImpl event = new StandardPaperServerListPingEventImpl(server, networkManager, server.getServerPing()); ++ server.server.getPluginManager().callEvent(event); ++ ++ // Close connection immediately if event is cancelled ++ if (event.isCancelled()) { ++ networkManager.close(null); ++ return; ++ } ++ ++ // Setup response ++ ServerPing ping = new ServerPing(); ++ ++ // Description ++ ping.setMOTD(new AdventureComponent(event.motd())); ++ ++ // Players ++ if (!event.shouldHidePlayers()) { ++ ping.setPlayerSample(new ServerPing.ServerPingPlayerSample(event.getMaxPlayers(), event.getNumPlayers())); ++ ping.getPlayers().setSample(event.getPlayerSampleHandle()); ++ } ++ ++ // Version ++ ping.setServerInfo(new ServerPing.ServerData(event.getVersion(), event.getProtocolVersion())); ++ ++ // Favicon ++ if (event.getServerIcon() != null) { ++ ping.setFavicon(event.getServerIcon().getData()); ++ } ++ ++ // Send response ++ networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java b/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java +index 0ebeacaaeb265d202f52c758566a5160c42e8a55..cb37805c8cc5a064391f338c6359df518f6db39a 100644 +--- a/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java ++++ b/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java +@@ -2,6 +2,7 @@ package net.minecraft.network.protocol.status; + + import com.google.gson.Gson; + import com.google.gson.GsonBuilder; ++import io.papermc.paper.adventure.AdventureComponent; // Paper + import java.io.IOException; + import net.minecraft.network.PacketDataSerializer; + import net.minecraft.network.chat.ChatModifier; +@@ -12,7 +13,9 @@ import net.minecraft.util.ChatTypeAdapterFactory; + + public class PacketStatusOutServerInfo implements Packet { + +- private static final Gson a = (new GsonBuilder()).registerTypeAdapter(ServerPing.ServerData.class, new ServerPing.ServerData.Serializer()).registerTypeAdapter(ServerPing.ServerPingPlayerSample.class, new ServerPing.ServerPingPlayerSample.Serializer()).registerTypeAdapter(ServerPing.class, new ServerPing.Serializer()).registerTypeHierarchyAdapter(IChatBaseComponent.class, new IChatBaseComponent.ChatSerializer()).registerTypeHierarchyAdapter(ChatModifier.class, new ChatModifier.ChatModifierSerializer()).registerTypeAdapterFactory(new ChatTypeAdapterFactory()).create(); ++ private static final Gson a = (new GsonBuilder()).registerTypeAdapter(ServerPing.ServerData.class, new ServerPing.ServerData.Serializer()).registerTypeAdapter(ServerPing.ServerPingPlayerSample.class, new ServerPing.ServerPingPlayerSample.Serializer()).registerTypeAdapter(ServerPing.class, new ServerPing.Serializer()).registerTypeHierarchyAdapter(IChatBaseComponent.class, new IChatBaseComponent.ChatSerializer()).registerTypeHierarchyAdapter(ChatModifier.class, new ChatModifier.ChatModifierSerializer()).registerTypeAdapterFactory(new ChatTypeAdapterFactory()) ++ .registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()) ++ .create(); + private ServerPing b; + + public PacketStatusOutServerInfo() {} +diff --git a/src/main/java/net/minecraft/network/protocol/status/ServerPing.java b/src/main/java/net/minecraft/network/protocol/status/ServerPing.java +index 005ae7a75dfb19152abb606da29acad07c85e499..b9e36a83837913cd3e5abe598f695ba7a9ffc417 100644 +--- a/src/main/java/net/minecraft/network/protocol/status/ServerPing.java ++++ b/src/main/java/net/minecraft/network/protocol/status/ServerPing.java +@@ -31,6 +31,7 @@ public class ServerPing { + this.a = ichatbasecomponent; + } + ++ public ServerPingPlayerSample getPlayers() { return b(); } // Paper - OBFHELPER + public ServerPing.ServerPingPlayerSample b() { + return this.b; + } +@@ -162,10 +163,12 @@ public class ServerPing { + return this.b; + } + ++ public GameProfile[] getSample() { return c(); } // Paper - OBFHELPER + public GameProfile[] c() { + return this.c; + } + ++ public void setSample(GameProfile[] sample) { a(sample); } // Paper - OBFHELPER + public void a(GameProfile[] agameprofile) { + this.c = agameprofile; + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 71496fff9faeb72e28dfc2842ed8105a9cb835c1..5bbd3bb52b76b8b6cdf90c94bcb29f122f31c543 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2,6 +2,9 @@ package net.minecraft.server; + + import com.google.common.base.Splitter; + import com.google.common.collect.ImmutableList; ++import co.aikar.timings.Timings; ++import com.destroystokyo.paper.event.server.PaperServerListPingEvent; ++import com.google.common.base.Stopwatch; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; +@@ -1240,7 +1243,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant= 5000000000L) { + this.T = i; + this.serverPing.setPlayerSample(new ServerPing.ServerPingPlayerSample(this.getMaxPlayers(), this.getPlayerCount())); +- GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), 12)]; ++ GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), org.spigotmc.SpigotConfig.playerSample)]; // Paper + int j = MathHelper.nextInt(this.r, 0, this.getPlayerCount() - agameprofile.length); + + for (int k = 0; k < agameprofile.length; ++k) { +diff --git a/src/main/java/net/minecraft/server/network/PacketStatusListener.java b/src/main/java/net/minecraft/server/network/PacketStatusListener.java +index d219eda271a71f786808a6958b829fca40a1aaba..e1997563984540e6edf5d3b697d029dc5f3c40e1 100644 +--- a/src/main/java/net/minecraft/server/network/PacketStatusListener.java ++++ b/src/main/java/net/minecraft/server/network/PacketStatusListener.java +@@ -48,6 +48,8 @@ public class PacketStatusListener implements PacketStatusInListener { + this.networkManager.close(PacketStatusListener.a); + } else { + this.d = true; ++ // Paper start - Replace everything ++ /* + // CraftBukkit start + // this.networkManager.sendPacket(new PacketStatusOutServerInfo(this.minecraftServer.getServerPing())); + final Object[] players = minecraftServer.getPlayerList().players.toArray(); +@@ -143,6 +145,9 @@ public class PacketStatusListener implements PacketStatusInListener { + ping.setServerInfo(new ServerPing.ServerData(minecraftServer.getServerModName() + " " + minecraftServer.getVersion(), version)); + + this.networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); ++ */ ++ com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.minecraftServer, this.networkManager); ++ // Paper end + } + // CraftBukkit end + } +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index e8e5e5b568ba53dd006f1461cb4f027ceeae5528..11f8a2e5bf43013bce8675ea310ff42eacf14754 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -289,7 +289,7 @@ public class SpigotConfig + public static int playerSample; + private static void playerSample() + { +- playerSample = getInt( "settings.sample-count", 12 ); ++ playerSample = Math.max( getInt( "settings.sample-count", 12 ), 0 ); // Paper - Avoid negative counts + Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger + } + diff --git a/patches/server-unmapped/0197-Improved-Async-Task-Scheduler.patch b/patches/server-unmapped/0197-Improved-Async-Task-Scheduler.patch new file mode 100644 index 0000000000..b0ae823221 --- /dev/null +++ b/patches/server-unmapped/0197-Improved-Async-Task-Scheduler.patch @@ -0,0 +1,370 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 16 Mar 2018 22:59:43 -0400 +Subject: [PATCH] Improved Async Task Scheduler + +The Craft Scheduler still uses the primary thread for task scheduling. +This results in the main thread still having to do work as part of the +dispatching of async tasks. + +If plugins make use of lots of async tasks, such as particle emitters +that want to keep the logic off the main thread, the main thread still +receives quite a bit of load from processing all of these queued tasks. + +Additionally, resizing and managing the pending entries for all of +these asynchronous tasks takes up time on the main thread too. + +This commit replaces the implementation of the scheduler when working +with asynchronous tasks, by forwarding calls to the new scheduler. + +The Async Scheduler uses a single thread executor for "management" tasks. +The Management Thread is responsible for all adding and dispatching of +scheduled tasks. + +The mainThreadHeartbeat will send a heartbeat task to the management thread +with the currentTick value, so that it can find which tasks to execute. + +Scheduling of an async tasks also dispatches a management task, ensuring +that any Queue resizing operation occurs off of the main thread. + +The async queue uses a complete separate PriorityQueue, ensuring that resize +operations are decoupled from the sync tasks queue. + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3c1992e212a6d6f1db4d5b807b38d71913619fc0 +--- /dev/null ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java +@@ -0,0 +1,122 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package org.bukkit.craftbukkit.scheduler; ++ ++import com.destroystokyo.paper.ServerSchedulerReportingWrapper; ++import com.google.common.util.concurrent.ThreadFactoryBuilder; ++import org.bukkit.plugin.Plugin; ++ ++import java.util.ArrayList; ++import java.util.Iterator; ++import java.util.List; ++import java.util.concurrent.Executor; ++import java.util.concurrent.Executors; ++import java.util.concurrent.SynchronousQueue; ++import java.util.concurrent.ThreadPoolExecutor; ++import java.util.concurrent.TimeUnit; ++ ++public class CraftAsyncScheduler extends CraftScheduler { ++ ++ private final ThreadPoolExecutor executor = new ThreadPoolExecutor( ++ 4, Integer.MAX_VALUE,30L, TimeUnit.SECONDS, new SynchronousQueue<>(), ++ new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").build()); ++ private final Executor management = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder() ++ .setNameFormat("Craft Async Scheduler Management Thread").build()); ++ private final List temp = new ArrayList<>(); ++ ++ CraftAsyncScheduler() { ++ super(true); ++ executor.allowCoreThreadTimeOut(true); ++ executor.prestartAllCoreThreads(); ++ } ++ ++ @Override ++ public void cancelTask(int taskId) { ++ this.management.execute(() -> this.removeTask(taskId)); ++ } ++ ++ private synchronized void removeTask(int taskId) { ++ parsePending(); ++ this.pending.removeIf((task) -> { ++ if (task.getTaskId() == taskId) { ++ task.cancel0(); ++ return true; ++ } ++ return false; ++ }); ++ } ++ ++ @Override ++ public void mainThreadHeartbeat(int currentTick) { ++ this.currentTick = currentTick; ++ this.management.execute(() -> this.runTasks(currentTick)); ++ } ++ ++ private synchronized void runTasks(int currentTick) { ++ parsePending(); ++ while (!this.pending.isEmpty() && this.pending.peek().getNextRun() <= currentTick) { ++ CraftTask task = this.pending.remove(); ++ if (executeTask(task)) { ++ final long period = task.getPeriod(); ++ if (period > 0) { ++ task.setNextRun(currentTick + period); ++ temp.add(task); ++ } ++ } ++ parsePending(); ++ } ++ this.pending.addAll(temp); ++ temp.clear(); ++ } ++ ++ private boolean executeTask(CraftTask task) { ++ if (isValid(task)) { ++ this.runners.put(task.getTaskId(), task); ++ this.executor.execute(new ServerSchedulerReportingWrapper(task)); ++ return true; ++ } ++ return false; ++ } ++ ++ @Override ++ public synchronized void cancelTasks(Plugin plugin) { ++ parsePending(); ++ for (Iterator iterator = this.pending.iterator(); iterator.hasNext(); ) { ++ CraftTask task = iterator.next(); ++ if (task.getTaskId() != -1 && (plugin == null || task.getOwner().equals(plugin))) { ++ task.cancel0(); ++ iterator.remove(); ++ } ++ } ++ } ++ ++ /** ++ * Task is not cancelled ++ * @param runningTask ++ * @return ++ */ ++ static boolean isValid(CraftTask runningTask) { ++ return runningTask.getPeriod() >= CraftTask.NO_REPEATING; ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483ca3c7c2a8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -63,7 +63,7 @@ public class CraftScheduler implements BukkitScheduler { + /** + * Main thread logic only + */ +- private final PriorityQueue pending = new PriorityQueue(10, ++ final PriorityQueue pending = new PriorityQueue(10, // Paper + new Comparator() { + @Override + public int compare(final CraftTask o1, final CraftTask o2) { +@@ -80,12 +80,13 @@ public class CraftScheduler implements BukkitScheduler { + /** + * These are tasks that are currently active. It's provided for 'viewing' the current state. + */ +- private final ConcurrentHashMap runners = new ConcurrentHashMap(); ++ final ConcurrentHashMap runners = new ConcurrentHashMap(); // Paper + /** + * The sync task that is currently running on the main thread. + */ + private volatile CraftTask currentTask = null; +- private volatile int currentTick = -1; ++ // Paper start - Improved Async Task Scheduler ++ volatile int currentTick = -1;/* + private final Executor executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %d").build()); + private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) { + @Override +@@ -94,12 +95,31 @@ public class CraftScheduler implements BukkitScheduler { + } + }; + private CraftAsyncDebugger debugTail = debugHead; ++ ++ */ // Paper end + private static final int RECENT_TICKS; + + static { + RECENT_TICKS = 30; + } + ++ ++ // Paper start ++ private final CraftScheduler asyncScheduler; ++ private final boolean isAsyncScheduler; ++ public CraftScheduler() { ++ this(false); ++ } ++ ++ public CraftScheduler(boolean isAsync) { ++ this.isAsyncScheduler = isAsync; ++ if (isAsync) { ++ this.asyncScheduler = this; ++ } else { ++ this.asyncScheduler = new CraftAsyncScheduler(); ++ } ++ } ++ // Paper end + @Override + public int scheduleSyncDelayedTask(final Plugin plugin, final Runnable task) { + return this.scheduleSyncDelayedTask(plugin, task, 0L); +@@ -222,7 +242,7 @@ public class CraftScheduler implements BukkitScheduler { + } else if (period < CraftTask.NO_REPEATING) { + period = CraftTask.NO_REPEATING; + } +- return handle(new CraftAsyncTask(runners, plugin, runnable, nextId(), period), delay); ++ return handle(new CraftAsyncTask(this.asyncScheduler.runners, plugin, runnable, nextId(), period), delay); // Paper + } + + @Override +@@ -238,6 +258,11 @@ public class CraftScheduler implements BukkitScheduler { + if (taskId <= 0) { + return; + } ++ // Paper start ++ if (!this.isAsyncScheduler) { ++ this.asyncScheduler.cancelTask(taskId); ++ } ++ // Paper end + CraftTask task = runners.get(taskId); + if (task != null) { + task.cancel0(); +@@ -280,6 +305,11 @@ public class CraftScheduler implements BukkitScheduler { + @Override + public void cancelTasks(final Plugin plugin) { + Validate.notNull(plugin, "Cannot cancel tasks of null plugin"); ++ // Paper start ++ if (!this.isAsyncScheduler) { ++ this.asyncScheduler.cancelTasks(plugin); ++ } ++ // Paper end + final CraftTask task = new CraftTask( + new Runnable() { + @Override +@@ -319,6 +349,13 @@ public class CraftScheduler implements BukkitScheduler { + + @Override + public boolean isCurrentlyRunning(final int taskId) { ++ // Paper start ++ if (!isAsyncScheduler) { ++ if (this.asyncScheduler.isCurrentlyRunning(taskId)) { ++ return true; ++ } ++ } ++ // Paper end + final CraftTask task = runners.get(taskId); + if (task == null) { + return false; +@@ -337,6 +374,11 @@ public class CraftScheduler implements BukkitScheduler { + if (taskId <= 0) { + return false; + } ++ // Paper start ++ if (!this.isAsyncScheduler && this.asyncScheduler.isQueued(taskId)) { ++ return true; ++ } ++ // Paper end + for (CraftTask task = head.getNext(); task != null; task = task.getNext()) { + if (task.getTaskId() == taskId) { + return task.getPeriod() >= CraftTask.NO_REPEATING; // The task will run +@@ -348,6 +390,12 @@ public class CraftScheduler implements BukkitScheduler { + + @Override + public List getActiveWorkers() { ++ // Paper start ++ if (!isAsyncScheduler) { ++ //noinspection TailRecursion ++ return this.asyncScheduler.getActiveWorkers(); ++ } ++ // Paper end + final ArrayList workers = new ArrayList(); + for (final CraftTask taskObj : runners.values()) { + // Iterator will be a best-effort (may fail to grab very new values) if called from an async thread +@@ -385,6 +433,11 @@ public class CraftScheduler implements BukkitScheduler { + pending.add(task); + } + } ++ // Paper start ++ if (!this.isAsyncScheduler) { ++ pending.addAll(this.asyncScheduler.getPendingTasks()); ++ } ++ // Paper end + return pending; + } + +@@ -392,6 +445,11 @@ public class CraftScheduler implements BukkitScheduler { + * This method is designed to never block or wait for locks; an immediate execution of all current tasks. + */ + public void mainThreadHeartbeat(final int currentTick) { ++ // Paper start ++ if (!this.isAsyncScheduler) { ++ this.asyncScheduler.mainThreadHeartbeat(currentTick); ++ } ++ // Paper end + this.currentTick = currentTick; + final List temp = this.temp; + parsePending(); +@@ -431,7 +489,7 @@ public class CraftScheduler implements BukkitScheduler { + parsePending(); + } else { + //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper +- executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper ++ task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Paper"); // Paper + // We don't need to parse pending + // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) + } +@@ -450,7 +508,7 @@ public class CraftScheduler implements BukkitScheduler { + //debugHead = debugHead.getNextHead(currentTick); // Paper + } + +- private void addTask(final CraftTask task) { ++ protected void addTask(final CraftTask task) { + final AtomicReference tail = this.tail; + CraftTask tailTask = tail.get(); + while (!tail.compareAndSet(tailTask, task)) { +@@ -459,7 +517,13 @@ public class CraftScheduler implements BukkitScheduler { + tailTask.setNext(task); + } + +- private CraftTask handle(final CraftTask task, final long delay) { ++ protected CraftTask handle(final CraftTask task, final long delay) { // Paper ++ // Paper start ++ if (!this.isAsyncScheduler && !task.isSync()) { ++ this.asyncScheduler.handle(task, delay); ++ return task; ++ } ++ // Paper end + task.setNextRun(currentTick + delay); + addTask(task); + return task; +@@ -478,8 +542,8 @@ public class CraftScheduler implements BukkitScheduler { + return ids.incrementAndGet(); + } + +- private void parsePending() { +- MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); ++ void parsePending() { // Paper ++ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); // Paper + CraftTask head = this.head; + CraftTask task = head.getNext(); + CraftTask lastTask = head; +@@ -498,7 +562,7 @@ public class CraftScheduler implements BukkitScheduler { + task.setNext(null); + } + this.head = lastTask; +- MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); ++ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); // Paper + } + + private boolean isReady(final int currentTick) { diff --git a/patches/server-unmapped/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/patches/server-unmapped/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch new file mode 100644 index 0000000000..9b4622cc44 --- /dev/null +++ b/patches/server-unmapped/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 18 Mar 2018 11:45:57 -0400 +Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent + +This will allow you to change the players name or skin on login. + +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index f95f5a8b30f42c8f5b6cee3ef6adb1f4e09832dc..31d404c5343c33b9b64724c5ac40d0c52ad5af66 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -1,5 +1,7 @@ + package net.minecraft.server.network; + ++import com.destroystokyo.paper.profile.CraftPlayerProfile; ++import com.destroystokyo.paper.profile.PlayerProfile; + import com.mojang.authlib.GameProfile; + import com.mojang.authlib.exceptions.AuthenticationUnavailableException; + import java.math.BigInteger; +@@ -38,6 +40,7 @@ import org.apache.logging.log4j.Logger; + // CraftBukkit start + import net.minecraft.network.chat.ChatComponentText; + import io.papermc.paper.adventure.PaperAdventure; // Paper ++import org.bukkit.Bukkit; + import org.bukkit.craftbukkit.util.Waitable; + import org.bukkit.event.player.AsyncPlayerPreLoginEvent; + import org.bukkit.event.player.PlayerPreLoginEvent; +@@ -316,8 +319,16 @@ public class LoginListener implements PacketLoginInListener { + java.util.UUID uniqueId = i.getId(); + final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; + +- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); ++ // Paper start ++ PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); ++ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); + server.getPluginManager().callEvent(asyncEvent); ++ profile = asyncEvent.getPlayerProfile(); ++ profile.complete(); ++ i = CraftPlayerProfile.asAuthlibCopy(profile); ++ playerName = i.getName(); ++ uniqueId = i.getId(); ++ // Paper end + + if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { + final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); diff --git a/patches/server-unmapped/0199-Player.setPlayerProfile-API.patch b/patches/server-unmapped/0199-Player.setPlayerProfile-API.patch new file mode 100644 index 0000000000..2fc79938cb --- /dev/null +++ b/patches/server-unmapped/0199-Player.setPlayerProfile-API.patch @@ -0,0 +1,142 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 18 Mar 2018 12:29:48 -0400 +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/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index 31d404c5343c33b9b64724c5ac40d0c52ad5af66..21e70a133278d85ecd65fec36a273ed4faabf6cc 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -56,7 +56,7 @@ public class LoginListener implements PacketLoginInListener { + public final NetworkManager networkManager; + private LoginListener.EnumProtocolState g; + private int h; +- private GameProfile i; ++ private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } private GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER + private final String j; + private SecretKey loginKey; + private EntityPlayer l; +@@ -320,12 +320,12 @@ public class LoginListener implements PacketLoginInListener { + final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; + + // Paper start +- PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); ++ PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); + AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); + server.getPluginManager().callEvent(asyncEvent); + profile = asyncEvent.getPlayerProfile(); +- profile.complete(); +- i = CraftPlayerProfile.asAuthlibCopy(profile); ++ profile.complete(true); ++ setGameProfile(CraftPlayerProfile.asAuthlib(profile)); + playerName = i.getName(); + uniqueId = i.getId(); + // Paper end +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 18b0020d184e46c8957e82100681c8c66b1c3b62..41dd46c6ef95f7dc41d9ca36a5f0b85f5608fdeb 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -162,7 +162,7 @@ public abstract class EntityHuman extends EntityLiving { + protected int bG; + protected final float bH = 0.02F; + private int g; +- private final GameProfile bJ; ++ private GameProfile bJ; public final void setProfile(final GameProfile profile) { this.bJ = profile; } // Paper - OBFHELPER + private ItemStack bL; + private final ItemCooldown bM; + @Nullable +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index e00b33493208865c0bd1bd11a96dd2ed1348da7c..e1d1aaa278287214e2edac5f690d4f5257696ed0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -70,6 +70,7 @@ import net.minecraft.world.item.EnumColor; + import net.minecraft.world.item.enchantment.EnchantmentManager; + import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.EnumGamemode; ++import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.entity.TileEntitySign; + import net.minecraft.world.level.saveddata.maps.MapIcon; + import net.minecraft.world.phys.Vec3D; +@@ -1310,8 +1311,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + hiddenPlayers.put(player.getUniqueId(), hidingPlugins); + + // Remove this player from the hidden player's EntityTrackerEntry +- PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; ++ // Paper start + EntityPlayer other = ((CraftPlayer) player).getHandle(); ++ unregisterPlayer(other); ++ } ++ private void unregisterPlayer(EntityPlayer other) { ++ PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; ++ // Paper end + PlayerChunkMap.EntityTracker entry = tracker.trackedEntities.get(other.getId()); + if (entry != null) { + entry.clear(getHandle()); +@@ -1352,8 +1358,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + hiddenPlayers.remove(player.getUniqueId()); + +- PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; ++ // Paper start + EntityPlayer other = ((CraftPlayer) player).getHandle(); ++ registerPlayer(other); ++ } ++ private void registerPlayer(EntityPlayer other) { ++ PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; ++ // Paper end + + getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, other)); + +@@ -1362,6 +1373,50 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + entry.updatePlayer(getHandle()); + } + } ++ // Paper start ++ private void reregisterPlayer(EntityPlayer player) { ++ if (!hiddenPlayers.containsKey(player.getUniqueID())) { ++ unregisterPlayer(player); ++ registerPlayer(player); ++ } ++ } ++ public void setPlayerProfile(com.destroystokyo.paper.profile.PlayerProfile profile) { ++ EntityPlayer self = getHandle(); ++ self.setProfile(com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile)); ++ if (!self.sentListPacket) { ++ return; ++ } ++ List players = server.getServer().getPlayerList().players; ++ for (EntityPlayer player : players) { ++ player.getBukkitEntity().reregisterPlayer(self); ++ } ++ refreshPlayer(); ++ } ++ public com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile() { ++ return new com.destroystokyo.paper.profile.CraftPlayerProfile(this).clone(); ++ } ++ ++ private void refreshPlayer() { ++ EntityPlayer handle = getHandle(); ++ ++ Location loc = getLocation(); ++ ++ PlayerConnection connection = handle.playerConnection; ++ reregisterPlayer(handle); ++ ++ //Respawn the player then update their position and selected slot ++ WorldServer worldserver = handle.getWorldServer(); ++ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutRespawn(worldserver.getDimensionManager(), worldserver.getDimensionKey(), BiomeManager.a(worldserver.getSeed()), handle.playerInteractManager.getGameMode(), handle.playerInteractManager.c(), worldserver.isDebugWorld(), worldserver.isFlatWorld(), true)); ++ handle.updateAbilities(); ++ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutPosition(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), new HashSet<>(), 0)); ++ net.minecraft.server.MinecraftServer.getServer().getPlayerList().updateClient(handle); ++ ++ if (this.isOp()) { ++ this.setOp(false); ++ this.setOp(true); ++ } ++ } ++ // Paper end + + public void removeDisconnectingPlayer(Player player) { + hiddenPlayers.remove(player.getUniqueId()); diff --git a/patches/server-unmapped/0200-Fix-Dragon-Server-Crashes.patch b/patches/server-unmapped/0200-Fix-Dragon-Server-Crashes.patch new file mode 100644 index 0000000000..1ec120745b --- /dev/null +++ b/patches/server-unmapped/0200-Fix-Dragon-Server-Crashes.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 21 Mar 2018 20:52:07 -0400 +Subject: [PATCH] Fix Dragon Server Crashes + +If the dragon tries to find "ground" and hits a hole, or off edge, +it will infinitely keep looking for non air and eventually crash. + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java +index fbecb61b8c511fc7daa21690b2a653254be74246..5adbd9fe858aad9c775a10254eb53b34719a9bd6 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java +@@ -63,7 +63,7 @@ public class DragonControllerLandedFlame extends AbstractDragonControllerLanded + double d3 = d2; + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(d0, d2, d1); + +- while (this.a.world.isEmpty(blockposition_mutableblockposition)) { ++ while (this.a.world.isEmpty(blockposition_mutableblockposition ) && d2 > 0) { // Paper + --d3; + if (d3 < 0.0D) { + d3 = d2; diff --git a/patches/server-unmapped/0201-getPlayerUniqueId-API.patch b/patches/server-unmapped/0201-getPlayerUniqueId-API.patch new file mode 100644 index 0000000000..c89810dd72 --- /dev/null +++ b/patches/server-unmapped/0201-getPlayerUniqueId-API.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 22 Mar 2018 01:40:24 -0400 +Subject: [PATCH] getPlayerUniqueId API + +Gets the unique ID of the player currently known as the specified player name +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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 3aed540b6359df9940a26901c55f0306743ad085..47443fae011fb8cdf18c38e6c4b443b874bd26e4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1518,6 +1518,25 @@ public final class CraftServer implements Server { + return recipients.size(); + } + ++ // Paper start ++ @Nullable ++ public UUID getPlayerUniqueId(String name) { ++ Player player = Bukkit.getPlayerExact(name); ++ if (player != null) { ++ return player.getUniqueId(); ++ } ++ GameProfile profile; ++ // Only fetch an online UUID in online mode ++ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) { ++ profile = console.getUserCache().getProfile( name ); ++ } else { ++ // Make an OfflinePlayer using an offline mode UUID since the name has no profile ++ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); ++ } ++ return profile != null ? profile.getId() : null; ++ } ++ // Paper end ++ + @Override + @Deprecated + public OfflinePlayer getOfflinePlayer(String name) { diff --git a/patches/server-unmapped/0202-Make-player-data-saving-configurable.patch b/patches/server-unmapped/0202-Make-player-data-saving-configurable.patch new file mode 100644 index 0000000000..7a7b4d1993 --- /dev/null +++ b/patches/server-unmapped/0202-Make-player-data-saving-configurable.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Mon, 26 Mar 2018 18:30:53 +0300 +Subject: [PATCH] Make player data saving configurable + +Upstream has added a patch which negates the need for this patch, +however, we should still migrate our configuration back upstream, +to prevent unexpected situations + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 52954fc3bf932cfc9d5ce63e3d3cace351305790..05a5abb951abe37f30a719cb75376d2d43c0d252 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -279,4 +279,13 @@ public class PaperConfig { + private static void authenticationServersDownKickMessage() { + authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); + } ++ ++ private static void savePlayerData() { ++ Object val = config.get("settings.save-player-data"); ++ if (val instanceof Boolean) { ++ SpigotConfig.disablePlayerDataSaving = !(Boolean) val; ++ SpigotConfig.config.set("players.disable-saving", SpigotConfig.disableAdvancementSaving); ++ SpigotConfig.save(); ++ } ++ } + } diff --git a/patches/server-unmapped/0203-Make-legacy-ping-handler-more-reliable.patch b/patches/server-unmapped/0203-Make-legacy-ping-handler-more-reliable.patch new file mode 100644 index 0000000000..a437521ba2 --- /dev/null +++ b/patches/server-unmapped/0203-Make-legacy-ping-handler-more-reliable.patch @@ -0,0 +1,168 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Wed, 11 Oct 2017 18:22:50 +0200 +Subject: [PATCH] Make legacy ping handler more reliable + +The Minecraft server often fails to respond to old ("legacy") pings +from old Minecraft versions using the protocol used before the switch +to Netty in Minecraft 1.7. + +Due to packet fragmentation[1], we might not have all needed bytes +available when the LegacyPingHandler is called. In this case, it will +run into an error, remove the handler and continue using the modern +protocol. + +This is unlikely to happen for the first two revisions of the legacy +ping protocol (used in Minecraft 1.5.x and older) since the request +consists of only one or two bytes, but happens frequently for the +last/third revision introduced in Minecraft 1.6. + +It has much larger, variable packet sizes due to the inclusion of +the virtual host (the hostname/port used to connect to the server). + +The solution[2] is simple: If we find more than two matching bytes, +we buffer the remaining bytes until we have enough to fully read and +respond to the request. + +[1]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h3-11 +[2]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h4-13 + +diff --git a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java +index e0edebf3eb93c11de2ed5c9013565950b4ad2375..0286d30b63e42224028b343315e1d1a9db2fe3d1 100644 +--- a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java ++++ b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java +@@ -15,6 +15,7 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { + + private static final Logger LOGGER = LogManager.getLogger(); + private final ServerConnection b; ++ private ByteBuf buf; // Paper + + public LegacyPingHandler(ServerConnection serverconnection) { + this.b = serverconnection; +@@ -23,6 +24,16 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { + public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) throws Exception { + ByteBuf bytebuf = (ByteBuf) object; + ++ // Paper start - Make legacy ping handler more reliable ++ if (this.buf != null) { ++ try { ++ readLegacy1_6(channelhandlercontext, bytebuf); ++ } finally { ++ bytebuf.release(); ++ } ++ return; ++ } ++ // Paper end + bytebuf.markReaderIndex(); + boolean flag = true; + +@@ -53,6 +64,10 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { + this.a(channelhandlercontext, this.a(s)); + break; + default: ++ // Paper start - Replace with improved version below ++ if (bytebuf.readUnsignedByte() != 0x01 || bytebuf.readUnsignedByte() != 0xFA) return; ++ readLegacy1_6(channelhandlercontext, bytebuf); ++ /* + boolean flag1 = bytebuf.readUnsignedByte() == 1; + + flag1 &= bytebuf.readUnsignedByte() == 250; +@@ -76,6 +91,7 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { + } finally { + bytebuf1.release(); + } ++ */ // Paper end - Replace with improved version below + } + + bytebuf.release(); +@@ -93,6 +109,90 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { + + } + ++ // Paper start ++ private static String readLegacyString(ByteBuf buf) { ++ int size = buf.readShort() * Character.BYTES; ++ if (!buf.isReadable(size)) { ++ return null; ++ } ++ ++ String result = buf.toString(buf.readerIndex(), size, StandardCharsets.UTF_16BE); ++ buf.skipBytes(size); // toString doesn't increase readerIndex automatically ++ return result; ++ } ++ ++ private void readLegacy1_6(ChannelHandlerContext ctx, ByteBuf part) { ++ ByteBuf buf = this.buf; ++ ++ if (buf == null) { ++ this.buf = buf = ctx.alloc().buffer(); ++ buf.markReaderIndex(); ++ } else { ++ buf.resetReaderIndex(); ++ } ++ ++ buf.writeBytes(part); ++ ++ if (!buf.isReadable(Short.BYTES + Short.BYTES + Byte.BYTES + Short.BYTES + Integer.BYTES)) { ++ return; ++ } ++ ++ String s = readLegacyString(buf); ++ if (s == null) { ++ return; ++ } ++ ++ if (!s.equals("MC|PingHost")) { ++ removeHandler(ctx); ++ return; ++ } ++ ++ if (!buf.isReadable(Short.BYTES) || !buf.isReadable(buf.readShort())) { ++ return; ++ } ++ ++ MinecraftServer server = this.b.d(); ++ int protocolVersion = buf.readByte(); ++ String host = readLegacyString(buf); ++ if (host == null) { ++ removeHandler(ctx); ++ return; ++ } ++ int port = buf.readInt(); ++ ++ if (buf.isReadable()) { ++ removeHandler(ctx); ++ return; ++ } ++ ++ buf.release(); ++ this.buf = null; ++ ++ LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); ++ ++ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", ++ Byte.MAX_VALUE, server.getVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); ++ this.a(ctx, this.a(response)); ++ } ++ ++ private void removeHandler(ChannelHandlerContext ctx) { ++ ByteBuf buf = this.buf; ++ this.buf = null; ++ ++ buf.resetReaderIndex(); ++ ctx.pipeline().remove(this); ++ ctx.fireChannelRead(buf); ++ } ++ ++ @Override ++ public void handlerRemoved(ChannelHandlerContext ctx) { ++ if (this.buf != null) { ++ this.buf.release(); ++ this.buf = null; ++ } ++ } ++ // Paper end ++ + private void a(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf) { + channelhandlercontext.pipeline().firstContext().writeAndFlush(bytebuf).addListener(ChannelFutureListener.CLOSE); + } diff --git a/patches/server-unmapped/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch b/patches/server-unmapped/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch new file mode 100644 index 0000000000..9274b7f30a --- /dev/null +++ b/patches/server-unmapped/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch @@ -0,0 +1,154 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Wed, 11 Oct 2017 19:30:51 +0200 +Subject: [PATCH] Call PaperServerListPingEvent for legacy pings + + +diff --git a/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java +new file mode 100644 +index 0000000000000000000000000000000000000000..74c012fd40491f1d870fbc1aa8c318a2197eb106 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java +@@ -0,0 +1,73 @@ ++package com.destroystokyo.paper.network; ++ ++import com.destroystokyo.paper.event.server.PaperServerListPingEvent; ++import net.minecraft.server.MinecraftServer; ++import org.apache.commons.lang3.StringUtils; ++import org.bukkit.ChatColor; ++ ++import java.net.InetSocketAddress; ++ ++import javax.annotation.Nullable; ++ ++public final class PaperLegacyStatusClient implements StatusClient { ++ ++ private final InetSocketAddress address; ++ private final int protocolVersion; ++ @Nullable private final InetSocketAddress virtualHost; ++ ++ private PaperLegacyStatusClient(InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { ++ this.address = address; ++ this.protocolVersion = protocolVersion; ++ this.virtualHost = virtualHost; ++ } ++ ++ @Override ++ public InetSocketAddress getAddress() { ++ return this.address; ++ } ++ ++ @Override ++ public int getProtocolVersion() { ++ return this.protocolVersion; ++ } ++ ++ @Nullable ++ @Override ++ public InetSocketAddress getVirtualHost() { ++ return this.virtualHost; ++ } ++ ++ @Override ++ public boolean isLegacy() { ++ return true; ++ } ++ ++ public static PaperServerListPingEvent processRequest(MinecraftServer server, ++ InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { ++ ++ PaperServerListPingEvent event = new PaperServerListPingEventImpl(server, ++ new PaperLegacyStatusClient(address, protocolVersion, virtualHost), Byte.MAX_VALUE, null); ++ server.server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return null; ++ } ++ ++ return event; ++ } ++ ++ public static String getMotd(PaperServerListPingEvent event) { ++ return getFirstLine(event.getMotd()); ++ } ++ ++ public static String getUnformattedMotd(PaperServerListPingEvent event) { ++ // Strip color codes and all other occurrences of the color char (because it's used as delimiter) ++ return getFirstLine(StringUtils.remove(ChatColor.stripColor(event.getMotd()), ChatColor.COLOR_CHAR)); ++ } ++ ++ private static String getFirstLine(String s) { ++ int pos = s.indexOf('\n'); ++ return pos >= 0 ? s.substring(0, pos) : s; ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java +index 0286d30b63e42224028b343315e1d1a9db2fe3d1..765dea6653b450802d45b76c7d2ac3d5778da9df 100644 +--- a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java ++++ b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java +@@ -1,5 +1,7 @@ + package net.minecraft.server.network; + ++import com.destroystokyo.paper.network.PaperLegacyStatusClient; ++ + import io.netty.buffer.ByteBuf; + import io.netty.buffer.Unpooled; + import io.netty.channel.ChannelFutureListener; +@@ -46,12 +48,19 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { + MinecraftServer minecraftserver = this.b.d(); + int i = bytebuf.readableBytes(); + String s; +- org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit ++ //org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit // Paper ++ com.destroystokyo.paper.event.server.PaperServerListPingEvent event; // Paper + + switch (i) { + case 0: + LegacyPingHandler.LOGGER.debug("Ping: (<1.3.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); +- s = String.format("%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit ++ // Paper start - Call PaperServerListPingEvent and use results ++ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 39, null); ++ if (event == null) { ++ channelhandlercontext.close(); ++ break; ++ } ++ s = String.format("%s\u00a7%d\u00a7%d", PaperLegacyStatusClient.getUnformattedMotd(event), event.getNumPlayers(), event.getMaxPlayers()); + this.a(channelhandlercontext, this.a(s)); + break; + case 1: +@@ -60,7 +69,14 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { + } + + LegacyPingHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); +- s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit ++ // Paper start - Call PaperServerListPingEvent and use results ++ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 127, null); // Paper ++ if (event == null) { ++ channelhandlercontext.close(); ++ break; ++ } ++ s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", new Object[] { event.getProtocolVersion(), minecraftserver.getVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()}); // CraftBukkit ++ // Paper end + this.a(channelhandlercontext, this.a(s)); + break; + default: +@@ -170,8 +186,16 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { + + LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); + +- String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", +- Byte.MAX_VALUE, server.getVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); ++ InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port); ++ com.destroystokyo.paper.event.server.PaperServerListPingEvent event = PaperLegacyStatusClient.processRequest( ++ server, (InetSocketAddress) ctx.channel().remoteAddress(), protocolVersion, virtualHost); ++ if (event == null) { ++ ctx.close(); ++ return; ++ } ++ ++ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", event.getProtocolVersion(), event.getVersion(), ++ PaperLegacyStatusClient.getMotd(event), event.getNumPlayers(), event.getMaxPlayers()); + this.a(ctx, this.a(response)); + } + diff --git a/patches/server-unmapped/0205-Flag-to-disable-the-channel-limit.patch b/patches/server-unmapped/0205-Flag-to-disable-the-channel-limit.patch new file mode 100644 index 0000000000..96390756fc --- /dev/null +++ b/patches/server-unmapped/0205-Flag-to-disable-the-channel-limit.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 31 Mar 2018 17:04:26 +0100 +Subject: [PATCH] Flag to disable the channel limit + +In some enviroments, the channel limit set by spigot can cause issues, +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 e1d1aaa278287214e2edac5f690d4f5257696ed0..2abd5157b0964fc02994ca7a9317d2fb5539dc1c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -146,6 +146,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + // Paper start + private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; + private String resourcePackHash; ++ private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit + // Paper end + + public CraftPlayer(CraftServer server, EntityPlayer entity) { +@@ -1579,7 +1580,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void addChannel(String channel) { +- Preconditions.checkState(channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); ++ Preconditions.checkState(DISABLE_CHANNEL_LIMIT || channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); // Paper - flag to disable channel limit + channel = StandardMessenger.validateAndCorrectChannel(channel); + if (channels.add(channel)) { + server.getPluginManager().callEvent(new PlayerRegisterChannelEvent(this, channel)); diff --git a/patches/server-unmapped/0206-Add-method-to-open-already-placed-sign.patch b/patches/server-unmapped/0206-Add-method-to-open-already-placed-sign.patch new file mode 100644 index 0000000000..857ab9d50a --- /dev/null +++ b/patches/server-unmapped/0206-Add-method-to-open-already-placed-sign.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 1 Apr 2018 02:29:37 +0300 +Subject: [PATCH] Add method to open already placed sign + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index 893cea754ea1858d2b08ba377bbbc90e7c0efd6d..1333d425147e6dc7f21f755a9b25ead9723d4a28 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -29,6 +29,7 @@ import net.minecraft.world.level.block.BlockEnchantmentTable; + import net.minecraft.world.level.block.BlockWorkbench; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.TileEntity; ++import net.minecraft.world.level.block.entity.TileEntitySign; + import net.minecraft.world.level.block.state.IBlockData; + import org.bukkit.GameMode; + import org.bukkit.Location; +@@ -605,6 +606,17 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + } + } + ++ // Paper start - Add method to open already placed sign ++ @Override ++ public void openSign(org.bukkit.block.Sign sign) { ++ org.apache.commons.lang.Validate.isTrue(sign.getWorld().equals(this.getWorld()), "Sign must be in the same world as player is in"); ++ org.bukkit.craftbukkit.block.CraftSign craftSign = (org.bukkit.craftbukkit.block.CraftSign) sign; ++ TileEntitySign teSign = craftSign.getTileEntity(); ++ // Make sign editable temporarily, will be set back to false in PlayerConnection later ++ teSign.isEditable = true; ++ getHandle().openSign(teSign); ++ } ++ // Paper end + @Override + public boolean dropItem(boolean dropAll) { + return getHandle().dropItem(dropAll); diff --git a/patches/server-unmapped/0207-Configurable-sprint-interruption-on-attack.patch b/patches/server-unmapped/0207-Configurable-sprint-interruption-on-attack.patch new file mode 100644 index 0000000000..99fb21f6e5 --- /dev/null +++ b/patches/server-unmapped/0207-Configurable-sprint-interruption-on-attack.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Sat, 14 Apr 2018 20:20:46 +0200 +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/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 48f0385c7203c7955de5a015f3dc42be2ab7b681..cebf1a623a9bec72d60fdd23dda01868ef6431d4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -358,4 +358,9 @@ public class PaperWorldConfig { + private void squidMaxSpawnHeight() { + squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); + } ++ ++ public boolean disableSprintInterruptionOnAttack; ++ private void disableSprintInterruptionOnAttack() { ++ disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 41dd46c6ef95f7dc41d9ca36a5f0b85f5608fdeb..7839553662d7f1f378969d42fb7a560e489852f4 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -1183,7 +1183,11 @@ public abstract class EntityHuman extends EntityLiving { + } + + this.setMot(this.getMot().d(0.6D, 1.0D, 0.6D)); +- this.setSprinting(false); ++ // Paper start - Configuration option to disable automatic sprint interruption ++ if (!world.paperConfig.disableSprintInterruptionOnAttack) { ++ this.setSprinting(false); ++ } ++ // Paper end + } + + if (flag3) { diff --git a/patches/server-unmapped/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/patches/server-unmapped/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch new file mode 100644 index 0000000000..a63e823a9b --- /dev/null +++ b/patches/server-unmapped/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 0x22 <0x22@futureclient.net> +Date: Thu, 26 Apr 2018 04:41:11 -0400 +Subject: [PATCH] Fix exploit that allowed colored signs to be created + + +diff --git a/src/main/java/net/minecraft/SharedConstants.java b/src/main/java/net/minecraft/SharedConstants.java +index b92975aa85fd79c70d6bec014284e8f55d0d3a4b..d5d6c545182b9b0b6aa5e52f1f9858450a17038e 100644 +--- a/src/main/java/net/minecraft/SharedConstants.java ++++ b/src/main/java/net/minecraft/SharedConstants.java +@@ -20,6 +20,7 @@ public class SharedConstants { + return c0 != 167 && c0 >= ' ' && c0 != 127; + } + ++ public static String filterAllowedChatCharacters(String input) { return a(input); } // Paper - OBFHELPER + public static String a(String s) { + StringBuilder stringbuilder = new StringBuilder(); + char[] achar = s.toCharArray(); +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 1860def3971d1e17429bdde51c2bc336887da233..6c5966901ffdc3c7f9950ff8b40fbf2489acbd4b 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2788,7 +2788,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + List lines = new java.util.ArrayList<>(); + + for (int i = 0; i < list.size(); ++i) { +- lines.add(net.kyori.adventure.text.Component.text(list.get(i))); ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. + } + SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); + this.server.getPluginManager().callEvent(event); diff --git a/patches/server-unmapped/0209-EndermanEscapeEvent.patch b/patches/server-unmapped/0209-EndermanEscapeEvent.patch new file mode 100644 index 0000000000..428f29678a --- /dev/null +++ b/patches/server-unmapped/0209-EndermanEscapeEvent.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 13:15:55 -0400 +Subject: [PATCH] EndermanEscapeEvent + +Fires an event anytime an enderman intends to teleport away from the player + +You may cancel this, enabling ranged attacks to damage the enderman for example. + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index 2de3210bd8988b156b756723d0f781fd92bc151a..b889c1954df39b6180351c418393f5c772702589 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster; + + import java.util.EnumSet; + import java.util.Optional; ++import com.destroystokyo.paper.event.entity.EndermanEscapeEvent; // Paper + import java.util.Random; + import java.util.UUID; + import java.util.function.Predicate; +@@ -109,6 +110,12 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + setGoalTarget(entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, true); + } + ++ // Paper start ++ private boolean tryEscape(EndermanEscapeEvent.Reason reason) { ++ return new EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent(); ++ } ++ // Paper end ++ + @Override + public boolean setGoalTarget(EntityLiving entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { + if (!super.setGoalTarget(entityliving, reason, fireEvent)) { +@@ -262,7 +269,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + if (this.world.isDay() && this.ticksLived >= this.bs + 600) { + float f = this.aR(); + +- if (f > 0.5F && this.world.e(this.getChunkCoordinates()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) { ++ if (f > 0.5F && this.world.e(this.getChunkCoordinates()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper + this.setGoalTarget((EntityLiving) null); + this.eL(); + } +@@ -360,17 +367,19 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + if (this.isInvulnerable(damagesource)) { + return false; + } else if (damagesource instanceof EntityDamageSourceIndirect) { ++ if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start + for (int i = 0; i < 64; ++i) { + if (this.eL()) { + return true; + } + } ++ } // Paper end + + return false; + } else { + boolean flag = super.damageEntity(damagesource, f); + +- if (!this.world.s_() && !(damagesource.getEntity() instanceof EntityLiving) && this.random.nextInt(10) != 0) { ++ if (!this.world.s_() && !(damagesource.getEntity() instanceof EntityLiving) && this.random.nextInt(10) != 0 && this.tryEscape(damagesource == DamageSource.DROWN ? EndermanEscapeEvent.Reason.DROWN : EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - use to be critical hits as else, but mojang removed critical hits in 1.16.2 due to MC-185684 + this.eL(); + } + +@@ -515,7 +524,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + + static class PathfinderGoalPlayerWhoLookedAtTarget extends PathfinderGoalNearestAttackableTarget { + +- private final EntityEnderman i; ++ private final EntityEnderman i; public final EntityEnderman getEnderman() { return this.i; } // Paper - OBFHELPER + private EntityHuman j; + private int k; + private int l; +@@ -578,7 +587,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + } else { + if (this.c != null && !this.i.isPassenger()) { + if (this.i.g((EntityHuman) this.c)) { +- if (this.c.h((Entity) this.i) < 16.0D) { ++ if (this.c.h((Entity) this.i) < 16.0D && this.getEnderman().tryEscape(EndermanEscapeEvent.Reason.STARE)) { // Paper + this.i.eL(); + } + diff --git a/patches/server-unmapped/0210-Enderman.teleportRandomly.patch b/patches/server-unmapped/0210-Enderman.teleportRandomly.patch new file mode 100644 index 0000000000..b64598e139 --- /dev/null +++ b/patches/server-unmapped/0210-Enderman.teleportRandomly.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 13:29:44 -0400 +Subject: [PATCH] Enderman.teleportRandomly() + +Ability to trigger the vanilla "teleport randomly" mechanic of an enderman. + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index b889c1954df39b6180351c418393f5c772702589..ef2f0211cd4d20dad0d3757c38c3c2882e99b2f2 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -278,6 +278,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + super.mobTick(); + } + ++ public final boolean teleportRandomly() { return this.eL(); } // Paper - OBFHELPER + protected boolean eL() { + if (!this.world.s_() && this.isAlive()) { + double d0 = this.locX() + (this.random.nextDouble() - 0.5D) * 64.0D; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java +index 8894d619796c7b81acde9ff27d0f9191122eade4..f54175a4b13ddedc475ef028942edb08eb4ff631 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java +@@ -16,6 +16,7 @@ public class CraftEnderman extends CraftMonster implements Enderman { + super(server, entity); + } + ++ @Override public boolean teleportRandomly() { return getHandle().teleportRandomly(); } // Paper + @Override + public MaterialData getCarriedMaterial() { + IBlockData blockData = getHandle().getCarried(); diff --git a/patches/server-unmapped/0211-Block-Enderpearl-Travel-Exploit.patch b/patches/server-unmapped/0211-Block-Enderpearl-Travel-Exploit.patch new file mode 100644 index 0000000000..38fdf2a105 --- /dev/null +++ b/patches/server-unmapped/0211-Block-Enderpearl-Travel-Exploit.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 30 Apr 2018 17:15:26 -0400 +Subject: [PATCH] Block Enderpearl Travel Exploit + +Players are able to use alt accounts and enderpearls to travel +long distances utilizing the pearls in unloaded chunks and loading +the chunk later when convenient. + +This disables that by not saving the thrower when the chunk is unloaded. + +This is mainly useful for survival servers that do not allow freeform teleporting. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index cebf1a623a9bec72d60fdd23dda01868ef6431d4..e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -363,4 +363,10 @@ public class PaperWorldConfig { + private void disableSprintInterruptionOnAttack() { + disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); + } ++ ++ public boolean disableEnderpearlExploit = true; ++ private void disableEnderpearlExploit() { ++ disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); ++ log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +index 5c9ffd02b4f2977ee13a962a214887f74c91594f..8f14e1ebefe172e056a04bd7b6f55b9bbb1e7b2e 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +@@ -63,6 +63,7 @@ public abstract class IProjectile extends Entity { + protected void loadData(NBTTagCompound nbttagcompound) { + if (nbttagcompound.b("Owner")) { + this.shooter = nbttagcompound.a("Owner"); ++ if (this instanceof EntityEnderPearl && this.world != null && this.world.paperConfig.disableEnderpearlExploit) { this.shooter = null; } // Paper - Don't store shooter name for pearls to block enderpearl travel exploit + } + + this.d = nbttagcompound.getBoolean("LeftOwner"); diff --git a/patches/server-unmapped/0212-Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/server-unmapped/0212-Expand-World.spawnParticle-API-and-add-Builder.patch new file mode 100644 index 0000000000..da5eceecb8 --- /dev/null +++ b/patches/server-unmapped/0212-Expand-World.spawnParticle-API-and-add-Builder.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 15 Aug 2017 22:29:12 -0400 +Subject: [PATCH] Expand World.spawnParticle API and add Builder + +Adds ability to control who receives it and who is the source/sender (vanish API) +the standard API is to send the packet to everyone in the world, which is ineffecient. +Adds an option to control the force mode of the particle. + +This adds a new Builder API which is much friendlier to use. + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 744ec6f09a1b3ccdf0d74fe50f1e1c913ee2df86..b73315df7dae243dd76e44d586dfc1d8f9017a56 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -170,7 +170,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + public final Int2ObjectMap entitiesById = new Int2ObjectLinkedOpenHashMap(); + private final Map entitiesByUUID = Maps.newHashMap(); + private final Queue entitiesToAdd = Queues.newArrayDeque(); +- private final List players = Lists.newArrayList(); ++ public final List players = Lists.newArrayList(); // Paper - private -> public + public final ChunkProviderServer chunkProvider; // Paper - public + boolean tickingEntities; + private final MinecraftServer server; +@@ -1478,12 +1478,17 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + public int sendParticles(EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { ++ // Paper start - Particle API Expansion ++ return sendParticles(players, sender, t0, d0, d1, d2, i, d3, d4, d5, d6, force); ++ } ++ public int sendParticles(List receivers, EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { ++ // Paper end + PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); + // CraftBukkit end + int j = 0; + +- for (int k = 0; k < this.players.size(); ++k) { +- EntityPlayer entityplayer = (EntityPlayer) this.players.get(k); ++ for (EntityHuman entityhuman : receivers) { // Paper - Particle API Expansion ++ EntityPlayer entityplayer = (EntityPlayer) entityhuman; // Paper - Particle API Expansion + if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit + + if (this.a(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index d7d58a0feac2d0b4303c625b7952103613e8c33e..13d3b6accfb86383660a7d0e991519fd930bd518 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2352,11 +2352,17 @@ public class CraftWorld implements World { + + @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) { ++ // Paper start - Particle API Expansion ++ spawnParticle(particle, null, null, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, force); ++ } ++ public void spawnParticle(Particle particle, List receivers, Player sender, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) { ++ // Paper end + if (data != null && !particle.getDataType().isInstance(data)) { + throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); + } + getHandle().sendParticles( +- null, // Sender ++ receivers == null ? getHandle().players : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API Expansion ++ sender != null ? ((CraftPlayer) sender).getHandle() : null, // Sender // Paper - Particle API Expansion + CraftParticle.toNMS(particle, data), // Particle + x, y, z, // Position + count, // Count diff --git a/patches/server-unmapped/0213-EndermanAttackPlayerEvent.patch b/patches/server-unmapped/0213-EndermanAttackPlayerEvent.patch new file mode 100644 index 0000000000..08c3406719 --- /dev/null +++ b/patches/server-unmapped/0213-EndermanAttackPlayerEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 1 May 2018 20:18:54 -0400 +Subject: [PATCH] EndermanAttackPlayerEvent + +Allow control over whether or not an enderman aggros a player. + +This allows you to override/extend the pumpkin/stare logic. + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index ef2f0211cd4d20dad0d3757c38c3c2882e99b2f2..aa6cb15637144c9d8db1b1861e58f3f02d68357a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -221,7 +221,15 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + this.a((WorldServer) this.world, nbttagcompound); + } + ++ // Paper start - OBFHELPER - ok not really, but verify this on updates + private boolean g(EntityHuman entityhuman) { ++ boolean shouldAttack = g_real(entityhuman); ++ com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) entityhuman.getBukkitEntity()); ++ event.setCancelled(!shouldAttack); ++ return event.callEvent(); ++ } ++ private boolean g_real(EntityHuman entityhuman) { ++ // Paper end + ItemStack itemstack = (ItemStack) entityhuman.inventory.armor.get(3); + + if (itemstack.getItem() == Blocks.CARVED_PUMPKIN.getItem()) { diff --git a/patches/server-unmapped/0214-WitchConsumePotionEvent.patch b/patches/server-unmapped/0214-WitchConsumePotionEvent.patch new file mode 100644 index 0000000000..4c85394244 --- /dev/null +++ b/patches/server-unmapped/0214-WitchConsumePotionEvent.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 16 May 2018 20:35:16 -0400 +Subject: [PATCH] WitchConsumePotionEvent + +Fires when a witch consumes the potion in their hand + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java +index 814ef118e983ee6807108b2e07cd9b35ef9dae15..0bfdcbe4a792e8243de86ded6c64d930ec6e4de8 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java +@@ -124,7 +124,11 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { + + this.setSlot(EnumItemSlot.MAINHAND, ItemStack.b); + if (itemstack.getItem() == Items.POTION) { +- List list = PotionUtil.getEffects(itemstack); ++ // Paper start ++ com.destroystokyo.paper.event.entity.WitchConsumePotionEvent event = new com.destroystokyo.paper.event.entity.WitchConsumePotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); ++ ++ List list = event.callEvent() ? PotionUtil.getEffects(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion())) : null; ++ // Paper end + + if (list != null) { + Iterator iterator = list.iterator(); diff --git a/patches/server-unmapped/0215-WitchThrowPotionEvent.patch b/patches/server-unmapped/0215-WitchThrowPotionEvent.patch new file mode 100644 index 0000000000..a9232360d4 --- /dev/null +++ b/patches/server-unmapped/0215-WitchThrowPotionEvent.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 16 May 2018 20:44:58 -0400 +Subject: [PATCH] WitchThrowPotionEvent + +Fired when a witch throws a potion at a player + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java +index 0bfdcbe4a792e8243de86ded6c64d930ec6e4de8..2e65f6107ffecfe00c9c09baa60dec3021aac527 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java +@@ -224,9 +224,16 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { + potionregistry = Potions.WEAKNESS; + } + ++ // Paper start ++ ItemStack potion = PotionUtil.a(new ItemStack(Items.SPLASH_POTION), potionregistry); ++ com.destroystokyo.paper.event.entity.WitchThrowPotionEvent event = new com.destroystokyo.paper.event.entity.WitchThrowPotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++ if (!event.callEvent()) { ++ return; ++ } ++ potion = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion()); + EntityPotion entitypotion = new EntityPotion(this.world, this); +- +- entitypotion.setItem(PotionUtil.a(new ItemStack(Items.SPLASH_POTION), potionregistry)); ++ entitypotion.setItem(potion); ++ // Paper end + entitypotion.pitch -= -20.0F; + entitypotion.shoot(d0, d1 + (double) (f1 * 0.2F), d2, 0.75F, 8.0F); + if (!this.isSilent()) { diff --git a/patches/server-unmapped/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/patches/server-unmapped/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch new file mode 100644 index 0000000000..e6991dda17 --- /dev/null +++ b/patches/server-unmapped/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 4 Jun 2018 20:39:20 -0400 +Subject: [PATCH] Allow spawning Item entities with World.spawnEntity + +This API has more capabilities than .dropItem with the Consumer function + +Item can be set inside of the Consumer pre spawn function. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 13d3b6accfb86383660a7d0e991519fd930bd518..2cc25177110d669e0f425668e26a38794c11c101 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1515,6 +1515,10 @@ public class CraftWorld implements World { + if (Boat.class.isAssignableFrom(clazz)) { + entity = new EntityBoat(world, x, y, z); + entity.setPositionRotation(x, y, z, yaw, pitch); ++ // Paper start ++ } else if (org.bukkit.entity.Item.class.isAssignableFrom(clazz)) { ++ entity = new EntityItem(world, x, y, z, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Item.getItemOf(net.minecraft.world.level.block.Blocks.DIRT))); ++ // Paper end + } else if (FallingBlock.class.isAssignableFrom(clazz)) { + entity = new EntityFallingBlock(world, x, y, z, world.getType(new BlockPosition(x, y, z))); + } else if (Projectile.class.isAssignableFrom(clazz)) { diff --git a/patches/server-unmapped/0217-WitchReadyPotionEvent.patch b/patches/server-unmapped/0217-WitchReadyPotionEvent.patch new file mode 100644 index 0000000000..379b2c1751 --- /dev/null +++ b/patches/server-unmapped/0217-WitchReadyPotionEvent.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Jun 2018 22:47:26 -0400 +Subject: [PATCH] WitchReadyPotionEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java +index 2e65f6107ffecfe00c9c09baa60dec3021aac527..c6d79125e7dd982fc528ce61144005194cbaa323 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java +@@ -157,7 +157,11 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { + } + + if (potionregistry != null) { +- this.setSlot(EnumItemSlot.MAINHAND, PotionUtil.a(new ItemStack(Items.POTION), potionregistry)); ++ // Paper start ++ ItemStack potion = PotionUtil.a(new ItemStack(Items.POTION), potionregistry); ++ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++ this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++ // Paper end + this.bq = this.getItemInMainHand().k(); + this.v(true); + if (!this.isSilent()) { diff --git a/patches/server-unmapped/0218-ItemStack-getMaxItemUseDuration.patch b/patches/server-unmapped/0218-ItemStack-getMaxItemUseDuration.patch new file mode 100644 index 0000000000..e22c07338a --- /dev/null +++ b/patches/server-unmapped/0218-ItemStack-getMaxItemUseDuration.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Jun 2018 23:00:29 -0400 +Subject: [PATCH] ItemStack#getMaxItemUseDuration + +Allows you to determine how long it takes to use a usable/consumable item + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index cac92ccacc9d5ff17c70ee266cf12bacce6242ea..2ac8b6ac38bdca26cddfb8652f13b0be0c4000fe 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -606,6 +606,7 @@ public final class ItemStack { + this.getItem().b(this, world, entityhuman); + } + ++ public int getItemUseMaxDuration() { return k(); } // Paper - OBFHELPER + public int k() { + return this.getItem().e_(this); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index 7221ac52c9f66ae0af6f6cbf15c8d47f9c0291a0..315addab147dfecf4aa88d32d154cefe850d0a78 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -174,6 +174,13 @@ public final class CraftItemStack extends ItemStack { + return (handle == null) ? Material.AIR.getMaxStackSize() : handle.getItem().getMaxStackSize(); + } + ++ // Paper start ++ @Override ++ public int getMaxItemUseDuration() { ++ return handle == null ? 0 : handle.getItemUseMaxDuration(); ++ } ++ // Paper end ++ + @Override + public void addUnsafeEnchantment(Enchantment ench, int level) { + Validate.notNull(ench, "Cannot add null enchantment"); diff --git a/patches/server-unmapped/0219-Implement-EntityTeleportEndGatewayEvent.patch b/patches/server-unmapped/0219-Implement-EntityTeleportEndGatewayEvent.patch new file mode 100644 index 0000000000..188e408423 --- /dev/null +++ b/patches/server-unmapped/0219-Implement-EntityTeleportEndGatewayEvent.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 9 Jun 2018 14:08:39 +0200 +Subject: [PATCH] Implement EntityTeleportEndGatewayEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java +index 2808cd0b100bd65a730aba315ab47a59a4621b30..b7548d0b3938d95328fc86db4000190532eaa8f5 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java +@@ -194,9 +194,20 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick + + } + // CraftBukkit end ++ // Paper start - EntityTeleportEndGatewayEvent - replicated from above ++ org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity = entity.getBukkitEntity(); ++ org.bukkit.Location location = new Location(world.getWorld(), (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); ++ location.setPitch(bukkitEntity.getLocation().getPitch()); ++ location.setYaw(bukkitEntity.getLocation().getYaw()); ++ ++ com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent event = new com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent(bukkitEntity, bukkitEntity.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(world, this.getPosition()).getBlock())); ++ if (!event.callEvent()) { ++ return; ++ } ++ // Paper end + + entity1.resetPortalCooldown(); +- entity1.enderTeleportAndLoad((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D); ++ entity1.enderTeleportAndLoad(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); // Paper + } + + this.h(); diff --git a/patches/server-unmapped/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/patches/server-unmapped/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch new file mode 100644 index 0000000000..72ccc51e06 --- /dev/null +++ b/patches/server-unmapped/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 Jun 2018 01:18:49 -0400 +Subject: [PATCH] Unset Ignited flag on cancel of Explosion Event + +Otherwise the creeper infinite explodes + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +index 08292753f925f33d75f3aca835c1fd19494b22ec..cbb973e077e04e5221bcc837f434b7093bdbcc2a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +@@ -48,7 +48,7 @@ public class EntityCreeper extends EntityMonster { + + private static final DataWatcherObject b = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.b); + private static final DataWatcherObject POWERED = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.i); +- private static final DataWatcherObject d = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.i); ++ private static final DataWatcherObject d = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.i); private static final DataWatcherObject isIgnitedDW = d; // Paper OBFHELPER + private int bo; + public int fuseTicks; // PAIL + public int maxFuseTicks = 30; +@@ -253,6 +253,7 @@ public class EntityCreeper extends EntityMonster { + this.createEffectCloud(); + } else { + fuseTicks = 0; ++ this.datawatcher.set(isIgnitedDW, Boolean.valueOf(false)); // Paper + } + // CraftBukkit end + } diff --git a/patches/server-unmapped/0221-Fix-CraftEntity-hashCode.patch b/patches/server-unmapped/0221-Fix-CraftEntity-hashCode.patch new file mode 100644 index 0000000000..bb0a09f3ce --- /dev/null +++ b/patches/server-unmapped/0221-Fix-CraftEntity-hashCode.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 Jun 2018 20:20:15 -0400 +Subject: [PATCH] Fix CraftEntity hashCode + +hashCodes are not allowed to change, however bukkit used a value +that does change, the entityId. + +When an entity is teleported dimensions, the entity reference is +replaced with a new one with a new entity ID. + +For hashCode, we can simply use the UUID's hashCode to keep +the hashCode from changing. + +equals() is ok to use getEntityId() because equals() should only +be true if both the left and right are the same reference. + +Since entity ids can not duplicate during runtime, this +check is essentially the same as this.getHandle() == other.getHandle() + +However, replaced it too to make it clearer of intent. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 4c2a35fb33da19a15a220dc5e0c9fa3233d657fb..3642b17cafffd2818ee7a18d26bc25645f596115 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -745,14 +745,15 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return false; + } + final CraftEntity other = (CraftEntity) obj; +- return (this.getEntityId() == other.getEntityId()); ++ return (this.getHandle() == other.getHandle()); // Paper - while logically the same, this is clearer + } + ++ // Paper - Fix hashCode. entity ID's are not static. ++ // A CraftEntity can change reference to a new entity with a new ID, and hash codes should never change + @Override + public int hashCode() { +- int hash = 7; +- hash = 29 * hash + this.getEntityId(); +- return hash; ++ return getUniqueId().hashCode(); ++ // Paper end + } + + @Override diff --git a/patches/server-unmapped/0222-Configurable-Alternative-LootPool-Luck-Formula.patch b/patches/server-unmapped/0222-Configurable-Alternative-LootPool-Luck-Formula.patch new file mode 100644 index 0000000000..e0ee8431f3 --- /dev/null +++ b/patches/server-unmapped/0222-Configurable-Alternative-LootPool-Luck-Formula.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 15 Jun 2018 00:30:32 -0400 +Subject: [PATCH] Configurable Alternative LootPool Luck Formula + +Rewrites the Vanilla luck application formula so that luck can be +applied to items that do not have any quality defined. + +See: https://luckformula.emc.gs for data and details +----------- + +The rough summary is: +My goal was that in a pool, when luck was applied, the pool +rebalances so the percentages for bigger items is +lowered and smaller items is boosted. + +Do this by boosting and then reducing the weight value, +so that larger numbers are penalized more than smaller numbers. +resulting in a larger reduction of entries for more common +items than the reduction on small weights, +giving smaller weights more of a chance + +----------- + +This work kind of obsoletes quality, but quality would be useful +for 2 items with same weight that you want luck to impact +in varying directions. + +Fishing still falls into that as the weights are closer, so luck +will invalidate junk more. + +This change will result in some major changes to fishing formulas. + +----------- + +I would love to see this change in Vanilla, so Mojang please pull :) + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 05a5abb951abe37f30a719cb75376d2d43c0d252..77a03abd59db4a43f6f2d59d4c7ef176e782f205 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -288,4 +288,12 @@ public class PaperConfig { + SpigotConfig.save(); + } + } ++ ++ public static boolean useAlternativeLuckFormula = false; ++ private static void useAlternativeLuckFormula() { ++ useAlternativeLuckFormula = getBoolean("settings.use-alternative-luck-formula", false); ++ if (useAlternativeLuckFormula) { ++ Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java +index ceb9a1e1b1d55a0a8cd74189450f356b9ad4c46c..632002c4db01ca3f3c19aa583226cf36f17afe7f 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java +@@ -20,8 +20,8 @@ import org.apache.commons.lang3.ArrayUtils; + + public abstract class LootSelectorEntry extends LootEntryAbstract { + +- protected final int c; +- protected final int e; ++ protected final int c; public int getWeight() { return c; } // Paper - OBFHELPER ++ protected final int e; public int getQuality() { return e; } // Paper - OBFHELPER + protected final LootItemFunction[] f; + private final BiFunction g; + private final LootEntry h = new LootSelectorEntry.c() { +@@ -152,11 +152,38 @@ public abstract class LootSelectorEntry extends LootEntryAbstract { + + public abstract class c implements LootEntry { + +- protected c() {} ++ protected c() { ++ } + + @Override + public int a(float f) { +- return Math.max(MathHelper.d((float) LootSelectorEntry.this.c + (float) LootSelectorEntry.this.e * f), 0); ++ // Paper start - Offer an alternative loot formula to refactor how luck bonus applies ++ // SEE: https://luckformula.emc.gs for details and data ++ if (lastLuck != null && lastLuck == f) { ++ return lastWeight; ++ } ++ // This is vanilla ++ float qualityModifer = (float) getQuality() * f; ++ double baseWeight = (getWeight() + qualityModifer); ++ if (com.destroystokyo.paper.PaperConfig.useAlternativeLuckFormula) { ++ // Random boost to avoid losing precision in the final int cast on return ++ final int weightBoost = 100; ++ baseWeight *= weightBoost; ++ // If we have vanilla 1, bump that down to 0 so nothing is is impacted ++ // vanilla 3 = 300, 200 basis = impact 2% ++ // =($B2*(($B2-100)/100/100)) ++ double impacted = baseWeight * ((baseWeight - weightBoost) / weightBoost / 100); ++ // =($B$7/100) ++ float luckModifier = Math.min(100, f * 10) / 100; ++ // =B2 - (C2 *($B$7/100)) ++ baseWeight = Math.ceil(baseWeight - (impacted * luckModifier)); ++ } ++ lastLuck = f; ++ lastWeight = (int) Math.max(0, Math.floor(baseWeight)); ++ return lastWeight; + } + } ++ private Float lastLuck = null; ++ private int lastWeight = 0; ++ // Paper end + } diff --git a/patches/server-unmapped/0223-Print-Error-details-when-failing-to-save-player-data.patch b/patches/server-unmapped/0223-Print-Error-details-when-failing-to-save-player-data.patch new file mode 100644 index 0000000000..de373f15f0 --- /dev/null +++ b/patches/server-unmapped/0223-Print-Error-details-when-failing-to-save-player-data.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 15 Jun 2018 20:37:03 -0400 +Subject: [PATCH] Print Error details when failing to save player data + + +diff --git a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java +index 191c9e9a00b9871038f60d54bc22620322f6bdbd..4d30ca69dd303f1d76c8e6292021deda97851773 100644 +--- a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java +@@ -43,7 +43,7 @@ public class WorldNBTStorage { + + SystemUtils.a(file1, file, file2); + } catch (Exception exception) { +- WorldNBTStorage.LOGGER.warn("Failed to save player data for {}", entityhuman.getDisplayName().getString()); ++ WorldNBTStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getName(), exception); // Paper + } + + } diff --git a/patches/server-unmapped/0224-Make-shield-blocking-delay-configurable.patch b/patches/server-unmapped/0224-Make-shield-blocking-delay-configurable.patch new file mode 100644 index 0000000000..ceedc3c799 --- /dev/null +++ b/patches/server-unmapped/0224-Make-shield-blocking-delay-configurable.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 16 Jun 2018 01:18:16 -0500 +Subject: [PATCH] Make shield blocking delay configurable + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec..3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -369,4 +369,9 @@ public class PaperWorldConfig { + disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); + log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); + } ++ ++ public int shieldBlockingDelay = 5; ++ private void shieldBlockingDelay() { ++ shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 91be4df855a0a249518f0b562d05d9647169aa92..b776b14a62919fdfe86095c5eb6dfd039486b4a7 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -3311,7 +3311,7 @@ public abstract class EntityLiving extends Entity { + if (this.isHandRaised() && !this.activeItem.isEmpty()) { + Item item = this.activeItem.getItem(); + +- return item.d_(this.activeItem) != EnumAnimation.BLOCK ? false : item.e_(this.activeItem) - this.bd >= 5; ++ return item.d_(this.activeItem) != EnumAnimation.BLOCK ? false : item.e_(this.activeItem) - this.bd >= getShieldBlockingDelay(); // Paper - shieldBlockingDelay + } else { + return false; + } +@@ -3590,4 +3590,15 @@ public abstract class EntityLiving extends Entity { + public void broadcastItemBreak(EnumHand enumhand) { + this.broadcastItemBreak(enumhand == EnumHand.MAIN_HAND ? EnumItemSlot.MAINHAND : EnumItemSlot.OFFHAND); + } ++ // Paper start ++ public int shieldBlockingDelay = world.paperConfig.shieldBlockingDelay; ++ ++ public int getShieldBlockingDelay() { ++ return shieldBlockingDelay; ++ } ++ ++ public void setShieldBlockingDelay(int shieldBlockingDelay) { ++ this.shieldBlockingDelay = shieldBlockingDelay; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index c43c300963bae9bca6ab9c9389dd53e42318715c..2d1c54eed8fa6885837d63014ff1f4b33dd35bd7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -711,5 +711,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setArrowsStuck(int arrows) { + getHandle().setArrowCount(arrows); + } ++ ++ @Override ++ public int getShieldBlockingDelay() { ++ return getHandle().getShieldBlockingDelay(); ++ } ++ ++ @Override ++ public void setShieldBlockingDelay(int delay) { ++ getHandle().setShieldBlockingDelay(delay); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0225-Improve-EntityShootBowEvent.patch b/patches/server-unmapped/0225-Improve-EntityShootBowEvent.patch new file mode 100644 index 0000000000..4d145bf944 --- /dev/null +++ b/patches/server-unmapped/0225-Improve-EntityShootBowEvent.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 15 Jun 2013 19:51:17 -0400 +Subject: [PATCH] Improve EntityShootBowEvent + +Adds missing call to Illagers and also adds Arrow ItemStack to skeltons + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java +index 54a4a295660375a0fcc54e02d80d569d9a32e73e..fee9a5140f097225b5da58b18bfbd528dffdc77b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java +@@ -171,8 +171,18 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan + double d3 = (double) MathHelper.sqrt(d0 * d0 + d2 * d2); + + entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.world.getDifficulty().a() * 4)); ++ // Paper start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), entityarrow.getOriginalItemStack(), entityarrow, entityliving.getRaisedHand(), 0.8F, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ this.world.addEntity(entityarrow); ++ } + this.playSound(SoundEffects.ENTITY_SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.world.addEntity(entityarrow); ++ // Paper end + } + + class a extends EntityIllagerWizard.PathfinderGoalCastSpell { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java +index a2a67bccf38464731670e98cb155348df94474c5..4dca5ea9127c15b2739483b2ad74a5296a6b96ad 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java +@@ -197,7 +197,7 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR + + entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.world.getDifficulty().a() * 4)); + // CraftBukkit start +- org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), null, entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), entityarrow.getOriginalItemStack(), entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); // Paper + if (event.isCancelled()) { + event.getProjectile().remove(); + return; diff --git a/patches/server-unmapped/0226-PlayerReadyArrowEvent.patch b/patches/server-unmapped/0226-PlayerReadyArrowEvent.patch new file mode 100644 index 0000000000..48c889f719 --- /dev/null +++ b/patches/server-unmapped/0226-PlayerReadyArrowEvent.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 18 Jun 2018 01:12:53 -0400 +Subject: [PATCH] PlayerReadyArrowEvent + +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/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 7839553662d7f1f378969d42fb7a560e489852f4..408732c59ed817c056671a78e43a734b048a818e 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -2142,6 +2142,17 @@ public abstract class EntityHuman extends EntityLiving { + return ImmutableList.of(EntityPose.STANDING, EntityPose.CROUCHING, EntityPose.SWIMMING); + } + ++ // Paper start ++ protected boolean tryReadyArrow(ItemStack bow, ItemStack itemstack) { ++ return !(this instanceof EntityPlayer) || ++ new com.destroystokyo.paper.event.player.PlayerReadyArrowEvent( ++ ((EntityPlayer) this).getBukkitEntity(), ++ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(bow), ++ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack) ++ ).callEvent(); ++ // Paper end ++ } ++ + @Override + public ItemStack f(ItemStack itemstack) { + if (!(itemstack.getItem() instanceof ItemProjectileWeapon)) { +@@ -2158,7 +2169,7 @@ public abstract class EntityHuman extends EntityLiving { + for (int i = 0; i < this.inventory.getSize(); ++i) { + ItemStack itemstack2 = this.inventory.getItem(i); + +- if (predicate.test(itemstack2)) { ++ if (predicate.test(itemstack2) && tryReadyArrow(itemstack, itemstack2)) { // Paper + return itemstack2; + } + } diff --git a/patches/server-unmapped/0227-Implement-EntityKnockbackByEntityEvent.patch b/patches/server-unmapped/0227-Implement-EntityKnockbackByEntityEvent.patch new file mode 100644 index 0000000000..0a66bfbf73 --- /dev/null +++ b/patches/server-unmapped/0227-Implement-EntityKnockbackByEntityEvent.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Mon, 18 Jun 2018 15:46:23 +0200 +Subject: [PATCH] Implement EntityKnockbackByEntityEvent + +This event is called when an entity receives knockback by another entity. + +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index 2cc15ac22000343dc540454ba971993bf5b2f5a3..e177483dace853ccd01d410fc7deea17663e9a3d 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -1568,7 +1568,7 @@ public abstract class EntityInsentient extends EntityLiving { + + if (flag) { + if (f1 > 0.0F && entity instanceof EntityLiving) { +- ((EntityLiving) entity).a(f1 * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F))); ++ ((EntityLiving) entity).doKnockback(f1 * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F)), this); // Paper + this.setMot(this.getMot().d(0.6D, 1.0D, 0.6D)); + } + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index b776b14a62919fdfe86095c5eb6dfd039486b4a7..daf09f3f0e6be57f540641d70e9c944de7fe6622 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -1339,7 +1339,7 @@ public abstract class EntityLiving extends Entity { + } + + this.ap = (float) (MathHelper.d(d1, d0) * 57.2957763671875D - (double) this.yaw); +- this.a(0.4F, d0, d1); ++ this.doKnockback(0.4F, d0, d1, entity1); // Paper + } else { + this.ap = (float) ((int) (Math.random() * 2.0D) * 180); + } +@@ -1387,7 +1387,7 @@ public abstract class EntityLiving extends Entity { + } + + protected void e(EntityLiving entityliving) { +- entityliving.a(0.5F, entityliving.locX() - this.locX(), entityliving.locZ() - this.locZ()); ++ entityliving.doKnockback(0.5F, entityliving.locX() - this.locX(), entityliving.locZ() - this.locZ(), this); // Paper + } + + private boolean f(DamageSource damagesource) { +@@ -1630,6 +1630,11 @@ public abstract class EntityLiving extends Entity { + } + + public void a(float f, double d0, double d1) { ++ // Paper start - add knockbacking entity parameter ++ this.doKnockback(f, d0, d1, null); ++ } ++ public void doKnockback(float f, double d0, double d1, Entity knockingBackEntity) { ++ // Paper end - add knockbacking entity parameter + f = (float) ((double) f * (1.0D - this.b(GenericAttributes.KNOCKBACK_RESISTANCE))); + if (f > 0.0F) { + this.impulse = true; +@@ -1637,6 +1642,16 @@ public abstract class EntityLiving extends Entity { + Vec3D vec3d1 = (new Vec3D(d0, 0.0D, d1)).d().a((double) f); + + this.setMot(vec3d.x / 2.0D - vec3d1.x, this.onGround ? Math.min(0.4D, vec3d.y / 2.0D + (double) f) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); ++ ++ // Paper start - call EntityKnockbackByEntityEvent ++ Vec3D currentMot = this.getMot(); ++ org.bukkit.util.Vector delta = new org.bukkit.util.Vector(currentMot.x - vec3d.x, currentMot.y - vec3d.y, currentMot.z - vec3d.z); ++ // Restore old velocity to be able to access it in the event ++ this.setMot(vec3d); ++ if (knockingBackEntity == null || new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent((LivingEntity) getBukkitEntity(), knockingBackEntity.getBukkitEntity(), f, delta).callEvent()) { ++ this.setMot(vec3d.x + delta.getX(), vec3d.y + delta.getY(), vec3d.z + delta.getZ()); ++ } ++ // Paper end + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 408732c59ed817c056671a78e43a734b048a818e..3c49d7acd4ad0717886adf6c469e8a49a58e859b 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -1177,7 +1177,7 @@ public abstract class EntityHuman extends EntityLiving { + if (flag5) { + if (i > 0) { + if (entity instanceof EntityLiving) { +- ((EntityLiving) entity).a((float) i * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F))); ++ ((EntityLiving) entity).doKnockback((float) i * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F)), this); // Paper + } else { + entity.i((double) (-MathHelper.sin(this.yaw * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (MathHelper.cos(this.yaw * 0.017453292F) * (float) i * 0.5F)); + } +@@ -1201,7 +1201,7 @@ public abstract class EntityHuman extends EntityLiving { + if (entityliving != this && entityliving != entity && !this.r(entityliving) && (!(entityliving instanceof EntityArmorStand) || !((EntityArmorStand) entityliving).isMarker()) && this.h((Entity) entityliving) < 9.0D) { + // CraftBukkit start - Only apply knockback if the damage hits + if (entityliving.damageEntity(DamageSource.playerAttack(this).sweep(), f4)) { +- entityliving.a(0.4F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F))); ++ entityliving.doKnockback(0.4F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F)), this); // Paper + } + // CraftBukkit end + } diff --git a/patches/server-unmapped/0228-Expand-Explosions-API.patch b/patches/server-unmapped/0228-Expand-Explosions-API.patch new file mode 100644 index 0000000000..2dcb0871e7 --- /dev/null +++ b/patches/server-unmapped/0228-Expand-Explosions-API.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 20 Jun 2018 23:17:24 -0400 +Subject: [PATCH] Expand Explosions API + +Add Entity as a Source capability, and add more API choices, and on Location. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 2cc25177110d669e0f425668e26a38794c11c101..1fce5548544f00fd79839a23e05ec5690f6f0621 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -889,6 +889,11 @@ public class CraftWorld implements World { + public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) { + return !world.createExplosion(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, breakBlocks ? Explosion.Effect.BREAK : Explosion.Effect.NONE).wasCanceled; + } ++ // Paper start ++ public boolean createExplosion(Entity source, Location loc, float power, boolean setFire, boolean breakBlocks) { ++ return !world.createExplosion(source != null ? ((org.bukkit.craftbukkit.entity.CraftEntity) source).getHandle() : null, loc.getX(), loc.getY(), loc.getZ(), power, setFire, breakBlocks ? Explosion.Effect.BREAK : Explosion.Effect.NONE).wasCanceled; ++ } ++ // Paper end + + @Override + public boolean createExplosion(Location loc, float power) { diff --git a/patches/server-unmapped/0229-LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/server-unmapped/0229-LivingEntity-Hand-Raised-Item-Use-API.patch new file mode 100644 index 0000000000..7ef5cf4e29 --- /dev/null +++ b/patches/server-unmapped/0229-LivingEntity-Hand-Raised-Item-Use-API.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 Jun 2018 00:21:28 -0400 +Subject: [PATCH] LivingEntity Hand Raised/Item Use API + +How long an entity has raised hands to charge an attack or use an item + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index daf09f3f0e6be57f540641d70e9c944de7fe6622..a530f13526ef1ee947adb22e24d5c9afb705a01d 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -212,7 +212,7 @@ public abstract class EntityLiving extends Entity { + private float bu; + private int jumpTicks; + private float bw; +- protected ItemStack activeItem; ++ public ItemStack activeItem; // Paper - public + protected int bd; + protected int be; + private BlockPosition bx; +@@ -3294,10 +3294,12 @@ public abstract class EntityLiving extends Entity { + return this.activeItem; + } + ++ public int getItemUseRemainingTime() { return this.dZ(); } // Paper - OBFHELPER + public int dZ() { + return this.bd; + } + ++ public int getHandRaisedTime() { return this.ea(); } // Paper - OBFHELPER + public int ea() { + return this.isHandRaised() ? this.activeItem.k() - this.dZ() : 0; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 2d1c54eed8fa6885837d63014ff1f4b33dd35bd7..a0b006f24829ff9f5754293fbe389d19a14dc001 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -721,5 +721,30 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setShieldBlockingDelay(int delay) { + getHandle().setShieldBlockingDelay(delay); + } ++ ++ @Override ++ public ItemStack getActiveItem() { ++ return getHandle().activeItem.asBukkitMirror(); ++ } ++ ++ @Override ++ public int getItemUseRemainingTime() { ++ return getHandle().getItemUseRemainingTime(); ++ } ++ ++ @Override ++ public int getHandRaisedTime() { ++ return getHandle().getHandRaisedTime(); ++ } ++ ++ @Override ++ public boolean isHandRaised() { ++ return getHandle().isHandRaised(); ++ } ++ ++ @Override ++ public org.bukkit.inventory.EquipmentSlot getHandRaised() { ++ return getHandle().getRaisedHand() == net.minecraft.world.EnumHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; ++ } + // Paper end + } diff --git a/patches/server-unmapped/0230-RangedEntity-API.patch b/patches/server-unmapped/0230-RangedEntity-API.patch new file mode 100644 index 0000000000..e8c055fe8b --- /dev/null +++ b/patches/server-unmapped/0230-RangedEntity-API.patch @@ -0,0 +1,171 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 26 Jun 2018 22:00:49 -0400 +Subject: [PATCH] RangedEntity API + +Allows you to determine if an entity is capable of ranged attacks, +and to perform an attack. + +diff --git a/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0195d4036f06db0f3f56f134dbfbc4360d44ed86 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java +@@ -0,0 +1,19 @@ ++package com.destroystokyo.paper.entity; ++ ++import net.minecraft.world.entity.monster.IRangedEntity; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.LivingEntity; ++ ++public interface CraftRangedEntity extends RangedEntity { ++ T getHandle(); ++ ++ @Override ++ default void rangedAttack(LivingEntity target, float charge) { ++ getHandle().rangedAttack(((CraftLivingEntity) target).getHandle(), charge); ++ } ++ ++ @Override ++ default void setChargingAttack(boolean raiseHands) { ++ getHandle().setChargingAttack(raiseHands); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java b/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java +index d79e6b28c77edc468c6471d909306c2135b496c7..0f0aaa8a15301dea8405e26333d30b385831506c 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java ++++ b/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java +@@ -4,5 +4,8 @@ import net.minecraft.world.entity.EntityLiving; + + public interface IRangedEntity { + +- void a(EntityLiving entityliving, float f); ++ void a(EntityLiving entityliving, float f); default void rangedAttack(EntityLiving entityliving, float f) { a(entityliving, f); } // Paper - OBFHELPER ++ ++ // - see EntitySkeletonAbstract melee goal ++ void setAggressive(boolean flag); default void setChargingAttack(boolean charging) { setAggressive(charging); }; // Paper + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java +index 3bb39dae11847bea1330ef68f53c90309fd2a095..bba2e3fba5b225e90744e78df085b3c318a029ce 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java +@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.Drowned; + import org.bukkit.entity.EntityType; + +-public class CraftDrowned extends CraftZombie implements Drowned { ++public class CraftDrowned extends CraftZombie implements Drowned, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftDrowned(CraftServer server, EntityDrowned entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java +index 0dabb012b37b6dda58368765b220b7d0aaf8e2d4..3763fb13920c98bb7cd250883ec89cdd1805dbd6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java +@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Illusioner; + +-public class CraftIllusioner extends CraftSpellcaster implements Illusioner { ++public class CraftIllusioner extends CraftSpellcaster implements Illusioner, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftIllusioner(CraftServer server, EntityIllagerIllusioner entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java +index 6dcf196fd83f2175a5d34c8d138d923c32ddb899..818034c62893a71808e3af0aa33393605611acdd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import com.destroystokyo.paper.entity.CraftRangedEntity; + import com.google.common.base.Preconditions; + import net.minecraft.world.entity.animal.horse.EntityLlama; + import org.bukkit.craftbukkit.CraftServer; +@@ -10,7 +11,7 @@ import org.bukkit.entity.Llama; + import org.bukkit.entity.Llama.Color; + import org.bukkit.inventory.LlamaInventory; + +-public class CraftLlama extends CraftChestedHorse implements Llama { ++public class CraftLlama extends CraftChestedHorse implements Llama, CraftRangedEntity { // Paper + + public CraftLlama(CraftServer server, EntityLlama entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java +index 0327f3d9e1f4f9078ad7838bc03c63d2cff35f9b..45239f1b0c654a7b8450d03189b5b935771598ad 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java +@@ -14,7 +14,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.Piglin; + import org.bukkit.inventory.Inventory; + +-public class CraftPiglin extends CraftPiglinAbstract implements Piglin { ++public class CraftPiglin extends CraftPiglinAbstract implements Piglin, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftPiglin(CraftServer server, EntityPiglin entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java +index 72ac9eae71028a40541f949d617ce326c00c6369..87eeb5b632b581dca7613973bc9a25f152839a33 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java +@@ -7,7 +7,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.Pillager; + import org.bukkit.inventory.Inventory; + +-public class CraftPillager extends CraftIllager implements Pillager { ++public class CraftPillager extends CraftIllager implements Pillager, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftPillager(CraftServer server, EntityPillager entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +index cebb90fd4a84c0a97d7493a6923d16d0c4215f5e..c2acfa2cc27a187154e17b7f45908682b41b52af 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +@@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; + import org.bukkit.entity.Skeleton; + import org.bukkit.entity.Skeleton.SkeletonType; + +-public class CraftSkeleton extends CraftMonster implements Skeleton { ++public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + public CraftSkeleton(CraftServer server, EntitySkeletonAbstract entity) { + super(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java +index 5720bdf64eadec1ebe1a2253e2b537ca299ffa6d..a262cf88eefca2767eb6e5da856626be34352ccd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java +@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Snowman; + +-public class CraftSnowman extends CraftGolem implements Snowman { ++public class CraftSnowman extends CraftGolem implements Snowman, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftSnowman(CraftServer server, EntitySnowman entity) { + super(server, entity); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +index 796bd26d41b52941c38d81411688116af7053535..9cc34cdb43596eff34625045f884b93da3f27ab6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Witch; + +-public class CraftWitch extends CraftRaider implements Witch { ++public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftWitch(CraftServer server, EntityWitch entity) { + super(server, entity); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +index 7150702d8dac0d9db44661b1b17f520302988b45..1d94aeec37dcb9758d88ef25a5cad1333bbfbf6c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +@@ -7,7 +7,7 @@ import org.bukkit.craftbukkit.boss.CraftBossBar; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Wither; + +-public class CraftWither extends CraftMonster implements Wither { ++public class CraftWither extends CraftMonster implements Wither, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + + private BossBar bossBar; + diff --git a/patches/server-unmapped/0231-Add-config-to-disable-ender-dragon-legacy-check.patch b/patches/server-unmapped/0231-Add-config-to-disable-ender-dragon-legacy-check.patch new file mode 100644 index 0000000000..153410f43a --- /dev/null +++ b/patches/server-unmapped/0231-Add-config-to-disable-ender-dragon-legacy-check.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 22 Jun 2018 10:38:31 -0500 +Subject: [PATCH] Add config to disable ender dragon legacy check + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77..4813f62d1e382d5ac6971b2244df3f13c80d1950 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -374,4 +374,9 @@ public class PaperWorldConfig { + private void shieldBlockingDelay() { + shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); + } ++ ++ public boolean scanForLegacyEnderDragon = true; ++ private void scanForLegacyEnderDragon() { ++ scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +index f727cc456bd23816c4e70be83c395d1d8ca7d876..0869af4670f040344f5b6c2c10bff5e5226f707c 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +@@ -73,7 +73,7 @@ public class EnderDragonBattle { + private boolean dragonKilled; + private boolean previouslyKilled; + public UUID dragonUUID; +- private boolean n; ++ private boolean n; private void setScanForLegacyFight(boolean scanForLegacyFight) { this.n = scanForLegacyFight; } private boolean scanForLegacyFight() { return this.n; } // Paper - OBFHELPER + public BlockPosition exitPortalLocation; + public EnumDragonRespawn respawnPhase; + private int q; +@@ -83,6 +83,10 @@ public class EnderDragonBattle { + this.bossBattle = (BossBattleServer) (new BossBattleServer(new ChatMessage("entity.minecraft.ender_dragon"), BossBattle.BarColor.PINK, BossBattle.BarStyle.PROGRESS)).setPlayMusic(true).c(true); + this.gateways = Lists.newArrayList(); + this.n = true; ++ // Paper start ++ setScanForLegacyFight(worldserver.paperConfig.scanForLegacyEnderDragon); ++ if (!scanForLegacyFight()) dragonKilled = true; ++ // Paper end + this.world = worldserver; + if (nbttagcompound.hasKeyOfType("DragonKilled", 99)) { + if (nbttagcompound.b("Dragon")) { diff --git a/patches/server-unmapped/0232-Implement-World.getEntity-UUID-API.patch b/patches/server-unmapped/0232-Implement-World.getEntity-UUID-API.patch new file mode 100644 index 0000000000..8856ce729b --- /dev/null +++ b/patches/server-unmapped/0232-Implement-World.getEntity-UUID-API.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Tue, 3 Jul 2018 16:08:14 +0200 +Subject: [PATCH] Implement World.getEntity(UUID) API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 1fce5548544f00fd79839a23e05ec5690f6f0621..a2b3f5106edc8328ba7edd65dedd56e0dc8d33d2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1304,6 +1304,15 @@ public class CraftWorld implements World { + return list; + } + ++ // Paper start - getEntity by UUID API ++ @Override ++ public Entity getEntity(UUID uuid) { ++ Validate.notNull(uuid, "UUID cannot be null"); ++ net.minecraft.world.entity.Entity entity = world.getEntity(uuid); ++ return entity == null ? null : entity.getBukkitEntity(); ++ } ++ // Paper end ++ + @Override + public void save() { + org.spigotmc.AsyncCatcher.catchOp("world save"); // Spigot diff --git a/patches/server-unmapped/0233-InventoryCloseEvent-Reason-API.patch b/patches/server-unmapped/0233-InventoryCloseEvent-Reason-API.patch new file mode 100644 index 0000000000..3a779bd68c --- /dev/null +++ b/patches/server-unmapped/0233-InventoryCloseEvent-Reason-API.patch @@ -0,0 +1,227 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 3 Jul 2018 21:56:23 -0400 +Subject: [PATCH] InventoryCloseEvent Reason API + +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/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index de7167ddf7b36ef266e511187789f99244401c21..b581a6d3ec06498a4c6db92eb50c5d2b28038131 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -547,7 +547,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + // Paper end + if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { +- this.closeInventory(); ++ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.activeContainer = this.defaultContainer; + } + +@@ -720,7 +720,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + // SPIGOT-943 - only call if they have an inventory open + if (this.activeContainer != this.defaultContainer) { +- this.closeInventory(); ++ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DEATH); // Paper + } + + net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure +@@ -1293,7 +1293,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + return OptionalInt.empty(); + } else { + if (this.activeContainer != this.defaultContainer) { +- this.closeInventory(); ++ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + this.nextContainerCounter(); +@@ -1353,7 +1353,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + // CraftBukkit end + if (this.activeContainer != this.defaultContainer) { +- this.closeInventory(); ++ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + // this.nextContainerCounter(); // CraftBukkit - moved up +@@ -1417,7 +1417,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + @Override + public void closeInventory() { +- CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit ++ // Paper start ++ closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); ++ } ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit ++ // Paper end + this.playerConnection.sendPacket(new PacketPlayOutCloseWindow(this.activeContainer.windowId)); + this.o(); + } +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index b73315df7dae243dd76e44d586dfc1d8f9017a56..eb19b6fc87bfd4e500ea7836c1010a80b36abab2 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1125,7 +1125,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + for (TileEntity tileentity : chunk.getTileEntities().values()) { + if (tileentity instanceof net.minecraft.world.IInventory) { + for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((net.minecraft.world.IInventory) tileentity).getViewers())) { +- h.closeInventory(); ++ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper + } + } + } +@@ -1183,7 +1183,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + // Spigot Start + if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder) { + for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) { +- h.closeInventory(); ++ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper + } + } + // Spigot End +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 6c5966901ffdc3c7f9950ff8b40fbf2489acbd4b..2a1ad096515247382da741fbcdc84f6d5b1001c5 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -190,6 +190,7 @@ import org.bukkit.event.inventory.ClickType; + import org.bukkit.event.inventory.CraftItemEvent; + import org.bukkit.event.inventory.InventoryAction; + import org.bukkit.event.inventory.InventoryClickEvent; ++import org.bukkit.event.inventory.InventoryCloseEvent; // Paper + import org.bukkit.event.inventory.InventoryCreativeEvent; + import org.bukkit.event.inventory.InventoryType.SlotType; + import org.bukkit.event.inventory.SmithItemEvent; +@@ -2311,10 +2312,15 @@ public class PlayerConnection implements PacketListenerPlayIn { + + @Override + public void a(PacketPlayInCloseWindow packetplayinclosewindow) { ++ // Paper start ++ handleContainerClose(packetplayinclosewindow, InventoryCloseEvent.Reason.PLAYER); ++ } ++ public void handleContainerClose(PacketPlayInCloseWindow packetplayinclosewindow, InventoryCloseEvent.Reason reason) { ++ // Paper end + PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.getWorldServer()); + + if (this.player.isFrozen()) return; // CraftBukkit +- CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit ++ CraftEventFactory.handleInventoryCloseEvent(this.player, reason); // CraftBukkit // Paper + + this.player.o(); + } +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index bd8bcc3891b29d31742bcfd6080a3972e4a9bee7..80934fc662b33b1c88dd7a3033792d612a7c7930 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -494,7 +494,7 @@ public abstract class PlayerList { + // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it + // See SPIGOT-5799, SPIGOT-6145 + if (entityplayer.activeContainer != entityplayer.defaultContainer) { +- entityplayer.closeInventory(); ++ entityplayer.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper + } + + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 3c49d7acd4ad0717886adf6c469e8a49a58e859b..b6effe1037f3ae59e6faa5f5d039b6ad54bca5d4 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -252,7 +252,7 @@ public abstract class EntityHuman extends EntityLiving { + this.et(); + super.tick(); + if (!this.world.isClientSide && this.activeContainer != null && !this.activeContainer.canUse(this)) { +- this.closeInventory(); ++ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.activeContainer = this.defaultContainer; + } + +@@ -447,6 +447,13 @@ public abstract class EntityHuman extends EntityLiving { + return 20; + } + ++ // Paper start - unused code, but to keep signatures aligned ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ closeInventory(); ++ this.activeContainer = this.defaultContainer; ++ } ++ // Paper end ++ + public void closeInventory() { + this.activeContainer = this.defaultContainer; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index 1333d425147e6dc7f21f755a9b25ead9723d4a28..3b3e6076f2565e02fa6f13e369094f8b6cac5382 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -375,7 +375,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + if (((EntityPlayer) getHandle()).playerConnection == null) return; + if (getHandle().activeContainer != getHandle().defaultContainer) { + // fire INVENTORY_CLOSE if one already open +- ((EntityPlayer) getHandle()).playerConnection.a(new PacketPlayInCloseWindow(getHandle().activeContainer.windowId)); ++ ((EntityPlayer) getHandle()).playerConnection.handleContainerClose(new PacketPlayInCloseWindow(getHandle().activeContainer.windowId), org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + EntityPlayer player = (EntityPlayer) getHandle(); + Container container; +@@ -445,8 +445,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + + @Override + public void closeInventory() { +- getHandle().closeInventory(); ++ // Paper start ++ getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); + } ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ getHandle().closeInventory(reason); ++ } ++ // Paper end + + @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 2abd5157b0964fc02994ca7a9317d2fb5539dc1c..ee3fbf0789b4841a113727397ba6809b2600ff83 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -898,7 +898,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + // Close any foreign inventory + if (getHandle().activeContainer != getHandle().defaultContainer) { +- getHandle().closeInventory(); ++ getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper + } + + // 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 69b5c76b312d055603ce62ad7b0c88cd01272ba9..7a245a0bc67ba7aaa986d20443d23e1a8a831dce 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1187,7 +1187,7 @@ public class CraftEventFactory { + + public static Container callInventoryOpenEvent(EntityPlayer player, Container container, boolean cancelled) { + if (player.activeContainer != player.defaultContainer) { // fire INVENTORY_CLOSE if one already open +- player.playerConnection.a(new PacketPlayInCloseWindow(player.activeContainer.windowId)); ++ player.playerConnection.handleContainerClose(new PacketPlayInCloseWindow(player.activeContainer.windowId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + CraftServer server = player.world.getServer(); +@@ -1353,8 +1353,18 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start ++ /** ++ * Incase plugins hooked into this or Spigot adds a new inventory close event. Prefer to pass a reason ++ * @param human ++ */ ++ @Deprecated + public static void handleInventoryCloseEvent(EntityHuman human) { +- InventoryCloseEvent event = new InventoryCloseEvent(human.activeContainer.getBukkitView()); ++ handleInventoryCloseEvent(human, org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); ++ } ++ public static void handleInventoryCloseEvent(EntityHuman human, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ // Paper end ++ InventoryCloseEvent event = new InventoryCloseEvent(human.activeContainer.getBukkitView(), reason); // Paper + human.world.getServer().getPluginManager().callEvent(event); + human.activeContainer.transferTo(human.defaultContainer, human.getBukkitEntity()); + } diff --git a/patches/server-unmapped/0234-Vex-getSummoner-API.patch b/patches/server-unmapped/0234-Vex-getSummoner-API.patch new file mode 100644 index 0000000000..c70d5e9bb3 --- /dev/null +++ b/patches/server-unmapped/0234-Vex-getSummoner-API.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 4 Jul 2018 15:30:22 -0400 +Subject: [PATCH] Vex#getSummoner API + +Get's the NPC that summoned this Vex + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java +index 3acf36a500424808cd91dc607df1ffbe23720c16..3b74ade60b3b0ae0e908866cb4ac11acd75620ff 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java +@@ -124,6 +124,7 @@ public class EntityVex extends EntityMonster { + + } + ++ public EntityInsentient getOwner() { return eK(); } // Paper - OBFHELPER + public EntityInsentient eK() { + return this.c; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +index ccaccffbf5eb18108760d1da09c4c1b2f33ebc42..962d6017f6acc47ebe4b754ccd9b97a1fc97cc58 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +@@ -16,6 +16,13 @@ public class CraftVex extends CraftMonster implements Vex { + return (EntityVex) super.getHandle(); + } + ++ // Paper start ++ public org.bukkit.entity.Mob getSummoner() { ++ net.minecraft.world.entity.EntityInsentient owner = getHandle().getOwner(); ++ return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; ++ } ++ // Paper end ++ + @Override + public String toString() { + return "CraftVex"; diff --git a/patches/server-unmapped/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/patches/server-unmapped/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch new file mode 100644 index 0000000000..052bf8e2fc --- /dev/null +++ b/patches/server-unmapped/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Fri, 13 Jul 2018 14:54:43 +0200 +Subject: [PATCH] Refresh player inventory when cancelling + PlayerInteractEntityEvent + +When interacting with entities with an item, the client will assume +the interaction is successful, and update the held item on the +client. However, if the interaction is cancelled on the server side, +the client will still mistakenly remove/replace the item in hand. + +Examples for this are milking cows with a bucket or dyeing sheep. +The bucket is replaced with milk and the dye removed from inventory. + +Refresh the player inventory when PlayerInteractEntityEvent is +cancelled to avoid this problem. + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 2a1ad096515247382da741fbcdc84f6d5b1001c5..ed5e13f668d09dcf56cec8c6269a5fbd93d156bd 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2224,6 +2224,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + + if (event.isCancelled()) { ++ this.player.updateInventory(this.player.activeContainer); // Paper - Refresh player inventory + return; + } + // CraftBukkit end diff --git a/patches/server-unmapped/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch b/patches/server-unmapped/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch new file mode 100644 index 0000000000..7640438b07 --- /dev/null +++ b/patches/server-unmapped/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 19 Jul 2018 01:05:00 -0400 +Subject: [PATCH] Don't change the Entity Random seed for squids + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java +index 7ce5e2597b34d3a4d2a79d73c15e893c064fc88c..1f5f3e0d209426b97e32b82dd15176b800f85816 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java +@@ -48,7 +48,7 @@ public class EntitySquid extends EntityWaterAnimal { + + public EntitySquid(EntityTypes entitytypes, World world) { + super(entitytypes, world); +- this.random.setSeed((long) this.getId()); ++ //this.random.setSeed((long) this.getId()); // Paper + this.bu = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; + } + diff --git a/patches/server-unmapped/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch b/patches/server-unmapped/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch new file mode 100644 index 0000000000..e2a6edf92c --- /dev/null +++ b/patches/server-unmapped/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 19 Jul 2018 01:08:05 -0400 +Subject: [PATCH] Re-add vanilla entity warnings for duplicates + +These are a critical sign that somethin went wrong, and you've lost some data.... + +We should kind of know about these things you know. + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index eb19b6fc87bfd4e500ea7836c1010a80b36abab2..d6a4ec132cadf8134a21f625f4ca978d37c643d0 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1077,7 +1077,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + if (entity1 == null) { + return false; + } else { +- // WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit ++ WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit // Paper + return true; + } + } diff --git a/patches/server-unmapped/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch b/patches/server-unmapped/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch new file mode 100644 index 0000000000..aded79d749 --- /dev/null +++ b/patches/server-unmapped/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Mon, 16 Jul 2018 12:42:20 +0200 +Subject: [PATCH] Avoid item merge if stack size above max stack size + + +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index de11fd9772f30ac72c3ca52ec4efc3fef4091425..4cfe3475fa913cd46116f13ea8ed9caf5372a41a 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -209,6 +209,10 @@ public class EntityItem extends Entity { + + private void mergeNearby() { + if (this.z()) { ++ // Paper start - avoid item merge if stack size above max stack size ++ ItemStack stack = getItemStack(); ++ if (stack.getCount() >= stack.getMaxStackSize()) return; ++ // Paper end + // Spigot start + double radius = world.spigotConfig.itemMerge; + List list = this.world.a(EntityItem.class, this.getBoundingBox().grow(radius, radius, radius), (entityitem) -> { diff --git a/patches/server-unmapped/0239-Use-asynchronous-Log4j-2-loggers.patch b/patches/server-unmapped/0239-Use-asynchronous-Log4j-2-loggers.patch new file mode 100644 index 0000000000..fd4a4b705a --- /dev/null +++ b/patches/server-unmapped/0239-Use-asynchronous-Log4j-2-loggers.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Tue, 17 Jul 2018 16:42:17 +0200 +Subject: [PATCH] Use asynchronous Log4j 2 loggers + + +diff --git a/pom.xml b/pom.xml +index f5429f2f1979542fd93956d2f436d20d0e3a66b8..4c8a057e790c96b0ab5123549d0566371acacb46 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -88,6 +88,13 @@ + log4j-iostreams + compile + ++ ++ ++ com.lmax ++ disruptor ++ 3.4.2 ++ runtime ++ + + org.ow2.asm + asm +diff --git a/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java +new file mode 100644 +index 0000000000000000000000000000000000000000..db652a1f7abc80bc751fd94925abaec58ab1a563 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.log; ++ ++import org.apache.logging.log4j.Level; ++import org.apache.logging.log4j.core.async.AsyncQueueFullPolicy; ++import org.apache.logging.log4j.core.async.EventRoute; ++ ++public final class LogFullPolicy implements AsyncQueueFullPolicy { ++ ++ /* ++ * Prevents log calls being logged out of order when the log queue is full. ++ */ ++ ++ @Override ++ public EventRoute getRoute(final long backgroundThreadId, final Level level) { ++ return EventRoute.ENQUEUE; ++ } ++} +diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties +index 0694b21465fb9e4164e71862ff24b62241b191f2..30efeb5faf8e7faccf1b252fa0ed6a9fc31c40a7 100644 +--- a/src/main/resources/log4j2.component.properties ++++ b/src/main/resources/log4j2.component.properties +@@ -1 +1,3 @@ ++Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector ++log4j2.AsyncQueueFullPolicy="com.destroystokyo.paper.log.LogFullPolicy" + log4j.skipJansi=true diff --git a/patches/server-unmapped/0240-add-more-information-to-Entity.toString.patch b/patches/server-unmapped/0240-add-more-information-to-Entity.toString.patch new file mode 100644 index 0000000000..c07f4b837a --- /dev/null +++ b/patches/server-unmapped/0240-add-more-information-to-Entity.toString.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 19 Jul 2018 01:13:28 -0400 +Subject: [PATCH] add more information to Entity.toString() + +UUID, ticks lived, valid, dead + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 43039c14e087259e3ce4b5091b887759b66fe52d..f15c60e56fc32a7dd525eefb2d622c33e00037c7 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2527,7 +2527,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public String toString() { +- return String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getDisplayName().getString(), this.id, this.world == null ? "~NULL~" : this.world.toString(), this.locX(), this.locY(), this.locZ()); ++ return String.format(Locale.ROOT, "%s['%s'/%d, uuid='%s', l='%s', x=%.2f, y=%.2f, z=%.2f, cx=%d, cz=%d, tl=%d, v=%b, d=%b]", new Object[] { this.getClass().getSimpleName(), this.getDisplayName().getString(), Integer.valueOf(this.id), this.uniqueID.toString(), this.world == null ? "~NULL~" : this.world.toString(), Double.valueOf(this.locX()), Double.valueOf(this.locY()), Double.valueOf(this.locZ()), chunkX, chunkZ, this.ticksLived, this.valid, this.dead}); // Paper - add more information + } + + public boolean isInvulnerable(DamageSource damagesource) { diff --git a/patches/server-unmapped/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/patches/server-unmapped/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch new file mode 100644 index 0000000000..88a4b140ae --- /dev/null +++ b/patches/server-unmapped/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch @@ -0,0 +1,131 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 21 Jul 2018 08:25:40 -0400 +Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues + +Add -Ddebug.entities=true to your JVM flags to gain more information + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index d1e45dfb99074ec027d4f943391a024c726d93b2..66c808244bba70f827d8f15a96814251d352a046 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -1147,6 +1147,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } else { + PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = new PlayerChunkMap.EntityTracker(entity, i, j, entitytypes.isDeltaTracking()); + ++ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker + this.trackedEntities.put(entity.getId(), playerchunkmap_entitytracker); + playerchunkmap_entitytracker.track(this.world.getPlayers()); + if (entity instanceof EntityPlayer) { +@@ -1188,7 +1189,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + if (playerchunkmap_entitytracker1 != null) { + playerchunkmap_entitytracker1.a(); + } +- ++ entity.tracker = null; // Paper - We're no longer tracked + } + + protected void g() { +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index d6a4ec132cadf8134a21f625f4ca978d37c643d0..650015f08ef4defe7510ff2f5cbd25364b733515 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -197,6 +197,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { + public final Convertable.ConversionSession convertable; + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper ++ private static Throwable getAddToWorldStackTrace(Entity entity) { ++ return new Throwable(entity + " Added to world at " + new java.util.Date()); ++ } + + @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkProvider.getChunkAt(x, z, false); +@@ -1038,8 +1041,28 @@ public class WorldServer extends World implements GeneratorAccessSeed { + // CraftBukkit start + private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot +- if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper ++ // Paper start ++ if (entity.valid) { ++ MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); ++ ++ if (DEBUG_ENTITIES) { ++ Throwable thr = entity.addedToWorldStack; ++ if (thr == null) { ++ MinecraftServer.LOGGER.error("Double add entity has no add stacktrace"); ++ } else { ++ MinecraftServer.LOGGER.error("Double add stacktrace: ", thr); ++ } ++ } ++ return true; ++ } ++ // Paper end + if (entity.dead) { ++ // Paper start ++ if (DEBUG_ENTITIES) { ++ new Throwable("Tried to add entity " + entity + " but it was marked as removed already").printStackTrace(); // CraftBukkit ++ getAddToWorldStackTrace(entity).printStackTrace(); ++ } ++ // Paper end + // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit + return false; + } else if (this.isUUIDTaken(entity)) { +@@ -1237,7 +1260,24 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + } + +- this.entitiesByUUID.put(entity.getUniqueID(), entity); ++ if (DEBUG_ENTITIES) { ++ entity.addedToWorldStack = getAddToWorldStackTrace(entity); ++ } ++ ++ Entity old = this.entitiesByUUID.put(entity.getUniqueID(), entity); ++ if (old != null && old.getId() != entity.getId() && old.valid) { ++ Logger logger = LogManager.getLogger(); ++ logger.error("Overwrote an existing entity " + old + " with " + entity); ++ if (DEBUG_ENTITIES) { ++ if (old.addedToWorldStack != null) { ++ old.addedToWorldStack.printStackTrace(); ++ } else { ++ logger.error("Oddly, the old entity was not added to the world in the normal way. Plugins?"); ++ } ++ entity.addedToWorldStack.printStackTrace(); ++ } ++ } ++ + this.getChunkProvider().addEntity(entity); + // CraftBukkit start - SPIGOT-5278 + if (entity instanceof EntityDrowned) { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index f15c60e56fc32a7dd525eefb2d622c33e00037c7..5d34c5c16942198c2ee998a8fb3c5bcd4bb3d1b5 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -48,6 +48,7 @@ import net.minecraft.resources.MinecraftKey; + import net.minecraft.resources.ResourceKey; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.PlayerChunkMap; + import net.minecraft.server.level.TicketType; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundCategory; +@@ -161,6 +162,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper + private CraftEntity bukkitEntity; + ++ PlayerChunkMap.EntityTracker tracker; // Paper ++ public Throwable addedToWorldStack; // Paper - entity debug + public CraftEntity getBukkitEntity() { + if (bukkitEntity == null) { + bukkitEntity = CraftEntity.getEntity(world.getServer(), this); +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index a9e7da1c848a6fe08fc112e445ceec1b7715d682..0d375af209e9768f430e08bd7a4bde1863b14da5 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -121,6 +121,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public boolean pvpMode; + public boolean keepSpawnInMemory = true; + public org.bukkit.generator.ChunkGenerator generator; ++ public static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper + + public boolean captureBlockStates = false; + public boolean captureTreeGeneration = false; diff --git a/patches/server-unmapped/0242-EnderDragon-Events.patch b/patches/server-unmapped/0242-EnderDragon-Events.patch new file mode 100644 index 0000000000..2ac7798d52 --- /dev/null +++ b/patches/server-unmapped/0242-EnderDragon-Events.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 01:51:27 -0500 +Subject: [PATCH] EnderDragon Events + + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java +index 5adbd9fe858aad9c775a10254eb53b34719a9bd6..91de4e6c1d478e001c8672d34b4ffe57f6cba0a6 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java +@@ -80,7 +80,11 @@ public class DragonControllerLandedFlame extends AbstractDragonControllerLanded + this.d.setDuration(200); + this.d.setParticle(Particles.DRAGON_BREATH); + this.d.addEffect(new MobEffect(MobEffects.HARM)); ++ if (new com.destroystokyo.paper.event.entity.EnderDragonFlameEvent((org.bukkit.entity.EnderDragon) this.a.getBukkitEntity(), (org.bukkit.entity.AreaEffectCloud) this.d.getBukkitEntity()).callEvent()) { // Paper + this.a.world.addEntity(this.d); ++ } else { ++ this.removeAreaEffect(); ++ } + } + + } +@@ -91,8 +95,8 @@ public class DragonControllerLandedFlame extends AbstractDragonControllerLanded + ++this.c; + } + +- @Override +- public void e() { ++ public final void removeAreaEffect() { this.e(); } // Paper - OBFHELPER ++ @Override public void e() { + if (this.d != null) { + this.d.die(); + this.d = null; +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java +index db3cef26c8d5cdf740bb151a5525d8740a0e8bbd..1a5d5d39d3090acc3914e40e8d30c4a09789dbc9 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java +@@ -81,7 +81,9 @@ public class DragonControllerStrafe extends AbstractDragonController { + EntityDragonFireball entitydragonfireball = new EntityDragonFireball(this.a.world, this.a, d9, d10, d11); + + entitydragonfireball.setPositionRotation(d6, d7, d8, 0.0F, 0.0F); ++ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) a.getBukkitEntity(), (org.bukkit.entity.DragonFireball) entitydragonfireball.getBukkitEntity()).callEvent()) // Paper + this.a.world.addEntity(entitydragonfireball); ++ else entitydragonfireball.die(); // Paper + this.c = 0; + if (this.d != null) { + while (!this.d.c()) { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java +index 59b5484731a5f71005c3efa56cbe40012d9641b5..27853f510e15e40c66da2cb4905c43f5e8f99d3d 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java +@@ -58,8 +58,10 @@ public class EntityDragonFireball extends EntityFireball { + } + } + ++ if (new com.destroystokyo.paper.event.entity.EnderDragonFireballHitEvent((org.bukkit.entity.DragonFireball) this.getBukkitEntity(), list.stream().map(EntityLiving::getBukkitLivingEntity).collect(java.util.stream.Collectors.toList()), (org.bukkit.entity.AreaEffectCloud) entityareaeffectcloud.getBukkitEntity()).callEvent()) { // Paper + this.world.triggerEffect(2006, this.getChunkCoordinates(), this.isSilent() ? -1 : 1); + this.world.addEntity(entityareaeffectcloud); ++ } else entityareaeffectcloud.die(); // Paper + this.die(); + } + diff --git a/patches/server-unmapped/0243-PlayerElytraBoostEvent.patch b/patches/server-unmapped/0243-PlayerElytraBoostEvent.patch new file mode 100644 index 0000000000..684680a7ed --- /dev/null +++ b/patches/server-unmapped/0243-PlayerElytraBoostEvent.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 01:59:59 -0500 +Subject: [PATCH] PlayerElytraBoostEvent + + +diff --git a/src/main/java/net/minecraft/world/item/ItemFireworks.java b/src/main/java/net/minecraft/world/item/ItemFireworks.java +index a2950faa48021782f10db0673d12d178443f7ccc..79e9be800385b94c4493bd8970620d76bfbd65ae 100644 +--- a/src/main/java/net/minecraft/world/item/ItemFireworks.java ++++ b/src/main/java/net/minecraft/world/item/ItemFireworks.java +@@ -45,11 +45,16 @@ public class ItemFireworks extends Item { + // Paper start + final EntityFireworks entityfireworks = new EntityFireworks(world, itemstack, entityhuman); + entityfireworks.spawningEntity = entityhuman.getUniqueID(); +- world.addEntity(entityfireworks); +- // Paper end +- if (!entityhuman.abilities.canInstantlyBuild) { +- itemstack.subtract(1); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); ++ if (event.callEvent() && world.addEntity(entityfireworks)) { ++ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { ++ itemstack.subtract(1); ++ } else ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } else if (entityhuman instanceof EntityPlayer) { ++ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); + } ++ // Paper end + } + + return InteractionResultWrapper.a(entityhuman.b(enumhand), world.s_()); diff --git a/patches/server-unmapped/0244-Improve-BlockPosition-inlining.patch b/patches/server-unmapped/0244-Improve-BlockPosition-inlining.patch new file mode 100644 index 0000000000..9d4fb270ac --- /dev/null +++ b/patches/server-unmapped/0244-Improve-BlockPosition-inlining.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Wed, 30 Nov 2016 20:56:58 -0600 +Subject: [PATCH] Improve BlockPosition inlining + +Normally the JVM can inline virtual getters by having two sets of code, one is the 'optimized' code and the other is the 'deoptimized' code. +If a single type is used 99% of the time, then its worth it to inline, and to revert to 'deoptimized' the 1% of the time we encounter other types. +But if two types are encountered commonly, then the JVM can't inline them both, and the call overhead remains. + +This scenario also occurs with BlockPos and MutableBlockPos. +The variables in BlockPos are final, so MutableBlockPos can't modify them. +MutableBlockPos fixes this by adding custom mutable variables, and overriding the getters to access them. + +This approach with utility methods that operate on MutableBlockPos and BlockPos. +Specific examples are BlockPosition.up(), and World.isValidLocation(). +It makes these simple methods much slower than they need to be. + +This should result in an across the board speedup in anything that accesses blocks or does logic with positions. + +This is based upon conclusions drawn from inspecting the assenmbly generated bythe JIT compiler on my microbenchmarks. +They had 'callq' (invoke) instead of 'mov' (get from memory) instructions. + +diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java +index 4b56683336fdab06804efdc8ca1f7c130b77291f..a44bcdb053877a6281e566ffe03ef72ffd50ca08 100644 +--- a/src/main/java/net/minecraft/core/BaseBlockPosition.java ++++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java +@@ -41,7 +41,7 @@ public class BaseBlockPosition implements Comparable { + this(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); + } + +- public boolean equals(Object object) { ++ public final boolean equals(Object object) { // Paper + if (this == object) { + return true; + } else if (!(object instanceof BaseBlockPosition)) { +@@ -53,7 +53,7 @@ public class BaseBlockPosition implements Comparable { + } + } + +- public int hashCode() { ++ public final int hashCode() { // Paper + return (this.getY() + this.getZ() * 31) * 31 + this.getX(); + } + +@@ -61,15 +61,15 @@ public class BaseBlockPosition implements Comparable { + return this.getY() == baseblockposition.getY() ? (this.getZ() == baseblockposition.getZ() ? this.getX() - baseblockposition.getX() : this.getZ() - baseblockposition.getZ()) : this.getY() - baseblockposition.getY(); + } + +- public int getX() { ++ public final int getX() { // Paper + return this.a; + } + +- public int getY() { ++ public final int getY() { // Paper + return this.b; + } + +- public int getZ() { ++ public final int getZ() { // Paper + return this.e; + } + +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index 9fb6db18c5c1f39b5a564c0f5f70498825defa97..370b2c4460d6b52b5ef7da89f5ebf7ef50deb582 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -88,6 +88,7 @@ public class BlockPosition extends BaseBlockPosition { + return a(this.getX(), this.getY(), this.getZ()); + } + ++ public static long asLong(int x, int y, int z) { return a(x, y, z); } // Paper - OBFHELPER + public static long a(int i, int j, int k) { + long l = 0L; + diff --git a/patches/server-unmapped/0245-Optimize-RegistryID.c.patch b/patches/server-unmapped/0245-Optimize-RegistryID.c.patch new file mode 100644 index 0000000000..028620de8b --- /dev/null +++ b/patches/server-unmapped/0245-Optimize-RegistryID.c.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Mon, 23 Jul 2018 13:08:19 -0400 +Subject: [PATCH] Optimize RegistryID.c() + +This is a frequent hotspot for world loading/saving. + +diff --git a/src/main/java/net/minecraft/util/RegistryID.java b/src/main/java/net/minecraft/util/RegistryID.java +index 6150f7a5c5004ac79414ab22dbaa3439dc8afdb4..a59dbfa01743137702b122f73c778452e63115b5 100644 +--- a/src/main/java/net/minecraft/util/RegistryID.java ++++ b/src/main/java/net/minecraft/util/RegistryID.java +@@ -15,12 +15,14 @@ public class RegistryID implements Registry { + private K[] d; + private int e; + private int f; ++ private java.util.BitSet usedIds; // Paper + + public RegistryID(int i) { + i = (int) ((float) i / 0.8F); + this.b = (K[]) (new Object[i]); // Paper - decompile fix + this.c = new int[i]; + this.d = (K[]) (new Object[i]); // Paper - decompile fix ++ this.usedIds = new java.util.BitSet(); // Paper + } + + // Paper start - decompile fix +@@ -52,9 +54,14 @@ public class RegistryID implements Registry { + } + + private int c() { ++ // Paper start ++ /* + while (this.e < this.d.length && this.d[this.e] != null) { + ++this.e; + } ++ */ ++ this.e = this.usedIds.nextClearBit(0); ++ // Paper end + + return this.e; + } +@@ -68,6 +75,7 @@ public class RegistryID implements Registry { + this.d = (K[]) (new Object[i]); // Paper - decompile fix + this.e = 0; + this.f = 0; ++ this.usedIds.clear(); // Paper + + for (int j = 0; j < ak.length; ++j) { + if (ak[j] != null) { +@@ -93,6 +101,7 @@ public class RegistryID implements Registry { + this.b[k] = k0; + this.c[k] = i; + this.d[i] = k0; ++ this.usedIds.set(i); // Paper + ++this.f; + if (i == this.e) { + ++this.e; +@@ -157,6 +166,7 @@ public class RegistryID implements Registry { + Arrays.fill(this.d, (Object) null); + this.e = 0; + this.f = 0; ++ this.usedIds.clear(); // Paper + } + + public int b() { diff --git a/patches/server-unmapped/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/patches/server-unmapped/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch new file mode 100644 index 0000000000..d24d23f2ac --- /dev/null +++ b/patches/server-unmapped/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Mon, 23 Jul 2018 12:57:39 +0200 +Subject: [PATCH] Option to prevent armor stands from doing entity lookups + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4813f62d1e382d5ac6971b2244df3f13c80d1950..3562950df4868b1393790b1a1ff1fe0dc589c155 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -379,4 +379,9 @@ public class PaperWorldConfig { + private void scanForLegacyEnderDragon() { + scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); + } ++ ++ public boolean armorStandEntityLookups = true; ++ private void armorStandEntityLookups() { ++ armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +index 57e0ea95df34fab22d6c5868ab839d56a3fa85fc..829013f57128cc6c92a45098c6883f2305cf4ea5 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +@@ -356,6 +356,7 @@ public class EntityArmorStand extends EntityLiving { + + @Override + protected void collideNearby() { ++ if (!world.paperConfig.armorStandEntityLookups) return; // Paper + List list = this.world.getEntities(this, this.getBoundingBox(), EntityArmorStand.br); + + for (int i = 0; i < list.size(); ++i) { +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 0d375af209e9768f430e08bd7a4bde1863b14da5..8c7263f9dbb00cf6484e7f70b8d97639bab0cefc 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -37,6 +37,7 @@ import net.minecraft.world.DifficultyDamageScaler; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.decoration.EntityArmorStand; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.CraftingManager; +@@ -854,6 +855,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + // Paper end + } + } ++ // Paper start - Prevent armor stands from doing entity lookups ++ @Override ++ public boolean getCubes(@Nullable Entity entity, AxisAlignedBB axisAlignedBB) { ++ if (entity instanceof EntityArmorStand && !entity.world.paperConfig.armorStandEntityLookups) return false; ++ return GeneratorAccess.super.getCubes(entity, axisAlignedBB); ++ } ++ // Paper end + + public Explosion explode(@Nullable Entity entity, double d0, double d1, double d2, float f, Explosion.Effect explosion_effect) { + return this.createExplosion(entity, (DamageSource) null, (ExplosionDamageCalculator) null, d0, d1, d2, f, false, explosion_effect); diff --git a/patches/server-unmapped/0247-Vanished-players-don-t-have-rights.patch b/patches/server-unmapped/0247-Vanished-players-don-t-have-rights.patch new file mode 100644 index 0000000000..2ec7ae0aca --- /dev/null +++ b/patches/server-unmapped/0247-Vanished-players-don-t-have-rights.patch @@ -0,0 +1,194 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Mon, 23 Jul 2018 14:22:26 +0200 +Subject: [PATCH] Vanished players don't have rights + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 5d34c5c16942198c2ee998a8fb3c5bcd4bb3d1b5..ae2f5664c3022b452b6cba8f9ce36b493fa9fec8 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -184,7 +184,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + private static double e = 1.0D; + private final EntityTypes f; + private int id; +- public boolean i; ++ public boolean i; public final boolean blocksEntitySpawning() { return this.i; } // Paper - OBFHELPER + public final List passengers; + protected int j; + @Nullable +diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +index 8f14e1ebefe172e056a04bd7b6f55b9bbb1e7b2e..b44b18341331e5176e0f1851aa60cc425ccbd439 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +@@ -4,6 +4,7 @@ import java.util.Iterator; + import java.util.UUID; + import javax.annotation.Nullable; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.util.MathHelper; + import net.minecraft.world.entity.Entity; +@@ -158,8 +159,14 @@ public abstract class IProjectile extends Entity { + protected boolean a(Entity entity) { + if (!entity.isSpectator() && entity.isAlive() && entity.isInteractable()) { + Entity entity1 = this.getShooter(); +- ++ // Paper start - Cancel hit for vanished players ++ if (entity1 instanceof EntityPlayer && entity instanceof EntityPlayer) { ++ org.bukkit.entity.Player collided = (org.bukkit.entity.Player) entity.getBukkitEntity(); ++ org.bukkit.entity.Player shooter = (org.bukkit.entity.Player) entity1.getBukkitEntity(); ++ if (!shooter.canSee(collided)) return false; ++ } + return entity1 == null || this.d || !entity1.isSameVehicle(entity); ++ // Paper end + } else { + return false; + } +diff --git a/src/main/java/net/minecraft/world/item/ItemBlock.java b/src/main/java/net/minecraft/world/item/ItemBlock.java +index ec12bea9de910824927ba31628b49f6713f31a29..59d52c252b2e59923b8e513dd4d2e1ec9ce34dc7 100644 +--- a/src/main/java/net/minecraft/world/item/ItemBlock.java ++++ b/src/main/java/net/minecraft/world/item/ItemBlock.java +@@ -177,7 +177,8 @@ public class ItemBlock extends Item { + EntityHuman entityhuman = blockactioncontext.getEntity(); + VoxelShapeCollision voxelshapecollision = entityhuman == null ? VoxelShapeCollision.a() : VoxelShapeCollision.a((Entity) entityhuman); + // CraftBukkit start - store default return +- boolean defaultReturn = (!this.isCheckCollisions() || iblockdata.canPlace(blockactioncontext.getWorld(), blockactioncontext.getClickPosition())) && blockactioncontext.getWorld().a(iblockdata, blockactioncontext.getClickPosition(), voxelshapecollision); ++ World world = blockactioncontext.getWorld(); // Paper ++ boolean defaultReturn = (!this.isCheckCollisions() || iblockdata.canPlace(blockactioncontext.getWorld(), blockactioncontext.getClickPosition())) && world.checkEntityCollision(iblockdata, entityhuman, voxelshapecollision, blockactioncontext.getClickPosition(), true); // Paper + org.bukkit.entity.Player player = (blockactioncontext.getEntity() instanceof EntityPlayer) ? (org.bukkit.entity.Player) blockactioncontext.getEntity().getBukkitEntity() : null; + + BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(blockactioncontext.getWorld(), blockactioncontext.getClickPosition()), player, CraftBlockData.fromData(iblockdata), defaultReturn); +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 8c7263f9dbb00cf6484e7f70b8d97639bab0cefc..07c5cdd00930a55fd412ef95f71f55ee908189a1 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -27,6 +27,7 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.resources.ResourceKey; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.PlayerChunk; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffect; +@@ -65,6 +66,10 @@ import net.minecraft.world.level.saveddata.maps.WorldMap; + import net.minecraft.world.level.storage.WorldData; + import net.minecraft.world.level.storage.WorldDataMutable; + import net.minecraft.world.phys.AxisAlignedBB; ++import net.minecraft.world.phys.shapes.OperatorBoolean; ++import net.minecraft.world.phys.shapes.VoxelShape; ++import net.minecraft.world.phys.shapes.VoxelShapeCollision; ++import net.minecraft.world.phys.shapes.VoxelShapes; + import net.minecraft.world.scores.Scoreboard; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -232,6 +237,46 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + } + ++ // Paper start ++ // ret true if no collision ++ public final boolean checkEntityCollision(IBlockData data, Entity source, VoxelShapeCollision voxelshapedcollision, ++ BlockPosition position, boolean checkCanSee) { ++ // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape) ++ VoxelShape voxelshape = data.getCollisionShape(this, position, voxelshapedcollision); ++ if (voxelshape.isEmpty()) { ++ return true; ++ } ++ ++ voxelshape = voxelshape.offset((double) position.getX(), (double) position.getY(), (double) position.getZ()); ++ if (voxelshape.isEmpty()) { ++ return true; ++ } ++ ++ List entities = this.getEntities(null, voxelshape.getBoundingBox()); ++ for (int i = 0, len = entities.size(); i < len; ++i) { ++ Entity entity = entities.get(i); ++ ++ if (checkCanSee && source instanceof EntityPlayer && entity instanceof EntityPlayer ++ && !((EntityPlayer) source).getBukkitEntity().canSee(((EntityPlayer) entity).getBukkitEntity())) { ++ continue; ++ } ++ ++ // !entity1.dead && entity1.i && (entity == null || !entity1.x(entity)); ++ // elide the last check since vanilla calls with entity = null ++ // only we care about the source for the canSee check ++ if (entity.dead || !entity.blocksEntitySpawning()) { ++ continue; ++ } ++ ++ if (VoxelShapes.applyOperation(voxelshape, VoxelShapes.of(entity.getBoundingBox()), OperatorBoolean.AND)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ // Paper end ++ + @Override + public boolean s_() { + return this.isClientSide; +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +index 2902117fd2803741b053a04fda7f4414fb8593cb..10f4015b8c36e4e27cf7d0745ba70b8a9e60aff3 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +@@ -505,6 +505,7 @@ public abstract class BlockBase { + return this.a != null ? this.a.b : this.b(iblockaccess, blockposition, VoxelShapeCollision.a()); + } + ++ public final VoxelShape getCollisionShape(IBlockAccess iblockaccess, BlockPosition blockposition, VoxelShapeCollision voxelshapecollision) { return this.b(iblockaccess, blockposition, voxelshapecollision); } // Paper - OBFHELPER + public VoxelShape b(IBlockAccess iblockaccess, BlockPosition blockposition, VoxelShapeCollision voxelshapecollision) { + return this.getBlock().c(this.p(), iblockaccess, blockposition, voxelshapecollision); + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +index 1b82349b96b3ec9490d06d1c1d1cbf2b1578d313..887016224c16f8a38c10a98eb0e2ae6cb353a153 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +@@ -54,6 +54,7 @@ public abstract class VoxelShape { + return this.a.a(); + } + ++ public final VoxelShape offset(double x, double y, double z) { return this.a(x, y, z); } // Paper - OBFHELPER + public VoxelShape a(double d0, double d1, double d2) { + return (VoxelShape) (this.isEmpty() ? VoxelShapes.a() : new VoxelShapeArray(this.a, new DoubleListOffset(this.a(EnumDirection.EnumAxis.X), d0), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Y), d1), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Z), d2))); + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +index fdd9e37a8c90fc3311e515355af0a0593efbdacc..cf32a4f63e8e59535c02a3f9c57f98833a2b0e83 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +@@ -45,6 +45,7 @@ public final class VoxelShapes { + return a(new AxisAlignedBB(d0, d1, d2, d3, d4, d5)); + } + ++ public static final VoxelShape of(AxisAlignedBB axisAlignedbb) { return VoxelShapes.a(axisAlignedbb); } // Paper - OBFHELPER + public static VoxelShape a(AxisAlignedBB axisalignedbb) { + int i = a(axisalignedbb.minX, axisalignedbb.maxX); + int j = a(axisalignedbb.minY, axisalignedbb.maxY); +@@ -139,6 +140,7 @@ public final class VoxelShapes { + } + } + ++ public static final boolean applyOperation(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { return VoxelShapes.c(voxelshape, voxelshape1, operatorboolean); } // Paper - OBFHELPER + public static boolean c(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { + if (operatorboolean.apply(false, false)) { + throw (IllegalArgumentException) SystemUtils.c((Throwable) (new IllegalArgumentException())); +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 7a245a0bc67ba7aaa986d20443d23e1a8a831dce..31358b90784a6e983ff8b687021c721ed5d43eab 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1223,6 +1223,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); ++ ++ if (projectile.getShooter() instanceof Player && collided instanceof Player) { ++ if (!((Player) projectile.getShooter()).canSee((Player) collided)) { ++ event.setCancelled(true); ++ return event; ++ } ++ } ++ + Bukkit.getPluginManager().callEvent(event); + return event; + } diff --git a/patches/server-unmapped/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch b/patches/server-unmapped/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch new file mode 100644 index 0000000000..a5f5fb4d8d --- /dev/null +++ b/patches/server-unmapped/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 23 Jul 2018 22:18:31 -0400 +Subject: [PATCH] Mark chunk dirty anytime entities change to guarantee it + saves + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index 7918dd4ad3e8cbb905b3929062a70fb7961b7d68..f56ff8e727c74870229d4d146b13534863f620d6 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -560,6 +560,7 @@ public class Chunk implements IChunkAccess { + entity.chunkZ = this.loc.z; + this.entities.add(entity); // Paper - per chunk entity list + this.entitySlices[k].add(entity); ++ this.markDirty(); // Paper + } + + @Override +@@ -588,6 +589,7 @@ public class Chunk implements IChunkAccess { + return; + } + entityCounts.decrement(entity.getMinecraftKeyString()); ++ this.markDirty(); // Paper + // Paper end + this.entities.remove(entity); // Paper + } diff --git a/patches/server-unmapped/0249-Add-some-Debug-to-Chunk-Entity-slices.patch b/patches/server-unmapped/0249-Add-some-Debug-to-Chunk-Entity-slices.patch new file mode 100644 index 0000000000..1f08354596 --- /dev/null +++ b/patches/server-unmapped/0249-Add-some-Debug-to-Chunk-Entity-slices.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 23 Jul 2018 22:44:23 -0400 +Subject: [PATCH] Add some Debug to Chunk Entity slices + +If we detect unexpected state, log and try to recover + +This should hopefully avoid duplicate entities ever being created +if the entity was to end up in 2 different chunk slices + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index ae2f5664c3022b452b6cba8f9ce36b493fa9fec8..a6f0cde7bdc930abced5063da237bcd27ddcd20f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -157,6 +157,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + } + }; ++ public List entitySlice = null; + // Paper end + + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index f56ff8e727c74870229d4d146b13534863f620d6..e4accac8f2e8daa58f9b0c279ffcad9347448bb0 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -26,6 +26,8 @@ import net.minecraft.ReportedException; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.IRegistry; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ChunkProviderServer; + import net.minecraft.server.level.PlayerChunk; + import net.minecraft.server.level.WorldServer; + import net.minecraft.util.EntitySlice; +@@ -551,6 +553,25 @@ public class Chunk implements IChunkAccess { + if (k >= this.entitySlices.length) { + k = this.entitySlices.length - 1; + } ++ // Paper - remove from any old list if its in one ++ List nextSlice = this.entitySlices[k]; // the next list to be added to ++ List currentSlice = entity.entitySlice; ++ if (nextSlice == currentSlice) { ++ if (World.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity was already in this chunk!" + entity, new Throwable()); ++ return; // ??? silly plugins ++ } ++ if (currentSlice != null && currentSlice.contains(entity)) { ++ // Still in an old chunk... ++ if (World.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity is still in another chunk!" + entity, new Throwable()); ++ Chunk chunk = entity.getCurrentChunk(); ++ if (chunk != null) { ++ chunk.removeEntity(entity); ++ } else { ++ removeEntity(entity); ++ } ++ currentSlice.remove(entity); // Just incase the above did not remove from the previous slice ++ } ++ // Paper end + + if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper + entity.inChunk = true; +@@ -560,6 +581,7 @@ public class Chunk implements IChunkAccess { + entity.chunkZ = this.loc.z; + this.entities.add(entity); // Paper - per chunk entity list + this.entitySlices[k].add(entity); ++ entity.entitySlice = this.entitySlices[k]; // Paper + this.markDirty(); // Paper + } + +@@ -585,6 +607,10 @@ public class Chunk implements IChunkAccess { + + // Paper start + if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); ++ if (entitySlices[i] == entity.entitySlice) { ++ entity.entitySlice = null; ++ entity.inChunk = false; ++ } + if (!this.entitySlices[i].remove(entity)) { + return; + } diff --git a/patches/server-unmapped/0250-SkeletonHorse-Additions.patch b/patches/server-unmapped/0250-SkeletonHorse-Additions.patch new file mode 100644 index 0000000000..96ea01f30a --- /dev/null +++ b/patches/server-unmapped/0250-SkeletonHorse-Additions.patch @@ -0,0 +1,152 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 27 Jul 2018 22:36:31 -0500 +Subject: [PATCH] SkeletonHorse Additions + + +diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +index dfcfdb31ca9531913d705aaaf85fb67399cfdc8c..4776a47566aac487dc77fd6b4b9b42b95974e31a 100644 +--- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +@@ -25,6 +25,7 @@ public final class IEntitySelector { + public static final Predicate f = (entity) -> { + return !(entity instanceof EntityHuman) || !entity.isSpectator() && !((EntityHuman) entity).isCreative() && entity.world.getDifficulty() != EnumDifficulty.PEACEFUL; + }; ++ public static Predicate notSpectator() { return g; } // Paper - OBFHELPER + public static final Predicate g = (entity) -> { + return !entity.isSpectator(); + }; +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java +index 0ddb676a2d1c38c97cd7750c1594fd6468156d0a..da5365372e89b847d626e52c5541544467f14702 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java +@@ -26,7 +26,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { + + private final PathfinderGoalHorseTrap bw = new PathfinderGoalHorseTrap(this); + private boolean bx; +- private int by; ++ private int by; public int getTrapTime() { return this.by; } // Paper - OBFHELPER + + public EntityHorseSkeleton(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -145,10 +145,12 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { + return 0.96F; + } + ++ public boolean isTrap() { return this.eM(); } // Paper - OBFHELPER + public boolean eM() { + return this.bx; + } + ++ public void setTrap(boolean trap) { this.t(trap); } // Paper - OBFHELPER + public void t(boolean flag) { + if (flag != this.bx) { + this.bx = flag; +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java b/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java +index 9b6a4f93dca6eeddad43d5f5675c551fb3fd2fdb..cf250cc6b7a77a7af742eab0b89cff2bc17fc5e4 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java +@@ -15,9 +15,14 @@ import net.minecraft.world.item.Items; + import net.minecraft.world.item.enchantment.EnchantmentManager; + import net.minecraft.world.level.World; + ++import org.bukkit.entity.HumanEntity; ++ ++import java.util.List; ++ + public class PathfinderGoalHorseTrap extends PathfinderGoal { + + private final EntityHorseSkeleton a; ++ private List eligiblePlayers; // Paper + + public PathfinderGoalHorseTrap(EntityHorseSkeleton entityhorseskeleton) { + this.a = entityhorseskeleton; +@@ -25,12 +30,13 @@ public class PathfinderGoalHorseTrap extends PathfinderGoal { + + @Override + public boolean a() { +- return this.a.world.isPlayerNearby(this.a.locX(), this.a.locY(), this.a.locZ(), 10.0D); ++ return !(eligiblePlayers = this.a.world.findNearbyBukkitPlayers(this.a.locX(), this.a.locY(), this.a.locZ(), 10.0D, false)).isEmpty(); // Paper + } + + @Override + public void e() { + WorldServer worldserver = (WorldServer) this.a.world; ++ if (!new com.destroystokyo.paper.event.entity.SkeletonHorseTrapEvent((org.bukkit.entity.SkeletonHorse) this.a.getBukkitEntity(), eligiblePlayers).callEvent()) return; // Paper + DifficultyDamageScaler difficultydamagescaler = worldserver.getDamageScaler(this.a.getChunkCoordinates()); + + this.a.t(false); +diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java +index 6d5d4c3df65995b9a13b66d070ba08d553cc98a2..8fdc4b22e8c99d653bd213fe64339c133b46b4e9 100644 +--- a/src/main/java/net/minecraft/world/level/IEntityAccess.java ++++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java +@@ -1,6 +1,9 @@ + package net.minecraft.world.level; + ++import com.google.common.collect.ImmutableList; + import com.google.common.collect.Lists; ++import org.bukkit.entity.HumanEntity; ++ + import java.util.Iterator; + import java.util.List; + import java.util.UUID; +@@ -115,6 +118,28 @@ public interface IEntityAccess { + return entityhuman; + } + ++ // Paper start ++ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, boolean notSpectator) { ++ return findNearbyBukkitPlayers(x, y, z, radius, notSpectator ? IEntitySelector.notSpectator() : IEntitySelector.canAITarget()); ++ } ++ ++ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate predicate) { ++ ImmutableList.Builder builder = ImmutableList.builder(); ++ ++ for (EntityHuman human : this.getPlayers()) { ++ if (predicate == null || predicate.test(human)) { ++ double distanceSquared = human.getDistanceSquared(x, y, z); ++ ++ if (radius < 0.0D || distanceSquared < radius * radius) { ++ builder.add(human.getBukkitEntity()); ++ } ++ } ++ } ++ ++ return builder.build(); ++ } ++ // Paper end ++ + @Nullable + default EntityHuman findNearbyPlayer(Entity entity, double d0) { + return this.a(entity.locX(), entity.locY(), entity.locZ(), d0, false); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java +index 4aec5fdb6b0379b0797969ff3c8f8a9629a18bfb..7366d56cefad45883f353ea5fb16b41f87006ec1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java +@@ -26,4 +26,26 @@ public class CraftSkeletonHorse extends CraftAbstractHorse implements SkeletonHo + public Variant getVariant() { + return Variant.SKELETON_HORSE; + } ++ ++ // Paper start ++ @Override ++ public EntityHorseSkeleton getHandle() { ++ return (EntityHorseSkeleton) super.getHandle(); ++ } ++ ++ @Override ++ public int getTrapTime() { ++ return getHandle().getTrapTime(); ++ } ++ ++ @Override ++ public boolean isTrap() { ++ return getHandle().isTrap(); ++ } ++ ++ @Override ++ public void setTrap(boolean trap) { ++ getHandle().setTrap(trap); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0251-Prevent-Saving-Bad-entities-to-chunks.patch b/patches/server-unmapped/0251-Prevent-Saving-Bad-entities-to-chunks.patch new file mode 100644 index 0000000000..f9e9f4cd9f --- /dev/null +++ b/patches/server-unmapped/0251-Prevent-Saving-Bad-entities-to-chunks.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 26 Jul 2018 00:11:12 -0400 +Subject: [PATCH] Prevent Saving Bad entities to chunks + +See https://github.com/PaperMC/Paper/issues/1223 + +Minecraft is saving invalid entities to the chunk files. + +Avoid saving bad data, and also make improvements to handle +loading these chunks. Any invalid entity will be instant killed, +so lets avoid adding it to the world... + +This lets us be safer about the dupe UUID resolver too, as now +we can ignore instant killed entities and avoid risk of duplicating +an invalid entity. + +This should reduce log occurrences of dupe uuid messages. + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 650015f08ef4defe7510ff2f5cbd25364b733515..e39f1ea4eefb0d8e0ca379b116b3699c13bb3f35 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1157,6 +1157,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + List[] aentityslice = chunk.getEntitySlices(); // Spigot + int i = aentityslice.length; + ++ java.util.List toMoveChunks = new java.util.ArrayList<>(); // Paper + for (int j = 0; j < i; ++j) { + List entityslice = aentityslice[j]; // Spigot + Iterator iterator = entityslice.iterator(); +@@ -1169,11 +1170,25 @@ public class WorldServer extends World implements GeneratorAccessSeed { + throw (IllegalStateException) SystemUtils.c((Throwable) (new IllegalStateException("Removing entity while ticking!"))); + } + ++ // Paper start - move out entities that shouldn't be in this chunk before it unloads ++ if (!entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { ++ toMoveChunks.add(entity); ++ continue; ++ } ++ // Paper end ++ + this.entitiesById.remove(entity.getId()); + this.unregisterEntity(entity); ++ ++ if (entity.dead) iterator.remove(); // Paper - don't save dead entities during unload + } + } + } ++ // Paper start - move out entities that shouldn't be in this chunk before it unloads ++ for (Entity entity : toMoveChunks) { ++ this.chunkCheck(entity); ++ } ++ // Paper end + + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index f301c7ba4b17b92c6cf2fcee6da1e67081dad4fa..69bc9dc18bab157851d8080a672504598e8572a8 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -26,6 +26,7 @@ import net.minecraft.nbt.NBTTagList; + import net.minecraft.nbt.NBTTagLongArray; + import net.minecraft.nbt.NBTTagShort; + import net.minecraft.server.level.ChunkProviderServer; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.LightEngineThreaded; + import net.minecraft.server.level.WorldServer; + import net.minecraft.world.entity.Entity; +@@ -349,6 +350,7 @@ public class ChunkRegionLoader { + nbttagcompound1.set("TileEntities", nbttaglist1); + NBTTagList nbttaglist2 = new NBTTagList(); + ++ java.util.List toUpdate = new java.util.ArrayList<>(); // Paper + if (ichunkaccess.getChunkStatus().getType() == ChunkStatus.Type.LEVELCHUNK) { + Chunk chunk = (Chunk) ichunkaccess; + +@@ -366,13 +368,28 @@ public class ChunkRegionLoader { + while (iterator1.hasNext()) { + Entity entity = (Entity) iterator1.next(); + NBTTagCompound nbttagcompound4 = new NBTTagCompound(); +- ++ // Paper start ++ if ((int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { ++ toUpdate.add(entity); ++ continue; ++ } ++ if (entity.dead || hasPlayerPassenger(entity)) { ++ continue; ++ } ++ // Paper end + if (entity.d(nbttagcompound4)) { + chunk.d(true); + nbttaglist2.add(nbttagcompound4); + } + } + } ++ ++ // Paper start - move entities to the correct chunk ++ for (Entity entity : toUpdate) { ++ worldserver.chunkCheck(entity); ++ } ++ // Paper end ++ + } else { + ProtoChunk protochunk = (ProtoChunk) ichunkaccess; + +@@ -431,6 +448,19 @@ public class ChunkRegionLoader { + nbttagcompound1.set("Structures", a(chunkcoordintpair, ichunkaccess.h(), ichunkaccess.v())); + return nbttagcompound; + } ++ // Paper start - this is saved with the player ++ private static boolean hasPlayerPassenger(Entity entity) { ++ for (Entity passenger : entity.passengers) { ++ if (passenger instanceof EntityPlayer) { ++ return true; ++ } ++ if (hasPlayerPassenger(passenger)) { ++ return true; ++ } ++ } ++ return false; ++ } ++ // Paper end + + public static ChunkStatus.Type a(@Nullable NBTTagCompound nbttagcompound) { + if (nbttagcompound != null) { diff --git a/patches/server-unmapped/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch b/patches/server-unmapped/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch new file mode 100644 index 0000000000..ab3543b44f --- /dev/null +++ b/patches/server-unmapped/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Thu, 26 Jul 2018 14:10:23 +0200 +Subject: [PATCH] Don't call getItemMeta on hasItemMeta + +Spigot 1.13 checks if any field (which are manually copied from the ItemStack's "tag" NBT tag) on the ItemMeta class of an ItemStack is set. + +We could just check if the "tag" NBT tag is empty, albeit that would break some plugins. The only general tag added on 1.13 is "Damage", and we can just check if the "tag" NBT tag contains any other tag that's not "Damage" (https://minecraft.gamepedia.com/Player.dat_format#Item_structure) making the `hasItemStack` method behave as before. + +Returns true if getDamage() == 0 or has damage tag or other tag is set. +Check the `ItemMetaTest#testTaggedButNotMeta` method to see how this method behaves. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index 315addab147dfecf4aa88d32d154cefe850d0a78..09d7a86b5f6cffdf6664ad657dd4f8dd8eabdd70 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -570,7 +570,7 @@ public final class CraftItemStack extends ItemStack { + + @Override + public boolean hasItemMeta() { +- return hasItemMeta(handle) && !CraftItemFactory.instance().equals(getItemMeta(), null); ++ return hasItemMeta(handle) && (handle.getDamage() != 0 || (handle.getTag() != null && handle.getTag().map.size() >= (handle.getTag().hasKey(CraftMetaItem.DAMAGE.NBT) ? 2 : 1))); // Paper - keep 1.12 CraftBukkit behavior without calling getItemMeta + } + + static boolean hasItemMeta(net.minecraft.world.item.ItemStack item) { +diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +index 42f577ed3508ba5a380648461e149f16ce97c9bd..b85a0a4c4f134dd6012d9141244ecf97b4300b65 100644 +--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java ++++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +@@ -96,6 +96,34 @@ public class ItemMetaTest extends AbstractTestingBase { + assertThat(itemMeta.hasConflictingEnchant(null), is(false)); + } + ++ // Paper start ++ private void testItemMeta(ItemStack stack) { ++ assertThat("Should not have ItemMeta", stack.hasItemMeta(), is(false)); ++ ++ stack.setDurability((short) 0); ++ assertThat("ItemStack with zero durability should not have ItemMeta", stack.hasItemMeta(), is(false)); ++ ++ stack.setDurability((short) 2); ++ assertThat("ItemStack with non-zero durability should have ItemMeta", stack.hasItemMeta(), is(true)); ++ ++ stack.setLore(java.util.Collections.singletonList("Lore")); ++ assertThat("ItemStack with lore and durability should have ItemMeta", stack.hasItemMeta(), is(true)); ++ ++ stack.setDurability((short) 0); ++ assertThat("ItemStack with lore should have ItemMeta", stack.hasItemMeta(), is(true)); ++ ++ stack.setLore(null); ++ } ++ ++ @Test ++ public void testHasItemMeta() { ++ ItemStack itemStack = new ItemStack(Material.SHEARS); ++ ++ testItemMeta(itemStack); ++ testItemMeta(CraftItemStack.asCraftCopy(itemStack)); ++ } ++ // Paper end ++ + @Test + public void testConflictingStoredEnchantment() { + EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) Bukkit.getItemFactory().getItemMeta(Material.ENCHANTED_BOOK); diff --git a/patches/server-unmapped/0253-Ignore-Dead-Entities-in-entityList-iteration.patch b/patches/server-unmapped/0253-Ignore-Dead-Entities-in-entityList-iteration.patch new file mode 100644 index 0000000000..a055870972 --- /dev/null +++ b/patches/server-unmapped/0253-Ignore-Dead-Entities-in-entityList-iteration.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 28 Jul 2018 12:18:27 -0400 +Subject: [PATCH] Ignore Dead Entities in entityList iteration + +A spigot change delays removal of entities from the entity list. +This causes a change in behavior from Vanilla where getEntities type +methods will return dead entities that they shouldn't otherwise be doing. + +This will ensure that dead entities are skipped from iteration since +they shouldn't of been in the list in the first place. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 6943524c2dd8b12691b8ac5b08daee823ce50c3d..b67bd98cca4a06bc0ebaed577195dffc3b3251ec 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -209,6 +209,7 @@ public class PaperCommand extends Command { + Collection entities = world.entitiesById.values(); + entities.forEach(e -> { + MinecraftKey key = e.getMinecraftKey(); ++ if (e.shouldBeRemoved) return; // Paper + + MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); + ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index e39f1ea4eefb0d8e0ca379b116b3699c13bb3f35..9151d84e2f6fb316525c74466589178769fbc8ef 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1309,6 +1309,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + entity.origin = entity.getBukkitEntity().getLocation(); + } + // Paper end ++ entity.shouldBeRemoved = false; // Paper - shouldn't be removed after being re-added + new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + } + +@@ -1321,6 +1322,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.removeEntityFromChunk(entity); + this.entitiesById.remove(entity.getId()); + this.unregisterEntity(entity); ++ entity.shouldBeRemoved = true; // Paper + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a6f0cde7bdc930abced5063da237bcd27ddcd20f..37497d7ff04b84d4758997970dbdbf88b40d0493 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -276,6 +276,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end ++ public boolean shouldBeRemoved; // Paper + + public float getBukkitYaw() { + return this.yaw; +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index e4accac8f2e8daa58f9b0c279ffcad9347448bb0..79ff96f18c53f3d1ce4a00be2e2d8fe68f77bf54 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -863,6 +863,7 @@ public class Chunk implements IChunkAccess { + + for (int i1 = 0; i1 < l; ++i1) { + Entity entity1 = (Entity) list1.get(i1); ++ if (entity1.shouldBeRemoved) continue; // Paper + + if (entity1.getBoundingBox().c(axisalignedbb) && entity1 != entity) { + if (predicate == null || predicate.test(entity1)) { +@@ -900,6 +901,7 @@ public class Chunk implements IChunkAccess { + + while (iterator.hasNext()) { + T entity = (T) iterator.next(); // CraftBukkit - decompile error ++ if (entity.shouldBeRemoved) continue; // Paper + + if ((entitytypes == null || entity.getEntityType() == entitytypes) && entity.getBoundingBox().c(axisalignedbb) && predicate.test(entity)) { + list.add(entity); +@@ -922,6 +924,7 @@ public class Chunk implements IChunkAccess { + + while (iterator.hasNext()) { + T t0 = (T) iterator.next(); // CraftBukkit - decompile error ++ if (t0.shouldBeRemoved) continue; // Paper + + if (oclass.isInstance(t0) && t0.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.test(t0))) { // Spigot - instance check + list.add(t0); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index a2b3f5106edc8328ba7edd65dedd56e0dc8d33d2..e7103b8021141071712759b1056eccb5e3da93b7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1040,6 +1040,7 @@ public class CraftWorld implements World { + for (Object o : world.entitiesById.values()) { + if (o instanceof net.minecraft.world.entity.Entity) { + net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; ++ if (mcEnt.shouldBeRemoved) continue; // Paper + Entity bukkitEntity = mcEnt.getBukkitEntity(); + + // Assuming that bukkitEntity isn't null +@@ -1059,6 +1060,7 @@ public class CraftWorld implements World { + for (Object o : world.entitiesById.values()) { + if (o instanceof net.minecraft.world.entity.Entity) { + net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; ++ if (mcEnt.shouldBeRemoved) continue; // Paper + Entity bukkitEntity = mcEnt.getBukkitEntity(); + + // Assuming that bukkitEntity isn't null +@@ -1085,6 +1087,7 @@ public class CraftWorld implements World { + + for (Object entity: world.entitiesById.values()) { + if (entity instanceof net.minecraft.world.entity.Entity) { ++ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper + Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); + + if (bukkitEntity == null) { +@@ -1108,6 +1111,7 @@ public class CraftWorld implements World { + + for (Object entity: world.entitiesById.values()) { + if (entity instanceof net.minecraft.world.entity.Entity) { ++ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper + Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); + + if (bukkitEntity == null) { diff --git a/patches/server-unmapped/0254-Implement-Expanded-ArmorStand-API.patch b/patches/server-unmapped/0254-Implement-Expanded-ArmorStand-API.patch new file mode 100644 index 0000000000..55ff4fad22 --- /dev/null +++ b/patches/server-unmapped/0254-Implement-Expanded-ArmorStand-API.patch @@ -0,0 +1,112 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: willies952002 +Date: Thu, 26 Jul 2018 02:25:46 -0400 +Subject: [PATCH] Implement Expanded ArmorStand API + +Add the following: +- Add proper methods for getting and setting items in both hands. Deprecates old methods +- Enable/Disable slot interactions + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +index 829013f57128cc6c92a45098c6883f2305cf4ea5..e97d25339b37a70f91022dcb021bbe82fb8f5eda 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +@@ -430,6 +430,7 @@ public class EntityArmorStand extends EntityLiving { + return enumitemslot; + } + ++ public final boolean isSlotDisabled(EnumItemSlot slot) { return this.d(slot); } // Paper - OBFHELPER + private boolean d(EnumItemSlot enumitemslot) { + return (this.disabledSlots & 1 << enumitemslot.getSlotFlag()) != 0 || enumitemslot.a() == EnumItemSlot.Function.HAND && !this.hasArms(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +index 6f922e4cbb095439fcd76ee0d0c08bc4160b8107..103f935d9b7a2cbe9639528c587d8ac2e5f14d07 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +@@ -1,6 +1,7 @@ + package org.bukkit.craftbukkit.entity; + + import net.minecraft.core.Vector3f; ++import net.minecraft.world.entity.EnumItemSlot; + import net.minecraft.world.entity.decoration.EntityArmorStand; + import org.bukkit.craftbukkit.CraftEquipmentSlot; + import org.bukkit.craftbukkit.CraftServer; +@@ -239,5 +240,78 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public void setCanMove(boolean move) { + getHandle().canMove = move; + } ++ ++ @Override ++ public ItemStack getItem(org.bukkit.inventory.EquipmentSlot slot) { ++ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); ++ return getHandle().getEquipment(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)).asBukkitMirror(); ++ } ++ ++ @Override ++ public void setItem(org.bukkit.inventory.EquipmentSlot slot, ItemStack item) { ++ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); ++ switch (slot) { ++ case HAND: ++ getEquipment().setItemInMainHand(item); ++ return; ++ case OFF_HAND: ++ getEquipment().setItemInOffHand(item); ++ return; ++ case FEET: ++ setBoots(item); ++ return; ++ case LEGS: ++ setLeggings(item); ++ return; ++ case CHEST: ++ setChestplate(item); ++ return; ++ case HEAD: ++ setHelmet(item); ++ return; ++ } ++ throw new UnsupportedOperationException(slot.name()); ++ } ++ ++ @Override ++ public java.util.Set getDisabledSlots() { ++ java.util.Set disabled = new java.util.HashSet<>(); ++ for (org.bukkit.inventory.EquipmentSlot slot : org.bukkit.inventory.EquipmentSlot.values()) { ++ if (this.isSlotDisabled(slot)) { ++ disabled.add(slot); ++ } ++ } ++ return disabled; ++ } ++ ++ @Override ++ public void setDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { ++ int disabled = 0; ++ for (org.bukkit.inventory.EquipmentSlot slot : slots) { ++ if (slot == org.bukkit.inventory.EquipmentSlot.OFF_HAND) continue; ++ EnumItemSlot nmsSlot = org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot); ++ disabled += (1 << nmsSlot.getSlotFlag()) + (1 << (nmsSlot.getSlotFlag() + 8)) + (1 << (nmsSlot.getSlotFlag() + 16)); ++ } ++ getHandle().disabledSlots = disabled; ++ } ++ ++ @Override ++ public void addDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { ++ java.util.Set disabled = getDisabledSlots(); ++ java.util.Collections.addAll(disabled, slots); ++ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); ++ } ++ ++ @Override ++ public void removeDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { ++ java.util.Set disabled = getDisabledSlots(); ++ for (final org.bukkit.inventory.EquipmentSlot slot : slots) disabled.remove(slot); ++ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); ++ } ++ ++ @Override ++ public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { ++ return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0255-AnvilDamageEvent.patch b/patches/server-unmapped/0255-AnvilDamageEvent.patch new file mode 100644 index 0000000000..3862e6017e --- /dev/null +++ b/patches/server-unmapped/0255-AnvilDamageEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 20 Jul 2018 23:37:03 -0500 +Subject: [PATCH] AnvilDamageEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java +index 9658c8206b5bab07838284935e9d5e0879e405f2..ff618bbb3fc4acfce51f5e5e6a504a63e9ad77cd 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java +@@ -80,7 +80,16 @@ public class ContainerAnvil extends ContainerAnvilAbstract { + + if (!entityhuman.abilities.canInstantlyBuild && iblockdata.a((Tag) TagsBlock.ANVIL) && entityhuman.getRandom().nextFloat() < 0.12F) { + IBlockData iblockdata1 = BlockAnvil.c(iblockdata); +- ++ // Paper start ++ com.destroystokyo.paper.event.block.AnvilDamagedEvent event = new com.destroystokyo.paper.event.block.AnvilDamagedEvent(getBukkitView(), iblockdata1 != null ? org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(iblockdata1) : null); ++ if (!event.callEvent()) { ++ return; ++ } else if (event.getDamageState() == com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState.BROKEN) { ++ iblockdata1 = null; ++ } else { ++ iblockdata1 = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getDamageState().getMaterial().createBlockData()).getState().set(BlockAnvil.FACING, iblockdata.get(BlockAnvil.FACING)); ++ } ++ // Paper end + if (iblockdata1 == null) { + world.a(blockposition, false); + world.triggerEffect(1029, blockposition, 0); diff --git a/patches/server-unmapped/0256-Add-TNTPrimeEvent.patch b/patches/server-unmapped/0256-Add-TNTPrimeEvent.patch new file mode 100644 index 0000000000..e848d18de0 --- /dev/null +++ b/patches/server-unmapped/0256-Add-TNTPrimeEvent.patch @@ -0,0 +1,148 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Mon, 16 Jul 2018 00:05:05 +0300 +Subject: [PATCH] Add TNTPrimeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +index 97ef4c65c8cc569a99d9697f56bd44d32b151328..51993191e01f55e16667c25b8b57d6a6ddaf493b 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +@@ -61,6 +61,7 @@ import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.event.entity.EntityExplodeEvent; + import org.bukkit.event.entity.EntityRegainHealthEvent; + // CraftBukkit end ++import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent + + public class EntityEnderDragon extends EntityInsentient implements IMonster { + +@@ -515,6 +516,11 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + }); + craftBlock.getNMS().dropNaturally((WorldServer) world, blockposition, ItemStack.b); + } ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, explosionSource.getSource().getBukkitEntity()).callEvent()) ++ continue; ++ // Paper end + nmsBlock.wasExploded(world, blockposition, explosionSource); + + this.world.a(blockposition, false); +diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java +index c22fad0038fdb0769e23db782e3341206fbd80f9..5ef38414d87fbce453e3ab11579c89a8ff089ae0 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockFire.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java +@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; + import com.google.common.collect.ImmutableMap; + import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent + import java.util.Map; + import java.util.Random; + import java.util.function.Function; +@@ -11,6 +12,7 @@ import net.minecraft.SystemUtils; + import net.minecraft.core.BaseBlockPosition; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.WorldServer; + import net.minecraft.world.item.context.BlockActionContext; + import net.minecraft.world.level.GameRules; +@@ -289,7 +291,7 @@ public class BlockFire extends BlockFireAbstract { + + world.setTypeAndData(blockposition, this.a(world, blockposition, l), 3); + } else { +- world.a(blockposition, false); ++ if(iblockdata.getBlock() != Blocks.TNT) world.a(blockposition, false); // Paper - TNTPrimeEvent - We might be cancelling it below, move the setAir down + } + + Block block = iblockdata.getBlock(); +@@ -297,6 +299,13 @@ public class BlockFire extends BlockFireAbstract { + if (block instanceof BlockTNT) { + BlockTNT blocktnt = (BlockTNT) block; + ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = MCUtil.toBukkitBlock(world, blockposition); ++ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.FIRE, null).callEvent()) { ++ return; ++ } ++ world.setAir(blockposition, false); ++ // Paper end + BlockTNT.a(world, blockposition); + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockTNT.java b/src/main/java/net/minecraft/world/level/block/BlockTNT.java +index b5d40898bb4a10b3170cd1f42f1a44de539d53c3..71c46d5042f7e4585b364682cd5464edccdf43f6 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockTNT.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockTNT.java +@@ -22,6 +22,7 @@ import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockProperties; + import net.minecraft.world.level.block.state.properties.BlockStateBoolean; + import net.minecraft.world.phys.MovingObjectPositionBlock; ++import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent + + public class BlockTNT extends Block { + +@@ -36,6 +37,11 @@ public class BlockTNT extends Block { + public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { + if (!iblockdata1.a(iblockdata.getBlock())) { + if (world.isBlockIndirectlyPowered(blockposition)) { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition);; ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) ++ return; ++ // Paper end + a(world, blockposition); + world.a(blockposition, false); + } +@@ -46,6 +52,11 @@ public class BlockTNT extends Block { + @Override + public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { + if (world.isBlockIndirectlyPowered(blockposition)) { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition);; ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) ++ return; ++ // Paper end + a(world, blockposition); + world.a(blockposition, false); + } +@@ -64,6 +75,12 @@ public class BlockTNT extends Block { + @Override + public void wasExploded(World world, BlockPosition blockposition, Explosion explosion) { + if (!world.isClientSide) { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); ++ org.bukkit.entity.Entity source = explosion.source != null ? explosion.source.getBukkitEntity() : null; ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) ++ return; ++ // Paper end + EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, explosion.getSource()); + + entitytntprimed.setFuseTicks((short) (world.random.nextInt(entitytntprimed.getFuseTicks() / 4) + entitytntprimed.getFuseTicks() / 8)); +@@ -92,6 +109,11 @@ public class BlockTNT extends Block { + if (item != Items.FLINT_AND_STEEL && item != Items.FIRE_CHARGE) { + return super.interact(iblockdata, world, blockposition, entityhuman, enumhand, movingobjectpositionblock); + } else { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); ++ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.ITEM, entityhuman.getBukkitEntity()).callEvent()) ++ return EnumInteractionResult.FAIL; ++ // Paper end + a(world, blockposition, (EntityLiving) entityhuman); + world.setTypeAndData(blockposition, Blocks.AIR.getBlockData(), 11); + if (!entityhuman.isCreative()) { +@@ -121,6 +143,13 @@ public class BlockTNT extends Block { + } + // CraftBukkit end + ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); ++ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.PROJECTILE, iprojectile.getBukkitEntity()).callEvent()) { ++ return; ++ } ++ // Paper end ++ + a(world, blockposition, entity instanceof EntityLiving ? (EntityLiving) entity : null); + world.a(blockposition, false); + } diff --git a/patches/server-unmapped/0257-Break-up-and-make-tab-spam-limits-configurable.patch b/patches/server-unmapped/0257-Break-up-and-make-tab-spam-limits-configurable.patch new file mode 100644 index 0000000000..79865d178b --- /dev/null +++ b/patches/server-unmapped/0257-Break-up-and-make-tab-spam-limits-configurable.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 29 Jul 2018 05:02:15 +0100 +Subject: [PATCH] Break up and make tab spam limits configurable + +Due to the changes in 1.13, clients will send a tab completion request +for all bukkit commands in order to factor in the lack of support for +brigadier and provide backwards support in the API. + +Craftbukkit, however; has moved the chat spam limiter to also interact +with the tab completion request, which while good for avoiding abuse, +causes 1.13 clients to easilly be kicked from a server in bukkit due +to this. Removing the spam limit could cause issues for servers, however, +there is no way for servers to manipulate this without blindly cancelling +kick events, which only causes additional complications. This also causes +issues in that the tab spam limit and chat share the same field but different +limits, meaning that a player having typed a long command may be kicked from +the server. + +Splitting the field up and making it configurable allows for server owners +to take the burden of this into their own hand without having to rely on +plugins doing unsafe things. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 77a03abd59db4a43f6f2d59d4c7ef176e782f205..bd508025b771424c942fd856c31d520b6f548082 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -296,4 +296,18 @@ public class PaperConfig { + Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); + } + } ++ ++ public static int tabSpamIncrement = 1; ++ public static int tabSpamLimit = 500; ++ private static void tabSpamLimiters() { ++ tabSpamIncrement = getInt("settings.spam-limiter.tab-spam-increment", tabSpamIncrement); ++ // Older versions used a smaller limit, which is too low for 1.13, we'll bump this up if default ++ if (version < 14) { ++ if (tabSpamIncrement == 10) { ++ set("settings.spam-limiter.tab-spam-increment", 2); ++ tabSpamIncrement = 2; ++ } ++ } ++ tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index ed5e13f668d09dcf56cec8c6269a5fbd93d156bd..b9825537599a8df8d772b2db4d56d5e28cc2bbe9 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -230,6 +230,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + // CraftBukkit start - multithreaded fields + private volatile int chatThrottle; + private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); ++ private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits + // CraftBukkit end + private int j; + private final Int2ShortMap k = new Int2ShortOpenHashMap(); +@@ -365,6 +366,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + this.minecraftServer.getMethodProfiler().exit(); + // CraftBukkit start + for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; ++ if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable + /* Use thread-safe field access instead + if (this.chatThrottle > 0) { + --this.chatThrottle; +@@ -716,7 +718,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + public void a(PacketPlayInTabComplete packetplayintabcomplete) { + // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async + // CraftBukkit start +- if (chatSpamField.addAndGet(this, 1) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { ++ if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { // Paper start - split and make configurable + minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper + return; + } diff --git a/patches/server-unmapped/0258-Add-hand-to-bucket-events.patch b/patches/server-unmapped/0258-Add-hand-to-bucket-events.patch new file mode 100644 index 0000000000..32d4088d7a --- /dev/null +++ b/patches/server-unmapped/0258-Add-hand-to-bucket-events.patch @@ -0,0 +1,174 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Thu, 2 Aug 2018 08:44:35 -0500 +Subject: [PATCH] Add hand to bucket events + + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 9151d84e2f6fb316525c74466589178769fbc8ef..ecb4cb5df868673e5aa2eec3fdd8618dbea09655 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1657,15 +1657,17 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.getMinecraftServer().getPlayerList().sendAll(new PacketPlayOutSpawnPosition(blockposition, f)); + } + +- public BlockPosition getSpawn() { +- BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); +- +- if (!this.getWorldBorder().a(blockposition)) { +- blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); +- } +- +- return blockposition; +- } ++ // Paper - moved up to World ++ //public BlockPosition getSpawn() { ++ // BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); ++ // ++ // if (!this.getWorldBorder().a(blockposition)) { ++ // blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); ++ // } ++ // ++ // return blockposition; ++ //} ++ // Paper end + + public float v() { + return this.worldData.d(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java +index ef48ae4d398a1dd5bc67262ccdb5d8fc6bb2769c..1b43688ad232620410aa924cef02b54630ab1313 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java +@@ -88,7 +88,7 @@ public class EntityCow extends EntityAnimal { + + if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) { + // CraftBukkit start - Got milk? +- org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET); ++ org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET, enumhand); // Paper - add enumHand + + if (event.isCancelled()) { + return EnumInteractionResult.PASS; +diff --git a/src/main/java/net/minecraft/world/item/ItemBucket.java b/src/main/java/net/minecraft/world/item/ItemBucket.java +index 4bcac8defeaa146713cce43e04a51c1c9afddb1f..d126f668828e0788e369294c0b376ef52b344f2c 100644 +--- a/src/main/java/net/minecraft/world/item/ItemBucket.java ++++ b/src/main/java/net/minecraft/world/item/ItemBucket.java +@@ -71,7 +71,7 @@ public class ItemBucket extends Item { + if (iblockdata.getBlock() instanceof IFluidSource) { + // CraftBukkit start + FluidType dummyFluid = ((IFluidSource) iblockdata.getBlock()).removeFluid(DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); +- PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) world, entityhuman, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.a()); ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) world, entityhuman, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.a(), enumhand); // Paper - add enumhand + + if (event.isCancelled()) { + ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) +@@ -99,7 +99,7 @@ public class ItemBucket extends Item { + iblockdata = world.getType(blockposition); + BlockPosition blockposition2 = iblockdata.getBlock() instanceof IFluidContainer && this.fluidType == FluidTypes.WATER ? blockposition : blockposition1; + +- if (this.a(entityhuman, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack)) { // CraftBukkit ++ if (this.a(entityhuman, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack, enumhand)) { // CraftBukkit // Paper - add enumhand + this.a(world, itemstack, blockposition2); + if (entityhuman instanceof EntityPlayer) { + CriterionTriggers.y.a((EntityPlayer) entityhuman, blockposition2, itemstack); +@@ -124,10 +124,12 @@ public class ItemBucket extends Item { + public void a(World world, ItemStack itemstack, BlockPosition blockposition) {} + + public boolean a(@Nullable EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock) { +- return a(entityhuman, world, blockposition, movingobjectpositionblock, null, null, null); ++ // Paper start - add enumHand ++ return a(entityhuman, world, blockposition, movingobjectpositionblock, null, null, null, null); + } + +- public boolean a(EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock, EnumDirection enumdirection, BlockPosition clicked, ItemStack itemstack) { ++ public boolean a(EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock, EnumDirection enumdirection, BlockPosition clicked, ItemStack itemstack, EnumHand enumhand) { ++ // Paper end + // CraftBukkit end + if (!(this.fluidType instanceof FluidTypeFlowing)) { + return false; +@@ -140,7 +142,7 @@ public class ItemBucket extends Item { + + // CraftBukkit start + if (flag1 && entityhuman != null) { +- PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((WorldServer) world, entityhuman, blockposition, clicked, enumdirection, itemstack); ++ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((WorldServer) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); // Paper - add enumhand + if (event.isCancelled()) { + ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition)); // SPIGOT-4238: needed when looking through entity + ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 +@@ -149,7 +151,7 @@ public class ItemBucket extends Item { + } + // CraftBukkit end + if (!flag1) { +- return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPosition().shift(movingobjectpositionblock.getDirection()), (MovingObjectPositionBlock) null, enumdirection, clicked, itemstack); // CraftBukkit ++ return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPosition().shift(movingobjectpositionblock.getDirection()), (MovingObjectPositionBlock) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit // Paper - add enumhand + } else if (world.getDimensionManager().isNether() && this.fluidType.a((Tag) TagsFluid.WATER)) { + int i = blockposition.getX(); + int j = blockposition.getY(); +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 07c5cdd00930a55fd412ef95f71f55ee908189a1..88b1a0235bfc0b41ae1855f8900632e425730d1c 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -277,6 +277,17 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + } + // Paper end + ++ // Paper start - moved up from WorldServer ++ public BlockPosition getSpawn() { ++ BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); ++ ++ if (!this.getWorldBorder().a(blockposition)) { ++ blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); ++ } ++ ++ return blockposition; ++ } ++ // Paper end + @Override + public boolean s_() { + 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 31358b90784a6e983ff8b687021c721ed5d43eab..338b319910d12cf62ab9c5977257ad1ccec5544a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -234,7 +234,7 @@ public class CraftEventFactory { + public static Entity entityDamage; // For use in EntityDamageByEntityEvent + + // helper methods +- private static boolean canBuild(WorldServer world, Player player, int x, int z) { ++ private static boolean canBuild(World world, Player player, int x, int z) { + int spawnSize = Bukkit.getServer().getSpawnRadius(); + + if (world.getDimensionKey() != World.OVERWORLD) return true; +@@ -424,6 +424,20 @@ public class CraftEventFactory { + } + + private static PlayerEvent getPlayerBucketEvent(boolean isFilling, WorldServer world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item) { ++ // Paper start - add enumHand ++ return getPlayerBucketEvent(isFilling, world, who, changed, clicked, clickedFace, itemstack, item, null); ++ } ++ ++ public static PlayerBucketEmptyEvent callPlayerBucketEmptyEvent(World world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemstack, EnumHand enumHand) { ++ return (PlayerBucketEmptyEvent) getPlayerBucketEvent(false, world, who, changed, clicked, clickedFace, itemstack, Items.BUCKET, enumHand); ++ } ++ ++ public static PlayerBucketFillEvent callPlayerBucketFillEvent(World world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemInHand, net.minecraft.world.item.Item bucket, EnumHand enumHand) { ++ return (PlayerBucketFillEvent) getPlayerBucketEvent(true, world, who, clicked, changed, clickedFace, itemInHand, bucket, enumHand); ++ } ++ ++ private static PlayerEvent getPlayerBucketEvent(boolean isFilling, World world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item, EnumHand enumHand) { ++ // Paper end + Player player = (Player) who.getBukkitEntity(); + CraftItemStack itemInHand = CraftItemStack.asNewCraftStack(item); + Material bucket = CraftMagicNumbers.getMaterial(itemstack.getItem()); +@@ -436,10 +450,10 @@ public class CraftEventFactory { + + PlayerEvent event; + if (isFilling) { +- event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand); ++ event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == EnumHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand + ((PlayerBucketFillEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); + } else { +- event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand); ++ event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == EnumHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand + ((PlayerBucketEmptyEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); + } + diff --git a/patches/server-unmapped/0259-MC-135506-Experience-should-save-as-Integers.patch b/patches/server-unmapped/0259-MC-135506-Experience-should-save-as-Integers.patch new file mode 100644 index 0000000000..7c85de6290 --- /dev/null +++ b/patches/server-unmapped/0259-MC-135506-Experience-should-save-as-Integers.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 3 Aug 2018 00:04:54 -0400 +Subject: [PATCH] MC-135506: Experience should save as Integers + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java +index 3387a19044b3ee2a1ef549c328c8bc354a5b6d23..a7551e95185895a290be70d501496279eaf884ae 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java +@@ -218,7 +218,7 @@ public class EntityExperienceOrb extends Entity { + public void saveData(NBTTagCompound nbttagcompound) { + nbttagcompound.setShort("Health", (short) this.e); + nbttagcompound.setShort("Age", (short) this.c); +- nbttagcompound.setShort("Value", (short) this.value); ++ nbttagcompound.setInt("Value", this.value); // Paper - save as Integer + this.savePaperNBT(nbttagcompound); // Paper + } + +@@ -226,7 +226,7 @@ public class EntityExperienceOrb extends Entity { + public void loadData(NBTTagCompound nbttagcompound) { + this.e = nbttagcompound.getShort("Health"); + this.c = nbttagcompound.getShort("Age"); +- this.value = nbttagcompound.getShort("Value"); ++ this.value = nbttagcompound.getInt("Value"); // Paper - load as Integer + this.loadPaperNBT(nbttagcompound); // Paper + } + diff --git a/patches/server-unmapped/0260-Fix-client-rendering-skulls-from-same-user.patch b/patches/server-unmapped/0260-Fix-client-rendering-skulls-from-same-user.patch new file mode 100644 index 0000000000..93f74c95ce --- /dev/null +++ b/patches/server-unmapped/0260-Fix-client-rendering-skulls-from-same-user.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 22 Nov 2016 00:40:42 -0500 +Subject: [PATCH] Fix client rendering skulls from same user + +See: https://github.com/PaperMC/Paper/issues/1304 + +Changes the UUID sent to client to be based on either +the texture payload, or random. + +This allows the client to render multiple skull textures from the same user, +for when different skins were used when skull was made. + +diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java +index df459918c14589155a574730205cb35d463b8079..5a1187b001004afe22d208bc5d7c288e796e16a6 100644 +--- a/src/main/java/net/minecraft/network/PacketDataSerializer.java ++++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java +@@ -37,6 +37,7 @@ import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.block.entity.TileEntitySkull; + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.Vec3D; + +@@ -311,9 +312,18 @@ public class PacketDataSerializer extends ByteBuf { + if (item.usesDurability() || item.n()) { + // Spigot start - filter + itemstack = itemstack.cloneItemStack(); +- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ //CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported + // Spigot end + nbttagcompound = itemstack.getTag(); ++ // Paper start ++ if (nbttagcompound != null && nbttagcompound.hasKeyOfType("SkullOwner", 10)) { ++ NBTTagCompound owner = nbttagcompound.getCompound("SkullOwner"); ++ if (owner.hasUUID("Id")) { ++ nbttagcompound.setUUID("SkullOwnerOrig", owner.getUUID("Id")); ++ TileEntitySkull.sanitizeUUID(owner); ++ } ++ } ++ // Paper end + } + + this.a(nbttagcompound); +@@ -333,7 +343,16 @@ public class PacketDataSerializer extends ByteBuf { + itemstack.setTag(this.l()); + // CraftBukkit start + if (itemstack.getTag() != null) { +- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ // Paper start - Fix skulls of same owner - restore orig ID since we changed it on send to client ++ if (itemstack.tag.hasKey("SkullOwnerOrig")) { ++ NBTTagCompound owner = itemstack.tag.getCompound("SkullOwner"); ++ if (itemstack.tag.hasKey("SkullOwnerOrig")) { ++ owner.map.put("Id", itemstack.tag.map.get("SkullOwnerOrig")); ++ itemstack.tag.remove("SkullOwnerOrig"); ++ } ++ } ++ // Paper end ++ // CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported + } + // CraftBukkit end + return itemstack; +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java +index b6b55d5baa5e8a6b69a3e4865c06bc8a4d61a4f3..152118729b1a95dcae05d32aa4289034ba394226 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java +@@ -15,6 +15,7 @@ import net.minecraft.network.PacketDataSerializer; + import net.minecraft.network.protocol.Packet; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.block.entity.TileEntity; ++import net.minecraft.world.level.block.entity.TileEntitySkull; + import net.minecraft.world.level.chunk.BiomeStorage; + import net.minecraft.world.level.chunk.Chunk; + import net.minecraft.world.level.chunk.ChunkSection; +@@ -69,6 +70,7 @@ public class PacketPlayOutMapChunk implements Packet { + + if (this.f() || (i & 1 << j) != 0) { + NBTTagCompound nbttagcompound = tileentity.b(); ++ if (tileentity instanceof TileEntitySkull) { TileEntitySkull.sanitizeTileEntityUUID(nbttagcompound); } // Paper + + this.g.add(nbttagcompound); + } +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 2ac8b6ac38bdca26cddfb8652f13b0be0c4000fe..24db5dedf8b41b26fa990a7c7317cdb3e89e7fcd 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -114,7 +114,7 @@ public final class ItemStack { + private int g; + @Deprecated + private Item item; +- private NBTTagCompound tag; ++ public NBTTagCompound tag; // Paper private -> public + private boolean j; + private Entity k; + private ShapeDetectorBlock l; +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java +index 22217f24b4a87f10b6d5a3e37d23a1164af84ace..4f7c014fa609a39cac651ccc6d3397d7edb77d8d 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java +@@ -9,6 +9,7 @@ import java.util.UUID; + import javax.annotation.Nullable; + import net.minecraft.nbt.GameProfileSerializer; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.nbt.NBTTagList; + import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; + import net.minecraft.server.players.UserCache; + import net.minecraft.util.UtilColor; +@@ -154,9 +155,37 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa + @Nullable + @Override + public PacketPlayOutTileEntityData getUpdatePacket() { +- return new PacketPlayOutTileEntityData(this.position, 4, this.b()); ++ return new PacketPlayOutTileEntityData(this.position, 4, sanitizeTileEntityUUID(this.b())); // Paper + } + ++ // Paper start ++ public static NBTTagCompound sanitizeTileEntityUUID(NBTTagCompound cmp) { ++ NBTTagCompound owner = cmp.getCompound("Owner"); ++ if (!owner.isEmpty()) { ++ sanitizeUUID(owner); ++ } ++ return cmp; ++ } ++ ++ public static void sanitizeUUID(NBTTagCompound owner) { ++ NBTTagCompound properties = owner.getCompound("Properties"); ++ NBTTagList list = null; ++ if (!properties.isEmpty()) { ++ list = properties.getList("textures", 10); ++ } ++ ++ if (list != null && !list.isEmpty()) { ++ String textures = ((NBTTagCompound)list.get(0)).getString("Value"); ++ if (textures != null && textures.length() > 3) { ++ UUID uuid = UUID.nameUUIDFromBytes(textures.getBytes()); ++ owner.setUUID("Id", uuid); ++ return; ++ } ++ } ++ owner.setUUID("Id", UUID.randomUUID()); ++ } ++ // Paper end ++ + @Override + public NBTTagCompound b() { + return this.save(new NBTTagCompound()); diff --git a/patches/server-unmapped/0261-Add-Early-Warning-Feature-to-WatchDog.patch b/patches/server-unmapped/0261-Add-Early-Warning-Feature-to-WatchDog.patch new file mode 100644 index 0000000000..98af37509a --- /dev/null +++ b/patches/server-unmapped/0261-Add-Early-Warning-Feature-to-WatchDog.patch @@ -0,0 +1,184 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: miclebrick +Date: Wed, 8 Aug 2018 15:30:52 -0400 +Subject: [PATCH] Add Early Warning Feature to WatchDog + +Detect when the server has been hung for a long duration, and start printing +thread dumps at an interval until the point of crash. + +This will help diagnose what was going on in that time before the crash. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index bd508025b771424c942fd856c31d520b6f548082..62621562137cba4804f0465c58d25ca2786328e5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -25,6 +25,7 @@ import org.bukkit.configuration.file.YamlConfiguration; + import co.aikar.timings.Timings; + import co.aikar.timings.TimingsManager; + import org.spigotmc.SpigotConfig; ++import org.spigotmc.WatchdogThread; + + public class PaperConfig { + +@@ -297,6 +298,14 @@ public class PaperConfig { + } + } + ++ public static int watchdogPrintEarlyWarningEvery = 5000; ++ public static int watchdogPrintEarlyWarningDelay = 10000; ++ private static void watchdogEarlyWarning() { ++ watchdogPrintEarlyWarningEvery = getInt("settings.watchdog.early-warning-every", 5000); ++ watchdogPrintEarlyWarningDelay = getInt("settings.watchdog.early-warning-delay", 10000); ++ WatchdogThread.doStart(SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash ); ++ } ++ + public static int tabSpamIncrement = 1; + public static int tabSpamLimit = 500; + private static void tabSpamLimiters() { +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 5bbd3bb52b76b8b6cdf90c94bcb29f122f31c543..52c0dd4f2779125116d9dcccc2aef7a11af92945 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1019,6 +1019,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable ++ // Paper start ++ Logger log = Bukkit.getServer().getLogger(); ++ long currentTime = monotonicMillis(); ++ if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) + { +- Logger log = Bukkit.getServer().getLogger(); ++ boolean isLongTimeout = currentTime > lastTick + timeoutTime; ++ // Don't spam early warning dumps ++ if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; ++ if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... ++ lastEarlyWarning = currentTime; ++ if (isLongTimeout) { ++ // Paper end + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper + log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); +@@ -93,29 +108,46 @@ public class WatchdogThread extends Thread + } + } + // Paper end ++ } else ++ { ++ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); ++ log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump"); ++ } ++ // Paper end - Different message for short timeout + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // ++ // Paper start - Only print full dump on long timeouts ++ if ( isLongTimeout ) ++ { + log.log( Level.SEVERE, "Entire Thread Dump:" ); + ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); + for ( ThreadInfo thread : threads ) + { + dumpThread( thread, log ); + } ++ } else { ++ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---"); ++ } ++ ++ + log.log( Level.SEVERE, "------------------------------" ); + ++ if ( isLongTimeout ) ++ { + if ( restart && !MinecraftServer.getServer().hasStopped() ) + { + RestartCommand.restart(); + } + break; ++ } // Paper end + } + + try + { +- sleep( 10000 ); ++ sleep( 1000 ); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout + } catch ( InterruptedException ex ) + { + interrupt(); diff --git a/patches/server-unmapped/0262-Make-EnderDragon-implement-Mob.patch b/patches/server-unmapped/0262-Make-EnderDragon-implement-Mob.patch new file mode 100644 index 0000000000..cce5f2ddd2 --- /dev/null +++ b/patches/server-unmapped/0262-Make-EnderDragon-implement-Mob.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 10 Aug 2018 22:11:49 -0400 +Subject: [PATCH] Make EnderDragon implement Mob + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java +index 3550eb81b66cad3cdfa41ddb5bb554b541cbbfe1..b537732070c784a97a96ccb77c211646b00580cc 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java +@@ -1,17 +1,18 @@ + package org.bukkit.craftbukkit.entity; + ++import net.minecraft.world.entity.EntityInsentient; // Paper + import net.minecraft.world.entity.EntityLiving; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.ComplexLivingEntity; + +-public abstract class CraftComplexLivingEntity extends CraftLivingEntity implements ComplexLivingEntity { +- public CraftComplexLivingEntity(CraftServer server, EntityLiving entity) { ++public abstract class CraftComplexLivingEntity extends CraftMob implements ComplexLivingEntity { // Paper ++ public CraftComplexLivingEntity(CraftServer server, EntityInsentient entity) { // Paper + super(server, entity); + } + + @Override +- public EntityLiving getHandle() { +- return (EntityLiving) entity; ++ public EntityInsentient getHandle() { // Paper ++ return (EntityInsentient) entity; // Paper + } + + @Override diff --git a/patches/server-unmapped/0263-Use-ConcurrentHashMap-in-JsonList.patch b/patches/server-unmapped/0263-Use-ConcurrentHashMap-in-JsonList.patch new file mode 100644 index 0000000000..8582eff151 --- /dev/null +++ b/patches/server-unmapped/0263-Use-ConcurrentHashMap-in-JsonList.patch @@ -0,0 +1,136 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: egg82 +Date: Tue, 7 Aug 2018 01:24:23 -0600 +Subject: [PATCH] Use ConcurrentHashMap in JsonList + +This is specifically aimed at fixing #471 + +Using a ConcurrentHashMap because thread safety +The performance benefit of Map over ConcurrentMap is negligabe at best in this scenaio, as most operations will be get and not add or remove +Even without considering the use-case the benefits are still negligable + +Original ideas for the system included an expiration policy and/or handler +The simpler solution was to use a computeIfPresent in the get method +This will simultaneously have an O(1) lookup time and automatically expire any values +Since the get method (nor other similar methods) don't seem to have a critical need to flush the map to disk at any of these points further processing is simply wasteful +Meaning the original function expired values unrelated to the current value without actually having any explicit need to + +The h method was heavily modified to be much more efficient in its processing +Also instead of being called on every get, it's now called just before a save +This will eliminate stale values being flushed to disk + +Modified isEmpty to use the isEmpty() method instead of the slightly confusing size() < 1 +The point of this is readability, but does have a side-benefit of a small microptimization + +Finally, added a couple obfhelpers for the modified code + +diff --git a/src/main/java/net/minecraft/server/players/JsonList.java b/src/main/java/net/minecraft/server/players/JsonList.java +index 52256f72b00d3b868ef1a60e15a3836197c769d9..cd35b833d3047a38be980ee550641e87bd3b9b01 100644 +--- a/src/main/java/net/minecraft/server/players/JsonList.java ++++ b/src/main/java/net/minecraft/server/players/JsonList.java +@@ -12,6 +12,8 @@ import java.io.BufferedReader; + import java.io.BufferedWriter; + import java.io.File; + import java.io.IOException; ++import java.lang.reflect.ParameterizedType; // Paper ++import java.lang.reflect.Type; // Paper + import java.nio.charset.StandardCharsets; + import java.util.Collection; + import java.util.Iterator; +@@ -28,7 +30,22 @@ public abstract class JsonList> { + protected static final Logger LOGGER = LogManager.getLogger(); + private static final Gson b = (new GsonBuilder()).setPrettyPrinting().create(); + private final File c; +- private final Map d = Maps.newHashMap(); ++ // Paper - replace HashMap is ConcurrentHashMap ++ private final Map d = Maps.newConcurrentMap(); private final Map getBackingMap() { return this.d; } // Paper - OBFHELPER ++ private boolean e = true; ++ private static final ParameterizedType f = new ParameterizedType() { ++ public Type[] getActualTypeArguments() { ++ return new Type[]{JsonListEntry.class}; ++ } ++ ++ public Type getRawType() { ++ return List.class; ++ } ++ ++ public Type getOwnerType() { ++ return null; ++ } ++ }; + + public JsonList(File file) { + this.c = file; +@@ -51,8 +68,13 @@ public abstract class JsonList> { + + @Nullable + public V get(K k0) { +- this.g(); +- return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error ++ // Paper start ++ // this.g(); ++ // return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error ++ return (V) this.getBackingMap().computeIfPresent(this.getMappingKey(k0), (k, v) -> { ++ return v.hasExpired() ? null : v; ++ }); ++ // Paper end + } + + public void remove(K k0) { +@@ -81,9 +103,11 @@ public abstract class JsonList> { + // CraftBukkit end + + public boolean isEmpty() { +- return this.d.size() < 1; ++ // return this.d.size() < 1; // Paper ++ return this.getBackingMap().isEmpty(); // Paper - readability is the goal. As an aside, isEmpty() uses only sumCount() and a comparison. size() uses sumCount(), casts, and boolean logic + } + ++ protected final String getMappingKey(K k0) { return a(k0); } // Paper - OBFHELPER + protected String a(K k0) { + return k0.toString(); + } +@@ -92,8 +116,9 @@ public abstract class JsonList> { + return this.d.containsKey(this.a(k0)); + } + ++ private void removeStaleEntries() { g(); } // Paper - OBFHELPER + private void g() { +- List list = Lists.newArrayList(); ++ /*List list = Lists.newArrayList(); + Iterator iterator = this.d.values().iterator(); + + while (iterator.hasNext()) { +@@ -110,8 +135,10 @@ public abstract class JsonList> { + K k0 = (K) iterator.next(); // CraftBukkit - decompile error + + this.d.remove(this.a(k0)); +- } ++ }*/ + ++ this.getBackingMap().values().removeIf(JsonListEntry::hasExpired); ++ // Paper end + } + + protected abstract JsonListEntry a(JsonObject jsonobject); +@@ -121,6 +148,7 @@ public abstract class JsonList> { + } + + public void save() throws IOException { ++ this.removeStaleEntries(); // Paper - remove expired values before saving + JsonArray jsonarray = new JsonArray(); + + this.d.values().stream().map((jsonlistentry) -> { +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 80934fc662b33b1c88dd7a3033792d612a7c7930..2299581fa889c0e8ddc6b2cc1d3551d02ff8dc2d 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -618,7 +618,7 @@ public abstract class PlayerList { + } else if (!this.isWhitelisted(gameprofile, event)) { // Paper + //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper + //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted +- } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { ++ } else if (getIPBans().isBanned(socketaddress) && getIPBans().get(socketaddress) != null && !getIPBans().get(socketaddress).hasExpired()) { // Paper - fix NPE with temp ip bans + IpBanEntry ipbanentry = this.l.get(socketaddress); + + chatmessage = new ChatMessage("multiplayer.disconnect.banned_ip.reason", new Object[]{ipbanentry.getReason()}); diff --git a/patches/server-unmapped/0264-Use-a-Queue-for-Queueing-Commands.patch b/patches/server-unmapped/0264-Use-a-Queue-for-Queueing-Commands.patch new file mode 100644 index 0000000000..eead0924bc --- /dev/null +++ b/patches/server-unmapped/0264-Use-a-Queue-for-Queueing-Commands.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 12 Aug 2018 02:33:39 -0400 +Subject: [PATCH] Use a Queue for Queueing Commands + +Lists are bad as Queues mmmkay. + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index a0804c4df6f047cf913ae70970219617052e853f..2d42b863b3fd83d1ee0532d1fcb63861641ec47b 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -75,7 +75,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + + private static final Logger LOGGER = LogManager.getLogger(); + private static final Pattern k = Pattern.compile("^[a-fA-F0-9]{40}$"); +- private final List serverCommandQueue = Collections.synchronizedList(Lists.newArrayList()); ++ private final java.util.Queue serverCommandQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Paper - use a proper queue + private RemoteStatusListener remoteStatusListener; + public final RemoteControlCommandListener remoteControlCommandListener; + private RemoteControlListener remoteControlListener; +@@ -434,8 +434,10 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + + public void handleCommandQueue() { + MinecraftTimings.serverCommandTimer.startTiming(); // Spigot +- while (!this.serverCommandQueue.isEmpty()) { +- ServerCommand servercommand = (ServerCommand) this.serverCommandQueue.remove(0); ++ // Paper start - use proper queue ++ ServerCommand servercommand; ++ while ((servercommand = this.serverCommandQueue.poll()) != null) { ++ // Paper end + + // CraftBukkit start - ServerCommand for preprocessing + ServerCommandEvent event = new ServerCommandEvent(console, servercommand.command); diff --git a/patches/server-unmapped/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/patches/server-unmapped/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch new file mode 100644 index 0000000000..2e0e968f6b --- /dev/null +++ b/patches/server-unmapped/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 15 Aug 2018 01:16:34 -0400 +Subject: [PATCH] Ability to get Tile Entities from a chunk without snapshots + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +index 32e4e59767587455272e685dfd23f945ba05f976..a8e94f69faec93661dc6ae2efeec44b8bfd2e965 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +@@ -3,8 +3,10 @@ package org.bukkit.craftbukkit; + import com.google.common.base.Preconditions; + import com.google.common.base.Predicates; + import java.lang.ref.WeakReference; ++import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collection; ++import java.util.List; + import java.util.function.Predicate; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.IRegistry; +@@ -130,9 +132,16 @@ public class CraftChunk implements Chunk { + + @Override + public BlockState[] getTileEntities() { ++ // Paper start ++ return getTileEntities(true); ++ } ++ ++ @Override ++ public BlockState[] getTileEntities(boolean useSnapshot) { + if (!isLoaded()) { + getWorld().getChunkAt(x, z); // Transient load for this tick + } ++ // Paper end + int index = 0; + net.minecraft.world.level.chunk.Chunk chunk = getHandle(); + +@@ -144,11 +153,33 @@ public class CraftChunk implements Chunk { + } + + BlockPosition position = (BlockPosition) obj; +- entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(); ++ entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(useSnapshot); // Paper ++ } ++ ++ return entities; ++ } ++ ++ // Paper start ++ @Override ++ public Collection getTileEntities(Predicate blockPredicate, boolean useSnapshot) { ++ Preconditions.checkNotNull(blockPredicate, "blockPredicate"); ++ if (!isLoaded()) { ++ getWorld().getChunkAt(x, z); // Transient load for this tick ++ } ++ net.minecraft.world.level.chunk.Chunk chunk = getHandle(); ++ ++ List entities = new ArrayList<>(); ++ ++ for (BlockPosition position : chunk.tileEntities.keySet()) { ++ Block block = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); ++ if (blockPredicate.test(block)) { ++ entities.add(block.getState(useSnapshot)); ++ } + } + + return entities; + } ++ // Paper end + + @Override + public boolean isLoaded() { diff --git a/patches/server-unmapped/0266-Allow-disabling-armour-stand-ticking.patch b/patches/server-unmapped/0266-Allow-disabling-armour-stand-ticking.patch new file mode 100644 index 0000000000..788112651f --- /dev/null +++ b/patches/server-unmapped/0266-Allow-disabling-armour-stand-ticking.patch @@ -0,0 +1,159 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 15 Aug 2018 01:26:09 -0700 +Subject: [PATCH] Allow disabling armour stand ticking + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 3562950df4868b1393790b1a1ff1fe0dc589c155..5ab0e7183e48134b7a0f736462516b1a8a333b04 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -384,4 +384,10 @@ public class PaperWorldConfig { + private void armorStandEntityLookups() { + armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); + } ++ ++ public boolean armorStandTick = true; ++ private void armorStandTick() { ++ this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); ++ log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +index e97d25339b37a70f91022dcb021bbe82fb8f5eda..8d35240405d7f7245f3c7b0b611973d58fa4384f 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +@@ -81,9 +81,16 @@ public class EntityArmorStand extends EntityLiving { + public Vector3f leftLegPose; + public Vector3f rightLegPose; + public boolean canMove = true; // Paper ++ // Paper start - Allow ArmorStands not to tick ++ public boolean canTick = true; ++ public boolean canTickSetByAPI = false; ++ private boolean noTickPoseDirty = false; ++ private boolean noTickEquipmentDirty = false; ++ // Paper end + + public EntityArmorStand(EntityTypes entitytypes, World world) { + super(entitytypes, world); ++ if (world != null) this.canTick = world.paperConfig.armorStandTick; // Paper - armour stand ticking + this.handItems = NonNullList.a(2, ItemStack.b); + this.armorItems = NonNullList.a(4, ItemStack.b); + this.headPose = EntityArmorStand.bj; +@@ -179,6 +186,7 @@ public class EntityArmorStand extends EntityLiving { + this.armorItems.set(enumitemslot.b(), itemstack); + } + ++ this.noTickEquipmentDirty = true; // Paper - Allow equipment to be updated even when tick disabled + } + + @Override +@@ -259,6 +267,7 @@ public class EntityArmorStand extends EntityLiving { + } + + nbttagcompound.set("Pose", this.B()); ++ if (this.canTickSetByAPI) nbttagcompound.setBoolean("Paper.CanTickOverride", this.canTick); // Paper - persist no tick setting + } + + @Override +@@ -290,6 +299,12 @@ public class EntityArmorStand extends EntityLiving { + this.setBasePlate(nbttagcompound.getBoolean("NoBasePlate")); + this.setMarker(nbttagcompound.getBoolean("Marker")); + this.noclip = !this.A(); ++ // Paper start - persist no tick ++ if (nbttagcompound.hasKey("Paper.CanTickOverride")) { ++ this.canTick = nbttagcompound.getBoolean("Paper.CanTickOverride"); ++ this.canTickSetByAPI = true; ++ } ++ // Paper end + NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Pose"); + + this.g(nbttagcompound1); +@@ -645,7 +660,29 @@ public class EntityArmorStand extends EntityLiving { + + @Override + public void tick() { ++ // Paper start ++ if (!this.canTick) { ++ if (this.noTickPoseDirty) { ++ this.noTickPoseDirty = false; ++ this.updatePose(); ++ } ++ ++ if (this.noTickEquipmentDirty) { ++ this.noTickEquipmentDirty = false; ++ this.updateEquipment(); ++ } ++ ++ return; ++ } ++ // Paper end ++ + super.tick(); ++ // Paper start - Split into separate method ++ updatePose(); ++ } ++ ++ public void updatePose() { ++ // Paper end + Vector3f vector3f = (Vector3f) this.datawatcher.get(EntityArmorStand.c); + + if (!this.headPose.equals(vector3f)) { +@@ -768,29 +805,36 @@ public class EntityArmorStand extends EntityLiving { + public void setHeadPose(Vector3f vector3f) { + this.headPose = vector3f; + this.datawatcher.set(EntityArmorStand.c, vector3f); ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + } + + public void setBodyPose(Vector3f vector3f) { + this.bodyPose = vector3f; + this.datawatcher.set(EntityArmorStand.d, vector3f); ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + } + + public void setLeftArmPose(Vector3f vector3f) { + this.leftArmPose = vector3f; + this.datawatcher.set(EntityArmorStand.e, vector3f); ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + } + + public void setRightArmPose(Vector3f vector3f) { + this.rightArmPose = vector3f; + this.datawatcher.set(EntityArmorStand.f, vector3f); ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + } + + public void setLeftLegPose(Vector3f vector3f) { ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + this.leftLegPose = vector3f; + this.datawatcher.set(EntityArmorStand.g, vector3f); ++ + } + + public void setRightLegPose(Vector3f vector3f) { ++ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking + this.rightLegPose = vector3f; + this.datawatcher.set(EntityArmorStand.bh, vector3f); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +index 103f935d9b7a2cbe9639528c587d8ac2e5f14d07..348993f3839f984be65daaf87f3510865e8e4670 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +@@ -313,5 +313,16 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { + return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); + } ++ ++ @Override ++ public boolean canTick() { ++ return this.getHandle().canTick; ++ } ++ ++ @Override ++ public void setCanTick(final boolean tick) { ++ this.getHandle().canTick = tick; ++ this.getHandle().canTickSetByAPI = true; ++ } + // Paper end + } diff --git a/patches/server-unmapped/0267-Optimize-BlockPosition-helper-methods.patch b/patches/server-unmapped/0267-Optimize-BlockPosition-helper-methods.patch new file mode 100644 index 0000000000..d248d915c6 --- /dev/null +++ b/patches/server-unmapped/0267-Optimize-BlockPosition-helper-methods.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Aug 2018 12:05:12 -0700 +Subject: [PATCH] Optimize BlockPosition helper methods + +Resolves #1338 + +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index 370b2c4460d6b52b5ef7da89f5ebf7ef50deb582..4c9ec211470f95d538d1d95c74796190edf99b87 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -121,58 +121,75 @@ public class BlockPosition extends BaseBlockPosition { + + @Override + public BlockPosition up() { +- return this.shift(EnumDirection.UP); ++ return new BlockPosition(this.getX(), this.getY() + 1, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPosition up(int i) { +- return this.shift(EnumDirection.UP, i); ++ return i == 0 ? this : new BlockPosition(this.getX(), this.getY() + i, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPosition down() { +- return this.shift(EnumDirection.DOWN); ++ return new BlockPosition(this.getX(), this.getY() - 1, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPosition down(int i) { +- return this.shift(EnumDirection.DOWN, i); ++ return i == 0 ? this : new BlockPosition(this.getX(), this.getY() - i, this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition north() { +- return this.shift(EnumDirection.NORTH); ++ return new BlockPosition(this.getX(), this.getY(), this.getZ() - 1); // Paper - Optimize BlockPosition + } + + public BlockPosition north(int i) { +- return this.shift(EnumDirection.NORTH, i); ++ return i == 0 ? this : new BlockPosition(this.getX(), this.getY(), this.getZ() - i); // Paper - Optimize BlockPosition + } + + public BlockPosition south() { +- return this.shift(EnumDirection.SOUTH); ++ return new BlockPosition(this.getX(), this.getY(), this.getZ() + 1); // Paper - Optimize BlockPosition + } + + public BlockPosition south(int i) { +- return this.shift(EnumDirection.SOUTH, i); ++ return i == 0 ? this : new BlockPosition(this.getX(), this.getY(), this.getZ() + i); // Paper - Optimize BlockPosition + } + + public BlockPosition west() { +- return this.shift(EnumDirection.WEST); ++ return new BlockPosition(this.getX() - 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition west(int i) { +- return this.shift(EnumDirection.WEST, i); ++ return i == 0 ? this : new BlockPosition(this.getX() - i, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition east() { +- return this.shift(EnumDirection.EAST); ++ return new BlockPosition(this.getX() + 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition east(int i) { +- return this.shift(EnumDirection.EAST, i); ++ return i == 0 ? this : new BlockPosition(this.getX() + i, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition shift(EnumDirection enumdirection) { +- return new BlockPosition(this.getX() + enumdirection.getAdjacentX(), this.getY() + enumdirection.getAdjacentY(), this.getZ() + enumdirection.getAdjacentZ()); ++ // Paper Start - Optimize BlockPosition ++ switch(enumdirection) { ++ case UP: ++ return new BlockPosition(this.getX(), this.getY() + 1, this.getZ()); ++ case DOWN: ++ return new BlockPosition(this.getX(), this.getY() - 1, this.getZ()); ++ case NORTH: ++ return new BlockPosition(this.getX(), this.getY(), this.getZ() - 1); ++ case SOUTH: ++ return new BlockPosition(this.getX(), this.getY(), this.getZ() + 1); ++ case WEST: ++ return new BlockPosition(this.getX() - 1, this.getY(), this.getZ()); ++ case EAST: ++ return new BlockPosition(this.getX() + 1, this.getY(), this.getZ()); ++ default: ++ return new BlockPosition(this.getX() + enumdirection.getAdjacentX(), this.getY() + enumdirection.getAdjacentY(), this.getZ() + enumdirection.getAdjacentZ()); ++ } ++ // Paper End + } + + @Override diff --git a/patches/server-unmapped/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/patches/server-unmapped/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch new file mode 100644 index 0000000000..50cfc368af --- /dev/null +++ b/patches/server-unmapped/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 18 Aug 2018 12:43:16 -0400 +Subject: [PATCH] Restore vanlla default mob-spawn-range and water animals + limit + + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 0efcbab8f8806aeb8dd8bd6384e5a7cee375d100..34ee684901906fc2ef5f0d09680d2686b813e52b 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -165,7 +165,7 @@ public class SpigotWorldConfig + public byte mobSpawnRange; + private void mobSpawnRange() + { +- mobSpawnRange = (byte) getInt( "mob-spawn-range", 6 ); ++ mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla + log( "Mob Spawn Range: " + mobSpawnRange ); + } + +diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml +index 6474a7fb738e1238cc272afc5ff14b645947e688..6d71bd0db752e6f523364ca5351579b6bcb434c8 100644 +--- a/src/main/resources/configurations/bukkit.yml ++++ b/src/main/resources/configurations/bukkit.yml +@@ -26,7 +26,7 @@ settings: + spawn-limits: + monsters: 70 + animals: 10 +- water-animals: 15 ++ water-animals: 5 + water-ambient: 20 + ambient: 15 + chunk-gc: diff --git a/patches/server-unmapped/0269-Slime-Pathfinder-Events.patch b/patches/server-unmapped/0269-Slime-Pathfinder-Events.patch new file mode 100644 index 0000000000..c9e838ba63 --- /dev/null +++ b/patches/server-unmapped/0269-Slime-Pathfinder-Events.patch @@ -0,0 +1,167 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 24 Aug 2018 08:18:42 -0500 +Subject: [PATCH] Slime Pathfinder Events + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java +index 01d5b0db9a34d88172e8c7c84c4e1d0b2562217c..40e39e382092b1a8f831da0cea1557a781c98600 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java +@@ -45,6 +45,14 @@ import net.minecraft.world.level.levelgen.SeededRandom; + import net.minecraft.world.level.storage.loot.LootTables; + import net.minecraft.world.phys.Vec3D; + ++// Paper start ++import com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent; ++import com.destroystokyo.paper.event.entity.SlimeSwimEvent; ++import com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent; ++import com.destroystokyo.paper.event.entity.SlimeWanderEvent; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Slime; ++// Paper end + // CraftBukkit start + import java.util.ArrayList; + import java.util.List; +@@ -105,6 +113,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { + @Override + public void saveData(NBTTagCompound nbttagcompound) { + super.saveData(nbttagcompound); ++ nbttagcompound.setBoolean("Paper.canWander", this.canWander); // Paper + nbttagcompound.setInt("Size", this.getSize() - 1); + nbttagcompound.setBoolean("wasOnGround", this.bp); + } +@@ -119,6 +128,11 @@ public class EntitySlime extends EntityInsentient implements IMonster { + + this.setSize(i + 1, false); + super.loadData(nbttagcompound); ++ // Paper start - check exists before loading or this will be loaded as false ++ if (nbttagcompound.hasKey("Paper.canWander")) { ++ this.canWander = nbttagcompound.getBoolean("Paper.canWander"); ++ } ++ // Paper end + this.bp = nbttagcompound.getBoolean("wasOnGround"); + } + +@@ -398,7 +412,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { + + @Override + public boolean a() { +- return !this.a.isPassenger(); ++ return !this.a.isPassenger() && this.a.canWander && new SlimeWanderEvent((Slime) this.a.getBukkitEntity()).callEvent(); // Paper + } + + @Override +@@ -419,7 +433,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { + + @Override + public boolean a() { +- return (this.a.isInWater() || this.a.aQ()) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime; ++ return (this.a.isInWater() || this.a.aQ()) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime && this.a.canWander && new SlimeSwimEvent((Slime) this.a.getBukkitEntity()).callEvent(); // Paper + } + + @Override +@@ -445,14 +459,18 @@ public class EntitySlime extends EntityInsentient implements IMonster { + + @Override + public boolean a() { +- return this.a.getGoalTarget() == null && (this.a.onGround || this.a.isInWater() || this.a.aQ() || this.a.hasEffect(MobEffects.LEVITATION)) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime; ++ return this.a.getGoalTarget() == null && (this.a.onGround || this.a.isInWater() || this.a.aQ() || this.a.hasEffect(MobEffects.LEVITATION)) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime && this.a.canWander; // Paper - add canWander + } + + @Override + public void e() { + if (--this.c <= 0) { + this.c = 40 + this.a.getRandom().nextInt(60); +- this.b = (float) this.a.getRandom().nextInt(360); ++ // Paper start ++ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((Slime) this.a.getBukkitEntity(), (float) this.a.getRandom().nextInt(360)); ++ if (!this.a.canWander || !event.callEvent()) return; ++ this.b = event.getNewYaw(); ++ // Paper end + } + + ((EntitySlime.ControllerMoveSlime) this.a.getControllerMove()).a(this.b, false); +@@ -473,7 +491,15 @@ public class EntitySlime extends EntityInsentient implements IMonster { + public boolean a() { + EntityLiving entityliving = this.a.getGoalTarget(); + +- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable ? false : this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime)); ++ // Paper start ++ if (entityliving == null || !entityliving.isAlive()) { ++ return false; ++ } ++ if (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable) { ++ return false; ++ } ++ return this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime && this.a.canWander && new SlimeTargetLivingEntityEvent((Slime) this.a.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); ++ // Paper end + } + + @Override +@@ -486,7 +512,15 @@ public class EntitySlime extends EntityInsentient implements IMonster { + public boolean b() { + EntityLiving entityliving = this.a.getGoalTarget(); + +- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable ? false : --this.b > 0)); ++ // Paper start ++ if (entityliving == null || !entityliving.isAlive()) { ++ return false; ++ } ++ if (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable) { ++ return false; ++ } ++ return --this.b > 0 && this.a.canWander && new SlimeTargetLivingEntityEvent((Slime) this.a.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); ++ // Paper end + } + + @Override +@@ -494,6 +528,13 @@ public class EntitySlime extends EntityInsentient implements IMonster { + this.a.a((Entity) this.a.getGoalTarget(), 10.0F, 10.0F); + ((EntitySlime.ControllerMoveSlime) this.a.getControllerMove()).a(this.a.yaw, this.a.eL()); + } ++ ++ // Paper start - clear timer and target when goal resets ++ public void d() { ++ this.b = 0; ++ this.a.setGoalTarget(null); ++ } ++ // Paper end + } + + static class ControllerMoveSlime extends ControllerMove { +@@ -552,4 +593,15 @@ public class EntitySlime extends EntityInsentient implements IMonster { + } + } + } ++ ++ // Paper start ++ private boolean canWander = true; ++ public boolean canWander() { ++ return canWander; ++ } ++ ++ public void setWander(boolean canWander) { ++ this.canWander = canWander; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +index aa0ac8d8493dc79dda3fed2ff4d80c5b7a7e3df6..cf5c6030105e56813f526e710e5db0c59d88c99e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +@@ -35,4 +35,14 @@ public class CraftSlime extends CraftMob implements Slime { + public EntityType getType() { + return EntityType.SLIME; + } ++ ++ // Paper start ++ public boolean canWander() { ++ return getHandle().canWander(); ++ } ++ ++ public void setWander(boolean canWander) { ++ getHandle().setWander(canWander); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0270-Configurable-speed-for-water-flowing-over-lava.patch b/patches/server-unmapped/0270-Configurable-speed-for-water-flowing-over-lava.patch new file mode 100644 index 0000000000..55ef5bbfa1 --- /dev/null +++ b/patches/server-unmapped/0270-Configurable-speed-for-water-flowing-over-lava.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 8 Aug 2018 16:33:21 -0600 +Subject: [PATCH] Configurable speed for water flowing over lava + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5ab0e7183e48134b7a0f736462516b1a8a333b04..f280dbff4a09bc611a9ca565c6d697d08801f53b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -390,4 +390,10 @@ public class PaperWorldConfig { + this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); + log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); + } ++ ++ public int waterOverLavaFlowSpeed; ++ private void waterOverLavaFlowSpeed() { ++ waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); ++ log("Water over lava flow speed: " + waterOverLavaFlowSpeed); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockFluids.java b/src/main/java/net/minecraft/world/level/block/BlockFluids.java +index 0654c77ab059dea2ad06cb16d07950e153d3f15d..0ed8d938b8fafdb03e01a00a201ba3f8597ac6e9 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockFluids.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockFluids.java +@@ -23,6 +23,7 @@ import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidType; + import net.minecraft.world.level.material.FluidTypeFlowing; + import net.minecraft.world.level.material.FluidTypes; ++import net.minecraft.world.level.material.Material; + import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.level.storage.loot.LootTableInfo; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -100,11 +101,28 @@ public class BlockFluids extends Block implements IFluidSource { + @Override + public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { + if (this.a(world, blockposition, iblockdata)) { +- world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.b.a((IWorldReader) world)); ++ world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.getFlowSpeed(world, blockposition)); // Paper + } + + } + ++ // Paper start - Get flow speed. Throttle if its water and flowing adjacent to lava ++ public int getFlowSpeed(World world, BlockPosition blockposition) { ++ if (this.material == Material.WATER) { ++ if ( ++ world.getMaterialIfLoaded(blockposition.north(1)) == Material.LAVA || ++ world.getMaterialIfLoaded(blockposition.south(1)) == Material.LAVA || ++ world.getMaterialIfLoaded(blockposition.west(1)) == Material.LAVA || ++ world.getMaterialIfLoaded(blockposition.east(1)) == Material.LAVA ++ ) { ++ return world.paperConfig.waterOverLavaFlowSpeed; ++ } ++ } ++ return this.b.a(world); ++ } ++ // Paper end ++ ++ + @Override + public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { + if (iblockdata.getFluid().isSource() || iblockdata1.getFluid().isSource()) { +@@ -117,7 +135,7 @@ public class BlockFluids extends Block implements IFluidSource { + @Override + public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { + if (this.a(world, blockposition, iblockdata)) { +- world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.b.a((IWorldReader) world)); ++ world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.getFlowSpeed(world, blockposition)); // Paper + } + + } diff --git a/patches/server-unmapped/0271-Optimize-CraftBlockData-Creation.patch b/patches/server-unmapped/0271-Optimize-CraftBlockData-Creation.patch new file mode 100644 index 0000000000..727414b274 --- /dev/null +++ b/patches/server-unmapped/0271-Optimize-CraftBlockData-Creation.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: miclebrick +Date: Thu, 23 Aug 2018 11:45:32 -0400 +Subject: [PATCH] Optimize CraftBlockData Creation + +Avoids a hashmap lookup by cacheing a reference to the CraftBlockData +and cloning it when one is needed. + +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +index 10f4015b8c36e4e27cf7d0745ba70b8a9e60aff3..57857cc33603cf278de424b540a3d4a5943584c9 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +@@ -375,6 +375,14 @@ public abstract class BlockBase { + this.o = blockbase_info.t; + this.p = blockbase_info.u; + } ++ // Paper start - impl cached craft block data, lazy load to fix issue with loading at the wrong time ++ private org.bukkit.craftbukkit.block.data.CraftBlockData cachedCraftBlockData; ++ ++ public org.bukkit.craftbukkit.block.data.CraftBlockData createCraftBlockData() { ++ if (cachedCraftBlockData == null) cachedCraftBlockData = org.bukkit.craftbukkit.block.data.CraftBlockData.createData(getBlockData()); ++ return (org.bukkit.craftbukkit.block.data.CraftBlockData) cachedCraftBlockData.clone(); ++ } ++ // Paper end + + public void a() { + if (!this.getBlock().o()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +index 76fd1fea386d0e65c63c529dba772f01d9888407..ed88da727feddc319a650fb35710d16727f6dbd7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +@@ -509,7 +509,17 @@ public class CraftBlockData implements BlockData { + return craft; + } + ++ // Paper start - optimize creating BlockData to not need a map lookup ++ static { ++ // Initialize cached data for all IBlockData instances after registration ++ Block.REGISTRY_ID.iterator().forEachRemaining(IBlockData::createCraftBlockData); ++ } + public static CraftBlockData fromData(IBlockData data) { ++ return data.createCraftBlockData(); ++ } ++ ++ public static CraftBlockData createData(IBlockData data) { ++ // Paper end + return MAP.getOrDefault(data.getBlock().getClass(), CraftBlockData::new).apply(data); + } + diff --git a/patches/server-unmapped/0272-Optimize-RegistryMaterials.patch b/patches/server-unmapped/0272-Optimize-RegistryMaterials.patch new file mode 100644 index 0000000000..a37df72fa3 --- /dev/null +++ b/patches/server-unmapped/0272-Optimize-RegistryMaterials.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 26 Aug 2018 20:49:50 -0400 +Subject: [PATCH] Optimize RegistryMaterials + +Use larger initial sizes to increase bucket capacity on the BiMap + +BiMap.get was seen to be using a good bit of CPU time. + +diff --git a/src/main/java/net/minecraft/core/RegistryMaterials.java b/src/main/java/net/minecraft/core/RegistryMaterials.java +index f3f6ed83d509d228944d15fc2b2b4cb85b05e366..18f78a5cb03dd9c8349c28b99d013752e32c9167 100644 +--- a/src/main/java/net/minecraft/core/RegistryMaterials.java ++++ b/src/main/java/net/minecraft/core/RegistryMaterials.java +@@ -30,6 +30,7 @@ import net.minecraft.SystemUtils; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.resources.RegistryDataPackCodec; + import net.minecraft.resources.ResourceKey; ++import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; // Paper + import org.apache.commons.lang3.Validate; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -38,7 +39,7 @@ public class RegistryMaterials extends IRegistryWritable { + + protected static final Logger LOGGER = LogManager.getLogger(); + private final ObjectList bf = new ObjectArrayList(256); +- private final Object2IntMap bg = new Object2IntOpenCustomHashMap(SystemUtils.k()); ++ private final Reference2IntOpenHashMap bg = new Reference2IntOpenHashMap(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map + private final BiMap bh; + private final BiMap, T> bi; + private final Map bj; +@@ -49,9 +50,9 @@ public class RegistryMaterials extends IRegistryWritable { + public RegistryMaterials(ResourceKey> resourcekey, Lifecycle lifecycle) { + super(resourcekey, lifecycle); + this.bg.defaultReturnValue(-1); +- this.bh = HashBiMap.create(); +- this.bi = HashBiMap.create(); +- this.bj = Maps.newIdentityHashMap(); ++ this.bh = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions ++ this.bi = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions ++ this.bj = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions + this.bk = lifecycle; + } + +@@ -195,7 +196,7 @@ public class RegistryMaterials extends IRegistryWritable { + this.b = collection.toArray(new Object[collection.size()]); + } + +- return SystemUtils.a(this.b, random); ++ return (T) SystemUtils.a(this.b, random); // Paper - Decompile fix + } + + public static Codec> a(ResourceKey> resourcekey, Lifecycle lifecycle, Codec codec) { +@@ -215,7 +216,7 @@ public class RegistryMaterials extends IRegistryWritable { + Iterator iterator = registrymaterials.iterator(); + + while (iterator.hasNext()) { +- T t0 = iterator.next(); ++ T t0 = (T) iterator.next(); // Paper - Decompile fix + + builder.add(new RegistryMaterials.a<>((ResourceKey) registrymaterials.c(t0).get(), registrymaterials.a(t0), t0)); + } diff --git a/patches/server-unmapped/0273-Add-PhantomPreSpawnEvent.patch b/patches/server-unmapped/0273-Add-PhantomPreSpawnEvent.patch new file mode 100644 index 0000000000..dca07a67d6 --- /dev/null +++ b/patches/server-unmapped/0273-Add-PhantomPreSpawnEvent.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 25 Aug 2018 19:56:51 -0500 +Subject: [PATCH] Add PhantomPreSpawnEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +index 6053894c5250e9a1a0c4aa2d681127dfd652b34f..6c498d4345df35a411d155799ac56e47c9c48114 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +@@ -161,6 +161,11 @@ public class EntityPhantom extends EntityFlying implements IMonster { + } + + this.setSize(nbttagcompound.getInt("Size")); ++ // Paper start ++ if (nbttagcompound.hasUUID("Paper.SpawningEntity")) { ++ this.spawningEntity = nbttagcompound.getUUID("Paper.SpawningEntity"); ++ } ++ // Paper end + } + + @Override +@@ -170,6 +175,11 @@ public class EntityPhantom extends EntityFlying implements IMonster { + nbttagcompound.setInt("AY", this.d.getY()); + nbttagcompound.setInt("AZ", this.d.getZ()); + nbttagcompound.setInt("Size", this.getSize()); ++ // Paper start ++ if (this.spawningEntity != null) { ++ nbttagcompound.setUUID("Paper.SpawningEntity", this.spawningEntity); ++ } ++ // Paper end + } + + @Override +@@ -216,6 +226,15 @@ public class EntityPhantom extends EntityFlying implements IMonster { + return entitysize.a(f); + } + ++ // Paper start ++ java.util.UUID spawningEntity; ++ ++ public java.util.UUID getSpawningEntity() { ++ return spawningEntity; ++ } ++ public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } ++ // Paper end ++ + class b extends PathfinderGoal { + + private final PathfinderTargetCondition b; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java +index cfc32acee1e456a0fda12a5faa4035e29d0c3d5e..96a5a6569387a25b15a06aaab3bd9d033547e875 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java +@@ -4,6 +4,7 @@ import java.util.Iterator; + import java.util.Random; + import net.minecraft.core.BlockPosition; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.stats.ServerStatisticManager; +@@ -73,8 +74,17 @@ public class MobSpawnerPhantom implements MobSpawner { + int k = 1 + random.nextInt(difficultydamagescaler.a().a() + 1); + + for (int l = 0; l < k; ++l) { ++ // Paper start ++ com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(MCUtil.toLocation(worldserver, blockposition1), ((EntityPlayer) entityhuman).getBukkitEntity(), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ break; ++ } ++ continue; ++ } ++ // Paper end + EntityPhantom entityphantom = (EntityPhantom) EntityTypes.PHANTOM.a((World) worldserver); +- ++ entityphantom.setSpawningEntity(entityhuman.getUniqueID()); // Paper + entityphantom.setPositionRotation(blockposition1, 0.0F, 0.0F); + groupdataentity = entityphantom.prepare(worldserver, difficultydamagescaler, EnumMobSpawn.NATURAL, groupdataentity, (NBTTagCompound) null); + worldserver.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +index 6ec7cf434b6586342da3f351466f5c7d72df290d..0cea1d8e23da3a79ef06e43752665a5401b01b4b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +@@ -35,4 +35,10 @@ public class CraftPhantom extends CraftFlying implements Phantom { + public EntityType getType() { + return EntityType.PHANTOM; + } ++ ++ // Paper start ++ public java.util.UUID getSpawningEntity() { ++ return getHandle().getSpawningEntity(); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0274-Add-More-Creeper-API.patch b/patches/server-unmapped/0274-Add-More-Creeper-API.patch new file mode 100644 index 0000000000..faced7350e --- /dev/null +++ b/patches/server-unmapped/0274-Add-More-Creeper-API.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 24 Aug 2018 11:50:26 -0500 +Subject: [PATCH] Add More Creeper API + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +index cbb973e077e04e5221bcc837f434b7093bdbcc2a..b47f71ca1f1c8bbd1a521836d9cb5d676a33ec76 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java +@@ -290,7 +290,18 @@ public class EntityCreeper extends EntityMonster { + } + + public void ignite() { +- this.datawatcher.set(EntityCreeper.d, true); ++ // Paper start ++ setIgnited(true); ++ } ++ ++ public void setIgnited(boolean ignited) { ++ if (isIgnited() != ignited) { ++ com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited); ++ if (event.callEvent()) { ++ this.datawatcher.set(EntityCreeper.d, event.isIgnited()); ++ } ++ } ++ // Paper end + } + + public boolean canCauseHeadDrop() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java +index 167b8f0c742be07ee0c5d698e04d6e29addda70c..629518d4bb314a1d46e32397b6fb7b90bce94e83 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java +@@ -101,4 +101,14 @@ public class CraftCreeper extends CraftMonster implements Creeper { + public EntityType getType() { + return EntityType.CREEPER; + } ++ ++ // Paper start ++ public void setIgnited(boolean ignited) { ++ getHandle().setIgnited(ignited); ++ } ++ ++ public boolean isIgnited() { ++ return getHandle().isIgnited(); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0275-Inventory-removeItemAnySlot.patch b/patches/server-unmapped/0275-Inventory-removeItemAnySlot.patch new file mode 100644 index 0000000000..8d4a86803e --- /dev/null +++ b/patches/server-unmapped/0275-Inventory-removeItemAnySlot.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 28 Aug 2018 23:04:15 -0400 +Subject: [PATCH] Inventory#removeItemAnySlot + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +index 4211bdfb213db0781107c67f1522e9689aa7ecfe..45634fded9916dca35a246921efb87964c860339 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +@@ -223,10 +223,16 @@ public class CraftInventory implements Inventory { + } + + private int first(ItemStack item, boolean withAmount) { ++ // Paper start ++ return first(item, withAmount, getStorageContents()); ++ } ++ ++ private int first(ItemStack item, boolean withAmount, ItemStack[] inventory) { ++ // Paper end + if (item == null) { + return -1; + } +- ItemStack[] inventory = getStorageContents(); ++ //ItemStack[] inventory = getStorageContents(); // Paper - let param deal + for (int i = 0; i < inventory.length; i++) { + if (inventory[i] == null) continue; + +@@ -349,6 +355,17 @@ public class CraftInventory implements Inventory { + + @Override + public HashMap removeItem(ItemStack... items) { ++ // Paper start ++ return removeItem(false, items); ++ } ++ ++ @Override ++ public HashMap removeItemAnySlot(ItemStack... items) { ++ return removeItem(true, items); ++ } ++ ++ private HashMap removeItem(boolean searchEntire, ItemStack... items) { ++ // Paper end + Validate.notNull(items, "Items cannot be null"); + HashMap leftover = new HashMap(); + +@@ -359,7 +376,10 @@ public class CraftInventory implements Inventory { + int toDelete = item.getAmount(); + + while (true) { +- int first = first(item, false); ++ // Paper start - Allow searching entire contents ++ ItemStack[] toSearch = searchEntire ? getContents() : getStorageContents(); ++ int first = first(item, false, toSearch); ++ // Paper end + + // Drat! we don't have this type in the inventory + if (first == -1) { diff --git a/patches/server-unmapped/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/patches/server-unmapped/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch new file mode 100644 index 0000000000..9fbcd0bc70 --- /dev/null +++ b/patches/server-unmapped/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 2 Sep 2018 19:34:33 -0700 +Subject: [PATCH] Make CraftWorld#loadChunk(int, int, false) load unconverted + chunks + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index e7103b8021141071712759b1056eccb5e3da93b7..880bbf09f77f59824184c1c9dd1ca3c3df09dae9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -508,7 +508,7 @@ public class CraftWorld implements World { + @Override + public boolean loadChunk(int x, int z, boolean generate) { + org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot +- IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); ++ IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper + + // If generate = false, but the chunk already exists, we will get this back. + if (chunk instanceof ProtoChunkExtension) { diff --git a/patches/server-unmapped/0277-Add-ray-tracing-methods-to-LivingEntity.patch b/patches/server-unmapped/0277-Add-ray-tracing-methods-to-LivingEntity.patch new file mode 100644 index 0000000000..41b6518aab --- /dev/null +++ b/patches/server-unmapped/0277-Add-ray-tracing-methods-to-LivingEntity.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 3 Sep 2018 18:20:03 -0500 +Subject: [PATCH] Add ray tracing methods to LivingEntity + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index a530f13526ef1ee947adb22e24d5c9afb705a01d..bfbfdeffe668ac3363ffdab2c5cb7b19217f55ea 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -3608,6 +3608,23 @@ public abstract class EntityLiving extends Entity { + this.broadcastItemBreak(enumhand == EnumHand.MAIN_HAND ? EnumItemSlot.MAINHAND : EnumItemSlot.OFFHAND); + } + // Paper start ++ public MovingObjectPosition getRayTrace(int maxDistance) { ++ return getRayTrace(maxDistance, RayTrace.FluidCollisionOption.NONE); ++ } ++ ++ public MovingObjectPosition getRayTrace(int maxDistance, RayTrace.FluidCollisionOption fluidCollisionOption) { ++ if (maxDistance < 1 || maxDistance > 120) { ++ throw new IllegalArgumentException("maxDistance must be between 1-120"); ++ } ++ ++ Vec3D start = new Vec3D(locX(), locY() + getHeadHeight(), locZ()); ++ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance); ++ Vec3D end = new Vec3D(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ()); ++ RayTrace raytrace = new RayTrace(start, end, RayTrace.BlockCollisionOption.OUTLINE, fluidCollisionOption, this); ++ ++ return world.rayTrace(raytrace); ++ } ++ + public int shieldBlockingDelay = world.paperConfig.shieldBlockingDelay; + + public int getShieldBlockingDelay() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index a0b006f24829ff9f5754293fbe389d19a14dc001..194583522c53ae838dfc0ccfa49f906c1a628984 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import com.destroystokyo.paper.block.TargetBlockInfo; + import com.google.common.base.Preconditions; + import com.google.common.collect.Sets; + import java.util.ArrayList; +@@ -8,6 +9,7 @@ import java.util.Iterator; + import java.util.List; + import java.util.Set; + import java.util.UUID; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.world.EnumHand; + import net.minecraft.world.damagesource.DamageSource; +@@ -40,6 +42,8 @@ import net.minecraft.world.entity.projectile.EntityThrownExpBottle; + import net.minecraft.world.entity.projectile.EntityThrownTrident; + import net.minecraft.world.entity.projectile.EntityTippedArrow; + import net.minecraft.world.entity.projectile.EntityWitherSkull; ++import net.minecraft.world.phys.MovingObjectPosition; ++import net.minecraft.world.phys.MovingObjectPositionBlock; + import org.apache.commons.lang.Validate; + import org.bukkit.FluidCollisionMode; + import org.bukkit.Location; +@@ -49,6 +53,7 @@ import org.bukkit.attribute.AttributeInstance; + import org.bukkit.block.Block; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.entity.memory.CraftMemoryKey; + import org.bukkit.craftbukkit.entity.memory.CraftMemoryMapper; + import org.bukkit.craftbukkit.inventory.CraftEntityEquipment; +@@ -202,6 +207,28 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return blocks.get(0); + } + ++ // Paper start ++ @Override ++ public Block getTargetBlock(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { ++ MovingObjectPosition rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof MovingObjectPositionBlock) ? null : CraftBlock.at(getHandle().world, ((MovingObjectPositionBlock)rayTrace).getBlockPosition()); ++ } ++ ++ @Override ++ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { ++ MovingObjectPosition rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof MovingObjectPositionBlock) ? null : MCUtil.toBukkitBlockFace(((MovingObjectPositionBlock)rayTrace).getDirection()); ++ } ++ ++ @Override ++ public TargetBlockInfo getTargetBlockInfo(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { ++ MovingObjectPosition rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof MovingObjectPositionBlock) ? null : ++ new TargetBlockInfo(CraftBlock.at(getHandle().world, ((MovingObjectPositionBlock)rayTrace).getBlockPosition()), ++ MCUtil.toBukkitBlockFace(((MovingObjectPositionBlock)rayTrace).getDirection())); ++ } ++ // Paper end ++ + @Override + public List getLastTwoTargetBlocks(Set transparent, int maxDistance) { + return getLineOfSight(transparent, maxDistance, 2); diff --git a/patches/server-unmapped/0278-Expose-attack-cooldown-methods-for-Player.patch b/patches/server-unmapped/0278-Expose-attack-cooldown-methods-for-Player.patch new file mode 100644 index 0000000000..74caa5c1f1 --- /dev/null +++ b/patches/server-unmapped/0278-Expose-attack-cooldown-methods-for-Player.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 4 Sep 2018 15:02:00 -0500 +Subject: [PATCH] Expose attack cooldown methods for Player + + +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index b6effe1037f3ae59e6faa5f5d039b6ad54bca5d4..87374174dcbf9e7ee448a1cdd9a3528557c3a2ea 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -2103,6 +2103,7 @@ public abstract class EntityHuman extends EntityLiving { + this.datawatcher.set(EntityHuman.bl, nbttagcompound); + } + ++ public float getCooldownPeriod() { return this.eR(); } // Paper - OBFHELPER + public float eR() { + return (float) (1.0D / this.b(GenericAttributes.ATTACK_SPEED) * 20.0D); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index ee3fbf0789b4841a113727397ba6809b2600ff83..a13867ff6d188e7633a91f1e1600116286ac0cd4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2189,6 +2189,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutOpenBook(net.minecraft.world.EnumHand.MAIN_HAND)); + connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutSetSlot(0, slot, inventory.getItemInHand())); + } ++ ++ public float getCooldownPeriod() { ++ return getHandle().getCooldownPeriod(); ++ } ++ ++ public float getCooledAttackStrength(float adjustTicks) { ++ return getHandle().getAttackCooldown(adjustTicks); ++ } ++ ++ public void resetCooldown() { ++ getHandle().resetAttackCooldown(); ++ } + // Paper end + + // Spigot start diff --git a/patches/server-unmapped/0279-Improve-death-events.patch b/patches/server-unmapped/0279-Improve-death-events.patch new file mode 100644 index 0000000000..3ba91d6451 --- /dev/null +++ b/patches/server-unmapped/0279-Improve-death-events.patch @@ -0,0 +1,425 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Tue, 21 Aug 2018 01:39:35 +0100 +Subject: [PATCH] Improve death events + +This adds the ability to cancel the death events and to modify the sound +an entity makes when dying. (In cases were no sound should it will be +called with shouldPlaySound set to false allowing unsilencing of silent +entities) + +It makes handling of entity deaths a lot nicer as you no longer need +to listen on the damage event and calculate if the entity dies yourself +to cancel the death which has the benefit of also receiving the dropped +items and experience which is otherwise only properly possible by using +internal code. + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index b581a6d3ec06498a4c6db92eb50c5d2b28038131..ae9e0f55ddc194aaef1e57e81863569d9bc7b8f3 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -214,6 +214,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public int ping; + public boolean viewingCredits; + private int containerUpdateDelay; // Paper ++ // Paper start - cancellable death event ++ public boolean queueHealthUpdatePacket = false; ++ public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; ++ // Paper end + + // CraftBukkit start + public String displayName; +@@ -717,6 +721,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + IChatBaseComponent defaultMessage = this.getCombatTracker().getDeathMessage(); + + org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure ++ // Paper start - cancellable death event ++ if (event.isCancelled()) { ++ // make compatible with plugins that might have already set the health in an event listener ++ if (this.getHealth() <= 0) { ++ this.setHealth((float) event.getReviveHealth()); ++ } ++ return; ++ } ++ // Paper end + + // SPIGOT-943 - only call if they have an inventory open + if (this.activeContainer != this.defaultContainer) { +@@ -863,8 +876,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + } + } +- +- return super.damageEntity(damagesource, f); ++ // Paper start - cancellable death events ++ //return super.damageEntity(damagesource, f); ++ this.queueHealthUpdatePacket = true; ++ boolean damaged = super.damageEntity(damagesource, f); ++ this.queueHealthUpdatePacket = false; ++ if (this.queuedHealthUpdatePacket != null) { ++ this.playerConnection.sendPacket(this.queuedHealthUpdatePacket); ++ this.queuedHealthUpdatePacket = null; ++ } ++ return damaged; ++ // Paper end + } + } + } +diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java +index f6f79ed9c38206cc6a4feb5504e854a476868aec..7d2b947b3c2b255c01241f2c4a6d7377a0a7c671 100644 +--- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java ++++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java +@@ -203,6 +203,7 @@ public class CombatTracker { + this.h = null; + } + ++ public final void reset() { this.g(); } // Paper - OBFHELPER + public void g() { + int i = this.f ? 300 : 100; + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 37497d7ff04b84d4758997970dbdbf88b40d0493..28390d3830ed9f3f5d97ab38913e6c40f9943a70 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1538,6 +1538,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + // CraftBukkit end + ++ public final void runKillTrigger(Entity entity, int kills, DamageSource damageSource) { this.a(entity, kills, damageSource); } // Paper - OBFHELPER + public void a(Entity entity, int i, DamageSource damagesource) { + if (entity instanceof EntityPlayer) { + CriterionTriggers.c.a((EntityPlayer) entity, this, damagesource); +@@ -2442,6 +2443,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.fallDistance = 0.0F; + } + ++ public final void onKill(WorldServer worldserver, EntityLiving entityLiving) { this.a(worldserver, entityLiving); } // Paper - OBFHELPER + public void a(WorldServer worldserver, EntityLiving entityliving) {} + + protected void l(double d0, double d1, double d2) { +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index bfbfdeffe668ac3363ffdab2c5cb7b19217f55ea..e20acbd904f12e9036cb0565d6aa9a3f63008d43 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -189,7 +189,7 @@ public abstract class EntityLiving extends Entity { + protected float aL; + protected float aM; + protected float aN; +- protected int aO; ++ protected int aO;protected int getKillCount() { return this.aO; } // Paper - OBFHELPER + public float lastDamage; + protected boolean jumping; + public float aR; +@@ -233,6 +233,7 @@ public abstract class EntityLiving extends Entity { + public Set collidableExemptions = new HashSet<>(); + public boolean canPickUpLoot; + public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper ++ public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event + + @Override + public float getBukkitYaw() { +@@ -1348,13 +1349,17 @@ public abstract class EntityLiving extends Entity { + if (knockbackCancelled) this.world.broadcastEntityEffect(this, (byte) 2); // Paper - Disable explosion knockback + if (this.dl()) { + if (!this.f(damagesource)) { +- SoundEffect soundeffect = this.getSoundDeath(); ++ // Paper start - moved into CraftEventFactory event caller for cancellable death event ++ //SoundEffect soundeffect = this.getSoundDeath(); + +- if (flag1 && soundeffect != null) { +- this.playSound(soundeffect, this.getSoundVolume(), this.dH()); +- } ++// if (flag1 && soundeffect != null) { ++// this.playSound(soundeffect, this.getSoundVolume(), this.dH()); ++// } ++ this.silentDeath = !flag1; // mark entity as dying silently ++ // Paper end + + this.die(damagesource); ++ this.silentDeath = false; // Paper - cancellable death event - reset to default + } + } else if (flag1) { + this.c(damagesource); +@@ -1493,6 +1498,7 @@ public abstract class EntityLiving extends Entity { + Entity entity = damagesource.getEntity(); + EntityLiving entityliving = this.getKillingEntity(); + ++ /* // Paper - move down to make death event cancellable - this is the runKillTrigger below + if (this.aO >= 0 && entityliving != null) { + entityliving.a(this, this.aO, damagesource); + } +@@ -1500,20 +1506,40 @@ public abstract class EntityLiving extends Entity { + if (this.isSleeping()) { + this.entityWakeup(); + } ++ */ // Paper + + this.killed = true; +- this.getCombatTracker().g(); ++ // this.getCombatTracker().g(); // Paper - moved into if below as .reset() + if (this.world instanceof WorldServer) { + if (entity != null) { +- entity.a((WorldServer) this.world, this); ++ // entity.a((WorldServer) this.world, this); // Paper - move below into if for onKill + } + +- this.d(damagesource); ++ // Paper start ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.d(damagesource); ++ if (deathEvent == null || !deathEvent.isCancelled()) { ++ if (this.getKillCount() >= 0 && entityliving != null) { ++ entityliving.runKillTrigger(this, this.getKillCount(), damagesource); ++ } ++ if (this.isSleeping()) { ++ this.entityWakeup(); ++ } ++ this.getCombatTracker().reset(); ++ if (entity != null) { ++ entity.onKill((WorldServer) this.world, this); ++ } ++ } else { ++ this.killed = false; ++ this.setHealth((float) deathEvent.getReviveHealth()); ++ } ++ // Paper end + this.f(entityliving); + } + ++ if (this.killed) { // Paper + this.world.broadcastEntityEffect(this, (byte) 3); + this.setPose(EntityPose.DYING); ++ } // Paper + } + } + +@@ -1521,7 +1547,7 @@ public abstract class EntityLiving extends Entity { + if (!this.world.isClientSide) { + boolean flag = false; + +- if (entityliving instanceof EntityWither) { ++ if (this.killed && entityliving instanceof EntityWither) { // Paper + if (this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { + BlockPosition blockposition = this.getChunkCoordinates(); + IBlockData iblockdata = Blocks.WITHER_ROSE.getBlockData(); +@@ -1549,7 +1575,8 @@ public abstract class EntityLiving extends Entity { + } + } + +- protected void d(DamageSource damagesource) { ++ protected org.bukkit.event.entity.EntityDeathEvent processDeath(DamageSource damagesource) { return d(damagesource); } // Paper - OBFHELPER ++ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper + Entity entity = damagesource.getEntity(); + int i; + +@@ -1567,15 +1594,18 @@ public abstract class EntityLiving extends Entity { + this.dropDeathLoot(damagesource, i, flag); + } + // CraftBukkit start - Call death event +- CraftEventFactory.callEntityDeathEvent(this, this.drops); ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper ++ this.postDeathDropItems(deathEvent); // Paper + this.drops = new ArrayList<>(); + // CraftBukkit end + + // this.dropInventory();// CraftBukkit - moved up + this.dropExperience(); ++ return deathEvent; // Paper + } + + protected void dropInventory() {} ++ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled + + // CraftBukkit start + public int getExpReward() { +@@ -1660,6 +1690,7 @@ public abstract class EntityLiving extends Entity { + return SoundEffects.ENTITY_GENERIC_HURT; + } + ++ public final SoundEffect getDeathSoundEffect() { return this.getSoundDeath(); } // Paper - OBFHELPER + @Nullable + protected SoundEffect getSoundDeath() { + return SoundEffects.ENTITY_GENERIC_DEATH; +@@ -2196,10 +2227,12 @@ public abstract class EntityLiving extends Entity { + + } + ++ public final float getDeathSoundVolume() { return this.getSoundVolume(); } // Paper - OBFHELPER + protected float getSoundVolume() { + return 1.0F; + } + ++ public float getSoundPitch() { return dH();} // Paper - OBFHELPER + protected float dH() { + return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.5F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +index 77de0706aaa32b565cb1e14754e93a1c4a6e15bd..b7fa24318ef43918b6b10ff4ea8acb960527296e 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java +@@ -647,15 +647,25 @@ public class EntityFox extends EntityAnimal { + } + + @Override +- protected void d(DamageSource damagesource) { +- ItemStack itemstack = this.getEquipment(EnumItemSlot.MAINHAND); ++ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper ++ ItemStack itemstack = this.getEquipment(EnumItemSlot.MAINHAND).cloneItemStack(); // Paper ++ ++ // Paper start - Cancellable death event ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.d(damagesource); ++ ++ // Below is code to drop ++ ++ if (deathEvent == null || deathEvent.isCancelled()) { ++ return deathEvent; ++ } ++ // Paper end + + if (!itemstack.isEmpty()) { + this.a(itemstack); + this.setSlot(EnumItemSlot.MAINHAND, ItemStack.b); + } + +- super.d(damagesource); ++ return deathEvent; // Paper + } + + public static boolean a(EntityFox entityfox, EntityLiving entityliving) { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java +index aa12a0c9f30cd2b8a6de75ff9822843da808ae64..3daa1780a332128bd472fa80039112f3ca9bc4e9 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java +@@ -68,11 +68,19 @@ public abstract class EntityHorseChestedAbstract extends EntityHorseAbstract { + this.a((IMaterial) Blocks.CHEST); + } + +- this.setCarryingChest(false); ++ //this.setCarryingChest(false); // Paper - moved to post death logic + } + + } + ++ // Paper start ++ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) { ++ if (this.isCarryingChest() && (event == null || !event.isCancelled())) { ++ this.setCarryingChest(false); ++ } ++ } ++ // Paper end ++ + @Override + public void saveData(NBTTagCompound nbttagcompound) { + super.saveData(nbttagcompound); +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +index 8d35240405d7f7245f3c7b0b611973d58fa4384f..69361caebf0d3caa5195b519a16691705ac5e16a 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +@@ -746,7 +746,8 @@ public class EntityArmorStand extends EntityLiving { + + @Override + public void killEntity() { +- org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event ++ org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event // Paper - make cancellable ++ if (event.isCancelled()) return; // Paper - make cancellable + this.die(); + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index a13867ff6d188e7633a91f1e1600116286ac0cd4..6c5075ef2420131aa21b403623a5dfa485ee73e5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1839,7 +1839,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void sendHealthUpdate() { +- getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); ++ // Paper start - cancellable death event ++ //getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); ++ PacketPlayOutUpdateHealth packet = new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel()); ++ if (this.getHandle().queueHealthUpdatePacket) { ++ this.getHandle().queuedHealthUpdatePacket = packet; ++ } else { ++ this.getHandle().playerConnection.sendPacket(packet); ++ } ++ // Paper end + } + + 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 338b319910d12cf62ab9c5977257ad1ccec5544a..b7ebd2e3e919d09ee99997f2358cc0c399d5041b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -18,6 +18,8 @@ import net.minecraft.network.protocol.game.PacketPlayInCloseWindow; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; ++import net.minecraft.sounds.SoundCategory; ++import net.minecraft.sounds.SoundEffect; + import net.minecraft.util.Unit; + import net.minecraft.world.EnumHand; + import net.minecraft.world.IInventory; +@@ -805,9 +807,16 @@ public class CraftEventFactory { + public static EntityDeathEvent callEntityDeathEvent(EntityLiving victim, List drops) { + CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); + EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward()); ++ populateFields(victim, event); // Paper - make cancellable + CraftWorld world = (CraftWorld) entity.getWorld(); + Bukkit.getServer().getPluginManager().callEvent(event); + ++ // Paper start - make cancellable ++ if (event.isCancelled()) { ++ return event; ++ } ++ playDeathSound(victim, event); ++ // Paper end + victim.expToDrop = event.getDroppedExp(); + + for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { +@@ -823,8 +832,15 @@ public class CraftEventFactory { + CraftPlayer entity = victim.getBukkitEntity(); + PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure + event.setKeepInventory(keepInventory); ++ populateFields(victim, event); // Paper - make cancellable + org.bukkit.World world = entity.getWorld(); + Bukkit.getServer().getPluginManager().callEvent(event); ++ // Paper start - make cancellable ++ if (event.isCancelled()) { ++ return event; ++ } ++ playDeathSound(victim, event); ++ // Paper end + + victim.keepLevel = event.getKeepLevel(); + victim.newLevel = event.getNewLevel(); +@@ -841,6 +857,31 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start - helper methods for making death event cancellable ++ // Add information to death event ++ private static void populateFields(EntityLiving victim, EntityDeathEvent event) { ++ event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue()); ++ event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent()); ++ SoundEffect soundEffect = victim.getDeathSoundEffect(); ++ event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null); ++ event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundCategory().name())); ++ event.setDeathSoundVolume(victim.getDeathSoundVolume()); ++ event.setDeathSoundPitch(victim.getSoundPitch()); ++ } ++ ++ // Play death sound manually ++ private static void playDeathSound(EntityLiving victim, EntityDeathEvent event) { ++ if (event.shouldPlayDeathSound() && event.getDeathSound() != null && event.getDeathSoundCategory() != null) { ++ EntityHuman source = victim instanceof EntityHuman ? (EntityHuman) victim : null; ++ double x = event.getEntity().getLocation().getX(); ++ double y = event.getEntity().getLocation().getY(); ++ double z = event.getEntity().getLocation().getZ(); ++ SoundEffect soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound()); ++ SoundCategory soundCategory = SoundCategory.valueOf(event.getDeathSoundCategory().name()); ++ victim.world.playSound(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch()); ++ } ++ } ++ // Paper end + /** + * Server methods + */ diff --git a/patches/server-unmapped/0280-Allow-chests-to-be-placed-with-NBT-data.patch b/patches/server-unmapped/0280-Allow-chests-to-be-placed-with-NBT-data.patch new file mode 100644 index 0000000000..d861678244 --- /dev/null +++ b/patches/server-unmapped/0280-Allow-chests-to-be-placed-with-NBT-data.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 8 Sep 2018 18:43:31 -0500 +Subject: [PATCH] Allow chests to be placed with NBT data + + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 24db5dedf8b41b26fa990a7c7317cdb3e89e7fcd..852f9d99001b35f8c97f4445d8f605533d7f6f2f 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -298,6 +298,7 @@ public final class ItemStack { + enuminteractionresult = EnumInteractionResult.FAIL; // cancel placement + // PAIL: Remove this when MC-99075 fixed + placeEvent.getPlayer().updateInventory(); ++ world.capturedTileEntities.clear(); // Paper - clear out tile entities as chests and such will pop loot + // revert back all captured blocks + for (BlockState blockstate : blocks) { + blockstate.update(true, false); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java +index 51167d776c710decb0107bebcb35bdf43103772b..111f62d0e5b40e945793b8f504f2c035c0884a6a 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java +@@ -327,7 +327,7 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic + // CraftBukkit start + @Override + public boolean isFilteredNBT() { +- return true; ++ return false; // Paper + } + // CraftBukkit end + } diff --git a/patches/server-unmapped/0281-Mob-Pathfinding-API.patch b/patches/server-unmapped/0281-Mob-Pathfinding-API.patch new file mode 100644 index 0000000000..34e0d63bf2 --- /dev/null +++ b/patches/server-unmapped/0281-Mob-Pathfinding-API.patch @@ -0,0 +1,290 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 9 Sep 2018 13:30:00 -0400 +Subject: [PATCH] Mob Pathfinding API + +Implements Pathfinding API for mobs + +diff --git a/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9a3edd114c4736b1843844c6ca49da7aea7983d1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java +@@ -0,0 +1,141 @@ ++package com.destroystokyo.paper.entity; ++ ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.level.pathfinder.PathEntity; ++import net.minecraft.world.level.pathfinder.PathPoint; ++import org.apache.commons.lang.Validate; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Mob; ++ ++import javax.annotation.Nonnull; ++import javax.annotation.Nullable; ++import java.util.ArrayList; ++import java.util.List; ++ ++public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder { ++ ++ private final EntityInsentient entity; ++ ++ public PaperPathfinder(EntityInsentient entity) { ++ this.entity = entity; ++ } ++ ++ @Override ++ public Mob getEntity() { ++ return entity.getBukkitMob(); ++ } ++ ++ @Override ++ public void stopPathfinding() { ++ entity.getNavigation().stopPathfinding(); ++ } ++ ++ @Override ++ public boolean hasPath() { ++ return entity.getNavigation().getPathEntity() != null; ++ } ++ ++ @Nullable ++ @Override ++ public PathResult getCurrentPath() { ++ PathEntity path = entity.getNavigation().getPathEntity(); ++ return path != null ? new PaperPathResult(path) : null; ++ } ++ ++ @Nullable ++ @Override ++ public PathResult findPath(Location loc) { ++ Validate.notNull(loc, "Location can not be null"); ++ PathEntity path = entity.getNavigation().calculateDestination(loc.getX(), loc.getY(), loc.getZ()); ++ return path != null ? new PaperPathResult(path) : null; ++ } ++ ++ @Nullable ++ @Override ++ public PathResult findPath(LivingEntity target) { ++ Validate.notNull(target, "Target can not be null"); ++ PathEntity path = entity.getNavigation().calculateDestination(((CraftLivingEntity) target).getHandle()); ++ return path != null ? new PaperPathResult(path) : null; ++ } ++ ++ @Override ++ public boolean moveTo(@Nonnull PathResult path, double speed) { ++ Validate.notNull(path, "PathResult can not be null"); ++ PathEntity pathEntity = ((PaperPathResult) path).path; ++ return entity.getNavigation().setDestination(pathEntity, speed); ++ } ++ ++ @Override ++ public boolean canOpenDoors() { ++ return entity.getNavigation().getPathfinder().getPathfinder().shouldOpenDoors(); ++ } ++ ++ @Override ++ public void setCanOpenDoors(boolean canOpenDoors) { ++ entity.getNavigation().getPathfinder().getPathfinder().setShouldOpenDoors(canOpenDoors); ++ } ++ ++ @Override ++ public boolean canPassDoors() { ++ return entity.getNavigation().getPathfinder().getPathfinder().shouldPassDoors(); ++ } ++ ++ @Override ++ public void setCanPassDoors(boolean canPassDoors) { ++ entity.getNavigation().getPathfinder().getPathfinder().setShouldPassDoors(canPassDoors); ++ } ++ ++ @Override ++ public boolean canFloat() { ++ return entity.getNavigation().getPathfinder().getPathfinder().shouldFloat(); ++ } ++ ++ @Override ++ public void setCanFloat(boolean canFloat) { ++ entity.getNavigation().getPathfinder().getPathfinder().setShouldFloat(canFloat); ++ } ++ ++ public class PaperPathResult implements com.destroystokyo.paper.entity.PaperPathfinder.PathResult { ++ ++ private final PathEntity path; ++ PaperPathResult(PathEntity path) { ++ this.path = path; ++ } ++ ++ @Nullable ++ @Override ++ public Location getFinalPoint() { ++ PathPoint point = path.getFinalPoint(); ++ return point != null ? toLoc(point) : null; ++ } ++ ++ @Override ++ public List getPoints() { ++ List points = new ArrayList<>(); ++ for (PathPoint point : path.getPoints()) { ++ points.add(toLoc(point)); ++ } ++ return points; ++ } ++ ++ @Override ++ public int getNextPointIndex() { ++ return path.getNextIndex(); ++ } ++ ++ @Nullable ++ @Override ++ public Location getNextPoint() { ++ if (!path.hasNext()) { ++ return null; ++ } ++ return toLoc(path.getPoints().get(path.getNextIndex())); ++ } ++ } ++ ++ private Location toLoc(PathPoint point) { ++ return new Location(entity.world.getWorld(), point.getX(), point.getY(), point.getZ()); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +index d134333c736dc1ee1c722d680d7a9c22c1b265bd..06d05b511d623d0247d44989bee85b383a8fb52f 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +@@ -100,7 +100,7 @@ public abstract class NavigationAbstract { + } + + @Nullable +- public final PathEntity a(double d0, double d1, double d2, int i) { ++ public final PathEntity calculateDestination(double d0, double d1, double d2) { return a(d0, d1, d2, 0); } public final PathEntity a(double d0, double d1, double d2, int i) { // Paper - OBFHELPER + return this.a(new BlockPosition(d0, d1, d2), i); + } + +@@ -125,7 +125,7 @@ public abstract class NavigationAbstract { + } + + @Nullable +- public PathEntity a(Entity entity, int i) { ++ public final PathEntity calculateDestination(Entity entity) { return a(entity, 0); } public PathEntity a(Entity entity, int i) { + return this.a(ImmutableSet.of(entity.getChunkCoordinates()), entity, 16, true, i); // Paper + } + +@@ -190,6 +190,7 @@ public abstract class NavigationAbstract { + return pathentity != null && this.a(pathentity, d0); + } + ++ public boolean setDestination(@Nullable PathEntity pathentity, double speed) { return a(pathentity, speed); } // Paper - OBFHELPER + public boolean a(@Nullable PathEntity pathentity, double d0) { + if (pathentity == null) { + this.c = null; +@@ -217,7 +218,7 @@ public abstract class NavigationAbstract { + } + } + +- @Nullable ++ @Nullable public PathEntity getPathEntity() { return k(); } @Nullable // Paper - OBFHELPER + public PathEntity k() { + return this.c; + } +@@ -341,6 +342,7 @@ public abstract class NavigationAbstract { + return !this.m(); + } + ++ public void stopPathfinding() { o(); } // Paper - OBFHELPER + public void o() { + this.c = null; + } +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java b/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java +index 606027de777750f6d2ab0d7f1ef387ed4f0c6092..81c3cb9da3f901d2bcf384f7113bdc5c60f9962f 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java +@@ -8,13 +8,14 @@ import net.minecraft.world.phys.Vec3D; + + public class PathEntity { + +- private final List a; ++ private final List a; public List getPoints() { return a; } // Paper - OBFHELPER + private PathPoint[] b = new PathPoint[0]; + private PathPoint[] c = new PathPoint[0]; +- private int e; ++ private int e; public int getNextIndex() { return this.e; } // Paper - OBFHELPER + private final BlockPosition f; + private final float g; + private final boolean h; ++ public boolean hasNext() { return getNextIndex() < getPoints().size(); } // Paper + + public PathEntity(List list, BlockPosition blockposition, boolean flag) { + this.a = list; +@@ -36,7 +37,7 @@ public class PathEntity { + } + + @Nullable +- public PathPoint d() { ++ public PathPoint getFinalPoint() { return d(); } @Nullable public PathPoint d() { // Paper - OBFHELPER + return !this.a.isEmpty() ? (PathPoint) this.a.get(this.a.size() - 1) : null; + } + +@@ -84,7 +85,7 @@ public class PathEntity { + return this.a(entity, this.e); + } + +- public BlockPosition g() { ++ public BlockPosition getNext() { return g(); } public BlockPosition g() { // Paper - OBFHELPER + return ((PathPoint) this.a.get(this.e)).a(); + } + +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java b/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java +index 43cc9430972a18cbf03a590d576ed200e3836017..c260b0ca70cb18811158761c574aee9c3166da28 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java +@@ -5,9 +5,9 @@ import net.minecraft.util.MathHelper; + + public class PathPoint { + +- public final int a; +- public final int b; +- public final int c; ++ public final int a; public final int getX() { return a; } // Paper - OBFHELPER ++ public final int b; public final int getY() { return b; } // Paper - OBFHELPER ++ public final int c; public final int getZ() { return c; } // Paper - OBFHELPER + private final int m; + public int d = -1; + public float e; +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java +index f2080bd50db04af6eabec4b4b757d6dadfb1a2f5..88be03bd77656235322522c3782b9f9a878b86b1 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java +@@ -16,9 +16,9 @@ public abstract class PathfinderAbstract { + protected int d; + protected int e; + protected int f; +- protected boolean g; +- protected boolean h; +- protected boolean i; ++ protected boolean g; public boolean shouldPassDoors() { return g; } public void setShouldPassDoors(boolean b) { g = b; } // Paper - obfhelper ++ protected boolean h; public boolean shouldOpenDoors() { return h; } public void setShouldOpenDoors(boolean b) { h = b; } // Paper - obfhelper ++ protected boolean i; public boolean shouldFloat() { return i; } public void setShouldFloat(boolean b) { i = b; } // Paper - obfhelper + + public PathfinderAbstract() {} + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +index eb275ac45def34d5bb1ed696b4f6a4d53d282ab3..28a4e90130f51fd2fda7003fde5b4d0a410e1aef 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +@@ -12,8 +12,11 @@ import org.bukkit.loot.LootTable; + public abstract class CraftMob extends CraftLivingEntity implements Mob { + public CraftMob(CraftServer server, EntityInsentient entity) { + super(server, entity); ++ paperPathfinder = new com.destroystokyo.paper.entity.PaperPathfinder(entity); // Paper + } + ++ private final com.destroystokyo.paper.entity.PaperPathfinder paperPathfinder; // Paper ++ @Override public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { return paperPathfinder; } // Paper + @Override + public void setTarget(LivingEntity target) { + EntityInsentient entity = getHandle(); diff --git a/patches/server-unmapped/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch b/patches/server-unmapped/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch new file mode 100644 index 0000000000..3b7bb307af --- /dev/null +++ b/patches/server-unmapped/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 10 Sep 2018 23:36:16 -0400 +Subject: [PATCH] Prevent chunk loading from Fluid Flowing + + +diff --git a/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java b/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java +index 2f0f8a44d808875d70123a63487ce1ebe02f53a9..6bb4ec00e40795ced73648fefcd1f5027e0113cd 100644 +--- a/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java ++++ b/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java +@@ -176,7 +176,8 @@ public abstract class FluidTypeFlowing extends FluidType { + EnumDirection enumdirection = (EnumDirection) entry.getKey(); + Fluid fluid1 = (Fluid) entry.getValue(); + BlockPosition blockposition1 = blockposition.shift(enumdirection); +- IBlockData iblockdata1 = generatoraccess.getType(blockposition1); ++ IBlockData iblockdata1 = generatoraccess.getTypeIfLoaded(blockposition1); // Paper ++ if (iblockdata1 == null) continue; // Paper + + if (this.a(generatoraccess, blockposition, iblockdata, enumdirection, blockposition1, iblockdata1, generatoraccess.getFluid(blockposition1), fluid1.getType())) { + // CraftBukkit start +@@ -203,7 +204,8 @@ public abstract class FluidTypeFlowing extends FluidType { + while (iterator.hasNext()) { + EnumDirection enumdirection = (EnumDirection) iterator.next(); + BlockPosition blockposition1 = blockposition.shift(enumdirection); +- IBlockData iblockdata1 = iworldreader.getType(blockposition1); ++ IBlockData iblockdata1 = iworldreader.getTypeIfLoaded(blockposition1); // Paper ++ if (iblockdata1 == null) continue; // Paper + Fluid fluid = iblockdata1.getFluid(); + + if (fluid.getType().a((FluidType) this) && this.a(enumdirection, (IBlockAccess) iworldreader, blockposition, iblockdata, blockposition1, iblockdata1)) { +@@ -320,11 +322,18 @@ public abstract class FluidTypeFlowing extends FluidType { + if (enumdirection1 != enumdirection) { + BlockPosition blockposition2 = blockposition.shift(enumdirection1); + short short0 = a(blockposition1, blockposition2); +- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (k) -> { +- IBlockData iblockdata1 = iworldreader.getType(blockposition2); ++ // Paper start - avoid loading chunks ++ Pair pair = short2objectmap.get(short0); ++ if (pair == null) { ++ IBlockData iblockdatax = iworldreader.getTypeIfLoaded(blockposition2); ++ if (iblockdatax == null) { ++ continue; ++ } + +- return Pair.of(iblockdata1, iblockdata1.getFluid()); +- }); ++ pair = Pair.of(iblockdatax, iblockdatax.getFluid()); ++ short2objectmap.put(short0, pair); ++ } ++ // Paper end + IBlockData iblockdata1 = (IBlockData) pair.getFirst(); + Fluid fluid = (Fluid) pair.getSecond(); + +@@ -396,11 +405,16 @@ public abstract class FluidTypeFlowing extends FluidType { + EnumDirection enumdirection = (EnumDirection) iterator.next(); + BlockPosition blockposition1 = blockposition.shift(enumdirection); + short short0 = a(blockposition, blockposition1); +- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (j) -> { +- IBlockData iblockdata1 = iworldreader.getType(blockposition1); +- +- return Pair.of(iblockdata1, iblockdata1.getFluid()); +- }); ++ // Paper start ++ Pair pair = (Pair) short2objectmap.get(short0); ++ if (pair == null) { ++ IBlockData iblockdatax = iworldreader.getTypeIfLoaded(blockposition1); ++ if (iblockdatax == null) continue; ++ ++ pair = Pair.of(iblockdatax, iblockdatax.getFluid()); ++ short2objectmap.put(short0, pair); ++ } ++ // Paper end + IBlockData iblockdata1 = (IBlockData) pair.getFirst(); + Fluid fluid = (Fluid) pair.getSecond(); + Fluid fluid1 = this.a(iworldreader, blockposition1, iblockdata1); diff --git a/patches/server-unmapped/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/patches/server-unmapped/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch new file mode 100644 index 0000000000..22d4952f48 --- /dev/null +++ b/patches/server-unmapped/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch @@ -0,0 +1,446 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Wed, 12 Sep 2018 18:53:55 +0300 +Subject: [PATCH] Implement an API for CanPlaceOn and CanDestroy NBT values + + +diff --git a/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java b/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java +index 7e53d8b787c42f8592140f7de8974bc63e5149b2..d72b800e5f03422d0b2518980b1955ec7d2b08e8 100644 +--- a/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java ++++ b/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java +@@ -57,7 +57,7 @@ public class ArgumentBlock { + private final boolean j; + private final Map, Comparable> k = Maps.newLinkedHashMap(); // CraftBukkit - stable + private final Map l = Maps.newHashMap(); +- private MinecraftKey m = new MinecraftKey(""); ++ private MinecraftKey m = new MinecraftKey(""); public final MinecraftKey getBlockKey() { return this.m; } // Paper - OBFHELPER + private BlockStateList n; + private IBlockData o; + @Nullable +@@ -86,11 +86,13 @@ public class ArgumentBlock { + return this.p; + } + ++ public final @Nullable MinecraftKey getTagKey() { return d(); } // Paper - OBFHELPER + @Nullable + public MinecraftKey d() { + return this.q; + } + ++ public final ArgumentBlock parse(boolean parseTile) throws CommandSyntaxException { return this.a(parseTile); } // Paper - OBFHELPER + public ArgumentBlock a(boolean flag) throws CommandSyntaxException { + this.s = this::l; + if (this.i.canRead() && this.i.peek() == '#') { +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 7f790c484fec77e1d1f1dc6abe0daa19d009ae46..8f8dccd6fb2e49d65383d6e8f3fc5ffbabd2b7a5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -39,12 +39,14 @@ import java.util.logging.Level; + import java.util.logging.Logger; + import javax.annotation.Nonnull; + import javax.annotation.Nullable; ++import net.minecraft.commands.arguments.blocks.ArgumentBlock; + import net.minecraft.nbt.NBTBase; + import net.minecraft.nbt.NBTCompressedStreamTools; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.nbt.NBTTagList; + import net.minecraft.nbt.NBTTagString; + import net.minecraft.network.chat.ChatComponentText; ++import net.minecraft.resources.MinecraftKey; + import net.minecraft.world.entity.EnumItemSlot; + import net.minecraft.world.item.ItemBlock; + import org.apache.commons.codec.binary.Base64; +@@ -84,6 +86,12 @@ import org.bukkit.persistence.PersistentDataContainer; + import static org.spigotmc.ValidateUtils.*; + // Spigot end + ++// Paper start ++import com.destroystokyo.paper.Namespaced; ++import com.destroystokyo.paper.NamespacedTag; ++import java.util.Collections; ++// Paper end ++ + /** + * Children must include the following: + * +@@ -267,6 +275,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + @Specific(Specific.To.NBT) + static final ItemMetaKey BLOCK_DATA = new ItemMetaKey("BlockStateTag"); + static final ItemMetaKey BUKKIT_CUSTOM_TAG = new ItemMetaKey("PublicBukkitValues"); ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ static final ItemMetaKey CAN_DESTROY = new ItemMetaKey("CanDestroy"); ++ static final ItemMetaKey CAN_PLACE_ON = new ItemMetaKey("CanPlaceOn"); ++ // Paper end + + // We store the raw original JSON representation of all text data. See SPIGOT-5063, SPIGOT-5656, SPIGOT-5304 + private String displayName; +@@ -280,6 +292,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + private int hideFlag; + private boolean unbreakable; + private int damage; ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ private Set placeableKeys = Sets.newHashSet(); ++ private Set destroyableKeys = Sets.newHashSet(); ++ // Paper end + + private static final Set HANDLED_TAGS = Sets.newHashSet(); + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); +@@ -317,6 +333,15 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + this.hideFlag = meta.hideFlag; + this.unbreakable = meta.unbreakable; + this.damage = meta.damage; ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (meta.hasPlaceableKeys()) { ++ this.placeableKeys = new java.util.HashSet<>(meta.placeableKeys); ++ } ++ ++ if (meta.hasDestroyableKeys()) { ++ this.destroyableKeys = new java.util.HashSet<>(meta.destroyableKeys); ++ } ++ // Paper end + this.unhandledTags.putAll(meta.unhandledTags); + this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw()); + +@@ -380,6 +405,31 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + persistentDataContainer.put(key, compound.get(key)); + } + } ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (tag.hasKey(CAN_DESTROY.NBT)) { ++ NBTTagList list = tag.getList(CAN_DESTROY.NBT, CraftMagicNumbers.NBT.TAG_STRING); ++ for (int i = 0; i < list.size(); i++) { ++ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); ++ if (namespaced == null) { ++ continue; ++ } ++ ++ this.destroyableKeys.add(namespaced); ++ } ++ } ++ ++ if (tag.hasKey(CAN_PLACE_ON.NBT)) { ++ NBTTagList list = tag.getList(CAN_PLACE_ON.NBT, CraftMagicNumbers.NBT.TAG_STRING); ++ for (int i = 0; i < list.size(); i++) { ++ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); ++ if (namespaced == null) { ++ continue; ++ } ++ ++ this.placeableKeys.add(namespaced); ++ } ++ } ++ // Paper end + + Set keys = tag.getKeys(); + for (String key : keys) { +@@ -518,6 +568,34 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + setDamage(damage); + } + ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ Iterable canPlaceOnSerialized = SerializableMeta.getObject(Iterable.class, map, CAN_PLACE_ON.BUKKIT, true); ++ if (canPlaceOnSerialized != null) { ++ for (Object canPlaceOnElement : canPlaceOnSerialized) { ++ String canPlaceOnRaw = (String) canPlaceOnElement; ++ Namespaced value = this.deserializeNamespaced(canPlaceOnRaw); ++ if (value == null) { ++ continue; ++ } ++ ++ this.placeableKeys.add(value); ++ } ++ } ++ ++ Iterable canDestroySerialized = SerializableMeta.getObject(Iterable.class, map, CAN_DESTROY.BUKKIT, true); ++ if (canDestroySerialized != null) { ++ for (Object canDestroyElement : canDestroySerialized) { ++ String canDestroyRaw = (String) canDestroyElement; ++ Namespaced value = this.deserializeNamespaced(canDestroyRaw); ++ if (value == null) { ++ continue; ++ } ++ ++ this.destroyableKeys.add(value); ++ } ++ } ++ // Paper end ++ + String internal = SerializableMeta.getString(map, "internal", true); + if (internal != null) { + ByteArrayInputStream buf = new ByteArrayInputStream(Base64.decodeBase64(internal)); +@@ -646,6 +724,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + if (hasDamage()) { + itemTag.setInt(DAMAGE.NBT, damage); + } ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (hasPlaceableKeys()) { ++ List items = this.placeableKeys.stream() ++ .map(this::serializeNamespaced) ++ .collect(java.util.stream.Collectors.toList()); ++ ++ itemTag.set(CAN_PLACE_ON.NBT, createNonComponentStringList(items)); ++ } ++ ++ if (hasDestroyableKeys()) { ++ List items = this.destroyableKeys.stream() ++ .map(this::serializeNamespaced) ++ .collect(java.util.stream.Collectors.toList()); ++ ++ itemTag.set(CAN_DESTROY.NBT, createNonComponentStringList(items)); ++ } ++ // Paper end + + for (Map.Entry e : unhandledTags.entrySet()) { + itemTag.set(e.getKey(), e.getValue()); +@@ -662,6 +757,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + } + ++ // Paper start ++ static NBTTagList createNonComponentStringList(List list) { ++ if (list == null || list.isEmpty()) { ++ return null; ++ } ++ ++ NBTTagList tagList = new NBTTagList(); ++ for (String value : list) { ++ tagList.add(NBTTagString.a(value)); // Paper - NBTTagString.of(String str) ++ } ++ ++ return tagList; ++ } ++ // Paper end ++ + NBTTagList createStringList(List list) { + if (list == null) { + return null; +@@ -745,7 +855,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + + @Overridden + boolean isEmpty() { +- return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); ++ return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers() || hasPlaceableKeys() || hasDestroyableKeys()); // Paper - Implement an API for CanPlaceOn and CanDestroy NBT values + } + + // Paper start +@@ -1169,7 +1279,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + && (this.hideFlag == that.hideFlag) + && (this.isUnbreakable() == that.isUnbreakable()) + && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) +- && (this.version == that.version); ++ && (this.version == that.version) ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ && (this.hasPlaceableKeys() ? that.hasPlaceableKeys() && this.placeableKeys.equals(that.placeableKeys) : !that.hasPlaceableKeys()) ++ && (this.hasDestroyableKeys() ? that.hasDestroyableKeys() && this.destroyableKeys.equals(that.destroyableKeys) : !that.hasDestroyableKeys()); ++ // Paper end + } + + /** +@@ -1204,6 +1318,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + hash = 61 * hash + (hasDamage() ? this.damage : 0); + hash = 61 * hash + (hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); + hash = 61 * hash + version; ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ hash = 61 * hash + (hasPlaceableKeys() ? this.placeableKeys.hashCode() : 0); ++ hash = 61 * hash + (hasDestroyableKeys() ? this.destroyableKeys.hashCode() : 0); ++ // Paper end + return hash; + } + +@@ -1228,6 +1346,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + clone.unbreakable = this.unbreakable; + clone.damage = this.damage; + clone.version = this.version; ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (this.placeableKeys != null) { ++ clone.placeableKeys = Sets.newHashSet(this.placeableKeys); ++ } ++ if (this.destroyableKeys != null) { ++ clone.destroyableKeys = Sets.newHashSet(this.destroyableKeys); ++ } ++ // Paper end + return clone; + } catch (CloneNotSupportedException e) { + throw new Error(e); +@@ -1285,6 +1411,24 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + builder.put(DAMAGE.BUKKIT, damage); + } + ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ if (hasPlaceableKeys()) { ++ List cerealPlaceable = this.placeableKeys.stream() ++ .map(this::serializeNamespaced) ++ .collect(java.util.stream.Collectors.toList()); ++ ++ builder.put(CAN_PLACE_ON.BUKKIT, cerealPlaceable); ++ } ++ ++ if (hasDestroyableKeys()) { ++ List cerealDestroyable = this.destroyableKeys.stream() ++ .map(this::serializeNamespaced) ++ .collect(java.util.stream.Collectors.toList()); ++ ++ builder.put(CAN_DESTROY.BUKKIT, cerealDestroyable); ++ } ++ // Paper end ++ + final Map internalTags = new HashMap(unhandledTags); + serializeInternal(internalTags); + if (!internalTags.isEmpty()) { +@@ -1449,6 +1593,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + CraftMetaArmorStand.SHOW_ARMS.NBT, + CraftMetaArmorStand.SMALL.NBT, + CraftMetaArmorStand.MARKER.NBT, ++ CAN_DESTROY.NBT, ++ CAN_PLACE_ON.NBT, + // Paper end + CraftMetaCompass.LODESTONE_DIMENSION.NBT, + CraftMetaCompass.LODESTONE_POS.NBT, +@@ -1476,4 +1622,147 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + // Paper end + ++ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values ++ @Override ++ @SuppressWarnings("deprecation") ++ public Set getCanDestroy() { ++ return !hasDestroyableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.destroyableKeys); ++ } ++ ++ @Override ++ @SuppressWarnings("deprecation") ++ public void setCanDestroy(Set canDestroy) { ++ Validate.notNull(canDestroy, "Cannot replace with null set!"); ++ legacyClearAndReplaceKeys(this.destroyableKeys, canDestroy); ++ } ++ ++ @Override ++ @SuppressWarnings("deprecation") ++ public Set getCanPlaceOn() { ++ return !hasPlaceableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.placeableKeys); ++ } ++ ++ @Override ++ @SuppressWarnings("deprecation") ++ public void setCanPlaceOn(Set canPlaceOn) { ++ Validate.notNull(canPlaceOn, "Cannot replace with null set!"); ++ legacyClearAndReplaceKeys(this.placeableKeys, canPlaceOn); ++ } ++ ++ @Override ++ public Set getDestroyableKeys() { ++ return !hasDestroyableKeys() ? Collections.emptySet() : Sets.newHashSet(this.destroyableKeys); ++ } ++ ++ @Override ++ public void setDestroyableKeys(Collection canDestroy) { ++ Validate.notNull(canDestroy, "Cannot replace with null collection!"); ++ Validate.isTrue(ofAcceptableType(canDestroy), "Can only use NamespacedKey or NamespacedTag objects!"); ++ this.destroyableKeys.clear(); ++ this.destroyableKeys.addAll(canDestroy); ++ } ++ ++ @Override ++ public Set getPlaceableKeys() { ++ return !hasPlaceableKeys() ? Collections.emptySet() : Sets.newHashSet(this.placeableKeys); ++ } ++ ++ @Override ++ public void setPlaceableKeys(Collection canPlaceOn) { ++ Validate.notNull(canPlaceOn, "Cannot replace with null collection!"); ++ Validate.isTrue(ofAcceptableType(canPlaceOn), "Can only use NamespacedKey or NamespacedTag objects!"); ++ this.placeableKeys.clear(); ++ this.placeableKeys.addAll(canPlaceOn); ++ } ++ ++ @Override ++ public boolean hasPlaceableKeys() { ++ return this.placeableKeys != null && !this.placeableKeys.isEmpty(); ++ } ++ ++ @Override ++ public boolean hasDestroyableKeys() { ++ return this.destroyableKeys != null && !this.destroyableKeys.isEmpty(); ++ } ++ ++ @Deprecated ++ private void legacyClearAndReplaceKeys(Collection toUpdate, Collection beingSet) { ++ if (beingSet.stream().anyMatch(Material::isLegacy)) { ++ throw new IllegalArgumentException("Set must not contain any legacy materials!"); ++ } ++ ++ toUpdate.clear(); ++ toUpdate.addAll(beingSet.stream().map(Material::getKey).collect(java.util.stream.Collectors.toSet())); ++ } ++ ++ @Deprecated ++ private Set legacyGetMatsFromKeys(Collection names) { ++ Set mats = Sets.newHashSet(); ++ for (Namespaced key : names) { ++ if (!(key instanceof org.bukkit.NamespacedKey)) { ++ continue; ++ } ++ ++ Material material = Material.matchMaterial(key.toString(), false); ++ if (material != null) { ++ mats.add(material); ++ } ++ } ++ ++ return mats; ++ } ++ ++ private @Nullable Namespaced deserializeNamespaced(String raw) { ++ boolean isTag = raw.length() > 0 && raw.codePointAt(0) == '#'; ++ ArgumentBlock blockParser = new ArgumentBlock(new com.mojang.brigadier.StringReader(raw), true); ++ try { ++ blockParser = blockParser.parse(false); ++ } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) { ++ e.printStackTrace(); ++ return null; ++ } ++ ++ MinecraftKey key; ++ if (isTag) { ++ key = blockParser.getTagKey(); ++ } else { ++ key = blockParser.getBlockKey(); ++ } ++ ++ if (key == null) { ++ return null; ++ } ++ ++ // don't DC the player if something slips through somehow ++ Namespaced resource = null; ++ try { ++ if (isTag) { ++ resource = new NamespacedTag(key.getNamespace(), key.getKey()); ++ } else { ++ resource = CraftNamespacedKey.fromMinecraft(key); ++ } ++ } catch (IllegalArgumentException ex) { ++ org.bukkit.Bukkit.getLogger().warning("Namespaced resource does not validate: " + key.toString()); ++ ex.printStackTrace(); ++ } ++ ++ return resource; ++ } ++ ++ private @Nonnull String serializeNamespaced(Namespaced resource) { ++ return resource.toString(); ++ } ++ ++ // not a fan of this ++ private boolean ofAcceptableType(Collection namespacedResources) { ++ ++ for (Namespaced resource : namespacedResources) { ++ if (!(resource instanceof org.bukkit.NamespacedKey || resource instanceof com.destroystokyo.paper.NamespacedTag)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/patches/server-unmapped/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch new file mode 100644 index 0000000000..29f93fd83f --- /dev/null +++ b/patches/server-unmapped/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 10 Sep 2018 23:56:36 -0400 +Subject: [PATCH] Prevent Mob AI Rules from Loading Chunks + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java +index b5c7b39a49afae1089a293b9b06bdd94deed1f64..61a62c093b24c43064f116630d85096159e082d3 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java +@@ -30,11 +30,13 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { + private final Block g; + private final EntityInsentient entity; + private int i; ++ private World world; // Paper + + public PathfinderGoalRemoveBlock(Block block, EntityCreature entitycreature, double d0, int i) { + super(entitycreature, d0, 24, i); + this.g = block; + this.entity = entitycreature; ++ this.world = entitycreature.world; // Paper + } + + @Override +@@ -132,7 +134,9 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { + + @Nullable + private BlockPosition a(BlockPosition blockposition, IBlockAccess iblockaccess) { +- if (iblockaccess.getType(blockposition).a(this.g)) { ++ Block block = world.getBlockIfLoaded(blockposition); // Paper ++ if (block == null) return null; // Paper ++ if (block.a(this.g)) { // Paper + return blockposition; + } else { + BlockPosition[] ablockposition = new BlockPosition[]{blockposition.down(), blockposition.west(), blockposition.east(), blockposition.north(), blockposition.south(), blockposition.down().down()}; +@@ -142,7 +146,7 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { + for (int j = 0; j < i; ++j) { + BlockPosition blockposition1 = ablockposition1[j]; + +- if (iblockaccess.getType(blockposition1).a(this.g)) { ++ if (iblockaccess.getBlockIfLoaded(blockposition1).a(this.g)) { // Paper + return blockposition1; + } + } +@@ -153,7 +157,7 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { + + @Override + protected boolean a(IWorldReader iworldreader, BlockPosition blockposition) { +- IChunkAccess ichunkaccess = iworldreader.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, false); ++ IChunkAccess ichunkaccess = iworldreader.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper + + return ichunkaccess == null ? false : ichunkaccess.getType(blockposition).a(this.g) && ichunkaccess.getType(blockposition.up()).isAir() && ichunkaccess.getType(blockposition.up(2)).isAir(); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java b/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java +index 129ea3857969ddb99e15ae817ee3eec67b4c3ccf..f9c40c8223109a9a40e7e7523c8f1f2e5aeddba1 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java ++++ b/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java +@@ -13,6 +13,7 @@ import net.minecraft.util.MathHelper; + import net.minecraft.world.entity.EntityCreature; + import net.minecraft.world.entity.ai.navigation.NavigationAbstract; + import net.minecraft.world.level.IBlockAccess; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.pathfinder.PathType; + import net.minecraft.world.level.pathfinder.PathfinderNormal; + import net.minecraft.world.phys.Vec3D; +@@ -128,6 +129,7 @@ public class RandomPositionGenerator { + } + + blockposition2 = new BlockPosition((double) k1 + entitycreature.locX(), (double) l1 + entitycreature.locY(), (double) i2 + entitycreature.locZ()); ++ if (!entitycreature.world.isLoaded(blockposition2)) continue; // Paper + if (blockposition2.getY() >= 0 && blockposition2.getY() <= entitycreature.world.getBuildHeight() && (!flag3 || entitycreature.a(blockposition2)) && (!flag2 || navigationabstract.a(blockposition2))) { + if (flag1) { + blockposition2 = a(blockposition2, random.nextInt(l + 1) + i1, entitycreature.world.getBuildHeight(), (blockposition3) -> { +@@ -135,7 +137,8 @@ public class RandomPositionGenerator { + }); + } + +- if (flag || !entitycreature.world.getFluid(blockposition2).a((Tag) TagsFluid.WATER)) { ++ Fluid fluid = entitycreature.world.getFluidIfLoaded(blockposition2); // Paper ++ if (flag || (fluid != null && !fluid.a((Tag) TagsFluid.WATER))) { // Paper + PathType pathtype = PathfinderNormal.a((IBlockAccess) entitycreature.world, blockposition2.i()); + + if (entitycreature.a(pathtype) == 0.0F) { diff --git a/patches/server-unmapped/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch b/patches/server-unmapped/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch new file mode 100644 index 0000000000..7a20915052 --- /dev/null +++ b/patches/server-unmapped/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 12 Sep 2018 21:12:57 -0400 +Subject: [PATCH] Prevent mob spawning from loading/generating chunks + +also prevents if out of world border bounds + +diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +index 1969d1002b3182338614a2be0519fcdc385b7a44..5307488fa48ffa91446dd4457de1ce6a8f61da61 100644 +--- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java ++++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +@@ -176,9 +176,9 @@ public final class SpawnerCreature { + StructureManager structuremanager = worldserver.getStructureManager(); + ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); + int i = blockposition.getY(); +- IBlockData iblockdata = ichunkaccess.getType(blockposition); ++ IBlockData iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn + +- if (!iblockdata.isOccluding(ichunkaccess, blockposition)) { ++ if (iblockdata != null && !iblockdata.isOccluding(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); + int j = 0; + int k = 0; +@@ -207,7 +207,7 @@ public final class SpawnerCreature { + if (entityhuman != null) { + double d2 = entityhuman.h(d0, (double) i, d1); + +- if (a(worldserver, ichunkaccess, blockposition_mutableblockposition, d2)) { ++ if (a(worldserver, ichunkaccess, blockposition_mutableblockposition, d2) && worldserver.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn + if (biomesettingsmobs_c == null) { + biomesettingsmobs_c = a(worldserver, structuremanager, chunkgenerator, enumcreaturetype, worldserver.random, (BlockPosition) blockposition_mutableblockposition); + if (biomesettingsmobs_c == null) { diff --git a/patches/server-unmapped/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/server-unmapped/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch new file mode 100644 index 0000000000..681fbbbb31 --- /dev/null +++ b/patches/server-unmapped/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 12 Sep 2018 21:47:01 -0400 +Subject: [PATCH] Optimize Biome Mob Lookups for Mob Spawning + +Uses an EnumMap as well as a Set paired List for O(1) contains calls. + +diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java b/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java +index 5adaf5fdaaec25220878213df2c0839ccf025d63..233ae33b5cbf1aafc7d2632149ccb84c0b243162 100644 +--- a/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java ++++ b/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java +@@ -30,18 +30,27 @@ public class BiomeSettingsMobs { + }, (enumcreaturetype) -> { + return ImmutableList.of(); + })), ImmutableMap.of(), false); ++ // Paper start- decompile error workaround ++ private static class bProxy extends BiomeSettingsMobs.b { ++ private bProxy(double d0, double d1) { ++ super(d0, d1); ++ } ++ } ++ private static class cProxy extends BiomeSettingsMobs.c { ++ public cProxy(EntityTypes entitytypes, int i, int j, int k) { ++ super(entitytypes, i, j, k); ++ } ++ }; ++ // Paper end + public static final MapCodec c = RecordCodecBuilder.mapCodec((instance) -> { +- RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { ++ RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { // Paper - add type to builder + return biomesettingsmobs.d; + }); +- Codec codec = EnumCreatureType.g; +- Codec codec1 = BiomeSettingsMobs.c.b.listOf(); +- Logger logger = BiomeSettingsMobs.LOGGER; ++ // Paper - remove unused vars + +- logger.getClass(); +- return instance.group(recordcodecbuilder, Codec.simpleMap(codec, codec1.promotePartial(SystemUtils.a("Spawn data: ", logger::error)), INamable.a(EnumCreatureType.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { ++ return instance.group(recordcodecbuilder, Codec.simpleMap(EnumCreatureType.g, cProxy.b.listOf().promotePartial(SystemUtils.a("Spawn data: ", BiomeSettingsMobs.LOGGER::error)), INamable.a(EnumCreatureType.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { // Paper - inline codec, cProxy, LOGGER + return biomesettingsmobs.e; +- }), Codec.simpleMap(IRegistry.ENTITY_TYPE, BiomeSettingsMobs.b.a, IRegistry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { ++ }), Codec.simpleMap(IRegistry.ENTITY_TYPE, bProxy.a, IRegistry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { // Paper - decompile error - bProxy + return biomesettingsmobs.f; + }), Codec.BOOL.fieldOf("player_spawn_friendly").orElse(false).forGetter(BiomeSettingsMobs::b)).apply(instance, BiomeSettingsMobs::new); + }); +@@ -76,11 +85,43 @@ public class BiomeSettingsMobs { + + public static class a { + +- private final Map> a = (Map) Stream.of(EnumCreatureType.values()).collect(ImmutableMap.toImmutableMap((enumcreaturetype) -> { ++ // Paper start - keep track of data in a pair set to give O(1) contains calls - we have to hook removals incase plugins mess with it ++ public static class MobList extends java.util.ArrayList { ++ java.util.Set biomes = new java.util.HashSet<>(); ++ ++ @Override ++ public boolean contains(Object o) { ++ return biomes.contains(o); ++ } ++ ++ @Override ++ public boolean add(BiomeSettingsMobs.c BiomeSettingsMobs) { ++ biomes.add(BiomeSettingsMobs); ++ return super.add(BiomeSettingsMobs); ++ } ++ ++ @Override ++ public BiomeSettingsMobs.c remove(int index) { ++ BiomeSettingsMobs.c removed = super.remove(index); ++ if (removed != null) { ++ biomes.remove(removed); ++ } ++ return removed; ++ } ++ ++ @Override ++ public void clear() { ++ biomes.clear(); ++ super.clear(); ++ } ++ } ++ // use toImmutableEnumMap collector ++ private final Map> a = (Map) Stream.of(EnumCreatureType.values()).collect(Maps.toImmutableEnumMap((enumcreaturetype) -> { + return enumcreaturetype; + }, (enumcreaturetype) -> { +- return Lists.newArrayList(); ++ return new MobList(); // Use MobList instead of ArrayList + })); ++ // Paper end + private final Map, BiomeSettingsMobs.b> b = Maps.newLinkedHashMap(); + private float c = 0.1F; + private boolean d; diff --git a/patches/server-unmapped/0287-Implement-furnace-cook-speed-multiplier-API.patch b/patches/server-unmapped/0287-Implement-furnace-cook-speed-multiplier-API.patch new file mode 100644 index 0000000000..110e0093a4 --- /dev/null +++ b/patches/server-unmapped/0287-Implement-furnace-cook-speed-multiplier-API.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tassu +Date: Thu, 13 Sep 2018 08:45:21 +0300 +Subject: [PATCH] Implement furnace cook speed multiplier API + +Signed-off-by: Tassu + +Fixed an issue where a furnace's cook-speed multiplier rounds down +to the nearest Integer when updating its current cook time. + +Modified by: Eric Su + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +index deaa4c136c23dc6c258cc1ce68523b3c007c80f9..e630e8d3e115d2a0177849ad8258a2304b9d3e9d 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +@@ -40,6 +40,7 @@ import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3D; + + // CraftBukkit start ++import java.util.List; + import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.craftbukkit.inventory.CraftItemStack; +@@ -58,6 +59,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + protected NonNullList items; + public int burnTime; + private int ticksForCurrentFuel; ++ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API + public int cookTime; + public int cookTimeTotal; + protected final IContainerProperties b; +@@ -258,6 +260,11 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + this.n.put(new MinecraftKey(s), nbttagcompound1.getInt(s)); + } + ++ // Paper start - cook speed API ++ if (nbttagcompound.hasKey("Paper.CookSpeedMultiplier")) { ++ this.cookSpeedMultiplier = nbttagcompound.getDouble("Paper.CookSpeedMultiplier"); ++ } ++ // Paper end + } + + @Override +@@ -266,6 +273,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + nbttagcompound.setShort("BurnTime", (short) this.burnTime); + nbttagcompound.setShort("CookTime", (short) this.cookTime); + nbttagcompound.setShort("CookTimeTotal", (short) this.cookTimeTotal); ++ nbttagcompound.setDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API + ContainerUtil.a(nbttagcompound, this.items); + NBTTagCompound nbttagcompound1 = new NBTTagCompound(); + +@@ -326,7 +334,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + + if (this.isBurning() && this.canBurn(irecipe)) { + ++this.cookTime; +- if (this.cookTime == this.cookTimeTotal) { ++ if (this.cookTime >= this.cookTimeTotal) { // Paper - cook speed multiplier API + this.cookTime = 0; + this.cookTimeTotal = this.getRecipeCookingTime(); + this.burn(irecipe); +@@ -426,9 +434,13 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + } + } + +- protected int getRecipeCookingTime() { +- return (this.hasWorld()) ? (Integer) this.world.getCraftingManager().craft((Recipes) this.c, this, this.world).map(RecipeCooking::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail ++ // Paper begin - Expose this function so CraftFurnace can correctly scale the total cooking time to a new multiplier ++ public int getRecipeCookingTime() { ++ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */ ++ int cookTime = (this.hasWorld()) ? (Integer) this.world.getCraftingManager().craft((Recipes) this.c, this, this.world).map(RecipeCooking::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail ++ return (int) Math.ceil (cookTime / this.cookSpeedMultiplier); + } ++ // Paper end + + public static boolean isFuel(ItemStack itemstack) { + return f().containsKey(itemstack.getItem()); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java +index 760fe719f2f8836c41f6a49d8a795703b2474390..86ad5f78eecc01863897838cb1f311f5dd3d996d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java +@@ -63,4 +63,20 @@ public abstract class CraftFurnace extends CraftCon + public void setCookTimeTotal(int cookTimeTotal) { + this.getSnapshot().cookTimeTotal = cookTimeTotal; + } ++ ++ // Paper start - cook speed multiplier API ++ @Override ++ public double getCookSpeedMultiplier() { ++ return this.getSnapshot().cookSpeedMultiplier; ++ } ++ ++ @Override ++ public void setCookSpeedMultiplier(double multiplier) { ++ com.google.common.base.Preconditions.checkArgument(multiplier >= 0, "Furnace speed multiplier cannot be negative"); ++ com.google.common.base.Preconditions.checkArgument(multiplier <= 200, "Furnace speed multiplier cannot more than 200"); ++ T snapshot = this.getSnapshot(); ++ snapshot.cookSpeedMultiplier = multiplier; ++ snapshot.cookTimeTotal = snapshot.getRecipeCookingTime(); // Update the snapshot's current total cook time to scale with the newly set multiplier ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0288-PreSpawnerSpawnEvent.patch b/patches/server-unmapped/0288-PreSpawnerSpawnEvent.patch new file mode 100644 index 0000000000..df8c61a859 --- /dev/null +++ b/patches/server-unmapped/0288-PreSpawnerSpawnEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Tue, 18 Sep 2018 23:53:23 +0100 +Subject: [PATCH] PreSpawnerSpawnEvent + +This adds a separate event before an entity is spawned by a spawner +which contains the location of the spawner too similarly to how the +SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for +spawners. + +diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +index d4b8126f12fdf7d9b4f882d3ed7d8da544ed9e8a..867478484c0ba4ff467b96e458689937299b981d 100644 +--- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java ++++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +@@ -132,11 +132,11 @@ public abstract class MobSpawnerAbstract { + + org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); + if (type != null) { +- com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; +- event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent( + MCUtil.toLocation(world, d3, d4, d5), + type, +- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER ++ MCUtil.toLocation(world, blockposition) + ); + if (!event.callEvent()) { + flag = true; diff --git a/patches/server-unmapped/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch b/patches/server-unmapped/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch new file mode 100644 index 0000000000..21a0e7b36d --- /dev/null +++ b/patches/server-unmapped/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 22 Sep 2018 15:56:59 -0400 +Subject: [PATCH] Catch JsonParseException in Entity and TE names + +As a result, data that no longer parses correctly will not crash the server +instead just logging the exception and continuing (and in most cases should +fix the data) + +Player data is fixed pretty much immediately but some block data (like +Shulkers) may need to be changed in order for it to re-save properly + +No more crashing though. + +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index cd7dc7d90efddb8a1bb50cd964b43d18cf9c83d1..35d1444c5b75d9a3a6cface5dd70aea0a08ac89d 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -7,6 +7,8 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; + import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; ++import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.server.level.WorldServer; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkCoordIntPair; +@@ -514,4 +516,19 @@ public final class MCUtil { + return null; + } + } ++ ++ @Nullable ++ public static IChatBaseComponent getBaseComponentFromNbt(String key, NBTTagCompound compound) { ++ if (!compound.hasKey(key)) { ++ return null; ++ } ++ String string = compound.getString(key); ++ try { ++ return IChatBaseComponent.ChatSerializer.jsonToComponent(string); ++ } catch (com.google.gson.JsonParseException e) { ++ org.bukkit.Bukkit.getLogger().warning("Unable to parse " + key + " from " + compound +": " + e.getMessage()); ++ } ++ ++ return null; ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java +index 94adf4d3b3a367e2a7fa383f1da6fb3b02b35c85..3fcdff3649c725580456dfc965d6c83bd5afe3da 100644 +--- a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java ++++ b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java +@@ -12,6 +12,7 @@ import net.minecraft.commands.ICommandListener; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.chat.ChatComponentText; + import net.minecraft.network.chat.IChatBaseComponent; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.util.UtilColor; +@@ -72,7 +73,7 @@ public abstract class CommandBlockListenerAbstract implements ICommandListener { + this.command = nbttagcompound.getString("Command"); + this.successCount = nbttagcompound.getInt("SuccessCount"); + if (nbttagcompound.hasKeyOfType("CustomName", 8)) { +- this.setName(IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName"))); ++ this.setName(MCUtil.getBaseComponentFromNbt("CustomName", nbttagcompound)); // Paper - Catch ParseException + } + + if (nbttagcompound.hasKeyOfType("TrackOutput", 1)) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java +index fd8d39d04f39ea8aa389deb66ca0ddaa3e282c40..45958ffedca64e08e347ae65033700c0d798beb5 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java +@@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagList; + import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; ++import net.minecraft.server.MCUtil; + import net.minecraft.world.INamableTileEntity; + import net.minecraft.world.item.EnumColor; + import net.minecraft.world.item.ItemStack; +@@ -70,7 +71,7 @@ public class TileEntityBanner extends TileEntity implements INamableTileEntity { + public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) { + super.load(iblockdata, nbttagcompound); + if (nbttagcompound.hasKeyOfType("CustomName", 8)) { +- this.a = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName")); ++ this.a = MCUtil.getBaseComponentFromNbt("CustomName", nbttagcompound); // Paper - Catch ParseException + } + + if (this.hasWorld()) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java +index 19739ad1fb01c767288da2667a48909e4c1c36cc..fb7a1a854efcf42f0351ef521aff67d5fcc4ab27 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java +@@ -4,6 +4,7 @@ import javax.annotation.Nullable; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.IChatBaseComponent; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.ChestLock; +@@ -30,7 +31,7 @@ public abstract class TileEntityContainer extends TileEntity implements IInvento + super.load(iblockdata, nbttagcompound); + this.chestLock = ChestLock.b(nbttagcompound); + if (nbttagcompound.hasKeyOfType("CustomName", 8)) { +- this.customName = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName")); ++ this.customName = MCUtil.getBaseComponentFromNbt("CustomName", nbttagcompound); // Paper - Catch ParseException + } + + } diff --git a/patches/server-unmapped/0290-Honor-EntityAgeable.ageLock.patch b/patches/server-unmapped/0290-Honor-EntityAgeable.ageLock.patch new file mode 100644 index 0000000000..e69ce43f71 --- /dev/null +++ b/patches/server-unmapped/0290-Honor-EntityAgeable.ageLock.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Sep 2018 20:59:53 -0500 +Subject: [PATCH] Honor EntityAgeable.ageLock + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityAgeable.java b/src/main/java/net/minecraft/world/entity/EntityAgeable.java +index ea356ff0f91083195899cc2bb84b2fde504163b4..850135582c41893823c43a78a016c7791755b8b5 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityAgeable.java ++++ b/src/main/java/net/minecraft/world/entity/EntityAgeable.java +@@ -82,6 +82,7 @@ public abstract class EntityAgeable extends EntityCreature { + } + + public void setAge(int i, boolean flag) { ++ if (ageLocked) return; // Paper - GH-1459 + int j = this.getAge(); + int k = j; + diff --git a/patches/server-unmapped/0291-Configurable-connection-throttle-kick-message.patch b/patches/server-unmapped/0291-Configurable-connection-throttle-kick-message.patch new file mode 100644 index 0000000000..4f33aeb255 --- /dev/null +++ b/patches/server-unmapped/0291-Configurable-connection-throttle-kick-message.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 2 Oct 2018 09:57:50 +0100 +Subject: [PATCH] Configurable connection throttle kick message + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 62621562137cba4804f0465c58d25ca2786328e5..7178b37f7978c7e9031a22726005c5099fd78fe0 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -281,6 +281,11 @@ public class PaperConfig { + authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); + } + ++ public static String connectionThrottleKickMessage = "Connection throttled! Please wait before reconnecting."; ++ private static void connectionThrottleKickMessage() { ++ connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); ++ } ++ + private static void savePlayerData() { + Object val = config.get("settings.save-player-data"); + if (val instanceof Boolean) { +diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java +index 93c67654bce188cd1eaf294abe7f765381ee0353..c4ba5c02c1be94bda2eb652415b48bf5a38400f6 100644 +--- a/src/main/java/net/minecraft/server/network/HandshakeListener.java ++++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java +@@ -50,7 +50,7 @@ public class HandshakeListener implements PacketHandshakingInListener { + synchronized (throttleTracker) { + if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { + throttleTracker.put(address, currentTime); +- ChatMessage chatmessage = new ChatMessage("Connection throttled! Please wait before reconnecting."); ++ ChatMessage chatmessage = new ChatMessage(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message + this.c.sendPacket(new PacketLoginOutDisconnect(chatmessage)); + this.c.close(chatmessage); + return; diff --git a/patches/server-unmapped/0292-Hook-into-CB-plugin-rewrites.patch b/patches/server-unmapped/0292-Hook-into-CB-plugin-rewrites.patch new file mode 100644 index 0000000000..06025aa8c5 --- /dev/null +++ b/patches/server-unmapped/0292-Hook-into-CB-plugin-rewrites.patch @@ -0,0 +1,184 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 3 Oct 2018 20:09:18 -0400 +Subject: [PATCH] Hook into CB plugin rewrites + +Allows us to do fun stuff like rewrite the OBC util fastutil location to +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 45cbdcfc131bbc0e2bf23cc30a572df72eecd51c..49e5a86c223f1b28ce7da6ced276b2f880777856 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java +@@ -6,7 +6,9 @@ import java.io.FileOutputStream; + import java.io.InputStream; + import java.util.Arrays; + import java.util.Enumeration; ++import java.util.HashMap; + import java.util.HashSet; ++import java.util.Map; + import java.util.Set; + import java.util.jar.JarEntry; + import java.util.jar.JarFile; +@@ -20,10 +22,15 @@ import org.bukkit.plugin.AuthorNagException; + import org.objectweb.asm.ClassReader; + import org.objectweb.asm.ClassVisitor; + import org.objectweb.asm.ClassWriter; ++import org.objectweb.asm.FieldVisitor; ++import org.objectweb.asm.Handle; ++import org.objectweb.asm.Label; + import org.objectweb.asm.MethodVisitor; + import org.objectweb.asm.Opcodes; + import org.objectweb.asm.Type; + ++import javax.annotation.Nonnull; ++ + /** + * This file is imported from Commodore. + * +@@ -46,6 +53,42 @@ public class Commodore + "org/bukkit/inventory/ItemStack (I)V setTypeId" + ) ); + ++ // Paper start - Plugin rewrites ++ private static final Map SEARCH_AND_REMOVE = initReplacementsMap(); ++ private static Map initReplacementsMap() ++ { ++ Map getAndRemove = new HashMap<>(); ++ // Be wary of maven shade's relocations ++ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/libs/it/unimi/dsi/fastutil/" ), "org/bukkit/".concat( "craftbukkit/libs/" ) ); // Remap fastutil to our location ++ ++ if ( Boolean.getBoolean( "debug.rewriteForIde" ) ) ++ { ++ // unversion incoming calls for pre-relocate debug work ++ final String NMS_REVISION_PACKAGE = "v1_16_R3/"; ++ ++ getAndRemove.put( "net/minecraft/".concat( "server/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); ++ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); ++ } ++ ++ return getAndRemove; ++ } ++ ++ @Nonnull ++ private static String getOriginalOrRewrite(@Nonnull String original) ++ { ++ String rewrite = null; ++ for ( Map.Entry entry : SEARCH_AND_REMOVE.entrySet() ) ++ { ++ if ( original.contains( entry.getKey() ) ) ++ { ++ rewrite = original.replace( entry.getValue(), "" ); ++ } ++ } ++ ++ return rewrite != null ? rewrite : original; ++ } ++ // Paper end ++ + public static void main(String[] args) + { + OptionParser parser = new OptionParser(); +@@ -130,15 +173,86 @@ public class Commodore + + cr.accept( new ClassVisitor( Opcodes.ASM9, cw ) + { ++ // Paper start - Rewrite plugins ++ @Override ++ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) ++ { ++ desc = getOriginalOrRewrite( desc ); ++ if ( signature != null ) { ++ signature = getOriginalOrRewrite( signature ); ++ } ++ ++ return super.visitField( access, name, desc, signature, value) ; ++ } ++ // Paper end ++ + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) + { + return new MethodVisitor( api, super.visitMethod( access, name, desc, signature, exceptions ) ) + { ++ // Paper start - Plugin rewrites ++ @Override ++ public void visitInvokeDynamicInsn(String name, String desc, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) ++ { ++ // Paper start - Rewrite plugins ++ name = getOriginalOrRewrite( name ); ++ if ( desc != null ) ++ { ++ desc = getOriginalOrRewrite( desc ); ++ } ++ // Paper end ++ ++ super.visitInvokeDynamicInsn( name, desc, bootstrapMethodHandle, bootstrapMethodArguments ); ++ } ++ ++ @Override ++ public void visitTypeInsn(int opcode, String type) ++ { ++ type = getOriginalOrRewrite( type ); ++ ++ super.visitTypeInsn( opcode, type ); ++ } ++ ++ @Override ++ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { ++ for ( int i = 0; i < local.length; i++ ) ++ { ++ if ( !( local[i] instanceof String ) ) { continue; } ++ ++ local[i] = getOriginalOrRewrite( (String) local[i] ); ++ } ++ ++ for ( int i = 0; i < stack.length; i++ ) ++ { ++ if ( !( stack[i] instanceof String ) ) { continue; } ++ ++ stack[i] = getOriginalOrRewrite( (String) stack[i] ); ++ } ++ ++ super.visitFrame( type, nLocal, local, nStack, stack ); ++ } ++ ++ @Override ++ public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) ++ { ++ descriptor = getOriginalOrRewrite( descriptor ); ++ ++ super.visitLocalVariable( name, descriptor, signature, start, end, index ); ++ } ++ // Paper end + + @Override + public void visitFieldInsn(int opcode, String owner, String name, String desc) + { ++ // Paper start - Rewrite plugins ++ owner = getOriginalOrRewrite( owner ); ++ if ( desc != null ) ++ { ++ desc = getOriginalOrRewrite( desc ); ++ } ++ // Paper end ++ + if ( owner.equals( "org/bukkit/block/Biome" ) ) + { + switch ( name ) +@@ -270,6 +384,14 @@ public class Commodore + return; + } + ++ // Paper start - Rewrite plugins ++ owner = getOriginalOrRewrite( owner) ; ++ if (desc != null) ++ { ++ desc = getOriginalOrRewrite(desc); ++ } ++ // Paper end ++ + if ( modern ) + { + if ( owner.equals( "org/bukkit/Material" ) ) diff --git a/patches/server-unmapped/0293-Allow-setting-the-vex-s-summoner.patch b/patches/server-unmapped/0293-Allow-setting-the-vex-s-summoner.patch new file mode 100644 index 0000000000..d97a31a735 --- /dev/null +++ b/patches/server-unmapped/0293-Allow-setting-the-vex-s-summoner.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 6 Oct 2018 21:47:44 -0500 +Subject: [PATCH] Allow setting the vex's summoner + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java +index 3b74ade60b3b0ae0e908866cb4ac11acd75620ff..9645d052069957311478a1ceca42ad52f7a9aa0b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java +@@ -165,6 +165,7 @@ public class EntityVex extends EntityMonster { + this.a(1, flag); + } + ++ public void setOwner(EntityInsentient entityinsentient) { a(entityinsentient); } // Paper - OBFHELPER + public void a(EntityInsentient entityinsentient) { + this.c = entityinsentient; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +index 962d6017f6acc47ebe4b754ccd9b97a1fc97cc58..30e2c169388b09b94d801be7543e75ea0bd56fcd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +@@ -21,6 +21,10 @@ public class CraftVex extends CraftMonster implements Vex { + net.minecraft.world.entity.EntityInsentient owner = getHandle().getOwner(); + return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; + } ++ ++ public void setSummoner(org.bukkit.entity.Mob summoner) { ++ getHandle().setOwner(summoner == null ? null : ((CraftMob) summoner).getHandle()); ++ } + // Paper end + + @Override diff --git a/patches/server-unmapped/0294-Add-sun-related-API.patch b/patches/server-unmapped/0294-Add-sun-related-API.patch new file mode 100644 index 0000000000..7d5adc05ed --- /dev/null +++ b/patches/server-unmapped/0294-Add-sun-related-API.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 7 Oct 2018 00:54:21 -0500 +Subject: [PATCH] Add sun related API + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index e177483dace853ccd01d410fc7deea17663e9a3d..0489fb4869c9a0b56df6f44ef3925de7651baef2 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -1597,6 +1597,7 @@ public abstract class EntityInsentient extends EntityLiving { + + } + ++ public boolean isInDaylight() { return this.eG(); } // Paper - OBFHELPER + protected boolean eG() { + if (this.world.isDay() && !this.world.isClientSide) { + float f = this.aR(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 880bbf09f77f59824184c1c9dd1ca3c3df09dae9..95b4774b7696fa9711d7169d06a23c70364bfdb2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -865,6 +865,13 @@ public class CraftWorld implements World { + } + } + ++ // Paper start ++ @Override ++ public boolean isDayTime() { ++ return getHandle().isDay(); ++ } ++ // Paper end ++ + @Override + public long getGameTime() { + return world.worldData.getTime(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +index 28a4e90130f51fd2fda7003fde5b4d0a410e1aef..06cbe63ef04e0de824ac0b9d545b6da1f53701b3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +@@ -78,4 +78,11 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { + public long getSeed() { + return getHandle().lootTableSeed; + } ++ ++ // Paper start ++ @Override ++ public boolean isInDaylight() { ++ return getHandle().isInDaylight(); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0295-Turtle-API.patch b/patches/server-unmapped/0295-Turtle-API.patch new file mode 100644 index 0000000000..5d55bbc3f4 --- /dev/null +++ b/patches/server-unmapped/0295-Turtle-API.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 29 Sep 2018 16:08:23 -0500 +Subject: [PATCH] Turtle API + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java +index 62276550627bfe453794a2b3101426fe05a585ff..6a156a488bc073b3b60f4d1081e3f2ab65ba9e96 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java +@@ -14,7 +14,7 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { + protected int c; + protected int d; + private int g; +- protected BlockPosition e; ++ protected BlockPosition e;public final BlockPosition getTargetPosition() { return this.e; } // Paper - OBFHELPER + private boolean h; + private final int i; + private final int j; +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java +index bf224c97854daa379c61affff6a0ac9524c2c35d..09a6310af6712d36c20167256b60dc3235e76021 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java +@@ -14,6 +14,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundCategory; +@@ -93,7 +94,7 @@ public class EntityTurtle extends EntityAnimal { + this.datawatcher.set(EntityTurtle.bp, blockposition); + } + +- private BlockPosition getHomePos() { ++ public BlockPosition getHomePos() { // Paper - public + return (BlockPosition) this.datawatcher.get(EntityTurtle.bp); + } + +@@ -109,31 +110,37 @@ public class EntityTurtle extends EntityAnimal { + return (Boolean) this.datawatcher.get(EntityTurtle.bq); + } + +- private void setHasEgg(boolean flag) { ++ public void setHasEgg(boolean flag) { // Paper + this.datawatcher.set(EntityTurtle.bq, flag); + } + ++ public final boolean isDigging() { return this.eL(); } // Paper - OBFHELPER + public boolean eL() { + return (Boolean) this.datawatcher.get(EntityTurtle.br); + } + ++ public final void setDigging(boolean digging) { this.u(digging); } // Paper - OBFHELPER + private void u(boolean flag) { + this.bv = flag ? 1 : 0; + this.datawatcher.set(EntityTurtle.br, flag); + } + ++ public final boolean isGoingHome() { return this.eU(); } // Paper - OBFHELPER + private boolean eU() { + return (Boolean) this.datawatcher.get(EntityTurtle.bt); + } + ++ public final void setGoingHome(boolean goingHome) { this.v(goingHome); } // Paper - OBFHELPER + private void v(boolean flag) { + this.datawatcher.set(EntityTurtle.bt, flag); + } + ++ public final boolean isTravelling() { return this.eV(); } // Paper - OBFHELPER + private boolean eV() { + return (Boolean) this.datawatcher.get(EntityTurtle.bu); + } + ++ public final void setTravelling(boolean travelling) { this.w(travelling); } // Paper - OBFHELPER + private void w(boolean flag) { + this.datawatcher.set(EntityTurtle.bu, flag); + } +@@ -500,14 +507,17 @@ public class EntityTurtle extends EntityAnimal { + + if (!this.g.isInWater() && this.l()) { + if (this.g.bv < 1) { +- this.g.u(true); ++ this.g.setDigging(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.g.getBukkitEntity(), MCUtil.toLocation(this.g.world, this.getTargetPosition())).callEvent()); // Paper + } else if (this.g.bv > 200) { + World world = this.g.world; + + // CraftBukkit start +- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.g, this.e.up(), (IBlockData) Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, this.g.random.nextInt(4) + 1)).isCancelled()) { ++ // Paper start ++ int eggCount = this.g.random.nextInt(4) + 1; ++ com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.g.getBukkitEntity(), MCUtil.toLocation(this.g.world, this.e.up()), eggCount); ++ if (layEggEvent.callEvent() && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.g, this.e.up(), Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, layEggEvent.getEggCount())).isCancelled()) { + world.playSound((EntityHuman) null, blockposition, SoundEffects.ENTITY_TURTLE_LAY_EGG, SoundCategory.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); +- world.setTypeAndData(this.e.up(), (IBlockData) Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, this.g.random.nextInt(4) + 1), 3); ++ world.setTypeAndData(this.e.up(), (IBlockData) Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, layEggEvent.getEggCount()), 3); + } + // CraftBukkit end + this.g.setHasEgg(false); +@@ -636,7 +646,7 @@ public class EntityTurtle extends EntityAnimal { + + @Override + public boolean a() { +- return this.a.isBaby() ? false : (this.a.hasEgg() ? true : (this.a.getRandom().nextInt(700) != 0 ? false : !this.a.getHomePos().a((IPosition) this.a.getPositionVector(), 64.0D))); ++ return this.a.isBaby() ? false : (this.a.hasEgg() ? true : (this.a.getRandom().nextInt(700) != 0 ? false : !this.a.getHomePos().a((IPosition) this.a.getPositionVector(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.a.getBukkitEntity()).callEvent(); // Paper + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java +index b46bb75926c14ab54ea309a400eb57405b11ce27..31f1a6b2b9a432cdd25826ced884424eeb50df97 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java +@@ -25,4 +25,36 @@ public class CraftTurtle extends CraftAnimals implements Turtle { + public EntityType getType() { + return EntityType.TURTLE; + } ++ ++ // Paper start ++ @Override ++ public org.bukkit.Location getHome() { ++ return net.minecraft.server.MCUtil.toLocation(getHandle().world, getHandle().getHomePos()); ++ } ++ ++ @Override ++ public void setHome(org.bukkit.Location location) { ++ getHandle().setHomePos(net.minecraft.server.MCUtil.toBlockPosition(location)); ++ } ++ ++ @Override ++ public boolean isGoingHome() { ++ return getHandle().isGoingHome(); ++ } ++ ++ @Override ++ public boolean isDigging() { ++ return getHandle().isDigging(); ++ } ++ ++ @Override ++ public boolean hasEgg() { ++ return getHandle().hasEgg(); ++ } ++ ++ @Override ++ public void setHasEgg(boolean hasEgg) { ++ getHandle().setHasEgg(hasEgg); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/patches/server-unmapped/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch new file mode 100644 index 0000000000..ab9d26a523 --- /dev/null +++ b/patches/server-unmapped/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 17 Oct 2018 19:17:27 -0400 +Subject: [PATCH] MC-50319: Check other worlds for shooter of projectiles + +Say a player shoots an arrow through a nether portal, the game +would lose the shooter for determining things such as Player Kills, +because the entity is in another world. + +If the projectile fails to find the shooter in the current world, check +other worlds. + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +index b44b18341331e5176e0f1851aa60cc425ccbd439..29834a3613c7701d46e879d170779eb7e6f664e1 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +@@ -45,7 +45,18 @@ public abstract class IProjectile extends Entity { + + @Nullable + public Entity getShooter() { +- return this.shooter != null && this.world instanceof WorldServer ? ((WorldServer) this.world).getEntity(this.shooter) : (this.c != 0 ? this.world.getEntity(this.c) : null); ++ // Paper start - MC-50319 - shooter might be in another world (arrows through portals) ++ Entity entity = this.shooter != null && this.world instanceof WorldServer ? ((WorldServer) this.world).getEntity(this.shooter) : (this.c != 0 ? this.world.getEntity(this.c) : null); ++ if (entity == null) { ++ for (WorldServer world : world.getMinecraftServer().getWorlds()) { ++ entity = world.getEntity(this.shooter); ++ if (entity != null) { ++ break; ++ } ++ } ++ } ++ return entity; ++ // Paper end + } + + @Override diff --git a/patches/server-unmapped/0297-Call-player-spectator-target-events-and-improve-impl.patch b/patches/server-unmapped/0297-Call-player-spectator-target-events-and-improve-impl.patch new file mode 100644 index 0000000000..7a0ba42f33 --- /dev/null +++ b/patches/server-unmapped/0297-Call-player-spectator-target-events-and-improve-impl.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Caleb Bassham +Date: Fri, 28 Sep 2018 02:32:19 -0500 +Subject: [PATCH] Call player spectator target events and improve + implementation + +Use a proper teleport for teleporting to entities in different +worlds. + +Implementation improvements authored by Spottedleaf +Validate that the target entity is valid and deny spectate +requests from frozen players. + +Also, make sure the entity is spawned to the client before +sending the camera packet. If the entity isn't spawned clientside +when it receives the camera packet, then the client will not +spectate the target entity. + +Co-authored-by: Spottedleaf + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index ae9e0f55ddc194aaef1e57e81863569d9bc7b8f3..f5be9554e1fd01a35b926196b30fd64f1567a799 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1820,15 +1820,59 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + return (Entity) (this.spectatedEntity == null ? this : this.spectatedEntity); + } + +- public void setSpectatorTarget(Entity entity) { ++ public void setSpectatorTarget(Entity newSpectatorTarget) { ++ // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event and improve implementation + Entity entity1 = this.getSpecatorTarget(); + +- this.spectatedEntity = (Entity) (entity == null ? this : entity); +- if (entity1 != this.spectatedEntity) { +- this.playerConnection.sendPacket(new PacketPlayOutCamera(this.spectatedEntity)); +- this.playerConnection.a(this.spectatedEntity.locX(), this.spectatedEntity.locY(), this.spectatedEntity.locZ(), this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit ++ if (newSpectatorTarget == null) { ++ newSpectatorTarget = this; + } + ++ if (entity1 == newSpectatorTarget) return; // new spec target is the current spec target ++ ++ if (newSpectatorTarget == this) { ++ com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent playerStopSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity()); ++ ++ if (!playerStopSpectatingEntityEvent.callEvent()) { ++ return; ++ } ++ } else { ++ com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent playerStartSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity(), newSpectatorTarget.getBukkitEntity()); ++ ++ if (!playerStartSpectatingEntityEvent.callEvent()) { ++ return; ++ } ++ } ++ // Validate ++ if (newSpectatorTarget != this) { ++ if (newSpectatorTarget.dead || newSpectatorTarget.shouldBeRemoved || !newSpectatorTarget.valid || newSpectatorTarget.world == null) { ++ MinecraftServer.LOGGER.info("Blocking player " + this.toString() + " from spectating invalid entity " + newSpectatorTarget.toString()); ++ return; ++ } ++ if (this.isFrozen()) { ++ // use debug: clients might maliciously spam this ++ MinecraftServer.LOGGER.debug("Blocking frozen player " + this.toString() + " from spectating entity " + newSpectatorTarget.toString()); ++ return; ++ } ++ } ++ ++ this.spectatedEntity = newSpectatorTarget; // only set after validating state ++ ++ if (newSpectatorTarget != this) { ++ // Make sure we're in the right place ++ this.ejectPassengers(); // teleport can fail if we have passengers... ++ this.getBukkitEntity().teleport(new Location(newSpectatorTarget.getWorld().getWorld(), newSpectatorTarget.locX(), newSpectatorTarget.locY(), newSpectatorTarget.locZ(), this.yaw, this.pitch), TeleportCause.SPECTATE); // Correctly handle cross-world entities from api calls by using CB teleport ++ ++ // Make sure we're tracking the entity before sending ++ PlayerChunkMap.EntityTracker tracker = ((WorldServer)newSpectatorTarget.world).getChunkProvider().playerChunkMap.trackedEntities.get(newSpectatorTarget.getId()); ++ if (tracker != null) { // dumb plugins... ++ tracker.updatePlayer(this); ++ } ++ } else { ++ this.playerConnection.teleport(this.spectatedEntity.locX(), this.spectatedEntity.locY(), this.spectatedEntity.locZ(), this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit ++ } ++ this.playerConnection.sendPacket(new PacketPlayOutCamera(newSpectatorTarget)); ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index b9825537599a8df8d772b2db4d56d5e28cc2bbe9..9a5f510d3a43df40934efb56d24956dee2c62380 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1355,6 +1355,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + + // CraftBukkit start - Delegate to teleport(Location) ++ public final void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { this.a(d0, d1, d2, f, f1, cause); } // Paper - OBFHELPER + public void a(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { + this.a(d0, d1, d2, f, f1, Collections.emptySet(), cause); + } diff --git a/patches/server-unmapped/0298-Add-Velocity-IP-Forwarding-Support.patch b/patches/server-unmapped/0298-Add-Velocity-IP-Forwarding-Support.patch new file mode 100644 index 0000000000..d09f71796d --- /dev/null +++ b/patches/server-unmapped/0298-Add-Velocity-IP-Forwarding-Support.patch @@ -0,0 +1,307 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Mon, 8 Oct 2018 14:36:14 -0400 +Subject: [PATCH] Add Velocity IP Forwarding Support + +While Velocity supports BungeeCord-style IP forwarding, it is not secure. Users +have a lot of problems setting up firewalls or setting up plugins like IPWhitelist. +Further, the BungeeCord IP forwarding protocol still retains essentially its original +form, when there is brand new support for custom login plugin messages in 1.13. + +Velocity's modern IP forwarding uses an HMAC-SHA256 code to ensure authenticity +of messages, is packed into a binary format that is smaller than BungeeCord's +forwarding, and is integrated into the Minecraft login process by using the 1.13 +login plugin message packet. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 7178b37f7978c7e9031a22726005c5099fd78fe0..3139c194f9b1bc3510d51a81f13ae43d00a3dc29 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -8,6 +8,7 @@ import java.io.IOException; + import java.lang.reflect.InvocationTargetException; + import java.lang.reflect.Method; + import java.lang.reflect.Modifier; ++import java.nio.charset.StandardCharsets; + import java.util.HashMap; + import java.util.List; + import java.util.Map; +@@ -252,7 +253,7 @@ public class PaperConfig { + } + + public static boolean isProxyOnlineMode() { +- return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); ++ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode) || (velocitySupport && velocityOnlineMode); + } + + public static int packetInSpamThreshold = 300; +@@ -324,4 +325,18 @@ public class PaperConfig { + } + tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); + } ++ ++ public static boolean velocitySupport; ++ public static boolean velocityOnlineMode; ++ public static byte[] velocitySecretKey; ++ private static void velocitySupport() { ++ velocitySupport = getBoolean("settings.velocity-support.enabled", false); ++ velocityOnlineMode = getBoolean("settings.velocity-support.online-mode", false); ++ String secret = getString("settings.velocity-support.secret", ""); ++ if (velocitySupport && secret.isEmpty()) { ++ fatal("Velocity support is enabled, but no secret key was specified. A secret key is required!"); ++ } else { ++ velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e6afaa41df086b1eb3950ce870c91dd5bf5a663b +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java +@@ -0,0 +1,67 @@ ++package com.destroystokyo.paper.proxy; ++ ++import com.destroystokyo.paper.PaperConfig; ++import com.google.common.net.InetAddresses; ++import com.mojang.authlib.GameProfile; ++import com.mojang.authlib.properties.Property; ++import net.minecraft.network.PacketDataSerializer; ++import net.minecraft.resources.MinecraftKey; ++ ++import java.net.InetAddress; ++import java.security.InvalidKeyException; ++import java.security.MessageDigest; ++import java.security.NoSuchAlgorithmException; ++ ++import javax.crypto.Mac; ++import javax.crypto.spec.SecretKeySpec; ++ ++public class VelocityProxy { ++ private static final int SUPPORTED_FORWARDING_VERSION = 1; ++ public static final MinecraftKey PLAYER_INFO_CHANNEL = new MinecraftKey("velocity", "player_info"); ++ ++ public static boolean checkIntegrity(final PacketDataSerializer buf) { ++ final byte[] signature = new byte[32]; ++ buf.readBytes(signature); ++ ++ final byte[] data = new byte[buf.readableBytes()]; ++ buf.getBytes(buf.readerIndex(), data); ++ ++ try { ++ final Mac mac = Mac.getInstance("HmacSHA256"); ++ mac.init(new SecretKeySpec(PaperConfig.velocitySecretKey, "HmacSHA256")); ++ final byte[] mySignature = mac.doFinal(data); ++ if (!MessageDigest.isEqual(signature, mySignature)) { ++ return false; ++ } ++ } catch (final InvalidKeyException | NoSuchAlgorithmException e) { ++ throw new AssertionError(e); ++ } ++ ++ int version = buf.readVarInt(); ++ if (version != SUPPORTED_FORWARDING_VERSION) { ++ throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted " + SUPPORTED_FORWARDING_VERSION); ++ } ++ ++ return true; ++ } ++ ++ public static InetAddress readAddress(final PacketDataSerializer buf) { ++ return InetAddresses.forString(buf.readUTF(Short.MAX_VALUE)); ++ } ++ ++ public static GameProfile createProfile(final PacketDataSerializer buf) { ++ final GameProfile profile = new GameProfile(buf.readUUID(), buf.readUTF(16)); ++ readProperties(buf, profile); ++ return profile; ++ } ++ ++ private static void readProperties(final PacketDataSerializer buf, final GameProfile profile) { ++ final int properties = buf.readVarInt(); ++ for (int i1 = 0; i1 < properties; i1++) { ++ final String name = buf.readUTF(Short.MAX_VALUE); ++ final String value = buf.readUTF(Short.MAX_VALUE); ++ final String signature = buf.readBoolean() ? buf.readUTF(Short.MAX_VALUE) : null; ++ profile.getProperties().put(name, new Property(name, value, signature)); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java +index 5a1187b001004afe22d208bc5d7c288e796e16a6..579eb1260c7266cd41025cff177de4fb00ac0cec 100644 +--- a/src/main/java/net/minecraft/network/PacketDataSerializer.java ++++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java +@@ -192,6 +192,7 @@ public class PacketDataSerializer extends ByteBuf { + return this.d(oenum.ordinal()); + } + ++ public int readVarInt() { return i(); } // Paper - OBFHELPER + public int i() { + int i = 0; + int j = 0; +@@ -232,6 +233,7 @@ public class PacketDataSerializer extends ByteBuf { + return this; + } + ++ public UUID readUUID() { return k(); } // Paper - OBFHELPER + public UUID k() { + return new UUID(this.readLong(), this.readLong()); + } +@@ -359,6 +361,7 @@ public class PacketDataSerializer extends ByteBuf { + } + } + ++ public String readUTF(int maxLength) { return this.e(maxLength); } // Paper - OBFHELPER + public String e(int i) { + int j = this.i(); + +diff --git a/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java b/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java +index c1bac2d07e5107c1346f246f5d5d929c73912bfd..c47c2d774a1990ad5007bbdc7bd3a81b3f3817e3 100644 +--- a/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java ++++ b/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java +@@ -6,8 +6,8 @@ import net.minecraft.network.protocol.Packet; + + public class PacketLoginInCustomPayload implements Packet { + +- private int a; +- private PacketDataSerializer b; ++ private int a; public int getId() { return a; } // Paper - OBFHELPER ++ private PacketDataSerializer b; public PacketDataSerializer getBuf() { return b; } // Paper - OBFHELPER + + public PacketLoginInCustomPayload() {} + +diff --git a/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java b/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java +index eb970c1e954cb0aa83aa12e83c471778809e69b2..2d8c917509f10a96fc82404908b452cb385c7c60 100644 +--- a/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java ++++ b/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java +@@ -13,6 +13,14 @@ public class PacketLoginOutCustomPayload implements Packet { ++ try { ++ new LoginHandler().fireEvents(); ++ } catch (Exception ex) { ++ disconnect("Failed to verify username!"); ++ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + i.getName(), ex); ++ } ++ }); ++ return; ++ } ++ // Paper end + this.disconnect(new ChatMessage("multiplayer.disconnect.unexpected_query_response")); + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index ba982907b97faace89b73365aef1c91dab692ff1..22f9d8c0189293b88353bbe1bcc40dd1d431d458 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -681,7 +681,7 @@ public final class CraftServer implements Server { + @Override + public long getConnectionThrottle() { + // Spigot Start - Automatically set connection throttle for bungee configurations +- if (org.spigotmc.SpigotConfig.bungee) { ++ if (org.spigotmc.SpigotConfig.bungee || com.destroystokyo.paper.PaperConfig.velocitySupport) { // Paper - Velocity support + return -1; + } else { + return this.configuration.getInt("settings.connection-throttle"); diff --git a/patches/server-unmapped/0299-Add-more-Witch-API.patch b/patches/server-unmapped/0299-Add-more-Witch-API.patch new file mode 100644 index 0000000000..fe9e372e32 --- /dev/null +++ b/patches/server-unmapped/0299-Add-more-Witch-API.patch @@ -0,0 +1,153 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 12 Oct 2018 14:10:46 -0500 +Subject: [PATCH] Add more Witch API + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java +index c6d79125e7dd982fc528ce61144005194cbaa323..63fb08e7b4290353e5148d1acb58f091dc5b08be 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java +@@ -1,5 +1,11 @@ + package net.minecraft.world.entity.monster; + ++// Paper start ++import com.destroystokyo.paper.event.entity.WitchReadyPotionEvent; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.Witch; ++// Paper end ++ + import java.util.Iterator; + import java.util.List; + import java.util.UUID; +@@ -49,7 +55,7 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { + private static final UUID b = UUID.fromString("5CD17E52-A79A-43D3-A529-90FDE04B181E"); + private static final AttributeModifier bo = new AttributeModifier(EntityWitch.b, "Drinking speed penalty", -0.25D, AttributeModifier.Operation.ADDITION); + private static final DataWatcherObject bp = DataWatcher.a(EntityWitch.class, DataWatcherRegistry.i); +- private int bq; ++ private int bq; public int getPotionUseTimeLeft() { return bq; } public void setPotionUseTimeLeft(int timeLeft) { bq = timeLeft; } // Paper - OBFHELPER + private PathfinderGoalNearestHealableRaider br; + private PathfinderGoalNearestAttackableTargetWitch bs; + +@@ -95,10 +101,12 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { + return SoundEffects.ENTITY_WITCH_DEATH; + } + ++ public void setDrinkingPotion(boolean drinkingPotion) { v(drinkingPotion); } // Paper - OBFHELPER + public void v(boolean flag) { + this.getDataWatcher().set(EntityWitch.bp, flag); + } + ++ public boolean isDrinkingPotion() { return m(); } // Paper - OBFHELPER + public boolean m() { + return (Boolean) this.getDataWatcher().get(EntityWitch.bp); + } +@@ -157,21 +165,24 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { + } + + if (potionregistry != null) { +- // Paper start + ItemStack potion = PotionUtil.a(new ItemStack(Items.POTION), potionregistry); +- org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); +- this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++ // Paper start - logic moved into setDrinkingPotion, copy exact impl into the method and then comment out ++ this.setDrinkingPotion(potion); ++// org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++// this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++// // Paper end ++// this.bq = this.getItemInMainHand().k(); ++// this.v(true); ++// if (!this.isSilent()) { ++// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); ++// } ++// ++// AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); ++// ++// attributemodifiable.removeModifier(EntityWitch.bo); ++// attributemodifiable.b(EntityWitch.bo); + // Paper end +- this.bq = this.getItemInMainHand().k(); +- this.v(true); +- if (!this.isSilent()) { +- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); +- } + +- AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); +- +- attributemodifiable.removeModifier(EntityWitch.bo); +- attributemodifiable.b(EntityWitch.bo); + } + } + +@@ -183,6 +194,24 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { + super.movementTick(); + } + ++ // Paper start - moved to its own method ++ public void setDrinkingPotion(ItemStack potion) { ++ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++ this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++ // Paper end ++ this.bq = this.getItemInMainHand().k(); ++ this.v(true); ++ if (!this.isSilent()) { ++ this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); ++ } ++ ++ AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); ++ ++ attributemodifiable.removeModifier(EntityWitch.bo); ++ attributemodifiable.b(EntityWitch.bo); ++ } ++ // Paper end ++ + @Override + public SoundEffect eL() { + return SoundEffects.ENTITY_WITCH_CELEBRATE; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +index 9cc34cdb43596eff34625045f884b93da3f27ab6..3b553c2455948a4102754b2617c2301c49f476d6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +@@ -4,6 +4,13 @@ import net.minecraft.world.entity.monster.EntityWitch; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.Witch; ++// Paper start ++import com.destroystokyo.paper.entity.CraftRangedEntity; ++import com.google.common.base.Preconditions; ++import org.bukkit.Material; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.inventory.ItemStack; ++// Paper end + + public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftWitch(CraftServer server, EntityWitch entity) { +@@ -24,4 +31,28 @@ public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo. + public EntityType getType() { + return EntityType.WITCH; + } ++ ++ // Paper start ++ public boolean isDrinkingPotion() { ++ return getHandle().isDrinkingPotion(); ++ } ++ ++ public int getPotionUseTimeLeft() { ++ return getHandle().getPotionUseTimeLeft(); ++ } ++ ++ @Override ++ public void setPotionUseTimeLeft(int ticks) { ++ getHandle().setPotionUseTimeLeft(ticks); ++ } ++ ++ public ItemStack getDrinkingPotion() { ++ return CraftItemStack.asCraftMirror(getHandle().getItemInMainHand()); ++ } ++ ++ public void setDrinkingPotion(ItemStack potion) { ++ Preconditions.checkArgument(potion == null || potion.getType().isEmpty() || potion.getType() == Material.POTION, "must be potion, air, or null"); ++ getHandle().setDrinkingPotion(CraftItemStack.asNMSCopy(potion)); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0300-Check-Drowned-for-Villager-Aggression-Config.patch b/patches/server-unmapped/0300-Check-Drowned-for-Villager-Aggression-Config.patch new file mode 100644 index 0000000000..efb266e1a5 --- /dev/null +++ b/patches/server-unmapped/0300-Check-Drowned-for-Villager-Aggression-Config.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Wed, 10 Oct 2018 21:22:44 -0500 +Subject: [PATCH] Check Drowned for Villager Aggression Config + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java +index c3457fc7c0f72af79b12dc50c270ca24b7590c22..e4794760fc918cccbdc3f8d10ab21dd9b6f29e8e 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java +@@ -82,7 +82,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { + this.goalSelector.a(7, new PathfinderGoalRandomStroll(this, 1.0D)); + this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityDrowned.class})).a(EntityPigZombie.class)); + this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::i)); +- this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)); ++ if ( world.spigotConfig.zombieAggressiveTowardsVillager ) this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)); // Paper + this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, true)); + this.targetSelector.a(5, new PathfinderGoalNearestAttackableTarget<>(this, EntityTurtle.class, 10, true, false, EntityTurtle.bo)); + } diff --git a/patches/server-unmapped/0301-Here-s-Johnny.patch b/patches/server-unmapped/0301-Here-s-Johnny.patch new file mode 100644 index 0000000000..b9a50189c2 --- /dev/null +++ b/patches/server-unmapped/0301-Here-s-Johnny.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 12 Oct 2018 01:37:22 -0500 +Subject: [PATCH] Here's Johnny! + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java +index c181d5f5e6108ade54fc97c665897d1db5e90719..c45dcb56af95f3e87e292b92b697a336461f01bc 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java +@@ -51,7 +51,7 @@ public class EntityVindicator extends EntityIllagerAbstract { + private static final Predicate b = (enumdifficulty) -> { + return enumdifficulty == EnumDifficulty.NORMAL || enumdifficulty == EnumDifficulty.HARD; + }; +- private boolean bo; ++ private boolean bo; public boolean isJohnny() { return bo; } public void setJohnny(boolean johnny) { bo = johnny; } // Paper - OBFHELPER + + public EntityVindicator(EntityTypes entitytypes, World world) { + super(entitytypes, world); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java +index e793820e1ede4bd4d31e6fe12ca8189707674ffe..b128e8291f2d7652a98f1271d763e33afa5de9f7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java +@@ -25,4 +25,14 @@ public class CraftVindicator extends CraftIllager implements Vindicator { + public EntityType getType() { + return EntityType.VINDICATOR; + } ++ ++ // Paper start ++ public boolean isJohnny() { ++ return getHandle().isJohnny(); ++ } ++ ++ public void setJohnny(boolean johnny) { ++ getHandle().setJohnny(johnny); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch b/patches/server-unmapped/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch new file mode 100644 index 0000000000..aa55d56895 --- /dev/null +++ b/patches/server-unmapped/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gabriele C +Date: Mon, 22 Oct 2018 17:34:10 +0200 +Subject: [PATCH] Add option to prevent players from moving into unloaded + chunks #1551 + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index f280dbff4a09bc611a9ca565c6d697d08801f53b..fbf3ccfb347a5ba6e895339e9576629d940d1aa4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -396,4 +396,9 @@ public class PaperWorldConfig { + waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); + log("Water over lava flow speed: " + waterOverLavaFlowSpeed); + } ++ ++ public boolean preventMovingIntoUnloadedChunks = false; ++ private void preventMovingIntoUnloadedChunks() { ++ preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 9a5f510d3a43df40934efb56d24956dee2c62380..f48683ef9afe3e5d0e0e5959c698152e9086632b 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -543,6 +543,13 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + speed *= 2f; // TODO: Get the speed of the vehicle instead of the player + ++ // Paper start - Prevent moving into unloaded chunks ++ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && worldserver.getChunkIfLoadedImmediately((int) Math.floor(packetplayinvehiclemove.getX()) >> 4, (int) Math.floor(packetplayinvehiclemove.getZ()) >> 4) == null) { ++ this.networkManager.sendPacket(new PacketPlayOutVehicleMove(entity)); ++ return; ++ } ++ // Paper end ++ + if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isExemptPlayer()) { + // CraftBukkit end + PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getDisplayName().getString(), this.player.getDisplayName().getString(), d6, d7, d8); +@@ -1141,9 +1148,9 @@ public class PlayerConnection implements PacketListenerPlayIn { + double d1 = this.player.locY(); + double d2 = this.player.locZ(); + double d3 = this.player.locY(); +- double d4 = packetplayinflying.a(this.player.locX()); ++ double d4 = packetplayinflying.a(this.player.locX());double toX = d4; // Paper - OBFHELPER + double d5 = packetplayinflying.b(this.player.locY()); +- double d6 = packetplayinflying.c(this.player.locZ()); ++ double d6 = packetplayinflying.c(this.player.locZ());double toZ = d6; // Paper - OBFHELPER + float f = packetplayinflying.a(this.player.yaw); + float f1 = packetplayinflying.b(this.player.pitch); + double d7 = d4 - this.l; +@@ -1182,6 +1189,12 @@ public class PlayerConnection implements PacketListenerPlayIn { + } else { + speed = player.abilities.walkSpeed * 10f; + } ++ // Paper start - Prevent moving into unloaded chunks ++ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && !worldserver.isChunkLoaded((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { ++ this.internalTeleport(this.player.locX(), this.player.locY(), this.player.locZ(), this.player.yaw, this.player.pitch, Collections.emptySet()); ++ return; ++ } ++ // Paper end + + if (!this.player.H() && (!this.player.getWorldServer().getGameRules().getBoolean(GameRules.DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isGliding())) { + float f2 = this.player.isGliding() ? 300.0F : 100.0F; diff --git a/patches/server-unmapped/0303-Reset-players-airTicks-on-respawn.patch b/patches/server-unmapped/0303-Reset-players-airTicks-on-respawn.patch new file mode 100644 index 0000000000..a2e59dc39e --- /dev/null +++ b/patches/server-unmapped/0303-Reset-players-airTicks-on-respawn.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: GreenMeanie +Date: Sat, 20 Oct 2018 22:34:02 -0400 +Subject: [PATCH] Reset players airTicks on respawn + + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index f5be9554e1fd01a35b926196b30fd64f1567a799..3e7ac6699ad1f147220c286e251ce0ec1ca25035 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -2162,6 +2162,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + + this.setHealth(this.getMaxHealth()); ++ this.setAirTicks(this.getMaxAirTicks()); // Paper + this.fireTicks = 0; + this.fallDistance = 0; + this.foodData = new FoodMetaData(this); +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 28390d3830ed9f3f5d97ab38913e6c40f9943a70..2292295bac55651850b5e033f1ca9819bb7fa96f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2355,6 +2355,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + } + ++ public final int getMaxAirTicks() { return bH(); } // Paper - OBFHELPER + public int bH() { + return 300; + } diff --git a/patches/server-unmapped/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch b/patches/server-unmapped/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch new file mode 100644 index 0000000000..01be147e24 --- /dev/null +++ b/patches/server-unmapped/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 23 Oct 2018 20:25:05 -0400 +Subject: [PATCH] Don't sleep after profile lookups if not needed + +Mojang was sleeping even if we had no more requests to go after +the current one finished, resulting in 100ms lost per profile lookup + +diff --git a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java +index a3ab666b5fa89aad7ee167d9aeff2f62019a4a78..8e182fdd69dba6e1c52e2f6a893534d77fb3bfaa 100644 +--- a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java ++++ b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java +@@ -43,6 +43,7 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { + } + + final int page = 0; ++ boolean hasRequested = false; // Paper + + for (final List request : Iterables.partition(criteria, ENTRIES_PER_PAGE)) { + int failCount = 0; +@@ -68,6 +69,12 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { + LOGGER.debug("Couldn't find profile {}", name); + callback.onProfileLookupFailed(new GameProfile(null, name), new ProfileNotFoundException("Server did not find the requested profile")); + } ++ // Paper start ++ if (!hasRequested) { ++ hasRequested = true; ++ continue; ++ } ++ // Paper end + + try { + Thread.sleep(DELAY_BETWEEN_PAGES); diff --git a/patches/server-unmapped/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/patches/server-unmapped/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch new file mode 100644 index 0000000000..88f88070b9 --- /dev/null +++ b/patches/server-unmapped/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 23 Oct 2018 23:14:38 -0400 +Subject: [PATCH] Improve Server Thread Pool and Thread Priorities + +Use a simple executor since Fork join is a much more complex pool +type and we are not using its capabilities. + +Set thread priorities so main thread has above normal priority over +server threads + +Allow usage of a single thread executor by not using ForkJoin so single core CPU's. + +diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java +index 68ce7605bd63ea280b96db8230463d2afb0a6cb1..46d82c1548088b8305f758699388edf0d5d4d050 100644 +--- a/src/main/java/net/minecraft/SystemUtils.java ++++ b/src/main/java/net/minecraft/SystemUtils.java +@@ -45,6 +45,7 @@ import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.server.DispenserRegistry; ++import net.minecraft.server.ServerWorkerThread; + import net.minecraft.util.MathHelper; + import net.minecraft.util.datafix.DataConverterRegistry; + import net.minecraft.world.level.block.state.properties.IBlockState; +@@ -54,8 +55,8 @@ import org.apache.logging.log4j.Logger; + public class SystemUtils { + + private static final AtomicInteger c = new AtomicInteger(1); +- private static final ExecutorService d = a("Bootstrap"); +- private static final ExecutorService e = a("Main"); ++ private static final ExecutorService d = a("Bootstrap", -2); // Paper - add -2 priority ++ private static final ExecutorService e = a("Main", -1); // Paper - add -1 priority + private static final ExecutorService f = n(); + public static LongSupplier a = System::nanoTime; + public static final UUID b = new UUID(0L, 0L); public static final UUID getNullUUID() {return b;} // Paper OBFHELPER +@@ -85,15 +86,18 @@ public class SystemUtils { + return Instant.now().toEpochMilli(); + } + +- private static ExecutorService a(String s) { +- int i = MathHelper.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, 7); +- Object object; ++ private static ExecutorService a(String s, int priorityModifier) { // Paper - add priority ++ // Paper start - use simpler thread pool that allows 1 thread ++ int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1)); ++ i = Integer.getInteger("Paper.WorkerThreadCount", i); ++ ExecutorService object; + + if (i <= 0) { + object = MoreExecutors.newDirectExecutorService(); + } else { +- object = new ForkJoinPool(i, (forkjoinpool) -> { +- ForkJoinWorkerThread forkjoinworkerthread = new ForkJoinWorkerThread(forkjoinpool) { ++ object = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue(), target -> new ServerWorkerThread(target, s, priorityModifier)); ++ } ++ /* + protected void onTermination(Throwable throwable) { + if (throwable != null) { + SystemUtils.LOGGER.warn("{} died", this.getName(), throwable); +@@ -109,6 +113,7 @@ public class SystemUtils { + return forkjoinworkerthread; + }, SystemUtils::a, true); + } ++ }*/ // Paper end + + return (ExecutorService) object; + } +@@ -157,6 +162,7 @@ public class SystemUtils { + }); + } + ++ public static void onThreadError(Thread thread, Throwable throwable) { a(thread, throwable); } // Paper - OBFHELPER + private static void a(Thread thread, Throwable throwable) { + c(throwable); + if (throwable instanceof CompletionException) { +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 52c0dd4f2779125116d9dcccc2aef7a11af92945..7d1ed99a919194296ee08a67cc543bedcf48395a 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -286,6 +286,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant +Date: Fri, 2 Nov 2018 23:11:51 -0400 +Subject: [PATCH] Optimize World Time Updates + +Splits time updates into incremental updates as well as does +the updates per world, so that we can re-use the same packet +object for every player unless they have per-player time enabled. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 7d1ed99a919194296ee08a67cc543bedcf48395a..419448fe02b58e08c17795c903c945ad8a3ce1b5 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1316,12 +1316,24 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant +Date: Mon, 5 Nov 2018 04:23:51 +0000 +Subject: [PATCH] Restore custom InventoryHolder support + +Upstream removed the ability to consistently use a custom InventoryHolder, +However, the implementation does not use an InventoryHolder in any form +outside of custom inventories. + +We can take that knowledge and apply some expected behavior, if we're given +an inventory holder, we should use it and return a custom inventory with the +holder, otherwise, create an inventory backed by the intended inventory, as +per upstream behavior. + +This provides a "best of both worlds" scenario: plugins with InventoryHolder's +will always work as intended in the past, those without will create implementation +based inventories. + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +index 94d807c5d09f165c6eedd0a1c4026c2b833806a0..3e56de295be0d03dddd3e54fcd7b05d4b9c74dc4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +@@ -40,6 +40,11 @@ public final class CraftInventoryCreator { + } + + public Inventory createInventory(InventoryHolder holder, InventoryType type) { ++ // Paper start ++ if (holder != null) { ++ return DEFAULT_CONVERTER.createInventory(holder, type); ++ } ++ //noinspection ConstantConditions // Paper end + return converterMap.get(type).createInventory(holder, type); + } + +@@ -55,6 +60,11 @@ public final class CraftInventoryCreator { + // Paper end + + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { ++ // Paper start ++ if (holder != null) { ++ return DEFAULT_CONVERTER.createInventory(holder, type, title); ++ } ++ //noinspection ConstantConditions // Paper end + return converterMap.get(type).createInventory(holder, type, title); + } + diff --git a/patches/server-unmapped/0308-Use-Vanilla-Minecart-Speeds.patch b/patches/server-unmapped/0308-Use-Vanilla-Minecart-Speeds.patch new file mode 100644 index 0000000000..7e7e806b36 --- /dev/null +++ b/patches/server-unmapped/0308-Use-Vanilla-Minecart-Speeds.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 8 Nov 2018 21:33:09 -0500 +Subject: [PATCH] Use Vanilla Minecart Speeds + +CraftBukkit changed the values on flying speed, restore back to vanilla + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +index 1f94cc096d95129d85a6278b1e369729df93d27d..7d91e6b75a8a827853b0ca8e53b8ec19e2cf1092 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +@@ -100,9 +100,9 @@ public abstract class EntityMinecartAbstract extends Entity { + private double derailedX = 0.5; + private double derailedY = 0.5; + private double derailedZ = 0.5; +- private double flyingX = 0.95; +- private double flyingY = 0.95; +- private double flyingZ = 0.95; ++ private double flyingX = 0.949999988079071D; // Paper - restore vanilla precision ++ private double flyingY = 0.949999988079071D; // Paper - restore vanilla precision ++ private double flyingZ = 0.949999988079071D; // Paper - restore vanilla precision + public double maxSpeed = 0.4D; + // CraftBukkit end + diff --git a/patches/server-unmapped/0309-Fix-SpongeAbsortEvent-handling.patch b/patches/server-unmapped/0309-Fix-SpongeAbsortEvent-handling.patch new file mode 100644 index 0000000000..f0c682b058 --- /dev/null +++ b/patches/server-unmapped/0309-Fix-SpongeAbsortEvent-handling.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 10 Nov 2018 05:15:21 +0000 +Subject: [PATCH] Fix SpongeAbsortEvent handling + +Only process drops when the block is actually going to be removed + +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 615a4418fd276cd3e0b3686d962ebaf13ef5d4be..e5c43b383a93fac76333a67b41535ab009d1dcf3 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -228,6 +228,7 @@ public class Block extends BlockBase implements IMaterial { + + } + ++ public static void dropNaturally(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, @Nullable TileEntity tileentity) { a(iblockdata, generatoraccess, blockposition, tileentity); } + public static void a(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, @Nullable TileEntity tileentity) { + if (generatoraccess instanceof WorldServer) { + a(iblockdata, (WorldServer) generatoraccess, blockposition, tileentity).forEach((itemstack) -> { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockSponge.java b/src/main/java/net/minecraft/world/level/block/BlockSponge.java +index ef48ad0ab68e2e050bc8aca484d850297990b78e..d80eee47390ab202eea0368571421bbc94655ab1 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockSponge.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockSponge.java +@@ -129,8 +129,11 @@ public class BlockSponge extends Block { + // NOP + } else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) { + TileEntity tileentity = iblockdata.getBlock().isTileEntity() ? world.getTileEntity(blockposition2) : null; +- +- a(iblockdata, world, blockposition2, tileentity); ++ // Paper start ++ if (block.getHandle().getMaterial() == Material.AIR) { ++ dropNaturally(iblockdata, world, blockposition2, tileentity); ++ } ++ // Paper end + } + } + world.setTypeAndData(blockposition2, block.getHandle(), block.getFlag()); diff --git a/patches/server-unmapped/0310-Don-t-allow-digging-into-unloaded-chunks.patch b/patches/server-unmapped/0310-Don-t-allow-digging-into-unloaded-chunks.patch new file mode 100644 index 0000000000..2447748fec --- /dev/null +++ b/patches/server-unmapped/0310-Don-t-allow-digging-into-unloaded-chunks.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 11 Nov 2018 21:01:09 +0000 +Subject: [PATCH] Don't allow digging into unloaded chunks + + +diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +index 14f287d30c9a141f78f6311bef02a6fc4fa17564..d86b1e528b53db809ac993aa2f1d2799d4f1a574 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java ++++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +@@ -114,8 +114,8 @@ public class PlayerInteractManager { + IBlockData iblockdata; + + if (this.j) { +- iblockdata = this.world.getType(this.k); +- if (iblockdata.isAir()) { ++ iblockdata = this.world.getTypeIfLoaded(this.k); // Paper ++ if (iblockdata == null || iblockdata.isAir()) { // Paper + this.j = false; + } else { + float f = this.a(iblockdata, this.k, this.l); +@@ -126,7 +126,13 @@ public class PlayerInteractManager { + } + } + } else if (this.f) { +- iblockdata = this.world.getType(this.h); ++ // Paper start - don't want to do same logic as above, return instead ++ iblockdata = this.world.getTypeIfLoaded(this.h); ++ if (iblockdata == null) { ++ this.f = false; ++ return; ++ } ++ // Paper end + if (iblockdata.isAir()) { + this.world.a(this.player.getId(), this.h, -1); + this.m = -1; +@@ -290,10 +296,12 @@ public class PlayerInteractManager { + this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(blockposition, this.world.getType(blockposition), packetplayinblockdig_enumplayerdigtype, true, "stopped destroying")); + } else if (packetplayinblockdig_enumplayerdigtype == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { + this.f = false; +- if (!Objects.equals(this.h, blockposition)) { ++ if (!Objects.equals(this.h, blockposition) && !BlockPosition.ZERO.equals(this.h)) { + PlayerInteractManager.LOGGER.debug("Mismatch in destroy block pos: " + this.h + " " + blockposition); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled +- this.world.a(this.player.getId(), this.h, -1); +- this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(this.h, this.world.getType(this.h), packetplayinblockdig_enumplayerdigtype, true, "aborted mismatched destroying")); ++ IBlockData type = this.world.getTypeIfLoaded(this.h); // Paper - don't load unloaded chunks for stale records here ++ if (type != null) this.world.a(this.player.getId(), this.h, -1); // Paper ++ if (type != null) this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(this.h, type, packetplayinblockdig_enumplayerdigtype, true, "aborted mismatched destroying")); // Paper ++ this.h = BlockPosition.ZERO; // Paper + } + + this.world.a(this.player.getId(), blockposition, -1); +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index f48683ef9afe3e5d0e0e5959c698152e9086632b..6f40d9fd45b42935d6eb58981f1d7aac2b4c2454 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1520,6 +1520,11 @@ public class PlayerConnection implements PacketListenerPlayIn { + case START_DESTROY_BLOCK: + case ABORT_DESTROY_BLOCK: + case STOP_DESTROY_BLOCK: ++ // Paper start - Don't allow digging in unloaded chunks ++ if (this.player.world.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { ++ return; ++ } ++ // Paper end - Don't allow digging in unloaded chunks + this.player.playerInteractManager.a(blockposition, packetplayinblockdig_enumplayerdigtype, packetplayinblockdig.c(), this.minecraftServer.getMaxBuildHeight()); + return; + default: diff --git a/patches/server-unmapped/0311-Book-Size-Limits.patch b/patches/server-unmapped/0311-Book-Size-Limits.patch new file mode 100644 index 0000000000..cbabef0949 --- /dev/null +++ b/patches/server-unmapped/0311-Book-Size-Limits.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 16 Nov 2018 23:08:50 -0500 +Subject: [PATCH] Book Size Limits + +Puts some limits on the size of books. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 3139c194f9b1bc3510d51a81f13ae43d00a3dc29..13edb435b3fa65b4980bd7472aa5a5196f4d5b2b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -339,4 +339,11 @@ public class PaperConfig { + velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); + } + } ++ ++ public static int maxBookPageSize = 2560; ++ public static double maxBookTotalSizeMultiplier = 0.98D; ++ private static void maxBookSize() { ++ maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); ++ maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 6f40d9fd45b42935d6eb58981f1d7aac2b4c2454..54399a2f2d1d86b650e27f6a31dce89035e7aeba 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1001,6 +1001,52 @@ public class PlayerConnection implements PacketListenerPlayIn { + + @Override + public void a(PacketPlayInBEdit packetplayinbedit) { ++ // Paper start ++ ItemStack testStack = packetplayinbedit.getBook(); ++ if (!server.isPrimaryThread() && !testStack.isEmpty() && testStack.getTag() != null) { ++ NBTTagList pageList = testStack.getTag().getList("pages", 8); ++ if (pageList.size() > 100) { ++ PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with too many pages"); ++ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ return; ++ } ++ long byteTotal = 0; ++ int maxBookPageSize = com.destroystokyo.paper.PaperConfig.maxBookPageSize; ++ double multiplier = Math.max(0.3D, Math.min(1D, com.destroystokyo.paper.PaperConfig.maxBookTotalSizeMultiplier)); ++ long byteAllowed = maxBookPageSize; ++ for (int i = 0; i < pageList.size(); ++i) { ++ String testString = pageList.getString(i); ++ int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; ++ if (byteLength > 256 * 4) { ++ PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with with a page too large!"); ++ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ return; ++ } ++ byteTotal += byteLength; ++ int length = testString.length(); ++ int multibytes = 0; ++ if (byteLength != length) { ++ for (char c : testString.toCharArray()) { ++ if (c > 127) { ++ multibytes++; ++ } ++ } ++ } ++ byteAllowed += (maxBookPageSize * Math.min(1, Math.max(0.1D, (double) length / 255D))) * multiplier; ++ ++ if (multibytes > 1) { ++ // penalize MB ++ byteAllowed -= multibytes; ++ } ++ } ++ ++ if (byteTotal > byteAllowed) { ++ PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); ++ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ return; ++ } ++ } ++ // Paper end + // CraftBukkit start + if (this.lastBookTick + 20 > MinecraftServer.currentTick) { + this.disconnect("Book edited too quickly!"); diff --git a/patches/server-unmapped/0312-Make-the-default-permission-message-configurable.patch b/patches/server-unmapped/0312-Make-the-default-permission-message-configurable.patch new file mode 100644 index 0000000000..89df9fee73 --- /dev/null +++ b/patches/server-unmapped/0312-Make-the-default-permission-message-configurable.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 18 Nov 2018 19:49:56 +0000 +Subject: [PATCH] Make the default permission message configurable + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 13edb435b3fa65b4980bd7472aa5a5196f4d5b2b..469f78775b03cf363d88e35c69c0dc185c22547c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -19,6 +19,7 @@ import java.util.regex.Pattern; + import com.google.common.collect.Lists; + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; ++import org.bukkit.ChatColor; + import org.bukkit.command.Command; + import org.bukkit.configuration.ConfigurationSection; + import org.bukkit.configuration.InvalidConfigurationException; +@@ -287,6 +288,11 @@ public class PaperConfig { + connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); + } + ++ public static String noPermissionMessage = "&cI'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error."; ++ private static void noPermissionMessage() { ++ noPermissionMessage = ChatColor.translateAlternateColorCodes('&', getString("messages.no-permission", noPermissionMessage)); ++ } ++ + private static void savePlayerData() { + Object val = config.get("settings.save-player-data"); + if (val instanceof Boolean) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 22f9d8c0189293b88353bbe1bcc40dd1d431d458..aff20bc4a4d9834b2555f5fe4fa9c46751eae2ba 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2341,6 +2341,11 @@ public final class CraftServer implements Server { + return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; + } + ++ @Override ++ public String getPermissionMessage() { ++ return com.destroystokyo.paper.PaperConfig.noPermissionMessage; ++ } ++ + @Override + public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { + return createProfile(uuid, null); diff --git a/patches/server-unmapped/0313-Prevent-rayTrace-from-loading-chunks.patch b/patches/server-unmapped/0313-Prevent-rayTrace-from-loading-chunks.patch new file mode 100644 index 0000000000..0295326280 --- /dev/null +++ b/patches/server-unmapped/0313-Prevent-rayTrace-from-loading-chunks.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 26 Nov 2018 19:21:58 -0500 +Subject: [PATCH] Prevent rayTrace from loading chunks + +ray tracing into an unloaded chunk should be treated as a miss +this saves a ton of lag for when AI tries to raytrace near unloaded chunks. + +diff --git a/src/main/java/net/minecraft/world/level/IBlockAccess.java b/src/main/java/net/minecraft/world/level/IBlockAccess.java +index e799765ecfada1eec78beb71651e52ad355a30aa..21ce19b9caf3150535a3f84027242a93bdd0d263 100644 +--- a/src/main/java/net/minecraft/world/level/IBlockAccess.java ++++ b/src/main/java/net/minecraft/world/level/IBlockAccess.java +@@ -58,7 +58,15 @@ public interface IBlockAccess { + + // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace + default MovingObjectPositionBlock rayTraceBlock(RayTrace raytrace1, BlockPosition blockposition) { +- IBlockData iblockdata = this.getType(blockposition); ++ // Paper start - Prevent raytrace from loading chunks ++ IBlockData iblockdata = this.getTypeIfLoaded(blockposition); ++ if (iblockdata == null) { ++ // copied the last function parameter (listed below) ++ Vec3D vec3d = raytrace1.b().d(raytrace1.a()); ++ ++ return MovingObjectPositionBlock.a(raytrace1.a(), EnumDirection.a(vec3d.x, vec3d.y, vec3d.z), new BlockPosition(raytrace1.a())); ++ } ++ // Paper end + Fluid fluid = this.getFluid(blockposition); + Vec3D vec3d = raytrace1.b(); + Vec3D vec3d1 = raytrace1.a(); diff --git a/patches/server-unmapped/0314-Handle-Large-Packets-disconnecting-client.patch b/patches/server-unmapped/0314-Handle-Large-Packets-disconnecting-client.patch new file mode 100644 index 0000000000..9f62fd514e --- /dev/null +++ b/patches/server-unmapped/0314-Handle-Large-Packets-disconnecting-client.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 27 Nov 2018 21:18:06 -0500 +Subject: [PATCH] Handle Large Packets disconnecting client + +If a players inventory is too big to send in a single packet, +split the inventory set into multiple packets instead. + +diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +index 297820baef99e97e1216a64c527219e9ccc3e320..dc788d75a6a34fbbae990609bfbbd13ca6cdee5a 100644 +--- a/src/main/java/net/minecraft/network/NetworkManager.java ++++ b/src/main/java/net/minecraft/network/NetworkManager.java +@@ -12,6 +12,7 @@ import io.netty.channel.epoll.EpollEventLoopGroup; + import io.netty.channel.local.LocalChannel; + import io.netty.channel.local.LocalServerChannel; + import io.netty.channel.nio.NioEventLoopGroup; ++import io.netty.handler.codec.EncoderException; // Paper + import io.netty.handler.timeout.TimeoutException; + import io.netty.util.AttributeKey; + import io.netty.util.concurrent.Future; +@@ -107,6 +108,15 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } + + public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { ++ // Paper start ++ if (throwable instanceof EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) { ++ if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) { ++ return; ++ } else { ++ throwable = throwable.getCause(); ++ } ++ } ++ // Paper end + if (throwable instanceof SkipEncodeException) { + NetworkManager.LOGGER.debug("Skipping packet due to errors", throwable.getCause()); + } else { +diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java +index 2f6da89d6b25ba5144ec15b1bf0e8ed13278e85e..037d989522d24a55eced1c462d40a6dc2a7ecfce 100644 +--- a/src/main/java/net/minecraft/network/PacketEncoder.java ++++ b/src/main/java/net/minecraft/network/PacketEncoder.java +@@ -53,7 +53,31 @@ public class PacketEncoder extends MessageToByteEncoder> { + throw throwable; + } + } ++ ++ // Paper start ++ int packetLength = bytebuf.readableBytes(); ++ if (packetLength > MAX_PACKET_SIZE) { ++ throw new PacketTooLargeException(packet, packetLength); ++ } ++ // Paper end + } + } + } ++ ++ // Paper start ++ private static int MAX_PACKET_SIZE = 2097152; ++ ++ public static class PacketTooLargeException extends RuntimeException { ++ private final Packet packet; ++ ++ PacketTooLargeException(Packet packet, int packetLength) { ++ super("PacketTooLarge - " + packet.getClass().getSimpleName() + " is " + packetLength + ". Max is " + MAX_PACKET_SIZE); ++ this.packet = packet; ++ } ++ ++ public Packet getPacket() { ++ return packet; ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java +index cd4493a023748264748d4e892815f14d8a7bd7f6..0783b0777c8d7788bbf6780b464b709bf6dc2191 100644 +--- a/src/main/java/net/minecraft/network/protocol/Packet.java ++++ b/src/main/java/net/minecraft/network/protocol/Packet.java +@@ -12,6 +12,12 @@ public interface Packet { + + void a(T t0); + ++ // Paper start ++ default boolean packetTooLarge(NetworkManager manager) { ++ return false; ++ } ++ // Paper end ++ + default boolean a() { + return false; + } +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java +index 152118729b1a95dcae05d32aa4289034ba394226..0059ede4ba3ff271d47dd38ea87fddc2399aa008 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java +@@ -91,7 +91,7 @@ public class PacketPlayOutMapChunk implements Packet { + + int i = packetdataserializer.i(); + +- if (i > 2097152) { ++ if (i > 2097152) { // Paper - if this changes, update PacketEncoder + throw new RuntimeException("Chunk Packet trying to allocate too much memory on read."); + } else { + this.f = new byte[i]; +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java +index b90e35a0099a2482f8fc2998bd079fc2fe6439e6..e540f95a370c627d3d81e0d3670049d01923559d 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java +@@ -4,6 +4,7 @@ import java.io.IOException; + import java.util.Iterator; + import java.util.List; + import net.minecraft.core.NonNullList; ++import net.minecraft.network.NetworkManager; + import net.minecraft.network.PacketDataSerializer; + import net.minecraft.network.protocol.Packet; + import net.minecraft.world.item.ItemStack; +@@ -13,6 +14,15 @@ public class PacketPlayOutWindowItems implements Packet { + private int a; + private List b; + ++ //Paper start ++ @Override ++ public boolean packetTooLarge(NetworkManager manager) { ++ for (int i = 0 ; i < this.b.size() ; i++) { ++ manager.sendPacket(new PacketPlayOutSetSlot(this.a, i, this.b.get(i))); ++ } ++ return true; ++ } ++ // Paper end + public PacketPlayOutWindowItems() {} + + public PacketPlayOutWindowItems(int i, NonNullList nonnulllist) { diff --git a/patches/server-unmapped/0315-force-entity-dismount-during-teleportation.patch b/patches/server-unmapped/0315-force-entity-dismount-during-teleportation.patch new file mode 100644 index 0000000000..966dd873fc --- /dev/null +++ b/patches/server-unmapped/0315-force-entity-dismount-during-teleportation.patch @@ -0,0 +1,134 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 15 Nov 2018 13:38:37 +0000 +Subject: [PATCH] force entity dismount during teleportation + +Entities must be dismounted before teleportation in order to avoid +multiple issues in the server with regards to teleportation, shamefully, +too many plugins rely on the events firing, which means that not firing +these events caues more issues than it solves; + +In order to counteract this, Entity dismount/exit vehicle events have +been modified to supress cancellation (and has a method to allow plugins +to check if this has been set), noting that cancellation will be silently +surpressed given that plugins are not expecting this event to not be cancellable. + +This is a far from ideal scenario, however: given the current state of this +event and other alternatives causing issues elsewhere, I believe that +this is going to be the best soultion all around. + +Improvements/suggestions welcome! + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 3e7ac6699ad1f147220c286e251ce0ec1ca25035..e755191435e74246b309f8fe5a668dae2e499df1 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1261,11 +1261,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + } + +- @Override +- public void stopRiding() { ++ // Paper start ++ @Override public void stopRiding() { stopRiding(false); } ++ @Override public void stopRiding(boolean suppressCancellation) { ++ // paper end + Entity entity = this.getVehicle(); + +- super.stopRiding(); ++ super.stopRiding(suppressCancellation); // Paper + Entity entity1 = this.getVehicle(); + + if (entity1 != entity && this.playerConnection != null) { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 2292295bac55651850b5e033f1ca9819bb7fa96f..af38b81df3f60163cafc341543ecad0865225943 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2045,12 +2045,15 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + } + +- public void bf() { ++ // Paper start ++ public void bf() { stopRiding(false); } ++ public void stopRiding(boolean suppressCancellation) { ++ // Paper end + if (this.vehicle != null) { + Entity entity = this.vehicle; + + this.vehicle = null; +- if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit ++ if (!entity.removePassenger(this, suppressCancellation)) this.vehicle = entity; // CraftBukkit // Paper + } + + } +@@ -2105,7 +2108,10 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return true; // CraftBukkit + } + +- protected boolean removePassenger(Entity entity) { // CraftBukkit ++ // Paper start ++ protected boolean removePassenger(Entity entity) { return removePassenger(entity, false);} ++ protected boolean removePassenger(Entity entity, boolean suppressCancellation) { // CraftBukkit ++ // Paper end + if (entity.getVehicle() == this) { + throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); + } else { +@@ -2115,7 +2121,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { + VehicleExitEvent event = new VehicleExitEvent( + (Vehicle) getBukkitEntity(), +- (LivingEntity) entity.getBukkitEntity() ++ (LivingEntity) entity.getBukkitEntity(), !suppressCancellation // Paper + ); + // Suppress during worldgen + if (this.valid) { +@@ -2129,7 +2135,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + // CraftBukkit end + // Spigot start +- org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity()); ++ org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity(), !suppressCancellation); // Paper + // Suppress during worldgen + if (this.valid) { + Bukkit.getPluginManager().callEvent(event); +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index e20acbd904f12e9036cb0565d6aa9a3f63008d43..32a2d6fd22ba69694a2f620174f618a95964074d 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -3015,11 +3015,13 @@ public abstract class EntityLiving extends Entity { + return ((Byte) this.datawatcher.get(EntityLiving.ag) & 4) != 0; + } + +- @Override +- public void stopRiding() { ++ // Paper start ++ @Override public void stopRiding() { stopRiding(false); } ++ @Override public void stopRiding(boolean suppressCancellation) { ++ // Paper end + Entity entity = this.getVehicle(); + +- super.stopRiding(); ++ super.stopRiding(suppressCancellation); // Paper - suppress + if (entity != null && entity != this.getVehicle() && !this.world.isClientSide) { + this.a(entity); + } +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 87374174dcbf9e7ee448a1cdd9a3528557c3a2ea..564dfa98c166fde509044e6e1938efb321ece53d 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -1039,9 +1039,11 @@ public abstract class EntityHuman extends EntityLiving { + return -0.35D; + } + +- @Override +- public void bf() { +- super.bf(); ++ // Paper start ++ @Override public void bf() { stopRiding(false); } ++ @Override public void stopRiding(boolean suppressCancellation) { ++ // Paper end ++ super.stopRiding(suppressCancellation); // Paper - suppress + this.j = 0; + } + diff --git a/patches/server-unmapped/0316-Add-more-Zombie-API.patch b/patches/server-unmapped/0316-Add-more-Zombie-API.patch new file mode 100644 index 0000000000..c620328b1a --- /dev/null +++ b/patches/server-unmapped/0316-Add-more-Zombie-API.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 7 Oct 2018 04:29:59 -0500 +Subject: [PATCH] Add more Zombie API + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index 219e3b1626d68ede57b08a706d24bb6bc4b13fac..79d34b0296f88e5b4fe0351fe2483fc0128deabc 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -94,6 +94,7 @@ public class EntityZombie extends EntityMonster { + private int bt; + public int drownedConversionTime; + private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field ++ private boolean shouldBurnInDay = true; // Paper + + public EntityZombie(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -262,6 +263,12 @@ public class EntityZombie extends EntityMonster { + super.movementTick(); + } + ++ // Paper start ++ public void stopDrowning() { ++ this.drownedConversionTime = -1; ++ this.getDataWatcher().set(EntityZombie.DROWN_CONVERTING, false); ++ } ++ // Paper end + public void startDrownedConversion(int i) { + this.lastTick = MinecraftServer.currentTick; // CraftBukkit + this.drownedConversionTime = i; +@@ -290,9 +297,16 @@ public class EntityZombie extends EntityMonster { + + } + ++ public boolean shouldBurnInDay() { return T_(); } // Paper - OBFHELPER + protected boolean T_() { +- return true; ++ return this.shouldBurnInDay; // Paper - use api value instead ++ } ++ ++ // Paper start ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { ++ this.shouldBurnInDay = shouldBurnInDay; + } ++ // Paper end + + @Override + public boolean damageEntity(DamageSource damagesource, float f) { +@@ -413,6 +427,7 @@ public class EntityZombie extends EntityMonster { + nbttagcompound.setBoolean("CanBreakDoors", this.eU()); + nbttagcompound.setInt("InWaterTime", this.isInWater() ? this.bt : -1); + nbttagcompound.setInt("DrownedConversionTime", this.isDrownConverting() ? this.drownedConversionTime : -1); ++ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); // Paper + } + + @Override +@@ -424,7 +439,11 @@ public class EntityZombie extends EntityMonster { + if (nbttagcompound.hasKeyOfType("DrownedConversionTime", 99) && nbttagcompound.getInt("DrownedConversionTime") > -1) { + this.startDrownedConversion(nbttagcompound.getInt("DrownedConversionTime")); + } +- ++ // Paper start ++ if (nbttagcompound.hasKey("Paper.ShouldBurnInDay")) { ++ shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); ++ } ++ // Paper end + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +index 8ba92b7edacc088d610a9ed46eb7f61ebd8101a8..42d98d798bb8fe2d3c7cc2bfcf2ec38d97d99bd2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +@@ -94,6 +94,42 @@ public class CraftZombie extends CraftMonster implements Zombie { + @Override + public void setAgeLock(boolean b) { + } ++ // Paper start ++ @Override ++ public boolean isDrowning() { ++ return getHandle().isDrownConverting(); ++ } ++ ++ @Override ++ public void startDrowning(int drownedConversionTime) { ++ getHandle().startDrownedConversion(drownedConversionTime); ++ } ++ ++ @Override ++ public void stopDrowning() { ++ getHandle().stopDrowning(); ++ } ++ ++ @Override ++ public boolean shouldBurnInDay() { ++ return getHandle().shouldBurnInDay(); ++ } ++ ++ @Override ++ public boolean isArmsRaised() { ++ return getHandle().isAggressive(); ++ } ++ ++ @Override ++ public void setArmsRaised(final boolean raised) { ++ getHandle().setAggressive(raised); ++ } ++ ++ @Override ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { ++ getHandle().setShouldBurnInDay(shouldBurnInDay); ++ } ++ // Paper end + + @Override + public boolean getAgeLock() { diff --git a/patches/server-unmapped/0317-Add-PlayerConnectionCloseEvent.patch b/patches/server-unmapped/0317-Add-PlayerConnectionCloseEvent.patch new file mode 100644 index 0000000000..4911606848 --- /dev/null +++ b/patches/server-unmapped/0317-Add-PlayerConnectionCloseEvent.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 7 Oct 2018 12:05:28 -0700 +Subject: [PATCH] Add PlayerConnectionCloseEvent + +This event is invoked when a player has disconnected. It is guaranteed that, +if the server is in online-mode, that the provided uuid and username have been +validated. + +The event is invoked for players who have not yet logged into the world, whereas +PlayerQuitEvent is only invoked on players who have logged into the world. + +The event is invoked for players who have already logged into the world, +although whether or not the player exists in the world at the time of +firing is undefined. (That is, whether the plugin can retrieve a Player object +using the event parameters is undefined). However, it is guaranteed that this +event is invoked AFTER PlayerQuitEvent, if the player has already logged into +the world. + +This event is guaranteed to never fire unless AsyncPlayerPreLoginEvent has +been called beforehand, and this event may not be called in parallel with +AsyncPlayerPreLoginEvent for the same connection. + +Cancelling the AsyncPlayerPreLoginEvent guarantees the corresponding +PlayerConnectionCloseEvent is never called. + +The event may be invoked asynchronously or synchronously. As it stands, +it is never invoked asynchronously. However, plugins should check +Event#isAsynchronous to be future-proof. + +On purpose, the deprecated PlayerPreLoginEvent event is left out of the +API spec for this event. Plugins should not be using that event, and +how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent +is undefined. + +diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +index dc788d75a6a34fbbae990609bfbbd13ca6cdee5a..6d40ade5a52383ed86d28d272c3dc83dbdcbd218 100644 +--- a/src/main/java/net/minecraft/network/NetworkManager.java ++++ b/src/main/java/net/minecraft/network/NetworkManager.java +@@ -350,6 +350,26 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + this.j().a(new ChatMessage("multiplayer.disconnect.generic")); + } + this.packetQueue.clear(); // Free up packet queue. ++ // Paper start - Add PlayerConnectionCloseEvent ++ final PacketListener packetListener = this.j(); ++ if (packetListener instanceof PlayerConnection) { ++ /* Player was logged in */ ++ final PlayerConnection playerConnection = (PlayerConnection) packetListener; ++ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(playerConnection.player.getUniqueID(), ++ playerConnection.player.getName(), ((java.net.InetSocketAddress)socketAddress).getAddress(), false).callEvent(); ++ } else if (packetListener instanceof LoginListener) { ++ /* Player is login stage */ ++ final LoginListener loginListener = (LoginListener) packetListener; ++ switch (loginListener.getLoginState()) { ++ case READY_TO_ACCEPT: ++ case DELAY_ACCEPT: ++ case ACCEPTED: ++ final com.mojang.authlib.GameProfile profile = loginListener.getGameProfile(); /* Should be non-null at this stage */ ++ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(profile.getId(), profile.getName(), ++ ((java.net.InetSocketAddress)socketAddress).getAddress(), false).callEvent(); ++ } ++ } ++ // Paper end + } + + } +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index b89a8ee2ea03d00a3d6af63d6e3e0fd62af31130..2e995103fba15c21dbe89321896c7df03ae5e67b 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -57,9 +57,9 @@ public class LoginListener implements PacketLoginInListener { + private final byte[] e = new byte[4]; + private final MinecraftServer server; + public final NetworkManager networkManager; +- private LoginListener.EnumProtocolState g; ++ private LoginListener.EnumProtocolState g; public final LoginListener.EnumProtocolState getLoginState() { return this.g; }; // Paper - OBFHELPER + private int h; +- private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } private GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER ++ private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } public GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER + private final String j; + private SecretKey loginKey; + private EntityPlayer l; diff --git a/patches/server-unmapped/0318-Prevent-Enderman-from-loading-chunks.patch b/patches/server-unmapped/0318-Prevent-Enderman-from-loading-chunks.patch new file mode 100644 index 0000000000..86be24f3d4 --- /dev/null +++ b/patches/server-unmapped/0318-Prevent-Enderman-from-loading-chunks.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 18 Dec 2018 02:15:08 +0000 +Subject: [PATCH] Prevent Enderman from loading chunks + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +index aa6cb15637144c9d8db1b1861e58f3f02d68357a..e993b1849beb60515c51ee4f37617faab63ca223 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -434,7 +434,8 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + int j = MathHelper.floor(this.enderman.locY() + random.nextDouble() * 3.0D); + int k = MathHelper.floor(this.enderman.locZ() - 2.0D + random.nextDouble() * 4.0D); + BlockPosition blockposition = new BlockPosition(i, j, k); +- IBlockData iblockdata = world.getType(blockposition); ++ IBlockData iblockdata = world.getTypeIfLoaded(blockposition); // Paper ++ if (iblockdata == null) return; // Paper + Block block = iblockdata.getBlock(); + Vec3D vec3d = new Vec3D((double) MathHelper.floor(this.enderman.locX()) + 0.5D, (double) j + 0.5D, (double) MathHelper.floor(this.enderman.locZ()) + 0.5D); + Vec3D vec3d1 = new Vec3D((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); +@@ -474,7 +475,8 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { + int j = MathHelper.floor(this.a.locY() + random.nextDouble() * 2.0D); + int k = MathHelper.floor(this.a.locZ() - 1.0D + random.nextDouble() * 2.0D); + BlockPosition blockposition = new BlockPosition(i, j, k); +- IBlockData iblockdata = world.getType(blockposition); ++ IBlockData iblockdata = world.getTypeIfLoaded(blockposition); // Paper ++ if (iblockdata == null) return; // Paper + BlockPosition blockposition1 = blockposition.down(); + IBlockData iblockdata1 = world.getType(blockposition1); + IBlockData iblockdata2 = this.a.getCarried(); diff --git a/patches/server-unmapped/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/patches/server-unmapped/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch new file mode 100644 index 0000000000..aefc2dfd10 --- /dev/null +++ b/patches/server-unmapped/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch @@ -0,0 +1,164 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Jan 2019 00:35:43 -0600 +Subject: [PATCH] Add APIs to replace OfflinePlayer#getLastPlayed + +Currently OfflinePlayer#getLastPlayed could more accurately be described +as "OfflinePlayer#getLastTimeTheirDataWasSaved". + +The API doc says it should return the last time the server "witnessed" +the player, whilst also saying it should return the last time they +logged in. The current implementation does neither. + +Given this interesting contradiction in the API documentation and the +current defacto implementation, I've elected to deprecate (with no +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/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index e755191435e74246b309f8fe5a668dae2e499df1..8d88ed3d68146fbcb090847351945689518e59a9 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -214,6 +214,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public int ping; + public boolean viewingCredits; + private int containerUpdateDelay; // Paper ++ public long loginTime; // Paper + // Paper start - cancellable death event + public boolean queueHealthUpdatePacket = false; + public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 2299581fa889c0e8ddc6b2cc1d3551d02ff8dc2d..7515e9ddbc89de882373469cf3c46046c76af974 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -168,6 +168,7 @@ public abstract class PlayerList { + } + + public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { ++ entityplayer.loginTime = System.currentTimeMillis(); // Paper + GameProfile gameprofile = entityplayer.getProfile(); + UserCache usercache = this.server.getUserCache(); + GameProfile gameprofile1 = usercache.getProfile(gameprofile.getId()); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +index 9b8d7b176e288fa715177196e7aff92900d8567a..1e741158bbcc0991259436bec549b32df61f0c54 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +@@ -244,6 +244,61 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa + return getData() != null; + } + ++ // Paper start ++ @Override ++ public long getLastLogin() { ++ Player player = getPlayer(); ++ if (player != null) return player.getLastLogin(); ++ ++ NBTTagCompound data = getPaperData(); ++ ++ if (data != null) { ++ if (data.hasKey("LastLogin")) { ++ return data.getLong("LastLogin"); ++ } else { ++ // if the player file cannot provide accurate data, this is probably the closest we can approximate ++ File file = getDataFile(); ++ return file.lastModified(); ++ } ++ } else { ++ return 0; ++ } ++ } ++ ++ @Override ++ public long getLastSeen() { ++ Player player = getPlayer(); ++ if (player != null) return player.getLastSeen(); ++ ++ NBTTagCompound data = getPaperData(); ++ ++ if (data != null) { ++ if (data.hasKey("LastSeen")) { ++ return data.getLong("LastSeen"); ++ } else { ++ // if the player file cannot provide accurate data, this is probably the closest we can approximate ++ File file = getDataFile(); ++ return file.lastModified(); ++ } ++ } else { ++ return 0; ++ } ++ } ++ ++ private NBTTagCompound getPaperData() { ++ NBTTagCompound result = getData(); ++ ++ if (result != null) { ++ if (!result.hasKey("Paper")) { ++ result.set("Paper", new NBTTagCompound()); ++ } ++ result = result.getCompound("Paper"); ++ } ++ ++ return result; ++ } ++ // Paper end ++ + @Override + public Location getBedSpawnLocation() { + NBTTagCompound data = getData(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 6c5075ef2420131aa21b403623a5dfa485ee73e5..25e0d0dd7b114560896679f0314cea288d7a768c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -147,6 +147,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; + private String resourcePackHash; + private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit ++ private long lastSaveTime; + // Paper end + + public CraftPlayer(CraftServer server, EntityPlayer entity) { +@@ -1483,6 +1484,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + this.firstPlayed = firstPlayed; + } + ++ // Paper start ++ @Override ++ public long getLastLogin() { ++ return getHandle().loginTime; ++ } ++ ++ @Override ++ public long getLastSeen() { ++ return isOnline() ? System.currentTimeMillis() : this.lastSaveTime; ++ } ++ // Paper end ++ + public void readExtraData(NBTTagCompound nbttagcompound) { + hasPlayedBefore = true; + if (nbttagcompound.hasKey("bukkit")) { +@@ -1505,6 +1518,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + public void setExtraData(NBTTagCompound nbttagcompound) { ++ this.lastSaveTime = System.currentTimeMillis(); // Paper ++ + if (!nbttagcompound.hasKey("bukkit")) { + nbttagcompound.set("bukkit", new NBTTagCompound()); + } +@@ -1519,6 +1534,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + data.setLong("firstPlayed", getFirstPlayed()); + data.setLong("lastPlayed", System.currentTimeMillis()); + data.setString("lastKnownName", handle.getName()); ++ ++ // Paper start - persist for use in offline save data ++ if (!nbttagcompound.hasKey("Paper")) { ++ nbttagcompound.set("Paper", new NBTTagCompound()); ++ } ++ ++ NBTTagCompound paper = nbttagcompound.getCompound("Paper"); ++ paper.setLong("LastLogin", handle.loginTime); ++ paper.setLong("LastSeen", System.currentTimeMillis()); ++ // Paper end + } + + @Override diff --git a/patches/server-unmapped/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/patches/server-unmapped/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch new file mode 100644 index 0000000000..dcefdae5b4 --- /dev/null +++ b/patches/server-unmapped/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: connorhartley +Date: Mon, 7 Jan 2019 14:43:48 -0600 +Subject: [PATCH] Workaround for vehicle tracking issue on disconnect + + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 8d88ed3d68146fbcb090847351945689518e59a9..82f49078a91b6ac471d303bc68891d80e201bd1f 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1527,6 +1527,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public void p() { + this.ch = true; + this.ejectPassengers(); ++ ++ // Paper start - Workaround an issue where the vehicle doesn't track the passenger disconnection dismount. ++ if (this.isPassenger() && this.getVehicle() instanceof EntityPlayer) { ++ this.stopRiding(); ++ } ++ // Paper end ++ + if (this.isSleeping()) { + this.wakeup(true, false); + } diff --git a/patches/server-unmapped/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/patches/server-unmapped/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch new file mode 100644 index 0000000000..79adf82b5f --- /dev/null +++ b/patches/server-unmapped/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 31 Jan 2019 16:33:36 -0500 +Subject: [PATCH] Fire BlockPistonRetractEvent for all empty pistons + +There is an explicit check in the handling code for empty pistons that +prevents sticky pistons from firing the event. However when we look back +at the history we see that this check was originally added so that ONLY +sticky pistons would fire the retract event. I'm not sure why. +https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1092acbddf07edfa4100bc6824504ac75088e913 + +Over the course of several updates, the meaning of that field appears to +have changed from "is NOT sticky" to "is sticky". So now its having the +opposite effect. Only normal pistons fire the retraction event. And like +all things in CB, it's just been carried around since. + +If we are to believe the history, the correct fix for this issue is to +flip it so it only fires for sticky pistons, but that puts us in a +bind. It's already firing for non-sticky pistons, changing it now would +likely result in breakage. Furthermore, there is little documentation as +to WHY that was ever intended to be the case. + +Instead we opt to remove the check entirely so that the event fires for +all piston types. + +diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java +index 869aaae93bc83b8271644147bb569c868ab13fb8..7de86d6232eb84642fb6423a1b0a9f30d9df9f2b 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java +@@ -141,7 +141,7 @@ public class BlockPiston extends BlockDirectional { + } + + // CraftBukkit start +- if (!this.sticky) { ++ //if (!this.sticky) { // Paper - Prevents empty sticky pistons from firing retract - history behind is odd + org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); + BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); + world.getServer().getPluginManager().callEvent(event); +@@ -149,7 +149,7 @@ public class BlockPiston extends BlockDirectional { + if (event.isCancelled()) { + return; + } +- } ++ //} // Paper + // PAIL: checkME - what happened to setTypeAndData? + // CraftBukkit end + world.playBlockAction(blockposition, this, b0, enumdirection.c()); diff --git a/patches/server-unmapped/0322-Block-Entity-remove-from-being-called-on-Players.patch b/patches/server-unmapped/0322-Block-Entity-remove-from-being-called-on-Players.patch new file mode 100644 index 0000000000..64d8d081f7 --- /dev/null +++ b/patches/server-unmapped/0322-Block-Entity-remove-from-being-called-on-Players.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 4 Feb 2019 23:33:24 -0500 +Subject: [PATCH] Block Entity#remove from being called on Players + +This doesn't result in the same behavior as other entities and causes +several problems. Anyone ever complain about the "Cannot send chat +message" thing? That's one of the issues this causes, among others. + +If a plugin developer can come up with a valid reason to call this on a +Player we will look at limiting the scope of this change. It appears to +be unintentional in the few cases we've seen so far. + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 25e0d0dd7b114560896679f0314cea288d7a768c..f57ad014fb3d2ce2405bdd63db4c730458aac17a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2234,6 +2234,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public void resetCooldown() { + getHandle().resetAttackCooldown(); + } ++ ++ @Override ++ public void remove() { ++ if (this.getHandle().getClass().equals(EntityPlayer.class)) { // special case for NMS plugins inheriting ++ throw new UnsupportedOperationException("Calling Entity#remove on players produces undefined (bad) behavior"); ++ } else { ++ super.remove(); ++ } ++ } + // Paper end + + // Spigot start diff --git a/patches/server-unmapped/0323-BlockDestroyEvent.patch b/patches/server-unmapped/0323-BlockDestroyEvent.patch new file mode 100644 index 0000000000..c27cd38c27 --- /dev/null +++ b/patches/server-unmapped/0323-BlockDestroyEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 Feb 2019 00:20:33 -0500 +Subject: [PATCH] BlockDestroyEvent + +Adds an event for when the server is going to destroy a current block, +potentially causing it to drop. This event can be cancelled to avoid +the block destruction, such as preventing signs from popping when +floating in the air. + +This can replace many uses of BlockPhysicsEvent + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 88b1a0235bfc0b41ae1855f8900632e425730d1c..3b5ddc083719608e944bdefa38e1fd3909e8e200 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -26,6 +26,7 @@ import net.minecraft.core.particles.ParticleParam; + import net.minecraft.network.protocol.Packet; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.PlayerChunk; +@@ -559,8 +560,20 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return false; + } else { + Fluid fluid = this.getFluid(blockposition); ++ // Paper start - while the above setAir method is named same and looks very similar ++ // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent, ++ // it doesn't imply destruction of a block that plays a sound effect / drops an item. ++ boolean playEffect = true; ++ if (com.destroystokyo.paper.event.block.BlockDestroyEvent.getHandlerList().getRegisteredListeners().length > 0) { ++ com.destroystokyo.paper.event.block.BlockDestroyEvent event = new com.destroystokyo.paper.event.block.BlockDestroyEvent(MCUtil.toBukkitBlock(this, blockposition), fluid.getBlockData().createCraftBlockData(), flag); ++ if (!event.callEvent()) { ++ return false; ++ } ++ playEffect = event.playEffect(); ++ } ++ // Paper end + +- if (!(iblockdata.getBlock() instanceof BlockFireAbstract)) { ++ if (playEffect && !(iblockdata.getBlock() instanceof BlockFireAbstract)) { // Paper + this.triggerEffect(2001, blockposition, Block.getCombinedId(iblockdata)); + } + diff --git a/patches/server-unmapped/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/patches/server-unmapped/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch new file mode 100644 index 0000000000..e98607e7c3 --- /dev/null +++ b/patches/server-unmapped/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 18 Jan 2019 00:08:15 -0500 +Subject: [PATCH] Fix Custom Shapeless Custom Crafting Recipes + +Mojang implemented Shapeless different than Shaped + +This made the Bukkit RecipeChoice API not work for Shapeless. + +This reimplements vanilla logic using the same test logic as Shaped + +diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java +index 9226602691ccbf39835f2dd071f171c2375b0a16..e112d149fc3a7af7f0c9a5280c94c9b03b2aba2d 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java ++++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java +@@ -72,16 +72,49 @@ public class ShapelessRecipes implements RecipeCrafting { + AutoRecipeStackManager autorecipestackmanager = new AutoRecipeStackManager(); + int i = 0; + ++ // Paper start ++ java.util.List providedItems = new java.util.ArrayList<>(); ++ co.aikar.util.Counter matchedProvided = new co.aikar.util.Counter<>(); ++ co.aikar.util.Counter matchedIngredients = new co.aikar.util.Counter<>(); ++ // Paper end + for (int j = 0; j < inventorycrafting.getSize(); ++j) { + ItemStack itemstack = inventorycrafting.getItem(j); + + if (!itemstack.isEmpty()) { +- ++i; +- autorecipestackmanager.a(itemstack, 1); ++ // Paper start ++ itemstack = itemstack.cloneItemStack(); ++ providedItems.add(itemstack); ++ for (RecipeItemStack ingredient : ingredients) { ++ if (ingredient.test(itemstack)) { ++ matchedProvided.increment(itemstack); ++ matchedIngredients.increment(ingredient); ++ } ++ } ++ // Paper end + } + } + +- return i == this.ingredients.size() && autorecipestackmanager.a(this, (IntList) null); ++ // Paper start ++ if (matchedProvided.isEmpty() || matchedIngredients.isEmpty()) { ++ return false; ++ } ++ java.util.List ingredients = new java.util.ArrayList<>(this.ingredients); ++ providedItems.sort(java.util.Comparator.comparingInt((ItemStack c) -> (int) matchedProvided.getCount(c)).reversed()); ++ ingredients.sort(java.util.Comparator.comparingInt((RecipeItemStack c) -> (int) matchedIngredients.getCount(c))); ++ ++ PROVIDED: ++ for (ItemStack provided : providedItems) { ++ for (Iterator itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) { ++ RecipeItemStack ingredient = itIngredient.next(); ++ if (ingredient.test(provided)) { ++ itIngredient.remove(); ++ continue PROVIDED; ++ } ++ } ++ return false; ++ } ++ return ingredients.isEmpty(); ++ // Paper end + } + + public ItemStack a(InventoryCrafting inventorycrafting) { diff --git a/patches/server-unmapped/0325-Fix-sign-edit-memory-leak.patch b/patches/server-unmapped/0325-Fix-sign-edit-memory-leak.patch new file mode 100644 index 0000000000..223cbe60ae --- /dev/null +++ b/patches/server-unmapped/0325-Fix-sign-edit-memory-leak.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 28 Feb 2019 00:15:28 -0500 +Subject: [PATCH] Fix sign edit memory leak + +when a player edits a sign, a reference to their Entity is never cleand up. + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 54399a2f2d1d86b650e27f6a31dce89035e7aeba..b7b431a649c6bc3066c267783007eee4384d27bd 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2852,7 +2852,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + + TileEntitySign tileentitysign = (TileEntitySign) tileentity; + +- if (!tileentitysign.d() || tileentitysign.f() != this.player) { ++ if (!tileentitysign.d() || tileentitysign.signEditor == null || !tileentitysign.signEditor.equals(this.player.getUniqueID())) { + PlayerConnection.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getDisplayName().getString()); + this.sendPacket(tileentity.getUpdatePacket()); // CraftBukkit + return; +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java +index ec550aaa4e7943af4ecdd2275f1f32c21edf770a..6d0fe58d7e574ce5189e1f7a8485060d60b466d9 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java +@@ -30,6 +30,7 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // + private EntityHuman c; + private final FormattedString[] g; + private EnumColor color; ++ public java.util.UUID signEditor; // Paper + + public TileEntitySign() { + super(TileEntityTypes.SIGN); +@@ -131,7 +132,10 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // + } + + public void a(EntityHuman entityhuman) { +- this.c = entityhuman; ++ // Paper start ++ //this.c = entityhuman; ++ signEditor = entityhuman != null ? entityhuman.getUniqueID() : null; ++ // Paper end + } + + public EntityHuman f() { diff --git a/patches/server-unmapped/0326-Limit-Client-Sign-length-more.patch b/patches/server-unmapped/0326-Limit-Client-Sign-length-more.patch new file mode 100644 index 0000000000..d3b0d1f52d --- /dev/null +++ b/patches/server-unmapped/0326-Limit-Client-Sign-length-more.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 27 Feb 2019 22:18:40 -0500 +Subject: [PATCH] Limit Client Sign length more + +modified clients can send more data from the client +to the server and it would get stored on the sign as sent. + +Mojang has a limit of 384 which is much higher than reasonable. + +the client can barely render around 16 characters as-is, but formatting +codes can get it to be more than 16 actual length. + +Set a limit of 80 which should give an average of 16 characters 2 +sets of legacy formatting codes which should be plenty for all uses. + +This does not strip any existing data from the NBT as plugins +may use this for storing data out of the rendered area. + +it only impacts data sent from the client. + +Set -DPaper.maxSignLength=XX to change limit or -1 to disable + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index b7b431a649c6bc3066c267783007eee4384d27bd..c0c9af81a933135e940587c10155a24cd399b922 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -256,6 +256,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + private int E; + private int receivedMovePackets; + private int processedMovePackets; ++ private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); + private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit + + public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { +@@ -2862,7 +2863,17 @@ public class PlayerConnection implements PacketListenerPlayIn { + List lines = new java.util.ArrayList<>(); + + for (int i = 0; i < list.size(); ++i) { +- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. ++ // Paper start - cap line length - modified clients can send longer data than normal ++ String currentLine = list.get(i); ++ if (MAX_SIGN_LINE_LENGTH > 0 && currentLine.length() > MAX_SIGN_LINE_LENGTH) { ++ // This handles multibyte characters as 1 ++ int offset = currentLine.codePoints().limit(MAX_SIGN_LINE_LENGTH).map(Character::charCount).sum(); ++ if (offset < currentLine.length()) { ++ list.set(i, currentLine = currentLine.substring(0, offset)); ++ } ++ } ++ // Paper end ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(currentLine))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. + } + SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); + this.server.getPluginManager().callEvent(event); diff --git a/patches/server-unmapped/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/patches/server-unmapped/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch new file mode 100644 index 0000000000..033181274d --- /dev/null +++ b/patches/server-unmapped/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 2 Mar 2019 11:11:29 -0500 +Subject: [PATCH] Don't check ConvertSigns boolean every sign save + +property lookups arent super cheap. they synchronize, validate +and check security managers. + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java +index 6d0fe58d7e574ce5189e1f7a8485060d60b466d9..7f78f388584899b13ff983f0dc37c679bfb1507e 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java +@@ -31,6 +31,7 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // + private final FormattedString[] g; + private EnumColor color; + public java.util.UUID signEditor; // Paper ++ private static final boolean CONVERT_LEGACY_SIGNS = Boolean.getBoolean("convertLegacySigns"); // Paper + + public TileEntitySign() { + super(TileEntityTypes.SIGN); +@@ -51,7 +52,7 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // + } + + // CraftBukkit start +- if (Boolean.getBoolean("convertLegacySigns")) { ++ if (CONVERT_LEGACY_SIGNS) { // Paper + nbttagcompound.setBoolean("Bukkit.isConverted", true); + } + // CraftBukkit end diff --git a/patches/server-unmapped/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server-unmapped/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch new file mode 100644 index 0000000000..053340619f --- /dev/null +++ b/patches/server-unmapped/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch @@ -0,0 +1,390 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 May 2020 04:53:35 -0400 +Subject: [PATCH] Optimize Network Manager and add advanced packet support + +Adds ability for 1 packet to bundle other packets to follow it +Adds ability for a packet to delay sending more packets until a state is ready. + +Removes synchronization from sending packets +Removes processing packet queue off of main thread + - for the few cases where it is allowed, order is not necessary nor + should it even be happening concurrently in first place (handshaking/login/status) + +Ensures packets sent asynchronously are dispatched on main thread + +This helps ensure safety for ProtocolLib as packet listeners +are commonly accessing world state. This will allow you to schedule +a packet to be sent async, but itll be dispatched sync for packet +listeners to process. + +This should solve some deadlock risks + +Also adds Netty Channel Flush Consolidation to reduce the amount of flushing + +Also avoids spamming closed channel exception by rechecking closed state in dispatch +and then catch exceptions and close if they fire. + +Part of this commit was authored by: Spottedleaf + +diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +index 6d40ade5a52383ed86d28d272c3dc83dbdcbd218..ab70eeaeca222de7de7cab1b3db14b2c4761c3c3 100644 +--- a/src/main/java/net/minecraft/network/NetworkManager.java ++++ b/src/main/java/net/minecraft/network/NetworkManager.java +@@ -25,8 +25,15 @@ import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.network.protocol.EnumProtocolDirection; + import net.minecraft.network.protocol.Packet; ++import net.minecraft.network.protocol.game.PacketPlayOutBoss; ++import net.minecraft.network.protocol.game.PacketPlayOutChat; ++import net.minecraft.network.protocol.game.PacketPlayOutKeepAlive; + import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; ++import net.minecraft.network.protocol.game.PacketPlayOutTabComplete; ++import net.minecraft.network.protocol.game.PacketPlayOutTitle; + import net.minecraft.server.CancelledPacketHandleException; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.network.LoginListener; + import net.minecraft.server.network.PlayerConnection; + import net.minecraft.util.LazyInitVar; +@@ -75,6 +82,10 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + public int protocolVersion; + public java.net.InetSocketAddress virtualHost; + private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); ++ // Optimize network ++ public boolean isPending = true; ++ public boolean queueImmunity = false; ++ public EnumProtocol protocol; + // Paper end + + public NetworkManager(EnumProtocolDirection enumprotocoldirection) { +@@ -98,6 +109,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } + + public void setProtocol(EnumProtocol enumprotocol) { ++ protocol = enumprotocol; // Paper + this.channel.attr(NetworkManager.c).set(enumprotocol); + this.channel.config().setAutoRead(true); + NetworkManager.LOGGER.debug("Enabled auto read"); +@@ -168,19 +180,84 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + Validate.notNull(packetlistener, "packetListener", new Object[0]); + this.packetListener = packetlistener; + } ++ // Paper start ++ public EntityPlayer getPlayer() { ++ if (packetListener instanceof PlayerConnection) { ++ return ((PlayerConnection) packetListener).player; ++ } else { ++ return null; ++ } ++ } ++ private static class InnerUtil { // Attempt to hide these methods from ProtocolLib so it doesn't accidently pick them up. ++ private static java.util.List buildExtraPackets(Packet packet) { ++ java.util.List extra = packet.getExtraPackets(); ++ if (extra == null || extra.isEmpty()) { ++ return null; ++ } ++ java.util.List ret = new java.util.ArrayList<>(1 + extra.size()); ++ buildExtraPackets0(extra, ret); ++ return ret; ++ } ++ ++ private static void buildExtraPackets0(java.util.List extraPackets, java.util.List into) { ++ for (Packet extra : extraPackets) { ++ into.add(extra); ++ java.util.List extraExtra = extra.getExtraPackets(); ++ if (extraExtra != null && !extraExtra.isEmpty()) { ++ buildExtraPackets0(extraExtra, into); ++ } ++ } ++ } ++ // Paper start ++ private static boolean canSendImmediate(NetworkManager networkManager, Packet packet) { ++ return networkManager.isPending || networkManager.protocol != EnumProtocol.PLAY || ++ packet instanceof PacketPlayOutKeepAlive || ++ packet instanceof PacketPlayOutChat || ++ packet instanceof PacketPlayOutTabComplete || ++ packet instanceof PacketPlayOutTitle || ++ packet instanceof PacketPlayOutBoss; ++ } ++ // Paper end ++ } ++ // Paper end + + public void sendPacket(Packet packet) { + this.sendPacket(packet, (GenericFutureListener) null); + } + + public void sendPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { +- if (this.isConnected()) { +- this.p(); +- this.b(packet, genericfuturelistener); +- } else { +- this.packetQueue.add(new NetworkManager.QueuedPacket(packet, genericfuturelistener)); ++ // Paper start - handle oversized packets better ++ boolean connected = this.isConnected(); ++ if (!connected && !preparing) { ++ return; // Do nothing ++ } ++ packet.onPacketDispatch(getPlayer()); ++ if (connected && (InnerUtil.canSendImmediate(this, packet) || ( ++ MCUtil.isMainThread() && packet.isReady() && this.packetQueue.isEmpty() && ++ (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) ++ ))) { ++ this.dispatchPacket(packet, genericfuturelistener); ++ return; + } ++ // write the packets to the queue, then flush - antixray hooks there already ++ java.util.List extraPackets = InnerUtil.buildExtraPackets(packet); ++ boolean hasExtraPackets = extraPackets != null && !extraPackets.isEmpty(); ++ if (!hasExtraPackets) { ++ this.packetQueue.add(new NetworkManager.QueuedPacket(packet, genericfuturelistener)); ++ } else { ++ java.util.List packets = new java.util.ArrayList<>(1 + extraPackets.size()); ++ packets.add(new NetworkManager.QueuedPacket(packet, null)); // delay the future listener until the end of the extra packets ++ ++ for (int i = 0, len = extraPackets.size(); i < len;) { ++ Packet extra = extraPackets.get(i); ++ boolean end = ++i == len; ++ packets.add(new NetworkManager.QueuedPacket(extra, end ? genericfuturelistener : null)); // append listener to the end ++ } + ++ this.packetQueue.addAll(packets); // atomic ++ } ++ this.sendPacketQueue(); ++ // Paper end + } + + private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER +@@ -194,51 +271,116 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + this.channel.config().setAutoRead(false); + } + ++ EntityPlayer player = getPlayer(); // Paper + if (this.channel.eventLoop().inEventLoop()) { + if (enumprotocol != enumprotocol1) { + this.setProtocol(enumprotocol); + } ++ // Paper start ++ if (!isConnected()) { ++ packet.onPacketDispatchFinish(player, null); ++ return; ++ } ++ try { ++ // Paper end + + ChannelFuture channelfuture = this.channel.writeAndFlush(packet); + + if (genericfuturelistener != null) { + channelfuture.addListener(genericfuturelistener); + } ++ // Paper start ++ if (packet.hasFinishListener()) { ++ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); ++ } ++ // Paper end + + channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); ++ // Paper start ++ } catch (Exception e) { ++ LOGGER.error("NetworkException: " + player, e); ++ close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; ++ packet.onPacketDispatchFinish(player, null); ++ } ++ // Paper end + } else { + this.channel.eventLoop().execute(() -> { + if (enumprotocol != enumprotocol1) { + this.setProtocol(enumprotocol); + } + ++ // Paper start ++ if (!isConnected()) { ++ packet.onPacketDispatchFinish(player, null); ++ return; ++ } ++ try { ++ // Paper end + ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet); + ++ + if (genericfuturelistener != null) { + channelfuture1.addListener(genericfuturelistener); + } ++ // Paper start ++ if (packet.hasFinishListener()) { ++ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); ++ } ++ // Paper end + + channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); ++ // Paper start ++ } catch (Exception e) { ++ LOGGER.error("NetworkException: " + player, e); ++ close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; ++ packet.onPacketDispatchFinish(player, null); ++ } ++ // Paper end + }); + } + + } + +- private void sendPacketQueue() { this.p(); } // Paper - OBFHELPER +- private void p() { +- if (this.channel != null && this.channel.isOpen()) { +- Queue queue = this.packetQueue; +- ++ // Paper start - rewrite this to be safer if ran off main thread ++ private boolean sendPacketQueue() { return this.p(); } // OBFHELPER // void -> boolean ++ private boolean p() { // void -> boolean ++ if (!isConnected()) { ++ return true; ++ } ++ if (MCUtil.isMainThread()) { ++ return processQueue(); ++ } else if (isPending) { ++ // Should only happen during login/status stages + synchronized (this.packetQueue) { +- NetworkManager.QueuedPacket networkmanager_queuedpacket; +- +- while ((networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.packetQueue.poll()) != null) { +- this.b(networkmanager_queuedpacket.a, networkmanager_queuedpacket.b); +- } ++ return this.processQueue(); ++ } ++ } ++ return false; ++ } ++ private boolean processQueue() { ++ if (this.packetQueue.isEmpty()) return true; ++ // If we are on main, we are safe here in that nothing else should be processing queue off main anymore ++ // But if we are not on main due to login/status, the parent is synchronized on packetQueue ++ java.util.Iterator iterator = this.packetQueue.iterator(); ++ while (iterator.hasNext()) { ++ NetworkManager.QueuedPacket queued = iterator.next(); // poll -> peek ++ ++ // Fix NPE (Spigot bug caused by handleDisconnection()) ++ if (queued == null) { ++ return true; ++ } + ++ Packet packet = queued.getPacket(); ++ if (!packet.isReady()) { ++ return false; ++ } else { ++ iterator.remove(); ++ this.dispatchPacket(packet, queued.getGenericFutureListener()); + } + } ++ return true; + } ++ // Paper end + + public void a() { + this.p(); +@@ -271,9 +413,21 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + return this.socketAddress; + } + ++ // Paper start ++ public void clearPacketQueue() { ++ EntityPlayer player = getPlayer(); ++ packetQueue.forEach(queuedPacket -> { ++ Packet packet = queuedPacket.getPacket(); ++ if (packet.hasFinishListener()) { ++ packet.onPacketDispatchFinish(player, null); ++ } ++ }); ++ packetQueue.clear(); ++ } // Paper end + public void close(IChatBaseComponent ichatbasecomponent) { + // Spigot Start + this.preparing = false; ++ clearPacketQueue(); // Paper + // Spigot End + if (this.channel.isOpen()) { + this.channel.close(); // We can't wait as this may be called from an event loop. +@@ -341,7 +495,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + public void handleDisconnection() { + if (this.channel != null && !this.channel.isOpen()) { + if (this.o) { +- NetworkManager.LOGGER.warn("handleDisconnection() called twice"); ++ //NetworkManager.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message + } else { + this.o = true; + if (this.k() != null) { +@@ -349,7 +503,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } else if (this.j() != null) { + this.j().a(new ChatMessage("multiplayer.disconnect.generic")); + } +- this.packetQueue.clear(); // Free up packet queue. ++ clearPacketQueue(); // Paper + // Paper start - Add PlayerConnectionCloseEvent + final PacketListener packetListener = this.j(); + if (packetListener instanceof PlayerConnection) { +diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java +index 0783b0777c8d7788bbf6780b464b709bf6dc2191..b644c91cecd8a347319dfe8c8923fd05919a9795 100644 +--- a/src/main/java/net/minecraft/network/protocol/Packet.java ++++ b/src/main/java/net/minecraft/network/protocol/Packet.java +@@ -1,5 +1,6 @@ + package net.minecraft.network.protocol; + ++import io.netty.channel.ChannelFuture; // Paper + import java.io.IOException; + import net.minecraft.network.PacketDataSerializer; + import net.minecraft.network.PacketListener; +@@ -13,6 +14,20 @@ public interface Packet { + void a(T t0); + + // Paper start ++ ++ /** ++ * @param player Null if not at PLAY stage yet ++ */ ++ default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} ++ ++ /** ++ * @param player Null if not at PLAY stage yet ++ * @param future Can be null if packet was cancelled ++ */ ++ default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} ++ default boolean hasFinishListener() { return false; } ++ default boolean isReady() { return true; } ++ default java.util.List getExtraPackets() { return null; } + default boolean packetTooLarge(NetworkManager manager) { + return false; + } +diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java +index d992cb5cd827e0fe655809e1088939cdad9c2301..dc362724ea0cc1b2f9d9ceffff483217b4356c40 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnection.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnection.java +@@ -16,6 +16,7 @@ import io.netty.channel.epoll.EpollServerSocketChannel; + import io.netty.channel.nio.NioEventLoopGroup; + import io.netty.channel.socket.ServerSocketChannel; + import io.netty.channel.socket.nio.NioServerSocketChannel; ++import io.netty.handler.flush.FlushConsolidationHandler; // Paper + import io.netty.handler.timeout.ReadTimeoutHandler; + import java.io.IOException; + import java.net.InetAddress; +@@ -54,10 +55,12 @@ public class ServerConnection { + private final List connectedChannels = Collections.synchronizedList(Lists.newArrayList()); + // Paper start - prevent blocking on adding a new network manager while the server is ticking + private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ private static final boolean disableFlushConsolidation = Boolean.getBoolean("Paper.disableFlushConsolidate"); // Paper + private void addPending() { + NetworkManager manager = null; + while ((manager = pending.poll()) != null) { + connectedChannels.add(manager); ++ manager.isPending = false; + } + } + // Paper end +@@ -92,6 +95,7 @@ public class ServerConnection { + ; + } + ++ if (!disableFlushConsolidation) channel.pipeline().addFirst(new FlushConsolidationHandler()); // Paper + channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyPingHandler(ServerConnection.this)).addLast("splitter", new PacketSplitter()).addLast("decoder", new PacketDecoder(EnumProtocolDirection.SERVERBOUND)).addLast("prepender", new PacketPrepender()).addLast("encoder", new PacketEncoder(EnumProtocolDirection.CLIENTBOUND)); + int j = ServerConnection.this.e.k(); + Object object = j > 0 ? new NetworkManagerServer(j) : new NetworkManager(EnumProtocolDirection.SERVERBOUND); diff --git a/patches/server-unmapped/0329-Handle-Oversized-Tile-Entities-in-chunks.patch b/patches/server-unmapped/0329-Handle-Oversized-Tile-Entities-in-chunks.patch new file mode 100644 index 0000000000..ee9073137c --- /dev/null +++ b/patches/server-unmapped/0329-Handle-Oversized-Tile-Entities-in-chunks.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 May 2020 05:00:57 -0400 +Subject: [PATCH] Handle Oversized Tile Entities in chunks + +Splits out Extra Packets if too many TE's are encountered to prevent +creating too large of a packet to sed. + +Co authored by Spottedleaf + +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java +index 0059ede4ba3ff271d47dd38ea87fddc2399aa008..a7d10d124021f3427f23fcd533f885367b64515c 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java +@@ -34,7 +34,15 @@ public class PacketPlayOutMapChunk implements Packet { + private boolean h; + + public PacketPlayOutMapChunk() {} ++ // Paper start ++ private final java.util.List extraPackets = new java.util.ArrayList<>(); ++ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); + ++ @Override ++ public java.util.List getExtraPackets() { ++ return extraPackets; ++ } ++ // Paper end + public PacketPlayOutMapChunk(Chunk chunk, int i) { + ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); + +@@ -61,6 +69,7 @@ public class PacketPlayOutMapChunk implements Packet { + this.c = this.a(new PacketDataSerializer(this.j()), chunk, i); + this.g = Lists.newArrayList(); + iterator = chunk.getTileEntities().entrySet().iterator(); ++ int totalTileEntities = 0; // Paper + + while (iterator.hasNext()) { + entry = (Entry) iterator.next(); +@@ -69,6 +78,15 @@ public class PacketPlayOutMapChunk implements Packet { + int j = blockposition.getY() >> 4; + + if (this.f() || (i & 1 << j) != 0) { ++ // Paper start - improve oversized chunk data packet handling ++ if (++totalTileEntities > TE_LIMIT) { ++ PacketPlayOutTileEntityData updatePacket = tileentity.getUpdatePacket(); ++ if (updatePacket != null) { ++ this.extraPackets.add(updatePacket); ++ continue; ++ } ++ } ++ // Paper end + NBTTagCompound nbttagcompound = tileentity.b(); + if (tileentity instanceof TileEntitySkull) { TileEntitySkull.sanitizeTileEntityUUID(nbttagcompound); } // Paper + diff --git a/patches/server-unmapped/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/patches/server-unmapped/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch new file mode 100644 index 0000000000..fe3dd5e8b2 --- /dev/null +++ b/patches/server-unmapped/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 2 Mar 2019 16:12:35 -0500 +Subject: [PATCH] MC-145260: Fix Whitelist On/Off inconsistency + +mojang stored whitelist state in 2 places (Whitelist Object, PlayerList) + +some things checked PlayerList, some checked object. This moves +everything to the Whitelist object. + +https://github.com/PaperMC/Paper/issues/1880 + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7515e9ddbc89de882373469cf3c46046c76af974..1a4ae92065f729ec521752bb87df8343d747f566 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -55,6 +55,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutViewDistance; + import net.minecraft.network.protocol.game.PacketPlayOutWorldBorder; + import net.minecraft.resources.ResourceKey; + import net.minecraft.server.AdvancementDataPlayer; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.ScoreboardServer; + import net.minecraft.server.level.DemoPlayerInteractManager; +@@ -1016,9 +1017,9 @@ public abstract class PlayerList { + } + public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { + boolean isOp = this.operators.d(gameprofile); +- boolean isWhitelisted = !this.hasWhitelist || isOp || this.whitelist.d(gameprofile); ++ boolean isWhitelisted = !this.getHasWhitelist() || isOp || this.whitelist.d(gameprofile); + final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; +- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.hasWhitelist, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); ++ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.getHasWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); + event.callEvent(); + if (!event.isWhitelisted()) { + if (loginEvent != null) { diff --git a/patches/server-unmapped/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/patches/server-unmapped/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch new file mode 100644 index 0000000000..30e7bd3924 --- /dev/null +++ b/patches/server-unmapped/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 4 Mar 2019 02:23:28 -0500 +Subject: [PATCH] Set Zombie last tick at start of drowning process + +Fixes GH-1887 + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index 79d34b0296f88e5b4fe0351fe2483fc0128deabc..f406826945dd752e6528743a0c8cad3cfdfc4a95 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -223,6 +223,7 @@ public class EntityZombie extends EntityMonster { + ++this.bt; + if (this.bt >= 600) { + this.startDrownedConversion(300); ++ this.lastTick = MinecraftServer.currentTick; // Paper - Make sure this is set at start of process - GH-1887 + } + } else { + this.bt = -1; diff --git a/patches/server-unmapped/0332-Allow-Saving-of-Oversized-Chunks.patch b/patches/server-unmapped/0332-Allow-Saving-of-Oversized-Chunks.patch new file mode 100644 index 0000000000..56fb7e5bc7 --- /dev/null +++ b/patches/server-unmapped/0332-Allow-Saving-of-Oversized-Chunks.patch @@ -0,0 +1,272 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 15 Feb 2019 01:08:19 -0500 +Subject: [PATCH] Allow Saving of Oversized Chunks + +The Minecraft World Region File format has a hard cap of 1MB per chunk. +This is due to the fact that the header of the file format only allocates +a single byte for sector count, meaning a maximum of 256 sectors, at 4k per sector. + +This limit can be reached fairly easily with books, resulting in the chunk being unable +to save to the world. Worse off, is that nothing printed when this occured, and silently +performed a chunk rollback on next load. + +This leads to security risk with duplication and is being actively exploited. + +This patch catches the too large scenario, falls back and moves any large Entity +or Tile Entity into a new compound, and this compound is saved into a different file. + +On Chunk Load, we check for oversized status, and if so, we load the extra file and +merge the Entities and Tile Entities from the oversized chunk back into the level to +then be loaded as normal. + +Once a chunk is returned back to normal size, the oversized flag will clear, and no +extra data file will exist. + +This fix maintains compatability with all existing Anvil Region Format tools as it +does not alter the save format. They will just not know about the extra entities. + +This fix also maintains compatability if someone switches server jars to one without +this fix, as the data will remain in the oversized file. Once the server returns +to a jar with this fix, the data will be restored. + +diff --git a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java +index 850d3a7bb8ae4c43c0e2f737cfe69261f338b026..20410a5853e34c90c872f5e9592d50c4727e914d 100644 +--- a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java ++++ b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java +@@ -132,6 +132,7 @@ public class NBTCompressedStreamTools { + + } + ++ public static NBTTagCompound readNBT(DataInput datainput) throws IOException { return a(datainput); } // Paper - OBFHELPER + public static NBTTagCompound a(DataInput datainput) throws IOException { + return a(datainput, NBTReadLimiter.a); + } +@@ -152,6 +153,7 @@ public class NBTCompressedStreamTools { + } + } + ++ public static void writeNBT(NBTTagCompound nbttagcompound, DataOutput dataoutput) throws IOException { a(nbttagcompound, dataoutput); } // Paper - OBFHELPER + public static void a(NBTTagCompound nbttagcompound, DataOutput dataoutput) throws IOException { + a((NBTBase) nbttagcompound, dataoutput); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 4bf3e0cb4602d33a2e00c502b1dd212032b22a8f..00cef1c0bc19976a000389e57a1af5d93690c0e7 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -20,8 +20,12 @@ import java.nio.file.LinkOption; + import java.nio.file.Path; + import java.nio.file.StandardCopyOption; + import java.nio.file.StandardOpenOption; ++import java.util.zip.InflaterInputStream; // Paper ++ + import javax.annotation.Nullable; + import net.minecraft.SystemUtils; ++import net.minecraft.nbt.NBTCompressedStreamTools; ++import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.world.level.ChunkCoordIntPair; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -38,6 +42,7 @@ public class RegionFile implements AutoCloseable { + private final IntBuffer i; + @VisibleForTesting + protected final RegionFileBitSet freeSectors; ++ public final File file; // Paper + + public RegionFile(File file, File file1, boolean flag) throws IOException { + this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag); +@@ -45,6 +50,8 @@ public class RegionFile implements AutoCloseable { + + public RegionFile(Path path, Path path1, RegionFileCompression regionfilecompression, boolean flag) throws IOException { + this.g = ByteBuffer.allocateDirect(8192); ++ this.file = path.toFile(); // Paper ++ initOversizedState(); // Paper + this.freeSectors = new RegionFileBitSet(); + this.f = regionfilecompression; + if (!Files.isDirectory(path1, new LinkOption[0])) { +@@ -408,6 +415,74 @@ public class RegionFile implements AutoCloseable { + void run() throws IOException; + } + ++ // Paper start ++ private final byte[] oversized = new byte[1024]; ++ private int oversizedCount = 0; ++ ++ private synchronized void initOversizedState() throws IOException { ++ File metaFile = getOversizedMetaFile(); ++ if (metaFile.exists()) { ++ final byte[] read = java.nio.file.Files.readAllBytes(metaFile.toPath()); ++ System.arraycopy(read, 0, oversized, 0, oversized.length); ++ for (byte temp : oversized) { ++ oversizedCount += temp; ++ } ++ } ++ } ++ ++ private static int getChunkIndex(int x, int z) { ++ return (x & 31) + (z & 31) * 32; ++ } ++ synchronized boolean isOversized(int x, int z) { ++ return this.oversized[getChunkIndex(x, z)] == 1; ++ } ++ synchronized void setOversized(int x, int z, boolean oversized) throws IOException { ++ final int offset = getChunkIndex(x, z); ++ boolean previous = this.oversized[offset] == 1; ++ this.oversized[offset] = (byte) (oversized ? 1 : 0); ++ if (!previous && oversized) { ++ oversizedCount++; ++ } else if (!oversized && previous) { ++ oversizedCount--; ++ } ++ if (previous && !oversized) { ++ File oversizedFile = getOversizedFile(x, z); ++ if (oversizedFile.exists()) { ++ oversizedFile.delete(); ++ } ++ } ++ if (oversizedCount > 0) { ++ if (previous != oversized) { ++ writeOversizedMeta(); ++ } ++ } else if (previous) { ++ File oversizedMetaFile = getOversizedMetaFile(); ++ if (oversizedMetaFile.exists()) { ++ oversizedMetaFile.delete(); ++ } ++ } ++ } ++ ++ private void writeOversizedMeta() throws IOException { ++ java.nio.file.Files.write(getOversizedMetaFile().toPath(), oversized); ++ } ++ ++ private File getOversizedMetaFile() { ++ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + ".oversized.nbt"); ++ } ++ ++ private File getOversizedFile(int x, int z) { ++ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); ++ } ++ ++ synchronized NBTTagCompound getOversizedData(int x, int z) throws IOException { ++ File file = getOversizedFile(x, z); ++ try (DataInputStream out = new DataInputStream(new BufferedInputStream(new InflaterInputStream(new java.io.FileInputStream(file))))) { ++ return NBTCompressedStreamTools.readNBT((java.io.DataInput) out); ++ } ++ ++ } ++ // Paper end + class ChunkBuffer extends ByteArrayOutputStream { + + private final ChunkCoordIntPair b; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +index 75b10a3755392870d8f5b51239a09a0e7fd75a42..ab9f4d40fd1126a3d7ba5b16fdc6ab09de4a7fdb 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +@@ -9,8 +9,10 @@ import java.io.DataOutputStream; + import java.io.File; + import java.io.IOException; + import javax.annotation.Nullable; ++import net.minecraft.nbt.NBTBase; + import net.minecraft.nbt.NBTCompressedStreamTools; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.nbt.NBTTagList; + import net.minecraft.server.MinecraftServer; + import net.minecraft.util.ExceptionSuppressor; + import net.minecraft.world.level.ChunkCoordIntPair; +@@ -50,6 +52,74 @@ public final class RegionFileCache implements AutoCloseable { + } + } + ++ // Paper start ++ private static void printOversizedLog(String msg, File file, int x, int z) { ++ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); ++ } ++ ++ private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 8; ++ private static final int OVERZEALOUS_TOTAL_THRESHOLD = 1024 * 64; ++ private static final int OVERZEALOUS_THRESHOLD = 1024; ++ private static int SIZE_THRESHOLD = DEFAULT_SIZE_THRESHOLD; ++ private static void resetFilterThresholds() { ++ SIZE_THRESHOLD = Math.max(1024 * 4, Integer.getInteger("Paper.FilterThreshhold", DEFAULT_SIZE_THRESHOLD)); ++ } ++ static { ++ resetFilterThresholds(); ++ } ++ ++ static boolean isOverzealous() { ++ return SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD; ++ } ++ ++ ++ private static NBTTagCompound readOversizedChunk(RegionFile regionfile, ChunkCoordIntPair chunkCoordinate) throws IOException { ++ synchronized (regionfile) { ++ try (DataInputStream datainputstream = regionfile.getReadStream(chunkCoordinate)) { ++ NBTTagCompound oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); ++ NBTTagCompound chunk = NBTCompressedStreamTools.readNBT((DataInput) datainputstream); ++ if (oversizedData == null) { ++ return chunk; ++ } ++ NBTTagCompound oversizedLevel = oversizedData.getCompound("Level"); ++ NBTTagCompound level = chunk.getCompound("Level"); ++ ++ mergeChunkList(level, oversizedLevel, "Entities"); ++ mergeChunkList(level, oversizedLevel, "TileEntities"); ++ ++ chunk.set("Level", level); ++ ++ return chunk; ++ } catch (Throwable throwable) { ++ throwable.printStackTrace(); ++ throw throwable; ++ } ++ } ++ } ++ ++ private static void mergeChunkList(NBTTagCompound level, NBTTagCompound oversizedLevel, String key) { ++ NBTTagList levelList = level.getList(key, 10); ++ NBTTagList oversizedList = oversizedLevel.getList(key, 10); ++ ++ if (!oversizedList.isEmpty()) { ++ levelList.addAll(oversizedList); ++ level.set(key, levelList); ++ } ++ } ++ ++ private static int getNBTSize(NBTBase nbtBase) { ++ DataOutputStream test = new DataOutputStream(new org.apache.commons.io.output.NullOutputStream()); ++ try { ++ nbtBase.write(test); ++ return test.size(); ++ } catch (IOException e) { ++ e.printStackTrace(); ++ return 0; ++ } ++ } ++ ++ // Paper End ++ + @Nullable + public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { + // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing +@@ -59,6 +129,12 @@ public final class RegionFileCache implements AutoCloseable { + } + // CraftBukkit end + DataInputStream datainputstream = regionfile.a(chunkcoordintpair); ++ // Paper start ++ if (regionfile.isOversized(chunkcoordintpair.x, chunkcoordintpair.z)) { ++ printOversizedLog("Loading Oversized Chunk!", regionfile.file, chunkcoordintpair.x, chunkcoordintpair.z); ++ return readOversizedChunk(regionfile, chunkcoordintpair); ++ } ++ // Paper end + Throwable throwable = null; + + NBTTagCompound nbttagcompound; +@@ -99,6 +175,7 @@ public final class RegionFileCache implements AutoCloseable { + + try { + NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream); ++ regionfile.setOversized(chunkcoordintpair.x, chunkcoordintpair.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone + } catch (Throwable throwable1) { + throwable = throwable1; + throw throwable1; diff --git a/patches/server-unmapped/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/patches/server-unmapped/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch new file mode 100644 index 0000000000..f3f9b1eb62 --- /dev/null +++ b/patches/server-unmapped/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Wed, 13 Mar 2019 20:08:09 +0200 +Subject: [PATCH] Call WhitelistToggleEvent when whitelist is toggled + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 1a4ae92065f729ec521752bb87df8343d747f566..1ae969aff1d44ad9af28fc94d8821884b9ad0563 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1135,6 +1135,7 @@ public abstract class PlayerList { + } + + public void setHasWhitelist(boolean flag) { ++ new com.destroystokyo.paper.event.server.WhitelistToggleEvent(flag).callEvent(); + this.hasWhitelist = flag; + } + diff --git a/patches/server-unmapped/0334-Add-LivingEntity-getTargetEntity.patch b/patches/server-unmapped/0334-Add-LivingEntity-getTargetEntity.patch new file mode 100644 index 0000000000..d372c84865 --- /dev/null +++ b/patches/server-unmapped/0334-Add-LivingEntity-getTargetEntity.patch @@ -0,0 +1,187 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 22 Sep 2018 00:33:08 -0500 +Subject: [PATCH] Add LivingEntity#getTargetEntity + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index af38b81df3f60163cafc341543ecad0865225943..413f715c98dc0a0953e60032ad1ebef2b0b3bbe3 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1504,6 +1504,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return this.c(f - 90.0F, f1); + } + ++ public final Vec3D getEyePosition(float partialTicks) { return j(partialTicks); } // Paper - OBFHELPER + public final Vec3D j(float f) { + if (f == 1.0F) { + return new Vec3D(this.locX(), this.getHeadY(), this.locZ()); +@@ -2154,6 +2155,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return this.getPassengers().size() < 1; + } + ++ public final float getCollisionBorderSize() { return bg(); } // Paper - OBFHELPER + public float bg() { + return 0.0F; + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 32a2d6fd22ba69694a2f620174f618a95964074d..4e2039e46741e8a09f3af7d3d9e98ef7a5b27abc 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -108,6 +108,7 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParameterSet + import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; + import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.MovingObjectPosition; ++import net.minecraft.world.phys.MovingObjectPositionEntity; + import net.minecraft.world.phys.Vec3D; + import net.minecraft.world.scores.ScoreboardTeam; + import org.apache.logging.log4j.Logger; +@@ -3660,6 +3661,37 @@ public abstract class EntityLiving extends Entity { + return world.rayTrace(raytrace); + } + ++ public MovingObjectPositionEntity getTargetEntity(int maxDistance) { ++ if (maxDistance < 1 || maxDistance > 120) { ++ throw new IllegalArgumentException("maxDistance must be between 1-120"); ++ } ++ ++ Vec3D start = this.getEyePosition(1.0F); ++ Vec3D direction = this.getLookDirection(); ++ Vec3D end = start.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance); ++ ++ List entityList = world.getEntities(this, getBoundingBox().expand(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance).grow(1.0D, 1.0D, 1.0D), IEntitySelector.canAITarget().and(Entity::isInteractable)); ++ ++ double distance = 0.0D; ++ MovingObjectPositionEntity result = null; ++ ++ for (Entity entity : entityList) { ++ AxisAlignedBB aabb = entity.getBoundingBox().grow((double) entity.getCollisionBorderSize()); ++ Optional rayTraceResult = aabb.calculateIntercept(start, end); ++ ++ if (rayTraceResult.isPresent()) { ++ Vec3D rayTrace = rayTraceResult.get(); ++ double distanceTo = start.distanceSquared(rayTrace); ++ if (distanceTo < distance || distance == 0.0D) { ++ result = new MovingObjectPositionEntity(entity, rayTrace); ++ distance = distanceTo; ++ } ++ } ++ } ++ ++ return result; ++ } ++ + public int shieldBlockingDelay = world.paperConfig.shieldBlockingDelay; + + public int getShieldBlockingDelay() { +diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +index 4776a47566aac487dc77fd6b4b9b42b95974e31a..cb5cda5e6497edeb801ef712f9bd8823cb055750 100644 +--- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +@@ -22,6 +22,7 @@ public final class IEntitySelector { + public static final Predicate e = (entity) -> { + return !(entity instanceof EntityHuman) || !entity.isSpectator() && !((EntityHuman) entity).isCreative(); + }; ++ public static Predicate canAITarget() { return f; } // Paper - OBFHELPER + public static final Predicate f = (entity) -> { + return !(entity instanceof EntityHuman) || !entity.isSpectator() && !((EntityHuman) entity).isCreative() && entity.world.getDifficulty() != EnumDifficulty.PEACEFUL; + }; +diff --git a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java +index 3941dd33da4b5c09d0087143f1d8a2d76fc18792..62513c812b497bb9d8dafe1d9c2f574059aebf15 100644 +--- a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java ++++ b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java +@@ -116,6 +116,7 @@ public class AxisAlignedBB { + return this.b(vec3d.x, vec3d.y, vec3d.z); + } + ++ public final AxisAlignedBB expand(double x, double y, double z) { return b(x, y, z); } // Paper - OBFHELPER + public AxisAlignedBB b(double d0, double d1, double d2) { + double d3 = this.minX; + double d4 = this.minY; +@@ -145,6 +146,12 @@ public class AxisAlignedBB { + return new AxisAlignedBB(d3, d4, d5, d6, d7, d8); + } + ++ // Paper start ++ public AxisAlignedBB grow(double d0) { ++ return grow(d0, d0, d0); ++ } ++ // Paper end ++ + public AxisAlignedBB grow(double d0, double d1, double d2) { + double d3 = this.minX - d0; + double d4 = this.minY - d1; +@@ -204,6 +211,7 @@ public class AxisAlignedBB { + return this.minX < d3 && this.maxX > d0 && this.minY < d4 && this.maxY > d1 && this.minZ < d5 && this.maxZ > d2; + } + ++ public final boolean contains(Vec3D vec3d) { return d(vec3d); } // Paper - OBFHELPER + public boolean d(Vec3D vec3d) { + return this.e(vec3d.x, vec3d.y, vec3d.z); + } +@@ -237,6 +245,7 @@ public class AxisAlignedBB { + return this.g(-d0); + } + ++ public final Optional calculateIntercept(Vec3D vec3d, Vec3D vec3d1) { return b(vec3d, vec3d1); } // Paper - OBFHELPER + public Optional b(Vec3D vec3d, Vec3D vec3d1) { + double[] adouble = new double[]{1.0D}; + double d0 = vec3d1.x - vec3d.x; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 194583522c53ae838dfc0ccfa49f906c1a628984..db5d9a8107babd42200f911d2b8ebdc15b4d7c8b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -1,6 +1,7 @@ + package org.bukkit.craftbukkit.entity; + + import com.destroystokyo.paper.block.TargetBlockInfo; ++import com.destroystokyo.paper.entity.TargetEntityInfo; + import com.google.common.base.Preconditions; + import com.google.common.collect.Sets; + import java.util.ArrayList; +@@ -42,8 +43,11 @@ import net.minecraft.world.entity.projectile.EntityThrownExpBottle; + import net.minecraft.world.entity.projectile.EntityThrownTrident; + import net.minecraft.world.entity.projectile.EntityTippedArrow; + import net.minecraft.world.entity.projectile.EntityWitherSkull; ++import net.minecraft.world.level.RayTrace; + import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionBlock; ++import net.minecraft.world.phys.MovingObjectPositionEntity; ++import net.minecraft.world.phys.Vec3D; + import org.apache.commons.lang.Validate; + import org.bukkit.FluidCollisionMode; + import org.bukkit.Location; +@@ -227,6 +231,33 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + new TargetBlockInfo(CraftBlock.at(getHandle().world, ((MovingObjectPositionBlock)rayTrace).getBlockPosition()), + MCUtil.toBukkitBlockFace(((MovingObjectPositionBlock)rayTrace).getDirection())); + } ++ ++ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks) { ++ MovingObjectPositionEntity rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); ++ return rayTrace == null ? null : rayTrace.getEntity().getBukkitEntity(); ++ } ++ ++ public TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks) { ++ MovingObjectPositionEntity rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); ++ return rayTrace == null ? null : new TargetEntityInfo(rayTrace.getEntity().getBukkitEntity(), new org.bukkit.util.Vector(rayTrace.getPos().x, rayTrace.getPos().y, rayTrace.getPos().z)); ++ } ++ ++ public MovingObjectPositionEntity rayTraceEntity(int maxDistance, boolean ignoreBlocks) { ++ MovingObjectPositionEntity rayTrace = getHandle().getTargetEntity(maxDistance); ++ if (rayTrace == null) { ++ return null; ++ } ++ if (!ignoreBlocks) { ++ MovingObjectPosition rayTraceBlocks = getHandle().getRayTrace(maxDistance, RayTrace.FluidCollisionOption.NONE); ++ if (rayTraceBlocks != null) { ++ Vec3D eye = getHandle().getEyePosition(1.0F); ++ if (eye.distanceSquared(rayTraceBlocks.getPos()) <= eye.distanceSquared(rayTrace.getPos())) { ++ return null; ++ } ++ } ++ } ++ return rayTrace; ++ } + // Paper end + + @Override diff --git a/patches/server-unmapped/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/patches/server-unmapped/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch new file mode 100644 index 0000000000..b9eefdc882 --- /dev/null +++ b/patches/server-unmapped/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 20 Mar 2019 21:19:29 -0700 +Subject: [PATCH] Use proper max length when serialising BungeeCord text + component + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java +index f6a1c5ac9acb34b1ef2262721adbbb1a5b0feaf7..fefcacf27d71c67403555502685a992a5a706099 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java +@@ -9,7 +9,7 @@ import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.network.protocol.Packet; + + public class PacketPlayOutChat implements Packet { +- ++ private static final int MAX_LENGTH = Short.MAX_VALUE * 8 + 8; // Paper + private IChatBaseComponent a; + public net.kyori.adventure.text.Component adventure$message; // Paper + public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot +@@ -43,9 +43,9 @@ public class PacketPlayOutChat implements Packet { + //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below + // Paper start - don't nest if we don't need to so that we can preserve formatting + if (this.components.length == 1) { +- packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); ++ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]), MAX_LENGTH); // Paper - use proper max length + } else { +- packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); ++ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components), MAX_LENGTH); // Paper - use proper max length + } + // Paper end + } else { diff --git a/patches/server-unmapped/0336-Entity-getEntitySpawnReason.patch b/patches/server-unmapped/0336-Entity-getEntitySpawnReason.patch new file mode 100644 index 0000000000..ff4a1a2635 --- /dev/null +++ b/patches/server-unmapped/0336-Entity-getEntitySpawnReason.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Mar 2019 00:24:52 -0400 +Subject: [PATCH] Entity#getEntitySpawnReason + +Allows you to return the SpawnReason for why an Entity Spawned + +Pre existing entities will return NATURAL if it was a non +persistenting Living Entity, SPAWNER for spawners, +or DEFAULT since data was not stored. + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index ecb4cb5df868673e5aa2eec3fdd8618dbea09655..d7c6f49ba1c84c45b387e155d9ae7452e5171df6 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1041,6 +1041,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + // CraftBukkit start + private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot ++ if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper + // Paper start + if (entity.valid) { + MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 1ae969aff1d44ad9af28fc94d8821884b9ad0563..47aa69dfe43390b811c264adc0af1d01bcd5ce4d 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -335,7 +335,7 @@ public abstract class PlayerList { + // CraftBukkit start + WorldServer finalWorldServer = worldserver1; + Entity entity = EntityTypes.a(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { +- return !finalWorldServer.addEntitySerialized(entity1) ? null : entity1; ++ return !finalWorldServer.addEntitySerialized(entity1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity1; // Paper + // CraftBukkit end + }); + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 413f715c98dc0a0953e60032ad1ebef2b0b3bbe3..712c81fe2cf6da6b80fea21fd6c3d0e0adc5a35a 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -63,6 +63,8 @@ import net.minecraft.world.EnumHand; + import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.INamableTileEntity; + import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.animal.EntityAnimal; ++import net.minecraft.world.entity.animal.EntityFish; + import net.minecraft.world.entity.item.EntityItem; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.vehicle.EntityBoat; +@@ -158,6 +160,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + }; + public List entitySlice = null; ++ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; + // Paper end + + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper +@@ -1674,6 +1677,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + nbttagcompound.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); + nbttagcompound.set("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); + } ++ if (spawnReason != null) { ++ nbttagcompound.setString("Paper.SpawnReason", spawnReason.name()); ++ } + // Save entity's from mob spawner status + if (spawnedViaMobSpawner) { + nbttagcompound.setBoolean("Paper.FromMobSpawner", true); +@@ -1812,6 +1818,26 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ if (nbttagcompound.hasKey("Paper.SpawnReason")) { ++ String spawnReasonName = nbttagcompound.getString("Paper.SpawnReason"); ++ try { ++ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName); ++ } catch (Exception ignored) { ++ LogManager.getLogger().error("Unknown SpawnReason " + spawnReasonName + " for " + this); ++ } ++ } ++ if (spawnReason == null) { ++ if (spawnedViaMobSpawner) { ++ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; ++ } else if (this instanceof EntityInsentient && (this instanceof EntityAnimal || this instanceof EntityFish) && !((EntityInsentient) this).isTypeNotPersistent(0.0)) { ++ if (!nbttagcompound.getBoolean("PersistenceRequired")) { ++ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL; ++ } ++ } ++ } ++ if (spawnReason == null) { ++ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; ++ } + // Paper end + + } catch (Throwable throwable) { +diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +index 867478484c0ba4ff467b96e458689937299b981d..34bcee4ff55ba118ba393e94b3c25ee2b84feaa2 100644 +--- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java ++++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +@@ -183,6 +183,7 @@ public abstract class MobSpawnerAbstract { + // Spigot End + } + entity.spawnedViaMobSpawner = true; // Paper ++ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper + flag = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 3642b17cafffd2818ee7a18d26bc25645f596115..93bbf63e9d38f32d5528c7693633d4b65655bb9d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1106,5 +1106,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public boolean fromMobSpawner() { + return getHandle().spawnedViaMobSpawner; + } ++ ++ @Override ++ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { ++ return getHandle().spawnReason; ++ } + // Paper end + } diff --git a/patches/server-unmapped/0337-Update-entity-Metadata-for-all-tracked-players.patch b/patches/server-unmapped/0337-Update-entity-Metadata-for-all-tracked-players.patch new file mode 100644 index 0000000000..8e4f0f1b36 --- /dev/null +++ b/patches/server-unmapped/0337-Update-entity-Metadata-for-all-tracked-players.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AgentTroll +Date: Fri, 22 Mar 2019 22:24:03 -0700 +Subject: [PATCH] Update entity Metadata for all tracked players + + +diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +index e3cdea3c85d762af6984f3dbe544fdfe101f6ff6..6110d7723b70df5380338a42b5cbff3446294bac 100644 +--- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java ++++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +@@ -421,6 +421,12 @@ public class EntityTrackerEntry { + return PacketPlayOutEntity.a(this.xLoc, this.yLoc, this.zLoc); + } + ++ // Paper start - Add broadcast method ++ void broadcast(Packet packet) { ++ this.getPacketConsumer().accept(packet); ++ } ++ // Paper end ++ + private void broadcastIncludingSelf(Packet packet) { + this.f.accept(packet); + if (this.tracker instanceof EntityPlayer) { +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index c0c9af81a933135e940587c10155a24cd399b922..d279c5673f1daf34914203ade0e893ea994fc607 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2288,7 +2288,14 @@ public class PlayerConnection implements PacketListenerPlayIn { + + if (event.isCancelled() || this.player.inventory.getItemInHand() == null || this.player.inventory.getItemInHand().getItem() != origItem) { + // Refresh the current entity metadata +- this.sendPacket(new PacketPlayOutEntityMetadata(entity.getId(), entity.getDataWatcher(), true)); ++ // Paper start - update entity for all players ++ PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entity.getId(), entity.getDataWatcher(), true); ++ if (entity.tracker != null) { ++ entity.tracker.broadcast(packet); ++ } else { ++ this.sendPacket(packet); ++ } ++ // Paper end + } + + if (event.isCancelled()) { diff --git a/patches/server-unmapped/0338-Implement-PlayerPostRespawnEvent.patch b/patches/server-unmapped/0338-Implement-PlayerPostRespawnEvent.patch new file mode 100644 index 0000000000..8a761d4f0c --- /dev/null +++ b/patches/server-unmapped/0338-Implement-PlayerPostRespawnEvent.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MisterVector +Date: Fri, 26 Oct 2018 21:31:00 -0700 +Subject: [PATCH] Implement PlayerPostRespawnEvent + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 47aa69dfe43390b811c264adc0af1d01bcd5ce4d..ec4e84f6275f8b305fb5a64f9c0cff24729d73ec 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -741,9 +741,14 @@ public abstract class PlayerList { + // this.a(entityplayer1, entityplayer, worldserver1); // CraftBukkit - removed + boolean flag2 = false; + ++ // Paper start ++ boolean isBedSpawn = false; ++ boolean isRespawn = false; ++ // Paper end ++ + // CraftBukkit start - fire PlayerRespawnEvent + if (location == null) { +- boolean isBedSpawn = false; ++ // boolean isBedSpawn = false; // Paper - moved up + WorldServer worldserver1 = this.server.getWorldServer(entityplayer.getSpawnDimension()); + if (worldserver1 != null) { + Optional optional; +@@ -794,6 +799,7 @@ public abstract class PlayerList { + + location = respawnEvent.getRespawnLocation(); + if (!flag) entityplayer.reset(); // SPIGOT-4785 ++ isRespawn = true; // Paper + } else { + location.setWorld(worldserver.getWorld()); + } +@@ -851,6 +857,13 @@ public abstract class PlayerList { + if (entityplayer.playerConnection.isDisconnected()) { + this.savePlayerFile(entityplayer); + } ++ ++ // Paper start ++ if (isRespawn) { ++ cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(entityplayer.getBukkitEntity(), location, isBedSpawn)); ++ } ++ // Paper end ++ + // CraftBukkit end + return entityplayer1; + } diff --git a/patches/server-unmapped/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/patches/server-unmapped/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch new file mode 100644 index 0000000000..f77a4f7db2 --- /dev/null +++ b/patches/server-unmapped/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Mar 2019 18:09:20 -0400 +Subject: [PATCH] don't go below 0 for pickupDelay, breaks picking up items + +vanilla checks for == 0 + +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index 4cfe3475fa913cd46116f13ea8ed9caf5372a41a..02e4d6891adc902f73ed349f15dae3a429bd283a 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -87,6 +87,7 @@ public class EntityItem extends Entity { + // CraftBukkit start - Use wall time for pickup and despawn timers + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; ++ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 + if (this.age != -32768) this.age += elapsedTicks; + this.lastTick = MinecraftServer.currentTick; + // CraftBukkit end +@@ -179,6 +180,7 @@ public class EntityItem extends Entity { + // CraftBukkit start - Use wall time for pickup and despawn timers + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; ++ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 + if (this.age != -32768) this.age += elapsedTicks; + this.lastTick = MinecraftServer.currentTick; + // CraftBukkit end diff --git a/patches/server-unmapped/0340-Server-Tick-Events.patch b/patches/server-unmapped/0340-Server-Tick-Events.patch new file mode 100644 index 0000000000..4d6df2d1b0 --- /dev/null +++ b/patches/server-unmapped/0340-Server-Tick-Events.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 27 Mar 2019 22:48:45 -0400 +Subject: [PATCH] Server Tick Events + +Fires event at start and end of a server tick + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 419448fe02b58e08c17795c903c945ad8a3ce1b5..fa7935cccb450ae5f782fec5ebe27275fe6dd510 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1239,6 +1239,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant +Date: Wed, 27 Mar 2019 23:01:33 -0400 +Subject: [PATCH] PlayerDeathEvent#getItemsToKeep + +Exposes a mutable array on items a player should keep on death + +Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4 + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 82f49078a91b6ac471d303bc68891d80e201bd1f..a15b119b24090ffc607bfc9003d5b95f3acf3b2f 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -695,6 +695,46 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + }); + } + ++ // Paper start - process inventory ++ private static void processKeep(org.bukkit.event.entity.PlayerDeathEvent event, NonNullList inv) { ++ List itemsToKeep = event.getItemsToKeep(); ++ if (inv == null) { ++ // remainder of items left in toKeep - plugin added stuff on death that wasn't in the initial loot? ++ if (!itemsToKeep.isEmpty()) { ++ for (org.bukkit.inventory.ItemStack itemStack : itemsToKeep) { ++ event.getEntity().getInventory().addItem(itemStack); ++ } ++ } ++ ++ return; ++ } ++ ++ for (int i = 0; i < inv.size(); ++i) { ++ ItemStack item = inv.get(i); ++ if (EnchantmentManager.shouldNotDrop(item) || itemsToKeep.isEmpty() || item.isEmpty()) { ++ inv.set(i, ItemStack.NULL_ITEM); ++ continue; ++ } ++ ++ final org.bukkit.inventory.ItemStack bukkitStack = item.getBukkitStack(); ++ boolean keep = false; ++ final Iterator iterator = itemsToKeep.iterator(); ++ while (iterator.hasNext()) { ++ final org.bukkit.inventory.ItemStack itemStack = iterator.next(); ++ if (bukkitStack.equals(itemStack)) { ++ iterator.remove(); ++ keep = true; ++ break; ++ } ++ } ++ ++ if (!keep) { ++ inv.set(i, ItemStack.NULL_ITEM); ++ } ++ } ++ } ++ // Paper end ++ + @Override + public void die(DamageSource damagesource) { + boolean flag = this.world.getGameRules().getBoolean(GameRules.SHOW_DEATH_MESSAGES); +@@ -778,7 +818,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.dropExperience(); + // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. + if (!event.getKeepInventory()) { +- this.inventory.clear(); ++ // Paper start - replace logic ++ for (NonNullList inv : this.inventory.getComponents()) { ++ processKeep(event, inv); ++ } ++ processKeep(event, null); ++ // Paper end + } + + this.setSpectatorTarget(this); // Remove spectated target diff --git a/patches/server-unmapped/0342-Optimize-Captured-TileEntity-Lookup.patch b/patches/server-unmapped/0342-Optimize-Captured-TileEntity-Lookup.patch new file mode 100644 index 0000000000..bcc3098364 --- /dev/null +++ b/patches/server-unmapped/0342-Optimize-Captured-TileEntity-Lookup.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 6 Apr 2019 10:16:48 -0400 +Subject: [PATCH] Optimize Captured TileEntity Lookup + +upstream was doing a containsKey/get pattern, and always doing it at that. +that scenario is only even valid if were in the middle of a block place. + +Optimize to check if the captured list even has values in it, and also to +just do a get call since the value can never be null. + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 3b5ddc083719608e944bdefa38e1fd3909e8e200..b6b9a471426ddf911a1f6bf38543c0304bfc31f6 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -968,12 +968,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return null; + } else { + // CraftBukkit start +- if (capturedTileEntities.containsKey(blockposition)) { +- return capturedTileEntities.get(blockposition); ++ TileEntity tileentity = null; // Paper ++ if (!capturedTileEntities.isEmpty() && (tileentity = capturedTileEntities.get(blockposition)) != null) { // Paper ++ return tileentity; // Paper + } + // CraftBukkit end + +- TileEntity tileentity = null; ++ //TileEntity tileentity = null; // Paper - move up + + if (this.tickingTileEntities) { + tileentity = this.E(blockposition); diff --git a/patches/server-unmapped/0343-Add-Heightmap-API.patch b/patches/server-unmapped/0343-Add-Heightmap-API.patch new file mode 100644 index 0000000000..f2e6c95731 --- /dev/null +++ b/patches/server-unmapped/0343-Add-Heightmap-API.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 1 Jan 2019 02:22:01 -0800 +Subject: [PATCH] Add Heightmap API + + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index b6b9a471426ddf911a1f6bf38543c0304bfc31f6..12ac3608736b45447afe6b0d35ead1441390be5e 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -670,8 +670,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + } + } + +- @Override +- public int a(HeightMap.Type heightmap_type, int i, int j) { ++ public final int getHighestBlockY(final HeightMap.Type heightmap, final int x, final int z) { return this.a(heightmap, x, z); } // Paper - OBFHELPER ++ @Override public int a(HeightMap.Type heightmap_type, int i, int j) { // Paper - OBFHELPER + int k; + + if (i >= -30000000 && j >= -30000000 && i < 30000000 && j < 30000000) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 95b4774b7696fa9711d7169d06a23c70364bfdb2..9e44b60843a6463951382cb66c93f1fab24e5e5d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -343,6 +343,29 @@ public class CraftWorld implements World { + return getHighestBlockYAt(x, z, org.bukkit.HeightMap.MOTION_BLOCKING); + } + ++ // Paper start - Implement heightmap api ++ @Override ++ public int getHighestBlockYAt(final int x, final int z, final com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { ++ this.getChunkAt(x >> 4, z >> 4); // heightmap will ret 0 on unloaded areas ++ ++ switch (heightmap) { ++ case LIGHT_BLOCKING: ++ throw new UnsupportedOperationException(); // TODO ++ //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z); ++ case ANY: ++ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.WORLD_SURFACE, x, z); ++ case SOLID: ++ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.OCEAN_FLOOR, x, z); ++ case SOLID_OR_LIQUID: ++ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.MOTION_BLOCKING, x, z); ++ case SOLID_OR_LIQUID_NO_LEAVES: ++ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, x, z); ++ default: ++ throw new UnsupportedOperationException(); ++ } ++ } ++ // Paper end ++ + @Override + public Location getSpawnLocation() { + BlockPosition spawn = world.getSpawn(); diff --git a/patches/server-unmapped/0344-Mob-Spawner-API-Enhancements.patch b/patches/server-unmapped/0344-Mob-Spawner-API-Enhancements.patch new file mode 100644 index 0000000000..37f6cfaac5 --- /dev/null +++ b/patches/server-unmapped/0344-Mob-Spawner-API-Enhancements.patch @@ -0,0 +1,140 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 19 Apr 2019 12:41:13 -0500 +Subject: [PATCH] Mob Spawner API Enhancements + + +diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +index 34bcee4ff55ba118ba393e94b3c25ee2b84feaa2..5538404456dfee42257fad9040fcc0fefdfc5fab 100644 +--- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java ++++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +@@ -65,6 +65,7 @@ public abstract class MobSpawnerAbstract { + this.mobs.clear(); // CraftBukkit - SPIGOT-3496, MC-92282 + } + ++ public boolean isActivated() { return h(); } // Paper - OBFHELPER + private boolean h() { + BlockPosition blockposition = this.b(); + +@@ -221,6 +222,7 @@ public abstract class MobSpawnerAbstract { + } + } + ++ public void resetTimer() { i(); } // Paper - OBFHELPER + private void i() { + if (this.maxSpawnDelay <= this.minSpawnDelay) { + this.spawnDelay = this.minSpawnDelay; +@@ -238,7 +240,13 @@ public abstract class MobSpawnerAbstract { + } + + public void a(NBTTagCompound nbttagcompound) { ++ // Paper start - use larger int if set ++ if (nbttagcompound.hasKey("Paper.Delay")) { ++ this.spawnDelay = nbttagcompound.getInt("Paper.Delay"); ++ } else { + this.spawnDelay = nbttagcompound.getShort("Delay"); ++ } ++ // Paper end + this.mobs.clear(); + if (nbttagcompound.hasKeyOfType("SpawnPotentials", 9)) { + NBTTagList nbttaglist = nbttagcompound.getList("SpawnPotentials", 10); +@@ -253,10 +261,15 @@ public abstract class MobSpawnerAbstract { + } else if (!this.mobs.isEmpty()) { + this.setSpawnData((MobSpawnerData) WeightedRandom.a(this.a().random, this.mobs)); + } +- ++ // Paper start - use ints if set ++ if (nbttagcompound.hasKeyOfType("Paper.MinSpawnDelay", 99)) { ++ this.minSpawnDelay = nbttagcompound.getInt("Paper.MinSpawnDelay"); ++ this.maxSpawnDelay = nbttagcompound.getInt("Paper.MaxSpawnDelay"); ++ this.spawnCount = nbttagcompound.getShort("SpawnCount"); ++ } else // Paper end + if (nbttagcompound.hasKeyOfType("MinSpawnDelay", 99)) { +- this.minSpawnDelay = nbttagcompound.getShort("MinSpawnDelay"); +- this.maxSpawnDelay = nbttagcompound.getShort("MaxSpawnDelay"); ++ this.minSpawnDelay = nbttagcompound.getInt("MinSpawnDelay"); ++ this.maxSpawnDelay = nbttagcompound.getInt("MaxSpawnDelay"); + this.spawnCount = nbttagcompound.getShort("SpawnCount"); + } + +@@ -281,9 +294,20 @@ public abstract class MobSpawnerAbstract { + if (minecraftkey == null) { + return nbttagcompound; + } else { +- nbttagcompound.setShort("Delay", (short) this.spawnDelay); +- nbttagcompound.setShort("MinSpawnDelay", (short) this.minSpawnDelay); +- nbttagcompound.setShort("MaxSpawnDelay", (short) this.maxSpawnDelay); ++ // Paper start ++ if (spawnDelay > Short.MAX_VALUE) { ++ nbttagcompound.setInt("Paper.Delay", this.spawnDelay); ++ } ++ nbttagcompound.setShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay)); ++ ++ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) { ++ nbttagcompound.setInt("Paper.MinSpawnDelay", this.minSpawnDelay); ++ nbttagcompound.setInt("Paper.MaxSpawnDelay", this.maxSpawnDelay); ++ } ++ ++ nbttagcompound.setShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay)); ++ nbttagcompound.setShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay)); ++ // Paper end + nbttagcompound.setShort("SpawnCount", (short) this.spawnCount); + nbttagcompound.setShort("MaxNearbyEntities", (short) this.maxNearbyEntities); + nbttagcompound.setShort("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 28295ebd338806a35cbef164cb014abfe7dae769..3d29be926e36b9a5a981eea1f2a1ec54a4c43393 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java +@@ -1,13 +1,21 @@ + package org.bukkit.craftbukkit.block; + + import com.google.common.base.Preconditions; ++import net.minecraft.core.IRegistry; ++import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.level.MobSpawnerData; + import net.minecraft.world.level.block.entity.TileEntityMobSpawner; + import org.bukkit.Material; + import org.bukkit.block.Block; + import org.bukkit.block.CreatureSpawner; + import org.bukkit.entity.EntityType; ++// Paper start ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.inventory.ItemStack; ++// Paper end + + public class CraftCreatureSpawner extends CraftBlockEntityState implements CreatureSpawner { + +@@ -121,4 +129,30 @@ public class CraftCreatureSpawner extends CraftBlockEntityState +Date: Mon, 6 May 2019 01:29:25 -0400 +Subject: [PATCH] Per-Player View Distance API placeholders + +I hope to look at this more in-depth soon. It appears doable. +However this should not block the update. + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +index 51993191e01f55e16667c25b8b57d6a6ddaf493b..5168a40eb53565bb3028efe559601acf72bddae5 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +@@ -625,9 +625,10 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + if (this.deathAnimationTicks == 1 && !this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1028, this.getChunkCoordinates(), 0); +- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API + for (net.minecraft.server.level.EntityPlayer player : (List) ((WorldServer)world).getPlayers()) { +- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch ++ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch ++ // Paper end + double deltaX = this.locX() - player.locX(); + double deltaZ = this.locZ() - player.locZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +index 145767e8b0fc4105a0afa47af17dcdbb75e952bc..174eb12722872182b2d9b54841e5bb57893695a1 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +@@ -258,9 +258,9 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + if (!this.isSilent()) { + // CraftBukkit start - Use relative location for far away sounds + // this.world.b(1023, new BlockPosition(this), 0); +- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API ++ int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API + for (EntityPlayer player : (List)this.world.getPlayers()) { +- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch ++ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch + double deltaX = this.locX() - player.locX(); + double deltaZ = this.locZ() - player.locZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index f57ad014fb3d2ce2405bdd63db4c730458aac17a..dc8545241ed62f6b654b2559e025c3b34c00575f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2243,6 +2243,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + super.remove(); + } + } ++ ++ @Override ++ public int getViewDistance() { ++ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO ++ } ++ ++ @Override ++ public void setViewDistance(int viewDistance) { ++ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO ++ } + // Paper end + + // Spigot start diff --git a/patches/server-unmapped/0346-Fix-CB-call-to-changed-postToMainThread-method.patch b/patches/server-unmapped/0346-Fix-CB-call-to-changed-postToMainThread-method.patch new file mode 100644 index 0000000000..66128f4cbe --- /dev/null +++ b/patches/server-unmapped/0346-Fix-CB-call-to-changed-postToMainThread-method.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Fri, 10 May 2019 18:38:19 +0100 +Subject: [PATCH] Fix CB call to changed postToMainThread method + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index d279c5673f1daf34914203ade0e893ea994fc607..c3a3837badb4b2a2ab51e6fb2d7cfbaa2f4d8edb 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -445,7 +445,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + + this.networkManager.getClass(); + // CraftBukkit - Don't wait +- minecraftserver.postToMainThread(networkmanager::handleDisconnection); ++ minecraftserver.scheduleOnMain(networkmanager::handleDisconnection); // Paper + } + + private void a(T t0, Consumer consumer, BiFunction>> bifunction) { diff --git a/patches/server-unmapped/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/patches/server-unmapped/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch new file mode 100644 index 0000000000..05a0bc0d4c --- /dev/null +++ b/patches/server-unmapped/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Sat, 27 Apr 2019 20:00:43 +0100 +Subject: [PATCH] Fix sounds when item frames are modified (MC-123450) + +This also fixes the adding sound playing when the item frame direction is changed. + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java +index 584f64946821092afab57b9409bc249403bc16e7..43152a6c70c9433d627a58051101530ddd693307 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java +@@ -277,7 +277,7 @@ public class EntityItemFrame extends EntityHanging { + } + + this.getDataWatcher().set(EntityItemFrame.ITEM, itemstack); +- if (!itemstack.isEmpty() && playSound) { // CraftBukkit ++ if (!itemstack.isEmpty() && flag && playSound) { // CraftBukkit // Paper - only play sound when update flag is set + this.playSound(SoundEffects.ENTITY_ITEM_FRAME_ADD_ITEM, 1.0F, 1.0F); + } + diff --git a/patches/server-unmapped/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/patches/server-unmapped/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch new file mode 100644 index 0000000000..0e8169316d --- /dev/null +++ b/patches/server-unmapped/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 13 May 2019 21:10:59 -0700 +Subject: [PATCH] Fix CraftServer#isPrimaryThread and MinecraftServer + isMainThread + +md_5 changed it so he could shut down the server asynchronously +from watchdog, although we have patches that prevent that type +of behavior for this exact reason. + +md_5 also placed code in PlayerConnectionUtils that would have +solved https://bugs.mojang.com/browse/MC-142590, making the change +to MinecraftServer#isMainThread irrelevant. +By reverting his change to MinecraftServer#isMainThread packet +handling that should have been handled synchronously will be handled +synchronously when the server gets shut down. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index fa7935cccb450ae5f782fec5ebe27275fe6dd510..5a5e097b131500d7cb9f61ea0f96f9006fabb941 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2192,7 +2192,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant +Date: Fri, 28 Sep 2018 21:49:53 -0400 +Subject: [PATCH] Fix issues with entity loss due to unloaded chunks + +Vanilla has risk of losing entities by causing them to be +removed from all chunks if they try to move into an unloaded chunk. + +This pretty much means high chance this entity will be lost in this +scenario. + +There is another case that adding an entity to the world can fail if +the chunk isn't loaded. + +Lots of the server is designed around addEntity never expecting to fail +for these reasons, nor is it really logical. + +This change ensures the chunks are always loaded when entities are +added to the world, or a valid entity moves between chunks. + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index d7c6f49ba1c84c45b387e155d9ae7452e5171df6..4e26db120e544d8867d895395241e425f23f575b 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -854,11 +854,18 @@ public class WorldServer extends World implements GeneratorAccessSeed { + int k = MathHelper.floor(entity.locZ() / 16.0D); + + if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) { ++ // Paper start - remove entity if its in a chunk more correctly. ++ Chunk currentChunk = entity.getCurrentChunk(); ++ if (currentChunk != null) { ++ currentChunk.removeEntity(entity); ++ } ++ // Paper end ++ + if (entity.inChunk && this.isChunkLoaded(entity.chunkX, entity.chunkZ)) { + this.getChunkAt(entity.chunkX, entity.chunkZ).a(entity, entity.chunkY); + } + +- if (!entity.ck() && !this.isChunkLoaded(i, k)) { ++ if (!entity.valid && !entity.ck() && !this.isChunkLoaded(i, k)) { // Paper - always load chunks to register valid entities location + if (entity.inChunk) { + WorldServer.LOGGER.warn("Entity {} left loaded chunk area", entity); + } +@@ -1073,7 +1080,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + return false; + } + // CraftBukkit end +- IChunkAccess ichunkaccess = this.getChunkAt(MathHelper.floor(entity.locX() / 16.0D), MathHelper.floor(entity.locZ() / 16.0D), ChunkStatus.FULL, entity.attachedToPlayer); ++ IChunkAccess ichunkaccess = this.getChunkAt(MathHelper.floor(entity.locX() / 16.0D), MathHelper.floor(entity.locZ() / 16.0D), ChunkStatus.FULL, true); // Paper - always load chunks for entity adds + + if (!(ichunkaccess instanceof Chunk)) { + return false; diff --git a/patches/server-unmapped/0350-Duplicate-UUID-Resolve-Option.patch b/patches/server-unmapped/0350-Duplicate-UUID-Resolve-Option.patch new file mode 100644 index 0000000000..3583743eaf --- /dev/null +++ b/patches/server-unmapped/0350-Duplicate-UUID-Resolve-Option.patch @@ -0,0 +1,249 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 21 Jul 2018 14:27:34 -0400 +Subject: [PATCH] Duplicate UUID Resolve Option + +Due to a bug in https://github.com/PaperMC/Paper/commit/2e29af3df05ec0a383f48be549d1c03200756d24 +which was added all the way back in March of 2016, it was unknown (potentially not at the time) +that an entity might actually change the seed of the random object. + +At some point, EntitySquid did start setting the seed. Due to this shared random, this caused +every entity to use a Random object with a predictable seed. + +This has caused entities to potentially generate with the same UUID.... + +Over the years, servers have had entities disappear, but no sign of trouble +because CraftBukkit removed the log lines indicating that something was wrong. + +We have fixed the root issue causing duplicate UUID's, however we now have chunk +files full of entities that have the same UUID as another entity! + +When these chunks load, the 2nd entity will not be added to the world correctly. + +If that chunk loads in a different order in the future, then it will reverse and the +missing one is now the one added to the world and not the other. This results in very +inconsistent entity behavior. + +This change allows you to recover any duplicate entity by generating a new UUID for it. +This also lets you delete them instead if you don't want to risk having new entities added to +the world that you previously did not see. + +But for those who are ok with leaving this inconsistent behavior, you may use WARN or NOTHING options. + +It is recommended you regenerate the entities, as these were legit entities, and deserve your love. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index fbf3ccfb347a5ba6e895339e9576629d940d1aa4..38d25a12c6a52d8a83214e2a0f43a218cf15ceac 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -401,4 +401,43 @@ public class PaperWorldConfig { + private void preventMovingIntoUnloadedChunks() { + preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); + } ++ ++ public enum DuplicateUUIDMode { ++ SAFE_REGEN, DELETE, NOTHING, WARN ++ } ++ public DuplicateUUIDMode duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; ++ public int duplicateUUIDDeleteRange = 32; ++ private void repairDuplicateUUID() { ++ String desiredMode = getString("duplicate-uuid-resolver", "saferegen").toLowerCase().trim(); ++ duplicateUUIDDeleteRange = getInt("duplicate-uuid-saferegen-delete-range", duplicateUUIDDeleteRange); ++ switch (desiredMode.toLowerCase()) { ++ case "regen": ++ case "regenerate": ++ case "saferegen": ++ case "saferegenerate": ++ duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; ++ log("Duplicate UUID Resolve: Regenerate New UUID if distant (Delete likely duplicates within " + duplicateUUIDDeleteRange + " blocks)"); ++ break; ++ case "remove": ++ case "delete": ++ duplicateUUIDMode = DuplicateUUIDMode.DELETE; ++ log("Duplicate UUID Resolve: Delete Entity"); ++ break; ++ case "silent": ++ case "nothing": ++ duplicateUUIDMode = DuplicateUUIDMode.NOTHING; ++ logError("Duplicate UUID Resolve: Do Nothing (no logs) - Warning, may lose indication of bad things happening"); ++ break; ++ case "log": ++ case "warn": ++ duplicateUUIDMode = DuplicateUUIDMode.WARN; ++ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); ++ break; ++ default: ++ duplicateUUIDMode = DuplicateUUIDMode.WARN; ++ logError("Warning: Invalid duplicate-uuid-resolver config " + desiredMode + " - must be one of: regen, delete, nothing, warn"); ++ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); ++ break; ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 66c808244bba70f827d8f15a96814251d352a046..b736917891afb17e412f94c5d8713aa653b8dc46 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -1,6 +1,7 @@ + package net.minecraft.server.level; + + import co.aikar.timings.Timing; // Paper ++import com.destroystokyo.paper.PaperWorldConfig; // Paper + import com.google.common.collect.ImmutableList; + import com.google.common.collect.Iterables; + import com.google.common.collect.ComparisonChain; // Paper +@@ -23,14 +24,17 @@ import it.unimi.dsi.fastutil.objects.ObjectIterator; + import java.io.File; + import java.io.IOException; + import java.io.Writer; ++import java.util.HashMap; // Paper + import java.util.Collection; + import java.util.Iterator; + import java.util.List; ++import java.util.Map; // Paper + import java.util.Objects; + import java.util.Optional; + import java.util.Queue; + import java.util.Set; + import java.util.concurrent.CancellationException; ++import java.util.UUID; // Paper + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.CompletionException; + import java.util.concurrent.Executor; +@@ -73,6 +77,7 @@ import net.minecraft.world.entity.boss.EntityComplexPart; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.GameRules; ++import net.minecraft.world.level.World; + import net.minecraft.world.level.chunk.Chunk; + import net.minecraft.world.level.chunk.ChunkConverter; + import net.minecraft.world.level.chunk.ChunkGenerator; +@@ -699,18 +704,18 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + if (chunk.needsDecoration) { + net.minecraft.server.dedicated.DedicatedServer server = this.world.getServer().getServer(); + if (!server.getSpawnNPCs() && entity instanceof net.minecraft.world.entity.npc.NPC) { +- entity.die(); ++ entity.dead = true; // Paper + needsRemoval = true; + } + + if (!server.getSpawnAnimals() && (entity instanceof net.minecraft.world.entity.animal.EntityAnimal || entity instanceof net.minecraft.world.entity.animal.EntityWaterAnimal)) { +- entity.die(); ++ entity.dead = true; // Paper + needsRemoval = true; + } + } +- +- if (!(entity instanceof EntityHuman) && (needsRemoval || !this.world.addEntityChunk(entity))) { +- // CraftBukkit end ++ // CraftBukkit end ++ checkDupeUUID(entity); // Paper ++ if (!(entity instanceof EntityHuman) && (entity.dead || !this.world.addEntityChunk(entity))) { // Paper + if (list == null) { + list = Lists.newArrayList(new Entity[]{entity}); + } else { +@@ -737,6 +742,44 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + }); + } + ++ // Paper start ++ private void checkDupeUUID(Entity entity) { ++ PaperWorldConfig.DuplicateUUIDMode mode = world.paperConfig.duplicateUUIDMode; ++ if (mode != PaperWorldConfig.DuplicateUUIDMode.WARN ++ && mode != PaperWorldConfig.DuplicateUUIDMode.DELETE ++ && mode != PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN) { ++ return; ++ } ++ Entity other = world.getEntity(entity.getUniqueID()); ++ ++ if (mode == PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN && other != null && !other.dead ++ && Objects.equals(other.getSaveID(), entity.getSaveID()) ++ && entity.getBukkitEntity().getLocation().distance(other.getBukkitEntity().getLocation()) < world.paperConfig.duplicateUUIDDeleteRange ++ ) { ++ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + " because it was near the duplicate and likely an actual duplicate. See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ entity.dead = true; ++ return; ++ } ++ if (other != null && !other.dead) { ++ switch (mode) { ++ case SAFE_REGEN: { ++ entity.setUUID(UUID.randomUUID()); ++ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", regenerated UUID for " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ break; ++ } ++ case DELETE: { ++ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ entity.dead = true; ++ break; ++ } ++ default: ++ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", doing nothing to " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); ++ break; ++ } ++ } ++ } ++ // Paper end ++ + public CompletableFuture> a(PlayerChunk playerchunk) { + ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); + CompletableFuture, PlayerChunk.Failure>> completablefuture = this.a(chunkcoordintpair, 1, (i) -> { +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 4e26db120e544d8867d895395241e425f23f575b..fbff779fa581a661cc03850bffa0da346ce15625 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -4,6 +4,8 @@ import com.google.common.annotations.VisibleForTesting; + import com.google.common.collect.Iterables; + import co.aikar.timings.TimingHistory; // Paper + import co.aikar.timings.Timings; // Paper ++ ++import com.destroystokyo.paper.PaperWorldConfig; // Paper + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Queues; +@@ -1108,7 +1110,22 @@ public class WorldServer extends World implements GeneratorAccessSeed { + if (entity1 == null) { + return false; + } else { ++ // Paper start ++ if (entity1.dead) { ++ unregisterEntity(entity1); // remove the existing entity ++ return false; ++ } ++ // Paper end + WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit // Paper ++ // Paper start ++ if (DEBUG_ENTITIES && entity.world.paperConfig.duplicateUUIDMode != PaperWorldConfig.DuplicateUUIDMode.NOTHING) { ++ if (entity1.addedToWorldStack != null) { ++ entity1.addedToWorldStack.printStackTrace(); ++ } ++ ++ getAddToWorldStackTrace(entity).printStackTrace(); ++ } ++ // Paper end + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 712c81fe2cf6da6b80fea21fd6c3d0e0adc5a35a..efa8d9a16e87475adf7e71a0dfa2861653f73c06 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2804,6 +2804,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + }); + } + ++ public final void setUUID(UUID uuid) { a_(uuid); } // Paper - OBFHELPER + public void a_(UUID uuid) { + this.uniqueID = uuid; + this.ae = this.uniqueID.toString(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index 79ff96f18c53f3d1ce4a00be2e2d8fe68f77bf54..3f926ed8e2b2c9dbf1e2493870af7eff3b6db019 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -542,6 +542,7 @@ public class Chunk implements IChunkAccess { + if (i != this.loc.x || j != this.loc.z) { + Chunk.LOGGER.warn("Wrong location! ({}, {}) should be ({}, {}), {}", i, j, this.loc.x, this.loc.z, entity); + entity.dead = true; ++ return; // Paper + } + + int k = MathHelper.floor(entity.locY() / 16.0D); diff --git a/patches/server-unmapped/0351-improve-CraftWorld-isChunkLoaded.patch b/patches/server-unmapped/0351-improve-CraftWorld-isChunkLoaded.patch new file mode 100644 index 0000000000..111ce24a81 --- /dev/null +++ b/patches/server-unmapped/0351-improve-CraftWorld-isChunkLoaded.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 21 May 2019 02:34:04 +0100 +Subject: [PATCH] improve CraftWorld#isChunkLoaded + +getChunkAt will request the chunk using vanillas chunk loading system, +which while we're not going to load the chunk, does involve the server +waiting for the execution queue to get to our request; We can just query +the chunk status and get a response now, vs having to wait + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 9e44b60843a6463951382cb66c93f1fab24e5e5d..5a5f920954effbe549cacdaa39474989dc98ad75 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -414,13 +414,13 @@ public class CraftWorld implements World { + + @Override + public boolean isChunkLoaded(int x, int z) { +- return world.getChunkProvider().isChunkLoaded(x, z); ++ return world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z) != null; // Paper + } + + @Override + public boolean isChunkGenerated(int x, int z) { + try { +- return isChunkLoaded(x, z) || world.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)) != null; ++ return world.getChunkProvider().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)) != null; // Paper (TODO check if the first part can be removed) + } catch (IOException ex) { + throw new RuntimeException(ex); + } diff --git a/patches/server-unmapped/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server-unmapped/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch new file mode 100644 index 0000000000..aedba49bc7 --- /dev/null +++ b/patches/server-unmapped/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -0,0 +1,261 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 13 Sep 2014 23:14:43 -0400 +Subject: [PATCH] Configurable Keep Spawn Loaded range per world + +This lets you disable it for some worlds and lower it for others. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 38d25a12c6a52d8a83214e2a0f43a218cf15ceac..ffe9b1a63d78925e1d77b9e730aef42fed6d58fa 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -440,4 +440,10 @@ public class PaperWorldConfig { + break; + } + } ++ ++ public short keepLoadedRange; ++ private void keepLoadedRange() { ++ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); ++ log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 5a5e097b131500d7cb9f61ea0f96f9006fabb941..aa2f4958fff659ef6b166b4644c81b5f1d8200a8 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -718,35 +718,36 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant> 4).forEach(pair -> { ++ getChunkProvider().getChunkAtMainThread(pair.x, pair.z); ++ }); ++ } ++ public void removeTicketsForSpawn(int radiusInBlocks, BlockPosition spawn) { ++ // In order to respect vanilla behavior, which is ensuring everything but the spawn border can tick, we added tickets ++ // with level 31 for the non-border spawn chunks ++ ChunkProviderServer chunkproviderserver = this.getChunkProvider(); ++ int tickRadius = radiusInBlocks - 16; ++ ++ // remove ticking chunks ++ for (int x = -tickRadius; x <= tickRadius; x += 16) { ++ for (int z = -tickRadius; z <= tickRadius; z += 16) { ++ // radius of 2 will have the current chunk be level 31 ++ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, z)), 2, Unit.INSTANCE); ++ } ++ } ++ ++ // remove border chunks ++ ++ // remove border along x axis (including corner chunks) ++ for (int x = -radiusInBlocks; x <= radiusInBlocks; x += 16) { ++ // top ++ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32 ++ // bottom ++ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, -radiusInBlocks)), 1, Unit.INSTANCE); // level 32 ++ } ++ ++ // remove border along z axis (excluding corner chunks) ++ for (int z = -radiusInBlocks + 16; z < radiusInBlocks; z += 16) { ++ // right ++ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 ++ // left ++ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 ++ } ++ } ++ // Paper end ++ + public void a(BlockPosition blockposition, float f) { +- ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); ++ // Paper - configurable spawn radius ++ BlockPosition prevSpawn = this.getSpawn(); ++ //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); + + this.worldData.setSpawn(blockposition, f); +- this.getChunkProvider().removeTicket(TicketType.START, chunkcoordintpair, 11, Unit.INSTANCE); +- this.getChunkProvider().addTicket(TicketType.START, new ChunkCoordIntPair(blockposition), 11, Unit.INSTANCE); ++ if (this.keepSpawnInMemory) { ++ // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add ++ this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); ++ this.addTicketsForSpawn(this.paperConfig.keepLoadedRange, blockposition); ++ } + this.getMinecraftServer().getPlayerList().sendAll(new PacketPlayOutSpawnPosition(blockposition, f)); + } + +diff --git a/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java b/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java +index de011b5e3a5e751160b4d3b65b50f28e6c6a5f52..4d9c167a41366779dbfb5ded6ea0115ffbf06ed7 100644 +--- a/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java ++++ b/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java +@@ -11,4 +11,6 @@ public interface WorldLoadListener { + void a(ChunkCoordIntPair chunkcoordintpair, @Nullable ChunkStatus chunkstatus); + + void b(); ++ ++ void setChunkRadius(int radius); // Paper - allow changing chunk radius + } +diff --git a/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java b/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java +index 872d00de41533ab7f4b43874de6c1747022e2ac5..ca81664d884e80e5cb1eb376a2c2ef1e017f16c0 100644 +--- a/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java ++++ b/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java +@@ -12,16 +12,24 @@ import org.apache.logging.log4j.Logger; + public class WorldLoadListenerLogger implements WorldLoadListener { + + private static final Logger LOGGER = LogManager.getLogger(); +- private final int b; ++ private int b; // Paper - remove final + private int c; + private long d; + private long e = Long.MAX_VALUE; + + public WorldLoadListenerLogger(int i) { +- int j = i * 2 + 1; ++ // Paper start - Allow changing radius later for configurable spawn patch ++ this.setChunkRadius(i); // Move to method ++ } ++ ++ @Override ++ public void setChunkRadius(int radius) { ++ // Paper - copied from above ++ int j = radius * 2 + 1; + + this.b = j * j; + } ++ // Paper end + + @Override + public void a(ChunkCoordIntPair chunkcoordintpair) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 5a5f920954effbe549cacdaa39474989dc98ad75..ec9f9fdf1be4f1e68eea5554a6721efd11a53958 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1972,15 +1972,21 @@ public class CraftWorld implements World { + + @Override + public void setKeepSpawnInMemory(boolean keepLoaded) { ++ // Paper start - Configurable spawn radius ++ if (keepLoaded == world.keepSpawnInMemory) { ++ // do nothing, nothing has changed ++ return; ++ } + world.keepSpawnInMemory = keepLoaded; + // Grab the worlds spawn chunk +- BlockPosition chunkcoordinates = this.world.getSpawn(); ++ BlockPosition prevSpawn = this.world.getSpawn(); + if (keepLoaded) { +- world.getChunkProvider().addTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE); ++ world.addTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); + } else { +- // TODO: doesn't work well if spawn changed.... +- world.getChunkProvider().removeTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE); ++ // TODO: doesn't work well if spawn changed.... // paper - resolved ++ world.removeTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); + } ++ // Paper end + } + + @Override diff --git a/patches/server-unmapped/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch b/patches/server-unmapped/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch new file mode 100644 index 0000000000..be4c0838f1 --- /dev/null +++ b/patches/server-unmapped/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Mon, 27 May 2019 17:35:39 -0500 +Subject: [PATCH] MC-114618 - Fix EntityAreaEffectCloud from going negative + size + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java +index 47099ecd70e5077cad8372446d54e28398785bec..679dfe75ea68e38679cd7d6348d0e24ca61911e4 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java ++++ b/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java +@@ -196,6 +196,12 @@ public class EntityAreaEffectCloud extends Entity { + super.tick(); + boolean flag = this.k(); + float f = this.getRadius(); ++ // Paper start - fix MC-114618 ++ if (f < 0.0F) { ++ this.die(); ++ return; ++ } ++ // Paper end + + if (this.world.isClientSide) { + ParticleParam particleparam = this.getParticle(); diff --git a/patches/server-unmapped/0354-ChunkMapDistance-CME.patch b/patches/server-unmapped/0354-ChunkMapDistance-CME.patch new file mode 100644 index 0000000000..148847522f --- /dev/null +++ b/patches/server-unmapped/0354-ChunkMapDistance-CME.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Wed, 29 May 2019 04:01:22 +0100 +Subject: [PATCH] ChunkMapDistance CME + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +index 6ef404ee29ddc79aeca534a58ec182e0e8b1b6c8..961257ebc28a8b4753faf3c2d5b6abaea4ffc0dd 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +@@ -39,7 +39,16 @@ public abstract class ChunkMapDistance { + private final ChunkMapDistance.a ticketLevelTracker = new ChunkMapDistance.a(); + private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); + private final ChunkMapDistance.c g = new ChunkMapDistance.c(33); +- private final Set pendingChunkUpdates = Sets.newHashSet(); ++ // Paper start use a queue, but still keep unique requirement ++ public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { ++ @Override ++ public boolean add(PlayerChunk o) { ++ if (o.isUpdateQueued) return true; ++ o.isUpdateQueued = true; ++ return super.add(o); ++ } ++ }; ++ // Paper end + private final ChunkTaskQueueSorter i; + private final Mailbox> j; + private final Mailbox k; +@@ -100,26 +109,14 @@ public abstract class ChunkMapDistance { + ; + } + ++ // Paper start + if (!this.pendingChunkUpdates.isEmpty()) { +- // CraftBukkit start +- // Iterate pending chunk updates with protection against concurrent modification exceptions +- java.util.Iterator iter = this.pendingChunkUpdates.iterator(); +- int expectedSize = this.pendingChunkUpdates.size(); +- do { +- PlayerChunk playerchunk = iter.next(); +- iter.remove(); +- expectedSize--; +- +- playerchunk.a(playerchunkmap); +- +- // Reset iterator if set was modified using add() +- if (this.pendingChunkUpdates.size() != expectedSize) { +- expectedSize = this.pendingChunkUpdates.size(); +- iter = this.pendingChunkUpdates.iterator(); +- } +- } while (iter.hasNext()); +- // CraftBukkit end +- ++ while(!this.pendingChunkUpdates.isEmpty()) { ++ PlayerChunk remove = this.pendingChunkUpdates.remove(); ++ remove.isUpdateQueued = false; ++ remove.a(playerchunkmap); ++ } ++ // Paper end + return true; + } else { + if (!this.l.isEmpty()) { +@@ -373,7 +370,7 @@ public abstract class ChunkMapDistance { + ObjectIterator objectiterator = this.a.long2ByteEntrySet().iterator(); + + while (objectiterator.hasNext()) { +- it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); ++ Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix + byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); + long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index 7dea5e783ce2a1f8ddd2b3ab7a19e03a56c36ba1..2c3d9a5d118cc4f3b5e78daf943911bb7386488a 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -45,6 +45,7 @@ public class PlayerChunk { + private static final CompletableFuture> UNLOADED_CHUNK_FUTURE = CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK); + private static final List CHUNK_STATUSES = ChunkStatus.a(); + private static final PlayerChunk.State[] CHUNK_STATES = PlayerChunk.State.values(); ++ boolean isUpdateQueued = false; // Paper + private final AtomicReferenceArray>> statusFutures; + private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage + private volatile CompletableFuture> tickingFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage diff --git a/patches/server-unmapped/0355-Implement-CraftBlockSoundGroup.patch b/patches/server-unmapped/0355-Implement-CraftBlockSoundGroup.patch new file mode 100644 index 0000000000..722e63e63a --- /dev/null +++ b/patches/server-unmapped/0355-Implement-CraftBlockSoundGroup.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: simpleauthority +Date: Tue, 28 May 2019 03:48:51 -0700 +Subject: [PATCH] Implement CraftBlockSoundGroup + + +diff --git a/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..34b3b858f616c4a1f877e6e58d315de2d8ff0720 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java +@@ -0,0 +1,38 @@ ++package com.destroystokyo.paper.block; ++ ++import net.minecraft.world.level.block.SoundEffectType; ++import org.bukkit.Sound; ++import org.bukkit.craftbukkit.CraftSound; ++ ++public class CraftBlockSoundGroup implements BlockSoundGroup { ++ private final SoundEffectType soundEffectType; ++ ++ public CraftBlockSoundGroup(SoundEffectType soundEffectType) { ++ this.soundEffectType = soundEffectType; ++ } ++ ++ @Override ++ public Sound getBreakSound() { ++ return CraftSound.getBukkit(soundEffectType.getBreakSound()); ++ } ++ ++ @Override ++ public Sound getStepSound() { ++ return CraftSound.getBukkit(soundEffectType.getStepSound()); ++ } ++ ++ @Override ++ public Sound getPlaceSound() { ++ return CraftSound.getBukkit(soundEffectType.getPlaceSound()); ++ } ++ ++ @Override ++ public Sound getHitSound() { ++ return CraftSound.getBukkit(soundEffectType.getHitSound()); ++ } ++ ++ @Override ++ public Sound getFallSound() { ++ return CraftSound.getBukkit(soundEffectType.getFallSound()); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/level/block/SoundEffectType.java b/src/main/java/net/minecraft/world/level/block/SoundEffectType.java +index 0987b25ac586d5d7b7954256c740fdf736498dae..b2a52c6bad5a83f34188b8f3db18c61ff9f52869 100644 +--- a/src/main/java/net/minecraft/world/level/block/SoundEffectType.java ++++ b/src/main/java/net/minecraft/world/level/block/SoundEffectType.java +@@ -54,10 +54,10 @@ public class SoundEffectType { + public static final SoundEffectType U = new SoundEffectType(1.0F, 1.0F, SoundEffects.BLOCK_GILDED_BLACKSTONE_BREAK, SoundEffects.BLOCK_GILDED_BLACKSTONE_STEP, SoundEffects.BLOCK_GILDED_BLACKSTONE_PLACE, SoundEffects.BLOCK_GILDED_BLACKSTONE_HIT, SoundEffects.BLOCK_GILDED_BLACKSTONE_FALL); + public final float volume; + public final float pitch; +- public final SoundEffect breakSound; ++ public final SoundEffect breakSound; public final SoundEffect getBreakSound() { return this.breakSound; } // Paper - OBFHELPER // PAIL private -> public, rename breakSound + private final SoundEffect stepSound; + private final SoundEffect placeSound; +- public final SoundEffect hitSound; ++ public final SoundEffect hitSound; public final SoundEffect getHitSound() { return this.hitSound; } // Paper - OBFHELPER // PAIL private -> public, rename hitSound + private final SoundEffect fallSound; + + public SoundEffectType(float f, float f1, SoundEffect soundeffect, SoundEffect soundeffect1, SoundEffect soundeffect2, SoundEffect soundeffect3, SoundEffect soundeffect4) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 8a6d8f21937ce7e2ac4623a3083421ed5ef9aa63..724b230259b1b44bc9fdde6c4fcbcdde5f690e05 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -750,4 +750,11 @@ public class CraftBlock implements Block { + AxisAlignedBB aabb = shape.getBoundingBox(); + return new BoundingBox(getX() + aabb.minX, getY() + aabb.minY, getZ() + aabb.minZ, getX() + aabb.maxX, getY() + aabb.maxY, getZ() + aabb.maxZ); + } ++ ++ // Paper start ++ @Override ++ public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { ++ return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().getBlockData().getStepSound()); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0356-Chunk-debug-command.patch b/patches/server-unmapped/0356-Chunk-debug-command.patch new file mode 100644 index 0000000000..bb3f023d4a --- /dev/null +++ b/patches/server-unmapped/0356-Chunk-debug-command.patch @@ -0,0 +1,486 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 1 Jun 2019 13:00:55 -0700 +Subject: [PATCH] Chunk debug command + +Prints all chunk information to a text file into the debug +folder in the root server folder. The format is in JSON, and +the data format is described in MCUtil#dumpChunks(File) + +The command will output server version and all online players to the +file as well. We do not log anything but the location, world and +username of the player. + +Also logs the value of these config values (note not all are paper's): +- keep spawn loaded value +- spawn radius +- view distance + +Each chunk has the following logged: +- Coordinate +- Ticket level & its corresponding state +- Whether it is queued for unload +- Chunk status (may be unloaded) +- All tickets on the chunk + +Example log: +https://gist.githubusercontent.com/Spottedleaf/0131e7710ffd5d531e5fd246c3367380/raw/169ae1b2e240485f99bc7a6bd8e78d90e3af7397/chunks-2019-06-01_19.57.05.txt + +For references on certain keywords (ticket, status, etc), please see: + +https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528273&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528273 +https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528577&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528577 + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index b67bd98cca4a06bc0ebaed577195dffc3b3251ec..a7a02072e5c7ce62cbecbb638fcc74abf2fb57ee 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -9,10 +9,12 @@ import com.google.common.collect.Maps; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkProviderServer; ++import net.minecraft.server.level.PlayerChunk; + import net.minecraft.server.level.WorldServer; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.server.MCUtil; + import org.apache.commons.lang3.tuple.MutablePair; + import org.apache.commons.lang3.tuple.Pair; + import org.bukkit.Bukkit; +@@ -41,7 +43,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); + + public PaperCommand(String name) { + super(name); +@@ -69,6 +71,21 @@ public class PaperCommand extends Command { + if (args.length == 3) + return getListMatchingLast(sender, args, EntityTypes.getEntityNameList().stream().map(MinecraftKey::toString).sorted().toArray(String[]::new)); + break; ++ case "debug": ++ if (args.length == 2) { ++ return getListMatchingLast(sender, args, "help", "chunks"); ++ } ++ break; ++ case "chunkinfo": ++ List worldNames = new ArrayList<>(); ++ worldNames.add("*"); ++ for (org.bukkit.World world : Bukkit.getWorlds()) { ++ worldNames.add(world.getName()); ++ } ++ if (args.length == 2) { ++ return getListMatchingLast(sender, args, worldNames); ++ } ++ break; + } + return Collections.emptyList(); + } +@@ -135,6 +152,12 @@ public class PaperCommand extends Command { + case "reload": + doReload(sender); + break; ++ case "debug": ++ doDebug(sender, args); ++ break; ++ case "chunkinfo": ++ doChunkInfo(sender, args); ++ break; + case "ver": + if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) + case "version": +@@ -152,6 +175,114 @@ public class PaperCommand extends Command { + return true; + } + ++ private void doChunkInfo(CommandSender sender, String[] args) { ++ List worlds; ++ if (args.length < 2 || args[1].equals("*")) { ++ worlds = Bukkit.getWorlds(); ++ } else { ++ worlds = new ArrayList<>(args.length - 1); ++ for (int i = 1; i < args.length; ++i) { ++ org.bukkit.World world = Bukkit.getWorld(args[i]); ++ if (world == null) { ++ sender.sendMessage(ChatColor.RED + "World '" + args[i] + "' is invalid"); ++ return; ++ } ++ worlds.add(world); ++ } ++ } ++ ++ int accumulatedTotal = 0; ++ int accumulatedInactive = 0; ++ int accumulatedBorder = 0; ++ int accumulatedTicking = 0; ++ int accumulatedEntityTicking = 0; ++ ++ for (org.bukkit.World bukkitWorld : worlds) { ++ WorldServer world = ((CraftWorld)bukkitWorld).getHandle(); ++ ++ int total = 0; ++ int inactive = 0; ++ int border = 0; ++ int ticking = 0; ++ int entityTicking = 0; ++ ++ for (PlayerChunk chunk : world.getChunkProvider().playerChunkMap.updatingChunks.values()) { ++ if (chunk.getFullChunkIfCached() == null) { ++ continue; ++ } ++ ++ ++total; ++ ++ PlayerChunk.State state = PlayerChunk.getChunkState(chunk.getTicketLevel()); ++ ++ switch (state) { ++ case INACCESSIBLE: ++ ++inactive; ++ continue; ++ case BORDER: ++ ++border; ++ continue; ++ case TICKING: ++ ++ticking; ++ continue; ++ case ENTITY_TICKING: ++ ++entityTicking; ++ continue; ++ } ++ } ++ ++ accumulatedTotal += total; ++ accumulatedInactive += inactive; ++ accumulatedBorder += border; ++ accumulatedTicking += ticking; ++ accumulatedEntityTicking += entityTicking; ++ ++ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + bukkitWorld.getName() + ChatColor.DARK_AQUA + ":"); ++ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + total + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA ++ + inactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + border + ChatColor.BLUE + " Ticking: " ++ + ChatColor.DARK_AQUA + ticking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + entityTicking); ++ } ++ if (worlds.size() > 1) { ++ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + "all listed worlds" + ChatColor.DARK_AQUA + ":"); ++ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + accumulatedTotal + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA ++ + accumulatedInactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + accumulatedBorder + ChatColor.BLUE + " Ticking: " ++ + ChatColor.DARK_AQUA + accumulatedTicking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + accumulatedEntityTicking); ++ } ++ } ++ ++ private void doDebug(CommandSender sender, String[] args) { ++ if (args.length < 2) { ++ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); ++ return; ++ } ++ ++ String debugType = args[1].toLowerCase(Locale.ENGLISH); ++ switch (debugType) { ++ case "chunks": ++ if (args.length >= 3 && args[2].toLowerCase(Locale.ENGLISH).equals("help")) { ++ sender.sendMessage(ChatColor.RED + "Use /paper debug chunks to dump loaded chunk information to a file"); ++ break; ++ } ++ File file = new File(new File(new File("."), "debug"), ++ "chunks-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); ++ sender.sendMessage(ChatColor.GREEN + "Writing chunk information dump to " + file.toString()); ++ try { ++ MCUtil.dumpChunks(file); ++ sender.sendMessage(ChatColor.GREEN + "Successfully written chunk information!"); ++ } catch (Throwable thr) { ++ MinecraftServer.LOGGER.warn("Failed to dump chunk information to file " + file.toString(), thr); ++ sender.sendMessage(ChatColor.RED + "Failed to dump chunk information, see console"); ++ } ++ ++ break; ++ case "help": ++ // fall through to default ++ default: ++ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); ++ return; ++ } ++ } ++ + /* + * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 + */ +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 35d1444c5b75d9a3a6cface5dd70aea0a08ac89d..fbd33aef21b4539d249c367609a36491530fb7ca 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -9,13 +9,27 @@ import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.chat.IChatBaseComponent; ++import net.minecraft.server.level.ChunkMapDistance; ++import net.minecraft.server.level.ChunkProviderServer; ++import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.PlayerChunk; ++import net.minecraft.server.level.PlayerChunkMap; ++import net.minecraft.server.level.Ticket; + import net.minecraft.server.level.WorldServer; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.RayTrace; + import net.minecraft.world.level.World; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.chunk.IChunkAccess; + import org.apache.commons.lang.exception.ExceptionUtils; ++import com.google.gson.JsonArray; ++import com.google.gson.JsonObject; ++import com.google.gson.internal.Streams; ++import com.google.gson.stream.JsonWriter; + import com.mojang.authlib.GameProfile; ++import com.mojang.datafixers.util.Either; ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; + import org.bukkit.Location; + import org.bukkit.block.BlockFace; + import org.bukkit.craftbukkit.CraftWorld; +@@ -24,8 +38,11 @@ import org.spigotmc.AsyncCatcher; + + import javax.annotation.Nonnull; + import javax.annotation.Nullable; ++import java.io.*; ++import java.util.ArrayList; + import java.util.List; + import java.util.Queue; ++import java.util.Set; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.ExecutionException; + import java.util.concurrent.LinkedBlockingQueue; +@@ -531,4 +548,170 @@ public final class MCUtil { + + return null; + } ++ ++ public static ChunkStatus getChunkStatus(PlayerChunk chunk) { ++ List statuses = ChunkProviderServer.getPossibleChunkStatuses(); ++ for (int i = statuses.size() - 1; i >= 0; --i) { ++ ChunkStatus curr = statuses.get(i); ++ CompletableFuture> future = chunk.getStatusFutureUnchecked(curr); ++ if (future != PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE) { ++ return curr; ++ } ++ } ++ return null; // unloaded ++ } ++ ++ public static void dumpChunks(File file) throws IOException { ++ file.getParentFile().mkdirs(); ++ file.createNewFile(); ++ /* ++ * Json format: ++ * ++ * Main data format: ++ * -server-version: ++ * -data-version: ++ * -worlds: ++ * -name: ++ * -view-distance: ++ * -keep-spawn-loaded: ++ * -keep-spawn-loaded-range: ++ * -visible-chunk-count: ++ * -loaded-chunk-count: ++ * -verified-fully-loaded-chunks: ++ * -players: ++ * -chunk-data: ++ * ++ * Player format: ++ * -name: ++ * -x: ++ * -y: ++ * -z: ++ * ++ * Chunk Format: ++ * -x: ++ * -z: ++ * -ticket-level: ++ * -state: ++ * -queued-for-unload: ++ * -status: ++ * -tickets: ++ * ++ * ++ * Ticket format: ++ * -ticket-type: ++ * -ticket-level: ++ * -add-tick: ++ * -object-reason: // This depends on the type of ticket. ie POST_TELEPORT -> entity id ++ */ ++ List worlds = org.bukkit.Bukkit.getWorlds(); ++ JsonObject data = new JsonObject(); ++ ++ data.addProperty("server-version", org.bukkit.Bukkit.getVersion()); ++ data.addProperty("data-version", 0); ++ ++ JsonArray worldsData = new JsonArray(); ++ ++ for (org.bukkit.World bukkitWorld : worlds) { ++ JsonObject worldData = new JsonObject(); ++ ++ WorldServer world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); ++ PlayerChunkMap chunkMap = world.getChunkProvider().playerChunkMap; ++ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunks; ++ ChunkMapDistance chunkMapDistance = chunkMap.chunkDistanceManager; ++ List allChunks = new ArrayList<>(visibleChunks.values()); ++ List players = world.players; ++ ++ int fullLoadedChunks = 0; ++ ++ for (PlayerChunk chunk : allChunks) { ++ if (chunk.getFullChunkIfCached() != null) { ++ ++fullLoadedChunks; ++ } ++ } ++ ++ // sorting by coordinate makes the log easier to read ++ allChunks.sort((PlayerChunk v1, PlayerChunk v2) -> { ++ if (v1.location.x != v2.location.x) { ++ return Integer.compare(v1.location.x, v2.location.x); ++ } ++ return Integer.compare(v1.location.z, v2.location.z); ++ }); ++ ++ worldData.addProperty("name", world.getWorld().getName()); ++ worldData.addProperty("view-distance", world.spigotConfig.viewDistance); ++ worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); ++ worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); ++ worldData.addProperty("visible-chunk-count", visibleChunks.size()); ++ worldData.addProperty("loaded-chunk-count", chunkMap.loadedChunks.size()); ++ worldData.addProperty("verified-fully-loaded-chunks", fullLoadedChunks); ++ ++ JsonArray playersData = new JsonArray(); ++ ++ for (EntityPlayer player : players) { ++ JsonObject playerData = new JsonObject(); ++ ++ playerData.addProperty("name", player.getName()); ++ playerData.addProperty("x", player.locX()); ++ playerData.addProperty("y", player.locY()); ++ playerData.addProperty("z", player.locZ()); ++ ++ playersData.add(playerData); ++ ++ } ++ ++ worldData.add("players", playersData); ++ ++ JsonArray chunksData = new JsonArray(); ++ ++ for (PlayerChunk playerChunk : allChunks) { ++ JsonObject chunkData = new JsonObject(); ++ ++ Set> tickets = chunkMapDistance.tickets.get(playerChunk.location.pair()); ++ ChunkStatus status = getChunkStatus(playerChunk); ++ ++ chunkData.addProperty("x", playerChunk.location.x); ++ chunkData.addProperty("z", playerChunk.location.z); ++ chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); ++ chunkData.addProperty("state", PlayerChunk.getChunkState(playerChunk.getTicketLevel()).toString()); ++ chunkData.addProperty("queued-for-unload", chunkMap.unloadQueue.contains(playerChunk.location.pair())); ++ chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); ++ ++ JsonArray ticketsData = new JsonArray(); ++ ++ if (tickets != null) { ++ for (Ticket ticket : tickets) { ++ JsonObject ticketData = new JsonObject(); ++ ++ ticketData.addProperty("ticket-type", ticket.getTicketType().toString()); ++ ticketData.addProperty("ticket-level", ticket.getTicketLevel()); ++ ticketData.addProperty("object-reason", String.valueOf(ticket.getObjectReason())); ++ ticketData.addProperty("add-tick", ticket.getCreationTick()); ++ ++ ticketsData.add(ticketData); ++ } ++ } ++ ++ chunkData.add("tickets", ticketsData); ++ chunksData.add(chunkData); ++ } ++ ++ ++ worldData.add("chunk-data", chunksData); ++ worldsData.add(worldData); ++ } ++ ++ data.add("worlds", worldsData); ++ ++ StringWriter stringWriter = new StringWriter(); ++ JsonWriter jsonWriter = new JsonWriter(stringWriter); ++ jsonWriter.setIndent(" "); ++ jsonWriter.setLenient(false); ++ Streams.write(data, jsonWriter); ++ ++ String fileData = stringWriter.toString(); ++ ++ try (PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) { ++ out.print(fileData); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 677c185aca2cdd64bead9dbed147a87c5bcf1678..3425ae4d036bbfa413e60eccfd6d82b8dae3775b 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -46,7 +46,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper + + public class ChunkProviderServer extends IChunkProvider { + +- private static final List b = ChunkStatus.a(); ++ private static final List b = ChunkStatus.a(); public static final List getPossibleChunkStatuses() { return ChunkProviderServer.b; } // Paper - OBFHELPER + private final ChunkMapDistance chunkMapDistance; + public final ChunkGenerator chunkGenerator; + private final WorldServer world; +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index 2c3d9a5d118cc4f3b5e78daf943911bb7386488a..9891cf98f8c740f84f9135ee8176e67abb648b3a 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -54,7 +54,7 @@ public class PlayerChunk { + public int oldTicketLevel; + private int ticketLevel; + private int n; +- private final ChunkCoordIntPair location; ++ final ChunkCoordIntPair location; // Paper - private -> package + private boolean p; + private final ShortSet[] dirtyBlocks; + private int r; +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index b736917891afb17e412f94c5d8713aa653b8dc46..e10c661755796e9c4e40f62a649b45dd1a71b46c 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -106,7 +106,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + public final Long2ObjectLinkedOpenHashMap updatingChunks = new Long2ObjectLinkedOpenHashMap(); + public volatile Long2ObjectLinkedOpenHashMap visibleChunks; + private final Long2ObjectLinkedOpenHashMap pendingUnload; +- private final LongSet loadedChunks; ++ public final LongSet loadedChunks; // Paper - private -> public + public final WorldServer world; + private final LightEngineThreaded lightEngine; + private final IAsyncTaskHandler executor; +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index 51ef4adf66c1e21093e63ab46fa47e66c2425fdb..e06fe77f6ea05a93e95fce223bcfd0d16394f96f 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -6,8 +6,8 @@ public final class Ticket implements Comparable> { + + private final TicketType a; + private final int b; +- public final T identifier; +- private long d; ++ public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER ++ private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER + + protected Ticket(TicketType tickettype, int i, T t0) { + this.a = tickettype; +@@ -51,6 +51,7 @@ public final class Ticket implements Comparable> { + return this.a; + } + ++ public final int getTicketLevel() { return this.b(); } // Paper - OBFHELPER + public int b() { + return this.b; + } diff --git a/patches/server-unmapped/0357-Catch-exceptions-from-dispenser-entity-spawns.patch b/patches/server-unmapped/0357-Catch-exceptions-from-dispenser-entity-spawns.patch new file mode 100644 index 0000000000..44ad23e85f --- /dev/null +++ b/patches/server-unmapped/0357-Catch-exceptions-from-dispenser-entity-spawns.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Mon, 10 Jun 2019 09:36:40 +0100 +Subject: [PATCH] Catch exceptions from dispenser entity spawns + + +diff --git a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java +index a7d690cb2289a79ee2b8fc665caef58a10ddab3e..50911632341d1b861c00f01077cae43884147fe0 100644 +--- a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java +@@ -8,6 +8,7 @@ import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; + import net.minecraft.core.IPosition; + import net.minecraft.core.ISourceBlock; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundCategory; +@@ -237,7 +238,14 @@ public interface IDispenseBehavior { + } + } + ++ try { // Paper + entitytypes.spawnCreature(isourceblock.getWorld(), itemstack, (EntityHuman) null, isourceblock.getBlockPosition().shift(enumdirection), EnumMobSpawn.DISPENSER, enumdirection != EnumDirection.UP, false); ++ // Paper start ++ } catch (Exception ex){ ++ MinecraftServer.LOGGER.warn("An exception occurred dispensing entity at {}[{}]", worldserver.getWorld().getName(), isourceblock.getBlockPosition(), ex); ++ } ++ // Paper end ++ + // itemstack.subtract(1); // Handled during event processing + // CraftBukkit end + return itemstack; diff --git a/patches/server-unmapped/0358-Fix-World-isChunkGenerated-calls.patch b/patches/server-unmapped/0358-Fix-World-isChunkGenerated-calls.patch new file mode 100644 index 0000000000..2da0e88e20 --- /dev/null +++ b/patches/server-unmapped/0358-Fix-World-isChunkGenerated-calls.patch @@ -0,0 +1,390 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 15 Jun 2019 08:54:33 -0700 +Subject: [PATCH] Fix World#isChunkGenerated calls + +Optimize World#loadChunk() too +This patch also adds a chunk status cache on region files (note that +its only purpose is to cache the status on DISK) + +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 3425ae4d036bbfa413e60eccfd6d82b8dae3775b..34b68443ff300f8626e9f7a8335cff75580bebfc 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -52,7 +52,7 @@ public class ChunkProviderServer extends IChunkProvider { + private final WorldServer world; + public final Thread serverThread; // Paper - private -> public + private final LightEngineThreaded lightEngine; +- private final ChunkProviderServer.a serverThreadQueue; ++ public final ChunkProviderServer.a serverThreadQueue; // Paper private -> public + public final PlayerChunkMap playerChunkMap; + private final WorldPersistentData worldPersistentData; + private long lastTickTime; +@@ -317,6 +317,21 @@ public class ChunkProviderServer extends IChunkProvider { + + return ret; + } ++ ++ @Nullable ++ public IChunkAccess getChunkAtImmediately(int x, int z) { ++ long k = ChunkCoordIntPair.pair(x, z); ++ ++ // Note: Bypass cache to make this MT-Safe ++ ++ PlayerChunk playerChunk = this.getChunk(k); ++ if (playerChunk == null) { ++ return null; ++ } ++ ++ return playerChunk.getAvailableChunkNow(); ++ ++ } + // Paper end + + @Nullable +@@ -770,7 +785,7 @@ public class ChunkProviderServer extends IChunkProvider { + return this.p; + } + +- final class a extends IAsyncTaskHandler { ++ public final class a extends IAsyncTaskHandler { // Paper - package -> public + + private a(World world) { + super("Chunk source main thread executor for " + world.getDimensionKey().a()); +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index 9891cf98f8c740f84f9135ee8176e67abb648b3a..6bced8533df49d7bfdb32dfa0caad9d788ffc2c8 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -142,6 +142,19 @@ public class PlayerChunk { + Either either = (Either) statusFuture.getNow(null); + return either == null ? null : (Chunk) either.left().orElse(null); + } ++ ++ public IChunkAccess getAvailableChunkNow() { ++ // TODO can we just getStatusFuture(EMPTY)? ++ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) { ++ CompletableFuture> future = this.getStatusFutureUnchecked(curr); ++ Either either = future.getNow(null); ++ if (either == null || !either.left().isPresent()) { ++ continue; ++ } ++ return either.left().get(); ++ } ++ return null; ++ } + // Paper end + + public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index e10c661755796e9c4e40f62a649b45dd1a71b46c..ed454f8dff7b0d94d4bde914a6f26bb019e82296 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -993,12 +993,61 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + @Nullable +- private NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { ++ public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public + NBTTagCompound nbttagcompound = this.read(chunkcoordintpair); ++ // Paper start - Cache chunk status on disk ++ if (nbttagcompound == null) { ++ return null; ++ } ++ ++ nbttagcompound = this.getChunkData(this.world.getTypeKey(), this.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit ++ if (nbttagcompound == null) { ++ return null; ++ } ++ ++ this.updateChunkStatusOnDisk(chunkcoordintpair, nbttagcompound); ++ ++ return nbttagcompound; ++ // Paper end ++ } ++ ++ // Paper start - chunk status cache "api" ++ public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) { ++ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); ++ ++ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ } ++ ++ public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException { ++ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); ++ ++ if (regionFile == null || !regionFile.chunkExists(chunkPos)) { ++ return null; ++ } ++ ++ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ ++ if (status != null) { ++ return status; ++ } ++ ++ this.readChunkData(chunkPos); + +- return nbttagcompound == null ? null : this.getChunkData(this.world.getTypeKey(), this.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit ++ return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); + } + ++ public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException { ++ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); ++ ++ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); ++ } ++ ++ public IChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { ++ PlayerChunk chunkHolder = this.pendingUnload.get(ChunkCoordIntPair.pair(chunkX, chunkZ)); ++ return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow(); ++ } ++ // Paper end ++ + boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair) { + // Spigot start + return isOutsideOfRange(chunkcoordintpair, false); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +index 5e4c162654349f884becc10e8fbae4ded6889deb..711308cf84a816f09d116a7414f9cbee803c8713 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +@@ -193,6 +193,7 @@ public class ChunkStatus { + return this.s; + } + ++ public ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER + public ChunkStatus e() { + return this.u; + } +@@ -213,6 +214,17 @@ public class ChunkStatus { + return this.y; + } + ++ // Paper start ++ public static ChunkStatus getStatus(String name) { ++ try { ++ // We need this otherwise we return EMPTY for invalid names ++ MinecraftKey key = new MinecraftKey(name); ++ return IRegistry.CHUNK_STATUS.getOptional(key).orElse(null); ++ } catch (Exception ex) { ++ return null; // invalid name ++ } ++ } ++ // Paper end + public static ChunkStatus a(String s) { + return (ChunkStatus) IRegistry.CHUNK_STATUS.get(MinecraftKey.a(s)); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index 69bc9dc18bab157851d8080a672504598e8572a8..98bc26c7ae01884eb53766e72fc7cbabbf065e6e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -462,6 +462,17 @@ public class ChunkRegionLoader { + } + // Paper end + ++ // Paper start ++ public static ChunkStatus getStatus(NBTTagCompound compound) { ++ if (compound == null) { ++ return null; ++ } ++ ++ // Note: Copied from below ++ return ChunkStatus.getStatus(compound.getCompound("Level").getString("Status")); ++ } ++ // Paper end ++ + public static ChunkStatus.Type a(@Nullable NBTTagCompound nbttagcompound) { + if (nbttagcompound != null) { + ChunkStatus chunkstatus = ChunkStatus.a(nbttagcompound.getCompound("Level").getString("Status")); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java +index 247d14a3ca56734bbbf4dc0ec247d60a1f241e7a..d785f44cd503d4d91589f3fc4bc8dc805dff3d41 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java +@@ -25,7 +25,7 @@ import net.minecraft.world.level.dimension.DimensionManager; + + public class IChunkLoader implements AutoCloseable { + +- private final IOWorker a; ++ private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER + protected final DataFixer b; + @Nullable + private PersistentStructureLegacy c; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index 00cef1c0bc19976a000389e57a1af5d93690c0e7..d50b9c9d030016f951e2ed7fb519250b7408c833 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -27,6 +27,7 @@ import net.minecraft.SystemUtils; + import net.minecraft.nbt.NBTCompressedStreamTools; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.level.chunk.ChunkStatus; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +@@ -44,6 +45,30 @@ public class RegionFile implements AutoCloseable { + protected final RegionFileBitSet freeSectors; + public final File file; // Paper + ++ // Paper start - Cache chunk status ++ private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; ++ ++ private boolean closed; ++ ++ // invoked on write/read ++ public void setStatus(int x, int z, ChunkStatus status) { ++ if (this.closed) { ++ // We've used an invalid region file. ++ throw new IllegalStateException("RegionFile is closed"); ++ } ++ this.statuses[getChunkLocation(x, z)] = status; ++ } ++ ++ public ChunkStatus getStatusIfCached(int x, int z) { ++ if (this.closed) { ++ // We've used an invalid region file. ++ throw new IllegalStateException("RegionFile is closed"); ++ } ++ final int location = getChunkLocation(x, z); ++ return this.statuses[location]; ++ } ++ // Paper end ++ + public RegionFile(File file, File file1, boolean flag) throws IOException { + this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag); + } +@@ -380,11 +405,13 @@ public class RegionFile implements AutoCloseable { + return this.getOffset(chunkcoordintpair) != 0; + } + ++ private static int getChunkLocation(int x, int z) { return (x & 31) + (z & 31) * 32; } // Paper - OBFHELPER - sort of, mirror of logic below + private static int g(ChunkCoordIntPair chunkcoordintpair) { + return chunkcoordintpair.j() + chunkcoordintpair.k() * 32; + } + + public void close() throws IOException { ++ this.closed = true; // Paper + try { + this.d(); + } finally { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +index ab9f4d40fd1126a3d7ba5b16fdc6ab09de4a7fdb..55e7e983d2c760a8052d7b3ddbdc8447f619a60f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +@@ -28,7 +28,14 @@ public final class RegionFileCache implements AutoCloseable { + this.c = flag; + } + +- private RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit ++ ++ // Paper start ++ public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { ++ return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); ++ } ++ ++ // Paper end ++ public RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public + long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); + RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i); + +@@ -175,6 +182,7 @@ public final class RegionFileCache implements AutoCloseable { + + try { + NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream); ++ regionfile.setStatus(chunkcoordintpair.x, chunkcoordintpair.z, ChunkRegionLoader.getStatus(nbttagcompound)); // Paper - cache status on disk + regionfile.setOversized(chunkcoordintpair.x, chunkcoordintpair.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone + } catch (Throwable throwable1) { + throwable = throwable1; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index ec9f9fdf1be4f1e68eea5554a6721efd11a53958..d46c513512c25e55ccdb0be16524f19444c358c5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -19,6 +19,7 @@ import java.util.Objects; + import java.util.Random; + import java.util.Set; + import java.util.UUID; ++import java.util.concurrent.CompletableFuture; + import java.util.function.Predicate; + import java.util.stream.Collectors; + import net.minecraft.core.BlockPosition; +@@ -419,8 +420,22 @@ public class CraftWorld implements World { + + @Override + public boolean isChunkGenerated(int x, int z) { ++ // Paper start - Fix this method ++ if (!Bukkit.isPrimaryThread()) { ++ return CompletableFuture.supplyAsync(() -> { ++ return CraftWorld.this.isChunkGenerated(x, z); ++ }, world.getChunkProvider().serverThreadQueue).join(); ++ } ++ IChunkAccess chunk = world.getChunkProvider().getChunkAtImmediately(x, z); ++ if (chunk == null) { ++ chunk = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); ++ } ++ if (chunk != null) { ++ return chunk instanceof ProtoChunkExtension || chunk instanceof net.minecraft.world.level.chunk.Chunk; ++ } + try { +- return world.getChunkProvider().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)) != null; // Paper (TODO check if the first part can be removed) ++ return world.getChunkProvider().playerChunkMap.getChunkStatusOnDisk(new ChunkCoordIntPair(x, z)) == ChunkStatus.FULL; ++ // Paper end + } catch (IOException ex) { + throw new RuntimeException(ex); + } +@@ -531,20 +546,48 @@ public class CraftWorld implements World { + @Override + public boolean loadChunk(int x, int z, boolean generate) { + org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot +- IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper ++ // Paper start - Optimize this method ++ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); + +- // If generate = false, but the chunk already exists, we will get this back. +- if (chunk instanceof ProtoChunkExtension) { +- // We then cycle through again to get the full chunk immediately, rather than after the ticket addition +- chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); +- } ++ if (!generate) { ++ IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); ++ if (immediate == null) { ++ immediate = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); ++ } ++ if (immediate != null) { ++ if (!(immediate instanceof ProtoChunkExtension) && !(immediate instanceof net.minecraft.world.level.chunk.Chunk)) { ++ return false; // not full status ++ } ++ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkAt(x, z); // make sure we're at ticket level 32 or lower ++ return true; ++ } + +- if (chunk instanceof net.minecraft.world.level.chunk.Chunk) { +- world.getChunkProvider().addTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE); +- return true; ++ net.minecraft.world.level.chunk.storage.RegionFile file; ++ try { ++ file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); ++ } catch (IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ ChunkStatus status = file.getStatusIfCached(x, z); ++ if (!file.chunkExists(chunkPos) || (status != null && status != ChunkStatus.FULL)) { ++ return false; ++ } ++ ++ IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.EMPTY, true); ++ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.world.level.chunk.Chunk)) { ++ return false; ++ } ++ ++ // fall through to load ++ // we do this so we do not re-read the chunk data on disk + } + +- return false; ++ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); ++ return true; ++ // Paper end + } + + @Override diff --git a/patches/server-unmapped/0359-Show-blockstate-location-if-we-failed-to-read-it.patch b/patches/server-unmapped/0359-Show-blockstate-location-if-we-failed-to-read-it.patch new file mode 100644 index 0000000000..8c64eb071a --- /dev/null +++ b/patches/server-unmapped/0359-Show-blockstate-location-if-we-failed-to-read-it.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 15 Jun 2019 10:28:25 -0700 +Subject: [PATCH] Show blockstate location if we failed to read it + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +index 2f0b48869077c27d0cacea81a99c9e34ff59c684..a4bd0d352c2babdbb31cdf49d63e2db3af4de146 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +@@ -19,6 +19,8 @@ public class CraftBlockEntityState extends CraftBlockState + public CraftBlockEntityState(Block block, Class tileEntityClass) { + super(block); + ++ try {// Paper - show location on failure ++ + this.tileEntityClass = tileEntityClass; + + // get tile entity from block: +@@ -38,6 +40,14 @@ public class CraftBlockEntityState extends CraftBlockState + this.load(this.snapshot); + } + // Paper end ++ // Paper start - show location on failure ++ } catch (Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ throw new RuntimeException("Failed to read BlockState at: world: " + block.getWorld().getName() + " location: (" + block.getX() + ", " + block.getY() + ", " + block.getZ() + ")", thr); ++ } ++ // Paper end + } + + public final boolean snapshotDisabled; // Paper diff --git a/patches/server-unmapped/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch b/patches/server-unmapped/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch new file mode 100644 index 0000000000..1dcdb2ef23 --- /dev/null +++ b/patches/server-unmapped/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 May 2020 20:29:02 -0400 +Subject: [PATCH] Synchronize DataPaletteBlock instead of ReentrantLock + +Mojang has flaws in their logic about chunks being concurrently +wrote to. So we constantly see crashes around multiple threads writing. + +Additionally, java has optimized synchronization so well that its +in many times faster than trying to manage read wrote locks for low +contention situations. + +And this is extremely a low contention situation. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +index 8928157b01bb4f0dfe043732777b33708c23cda7..cc0c5995dc3840ce66ea849849f7c37555d3b5e6 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java ++++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +@@ -32,7 +32,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { + private int i; private int getBitsPerObject() { return this.i; } // Paper - OBFHELPER + private final ReentrantLock j = new ReentrantLock(); + +- public void a() { ++ public void a() { /* // Paper start - disable this - use proper synchronization + if (this.j.isLocked() && !this.j.isHeldByCurrentThread()) { + String s = (String) Thread.getAllStackTraces().keySet().stream().filter(Objects::nonNull).map((thread) -> { + return thread.getName() + ": \n\tat " + (String) Arrays.stream(thread.getStackTrace()).map(Object::toString).collect(Collectors.joining("\n\tat ")); +@@ -44,11 +44,11 @@ public class DataPaletteBlock implements DataPaletteExpandable { + throw new ReportedException(crashreport); + } else { + this.j.lock(); +- } ++ } */ // Paper end + } + + public void b() { +- this.j.unlock(); ++ //this.j.unlock(); // Paper - disable this + } + + public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0) { +@@ -84,7 +84,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { + } + + @Override +- public int onResize(int i, T t0) { ++ public synchronized int onResize(int i, T t0) { // Paper - synchronize + this.a(); + DataBits databits = this.a; + DataPalette datapalette = this.h; +@@ -107,18 +107,18 @@ public class DataPaletteBlock implements DataPaletteExpandable { + } + + public T setBlock(int i, int j, int k, T t0) { +- this.a(); +- T t1 = this.a(b(i, j, k), t0); ++ //this.a(); // Paper - remove to reduce ops - synchronize handled below ++ return this.a(b(i, j, k), t0); // Paper + +- this.b(); +- return t1; ++ //this.b(); // Paper ++ //return t1; // PAper + } + + public T b(int i, int j, int k, T t0) { + return this.a(b(i, j, k), t0); + } + +- protected T a(int i, T t0) { ++ protected synchronized T a(int i, T t0) { // Paper - synchronize - writes + int j = this.h.a(t0); + int k = this.a.a(i, j); + T t1 = this.h.a(k); +@@ -143,7 +143,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { + } + + public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER +- public void b(PacketDataSerializer packetdataserializer) { ++ public synchronized void b(PacketDataSerializer packetdataserializer) { // Paper - synchronize + this.a(); + packetdataserializer.writeByte(this.i); + this.h.b(packetdataserializer); +@@ -151,7 +151,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { + this.b(); + } + +- public void a(NBTTagList nbttaglist, long[] along) { ++ public synchronized void a(NBTTagList nbttaglist, long[] along) { // Paper - synchronize + this.a(); + int i = Math.max(4, MathHelper.e(nbttaglist.size())); + +@@ -184,7 +184,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { + this.b(); + } + +- public void a(NBTTagCompound nbttagcompound, String s, String s1) { ++ public synchronized void a(NBTTagCompound nbttagcompound, String s, String s1) { // Paper - synchronize + this.a(); + DataPaletteHash datapalettehash = new DataPaletteHash<>(this.d, this.i, this.c, this.e, this.f); + T t0 = this.g; diff --git a/patches/server-unmapped/0361-incremental-chunk-saving.patch b/patches/server-unmapped/0361-incremental-chunk-saving.patch new file mode 100644 index 0000000000..87d8a2e957 --- /dev/null +++ b/patches/server-unmapped/0361-incremental-chunk-saving.patch @@ -0,0 +1,317 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 9 Jun 2019 03:53:22 +0100 +Subject: [PATCH] incremental chunk saving + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index ffe9b1a63d78925e1d77b9e730aef42fed6d58fa..1278d09f70c1e97607ef20d87a178dc252c7f723 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -446,4 +446,19 @@ public class PaperWorldConfig { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); + log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); + } ++ ++ public int autoSavePeriod = -1; ++ private void autoSavePeriod() { ++ autoSavePeriod = getInt("auto-save-interval", -1); ++ if (autoSavePeriod > 0) { ++ log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)"); ++ } else if (autoSavePeriod < 0) { ++ autoSavePeriod = net.minecraft.server.MinecraftServer.getServer().autosavePeriod; ++ } ++ } ++ ++ public int maxAutoSaveChunksPerTick = 24; ++ private void maxAutoSaveChunksPerTick() { ++ maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index aa2f4958fff659ef6b166b4644c81b5f1d8200a8..8b922136336d5dc8fc302cc0f4879c4968a1cc67 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -263,6 +263,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; ++ public boolean serverAutoSave = false; // Paper + public CommandDispatcher vanillaCommandDispatcher; + private boolean forceTicks; + // CraftBukkit end +@@ -1258,14 +1259,24 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit +- MinecraftServer.LOGGER.debug("Autosave started"); ++ //if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down ++ //MinecraftServer.LOGGER.debug("Autosave started"); // Paper ++ serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper + this.methodProfiler.enter("save"); ++ if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper + this.playerList.savePlayers(); +- this.saveChunks(true, false, false); ++ }// Paper ++ // Paper start ++ for (WorldServer world : getWorlds()) { ++ if (world.paperConfig.autoSavePeriod > 0) { ++ world.saveIncrementally(serverAutoSave); ++ } ++ } ++ // Paper end ++ + this.methodProfiler.exit(); +- MinecraftServer.LOGGER.debug("Autosave finished"); +- } ++ //MinecraftServer.LOGGER.debug("Autosave finished"); // Paper ++ //} // Paper + + this.methodProfiler.enter("snooper"); + if (((DedicatedServer) this).getDedicatedServerProperties().snooperEnabled && !this.snooper.d() && this.ticks > 100) { // Spigot +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 34b68443ff300f8626e9f7a8335cff75580bebfc..8c497da1a4bde904e234a8fa00bf04a12787c7ed 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -557,6 +557,15 @@ public class ChunkProviderServer extends IChunkProvider { + } // Paper - Timings + } + ++ // Paper start - duplicate save, but call incremental ++ public void saveIncrementally() { ++ this.tickDistanceManager(); ++ try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { // Paper - Timings ++ this.playerChunkMap.saveIncrementally(); ++ } // Paper - Timings ++ } ++ // Paper end ++ + @Override + public void close() throws IOException { + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index 6bced8533df49d7bfdb32dfa0caad9d788ffc2c8..75d4a8fc394449ccc006fe67a8842edcd9f36854 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -67,6 +67,9 @@ public class PlayerChunk { + + private final PlayerChunkMap chunkMap; // Paper + ++ long lastAutoSaveTime; // Paper - incremental autosave ++ long inactiveTimeStart; // Paper - incremental autosave ++ + public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { + this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); + this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; +@@ -422,7 +425,19 @@ public class PlayerChunk { + boolean flag2 = playerchunk_state.isAtLeast(PlayerChunk.State.BORDER); + boolean flag3 = playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER); + ++ boolean prevHasBeenLoaded = this.hasBeenLoaded; // Paper + this.hasBeenLoaded |= flag3; ++ // Paper start - incremental autosave ++ if (this.hasBeenLoaded & !prevHasBeenLoaded) { ++ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; ++ if (timeSinceAutoSave < 0) { ++ // safest bet is to assume autosave is needed here ++ timeSinceAutoSave = this.chunkMap.world.paperConfig.autoSavePeriod; ++ } ++ this.lastAutoSaveTime = this.chunkMap.world.getTime() - timeSinceAutoSave; ++ this.chunkMap.autoSaveQueue.add(this); ++ } ++ // Paper end + if (!flag2 && flag3) { + // Paper start - cache ticking ready status + int expectCreateCount = ++this.fullChunkCreateCount; +@@ -542,8 +557,32 @@ public class PlayerChunk { + } + + public void m() { ++ boolean prev = this.hasBeenLoaded; // Paper ++ this.hasBeenLoaded = getChunkState(this.ticketLevel).isAtLeast(PlayerChunk.State.BORDER); ++ // Paper start - incremental autosave ++ if (prev != this.hasBeenLoaded) { ++ if (this.hasBeenLoaded) { ++ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; ++ if (timeSinceAutoSave < 0) { ++ // safest bet is to assume autosave is needed here ++ timeSinceAutoSave = this.chunkMap.world.paperConfig.autoSavePeriod; ++ } ++ this.lastAutoSaveTime = this.chunkMap.world.getTime() - timeSinceAutoSave; ++ this.chunkMap.autoSaveQueue.add(this); ++ } else { ++ this.inactiveTimeStart = this.chunkMap.world.getTime(); ++ this.chunkMap.autoSaveQueue.remove(this); ++ } ++ } ++ // Paper end ++ } ++ ++ // Paper start - incremental autosave ++ public boolean setHasBeenLoaded() { + this.hasBeenLoaded = getChunkState(this.ticketLevel).isAtLeast(PlayerChunk.State.BORDER); ++ return this.hasBeenLoaded; + } ++ // Paper end + + public void a(ProtoChunkExtension protochunkextension) { + for (int i = 0; i < this.statusFutures.length(); ++i) { +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index ed454f8dff7b0d94d4bde914a6f26bb019e82296..ca05fe4ed0773b94035c63f8f8db6c034f0b92e2 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -93,6 +93,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStruct + import net.minecraft.world.level.storage.Convertable; + import net.minecraft.world.level.storage.WorldPersistentData; + import net.minecraft.world.phys.Vec3D; ++import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper + import org.apache.commons.lang3.mutable.MutableBoolean; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -380,6 +381,64 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + } + ++ // Paper start - incremental autosave ++ final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((playerchunk1, playerchunk2) -> { ++ int timeCompare = Long.compare(playerchunk1.lastAutoSaveTime, playerchunk2.lastAutoSaveTime); ++ if (timeCompare != 0) { ++ return timeCompare; ++ } ++ ++ return Long.compare(MCUtil.getCoordinateKey(playerchunk1.location), MCUtil.getCoordinateKey(playerchunk2.location)); ++ }); ++ ++ protected void saveIncrementally() { ++ int savedThisTick = 0; ++ // optimized since we search far less chunks to hit ones that need to be saved ++ List reschedule = new java.util.ArrayList<>(this.world.paperConfig.maxAutoSaveChunksPerTick); ++ long currentTick = this.world.getTime(); ++ long maxSaveTime = currentTick - this.world.paperConfig.autoSavePeriod; ++ ++ for (Iterator iterator = this.autoSaveQueue.iterator(); iterator.hasNext();) { ++ PlayerChunk playerchunk = iterator.next(); ++ if (playerchunk.lastAutoSaveTime > maxSaveTime) { ++ break; ++ } ++ ++ iterator.remove(); ++ ++ IChunkAccess ichunkaccess = playerchunk.getChunkSave().getNow(null); ++ if (ichunkaccess instanceof Chunk) { ++ boolean shouldSave = ((Chunk)ichunkaccess).lastSaved <= maxSaveTime; ++ ++ if (shouldSave && this.saveChunk(ichunkaccess)) { ++ ++savedThisTick; ++ ++ if (!playerchunk.setHasBeenLoaded()) { ++ // do not fall through to reschedule logic ++ playerchunk.inactiveTimeStart = currentTick; ++ if (savedThisTick >= this.world.paperConfig.maxAutoSaveChunksPerTick) { ++ break; ++ } ++ continue; ++ } ++ } ++ } ++ ++ reschedule.add(playerchunk); ++ ++ if (savedThisTick >= this.world.paperConfig.maxAutoSaveChunksPerTick) { ++ break; ++ } ++ } ++ ++ for (int i = 0, len = reschedule.size(); i < len; ++i) { ++ PlayerChunk playerchunk = reschedule.get(i); ++ playerchunk.lastAutoSaveTime = this.world.getTime(); ++ this.autoSaveQueue.add(playerchunk); ++ } ++ } ++ // Paper end ++ + protected void save(boolean flag) { + if (flag) { + List list = (List) this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList()); +@@ -490,6 +549,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + this.world.unloadChunk(chunk); + } ++ this.autoSaveQueue.remove(playerchunk); // Paper + + this.lightEngine.a(ichunkaccess.getPos()); + this.lightEngine.queueUpdate(); +@@ -682,6 +742,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + playerchunk.a(new ProtoChunkExtension(chunk)); + } + ++ chunk.setLastSaved(this.world.getTime() - 1); // Paper - avoid autosaving newly generated/loaded chunks ++ + chunk.a(() -> { + return PlayerChunk.getChunkState(playerchunk.getTicketLevel()); + }); +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index d308197995a92f5be8f5b928fa9ae83dd659545c..12e34e1514f060ffef96cdd3ac57d0495dd37321 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -888,6 +888,38 @@ public class WorldServer extends World implements GeneratorAccessSeed { + return !this.server.a(this, blockposition, entityhuman) && this.getWorldBorder().a(blockposition); + } + ++ // Paper start - derived from below ++ public void saveIncrementally(boolean doFull) { ++ ChunkProviderServer chunkproviderserver = this.getChunkProvider(); ++ ++ if (doFull) { ++ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); ++ } ++ ++ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { ++ if (doFull) { ++ this.saveData(); ++ } ++ ++ timings.worldSaveChunks.startTiming(); // Paper ++ if (!this.isSavingDisabled()) chunkproviderserver.saveIncrementally(); ++ timings.worldSaveChunks.stopTiming(); // Paper ++ ++ ++ // Copied from save() ++ // CraftBukkit start - moved from MinecraftServer.saveChunks ++ if (doFull) { // Paper ++ WorldServer worldserver1 = this; ++ ++ worldDataServer.a(worldserver1.getWorldBorder().t()); ++ worldDataServer.setCustomBossEvents(this.server.getBossBattleCustomData().save()); ++ convertable.a(this.server.customRegistry, this.worldDataServer, this.server.getPlayerList().save()); ++ } ++ // CraftBukkit end ++ } ++ } ++ // Paper end ++ + public void save(@Nullable IProgressUpdate iprogressupdate, boolean flag, boolean flag1) { + ChunkProviderServer chunkproviderserver = this.getChunkProvider(); + +@@ -918,6 +950,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + // CraftBukkit end + } + ++ private void saveData() { this.aj(); } // Paper - OBFHELPER + private void aj() { + if (this.dragonBattle != null) { + this.worldDataServer.a(this.dragonBattle.a()); // CraftBukkit +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index 3f926ed8e2b2c9dbf1e2493870af7eff3b6db019..2690c44eaae193a259fe195c95e59d07d5e1cc5a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -81,7 +81,7 @@ public class Chunk implements IChunkAccess { + private TickList o; + private TickList p; + private boolean q; +- private long lastSaved; ++ public long lastSaved; // Paper + private volatile boolean s; + private long inhabitedTime; + @Nullable diff --git a/patches/server-unmapped/0362-Anti-Xray.patch b/patches/server-unmapped/0362-Anti-Xray.patch new file mode 100644 index 0000000000..ddd0aa5463 --- /dev/null +++ b/patches/server-unmapped/0362-Anti-Xray.patch @@ -0,0 +1,1567 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: stonar96 +Date: Mon, 20 Aug 2018 03:03:58 +0200 +Subject: [PATCH] Anti-Xray + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1278d09f70c1e97607ef20d87a178dc252c7f723..c45493e88bf7e8811be2759ff9ac19e3fe9d938a 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -1,7 +1,9 @@ + package com.destroystokyo.paper; + ++import java.util.Arrays; + import java.util.List; + ++import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; + import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; +@@ -461,4 +463,38 @@ public class PaperWorldConfig { + private void maxAutoSaveChunksPerTick() { + maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); + } ++ ++ public boolean antiXray; ++ public EngineMode engineMode; ++ public int maxChunkSectionIndex; ++ public int updateRadius; ++ public boolean lavaObscures; ++ public boolean usePermission; ++ public List hiddenBlocks; ++ public List replacementBlocks; ++ private void antiXray() { ++ antiXray = getBoolean("anti-xray.enabled", false); ++ engineMode = EngineMode.getById(getInt("anti-xray.engine-mode", EngineMode.HIDE.getId())); ++ engineMode = engineMode == null ? EngineMode.HIDE : engineMode; ++ maxChunkSectionIndex = getInt("anti-xray.max-chunk-section-index", 3); ++ maxChunkSectionIndex = maxChunkSectionIndex > 15 ? 15 : maxChunkSectionIndex; ++ updateRadius = getInt("anti-xray.update-radius", 2); ++ lavaObscures = getBoolean("anti-xray.lava-obscures", false); ++ usePermission = getBoolean("anti-xray.use-permission", false); ++ hiddenBlocks = getList("anti-xray.hidden-blocks", Arrays.asList("gold_ore", "iron_ore", "coal_ore", "lapis_ore", "mossy_cobblestone", "obsidian", "chest", "diamond_ore", "redstone_ore", "clay", "emerald_ore", "ender_chest")); ++ replacementBlocks = getList("anti-xray.replacement-blocks", Arrays.asList("stone", "oak_planks")); ++ if (PaperConfig.version < 19) { ++ hiddenBlocks.remove("lit_redstone_ore"); ++ int index = replacementBlocks.indexOf("planks"); ++ if (index != -1) { ++ replacementBlocks.set(index, "oak_planks"); ++ } ++ set("anti-xray.hidden-blocks", hiddenBlocks); ++ set("anti-xray.replacement-blocks", replacementBlocks); ++ } ++ log("Anti-Xray: " + (antiXray ? "enabled" : "disabled") + " / Engine Mode: " + engineMode.getDescription() + " / Up to " + ((maxChunkSectionIndex + 1) * 16) + " blocks / Update Radius: " + updateRadius); ++ if (antiXray && usePermission) { ++ Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java +new file mode 100644 +index 0000000000000000000000000000000000000000..83a023ae018cbb79b5f151b1c7a5c8ba0c3bf1bf +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java +@@ -0,0 +1,45 @@ ++package com.destroystokyo.paper.antixray; ++ ++import net.minecraft.core.BlockPosition; ++import net.minecraft.core.EnumDirection; ++import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; ++import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.PlayerInteractManager; ++import net.minecraft.world.level.World; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.chunk.Chunk; ++import net.minecraft.world.level.chunk.ChunkSection; ++import net.minecraft.world.level.chunk.IChunkAccess; ++ ++public class ChunkPacketBlockController { ++ ++ public static final ChunkPacketBlockController NO_OPERATION_INSTANCE = new ChunkPacketBlockController(); ++ ++ protected ChunkPacketBlockController() { ++ ++ } ++ ++ public IBlockData[] getPredefinedBlockData(World world, IChunkAccess chunk, ChunkSection chunkSection, boolean initializeBlocks) { ++ return null; ++ } ++ ++ public boolean shouldModify(EntityPlayer entityPlayer, Chunk chunk, int chunkSectionSelector) { ++ return false; ++ } ++ ++ public ChunkPacketInfo getChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { ++ return null; ++ } ++ ++ public void modifyBlocks(PacketPlayOutMapChunk packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { ++ packetPlayOutMapChunk.setReady(true); ++ } ++ ++ public void onBlockChange(World world, BlockPosition blockPosition, IBlockData newBlockData, IBlockData oldBlockData, int flag) { ++ ++ } ++ ++ public void onPlayerLeftClickBlock(PlayerInteractManager playerInteractManager, BlockPosition blockPosition, EnumDirection enumDirection) { ++ ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java +new file mode 100644 +index 0000000000000000000000000000000000000000..cd3b5b62d470ab6753b44f9b13dcf5522e4cbd15 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java +@@ -0,0 +1,650 @@ ++package com.destroystokyo.paper.antixray; ++ ++import java.util.ArrayList; ++import java.util.LinkedHashSet; ++import java.util.LinkedList; ++import java.util.List; ++import java.util.Set; ++import java.util.concurrent.Executor; ++import java.util.concurrent.ThreadLocalRandom; ++import java.util.function.IntSupplier; ++ ++import net.minecraft.core.BlockPosition; ++import net.minecraft.core.EnumDirection; ++import net.minecraft.core.IRegistry; ++import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; ++import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.PlayerInteractManager; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.level.World; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.chunk.Chunk; ++import net.minecraft.world.level.chunk.ChunkEmpty; ++import net.minecraft.world.level.chunk.ChunkSection; ++import net.minecraft.world.level.chunk.DataPalette; ++import net.minecraft.world.level.chunk.IChunkAccess; ++import org.bukkit.Bukkit; ++import org.bukkit.World.Environment; ++ ++import com.destroystokyo.paper.PaperWorldConfig; ++ ++public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockController { ++ ++ private final Executor executor; ++ private final EngineMode engineMode; ++ private final int maxChunkSectionIndex; ++ private final int updateRadius; ++ private final boolean usePermission; ++ private final IBlockData[] predefinedBlockData; ++ private final IBlockData[] predefinedBlockDataFull; ++ private final IBlockData[] predefinedBlockDataStone; ++ private final IBlockData[] predefinedBlockDataNetherrack; ++ private final IBlockData[] predefinedBlockDataEndStone; ++ private final int[] predefinedBlockDataBitsGlobal; ++ private final int[] predefinedBlockDataBitsStoneGlobal; ++ private final int[] predefinedBlockDataBitsNetherrackGlobal; ++ private final int[] predefinedBlockDataBitsEndStoneGlobal; ++ private final boolean[] solidGlobal = new boolean[Block.REGISTRY_ID.size()]; ++ private final boolean[] obfuscateGlobal = new boolean[Block.REGISTRY_ID.size()]; ++ private final ChunkSection[] emptyNearbyChunkSections = {Chunk.EMPTY_CHUNK_SECTION, Chunk.EMPTY_CHUNK_SECTION, Chunk.EMPTY_CHUNK_SECTION, Chunk.EMPTY_CHUNK_SECTION}; ++ private final int maxBlockYUpdatePosition; ++ ++ public ChunkPacketBlockControllerAntiXray(World world, Executor executor) { ++ PaperWorldConfig paperWorldConfig = world.paperConfig; ++ engineMode = paperWorldConfig.engineMode; ++ maxChunkSectionIndex = paperWorldConfig.maxChunkSectionIndex; ++ updateRadius = paperWorldConfig.updateRadius; ++ usePermission = paperWorldConfig.usePermission; ++ ++ this.executor = executor; ++ ++ List toObfuscate; ++ ++ if (engineMode == EngineMode.HIDE) { ++ toObfuscate = paperWorldConfig.hiddenBlocks; ++ predefinedBlockData = null; ++ predefinedBlockDataFull = null; ++ predefinedBlockDataStone = new IBlockData[] {Blocks.STONE.getBlockData()}; ++ predefinedBlockDataNetherrack = new IBlockData[] {Blocks.NETHERRACK.getBlockData()}; ++ predefinedBlockDataEndStone = new IBlockData[] {Blocks.END_STONE.getBlockData()}; ++ predefinedBlockDataBitsGlobal = null; ++ predefinedBlockDataBitsStoneGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.STONE.getBlockData())}; ++ predefinedBlockDataBitsNetherrackGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.NETHERRACK.getBlockData())}; ++ predefinedBlockDataBitsEndStoneGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.END_STONE.getBlockData())}; ++ } else { ++ toObfuscate = new ArrayList<>(paperWorldConfig.replacementBlocks); ++ List predefinedBlockDataList = new LinkedList(); ++ ++ for (String id : paperWorldConfig.hiddenBlocks) { ++ Block block = IRegistry.BLOCK.getOptional(new MinecraftKey(id)).orElse(null); ++ ++ if (block != null && !block.isTileEntity()) { ++ toObfuscate.add(id); ++ predefinedBlockDataList.add(block.getBlockData()); ++ } ++ } ++ ++ // The doc of the LinkedHashSet(Collection c) constructor doesn't specify that the insertion order is the predictable iteration order of the specified Collection, although it is in the implementation ++ Set predefinedBlockDataSet = new LinkedHashSet(); ++ // Therefore addAll(Collection c) is used, which guarantees this order in the doc ++ predefinedBlockDataSet.addAll(predefinedBlockDataList); ++ predefinedBlockData = predefinedBlockDataSet.size() == 0 ? new IBlockData[] {Blocks.DIAMOND_ORE.getBlockData()} : predefinedBlockDataSet.toArray(new IBlockData[0]); ++ predefinedBlockDataFull = predefinedBlockDataSet.size() == 0 ? new IBlockData[] {Blocks.DIAMOND_ORE.getBlockData()} : predefinedBlockDataList.toArray(new IBlockData[0]); ++ predefinedBlockDataStone = null; ++ predefinedBlockDataNetherrack = null; ++ predefinedBlockDataEndStone = null; ++ predefinedBlockDataBitsGlobal = new int[predefinedBlockDataFull.length]; ++ ++ for (int i = 0; i < predefinedBlockDataFull.length; i++) { ++ predefinedBlockDataBitsGlobal[i] = ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(predefinedBlockDataFull[i]); ++ } ++ ++ predefinedBlockDataBitsStoneGlobal = null; ++ predefinedBlockDataBitsNetherrackGlobal = null; ++ predefinedBlockDataBitsEndStoneGlobal = null; ++ } ++ ++ for (String id : toObfuscate) { ++ Block block = IRegistry.BLOCK.getOptional(new MinecraftKey(id)).orElse(null); ++ ++ // Don't obfuscate air because air causes unnecessary block updates and causes block updates to fail in the void ++ if (block != null && !block.getBlockData().isAir()) { ++ // Replace all block states of a specified block ++ // No OBFHELPER for nms.BlockStateList#a() due to too many decompile errors ++ // The OBFHELPER should be getBlockDataList() ++ for (IBlockData blockData : block.getStates().a()) { ++ obfuscateGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(blockData)] = true; ++ } ++ } ++ } ++ ++ ChunkEmpty emptyChunk = new ChunkEmpty(world, new ChunkCoordIntPair(0, 0)); ++ BlockPosition zeroPos = new BlockPosition(0, 0, 0); ++ ++ for (int i = 0; i < solidGlobal.length; i++) { ++ IBlockData blockData = ChunkSection.GLOBAL_PALETTE.getObject(i); ++ ++ if (blockData != null) { ++ solidGlobal[i] = blockData.isOccluding(emptyChunk, zeroPos) ++ && blockData.getBlock() != Blocks.SPAWNER && blockData.getBlock() != Blocks.BARRIER && blockData.getBlock() != Blocks.SHULKER_BOX && blockData.getBlock() != Blocks.SLIME_BLOCK || paperWorldConfig.lavaObscures && blockData == Blocks.LAVA.getBlockData(); ++ // Comparing blockData == Blocks.LAVA.getBlockData() instead of blockData.getBlock() == Blocks.LAVA ensures that only "stationary lava" is used ++ // shulker box checks TE. ++ } ++ } ++ ++ this.maxBlockYUpdatePosition = (maxChunkSectionIndex + 1) * 16 + updateRadius - 1; ++ } ++ ++ private int getPredefinedBlockDataFullLength() { ++ return engineMode == EngineMode.HIDE ? 1 : predefinedBlockDataFull.length; ++ } ++ ++ @Override ++ public IBlockData[] getPredefinedBlockData(World world, IChunkAccess chunk, ChunkSection chunkSection, boolean initializeBlocks) { ++ // Return the block data which should be added to the data palettes so that they can be used for the obfuscation ++ if (chunkSection.getYPosition() >> 4 <= maxChunkSectionIndex) { ++ switch (engineMode) { ++ case HIDE: ++ switch (world.getWorld().getEnvironment()) { ++ case NETHER: ++ return predefinedBlockDataNetherrack; ++ case THE_END: ++ return predefinedBlockDataEndStone; ++ default: ++ return predefinedBlockDataStone; ++ } ++ default: ++ return predefinedBlockData; ++ } ++ } ++ ++ return null; ++ } ++ ++ @Override ++ public boolean shouldModify(EntityPlayer entityPlayer, Chunk chunk, int chunkSectionSelector) { ++ return !usePermission || !entityPlayer.getBukkitEntity().hasPermission("paper.antixray.bypass"); ++ } ++ ++ @Override ++ public ChunkPacketInfoAntiXray getChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { ++ // Return a new instance to collect data and objects in the right state while creating the chunk packet for thread safe access later ++ // Note: As of 1.14 this has to be moved later due to the chunk system. ++ ChunkPacketInfoAntiXray chunkPacketInfoAntiXray = new ChunkPacketInfoAntiXray(packetPlayOutMapChunk, chunk, chunkSectionSelector, this); ++ return chunkPacketInfoAntiXray; ++ } ++ ++ @Override ++ public void modifyBlocks(PacketPlayOutMapChunk packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { ++ if (chunkPacketInfo == null) { ++ packetPlayOutMapChunk.setReady(true); ++ return; ++ } ++ ++ if (!Bukkit.isPrimaryThread()) { ++ // plugins? ++ MinecraftServer.getServer().scheduleOnMain(() -> { ++ this.modifyBlocks(packetPlayOutMapChunk, chunkPacketInfo); ++ }); ++ return; ++ } ++ ++ Chunk chunk = chunkPacketInfo.getChunk(); ++ int x = chunk.getPos().x; ++ int z = chunk.getPos().z; ++ WorldServer world = (WorldServer)chunk.world; ++ ((ChunkPacketInfoAntiXray) chunkPacketInfo).setNearbyChunks( ++ (Chunk) world.getChunkIfLoadedImmediately(x - 1, z), ++ (Chunk) world.getChunkIfLoadedImmediately(x + 1, z), ++ (Chunk) world.getChunkIfLoadedImmediately(x, z - 1), ++ (Chunk) world.getChunkIfLoadedImmediately(x, z + 1)); ++ ++ executor.execute((ChunkPacketInfoAntiXray) chunkPacketInfo); ++ } ++ ++ // Actually these fields should be variables inside the obfuscate method but in sync mode or with SingleThreadExecutor in async mode it's okay (even without ThreadLocal) ++ // If an ExecutorService with multiple threads is used, ThreadLocal must be used here ++ private final ThreadLocal predefinedBlockDataBits = ThreadLocal.withInitial(() -> new int[getPredefinedBlockDataFullLength()]); ++ private static final ThreadLocal solid = ThreadLocal.withInitial(() -> new boolean[Block.REGISTRY_ID.size()]); ++ private static final ThreadLocal obfuscate = ThreadLocal.withInitial(() -> new boolean[Block.REGISTRY_ID.size()]); ++ // These boolean arrays represent chunk layers, true means don't obfuscate, false means obfuscate ++ private static final ThreadLocal current = ThreadLocal.withInitial(() -> new boolean[16][16]); ++ private static final ThreadLocal next = ThreadLocal.withInitial(() -> new boolean[16][16]); ++ private static final ThreadLocal nextNext = ThreadLocal.withInitial(() -> new boolean[16][16]); ++ ++ public void obfuscate(ChunkPacketInfoAntiXray chunkPacketInfoAntiXray) { ++ int[] predefinedBlockDataBits = this.predefinedBlockDataBits.get(); ++ boolean[] solid = this.solid.get(); ++ boolean[] obfuscate = this.obfuscate.get(); ++ boolean[][] current = this.current.get(); ++ boolean[][] next = this.next.get(); ++ boolean[][] nextNext = this.nextNext.get(); ++ // dataBitsReader, dataBitsWriter and nearbyChunkSections could also be reused (with ThreadLocal if necessary) but it's not worth it ++ DataBitsReader dataBitsReader = new DataBitsReader(); ++ DataBitsWriter dataBitsWriter = new DataBitsWriter(); ++ ChunkSection[] nearbyChunkSections = new ChunkSection[4]; ++ boolean[] solidTemp = null; ++ boolean[] obfuscateTemp = null; ++ dataBitsReader.setDataBits(chunkPacketInfoAntiXray.getData()); ++ dataBitsWriter.setDataBits(chunkPacketInfoAntiXray.getData()); ++ int numberOfBlocks = predefinedBlockDataBits.length; ++ // Keep the lambda expressions as simple as possible. They are used very frequently. ++ IntSupplier random = numberOfBlocks == 1 ? (() -> 0) : new IntSupplier() { ++ private int state; ++ ++ { ++ while ((state = ThreadLocalRandom.current().nextInt()) == 0); ++ } ++ ++ @Override ++ public int getAsInt() { ++ // https://en.wikipedia.org/wiki/Xorshift ++ state ^= state << 13; ++ state ^= state >>> 17; ++ state ^= state << 5; ++ // https://www.pcg-random.org/posts/bounded-rands.html ++ return (int) ((Integer.toUnsignedLong(state) * numberOfBlocks) >>> 32); ++ } ++ }; ++ ++ for (int chunkSectionIndex = 0; chunkSectionIndex <= maxChunkSectionIndex; chunkSectionIndex++) { ++ if (chunkPacketInfoAntiXray.isWritten(chunkSectionIndex) && chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) != null) { ++ int[] predefinedBlockDataBitsTemp; ++ ++ if (chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex) == ChunkSection.GLOBAL_PALETTE) { ++ predefinedBlockDataBitsTemp = engineMode == EngineMode.HIDE ? chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.NETHER ? predefinedBlockDataBitsNetherrackGlobal : chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.THE_END ? predefinedBlockDataBitsEndStoneGlobal : predefinedBlockDataBitsStoneGlobal : predefinedBlockDataBitsGlobal; ++ } else { ++ // If it's this.predefinedBlockData, use this.predefinedBlockDataFull instead ++ IBlockData[] predefinedBlockDataFull = chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) == predefinedBlockData ? this.predefinedBlockDataFull : chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex); ++ predefinedBlockDataBitsTemp = predefinedBlockDataBits; ++ ++ for (int i = 0; i < predefinedBlockDataBitsTemp.length; i++) { ++ predefinedBlockDataBitsTemp[i] = chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex).getOrCreateIdFor(predefinedBlockDataFull[i]); ++ } ++ } ++ ++ dataBitsWriter.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); ++ ++ // Check if the chunk section below was not obfuscated ++ if (chunkSectionIndex == 0 || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex - 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex - 1) == null) { ++ // If so, initialize some stuff ++ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); ++ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); ++ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), solid, solidGlobal); ++ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), obfuscate, obfuscateGlobal); ++ // Read the blocks of the upper layer of the chunk section below if it exists ++ ChunkSection belowChunkSection = null; ++ boolean skipFirstLayer = chunkSectionIndex == 0 || (belowChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex - 1]) == Chunk.EMPTY_CHUNK_SECTION; ++ ++ for (int z = 0; z < 16; z++) { ++ for (int x = 0; x < 16; x++) { ++ current[z][x] = true; ++ next[z][x] = skipFirstLayer || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(belowChunkSection.getType(x, 15, z))]; ++ } ++ } ++ ++ // Abuse the obfuscateLayer method to read the blocks of the first layer of the current chunk section ++ dataBitsWriter.setBitsPerObject(0); ++ obfuscateLayer(-1, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, emptyNearbyChunkSections, random); ++ } ++ ++ dataBitsWriter.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); ++ nearbyChunkSections[0] = chunkPacketInfoAntiXray.getNearbyChunks()[0] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[0].getSections()[chunkSectionIndex]; ++ nearbyChunkSections[1] = chunkPacketInfoAntiXray.getNearbyChunks()[1] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[1].getSections()[chunkSectionIndex]; ++ nearbyChunkSections[2] = chunkPacketInfoAntiXray.getNearbyChunks()[2] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[2].getSections()[chunkSectionIndex]; ++ nearbyChunkSections[3] = chunkPacketInfoAntiXray.getNearbyChunks()[3] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[3].getSections()[chunkSectionIndex]; ++ ++ // Obfuscate all layers of the current chunk section except the upper one ++ for (int y = 0; y < 15; y++) { ++ boolean[][] temp = current; ++ current = next; ++ next = nextNext; ++ nextNext = temp; ++ obfuscateLayer(y, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); ++ } ++ ++ // Check if the chunk section above doesn't need obfuscation ++ if (chunkSectionIndex == maxChunkSectionIndex || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex + 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex + 1) == null) { ++ // If so, obfuscate the upper layer of the current chunk section by reading blocks of the first layer from the chunk section above if it exists ++ ChunkSection aboveChunkSection; ++ ++ if (chunkSectionIndex != 15 && (aboveChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex + 1]) != Chunk.EMPTY_CHUNK_SECTION) { ++ boolean[][] temp = current; ++ current = next; ++ next = nextNext; ++ nextNext = temp; ++ ++ for (int z = 0; z < 16; z++) { ++ for (int x = 0; x < 16; x++) { ++ if (!solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(aboveChunkSection.getType(x, 0, z))]) { ++ current[z][x] = true; ++ } ++ } ++ } ++ ++ // There is nothing to read anymore ++ dataBitsReader.setBitsPerObject(0); ++ solid[0] = true; ++ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solid, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); ++ } ++ } else { ++ // If not, initialize the reader and other stuff for the chunk section above to obfuscate the upper layer of the current chunk section ++ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex + 1)); ++ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex + 1)); ++ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), solid, solidGlobal); ++ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), obfuscate, obfuscateGlobal); ++ boolean[][] temp = current; ++ current = next; ++ next = nextNext; ++ nextNext = temp; ++ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); ++ } ++ ++ dataBitsWriter.finish(); ++ } ++ } ++ ++ chunkPacketInfoAntiXray.getPacketPlayOutMapChunk().setReady(true); ++ } ++ ++ private void obfuscateLayer(int y, DataBitsReader dataBitsReader, DataBitsWriter dataBitsWriter, boolean[] solid, boolean[] obfuscate, int[] predefinedBlockDataBits, boolean[][] current, boolean[][] next, boolean[][] nextNext, ChunkSection[] nearbyChunkSections, IntSupplier random) { ++ // First block of first line ++ int dataBits = dataBitsReader.read(); ++ ++ if (nextNext[0][0] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[0][1] = true; ++ next[1][0] = true; ++ } else { ++ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(0, y, 15))] || nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, 0))] || current[0][0]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[0][0] = true; ++ } ++ ++ // First line ++ for (int x = 1; x < 15; x++) { ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[0][x] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[0][x - 1] = true; ++ next[0][x + 1] = true; ++ next[1][x] = true; ++ } else { ++ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(x, y, 15))] || current[0][x]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[0][x] = true; ++ } ++ } ++ ++ // Last block of first line ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[0][15] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[0][14] = true; ++ next[1][15] = true; ++ } else { ++ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(15, y, 15))] || nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, 0))] || current[0][15]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[0][15] = true; ++ } ++ ++ // All inner lines ++ for (int z = 1; z < 15; z++) { ++ // First block ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[z][0] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[z][1] = true; ++ next[z - 1][0] = true; ++ next[z + 1][0] = true; ++ } else { ++ if (nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, z))] || current[z][0]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[z][0] = true; ++ } ++ ++ // All inner blocks ++ for (int x = 1; x < 15; x++) { ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[z][x] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[z][x - 1] = true; ++ next[z][x + 1] = true; ++ next[z - 1][x] = true; ++ next[z + 1][x] = true; ++ } else { ++ if (current[z][x]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[z][x] = true; ++ } ++ } ++ ++ // Last block ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[z][15] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[z][14] = true; ++ next[z - 1][15] = true; ++ next[z + 1][15] = true; ++ } else { ++ if (nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, z))] || current[z][15]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[z][15] = true; ++ } ++ } ++ ++ // First block of last line ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[15][0] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[15][1] = true; ++ next[14][0] = true; ++ } else { ++ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(0, y, 0))] || nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, 15))] || current[15][0]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[15][0] = true; ++ } ++ ++ // Last line ++ for (int x = 1; x < 15; x++) { ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[15][x] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[15][x - 1] = true; ++ next[15][x + 1] = true; ++ next[14][x] = true; ++ } else { ++ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(x, y, 0))] || current[15][x]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[15][x] = true; ++ } ++ } ++ ++ // Last block of last line ++ dataBits = dataBitsReader.read(); ++ ++ if (nextNext[15][15] = !solid[dataBits]) { ++ dataBitsWriter.skip(); ++ next[15][14] = true; ++ next[14][15] = true; ++ } else { ++ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(15, y, 0))] || nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, 15))] || current[15][15]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[15][15] = true; ++ } ++ } ++ ++ private boolean[] readDataPalette(DataPalette dataPalette, boolean[] temp, boolean[] global) { ++ if (dataPalette == ChunkSection.GLOBAL_PALETTE) { ++ return global; ++ } ++ ++ IBlockData blockData; ++ ++ for (int i = 0; (blockData = dataPalette.getObject(i)) != null; i++) { ++ temp[i] = global[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(blockData)]; ++ } ++ ++ return temp; ++ } ++ ++ @Override ++ public void onBlockChange(World world, BlockPosition blockPosition, IBlockData newBlockData, IBlockData oldBlockData, int flag) { ++ if (oldBlockData != null && solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(oldBlockData)] && !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(newBlockData)] && blockPosition.getY() <= maxBlockYUpdatePosition) { ++ updateNearbyBlocks(world, blockPosition); ++ } ++ } ++ ++ @Override ++ public void onPlayerLeftClickBlock(PlayerInteractManager playerInteractManager, BlockPosition blockPosition, EnumDirection enumDirection) { ++ if (blockPosition.getY() <= maxBlockYUpdatePosition) { ++ updateNearbyBlocks(playerInteractManager.world, blockPosition); ++ } ++ } ++ ++ private void updateNearbyBlocks(World world, BlockPosition blockPosition) { ++ if (updateRadius >= 2) { ++ BlockPosition temp = blockPosition.west(); ++ updateBlock(world, temp); ++ updateBlock(world, temp.west()); ++ updateBlock(world, temp.down()); ++ updateBlock(world, temp.up()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.east()); ++ updateBlock(world, temp.east()); ++ updateBlock(world, temp.down()); ++ updateBlock(world, temp.up()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.down()); ++ updateBlock(world, temp.down()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.up()); ++ updateBlock(world, temp.up()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.north()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp = blockPosition.south()); ++ updateBlock(world, temp.south()); ++ } else if (updateRadius == 1) { ++ updateBlock(world, blockPosition.west()); ++ updateBlock(world, blockPosition.east()); ++ updateBlock(world, blockPosition.down()); ++ updateBlock(world, blockPosition.up()); ++ updateBlock(world, blockPosition.north()); ++ updateBlock(world, blockPosition.south()); ++ } else { ++ // Do nothing if updateRadius <= 0 (test mode) ++ } ++ } ++ ++ private void updateBlock(World world, BlockPosition blockPosition) { ++ IBlockData blockData = world.getTypeIfLoaded(blockPosition); ++ ++ if (blockData != null && obfuscateGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(blockData)]) { ++ // world.notify(blockPosition, blockData, blockData, 3); ++ ((WorldServer)world).getChunkProvider().flagDirty(blockPosition); // We only need to re-send to client ++ } ++ } ++ ++ public enum EngineMode { ++ ++ HIDE(1, "hide ores"), ++ OBFUSCATE(2, "obfuscate"); ++ ++ private final int id; ++ private final String description; ++ ++ EngineMode(int id, String description) { ++ this.id = id; ++ this.description = description; ++ } ++ ++ public static EngineMode getById(int id) { ++ for (EngineMode engineMode : values()) { ++ if (engineMode.id == id) { ++ return engineMode; ++ } ++ } ++ ++ return null; ++ } ++ ++ public int getId() { ++ return id; ++ } ++ ++ public String getDescription() { ++ return description; ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java +new file mode 100644 +index 0000000000000000000000000000000000000000..22c9adefc3e51e9e4b8d611a40d1497d2a16a8d2 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java +@@ -0,0 +1,81 @@ ++package com.destroystokyo.paper.antixray; ++ ++import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; ++import net.minecraft.world.level.chunk.Chunk; ++import net.minecraft.world.level.chunk.DataPalette; ++ ++public class ChunkPacketInfo { ++ ++ private final PacketPlayOutMapChunk packetPlayOutMapChunk; ++ private final Chunk chunk; ++ private final int chunkSectionSelector; ++ private byte[] data; ++ private final int[] bitsPerObject = new int[16]; ++ private final Object[] dataPalettes = new Object[16]; ++ private final int[] dataBitsIndexes = new int[16]; ++ private final Object[][] predefinedObjects = new Object[16][]; ++ ++ public ChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { ++ this.packetPlayOutMapChunk = packetPlayOutMapChunk; ++ this.chunk = chunk; ++ this.chunkSectionSelector = chunkSectionSelector; ++ } ++ ++ public PacketPlayOutMapChunk getPacketPlayOutMapChunk() { ++ return packetPlayOutMapChunk; ++ } ++ ++ public Chunk getChunk() { ++ return chunk; ++ } ++ ++ public int getChunkSectionSelector() { ++ return chunkSectionSelector; ++ } ++ ++ public byte[] getData() { ++ return data; ++ } ++ ++ public void setData(byte[] data) { ++ this.data = data; ++ } ++ ++ public int getBitsPerObject(int chunkSectionIndex) { ++ return bitsPerObject[chunkSectionIndex]; ++ } ++ ++ public void setBitsPerObject(int chunkSectionIndex, int bitsPerObject) { ++ this.bitsPerObject[chunkSectionIndex] = bitsPerObject; ++ } ++ ++ @SuppressWarnings("unchecked") ++ public DataPalette getDataPalette(int chunkSectionIndex) { ++ return (DataPalette) dataPalettes[chunkSectionIndex]; ++ } ++ ++ public void setDataPalette(int chunkSectionIndex, DataPalette dataPalette) { ++ dataPalettes[chunkSectionIndex] = dataPalette; ++ } ++ ++ public int getDataBitsIndex(int chunkSectionIndex) { ++ return dataBitsIndexes[chunkSectionIndex]; ++ } ++ ++ public void setDataBitsIndex(int chunkSectionIndex, int dataBitsIndex) { ++ dataBitsIndexes[chunkSectionIndex] = dataBitsIndex; ++ } ++ ++ @SuppressWarnings("unchecked") ++ public T[] getPredefinedObjects(int chunkSectionIndex) { ++ return (T[]) predefinedObjects[chunkSectionIndex]; ++ } ++ ++ public void setPredefinedObjects(int chunkSectionIndex, T[] predefinedObjects) { ++ this.predefinedObjects[chunkSectionIndex] = predefinedObjects; ++ } ++ ++ public boolean isWritten(int chunkSectionIndex) { ++ return bitsPerObject[chunkSectionIndex] != 0; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4b64964e52b11bea4d2c0d0f64f55ad08d2189be +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java +@@ -0,0 +1,30 @@ ++package com.destroystokyo.paper.antixray; ++ ++import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.chunk.Chunk; ++ ++public final class ChunkPacketInfoAntiXray extends ChunkPacketInfo implements Runnable { ++ ++ private Chunk[] nearbyChunks; ++ private final ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray; ++ ++ public ChunkPacketInfoAntiXray(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector, ++ ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray) { ++ super(packetPlayOutMapChunk, chunk, chunkSectionSelector); ++ this.chunkPacketBlockControllerAntiXray = chunkPacketBlockControllerAntiXray; ++ } ++ ++ public Chunk[] getNearbyChunks() { ++ return nearbyChunks; ++ } ++ ++ public void setNearbyChunks(Chunk... nearbyChunks) { ++ this.nearbyChunks = nearbyChunks; ++ } ++ ++ @Override ++ public void run() { ++ chunkPacketBlockControllerAntiXray.obfuscate(this); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..298ea423084dbcc1b61f991bcd82b8ae51bf0977 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java +@@ -0,0 +1,51 @@ ++package com.destroystokyo.paper.antixray; ++ ++public final class DataBitsReader { ++ ++ private byte[] dataBits; ++ private int bitsPerObject; ++ private int mask; ++ private int longInDataBitsIndex; ++ private int bitInLongIndex; ++ private long current; ++ ++ public void setDataBits(byte[] dataBits) { ++ this.dataBits = dataBits; ++ } ++ ++ public void setBitsPerObject(int bitsPerObject) { ++ this.bitsPerObject = bitsPerObject; ++ mask = (1 << bitsPerObject) - 1; ++ } ++ ++ public void setIndex(int index) { ++ this.longInDataBitsIndex = index; ++ bitInLongIndex = 0; ++ init(); ++ } ++ ++ private void init() { ++ if (dataBits.length > longInDataBitsIndex + 7) { ++ current = ((((long) dataBits[longInDataBitsIndex]) << 56) ++ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) ++ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) ++ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) ++ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) ++ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) ++ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) ++ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); ++ } ++ } ++ ++ public int read() { ++ if (bitInLongIndex + bitsPerObject > 64) { ++ bitInLongIndex = 0; ++ longInDataBitsIndex += 8; ++ init(); ++ } ++ ++ int value = (int) (current >>> bitInLongIndex) & mask; ++ bitInLongIndex += bitsPerObject; ++ return value; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..333763936897befda5bb6c077944d2667f922799 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java +@@ -0,0 +1,79 @@ ++package com.destroystokyo.paper.antixray; ++ ++public final class DataBitsWriter { ++ ++ private byte[] dataBits; ++ private int bitsPerObject; ++ private long mask; ++ private int longInDataBitsIndex; ++ private int bitInLongIndex; ++ private long current; ++ private boolean dirty; ++ ++ public void setDataBits(byte[] dataBits) { ++ this.dataBits = dataBits; ++ } ++ ++ public void setBitsPerObject(int bitsPerObject) { ++ this.bitsPerObject = bitsPerObject; ++ mask = (1 << bitsPerObject) - 1; ++ } ++ ++ public void setIndex(int index) { ++ this.longInDataBitsIndex = index; ++ bitInLongIndex = 0; ++ init(); ++ } ++ ++ private void init() { ++ if (dataBits.length > longInDataBitsIndex + 7) { ++ current = ((((long) dataBits[longInDataBitsIndex]) << 56) ++ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) ++ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) ++ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) ++ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) ++ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) ++ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) ++ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); ++ } ++ ++ dirty = false; ++ } ++ ++ public void finish() { ++ if (dirty && dataBits.length > longInDataBitsIndex + 7) { ++ dataBits[longInDataBitsIndex] = (byte) (current >> 56 & 0xff); ++ dataBits[longInDataBitsIndex + 1] = (byte) (current >> 48 & 0xff); ++ dataBits[longInDataBitsIndex + 2] = (byte) (current >> 40 & 0xff); ++ dataBits[longInDataBitsIndex + 3] = (byte) (current >> 32 & 0xff); ++ dataBits[longInDataBitsIndex + 4] = (byte) (current >> 24 & 0xff); ++ dataBits[longInDataBitsIndex + 5] = (byte) (current >> 16 & 0xff); ++ dataBits[longInDataBitsIndex + 6] = (byte) (current >> 8 & 0xff); ++ dataBits[longInDataBitsIndex + 7] = (byte) (current & 0xff); ++ } ++ } ++ ++ public void write(int value) { ++ if (bitInLongIndex + bitsPerObject > 64) { ++ finish(); ++ bitInLongIndex = 0; ++ longInDataBitsIndex += 8; ++ init(); ++ } ++ ++ current = current & ~(mask << bitInLongIndex) | (value & mask) << bitInLongIndex; ++ dirty = true; ++ bitInLongIndex += bitsPerObject; ++ } ++ ++ public void skip() { ++ bitInLongIndex += bitsPerObject; ++ ++ if (bitInLongIndex > 64) { ++ finish(); ++ bitInLongIndex = bitsPerObject; ++ longInDataBitsIndex += 8; ++ init(); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java +index a7d10d124021f3427f23fcd533f885367b64515c..3047cf8c4ec1b664d6b790f18d2b1657e4b00435 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java +@@ -1,5 +1,6 @@ + package net.minecraft.network.protocol.game; + ++import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info + import com.google.common.collect.Lists; + import io.netty.buffer.ByteBuf; + import io.netty.buffer.Unpooled; +@@ -16,6 +17,7 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.block.entity.TileEntity; + import net.minecraft.world.level.block.entity.TileEntitySkull; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.BiomeStorage; + import net.minecraft.world.level.chunk.Chunk; + import net.minecraft.world.level.chunk.ChunkSection; +@@ -33,7 +35,13 @@ public class PacketPlayOutMapChunk implements Packet { + private List g; + private boolean h; + +- public PacketPlayOutMapChunk() {} ++ // Paper start - Async-Anti-Xray - Set the ready flag to true ++ private volatile boolean ready; // Paper - Async-Anti-Xray - Ready flag for the network manager ++ public PacketPlayOutMapChunk() { ++ this.ready = true; ++ } ++ // Paper end ++ + // Paper start + private final java.util.List extraPackets = new java.util.ArrayList<>(); + private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); +@@ -43,7 +51,11 @@ public class PacketPlayOutMapChunk implements Packet { + return extraPackets; + } + // Paper end +- public PacketPlayOutMapChunk(Chunk chunk, int i) { ++ // Paper start - Anti-Xray - Add chunk packet info ++ @Deprecated public PacketPlayOutMapChunk(Chunk chunk, int i) { this(chunk, i, true); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public PacketPlayOutMapChunk(Chunk chunk, int i, boolean modifyBlocks) { ++ ChunkPacketInfo chunkPacketInfo = modifyBlocks ? chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i) : null; ++ // Paper end + ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); + + this.a = chunkcoordintpair.x; +@@ -66,7 +78,12 @@ public class PacketPlayOutMapChunk implements Packet { + } + + this.f = new byte[this.a(chunk, i)]; +- this.c = this.a(new PacketDataSerializer(this.j()), chunk, i); ++ // Paper start - Anti-Xray - Add chunk packet info ++ if (chunkPacketInfo != null) { ++ chunkPacketInfo.setData(this.getData()); ++ } ++ this.c = this.writeChunk(new PacketDataSerializer(this.j()), chunk, i, chunkPacketInfo); ++ // Paper end + this.g = Lists.newArrayList(); + iterator = chunk.getTileEntities().entrySet().iterator(); + int totalTileEntities = 0; // Paper +@@ -93,8 +110,19 @@ public class PacketPlayOutMapChunk implements Packet { + this.g.add(nbttagcompound); + } + } ++ chunk.world.chunkPacketBlockController.modifyBlocks(this, chunkPacketInfo); // Paper - Anti-Xray - Modify blocks ++ } + ++ // Paper start - Async-Anti-Xray - Getter and Setter for the ready flag ++ @Override ++ public boolean isReady() { ++ return this.ready; ++ } ++ ++ public void setReady(boolean ready) { ++ this.ready = ready; + } ++ // Paper end + + @Override + public void a(PacketDataSerializer packetdataserializer) throws IOException { +@@ -160,8 +188,12 @@ public class PacketPlayOutMapChunk implements Packet { + return bytebuf; + } + +- public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, chunkSectionSelector); } // Paper - OBFHELPER +- public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i) { ++ // Paper start - Anti-Xray - Add chunk packet info ++ @Deprecated public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, chunkSectionSelector); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere ++ @Deprecated public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i) { return this.writeChunk(packetdataserializer, chunk, i, null); } // Notice for updates: Please make sure this method isn't used anywhere ++ public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector, ChunkPacketInfo chunkPacketInfo) { return this.a(packetDataSerializer, chunk, chunkSectionSelector, chunkPacketInfo); } // OBFHELPER ++ public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i, ChunkPacketInfo chunkPacketInfo) { ++ // Paper end + int j = 0; + ChunkSection[] achunksection = chunk.getSections(); + int k = 0; +@@ -171,7 +203,7 @@ public class PacketPlayOutMapChunk implements Packet { + + if (chunksection != Chunk.a && (!this.f() || !chunksection.c()) && (i & 1 << k) != 0) { + j |= 1 << k; +- chunksection.b(packetdataserializer); ++ chunksection.writeChunkSection(packetdataserializer, chunkPacketInfo); // Paper - Anti-Xray - Add chunk packet info + } + } + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index ca05fe4ed0773b94035c63f8f8db6c034f0b92e2..5a11765c8a7d754ec86d829fa5e85d2809dd937e 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -656,7 +656,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + this.g(chunkcoordintpair); +- return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a)); ++ return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter + }, this.executor); + } + +@@ -1404,9 +1404,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + } + ++ private final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER + private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { + if (apacket[0] == null) { +- apacket[0] = new PacketPlayOutMapChunk(chunk, 65535); ++ apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(entityplayer, chunk, 65535)); // Paper - Anti-Xray - Bypass + apacket[1] = new PacketPlayOutLightUpdate(chunk.getPos(), this.lightEngine, true); + } + +diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +index d86b1e528b53db809ac993aa2f1d2799d4f1a574..fbd8a6985a261396789c87e4b687140bd49cea0d 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java ++++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +@@ -309,6 +309,8 @@ public class PlayerInteractManager { + } + + } ++ ++ this.world.chunkPacketBlockController.onPlayerLeftClickBlock(this, blockposition, enumdirection); // Paper - Anti-Xray + } + + public void a(BlockPosition blockposition, PacketPlayInBlockDig.EnumPlayerDigType packetplayinblockdig_enumplayerdigtype, String s) { +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 12e34e1514f060ffef96cdd3ac57d0495dd37321..024e0bf39b73076fba5c4187c4ff5066e663cf7e 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -210,7 +210,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + // Add env and gen to constructor, WorldData -> WorldDataServer + public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { +- super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env); ++ super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor + this.pvpMode = minecraftserver.getPVP(); + convertable = convertable_conversionsession; + uuid = WorldUUID.getUUID(convertable_conversionsession.folder.toFile()); +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 12ac3608736b45447afe6b0d35ead1441390be5e..15da3511a9e57c320f4cf409852bee07109095bc 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -2,6 +2,8 @@ package net.minecraft.world.level; + + import co.aikar.timings.Timing; + import co.aikar.timings.Timings; ++import com.destroystokyo.paper.antixray.ChunkPacketBlockController; // Paper - Anti-Xray ++import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray; // Paper - Anti-Xray + import com.destroystokyo.paper.event.server.ServerExceptionEvent; + import com.destroystokyo.paper.exception.ServerInternalException; + import com.google.common.base.MoreObjects; +@@ -144,6 +146,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + + public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper ++ public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray + + public final co.aikar.timings.WorldTimingsHandler timings; // Paper + public static BlockPosition lastPhysicsProblem; // Spigot +@@ -165,9 +168,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return typeKey; + } + +- protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { ++ protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName()); // Spigot + this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper ++ this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray + this.generator = gen; + this.world = new CraftWorld((WorldServer) this, gen, env); + this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit +@@ -433,6 +437,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + // CraftBukkit end + + IBlockData iblockdata1 = chunk.setType(blockposition, iblockdata, (i & 64) != 0, (i & 1024) == 0); // CraftBukkit custom NO_PLACE flag ++ this.chunkPacketBlockController.onBlockChange(this, blockposition, iblockdata, iblockdata1, i); // Paper - Anti-Xray + + if (iblockdata1 == null) { + // CraftBukkit start - remove blockstate if failed (or the same) +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index 2690c44eaae193a259fe195c95e59d07d5e1cc5a..3fdce0e6fa34eb4b1eafc618068a3fb06abd5ec1 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -465,7 +465,7 @@ public class Chunk implements IChunkAccess { + return null; + } + +- chunksection = new ChunkSection(j >> 4 << 4); ++ chunksection = new ChunkSection(j >> 4 << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters + this.sections[j >> 4] = chunksection; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java +index 89efd0b68b04457e1cd617dcc8bb1a6ea1c4717c..9fb8d20e9e1a8cc716c32a100b1d70e90f385eca 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java +@@ -8,6 +8,7 @@ import net.minecraft.SystemUtils; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.IRegistry; + import net.minecraft.data.worldgen.biome.BiomeRegistry; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.PlayerChunk; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkCoordIntPair; +@@ -28,7 +29,7 @@ public class ChunkEmpty extends Chunk { + }); + + public ChunkEmpty(World world, ChunkCoordIntPair chunkcoordintpair) { +- super(world, chunkcoordintpair, new BiomeStorage(world.r().b(IRegistry.ay), ChunkEmpty.b)); ++ super(world, chunkcoordintpair, new BiomeStorage(MinecraftServer.getServer().getCustomRegistry().b(IRegistry.ay), ChunkEmpty.b)); // Paper - world isnt ready yet for anti xray use here, use server singleton for registry + } + + // Paper start +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +index eea4a30428293eaf7afbe303a37adec60b44c2b4..0b4e346daaea91565fde2f789fafa8b431a7b042 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +@@ -1,9 +1,11 @@ + package net.minecraft.world.level.chunk; + + import java.util.function.Predicate; ++import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info + import javax.annotation.Nullable; + import net.minecraft.nbt.GameProfileSerializer; + import net.minecraft.network.PacketDataSerializer; ++import net.minecraft.world.level.World; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.IBlockData; +@@ -18,16 +20,22 @@ public class ChunkSection { + private short e; + final DataPaletteBlock blockIds; // Paper - package-private + +- public ChunkSection(int i) { +- this(i, (short) 0, (short) 0, (short) 0); ++ // Paper start - Anti-Xray - Add parameters ++ @Deprecated public ChunkSection(int i) { this(i, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public ChunkSection(int i, IChunkAccess chunk, World world, boolean initializeBlocks) { ++ this(i, (short) 0, (short) 0, (short) 0, chunk, world, initializeBlocks); ++ // Paper end + } + +- public ChunkSection(int i, short short0, short short1, short short2) { ++ // Paper start - Anti-Xray - Add parameters ++ @Deprecated public ChunkSection(int i, short short0, short short1, short short2) { this(i, short0, short1, short2, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public ChunkSection(int i, short short0, short short1, short short2, IChunkAccess chunk, World world, boolean initializeBlocks) { ++ // Paper end + this.yPos = i; + this.nonEmptyBlockCount = short0; + this.tickingBlockCount = short1; + this.e = short2; +- this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); ++ this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData(), world == null ? null : world.chunkPacketBlockController.getPredefinedBlockData(world, chunk, this, initializeBlocks), initializeBlocks); // Paper - Anti-Xray - Add predefined block data + } + + public final IBlockData getType(int i, int j, int k) { // Paper +@@ -139,10 +147,14 @@ public class ChunkSection { + return this.blockIds; + } + +- public void writeChunkSection(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER +- public void b(PacketDataSerializer packetdataserializer) { ++ // Paper start - Anti-Xray - Add chunk packet info ++ @Deprecated public final void writeChunkSection(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere ++ @Deprecated public final void b(PacketDataSerializer packetdataserializer) { this.writeChunkSection(packetdataserializer, null); } // Notice for updates: Please make sure this method isn't used anywhere ++ public final void writeChunkSection(PacketDataSerializer packetDataSerializer, ChunkPacketInfo chunkPacketInfo) { this.b(packetDataSerializer, chunkPacketInfo); } // OBFHELPER ++ public void b(PacketDataSerializer packetdataserializer, ChunkPacketInfo chunkPacketInfo) { ++ // Paper end + packetdataserializer.writeShort(this.nonEmptyBlockCount); +- this.blockIds.b(packetdataserializer); ++ this.blockIds.writeDataPaletteBlock(packetdataserializer, chunkPacketInfo, this.yPos >> 4); // Paper - Anti-Xray - Add chunk packet info + } + + public int j() { +diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +index cc0c5995dc3840ce66ea849849f7c37555d3b5e6..68d53a51acc9790b9cda20ec4d2ec6edd1baac1a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java ++++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.chunk; + + import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; ++import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info + import java.util.Arrays; + import java.util.Objects; + import java.util.concurrent.locks.ReentrantLock; +@@ -27,6 +28,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { + private final Function e; + private final Function f; + private final T g; ++ private final T[] predefinedObjects; // Paper - Anti-Xray - Add predefined objects + protected DataBits a; public final DataBits getDataBits() { return this.a; } // Paper - OBFHELPER + private DataPalette h; private DataPalette getDataPalette() { return this.h; } // Paper - OBFHELPER + private int i; private int getBitsPerObject() { return this.i; } // Paper - OBFHELPER +@@ -51,14 +53,47 @@ public class DataPaletteBlock implements DataPaletteExpandable { + //this.j.unlock(); // Paper - disable this + } + +- public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0) { ++ // Paper start - Anti-Xray - Add predefined objects ++ @Deprecated public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0) { this(datapalette, registryblockid, function, function1, t0, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0, T[] predefinedObjects, boolean initialize) { ++ // Paper end + this.b = datapalette; + this.d = registryblockid; + this.e = function; + this.f = function1; + this.g = t0; +- this.b(4); ++ // Paper start - Anti-Xray - Add predefined objects ++ this.predefinedObjects = predefinedObjects; ++ ++ if (initialize) { ++ if (predefinedObjects == null) { ++ // Default ++ this.initialize(4); ++ } else { ++ // MathHelper.d() is trailingBits(roundCeilPow2(n)), alternatively; (int)ceil(log2(n)); however it's trash, use numberOfLeadingZeros instead ++ // Count the bits of the maximum array index to initialize a data palette with enough space from the beginning ++ // The length of the array is used because air is also added to the data palette from the beginning ++ // Start with at least 4 ++ int maxIndex = predefinedObjects.length >> 4; ++ int bitCount = (32 - Integer.numberOfLeadingZeros(Math.max(16, maxIndex) - 1)); ++ ++ // Initialize with at least 15 free indixes ++ this.initialize((1 << bitCount) - predefinedObjects.length < 16 ? bitCount + 1 : bitCount); ++ this.addPredefinedObjects(); ++ } ++ } ++ // Paper end ++ } ++ ++ // Paper start - Anti-Xray - Add predefined objects ++ private void addPredefinedObjects() { ++ if (this.predefinedObjects != null && this.getDataPalette() != this.getDataPaletteGlobal()) { ++ for (int i = 0; i < this.predefinedObjects.length; i++) { ++ this.getDataPalette().getOrCreateIdFor(this.predefinedObjects[i]); ++ } ++ } + } ++ // Paper end + + private static int b(int i, int j, int k) { + return j << 8 | k << 4 | i; +@@ -93,6 +128,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { + + int j; + ++ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects + for (j = 0; j < databits.b(); ++j) { + T t1 = datapalette.a(databits.a(j)); + +@@ -142,24 +178,38 @@ public class DataPaletteBlock implements DataPaletteExpandable { + return t0 == null ? this.g : t0; + } + +- public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER +- public synchronized void b(PacketDataSerializer packetdataserializer) { // Paper - synchronize ++ // Paper start - Anti-Xray - Add chunk packet info ++ @Deprecated public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere ++ @Deprecated public void b(PacketDataSerializer packetdataserializer) { this.writeDataPaletteBlock(packetdataserializer, null, 0); } // Notice for updates: Please make sure this method isn't used anywhere ++ public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { this.b(packetDataSerializer, chunkPacketInfo, chunkSectionIndex); } // OBFHELPER ++ public synchronized void b(PacketDataSerializer packetdataserializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { // Paper - synchronize ++ // Paper end + this.a(); + packetdataserializer.writeByte(this.i); + this.h.b(packetdataserializer); ++ // Paper start - Anti-Xray - Add chunk packet info ++ if (chunkPacketInfo != null) { ++ chunkPacketInfo.setBitsPerObject(chunkSectionIndex, this.getBitsPerObject()); ++ chunkPacketInfo.setDataPalette(chunkSectionIndex, this.getDataPalette()); ++ chunkPacketInfo.setDataBitsIndex(chunkSectionIndex, packetdataserializer.writerIndex() + PacketDataSerializer.countBytes(this.getDataBits().getDataBits().length)); ++ chunkPacketInfo.setPredefinedObjects(chunkSectionIndex, this.predefinedObjects); ++ } ++ // Paper end + packetdataserializer.a(this.a.a()); + this.b(); + } + + public synchronized void a(NBTTagList nbttaglist, long[] along) { // Paper - synchronize + this.a(); +- int i = Math.max(4, MathHelper.e(nbttaglist.size())); ++ // Paper - Anti-Xray - TODO: Should this.predefinedObjects.length just be added here (faster) or should the contents be compared to calculate the size (less RAM)? ++ int i = Math.max(4, MathHelper.e(nbttaglist.size() + (this.predefinedObjects == null ? 0 : this.predefinedObjects.length))); // Paper - Anti-Xray - Calculate the size with predefined objects + +- if (i != this.i) { ++ if (true || i != this.i) { // Paper - Anti-Xray - Not initialized yet + this.b(i); + } + + this.h.a(nbttaglist); ++ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects + int j = along.length * 64 / 4096; + + if (this.h == this.b) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index 9eeb99a21a6ed7f71ff64cf4cfdff646d31abbcf..9b308a10554b037ede0c455fbd3e906021218ddc 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -64,16 +64,24 @@ public class ProtoChunk implements IChunkAccess { + private long s; + private final Map t; + private volatile boolean u; ++ private final World world; // Paper - Anti-Xray - Add world + +- public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { ++ // Paper start - Anti-Xray - Add world ++ @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { this(chunkcoordintpair, chunkconverter, null); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, World world) { ++ // Paper end + this(chunkcoordintpair, chunkconverter, (ChunkSection[]) null, new ProtoChunkTickList<>((block) -> { + return block == null || block.getBlockData().isAir(); + }, chunkcoordintpair), new ProtoChunkTickList<>((fluidtype) -> { + return fluidtype == null || fluidtype == FluidTypes.EMPTY; +- }, chunkcoordintpair)); ++ }, chunkcoordintpair), world); // Paper - Anti-Xray - Add world + } + +- public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, @Nullable ChunkSection[] achunksection, ProtoChunkTickList protochunkticklist, ProtoChunkTickList protochunkticklist1) { ++ // Paper start - Anti-Xray - Add world ++ @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, @Nullable ChunkSection[] achunksection, ProtoChunkTickList protochunkticklist, ProtoChunkTickList protochunkticklist1) { this(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, null); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, @Nullable ChunkSection[] achunksection, ProtoChunkTickList protochunkticklist, ProtoChunkTickList protochunkticklist1, World world) { ++ this.world = world; ++ // Paper end + this.f = Maps.newEnumMap(HeightMap.Type.class); + this.g = ChunkStatus.EMPTY; + this.h = Maps.newHashMap(); +@@ -228,7 +236,7 @@ public class ProtoChunk implements IChunkAccess { + + public ChunkSection a(int i) { + if (this.j[i] == Chunk.a) { +- this.j[i] = new ChunkSection(i << 4); ++ this.j[i] = new ChunkSection(i << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters + } + + return this.j[i]; +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java +index 9351e6ba541d440c485b6e4a3209170c5756e31e..7a82d43d51d80a3054e0871bf4b9aa7635920efc 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java +@@ -27,7 +27,7 @@ public class ProtoChunkExtension extends ProtoChunk { + private final Chunk a; + + public ProtoChunkExtension(Chunk chunk) { +- super(chunk.getPos(), ChunkConverter.a); ++ super(chunk.getPos(), ChunkConverter.a, chunk.world); // Paper - Anti-Xray - Add parameter + this.a = chunk; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index 98bc26c7ae01884eb53766e72fc7cbabbf065e6e..c652897aae99c48c6cc020b5d64f6a8b02beecb5 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -101,7 +101,7 @@ public class ChunkRegionLoader { + byte b0 = nbttagcompound2.getByte("Y"); + + if (nbttagcompound2.hasKeyOfType("Palette", 9) && nbttagcompound2.hasKeyOfType("BlockStates", 12)) { +- ChunkSection chunksection = new ChunkSection(b0 << 4); ++ ChunkSection chunksection = new ChunkSection(b0 << 4, null, worldserver, false); // Paper - Anti-Xray - Add parameters + + chunksection.getBlocks().a(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); + chunksection.recalcBlockCounts(); +@@ -165,7 +165,7 @@ public class ChunkRegionLoader { + // CraftBukkit end + }); + } else { +- ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1); ++ ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter + + protochunk.a(biomestorage); + object = protochunk; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +index a8e94f69faec93661dc6ae2efeec44b8bfd2e965..c36f55f178166eb099cc5c64784be5a9f4750199 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +@@ -44,7 +44,7 @@ public class CraftChunk implements Chunk { + private final WorldServer worldServer; + private final int x; + private final int z; +- private static final DataPaletteBlock emptyBlockIDs = new ChunkSection(0).getBlocks(); ++ private static final DataPaletteBlock emptyBlockIDs = new ChunkSection(0, null, null, true).getBlocks(); // Paper - Anti-Xray - Add parameters + private static final byte[] emptyLight = new byte[2048]; + + public CraftChunk(net.minecraft.world.level.chunk.Chunk chunk) { +@@ -288,7 +288,7 @@ public class CraftChunk implements Chunk { + NBTTagCompound data = new NBTTagCompound(); + cs[i].getBlocks().a(data, "Palette", "BlockStates"); + +- DataPaletteBlock blockids = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, net.minecraft.world.level.block.Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); // TODO: snapshot whole ChunkSection ++ DataPaletteBlock blockids = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, net.minecraft.world.level.block.Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData(), null, false); // TODO: snapshot whole ChunkSection // Paper - Anti-Xray - Add no predefined block data and don't initialize because it's done in the line below internally + blockids.a(data.getList("Palette", CraftMagicNumbers.NBT.TAG_COMPOUND), data.getLongArray("BlockStates")); + + sectionBlockIDs[i] = blockids; +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +index 3d15915275331cb767750c24c89b4b43d43033ef..afca0038bb74ac53f07a25729a3c1542e244c6fd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +@@ -21,9 +21,11 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + private final int maxHeight; + private final ChunkSection[] sections; + private Set tiles; ++ private World world; // Paper - Anti-Xray - Add world + + public CraftChunkData(World world) { + this(world.getMaxHeight()); ++ this.world = world; // Paper - Anti-Xray - Add world + } + + /* pp for tests */ CraftChunkData(int maxHeight) { +@@ -157,7 +159,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + private ChunkSection getChunkSection(int y, boolean create) { + ChunkSection section = sections[y >> 4]; + if (create && section == null) { +- sections[y >> 4] = section = new ChunkSection(y >> 4 << 4); ++ sections[y >> 4] = section = new ChunkSection(y >> 4 << 4, null, world instanceof org.bukkit.craftbukkit.CraftWorld ? ((org.bukkit.craftbukkit.CraftWorld) world).getHandle() : null, true); // Paper - Anti-Xray - Add parameters + } + return section; + } diff --git a/patches/server-unmapped/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/patches/server-unmapped/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch new file mode 100644 index 0000000000..528f3c9022 --- /dev/null +++ b/patches/server-unmapped/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 24 Mar 2019 01:01:32 -0400 +Subject: [PATCH] Only count Natural Spawned mobs towards natural spawn mob + limit + +This resolves the super common complaint about mobs not spawning. + +This was ultimately a flaw in the vanilla count algorithim that allows +spawners and other misc mobs to count against the mob limit, which are +not bounded, and can prevent the entire world from spawning new. + +I believe Bukkits changes around persistence may of actually made it +worse than vanilla. + +This should fully solve all of the issues around it so that only natural +influences natural spawns. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index c45493e88bf7e8811be2759ff9ac19e3fe9d938a..384cb363eed794551bee6b0ec11ba1be92a3d7ac 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -464,6 +464,16 @@ public class PaperWorldConfig { + maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); + } + ++ public boolean countAllMobsForSpawning = false; ++ private void countAllMobsForSpawning() { ++ countAllMobsForSpawning = getBoolean("count-all-mobs-for-spawning", false); ++ if (countAllMobsForSpawning) { ++ log("Counting all mobs for spawning. Mob farms may reduce natural spawns elsewhere in world."); ++ } else { ++ log("Using improved mob spawn limits (Only Natural Spawns impact spawn limits for more natural spawns)"); ++ } ++ } ++ + public boolean antiXray; + public EngineMode engineMode; + public int maxChunkSectionIndex; +diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +index 5307488fa48ffa91446dd4457de1ce6a8f61da61..d30a3de84dc75a57680052904337af02b6b80636 100644 +--- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java ++++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +@@ -81,6 +81,13 @@ public final class SpawnerCreature { + EnumCreatureType enumcreaturetype = entity.getEntityType().e(); + + if (enumcreaturetype != EnumCreatureType.MISC) { ++ // Paper start - Only count natural spawns ++ if (!entity.world.paperConfig.countAllMobsForSpawning && ++ !(entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL || ++ entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { ++ continue; ++ } ++ // Paper end + BlockPosition blockposition = entity.getChunkCoordinates(); + long j = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4); + diff --git a/patches/server-unmapped/0364-Configurable-projectile-relative-velocity.patch b/patches/server-unmapped/0364-Configurable-projectile-relative-velocity.patch new file mode 100644 index 0000000000..0f0d7c1e91 --- /dev/null +++ b/patches/server-unmapped/0364-Configurable-projectile-relative-velocity.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lucavon +Date: Tue, 23 Jul 2019 20:29:20 -0500 +Subject: [PATCH] Configurable projectile relative velocity + +This patch adds an option "disable relative projectile velocity", which, when +nabled, will cause projectiles to ignore the shooter's current velocity, +like they did in Minecraft 1.8 and prior. +If a player is falling, for example, their shooting range will be drastically +reduced, as a downwards velocity is applied to the projectile. This prevents +players from saving themselves from falling off floating islands, for example, +as a thrown ender pearl will not make it back to the island, while it would +have in 1.8. + +While this could easily be done with plugins, too, there are multiple problems: +P1) If multiple plugins cancel the velocity by subtracting the shooter's velocity +from the projectile's velocity, the projectile's velocity would be different. +As there's no way to detect whether the projectile's velocity has already been +adjusted to ignore the player's velocity, plugins can't not do it if it's not +necessary. +P2) I've noticed some inconsistencies, e.g. weird velocity when shooting while +using an elytra. Checking for those inconsistencies is possible, but not as +efficient as just not applying the velocity in the first place. +P3) Solutions for 1) and especially 2) might not be future-proof, while this +server-internal fix makes this change future-proof. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 384cb363eed794551bee6b0ec11ba1be92a3d7ac..1ee2cced100626e48eb36ee14f84b9257c79a2f8 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -507,4 +507,9 @@ public class PaperWorldConfig { + Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); + } + } ++ ++ public boolean disableRelativeProjectileVelocity; ++ private void disableRelativeProjectileVelocity() { ++ disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +index 29834a3613c7701d46e879d170779eb7e6f664e1..8fe98404ebb8b3b5d1fdac0896b27da10736026d 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java +@@ -130,7 +130,7 @@ public abstract class IProjectile extends Entity { + this.shoot((double) f5, (double) f6, (double) f7, f3, f4); + Vec3D vec3d = entity.getMot(); + +- this.setMot(this.getMot().add(vec3d.x, entity.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); ++ if (!entity.world.paperConfig.disableRelativeProjectileVelocity) this.setMot(this.getMot().add(vec3d.x, entity.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); // Paper - allow disabling relative velocity + } + + // CraftBukkit start - call projectile hit event diff --git a/patches/server-unmapped/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch b/patches/server-unmapped/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch new file mode 100644 index 0000000000..63ff602a83 --- /dev/null +++ b/patches/server-unmapped/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 28 Jul 2019 00:51:11 +0100 +Subject: [PATCH] Mark entities as being ticked when notifying navigation + + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 024e0bf39b73076fba5c4187c4ff5066e663cf7e..3eb337d42f0292ed7b85a5fdbf6b450bc446b81a 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1475,6 +1475,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition); + + if (VoxelShapes.c(voxelshape, voxelshape1, OperatorBoolean.NOT_SAME)) { ++ boolean wasTicking = this.tickingEntities; this.tickingEntities = true; // Paper + Iterator iterator = this.navigators.iterator(); + + while (iterator.hasNext()) { +@@ -1496,6 +1497,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + } + ++ this.tickingEntities = wasTicking; // Paper + } + } + diff --git a/patches/server-unmapped/0366-offset-item-frame-ticking.patch b/patches/server-unmapped/0366-offset-item-frame-ticking.patch new file mode 100644 index 0000000000..b2190b5c55 --- /dev/null +++ b/patches/server-unmapped/0366-offset-item-frame-ticking.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Tue, 30 Jul 2019 03:17:16 +0500 +Subject: [PATCH] offset item frame ticking + + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java b/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java +index 477c86bec21159608707c1b3bf2ad5f2b455214f..9d491240bcb3ba6ffbee963a13d31aa7b6cd5d45 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java +@@ -37,7 +37,7 @@ public abstract class EntityHanging extends Entity { + protected static final Predicate b = (entity) -> { + return entity instanceof EntityHanging; + }; +- private int e; ++ private int e; { this.e = this.getId() % this.world.spigotConfig.hangingTickFrequency; } // Paper + public BlockPosition blockPosition; + protected EnumDirection direction; + diff --git a/patches/server-unmapped/0367-Avoid-hopper-searches-if-there-are-no-items.patch b/patches/server-unmapped/0367-Avoid-hopper-searches-if-there-are-no-items.patch new file mode 100644 index 0000000000..77f09da2e9 --- /dev/null +++ b/patches/server-unmapped/0367-Avoid-hopper-searches-if-there-are-no-items.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: CullanP +Date: Thu, 3 Mar 2016 02:13:38 -0600 +Subject: [PATCH] Avoid hopper searches if there are no items + +Hoppers searching for items and minecarts is the most expensive part of hopper ticking. +We keep track of the number of minecarts and items in a chunk. +If there are no items in the chunk, we skip searching for items. +If there are no minecarts in the chunk, we skip searching for them. + +Usually hoppers aren't near items, so we can skip most item searches. +And since minecart hoppers are used _very_ rarely near we can avoid alot of searching there. + +Combined, this adds up a lot. + +diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +index cb5cda5e6497edeb801ef712f9bd8823cb055750..1a6f8aec32af85717f5d56e0b00a02cda88ce028 100644 +--- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +@@ -16,6 +16,7 @@ public final class IEntitySelector { + public static final Predicate c = (entity) -> { + return entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); + }; ++ public static final Predicate isInventory() { return d; } // Paper - OBFHELPER + public static final Predicate d = (entity) -> { + return entity instanceof IInventory && entity.isAlive(); + }; +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index 3fdce0e6fa34eb4b1eafc618068a3fb06abd5ec1..e7bb33125a25b9e5a68013b15d7b5b6b6769ab9b 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -32,10 +32,13 @@ import net.minecraft.server.level.PlayerChunk; + import net.minecraft.server.level.WorldServer; + import net.minecraft.util.EntitySlice; + import net.minecraft.util.MathHelper; ++import net.minecraft.world.IInventory; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.IEntitySelector; + import net.minecraft.world.entity.boss.EntityComplexPart; + import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; ++import net.minecraft.world.entity.item.EntityItem; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.TickList; +@@ -123,6 +126,10 @@ public class Chunk implements IChunkAccess { + return removed; + } + } ++ // Track the number of minecarts and items ++ // Keep this synced with entitySlices.add() and entitySlices.remove() ++ private final int[] itemCounts = new int[16]; ++ private final int[] inventoryEntityCounts = new int[16]; + // Paper end + + public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList ticklist, TickList ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer consumer) { +@@ -582,6 +589,13 @@ public class Chunk implements IChunkAccess { + entity.chunkZ = this.loc.z; + this.entities.add(entity); // Paper - per chunk entity list + this.entitySlices[k].add(entity); ++ // Paper start ++ if (entity instanceof EntityItem) { ++ itemCounts[k]++; ++ } else if (entity instanceof IInventory) { ++ inventoryEntityCounts[k]++; ++ } ++ // Paper end + entity.entitySlice = this.entitySlices[k]; // Paper + this.markDirty(); // Paper + } +@@ -615,6 +629,11 @@ public class Chunk implements IChunkAccess { + if (!this.entitySlices[i].remove(entity)) { + return; + } ++ if (entity instanceof EntityItem) { ++ itemCounts[i]--; ++ } else if (entity instanceof IInventory) { ++ inventoryEntityCounts[i]--; ++ } + entityCounts.decrement(entity.getMinecraftKeyString()); + this.markDirty(); // Paper + // Paper end +@@ -900,6 +919,14 @@ public class Chunk implements IChunkAccess { + for (int k = i; k <= j; ++k) { + Iterator iterator = this.entitySlices[k].iterator(); // Spigot + ++ // Paper start - Don't search for inventories if we have none, and that is all we want ++ /* ++ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` ++ * ++ * Make sure the inventory selector stays in sync. ++ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` ++ */ ++ if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; + while (iterator.hasNext()) { + T entity = (T) iterator.next(); // CraftBukkit - decompile error + if (entity.shouldBeRemoved) continue; // Paper +@@ -920,9 +947,29 @@ public class Chunk implements IChunkAccess { + i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); + j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); + ++ // Paper start ++ int[] counts; ++ if (EntityItem.class.isAssignableFrom(oclass)) { ++ counts = itemCounts; ++ } else if (IInventory.class.isAssignableFrom(oclass)) { ++ counts = inventoryEntityCounts; ++ } else { ++ counts = null; ++ } ++ // Paper end + for (int k = i; k <= j; ++k) { ++ if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for + Iterator iterator = this.entitySlices[k].iterator(); // Spigot + ++ // Paper start - Don't search for inventories if we have none, and that is all we want ++ /* ++ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` ++ * ++ * Make sure the inventory selector stays in sync. ++ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` ++ */ ++ if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; ++ // Paper end + while (iterator.hasNext()) { + T t0 = (T) iterator.next(); // CraftBukkit - decompile error + if (t0.shouldBeRemoved) continue; // Paper diff --git a/patches/server-unmapped/0368-Asynchronous-chunk-IO-and-loading.patch b/patches/server-unmapped/0368-Asynchronous-chunk-IO-and-loading.patch new file mode 100644 index 0000000000..c091706a07 --- /dev/null +++ b/patches/server-unmapped/0368-Asynchronous-chunk-IO-and-loading.patch @@ -0,0 +1,4203 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 13 Jul 2019 09:23:10 -0700 +Subject: [PATCH] Asynchronous chunk IO and loading + +This patch re-adds a file IO thread as well as shoving de-serializing +chunk NBT data onto worker threads. This patch also will shove +chunk data serialization onto the same worker threads when the chunk +is unloaded - this cannot be done for regular saves since that's unsafe. + +The file IO Thread + +Unlike 1.13 and below, the file IO thread is prioritized - IO tasks can +be reoredered, however they are "stuck" to a world & coordinate. + +Scheduling IO tasks works as follows, given a world & coordinate - location: + +The IO thread has been designed to ensure that reads and writes appear to +occur synchronously for a given location, however the implementation also +has the unfortunate side-effect of making every write appear as if +they occur without failure. + +The IO thread has also been designed to accomodate Mojang's decision to +store chunk data and POI data separately. It can independently schedule +tasks for each. + +However threads can wait for writes to complete and check if: + - The write was overwriten by another scheduler + - The write failed (however it does not indicate whether it was overwritten by another scheduler) + +Scheduling reads: + + - If a write task is in progress, the task is not scheduled and returns the in-progress write data + This means that readers cannot modify the NBTTagCompound returned and must clone if it they wish to write + - If a write task is not in progress but a read task is in progress, then the read task is simply chained + This means that again, readers cannot modify the NBTTagCompound returned + +Scheduling writes: + + - If a read task is in progress, ignore the read task and schedule the write + We cannot complete the read task since we assume it wants old data - not current + - If a write task is pending, overwrite the write data + The file IO thread does correctly handle cases where the data is overwritten when it + is writing data (before completing a task it will check if the data was overwritten and + will retry). + +When the file IO thread executes a task for a location, the it will +execute the read task first (if it exists), then it will execute the +write task. This ensures that, even when scheduling at different +priorities, that reads/writes for a location act synchronously. + +The downside of the file IO thread is that write failure can only be +indicated to the scheduling thread if: + +- No other thread decides to schedule another write for the location +concurrently +- The scheduling thread blocks on the write to complete (however the +current implementation can be modified to indicate success +asynchronously) + +The file io thread can be modified easily to provide indications +of write failure and write overwriting if needed. + +The upside of the file IO thread is that if a write failures, then +chunk data is not lost until server restart. This leaves more room +for spurious failure. + +Finally, the io thread will indicate to the console when reads +or writes fail - with relevant detail. + +Asynchronous chunk data serialization for unloading chunks + +When chunks unload they make a call to PlayerChunkMap#saveChunk(IChunkAccess). +Even if I make the IO asynchronous for this call, the data serialization +still hits pretty hard. And given that now the chunk system will +aggressively unload chunks more often (queued immediately at +ticket level 45 or higher), unloads occur more often, and +combined with our changes to the unload queue to make it +significantly more aggresive - chunk unloads can hit pretty hard. +Especially players running around with elytras and fireworks. + +For serializing chunk data off main, there are some tasks which cannot be +done asynchronously. Lighting data must be saved beforehand as well as +potentially some tick lists. These are completed before scheduling the +asynchronous save. + +However serializing chunk data off of the main thread is still risky. +Even though this patch schedules the save to occur after ALL references +of the chunk are removed from the world, plugins can still technically +access entities inside the chunks. For this, if the serialization task +fails for any reason, it will be re-scheduled to be serialized on the +main thread - with the hopes that the reason it failed was due to a plugin +and not an error with the save code itself. Like vanilla code - if the +serialization fails, the chunk data is lost. + +Asynchronous chunk io/loading + +Mojang's current implementation for loading chunk data off disk is +to return a CompletableFuture that will be completed by scheduling a +task to be executed on the world's chunk queue (which is only drained +on the main thread). This task will read the IO off disk and it will +apply data conversions & deserialization synchronously. Obviously +all 3 of these operations are expensive however all can be completed +asynchronously instead. + +The solution this patch uses is as follows: + +0. If an asynchronous chunk save is in progress (see above), wait +for that task to complete. It will use the serialized NBTTagCompound +created by the task. If the task fails to complete, then we would continue +with step 1. If it does not, we skip step 1. (Note: We actually load +POI data no matter what in this case). +1. Schedule an IO task to read chunk & poi data off disk. +2. The IO task will schedule a chunk load task. +3. The chunk load task executes on the async chunk loader threads +and will apply datafixers & de-serialize the chunk into a ProtoChunk +or ProtoChunkExtension. +4. The in progress chunk is then passed on to the world's chunk queue +to complete the ComletableFuture and execute any of the synchronous +tasks required to be executed by the chunk load task (i.e lighting +and some poi tasks). + +diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +index fa154ed68187a2020e814db6345a8cc1119ab4ba..2da28784ee427001b1137c859f0b4c350abd3110 100644 +--- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java ++++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +@@ -58,6 +58,17 @@ public class WorldTimingsHandler { + + public final Timing miscMobSpawning; + ++ public final Timing poiUnload; ++ public final Timing chunkUnload; ++ public final Timing poiSaveDataSerialization; ++ public final Timing chunkSave; ++ public final Timing chunkSaveOverwriteCheck; ++ public final Timing chunkSaveDataSerialization; ++ public final Timing chunkSaveIOWait; ++ public final Timing chunkUnloadPrepareSave; ++ public final Timing chunkUnloadPOISerialization; ++ public final Timing chunkUnloadDataSave; ++ + public WorldTimingsHandler(World server) { + String name = ((WorldDataServer) server.getWorldData()).getName() + " - "; + +@@ -111,6 +122,17 @@ public class WorldTimingsHandler { + + + miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); ++ ++ poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); ++ chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); ++ poiSaveDataSerialization = Timings.ofSafe(name + "Chunk save - POI Data serialization"); ++ chunkSave = Timings.ofSafe(name + "Chunk save - Chunk"); ++ chunkSaveOverwriteCheck = Timings.ofSafe(name + "Chunk save - Chunk Overwrite Check"); ++ chunkSaveDataSerialization = Timings.ofSafe(name + "Chunk save - Chunk Data serialization"); ++ chunkSaveIOWait = Timings.ofSafe(name + "Chunk save - Chunk IO Wait"); ++ chunkUnloadPrepareSave = Timings.ofSafe(name + "Chunk unload - Async Save Prepare"); ++ chunkUnloadPOISerialization = Timings.ofSafe(name + "Chunk unload - POI Data Serialization"); ++ chunkUnloadDataSave = Timings.ofSafe(name + "Chunk unload - Data Serialization"); + } + + public static Timing getTickList(WorldServer worldserver, String timingsType) { +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index a7a02072e5c7ce62cbecbb638fcc74abf2fb57ee..f657e9b6bb3d24a6c77ef584711a003d1eea0341 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -1,5 +1,6 @@ + package com.destroystokyo.paper; + ++import com.destroystokyo.paper.io.chunk.ChunkTaskManager; + import com.google.common.base.Functions; + import com.google.common.base.Joiner; + import com.google.common.collect.ImmutableSet; +@@ -43,7 +44,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); + + public PaperCommand(String name) { + super(name); +@@ -155,6 +156,9 @@ public class PaperCommand extends Command { + case "debug": + doDebug(sender, args); + break; ++ case "dumpwaiting": ++ ChunkTaskManager.dumpAllChunkLoadInfo(); ++ break; + case "chunkinfo": + doChunkInfo(sender, args); + break; +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 469f78775b03cf363d88e35c69c0dc185c22547c..8bf4d2b8c38c02d6a5b2fea37113689a252f1571 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -1,5 +1,6 @@ + package com.destroystokyo.paper; + ++import com.destroystokyo.paper.io.chunk.ChunkTaskManager; + import com.google.common.base.Strings; + import com.google.common.base.Throwables; + +@@ -352,4 +353,54 @@ public class PaperConfig { + maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); + maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); + } ++ ++ public static boolean asyncChunks = false; ++ private static void asyncChunks() { ++ ConfigurationSection section; ++ if (version < 15) { ++ section = config.createSection("settings.async-chunks"); ++ section.set("threads", -1); ++ } else { ++ section = config.getConfigurationSection("settings.async-chunks"); ++ if (section == null) { ++ section = config.createSection("settings.async-chunks"); ++ } ++ } ++ // Clean up old configs ++ if (section.contains("load-threads")) { ++ if (!section.contains("threads")) { ++ section.set("threads", section.get("load-threads")); ++ } ++ section.set("load-threads", null); ++ } ++ section.set("generation", null); ++ section.set("enabled", null); ++ section.set("thread-per-world-generation", null); ++ ++ int threads = getInt("settings.async-chunks.threads", -1); ++ int cpus = Runtime.getRuntime().availableProcessors(); ++ if (threads <= 0) { ++ threads = (int) Math.min(Integer.getInteger("paper.maxChunkThreads", 8), Math.max(1, cpus - 1)); ++ } ++ if (cpus == 1 && !Boolean.getBoolean("Paper.allowAsyncChunksSingleCore")) { ++ asyncChunks = false; ++ } else { ++ asyncChunks = true; ++ } ++ ++ // Let Shared Host set some limits ++ String sharedHostThreads = System.getenv("PAPER_ASYNC_CHUNKS_SHARED_HOST_THREADS"); ++ if (sharedHostThreads != null) { ++ try { ++ threads = Math.max(1, Math.min(threads, Integer.parseInt(sharedHostThreads))); ++ } catch (NumberFormatException ignored) {} ++ } ++ ++ if (!asyncChunks) { ++ log("Async Chunks: Disabled - Chunks will be managed synchronously, and will cause tremendous lag."); ++ } else { ++ ChunkTaskManager.initGlobalLoadThreads(threads); ++ log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/io/IOUtil.java b/src/main/java/com/destroystokyo/paper/io/IOUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5af0ac3d9e87c06053e65433060f15779c156c2a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/IOUtil.java +@@ -0,0 +1,62 @@ ++package com.destroystokyo.paper.io; ++ ++import org.bukkit.Bukkit; ++ ++public final class IOUtil { ++ ++ /* Copied from concrete or concurrentutil */ ++ ++ public static long getCoordinateKey(final int x, final int z) { ++ return ((long)z << 32) | (x & 0xFFFFFFFFL); ++ } ++ ++ public static int getCoordinateX(final long key) { ++ return (int)key; ++ } ++ ++ public static int getCoordinateZ(final long key) { ++ return (int)(key >>> 32); ++ } ++ ++ public static int getRegionCoordinate(final int chunkCoordinate) { ++ return chunkCoordinate >> 5; ++ } ++ ++ public static int getChunkInRegion(final int chunkCoordinate) { ++ return chunkCoordinate & 31; ++ } ++ ++ public static String genericToString(final Object object) { ++ return object == null ? "null" : object.getClass().getName() + ":" + object.toString(); ++ } ++ ++ public static T notNull(final T obj) { ++ if (obj == null) { ++ throw new NullPointerException(); ++ } ++ return obj; ++ } ++ ++ public static T notNull(final T obj, final String msgIfNull) { ++ if (obj == null) { ++ throw new NullPointerException(msgIfNull); ++ } ++ return obj; ++ } ++ ++ public static void arrayBounds(final int off, final int len, final int arrayLength, final String msgPrefix) { ++ if (off < 0 || len < 0 || (arrayLength - off) < len) { ++ throw new ArrayIndexOutOfBoundsException(msgPrefix + ": off: " + off + ", len: " + len + ", array length: " + arrayLength); ++ } ++ } ++ ++ public static int getPriorityForCurrentThread() { ++ return Bukkit.isPrimaryThread() ? PrioritizedTaskQueue.HIGHEST_PRIORITY : PrioritizedTaskQueue.NORMAL_PRIORITY; ++ } ++ ++ @SuppressWarnings("unchecked") ++ public static void rethrow(final Throwable throwable) throws T { ++ throw (T)throwable; ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9fe91f9512ee8c2589fc8da76bda5f6d70c9fac4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java +@@ -0,0 +1,606 @@ ++package com.destroystokyo.paper.io; ++ ++import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.level.chunk.storage.RegionFile; ++import org.apache.logging.log4j.Logger; ++ ++import java.io.IOException; ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.atomic.AtomicLong; ++import java.util.function.Consumer; ++import java.util.function.Function; ++ ++/** ++ * Prioritized singleton thread responsible for all chunk IO that occurs in a minecraft server. ++ * ++ *

    ++ * Singleton access: {@link Holder#INSTANCE} ++ *

    ++ * ++ *

    ++ * All functions provided are MT-Safe, however certain ordering constraints are (but not enforced): ++ *

  • ++ * Chunk saves may not occur for unloaded chunks. ++ *
  • ++ *
  • ++ * Tasks must be scheduled on the main thread. ++ *
  • ++ *

    ++ * ++ * @see Holder#INSTANCE ++ * @see #scheduleSave(WorldServer, int, int, NBTTagCompound, NBTTagCompound, int) ++ * @see #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean) ++ */ ++public final class PaperFileIOThread extends QueueExecutorThread { ++ ++ public static final Logger LOGGER = MinecraftServer.LOGGER; ++ public static final NBTTagCompound FAILURE_VALUE = new NBTTagCompound(); ++ ++ public static final class Holder { ++ ++ public static final PaperFileIOThread INSTANCE = new PaperFileIOThread(); ++ ++ static { ++ INSTANCE.start(); ++ } ++ } ++ ++ private final AtomicLong writeCounter = new AtomicLong(); ++ ++ private PaperFileIOThread() { ++ super(new PrioritizedTaskQueue<>(), (int)(1.0e6)); // 1.0ms spinwait time ++ this.setName("Paper RegionFile IO Thread"); ++ this.setPriority(Thread.NORM_PRIORITY - 1); // we keep priority close to normal because threads can wait on us ++ this.setUncaughtExceptionHandler((final Thread unused, final Throwable thr) -> { ++ LOGGER.fatal("Uncaught exception thrown from IO thread, report this!", thr); ++ }); ++ } ++ ++ /* run() is implemented by superclass */ ++ ++ /* ++ * ++ * IO thread will perform reads before writes ++ * ++ * How reads/writes are scheduled: ++ * ++ * If read in progress while scheduling write, ignore read and schedule write ++ * If read in progress while scheduling read (no write in progress), chain the read task ++ * ++ * ++ * If write in progress while scheduling read, use the pending write data and ret immediately ++ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data ++ * ++ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however ++ * it fails to properly propagate write failures. When writes fail the data is kept so future reads will actually ++ * read the failed write data. This should hopefully act as a way to prevent data loss for spurious fails for writing data. ++ * ++ */ ++ ++ /** ++ * Attempts to bump the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. ++ * @param world Chunk's world ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority level to try to bump to ++ */ ++ public void bumpPriority(final WorldServer world, final int chunkX, final int chunkZ, final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority: " + priority); ++ } ++ ++ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); ++ ++ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); ++ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); ++ ++ if (poiTask != null) { ++ poiTask.raisePriority(priority); ++ } ++ if (chunkTask != null) { ++ chunkTask.raisePriority(priority); ++ } ++ } ++ ++ public NBTTagCompound getPendingWrite(final WorldServer world, final int chunkX, final int chunkZ, final boolean poiData) { ++ final ChunkDataController taskController = poiData ? world.poiDataController : world.chunkDataController; ++ ++ final ChunkDataTask dataTask = taskController.tasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); ++ ++ if (dataTask == null) { ++ return null; ++ } ++ ++ final ChunkDataController.InProgressWrite write = dataTask.inProgressWrite; ++ ++ if (write == null) { ++ return null; ++ } ++ ++ return write.data; ++ } ++ ++ /** ++ * Sets the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. ++ * @param world Chunk's world ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority level to set to ++ */ ++ public void setPriority(final WorldServer world, final int chunkX, final int chunkZ, final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority: " + priority); ++ } ++ ++ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); ++ ++ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); ++ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); ++ ++ if (poiTask != null) { ++ poiTask.updatePriority(priority); ++ } ++ if (chunkTask != null) { ++ chunkTask.updatePriority(priority); ++ } ++ } ++ ++ /** ++ * Schedules the chunk data to be written asynchronously. ++ *

    ++ * Impl notes: ++ *

    ++ *
  • ++ * This function presumes a chunk load for the coordinates is not called during this function (anytime after is OK). This means ++ * saves must be scheduled before a chunk is unloaded. ++ *
  • ++ *
  • ++ * Writes may be called concurrently, although only the "later" write will go through. ++ *
  • ++ * @param world Chunk's world ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param poiData Chunk point of interest data. If {@code null}, then no poi data is saved. ++ * @param chunkData Chunk data. If {@code null}, then no chunk data is saved. ++ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} ++ * @throws IllegalArgumentException If both {@code poiData} and {@code chunkData} are {@code null}. ++ * @throws IllegalStateException If the file io thread has shutdown. ++ */ ++ public void scheduleSave(final WorldServer world, final int chunkX, final int chunkZ, ++ final NBTTagCompound poiData, final NBTTagCompound chunkData, ++ final int priority) throws IllegalArgumentException { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority: " + priority); ++ } ++ ++ final long writeCounter = this.writeCounter.getAndIncrement(); ++ ++ if (poiData != null) { ++ this.scheduleWrite(world.poiDataController, world, chunkX, chunkZ, poiData, priority, writeCounter); ++ } ++ if (chunkData != null) { ++ this.scheduleWrite(world.chunkDataController, world, chunkX, chunkZ, chunkData, priority, writeCounter); ++ } ++ } ++ ++ private void scheduleWrite(final ChunkDataController dataController, final WorldServer world, ++ final int chunkX, final int chunkZ, final NBTTagCompound data, final int priority, final long writeCounter) { ++ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask taskRunning) -> { ++ if (taskRunning == null) { ++ // no task is scheduled ++ ++ // create task ++ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); ++ newTask.inProgressWrite = new ChunkDataController.InProgressWrite(); ++ newTask.inProgressWrite.writeCounter = writeCounter; ++ newTask.inProgressWrite.data = data; ++ ++ PaperFileIOThread.this.queueTask(newTask); // schedule ++ return newTask; ++ } ++ ++ taskRunning.raisePriority(priority); ++ ++ if (taskRunning.inProgressWrite == null) { ++ taskRunning.inProgressWrite = new ChunkDataController.InProgressWrite(); ++ } ++ ++ boolean reschedule = taskRunning.inProgressWrite.writeCounter == -1L; ++ ++ // synchronize for readers ++ //noinspection SynchronizationOnLocalVariableOrMethodParameter ++ synchronized (taskRunning) { ++ taskRunning.inProgressWrite.data = data; ++ taskRunning.inProgressWrite.writeCounter = writeCounter; ++ } ++ ++ if (reschedule) { ++ // We need to reschedule this task since the previous one is not currently scheduled since it failed ++ taskRunning.reschedule(priority); ++ } ++ ++ return taskRunning; ++ }); ++ } ++ ++ /** ++ * Same as {@link #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns ++ * a {@link CompletableFuture} which is potentially completed ASYNCHRONOUSLY ON THE FILE IO THREAD when the load task ++ * has completed. ++ *

    ++ * Note that if the chunk fails to load the returned future is completed with {@code null}. ++ *

    ++ */ ++ public CompletableFuture loadChunkDataAsyncFuture(final WorldServer world, final int chunkX, final int chunkZ, ++ final int priority, final boolean readPoiData, final boolean readChunkData, ++ final boolean intendingToBlock) { ++ final CompletableFuture future = new CompletableFuture<>(); ++ this.loadChunkDataAsync(world, chunkX, chunkZ, priority, future::complete, readPoiData, readChunkData, intendingToBlock); ++ return future; ++ } ++ ++ /** ++ * Schedules a load to be executed asynchronously. ++ *

    ++ * Impl notes: ++ *

    ++ *
  • ++ * If a chunk fails to load, the {@code onComplete} parameter is completed with {@code null}. ++ *
  • ++ *
  • ++ * It is possible for the {@code onComplete} parameter to be given {@link ChunkData} containing data ++ * this call did not request. ++ *
  • ++ *
  • ++ * The {@code onComplete} parameter may be completed during the execution of this function synchronously or it may ++ * be completed asynchronously on this file io thread. Interacting with the file IO thread in the completion of ++ * data is undefined behaviour, and can cause deadlock. ++ *
  • ++ * @param world Chunk's world ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} ++ * @param onComplete Consumer to execute once this task has completed ++ * @param readPoiData Whether to read point of interest data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. ++ * @param readChunkData Whether to read chunk data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. ++ * @return The {@link PrioritizedTaskQueue.PrioritizedTask} associated with this task. Note that this task does not support ++ * cancellation. ++ */ ++ public void loadChunkDataAsync(final WorldServer world, final int chunkX, final int chunkZ, ++ final int priority, final Consumer onComplete, ++ final boolean readPoiData, final boolean readChunkData, ++ final boolean intendingToBlock) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority: " + priority); ++ } ++ ++ if (!(readPoiData | readChunkData)) { ++ throw new IllegalArgumentException("Must read chunk data or poi data"); ++ } ++ ++ final ChunkData complete = new ChunkData(); ++ final boolean[] requireCompletion = new boolean[] { readPoiData, readChunkData }; ++ ++ if (readPoiData) { ++ this.scheduleRead(world.poiDataController, world, chunkX, chunkZ, (final NBTTagCompound poiData) -> { ++ complete.poiData = poiData; ++ ++ final boolean finished; ++ ++ // avoid a race condition where the file io thread completes and we complete synchronously ++ // Note: Synchronization can be elided if both of the accesses are volatile ++ synchronized (requireCompletion) { ++ requireCompletion[0] = false; // 0 -> poi data ++ finished = !requireCompletion[1]; // 1 -> chunk data ++ } ++ ++ if (finished) { ++ onComplete.accept(complete); ++ } ++ }, priority, intendingToBlock); ++ } ++ ++ if (readChunkData) { ++ this.scheduleRead(world.chunkDataController, world, chunkX, chunkZ, (final NBTTagCompound chunkData) -> { ++ complete.chunkData = chunkData; ++ ++ final boolean finished; ++ ++ // avoid a race condition where the file io thread completes and we complete synchronously ++ // Note: Synchronization can be elided if both of the accesses are volatile ++ synchronized (requireCompletion) { ++ requireCompletion[1] = false; // 1 -> chunk data ++ finished = !requireCompletion[0]; // 0 -> poi data ++ } ++ ++ if (finished) { ++ onComplete.accept(complete); ++ } ++ }, priority, intendingToBlock); ++ } ++ ++ } ++ ++ // Note: the onComplete may be called asynchronously or synchronously here. ++ private void scheduleRead(final ChunkDataController dataController, final WorldServer world, ++ final int chunkX, final int chunkZ, final Consumer onComplete, final int priority, ++ final boolean intendingToBlock) { ++ ++ Function tryLoadFunction = (final RegionFile file) -> { ++ if (file == null) { ++ return Boolean.TRUE; ++ } ++ return Boolean.valueOf(file.chunkExists(new ChunkCoordIntPair(chunkX, chunkZ))); ++ }; ++ ++ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask running) -> { ++ if (running == null) { ++ // not scheduled ++ ++ final Boolean shouldSchedule = intendingToBlock ? dataController.computeForRegionFile(chunkX, chunkZ, tryLoadFunction) : ++ dataController.computeForRegionFileIfLoaded(chunkX, chunkZ, tryLoadFunction); ++ ++ if (shouldSchedule == Boolean.FALSE) { ++ // not on disk ++ onComplete.accept(null); ++ return null; ++ } ++ ++ // set up task ++ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); ++ newTask.inProgressRead = new ChunkDataController.InProgressRead(); ++ newTask.inProgressRead.readFuture.thenAccept(onComplete); ++ ++ PaperFileIOThread.this.queueTask(newTask); // schedule task ++ return newTask; ++ } ++ ++ running.raisePriority(priority); ++ ++ if (running.inProgressWrite == null) { ++ // chain to the read future ++ running.inProgressRead.readFuture.thenAccept(onComplete); ++ return running; ++ } ++ ++ // at this stage we have to use the in progress write's data to avoid an order issue ++ // we don't synchronize since all writes to data occur in the compute() call ++ onComplete.accept(running.inProgressWrite.data); ++ return running; ++ }); ++ } ++ ++ /** ++ * Same as {@link #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns ++ * the {@link ChunkData} associated with the specified chunk when the task is complete. ++ * @return The chunk data, or {@code null} if the chunk failed to load. ++ */ ++ public ChunkData loadChunkData(final WorldServer world, final int chunkX, final int chunkZ, final int priority, ++ final boolean readPoiData, final boolean readChunkData) { ++ return this.loadChunkDataAsyncFuture(world, chunkX, chunkZ, priority, readPoiData, readChunkData, true).join(); ++ } ++ ++ /** ++ * Schedules the given task at the specified priority to be executed on the IO thread. ++ *

    ++ * Internal api. Do not use. ++ *

    ++ */ ++ public void runTask(final int priority, final Runnable runnable) { ++ this.queueTask(new GeneralTask(priority, runnable)); ++ } ++ ++ static final class GeneralTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { ++ ++ private final Runnable run; ++ ++ public GeneralTask(final int priority, final Runnable run) { ++ super(priority); ++ this.run = IOUtil.notNull(run, "Task may not be null"); ++ } ++ ++ @Override ++ public void run() { ++ try { ++ this.run.run(); ++ } catch (final Throwable throwable) { ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath)throwable; ++ } ++ LOGGER.fatal("Failed to execute general task on IO thread " + IOUtil.genericToString(this.run), throwable); ++ } ++ } ++ } ++ ++ public static final class ChunkData { ++ ++ public NBTTagCompound poiData; ++ public NBTTagCompound chunkData; ++ ++ public ChunkData() {} ++ ++ public ChunkData(final NBTTagCompound poiData, final NBTTagCompound chunkData) { ++ this.poiData = poiData; ++ this.chunkData = chunkData; ++ } ++ } ++ ++ public static abstract class ChunkDataController { ++ ++ // ConcurrentHashMap synchronizes per chain, so reduce the chance of task's hashes colliding. ++ public final ConcurrentHashMap tasks = new ConcurrentHashMap<>(64, 0.5f); ++ ++ public abstract void writeData(final int x, final int z, final NBTTagCompound compound) throws IOException; ++ public abstract NBTTagCompound readData(final int x, final int z) throws IOException; ++ ++ public abstract T computeForRegionFile(final int chunkX, final int chunkZ, final Function function); ++ public abstract T computeForRegionFileIfLoaded(final int chunkX, final int chunkZ, final Function function); ++ ++ public static final class InProgressWrite { ++ public long writeCounter; ++ public NBTTagCompound data; ++ } ++ ++ public static final class InProgressRead { ++ public final CompletableFuture readFuture = new CompletableFuture<>(); ++ } ++ } ++ ++ public static final class ChunkDataTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { ++ ++ public ChunkDataController.InProgressWrite inProgressWrite; ++ public ChunkDataController.InProgressRead inProgressRead; ++ ++ private final WorldServer world; ++ private final int x; ++ private final int z; ++ private final ChunkDataController taskController; ++ ++ public ChunkDataTask(final int priority, final WorldServer world, final int x, final int z, final ChunkDataController taskController) { ++ super(priority); ++ this.world = world; ++ this.x = x; ++ this.z = z; ++ this.taskController = taskController; ++ } ++ ++ @Override ++ public String toString() { ++ return "Task for world: '" + this.world.getWorld().getName() + "' at " + this.x + "," + this.z + ++ " poi: " + (this.taskController == this.world.poiDataController) + ", hash: " + this.hashCode(); ++ } ++ ++ /* ++ * ++ * IO thread will perform reads before writes ++ * ++ * How reads/writes are scheduled: ++ * ++ * If read in progress while scheduling write, ignore read and schedule write ++ * If read in progress while scheduling read (no write in progress), chain the read task ++ * ++ * ++ * If write in progress while scheduling read, use the pending write data and ret immediately ++ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data ++ * ++ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however ++ * it fails to properly propagate write failures ++ * ++ */ ++ ++ void reschedule(final int priority) { ++ // priority is checked before this stage // TODO what ++ this.queue.lazySet(null); ++ this.priority.lazySet(priority); ++ PaperFileIOThread.Holder.INSTANCE.queueTask(this); ++ } ++ ++ @Override ++ public void run() { ++ ChunkDataController.InProgressRead read = this.inProgressRead; ++ if (read != null) { ++ NBTTagCompound compound = PaperFileIOThread.FAILURE_VALUE; ++ try { ++ compound = this.taskController.readData(this.x, this.z); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ LOGGER.fatal("Failed to read chunk data for task: " + this.toString(), thr); ++ // fall through to complete with null data ++ } ++ read.readFuture.complete(compound); ++ } ++ ++ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(this.x, this.z)); ++ ++ ChunkDataController.InProgressWrite write = this.inProgressWrite; ++ ++ if (write == null) { ++ // IntelliJ warns this is invalid, however it does not consider that writes to the task map & the inProgress field can occur concurrently. ++ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { ++ if (valueInMap == null) { ++ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); ++ } ++ if (valueInMap != ChunkDataTask.this) { ++ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); ++ } ++ return valueInMap.inProgressWrite == null ? null : valueInMap; ++ }); ++ ++ if (inMap == null) { ++ return; // set the task value to null, indicating we're done ++ } ++ ++ // not null, which means there was a concurrent write ++ write = this.inProgressWrite; ++ } ++ ++ // check if another process is writing ++ /*try { TODO: Can we restore this? ++ ((WorldServer)this.world).checkSession(); ++ } catch (final Exception ex) { ++ LOGGER.fatal("Couldn't save chunk; already in use by another instance of Minecraft?", ex); ++ // we don't need to set the write counter to -1 as we know at this stage there's no point in re-scheduling ++ // writes since they'll fail anyways. ++ return; ++ } ++*/ ++ for (;;) { ++ final long writeCounter; ++ final NBTTagCompound data; ++ ++ //noinspection SynchronizationOnLocalVariableOrMethodParameter ++ synchronized (write) { ++ writeCounter = write.writeCounter; ++ data = write.data; ++ } ++ ++ boolean failedWrite = false; ++ ++ try { ++ this.taskController.writeData(this.x, this.z, data); ++ } catch (final Throwable thr) { ++ if (thr instanceof ThreadDeath) { ++ throw (ThreadDeath)thr; ++ } ++ LOGGER.fatal("Failed to write chunk data for task: " + this.toString(), thr); ++ failedWrite = true; ++ } ++ ++ boolean finalFailWrite = failedWrite; ++ ++ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { ++ if (valueInMap == null) { ++ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); ++ } ++ if (valueInMap != ChunkDataTask.this) { ++ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); ++ } ++ if (valueInMap.inProgressWrite.writeCounter == writeCounter) { ++ if (finalFailWrite) { ++ valueInMap.inProgressWrite.writeCounter = -1L; ++ } ++ ++ return null; ++ } ++ return valueInMap; ++ // Hack end ++ }); ++ ++ if (inMap == null) { ++ // write counter matched, so we wrote the most up-to-date pending data, we're done here ++ // or we failed to write and successfully set the write counter to -1 ++ return; // we're done here ++ } ++ ++ // fetch & write new data ++ continue; ++ } ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java +new file mode 100644 +index 0000000000000000000000000000000000000000..97f2e433c483f1ebd7500ae142269e144ef5fda4 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java +@@ -0,0 +1,277 @@ ++package com.destroystokyo.paper.io; ++ ++import java.util.concurrent.ConcurrentLinkedQueue; ++import java.util.concurrent.atomic.AtomicBoolean; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.concurrent.atomic.AtomicReference; ++ ++public class PrioritizedTaskQueue { ++ ++ // lower numbers are a higher priority (except < 0) ++ // higher priorities are always executed before lower priorities ++ ++ /** ++ * Priority value indicating the task has completed or is being completed. ++ */ ++ public static final int COMPLETING_PRIORITY = -1; ++ ++ /** ++ * Highest priority, should only be used for main thread tasks or tasks that are blocking the main thread. ++ */ ++ public static final int HIGHEST_PRIORITY = 0; ++ ++ /** ++ * Should be only used in an IO task so that chunk loads do not wait on other IO tasks. ++ * This only exists because IO tasks are scheduled before chunk load tasks to decrease IO waiting times. ++ */ ++ public static final int HIGHER_PRIORITY = 1; ++ ++ /** ++ * Should be used for scheduling chunk loads/generation that would increase response times to users. ++ */ ++ public static final int HIGH_PRIORITY = 2; ++ ++ /** ++ * Default priority. ++ */ ++ public static final int NORMAL_PRIORITY = 3; ++ ++ /** ++ * Use for tasks not at all critical and can potentially be delayed. ++ */ ++ public static final int LOW_PRIORITY = 4; ++ ++ /** ++ * Use for tasks that should "eventually" execute. ++ */ ++ public static final int LOWEST_PRIORITY = 5; ++ ++ private static final int TOTAL_PRIORITIES = 6; ++ ++ final ConcurrentLinkedQueue[] queues = (ConcurrentLinkedQueue[])new ConcurrentLinkedQueue[TOTAL_PRIORITIES]; ++ ++ private final AtomicBoolean shutdown = new AtomicBoolean(); ++ ++ { ++ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { ++ this.queues[i] = new ConcurrentLinkedQueue<>(); ++ } ++ } ++ ++ /** ++ * Returns whether the specified priority is valid ++ */ ++ public static boolean validPriority(final int priority) { ++ return priority >= 0 && priority < TOTAL_PRIORITIES; ++ } ++ ++ /** ++ * Queues a task. ++ * @throws IllegalStateException If the task has already been queued. Use {@link PrioritizedTask#raisePriority(int)} to ++ * raise a task's priority. ++ * This can also be thrown if the queue has shutdown. ++ */ ++ public void add(final T task) throws IllegalStateException { ++ int priority = task.getPriority(); ++ if (priority != COMPLETING_PRIORITY) { ++ task.setQueue(this); ++ this.queues[priority].add(task); ++ } ++ if (this.shutdown.get()) { ++ // note: we're not actually sure at this point if our task will go through ++ throw new IllegalStateException("Queue has shutdown, refusing to execute task " + IOUtil.genericToString(task)); ++ } ++ } ++ ++ /** ++ * Polls the highest priority task currently available. {@code null} if none. ++ */ ++ public T poll() { ++ T task; ++ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { ++ final ConcurrentLinkedQueue queue = this.queues[i]; ++ ++ while ((task = queue.poll()) != null) { ++ final int prevPriority = task.tryComplete(i); ++ if (prevPriority != COMPLETING_PRIORITY && prevPriority <= i) { ++ // if the prev priority was greater-than or equal to our current priority ++ return task; ++ } ++ } ++ } ++ ++ return null; ++ } ++ ++ /** ++ * Returns whether this queue may have tasks queued. ++ *

    ++ * This operation is not atomic, but is MT-Safe. ++ *

    ++ * @return {@code true} if tasks may be queued, {@code false} otherwise ++ */ ++ public boolean hasTasks() { ++ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { ++ final ConcurrentLinkedQueue queue = this.queues[i]; ++ ++ if (queue.peek() != null) { ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ /** ++ * Prevent further additions to this queue. Attempts to add after this call has completed (potentially during) will ++ * result in {@link IllegalStateException} being thrown. ++ *

    ++ * This operation is atomic with respect to other shutdown calls ++ *

    ++ *

    ++ * After this call has completed, regardless of return value, this queue will be shutdown. ++ *

    ++ * @return {@code true} if the queue was shutdown, {@code false} if it has shut down already ++ */ ++ public boolean shutdown() { ++ return this.shutdown.getAndSet(false); ++ } ++ ++ public abstract static class PrioritizedTask { ++ ++ protected final AtomicReference queue = new AtomicReference<>(); ++ ++ protected final AtomicInteger priority; ++ ++ protected PrioritizedTask() { ++ this(PrioritizedTaskQueue.NORMAL_PRIORITY); ++ } ++ ++ protected PrioritizedTask(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority " + priority); ++ } ++ this.priority = new AtomicInteger(priority); ++ } ++ ++ /** ++ * Returns the current priority. Note that {@link PrioritizedTaskQueue#COMPLETING_PRIORITY} will be returned ++ * if this task is completing or has completed. ++ */ ++ public final int getPriority() { ++ return this.priority.get(); ++ } ++ ++ /** ++ * Returns whether this task is scheduled to execute, or has been already executed. ++ */ ++ public boolean isScheduled() { ++ return this.queue.get() != null; ++ } ++ ++ final int tryComplete(final int minPriority) { ++ for (int curr = this.getPriorityVolatile();;) { ++ if (curr == COMPLETING_PRIORITY) { ++ return COMPLETING_PRIORITY; ++ } ++ if (curr > minPriority) { ++ // curr is lower priority ++ return curr; ++ } ++ ++ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, COMPLETING_PRIORITY))) { ++ return curr; ++ } ++ continue; ++ } ++ } ++ ++ /** ++ * Forces this task to be completed. ++ * @return {@code true} if the task was cancelled, {@code false} if the task has already completed or is being completed. ++ */ ++ public boolean cancel() { ++ return this.exchangePriorityVolatile(PrioritizedTaskQueue.COMPLETING_PRIORITY) != PrioritizedTaskQueue.COMPLETING_PRIORITY; ++ } ++ ++ /** ++ * Attempts to raise the priority to the priority level specified. ++ * @param priority Priority specified ++ * @return {@code true} if successful, {@code false} otherwise. ++ */ ++ public boolean raisePriority(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority"); ++ } ++ ++ for (int curr = this.getPriorityVolatile();;) { ++ if (curr == COMPLETING_PRIORITY) { ++ return false; ++ } ++ if (priority >= curr) { ++ return true; ++ } ++ ++ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { ++ PrioritizedTaskQueue queue = this.queue.get(); ++ if (queue != null) { ++ //noinspection unchecked ++ queue.queues[priority].add(this); // silently fail on shutdown ++ } ++ return true; ++ } ++ continue; ++ } ++ } ++ ++ /** ++ * Attempts to set this task's priority level to the level specified. ++ * @param priority Specified priority level. ++ * @return {@code true} if successful, {@code false} if this task is completing or has completed. ++ */ ++ public boolean updatePriority(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalArgumentException("Invalid priority"); ++ } ++ ++ for (int curr = this.getPriorityVolatile();;) { ++ if (curr == COMPLETING_PRIORITY) { ++ return false; ++ } ++ if (curr == priority) { ++ return true; ++ } ++ ++ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { ++ PrioritizedTaskQueue queue = this.queue.get(); ++ if (queue != null) { ++ //noinspection unchecked ++ queue.queues[priority].add(this); // silently fail on shutdown ++ } ++ return true; ++ } ++ continue; ++ } ++ } ++ ++ void setQueue(final PrioritizedTaskQueue queue) { ++ this.queue.set(queue); ++ } ++ ++ /* priority */ ++ ++ protected final int getPriorityVolatile() { ++ return this.priority.get(); ++ } ++ ++ protected final int compareAndExchangePriorityVolatile(final int expect, final int update) { ++ if (this.priority.compareAndSet(expect, update)) { ++ return expect; ++ } ++ return this.priority.get(); ++ } ++ ++ protected final int exchangePriorityVolatile(final int value) { ++ return this.priority.getAndSet(value); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ee906b594b306906c170180a29a8b61997d05168 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java +@@ -0,0 +1,241 @@ ++package com.destroystokyo.paper.io; ++ ++import net.minecraft.server.MinecraftServer; ++import org.apache.logging.log4j.Logger; ++ ++import java.util.concurrent.ConcurrentLinkedQueue; ++import java.util.concurrent.atomic.AtomicBoolean; ++import java.util.concurrent.locks.LockSupport; ++ ++public class QueueExecutorThread extends Thread { ++ ++ private static final Logger LOGGER = MinecraftServer.LOGGER; ++ ++ protected final PrioritizedTaskQueue queue; ++ protected final long spinWaitTime; ++ ++ protected volatile boolean closed; ++ ++ protected final AtomicBoolean parked = new AtomicBoolean(); ++ ++ protected volatile ConcurrentLinkedQueue flushQueue = new ConcurrentLinkedQueue<>(); ++ protected volatile long flushCycles; ++ ++ public QueueExecutorThread(final PrioritizedTaskQueue queue) { ++ this(queue, (int)(1.e6)); // 1.0ms ++ } ++ ++ public QueueExecutorThread(final PrioritizedTaskQueue queue, final long spinWaitTime) { // in ms ++ this.queue = queue; ++ this.spinWaitTime = spinWaitTime; ++ } ++ ++ @Override ++ public void run() { ++ final long spinWaitTime = this.spinWaitTime; ++ main_loop: ++ for (;;) { ++ this.pollTasks(true); ++ ++ // spinwait ++ ++ final long start = System.nanoTime(); ++ ++ for (;;) { ++ // If we are interrpted for any reason, park() will always return immediately. Clear so that we don't needlessly use cpu in such an event. ++ Thread.interrupted(); ++ LockSupport.parkNanos("Spinwaiting on tasks", 1000L); // 1us ++ ++ if (this.pollTasks(true)) { ++ // restart loop, found tasks ++ continue main_loop; ++ } ++ ++ if (this.handleClose()) { ++ return; // we're done ++ } ++ ++ if ((System.nanoTime() - start) >= spinWaitTime) { ++ break; ++ } ++ } ++ ++ if (this.handleClose()) { ++ return; ++ } ++ ++ this.parked.set(true); ++ ++ // We need to parse here to avoid a race condition where a thread queues a task before we set parked to true ++ // (i.e it will not notify us) ++ if (this.pollTasks(true)) { ++ this.parked.set(false); ++ continue; ++ } ++ ++ if (this.handleClose()) { ++ return; ++ } ++ ++ // we don't need to check parked before sleeping, but we do need to check parked in a do-while loop ++ // LockSupport.park() can fail for any reason ++ do { ++ Thread.interrupted(); ++ LockSupport.park("Waiting on tasks"); ++ } while (this.parked.get()); ++ } ++ } ++ ++ protected boolean handleClose() { ++ if (this.closed) { ++ this.pollTasks(true); // this ensures we've emptied the queue ++ this.handleFlushThreads(true); ++ return true; ++ } ++ return false; ++ } ++ ++ protected boolean pollTasks(boolean flushTasks) { ++ Runnable task; ++ boolean ret = false; ++ ++ while ((task = this.queue.poll()) != null) { ++ ret = true; ++ try { ++ task.run(); ++ } catch (final Throwable throwable) { ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath)throwable; ++ } ++ LOGGER.fatal("Exception thrown from prioritized runnable task in thread '" + this.getName() + "': " + IOUtil.genericToString(task), throwable); ++ } ++ } ++ ++ if (flushTasks) { ++ this.handleFlushThreads(false); ++ } ++ ++ return ret; ++ } ++ ++ protected void handleFlushThreads(final boolean shutdown) { ++ Thread parking; ++ ConcurrentLinkedQueue flushQueue = this.flushQueue; ++ do { ++ ++flushCycles; // may be plain read opaque write ++ while ((parking = flushQueue.poll()) != null) { ++ LockSupport.unpark(parking); ++ } ++ } while (this.pollTasks(false)); ++ ++ if (shutdown) { ++ this.flushQueue = null; ++ ++ // defend against a race condition where a flush thread double-checks right before we set to null ++ while ((parking = flushQueue.poll()) != null) { ++ LockSupport.unpark(parking); ++ } ++ } ++ } ++ ++ /** ++ * Notify's this thread that a task has been added to its queue ++ * @return {@code true} if this thread was waiting for tasks, {@code false} if it is executing tasks ++ */ ++ public boolean notifyTasks() { ++ if (this.parked.get() && this.parked.getAndSet(false)) { ++ LockSupport.unpark(this); ++ return true; ++ } ++ return false; ++ } ++ ++ protected void queueTask(final T task) { ++ this.queue.add(task); ++ this.notifyTasks(); ++ } ++ ++ /** ++ * Waits until this thread's queue is empty. ++ * ++ * @throws IllegalStateException If the current thread is {@code this} thread. ++ */ ++ public void flush() { ++ final Thread currentThread = Thread.currentThread(); ++ ++ if (currentThread == this) { ++ // avoid deadlock ++ throw new IllegalStateException("Cannot flush the queue executor thread while on the queue executor thread"); ++ } ++ ++ // order is important ++ ++ int successes = 0; ++ long lastCycle = -1L; ++ ++ do { ++ final ConcurrentLinkedQueue flushQueue = this.flushQueue; ++ if (flushQueue == null) { ++ return; ++ } ++ ++ flushQueue.add(currentThread); ++ ++ // double check flush queue ++ if (this.flushQueue == null) { ++ return; ++ } ++ ++ final long currentCycle = this.flushCycles; // may be opaque read ++ ++ if (currentCycle == lastCycle) { ++ Thread.yield(); ++ continue; ++ } ++ ++ // force response ++ this.parked.set(false); ++ LockSupport.unpark(this); ++ ++ LockSupport.park("flushing queue executor thread"); ++ ++ // returns whether there are tasks queued, does not return whether there are tasks executing ++ // this is why we cycle twice twice through flush (we know a pollTask call is made after a flush cycle) ++ // we really only need to guarantee that the tasks this thread has queued has gone through, and can leave ++ // tasks queued concurrently that are unsychronized with this thread as undefined behavior ++ if (this.queue.hasTasks()) { ++ successes = 0; ++ } else { ++ ++successes; ++ } ++ ++ } while (successes != 2); ++ ++ } ++ ++ /** ++ * Closes this queue executor's queue and optionally waits for it to empty. ++ *

    ++ * If wait is {@code true}, then the queue will be empty by the time this call completes. ++ *

    ++ *

    ++ * This function is MT-Safe. ++ *

    ++ * @param wait If this call is to wait until the queue is empty ++ * @param killQueue Whether to shutdown this thread's queue ++ * @return whether this thread shut down the queue ++ */ ++ public boolean close(final boolean wait, final boolean killQueue) { ++ boolean ret = !killQueue ? false : this.queue.shutdown(); ++ this.closed = true; ++ ++ // force thread to respond to the shutdown ++ this.parked.set(false); ++ LockSupport.unpark(this); ++ ++ if (wait) { ++ this.flush(); ++ } ++ return ret; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9a2b51d005efc9d31b3685e8298fd00b341c7dc7 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java +@@ -0,0 +1,146 @@ ++package com.destroystokyo.paper.io.chunk; ++ ++import co.aikar.timings.Timing; ++import com.destroystokyo.paper.io.PaperFileIOThread; ++import com.destroystokyo.paper.io.IOUtil; ++import net.minecraft.server.level.PlayerChunkMap; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; ++ ++import java.util.ArrayDeque; ++import java.util.function.Consumer; ++ ++public final class ChunkLoadTask extends ChunkTask { ++ ++ public boolean cancelled; ++ ++ Consumer onComplete; ++ public PaperFileIOThread.ChunkData chunkData; ++ ++ private boolean hasCompleted; ++ ++ public ChunkLoadTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, ++ final ChunkTaskManager taskManager, ++ final Consumer onComplete) { ++ super(world, chunkX, chunkZ, priority, taskManager); ++ this.onComplete = onComplete; ++ } ++ ++ private static final ArrayDeque EMPTY_QUEUE = new ArrayDeque<>(); ++ ++ private static ChunkRegionLoader.InProgressChunkHolder createEmptyHolder() { ++ return new ChunkRegionLoader.InProgressChunkHolder(null, EMPTY_QUEUE); ++ } ++ ++ @Override ++ public void run() { ++ try { ++ this.executeTask(); ++ } catch (final Throwable ex) { ++ PaperFileIOThread.LOGGER.error("Failed to execute chunk load task: " + this.toString(), ex); ++ if (!this.hasCompleted) { ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ } ++ } ++ } ++ ++ private boolean checkCancelled() { ++ if (this.cancelled) { ++ // IntelliJ does not understand writes may occur to cancelled concurrently. ++ return this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap != ChunkLoadTask.this) { ++ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); ++ } ++ ++ if (valueInMap.cancelled) { ++ return null; ++ } ++ return valueInMap; ++ }) == null; ++ } ++ return false; ++ } ++ ++ public void executeTask() { ++ if (this.checkCancelled()) { ++ return; ++ } ++ ++ // either executed synchronously or asynchronously ++ final PaperFileIOThread.ChunkData chunkData = this.chunkData; ++ ++ if (chunkData.poiData == PaperFileIOThread.FAILURE_VALUE || chunkData.chunkData == PaperFileIOThread.FAILURE_VALUE) { ++ PaperFileIOThread.LOGGER.error("Could not load chunk for task: " + this.toString() + ", file IO thread has dumped the relevant exception above"); ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ return; ++ } ++ ++ if (chunkData.chunkData == null) { ++ // not on disk ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ return; ++ } ++ ++ final ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(this.chunkX, this.chunkZ); ++ ++ final PlayerChunkMap chunkManager = this.world.getChunkProvider().playerChunkMap; ++ ++ try (Timing ignored = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { ++ final ChunkRegionLoader.InProgressChunkHolder chunkHolder; ++ ++ // apply fixes ++ ++ try { ++ chunkData.chunkData = chunkManager.getChunkData(this.world.getTypeKey(), ++ chunkManager.getWorldPersistentDataSupplier(), chunkData.chunkData, chunkPos, this.world); // clone data for safety, file IO thread does not clone ++ } catch (final Throwable ex) { ++ PaperFileIOThread.LOGGER.error("Could not apply datafixers for chunk task: " + this.toString(), ex); ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ } ++ ++ if (this.checkCancelled()) { ++ return; ++ } ++ ++ try { ++ this.world.getChunkProvider().playerChunkMap.updateChunkStatusOnDisk(chunkPos, chunkData.chunkData); ++ } catch (final Throwable ex) { ++ PaperFileIOThread.LOGGER.warn("Failed to update chunk status cache for task: " + this.toString(), ex); ++ // non-fatal, continue ++ } ++ ++ try { ++ chunkHolder = ChunkRegionLoader.loadChunk(this.world, ++ chunkManager.definedStructureManager, chunkManager.getVillagePlace(), chunkPos, ++ chunkData.chunkData, true); ++ } catch (final Throwable ex) { ++ PaperFileIOThread.LOGGER.error("Could not de-serialize chunk data for task: " + this.toString(), ex); ++ this.complete(ChunkLoadTask.createEmptyHolder()); ++ return; ++ } ++ ++ this.complete(chunkHolder); ++ } ++ } ++ ++ private void complete(final ChunkRegionLoader.InProgressChunkHolder holder) { ++ this.hasCompleted = true; ++ holder.poiData = this.chunkData == null ? null : this.chunkData.poiData; ++ ++ this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap != ChunkLoadTask.this) { ++ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); ++ } ++ if (valueInMap.cancelled) { ++ return null; ++ } ++ try { ++ ChunkLoadTask.this.onComplete.accept(holder); ++ } catch (final Throwable thr) { ++ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); ++ } ++ return null; ++ }); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e3ad8f50b51c4e9bf38ffa5911444cc88d3f67eb +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java +@@ -0,0 +1,111 @@ ++package com.destroystokyo.paper.io.chunk; ++ ++import co.aikar.timings.Timing; ++import com.destroystokyo.paper.io.PaperFileIOThread; ++import com.destroystokyo.paper.io.IOUtil; ++import com.destroystokyo.paper.io.PrioritizedTaskQueue; ++ ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.atomic.AtomicInteger; ++import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.chunk.IChunkAccess; ++import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; ++ ++public final class ChunkSaveTask extends ChunkTask { ++ ++ public final ChunkRegionLoader.AsyncSaveData asyncSaveData; ++ public final IChunkAccess chunk; ++ public final CompletableFuture onComplete = new CompletableFuture<>(); ++ ++ private final AtomicInteger attemptedPriority; ++ ++ public ChunkSaveTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, ++ final ChunkTaskManager taskManager, final ChunkRegionLoader.AsyncSaveData asyncSaveData, ++ final IChunkAccess chunk) { ++ super(world, chunkX, chunkZ, priority, taskManager); ++ this.chunk = chunk; ++ this.asyncSaveData = asyncSaveData; ++ this.attemptedPriority = new AtomicInteger(priority); ++ } ++ ++ @Override ++ public void run() { ++ // can be executed asynchronously or synchronously ++ final NBTTagCompound compound; ++ ++ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTimingIfSync()) { ++ compound = ChunkRegionLoader.saveChunk(this.world, this.chunk, this.asyncSaveData); ++ } catch (final Throwable ex) { ++ // has a plugin modified something it should not have and made us CME? ++ PaperFileIOThread.LOGGER.error("Failed to serialize unloading chunk data for task: " + this.toString() + ", falling back to a synchronous execution", ex); ++ ++ // Note: We add to the server thread queue here since this is what the server will drain tasks from ++ // when waiting for chunks ++ ChunkTaskManager.queueChunkWaitTask(() -> { ++ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTiming()) { ++ NBTTagCompound data = PaperFileIOThread.FAILURE_VALUE; ++ ++ try { ++ data = ChunkRegionLoader.saveChunk(this.world, this.chunk, this.asyncSaveData); ++ PaperFileIOThread.LOGGER.info("Successfully serialized chunk data for task: " + this.toString() + " synchronously"); ++ } catch (final Throwable ex1) { ++ PaperFileIOThread.LOGGER.fatal("Failed to synchronously serialize unloading chunk data for task: " + this.toString() + "! Chunk data will be lost", ex1); ++ } ++ ++ ChunkSaveTask.this.complete(data); ++ } ++ }); ++ ++ return; // the main thread will now complete the data ++ } ++ ++ this.complete(compound); ++ } ++ ++ @Override ++ public boolean raisePriority(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalStateException("Invalid priority: " + priority); ++ } ++ ++ // we know priority is valid here ++ for (int curr = this.attemptedPriority.get();;) { ++ if (curr <= priority) { ++ break; // curr is higher/same priority ++ } ++ if (this.attemptedPriority.compareAndSet(curr, priority)) { ++ break; ++ } ++ curr = this.attemptedPriority.get(); ++ } ++ ++ return super.raisePriority(priority); ++ } ++ ++ @Override ++ public boolean updatePriority(final int priority) { ++ if (!PrioritizedTaskQueue.validPriority(priority)) { ++ throw new IllegalStateException("Invalid priority: " + priority); ++ } ++ this.attemptedPriority.set(priority); ++ return super.updatePriority(priority); ++ } ++ ++ private void complete(final NBTTagCompound compound) { ++ try { ++ this.onComplete.complete(compound); ++ } catch (final Throwable thr) { ++ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); ++ } ++ if (compound != PaperFileIOThread.FAILURE_VALUE) { ++ PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, this.chunkX, this.chunkZ, null, compound, this.attemptedPriority.get()); ++ } ++ this.taskManager.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { ++ if (valueInMap != ChunkSaveTask.this) { ++ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", this: " + ChunkSaveTask.this); ++ } ++ return null; ++ }); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9c1370c7d85262da9d64871e03e5a8a8c5e087d7 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java +@@ -0,0 +1,40 @@ ++package com.destroystokyo.paper.io.chunk; ++ ++import com.destroystokyo.paper.io.PaperFileIOThread; ++import com.destroystokyo.paper.io.PrioritizedTaskQueue; ++import net.minecraft.server.level.WorldServer; ++ ++abstract class ChunkTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { ++ ++ public final WorldServer world; ++ public final int chunkX; ++ public final int chunkZ; ++ public final ChunkTaskManager taskManager; ++ ++ public ChunkTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, ++ final ChunkTaskManager taskManager) { ++ super(priority); ++ this.world = world; ++ this.chunkX = chunkX; ++ this.chunkZ = chunkZ; ++ this.taskManager = taskManager; ++ } ++ ++ @Override ++ public String toString() { ++ return "Chunk task: class:" + this.getClass().getName() + ", for world '" + this.world.getWorld().getName() + ++ "', (" + this.chunkX + "," + this.chunkZ + "), hashcode:" + this.hashCode() + ", priority: " + this.getPriority(); ++ } ++ ++ @Override ++ public boolean raisePriority(final int priority) { ++ PaperFileIOThread.Holder.INSTANCE.bumpPriority(this.world, this.chunkX, this.chunkZ, priority); ++ return super.raisePriority(priority); ++ } ++ ++ @Override ++ public boolean updatePriority(final int priority) { ++ PaperFileIOThread.Holder.INSTANCE.setPriority(this.world, this.chunkX, this.chunkZ, priority); ++ return super.updatePriority(priority); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8e642f450b974d81f128d26edfd40915554db638 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +@@ -0,0 +1,513 @@ ++package com.destroystokyo.paper.io.chunk; ++ ++import com.destroystokyo.paper.io.PaperFileIOThread; ++import com.destroystokyo.paper.io.IOUtil; ++import com.destroystokyo.paper.io.PrioritizedTaskQueue; ++import com.destroystokyo.paper.io.QueueExecutorThread; ++import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ChunkProviderServer; ++import net.minecraft.server.level.PlayerChunk; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.util.thread.IAsyncTaskHandler; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.chunk.IChunkAccess; ++import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; ++import org.apache.commons.lang.StringUtils; ++import org.apache.logging.log4j.Level; ++import org.bukkit.Bukkit; ++import org.spigotmc.AsyncCatcher; ++ ++import java.util.ArrayDeque; ++import java.util.HashSet; ++import java.util.Set; ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.ConcurrentLinkedQueue; ++import java.util.function.Consumer; ++ ++public final class ChunkTaskManager { ++ ++ private final QueueExecutorThread[] workers; ++ private final WorldServer world; ++ ++ private final PrioritizedTaskQueue queue; ++ private final boolean perWorldQueue; ++ ++ final ConcurrentHashMap chunkLoadTasks = new ConcurrentHashMap<>(64, 0.5f); ++ final ConcurrentHashMap chunkSaveTasks = new ConcurrentHashMap<>(64, 0.5f); ++ ++ private final PrioritizedTaskQueue chunkTasks = new PrioritizedTaskQueue<>(); // used if async chunks are disabled in config ++ ++ protected static QueueExecutorThread[] globalWorkers; ++ protected static QueueExecutorThread globalUrgentWorker; ++ protected static PrioritizedTaskQueue globalQueue; ++ protected static PrioritizedTaskQueue globalUrgentQueue; ++ ++ protected static final ConcurrentLinkedQueue CHUNK_WAIT_QUEUE = new ConcurrentLinkedQueue<>(); ++ ++ public static final ArrayDeque WAITING_CHUNKS = new ArrayDeque<>(); // stack ++ ++ private static final class ChunkInfo { ++ ++ public final int chunkX; ++ public final int chunkZ; ++ public final WorldServer world; ++ ++ public ChunkInfo(final int chunkX, final int chunkZ, final WorldServer world) { ++ this.chunkX = chunkX; ++ this.chunkZ = chunkZ; ++ this.world = world; ++ } ++ ++ @Override ++ public String toString() { ++ return "[( " + this.chunkX + "," + this.chunkZ + ") in '" + this.world.getWorld().getName() + "']"; ++ } ++ } ++ ++ public static void pushChunkWait(final WorldServer world, final int chunkX, final int chunkZ) { ++ synchronized (WAITING_CHUNKS) { ++ WAITING_CHUNKS.push(new ChunkInfo(chunkX, chunkZ, world)); ++ } ++ } ++ ++ public static void popChunkWait() { ++ synchronized (WAITING_CHUNKS) { ++ WAITING_CHUNKS.pop(); ++ } ++ } ++ ++ private static ChunkInfo[] getChunkInfos() { ++ ChunkInfo[] chunks; ++ synchronized (WAITING_CHUNKS) { ++ chunks = WAITING_CHUNKS.toArray(new ChunkInfo[0]); ++ } ++ return chunks; ++ } ++ ++ public static void dumpAllChunkLoadInfo() { ++ ChunkInfo[] chunks = getChunkInfos(); ++ if (chunks.length > 0) { ++ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk wait task info below: "); ++ ++ for (final ChunkInfo chunkInfo : chunks) { ++ final long key = IOUtil.getCoordinateKey(chunkInfo.chunkX, chunkInfo.chunkZ); ++ final ChunkLoadTask loadTask = chunkInfo.world.asyncChunkTaskManager.chunkLoadTasks.get(key); ++ final ChunkSaveTask saveTask = chunkInfo.world.asyncChunkTaskManager.chunkSaveTasks.get(key); ++ ++ PaperFileIOThread.LOGGER.log(Level.ERROR, chunkInfo.chunkX + "," + chunkInfo.chunkZ + " in '" + chunkInfo.world.getWorld().getName() + ":"); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, "Load Task - " + (loadTask == null ? "none" : loadTask.toString())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, "Save Task - " + (saveTask == null ? "none" : saveTask.toString())); ++ // log current status of chunk to indicate whether we're waiting on generation or loading ++ PlayerChunk chunkHolder = chunkInfo.world.getChunkProvider().playerChunkMap.getVisibleChunk(key); ++ ++ dumpChunkInfo(new HashSet<>(), chunkHolder, chunkInfo.chunkX, chunkInfo.chunkZ); ++ } ++ } ++ } ++ ++ static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z) { ++ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); ++ } ++ ++ static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z, int indent, int maxDepth) { ++ if (seenChunks.contains(chunkHolder)) { ++ return; ++ } ++ if (indent > maxDepth) { ++ return; ++ } ++ seenChunks.add(chunkHolder); ++ String indentStr = StringUtils.repeat(" ", indent); ++ if (chunkHolder == null) { ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - null for (" + x +"," + z +")"); ++ } else { ++ IChunkAccess chunk = chunkHolder.getAvailableChunkNow(); ++ ChunkStatus holderStatus = chunkHolder.getChunkHolderStatus(); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - non-null"); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getChunkStatus().toString())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + PlayerChunk.getChunkStatus(chunkHolder.getTicketLevel())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); ++ } ++ } ++ ++ public static void initGlobalLoadThreads(int threads) { ++ if (threads <= 0 || globalWorkers != null) { ++ return; ++ } ++ ++ globalWorkers = new QueueExecutorThread[threads]; ++ globalQueue = new PrioritizedTaskQueue<>(); ++ globalUrgentQueue = new PrioritizedTaskQueue<>(); ++ ++ for (int i = 0; i < threads; ++i) { ++ globalWorkers[i] = new QueueExecutorThread<>(globalQueue, (long)0.10e6); //0.1ms ++ globalWorkers[i].setName("Paper Async Chunk Task Thread #" + i); ++ globalWorkers[i].setPriority(Thread.NORM_PRIORITY - 1); ++ globalWorkers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { ++ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); ++ }); ++ ++ globalWorkers[i].start(); ++ } ++ ++ globalUrgentWorker = new QueueExecutorThread<>(globalUrgentQueue, (long)0.10e6); //0.1ms ++ globalUrgentWorker.setName("Paper Async Chunk Urgent Task Thread"); ++ globalUrgentWorker.setPriority(Thread.NORM_PRIORITY+1); ++ globalUrgentWorker.setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { ++ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); ++ }); ++ ++ globalUrgentWorker.start(); ++ } ++ ++ /** ++ * Creates this chunk task manager to operate off the specified number of threads. If the specified number of threads is ++ * less-than or equal to 0, then this chunk task manager will operate off of the world's chunk task queue. ++ * @param world Specified world. ++ * @param threads Specified number of threads. ++ * @see ChunkProviderServer#serverThreadQueue ++ */ ++ public ChunkTaskManager(final WorldServer world, final int threads) { ++ this.world = world; ++ this.workers = threads <= 0 ? null : new QueueExecutorThread[threads]; ++ this.queue = new PrioritizedTaskQueue<>(); ++ this.perWorldQueue = true; ++ ++ for (int i = 0; i < threads; ++i) { ++ this.workers[i] = new QueueExecutorThread<>(this.queue, (long)0.10e6); //0.1ms ++ this.workers[i].setName("Async chunk loader thread #" + i + " for world: " + world.getWorld().getName()); ++ this.workers[i].setPriority(Thread.NORM_PRIORITY - 1); ++ this.workers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { ++ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); ++ }); ++ ++ this.workers[i].start(); ++ } ++ } ++ ++ /** ++ * Creates the chunk task manager to work from the global workers. When {@link #close(boolean)} is invoked, ++ * the global queue is not shutdown. If the global workers is configured to be disabled or use 0 threads, then ++ * this chunk task manager will operate off of the world's chunk task queue. ++ * @param world The world that this task manager is responsible for ++ * @see ChunkProviderServer#serverThreadQueue ++ */ ++ public ChunkTaskManager(final WorldServer world) { ++ this.world = world; ++ this.workers = globalWorkers; ++ this.queue = globalQueue; ++ this.perWorldQueue = false; ++ } ++ ++ public boolean pollNextChunkTask() { ++ final ChunkTask task = this.chunkTasks.poll(); ++ ++ if (task != null) { ++ task.run(); ++ return true; ++ } ++ return false; ++ } ++ ++ /** ++ * Polls and runs the next available chunk wait queue task. This is to be used when the server is waiting on a chunk queue. ++ * (per-world can cause issues if all the worker threads are blocked waiting for a response from the main thread) ++ */ ++ public static boolean pollChunkWaitQueue() { ++ final Runnable run = CHUNK_WAIT_QUEUE.poll(); ++ if (run != null) { ++ run.run(); ++ return true; ++ } ++ return false; ++ } ++ ++ /** ++ * Queues a chunk wait task. Note that this will execute out of order with respect to tasks scheduled on a world's ++ * chunk task queue, since this is the global chunk wait queue. ++ */ ++ public static void queueChunkWaitTask(final Runnable runnable) { ++ CHUNK_WAIT_QUEUE.add(runnable); ++ } ++ ++ private static void drainChunkWaitQueue() { ++ Runnable run; ++ while ((run = CHUNK_WAIT_QUEUE.poll()) != null) { ++ run.run(); ++ } ++ } ++ ++ /** ++ * The exact same as {@link #scheduleChunkLoad(int, int, int, Consumer, boolean)}, except that the chunk data is provided as ++ * the {@code data} parameter. ++ */ ++ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, ++ final Consumer onComplete, ++ final boolean intendingToBlock, final CompletableFuture dataFuture) { ++ final WorldServer world = this.world; ++ ++ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap != null) { ++ if (!valueInMap.cancelled) { ++ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); ++ } ++ valueInMap.cancelled = false; ++ valueInMap.onComplete = onComplete; ++ return valueInMap; ++ } ++ ++ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); ++ ++ dataFuture.thenAccept((final NBTTagCompound data) -> { ++ final boolean failed = data == PaperFileIOThread.FAILURE_VALUE; ++ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { ++ ret.chunkData = chunkData; ++ if (!failed) { ++ chunkData.chunkData = data; ++ } ++ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here ++ }, true, failed, intendingToBlock); // read data off disk if the future fails ++ }); ++ ++ return ret; ++ }); ++ } ++ ++ public void cancelChunkLoad(final int chunkX, final int chunkZ) { ++ this.chunkLoadTasks.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap == null) { ++ return null; ++ } ++ ++ if (valueInMap.cancelled) { ++ PaperFileIOThread.LOGGER.warn("Task " + valueInMap.toString() + " is already cancelled!"); ++ } ++ valueInMap.cancelled = true; ++ if (valueInMap.cancel()) { ++ return null; ++ } ++ ++ return valueInMap; ++ }); ++ } ++ ++ /** ++ * Schedules an asynchronous chunk load for the specified coordinates. The onComplete parameter may be invoked asynchronously ++ * on a worker thread or on the world's chunk executor queue. As such the code that is executed for the parameter should be ++ * carefully chosen. ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority for this task ++ * @param onComplete The consumer to invoke with the {@link ChunkRegionLoader.InProgressChunkHolder} object once this task is complete ++ * @param intendingToBlock Whether the caller is intending to block on this task completing (this is a performance tune, and has no adverse side-effects) ++ * @return The {@link ChunkLoadTask} associated with ++ */ ++ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, ++ final Consumer onComplete, ++ final boolean intendingToBlock) { ++ final WorldServer world = this.world; ++ ++ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { ++ if (valueInMap != null) { ++ if (!valueInMap.cancelled) { ++ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); ++ } ++ valueInMap.cancelled = false; ++ valueInMap.onComplete = onComplete; ++ return valueInMap; ++ } ++ ++ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); ++ ++ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { ++ ret.chunkData = chunkData; ++ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here ++ }, true, true, intendingToBlock); ++ ++ return ret; ++ }); ++ } ++ ++ /** ++ * Schedules an async save for the specified chunk. The chunk, at the beginning of this call, must be completely unloaded ++ * from the world. ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @param priority Priority for this task ++ * @param asyncSaveData Async save data. See {@link ChunkRegionLoader#getAsyncSaveData(WorldServer, IChunkAccess)} ++ * @param chunk Chunk to save ++ * @return The {@link ChunkSaveTask} associated with the save task. ++ */ ++ public ChunkSaveTask scheduleChunkSave(final int chunkX, final int chunkZ, final int priority, ++ final ChunkRegionLoader.AsyncSaveData asyncSaveData, ++ final IChunkAccess chunk) { ++ AsyncCatcher.catchOp("chunk save schedule"); ++ ++ final WorldServer world = this.world; ++ ++ return this.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { ++ if (valueInMap != null) { ++ throw new IllegalStateException("Double scheduling chunk save for task: " + valueInMap.toString()); ++ } ++ ++ final ChunkSaveTask ret = new ChunkSaveTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, asyncSaveData, chunk); ++ ++ ChunkTaskManager.this.internalSchedule(ret); ++ ++ return ret; ++ }); ++ } ++ ++ /** ++ * Returns a completable future which will be completed with the un-copied chunk data for an in progress async save. ++ * Returns {@code null} if no save is in progress. ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ */ ++ public CompletableFuture getChunkSaveFuture(final int chunkX, final int chunkZ) { ++ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); ++ if (chunkSaveTask == null) { ++ return null; ++ } ++ return chunkSaveTask.onComplete; ++ } ++ ++ /** ++ * Returns the chunk object being used to serialize data async for an unloaded chunk. Note that modifying this chunk ++ * is not safe to do as another thread is handling its save. The chunk is also not loaded into the world. ++ * @param chunkX Chunk's x coordinate ++ * @param chunkZ Chunk's z coordinate ++ * @return Chunk object for an in-progress async save, or {@code null} if no save is in progress ++ */ ++ public IChunkAccess getChunkInSaveProgress(final int chunkX, final int chunkZ) { ++ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); ++ if (chunkSaveTask == null) { ++ return null; ++ } ++ return chunkSaveTask.chunk; ++ } ++ ++ public void flush() { ++ // flush here since we schedule tasks on the IO thread that can schedule tasks here ++ drainChunkWaitQueue(); ++ PaperFileIOThread.Holder.INSTANCE.flush(); ++ drainChunkWaitQueue(); ++ ++ if (this.workers == null) { ++ if (Bukkit.isPrimaryThread() || MinecraftServer.getServer().hasStopped()) { ++ ((IAsyncTaskHandler)this.world.getChunkProvider().serverThreadQueue).executeAll(); ++ } else { ++ CompletableFuture wait = new CompletableFuture<>(); ++ MinecraftServer.getServer().scheduleOnMain(() -> { ++ ((IAsyncTaskHandler)this.world.getChunkProvider().serverThreadQueue).executeAll(); ++ }); ++ wait.join(); ++ } ++ } else { ++ for (final QueueExecutorThread worker : this.workers) { ++ worker.flush(); ++ } ++ } ++ if (globalUrgentWorker != null) globalUrgentWorker.flush(); ++ ++ // flush again since tasks we execute async saves ++ drainChunkWaitQueue(); ++ PaperFileIOThread.Holder.INSTANCE.flush(); ++ } ++ ++ public void close(final boolean wait) { ++ // flush here since we schedule tasks on the IO thread that can schedule tasks to this task manager ++ // we do this regardless of the wait param since after we invoke close no tasks can be queued ++ PaperFileIOThread.Holder.INSTANCE.flush(); ++ ++ if (this.workers == null) { ++ if (wait) { ++ this.flush(); ++ } ++ return; ++ } ++ ++ if (this.workers != globalWorkers) { ++ for (final QueueExecutorThread worker : this.workers) { ++ worker.close(false, this.perWorldQueue); ++ } ++ } ++ ++ if (wait) { ++ this.flush(); ++ } ++ } ++ ++ public void raisePriority(final int chunkX, final int chunkZ, final int priority) { ++ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); ++ ++ ChunkTask chunkSaveTask = this.chunkSaveTasks.get(chunkKey); ++ if (chunkSaveTask != null) { ++ // don't bump save into urgent queue ++ raiseTaskPriority(chunkSaveTask, priority != PrioritizedTaskQueue.HIGHEST_PRIORITY ? priority : PrioritizedTaskQueue.HIGH_PRIORITY); ++ } ++ ++ ChunkLoadTask chunkLoadTask = this.chunkLoadTasks.get(chunkKey); ++ if (chunkLoadTask != null) { ++ raiseTaskPriority(chunkLoadTask, priority); ++ } ++ } ++ ++ private void raiseTaskPriority(ChunkTask task, int priority) { ++ final boolean raised = task.raisePriority(priority); ++ if (task.isScheduled() && raised && this.workers != null) { ++ // only notify if we're in queue to be executed ++ if (priority == PrioritizedTaskQueue.HIGHEST_PRIORITY) { ++ // was in another queue but became urgent later, add to urgent queue and the previous ++ // queue will just have to ignore this task if it has already been started. ++ // Ultimately, we now have 2 potential queues that can pull it out whoever gets it first ++ // but the urgent queue has dedicated thread(s) so it's likely to win.... ++ globalUrgentQueue.add(task); ++ this.internalScheduleNotifyUrgent(); ++ } else { ++ this.internalScheduleNotify(); ++ } ++ } ++ } ++ ++ protected void internalSchedule(final ChunkTask task) { ++ if (this.workers == null) { ++ this.chunkTasks.add(task); ++ return; ++ } ++ ++ // It's important we order the task to be executed before notifying. Avoid a race condition where the worker thread ++ // wakes up and goes to sleep before we actually schedule (or it's just about to sleep) ++ if (task.getPriority() == PrioritizedTaskQueue.HIGHEST_PRIORITY) { ++ globalUrgentQueue.add(task); ++ this.internalScheduleNotifyUrgent(); ++ } else { ++ this.queue.add(task); ++ this.internalScheduleNotify(); ++ } ++ ++ } ++ ++ protected void internalScheduleNotify() { ++ if (this.workers == null) { ++ return; ++ } ++ for (final QueueExecutorThread worker : this.workers) { ++ if (worker.notifyTasks()) { ++ // break here since we only want to wake up one worker for scheduling one task ++ break; ++ } ++ } ++ } ++ ++ ++ protected void internalScheduleNotifyUrgent() { ++ if (globalUrgentWorker == null) { ++ return; ++ } ++ globalUrgentWorker.notifyTasks(); ++ } ++ ++} +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java +index e201e4efd4ecc65ec3c38528a4ec5336e2d51ab2..45f3f8964a587c382b6ea82560e9da30be42987f 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java +@@ -14,7 +14,7 @@ public class PacketPlayInTabComplete implements Packet { + @Override + public void a(PacketDataSerializer packetdataserializer) throws IOException { + this.a = packetdataserializer.i(); +- this.b = packetdataserializer.e(32500); ++ this.b = packetdataserializer.e(2048); + } + + @Override +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index fbd33aef21b4539d249c367609a36491530fb7ca..5a410550cfb48505c9de9979465ed1528c8fbf05 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -714,4 +714,9 @@ public final class MCUtil { + out.print(fileData); + } + } ++ ++ public static int getTicketLevelFor(ChunkStatus status) { ++ // TODO make sure the constant `33` is correct on future updates. See getChunkAt(int, int, ChunkStatus, boolean) ++ return 33 + ChunkStatus.getTicketLevelOffset(status); ++ } + } +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 191a74bd9b894f9d64d0a55747cb17e07ceef597..1732fc552c290d294b68d6f92f2a58d985fbef21 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -42,6 +42,7 @@ import net.minecraft.server.players.UserCache; + import net.minecraft.util.MathHelper; + import net.minecraft.util.datafix.DataConverterRegistry; + import net.minecraft.util.worldupdate.WorldUpgrader; ++import net.minecraft.world.entity.npc.VillagerTrades; + import net.minecraft.world.level.DataPackConfiguration; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.World; +@@ -210,6 +211,7 @@ public class Main { + + convertable_conversionsession.a((IRegistryCustom) iregistrycustom_dimension, (SaveData) object); + */ ++ Class.forName(VillagerTrades.class.getName());// Paper - load this sync so it won't fail later async + final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.a((thread) -> { + DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataConverterRegistry.a(), minecraftsessionservice, gameprofilerepository, usercache, WorldLoadListenerLogger::new); + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 8b922136336d5dc8fc302cc0f4879c4968a1cc67..e6e8ab0b39a11b0aed247b9b80a6c1f97505546b 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -922,7 +922,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant> getChunkAtAsynchronously(int x, int z, boolean gen, boolean isUrgent) { ++ if (Thread.currentThread() != this.serverThread) { ++ CompletableFuture> future = new CompletableFuture>(); ++ this.serverThreadQueue.execute(() -> { ++ this.getChunkAtAsynchronously(x, z, gen, isUrgent).whenComplete((chunk, ex) -> { ++ if (ex != null) { ++ future.completeExceptionally(ex); ++ } else { ++ future.complete(chunk); ++ } ++ }); ++ }); ++ return future; ++ } ++ ++ if (!com.destroystokyo.paper.PaperConfig.asyncChunks) { ++ world.getWorld().loadChunk(x, z, gen); ++ Chunk chunk = getChunkAtIfLoadedMainThread(x, z); ++ return CompletableFuture.completedFuture(chunk != null ? Either.left(chunk) : PlayerChunk.UNLOADED_CHUNK_ACCESS); ++ } ++ ++ long k = ChunkCoordIntPair.pair(x, z); ++ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); ++ ++ IChunkAccess ichunkaccess; ++ ++ // try cache ++ for (int l = 0; l < 4; ++l) { ++ if (k == this.cachePos[l] && ChunkStatus.FULL == this.cacheStatus[l]) { ++ ichunkaccess = this.cacheChunk[l]; ++ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime ++ ++ // move to first in cache ++ ++ for (int i1 = 3; i1 > 0; --i1) { ++ this.cachePos[i1] = this.cachePos[i1 - 1]; ++ this.cacheStatus[i1] = this.cacheStatus[i1 - 1]; ++ this.cacheChunk[i1] = this.cacheChunk[i1 - 1]; ++ } ++ ++ this.cachePos[0] = k; ++ this.cacheStatus[0] = ChunkStatus.FULL; ++ this.cacheChunk[0] = ichunkaccess; ++ ++ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); ++ } ++ } ++ } ++ ++ if (gen) { ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ } ++ ++ IChunkAccess current = this.getChunkAtImmediately(x, z); // we want to bypass ticket restrictions ++ if (current != null) { ++ if (!(current instanceof ProtoChunkExtension) && !(current instanceof Chunk)) { ++ return CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK_ACCESS); ++ } ++ // we know the chunk is at full status here (either in read-only mode or the real thing) ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ } ++ ++ ChunkStatus status = world.getChunkProvider().playerChunkMap.getStatusOnDiskNoLoad(x, z); ++ ++ if (status != null && status != ChunkStatus.FULL) { ++ // does not exist on disk ++ return CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK_ACCESS); ++ } ++ ++ if (status == ChunkStatus.FULL) { ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ } ++ ++ // status is null here ++ ++ // here we don't know what status it is and we're not supposed to generate ++ // so we asynchronously load empty status ++ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.EMPTY, isUrgent).thenCompose((either) -> { ++ IChunkAccess chunk = either.left().orElse(null); ++ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof Chunk)) { ++ // the chunk on disk was not a full status chunk ++ return CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK_ACCESS); ++ } ++ ; // bring to full status if required ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ }); ++ } ++ ++ private CompletableFuture> bringToFullStatusAsync(int x, int z, ChunkCoordIntPair chunkPos, boolean isUrgent) { ++ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.FULL, isUrgent); ++ } ++ ++ private CompletableFuture> bringToStatusAsync(int x, int z, ChunkCoordIntPair chunkPos, ChunkStatus status, boolean isUrgent) { ++ CompletableFuture> future = this.getChunkFutureMainThread(x, z, status, true, isUrgent); ++ Long identifier = Long.valueOf(this.asyncLoadSeqCounter++); ++ int ticketLevel = MCUtil.getTicketLevelFor(status); ++ this.addTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); ++ ++ return future.thenComposeAsync((Either either) -> { ++ // either left -> success ++ // either right -> failure ++ ++ this.removeTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); ++ this.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); // allow unloading ++ ++ Optional failure = either.right(); ++ ++ if (failure.isPresent()) { ++ // failure ++ throw new IllegalStateException("Chunk failed to load: " + failure.get().toString()); ++ } ++ ++ return CompletableFuture.completedFuture(either); ++ }, this.serverThreadQueue); ++ } ++ ++ public void addTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { ++ this.chunkMapDistance.addTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); ++ } ++ ++ public void removeTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { ++ this.chunkMapDistance.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); ++ } + // Paper end + + @Nullable + @Override + public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { ++ final int x = i; final int z = j; // Paper - conflict on variable change + if (Thread.currentThread() != this.serverThread) { + return (IChunkAccess) CompletableFuture.supplyAsync(() -> { + return this.getChunkAt(i, j, chunkstatus, flag); +@@ -359,11 +487,16 @@ public class ChunkProviderServer extends IChunkProvider { + } + + gameprofilerfiller.c("getChunkCacheMiss"); +- CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag); ++ CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag, true); // Paper + + if (!completablefuture.isDone()) { // Paper ++ // Paper start - async chunk io/loading ++ this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z); ++ // Paper end + this.world.timings.syncChunkLoad.startTiming(); // Paper + this.serverThreadQueue.awaitTasks(completablefuture::isDone); ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug + this.world.timings.syncChunkLoad.stopTiming(); // Paper + } // Paper + ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { +@@ -429,6 +562,11 @@ public class ChunkProviderServer extends IChunkProvider { + } + + private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag) { ++ // Paper start - add isUrgent - old sig left in place for dirty nms plugins ++ return getChunkFutureMainThread(i, j, chunkstatus, flag, false); ++ } ++ private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag, boolean isUrgent) { ++ // Paper end + ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i, j); + long k = chunkcoordintpair.pair(); + int l = 33 + ChunkStatus.a(chunkstatus); +@@ -830,11 +968,12 @@ public class ChunkProviderServer extends IChunkProvider { + protected boolean executeNext() { + // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task + try { ++ boolean execChunkTask = com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ChunkProviderServer.this.world.asyncChunkTaskManager.pollNextChunkTask(); // Paper + if (ChunkProviderServer.this.tickDistanceManager()) { + return true; + } else { + ChunkProviderServer.this.lightEngine.queueUpdate(); +- return super.executeNext(); ++ return super.executeNext() || execChunkTask; // Paper + } + } finally { + playerChunkMap.callbackExecutor.run(); +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index 75d4a8fc394449ccc006fe67a8842edcd9f36854..6433463938d8bb717840c8f57fe6e7079e1030f2 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -158,6 +158,18 @@ public class PlayerChunk { + } + return null; + } ++ ++ public ChunkStatus getChunkHolderStatus() { ++ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) { ++ CompletableFuture> future = this.getStatusFutureUnchecked(curr); ++ Either either = future.getNow(null); ++ if (either == null || !either.left().isPresent()) { ++ continue; ++ } ++ return curr; ++ } ++ return null; ++ } + // Paper end + + public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { +@@ -376,7 +388,7 @@ public class PlayerChunk { + ChunkStatus chunkstatus = getChunkStatus(this.oldTicketLevel); + ChunkStatus chunkstatus1 = getChunkStatus(this.ticketLevel); + boolean flag = this.oldTicketLevel <= PlayerChunkMap.GOLDEN_TICKET; +- boolean flag1 = this.ticketLevel <= PlayerChunkMap.GOLDEN_TICKET; ++ boolean flag1 = this.ticketLevel <= PlayerChunkMap.GOLDEN_TICKET; // Paper - diff on change: (flag1 = new ticket level is in loadable range) + PlayerChunk.State playerchunk_state = getChunkState(this.oldTicketLevel); + PlayerChunk.State playerchunk_state1 = getChunkState(this.ticketLevel); + // CraftBukkit start +@@ -412,6 +424,12 @@ public class PlayerChunk { + } + }); + ++ // Paper start ++ if (!flag1) { ++ playerchunkmap.world.asyncChunkTaskManager.cancelChunkLoad(this.location.x, this.location.z); ++ } ++ // Paper end ++ + for (int i = flag1 ? chunkstatus1.c() + 1 : 0; i <= chunkstatus.c(); ++i) { + completablefuture = (CompletableFuture) this.statusFutures.get(i); + if (completablefuture != null) { +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 5a11765c8a7d754ec86d829fa5e85d2809dd937e..46c91230ab6f12db77b453c312fa7382b76fad34 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -88,6 +88,7 @@ import net.minecraft.world.level.chunk.ProtoChunk; + import net.minecraft.world.level.chunk.ProtoChunkExtension; + import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; + import net.minecraft.world.level.chunk.storage.IChunkLoader; ++import net.minecraft.world.level.chunk.storage.RegionFile; + import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureManager; + import net.minecraft.world.level.storage.Convertable; +@@ -112,7 +113,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + private final LightEngineThreaded lightEngine; + private final IAsyncTaskHandler executor; + public final ChunkGenerator chunkGenerator; +- private final Supplier l; ++ private final Supplier l; public final Supplier getWorldPersistentDataSupplier() { return this.l; } // Paper - OBFHELPER + private final VillagePlace m; + public final LongSet unloadQueue; + private boolean updatingChunksModified; +@@ -122,7 +123,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + public final WorldLoadListener worldLoadListener; + public final PlayerChunkMap.a chunkDistanceManager; + private final AtomicInteger u; +- private final DefinedStructureManager definedStructureManager; ++ public final DefinedStructureManager definedStructureManager; // Paper - private -> public + private final File w; + private final PlayerMap playerMap; + public final Int2ObjectMap trackedEntities; +@@ -205,7 +206,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false)); + this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); + this.l = supplier; +- this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag); ++ this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper + this.setViewDistance(i); + } + +@@ -247,12 +248,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + @Nullable +- protected PlayerChunk getUpdatingChunk(long i) { ++ public PlayerChunk getUpdatingChunk(long i) { // Paper + return (PlayerChunk) this.updatingChunks.get(i); + } + + @Nullable +- protected PlayerChunk getVisibleChunk(long i) { ++ public PlayerChunk getVisibleChunk(long i) { // Paper - protected -> public + return (PlayerChunk) this.visibleChunks.get(i); + } + +@@ -374,6 +375,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + public void close() throws IOException { + try { + this.p.close(); ++ this.world.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line + this.m.close(); + } finally { + super.close(); +@@ -465,7 +467,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.b(() -> { + return true; + }); +- this.i(); ++ this.world.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour ++// this.i(); // Paper - nuke IOWorker + PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName()); + } else { + this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { +@@ -481,16 +484,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + } + +- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot ++ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more + + protected void unloadChunks(BooleanSupplier booleansupplier) { + GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); + ++ try (Timing ignored = this.world.timings.poiUnload.startTiming()) { // Paper + gameprofilerfiller.enter("poi"); + this.m.a(booleansupplier); ++ } // Paper + gameprofilerfiller.exitEnter("chunk_unload"); + if (!this.world.isSavingDisabled()) { ++ try (Timing ignored = this.world.timings.chunkUnload.startTiming()) { // Paper + this.b(booleansupplier); ++ }// Paper + } + + gameprofilerfiller.exit(); +@@ -511,12 +518,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + if (playerchunk != null) { + this.pendingUnload.put(j, playerchunk); + this.updatingChunksModified = true; ++ this.a(j, playerchunk); // Paper - Move up - don't leak chunks + // Spigot start + if (!booleansupplier.getAsBoolean() && this.unloadQueue.size() <= targetSize && activityAccountant.activityTimeIsExhausted()) { + break; + } + // Spigot end +- this.a(j, playerchunk); ++ //this.a(j, playerchunk); // Paper - move up because spigot did a dumb + } + } + activityAccountant.endActivity(); // Spigot +@@ -530,6 +538,60 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + } + ++ // Paper start - async chunk save for unload ++ // Note: This is very unsafe to call if the chunk is still in use. ++ // This is also modeled after PlayerChunkMap#saveChunk(IChunkAccess, boolean), with the intentional difference being ++ // serializing the chunk is left to a worker thread. ++ private void asyncSave(IChunkAccess chunk) { ++ ChunkCoordIntPair chunkPos = chunk.getPos(); ++ NBTTagCompound poiData; ++ try (Timing ignored = this.world.timings.chunkUnloadPOISerialization.startTiming()) { ++ poiData = this.getVillagePlace().getData(chunk.getPos()); ++ } ++ ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkPos.x, chunkPos.z, ++ poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); ++ ++ if (!chunk.isNeedsSaving()) { ++ return; ++ } ++ ++ ChunkStatus chunkstatus = chunk.getChunkStatus(); ++ ++ // Copied from PlayerChunkMap#saveChunk(IChunkAccess, boolean) ++ if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) { ++ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper ++ // Paper start - Optimize save by using status cache ++ try { ++ ChunkStatus statusOnDisk = this.getChunkStatusOnDisk(chunkPos); ++ if (statusOnDisk != null && statusOnDisk.getType() == ChunkStatus.Type.LEVELCHUNK) { ++ // Paper end ++ return; ++ } ++ ++ if (chunkstatus == ChunkStatus.EMPTY && chunk.h().values().stream().noneMatch(StructureStart::e)) { ++ return; ++ } ++ } catch (IOException ex) { ++ ex.printStackTrace(); ++ return; ++ } ++ } ++ } ++ ++ ChunkRegionLoader.AsyncSaveData asyncSaveData; ++ try (Timing ignored = this.world.timings.chunkUnloadPrepareSave.startTiming()) { ++ asyncSaveData = ChunkRegionLoader.getAsyncSaveData(this.world, chunk); ++ } ++ ++ this.world.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY, ++ asyncSaveData, chunk); ++ ++ chunk.setLastSaved(this.world.getTime()); ++ chunk.setNeedsSaving(false); ++ } ++ // Paper end ++ + private void a(long i, PlayerChunk playerchunk) { + CompletableFuture completablefuture = playerchunk.getChunkSave(); + Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error +@@ -543,7 +605,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + ((Chunk) ichunkaccess).setLoaded(false); + } + +- this.saveChunk(ichunkaccess); ++ //this.saveChunk(ichunkaccess);// Paper - delay + if (this.loadedChunks.remove(i) && ichunkaccess instanceof Chunk) { + Chunk chunk = (Chunk) ichunkaccess; + +@@ -551,6 +613,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + this.autoSaveQueue.remove(playerchunk); // Paper + ++ try { ++ this.asyncSave(ichunkaccess); // Paper - async chunk saving ++ } catch (Throwable ex) { ++ LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex); ++ this.saveChunk(ichunkaccess); ++ } ++ + this.lightEngine.a(ichunkaccess.getPos()); + this.lightEngine.queueUpdate(); + this.worldLoadListener.a(ichunkaccess.getPos(), (ChunkStatus) null); +@@ -621,19 +690,23 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + private CompletableFuture> f(ChunkCoordIntPair chunkcoordintpair) { +- return CompletableFuture.supplyAsync(() -> { ++ // Paper start - Async chunk io ++ final java.util.function.BiFunction> syncLoadComplete = (chunkHolder, ioThrowable) -> { + try (Timing ignored = this.world.timings.chunkLoad.startTimingIfSync()) { // Paper + this.world.getMethodProfiler().c("chunkLoad"); +- NBTTagCompound nbttagcompound; // Paper +- try (Timing ignored2 = this.world.timings.chunkIO.startTimingIfSync()) { // Paper start - timings +- nbttagcompound = this.readChunkData(chunkcoordintpair); +- } // Paper end ++ // Paper start ++ if (ioThrowable != null) { ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable); ++ } + +- if (nbttagcompound != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings +- boolean flag = nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8); ++ this.getVillagePlace().loadInData(chunkcoordintpair, chunkHolder.poiData); ++ chunkHolder.tasks.forEach(Runnable::run); ++ // Paper end + +- if (flag) { +- ProtoChunk protochunk = ChunkRegionLoader.loadChunk(this.world, this.definedStructureManager, this.m, chunkcoordintpair, nbttagcompound); ++ if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async ++ ++ if (true) { ++ ProtoChunk protochunk = chunkHolder.protoChunk; + + protochunk.setLastSaved(this.world.getTime()); + this.a(chunkcoordintpair, protochunk.getChunkStatus().getType()); +@@ -657,7 +730,32 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + this.g(chunkcoordintpair); + return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter +- }, this.executor); ++ // Paper start - Async chunk io ++ }; ++ CompletableFuture> ret = new CompletableFuture<>(); ++ ++ Consumer chunkHolderConsumer = (ChunkRegionLoader.InProgressChunkHolder holder) -> { ++ // Go into the chunk load queue and not server task queue so we can be popped out even faster. ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.queueChunkWaitTask(() -> { ++ try { ++ ret.complete(syncLoadComplete.apply(holder, null)); ++ } catch (Exception e) { ++ ret.completeExceptionally(e); ++ } ++ }); ++ }; ++ ++ CompletableFuture chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z); ++ if (chunkSaveFuture != null) { ++ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, ++ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); ++ this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); ++ } else { ++ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, ++ com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); ++ } ++ return ret; ++ // Paper end + } + + private void g(ChunkCoordIntPair chunkcoordintpair) { +@@ -892,6 +990,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + public boolean saveChunk(IChunkAccess ichunkaccess) { ++ try (co.aikar.timings.Timing ignored = this.world.timings.chunkSave.startTiming()) { // Paper + this.m.a(ichunkaccess.getPos()); + if (!ichunkaccess.isNeedsSaving()) { + return false; +@@ -904,6 +1003,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + ChunkStatus chunkstatus = ichunkaccess.getChunkStatus(); + + if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) { ++ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper + if (this.h(chunkcoordintpair)) { + return false; + } +@@ -911,12 +1011,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + if (chunkstatus == ChunkStatus.EMPTY && ichunkaccess.h().values().stream().noneMatch(StructureStart::e)) { + return false; + } ++ } // Paper + } + + this.world.getMethodProfiler().c("chunkSave"); +- NBTTagCompound nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess); ++ NBTTagCompound nbttagcompound; ++ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveDataSerialization.startTiming()) { // Paper ++ nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess); ++ } // Paper ++ + +- this.a(chunkcoordintpair, nbttagcompound); ++ // Paper start - async chunk io ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkcoordintpair.x, chunkcoordintpair.z, ++ null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); ++ // Paper end - async chunk io + this.a(chunkcoordintpair, chunkstatus.getType()); + return true; + } catch (Exception exception) { +@@ -925,6 +1033,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return false; + } + } ++ } // Paper + } + + private boolean h(ChunkCoordIntPair chunkcoordintpair) { +@@ -1054,6 +1163,35 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + } + ++ // Paper start - Asynchronous chunk io ++ @Nullable ++ @Override ++ public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { ++ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { ++ NBTTagCompound ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), ++ false, true, true).join().chunkData; ++ ++ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { ++ throw new IOException("See logs for further detail"); ++ } ++ return ret; ++ } ++ return super.read(chunkcoordintpair); ++ } ++ ++ @Override ++ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { ++ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( ++ this.world, chunkcoordintpair.x, chunkcoordintpair.z, null, nbttagcompound, ++ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); ++ return; ++ } ++ super.write(chunkcoordintpair, nbttagcompound); ++ } ++ // Paper end ++ + @Nullable + public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public + NBTTagCompound nbttagcompound = this.read(chunkcoordintpair); +@@ -1075,33 +1213,55 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + // Paper start - chunk status cache "api" + public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) { +- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); ++ synchronized (this) { // Paper ++ RegionFile regionFile = this.regionFileCache.getRegionFileIfLoaded(chunkPos); + + return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ } // Paper + } + + public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException { +- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); ++ // Paper start - async chunk save for unload ++ IChunkAccess unloadingChunk = this.world.asyncChunkTaskManager.getChunkInSaveProgress(chunkPos.x, chunkPos.z); ++ if (unloadingChunk != null) { ++ return unloadingChunk.getChunkStatus(); ++ } ++ // Paper end ++ // Paper start - async io ++ NBTTagCompound inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .getPendingWrite(this.world, chunkPos.x, chunkPos.z, false); + +- if (regionFile == null || !regionFile.chunkExists(chunkPos)) { +- return null; ++ if (inProgressWrite != null) { ++ return ChunkRegionLoader.getStatus(inProgressWrite); + } ++ // Paper end ++ synchronized (this) { // Paper - async io ++ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, true); ++ ++ if (regionFile == null || !regionFile.chunkExists(chunkPos)) { ++ return null; ++ } + +- ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); + +- if (status != null) { +- return status; ++ if (status != null) { ++ return status; ++ } ++ // Paper start - async io + } + +- this.readChunkData(chunkPos); ++ NBTTagCompound compound = this.readChunkData(chunkPos); + +- return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ return ChunkRegionLoader.getStatus(compound); ++ // Paper end + } + + public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException { +- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); ++ synchronized (this) { ++ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, false); + +- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); ++ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); ++ } + } + + public IChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { +@@ -1110,6 +1270,39 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + // Paper end + ++ ++ // Paper start - async io ++ // this function will not load chunk data off disk to check for status ++ // ret null for unknown, empty for empty status on disk or absent from disk ++ public ChunkStatus getStatusOnDiskNoLoad(int x, int z) { ++ // Paper start - async chunk save for unload ++ IChunkAccess unloadingChunk = this.world.asyncChunkTaskManager.getChunkInSaveProgress(x, z); ++ if (unloadingChunk != null) { ++ return unloadingChunk.getChunkStatus(); ++ } ++ // Paper end ++ // Paper start - async io ++ NBTTagCompound inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .getPendingWrite(this.world, x, z, false); ++ ++ if (inProgressWrite != null) { ++ return ChunkRegionLoader.getStatus(inProgressWrite); ++ } ++ // Paper end ++ // variant of PlayerChunkMap#getChunkStatusOnDisk that does not load data off disk, but loads the region file ++ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); ++ synchronized (world.getChunkProvider().playerChunkMap) { ++ RegionFile file; ++ try { ++ file = world.getChunkProvider().playerChunkMap.regionFileCache.getFile(chunkPos, false); ++ } catch (IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return !file.chunkExists(chunkPos) ? ChunkStatus.EMPTY : file.getStatusIfCached(x, z); ++ } ++ } ++ + boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair) { + // Spigot start + return isOutsideOfRange(chunkcoordintpair, false); +@@ -1456,6 +1649,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + } + ++ public VillagePlace getVillagePlace() { return this.h(); } // Paper - OBFHELPER + protected VillagePlace h() { + return this.m; + } +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index 285a03b57431bd6a4d26bb84e916d2c6e1eb0213..218dc900e125a11548485887b1918742072c7a77 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -26,6 +26,7 @@ public class TicketType { + public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit + public static final TicketType PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + public static final TicketType FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper ++ public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper + + public static TicketType a(String s, Comparator comparator) { + return new TicketType<>(s, comparator, 0L); +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 3eb337d42f0292ed7b85a5fdbf6b450bc446b81a..52d22da115212eae6c380bb5012398e3df92f5f3 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -51,6 +51,7 @@ import net.minecraft.core.IRegistry; + import net.minecraft.core.IRegistryCustom; + import net.minecraft.core.SectionPosition; + import net.minecraft.core.particles.ParticleParam; ++import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.network.protocol.Packet; +@@ -126,6 +127,7 @@ import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.ChunkSection; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.IChunkAccess; ++import net.minecraft.world.level.chunk.storage.RegionFile; + import net.minecraft.world.level.dimension.DimensionManager; + import net.minecraft.world.level.dimension.end.EnderDragonBattle; + import net.minecraft.world.level.levelgen.HeightMap; +@@ -208,6 +210,79 @@ public class WorldServer extends World implements GeneratorAccessSeed { + return this.chunkProvider.getChunkAt(x, z, false); + } + ++ // Paper start - Asynchronous IO ++ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController poiDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { ++ @Override ++ public void writeData(int x, int z, NBTTagCompound compound) throws java.io.IOException { ++ WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().write(new ChunkCoordIntPair(x, z), compound); ++ } ++ ++ @Override ++ public NBTTagCompound readData(int x, int z) throws java.io.IOException { ++ return WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().read(new ChunkCoordIntPair(x, z)); ++ } ++ ++ @Override ++ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace()) { ++ RegionFile file; ++ ++ try { ++ file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getFile(new ChunkCoordIntPair(chunkX, chunkZ), false); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return function.apply(file); ++ } ++ } ++ ++ @Override ++ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace()) { ++ RegionFile file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getRegionFileIfLoaded(new ChunkCoordIntPair(chunkX, chunkZ)); ++ return function.apply(file); ++ } ++ } ++ }; ++ ++ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController chunkDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { ++ @Override ++ public void writeData(int x, int z, NBTTagCompound compound) throws java.io.IOException { ++ WorldServer.this.getChunkProvider().playerChunkMap.write(new ChunkCoordIntPair(x, z), compound); ++ } ++ ++ @Override ++ public NBTTagCompound readData(int x, int z) throws java.io.IOException { ++ return WorldServer.this.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)); ++ } ++ ++ @Override ++ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (WorldServer.this.getChunkProvider().playerChunkMap) { ++ RegionFile file; ++ ++ try { ++ file = WorldServer.this.getChunkProvider().playerChunkMap.regionFileCache.getFile(new ChunkCoordIntPair(chunkX, chunkZ), false); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return function.apply(file); ++ } ++ } ++ ++ @Override ++ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (WorldServer.this.getChunkProvider().playerChunkMap) { ++ RegionFile file = WorldServer.this.getChunkProvider().playerChunkMap.regionFileCache.getRegionFileIfLoaded(new ChunkCoordIntPair(chunkX, chunkZ)); ++ return function.apply(file); ++ } ++ } ++ }; ++ public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; ++ // Paper end ++ + // Add env and gen to constructor, WorldData -> WorldDataServer + public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor +@@ -255,6 +330,8 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.dragonBattle = null; + } + this.getServer().addWorld(this.getWorld()); // CraftBukkit ++ ++ this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper + } + + // CraftBukkit start +@@ -1743,7 +1820,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + MCUtil.getSpiralOutChunks(spawn, radiusInBlocks >> 4).forEach(pair -> { +- getChunkProvider().getChunkAtMainThread(pair.x, pair.z); ++ getChunkProvider().getChunkAtAsynchronously(pair.x, pair.z, true, false).exceptionally((ex) -> { ++ ex.printStackTrace(); ++ return null; ++ }); + }); + } + public void removeTicketsForSpawn(int radiusInBlocks, BlockPosition spawn) { +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index c3a3837badb4b2a2ab51e6fb2d7cfbaa2f4d8edb..d74d6abfff647c148e524905cd733c4b7fc6591f 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -730,6 +730,13 @@ public class PlayerConnection implements PacketListenerPlayIn { + minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper + return; + } ++ // Paper start ++ String str = packetplayintabcomplete.c(); int index = -1; ++ if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { ++ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper ++ return; ++ } ++ // Paper end + // CraftBukkit end + StringReader stringreader = new StringReader(packetplayintabcomplete.c()); + +diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java +index e5641f2b41d89a57285fc072a48b951aa03a14a7..ca23ca14d8011fc8daa7e20f2eaa550a8ff92c53 100644 +--- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java ++++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java +@@ -91,7 +91,7 @@ public abstract class IAsyncTaskHandler implements Mailbox public + while (this.executeNext()) { + ; + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java +index aa1d948e6aebef25f0f4c4c07f5131d2e8387e59..04b01cb841dc4f34ded5aaa4ea7a8e6d4b470183 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java +@@ -22,7 +22,9 @@ import java.util.stream.Stream; + import net.minecraft.SystemUtils; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.SectionPosition; ++import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.server.level.LightEngineGraphSection; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.IWorldReader; +@@ -36,8 +38,16 @@ public class VillagePlace extends RegionFileSection { + private final VillagePlace.a a = new VillagePlace.a(); + private final LongSet b = new LongOpenHashSet(); + ++ private final WorldServer world; // Paper ++ + public VillagePlace(File file, DataFixer datafixer, boolean flag) { ++ // Paper start - add world parameter ++ this(file, datafixer, flag, null); ++ } ++ public VillagePlace(File file, DataFixer datafixer, boolean flag, WorldServer world) { + super(file, VillagePlaceSection::a, VillagePlaceSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); ++ this.world = world; ++ // Paper end - add world parameter + } + + public void a(BlockPosition blockposition, VillagePlaceType villageplacetype) { +@@ -155,7 +165,23 @@ public class VillagePlace extends RegionFileSection { + + @Override + public void a(BooleanSupplier booleansupplier) { +- super.a(booleansupplier); ++ // Paper start - async chunk io ++ if (this.world == null) { ++ super.a(booleansupplier); ++ } else { ++ //super.a(booleansupplier); // re-implement below ++ while (!((RegionFileSection)this).d.isEmpty() && booleansupplier.getAsBoolean()) { ++ ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(((RegionFileSection)this).d.firstLong()).r(); ++ ++ NBTTagCompound data; ++ try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) { ++ data = this.getData(chunkcoordintpair); ++ } ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, ++ chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); ++ } ++ } ++ // Paper end + this.a.a(); + } + +@@ -255,6 +281,35 @@ public class VillagePlace extends RegionFileSection { + } + } + ++ // Paper start - Asynchronous chunk io ++ @javax.annotation.Nullable ++ @Override ++ public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws java.io.IOException { ++ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { ++ NBTTagCompound ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), ++ true, false, true).join().poiData; ++ ++ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { ++ throw new java.io.IOException("See logs for further detail"); ++ } ++ return ret; ++ } ++ return super.read(chunkcoordintpair); ++ } ++ ++ @Override ++ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws java.io.IOException { ++ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( ++ this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, ++ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); ++ return; ++ } ++ super.write(chunkcoordintpair, nbttagcompound); ++ } ++ // Paper end ++ + public static enum Occupancy { + + HAS_SPACE(VillagePlaceRecord::d), IS_OCCUPIED(VillagePlaceRecord::e), ANY((villageplacerecord) -> { +diff --git a/src/main/java/net/minecraft/world/level/NextTickListEntry.java b/src/main/java/net/minecraft/world/level/NextTickListEntry.java +index f3bcb96232d18abbcd86b079a7c5830bb30d75d2..37b7dd82a227a88b720c13a813dd7e8caf803e03 100644 +--- a/src/main/java/net/minecraft/world/level/NextTickListEntry.java ++++ b/src/main/java/net/minecraft/world/level/NextTickListEntry.java +@@ -5,7 +5,7 @@ import net.minecraft.core.BlockPosition; + + public class NextTickListEntry { + +- private static long d; ++ private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading + private final T e; + public final BlockPosition a; + public final long b; +@@ -17,7 +17,7 @@ public class NextTickListEntry { + } + + public NextTickListEntry(BlockPosition blockposition, T t0, long i, TickListPriority ticklistpriority) { +- this.f = (long) (NextTickListEntry.d++); ++ this.f = (long) (NextTickListEntry.COUNTER.getAndIncrement()); // Paper - async chunk loading + this.a = blockposition.immutableCopy(); + this.e = t0; + this.b = i; +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +index 711308cf84a816f09d116a7414f9cbee803c8713..f094ddf6b4d155f3c7a08a3b811c98b0862fd098 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +@@ -170,6 +170,7 @@ public class ChunkStatus { + return ChunkStatus.q.size(); + } + ++ public static int getTicketLevelOffset(ChunkStatus status) { return ChunkStatus.a(status); } // Paper - OBFHELPER + public static int a(ChunkStatus chunkstatus) { + return ChunkStatus.r.getInt(chunkstatus.c()); + } +@@ -185,6 +186,7 @@ public class ChunkStatus { + this.t = chunkstatus == null ? 0 : chunkstatus.c() + 1; + } + ++ public final int getStatusIndex() { return c(); } // Paper - OBFHELPER + public int c() { + return this.t; + } +@@ -193,7 +195,7 @@ public class ChunkStatus { + return this.s; + } + +- public ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER ++ public final ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER + public ChunkStatus e() { + return this.u; + } +@@ -206,6 +208,7 @@ public class ChunkStatus { + return this.w.doWork(this, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess); + } + ++ public final int getNeighborRadius() { return this.f(); } // Paper - OBFHELPER + public int f() { + return this.x; + } +@@ -233,6 +236,7 @@ public class ChunkStatus { + return this.z; + } + ++ public final boolean isAtLeastStatus(ChunkStatus chunkstatus) { return b(chunkstatus); } // Paper - OBFHELPER + public boolean b(ChunkStatus chunkstatus) { + return this.c() >= chunkstatus.c(); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java +index a2518fdadd1d7239e8614f498a5223144f1c2a36..86b4db483787c5fd10461f7d7e90a772ee049599 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java ++++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java +@@ -73,6 +73,7 @@ public class NibbleArray { + return this.a; + } + ++ public NibbleArray copy() { return this.b(); } // Paper - OBFHELPER + public NibbleArray b() { + return this.a == null ? new NibbleArray() : new NibbleArray((byte[]) this.a.clone()); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index c652897aae99c48c6cc020b5d64f6a8b02beecb5..c95fcdf47db8bfe59a83c0d28f4744b4d8540ef8 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet; + import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.shorts.ShortList; + import it.unimi.dsi.fastutil.shorts.ShortListIterator; ++import java.util.ArrayDeque; // Paper + import java.util.Arrays; + import java.util.BitSet; + import java.util.EnumSet; +@@ -66,7 +67,29 @@ public class ChunkRegionLoader { + + private static final Logger LOGGER = LogManager.getLogger(); + ++ // Paper start ++ public static final class InProgressChunkHolder { ++ ++ public final ProtoChunk protoChunk; ++ public final ArrayDeque tasks; ++ ++ public NBTTagCompound poiData; ++ ++ public InProgressChunkHolder(final ProtoChunk protoChunk, final ArrayDeque tasks) { ++ this.protoChunk = protoChunk; ++ this.tasks = tasks; ++ } ++ } ++ + public static ProtoChunk loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { ++ InProgressChunkHolder holder = loadChunk(worldserver, definedstructuremanager, villageplace, chunkcoordintpair, nbttagcompound, true); ++ holder.tasks.forEach(Runnable::run); ++ return holder.protoChunk; ++ } ++ ++ public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) { ++ ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); ++ // Paper end + ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); + WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); + NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); +@@ -93,7 +116,9 @@ public class ChunkRegionLoader { + LightEngine lightengine = chunkproviderserver.getLightEngine(); + + if (flag) { +- lightengine.b(chunkcoordintpair, true); ++ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main ++ lightengine.b(chunkcoordintpair, true); ++ }); // Paper - delay this task since we're executing off-main + } + + for (int i = 0; i < nbttaglist.size(); ++i) { +@@ -109,16 +134,28 @@ public class ChunkRegionLoader { + achunksection[b0] = chunksection; + } + +- villageplace.a(chunkcoordintpair, chunksection); ++ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main ++ villageplace.a(chunkcoordintpair, chunksection); ++ }); // Paper - delay this task since we're executing off-main + } + + if (flag) { + if (nbttagcompound2.hasKeyOfType("BlockLight", 7)) { +- lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), new NibbleArray(nbttagcompound2.getByteArray("BlockLight")), true); ++ // Paper start - delay this task since we're executing off-main ++ NibbleArray blockLight = new NibbleArray(nbttagcompound2.getByteArray("BlockLight")); ++ tasksToExecuteOnMain.add(() -> { ++ lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), blockLight, true); ++ }); ++ // Paper end - delay this task since we're executing off-main + } + + if (flag2 && nbttagcompound2.hasKeyOfType("SkyLight", 7)) { +- lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), new NibbleArray(nbttagcompound2.getByteArray("SkyLight")), true); ++ // Paper start - delay this task since we're executing off-main ++ NibbleArray skyLight = new NibbleArray(nbttagcompound2.getByteArray("SkyLight")); ++ tasksToExecuteOnMain.add(() -> { ++ lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), skyLight, true); ++ }); ++ // Paper end - delay this task since we're executing off-main + } + } + } +@@ -227,7 +264,7 @@ public class ChunkRegionLoader { + } + + if (chunkstatus_type == ChunkStatus.Type.LEVELCHUNK) { +- return new ProtoChunkExtension((Chunk) object); ++ return new InProgressChunkHolder(new ProtoChunkExtension((Chunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading + } else { + ProtoChunk protochunk1 = (ProtoChunk) object; + +@@ -266,11 +303,83 @@ public class ChunkRegionLoader { + protochunk1.a(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1))); + } + +- return protochunk1; ++ return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading ++ } ++ } ++ ++ // Paper start - async chunk save for unload ++ public static final class AsyncSaveData { ++ public final NibbleArray[] blockLight; // null or size of 17 (for indices -1 through 15) ++ public final NibbleArray[] skyLight; ++ ++ public final NBTTagList blockTickList; // non-null if we had to go to the server's tick list ++ public final NBTTagList fluidTickList; // non-null if we had to go to the server's tick list ++ ++ public final long worldTime; ++ ++ public AsyncSaveData(NibbleArray[] blockLight, NibbleArray[] skyLight, NBTTagList blockTickList, NBTTagList fluidTickList, ++ long worldTime) { ++ this.blockLight = blockLight; ++ this.skyLight = skyLight; ++ this.blockTickList = blockTickList; ++ this.fluidTickList = fluidTickList; ++ this.worldTime = worldTime; + } + } + ++ // must be called sync ++ public static AsyncSaveData getAsyncSaveData(WorldServer world, IChunkAccess chunk) { ++ org.spigotmc.AsyncCatcher.catchOp("preparation of chunk data for async save"); ++ ChunkCoordIntPair chunkPos = chunk.getPos(); ++ ++ LightEngineThreaded lightenginethreaded = world.getChunkProvider().getLightEngine(); ++ ++ NibbleArray[] blockLight = new NibbleArray[17 - (-1)]; ++ NibbleArray[] skyLight = new NibbleArray[17 - (-1)]; ++ ++ for (int i = -1; i < 17; ++i) { ++ NibbleArray blockArray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkPos, i)); ++ NibbleArray skyArray = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkPos, i)); ++ ++ // copy data for safety ++ if (blockArray != null) { ++ blockArray = blockArray.copy(); ++ } ++ if (skyArray != null) { ++ skyArray = skyArray.copy(); ++ } ++ ++ // apply offset of 1 for -1 starting index ++ blockLight[i + 1] = blockArray; ++ skyLight[i + 1] = skyArray; ++ } ++ ++ TickList blockTickList = chunk.n(); ++ ++ NBTTagList blockTickListSerialized; ++ if (blockTickList instanceof ProtoChunkTickList || blockTickList instanceof TickListChunk) { ++ blockTickListSerialized = null; ++ } else { ++ blockTickListSerialized = world.getBlockTickList().a(chunkPos); ++ } ++ ++ TickList fluidTickList = chunk.o(); ++ ++ NBTTagList fluidTickListSerialized; ++ if (fluidTickList instanceof ProtoChunkTickList || fluidTickList instanceof TickListChunk) { ++ fluidTickListSerialized = null; ++ } else { ++ fluidTickListSerialized = world.getFluidTickList().a(chunkPos); ++ } ++ ++ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, world.getTime()); ++ } ++ + public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess) { ++ return saveChunk(worldserver, ichunkaccess, null); ++ } ++ public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { ++ // Paper end + ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); + NBTTagCompound nbttagcompound = new NBTTagCompound(); + NBTTagCompound nbttagcompound1 = new NBTTagCompound(); +@@ -279,7 +388,7 @@ public class ChunkRegionLoader { + nbttagcompound.set("Level", nbttagcompound1); + nbttagcompound1.setInt("xPos", chunkcoordintpair.x); + nbttagcompound1.setInt("zPos", chunkcoordintpair.z); +- nbttagcompound1.setLong("LastUpdate", worldserver.getTime()); ++ nbttagcompound1.setLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getTime()); // Paper - async chunk unloading + nbttagcompound1.setLong("InhabitedTime", ichunkaccess.getInhabitedTime()); + nbttagcompound1.setString("Status", ichunkaccess.getChunkStatus().d()); + ChunkConverter chunkconverter = ichunkaccess.p(); +@@ -295,14 +404,22 @@ public class ChunkRegionLoader { + + NBTTagCompound nbttagcompound2; + +- for (int i = -1; i < 17; ++i) { ++ for (int i = -1; i < 17; ++i) { // Paper - conflict on loop parameter change + int finalI = i; // CraftBukkit - decompile errors + ChunkSection chunksection = (ChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { + return chunksection1 != null && chunksection1.getYPosition() >> 4 == finalI; // CraftBukkit - decompile errors + }).findFirst().orElse(Chunk.a); +- NibbleArray nibblearray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, i)); +- NibbleArray nibblearray1 = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, i)); +- ++ // Paper start - async chunk save for unload ++ NibbleArray nibblearray; // block light ++ NibbleArray nibblearray1; // sky light ++ if (asyncsavedata == null) { ++ nibblearray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, i)); /// Paper - diff on method change (see getAsyncSaveData) ++ nibblearray1 = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, i)); // Paper - diff on method change (see getAsyncSaveData) ++ } else { ++ nibblearray = asyncsavedata.blockLight[i + 1]; // +1 to offset the -1 starting index ++ nibblearray1 = asyncsavedata.skyLight[i + 1]; // +1 to offset the -1 starting index ++ } ++ // Paper end + if (chunksection != Chunk.a || nibblearray != null || nibblearray1 != null) { + nbttagcompound2 = new NBTTagCompound(); + nbttagcompound2.setByte("Y", (byte) (i & 255)); +@@ -369,7 +486,7 @@ public class ChunkRegionLoader { + Entity entity = (Entity) iterator1.next(); + NBTTagCompound nbttagcompound4 = new NBTTagCompound(); + // Paper start +- if ((int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { ++ if (asyncsavedata == null && !entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { + toUpdate.add(entity); + continue; + } +@@ -412,24 +529,32 @@ public class ChunkRegionLoader { + } + + nbttagcompound1.set("Entities", nbttaglist2); +- TickList ticklist = ichunkaccess.n(); ++ TickList ticklist = ichunkaccess.n(); // Paper - diff on method change (see getAsyncSaveData) + + if (ticklist instanceof ProtoChunkTickList) { + nbttagcompound1.set("ToBeTicked", ((ProtoChunkTickList) ticklist).b()); + } else if (ticklist instanceof TickListChunk) { + nbttagcompound1.set("TileTicks", ((TickListChunk) ticklist).b()); ++ // Paper start - async chunk save for unload ++ } else if (asyncsavedata != null) { ++ nbttagcompound1.set("TileTicks", asyncsavedata.blockTickList); ++ // Paper end + } else { +- nbttagcompound1.set("TileTicks", worldserver.getBlockTickList().a(chunkcoordintpair)); ++ nbttagcompound1.set("TileTicks", worldserver.getBlockTickList().a(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) + } + +- TickList ticklist1 = ichunkaccess.o(); ++ TickList ticklist1 = ichunkaccess.o(); // Paper - diff on method change (see getAsyncSaveData) + + if (ticklist1 instanceof ProtoChunkTickList) { + nbttagcompound1.set("LiquidsToBeTicked", ((ProtoChunkTickList) ticklist1).b()); + } else if (ticklist1 instanceof TickListChunk) { + nbttagcompound1.set("LiquidTicks", ((TickListChunk) ticklist1).b()); ++ // Paper start - async chunk save for unload ++ } else if (asyncsavedata != null) { ++ nbttagcompound1.set("LiquidTicks", asyncsavedata.fluidTickList); ++ // Paper end + } else { +- nbttagcompound1.set("LiquidTicks", worldserver.getFluidTickList().a(chunkcoordintpair)); ++ nbttagcompound1.set("LiquidTicks", worldserver.getFluidTickList().a(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) + } + + nbttagcompound1.set("PostProcessing", a(ichunkaccess.l())); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java +index d785f44cd503d4d91589f3fc4bc8dc805dff3d41..01ae13385dd0208c9f34da8b3897b571f86305d0 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java +@@ -3,6 +3,10 @@ package net.minecraft.world.level.chunk.storage; + import com.mojang.datafixers.DataFixer; + import java.io.File; + import java.io.IOException; ++// Paper start ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.CompletionException; ++// Paper end + import java.util.function.Supplier; + import javax.annotation.Nullable; + import net.minecraft.SharedConstants; +@@ -25,32 +29,41 @@ import net.minecraft.world.level.dimension.DimensionManager; + + public class IChunkLoader implements AutoCloseable { + +- private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER ++ // Paper - OBFHELPER - nuke IOWorker + protected final DataFixer b; + @Nullable +- private PersistentStructureLegacy c; ++ private volatile PersistentStructureLegacy c; // Paper - async chunk loading ++ ++ private final Object persistentDataLock = new Object(); // Paper ++ public final RegionFileCache regionFileCache; + + public IChunkLoader(File file, DataFixer datafixer, boolean flag) { ++ this.regionFileCache = new RegionFileCache(file, flag); // Paper - nuke IOWorker + this.b = datafixer; +- this.a = new IOWorker(file, flag, "chunk"); ++ // Paper - nuke IOWorker + } + + // CraftBukkit start + private boolean check(ChunkProviderServer cps, int x, int z) throws IOException { + ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z); + if (cps != null) { +- com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); +- if (cps.isLoaded(x, z)) { ++ //com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe ++ if (cps.getChunkAtIfCachedImmediately(x, z) != null) { // Paper - isLoaded is a ticket level check, not a chunk loaded check! + return true; + } + } + +- NBTTagCompound nbt = read(pos); +- if (nbt != null) { +- NBTTagCompound level = nbt.getCompound("Level"); +- if (level.getBoolean("TerrainPopulated")) { +- return true; +- } ++ ++ // Paper start - prioritize ++ NBTTagCompound nbt = cps == null ? read(pos) : ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.loadChunkData((WorldServer)cps.getWorld(), x, z, ++ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHER_PRIORITY, false, true).chunkData; ++ // Paper end ++ if (nbt != null) { ++ NBTTagCompound level = nbt.getCompound("Level"); ++ if (level.getBoolean("TerrainPopulated")) { ++ return true; ++ } + + ChunkStatus status = ChunkStatus.a(level.getString("Status")); + if (status != null && status.b(ChunkStatus.FEATURES)) { +@@ -81,11 +94,13 @@ public class IChunkLoader implements AutoCloseable { + if (i < 1493) { + nbttagcompound = GameProfileSerializer.a(this.b, DataFixTypes.CHUNK, nbttagcompound, i, 1493); + if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { ++ synchronized (this.persistentDataLock) { // Paper - Async chunk loading + if (this.c == null) { + this.c = PersistentStructureLegacy.a(resourcekey, (WorldPersistentData) supplier.get()); + } + + nbttagcompound = this.c.a(nbttagcompound); ++ } // Paper - Async chunk loading + } + } + +@@ -103,22 +118,20 @@ public class IChunkLoader implements AutoCloseable { + + @Nullable + public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { +- return this.a.a(chunkcoordintpair); ++ return this.regionFileCache.read(chunkcoordintpair); + } + +- public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { +- this.a.a(chunkcoordintpair, nbttagcompound); ++ public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER ++ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) ++ this.regionFileCache.write(chunkcoordintpair, nbttagcompound); + if (this.c != null) { ++ synchronized (this.persistentDataLock) { // Paper - Async chunk loading + this.c.a(chunkcoordintpair.pair()); ++ } // Paper - Async chunk loading} + } +- +- } +- +- public void i() { +- this.a.a().join(); + } + + public void close() throws IOException { +- this.a.close(); ++ this.regionFileCache.close(); + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +index d50b9c9d030016f951e2ed7fb519250b7408c833..1b0535ba211904b2384cc80c02c21ed1a606e752 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -45,6 +45,8 @@ public class RegionFile implements AutoCloseable { + protected final RegionFileBitSet freeSectors; + public final File file; // Paper + ++ public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper ++ + // Paper start - Cache chunk status + private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; + +@@ -251,7 +253,7 @@ public class RegionFile implements AutoCloseable { + return (i + 4096 - 1) / 4096; + } + +- public boolean b(ChunkCoordIntPair chunkcoordintpair) { ++ public synchronized boolean b(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronized + int i = this.getOffset(chunkcoordintpair); + + if (i == 0) { +@@ -411,6 +413,11 @@ public class RegionFile implements AutoCloseable { + } + + public void close() throws IOException { ++ // Paper start - Prevent regionfiles from being closed during use ++ this.fileLock.lock(); ++ synchronized (this) { ++ try { ++ // Paper end + this.closed = true; // Paper + try { + this.d(); +@@ -421,6 +428,10 @@ public class RegionFile implements AutoCloseable { + this.dataFile.close(); + } + } ++ } finally { // Paper start - Prevent regionfiles from being closed during use ++ this.fileLock.unlock(); ++ } ++ } // Paper end + + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +index 55e7e983d2c760a8052d7b3ddbdc8447f619a60f..ebb0d6988f87013ea5d523ab4a1b31cb669ccc43 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +@@ -17,7 +17,7 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.util.ExceptionSuppressor; + import net.minecraft.world.level.ChunkCoordIntPair; + +-public final class RegionFileCache implements AutoCloseable { ++public class RegionFileCache implements AutoCloseable { // Paper - no final + + public final Long2ObjectLinkedOpenHashMap cache = new Long2ObjectLinkedOpenHashMap(); + private final File b; +@@ -30,16 +30,27 @@ public final class RegionFileCache implements AutoCloseable { + + + // Paper start +- public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { ++ public synchronized RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronize for async io + return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); + } + + // Paper end +- public RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public ++ public synchronized RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public, synchronize ++ // Paper start - add lock parameter ++ return this.getFile(chunkcoordintpair, existingOnly, false); ++ } ++ public synchronized RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly, boolean lock) throws IOException { ++ // Paper end + long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); + RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i); + + if (regionfile != null) { ++ // Paper start ++ if (lock) { ++ // must be in this synchronized block ++ regionfile.fileLock.lock(); ++ } ++ // Paper end + return regionfile; + } else { + if (this.cache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable +@@ -55,6 +66,12 @@ public final class RegionFileCache implements AutoCloseable { + RegionFile regionfile1 = new RegionFile(file, this.b, this.c); + + this.cache.putAndMoveToFirst(i, regionfile1); ++ // Paper start ++ if (lock) { ++ // must be in this synchronized block ++ regionfile1.fileLock.lock(); ++ } ++ // Paper end + return regionfile1; + } + } +@@ -130,11 +147,12 @@ public final class RegionFileCache implements AutoCloseable { + @Nullable + public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { + // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing +- RegionFile regionfile = this.getFile(chunkcoordintpair, true); ++ RegionFile regionfile = this.getFile(chunkcoordintpair, true, true); // Paper + if (regionfile == null) { + return null; + } + // CraftBukkit end ++ try { // Paper + DataInputStream datainputstream = regionfile.a(chunkcoordintpair); + // Paper start + if (regionfile.isOversized(chunkcoordintpair.x, chunkcoordintpair.z)) { +@@ -172,10 +190,14 @@ public final class RegionFileCache implements AutoCloseable { + } + + return nbttagcompound; ++ } finally { // Paper start ++ regionfile.fileLock.unlock(); ++ } // Paper end + } + + protected void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { +- RegionFile regionfile = this.getFile(chunkcoordintpair, false); // CraftBukkit ++ RegionFile regionfile = this.getFile(chunkcoordintpair, false, true); // CraftBukkit // Paper ++ try { // Paper + int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper + DataOutputStream dataoutputstream = regionfile.c(chunkcoordintpair); + Throwable throwable = null; +@@ -214,9 +236,12 @@ public final class RegionFileCache implements AutoCloseable { + MinecraftServer.LOGGER.error("Failed to save chunk", laste); + } + // Paper end ++ } finally { // Paper start ++ regionfile.fileLock.unlock(); ++ } // Paper end + } + +- public void close() throws IOException { ++ public synchronized void close() throws IOException { // Paper -> synchronized + ExceptionSuppressor exceptionsuppressor = new ExceptionSuppressor<>(); + ObjectIterator objectiterator = this.cache.values().iterator(); + +@@ -243,4 +268,12 @@ public final class RegionFileCache implements AutoCloseable { + } + + } ++ ++ // CraftBukkit start ++ public synchronized boolean chunkExists(ChunkCoordIntPair pos) throws IOException { // Paper - synchronize ++ RegionFile regionfile = getFile(pos, true); ++ ++ return regionfile != null ? regionfile.chunkExists(pos) : false; ++ } ++ // CraftBukkit end + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java +index 8ad97a8a2189553da88810380b1c240079eacc93..d3b9a9e4695655860c72db5f2188472681e8d37a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java +@@ -30,28 +30,29 @@ import net.minecraft.world.level.World; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +-public class RegionFileSection implements AutoCloseable { ++public class RegionFileSection extends RegionFileCache implements AutoCloseable { // Paper - nuke IOWorker + + private static final Logger LOGGER = LogManager.getLogger(); +- private final IOWorker b; ++ // Paper - nuke IOWorker + private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); +- private final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); ++ public final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> public + private final Function> e; + private final Function f; + private final DataFixer g; + private final DataFixTypes h; + + public RegionFileSection(File file, Function> function, Function function1, DataFixer datafixer, DataFixTypes datafixtypes, boolean flag) { ++ super(file, flag); // Paper - nuke IOWorker + this.e = function; + this.f = function1; + this.g = datafixer; + this.h = datafixtypes; +- this.b = new IOWorker(file, flag, file.getName()); ++ //this.b = new IOWorker(file, flag, file.getName()); // Paper - nuke IOWorker + } + + protected void a(BooleanSupplier booleansupplier) { + while (!this.d.isEmpty() && booleansupplier.getAsBoolean()) { +- ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).r(); ++ ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).r(); // Paper - conflict here to avoid obfhelpers + + this.d(chunkcoordintpair); + } +@@ -105,13 +106,18 @@ public class RegionFileSection implements AutoCloseable { + } + + private void b(ChunkCoordIntPair chunkcoordintpair) { +- this.a(chunkcoordintpair, DynamicOpsNBT.a, this.c(chunkcoordintpair)); ++ // Paper start - load data in function ++ this.loadInData(chunkcoordintpair, this.c(chunkcoordintpair)); ++ } ++ public void loadInData(ChunkCoordIntPair chunkPos, NBTTagCompound compound) { ++ this.a(chunkPos, DynamicOpsNBT.a, compound); ++ // Paper end + } + + @Nullable + private NBTTagCompound c(ChunkCoordIntPair chunkcoordintpair) { + try { +- return this.b.a(chunkcoordintpair); ++ return this.read(chunkcoordintpair); // Paper - nuke IOWorker + } catch (IOException ioexception) { + RegionFileSection.LOGGER.error("Error reading chunk {} data from disk", chunkcoordintpair, ioexception); + return null; +@@ -157,17 +163,31 @@ public class RegionFileSection implements AutoCloseable { + } + + private void d(ChunkCoordIntPair chunkcoordintpair) { +- Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); ++ Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); // Paper - conflict here to avoid adding obfhelpers :) + NBTBase nbtbase = (NBTBase) dynamic.getValue(); + + if (nbtbase instanceof NBTTagCompound) { +- this.b.a(chunkcoordintpair, (NBTTagCompound) nbtbase); ++ try { this.write(chunkcoordintpair, (NBTTagCompound) nbtbase); } catch (IOException ioexception) { RegionFileSection.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker // TODO make this write async + } else { + RegionFileSection.LOGGER.error("Expected compound tag, got {}", nbtbase); + } + + } + ++ // Paper start - internal get data function, copied from above ++ private NBTTagCompound getDataInternal(ChunkCoordIntPair chunkcoordintpair) { ++ Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); ++ NBTBase nbtbase = (NBTBase) dynamic.getValue(); ++ ++ if (nbtbase instanceof NBTTagCompound) { ++ return (NBTTagCompound)nbtbase; ++ } else { ++ RegionFileSection.LOGGER.error("Expected compound tag, got {}", nbtbase); ++ } ++ return null; ++ } ++ // Paper end ++ + private Dynamic a(ChunkCoordIntPair chunkcoordintpair, DynamicOps dynamicops) { + Map map = Maps.newHashMap(); + +@@ -213,9 +233,9 @@ public class RegionFileSection implements AutoCloseable { + public void a(ChunkCoordIntPair chunkcoordintpair) { + if (!this.d.isEmpty()) { + for (int i = 0; i < 16; ++i) { +- long j = SectionPosition.a(chunkcoordintpair, i).s(); ++ long j = SectionPosition.a(chunkcoordintpair, i).s(); // Paper - conflict here to avoid obfhelpers + +- if (this.d.contains(j)) { ++ if (this.d.contains(j)) { // Paper - conflict here to avoid obfhelpers + this.d(chunkcoordintpair); + return; + } +@@ -224,7 +244,26 @@ public class RegionFileSection implements AutoCloseable { + + } + +- public void close() throws IOException { +- this.b.close(); ++// Paper start - nuke IOWorker ++// public void close() throws IOException { ++// this.b.close(); ++// } ++// Paper end ++ ++ // Paper start - get data function ++ public NBTTagCompound getData(ChunkCoordIntPair chunkcoordintpair) { ++ // Note: Copied from above ++ // This is checking if the data exists, then it builds it later in getDataInternal(ChunkCoordIntPair) ++ if (!this.d.isEmpty()) { ++ for (int i = 0; i < 16; ++i) { ++ long j = SectionPosition.a(chunkcoordintpair, i).s(); ++ ++ if (this.d.contains(j)) { ++ return this.getDataInternal(chunkcoordintpair); ++ } ++ } ++ } ++ return null; + } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index d46c513512c25e55ccdb0be16524f19444c358c5..6aaf868cf3213e1935080c64c652c3055cb58e0c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -563,22 +563,23 @@ public class CraftWorld implements World { + return true; + } + +- net.minecraft.world.level.chunk.storage.RegionFile file; +- try { +- file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); +- } catch (IOException ex) { +- throw new RuntimeException(ex); +- } ++ ChunkStatus status = world.getChunkProvider().playerChunkMap.getStatusOnDiskNoLoad(x, z); // Paper - async io - move to own method + +- ChunkStatus status = file.getStatusIfCached(x, z); +- if (!file.chunkExists(chunkPos) || (status != null && status != ChunkStatus.FULL)) { ++ // Paper start - async io ++ if (status == ChunkStatus.EMPTY) { ++ // does not exist on disk + return false; + } + ++ if (status == null) { // at this stage we don't know what it is on disk + IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.EMPTY, true); + if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.world.level.chunk.Chunk)) { + return false; + } ++ } else if (status != ChunkStatus.FULL) { ++ return false; // not full status on disk ++ } ++ // Paper end + + // fall through to load + // we do this so we do not re-read the chunk data on disk +@@ -2501,6 +2502,34 @@ public class CraftWorld implements World { + public DragonBattle getEnderDragonBattle() { + return (getHandle().getDragonBattle() == null) ? null : new CraftDragonBattle(getHandle().getDragonBattle()); + } ++ // Paper start ++ @Override ++ public CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { ++ if (Bukkit.isPrimaryThread()) { ++ net.minecraft.world.level.chunk.Chunk immediate = this.world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); ++ if (immediate != null) { ++ return CompletableFuture.completedFuture(immediate.getBukkitChunk()); ++ } ++ } else { ++ CompletableFuture future = new CompletableFuture(); ++ world.getMinecraftServer().execute(() -> { ++ getChunkAtAsync(x, z, gen, urgent).whenComplete((chunk, err) -> { ++ if (err != null) { ++ future.completeExceptionally(err); ++ } else { ++ future.complete(chunk); ++ } ++ }); ++ }); ++ return future; ++ } ++ ++ return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { ++ net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); ++ return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); ++ }, net.minecraft.server.MinecraftServer.getServer()); ++ } ++ // Paper end + + // Spigot start + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 93bbf63e9d38f32d5528c7693633d4b65655bb9d..266b2cbd6bfaf10743929a1eeb9732a5d1fb4c62 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -12,6 +12,9 @@ import net.minecraft.nbt.NBTBase; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.PlayerChunk; ++import net.minecraft.server.level.PlayerChunkMap; ++import net.minecraft.server.level.TicketType; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityAreaEffectCloud; +@@ -144,6 +147,7 @@ import net.minecraft.world.entity.vehicle.EntityMinecartHopper; + import net.minecraft.world.entity.vehicle.EntityMinecartMobSpawner; + import net.minecraft.world.entity.vehicle.EntityMinecartRideable; + import net.minecraft.world.entity.vehicle.EntityMinecartTNT; ++import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.phys.AxisAlignedBB; + import org.bukkit.Chunk; // Paper + import org.bukkit.EntityEffect; +@@ -508,6 +512,28 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + entity.setHeadRotation(yaw); + } + ++ @Override// Paper start ++ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ PlayerChunkMap playerChunkMap = ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().playerChunkMap; ++ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); ++ ++ loc.getWorld().getChunkAtAsyncUrgently(loc).thenCompose(chunk -> { ++ ChunkCoordIntPair pair = new ChunkCoordIntPair(chunk.getX(), chunk.getZ()); ++ ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().addTicketAtLevel(TicketType.POST_TELEPORT, pair, 31, 0); ++ PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pair.pair()); ++ if (updatingChunk != null) { ++ return updatingChunk.getEntityTickingFuture(); ++ } else { ++ return java.util.concurrent.CompletableFuture.completedFuture(com.mojang.datafixers.util.Either.left(((org.bukkit.craftbukkit.CraftChunk)chunk).getHandle())); ++ } ++ }).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { ++ future.completeExceptionally(ex); ++ return null; ++ }); ++ return future; ++ } ++ // Paper end ++ + @Override + public boolean teleport(Location location) { + return teleport(location, TeleportCause.PLUGIN); +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index abaefa0b71104756e4b458abefe13d179e7a1724..58e50bf0fb0f309227e1f4c1f6bb11c01d8e08d3 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -6,6 +6,7 @@ import java.lang.management.ThreadInfo; + import java.util.logging.Level; + import java.util.logging.Logger; + import com.destroystokyo.paper.PaperConfig; ++import com.destroystokyo.paper.io.chunk.ChunkTaskManager; // Paper + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; + +@@ -116,6 +117,7 @@ public class WatchdogThread extends Thread + // Paper end - Different message for short timeout + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper ++ ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // diff --git a/patches/server-unmapped/0369-Use-getChunkIfLoadedImmediately-in-places.patch b/patches/server-unmapped/0369-Use-getChunkIfLoadedImmediately-in-places.patch new file mode 100644 index 0000000000..7b764afb8b --- /dev/null +++ b/patches/server-unmapped/0369-Use-getChunkIfLoadedImmediately-in-places.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 8 Jul 2019 00:13:36 -0700 +Subject: [PATCH] Use getChunkIfLoadedImmediately in places + +This prevents us from hitting chunk loads for chunks at or less-than +ticket level 33 (yes getChunkIfLoaded will actually perform a chunk +load in that case). + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 52d22da115212eae6c380bb5012398e3df92f5f3..13c99bdb8894d08f297f84ee1f98f50c811f7f4b 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -207,7 +207,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI +- return this.chunkProvider.getChunkAt(x, z, false); ++ return this.chunkProvider.getChunkAtIfLoadedImmediately(x, z); // Paper + } + + // Paper start - Asynchronous IO +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index d74d6abfff647c148e524905cd733c4b7fc6591f..24dfdb3807dbf6e9acc59d35d7c76f7ac0185219 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1244,7 +1244,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + speed = player.abilities.walkSpeed * 10f; + } + // Paper start - Prevent moving into unloaded chunks +- if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && !worldserver.isChunkLoaded((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { ++ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && worldserver.getChunkIfLoadedImmediately((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4) == null) { // Paper - use getIfLoadedImmediately + this.internalTeleport(this.player.locX(), this.player.locY(), this.player.locZ(), this.player.yaw, this.player.pitch, Collections.emptySet()); + return; + } +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 15da3511a9e57c320f4cf409852bee07109095bc..b620d7e0d824c8d0758a66a8fbe872c3e45103d2 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -164,6 +164,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return (CraftServer) Bukkit.getServer(); + } + ++ // Paper start ++ @Override ++ public boolean isChunkLoaded(int x, int z) { ++ return ((WorldServer)this).getChunkIfLoaded(x, z) != null; ++ } ++ // Paper end ++ + public ResourceKey getTypeKey() { + return typeKey; + } +@@ -1062,14 +1069,14 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + } + + public boolean p(BlockPosition blockposition) { +- return isOutsideWorld(blockposition) ? false : this.getChunkProvider().b(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return isOutsideWorld(blockposition) ? false : isChunkLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper + } + + public boolean a(BlockPosition blockposition, Entity entity, EnumDirection enumdirection) { + if (isOutsideWorld(blockposition)) { + return false; + } else { +- IChunkAccess ichunkaccess = this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, false); ++ IChunkAccess ichunkaccess = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper + + return ichunkaccess == null ? false : ichunkaccess.getType(blockposition).a((IBlockAccess) this, blockposition, entity, enumdirection); + } +@@ -1190,7 +1197,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + for (int i1 = i; i1 < j; ++i1) { + for (int j1 = k; j1 < l; ++j1) { +- Chunk chunk = ichunkprovider.a(i1, j1); ++ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { + chunk.a(oclass, axisalignedbb, list, predicate); +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 58d22363124a9343188d8c19476e5a92f2f0b80b..53d0541aba207b5eaea2e49edbb56df918d30333 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -140,9 +140,10 @@ public class ActivationRange + { + for ( int j1 = k; j1 <= l; ++j1 ) + { +- if ( world.getWorld().isChunkLoaded( i1, j1 ) ) ++ Chunk chunk = (Chunk) world.getChunkIfLoadedImmediately( i1, j1 ); ++ if ( chunk != null ) + { +- activateChunkEntities( world.getChunkAt( i1, j1 ) ); ++ activateChunkEntities( chunk ); + } + } + } diff --git a/patches/server-unmapped/0370-Reduce-sync-loads.patch b/patches/server-unmapped/0370-Reduce-sync-loads.patch new file mode 100644 index 0000000000..7b195978a9 --- /dev/null +++ b/patches/server-unmapped/0370-Reduce-sync-loads.patch @@ -0,0 +1,342 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 19 Jul 2019 03:29:14 -0700 +Subject: [PATCH] Reduce sync loads + +This reduces calls to getChunkAt which would load chunks. + +This patch also adds a tool to find calls which are doing this, however +it must be enabled by setting the startup flag -Dpaper.debug-sync-loads=true + +To get a debug log for sync loads, the command is /paper syncloadinfo + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index f657e9b6bb3d24a6c77ef584711a003d1eea0341..eb1e86e8bb0f421e3686ffa02a4015a588107863 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -1,6 +1,7 @@ + package com.destroystokyo.paper; + + import com.destroystokyo.paper.io.chunk.ChunkTaskManager; ++import com.destroystokyo.paper.io.SyncLoadFinder; + import com.google.common.base.Functions; + import com.google.common.base.Joiner; + import com.google.common.collect.ImmutableSet; +@@ -8,6 +9,10 @@ import com.google.common.collect.Iterables; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import net.minecraft.resources.MinecraftKey; ++import com.google.gson.JsonObject; ++import com.google.gson.internal.Streams; ++import com.google.gson.stream.JsonWriter; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkProviderServer; + import net.minecraft.server.level.PlayerChunk; +@@ -29,6 +34,9 @@ import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.entity.Player; + + import java.io.File; ++import java.io.FileOutputStream; ++import java.io.PrintStream; ++import java.io.StringWriter; + import java.time.LocalDateTime; + import java.time.format.DateTimeFormatter; + import java.util.ArrayList; +@@ -44,7 +52,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); + + public PaperCommand(String name) { + super(name); +@@ -162,6 +170,9 @@ public class PaperCommand extends Command { + case "chunkinfo": + doChunkInfo(sender, args); + break; ++ case "syncloadinfo": ++ this.doSyncLoadInfo(sender, args); ++ break; + case "ver": + if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) + case "version": +@@ -179,6 +190,40 @@ public class PaperCommand extends Command { + return true; + } + ++ private void doSyncLoadInfo(CommandSender sender, String[] args) { ++ if (!SyncLoadFinder.ENABLED) { ++ sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); ++ return; ++ } ++ File file = new File(new File(new File("."), "debug"), ++ "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); ++ file.getParentFile().mkdirs(); ++ sender.sendMessage(ChatColor.GREEN + "Writing sync load info to " + file.toString()); ++ ++ ++ try { ++ final JsonObject data = SyncLoadFinder.serialize(); ++ ++ StringWriter stringWriter = new StringWriter(); ++ JsonWriter jsonWriter = new JsonWriter(stringWriter); ++ jsonWriter.setIndent(" "); ++ jsonWriter.setLenient(false); ++ Streams.write(data, jsonWriter); ++ ++ String fileData = stringWriter.toString(); ++ ++ try ( ++ PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8") ++ ) { ++ out.print(fileData); ++ } ++ sender.sendMessage(ChatColor.GREEN + "Successfully written sync load information!"); ++ } catch (Throwable thr) { ++ sender.sendMessage(ChatColor.RED + "Failed to write sync load information"); ++ thr.printStackTrace(); ++ } ++ } ++ + private void doChunkInfo(CommandSender sender, String[] args) { + List worlds; + if (args.length < 2 || args[1].equals("*")) { +diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d381f91cf105bfc01846ada90da8971a3618e784 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java +@@ -0,0 +1,171 @@ ++package com.destroystokyo.paper.io; ++ ++import com.google.gson.JsonArray; ++import com.google.gson.JsonObject; ++import com.mojang.datafixers.util.Pair; ++import it.unimi.dsi.fastutil.longs.Long2IntMap; ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++import java.util.WeakHashMap; ++import net.minecraft.world.level.World; ++ ++public class SyncLoadFinder { ++ ++ public static final boolean ENABLED = Boolean.getBoolean("paper.debug-sync-loads"); ++ ++ private static final WeakHashMap> SYNC_LOADS = new WeakHashMap<>(); ++ ++ private static final class SyncLoadInformation { ++ ++ public int times; ++ ++ public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); ++ } ++ ++ public static void logSyncLoad(final World world, final int chunkX, final int chunkZ) { ++ if (!ENABLED) { ++ return; ++ } ++ ++ final ThrowableWithEquals stacktrace = new ThrowableWithEquals(Thread.currentThread().getStackTrace()); ++ ++ SYNC_LOADS.compute(world, (final World keyInMap, Object2ObjectOpenHashMap map) -> { ++ if (map == null) { ++ map = new Object2ObjectOpenHashMap<>(); ++ } ++ ++ map.compute(stacktrace, (ThrowableWithEquals keyInMap0, SyncLoadInformation valueInMap) -> { ++ if (valueInMap == null) { ++ valueInMap = new SyncLoadInformation(); ++ } ++ ++ ++valueInMap.times; ++ ++ valueInMap.coordinateTimes.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (Long keyInMap1, Integer valueInMap1) -> { ++ return valueInMap1 == null ? Integer.valueOf(1) : Integer.valueOf(valueInMap1.intValue() + 1); ++ }); ++ ++ return valueInMap; ++ }); ++ ++ return map; ++ }); ++ } ++ ++ public static JsonObject serialize() { ++ final JsonObject ret = new JsonObject(); ++ ++ final JsonArray worldsData = new JsonArray(); ++ ++ for (final Map.Entry> entry : SYNC_LOADS.entrySet()) { ++ final World world = entry.getKey(); ++ ++ final JsonObject worldData = new JsonObject(); ++ ++ worldData.addProperty("name", world.getWorld().getName()); ++ ++ final List> data = new ArrayList<>(); ++ ++ entry.getValue().forEach((ThrowableWithEquals stacktrace, SyncLoadInformation times) -> { ++ data.add(new Pair<>(stacktrace, times)); ++ }); ++ ++ data.sort((Pair pair1, Pair pair2) -> { ++ return Integer.compare(pair2.getSecond().times, pair1.getSecond().times); // reverse order ++ }); ++ ++ final JsonArray stacktraces = new JsonArray(); ++ ++ for (Pair pair : data) { ++ final JsonObject stacktrace = new JsonObject(); ++ ++ stacktrace.addProperty("times", pair.getSecond().times); ++ ++ final JsonArray traces = new JsonArray(); ++ ++ for (StackTraceElement element : pair.getFirst().stacktrace) { ++ traces.add(String.valueOf(element)); ++ } ++ ++ stacktrace.add("stacktrace", traces); ++ ++ final JsonArray coordinates = new JsonArray(); ++ ++ for (Long2IntMap.Entry coordinate : pair.getSecond().coordinateTimes.long2IntEntrySet()) { ++ final long key = coordinate.getLongKey(); ++ final int times = coordinate.getIntValue(); ++ coordinates.add("(" + IOUtil.getCoordinateX(key) + "," + IOUtil.getCoordinateZ(key) + "): " + times); ++ } ++ ++ stacktrace.add("coordinates", coordinates); ++ ++ stacktraces.add(stacktrace); ++ } ++ ++ ++ worldData.add("stacktraces", stacktraces); ++ worldsData.add(worldData); ++ } ++ ++ ret.add("worlds", worldsData); ++ ++ return ret; ++ } ++ ++ static final class ThrowableWithEquals { ++ ++ private final StackTraceElement[] stacktrace; ++ private final int hash; ++ ++ public ThrowableWithEquals(final StackTraceElement[] stacktrace) { ++ this.stacktrace = stacktrace; ++ this.hash = ThrowableWithEquals.hash(stacktrace); ++ } ++ ++ public static int hash(final StackTraceElement[] stacktrace) { ++ int hash = 0; ++ ++ for (int i = 0; i < stacktrace.length; ++i) { ++ hash *= 31; ++ hash += stacktrace[i].hashCode(); ++ } ++ ++ return hash; ++ } ++ ++ @Override ++ public int hashCode() { ++ return this.hash; ++ } ++ ++ @Override ++ public boolean equals(final Object obj) { ++ if (obj == null || obj.getClass() != this.getClass()) { ++ return false; ++ } ++ ++ final ThrowableWithEquals other = (ThrowableWithEquals)obj; ++ final StackTraceElement[] otherStackTrace = other.stacktrace; ++ ++ if (this.stacktrace.length != otherStackTrace.length || this.hash != other.hash) { ++ return false; ++ } ++ ++ if (this == obj) { ++ return true; ++ } ++ ++ for (int i = 0; i < this.stacktrace.length; ++i) { ++ if (!this.stacktrace[i].equals(otherStackTrace[i])) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 2a5df37a94b4b609a2d1b045f8e6a7f08d3f8eaa..24201665f8e7fb635839334308a1bad8fc4ac7b9 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -494,6 +494,7 @@ public class ChunkProviderServer extends IChunkProvider { + this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z); + // Paper end ++ com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.world, x, z); // Paper - sync load info + this.world.timings.syncChunkLoad.startTiming(); // Paper + this.serverThreadQueue.awaitTasks(completablefuture::isDone); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 13c99bdb8894d08f297f84ee1f98f50c811f7f4b..fbb550cce96e7e5539c69bae1459326090d0c508 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -282,6 +282,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { + }; + public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; + // Paper end ++ // Paper start ++ @Override ++ public boolean isChunkLoaded(int x, int z) { ++ return this.getChunkProvider().getChunkAtIfLoadedImmediately(x, z) != null; ++ } ++ // Paper end + + // Add env and gen to constructor, WorldData -> WorldDataServer + public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index b620d7e0d824c8d0758a66a8fbe872c3e45103d2..6781b25cc8e15be2556bb1bb8dc8c18c106b40ec 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -1130,7 +1130,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + for (int i1 = i; i1 <= j; ++i1) { + for (int j1 = k; j1 <= l; ++j1) { +- Chunk chunk = ichunkprovider.getChunkAt(i1, j1, false); ++ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { + chunk.a(entity, axisalignedbb, list, predicate); +@@ -1151,7 +1151,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + for (int i1 = i; i1 < j; ++i1) { + for (int j1 = k; j1 < l; ++j1) { +- Chunk chunk = this.getChunkProvider().getChunkAt(i1, j1, false); ++ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { + chunk.a(entitytypes, axisalignedbb, list, predicate); +@@ -1174,7 +1174,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + for (int i1 = i; i1 < j; ++i1) { + for (int j1 = k; j1 < l; ++j1) { +- Chunk chunk = ichunkprovider.getChunkAt(i1, j1, false); ++ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + + if (chunk != null) { + chunk.a(oclass, axisalignedbb, list, predicate); diff --git a/patches/server-unmapped/0371-Implement-alternative-item-despawn-rate.patch b/patches/server-unmapped/0371-Implement-alternative-item-despawn-rate.patch new file mode 100644 index 0000000000..4af6ed58d8 --- /dev/null +++ b/patches/server-unmapped/0371-Implement-alternative-item-despawn-rate.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Mon, 3 Jun 2019 02:02:39 -0400 +Subject: [PATCH] Implement alternative item-despawn-rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1ee2cced100626e48eb36ee14f84b9257c79a2f8..b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -1,10 +1,15 @@ + package com.destroystokyo.paper; + + import java.util.Arrays; ++import java.util.EnumMap; ++import java.util.HashMap; + import java.util.List; ++import java.util.Map; + + import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; + import org.bukkit.Bukkit; ++import org.bukkit.Material; ++import org.bukkit.configuration.ConfigurationSection; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; + +@@ -512,4 +517,52 @@ public class PaperWorldConfig { + private void disableRelativeProjectileVelocity() { + disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); + } ++ ++ public boolean altItemDespawnRateEnabled; ++ public Map altItemDespawnRateMap; ++ private void altItemDespawnRate() { ++ String path = "alt-item-despawn-rate"; ++ ++ altItemDespawnRateEnabled = getBoolean(path + ".enabled", false); ++ ++ Map altItemDespawnRateMapDefault = new EnumMap<>(Material.class); ++ altItemDespawnRateMapDefault.put(Material.COBBLESTONE, 300); ++ for (Material key : altItemDespawnRateMapDefault.keySet()) { ++ config.addDefault("world-settings.default." + path + ".items." + key, altItemDespawnRateMapDefault.get(key)); ++ } ++ ++ Map rawMap = new HashMap<>(); ++ try { ++ ConfigurationSection mapSection = config.getConfigurationSection("world-settings." + worldName + "." + path + ".items"); ++ if (mapSection == null) { ++ mapSection = config.getConfigurationSection("world-settings.default." + path + ".items"); ++ } ++ for (String key : mapSection.getKeys(false)) { ++ int val = mapSection.getInt(key); ++ rawMap.put(key, val); ++ } ++ } ++ catch (Exception e) { ++ logError("alt-item-despawn-rate was malformatted"); ++ altItemDespawnRateEnabled = false; ++ } ++ ++ altItemDespawnRateMap = new EnumMap<>(Material.class); ++ if (!altItemDespawnRateEnabled) { ++ return; ++ } ++ ++ for(String key : rawMap.keySet()) { ++ try { ++ altItemDespawnRateMap.put(Material.valueOf(key), rawMap.get(key)); ++ } catch (Exception e) { ++ logError("Could not add item " + key + " to altItemDespawnRateMap: " + e.getMessage()); ++ } ++ } ++ if(altItemDespawnRateEnabled) { ++ for(Material key : altItemDespawnRateMap.keySet()) { ++ log("Alternative item despawn rate of " + key + ": " + altItemDespawnRateMap.get(key)); ++ } ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index 02e4d6891adc902f73ed349f15dae3a429bd283a..0b2e6e72a85e05f239d56afb6785c91da5b25d55 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -33,6 +33,7 @@ import net.minecraft.world.phys.Vec3D; + + // CraftBukkit start + import net.minecraft.server.MinecraftServer; ++import org.bukkit.Material; // Paper + import org.bukkit.event.entity.EntityPickupItemEvent; + import org.bukkit.event.player.PlayerPickupItemEvent; + // CraftBukkit end +@@ -161,7 +162,7 @@ public class EntityItem extends Entity { + } + } + +- if (!this.world.isClientSide && this.age >= world.spigotConfig.itemDespawnRate) { // Spigot ++ if (!this.world.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper + // CraftBukkit start - fire ItemDespawnEvent + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { + this.age = 0; +@@ -185,7 +186,7 @@ public class EntityItem extends Entity { + this.lastTick = MinecraftServer.currentTick; + // CraftBukkit end + +- if (!this.world.isClientSide && this.age >= world.spigotConfig.itemDespawnRate) { // Spigot ++ if (!this.world.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper + // CraftBukkit start - fire ItemDespawnEvent + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { + this.age = 0; +@@ -535,9 +536,16 @@ public class EntityItem extends Entity { + + public void s() { + this.o(); +- this.age = world.spigotConfig.itemDespawnRate - 1; // Spigot ++ this.age = this.getDespawnRate() - 1; // Spigot // Paper + } + ++ // Paper start ++ public int getDespawnRate(){ ++ Material material = this.getItemStack().getBukkitStack().getType(); ++ return world.paperConfig.altItemDespawnRateMap.getOrDefault(material, world.spigotConfig.itemDespawnRate); ++ } ++ // Paper end ++ + @Override + public Packet P() { + return new PacketPlayOutSpawnEntity(this); diff --git a/patches/server-unmapped/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/patches/server-unmapped/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch new file mode 100644 index 0000000000..4968b9eb2f --- /dev/null +++ b/patches/server-unmapped/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paul Sauve +Date: Sun, 14 Jul 2019 21:05:03 -0500 +Subject: [PATCH] Do less work if we have a custom Bukkit generator + +If the Bukkit generator already has a spawn, use it immediately instead +of spending time generating one that we won't use + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index e6e8ab0b39a11b0aed247b9b80a6c1f97505546b..eb134ccb68dc135ab6db4c5a1d29edb321cf3f59 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -630,12 +630,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { +- return biomebase.b().b(); +- }, random); +- ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition); ++ // Paper start - moved down + // CraftBukkit start + if (worldserver.generator != null) { + Random rand = new Random(worldserver.getSeed()); +@@ -651,6 +646,15 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { ++ return biomebase.b().b(); ++ }, random); ++ ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition); ++ // Paper end + + if (blockposition == null) { + MinecraftServer.LOGGER.warn("Unable to find spawn biome"); diff --git a/patches/server-unmapped/0373-Fix-MC-158900.patch b/patches/server-unmapped/0373-Fix-MC-158900.patch new file mode 100644 index 0000000000..023ce89b91 --- /dev/null +++ b/patches/server-unmapped/0373-Fix-MC-158900.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 13 Aug 2019 06:35:17 -0700 +Subject: [PATCH] Fix MC-158900 + +The problem was we were checking isExpired() on the entry, but if it +was expired at that point, then it would be null. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index ec4e84f6275f8b305fb5a64f9c0cff24729d73ec..553b14f7167673938d1bc83d79c730692a4ef105 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -607,8 +607,10 @@ public abstract class PlayerList { + Player player = entity.getBukkitEntity(); + PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress()); + +- if (getProfileBans().isBanned(gameprofile) && !getProfileBans().get(gameprofile).hasExpired()) { +- GameProfileBanEntry gameprofilebanentry = (GameProfileBanEntry) this.k.get(gameprofile); ++ // Paper start - Fix MC-158900 ++ GameProfileBanEntry gameprofilebanentry; ++ if (getProfileBans().isBanned(gameprofile) && (gameprofilebanentry = getProfileBans().get(gameprofile)) != null) { ++ // Paper end + + chatmessage = new ChatMessage("multiplayer.disconnect.banned.reason", new Object[]{gameprofilebanentry.getReason()}); + if (gameprofilebanentry.getExpires() != null) { diff --git a/patches/server-unmapped/0374-implement-optional-per-player-mob-spawns.patch b/patches/server-unmapped/0374-implement-optional-per-player-mob-spawns.patch new file mode 100644 index 0000000000..54831e29f7 --- /dev/null +++ b/patches/server-unmapped/0374-implement-optional-per-player-mob-spawns.patch @@ -0,0 +1,848 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Mon, 19 Aug 2019 01:27:58 +0500 +Subject: [PATCH] implement optional per player mob spawns + + +diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +index 2da28784ee427001b1137c859f0b4c350abd3110..c5f594d45012016d99b83a778a2b9d20a7c086ac 100644 +--- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java ++++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java +@@ -57,6 +57,7 @@ public class WorldTimingsHandler { + + + public final Timing miscMobSpawning; ++ public final Timing playerMobDistanceMapUpdate; + + public final Timing poiUnload; + public final Timing chunkUnload; +@@ -122,6 +123,7 @@ public class WorldTimingsHandler { + + + miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); ++ playerMobDistanceMapUpdate = Timings.ofSafe(name + "Per Player Mob Spawning - Distance Map Update"); + + poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); + chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920..6aec502eb529d4090306e12e837117cde7e114eb 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -565,4 +565,9 @@ public class PaperWorldConfig { + } + } + } ++ ++ public boolean perPlayerMobSpawns = false; ++ private void perPlayerMobSpawns() { ++ perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6124b54d99adbb2a5bb9bb09dfd02522a67ab3ba +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java +@@ -0,0 +1,252 @@ ++package com.destroystokyo.paper.util; ++ ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; ++import java.util.List; ++import java.util.Map; ++import net.minecraft.core.SectionPosition; ++import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import org.spigotmc.AsyncCatcher; ++import java.util.HashMap; ++ ++/** @author Spottedleaf */ ++public final class PlayerMobDistanceMap { ++ ++ private static final PooledHashSets.PooledObjectLinkedOpenHashSet EMPTY_SET = new PooledHashSets.PooledObjectLinkedOpenHashSet<>(); ++ ++ private final Map players = new HashMap<>(); ++ // we use linked for better iteration. ++ private final Long2ObjectOpenHashMap> playerMap = new Long2ObjectOpenHashMap<>(32, 0.5f); ++ private int viewDistance; ++ ++ private final PooledHashSets pooledHashSets = new PooledHashSets<>(); ++ ++ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final ChunkCoordIntPair chunkPos) { ++ return this.getPlayersInRange(chunkPos.x, chunkPos.z); ++ } ++ ++ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final int chunkX, final int chunkZ) { ++ return this.playerMap.getOrDefault(ChunkCoordIntPair.pair(chunkX, chunkZ), EMPTY_SET); ++ } ++ ++ public void update(final List currentPlayers, final int newViewDistance) { ++ AsyncCatcher.catchOp("Distance map update"); ++ final ObjectLinkedOpenHashSet gone = new ObjectLinkedOpenHashSet<>(this.players.keySet()); ++ ++ final int oldViewDistance = this.viewDistance; ++ this.viewDistance = newViewDistance; ++ ++ for (final EntityPlayer player : currentPlayers) { ++ if (player.isSpectator() || !player.affectsSpawning) { ++ continue; // will be left in 'gone' (or not added at all) ++ } ++ ++ gone.remove(player); ++ ++ final SectionPosition newPosition = player.getPlayerMapSection(); ++ final SectionPosition oldPosition = this.players.put(player, newPosition); ++ ++ if (oldPosition == null) { ++ this.addNewPlayer(player, newPosition, newViewDistance); ++ } else { ++ this.updatePlayer(player, oldPosition, newPosition, oldViewDistance, newViewDistance); ++ } ++ //this.validatePlayer(player, newViewDistance); // debug only ++ } ++ ++ for (final EntityPlayer player : gone) { ++ final SectionPosition oldPosition = this.players.remove(player); ++ if (oldPosition != null) { ++ this.removePlayer(player, oldPosition, oldViewDistance); ++ } ++ } ++ } ++ ++ // expensive op, only for debug ++ private void validatePlayer(final EntityPlayer player, final int viewDistance) { ++ int entiesGot = 0; ++ int expectedEntries = (2 * viewDistance + 1); ++ expectedEntries *= expectedEntries; ++ ++ final SectionPosition currPosition = player.getPlayerMapSection(); ++ ++ final int centerX = currPosition.getX(); ++ final int centerZ = currPosition.getZ(); ++ ++ for (final Long2ObjectLinkedOpenHashMap.Entry> entry : this.playerMap.long2ObjectEntrySet()) { ++ final long key = entry.getLongKey(); ++ final PooledHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); ++ ++ if (map.referenceCount == 0) { ++ throw new IllegalStateException("Invalid map"); ++ } ++ ++ if (map.set.contains(player)) { ++ ++entiesGot; ++ ++ final int chunkX = ChunkCoordIntPair.getX(key); ++ final int chunkZ = ChunkCoordIntPair.getZ(key); ++ ++ final int dist = Math.max(Math.abs(chunkX - centerX), Math.abs(chunkZ - centerZ)); ++ ++ if (dist > viewDistance) { ++ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); ++ } ++ } ++ } ++ ++ if (entiesGot != expectedEntries) { ++ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); ++ } ++ } ++ ++ private void addPlayerTo(final EntityPlayer player, final int chunkX, final int chunkZ) { ++ this.playerMap.compute(ChunkCoordIntPair.pair(chunkX, chunkZ), (final Long key, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { ++ if (players == null) { ++ return player.cachedSingleMobDistanceMap; ++ } else { ++ return PlayerMobDistanceMap.this.pooledHashSets.findMapWith(players, player); ++ } ++ }); ++ } ++ ++ private void removePlayerFrom(final EntityPlayer player, final int chunkX, final int chunkZ) { ++ this.playerMap.compute(ChunkCoordIntPair.pair(chunkX, chunkZ), (final Long keyInMap, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { ++ return PlayerMobDistanceMap.this.pooledHashSets.findMapWithout(players, player); // rets null instead of an empty map ++ }); ++ } ++ ++ private void updatePlayer(final EntityPlayer player, final SectionPosition oldPosition, final SectionPosition newPosition, final int oldViewDistance, final int newViewDistance) { ++ final int toX = newPosition.getX(); ++ final int toZ = newPosition.getZ(); ++ final int fromX = oldPosition.getX(); ++ final int fromZ = oldPosition.getZ(); ++ ++ final int dx = toX - fromX; ++ final int dz = toZ - fromZ; ++ ++ final int totalX = Math.abs(fromX - toX); ++ final int totalZ = Math.abs(fromZ - toZ); ++ ++ if (Math.max(totalX, totalZ) > (2 * oldViewDistance)) { ++ // teleported? ++ this.removePlayer(player, oldPosition, oldViewDistance); ++ this.addNewPlayer(player, newPosition, newViewDistance); ++ return; ++ } ++ ++ // x axis is width ++ // z axis is height ++ // right refers to the x axis of where we moved ++ // top refers to the z axis of where we moved ++ ++ if (oldViewDistance == newViewDistance) { ++ // same view distance ++ ++ // used for relative positioning ++ final int up = 1 | (dz >> (Integer.SIZE - 1)); // 1 if dz >= 0, -1 otherwise ++ final int right = 1 | (dx >> (Integer.SIZE - 1)); // 1 if dx >= 0, -1 otherwise ++ ++ // The area excluded by overlapping the two view distance squares creates four rectangles: ++ // Two on the left, and two on the right. The ones on the left we consider the "removed" section ++ // and on the right the "added" section. ++ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually ++ // exclusive to the regions they surround. ++ ++ // 4 points of the rectangle ++ int maxX; // exclusive ++ int minX; // inclusive ++ int maxZ; // exclusive ++ int minZ; // inclusive ++ ++ if (dx != 0) { ++ // handle right addition ++ ++ maxX = toX + (oldViewDistance * right) + right; // exclusive ++ minX = fromX + (oldViewDistance * right) + right; // inclusive ++ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive ++ minZ = toZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.addPlayerTo(player, currX, currZ); ++ } ++ } ++ } ++ ++ if (dz != 0) { ++ // handle up addition ++ ++ maxX = toX + (oldViewDistance * right) + right; // exclusive ++ minX = toX - (oldViewDistance * right); // inclusive ++ maxZ = toZ + (oldViewDistance * up) + up; // exclusive ++ minZ = fromZ + (oldViewDistance * up) + up; // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.addPlayerTo(player, currX, currZ); ++ } ++ } ++ } ++ ++ if (dx != 0) { ++ // handle left removal ++ ++ maxX = toX - (oldViewDistance * right); // exclusive ++ minX = fromX - (oldViewDistance * right); // inclusive ++ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive ++ minZ = toZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.removePlayerFrom(player, currX, currZ); ++ } ++ } ++ } ++ ++ if (dz != 0) { ++ // handle down removal ++ ++ maxX = fromX + (oldViewDistance * right) + right; // exclusive ++ minX = fromX - (oldViewDistance * right); // inclusive ++ maxZ = toZ - (oldViewDistance * up); // exclusive ++ minZ = fromZ - (oldViewDistance * up); // inclusive ++ ++ for (int currX = minX; currX != maxX; currX += right) { ++ for (int currZ = minZ; currZ != maxZ; currZ += up) { ++ this.removePlayerFrom(player, currX, currZ); ++ } ++ } ++ } ++ } else { ++ // different view distance ++ // for now :) ++ this.removePlayer(player, oldPosition, oldViewDistance); ++ this.addNewPlayer(player, newPosition, newViewDistance); ++ } ++ } ++ ++ private void removePlayer(final EntityPlayer player, final SectionPosition position, final int viewDistance) { ++ final int x = position.getX(); ++ final int z = position.getZ(); ++ ++ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { ++ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { ++ this.removePlayerFrom(player, x + xoff, z + zoff); ++ } ++ } ++ } ++ ++ private void addNewPlayer(final EntityPlayer player, final SectionPosition position, final int viewDistance) { ++ final int x = position.getX(); ++ final int z = position.getZ(); ++ ++ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { ++ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { ++ this.addPlayerTo(player, x + xoff, z + zoff); ++ } ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4f13d3ff8391793a99f067189f854078334499c6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java +@@ -0,0 +1,241 @@ ++package com.destroystokyo.paper.util; ++ ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; ++import java.lang.ref.WeakReference; ++import java.util.Iterator; ++ ++/** @author Spottedleaf */ ++public class PooledHashSets { ++ ++ // we really want to avoid that equals() check as much as possible... ++ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(64, 0.25f); ++ ++ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { ++ if (current.referenceCount == 0) { ++ throw new IllegalStateException("Cannot decrement reference count for " + current); ++ } ++ if (current.referenceCount == -1 || --current.referenceCount > 0) { ++ return; ++ } ++ ++ this.mapPool.remove(current); ++ return; ++ } ++ ++ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { ++ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); ++ ++ if (cached != null) { ++ if (cached.referenceCount != -1) { ++ ++cached.referenceCount; ++ } ++ ++ decrementReferenceCount(current); ++ ++ return cached; ++ } ++ ++ if (!current.add(object)) { ++ return current; ++ } ++ ++ // we use get/put since we use a different key on put ++ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); ++ ++ if (ret == null) { ++ ret = new PooledObjectLinkedOpenHashSet<>(current); ++ current.remove(object); ++ this.mapPool.put(ret, ret); ++ ret.referenceCount = 1; ++ } else { ++ if (ret.referenceCount != -1) { ++ ++ret.referenceCount; ++ } ++ current.remove(object); ++ } ++ ++ current.updateAddCache(object, ret); ++ ++ decrementReferenceCount(current); ++ return ret; ++ } ++ ++ // rets null if current.size() == 1 ++ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { ++ if (current.set.size() == 1) { ++ decrementReferenceCount(current); ++ return null; ++ } ++ ++ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); ++ ++ if (cached != null) { ++ if (cached.referenceCount != -1) { ++ ++cached.referenceCount; ++ } ++ ++ decrementReferenceCount(current); ++ ++ return cached; ++ } ++ ++ if (!current.remove(object)) { ++ return current; ++ } ++ ++ // we use get/put since we use a different key on put ++ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); ++ ++ if (ret == null) { ++ ret = new PooledObjectLinkedOpenHashSet<>(current); ++ current.add(object); ++ this.mapPool.put(ret, ret); ++ ret.referenceCount = 1; ++ } else { ++ if (ret.referenceCount != -1) { ++ ++ret.referenceCount; ++ } ++ current.add(object); ++ } ++ ++ current.updateRemoveCache(object, ret); ++ ++ decrementReferenceCount(current); ++ return ret; ++ } ++ ++ public static final class PooledObjectLinkedOpenHashSet implements Iterable { ++ ++ private static final WeakReference NULL_REFERENCE = new WeakReference(null); ++ ++ final ObjectLinkedOpenHashSet set; ++ int referenceCount; // -1 if special ++ int hash; // optimize hashcode ++ ++ // add cache ++ WeakReference lastAddObject = NULL_REFERENCE; ++ WeakReference> lastAddMap = NULL_REFERENCE; ++ ++ // remove cache ++ WeakReference lastRemoveObject = NULL_REFERENCE; ++ WeakReference> lastRemoveMap = NULL_REFERENCE; ++ ++ public PooledObjectLinkedOpenHashSet() { ++ this.set = new ObjectLinkedOpenHashSet<>(2, 0.6f); ++ } ++ ++ public PooledObjectLinkedOpenHashSet(final E single) { ++ this(); ++ this.referenceCount = -1; ++ this.add(single); ++ } ++ ++ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { ++ this.set = other.set.clone(); ++ this.hash = other.hash; ++ } ++ ++ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java ++ // generated by https://github.com/skeeto/hash-prospector ++ static int hash0(int x) { ++ x *= 0x36935555; ++ x ^= x >>> 16; ++ return x; ++ } ++ ++ public PooledObjectLinkedOpenHashSet getAddCache(final E element) { ++ final E currentAdd = this.lastAddObject.get(); ++ ++ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { ++ return null; ++ } ++ ++ final PooledObjectLinkedOpenHashSet map = this.lastAddMap.get(); ++ if (map == null || map.referenceCount == 0) { ++ // we need to ret null if ref count is zero as calling code will assume the map is in use ++ return null; ++ } ++ ++ return map; ++ } ++ ++ public PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { ++ final E currentRemove = this.lastRemoveObject.get(); ++ ++ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { ++ return null; ++ } ++ ++ final PooledObjectLinkedOpenHashSet map = this.lastRemoveMap.get(); ++ if (map == null || map.referenceCount == 0) { ++ // we need to ret null if ref count is zero as calling code will assume the map is in use ++ return null; ++ } ++ ++ return map; ++ } ++ ++ public void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { ++ this.lastAddObject = new WeakReference<>(element); ++ this.lastAddMap = new WeakReference<>(map); ++ } ++ ++ public void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { ++ this.lastRemoveObject = new WeakReference<>(element); ++ this.lastRemoveMap = new WeakReference<>(map); ++ } ++ ++ boolean add(final E element) { ++ boolean added = this.set.add(element); ++ ++ if (added) { ++ this.hash += hash0(element.hashCode()); ++ } ++ ++ return added; ++ } ++ ++ boolean remove(Object element) { ++ boolean removed = this.set.remove(element); ++ ++ if (removed) { ++ this.hash -= hash0(element.hashCode()); ++ } ++ ++ return removed; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return this.set.iterator(); ++ } ++ ++ @Override ++ public int hashCode() { ++ return this.hash; ++ } ++ ++ @Override ++ public boolean equals(final Object other) { ++ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { ++ return false; ++ } ++ if (this.referenceCount == 0) { ++ return other == this; ++ } else { ++ if (other == this) { ++ // Unfortunately we are never equal to our own instance while in use! ++ return false; ++ } ++ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); ++ } ++ } ++ ++ @Override ++ public String toString() { ++ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + ++ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 24201665f8e7fb635839334308a1bad8fc4ac7b9..12b9be00d486ec960ef0ebc750f56011c90ce37c 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -767,7 +767,22 @@ public class ChunkProviderServer extends IChunkProvider { + this.world.getMethodProfiler().enter("naturalSpawnCount"); + this.world.timings.countNaturalMobs.startTiming(); // Paper - timings + int l = this.chunkMapDistance.b(); +- SpawnerCreature.d spawnercreature_d = SpawnerCreature.a(l, this.world.A(), this::a); ++ // Paper start - per player mob spawning ++ SpawnerCreature.d spawnercreature_d; // moved down ++ if (this.playerChunkMap.playerMobDistanceMap != null) { ++ // update distance map ++ this.world.timings.playerMobDistanceMapUpdate.startTiming(); ++ this.playerChunkMap.playerMobDistanceMap.update(this.world.players, this.playerChunkMap.viewDistance); ++ this.world.timings.playerMobDistanceMapUpdate.stopTiming(); ++ // re-set mob counts ++ for (EntityPlayer player : this.world.players) { ++ Arrays.fill(player.mobCounts, 0); ++ } ++ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, true); ++ } else { ++ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, false); ++ } ++ // Paper end + this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings + + this.p = spawnercreature_d; +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index a15b119b24090ffc607bfc9003d5b95f3acf3b2f..f0c3bfb0e641b9f1a22fb6873ab3645be6e481c4 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -94,6 +94,7 @@ import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityInsentient; + import net.minecraft.world.entity.EntityLiving; ++import net.minecraft.world.entity.EnumCreatureType; + import net.minecraft.world.entity.EnumMainHand; + import net.minecraft.world.entity.IEntityAngerable; + import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; +@@ -219,6 +220,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public boolean queueHealthUpdatePacket = false; + public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; + // Paper end ++ // Paper start - mob spawning rework ++ public static final int ENUMCREATURETYPE_TOTAL_ENUMS = EnumCreatureType.values().length; ++ public final int[] mobCounts = new int[ENUMCREATURETYPE_TOTAL_ENUMS]; // Paper ++ public final com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet cachedSingleMobDistanceMap; ++ // Paper end + + // CraftBukkit start + public String displayName; +@@ -257,6 +263,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getName()); // Paper + this.canPickUpLoot = true; + this.maxHealthCache = this.getMaxHealth(); ++ this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper + } + + // Yes, this doesn't match Vanilla, but it's the best we can do for now. +@@ -2061,6 +2068,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + } + ++ public final SectionPosition getPlayerMapSection() { return this.O(); } // Paper - OBFHELPER + public SectionPosition O() { + return this.cj; + } +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 46c91230ab6f12db77b453c312fa7382b76fad34..d00dc8d7933be61f1401f598e5d675f5ae5d7029 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -72,6 +72,7 @@ import net.minecraft.util.thread.ThreadedMailbox; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityInsentient; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.EnumCreatureType; + import net.minecraft.world.entity.ai.village.poi.VillagePlace; + import net.minecraft.world.entity.boss.EntityComplexPart; + import net.minecraft.world.entity.player.EntityHuman; +@@ -129,7 +130,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + public final Int2ObjectMap trackedEntities; + private final Long2ByteMap z; + private final Queue A; private final Queue getUnloadQueueTasks() { return this.A; } // Paper - OBFHELPER +- private int viewDistance; ++ int viewDistance; // Paper - private -> package private ++ public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper + + // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() + public final CallbackExecutor callbackExecutor = new CallbackExecutor(); +@@ -208,6 +210,24 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.l = supplier; + this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper + this.setViewDistance(i); ++ this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper ++ } ++ ++ public void updatePlayerMobTypeMap(Entity entity) { ++ if (!this.world.paperConfig.perPlayerMobSpawns) { ++ return; ++ } ++ int chunkX = (int)Math.floor(entity.locX()) >> 4; ++ int chunkZ = (int)Math.floor(entity.locZ()) >> 4; ++ int index = entity.getEntityType().getEnumCreatureType().ordinal(); ++ ++ for (EntityPlayer player : this.playerMobDistanceMap.getPlayersInRange(chunkX, chunkZ)) { ++ ++player.mobCounts[index]; ++ } ++ } ++ ++ public int getMobCountNear(EntityPlayer entityPlayer, EnumCreatureType enumCreatureType) { ++ return entityPlayer.mobCounts[enumCreatureType.ordinal()]; + } + + private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) { +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index 1355c074353611669c947cb0f06c67be0ab418aa..9d2955f05aadd4bbc6dcfec068a55d7fe6950ba0 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -426,6 +426,7 @@ public class EntityTypes { + return this.bl; + } + ++ public final EnumCreatureType getEnumCreatureType() { return this.e(); } // Paper - OBFHELPER + public EnumCreatureType e() { + return this.bg; + } +diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +index d30a3de84dc75a57680052904337af02b6b80636..24771c3522ea74ac12058591137eafc21adf3762 100644 +--- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java ++++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java +@@ -16,6 +16,7 @@ import net.minecraft.core.IPosition; + import net.minecraft.core.IRegistry; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.server.MCUtil; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; + import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsBlock; +@@ -62,6 +63,11 @@ public final class SpawnerCreature { + }); + + public static SpawnerCreature.d a(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b) { ++ // Paper start - add countMobs parameter ++ return countMobs(i, iterable, spawnercreature_b, false); ++ } ++ public static SpawnerCreature.d countMobs(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b, boolean countMobs) { ++ // Paper end - add countMobs parameter + SpawnerCreatureProbabilities spawnercreatureprobabilities = new SpawnerCreatureProbabilities(); + Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); + Iterator iterator = iterable.iterator(); +@@ -99,6 +105,11 @@ public final class SpawnerCreature { + } + + object2intopenhashmap.addTo(enumcreaturetype, 1); ++ // Paper start ++ if (countMobs) { ++ ((WorldServer)chunk.world).getChunkProvider().playerChunkMap.updatePlayerMobTypeMap(entity); ++ } ++ // Paper end + }); + } + } +@@ -157,13 +168,31 @@ public final class SpawnerCreature { + continue; + } + +- if ((flag || !enumcreaturetype.d()) && (flag1 || enumcreaturetype.d()) && (flag2 || !enumcreaturetype.e()) && spawnercreature_d.a(enumcreaturetype, limit)) { ++ // Paper start - only allow spawns upto the limit per chunk and update count afterwards ++ int currEntityCount = spawnercreature_d.getEntityCountsByType().getInt(enumcreaturetype); ++ int k1 = limit * spawnercreature_d.getSpawnerChunks() / SpawnerCreature.b; ++ int difference = k1 - currEntityCount; ++ ++ if (worldserver.paperConfig.perPlayerMobSpawns) { ++ int minDiff = Integer.MAX_VALUE; ++ for (EntityPlayer entityplayer : worldserver.getChunkProvider().playerChunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) { ++ minDiff = Math.min(limit - worldserver.getChunkProvider().playerChunkMap.getMobCountNear(entityplayer, enumcreaturetype), minDiff); ++ } ++ difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff; ++ } ++ // Paper end ++ ++ // Paper start - per player mob spawning ++ if ((flag || !enumcreaturetype.d()) && (flag1 || enumcreaturetype.d()) && (flag2 || !enumcreaturetype.e()) && difference > 0) { + // CraftBukkit end +- a(enumcreaturetype, worldserver, chunk, (entitytypes, blockposition, ichunkaccess) -> { ++ int spawnCount = spawnMobs(enumcreaturetype, worldserver, chunk, (entitytypes, blockposition, ichunkaccess) -> { + return spawnercreature_d.a(entitytypes, blockposition, ichunkaccess); + }, (entityinsentient, ichunkaccess) -> { + spawnercreature_d.a(entityinsentient, ichunkaccess); +- }); ++ }, ++ difference, worldserver.paperConfig.perPlayerMobSpawns ? worldserver.getChunkProvider().playerChunkMap::updatePlayerMobTypeMap : null); ++ spawnercreature_d.getEntityCountsByType().mergeInt(enumcreaturetype, spawnCount, Integer::sum); ++ // Paper end - per player mob spawning + } + } + +@@ -172,22 +201,34 @@ public final class SpawnerCreature { + } + + public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a) { ++ // Paper start - add parameters and int ret type ++ spawnMobs(enumcreaturetype, worldserver, chunk, spawnercreature_c, spawnercreature_a, Integer.MAX_VALUE, null); ++ } ++ public static int spawnMobs(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer trackEntity) { ++ // Paper end - add parameters and int ret type + BlockPosition blockposition = getRandomPosition(worldserver, chunk); + + if (blockposition.getY() >= 1) { +- a(enumcreaturetype, worldserver, (IChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a); ++ return spawnMobsInternal(enumcreaturetype, worldserver, (IChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a, maxSpawns, trackEntity); + } ++ return 0; // Paper + } + + public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition blockposition, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a) { ++ // Paper start - add maxSpawns parameter and return spawned mobs ++ spawnMobsInternal(enumcreaturetype, worldserver, ichunkaccess, blockposition, spawnercreature_c, spawnercreature_a, Integer.MAX_VALUE, null); ++ } ++ public static int spawnMobsInternal(EnumCreatureType enumcreaturetype, WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition blockposition, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer trackEntity) { ++ // Paper end - add maxSpawns parameter and return spawned mobs + StructureManager structuremanager = worldserver.getStructureManager(); + ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); + int i = blockposition.getY(); + IBlockData iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn ++ int j = 0; // Paper - moved up + + if (iblockdata != null && !iblockdata.isOccluding(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); +- int j = 0; ++ // Paper - moved up + int k = 0; + + while (k < 3) { +@@ -227,7 +268,7 @@ public final class SpawnerCreature { + // Paper start + Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); + if (doSpawning == null) { +- return; ++ return j; // Paper + } + if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { + // Paper end +@@ -235,7 +276,7 @@ public final class SpawnerCreature { + + + if (entityinsentient == null) { +- return; ++ return j; // Paper + } + + entityinsentient.setPositionRotation(d0, (double) i, d1, worldserver.random.nextFloat() * 360.0F, 0.0F); +@@ -244,13 +285,18 @@ public final class SpawnerCreature { + // CraftBukkit start + worldserver.addAllEntities(entityinsentient, SpawnReason.NATURAL); + if (!entityinsentient.dead) { +- ++j; ++ ++j; // Paper - force diff on name change - we expect this to be the total amount spawned + ++k1; + spawnercreature_a.run(entityinsentient, ichunkaccess); ++ // Paper start ++ if (trackEntity != null) { ++ trackEntity.accept(entityinsentient); ++ } ++ // Paper end + } + // CraftBukkit end +- if (j >= entityinsentient.getMaxSpawnGroup()) { +- return; ++ if (j >= entityinsentient.getMaxSpawnGroup() || j >= maxSpawns) { // Paper ++ return j; // Paper + } + + if (entityinsentient.c(k1)) { +@@ -272,6 +318,7 @@ public final class SpawnerCreature { + } + + } ++ return j; // Paper + } + + private static boolean a(WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { +@@ -512,8 +559,8 @@ public final class SpawnerCreature { + + public static class d { + +- private final int a; +- private final Object2IntOpenHashMap b; ++ private final int a; final int getSpawnerChunks() { return this.a; } // Paper - OBFHELPER ++ private final Object2IntOpenHashMap b; final Object2IntMap getEntityCountsByType() { return this.b; } // Paper - OBFHELPER + private final SpawnerCreatureProbabilities c; + private final Object2IntMap d; + @Nullable +@@ -574,7 +621,7 @@ public final class SpawnerCreature { + + // CraftBukkit start + private boolean a(EnumCreatureType enumcreaturetype, int limit) { +- int i = limit * this.a / SpawnerCreature.b; ++ int i = limit * this.a / SpawnerCreature.b; // Paper - diff on change, needed in the spawn method + // CraftBukkit end + + return this.b.getInt(enumcreaturetype) < i; diff --git a/patches/server-unmapped/0375-Prevent-consuming-the-wrong-itemstack.patch b/patches/server-unmapped/0375-Prevent-consuming-the-wrong-itemstack.patch new file mode 100644 index 0000000000..053e08edc4 --- /dev/null +++ b/patches/server-unmapped/0375-Prevent-consuming-the-wrong-itemstack.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Mon, 19 Aug 2019 19:42:35 +0500 +Subject: [PATCH] Prevent consuming the wrong itemstack + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 4e2039e46741e8a09f3af7d3d9e98ef7a5b27abc..48f932b2e049741ebee5824e158e4bda87d42faf 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -3201,10 +3201,13 @@ public abstract class EntityLiving extends Entity { + this.datawatcher.set(EntityLiving.ag, (byte) j); + } + +- public void c(EnumHand enumhand) { ++ // Paper start -- OBFHELPER and forwarder to method with forceUpdate parameter ++ public void c(EnumHand enumhand) { this.updateActiveItem(enumhand, false); } ++ public void updateActiveItem(EnumHand enumhand, boolean forceUpdate) { ++ // Paper end + ItemStack itemstack = this.b(enumhand); + +- if (!itemstack.isEmpty() && !this.isHandRaised()) { ++ if (!itemstack.isEmpty() && !this.isHandRaised() || forceUpdate) { // Paper use override flag + this.activeItem = itemstack; + this.bd = itemstack.k(); + if (!this.world.isClientSide) { +@@ -3282,6 +3285,7 @@ public abstract class EntityLiving extends Entity { + this.releaseActiveItem(); + } else { + if (!this.activeItem.isEmpty() && this.isHandRaised()) { ++ this.updateActiveItem(this.getRaisedHand(), true); // Paper + this.b(this.activeItem, 16); + // CraftBukkit start - fire PlayerItemConsumeEvent + ItemStack itemstack; +@@ -3316,8 +3320,8 @@ public abstract class EntityLiving extends Entity { + } + + this.clearActiveItem(); +- // Paper start - if the replacement is anything but the default, update the client inventory +- if (this instanceof EntityPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { ++ // Paper start ++ if (this instanceof EntityPlayer) { + ((EntityPlayer) this).getBukkitEntity().updateInventory(); + } + // Paper end diff --git a/patches/server-unmapped/0376-Generator-Settings.patch b/patches/server-unmapped/0376-Generator-Settings.patch new file mode 100644 index 0000000000..35a2520f5f --- /dev/null +++ b/patches/server-unmapped/0376-Generator-Settings.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 2 Mar 2016 02:17:54 -0600 +Subject: [PATCH] Generator Settings + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6aec502eb529d4090306e12e837117cde7e114eb..290e49cf0077909ad7ab8127c01ef93cf7b70b51 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -570,4 +570,9 @@ public class PaperWorldConfig { + private void perPlayerMobSpawns() { + perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); + } ++ ++ public boolean generateFlatBedrock; ++ private void generatorSettings() { ++ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java +index e570dc58efa56bd0aa5ada5575b4054ee38d505e..cdf612d7553a8f4aaebb5e0e66bd2a47a280457a 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java +@@ -25,6 +25,18 @@ import org.apache.logging.log4j.LogManager; + + public interface IChunkAccess extends IBlockAccess, IStructureAccess { + ++ // Paper start ++ default boolean generateFlatBedrock() { ++ if (this instanceof ProtoChunk) { ++ return ((ProtoChunk)this).world.paperConfig.generateFlatBedrock; ++ } else if (this instanceof Chunk) { ++ return ((Chunk)this).world.paperConfig.generateFlatBedrock; ++ } else { ++ return false; ++ } ++ } ++ // Paper end ++ + IBlockData getType(final int x, final int y, final int z); // Paper + @Nullable + IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index 9b308a10554b037ede0c455fbd3e906021218ddc..7bfac4e852c4a6697435647dab173913df6034e9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -64,7 +64,7 @@ public class ProtoChunk implements IChunkAccess { + private long s; + private final Map t; + private volatile boolean u; +- private final World world; // Paper - Anti-Xray - Add world ++ final World world; // Paper - Anti-Xray - Add world // Paper - private -> default + + // Paper start - Anti-Xray - Add world + @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { this(chunkcoordintpair, chunkconverter, null); } // Notice for updates: Please make sure this constructor isn't used anywhere +diff --git a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java +index b137d65953fe1e44709e9a6dab3a4533df644d06..700b32322e8d0fbb8ec2824e50a340be16b48f81 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java +@@ -408,8 +408,8 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + int i = ichunkaccess.getPos().d(); + int j = ichunkaccess.getPos().e(); + GeneratorSettingBase generatorsettingbase = (GeneratorSettingBase) this.h.get(); +- int k = generatorsettingbase.f(); +- int l = this.x - 1 - generatorsettingbase.e(); ++ int k = generatorsettingbase.f(); final int floorHeight = k; // Paper ++ int l = this.x - 1 - generatorsettingbase.e(); final int roofHeight = l; // Paper + boolean flag = true; + boolean flag1 = l + 4 >= 0 && l < this.x; + boolean flag2 = k + 4 >= 0 && k < this.x; +@@ -423,7 +423,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + + if (flag1) { + for (i1 = 0; i1 < 5; ++i1) { +- if (i1 <= random.nextInt(5)) { ++ if (i1 <= (ichunkaccess.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof + ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), l - i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false); + } + } +@@ -431,7 +431,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + + if (flag2) { + for (i1 = 4; i1 >= 0; --i1) { +- if (i1 <= random.nextInt(5)) { ++ if (i1 <= (ichunkaccess.generateFlatBedrock() ? floorHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor + ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), k + i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false); + } + } diff --git a/patches/server-unmapped/0377-Fix-MC-161754.patch b/patches/server-unmapped/0377-Fix-MC-161754.patch new file mode 100644 index 0000000000..8ef2ece0bd --- /dev/null +++ b/patches/server-unmapped/0377-Fix-MC-161754.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 24 Sep 2019 16:03:00 -0700 +Subject: [PATCH] Fix MC-161754 + +Fixes https://github.com/PaperMC/Paper/issues/2580 + +We can use an entity valid check since this method is invoked for +each inventory iteraction (thanks to CB) and on player tick (vanilla). + +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerHorse.java b/src/main/java/net/minecraft/world/inventory/ContainerHorse.java +index ecabe8e52865b71b6f89d09850b37741e7e79b50..ea64ef313a8378fa7dee086e137e1e5f43376804 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerHorse.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerHorse.java +@@ -85,7 +85,7 @@ public class ContainerHorse extends Container { + + @Override + public boolean canUse(EntityHuman entityhuman) { +- return this.c.a(entityhuman) && this.d.isAlive() && this.d.g((Entity) entityhuman) < 8.0F; ++ return this.c.a(entityhuman) && (this.d.isAlive() && this.d.valid) && this.d.g((Entity) entityhuman) < 8.0F; // Paper - Fix MC-161754 + } + + @Override diff --git a/patches/server-unmapped/0378-Performance-improvement-for-Chunk.getEntities.patch b/patches/server-unmapped/0378-Performance-improvement-for-Chunk.getEntities.patch new file mode 100644 index 0000000000..0b09feb060 --- /dev/null +++ b/patches/server-unmapped/0378-Performance-improvement-for-Chunk.getEntities.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: wea_ondara +Date: Thu, 10 Oct 2019 11:29:42 +0200 +Subject: [PATCH] Performance improvement for Chunk.getEntities + +This patch aims to reduce performance cost used by collecting the +entities of a chunk. Previously the entitySlices were copied into an +extra array with List.toArray() with is a costly and unneccessary +operation. This patch will reduce the load of plugins which for example +implement custom moblimits and depend on Chunk.getEntities(). + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +index c36f55f178166eb099cc5c64784be5a9f4750199..8ade81a693286cdf65f8c0eeca2121a217c90350 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +@@ -117,14 +117,14 @@ public class CraftChunk implements Chunk { + Entity[] entities = new Entity[count]; + + for (int i = 0; i < 16; i++) { +- +- for (Object obj : chunk.entitySlices[i].toArray()) { +- if (!(obj instanceof net.minecraft.world.entity.Entity)) { ++ // Paper start - speed up (was with chunk.entitySlices[i].toArray() and cast checks which costs a lot of performance if called often) ++ for (net.minecraft.world.entity.Entity entity : chunk.entitySlices[i]) { ++ if (entity == null) { + continue; + } +- +- entities[index++] = ((net.minecraft.world.entity.Entity) obj).getBukkitEntity(); ++ entities[index++] = entity.getBukkitEntity(); + } ++ // Paper end + } + + return entities; diff --git a/patches/server-unmapped/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/patches/server-unmapped/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch new file mode 100644 index 0000000000..225102e634 --- /dev/null +++ b/patches/server-unmapped/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MisterErwin +Date: Wed, 30 Oct 2019 16:57:54 +0100 +Subject: [PATCH] Fix spawning of hanging entities that are not ItemFrames and + can not face UP or DOWN + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 6aaf868cf3213e1935080c64c652c3055cb58e0c..fcad64fcfc22af227be19741b634b773aca7a98d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1886,7 +1886,12 @@ public class CraftWorld implements World { + height = 9; + } + +- BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; ++ // Paper start - In addition to d65a2576e40e58c8e446b330febe6799d13a604f do not check UP/DOWN for non item frames ++ // BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; ++ BlockFace[] faces = (ItemFrame.class.isAssignableFrom(clazz)) ++ ? new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN} ++ : new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH}; ++ // Paper end + final BlockPosition pos = new BlockPosition(x, y, z); + for (BlockFace dir : faces) { + IBlockData nmsBlock = world.getType(pos.shift(CraftBlock.blockFaceToNotch(dir))); diff --git a/patches/server-unmapped/0380-Expose-the-internal-current-tick.patch b/patches/server-unmapped/0380-Expose-the-internal-current-tick.patch new file mode 100644 index 0000000000..336ed3d11d --- /dev/null +++ b/patches/server-unmapped/0380-Expose-the-internal-current-tick.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 20 Apr 2019 19:47:34 -0500 +Subject: [PATCH] Expose the internal current tick + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 40ed419457982e1dae1605915aeccd10703df57b..b76da976d8710d9e91b8b00fa3b888adfc791dc3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2364,5 +2364,10 @@ public final class CraftServer implements Server { + } + return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); + } ++ ++ @Override ++ public int getCurrentTick() { ++ return net.minecraft.server.MinecraftServer.currentTick; ++ } + // Paper end + } diff --git a/patches/server-unmapped/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/patches/server-unmapped/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch new file mode 100644 index 0000000000..5535fda04e --- /dev/null +++ b/patches/server-unmapped/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 9 Oct 2019 21:51:43 -0500 +Subject: [PATCH] Fix stuck in sneak when changing worlds (MC-10657) + + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index f0c3bfb0e641b9f1a22fb6873ab3645be6e481c4..a0c426afaa7a18f7596d56699f02dcd665f7aa9d 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1073,6 +1073,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.lastHealthSent = -1.0F; + this.lastFoodSent = -1; + ++ setSneaking(false); // Paper - fix MC-10657 ++ + // CraftBukkit start + PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); + this.world.getServer().getPluginManager().callEvent(changeEvent); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 553b14f7167673938d1bc83d79c730692a4ef105..9af1d81475d2def60a682ed23e88f1afbbc4c7e6 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -846,6 +846,8 @@ public abstract class PlayerList { + entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityEffect(entityplayer.getId(), mobEffect)); + } + ++ entityplayer.setSneaking(false); // Paper - fix MC-10657 ++ + // Fire advancement trigger + entityplayer.triggerDimensionAdvancements(((CraftWorld) fromWorld).getHandle()); + diff --git a/patches/server-unmapped/0382-Add-option-to-disable-pillager-patrols.patch b/patches/server-unmapped/0382-Add-option-to-disable-pillager-patrols.patch new file mode 100644 index 0000000000..7adaa55dec --- /dev/null +++ b/patches/server-unmapped/0382-Add-option-to-disable-pillager-patrols.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 9 Oct 2019 21:46:15 -0500 +Subject: [PATCH] Add option to disable pillager patrols + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 290e49cf0077909ad7ab8127c01ef93cf7b70b51..e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -575,4 +575,9 @@ public class PaperWorldConfig { + private void generatorSettings() { + generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); + } ++ ++ public boolean disablePillagerPatrols = false; ++ private void pillagerSettings() { ++ disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java +index 04a1af9c6742f7aa944dec80e75ff8a4ca4bf57f..cba98adb7f2711fb97c7e4120d962f46a59682e7 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java +@@ -26,6 +26,7 @@ public class MobSpawnerPatrol implements MobSpawner { + + @Override + public int a(WorldServer worldserver, boolean flag, boolean flag1) { ++ if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper + if (!flag) { + return 0; + } else if (!worldserver.getGameRules().getBoolean(GameRules.DO_PATROL_SPAWNING)) { diff --git a/patches/server-unmapped/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/patches/server-unmapped/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch new file mode 100644 index 0000000000..904f78b816 --- /dev/null +++ b/patches/server-unmapped/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lukasz Derlatka +Date: Mon, 11 Nov 2019 16:08:13 +0100 +Subject: [PATCH] Fix AssertionError when player hand set to empty type + +Fixes an AssertionError when setting the player's item in hand to null or a new ItemStack of Air in PlayerInteractEvent +Fixes GH-2718 + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 24dfdb3807dbf6e9acc59d35d7c76f7ac0185219..72df753d8c8e12cb3efaa02f37b05496701cc9f9 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1708,6 +1708,10 @@ public class PlayerConnection implements PacketListenerPlayIn { + this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 + return; + } ++ // Paper start ++ itemstack = this.player.getItemInHand(enumhand); ++ if (itemstack.isEmpty()) return; ++ // Paper end + EnumInteractionResult enuminteractionresult = this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand); + + if (enuminteractionresult.b()) { +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 48f932b2e049741ebee5824e158e4bda87d42faf..cd880fb9e61dad7dff185d0b4fa2b8c5dee04861 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -2156,6 +2156,7 @@ public abstract class EntityLiving extends Entity { + return predicate.test(this.getItemInMainHand().getItem()) || predicate.test(this.getItemInOffHand().getItem()); + } + ++ public final ItemStack getItemInHand(EnumHand enumhand) { return this.b(enumhand); } // Paper - OBFHELPER + public ItemStack b(EnumHand enumhand) { + if (enumhand == EnumHand.MAIN_HAND) { + return this.getEquipment(EnumItemSlot.MAINHAND); diff --git a/patches/server-unmapped/0384-PlayerLaunchProjectileEvent.patch b/patches/server-unmapped/0384-PlayerLaunchProjectileEvent.patch new file mode 100644 index 0000000000..ceeb9bcd0e --- /dev/null +++ b/patches/server-unmapped/0384-PlayerLaunchProjectileEvent.patch @@ -0,0 +1,329 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 03:11:03 -0500 +Subject: [PATCH] PlayerLaunchProjectileEvent + + +diff --git a/src/main/java/net/minecraft/world/InteractionResultWrapper.java b/src/main/java/net/minecraft/world/InteractionResultWrapper.java +index dd17c111670e637b574f5c7f38d27848900ce194..8cecc3d909a51b1892b4a299a5e6ec3518db9b39 100644 +--- a/src/main/java/net/minecraft/world/InteractionResultWrapper.java ++++ b/src/main/java/net/minecraft/world/InteractionResultWrapper.java +@@ -10,6 +10,7 @@ public class InteractionResultWrapper { + this.b = t0; + } + ++ public EnumInteractionResult getResult() { return this.a(); } // Paper - OBFHELPER + public EnumInteractionResult a() { + return this.a; + } +diff --git a/src/main/java/net/minecraft/world/item/ItemEgg.java b/src/main/java/net/minecraft/world/item/ItemEgg.java +index 2083ab6e0dc7e48d409a5ee33e712e34abd6f6bf..4b1a6ee784da4595931396a905f1358b7a13f3dd 100644 +--- a/src/main/java/net/minecraft/world/item/ItemEgg.java ++++ b/src/main/java/net/minecraft/world/item/ItemEgg.java +@@ -25,21 +25,35 @@ public class ItemEgg extends Item { + + entityegg.setItem(itemstack); + entityegg.a(entityhuman, entityhuman.pitch, entityhuman.yaw, 0.0F, 1.5F, 1.0F); +- // CraftBukkit start +- if (!world.addEntity(entityegg)) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityegg.getBukkitEntity()); ++ if (event.callEvent() && world.addEntity(entityegg)) { ++ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { ++ itemstack.subtract(1); ++ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { ++ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ entityhuman.b(StatisticList.ITEM_USED.b(this)); ++ } else { + if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { + ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); + } +- return InteractionResultWrapper.fail(itemstack); ++ return new InteractionResultWrapper(net.minecraft.world.EnumInteractionResult.FAIL, itemstack); + } +- // CraftBukkit end ++ // Paper end ++ ++ + } + world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemEgg.RANDOM.nextFloat() * 0.4F + 0.8F)); // CraftBukkit - from above + ++ /* // Paper start - moved up + entityhuman.b(StatisticList.ITEM_USED.b(this)); + if (!entityhuman.abilities.canInstantlyBuild) { + itemstack.subtract(1); + } ++ */ // Paper end + + return InteractionResultWrapper.a(itemstack, world.s_()); + } +diff --git a/src/main/java/net/minecraft/world/item/ItemEnderPearl.java b/src/main/java/net/minecraft/world/item/ItemEnderPearl.java +index 5349282b9a5b43c4c3539e1677971463e2ca5a17..9896d77381e7fadf1ef2619210713e190c1445d0 100644 +--- a/src/main/java/net/minecraft/world/item/ItemEnderPearl.java ++++ b/src/main/java/net/minecraft/world/item/ItemEnderPearl.java +@@ -25,22 +25,37 @@ public class ItemEnderPearl extends Item { + + entityenderpearl.setItem(itemstack); + entityenderpearl.a(entityhuman, entityhuman.pitch, entityhuman.yaw, 0.0F, 1.5F, 1.0F); +- if (!world.addEntity(entityenderpearl)) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityenderpearl.getBukkitEntity()); ++ if (event.callEvent() && world.addEntity(entityenderpearl)) { ++ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { ++ itemstack.subtract(1); ++ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { ++ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ entityhuman.b(StatisticList.ITEM_USED.b(this)); ++ entityhuman.getCooldownTracker().setCooldown(this, 20); ++ } else { ++ // Paper end + if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { + ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); + } +- return InteractionResultWrapper.fail(itemstack); ++ return new InteractionResultWrapper(net.minecraft.world.EnumInteractionResult.FAIL, itemstack); + } + } + +- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F)); +- entityhuman.getCooldownTracker().setCooldown(this, 20); +- // CraftBukkit end +- +- entityhuman.b(StatisticList.ITEM_USED.b(this)); +- if (!entityhuman.abilities.canInstantlyBuild) { +- itemstack.subtract(1); +- } ++ // Paper start - moved up ++// world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F)); ++// entityhuman.getCooldownTracker().setCooldown(this, 20); ++// // CraftBukkit end ++// ++// entityhuman.b(StatisticList.ITEM_USED.b(this)); ++// if (!entityhuman.abilities.canInstantlyBuild) { ++// itemstack.subtract(1); ++// } ++ // Paper end - moved up + + return InteractionResultWrapper.a(itemstack, world.s_()); + } +diff --git a/src/main/java/net/minecraft/world/item/ItemExpBottle.java b/src/main/java/net/minecraft/world/item/ItemExpBottle.java +index 3f41fe5bf1a0cc283d6a72824779026fdad75708..cf36ec4769dc316e3ed16262043cb78cbba340ab 100644 +--- a/src/main/java/net/minecraft/world/item/ItemExpBottle.java ++++ b/src/main/java/net/minecraft/world/item/ItemExpBottle.java +@@ -1,10 +1,13 @@ + package net.minecraft.world.item; + ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.stats.StatisticList; + import net.minecraft.world.EnumHand; ++import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.InteractionResultWrapper; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.projectile.EntityThrownExpBottle; + import net.minecraft.world.level.World; +@@ -24,19 +27,38 @@ public class ItemExpBottle extends Item { + public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { + ItemStack itemstack = entityhuman.b(enumhand); + +- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); ++ //world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); // Paper - moved down + if (!world.isClientSide) { + EntityThrownExpBottle entitythrownexpbottle = new EntityThrownExpBottle(world, entityhuman); + + entitythrownexpbottle.setItem(itemstack); + entitythrownexpbottle.a(entityhuman, entityhuman.pitch, entityhuman.yaw, -20.0F, 0.7F, 1.0F); +- world.addEntity(entitythrownexpbottle); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitythrownexpbottle.getBukkitEntity()); ++ if (event.callEvent() && world.addEntity(entitythrownexpbottle)) { ++ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { ++ itemstack.subtract(1); ++ } else if (entityhuman instanceof EntityPlayer) { ++ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ entityhuman.b(StatisticList.ITEM_USED.b(this)); ++ } else { ++ if (entityhuman instanceof EntityPlayer) { ++ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return new InteractionResultWrapper(EnumInteractionResult.FAIL, itemstack); ++ } ++ // Paper end + } + ++ /* // Paper start - moved up + entityhuman.b(StatisticList.ITEM_USED.b(this)); + if (!entityhuman.abilities.canInstantlyBuild) { + itemstack.subtract(1); + } ++ */ // Paper end + + return InteractionResultWrapper.a(itemstack, world.s_()); + } +diff --git a/src/main/java/net/minecraft/world/item/ItemFireworks.java b/src/main/java/net/minecraft/world/item/ItemFireworks.java +index 79e9be800385b94c4493bd8970620d76bfbd65ae..e7f958d137257da912ce9b83db017b4423959943 100644 +--- a/src/main/java/net/minecraft/world/item/ItemFireworks.java ++++ b/src/main/java/net/minecraft/world/item/ItemFireworks.java +@@ -3,6 +3,7 @@ package net.minecraft.world.item; + import java.util.Arrays; + import java.util.Comparator; + import net.minecraft.core.EnumDirection; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.world.EnumHand; + import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.InteractionResultWrapper; +@@ -29,8 +30,12 @@ public class ItemFireworks extends Item { + EntityFireworks entityfireworks = new EntityFireworks(world, itemactioncontext.getEntity(), vec3d.x + (double) enumdirection.getAdjacentX() * 0.15D, vec3d.y + (double) enumdirection.getAdjacentY() * 0.15D, vec3d.z + (double) enumdirection.getAdjacentZ() * 0.15D, itemstack); + entityfireworks.spawningEntity = itemactioncontext.getEntity().getUniqueID(); // Paper + +- world.addEntity(entityfireworks); +- itemstack.subtract(1); ++ // Paper start - PlayerLaunchProjectileEvent ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) itemactioncontext.getEntity().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); ++ if (!event.callEvent() || !world.addEntity(entityfireworks)) return EnumInteractionResult.PASS; ++ if (event.shouldConsume() && !itemactioncontext.getEntity().abilities.canInstantlyBuild) itemstack.subtract(1); ++ else if (itemactioncontext.getEntity() instanceof EntityPlayer) ((EntityPlayer) itemactioncontext.getEntity()).getBukkitEntity().updateInventory(); ++ // Paper end + } + + return EnumInteractionResult.a(world.isClientSide); +diff --git a/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java b/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java +index a75f374f0639e8143772aa863666afe25d2020cf..0e073a8c23d24afb8b0198a9cfd8dc7d0b9d0a6b 100644 +--- a/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java ++++ b/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java +@@ -3,6 +3,7 @@ package net.minecraft.world.item; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.EnumHand; ++import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.InteractionResultWrapper; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.level.World; +@@ -15,7 +16,12 @@ public class ItemLingeringPotion extends ItemPotionThrowable { + + @Override + public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { +- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_LINGERING_POTION_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemLingeringPotion.RANDOM.nextFloat() * 0.4F + 0.8F)); +- return super.a(world, entityhuman, enumhand); ++ // Paper start ++ InteractionResultWrapper wrapper = super.a(world, entityhuman, enumhand); ++ if (wrapper.getResult() != EnumInteractionResult.FAIL) { ++ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_LINGERING_POTION_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemLingeringPotion.RANDOM.nextFloat() * 0.4F + 0.8F)); ++ } ++ return wrapper; ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java b/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java +index d050243946ad7023d5dd3958d7056cddcaf185a4..27c61fc4e61b0d76565ca6893514b3c73247c954 100644 +--- a/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java ++++ b/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java +@@ -1,7 +1,9 @@ + package net.minecraft.world.item; + ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.stats.StatisticList; + import net.minecraft.world.EnumHand; ++import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.InteractionResultWrapper; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.projectile.EntityPotion; +@@ -22,13 +24,31 @@ public class ItemPotionThrowable extends ItemPotion { + + entitypotion.setItem(itemstack); + entitypotion.a(entityhuman, entityhuman.pitch, entityhuman.yaw, -20.0F, 0.5F, 1.0F); +- world.addEntity(entitypotion); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitypotion.getBukkitEntity()); ++ if (event.callEvent() && world.addEntity(entitypotion)) { ++ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { ++ itemstack.subtract(1); ++ } else if (entityhuman instanceof EntityPlayer) { ++ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ ++ entityhuman.b(StatisticList.ITEM_USED.b(this)); ++ } else { ++ if (entityhuman instanceof EntityPlayer) { ++ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return new InteractionResultWrapper(EnumInteractionResult.FAIL, itemstack); ++ } ++ // Paper end + } + ++ /* // Paper start - moved up + entityhuman.b(StatisticList.ITEM_USED.b(this)); + if (!entityhuman.abilities.canInstantlyBuild) { + itemstack.subtract(1); + } ++ */ // Paper end + + return InteractionResultWrapper.a(itemstack, world.s_()); + } +diff --git a/src/main/java/net/minecraft/world/item/ItemSnowball.java b/src/main/java/net/minecraft/world/item/ItemSnowball.java +index e5200b2a7d6d5c2d549e585ed157ec5217edae8e..8a1d59cb1ea5a8959c52272aa762ec35307246d7 100644 +--- a/src/main/java/net/minecraft/world/item/ItemSnowball.java ++++ b/src/main/java/net/minecraft/world/item/ItemSnowball.java +@@ -26,14 +26,20 @@ public class ItemSnowball extends Item { + + entitysnowball.setItem(itemstack); + entitysnowball.a(entityhuman, entityhuman.pitch, entityhuman.yaw, 0.0F, 1.5F, 1.0F); +- if (world.addEntity(entitysnowball)) { +- if (!entityhuman.abilities.canInstantlyBuild) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity()); ++ if (event.callEvent() && world.addEntity(entitysnowball)) { ++ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { ++ // Paper end + itemstack.subtract(1); ++ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { // Paper ++ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // Paper + } + + world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemSnowball.RANDOM.nextFloat() * 0.4F + 0.8F)); +- } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { +- ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } else { // Paper ++ if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // Paper ++ return new InteractionResultWrapper(net.minecraft.world.EnumInteractionResult.FAIL, itemstack); // Paper + } + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/item/ItemSplashPotion.java b/src/main/java/net/minecraft/world/item/ItemSplashPotion.java +index 98f29fac4bf087ad15f1cc7e85b408e22ec07efd..971491a461ccb7a707c6ca1a5b7c16d8823a7a80 100644 +--- a/src/main/java/net/minecraft/world/item/ItemSplashPotion.java ++++ b/src/main/java/net/minecraft/world/item/ItemSplashPotion.java +@@ -3,6 +3,7 @@ package net.minecraft.world.item; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.EnumHand; ++import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.InteractionResultWrapper; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.level.World; +@@ -15,7 +16,12 @@ public class ItemSplashPotion extends ItemPotionThrowable { + + @Override + public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { ++ // Paper start ++ InteractionResultWrapper wrapper = super.a(world, entityhuman, enumhand); ++ if (wrapper.getResult() != EnumInteractionResult.FAIL) { + world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SPLASH_POTION_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemSplashPotion.RANDOM.nextFloat() * 0.4F + 0.8F)); +- return super.a(world, entityhuman, enumhand); ++ } ++ return wrapper; ++ // Paper end + } + } diff --git a/patches/server-unmapped/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch b/patches/server-unmapped/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch new file mode 100644 index 0000000000..abf6eb1d92 --- /dev/null +++ b/patches/server-unmapped/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BlackHole +Date: Sun, 15 Dec 2019 19:12:39 +0100 +Subject: [PATCH] Add CraftMagicNumbers.isSupportedApiVersion() + + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 8aa9e7796ea39c09a965750d06c3d358250f33b8..7e4cceff7ce9ffaff00caf21088fd7bc59e66933 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -375,6 +375,11 @@ public final class CraftMagicNumbers implements UnsafeValues { + public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { + return new com.destroystokyo.paper.PaperVersionFetcher(); + } ++ ++ @Override ++ public boolean isSupportedApiVersion(String apiVersion) { ++ return apiVersion != null && SUPPORTED_API.contains(apiVersion); ++ } + // Paper end + + /** diff --git a/patches/server-unmapped/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/patches/server-unmapped/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch new file mode 100644 index 0000000000..0188a5ae7f --- /dev/null +++ b/patches/server-unmapped/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Callahan +Date: Mon, 13 Jan 2020 23:47:28 -0600 +Subject: [PATCH] Prevent sync chunk loads when villagers try to find beds + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java +index 84eba4c91e8e608b84623d6c71233e2512b77a54..ce86301723d20e79f95207cce1084bac091742fe 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java +@@ -46,7 +46,8 @@ public class BehaviorSleep extends Behavior { + } + } + +- IBlockData iblockdata = worldserver.getType(globalpos.getBlockPosition()); ++ IBlockData iblockdata = worldserver.getTypeIfLoaded(globalpos.getBlockPosition()); // Paper ++ if (iblockdata == null) { return false; } // Paper + + return globalpos.getBlockPosition().a((IPosition) entityliving.getPositionVector(), 2.0D) && iblockdata.getBlock().a((Tag) TagsBlock.BEDS) && !(Boolean) iblockdata.get(BlockBed.OCCUPIED); + } diff --git a/patches/server-unmapped/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch b/patches/server-unmapped/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch new file mode 100644 index 0000000000..342a7deea1 --- /dev/null +++ b/patches/server-unmapped/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 18 Dec 2019 22:21:35 -0600 +Subject: [PATCH] MC-145656 Fix Follow Range Initial Target + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5..edda2121f8c1046478beaa77030ebb36d403b334 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -580,4 +580,9 @@ public class PaperWorldConfig { + private void pillagerSettings() { + disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); + } ++ ++ public boolean entitiesTargetWithFollowRange = false; ++ private void entitiesTargetWithFollowRange() { ++ entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java +index 4f0a2cbdd6d42e3e4721345e21bf0ef33ec48e1e..44f21c3f7af17e9d39777a48c6715a22fc085da6 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java +@@ -32,6 +32,7 @@ public class PathfinderGoalNearestAttackableTarget exten + this.b = i; + this.a(EnumSet.of(PathfinderGoal.Type.TARGET)); + this.d = (new PathfinderTargetCondition()).a(this.k()).a(predicate); ++ if (entityinsentient.world.paperConfig.entitiesTargetWithFollowRange) this.d.useFollowRange(); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java +index 0de32bcf24a94efe5af922b877d4cdc3578e0cbd..e6988f7ea428f1503e3db63876b13e57f898ee30 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java ++++ b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java +@@ -4,6 +4,8 @@ import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.world.entity.EntityInsentient; + import net.minecraft.world.entity.EntityLiving; ++import net.minecraft.world.entity.ai.attributes.AttributeModifiable; ++import net.minecraft.world.entity.ai.attributes.GenericAttributes; + + public class PathfinderTargetCondition { + +@@ -82,7 +84,7 @@ public class PathfinderTargetCondition { + + if (this.b > 0.0D) { + double d0 = this.g ? entityliving1.A(entityliving) : 1.0D; +- double d1 = Math.max(this.b * d0, 2.0D); ++ double d1 = Math.max((useFollowRange ? getFollowRange(entityliving) : this.b) * d0, 2.0D); // Paper + double d2 = entityliving.h(entityliving1.locX(), entityliving1.locY(), entityliving1.locZ()); + + if (d2 > d1 * d1) { +@@ -98,4 +100,18 @@ public class PathfinderTargetCondition { + return true; + } + } ++ ++ // Paper start ++ private boolean useFollowRange = false; ++ ++ public PathfinderTargetCondition useFollowRange() { ++ this.useFollowRange = true; ++ return this; ++ } ++ ++ private double getFollowRange(EntityLiving entityliving) { ++ AttributeModifiable attributeinstance = entityliving.getAttributeInstance(GenericAttributes.FOLLOW_RANGE); ++ return attributeinstance == null ? 16.0D : attributeinstance.getValue(); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0388-Optimize-Hoppers.patch b/patches/server-unmapped/0388-Optimize-Hoppers.patch new file mode 100644 index 0000000000..52b5dc57f2 --- /dev/null +++ b/patches/server-unmapped/0388-Optimize-Hoppers.patch @@ -0,0 +1,517 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 27 Apr 2016 22:09:52 -0400 +Subject: [PATCH] Optimize Hoppers + +* Removes unnecessary extra calls to .update() that are very expensive +* Lots of itemstack cloning removed. Only clone if the item is actually moved +* Return true when a plugin cancels inventory move item event instead of false, as false causes pulls to cycle through all items. + However, pushes do not exhibit the same behavior, so this is not something plugins could of been relying on. +* Add option (Default on) to cooldown hoppers when they fail to move an item due to full inventory +* Skip subsequent InventoryMoveItemEvents if a plugin does not use the item after first event fire for an iteration +* Don't check for Entities with Inventories if the block above us is also occluding (not just Inventoried) +* Remove Streams from Item Suck In and restore restore 1.12 AABB checks which is simpler and no voxel allocations (was doing TWO Item Suck ins) + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index edda2121f8c1046478beaa77030ebb36d403b334..7fbd501d70dccf869a4454e2789a5d68f2e15754 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -585,4 +585,13 @@ public class PaperWorldConfig { + private void entitiesTargetWithFollowRange() { + entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); + } ++ ++ public boolean cooldownHopperWhenFull = true; ++ public boolean disableHopperMoveEvents = false; ++ private void hopperOptimizations() { ++ cooldownHopperWhenFull = getBoolean("hopper.cooldown-when-full", cooldownHopperWhenFull); ++ log("Cooldown Hoppers when Full: " + (cooldownHopperWhenFull ? "enabled" : "disabled")); ++ disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); ++ log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index eb134ccb68dc135ab6db4c5a1d29edb321cf3f59..566b7c88ca467a92bcba2665edb852f77f8acd1e 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -129,6 +129,7 @@ import net.minecraft.world.level.WorldSettings; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.biome.WorldChunkManager; + import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.entity.TileEntityHopper; + import net.minecraft.world.level.border.IWorldBorderListener; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.chunk.ChunkGenerator; +@@ -1362,6 +1363,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper ++ TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + + this.methodProfiler.a(() -> { + return worldserver + " " + worldserver.getDimensionKey().a(); +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 852f9d99001b35f8c97f4445d8f605533d7f6f2f..7b1df591007b9c50bcaf4bcd30562396a9549193 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -540,11 +540,12 @@ public final class ItemStack { + return this.getItem().a(this, entityhuman, entityliving, enumhand); + } + +- public ItemStack cloneItemStack() { +- if (this.isEmpty()) { ++ public ItemStack cloneItemStack() { return cloneItemStack(false); } // Paper ++ public ItemStack cloneItemStack(boolean origItem) { // Paper ++ if (!origItem && this.isEmpty()) { // Paper + return ItemStack.b; + } else { +- ItemStack itemstack = new ItemStack(this.getItem(), this.count); ++ ItemStack itemstack = new ItemStack(origItem ? this.item : this.getItem(), this.count); // Paper + + itemstack.d(this.D()); + if (this.tag != null) { +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 6781b25cc8e15be2556bb1bb8dc8c18c106b40ec..d1738b57efd3f5e6c51603553a773173e4b09bb5 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -1162,8 +1162,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return list; + } + +- @Override +- public List a(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { ++ public List getEntities(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { return a(oclass, axisalignedbb, predicate); } // Paper - OBFHELPER ++ @Override public List a(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { + this.getMethodProfiler().c("getEntities"); + int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D); + int j = MathHelper.f((axisalignedbb.maxX + 2.0D) / 16.0D); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/IHopper.java b/src/main/java/net/minecraft/world/level/block/entity/IHopper.java +index d0943ae1f372784716195666212ff83e6ee4873e..1db7b7bfe98658d0b20800a4178556f8daaf881a 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/IHopper.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/IHopper.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block.entity; + + import javax.annotation.Nullable; ++import net.minecraft.core.BlockPosition; + import net.minecraft.world.IInventory; + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.Block; +@@ -17,12 +18,13 @@ public interface IHopper extends IInventory { + return IHopper.c; + } + +- @Nullable ++ //@Nullable // Paper - it's annoying + World getWorld(); ++ default BlockPosition getBlockPosition() { return new BlockPosition(getX(), getY(), getZ()); } // Paper + +- double x(); ++ double x(); default double getX() { return this.x(); } // Paper - OBFHELPER + +- double z(); ++ double z(); default double getY() { return this.z(); } // Paper - OBFHELPER + +- double A(); ++ double A(); default double getZ() { return this.A(); } // Paper - OBFHELPER + } +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +index 48daa039ffa8ccb7b6f3ca47bdc56394addf9254..f1e586754396439dfb70a4d63e3b8b34fb36ebf4 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +@@ -77,6 +77,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / + public void setCurrentChunk(Chunk chunk) { + this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; + } ++ static boolean IGNORE_TILE_UPDATES = false; + // Paper end + + @Nullable +@@ -155,6 +156,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / + + public void update() { + if (this.world != null) { ++ if (IGNORE_TILE_UPDATES) return; // Paper + this.c = this.world.getType(this.position); + this.world.b(this.position, this); + if (!this.c.isAir()) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java +index 5fe715e8dbe9d925170acce6e0f18312d9f998f2..537dc52e5ff3325555ee6049bc7f277952983b76 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java +@@ -196,6 +196,160 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + return false; + } + ++ // Paper start - Optimize Hoppers ++ private static boolean skipPullModeEventFire = false; ++ private static boolean skipPushModeEventFire = false; ++ public static boolean skipHopperEvents = false; ++ ++ private boolean hopperPush(IInventory iinventory, EnumDirection enumdirection) { ++ skipPushModeEventFire = skipHopperEvents; ++ boolean foundItem = false; ++ for (int i = 0; i < this.getSize(); ++i) { ++ ItemStack item = this.getItem(i); ++ if (!item.isEmpty()) { ++ foundItem = true; ++ ItemStack origItemStack = item; ++ ItemStack itemstack = origItemStack; ++ ++ final int origCount = origItemStack.getCount(); ++ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); ++ origItemStack.setCount(moved); ++ ++ // We only need to fire the event once to give protection plugins a chance to cancel this event ++ // Because nothing uses getItem, every event call should end up the same result. ++ if (!skipPushModeEventFire) { ++ itemstack = callPushMoveEvent(iinventory, itemstack); ++ if (itemstack == null) { // cancelled ++ origItemStack.setCount(origCount); ++ return false; ++ } ++ } ++ final ItemStack itemstack2 = addItem(this, iinventory, itemstack, enumdirection); ++ final int remaining = itemstack2.getCount(); ++ if (remaining != moved) { ++ origItemStack = origItemStack.cloneItemStack(true); ++ origItemStack.setCount(origCount); ++ if (!origItemStack.isEmpty()) { ++ origItemStack.setCount(origCount - moved + remaining); ++ } ++ this.setItem(i, origItemStack); ++ iinventory.update(); ++ return true; ++ } ++ origItemStack.setCount(origCount); ++ } ++ } ++ if (foundItem && world.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown ++ this.setCooldown(world.spigotConfig.hopperTransfer); ++ } ++ return false; ++ } ++ ++ private static boolean hopperPull(IHopper ihopper, IInventory iinventory, ItemStack origItemStack, int i) { ++ ItemStack itemstack = origItemStack; ++ final int origCount = origItemStack.getCount(); ++ final World world = ihopper.getWorld(); ++ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); ++ itemstack.setCount(moved); ++ ++ if (!skipPullModeEventFire) { ++ itemstack = callPullMoveEvent(ihopper, iinventory, itemstack); ++ if (itemstack == null) { // cancelled ++ origItemStack.setCount(origCount); ++ // Drastically improve performance by returning true. ++ // No plugin could of relied on the behavior of false as the other call ++ // site for IMIE did not exhibit the same behavior ++ return true; ++ } ++ } ++ ++ final ItemStack itemstack2 = addItem(iinventory, ihopper, itemstack, null); ++ final int remaining = itemstack2.getCount(); ++ if (remaining != moved) { ++ origItemStack = origItemStack.cloneItemStack(true); ++ origItemStack.setCount(origCount); ++ if (!origItemStack.isEmpty()) { ++ origItemStack.setCount(origCount - moved + remaining); ++ } ++ IGNORE_TILE_UPDATES = true; ++ iinventory.setItem(i, origItemStack); ++ IGNORE_TILE_UPDATES = false; ++ iinventory.update(); ++ return true; ++ } ++ origItemStack.setCount(origCount); ++ ++ if (world.paperConfig.cooldownHopperWhenFull) { ++ cooldownHopper(ihopper); ++ } ++ ++ return false; ++ } ++ ++ private ItemStack callPushMoveEvent(IInventory iinventory, ItemStack itemstack) { ++ Inventory destinationInventory = getInventory(iinventory); ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner(false).getInventory(), ++ CraftItemStack.asCraftMirror(itemstack), destinationInventory, true); ++ boolean result = event.callEvent(); ++ if (!event.calledGetItem && !event.calledSetItem) { ++ skipPushModeEventFire = true; ++ } ++ if (!result) { ++ cooldownHopper(this); ++ return null; ++ } ++ ++ if (event.calledSetItem) { ++ return CraftItemStack.asNMSCopy(event.getItem()); ++ } else { ++ return itemstack; ++ } ++ } ++ ++ private static ItemStack callPullMoveEvent(IHopper hopper, IInventory iinventory, ItemStack itemstack) { ++ Inventory sourceInventory = getInventory(iinventory); ++ Inventory destination = getInventory(hopper); ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, ++ // Mirror is safe as we no plugins ever use this item ++ CraftItemStack.asCraftMirror(itemstack), destination, false); ++ boolean result = event.callEvent(); ++ if (!event.calledGetItem && !event.calledSetItem) { ++ skipPullModeEventFire = true; ++ } ++ if (!result) { ++ cooldownHopper(hopper); ++ return null; ++ } ++ ++ if (event.calledSetItem) { ++ return CraftItemStack.asNMSCopy(event.getItem()); ++ } else { ++ return itemstack; ++ } ++ } ++ ++ private static Inventory getInventory(IInventory iinventory) { ++ Inventory sourceInventory;// Have to special case large chests as they work oddly ++ if (iinventory instanceof InventoryLargeChest) { ++ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); ++ } else if (iinventory instanceof TileEntity) { ++ sourceInventory = ((TileEntity) iinventory).getOwner(false).getInventory(); ++ } else { ++ sourceInventory = iinventory.getOwner().getInventory(); ++ } ++ return sourceInventory; ++ } ++ ++ private static void cooldownHopper(IHopper hopper) { ++ if (hopper instanceof TileEntityHopper) { ++ ((TileEntityHopper) hopper).setCooldown(hopper.getWorld().spigotConfig.hopperTransfer); ++ } else if (hopper instanceof EntityMinecartHopper) { ++ ((EntityMinecartHopper) hopper).setCooldown(hopper.getWorld().spigotConfig.hopperTransfer / 2); ++ } ++ } ++ // Paper end ++ + private boolean k() { + IInventory iinventory = this.l(); + +@@ -207,6 +361,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + if (this.b(iinventory, enumdirection)) { + return false; + } else { ++ return hopperPush(iinventory, enumdirection); /* // Paper - disable rest + for (int i = 0; i < this.getSize(); ++i) { + if (!this.getItem(i).isEmpty()) { + ItemStack itemstack = this.getItem(i).cloneItemStack(); +@@ -244,7 +399,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + } + +- return false; ++ return false;*/ // Paper - end commenting out replaced block for Hopper Optimizations + } + } + } +@@ -253,18 +408,54 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + return iinventory instanceof IWorldInventory ? IntStream.of(((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) : IntStream.range(0, iinventory.getSize()); + } + +- private boolean b(IInventory iinventory, EnumDirection enumdirection) { +- return a(iinventory, enumdirection).allMatch((i) -> { +- ItemStack itemstack = iinventory.getItem(i); ++ private static boolean allMatch(IInventory iinventory, EnumDirection enumdirection, java.util.function.BiPredicate test) { ++ if (iinventory instanceof IWorldInventory) { ++ for (int i : ((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) { ++ if (!test.test(iinventory.getItem(i), i)) { ++ return false; ++ } ++ } ++ } else { ++ int size = iinventory.getSize(); ++ for (int i = 0; i < size; i++) { ++ if (!test.test(iinventory.getItem(i), i)) { ++ return false; ++ } ++ } ++ } ++ return true; ++ } + +- return itemstack.getCount() >= itemstack.getMaxStackSize(); +- }); ++ private static boolean anyMatch(IInventory iinventory, EnumDirection enumdirection, java.util.function.BiPredicate test) { ++ if (iinventory instanceof IWorldInventory) { ++ for (int i : ((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) { ++ if (test.test(iinventory.getItem(i), i)) { ++ return true; ++ } ++ } ++ } else { ++ int size = iinventory.getSize(); ++ for (int i = 0; i < size; i++) { ++ if (test.test(iinventory.getItem(i), i)) { ++ return true; ++ } ++ } ++ } ++ return true; ++ } ++ private static final java.util.function.BiPredicate STACK_SIZE_TEST = (itemstack, i) -> itemstack.getCount() >= itemstack.getMaxStackSize(); ++ private static final java.util.function.BiPredicate IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty(); ++ ++ // Paper end ++ ++ private boolean b(IInventory iinventory, EnumDirection enumdirection) { ++ // Paper start - no streams ++ return allMatch(iinventory, enumdirection, STACK_SIZE_TEST); ++ // Paper end + } + + private static boolean c(IInventory iinventory, EnumDirection enumdirection) { +- return a(iinventory, enumdirection).allMatch((i) -> { +- return iinventory.getItem(i).isEmpty(); +- }); ++ return allMatch(iinventory, enumdirection, IS_EMPTY_TEST); + } + + public static boolean a(IHopper ihopper) { +@@ -273,9 +464,17 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + if (iinventory != null) { + EnumDirection enumdirection = EnumDirection.DOWN; + +- return c(iinventory, enumdirection) ? false : a(iinventory, enumdirection).anyMatch((i) -> { +- return a(ihopper, iinventory, i, enumdirection); ++ // Paper start - optimize hoppers and remove streams ++ skipPullModeEventFire = skipHopperEvents; ++ return !c(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { ++ // Logic copied from below to avoid extra getItem calls ++ if (!item.isEmpty() && canTakeItem(iinventory, item, i, enumdirection)) { ++ return hopperPull(ihopper, iinventory, item, i); ++ } else { ++ return false; ++ } + }); ++ // Paper end + } else { + Iterator iterator = c(ihopper).iterator(); + +@@ -293,10 +492,11 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + } + +- private static boolean a(IHopper ihopper, IInventory iinventory, int i, EnumDirection enumdirection) { ++ private static boolean a(IHopper ihopper, IInventory iinventory, int i, EnumDirection enumdirection) {// Paper - method unused as logic is inlined above + ItemStack itemstack = iinventory.getItem(i); + +- if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { ++ if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { // If this logic changes, update above. this is left inused incase reflective plugins ++ return hopperPull(ihopper, iinventory, itemstack, i); /* // Paper - disable rest + ItemStack itemstack1 = itemstack.cloneItemStack(); + // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null); + // CraftBukkit start - Call event on collection of items from inventories into the hopper +@@ -333,7 +533,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + + itemstack1.subtract(origCount - itemstack2.getCount()); // Spigot +- iinventory.setItem(i, itemstack1); ++ iinventory.setItem(i, itemstack1);*/ // Paper - end commenting out replaced block for Hopper Optimizations + } + + return false; +@@ -342,7 +542,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + public static boolean a(IInventory iinventory, EntityItem entityitem) { + boolean flag = false; + // CraftBukkit start +- InventoryPickupItemEvent event = new InventoryPickupItemEvent(iinventory.getOwner().getInventory(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ InventoryPickupItemEvent event = new InventoryPickupItemEvent(getInventory(iinventory), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); // Paper - use getInventory() to avoid snapshot creation + entityitem.world.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; +@@ -384,6 +584,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + return !iinventory.b(i, itemstack) ? false : !(iinventory instanceof IWorldInventory) || ((IWorldInventory) iinventory).canPlaceItemThroughFace(i, itemstack, enumdirection); + } + ++ private static boolean canTakeItem(IInventory iinventory, ItemStack itemstack, int i, EnumDirection enumdirection) { return b(iinventory, itemstack, i, enumdirection); } // Paper - OBFHELPER + private static boolean b(IInventory iinventory, ItemStack itemstack, int i, EnumDirection enumdirection) { + return !(iinventory instanceof IWorldInventory) || ((IWorldInventory) iinventory).canTakeItemThroughFace(i, itemstack, enumdirection); + } +@@ -396,7 +597,9 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + boolean flag1 = iinventory1.isEmpty(); + + if (itemstack1.isEmpty()) { ++ IGNORE_TILE_UPDATES = true; // Paper + iinventory1.setItem(i, itemstack); ++ IGNORE_TILE_UPDATES = false; // Paper + itemstack = ItemStack.b; + flag = true; + } else if (a(itemstack1, itemstack)) { +@@ -447,18 +650,24 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + + public static List c(IHopper ihopper) { +- return (List) ihopper.aa_().d().stream().flatMap((axisalignedbb) -> { +- return ihopper.getWorld().a(EntityItem.class, axisalignedbb.d(ihopper.x() - 0.5D, ihopper.z() - 0.5D, ihopper.A() - 0.5D), IEntitySelector.a).stream(); +- }).collect(Collectors.toList()); ++ // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?! ++ World world = ihopper.getWorld(); ++ double d0 = ihopper.getX(); ++ double d1 = ihopper.getY(); ++ double d2 = ihopper.getZ(); ++ AxisAlignedBB bb = new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); ++ return world.getEntities(EntityItem.class, bb, Entity::isAlive); ++ // Paper end + } + + @Nullable + public static IInventory b(World world, BlockPosition blockposition) { +- return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); ++ return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, true); // Paper + } + + @Nullable +- public static IInventory a(World world, double d0, double d1, double d2) { ++ public static IInventory a(World world, double d0, double d1, double d2) { return a(world, d0, d1, d2, false); } // Paper - overload to default false ++ public static IInventory a(World world, double d0, double d1, double d2, boolean optimizeEntities) { // Paper + Object object = null; + BlockPosition blockposition = new BlockPosition(d0, d1, d2); + if ( !world.isLoaded( blockposition ) ) return null; // Spigot +@@ -478,7 +687,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + } + +- if (object == null) { ++ if (object == null && (!optimizeEntities || !org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(block).isOccluding())) { // Paper + List list = world.getEntities((Entity) null, new AxisAlignedBB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), IEntitySelector.d); + + if (!list.isEmpty()) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java +index 1508e267a38555820e2d31f3075adca185fbd4b6..f0da819627035bed83561128a11059424d2b7e30 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java +@@ -97,12 +97,19 @@ public abstract class TileEntityLootable extends TileEntityContainer { + @Override + public boolean isEmpty() { + this.d((EntityHuman) null); +- return this.f().stream().allMatch(ItemStack::isEmpty); ++ // Paper start ++ for (ItemStack itemStack : this.f()) { ++ if (!itemStack.isEmpty()) { ++ return false; ++ } ++ } ++ // Paper end ++ return true; + } + + @Override + public ItemStack getItem(int i) { +- this.d((EntityHuman) null); ++ if (i == 0) this.d((EntityHuman) null); // Paper + return (ItemStack) this.f().get(i); + } + diff --git a/patches/server-unmapped/0389-PlayerDeathEvent-shouldDropExperience.patch b/patches/server-unmapped/0389-PlayerDeathEvent-shouldDropExperience.patch new file mode 100644 index 0000000000..805bed1302 --- /dev/null +++ b/patches/server-unmapped/0389-PlayerDeathEvent-shouldDropExperience.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 24 Dec 2019 00:35:42 +0000 +Subject: [PATCH] PlayerDeathEvent#shouldDropExperience + + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index a0c426afaa7a18f7596d56699f02dcd665f7aa9d..f5212a7ec0f2dd27fb1c06e0dfc37f2aff595fde 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -822,7 +822,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.eW(); + } + // SPIGOT-5478 must be called manually now +- this.dropExperience(); ++ if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event + // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. + if (!event.getKeepInventory()) { + // Paper start - replace logic diff --git a/patches/server-unmapped/0390-Prevent-bees-loading-chunks-checking-hive-position.patch b/patches/server-unmapped/0390-Prevent-bees-loading-chunks-checking-hive-position.patch new file mode 100644 index 0000000000..224000580d --- /dev/null +++ b/patches/server-unmapped/0390-Prevent-bees-loading-chunks-checking-hive-position.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 5 Jan 2020 17:24:34 -0600 +Subject: [PATCH] Prevent bees loading chunks checking hive position + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +index 1554f1d1d35084c283b573b3e58e48c6747fe7d6..1ecf73f874f404f58a99316ae027f76db6b557db 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +@@ -442,6 +442,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB + if (!this.hasHivePos()) { + return false; + } else { ++ if (world.getChunkIfLoadedImmediately(hivePos.getX() >> 4, hivePos.getZ() >> 4) == null) return true; // Paper - just assume the hive is still there, no need to load the chunk(s) + TileEntity tileentity = this.world.getTileEntity(this.hivePos); + + return tileentity != null && tileentity.getTileType() == TileEntityTypes.BEEHIVE; diff --git a/patches/server-unmapped/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/patches/server-unmapped/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch new file mode 100644 index 0000000000..34cdbbb716 --- /dev/null +++ b/patches/server-unmapped/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Nov 2016 20:28:12 -0400 +Subject: [PATCH] Don't load Chunks from Hoppers and other things + +Hoppers call this to I guess "get the primary side" of a double sided chest. + +If the double sided chest crosses chunk lines, it causes the chunk to load. +This will end up causing sync chunk loads, which will unload with Chunk GC, +only to be reloaded again the next tick. + +This of course is undesirable, so just return the loaded side as "primary" +and treat it as a single chest if the other sides are unloaded + +diff --git a/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java b/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java +index d51f89fed6129c4b37ef63971f8f61dc14e8032d..efa98e87eead036246348f3915b401f0f52f2242 100644 +--- a/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java ++++ b/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java +@@ -29,7 +29,12 @@ public class DoubleBlockFinder { + return new DoubleBlockFinder.Result.Single<>(s0); + } else { + BlockPosition blockposition1 = blockposition.shift((EnumDirection) function1.apply(iblockdata)); +- IBlockData iblockdata1 = generatoraccess.getType(blockposition1); ++ // Paper start ++ IBlockData iblockdata1 = generatoraccess.getTypeIfLoaded(blockposition1); ++ if (iblockdata1 == null) { ++ return new DoubleBlockFinder.Result.Single<>(s0); ++ } ++ // Paper end + + if (iblockdata1.a(iblockdata.getBlock())) { + DoubleBlockFinder.BlockType doubleblockfinder_blocktype1 = (DoubleBlockFinder.BlockType) function.apply(iblockdata1); diff --git a/patches/server-unmapped/0392-Guard-against-serializing-mismatching-chunk-coordina.patch b/patches/server-unmapped/0392-Guard-against-serializing-mismatching-chunk-coordina.patch new file mode 100644 index 0000000000..1c55da068c --- /dev/null +++ b/patches/server-unmapped/0392-Guard-against-serializing-mismatching-chunk-coordina.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 27 Dec 2019 09:42:26 -0800 +Subject: [PATCH] Guard against serializing mismatching chunk coordinate + +Should help if something dumb happens + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index c95fcdf47db8bfe59a83c0d28f4744b4d8540ef8..e16e046d165330326ed220c9c440a637007f3137 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -67,6 +67,13 @@ public class ChunkRegionLoader { + + private static final Logger LOGGER = LogManager.getLogger(); + ++ // Paper start - guard against serializing mismatching coordinates ++ // TODO Note: This needs to be re-checked each update ++ public static ChunkCoordIntPair getChunkCoordinate(NBTTagCompound chunkData) { ++ NBTTagCompound levelData = chunkData.getCompound("Level"); ++ return new ChunkCoordIntPair(levelData.getInt("xPos"), levelData.getInt("zPos")); ++ } ++ // Paper end + // Paper start + public static final class InProgressChunkHolder { + +@@ -92,8 +99,8 @@ public class ChunkRegionLoader { + // Paper end + ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); + WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); +- NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); +- ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); ++ NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate ++ ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate + + if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { + ChunkRegionLoader.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java +index 01ae13385dd0208c9f34da8b3897b571f86305d0..890362d28ab9cb760c73fe5014e144fb08ada6b8 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java +@@ -13,6 +13,7 @@ import net.minecraft.SharedConstants; + import net.minecraft.nbt.GameProfileSerializer; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.level.PlayerChunkMap; + import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.World; +@@ -123,6 +124,13 @@ public class IChunkLoader implements AutoCloseable { + + public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER + public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) ++ // Paper start ++ if (!chunkcoordintpair.equals(ChunkRegionLoader.getChunkCoordinate(nbttagcompound))) { ++ String world = (this instanceof PlayerChunkMap) ? ((PlayerChunkMap)this).world.getWorld().getName() : null; ++ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkcoordintpair.toString() ++ + " but compound says coordinate is " + ChunkRegionLoader.getChunkCoordinate(nbttagcompound).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); ++ } ++ // Paper end + this.regionFileCache.write(chunkcoordintpair, nbttagcompound); + if (this.c != null) { + synchronized (this.persistentDataLock) { // Paper - Async chunk loading diff --git a/patches/server-unmapped/0393-Optimise-IEntityAccess-getPlayerByUUID.patch b/patches/server-unmapped/0393-Optimise-IEntityAccess-getPlayerByUUID.patch new file mode 100644 index 0000000000..cd0b940339 --- /dev/null +++ b/patches/server-unmapped/0393-Optimise-IEntityAccess-getPlayerByUUID.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 11 Jan 2020 21:50:56 -0800 +Subject: [PATCH] Optimise IEntityAccess#getPlayerByUUID + +Use the world entity map instead of iterating over all players + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index fbb550cce96e7e5539c69bae1459326090d0c508..de4e0477c5c777ce9ac601f88d24f2dd2786eb6f 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -289,6 +289,15 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + // Paper end + ++ // Paper start - optimise getPlayerByUUID ++ @Nullable ++ @Override ++ public EntityHuman getPlayerByUUID(UUID uuid) { ++ Entity player = this.entitiesByUUID.get(uuid); ++ return (player instanceof EntityHuman) ? (EntityHuman)player : null; ++ } ++ // Paper end ++ + // Add env and gen to constructor, WorldData -> WorldDataServer + public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor +diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java +index 8fdc4b22e8c99d653bd213fe64339c133b46b4e9..1ff9e771788a4ab52129070e355ca48df2949470 100644 +--- a/src/main/java/net/minecraft/world/level/IEntityAccess.java ++++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java +@@ -277,6 +277,12 @@ public interface IEntityAccess { + + @Nullable + default EntityHuman b(UUID uuid) { ++ // Paper start - allow WorldServer to override ++ return this.getPlayerByUUID(uuid); ++ } ++ @Nullable ++ default EntityHuman getPlayerByUUID(UUID uuid) { ++ // Paper end + for (int i = 0; i < this.getPlayers().size(); ++i) { + EntityHuman entityhuman = (EntityHuman) this.getPlayers().get(i); + diff --git a/patches/server-unmapped/0394-Fix-items-not-falling-correctly.patch b/patches/server-unmapped/0394-Fix-items-not-falling-correctly.patch new file mode 100644 index 0000000000..f9047f957b --- /dev/null +++ b/patches/server-unmapped/0394-Fix-items-not-falling-correctly.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AJMFactsheets +Date: Fri, 17 Jan 2020 17:17:54 -0600 +Subject: [PATCH] Fix items not falling correctly + +Since 1.14, Mojang has added an optimization which skips checking if +an item should fall every fourth tick. + +However, Spigot's entity activation range class also has an +optimization which skips ticking active entities every fourth tick. +This can result in a state where an item will never properly fall +due to its move method never being called. + +This patch resolves the conflict by offsetting checking an item's +move method from Spigot's entity activation range check. + +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index 0b2e6e72a85e05f239d56afb6785c91da5b25d55..11e029f6f97f1dd9c32e311d1a3800f2fa54b91f 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -116,7 +116,7 @@ public class EntityItem extends Entity { + } + } + +- if (!this.onGround || c(this.getMot()) > 9.999999747378752E-6D || (this.ticksLived + this.getId()) % 4 == 0) { ++ if (!this.onGround || c(this.getMot()) > 9.999999747378752E-6D || this.ticksLived % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check + this.move(EnumMoveType.SELF, this.getMot()); + float f1 = 0.98F; + diff --git a/patches/server-unmapped/0395-Lag-compensate-eating.patch b/patches/server-unmapped/0395-Lag-compensate-eating.patch new file mode 100644 index 0000000000..b23bae79ab --- /dev/null +++ b/patches/server-unmapped/0395-Lag-compensate-eating.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 14 Jan 2020 15:28:28 -0800 +Subject: [PATCH] Lag compensate eating + +When the server is lagging, players will wait longer when eating. +Change to also use a time check instead if it passes. + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index cd880fb9e61dad7dff185d0b4fa2b8c5dee04861..6a81aa44d2acde7575e0ed74ea8bf4070739f10e 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -214,7 +214,7 @@ public abstract class EntityLiving extends Entity { + private int jumpTicks; + private float bw; + public ItemStack activeItem; // Paper - public +- protected int bd; ++ protected int bd; protected final int getEatTimeTicks() { return this.bd; } protected final void setEatTimeTicks(int value) { this.bd = value; } // Paper - OBFHELPER + protected int be; + private BlockPosition bx; + private Optional by; +@@ -3151,6 +3151,11 @@ public abstract class EntityLiving extends Entity { + return ((Byte) this.datawatcher.get(EntityLiving.ag) & 2) > 0 ? EnumHand.OFF_HAND : EnumHand.MAIN_HAND; + } + ++ // Paper start - lag compensate eating ++ protected long eatStartTime; ++ protected int totalEatTimeTicks; ++ // Paper end ++ + private void t() { + if (this.isHandRaised()) { + if (ItemStack.d(this.b(this.getRaisedHand()), this.activeItem)) { +@@ -3160,7 +3165,12 @@ public abstract class EntityLiving extends Entity { + this.b(this.activeItem, 5); + } + +- if (--this.bd == 0 && !this.world.isClientSide && !this.activeItem.m()) { ++ // Paper start - lag compensate eating ++ // we add 1 to the expected time to avoid lag compensating when we should not ++ boolean shouldLagCompensate = this.activeItem.getItem().isFood() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); ++ if ((--this.bd == 0 || shouldLagCompensate) && !this.world.isClientSide && !this.activeItem.m()) { ++ this.setEatTimeTicks(0); ++ // Paper end + this.s(); + } + } else { +@@ -3210,7 +3220,10 @@ public abstract class EntityLiving extends Entity { + + if (!itemstack.isEmpty() && !this.isHandRaised() || forceUpdate) { // Paper use override flag + this.activeItem = itemstack; +- this.bd = itemstack.k(); ++ // Paper start - lag compensate eating ++ this.bd = this.totalEatTimeTicks = itemstack.k(); ++ this.eatStartTime = System.nanoTime(); ++ // Paper end + if (!this.world.isClientSide) { + this.c(1, true); + this.c(2, enumhand == EnumHand.OFF_HAND); +@@ -3234,7 +3247,10 @@ public abstract class EntityLiving extends Entity { + } + } else if (!this.isHandRaised() && !this.activeItem.isEmpty()) { + this.activeItem = ItemStack.b; +- this.bd = 0; ++ // Paper start - lag compensate eating ++ this.bd = this.totalEatTimeTicks = 0; ++ this.eatStartTime = -1L; ++ // Paper end + } + } + +@@ -3362,7 +3378,10 @@ public abstract class EntityLiving extends Entity { + } + + this.activeItem = ItemStack.b; +- this.bd = 0; ++ // Paper start - lag compensate eating ++ this.bd = this.totalEatTimeTicks = 0; ++ this.eatStartTime = -1L; ++ // Paper end + } + + public boolean isBlocking() { diff --git a/patches/server-unmapped/0396-Optimize-call-to-getFluid-for-explosions.patch b/patches/server-unmapped/0396-Optimize-call-to-getFluid-for-explosions.patch new file mode 100644 index 0000000000..aa68e86bd8 --- /dev/null +++ b/patches/server-unmapped/0396-Optimize-call-to-getFluid-for-explosions.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BrodyBeckwith +Date: Tue, 14 Jan 2020 17:49:03 -0500 +Subject: [PATCH] Optimize call to getFluid for explosions + + +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 618cf4e0d71b4b04085807314e79a02785f8a498..a9ecc2b4da587ca3d3c99f8c8af38092a02fb572 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -153,7 +153,7 @@ public class Explosion { + for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { + BlockPosition blockposition = new BlockPosition(d4, d5, d6); + IBlockData iblockdata = this.world.getType(blockposition); +- Fluid fluid = this.world.getFluid(blockposition); ++ Fluid fluid = iblockdata.getFluid(); // Paper + Optional optional = this.l.a(this, this.world, blockposition, iblockdata, fluid); + + if (optional.isPresent()) { diff --git a/patches/server-unmapped/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch b/patches/server-unmapped/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch new file mode 100644 index 0000000000..9bb8424860 --- /dev/null +++ b/patches/server-unmapped/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 17 Jan 2020 18:44:55 -0800 +Subject: [PATCH] Fix last firework in stack not having effects when dispensed + - #2871 + +CB used the resulting item in the dispenser rather than the item +dispensed. The resulting item would have size == 0 and therefore +be convertered to air, hence why the effects disappeared. + +diff --git a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java +index 50911632341d1b861c00f01077cae43884147fe0..0055a96b51a1d38d31e129c417c97bcfc9d0b745 100644 +--- a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java +@@ -427,7 +427,7 @@ public interface IDispenseBehavior { + } + + itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); +- EntityFireworks entityfireworks = new EntityFireworks(isourceblock.getWorld(), itemstack, isourceblock.getX(), isourceblock.getY(), isourceblock.getX(), true); ++ EntityFireworks entityfireworks = new EntityFireworks(isourceblock.getWorld(), itemstack1, isourceblock.getX(), isourceblock.getY(), isourceblock.getX(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed + + IDispenseBehavior.a(isourceblock, entityfireworks, enumdirection); + entityfireworks.shoot((double) enumdirection.getAdjacentX(), (double) enumdirection.getAdjacentY(), (double) enumdirection.getAdjacentZ(), 0.5F, 1.0F); diff --git a/patches/server-unmapped/0398-Add-effect-to-block-break-naturally.patch b/patches/server-unmapped/0398-Add-effect-to-block-break-naturally.patch new file mode 100644 index 0000000000..e1c6127f7b --- /dev/null +++ b/patches/server-unmapped/0398-Add-effect-to-block-break-naturally.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 2 Jan 2020 12:25:07 -0600 +Subject: [PATCH] Add effect to block break naturally + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 724b230259b1b44bc9fdde6c4fcbcdde5f690e05..e3ab0b76e5003553b29215a43bc5a762f2663648 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -633,6 +633,13 @@ public class CraftBlock implements Block { + + @Override + public boolean breakNaturally(ItemStack item) { ++ // Paper start ++ return breakNaturally(item, false); ++ } ++ ++ @Override ++ public boolean breakNaturally(ItemStack item, boolean triggerEffect) { ++ // Paper end + // Order matters here, need to drop before setting to air so skulls can get their data + net.minecraft.world.level.block.state.IBlockData iblockdata = this.getNMS(); + net.minecraft.world.level.block.Block block = iblockdata.getBlock(); +@@ -642,6 +649,7 @@ public class CraftBlock implements Block { + // Modelled off EntityHuman#hasBlock + if (block != Blocks.AIR && (item == null || !iblockdata.isRequiresSpecialTool() || nmsItem.canDestroySpecialBlock(iblockdata))) { + net.minecraft.world.level.block.Block.dropItems(iblockdata, world.getMinecraftWorld(), position, world.getTileEntity(position), null, nmsItem); ++ if (triggerEffect) world.triggerEffect(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.world.level.block.Block.getCombinedId(block.getBlockData())); // Paper + result = true; + } + diff --git a/patches/server-unmapped/0399-Tracking-Range-Improvements.patch b/patches/server-unmapped/0399-Tracking-Range-Improvements.patch new file mode 100644 index 0000000000..8754eec0d1 --- /dev/null +++ b/patches/server-unmapped/0399-Tracking-Range-Improvements.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Sat, 21 Dec 2019 15:22:09 -0500 +Subject: [PATCH] Tracking Range Improvements + +Sets tracking range of watermobs to animals instead of misc and simplifies code + +Also ignores Enderdragon, defaulting it to Mojang's setting + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index d00dc8d7933be61f1401f598e5d675f5ae5d7029..baef98331c07b0f8c95351f39c5e471f96a59c05 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -1797,6 +1797,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + int j = entity.getEntityType().getChunkRange() * 16; ++ j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper + + if (j > i) { + i = j; +diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java +index 0449451142d59e828a32fe237751c7d8484894a2..3277a8aaffb6a25624967aa0c62f61309a517739 100644 +--- a/src/main/java/org/spigotmc/TrackingRange.java ++++ b/src/main/java/org/spigotmc/TrackingRange.java +@@ -25,26 +25,26 @@ public class TrackingRange + if ( entity instanceof EntityPlayer ) + { + return config.playerTrackingRange; +- } else if ( entity.activationType == ActivationRange.ActivationType.MONSTER || entity.activationType == ActivationRange.ActivationType.RAIDER ) +- { +- return config.monsterTrackingRange; +- } else if ( entity instanceof EntityGhast ) +- { +- if ( config.monsterTrackingRange > config.monsterActivationRange ) +- { ++ // Paper start - Simplify and set water mobs to animal tracking range ++ } ++ switch (entity.activationType) { ++ case RAIDER: ++ case MONSTER: ++ case FLYING_MONSTER: + return config.monsterTrackingRange; +- } else +- { +- return config.monsterActivationRange; +- } +- } else if ( entity.activationType == ActivationRange.ActivationType.ANIMAL ) +- { +- return config.animalTrackingRange; +- } else if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) ++ case WATER: ++ case VILLAGER: ++ case ANIMAL: ++ return config.animalTrackingRange; ++ case MISC: ++ } ++ if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) ++ // Paper end + { + return config.miscTrackingRange; + } else + { ++ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return ((net.minecraft.server.level.WorldServer)(entity.getWorld())).getChunkProvider().playerChunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt + return config.otherTrackingRange; + } + } diff --git a/patches/server-unmapped/0400-Entity-Activation-Range-2.0.patch b/patches/server-unmapped/0400-Entity-Activation-Range-2.0.patch new file mode 100644 index 0000000000..1f2ba41bd2 --- /dev/null +++ b/patches/server-unmapped/0400-Entity-Activation-Range-2.0.patch @@ -0,0 +1,869 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 13 May 2016 01:38:06 -0400 +Subject: [PATCH] Entity Activation Range 2.0 + +Optimizes performance of Activation Range + +Adds many new configurations and a new wake up inactive system + +Fixes and adds new Immunities to improve gameplay behavior + +Adds water Mobs to activation range config and nerfs fish +Adds flying monsters to control ghast and phantoms +Adds villagers as separate config + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index de4e0477c5c777ce9ac601f88d24f2dd2786eb6f..17c6118fb1ea1f16d37eb13116e11f886274ba95 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -861,17 +861,17 @@ public class WorldServer extends World implements GeneratorAccessSeed { + ++TimingHistory.entityTicks; // Paper - timings + // Spigot start + co.aikar.timings.Timing timer; // Paper +- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { ++ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below + entity.ticksLived++; + timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings + entity.inactiveTick(); + } finally { timer.stopTiming(); } // Paper + return; +- } ++ }*/ // Paper - comment out EAR 2 + // Spigot end + // Paper start- timings +- TimingHistory.activatedEntityTicks++; +- timer = entity.getVehicle() != null ? entity.getEntityType().passengerTickTimer.startTiming() : entity.getEntityType().tickTimer.startTiming(); ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); ++ timer = isActive ? entity.getEntityType().tickTimer.startTiming() : entity.getEntityType().inactiveTickTimer.startTiming(); // Paper + try { + // Paper end - timings + entity.g(entity.locX(), entity.locY(), entity.locZ()); +@@ -885,12 +885,16 @@ public class WorldServer extends World implements GeneratorAccessSeed { + return IRegistry.ENTITY_TYPE.getKey(entity.getEntityType()).toString(); + }); + gameprofilerfiller.c("tickNonPassenger"); ++ if (isActive) { // Paper - EAR 2 ++ TimingHistory.activatedEntityTicks++; // Paper + entity.tick(); + entity.postTick(); // CraftBukkit ++ } else { entity.inactiveTick(); } // Paper - EAR 2 + gameprofilerfiller.exit(); + } + + this.chunkCheck(entity); ++ } finally { timer.stopTiming(); } // Paper - timings + if (entity.inChunk) { + Iterator iterator = entity.getPassengers().iterator(); + +@@ -900,7 +904,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.a(entity, entity1); + } + } +- } finally { timer.stopTiming(); } // Paper - timings ++ //} finally { timer.stopTiming(); } // Paper - timings - move up + + } + } +@@ -908,6 +912,11 @@ public class WorldServer extends World implements GeneratorAccessSeed { + public void a(Entity entity, Entity entity1) { + if (!entity1.dead && entity1.getVehicle() == entity) { + if (entity1 instanceof EntityHuman || this.getChunkProvider().a(entity1)) { ++ // Paper - EAR 2 ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity1); ++ co.aikar.timings.Timing timer = isActive ? entity1.getEntityType().passengerTickTimer.startTiming() : entity1.getEntityType().passengerInactiveTickTimer.startTiming(); // Paper ++ try { ++ // Paper end + entity1.g(entity1.locX(), entity1.locY(), entity1.locZ()); + entity1.lastYaw = entity1.yaw; + entity1.lastPitch = entity1.pitch; +@@ -919,8 +928,17 @@ public class WorldServer extends World implements GeneratorAccessSeed { + return IRegistry.ENTITY_TYPE.getKey(entity1.getEntityType()).toString(); + }); + gameprofilerfiller.c("tickPassenger"); ++ // Paper start - EAR 2 ++ if (isActive) { + entity1.passengerTick(); + entity1.postTick(); // CraftBukkit ++ } else { ++ entity1.setMot(Vec3D.ORIGIN); ++ entity1.inactiveTick(); ++ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary ++ entity.syncPositionOf(entity1); ++ } ++ // Paper end - EAR 2 + gameprofilerfiller.exit(); + } + +@@ -933,7 +951,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + this.a(entity1, entity2); + } +- } ++ } } finally { timer.stopTiming(); } // Paper - EAR2 timings + + } + } else { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index efa8d9a16e87475adf7e71a0dfa2861653f73c06..32dad0b72ee0d0a1ac30decb0fb52f4399f9f39f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -68,6 +68,7 @@ import net.minecraft.world.entity.animal.EntityFish; + import net.minecraft.world.entity.item.EntityItem; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.vehicle.EntityBoat; ++import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.enchantment.EnchantmentManager; + import net.minecraft.world.item.enchantment.EnchantmentProtection; +@@ -251,7 +252,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public boolean Y; + public boolean impulse; + public int portalCooldown; +- protected boolean inPortal; ++ public boolean inPortal; // Paper - public + protected int portalTicks; + protected BlockPosition ac; + private boolean invulnerable; +@@ -275,6 +276,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; + public long activatedTick = Integer.MIN_VALUE; ++ public boolean isTemporarilyActive = false; // Paper + public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one + protected int numCollisions = 0; // Paper + public void inactiveTick() { } +@@ -665,6 +667,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.recalcPosition(); + } else { + if (enummovetype == EnumMoveType.PISTON) { ++ this.activatedTick = MinecraftServer.currentTick + 20; // Paper + vec3d = this.b(vec3d); + if (vec3d.equals(Vec3D.ORIGIN)) { + return; +@@ -677,6 +680,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.x = Vec3D.ORIGIN; + this.setMot(Vec3D.ORIGIN); + } ++ // Paper start - ignore movement changes while inactive. ++ if (isTemporarilyActive && !(this instanceof EntityItem || this instanceof EntityMinecartAbstract) && vec3d == getMot() && enummovetype == EnumMoveType.SELF) { ++ setMot(Vec3D.ORIGIN); ++ this.world.getMethodProfiler().exit(); ++ return; ++ } ++ // Paper end + + vec3d = this.a(vec3d, enummovetype); + Vec3D vec3d1 = this.g(vec3d); +@@ -2012,6 +2022,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + } + ++ public void syncPositionOf(Entity entity) { k(entity); } // Paper - OBFHELPER + public void k(Entity entity) { + this.a(entity, Entity::setPosition); + } +@@ -2822,6 +2833,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return this.ae; + } + ++ public final boolean isPushedByWater() { return this.bV(); } // Paper - OBFHELPER - the below is not an obfhelper, don't use it! + public boolean bV() { + // Paper start + return this.pushedByWater(); +diff --git a/src/main/java/net/minecraft/world/entity/EntityCreature.java b/src/main/java/net/minecraft/world/entity/EntityCreature.java +index a9322e7cd8e07a2d5578c861991d53ec85fbfbcc..bbf0f345bfdd8a3a1f7fe902a42b2b18cdcf07a5 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityCreature.java ++++ b/src/main/java/net/minecraft/world/entity/EntityCreature.java +@@ -14,6 +14,7 @@ import org.bukkit.event.entity.EntityUnleashEvent; + public abstract class EntityCreature extends EntityInsentient { + + public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper ++ public BlockPosition movingTarget = null; public BlockPosition getMovingTarget() { return movingTarget; } // Paper + + protected EntityCreature(EntityTypes entitytypes, World world) { + super(entitytypes, world); +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index 0489fb4869c9a0b56df6f44ef3925de7651baef2..da190d0b21098e327fab42e79a4ae18629bcf6e5 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -115,7 +115,7 @@ public abstract class EntityInsentient extends EntityLiving { + public MinecraftKey lootTableKey; + public long lootTableSeed; + @Nullable +- private Entity leashHolder; ++ public Entity leashHolder; // Paper - private -> public + private int bx; + @Nullable + private NBTTagCompound by; +@@ -196,6 +196,19 @@ public abstract class EntityInsentient extends EntityLiving { + return this.lookController; + } + ++ // Paper start ++ @Override ++ public void inactiveTick() { ++ super.inactiveTick(); ++ if (this.goalSelector.inactiveTick()) { ++ this.goalSelector.doTick(); ++ } ++ if (this.targetSelector.inactiveTick()) { ++ this.targetSelector.doTick(); ++ } ++ } ++ // Paper end ++ + public ControllerMove getControllerMove() { + if (this.isPassenger() && this.getVehicle() instanceof EntityInsentient) { + EntityInsentient entityinsentient = (EntityInsentient) this.getVehicle(); +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 6a81aa44d2acde7575e0ed74ea8bf4070739f10e..ffb4072f46456b3a2b2daa55947787cee774d26d 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -192,7 +192,7 @@ public abstract class EntityLiving extends Entity { + protected float aN; + protected int aO;protected int getKillCount() { return this.aO; } // Paper - OBFHELPER + public float lastDamage; +- protected boolean jumping; ++ public boolean jumping; // Paper protected -> public + public float aR; + public float aS; + public float aT; +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java +index 5e599d88a150c907f50acbb58ad1725c3fe361e4..b505c23c57a4b84faf5906c6295455b4720c4426 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java +@@ -20,7 +20,10 @@ public abstract class PathfinderGoal { + + public void c() {} + +- public void d() {} ++ public void d() { ++ onTaskReset(); // Paper ++ } ++ public void onTaskReset() {} // Paper + + public void e() {} + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java +index 6a156a488bc073b3b60f4d1081e3f2ab65ba9e96..8a0515ae03c9081b03e9c2a312826345038b8fa7 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java +@@ -9,12 +9,12 @@ import net.minecraft.world.level.IWorldReader; + + public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { + +- protected final EntityCreature a; ++ protected final EntityCreature a;public EntityCreature getEntity() { return a; } // Paper - OBFHELPER + public final double b; + protected int c; + protected int d; + private int g; +- protected BlockPosition e;public final BlockPosition getTargetPosition() { return this.e; } // Paper - OBFHELPER ++ protected BlockPosition e; public final BlockPosition getTargetPosition() { return this.e; } public void setTargetPosition(BlockPosition pos) { this.e = pos; getEntity().movingTarget = pos != BlockPosition.ZERO ? pos : null; } // Paper - OBFHELPER + private boolean h; + private final int i; + private final int j; +@@ -23,6 +23,13 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { + public PathfinderGoalGotoTarget(EntityCreature entitycreature, double d0, int i) { + this(entitycreature, d0, i, 1); + } ++ // Paper start - activation range improvements ++ @Override ++ public void onTaskReset() { ++ super.onTaskReset(); ++ setTargetPosition(BlockPosition.ZERO); ++ } ++ // Paper end + + public PathfinderGoalGotoTarget(EntityCreature entitycreature, double d0, int i, int j) { + this.e = BlockPosition.ZERO; +@@ -111,6 +118,7 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { + blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, i1, k - 1, j1); + if (this.a.a((BlockPosition) blockposition_mutableblockposition) && this.a(this.a.world, blockposition_mutableblockposition)) { + this.e = blockposition_mutableblockposition; ++ setTargetPosition(blockposition_mutableblockposition.immutableCopy()); // Paper + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java +index c9aaa63fcb0abe5628798827003c677c883c2a18..8c234c09a4d9ada83e36e3cdbcc1f2f5c6202f28 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java +@@ -26,10 +26,11 @@ public class PathfinderGoalSelector { + } + }; + private final Map c = new EnumMap(PathfinderGoal.Type.class); +- private final Set d = Sets.newLinkedHashSet(); ++ private final Set d = Sets.newLinkedHashSet(); private Set getTasks() { return d; }// Paper - OBFHELPER + private final Supplier e; + private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); +- private int g = 3; ++ private int g = 3;private int getTickRate() { return g; } // Paper - OBFHELPER ++ private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO + + public PathfinderGoalSelector(Supplier supplier) { + this.e = supplier; +@@ -39,6 +40,21 @@ public class PathfinderGoalSelector { + this.d.add(new PathfinderGoalWrapped(i, pathfindergoal)); + } + ++ // Paper start ++ public boolean inactiveTick() { ++ incRate(); ++ return getCurRate() % getTickRate() == 0; ++ } ++ public boolean hasTasks() { ++ for (PathfinderGoalWrapped task : getTasks()) { ++ if (task.isRunning()) { ++ return true; ++ } ++ } ++ return false; ++ } ++ // Paper end ++ + public void a(PathfinderGoal pathfindergoal) { + this.d.stream().filter((pathfindergoalwrapped) -> { + return pathfindergoalwrapped.j() == pathfindergoal; +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java +index 7395335ee97237376d34e315ea1d7d46766b278a..7bb531e47668cf445083c4dedb03ccafe6a9c96b 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java +@@ -64,6 +64,7 @@ public class PathfinderGoalWrapped extends PathfinderGoal { + return this.a.i(); + } + ++ public boolean isRunning() { return this.g(); } // Paper - OBFHELPER + public boolean g() { + return this.c; + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java +index 8b09aaa30dd753fd34bea155890bdd9e5cb180f5..2005cb484ba6b5929ad81d3d120521f247f3d4cf 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java +@@ -454,6 +454,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn + return this.bC != null; + } + ++ public final boolean inCaravan() { return this.fC(); } // Paper - OBFHELPER + public boolean fC() { + return this.bB != null; + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index 29957e79161db862c3eee5d0ed0cb8edb5dceb1c..596450d3cdb3be4abca3e75bed743abd071fb0b0 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -213,17 +213,29 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + @Override + public void inactiveTick() { + // SPIGOT-3874, SPIGOT-3894, SPIGOT-3846, SPIGOT-5286 :( +- if (world.spigotConfig.tickInactiveVillagers && this.doAITick()) { +- this.mobTick(); ++ // Paper start ++ if (this.getUnhappy() > 0) { ++ this.setUnhappy(this.getUnhappy() - 1); + } ++ if (this.doAITick()) { ++ if (world.spigotConfig.tickInactiveVillagers) { ++ this.mobTick(); ++ } else { ++ this.mobTick(true); ++ } ++ } ++ doReputationTick(); ++ // Paper end ++ + super.inactiveTick(); + } + // Spigot End + + @Override +- protected void mobTick() { ++ protected void mobTick() { mobTick(false); } ++ protected void mobTick(boolean inactive) { + this.world.getMethodProfiler().enter("villagerBrain"); +- this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error ++ if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper + this.world.getMethodProfiler().exit(); + if (this.bF) { + this.bF = false; +@@ -247,7 +259,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + this.bv = null; + } + +- if (!this.isNoAI() && this.random.nextInt(100) == 0) { ++ if (!inactive && !this.isNoAI() && this.random.nextInt(100) == 0) { // Paper + Raid raid = ((WorldServer) this.world).b_(this.getChunkCoordinates()); + + if (raid != null && raid.v() && !raid.a()) { +@@ -258,6 +270,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.eN()) { + this.eT(); + } ++ if (inactive) return; // Paper + + super.mobTick(); + } +@@ -901,6 +914,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + } + } + ++ private void doReputationTick() { fw(); } // Paper - OBFHELPER + private void fw() { + long i = this.world.getTime(); + +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java +index 190411d6fcee8bed686a2bcfd088aa7c2513fc26..3dd80fcf9237f15bb3bf38d1529340e178f09388 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java +@@ -72,10 +72,12 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP + return super.prepare(worldaccess, difficultydamagescaler, enummobspawn, (GroupDataEntity) groupdataentity, nbttagcompound); + } + ++ public final int getUnhappy() { return eK(); } // Paper - OBFHELPER + public int eK() { + return (Integer) this.datawatcher.get(EntityVillagerAbstract.bp); + } + ++ public final void setUnhappy(int i) { s(i); } // Paper - OBFHELPER + public void s(int i) { + this.datawatcher.set(EntityVillagerAbstract.bp, i); + } +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index d1738b57efd3f5e6c51603553a773173e4b09bb5..c4680142bf23d30169555abe7db78d85811e042b 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -142,6 +142,12 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public long ticksPerWaterSpawns; + public long ticksPerWaterAmbientSpawns; + public long ticksPerAmbientSpawns; ++ // Paper start ++ public int wakeupInactiveRemainingAnimals; ++ public int wakeupInactiveRemainingFlying; ++ public int wakeupInactiveRemainingMonsters; ++ public int wakeupInactiveRemainingVillagers; ++ // Paper end + public boolean populating; + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 53d0541aba207b5eaea2e49edbb56df918d30333..663127e6e6ec507959142b18a11a5a4790d4b98b 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -31,11 +31,30 @@ import net.minecraft.world.level.chunk.Chunk; + import net.minecraft.world.phys.AxisAlignedBB; + import co.aikar.timings.MinecraftTimings; + ++// Paper start ++import net.minecraft.core.BlockPosition; ++import net.minecraft.server.level.ChunkProviderServer; ++import net.minecraft.world.entity.EntityFlying; ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.entity.ai.BehaviorController; ++import net.minecraft.world.entity.animal.EntityBee; ++import net.minecraft.world.entity.animal.EntityWaterAnimal; ++import net.minecraft.world.entity.animal.horse.EntityLlama; ++import net.minecraft.world.entity.monster.EntityPillager; ++import net.minecraft.world.entity.monster.IMonster; ++import net.minecraft.world.entity.schedule.Activity; ++import net.minecraft.world.entity.item.EntityFallingBlock; ++import net.minecraft.world.entity.projectile.EntityEnderSignal; ++// Paper end ++ + public class ActivationRange + { + + public enum ActivationType + { ++ WATER, // Paper ++ FLYING_MONSTER, // Paper ++ VILLAGER, // Paper + MONSTER, + ANIMAL, + RAIDER, +@@ -43,6 +62,43 @@ public class ActivationRange + + AxisAlignedBB boundingBox = new AxisAlignedBB( 0, 0, 0, 0, 0, 0 ); + } ++ // Paper start ++ ++ static Activity[] VILLAGER_PANIC_IMMUNITIES = { ++ Activity.HIDE, ++ Activity.PRE_RAID, ++ Activity.RAID, ++ Activity.PANIC ++ }; ++ ++ private static int checkInactiveWakeup(Entity entity) { ++ World world = entity.world; ++ SpigotWorldConfig config = world.spigotConfig; ++ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; ++ if (entity.activationType == ActivationType.VILLAGER) { ++ if (inactiveFor > config.wakeUpInactiveVillagersEvery && world.wakeupInactiveRemainingVillagers > 0) { ++ world.wakeupInactiveRemainingVillagers--; ++ return config.wakeUpInactiveVillagersFor; ++ } ++ } else if (entity.activationType == ActivationType.ANIMAL) { ++ if (inactiveFor > config.wakeUpInactiveAnimalsEvery && world.wakeupInactiveRemainingAnimals > 0) { ++ world.wakeupInactiveRemainingAnimals--; ++ return config.wakeUpInactiveAnimalsFor; ++ } ++ } else if (entity.activationType == ActivationType.FLYING_MONSTER) { ++ if (inactiveFor > config.wakeUpInactiveFlyingEvery && world.wakeupInactiveRemainingFlying > 0) { ++ world.wakeupInactiveRemainingFlying--; ++ return config.wakeUpInactiveFlyingFor; ++ } ++ } else if (entity.activationType == ActivationType.MONSTER || entity.activationType == ActivationType.RAIDER) { ++ if (inactiveFor > config.wakeUpInactiveMonstersEvery && world.wakeupInactiveRemainingMonsters > 0) { ++ world.wakeupInactiveRemainingMonsters--; ++ return config.wakeUpInactiveMonstersFor; ++ } ++ } ++ return -1; ++ } ++ // Paper end + + static AxisAlignedBB maxBB = new AxisAlignedBB( 0, 0, 0, 0, 0, 0 ); + +@@ -55,10 +111,13 @@ public class ActivationRange + */ + public static ActivationType initializeEntityActivationType(Entity entity) + { ++ if (entity instanceof EntityWaterAnimal) { return ActivationType.WATER; } // Paper ++ else if (entity instanceof EntityVillager) { return ActivationType.VILLAGER; } // Paper ++ else if (entity instanceof EntityFlying && entity instanceof IMonster) { return ActivationType.FLYING_MONSTER; } // Paper - doing & Monster incase Flying no longer includes monster in future + if ( entity instanceof EntityRaider ) + { + return ActivationType.RAIDER; +- } else if ( entity instanceof EntityMonster || entity instanceof EntitySlime ) ++ } else if ( entity instanceof IMonster ) // Paper - correct monster check + { + return ActivationType.MONSTER; + } else if ( entity instanceof EntityCreature || entity instanceof EntityAmbient ) +@@ -79,10 +138,14 @@ public class ActivationRange + */ + public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) + { +- if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange == 0 ) +- || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange == 0 ) +- || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange == 0 ) +- || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange == 0 ) ++ if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.VILLAGER && config.villagerActivationRange <= 0 ) // Paper ++ || ( entity.activationType == ActivationType.WATER && config.waterActivationRange <= 0 ) // Paper ++ || ( entity.activationType == ActivationType.FLYING_MONSTER && config.flyingMonsterActivationRange <= 0 ) // Paper ++ || entity instanceof EntityEnderSignal // Paper + || entity instanceof EntityHuman + || entity instanceof EntityProjectile + || entity instanceof EntityEnderDragon +@@ -115,10 +178,25 @@ public class ActivationRange + final int raiderActivationRange = world.spigotConfig.raiderActivationRange; + final int animalActivationRange = world.spigotConfig.animalActivationRange; + final int monsterActivationRange = world.spigotConfig.monsterActivationRange; ++ // Paper start ++ final int waterActivationRange = world.spigotConfig.waterActivationRange; ++ final int flyingActivationRange = world.spigotConfig.flyingMonsterActivationRange; ++ final int villagerActivationRange = world.spigotConfig.villagerActivationRange; ++ world.wakeupInactiveRemainingAnimals = Math.min(world.wakeupInactiveRemainingAnimals + 1, world.spigotConfig.wakeUpInactiveAnimals); ++ world.wakeupInactiveRemainingVillagers = Math.min(world.wakeupInactiveRemainingVillagers + 1, world.spigotConfig.wakeUpInactiveVillagers); ++ world.wakeupInactiveRemainingMonsters = Math.min(world.wakeupInactiveRemainingMonsters + 1, world.spigotConfig.wakeUpInactiveMonsters); ++ world.wakeupInactiveRemainingFlying = Math.min(world.wakeupInactiveRemainingFlying + 1, world.spigotConfig.wakeUpInactiveFlying); ++ final ChunkProviderServer chunkProvider = (ChunkProviderServer) world.getChunkProvider(); ++ // Paper end + + int maxRange = Math.max( monsterActivationRange, animalActivationRange ); + maxRange = Math.max( maxRange, raiderActivationRange ); + maxRange = Math.max( maxRange, miscActivationRange ); ++ // Paper start ++ maxRange = Math.max( maxRange, flyingActivationRange ); ++ maxRange = Math.max( maxRange, waterActivationRange ); ++ maxRange = Math.max( maxRange, villagerActivationRange ); ++ // Paper end + maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); + + for ( EntityHuman player : world.getPlayers() ) +@@ -130,6 +208,11 @@ public class ActivationRange + ActivationType.RAIDER.boundingBox = player.getBoundingBox().grow( raiderActivationRange, 256, raiderActivationRange ); + ActivationType.ANIMAL.boundingBox = player.getBoundingBox().grow( animalActivationRange, 256, animalActivationRange ); + ActivationType.MONSTER.boundingBox = player.getBoundingBox().grow( monsterActivationRange, 256, monsterActivationRange ); ++ // Paper start ++ ActivationType.WATER.boundingBox = player.getBoundingBox().grow( waterActivationRange, 256, waterActivationRange ); ++ ActivationType.FLYING_MONSTER.boundingBox = player.getBoundingBox().grow( flyingActivationRange, 256, flyingActivationRange ); ++ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().grow( villagerActivationRange, 256, waterActivationRange ); ++ // Paper end + + int i = MathHelper.floor( maxBB.minX / 16.0D ); + int j = MathHelper.floor( maxBB.maxX / 16.0D ); +@@ -140,7 +223,7 @@ public class ActivationRange + { + for ( int j1 = k; j1 <= l; ++j1 ) + { +- Chunk chunk = (Chunk) world.getChunkIfLoadedImmediately( i1, j1 ); ++ Chunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper + if ( chunk != null ) + { + activateChunkEntities( chunk ); +@@ -158,19 +241,15 @@ public class ActivationRange + */ + private static void activateChunkEntities(Chunk chunk) + { +- for ( java.util.List slice : chunk.entitySlices ) +- { +- for ( Entity entity : (Collection) slice ) ++ // Paper start ++ Entity[] rawData = chunk.entities.getRawData(); ++ for (int i = 0; i < chunk.entities.size(); i++) { ++ Entity entity = rawData[i]; ++ //for ( Entity entity : (Collection) slice ) ++ // Paper end + { +- if ( MinecraftServer.currentTick > entity.activatedTick ) +- { +- if ( entity.defaultActivationState ) +- { +- entity.activatedTick = MinecraftServer.currentTick; +- continue; +- } +- if ( entity.activationType.boundingBox.c( entity.getBoundingBox() ) ) +- { ++ if (MinecraftServer.currentTick > entity.activatedTick) { ++ if (entity.defaultActivationState || entity.activationType.boundingBox.c(entity.getBoundingBox())) { // Paper + entity.activatedTick = MinecraftServer.currentTick; + } + } +@@ -185,56 +264,105 @@ public class ActivationRange + * @param entity + * @return + */ +- public static boolean checkEntityImmunities(Entity entity) ++ public static int checkEntityImmunities(Entity entity) // Paper - return # of ticks to get immunity + { ++ // Paper start ++ SpigotWorldConfig config = entity.world.spigotConfig; ++ int inactiveWakeUpImmunity = checkInactiveWakeup(entity); ++ if (inactiveWakeUpImmunity > -1) { ++ return inactiveWakeUpImmunity; ++ } ++ if (entity.fireTicks > 0) { ++ return 2; ++ } ++ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; ++ // Paper end + // quick checks. +- if ( entity.inWater || entity.fireTicks > 0 ) ++ if ( (entity.activationType != ActivationType.WATER && entity.inWater && entity.isPushedByWater()) ) // Paper + { +- return true; ++ return 100; // Paper + } + if ( !( entity instanceof EntityArrow ) ) + { +- if ( !entity.isOnGround() || !entity.passengers.isEmpty() || entity.isPassenger() ) ++ if ( (!entity.isOnGround() && !(entity instanceof EntityFlying)) ) // Paper - remove passengers logic + { +- return true; ++ return 10; // Paper + } + } else if ( !( (EntityArrow) entity ).inGround ) + { +- return true; ++ return 1; // Paper + } + // special cases. + if ( entity instanceof EntityLiving ) + { + EntityLiving living = (EntityLiving) entity; +- if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTicks > 0 || living.effects.size() > 0 ) ++ if ( living.isClimbing() || living.jumping || living.hurtTicks > 0 || living.effects.size() > 0 ) // Paper + { +- return true; ++ return 1; // Paper + } +- if ( entity instanceof EntityCreature && ( (EntityCreature) entity ).getGoalTarget() != null ) ++ if ( entity instanceof EntityInsentient && ((EntityInsentient) entity ).getGoalTarget() != null) // Paper + { +- return true; ++ return 20; // Paper + } +- if ( entity instanceof EntityVillager && ( (EntityVillager) entity ).canBreed() ) ++ // Paper start ++ if (entity instanceof EntityBee) { ++ EntityBee bee = (EntityBee)entity; ++ BlockPosition movingTarget = bee.getMovingTarget(); ++ if (bee.isAngry() || ++ (bee.getHivePos() != null && bee.getHivePos().equals(movingTarget)) || ++ (bee.getFlowerPos() != null && bee.getFlowerPos().equals(movingTarget)) ++ ) { ++ return 20; ++ } ++ } ++ if ( entity instanceof EntityVillager ) { ++ BehaviorController behaviorController = ((EntityVillager) entity).getBehaviorController(); ++ ++ if (config.villagersActiveForPanic) { ++ for (Activity activity : VILLAGER_PANIC_IMMUNITIES) { ++ if (behaviorController.c(activity)) { ++ return 20*5; ++ } ++ } ++ } ++ ++ if (config.villagersWorkImmunityAfter > 0 && inactiveFor >= config.villagersWorkImmunityAfter) { ++ if (behaviorController.c(Activity.WORK)) { ++ return config.villagersWorkImmunityFor; ++ } ++ } ++ } ++ if ( entity instanceof EntityLlama && ( (EntityLlama) entity ).inCaravan() ) + { +- return true; ++ return 1; + } ++ // Paper end + if ( entity instanceof EntityAnimal ) + { + EntityAnimal animal = (EntityAnimal) entity; + if ( animal.isBaby() || animal.isInLove() ) + { +- return true; ++ return 5; // Paper + } + if ( entity instanceof EntitySheep && ( (EntitySheep) entity ).isSheared() ) + { +- return true; ++ return 1; // Paper + } + } + if (entity instanceof EntityCreeper && ((EntityCreeper) entity).isIgnited()) { // isExplosive +- return true; ++ return 20; // Paper + } ++ // Paper start ++ if (entity instanceof EntityInsentient && ((EntityInsentient) entity).targetSelector.hasTasks() ) { ++ return 0; ++ } ++ if (entity instanceof EntityPillager) { ++ EntityPillager pillager = (EntityPillager) entity; ++ // TODO:? ++ } ++ // Paper end + } +- return false; ++ return -1; // Paper + } + + /** +@@ -249,8 +377,19 @@ public class ActivationRange + if ( !entity.inChunk || entity instanceof EntityFireworks ) { + return true; + } ++ // Paper start - special case always immunities ++ // immunize brand new entities, dead entities, and portal scenarios ++ if (entity.defaultActivationState || entity.ticksLived < 20*10 || !entity.isAlive() || entity.inPortal || entity.portalCooldown > 0) { ++ return true; ++ } ++ // immunize leashed entities ++ if (entity instanceof EntityInsentient && ((EntityInsentient)entity).leashHolder instanceof EntityHuman) { ++ return true; ++ } ++ // Paper end + +- boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; ++ boolean isActive = entity.activatedTick >= MinecraftServer.currentTick; ++ entity.isTemporarilyActive = false; // Paper + + // Should this entity tick? + if ( !isActive ) +@@ -258,15 +397,19 @@ public class ActivationRange + if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) + { + // Check immunities every 20 ticks. +- if ( checkEntityImmunities( entity ) ) +- { +- // Triggered some sort of immunity, give 20 full ticks before we check again. +- entity.activatedTick = MinecraftServer.currentTick + 20; ++ // Paper start ++ int immunity = checkEntityImmunities(entity); ++ if (immunity >= 0) { ++ entity.activatedTick = MinecraftServer.currentTick + immunity; ++ } else { ++ entity.isTemporarilyActive = true; + } ++ // Paper end + isActive = true; ++ + } + // Add a little performance juice to active entities. Skip 1/4 if not immune. +- } else if ( !entity.defaultActivationState && entity.ticksLived % 4 == 0 && !checkEntityImmunities( entity ) ) ++ } else if (entity.ticksLived % 4 == 0 && checkEntityImmunities( entity) < 0 ) // Paper + { + isActive = false; + } +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 34ee684901906fc2ef5f0d09680d2686b813e52b..6b015c1f26facb4e82d75b252164dec05731ca6c 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -180,13 +180,59 @@ public class SpigotWorldConfig + public int monsterActivationRange = 32; + public int raiderActivationRange = 48; + public int miscActivationRange = 16; ++ // Paper start ++ public int flyingMonsterActivationRange = 32; ++ public int waterActivationRange = 16; ++ public int villagerActivationRange = 32; ++ public int wakeUpInactiveAnimals = 4; ++ public int wakeUpInactiveAnimalsEvery = 60*20; ++ public int wakeUpInactiveAnimalsFor = 5*20; ++ public int wakeUpInactiveMonsters = 8; ++ public int wakeUpInactiveMonstersEvery = 20*20; ++ public int wakeUpInactiveMonstersFor = 5*20; ++ public int wakeUpInactiveVillagers = 4; ++ public int wakeUpInactiveVillagersEvery = 30*20; ++ public int wakeUpInactiveVillagersFor = 5*20; ++ public int wakeUpInactiveFlying = 8; ++ public int wakeUpInactiveFlyingEvery = 10*20; ++ public int wakeUpInactiveFlyingFor = 5*20; ++ public int villagersWorkImmunityAfter = 5*20; ++ public int villagersWorkImmunityFor = 20; ++ public boolean villagersActiveForPanic = true; ++ // Paper end + public boolean tickInactiveVillagers = true; + private void activationRange() + { ++ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", animalActivationRange) != animalActivationRange; // Paper + animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange ); + monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange ); + raiderActivationRange = getInt( "entity-activation-range.raiders", raiderActivationRange ); + miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange ); ++ // Paper start ++ waterActivationRange = getInt( "entity-activation-range.water", waterActivationRange ); ++ villagerActivationRange = getInt( "entity-activation-range.villagers", hasAnimalsConfig ? animalActivationRange : villagerActivationRange ); ++ flyingMonsterActivationRange = getInt( "entity-activation-range.flying-monsters", flyingMonsterActivationRange ); ++ ++ wakeUpInactiveAnimals = getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", wakeUpInactiveAnimals); ++ wakeUpInactiveAnimalsEvery = getInt("entity-activation-range.wake-up-inactive.animals-every", wakeUpInactiveAnimalsEvery); ++ wakeUpInactiveAnimalsFor = getInt("entity-activation-range.wake-up-inactive.animals-for", wakeUpInactiveAnimalsFor); ++ ++ wakeUpInactiveMonsters = getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", wakeUpInactiveMonsters); ++ wakeUpInactiveMonstersEvery = getInt("entity-activation-range.wake-up-inactive.monsters-every", wakeUpInactiveMonstersEvery); ++ wakeUpInactiveMonstersFor = getInt("entity-activation-range.wake-up-inactive.monsters-for", wakeUpInactiveMonstersFor); ++ ++ wakeUpInactiveVillagers = getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", wakeUpInactiveVillagers); ++ wakeUpInactiveVillagersEvery = getInt("entity-activation-range.wake-up-inactive.villagers-every", wakeUpInactiveVillagersEvery); ++ wakeUpInactiveVillagersFor = getInt("entity-activation-range.wake-up-inactive.villagers-for", wakeUpInactiveVillagersFor); ++ ++ wakeUpInactiveFlying = getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", wakeUpInactiveFlying); ++ wakeUpInactiveFlyingEvery = getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", wakeUpInactiveFlyingEvery); ++ wakeUpInactiveFlyingFor = getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", wakeUpInactiveFlyingFor); ++ ++ villagersWorkImmunityAfter = getInt( "entity-activation-range.villagers-work-immunity-after", villagersWorkImmunityAfter ); ++ villagersWorkImmunityFor = getInt( "entity-activation-range.villagers-work-immunity-for", villagersWorkImmunityFor ); ++ villagersActiveForPanic = getBoolean( "entity-activation-range.villagers-active-for-panic", villagersActiveForPanic ); ++ // Paper end + tickInactiveVillagers = getBoolean( "entity-activation-range.tick-inactive-villagers", tickInactiveVillagers ); + log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Ra " + raiderActivationRange + " / Mi " + miscActivationRange + " / Tiv " + tickInactiveVillagers ); + } diff --git a/patches/server-unmapped/0401-Fix-items-vanishing-through-end-portal.patch b/patches/server-unmapped/0401-Fix-items-vanishing-through-end-portal.patch new file mode 100644 index 0000000000..721133fa97 --- /dev/null +++ b/patches/server-unmapped/0401-Fix-items-vanishing-through-end-portal.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AJMFactsheets +Date: Wed, 22 Jan 2020 19:52:28 -0600 +Subject: [PATCH] Fix items vanishing through end portal + +If the Paper configuration option "keep-spawn-loaded" is set to false, +items entering the overworld from the end will spawn at Y = 0. + +This is due to logic in the getHighestBlockYAt method in World.java +only searching the heightmap if the chunk is loaded. + +Quickly loading the exact world spawn chunk before searching the +heightmap resolves the issue without having to load all spawn chunks. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 32dad0b72ee0d0a1ac30decb0fb52f4399f9f39f..b1495da5fdead24caf9e936a385d97fd2db2a0cc 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2735,6 +2735,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + BlockPosition blockposition1; + + if (flag1) { ++ // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate ++ this.world.getChunkAtWorldCoords(this.world.getSpawn()); ++ // Paper end + blockposition1 = WorldServer.a; + } else { + blockposition1 = worldserver.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver.getSpawn()); diff --git a/patches/server-unmapped/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server-unmapped/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch new file mode 100644 index 0000000000..7fbf667ed7 --- /dev/null +++ b/patches/server-unmapped/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 26 Jan 2020 16:30:19 -0600 +Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java +index 4044861622294a317fef7e93aa86e96e8474b513..2aa5789437ba7eb20579da238c407a65a25b1d44 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java +@@ -16,7 +16,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; + + public class ControllerMove { + +- protected final EntityInsentient a; ++ protected final EntityInsentient a; public final EntityInsentient getEntity() { return a; } // Paper - OBFHELPER + protected double b; + protected double c; + protected double d; +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java +index 80cba36bc59e89c40c96ca556594a4285f06fc6f..d0cbc429144b89498a7f4dc6ff64924c5ba54ad8 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java +@@ -16,7 +16,7 @@ public class ControllerMoveFlying extends ControllerMove { + } + + @Override +- public void a() { ++ public void a() { tick(); } public void tick() { // Paper - OBFHELPER + if (this.h == ControllerMove.Operation.MOVE_TO) { + this.h = ControllerMove.Operation.WAIT; + this.a.setNoGravity(true); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +index 1ecf73f874f404f58a99316ae027f76db6b557db..7ce8eaeb9af3547869f467910b6a458118c63c1f 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +@@ -111,7 +111,17 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB + + public EntityBee(EntityTypes entitytypes, World world) { + super(entitytypes, world); +- this.moveController = new ControllerMoveFlying(this, 20, true); ++ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 ++ this.moveController = new ControllerMoveFlying(this, 20, true) { ++ @Override ++ public void tick() { ++ if (getEntity().locY() <= 0) { ++ getEntity().setNoGravity(false); ++ } ++ super.tick(); ++ } ++ }; ++ // Paper end + this.lookController = new EntityBee.j(this); + this.a(PathType.DANGER_FIRE, -1.0F); + this.a(PathType.WATER, -1.0F); diff --git a/patches/server-unmapped/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server-unmapped/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch new file mode 100644 index 0000000000..87a5073590 --- /dev/null +++ b/patches/server-unmapped/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 25 Jan 2020 17:04:35 -0800 +Subject: [PATCH] Optimise getChunkAt calls for loaded chunks + +bypass the need to get a player chunk, then get the either, +then unwrap it... + +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 12b9be00d486ec960ef0ebc750f56011c90ce37c..5caf2121f2e551d7b4f0ddc74f10a44dc28ac62b 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -470,6 +470,12 @@ public class ChunkProviderServer extends IChunkProvider { + return this.getChunkAt(i, j, chunkstatus, flag); + }, this.serverThreadQueue).join(); + } else { ++ // Paper start - optimise for loaded chunks ++ Chunk ifLoaded = this.getChunkAtIfLoadedMainThread(i, j); ++ if (ifLoaded != null) { ++ return ifLoaded; ++ } ++ // Paper end + GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); + + gameprofilerfiller.c("getChunk"); +@@ -520,39 +526,7 @@ public class ChunkProviderServer extends IChunkProvider { + if (Thread.currentThread() != this.serverThread) { + return null; + } else { +- this.world.getMethodProfiler().c("getChunkNow"); +- long k = ChunkCoordIntPair.pair(i, j); +- +- for (int l = 0; l < 4; ++l) { +- if (k == this.cachePos[l] && this.cacheStatus[l] == ChunkStatus.FULL) { +- IChunkAccess ichunkaccess = this.cacheChunk[l]; +- +- return ichunkaccess instanceof Chunk ? (Chunk) ichunkaccess : null; +- } +- } +- +- PlayerChunk playerchunk = this.getChunk(k); +- +- if (playerchunk == null) { +- return null; +- } else { +- Either either = (Either) playerchunk.b(ChunkStatus.FULL).getNow(null); // CraftBukkit - decompile error +- +- if (either == null) { +- return null; +- } else { +- IChunkAccess ichunkaccess1 = (IChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error +- +- if (ichunkaccess1 != null) { +- this.a(k, ichunkaccess1, ChunkStatus.FULL); +- if (ichunkaccess1 instanceof Chunk) { +- return (Chunk) ichunkaccess1; +- } +- } +- +- return null; +- } +- } ++ return this.getChunkAtIfLoadedMainThread(i, j); // Paper - optimise for loaded chunks + } + } + diff --git a/patches/server-unmapped/0404-Allow-overriding-the-java-version-check.patch b/patches/server-unmapped/0404-Allow-overriding-the-java-version-check.patch new file mode 100644 index 0000000000..04082e9a36 --- /dev/null +++ b/patches/server-unmapped/0404-Allow-overriding-the-java-version-check.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 8 Feb 2020 18:02:24 -0600 +Subject: [PATCH] Allow overriding the java version check + +-DPaper.IgnoreJavaVersion=true + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 808a7688ed81bdfef623ee0a151ff8f94df2a3d7..c519ceca6f7788ca7c5d74ad1001dbc09f62681c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -181,7 +181,7 @@ public class Main { + float javaVersion = Float.parseFloat(System.getProperty("java.class.version")); + if (javaVersion > 60.0) { + System.err.println("Unsupported Java detected (" + javaVersion + "). Only up to Java 16 is supported."); +- return; ++ if (!Boolean.getBoolean("Paper.IgnoreJavaVersion")) return; // Paper + } + + try { diff --git a/patches/server-unmapped/0405-Add-ThrownEggHatchEvent.patch b/patches/server-unmapped/0405-Add-ThrownEggHatchEvent.patch new file mode 100644 index 0000000000..60a1317040 --- /dev/null +++ b/patches/server-unmapped/0405-Add-ThrownEggHatchEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 9 Feb 2020 00:19:05 -0600 +Subject: [PATCH] Add ThrownEggHatchEvent + +Adds a new event similar to PlayerEggThrowEvent, but without the Player requirement +(dispensers can throw eggs to hatch them, too). + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java b/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java +index 01cee6599f5d21a29310c30a8b1e505023d1a260..dc2e51718395494f60b0376d65d496daf2f76e71 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java +@@ -67,6 +67,16 @@ public class EntityEgg extends EntityProjectileThrowable { + hatchingType = event.getHatchingType(); + } + ++ // Paper start ++ com.destroystokyo.paper.event.entity.ThrownEggHatchEvent event = new com.destroystokyo.paper.event.entity.ThrownEggHatchEvent((org.bukkit.entity.Egg) getBukkitEntity(), hatching, b0, hatchingType); ++ event.callEvent(); ++ ++ b0 = event.getNumHatches(); ++ hatching = event.isHatching(); ++ hatchingType = event.getHatchingType(); ++ // Paper end ++ ++ + if (hatching) { + for (int i = 0; i < b0; ++i) { + Entity entity = world.getWorld().createEntity(new org.bukkit.Location(world.getWorld(), this.locX(), this.locY(), this.locZ(), this.yaw, 0.0F), hatchingType.getEntityClass()); diff --git a/patches/server-unmapped/0406-Optimise-random-block-ticking.patch b/patches/server-unmapped/0406-Optimise-random-block-ticking.patch new file mode 100644 index 0000000000..8fd5f28cc8 --- /dev/null +++ b/patches/server-unmapped/0406-Optimise-random-block-ticking.patch @@ -0,0 +1,407 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 27 Jan 2020 21:28:00 -0800 +Subject: [PATCH] Optimise random block ticking + +Massive performance improvement for random block ticking. +The performance increase comes from the fact that the vast +majority of attempted block ticks (~95% in my testing) fail +because the randomly selected block is not tickable. + +Now only tickable blocks are targeted, however this means that +the maximum number of block ticks occurs per chunk. However, +not all chunks are going to be targeted. The percent chance +of a chunk being targeted is based on how many tickable blocks +are in the chunk. +This means that while block ticks are spread out less, the +total number of blocks ticked per world tick remains the same. +Therefore, the chance of a random tickable block being ticked +remains the same. + +diff --git a/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3edc8e52e06a62ce9f8cc734fd7458b37cfaad91 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java +@@ -0,0 +1,46 @@ ++package com.destroystokyo.paper.util.math; ++ ++import java.util.Random; ++ ++public final class ThreadUnsafeRandom extends Random { ++ ++ // See javadoc and internal comments for java.util.Random where these values come from, how they are used, and the author for them. ++ private static final long multiplier = 0x5DEECE66DL; ++ private static final long addend = 0xBL; ++ private static final long mask = (1L << 48) - 1; ++ ++ private static long initialScramble(long seed) { ++ return (seed ^ multiplier) & mask; ++ } ++ ++ private long seed; ++ ++ @Override ++ public void setSeed(long seed) { ++ // note: called by Random constructor ++ this.seed = initialScramble(seed); ++ } ++ ++ @Override ++ protected int next(int bits) { ++ // avoid the expensive CAS logic used by superclass ++ return (int) (((this.seed = this.seed * multiplier + addend) & mask) >>> (48 - bits)); ++ } ++ ++ // Taken from ++ // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ ++ // https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2016/06/25/fastrange.c ++ // Original license is public domain ++ public static int fastRandomBounded(final long randomInteger, final long limit) { ++ // randomInteger must be [0, pow(2, 32)) ++ // limit must be [0, pow(2, 32)) ++ return (int)((randomInteger * limit) >>> 32); ++ } ++ ++ @Override ++ public int nextInt(int bound) { ++ // yes this breaks random's spec ++ // however there's nothing that uses this class that relies on it ++ return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound); ++ } ++} +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index 4c9ec211470f95d538d1d95c74796190edf99b87..8c0aeb51f5e230fd6109e750732eb54559bc9637 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -468,6 +468,7 @@ public class BlockPosition extends BaseBlockPosition { + return this.d(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); + } + ++ public final BlockPosition.MutableBlockPosition setValues(final BaseBlockPosition baseblockposition) { return this.g(baseblockposition); } // Paper - OBFHELPER + public BlockPosition.MutableBlockPosition g(BaseBlockPosition baseblockposition) { + return this.d(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); + } +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 17c6118fb1ea1f16d37eb13116e11f886274ba95..82f9c49233acce3c95d8a07b2a1b187d5c57552d 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -675,7 +675,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { + }); + } + +- public void a(Chunk chunk, int i) { ++ // Paper start - optimise random block ticking ++ private final BlockPosition.MutableBlockPosition chunkTickMutablePosition = new BlockPosition.MutableBlockPosition(); ++ private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom(); ++ // Paper end ++ ++ public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper + ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); + boolean flag = this.isRaining(); + int j = chunkcoordintpair.d(); +@@ -683,10 +688,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { + GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); + + gameprofilerfiller.enter("thunder"); +- BlockPosition blockposition; ++ final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change + + if (!this.paperConfig.disableThunder && flag && this.W() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder +- blockposition = this.a(this.a(j, 0, k, 15)); ++ blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper + if (this.isRainingAt(blockposition)) { + DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); + boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper +@@ -709,59 +714,77 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + gameprofilerfiller.exitEnter("iceandsnow"); +- if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow +- blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, this.a(j, 0, k, 15)); +- BlockPosition blockposition1 = blockposition.down(); ++ if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking ++ // Paper start - optimise chunk ticking ++ this.getRandomBlockPosition(j, 0, k, 15, blockposition); ++ int normalY = chunk.getHighestBlockY(HeightMap.Type.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15); ++ int downY = normalY - 1; ++ blockposition.setY(normalY); ++ // Paper end + BiomeBase biomebase = this.getBiome(blockposition); + +- if (biomebase.a(this, blockposition1)) { +- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.getBlockData(), null); // CraftBukkit ++ // Paper start - optimise chunk ticking ++ blockposition.setY(downY); ++ if (biomebase.a(this, blockposition)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.ICE.getBlockData(), null); // CraftBukkit ++ // Paper end + } + ++ blockposition.setY(normalY); // Paper + if (flag && biomebase.b(this, blockposition)) { + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.getBlockData(), null); // CraftBukkit + } + +- if (flag && this.getBiome(blockposition1).c() == BiomeBase.Precipitation.RAIN) { +- this.getType(blockposition1).getBlock().c((World) this, blockposition1); ++ // Paper start - optimise chunk ticking ++ blockposition.setY(downY); ++ if (flag && this.getBiome(blockposition).c() == BiomeBase.Precipitation.RAIN) { ++ chunk.getType(blockposition).getBlock().c((World) this, blockposition); ++ // Paper end + } + } + +- gameprofilerfiller.exitEnter("tickBlocks"); +- timings.chunkTicksBlocks.startTiming(); // Paper ++ // Paper start - optimise random block ticking ++ gameprofilerfiller.exit(); + if (i > 0) { +- ChunkSection[] achunksection = chunk.getSections(); +- int l = achunksection.length; ++ gameprofilerfiller.enter("randomTick"); ++ timings.chunkTicksBlocks.startTiming(); // Paper + +- for (int i1 = 0; i1 < l; ++i1) { +- ChunkSection chunksection = achunksection[i1]; ++ ChunkSection[] sections = chunk.getSections(); + +- if (chunksection != Chunk.a && chunksection.d()) { +- int j1 = chunksection.getYPosition(); ++ for (int sectionIndex = 0; sectionIndex < 16; ++sectionIndex) { ++ ChunkSection section = sections[sectionIndex]; ++ if (section == null || section.tickingList.size() == 0) { ++ continue; ++ } + +- for (int k1 = 0; k1 < i; ++k1) { +- BlockPosition blockposition2 = this.a(j, j1, k, 15); ++ int yPos = sectionIndex << 4; + +- gameprofilerfiller.enter("randomTick"); +- IBlockData iblockdata = chunksection.getType(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); ++ for (int a = 0; a < randomTickSpeed; ++a) { ++ int tickingBlocks = section.tickingList.size(); ++ int index = this.randomTickRandom.nextInt(16 * 16 * 16); ++ if (index >= tickingBlocks) { ++ continue; ++ } + +- if (iblockdata.isTicking()) { +- iblockdata.b(this, blockposition2, this.random); +- } ++ long raw = section.tickingList.getRaw(index); ++ int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); ++ int randomX = location & 15; ++ int randomY = ((location >>> (4 + 4)) & 255) | yPos; ++ int randomZ = (location >>> 4) & 15; + +- Fluid fluid = iblockdata.getFluid(); ++ BlockPosition blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ); ++ IBlockData iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); + +- if (fluid.f()) { +- fluid.b(this, blockposition2, this.random); +- } ++ iblockdata.b(this, blockposition2, this.randomTickRandom); + +- gameprofilerfiller.exit(); +- } ++ // We drop the fluid tick since LAVA is ALREADY TICKED by the above method. ++ // TODO CHECK ON UPDATE + } + } ++ gameprofilerfiller.exit(); ++ timings.chunkTicksBlocks.stopTiming(); // Paper ++ // Paper end + } +- timings.chunkTicksBlocks.stopTiming(); // Paper +- gameprofilerfiller.exit(); + } + + protected BlockPosition a(BlockPosition blockposition) { +diff --git a/src/main/java/net/minecraft/util/DataBits.java b/src/main/java/net/minecraft/util/DataBits.java +index c4f3b680512fb15cea01ad12d0a00c6e60bf34b7..cfa444cf384920d446c6dc14b23e5158fc28df3b 100644 +--- a/src/main/java/net/minecraft/util/DataBits.java ++++ b/src/main/java/net/minecraft/util/DataBits.java +@@ -112,4 +112,32 @@ public class DataBits { + } + + } ++ ++ // Paper start ++ public final void forEach(DataBitConsumer consumer) { ++ int i = 0; ++ long[] along = this.b; ++ int j = along.length; ++ ++ for (int k = 0; k < j; ++k) { ++ long l = along[k]; ++ ++ for (int i1 = 0; i1 < this.f; ++i1) { ++ consumer.accept(i, (int) (l & this.d)); ++ l >>= this.c; ++ ++i; ++ if (i >= this.e) { ++ return; ++ } ++ } ++ } ++ } ++ ++ @FunctionalInterface ++ public static interface DataBitConsumer { ++ ++ void accept(int location, int data); ++ ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java +index 09a6310af6712d36c20167256b60dc3235e76021..ecec8a3c4d4b5d491f79ad60d7ce5a118f30b3db 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java +@@ -91,7 +91,7 @@ public class EntityTurtle extends EntityAnimal { + } + + public void setHomePos(BlockPosition blockposition) { +- this.datawatcher.set(EntityTurtle.bp, blockposition); ++ this.datawatcher.set(EntityTurtle.bp, blockposition.immutableCopy()); // Paper - called with mutablepos... + } + + public BlockPosition getHomePos() { // Paper - public +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index c4680142bf23d30169555abe7db78d85811e042b..cc41dcd85760b57bb8076b37e9a907d1cb4e12c7 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -1472,10 +1472,18 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public abstract ITagRegistry p(); + + public BlockPosition a(int i, int j, int k, int l) { ++ // Paper start - allow use of mutable pos ++ BlockPosition.MutableBlockPosition ret = new BlockPosition.MutableBlockPosition(); ++ this.getRandomBlockPosition(i, j, k, l, ret); ++ return ret.immutableCopy(); ++ } ++ public final BlockPosition.MutableBlockPosition getRandomBlockPosition(int i, int j, int k, int l, BlockPosition.MutableBlockPosition out) { ++ // Paper end + this.n = this.n * 3 + 1013904223; + int i1 = this.n >> 2; + +- return new BlockPosition(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); ++ out.setValues(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); // Paper - change to setValues call ++ return out; // Paper + } + + public boolean isSavingDisabled() { +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index e7bb33125a25b9e5a68013b15d7b5b6b6769ab9b..fc55e89260fdec2c5045e8f00e091191980ff1f2 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -640,8 +640,8 @@ public class Chunk implements IChunkAccess { + this.entities.remove(entity); // Paper + } + +- @Override +- public int getHighestBlock(HeightMap.Type heightmap_type, int i, int j) { ++ public final int getHighestBlockY(HeightMap.Type heightmap_type, int i, int j) { return this.getHighestBlock(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1 ++ @Override public int getHighestBlock(HeightMap.Type heightmap_type, int i, int j) { // Paper + return ((HeightMap) this.heightMap.get(heightmap_type)).a(i & 15, j & 15) - 1; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +index 0b4e346daaea91565fde2f789fafa8b431a7b042..4bc26a7a4ae91aac90c256758ec8868d83027c0c 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +@@ -14,12 +14,14 @@ import net.minecraft.world.level.material.Fluid; + public class ChunkSection { + + public static final DataPalette GLOBAL_PALETTE = new DataPaletteGlobal<>(Block.REGISTRY_ID, Blocks.AIR.getBlockData()); +- private final int yPos; ++ final int yPos; // Paper - private -> package-private + short nonEmptyBlockCount; // Paper - package-private +- private short tickingBlockCount; ++ short tickingBlockCount; // Paper - private -> package-private + private short e; + final DataPaletteBlock blockIds; // Paper - package-private + ++ public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper ++ + // Paper start - Anti-Xray - Add parameters + @Deprecated public ChunkSection(int i) { this(i, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere + public ChunkSection(int i, IChunkAccess chunk, World world, boolean initializeBlocks) { +@@ -74,6 +76,9 @@ public class ChunkSection { + --this.nonEmptyBlockCount; + if (iblockdata1.isTicking()) { + --this.tickingBlockCount; ++ // Paper start ++ this.tickingList.remove(i, j, k); ++ // Paper end + } + } + +@@ -85,6 +90,9 @@ public class ChunkSection { + ++this.nonEmptyBlockCount; + if (iblockdata.isTicking()) { + ++this.tickingBlockCount; ++ // Paper start ++ this.tickingList.add(i, j, k, iblockdata); ++ // Paper end + } + } + +@@ -120,23 +128,29 @@ public class ChunkSection { + } + + public void recalcBlockCounts() { ++ // Paper start ++ this.tickingList.clear(); ++ // Paper end + this.nonEmptyBlockCount = 0; + this.tickingBlockCount = 0; + this.e = 0; +- this.blockIds.a((iblockdata, i) -> { ++ this.blockIds.forEachLocation((iblockdata, location) -> { // Paper + Fluid fluid = iblockdata.getFluid(); + + if (!iblockdata.isAir()) { +- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); ++ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); + if (iblockdata.isTicking()) { +- this.tickingBlockCount = (short) (this.tickingBlockCount + i); ++ this.tickingBlockCount = (short) (this.tickingBlockCount + 1); ++ // Paper start ++ this.tickingList.add(location, iblockdata); ++ // Paper end + } + } + + if (!fluid.isEmpty()) { +- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); ++ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); + if (fluid.f()) { +- this.e = (short) (this.e + i); ++ this.e = (short) (this.e + 1); + } + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +index 68d53a51acc9790b9cda20ec4d2ec6edd1baac1a..86dfab740883c138a0df8a3da9dfb4eb9acefaa3 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java ++++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java +@@ -286,6 +286,14 @@ public class DataPaletteBlock implements DataPaletteExpandable { + }); + } + ++ // Paper start ++ public void forEachLocation(DataPaletteBlock.a datapaletteblock_a) { ++ this.getDataBits().forEach((int location, int data) -> { ++ datapaletteblock_a.accept(this.getDataPalette().getObject(data), location); ++ }); ++ } ++ // Paper end ++ + @FunctionalInterface + public interface a { + diff --git a/patches/server-unmapped/0407-Entity-Jump-API.patch b/patches/server-unmapped/0407-Entity-Jump-API.patch new file mode 100644 index 0000000000..99dca253e4 --- /dev/null +++ b/patches/server-unmapped/0407-Entity-Jump-API.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 8 Feb 2020 23:26:11 -0600 +Subject: [PATCH] Entity Jump API + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index ffb4072f46456b3a2b2daa55947787cee774d26d..571e6bced3cfaacbd40378e67b01cdfda550feb7 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -2876,8 +2876,10 @@ public abstract class EntityLiving extends Entity { + } else if (this.aQ() && (!this.onGround || d7 > d8)) { + this.c((Tag) TagsFluid.LAVA); + } else if ((this.onGround || flag && d7 <= d8) && this.jumpTicks == 0) { ++ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper + this.jump(); + this.jumpTicks = 10; ++ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop + } + } else { + this.jumpTicks = 0; +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java +index f755607872920caae1410d38c431c16b5238c00f..711b322007a0973ff0aebf3c25efbae8fc7741d0 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java +@@ -490,7 +490,9 @@ public class EntityPanda extends EntityAnimal { + EntityPanda entitypanda = (EntityPanda) iterator.next(); + + if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.fh()) { ++ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper + entitypanda.jump(); ++ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop + } + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index db5d9a8107babd42200f911d2b8ebdc15b4d7c8b..468dca6d8c2ec77c3c77c93d04fb9dc329b1befa 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -804,5 +804,19 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public org.bukkit.inventory.EquipmentSlot getHandRaised() { + return getHandle().getRaisedHand() == net.minecraft.world.EnumHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; + } ++ ++ @Override ++ public boolean isJumping() { ++ return getHandle().jumping; ++ } ++ ++ @Override ++ public void setJumping(boolean jumping) { ++ getHandle().setJumping(jumping); ++ if (jumping && getHandle() instanceof EntityInsentient) { ++ // this is needed to actually make a mob jump ++ ((EntityInsentient) getHandle()).getControllerJump().jump(); ++ } ++ } + // Paper end + } diff --git a/patches/server-unmapped/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server-unmapped/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch new file mode 100644 index 0000000000..3fe02b251a --- /dev/null +++ b/patches/server-unmapped/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 7 Feb 2020 14:36:56 -0600 +Subject: [PATCH] Add option to nerf pigmen from nether portals + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 7fbd501d70dccf869a4454e2789a5d68f2e15754..9e4591ddc4b755f4ff5a6f1078b51cb13db80480 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -594,4 +594,9 @@ public class PaperWorldConfig { + disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); + log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); + } ++ ++ public boolean nerfNetherPortalPigmen = false; ++ private void nerfNetherPortalPigmen() { ++ nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index b1495da5fdead24caf9e936a385d97fd2db2a0cc..334d60c71fa13841f9d04af5404cc25acbc0ec76 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -278,6 +278,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public long activatedTick = Integer.MIN_VALUE; + public boolean isTemporarilyActive = false; // Paper + public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one ++ public boolean fromNetherPortal; // Paper + protected int numCollisions = 0; // Paper + public void inactiveTick() { } + // Spigot end +@@ -1694,6 +1695,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + if (spawnedViaMobSpawner) { + nbttagcompound.setBoolean("Paper.FromMobSpawner", true); + } ++ if (fromNetherPortal) { ++ nbttagcompound.setBoolean("Paper.FromNetherPortal", true); ++ } + // Paper end + return nbttagcompound; + } catch (Throwable throwable) { +@@ -1828,6 +1832,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ fromNetherPortal = nbttagcompound.getBoolean("Paper.FromNetherPortal"); + if (nbttagcompound.hasKey("Paper.SpawnReason")) { + String spawnReasonName = nbttagcompound.getString("Paper.SpawnReason"); + try { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockPortal.java b/src/main/java/net/minecraft/world/level/block/BlockPortal.java +index e115ff86987c69f5e3571af5d7f034f24a3f6bba..5f797260eff317409a5039b88b01ad79ee2fdd91 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockPortal.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockPortal.java +@@ -7,6 +7,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.server.level.WorldServer; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityInsentient; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.player.EntityHuman; +@@ -62,6 +63,8 @@ public class BlockPortal extends Block { + + if (entity != null) { + entity.resetPortalCooldown(); ++ entity.fromNetherPortal = true; // Paper ++ if (worldserver.paperConfig.nerfNetherPortalPigmen) ((EntityInsentient) entity).aware = false; // Paper + } + } + } diff --git a/patches/server-unmapped/0409-Make-the-GUI-graph-fancier.patch b/patches/server-unmapped/0409-Make-the-GUI-graph-fancier.patch new file mode 100644 index 0000000000..93777c67a1 --- /dev/null +++ b/patches/server-unmapped/0409-Make-the-GUI-graph-fancier.patch @@ -0,0 +1,436 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 2 Feb 2020 04:00:40 -0600 +Subject: [PATCH] Make the GUI graph fancier + + +diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphColor.java b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a4e641fdcccd3efcd1a2865dc6dc28d50671b995 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java +@@ -0,0 +1,44 @@ ++package com.destroystokyo.paper.gui; ++ ++import java.awt.Color; ++ ++public class GraphColor { ++ private static final Color[] colorLine = new Color[101]; ++ private static final Color[] colorFill = new Color[101]; ++ ++ static { ++ for (int i = 0; i < 101; i++) { ++ Color color = createColor(i); ++ colorLine[i] = new Color(color.getRed() / 2, color.getGreen() / 2, color.getBlue() / 2, 255); ++ colorFill[i] = new Color(colorLine[i].getRed(), colorLine[i].getGreen(), colorLine[i].getBlue(), 125); ++ } ++ } ++ ++ public static Color getLineColor(int percent) { ++ return colorLine[percent]; ++ } ++ ++ public static Color getFillColor(int percent) { ++ return colorFill[percent]; ++ } ++ ++ private static Color createColor(int percent) { ++ if (percent <= 50) { ++ return new Color(0X00FF00); ++ } ++ ++ int value = 510 - (int) (Math.min(Math.max(0, ((percent - 50) / 50F)), 1) * 510); ++ ++ int red, green; ++ if (value < 255) { ++ red = 255; ++ green = (int) (Math.sqrt(value) * 16); ++ } else { ++ green = 255; ++ value = value - 255; ++ red = 255 - (value * value / 255); ++ } ++ ++ return new Color(red, green, 0); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphData.java b/src/main/java/com/destroystokyo/paper/gui/GraphData.java +new file mode 100644 +index 0000000000000000000000000000000000000000..186fc722965e403f76b1480e1c2381fc34e29049 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/GraphData.java +@@ -0,0 +1,47 @@ ++package com.destroystokyo.paper.gui; ++ ++import java.awt.Color; ++ ++public class GraphData { ++ private long total; ++ private long free; ++ private long max; ++ private long usedMem; ++ private int usedPercent; ++ ++ public GraphData(long total, long free, long max) { ++ this.total = total; ++ this.free = free; ++ this.max = max; ++ this.usedMem = total - free; ++ this.usedPercent = usedMem == 0 ? 0 : (int) (usedMem * 100L / max); ++ } ++ ++ public long getTotal() { ++ return total; ++ } ++ ++ public long getFree() { ++ return free; ++ } ++ ++ public long getMax() { ++ return max; ++ } ++ ++ public long getUsedMem() { ++ return usedMem; ++ } ++ ++ public int getUsedPercent() { ++ return usedPercent; ++ } ++ ++ public Color getFillColor() { ++ return GraphColor.getFillColor(usedPercent); ++ } ++ ++ public Color getLineColor() { ++ return GraphColor.getLineColor(usedPercent); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0f29ad583e798c09b2fe3f568ed50cbc719e40e2 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.gui; ++ ++import net.minecraft.server.MinecraftServer; ++ ++import javax.swing.JPanel; ++import javax.swing.Timer; ++import java.awt.BorderLayout; ++import java.awt.Dimension; ++ ++public class GuiStatsComponent extends JPanel { ++ private final Timer timer; ++ private final RAMGraph ramGraph; ++ ++ public GuiStatsComponent(MinecraftServer server) { ++ super(new BorderLayout()); ++ ++ setOpaque(false); ++ ++ ramGraph = new RAMGraph(); ++ RAMDetails ramDetails = new RAMDetails(server); ++ ++ add(ramGraph, "North"); ++ add(ramDetails, "Center"); ++ ++ timer = new Timer(500, (event) -> { ++ ramGraph.update(); ++ ramDetails.update(); ++ }); ++ timer.start(); ++ } ++ ++ @Override ++ public Dimension getPreferredSize() { ++ return new Dimension(350, 200); ++ } ++ ++ public void stop() { a(); } public void a() { ++ timer.stop(); ++ ramGraph.stop(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +new file mode 100644 +index 0000000000000000000000000000000000000000..67d064e3959ed8d886df30ce9d97f86c2443fa39 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +@@ -0,0 +1,73 @@ ++package com.destroystokyo.paper.gui; ++ ++import net.minecraft.SystemUtils; ++import net.minecraft.server.MinecraftServer; ++ ++import javax.swing.DefaultListCellRenderer; ++import javax.swing.DefaultListSelectionModel; ++import javax.swing.JList; ++import javax.swing.border.EmptyBorder; ++import java.awt.Dimension; ++import java.text.DecimalFormat; ++import java.text.DecimalFormatSymbols; ++import java.util.Locale; ++import java.util.Vector; ++ ++public class RAMDetails extends JList { ++ public static final DecimalFormat DECIMAL_FORMAT = SystemUtils.peek(new DecimalFormat("########0.000"), (format) ++ -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT))); ++ ++ private final MinecraftServer server; ++ ++ public RAMDetails(MinecraftServer server) { ++ this.server = server; ++ ++ setBorder(new EmptyBorder(0, 10, 0, 0)); ++ setFixedCellHeight(20); ++ setOpaque(false); ++ ++ DefaultListCellRenderer renderer = new DefaultListCellRenderer(); ++ renderer.setOpaque(false); ++ setCellRenderer(renderer); ++ ++ setSelectionModel(new DefaultListSelectionModel() { ++ @Override ++ public void setAnchorSelectionIndex(final int anchorIndex) { ++ } ++ ++ @Override ++ public void setLeadAnchorNotificationEnabled(final boolean flag) { ++ } ++ ++ @Override ++ public void setLeadSelectionIndex(final int leadIndex) { ++ } ++ ++ @Override ++ public void setSelectionInterval(final int index0, final int index1) { ++ } ++ }); ++ } ++ ++ @Override ++ public Dimension getPreferredSize() { ++ return new Dimension(350, 100); ++ } ++ ++ public void update() { ++ GraphData data = RAMGraph.DATA.peekLast(); ++ Vector vector = new Vector<>(); ++ vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); ++ vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); ++ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); ++ setListData(vector); ++ } ++ ++ public double getAverage(long[] tickTimes) { ++ long total = 0L; ++ for (long value : tickTimes) { ++ total += value; ++ } ++ return ((double) total / (double) tickTimes.length) * 1.0E-6D; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c3e54da4ab6440811aab2f9dd1e218802ac13285 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java +@@ -0,0 +1,144 @@ ++package com.destroystokyo.paper.gui; ++ ++import javax.swing.JComponent; ++import javax.swing.SwingUtilities; ++import javax.swing.Timer; ++import javax.swing.ToolTipManager; ++import java.awt.Color; ++import java.awt.Dimension; ++import java.awt.Graphics; ++import java.awt.MouseInfo; ++import java.awt.Point; ++import java.awt.PointerInfo; ++import java.awt.event.MouseAdapter; ++import java.awt.event.MouseEvent; ++import java.text.SimpleDateFormat; ++import java.util.Date; ++import java.util.LinkedList; ++import java.util.concurrent.TimeUnit; ++ ++public class RAMGraph extends JComponent { ++ public static final LinkedList DATA = new LinkedList() { ++ @Override ++ public boolean add(GraphData data) { ++ if (size() >= 348) { ++ remove(); ++ } ++ return super.add(data); ++ } ++ }; ++ ++ static { ++ GraphData empty = new GraphData(0, 0, 0); ++ for (int i = 0; i < 350; i++) { ++ DATA.add(empty); ++ } ++ } ++ ++ private final Timer timer; ++ private final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); ++ ++ private int currentTick; ++ ++ public RAMGraph() { ++ ToolTipManager.sharedInstance().setInitialDelay(0); ++ ++ addMouseListener(new MouseAdapter() { ++ final int defaultDismissTimeout = ToolTipManager.sharedInstance().getDismissDelay(); ++ final int dismissDelayMinutes = (int) TimeUnit.MINUTES.toMillis(10); ++ ++ @Override ++ public void mouseEntered(MouseEvent me) { ++ ToolTipManager.sharedInstance().setDismissDelay(dismissDelayMinutes); ++ } ++ ++ @Override ++ public void mouseExited(MouseEvent me) { ++ ToolTipManager.sharedInstance().setDismissDelay(defaultDismissTimeout); ++ } ++ }); ++ ++ timer = new Timer(50, (event) -> repaint()); ++ timer.start(); ++ } ++ ++ @Override ++ public Dimension getPreferredSize() { ++ return new Dimension(350, 110); ++ } ++ ++ public void update() { ++ Runtime jvm = Runtime.getRuntime(); ++ DATA.add(new GraphData(jvm.totalMemory(), jvm.freeMemory(), jvm.maxMemory())); ++ ++ PointerInfo pointerInfo = MouseInfo.getPointerInfo(); ++ if (pointerInfo != null) { ++ Point point = pointerInfo.getLocation(); ++ if (point != null) { ++ Point loc = new Point(point); ++ SwingUtilities.convertPointFromScreen(loc, this); ++ if (this.contains(loc)) { ++ ToolTipManager.sharedInstance().mouseMoved( ++ new MouseEvent(this, -1, System.currentTimeMillis(), 0, loc.x, loc.y, ++ point.x, point.y, 0, false, 0)); ++ } ++ } ++ } ++ ++ currentTick++; ++ } ++ ++ @Override ++ public void paint(Graphics graphics) { ++ graphics.setColor(new Color(0xFFFFFFFF)); ++ graphics.fillRect(0, 0, 350, 100); ++ ++ graphics.setColor(new Color(0x888888)); ++ graphics.drawLine(1, 25, 348, 25); ++ graphics.drawLine(1, 50, 348, 50); ++ graphics.drawLine(1, 75, 348, 75); ++ ++ int i = 0; ++ for (GraphData data : DATA) { ++ i++; ++ if ((i + currentTick) % 120 == 0) { ++ graphics.setColor(new Color(0x888888)); ++ graphics.drawLine(i, 1, i, 99); ++ } ++ int used = data.getUsedPercent(); ++ if (used > 0) { ++ Color color = data.getLineColor(); ++ graphics.setColor(data.getFillColor()); ++ graphics.fillRect(i, 100 - used, 1, used); ++ graphics.setColor(color); ++ graphics.fillRect(i, 100 - used, 1, 1); ++ } ++ } ++ ++ graphics.setColor(new Color(0xFF000000)); ++ graphics.drawRect(0, 0, 348, 100); ++ ++ Point m = getMousePosition(); ++ if (m != null && m.x > 0 && m.x < 348 && m.y > 0 && m.y < 100) { ++ GraphData data = DATA.get(m.x); ++ int used = data.getUsedPercent(); ++ graphics.setColor(new Color(0x000000)); ++ graphics.drawLine(m.x, 1, m.x, 99); ++ graphics.drawOval(m.x - 2, 100 - used - 2, 5, 5); ++ graphics.setColor(data.getLineColor()); ++ graphics.fillOval(m.x - 2, 100 - used - 2, 5, 5); ++ setToolTipText(String.format("Used: %s mb (%s%%)
    %s", ++ Math.round(data.getUsedMem() / 1024F / 1024F), ++ used, getTime(m.x))); ++ } ++ } ++ ++ public String getTime(int halfSeconds) { ++ int millis = (348 - halfSeconds) / 2 * 1000; ++ return TIME_FORMAT.format(new Date((System.currentTimeMillis() - millis))); ++ } ++ ++ public void stop() { ++ timer.stop(); ++ } ++} +diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java +index 46d82c1548088b8305f758699388edf0d5d4d050..397194b3e90c9df39cfae17b401c7ac891b0dbb7 100644 +--- a/src/main/java/net/minecraft/SystemUtils.java ++++ b/src/main/java/net/minecraft/SystemUtils.java +@@ -260,6 +260,7 @@ public class SystemUtils { + return supplier.get(); + } + ++ public static T peek(T t0, Consumer consumer) { return a(t0, consumer); } // Paper - OBFHELPER + public static T a(T t0, Consumer consumer) { + consumer.accept(t0); + return t0; +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 566b7c88ca467a92bcba2665edb852f77f8acd1e..b4e058794c3f8a827f3aabab5b98239a4c79c42c 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -218,7 +218,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { ++ private static final DecimalFormat a = (DecimalFormat) SystemUtils.a(new DecimalFormat("########0.000"), (decimalformat) -> { // Paper - decompile error + decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); + }); + private final int[] b = new int[256]; +diff --git a/src/main/java/net/minecraft/server/gui/ServerGUI.java b/src/main/java/net/minecraft/server/gui/ServerGUI.java +index dc2a36f6dbc83ba25bcd59d981f75499adbd22e5..c2c075b9e3b70f863b6c450e4f31d6fde2935be6 100644 +--- a/src/main/java/net/minecraft/server/gui/ServerGUI.java ++++ b/src/main/java/net/minecraft/server/gui/ServerGUI.java +@@ -91,7 +91,7 @@ public class ServerGUI extends JComponent { + + private JComponent c() { + JPanel jpanel = new JPanel(new BorderLayout()); +- GuiStatsComponent guistatscomponent = new GuiStatsComponent(this.c); ++ com.destroystokyo.paper.gui.GuiStatsComponent guistatscomponent = new com.destroystokyo.paper.gui.GuiStatsComponent(this.c); // Paper + + this.e.add(guistatscomponent::a); + jpanel.add(guistatscomponent, "North"); diff --git a/patches/server-unmapped/0410-add-hand-to-BlockMultiPlaceEvent.patch b/patches/server-unmapped/0410-add-hand-to-BlockMultiPlaceEvent.patch new file mode 100644 index 0000000000..9d62e030b8 --- /dev/null +++ b/patches/server-unmapped/0410-add-hand-to-BlockMultiPlaceEvent.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Sun, 1 Mar 2020 22:43:24 +0100 +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 b7ebd2e3e919d09ee99997f2358cc0c399d5041b..0b27d68dce9537c17701bd4944c807414564170b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -349,13 +349,18 @@ public class CraftEventFactory { + } + + org.bukkit.inventory.ItemStack item; ++ //Paper start - add hand to BlockMultiPlaceEvent ++ EquipmentSlot equipmentSlot; + if (hand == EnumHand.MAIN_HAND) { + item = player.getInventory().getItemInMainHand(); ++ equipmentSlot = EquipmentSlot.HAND; + } else { + item = player.getInventory().getItemInOffHand(); ++ equipmentSlot = EquipmentSlot.OFF_HAND; + } + +- BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild); ++ BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild, equipmentSlot); ++ //Paper end + craftServer.getPluginManager().callEvent(event); + + return event; diff --git a/patches/server-unmapped/0411-Prevent-teleporting-dead-entities.patch b/patches/server-unmapped/0411-Prevent-teleporting-dead-entities.patch new file mode 100644 index 0000000000..7d5e3227f2 --- /dev/null +++ b/patches/server-unmapped/0411-Prevent-teleporting-dead-entities.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 3 Mar 2020 05:26:40 +0000 +Subject: [PATCH] Prevent teleporting dead entities + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 72df753d8c8e12cb3efaa02f37b05496701cc9f9..8a8f75acdd55e00ac2e7b5c621d1f522208df2c2 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1470,6 +1470,10 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + + private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { ++ if (player.dead) { ++ LOGGER.info("Attempt to teleport dead player {} restricted", player.getName()); ++ return; ++ } + // CraftBukkit start + if (Float.isNaN(f)) { + f = 0; diff --git a/patches/server-unmapped/0412-Validate-tripwire-hook-placement-before-update.patch b/patches/server-unmapped/0412-Validate-tripwire-hook-placement-before-update.patch new file mode 100644 index 0000000000..75c8efe983 --- /dev/null +++ b/patches/server-unmapped/0412-Validate-tripwire-hook-placement-before-update.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 7 Mar 2020 00:07:51 +0000 +Subject: [PATCH] Validate tripwire hook placement before update + + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java b/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java +index 8b24978cb54f2102d61f27038dedc5e3dc392dbc..5e3cf96b813d2871adf7a7f870af6c6a5dd878c1 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java +@@ -170,6 +170,7 @@ public class BlockTripwireHook extends Block { + + this.a(world, blockposition, flag4, flag5, flag2, flag3); + if (!flag) { ++ if (world.getType(blockposition).getBlock() == Blocks.TRIPWIRE_HOOK) // Paper - validate + world.setTypeAndData(blockposition, (IBlockData) iblockdata3.set(BlockTripwireHook.FACING, enumdirection), 3); + if (flag1) { + this.a(world, blockposition, enumdirection); diff --git a/patches/server-unmapped/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server-unmapped/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch new file mode 100644 index 0000000000..bc4517ce5b --- /dev/null +++ b/patches/server-unmapped/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 13 Apr 2019 16:50:58 -0500 +Subject: [PATCH] Add option to allow iron golems to spawn in air + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 9e4591ddc4b755f4ff5a6f1078b51cb13db80480..fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -387,6 +387,11 @@ public class PaperWorldConfig { + scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); + } + ++ public boolean ironGolemsCanSpawnInAir = false; ++ private void ironGolemsCanSpawnInAir() { ++ ironGolemsCanSpawnInAir = getBoolean("iron-golems-can-spawn-in-air", ironGolemsCanSpawnInAir); ++ } ++ + public boolean armorStandEntityLookups = true; + private void armorStandEntityLookups() { + armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java +index 49495cfbcf9b7742583536b87fc7cbd7c7c4c867..5e2b49d120b724cb5a7ae00940ded4f4875ea8a1 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java +@@ -297,7 +297,7 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { + BlockPosition blockposition1 = blockposition.down(); + IBlockData iblockdata = iworldreader.getType(blockposition1); + +- if (!iblockdata.a((IBlockAccess) iworldreader, blockposition1, (Entity) this)) { ++ if (!iblockdata.a((IBlockAccess) iworldreader, blockposition1, (Entity) this) && !world.paperConfig.ironGolemsCanSpawnInAir) { // Paper + return false; + } else { + for (int i = 1; i < 3; ++i) { diff --git a/patches/server-unmapped/0414-Configurable-chance-of-villager-zombie-infection.patch b/patches/server-unmapped/0414-Configurable-chance-of-villager-zombie-infection.patch new file mode 100644 index 0000000000..0a2c05d50a --- /dev/null +++ b/patches/server-unmapped/0414-Configurable-chance-of-villager-zombie-infection.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zero +Date: Sat, 22 Feb 2020 16:10:31 -0500 +Subject: [PATCH] Configurable chance of villager zombie infection + +This allows you to solve an issue in vanilla behavior where: +* On easy difficulty your villagers will NEVER get infected, meaning they will always die. +* On normal difficulty they will have a 50% of getting infected or dying. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f..525d702d78a609af987ebd2c32169b873e5c05ed 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -604,4 +604,9 @@ public class PaperWorldConfig { + private void nerfNetherPortalPigmen() { + nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); + } ++ ++ public double zombieVillagerInfectionChance = -1.0; ++ private void zombieVillagerInfectionChance() { ++ zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index f406826945dd752e6528743a0c8cad3cfdfc4a95..3d8d4a43e6cd554b6f1eeafa1c8d43cef877139a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -450,10 +450,14 @@ public class EntityZombie extends EntityMonster { + @Override + public void a(WorldServer worldserver, EntityLiving entityliving) { + super.a(worldserver, entityliving); +- if ((worldserver.getDifficulty() == EnumDifficulty.NORMAL || worldserver.getDifficulty() == EnumDifficulty.HARD) && entityliving instanceof EntityVillager) { +- if (worldserver.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) { ++ // Paper start ++ if (world.paperConfig.zombieVillagerInfectionChance != 0.0 && (world.paperConfig.zombieVillagerInfectionChance != -1.0 || worldserver.getDifficulty() == EnumDifficulty.NORMAL || worldserver.getDifficulty() == EnumDifficulty.HARD) && entityliving instanceof EntityVillager) { ++ if (world.paperConfig.zombieVillagerInfectionChance == -1.0 && worldserver.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) { + return; + } ++ if (world.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > world.paperConfig.zombieVillagerInfectionChance) { ++ return; ++ } // Paper end + + EntityVillager entityvillager = (EntityVillager) entityliving; + // CraftBukkit start diff --git a/patches/server-unmapped/0415-Optimise-Chunk-getFluid.patch b/patches/server-unmapped/0415-Optimise-Chunk-getFluid.patch new file mode 100644 index 0000000000..593c9aaac6 --- /dev/null +++ b/patches/server-unmapped/0415-Optimise-Chunk-getFluid.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 14 Jan 2020 14:59:08 -0800 +Subject: [PATCH] Optimise Chunk#getFluid + +Removing the try catch and generally reducing ops should make it +faster on its own, however removing the try catch makes it +easier to inline due to code size + +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index fc55e89260fdec2c5045e8f00e091191980ff1f2..bb2ff043f0d159fa18769c31b08683ee12037c58 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -431,17 +431,20 @@ public class Chunk implements IChunkAccess { + } + + public Fluid a(int i, int j, int k) { +- try { +- if (j >= 0 && j >> 4 < this.sections.length) { +- ChunkSection chunksection = this.sections[j >> 4]; +- +- if (!ChunkSection.a(chunksection)) { +- return chunksection.b(i & 15, j & 15, k & 15); ++ //try { // Paper - remove try catch ++ // Paper start - reduce the number of ops in this call ++ int index = j >> 4; ++ if (index >= 0 && index < this.sections.length) { ++ ChunkSection chunksection = this.sections[index]; ++ ++ if (chunksection != null) { ++ return chunksection.blockIds.a((j & 15) << 8 | (k & 15) << 4 | i & 15).getFluid(); + } ++ // Paper end + } + + return FluidTypes.EMPTY.h(); +- } catch (Throwable throwable) { ++ /*} catch (Throwable throwable) { // Paper - remove try catch + CrashReport crashreport = CrashReport.a(throwable, "Getting fluid state"); + CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being got"); + +@@ -450,6 +453,7 @@ public class Chunk implements IChunkAccess { + }); + throw new ReportedException(crashreport); + } ++ */ // Paper - remove try catch + } + + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +index 4bc26a7a4ae91aac90c256758ec8868d83027c0c..973aa060d6964c7d470bc7aff89b879daf1df153 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +@@ -45,7 +45,7 @@ public class ChunkSection { + } + + public Fluid b(int i, int j, int k) { +- return ((IBlockData) this.blockIds.a(i, j, k)).getFluid(); ++ return ((IBlockData) this.blockIds.a(i, j, k)).getFluid(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid. + } + + public void a() { diff --git a/patches/server-unmapped/0416-Optimise-TickListServer-by-rewriting-it.patch b/patches/server-unmapped/0416-Optimise-TickListServer-by-rewriting-it.patch new file mode 100644 index 0000000000..22f8ddc9bd --- /dev/null +++ b/patches/server-unmapped/0416-Optimise-TickListServer-by-rewriting-it.patch @@ -0,0 +1,1267 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 14 Feb 2020 01:24:39 -0800 +Subject: [PATCH] Optimise TickListServer by rewriting it + +In my profiling TickListServer showed up as +~10% for saving chunks and ~5% for the scheduling +of items on a server with ~90 players at +view distance = 5. Most of the performance +loss is unneccessary. + +TickListServer has numerous performance issues: + 1. Handling scheduled items is O(nlogn) + 2. Getting scheduled items for a chunk is O(n), + with n being the the number of scheduled items + for all chunks (hits saving very hard) + 3. Checking if an item is scheduled for the current tick is O(n), + with n being the number of items scheduled for current tick + 4. Items not in ticking chunks are churned in the scheduler + +The biggest issues are 4 & 2. + +We solve 1 by splitting up scheduled items into short and long scheduled, +where we expect the vast majority of our entries to be in the short scheduled +set. Handling short scheduled items is O(n) due to how the comparison +process is reduced to mapping. See TickListServerInterval. However, +this isn't memory-efficient - which is why long scheduled exists. +Long scheduled is handled the same as TickListServer. + +2 is solved by mapping what entries are in what chunks. + +3 is solved by mapping what blocks have what scheduled for them. + +4 is solved by moving the items that are not in ticking chunks +into a map of entries for that chunk. Once the chunk is moved +to ticking, the items are re-scheduled. + +This patch has also added two flags to debug excessive tick delays: +-Dpaper.ticklist-warn-on-excessive-delay=true (false by default) +and -Dpaper.ticklist-excessive-delay-threshold=ticks which +sets the excessive tick delay to the specified ticks (defaults to +60 * 20 ticks, aka 60 seconds) + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 8bf4d2b8c38c02d6a5b2fea37113689a252f1571..da93d38fe63035e4ff198ada84a4431f52d97c01 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -354,6 +354,13 @@ public class PaperConfig { + maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); + } + ++ public static boolean useOptimizedTickList = true; ++ private static void useOptimizedTickList() { ++ if (config.contains("settings.use-optimized-ticklist")) { // don't add default, hopefully temporary config ++ useOptimizedTickList = config.getBoolean("settings.use-optimized-ticklist"); ++ } ++ } ++ + public static boolean asyncChunks = false; + private static void asyncChunks() { + ConfigurationSection section; +diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8918bad880d6eeed30db39b6326b2f65e24edf45 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java +@@ -0,0 +1,628 @@ ++package com.destroystokyo.paper.server.ticklist; ++ ++import java.util.function.Function; ++import net.minecraft.CrashReport; ++import net.minecraft.CrashReportSystemDetails; ++import net.minecraft.ReportedException; ++import net.minecraft.core.BlockPosition; ++import net.minecraft.nbt.NBTTagList; ++import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; ++import it.unimi.dsi.fastutil.longs.Long2ObjectMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; ++import java.util.ArrayDeque; ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.Comparator; ++import java.util.Iterator; ++import java.util.List; ++import java.util.function.Consumer; ++import java.util.function.Predicate; ++import net.minecraft.server.level.ChunkProviderServer; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.level.NextTickListEntry; ++import net.minecraft.world.level.TickListPriority; ++import net.minecraft.world.level.TickListServer; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; ++ ++public final class PaperTickList extends TickListServer { // extend to avoid breaking ABI ++ ++ // in the order the state is expected to change (mostly) ++ public static final int STATE_UNSCHEDULED = 1 << 0; ++ public static final int STATE_SCHEDULED = 1 << 1; // scheduled for some tick ++ public static final int STATE_PENDING_TICK = 1 << 2; // for this tick ++ public static final int STATE_TICKING = 1 << 3; ++ public static final int STATE_TICKED = 1 << 4; // after this, it gets thrown back to unscheduled ++ public static final int STATE_CANCELLED_TICK = 1 << 5; // still gets moved to unscheduled after tick ++ ++ private static final int SHORT_SCHEDULE_TICK_THRESHOLD = 20 * 20 + 1; // 20 seconds ++ ++ private final WorldServer world; ++ private final Predicate excludeFromScheduling; ++ private final Function getMinecraftKeyFrom; ++ //private final Function getObjectFronMinecraftKey; ++ private final Consumer> tickFunction; ++ ++ private final co.aikar.timings.Timing timingCleanup; // Paper ++ private final co.aikar.timings.Timing timingTicking; // Paper ++ private final co.aikar.timings.Timing timingFinished; ++ ++ // note: remove ops / add ops suck on fastutil, a chained hashtable implementation would work better, but Long... ++ // try to alleviate with a very small load factor ++ private final Long2ObjectOpenHashMap>> entriesByBlock = new Long2ObjectOpenHashMap<>(1024, 0.25f); ++ private final Long2ObjectOpenHashMap>> entriesByChunk = new Long2ObjectOpenHashMap<>(1024, 0.25f); ++ private final Long2ObjectOpenHashMap>> pendingChunkTickLoad = new Long2ObjectOpenHashMap<>(1024, 0.5f); ++ ++ // fastutil has O(1) first/last while TreeMap/TreeSet are log(n) ++ private final ObjectRBTreeSet> longScheduled = new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); ++ ++ private final ArrayDeque> toTickThisTick = new ArrayDeque<>(); ++ ++ private final TickListServerInterval[] shortScheduled = new TickListServerInterval[SHORT_SCHEDULE_TICK_THRESHOLD]; ++ { ++ for (int i = 0, len = this.shortScheduled.length; i < len; ++i) { ++ this.shortScheduled[i] = new TickListServerInterval<>(); ++ } ++ } ++ private int shortScheduledIndex; ++ ++ private long currentTick; ++ ++ private static final boolean WARN_ON_EXCESSIVE_DELAY = Boolean.getBoolean("paper.ticklist-warn-on-excessive-delay"); ++ private static final long EXCESSIVE_DELAY_THRESHOLD = Long.getLong("paper.ticklist-excessive-delay-threshold", 60 * 20).longValue(); // 1 min dfl ++ ++ // assume index < length ++ private static int getWrappedIndex(final int start, final int length, final int index) { ++ final int next = start + index; ++ return next < length ? next : next - length; ++ } ++ ++ private static int getNextIndex(final int curr, final int length) { ++ final int next = curr + 1; ++ return next < length ? next : 0; ++ } ++ ++ public PaperTickList(final WorldServer world, final Predicate excludeFromScheduling, final Function getMinecraftKeyFrom, ++ final Consumer> tickFunction, final String timingsType) { ++ super(world, excludeFromScheduling, getMinecraftKeyFrom, tickFunction, timingsType); ++ this.world = world; ++ this.excludeFromScheduling = excludeFromScheduling; ++ this.getMinecraftKeyFrom = getMinecraftKeyFrom; ++ this.tickFunction = tickFunction; ++ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Cleanup"); // Paper ++ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Ticking"); // Paper ++ this.timingFinished = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Finish"); ++ this.currentTick = this.world.getTime(); ++ } ++ ++ private void queueEntryForTick(final NextTickListEntry entry, final ChunkProviderServer chunkProvider) { ++ if (entry.tickState == STATE_SCHEDULED) { ++ if (chunkProvider.isTickingReadyMainThread(entry.getPosition())) { ++ this.toTickThisTick.add(entry); ++ entry.tickState = STATE_PENDING_TICK; ++ } else { ++ // we dump them to a map to avoid constantly re-scheduling them ++ this.addToNotTickingReady(entry); ++ } ++ } ++ } ++ ++ private void addToNotTickingReady(final NextTickListEntry entry) { ++ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (long keyInMap) -> { ++ return new ArrayList<>(); ++ }).add(entry); ++ } ++ ++ private void addToSchedule(final NextTickListEntry entry) { ++ long delay = entry.getTargetTick() - (this.currentTick + 1); ++ if (delay < SHORT_SCHEDULE_TICK_THRESHOLD) { ++ if (delay < 0) { ++ // longScheduled orders by tick time, short scheduled does not ++ this.longScheduled.add(entry); ++ } else { ++ this.shortScheduled[getWrappedIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD, (int)delay)].addEntryLast(entry); ++ } ++ } else { ++ this.longScheduled.add(entry); ++ } ++ } ++ ++ private void removeEntry(final NextTickListEntry entry) { ++ entry.tickState = STATE_CANCELLED_TICK; ++ // short/long scheduled will skip the entry ++ ++ final BlockPosition pos = entry.getPosition(); ++ final long blockKey = MCUtil.getBlockKey(pos); ++ ++ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); ++ ++ if (currentEntries.size() == 1) { ++ // it should contain our entry ++ this.entriesByBlock.remove(blockKey); ++ } else { ++ // it's more likely that this entry is at the start of the list than the end ++ for (int i = 0, len = currentEntries.size(); i < len; ++i) { ++ final NextTickListEntry currentEntry = currentEntries.get(i); ++ if (currentEntry == entry) { ++ currentEntries.remove(i); ++ break; ++ } ++ } ++ } ++ ++ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ ++ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); ++ ++ set.remove(entry); ++ ++ if (set.isEmpty()) { ++ this.entriesByChunk.remove(chunkKey); ++ } ++ ++ ArrayList> pendingTickingLoad = this.pendingChunkTickLoad.get(chunkKey); ++ ++ if (pendingTickingLoad != null) { ++ for (int i = 0, len = pendingTickingLoad.size(); i < len; ++i) { ++ if (pendingTickingLoad.get(i) == entry) { ++ pendingTickingLoad.remove(i); ++ break; ++ } ++ } ++ ++ if (pendingTickingLoad.isEmpty()) { ++ this.pendingChunkTickLoad.remove(chunkKey); ++ } ++ } ++ ++ long delay = entry.getTargetTick() - (this.currentTick + 1); ++ if (delay >= SHORT_SCHEDULE_TICK_THRESHOLD) { ++ this.longScheduled.remove(entry); ++ } ++ } ++ ++ public void onChunkSetTicking(final int chunkX, final int chunkZ) { ++ final ArrayList> pending = this.pendingChunkTickLoad.remove(MCUtil.getCoordinateKey(chunkX, chunkZ)); ++ if (pending == null) { ++ return; ++ } ++ ++ for (int i = 0, size = pending.size(); i < size; ++i) { ++ final NextTickListEntry entry = pending.get(i); ++ // already in all the relevant reference maps, just need to add to longScheduled or shortScheduled ++ this.addToSchedule(entry); ++ } ++ } ++ ++ private void prepare() { ++ final long currentTick = this.currentTick; ++ ++ final ChunkProviderServer chunkProvider = this.world.getChunkProvider(); ++ ++ // here we setup what's going to tick ++ ++ // we don't remove items from shortScheduled (but do from longScheduled) because they're cleared at the end of ++ // this tick ++ if (this.longScheduled.isEmpty() || this.longScheduled.first().getTargetTick() > currentTick) { ++ // nothing in longScheduled to worry about ++ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; ++ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { ++ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { ++ this.queueEntryForTick(iterator.next(), chunkProvider); ++ } ++ } ++ } else { ++ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; ++ ++ // combine interval and longScheduled, keeping order ++ final Comparator> comparator = (Comparator)TickListServerInterval.ENTRY_COMPARATOR; ++ final Iterator> longScheduledIterator = this.longScheduled.iterator(); ++ NextTickListEntry longCurrent = longScheduledIterator.next(); ++ ++ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { ++ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { ++ final NextTickListEntry shortCurrent = iterator.next(); ++ if (longCurrent != null) { ++ // drain longCurrent until we can add shortCurrent ++ while (comparator.compare(longCurrent, shortCurrent) <= 0) { ++ this.queueEntryForTick(longCurrent, chunkProvider); ++ longScheduledIterator.remove(); ++ if (longScheduledIterator.hasNext()) { ++ longCurrent = longScheduledIterator.next(); ++ if (longCurrent.getTargetTick() > currentTick) { ++ longCurrent = null; ++ break; ++ } ++ } else { ++ longCurrent = null; ++ break; ++ } ++ } ++ } ++ this.queueEntryForTick(shortCurrent, chunkProvider); ++ } ++ } ++ ++ // add remaining from long scheduled ++ for (;;) { ++ if (longCurrent == null || longCurrent.getTargetTick() > currentTick) { ++ break; ++ } ++ longScheduledIterator.remove(); ++ this.queueEntryForTick(longCurrent, chunkProvider); ++ ++ if (longScheduledIterator.hasNext()) { ++ longCurrent = longScheduledIterator.next(); ++ } else { ++ break; ++ } ++ } ++ } ++ } ++ ++ private boolean warnedAboutDesync; ++ ++ @Override ++ public void nextTick() { ++ ++this.currentTick; ++ if (this.currentTick != this.world.getTime()) { ++ if (!this.warnedAboutDesync) { ++ this.warnedAboutDesync = true; ++ MinecraftServer.LOGGER.error("World tick desync detected! Expected " + this.currentTick + " ticks, but got " + this.world.getTime() + " ticks for world '" + this.world.getWorld().getName() + "'", new Throwable()); ++ MinecraftServer.LOGGER.error("Preventing redstone from breaking by refusing to accept new tick time"); ++ } ++ } ++ } ++ ++ @Override ++ public void tick() { ++ final ChunkProviderServer chunkProvider = this.world.getChunkProvider(); ++ ++ this.world.getMethodProfiler().enter("cleaning"); ++ this.timingCleanup.startTiming(); ++ ++ this.prepare(); ++ ++ // this must be done here in case something schedules in the tick code ++ this.shortScheduled[this.shortScheduledIndex].clear(); ++ this.shortScheduledIndex = getNextIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD); ++ ++ this.timingCleanup.stopTiming(); ++ this.world.getMethodProfiler().exitEnter("ticking"); ++ this.timingTicking.startTiming(); ++ ++ for (final NextTickListEntry toTick : this.toTickThisTick) { ++ if (toTick.tickState != STATE_PENDING_TICK) { ++ // onTickEnd gets called at end of tick ++ continue; ++ } ++ try { ++ if (chunkProvider.isTickingReadyMainThread(toTick.getPosition())) { ++ toTick.tickState = STATE_TICKING; ++ this.tickFunction.accept(toTick); ++ if (toTick.tickState == STATE_TICKING) { ++ toTick.tickState = STATE_TICKED; ++ } // else it's STATE_CANCELLED_TICK ++ } else { ++ // re-schedule eventually ++ toTick.tickState = STATE_SCHEDULED; ++ this.addToNotTickingReady(toTick); ++ } ++ } catch (final Throwable thr) { ++ // start copy from TickListServer // TODO check on update ++ CrashReport crashreport = CrashReport.a(thr, "Exception while ticking"); ++ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being ticked"); ++ ++ CrashReportSystemDetails.a(crashreportsystemdetails, toTick.getPosition(), (IBlockData) null); ++ throw new ReportedException(crashreport); ++ // end copy from TickListServer ++ } ++ } ++ ++ this.timingTicking.stopTiming(); ++ this.world.getMethodProfiler().exit(); ++ this.timingFinished.startTiming(); ++ ++ // finished ticking, actual cleanup time ++ for (int i = 0, len = this.toTickThisTick.size(); i < len; ++i) { ++ final NextTickListEntry entry = this.toTickThisTick.poll(); ++ if (entry.tickState != STATE_SCHEDULED) { ++ // some entries get re-scheduled due to their chunk not being loaded/at correct status, so do not ++ // call onTickEnd for them ++ this.onTickEnd(entry); ++ } ++ } ++ ++ this.timingFinished.stopTiming(); ++ } ++ ++ private void onTickEnd(final NextTickListEntry entry) { ++ if (entry.tickState == STATE_CANCELLED_TICK) { ++ return; ++ } ++ entry.tickState = STATE_UNSCHEDULED; ++ ++ final BlockPosition pos = entry.getPosition(); ++ final long blockKey = MCUtil.getBlockKey(pos); ++ ++ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); ++ ++ if (currentEntries.size() == 1) { ++ // it should contain our entry ++ this.entriesByBlock.remove(blockKey); ++ } else { ++ // it's more likely that this entry is at the start of the list than the end ++ for (int i = 0, len = currentEntries.size(); i < len; ++i) { ++ final NextTickListEntry currentEntry = currentEntries.get(i); ++ if (currentEntry == entry) { ++ currentEntries.remove(i); ++ break; ++ } ++ } ++ } ++ ++ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ ++ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); ++ ++ set.remove(entry); ++ ++ if (set.isEmpty()) { ++ this.entriesByChunk.remove(chunkKey); ++ } ++ ++ // already removed from longScheduled or shortScheduled ++ } ++ ++ @Override ++ public boolean isPendingTickThisTick(final BlockPosition blockposition, final T data) { ++ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); ++ ++ if (entries == null) { ++ return false; ++ } ++ ++ for (int i = 0, size = entries.size(); i < size; ++i) { ++ final NextTickListEntry entry = entries.get(i); ++ if (entry.getData() == data && entry.tickState == STATE_PENDING_TICK) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ @Override ++ public boolean isScheduledForTick(final BlockPosition blockposition, final T data) { ++ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); ++ ++ if (entries == null) { ++ return false; ++ } ++ ++ for (int i = 0, size = entries.size(); i < size; ++i) { ++ final NextTickListEntry entry = entries.get(i); ++ if (entry.getData() == data && entry.tickState == STATE_SCHEDULED) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ @Override ++ public void schedule(BlockPosition blockPosition, T t, int i, TickListPriority tickListPriority) { ++ this.schedule(blockPosition, t, i + this.currentTick, tickListPriority); ++ } ++ ++ public void schedule(final NextTickListEntry entry) { ++ this.schedule(entry.getPosition(), entry.getData(), entry.getTargetTick(), entry.getPriority()); ++ } ++ ++ public void schedule(final BlockPosition pos, final T data, final long targetTick, final TickListPriority priority) { ++ final NextTickListEntry entry = new NextTickListEntry<>(pos, data, targetTick, priority); ++ if (this.excludeFromScheduling.test(entry.getData())) { ++ return; ++ } ++ ++ if (WARN_ON_EXCESSIVE_DELAY) { ++ final long delay = entry.getTargetTick() - this.currentTick; ++ if (delay >= EXCESSIVE_DELAY_THRESHOLD) { ++ MinecraftServer.LOGGER.warn("Entry " + entry.toString() + " has been scheduled with an excessive delay of: " + delay, new Throwable()); ++ } ++ } ++ ++ final long blockKey = MCUtil.getBlockKey(pos); ++ ++ final ArrayList> currentEntries = this.entriesByBlock.computeIfAbsent(blockKey, (long keyInMap) -> new ArrayList<>(3)); ++ ++ if (currentEntries.isEmpty()) { ++ currentEntries.add(entry); ++ } else { ++ for (int i = 0, size = currentEntries.size(); i < size; ++i) { ++ final NextTickListEntry currentEntry = currentEntries.get(i); ++ ++ // entries are only blocked from scheduling if currentEntry.equals(toSchedule) && currentEntry is scheduled to tick (NOT including pending) ++ if (currentEntry.getData() == entry.getData() && currentEntry.tickState == STATE_SCHEDULED) { ++ // can't add ++ return; ++ } ++ } ++ currentEntries.add(entry); ++ } ++ ++ entry.tickState = STATE_SCHEDULED; ++ ++ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (final long keyInMap) -> { ++ return new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); ++ }).add(entry); ++ ++ this.addToSchedule(entry); ++ } ++ ++ public void scheduleAll(final Iterator> iterator) { ++ while (iterator.hasNext()) { ++ this.schedule(iterator.next()); ++ } ++ } ++ ++ // this is not the standard interception calculation, but it's the one vanilla uses ++ // i.e the y value is ignored? the x, z calc isn't correct? ++ // however for the copy op they use the correct intersection, after using this one of course... ++ private static boolean isBlockInSortof(final StructureBoundingBox boundingBox, final BlockPosition pos) { ++ return pos.getX() >= boundingBox.getMinX() && pos.getX() < boundingBox.getMaxX() && pos.getZ() >= boundingBox.getMinZ() && pos.getZ() < boundingBox.getMaxZ(); ++ } ++ ++ @Override ++ public List> getEntriesInBoundingBox(final StructureBoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { ++ if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) { ++ return Collections.emptyList(); // vanilla behaviour, check isBlockInSortof above ++ } ++ ++ final int lowerChunkX = structureboundingbox.getMinX() >> 4; ++ final int upperChunkX = (structureboundingbox.getMaxX() - 1) >> 4; // subtract 1 since maxX is exclusive ++ final int lowerChunkZ = structureboundingbox.getMinZ() >> 4; ++ final int upperChunkZ = (structureboundingbox.getMaxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive ++ ++ final int xChunksLength = (upperChunkX - lowerChunkX + 1); ++ final int zChunksLength = (upperChunkZ - lowerChunkZ + 1); ++ ++ final ObjectRBTreeSet>[] containingChunks = new ObjectRBTreeSet[xChunksLength * zChunksLength]; ++ ++ final int offset = (xChunksLength * -lowerChunkZ - lowerChunkX); ++ int totalEntries = 0; ++ for (int currChunkX = lowerChunkX; currChunkX <= upperChunkX; ++currChunkX) { ++ for (int currChunkZ = lowerChunkZ; currChunkZ <= upperChunkZ; ++currChunkZ) { ++ // todo optimize ++ //final int index = (currChunkX - lowerChunkX) + xChunksLength * (currChunkZ - lowerChunkZ); ++ final int index = offset + currChunkX + xChunksLength * currChunkZ; ++ final ObjectRBTreeSet> set = containingChunks[index] = this.entriesByChunk.get(MCUtil.getCoordinateKey(currChunkX, currChunkZ)); ++ if (set != null) { ++ totalEntries += set.size(); ++ } ++ } ++ } ++ ++ final List> ret = new ArrayList<>(totalEntries); ++ ++ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); ++ ++ MCUtil.mergeSortedSets((NextTickListEntry entry) -> { ++ if (!isBlockInSortof(structureboundingbox, entry.getPosition())) { ++ return; ++ } ++ final int tickState = entry.tickState; ++ if ((tickState & matchOne) == 0) { ++ return; ++ } ++ ++ ret.add(entry); ++ return; ++ }, TickListServerInterval.ENTRY_COMPARATOR, containingChunks); ++ ++ if (removeReturned) { ++ for (NextTickListEntry entry : ret) { ++ this.removeEntry(entry); ++ } ++ } ++ ++ return ret; ++ } ++ ++ @Override ++ public void copy(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { ++ // start copy from TickListServer // TODO check on update ++ List> list = this.getEntriesInBoundingBox(structureboundingbox, false, false); ++ Iterator> iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ NextTickListEntry nextticklistentry = iterator.next(); ++ ++ if (structureboundingbox.hasPoint( nextticklistentry.getPosition())) { ++ BlockPosition blockposition1 = nextticklistentry.getPosition().add(blockposition); ++ T t0 = nextticklistentry.getData(); ++ ++ this.schedule(new NextTickListEntry<>(blockposition1, t0, nextticklistentry.getTargetTick(), nextticklistentry.getPriority())); ++ } ++ } ++ // end copy from TickListServer ++ } ++ ++ @Override ++ public List> getEntriesInChunk(ChunkCoordIntPair chunkPos, boolean removeReturned, boolean excludeTicked) { ++ // Vanilla DOES get the entries 2 blocks out of the chunk too, but that doesn't matter since we ignore chunks ++ // not at ticking status, and ticking status requires neighbours loaded ++ // so with this method we will reduce scheduler churning ++ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); ++ ++ final ObjectRBTreeSet> entries = this.entriesByChunk.get(MCUtil.getCoordinateKey(chunkPos)); ++ ++ if (entries == null) { ++ return Collections.emptyList(); ++ } ++ ++ final List> ret = new ArrayList<>(entries.size()); ++ ++ for (NextTickListEntry entry : entries) { ++ if ((entry.tickState & matchOne) == 0) { ++ continue; ++ } ++ ret.add(entry); ++ } ++ ++ if (removeReturned) { ++ for (NextTickListEntry entry : ret) { ++ this.removeEntry(entry); ++ } ++ } ++ ++ return ret; ++ } ++ ++ @Override ++ public NBTTagList serialize(ChunkCoordIntPair chunkcoordintpair) { ++ // start copy from TickListServer // TODO check on update ++ List> list = this.getEntriesInChunk(chunkcoordintpair, false, true); ++ ++ return TickListServer.serialize(this.getMinecraftKeyFrom, list, this.currentTick); ++ // end copy from TickListServer ++ } ++ ++ @Override ++ public int getTotalScheduledEntries() { ++ // good thing this is only used in debug reports // TODO check on update ++ int ret = 0; ++ ++ for (NextTickListEntry entry : this.longScheduled) { ++ if (entry.tickState == STATE_SCHEDULED) { ++ ++ret; ++ } ++ } ++ ++ for (Iterator>>> iterator = this.pendingChunkTickLoad.long2ObjectEntrySet().iterator(); iterator.hasNext();) { ++ ArrayList> list = iterator.next().getValue(); ++ ++ for (NextTickListEntry entry : list) { ++ if (entry.tickState == STATE_SCHEDULED) { ++ ++ret; ++ } ++ } ++ } ++ ++ for (TickListServerInterval interval : this.shortScheduled) { ++ for (Iterable> set : interval.byPriority) { ++ for (NextTickListEntry entry : set) { ++ if (entry.tickState == STATE_SCHEDULED) { ++ ++ret; ++ } ++ } ++ } ++ } ++ ++ return ret; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b58432a8b60670562baf00cf5279c702aaad4557 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.server.ticklist; ++ ++import com.destroystokyo.paper.util.set.LinkedSortedSet; ++import java.util.Comparator; ++import net.minecraft.world.level.NextTickListEntry; ++import net.minecraft.world.level.TickListPriority; ++ ++// represents a set of entries to tick at a specified time ++public final class TickListServerInterval { ++ ++ public static final int TOTAL_PRIORITIES = TickListPriority.values().length; ++ public static final Comparator> ENTRY_COMPARATOR_BY_ID = (entry1, entry2) -> { ++ return Long.compare(entry1.getId(), entry2.getId()); ++ }; ++ public static final Comparator> ENTRY_COMPARATOR = (Comparator)NextTickListEntry.comparator(); ++ ++ // we do not record the interval, this class is meant to be used on a ring buffer ++ ++ // inlined enum map for TickListPriority ++ public final LinkedSortedSet>[] byPriority = new LinkedSortedSet[TOTAL_PRIORITIES]; ++ ++ { ++ for (int i = 0, len = this.byPriority.length; i < len; ++i) { ++ this.byPriority[i] = new LinkedSortedSet<>(ENTRY_COMPARATOR_BY_ID); ++ } ++ } ++ ++ public void addEntryLast(final NextTickListEntry entry) { ++ this.byPriority[entry.getPriority().ordinal()].addLast(entry); ++ } ++ ++ public void addEntryFirst(final NextTickListEntry entry) { ++ this.byPriority[entry.getPriority().ordinal()].addFirst(entry); ++ } ++ ++ public void clear() { ++ for (int i = 0, len = this.byPriority.length; i < len; ++i) { ++ this.byPriority[i].clear(); // O(1) clear ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..118988c39e58f28e8a2851792b9c014f341f06fc +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java +@@ -0,0 +1,142 @@ ++package com.destroystokyo.paper.util.set; ++ ++import java.util.Comparator; ++import java.util.Iterator; ++import java.util.NoSuchElementException; ++ ++public final class LinkedSortedSet implements Iterable { ++ ++ public final Comparator comparator; ++ ++ protected Link head; ++ protected Link tail; ++ ++ public LinkedSortedSet() { ++ this((Comparator)Comparator.naturalOrder()); ++ } ++ ++ public LinkedSortedSet(final Comparator comparator) { ++ this.comparator = comparator; ++ } ++ ++ public void clear() { ++ this.head = this.tail = null; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return new Iterator() { ++ ++ Link next = LinkedSortedSet.this.head; ++ ++ @Override ++ public boolean hasNext() { ++ return this.next != null; ++ } ++ ++ @Override ++ public E next() { ++ final Link next = this.next; ++ if (next == null) { ++ throw new NoSuchElementException(); ++ } ++ this.next = next.next; ++ return next.element; ++ } ++ }; ++ } ++ ++ public boolean addLast(final E element) { ++ final Comparator comparator = this.comparator; ++ ++ Link curr = this.tail; ++ if (curr != null) { ++ int compare; ++ ++ while ((compare = comparator.compare(element, curr.element)) < 0) { ++ Link prev = curr; ++ curr = curr.prev; ++ if (curr != null) { ++ continue; ++ } ++ this.head = prev.prev = new Link<>(element, null, prev); ++ return true; ++ } ++ ++ if (compare != 0) { ++ // insert after curr ++ final Link next = curr.next; ++ final Link insert = new Link<>(element, curr, next); ++ curr.next = insert; ++ ++ if (next == null) { ++ this.tail = insert; ++ } else { ++ next.prev = insert; ++ } ++ return true; ++ } ++ ++ return false; ++ } else { ++ this.head = this.tail = new Link<>(element); ++ return true; ++ } ++ } ++ ++ public boolean addFirst(final E element) { ++ final Comparator comparator = this.comparator; ++ ++ Link curr = this.head; ++ if (curr != null) { ++ int compare; ++ ++ while ((compare = comparator.compare(element, curr.element)) > 0) { ++ Link prev = curr; ++ curr = curr.next; ++ if (curr != null) { ++ continue; ++ } ++ this.tail = prev.next = new Link<>(element, prev, null); ++ return true; ++ } ++ ++ if (compare != 0) { ++ // insert before curr ++ final Link prev = curr.prev; ++ final Link insert = new Link<>(element, prev, curr); ++ curr.prev = insert; ++ ++ if (prev == null) { ++ this.head = insert; ++ } else { ++ prev.next = insert; ++ } ++ return true; ++ } ++ ++ return false; ++ } else { ++ this.head = this.tail = new Link<>(element); ++ return true; ++ } ++ } ++ ++ protected static final class Link { ++ public E element; ++ public Link prev; ++ public Link next; ++ ++ public Link() {} ++ ++ public Link(final E element) { ++ this.element = element; ++ } ++ ++ public Link(final E element, final Link prev, final Link next) { ++ this.element = element; ++ this.prev = prev; ++ this.next = next; ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index 8c0aeb51f5e230fd6109e750732eb54559bc9637..1fb931d4c0720a5e496030e25c865771aea3ec70 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -111,6 +111,7 @@ public class BlockPosition extends BaseBlockPosition { + return i == 0 && j == 0 && k == 0 ? this : new BlockPosition(this.getX() + i, this.getY() + j, this.getZ() + k); + } + ++ public final BlockPosition add(BaseBlockPosition baseblockposition) { return this.a(baseblockposition); } // Paper - OBFHELPER + public BlockPosition a(BaseBlockPosition baseblockposition) { + return this.b(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); + } +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 5caf2121f2e551d7b4f0ddc74f10a44dc28ac62b..214098d7ad95839e90b0ec9ea997930c27b4bea4 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -21,6 +21,7 @@ import net.minecraft.SystemUtils; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.SectionPosition; + import net.minecraft.network.protocol.Packet; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.progress.WorldLoadListener; + import net.minecraft.util.MathHelper; + import net.minecraft.util.profiling.GameProfilerFiller; +@@ -217,6 +218,13 @@ public class ChunkProviderServer extends IChunkProvider { + } + // Paper end + ++ // Paper start - rewrite ticklistserver ++ public final boolean isTickingReadyMainThread(BlockPosition pos) { ++ PlayerChunk chunk = this.playerChunkMap.getUpdatingChunk(MCUtil.getCoordinateKey(pos)); ++ return chunk != null && chunk.isTickingReady(); ++ } ++ // Paper end - rewrite ticklistserver ++ + public ChunkProviderServer(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, boolean flag, WorldLoadListener worldloadlistener, Supplier supplier) { + this.world = worldserver; + this.serverThreadQueue = new ChunkProviderServer.a(worldserver); +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index 6433463938d8bb717840c8f57fe6e7079e1030f2..445dba8ed210407664904b707c36c78a76f25510 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -496,7 +496,9 @@ public class PlayerChunk { + PlayerChunk.this.isTickingReady = true; + + +- ++ // Paper start - rewrite ticklistserver ++ PlayerChunk.this.chunkMap.world.onChunkSetTicking(PlayerChunk.this.location.x, PlayerChunk.this.location.z); ++ // Paper end - rewrite ticklistserver + + } + }); +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 82f9c49233acce3c95d8a07b2a1b187d5c57552d..7fc75749e4983582275f794ed152af7cffce910f 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -298,6 +298,15 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + // Paper end + ++ // Paper start - rewrite ticklistserver ++ void onChunkSetTicking(int chunkX, int chunkZ) { ++ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { ++ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.nextTickListBlock).onChunkSetTicking(chunkX, chunkZ); ++ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.nextTickListFluid).onChunkSetTicking(chunkX, chunkZ); ++ } ++ } ++ // Paper end - rewrite ticklistserver ++ + // Add env and gen to constructor, WorldData -> WorldDataServer + public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor +@@ -305,12 +314,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { + convertable = convertable_conversionsession; + uuid = WorldUUID.getUUID(convertable_conversionsession.folder.toFile()); + // CraftBukkit end +- this.nextTickListBlock = new TickListServer<>(this, (block) -> { +- return block == null || block.getBlockData().isAir(); +- }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings +- this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { +- return fluidtype == null || fluidtype == FluidTypes.EMPTY; +- }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings ++ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { ++ this.nextTickListBlock = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> { ++ return block == null || block.getBlockData().isAir(); ++ }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings ++ this.nextTickListFluid = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (fluidtype) -> { ++ return fluidtype == null || fluidtype == FluidTypes.EMPTY; ++ }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings ++ } else { ++ this.nextTickListBlock = new TickListServer<>(this, (block) -> { ++ return block == null || block.getBlockData().isAir(); ++ }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings ++ this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { ++ return fluidtype == null || fluidtype == FluidTypes.EMPTY; ++ }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings ++ } + this.navigators = Sets.newHashSet(); + this.L = new ObjectLinkedOpenHashSet(); + this.Q = flag1; +@@ -645,7 +663,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { + if (this.Q) { + long i = this.worldData.getTime() + 1L; + +- this.worldDataServer.setTime(i); ++ this.worldDataServer.setTime(i); // Paper - diff on change, we want the below to be ran right after this ++ this.nextTickListBlock.nextTick(); // Paper ++ this.nextTickListFluid.nextTick(); // Paper + this.worldDataServer.u().a(this.server, i); + if (this.worldData.q().getBoolean(GameRules.DO_DAYLIGHT_CYCLE)) { + this.setDayTime(this.worldData.getDayTime() + 1L); +diff --git a/src/main/java/net/minecraft/world/level/NextTickListEntry.java b/src/main/java/net/minecraft/world/level/NextTickListEntry.java +index 37b7dd82a227a88b720c13a813dd7e8caf803e03..8eb3084def3aa8776d32f8a3c942c95d24ccea3f 100644 +--- a/src/main/java/net/minecraft/world/level/NextTickListEntry.java ++++ b/src/main/java/net/minecraft/world/level/NextTickListEntry.java +@@ -6,11 +6,13 @@ import net.minecraft.core.BlockPosition; + public class NextTickListEntry { + + private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading +- private final T e; +- public final BlockPosition a; +- public final long b; +- public final TickListPriority c; +- private final long f; ++ private final T e; public final T getData() { return this.e; } // Paper - OBFHELPER ++ public final BlockPosition a; public final BlockPosition getPosition() { return this.a; } // Paper - OBFHELPER ++ public final long b; public final long getTargetTick() { return this.b; } // Paper - OBFHELPER ++ public final TickListPriority c; public final TickListPriority getPriority() { return this.c; } // Paper - OBFHELPER ++ private final long f; public final long getId() { return this.f; } // Paper - OBFHELPER ++ private final int hash; // Paper ++ public int tickState; // Paper + + public NextTickListEntry(BlockPosition blockposition, T t0) { + this(blockposition, t0, 0L, TickListPriority.NORMAL); +@@ -22,6 +24,7 @@ public class NextTickListEntry { + this.e = t0; + this.b = i; + this.c = ticklistpriority; ++ this.hash = this.computeHash(); // Paper + } + + public boolean equals(Object object) { +@@ -34,19 +37,31 @@ public class NextTickListEntry { + } + } + ++ // Paper start - optimize hashcode ++ @Override + public int hashCode() { ++ return this.hash; ++ } ++ public final int computeHash() { ++ // Paper end - optimize hashcode + return this.a.hashCode(); + } + +- public static Comparator a() { // Paper - decompile fix +- return Comparator.comparingLong((nextticklistentry) -> { +- return ((NextTickListEntry) nextticklistentry).b; // Paper - decompile fix +- }).thenComparing((nextticklistentry) -> { +- return ((NextTickListEntry) nextticklistentry).c; // Paper - decompile fix +- }).thenComparingLong((nextticklistentry) -> { +- return ((NextTickListEntry) nextticklistentry).f; // Paper - decompile fix +- }); ++ // Paper start - let's not use more functional code for no reason. ++ public static Comparator comparator() { return NextTickListEntry.a(); } // Paper - OBFHELPER ++ public static Comparator a() { ++ return (Comparator)(Comparator)(NextTickListEntry nextticklistentry, NextTickListEntry nextticklistentry1) -> { ++ int i = Long.compare(nextticklistentry.getTargetTick(), nextticklistentry1.getTargetTick()); ++ ++ if (i != 0) { ++ return i; ++ } else { ++ i = nextticklistentry.getPriority().compareTo(nextticklistentry1.getPriority()); ++ return i != 0 ? i : Long.compare(nextticklistentry.getId(), nextticklistentry1.getId()); ++ } ++ }; + } ++ // Paper end - let's not use more functional code for no reason. + + public String toString() { + return this.e + ": " + this.a + ", " + this.b + ", " + this.c + ", " + this.f; +diff --git a/src/main/java/net/minecraft/world/level/TickListChunk.java b/src/main/java/net/minecraft/world/level/TickListChunk.java +index c3cb513d0d107ecb43e98960b25054626aa6a03f..fd293e11ec62a41a53c1e5238cb1219349d446d4 100644 +--- a/src/main/java/net/minecraft/world/level/TickListChunk.java ++++ b/src/main/java/net/minecraft/world/level/TickListChunk.java +@@ -9,6 +9,7 @@ import net.minecraft.core.BlockPosition; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.nbt.NBTTagList; + import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.MinecraftServer; + + public class TickListChunk implements TickList { + +@@ -61,6 +62,8 @@ public class TickListChunk implements TickList { + return nbttaglist; + } + ++ private static final int MAX_TICK_DELAY = Integer.getInteger("paper.ticklist-max-tick-delay", -1).intValue(); // Paper - clean up broken entries ++ + public static TickListChunk a(NBTTagList nbttaglist, Function function, Function function1) { + List> list = Lists.newArrayList(); + +@@ -71,7 +74,14 @@ public class TickListChunk implements TickList { + if (t0 != null) { + BlockPosition blockposition = new BlockPosition(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); + +- list.add(new TickListChunk.a<>(t0, blockposition, nbttagcompound.getInt("t"), TickListPriority.a(nbttagcompound.getInt("p")))); ++ // Paper start - clean up broken entries ++ int delay = nbttagcompound.getInt("t"); ++ if (MAX_TICK_DELAY > 0 && delay > MAX_TICK_DELAY) { ++ MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockposition + ", tick delay " + delay); ++ continue; ++ } ++ list.add(new TickListChunk.a<>(t0, blockposition, delay, TickListPriority.a(nbttagcompound.getInt("p")))); ++ // Paper end - clean up broken entries + } + } + +diff --git a/src/main/java/net/minecraft/world/level/TickListServer.java b/src/main/java/net/minecraft/world/level/TickListServer.java +index c221e5caf518b8c588390e438346fa58fa8c5a38..4fd89bbe6ce578fd3a166bcfbbe41908a7bb4753 100644 +--- a/src/main/java/net/minecraft/world/level/TickListServer.java ++++ b/src/main/java/net/minecraft/world/level/TickListServer.java +@@ -50,7 +50,16 @@ public class TickListServer implements TickList { + private final co.aikar.timings.Timing timingTicking; // Paper + // Paper end + ++ // Paper start ++ public void nextTick() {} ++ // Paper end ++ + public void b() { ++ // Paper start - allow overriding ++ this.tick(); ++ } ++ public void tick() { ++ // Paper end + int i = this.nextTickList.size(); + + if (false) { // CraftBukkit +@@ -118,10 +127,20 @@ public class TickListServer implements TickList { + + @Override + public boolean b(BlockPosition blockposition, T t0) { ++ // Paper start - allow overriding ++ return this.isPendingTickThisTick(blockposition, t0); ++ } ++ public boolean isPendingTickThisTick(BlockPosition blockposition, T t0) { ++ // Paper end + return this.f.contains(new NextTickListEntry<>(blockposition, t0)); + } + + public List> a(ChunkCoordIntPair chunkcoordintpair, boolean flag, boolean flag1) { ++ // Paper start - allow overriding ++ return this.getEntriesInChunk(chunkcoordintpair, flag, flag1); ++ } ++ public List> getEntriesInChunk(ChunkCoordIntPair chunkcoordintpair, boolean flag, boolean flag1) { ++ // Paper end + int i = (chunkcoordintpair.x << 4) - 2; + int j = i + 16 + 2; + int k = (chunkcoordintpair.z << 4) - 2; +@@ -131,6 +150,11 @@ public class TickListServer implements TickList { + } + + public List> a(StructureBoundingBox structureboundingbox, boolean flag, boolean flag1) { ++ // Paper start - allow overriding ++ return this.getEntriesInBoundingBox(structureboundingbox, flag, flag1); ++ } ++ public List> getEntriesInBoundingBox(StructureBoundingBox structureboundingbox, boolean flag, boolean flag1) { ++ // Paper end + List> list = this.a((List) null, this.nextTickList, structureboundingbox, flag); + + if (flag && list != null) { +@@ -170,6 +194,11 @@ public class TickListServer implements TickList { + } + + public void a(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { ++ // Paper start - allow overriding ++ this.copy(structureboundingbox, blockposition); ++ } ++ public void copy(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { ++ // Paper end + List> list = this.a(structureboundingbox, false, false); + Iterator iterator = list.iterator(); + +@@ -187,11 +216,17 @@ public class TickListServer implements TickList { + } + + public NBTTagList a(ChunkCoordIntPair chunkcoordintpair) { ++ // Paper start - allow overriding ++ return this.serialize(chunkcoordintpair); ++ } ++ public NBTTagList serialize(ChunkCoordIntPair chunkcoordintpair) { ++ // Paper end + List> list = this.a(chunkcoordintpair, false, true); + + return a(this.b, list, this.e.getTime()); + } + ++ public static NBTTagList serialize(Function function, Iterable> iterable, long i) { return TickListServer.a(function, iterable, i); } // Paper - OBFHELPER + private static NBTTagList a(Function function, Iterable> iterable, long i) { + NBTTagList nbttaglist = new NBTTagList(); + Iterator iterator = iterable.iterator(); +@@ -214,11 +249,21 @@ public class TickListServer implements TickList { + + @Override + public boolean a(BlockPosition blockposition, T t0) { ++ // Paper start - allow overriding ++ return this.isScheduledForTick(blockposition, t0); ++ } ++ public boolean isScheduledForTick(BlockPosition blockposition, T t0) { ++ // Paper end + return this.nextTickListHash.contains(new NextTickListEntry<>(blockposition, t0)); + } + + @Override + public void a(BlockPosition blockposition, T t0, int i, TickListPriority ticklistpriority) { ++ // Paper start - allow overriding ++ this.schedule(blockposition, t0, i, ticklistpriority); ++ } ++ public void schedule(BlockPosition blockposition, T t0, int i, TickListPriority ticklistpriority) { ++ // Paper end + if (!this.a.test(t0)) { + this.a(new NextTickListEntry<>(blockposition, t0, (long) i + this.e.getTime(), ticklistpriority)); + } +@@ -234,6 +279,11 @@ public class TickListServer implements TickList { + } + + public int a() { ++ // Paper start - allow overriding ++ return this.getTotalScheduledEntries(); ++ } ++ public int getTotalScheduledEntries() { ++ // Paper end + return this.nextTickListHash.size(); + } + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java +index b5d6c8163c686c31375fb645d7721af06c01df40..fb4b8d7167ad7f1d24d40bbbda5f52e278f25895 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java +@@ -8,12 +8,12 @@ import net.minecraft.nbt.NBTTagIntArray; + + public class StructureBoundingBox { + +- public int a; +- public int b; +- public int c; +- public int d; +- public int e; +- public int f; ++ public int a; public final int getMinX() { return this.a; } // Paper - OBFHELPER ++ public int b; public final int getMinY() { return this.b; } // Paper - OBFHELPER ++ public int c; public final int getMinZ() { return this.c; } // Paper - OBFHELPER ++ public int d; public final int getMaxX() { return this.d; } // Paper - OBFHELPER ++ public int e; public final int getMaxY() { return this.e; } // Paper - OBFHELPER ++ public int f; public final int getMaxZ() { return this.f; } // Paper - OBFHELPER + + public StructureBoundingBox() {} + +@@ -92,6 +92,7 @@ public class StructureBoundingBox { + this.e = 512; + } + ++ public final boolean intersects(StructureBoundingBox boundingBox) { return this.b(boundingBox); } // Paper - OBFHELPER + public boolean b(StructureBoundingBox structureboundingbox) { + return this.d >= structureboundingbox.a && this.a <= structureboundingbox.d && this.f >= structureboundingbox.c && this.c <= structureboundingbox.f && this.e >= structureboundingbox.b && this.b <= structureboundingbox.e; + } +@@ -126,6 +127,7 @@ public class StructureBoundingBox { + this.a(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); + } + ++ public final boolean hasPoint(BaseBlockPosition baseblockposition) { return this.b(baseblockposition); } // Paper - OBFHELPER + public boolean b(BaseBlockPosition baseblockposition) { + return baseblockposition.getX() >= this.a && baseblockposition.getX() <= this.d && baseblockposition.getZ() >= this.c && baseblockposition.getZ() <= this.f && baseblockposition.getY() >= this.b && baseblockposition.getY() <= this.e; + } diff --git a/patches/server-unmapped/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server-unmapped/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch new file mode 100644 index 0000000000..6d6444c726 --- /dev/null +++ b/patches/server-unmapped/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch @@ -0,0 +1,151 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Sat, 1 Feb 2020 16:50:39 +0100 +Subject: [PATCH] Pillager patrol spawn settings and per player options + +This adds config options for defining the spawn chance, spawn delay and +spawn start day as well as toggles for handling the spawn delay and +start day per player. (Based on the time played statistic) +When not per player it will use the Vanilla mechanic of one delay per +world and the world age for the start day. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 525d702d78a609af987ebd2c32169b873e5c05ed..6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -582,10 +582,21 @@ public class PaperWorldConfig { + } + + public boolean disablePillagerPatrols = false; ++ public double patrolSpawnChance = 0.2; ++ public boolean patrolPerPlayerDelay = false; ++ public int patrolDelay = 12000; ++ public boolean patrolPerPlayerStart = false; ++ public int patrolStartDay = 5; + private void pillagerSettings() { + disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); ++ patrolSpawnChance = getDouble("game-mechanics.pillager-patrols.spawn-chance", patrolSpawnChance); ++ patrolPerPlayerDelay = getBoolean("game-mechanics.pillager-patrols.spawn-delay.per-player", patrolPerPlayerDelay); ++ patrolDelay = getInt("game-mechanics.pillager-patrols.spawn-delay.ticks", patrolDelay); ++ patrolPerPlayerStart = getBoolean("game-mechanics.pillager-patrols.start.per-player", patrolPerPlayerStart); ++ patrolStartDay = getInt("game-mechanics.pillager-patrols.start.day", patrolStartDay); + } + ++ + public boolean entitiesTargetWithFollowRange = false; + private void entitiesTargetWithFollowRange() { + entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index f5212a7ec0f2dd27fb1c06e0dfc37f2aff595fde..c0e32b13e79fa6b34ac9448d2f74339bb771274f 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -216,6 +216,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public boolean viewingCredits; + private int containerUpdateDelay; // Paper + public long loginTime; // Paper ++ public int patrolSpawnDelay; // Paper - per player patrol spawns + // Paper start - cancellable death event + public boolean queueHealthUpdatePacket = false; + public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; +diff --git a/src/main/java/net/minecraft/stats/StatisticWrapper.java b/src/main/java/net/minecraft/stats/StatisticWrapper.java +index c1a694c4a773a41cdefca6b154711f7fc0a7fcaa..00d79ccf9c65acadc030ab1796cff4598392cb6a 100644 +--- a/src/main/java/net/minecraft/stats/StatisticWrapper.java ++++ b/src/main/java/net/minecraft/stats/StatisticWrapper.java +@@ -28,6 +28,7 @@ public class StatisticWrapper implements Iterable> { + return this.b.values().iterator(); + } + ++ public final Statistic get(T t) { return this.b(t); }; // Paper - OBFHELPER + public Statistic b(T t0) { + return this.a(t0, Counter.DEFAULT); + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java +index cba98adb7f2711fb97c7e4120d962f46a59682e7..111c4c1fad2f1839a8c6b7c277cf801236ae1685 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java +@@ -3,7 +3,9 @@ package net.minecraft.world.level.levelgen; + import java.util.Random; + import net.minecraft.core.BlockPosition; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.WorldServer; ++import net.minecraft.stats.StatisticList; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.GroupDataEntity; +@@ -20,13 +22,13 @@ import net.minecraft.world.level.block.state.IBlockData; + + public class MobSpawnerPatrol implements MobSpawner { + +- private int a; ++ private int a;private int getSpawnDelay() { return a; } private void setSpawnDelay(int spawnDelay) { this.a = spawnDelay; } // Paper - OBFHELPER + + public MobSpawnerPatrol() {} + + @Override + public int a(WorldServer worldserver, boolean flag, boolean flag1) { +- if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper ++ if (worldserver.paperConfig.disablePillagerPatrols || worldserver.paperConfig.patrolSpawnChance == 0) return 0; // Paper + if (!flag) { + return 0; + } else if (!worldserver.getGameRules().getBoolean(GameRules.DO_PATROL_SPAWNING)) { +@@ -34,23 +36,51 @@ public class MobSpawnerPatrol implements MobSpawner { + } else { + Random random = worldserver.random; + +- --this.a; +- if (this.a > 0) { ++ // Paper start - Patrol settings ++ // Random player selection moved up for per player spawning and configuration ++ int j = worldserver.getPlayers().size(); ++ if (j < 1) { + return 0; ++ } ++ ++ EntityPlayer entityhuman = worldserver.getPlayers().get(random.nextInt(j)); ++ if (entityhuman.isSpectator()) { ++ return 0; ++ } ++ ++ int patrolSpawnDelay; ++ if (worldserver.paperConfig.patrolPerPlayerDelay) { ++ --entityhuman.patrolSpawnDelay; ++ patrolSpawnDelay = entityhuman.patrolSpawnDelay; + } else { +- this.a += 12000 + random.nextInt(1200); +- long i = worldserver.getDayTime() / 24000L; ++ setSpawnDelay(getSpawnDelay() - 1); ++ patrolSpawnDelay = getSpawnDelay(); ++ } ++ ++ if (patrolSpawnDelay > 0) { ++ return 0; ++ } else { ++ long days; ++ if (worldserver.paperConfig.patrolPerPlayerStart) { ++ days = entityhuman.getStatisticManager().getStatisticValue(StatisticList.CUSTOM.get(StatisticList.PLAY_ONE_MINUTE)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang ++ } else { ++ days = worldserver.getDayTime() / 24000L; ++ } ++ if (worldserver.paperConfig.patrolPerPlayerDelay) { ++ entityhuman.patrolSpawnDelay += worldserver.paperConfig.patrolDelay + random.nextInt(1200); ++ } else { ++ setSpawnDelay(getSpawnDelay() + worldserver.paperConfig.patrolDelay + random.nextInt(1200)); ++ } + +- if (i >= 5L && worldserver.isDay()) { +- if (random.nextInt(5) != 0) { ++ if (days >= worldserver.paperConfig.patrolStartDay && worldserver.isDay()) { ++ if (random.nextDouble() >= worldserver.paperConfig.patrolSpawnChance) { ++ // Paper end + return 0; + } else { +- int j = worldserver.getPlayers().size(); + + if (j < 1) { + return 0; + } else { +- EntityHuman entityhuman = (EntityHuman) worldserver.getPlayers().get(random.nextInt(j)); + + if (entityhuman.isSpectator()) { + return 0; diff --git a/patches/server-unmapped/0418-Ensure-Entity-is-never-double-registered.patch b/patches/server-unmapped/0418-Ensure-Entity-is-never-double-registered.patch new file mode 100644 index 0000000000..cb8c24e677 --- /dev/null +++ b/patches/server-unmapped/0418-Ensure-Entity-is-never-double-registered.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 29 Mar 2020 18:26:14 -0400 +Subject: [PATCH] Ensure Entity is never double registered + +If something calls register twice, and the world is ticking, it could be +enqueued to add twice. + +Vs behavior of non ticking of just overwriting state. + +We will now simply log a warning when this happens instead of crashing the server. + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 7fc75749e4983582275f794ed152af7cffce910f..8f54534356408a17132578b8a39686651a97a0d5 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -649,6 +649,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + Entity entity2; + + while ((entity2 = (Entity) this.entitiesToAdd.poll()) != null) { ++ if (!entity2.isQueuedForRegister) continue; // Paper - ignore cancelled registers + this.registerEntity(entity2); + } + +@@ -1406,6 +1407,19 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + public void unregisterEntity(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot ++ // Paper start - fix entity registration issues ++ if (entity instanceof EntityComplexPart) { ++ // Usually this is a no-op for complex parts, and ID's should be removed, but go ahead and remove it anyways ++ // Dragon parts are handled special in register. they don't receive a valid = true or register by UUID etc. ++ this.entitiesById.remove(entity.getId(), entity); ++ return; ++ } ++ if (!entity.valid) { ++ // Someone called remove before we ever got added, cancel the add. ++ entity.isQueuedForRegister = false; ++ return; ++ } ++ // Paper end + // Spigot start + if ( entity instanceof EntityHuman ) + { +@@ -1472,9 +1486,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + private void registerEntity(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot ++ // Paper start - don't double enqueue entity registration ++ //noinspection ObjectEquality ++ if (this.entitiesById.get(entity.getId()) == entity) { ++ LOGGER.error(entity + " was already registered!"); ++ new Throwable().printStackTrace(); ++ return; ++ } ++ // Paper end + if (this.tickingEntities) { +- this.entitiesToAdd.add(entity); ++ if (!entity.isQueuedForRegister) { // Paper ++ this.entitiesToAdd.add(entity); ++ entity.isQueuedForRegister = true; // Paper ++ } + } else { ++ entity.isQueuedForRegister = false; // Paper + this.entitiesById.put(entity.getId(), entity); + if (entity instanceof EntityEnderDragon) { + EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity).eJ(); +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 334d60c71fa13841f9d04af5404cc25acbc0ec76..a9d8baef5db0655742e85482604db6f6208eb9b6 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -148,6 +148,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + // Paper start ++ public boolean isQueuedForRegister = false; + public static Random SHARED_RANDOM = new Random() { + private boolean locked = false; + @Override diff --git a/patches/server-unmapped/0419-Fix-unregistering-entities-from-unloading-chunks.patch b/patches/server-unmapped/0419-Fix-unregistering-entities-from-unloading-chunks.patch new file mode 100644 index 0000000000..eeeff7b0cc --- /dev/null +++ b/patches/server-unmapped/0419-Fix-unregistering-entities-from-unloading-chunks.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 31 Mar 2020 03:01:45 -0400 +Subject: [PATCH] Fix unregistering entities from unloading chunks + +CraftBukkit caused a regression here by making unloading chunks not +have a ticket added and returning unloaded future. + +This caused entities who were killed in same tick their chunk is unloading +to not be able to be removed from the chunk. + +This then results in dead entities lingering in the Chunk. + +Combine that with a buggy detail of the previous implementation of +the Dupe UUID patch, then this was the likely source of the "Ghost entities" + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 8f54534356408a17132578b8a39686651a97a0d5..2e45f9006eba3b52916d2fccf8f2bebe7b8b8a9c 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1565,9 +1565,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + private void removeEntityFromChunk(Entity entity) { +- IChunkAccess ichunkaccess = chunkProvider.getChunkUnchecked(entity.chunkX, entity.chunkZ); // CraftBukkit - SPIGOT-5228: getChunkAt won't find the entity's chunk if it has already been unloaded (i.e. if it switched to state INACCESSIBLE). ++ Chunk ichunkaccess = entity.getCurrentChunk(); // Paper - getChunkAt(x,z,full,false) is broken by CraftBukkit as it won't return an unloading chunk. Use our current chunk reference as this points to what chunk they need to be removed from anyways + +- if (ichunkaccess instanceof Chunk) { ++ if (ichunkaccess != null) { // Paper + ((Chunk) ichunkaccess).b(entity); + } + diff --git a/patches/server-unmapped/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server-unmapped/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch new file mode 100644 index 0000000000..f765b7f7b5 --- /dev/null +++ b/patches/server-unmapped/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 31 Mar 2020 03:50:42 -0400 +Subject: [PATCH] Remote Connections shouldn't hold up shutdown + +Bugs in the connection logic appears to leave stale connections even, preventing shutdown + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 2d42b863b3fd83d1ee0532d1fcb63861641ec47b..557f80accfa36b495c9a8cffdab2e248c1cbb514 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -400,11 +400,11 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + } + + if (this.remoteControlListener != null) { +- this.remoteControlListener.b(); ++ //this.remoteControlListener.b(); // Paper - don't wait for remote connections + } + + if (this.remoteStatusListener != null) { +- this.remoteStatusListener.b(); ++ //this.remoteStatusListener.b(); // Paper - don't wait for remote connections + } + + System.exit(0); // CraftBukkit diff --git a/patches/server-unmapped/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server-unmapped/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch new file mode 100644 index 0000000000..290489e398 --- /dev/null +++ b/patches/server-unmapped/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Tue, 17 Mar 2020 14:18:50 -0500 +Subject: [PATCH] Do not allow bees to load chunks for beehives + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +index 7ce8eaeb9af3547869f467910b6a458118c63c1f..1d1f71a995a99b2101891a7a5bda7bec5d67f118 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +@@ -358,6 +358,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB + if (this.hivePos == null) { + return false; + } else { ++ if (!this.world.isLoadedAndInBounds(hivePos)) return false; // Paper + TileEntity tileentity = this.world.getTileEntity(this.hivePos); + + return tileentity instanceof TileEntityBeehive && ((TileEntityBeehive) tileentity).d(); +@@ -390,6 +391,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB + } + + private boolean i(BlockPosition blockposition) { ++ if (!this.world.isLoadedAndInBounds(blockposition)) return false; // Paper + TileEntity tileentity = this.world.getTileEntity(blockposition); + + return tileentity instanceof TileEntityBeehive ? !((TileEntityBeehive) tileentity).isFull() : false; +@@ -632,6 +634,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB + @Override + public boolean g() { + if (EntityBee.this.hasHivePos() && EntityBee.this.fd() && EntityBee.this.hivePos.a((IPosition) EntityBee.this.getPositionVector(), 2.0D)) { ++ if (!EntityBee.this.world.isLoadedAndInBounds(EntityBee.this.hivePos)) return false; // Paper + TileEntity tileentity = EntityBee.this.world.getTileEntity(EntityBee.this.hivePos); + + if (tileentity instanceof TileEntityBeehive) { +@@ -655,6 +658,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB + + @Override + public void c() { ++ if (!EntityBee.this.world.isLoadedAndInBounds(EntityBee.this.hivePos)) return; // Paper + TileEntity tileentity = EntityBee.this.world.getTileEntity(EntityBee.this.hivePos); + + if (tileentity instanceof TileEntityBeehive) { diff --git a/patches/server-unmapped/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server-unmapped/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch new file mode 100644 index 0000000000..c003c40257 --- /dev/null +++ b/patches/server-unmapped/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 01:42:39 -0400 +Subject: [PATCH] Prevent Double PlayerChunkMap adds crashing server + +Suspected case would be around the technique used in .stopRiding +Stack will identify any causer of this and warn instead of crashing. + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index baef98331c07b0f8c95351f39c5e471f96a59c05..c7619bba9115e8695b5aea2b4d059bea577e748e 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -1503,6 +1503,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + protected void addEntity(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot ++ // Paper start - ignore and warn about illegal addEntity calls instead of crashing server ++ if (!entity.valid || entity.world != this.world || this.trackedEntities.containsKey(entity.getId())) { ++ new Throwable("[ERROR] Illegal PlayerChunkMap::addEntity for world " + this.world.getWorld().getName() ++ + ": " + entity + (this.trackedEntities.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : "")) ++ .printStackTrace(); ++ return; ++ } ++ // Paper end + if (!(entity instanceof EntityComplexPart)) { + EntityTypes entitytypes = entity.getEntityType(); + int i = entitytypes.getChunkRange() * 16; +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 2e45f9006eba3b52916d2fccf8f2bebe7b8b8a9c..35fc51ac93a62f6dc4b141dc94a3cda0399f0ce1 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1531,7 +1531,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + } + +- this.getChunkProvider().addEntity(entity); ++ // this.getChunkProvider().addEntity(entity); // Paper - moved down below valid=true + // CraftBukkit start - SPIGOT-5278 + if (entity instanceof EntityDrowned) { + this.navigators.add(((EntityDrowned) entity).navigationWater); +@@ -1542,6 +1542,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.navigators.add(((EntityInsentient) entity).getNavigation()); + } + entity.valid = true; // CraftBukkit ++ this.getChunkProvider().addEntity(entity); // Paper - from above to be below valid=true + // Paper start - Set origin location when the entity is being added to the world + if (entity.origin == null) { + entity.origin = entity.getBukkitEntity().getLocation(); diff --git a/patches/server-unmapped/0423-Optimize-Collision-to-not-load-chunks.patch b/patches/server-unmapped/0423-Optimize-Collision-to-not-load-chunks.patch new file mode 100644 index 0000000000..c69af5d666 --- /dev/null +++ b/patches/server-unmapped/0423-Optimize-Collision-to-not-load-chunks.patch @@ -0,0 +1,161 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 02:37:57 -0400 +Subject: [PATCH] Optimize Collision to not load chunks + +The collision code takes an AABB and generates a cuboid of checks rather +than a cylinder, so at high velocity this can generate a lot of chunk checks. + +Treat an unloaded chunk as a collision for entities, and also for players if +the "prevent moving into unloaded chunks" setting is enabled. + +If that serting is not enabled, collisions will be ignored for players, since +movement will load only the chunk the player enters anyways and avoids loading +massive amounts of surrounding chunks due to large AABB lookups. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 9af1d81475d2def60a682ed23e88f1afbbc4c7e6..0a99ee6221c46043ecdf9e9df7a064aa63ee6951 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -61,6 +61,7 @@ import net.minecraft.server.ScoreboardServer; + import net.minecraft.server.level.DemoPlayerInteractManager; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.PlayerInteractManager; ++import net.minecraft.server.level.TicketType; + import net.minecraft.server.level.WorldServer; + import net.minecraft.server.network.PlayerConnection; + import net.minecraft.sounds.SoundCategory; +@@ -74,6 +75,7 @@ import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.player.EntityHuman; ++import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.EnumGamemode; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.World; +@@ -809,6 +811,7 @@ public abstract class PlayerList { + entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + // CraftBukkit end + ++ worldserver1.getChunkProvider().addTicket(TicketType.POST_TELEPORT, new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper + while (avoidSuffocation && !worldserver1.getCubes(entityplayer1) && entityplayer1.locY() < 256.0D) { + entityplayer1.setPosition(entityplayer1.locX(), entityplayer1.locY() + 1.0D, entityplayer1.locZ()); + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a9d8baef5db0655742e85482604db6f6208eb9b6..6c368921f76fb6eb99dd20dd49d6ba5ac80cdfad 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -169,6 +169,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + private CraftEntity bukkitEntity; + + PlayerChunkMap.EntityTracker tracker; // Paper ++ public boolean collisionLoadChunks = false; // Paper + public Throwable addedToWorldStack; // Paper - entity debug + public CraftEntity getBukkitEntity() { + if (bukkitEntity == null) { +diff --git a/src/main/java/net/minecraft/world/level/ICollisionAccess.java b/src/main/java/net/minecraft/world/level/ICollisionAccess.java +index fcf6cc86e3b5d9afe3ab3b3fba2ec13846ed0b4c..fcb3e2f9dea97138e0fd4cd2eb11b54799e1d3b5 100644 +--- a/src/main/java/net/minecraft/world/level/ICollisionAccess.java ++++ b/src/main/java/net/minecraft/world/level/ICollisionAccess.java +@@ -54,7 +54,9 @@ public interface ICollisionAccess extends IBlockAccess { + } + + default boolean b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { ++ try { if (entity != null) entity.collisionLoadChunks = true; // Paper + return this.d(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty); ++ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper + } + + Stream c(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate); +diff --git a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java +index fa3421c9cd8531618827627e9c524a8df77c4c58..d0cc8677f2be422722160fee9b71894b5ddd3186 100644 +--- a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java ++++ b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java +@@ -7,6 +7,9 @@ import java.util.function.Consumer; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.CursorPosition; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.RegionLimitedWorldAccess; + import net.minecraft.util.MathHelper; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.block.Blocks; +@@ -21,13 +24,13 @@ import net.minecraft.world.phys.shapes.VoxelShapes; + public class VoxelShapeSpliterator extends AbstractSpliterator { + + @Nullable +- private final Entity a; ++ private final Entity a; final Entity getEntity() { return this.a; } // Paper - OBFHELPER + private final AxisAlignedBB b; + private final VoxelShapeCollision c; + private final CursorPosition d; +- private final BlockPosition.MutableBlockPosition e; ++ private final BlockPosition.MutableBlockPosition e; final BlockPosition.MutableBlockPosition getMutablePos() { return this.e; } // Paper - OBFHELPER + private final VoxelShape f; +- private final ICollisionAccess g; ++ private final ICollisionAccess g; final ICollisionAccess getCollisionAccess() { return this.g; } // Paper - OBFHELPER + private boolean h; + private final BiPredicate i; + +@@ -64,23 +67,37 @@ public class VoxelShapeSpliterator extends AbstractSpliterator { + boolean a(Consumer consumer) { + while (true) { + if (this.d.a()) { +- int i = this.d.b(); +- int j = this.d.c(); +- int k = this.d.d(); ++ int i = this.d.b(); final int x = i; ++ int j = this.d.c(); final int y = j; ++ int k = this.d.d(); final int z = k; + int l = this.d.e(); + + if (l == 3) { + continue; + } + +- IBlockAccess iblockaccess = this.a(i, k); +- +- if (iblockaccess == null) { ++ // Paper start - ensure we don't load chunks ++ Entity entity = this.getEntity(); ++ BlockPosition.MutableBlockPosition blockposition_mutableblockposition = this.getMutablePos(); ++ boolean far = entity != null && MCUtil.distanceSq(entity.locX(), y, entity.locZ(), x, y, z) > 14; ++ blockposition_mutableblockposition.setValues(x, y, z); ++ ++ boolean isRegionLimited = this.getCollisionAccess() instanceof RegionLimitedWorldAccess; ++ IBlockData iblockdata = isRegionLimited ? Blocks.VOID_AIR.getBlockData() : ((!far && entity instanceof EntityPlayer) || (entity != null && entity.collisionLoadChunks) ++ ? this.getCollisionAccess().getType(blockposition_mutableblockposition) ++ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition) ++ ); ++ ++ if (iblockdata == null) { ++ if (!(entity instanceof EntityPlayer) || entity.world.paperConfig.preventMovingIntoUnloadedChunks) { ++ VoxelShape voxelshape3 = VoxelShapes.of(far ? entity.getBoundingBox() : new AxisAlignedBB(new BlockPosition(x, y, z))); ++ consumer.accept(voxelshape3); ++ return true; ++ } + continue; + } +- +- this.e.d(i, j, k); +- IBlockData iblockdata = iblockaccess.getType(this.e); ++ // Paper - moved up ++ // Paper end + + if (!this.i.test(iblockdata, this.e) || l == 1 && !iblockdata.d() || l == 2 && !iblockdata.a(Blocks.MOVING_PISTON)) { + continue; +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +index cf32a4f63e8e59535c02a3f9c57f98833a2b0e83..24ecac40625629b0bbe460e7fc984b147ede1f1f 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +@@ -249,7 +249,8 @@ public final class VoxelShapes { + + if (k2 < 3) { + blockposition_mutableblockposition.a(enumaxiscycle1, i2, j2, l1); +- IBlockData iblockdata = iworldreader.getType(blockposition_mutableblockposition); ++ IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition_mutableblockposition); // Paper ++ if (iblockdata == null) return 0.0D; // Paper + + if ((k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) { + d0 = iblockdata.b((IBlockAccess) iworldreader, blockposition_mutableblockposition, voxelshapecollision).a(enumdirection_enumaxis2, axisalignedbb.d((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), d0); diff --git a/patches/server-unmapped/0424-Don-t-tick-dead-players.patch b/patches/server-unmapped/0424-Don-t-tick-dead-players.patch new file mode 100644 index 0000000000..9b85066c21 --- /dev/null +++ b/patches/server-unmapped/0424-Don-t-tick-dead-players.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 17:16:48 -0400 +Subject: [PATCH] Don't tick dead players + +Causes sync chunk loads and who knows what all else. +This is safe because Spectators are skipped in unloaded chunks too in vanilla. + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index c0e32b13e79fa6b34ac9448d2f74339bb771274f..e3721287cc18c8df81d1353084364966eb3f55ab 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -609,7 +609,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + public void playerTick() { + try { +- if (!this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { ++ if (valid && !this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) + super.tick(); + } + diff --git a/patches/server-unmapped/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server-unmapped/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch new file mode 100644 index 0000000000..04592576bc --- /dev/null +++ b/patches/server-unmapped/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 19:31:16 -0400 +Subject: [PATCH] Dead Player's shouldn't be able to move + +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/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 564dfa98c166fde509044e6e1938efb321ece53d..8981dfacd10cae9de052e1b36ce5181cd0e6752d 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -1049,7 +1049,7 @@ public abstract class EntityHuman extends EntityLiving { + + @Override + protected boolean isFrozen() { +- return super.isFrozen() || this.isSleeping(); ++ return super.isFrozen() || this.isSleeping() || dead || !valid; // Paper - player's who are dead or not in a world shouldn't move... + } + + @Override diff --git a/patches/server-unmapped/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server-unmapped/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch new file mode 100644 index 0000000000..a3d311fb6f --- /dev/null +++ b/patches/server-unmapped/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch @@ -0,0 +1,294 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 8 Apr 2020 03:06:30 -0400 +Subject: [PATCH] Optimize PlayerChunkMap memory use for visibleChunks + +No longer clones visible chunks which is causing massive memory +allocation issues, likely the source of Humongous Objects on large servers. + +Instead we just synchronize, clear and rebuild, reusing the same object buffers +as before with only 2 small objects created (FastIterator/MapEntry) + +This should result in siginificant memory use reduction and improved GC behavior. + +diff --git a/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f6ff4d8132a95895680f5bc81f8f873e78f0bbdb +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java +@@ -0,0 +1,39 @@ ++package com.destroystokyo.paper.util.map; ++ ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++ ++public class Long2ObjectLinkedOpenHashMapFastCopy extends Long2ObjectLinkedOpenHashMap { ++ ++ public void copyFrom(Long2ObjectLinkedOpenHashMapFastCopy map) { ++ if (key.length != map.key.length) { ++ key = null; ++ key = new long[map.key.length]; ++ } ++ if (value.length != map.value.length) { ++ value = null; ++ //noinspection unchecked ++ value = (V[]) new Object[map.value.length]; ++ } ++ if (link.length != map.link.length) { ++ link = null; ++ link = new long[map.link.length]; ++ } ++ System.arraycopy(map.key, 0, this.key, 0, map.key.length); ++ System.arraycopy(map.value, 0, this.value, 0, map.value.length); ++ System.arraycopy(map.link, 0, this.link, 0, map.link.length); ++ this.size = map.size; ++ this.mask = map.mask; ++ this.first = map.first; ++ this.last = map.last; ++ this.n = map.n; ++ this.maxFill = map.maxFill; ++ this.containsNullKey = map.containsNullKey; ++ } ++ ++ @Override ++ public Long2ObjectLinkedOpenHashMapFastCopy clone() { ++ Long2ObjectLinkedOpenHashMapFastCopy clone = (Long2ObjectLinkedOpenHashMapFastCopy) super.clone(); ++ clone.copyFrom(this); ++ return clone; ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 5a410550cfb48505c9de9979465ed1528c8fbf05..9edbde8299bcd127e1727d34ed441f638e716b2a 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -616,7 +616,7 @@ public final class MCUtil { + + WorldServer world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); + PlayerChunkMap chunkMap = world.getChunkProvider().playerChunkMap; +- Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunks; ++ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.getVisibleChunks(); + ChunkMapDistance chunkMapDistance = chunkMap.chunkDistanceManager; + List allChunks = new ArrayList<>(visibleChunks.values()); + List players = world.players; +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 214098d7ad95839e90b0ec9ea997930c27b4bea4..13ac946487bb05b5c47ee8ee10cb6ed1c992c0e2 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -781,7 +781,7 @@ public class ChunkProviderServer extends IChunkProvider { + }; + // Paper end + this.world.timings.chunkTicks.startTiming(); // Paper +- this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... ++ this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); + + if (optional.isPresent()) { +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index c7619bba9115e8695b5aea2b4d059bea577e748e..5ccc70f36616e1bd8cdb8b23315f7422ec5acc61 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -106,8 +106,33 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + private static final Logger LOGGER = LogManager.getLogger(); + public static final int GOLDEN_TICKET = 33 + ChunkStatus.b(); +- public final Long2ObjectLinkedOpenHashMap updatingChunks = new Long2ObjectLinkedOpenHashMap(); +- public volatile Long2ObjectLinkedOpenHashMap visibleChunks; ++ // Paper start - faster copying ++ public final Long2ObjectLinkedOpenHashMap updatingChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<>(); // Paper - faster copying ++ public final Long2ObjectLinkedOpenHashMap visibleChunks = new ProtectedVisibleChunksMap(); // Paper - faster copying ++ ++ private class ProtectedVisibleChunksMap extends com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy { ++ @Override ++ public PlayerChunk put(long k, PlayerChunk playerChunk) { ++ throw new UnsupportedOperationException("Updating visible Chunks"); ++ } ++ ++ @Override ++ public PlayerChunk remove(long k) { ++ throw new UnsupportedOperationException("Removing visible Chunks"); ++ } ++ ++ @Override ++ public PlayerChunk get(long k) { ++ return PlayerChunkMap.this.getVisibleChunk(k); ++ } ++ ++ public PlayerChunk safeGet(long k) { ++ return super.get(k); ++ } ++ } ++ // Paper end ++ public final com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy pendingVisibleChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy(); // Paper - this is used if the visible chunks is updated while iterating only ++ public transient com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy visibleChunksClone; // Paper - used for async access of visible chunks, clone and cache only when needed + private final Long2ObjectLinkedOpenHashMap pendingUnload; + public final LongSet loadedChunks; // Paper - private -> public + public final WorldServer world; +@@ -180,7 +205,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { + super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag); +- this.visibleChunks = this.updatingChunks.clone(); ++ //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning + this.pendingUnload = new Long2ObjectLinkedOpenHashMap(); + this.loadedChunks = new LongOpenHashSet(); + this.unloadQueue = new LongOpenHashSet(); +@@ -272,9 +297,52 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return (PlayerChunk) this.updatingChunks.get(i); + } + ++ // Paper start - remove cloning of visible chunks unless accessed as a collection async ++ private static final boolean DEBUG_ASYNC_VISIBLE_CHUNKS = Boolean.getBoolean("paper.debug-async-visible-chunks"); ++ private boolean isIterating = false; ++ private boolean hasPendingVisibleUpdate = false; ++ public void forEachVisibleChunk(java.util.function.Consumer consumer) { ++ org.spigotmc.AsyncCatcher.catchOp("forEachVisibleChunk"); ++ boolean prev = isIterating; ++ isIterating = true; ++ try { ++ for (PlayerChunk value : this.visibleChunks.values()) { ++ consumer.accept(value); ++ } ++ } finally { ++ this.isIterating = prev; ++ if (!this.isIterating && this.hasPendingVisibleUpdate) { ++ ((ProtectedVisibleChunksMap)this.visibleChunks).copyFrom(this.pendingVisibleChunks); ++ this.pendingVisibleChunks.clear(); ++ this.hasPendingVisibleUpdate = false; ++ } ++ } ++ } ++ public Long2ObjectLinkedOpenHashMap getVisibleChunks() { ++ if (Thread.currentThread() == this.world.serverThread) { ++ return this.visibleChunks; ++ } else { ++ synchronized (this.visibleChunks) { ++ if (DEBUG_ASYNC_VISIBLE_CHUNKS) new Throwable("Async getVisibleChunks").printStackTrace(); ++ if (this.visibleChunksClone == null) { ++ this.visibleChunksClone = this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.clone() : ((ProtectedVisibleChunksMap)this.visibleChunks).clone(); ++ } ++ return this.visibleChunksClone; ++ } ++ } ++ } ++ // Paper end ++ + @Nullable + public PlayerChunk getVisibleChunk(long i) { // Paper - protected -> public +- return (PlayerChunk) this.visibleChunks.get(i); ++ // Paper start - mt safe get ++ if (Thread.currentThread() != this.world.serverThread) { ++ synchronized (this.visibleChunks) { ++ return (PlayerChunk) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap)this.visibleChunks).safeGet(i)); ++ } ++ } ++ return (PlayerChunk) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap)this.visibleChunks).safeGet(i)); ++ // Paper end + } + + protected IntSupplier c(long i) { +@@ -462,8 +530,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + // Paper end + + protected void save(boolean flag) { ++ Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) + if (flag) { +- List list = (List) this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList()); ++ List list = (List) visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList()); // Paper - remove cloning of visible chunks + MutableBoolean mutableboolean = new MutableBoolean(); + + do { +@@ -491,7 +560,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + // this.i(); // Paper - nuke IOWorker + PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName()); + } else { +- this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { ++ visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { + IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkSave().getNow(null); // CraftBukkit - decompile error + + if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) { +@@ -662,7 +731,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + if (!this.updatingChunksModified) { + return false; + } else { +- this.visibleChunks = this.updatingChunks.clone(); ++ // Paper start - stop cloning visibleChunks ++ synchronized (this.visibleChunks) { ++ if (isIterating) { ++ hasPendingVisibleUpdate = true; ++ this.pendingVisibleChunks.copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunks); ++ } else { ++ hasPendingVisibleUpdate = false; ++ this.pendingVisibleChunks.clear(); ++ ((ProtectedVisibleChunksMap)this.visibleChunks).copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunks); ++ this.visibleChunksClone = null; ++ } ++ } ++ // Paper end ++ + this.updatingChunksModified = false; + return true; + } +@@ -1141,12 +1223,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + protected Iterable f() { +- return Iterables.unmodifiableIterable(this.visibleChunks.values()); ++ return Iterables.unmodifiableIterable(this.getVisibleChunks().values()); // Paper + } + + void a(Writer writer) throws IOException { + CSVWriter csvwriter = CSVWriter.a().a("x").a("z").a("level").a("in_memory").a("status").a("full_status").a("accessible_ready").a("ticking_ready").a("entity_ticking_ready").a("ticket").a("spawning").a("entity_count").a("block_entity_count").a(writer); +- ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunks.long2ObjectEntrySet().iterator(); ++ ObjectBidirectionalIterator objectbidirectionaliterator = this.getVisibleChunks().long2ObjectEntrySet().iterator(); // Paper + + while (objectbidirectionaliterator.hasNext()) { + Entry entry = (Entry) objectbidirectionaliterator.next(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index fcad64fcfc22af227be19741b634b773aca7a98d..c5a4c8c4c9d90a8a081a593488f86ab487adaecb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -294,6 +294,7 @@ public class CraftWorld implements World { + return ret; + } + public int getTileEntityCount() { ++ return net.minecraft.server.MCUtil.ensureMain(() -> { + // We don't use the full world tile entity list, so we must iterate chunks + Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; + int size = 0; +@@ -305,11 +306,13 @@ public class CraftWorld implements World { + size += chunk.tileEntities.size(); + } + return size; ++ }); + } + public int getTickableTileEntityCount() { + return world.tileEntityListTick.size(); + } + public int getChunkCount() { ++ return net.minecraft.server.MCUtil.ensureMain(() -> { + int ret = 0; + + for (PlayerChunk chunkHolder : world.getChunkProvider().playerChunkMap.visibleChunks.values()) { +@@ -318,7 +321,7 @@ public class CraftWorld implements World { + } + } + +- return ret; ++ return ret; }); + } + public int getPlayerCount() { + return world.players.size(); +@@ -443,6 +446,14 @@ public class CraftWorld implements World { + + @Override + public Chunk[] getLoadedChunks() { ++ // Paper start ++ if (Thread.currentThread() != world.getMinecraftWorld().serverThread) { ++ synchronized (world.getChunkProvider().playerChunkMap.visibleChunks) { ++ Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; ++ return chunks.values().stream().map(PlayerChunk::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.Chunk::getBukkitChunk).toArray(Chunk[]::new); ++ } ++ } ++ // Paper end + Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; + return chunks.values().stream().map(PlayerChunk::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.Chunk::getBukkitChunk).toArray(Chunk[]::new); + } diff --git a/patches/server-unmapped/0427-Increase-Light-Queue-Size.patch b/patches/server-unmapped/0427-Increase-Light-Queue-Size.patch new file mode 100644 index 0000000000..2b28126ee7 --- /dev/null +++ b/patches/server-unmapped/0427-Increase-Light-Queue-Size.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 8 Apr 2020 21:24:05 -0400 +Subject: [PATCH] Increase Light Queue Size + +Wiz mentioned that large WorldEdit operations cause light to run on +main thread. The queue was small, set to 5.. this bumps it to 20 +but makes it configurable per-world. + +The main risk of increasing this higher is during shutdown, some +queued light updates may be lost because mojang did not flush the +light engine on shutdown... + +The queue size only puts a cap on max loss, doesn't solve that problem. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1..cd248eb6be663e8be33f2c3c6b06b77b6d5753a4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -620,4 +620,9 @@ public class PaperWorldConfig { + private void zombieVillagerInfectionChance() { + zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); + } ++ ++ public int lightQueueSize = 20; ++ private void lightQueueSize() { ++ lightQueueSize = getInt("light-queue-size", lightQueueSize); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index b4e058794c3f8a827f3aabab5b98239a4c79c42c..34c273178e711466ec6638f24e0371554e26e134 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -777,7 +777,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant +Date: Thu, 9 Apr 2020 00:09:26 -0400 +Subject: [PATCH] Mid Tick Chunk Tasks - Speed up processing of chunk loads and + generation + +Credit to Spotted for the idea + +A lot of the new chunk system requires constant back and forth the main thread +to handle priority scheduling and ensuring conflicting tasks do not run at the +same time. + +The issue is, these queues are only checked at either: + +A) Sync Chunk Loads +B) End of Tick while sleeping + +This results in generating chunks sitting waiting for a full tick to +complete before it will even start the next unit of work to do. + +Additionally, this also delays loading of chunks until this same timing. + +We will now periodically poll the chunk task queues throughout the tick, +looking for work to do. +We do this in a fair method that considers all worlds, not just the one being +ticked, so that each world can get 1 task procesed each before the next pass. + +In a view distance of 15, chunk loading performance was visually faster on the client. + +Flying at high speed in spectator mode was able to keep up with chunk loading (as long as they are already generated) + +diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java +index fed920e5ec65409377f181d74dcf9274d45aadc1..b4d43ceed368552e703886213327a0c0bb5ccb92 100644 +--- a/src/main/java/co/aikar/timings/MinecraftTimings.java ++++ b/src/main/java/co/aikar/timings/MinecraftTimings.java +@@ -16,6 +16,7 @@ import java.util.Map; + public final class MinecraftTimings { + + public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); ++ public static final Timing midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks"); + public static final Timing playerListTimer = Timings.ofSafe("Player List"); + public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); + public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index da93d38fe63035e4ff198ada84a4431f52d97c01..ddbc8cb712c50038922eded75dd6ca85fe851078 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -410,4 +410,9 @@ public class PaperConfig { + log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); + } + } ++ ++ public static int midTickChunkTasks = 1000; ++ private static void midTickChunkTasks() { ++ midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 34c273178e711466ec6638f24e0371554e26e134..cb15606d528b2f94103d347ad89d3836fa93c360 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1057,6 +1057,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { ++ midTickLoadChunks(); // will only do loads since we are still considered !canSleepForTick + return !this.canOversleep(); + }); + isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); +@@ -1320,13 +1339,16 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { // Paper - safe iterator incase chunk loads, also no wrapping ++ final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); + + if (optional.isPresent()) { +@@ -805,6 +808,7 @@ public class ChunkProviderServer extends IChunkProvider { + //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper + this.world.a(chunk, k); + //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper ++ if (chunksTicked[0]++ % 10 == 0) this.world.getMinecraftServer().midTickLoadChunks(); // Paper + } + } + } +@@ -962,6 +966,41 @@ public class ChunkProviderServer extends IChunkProvider { + super.executeTask(runnable); + } + ++ // Paper start ++ private long lastMidTickChunkTask = 0; ++ public boolean pollChunkLoadTasks() { ++ if (com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ChunkProviderServer.this.world.asyncChunkTaskManager.pollNextChunkTask()) { ++ try { ++ ChunkProviderServer.this.tickDistanceManager(); ++ } finally { ++ // from below: process pending Chunk loadCallback() and unloadCallback() after each run task ++ playerChunkMap.callbackExecutor.run(); ++ } ++ return true; ++ } ++ return false; ++ } ++ public void midTickLoadChunks() { ++ MinecraftServer server = ChunkProviderServer.this.world.getMinecraftServer(); ++ // always try to load chunks, restrain generation/other updates only. don't count these towards tick count ++ //noinspection StatementWithEmptyBody ++ while (pollChunkLoadTasks()) {} ++ ++ if (System.nanoTime() - lastMidTickChunkTask < 200000) { ++ return; ++ } ++ ++ for (;server.midTickChunksTasksRan < com.destroystokyo.paper.PaperConfig.midTickChunkTasks && server.canSleepForTick();) { ++ if (this.executeNext()) { ++ server.midTickChunksTasksRan++; ++ lastMidTickChunkTask = System.nanoTime(); ++ } else { ++ break; ++ } ++ } ++ } ++ // Paper end ++ + @Override + protected boolean executeNext() { + // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 35fc51ac93a62f6dc4b141dc94a3cda0399f0ce1..ce0bbd6fb467c84d14fa4eaa8f80ed5b261e07bd 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -571,6 +571,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + timings.scheduledBlocks.stopTiming(); // Paper + ++ this.getMinecraftServer().midTickLoadChunks(); // Paper + gameprofilerfiller.exitEnter("raid"); + this.timings.raids.startTiming(); // Paper - timings + this.persistentRaid.a(); +@@ -579,6 +580,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + timings.doSounds.startTiming(); // Spigot + this.ak(); + timings.doSounds.stopTiming(); // Spigot ++ this.getMinecraftServer().midTickLoadChunks(); // Paper + this.ticking = false; + gameprofilerfiller.exitEnter("entities"); + boolean flag3 = true || !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players +@@ -645,6 +647,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + timings.entityTick.stopTiming(); // Spigot + + this.tickingEntities = false; ++ this.getMinecraftServer().midTickLoadChunks(); // Paper + + Entity entity2; + +@@ -654,6 +657,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + timings.tickEntities.stopTiming(); // Spigot ++ this.getMinecraftServer().midTickLoadChunks(); // Paper + this.tickBlockEntities(); + } + diff --git a/patches/server-unmapped/0429-Don-t-move-existing-players-to-world-spawn.patch b/patches/server-unmapped/0429-Don-t-move-existing-players-to-world-spawn.patch new file mode 100644 index 0000000000..17f522dfd3 --- /dev/null +++ b/patches/server-unmapped/0429-Don-t-move-existing-players-to-world-spawn.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 9 Apr 2020 21:20:33 -0400 +Subject: [PATCH] Don't move existing players to world spawn + +This can cause a nasty server lag the spawn chunks are not kept loaded +or they aren't finished loading yet, or if the world spawn radius is +larger than the keep loaded range. + +By skipping this, we avoid potential for a large spike on server start. + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index e3721287cc18c8df81d1353084364966eb3f55ab..79003f43c4f15a7e5dd51587bc8c2f477bedb1b2 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -254,7 +254,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.serverStatisticManager = minecraftserver.getPlayerList().getStatisticManager(this); + this.advancementDataPlayer = minecraftserver.getPlayerList().f(this); + this.G = 1.0F; +- this.c(worldserver); ++ //this.c(worldserver); // Paper - don't move to spawn on login, only first join + this.co = minecraftserver.a(this); + + this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper +@@ -306,6 +306,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + // CraftBukkit end + ++ public final void moveToSpawn(WorldServer worldserver) { c(worldserver); } // Paper - OBFHELPER + private void c(WorldServer worldserver) { + BlockPosition blockposition = worldserver.getSpawn(); + +@@ -483,7 +484,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + position = Vec3D.a(((WorldServer) world).getSpawn()); + } + this.world = world; +- this.setPosition(position.getX(), position.getY(), position.getZ()); ++ this.setPositionRaw(position.getX(), position.getY(), position.getZ()); // Paper - don't register to chunks yet + } + this.playerInteractManager.a((WorldServer) world); + } +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 0a99ee6221c46043ecdf9e9df7a064aa63ee6951..bd272d6fe86c30c3f22418802f98609410f947f8 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -208,6 +208,8 @@ public abstract class PlayerList { + worldserver1 = worldserver; + } + ++ if (nbttagcompound == null) entityplayer.moveToSpawn(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are.... ++ + entityplayer.spawnIn(worldserver1); + entityplayer.playerInteractManager.a((WorldServer) entityplayer.world); + String s1 = "local"; diff --git a/patches/server-unmapped/0430-Add-tick-times-API-and-mspt-command.patch b/patches/server-unmapped/0430-Add-tick-times-API-and-mspt-command.patch new file mode 100644 index 0000000000..d32bc81676 --- /dev/null +++ b/patches/server-unmapped/0430-Add-tick-times-API-and-mspt-command.patch @@ -0,0 +1,169 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 5 Apr 2020 22:23:14 -0500 +Subject: [PATCH] Add tick times API and /mspt command + + +diff --git a/src/main/java/com/destroystokyo/paper/MSPTCommand.java b/src/main/java/com/destroystokyo/paper/MSPTCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d0211d4f39f9d6af1d751ac66342b42cc6d7ba6d +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/MSPTCommand.java +@@ -0,0 +1,64 @@ ++package com.destroystokyo.paper; ++ ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.ChatColor; ++import org.bukkit.Location; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++ ++import java.text.DecimalFormat; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.List; ++ ++public class MSPTCommand extends Command { ++ private static final DecimalFormat DF = new DecimalFormat("########0.0"); ++ ++ public MSPTCommand(String name) { ++ super(name); ++ this.description = "View server tick times"; ++ this.usageMessage = "/mspt"; ++ this.setPermission("bukkit.command.mspt"); ++ } ++ ++ @Override ++ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { ++ return Collections.emptyList(); ++ } ++ ++ @Override ++ public boolean execute(CommandSender sender, String commandLabel, String[] args) { ++ if (!testPermission(sender)) return true; ++ ++ MinecraftServer server = MinecraftServer.getServer(); ++ ++ List times = new ArrayList<>(); ++ times.addAll(eval(server.tickTimes5s.getTimes())); ++ times.addAll(eval(server.tickTimes10s.getTimes())); ++ times.addAll(eval(server.tickTimes60s.getTimes())); ++ ++ sender.sendMessage("§6Server tick times §e(§7avg§e/§7min§e/§7max§e)§6 from last 5s§7,§6 10s§7,§6 1m§e:"); ++ sender.sendMessage(String.format("§6◴ %s§7/%s§7/%s§e, %s§7/%s§7/%s§e, %s§7/%s§7/%s", times.toArray())); ++ return true; ++ } ++ ++ private static List eval(long[] times) { ++ long min = Integer.MAX_VALUE; ++ long max = 0L; ++ long total = 0L; ++ for (long value : times) { ++ if (value > 0L && value < min) min = value; ++ if (value > max) max = value; ++ total += value; ++ } ++ double avgD = ((double) total / (double) times.length) * 1.0E-6D; ++ double minD = ((double) min) * 1.0E-6D; ++ double maxD = ((double) max) * 1.0E-6D; ++ return Arrays.asList(getColor(avgD), getColor(minD), getColor(maxD)); ++ } ++ ++ private static String getColor(double avg) { ++ return ChatColor.COLOR_CHAR + (avg >= 50 ? "c" : avg >= 40 ? "e" : "a") + DF.format(avg); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index ddbc8cb712c50038922eded75dd6ca85fe851078..78271b400c79578d043b20a5389a37b1bef9a70d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -69,6 +69,7 @@ public class PaperConfig { + + commands = new HashMap(); + commands.put("paper", new PaperCommand("paper")); ++ commands.put("mspt", new MSPTCommand("mspt")); + + version = getInt("config-version", 20); + set("config-version", 20); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index cb15606d528b2f94103d347ad89d3836fa93c360..04363d1076b428c302e045039a5d240490dc5e6a 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -219,6 +219,11 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant +Date: Fri, 10 Apr 2020 21:24:12 -0400 +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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 8577451ed4dcba901ca9f74e0ff198ab0336d689..e11649b838b6c6e8745d3a0c6d093b3cfff0acda 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2379,5 +2379,10 @@ public final class CraftServer implements Server { + public int getCurrentTick() { + return net.minecraft.server.MinecraftServer.currentTick; + } ++ ++ @Override ++ public boolean isStopping() { ++ return net.minecraft.server.MinecraftServer.getServer().hasStopped(); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0432-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server-unmapped/0432-Add-Raw-Byte-ItemStack-Serialization.patch new file mode 100644 index 0000000000..292ccedef1 --- /dev/null +++ b/patches/server-unmapped/0432-Add-Raw-Byte-ItemStack-Serialization.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Thu, 30 Apr 2020 16:56:54 +0200 +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/net/minecraft/nbt/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java +index 20410a5853e34c90c872f5e9592d50c4727e914d..860f084de38dc3f8723d881ff78fb1873f2b602a 100644 +--- a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java ++++ b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java +@@ -51,6 +51,7 @@ public class NBTCompressedStreamTools { + return nbttagcompound; + } + ++ public static NBTTagCompound readNBT(InputStream inputstream) throws IOException { return a(inputstream); } // Paper - OBFHELPER + public static NBTTagCompound a(InputStream inputstream) throws IOException { + DataInputStream datainputstream = new DataInputStream(new BufferedInputStream(new GZIPInputStream(inputstream))); + Throwable throwable = null; +@@ -106,6 +107,7 @@ public class NBTCompressedStreamTools { + + } + ++ public static void writeNBT(NBTTagCompound nbttagcompound, OutputStream outputstream) throws IOException { a(nbttagcompound, outputstream); } // Paper - OBFHELPER + public static void a(NBTTagCompound nbttagcompound, OutputStream outputstream) throws IOException { + DataOutputStream dataoutputstream = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(outputstream))); + Throwable throwable = null; +diff --git a/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java b/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java +index 6527509e6aed7187667c681af682e9a02937a224..28e36ee76da533f8aa0a09cfc4f1fc0f744af715 100644 +--- a/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java ++++ b/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java +@@ -208,6 +208,7 @@ public class DataConverterRegistry { + return datafixerbuilder.build(SystemUtils.e()); + } + ++ public static DataFixer getDataFixer() { return a(); } // Paper - OBFHELPER + public static DataFixer a() { + return DataConverterRegistry.c; + } +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 7b1df591007b9c50bcaf4bcd30562396a9549193..b88aec3b97d43018cf2733bad069a90338aa98cb 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -198,6 +198,7 @@ public final class ItemStack { + this.checkEmpty(); + } + ++ public static ItemStack fromCompound(NBTTagCompound nbttagcompound) { return a(nbttagcompound); } // Paper - OBFHELPER + public static ItemStack a(NBTTagCompound nbttagcompound) { + try { + return new ItemStack(nbttagcompound); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 7e4cceff7ce9ffaff00caf21088fd7bc59e66933..2519dbce9717ff647d50c31aed6aca68b9f4e3af 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -380,6 +380,46 @@ public final class CraftMagicNumbers implements UnsafeValues { + public boolean isSupportedApiVersion(String apiVersion) { + return apiVersion != null && SUPPORTED_API.contains(apiVersion); + } ++ ++ @Override ++ public byte[] serializeItem(ItemStack item) { ++ Preconditions.checkNotNull(item, "null cannot be serialized"); ++ Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized"); ++ ++ java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); ++ NBTTagCompound compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).getHandle() : CraftItemStack.asNMSCopy(item)).save(new NBTTagCompound()); ++ compound.setInt("DataVersion", getDataVersion()); ++ try { ++ net.minecraft.nbt.NBTCompressedStreamTools.writeNBT( ++ compound, ++ outputStream ++ ); ++ } catch (IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return outputStream.toByteArray(); ++ } ++ ++ @Override ++ public ItemStack deserializeItem(byte[] data) { ++ Preconditions.checkNotNull(data, "null cannot be deserialized"); ++ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing"); ++ ++ try { ++ NBTTagCompound compound = net.minecraft.nbt.NBTCompressedStreamTools.readNBT( ++ new java.io.ByteArrayInputStream(data) ++ ); ++ int dataVersion = compound.getInt("DataVersion"); ++ ++ Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); ++ Dynamic converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ITEM_STACK, new Dynamic(DynamicOpsNBT.a, compound), dataVersion, getDataVersion()); ++ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.fromCompound((NBTTagCompound) converted.getValue())); ++ } catch (IOException ex) { ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(ex); ++ throw new RuntimeException(); ++ } ++ } + // Paper end + + /** diff --git a/patches/server-unmapped/0433-Remove-streams-from-Mob-AI-System.patch b/patches/server-unmapped/0433-Remove-streams-from-Mob-AI-System.patch new file mode 100644 index 0000000000..4937798620 --- /dev/null +++ b/patches/server-unmapped/0433-Remove-streams-from-Mob-AI-System.patch @@ -0,0 +1,253 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 17:53:29 -0700 +Subject: [PATCH] Remove streams from Mob AI System + +The streams hurt performance and allocate tons of garbage, so +replace them with the standard iterator. + +Also optimise the stream.anyMatch statement to move to a bitset +where we can replace the call with a single bitwise operation. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java +index b505c23c57a4b84faf5906c6295455b4720c4426..5c32cbe81c47fcb9ae347faa6fc007c5d28d79bf 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java +@@ -1,10 +1,12 @@ + package net.minecraft.world.entity.ai.goal; + ++import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector + import java.util.EnumSet; + + public abstract class PathfinderGoal { + +- private final EnumSet a = EnumSet.noneOf(PathfinderGoal.Type.class); ++ private final EnumSet a = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. ++ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector + + public PathfinderGoal() {} + +@@ -28,16 +30,20 @@ public abstract class PathfinderGoal { + public void e() {} + + public void a(EnumSet enumset) { +- this.a.clear(); +- this.a.addAll(enumset); ++ // Paper start - remove streams from pathfindergoalselector ++ this.goalTypes.clear(); ++ this.goalTypes.addAllUnchecked(enumset); ++ // Paper end - remove streams from pathfindergoalselector + } + + public String toString() { + return this.getClass().getSimpleName(); + } + +- public EnumSet i() { +- return this.a; ++ // Paper start - remove streams from pathfindergoalselector ++ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { ++ return this.goalTypes; ++ // Paper end - remove streams from pathfindergoalselector + } + + public static enum Type { +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java +index 8c234c09a4d9ada83e36e3cdbcc1f2f5c6202f28..385cd079e264a7e66e91ab3b70b90afb59688dcd 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java +@@ -1,8 +1,10 @@ + package net.minecraft.world.entity.ai.goal; + ++import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector + import com.google.common.collect.Sets; + import java.util.EnumMap; + import java.util.EnumSet; ++import java.util.Iterator; // Paper - remove streams from pathfindergoalselector + import java.util.Map; + import java.util.Set; + import java.util.function.Supplier; +@@ -28,7 +30,8 @@ public class PathfinderGoalSelector { + private final Map c = new EnumMap(PathfinderGoal.Type.class); + private final Set d = Sets.newLinkedHashSet(); private Set getTasks() { return d; }// Paper - OBFHELPER + private final Supplier e; +- private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); ++ private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. ++ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector + private int g = 3;private int getTickRate() { return g; } // Paper - OBFHELPER + private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO + +@@ -56,35 +59,38 @@ public class PathfinderGoalSelector { + // Paper end + + public void a(PathfinderGoal pathfindergoal) { +- this.d.stream().filter((pathfindergoalwrapped) -> { +- return pathfindergoalwrapped.j() == pathfindergoal; +- }).filter(PathfinderGoalWrapped::g).forEach(PathfinderGoalWrapped::d); +- this.d.removeIf((pathfindergoalwrapped) -> { +- return pathfindergoalwrapped.j() == pathfindergoal; +- }); ++ // Paper start - remove streams from pathfindergoalselector ++ for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { ++ PathfinderGoalWrapped goalWrapped = iterator.next(); ++ if (goalWrapped.j() != pathfindergoal) { ++ continue; ++ } ++ if (goalWrapped.g()) { ++ goalWrapped.d(); ++ } ++ iterator.remove(); ++ } ++ // Paper end - remove streams from pathfindergoalselector + } + ++ private static final PathfinderGoal.Type[] PATHFINDER_GOAL_TYPES = PathfinderGoal.Type.values(); // Paper - remove streams from pathfindergoalselector ++ + public void doTick() { + GameProfilerFiller gameprofilerfiller = (GameProfilerFiller) this.e.get(); + + gameprofilerfiller.enter("goalCleanup"); +- this.d().filter((pathfindergoalwrapped) -> { +- boolean flag; +- +- if (pathfindergoalwrapped.g()) { +- Stream stream = pathfindergoalwrapped.i().stream(); +- EnumSet enumset = this.f; +- +- this.f.getClass(); +- if (!stream.anyMatch(enumset::contains) && pathfindergoalwrapped.b()) { +- flag = false; +- return flag; +- } ++ // Paper start - remove streams from pathfindergoalselector ++ for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { ++ PathfinderGoalWrapped wrappedGoal = iterator.next(); ++ if (!wrappedGoal.g()) { ++ continue; + } +- +- flag = true; +- return flag; +- }).forEach(PathfinderGoal::d); ++ if (!this.goalTypes.hasCommonElements(wrappedGoal.getGoalTypes()) && wrappedGoal.b()) { ++ continue; ++ } ++ wrappedGoal.d(); ++ } ++ // Paper end - remove streams from pathfindergoalselector + this.c.forEach((pathfindergoal_type, pathfindergoalwrapped) -> { + if (!pathfindergoalwrapped.g()) { + this.c.remove(pathfindergoal_type); +@@ -93,30 +99,58 @@ public class PathfinderGoalSelector { + }); + gameprofilerfiller.exit(); + gameprofilerfiller.enter("goalUpdate"); +- this.d.stream().filter((pathfindergoalwrapped) -> { +- return !pathfindergoalwrapped.g(); +- }).filter((pathfindergoalwrapped) -> { +- Stream stream = pathfindergoalwrapped.i().stream(); +- EnumSet enumset = this.f; +- +- this.f.getClass(); +- return stream.noneMatch(enumset::contains); +- }).filter((pathfindergoalwrapped) -> { +- return pathfindergoalwrapped.i().stream().allMatch((pathfindergoal_type) -> { +- return ((PathfinderGoalWrapped) this.c.getOrDefault(pathfindergoal_type, PathfinderGoalSelector.b)).a(pathfindergoalwrapped); +- }); +- }).filter(PathfinderGoalWrapped::a).forEach((pathfindergoalwrapped) -> { +- pathfindergoalwrapped.i().forEach((pathfindergoal_type) -> { +- PathfinderGoalWrapped pathfindergoalwrapped1 = (PathfinderGoalWrapped) this.c.getOrDefault(pathfindergoal_type, PathfinderGoalSelector.b); +- +- pathfindergoalwrapped1.d(); +- this.c.put(pathfindergoal_type, pathfindergoalwrapped); +- }); +- pathfindergoalwrapped.c(); +- }); ++ // Paper start - remove streams from pathfindergoalselector ++ goal_update_loop: for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { ++ PathfinderGoalWrapped wrappedGoal = iterator.next(); ++ if (wrappedGoal.g()) { ++ continue; ++ } ++ ++ OptimizedSmallEnumSet wrappedGoalSet = wrappedGoal.getGoalTypes(); ++ ++ if (this.goalTypes.hasCommonElements(wrappedGoalSet)) { ++ continue; ++ } ++ ++ long iterator1 = wrappedGoalSet.getBackingSet(); ++ int wrappedGoalSize = wrappedGoalSet.size(); ++ for (int i = 0; i < wrappedGoalSize; ++i) { ++ PathfinderGoal.Type type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; ++ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); ++ PathfinderGoalWrapped wrapped = this.c.getOrDefault(type, PathfinderGoalSelector.b); ++ if (!wrapped.a(wrappedGoal)) { ++ continue goal_update_loop; ++ } ++ } ++ ++ if (!wrappedGoal.a()) { ++ continue; ++ } ++ ++ iterator1 = wrappedGoalSet.getBackingSet(); ++ wrappedGoalSize = wrappedGoalSet.size(); ++ for (int i = 0; i < wrappedGoalSize; ++i) { ++ PathfinderGoal.Type type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; ++ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); ++ PathfinderGoalWrapped wrapped = this.c.getOrDefault(type, PathfinderGoalSelector.b); ++ ++ wrapped.d(); ++ this.c.put(type, wrappedGoal); ++ } ++ ++ wrappedGoal.c(); ++ } ++ // Paper end - remove streams from pathfindergoalselector + gameprofilerfiller.exit(); + gameprofilerfiller.enter("goalTick"); +- this.d().forEach(PathfinderGoalWrapped::e); ++ // Paper start - remove streams from pathfindergoalselector ++ for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { ++ PathfinderGoalWrapped wrappedGoal = iterator.next(); ++ if (wrappedGoal.g()) { ++ wrappedGoal.e(); ++ } ++ } ++ // Paper end - remove streams from pathfindergoalselector + gameprofilerfiller.exit(); + } + +@@ -125,11 +159,11 @@ public class PathfinderGoalSelector { + } + + public void a(PathfinderGoal.Type pathfindergoal_type) { +- this.f.add(pathfindergoal_type); ++ this.goalTypes.addUnchecked(pathfindergoal_type); // Paper - remove streams from pathfindergoalselector + } + + public void b(PathfinderGoal.Type pathfindergoal_type) { +- this.f.remove(pathfindergoal_type); ++ this.goalTypes.removeUnchecked(pathfindergoal_type); // Paper - remove streams from pathfindergoalselector + } + + public void a(PathfinderGoal.Type pathfindergoal_type, boolean flag) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java +index 7bb531e47668cf445083c4dedb03ccafe6a9c96b..8c8e39d35fb56aa6cf7d456adab01dff5d13a60d 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java +@@ -59,9 +59,10 @@ public class PathfinderGoalWrapped extends PathfinderGoal { + this.a.a(enumset); + } + +- @Override +- public EnumSet i() { +- return this.a.i(); ++ // Paper start - remove streams from pathfindergoalselector ++ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { ++ return this.a.getGoalTypes(); ++ // Paper end - remove streams from pathfindergoalselector + } + + public boolean isRunning() { return this.g(); } // Paper - OBFHELPER diff --git a/patches/server-unmapped/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch b/patches/server-unmapped/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch new file mode 100644 index 0000000000..b557363c64 --- /dev/null +++ b/patches/server-unmapped/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 11 Apr 2020 21:23:42 -0400 +Subject: [PATCH] Delay unsafe actions until after entity ticking is done + +This will help prevent many cases of unregistering entities during entity ticking + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index ce0bbd6fb467c84d14fa4eaa8f80ed5b261e07bd..bc629c8355a0a2273bcf1285a22deb1ce1154bf9 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -178,6 +178,16 @@ public class WorldServer extends World implements GeneratorAccessSeed { + public final List players = Lists.newArrayList(); // Paper - private -> public + public final ChunkProviderServer chunkProvider; // Paper - public + boolean tickingEntities; ++ // Paper start ++ List afterEntityTickingTasks = Lists.newArrayList(); ++ public void doIfNotEntityTicking(java.lang.Runnable run) { ++ if (tickingEntities) { ++ afterEntityTickingTasks.add(run); ++ } else { ++ run.run(); ++ } ++ } ++ // Paper end + private final MinecraftServer server; + public final WorldDataServer worldDataServer; // CraftBukkit - type + public boolean savingDisabled; +@@ -647,6 +657,16 @@ public class WorldServer extends World implements GeneratorAccessSeed { + timings.entityTick.stopTiming(); // Spigot + + this.tickingEntities = false; ++ // Paper start ++ for (java.lang.Runnable run : this.afterEntityTickingTasks) { ++ try { ++ run.run(); ++ } catch (Exception e) { ++ LOGGER.error("Error in After Entity Ticking Task", e); ++ } ++ } ++ this.afterEntityTickingTasks.clear(); ++ // Paper end + this.getMinecraftServer().midTickLoadChunks(); // Paper + + Entity entity2; diff --git a/patches/server-unmapped/0435-Async-command-map-building.patch b/patches/server-unmapped/0435-Async-command-map-building.patch new file mode 100644 index 0000000000..303aa637e9 --- /dev/null +++ b/patches/server-unmapped/0435-Async-command-map-building.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Callahan +Date: Wed, 8 Apr 2020 02:42:14 -0500 +Subject: [PATCH] Async command map building + + +diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java +index 63948c78205730d4aa6a6cc418f4f9de30401beb..592b1bb2ce5cedb627f42c73ef072ade6553347e 100644 +--- a/src/main/java/net/minecraft/commands/CommandDispatcher.java ++++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java +@@ -29,6 +29,7 @@ import net.minecraft.network.chat.ChatHoverable; + import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.IChatMutableComponent; + import net.minecraft.network.protocol.game.PacketPlayOutCommands; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.commands.CommandAdvancement; + import net.minecraft.server.commands.CommandAttribute; + import net.minecraft.server.commands.CommandBan; +@@ -328,6 +329,14 @@ public class CommandDispatcher { + if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot + // CraftBukkit start + // Register Vanilla commands into builtRoot as before ++ // Paper start - Async command map building ++ java.util.concurrent.ForkJoinPool.commonPool().execute(() -> { ++ sendAsync(entityplayer); ++ }); ++ } ++ ++ private void sendAsync(EntityPlayer entityplayer) { ++ // Paper end - Async command map building + Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues + RootCommandNode vanillaRoot = new RootCommandNode(); + +@@ -345,7 +354,14 @@ public class CommandDispatcher { + for (CommandNode node : rootcommandnode.getChildren()) { + bukkit.add(node.getName()); + } ++ // Paper start - Async command map building ++ MinecraftServer.getServer().execute(() -> { ++ runSync(entityplayer, bukkit, rootcommandnode); ++ }); ++ } + ++ private void runSync(EntityPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { ++ // Paper end - Async command map building + PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); + event.getPlayer().getServer().getPluginManager().callEvent(event); + diff --git a/patches/server-unmapped/0436-Improved-Watchdog-Support.patch b/patches/server-unmapped/0436-Improved-Watchdog-Support.patch new file mode 100644 index 0000000000..d294732178 --- /dev/null +++ b/patches/server-unmapped/0436-Improved-Watchdog-Support.patch @@ -0,0 +1,608 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 12 Apr 2020 15:50:48 -0400 +Subject: [PATCH] Improved Watchdog Support + +Forced Watchdog Crash support and Improve Async Shutdown + +If the request to shut down the server is received while we are in +a watchdog hang, immediately treat it as a crash and begin the shutdown +process. Shutdown process is now improved to also shutdown cleanly when +not using restart scripts either. + +If a server is deadlocked, a server owner can send SIGUP (or any other signal +the JVM understands to shut down as it currently does) and the watchdog +will no longer need to wait until the full timeout, allowing you to trigger +a close process and try to shut the server down gracefully, saving player and +world data. + +Previously there was no way to trigger this outside of waiting for a full watchdog +timeout, which may be set to a really long time... + +Additionally, fix everything to do with shutting the server down asynchronously. + +Previously, nearly everything about the process was fragile and unsafe. Main might +not have actually been frozen, and might still be manipulating state. + +Or, some reuest might ask main to do something in the shutdown but main is dead. + +Or worse, other things might start closing down items such as the Console or Thread Pool +before we are fully shutdown. + +This change tries to resolve all of these issues by moving everything into the stop +method and guaranteeing only one thread is stopping the server. + +We then issue Thread Death to the main thread of another thread initiates the stop process. +We have to ensure Thread Death propagates correctly though to stop main completely. + +This is to ensure that if main isn't truely stuck, it's not manipulating state we are trying to save. + +This also moves all plugins who register "delayed init" tasks to occur just before "Done" so they +are properly accounted for and wont trip watchdog on init. + +diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java +index 0b9e689d57705965721b5c55bc45d36657f360e4..dee00aac05f1acf050f05d4db557a08dd0f301c8 100644 +--- a/src/main/java/com/destroystokyo/paper/Metrics.java ++++ b/src/main/java/com/destroystokyo/paper/Metrics.java +@@ -92,7 +92,12 @@ public class Metrics { + * Starts the Scheduler which submits our data every 30 minutes. + */ + private void startSubmitting() { +- final Runnable submitTask = this::submitData; ++ final Runnable submitTask = () -> { ++ if (MinecraftServer.getServer().hasStopped()) { ++ return; ++ } ++ submitData(); ++ }; + + // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the + // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. +diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java +index d0fdb9ce57b22a1f582cddec9afcc35b75d58cc6..9b7a51890c667601b195ff15b2bf0d6c76c7f19f 100644 +--- a/src/main/java/net/minecraft/CrashReport.java ++++ b/src/main/java/net/minecraft/CrashReport.java +@@ -257,6 +257,7 @@ public class CrashReport { + } + + public static CrashReport a(Throwable throwable, String s) { ++ if (throwable instanceof ThreadDeath) com.destroystokyo.paper.util.SneakyThrow.sneaky(throwable); // Paper + while (throwable instanceof CompletionException && throwable.getCause() != null) { + throwable = throwable.getCause(); + } +diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java +index 397194b3e90c9df39cfae17b401c7ac891b0dbb7..61b4c42e95994343772a91640b243b8e8224e09b 100644 +--- a/src/main/java/net/minecraft/SystemUtils.java ++++ b/src/main/java/net/minecraft/SystemUtils.java +@@ -130,6 +130,7 @@ public class SystemUtils { + return SystemUtils.f; + } + ++ public static void shutdownServerThreadPool() { h(); } // Paper - OBFHELPER + public static void h() { + a(SystemUtils.e); + a(SystemUtils.f); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 04363d1076b428c302e045039a5d240490dc5e6a..7f67773686a2d55153f7b2bfbe24df84fe1198be 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -271,7 +271,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant S a(Function function) { + AtomicReference atomicreference = new AtomicReference(); + Thread thread = new Thread(() -> { +@@ -853,6 +856,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { ++ world.tickingEntities = false; ++ }); ++ } ++ // Paper end + // CraftBukkit end + MinecraftServer.LOGGER.info("Stopping server"); + MinecraftTimings.stopServer(); // Paper +@@ -932,7 +953,18 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant {}; ++ } ++ // Paper end + return new TickTask(this.ticks, runnable); + } + +@@ -1423,6 +1480,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { + CompletableFuture completablefuture; +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index bc629c8355a0a2273bcf1285a22deb1ce1154bf9..524bbf9bdf5fb0e1e4ff217ae3291fdbe742437e 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -177,7 +177,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + private final Queue entitiesToAdd = Queues.newArrayDeque(); + public final List players = Lists.newArrayList(); // Paper - private -> public + public final ChunkProviderServer chunkProvider; // Paper - public +- boolean tickingEntities; ++ public boolean tickingEntities; // Paper - expose for watchdog + // Paper start + List afterEntityTickingTasks = Lists.newArrayList(); + public void doIfNotEntityTicking(java.lang.Runnable run) { +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index bd272d6fe86c30c3f22418802f98609410f947f8..9eec320ca5a63a313138dc84367e93038b457c0d 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -507,7 +507,7 @@ public abstract class PlayerList { + cserver.getPluginManager().callEvent(playerQuitEvent); + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + +- entityplayer.playerTick(); // SPIGOT-924 ++ if (server.isMainThread()) entityplayer.playerTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) + // CraftBukkit end + + // Paper start - Remove from collideRule team if needed +diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java +index ca23ca14d8011fc8daa7e20f2eaa550a8ff92c53..158ea6d77698d62ba795aff6c061a80652e42e03 100644 +--- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java ++++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java +@@ -135,6 +135,7 @@ public abstract class IAsyncTaskHandler implements Mailbox asList(String... params) { + return Arrays.asList(params); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +index 449e99d1b673870ed6892f6ab2c715a2db35c35d..c7ed6e0f8a989cec97700df2b15198c9c481c549 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +@@ -12,12 +12,27 @@ public class ServerShutdownThread extends Thread { + @Override + public void run() { + try { ++ // Paper start - try to shutdown on main ++ server.safeShutdown(false, false); ++ for (int i = 1000; i > 0 && !server.hasStopped(); i -= 100) { ++ Thread.sleep(100); ++ } ++ if (server.hasStopped()) { ++ while (!server.hasFullyShutdown) Thread.sleep(1000); ++ return; ++ } ++ // Looks stalled, close async + org.spigotmc.AsyncCatcher.enabled = false; // Spigot + org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper ++ server.forceTicks = true; + server.close(); ++ while (!server.hasFullyShutdown) Thread.sleep(1000); ++ } catch (InterruptedException e) { ++ e.printStackTrace(); ++ // Paper end + } finally { + try { +- net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender ++ //net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Move into stop + } catch (Exception e) { + } + } +diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java +index b45d7e5c108c7a8541fcbc9ad92d1a79a94746a1..6a408dc9286a60c3ca7830f88171919fb0fe6363 100644 +--- a/src/main/java/org/spigotmc/RestartCommand.java ++++ b/src/main/java/org/spigotmc/RestartCommand.java +@@ -139,7 +139,7 @@ public class RestartCommand extends Command + // Paper end + + // Paper start - copied from above and modified to return if the hook registered +- private static boolean addShutdownHook(String restartScript) ++ public static boolean addShutdownHook(String restartScript) + { + String[] split = restartScript.split( " " ); + if ( split.length > 0 && new File( split[0] ).isFile() ) +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 58e50bf0fb0f309227e1f4c1f6bb11c01d8e08d3..c58de4de8d98c6b1e79d83cc7fcd46a7590ed2a0 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -13,6 +13,7 @@ import org.bukkit.Bukkit; + public class WatchdogThread extends Thread + { + ++ public static final boolean DISABLE_WATCHDOG = Boolean.getBoolean("disable.watchdog"); // Paper + private static WatchdogThread instance; + private long timeoutTime; + private boolean restart; +@@ -41,6 +42,7 @@ public class WatchdogThread extends Thread + { + if ( instance == null ) + { ++ if (timeoutTime <= 0) timeoutTime = 300; // Paper + instance = new WatchdogThread( timeoutTime * 1000L, restart ); + instance.start(); + } else +@@ -71,12 +73,13 @@ public class WatchdogThread extends Thread + // Paper start + Logger log = Bukkit.getServer().getLogger(); + long currentTime = monotonicMillis(); +- if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) ++ MinecraftServer server = MinecraftServer.getServer(); ++ if (lastTick != 0 && timeoutTime > 0 && hasStarted && (!server.isRunning() || (currentTime > lastTick + earlyWarningEvery && !DISABLE_WATCHDOG) )) + { +- boolean isLongTimeout = currentTime > lastTick + timeoutTime; ++ boolean isLongTimeout = currentTime > lastTick + timeoutTime || (!server.isRunning() && !server.hasStopped() && currentTime > lastTick + 1000); + // Don't spam early warning dumps + if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; +- if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... ++ if ( !isLongTimeout && server.hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... + lastEarlyWarning = currentTime; + if (isLongTimeout) { + // Paper end +@@ -118,7 +121,7 @@ public class WatchdogThread extends Thread + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper +- dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); ++ dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // + // Paper start - Only print full dump on long timeouts +@@ -139,9 +142,25 @@ public class WatchdogThread extends Thread + + if ( isLongTimeout ) + { +- if ( restart && !MinecraftServer.getServer().hasStopped() ) ++ if ( !server.hasStopped() ) + { +- RestartCommand.restart(); ++ AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us ++ AsyncCatcher.shuttingDown = true; ++ server.forceTicks = true; ++ if (restart) { ++ RestartCommand.addShutdownHook( SpigotConfig.restartScript ); ++ } ++ // try one last chance to safe shutdown on main incase it 'comes back' ++ server.abnormalExit = true; ++ server.safeShutdown(false, restart); ++ try { ++ Thread.sleep(1000); ++ } catch (InterruptedException e) { ++ e.printStackTrace(); ++ } ++ if (!server.hasStopped()) { ++ server.close(); ++ } + } + break; + } // Paper end +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 476f4a5cbe664ddd05474cb88553018bd334a5b8..8af159abd3d0cc94cf155fec5b384c42f69551bf 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -1,5 +1,5 @@ + +- ++ + + + diff --git a/patches/server-unmapped/0437-Optimize-Pathfinding.patch b/patches/server-unmapped/0437-Optimize-Pathfinding.patch new file mode 100644 index 0000000000..812fed5f72 --- /dev/null +++ b/patches/server-unmapped/0437-Optimize-Pathfinding.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 02:02:07 -0600 +Subject: [PATCH] Optimize Pathfinding + +Prevents pathfinding from spamming failures for things such as +arrow attacks. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +index 06d05b511d623d0247d44989bee85b383a8fb52f..e6ba9b7fbf08ae0dd083a1ebee8eb7ed8a937751 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +@@ -11,6 +11,7 @@ import net.minecraft.core.BlockPosition; + import net.minecraft.core.IPosition; + import net.minecraft.network.protocol.game.PacketDebug; + import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.util.MathHelper; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityInsentient; +@@ -32,7 +33,7 @@ public abstract class NavigationAbstract { + protected final EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER + protected final World b; + @Nullable +- protected PathEntity c; ++ protected PathEntity c; protected final PathEntity getCurrentPath() { return this.c; } // Paper - OBFHELPER + protected double d; + protected int e; + protected int f; +@@ -184,10 +185,30 @@ public abstract class NavigationAbstract { + return this.a(this.a(d0, d1, d2, 1), d3); + } + ++ // Paper start - optimise pathfinding ++ private int lastFailure = 0; ++ private int pathfindFailures = 0; ++ // Paper end ++ + public boolean a(Entity entity, double d0) { ++ // Paper start - Pathfinding optimizations ++ if (this.pathfindFailures > 10 && this.getCurrentPath() == null && MinecraftServer.currentTick < this.lastFailure + 40) { ++ return false; ++ } ++ // Paper end + PathEntity pathentity = this.a(entity, 1); + +- return pathentity != null && this.a(pathentity, d0); ++ // Paper start - Pathfinding optimizations ++ if (pathentity != null && this.a(pathentity, d0)) { ++ this.lastFailure = 0; ++ this.pathfindFailures = 0; ++ return true; ++ } else { ++ this.pathfindFailures++; ++ this.lastFailure = MinecraftServer.currentTick; ++ return false; ++ } ++ // Paper end + } + + public boolean setDestination(@Nullable PathEntity pathentity, double speed) { return a(pathentity, speed); } // Paper - OBFHELPER diff --git a/patches/server-unmapped/0438-Reduce-Either-Optional-allocation.patch b/patches/server-unmapped/0438-Reduce-Either-Optional-allocation.patch new file mode 100644 index 0000000000..0f4641263b --- /dev/null +++ b/patches/server-unmapped/0438-Reduce-Either-Optional-allocation.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 18:35:09 -0700 +Subject: [PATCH] Reduce Either Optional allocation + +In order to get chunk values, we shouldn't need to create +an optional each time. + +diff --git a/src/main/java/com/mojang/datafixers/util/Either.java b/src/main/java/com/mojang/datafixers/util/Either.java +index a90adac7bd7ebd423f480e9ae0f44cb9d521fa4f..3f65fe71024928e35111fc6719a290aab9a6859e 100644 +--- a/src/main/java/com/mojang/datafixers/util/Either.java ++++ b/src/main/java/com/mojang/datafixers/util/Either.java +@@ -22,7 +22,7 @@ public abstract class Either implements App, L> { + } + + private static final class Left extends Either { +- private final L value; ++ private final L value; private Optional valueOptional; // Paper - reduce the optional allocation... + + public Left(final L value) { + this.value = value; +@@ -51,7 +51,7 @@ public abstract class Either implements App, L> { + + @Override + public Optional left() { +- return Optional.of(value); ++ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... + } + + @Override +@@ -83,7 +83,7 @@ public abstract class Either implements App, L> { + } + + private static final class Right extends Either { +- private final R value; ++ private final R value; private Optional valueOptional; // Paper - reduce the optional allocation... + + public Right(final R value) { + this.value = value; +@@ -117,7 +117,7 @@ public abstract class Either implements App, L> { + + @Override + public Optional right() { +- return Optional.of(value); ++ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... + } + + @Override diff --git a/patches/server-unmapped/0439-Remove-streams-from-PairedQueue.patch b/patches/server-unmapped/0439-Remove-streams-from-PairedQueue.patch new file mode 100644 index 0000000000..f1a9a0128a --- /dev/null +++ b/patches/server-unmapped/0439-Remove-streams-from-PairedQueue.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 18:10:43 -0700 +Subject: [PATCH] Remove streams from PairedQueue + +We shouldn't be doing stream calls just to see if the queue is +empty. This creates loads of garbage thanks to how often it's called. + +diff --git a/src/main/java/net/minecraft/util/thread/PairedQueue.java b/src/main/java/net/minecraft/util/thread/PairedQueue.java +index 024b414aae32c8ad32bdf031361257fc74b80eb3..56c9efa78ceeac499182eb401e605a60dad12182 100644 +--- a/src/main/java/net/minecraft/util/thread/PairedQueue.java ++++ b/src/main/java/net/minecraft/util/thread/PairedQueue.java +@@ -20,32 +20,30 @@ public interface PairedQueue { + + public static final class a implements PairedQueue { + +- private final List> a; ++ private final List> a; private final List> getQueues() { return this.a; } // Paper - OBFHELPER + + public a(int i) { +- this.a = (List) IntStream.range(0, i).mapToObj((j) -> { +- return Queues.newConcurrentLinkedQueue(); +- }).collect(Collectors.toList()); ++ // Paper start - remove streams ++ this.a = new java.util.ArrayList<>(i); // queues ++ for (int j = 0; j < i; ++j) { ++ this.getQueues().add(Queues.newConcurrentLinkedQueue()); ++ } ++ // Paper end - remove streams + } + + @Nullable + @Override + public Runnable a() { +- Iterator iterator = this.a.iterator(); +- +- Runnable runnable; +- +- do { +- if (!iterator.hasNext()) { +- return null; ++ // Paper start - remove iterator creation ++ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { ++ Queue queue = this.getQueues().get(i); ++ Runnable ret = queue.poll(); ++ if (ret != null) { ++ return ret; + } +- +- Queue queue = (Queue) iterator.next(); +- +- runnable = (Runnable) queue.poll(); +- } while (runnable == null); +- +- return runnable; ++ } ++ return null; ++ // Paper end - remove iterator creation + } + + public boolean a(PairedQueue.b pairedqueue_b) { +@@ -57,7 +55,16 @@ public interface PairedQueue { + + @Override + public boolean b() { +- return this.a.stream().allMatch(Collection::isEmpty); ++ // Paper start - remove streams ++ // why are we doing streams every time we might want to execute a task? ++ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { ++ Queue queue = this.getQueues().get(i); ++ if (!queue.isEmpty()) { ++ return false; ++ } ++ } ++ return true; ++ // Paper end - remove streams + } + } + diff --git a/patches/server-unmapped/0440-Reduce-memory-footprint-of-NBTTagCompound.patch b/patches/server-unmapped/0440-Reduce-memory-footprint-of-NBTTagCompound.patch new file mode 100644 index 0000000000..a8f074ccde --- /dev/null +++ b/patches/server-unmapped/0440-Reduce-memory-footprint-of-NBTTagCompound.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 17:39:25 -0700 +Subject: [PATCH] Reduce memory footprint of NBTTagCompound + +Fastutil maps are going to have a lower memory footprint - which +is important because we clone chunk data after reading it for safety. +So, reduce the impact of the clone on GC. + +diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java +index d5508deff819309034554abc7b36aac40fa33503..77afbaad5b2cb8d912f5404fcbd3a0970490f4f3 100644 +--- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java ++++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java +@@ -26,6 +26,7 @@ import net.minecraft.ReportedException; + import net.minecraft.network.chat.ChatComponentText; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.network.chat.IChatMutableComponent; ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; // Paper + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +@@ -47,7 +48,7 @@ public class NBTTagCompound implements NBTBase { + if (i > 512) { + throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512"); + } else { +- HashMap hashmap = Maps.newHashMap(); ++ Object2ObjectOpenHashMap hashmap = new Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound + + byte b0; + +@@ -83,7 +84,7 @@ public class NBTTagCompound implements NBTBase { + } + + public NBTTagCompound() { +- this(Maps.newHashMap()); ++ this(new Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - reduce memory footprint of NBTTagCompound + } + + @Override +@@ -417,9 +418,17 @@ public class NBTTagCompound implements NBTBase { + + @Override + public NBTTagCompound clone() { +- Map map = Maps.newHashMap(Maps.transformValues(this.map, NBTBase::clone)); ++ // Paper start - reduce memory footprint of NBTTagCompound ++ Object2ObjectOpenHashMap ret = new Object2ObjectOpenHashMap<>(this.map.size(), 0.8f); + +- return new NBTTagCompound(map); ++ Iterator> iterator = (this.map instanceof Object2ObjectOpenHashMap) ? ((Object2ObjectOpenHashMap)this.map).object2ObjectEntrySet().fastIterator() : this.map.entrySet().iterator(); ++ while (iterator.hasNext()) { ++ Map.Entry entry = iterator.next(); ++ ret.put(entry.getKey(), entry.getValue().clone()); ++ } ++ ++ return new NBTTagCompound(ret); ++ // Paper end - reduce memory footprint of NBTTagCompound + } + + public boolean equals(Object object) { diff --git a/patches/server-unmapped/0441-Prevent-opening-inventories-when-frozen.patch b/patches/server-unmapped/0441-Prevent-opening-inventories-when-frozen.patch new file mode 100644 index 0000000000..b2d315bd4f --- /dev/null +++ b/patches/server-unmapped/0441-Prevent-opening-inventories-when-frozen.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Mon, 13 Apr 2020 07:31:44 +0100 +Subject: [PATCH] Prevent opening inventories when frozen + + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 79003f43c4f15a7e5dd51587bc8c2f477bedb1b2..5382dfbad7a33670268d5d713cf3bdd425bbe885 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -560,7 +560,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + containerUpdateDelay = world.paperConfig.containerUpdateTickRate; + } + // Paper end +- if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { ++ if (!this.world.isClientSide && this.activeContainer != this.defaultContainer && (isFrozen() || !this.activeContainer.canUse(this))) { // Paper - auto close while frozen + this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.activeContainer = this.defaultContainer; + } +@@ -1407,7 +1407,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } else { + // CraftBukkit start + this.activeContainer = container; +- this.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, container.getType(), container.getTitle())); ++ if (!isFrozen()) this.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, container.getType(), container.getTitle())); // Paper + // CraftBukkit end + container.addSlotListener(this); + return OptionalInt.of(this.containerCounter); +@@ -2209,7 +2209,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + + @Override +- protected boolean isFrozen() { ++ public boolean isFrozen() { // Paper - protected > public + return super.isFrozen() || (this.playerConnection != null && this.playerConnection.isDisconnected()); // Paper + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index 3b3e6076f2565e02fa6f13e369094f8b6cac5382..3bfb93890259210afd2f5e226cef100d26a11628 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -324,7 +324,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper + + //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment +- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper ++ if (!player.isFrozen()) player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + getHandle().activeContainer = container; + getHandle().activeContainer.addSlotListener(player); + } +@@ -398,7 +398,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper + if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper + //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment +- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper ++ if (!player.isFrozen()) player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + player.activeContainer = container; + player.activeContainer.addSlotListener(player); + } diff --git a/patches/server-unmapped/0442-Optimise-ArraySetSorted-removeIf.patch b/patches/server-unmapped/0442-Optimise-ArraySetSorted-removeIf.patch new file mode 100644 index 0000000000..1ff7b9b2f9 --- /dev/null +++ b/patches/server-unmapped/0442-Optimise-ArraySetSorted-removeIf.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Apr 2020 18:23:28 -0700 +Subject: [PATCH] Optimise ArraySetSorted#removeIf + +Remove iterator allocation and ensure the call is always O(n) + +diff --git a/src/main/java/net/minecraft/util/ArraySetSorted.java b/src/main/java/net/minecraft/util/ArraySetSorted.java +index 427daa94322f47b4eaf881d85a01fed239db549a..936a90272579f78832eff93f2a81d673feb669c1 100644 +--- a/src/main/java/net/minecraft/util/ArraySetSorted.java ++++ b/src/main/java/net/minecraft/util/ArraySetSorted.java +@@ -10,8 +10,8 @@ import java.util.NoSuchElementException; + public class ArraySetSorted extends AbstractSet { + + private final Comparator a; +- private T[] b; +- private int c; ++ private T[] b; private final T[] getBackingArray() { return this.b; } // Paper - OBFHELPER ++ private int c; private final int getSize() { return this.c; } private final void setSize(int value) { this.c = value; } // Paper - OBFHELPER + + private ArraySetSorted(int i, Comparator comparator) { + this.a = comparator; +@@ -22,6 +22,42 @@ public class ArraySetSorted extends AbstractSet { + } + } + ++ // Paper start - optimise removeIf ++ @Override ++ public boolean removeIf(java.util.function.Predicate filter) { ++ // prev. impl used an iterator, which could be n^2 and creates garbage ++ int i = 0, len = this.getSize(); ++ T[] backingArray = this.getBackingArray(); ++ ++ for (;;) { ++ if (i >= len) { ++ return false; ++ } ++ if (!filter.test(backingArray[i])) { ++ ++i; ++ continue; ++ } ++ break; ++ } ++ ++ // we only want to write back to backingArray if we really need to ++ ++ int lastIndex = i; // this is where new elements are shifted to ++ ++ for (; i < len; ++i) { ++ T curr = backingArray[i]; ++ if (!filter.test(curr)) { // if test throws we're screwed ++ backingArray[lastIndex++] = curr; ++ } ++ } ++ ++ // cleanup end ++ Arrays.fill(backingArray, lastIndex, len, null); ++ this.setSize(lastIndex); ++ return true; ++ } ++ // Paper end - optimise removeIf ++ + public static > ArraySetSorted a(int i) { + return new ArraySetSorted<>(i, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix + } diff --git a/patches/server-unmapped/0443-Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server-unmapped/0443-Don-t-run-entity-collision-code-if-not-needed.patch new file mode 100644 index 0000000000..5e3b27cf93 --- /dev/null +++ b/patches/server-unmapped/0443-Don-t-run-entity-collision-code-if-not-needed.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Apr 2020 17:56:07 -0700 +Subject: [PATCH] Don't run entity collision code if not needed + +Will not run if max entity craming is disabled and +the max collisions per entity is less than or equal to 0 + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 571e6bced3cfaacbd40378e67b01cdfda550feb7..40fb7e96af7bbbe6c5586fa4d2a629b5a8f7b07a 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -2944,10 +2944,16 @@ public abstract class EntityLiving extends Entity { + protected void doTick() {} + + protected void collideNearby() { ++ // Paper - start don't run getEntities if we're not going to use its result ++ int i = this.world.getGameRules().getInt(GameRules.MAX_ENTITY_CRAMMING); ++ if (i <= 0 && world.paperConfig.maxCollisionsPerEntity <= 0) { ++ return; ++ } ++ // Paper - end don't run getEntities if we're not going to use its result + List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.a(this)); + + if (!list.isEmpty()) { +- int i = this.world.getGameRules().getInt(GameRules.MAX_ENTITY_CRAMMING); ++ // Paper - move up + int j; + + if (i > 0 && list.size() > i - 1 && this.random.nextInt(4) == 0) { diff --git a/patches/server-unmapped/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch b/patches/server-unmapped/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch new file mode 100644 index 0000000000..f9bae9ab71 --- /dev/null +++ b/patches/server-unmapped/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Thu, 16 Apr 2020 16:13:59 -0700 +Subject: [PATCH] Optimize ChunkProviderServer's chunk level checking helper + methods + +These can be hot functions (i.e entity ticking and block ticking), +so inline where possible, and avoid the abstraction of the +Either class. + +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 48d0c37a1d7df9b7ac8077e1e82420566dc42718..d8355caf6f86e0bb8c16ad0b58b81d7926bc7bff 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -643,21 +643,29 @@ public class ChunkProviderServer extends IChunkProvider { + + public final boolean isInEntityTickingChunk(Entity entity) { return this.a(entity); } // Paper - OBFHELPER + @Override public boolean a(Entity entity) { +- long i = ChunkCoordIntPair.pair(MathHelper.floor(entity.locX()) >> 4, MathHelper.floor(entity.locZ()) >> 4); +- +- return this.a(i, (Function>>) PlayerChunk::b); // CraftBukkit - decompile error ++ // Paper start - optimize is ticking ready type functions ++ // entity ticking ++ PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(entity)); ++ return playerChunk != null && playerChunk.isEntityTickingReady(); ++ // Paper end - optimize is ticking ready type functions + } + + public final boolean isEntityTickingChunk(ChunkCoordIntPair chunkcoordintpair) { return this.a(chunkcoordintpair); } // Paper - OBFHELPER + @Override public boolean a(ChunkCoordIntPair chunkcoordintpair) { +- return this.a(chunkcoordintpair.pair(), (Function>>) PlayerChunk::b); // CraftBukkit - decompile error ++ // Paper start - optimize is ticking ready type functions ++ // is entity ticking ready ++ PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(chunkcoordintpair)); ++ return playerChunk != null && playerChunk.isEntityTickingReady(); ++ // Paper end - optimize is ticking ready type functions + } + + @Override + public boolean a(BlockPosition blockposition) { +- long i = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4); +- +- return this.a(i, (Function>>) PlayerChunk::a); // CraftBukkit - decompile error ++ // Paper start - optimize is ticking ready type functions ++ // is ticking ready ++ PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(blockposition)); ++ return playerChunk != null && playerChunk.isTickingReady(); ++ // Paper end - optimize is ticking ready type functions + } + + private boolean a(long i, Function>> function) { diff --git a/patches/server-unmapped/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch b/patches/server-unmapped/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch new file mode 100644 index 0000000000..ed7ce57a14 --- /dev/null +++ b/patches/server-unmapped/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Thu, 16 Apr 2020 20:07:29 -0500 +Subject: [PATCH] Restrict vanilla teleport command to valid locations + +Fixes GH-3165, GH-3575 + +diff --git a/src/main/java/net/minecraft/server/commands/CommandTeleport.java b/src/main/java/net/minecraft/server/commands/CommandTeleport.java +index b59763643def065cd998fa3005523c37973613fd..dcc92b0c9a7a0214a3e803d714c5e7078c17a039 100644 +--- a/src/main/java/net/minecraft/server/commands/CommandTeleport.java ++++ b/src/main/java/net/minecraft/server/commands/CommandTeleport.java +@@ -142,6 +142,12 @@ public class CommandTeleport { + + private static void a(CommandListenerWrapper commandlistenerwrapper, Entity entity, WorldServer worldserver, double d0, double d1, double d2, Set set, float f, float f1, @Nullable CommandTeleport.a commandteleport_a) throws CommandSyntaxException { + BlockPosition blockposition = new BlockPosition(d0, d1, d2); ++ // Paper start - Don't allow teleport command to invalid locations ++ if (d0 <= -30000000 || d2 <= -30000000 || d0 > 30000000 || d2 > 30000000 || d1 > 30000000 || d1 <= -30000000) { // Copy/pasta from BaseBlockPosition#isValidLocation ++ org.bukkit.Bukkit.getLogger().warning("Refused to teleport " + entity.getName() + " to " + d0 + ", " + d1 + ", " + d2); ++ return; ++ } ++ // Paper end + + if (!World.l(blockposition)) { + throw CommandTeleport.a.create(); diff --git a/patches/server-unmapped/0446-Implement-Player-Client-Options-API.patch b/patches/server-unmapped/0446-Implement-Player-Client-Options-API.patch new file mode 100644 index 0000000000..92a17b9c3a --- /dev/null +++ b/patches/server-unmapped/0446-Implement-Player-Client-Options-API.patch @@ -0,0 +1,188 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Mon, 20 Jan 2020 21:38:15 +0100 +Subject: [PATCH] Implement Player Client Options API + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperSkinParts.java b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabba57885e1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java +@@ -0,0 +1,74 @@ ++package com.destroystokyo.paper; ++ ++import com.google.common.base.Objects; ++ ++import java.util.StringJoiner; ++ ++public class PaperSkinParts implements SkinParts { ++ ++ private final int raw; ++ ++ public PaperSkinParts(int raw) { ++ this.raw = raw; ++ } ++ ++ public boolean hasCapeEnabled() { ++ return (raw & 1) == 1; ++ } ++ ++ public boolean hasJacketEnabled() { ++ return (raw >> 1 & 1) == 1; ++ } ++ ++ public boolean hasLeftSleeveEnabled() { ++ return (raw >> 2 & 1) == 1; ++ } ++ ++ public boolean hasRightSleeveEnabled() { ++ return (raw >> 3 & 1) == 1; ++ } ++ ++ public boolean hasLeftPantsEnabled() { ++ return (raw >> 4 & 1) == 1; ++ } ++ ++ public boolean hasRightPantsEnabled() { ++ return (raw >> 5 & 1) == 1; ++ } ++ ++ public boolean hasHatsEnabled() { ++ return (raw >> 6 & 1) == 1; ++ } ++ ++ @Override ++ public int getRaw() { ++ return raw; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ PaperSkinParts that = (PaperSkinParts) o; ++ return raw == that.raw; ++ } ++ ++ @Override ++ public int hashCode() { ++ return Objects.hashCode(raw); ++ } ++ ++ @Override ++ public String toString() { ++ return new StringJoiner(", ", PaperSkinParts.class.getSimpleName() + "[", "]") ++ .add("raw=" + raw) ++ .add("cape=" + hasCapeEnabled()) ++ .add("jacket=" + hasJacketEnabled()) ++ .add("leftSleeve=" + hasLeftSleeveEnabled()) ++ .add("rightSleeve=" + hasRightSleeveEnabled()) ++ .add("leftPants=" + hasLeftPantsEnabled()) ++ .add("rightPants=" + hasRightPantsEnabled()) ++ .add("hats=" + hasHatsEnabled()) ++ .toString(); ++ } ++} +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java +index 90842b27f64afcdd8eb7d0e52df8cfcb418b5b5a..f47cd43f96f61475bd1d5da11bdbc7c5e5f7e1bc 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java +@@ -41,14 +41,17 @@ public class PacketPlayInSettings implements Packet { + packetlistenerplayin.a(this); + } + ++ public EnumChatVisibility getChatVisibility() { return d(); } // Paper - OBFHELPER + public EnumChatVisibility d() { + return this.c; + } + ++ public boolean hasChatColorsEnabled() { return e(); } // Paper - OBFHELPER + public boolean e() { + return this.d; + } + ++ public int getSkinParts() { return f(); } // Paper - OBFHELPER + public int f() { + return this.e; + } +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 5382dfbad7a33670268d5d713cf3bdd425bbe885..ff0913941a888ab529d7a4dd1b160fe9659b25cb 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -2,6 +2,7 @@ package net.minecraft.server.level; + + import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent; + import com.google.common.collect.Lists; ++import com.destroystokyo.paper.event.player.PlayerClientOptionsChangeEvent; // Paper + import com.mojang.authlib.GameProfile; + import com.mojang.datafixers.util.Either; + import com.mojang.serialization.DataResult; +@@ -191,7 +192,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public int lastSentExp = -99999999; + public int invulnerableTicks = 60; + private EnumChatVisibility bY; +- private boolean bZ = true; ++ private boolean bZ = true; public boolean hasChatColorsEnabled() { return this.bZ; } // Paper - OBFHELPER + private long ca = SystemUtils.getMonotonicMillis(); + private Entity spectatedEntity; + public boolean worldChangeInvuln; +@@ -1810,6 +1811,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null + public java.util.Locale adventure$locale = java.util.Locale.US; // Paper + public void a(PacketPlayInSettings packetplayinsettings) { ++ new PlayerClientOptionsChangeEvent(getBukkitEntity(), packetplayinsettings.locale, packetplayinsettings.viewDistance, com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(packetplayinsettings.getChatVisibility().name()), packetplayinsettings.hasChatColorsEnabled(), new com.destroystokyo.paper.PaperSkinParts(packetplayinsettings.getSkinParts()), packetplayinsettings.getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT).callEvent(); // Paper - settings event + // CraftBukkit start + if (getMainHand() != packetplayinsettings.getMainHand()) { + PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT); +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 8981dfacd10cae9de052e1b36ce5181cd0e6752d..202fa94d5dc55b549475ae0309bbcfca8f1b2c96 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -133,7 +133,7 @@ public abstract class EntityHuman extends EntityLiving { + private static final Map b = ImmutableMap.builder().put(EntityPose.STANDING, EntityHuman.bh).put(EntityPose.SLEEPING, EntityHuman.ah).put(EntityPose.FALL_FLYING, EntitySize.b(0.6F, 0.6F)).put(EntityPose.SWIMMING, EntitySize.b(0.6F, 0.6F)).put(EntityPose.SPIN_ATTACK, EntitySize.b(0.6F, 0.6F)).put(EntityPose.CROUCHING, EntitySize.b(0.6F, 1.5F)).put(EntityPose.DYING, EntitySize.c(0.2F, 0.2F)).build(); + private static final DataWatcherObject c = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.c); + private static final DataWatcherObject d = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.b); +- protected static final DataWatcherObject bi = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); ++ protected static final DataWatcherObject bi = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); public static DataWatcherObject getSkinPartsWatcher() { return bi; } // Paper - OBFHELPER + protected static final DataWatcherObject bj = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); + protected static final DataWatcherObject bk = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.p); + protected static final DataWatcherObject bl = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.p); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index dc8545241ed62f6b654b2559e025c3b34c00575f..935b5668a81db4d19a08b09c61519114532a23d9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1,5 +1,8 @@ + package org.bukkit.craftbukkit.entity; + ++import com.destroystokyo.paper.ClientOption.ChatVisibility; ++import com.destroystokyo.paper.PaperSkinParts; ++import com.destroystokyo.paper.ClientOption; + import com.destroystokyo.paper.Title; + import com.google.common.base.Preconditions; + import com.google.common.collect.ImmutableSet; +@@ -2253,6 +2256,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public void setViewDistance(int viewDistance) { + throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO + } ++ ++ @Override ++ public T getClientOption(ClientOption type) { ++ if(ClientOption.SKIN_PARTS.equals(type)) { ++ return type.getType().cast(new PaperSkinParts(getHandle().getDataWatcher().get(EntityHuman.getSkinPartsWatcher()))); ++ } else if(ClientOption.CHAT_COLORS_ENABLED.equals(type)) { ++ return type.getType().cast(getHandle().hasChatColorsEnabled()); ++ } else if(ClientOption.CHAT_VISIBILITY.equals(type)) { ++ return type.getType().cast(getHandle().getChatFlags() == null ? ChatVisibility.UNKNOWN : ChatVisibility.valueOf(getHandle().getChatFlags().name())); ++ } else if(ClientOption.LOCALE.equals(type)) { ++ return type.getType().cast(getLocale()); ++ } else if(ClientOption.MAIN_HAND.equals(type)) { ++ return type.getType().cast(getMainHand()); ++ } else if(ClientOption.VIEW_DISTANCE.equals(type)) { ++ return type.getType().cast(getClientViewDistance()); ++ } ++ throw new RuntimeException("Unknown settings type"); ++ } + // Paper end + + // Spigot start diff --git a/patches/server-unmapped/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server-unmapped/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch new file mode 100644 index 0000000000..54424991d0 --- /dev/null +++ b/patches/server-unmapped/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 18 Apr 2020 04:36:11 -0400 +Subject: [PATCH] Fix Chunk Post Processing deadlock risk + +See: https://gist.github.com/aikar/dd22bbd2a3d78a2fd3d92e95e9f28dc6 + +as part of post processing a chunk, we can call ChunkConverter. + +ChunkConverter then kicks off major physics updates, and when blocks +that have connections across chunk boundries occur, a recursive risk +can occur where A updates a block that triggers a physics request. + +That physics request may trigger a chunk request, that then enqueues +a task into the Mailbox ChunkTaskQueueSorter. + +If anything requests that same chunk that is in the middle of conversion, +it's mailbox queue is going to be held up, so the subsequent chunk request +will be unable to proceed. + +We delay post processing of Chunk.A() 1 "pass" by re stuffing it back into +the executor so that the mailbox ChunkQueue is now considered empty. + +This successfully fixed a reoccurring and highly reproduceable crash +for heightmaps. + +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index d8355caf6f86e0bb8c16ad0b58b81d7926bc7bff..cb098defa7b93864294befa9b9a427804461188b 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -1021,6 +1021,7 @@ public class ChunkProviderServer extends IChunkProvider { + return super.executeNext() || execChunkTask; // Paper + } + } finally { ++ playerChunkMap.chunkLoadConversionCallbackExecutor.run(); // Paper - Add chunk load conversion callback executor to prevent deadlock due to recursion in the chunk task queue sorter + playerChunkMap.callbackExecutor.run(); + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index b00c5a7eaf456e6d6ce250ee790ce33dfa9bb496..6279846a92489b5dade21ad55a1bec1157073e27 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -183,6 +183,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + }; + // CraftBukkit end + ++ final CallbackExecutor chunkLoadConversionCallbackExecutor = new CallbackExecutor(); // Paper ++ + // Paper start - distance maps + private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); + +@@ -1056,7 +1058,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return Either.left(chunk); + }); + }, (runnable) -> { +- this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); ++ this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, () -> PlayerChunkMap.this.chunkLoadConversionCallbackExecutor.execute(runnable))); // Paper - delay running Chunk post processing until outside of the sorter to prevent a deadlock scenario when post processing causes another chunk request. + }); + + completablefuture1.thenAcceptAsync((either) -> { diff --git a/patches/server-unmapped/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/patches/server-unmapped/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch new file mode 100644 index 0000000000..83e1af8a9c --- /dev/null +++ b/patches/server-unmapped/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 18 Apr 2020 15:59:41 -0400 +Subject: [PATCH] Don't crash if player is attempted to be removed from + untracked chunk. + +I suspect it deals with teleporting as it uses players current x/y/z + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +index 961257ebc28a8b4753faf3c2d5b6abaea4ffc0dd..60fcea78bf617559114b1ca1c0bf2d4cd9075a8c 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +@@ -245,8 +245,8 @@ public abstract class ChunkMapDistance { + ObjectSet objectset = (ObjectSet) this.c.get(i); + if (objectset == null) return; // CraftBukkit - SPIGOT-6208 + +- objectset.remove(entityplayer); +- if (objectset.isEmpty()) { ++ if (objectset != null) objectset.remove(entityplayer); // Paper - some state corruption happens here, don't crash, clean up gracefully. ++ if (objectset == null || objectset.isEmpty()) { // Paper + this.c.remove(i); + this.f.update(i, Integer.MAX_VALUE, false); + this.g.update(i, Integer.MAX_VALUE, false); diff --git a/patches/server-unmapped/0449-Broadcast-join-message-to-console.patch b/patches/server-unmapped/0449-Broadcast-join-message-to-console.patch new file mode 100644 index 0000000000..6ffc693706 --- /dev/null +++ b/patches/server-unmapped/0449-Broadcast-join-message-to-console.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AvrooVulcan +Date: Fri, 17 Apr 2020 00:15:23 +0100 +Subject: [PATCH] Broadcast join message to console + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 9eec320ca5a63a313138dc84367e93038b457c0d..7d336c23a57c06c3744ae5b187960da798dd07c8 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -288,7 +288,9 @@ public abstract class PlayerList { + + if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure + joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure +- server.getPlayerList().sendAll(new PacketPlayOutChat(joinMessage, ChatMessageType.SYSTEM, SystemUtils.b)); // Paper - Adventure ++ // Paper start - Removed sendAll for loop and broadcasted to console also ++ server.getPlayerList().sendMessage(joinMessage); // Paper - Adventure ++ // Paper end + } + // CraftBukkit end + diff --git a/patches/server-unmapped/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/patches/server-unmapped/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch new file mode 100644 index 0000000000..d064811c32 --- /dev/null +++ b/patches/server-unmapped/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch @@ -0,0 +1,111 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 19 Apr 2020 00:05:46 -0400 +Subject: [PATCH] Fix Longstanding Broken behavior of PlayerJoinEvent + +For years, plugin developers have had to delay many things they do +inside of the PlayerJoinEvent by 1 tick to make it actually work. + +This all boiled down to 1 reason why: The event fired before the +player was fully ready and joined to the world! + +Additionally, if that player logged out on a vehicle, the event +fired before the vehicle was even loaded, so that plugins had no +access to the vehicle during this event either. + +This change finally fixes this issue, fully preparing the player +into the world as a fully ready entity, vehicle included. + +There should be no plugins that break because of this change, but might +improve consistency with other plugins instead. + +For example, if 2 plugins listens to this event, and the first one +teleported the player in the event, then the 2nd plugin actually +would be getting a valid player! + +This was very non deterministic. This change will ensure every plugin +receives a deterministic result, and should no longer require 1 tick +delays anymore. + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index ff0913941a888ab529d7a4dd1b160fe9659b25cb..505cb0eb74d45906132e78c5cf8741dc5fd4eaf0 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -240,6 +240,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public double maxHealthCache; + public boolean joining = true; + public boolean sentListPacket = false; ++ public boolean supressTrackerForLogin = false; // Paper + public Integer clientViewDistance; + // CraftBukkit end + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 6279846a92489b5dade21ad55a1bec1157073e27..86cb1f33cd5269ff271129ceedd3a3a8532fa6eb 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -1586,7 +1586,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + }); + } + +- protected void addEntity(Entity entity) { ++ public void addEntity(Entity entity) { // Paper - protected -> public + org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot + // Paper start - ignore and warn about illegal addEntity calls instead of crashing server + if (!entity.valid || entity.world != this.world || this.trackedEntities.containsKey(entity.getId())) { +@@ -1595,6 +1595,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + .printStackTrace(); + return; + } ++ if (entity instanceof EntityPlayer && ((EntityPlayer) entity).supressTrackerForLogin) return; // Delay adding to tracker until after list packets + // Paper end + if (!(entity instanceof EntityComplexPart)) { + EntityTypes entitytypes = entity.getEntityType(); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7d336c23a57c06c3744ae5b187960da798dd07c8..66c1a9ca392b29fe2191577d32c70b214fa7293d 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -276,6 +276,12 @@ public abstract class PlayerList { + this.j.put(entityplayer.getUniqueID(), entityplayer); + // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below + ++ // Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks ++ entityplayer.supressTrackerForLogin = true; ++ worldserver1.addPlayerJoin(entityplayer); ++ this.server.getBossBattleCustomData().a(entityplayer); // see commented out section below worldserver.addPlayerJoin(entityplayer); ++ mountSavedVehicle(entityplayer, worldserver1, nbttagcompound); ++ // Paper end + // CraftBukkit start + PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + cserver.getPluginManager().callEvent(playerJoinEvent); +@@ -311,6 +317,8 @@ public abstract class PlayerList { + entityplayer.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[] { entityplayer1})); + } + entityplayer.sentListPacket = true; ++ entityplayer.supressTrackerForLogin = false; // Paper ++ ((WorldServer)entityplayer.world).getChunkProvider().playerChunkMap.addEntity(entityplayer); // Paper - track entity now + // CraftBukkit end + + entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityMetadata(entityplayer.getId(), entityplayer.getDataWatcher(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn +@@ -336,6 +344,11 @@ public abstract class PlayerList { + playerconnection.sendPacket(new PacketPlayOutEntityEffect(entityplayer.getId(), mobeffect)); + } + ++ // Paper start - move vehicle into method so it can be called above - short circuit around that code ++ onPlayerJoinFinish(entityplayer, worldserver1, s1); ++ } ++ private void mountSavedVehicle(EntityPlayer entityplayer, WorldServer worldserver1, NBTTagCompound nbttagcompound) { ++ // Paper end + if (nbttagcompound != null && nbttagcompound.hasKeyOfType("RootVehicle", 10)) { + NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); + // CraftBukkit start +@@ -384,6 +397,10 @@ public abstract class PlayerList { + } + } + ++ // Paper start ++ } ++ public void onPlayerJoinFinish(EntityPlayer entityplayer, WorldServer worldserver1, String s1) { ++ // Paper end + entityplayer.syncInventory(); + // Paper start - Add to collideRule team if needed + final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); diff --git a/patches/server-unmapped/0451-Load-Chunks-for-Login-Asynchronously.patch b/patches/server-unmapped/0451-Load-Chunks-for-Login-Asynchronously.patch new file mode 100644 index 0000000000..8a2ef5272c --- /dev/null +++ b/patches/server-unmapped/0451-Load-Chunks-for-Login-Asynchronously.patch @@ -0,0 +1,306 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 19 Apr 2020 04:28:29 -0400 +Subject: [PATCH] Load Chunks for Login Asynchronously + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index cb098defa7b93864294befa9b9a427804461188b..fc7140e0eb11e4bec99e453647fce200bca0ed7f 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -629,7 +629,7 @@ public class ChunkProviderServer extends IChunkProvider { + return this.serverThreadQueue.executeNext(); + } + +- private boolean tickDistanceManager() { ++ public boolean tickDistanceManager() { // Paper - private -> public + boolean flag = this.chunkMapDistance.a(this.playerChunkMap); + boolean flag1 = this.playerChunkMap.b(); + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 505cb0eb74d45906132e78c5cf8741dc5fd4eaf0..39fb3a1445338c3ac1642b8e518eb8d1031f9a5c 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -31,6 +31,7 @@ import net.minecraft.core.NonNullList; + import net.minecraft.core.SectionPosition; + import net.minecraft.nbt.DynamicOpsNBT; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.network.NetworkManager; + import net.minecraft.network.chat.ChatComponentText; + import net.minecraft.network.chat.ChatHoverable; + import net.minecraft.network.chat.ChatMessage; +@@ -175,6 +176,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + private static final Logger LOGGER = LogManager.getLogger(); + public PlayerConnection playerConnection; ++ public NetworkManager networkManager; // Paper + public final MinecraftServer server; + public final PlayerInteractManager playerInteractManager; + public final Deque removeQueue = new ArrayDeque<>(); // Paper +@@ -241,6 +243,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public boolean joining = true; + public boolean sentListPacket = false; + public boolean supressTrackerForLogin = false; // Paper ++ public boolean didPlayerJoinEvent = false; // Paper + public Integer clientViewDistance; + // CraftBukkit end + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 86cb1f33cd5269ff271129ceedd3a3a8532fa6eb..6e4a47581843be42b77034fec16b1d531a5b5759 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -147,7 +147,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + private final Mailbox> mailboxWorldGen; + private final Mailbox> mailboxMain; + public final WorldLoadListener worldLoadListener; +- public final PlayerChunkMap.a chunkDistanceManager; ++ public final PlayerChunkMap.a chunkDistanceManager; public final ChunkMapDistance getChunkDistanceManager() { return this.chunkDistanceManager; } // Paper - OBFHELPER + private final AtomicInteger u; + public final DefinedStructureManager definedStructureManager; // Paper - private -> public + private final File w; +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index 218dc900e125a11548485887b1918742072c7a77..2c932d36f982e7f8713aabff9a6c631055810366 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -21,6 +21,7 @@ public class TicketType { + public static final TicketType FORCED = a("forced", Comparator.comparingLong(ChunkCoordIntPair::pair)); + public static final TicketType LIGHT = a("light", Comparator.comparingLong(ChunkCoordIntPair::pair)); + public static final TicketType PORTAL = a("portal", BaseBlockPosition::compareTo, 300); ++ public static final TicketType LOGIN = a("login", Long::compareTo, 100); // Paper + public static final TicketType POST_TELEPORT = a("post_teleport", Integer::compareTo, 5); + public static final TicketType UNKNOWN = a("unknown", Comparator.comparingLong(ChunkCoordIntPair::pair), 1); + public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index 2e995103fba15c21dbe89321896c7df03ae5e67b..ef2aa000932c222e358789fcd2629dd8a46cfe80 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -88,7 +88,7 @@ public class LoginListener implements PacketLoginInListener { + } + // Paper end + } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { +- EntityPlayer entityplayer = this.server.getPlayerList().getPlayer(this.i.getId()); ++ EntityPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.i.getId()); // Paper + + if (entityplayer == null) { + this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT; +@@ -188,7 +188,7 @@ public class LoginListener implements PacketLoginInListener { + } + + this.networkManager.sendPacket(new PacketLoginOutSuccess(this.i)); +- EntityPlayer entityplayer = this.server.getPlayerList().getPlayer(this.i.getId()); ++ EntityPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.i.getId()); // Paper + + if (entityplayer != null) { + this.g = LoginListener.EnumProtocolState.DELAY_ACCEPT; +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 8a8f75acdd55e00ac2e7b5c621d1f522208df2c2..7c1d25feab71c325ce2379afa6c61732eebd74f9 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -222,6 +222,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + private static final Logger LOGGER = LogManager.getLogger(); + public final NetworkManager networkManager; + private final MinecraftServer minecraftServer; ++ public Runnable playerJoinReady; // Paper + public EntityPlayer player; + private int e; + private long lastKeepAlive = SystemUtils.getMonotonicMillis(); private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER +@@ -300,6 +301,15 @@ public class PlayerConnection implements PacketListenerPlayIn { + // CraftBukkit end + + public void tick() { ++ // Paper start - login async ++ Runnable playerJoinReady = this.playerJoinReady; ++ if (playerJoinReady != null) { ++ this.playerJoinReady = null; ++ playerJoinReady.run(); ++ } ++ // Don't tick if not valid (dead), otherwise we load chunks below ++ if (this.player.valid) { ++ // Paper end + this.syncPosition(); + this.player.lastX = this.player.locX(); + this.player.lastY = this.player.locY(); +@@ -341,7 +351,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + this.r = null; + this.D = false; + this.E = 0; +- } ++ }} // Paper - end if (valid) + + this.minecraftServer.getMethodProfiler().enter("keepAlive"); + // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 66c1a9ca392b29fe2191577d32c70b214fa7293d..c7e78d0626fa0dd18021c1a0827a10c08ab10b4a 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -41,6 +41,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutEntityStatus; + import net.minecraft.network.protocol.game.PacketPlayOutExperience; + import net.minecraft.network.protocol.game.PacketPlayOutGameStateChange; + import net.minecraft.network.protocol.game.PacketPlayOutHeldItemSlot; ++import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; + import net.minecraft.network.protocol.game.PacketPlayOutLogin; + import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; + import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo; +@@ -60,6 +61,8 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.server.ScoreboardServer; + import net.minecraft.server.level.DemoPlayerInteractManager; + import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.PlayerChunk; ++import net.minecraft.server.level.PlayerChunkMap; + import net.minecraft.server.level.PlayerInteractManager; + import net.minecraft.server.level.TicketType; + import net.minecraft.server.level.WorldServer; +@@ -128,11 +131,12 @@ public abstract class PlayerList { + private static final SimpleDateFormat g = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); + private final MinecraftServer server; + public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety +- private final Map j = Maps.newHashMap(); ++ private final Map j = Maps.newHashMap();Map getUUIDMap() { return j; } // Paper - OBFHELPER + private final GameProfileBanList k; + private final IpBanList l; + private final OpList operators; + private final WhiteList whitelist; ++ private final Map pendingPlayers = Maps.newHashMap(); // Paper + // CraftBukkit start + // private final Map o; + // private final Map p; +@@ -171,6 +175,11 @@ public abstract class PlayerList { + } + + public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { ++ EntityPlayer prev = pendingPlayers.put(entityplayer.getUniqueID(), entityplayer);// Paper ++ if (prev != null) { ++ disconnectPendingPlayer(prev); ++ } ++ entityplayer.networkManager = networkmanager; // Paper + entityplayer.loginTime = System.currentTimeMillis(); // Paper + GameProfile gameprofile = entityplayer.getProfile(); + UserCache usercache = this.server.getUserCache(); +@@ -184,7 +193,7 @@ public abstract class PlayerList { + if (nbttagcompound != null && nbttagcompound.hasKey("bukkit")) { + NBTTagCompound bukkit = nbttagcompound.getCompound("bukkit"); + s = bukkit.hasKeyOfType("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; +- } ++ }String lastKnownName = s; // Paper + // CraftBukkit end + + if (nbttagcompound != null) { +@@ -259,6 +268,51 @@ public abstract class PlayerList { + entityplayer.getRecipeBook().a(entityplayer); + this.sendScoreboard(worldserver1.getScoreboard(), entityplayer); + this.server.invalidatePingSample(); ++ // Paper start - async load spawn in chunk ++ WorldServer finalWorldserver = worldserver1; ++ int chunkX = loc.getBlockX() >> 4; ++ int chunkZ = loc.getBlockZ() >> 4; ++ final ChunkCoordIntPair pos = new ChunkCoordIntPair(chunkX, chunkZ); ++ PlayerChunkMap playerChunkMap = worldserver1.getChunkProvider().playerChunkMap; ++ playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.pair()); ++ worldserver1.getChunkProvider().tickDistanceManager(); ++ worldserver1.getChunkProvider().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { ++ PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pos.pair()); ++ if (updatingChunk != null) { ++ return updatingChunk.getEntityTickingFuture(); ++ } else { ++ return java.util.concurrent.CompletableFuture.completedFuture(chunk); ++ } ++ }).thenAccept(chunk -> { ++ playerconnection.playerJoinReady = () -> { ++ postChunkLoadJoin( ++ entityplayer, finalWorldserver, networkmanager, playerconnection, ++ nbttagcompound, networkmanager.getSocketAddress().toString(), lastKnownName ++ ); ++ }; ++ }); ++ } ++ ++ public EntityPlayer getActivePlayer(UUID uuid) { ++ EntityPlayer player = this.getUUIDMap().get(uuid); ++ return player != null ? player : pendingPlayers.get(uuid); ++ } ++ ++ void disconnectPendingPlayer(EntityPlayer entityplayer) { ++ ChatMessage msg = new ChatMessage("multiplayer.disconnect.duplicate_login", new Object[0]); ++ entityplayer.networkManager.sendPacket(new PacketPlayOutKickDisconnect(msg), (future) -> { ++ entityplayer.networkManager.close(msg); ++ entityplayer.networkManager = null; ++ }); ++ } ++ ++ private void postChunkLoadJoin(EntityPlayer entityplayer, WorldServer worldserver1, NetworkManager networkmanager, PlayerConnection playerconnection, NBTTagCompound nbttagcompound, String s1, String s) { ++ pendingPlayers.remove(entityplayer.getUniqueID(), entityplayer); ++ if (!networkmanager.isConnected()) { ++ return; ++ } ++ entityplayer.didPlayerJoinEvent = true; ++ // Paper end + ChatMessage chatmessage; + + if (entityplayer.getProfile().getName().equalsIgnoreCase(s)) { +@@ -496,6 +550,7 @@ public abstract class PlayerList { + + protected void savePlayerFile(EntityPlayer entityplayer) { + if (!entityplayer.getBukkitEntity().isPersistent()) return; // CraftBukkit ++ if (!entityplayer.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) + this.playerFileData.save(entityplayer); + ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) entityplayer.getStatisticManager(); // CraftBukkit + +@@ -523,7 +578,7 @@ public abstract class PlayerList { + } + + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); +- cserver.getPluginManager().callEvent(playerQuitEvent); ++ if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + + if (server.isMainThread()) entityplayer.playerTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) +@@ -576,6 +631,13 @@ public abstract class PlayerList { + // this.p.remove(uuid); + // CraftBukkit end + } ++ // Paper start ++ entityplayer1 = pendingPlayers.get(uuid); ++ if (entityplayer1 == entityplayer) { ++ pendingPlayers.remove(uuid); ++ } ++ entityplayer.networkManager = null; ++ // Paper end + + // CraftBukkit start + // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[]{entityplayer})); +@@ -593,7 +655,7 @@ public abstract class PlayerList { + cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); + // CraftBukkit end + +- return playerQuitEvent.quitMessage(); // Paper - Adventure ++ return entityplayer.didPlayerJoinEvent ? playerQuitEvent.quitMessage() : null; // CraftBukkit // Paper - Adventure // Paper - don't print quit if we never printed join + } + + // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer +@@ -612,6 +674,13 @@ public abstract class PlayerList { + list.add(entityplayer); + } + } ++ // Paper start - check pending players too ++ entityplayer = pendingPlayers.get(uuid); ++ if (entityplayer != null) { ++ this.pendingPlayers.remove(uuid); ++ disconnectPendingPlayer(entityplayer); ++ } ++ // Paper end + + Iterator iterator = list.iterator(); + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 6c368921f76fb6eb99dd20dd49d6ba5ac80cdfad..896b4d016de78e98276d7cdf9328d8951572e3be 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1372,7 +1372,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.lastY = d1; + this.lastZ = d4; + this.setPosition(d3, d1, d4); +- world.getChunkAt((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); // CraftBukkit ++ if (valid) world.getChunkAt((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); // CraftBukkit // Paper + } + + public void d(Vec3D vec3d) { diff --git a/patches/server-unmapped/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/patches/server-unmapped/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch new file mode 100644 index 0000000000..49becb3d56 --- /dev/null +++ b/patches/server-unmapped/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2277 <38501234+2277@users.noreply.github.com> +Date: Tue, 31 Mar 2020 10:33:55 +0100 +Subject: [PATCH] Move player to spawn point if spawn in unloaded world + +The code following this has better support for null worlds to move +them back to the world spawn. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 896b4d016de78e98276d7cdf9328d8951572e3be..fbd473d39cd71510b5fe8b7a4d34d3b824301f73 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1809,9 +1809,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + bworld = server.getWorld(worldName); + } + +- if (bworld == null) { +- bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld(); +- } ++ // Paper start - Move player to spawn point if spawn in unloaded world ++// if (bworld == null) { ++// bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld(); ++// } ++ // Paper end - Move player to spawn point if spawn in unloaded world + + spawnIn(bworld == null ? null : ((CraftWorld) bworld).getHandle()); + } diff --git a/patches/server-unmapped/0453-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server-unmapped/0453-Add-PlayerAttackEntityCooldownResetEvent.patch new file mode 100644 index 0000000000..c5cfc7c622 --- /dev/null +++ b/patches/server-unmapped/0453-Add-PlayerAttackEntityCooldownResetEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: nossr50 +Date: Thu, 26 Mar 2020 19:44:50 -0700 +Subject: [PATCH] Add PlayerAttackEntityCooldownResetEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 40fb7e96af7bbbe6c5586fa4d2a629b5a8f7b07a..13896da2194cab683782504291ede6f135ca7279 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -1931,7 +1931,16 @@ public abstract class EntityLiving extends Entity { + + EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, hardHat, blocking, armor, resistance, magic, absorption); + if (damagesource.getEntity() instanceof EntityHuman) { +- ((EntityHuman) damagesource.getEntity()).resetAttackCooldown(); // Moved from EntityHuman in order to make the cooldown reset get called after the damage event is fired ++ // Paper start - PlayerAttackEntityCooldownResetEvent ++ if (damagesource.getEntity() instanceof EntityPlayer) { ++ EntityPlayer player = (EntityPlayer) damagesource.getEntity(); ++ if (new com.destroystokyo.paper.event.player.PlayerAttackEntityCooldownResetEvent(player.getBukkitEntity(), this.getBukkitEntity(), player.getAttackCooldown(0F)).callEvent()) { ++ player.resetAttackCooldown(); ++ } ++ } else { ++ ((EntityHuman) damagesource.getEntity()).resetAttackCooldown(); ++ } ++ // Paper end + } + if (event.isCancelled()) { + return false; diff --git a/patches/server-unmapped/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/patches/server-unmapped/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch new file mode 100644 index 0000000000..df3e2c58ef --- /dev/null +++ b/patches/server-unmapped/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 21 Apr 2020 03:51:53 -0400 +Subject: [PATCH] Allow multiple callbacks to schedule for Callback Executor + +ChunkMapDistance polls multiple entries for pendingChunkUpdates + +Each of these have the potential to move a chunk in and out of +"Loaded" state, which will result in multiple callbacks being +needed within a single tick of ChunkMapDistance + +Use an ArrayDeque to store this Queue + +We make sure to also implement a pattern that is recursion safe too. + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 6e4a47581843be42b77034fec16b1d531a5b5759..d509cfd2da99233e5142abd176cc50ccea7c32b6 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -162,24 +162,32 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + public final CallbackExecutor callbackExecutor = new CallbackExecutor(); + public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { + +- private Runnable queued; ++ // Paper start - replace impl with recursive safe multi entry queue ++ // it's possible to schedule multiple tasks currently, so it's vital we change this impl ++ // If we recurse into the executor again, we will append to another queue, ensuring task order consistency ++ private java.util.ArrayDeque queued = new java.util.ArrayDeque<>(); + + @Override + public void execute(Runnable runnable) { +- if (queued != null) { +- throw new IllegalStateException("Already queued"); ++ if (queued == null) { ++ queued = new java.util.ArrayDeque<>(); + } +- queued = runnable; ++ queued.add(runnable); + } + + @Override + public void run() { +- Runnable task = queued; ++ if (queued == null) { ++ return; ++ } ++ java.util.ArrayDeque queue = queued; + queued = null; +- if (task != null) { ++ Runnable task; ++ while ((task = queue.pollFirst()) != null) { + task.run(); + } + } ++ // Paper end + }; + // CraftBukkit end + diff --git a/patches/server-unmapped/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch b/patches/server-unmapped/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch new file mode 100644 index 0000000000..895675ad80 --- /dev/null +++ b/patches/server-unmapped/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 23 Apr 2020 01:36:39 -0400 +Subject: [PATCH] Don't fire BlockFade on worldgen threads + +Caused a deadlock + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java +index 5ef38414d87fbce453e3ab11579c89a8ff089ae0..e6ea1d29c7f3f4cb6039df0e35c8db94b6f38c3e 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockFire.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java +@@ -94,6 +94,7 @@ public class BlockFire extends BlockFireAbstract { + @Override + public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { + // CraftBukkit start ++ if (!(generatoraccess instanceof WorldServer)) return this.canPlace(iblockdata, generatoraccess, blockposition) ? (IBlockData) this.a(generatoraccess, blockposition, (Integer) iblockdata.get(BlockFire.AGE)) : Blocks.AIR.getBlockData(); // Paper - don't fire events in world generation + if (!this.canPlace(iblockdata, generatoraccess, blockposition)) { + // Suppress during worldgen + if (!(generatoraccess instanceof World)) { +@@ -109,7 +110,7 @@ public class BlockFire extends BlockFireAbstract { + return blockState.getHandle(); + } + } +- return this.a(generatoraccess, blockposition, (Integer) iblockdata.get(BlockFire.AGE)); ++ return this.a(generatoraccess, blockposition, (Integer) iblockdata.get(BlockFire.AGE)); // Paper - diff on change, see "don't fire events in world generation" + // CraftBukkit end + } + diff --git a/patches/server-unmapped/0456-Add-phantom-creative-and-insomniac-controls.patch b/patches/server-unmapped/0456-Add-phantom-creative-and-insomniac-controls.patch new file mode 100644 index 0000000000..68c8e2168d --- /dev/null +++ b/patches/server-unmapped/0456-Add-phantom-creative-and-insomniac-controls.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 25 Apr 2020 15:13:41 -0500 +Subject: [PATCH] Add phantom creative and insomniac controls + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index cd248eb6be663e8be33f2c3c6b06b77b6d5753a4..46ac6d91422423f1e03b86d3efa3241f2599000d 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -625,4 +625,11 @@ public class PaperWorldConfig { + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); + } ++ ++ public boolean phantomIgnoreCreative = true; ++ public boolean phantomOnlyAttackInsomniacs = true; ++ private void phantomSettings() { ++ phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); ++ phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +index 1a6f8aec32af85717f5d56e0b00a02cda88ce028..c8d7ea8cfa4945af4a6675172b931a4cc3ca2801 100644 +--- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +@@ -3,6 +3,9 @@ package net.minecraft.world.entity; + import com.google.common.base.Predicates; + import java.util.function.Predicate; + import javax.annotation.Nullable; ++import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.stats.StatisticList; ++import net.minecraft.util.MathHelper; + import net.minecraft.world.EnumDifficulty; + import net.minecraft.world.IInventory; + import net.minecraft.world.entity.player.EntityHuman; +@@ -31,6 +34,7 @@ public final class IEntitySelector { + public static final Predicate g = (entity) -> { + return !entity.isSpectator(); + }; ++ public static Predicate isInsomniac = (player) -> MathHelper.clamp(((EntityPlayer) player).getStatisticManager().getStatisticValue(StatisticList.CUSTOM.get(StatisticList.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper + + // Paper start + public static final Predicate affectsSpawning = (entity) -> { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +index 6c498d4345df35a411d155799ac56e47c9c48114..42cf3fa42b73739182d26fbb524ee5b304c799b2 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +@@ -262,6 +262,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { + EntityHuman entityhuman = (EntityHuman) iterator.next(); + + if (EntityPhantom.this.a((EntityLiving) entityhuman, PathfinderTargetCondition.a)) { ++ if (!world.paperConfig.phantomOnlyAttackInsomniacs || IEntitySelector.isInsomniac.test(entityhuman)) // Paper + EntityPhantom.this.setGoalTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason + return true; + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java +index 96a5a6569387a25b15a06aaab3bd9d033547e875..e4f5e570636862481aac92ec9b74d6cf5723eb6e 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java +@@ -53,7 +53,7 @@ public class MobSpawnerPhantom implements MobSpawner { + while (iterator.hasNext()) { + EntityHuman entityhuman = (EntityHuman) iterator.next(); + +- if (!entityhuman.isSpectator()) { ++ if (!entityhuman.isSpectator() && (!worldserver.paperConfig.phantomIgnoreCreative || !entityhuman.isCreative())) { // Paper + BlockPosition blockposition = entityhuman.getChunkCoordinates(); + + if (!worldserver.getDimensionManager().hasSkyLight() || blockposition.getY() >= worldserver.getSeaLevel() && worldserver.e(blockposition)) { diff --git a/patches/server-unmapped/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/patches/server-unmapped/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch new file mode 100644 index 0000000000..eb495bf0f5 --- /dev/null +++ b/patches/server-unmapped/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 25 Apr 2020 06:46:35 -0400 +Subject: [PATCH] Fix numerous item duplication issues and teleport issues + +This notably fixes the newest "Donkey Dupe", but also fixes a lot +of dupe bugs in general around nether portals and entity world transfer + +We also fix item duplication generically by anytime we clone an item +to drop it on the ground, destroy the source item. + +This avoid an itemstack ever existing twice in the world state pre +clean up stage. + +So even if something NEW comes up, it would be impossible to drop the +same item twice because the source was destroyed. + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index fbd473d39cd71510b5fe8b7a4d34d3b824301f73..8d8d94219f9a556212763fce736452a19249ffec 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1974,11 +1974,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } else { + // CraftBukkit start - Capture drops for death event + if (this instanceof EntityLiving && !((EntityLiving) this).forceDrops) { +- ((EntityLiving) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); ++ ((EntityLiving) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // Paper - mirror so we can destroy it later + return null; + } + // CraftBukkit end +- EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY() + (double) f, this.locZ(), itemstack); ++ EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY() + (double) f, this.locZ(), itemstack.cloneItemStack()); // Paper - clone so we can destroy original ++ itemstack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe + + entityitem.defaultPickupDelay(); + // CraftBukkit start +@@ -2626,6 +2627,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + @Nullable + public Entity teleportTo(WorldServer worldserver, BlockPosition location) { + // CraftBukkit end ++ // Paper start - fix bad state entities causing dupes ++ if (!isAlive() || !valid) { ++ LOGGER.warn("Illegal Entity Teleport " + this + " to " + worldserver + ":" + location, new Throwable()); ++ return null; ++ } ++ // Paper end + if (this.world instanceof WorldServer && !this.dead) { + this.world.getMethodProfiler().enter("changeDimension"); + // CraftBukkit start +@@ -2646,6 +2653,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + // CraftBukkit end + + this.world.getMethodProfiler().exitEnter("reloading"); ++ // Paper start - Change lead drop timing to prevent dupe ++ if (this instanceof EntityInsentient) { ++ ((EntityInsentient) this).unleash(true, true); // Paper drop lead ++ } ++ // Paper end + Entity entity = this.getEntityType().a((World) worldserver); + + if (entity != null) { +@@ -2659,10 +2671,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + // CraftBukkit start - Forward the CraftEntity to the new entity + this.getBukkitEntity().setHandle(entity); + entity.bukkitEntity = this.getBukkitEntity(); +- +- if (this instanceof EntityInsentient) { +- ((EntityInsentient) this).unleash(true, false); // Unleash to prevent duping of leads. +- } + // CraftBukkit end + } + +@@ -2787,7 +2795,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public boolean canPortal() { +- return true; ++ return isAlive() && valid; // Paper + } + + public float a(Explosion explosion, IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, float f) { +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +index 69361caebf0d3caa5195b519a16691705ac5e16a..5eb900619951083b9a777b1645cb5495b99968ec 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +@@ -602,7 +602,7 @@ public class EntityArmorStand extends EntityLiving { + for (i = 0; i < this.handItems.size(); ++i) { + itemstack = (ItemStack) this.handItems.get(i); + if (!itemstack.isEmpty()) { +- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe + this.handItems.set(i, ItemStack.b); + } + } +@@ -610,7 +610,7 @@ public class EntityArmorStand extends EntityLiving { + for (i = 0; i < this.armorItems.size(); ++i) { + itemstack = (ItemStack) this.armorItems.get(i); + if (!itemstack.isEmpty()) { +- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe + this.armorItems.set(i, ItemStack.b); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 0b27d68dce9537c17701bd4944c807414564170b..d620d3e7c023786d1b7411399a05a75028a404cc 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -827,7 +827,8 @@ public class CraftEventFactory { + for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { + if (stack == null || stack.getType() == Material.AIR || stack.getAmount() == 0) continue; + +- world.dropItem(entity.getLocation(), stack); ++ world.dropItem(entity.getLocation(), stack); // Paper - note: dropItem already clones due to this being bukkit -> NMS ++ if (stack instanceof CraftItemStack) stack.setAmount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe, but don't nuke bukkit stacks of manually added items + } + + return event; diff --git a/patches/server-unmapped/0458-Implement-Brigadier-Mojang-API.patch b/patches/server-unmapped/0458-Implement-Brigadier-Mojang-API.patch new file mode 100644 index 0000000000..16614706f6 --- /dev/null +++ b/patches/server-unmapped/0458-Implement-Brigadier-Mojang-API.patch @@ -0,0 +1,139 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 19 Apr 2020 18:15:29 -0400 +Subject: [PATCH] Implement Brigadier Mojang API + +Adds AsyncPlayerSendCommandsEvent + - Allows modifying on a per command basis what command data they see. + +Adds CommandRegisteredEvent + - Allows manipulating the CommandNode to add more children/metadata for the client + +diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java +index 592b1bb2ce5cedb627f42c73ef072ade6553347e..a13c684e1360169993f323aa4aa91078c5e8b031 100644 +--- a/src/main/java/net/minecraft/commands/CommandDispatcher.java ++++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java +@@ -355,6 +355,7 @@ public class CommandDispatcher { + bukkit.add(node.getName()); + } + // Paper start - Async command map building ++ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper + MinecraftServer.getServer().execute(() -> { + runSync(entityplayer, bukkit, rootcommandnode); + }); +@@ -362,6 +363,7 @@ public class CommandDispatcher { + + private void runSync(EntityPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { + // Paper end - Async command map building ++ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper + PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); + event.getPlayer().getServer().getPluginManager().callEvent(event); + +diff --git a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java +index eb2c9d2248a8647beee9960c5016a83f35aa1247..b5ee789c8dfb7f413ab60902ff3d2ef0cf8273cd 100644 +--- a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java ++++ b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java +@@ -38,7 +38,7 @@ import net.minecraft.world.phys.Vec3D; + + import com.mojang.brigadier.tree.CommandNode; // CraftBukkit + +-public class CommandListenerWrapper implements ICompletionProvider { ++public class CommandListenerWrapper implements ICompletionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource { // Paper + + public static final SimpleCommandExceptionType a = new SimpleCommandExceptionType(new ChatMessage("permissions.requires.player")); + public static final SimpleCommandExceptionType b = new SimpleCommandExceptionType(new ChatMessage("permissions.requires.entity")); +@@ -150,6 +150,25 @@ public class CommandListenerWrapper implements ICompletionProvider { + return this.g; + } + ++ // Paper start ++ @Override ++ public org.bukkit.entity.Entity getBukkitEntity() { ++ return getEntity() != null ? getEntity().getBukkitEntity() : null; ++ } ++ ++ @Override ++ public org.bukkit.World getBukkitWorld() { ++ return getWorld() != null ? getWorld().getWorld() : null; ++ } ++ ++ @Override ++ public org.bukkit.Location getBukkitLocation() { ++ Vec3D pos = getPosition(); ++ org.bukkit.World world = getBukkitWorld(); ++ return world != null && pos != null ? new org.bukkit.Location(world, pos.x, pos.y, pos.z) : null; ++ } ++ // Paper end ++ + @Override + public boolean hasPermission(int i) { + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 7c1d25feab71c325ce2379afa6c61732eebd74f9..358d1acf7ca9ce510325fedf31e18a27c3a784d5 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -770,8 +770,12 @@ public class PlayerConnection implements PacketListenerPlayIn { + ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); + + this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { +- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer +- this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); ++ // Paper start ++ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); ++ suggestEvent.setCancelled(suggestions.isEmpty()); ++ if (!suggestEvent.callEvent()) return; ++ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), (com.mojang.brigadier.suggestion.Suggestions) suggestEvent.getSuggestions())); // CraftBukkit - decompile error // Paper ++ // Paper end + }); + }); + } +@@ -780,7 +784,11 @@ public class PlayerConnection implements PacketListenerPlayIn { + + builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); + completions.forEach(builder::suggest); +- player.playerConnection.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), builder.buildFuture().join())); ++ com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); ++ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); ++ suggestEvent.setCancelled(suggestions.isEmpty()); ++ if (!suggestEvent.callEvent()) return; ++ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestEvent.getSuggestions())); + } + // Paper end - async tab completion + } +diff --git a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java +index 23d922a8baac01144602fd7813e9e76abc5335a3..8ddd246ad69a2e53749d38c369af701c161de54e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java +@@ -17,7 +17,7 @@ import net.minecraft.commands.CommandListenerWrapper; + import org.bukkit.command.Command; + import org.bukkit.craftbukkit.CraftServer; + +-public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider { ++public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommand { // Paper + + private final CraftServer server; + private final Command command; +@@ -28,10 +28,19 @@ public class BukkitCommandWrapper implements com.mojang.brigadier.Command register(CommandDispatcher dispatcher, String label) { +- return dispatcher.register( +- LiteralArgumentBuilder.literal(label).requires(this).executes(this) +- .then(RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this)) +- ); ++ // Paper start - Expose Brigadier to Paper-MojangAPI ++ com.mojang.brigadier.tree.RootCommandNode root = dispatcher.getRoot(); ++ LiteralCommandNode literal = LiteralArgumentBuilder.literal(label).requires(this).executes(this).build(); ++ com.mojang.brigadier.tree.ArgumentCommandNode defaultArgs = RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this).build(); ++ literal.addChild(defaultArgs); ++ com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent event = new com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent<>(label, this, this.command, root, literal, defaultArgs); ++ if (!event.callEvent()) { ++ return null; ++ } ++ literal = event.getLiteral(); ++ root.addChild(literal); ++ return literal; ++ // Paper end + } + + @Override diff --git a/patches/server-unmapped/0459-Villager-Restocks-API.patch b/patches/server-unmapped/0459-Villager-Restocks-API.patch new file mode 100644 index 0000000000..55095b2a01 --- /dev/null +++ b/patches/server-unmapped/0459-Villager-Restocks-API.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: zbk +Date: Sun, 26 Apr 2020 23:49:01 -0400 +Subject: [PATCH] Villager Restocks API + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index 596450d3cdb3be4abca3e75bed743abd071fb0b0..fb97325e8df33c0edabb81053877ad4a326a3d34 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -113,7 +113,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + private long bA; + private int bB; + private long bC; +- private int bD; ++ private int bD; public int getRestocksToday(){ return this.bD; } public void setRestocksToday(int restocksToday){ this.bD = restocksToday; } // Paper OBFHELPER + private long bE; + private boolean bF; + private static final ImmutableList> bG = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.MOBS, MemoryModuleType.VISIBLE_MOBS, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.WALK_TARGET, new MemoryModuleType[]{MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +index b020bc9e78a524b4745844ceb99249949c5ab6a4..4b2451179cdda918808ea7001f5033c7e5a8b9ac 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +@@ -84,6 +84,18 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { + getHandle().setExperience(experience); + } + ++ // Paper start ++ @Override ++ public int getRestocksToday() { ++ return getHandle().getRestocksToday(); ++ } ++ ++ @Override ++ public void setRestocksToday(int restocksToday) { ++ getHandle().setRestocksToday(restocksToday); ++ } ++ // Paper end ++ + @Override + public boolean sleep(Location location) { + Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/patches/server-unmapped/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch b/patches/server-unmapped/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch new file mode 100644 index 0000000000..2c474587ad --- /dev/null +++ b/patches/server-unmapped/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 2 May 2020 03:09:46 -0400 +Subject: [PATCH] Validate PickItem Packet and kick for invalid + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 358d1acf7ca9ce510325fedf31e18a27c3a784d5..b491a3563bf457bcb631e05cf41b661712134966 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -883,7 +883,14 @@ public class PlayerConnection implements PacketListenerPlayIn { + @Override + public void a(PacketPlayInPickItem packetplayinpickitem) { + PlayerConnectionUtils.ensureMainThread(packetplayinpickitem, this, this.player.getWorldServer()); +- this.player.inventory.c(packetplayinpickitem.b()); ++ // Paper start - validate pick item position ++ if (!(packetplayinpickitem.b() >= 0 && packetplayinpickitem.b() < this.player.inventory.items.size())) { ++ PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getDisplayName().getString()); ++ this.disconnect("Invalid hotbar selection (Hacking?)"); ++ return; ++ } ++ this.player.inventory.c(packetplayinpickitem.b()); // Paper - Diff above if changed ++ // Paper end + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, this.player.inventory.itemInHandIndex, this.player.inventory.getItem(this.player.inventory.itemInHandIndex))); + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, packetplayinpickitem.b(), this.player.inventory.getItem(packetplayinpickitem.b()))); + this.player.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(this.player.inventory.itemInHandIndex)); diff --git a/patches/server-unmapped/0461-Expose-game-version.patch b/patches/server-unmapped/0461-Expose-game-version.patch new file mode 100644 index 0000000000..24b6d2653e --- /dev/null +++ b/patches/server-unmapped/0461-Expose-game-version.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Fri, 1 May 2020 17:39:26 +0300 +Subject: [PATCH] Expose game version + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 63f89916d9982caa99525e01bd0e3f153af74d0f..f6e2e54b5a1b8c2df41a0593fa15112c5195c49c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -515,6 +515,13 @@ public final class CraftServer implements Server { + return bukkitVersion; + } + ++ // Paper start - expose game version ++ @Override ++ public String getMinecraftVersion() { ++ return console.getVersion(); ++ } ++ // Paper end ++ + @Override + public List getOnlinePlayers() { + return this.playerView; diff --git a/patches/server-unmapped/0462-Optimize-Voxel-Shape-Merging.patch b/patches/server-unmapped/0462-Optimize-Voxel-Shape-Merging.patch new file mode 100644 index 0000000000..e817b38737 --- /dev/null +++ b/patches/server-unmapped/0462-Optimize-Voxel-Shape-Merging.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 May 2020 22:35:09 -0400 +Subject: [PATCH] Optimize Voxel Shape Merging + +This method shows up as super hot in profiler, and also a high "self" time. + +Upon analyzing, it appears most usages of this method fall down to the final +else statement of the nasty ternary. + +Upon even further analyzation, it appears then the majority of those have a +consistent list 1.... One with Infinity head and Tails. + +First optimization is to detect these infinite states and immediately return that +VoxelShapeMergerList so we can avoid testing the rest for most cases. + +Break the method into 2 to help the JVM promote inlining of this fast path. + +Then it was also noticed that VoxelShapeMergerList constructor is also a hotspot +with a high self time... + +Well, knowing that in most cases our list 1 is actualy the same value, it allows +us to know that with an infinite list1, the result on the merger is essentially +list2 as the final values. + +This let us analyze the 2 potential states (Infinite with 2 sources or 4 sources) +and compute a deterministic result for the MergerList values. + +Additionally, this lets us avoid even allocating new objects for this too, further +reducing memory usage. + +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java +index c58d380b96e81d65d7c254a9e53017e5157769b0..57a4b4fcb6f89aacadcca49b25153157c8d06cc3 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java +@@ -6,10 +6,16 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; + + public final class VoxelShapeMergerList implements VoxelShapeMerger { + +- private final DoubleArrayList a; ++ private final DoubleList a; // Paper + private final IntArrayList b; + private final IntArrayList c; + ++ // Paper start ++ private static final IntArrayList INFINITE_B_1 = new IntArrayList(new int[]{1, 1}); ++ private static final IntArrayList INFINITE_B_0 = new IntArrayList(new int[]{0, 0}); ++ private static final IntArrayList INFINITE_C = new IntArrayList(new int[]{0, 1}); ++ // Paper end ++ + protected VoxelShapeMergerList(DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { + int i = 0; + int j = 0; +@@ -18,6 +24,22 @@ public final class VoxelShapeMergerList implements VoxelShapeMerger { + int l = doublelist1.size(); + int i1 = k + l; + ++ // Paper start - optimize common path of infinity doublelist ++ int size = doublelist.size(); ++ double tail = doublelist.getDouble(size - 1); ++ double head = doublelist.getDouble(0); ++ if (head == Double.NEGATIVE_INFINITY && tail == Double.POSITIVE_INFINITY && !flag && !flag1 && (size == 2 || size == 4)) { ++ this.a = doublelist1; ++ if (size == 2) { ++ this.b = INFINITE_B_0; ++ } else { ++ this.b = INFINITE_B_1; ++ } ++ this.c = INFINITE_C; ++ return; ++ } ++ // Paper end ++ + this.a = new DoubleArrayList(i1); + this.b = new IntArrayList(i1); + this.c = new IntArrayList(i1); +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +index 24ecac40625629b0bbe460e7fc984b147ede1f1f..2d7405d1fa7c8f378bebe86f5d0de57a129ed92d 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +@@ -329,9 +329,21 @@ public final class VoxelShapes { + } + + @VisibleForTesting +- protected static VoxelShapeMerger a(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { ++ private static VoxelShapeMerger a(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { // Paper - private ++ // Paper start - fast track the most common scenario ++ // doublelist is usually a DoubleArrayList with Infinite head/tails that falls to the final else clause ++ // This is actually the most common path, so jump to it straight away ++ if (doublelist.getDouble(0) == Double.NEGATIVE_INFINITY && doublelist.getDouble(doublelist.size() - 1) == Double.POSITIVE_INFINITY) { ++ return new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1); ++ } ++ // Split out rest to hopefully inline the above ++ return lessCommonMerge(i, doublelist, doublelist1, flag, flag1); ++ } ++ ++ private static VoxelShapeMerger lessCommonMerge(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { + int j = doublelist.size() - 1; + int k = doublelist1.size() - 1; ++ // Paper note - Rewrite below as optimized order if instead of nasty ternary + + if (doublelist instanceof VoxelShapeCubePoint && doublelist1 instanceof VoxelShapeCubePoint) { + long l = a(j, k); +@@ -341,7 +353,22 @@ public final class VoxelShapes { + } + } + +- return (VoxelShapeMerger) (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-7D ? new VoxelShapeMergerDisjoint(doublelist, doublelist1, false) : (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-7D ? new VoxelShapeMergerDisjoint(doublelist1, doublelist, true) : (j == k && Objects.equals(doublelist, doublelist1) ? (doublelist instanceof VoxelShapeMergerIdentical ? (VoxelShapeMerger) doublelist : (doublelist1 instanceof VoxelShapeMergerIdentical ? (VoxelShapeMerger) doublelist1 : new VoxelShapeMergerIdentical(doublelist))) : new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1)))); ++ // Identical happens more often than Disjoint ++ if (j == k && Objects.equals(doublelist, doublelist1)) { ++ if (doublelist instanceof VoxelShapeMergerIdentical) { ++ return (VoxelShapeMerger) doublelist; ++ } else if (doublelist1 instanceof VoxelShapeMergerIdentical) { ++ return (VoxelShapeMerger) doublelist1; ++ } ++ return new VoxelShapeMergerIdentical(doublelist); ++ } else if (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-07) { ++ return new VoxelShapeMergerDisjoint(doublelist, doublelist1, false); ++ } else if (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-07) { ++ return new VoxelShapeMergerDisjoint(doublelist1, doublelist, true); ++ } else { ++ return new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1); ++ } ++ // Paper end + } + + public interface a { diff --git a/patches/server-unmapped/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/patches/server-unmapped/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch new file mode 100644 index 0000000000..52eb1dbcaa --- /dev/null +++ b/patches/server-unmapped/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 4 May 2020 01:08:56 -0400 +Subject: [PATCH] Set cap on JDK per-thread native byte buffer cache + +See: https://www.evanjones.ca/java-bytebuffer-leak.html + +This is potentially a source of lots of native memory usage. + +We are clearly seeing native usage upwards to 1-4GB which doesn't make sense. + +Region File usage fixed in previous patch should of tecnically only been somewhat +temporary until GC finally gets it some time later, but between all the various +plugins doing IO on various threads, this hidden detail of the JDK could be +keeping long lived large direct buffers in cache. + +Set system properly at server startup if not set already to help protect from this. + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 5c54ecf6b1cf5531e51ae4d0a318aa64b837b574..6459ec144fa54a1e6ad1f0c40776321e95b41197 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -28,6 +28,7 @@ public class Main { + } + // Paper end + // Todo: Installation script ++ if (System.getProperty("jdk.nio.maxCachedBufferSize") == null) System.setProperty("jdk.nio.maxCachedBufferSize", "262144"); // Paper - cap per-thread NIO cache size + OptionParser parser = new OptionParser() { + { + acceptsAll(asList("?", "help"), "Show the help"); diff --git a/patches/server-unmapped/0464-Implement-Mob-Goal-API.patch b/patches/server-unmapped/0464-Implement-Mob-Goal-API.patch new file mode 100644 index 0000000000..3fbd0e0c30 --- /dev/null +++ b/patches/server-unmapped/0464-Implement-Mob-Goal-API.patch @@ -0,0 +1,1170 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Fri, 3 Jan 2020 16:26:19 +0100 +Subject: [PATCH] Implement Mob Goal API + + +diff --git a/pom.xml b/pom.xml +index 4c8a057e790c96b0ab5123549d0566371acacb46..1a9204c869dd36e80932b1366352db15ebd70723 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -176,6 +176,13 @@ + 1.3 + test + ++ ++ ++ io.github.classgraph ++ classgraph ++ 4.8.47 ++ test ++ + + + +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f62d0ee49ebda2b0c7a136562b24ee038502d048 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java +@@ -0,0 +1,530 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import com.destroystokyo.paper.entity.RangedEntity; ++import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; ++import com.google.common.collect.BiMap; ++import com.google.common.collect.HashBiMap; ++import java.lang.reflect.Constructor; ++import java.util.EnumSet; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.Map; ++import java.util.Set; ++import net.minecraft.world.entity.EntityAgeable; ++import net.minecraft.world.entity.EntityCreature; ++import net.minecraft.world.entity.EntityFlying; ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.entity.EntityTameableAnimal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoal; ++import net.minecraft.world.entity.ambient.EntityAmbient; ++import net.minecraft.world.entity.ambient.EntityBat; ++import net.minecraft.world.entity.animal.EntityAnimal; ++import net.minecraft.world.entity.animal.EntityBee; ++import net.minecraft.world.entity.animal.EntityCat; ++import net.minecraft.world.entity.animal.EntityChicken; ++import net.minecraft.world.entity.animal.EntityCod; ++import net.minecraft.world.entity.animal.EntityCow; ++import net.minecraft.world.entity.animal.EntityDolphin; ++import net.minecraft.world.entity.animal.EntityFish; ++import net.minecraft.world.entity.animal.EntityFishSchool; ++import net.minecraft.world.entity.animal.EntityFox; ++import net.minecraft.world.entity.animal.EntityGolem; ++import net.minecraft.world.entity.animal.EntityIronGolem; ++import net.minecraft.world.entity.animal.EntityMushroomCow; ++import net.minecraft.world.entity.animal.EntityOcelot; ++import net.minecraft.world.entity.animal.EntityPanda; ++import net.minecraft.world.entity.animal.EntityParrot; ++import net.minecraft.world.entity.animal.EntityPerchable; ++import net.minecraft.world.entity.animal.EntityPig; ++import net.minecraft.world.entity.animal.EntityPolarBear; ++import net.minecraft.world.entity.animal.EntityPufferFish; ++import net.minecraft.world.entity.animal.EntityRabbit; ++import net.minecraft.world.entity.animal.EntitySalmon; ++import net.minecraft.world.entity.animal.EntitySheep; ++import net.minecraft.world.entity.animal.EntitySnowman; ++import net.minecraft.world.entity.animal.EntitySquid; ++import net.minecraft.world.entity.animal.EntityTropicalFish; ++import net.minecraft.world.entity.animal.EntityTurtle; ++import net.minecraft.world.entity.animal.EntityWaterAnimal; ++import net.minecraft.world.entity.animal.EntityWolf; ++import net.minecraft.world.entity.animal.horse.EntityHorse; ++import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; ++import net.minecraft.world.entity.animal.horse.EntityHorseChestedAbstract; ++import net.minecraft.world.entity.animal.horse.EntityHorseDonkey; ++import net.minecraft.world.entity.animal.horse.EntityHorseMule; ++import net.minecraft.world.entity.animal.horse.EntityHorseSkeleton; ++import net.minecraft.world.entity.animal.horse.EntityHorseZombie; ++import net.minecraft.world.entity.animal.horse.EntityLlama; ++import net.minecraft.world.entity.animal.horse.EntityLlamaTrader; ++import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; ++import net.minecraft.world.entity.boss.wither.EntityWither; ++import net.minecraft.world.entity.monster.EntityBlaze; ++import net.minecraft.world.entity.monster.EntityCaveSpider; ++import net.minecraft.world.entity.monster.EntityCreeper; ++import net.minecraft.world.entity.monster.EntityDrowned; ++import net.minecraft.world.entity.monster.EntityEnderman; ++import net.minecraft.world.entity.monster.EntityEndermite; ++import net.minecraft.world.entity.monster.EntityEvoker; ++import net.minecraft.world.entity.monster.EntityGhast; ++import net.minecraft.world.entity.monster.EntityGiantZombie; ++import net.minecraft.world.entity.monster.EntityGuardian; ++import net.minecraft.world.entity.monster.EntityGuardianElder; ++import net.minecraft.world.entity.monster.EntityIllagerAbstract; ++import net.minecraft.world.entity.monster.EntityIllagerIllusioner; ++import net.minecraft.world.entity.monster.EntityIllagerWizard; ++import net.minecraft.world.entity.monster.EntityMagmaCube; ++import net.minecraft.world.entity.monster.EntityMonster; ++import net.minecraft.world.entity.monster.EntityMonsterPatrolling; ++import net.minecraft.world.entity.monster.EntityPhantom; ++import net.minecraft.world.entity.monster.EntityPigZombie; ++import net.minecraft.world.entity.monster.EntityPillager; ++import net.minecraft.world.entity.monster.EntityRavager; ++import net.minecraft.world.entity.monster.EntityShulker; ++import net.minecraft.world.entity.monster.EntitySilverfish; ++import net.minecraft.world.entity.monster.EntitySkeleton; ++import net.minecraft.world.entity.monster.EntitySkeletonAbstract; ++import net.minecraft.world.entity.monster.EntitySkeletonStray; ++import net.minecraft.world.entity.monster.EntitySkeletonWither; ++import net.minecraft.world.entity.monster.EntitySlime; ++import net.minecraft.world.entity.monster.EntitySpider; ++import net.minecraft.world.entity.monster.EntityStrider; ++import net.minecraft.world.entity.monster.EntityVex; ++import net.minecraft.world.entity.monster.EntityVindicator; ++import net.minecraft.world.entity.monster.EntityWitch; ++import net.minecraft.world.entity.monster.EntityZoglin; ++import net.minecraft.world.entity.monster.EntityZombie; ++import net.minecraft.world.entity.monster.EntityZombieHusk; ++import net.minecraft.world.entity.monster.EntityZombieVillager; ++import net.minecraft.world.entity.monster.IRangedEntity; ++import net.minecraft.world.entity.monster.hoglin.EntityHoglin; ++import net.minecraft.world.entity.monster.piglin.EntityPiglin; ++import net.minecraft.world.entity.monster.piglin.EntityPiglinAbstract; ++import net.minecraft.world.entity.monster.piglin.EntityPiglinBrute; ++import net.minecraft.world.entity.npc.EntityVillager; ++import net.minecraft.world.entity.npc.EntityVillagerAbstract; ++import net.minecraft.world.entity.npc.EntityVillagerTrader; ++import net.minecraft.world.entity.raid.EntityRaider; ++import org.bukkit.NamespacedKey; ++import org.bukkit.entity.AbstractHorse; ++import org.bukkit.entity.AbstractVillager; ++import org.bukkit.entity.Ageable; ++import org.bukkit.entity.Ambient; ++import org.bukkit.entity.Animals; ++import org.bukkit.entity.Bat; ++import org.bukkit.entity.Bee; ++import org.bukkit.entity.Blaze; ++import org.bukkit.entity.Cat; ++import org.bukkit.entity.CaveSpider; ++import org.bukkit.entity.ChestedHorse; ++import org.bukkit.entity.Chicken; ++import org.bukkit.entity.Cod; ++import org.bukkit.entity.Cow; ++import org.bukkit.entity.Creature; ++import org.bukkit.entity.Creeper; ++import org.bukkit.entity.Dolphin; ++import org.bukkit.entity.Donkey; ++import org.bukkit.entity.Drowned; ++import org.bukkit.entity.ElderGuardian; ++import org.bukkit.entity.EnderDragon; ++import org.bukkit.entity.Enderman; ++import org.bukkit.entity.Endermite; ++import org.bukkit.entity.Evoker; ++import org.bukkit.entity.Fish; ++import org.bukkit.entity.Flying; ++import org.bukkit.entity.Fox; ++import org.bukkit.entity.Ghast; ++import org.bukkit.entity.Giant; ++import org.bukkit.entity.Golem; ++import org.bukkit.entity.Guardian; ++import org.bukkit.entity.Hoglin; ++import org.bukkit.entity.Horse; ++import org.bukkit.entity.Husk; ++import org.bukkit.entity.Illager; ++import org.bukkit.entity.Illusioner; ++import org.bukkit.entity.IronGolem; ++import org.bukkit.entity.Llama; ++import org.bukkit.entity.MagmaCube; ++import org.bukkit.entity.Mob; ++import org.bukkit.entity.Monster; ++import org.bukkit.entity.Mule; ++import org.bukkit.entity.MushroomCow; ++import org.bukkit.entity.Ocelot; ++import org.bukkit.entity.Panda; ++import org.bukkit.entity.Parrot; ++import org.bukkit.entity.Phantom; ++import org.bukkit.entity.Pig; ++import org.bukkit.entity.PigZombie; ++import org.bukkit.entity.Piglin; ++import org.bukkit.entity.PiglinAbstract; ++import org.bukkit.entity.PiglinBrute; ++import org.bukkit.entity.Pillager; ++import org.bukkit.entity.PolarBear; ++import org.bukkit.entity.PufferFish; ++import org.bukkit.entity.Rabbit; ++import org.bukkit.entity.Raider; ++import org.bukkit.entity.Ravager; ++import org.bukkit.entity.Salmon; ++import org.bukkit.entity.Sheep; ++import org.bukkit.entity.Shulker; ++import org.bukkit.entity.Silverfish; ++import org.bukkit.entity.Skeleton; ++import org.bukkit.entity.SkeletonHorse; ++import org.bukkit.entity.Slime; ++import org.bukkit.entity.Snowman; ++import org.bukkit.entity.Spellcaster; ++import org.bukkit.entity.Spider; ++import org.bukkit.entity.Squid; ++import org.bukkit.entity.Stray; ++import org.bukkit.entity.Strider; ++import org.bukkit.entity.Tameable; ++import org.bukkit.entity.TraderLlama; ++import org.bukkit.entity.TropicalFish; ++import org.bukkit.entity.Turtle; ++import org.bukkit.entity.Vex; ++import org.bukkit.entity.Villager; ++import org.bukkit.entity.Vindicator; ++import org.bukkit.entity.WanderingTrader; ++import org.bukkit.entity.WaterMob; ++import org.bukkit.entity.Witch; ++import org.bukkit.entity.Wither; ++import org.bukkit.entity.WitherSkeleton; ++import org.bukkit.entity.Wolf; ++import org.bukkit.entity.Zoglin; ++import org.bukkit.entity.Zombie; ++import org.bukkit.entity.ZombieHorse; ++import org.bukkit.entity.ZombieVillager; ++ ++public class MobGoalHelper { ++ ++ private static final BiMap deobfuscationMap = HashBiMap.create(); ++ private static final Map, Class> entityClassCache = new HashMap<>(); ++ private static final Map, Class> bukkitMap = new HashMap<>(); ++ ++ static final Set ignored = new HashSet<>(); ++ ++ static { ++ // TODO these kinda should be checked on each release, in case obfuscation changes ++ deobfuscationMap.put("bee_b", "bee_attack"); ++ deobfuscationMap.put("bee_c", "bee_become_angry"); ++ deobfuscationMap.put("bee_d", "bee_enter_hive"); ++ deobfuscationMap.put("bee_e", "bee_go_to_hive"); ++ deobfuscationMap.put("bee_f", "bee_go_to_known_flower"); ++ deobfuscationMap.put("bee_g", "bee_grow_crop"); ++ deobfuscationMap.put("bee_h", "bee_hurt_by_other"); ++ deobfuscationMap.put("bee_i", "bee_locate_hive"); ++ deobfuscationMap.put("bee_k", "bee_pollinate"); ++ deobfuscationMap.put("bee_l", "bee_wander"); ++ deobfuscationMap.put("cat_a", "cat_avoid_entity"); ++ deobfuscationMap.put("cat_b", "cat_relax_on_owner"); ++ deobfuscationMap.put("dolphin_b", "dolphin_swim_to_treasure"); ++ deobfuscationMap.put("dolphin_c", "dolphin_swim_with_player"); ++ deobfuscationMap.put("dolphin_d", "dolphin_play_with_items"); ++ deobfuscationMap.put("drowned_a", "drowned_attack"); ++ deobfuscationMap.put("drowned_b", "drowned_goto_beach"); ++ deobfuscationMap.put("drowned_c", "drowned_goto_water"); ++ deobfuscationMap.put("drowned_e", "drowned_swim_up"); ++ deobfuscationMap.put("drowned_f", "drowned_trident_attack"); ++ deobfuscationMap.put("enderman_a", "enderman_freeze_when_looked_at"); ++ deobfuscationMap.put("evoker_a", "evoker_attack_spell"); ++ deobfuscationMap.put("evoker_b", "evoker_cast_spell"); ++ deobfuscationMap.put("evoker_c", "evoker_summon_spell"); ++ deobfuscationMap.put("evoker_d", "evoker_wololo_spell"); ++ deobfuscationMap.put("fish_b", "fish_swim"); ++ deobfuscationMap.put("fox_a", "fox_defend_trusted"); ++ deobfuscationMap.put("fox_b", "fox_faceplant"); ++ deobfuscationMap.put("fox_e", "fox_breed"); ++ deobfuscationMap.put("fox_f", "fox_eat_berries"); ++ deobfuscationMap.put("fox_g", "fox_float"); ++ deobfuscationMap.put("fox_h", "fox_follow_parent"); ++ deobfuscationMap.put("fox_j", "fox_look_at_player"); ++ deobfuscationMap.put("fox_l", "fox_melee_attack"); ++ deobfuscationMap.put("fox_n", "fox_panic"); ++ deobfuscationMap.put("fox_o", "fox_pounce"); ++ deobfuscationMap.put("fox_p", "fox_search_for_items"); ++ deobfuscationMap.put("fox_q", "fox_stroll_through_village"); ++ deobfuscationMap.put("fox_r", "fox_perch_and_search"); ++ deobfuscationMap.put("fox_s", "fox_seek_shelter"); ++ deobfuscationMap.put("fox_t", "fox_sleep"); ++ deobfuscationMap.put("fox_u", "fox_stalk_prey"); ++ deobfuscationMap.put("illager_abstract_b", "raider_open_door"); ++ deobfuscationMap.put("illager_illusioner_a", "illusioner_blindness_spell"); ++ deobfuscationMap.put("illager_illusioner_b", "illusioner_mirror_spell"); ++ deobfuscationMap.put("illager_wizard_b", "spellcaster_cast_spell"); ++ deobfuscationMap.put("llama_a", "llama_attack_wolf"); ++ deobfuscationMap.put("llama_c", "llama_hurt_by"); ++ deobfuscationMap.put("llama_trader_a", "llamatrader_defended_wandering_trader"); ++ deobfuscationMap.put("monster_patrolling_a", "long_distance_patrol"); ++ deobfuscationMap.put("ocelot_a", "ocelot_avoid_entity"); ++ deobfuscationMap.put("ocelot_b", "ocelot_tempt"); ++ deobfuscationMap.put("panda_b", "panda_attack"); ++ deobfuscationMap.put("panda_c", "panda_avoid"); ++ deobfuscationMap.put("panda_d", "panda_breed"); ++ deobfuscationMap.put("panda_e", "panda_hurt_by_target"); ++ deobfuscationMap.put("panda_f", "panda_lie_on_back"); ++ deobfuscationMap.put("panda_g", "panda_look_at_player"); ++ deobfuscationMap.put("panda_i", "panda_panic"); ++ deobfuscationMap.put("panda_j", "panda_roll"); ++ deobfuscationMap.put("panda_k", "panda_sit"); ++ deobfuscationMap.put("panda_l", "panda_sneeze"); ++ deobfuscationMap.put("phantom_b", "phantom_attack_player"); ++ deobfuscationMap.put("phantom_c", "phantom_attack_strategy"); ++ deobfuscationMap.put("phantom_e", "phantom_circle_around_anchor"); ++ deobfuscationMap.put("phantom_i", "phantom_sweep_attack"); ++ deobfuscationMap.put("polar_bear_a", "polarbear_attack_players"); ++ deobfuscationMap.put("polar_bear_b", "polarbear_hurt_by"); ++ deobfuscationMap.put("polar_bear_c", "polarbear_melee"); ++ deobfuscationMap.put("polar_bear_d", "polarbear_panic"); ++ deobfuscationMap.put("puffer_fish_a", "pufferfish_puff"); ++ deobfuscationMap.put("raider_a", "raider_hold_ground"); ++ deobfuscationMap.put("raider_b", "raider_obtain_banner"); ++ deobfuscationMap.put("raider_c", "raider_celebration"); ++ deobfuscationMap.put("raider_d", "raider_move_through_village"); ++ deobfuscationMap.put("ravager_a", "ravager_melee_attack"); ++ deobfuscationMap.put("shulker_a", "shulker_attack"); ++ deobfuscationMap.put("shulker_c", "shulker_defense"); ++ deobfuscationMap.put("shulker_d", "shulker_nearest"); ++ deobfuscationMap.put("shulker_e", "shulker_peek"); ++ deobfuscationMap.put("squid_a", "squid_flee"); ++ deobfuscationMap.put("skeleton_abstract_1", "skeleton_melee"); ++ deobfuscationMap.put("strider_a", "strider_go_to_lava"); ++ deobfuscationMap.put("turtle_a", "turtle_breed"); ++ deobfuscationMap.put("turtle_b", "turtle_go_home"); ++ deobfuscationMap.put("turtle_c", "turtle_goto_water"); ++ deobfuscationMap.put("turtle_d", "turtle_lay_egg"); ++ deobfuscationMap.put("turtle_f", "turtle_panic"); ++ deobfuscationMap.put("turtle_h", "turtle_random_stroll"); ++ deobfuscationMap.put("turtle_i", "turtle_tempt"); ++ deobfuscationMap.put("turtle_j", "turtle_travel"); ++ deobfuscationMap.put("vex_a", "vex_charge_attack"); ++ deobfuscationMap.put("vex_b", "vex_copy_target_of_owner"); ++ deobfuscationMap.put("vex_d", "vex_random_move"); ++ deobfuscationMap.put("villager_trader_a", "villagertrader_wander_to_position"); ++ deobfuscationMap.put("vindicator_a", "vindicator_break_door"); ++ deobfuscationMap.put("vindicator_b", "vindicator_johnny_attack"); ++ deobfuscationMap.put("vindicator_c", "vindicator_melee_attack"); ++ deobfuscationMap.put("wither_a", "wither_do_nothing"); ++ deobfuscationMap.put("wolf_a", "wolf_avoid_entity"); ++ deobfuscationMap.put("zombie_a", "zombie_attack_turtle_egg"); ++ ++ ignored.add("selector_1"); ++ ignored.add("selector_2"); ++ ignored.add("wrapped"); ++ ++ bukkitMap.put(EntityInsentient.class, Mob.class); ++ bukkitMap.put(EntityAgeable.class, Ageable.class); ++ bukkitMap.put(EntityAmbient.class, Ambient.class); ++ bukkitMap.put(EntityAnimal.class, Animals.class); ++ bukkitMap.put(EntityBat.class, Bat.class); ++ bukkitMap.put(EntityBee.class, Bee.class); ++ bukkitMap.put(EntityBlaze.class, Blaze.class); ++ bukkitMap.put(EntityCat.class, Cat.class); ++ bukkitMap.put(EntityCaveSpider.class, CaveSpider.class); ++ bukkitMap.put(EntityChicken.class, Chicken.class); ++ bukkitMap.put(EntityCod.class, Cod.class); ++ bukkitMap.put(EntityCow.class, Cow.class); ++ bukkitMap.put(EntityCreature.class, Creature.class); ++ bukkitMap.put(EntityCreeper.class, Creeper.class); ++ bukkitMap.put(EntityDolphin.class, Dolphin.class); ++ bukkitMap.put(EntityDrowned.class, Drowned.class); ++ bukkitMap.put(EntityEnderDragon.class, EnderDragon.class); ++ bukkitMap.put(EntityEnderman.class, Enderman.class); ++ bukkitMap.put(EntityEndermite.class, Endermite.class); ++ bukkitMap.put(EntityEvoker.class, Evoker.class); ++ bukkitMap.put(EntityFish.class, Fish.class); ++ bukkitMap.put(EntityFishSchool.class, Fish.class); // close enough ++ bukkitMap.put(EntityFlying.class, Flying.class); ++ bukkitMap.put(EntityFox.class, Fox.class); ++ bukkitMap.put(EntityGhast.class, Ghast.class); ++ bukkitMap.put(EntityGiantZombie.class, Giant.class); ++ bukkitMap.put(EntityGolem.class, Golem.class); ++ bukkitMap.put(EntityGuardian.class, Guardian.class); ++ bukkitMap.put(EntityGuardianElder.class, ElderGuardian.class); ++ bukkitMap.put(EntityHorse.class, Horse.class); ++ bukkitMap.put(EntityHorseAbstract.class, AbstractHorse.class); ++ bukkitMap.put(EntityHorseChestedAbstract.class, ChestedHorse.class); ++ bukkitMap.put(EntityHorseDonkey.class, Donkey.class); ++ bukkitMap.put(EntityHorseMule.class, Mule.class); ++ bukkitMap.put(EntityHorseSkeleton.class, SkeletonHorse.class); ++ bukkitMap.put(EntityHorseZombie.class, ZombieHorse.class); ++ bukkitMap.put(EntityIllagerAbstract.class, Illager.class); ++ bukkitMap.put(EntityIllagerIllusioner.class, Illusioner.class); ++ bukkitMap.put(EntityIllagerWizard.class, Spellcaster.class); ++ bukkitMap.put(EntityIronGolem.class, IronGolem.class); ++ bukkitMap.put(EntityLlama.class, Llama.class); ++ bukkitMap.put(EntityLlamaTrader.class, TraderLlama.class); ++ bukkitMap.put(EntityMagmaCube.class, MagmaCube.class); ++ bukkitMap.put(EntityMonster.class, Monster.class); ++ bukkitMap.put(EntityMonsterPatrolling.class, Monster.class); // close enough ++ bukkitMap.put(EntityMushroomCow.class, MushroomCow.class); ++ bukkitMap.put(EntityOcelot.class, Ocelot.class); ++ bukkitMap.put(EntityPanda.class, Panda.class); ++ bukkitMap.put(EntityParrot.class, Parrot.class); ++ bukkitMap.put(EntityPerchable.class, Parrot.class); // close enough ++ bukkitMap.put(EntityPhantom.class, Phantom.class); ++ bukkitMap.put(EntityPig.class, Pig.class); ++ bukkitMap.put(EntityPigZombie.class, PigZombie.class); ++ bukkitMap.put(EntityPillager.class, Pillager.class); ++ bukkitMap.put(EntityPolarBear.class, PolarBear.class); ++ bukkitMap.put(EntityPufferFish.class, PufferFish.class); ++ bukkitMap.put(EntityRabbit.class, Rabbit.class); ++ bukkitMap.put(EntityRaider.class, Raider.class); ++ bukkitMap.put(EntityRavager.class, Ravager.class); ++ bukkitMap.put(EntitySalmon.class, Salmon.class); ++ bukkitMap.put(EntitySheep.class, Sheep.class); ++ bukkitMap.put(EntityShulker.class, Shulker.class); ++ bukkitMap.put(EntitySilverfish.class, Silverfish.class); ++ bukkitMap.put(EntitySkeleton.class, Skeleton.class); ++ bukkitMap.put(EntitySkeletonAbstract.class, Skeleton.class); ++ bukkitMap.put(EntitySkeletonStray.class, Stray.class); ++ bukkitMap.put(EntitySkeletonWither.class, WitherSkeleton.class); ++ bukkitMap.put(EntitySlime.class, Slime.class); ++ bukkitMap.put(EntitySnowman.class, Snowman.class); ++ bukkitMap.put(EntitySpider.class, Spider.class); ++ bukkitMap.put(EntitySquid.class, Squid.class); ++ bukkitMap.put(EntityTameableAnimal.class, Tameable.class); ++ bukkitMap.put(EntityTropicalFish.class, TropicalFish.class); ++ bukkitMap.put(EntityTurtle.class, Turtle.class); ++ bukkitMap.put(EntityVex.class, Vex.class); ++ bukkitMap.put(EntityVillager.class, Villager.class); ++ bukkitMap.put(EntityVillagerAbstract.class, AbstractVillager.class); ++ bukkitMap.put(EntityVillagerTrader.class, WanderingTrader.class); ++ bukkitMap.put(EntityVindicator.class, Vindicator.class); ++ bukkitMap.put(EntityWaterAnimal.class, WaterMob.class); ++ bukkitMap.put(EntityWitch.class, Witch.class); ++ bukkitMap.put(EntityWither.class, Wither.class); ++ bukkitMap.put(EntityWolf.class, Wolf.class); ++ bukkitMap.put(EntityZombie.class, Zombie.class); ++ bukkitMap.put(EntityZombieHusk.class, Husk.class); ++ bukkitMap.put(EntityZombieVillager.class, ZombieVillager.class); ++ bukkitMap.put(EntityHoglin.class, Hoglin.class); ++ bukkitMap.put(EntityPiglin.class, Piglin.class); ++ bukkitMap.put(EntityPiglinAbstract.class, PiglinAbstract.class); ++ bukkitMap.put(EntityPiglinBrute.class, PiglinBrute.class); ++ bukkitMap.put(EntityStrider.class, Strider.class); ++ bukkitMap.put(EntityZoglin.class, Zoglin.class); ++ } ++ ++ public static String getUsableName(Class clazz) { ++ String name = clazz.getName(); ++ name = name.substring(name.lastIndexOf(".") + 1); ++ boolean flag = false; ++ // inner classes ++ if (name.contains("$")) { ++ String cut = name.substring(name.indexOf("$") + 1); ++ if (cut.length() <= 2) { ++ name = name.replace("Entity", ""); ++ name = name.replace("$", "_"); ++ flag = true; ++ } else { ++ // mapped, wooo ++ name = cut; ++ } ++ } ++ name = name.replace("PathfinderGoal", ""); ++ StringBuilder sb = new StringBuilder(); ++ for (char c : name.toCharArray()) { ++ if (c >= 'A' && c <= 'Z') { ++ sb.append("_"); ++ sb.append(Character.toLowerCase(c)); ++ } else { ++ sb.append(c); ++ } ++ } ++ name = sb.toString(); ++ name = name.replaceFirst("_", ""); ++ ++ if (flag && !deobfuscationMap.containsKey(name.toLowerCase()) && !ignored.contains(name)) { ++ System.out.println("need to map " + clazz.getName() + " (" + name.toLowerCase() + ")"); ++ } ++ ++ // did we rename this key? ++ return deobfuscationMap.getOrDefault(name, name); ++ } ++ ++ public static EnumSet vanillaToPaper(OptimizedSmallEnumSet types) { ++ EnumSet goals = EnumSet.noneOf(GoalType.class); ++ for (GoalType type : GoalType.values()) { ++ if (types.hasElement(paperToVanilla(type))) { ++ goals.add(type); ++ } ++ } ++ return goals; ++ } ++ ++ public static GoalType vanillaToPaper(PathfinderGoal.Type type) { ++ switch (type) { ++ case MOVE: ++ return GoalType.MOVE; ++ case LOOK: ++ return GoalType.LOOK; ++ case JUMP: ++ return GoalType.JUMP; ++ case UNKNOWN_BEHAVIOR: ++ return GoalType.UNKNOWN_BEHAVIOR; ++ case TARGET: ++ return GoalType.TARGET; ++ default: ++ throw new IllegalArgumentException("Unknown vanilla mob goal type " + type.name()); ++ } ++ } ++ ++ public static EnumSet paperToVanilla(EnumSet types) { ++ EnumSet goals = EnumSet.noneOf(PathfinderGoal.Type.class); ++ for (GoalType type : types) { ++ goals.add(paperToVanilla(type)); ++ } ++ return goals; ++ } ++ ++ public static PathfinderGoal.Type paperToVanilla(GoalType type) { ++ switch (type) { ++ case MOVE: ++ return PathfinderGoal.Type.MOVE; ++ case LOOK: ++ return PathfinderGoal.Type.LOOK; ++ case JUMP: ++ return PathfinderGoal.Type.JUMP; ++ case UNKNOWN_BEHAVIOR: ++ return PathfinderGoal.Type.UNKNOWN_BEHAVIOR; ++ case TARGET: ++ return PathfinderGoal.Type.TARGET; ++ default: ++ throw new IllegalArgumentException("Unknown paper mob goal type " + type.name()); ++ } ++ } ++ ++ public static GoalKey getKey(Class goalClass) { ++ String name = getUsableName(goalClass); ++ if (ignored.contains(name)) { ++ //noinspection unchecked ++ return (GoalKey) GoalKey.of(Mob.class, NamespacedKey.minecraft(name)); ++ } ++ return GoalKey.of(getEntity(goalClass), NamespacedKey.minecraft(name)); ++ } ++ ++ public static Class getEntity(Class goalClass) { ++ //noinspection unchecked ++ return (Class) entityClassCache.computeIfAbsent(goalClass, key -> { ++ for (Constructor ctor : key.getDeclaredConstructors()) { ++ for (int i = 0; i < ctor.getParameterCount(); i++) { ++ Class param = ctor.getParameterTypes()[i]; ++ if (EntityInsentient.class.isAssignableFrom(param)) { ++ //noinspection unchecked ++ return toBukkitClass((Class) param); ++ } else if (IRangedEntity.class.isAssignableFrom(param)) { ++ return RangedEntity.class; ++ } ++ } ++ } ++ throw new RuntimeException("Can't figure out applicable entity for mob goal " + goalClass); // maybe just return EntityInsentient? ++ }); ++ } ++ ++ public static Class toBukkitClass(Class nmsClass) { ++ Class bukkitClass = bukkitMap.get(nmsClass); ++ if (bukkitClass == null) { ++ throw new RuntimeException("Can't figure out applicable bukkit entity for nms entity " + nmsClass); // maybe just return Mob? ++ } ++ return bukkitClass; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0b963f80857209bc73ece917203447d8839860b6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java +@@ -0,0 +1,54 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import net.minecraft.world.entity.ai.goal.PathfinderGoal; ++import org.bukkit.entity.Mob; ++ ++/** ++ * Wraps api in vanilla ++ */ ++public class PaperCustomGoal extends PathfinderGoal { ++ ++ private final Goal handle; ++ ++ public PaperCustomGoal(Goal handle) { ++ this.handle = handle; ++ ++ this.setTypes(MobGoalHelper.paperToVanilla(handle.getTypes())); ++ if (this.getGoalTypes().size() == 0) { ++ this.getGoalTypes().addUnchecked(Type.UNKNOWN_BEHAVIOR); ++ } ++ } ++ ++ @Override ++ public boolean shouldActivate() { ++ return handle.shouldActivate(); ++ } ++ ++ @Override ++ public boolean shouldStayActive() { ++ return handle.shouldStayActive(); ++ } ++ ++ @Override ++ public void start() { ++ handle.start(); ++ } ++ ++ @Override ++ public void onTaskReset() { ++ handle.stop(); ++ } ++ ++ @Override ++ public void tick() { ++ handle.tick(); ++ } ++ ++ public Goal getHandle() { ++ return handle; ++ } ++ ++ public GoalKey getKey() { ++ return handle.getKey(); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bf792c013fe3b9a0b5800a35308b9aaa36e5350d +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java +@@ -0,0 +1,222 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import java.util.Collection; ++import java.util.EnumSet; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.LinkedList; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import net.minecraft.world.entity.ai.goal.PathfinderGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalSelector; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalWrapped; ++import org.bukkit.craftbukkit.entity.CraftMob; ++import org.bukkit.entity.Mob; ++ ++public class PaperMobGoals implements MobGoals { ++ ++ private final Map> instanceCache = new HashMap<>(); ++ ++ @Override ++ public void addGoal(T mob, int priority, Goal goal) { ++ CraftMob craftMob = (CraftMob) mob; ++ getHandle(craftMob, goal.getTypes()).addGoal(priority, new PaperCustomGoal<>(goal)); ++ } ++ ++ @Override ++ public void removeGoal(T mob, Goal goal) { ++ CraftMob craftMob = (CraftMob) mob; ++ if (goal instanceof PaperCustomGoal) { ++ getHandle(craftMob, goal.getTypes()).removeGoal((PathfinderGoal) goal); ++ } else if (goal instanceof PaperVanillaGoal) { ++ getHandle(craftMob, goal.getTypes()).removeGoal(((PaperVanillaGoal) goal).getHandle()); ++ } else { ++ List toRemove = new LinkedList<>(); ++ for (PathfinderGoalWrapped item : getHandle(craftMob, goal.getTypes()).getTasks()) { ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ if (((PaperCustomGoal) item.getGoal()).getHandle() == goal) { ++ toRemove.add(item.getGoal()); ++ } ++ } ++ } ++ ++ for (PathfinderGoal g : toRemove) { ++ getHandle(craftMob, goal.getTypes()).removeGoal(g); ++ } ++ } ++ } ++ ++ @Override ++ public void removeAllGoals(T mob) { ++ for (GoalType type : GoalType.values()) { ++ removeAllGoals(mob, type); ++ } ++ } ++ ++ @Override ++ public void removeAllGoals(T mob, GoalType type) { ++ for (Goal goal : getAllGoals(mob, type)) { ++ removeGoal(mob, goal); ++ } ++ } ++ ++ @Override ++ public void removeGoal(T mob, GoalKey key) { ++ for (Goal goal : getGoals(mob, key)) { ++ removeGoal(mob, goal); ++ } ++ } ++ ++ @Override ++ public boolean hasGoal(T mob, GoalKey key) { ++ for (Goal g : getAllGoals(mob)) { ++ if (g.getKey().equals(key)) { ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ @Override ++ public Goal getGoal(T mob, GoalKey key) { ++ for (Goal g : getAllGoals(mob)) { ++ if (g.getKey().equals(key)) { ++ return g; ++ } ++ } ++ return null; ++ } ++ ++ @Override ++ public Collection> getGoals(T mob, GoalKey key) { ++ Set> goals = new HashSet<>(); ++ for (Goal g : getAllGoals(mob)) { ++ if (g.getKey().equals(key)) { ++ goals.add(g); ++ } ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getAllGoals(T mob) { ++ Set> goals = new HashSet<>(); ++ for (GoalType type : GoalType.values()) { ++ goals.addAll(getAllGoals(mob, type)); ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getAllGoals(T mob, GoalType type) { ++ CraftMob craftMob = (CraftMob) mob; ++ Set> goals = new HashSet<>(); ++ for (PathfinderGoalWrapped item : getHandle(craftMob, type).getTasks()) { ++ if (!item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { ++ continue; ++ } ++ ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); ++ } else { ++ //noinspection unchecked ++ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); ++ } ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getAllGoalsWithout(T mob, GoalType type) { ++ CraftMob craftMob = (CraftMob) mob; ++ Set> goals = new HashSet<>(); ++ for (GoalType internalType : GoalType.values()) { ++ if (internalType == type) { ++ continue; ++ } ++ for (PathfinderGoalWrapped item : getHandle(craftMob, internalType).getTasks()) { ++ if (item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { ++ continue; ++ } ++ ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); ++ } else { ++ //noinspection unchecked ++ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); ++ } ++ } ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getRunningGoals(T mob) { ++ Set> goals = new HashSet<>(); ++ for (GoalType type : GoalType.values()) { ++ goals.addAll(getRunningGoals(mob, type)); ++ } ++ return goals; ++ } ++ ++ @Override ++ public Collection> getRunningGoals(T mob, GoalType type) { ++ CraftMob craftMob = (CraftMob) mob; ++ Set> goals = new HashSet<>(); ++ getHandle(craftMob, type).getExecutingGoals() ++ .filter(item -> item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) ++ .forEach(item -> { ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); ++ } else { ++ //noinspection unchecked ++ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); ++ } ++ }); ++ return goals; ++ } ++ ++ @Override ++ public Collection> getRunningGoalsWithout(T mob, GoalType type) { ++ CraftMob craftMob = (CraftMob) mob; ++ Set> goals = new HashSet<>(); ++ for (GoalType internalType : GoalType.values()) { ++ if (internalType == type) { ++ continue; ++ } ++ getHandle(craftMob, internalType).getExecutingGoals() ++ .filter(item -> !item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) ++ .forEach(item -> { ++ if (item.getGoal() instanceof PaperCustomGoal) { ++ //noinspection unchecked ++ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); ++ } else { ++ //noinspection unchecked ++ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); ++ } ++ }); ++ } ++ return goals; ++ } ++ ++ private PathfinderGoalSelector getHandle(CraftMob mob, EnumSet types) { ++ if (types.contains(GoalType.TARGET)) { ++ return mob.getHandle().targetSelector; ++ } else { ++ return mob.getHandle().goalSelector; ++ } ++ } ++ ++ private PathfinderGoalSelector getHandle(CraftMob mob, GoalType type) { ++ if (type == GoalType.TARGET) { ++ return mob.getHandle().targetSelector; ++ } else { ++ return mob.getHandle().goalSelector; ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1ed6e7273bc84a406ca843bc47bb69314bb2dd74 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java +@@ -0,0 +1,62 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import java.util.EnumSet; ++ ++import net.minecraft.world.entity.ai.goal.PathfinderGoal; ++import org.bukkit.entity.Mob; ++ ++/** ++ * Wraps vanilla in api ++ */ ++public class PaperVanillaGoal implements VanillaGoal { ++ ++ private final PathfinderGoal handle; ++ private final GoalKey key; ++ ++ private final EnumSet types; ++ ++ public PaperVanillaGoal(PathfinderGoal handle) { ++ this.handle = handle; ++ this.key = MobGoalHelper.getKey(handle.getClass()); ++ this.types = MobGoalHelper.vanillaToPaper(handle.getGoalTypes()); ++ } ++ ++ public PathfinderGoal getHandle() { ++ return handle; ++ } ++ ++ @Override ++ public boolean shouldActivate() { ++ return handle.shouldActivate2(); ++ } ++ ++ @Override ++ public boolean shouldStayActive() { ++ return handle.shouldStayActive2(); ++ } ++ ++ @Override ++ public void start() { ++ handle.start(); ++ } ++ ++ @Override ++ public void stop() { ++ handle.onTaskReset(); ++ } ++ ++ @Override ++ public void tick() { ++ handle.tick(); ++ } ++ ++ @Override ++ public GoalKey getKey() { ++ return key; ++ } ++ ++ @Override ++ public EnumSet getTypes() { ++ return types; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java +index 9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f..b3329c6fcd6758a781a51f5ba8f5052ac1c77b49 100644 +--- a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java ++++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java +@@ -64,4 +64,8 @@ public final class OptimizedSmallEnumSet> { + public boolean hasCommonElements(final OptimizedSmallEnumSet other) { + return (other.backingSet & this.backingSet) != 0; + } ++ ++ public boolean hasElement(final E element) { ++ return (this.backingSet & (1L << element.ordinal())) != 0; ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java +index 5c32cbe81c47fcb9ae347faa6fc007c5d28d79bf..59ea1432152051ce8a60c0a526db787593f0e744 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java +@@ -8,11 +8,17 @@ public abstract class PathfinderGoal { + private final EnumSet a = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. + private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector + +- public PathfinderGoal() {} ++ // Paper start make sure goaltypes is never empty ++ public PathfinderGoal() { ++ if (this.goalTypes.size() == 0) { ++ this.goalTypes.addUnchecked(Type.UNKNOWN_BEHAVIOR); ++ } ++ } ++ // paper end + +- public abstract boolean a(); ++ public boolean a() { return this.shouldActivate(); } public boolean shouldActivate() { return false;} public boolean shouldActivate2() { return a(); } // Paper - OBFHELPER, for both directions... + +- public boolean b() { ++ public boolean b() { return this.shouldStayActive(); } public boolean shouldStayActive2() { return b(); } public boolean shouldStayActive() { // Paper - OBFHELPER, for both directions... + return this.a(); + } + +@@ -20,19 +26,23 @@ public abstract class PathfinderGoal { + return true; + } + +- public void c() {} ++ public void c() { this.start(); } public void start() {} // Paper - OBFHELPER + + public void d() { + onTaskReset(); // Paper + } + public void onTaskReset() {} // Paper + +- public void e() {} ++ public void e() { this.tick(); } public void tick() {} // Paper OBFHELPER + +- public void a(EnumSet enumset) { ++ public void a(EnumSet enumset) { this.setTypes(enumset); } public void setTypes(EnumSet enumset) { // Paper - OBFHELPER + // Paper start - remove streams from pathfindergoalselector + this.goalTypes.clear(); + this.goalTypes.addAllUnchecked(enumset); ++ // make sure its never empty ++ if (this.goalTypes.size() == 0) { ++ this.goalTypes.addUnchecked(Type.UNKNOWN_BEHAVIOR); ++ } + // Paper end - remove streams from pathfindergoalselector + } + +@@ -48,7 +58,7 @@ public abstract class PathfinderGoal { + + public static enum Type { + +- MOVE, LOOK, JUMP, TARGET; ++ MOVE, LOOK, JUMP, TARGET, UNKNOWN_BEHAVIOR; // Paper - add unknown + + private Type() {} + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java +index 385cd079e264a7e66e91ab3b70b90afb59688dcd..637928664f8c7b1c694a234e507c20724294e450 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java +@@ -28,7 +28,7 @@ public class PathfinderGoalSelector { + } + }; + private final Map c = new EnumMap(PathfinderGoal.Type.class); +- private final Set d = Sets.newLinkedHashSet(); private Set getTasks() { return d; }// Paper - OBFHELPER ++ private final Set d = Sets.newLinkedHashSet(); public final Set getTasks() { return d; }// Paper - OBFHELPER // Paper - private -> public + private final Supplier e; + private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. + private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector +@@ -39,7 +39,7 @@ public class PathfinderGoalSelector { + this.e = supplier; + } + +- public void a(int i, PathfinderGoal pathfindergoal) { ++ public void addGoal(int priority, PathfinderGoal goal) {a(priority, goal);} public void a(int i, PathfinderGoal pathfindergoal) { // Paper - OBFHELPER + this.d.add(new PathfinderGoalWrapped(i, pathfindergoal)); + } + +@@ -58,7 +58,7 @@ public class PathfinderGoalSelector { + } + // Paper end + +- public void a(PathfinderGoal pathfindergoal) { ++ public void removeGoal(PathfinderGoal goal) {a(goal);} public void a(PathfinderGoal pathfindergoal) { // Paper - OBFHELPER + // Paper start - remove streams from pathfindergoalselector + for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { + PathfinderGoalWrapped goalWrapped = iterator.next(); +@@ -154,6 +154,7 @@ public class PathfinderGoalSelector { + gameprofilerfiller.exit(); + } + ++ public final Stream getExecutingGoals() { return d(); } // Paper - OBFHELPER + public Stream d() { + return this.d.stream().filter(PathfinderGoalWrapped::g); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java +index 8c8e39d35fb56aa6cf7d456adab01dff5d13a60d..bcf6c924894f49f1c602b83b501f904e553235fd 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java +@@ -5,8 +5,8 @@ import javax.annotation.Nullable; + + public class PathfinderGoalWrapped extends PathfinderGoal { + +- private final PathfinderGoal a; +- private final int b; ++ private final PathfinderGoal a; public PathfinderGoal getGoal() {return a;} // Paper - OBFHELPER ++ private final int b; public int getPriority() {return b;} // Paper - OBFHELPER + private boolean c; + + public PathfinderGoalWrapped(int i, PathfinderGoal pathfindergoal) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index f6e2e54b5a1b8c2df41a0593fa15112c5195c49c..aa5efc9225bb58f9290b9aefcb5ef171c7a88e7d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2391,5 +2391,11 @@ public final class CraftServer implements Server { + public boolean isStopping() { + return net.minecraft.server.MinecraftServer.getServer().hasStopped(); + } ++ ++ private com.destroystokyo.paper.entity.ai.MobGoals mobGoals = new com.destroystokyo.paper.entity.ai.PaperMobGoals(); ++ @Override ++ public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { ++ return mobGoals; ++ } + // Paper end + } +diff --git a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c0525216a8469613c3e0d4b5774a82f69e70fb16 +--- /dev/null ++++ b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java +@@ -0,0 +1,104 @@ ++package com.destroystokyo.paper.entity.ai; ++ ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.entity.ai.goal.PathfinderGoal; ++import org.junit.Assert; ++import org.junit.Test; ++ ++import java.lang.reflect.Field; ++import java.lang.reflect.Modifier; ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++import java.util.stream.Collectors; ++ ++import org.bukkit.entity.Mob; ++ ++import io.github.classgraph.ClassGraph; ++import io.github.classgraph.ScanResult; ++ ++public class VanillaMobGoalTest { ++ ++ @Test ++ public void testKeys() { ++ List> deprecated = new ArrayList<>(); ++ List> keys = new ArrayList<>(); ++ for (Field field : VanillaGoal.class.getFields()) { ++ if (field.getType().equals(GoalKey.class)) { ++ try { ++ GoalKey goalKey = (GoalKey) field.get(null); ++ if (field.getAnnotation(Deprecated.class) != null) { ++ deprecated.add(goalKey); ++ } else { ++ keys.add(goalKey); ++ } ++ } catch (IllegalAccessException e) { ++ System.out.println("Skipping " + field.getName() + ": " + e.getMessage()); ++ } ++ } ++ } ++ ++ List> classes; ++ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) { ++ classes = scanResult.getSubclasses(PathfinderGoal.class.getName()).loadClasses(); ++ } ++ ++ List> vanillaNames = classes.stream() ++ .filter(VanillaMobGoalTest::hasNoEnclosingClass) ++ .filter(clazz -> !Modifier.isAbstract(clazz.getModifiers())) ++ .map(goalClass -> MobGoalHelper.getKey((Class) goalClass)) ++ .collect(Collectors.toList()); ++ ++ List> missingFromAPI = new ArrayList<>(vanillaNames); ++ missingFromAPI.removeAll(keys); ++ missingFromAPI.removeIf(k -> MobGoalHelper.ignored.contains(k.getNamespacedKey().getKey())); ++ List> missingFromVanilla = new ArrayList<>(keys); ++ missingFromVanilla.removeAll(vanillaNames); ++ ++ boolean shouldFail = false; ++ if (missingFromAPI.size() != 0) { ++ System.out.println("Missing from API: "); ++ for (GoalKey key : missingFromAPI) { ++ System.out.println("GoalKey<" + key.getEntityClass().getSimpleName() + "> " + key.getNamespacedKey().getKey().toUpperCase() + ++ " = GoalKey.of(" + key.getEntityClass().getSimpleName() + ".class, NamespacedKey.minecraft(\"" + key.getNamespacedKey().getKey() + "\"));"); ++ } ++ shouldFail = true; ++ } ++ if (missingFromVanilla.size() != 0) { ++ System.out.println("Missing from vanilla: "); ++ missingFromVanilla.forEach(System.out::println); ++ shouldFail = true; ++ } ++ ++ if (deprecated.size() != 0) { ++ System.out.println("Deprecated (might want to remove them at some point): "); ++ deprecated.forEach(System.out::println); ++ } ++ ++ if (shouldFail) Assert.fail("See above"); ++ } ++ ++ private static boolean hasNoEnclosingClass(Class clazz) { ++ return clazz.getEnclosingClass() == null || hasNoEnclosingClass(clazz.getSuperclass()); ++ } ++ ++ @Test ++ public void testBukkitMap() { ++ List> classes; ++ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft.world.entity").scan()) { ++ classes = scanResult.getSubclasses("net.minecraft.world.entity.EntityInsentient").loadClasses(); ++ } ++ Assert.assertNotEquals("There are supposed to be more than 0 entity types!", Collections.emptyList(), classes); ++ ++ boolean shouldFail = false; ++ for (Class nmsClass : classes) { ++ Class bukkitClass = MobGoalHelper.toBukkitClass((Class) nmsClass); ++ if (bukkitClass == null) { ++ shouldFail = true; ++ System.out.println("Missing bukkitMap.put(" + nmsClass.getSimpleName() + ".class, " + nmsClass.getSimpleName().replace("Entity", "") + ".class);"); ++ } ++ } ++ ++ if (shouldFail) Assert.fail("See above"); ++ } ++} diff --git a/patches/server-unmapped/0465-Use-distance-map-to-optimise-entity-tracker.patch b/patches/server-unmapped/0465-Use-distance-map-to-optimise-entity-tracker.patch new file mode 100644 index 0000000000..0eecb7f13e --- /dev/null +++ b/patches/server-unmapped/0465-Use-distance-map-to-optimise-entity-tracker.patch @@ -0,0 +1,413 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 5 May 2020 20:18:05 -0700 +Subject: [PATCH] Use distance map to optimise entity tracker + +Use the distance map to find candidate players for tracking. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 7f67773686a2d55153f7b2bfbe24df84fe1198be..1eb1da61ee2aa2cc5d28a46fd364a182cd16983b 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1654,6 +1654,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant list = this.tracker.getPassengers(); + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index d509cfd2da99233e5142abd176cc50ccea7c32b6..9fc74f08b912ff885c9478167c7ef173c32f1654 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -61,6 +61,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; + import net.minecraft.network.protocol.game.PacketPlayOutMount; + import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; + import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.progress.WorldLoadListener; + import net.minecraft.util.CSVWriter; + import net.minecraft.util.EntitySlice; +@@ -195,21 +196,55 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + // Paper start - distance maps + private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); ++ // Paper start - use distance map to optimise tracker ++ public static boolean isLegacyTrackingEntity(Entity entity) { ++ return entity.isLegacyTrackingEntity; ++ } ++ ++ // inlined EnumMap, TrackingRange.TrackingRangeType ++ static final org.spigotmc.TrackingRange.TrackingRangeType[] TRACKING_RANGE_TYPES = org.spigotmc.TrackingRange.TrackingRangeType.values(); ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap[] playerEntityTrackerTrackMaps; ++ final int[] entityTrackerTrackRanges; ++ ++ private int convertSpigotRangeToVanilla(final int vanilla) { ++ return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); ++ } ++ // Paper end - use distance map to optimise tracker + + void addPlayerToDistanceMaps(EntityPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.locX()); + int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); + // Note: players need to be explicitly added to distance maps before they can be updated ++ // Paper start - use distance map to optimise entity tracker ++ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { ++ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; ++ int trackRange = this.entityTrackerTrackRanges[i]; ++ ++ trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); ++ } ++ // Paper end - use distance map to optimise entity tracker + } + + void removePlayerFromDistanceMaps(EntityPlayer player) { +- ++ // Paper start - use distance map to optimise tracker ++ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { ++ this.playerEntityTrackerTrackMaps[i].remove(player); ++ } ++ // Paper end - use distance map to optimise tracker + } + + void updateMaps(EntityPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.locX()); + int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); + // Note: players need to be explicitly added to distance maps before they can be updated ++ // Paper start - use distance map to optimise entity tracker ++ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { ++ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; ++ int trackRange = this.entityTrackerTrackRanges[i]; ++ ++ trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); ++ } ++ // Paper end - use distance map to optimise entity tracker + } + // Paper end + +@@ -246,6 +281,45 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper + this.setViewDistance(i); + this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper ++ // Paper start - use distance map to optimise entity tracker ++ this.playerEntityTrackerTrackMaps = new com.destroystokyo.paper.util.misc.PlayerAreaMap[TRACKING_RANGE_TYPES.length]; ++ this.entityTrackerTrackRanges = new int[TRACKING_RANGE_TYPES.length]; ++ ++ org.spigotmc.SpigotWorldConfig spigotWorldConfig = this.world.spigotConfig; ++ ++ for (int ordinal = 0, len = TRACKING_RANGE_TYPES.length; ordinal < len; ++ordinal) { ++ org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = TRACKING_RANGE_TYPES[ordinal]; ++ int configuredSpigotValue; ++ switch (trackingRangeType) { ++ case PLAYER: ++ configuredSpigotValue = spigotWorldConfig.playerTrackingRange; ++ break; ++ case ANIMAL: ++ configuredSpigotValue = spigotWorldConfig.animalTrackingRange; ++ break; ++ case MONSTER: ++ configuredSpigotValue = spigotWorldConfig.monsterTrackingRange; ++ break; ++ case MISC: ++ configuredSpigotValue = spigotWorldConfig.miscTrackingRange; ++ break; ++ case OTHER: ++ configuredSpigotValue = spigotWorldConfig.otherTrackingRange; ++ break; ++ case ENDERDRAGON: ++ configuredSpigotValue = EntityTypes.ENDER_DRAGON.getChunkRange() * 16; ++ break; ++ default: ++ throw new IllegalStateException("Missing case for enum " + trackingRangeType); ++ } ++ configuredSpigotValue = convertSpigotRangeToVanilla(configuredSpigotValue); ++ ++ int trackRange = (configuredSpigotValue >>> 4) + ((configuredSpigotValue & 15) != 0 ? 1 : 0); ++ this.entityTrackerTrackRanges[ordinal] = trackRange; ++ ++ this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); ++ } ++ // Paper end - use distance map to optimise entity tracker + } + + public void updatePlayerMobTypeMap(Entity entity) { +@@ -1492,17 +1566,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + + public void movePlayer(EntityPlayer entityplayer) { +- ObjectIterator objectiterator = this.trackedEntities.values().iterator(); +- +- while (objectiterator.hasNext()) { +- PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); +- +- if (playerchunkmap_entitytracker.tracker == entityplayer) { +- playerchunkmap_entitytracker.track(this.world.getPlayers()); +- } else { +- playerchunkmap_entitytracker.updatePlayer(entityplayer); +- } +- } ++ // Paper - delay this logic for the entity tracker tick, no need to duplicate it + + int i = MathHelper.floor(entityplayer.locX()) >> 4; + int j = MathHelper.floor(entityplayer.locZ()) >> 4; +@@ -1618,7 +1682,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker + this.trackedEntities.put(entity.getId(), playerchunkmap_entitytracker); +- playerchunkmap_entitytracker.track(this.world.getPlayers()); ++ playerchunkmap_entitytracker.updatePlayers(entity.getPlayersInTrackRange()); // Paper - don't search all players + if (entity instanceof EntityPlayer) { + EntityPlayer entityplayer = (EntityPlayer) entity; + +@@ -1661,7 +1725,37 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + entity.tracker = null; // Paper - We're no longer tracked + } + ++ // Paper start - optimised tracker ++ private final void processTrackQueue() { ++ this.world.timings.tracker1.startTiming(); ++ try { ++ for (EntityTracker tracker : this.trackedEntities.values()) { ++ // update tracker entry ++ tracker.updatePlayers(tracker.tracker.getPlayersInTrackRange()); ++ } ++ } finally { ++ this.world.timings.tracker1.stopTiming(); ++ } ++ ++ ++ this.world.timings.tracker2.startTiming(); ++ try { ++ for (EntityTracker tracker : this.trackedEntities.values()) { ++ tracker.trackerEntry.tick(); ++ } ++ } finally { ++ this.world.timings.tracker2.stopTiming(); ++ } ++ } ++ // Paper end - optimised tracker ++ + protected void g() { ++ // Paper start - optimized tracker ++ if (true) { ++ this.processTrackQueue(); ++ return; ++ } ++ // Paper end - optimized tracker + List list = Lists.newArrayList(); + List list1 = this.world.getPlayers(); + +@@ -1730,23 +1824,31 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + PacketDebug.a(this.world, chunk.getPos()); + List list = Lists.newArrayList(); + List list1 = Lists.newArrayList(); +- ObjectIterator objectiterator = this.trackedEntities.values().iterator(); ++ // Paper start - optimise entity tracker ++ // use the chunk entity list, not the whole trackedEntities map... ++ Entity[] entities = chunk.entities.getRawData(); ++ for (int i = 0, size = chunk.entities.size(); i < size; ++i) { ++ Entity entity = entities[i]; ++ if (entity == entityplayer) { ++ continue; ++ } ++ PlayerChunkMap.EntityTracker tracker = this.trackedEntities.get(entity.getId()); ++ if (tracker != null) { // dumb plugins... move on... ++ tracker.updatePlayer(entityplayer); ++ } + +- while (objectiterator.hasNext()) { +- PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); +- Entity entity = playerchunkmap_entitytracker.tracker; ++ // keep the vanilla logic here - this is REQUIRED or else passengers and their vehicles disappear! ++ // (and god knows what the leash thing is) + +- if (entity != entityplayer && entity.chunkX == chunk.getPos().x && entity.chunkZ == chunk.getPos().z) { +- playerchunkmap_entitytracker.updatePlayer(entityplayer); +- if (entity instanceof EntityInsentient && ((EntityInsentient) entity).getLeashHolder() != null) { +- list.add(entity); +- } ++ if (entity instanceof EntityInsentient && ((EntityInsentient)entity).getLeashHolder() != null) { ++ list.add(entity); ++ } + +- if (!entity.getPassengers().isEmpty()) { +- list1.add(entity); +- } ++ if (!entity.getPassengers().isEmpty()) { ++ list1.add(entity); + } + } ++ // Paper end - optimise entity tracker + + Iterator iterator; + Entity entity1; +@@ -1784,7 +1886,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + public class EntityTracker { + +- private final EntityTrackerEntry trackerEntry; ++ final EntityTrackerEntry trackerEntry; // Paper - private -> package private + private final Entity tracker; + private final int trackingDistance; + private SectionPosition e; +@@ -1801,6 +1903,42 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.e = SectionPosition.a(entity); + } + ++ // Paper start - use distance map to optimise tracker ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet lastTrackerCandidates; ++ ++ final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet oldTrackerCandidates = this.lastTrackerCandidates; ++ this.lastTrackerCandidates = newTrackerCandidates; ++ ++ if (newTrackerCandidates != null) { ++ Object[] rawData = newTrackerCandidates.getBackingSet(); ++ for (int i = 0, len = rawData.length; i < len; ++i) { ++ Object raw = rawData[i]; ++ if (!(raw instanceof EntityPlayer)) { ++ continue; ++ } ++ EntityPlayer player = (EntityPlayer)raw; ++ this.updatePlayer(player); ++ } ++ } ++ ++ if (oldTrackerCandidates == newTrackerCandidates) { ++ // this is likely the case. ++ // means there has been no range changes, so we can just use the above for tracking. ++ return; ++ } ++ ++ // stuff could have been removed, so we need to check the trackedPlayers set ++ // for players that were removed ++ ++ for (EntityPlayer player : this.trackedPlayers.toArray(new EntityPlayer[0])) { // avoid CME ++ if (newTrackerCandidates == null || !newTrackerCandidates.contains(player)) { ++ this.updatePlayer(player); ++ } ++ } ++ } ++ // Paper end - use distance map to optimise tracker ++ + public boolean equals(Object object) { + return object instanceof PlayerChunkMap.EntityTracker ? ((PlayerChunkMap.EntityTracker) object).tracker.getId() == this.tracker.getId() : false; + } +@@ -1901,7 +2039,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + int j = entity.getEntityType().getChunkRange() * 16; + j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper + +- if (j > i) { ++ if (j < i) { // Paper - we need the lowest range thanks to the fact that our tracker doesn't account for passenger logic + i = j; + } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 8d8d94219f9a556212763fce736452a19249ffec..b244f5d204938452ea19335947830de47336bbd4 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -46,6 +46,7 @@ import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.PlayerChunkMap; +@@ -295,6 +296,21 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + // CraftBukkit end + ++ // Paper start - optimise entity tracking ++ final org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = org.spigotmc.TrackingRange.getTrackingRangeType(this); ++ ++ public boolean isLegacyTrackingEntity = false; ++ ++ public final void setLegacyTrackingEntity(final boolean isLegacyTrackingEntity) { ++ this.isLegacyTrackingEntity = isLegacyTrackingEntity; ++ } ++ ++ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayersInTrackRange() { ++ return ((WorldServer)this.world).getChunkProvider().playerChunkMap.playerEntityTrackerTrackMaps[this.trackingRangeType.ordinal()] ++ .getObjectsInRange(MCUtil.getCoordinateKey(this)); ++ } ++ // Paper end - optimise entity tracking ++ + public Entity(EntityTypes entitytypes, World world) { + this.id = Entity.entityCount.incrementAndGet(); + this.passengers = Lists.newArrayList(); +diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java +index 3277a8aaffb6a25624967aa0c62f61309a517739..cd569ad95176fdd0537459b40dfba5c5127a62df 100644 +--- a/src/main/java/org/spigotmc/TrackingRange.java ++++ b/src/main/java/org/spigotmc/TrackingRange.java +@@ -21,6 +21,7 @@ public class TrackingRange + */ + public static int getEntityTrackingRange(Entity entity, int defaultRange) + { ++ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return defaultRange; // Paper - enderdragon is exempt + SpigotWorldConfig config = entity.world.spigotConfig; + if ( entity instanceof EntityPlayer ) + { +@@ -44,8 +45,48 @@ public class TrackingRange + return config.miscTrackingRange; + } else + { +- if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return ((net.minecraft.server.level.WorldServer)(entity.getWorld())).getChunkProvider().playerChunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt + return config.otherTrackingRange; + } + } ++ ++ // Paper start - optimise entity tracking ++ // copied from above, TODO check on update ++ public static TrackingRangeType getTrackingRangeType(Entity entity) ++ { ++ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return TrackingRangeType.ENDERDRAGON; // Paper - enderdragon is exempt ++ if ( entity instanceof EntityPlayer ) ++ { ++ return TrackingRangeType.PLAYER; ++ // Paper start - Simplify and set water mobs to animal tracking range ++ } ++ switch (entity.activationType) { ++ case RAIDER: ++ case MONSTER: ++ case FLYING_MONSTER: ++ return TrackingRangeType.MONSTER; ++ case WATER: ++ case VILLAGER: ++ case ANIMAL: ++ return TrackingRangeType.ANIMAL; ++ case MISC: ++ } ++ if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) ++ // Paper end ++ { ++ return TrackingRangeType.MISC; ++ } else ++ { ++ return TrackingRangeType.OTHER; ++ } ++ } ++ ++ public static enum TrackingRangeType { ++ PLAYER, ++ ANIMAL, ++ MONSTER, ++ MISC, ++ OTHER, ++ ENDERDRAGON; ++ } ++ // Paper end - optimise entity tracking + } diff --git a/patches/server-unmapped/0466-Optimize-isOutsideRange-to-use-distance-maps.patch b/patches/server-unmapped/0466-Optimize-isOutsideRange-to-use-distance-maps.patch new file mode 100644 index 0000000000..9fedfd9a43 --- /dev/null +++ b/patches/server-unmapped/0466-Optimize-isOutsideRange-to-use-distance-maps.patch @@ -0,0 +1,384 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 5 May 2020 20:40:53 -0700 +Subject: [PATCH] Optimize isOutsideRange to use distance maps + +Use a distance map to find the players in range quickly + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +index 60fcea78bf617559114b1ca1c0bf2d4cd9075a8c..335666db1854e8aa4b2ba71d5bdc2658305cb70a 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +@@ -37,7 +37,7 @@ public abstract class ChunkMapDistance { + private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); + public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); + private final ChunkMapDistance.a ticketLevelTracker = new ChunkMapDistance.a(); +- private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); ++ public static final int MOB_SPAWN_RANGE = 8; // private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used + private final ChunkMapDistance.c g = new ChunkMapDistance.c(33); + // Paper start use a queue, but still keep unique requirement + public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { +@@ -56,6 +56,8 @@ public abstract class ChunkMapDistance { + private final Executor m; + private long currentTick; + ++ PlayerChunkMap chunkMap; // Paper ++ + protected ChunkMapDistance(Executor executor, Executor executor1) { + executor1.getClass(); + Mailbox mailbox = Mailbox.a("player ticket throttler", executor1::execute); +@@ -100,7 +102,7 @@ public abstract class ChunkMapDistance { + protected abstract PlayerChunk a(long i, int j, @Nullable PlayerChunk playerchunk, int k); + + public boolean a(PlayerChunkMap playerchunkmap) { +- this.f.a(); ++ //this.f.a(); // Paper - no longer used + this.g.a(); + int i = Integer.MAX_VALUE - this.ticketLevelTracker.a(Integer.MAX_VALUE); + boolean flag = i != 0; +@@ -236,7 +238,7 @@ public abstract class ChunkMapDistance { + ((ObjectSet) this.c.computeIfAbsent(i, (j) -> { + return new ObjectOpenHashSet(); + })).add(entityplayer); +- this.f.update(i, 0, true); ++ //this.f.update(i, 0, true); // Paper - no longer used + this.g.update(i, 0, true); + } + +@@ -248,7 +250,7 @@ public abstract class ChunkMapDistance { + if (objectset != null) objectset.remove(entityplayer); // Paper - some state corruption happens here, don't crash, clean up gracefully. + if (objectset == null || objectset.isEmpty()) { // Paper + this.c.remove(i); +- this.f.update(i, Integer.MAX_VALUE, false); ++ //this.f.update(i, Integer.MAX_VALUE, false); // Paper - no longer used + this.g.update(i, Integer.MAX_VALUE, false); + } + +@@ -272,13 +274,17 @@ public abstract class ChunkMapDistance { + } + + public int b() { +- this.f.a(); +- return this.f.a.size(); ++ // Paper start - use distance map to implement ++ // note: this is the spawn chunk count ++ return this.chunkMap.playerChunkTickRangeMap.size(); ++ // Paper end - use distance map to implement + } + + public boolean d(long i) { +- this.f.a(); +- return this.f.a.containsKey(i); ++ // Paper start - use distance map to implement ++ // note: this is the is spawn chunk method ++ return this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(i) != null; ++ // Paper end - use distance map to implement + } + + public String c() { +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index fc7140e0eb11e4bec99e453647fce200bca0ed7f..46a2e89df71654024102427859c385fc2e09cae7 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -753,6 +753,37 @@ public class ChunkProviderServer extends IChunkProvider { + boolean flag1 = this.world.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && !world.getPlayers().isEmpty(); // CraftBukkit + + if (!flag) { ++ // Paper start - optimize isOutisdeRange ++ PlayerChunkMap playerChunkMap = this.playerChunkMap; ++ for (EntityPlayer player : this.world.players) { ++ if (!player.affectsSpawning || player.isSpectator()) { ++ playerChunkMap.playerMobSpawnMap.remove(player); ++ continue; ++ } ++ ++ int viewDistance = this.playerChunkMap.getEffectiveViewDistance(); ++ ++ // copied and modified from isOutisdeRange ++ int chunkRange = world.spigotConfig.mobSpawnRange; ++ chunkRange = (chunkRange > viewDistance) ? (byte)viewDistance : chunkRange; ++ chunkRange = (chunkRange > ChunkMapDistance.MOB_SPAWN_RANGE) ? ChunkMapDistance.MOB_SPAWN_RANGE : chunkRange; ++ ++ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(player.getBukkitEntity(), (byte)chunkRange); ++ event.callEvent(); ++ if (event.isCancelled() || event.getSpawnRadius() < 0 || playerChunkMap.playerChunkTickRangeMap.getLastViewDistance(player) == -1) { ++ playerChunkMap.playerMobSpawnMap.remove(player); ++ continue; ++ } ++ ++ int range = Math.min(event.getSpawnRadius(), 32); // limit to max view distance ++ int chunkX = net.minecraft.server.MCUtil.getChunkCoordinate(player.locX()); ++ int chunkZ = net.minecraft.server.MCUtil.getChunkCoordinate(player.locZ()); ++ ++ playerChunkMap.playerMobSpawnMap.addOrUpdate(player, chunkX, chunkZ, range); ++ player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in isOutsideRange ++ player.playerNaturallySpawnedEvent = event; ++ } ++ // Paper end - optimize isOutisdeRange + this.world.getMethodProfiler().enter("pollingChunks"); + int k = this.world.getGameRules().getInt(GameRules.RANDOM_TICK_SPEED); + boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit +@@ -782,15 +813,7 @@ public class ChunkProviderServer extends IChunkProvider { + this.world.getMethodProfiler().exit(); + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper +- //Paper start - call player naturally spawn event +- int chunkRange = world.spigotConfig.mobSpawnRange; +- chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; +- chunkRange = Math.min(chunkRange, 8); +- for (EntityPlayer entityPlayer : this.world.getPlayers()) { +- entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); +- entityPlayer.playerNaturallySpawnedEvent.callEvent(); +- }; +- // Paper end ++ // Paper - moved up + this.world.timings.chunkTicks.startTiming(); // Paper + final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); +@@ -807,9 +830,9 @@ public class ChunkProviderServer extends IChunkProvider { + Chunk chunk = (Chunk) optional1.get(); + ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); + +- if (!this.playerChunkMap.isOutsideOfRange(chunkcoordintpair)) { ++ if (!this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange + chunk.setInhabitedTime(chunk.getInhabitedTime() + j); +- if (flag1 && (this.allowMonsters || this.allowAnimals) && this.world.getWorldBorder().isInBounds(chunk.getPos()) && !this.playerChunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot ++ if (flag1 && (this.allowMonsters || this.allowAnimals) && this.world.getWorldBorder().isInBounds(chunk.getPos()) && !this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange + SpawnerCreature.a(this.world, chunk, spawnercreature_d, this.allowAnimals, this.allowMonsters, flag2); + } + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 39fb3a1445338c3ac1642b8e518eb8d1031f9a5c..62ed75ae7ec492d8502776fdf3cf3ee461a38a53 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -250,6 +250,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + ++ double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks ++ + public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { + super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); + this.spawnDimension = World.OVERWORLD; +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index 445dba8ed210407664904b707c36c78a76f25510..25484cac9c62e49de39fbbf506fcb3edc4ba6e65 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -70,6 +70,18 @@ public class PlayerChunk { + long lastAutoSaveTime; // Paper - incremental autosave + long inactiveTimeStart; // Paper - incremental autosave + ++ // Paper start - optimise isOutsideOfRange ++ // cached here to avoid a map lookup ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInMobSpawnRange; ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInChunkTickRange; ++ ++ void updateRanges() { ++ long key = net.minecraft.server.MCUtil.getCoordinateKey(this.location); ++ this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key); ++ this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); ++ } ++ // Paper end - optimise isOutsideOfRange ++ + public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { + this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); + this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; +@@ -86,6 +98,7 @@ public class PlayerChunk { + this.n = this.oldTicketLevel; + this.a(i); + this.chunkMap = (PlayerChunkMap)playerchunk_d; // Paper ++ this.updateRanges(); // Paper - optimise isOutsideOfRange + } + + // Paper start +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 9fc74f08b912ff885c9478167c7ef173c32f1654..a6bb8e3b9e73f81bfa92ac13df27e9c44dd9e311 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -210,6 +210,17 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); + } + // Paper end - use distance map to optimise tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ // A note about the naming used here: ++ // Previously, mojang used a "spawn range" of 8 for controlling both ticking and ++ // mob spawn range. However, spigot makes the spawn range configurable by ++ // checking if the chunk is in the tick range (8) and the spawn range ++ // obviously this means a spawn range > 8 cannot be implemented ++ ++ // these maps are named after spigot's uses ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + + void addPlayerToDistanceMaps(EntityPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.locX()); +@@ -223,6 +234,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); + } + // Paper end - use distance map to optimise entity tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + } + + void removePlayerFromDistanceMaps(EntityPlayer player) { +@@ -231,6 +245,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.playerEntityTrackerTrackMaps[i].remove(player); + } + // Paper end - use distance map to optimise tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerMobSpawnMap.remove(player); ++ this.playerChunkTickRangeMap.remove(player); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + } + + void updateMaps(EntityPlayer player) { +@@ -245,6 +263,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); + } + // Paper end - use distance map to optimise entity tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + } + // Paper end + +@@ -276,7 +297,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.mailboxWorldGen = this.p.a(threadedmailbox, false); + this.mailboxMain = this.p.a(mailbox, false); + this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false)); +- this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); ++ this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); this.chunkDistanceManager.chunkMap = this; // Paper + this.l = supplier; + this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper + this.setViewDistance(i); +@@ -320,6 +341,38 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); + } + // Paper end - use distance map to optimise entity tracker ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerChunkTickRangeMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInChunkTickRange = newState; ++ } ++ }, ++ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInChunkTickRange = newState; ++ } ++ }); ++ this.playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInMobSpawnRange = newState; ++ } ++ }, ++ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInMobSpawnRange = newState; ++ } ++ }); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + } + + public void updatePlayerMobTypeMap(Entity entity) { +@@ -339,6 +392,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return entityPlayer.mobCounts[enumCreatureType.ordinal()]; + } + ++ private static double getDistanceSquaredFromChunk(ChunkCoordIntPair chunkPos, Entity entity) { return a(chunkPos, entity); } // Paper - OBFHELPER + private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) { + double d0 = (double) (chunkcoordintpair.x * 16 + 8); + double d1 = (double) (chunkcoordintpair.z * 16 + 8); +@@ -517,6 +571,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } else { + if (playerchunk != null) { + playerchunk.a(j); ++ playerchunk.updateRanges(); // Paper - optimise isOutsideOfRange + } + + if (playerchunk != null) { +@@ -1495,30 +1550,53 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return isOutsideOfRange(chunkcoordintpair, false); + } + +- boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { +- int chunkRange = world.spigotConfig.mobSpawnRange; +- chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; +- chunkRange = (chunkRange > 8) ? 8 : chunkRange; ++ // Paper start - optimise isOutsideOfRange ++ final boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { ++ return this.isOutsideOfRange(this.getUpdatingChunk(chunkcoordintpair.pair()), chunkcoordintpair, reducedRange); ++ } + +- final int finalChunkRange = chunkRange; // Paper for lambda below +- //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event +- // Spigot end +- long i = chunkcoordintpair.pair(); ++ final boolean isOutsideOfRange(PlayerChunk playerchunk, ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { ++ // this function is so hot that removing the map lookup call can have an order of magnitude impact on its performance ++ // tested and confirmed via System.nanoTime() ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInRange = reducedRange ? playerchunk.playersInMobSpawnRange : playerchunk.playersInChunkTickRange; + +- return !this.chunkDistanceManager.d(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { +- // Paper start - +- com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; +- double blockRange = 16384.0D; +- if (reducedRange) { +- event = entityplayer.playerNaturallySpawnedEvent; +- if (event == null || event.isCancelled()) return false; +- blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); +- } ++ if (playersInRange == null) { ++ return true; ++ } + +- return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot +- // Paper end +- }); ++ Object[] backingSet = playersInRange.getBackingSet(); ++ ++ if (reducedRange) { ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object raw = backingSet[i]; ++ if (!(raw instanceof EntityPlayer)) { ++ continue; ++ } ++ EntityPlayer player = (EntityPlayer) raw; ++ // don't check spectator and whatnot, already handled by mob spawn map update ++ if (player.lastEntitySpawnRadiusSquared > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { ++ return false; // in range ++ } ++ } ++ } else { ++ final double range = (ChunkMapDistance.MOB_SPAWN_RANGE * 16) * (ChunkMapDistance.MOB_SPAWN_RANGE * 16); ++ // before spigot, mob spawn range was actually mob spawn range + tick range, but it was split ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object raw = backingSet[i]; ++ if (!(raw instanceof EntityPlayer)) { ++ continue; ++ } ++ EntityPlayer player = (EntityPlayer) raw; ++ // don't check spectator and whatnot, already handled by mob spawn map update ++ if (range > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { ++ return false; // in range ++ } ++ } ++ } ++ // no players in range ++ return true; + } ++ // Paper end - optimise isOutsideOfRange + + private boolean b(EntityPlayer entityplayer) { + return entityplayer.isSpectator() && !this.world.getGameRules().getBoolean(GameRules.SPECTATORS_GENERATE_CHUNKS); diff --git a/patches/server-unmapped/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch b/patches/server-unmapped/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch new file mode 100644 index 0000000000..ef0648a1f5 --- /dev/null +++ b/patches/server-unmapped/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch @@ -0,0 +1,319 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 27 Apr 2020 04:05:38 -0700 +Subject: [PATCH] Stop copy-on-write operations for updating light data + +Causes huge memory allocations + gc issues + +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java +index 5f3d2c090d098834e38e447d93f1ea8184c8fb3e..5b1ff4ff87591dd4ff0b79e4ac6ff0494fc3d0f8 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java +@@ -26,8 +26,8 @@ public abstract class LightEngineStorage> e + protected final LongSet b = new LongOpenHashSet(); + protected final LongSet c = new LongOpenHashSet(); + protected final LongSet d = new LongOpenHashSet(); +- protected volatile M e; +- protected final M f; ++ protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change ++ protected final M f; // Paper - diff on change, should be "updating" + protected final LongSet g = new LongOpenHashSet(); + protected final LongSet h = new LongOpenHashSet(); + protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); +@@ -41,8 +41,8 @@ public abstract class LightEngineStorage> e + this.l = enumskyblock; + this.m = ilightaccess; + this.f = m0; +- this.e = m0.b(); +- this.e.d(); ++ this.e_visible = m0.b(); // Paper - avoid copying light data ++ this.e_visible.d(); // Paper - avoid copying light data + } + + protected boolean g(long i) { +@@ -51,7 +51,15 @@ public abstract class LightEngineStorage> e + + @Nullable + protected NibbleArray a(long i, boolean flag) { +- return this.a(flag ? this.f : this.e, i); ++ // Paper start - avoid copying light data ++ if (flag) { ++ return this.a(this.f, i); ++ } else { ++ synchronized (this.visibleUpdateLock) { ++ return this.a(this.e_visible, i); ++ } ++ } ++ // Paper end - avoid copying light data + } + + @Nullable +@@ -364,10 +372,12 @@ public abstract class LightEngineStorage> e + + protected void e() { + if (!this.g.isEmpty()) { ++ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data + M m0 = this.f.b(); + + m0.d(); +- this.e = m0; ++ this.e_visible = m0; // Paper - avoid copying light data ++ } // Paper - avoid copying light data + this.g.clear(); + } + +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java +index 242a2c5dea1241b515b9eee7c334ab3c31ad9d12..ed7864c552054fc47c6010a094230ce4aebf1c54 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java +@@ -9,10 +9,23 @@ public abstract class LightEngineStorageArray a; +- +- protected LightEngineStorageArray(Long2ObjectOpenHashMap long2objectopenhashmap) { +- this.a = long2objectopenhashmap; ++ protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data ++ protected final boolean isVisible; // Paper - avoid copying light data ++ java.util.function.Function lookup; // Paper - faster branchless lookup ++ ++ // Paper start - avoid copying light data ++ protected LightEngineStorageArray(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { ++ if (isVisible) { ++ data.performUpdatesLockMap(); ++ } ++ this.data = data; ++ this.isVisible = isVisible; ++ if (isVisible) { ++ lookup = data::getVisibleAsync; ++ } else { ++ lookup = data::getUpdating; ++ } ++ // Paper end - avoid copying light data + this.c(); + this.d = true; + } +@@ -20,16 +33,17 @@ public abstract class LightEngineStorageArray { + + protected LightEngineStorageBlock(ILightAccess ilightaccess) { +- super(EnumSkyBlock.BLOCK, ilightaccess, new LightEngineStorageBlock.a(new Long2ObjectOpenHashMap())); ++ super(EnumSkyBlock.BLOCK, ilightaccess, new LightEngineStorageBlock.a(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data + } + + @Override +@@ -23,13 +23,13 @@ public class LightEngineStorageBlock extends LightEngineStorage { + +- public a(Long2ObjectOpenHashMap long2objectopenhashmap) { +- super(long2objectopenhashmap); ++ public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data ++ super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data + } + + @Override + public LightEngineStorageBlock.a b() { +- return new LightEngineStorageBlock.a(this.a.clone()); ++ return new a(this.data, true); // Paper - avoid copying light data + } + } + } +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java +index befc8f846c772d58ee687ad427bb71206b4dc43e..64d37f4c6a8167f47c80953a388ea6635490563a 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java +@@ -23,15 +23,16 @@ public class LightEngineStorageSky extends LightEngineStorage(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data + } + + @Override + protected int d(long i) { + long j = SectionPosition.e(i); + int k = SectionPosition.c(j); +- LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e; +- int l = lightenginestoragesky_a.c.get(SectionPosition.f(j)); ++ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data ++ LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e_visible; // Paper - avoid copying light data - must be after lock acquire ++ int l = lightenginestoragesky_a.otherData.getVisibleAsync(SectionPosition.f(j)); // Paper - avoid copying light data + + if (l != lightenginestoragesky_a.b && k < l) { + NibbleArray nibblearray = this.a(lightenginestoragesky_a, j); // Paper - decompile fix +@@ -52,6 +53,7 @@ public class LightEngineStorageSky extends LightEngineStorage j) { + ((LightEngineStorageSky.a) this.f).b = j; +- ((LightEngineStorageSky.a) this.f).c.defaultReturnValue(((LightEngineStorageSky.a) this.f).b); ++ ((LightEngineStorageSky.a) this.f).otherData.queueDefaultReturnValue(((LightEngineStorageSky.a) this.f).b); // Paper - avoid copying light data + } + + long k = SectionPosition.f(i); +- int l = ((LightEngineStorageSky.a) this.f).c.get(k); ++ int l = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(k); // Paper - avoid copying light data + + if (l < j + 1) { +- ((LightEngineStorageSky.a) this.f).c.put(k, j + 1); ++ ((LightEngineStorageSky.a) this.f).otherData.queueUpdate(k, j + 1); // Paper - avoid copying light data + if (this.o.contains(k)) { + this.q(i); + if (l > ((LightEngineStorageSky.a) this.f).b) { +@@ -107,7 +109,7 @@ public class LightEngineStorageSky extends LightEngineStorage= k; + } +@@ -327,18 +329,21 @@ public class LightEngineStorageSky extends LightEngineStorage { + + private int b; +- private final Long2IntOpenHashMap c; +- +- public a(Long2ObjectOpenHashMap long2objectopenhashmap, Long2IntOpenHashMap long2intopenhashmap, int i) { +- super(long2objectopenhashmap); +- this.c = long2intopenhashmap; +- long2intopenhashmap.defaultReturnValue(i); ++ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data ++ ++ // Paper start - avoid copying light data ++ public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData, int i, boolean isVisible) { ++ super(data, isVisible); ++ this.otherData = otherData; ++ otherData.queueDefaultReturnValue(i); ++ // Paper end - avoid copying light data + this.b = i; + } + + @Override + public LightEngineStorageSky.a b() { +- return new LightEngineStorageSky.a(this.a.clone(), this.c.clone(), this.b); ++ this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data ++ return new LightEngineStorageSky.a(this.data, this.otherData, this.b, true); // Paper - avoid copying light data + } + } + } diff --git a/patches/server-unmapped/0468-No-Tick-view-distance-implementation.patch b/patches/server-unmapped/0468-No-Tick-view-distance-implementation.patch new file mode 100644 index 0000000000..1e68582fcf --- /dev/null +++ b/patches/server-unmapped/0468-No-Tick-view-distance-implementation.patch @@ -0,0 +1,774 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 5 May 2020 21:23:34 -0700 +Subject: [PATCH] No-Tick view distance implementation + +Implements world view distance getters/setters + +Per-Player is absent due to difficulty of maintaining +the diff required to make it happen. + +diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java +index c9164dfdb27ddf3709129c8aec54903a1df121ff..e33e889c291d37a821a4fbd40d9aac7bb079de0d 100644 +--- a/src/main/java/co/aikar/timings/TimingsExport.java ++++ b/src/main/java/co/aikar/timings/TimingsExport.java +@@ -153,7 +153,8 @@ public class TimingsExport extends Thread { + pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { + return pair(rule, world.getWorld().getGameRuleValue(rule)); + })), +- pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) ++ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()), ++ pair("notick-viewdistance", world.getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance()) + )); + })); + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 46ac6d91422423f1e03b86d3efa3241f2599000d..6463d3e4837d032a35654a035f42b8a805e0e286 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -632,4 +632,9 @@ public class PaperWorldConfig { + phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); + phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); + } ++ ++ public int noTickViewDistance; ++ private void viewDistance() { ++ this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); ++ } + } +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 9edbde8299bcd127e1727d34ed441f638e716b2a..17de074111a174f3a39a4477afc3ad62e04a73b5 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -638,7 +638,8 @@ public final class MCUtil { + }); + + worldData.addProperty("name", world.getWorld().getName()); +- worldData.addProperty("view-distance", world.spigotConfig.viewDistance); ++ worldData.addProperty("view-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()); ++ worldData.addProperty("no-view-distance", world.getChunkProvider().playerChunkMap.getRawNoTickViewDistance()); + worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); + worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); + worldData.addProperty("visible-chunk-count", visibleChunks.size()); +diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +index 335666db1854e8aa4b2ba71d5bdc2658305cb70a..2bbdcedf4856080ea9232effdf3bdae9c26c425b 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +@@ -269,7 +269,7 @@ public abstract class ChunkMapDistance { + return s; + } + +- protected void a(int i) { ++ protected void setNoTickViewDistance(int i) { // Paper - force abi breakage on usage change + this.g.a(i); + } + +@@ -388,7 +388,7 @@ public abstract class ChunkMapDistance { + + private void a(long i, int j, boolean flag, boolean flag1) { + if (flag != flag1) { +- Ticket ticket = new Ticket<>(TicketType.PLAYER, ChunkMapDistance.b, new ChunkCoordIntPair(i)); ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkCoordIntPair(i)); // Paper - no-tick view distance + + if (flag1) { + ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 62ed75ae7ec492d8502776fdf3cf3ee461a38a53..89a66078b722f265abd73579545a1f24df9442aa 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -252,6 +252,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks + ++ boolean needsChunkCenterUpdate; // Paper - no-tick view distance ++ + public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { + super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); + this.spawnDimension = World.OVERWORLD; +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index 25484cac9c62e49de39fbbf506fcb3edc4ba6e65..1f6333c2c26ad04e23d2881235ed1dcf707be038 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -82,6 +82,18 @@ public class PlayerChunk { + } + // Paper end - optimise isOutsideOfRange + ++ // Paper start - no-tick view distance ++ public final Chunk getSendingChunk() { ++ // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used ++ // in Chunk's neighbour callback ++ Chunk ret = this.chunkMap.world.getChunkProvider().getChunkAtIfLoadedImmediately(this.location.x, this.location.z); ++ if (ret != null && ret.areNeighboursLoaded(1)) { ++ return ret; ++ } ++ return null; ++ } ++ // Paper end - no-tick view distance ++ + public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { + this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); + this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; +@@ -241,7 +253,7 @@ public class PlayerChunk { + } + + public void a(BlockPosition blockposition) { +- Chunk chunk = this.getChunk(); ++ Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { + byte b0 = (byte) SectionPosition.a(blockposition.getY()); +@@ -257,7 +269,7 @@ public class PlayerChunk { + } + + public void a(EnumSkyBlock enumskyblock, int i) { +- Chunk chunk = this.getChunk(); ++ Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { + chunk.setNeedsSaving(true); +@@ -339,9 +351,48 @@ public class PlayerChunk { + } + + private void a(Packet packet, boolean flag) { +- this.players.a(this.location, flag).forEach((entityplayer) -> { +- entityplayer.playerConnection.sendPacket(packet); +- }); ++ // Paper start - per player view distance ++ // there can be potential desync with player's last mapped section and the view distance map, so use the ++ // view distance map here. ++ com.destroystokyo.paper.util.misc.PlayerAreaMap viewDistanceMap = this.chunkMap.playerViewDistanceBroadcastMap; ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = viewDistanceMap.getObjectsInRange(this.location); ++ if (players == null) { ++ return; ++ } ++ ++ if (flag) { // flag -> border only ++ Object[] backingSet = players.getBackingSet(); ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof EntityPlayer)) { ++ continue; ++ } ++ EntityPlayer player = (EntityPlayer)temp; ++ ++ int viewDistance = viewDistanceMap.getLastViewDistance(player); ++ long lastPosition = viewDistanceMap.getLastCoordinate(player); ++ ++ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - this.location.x); ++ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - this.location.z); ++ ++ if (Math.max(distX, distZ) == viewDistance) { ++ player.playerConnection.sendPacket(packet); ++ } ++ } ++ } else { ++ Object[] backingSet = players.getBackingSet(); ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof EntityPlayer)) { ++ continue; ++ } ++ EntityPlayer player = (EntityPlayer)temp; ++ player.playerConnection.sendPacket(packet); ++ } ++ } ++ ++ return; ++ // Paper end - per player view distance + } + + public CompletableFuture> a(ChunkStatus chunkstatus, PlayerChunkMap playerchunkmap) { +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index a6bb8e3b9e73f81bfa92ac13df27e9c44dd9e311..e4b5649fbc8cb9662e818581fe2891641de419b6 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -60,9 +60,11 @@ import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; + import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; + import net.minecraft.network.protocol.game.PacketPlayOutMount; + import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; ++import net.minecraft.network.protocol.game.PacketPlayOutViewDistance; + import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.progress.WorldLoadListener; ++import net.minecraft.server.network.PlayerConnection; + import net.minecraft.util.CSVWriter; + import net.minecraft.util.EntitySlice; + import net.minecraft.util.MathHelper; +@@ -146,7 +148,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + private boolean updatingChunksModified; + private final ChunkTaskQueueSorter p; + private final Mailbox> mailboxWorldGen; +- private final Mailbox> mailboxMain; ++ public final Mailbox> mailboxMain; // Paper - private -> public ++ // Paper start ++ final Mailbox> mailboxLight; ++ public void addLightTask(PlayerChunk playerchunk, Runnable run) { ++ this.mailboxLight.a(ChunkTaskQueueSorter.a(playerchunk, run)); ++ } ++ // Paper end + public final WorldLoadListener worldLoadListener; + public final PlayerChunkMap.a chunkDistanceManager; public final ChunkMapDistance getChunkDistanceManager() { return this.chunkDistanceManager; } // Paper - OBFHELPER + private final AtomicInteger u; +@@ -221,6 +229,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick + public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ int noTickViewDistance; ++ public final int getRawNoTickViewDistance() { ++ return this.noTickViewDistance; ++ } ++ public final int getEffectiveNoTickViewDistance() { ++ return this.noTickViewDistance == -1 ? this.getEffectiveViewDistance() : this.noTickViewDistance; ++ } ++ public final int getLoadViewDistance() { ++ return Math.max(this.getEffectiveViewDistance(), this.getEffectiveNoTickViewDistance()); ++ } ++ ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceBroadcastMap; ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap; ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap; ++ // Paper end - no-tick view distance + + void addPlayerToDistanceMaps(EntityPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.locX()); +@@ -237,6 +261,19 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + // Paper start - optimise PlayerChunkMap#isOutsideRange + this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ int effectiveTickViewDistance = this.getEffectiveViewDistance(); ++ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); ++ ++ if (!this.cannotLoadChunks(player)) { ++ this.playerViewDistanceTickMap.add(player, chunkX, chunkZ, effectiveTickViewDistance); ++ this.playerViewDistanceNoTickMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) ++ } ++ ++ player.needsChunkCenterUpdate = true; ++ this.playerViewDistanceBroadcastMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured ++ player.needsChunkCenterUpdate = false; ++ // Paper end - no-tick view distance + } + + void removePlayerFromDistanceMaps(EntityPlayer player) { +@@ -249,6 +286,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.playerMobSpawnMap.remove(player); + this.playerChunkTickRangeMap.remove(player); + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ this.playerViewDistanceBroadcastMap.remove(player); ++ this.playerViewDistanceTickMap.remove(player); ++ this.playerViewDistanceNoTickMap.remove(player); ++ // Paper end - no-tick view distance + } + + void updateMaps(EntityPlayer player) { +@@ -266,6 +308,19 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + // Paper start - optimise PlayerChunkMap#isOutsideRange + this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ int effectiveTickViewDistance = this.getEffectiveViewDistance(); ++ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); ++ ++ if (!this.cannotLoadChunks(player)) { ++ this.playerViewDistanceTickMap.update(player, chunkX, chunkZ, effectiveTickViewDistance); ++ this.playerViewDistanceNoTickMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) ++ } ++ ++ player.needsChunkCenterUpdate = true; ++ this.playerViewDistanceBroadcastMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured ++ player.needsChunkCenterUpdate = false; ++ // Paper end - no-tick view distance + } + // Paper end + +@@ -373,6 +428,45 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + }); + // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - no-tick view distance ++ this.setNoTickViewDistance(this.world.paperConfig.noTickViewDistance); ++ this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ if (newState.size() != 1) { ++ return; ++ } ++ Chunk chunk = PlayerChunkMap.this.world.getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(rangeX, rangeZ); ++ if (chunk == null || !chunk.areNeighboursLoaded(2)) { ++ return; ++ } ++ ++ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ); ++ PlayerChunkMap.this.world.getChunkProvider().addTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update ++ }, ++ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ if (newState != null) { ++ return; ++ } ++ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ); ++ PlayerChunkMap.this.world.getChunkProvider().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update ++ }); ++ this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); ++ this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ if (player.needsChunkCenterUpdate) { ++ player.needsChunkCenterUpdate = false; ++ player.playerConnection.sendPacket(new PacketPlayOutViewCentre(currPosX, currPosZ)); ++ } ++ PlayerChunkMap.this.sendChunk(player, new ChunkCoordIntPair(rangeX, rangeZ), new Packet[2], false, true); // unloaded, loaded ++ }, ++ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ PlayerChunkMap.this.sendChunk(player, new ChunkCoordIntPair(rangeX, rangeZ), null, true, false); // unloaded, loaded ++ }); ++ // Paper end - no-tick view distance + } + + public void updatePlayerMobTypeMap(Entity entity) { +@@ -1201,15 +1295,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + completablefuture1.thenAcceptAsync((either) -> { + either.mapLeft((chunk) -> { + this.u.getAndIncrement(); +- Packet[] apacket = new Packet[2]; +- +- this.a(chunkcoordintpair, false).forEach((entityplayer) -> { +- this.a(entityplayer, apacket, chunk); +- }); ++ // Paper - no-tick view distance - moved to Chunk neighbour update + return Either.left(chunk); + }); + }, (runnable) -> { +- this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); ++ this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); // Paper - diff on change, this is the scheduling method copied in Chunk used to schedule chunk broadcasts (on change it needs to be copied again) + }); + return completablefuture1; + } +@@ -1304,32 +1394,38 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + } + +- protected void setViewDistance(int i) { +- int j = MathHelper.clamp(i + 1, 3, 33); ++ public void setViewDistance(int i) { // Paper - public ++ int j = MathHelper.clamp(i + 1, 3, 33); // Paper - diff on change, these make the lower view distance limit 2 and the upper 32 + + if (j != this.viewDistance) { + int k = this.viewDistance; + + this.viewDistance = j; +- this.chunkDistanceManager.a(this.viewDistance); +- ObjectIterator objectiterator = this.updatingChunks.values().iterator(); ++ this.setNoTickViewDistance(this.getRawNoTickViewDistance()); //Paper - no-tick view distance - propagate changes to no-tick, which does the actual chunk loading/sending ++ } + +- while (objectiterator.hasNext()) { +- PlayerChunk playerchunk = (PlayerChunk) objectiterator.next(); +- ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); +- Packet[] apacket = new Packet[2]; ++ } + +- this.a(chunkcoordintpair, false).forEach((entityplayer) -> { +- int l = b(chunkcoordintpair, entityplayer, true); +- boolean flag = l <= k; +- boolean flag1 = l <= this.viewDistance; ++ // Paper start - no-tick view distance ++ public final void setNoTickViewDistance(int viewDistance) { ++ viewDistance = viewDistance == -1 ? -1 : MathHelper.clamp(viewDistance, 2, 32); + +- this.sendChunk(entityplayer, chunkcoordintpair, apacket, flag, flag1); +- }); ++ this.noTickViewDistance = viewDistance; ++ int loadViewDistance = this.getLoadViewDistance(); ++ this.chunkDistanceManager.setNoTickViewDistance(loadViewDistance + 2 + 2); // add 2 to account for the change to 31 -> 33 tickets // see notes in the distance map updating for the other + 2 ++ ++ if (this.world != null && this.world.players != null) { // this can be called from constructor, where these aren't set ++ for (EntityPlayer player : this.world.players) { ++ PlayerConnection connection = player.playerConnection; ++ if (connection != null) { ++ // moved in from PlayerList ++ connection.sendPacket(new PacketPlayOutViewDistance(loadViewDistance)); ++ } ++ this.updateMaps(player); + } + } +- + } ++ // Paper end - no-tick view distance + + protected void sendChunk(EntityPlayer entityplayer, ChunkCoordIntPair chunkcoordintpair, Packet[] apacket, boolean flag, boolean flag1) { + if (entityplayer.world == this.world) { +@@ -1337,7 +1433,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + PlayerChunk playerchunk = this.getVisibleChunk(chunkcoordintpair.pair()); + + if (playerchunk != null) { +- Chunk chunk = playerchunk.getChunk(); ++ Chunk chunk = playerchunk.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { + this.a(entityplayer, apacket, chunk); +@@ -1598,6 +1694,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + // Paper end - optimise isOutsideOfRange + ++ private boolean cannotLoadChunks(EntityPlayer entityplayer) { return this.b(entityplayer); } // Paper - OBFHELPER + private boolean b(EntityPlayer entityplayer) { + return entityplayer.isSpectator() && !this.world.getGameRules().getBoolean(GameRules.SPECTATORS_GENERATE_CHUNKS); + } +@@ -1625,13 +1722,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.removePlayerFromDistanceMaps(entityplayer); // Paper - distance maps + } + +- for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { +- for (int l = j - this.viewDistance; l <= j + this.viewDistance; ++l) { +- ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k, l); +- +- this.sendChunk(entityplayer, chunkcoordintpair, new Packet[2], !flag, flag); +- } +- } ++ // Paper - broadcast view distance map handles this (see remove/add calls above) + + } + +@@ -1639,7 +1730,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + SectionPosition sectionposition = SectionPosition.a((Entity) entityplayer); + + entityplayer.a(sectionposition); +- entityplayer.playerConnection.sendPacket(new PacketPlayOutViewCentre(sectionposition.a(), sectionposition.c())); ++ // Paper - distance map handles this now + return sectionposition; + } + +@@ -1684,6 +1775,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + int k1; + int l1; + ++ /* // Paper start - replaced by distance map + if (Math.abs(i1 - i) <= this.viewDistance * 2 && Math.abs(j1 - j) <= this.viewDistance * 2) { + k1 = Math.min(i, i1) - this.viewDistance; + l1 = Math.min(j, j1) - this.viewDistance; +@@ -1721,7 +1813,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], false, true); + } + } +- } ++ }*/ // Paper end - replaced by distance map + + this.updateMaps(entityplayer); // Paper - distance maps + +@@ -1729,11 +1821,46 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + @Override + public Stream a(ChunkCoordIntPair chunkcoordintpair, boolean flag) { +- return this.playerMap.a(chunkcoordintpair.pair()).filter((entityplayer) -> { +- int i = b(chunkcoordintpair, entityplayer, true); ++ // Paper start - per player view distance ++ // there can be potential desync with player's last mapped section and the view distance map, so use the ++ // view distance map here. ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = this.playerViewDistanceBroadcastMap.getObjectsInRange(chunkcoordintpair); + +- return i > this.viewDistance ? false : !flag || i == this.viewDistance; +- }); ++ if (inRange == null) { ++ return Stream.empty(); ++ } ++ // all current cases are inlined so we wont hit this code, it's just in case plugins or future updates use it ++ List players = new java.util.ArrayList<>(); ++ Object[] backingSet = inRange.getBackingSet(); ++ ++ if (flag) { // flag -> border only ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof EntityPlayer)) { ++ continue; ++ } ++ EntityPlayer player = (EntityPlayer)temp; ++ int viewDistance = this.playerViewDistanceBroadcastMap.getLastViewDistance(player); ++ long lastPosition = this.playerViewDistanceBroadcastMap.getLastCoordinate(player); ++ ++ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - chunkcoordintpair.x); ++ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - chunkcoordintpair.z); ++ if (Math.max(distX, distZ) == viewDistance) { ++ players.add(player); ++ } ++ } ++ } else { ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof EntityPlayer)) { ++ continue; ++ } ++ EntityPlayer player = (EntityPlayer)temp; ++ players.add(player); ++ } ++ } ++ return players.stream(); ++ // Paper end - per player view distance + } + + public void addEntity(Entity entity) { // Paper - protected -> public +@@ -1891,7 +2018,48 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + } + +- private final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER ++ // Paper start ++ private static int getLightMask(final Chunk chunk) { ++ final ChunkSection[] chunkSections = chunk.getSections(); ++ int mask = 0; ++ ++ for (int i = 0; i < chunkSections.length; ++i) { ++ /* ++ ++ ++Lightmasks have 18 bits, from the -1 (void) section until the 17th (air) section. ++Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. ++ ++ */ ++ mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; ++ } ++ ++ return mask; ++ } ++ ++ private static int getCeilingLightMask(final Chunk chunk) { ++ int mask = getLightMask(chunk); ++ ++ /* ++ It is similar to get highest bit, it would turn an 001010 into an 001111 so basically the highest bit and all below. ++ We then invert this, so we'd have 110000 and compare that to the "main" chunk. ++ This is because the bug only appears when the current chunks lightmaps are higher than those of the neighbors, thus we can omit sending neighbors which are lower than the current chunks lights. ++ ++ so TLDR is that getCeilingLightMask returns a light mask with all bits set below the highest affected section. We could also count the number of leading zeros and invert them, somehow. ++ @TODO: Implement Leafs suggestion ++ either use Integer#numberOfLeadingZeros or document what this bithack is supposed to be doing then ++ */ ++ mask |= mask >> 1; ++ mask |= mask >> 2; ++ mask |= mask >> 4; ++ mask |= mask >> 8; ++ mask |= mask >> 16; ++ ++ return mask; ++ } ++ // Paper end ++ ++ public final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER + private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { + if (apacket[0] == null) { + apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(entityplayer, chunk, 65535)); // Paper - Anti-Xray - Bypass +@@ -2077,7 +2245,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(this.tracker.chunkX, this.tracker.chunkZ); + PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair.pair()); + +- if (playerchunk != null && playerchunk.getChunk() != null) { ++ if (playerchunk != null && playerchunk.getSendingChunk() != null) { // Paper - no-tick view distance + flag1 = PlayerChunkMap.b(chunkcoordintpair, entityplayer, false) <= PlayerChunkMap.this.viewDistance; + } + } +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index c7e78d0626fa0dd18021c1a0827a10c08ab10b4a..66fcd68f0a0a21b113e8741cc42c841f49009118 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -254,7 +254,7 @@ public abstract class PlayerList { + boolean flag1 = gamerules.getBoolean(GameRules.REDUCED_DEBUG_INFO); + + // Spigot - view distance +- playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.spigotConfig.viewDistance, flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); ++ playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.getChunkProvider().playerChunkMap.getLoadViewDistance(), flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); // Paper - no-tick view distance + entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit + playerconnection.sendPacket(new PacketPlayOutCustomPayload(PacketPlayOutCustomPayload.a, (new PacketDataSerializer(Unpooled.buffer())).a(this.getServer().getServerModName()))); + playerconnection.sendPacket(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); +@@ -908,7 +908,7 @@ public abstract class PlayerList { + // CraftBukkit start + WorldData worlddata = worldserver1.getWorldData(); + entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn(worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), BiomeManager.a(worldserver1.getSeed()), entityplayer1.playerInteractManager.getGameMode(), entityplayer1.playerInteractManager.c(), worldserver1.isDebugWorld(), worldserver1.isFlatWorld(), flag)); +- entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver1.spigotConfig.viewDistance)); // Spigot ++ entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver1.getChunkProvider().playerChunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance + entityplayer1.spawnIn(worldserver1); + entityplayer1.dead = false; + entityplayer1.playerConnection.teleport(new Location(worldserver1.getWorld(), entityplayer1.locX(), entityplayer1.locY(), entityplayer1.locZ(), entityplayer1.yaw, entityplayer1.pitch)); +@@ -1376,7 +1376,7 @@ public abstract class PlayerList { + + public void a(int i) { + this.viewDistance = i; +- this.sendAll(new PacketPlayOutViewDistance(i)); ++ //this.sendAll(new PacketPlayOutViewDistance(i)); // Paper - move into setViewDistance + Iterator iterator = this.server.getWorlds().iterator(); + + while (iterator.hasNext()) { +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index efcfc8f0f45901d14ac8fdf8ed7b0bd67f8f94da..7ead848342bfbb5b20e95d716805f4b4fd36eb63 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -525,8 +525,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + this.b(blockposition, iblockdata1, iblockdata2); + } + +- if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getState() != null && chunk.getState().isAtLeast(PlayerChunk.State.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement ++ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getState() != null && chunk.getState().isAtLeast(PlayerChunk.State.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement // Paper - diff on change, see below + this.notify(blockposition, iblockdata1, iblockdata, i); ++ // Paper start - per player view distance - allow block updates for non-ticking chunks in player view distance ++ // if copied from above ++ } else if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || ((WorldServer)this).getChunkProvider().playerChunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.getCoordinateKey(blockposition)) != null)) { ++ ((WorldServer)this).getChunkProvider().flagDirty(blockposition); ++ // Paper end - per player view distance + } + + if ((i & 1) != 0) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index bb2ff043f0d159fa18769c31b08683ee12037c58..90e895e9eac6158a28de4a30589bf7538e5ec9cc 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -28,7 +28,12 @@ import net.minecraft.core.IRegistry; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkProviderServer; ++import net.minecraft.network.protocol.Packet; ++import net.minecraft.server.level.ChunkTaskQueueSorter; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.PlayerChunk; ++import net.minecraft.server.level.PlayerChunkMap; ++import net.minecraft.server.level.TicketType; + import net.minecraft.server.level.WorldServer; + import net.minecraft.util.EntitySlice; + import net.minecraft.util.MathHelper; +@@ -243,7 +248,51 @@ public class Chunk implements IChunkAccess { + } + + protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { ++ // Paper start - no-tick view distance ++ ChunkProviderServer chunkProviderServer = ((WorldServer)this.world).getChunkProvider(); ++ PlayerChunkMap chunkMap = chunkProviderServer.playerChunkMap; ++ // this code handles the addition of ticking tickets - the distance map handles the removal ++ if (!areNeighboursLoaded(bitsetBefore, 2) && areNeighboursLoaded(bitsetAfter, 2)) { ++ if (chunkMap.playerViewDistanceTickMap.getObjectsInRange(this.coordinateKey) != null) { ++ // now we're ready for entity ticking ++ chunkProviderServer.serverThreadQueue.execute(() -> { ++ // double check that this condition still holds. ++ if (Chunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(Chunk.this.coordinateKey) != null) { ++ chunkProviderServer.addTicketAtLevel(TicketType.PLAYER, Chunk.this.loc, 31, Chunk.this.loc); // 31 -> entity ticking, TODO check on update ++ } ++ }); ++ } ++ } + ++ // this code handles the chunk sending ++ if (!areNeighboursLoaded(bitsetBefore, 1) && areNeighboursLoaded(bitsetAfter, 1)) { ++ if (chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(this.coordinateKey) != null) { ++ // now we're ready to send ++ chunkMap.mailboxMain.a(ChunkTaskQueueSorter.a(chunkMap.getUpdatingChunk(this.coordinateKey), (() -> { // Copied frm PlayerChunkMap ++ // double check that this condition still holds. ++ if (!Chunk.this.areNeighboursLoaded(1)) { ++ return; ++ } ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(Chunk.this.coordinateKey); ++ if (inRange == null) { ++ return; ++ } ++ ++ // broadcast ++ Object[] backingSet = inRange.getBackingSet(); ++ Packet[] chunkPackets = new Packet[2]; ++ for (int index = 0, len = backingSet.length; index < len; ++index) { ++ Object temp = backingSet[index]; ++ if (!(temp instanceof EntityPlayer)) { ++ continue; ++ } ++ EntityPlayer player = (EntityPlayer)temp; ++ chunkMap.sendChunk(player, chunkPackets, Chunk.this); ++ } ++ }))); ++ } ++ } ++ // Paper end - no-tick view distance + } + + public final boolean isAnyNeighborsLoaded() { +@@ -1132,7 +1181,7 @@ public class Chunk implements IChunkAccess { + IBlockData iblockdata = this.getType(blockposition); + IBlockData iblockdata1 = Block.b(iblockdata, (GeneratorAccess) this.world, blockposition); + +- this.world.setTypeAndData(blockposition, iblockdata1, 20); ++ this.world.setTypeAndData(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here + } + + this.n[i].clear(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index c5a4c8c4c9d90a8a081a593488f86ab487adaecb..2d90ecf04f522a4e16f44c905450a61becaa1ed2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -32,6 +32,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.server.level.ChunkMapDistance; + import net.minecraft.server.level.PlayerChunk; ++import net.minecraft.server.level.PlayerChunkMap; + import net.minecraft.server.level.Ticket; + import net.minecraft.server.level.TicketType; + import net.minecraft.server.level.WorldServer; +@@ -2550,10 +2551,39 @@ public class CraftWorld implements World { + // Spigot start + @Override + public int getViewDistance() { +- return world.spigotConfig.viewDistance; ++ return getHandle().getChunkProvider().playerChunkMap.getEffectiveViewDistance(); // Paper - no-tick view distance + } + // Spigot end + ++ // Paper start - per player view distance ++ @Override ++ public void setViewDistance(int viewDistance) { ++ if (viewDistance < 2 || viewDistance > 32) { ++ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); ++ } ++ PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; ++ if (viewDistance != chunkMap.getEffectiveViewDistance()) { ++ chunkMap.setViewDistance(viewDistance); ++ } ++ } ++ ++ @Override ++ public int getNoTickViewDistance() { ++ return getHandle().getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance(); ++ } ++ ++ @Override ++ public void setNoTickViewDistance(int viewDistance) { ++ if ((viewDistance < 2 || viewDistance > 32) && viewDistance != -1) { ++ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); ++ } ++ PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; ++ if (viewDistance != chunkMap.getRawNoTickViewDistance()) { ++ chunkMap.setNoTickViewDistance(viewDistance); ++ } ++ } ++ // Paper end - per player view distance ++ + // Spigot start + private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot() + { +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 663127e6e6ec507959142b18a11a5a4790d4b98b..5c2eaca0bc63c7880ee928aba6a24761737aa649 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -2,6 +2,7 @@ package org.spigotmc; + + import java.util.Collection; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.util.MathHelper; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityCreature; +@@ -197,7 +198,7 @@ public class ActivationRange + maxRange = Math.max( maxRange, waterActivationRange ); + maxRange = Math.max( maxRange, villagerActivationRange ); + // Paper end +- maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); ++ maxRange = Math.min( ( ((WorldServer)world).getChunkProvider().playerChunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance + + for ( EntityHuman player : world.getPlayers() ) + { diff --git a/patches/server-unmapped/0469-Add-villager-reputation-API.patch b/patches/server-unmapped/0469-Add-villager-reputation-API.patch new file mode 100644 index 0000000000..6b57ec94ac --- /dev/null +++ b/patches/server-unmapped/0469-Add-villager-reputation-API.patch @@ -0,0 +1,153 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 22 Apr 2020 23:29:20 +0200 +Subject: [PATCH] Add villager reputation API + + +diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0f10c333d88f2e1c56a6c7f22d421084adfd3789 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java +@@ -0,0 +1,9 @@ ++package com.destroystokyo.paper.entity.villager; ++// Must have own package due to package-level constructor. ++ ++public final class ReputationConstructor { ++ // Abuse the package-level constructor. ++ public static Reputation construct(int[] values) { ++ return new Reputation(values); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java +index a7f5e4a499c1f6fb1450e536dbf117a8af3b3b84..9cc3a18636a356977577076e96cb7be706c61abf 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java +@@ -27,7 +27,7 @@ import net.minecraft.core.MinecraftSerializableUUID; + + public class Reputation { + +- private final Map a = Maps.newHashMap(); ++ private final Map a = Maps.newHashMap(); public Map getReputations() { return this.a; } // Paper - add getter for reputations + + public Reputation() {} + +@@ -142,11 +142,11 @@ public class Reputation { + return k > reputationtype.h ? Math.max(reputationtype.h, i) : k; + } + +- static class a { ++ public static class a { // Paper - make public + + private final Object2IntMap a; + +- private a() { ++ public a() { // Paper - make public - update CraftVillager setReputation on change + this.a = new Object2IntOpenHashMap(); + } + +@@ -200,6 +200,28 @@ public class Reputation { + public void b(ReputationType reputationtype) { + this.a.removeInt(reputationtype); + } ++ ++ // Paper start - Add villager reputation API ++ private static final com.destroystokyo.paper.entity.villager.ReputationType[] REPUTATION_TYPES = com.destroystokyo.paper.entity.villager.ReputationType.values(); ++ public com.destroystokyo.paper.entity.villager.Reputation getPaperReputation() { ++ int[] reputation = new int[REPUTATION_TYPES.length]; ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE.ordinal()] = a.getOrDefault(ReputationType.MAJOR_NEGATIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE.ordinal()] = a.getOrDefault(ReputationType.MAJOR_POSITIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE.ordinal()] = a.getOrDefault(ReputationType.MINOR_NEGATIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE.ordinal()] = a.getOrDefault(ReputationType.MINOR_POSITIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.TRADING.ordinal()] = a.getOrDefault(ReputationType.TRADING, 0); ++ return com.destroystokyo.paper.entity.villager.ReputationConstructor.construct(reputation); ++ } ++ ++ public void assignFromPaperReputation(com.destroystokyo.paper.entity.villager.Reputation rep) { ++ int val; ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE)) != 0) this.a.put(ReputationType.MAJOR_NEGATIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE)) != 0) this.a.put(ReputationType.MAJOR_POSITIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE)) != 0) this.a.put(ReputationType.MINOR_NEGATIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE)) != 0) this.a.put(ReputationType.MINOR_POSITIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.TRADING)) != 0) this.a.put(ReputationType.TRADING, val); ++ } ++ // Paper end + } + + static class b { +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index fb97325e8df33c0edabb81053877ad4a326a3d34..5e84e33ffdda85be96c3d31fbd6a2aa3eab1106a 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -1038,6 +1038,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + this.bD = 0; + } + ++ public Reputation getReputation() { return this.fj(); } // Paper - OBFHELPER + public Reputation fj() { + return this.by; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +index 4b2451179cdda918808ea7001f5033c7e5a8b9ac..073c4c518be5a32fccd82e5739ede461214007b2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +@@ -17,6 +17,13 @@ import org.bukkit.entity.Villager; + import org.bukkit.entity.Villager.Profession; + import org.bukkit.entity.Villager.Type; + ++// Paper start ++import com.destroystokyo.paper.entity.villager.Reputation; ++import com.google.common.collect.Maps; ++import java.util.Map; ++import java.util.UUID; ++// Paper end ++ + public class CraftVillager extends CraftAbstractVillager implements Villager { + + public CraftVillager(CraftServer server, EntityVillager entity) { +@@ -126,4 +133,45 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { + public static VillagerProfession bukkitToNmsProfession(Profession bukkit) { + return IRegistry.VILLAGER_PROFESSION.get(CraftNamespacedKey.toMinecraft(bukkit.getKey())); + } ++ ++ // Paper start - Add villager reputation API ++ @Override ++ public Reputation getReputation(UUID uniqueId) { ++ net.minecraft.world.entity.ai.gossip.Reputation.a rep = getHandle().getReputation().getReputations().get(uniqueId); ++ if (rep == null) { ++ return new Reputation(Maps.newHashMap()); ++ } ++ ++ return rep.getPaperReputation(); ++ } ++ ++ @Override ++ public Map getReputations() { ++ return getHandle().getReputation().getReputations().entrySet() ++ .stream() ++ .collect(java.util.stream.Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getPaperReputation())); ++ } ++ ++ @Override ++ public void setReputation(UUID uniqueId, Reputation reputation) { ++ net.minecraft.world.entity.ai.gossip.Reputation.a nmsReputation = ++ getHandle().getReputation().getReputations().computeIfAbsent( ++ uniqueId, ++ key -> new net.minecraft.world.entity.ai.gossip.Reputation.a() ++ ); ++ nmsReputation.assignFromPaperReputation(reputation); ++ } ++ ++ @Override ++ public void setReputations(Map reputations) { ++ for (Map.Entry entry : reputations.entrySet()) { ++ setReputation(entry.getKey(), entry.getValue()); ++ } ++ } ++ ++ @Override ++ public void clearReputations() { ++ getHandle().getReputation().getReputations().clear(); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0470-Fix-Light-Command.patch b/patches/server-unmapped/0470-Fix-Light-Command.patch new file mode 100644 index 0000000000..6b3d2eed34 --- /dev/null +++ b/patches/server-unmapped/0470-Fix-Light-Command.patch @@ -0,0 +1,185 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 7 May 2020 19:17:36 -0400 +Subject: [PATCH] Fix Light Command + +This lets you run /paper fixlight (max 5) to automatically +fix all light data in the chunks. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index eb1e86e8bb0f421e3686ffa02a4015a588107863..d165e8c232c38ba2e2faf93c60c8a127bb74c9b6 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -8,6 +8,8 @@ import com.google.common.collect.ImmutableSet; + import com.google.common.collect.Iterables; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; ++import net.minecraft.core.BlockPosition; ++import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; + import net.minecraft.resources.MinecraftKey; + import com.google.gson.JsonObject; + import com.google.gson.internal.Streams; +@@ -15,12 +17,14 @@ import com.google.gson.stream.JsonWriter; + import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkProviderServer; ++import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.LightEngineThreaded; + import net.minecraft.server.level.PlayerChunk; + import net.minecraft.server.level.WorldServer; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.level.ChunkCoordIntPair; +-import net.minecraft.server.MCUtil; ++import net.minecraft.world.level.chunk.Chunk; + import org.apache.commons.lang3.tuple.MutablePair; + import org.apache.commons.lang3.tuple.Pair; + import org.bukkit.Bukkit; +@@ -31,6 +35,7 @@ import org.bukkit.command.Command; + import org.bukkit.command.CommandSender; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftPlayer; + import org.bukkit.entity.Player; + + import java.io.File; +@@ -39,10 +44,12 @@ import java.io.PrintStream; + import java.io.StringWriter; + import java.time.LocalDateTime; + import java.time.format.DateTimeFormatter; ++import java.util.ArrayDeque; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collection; + import java.util.Collections; ++import java.util.Deque; + import java.util.Iterator; + import java.util.List; + import java.util.Locale; +@@ -52,7 +59,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); + + public PaperCommand(String name) { + super(name); +@@ -173,6 +180,9 @@ public class PaperCommand extends Command { + case "syncloadinfo": + this.doSyncLoadInfo(sender, args); + break; ++ case "fixlight": ++ this.doFixLight(sender, args); ++ break; + case "ver": + if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) + case "version": +@@ -190,6 +200,77 @@ public class PaperCommand extends Command { + return true; + } + ++ private void doFixLight(CommandSender sender, String[] args) { ++ if (!(sender instanceof Player)) { ++ sender.sendMessage("Only players can use this command"); ++ return; ++ } ++ int radius = 2; ++ if (args.length > 1) { ++ try { ++ radius = Math.min(5, Integer.parseInt(args[1])); ++ } catch (Exception e) { ++ sender.sendMessage("Not a number"); ++ return; ++ } ++ ++ } ++ ++ CraftPlayer player = (CraftPlayer) sender; ++ EntityPlayer handle = player.getHandle(); ++ WorldServer world = (WorldServer) handle.world; ++ LightEngineThreaded lightengine = world.getChunkProvider().getLightEngine(); ++ ++ BlockPosition center = MCUtil.toBlockPosition(player.getLocation()); ++ Deque queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius)); ++ updateLight(sender, world, lightengine, queue); ++ } ++ ++ private void updateLight(CommandSender sender, WorldServer world, LightEngineThreaded lightengine, Deque queue) { ++ ChunkCoordIntPair coord = queue.poll(); ++ if (coord == null) { ++ sender.sendMessage("All Chunks Light updated"); ++ return; ++ } ++ world.getChunkProvider().getChunkAtAsynchronously(coord.x, coord.z, false, false).whenCompleteAsync((either, ex) -> { ++ if (ex != null) { ++ sender.sendMessage("Error loading chunk " + coord); ++ updateLight(sender, world, lightengine, queue); ++ return; ++ } ++ Chunk chunk = (Chunk) either.left().orElse(null); ++ if (chunk == null) { ++ updateLight(sender, world, lightengine, queue); ++ return; ++ } ++ lightengine.a(world.paperConfig.lightQueueSize + 16 * 256); // ensure full chunk can fit into queue ++ sender.sendMessage("Updating Light " + coord); ++ int cx = chunk.getPos().x << 4; ++ int cz = chunk.getPos().z << 4; ++ for (int y = 0; y < world.getHeight(); y++) { ++ for (int x = 0; x < 16; x++) { ++ for (int z = 0; z < 16; z++) { ++ BlockPosition pos = new BlockPosition(cx + x, y, cz + z); ++ lightengine.a(pos); ++ } ++ } ++ } ++ lightengine.queueUpdate(); ++ PlayerChunk visibleChunk = world.getChunkProvider().playerChunkMap.getVisibleChunk(chunk.coordinateKey); ++ if (visibleChunk != null) { ++ world.getChunkProvider().playerChunkMap.addLightTask(visibleChunk, () -> { ++ MinecraftServer.getServer().processQueue.add(() -> { ++ visibleChunk.sendPacketToTrackedPlayers(new PacketPlayOutLightUpdate(chunk.getPos(), lightengine, true), false); ++ updateLight(sender, world, lightengine, queue); ++ }); ++ }); ++ } else { ++ updateLight(sender, world, lightengine, queue); ++ } ++ lightengine.a(world.paperConfig.lightQueueSize); ++ }, MinecraftServer.getServer()); ++ } ++ + private void doSyncLoadInfo(CommandSender sender, String[] args) { + if (!SyncLoadFinder.ENABLED) { + sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index 1f6333c2c26ad04e23d2881235ed1dcf707be038..e53054fc46e528f9c713eb4c03add61316e19396 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -350,6 +350,7 @@ public class PlayerChunk { + + } + ++ public void sendPacketToTrackedPlayers(Packet packet, boolean flag) { a(packet, flag); } // Paper - OBFHELPER + private void a(Packet packet, boolean flag) { + // Paper start - per player view distance + // there can be potential desync with player's last mapped section and the view distance map, so use the +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index e4b5649fbc8cb9662e818581fe2891641de419b6..a7e3a979dca4dd7705a8f80366677378f0643f27 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -346,11 +346,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + Mailbox mailbox = Mailbox.a("main", iasynctaskhandler::a); + + this.worldLoadListener = worldloadlistener; +- ThreadedMailbox threadedmailbox1 = ThreadedMailbox.a(executor, "light"); ++ ThreadedMailbox lightthreaded; ThreadedMailbox threadedmailbox1 = lightthreaded = ThreadedMailbox.a(executor, "light"); // Paper + + this.p = new ChunkTaskQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE); + this.mailboxWorldGen = this.p.a(threadedmailbox, false); + this.mailboxMain = this.p.a(mailbox, false); ++ this.mailboxLight = this.p.a(lightthreaded, false);// Paper + this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false)); + this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); this.chunkDistanceManager.chunkMap = this; // Paper + this.l = supplier; diff --git a/patches/server-unmapped/0471-Fix-PotionEffect-ignores-icon-flag.patch b/patches/server-unmapped/0471-Fix-PotionEffect-ignores-icon-flag.patch new file mode 100644 index 0000000000..830778e6bb --- /dev/null +++ b/patches/server-unmapped/0471-Fix-PotionEffect-ignores-icon-flag.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Fri, 8 May 2020 00:49:18 -0400 +Subject: [PATCH] Fix PotionEffect ignores icon flag + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 468dca6d8c2ec77c3c77c93d04fb9dc329b1befa..fdf4d258dd3e81cf4317ad66334c323be2d88fb2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -420,7 +420,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + + @Override + public boolean addPotionEffect(PotionEffect effect, boolean force) { +- getHandle().addEffect(new MobEffect(MobEffectList.fromId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN); ++ getHandle().addEffect(new MobEffect(MobEffectList.fromId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon + return true; + } + diff --git a/patches/server-unmapped/0472-Optimize-brigadier-child-sorting-performance.patch b/patches/server-unmapped/0472-Optimize-brigadier-child-sorting-performance.patch new file mode 100644 index 0000000000..e32f00ecf8 --- /dev/null +++ b/patches/server-unmapped/0472-Optimize-brigadier-child-sorting-performance.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: virustotalop +Date: Thu, 16 Apr 2020 20:51:32 -0700 +Subject: [PATCH] Optimize brigadier child sorting performance + + +diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +index f0f25fa40d4a0aa0e299ad11847b6a5f9102c214..7ef6c99d2235eed38197aa76bc9553d7efbe52a4 100644 +--- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java ++++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +@@ -27,7 +27,7 @@ import java.util.stream.Collectors; + import net.minecraft.commands.CommandListenerWrapper; // CraftBukkit + + public abstract class CommandNode implements Comparable> { +- private Map> children = Maps.newLinkedHashMap(); ++ private Map> children = Maps.newTreeMap(); //Paper - Switch to tree map for automatic sorting + private Map> literals = Maps.newLinkedHashMap(); + private Map> arguments = Maps.newLinkedHashMap(); + private final Predicate requirement; +@@ -107,8 +107,7 @@ public abstract class CommandNode implements Comparable> { + arguments.put(node.getName(), (ArgumentCommandNode) node); + } + } +- +- children = children.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); ++ //Paper - Remove manual sorting, it is no longer needed + } + + public void findAmbiguities(final AmbiguityConsumer consumer) { diff --git a/patches/server-unmapped/0473-Potential-bed-API.patch b/patches/server-unmapped/0473-Potential-bed-API.patch new file mode 100644 index 0000000000..dda9b9bbad --- /dev/null +++ b/patches/server-unmapped/0473-Potential-bed-API.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Sun, 10 May 2020 23:06:30 -0400 +Subject: [PATCH] Potential bed API + +Adds a new method to fetch the location of a player's bed without generating any sync loads. + +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/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index 3bfb93890259210afd2f5e226cef100d26a11628..4028f4bd87a183a808f4c9a19d51ee1c9b9e30f7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -13,6 +13,7 @@ import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.network.protocol.game.PacketPlayInCloseWindow; + import net.minecraft.network.protocol.game.PacketPlayOutOpenWindow; + import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.world.ITileInventory; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityTypes; +@@ -127,6 +128,22 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + return getHandle().sleepTicks; + } + ++ // Paper start - Potential bed api ++ @Override ++ public Location getPotentialBedLocation() { ++ EntityPlayer handle = (EntityPlayer) getHandle(); ++ BlockPosition bed = handle.getSpawn(); ++ if (bed == null) { ++ return null; ++ } ++ ++ WorldServer worldServer = handle.server.getWorldServer(handle.getSpawnDimension()); ++ if (worldServer == null) { ++ return null; ++ } ++ return new Location(worldServer.getWorld(), bed.getX(), bed.getY(), bed.getZ()); ++ } ++ // Paper end + @Override + public boolean sleep(Location location, boolean force) { + Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/patches/server-unmapped/0474-Wait-for-Async-Tasks-during-shutdown.patch b/patches/server-unmapped/0474-Wait-for-Async-Tasks-during-shutdown.patch new file mode 100644 index 0000000000..f826db1c4f --- /dev/null +++ b/patches/server-unmapped/0474-Wait-for-Async-Tasks-during-shutdown.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 May 2020 22:16:17 -0400 +Subject: [PATCH] Wait for Async Tasks during shutdown + +Server.reload() had this logic to give time for tasks to shutdown, +however shutdown did not... + +Adds a 5 second grace period for any async tasks to finish and warns +if any are still running after that delay just as reload does. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 1eb1da61ee2aa2cc5d28a46fd364a182cd16983b..69476bb6bca963c5ea88a7cc66622ae599595e62 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -894,6 +894,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0) { ++ try { ++ Thread.sleep(100); ++ } catch (InterruptedException e) {} ++ pollCount++; ++ } ++ ++ List overdueWorkers = getScheduler().getActiveWorkers(); ++ for (BukkitWorker worker : overdueWorkers) { ++ Plugin plugin = worker.getOwner(); ++ String author = ""; ++ if (plugin.getDescription().getAuthors().size() > 0) { ++ author = plugin.getDescription().getAuthors().get(0); ++ } ++ getLogger().log(Level.SEVERE, String.format( ++ "Nag author: '%s' of '%s' about the following: %s", ++ author, ++ plugin.getDescription().getName(), ++ "This plugin is not properly shutting down its async tasks when it is being shut down. This task may throw errors during the final shutdown logs and might not complete before process dies." ++ )); ++ } ++ } ++ // Paper end ++ + @Override + public void reloadData() { + CommandReload.reload(console); diff --git a/patches/server-unmapped/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/patches/server-unmapped/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch new file mode 100644 index 0000000000..a5eab26a70 --- /dev/null +++ b/patches/server-unmapped/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Sat, 9 May 2020 02:01:48 -0400 +Subject: [PATCH] Ensure EntityRaider respects game and entity rules for + picking up items + + +diff --git a/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java b/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java +index b9f5ed4e9348648a248dcd23eb100ceac49f26df..ff41ee884e3e46af1b1e9fb550f0abc6998fd031 100644 +--- a/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java ++++ b/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java +@@ -523,7 +523,7 @@ public abstract class EntityRaider extends EntityMonsterPatrolling { + + public class b extends PathfinderGoal { + +- private final T b; ++ private final T b; private T getRaider() { return b; } // Paper - obfhelper + + public b(T entityraider) { // CraftBukkit - decompile error + this.b = entityraider; +@@ -532,6 +532,7 @@ public abstract class EntityRaider extends EntityMonsterPatrolling { + + @Override + public boolean a() { ++ if (!getRaider().world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) || !getRaider().canPickupLoot()) return false; // Paper - respect game and entity rules for picking up items + Raid raid = this.b.fa(); + + if (this.b.fb() && !this.b.fa().a() && this.b.eN() && !ItemStack.matches(this.b.getEquipment(EnumItemSlot.HEAD), Raid.s())) { diff --git a/patches/server-unmapped/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server-unmapped/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch new file mode 100644 index 0000000000..c5742080fb --- /dev/null +++ b/patches/server-unmapped/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch @@ -0,0 +1,173 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 13 May 2020 23:01:26 -0400 +Subject: [PATCH] Protect Bedrock and End Portal/Frames from being destroyed + +This fixes exploits that let players destroy bedrock by Pistons, explosions +and Mushrooom/Tree generation. + +These blocks are designed to not be broken except by creative players/commands. +So protect them from a multitude of methods of destroying them. + +A config is provided if you rather let players use these exploits, and let +them destroy the worlds End Portals and get on top of the nether easy. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 78271b400c79578d043b20a5389a37b1bef9a70d..5f3b0d95cc7e6a0434d78ea7305a70689c41c71c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -416,4 +416,17 @@ public class PaperConfig { + private static void midTickChunkTasks() { + midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); + } ++ ++ public static boolean allowBlockPermanentBreakingExploits = false; ++ private static void allowBlockPermanentBreakingExploits() { ++ if (config.contains("allow-perm-block-break-exploits")) { ++ allowBlockPermanentBreakingExploits = config.getBoolean("allow-perm-block-break-exploits", false); ++ config.set("allow-perm-block-break-exploits", null); ++ } ++ ++ config.set("settings.unsupported-settings.allow-permanent-block-break-exploits-readme", "This setting controls if players should be able to break bedrock, end portals and other intended to be permanent blocks."); ++ allowBlockPermanentBreakingExploits = getBoolean("settings.unsupported-settings.allow-permanent-block-break-exploits", allowBlockPermanentBreakingExploits); ++ ++ } ++ + } +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index a9ecc2b4da587ca3d3c99f8c8af38092a02fb572..0b3479aae8f7cad7bd0b8b64aa2dead43baf4c56 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -153,6 +153,7 @@ public class Explosion { + for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { + BlockPosition blockposition = new BlockPosition(d4, d5, d6); + IBlockData iblockdata = this.world.getType(blockposition); ++ if (!iblockdata.isDestroyable()) continue; // Paper + Fluid fluid = iblockdata.getFluid(); // Paper + Optional optional = this.l.a(this, this.world, blockposition, iblockdata, fluid); + +@@ -306,7 +307,7 @@ public class Explosion { + IBlockData iblockdata = this.world.getType(blockposition); + Block block = iblockdata.getBlock(); + +- if (!iblockdata.isAir()) { ++ if (!iblockdata.isAir() && iblockdata.isDestroyable()) { // Paper + BlockPosition blockposition1 = blockposition.immutableCopy(); + + this.world.getMethodProfiler().enter("explosion_blocks"); +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 7ead848342bfbb5b20e95d716805f4b4fd36eb63..9369a0c6c0ae2d8518ebfb17f2c93ead2647ab8d 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -422,6 +422,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) { + // CraftBukkit start - tree generation + if (this.captureTreeGeneration) { ++ // Paper start ++ IBlockData type = getType(blockposition); ++ if (!type.isDestroyable()) return false; ++ // Paper end + CraftBlockState blockstate = capturedBlockStates.get(blockposition); + if (blockstate == null) { + blockstate = CapturedBlockState.getTreeBlockState(this, blockposition, i); +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index e5c43b383a93fac76333a67b41535ab009d1dcf3..cc512bd2e89382e7fdbc59b41640e95ccafbbfe9 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -62,6 +62,19 @@ public class Block extends BlockBase implements IMaterial { + protected final BlockStateList blockStateList; + private IBlockData blockData; + // Paper start ++ public final boolean isDestroyable() { ++ return com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || ++ this != Blocks.BEDROCK && ++ this != Blocks.END_PORTAL_FRAME && ++ this != Blocks.END_PORTAL && ++ this != Blocks.END_GATEWAY && ++ this != Blocks.COMMAND_BLOCK && ++ this != Blocks.REPEATING_COMMAND_BLOCK && ++ this != Blocks.CHAIN_COMMAND_BLOCK && ++ this != Blocks.BARRIER && ++ this != Blocks.STRUCTURE_BLOCK && ++ this != Blocks.JIGSAW; ++ } + public co.aikar.timings.Timing timing; + public co.aikar.timings.Timing getTiming() { + if (timing == null) { +diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java +index 7de86d6232eb84642fb6423a1b0a9f30d9df9f2b..e062fd288098127fae22a55562e0207ceaf50163 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java +@@ -194,6 +194,12 @@ public class BlockPiston extends BlockDirectional { + @Override + public boolean a(IBlockData iblockdata, World world, BlockPosition blockposition, int i, int j) { + EnumDirection enumdirection = (EnumDirection) iblockdata.get(BlockPiston.FACING); ++ // Paper start - prevent retracting when we're facing the wrong way (we were replaced before retraction could occur) ++ EnumDirection directionQueuedAs = EnumDirection.fromType1(j & 7); // Paper - copied from below ++ if (!com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits && enumdirection != directionQueuedAs) { ++ return false; ++ } ++ // Paper end - prevent retracting when we're facing the wrong way + + if (!world.isClientSide) { + boolean flag = this.a(world, blockposition, enumdirection); +@@ -225,7 +231,7 @@ public class BlockPiston extends BlockDirectional { + IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.MOVING_PISTON.getBlockData().set(BlockPistonMoving.a, enumdirection)).set(BlockPistonMoving.b, this.sticky ? BlockPropertyPistonType.STICKY : BlockPropertyPistonType.DEFAULT); + + world.setTypeAndData(blockposition, iblockdata1, 20); +- world.setTileEntity(blockposition, BlockPistonMoving.a((IBlockData) this.getBlockData().set(BlockPiston.FACING, EnumDirection.fromType1(j & 7)), enumdirection, false, true)); ++ world.setTileEntity(blockposition, BlockPistonMoving.a((IBlockData) this.getBlockData().set(BlockPiston.FACING, EnumDirection.fromType1(j & 7)), enumdirection, false, true)); // Paper - diff on change, j is facing direction - copy this above + world.update(blockposition, iblockdata1.getBlock()); + iblockdata1.a(world, blockposition, 2); + if (this.sticky) { +@@ -254,7 +260,14 @@ public class BlockPiston extends BlockDirectional { + } + } + } else { +- world.a(blockposition.shift(enumdirection), false); ++ // Paper start - fix headless pistons breaking blocks ++ BlockPosition headPos = blockposition.shift(enumdirection); ++ if (com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || world.getType(headPos) == Blocks.PISTON_HEAD.getBlockData().set(FACING, enumdirection)) { // double check to make sure we're not a headless piston. ++ world.setAir(headPos, false); ++ } else { ++ ((WorldServer)world).getChunkProvider().flagDirty(headPos); // ... fix client desync ++ } ++ // Paper end - fix headless pistons breaking blocks + } + + world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_PISTON_CONTRACT, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F); +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +index 57857cc33603cf278de424b540a3d4a5943584c9..2a785ea58a7bdc80c703a60bc6ed602dc8040aa0 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +@@ -190,7 +190,7 @@ public abstract class BlockBase { + + @Deprecated + public boolean a(IBlockData iblockdata, BlockActionContext blockactioncontext) { +- return this.material.isReplaceable() && (blockactioncontext.getItemStack().isEmpty() || blockactioncontext.getItemStack().getItem() != this.getItem()); ++ return this.material.isReplaceable() && (blockactioncontext.getItemStack().isEmpty() || blockactioncontext.getItemStack().getItem() != this.getItem()) && (iblockdata.isDestroyable() || (blockactioncontext.getEntity() != null && blockactioncontext.getEntity().abilities.canInstantlyBuild)); // Paper + } + + @Deprecated +@@ -394,7 +394,11 @@ public abstract class BlockBase { + public Block getBlock() { + return (Block) this.c; + } +- ++ // Paper start ++ public final boolean isDestroyable() { ++ return getBlock().isDestroyable(); ++ } ++ // Paper end + public Material getMaterial() { + return this.g; + } +@@ -484,7 +488,7 @@ public abstract class BlockBase { + } + + public EnumPistonReaction getPushReaction() { +- return this.getBlock().getPushReaction(this.p()); ++ return !isDestroyable() ? EnumPistonReaction.BLOCK : this.getBlock().getPushReaction(this.p()); // Paper + } + + public boolean i(IBlockAccess iblockaccess, BlockPosition blockposition) { diff --git a/patches/server-unmapped/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch b/patches/server-unmapped/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch new file mode 100644 index 0000000000..0b519eafdf --- /dev/null +++ b/patches/server-unmapped/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch @@ -0,0 +1,394 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 May 2020 23:30:30 -0400 +Subject: [PATCH] Optimize NibbleArray to use pooled buffers + +Massively reduces memory allocation of 2048 byte buffers by using +an object pool for these. + +Uses lots of advanced new capabilities of the Paper codebase :) + +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java +index 247d969e7d1aa59d9650fce1032aaa09db3903e5..9050ff7180f63c1f5756570446c4d0a8cc767779 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java +@@ -1,12 +1,16 @@ + package net.minecraft.network.protocol.game; + + import com.google.common.collect.Lists; ++import io.netty.channel.ChannelFuture; // Paper ++ + import java.io.IOException; + import java.util.Iterator; + import java.util.List; + import net.minecraft.core.SectionPosition; + import net.minecraft.network.PacketDataSerializer; + import net.minecraft.network.protocol.Packet; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.chunk.NibbleArray; +@@ -24,14 +28,43 @@ public class PacketPlayOutLightUpdate implements Packet { + private List h; + private boolean i; + ++ // Paper start ++ java.lang.Runnable cleaner1; ++ java.lang.Runnable cleaner2; ++ java.util.concurrent.atomic.AtomicInteger remainingSends = new java.util.concurrent.atomic.AtomicInteger(0); ++ ++ @Override ++ public void onPacketDispatch(EntityPlayer player) { ++ remainingSends.incrementAndGet(); ++ } ++ ++ @Override ++ public void onPacketDispatchFinish(EntityPlayer player, ChannelFuture future) { ++ if (remainingSends.decrementAndGet() <= 0) { ++ // incase of any race conditions, schedule this delayed ++ MCUtil.scheduleTask(5, () -> { ++ if (remainingSends.get() == 0) { ++ cleaner1.run(); ++ cleaner2.run(); ++ } ++ }, "Light Packet Release"); ++ } ++ } ++ ++ @Override ++ public boolean hasFinishListener() { ++ return true; ++ } ++ ++ // Paper end + public PacketPlayOutLightUpdate() {} + + public PacketPlayOutLightUpdate(ChunkCoordIntPair chunkcoordintpair, LightEngine lightengine, boolean flag) { + this.a = chunkcoordintpair.x; + this.b = chunkcoordintpair.z; + this.i = flag; +- this.g = Lists.newArrayList(); +- this.h = Lists.newArrayList(); ++ this.g = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper ++ this.h = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper + + for (int i = 0; i < 18; ++i) { + NibbleArray nibblearray = lightengine.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, -1 + i)); +@@ -42,7 +75,7 @@ public class PacketPlayOutLightUpdate implements Packet { + this.e |= 1 << i; + } else { + this.c |= 1 << i; +- this.g.add(nibblearray.asBytes().clone()); ++ this.g.add(nibblearray.getCloneIfSet()); // Paper + } + } + +@@ -51,7 +84,7 @@ public class PacketPlayOutLightUpdate implements Packet { + this.f |= 1 << i; + } else { + this.d |= 1 << i; +- this.h.add(nibblearray1.asBytes().clone()); ++ this.h.add(nibblearray1.getCloneIfSet()); // Paper + } + } + } +@@ -64,8 +97,8 @@ public class PacketPlayOutLightUpdate implements Packet { + this.i = flag; + this.c = i; + this.d = j; +- this.g = Lists.newArrayList(); +- this.h = Lists.newArrayList(); ++ this.g = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper ++ this.h = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper + + for (int k = 0; k < 18; ++k) { + NibbleArray nibblearray; +@@ -73,7 +106,7 @@ public class PacketPlayOutLightUpdate implements Packet { + if ((this.c & 1 << k) != 0) { + nibblearray = lightengine.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, -1 + k)); + if (nibblearray != null && !nibblearray.c()) { +- this.g.add(nibblearray.asBytes().clone()); ++ this.g.add(nibblearray.getCloneIfSet()); // Paper + } else { + this.c &= ~(1 << k); + if (nibblearray != null) { +@@ -85,7 +118,7 @@ public class PacketPlayOutLightUpdate implements Packet { + if ((this.d & 1 << k) != 0) { + nibblearray = lightengine.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, -1 + k)); + if (nibblearray != null && !nibblearray.c()) { +- this.h.add(nibblearray.asBytes().clone()); ++ this.h.add(nibblearray.getCloneIfSet()); // Paper + } else { + this.d &= ~(1 << k); + if (nibblearray != null) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java +index 86b4db483787c5fd10461f7d7e90a772ee049599..b82420e9a5d42a4383d24921614fe613c640edb9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java ++++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java +@@ -1,18 +1,78 @@ + // mc-dev import + package net.minecraft.world.level.chunk; + ++import com.destroystokyo.paper.util.pooled.PooledObjects; // Paper ++ ++import javax.annotation.Nonnull; + import javax.annotation.Nullable; + import net.minecraft.SystemUtils; ++import net.minecraft.server.MCUtil; + + public class NibbleArray { + +- @Nullable +- protected byte[] a; ++ // Paper start ++ public static byte[] EMPTY_NIBBLE = new byte[2048]; ++ private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072); ++ private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8)); ++ public static final PooledObjects BYTE_2048 = new PooledObjects<>(() -> new byte[2048], maxPoolSize); ++ public static void releaseBytes(byte[] bytes) { ++ if (bytes != null && bytes != EMPTY_NIBBLE && bytes.length == 2048) { ++ System.arraycopy(EMPTY_NIBBLE, 0, bytes, 0, 2048); ++ BYTE_2048.release(bytes); ++ } ++ } ++ ++ public NibbleArray markPoolSafe(byte[] bytes) { ++ if (bytes != EMPTY_NIBBLE) this.a = bytes; ++ return markPoolSafe(); ++ } ++ public NibbleArray markPoolSafe() { ++ poolSafe = true; ++ return this; ++ } ++ public byte[] getIfSet() { ++ return this.a != null ? this.a : EMPTY_NIBBLE; ++ } ++ public byte[] getCloneIfSet() { ++ if (a == null) { ++ return EMPTY_NIBBLE; ++ } ++ byte[] ret = BYTE_2048.acquire(); ++ System.arraycopy(getIfSet(), 0, ret, 0, 2048); ++ return ret; ++ } ++ ++ public NibbleArray cloneAndSet(byte[] bytes) { ++ if (bytes != null && bytes != EMPTY_NIBBLE) { ++ this.a = BYTE_2048.acquire(); ++ System.arraycopy(bytes, 0, this.a, 0, 2048); ++ } ++ return this; ++ } ++ boolean poolSafe = false; ++ public java.lang.Runnable cleaner; ++ private void registerCleaner() { ++ if (!poolSafe) { ++ cleaner = MCUtil.registerCleaner(this, this.a, NibbleArray::releaseBytes); ++ } else { ++ cleaner = MCUtil.once(() -> NibbleArray.releaseBytes(this.a)); ++ } ++ } ++ // Paper end ++ @Nullable protected byte[] a; ++ + + public NibbleArray() {} + + public NibbleArray(byte[] abyte) { ++ // Paper start ++ this(abyte, false); ++ } ++ public NibbleArray(byte[] abyte, boolean isSafe) { + this.a = abyte; ++ if (!isSafe) this.a = getCloneIfSet(); // Paper - clone for safety ++ registerCleaner(); ++ // Paper end + if (abyte.length != 2048) { + throw (IllegalArgumentException) SystemUtils.c((Throwable) (new IllegalArgumentException("ChunkNibbleArrays should be 2048 bytes not: " + abyte.length))); + } +@@ -46,7 +106,8 @@ public class NibbleArray { + + public void a(int i, int j) { // PAIL: private -> public + if (this.a == null) { +- this.a = new byte[2048]; ++ this.a = BYTE_2048.acquire(); // Paper ++ registerCleaner();// Paper + } + + int k = this.d(i); +@@ -68,14 +129,36 @@ public class NibbleArray { + public byte[] asBytes() { + if (this.a == null) { + this.a = new byte[2048]; ++ } else { // Paper start ++ // Accessor may need this object past garbage collection so need to clone it and return pooled value ++ // If we know its safe for pre GC access, use asBytesPoolSafe(). If you just need read, use getIfSet() ++ Runnable cleaner = this.cleaner; ++ if (cleaner != null) { ++ this.a = this.a.clone(); ++ cleaner.run(); // release the previously pooled value ++ this.cleaner = null; ++ } ++ } ++ // Paper end ++ ++ return this.a; ++ } ++ ++ @Nonnull ++ public byte[] asBytesPoolSafe() { ++ if (this.a == null) { ++ this.a = BYTE_2048.acquire(); // Paper ++ registerCleaner(); // Paper + } + ++ //noinspection ConstantConditions + return this.a; + } ++ // Paper end + + public NibbleArray copy() { return this.b(); } // Paper - OBFHELPER + public NibbleArray b() { +- return this.a == null ? new NibbleArray() : new NibbleArray((byte[]) this.a.clone()); ++ return this.a == null ? new NibbleArray() : new NibbleArray(this.a); // Paper - clone in ctor + } + + public String toString() { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index e16e046d165330326ed220c9c440a637007f3137..91bcbf7156dd90b00e2d53bb6bff4abc44ecb721 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -435,11 +435,11 @@ public class ChunkRegionLoader { + } + + if (nibblearray != null && !nibblearray.c()) { +- nbttagcompound2.setByteArray("BlockLight", nibblearray.asBytes()); ++ nbttagcompound2.setByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper + } + + if (nibblearray1 != null && !nibblearray1.c()) { +- nbttagcompound2.setByteArray("SkyLight", nibblearray1.asBytes()); ++ nbttagcompound2.setByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper + } + + nbttaglist.add(nbttagcompound2); +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java +index 5b1ff4ff87591dd4ff0b79e4ac6ff0494fc3d0f8..9ba9efb181b9607f25b7c921e69e4c59b182d429 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java +@@ -156,7 +156,7 @@ public abstract class LightEngineStorage> e + protected NibbleArray j(long i) { + NibbleArray nibblearray = (NibbleArray) this.i.get(i); + +- return nibblearray != null ? nibblearray : new NibbleArray(); ++ return nibblearray != null ? nibblearray : new NibbleArray().markPoolSafe(); // Paper + } + + protected void a(LightEngineLayer lightenginelayer, long i) { +@@ -338,12 +338,12 @@ public abstract class LightEngineStorage> e + + protected void a(long i, @Nullable NibbleArray nibblearray, boolean flag) { + if (nibblearray != null) { +- this.i.put(i, nibblearray); ++ NibbleArray remove = this.i.put(i, nibblearray); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed + if (!flag) { + this.n.add(i); + } + } else { +- this.i.remove(i); ++ NibbleArray remove = this.i.remove(i); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed + } + + } +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java +index ed7864c552054fc47c6010a094230ce4aebf1c54..da78d4c4b5f8af4648ac82d63c21f6a2a5b73ecb 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.lighting; + + import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; + import javax.annotation.Nullable; ++import net.minecraft.server.MCUtil; + import net.minecraft.world.level.chunk.NibbleArray; + + public abstract class LightEngineStorageArray> { +@@ -34,7 +35,9 @@ public abstract class LightEngineStorageArray +Date: Mon, 27 Apr 2020 02:48:06 -0700 +Subject: [PATCH] Reduce MutableInt allocations from light engine + +We can abuse the fact light is single threaded and share an instance +per light engine instance + +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java +index 2a0a5a70c795ba33780c8db774eaf9769a85daa7..f6198069e3ca421b4f551939263c7cf8bd5b754e 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java +@@ -16,6 +16,7 @@ public final class LightEngineBlock extends LightEngineLayer= 15) { +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java +index 113c575a16121aa1146f21a6f41ebd9d12a0c924..37fa5faea6e2972e3eb8a3cbd1913ef38dc9456f 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java +@@ -15,6 +15,7 @@ public final class LightEngineSky extends LightEngineLayer= 15) { + return k; + } else { +- MutableInt mutableint = new MutableInt(); ++ //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded + IBlockData iblockdata = this.a(j, mutableint); + + if (mutableint.getValue() >= 15) { diff --git a/patches/server-unmapped/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/patches/server-unmapped/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch new file mode 100644 index 0000000000..40cf990128 --- /dev/null +++ b/patches/server-unmapped/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 27 Apr 2020 00:04:16 -0700 +Subject: [PATCH] Reduce allocation of Vec3D by entity tracker + + +diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +index b64aa6c9ce906b08e43891f8c465fa4e8b2a8906..58dd349adf2bc9bac6569464ef7a7aec81729e79 100644 +--- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java ++++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +@@ -155,8 +155,12 @@ public class EntityTrackerEntry { + ++this.o; + i = MathHelper.d(this.tracker.yaw * 256.0F / 360.0F); + j = MathHelper.d(this.tracker.pitch * 256.0F / 360.0F); +- Vec3D vec3d = this.tracker.getPositionVector().d(PacketPlayOutEntity.a(this.xLoc, this.yLoc, this.zLoc)); +- boolean flag1 = vec3d.g() >= 7.62939453125E-6D; ++ // Paper start - reduce allocation of Vec3D here ++ double vec3d_dx = this.tracker.locX() - 2.44140625E-4D*(this.xLoc); ++ double vec3d_dy = this.tracker.locY() - 2.44140625E-4D*(this.yLoc); ++ double vec3d_dz = this.tracker.locZ() - 2.44140625E-4D*(this.zLoc); ++ boolean flag1 = (vec3d_dx * vec3d_dx + vec3d_dy * vec3d_dy + vec3d_dz * vec3d_dz) >= 7.62939453125E-6D; ++ // Paper end - reduce allocation of Vec3D here + Packet packet1 = null; + boolean flag2 = flag1 || this.tickCounter % 60 == 0; + boolean flag3 = Math.abs(i - this.yRot) >= 1 || Math.abs(j - this.xRot) >= 1; +@@ -173,9 +177,11 @@ public class EntityTrackerEntry { + // CraftBukkit end + + if (this.tickCounter > 0 || this.tracker instanceof EntityArrow) { +- long k = PacketPlayOutEntity.a(vec3d.x); +- long l = PacketPlayOutEntity.a(vec3d.y); +- long i1 = PacketPlayOutEntity.a(vec3d.z); ++ // Paper start - remove allocation of Vec3D here ++ long k = PacketPlayOutEntity.a(vec3d_dx); ++ long l = PacketPlayOutEntity.a(vec3d_dy); ++ long i1 = PacketPlayOutEntity.a(vec3d_dz); ++ // Paper end - remove allocation of Vec3D here + boolean flag4 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L; + + if (!flag4 && this.o <= 400 && !this.q && this.r == this.tracker.isOnGround()) { +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index a7e3a979dca4dd7705a8f80366677378f0643f27..c3394b22d1a22fd83ff43473da34704ad547836f 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -2235,9 +2235,14 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + public void updatePlayer(EntityPlayer entityplayer) { + org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot + if (entityplayer != this.tracker) { +- Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 ++ // Paper start - remove allocation of Vec3D here ++ //Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 ++ double vec3d_dx = entityplayer.locX() - this.tracker.locX(); ++ double vec3d_dy = entityplayer.locY() - this.tracker.locY(); ++ double vec3d_dz = entityplayer.locZ() - this.tracker.locZ(); ++ // Paper end - remove allocation of Vec3D here + int i = Math.min(this.b(), (PlayerChunkMap.this.viewDistance - 1) * 16); +- boolean flag = vec3d.x >= (double) (-i) && vec3d.x <= (double) i && vec3d.z >= (double) (-i) && vec3d.z <= (double) i && this.tracker.a(entityplayer); ++ boolean flag = vec3d_dx >= (double) (-i) && vec3d_dx <= (double) i && vec3d_dz >= (double) (-i) && vec3d_dz <= (double) i && this.tracker.a(entityplayer); // Paper - remove allocation of Vec3D here + + if (flag) { + boolean flag1 = this.tracker.attachedToPlayer; diff --git a/patches/server-unmapped/0480-Ensure-safe-gateway-teleport.patch b/patches/server-unmapped/0480-Ensure-safe-gateway-teleport.patch new file mode 100644 index 0000000000..cf98a288ea --- /dev/null +++ b/patches/server-unmapped/0480-Ensure-safe-gateway-teleport.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Fri, 15 May 2020 01:10:03 -0400 +Subject: [PATCH] Ensure safe gateway teleport + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java +index b7548d0b3938d95328fc86db4000190532eaa8f5..855c49164277ca96ca08fb204d851a5ad6789990 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java +@@ -89,9 +89,14 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick + } else if (!this.world.isClientSide) { + List list = this.world.a(Entity.class, new AxisAlignedBB(this.getPosition()), TileEntityEndGateway::a); + +- if (!list.isEmpty()) { +- this.b((Entity) list.get(this.world.random.nextInt(list.size()))); ++ // Paper start ++ for (Entity entity : list) { ++ if (entity.canPortal()) { ++ this.b(entity); ++ break; ++ } + } ++ // Paper end + + if (this.age % 2400L == 0L) { + this.h(); diff --git a/patches/server-unmapped/0481-Add-option-for-console-having-all-permissions.patch b/patches/server-unmapped/0481-Add-option-for-console-having-all-permissions.patch new file mode 100644 index 0000000000..908755e004 --- /dev/null +++ b/patches/server-unmapped/0481-Add-option-for-console-having-all-permissions.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 16 May 2020 10:12:15 +0200 +Subject: [PATCH] Add option for console having all permissions + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 5f3b0d95cc7e6a0434d78ea7305a70689c41c71c..7f140333c2e62012fa572c1a061d84432426997f 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -429,4 +429,9 @@ public class PaperConfig { + + } + ++ public static boolean consoleHasAllPermissions = false; ++ private static void consoleHasAllPermissions() { ++ consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); ++ } ++ + } +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 202fa94d5dc55b549475ae0309bbcfca8f1b2c96..ec0956a98c133bcd3d4f92f696c667eab6ff98f1 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -1889,7 +1889,7 @@ public abstract class EntityHuman extends EntityLiving { + } + } + +- protected void releaseShoulderEntities() { ++ public void releaseShoulderEntities() { // Paper - protected -> public + if (this.e + 20L < this.world.getTime()) { + // CraftBukkit start + if (this.spawnEntityFromShoulder(this.getShoulderEntityLeft())) { +diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +index af986adfdb547cb61fbd52f0f89858f1a9e52cc3..80a67deaeaae3b3f0ceb9a298de5bb38b8ee707b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +@@ -86,5 +86,15 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co + public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { + this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); + } ++ ++ @Override ++ public boolean hasPermission(String name) { ++ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); ++ } ++ ++ @Override ++ public boolean hasPermission(org.bukkit.permissions.Permission perm) { ++ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java +index 24662d58cb4a9bf2f3b252858b504165d91d4419..a6f3594def0abe076ff44fcfa61dd05bee729387 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java +@@ -39,4 +39,16 @@ public class CraftRemoteConsoleCommandSender extends ServerCommandSender impleme + public void setOp(boolean value) { + throw new UnsupportedOperationException("Cannot change operator status of remote controller."); + } ++ ++ // Paper start ++ @Override ++ public boolean hasPermission(String name) { ++ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); ++ } ++ ++ @Override ++ public boolean hasPermission(org.bukkit.permissions.Permission perm) { ++ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/patches/server-unmapped/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch new file mode 100644 index 0000000000..5f3ad1df79 --- /dev/null +++ b/patches/server-unmapped/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 23 May 2020 01:31:06 -0400 +Subject: [PATCH] Fix Non Full Status Chunk NBT Memory Leak + +Any full status chunk that was requested for any status less than full +would hold onto their entire nbt tree and every variable in that function. + +This was due to use of a lambda that persists on the Chunk object +until that chunk reaches FULL status. + +With introduction of no tick, we greatly increased the number of non +full chunks so this was really starting to hurt. + +We further improve it by making a copy of the nbt tag with only the memory +it needs, so that we dont have to hold a copy to the entire compound. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index 91bcbf7156dd90b00e2d53bb6bff4abc44ecb721..8e4924cd649c350520cba54a0e1497d5acf089ff 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -22,6 +22,7 @@ import net.minecraft.core.BlockPosition; + import net.minecraft.core.IRegistry; + import net.minecraft.core.RegistryBlocks; + import net.minecraft.core.SectionPosition; ++import net.minecraft.nbt.NBTBase; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.nbt.NBTTagList; + import net.minecraft.nbt.NBTTagLongArray; +@@ -199,15 +200,9 @@ public class ChunkRegionLoader { + object2 = protochunkticklist1; + } + +- object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { +- loadEntities(nbttagcompound1, chunk); +- // CraftBukkit start - load chunk persistent data from nbt +- net.minecraft.nbt.NBTBase persistentBase = nbttagcompound1.get("ChunkBukkitValues"); +- if (persistentBase instanceof NBTTagCompound) { +- chunk.persistentDataContainer.putAll((NBTTagCompound) persistentBase); +- } +- // CraftBukkit end +- }); ++ object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. ++ createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities", "ChunkBukkitValues")) // Paper - move CB Chunk PDC into here ++ );// Paper end + } else { + ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter + +@@ -313,6 +308,50 @@ public class ChunkRegionLoader { + return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading + } + } ++ // Paper start ++ ++ /** ++ * This wrapper will error out if any key is accessed that wasn't copied so we can catch it easy on an update ++ */ ++ private static class SafeNBTCopy extends NBTTagCompound { ++ private final java.util.Set keys = new java.util.HashSet(); ++ public SafeNBTCopy(NBTTagCompound base, String... keys) { ++ for (String key : keys) { ++ this.keys.add(key); ++ final NBTBase nbtBase = base.get(key); ++ if (nbtBase != null) { ++ this.set(key, nbtBase); ++ } ++ } ++ } ++ ++ @Override ++ public boolean hasKey(String s) { ++ if (super.hasKey(s)) { ++ return true; ++ } else if (keys.contains(s)) { ++ return false; ++ } ++ throw new IllegalStateException("Missing Key " + s + " in SafeNBTCopy"); ++ } ++ ++ @Override ++ public boolean hasKeyOfType(String s, int i) { ++ return hasKey(s) && super.hasKeyOfType(s, i); ++ } ++ } ++ private static java.util.function.Consumer createLoadEntitiesConsumer(NBTTagCompound nbt) { ++ return (chunk) -> { ++ loadEntities(nbt, chunk); ++ // CraftBukkit start - load chunk persistent data from nbt ++ NBTBase persistentBase = nbt.get("ChunkBukkitValues"); ++ if (persistentBase instanceof NBTTagCompound) { ++ chunk.persistentDataContainer.putAll((NBTTagCompound) persistentBase); ++ } ++ // CraftBukkit end ++ }; ++ } ++ // Paper end + + // Paper start - async chunk save for unload + public static final class AsyncSaveData { diff --git a/patches/server-unmapped/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch b/patches/server-unmapped/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch new file mode 100644 index 0000000000..3581cde231 --- /dev/null +++ b/patches/server-unmapped/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Tue, 12 May 2020 23:02:43 +0200 +Subject: [PATCH] Workaround for Client Lag Spikes (MC-162253) + +When crossing certain chunk boundaries, the client needlessly +calculates light maps for chunk neighbours. In some specific map +configurations, these calculations cause a 500ms+ freeze on the Client. + +This patch basically serves as a workaround by sending light maps +to the client, so that it doesn't attempt to calculate them. +This mitigates the frametime impact to a minimum (but it's still there). + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index c3394b22d1a22fd83ff43473da34704ad547836f..6ddbc83a08be4e7aa5cd85cf78f14604d4759f30 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -85,6 +85,7 @@ import net.minecraft.world.level.World; + import net.minecraft.world.level.chunk.Chunk; + import net.minecraft.world.level.chunk.ChunkConverter; + import net.minecraft.world.level.chunk.ChunkGenerator; ++import net.minecraft.world.level.chunk.ChunkSection; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.IChunkAccess; + import net.minecraft.world.level.chunk.ILightAccess; +@@ -2063,9 +2064,68 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + public final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER + private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { + if (apacket[0] == null) { ++ // Paper start - add 8 for light fix workaround ++ if (apacket.length != 10) { // in case Plugins call sendChunk, resize ++ apacket = new Packet[10]; ++ } ++ // Paper end + apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(entityplayer, chunk, 65535)); // Paper - Anti-Xray - Bypass + apacket[1] = new PacketPlayOutLightUpdate(chunk.getPos(), this.lightEngine, true); ++ ++ // Paper start - Fix MC-162253 ++ final int lightMask = getLightMask(chunk); ++ int i = 1; ++ for (int x = -1; x <= 1; x++) { ++ for (int z = -1; z <= 1; z++) { ++ if (x == 0 && z == 0) { ++ continue; ++ } ++ ++ ++i; ++ ++ if (!chunk.isNeighbourLoaded(x, z)) { ++ continue; ++ } ++ ++ final Chunk neighbor = chunk.getRelativeNeighbourIfLoaded(x, z); ++ final int updateLightMask = lightMask & ~getCeilingLightMask(neighbor); ++ ++ if (updateLightMask == 0) { ++ continue; ++ } ++ ++ apacket[i] = new PacketPlayOutLightUpdate(new ChunkCoordIntPair(chunk.getPos().x + x, chunk.getPos().z + z), lightEngine, updateLightMask, 0, true); ++ } ++ } ++ } ++ ++ final int viewDistance = playerViewDistanceBroadcastMap.getLastViewDistance(entityplayer); ++ final long lastPosition = playerViewDistanceBroadcastMap.getLastCoordinate(entityplayer); ++ ++ int j = 1; ++ for (int x = -1; x <= 1; x++) { ++ for (int z = -1; z <= 1; z++) { ++ if (x == 0 && z == 0) { ++ continue; ++ } ++ ++ ++j; ++ ++ Packet packet = apacket[j]; ++ if (packet == null) { ++ continue; ++ } ++ ++ final int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - (chunk.getPos().x + x)); ++ final int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - (chunk.getPos().z + z)); ++ ++ if (Math.max(distX, distZ) > viewDistance) { ++ continue; ++ } ++ entityplayer.playerConnection.sendPacket(packet); ++ } + } ++ // Paper end - Fix MC-162253 + + entityplayer.a(chunk.getPos(), apacket[0], apacket[1]); + PacketDebug.a(this.world, chunk.getPos()); +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index 90e895e9eac6158a28de4a30589bf7538e5ec9cc..34a9f7b2f998f77b1279516cd09397ab6c2ac1cc 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -280,7 +280,7 @@ public class Chunk implements IChunkAccess { + + // broadcast + Object[] backingSet = inRange.getBackingSet(); +- Packet[] chunkPackets = new Packet[2]; ++ Packet[] chunkPackets = new Packet[10]; + for (int index = 0, len = backingSet.length; index < len; ++index) { + Object temp = backingSet[index]; + if (!(temp instanceof EntityPlayer)) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +index 973aa060d6964c7d470bc7aff89b879daf1df153..8fe060c3b2ad0873f96218eb7d02cdff3279224e 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java +@@ -107,6 +107,7 @@ public class ChunkSection { + return this.nonEmptyBlockCount == 0; + } + ++ public static boolean isEmpty(@Nullable ChunkSection chunksection) { return a(chunksection) ; } // Paper - OBFHELPER + public static boolean a(@Nullable ChunkSection chunksection) { + return chunksection == Chunk.a || chunksection.c(); + } diff --git a/patches/server-unmapped/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server-unmapped/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch new file mode 100644 index 0000000000..107312d21f --- /dev/null +++ b/patches/server-unmapped/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch @@ -0,0 +1,1326 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 11 Apr 2020 03:56:07 -0400 +Subject: [PATCH] Implement Chunk Priority / Urgency System for Chunks + +Mark chunks that are blocking main thread for world generation as urgent + +Implements a general priority system so that chunks that are sorted in +the generator queues can prioritize certain chunks over another. + +Urgent chunks will jump to the front of the line, ensuring that a +sync chunk load on an ungenerated chunk does not lag the server for +a long period of time if the servers generator queues are filled with +lots of chunks already. + +This massively reduces the lag spikes from sync chunk gens. + +Then we further prioritize loading order so nearby chunks have higher +priority than distant chunks, reducing the pressure a high no tick +view distance holds on you. + +Chunks in front of the player have higher priority, to help with +fast traveling players keep up with their movement. + +diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +index 8e642f450b974d81f128d26edfd40915554db638..dc641664abe8ff6b36c69c7d21a3200d160ff1b6 100644 +--- a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java ++++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +@@ -108,7 +108,7 @@ public final class ChunkTaskManager { + } + + static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z) { +- dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); ++ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 4); + } + + static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z, int indent, int maxDepth) { +@@ -129,6 +129,30 @@ public final class ChunkTaskManager { + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getChunkStatus().toString())); + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + PlayerChunk.getChunkStatus(chunkHolder.getTicketLevel())); + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Priority - " + chunkHolder.getCurrentPriority()); ++ ++ if (!chunkHolder.neighbors.isEmpty()) { ++ if (indent >= maxDepth) { ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: (Can't show, too deeply nested)"); ++ return; ++ } ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: "); ++ for (PlayerChunk neighbor : chunkHolder.neighbors.keySet()) { ++ ChunkStatus status = neighbor.getChunkHolderStatus(); ++ if (status != null && status.isAtLeastStatus(PlayerChunk.getChunkStatus(neighbor.getTicketLevel()))) { ++ continue; ++ } ++ int nx = neighbor.location.x; ++ int nz = neighbor.location.z; ++ if (seenChunks.contains(neighbor)) { ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + " (CIRCULAR)"); ++ continue; ++ } ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + ":"); ++ dumpChunkInfo(seenChunks, neighbor, nx, nz, indent + 1, maxDepth); ++ } ++ } ++ + } + } + +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 17de074111a174f3a39a4477afc3ad62e04a73b5..1d72af9cace7aa8f1d20c7c1c5be621f533e2dad 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -673,6 +673,7 @@ public final class MCUtil { + chunkData.addProperty("x", playerChunk.location.x); + chunkData.addProperty("z", playerChunk.location.z); + chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); ++ chunkData.addProperty("priority", playerChunk.getCurrentPriority()); + chunkData.addProperty("state", PlayerChunk.getChunkState(playerChunk.getTicketLevel()).toString()); + chunkData.addProperty("queued-for-unload", chunkMap.unloadQueue.contains(playerChunk.location.pair())); + chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); +diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +index 2bbdcedf4856080ea9232effdf3bdae9c26c425b..a3c44fdfca8290313b9b1117b984533183b583ad 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +@@ -21,7 +21,10 @@ import java.util.Set; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.Executor; + import javax.annotation.Nullable; ++import net.minecraft.core.BlockPosition; + import net.minecraft.core.SectionPosition; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.util.ArraySetSorted; + import net.minecraft.util.thread.Mailbox; + import net.minecraft.world.level.ChunkCoordIntPair; +@@ -29,6 +32,7 @@ import net.minecraft.world.level.chunk.Chunk; + import net.minecraft.world.level.chunk.ChunkStatus; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import org.spigotmc.AsyncCatcher; // Paper + + public abstract class ChunkMapDistance { + +@@ -52,7 +56,7 @@ public abstract class ChunkMapDistance { + private final ChunkTaskQueueSorter i; + private final Mailbox> j; + private final Mailbox k; +- private final LongSet l = new LongOpenHashSet(); ++ private final LongSet l = new LongOpenHashSet(); public final LongSet getOnPlayerTicketAddQueue() { return l; } // Paper - OBFHELPER + private final Executor m; + private long currentTick; + +@@ -90,6 +94,7 @@ public abstract class ChunkMapDistance { + } + + private static int getLowestTicketLevel(ArraySetSorted> arraysetsorted) { ++ AsyncCatcher.catchOp("ChunkMapDistance::getLowestTicketLevel"); // Paper + return !arraysetsorted.isEmpty() ? ((Ticket) arraysetsorted.b()).b() : PlayerChunkMap.GOLDEN_TICKET + 1; + } + +@@ -103,6 +108,7 @@ public abstract class ChunkMapDistance { + + public boolean a(PlayerChunkMap playerchunkmap) { + //this.f.a(); // Paper - no longer used ++ AsyncCatcher.catchOp("DistanceManagerTick"); // Paper + this.g.a(); + int i = Integer.MAX_VALUE - this.ticketLevelTracker.a(Integer.MAX_VALUE); + boolean flag = i != 0; +@@ -113,11 +119,13 @@ public abstract class ChunkMapDistance { + + // Paper start + if (!this.pendingChunkUpdates.isEmpty()) { ++ this.pollingPendingChunkUpdates = true; try { + while(!this.pendingChunkUpdates.isEmpty()) { + PlayerChunk remove = this.pendingChunkUpdates.remove(); + remove.isUpdateQueued = false; + remove.a(playerchunkmap); + } ++ } finally { this.pollingPendingChunkUpdates = false; } + // Paper end + return true; + } else { +@@ -153,8 +161,10 @@ public abstract class ChunkMapDistance { + return flag; + } + } ++ boolean pollingPendingChunkUpdates = false; // Paper + + private boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ AsyncCatcher.catchOp("ChunkMapDistance::addTicket"); // Paper + ArraySetSorted> arraysetsorted = this.e(i); + int j = getLowestTicketLevel(arraysetsorted); + Ticket ticket1 = (Ticket) arraysetsorted.a(ticket); // CraftBukkit - decompile error +@@ -168,7 +178,9 @@ public abstract class ChunkMapDistance { + } + + private boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ AsyncCatcher.catchOp("ChunkMapDistance::removeTicket"); // Paper + ArraySetSorted> arraysetsorted = this.e(i); ++ int oldLevel = getLowestTicketLevel(arraysetsorted); // Paper + + boolean removed = false; // CraftBukkit + if (arraysetsorted.remove(ticket)) { +@@ -179,7 +191,8 @@ public abstract class ChunkMapDistance { + this.tickets.remove(i); + } + +- this.ticketLevelTracker.update(i, getLowestTicketLevel(arraysetsorted), false); ++ int newLevel = getLowestTicketLevel(arraysetsorted); // Paper ++ if (newLevel > oldLevel) this.ticketLevelTracker.update(i, newLevel, false); // Paper + return removed; // CraftBukkit + } + +@@ -188,6 +201,135 @@ public abstract class ChunkMapDistance { + this.addTicketAtLevel(tickettype, chunkcoordintpair, i, t0); + } + ++ // Paper start ++ public static final int PRIORITY_TICKET_LEVEL = PlayerChunkMap.GOLDEN_TICKET; ++ public static final int URGENT_PRIORITY = 29; ++ public boolean delayDistanceManagerTick = false; ++ public boolean markUrgent(ChunkCoordIntPair coords) { ++ return addPriorityTicket(coords, TicketType.URGENT, URGENT_PRIORITY); ++ } ++ public boolean markHighPriority(ChunkCoordIntPair coords, int priority) { ++ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); ++ return addPriorityTicket(coords, TicketType.PRIORITY, priority); ++ } ++ ++ public void markAreaHighPriority(ChunkCoordIntPair center, int priority, int radius) { ++ delayDistanceManagerTick = true; ++ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); ++ int finalPriority = priority; ++ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { ++ addPriorityTicket(coords, TicketType.PRIORITY, finalPriority); ++ }); ++ delayDistanceManagerTick = false; ++ chunkMap.world.getChunkProvider().tickDistanceManager(); ++ } ++ ++ public void clearAreaPriorityTickets(ChunkCoordIntPair center, int radius) { ++ delayDistanceManagerTick = true; ++ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { ++ this.removeTicket(coords.pair(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); ++ }); ++ delayDistanceManagerTick = false; ++ chunkMap.world.getChunkProvider().tickDistanceManager(); ++ } ++ ++ private boolean hasPlayerTicket(ChunkCoordIntPair coords, int level) { ++ ArraySetSorted> tickets = this.tickets.get(coords.pair()); ++ if (tickets == null || tickets.isEmpty()) { ++ return false; ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getTicketType() == TicketType.PLAYER && ticket.getTicketLevel() == level) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ private boolean addPriorityTicket(ChunkCoordIntPair coords, TicketType ticketType, int priority) { ++ AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket"); ++ long pair = coords.pair(); ++ PlayerChunk chunk = chunkMap.getUpdatingChunk(pair); ++ boolean needsTicket = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(pair) != null && !hasPlayerTicket(coords, 33); ++ ++ if (needsTicket) { ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); ++ getOnPlayerTicketAddQueue().add(pair); ++ addTicket(pair, ticket); ++ } ++ if ((chunk != null && chunk.isFullChunkReady())) { ++ if (needsTicket) { ++ chunkMap.world.getChunkProvider().tickDistanceManager(); ++ } ++ return needsTicket; ++ } ++ ++ boolean success; ++ if (!(success = updatePriorityTicket(coords, ticketType, priority))) { ++ Ticket ticket = new Ticket(ticketType, PRIORITY_TICKET_LEVEL, coords); ++ ticket.priority = priority; ++ success = this.addTicket(pair, ticket); ++ } else { ++ if (chunk == null) { ++ chunk = chunkMap.getUpdatingChunk(pair); ++ } ++ chunkMap.queueHolderUpdate(chunk); ++ } ++ ++ //chunkMap.world.getWorld().spawnParticle(priority <= 15 ? org.bukkit.Particle.EXPLOSION_HUGE : org.bukkit.Particle.EXPLOSION_NORMAL, chunkMap.world.getWorld().getPlayers(), null, coords.x << 4, 70, coords.z << 4, 2, 0, 0, 0, 1, null, true); ++ ++ chunkMap.world.getChunkProvider().tickDistanceManager(); ++ ++ return success; ++ } ++ ++ private boolean updatePriorityTicket(ChunkCoordIntPair coords, TicketType type, int priority) { ++ ArraySetSorted> tickets = this.tickets.get(coords.pair()); ++ if (tickets == null) { ++ return false; ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getTicketType() == type) { ++ // We only support increasing, not decreasing, too complicated ++ ticket.setCurrentTick(this.currentTick); ++ ticket.priority = Math.max(ticket.priority, priority); ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ public int getChunkPriority(ChunkCoordIntPair coords) { ++ AsyncCatcher.catchOp("ChunkMapDistance::getChunkPriority"); ++ ArraySetSorted> tickets = this.tickets.get(coords.pair()); ++ if (tickets == null) { ++ return 0; ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getTicketType() == TicketType.URGENT) { ++ return URGENT_PRIORITY; ++ } ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getTicketType() == TicketType.PRIORITY && ticket.priority > 0) { ++ return ticket.priority; ++ } ++ } ++ return 0; ++ } ++ ++ public void clearPriorityTickets(ChunkCoordIntPair coords) { ++ AsyncCatcher.catchOp("ChunkMapDistance::clearPriority"); ++ this.removeTicket(coords.pair(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); ++ } ++ ++ public void clearUrgent(ChunkCoordIntPair coords) { ++ AsyncCatcher.catchOp("ChunkMapDistance::clearUrgent"); ++ this.removeTicket(coords.pair(), new Ticket(TicketType.URGENT, PRIORITY_TICKET_LEVEL, coords)); ++ } ++ // Paper end + public boolean addTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkcoordintpair, int level, T identifier) { + return this.addTicket(chunkcoordintpair.pair(), new Ticket<>(ticketType, level, identifier)); + // CraftBukkit end +@@ -358,7 +500,7 @@ public abstract class ChunkMapDistance { + + class c extends ChunkMapDistance.b { + +- private int e = 0; ++ private int e = 0; private int getViewDistance() { return e; } private void setViewDistance(int value) { this.e = value; } // Paper - OBFHELPER + private final Long2IntMap f = Long2IntMaps.synchronize(new Long2IntOpenHashMap()); + private final LongSet g = new LongOpenHashSet(); + +@@ -374,41 +516,68 @@ public abstract class ChunkMapDistance { + + public void a(int i) { + ObjectIterator objectiterator = this.a.long2ByteEntrySet().iterator(); ++ // Paper start - set the view distance before scheduling chunk loads/unloads ++ int lastViewDistance = getViewDistance(); ++ setViewDistance(i); ++ // Paper end + + while (objectiterator.hasNext()) { + Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix + byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); + long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); + +- this.a(j, b0, this.c(b0), b0 <= i - 2); ++ this.a(j, b0, b0 <= lastViewDistance - 2, this.c(b0)); // Paper + } + +- this.e = i; ++ //this.e = i; // Paper - view distance is now set further up + } + + private void a(long i, int j, boolean flag, boolean flag1) { + if (flag != flag1) { +- Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkCoordIntPair(i)); // Paper - no-tick view distance ++ ChunkCoordIntPair coords = new ChunkCoordIntPair(i); // Paper ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); // Paper - no-tick view distance + + if (flag1) { +- ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { ++ scheduleChunkLoad(i, MinecraftServer.currentTick, j, (priority) -> { // Paper - smarter ticket delay based on frustum and distance ++ // Paper start - recheck its still valid if not cancel ++ if (!isChunkInRange(i)) { ++ ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { ++ ChunkMapDistance.this.m.execute(() -> { ++ ChunkMapDistance.this.removeTicket(i, ticket); ++ ChunkMapDistance.this.clearPriorityTickets(coords); ++ }); ++ }, i, false)); ++ return; ++ } ++ // abort early if we got a ticket already ++ if (hasPlayerTicket(coords, 33)) return; ++ // skip player ticket throttle for near chunks ++ if (priority <= 3) { ++ ChunkMapDistance.this.addTicket(i, ticket); ++ ChunkMapDistance.this.l.add(i); ++ return; ++ } ++ // Paper end ++ ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error + ChunkMapDistance.this.m.execute(() -> { +- if (this.c(this.c(i))) { ++ if (isChunkInRange(i)) { if (!hasPlayerTicket(coords, 33)) { // Paper - high priority might of already added it + ChunkMapDistance.this.addTicket(i, ticket); + ChunkMapDistance.this.l.add(i); +- } else { +- ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { ++ }} else { // Paper ++ ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error + }, i, false)); + } + + }); + }, i, () -> { +- return j; ++ return Math.min(PlayerChunkMap.GOLDEN_TICKET, priority); // Paper + })); ++ }); // Paper + } else { + ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { + ChunkMapDistance.this.m.execute(() -> { + ChunkMapDistance.this.removeTicket(i, ticket); ++ ChunkMapDistance.this.clearPriorityTickets(coords); // Paper + }); + }, i, true)); + } +@@ -416,6 +585,101 @@ public abstract class ChunkMapDistance { + + } + ++ // Paper start - smart scheduling of player tickets ++ private boolean isChunkInRange(long i) { ++ return this.isLoadedChunkLevel(this.getChunkLevel(i)); ++ } ++ public void scheduleChunkLoad(long i, long startTick, int initialDistance, java.util.function.Consumer task) { ++ long elapsed = MinecraftServer.currentTick - startTick; ++ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(i); ++ PlayerChunk updatingChunk = chunkMap.getUpdatingChunk(i); ++ if ((updatingChunk != null && updatingChunk.isFullChunkReady()) || !isChunkInRange(i) || getChunkPriority(chunkPos) > 0) { // Copied from above ++ // no longer needed ++ task.accept(1); ++ return; ++ } ++ ++ int desireDelay = 0; ++ double minDist = Double.MAX_VALUE; ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(i); ++ if (elapsed == 0 && initialDistance <= 4) { ++ // Aim for no delay on initial 6 chunk radius tickets save on performance of the below code to only > 6 ++ minDist = initialDistance; ++ } else if (players != null) { ++ Object[] backingSet = players.getBackingSet(); ++ ++ BlockPosition blockPos = chunkPos.asPosition(); ++ ++ boolean isFront = false; ++ BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(); ++ for (int index = 0, len = backingSet.length; index < len; ++index) { ++ if (!(backingSet[index] instanceof EntityPlayer)) { ++ continue; ++ } ++ EntityPlayer player = (EntityPlayer) backingSet[index]; ++ ++ ChunkCoordIntPair pointInFront = player.getChunkInFront(5); ++ pos.setValues(pointInFront.x << 4, 0, pointInFront.z << 4); ++ double frontDist = MCUtil.distanceSq(pos, blockPos); ++ ++ pos.setValues(player.locX(), 0, player.locZ()); ++ double center = MCUtil.distanceSq(pos, blockPos); ++ ++ double dist = Math.min(frontDist, center); ++ if (!isFront) { ++ ChunkCoordIntPair pointInBack = player.getChunkInFront(-7); ++ pos.setValues(pointInBack.x << 4, 0, pointInBack.z << 4); ++ double backDist = MCUtil.distanceSq(pos, blockPos); ++ if (frontDist < backDist) { ++ isFront = true; ++ } ++ } ++ if (dist < minDist) { ++ minDist = dist; ++ } ++ } ++ if (minDist == Double.MAX_VALUE) { ++ minDist = 15; ++ } else { ++ minDist = Math.sqrt(minDist) / 16; ++ } ++ if (minDist > 4) { ++ int desiredTimeDelayMax = isFront ? ++ (minDist < 10 ? 7 : 15) : // Front ++ (minDist < 10 ? 15 : 45); // Back ++ desireDelay += (desiredTimeDelayMax * 20) * (minDist / 32); ++ } ++ } else { ++ minDist = initialDistance; ++ desireDelay = 1; ++ } ++ long delay = desireDelay - elapsed; ++ if (delay <= 0 && minDist > 4 && minDist < Double.MAX_VALUE) { ++ boolean hasAnyNeighbor = false; ++ for (int x = -1; x <= 1; x++) { ++ for (int z = -1; z <= 1; z++) { ++ if (x == 0 && z == 0) continue; ++ long pair = ChunkCoordIntPair.pair(chunkPos.x + x, chunkPos.z + z); ++ PlayerChunk neighbor = chunkMap.getUpdatingChunk(pair); ++ ChunkStatus current = neighbor != null ? neighbor.getChunkHolderStatus() : null; ++ if (current != null && current.isAtLeastStatus(ChunkStatus.LIGHT)) { ++ hasAnyNeighbor = true; ++ } ++ } ++ } ++ if (!hasAnyNeighbor) { ++ delay += 20; ++ } ++ } ++ if (delay <= 0) { ++ task.accept((int) minDist); ++ } else { ++ int taskDelay = (int) Math.min(delay, minDist >= 10 ? 40 : (minDist < 6 ? 5 : 20)); ++ MCUtil.scheduleTask(taskDelay, () -> scheduleChunkLoad(i, startTick, initialDistance, task), "Player Ticket Delayer"); ++ } ++ } ++ // Paper end ++ + @Override + public void a() { + super.a(); +@@ -447,6 +711,7 @@ public abstract class ChunkMapDistance { + + } + ++ private boolean isLoadedChunkLevel(int i) { return c(i); } // Paper - OBFHELPER + private boolean c(int i) { + return i <= this.e - 2; + } +@@ -463,6 +728,7 @@ public abstract class ChunkMapDistance { + this.a.defaultReturnValue((byte) (i + 2)); + } + ++ protected final int getChunkLevel(long i) { return c(i); } // Paper - OBFHELPER + @Override + protected int c(long i) { + return this.a.get(i); +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 46a2e89df71654024102427859c385fc2e09cae7..17a4970cf78f3ee3a62a76a3f9e28251db17bac2 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -468,6 +468,26 @@ public class ChunkProviderServer extends IChunkProvider { + public void removeTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { + this.chunkMapDistance.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); + } ++ ++ public boolean markUrgent(ChunkCoordIntPair coords) { ++ return this.chunkMapDistance.markUrgent(coords); ++ } ++ ++ public boolean markHighPriority(ChunkCoordIntPair coords, int priority) { ++ return this.chunkMapDistance.markHighPriority(coords, priority); ++ } ++ ++ public void markAreaHighPriority(ChunkCoordIntPair center, int priority, int radius) { ++ this.chunkMapDistance.markAreaHighPriority(center, priority, radius); ++ } ++ ++ public void clearAreaPriorityTickets(ChunkCoordIntPair center, int radius) { ++ this.chunkMapDistance.clearAreaPriorityTickets(center, radius); ++ } ++ ++ public void clearPriorityTickets(ChunkCoordIntPair coords) { ++ this.chunkMapDistance.clearPriorityTickets(coords); ++ } + // Paper end + + @Nullable +@@ -506,6 +526,8 @@ public class ChunkProviderServer extends IChunkProvider { + + if (!completablefuture.isDone()) { // Paper + // Paper start - async chunk io/loading ++ ChunkCoordIntPair pair = new ChunkCoordIntPair(x, z); ++ this.chunkMapDistance.markUrgent(pair); + this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z); + // Paper end +@@ -514,6 +536,8 @@ public class ChunkProviderServer extends IChunkProvider { + this.serverThreadQueue.awaitTasks(completablefuture::isDone); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug + this.world.timings.syncChunkLoad.stopTiming(); // Paper ++ this.chunkMapDistance.clearPriorityTickets(pair); // Paper ++ this.chunkMapDistance.clearUrgent(pair); // Paper + } // Paper + ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { + return ichunkaccess1; +@@ -566,10 +590,12 @@ public class ChunkProviderServer extends IChunkProvider { + if (flag && !currentlyUnloading) { + // CraftBukkit end + this.chunkMapDistance.a(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); ++ if (isUrgent) this.chunkMapDistance.markUrgent(chunkcoordintpair); // Paper + if (this.a(playerchunk, l)) { + GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); + + gameprofilerfiller.enter("chunkLoad"); ++ chunkMapDistance.delayDistanceManagerTick = false; // Paper - ensure this is never false + this.tickDistanceManager(); + playerchunk = this.getChunk(k); + gameprofilerfiller.exit(); +@@ -578,8 +604,13 @@ public class ChunkProviderServer extends IChunkProvider { + } + } + } +- +- return this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap); ++ // Paper start ++ CompletableFuture> future = this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap); ++ if (isUrgent) { ++ future.thenAccept(either -> this.chunkMapDistance.clearUrgent(chunkcoordintpair)); ++ } ++ return future; ++ // Paper end + } + + private boolean a(@Nullable PlayerChunk playerchunk, int i) { +@@ -630,6 +661,7 @@ public class ChunkProviderServer extends IChunkProvider { + } + + public boolean tickDistanceManager() { // Paper - private -> public ++ if (chunkMapDistance.delayDistanceManagerTick) return false; // Paper + boolean flag = this.chunkMapDistance.a(this.playerChunkMap); + boolean flag1 = this.playerChunkMap.b(); + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 89a66078b722f265abd73579545a1f24df9442aa..8055172c806f285aa9a9e6de681d03b008fbf785 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -73,6 +73,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; + import net.minecraft.resources.MinecraftKey; + import net.minecraft.resources.ResourceKey; + import net.minecraft.server.AdvancementDataPlayer; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.network.ITextFilter; + import net.minecraft.server.network.PlayerConnection; +@@ -188,6 +189,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + private int lastArmorScored = Integer.MIN_VALUE; + private int lastExpLevelScored = Integer.MIN_VALUE; + private int lastExpTotalScored = Integer.MIN_VALUE; ++ public long lastHighPriorityChecked; // Paper ++ public void forceCheckHighPriority() { ++ lastHighPriorityChecked = -1; ++ getWorldServer().getChunkProvider().playerChunkMap.checkHighPriorityChunks(this); ++ } ++ public boolean isRealPlayer; // Paper + private float lastHealthSent = -1.0E8F; + private int lastFoodSent = -99999999; + private boolean lastSentSaturationZero = true; +@@ -275,6 +282,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.maxHealthCache = this.getMaxHealth(); + this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper + } ++ // Paper start ++ public BlockPosition getPointInFront(double inFront) { ++ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yaw+90)); // MC rotates yaw 90 for some odd reason ++ final double x = locX() + inFront * Math.cos(rads); ++ final double z = locZ() + inFront * Math.sin(rads); ++ return new BlockPosition(x, locY(), z); ++ } ++ ++ public ChunkCoordIntPair getChunkInFront(double inFront) { ++ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yaw+90)); // MC rotates yaw 90 for some odd reason ++ final double x = locX() + (inFront * 16) * Math.cos(rads); ++ final double z = locZ() + (inFront * 16) * Math.sin(rads); ++ return new ChunkCoordIntPair(MathHelper.floor(x) >> 4, MathHelper.floor(z) >> 4); ++ } ++ // Paper end + + // Yes, this doesn't match Vanilla, but it's the best we can do for now. + // If this is an issue, PRs are welcome +@@ -622,6 +644,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + if (valid && !this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) + super.tick(); + } ++ if (valid && isAlive() && playerConnection != null) ((WorldServer)world).getChunkProvider().playerChunkMap.checkHighPriorityChunks(this); // Paper + + for (int i = 0; i < this.inventory.getSize(); ++i) { + ItemStack itemstack = this.inventory.getItem(i); +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index e53054fc46e528f9c713eb4c03add61316e19396..fc79a73c884ceb7e0ce56443c36b135c4e525193 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -1,6 +1,7 @@ + package net.minecraft.server.level; + + import com.mojang.datafixers.util.Either; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper + import it.unimi.dsi.fastutil.shorts.ShortArraySet; + import it.unimi.dsi.fastutil.shorts.ShortSet; + import java.util.List; +@@ -19,6 +20,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutBlockChange; + import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; + import net.minecraft.network.protocol.game.PacketPlayOutMultiBlockChange; + import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; ++import net.minecraft.server.MCUtil; + import net.minecraft.util.MathHelper; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.EnumSkyBlock; +@@ -53,8 +55,8 @@ public class PlayerChunk { + private CompletableFuture chunkSave; + public int oldTicketLevel; + private int ticketLevel; +- private int n; +- final ChunkCoordIntPair location; // Paper - private -> package ++ volatile int n; public final int getCurrentPriority() { return n; } // Paper - OBFHELPER - make volatile since this is concurrently accessed ++ public final ChunkCoordIntPair location; // Paper - private -> public + private boolean p; + private final ShortSet[] dirtyBlocks; + private int r; +@@ -66,6 +68,7 @@ public class PlayerChunk { + private boolean x; + + private final PlayerChunkMap chunkMap; // Paper ++ public WorldServer getWorld() { return chunkMap.world; } // Paper + + long lastAutoSaveTime; // Paper - incremental autosave + long inactiveTimeStart; // Paper - incremental autosave +@@ -93,6 +96,120 @@ public class PlayerChunk { + return null; + } + // Paper end - no-tick view distance ++ // Paper start - Chunk gen/load priority system ++ volatile int neighborPriority = -1; ++ volatile int priorityBoost = 0; ++ public final java.util.concurrent.ConcurrentHashMap neighbors = new java.util.concurrent.ConcurrentHashMap<>(); ++ public final Long2ObjectOpenHashMap neighborPriorities = new Long2ObjectOpenHashMap<>(); ++ ++ private int getDemandedPriority() { ++ int priority = neighborPriority; // if we have a neighbor priority, use it ++ int myPriority = getMyPriority(); ++ ++ if (priority == -1 || (ticketLevel <= 33 && priority > myPriority)) { ++ priority = myPriority; ++ } ++ ++ return Math.max(1, Math.min(Math.max(ticketLevel, PlayerChunkMap.GOLDEN_TICKET), priority)); ++ } ++ ++ private int getMyPriority() { ++ if (priorityBoost == ChunkMapDistance.URGENT_PRIORITY) { ++ return 2; // Urgent - ticket level isn't always 31 so 33-30 = 3, but allow 1 more tasks to go below this for dependents ++ } ++ return ticketLevel - priorityBoost; ++ } ++ ++ private int getNeighborsPriority() { ++ return (neighborPriorities.isEmpty() ? getMyPriority() : getDemandedPriority()) + 1; ++ } ++ ++ public void onNeighborRequest(PlayerChunk neighbor, ChunkStatus status) { ++ neighbor.setNeighborPriority(this, getNeighborsPriority()); ++ this.neighbors.compute(neighbor, (playerChunk, currentWantedStatus) -> { ++ if (currentWantedStatus == null || !currentWantedStatus.isAtLeastStatus(status)) { ++ //System.out.println(this + " request " + neighbor + " at " + status + " currently " + currentWantedStatus); ++ return status; ++ } else { ++ //System.out.println(this + " requested " + neighbor + " at " + status + " but thats lower than other wanted status " + currentWantedStatus); ++ return currentWantedStatus; ++ } ++ }); ++ ++ } ++ ++ public void onNeighborDone(PlayerChunk neighbor, ChunkStatus chunkstatus, IChunkAccess chunk) { ++ this.neighbors.compute(neighbor, (playerChunk, wantedStatus) -> { ++ if (wantedStatus != null && chunkstatus.isAtLeastStatus(wantedStatus)) { ++ //System.out.println(this + " neighbor done at " + neighbor + " for status " + chunkstatus + " wanted " + wantedStatus); ++ neighbor.removeNeighborPriority(this); ++ return null; ++ } else { ++ //System.out.println(this + " neighbor finished our previous request at " + neighbor + " for status " + chunkstatus + " but we now want instead " + wantedStatus); ++ return wantedStatus; ++ } ++ }); ++ } ++ ++ private void removeNeighborPriority(PlayerChunk requester) { ++ synchronized (neighborPriorities) { ++ neighborPriorities.remove(requester.location.pair()); ++ recalcNeighborPriority(); ++ } ++ checkPriority(); ++ } ++ ++ ++ private void setNeighborPriority(PlayerChunk requester, int priority) { ++ synchronized (neighborPriorities) { ++ neighborPriorities.put(requester.location.pair(), Integer.valueOf(priority)); ++ recalcNeighborPriority(); ++ } ++ checkPriority(); ++ } ++ ++ private void recalcNeighborPriority() { ++ neighborPriority = -1; ++ if (!neighborPriorities.isEmpty()) { ++ synchronized (neighborPriorities) { ++ for (Integer neighbor : neighborPriorities.values()) { ++ if (neighbor < neighborPriority || neighborPriority == -1) { ++ neighborPriority = neighbor; ++ } ++ } ++ } ++ } ++ } ++ private void checkPriority() { ++ if (getCurrentPriority() != getDemandedPriority()) this.chunkMap.queueHolderUpdate(this); ++ } ++ ++ public final double getDistance(EntityPlayer player) { ++ return getDistance(player.locX(), player.locZ()); ++ } ++ public final double getDistance(double blockX, double blockZ) { ++ int cx = MCUtil.fastFloor(blockX) >> 4; ++ int cz = MCUtil.fastFloor(blockZ) >> 4; ++ final double x = location.x - cx; ++ final double z = location.z - cz; ++ return (x * x) + (z * z); ++ } ++ ++ public final double getDistanceFrom(BlockPosition pos) { ++ return getDistance(pos.getX(), pos.getZ()); ++ } ++ ++ @Override ++ public String toString() { ++ return "PlayerChunk{" + ++ "location=" + location + ++ ", ticketLevel=" + ticketLevel + "/" + getChunkStatus(this.ticketLevel) + ++ ", chunkHolderStatus=" + getChunkHolderStatus() + ++ ", neighborPriority=" + getNeighborsPriority() + ++ ", priority=(" + ticketLevel + " - " + priorityBoost +" vs N " + neighborPriority + ") = " + getDemandedPriority() + " A " + getCurrentPriority() + ++ '}'; ++ } ++ // Paper end + + public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { + this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); +@@ -195,6 +312,18 @@ public class PlayerChunk { + } + return null; + } ++ public static ChunkStatus getNextStatus(ChunkStatus status) { ++ if (status == ChunkStatus.FULL) { ++ return status; ++ } ++ return CHUNK_STATUSES.get(status.getStatusIndex() + 1); ++ } ++ public CompletableFuture> getStatusFutureUncheckedMain(ChunkStatus chunkstatus) { ++ return ensureMain(getStatusFutureUnchecked(chunkstatus)); ++ } ++ public CompletableFuture ensureMain(CompletableFuture future) { ++ return future.thenApplyAsync(r -> r, chunkMap.mainInvokingExecutor); ++ } + // Paper end + + public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { +@@ -441,6 +570,7 @@ public class PlayerChunk { + return this.n; + } + ++ private void setPriority(int i) { d(i); } // Paper - OBFHELPER + private void d(int i) { + this.n = i; + } +@@ -459,7 +589,7 @@ public class PlayerChunk { + // CraftBukkit start + // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. + if (playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && !playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) { +- this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main + Chunk chunk = (Chunk)either.left().orElse(null); + if (chunk != null) { + playerchunkmap.callbackExecutor.execute(() -> { +@@ -524,12 +654,13 @@ public class PlayerChunk { + if (!flag2 && flag3) { + // Paper start - cache ticking ready status + int expectCreateCount = ++this.fullChunkCreateCount; +- this.fullChunkFuture = playerchunkmap.b(this); this.fullChunkFuture.thenAccept((either) -> { ++ this.fullChunkFuture = playerchunkmap.b(this); ensureMain(this.fullChunkFuture).thenAccept((either) -> { // Paper - ensure main + if (either.left().isPresent() && PlayerChunk.this.fullChunkCreateCount == expectCreateCount) { + // note: Here is a very good place to add callbacks to logic waiting on this. + Chunk fullChunk = either.left().get(); + PlayerChunk.this.isFullChunkReady = true; + fullChunk.playerChunk = PlayerChunk.this; ++ this.chunkMap.chunkDistanceManager.clearPriorityTickets(location); + + + } +@@ -554,7 +685,7 @@ public class PlayerChunk { + + if (!flag4 && flag5) { + // Paper start - cache ticking ready status +- this.tickingFuture = playerchunkmap.a(this); this.tickingFuture.thenAccept((either) -> { ++ this.tickingFuture = playerchunkmap.a(this); ensureMain(this.tickingFuture).thenAccept((either) -> { // Paper - ensure main + if (either.left().isPresent()) { + // note: Here is a very good place to add callbacks to logic waiting on this. + Chunk tickingChunk = either.left().get(); +@@ -585,7 +716,7 @@ public class PlayerChunk { + } + + // Paper start - cache ticking ready status +- this.entityTickingFuture = playerchunkmap.b(this.location); this.entityTickingFuture.thenAccept((either) -> { ++ this.entityTickingFuture = playerchunkmap.b(this.location); ensureMain(this.entityTickingFuture).thenAccept((either) -> { // Paper ensureMain + if (either.left().isPresent()) { + // note: Here is a very good place to add callbacks to logic waiting on this. + Chunk entityTickingChunk = either.left().get(); +@@ -605,12 +736,29 @@ public class PlayerChunk { + this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; + } + +- this.u.a(this.location, this::k, this.ticketLevel, this::d); ++ // Paper start - raise IO/load priority if priority changes, use our preferred priority ++ priorityBoost = chunkMap.chunkDistanceManager.getChunkPriority(location); ++ int priority = getDemandedPriority(); ++ if (getCurrentPriority() > priority) { ++ int ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; ++ if (priority <= 10) { ++ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; ++ } else if (priority <= 20) { ++ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; ++ } ++ chunkMap.world.asyncChunkTaskManager.raisePriority(location.x, location.z, ioPriority); ++ } ++ if (getCurrentPriority() != priority) { ++ this.u.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority ++ int neighborsPriority = getNeighborsPriority(); ++ this.neighbors.forEach((neighbor, neighborDesired) -> neighbor.setNeighborPriority(this, neighborsPriority)); ++ } ++ // Paper end + this.oldTicketLevel = this.ticketLevel; + // CraftBukkit start + // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. + if (!playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) { +- this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main + Chunk chunk = (Chunk)either.left().orElse(null); + if (chunk != null) { + playerchunkmap.callbackExecutor.execute(() -> { +@@ -692,6 +840,7 @@ public class PlayerChunk { + + public interface c { + ++ default void changePriority(ChunkCoordIntPair chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer) { a(chunkcoordintpair, intsupplier, i, intconsumer); } // Paper - OBFHELPER + void a(ChunkCoordIntPair chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer); + } + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 6ddbc83a08be4e7aa5cd85cf78f14604d4759f30..5bea15ba1ee3d2c8e8d78ab34ba75723164b7117 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -14,6 +14,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; + import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + import it.unimi.dsi.fastutil.longs.Long2ByteMap; + import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; // Paper + import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; + import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; + import it.unimi.dsi.fastutil.longs.LongIterator; +@@ -51,6 +52,7 @@ import net.minecraft.CrashReport; + import net.minecraft.CrashReportSystemDetails; + import net.minecraft.ReportedException; + import net.minecraft.SystemUtils; ++import net.minecraft.core.BlockPosition; + import net.minecraft.core.SectionPosition; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.protocol.Packet; +@@ -105,6 +107,7 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + import org.bukkit.entity.Player; // CraftBukkit ++import org.spigotmc.AsyncCatcher; + + public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + +@@ -142,6 +145,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + public final WorldServer world; + private final LightEngineThreaded lightEngine; + private final IAsyncTaskHandler executor; ++ final java.util.concurrent.Executor mainInvokingExecutor; // Paper + public final ChunkGenerator chunkGenerator; + private final Supplier l; public final Supplier getWorldPersistentDataSupplier() { return this.l; } // Paper - OBFHELPER + private final VillagePlace m; +@@ -179,6 +183,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + @Override + public void execute(Runnable runnable) { ++ AsyncCatcher.catchOp("Callback Executor execute"); + if (queued == null) { + queued = new java.util.ArrayDeque<>(); + } +@@ -187,6 +192,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + @Override + public void run() { ++ AsyncCatcher.catchOp("Callback Executor run"); + if (queued == null) { + return; + } +@@ -341,6 +347,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.world = worldserver; + this.chunkGenerator = chunkgenerator; + this.executor = iasynctaskhandler; ++ // Paper start ++ this.mainInvokingExecutor = (run) -> { ++ if (MCUtil.isMainThread()) { ++ run.run(); ++ } else { ++ iasynctaskhandler.execute(run); ++ } ++ }; ++ // Paper end + ThreadedMailbox threadedmailbox = ThreadedMailbox.a(executor, "worldgen"); + + iasynctaskhandler.getClass(); +@@ -435,6 +450,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, + (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ checkHighPriorityChunks(player); + if (newState.size() != 1) { + return; + } +@@ -453,7 +469,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ); + PlayerChunkMap.this.world.getChunkProvider().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update +- }); ++ PlayerChunkMap.this.world.getChunkProvider().clearPriorityTickets(chunkPos); ++ }, (player, prevPos, newPos) -> { ++ player.lastHighPriorityChecked = -1; // reset and recheck ++ checkHighPriorityChunks(player); ++ }); + this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); + this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, + (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, +@@ -470,6 +490,115 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + }); + // Paper end - no-tick view distance + } ++ // Paper start - Chunk Prioritization ++ public void queueHolderUpdate(PlayerChunk playerchunk) { ++ Runnable runnable = () -> { ++ if (isUnloading(playerchunk)) { ++ return; // unloaded ++ } ++ chunkDistanceManager.pendingChunkUpdates.add(playerchunk); ++ if (!chunkDistanceManager.pollingPendingChunkUpdates) { ++ world.getChunkProvider().tickDistanceManager(); ++ } ++ }; ++ if (MCUtil.isMainThread()) { ++ // We can't use executor here because it will not execute tasks if its currently in the middle of executing tasks... ++ runnable.run(); ++ } else { ++ executor.execute(runnable); ++ } ++ } ++ ++ private boolean isUnloading(PlayerChunk playerchunk) { ++ return playerchunk == null || unloadQueue.contains(playerchunk.location.pair()); ++ } ++ ++ private void updateChunkPriorityMap(Long2IntOpenHashMap map, long chunk, int level) { ++ int prev = map.getOrDefault(chunk, -1); ++ if (level > prev) { ++ map.put(chunk, level); ++ } ++ } ++ ++ public void checkHighPriorityChunks(EntityPlayer player) { ++ int currentTick = MinecraftServer.currentTick; ++ if (currentTick - player.lastHighPriorityChecked < 20 || !player.isRealPlayer) { // weed out fake players ++ return; ++ } ++ player.lastHighPriorityChecked = currentTick; ++ Long2IntOpenHashMap priorities = new Long2IntOpenHashMap(); ++ ++ int viewDistance = getEffectiveNoTickViewDistance(); ++ BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(); ++ ++ // Prioritize circular near ++ double playerChunkX = MathHelper.floor(player.locX()) >> 4; ++ double playerChunkZ = MathHelper.floor(player.locZ()) >> 4; ++ pos.setValues(player.locX(), 0, player.locZ()); ++ double twoThirdModifier = 2D / 3D; ++ MCUtil.getSpiralOutChunks(pos, Math.min(6, viewDistance)).forEach(coord -> { ++ if (shouldSkipPrioritization(coord)) return; ++ ++ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); ++ // Prioritize immediate ++ if (dist <= 4) { ++ updateChunkPriorityMap(priorities, coord.pair(), (int) (27 - dist)); ++ return; ++ } ++ ++ // Prioritize nearby chunks ++ updateChunkPriorityMap(priorities, coord.pair(), (int) (20 - dist * twoThirdModifier)); ++ }); ++ ++ // Prioritize Frustum near 3 ++ ChunkCoordIntPair front3 = player.getChunkInFront(3); ++ pos.setValues(front3.x << 4, 0, front3.z << 4); ++ MCUtil.getSpiralOutChunks(pos, Math.min(5, viewDistance)).forEach(coord -> { ++ if (shouldSkipPrioritization(coord)) return; ++ ++ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); ++ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - dist * twoThirdModifier)); ++ }); ++ ++ // Prioritize Frustum near 5 ++ if (viewDistance > 4) { ++ ChunkCoordIntPair front5 = player.getChunkInFront(5); ++ pos.setValues(front5.x << 4, 0, front5.z << 4); ++ MCUtil.getSpiralOutChunks(pos, 4).forEach(coord -> { ++ if (shouldSkipPrioritization(coord)) return; ++ ++ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); ++ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - dist * twoThirdModifier)); ++ }); ++ } ++ ++ // Prioritize Frustum far 7 ++ if (viewDistance > 6) { ++ ChunkCoordIntPair front7 = player.getChunkInFront(7); ++ pos.setValues(front7.x << 4, 0, front7.z << 4); ++ MCUtil.getSpiralOutChunks(pos, 3).forEach(coord -> { ++ if (shouldSkipPrioritization(coord)) { ++ return; ++ } ++ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); ++ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - dist * twoThirdModifier)); ++ }); ++ } ++ ++ if (priorities.isEmpty()) return; ++ chunkDistanceManager.delayDistanceManagerTick = true; ++ priorities.long2IntEntrySet().fastForEach(entry -> chunkDistanceManager.markHighPriority(new ChunkCoordIntPair(entry.getLongKey()), entry.getIntValue())); ++ chunkDistanceManager.delayDistanceManagerTick = false; ++ world.getChunkProvider().tickDistanceManager(); ++ ++ } ++ ++ private boolean shouldSkipPrioritization(ChunkCoordIntPair coord) { ++ if (playerViewDistanceNoTickMap.getObjectsInRange(coord.pair()) == null) return true; ++ PlayerChunk chunk = getUpdatingChunk(coord.pair()); ++ return chunk != null && (chunk.isFullChunkReady()); ++ } ++ // Paper end + + public void updatePlayerMobTypeMap(Entity entity) { + if (!this.world.paperConfig.perPlayerMobSpawns) { +@@ -599,6 +728,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + List>> list = Lists.newArrayList(); + int j = chunkcoordintpair.x; + int k = chunkcoordintpair.z; ++ PlayerChunk requestingNeighbor = getUpdatingChunk(chunkcoordintpair.pair()); // Paper + + for (int l = -i; l <= i; ++l) { + for (int i1 = -i; i1 <= i; ++i1) { +@@ -617,6 +747,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + ChunkStatus chunkstatus = (ChunkStatus) intfunction.apply(j1); + CompletableFuture> completablefuture = playerchunk.a(chunkstatus, this); ++ // Paper start ++ if (requestingNeighbor != null && requestingNeighbor != playerchunk && !completablefuture.isDone()) { ++ requestingNeighbor.onNeighborRequest(playerchunk, chunkstatus); ++ completablefuture.thenAccept(either -> { ++ requestingNeighbor.onNeighborDone(playerchunk, chunkstatus, either.left().orElse(null)); ++ }); ++ } ++ // Paper end + + list.add(completablefuture); + } +@@ -1084,14 +1222,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + }; + + CompletableFuture chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z); ++ PlayerChunk playerChunk = getUpdatingChunk(chunkcoordintpair.pair()); ++ int chunkPriority = playerChunk != null ? playerChunk.getCurrentPriority() : 33; ++ int priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; ++ ++ if (chunkPriority <= 10) { ++ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; ++ } else if (chunkPriority <= 20) { ++ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; ++ } ++ boolean isHighestPriority = priority == com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; + if (chunkSaveFuture != null) { +- this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, +- com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); +- this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); ++ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, priority, chunkHolderConsumer, isHighestPriority, chunkSaveFuture); + } else { +- this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, +- com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); ++ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, priority, chunkHolderConsumer, isHighestPriority); + } ++ this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, priority); + return ret; + // Paper end + } +@@ -1236,7 +1382,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + long i = playerchunk.i().pair(); + + playerchunk.getClass(); +- mailbox.a(ChunkTaskQueueSorter.a(runnable, i, playerchunk::getTicketLevel)); ++ mailbox.a(ChunkTaskQueueSorter.a(runnable, i, () -> 1)); // Paper - final loads are always urgent! + }); + } + +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index e06fe77f6ea05a93e95fce223bcfd0d16394f96f..90cbd12611b7b078f35f08f910453bcc02f6665b 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -8,6 +8,7 @@ public final class Ticket implements Comparable> { + private final int b; + public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER + private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER ++ public int priority = 0; // Paper + + protected Ticket(TicketType tickettype, int i, T t0) { + this.a = tickettype; +@@ -56,6 +57,7 @@ public final class Ticket implements Comparable> { + return this.b; + } + ++ public final void setCurrentTick(long i) { this.a(i); } // Paper - OBFHELPER + protected void a(long i) { + this.d = i; + } +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index 2c932d36f982e7f8713aabff9a6c631055810366..f5d18834e0e2ee0e3bcf55810456766d2f134450 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -28,6 +28,8 @@ public class TicketType { + public static final TicketType PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + public static final TicketType FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper + public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper ++ public static final TicketType PRIORITY = a("priority", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper ++ public static final TicketType URGENT = a("urgent", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper + + public static TicketType a(String s, Comparator comparator) { + return new TicketType<>(s, comparator, 0L); +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index b491a3563bf457bcb631e05cf41b661712134966..40fefdb9da9c4fd3ef3e3bb6276de215dd5265f9 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1530,6 +1530,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + + this.A = this.e; + this.player.setLocation(d0, d1, d2, f, f1); ++ this.player.forceCheckHighPriority(); // Paper + this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.teleportAwait)); + } + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 66fcd68f0a0a21b113e8741cc42c841f49009118..b4c5915cc68a838259129b8973b3a6a39c1fc963 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -275,8 +275,8 @@ public abstract class PlayerList { + final ChunkCoordIntPair pos = new ChunkCoordIntPair(chunkX, chunkZ); + PlayerChunkMap playerChunkMap = worldserver1.getChunkProvider().playerChunkMap; + playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.pair()); +- worldserver1.getChunkProvider().tickDistanceManager(); +- worldserver1.getChunkProvider().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { ++ worldserver1.getChunkProvider().markAreaHighPriority(pos, 28, 3); ++ worldserver1.getChunkProvider().getChunkAtAsynchronously(chunkX, chunkZ, true, false).thenApply(chunk -> { + PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pos.pair()); + if (updatingChunk != null) { + return updatingChunk.getEntityTickingFuture(); +@@ -696,6 +696,7 @@ public abstract class PlayerList { + SocketAddress socketaddress = loginlistener.networkManager.getSocketAddress(); + + EntityPlayer entity = new EntityPlayer(this.server, this.server.getWorldServer(World.OVERWORLD), gameprofile, new PlayerInteractManager(this.server.getWorldServer(World.OVERWORLD))); ++ entity.isRealPlayer = true; // Paper + Player player = entity.getBukkitEntity(); + PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress()); + +@@ -902,6 +903,7 @@ public abstract class PlayerList { + // CraftBukkit end + + worldserver1.getChunkProvider().addTicket(TicketType.POST_TELEPORT, new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper ++ entityplayer1.forceCheckHighPriority(); // Player + while (avoidSuffocation && !worldserver1.getCubes(entityplayer1) && entityplayer1.locY() < 256.0D) { + entityplayer1.setPosition(entityplayer1.locX(), entityplayer1.locY() + 1.0D, entityplayer1.locZ()); + } +diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java +index 9a88791be443a5b18934e7d752aee6dcdb8aa38f..e41d63596c32eee5f0c04a6f043d576d8021ff1a 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java ++++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java +@@ -104,6 +104,7 @@ public class ChunkCoordIntPair { + return "[" + this.x + ", " + this.z + "]"; + } + ++ public final BlockPosition asPosition() { return l(); } // Paper - OBFHELPER + public BlockPosition l() { + return new BlockPosition(this.d(), 0, this.e()); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 2d90ecf04f522a4e16f44c905450a61becaa1ed2..6034ef65ee6030948a5b76fa493addb44188ef62 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2541,6 +2541,10 @@ public class CraftWorld implements World { + return future; + } + ++ if (!urgent) { ++ // if not urgent, at least use a slightly boosted priority ++ world.getChunkProvider().markHighPriority(new ChunkCoordIntPair(x, z), 1); ++ } + return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { + net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); + return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 935b5668a81db4d19a08b09c61519114532a23d9..0f8d10c2bc7728b58528096fc0686c3aeee623a7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -60,6 +60,7 @@ import net.minecraft.server.level.PlayerChunkMap; + import net.minecraft.server.level.WorldServer; + import net.minecraft.server.network.PlayerConnection; + import net.minecraft.server.players.WhiteListEntry; ++import net.minecraft.util.MathHelper; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityExperienceOrb; + import net.minecraft.world.entity.EntityLiving; +@@ -72,6 +73,7 @@ import net.minecraft.world.inventory.Container; + import net.minecraft.world.item.EnumColor; + import net.minecraft.world.item.enchantment.EnchantmentManager; + import net.minecraft.world.item.enchantment.Enchantments; ++import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.EnumGamemode; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.entity.TileEntitySign; +@@ -851,6 +853,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + throw new UnsupportedOperationException("Cannot set rotation of players. Consider teleporting instead."); + } + ++ // Paper start ++ @Override ++ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull PlayerTeleportEvent.TeleportCause cause) { ++ ((CraftWorld)loc.getWorld()).getHandle().getChunkProvider().markAreaHighPriority(new ChunkCoordIntPair(MathHelper.floor(loc.getX()) >> 4, MathHelper.floor(loc.getZ()) >> 4), 28, 3); // Paper - load area high priority ++ return super.teleportAsync(loc, cause); ++ } ++ // Paper end ++ + @Override + public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) { + Preconditions.checkArgument(location != null, "location"); diff --git a/patches/server-unmapped/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/patches/server-unmapped/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch new file mode 100644 index 0000000000..ee6a2dd544 --- /dev/null +++ b/patches/server-unmapped/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 23 May 2020 17:03:41 -0400 +Subject: [PATCH] Optimize sending packets to nearby locations (sounds/effects) + +Instead of using the entire world or player list, use the distance +maps to only iterate players who are even seeing the chunk the packet +is originating from. + +This will drastically cut down on packet sending cost for worlds with +lots of players in them. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index b4c5915cc68a838259129b8973b3a6a39c1fc963..4c3a2e3cfd60321b3b74d143a32aa5f5d59d7e1e 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1153,16 +1153,40 @@ public abstract class PlayerList { + } + + public void sendPacketNearby(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, double d3, ResourceKey resourcekey, Packet packet) { +- for (int i = 0; i < this.players.size(); ++i) { +- EntityPlayer entityplayer = (EntityPlayer) this.players.get(i); ++ WorldServer world = null; ++ if (entityhuman != null && entityhuman.world instanceof WorldServer) { ++ world = (WorldServer) entityhuman.world; ++ } + +- // CraftBukkit start - Test if player receiving packet can see the source of the packet +- if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { +- continue; ++ // Paper start ++ if (world == null) { ++ world = server.getWorldServer(resourcekey); ++ } ++ PlayerChunkMap chunkMap = world != null ? world.getChunkProvider().playerChunkMap : null; ++ Object[] backingSet; ++ if (chunkMap == null) { ++ // Really shouldn't happen... ++ backingSet = world != null ? world.players.toArray() : players.toArray(); ++ } else { ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.fastFloor(d0) >> 4, MCUtil.fastFloor(d2) >> 4); ++ if (nearbyPlayers == null) { ++ return; + } ++ backingSet = nearbyPlayers.getBackingSet(); ++ } ++ ++ for (Object object : backingSet) { ++ if (!(object instanceof EntityPlayer)) continue; ++ EntityPlayer entityplayer = (EntityPlayer) object; ++ // Paper end ++ ++ // CraftBukkit start - Test if player receiving packet can see the source of the packet ++ //if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { // Paper ++ //continue; // Paper ++ //} // Paper + // CraftBukkit end + +- if (entityplayer != entityhuman && entityplayer.world.getDimensionKey() == resourcekey) { ++ if (entityplayer != entityhuman && entityplayer.world.getDimensionKey() == resourcekey && (!(entityhuman instanceof EntityPlayer) || entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity()))) { // Paper + double d4 = d0 - entityplayer.locX(); + double d5 = d1 - entityplayer.locY(); + double d6 = d2 - entityplayer.locZ(); diff --git a/patches/server-unmapped/0486-Improve-Chunk-Status-Transition-Speed.patch b/patches/server-unmapped/0486-Improve-Chunk-Status-Transition-Speed.patch new file mode 100644 index 0000000000..969bc53a1c --- /dev/null +++ b/patches/server-unmapped/0486-Improve-Chunk-Status-Transition-Speed.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 May 2020 23:32:14 -0400 +Subject: [PATCH] Improve Chunk Status Transition Speed + +When a chunk is loaded from disk that has already been generated, +the server has to promote the chunk through the system to reach +it's current desired status level. + +This results in every single status transition going from the main thread +to the world gen threads, only to discover it has no work it actually +needs to do.... and then it returns back to main. + +This back and forth costs a lot of time and can really delay chunk loads +when the server is under high TPS due to their being a lot of time in +between chunk load times, as well as hogs up the chunk threads from doing +actual generation and light work. + +Additionally, the whole task system uses a lot of CPU on the server threads anyways. + +So by optimizing status transitions for status's that are already complete, +we can run them to the desired level while on main thread (where it has +to happen anyways) instead of ever jumping to world gen thread. + +This will improve chunk loading effeciency to be reduced down to the following +scenario / path: + +1) MAIN: Chunk Requested, Load Request sent to ChunkTaskManager / IO Queue +2) IO: Once position in queue comes, submit read IO data and schedule to chunk task thread +3) CHUNK: Once IO is loaded and position in queue comes, deserialize the chunk data, process conversions, submit to main queue +4) MAIN: next Chunk Task process (Mid Tick or End Of Tick), load chunk data into world (POI, main thread tasks) +5) MAIN: process status transitions all the way to LIGHT, light schedules Threaded task +6) SERVER: Light tasks register light enablement for chunk and any lighting needing to be done +7) MAIN: Task returns to main, finish processing to FULL/TICKING status + +Previously would have hopped to SERVER around 12+ times there extra. + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index fc79a73c884ceb7e0ce56443c36b135c4e525193..88022e3ccd04f9c041ced68be66a95247c1017e9 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -84,6 +84,13 @@ public class PlayerChunk { + this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); + } + // Paper end - optimise isOutsideOfRange ++ // Paper start - optimize chunk status progression without jumping through thread pool ++ public boolean canAdvanceStatus() { ++ ChunkStatus status = getChunkHolderStatus(); ++ IChunkAccess chunk = getAvailableChunkNow(); ++ return chunk != null && (status == null || chunk.getChunkStatus().isAtLeastStatus(getNextStatus(status))); ++ } ++ // Paper end + + // Paper start - no-tick view distance + public final Chunk getSendingChunk() { +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 5bea15ba1ee3d2c8e8d78ab34ba75723164b7117..74146ab6bd172807fb8545c1a29e376b1224e34d 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -795,7 +795,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return either.mapLeft((list) -> { + return (Chunk) list.get(list.size() / 2); + }); +- }, this.executor); ++ }, this.mainInvokingExecutor); // Paper + } + + @Nullable +@@ -1145,7 +1145,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + IChunkAccess ichunkaccess = (IChunkAccess) optional.get(); + + if (ichunkaccess.getChunkStatus().b(chunkstatus)) { +- CompletableFuture completablefuture1; ++ CompletableFuture> completablefuture1; // Paper + + if (chunkstatus == ChunkStatus.LIGHT) { + completablefuture1 = this.b(playerchunk, chunkstatus); +@@ -1161,7 +1161,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return this.b(playerchunk, chunkstatus); + } + } +- }, this.executor); ++ }, this.mainInvokingExecutor).thenComposeAsync(CompletableFuture::completedFuture, this.mainInvokingExecutor); // Paper - optimize chunk status progression without jumping through thread pool - ensure main + } + } + +@@ -1282,6 +1282,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + return CompletableFuture.completedFuture(Either.right(playerchunk_failure)); + }); + }, (runnable) -> { ++ // Paper start - optimize chunk status progression without jumping through thread pool ++ if (playerchunk.canAdvanceStatus()) { ++ this.mainInvokingExecutor.execute(runnable); ++ return; ++ } ++ // Paper end + this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); + }); + } diff --git a/patches/server-unmapped/0487-Fix-villager-trading-demand-MC-163962.patch b/patches/server-unmapped/0487-Fix-villager-trading-demand-MC-163962.patch new file mode 100644 index 0000000000..b6b2585f20 --- /dev/null +++ b/patches/server-unmapped/0487-Fix-villager-trading-demand-MC-163962.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Fri, 5 Jun 2020 20:02:04 -0500 +Subject: [PATCH] Fix villager trading demand - MC-163962 + +Prevent demand from going negative and tending to negative infinity + +diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java +index d840c657a6a992c86364a5f4536da0b217515c53..9e2fe0d5e6d4ea1f4c9cea96b755ddcd1e3c9009 100644 +--- a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java ++++ b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java +@@ -109,7 +109,7 @@ public class MerchantRecipe { + } + + public void e() { +- this.demand = this.demand + this.uses - (this.maxUses - this.uses); ++ this.demand = Math.max(0, this.demand + this.uses - (this.maxUses - this.uses)); // Paper + } + + public ItemStack f() { diff --git a/patches/server-unmapped/0488-Maps-shouldn-t-load-chunks.patch b/patches/server-unmapped/0488-Maps-shouldn-t-load-chunks.patch new file mode 100644 index 0000000000..28c169e754 --- /dev/null +++ b/patches/server-unmapped/0488-Maps-shouldn-t-load-chunks.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Sun, 7 Jun 2020 21:43:42 +0100 +Subject: [PATCH] Maps shouldn't load chunks + +Previously maps would load all chunks in a certain radius depending on + their scale when trying to update their content. This would result in + main thread chunk loads when they weren't really necessary, especially + on low view distances or "slow" async chunk loads after teleports or + other prioritisation. + + This changes it to only try to render already loaded chunks based on + the assumption that the chunks around the player will get loaded + eventually anyways and that maps will get checked for update every + five ticks that movement occur in anyways. + +diff --git a/src/main/java/net/minecraft/world/item/ItemWorldMap.java b/src/main/java/net/minecraft/world/item/ItemWorldMap.java +index b18149cf048e78fefc019b50ed8f20ff8b609f5c..a1945e9ac1dd8961c5758a22bef3908d3adf0704 100644 +--- a/src/main/java/net/minecraft/world/item/ItemWorldMap.java ++++ b/src/main/java/net/minecraft/world/item/ItemWorldMap.java +@@ -120,9 +120,9 @@ public class ItemWorldMap extends ItemWorldMapBase { + int k2 = (j / i + k1 - 64) * i; + int l2 = (k / i + l1 - 64) * i; + Multiset multiset = LinkedHashMultiset.create(); +- Chunk chunk = world.getChunkAtWorldCoords(new BlockPosition(k2, 0, l2)); ++ Chunk chunk = world.getChunkIfLoaded(new BlockPosition(k2, 0, l2)); // Paper - Maps shouldn't load chunks + +- if (!chunk.isEmpty()) { ++ if (chunk != null && !chunk.isEmpty()) { // Paper - Maps shouldn't load chunks + ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); + int i3 = k2 & 15; + int j3 = l2 & 15; diff --git a/patches/server-unmapped/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/patches/server-unmapped/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch new file mode 100644 index 0000000000..c789a5a683 --- /dev/null +++ b/patches/server-unmapped/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 7 Jun 2020 19:25:13 -0400 +Subject: [PATCH] Use seed based lookup for Treasure Maps - Fixes lag from + carto/sunken maps + + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 524bbf9bdf5fb0e1e4ff217ae3291fdbe742437e..a0670bdd858f59ee5719580625c9f25235e23fc4 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -421,8 +421,8 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.worldDataServer.setThundering(flag1); + } + +- @Override +- public BiomeBase a(int i, int j, int k) { ++ public BiomeBase getBiomeBySeed(int i, int j, int k) { return a(i, j, k); } // Paper - OBFHELPER ++ @Override public BiomeBase a(int i, int j, int k) { + return this.getChunkProvider().getChunkGenerator().getWorldChunkManager().getBiome(i, j, k); + } + +diff --git a/src/main/java/net/minecraft/world/item/ItemWorldMap.java b/src/main/java/net/minecraft/world/item/ItemWorldMap.java +index a1945e9ac1dd8961c5758a22bef3908d3adf0704..3aa0f19d4a924d40005a38bb95a08d4a109c5b2e 100644 +--- a/src/main/java/net/minecraft/world/item/ItemWorldMap.java ++++ b/src/main/java/net/minecraft/world/item/ItemWorldMap.java +@@ -253,7 +253,7 @@ public class ItemWorldMap extends ItemWorldMapBase { + + for (l = 0; l < 128 * i; ++l) { + for (i1 = 0; i1 < 128 * i; ++i1) { +- abiomebase[l * 128 * i + i1] = worldserver.getBiome(new BlockPosition((j / i - 64) * i + i1, 0, (k / i - 64) * i + l)); ++ abiomebase[l * 128 * i + i1] = worldserver.getBiomeBySeed((j / i - 64) * i + i1, 0, (k / i - 64) * i + l); // Paper + } + } + diff --git a/patches/server-unmapped/0490-Optimize-Bit-Operations-by-inlining.patch b/patches/server-unmapped/0490-Optimize-Bit-Operations-by-inlining.patch new file mode 100644 index 0000000000..3e547b0e89 --- /dev/null +++ b/patches/server-unmapped/0490-Optimize-Bit-Operations-by-inlining.patch @@ -0,0 +1,220 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 4 Jun 2020 02:24:49 -0400 +Subject: [PATCH] Optimize Bit Operations by inlining + +Inline bit operations and reduce instruction count to make these hot +operations faster + +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index 1fb931d4c0720a5e496030e25c865771aea3ec70..eb67af795dd716d9f92ac32843accc1ec4efd647 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -31,14 +31,16 @@ public class BlockPosition extends BaseBlockPosition { + }).stable(); + private static final Logger LOGGER = LogManager.getLogger(); + public static final BlockPosition ZERO = new BlockPosition(0, 0, 0); +- private static final int f = 1 + MathHelper.f(MathHelper.c(30000000)); +- private static final int g = BlockPosition.f; +- private static final int h = 64 - BlockPosition.f - BlockPosition.g; +- private static final long i = (1L << BlockPosition.f) - 1L; +- private static final long j = (1L << BlockPosition.h) - 1L; +- private static final long k = (1L << BlockPosition.g) - 1L; +- private static final int l = BlockPosition.h; +- private static final int m = BlockPosition.h + BlockPosition.g; ++ // Paper start - static constants ++ private static final int f = 26; ++ private static final int g = 26; ++ private static final int h = 12; ++ private static final long i = 67108863; ++ private static final long j = 4095; ++ private static final long k = 67108863; ++ private static final int l = 12; ++ private static final int m = 38; ++ // Paper end + + public BlockPosition(int i, int j, int k) { + super(i, j, k); +@@ -60,28 +62,29 @@ public class BlockPosition extends BaseBlockPosition { + this(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); + } + ++ public static long getAdjacent(int baseX, int baseY, int baseZ, EnumDirection enumdirection) { return asLong(baseX + enumdirection.getAdjacentX(), baseY + enumdirection.getAdjacentY(), baseZ + enumdirection.getAdjacentZ()); } // Paper + public static long a(long i, EnumDirection enumdirection) { + return a(i, enumdirection.getAdjacentX(), enumdirection.getAdjacentY(), enumdirection.getAdjacentZ()); + } + + public static long a(long i, int j, int k, int l) { +- return a(b(i) + j, c(i) + k, d(i) + l); ++ return a((int) (i >> 38) + j, (int) ((i << 52) >> 52) + k, (int) ((i << 26) >> 38) + l); // Paper - simplify/inline + } + + public static int b(long i) { +- return (int) (i << 64 - BlockPosition.m - BlockPosition.f >> 64 - BlockPosition.f); ++ return (int) (i >> 38); // Paper - simplify/inline + } + + public static int c(long i) { +- return (int) (i << 64 - BlockPosition.h >> 64 - BlockPosition.h); ++ return (int) ((i << 52) >> 52); // Paper - simplify/inline + } + + public static int d(long i) { +- return (int) (i << 64 - BlockPosition.l - BlockPosition.g >> 64 - BlockPosition.g); ++ return (int) ((i << 26) >> 38); // Paper - simplify/inline + } + + public static BlockPosition fromLong(long i) { +- return new BlockPosition(b(i), c(i), d(i)); ++ return new BlockPosition((int) (i >> 38), (int) ((i << 52) >> 52), (int) ((i << 26) >> 38)); // Paper - simplify/inline + } + + public long asLong() { +@@ -90,12 +93,7 @@ public class BlockPosition extends BaseBlockPosition { + + public static long asLong(int x, int y, int z) { return a(x, y, z); } // Paper - OBFHELPER + public static long a(int i, int j, int k) { +- long l = 0L; +- +- l |= ((long) i & BlockPosition.i) << BlockPosition.m; +- l |= ((long) j & BlockPosition.j) << 0; +- l |= ((long) k & BlockPosition.k) << BlockPosition.l; +- return l; ++ return (((long) i & (long) 67108863) << 38) | (((long) j & (long) 4095)) | (((long) k & (long) 67108863) << 12); // Paper - inline constants and simplify + } + + public static long f(long i) { +diff --git a/src/main/java/net/minecraft/core/SectionPosition.java b/src/main/java/net/minecraft/core/SectionPosition.java +index 97126ae5a43bb7acb04a1ab14fb7f364c8c2675f..7d9a16eb81288b74425319c60525f57c98ad3b69 100644 +--- a/src/main/java/net/minecraft/core/SectionPosition.java ++++ b/src/main/java/net/minecraft/core/SectionPosition.java +@@ -19,7 +19,7 @@ public class SectionPosition extends BaseBlockPosition { + } + + public static SectionPosition a(BlockPosition blockposition) { +- return new SectionPosition(a(blockposition.getX()), a(blockposition.getY()), a(blockposition.getZ())); ++ return new SectionPosition(blockposition.getX() >> 4, blockposition.getY() >> 4, blockposition.getZ() >> 4); // Paper + } + + public static SectionPosition a(ChunkCoordIntPair chunkcoordintpair, int i) { +@@ -31,15 +31,23 @@ public class SectionPosition extends BaseBlockPosition { + } + + public static SectionPosition a(long i) { +- return new SectionPosition(b(i), c(i), d(i)); ++ return new SectionPosition((int) (i >> 42), (int) (i << 44 >> 44), (int) (i << 22 >> 42)); // Paper + } + + public static long a(long i, EnumDirection enumdirection) { + return a(i, enumdirection.getAdjacentX(), enumdirection.getAdjacentY(), enumdirection.getAdjacentZ()); + } + ++ // Paper start ++ public static long getAdjacentFromBlockPos(int x, int y, int z, EnumDirection enumdirection) { ++ return (((long) ((x >> 4) + enumdirection.getAdjacentX()) & 4194303L) << 42) | (((long) ((y >> 4) + enumdirection.getAdjacentY()) & 1048575L)) | (((long) ((z >> 4) + enumdirection.getAdjacentZ()) & 4194303L) << 20); ++ } ++ public static long getAdjacentFromSectionPos(int x, int y, int z, EnumDirection enumdirection) { ++ return (((long) (x + enumdirection.getAdjacentX()) & 4194303L) << 42) | (((long) ((y) + enumdirection.getAdjacentY()) & 1048575L)) | (((long) (z + enumdirection.getAdjacentZ()) & 4194303L) << 20); ++ } ++ // Paper end + public static long a(long i, int j, int k, int l) { +- return b(b(i) + j, c(i) + k, d(i) + l); ++ return (((long) ((int) (i >> 42) + j) & 4194303L) << 42) | (((long) ((int) (i << 44 >> 44) + k) & 1048575L)) | (((long) ((int) (i << 22 >> 42) + l) & 4194303L) << 20); // Simplify to reduce instruction count + } + + public static int a(int i) { +@@ -51,11 +59,7 @@ public class SectionPosition extends BaseBlockPosition { + } + + public static short b(BlockPosition blockposition) { +- int i = b(blockposition.getX()); +- int j = b(blockposition.getY()); +- int k = b(blockposition.getZ()); +- +- return (short) (i << 8 | k << 4 | j << 0); ++ return (short) ((blockposition.getX() & 15) << 8 | (blockposition.getZ() & 15) << 4 | blockposition.getY() & 15); // Paper - simplify/inline + } + + public static int a(short short0) { +@@ -114,16 +118,16 @@ public class SectionPosition extends BaseBlockPosition { + return this.getZ(); + } + +- public int d() { +- return this.a() << 4; ++ public final int d() { // Paper ++ return this.getX() << 4; // Paper + } + +- public int e() { +- return this.b() << 4; ++ public final int e() { // Paper ++ return this.getY() << 4; // Paper + } + +- public int f() { +- return this.c() << 4; ++ public final int f() { // Paper ++ return this.getZ() << 4; // Paper + } + + public int g() { +@@ -138,8 +142,10 @@ public class SectionPosition extends BaseBlockPosition { + return (this.c() << 4) + 15; + } + ++ public static long blockToSection(long i) { return e(i); } // Paper - OBFHELPER + public static long e(long i) { +- return b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); ++ // b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); ++ return (((long) (int) (i >> 42) & 4194303L) << 42) | (((long) (int) ((i << 52) >> 56) & 1048575L)) | (((long) (int) ((i << 26) >> 42) & 4194303L) << 20); // Simplify to reduce instruction count + } + + public static long f(long i) { +@@ -160,17 +166,18 @@ public class SectionPosition extends BaseBlockPosition { + return new ChunkCoordIntPair(this.a(), this.c()); + } + ++ // Paper start ++ public static long blockPosAsSectionLong(int i, int j, int k) { ++ return (((long) (i >> 4) & 4194303L) << 42) | (((long) (j >> 4) & 1048575L)) | (((long) (k >> 4) & 4194303L) << 20); ++ } ++ // Paper end ++ public static long asLong(int i, int j, int k) { return b(i, j, k); } // Paper - OBFHELPER + public static long b(int i, int j, int k) { +- long l = 0L; +- +- l |= ((long) i & 4194303L) << 42; +- l |= ((long) j & 1048575L) << 0; +- l |= ((long) k & 4194303L) << 20; +- return l; ++ return (((long) i & 4194303L) << 42) | (((long) j & 1048575L)) | (((long) k & 4194303L) << 20); // Paper - Simplify to reduce instruction count + } + + public long s() { +- return b(this.a(), this.b(), this.c()); ++ return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count + } + + public Stream t() { +@@ -178,18 +185,11 @@ public class SectionPosition extends BaseBlockPosition { + } + + public static Stream a(SectionPosition sectionposition, int i) { +- int j = sectionposition.a(); +- int k = sectionposition.b(); +- int l = sectionposition.c(); +- +- return a(j - i, k - i, l - i, j + i, k + i, l + i); ++ return a(sectionposition.getX() - i, sectionposition.getY() - i, sectionposition.getZ() - i, sectionposition.getX() + i, sectionposition.getY() + i, sectionposition.getZ() + i); // Paper - simplify/inline + } + + public static Stream b(ChunkCoordIntPair chunkcoordintpair, int i) { +- int j = chunkcoordintpair.x; +- int k = chunkcoordintpair.z; +- +- return a(j - i, 0, k - i, j + i, 15, k + i); ++ return a(chunkcoordintpair.x - i, 0, chunkcoordintpair.z - i, chunkcoordintpair.x + i, 15, chunkcoordintpair.z + i); // Paper - simplify/inline + } + + public static Stream a(final int i, final int j, final int k, final int l, final int i1, final int j1) { diff --git a/patches/server-unmapped/0491-Optimize-Light-Engine.patch b/patches/server-unmapped/0491-Optimize-Light-Engine.patch new file mode 100644 index 0000000000..8e197795b4 --- /dev/null +++ b/patches/server-unmapped/0491-Optimize-Light-Engine.patch @@ -0,0 +1,1433 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 4 Jun 2020 22:43:29 -0400 +Subject: [PATCH] Optimize Light Engine + +Massive update to light to improve performance and chunk loading/generation. + +1) Massive bit packing/unpacking optimizations and inlining. + A lot of performance has to do with constant packing and unpacking of bits. + We now inline a most bit operations, and re-use base x/y/z bits in many places. + This helps with cpu level processing to just do all the math at once instead + of having to jump in and out of function calls. + + This much logic also is likely over the JVM Inline limit for JIT too. +2) Applied a few of JellySquid's Phosphor mod optimizations such as + - ensuring we don't notify neighbor chunks when neighbor chunk doesn't need to be notified + - reduce hasLight checks in initializing light, and prob some more, they are tagged JellySquid where phosphor influence was used. +3) Optimize hot path accesses to getting updating chunk to have less branching +4) Optimize getBlock accesses to have less branching, and less unpacking +5) Have a separate urgent bucket for chunk light tasks. These tasks will always cut in line over non blocking light tasks. +6) Retain chunk priority while light tasks are enqueued. So if a task comes in at high priority but the queue is full + of tasks already at a lower priority, before the task was simply added to the end. Now it can cut in line to the front. + this applies for both urgent and non urgent tasks. +7) Buffer non urgent tasks even if queueUpdate is called multiple times to improve efficiency. +8) Fix NPE risk that crashes server in getting nibble data + +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 17a4970cf78f3ee3a62a76a3f9e28251db17bac2..6770307d69c6b3934bfa804fd713cade22f0fb5c 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -1072,7 +1072,7 @@ public class ChunkProviderServer extends IChunkProvider { + if (ChunkProviderServer.this.tickDistanceManager()) { + return true; + } else { +- ChunkProviderServer.this.lightEngine.queueUpdate(); ++ ChunkProviderServer.this.lightEngine.queueUpdate(); // Paper - not needed + return super.executeNext() || execChunkTask; // Paper + } + } finally { +diff --git a/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java b/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java +index c8bb040e7ed848877ec9c2f9b30dcda137cadf35..4ee7070364a8989eece4fa4237b529926821f9c9 100644 +--- a/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java ++++ b/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java +@@ -16,14 +16,20 @@ public abstract class LightEngineGraphSection extends LightEngineGraph { + + @Override + protected void a(long i, int j, boolean flag) { ++ // Paper start ++ int x = (int) (i >> 42); ++ int y = (int) (i << 44 >> 44); ++ int z = (int) (i << 22 >> 42); ++ // Paper end + for (int k = -1; k <= 1; ++k) { + for (int l = -1; l <= 1; ++l) { + for (int i1 = -1; i1 <= 1; ++i1) { +- long j1 = SectionPosition.a(i, k, l, i1); ++ if (k == 0 && l == 0 && i1 == 0) continue; // Paper ++ long j1 = (((long) (x + k) & 4194303L) << 42) | (((long) (y + l) & 1048575L)) | (((long) (z + i1) & 4194303L) << 20); // Paper + +- if (j1 != i) { ++ //if (j1 != i) { // Paper - checked above + this.b(i, j1, j, flag); +- } ++ //} // Paper + } + } + } +@@ -34,10 +40,15 @@ public abstract class LightEngineGraphSection extends LightEngineGraph { + protected int a(long i, long j, int k) { + int l = k; + ++ // Paper start ++ int x = (int) (i >> 42); ++ int y = (int) (i << 44 >> 44); ++ int z = (int) (i << 22 >> 42); ++ // Paper end + for (int i1 = -1; i1 <= 1; ++i1) { + for (int j1 = -1; j1 <= 1; ++j1) { + for (int k1 = -1; k1 <= 1; ++k1) { +- long l1 = SectionPosition.a(i, i1, j1, k1); ++ long l1 = (((long) (x + i1) & 4194303L) << 42) | (((long) (y + j1) & 1048575L)) | (((long) (z + k1) & 4194303L) << 20); // Paper + + if (l1 == i) { + l1 = Long.MAX_VALUE; +diff --git a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java +index e066848127cb9a42e8c39422691cc65132cac6bb..0b80569648c1df01aab52d0b8d47028cda925d86 100644 +--- a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java ++++ b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java +@@ -1,6 +1,7 @@ + package net.minecraft.server.level; + + import com.mojang.datafixers.util.Pair; ++import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; // Paper + import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import it.unimi.dsi.fastutil.objects.ObjectList; + import it.unimi.dsi.fastutil.objects.ObjectListIterator; +@@ -16,6 +17,7 @@ import net.minecraft.util.thread.ThreadedMailbox; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.chunk.ChunkSection; ++import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.IChunkAccess; + import net.minecraft.world.level.chunk.ILightAccess; + import net.minecraft.world.level.chunk.NibbleArray; +@@ -27,15 +29,149 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { + + private static final Logger LOGGER = LogManager.getLogger(); + private final ThreadedMailbox b; +- private final ObjectList> c = new ObjectArrayList(); +- private final PlayerChunkMap d; ++ // Paper start ++ private static final int MAX_PRIORITIES = PlayerChunkMap.GOLDEN_TICKET + 2; ++ ++ private boolean isChunkLightStatus(long pair) { ++ PlayerChunk playerChunk = playerChunkMap.getVisibleChunk(pair); ++ if (playerChunk == null) { ++ return false; ++ } ++ ChunkStatus status = PlayerChunk.getChunkStatus(playerChunk.getTicketLevel()); ++ return status != null && status.isAtLeastStatus(ChunkStatus.LIGHT); ++ } ++ ++ static class ChunkLightQueue { ++ public boolean shouldFastUpdate; ++ java.util.ArrayDeque pre = new java.util.ArrayDeque(); ++ java.util.ArrayDeque post = new java.util.ArrayDeque(); ++ ++ ChunkLightQueue(long chunk) {} ++ } ++ ++ static class PendingLightTask { ++ long chunkId; ++ IntSupplier priority; ++ Runnable pre; ++ Runnable post; ++ boolean fastUpdate; ++ ++ public PendingLightTask(long chunkId, IntSupplier priority, Runnable pre, Runnable post, boolean fastUpdate) { ++ this.chunkId = chunkId; ++ this.priority = priority; ++ this.pre = pre; ++ this.post = post; ++ this.fastUpdate = fastUpdate; ++ } ++ } ++ ++ ++ // Retain the chunks priority level for queued light tasks ++ class LightQueue { ++ private int size = 0; ++ private final Long2ObjectLinkedOpenHashMap[] buckets = new Long2ObjectLinkedOpenHashMap[MAX_PRIORITIES]; ++ private final java.util.concurrent.ConcurrentLinkedQueue pendingTasks = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ private final java.util.concurrent.ConcurrentLinkedQueue priorityChanges = new java.util.concurrent.ConcurrentLinkedQueue<>(); ++ ++ private LightQueue() { ++ for (int i = 0; i < buckets.length; i++) { ++ buckets[i] = new Long2ObjectLinkedOpenHashMap<>(); ++ } ++ } ++ ++ public void changePriority(long pair, int currentPriority, int priority) { ++ this.priorityChanges.add(() -> { ++ ChunkLightQueue remove = this.buckets[currentPriority].remove(pair); ++ if (remove != null) { ++ ChunkLightQueue existing = this.buckets[Math.max(1, priority)].put(pair, remove); ++ if (existing != null) { ++ remove.pre.addAll(existing.pre); ++ remove.post.addAll(existing.post); ++ } ++ } ++ }); ++ } ++ ++ public final void addChunk(long chunkId, IntSupplier priority, Runnable pre, Runnable post) { ++ pendingTasks.add(new PendingLightTask(chunkId, priority, pre, post, true)); ++ queueUpdate(); ++ } ++ ++ public final void add(long chunkId, IntSupplier priority, LightEngineThreaded.Update type, Runnable run) { ++ pendingTasks.add(new PendingLightTask(chunkId, priority, type == Update.PRE_UPDATE ? run : null, type == Update.POST_UPDATE ? run : null, false)); ++ } ++ public final void add(PendingLightTask update) { ++ int priority = update.priority.getAsInt(); ++ ChunkLightQueue lightQueue = this.buckets[priority].computeIfAbsent(update.chunkId, ChunkLightQueue::new); ++ ++ if (update.pre != null) { ++ this.size++; ++ lightQueue.pre.add(update.pre); ++ } ++ if (update.post != null) { ++ this.size++; ++ lightQueue.post.add(update.post); ++ } ++ if (update.fastUpdate) { ++ lightQueue.shouldFastUpdate = true; ++ } ++ } ++ ++ public final boolean isEmpty() { ++ return this.size == 0 && this.pendingTasks.isEmpty(); ++ } ++ ++ public final int size() { ++ return this.size; ++ } ++ ++ public boolean poll(java.util.List pre, java.util.List post) { ++ PendingLightTask pending; ++ while ((pending = pendingTasks.poll()) != null) { ++ add(pending); ++ } ++ Runnable run; ++ while ((run = priorityChanges.poll()) != null) { ++ run.run(); ++ } ++ boolean hasWork = false; ++ Long2ObjectLinkedOpenHashMap[] buckets = this.buckets; ++ int priority = 0; ++ while (priority < MAX_PRIORITIES && !isEmpty()) { ++ Long2ObjectLinkedOpenHashMap bucket = buckets[priority]; ++ if (bucket.isEmpty()) { ++ priority++; ++ if (hasWork) { ++ return true; ++ } else { ++ continue; ++ } ++ } ++ ChunkLightQueue queue = bucket.removeFirst(); ++ this.size -= queue.pre.size() + queue.post.size(); ++ pre.addAll(queue.pre); ++ post.addAll(queue.post); ++ queue.pre.clear(); ++ queue.post.clear(); ++ hasWork = true; ++ if (queue.shouldFastUpdate) { ++ return true; ++ } ++ } ++ return hasWork; ++ } ++ } ++ ++ final LightQueue queue = new LightQueue(); ++ // Paper end ++ private final PlayerChunkMap d; private final PlayerChunkMap playerChunkMap; // Paper + private final Mailbox> e; + private volatile int f = 5; + private final AtomicBoolean g = new AtomicBoolean(); + + public LightEngineThreaded(ILightAccess ilightaccess, PlayerChunkMap playerchunkmap, boolean flag, ThreadedMailbox threadedmailbox, Mailbox> mailbox) { + super(ilightaccess, true, flag); +- this.d = playerchunkmap; ++ this.d = playerchunkmap; this.playerChunkMap = d; // Paper + this.e = mailbox; + this.b = threadedmailbox; + } +@@ -122,13 +258,9 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { + } + + private void a(int i, int j, IntSupplier intsupplier, LightEngineThreaded.Update lightenginethreaded_update, Runnable runnable) { +- this.e.a(ChunkTaskQueueSorter.a(() -> { +- this.c.add(Pair.of(lightenginethreaded_update, runnable)); +- if (this.c.size() >= this.f) { +- this.b(); +- } +- +- }, ChunkCoordIntPair.pair(i, j), intsupplier)); ++ // Paper start - replace method ++ this.queue.add(ChunkCoordIntPair.pair(i, j), intsupplier, lightenginethreaded_update, runnable); ++ // Paper end + } + + @Override +@@ -145,8 +277,19 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { + public CompletableFuture a(IChunkAccess ichunkaccess, boolean flag) { + ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); + +- ichunkaccess.b(false); +- this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { ++ // Paper start ++ //ichunkaccess.b(false); // Don't need to disable this ++ long pair = chunkcoordintpair.pair(); ++ CompletableFuture future = new CompletableFuture<>(); ++ IntSupplier prioritySupplier = playerChunkMap.getPrioritySupplier(pair); ++ boolean[] skippedPre = {false}; ++ this.queue.addChunk(pair, prioritySupplier, SystemUtils.a(() -> { ++ if (!isChunkLightStatus(pair)) { ++ future.complete(ichunkaccess); ++ skippedPre[0] = true; ++ return; ++ } ++ // Paper end + ChunkSection[] achunksection = ichunkaccess.getSections(); + + for (int i = 0; i < 16; ++i) { +@@ -164,55 +307,48 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { + }); + } + +- this.d.c(chunkcoordintpair); ++ // this.d.c(chunkcoordintpair); // Paper - move into post task below + }, () -> { + return "lightChunk " + chunkcoordintpair + " " + flag; +- })); +- return CompletableFuture.supplyAsync(() -> { ++ // Paper start - merge the 2 together ++ }), () -> { ++ this.d.c(chunkcoordintpair); // Paper - release light tickets as post task to ensure they stay loaded until fully done ++ if (skippedPre[0]) return; // Paper - future's already complete + ichunkaccess.b(true); + super.b(chunkcoordintpair, false); +- return ichunkaccess; +- }, (runnable) -> { +- this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.POST_UPDATE, runnable); ++ // Paper start ++ future.complete(ichunkaccess); + }); ++ return future; ++ // Paper end + } + + public void queueUpdate() { +- if ((!this.c.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { ++ if ((!this.queue.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { // Paper + this.b.a((() -> { // Paper - decompile error + this.b(); + this.g.set(false); ++ queueUpdate(); // Paper - if we still have work to do, do it! + })); + } + + } + ++ // Paper start - replace impl ++ private final java.util.List pre = new java.util.ArrayList<>(); ++ private final java.util.List post = new java.util.ArrayList<>(); + private void b() { +- int i = Math.min(this.c.size(), this.f); +- ObjectListIterator> objectlistiterator = this.c.iterator(); +- +- Pair pair; +- int j; +- +- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { +- pair = (Pair) objectlistiterator.next(); +- if (pair.getFirst() == LightEngineThreaded.Update.PRE_UPDATE) { +- ((Runnable) pair.getSecond()).run(); +- } ++ if (queue.poll(pre, post)) { ++ pre.forEach(Runnable::run); ++ pre.clear(); ++ super.a(Integer.MAX_VALUE, true, true); ++ post.forEach(Runnable::run); ++ post.clear(); ++ } else { ++ // might have level updates to go still ++ super.a(Integer.MAX_VALUE, true, true); + } +- +- objectlistiterator.back(j); +- super.a(Integer.MAX_VALUE, true, true); +- +- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { +- pair = (Pair) objectlistiterator.next(); +- if (pair.getFirst() == LightEngineThreaded.Update.POST_UPDATE) { +- ((Runnable) pair.getSecond()).run(); +- } +- +- objectlistiterator.remove(); +- } +- ++ // Paper end + } + + public void a(int i) { +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index 88022e3ccd04f9c041ced68be66a95247c1017e9..d6a5a0b17308913a5efd97cd27fabd0825ef68c6 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -754,6 +754,7 @@ public class PlayerChunk { + ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; + } + chunkMap.world.asyncChunkTaskManager.raisePriority(location.x, location.z, ioPriority); ++ chunkMap.world.getChunkProvider().getLightEngine().queue.changePriority(location.pair(), getCurrentPriority(), priority); + } + if (getCurrentPriority() != priority) { + this.u.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 74146ab6bd172807fb8545c1a29e376b1224e34d..169fa174f86f8a8dc42d3b9c4954a39d0a738c06 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -99,6 +99,7 @@ import net.minecraft.world.level.chunk.storage.RegionFile; + import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureManager; + import net.minecraft.world.level.storage.Convertable; ++import net.minecraft.world.level.storage.WorldDataServer; + import net.minecraft.world.level.storage.WorldPersistentData; + import net.minecraft.world.phys.Vec3D; + import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper +@@ -331,6 +332,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + // Paper end + ++ private final java.util.concurrent.ExecutorService lightThread; + public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { + super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag); + //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning +@@ -362,7 +364,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + Mailbox mailbox = Mailbox.a("main", iasynctaskhandler::a); + + this.worldLoadListener = worldloadlistener; +- ThreadedMailbox lightthreaded; ThreadedMailbox threadedmailbox1 = lightthreaded = ThreadedMailbox.a(executor, "light"); // Paper ++ // Paper start - use light thread ++ ThreadedMailbox lightthreaded; ThreadedMailbox threadedmailbox1 = lightthreaded = ThreadedMailbox.a(lightThread = java.util.concurrent.Executors.newSingleThreadExecutor(r -> { ++ Thread thread = new Thread(r); ++ thread.setName(((WorldDataServer)world.getWorldData()).getName() + " - Light"); ++ thread.setDaemon(true); ++ thread.setPriority(Thread.NORM_PRIORITY+1); ++ return thread; ++ }), "light"); ++ // Paper end + + this.p = new ChunkTaskQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE); + this.mailboxWorldGen = this.p.a(threadedmailbox, false); +@@ -708,6 +718,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + // Paper end + } + ++ protected final IntSupplier getPrioritySupplier(long i) { return c(i); } // Paper - OBFHELPER + protected IntSupplier c(long i) { + return () -> { + PlayerChunk playerchunk = this.getVisibleChunk(i); +@@ -835,6 +846,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + @Override + public void close() throws IOException { + try { ++ this.lightThread.shutdown(); // Paper + this.p.close(); + this.world.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line + this.m.close(); +diff --git a/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java b/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java +index 2efca1fe92b2e93dcbf5337eea8855b1b2b9a564..72bfda620f073fd3c3e4c43d78583386dadf95e6 100644 +--- a/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java ++++ b/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java +@@ -110,7 +110,8 @@ public class ThreadedMailbox implements Mailbox, AutoCloseable, Runnable { + + } + +- @Override ++ ++ public final void queue(T t0) { a(t0); } @Override // Paper - OBFHELPER + public void a(T t0) { + this.a.a(t0); + this.f(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java +index b82420e9a5d42a4383d24921614fe613c640edb9..0fec15e141051863dbf51a2b3e1ace5028cd2fc1 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java ++++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java +@@ -11,6 +11,13 @@ import net.minecraft.server.MCUtil; + public class NibbleArray { + + // Paper start ++ public static final NibbleArray EMPTY_NIBBLE_ARRAY = new NibbleArray() { ++ @Override ++ public byte[] asBytes() { ++ throw new IllegalStateException(); ++ } ++ }; ++ public long lightCacheKey = Long.MIN_VALUE; + public static byte[] EMPTY_NIBBLE = new byte[2048]; + private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072); + private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8)); +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java +index f6198069e3ca421b4f551939263c7cf8bd5b754e..29e98864209c51368a91fa9e530c33cbf9830b51 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java +@@ -23,9 +23,11 @@ public final class LightEngineBlock extends LightEngineLayer> 38); ++ int k = (int) ((i << 52) >> 52); ++ int l = (int) ((i << 26) >> 38); ++ // Paper end + IBlockAccess iblockaccess = this.a.c(j >> 4, l >> 4); + + return iblockaccess != null ? iblockaccess.g(this.f.d(j, k, l)) : 0; +@@ -40,25 +42,33 @@ public final class LightEngineBlock extends LightEngineLayer= 15) { + return k; + } else { +- int l = Integer.signum(BlockPosition.b(j) - BlockPosition.b(i)); +- int i1 = Integer.signum(BlockPosition.c(j) - BlockPosition.c(i)); +- int j1 = Integer.signum(BlockPosition.d(j) - BlockPosition.d(i)); ++ // Paper start - reuse math - credit to JellySquid for idea ++ int jx = (int) (j >> 38); ++ int jy = (int) ((j << 52) >> 52); ++ int jz = (int) ((j << 26) >> 38); ++ int ix = (int) (i >> 38); ++ int iy = (int) ((i << 52) >> 52); ++ int iz = (int) ((i << 26) >> 38); ++ int l = Integer.signum(jx - ix); ++ int i1 = Integer.signum(jy - iy); ++ int j1 = Integer.signum(jz - iz); ++ // Paper end + EnumDirection enumdirection = EnumDirection.a(l, i1, j1); + + if (enumdirection == null) { + return 15; + } else { + //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded +- IBlockData iblockdata = this.a(j, mutableint); +- +- if (mutableint.getValue() >= 15) { ++ IBlockData iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); // Paper ++ int blockedLight = mutableint.getValue(); // Paper ++ if (blockedLight >= 15) { // Paper + return 15; + } else { +- IBlockData iblockdata1 = this.a(i, (MutableInt) null); ++ IBlockData iblockdata1 = this.getBlockOptimized(ix, iy, iz); // Paper + VoxelShape voxelshape = this.a(iblockdata1, i, enumdirection); + VoxelShape voxelshape1 = this.a(iblockdata, j, enumdirection.opposite()); + +- return VoxelShapes.b(voxelshape, voxelshape1) ? 15 : k + Math.max(1, mutableint.getValue()); ++ return VoxelShapes.b(voxelshape, voxelshape1) ? 15 : k + Math.max(1, blockedLight); // Paper + } + } + } +@@ -66,14 +76,19 @@ public final class LightEngineBlock extends LightEngineLayer> 38); ++ int y = (int) ((i << 52) >> 52); ++ int z = (int) ((i << 26) >> 38); ++ long k = SectionPosition.blockPosAsSectionLong(x, y, z); ++ // Paper end + EnumDirection[] aenumdirection = LightEngineBlock.e; + int l = aenumdirection.length; + + for (int i1 = 0; i1 < l; ++i1) { + EnumDirection enumdirection = aenumdirection[i1]; +- long j1 = BlockPosition.a(i, enumdirection); +- long k1 = SectionPosition.e(j1); ++ long j1 = BlockPosition.getAdjacent(x, y, z, enumdirection); // Paper ++ long k1 = SectionPosition.blockToSection(j1); // Paper + + if (k == k1 || ((LightEngineStorageBlock) this.c).g(k1)) { + this.b(i, j1, j, flag); +@@ -98,27 +113,37 @@ public final class LightEngineBlock extends LightEngineLayer> 38); ++ int baseY = (int) ((i << 52) >> 52); ++ int baseZ = (int) ((i << 26) >> 38); ++ long j1 = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); ++ NibbleArray nibblearray = this.c.updating.getUpdatingOptimized(j1); ++ // Paper end + EnumDirection[] aenumdirection = LightEngineBlock.e; + int k1 = aenumdirection.length; + + for (int l1 = 0; l1 < k1; ++l1) { + EnumDirection enumdirection = aenumdirection[l1]; +- long i2 = BlockPosition.a(i, enumdirection); ++ // Paper start ++ int newX = baseX + enumdirection.getAdjacentX(); ++ int newY = baseY + enumdirection.getAdjacentY(); ++ int newZ = baseZ + enumdirection.getAdjacentZ(); ++ long i2 = BlockPosition.asLong(newX, newY, newZ); + + if (i2 != j) { +- long j2 = SectionPosition.e(i2); ++ long j2 = SectionPosition.blockPosAsSectionLong(newX, newY, newZ); ++ // Paper end + NibbleArray nibblearray1; + + if (j1 == j2) { + nibblearray1 = nibblearray; + } else { +- nibblearray1 = ((LightEngineStorageBlock) this.c).a(j2, true); ++ nibblearray1 = ((LightEngineStorageBlock) this.c).updating.getUpdatingOptimized(j2); // Paper + } + + if (nibblearray1 != null) { +- int k2 = this.b(i2, i, this.a(nibblearray1, i2)); ++ int k2 = this.b(i2, i, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper + + if (l > k2) { + l = k2; +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java +index 944a8c295ff9df0d96800ddc4f6763598cf61d0d..64dad8ed7c16011d9cb3e9d22ac6f892c638e3b2 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java +@@ -10,6 +10,7 @@ import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.IBlockAccess; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.chunk.IChunkAccess; + import net.minecraft.world.level.chunk.ILightAccess; + import net.minecraft.world.level.chunk.NibbleArray; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -23,10 +24,37 @@ public abstract class LightEngineLayer, S e + protected final EnumSkyBlock b; + protected final S c; + private boolean f; +- protected final BlockPosition.MutableBlockPosition d = new BlockPosition.MutableBlockPosition(); ++ protected final BlockPosition.MutableBlockPosition d = new BlockPosition.MutableBlockPosition(); protected final BlockPosition.MutableBlockPosition pos = d; // Paper + private final long[] g = new long[2]; +- private final IBlockAccess[] h = new IBlockAccess[2]; ++ private final IChunkAccess[] h = new IChunkAccess[2]; // Paper + ++ // Paper start - see fully commented out method below (look for Bedrock) ++ // optimized method with less branching for when scenarios arent needed. ++ // avoid using mutable version if can ++ protected final IBlockData getBlockOptimized(int x, int y, int z, MutableInt mutableint) { ++ IChunkAccess iblockaccess = this.a(x >> 4, z >> 4); ++ ++ if (iblockaccess == null) { ++ mutableint.setValue(16); ++ return Blocks.BEDROCK.getBlockData(); ++ } else { ++ this.pos.setValues(x, y, z); ++ IBlockData iblockdata = iblockaccess.getType(x, y, z); ++ mutableint.setValue(iblockdata.b(this.a.getWorld(), this.pos)); ++ return iblockdata.l() && iblockdata.e() ? iblockdata : Blocks.AIR.getBlockData(); ++ } ++ } ++ protected final IBlockData getBlockOptimized(int x, int y, int z) { ++ IChunkAccess iblockaccess = this.a(x >> 4, z >> 4); ++ ++ if (iblockaccess == null) { ++ return Blocks.BEDROCK.getBlockData(); ++ } else { ++ IBlockData iblockdata = iblockaccess.getType(x, y, z); ++ return iblockdata.l() && iblockdata.e() ? iblockdata : Blocks.AIR.getBlockData(); ++ } ++ } ++ // Paper end + public LightEngineLayer(ILightAccess ilightaccess, EnumSkyBlock enumskyblock, S s0) { + super(16, 256, 8192); + this.a = ilightaccess; +@@ -45,7 +73,7 @@ public abstract class LightEngineLayer, S e + } + + @Nullable +- private IBlockAccess a(int i, int j) { ++ private IChunkAccess a(int i, int j) { // Paper + long k = ChunkCoordIntPair.pair(i, j); + + for (int l = 0; l < 2; ++l) { +@@ -54,7 +82,7 @@ public abstract class LightEngineLayer, S e + } + } + +- IBlockAccess iblockaccess = this.a.c(i, j); ++ IChunkAccess iblockaccess = (IChunkAccess) this.a.c(i, j); // Paper + + for (int i1 = 1; i1 > 0; --i1) { + this.g[i1] = this.g[i1 - 1]; +@@ -71,37 +99,39 @@ public abstract class LightEngineLayer, S e + Arrays.fill(this.h, (Object) null); + } + +- protected IBlockData a(long i, @Nullable MutableInt mutableint) { +- if (i == Long.MAX_VALUE) { +- if (mutableint != null) { +- mutableint.setValue(0); +- } +- +- return Blocks.AIR.getBlockData(); +- } else { +- int j = SectionPosition.a(BlockPosition.b(i)); +- int k = SectionPosition.a(BlockPosition.d(i)); +- IBlockAccess iblockaccess = this.a(j, k); +- +- if (iblockaccess == null) { +- if (mutableint != null) { +- mutableint.setValue(16); +- } +- +- return Blocks.BEDROCK.getBlockData(); +- } else { +- this.d.g(i); +- IBlockData iblockdata = iblockaccess.getType(this.d); +- boolean flag = iblockdata.l() && iblockdata.e(); +- +- if (mutableint != null) { +- mutableint.setValue(iblockdata.b(this.a.getWorld(), (BlockPosition) this.d)); +- } +- +- return flag ? iblockdata : Blocks.AIR.getBlockData(); +- } +- } +- } ++ // Paper start - comment out, see getBlockOptimized ++// protected IBlockData a(long i, @Nullable MutableInt mutableint) { ++// if (i == Long.MAX_VALUE) { ++// if (mutableint != null) { ++// mutableint.setValue(0); ++// } ++// ++// return Blocks.AIR.getBlockData(); ++// } else { ++// int j = SectionPosition.a(BlockPosition.b(i)); ++// int k = SectionPosition.a(BlockPosition.d(i)); ++// IBlockAccess iblockaccess = this.a(j, k); ++// ++// if (iblockaccess == null) { ++// if (mutableint != null) { ++// mutableint.setValue(16); ++// } ++// ++// return Blocks.BEDROCK.getBlockData(); ++// } else { ++// this.d.g(i); ++// IBlockData iblockdata = iblockaccess.getType(this.d); ++// boolean flag = iblockdata.l() && iblockdata.e(); ++// ++// if (mutableint != null) { ++// mutableint.setValue(iblockdata.b(this.a.getWorld(), (BlockPosition) this.d)); ++// } ++// ++// return flag ? iblockdata : Blocks.AIR.getBlockData(); ++// } ++// } ++// } ++ // Paper end + + protected VoxelShape a(IBlockData iblockdata, long i, EnumDirection enumdirection) { + return iblockdata.l() ? iblockdata.a(this.a.getWorld(), this.d.g(i), enumdirection) : VoxelShapes.a(); +@@ -136,8 +166,9 @@ public abstract class LightEngineLayer, S e + return i == Long.MAX_VALUE ? 0 : 15 - this.c.i(i); + } + ++ protected int getNibbleLightInverse(NibbleArray nibblearray, int x, int y, int z) { return 15 - nibblearray.a(x & 15, y & 15, z & 15); } // Paper - x/y/z version of below + protected int a(NibbleArray nibblearray, long i) { +- return 15 - nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i))); ++ return 15 - nibblearray.a((int) (i >> 38) & 15, (int) ((i << 52) >> 52) & 15, (int) ((i << 26) >> 38) & 15); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java +index 37fa5faea6e2972e3eb8a3cbd1913ef38dc9456f..9cd2dfbfa216fdc58297fd25066d31bb92e13ec2 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java +@@ -4,6 +4,7 @@ import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; + import net.minecraft.core.SectionPosition; + import net.minecraft.world.level.EnumSkyBlock; ++import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ILightAccess; + import net.minecraft.world.level.chunk.NibbleArray; +@@ -38,21 +39,25 @@ public final class LightEngineSky extends LightEngineLayer= 15) { ++ // Paper start - use x/y/z and optimized block lookup ++ int jx = (int) (j >> 38); ++ int jy = (int) ((j << 52) >> 52); ++ int jz = (int) ((j << 26) >> 38); ++ IBlockData iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); ++ int blockedLight = mutableint.getValue(); ++ if (blockedLight >= 15) { ++ // Paper end + return 15; + } else { +- int l = BlockPosition.b(i); +- int i1 = BlockPosition.c(i); +- int j1 = BlockPosition.d(i); +- int k1 = BlockPosition.b(j); +- int l1 = BlockPosition.c(j); +- int i2 = BlockPosition.d(j); +- boolean flag = l == k1 && j1 == i2; +- int j2 = Integer.signum(k1 - l); +- int k2 = Integer.signum(l1 - i1); +- int l2 = Integer.signum(i2 - j1); ++ // Paper start - inline math ++ int ix = (int) (i >> 38); ++ int iy = (int) ((i << 52) >> 52); ++ int iz = (int) ((i << 26) >> 38); ++ boolean flag = ix == jx && iz == jz; ++ int j2 = Integer.signum(jx - ix); ++ int k2 = Integer.signum(jy - iy); ++ int l2 = Integer.signum(jz - iz); ++ // Paper end + EnumDirection enumdirection; + + if (i == Long.MAX_VALUE) { +@@ -61,7 +66,7 @@ public final class LightEngineSky extends LightEngineLayer l1; ++ boolean flag1 = i == Long.MAX_VALUE || flag && iy > jy; // Paper rename vars to iy > jy + +- return flag1 && k == 0 && mutableint.getValue() == 0 ? 0 : k + Math.max(1, mutableint.getValue()); ++ return flag1 && k == 0 && blockedLight == 0 ? 0 : k + Math.max(1, blockedLight); // Paper + } + } + } +@@ -101,10 +106,14 @@ public final class LightEngineSky extends LightEngineLayer> 38); ++ int baseY = (int) ((i << 52) >> 52); ++ int baseZ = (int) ((i << 26) >> 38); ++ long k = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); ++ int i1 = baseY & 15; ++ int j1 = baseY >> 4; ++ // Paper end + int k1; + + if (i1 != 0) { +@@ -119,15 +128,16 @@ public final class LightEngineSky extends LightEngineLayer> 38); ++ int baseY = (int) ((i << 52) >> 52); ++ int baseZ = (int) ((i << 26) >> 38); ++ long j1 = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); ++ NibbleArray nibblearray = this.c.updating.getUpdatingOptimized(j1); ++ // Paper end + EnumDirection[] aenumdirection = LightEngineSky.e; + int k1 = aenumdirection.length; + + for (int l1 = 0; l1 < k1; ++l1) { + EnumDirection enumdirection = aenumdirection[l1]; +- long i2 = BlockPosition.a(i, enumdirection); +- long j2 = SectionPosition.e(i2); ++ // Paper start ++ int newX = baseX + enumdirection.getAdjacentX(); ++ int newY = baseY + enumdirection.getAdjacentY(); ++ int newZ = baseZ + enumdirection.getAdjacentZ(); ++ long i2 = BlockPosition.asLong(newX, newY, newZ); ++ long j2 = SectionPosition.blockPosAsSectionLong(newX, newY, newZ); ++ // Paper end + NibbleArray nibblearray1; + + if (j1 == j2) { + nibblearray1 = nibblearray; + } else { +- nibblearray1 = ((LightEngineStorageSky) this.c).a(j2, true); ++ nibblearray1 = ((LightEngineStorageSky) this.c).updating.getUpdatingOptimized(j2); // Paper + } + + if (nibblearray1 != null) { + if (i2 != j) { +- int k2 = this.b(i2, i, this.a(nibblearray1, i2)); ++ int k2 = this.b(i2, i, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper + + if (l > k2) { + l = k2; +@@ -215,7 +235,7 @@ public final class LightEngineSky extends LightEngineLayer> e + protected final LongSet c = new LongOpenHashSet(); + protected final LongSet d = new LongOpenHashSet(); + protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change +- protected final M f; // Paper - diff on change, should be "updating" ++ protected final M f; protected final M updating; // Paper - diff on change, should be "updating" + protected final LongSet g = new LongOpenHashSet(); +- protected final LongSet h = new LongOpenHashSet(); ++ protected final LongSet h = new LongOpenHashSet(); LongSet dirty = h; // Paper - OBFHELPER + protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); + private final LongSet n = new LongOpenHashSet(); + private final LongSet o = new LongOpenHashSet(); +@@ -37,33 +37,33 @@ public abstract class LightEngineStorage> e + protected volatile boolean j; + + protected LightEngineStorage(EnumSkyBlock enumskyblock, ILightAccess ilightaccess, M m0) { +- super(3, 16, 256); ++ super(3, 256, 256); // Paper - bump expected size of level sets to improve collisions and reduce rehashing (seen a lot of it) + this.l = enumskyblock; + this.m = ilightaccess; +- this.f = m0; ++ this.f = m0; updating = m0; // Paper + this.e_visible = m0.b(); // Paper - avoid copying light data + this.e_visible.d(); // Paper - avoid copying light data + } + +- protected boolean g(long i) { +- return this.a(i, true) != null; ++ protected final boolean g(long i) { // Paper - final to help inlining ++ return this.updating.getUpdatingOptimized(i) != null; // Paper - inline to avoid branching + } + + @Nullable + protected NibbleArray a(long i, boolean flag) { + // Paper start - avoid copying light data + if (flag) { +- return this.a(this.f, i); ++ return this.updating.getUpdatingOptimized(i); + } else { + synchronized (this.visibleUpdateLock) { +- return this.a(this.e_visible, i); ++ return this.e_visible.lookup.apply(i); + } + } + // Paper end - avoid copying light data + } + + @Nullable +- protected NibbleArray a(M m0, long i) { ++ protected final NibbleArray a(M m0, long i) { // Paper + return m0.c(i); + } + +@@ -77,27 +77,57 @@ public abstract class LightEngineStorage> e + protected abstract int d(long i); + + protected int i(long i) { +- long j = SectionPosition.e(i); +- NibbleArray nibblearray = this.a(j, true); ++ // Paper start - reuse and inline math, use Optimized Updating path ++ final int x = (int) (i >> 38); ++ final int y = (int) ((i << 52) >> 52); ++ final int z = (int) ((i << 26) >> 38); ++ long j = SectionPosition.blockPosAsSectionLong(x, y, z); ++ NibbleArray nibblearray = this.updating.getUpdatingOptimized(j); ++ // BUG: Sometimes returns null and crashes, try to recover, but to prevent crash just return no light. ++ if (nibblearray == null) { ++ nibblearray = this.e_visible.lookup.apply(j); ++ } ++ if (nibblearray == null) { ++ System.err.println("Null nibble, preventing crash " + BlockPosition.fromLong(i)); ++ return 0; ++ } + +- return nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i))); ++ return nibblearray.a(x & 15, y & 15, z & 15); // Paper - inline operations ++ // Paper end + } + + protected void b(long i, int j) { +- long k = SectionPosition.e(i); ++ // Paper start - cache part of the math done in loop below ++ int x = (int) (i >> 38); ++ int y = (int) ((i << 52) >> 52); ++ int z = (int) ((i << 26) >> 38); ++ long k = SectionPosition.blockPosAsSectionLong(x, y, z); ++ // Paper end + + if (this.g.add(k)) { + this.f.a(k); + } + + NibbleArray nibblearray = this.a(k, true); +- +- nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i)), j); +- +- for (int l = -1; l <= 1; ++l) { +- for (int i1 = -1; i1 <= 1; ++i1) { +- for (int j1 = -1; j1 <= 1; ++j1) { +- this.h.add(SectionPosition.e(BlockPosition.a(i, i1, j1, l))); ++ nibblearray.a(x & 15, y & 15, z & 15, j); // Paper - use already calculated x/y/z ++ ++ // Paper start - credit to JellySquid for a major optimization here: ++ /* ++ * An extremely important optimization is made here in regards to adding items to the pending notification set. The ++ * original implementation attempts to add the coordinate of every chunk which contains a neighboring block position ++ * even though a huge number of loop iterations will simply map to block positions within the same updating chunk. ++ * ++ * Our implementation here avoids this by pre-calculating the min/max chunk coordinates so we can iterate over only ++ * the relevant chunk positions once. This reduces what would always be 27 iterations to just 1-8 iterations. ++ * ++ * @reason Use faster implementation ++ * @author JellySquid ++ */ ++ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { ++ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { ++ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { ++ this.dirty.add(SectionPosition.asLong(x2, y2, z2)); ++ // Paper end + } + } + } +@@ -129,17 +159,23 @@ public abstract class LightEngineStorage> e + } + + if (k >= 2 && j != 2) { +- if (this.p.contains(i)) { +- this.p.remove(i); +- } else { ++ if (!this.p.remove(i)) { // Paper - remove useless contains - credit to JellySquid ++ //this.p.remove(i); // Paper ++ //} else { // Paper + this.f.a(i, this.j(i)); + this.g.add(i); + this.k(i); + +- for (int l = -1; l <= 1; ++l) { +- for (int i1 = -1; i1 <= 1; ++i1) { +- for (int j1 = -1; j1 <= 1; ++j1) { +- this.h.add(SectionPosition.e(BlockPosition.a(i, i1, j1, l))); ++ // Paper start - reuse x/y/z and only notify valid chunks - Credit to JellySquid (See above method for notes) ++ int x = (int) (i >> 38); ++ int y = (int) ((i << 52) >> 52); ++ int z = (int) ((i << 26) >> 38); ++ ++ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { ++ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { ++ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { ++ this.dirty.add(SectionPosition.asLong(x2, y2, z2)); ++ // Paper end + } + } + } +@@ -165,9 +201,9 @@ public abstract class LightEngineStorage> e + return SectionPosition.e(j) == i; + }); + } else { +- int j = SectionPosition.c(SectionPosition.b(i)); +- int k = SectionPosition.c(SectionPosition.c(i)); +- int l = SectionPosition.c(SectionPosition.d(i)); ++ int j = (int) (i >> 42) << 4; // Paper - inline ++ int k = (int) (i << 44 >> 44) << 4; // Paper - inline ++ int l = (int) (i << 22 >> 42) << 4; // Paper - inline + + for (int i1 = 0; i1 < 16; ++i1) { + for (int j1 = 0; j1 < 16; ++j1) { +@@ -194,7 +230,7 @@ public abstract class LightEngineStorage> e + NibbleArray nibblearray; + + while (longiterator.hasNext()) { +- i = (Long) longiterator.next(); ++ i = longiterator.nextLong(); // Paper + this.a(lightenginelayer, i); + NibbleArray nibblearray1 = (NibbleArray) this.i.remove(i); + +@@ -212,7 +248,7 @@ public abstract class LightEngineStorage> e + longiterator = this.p.iterator(); + + while (longiterator.hasNext()) { +- i = (Long) longiterator.next(); ++ i = longiterator.nextLong(); // Paper + this.l(i); + } + +@@ -223,12 +259,13 @@ public abstract class LightEngineStorage> e + Entry entry; + long j; + ++ NibbleArray test = null; // Paper + while (objectiterator.hasNext()) { + entry = (Entry) objectiterator.next(); + j = entry.getLongKey(); +- if (this.g(j)) { ++ if ((test = this.updating.getUpdatingOptimized(j)) != null) { // Paper - dont look up nibble twice + nibblearray = (NibbleArray) entry.getValue(); +- if (this.f.c(j) != nibblearray) { ++ if (test != nibblearray) { // Paper + this.a(lightenginelayer, j); + this.f.a(j, nibblearray); + this.g.add(j); +@@ -241,14 +278,14 @@ public abstract class LightEngineStorage> e + longiterator = this.i.keySet().iterator(); + + while (longiterator.hasNext()) { +- i = (Long) longiterator.next(); ++ i = longiterator.nextLong(); // Paper + this.b(lightenginelayer, i); + } + } else { + longiterator = this.n.iterator(); + + while (longiterator.hasNext()) { +- i = (Long) longiterator.next(); ++ i = longiterator.nextLong(); // Paper + this.b(lightenginelayer, i); + } + } +@@ -269,15 +306,20 @@ public abstract class LightEngineStorage> e + + private void b(LightEngineLayer lightenginelayer, long i) { + if (this.g(i)) { +- int j = SectionPosition.c(SectionPosition.b(i)); +- int k = SectionPosition.c(SectionPosition.c(i)); +- int l = SectionPosition.c(SectionPosition.d(i)); ++ // Paper start ++ int secX = (int) (i >> 42); ++ int secY = (int) (i << 44 >> 44); ++ int secZ = (int) (i << 22 >> 42); ++ int j = secX << 4; // baseX ++ int k = secY << 4; // baseY ++ int l = secZ << 4; // baseZ ++ // Paper end + EnumDirection[] aenumdirection = LightEngineStorage.k; + int i1 = aenumdirection.length; + + for (int j1 = 0; j1 < i1; ++j1) { + EnumDirection enumdirection = aenumdirection[j1]; +- long k1 = SectionPosition.a(i, enumdirection); ++ long k1 = SectionPosition.getAdjacentFromSectionPos(secX, secY, secZ, enumdirection); // Paper - avoid extra unpacking + + if (!this.i.containsKey(k1) && this.g(k1)) { + for (int l1 = 0; l1 < 16; ++l1) { +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java +index da78d4c4b5f8af4648ac82d63c21f6a2a5b73ecb..2ce5cf2e5b6e1dae463439fbfde519fa54677714 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java +@@ -7,13 +7,18 @@ import net.minecraft.world.level.chunk.NibbleArray; + + public abstract class LightEngineStorageArray> { + +- private final long[] b = new long[2]; +- private final NibbleArray[] c = new NibbleArray[2]; ++ // private final long[] b = new long[2]; // Paper - unused ++ private final NibbleArray[] c = new NibbleArray[]{NibbleArray.EMPTY_NIBBLE_ARRAY, NibbleArray.EMPTY_NIBBLE_ARRAY}; private final NibbleArray[] cache = c; // Paper - OBFHELPER + private boolean d; + protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data + protected final boolean isVisible; // Paper - avoid copying light data +- java.util.function.Function lookup; // Paper - faster branchless lookup + ++ // Paper start - faster lookups with less branching, use interface to avoid boxing instead of Function ++ public final NibbleArrayAccess lookup; ++ public interface NibbleArrayAccess { ++ NibbleArray apply(long id); ++ } ++ // Paper end + // Paper start - avoid copying light data + protected LightEngineStorageArray(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { + if (isVisible) { +@@ -21,12 +26,14 @@ public abstract class LightEngineStorageArray 0; --k) { +- this.b[k] = this.b[k - 1]; +- this.c[k] = this.c[k - 1]; +- } +- +- this.b[0] = i; +- this.c[0] = nibblearray; +- } +- ++ cache[1] = cache[0]; ++ cache[0] = nibblearray; + return nibblearray; + } + } ++ // Paper end ++ ++ @Nullable ++ public final NibbleArray c(final long i) { // Paper - final ++ // Paper start - optimize visible case or missed updating cases ++ if (this.d) { ++ // short circuit to optimized ++ return getUpdatingOptimized(i); ++ } ++ ++ return this.lookup.apply(i); ++ // Paper end ++ } + + @Nullable + public NibbleArray d(long i) { +@@ -82,13 +91,14 @@ public abstract class LightEngineStorageArray> 38); ++ int baseY = (int) ((i << 52) >> 52); ++ int baseZ = (int) ((i << 26) >> 38); ++ long j = (((long) (baseX >> 4) & 4194303L) << 42) | (((long) (baseY >> 4) & 1048575L)) | (((long) (baseZ >> 4) & 4194303L) << 20); ++ NibbleArray nibblearray = this.e_visible.lookup.apply(j); ++ return nibblearray == null ? 0 : nibblearray.a(baseX & 15, baseY & 15, baseZ & 15); ++ // Paper end + } + + public static final class a extends LightEngineStorageArray { +diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java +index 488403a6765598317faedc2d600ae82238e99e39..6d31b19c851081a37e6fcefdcdfcb7018fce6b26 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java +@@ -28,7 +28,12 @@ public class LightEngineStorageSky extends LightEngineStorage> 38); ++ int baseY = (int) ((i << 52) >> 52); ++ int baseZ = (int) ((i << 26) >> 38); ++ long j = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); ++ // Paper end + int k = SectionPosition.c(j); + synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data + LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e_visible; // Paper - avoid copying light data - must be after lock acquire +@@ -49,7 +54,7 @@ public class LightEngineStorageSky extends LightEngineStorage> 52) & 15, (int) baseZ & 15); // Paper - y changed above + } else { + return 15; + } +@@ -168,7 +173,7 @@ public class LightEngineStorageSky extends LightEngineStorage> 42) << 4; // Paper ++ int baseY = (int) (i << 44 >> 44) << 4; // Paper ++ int baseZ = (int) (i << 22 >> 42) << 4; // Paper + j = this.c(i); + if (j != 2 && !this.n.contains(i) && this.l.add(i)) { + int l; +@@ -203,10 +211,10 @@ public class LightEngineStorageSky extends LightEngineStorage> 42) << 4; // Paper ++ int baseY = (int) (i << 44 >> 44) << 4; // Paper ++ int baseZ = (int) (i << 22 >> 42) << 4; // Paper + if (this.l.remove(i) && this.g(i)) { + for (j = 0; j < 16; ++j) { + for (k = 0; k < 16; ++k) { +- long l3 = BlockPosition.a(SectionPosition.c(SectionPosition.b(i)) + j, SectionPosition.c(SectionPosition.c(i)) + 16 - 1, SectionPosition.c(SectionPosition.d(i)) + k); ++ long l3 = BlockPosition.a(baseX + j, baseY + 16 - 1, baseZ + k); // Paper + + lightenginelayer.a(Long.MAX_VALUE, l3, 15, false); + } diff --git a/patches/server-unmapped/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/patches/server-unmapped/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch new file mode 100644 index 0000000000..d2c3fa9257 --- /dev/null +++ b/patches/server-unmapped/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 18 Jun 2016 23:22:12 -0400 +Subject: [PATCH] Delay Chunk Unloads based on Player Movement + +When players are moving in the world, doing things such as building or exploring, +they will commonly go back and forth in a small area. This causes a ton of chunk load +and unload activity on the edge chunks of their view distance. + +A simple back and forth movement in 6 blocks could spam a chunk to thrash a +loading and unload cycle over and over again. + +This is very wasteful. This system introduces a delay of inactivity on a chunk +before it actually unloads, which will be handled by the ticket expiry process. + +This allows servers with smaller worlds who do less long distance exploring to stop +wasting cpu cycles on saving/unloading/reloading chunks repeatedly. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 6463d3e4837d032a35654a035f42b8a805e0e286..1655bca0502e7b871de4addaa163536d86547a02 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -637,4 +637,13 @@ public class PaperWorldConfig { + private void viewDistance() { + this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); + } ++ ++ public long delayChunkUnloadsBy; ++ private void delayChunkUnloadsBy() { ++ delayChunkUnloadsBy = PaperConfig.getSeconds(getString("delay-chunk-unloads-by", "10s")); ++ if (delayChunkUnloadsBy > 0) { ++ log("Delaying chunk unloads by " + delayChunkUnloadsBy + " seconds"); ++ delayChunkUnloadsBy *= 20; ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +index a3c44fdfca8290313b9b1117b984533183b583ad..3644e8b24b082e17752ef52934625416130aaa08 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java +@@ -185,6 +185,27 @@ public abstract class ChunkMapDistance { + boolean removed = false; // CraftBukkit + if (arraysetsorted.remove(ticket)) { + removed = true; // CraftBukkit ++ // Paper start - delay chunk unloads for player tickets ++ long delayChunkUnloadsBy = chunkMap.world.paperConfig.delayChunkUnloadsBy; ++ if (ticket.getTicketType() == TicketType.PLAYER && delayChunkUnloadsBy > 0) { ++ boolean hasPlayer = false; ++ for (Ticket ticket1 : arraysetsorted) { ++ if (ticket1.getTicketType() == TicketType.PLAYER) { ++ hasPlayer = true; ++ break; ++ } ++ } ++ PlayerChunk playerChunk = chunkMap.getUpdatingChunk(i); ++ if (!hasPlayer && playerChunk != null && playerChunk.isFullChunkReady()) { ++ Ticket delayUnload = new Ticket(TicketType.DELAY_UNLOAD, 33, i); ++ delayUnload.delayUnloadBy = delayChunkUnloadsBy; ++ delayUnload.setCurrentTick(this.currentTick); ++ arraysetsorted.remove(delayUnload); ++ // refresh ticket ++ arraysetsorted.add(delayUnload); ++ } ++ } ++ // Paper end + } + + if (arraysetsorted.isEmpty()) { +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index 90cbd12611b7b078f35f08f910453bcc02f6665b..6e5ae954c6eb40590bf8c83f592c22088d489be8 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -9,11 +9,13 @@ public final class Ticket implements Comparable> { + public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER + private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER + public int priority = 0; // Paper ++ public long delayUnloadBy; // Paper + + protected Ticket(TicketType tickettype, int i, T t0) { + this.a = tickettype; + this.b = i; + this.identifier = t0; ++ this.delayUnloadBy = tickettype.loadPeriod; // Paper + } + + public int compareTo(Ticket ticket) { +@@ -63,7 +65,7 @@ public final class Ticket implements Comparable> { + } + + protected boolean b(long i) { +- long j = this.a.b(); ++ long j = delayUnloadBy; // Paper + + return j != 0L && i - this.d > j; + } +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index f5d18834e0e2ee0e3bcf55810456766d2f134450..3c804c7b20a14ea6e510810e2be10c1cc89ff5c1 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -30,6 +30,7 @@ public class TicketType { + public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper + public static final TicketType PRIORITY = a("priority", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper + public static final TicketType URGENT = a("urgent", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper ++ public static final TicketType DELAY_UNLOAD = a("delay_unload", Long::compareTo, 300); // Paper + + public static TicketType a(String s, Comparator comparator) { + return new TicketType<>(s, comparator, 0L); diff --git a/patches/server-unmapped/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/patches/server-unmapped/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch new file mode 100644 index 0000000000..f91b76cc6e --- /dev/null +++ b/patches/server-unmapped/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch @@ -0,0 +1,129 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 9 Jun 2020 03:33:03 -0400 +Subject: [PATCH] Add Plugin Tickets to API Chunk Methods + +Like previous versions, plugins loading chunks kept them loaded until +they garbage collected to avoid constant spamming of chunk loads + +This adds tickets to a few more places so that they can be unloaded. + +Additionally, this drops their ticket level to BORDER so they wont be ticking +so they will just sit inactive instead. + +Using .loadChunk to keep a chunk ticking was a horrible idea for upstream +when we have TWO methods that are able to do that already in the API. + +Also reduce their collection count down to a maximum of 1 second. Barely +anyone knows what chunk-gc is in bukkit.yml as its less relevant now, and +since this wasn't spigot behavior, this is safe to mostly ignore (unless someone +wants it to collect even faster, they can restore that setting back to 1 instead of 20+) + +Not adding it to .getType() though to keep behavior consistent with vanilla for performance reasons. + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 5f03ec59588fd975ca2fb62961b10212d8a9cbec..a295ab6a7ec79775224381e94e288069f5d311fe 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -343,7 +343,7 @@ public final class CraftServer implements Server { + ambientSpawn = configuration.getInt("spawn-limits.ambient"); + console.autosavePeriod = configuration.getInt("ticks-per.autosave"); + warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); +- TicketType.PLUGIN.loadPeriod = configuration.getInt("chunk-gc.period-in-ticks"); ++ TicketType.PLUGIN.loadPeriod = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + minimumAPI = configuration.getString("settings.minimum-api"); + loadIcon(); + } +@@ -833,7 +833,7 @@ public final class CraftServer implements Server { + waterAmbientSpawn = configuration.getInt("spawn-limits.water-ambient"); + ambientSpawn = configuration.getInt("spawn-limits.ambient"); + warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); +- TicketType.PLUGIN.loadPeriod = configuration.getInt("chunk-gc.period-in-ticks"); ++ TicketType.PLUGIN.loadPeriod = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + minimumAPI = configuration.getString("settings.minimum-api"); + printSaveWarning = false; + console.autosavePeriod = configuration.getInt("ticks-per.autosave"); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 6034ef65ee6030948a5b76fa493addb44188ef62..80cd8ce4e70dbb740439ac530a7bc70a7a54cb85 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffect; + import net.minecraft.network.protocol.game.PacketPlayOutUpdateTime; + import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; + import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ChunkMapDistance; + import net.minecraft.server.level.PlayerChunk; + import net.minecraft.server.level.PlayerChunkMap; +@@ -407,8 +408,21 @@ public class CraftWorld implements World { + + @Override + public Chunk getChunkAt(int x, int z) { +- return this.world.getChunkProvider().getChunkAt(x, z, true).bukkitChunk; ++ // Paper start - add ticket to hold chunk for a little while longer if plugin accesses it ++ net.minecraft.world.level.chunk.Chunk chunk = world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); ++ if (chunk == null) { ++ addTicket(x, z); ++ chunk = this.world.getChunkProvider().getChunkAt(x, z, true); ++ } ++ return chunk.bukkitChunk; ++ // Paper end ++ } ++ ++ // Paper start ++ private void addTicket(int x, int z) { ++ MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkProvider().addTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 0, Unit.INSTANCE)); // Paper + } ++ // Paper end + + @Override + public Chunk getChunkAt(Block block) { +@@ -483,7 +497,7 @@ public class CraftWorld implements World { + public boolean unloadChunkRequest(int x, int z) { + org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot + if (isChunkLoaded(x, z)) { +- world.getChunkProvider().removeTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE); ++ world.getChunkProvider().removeTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 0, Unit.INSTANCE); // Paper + } + + return true; +@@ -560,9 +574,12 @@ public class CraftWorld implements World { + org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot + // Paper start - Optimize this method + ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); ++ IChunkAccess immediate = world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); // Paper ++ if (immediate != null) return true; // Paper + + if (!generate) { +- IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); ++ ++ //IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); // Paper + if (immediate == null) { + immediate = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); + } +@@ -570,7 +587,7 @@ public class CraftWorld implements World { + if (!(immediate instanceof ProtoChunkExtension) && !(immediate instanceof net.minecraft.world.level.chunk.Chunk)) { + return false; // not full status + } +- world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper + world.getChunkAt(x, z); // make sure we're at ticket level 32 or lower + return true; + } +@@ -597,7 +614,7 @@ public class CraftWorld implements World { + // we do this so we do not re-read the chunk data on disk + } + +- world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper + world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); + return true; + // Paper end +@@ -2547,6 +2564,7 @@ public class CraftWorld implements World { + } + return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { + net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); ++ if (chunk != null) addTicket(x, z); // Paper + return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + }, net.minecraft.server.MinecraftServer.getServer()); + } diff --git a/patches/server-unmapped/0494-Fix-missing-chunks-due-to-integer-overflow.patch b/patches/server-unmapped/0494-Fix-missing-chunks-due-to-integer-overflow.patch new file mode 100644 index 0000000000..15f03e8c36 --- /dev/null +++ b/patches/server-unmapped/0494-Fix-missing-chunks-due-to-integer-overflow.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: David Slovikosky +Date: Tue, 9 Jun 2020 00:10:03 -0700 +Subject: [PATCH] Fix missing chunks due to integer overflow + +This patch fixes a bug in the WorldChunkManagerTheEnd class where the distance +from 0,0 squared overflows the maximum size of an integer. The overflow leads +to hard chunk borders around 370,000 blocks from 0,0. After this cutoff there +is a few hundred thousand block gap before end land resuming to generate at +530,000 blocks from spawn. This is due to the integer flipping back and forth. + +The fix for the issue is quite simple, casting chunk coordinates to longs +allows the distance calculation to avoid overflow and work as intended. + +diff --git a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java +index 1d46e2c4e06cfe32eac06223e1966ce39c41685e..1077972d694d604c3ec97d333d34a9ab81819c33 100644 +--- a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java ++++ b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java +@@ -75,7 +75,9 @@ public class WorldChunkManagerTheEnd extends WorldChunkManager { + int l = j / 2; + int i1 = i % 2; + int j1 = j % 2; +- float f = 100.0F - MathHelper.c((float) (i * i + j * j)) * 8.0F; ++ // Paper start - cast ints to long to avoid integer overflow ++ float f = 100.0F - MathHelper.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; ++ // Paper end + + f = MathHelper.a(f, -100.0F, 80.0F); + diff --git a/patches/server-unmapped/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/patches/server-unmapped/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch new file mode 100644 index 0000000000..423af0ebf9 --- /dev/null +++ b/patches/server-unmapped/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ossi +Date: Fri, 12 Jun 2020 01:38:06 +0300 +Subject: [PATCH] Fix CraftScheduler#runTaskTimerAsynchronously(Plugin, + Consumer, long, long) scheduling a non-repeating task instead of + a repeating one. + + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index ca90237a53c9a026919d28adaedf483ca3c7c2a8..13e461ffb2ee2e7d0440c0f60809ea99629b843c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -184,7 +184,7 @@ public class CraftScheduler implements BukkitScheduler { + + @Override + public void runTaskTimerAsynchronously(Plugin plugin, Consumer task, long delay, long period) throws IllegalArgumentException { +- runTaskTimerAsynchronously(plugin, (Object) task, delay, CraftTask.NO_REPEATING); ++ runTaskTimerAsynchronously(plugin, (Object) task, delay, period); + } + + @Override diff --git a/patches/server-unmapped/0496-Fix-piston-physics-inconsistency-MC-188840.patch b/patches/server-unmapped/0496-Fix-piston-physics-inconsistency-MC-188840.patch new file mode 100644 index 0000000000..86e65e4b6f --- /dev/null +++ b/patches/server-unmapped/0496-Fix-piston-physics-inconsistency-MC-188840.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Thu, 11 Jun 2020 17:29:42 -0700 +Subject: [PATCH] Fix piston physics inconsistency - MC-188840 + +Pistons invoke physics when they move blocks. The physics can cause +tnt blocks to ignite. However, pistons (when storing the blocks they "moved") +don't actually go back to the world state sometimes to check if something +like that happened. As a result they end up moving the tnt like it was +never ignited. This resulted in the ability to create machines +that can duplicate tnt, called "world eaters". +This patch makes the piston logic retrieve the block state from the world +prevent this from occuring. + +This patch also sets the moved pos to air immediately after creating +the moving piston TE. This prevents the block from being updated from +other physics calls by the piston. + +Tested against the following tnt duper design: +https://www.youtube.com/watch?v=mS7xxNGhjxs + +This patch also affects every type of machine that utilises +this mechanic. For example, dead coral is removed by a physics +update when being moved while it is attached to slimeblocks. + +Standard piston machines that don't destroy or modify the +blocks they move by physics updates should be entirely +unaffected. + +This patch fixes https://bugs.mojang.com/browse/MC-188840 + +This patch also fixes rail duping and carpet duping. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 7f140333c2e62012fa572c1a061d84432426997f..b67ba8f75e4a3358d7c2462918b85b0bf9b5a922 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -434,4 +434,10 @@ public class PaperConfig { + consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); + } + ++ public static boolean allowPistonDuplication; ++ private static void allowPistonDuplication() { ++ config.set("settings.unsupported-settings.allow-piston-duplication-readme", "This setting controls if player should be able to use TNT duplication, but this also allows duplicating carpet, rails and potentially other items"); ++ allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); ++ set("settings.unsupported-settings.allow-tnt-duplication", null); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java +index e062fd288098127fae22a55562e0207ceaf50163..8aa51fb207820a7629d50b80ea821ec6cccf8b54 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java +@@ -399,12 +399,24 @@ public class BlockPiston extends BlockDirectional { + } + + for (k = list.size() - 1; k >= 0; --k) { +- blockposition3 = (BlockPosition) list.get(k); +- iblockdata1 = world.getType(blockposition3); ++ // Paper start - fix a variety of piston desync dupes ++ boolean allowDesync = com.destroystokyo.paper.PaperConfig.allowPistonDuplication; ++ BlockPosition oldPos = blockposition3 = (BlockPosition) list.get(k); ++ iblockdata1 = allowDesync ? world.getType(oldPos) : null; ++ // Paper end - fix a variety of piston desync dupes + blockposition3 = blockposition3.shift(enumdirection1); + map.remove(blockposition3); + world.setTypeAndData(blockposition3, (IBlockData) Blocks.MOVING_PISTON.getBlockData().set(BlockPiston.FACING, enumdirection), 68); +- world.setTileEntity(blockposition3, BlockPistonMoving.a((IBlockData) list1.get(k), enumdirection, flag, false)); ++ // Paper start - fix a variety of piston desync dupes ++ if (!allowDesync) { ++ iblockdata1 = world.getType(oldPos); ++ map.replace(oldPos, iblockdata1); ++ } ++ world.setTileEntity(blockposition3, BlockPistonMoving.a(allowDesync ? list1.get(k) : iblockdata1, enumdirection, flag, false)); ++ if (!allowDesync) { ++ world.setTypeAndData(oldPos, Blocks.AIR.getBlockData(), 2 | 4 | 16 | 1024); // set air to prevent later physics updates from seeing this block ++ } ++ // Paper end - fix a variety of piston desync dupes + aiblockdata[j++] = iblockdata1; + } + +diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java +index 8d13e60f40e1b760e9e69969dc3f37bc6c70dbe9..e70c3a8c9075b6c0bc73e6488d784dfe3b86e58d 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java +@@ -279,7 +279,7 @@ public class TileEntityPiston extends TileEntity implements ITickable { + IBlockData iblockdata = Block.b(this.a, (GeneratorAccess) this.world, this.position); + + if (iblockdata.isAir()) { +- this.world.setTypeAndData(this.position, this.a, 84); ++ this.world.setTypeAndData(this.position, this.a, com.destroystokyo.paper.PaperConfig.allowPistonDuplication ? 84 : (84 | 2)); // Paper - force notify (flag 2), it's possible the set type by the piston block (which doesn't notify) set this block to air + Block.a(this.a, iblockdata, this.world, this.position, 3); + } else { + if (iblockdata.b(BlockProperties.C) && (Boolean) iblockdata.get(BlockProperties.C)) { diff --git a/patches/server-unmapped/0497-Fix-sand-duping.patch b/patches/server-unmapped/0497-Fix-sand-duping.patch new file mode 100644 index 0000000000..e3e2417078 --- /dev/null +++ b/patches/server-unmapped/0497-Fix-sand-duping.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 12 Jun 2020 13:33:19 -0700 +Subject: [PATCH] Fix sand duping + +If the falling block dies during teleportation (entity#move), then we need +to detect that by placing a check after the move. + +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java +index 411e3915c0aa00249aacb6658ed04309665d2fb4..62d8b53c024888aa43b8fddf8a475dfb8284a4cc 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java +@@ -103,6 +103,11 @@ public class EntityFallingBlock extends Entity { + + @Override + public void tick() { ++ // Paper start - fix sand duping ++ if (this.dead) { ++ return; ++ } ++ // Paper end - fix sand duping + if (this.block.isAir()) { + this.die(); + } else { +@@ -125,6 +130,12 @@ public class EntityFallingBlock extends Entity { + + this.move(EnumMoveType.SELF, this.getMot()); + ++ // Paper start - fix sand duping ++ if (this.dead) { ++ return; ++ } ++ // Paper end - fix sand duping ++ + // Paper start - Configurable EntityFallingBlock height nerf + if (this.world.paperConfig.fallingBlockHeightNerf != 0 && this.locY() > this.world.paperConfig.fallingBlockHeightNerf) { + if (this.dropItem && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) { diff --git a/patches/server-unmapped/0498-Prevent-position-desync-in-playerconnection-causing-.patch b/patches/server-unmapped/0498-Prevent-position-desync-in-playerconnection-causing-.patch new file mode 100644 index 0000000000..9da724328c --- /dev/null +++ b/patches/server-unmapped/0498-Prevent-position-desync-in-playerconnection-causing-.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 12 Jun 2020 16:51:39 -0700 +Subject: [PATCH] Prevent position desync in playerconnection causing tp + exploit + +Caused the server to revert to the player's overworld coordinates +after teleporting into the end. + +Sidenote: The underlying issue is that the move call can teleport +entities and do other things like kill the entity. In the future, +to fix all exploits derieved from this usually unexpected +behaviour, we need to move all of this dangerous logic outside +of the move call and into an appropriate place in the tick method. + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 40fefdb9da9c4fd3ef3e3bb6276de215dd5265f9..3648ea649158e4f7d385eaccf08a85584e6aa869 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1326,6 +1326,11 @@ public class PlayerConnection implements PacketListenerPlayIn { + + this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9)); + this.player.setOnGround(packetplayinflying.b()); // CraftBukkit - SPIGOT-5810, SPIGOT-5835: reset by this.player.move ++ // Paper start - prevent position desync ++ if (this.teleportPos != null) { ++ return; // ... thanks Mojang for letting move calls teleport across dimensions. ++ } ++ // Paper end - prevent position desync + double d12 = d8; + + d7 = d4 - this.player.locX(); diff --git a/patches/server-unmapped/0499-Fix-enderdragon-exp-dupe.patch b/patches/server-unmapped/0499-Fix-enderdragon-exp-dupe.patch new file mode 100644 index 0000000000..6217196c77 --- /dev/null +++ b/patches/server-unmapped/0499-Fix-enderdragon-exp-dupe.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 12 Jun 2020 22:25:11 -0700 +Subject: [PATCH] Fix enderdragon exp dupe + +Properly track death stage when unloading/loading in the +dragon + +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +index 5168a40eb53565bb3028efe559601acf72bddae5..c296fcf80c2f3f210fa020416973ec8d5db541ba 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +@@ -879,6 +879,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + public void saveData(NBTTagCompound nbttagcompound) { + super.saveData(nbttagcompound); + nbttagcompound.setInt("DragonPhase", this.bG.a().getControllerPhase().b()); ++ nbttagcompound.setInt("Paper.DeathTick", this.deathAnimationTicks); // Paper + } + + @Override +@@ -887,6 +888,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { + if (nbttagcompound.hasKey("DragonPhase")) { + this.bG.setControllerPhase(DragonControllerPhase.getById(nbttagcompound.getInt("DragonPhase"))); + } ++ this.deathAnimationTicks = nbttagcompound.getInt("Paper.DeathTick"); // Paper + + } + diff --git a/patches/server-unmapped/0500-Inventory-getHolder-method-without-block-snapshot.patch b/patches/server-unmapped/0500-Inventory-getHolder-method-without-block-snapshot.patch new file mode 100644 index 0000000000..eeb9b62352 --- /dev/null +++ b/patches/server-unmapped/0500-Inventory-getHolder-method-without-block-snapshot.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Wed, 10 Jun 2020 23:55:15 +0100 +Subject: [PATCH] Inventory getHolder method without block snapshot + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +index 45634fded9916dca35a246921efb87964c860339..c3fa97ac34e1fc61ae02f224f8afe5a0b486fb4d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +@@ -9,6 +9,7 @@ import net.minecraft.world.inventory.InventoryCrafting; + import net.minecraft.world.inventory.InventoryEnderChest; + import net.minecraft.world.inventory.InventoryMerchant; + import net.minecraft.world.level.block.entity.IHopper; ++import net.minecraft.world.level.block.entity.TileEntity; + import net.minecraft.world.level.block.entity.TileEntityBarrel; + import net.minecraft.world.level.block.entity.TileEntityBlastFurnace; + import net.minecraft.world.level.block.entity.TileEntityBrewingStand; +@@ -526,6 +527,13 @@ public class CraftInventory implements Inventory { + return inventory.getOwner(); + } + ++ // Paper start - getHolder without snapshot ++ @Override ++ public InventoryHolder getHolder(boolean useSnapshot) { ++ return inventory instanceof TileEntity ? ((TileEntity) inventory).getOwner(useSnapshot) : getHolder(); ++ } ++ // Paper end ++ + @Override + public int getMaxStackSize() { + return inventory.getMaxStackSize(); +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java +index 47029af761e26453090980b9a231fd53d4238cc4..d22abb4259dfcfd3ec0e0516f87fc838a81353ce 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java +@@ -64,6 +64,13 @@ public class CraftInventoryDoubleChest extends CraftInventory implements DoubleC + return new DoubleChest(this); + } + ++ // Paper start - getHolder without snapshot ++ @Override ++ public DoubleChest getHolder(boolean useSnapshot) { ++ return getHolder(); ++ } ++ // Paper end ++ + @Override + public Location getLocation() { + return getLeftSide().getLocation().add(getRightSide().getLocation()).multiply(0.5); diff --git a/patches/server-unmapped/0501-Expose-Arrow-getItemStack.patch b/patches/server-unmapped/0501-Expose-Arrow-getItemStack.patch new file mode 100644 index 0000000000..07e4be3370 --- /dev/null +++ b/patches/server-unmapped/0501-Expose-Arrow-getItemStack.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nesaak <52047222+Nesaak@users.noreply.github.com> +Date: Sat, 23 May 2020 10:31:11 -0400 +Subject: [PATCH] Expose Arrow getItemStack + + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +index c325c9fe680d9033b20909bcd6100ecc4b0195f6..ce754e0da047050daa08e5e0564fa399d334c04b 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +@@ -558,6 +558,7 @@ public abstract class EntityArrow extends IProjectile { + } + } + ++ public final ItemStack getOriginalItemStack() { return getItemStack(); } // Paper - OBFHELPER - exists purely due to overrides all as protected and dont want to change them all + protected abstract ItemStack getItemStack(); + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +index ea33a36dfa6f304946f5b998eb536678a9b2f98c..2ab41a24a22e736753276b95fa0d060017cca0bc 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +@@ -103,6 +103,13 @@ public class CraftArrow extends AbstractProjectile implements AbstractArrow { + getHandle().fromPlayer = EntityArrow.PickupStatus.a(status.ordinal()); + } + ++ // Paper start ++ @Override ++ public org.bukkit.craftbukkit.inventory.CraftItemStack getItemStack() { ++ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(getHandle().getOriginalItemStack()); ++ } ++ //Paper end ++ + @Override + public void setTicksLived(int value) { + super.setTicksLived(value); diff --git a/patches/server-unmapped/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/server-unmapped/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch new file mode 100644 index 0000000000..16854ab4a9 --- /dev/null +++ b/patches/server-unmapped/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Fri, 5 Jun 2020 18:24:06 -0400 +Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 3648ea649158e4f7d385eaccf08a85584e6aa869..4c9ac550fa5556525c66bc02c8c80d375fce0fe4 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2772,9 +2772,15 @@ public class PlayerConnection implements PacketListenerPlayIn { + PlayerConnectionUtils.ensureMainThread(packetplayinautorecipe, this, this.player.getWorldServer()); + this.player.resetIdleTimer(); + if (!this.player.isSpectator() && this.player.activeContainer.windowId == packetplayinautorecipe.b() && this.player.activeContainer.c(this.player) && this.player.activeContainer instanceof ContainerRecipeBook) { +- this.minecraftServer.getCraftingManager().getRecipe(packetplayinautorecipe.c()).ifPresent((irecipe) -> { +- ((ContainerRecipeBook) this.player.activeContainer).a(packetplayinautorecipe.d(), irecipe, this.player); +- }); ++ // Paper start - fire event for clicking recipes in the recipe book ++ com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent event = new com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent( ++ player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(packetplayinautorecipe.c()), packetplayinautorecipe.d()); ++ if (event.callEvent()) { ++ this.minecraftServer.getCraftingManager().getRecipe(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getRecipe())).ifPresent((irecipe) -> { ++ ((ContainerRecipeBook) this.player.activeContainer).a(event.isMakeAll(), irecipe, this.player); ++ }); ++ } ++ // Paper end + } + } + diff --git a/patches/server-unmapped/0503-Hide-sync-chunk-writes-behind-flag.patch b/patches/server-unmapped/0503-Hide-sync-chunk-writes-behind-flag.patch new file mode 100644 index 0000000000..9b9dd4ede4 --- /dev/null +++ b/patches/server-unmapped/0503-Hide-sync-chunk-writes-behind-flag.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 26 Jun 2020 22:35:08 -0700 +Subject: [PATCH] Hide sync chunk writes behind flag + +Syncing writes on each write call has terrible performance +on harddrives. + +-DPaper.enable-sync-chunk-writes=true to enable + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +index b7cf02301c02ed0a6b696384e656426762ae2105..1fab9b9c7d41a0d2a551096c2c15f741a887fa2d 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +@@ -111,7 +111,7 @@ public class DedicatedServerProperties extends PropertyManager { + return MathHelper.clamp(integer, 1, 29999984); + }, 29999984); +- this.syncChunkWrites = this.getBoolean("sync-chunk-writes", true); ++ this.syncChunkWrites = this.getBoolean("sync-chunk-writes", true) && Boolean.getBoolean("Paper.enable-sync-chunk-writes"); // Paper - hide behind flag + this.enableJmxMonitoring = this.getBoolean("enable-jmx-monitoring", false); + this.enableStatus = this.getBoolean("enable-status", true); + this.entityBroadcastRangePercentage = this.a("entity-broadcast-range-percentage", (integer) -> { diff --git a/patches/server-unmapped/0504-Limit-lightning-strike-effect-distance.patch b/patches/server-unmapped/0504-Limit-lightning-strike-effect-distance.patch new file mode 100644 index 0000000000..779333c56d --- /dev/null +++ b/patches/server-unmapped/0504-Limit-lightning-strike-effect-distance.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Fri, 14 Sep 2018 17:42:08 +0200 +Subject: [PATCH] Limit lightning strike effect distance + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1655bca0502e7b871de4addaa163536d86547a02..978062774c1db286bfb9b0ffdef19d880b1f249b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -646,4 +646,26 @@ public class PaperWorldConfig { + delayChunkUnloadsBy *= 20; + } + } ++ ++ public double sqrMaxThunderDistance; ++ public double sqrMaxLightningImpactSoundDistance; ++ public double maxLightningFlashDistance; ++ private void lightningStrikeDistanceLimit() { ++ sqrMaxThunderDistance = getInt("lightning-strike-distance-limit.sound", -1); ++ if (sqrMaxThunderDistance > 0) { ++ sqrMaxThunderDistance *= sqrMaxThunderDistance; ++ } ++ ++ sqrMaxLightningImpactSoundDistance = getInt("lightning-strike-distance-limit.impact-sound", -1); ++ if (sqrMaxLightningImpactSoundDistance < 0) { ++ sqrMaxLightningImpactSoundDistance = 32 * 32; //Vanilla value ++ } else { ++ sqrMaxLightningImpactSoundDistance *= sqrMaxLightningImpactSoundDistance; ++ } ++ ++ maxLightningFlashDistance = getInt("lightning-strike-distance-limit.flash", -1); ++ if (maxLightningFlashDistance < 0) { ++ maxLightningFlashDistance = 512; // Vanilla value ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityLightning.java b/src/main/java/net/minecraft/world/entity/EntityLightning.java +index 8946fcd93bd785a8c21683b932aa954fbf15d566..834ced9d9b385c8f1d66355244313d62a97d9c98 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLightning.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLightning.java +@@ -76,6 +76,17 @@ public class EntityLightning extends Entity { + double deltaX = this.locX() - player.locX(); + double deltaZ = this.locZ() - player.locZ(); + double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; ++ // Paper start - Limit lightning strike effect distance ++ if (distanceSquared <= this.world.paperConfig.sqrMaxLightningImpactSoundDistance) { ++ player.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, ++ SoundCategory.WEATHER, this.locX(), this.locY(), this.locZ(), 2.0f, 0.5F + this.random.nextFloat() * 0.2F)); ++ } ++ ++ if (world.paperConfig.sqrMaxThunderDistance != -1 && distanceSquared >= world.paperConfig.sqrMaxThunderDistance) { ++ continue; ++ } ++ ++ // Paper end + if (distanceSquared > viewDistance * viewDistance) { + double deltaLength = Math.sqrt(distanceSquared); + double relativeX = player.locX() + (deltaX / deltaLength) * viewDistance; +@@ -86,7 +97,7 @@ public class EntityLightning extends Entity { + } + } + // CraftBukkit end +- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); ++// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); // Paper - Limit lightning strike effect distance (the packet is now sent from inside the loop) + } + + --this.lifeTicks; diff --git a/patches/server-unmapped/0505-Add-permission-for-command-blocks.patch b/patches/server-unmapped/0505-Add-permission-for-command-blocks.patch new file mode 100644 index 0000000000..f2a2eb6550 --- /dev/null +++ b/patches/server-unmapped/0505-Add-permission-for-command-blocks.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 16 May 2020 10:05:30 +0200 +Subject: [PATCH] Add permission for command blocks + + +diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +index fbd8a6985a261396789c87e4b687140bd49cea0d..984209e4f66ad23d85d2c5d02318caab1aff7324 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java ++++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +@@ -387,7 +387,7 @@ public class PlayerInteractManager { + TileEntity tileentity = this.world.getTileEntity(blockposition); + Block block = iblockdata.getBlock(); + +- if ((block instanceof BlockCommand || block instanceof BlockStructure || block instanceof BlockJigsaw) && !this.player.isCreativeAndOp()) { ++ if ((block instanceof BlockCommand || block instanceof BlockStructure || block instanceof BlockJigsaw) && !this.player.isCreativeAndOp() && !(block instanceof BlockCommand && (this.player.isCreative() && this.player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission + this.world.notify(blockposition, iblockdata, iblockdata, 3); + return false; + } else if (this.player.a((World) this.world, blockposition, this.gamemode)) { +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 4c9ac550fa5556525c66bc02c8c80d375fce0fe4..168fcf3570e5af68d99944dae9a7d7275fb93ff1 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -798,7 +798,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + PlayerConnectionUtils.ensureMainThread(packetplayinsetcommandblock, this, this.player.getWorldServer()); + if (!this.minecraftServer.getEnableCommandBlock()) { + this.player.sendMessage(new ChatMessage("advMode.notEnabled"), SystemUtils.b); +- } else if (!this.player.isCreativeAndOp()) { ++ } else if (!this.player.isCreativeAndOp() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission + this.player.sendMessage(new ChatMessage("advMode.notAllowed"), SystemUtils.b); + } else { + CommandBlockListenerAbstract commandblocklistenerabstract = null; +@@ -861,7 +861,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + PlayerConnectionUtils.ensureMainThread(packetplayinsetcommandminecart, this, this.player.getWorldServer()); + if (!this.minecraftServer.getEnableCommandBlock()) { + this.player.sendMessage(new ChatMessage("advMode.notEnabled"), SystemUtils.b); +- } else if (!this.player.isCreativeAndOp()) { ++ } else if (!this.player.isCreativeAndOp() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission + this.player.sendMessage(new ChatMessage("advMode.notAllowed"), SystemUtils.b); + } else { + CommandBlockListenerAbstract commandblocklistenerabstract = packetplayinsetcommandminecart.a(this.player.world); +diff --git a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java +index 3fcdff3649c725580456dfc965d6c83bd5afe3da..85e7957103d2b2e16e4d3a3ea0bd7de4935f61cd 100644 +--- a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java ++++ b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java +@@ -192,7 +192,7 @@ public abstract class CommandBlockListenerAbstract implements ICommandListener { + } + + public EnumInteractionResult a(EntityHuman entityhuman) { +- if (!entityhuman.isCreativeAndOp()) { ++ if (!entityhuman.isCreativeAndOp() && !entityhuman.isCreative() && !entityhuman.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission + return EnumInteractionResult.PASS; + } else { + if (entityhuman.getWorld().isClientSide) { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockCommand.java b/src/main/java/net/minecraft/world/level/block/BlockCommand.java +index ad50f86d11ff22f055ca9f26cd02a84e75c7d8c8..f7d22282a59277375d146e9459f9f43962dd7d09 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockCommand.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockCommand.java +@@ -128,7 +128,7 @@ public class BlockCommand extends BlockTileEntity { + public EnumInteractionResult interact(IBlockData iblockdata, World world, BlockPosition blockposition, EntityHuman entityhuman, EnumHand enumhand, MovingObjectPositionBlock movingobjectpositionblock) { + TileEntity tileentity = world.getTileEntity(blockposition); + +- if (tileentity instanceof TileEntityCommand && entityhuman.isCreativeAndOp()) { ++ if (tileentity instanceof TileEntityCommand && (entityhuman.isCreativeAndOp() || (entityhuman.isCreative() && entityhuman.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission + entityhuman.a((TileEntityCommand) tileentity); + return EnumInteractionResult.a(world.isClientSide); + } else { +diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java +index 525ebf961e5da0687183a5e2ead23ed92cbd9d79..a4a809f302c5ff9c76cde5fc0add2ceec1bdf9b5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java +@@ -16,6 +16,7 @@ public final class CraftDefaultPermissions { + DefaultPermissions.registerPermission(ROOT + ".nbt.copy", "Gives the user the ability to copy NBT in creative", org.bukkit.permissions.PermissionDefault.TRUE, parent); + DefaultPermissions.registerPermission(ROOT + ".debugstick", "Gives the user the ability to use the debug stick in creative", org.bukkit.permissions.PermissionDefault.OP, parent); + DefaultPermissions.registerPermission(ROOT + ".debugstick.always", "Gives the user the ability to use the debug stick in all game modes", org.bukkit.permissions.PermissionDefault.FALSE, parent); ++ DefaultPermissions.registerPermission(ROOT + ".commandblock", "Gives the user the ability to use command blocks.", org.bukkit.permissions.PermissionDefault.OP, parent); // Paper + // Spigot end + parent.recalculatePermissibles(); + } diff --git a/patches/server-unmapped/0506-Ensure-Entity-AABB-s-are-never-invalid.patch b/patches/server-unmapped/0506-Ensure-Entity-AABB-s-are-never-invalid.patch new file mode 100644 index 0000000000..b0248c30f4 --- /dev/null +++ b/patches/server-unmapped/0506-Ensure-Entity-AABB-s-are-never-invalid.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 May 2020 22:12:46 -0400 +Subject: [PATCH] Ensure Entity AABB's are never invalid + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index b244f5d204938452ea19335947830de47336bbd4..8151403b2a7f5f8441c6810d1bd2bf3df4cefa80 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -66,6 +66,7 @@ import net.minecraft.world.INamableTileEntity; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.animal.EntityAnimal; + import net.minecraft.world.entity.animal.EntityFish; ++import net.minecraft.world.entity.decoration.EntityHanging; + import net.minecraft.world.entity.item.EntityItem; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.vehicle.EntityBoat; +@@ -479,7 +480,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + public void setPosition(double d0, double d1, double d2) { + this.setPositionRaw(d0, d1, d2); +- this.a(this.size.a(d0, d1, d2)); ++ //this.a(this.size.a(d0, d1, d2)); // Paper - move into setPositionRaw + if (valid) ((WorldServer) world).chunkCheck(this); // CraftBukkit + } + +@@ -2999,6 +3000,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return new AxisAlignedBB(vec3d, vec3d1); + } + ++ public final void setBoundingBox(AxisAlignedBB axisalignedbb) { a(axisalignedbb); } // Paper - OBFHELPER + public void a(AxisAlignedBB axisalignedbb) { + // CraftBukkit start - block invalid bounding boxes + double minX = axisalignedbb.minX, +@@ -3437,6 +3439,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public void setPositionRaw(double d0, double d1, double d2) { ++ // Paper start - never allow AABB to become desynced from position ++ // hanging has its own special logic ++ if (!(this instanceof EntityHanging) && (this.loc.x != d0 || this.loc.y != d1 || this.loc.z != d2)) { ++ this.setBoundingBox(this.size.a(d0, d1, d2)); ++ } ++ // Paper end + if (this.loc.x != d0 || this.loc.y != d1 || this.loc.z != d2) { + this.loc = new Vec3D(d0, d1, d2); + int i = MathHelper.floor(d0); diff --git a/patches/server-unmapped/0507-Optimize-WorldBorder-collision-checks-and-air.patch b/patches/server-unmapped/0507-Optimize-WorldBorder-collision-checks-and-air.patch new file mode 100644 index 0000000000..919498d8ec --- /dev/null +++ b/patches/server-unmapped/0507-Optimize-WorldBorder-collision-checks-and-air.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 10 May 2020 22:49:05 -0400 +Subject: [PATCH] Optimize WorldBorder collision checks and air + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 8151403b2a7f5f8441c6810d1bd2bf3df4cefa80..a6df453acadccc6500cec0ac816ec4d1e35adad7 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -909,7 +909,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + AxisAlignedBB axisalignedbb = this.getBoundingBox(); + VoxelShapeCollision voxelshapecollision = VoxelShapeCollision.a(this); + VoxelShape voxelshape = this.world.getWorldBorder().c(); +- Stream stream = VoxelShapes.c(voxelshape, VoxelShapes.a(axisalignedbb.shrink(1.0E-7D)), OperatorBoolean.AND) ? Stream.empty() : Stream.of(voxelshape); ++ Stream stream = !this.world.getWorldBorder().isInBounds(axisalignedbb) ? Stream.empty() : Stream.of(voxelshape); // Paper + Stream stream1 = this.world.c(this, axisalignedbb.b(vec3d), (entity) -> { + return true; + }); +diff --git a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java +index d0cc8677f2be422722160fee9b71894b5ddd3186..03584572fa5bf0d96fc4cecece573547f9c94cea 100644 +--- a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java ++++ b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java +@@ -143,10 +143,10 @@ public class VoxelShapeSpliterator extends AbstractSpliterator { + AxisAlignedBB axisalignedbb = this.a.getBoundingBox(); + + if (!a(worldborder, axisalignedbb)) { +- VoxelShape voxelshape = worldborder.c(); +- +- if (!b(voxelshape, axisalignedbb) && a(voxelshape, axisalignedbb)) { +- consumer.accept(voxelshape); ++ // Paper start ++ if (worldborder.isInBounds(axisalignedbb.shrink(1.0E-7D)) && !worldborder.isInBounds(axisalignedbb.grow(1.0E-7D))) { ++ consumer.accept(worldborder.asVoxelShape()); ++ // Paper end + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index 50e2085766caabec1125ca24a2117549efd1a354..bedaa9dd6390e81df5872c2dd6e202a038367bf6 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -52,6 +52,7 @@ public class WorldBorder { + return (double) chunkcoordintpair.f() > this.e() && (double) chunkcoordintpair.d() < this.g() && (double) chunkcoordintpair.g() > this.f() && (double) chunkcoordintpair.e() < this.h(); + } + ++ public final boolean isInBounds(AxisAlignedBB aabb) { return this.a(aabb); } // Paper - OBFHELPER + public boolean a(AxisAlignedBB axisalignedbb) { + return axisalignedbb.maxX > this.e() && axisalignedbb.minX < this.g() && axisalignedbb.maxZ > this.f() && axisalignedbb.minZ < this.h(); + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +index 2d7405d1fa7c8f378bebe86f5d0de57a129ed92d..858d4689e618c72250447adb61e0bcc3c156f8f3 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +@@ -252,7 +252,7 @@ public final class VoxelShapes { + IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition_mutableblockposition); // Paper + if (iblockdata == null) return 0.0D; // Paper + +- if ((k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) { ++ if (!iblockdata.isAir() && (k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) { // Paper + d0 = iblockdata.b((IBlockAccess) iworldreader, blockposition_mutableblockposition, voxelshapecollision).a(enumdirection_enumaxis2, axisalignedbb.d((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), d0); + if (Math.abs(d0) < 1.0E-7D) { + return 0.0D; diff --git a/patches/server-unmapped/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/patches/server-unmapped/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch new file mode 100644 index 0000000000..e1f6589002 --- /dev/null +++ b/patches/server-unmapped/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 28 Jun 2020 03:59:10 -0400 +Subject: [PATCH] Fix Per World Difficulty / Remembering Difficulty + +Fixes per world difficulty with /difficulty command and also +makes it so that the server keeps the last difficulty used instead +of restoring the server.properties every single load. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 69476bb6bca963c5ea88a7cc66622ae599595e62..afdbbe62eba7b4f0ad63c5126c6d21488c4e9a7a 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1647,11 +1647,15 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant +Date: Sun, 28 Jun 2020 19:27:20 -0400 +Subject: [PATCH] Paper dumpitem command + +Let's you quickly view the item in your hands NBT data + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index d165e8c232c38ba2e2faf93c60c8a127bb74c9b6..4b3efe01750d79bcc27a42b5a145d9aa6b124d18 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -9,6 +9,7 @@ import com.google.common.collect.Iterables; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import net.minecraft.core.BlockPosition; ++import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; + import net.minecraft.resources.MinecraftKey; + import com.google.gson.JsonObject; +@@ -36,7 +37,9 @@ import org.bukkit.command.CommandSender; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.entity.Player; ++import org.bukkit.inventory.ItemStack; + + import java.io.File; + import java.io.FileOutputStream; +@@ -59,7 +62,7 @@ import java.util.stream.Collectors; + + public class PaperCommand extends Command { + private static final String BASE_PERM = "bukkit.command.paper."; +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight", "dumpitem").build(); + + public PaperCommand(String name) { + super(name); +@@ -168,6 +171,9 @@ public class PaperCommand extends Command { + case "reload": + doReload(sender); + break; ++ case "dumpitem": ++ doDumpItem(sender); ++ break; + case "debug": + doDebug(sender, args); + break; +@@ -200,6 +206,19 @@ public class PaperCommand extends Command { + return true; + } + ++ private void doDumpItem(CommandSender sender) { ++ ItemStack itemInHand = ((CraftPlayer) sender).getItemInHand(); ++ net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(itemInHand); ++ NBTTagCompound tag = itemStack.getTag(); ++ if (tag != null) { ++ String nbt = org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(tag.getNbtPrettyComponent()); ++ Bukkit.getConsoleSender().sendMessage(nbt); ++ sender.sendMessage(nbt); ++ } else { ++ sender.sendMessage("Item does not have NBT"); ++ } ++ } ++ + private void doFixLight(CommandSender sender, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage("Only players can use this command"); +diff --git a/src/main/java/net/minecraft/nbt/NBTBase.java b/src/main/java/net/minecraft/nbt/NBTBase.java +index d6e51f82f6df2d7058806f3e483766e18398af77..3921b99b9a4c1a867b5159668d2cd62d7463e1ff 100644 +--- a/src/main/java/net/minecraft/nbt/NBTBase.java ++++ b/src/main/java/net/minecraft/nbt/NBTBase.java +@@ -26,6 +26,7 @@ public interface NBTBase { + return this.toString(); + } + ++ default IChatBaseComponent getNbtPrettyComponent() { return this.l(); } // Paper - OBFHELPER + default IChatBaseComponent l() { + return this.a("", 0); + } diff --git a/patches/server-unmapped/0510-Don-t-allow-null-UUID-s-for-chat.patch b/patches/server-unmapped/0510-Don-t-allow-null-UUID-s-for-chat.patch new file mode 100644 index 0000000000..b5584efc91 --- /dev/null +++ b/patches/server-unmapped/0510-Don-t-allow-null-UUID-s-for-chat.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 28 Jun 2020 19:36:55 -0400 +Subject: [PATCH] Don't allow null UUID's for chat + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java +index fefcacf27d71c67403555502685a992a5a706099..267e1baeaaed83befc7f6d6445a9416f7b8dfc0f 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java +@@ -3,6 +3,7 @@ package net.minecraft.network.protocol.game; + + import java.io.IOException; + import java.util.UUID; ++import net.minecraft.SystemUtils; + import net.minecraft.network.PacketDataSerializer; + import net.minecraft.network.chat.ChatMessageType; + import net.minecraft.network.chat.IChatBaseComponent; +@@ -21,7 +22,7 @@ public class PacketPlayOutChat implements Packet { + public PacketPlayOutChat(IChatBaseComponent ichatbasecomponent, ChatMessageType chatmessagetype, UUID uuid) { + this.a = ichatbasecomponent; + this.b = chatmessagetype; +- this.c = uuid; ++ this.c = uuid != null ? uuid : SystemUtils.getNullUUID(); // Paper + } + + @Override diff --git a/patches/server-unmapped/0511-Improve-Legacy-Component-serialization-size.patch b/patches/server-unmapped/0511-Improve-Legacy-Component-serialization-size.patch new file mode 100644 index 0000000000..f63ad3aa32 --- /dev/null +++ b/patches/server-unmapped/0511-Improve-Legacy-Component-serialization-size.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 28 Jun 2020 19:08:41 -0400 +Subject: [PATCH] Improve Legacy Component serialization size + +Don't constantly send format: false for all formatting options when parent already +has it false + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +index 666af6cc91bd12ba5d5a846d663a5aabf861fbc4..189a416bd033c9ff390d359aa19cec515d0461e4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +@@ -46,6 +46,7 @@ public final class CraftChatMessage { + // Separate pattern with no group 3, new lines are part of previous string + private static final Pattern INCREMENTAL_PATTERN_KEEP_NEWLINES = Pattern.compile("(" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + "[0-9a-fk-orx])|((?:(?:https?):\\/\\/)?(?:[-\\w_\\.]{2,}\\.[a-z]{2,4}.*?(?=[\\.\\?!,;:]?(?:[" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + " ]|$))))", Pattern.CASE_INSENSITIVE); + // ChatColor.b does not explicitly reset, its more of empty ++ private static final ChatModifier EMPTY = ChatModifier.a.setItalic(false); // Paper - OBFHELPER + private static final ChatModifier RESET = ChatModifier.a.setBold(false).setItalic(false).setUnderline(false).setStrikethrough(false).setRandom(false); + + private final List list = new ArrayList(); +@@ -67,6 +68,7 @@ public final class CraftChatMessage { + Matcher matcher = (keepNewlines ? INCREMENTAL_PATTERN_KEEP_NEWLINES : INCREMENTAL_PATTERN).matcher(message); + String match = null; + boolean needsAdd = false; ++ boolean hasReset = false; // Paper + while (matcher.find()) { + int groupId = 0; + while ((match = matcher.group(++groupId)) == null) { +@@ -112,7 +114,26 @@ public final class CraftChatMessage { + throw new AssertionError("Unexpected message format"); + } + } else { // Color resets formatting +- modifier = RESET.setColor(format); ++ // Paper start - improve legacy formatting ++ ChatModifier previous = modifier; ++ modifier = (!hasReset ? RESET : EMPTY).setColor(format); ++ hasReset = true; ++ if (previous.isBold()) { ++ modifier = modifier.setBold(false); ++ } ++ if (previous.isItalic()) { ++ modifier = modifier.setItalic(false); ++ } ++ if (previous.isRandom()) { ++ modifier = modifier.setRandom(false); ++ } ++ if (previous.isStrikethrough()) { ++ modifier = modifier.setStrikethrough(false); ++ } ++ if (previous.isUnderlined()) { ++ modifier = modifier.setUnderline(false); ++ } ++ // Paper end + } + needsAdd = true; + break; diff --git a/patches/server-unmapped/0512-Support-old-UUID-format-for-NBT.patch b/patches/server-unmapped/0512-Support-old-UUID-format-for-NBT.patch new file mode 100644 index 0000000000..8ba6c36f4a --- /dev/null +++ b/patches/server-unmapped/0512-Support-old-UUID-format-for-NBT.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 29 Jun 2020 03:26:17 -0400 +Subject: [PATCH] Support old UUID format for NBT + +We have stored UUID in plenty of places that did not get DFU'd + +So just look for old format and load it if it exists. + +diff --git a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java +index 0560d115288c67e46d921ce529e603f424e601f5..50515cd9287505fcc8ab52e47393fb1dc771bfc3 100644 +--- a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java ++++ b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java +@@ -41,6 +41,11 @@ public final class GameProfileSerializer { + s = nbttagcompound.getString("Name"); + } + ++ // Paper start - support string UUID's ++ if (nbttagcompound.hasKeyOfType("Id", 8)) { ++ uuid = UUID.fromString(nbttagcompound.getString("Id")); ++ } ++ // Paper end + if (nbttagcompound.b("Id")) { + uuid = nbttagcompound.a("Id"); + } +diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java +index 77afbaad5b2cb8d912f5404fcbd3a0970490f4f3..945df83d4a2170cdcc29cb6d7b9f0f5f3940cb96 100644 +--- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java ++++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java +@@ -142,6 +142,12 @@ public class NBTTagCompound implements NBTBase { + + public void setUUID(String prefix, UUID uuid) { a(prefix, uuid); } // Paper - OBFHELPER + public void a(String s, UUID uuid) { ++ // Paper start - support old format ++ if (this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99)) { ++ this.map.remove(s + "Most"); ++ this.map.remove(s + "Least"); ++ } ++ // Paper end + this.map.put(s, GameProfileSerializer.a(uuid)); + } + +@@ -151,11 +157,21 @@ public class NBTTagCompound implements NBTBase { + */ + public UUID getUUID(String prefix) { return a(prefix); } // Paper - OBFHELPER + public UUID a(String s) { ++ // Paper start - support old format ++ if (!hasKeyOfType(s, 11) && this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99)) { ++ return new UUID(this.getLong(s + "Most"), this.getLong(s + "Least")); ++ } ++ // Paper end + return GameProfileSerializer.a(this.get(s)); + } + + public final boolean hasUUID(String s) { return this.b(s); } // Paper - OBFHELPER + public boolean b(String s) { ++ // Paper start - support old format ++ if (this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99)) { ++ return true; ++ } ++ // Paper end + NBTBase nbtbase = this.get(s); + + return nbtbase != null && nbtbase.b() == NBTTagIntArray.a && ((NBTTagIntArray) nbtbase).getInts().length == 4; diff --git a/patches/server-unmapped/0513-Clean-up-duplicated-GameProfile-Properties.patch b/patches/server-unmapped/0513-Clean-up-duplicated-GameProfile-Properties.patch new file mode 100644 index 0000000000..7309e30816 --- /dev/null +++ b/patches/server-unmapped/0513-Clean-up-duplicated-GameProfile-Properties.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 1 Jul 2020 03:12:06 -0400 +Subject: [PATCH] Clean up duplicated GameProfile Properties + +We had a bug where we accidently cloned properties resulting in skulls +growing to large sizes and preventing login. + +This now automatically cleans up the extra properties. + +diff --git a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java +index 50515cd9287505fcc8ab52e47393fb1dc771bfc3..a654ea9e43c4e7dd9cde1c47d0b07834f47aa751 100644 +--- a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java ++++ b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java +@@ -60,8 +60,8 @@ public final class GameProfileSerializer { + while (iterator.hasNext()) { + String s1 = (String) iterator.next(); + NBTTagList nbttaglist = nbttagcompound1.getList(s1, 10); +- +- for (int i = 0; i < nbttaglist.size(); ++i) { ++ if (nbttaglist.size() == 0) continue; // Paper - remove duplicate properties ++ for (int i = nbttaglist.size() - 1; i < nbttaglist.size(); ++i) { // Paper - remove duplicate properties + NBTTagCompound nbttagcompound2 = nbttaglist.getCompound(i); + String s2 = nbttagcompound2.getString("Value"); + +@@ -247,7 +247,7 @@ public final class GameProfileSerializer { + Optional optional = iblockstate.b(nbttagcompound.getString(s)); + + if (optional.isPresent()) { +- return (IBlockDataHolder) s0.set(iblockstate, (Comparable) optional.get()); ++ return s0.set(iblockstate, optional.get()); // Paper - decompile error + } else { + GameProfileSerializer.LOGGER.warn("Unable to read property: {} with value: {} for blockstate: {}", s, nbttagcompound.getString(s), nbttagcompound1.toString()); + return s0; +@@ -277,8 +277,8 @@ public final class GameProfileSerializer { + return nbttagcompound; + } + +- private static > String a(IBlockState iblockstate, Comparable comparable) { +- return iblockstate.a(comparable); ++ private static > String a(IBlockState iblockstate, Comparable comparable) {// Paper - decompile error ++ return iblockstate.a((T) comparable);// Paper - decompile error + } + + public static NBTTagCompound a(DataFixer datafixer, DataFixTypes datafixtypes, NBTTagCompound nbttagcompound, int i) { +diff --git a/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java b/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java +index 70207d1ca5b971f829911b1231160f4664062da0..47eed24fa28db8c12ce98b6b72ca1671e13e9f52 100644 +--- a/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java ++++ b/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java +@@ -59,6 +59,18 @@ public class ItemSkullPlayer extends ItemBlockWallable { + return true; + } else { + // CraftBukkit start ++ // Paper start - clean up old duplicated properties ++ NBTTagCompound properties = nbttagcompound.getCompound("SkullOwner").getCompound("Properties"); ++ for (String key : properties.getKeys()) { ++ net.minecraft.nbt.NBTTagList values = properties.getList(key, 10); ++ if (values.size() > 1) { ++ net.minecraft.nbt.NBTBase texture = values.get(values.size() - 1); ++ values = new net.minecraft.nbt.NBTTagList(); ++ values.add(texture); ++ properties.set(key, values); ++ } ++ } ++ // Paper end + net.minecraft.nbt.NBTTagList textures = nbttagcompound.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts + for (int i = 0; i < textures.size(); i++) { + if (textures.get(i) instanceof NBTTagCompound && !((NBTTagCompound) textures.get(i)).hasKeyOfType("Signature", 8) && ((NBTTagCompound) textures.get(i)).getString("Value").trim().isEmpty()) { diff --git a/patches/server-unmapped/0514-Convert-legacy-attributes-in-Item-Meta.patch b/patches/server-unmapped/0514-Convert-legacy-attributes-in-Item-Meta.patch new file mode 100644 index 0000000000..025b86e719 --- /dev/null +++ b/patches/server-unmapped/0514-Convert-legacy-attributes-in-Item-Meta.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 1 Jul 2020 04:50:22 -0400 +Subject: [PATCH] Convert legacy attributes in Item Meta + + +diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +index 43fa8d3c573540682fc87ee2bf8d61ba80d3732d..673948947bd918c1dbb6c4c99486b4200e3c09fe 100644 +--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java ++++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +@@ -13,6 +13,20 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; + public class CraftAttributeMap implements Attributable { + + private final AttributeMapBase handle; ++ // Paper start - convert legacy attributes ++ private static final com.google.common.collect.ImmutableMap legacyNMS = com.google.common.collect.ImmutableMap.builder().put("generic.maxHealth", "generic.max_health").put("Max Health", "generic.max_health").put("zombie.spawnReinforcements", "zombie.spawn_reinforcements").put("Spawn Reinforcements Chance", "zombie.spawn_reinforcements").put("horse.jumpStrength", "horse.jump_strength").put("Jump Strength", "horse.jump_strength").put("generic.followRange", "generic.follow_range").put("Follow Range", "generic.follow_range").put("generic.knockbackResistance", "generic.knockback_resistance").put("Knockback Resistance", "generic.knockback_resistance").put("generic.movementSpeed", "generic.movement_speed").put("Movement Speed", "generic.movement_speed").put("generic.flyingSpeed", "generic.flying_speed").put("Flying Speed", "generic.flying_speed").put("generic.attackDamage", "generic.attack_damage").put("generic.attackKnockback", "generic.attack_knockback").put("generic.attackSpeed", "generic.attack_speed").put("generic.armorToughness", "generic.armor_toughness").build(); ++ ++ public static String convertIfNeeded(String nms) { ++ if (nms == null) { ++ return null; ++ } ++ nms = legacyNMS.getOrDefault(nms, nms); ++ if (!nms.toLowerCase().equals(nms) || nms.indexOf(' ') != -1) { ++ return null; ++ } ++ return nms; ++ } ++ // Paper end + + public CraftAttributeMap(AttributeMapBase handle) { + this.handle = handle; +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 8f8dccd6fb2e49d65383d6e8f3fc5ffbabd2b7a5..8398ac45e988c621b3e059d75101185513ddd9ab 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -481,7 +481,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + + AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); + +- String attributeName = entry.getString(ATTRIBUTES_IDENTIFIER.NBT); ++ String attributeName = CraftAttributeMap.convertIfNeeded(entry.getString(ATTRIBUTES_IDENTIFIER.NBT)); // Paper + if (attributeName == null || attributeName.isEmpty()) { + continue; + } diff --git a/patches/server-unmapped/0515-Remove-some-streams-from-structures.patch b/patches/server-unmapped/0515-Remove-some-streams-from-structures.patch new file mode 100644 index 0000000000..67b43bca11 --- /dev/null +++ b/patches/server-unmapped/0515-Remove-some-streams-from-structures.patch @@ -0,0 +1,140 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Mon, 29 Jun 2020 17:03:06 -0400 +Subject: [PATCH] Remove some streams from structures + +This showed up a lot in the spark profiler, should have a low-medium performance improvement. + +diff --git a/src/main/java/net/minecraft/world/level/StructureManager.java b/src/main/java/net/minecraft/world/level/StructureManager.java +index 6fe276b29aa9fe1b312ef2773484fa780506fded..07dcfd56af1014ad159828dd9ee2d89c2010b9f4 100644 +--- a/src/main/java/net/minecraft/world/level/StructureManager.java ++++ b/src/main/java/net/minecraft/world/level/StructureManager.java +@@ -2,6 +2,7 @@ + package net.minecraft.world.level; + + import com.mojang.datafixers.DataFixUtils; ++import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper + import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.core.BaseBlockPosition; +@@ -12,11 +13,12 @@ import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.IStructureAccess; + import net.minecraft.world.level.levelgen.GeneratorSettings; + import net.minecraft.world.level.levelgen.feature.StructureGenerator; ++import net.minecraft.world.level.levelgen.structure.StructurePiece; + import net.minecraft.world.level.levelgen.structure.StructureStart; + + public class StructureManager { + +- private final GeneratorAccess a; ++ private final GeneratorAccess a; public GeneratorAccess getLevel() { return a; } // Paper - OBFHELPER + private final GeneratorSettings b; + + public StructureManager(GeneratorAccess generatoraccess, GeneratorSettings generatorsettings) { +@@ -42,6 +44,20 @@ public class StructureManager { + }); + } + ++ // Paper start - remove structure streams ++ public java.util.List> getFeatureStarts(SectionPosition sectionPosition, StructureGenerator structureGenerator) { ++ java.util.List> list = new ObjectArrayList<>(); ++ for (Long curLong: getLevel().getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structureGenerator)) { ++ SectionPosition sectionPosition1 = SectionPosition.a(new ChunkCoordIntPair(curLong), 0); ++ StructureStart structurestart = a(sectionPosition1, structureGenerator, getLevel().getChunkAt(sectionPosition1.a(), sectionPosition1.c(), ChunkStatus.STRUCTURE_STARTS)); ++ if (structurestart != null && structurestart.e()) { ++ list.add(structurestart); ++ } ++ } ++ return list; ++ } ++ // Paper end ++ + @Nullable + public StructureStart a(SectionPosition sectionposition, StructureGenerator structuregenerator, IStructureAccess istructureaccess) { + return istructureaccess.a(structuregenerator); +@@ -60,13 +76,21 @@ public class StructureManager { + } + + public StructureStart a(BlockPosition blockposition, boolean flag, StructureGenerator structuregenerator) { +- return (StructureStart) DataFixUtils.orElse(this.a(SectionPosition.a(blockposition), structuregenerator).filter((structurestart) -> { +- return structurestart.c().b((BaseBlockPosition) blockposition); +- }).filter((structurestart) -> { +- return !flag || structurestart.d().stream().anyMatch((structurepiece) -> { +- return structurepiece.g().b((BaseBlockPosition) blockposition); +- }); +- }).findFirst(), StructureStart.a); ++ // Paper start - remove structure streams ++ for (StructureStart structurestart : getFeatureStarts(SectionPosition.a(blockposition), structuregenerator)) { ++ if (structurestart.c().b(blockposition)) { ++ if (!flag) { ++ return structurestart; ++ } ++ for (StructurePiece structurepiece : structurestart.d()) { ++ if (structurepiece.g().b(blockposition)) { ++ return structurestart; ++ } ++ } ++ } ++ } ++ return StructureStart.a; ++ // Paper end + } + + // Spigot start +diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java +index 7147cdda756ccb3d4f6880802128f68601783883..15096a9c2719b8b4c099f62d0a1c808e56b63a8e 100644 +--- a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java ++++ b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java +@@ -39,6 +39,7 @@ import net.minecraft.world.level.levelgen.WorldGenStage; + import net.minecraft.world.level.levelgen.feature.StructureGenerator; + import net.minecraft.world.level.levelgen.feature.WorldGenFeatureConfigured; + import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; ++import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.surfacebuilders.WorldGenSurfaceComposite; + import net.minecraft.world.level.levelgen.synth.NoiseGenerator3; + import net.minecraft.world.level.material.Fluid; +@@ -238,9 +239,11 @@ public final class BiomeBase { + int l1 = j1 << 4; + + try { +- structuremanager.a(SectionPosition.a(blockposition), structuregenerator).forEach((structurestart) -> { +- structurestart.a(regionlimitedworldaccess, structuremanager, chunkgenerator, seededrandom, new StructureBoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkCoordIntPair(i1, j1)); +- }); ++ // Paper start - remove structure streams ++ for (StructureStart structureStart : structuremanager.getFeatureStarts(SectionPosition.a(blockposition), structuregenerator)) { ++ structureStart.a(regionlimitedworldaccess, structuremanager, chunkgenerator, seededrandom, new StructureBoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkCoordIntPair(i1, j1)); ++ } ++ // Paper end + } catch (Exception exception) { + CrashReport crashreport = CrashReport.a(exception, "Feature placement"); + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java +index 700b32322e8d0fbb8ec2824e50a340be16b48f81..369fb0bda22f02e76b901b6eb8990651c53c7577 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java +@@ -40,6 +40,7 @@ import net.minecraft.world.level.levelgen.feature.structures.WorldGenFeatureDefi + import net.minecraft.world.level.levelgen.feature.structures.WorldGenFeatureDefinedStructurePoolTemplate; + import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; + import net.minecraft.world.level.levelgen.structure.StructurePiece; ++import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.structure.WorldGenFeaturePillagerOutpostPoolPiece; + import net.minecraft.world.level.levelgen.synth.NoiseGenerator; + import net.minecraft.world.level.levelgen.synth.NoiseGenerator3; +@@ -455,7 +456,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + while (iterator.hasNext()) { + StructureGenerator structuregenerator = (StructureGenerator) iterator.next(); + +- structuremanager.a(SectionPosition.a(chunkcoordintpair, 0), structuregenerator).forEach((structurestart) -> { ++ for (StructureStart structurestart : structuremanager.getFeatureStarts(SectionPosition.a(chunkcoordintpair, 0), structuregenerator)) { // Paper - remove structure streams + Iterator iterator1 = structurestart.d().iterator(); + + while (iterator1.hasNext()) { +@@ -487,7 +488,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + } + } + +- }); ++ } // Paper - remove structure streams + } + + double[][][] adouble = new double[2][this.p + 1][this.o + 1]; diff --git a/patches/server-unmapped/0516-Remove-streams-from-classes-related-villager-gossip.patch b/patches/server-unmapped/0516-Remove-streams-from-classes-related-villager-gossip.patch new file mode 100644 index 0000000000..2e8b227335 --- /dev/null +++ b/patches/server-unmapped/0516-Remove-streams-from-classes-related-villager-gossip.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 1 Jul 2020 18:01:49 -0400 +Subject: [PATCH] Remove streams from classes related villager gossip + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java +index 9cc3a18636a356977577076e96cb7be706c61abf..7d34d1157786227ac210edc1595a024ccb61a3e9 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java +@@ -9,6 +9,7 @@ import com.mojang.serialization.DynamicOps; + import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import java.util.Arrays; + import java.util.Collection; +@@ -51,8 +52,21 @@ public class Reputation { + }); + } + ++ // Paper start - Remove streams from reputation ++ private List decompress() { ++ List list = new ObjectArrayList<>(); ++ for (Map.Entry entry : getReputations().entrySet()) { ++ for (Reputation.b cur : entry.getValue().decompress(entry.getKey())) { ++ if (cur.a() != 0) ++ list.add(cur); ++ } ++ } ++ return list; ++ } ++ // Paper end ++ + private Collection a(Random random, int i) { +- List list = (List) this.c().collect(Collectors.toList()); ++ List list = decompress(); // Paper - Remove streams from reputation + + if (list.isEmpty()) { + return Collections.emptyList(); +@@ -119,7 +133,7 @@ public class Reputation { + } + + public Dynamic a(DynamicOps dynamicops) { +- return new Dynamic(dynamicops, dynamicops.createList(this.c().map((reputation_b) -> { ++ return new Dynamic(dynamicops, dynamicops.createList(this.decompress().stream().map((reputation_b) -> { + return reputation_b.a(dynamicops); + }).map(Dynamic::getValue))); + } +@@ -144,18 +158,30 @@ public class Reputation { + + public static class a { // Paper - make public + +- private final Object2IntMap a; ++ private final Object2IntMap a; private Object2IntMap getEntries() { return a; } // Paper - OBFHELPER + + public a() { // Paper - make public - update CraftVillager setReputation on change + this.a = new Object2IntOpenHashMap(); + } + + public int a(Predicate predicate) { +- return this.a.object2IntEntrySet().stream().filter((entry) -> { +- return predicate.test(entry.getKey()); +- }).mapToInt((entry) -> { +- return entry.getIntValue() * ((ReputationType) entry.getKey()).g; +- }).sum(); ++ // Paper start - Remove streams from reputation ++ int weight = 0; ++ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { ++ if (predicate.test(entry.getKey())) { ++ weight += entry.getIntValue() * entry.getKey().getWeight(); ++ } ++ } ++ return weight; ++ } ++ ++ public List decompress(UUID uuid) { ++ List list = new ObjectArrayList<>(); ++ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { ++ list.add(new Reputation.b(uuid, entry.getKey(), entry.getIntValue())); ++ } ++ return list; ++ // Paper - end + } + + public Stream a(UUID uuid) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java b/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java +index 89651e6e3bb1cfbb8eb8a120b3c3e553cd831a68..6036476aac4a81152e8b142445041ecdb2d6e5d1 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java +@@ -11,7 +11,7 @@ public enum ReputationType { + MAJOR_NEGATIVE("major_negative", -5, 100, 10, 10), MINOR_NEGATIVE("minor_negative", -1, 200, 20, 20), MINOR_POSITIVE("minor_positive", 1, 200, 1, 5), MAJOR_POSITIVE("major_positive", 5, 100, 0, 100), TRADING("trading", 1, 25, 2, 20); + + public final String f; +- public final int g; ++ public final int g; public int getWeight() { return g; } // Paper - OBFHELPER + public final int h; + public final int i; + public final int j; diff --git a/patches/server-unmapped/0517-Support-components-in-ItemMeta.patch b/patches/server-unmapped/0517-Support-components-in-ItemMeta.patch new file mode 100644 index 0000000000..6f1e33b76d --- /dev/null +++ b/patches/server-unmapped/0517-Support-components-in-ItemMeta.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Sat, 6 Jun 2020 18:13:42 +0200 +Subject: [PATCH] Support components in ItemMeta + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 8398ac45e988c621b3e059d75101185513ddd9ab..5c1319a86f6314c1d0a979af34424ee025a8030f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -875,11 +875,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return CraftChatMessage.fromJSONComponent(displayName); + } + ++ // 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(displayName); ++ } ++ // Paper end + @Override + public final void setDisplayName(String name) { + this.displayName = CraftChatMessage.fromStringOrNullToJSON(name); + } + ++ // Paper start ++ @Override ++ public void setDisplayNameComponent(net.md_5.bungee.api.chat.BaseComponent[] component) { ++ this.displayName = net.md_5.bungee.chat.ComponentSerializer.toString(component); ++ } ++ // Paper end + @Override + public boolean hasDisplayName() { + return displayName != null; +@@ -1022,6 +1034,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return this.lore == null ? null : new ArrayList(Lists.transform(this.lore, CraftChatMessage::fromJSONComponent)); + } + ++ // 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(entry) ++ ).collect(java.util.stream.Collectors.toList())); ++ } ++ // Paper end + @Override + public void setLore(List lore) { + if (lore == null || lore.isEmpty()) { +@@ -1036,6 +1056,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + } + ++ // 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 customModelData != null; +@@ -1497,6 +1532,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + + for (Object object : addFrom) { ++ // Paper start - support components ++ if(object instanceof net.md_5.bungee.api.chat.BaseComponent[]) { ++ addTo.add(net.md_5.bungee.chat.ComponentSerializer.toString((net.md_5.bungee.api.chat.BaseComponent[]) object)); ++ } else ++ // Paper end + if (!(object instanceof String)) { + if (object != null) { + throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName()); diff --git a/patches/server-unmapped/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/patches/server-unmapped/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch new file mode 100644 index 0000000000..c5d87e17db --- /dev/null +++ b/patches/server-unmapped/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 3 Jul 2020 15:03:33 -0700 +Subject: [PATCH] Improve EntityTargetLivingEntityEvent for 1.16 mobs + +CraftBukkit has a bug in their implementation and is incorrectly handling forget +Also adds more target reasons for why it forgot target. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java +index ad2e4be7483d39aeb7be3727aba6a5fe89ea9602..05c507270ff5b4c0d684d0fc4a69ee47618cd281 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java +@@ -33,15 +33,15 @@ public class BehaviorAttackTargetForget extends Beha + + protected void a(WorldServer worldserver, E e0, long i) { + if (a((EntityLiving) e0)) { +- this.d(e0); ++ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // Paper + } else if (this.c(e0)) { +- this.d(e0); ++ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_DIED); // Paper + } else if (this.a(e0)) { +- this.d(e0); ++ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_OTHER_LEVEL); // Paper + } else if (!IEntitySelector.f.test(this.b(e0))) { +- this.d(e0); ++ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper + } else if (this.b.test(this.b(e0))) { +- this.d(e0); ++ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper + } + } + +@@ -65,17 +65,20 @@ public class BehaviorAttackTargetForget extends Beha + return optional.isPresent() && !((EntityLiving) optional.get()).isAlive(); + } + +- private void d(E e0) { ++ private void d(E e0, EntityTargetEvent.TargetReason reason) { + // CraftBukkit start +- EntityLiving old = e0.getBehaviorController().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); +- EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(e0, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ // Paper start - fix this event ++ //EntityLiving old = e0.getBehaviorController().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(e0, null, reason); + if (event.isCancelled()) { + return; + } +- if (event.getTarget() != null) { ++ // comment out, bad logic - bad ++ /*if (event.getTarget() != null) { + e0.getBehaviorController().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); + return; +- } ++ }*/ ++ // Paper end + // CraftBukkit end + e0.getBehaviorController().removeMemory(MemoryModuleType.ATTACK_TARGET); + } diff --git a/patches/server-unmapped/0519-Add-entity-liquid-API.patch b/patches/server-unmapped/0519-Add-entity-liquid-API.patch new file mode 100644 index 0000000000..f5fdce42cd --- /dev/null +++ b/patches/server-unmapped/0519-Add-entity-liquid-API.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 2 Jul 2020 18:11:43 -0500 +Subject: [PATCH] Add entity liquid API + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a6df453acadccc6500cec0ac816ec4d1e35adad7..f5bb9313a249bfd4e63ab77e19cfd6f997d22fb1 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1166,12 +1166,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return this.inWater; + } + +- private boolean isInRain() { ++ public boolean isInRain() { // Paper - private -> public + BlockPosition blockposition = this.getChunkCoordinates(); + + return this.world.isRainingAt(blockposition) || this.world.isRainingAt(new BlockPosition((double) blockposition.getX(), this.getBoundingBox().maxY, (double) blockposition.getZ())); + } + ++ public final boolean isInBubbleColumn() { return k(); } // Paper - OBFHELPER + private boolean k() { + return this.world.getType(this.getChunkCoordinates()).a(Blocks.BUBBLE_COLUMN); + } +@@ -1185,6 +1186,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return this.isInWater() || this.isInRain() || this.k(); + } + ++ public final boolean isInWaterOrBubbleColumn() { return aH(); } // Paper - OBFHELPER + public boolean aH() { + return this.isInWater() || this.k(); + } +@@ -1327,6 +1329,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return this.O == tag; + } + ++ public final boolean isInLava() { return aQ(); } // Paper - OBFHELPER + public boolean aQ() { + return !this.justCreated && this.M.getDouble(TagsFluid.LAVA) > 0.0D; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 266b2cbd6bfaf10743929a1eeb9732a5d1fb4c62..387f6f6fa9bbb1cce544cfb907f68c7993752dd7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1137,5 +1137,29 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { + return getHandle().spawnReason; + } ++ ++ public boolean isInRain() { ++ return getHandle().isInRain(); ++ } ++ ++ public boolean isInBubbleColumn() { ++ return getHandle().isInBubbleColumn(); ++ } ++ ++ public boolean isInWaterOrRain() { ++ return getHandle().isInWaterOrRain(); ++ } ++ ++ public boolean isInWaterOrBubbleColumn() { ++ return getHandle().isInWaterOrBubbleColumn(); ++ } ++ ++ public boolean isInWaterOrRainOrBubbleColumn() { ++ return getHandle().isInWaterOrRainOrBubble(); ++ } ++ ++ public boolean isInLava() { ++ return getHandle().isInLava(); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0520-Update-itemstack-legacy-name-and-lore.patch b/patches/server-unmapped/0520-Update-itemstack-legacy-name-and-lore.patch new file mode 100644 index 0000000000..2398718e40 --- /dev/null +++ b/patches/server-unmapped/0520-Update-itemstack-legacy-name-and-lore.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 1 Jul 2020 11:57:40 -0500 +Subject: [PATCH] Update itemstack legacy name and lore + + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index b88aec3b97d43018cf2733bad069a90338aa98cb..800d10db92a956d3ca8a3d569d12862f36044ee9 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -27,6 +27,7 @@ import net.minecraft.core.IRegistry; + import net.minecraft.nbt.NBTBase; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.nbt.NBTTagList; ++import net.minecraft.nbt.NBTTagString; + import net.minecraft.network.chat.ChatComponentText; + import net.minecraft.network.chat.ChatComponentUtils; + import net.minecraft.network.chat.ChatHoverable; +@@ -137,6 +138,44 @@ public final class ItemStack { + list.sort((Comparator) enchantSorter); // Paper + } catch (Exception ignored) {} + } ++ ++ private void processText() { ++ NBTTagCompound display = getSubTag("display"); ++ if (display != null) { ++ if (display.hasKeyOfType("Name", 8)) { ++ String json = display.getString("Name"); ++ if (json != null && json.contains("\u00A7")) { ++ try { ++ display.set("Name", convert(json)); ++ } catch (JsonParseException jsonparseexception) { ++ display.remove("Name"); ++ } ++ } ++ } ++ if (display.hasKeyOfType("Lore", 9)) { ++ NBTTagList list = display.getList("Lore", 8); ++ for (int index = 0; index < list.size(); index++) { ++ String json = list.getString(index); ++ if (json != null && json.contains("\u00A7")) { // Only try if it has legacy in the unparsed json ++ try { ++ list.set(index, convert(json)); ++ } catch (JsonParseException e) { ++ list.set(index, NBTTagString.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(new ChatComponentText("")))); ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ private NBTTagString convert(String json) { ++ IChatBaseComponent component = IChatBaseComponent.ChatSerializer.jsonToComponent(json); ++ if (component instanceof ChatComponentText && component.getText().contains("\u00A7") && component.getSiblings().isEmpty()) { ++ // Only convert if the root component is a single comp with legacy in it, don't convert already normal components ++ component = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(component.getText())[0]; ++ } ++ return NBTTagString.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(component)); ++ } + // Paper end + + public ItemStack(IMaterial imaterial) { +@@ -182,6 +221,7 @@ public final class ItemStack { + // CraftBukkit start - make defensive copy as this data may be coming from the save thread + this.tag = (NBTTagCompound) nbttagcompound.getCompound("tag").clone(); + processEnchantOrder(this.tag); // Paper ++ processText(); // Paper + this.getItem().b(this.tag); + // CraftBukkit end + } +@@ -665,6 +705,7 @@ public final class ItemStack { + } + } + ++ @Nullable public NBTTagCompound getSubTag(String s) { return b(s); } // Paper - OBFHELPER + @Nullable + public NBTTagCompound b(String s) { + return this.tag != null && this.tag.hasKeyOfType(s, 10) ? this.tag.getCompound(s) : null; diff --git a/patches/server-unmapped/0521-Spawn-player-in-correct-world-on-login.patch b/patches/server-unmapped/0521-Spawn-player-in-correct-world-on-login.patch new file mode 100644 index 0000000000..0810b4a11b --- /dev/null +++ b/patches/server-unmapped/0521-Spawn-player-in-correct-world-on-login.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Wyatt Childers +Date: Fri, 3 Jul 2020 14:57:05 -0400 +Subject: [PATCH] Spawn player in correct world on login + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 4c3a2e3cfd60321b3b74d143a32aa5f5d59d7e1e..34b45a6818209245fa5692a83cf4143030057095 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -196,7 +196,18 @@ public abstract class PlayerList { + }String lastKnownName = s; // Paper + // CraftBukkit end + +- if (nbttagcompound != null) { ++ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID. ++ if (nbttagcompound != null && nbttagcompound.hasKey("WorldUUIDMost") && nbttagcompound.hasKey("WorldUUIDLeast")) { ++ UUID uid = new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast")); ++ org.bukkit.World bWorld = org.bukkit.Bukkit.getServer().getWorld(uid); ++ if (bWorld != null) { ++ resourcekey = ((CraftWorld) bWorld).getHandle().getDimensionKey(); ++ } else { ++ resourcekey = World.OVERWORLD; ++ } ++ } else if (nbttagcompound != null) { ++ // Vanilla migration support ++ // Paper end + DataResult dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, nbttagcompound.get("Dimension"))); + Logger logger = PlayerList.LOGGER; + diff --git a/patches/server-unmapped/0522-Add-PrepareResultEvent.patch b/patches/server-unmapped/0522-Add-PrepareResultEvent.patch new file mode 100644 index 0000000000..a94b9bff00 --- /dev/null +++ b/patches/server-unmapped/0522-Add-PrepareResultEvent.patch @@ -0,0 +1,164 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 3 Jul 2020 11:58:56 -0500 +Subject: [PATCH] Add PrepareResultEvent + +Adds a new event for all crafting stations that generate a result slot item + +Anvil, Grindstone and Smithing now extend this event + +diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java +index e9733fd9dac89d31dbad391cb22a8c84216045db..e7c29d194d5c3e3b1b79228758f7a3d8aa060fbd 100644 +--- a/src/main/java/net/minecraft/world/inventory/Container.java ++++ b/src/main/java/net/minecraft/world/inventory/Container.java +@@ -142,6 +142,7 @@ public abstract class Container { + return nonnulllist; + } + ++ public final void notifyListeners() { this.c(); } // Paper - OBFHELPER + public void c() { + int i; + +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java +index ff618bbb3fc4acfce51f5e5e6a504a63e9ad77cd..ae5674ae9c539720a657838a640050cd3b4dc5b5 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java +@@ -307,6 +307,7 @@ public class ContainerAnvil extends ContainerAnvilAbstract { + } + + this.e(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java +index 949042d4e4a1a63c0477704265fe32c371543e8c..9d47f2253a8adbcecbbe3d8a0a42e62f1dac1408 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java +@@ -71,6 +71,7 @@ public abstract class ContainerAnvilAbstract extends Container { + super.a(iinventory); + if (iinventory == this.repairInventory) { + this.e(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerCartography.java b/src/main/java/net/minecraft/world/inventory/ContainerCartography.java +index ce3c22d6f05703874eedf634331ea92ef4c039bf..031e75dc1f3dd6fc1cee684e8e7a105b3e402127 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerCartography.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerCartography.java +@@ -148,6 +148,7 @@ public class ContainerCartography extends Container { + this.a(itemstack, itemstack1, itemstack2); + } + ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + private void a(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2) { +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java +index fad7355a549aef811bca43be198af3d1c0a53980..1d5dcbbd3870eb8e1013a97f6ce882bfc096bf95 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java +@@ -157,6 +157,7 @@ public class ContainerGrindstone extends Container { + super.a(iinventory); + if (iinventory == this.craftInventory) { + this.e(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java +index 350a9b6525a95a00e72e836f1cc9e1a6b99fdd7a..7980930cc712e37a788f894bf2d2ee2b1cfc1196 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java +@@ -190,7 +190,8 @@ public class ContainerLoom extends Container { + } + + this.j(); +- this.c(); ++ //this.c(); // Paper - done below ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 3); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java b/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java +index 1cc0ba5b8f182ac5105d2dc493463055e32a52e5..594cbd23c5d8ee2aa88106a1f0a79db0c8ba83a3 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java +@@ -79,6 +79,7 @@ public class ContainerSmithing extends ContainerAnvilAbstract { + // CraftBukkit end + } + ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java +index cfcb2469569edd51bbb74ca8d7a35a1ec0ecb434..1589d9ca201d386d11d9fd57fa8ba6848bae215c 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java +@@ -156,6 +156,7 @@ public class ContainerStonecutter extends Container { + this.a(iinventory, itemstack); + } + ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 1); // Paper + } + + private void a(IInventory iinventory, ItemStack itemstack) { +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index d620d3e7c023786d1b7411399a05a75028a404cc..55619fbc3fdb9393d7c47a23dc337b06ce4495d6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1534,19 +1534,44 @@ public class CraftEventFactory { + return event; + } + +- public static PrepareAnvilEvent callPrepareAnvilEvent(InventoryView view, ItemStack item) { +- PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item).clone()); +- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); ++ // Paper start - disable this method, handled below ++ public static void callPrepareAnvilEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult ++ PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone ++ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // disable event + event.getInventory().setItem(2, event.getResult()); +- return event; ++ //return event; // Paper + } ++ // Paper end + +- public static PrepareSmithingEvent callPrepareSmithingEvent(InventoryView view, ItemStack item) { +- PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item).clone()); +- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); ++ // Paper start - disable this method, handled in callPrepareResultEvent ++ public static void callPrepareSmithingEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult ++ PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone ++ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // Paper - disable event + event.getInventory().setItem(2, event.getResult()); +- return event; ++ //return event; // Paper + } ++ // Paper end ++ ++ // Paper start - support specific overrides for prepare result ++ public static void callPrepareResultEvent(Container container, int resultSlot) { ++ com.destroystokyo.paper.event.inventory.PrepareResultEvent event; ++ InventoryView view = container.getBukkitView(); ++ org.bukkit.inventory.ItemStack origItem = view.getTopInventory().getItem(resultSlot); ++ CraftItemStack result = origItem != null ? CraftItemStack.asCraftCopy(origItem) : null; ++ if (view.getTopInventory() instanceof org.bukkit.inventory.AnvilInventory) { ++ event = new PrepareAnvilEvent(view, result); ++ } else if (view.getTopInventory() instanceof org.bukkit.inventory.GrindstoneInventory) { ++ event = new com.destroystokyo.paper.event.inventory.PrepareGrindstoneEvent(view, result); ++ } else if (view.getTopInventory() instanceof org.bukkit.inventory.SmithingInventory) { ++ event = new PrepareSmithingEvent(view, result); ++ } else { ++ event = new com.destroystokyo.paper.event.inventory.PrepareResultEvent(view, result); ++ } ++ event.callEvent(); ++ event.getInventory().setItem(resultSlot, event.getResult()); ++ container.notifyListeners(); ++ } ++ // Paper end + + /** + * Mob spawner event. diff --git a/patches/server-unmapped/0523-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server-unmapped/0523-Allow-delegation-to-vanilla-chunk-gen.patch new file mode 100644 index 0000000000..85ce652a8e --- /dev/null +++ b/patches/server-unmapped/0523-Allow-delegation-to-vanilla-chunk-gen.patch @@ -0,0 +1,104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MiniDigger +Date: Wed, 29 Apr 2020 02:10:32 +0200 +Subject: [PATCH] Allow delegation to vanilla chunk gen + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java b/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java +index 60ecd3a92af0f1968b10bb8babfb43147ef568d3..9077b70650d70dd294f53a1ef73e86e28ceaece9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java +@@ -36,7 +36,7 @@ import org.apache.logging.log4j.Logger; + public class ChunkConverter { + + private static final Logger LOGGER = LogManager.getLogger(); +- public static final ChunkConverter a = new ChunkConverter(); ++ public static final ChunkConverter a = new ChunkConverter(); public static ChunkConverter getEmptyConverter() { return a; } // Paper - obfhelper + private static final EnumDirection8[] c = EnumDirection8.values(); + private final EnumSet d; + private final int[][] e; +@@ -322,7 +322,7 @@ public class ChunkConverter { + if ((Integer) iblockdata.get(BlockProperties.an) >= j) { + generatoraccess.setTypeAndData(blockposition, (IBlockData) iblockdata.set(BlockProperties.an, j), 18); + if (i != 7) { +- EnumDirection[] aenumdirection = null.f; ++ EnumDirection[] aenumdirection = f; // Paper - decomp fix + int k = aenumdirection.length; + + for (int l = 0; l < k; ++l) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index a295ab6a7ec79775224381e94e288069f5d311fe..8f44857e9f61c72fa210c16c8bd6b8a6bbdac239 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2033,6 +2033,32 @@ public final class CraftServer implements Server { + return new CraftChunkData(world); + } + ++ // Paper start ++ @Override ++ public ChunkGenerator.ChunkData createVanillaChunkData(World world, int x, int z) { ++ // get empty object ++ CraftChunkData data = (CraftChunkData) createChunkData(world); ++ // do bunch of vanilla shit ++ net.minecraft.server.level.WorldServer nmsWorld = ((CraftWorld) world).getHandle(); ++ net.minecraft.world.level.chunk.ProtoChunk protoChunk = new net.minecraft.world.level.chunk.ProtoChunk(new net.minecraft.world.level.ChunkCoordIntPair(x, z), net.minecraft.world.level.chunk.ChunkConverter.getEmptyConverter(), nmsWorld); ++ List list = new ArrayList<>(); ++ list.add(protoChunk); ++ net.minecraft.server.level.RegionLimitedWorldAccess genRegion = new net.minecraft.server.level.RegionLimitedWorldAccess(nmsWorld, list); ++ // call vanilla generator, one feature after another. Order here is important! ++ net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator = nmsWorld.getChunkProvider().chunkGenerator; ++ if (chunkGenerator instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator) { ++ chunkGenerator = ((org.bukkit.craftbukkit.generator.CustomChunkGenerator) chunkGenerator).delegate; ++ } ++ chunkGenerator.createBiomes(nmsWorld.r().b(IRegistry.ay), protoChunk); ++ chunkGenerator.buildNoise(genRegion, nmsWorld.getStructureManager(), protoChunk); ++ chunkGenerator.buildBase(genRegion, protoChunk); ++ // copy over generated sections ++ data.setRawChunkData(protoChunk.getSections()); ++ // hooray! ++ return data; ++ } ++ // Paper end ++ + @Override + public BossBar createBossBar(String title, BarColor color, BarStyle style, BarFlag... flags) { + return new CraftBossBar(title, color, style, flags); +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +index afca0038bb74ac53f07a25729a3c1542e244c6fd..d02281f954aac8d8b65f5d36ec70f0352e4c7cdd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +@@ -19,7 +19,7 @@ import org.bukkit.material.MaterialData; + */ + public final class CraftChunkData implements ChunkGenerator.ChunkData { + private final int maxHeight; +- private final ChunkSection[] sections; ++ private ChunkSection[] sections; // Paper - remove final + private Set tiles; + private World world; // Paper - Anti-Xray - Add world + +@@ -168,6 +168,12 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + return sections; + } + ++ // Paper start ++ public void setRawChunkData(ChunkSection[] sections) { ++ this.sections = sections; ++ } ++ // Paper end ++ + Set getTiles() { + return tiles; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java +index 7ce7e13032fe43b8998410937d07bfffa6f01527..fb7f68887efb1de8ff9167dd110fcb52627e9206 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java +@@ -33,7 +33,7 @@ import org.bukkit.generator.ChunkGenerator.ChunkData; + + public class CustomChunkGenerator extends InternalChunkGenerator { + +- private final net.minecraft.world.level.chunk.ChunkGenerator delegate; ++ public final net.minecraft.world.level.chunk.ChunkGenerator delegate; // Paper - public + private final ChunkGenerator generator; + private final WorldServer world; + private final Random random = new Random(); diff --git a/patches/server-unmapped/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server-unmapped/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch new file mode 100644 index 0000000000..20d87b812e --- /dev/null +++ b/patches/server-unmapped/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 5 Jul 2020 14:59:31 -0400 +Subject: [PATCH] Don't check chunk for portal on world gen entity add + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 13896da2194cab683782504291ede6f135ca7279..60dfa764898b59b60aec2da9580a80634e624dbe 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -3041,7 +3041,7 @@ public abstract class EntityLiving extends Entity { + Entity entity = this.getVehicle(); + + super.stopRiding(suppressCancellation); // Paper - suppress +- if (entity != null && entity != this.getVehicle() && !this.world.isClientSide) { ++ if (entity != null && entity != this.getVehicle() && !this.world.isClientSide && entity.valid) { // Paper - don't process on world gen + this.a(entity); + } + diff --git a/patches/server-unmapped/0525-Optimize-NetworkManager-Exception-Handling.patch b/patches/server-unmapped/0525-Optimize-NetworkManager-Exception-Handling.patch new file mode 100644 index 0000000000..267d81608f --- /dev/null +++ b/patches/server-unmapped/0525-Optimize-NetworkManager-Exception-Handling.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Sun, 5 Jul 2020 22:38:18 -0400 +Subject: [PATCH] Optimize NetworkManager Exception Handling + + +diff --git a/src/main/java/net/minecraft/network/EnumProtocol.java b/src/main/java/net/minecraft/network/EnumProtocol.java +index a892521db1197369bf6363bd2f5da24bf53643ab..46d8471ba98a5f2c659d35dd86c4c20c67f1ceac 100644 +--- a/src/main/java/net/minecraft/network/EnumProtocol.java ++++ b/src/main/java/net/minecraft/network/EnumProtocol.java +@@ -286,6 +286,7 @@ public enum EnumProtocol { + + @Nullable + public Packet a(int i) { ++ if (i < 0 || i >= this.b.size()) return null; // Paper + Supplier> supplier = (Supplier) this.b.get(i); + + return supplier != null ? (Packet) supplier.get() : null; +diff --git a/src/main/java/net/minecraft/network/PacketSplitter.java b/src/main/java/net/minecraft/network/PacketSplitter.java +index 2c7de7ab6da2106394ec668cd7cb9be1f8dabeb3..e81bfd35b9a745eeb1457ceda5fda320654bd89a 100644 +--- a/src/main/java/net/minecraft/network/PacketSplitter.java ++++ b/src/main/java/net/minecraft/network/PacketSplitter.java +@@ -9,11 +9,21 @@ import java.util.List; + + public class PacketSplitter extends ByteToMessageDecoder { + ++ private final byte[] lenBuf = new byte[3]; // Paper + public PacketSplitter() {} + + protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { ++ // Paper start - if channel is not active just discard the packet ++ if (!channelhandlercontext.channel().isActive()) { ++ bytebuf.skipBytes(bytebuf.readableBytes()); ++ return; ++ } ++ // Paper end + bytebuf.markReaderIndex(); +- byte[] abyte = new byte[3]; ++ // Paper start - reuse temporary length buffer ++ byte[] abyte = lenBuf; ++ java.util.Arrays.fill(abyte, (byte) 0); ++ // Paper end + + for (int i = 0; i < abyte.length; ++i) { + if (!bytebuf.isReadable()) { +diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java +index b644c91cecd8a347319dfe8c8923fd05919a9795..4c583593de4dc8ab27b3e1187f4dfe1740ef07a7 100644 +--- a/src/main/java/net/minecraft/network/protocol/Packet.java ++++ b/src/main/java/net/minecraft/network/protocol/Packet.java +@@ -2,8 +2,10 @@ package net.minecraft.network.protocol; + + import io.netty.channel.ChannelFuture; // Paper + import java.io.IOException; ++import net.minecraft.network.NetworkManager; + import net.minecraft.network.PacketDataSerializer; + import net.minecraft.network.PacketListener; ++import net.minecraft.server.level.EntityPlayer; + + public interface Packet { + +diff --git a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java +index e47da20ab8ce4da34755e105bf55d8542fb50138..67d8fe8ad036a9252c774bb6a914c8ec79981876 100644 +--- a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java ++++ b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java +@@ -1,6 +1,9 @@ + package net.minecraft.network.protocol; + ++import net.minecraft.network.NetworkManager; + import net.minecraft.network.PacketListener; ++import net.minecraft.network.chat.ChatComponentText; ++import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; + import net.minecraft.server.CancelledPacketHandleException; + import net.minecraft.server.level.WorldServer; + import net.minecraft.util.thread.IAsyncTaskHandler; +@@ -31,6 +34,21 @@ public class PlayerConnectionUtils { + try (Timing ignored = timing.startTiming()) { // Paper - timings + packet.a(t0); + } // Paper - timings ++ // Paper start ++ catch (Exception e) { ++ NetworkManager networkmanager = t0.a(); ++ if (networkmanager.getPlayer() != null) { ++ LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getName(), networkmanager.getSocketAddress(), e); ++ } else { ++ LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getSocketAddress(), e); ++ } ++ ChatComponentText error = new ChatComponentText("Packet processing error"); ++ networkmanager.sendPacket(new PacketPlayOutKickDisconnect(error), (future) -> { ++ networkmanager.close(error); ++ }); ++ networkmanager.stopReading(); ++ } ++ // Paper end + } else { + PlayerConnectionUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); + } diff --git a/patches/server-unmapped/0526-Fix-Concurrency-issue-in-WeightedList.patch b/patches/server-unmapped/0526-Fix-Concurrency-issue-in-WeightedList.patch new file mode 100644 index 0000000000..650fc02cf8 --- /dev/null +++ b/patches/server-unmapped/0526-Fix-Concurrency-issue-in-WeightedList.patch @@ -0,0 +1,148 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 6 Jul 2020 18:36:41 -0400 +Subject: [PATCH] Fix Concurrency issue in WeightedList + +if multiple threads from worldgen sort at same time, it will crash. +So make a copy of the list for sorting purposes. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java +index dc926f7e59fa350902d4a24aefc3df3eac7d75db..2d4345de154fb2d31f34695672ebdb4dac31b181 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java +@@ -17,7 +17,7 @@ public class BehaviorGate extends Behavior { + private final Set> b; + private final BehaviorGate.Order c; + private final BehaviorGate.Execution d; +- private final WeightedList> e = new WeightedList<>(); ++ private final WeightedList> e = new WeightedList<>(false); // Paper - don't use a clone + + public BehaviorGate(Map, MemoryStatus> map, Set> set, BehaviorGate.Order behaviorgate_order, BehaviorGate.Execution behaviorgate_execution, List, Integer>> list) { + super(map); +@@ -65,10 +65,9 @@ public class BehaviorGate extends Behavior { + }).forEach((behavior) -> { + behavior.g(worldserver, e0, i); + }); +- Set set = this.b; + BehaviorController behaviorcontroller = e0.getBehaviorController(); + +- set.forEach(behaviorcontroller::removeMemory); ++ this.b.forEach(behaviorcontroller::removeMemory); // Paper - decomp fix + } + + @Override +@@ -115,7 +114,7 @@ public class BehaviorGate extends Behavior { + + private final Consumer> c; + +- private Order(Consumer consumer) { ++ private Order(Consumer> consumer) { // Paper - decomp fix + this.c = consumer; + } + +diff --git a/src/main/java/net/minecraft/util/random/WeightedRandomList.java b/src/main/java/net/minecraft/util/random/WeightedRandomList.java +index f6f8c68ff3642e28901094e8b501fcf8ec2cecd7..1ca9b0595ae9d914d23590ec0b0c2e857c39b250 100644 +--- a/src/main/java/net/minecraft/util/random/WeightedRandomList.java ++++ b/src/main/java/net/minecraft/util/random/WeightedRandomList.java +@@ -6,7 +6,7 @@ import com.mojang.serialization.Codec; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import com.mojang.serialization.DynamicOps; +-import com.mojang.serialization.OptionalDynamic; ++ + import java.util.Comparator; + import java.util.List; + import java.util.Random; +@@ -14,26 +14,32 @@ import java.util.stream.Stream; + + public class WeightedList { + +- protected final List> a; ++ protected final List> list; // Paper - decompile conflict + private final Random b; ++ private final boolean isUnsafe; // Paper + +- public WeightedList() { +- this(Lists.newArrayList()); ++ // Paper start - add useClone option ++ public WeightedList() { this(true); } ++ public WeightedList(boolean isUnsafe) { ++ this(Lists.newArrayList(), isUnsafe); + } + +- private WeightedList(List> list) { ++ private WeightedList(List> list) { this(list, true); } ++ private WeightedList(List> list, boolean isUnsafe) { ++ this.isUnsafe = isUnsafe; ++ // Paper end + this.b = new Random(); +- this.a = Lists.newArrayList(list); ++ this.list = Lists.newArrayList(list); // Paper - decompile conflict + } + + public static Codec> a(Codec codec) { +- return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { +- return weightedlist.a; ++ return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { // Paper - decompile conflict ++ return weightedlist.list; // Paper - decompile conflict + }); + } + + public WeightedList a(U u0, int i) { +- this.a.add(new WeightedList.a<>(u0, i)); ++ this.list.add(new WeightedList.a<>(u0, i)); // Paper - decompile conflict + return this; + } + +@@ -42,21 +48,20 @@ public class WeightedList { + } + + public WeightedList a(Random random) { +- this.a.forEach((weightedlist_a) -> { +- weightedlist_a.a(random.nextFloat()); +- }); +- this.a.sort(Comparator.comparingDouble((object) -> { +- return ((WeightedList.a) object).c(); +- })); +- return this; ++ // Paper start - make concurrent safe, work off a clone of the list ++ List> list = isUnsafe ? new java.util.ArrayList>(this.list) : this.list; ++ list.forEach((weightedlist_a) -> weightedlist_a.a(random.nextFloat())); ++ list.sort(Comparator.comparingDouble(a::c)); ++ return isUnsafe ? new WeightedList<>(list, isUnsafe) : this; ++ // Paper end + } + + public boolean b() { +- return this.a.isEmpty(); ++ return this.list.isEmpty(); // Paper - decompile conflict + } + + public Stream c() { +- return this.a.stream().map(WeightedList.a::a); ++ return this.list.stream().map(WeightedList.a::a); // Paper - decompile conflict + } + + public U b(Random random) { +@@ -64,7 +69,7 @@ public class WeightedList { + } + + public String toString() { +- return "WeightedList[" + this.a + "]"; ++ return "WeightedList[" + this.list + "]"; // Paper - decompile conflict + } + + public static class a { +@@ -98,11 +103,7 @@ public class WeightedList { + return new Codec>() { + public DataResult, T>> decode(DynamicOps dynamicops, T t0) { + Dynamic dynamic = new Dynamic(dynamicops, t0); +- OptionalDynamic optionaldynamic = dynamic.get("data"); +- Codec codec1 = codec; +- +- codec.getClass(); +- return optionaldynamic.flatMap(codec1::parse).map((object) -> { ++ return dynamic.get("data").flatMap(codec::parse).map((object) -> { // Paper - decompile error + return new WeightedList.a<>(object, dynamic.get("weight").asInt(1)); + }).map((weightedlist_a) -> { + return Pair.of(weightedlist_a, dynamicops.empty()); diff --git a/patches/server-unmapped/0527-Optimize-the-advancement-data-player-iteration-to-be.patch b/patches/server-unmapped/0527-Optimize-the-advancement-data-player-iteration-to-be.patch new file mode 100644 index 0000000000..434cd1b5f5 --- /dev/null +++ b/patches/server-unmapped/0527-Optimize-the-advancement-data-player-iteration-to-be.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Wyatt Childers +Date: Sat, 4 Jul 2020 23:07:43 -0400 +Subject: [PATCH] Optimize the advancement data player iteration to be O(N) + rather than O(N^2) + + +diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java +index 7d37626277823d5db05189c20bb1ebf91aa2a286..e1d3f7e63c731f9376900a86abe17282e9b55ded 100644 +--- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java ++++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java +@@ -457,6 +457,16 @@ public class AdvancementDataPlayer { + } + + private void e(Advancement advancement) { ++ // Paper start ++ e(advancement, IterationEntryPoint.ROOT); ++ } ++ private enum IterationEntryPoint { ++ ROOT, ++ ITERATOR, ++ PARENT_OF_ITERATOR ++ } ++ private void e(Advancement advancement, IterationEntryPoint entryPoint) { ++ // Paper end + boolean flag = this.f(advancement); + boolean flag1 = this.h.contains(advancement); + +@@ -472,15 +482,23 @@ public class AdvancementDataPlayer { + } + + if (flag != flag1 && advancement.b() != null) { +- this.e(advancement.b()); ++ // Paper start - If we're not coming from an iterator consider this to be a root entry, otherwise ++ // market that we're entering from the parent of an iterator. ++ this.e(advancement.b(), entryPoint == IterationEntryPoint.ITERATOR ? IterationEntryPoint.PARENT_OF_ITERATOR : IterationEntryPoint.ROOT); + } + ++ // If this is true, we've went through a child iteration, entered the parent, processed the parent ++ // and are about to reprocess the children. Stop processing here to prevent O(N^2) processing. ++ if (entryPoint == IterationEntryPoint.PARENT_OF_ITERATOR) { ++ return; ++ } // Paper end ++ + Iterator iterator = advancement.e().iterator(); + + while (iterator.hasNext()) { + Advancement advancement1 = (Advancement) iterator.next(); + +- this.e(advancement1); ++ this.e(advancement1, IterationEntryPoint.ITERATOR); // Paper - Mark this call as being from iteration + } + + } diff --git a/patches/server-unmapped/0528-Fix-arrows-never-despawning-MC-125757.patch b/patches/server-unmapped/0528-Fix-arrows-never-despawning-MC-125757.patch new file mode 100644 index 0000000000..384b4e0382 --- /dev/null +++ b/patches/server-unmapped/0528-Fix-arrows-never-despawning-MC-125757.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Wed, 8 Jul 2020 11:24:30 -0500 +Subject: [PATCH] Fix arrows never despawning MC-125757 + +This forces the despawn counter to start ticking regardless of +state after the arrow has been alive for 200 ticks (10 seconds) +instead of getting stuck in a never despawn state (bubble columns, +etc). + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +index ce754e0da047050daa08e5e0564fa399d334c04b..b0e8e9934edbb0cf7ac063e4903452be526afbc7 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java +@@ -171,6 +171,7 @@ public abstract class EntityArrow extends IProjectile { + + ++this.c; + } else { ++ if (ticksLived > 200) this.tickDespawnCounter(); // Paper - tick despawnCounter regardless after 10 seconds + this.c = 0; + Vec3D vec3d2 = this.getPositionVector(); + +@@ -292,6 +293,7 @@ public abstract class EntityArrow extends IProjectile { + + } + ++ protected final void tickDespawnCounter() { this.h(); } // Paper - OBFHELPER + protected void h() { + ++this.despawnCounter; + if (this.despawnCounter >= (fromPlayer == PickupStatus.CREATIVE_ONLY ? world.paperConfig.creativeArrowDespawnRate : (fromPlayer == PickupStatus.DISALLOWED ? world.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof EntityThrownTrident) ? world.spigotConfig.tridentDespawnRate : world.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? diff --git a/patches/server-unmapped/0529-Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server-unmapped/0529-Thread-Safe-Vanilla-Command-permission-checking.patch new file mode 100644 index 0000000000..2786d49de2 --- /dev/null +++ b/patches/server-unmapped/0529-Thread-Safe-Vanilla-Command-permission-checking.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 11 Jul 2020 03:54:28 -0400 +Subject: [PATCH] Thread Safe Vanilla Command permission checking + +Datapacks check this on load and are built concurrently. This was breaking them badly due +to race conditions. + +Plus, .canUse we want to be safe for async anyways. + +diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +index 7ef6c99d2235eed38197aa76bc9553d7efbe52a4..c0fac7369b111e65b896a15848ae22457e5e8914 100644 +--- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java ++++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java +@@ -75,10 +75,10 @@ public abstract class CommandNode implements Comparable> { + public synchronized boolean canUse(final S source) { + if (source instanceof CommandListenerWrapper) { + try { +- ((CommandListenerWrapper) source).currentCommand = this; ++ ((CommandListenerWrapper) source).currentCommand.set(this); // Paper + return requirement.test(source); + } finally { +- ((CommandListenerWrapper) source).currentCommand = null; ++ ((CommandListenerWrapper) source).currentCommand.set(null); // Paper + } + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java +index b5ee789c8dfb7f413ab60902ff3d2ef0cf8273cd..8402af32cc476d7f468842eb4f34c7521d72bcc8 100644 +--- a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java ++++ b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java +@@ -55,7 +55,7 @@ public class CommandListenerWrapper implements ICompletionProvider, com.destroys + private final ResultConsumer l; + private final ArgumentAnchor.Anchor m; + private final Vec2F n; +- public volatile CommandNode currentCommand; // CraftBukkit ++ public ThreadLocal currentCommand = new ThreadLocal<>(); // CraftBukkit // Paper + + public CommandListenerWrapper(ICommandListener icommandlistener, Vec3D vec3d, Vec2F vec2f, WorldServer worldserver, int i, String s, IChatBaseComponent ichatbasecomponent, MinecraftServer minecraftserver, @Nullable Entity entity) { + this(icommandlistener, vec3d, vec2f, worldserver, i, s, ichatbasecomponent, minecraftserver, entity, false, (commandcontext, flag, j) -> { +@@ -172,9 +172,11 @@ public class CommandListenerWrapper implements ICompletionProvider, com.destroys + @Override + public boolean hasPermission(int i) { + // CraftBukkit start +- CommandNode currentCommand = this.currentCommand; ++ // Paper start - fix concurrency issue ++ CommandNode currentCommand = this.currentCommand.get(); + if (currentCommand != null) { + return hasPermission(i, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); ++ // Paper end + } + // CraftBukkit end + diff --git a/patches/server-unmapped/0530-Move-range-check-for-block-placing-up.patch b/patches/server-unmapped/0530-Move-range-check-for-block-placing-up.patch new file mode 100644 index 0000000000..d87d776d17 --- /dev/null +++ b/patches/server-unmapped/0530-Move-range-check-for-block-placing-up.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Jul 2020 19:34:11 -0700 +Subject: [PATCH] Move range check for block placing up + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index a25edac931db8c737c81962bf69233b547d038c7..8f3dd1493f3a8121376f79632b3941cf642219a7 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1663,15 +1663,19 @@ public class PlayerConnection implements PacketListenerPlayIn { + BlockPosition blockposition = movingobjectpositionblock.getBlockPosition(); + EnumDirection enumdirection = movingobjectpositionblock.getDirection(); + ++ // Paper start - move check up ++ Location eyeLoc = this.getPlayer().getEyeLocation(); ++ double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); ++ if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { ++ return; ++ } ++ // Paper end - move check up ++ + this.player.resetIdleTimer(); + if (blockposition.getY() < this.minecraftServer.getMaxBuildHeight()) { + if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.a((EntityHuman) this.player, blockposition)) { + // CraftBukkit start - Check if we can actually do something over this large a distance +- Location eyeLoc = this.getPlayer().getEyeLocation(); +- double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); +- if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { +- return; +- } ++ // Paper - move check up + this.player.clearActiveItem(); // SPIGOT-4706 + // CraftBukkit end + EnumInteractionResult enuminteractionresult = this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); diff --git a/patches/server-unmapped/0531-Fix-SPIGOT-5989.patch b/patches/server-unmapped/0531-Fix-SPIGOT-5989.patch new file mode 100644 index 0000000000..06e7d808b5 --- /dev/null +++ b/patches/server-unmapped/0531-Fix-SPIGOT-5989.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 15 Jul 2020 21:42:52 -0400 +Subject: [PATCH] Fix SPIGOT-5989 + +Before this fix, if a player was respawning to a respawn anchor and +the respawn location was modified away from the anchor with the +PlayerRespawnEvent, the anchor would still lose some charge. +This fixes that by checking if the modified spawn location is +still at a respawn anchor. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 34b45a6818209245fa5692a83cf4143030057095..7f5311770f0a461f02039255fbbf1a48df4178f3 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -83,6 +83,7 @@ import net.minecraft.world.level.EnumGamemode; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.World; + import net.minecraft.world.level.biome.BiomeManager; ++import net.minecraft.world.level.block.BlockRespawnAnchor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.border.IWorldBorderListener; +@@ -850,6 +851,7 @@ public abstract class PlayerList { + // Paper start + boolean isBedSpawn = false; + boolean isRespawn = false; ++ boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 + // Paper end + + // CraftBukkit start - fire PlayerRespawnEvent +@@ -860,7 +862,7 @@ public abstract class PlayerList { + Optional optional; + + if (blockposition != null) { +- optional = EntityHuman.getBed(worldserver1, blockposition, f, flag1, flag); ++ optional = EntityHuman.getBed(worldserver1, blockposition, f, flag1, true); // Paper - Fix SPIGOT-5989 + } else { + optional = Optional.empty(); + } +@@ -903,7 +905,12 @@ public abstract class PlayerList { + } + // Spigot End + +- location = respawnEvent.getRespawnLocation(); ++ // Paper start - Fix SPIGOT-5989 ++ if (!location.equals(respawnEvent.getRespawnLocation()) ) { ++ location = respawnEvent.getRespawnLocation(); ++ isLocAltered = true; ++ } ++ // Paper end + if (!flag) entityplayer.reset(); // SPIGOT-4785 + isRespawn = true; // Paper + } else { +@@ -941,8 +948,12 @@ public abstract class PlayerList { + } + // entityplayer1.syncInventory(); + entityplayer1.setHealth(entityplayer1.getHealth()); +- if (flag2) { +- entityplayer1.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.BLOCK_RESPAWN_ANCHOR_DEPLETE, SoundCategory.BLOCKS, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 1.0F, 1.0F)); ++ // Paper start - Fix SPIGOT-5989 ++ if (flag2 && !isLocAltered) { ++ IBlockData data = worldserver1.getType(blockposition); ++ worldserver1.setTypeAndData(blockposition, data.set(BlockRespawnAnchor.a, data.get(BlockRespawnAnchor.a) - 1), 3); ++ entityplayer1.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.BLOCK_RESPAWN_ANCHOR_DEPLETE, SoundCategory.BLOCKS, (double) location.getX(), (double) location.getY(), (double) location.getZ(), 1.0F, 1.0F)); ++ // Paper end + } + // Added from changeDimension + updateClient(entityplayer); // Update health, etc... diff --git a/patches/server-unmapped/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/patches/server-unmapped/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch new file mode 100644 index 0000000000..c659730156 --- /dev/null +++ b/patches/server-unmapped/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 10 Jul 2020 13:12:33 -0500 +Subject: [PATCH] Fix SPIGOT-5824 Bukkit world-container is not used + + +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 1732fc552c290d294b68d6f92f2a58d985fbef21..3dcbeec94d86f3b56eaf05676b176f60d711f9cd 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -132,11 +132,20 @@ public class Main { + return; + } + +- File file = (File) optionset.valueOf("universe"); // CraftBukkit ++ // Paper start - fix SPIGOT-5824 ++ File file; ++ File userCacheFile = new File("usercache.json"); ++ if (optionset.has("universe")) { ++ file = (File) optionset.valueOf("universe"); // CraftBukkit ++ userCacheFile = new File(file, "usercache.json"); ++ } else { ++ file = new File(bukkitConfiguration.getString("settings.world-container", ".")); ++ } ++ // Paper end - fix SPIGOT-5824 + YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper + MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); + GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); +- UserCache usercache = new UserCache(gameprofilerepository, new File(file, MinecraftServer.b.getName())); ++ UserCache usercache = new UserCache(gameprofilerepository, userCacheFile); // Paper - only move usercache.json into folder if --universe is used, not world-container + // CraftBukkit start + String s = (String) Optional.ofNullable(optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); + Convertable convertable = Convertable.a(file.toPath()); diff --git a/patches/server-unmapped/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/patches/server-unmapped/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch new file mode 100644 index 0000000000..3c64f53489 --- /dev/null +++ b/patches/server-unmapped/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 10 Jul 2020 12:38:12 -0500 +Subject: [PATCH] Fix SPIGOT-5885 Unable to disable advancements + + +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 3dcbeec94d86f3b56eaf05676b176f60d711f9cd..6818f8496ab76ee6ffc747bd6848b43830ec8914 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -132,6 +132,7 @@ public class Main { + return; + } + ++ org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init + // Paper start - fix SPIGOT-5824 + File file; + File userCacheFile = new File("usercache.json"); diff --git a/patches/server-unmapped/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/patches/server-unmapped/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch new file mode 100644 index 0000000000..e8ab744e26 --- /dev/null +++ b/patches/server-unmapped/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 13 Jul 2020 06:22:54 -0700 +Subject: [PATCH] Fix AdvancementDataPlayer leak due from quitting early in + login + +Move the criterion storage to the AdvancementDataPlayer object +itself, so the criterion object stores no references - and thus +needs no cleanup. + +diff --git a/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java b/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java +index c2ee816af000f0c94782d704e6372cd93fd34bb3..c6388223daa26b200dc16cd562bcef19a5a59c8f 100644 +--- a/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java ++++ b/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java +@@ -16,25 +16,25 @@ import net.minecraft.world.level.storage.loot.LootTableInfo; + + public abstract class CriterionTriggerAbstract implements CriterionTrigger { + +- private final Map>> a = Maps.newIdentityHashMap(); ++ //private final Map>> a = Maps.newIdentityHashMap(); // Paper - moved into AdvancementDataPlayer to fix memory leak + + public CriterionTriggerAbstract() {} + + @Override + public final void a(AdvancementDataPlayer advancementdataplayer, CriterionTrigger.a criteriontrigger_a) { +- ((Set) this.a.computeIfAbsent(advancementdataplayer, (advancementdataplayer1) -> { ++ (advancementdataplayer.criterionData.computeIfAbsent(this, (advancementdataplayer1) -> { // Paper - fix AdvancementDataPlayer leak + return Sets.newHashSet(); + })).add(criteriontrigger_a); + } + + @Override + public final void b(AdvancementDataPlayer advancementdataplayer, CriterionTrigger.a criteriontrigger_a) { +- Set> set = (Set) this.a.get(advancementdataplayer); ++ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak + + if (set != null) { + set.remove(criteriontrigger_a); + if (set.isEmpty()) { +- this.a.remove(advancementdataplayer); ++ advancementdataplayer.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak + } + } + +@@ -42,7 +42,7 @@ public abstract class CriterionTriggerAbstract predicate) { + AdvancementDataPlayer advancementdataplayer = entityplayer.getAdvancementData(); +- Set> set = (Set) this.a.get(advancementdataplayer); ++ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak + + if (set != null && !set.isEmpty()) { + LootTableInfo loottableinfo = CriterionConditionEntity.b(entityplayer, entityplayer); +@@ -67,7 +67,7 @@ public abstract class CriterionTriggerAbstract> criterionData = Maps.newIdentityHashMap(); ++ // Paper end - fix advancement data player leakage ++ + public AdvancementDataPlayer(DataFixer datafixer, PlayerList playerlist, AdvancementDataWorld advancementdataworld, File file, EntityPlayer entityplayer) { + this.d = datafixer; + this.e = playerlist; diff --git a/patches/server-unmapped/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/patches/server-unmapped/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch new file mode 100644 index 0000000000..6c0360c411 --- /dev/null +++ b/patches/server-unmapped/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 26 Jul 2020 12:11:39 +0100 +Subject: [PATCH] Add missing strikeLighting call to + World#spigot()#strikeLightningEffect + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 80cd8ce4e70dbb740439ac530a7bc70a7a54cb85..74ee2013a47855cdd1d56a06a2e209776513fd14 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2627,6 +2627,7 @@ public class CraftWorld implements World { + lightning.teleportAndSync( loc.getX(), loc.getY(), loc.getZ() ); + lightning.isEffect = true; + lightning.isSilent = isSilent; ++ world.strikeLightning( lightning ); + return (LightningStrike) lightning.getBukkitEntity(); + } + }; diff --git a/patches/server-unmapped/0536-Fix-some-rails-connecting-improperly.patch b/patches/server-unmapped/0536-Fix-some-rails-connecting-improperly.patch new file mode 100644 index 0000000000..9241cffb87 --- /dev/null +++ b/patches/server-unmapped/0536-Fix-some-rails-connecting-improperly.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 24 Jul 2020 15:56:05 -0700 +Subject: [PATCH] Fix some rails connecting improperly + + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java +index 61c4a57174237f5f77d841bb2274ace6297db8a4..27573a0334b06f4b6ada672057695d8f8a2bcfc4 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java +@@ -71,6 +71,7 @@ public class BlockMinecartDetector extends BlockMinecartTrackAbstract { + + private void a(World world, BlockPosition blockposition, IBlockData iblockdata) { + if (this.canPlace(iblockdata, world, blockposition)) { ++ if (iblockdata.getBlock() != this) { return; } // Paper - not our block, don't do anything + boolean flag = (Boolean) iblockdata.get(BlockMinecartDetector.POWERED); + boolean flag1 = false; + List list = this.a(world, blockposition, EntityMinecartAbstract.class, (Predicate) null); +diff --git a/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java +index f65a53347f26affd1ce8d79527a6486e6bf8fbdd..0545dd68ea1f0a27739fac1a358c7def849e6b6a 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java +@@ -62,6 +62,7 @@ public abstract class BlockMinecartTrackAbstract extends Block { + iblockdata = this.a(world, blockposition, iblockdata, true); + if (this.c) { + iblockdata.doPhysics(world, blockposition, this, blockposition, flag); ++ iblockdata = world.getType(blockposition); // Paper - don't desync, update again + } + + return iblockdata; +diff --git a/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java b/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java +index 8a8e3af0290a9483ee59d5fab061a9a9f5613f0a..436cfcde89aa780bcd58150f6167a365d8d955bc 100644 +--- a/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java ++++ b/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java +@@ -12,13 +12,19 @@ import net.minecraft.world.level.block.state.properties.BlockPropertyTrackPositi + + public class MinecartTrackLogic { + +- private final World a; +- private final BlockPosition b; ++ private final World a; public final World getWorld() { return this.a; } // Paper - OBFHELPER ++ private final BlockPosition b; public final BlockPosition getPos() { return this.b; } // Paper - OBFHELPER + private final BlockMinecartTrackAbstract c; +- private IBlockData d; ++ private IBlockData d; public final IBlockData getRailState() { return this.d; } // Paper - OBFHELPER + private final boolean e; + private final List f = Lists.newArrayList(); + ++ // Paper start - prevent desync ++ public boolean isValid() { ++ return this.getWorld().getType(this.getPos()).getBlock() == this.getRailState().getBlock(); ++ } ++ // Paper end - prevent desync ++ + public MinecartTrackLogic(World world, BlockPosition blockposition, IBlockData iblockdata) { + this.a = world; + this.b = blockposition; +@@ -153,6 +159,11 @@ public class MinecartTrackLogic { + } + + private void c(MinecartTrackLogic minecarttracklogic) { ++ // Paper start - prevent desync ++ if (!this.isValid() || !minecarttracklogic.isValid()) { ++ return; ++ } ++ // Paper end - prevent desync + this.f.add(minecarttracklogic.b); + BlockPosition blockposition = this.b.north(); + BlockPosition blockposition1 = this.b.south(); +@@ -347,11 +358,16 @@ public class MinecartTrackLogic { + this.d = (IBlockData) this.d.set(this.c.d(), blockpropertytrackposition1); + if (flag1 || this.a.getType(this.b) != this.d) { + this.a.setTypeAndData(this.b, this.d, 3); ++ // Paper start - prevent desync ++ if (!this.isValid()) { ++ return this; ++ } ++ // Paper end - prevent desync + + for (int i = 0; i < this.f.size(); ++i) { + MinecartTrackLogic minecarttracklogic = this.b((BlockPosition) this.f.get(i)); + +- if (minecarttracklogic != null) { ++ if (minecarttracklogic != null && minecarttracklogic.isValid()) { // Paper - prevent desync + minecarttracklogic.d(); + if (minecarttracklogic.b(this)) { + minecarttracklogic.c(this); +@@ -364,6 +380,6 @@ public class MinecartTrackLogic { + } + + public IBlockData c() { +- return this.d; ++ return this.getWorld().getType(this.getPos()); // Paper - prevent desync + } + } diff --git a/patches/server-unmapped/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/patches/server-unmapped/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch new file mode 100644 index 0000000000..f274992699 --- /dev/null +++ b/patches/server-unmapped/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch @@ -0,0 +1,134 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 4 Aug 2020 22:24:15 +0200 +Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections + +I utilized the IDE to convert streams to non streams code, so shouldn't +be any risk of behavior change. Only did minor optimization of the +generated code set to remove unnecessary things. + +I expect us to just drop this patch on next major update and re-apply +it with the IDE again and re-apply the collections optimization. + +Optimize collection by creating a list instead of a set of the key and value. + +This lets us get faster foreach iteration, as well as avoids map lookups on +the values when needed. + +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java +index 5784be69098805e4d550a0923ac8daa5aada73f9..76e19f3a4ae988f6f3b59763d639fa5e084fa0bf 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java +@@ -33,9 +33,12 @@ public class Pathfinder { + this.d.a(); + this.c.a(chunkcache, entityinsentient); + PathPoint pathpoint = this.c.b(); +- Map map = (Map) set.stream().collect(Collectors.toMap((blockposition) -> { +- return this.c.a((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); +- }, Function.identity())); ++ // Paper start - remove streams - and optimize collection ++ List> map = Lists.newArrayList(); ++ for (BlockPosition blockposition : set) { ++ map.add(new java.util.AbstractMap.SimpleEntry<>(this.c.a((double) blockposition.getX(), blockposition.getY(), blockposition.getZ()), blockposition)); ++ } ++ // Paper end + PathEntity pathentity = this.a(pathpoint, map, f, i, f1); + + this.c.a(); +@@ -43,17 +46,17 @@ public class Pathfinder { + } + + @Nullable +- private PathEntity a(PathPoint pathpoint, Map map, float f, int i, float f1) { +- Set set = map.keySet(); ++ private PathEntity a(PathPoint pathpoint, List> list, float f, int i, float f1) { // Paper - optimize collection ++ //Set set = map.keySet(); // Paper + + pathpoint.e = 0.0F; +- pathpoint.f = this.a(pathpoint, set); ++ pathpoint.f = this.a(pathpoint, list); // Paper - optimize collection + pathpoint.g = pathpoint.f; + this.d.a(); + this.d.a(pathpoint); + Set set1 = ImmutableSet.of(); + int j = 0; +- Set set2 = Sets.newHashSetWithExpectedSize(set.size()); ++ List> set2 = Lists.newArrayListWithExpectedSize(list.size()); // Paper - optimize collection + int k = (int) ((float) this.b * f1); + + while (!this.d.e()) { +@@ -65,14 +68,15 @@ public class Pathfinder { + PathPoint pathpoint1 = this.d.c(); + + pathpoint1.i = true; +- Iterator iterator = set.iterator(); +- +- while (iterator.hasNext()) { +- PathDestination pathdestination = (PathDestination) iterator.next(); ++ // Paper start - optimize collection ++ for (int i1 = 0; i1 < list.size(); i1++) { ++ Map.Entry entry = list.get(i1); ++ PathDestination pathdestination = entry.getKey(); + + if (pathpoint1.c((PathPoint) pathdestination) <= (float) i) { + pathdestination.e(); +- set2.add(pathdestination); ++ set2.add(entry); ++ // Paper end + } + } + +@@ -93,7 +97,7 @@ public class Pathfinder { + if (pathpoint2.j < f && (!pathpoint2.c() || f3 < pathpoint2.e)) { + pathpoint2.h = pathpoint1; + pathpoint2.e = f3; +- pathpoint2.f = this.a(pathpoint2, set) * 1.5F; ++ pathpoint2.f = this.a(pathpoint2, list) * 1.5F; // Paper - list instead of set + if (pathpoint2.c()) { + this.d.a(pathpoint2, pathpoint2.e + pathpoint2.f); + } else { +@@ -105,28 +109,29 @@ public class Pathfinder { + } + } + +- Optional optional = !set2.isEmpty() ? set2.stream().map((pathdestination1) -> { +- return this.a(pathdestination1.d(), (BlockPosition) map.get(pathdestination1), true); +- }).min(Comparator.comparingInt(PathEntity::e)) : set.stream().map((pathdestination1) -> { +- return this.a(pathdestination1.d(), (BlockPosition) map.get(pathdestination1), false); +- }).min(Comparator.comparingDouble(PathEntity::n).thenComparingInt(PathEntity::e)); +- +- if (!optional.isPresent()) { +- return null; +- } else { +- PathEntity pathentity = (PathEntity) optional.get(); +- +- return pathentity; ++ // Paper start - remove streams - and optimize collection ++ PathEntity best = null; ++ boolean useSet1 = set2.isEmpty(); ++ Comparator comparator = useSet1 ? Comparator.comparingInt(PathEntity::e) ++ : Comparator.comparingDouble(PathEntity::n).thenComparingInt(PathEntity::e); ++ for (Map.Entry entry : useSet1 ? list : set2) { ++ PathEntity pathEntity = this.a(entry.getKey().d(), entry.getValue(), !useSet1); ++ if (best == null || comparator.compare(pathEntity, best) < 0) ++ best = pathEntity; + } ++ return best; ++ // Paper end + } + +- private float a(PathPoint pathpoint, Set set) { ++ private float a(PathPoint pathpoint, List> list) { // Paper - optimize collection + float f = Float.MAX_VALUE; + + float f1; + +- for (Iterator iterator = set.iterator(); iterator.hasNext(); f = Math.min(f1, f)) { +- PathDestination pathdestination = (PathDestination) iterator.next(); ++ // Paper start - optimize collection ++ for (int i = 0, listSize = list.size(); i < listSize; f = Math.min(f1, f), i++) { // Paper ++ PathDestination pathdestination = list.get(i).getKey(); // Paper ++ // Paper end + + f1 = pathpoint.a(pathdestination); + pathdestination.a(f1, pathpoint); diff --git a/patches/server-unmapped/0538-Incremental-player-saving.patch b/patches/server-unmapped/0538-Incremental-player-saving.patch new file mode 100644 index 0000000000..a7deadb443 --- /dev/null +++ b/patches/server-unmapped/0538-Incremental-player-saving.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 9 Aug 2020 08:59:25 +0300 +Subject: [PATCH] Incremental player saving + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index b67ba8f75e4a3358d7c2462918b85b0bf9b5a922..fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -440,4 +440,15 @@ public class PaperConfig { + allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); + set("settings.unsupported-settings.allow-tnt-duplication", null); + } ++ ++ public static int playerAutoSaveRate = -1; ++ public static int maxPlayerAutoSavePerTick = 10; ++ private static void playerAutoSaveRate() { ++ playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1); ++ maxPlayerAutoSavePerTick = getInt("settings.max-player-auto-save-per-tick", -1); ++ if (maxPlayerAutoSavePerTick == -1) { // -1 Automatic / "Recommended" ++ // 10 should be safe for everyone unless you mass spamming player auto save ++ maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index afdbbe62eba7b4f0ad63c5126c6d21488c4e9a7a..5acc6cfa96084728f45cfbec0ff9571e5dd0b844 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1349,9 +1349,15 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down + //MinecraftServer.LOGGER.debug("Autosave started"); // Paper + serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper ++ // Paper start ++ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate; ++ if (playerSaveInterval < 0) { ++ playerSaveInterval = autosavePeriod; ++ } ++ // Paper end + this.methodProfiler.enter("save"); +- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper +- this.playerList.savePlayers(); ++ if (playerSaveInterval > 0) { // Paper ++ this.playerList.savePlayers(playerSaveInterval); // Paper + }// Paper + // Paper start + for (WorldServer world : getWorlds()) { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 8055172c806f285aa9a9e6de681d03b008fbf785..3908dc27a5cf127ab3c3630da47318da1bf4e3c9 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -176,6 +176,7 @@ import org.bukkit.inventory.MainHand; + public class EntityPlayer extends EntityHuman implements ICrafting { + + private static final Logger LOGGER = LogManager.getLogger(); ++ public long lastSave = MinecraftServer.currentTick; // Paper + public PlayerConnection playerConnection; + public NetworkManager networkManager; // Paper + public final MinecraftServer server; +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 7f5311770f0a461f02039255fbbf1a48df4178f3..d3f3dc4ad2c758482b7a8d5c07caa526ce1e3424 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -563,6 +563,7 @@ public abstract class PlayerList { + protected void savePlayerFile(EntityPlayer entityplayer) { + if (!entityplayer.getBukkitEntity().isPersistent()) return; // CraftBukkit + if (!entityplayer.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) ++ entityplayer.lastSave = MinecraftServer.currentTick; // Paper + this.playerFileData.save(entityplayer); + ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) entityplayer.getStatisticManager(); // CraftBukkit + +@@ -1222,10 +1223,21 @@ public abstract class PlayerList { + } + + public void savePlayers() { ++ // Paper start - incremental player saving ++ savePlayers(null); ++ } ++ public void savePlayers(Integer interval) { + MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main + MinecraftTimings.savePlayers.startTiming(); // Paper ++ int numSaved = 0; ++ long now = MinecraftServer.currentTick; + for (int i = 0; i < this.players.size(); ++i) { +- this.savePlayerFile((EntityPlayer) this.players.get(i)); ++ EntityPlayer entityplayer = this.players.get(i); ++ if (interval == null || now - entityplayer.lastSave >= interval) { ++ this.savePlayerFile(entityplayer); ++ if (interval != null && ++numSaved <= com.destroystokyo.paper.PaperConfig.maxPlayerAutoSavePerTick) { break; } ++ } ++ // Paper end + } + MinecraftTimings.savePlayers.stopTiming(); // Paper + return null; }); // Paper - ensure main diff --git a/patches/server-unmapped/0539-Import-fastutil-classes.patch b/patches/server-unmapped/0539-Import-fastutil-classes.patch new file mode 100644 index 0000000000..a367d82509 --- /dev/null +++ b/patches/server-unmapped/0539-Import-fastutil-classes.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 12 Aug 2020 11:33:04 +0200 +Subject: [PATCH] Import fastutil classes + + +diff --git a/src/main/java/net/minecraft/network/syncher/DataWatcher.java b/src/main/java/net/minecraft/network/syncher/DataWatcher.java +index 3cdae5409989ea4bad8311b0083517b7815caae1..bb09b7be91b488ebc336b2b6f5deafc0ccab27a4 100644 +--- a/src/main/java/net/minecraft/network/syncher/DataWatcher.java ++++ b/src/main/java/net/minecraft/network/syncher/DataWatcher.java +@@ -17,6 +17,7 @@ import net.minecraft.CrashReportSystemDetails; + import net.minecraft.ReportedException; + import net.minecraft.network.PacketDataSerializer; + import net.minecraft.world.entity.Entity; ++import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; // Paper + import org.apache.commons.lang3.ObjectUtils; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -26,7 +27,7 @@ public class DataWatcher { + private static final Logger LOGGER = LogManager.getLogger(); + private static final Map, Integer> b = Maps.newHashMap(); + private final Entity entity; +- private final it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap> entries = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL ++ private final Int2ObjectOpenHashMap> entries = new Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL + // private final ReadWriteLock lock = new ReentrantReadWriteLock(); // Spigot - not required + private boolean f = true; + private boolean g; diff --git a/patches/server-unmapped/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch b/patches/server-unmapped/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch new file mode 100644 index 0000000000..c694cf5898 --- /dev/null +++ b/patches/server-unmapped/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Fri, 14 Aug 2020 23:41:19 +0200 +Subject: [PATCH] Don't mark null chunk sections for block updates + + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index d6a5a0b17308913a5efd97cd27fabd0825ef68c6..00cebd33101916f29bbc192d531ac0fba31e037b 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -450,6 +450,7 @@ public class PlayerChunk { + this.a(world, blockposition, iblockdata); + } else { + ChunkSection chunksection = chunk.getSections()[sectionposition.getY()]; ++ if (chunksection == null) chunksection = new ChunkSection(sectionposition.getY(), chunk, world, true); // Paper - make a new chunk section if none was found + PacketPlayOutMultiBlockChange packetplayoutmultiblockchange = new PacketPlayOutMultiBlockChange(sectionposition, shortset, chunksection, this.x); + + this.a(packetplayoutmultiblockchange, false); diff --git a/patches/server-unmapped/0541-Remove-armour-stand-double-add-to-world.patch b/patches/server-unmapped/0541-Remove-armour-stand-double-add-to-world.patch new file mode 100644 index 0000000000..835c6e761b --- /dev/null +++ b/patches/server-unmapped/0541-Remove-armour-stand-double-add-to-world.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Fri, 14 Aug 2020 23:59:26 +0200 +Subject: [PATCH] Remove armour stand double add to world + + +diff --git a/src/main/java/net/minecraft/world/item/ItemArmorStand.java b/src/main/java/net/minecraft/world/item/ItemArmorStand.java +index dd0dc2a321f2f99cbf1060e47deec0f690d6b948..cd46df5485ebfd597ea72360a27872d46174ee19 100644 +--- a/src/main/java/net/minecraft/world/item/ItemArmorStand.java ++++ b/src/main/java/net/minecraft/world/item/ItemArmorStand.java +@@ -53,7 +53,7 @@ public class ItemArmorStand extends Item { + return EnumInteractionResult.FAIL; + } + +- worldserver.addAllEntities(entityarmorstand); ++ // Paper - moved down + float f = (float) MathHelper.d((MathHelper.g(itemactioncontext.h() - 180.0F) + 22.5F) / 45.0F) * 45.0F; + + entityarmorstand.setPositionRotation(entityarmorstand.locX(), entityarmorstand.locY(), entityarmorstand.locZ(), f, 0.0F); +@@ -63,7 +63,7 @@ public class ItemArmorStand extends Item { + return EnumInteractionResult.FAIL; + } + // CraftBukkit end +- world.addEntity(entityarmorstand); ++ worldserver.addAllEntities(entityarmorstand); // Paper - moved down + world.playSound((EntityHuman) null, entityarmorstand.locX(), entityarmorstand.locY(), entityarmorstand.locZ(), SoundEffects.ENTITY_ARMOR_STAND_PLACE, SoundCategory.BLOCKS, 0.75F, 0.8F); + } + diff --git a/patches/server-unmapped/0542-Fix-MC-187716-Use-configured-height.patch b/patches/server-unmapped/0542-Fix-MC-187716-Use-configured-height.patch new file mode 100644 index 0000000000..ba23e86875 --- /dev/null +++ b/patches/server-unmapped/0542-Fix-MC-187716-Use-configured-height.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 15 Aug 2020 08:04:49 -0500 +Subject: [PATCH] Fix MC-187716 Use configured height + + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java +index 9efe3a1dc5da760f0d8b0b39a10e642a53321aa5..ea2b107cddc7c9a6e8b8a0590e3b22a9cd7e34a6 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java +@@ -36,7 +36,7 @@ public class WorldGenSurfaceNether extends WorldGenSurface= 0; --k2) { ++ for (int k2 = k; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height + blockposition_mutableblockposition.d(k1, k2, l1); + IBlockData iblockdata4 = ichunkaccess.getType(blockposition_mutableblockposition); + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java +index 22926296e66866c7fca13466004c20a16e94dc47..b9523f5611b5b8d786fddcc5fd265e8a2043ab6c 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java +@@ -44,7 +44,7 @@ public abstract class WorldGenSurfaceNetherAbstract extends WorldGenSurface= 0; --k2) { ++ for (int k2 = k; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height + blockposition_mutableblockposition.d(k1, k2, l1); + IBlockData iblockdata5 = ichunkaccess.getType(blockposition_mutableblockposition); + int l2; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java +index 3bd78b0fc75a536e4e37f5ac67843ff778cd1b5f..a2abfc8816f2dad6c95aa89b443af0d3dec480aa 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java +@@ -34,7 +34,7 @@ public class WorldGenSurfaceNetherForest extends WorldGenSurface= 0; --k2) { ++ for (int k2 = k; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height + blockposition_mutableblockposition.d(k1, k2, l1); + IBlockData iblockdata3 = worldgensurfaceconfigurationbase.a(); + IBlockData iblockdata4 = ichunkaccess.getType(blockposition_mutableblockposition); diff --git a/patches/server-unmapped/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/patches/server-unmapped/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch new file mode 100644 index 0000000000..fb98e08a74 --- /dev/null +++ b/patches/server-unmapped/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: mbax +Date: Mon, 17 Aug 2020 12:17:37 -0400 +Subject: [PATCH] Fix regex mistake in CB NBT int deserialization + +The existing regex is too open and allows for the absence of any actual +number data, detecting an NBT entry of just the letter "i" in upper or +lower case. This causes a single-character NBT entry to be processed as +an integer ending in "i", passing an empty String to to Integer.parseInt, +triggering an exception in loading the item. + +This commit forces numbers to be present prior to the ending "i" +letter. + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java +index 1c5d62abcb968c2a60034e717aeb6d0df6548b92..83985a5aed4db54880c16228990abb3e495b079a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java +@@ -19,7 +19,7 @@ import net.minecraft.nbt.NBTTagString; + public class CraftNBTTagConfigSerializer { + + private static final Pattern ARRAY = Pattern.compile("^\\[.*]"); +- private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)?i", Pattern.CASE_INSENSITIVE); ++ private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)i", Pattern.CASE_INSENSITIVE); // Paper - fix regex + private static final Pattern DOUBLE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", Pattern.CASE_INSENSITIVE); + private static final MojangsonParser MOJANGSON_PARSER = new MojangsonParser(new StringReader("")); + diff --git a/patches/server-unmapped/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server-unmapped/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch new file mode 100644 index 0000000000..1848cd99d4 --- /dev/null +++ b/patches/server-unmapped/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 23 Jul 2019 20:44:47 -0500 +Subject: [PATCH] Do not let the server load chunks from newer versions + +If the server attempts to load a chunk generated by a newer version of +the game, immediately stop the server to prevent data corruption. + +You can override this functionality at your own peril. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index 8e4924cd649c350520cba54a0e1497d5acf089ff..2e5221bc1b9e260e33f2cef2653dc59d05e2680d 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -95,10 +95,24 @@ public class ChunkRegionLoader { + return holder.protoChunk; + } + ++ // Paper start ++ private static final int CURRENT_DATA_VERSION = SharedConstants.getGameVersion().getWorldVersion(); ++ private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion"); ++ // Paper end ++ + public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) { + ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); + // Paper end + ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); ++ // Paper start - Do NOT attempt to load chunks saved with newer versions ++ if (nbttagcompound.hasKeyOfType("DataVersion", 99)) { ++ int dataVersion = nbttagcompound.getInt("DataVersion"); ++ if (!JUST_CORRUPT_IT && dataVersion > CURRENT_DATA_VERSION) { ++ new RuntimeException("Server attempted to load chunk saved with newer version of minecraft! " + dataVersion + " > " + CURRENT_DATA_VERSION).printStackTrace(); ++ System.exit(1); ++ } ++ } ++ // Paper end + WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); + NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate + ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate diff --git a/patches/server-unmapped/0545-Brand-support.patch b/patches/server-unmapped/0545-Brand-support.patch new file mode 100644 index 0000000000..eb075ada53 --- /dev/null +++ b/patches/server-unmapped/0545-Brand-support.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DigitalRegent +Date: Sat, 11 Apr 2020 13:10:58 +0200 +Subject: [PATCH] Brand support + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 8f3dd1493f3a8121376f79632b3941cf642219a7..d3449dc9eeba0d8022c3a7b0280eaffcd42e7265 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -5,6 +5,7 @@ import com.google.common.primitives.Doubles; + import com.google.common.primitives.Floats; + import com.mojang.brigadier.ParseResults; + import com.mojang.brigadier.StringReader; ++import io.netty.buffer.Unpooled; + import io.netty.util.concurrent.Future; + import io.netty.util.concurrent.GenericFutureListener; + import it.unimi.dsi.fastutil.ints.Int2ShortMap; +@@ -37,6 +38,7 @@ import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.nbt.NBTTagList; + import net.minecraft.nbt.NBTTagString; + import net.minecraft.network.NetworkManager; ++import net.minecraft.network.PacketDataSerializer; + import net.minecraft.network.chat.ChatComponentText; + import net.minecraft.network.chat.ChatMessage; + import net.minecraft.network.chat.ChatMessageType; +@@ -260,6 +262,8 @@ public class PlayerConnection implements PacketListenerPlayIn { + private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); + private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit + ++ private String clientBrandName = null; // Paper - Brand name ++ + public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { + this.minecraftServer = minecraftserver; + this.networkManager = networkmanager; +@@ -3000,6 +3004,8 @@ public class PlayerConnection implements PacketListenerPlayIn { + private static final MinecraftKey CUSTOM_REGISTER = new MinecraftKey("register"); + private static final MinecraftKey CUSTOM_UNREGISTER = new MinecraftKey("unregister"); + ++ private static final MinecraftKey MINECRAFT_BRAND = new MinecraftKey("brand"); // Paper - Brand support ++ + @Override + public void a(PacketPlayInCustomPayload packetplayincustompayload) { + PlayerConnectionUtils.ensureMainThread(packetplayincustompayload, this, this.player.getWorldServer()); +@@ -3027,6 +3033,16 @@ public class PlayerConnection implements PacketListenerPlayIn { + try { + byte[] data = new byte[packetplayincustompayload.data.readableBytes()]; + packetplayincustompayload.data.readBytes(data); ++ ++ // Paper start - Brand support ++ if (packetplayincustompayload.tag.equals(MINECRAFT_BRAND)) { ++ try { ++ this.clientBrandName = new PacketDataSerializer(Unpooled.copiedBuffer(data)).readUTF(256); ++ } catch (StringIndexOutOfBoundsException ex) { ++ this.clientBrandName = "illegal"; ++ } ++ } ++ // Paper end + server.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packetplayincustompayload.tag.toString(), data); + } catch (Exception ex) { + PlayerConnection.LOGGER.error("Couldn\'t dispatch custom payload", ex); +@@ -3036,6 +3052,12 @@ public class PlayerConnection implements PacketListenerPlayIn { + + } + ++ // Paper start - brand support ++ public String getClientBrandName() { ++ return clientBrandName; ++ } ++ // Paper end ++ + public final boolean isDisconnected() { + return (!this.player.joining && !this.networkManager.isConnected()) || this.processedDisconnect; // Paper + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0f8d10c2bc7728b58528096fc0686c3aeee623a7..18d7cf6e783843d44715210b7c8db7bf0a5c89ae 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2388,6 +2388,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + // Paper end + }; + ++ // Paper start - brand support ++ @Override ++ public String getClientBrandName() { ++ return getHandle().playerConnection != null ? getHandle().playerConnection.getClientBrandName() : null; ++ } ++ // Paper end ++ + public Player.Spigot spigot() + { + return spigot; diff --git a/patches/server-unmapped/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch b/patches/server-unmapped/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch new file mode 100644 index 0000000000..61129f1906 --- /dev/null +++ b/patches/server-unmapped/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Thu, 20 Aug 2020 19:24:13 -0700 +Subject: [PATCH] Fix MC-99259 Wither Boss Bar doesn't update until + invulnerability period is over + + +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +index 174eb12722872182b2d9b54841e5bb57893695a1..30290c0208a4725b2eb0e7764465c354e592e4ee 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +@@ -393,8 +393,9 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + +- this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); ++ //this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Moved down + } ++ this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Fix MC-99259 (Boss bar does not update until Wither invulnerability period ends) + } + + public static boolean c(IBlockData iblockdata) { diff --git a/patches/server-unmapped/0547-Fix-MC-197271.patch b/patches/server-unmapped/0547-Fix-MC-197271.patch new file mode 100644 index 0000000000..5c61d89c86 --- /dev/null +++ b/patches/server-unmapped/0547-Fix-MC-197271.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ishland +Date: Sun, 23 Aug 2020 10:57:44 +0200 +Subject: [PATCH] Fix MC-197271 + +This patch only fixes an issue for servers running OpenJ9. + +diff --git a/src/main/java/net/minecraft/data/RegistryGeneration.java b/src/main/java/net/minecraft/data/RegistryGeneration.java +index 25762daca063ff5a422975d7fe64752a2deae163..2c06e3ab167443ac54c27cfe09e279f18a9f7300 100644 +--- a/src/main/java/net/minecraft/data/RegistryGeneration.java ++++ b/src/main/java/net/minecraft/data/RegistryGeneration.java +@@ -48,11 +48,11 @@ public class RegistryGeneration { + public static final IRegistry g = a(IRegistry.aw, () -> { + return ProcessorLists.b; + }); +- public static final IRegistry h = a(IRegistry.ax, WorldGenFeaturePieces::a); ++ public static final IRegistry h = a(IRegistry.ax, () -> WorldGenFeaturePieces.a()); // Paper - MC-197271 + public static final IRegistry WORLDGEN_BIOME = a(IRegistry.ay, () -> { + return BiomeRegistry.a; + }); +- public static final IRegistry j = a(IRegistry.ar, GeneratorSettingBase::i); ++ public static final IRegistry j = a(IRegistry.ar, () -> GeneratorSettingBase.i()); // Paper - MC-197271 + + private static IRegistry a(ResourceKey> resourcekey, Supplier supplier) { + return a(resourcekey, Lifecycle.stable(), supplier); +@@ -66,9 +66,9 @@ public class RegistryGeneration { + MinecraftKey minecraftkey = resourcekey.a(); + + RegistryGeneration.k.put(minecraftkey, supplier); +- IRegistryWritable iregistrywritable = RegistryGeneration.l; ++ IRegistryWritable iregistrywritable = (IRegistryWritable) RegistryGeneration.l; // Paper - decompile fix + +- return (IRegistryWritable) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); ++ return (R) iregistrywritable.a((ResourceKey) resourcekey, r0, lifecycle); // Paper - decompile fix + } + + public static T a(IRegistry iregistry, String s, T t0) { +@@ -76,11 +76,11 @@ public class RegistryGeneration { + } + + public static T a(IRegistry iregistry, MinecraftKey minecraftkey, T t0) { +- return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.f(), minecraftkey), t0, Lifecycle.stable()); ++ return (T) ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.f(), minecraftkey), t0, Lifecycle.stable()); // Paper - decompile fix + } + + public static T a(IRegistry iregistry, int i, ResourceKey resourcekey, T t0) { +- return ((IRegistryWritable) iregistry).a(i, resourcekey, t0, Lifecycle.stable()); ++ return (T) ((IRegistryWritable) iregistry).a(i, resourcekey, t0, Lifecycle.stable()); // Paper - decompile fix + } + + public static void a() {} diff --git a/patches/server-unmapped/0548-MC-197883-Bandaid-decode-issue.patch b/patches/server-unmapped/0548-MC-197883-Bandaid-decode-issue.patch new file mode 100644 index 0000000000..fd35ea34e4 --- /dev/null +++ b/patches/server-unmapped/0548-MC-197883-Bandaid-decode-issue.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 21 Aug 2020 21:05:28 -0400 +Subject: [PATCH] MC-197883: Bandaid decode issue + +Mojang has a mix of type and name in the data sets, but you can only +use one. + +This will retry as name if type is asked for and not found. + +diff --git a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java +index de7d1e5e0319c65775d932144c268c2d55bb7dc7..bd6a0e1b5454e880a4f2a16be7dc8da64b73e11d 100644 +--- a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java ++++ b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java +@@ -48,7 +48,12 @@ public class KeyDispatchCodec extends MapCodec { + + @Override + public DataResult decode(final DynamicOps ops, final MapLike input) { +- final T elementName = input.get(typeKey); ++ // Paper start - bandaid MC-197883 ++ T elementName = input.get(typeKey); ++ if (elementName == null && "type".equals(typeKey)) { ++ elementName = input.get("name"); ++ } ++ // Paper end + if (elementName == null) { + return DataResult.error("Input does not contain a key [" + typeKey + "]: " + input); + } diff --git a/patches/server-unmapped/0549-Add-setMaxPlayers-API.patch b/patches/server-unmapped/0549-Add-setMaxPlayers-API.patch new file mode 100644 index 0000000000..af8f01de47 --- /dev/null +++ b/patches/server-unmapped/0549-Add-setMaxPlayers-API.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 22 Aug 2020 23:59:30 +0200 +Subject: [PATCH] Add #setMaxPlayers API + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index d3f3dc4ad2c758482b7a8d5c07caa526ce1e3424..8bd55e3d2b5142081a7dfe1dbbd36f2f995e5856 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -145,7 +145,7 @@ public abstract class PlayerList { + public final WorldNBTStorage playerFileData; + private boolean hasWhitelist; + private final IRegistryCustom.Dimension s; +- protected final int maxPlayers; ++ protected int maxPlayers; public final void setMaxPlayers(int maxPlayers) { this.maxPlayers = maxPlayers; } // Paper - remove final and add setter + private int viewDistance; + private EnumGamemode u; + private boolean v; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 8f44857e9f61c72fa210c16c8bd6b8a6bbdac239..4dceb2d0beb6f91526b101d4947556049a0f3251 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -614,6 +614,13 @@ public final class CraftServer implements Server { + return playerList.getMaxPlayers(); + } + ++ // Paper start ++ @Override ++ public void setMaxPlayers(int maxPlayers) { ++ this.playerList.setMaxPlayers(maxPlayers); ++ } ++ // Paper end ++ + // NOTE: These are dependent on the corresponding call in MinecraftServer + // so if that changes this will need to as well + @Override diff --git a/patches/server-unmapped/0550-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server-unmapped/0550-Add-playPickupItemAnimation-to-LivingEntity.patch new file mode 100644 index 0000000000..6306ebc1e9 --- /dev/null +++ b/patches/server-unmapped/0550-Add-playPickupItemAnimation-to-LivingEntity.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 23 Aug 2020 19:36:22 +0200 +Subject: [PATCH] Add playPickupItemAnimation to LivingEntity + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index fdf4d258dd3e81cf4317ad66334c323be2d88fb2..de12a050739b8d12d268cc9ca496259ea2c46569 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -818,5 +818,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + ((EntityInsentient) getHandle()).getControllerJump().jump(); + } + } ++ ++ @Override ++ public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { ++ getHandle().receive(((CraftItem) item).getHandle(), quantity); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0551-Don-t-require-FACING-data.patch b/patches/server-unmapped/0551-Don-t-require-FACING-data.patch new file mode 100644 index 0000000000..00f9b23e6f --- /dev/null +++ b/patches/server-unmapped/0551-Don-t-require-FACING-data.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sun, 23 Aug 2020 19:01:04 +0200 +Subject: [PATCH] Don't require FACING data + + +diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java b/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java +index 979b862284ecd0dc504ee8a7018b27ff569b7b85..3d14ec72bb9babdf6b24aca3bde06d8b54815f9d 100644 +--- a/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java ++++ b/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java +@@ -15,20 +15,22 @@ import org.bukkit.event.block.BlockDispenseEvent; + // CraftBukkit end + + public class DispenseBehaviorItem implements IDispenseBehavior { ++ private EnumDirection enumdirection; // Paper + + public DispenseBehaviorItem() {} + + @Override + public final ItemStack dispense(ISourceBlock isourceblock, ItemStack itemstack) { ++ enumdirection = isourceblock.getBlockData().get(BlockDispenser.FACING); // Paper - cache facing direction + ItemStack itemstack1 = this.a(isourceblock, itemstack); + + this.a(isourceblock); +- this.a(isourceblock, (EnumDirection) isourceblock.getBlockData().get(BlockDispenser.FACING)); ++ this.a(isourceblock, enumdirection); // Paper - cache facing direction + return itemstack1; + } + + protected ItemStack a(ISourceBlock isourceblock, ItemStack itemstack) { +- EnumDirection enumdirection = (EnumDirection) isourceblock.getBlockData().get(BlockDispenser.FACING); ++ // Paper - cached enum direction + IPosition iposition = BlockDispenser.a(isourceblock); + ItemStack itemstack1 = itemstack.cloneAndSubtract(1); + diff --git a/patches/server-unmapped/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server-unmapped/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch new file mode 100644 index 0000000000..99ee434bf4 --- /dev/null +++ b/patches/server-unmapped/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 22 Aug 2020 23:36:21 +0200 +Subject: [PATCH] Fix SpawnChangeEvent not firing for all use-cases + + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index a0670bdd858f59ee5719580625c9f25235e23fc4..70f8fbff2ac825b61c5c9f7c6830de3106e7926c 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1987,12 +1987,14 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + // Paper end + ++ public final void setSpawn(BlockPosition blockposition, float f) { this.a(blockposition, f); } // Paper - OBFHELPER + public void a(BlockPosition blockposition, float f) { + // Paper - configurable spawn radius + BlockPosition prevSpawn = this.getSpawn(); + //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); + + this.worldData.setSpawn(blockposition, f); ++ new org.bukkit.event.world.SpawnChangeEvent(getWorld(), MCUtil.toLocation(this, prevSpawn)).callEvent(); // Paper + if (this.keepSpawnInMemory) { + // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add + this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 74ee2013a47855cdd1d56a06a2e209776513fd14..d3f5a3d4872665b4c52a6cfad1518016919557d0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -389,11 +389,13 @@ public class CraftWorld implements World { + public boolean setSpawnLocation(int x, int y, int z, float angle) { + try { + Location previousLocation = getSpawnLocation(); +- world.worldData.setSpawn(new BlockPosition(x, y, z), angle); ++ world.setSpawn(new BlockPosition(x, y, z), angle); // Paper - use WorldServer#setSpawn + ++ // Paper start - move to nms.World + // Notify anyone who's listening. +- SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); +- server.getPluginManager().callEvent(event); ++ // SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); ++ // server.getPluginManager().callEvent(event); ++ // Paper end + + return true; + } catch (Exception e) { diff --git a/patches/server-unmapped/0553-Add-moon-phase-API.patch b/patches/server-unmapped/0553-Add-moon-phase-API.patch new file mode 100644 index 0000000000..c49db87041 --- /dev/null +++ b/patches/server-unmapped/0553-Add-moon-phase-API.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Aug 2020 16:32:11 +0200 +Subject: [PATCH] Add moon phase API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index d3f5a3d4872665b4c52a6cfad1518016919557d0..76a7889b49a16ddeb8f310d3a79cfee80ad9a1db 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -328,6 +328,11 @@ public class CraftWorld implements World { + public int getPlayerCount() { + return world.players.size(); + } ++ ++ @Override ++ public io.papermc.paper.world.MoonPhase getMoonPhase() { ++ return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); ++ } + // Paper end + + private static final Random rand = new Random(); diff --git a/patches/server-unmapped/0554-Prevent-headless-pistons-from-being-created.patch b/patches/server-unmapped/0554-Prevent-headless-pistons-from-being-created.patch new file mode 100644 index 0000000000..f6e166986f --- /dev/null +++ b/patches/server-unmapped/0554-Prevent-headless-pistons-from-being-created.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: commandblockguy +Date: Fri, 14 Aug 2020 14:44:14 -0500 +Subject: [PATCH] Prevent headless pistons from being created + +Prevent headless pistons from being created by explosions or tree/mushroom growth. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb..faa1b775e45563b93ac1d5b904938b1f5ad8d80c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -441,6 +441,12 @@ public class PaperConfig { + set("settings.unsupported-settings.allow-tnt-duplication", null); + } + ++ public static boolean allowHeadlessPistons; ++ private static void allowHeadlessPistons() { ++ config.set("settings.unsupported-settings.allow-headless-pistons-readme", "This setting controls if players should be able to create headless pistons."); ++ allowHeadlessPistons = getBoolean("settings.unsupported-settings.allow-headless-pistons", false); ++ } ++ + public static int playerAutoSaveRate = -1; + public static int maxPlayerAutoSavePerTick = 10; + private static void playerAutoSaveRate() { +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 0b3479aae8f7cad7bd0b8b64aa2dead43baf4c56..79008bda42558ea7d28ccf51b66405a3bdb52da7 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -16,6 +16,7 @@ import java.util.Set; + import javax.annotation.Nullable; + import net.minecraft.core.BaseBlockPosition; + import net.minecraft.core.BlockPosition; ++import net.minecraft.core.EnumDirection; + import net.minecraft.core.particles.Particles; + import net.minecraft.server.level.WorldServer; + import net.minecraft.sounds.SoundCategory; +@@ -34,6 +35,8 @@ import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.BlockFireAbstract; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.TileEntity; ++import net.minecraft.world.level.block.piston.BlockPistonExtension; ++import net.minecraft.world.level.block.piston.TileEntityPiston; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.storage.loot.LootTableInfo; +@@ -163,6 +166,15 @@ public class Explosion { + + if (f > 0.0F && this.l.a(this, this.world, blockposition, iblockdata, f) && blockposition.getY() < 256 && blockposition.getY() >= 0) { // CraftBukkit - don't wrap explosions + set.add(blockposition); ++ // Paper start - prevent headless pistons from forming ++ if (!com.destroystokyo.paper.PaperConfig.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) { ++ TileEntity extension = this.world.getTileEntity(blockposition); ++ if (extension instanceof TileEntityPiston && ((TileEntityPiston) extension).isHead()) { ++ EnumDirection direction = iblockdata.get(BlockPistonExtension.FACING); ++ set.add(blockposition.shift(direction.opposite())); ++ } ++ } ++ // Paper end + } + + d4 += d0 * 0.30000001192092896D; +diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java +index e70c3a8c9075b6c0bc73e6488d784dfe3b86e58d..58c7a52612fe0f5c1e4ddacc0bf93cd81f1286b8 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java +@@ -65,6 +65,8 @@ public class TileEntityPiston extends TileEntity implements ITickable { + return this.b; + } + ++ public final boolean isHead() { return this.h(); } // Paper - OBFHELPER ++ + public boolean h() { + return this.g; + } diff --git a/patches/server-unmapped/0555-Add-BellRingEvent.patch b/patches/server-unmapped/0555-Add-BellRingEvent.patch new file mode 100644 index 0000000000..6352b44128 --- /dev/null +++ b/patches/server-unmapped/0555-Add-BellRingEvent.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Eearslya Sleiarion +Date: Sun, 23 Aug 2020 13:04:02 +0200 +Subject: [PATCH] Add BellRingEvent + +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/net/minecraft/world/level/block/BlockBell.java b/src/main/java/net/minecraft/world/level/block/BlockBell.java +index 687f7acd8254294b568c9adf3e72d02d12551381..24754057bc83577f4854262bbb82db355591270e 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockBell.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockBell.java +@@ -1,8 +1,11 @@ + package net.minecraft.world.level.block; + ++import io.papermc.paper.event.block.BellRingEvent; ++ + import javax.annotation.Nullable; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.stats.StatisticList; +@@ -89,7 +92,7 @@ public class BlockBell extends BlockTileEntity { + boolean flag1 = !flag || this.a(iblockdata, enumdirection, movingobjectpositionblock.getPos().y - (double) blockposition.getY()); + + if (flag1) { +- boolean flag2 = this.a(world, blockposition, enumdirection); ++ boolean flag2 = this.handleBellRing(world, blockposition, enumdirection, entityhuman); // Paper + + if (flag2 && entityhuman != null) { + entityhuman.a(StatisticList.BELL_RING); +@@ -123,6 +126,11 @@ public class BlockBell extends BlockTileEntity { + } + + public boolean a(World world, BlockPosition blockposition, @Nullable EnumDirection enumdirection) { ++ // Paper start - add ringer param ++ return this.handleBellRing(world, blockposition, enumdirection, null); ++ } ++ public boolean handleBellRing(World world, BlockPosition blockposition, @Nullable EnumDirection enumdirection, @Nullable Entity ringer) { ++ // Paper end + TileEntity tileentity = world.getTileEntity(blockposition); + + if (!world.isClientSide && tileentity instanceof TileEntityBell) { +@@ -130,6 +138,7 @@ public class BlockBell extends BlockTileEntity { + enumdirection = (EnumDirection) world.getType(blockposition).get(BlockBell.a); + } + ++ if (!new BellRingEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, blockposition)), ringer == null ? null : ringer.getBukkitEntity()).callEvent()) return false; // Paper - BellRingEvent + ((TileEntityBell) tileentity).a(enumdirection); + world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_BELL_USE, SoundCategory.BLOCKS, 2.0F, 1.0F); + return true; diff --git a/patches/server-unmapped/0556-Add-zombie-targets-turtle-egg-config.patch b/patches/server-unmapped/0556-Add-zombie-targets-turtle-egg-config.patch new file mode 100644 index 0000000000..2d5c7f12aa --- /dev/null +++ b/patches/server-unmapped/0556-Add-zombie-targets-turtle-egg-config.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Aug 2020 15:47:34 +0200 +Subject: [PATCH] Add zombie targets turtle egg config + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 978062774c1db286bfb9b0ffdef19d880b1f249b..36ecdfce84141ac731b827e469ac842f5c666259 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -668,4 +668,9 @@ public class PaperWorldConfig { + maxLightningFlashDistance = 512; // Vanilla value + } + } ++ ++ public boolean zombiesTargetTurtleEggs = true; ++ private void zombiesTargetTurtleEggs() { ++ zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index 3d8d4a43e6cd554b6f1eeafa1c8d43cef877139a..87acbdee03edf8bc35f4b3bcb9b82855ed4a3c33 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -107,7 +107,7 @@ public class EntityZombie extends EntityMonster { + + @Override + protected void initPathfinder() { +- this.goalSelector.a(4, new EntityZombie.a(this, 1.0D, 3)); ++ if (world.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.a(4, new EntityZombie.a(this, 1.0D, 3)); // Paper + this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); + this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); + this.m(); diff --git a/patches/server-unmapped/0557-Buffer-joins-to-world.patch b/patches/server-unmapped/0557-Buffer-joins-to-world.patch new file mode 100644 index 0000000000..3b7cd4b59a --- /dev/null +++ b/patches/server-unmapped/0557-Buffer-joins-to-world.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Wed, 19 Aug 2020 05:05:54 +0100 +Subject: [PATCH] Buffer joins to world + +This patch buffers the number of logins which will attempt to join +the world per tick, this attempts to reduce the impact that join floods +has on the server + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index faa1b775e45563b93ac1d5b904938b1f5ad8d80c..545948f20efd6c8dd42140b565af94cd6b52b661 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -457,4 +457,9 @@ public class PaperConfig { + maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; + } + } ++ ++ public static int maxJoinsPerTick; ++ private static void maxJoinsPerTick() { ++ maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); ++ } + } +diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +index ab70eeaeca222de7de7cab1b3db14b2c4761c3c3..878f879f8d410c428ad8a4c49e0c86c559bc47a9 100644 +--- a/src/main/java/net/minecraft/network/NetworkManager.java ++++ b/src/main/java/net/minecraft/network/NetworkManager.java +@@ -33,6 +33,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutTabComplete; + import net.minecraft.network.protocol.game.PacketPlayOutTitle; + import net.minecraft.server.CancelledPacketHandleException; + import net.minecraft.server.MCUtil; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.network.LoginListener; + import net.minecraft.server.network.PlayerConnection; +@@ -382,10 +383,22 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } + // Paper end + ++ private static final int MAX_PER_TICK = com.destroystokyo.paper.PaperConfig.maxJoinsPerTick; // Paper ++ private static int joinAttemptsThisTick; // Paper ++ private static int currTick; // Paper + public void a() { + this.p(); ++ // Paper start ++ if (currTick != MinecraftServer.currentTick) { ++ currTick = MinecraftServer.currentTick; ++ joinAttemptsThisTick = 0; ++ } ++ // Paper end + if (this.packetListener instanceof LoginListener) { ++ if ( ((LoginListener) this.packetListener).getLoginState() != LoginListener.EnumProtocolState.READY_TO_ACCEPT // Paper ++ || (joinAttemptsThisTick++ < MAX_PER_TICK)) { // Paper - limit the number of joins which can be processed each tick + ((LoginListener) this.packetListener).tick(); ++ } // Paper + } + + if (this.packetListener instanceof PlayerConnection) { +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index ef2aa000932c222e358789fcd2629dd8a46cfe80..f40736a836d6097930b9704246c7077617b1f962 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -422,7 +422,7 @@ public class LoginListener implements PacketLoginInListener { + return new GameProfile(uuid, gameprofile.getName()); + } + +- static enum EnumProtocolState { ++ public enum EnumProtocolState { // Paper - package private -> public + + HELLO, KEY, AUTHENTICATING, NEGOTIATING, READY_TO_ACCEPT, DELAY_ACCEPT, ACCEPTED; + diff --git a/patches/server-unmapped/0558-Optimize-redstone-algorithm.patch b/patches/server-unmapped/0558-Optimize-redstone-algorithm.patch new file mode 100644 index 0000000000..4e538c9eb3 --- /dev/null +++ b/patches/server-unmapped/0558-Optimize-redstone-algorithm.patch @@ -0,0 +1,1158 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: theosib +Date: Thu, 27 Sep 2018 01:43:35 -0600 +Subject: [PATCH] Optimize redstone algorithm + +Author: theosib +Co-authored-by: egg82 + +Original license: MIT + +This patch implements theosib's redstone algorithms to completely overhaul the way redstone works. +The new algorithms should be many times faster than current vanilla ones. +From the original author's comments, it looks like it shouldn't interfere with any redstone save for very extreme edge-cases. + +Surprisingly, not a lot was touched aside from a few obfuscation helpers and BlockRedstoneWire. +A lot of this code is self-contained in a helper class. + +Aside from making the obvious class/function renames and obfhelpers I didn't need to modify much. +Just added Bukkit's event system and took a few liberties with dead code and comment misspellings. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 36ecdfce84141ac731b827e469ac842f5c666259..02bb85364560784adea47c877c13291c3d016b86 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -673,4 +673,14 @@ public class PaperWorldConfig { + private void zombiesTargetTurtleEggs() { + zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); + } ++ ++ public boolean useEigencraftRedstone = false; ++ private void useEigencraftRedstone() { ++ useEigencraftRedstone = this.getBoolean("use-faster-eigencraft-redstone", false); ++ if (useEigencraftRedstone) { ++ log("Using Eigencraft redstone algorithm by theosib."); ++ } else { ++ log("Using vanilla redstone algorithm."); ++ } ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java +new file mode 100644 +index 0000000000000000000000000000000000000000..167e0aaec8c2f83856465b7efc9ac9e5f9389d91 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java +@@ -0,0 +1,914 @@ ++package com.destroystokyo.paper.util; ++ ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.ThreadLocalRandom; ++ ++import net.minecraft.core.BlockPosition; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.item.Items; ++import net.minecraft.world.level.World; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.BlockRedstoneWire; ++import net.minecraft.world.level.block.state.IBlockData; ++import org.bukkit.event.block.BlockRedstoneEvent; ++ ++import com.google.common.collect.Lists; ++import com.google.common.collect.Maps; ++ ++/** ++ * Used for the faster redstone algorithm. ++ * Original author: theosib ++ * Original license: MIT ++ * ++ * Ported to Paper and updated to 1.13 by egg82 ++ */ ++public class RedstoneWireTurbo { ++ /* ++ * This is Helper class for BlockRedstoneWire. It implements a minimally-invasive ++ * bolt-on accelerator that performs a breadth-first search through redstone wire blocks ++ * in order to more efficiently and deterministically compute new redstone wire power levels ++ * and determine the order in which other blocks should be updated. ++ * ++ * Features: ++ * - Changes to BlockRedstoneWire are very limited, no other classes are affected, and the ++ * choice between old and new redstone wire update algorithms is switchable on-line. ++ * - The vanilla implementation relied on World.notifyNeighborsOfStateChange for redstone ++ * wire blocks to communicate power level changes to each other, generating 36 block ++ * updates per call. This improved implementation propagates power level changes directly ++ * between redstone wire blocks. Redstone wire power levels are therefore computed more quickly, ++ * and block updates are sent only to non-redstone blocks, many of which may perform an ++ * action when informed of a change in redstone power level. (Note: Block updates are not ++ * the same as state changes to redstone wire. Wire block states are updated as soon ++ * as they are computed.) ++ * - Of the 36 block updates generated by a call to World.notifyNeighborsOfStateChange, ++ * 12 of them are obviously redundant (e.g. the west neighbor of the east neighbor). ++ * These are eliminated. ++ * - Updates to redstone wire and other connected blocks are propagated in a breath-first ++ * manner, radiating out from the initial trigger (a block update to a redstone wire ++ * from something other than redstone wire). ++ * - Updates are scheduled both deterministically and in an intuitive order, addressing bug ++ * MC-11193. ++ * - All redstone behavior that used to be locational now works the same in all locations. ++ * - All behaviors of redstone wire that used to be orientational now work the same in all ++ * orientations, as long as orientation can be determined; random otherwise. Some other ++ * redstone components still update directionally (e.g. switches), and this code can't ++ * compensate for that. ++ * - Information that is otherwise computed over and over again or which is expensive to ++ * to compute is cached for faster lookup. This includes coordinates of block position ++ * neighbors and block states that won't change behind our backs during the execution of ++ * this search algorithm. ++ * - Redundant block updates (both to redstone wire and to other blocks) are heavily ++ * consolidated. For worst-case scenarios (depowering of redstone wire) this results ++ * in a reduction of block updates by as much as 95% (factor of 1/21). Due to overheads, ++ * empirical testing shows a speedup better than 10x. This addresses bug MC-81098. ++ * ++ * Extensive testing has been performed to ensure that existing redstone contraptions still ++ * behave as expected. Results of early testing that identified undesirable behavior changes ++ * were addressed. Additionally, real-time performance testing revealed compute inefficiencies ++ * With earlier implementations of this accelerator. Some compatibility adjustments and ++ * performance optimizations resulted in harmless increases in block updates above the ++ * theoretical minimum. ++ * ++ * Only a single redstone machine was found to break: An instant dropper line hack that ++ * relies on powered rails and quasi-connectivity but doesn't work in all directions. The ++ * replacement is to lay redstone wire directly on top of the dropper line, which now works ++ * reliably in any direction. ++ * ++ * There are numerous other optimization that can be made, but those will be provided later in ++ * separate updates. This version is designed to be minimalistic. ++ * ++ * Many thanks to the following individuals for their help in testing this functionality: ++ * - pokechu22, _MethodZz_, WARBEN, NarcolepticFrog, CommandHelper (nessie), ilmango, ++ * OreoLamp, Xcom6000, tryashtar, RedCMD, Smokey95Dog, EDDxample, Rays Works, ++ * Nodnam, BlockyPlays, Grumm, NeunEinser, HelVince. ++ */ ++ ++ /* Reference to BlockRedstoneWire object, which uses this accelerator */ ++ private final BlockRedstoneWire wire; ++ ++ /* ++ * Implementation: ++ * ++ * RedstoneWire Blocks are updated in concentric rings or "layers" radiating out from the ++ * initial block update that came from a call to BlockRedstoneWire.neighborChanged(). ++ * All nodes put in Layer N are those with Manhattan distance N from the trigger ++ * position, reachable through connected redstone wire blocks. ++ * ++ * Layer 0 represents the trigger block position that was input to neighborChanged. ++ * Layer 1 contains the immediate neighbors of that position. ++ * Layer N contains the neighbors of blocks in layer N-1, not including ++ * those in previous layers. ++ * ++ * Layers enforce an update order that is a function of Manhattan distance ++ * from the initial coordinates input to neighborChanged. The same ++ * coordinates may appear in multiple layers, but redundant updates are minimized. ++ * Block updates are sent layer-by-layer. If multiple of a block's neighbors experience ++ * redstone wire changes before its layer is processed, then those updates will be merged. ++ * If a block's update has been sent, but its neighboring redstone changes ++ * after that, then another update will be sent. This preserves compatibility with ++ * machines that rely on zero-tick behavior, except that the new functionality is non- ++ * locational. ++ * ++ * Within each layer, updates are ordered left-to-right relative to the direction of ++ * information flow. This makes the implementation non-orientational. Only when ++ * this direction is ambiguous is randomness applied (intentionally). ++ */ ++ private List updateQueue0 = Lists.newArrayList(); ++ private List updateQueue1 = Lists.newArrayList(); ++ private List updateQueue2 = Lists.newArrayList(); ++ ++ public RedstoneWireTurbo(BlockRedstoneWire wire) { ++ this.wire = wire; ++ } ++ ++ /* ++ * Compute neighbors of a block. When a redstone wire value changes, previously it called ++ * World.notifyNeighborsOfStateChange. That lists immediately neighboring blocks in ++ * west, east, down, up, north, south order. For each of those neighbors, their own ++ * neighbors are updated in the same order. This generates 36 updates, but 12 of them are ++ * redundant; for instance the west neighbor of a block's east neighbor. ++ * ++ * Note that this ordering is only used to create the initial list of neighbors. Once ++ * the direction of signal flow is identified, the ordering of updates is completely ++ * reorganized. ++ */ ++ public static BlockPosition[] computeAllNeighbors(final BlockPosition pos) { ++ final int x = pos.getX(); ++ final int y = pos.getY(); ++ final int z = pos.getZ(); ++ final BlockPosition[] n = new BlockPosition[24]; ++ ++ // Immediate neighbors, in the same order as ++ // World.notifyNeighborsOfStateChange, etc.: ++ // west, east, down, up, north, south ++ n[0] = new BlockPosition(x - 1, y, z); ++ n[1] = new BlockPosition(x + 1, y, z); ++ n[2] = new BlockPosition(x, y - 1, z); ++ n[3] = new BlockPosition(x, y + 1, z); ++ n[4] = new BlockPosition(x, y, z - 1); ++ n[5] = new BlockPosition(x, y, z + 1); ++ ++ // Neighbors of neighbors, in the same order, ++ // except that duplicates are not included ++ n[6] = new BlockPosition(x - 2, y, z); ++ n[7] = new BlockPosition(x - 1, y - 1, z); ++ n[8] = new BlockPosition(x - 1, y + 1, z); ++ n[9] = new BlockPosition(x - 1, y, z - 1); ++ n[10] = new BlockPosition(x - 1, y, z + 1); ++ n[11] = new BlockPosition(x + 2, y, z); ++ n[12] = new BlockPosition(x + 1, y - 1, z); ++ n[13] = new BlockPosition(x + 1, y + 1, z); ++ n[14] = new BlockPosition(x + 1, y, z - 1); ++ n[15] = new BlockPosition(x + 1, y, z + 1); ++ n[16] = new BlockPosition(x, y - 2, z); ++ n[17] = new BlockPosition(x, y - 1, z - 1); ++ n[18] = new BlockPosition(x, y - 1, z + 1); ++ n[19] = new BlockPosition(x, y + 2, z); ++ n[20] = new BlockPosition(x, y + 1, z - 1); ++ n[21] = new BlockPosition(x, y + 1, z + 1); ++ n[22] = new BlockPosition(x, y, z - 2); ++ n[23] = new BlockPosition(x, y, z + 2); ++ return n; ++ } ++ ++ /* ++ * We only want redstone wires to update redstone wires that are ++ * immediately adjacent. Some more distant updates can result ++ * in cross-talk that (a) wastes time and (b) can make the update ++ * order unintuitive. Therefore (relative to the neighbor order ++ * computed by computeAllNeighbors), updates are not scheduled ++ * for redstone wire in those non-connecting positions. On the ++ * other hand, updates will always be sent to *other* types of blocks ++ * in any of the 24 neighboring positions. ++ */ ++ private static final boolean[] update_redstone = { ++ true, true, false, false, true, true, // 0 to 5 ++ false, true, true, false, false, false, // 6 to 11 ++ true, true, false, false, false, true, // 12 to 17 ++ true, false, true, true, false, false // 18 to 23 ++ }; ++ ++ // Internal numbering for cardinal directions ++ private static final int North = 0; ++ private static final int East = 1; ++ private static final int South = 2; ++ private static final int West = 3; ++ ++ /* ++ * These lookup tables completely remap neighbor positions into a left-to-right ++ * ordering, based on the cardinal direction that is determined to be forward. ++ * See below for more explanation. ++ */ ++ private static final int[] forward_is_north = {2, 3, 16, 19, 0, 4, 1, 5, 7, 8, 17, 20, 12, 13, 18, 21, 6, 9, 22, 14, 11, 10, 23, 15}; ++ private static final int[] forward_is_east = {2, 3, 16, 19, 4, 1, 5, 0, 17, 20, 12, 13, 18, 21, 7, 8, 22, 14, 11, 15, 23, 9, 6, 10}; ++ private static final int[] forward_is_south = {2, 3, 16, 19, 1, 5, 0, 4, 12, 13, 18, 21, 7, 8, 17, 20, 11, 15, 23, 10, 6, 14, 22, 9}; ++ private static final int[] forward_is_west = {2, 3, 16, 19, 5, 0, 4, 1, 18, 21, 7, 8, 17, 20, 12, 13, 23, 10, 6, 9, 22, 15, 11, 14}; ++ ++ /* For any orientation, we end up with the update order defined below. This order is relative to any redstone wire block ++ * that is itself having an update computed, and this center position is marked with C. ++ * - The update position marked 0 is computed first, and the one marked 23 is last. ++ * - Forward is determined by the local direction of information flow into position C from prior updates. ++ * - The first updates are scheduled for the four positions below and above C. ++ * - Then updates are scheduled for the four horizontal neighbors of C, followed by the positions below and above those neighbors. ++ * - Finally, updates are scheduled for the remaining positions with Manhattan distance 2 from C (at the same Y coordinate). ++ * - For a given horizontal distance from C, updates are scheduled starting from directly left and stepping clockwise to directly ++ * right. The remaining positions behind C are scheduled counterclockwise so as to maintain the left-to-right ordering. ++ * - If C is in layer N of the update schedule, then all 24 positions may be scheduled for layer N+1. For redstone wire, no ++ * updates are scheduled for positions that cannot directly connect. Additionally, the four positions above and below C ++ * are ALSO scheduled for layer N+2. ++ * - This update order was selected after experimenting with a number of alternative schedules, based on its compatibility ++ * with existing redstone designs and behaviors that were considered to be intuitive by various testers. WARBEN in particular ++ * made some of the most challenging test cases, but the 3-tick clocks (made by RedCMD) were also challenging to fix, ++ * along with the rail-based instant dropper line built by ilmango. Numerous others made test cases as well, including ++ * NarcolepticFrog, nessie, and Pokechu22. ++ * ++ * - The forward direction is determined locally. So when there are branches in the redstone wire, the left one will get updated ++ * before the right one. Each branch can have its own relative forward direction, resulting in the left side of a left branch ++ * having priority over the right branch of a left branch, which has priority over the left branch of a right branch, followed ++ * by the right branch of a right branch. And so forth. Since redstone power reduces to zero after a path distance of 15, ++ * that imposes a practical limit on the branching. Note that the branching is not tracked explicitly -- relative forward ++ * directions dictate relative sort order, which maintains the proper global ordering. This also makes it unnecessary to be ++ * concerned about branches meeting up with each other. ++ * ++ * ^ ++ * | ++ * Forward ++ * <-- Left Right --> ++ * ++ * 18 ++ * 10 17 5 19 11 ++ * 2 8 0 12 16 4 C 6 20 9 1 13 3 ++ * 14 21 7 23 15 ++ * Further 22 Further ++ * Down Down Up Up ++ * ++ * Backward ++ * | ++ * V ++ */ ++ ++ // This allows the above remapping tables to be looked up by cardial direction index ++ private static final int[][] reordering = { forward_is_north, forward_is_east, forward_is_south, forward_is_west }; ++ ++ /* ++ * Input: Array of UpdateNode objects in an order corresponding to the positions ++ * computed by computeAllNeighbors above. ++ * Output: Array of UpdateNode objects oriented using the above remapping tables ++ * corresponding to the identified heading (direction of information flow). ++ */ ++ private static void orientNeighbors(final UpdateNode[] src, final UpdateNode[] dst, final int heading) { ++ final int[] re = reordering[heading]; ++ for (int i = 0; i < 24; i++) { ++ dst[i] = src[re[i]]; ++ } ++ } ++ ++ /* ++ * Structure to keep track of redstone wire blocks and ++ * neighbors that will receive updates. ++ */ ++ private static class UpdateNode { ++ public static enum Type { ++ UNKNOWN, REDSTONE, OTHER ++ } ++ ++ IBlockData currentState; // Keep track of redstone wire value ++ UpdateNode[] neighbor_nodes; // References to neighbors (directed graph edges) ++ BlockPosition self; // UpdateNode's own position ++ BlockPosition parent; // Which block pos spawned/updated this node ++ Type type = Type.UNKNOWN; // unknown, redstone wire, other type of block ++ int layer; // Highest layer this node is scheduled in ++ boolean visited; // To keep track of information flow direction, visited restone wire is marked ++ int xbias, zbias; // Remembers directionality of ancestor nodes; helps eliminate directional ambiguities. ++ } ++ ++ /* ++ * Keep track of all block positions discovered during search and their current states. ++ * We want to remember one entry for each position. ++ */ ++ private final Map nodeCache = Maps.newHashMap(); ++ ++ /* ++ * For a newly created UpdateNode object, determine what type of block it is. ++ */ ++ private void identifyNode(final World worldIn, final UpdateNode upd1) { ++ final BlockPosition pos = upd1.self; ++ final IBlockData oldState = worldIn.getType(pos); ++ upd1.currentState = oldState; ++ ++ // Some neighbors of redstone wire are other kinds of blocks. ++ // These need to receive block updates to inform them that ++ // redstone wire values have changed. ++ final Block block = oldState.getBlock(); ++ if (block != wire) { ++ // Mark this block as not redstone wire and therefore ++ // requiring updates ++ upd1.type = UpdateNode.Type.OTHER; ++ ++ // Non-redstone blocks may propagate updates, but those updates ++ // are not handled by this accelerator. Therefore, we do not ++ // expand this position's neighbors. ++ return; ++ } ++ ++ // One job of BlockRedstoneWire.neighborChanged is to convert ++ // redstone wires to items if the block beneath was removed. ++ // With this accelerator, BlockRedstoneWire.neighborChanged ++ // is only typically called for a single wire block, while ++ // others are processed internally by the breadth first search ++ // algorithm. To preserve this game behavior, this check must ++ // be replicated here. ++ if (!wire.canPlace(null, worldIn, pos)) { ++ // Pop off the redstone dust ++ Block.a(worldIn, pos, new ItemStack(Items.REDSTONE)); // TODO ++ worldIn.setAir(pos); ++ ++ // Mark this position as not being redstone wire ++ upd1.type = UpdateNode.Type.OTHER; ++ ++ // Note: Sending updates to air blocks leads to an empty method. ++ // Testing shows this to be faster than explicitly avoiding updates to ++ // air blocks. ++ return; ++ } ++ ++ // If the above conditions fail, then this is a redstone wire block. ++ upd1.type = UpdateNode.Type.REDSTONE; ++ } ++ ++ /* ++ * Given which redstone wire blocks have been visited and not visited ++ * around the position currently being updated, compute the cardinal ++ * direction that is "forward." ++ * ++ * rx is the forward direction along the West/East axis ++ * rz is the forward direction along the North/South axis ++ */ ++ static private int computeHeading(final int rx, final int rz) { ++ // rx and rz can only take on values -1, 0, and 1, so we can ++ // compute a code number that allows us to use a single switch ++ // to determine the heading. ++ final int code = (rx + 1) + 3 * (rz + 1); ++ switch (code) { ++ case 0: { ++ // Both rx and rz are -1 (northwest) ++ // Randomly choose one to be forward. ++ final int j = ThreadLocalRandom.current().nextInt(0, 1); ++ return (j == 0) ? North : West; ++ } ++ case 1: { ++ // rx=0, rz=-1 ++ // Definitively North ++ return North; ++ } ++ case 2: { ++ // rx=1, rz=-1 (northeast) ++ // Choose randomly between north and east ++ final int j = ThreadLocalRandom.current().nextInt(0, 1); ++ return (j == 0) ? North : East; ++ } ++ case 3: { ++ // rx=-1, rz=0 ++ // Definitively West ++ return West; ++ } ++ case 4: { ++ // rx=0, rz=0 ++ // Heading is completely ambiguous. Choose ++ // randomly among the four cardinal directions. ++ return ThreadLocalRandom.current().nextInt(0, 4); ++ } ++ case 5: { ++ // rx=1, rz=0 ++ // Definitively East ++ return East; ++ } ++ case 6: { ++ // rx=-1, rz=1 (southwest) ++ // Choose randomly between south and west ++ final int j = ThreadLocalRandom.current().nextInt(0, 1); ++ return (j == 0) ? South : West; ++ } ++ case 7: { ++ // rx=0, rz=1 ++ // Definitively South ++ return South; ++ } ++ case 8: { ++ // rx=1, rz=1 (southeast) ++ // Choose randomly between south and east ++ final int j = ThreadLocalRandom.current().nextInt(0, 1); ++ return (j == 0) ? South : East; ++ } ++ } ++ ++ // We should never get here ++ return ThreadLocalRandom.current().nextInt(0, 4); ++ } ++ ++ // Select whether to use updateSurroundingRedstone from BlockRedstoneWire (old) ++ // or this helper class (new) ++ private static final boolean old_current_change = false; ++ ++ /* ++ * Process a node whose neighboring redstone wire has experienced value changes. ++ */ ++ private void updateNode(final World worldIn, final UpdateNode upd1, final int layer) { ++ final BlockPosition pos = upd1.self; ++ ++ // Mark this redstone wire as having been visited so that it can be used ++ // to calculate direction of information flow. ++ upd1.visited = true; ++ ++ // Look up the last known state. ++ // Due to the way other redstone components are updated, we do not ++ // have to worry about a state changing behind our backs. The rare ++ // exception is handled by scheduleReentrantNeighborChanged. ++ final IBlockData oldState = upd1.currentState; ++ ++ // Ask the wire block to compute its power level from its neighbors. ++ // This will also update the wire's power level and return a new ++ // state if it has changed. When a wire power level is changed, ++ // calculateCurrentChanges will immediately update the block state in the world ++ // and return the same value here to be cached in the corresponding ++ // UpdateNode object. ++ IBlockData newState; ++ if (old_current_change) { ++ newState = wire.calculateCurrentChanges(worldIn, pos, pos, oldState); ++ } else { ++ // Looking up block state is slow. This accelerator includes a version of ++ // calculateCurrentChanges that uses cahed wire values for a ++ // significant performance boost. ++ newState = this.calculateCurrentChanges(worldIn, upd1); ++ } ++ ++ // Only inform neighbors if the state has changed ++ if (newState != oldState) { ++ // Store the new state ++ upd1.currentState = newState; ++ ++ // Inform neighbors of the change ++ propagateChanges(worldIn, upd1, layer); ++ } ++ } ++ ++ /* ++ * This identifies the neighboring positions of a new UpdateNode object, ++ * determines their types, and links those to into the graph. Then based on ++ * what nodes in the redstone wire graph have been visited, the neighbors ++ * are reordered left-to-right relative to the direction of information flow. ++ */ ++ private void findNeighbors(final World worldIn, final UpdateNode upd1) { ++ final BlockPosition pos = upd1.self; ++ ++ // Get the list of neighbor coordinates ++ final BlockPosition[] neighbors = computeAllNeighbors(pos); ++ ++ // Temporary array of neighbors in cardinal ordering ++ final UpdateNode[] neighbor_nodes = new UpdateNode[24]; ++ ++ // Target array of neighbors sorted left-to-right ++ upd1.neighbor_nodes = new UpdateNode[24]; ++ ++ for (int i=0; i<24; i++) { ++ // Look up each neighbor in the node cache ++ final BlockPosition pos2 = neighbors[i]; ++ UpdateNode upd2 = nodeCache.get(pos2); ++ if (upd2 == null) { ++ // If this is a previously unreached position, create ++ // a new update node, add it to the cache, and identify what it is. ++ upd2 = new UpdateNode(); ++ upd2.self = pos2; ++ upd2.parent = pos; ++ nodeCache.put(pos2, upd2); ++ identifyNode(worldIn, upd2); ++ } ++ ++ // For non-redstone blocks, any of the 24 neighboring positions ++ // should receive a block update. However, some block coordinates ++ // may contain a redstone wire that does not directly connect to the ++ // one being expanded. To avoid redundant calculations and confusing ++ // cross-talk, those neighboring positions are not included. ++ if (update_redstone[i] || upd2.type != UpdateNode.Type.REDSTONE) { ++ neighbor_nodes[i] = upd2; ++ } ++ } ++ ++ // Determine the directions from which the redstone signal may have come from. This ++ // checks for redstone wire at the same Y level and also Y+1 and Y-1, relative to the ++ // block being expanded. ++ final boolean fromWest = (neighbor_nodes[0].visited || neighbor_nodes[7].visited || neighbor_nodes[8].visited); ++ final boolean fromEast = (neighbor_nodes[1].visited || neighbor_nodes[12].visited || neighbor_nodes[13].visited); ++ final boolean fromNorth = (neighbor_nodes[4].visited || neighbor_nodes[17].visited || neighbor_nodes[20].visited); ++ final boolean fromSouth = (neighbor_nodes[5].visited || neighbor_nodes[18].visited || neighbor_nodes[21].visited); ++ ++ int cx = 0, cz = 0; ++ if (fromWest) cx += 1; ++ if (fromEast) cx -= 1; ++ if (fromNorth) cz += 1; ++ if (fromSouth) cz -= 1; ++ ++ int heading; ++ if (cx==0 && cz==0) { ++ // If there is no clear direction, try to inherit the heading from ancestor nodes. ++ heading = computeHeading(upd1.xbias, upd1.zbias); ++ ++ // Propagate that heading to descendant nodes. ++ for (int i=0; i<24; i++) { ++ final UpdateNode nn = neighbor_nodes[i]; ++ if (nn != null) { ++ nn.xbias = upd1.xbias; ++ nn.zbias = upd1.zbias; ++ } ++ } ++ } else { ++ if (cx != 0 && cz != 0) { ++ // If the heading is somewhat ambiguous, try to disambiguate based on ++ // ancestor nodes. ++ if (upd1.xbias != 0) cz = 0; ++ if (upd1.zbias != 0) cx = 0; ++ } ++ heading = computeHeading(cx, cz); ++ ++ // Propagate that heading to descendant nodes. ++ for (int i=0; i<24; i++) { ++ final UpdateNode nn = neighbor_nodes[i]; ++ if (nn != null) { ++ nn.xbias = cx; ++ nn.zbias = cz; ++ } ++ } ++ } ++ ++ // Reorder neighboring UpdateNode objects according to the forward direction ++ // determined above. ++ orientNeighbors(neighbor_nodes, upd1.neighbor_nodes, heading); ++ } ++ ++ /* ++ * For any redstone wire block in layer N, inform neighbors to recompute their states ++ * in layers N+1 and N+2; ++ */ ++ private void propagateChanges(final World worldIn, final UpdateNode upd1, final int layer) { ++ if (upd1.neighbor_nodes == null) { ++ // If this node has not been expanded yet, find its neighbors ++ findNeighbors(worldIn, upd1); ++ } ++ ++ final BlockPosition pos = upd1.self; ++ ++ // All neighbors may be scheduled for layer N+1 ++ final int layer1 = layer + 1; ++ ++ // If the node being updated (upd1) has already been expanded, then merely ++ // schedule updates to its neighbors. ++ for (int i = 0; i < 24; i++) { ++ final UpdateNode upd2 = upd1.neighbor_nodes[i]; ++ ++ // This test ensures that an UpdateNode is never scheduled to the same layer ++ // more than once. Also, skip non-connecting redstone wire blocks ++ if (upd2 != null && layer1 > upd2.layer) { ++ upd2.layer = layer1; ++ updateQueue1.add(upd2); ++ ++ // Keep track of which block updated this neighbor ++ upd2.parent = pos; ++ } ++ } ++ ++ // Nodes above and below are scheduled ALSO for layer N+2 ++ final int layer2 = layer + 2; ++ ++ // Repeat of the loop above, but only for the first four (above and below) neighbors ++ // and for layer N+2; ++ for (int i = 0; i < 4; i++) { ++ final UpdateNode upd2 = upd1.neighbor_nodes[i]; ++ if (upd2 != null && layer2 > upd2.layer) { ++ upd2.layer = layer2; ++ updateQueue2.add(upd2); ++ upd2.parent = pos; ++ } ++ } ++ } ++ ++ // The breadth-first search below will send block updates to blocks ++ // that are not redstone wire. If one of those updates results in ++ // a distant redstone wire getting an update, then this.neighborChanged ++ // will get called. This would be a reentrant call, and ++ // it is necessary to properly integrate those updates into the ++ // on-going search through redstone wire. Thus, we make the layer ++ // currently being processed visible at the object level. ++ ++ // The current layer being processed by the breadth-first search ++ private int currentWalkLayer = 0; ++ ++ private void shiftQueue() { ++ final List t = updateQueue0; ++ t.clear(); ++ updateQueue0 = updateQueue1; ++ updateQueue1 = updateQueue2; ++ updateQueue2 = t; ++ } ++ ++ /* ++ * Perform a breadth-first (layer by layer) traversal through redstone ++ * wire blocks, propagating value changes to neighbors in an order ++ * that is a function of distance from the initial call to ++ * this.neighborChanged. ++ */ ++ private void breadthFirstWalk(final World worldIn) { ++ shiftQueue(); ++ currentWalkLayer = 1; ++ ++ // Loop over all layers ++ while (updateQueue0.size()>0 || updateQueue1.size()>0) { ++ // Get the set of blocks in this layer ++ final List thisLayer = updateQueue0; ++ ++ // Loop over all blocks in the layer. Recall that ++ // this is a List, preserving the insertion order of ++ // left-to-right based on direction of information flow. ++ for (UpdateNode upd : thisLayer) { ++ if (upd.type == UpdateNode.Type.REDSTONE) { ++ // If the node is is redstone wire, ++ // schedule updates to neighbors if its value ++ // has changed. ++ updateNode(worldIn, upd, currentWalkLayer); ++ } else { ++ // If this block is not redstone wire, send a block update. ++ // Redstone wire blocks get state updates, but they don't ++ // need block updates. Only non-redstone neighbors need updates. ++ ++ // World.neighborChanged is called from ++ // World.notifyNeighborsOfStateChange, and ++ // notifyNeighborsOfStateExcept. We don't use ++ // World.notifyNeighborsOfStateChange here, since we are ++ // already keeping track of all of the neighbor positions ++ // that need to be updated. All on its own, handling neighbors ++ // this way reduces block updates by 1/3 (24 instead of 36). ++ worldIn.neighborChanged(upd.self, wire, upd.parent); ++ } ++ } ++ ++ // Move on to the next layer ++ shiftQueue(); ++ currentWalkLayer++; ++ } ++ ++ currentWalkLayer = 0; ++ } ++ ++ /* ++ * Normally, when Minecraft is computing redstone wire power changes, and a wire power level ++ * change sends a block update to a neighboring functional component (e.g. piston, repeater, etc.), ++ * those updates are queued. Only once all redstone wire updates are complete will any component ++ * action generate any further block updates to redstone wire. Instant repeater lines, for instance, ++ * will process all wire updates for one redstone line, after which the pistons will zero-tick, ++ * after which the next redstone line performs all of its updates. Thus, each wire is processed in its ++ * own discrete wave. ++ * ++ * However, there are some corner cases where this pattern breaks, with a proof of concept discovered ++ * by Rays Works, which works the same in vanilla. The scenario is as follows: ++ * (1) A redstone wire is conducting a signal. ++ * (2) Part-way through that wave of updates, a neighbor is updated that causes an update to a completely ++ * separate redstone wire. ++ * (3) This results in a call to BlockRedstoneWire.neighborChanged for that other wire, in the middle of ++ * an already on-going propagation through the first wire. ++ * ++ * The vanilla code, being depth-first, would end up fully processing the second wire before going back ++ * to finish processing the first one. (Although technically, vanilla has no special concept of "being ++ * in the middle" of processing updates to a wire.) For the breadth-first algorithm, we give this ++ * situation special handling, where the updates for the second wire are incorporated into the schedule ++ * for the first wire, and then the callstack is allowed to unwind back to the on-going search loop in ++ * order to continue processing both the first and second wire in the order of distance from the initial ++ * trigger. ++ */ ++ private IBlockData scheduleReentrantNeighborChanged(final World worldIn, final BlockPosition pos, final IBlockData newState, final BlockPosition source) { ++ if (source != null) { ++ // If the cause of the redstone wire update is known, we can use that to help determine ++ // direction of information flow. ++ UpdateNode src = nodeCache.get(source); ++ if (src == null) { ++ src = new UpdateNode(); ++ src.self = source; ++ src.parent = source; ++ src.visited = true; ++ identifyNode(worldIn, src); ++ nodeCache.put(source, src); ++ } ++ } ++ ++ // Find or generate a node for the redstone block position receiving the update ++ UpdateNode upd = nodeCache.get(pos); ++ if (upd == null) { ++ upd = new UpdateNode(); ++ upd.self = pos; ++ upd.parent = pos; ++ upd.visited = true; ++ identifyNode(worldIn, upd); ++ nodeCache.put(pos, upd); ++ } ++ upd.currentState = newState; ++ ++ // Receiving this block update may mean something in the world changed. ++ // Therefore we clear the cached block info about all neighbors of ++ // the position receiving the update and then re-identify what they are. ++ if (upd.neighbor_nodes != null) { ++ for (int i=0; i<24; i++) { ++ final UpdateNode upd2 = upd.neighbor_nodes[i]; ++ if (upd2 == null) continue; ++ upd2.type = UpdateNode.Type.UNKNOWN; ++ upd2.currentState = null; ++ identifyNode(worldIn, upd2); ++ } ++ } ++ ++ // The block at 'pos' is a redstone wire and has been updated already by calling ++ // wire.calculateCurrentChanges, so we don't schedule that. However, we do need ++ // to schedule its neighbors. By passing the current value of 'currentWalkLayer' to ++ // propagateChanges, the neighbors of 'pos' are scheduled for layers currentWalkLayer+1 ++ // and currentWalkLayer+2. ++ propagateChanges(worldIn, upd, currentWalkLayer); ++ ++ // Return here. The call stack will unwind back to the first call to ++ // updateSurroundingRedstone, whereupon the new updates just scheduled will ++ // be propagated. This also facilitates elimination of superfluous and ++ // redundant block updates. ++ return newState; ++ } ++ ++ /* ++ * New version of pre-existing updateSurroundingRedstone, which is called from ++ * wire.updateSurroundingRedstone, which is called from wire.neighborChanged and a ++ * few other methods in BlockRedstoneWire. This sets off the breadth-first ++ * walk through all redstone dust connected to the initial position triggered. ++ */ ++ public IBlockData updateSurroundingRedstone(final World worldIn, final BlockPosition pos, final IBlockData state, final BlockPosition source) { ++ // Check this block's neighbors and see if its power level needs to change ++ // Use the calculateCurrentChanges method in BlockRedstoneWire since we have no ++ // cached block states at this point. ++ final IBlockData newState = wire.calculateCurrentChanges(worldIn, pos, pos, state); ++ ++ // If no change, exit ++ if (newState == state) { ++ return state; ++ } ++ ++ // Check to see if this update was received during an on-going breadth first search ++ if (currentWalkLayer > 0 || nodeCache.size() > 0) { ++ // As breadthFirstWalk progresses, it sends block updates to neighbors. Some of those ++ // neighbors may affect the world so as to cause yet another redstone wire block to receive ++ // an update. If that happens, we need to integrate those redstone wire updates into the ++ // already on-going graph walk being performed by breadthFirstWalk. ++ return scheduleReentrantNeighborChanged(worldIn, pos, newState, source); ++ } ++ // If there are no on-going walks through redstone wire, then start a new walk. ++ ++ // If the source of the block update to the redstone wire at 'pos' is known, we can use ++ // that to help determine the direction of information flow. ++ if (source != null) { ++ final UpdateNode src = new UpdateNode(); ++ src.self = source; ++ src.parent = source; ++ src.visited = true; ++ nodeCache.put(source, src); ++ identifyNode(worldIn, src); ++ } ++ ++ // Create a node representing the block at 'pos', and then propagate updates ++ // to its neighbors. As stated above, the call to wire.calculateCurrentChanges ++ // already performs the update to the block at 'pos', so it is not added to the schedule. ++ final UpdateNode upd = new UpdateNode(); ++ upd.self = pos; ++ upd.parent = source!=null ? source : pos; ++ upd.currentState = newState; ++ upd.type = UpdateNode.Type.REDSTONE; ++ upd.visited = true; ++ nodeCache.put(pos, upd); ++ propagateChanges(worldIn, upd, 0); ++ ++ // Perform the walk over all directly reachable redstone wire blocks, propagating wire value ++ // updates in a breadth first order out from the initial update received for the block at 'pos'. ++ breadthFirstWalk(worldIn); ++ ++ // With the whole search completed, clear the list of all known blocks. ++ // We do not want to keep around state information that may be changed by other code. ++ // In theory, we could cache the neighbor block positions, but that is a separate ++ // optimization. ++ nodeCache.clear(); ++ ++ return newState; ++ } ++ ++ // For any array of neighbors in an UpdateNode object, these are always ++ // the indices of the four immediate neighbors at the same Y coordinate. ++ private static final int[] rs_neighbors = {4, 5, 6, 7}; ++ private static final int[] rs_neighbors_up = {9, 11, 13, 15}; ++ private static final int[] rs_neighbors_dn = {8, 10, 12, 14}; ++ ++ /* ++ * Updated calculateCurrentChanges that is optimized for speed and uses ++ * the UpdateNode's neighbor array to find the redstone states of neighbors ++ * that might power it. ++ */ ++ private IBlockData calculateCurrentChanges(final World worldIn, final UpdateNode upd) { ++ IBlockData state = upd.currentState; ++ final int i = state.get(BlockRedstoneWire.POWER).intValue(); ++ int j = 0; ++ j = getMaxCurrentStrength(upd, j); ++ int l = 0; ++ ++ wire.setCanProvidePower(false); ++ // Unfortunately, World.isBlockIndirectlyGettingPowered is complicated, ++ // and I'm not ready to try to replicate even more functionality from ++ // elsewhere in Minecraft into this accelerator. So sadly, we must ++ // suffer the performance hit of this very expensive call. If there ++ // is consistency to what this call returns, we may be able to cache it. ++ final int k = worldIn.isBlockIndirectlyGettingPowered(upd.self); ++ wire.setCanProvidePower(true); ++ ++ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. ++ // If 'k' has the highest level of all neighbors, then the power level of this ++ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the ++ // following loop can affect the power level of the wire. Therefore, the loop is ++ // skipped if k is already 15. ++ if (k < 15) { ++ if (upd.neighbor_nodes == null) { ++ // If this node's neighbors are not known, expand the node ++ findNeighbors(worldIn, upd); ++ } ++ ++ // These remain constant, so pull them out of the loop. ++ // Regardless of which direction is forward, the UpdateNode for the ++ // position directly above the node being calculated is always ++ // at index 1. ++ UpdateNode center_up = upd.neighbor_nodes[1]; ++ boolean center_up_is_cube = center_up.currentState.isOccluding(worldIn, center_up.self); // TODO ++ ++ for (int m = 0; m < 4; m++) { ++ // Get the neighbor array index of each of the four cardinal ++ // neighbors. ++ int n = rs_neighbors[m]; ++ ++ // Get the max redstone power level of each of the cardinal ++ // neighbors ++ UpdateNode neighbor = upd.neighbor_nodes[n]; ++ l = getMaxCurrentStrength(neighbor, l); ++ ++ // Also check the positions above and below the cardinal ++ // neighbors ++ boolean neighbor_is_cube = neighbor.currentState.isOccluding(worldIn, neighbor.self); // TODO ++ if (!neighbor_is_cube) { ++ UpdateNode neighbor_down = upd.neighbor_nodes[rs_neighbors_dn[m]]; ++ l = getMaxCurrentStrength(neighbor_down, l); ++ } else ++ if (!center_up_is_cube) { ++ UpdateNode neighbor_up = upd.neighbor_nodes[rs_neighbors_up[m]]; ++ l = getMaxCurrentStrength(neighbor_up, l); ++ } ++ } ++ } ++ ++ // The new code sets this RedstoneWire block's power level to the highest neighbor ++ // minus 1. This usually results in wire power levels dropping by 2 at a time. ++ // This optimization alone has no impact on update order, only the number of updates. ++ j = l - 1; ++ ++ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will ++ // always be in the range of 0 to 15, the following if will correct that. ++ if (k > j) j = k; ++ ++ // egg82's amendment ++ // Adding Bukkit's BlockRedstoneEvent - er.. event. ++ if (i != j) { ++ BlockRedstoneEvent event = new BlockRedstoneEvent(worldIn.getWorld().getBlockAt(upd.self.getX(), upd.self.getY(), upd.self.getZ()), i, j); ++ worldIn.getServer().getPluginManager().callEvent(event); ++ j = event.getNewCurrent(); ++ } ++ ++ if (i != j) { ++ // If the power level has changed from its previous value, compute a new state ++ // and set it in the world. ++ // Possible optimization: Don't commit state changes to the world until they ++ // need to be known by some nearby non-redstone-wire block. ++ BlockPosition pos = new BlockPosition(upd.self.getX(), upd.self.getY(), upd.self.getZ()); ++ if (wire.canPlace(null, worldIn, pos)) { ++ state = state.set(BlockRedstoneWire.POWER, Integer.valueOf(j)); ++ worldIn.setTypeAndData(upd.self, state, 2); ++ } ++ } ++ ++ return state; ++ } ++ ++ /* ++ * Optimized function to compute a redstone wire's power level based on cached ++ * state. ++ */ ++ private static int getMaxCurrentStrength(final UpdateNode upd, final int strength) { ++ if (upd.type != UpdateNode.Type.REDSTONE) return strength; ++ final int i = upd.currentState.get(BlockRedstoneWire.POWER).intValue(); ++ return i > strength ? i : strength; ++ } ++} +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 9369a0c6c0ae2d8518ebfb17f2c93ead2647ab8d..307a89c431739ed15d8869faace7b08927626f60 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -659,6 +659,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + + } + ++ public void neighborChanged(BlockPosition pos, Block blockIn, BlockPosition fromPos) { a(pos, blockIn, fromPos); } // Paper - OBFHELPER + public void a(BlockPosition blockposition, Block block, BlockPosition blockposition1) { + if (!this.isClientSide) { + IBlockData iblockdata = this.getType(blockposition); +@@ -1287,6 +1288,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return this.getBlockFacePower(blockposition.down(), EnumDirection.DOWN) > 0 ? true : (this.getBlockFacePower(blockposition.up(), EnumDirection.UP) > 0 ? true : (this.getBlockFacePower(blockposition.north(), EnumDirection.NORTH) > 0 ? true : (this.getBlockFacePower(blockposition.south(), EnumDirection.SOUTH) > 0 ? true : (this.getBlockFacePower(blockposition.west(), EnumDirection.WEST) > 0 ? true : this.getBlockFacePower(blockposition.east(), EnumDirection.EAST) > 0)))); + } + ++ public int isBlockIndirectlyGettingPowered(BlockPosition pos) { return this.s(pos); } // Paper - OBFHELPER + public int s(BlockPosition blockposition) { + int i = 0; + EnumDirection[] aenumdirection = World.a; +diff --git a/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java b/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java +index 60f0e582199472f9c5ef26e12ee1da0c3867254e..71ba55d36f5bc8a417930015c31553b30cf3e8dd 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.level.block; + ++import com.destroystokyo.paper.PaperConfig; ++import com.destroystokyo.paper.util.RedstoneWireTurbo; + import com.google.common.collect.ImmutableMap; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; +@@ -50,7 +52,7 @@ public class BlockRedstoneWire extends Block { + private final Map j = Maps.newHashMap(); + private static final Vector3fa[] k = new Vector3fa[16]; + private final IBlockData o; +- private boolean p = true; ++ private boolean p = true; public final boolean canProvidePower() { return this.p; } public final void setCanProvidePower(boolean value) { this.p = value; } // Paper - OBFHELPER + + public BlockRedstoneWire(BlockBase.Info blockbase_info) { + super(blockbase_info); +@@ -237,6 +239,121 @@ public class BlockRedstoneWire extends Block { + return iblockdata.d(iblockaccess, blockposition, EnumDirection.UP) || iblockdata.a(Blocks.HOPPER); + } + ++ // Paper start - Optimize redstone ++ // The bulk of the new functionality is found in RedstoneWireTurbo.java ++ RedstoneWireTurbo turbo = new RedstoneWireTurbo(this); ++ ++ /* ++ * Modified version of pre-existing updateSurroundingRedstone, which is called from ++ * this.neighborChanged and a few other methods in this class. ++ * Note: Added 'source' argument so as to help determine direction of information flow ++ */ ++ private void updateSurroundingRedstone(World worldIn, BlockPosition pos, IBlockData state, BlockPosition source) { ++ if (worldIn.paperConfig.useEigencraftRedstone) { ++ turbo.updateSurroundingRedstone(worldIn, pos, state, source); ++ return; ++ } ++ a(worldIn, pos, state); ++ } ++ ++ /* ++ * Slightly modified method to compute redstone wire power levels from neighboring blocks. ++ * Modifications cut the number of power level changes by about 45% from vanilla, and this ++ * optimization synergizes well with the breadth-first search implemented in ++ * RedstoneWireTurbo. ++ * Note: RedstoneWireTurbo contains a faster version of this code. ++ * Note: Made this public so that RedstoneWireTurbo can access it. ++ */ ++ public IBlockData calculateCurrentChanges(World worldIn, BlockPosition pos1, BlockPosition pos2, IBlockData state) { ++ IBlockData iblockstate = state; ++ int i = state.get(POWER); ++ int j = 0; ++ j = this.getPower(j, worldIn.getType(pos2)); ++ this.setCanProvidePower(false); ++ int k = worldIn.isBlockIndirectlyGettingPowered(pos1); ++ this.setCanProvidePower(true); ++ ++ if (!worldIn.paperConfig.useEigencraftRedstone) { ++ // This code is totally redundant to if statements just below the loop. ++ if (k > 0 && k > j - 1) { ++ j = k; ++ } ++ } ++ ++ int l = 0; ++ ++ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. ++ // If 'k' has the highest level of all neighbors, then the power level of this ++ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the ++ // following loop can affect the power level of the wire. Therefore, the loop is ++ // skipped if k is already 15. ++ if (!worldIn.paperConfig.useEigencraftRedstone || k < 15) { ++ for (EnumDirection enumfacing : EnumDirection.EnumDirectionLimit.HORIZONTAL) { ++ BlockPosition blockpos = pos1.shift(enumfacing); ++ boolean flag = blockpos.getX() != pos2.getX() || blockpos.getZ() != pos2.getZ(); ++ ++ if (flag) { ++ l = this.getPower(l, worldIn.getType(blockpos)); ++ } ++ ++ if (worldIn.getType(blockpos).isOccluding(worldIn, blockpos) && !worldIn.getType(pos1.up()).isOccluding(worldIn, pos1)) { ++ if (flag && pos1.getY() >= pos2.getY()) { ++ l = this.getPower(l, worldIn.getType(blockpos.up())); ++ } ++ } else if (!worldIn.getType(blockpos).isOccluding(worldIn, blockpos) && flag && pos1.getY() <= pos2.getY()) { ++ l = this.getPower(l, worldIn.getType(blockpos.down())); ++ } ++ } ++ } ++ ++ if (!worldIn.paperConfig.useEigencraftRedstone) { ++ // The old code would decrement the wire value only by 1 at a time. ++ if (l > j) { ++ j = l - 1; ++ } else if (j > 0) { ++ --j; ++ } else { ++ j = 0; ++ } ++ ++ if (k > j - 1) { ++ j = k; ++ } ++ } else { ++ // The new code sets this RedstoneWire block's power level to the highest neighbor ++ // minus 1. This usually results in wire power levels dropping by 2 at a time. ++ // This optimization alone has no impact on update order, only the number of updates. ++ j = l - 1; ++ ++ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will ++ // always be in the range of 0 to 15, the following if will correct that. ++ if (k > j) j = k; ++ } ++ ++ if (i != j) { ++ state = state.set(POWER, j); ++ ++ if (worldIn.getType(pos1) == iblockstate) { ++ worldIn.setTypeAndData(pos1, state, 2); ++ } ++ ++ // 1.16(.1?) dropped the need for blocks needing updates. ++ // Whether this is necessary after all is to be seen. ++// if (!worldIn.paperConfig.useEigencraftRedstone) { ++// // The new search algorithm keeps track of blocks needing updates in its own data structures, ++// // so only add anything to blocksNeedingUpdate if we're using the vanilla update algorithm. ++// this.getBlocksNeedingUpdate().add(pos1); ++// ++// for (EnumDirection enumfacing1 : EnumDirection.values()) { ++// this.getBlocksNeedingUpdate().add(pos1.shift(enumfacing1)); ++// } ++// } ++ } ++ ++ return state; ++ } ++ // Paper end ++ + private void a(World world, BlockPosition blockposition, IBlockData iblockdata) { + int i = this.a(world, blockposition); + +@@ -306,6 +423,8 @@ public class BlockRedstoneWire extends Block { + return Math.max(i, j - 1); + } + ++ private int getPower(int min, IBlockData iblockdata) { return Math.max(min, getPower(iblockdata)); } // Paper - Optimize redstone ++ private int getPower(IBlockData iblockdata) { return this.o(iblockdata); } // Paper - OBFHELPER + private int o(IBlockData iblockdata) { + return iblockdata.a((Block) this) ? (Integer) iblockdata.get(BlockRedstoneWire.POWER) : 0; + } +@@ -328,7 +447,7 @@ public class BlockRedstoneWire extends Block { + @Override + public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { + if (!iblockdata1.a(iblockdata.getBlock()) && !world.isClientSide) { +- this.a(world, blockposition, iblockdata); ++ this.updateSurroundingRedstone(world, blockposition, iblockdata, null); // Paper - Optimize redstone + Iterator iterator = EnumDirection.EnumDirectionLimit.VERTICAL.iterator(); + + while (iterator.hasNext()) { +@@ -355,7 +474,7 @@ public class BlockRedstoneWire extends Block { + world.applyPhysics(blockposition.shift(enumdirection), this); + } + +- this.a(world, blockposition, iblockdata); ++ this.updateSurroundingRedstone(world, blockposition, iblockdata, null); // Paper - Optimize redstone + this.d(world, blockposition); + } + } +@@ -390,7 +509,7 @@ public class BlockRedstoneWire extends Block { + public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { + if (!world.isClientSide) { + if (iblockdata.canPlace(world, blockposition)) { +- this.a(world, blockposition, iblockdata); ++ this.updateSurroundingRedstone(world, blockposition, iblockdata, blockposition1); // Paper - Optimize redstone + } else { + c(iblockdata, world, blockposition); + world.a(blockposition, false); diff --git a/patches/server-unmapped/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch b/patches/server-unmapped/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch new file mode 100644 index 0000000000..73ff3451e7 --- /dev/null +++ b/patches/server-unmapped/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Thu, 27 Aug 2020 16:57:25 -0400 +Subject: [PATCH] Fix hex colors not working in some kick messages + + +diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java +index c4ba5c02c1be94bda2eb652415b48bf5a38400f6..26fe1f612e9dab37e5bf6bc431eb362bd7e4803a 100644 +--- a/src/main/java/net/minecraft/server/network/HandshakeListener.java ++++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java +@@ -50,7 +50,7 @@ public class HandshakeListener implements PacketHandshakingInListener { + synchronized (throttleTracker) { + if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { + throttleTracker.put(address, currentTime); +- ChatMessage chatmessage = new ChatMessage(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message ++ IChatBaseComponent chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage, true)[0]; // Paper - Configurable connection throttle kick message // Paper - Fix hex colors not working in some kick messages + this.c.sendPacket(new PacketLoginOutDisconnect(chatmessage)); + this.c.close(chatmessage); + return; +@@ -76,12 +76,12 @@ public class HandshakeListener implements PacketHandshakingInListener { + } + // CraftBukkit end + if (packethandshakinginsetprotocol.c() != SharedConstants.getGameVersion().getProtocolVersion()) { +- ChatMessage chatmessage; ++ IChatBaseComponent chatmessage; // Paper - Fix hex colors not working in some kick messages + + if (packethandshakinginsetprotocol.c() < 754) { +- chatmessage = new ChatMessage( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) ); // Spigot ++ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages + } else { +- chatmessage = new ChatMessage( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) ); // Spigot ++ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages + } + + this.c.sendPacket(new PacketLoginOutDisconnect(chatmessage)); +@@ -99,7 +99,7 @@ public class HandshakeListener implements PacketHandshakingInListener { + if (event.callEvent()) { + // If we've failed somehow, let the client know so and go no further. + if (event.isFailed()) { +- chatmessage = new ChatMessage(event.getFailMessage()); ++ IChatBaseComponent chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(event.getFailMessage(), true)[0]; // Paper - Fix hex colors not working in some kick messages + this.getNetworkManager().sendPacket(new PacketLoginOutDisconnect(chatmessage)); + this.getNetworkManager().close(chatmessage); + return; +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index f40736a836d6097930b9704246c7077617b1f962..190fc9f764420ea5fd20d629101644aeda2d8239 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -106,14 +106,7 @@ public class LoginListener implements PacketLoginInListener { + // CraftBukkit start + @Deprecated + public void disconnect(String s) { +- try { +- IChatBaseComponent ichatbasecomponent = new ChatComponentText(s); +- LoginListener.LOGGER.info("Disconnecting {}: {}", this.d(), s); +- this.networkManager.sendPacket(new PacketLoginOutDisconnect(ichatbasecomponent)); +- this.networkManager.close(ichatbasecomponent); +- } catch (Exception exception) { +- LoginListener.LOGGER.error("Error whilst disconnecting player", exception); +- } ++ disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s, true)[0]); // Paper - Fix hex colors not working in some kick messages + } + // CraftBukkit end + diff --git a/patches/server-unmapped/0560-PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server-unmapped/0560-PortalCreateEvent-needs-to-know-its-entity.patch new file mode 100644 index 0000000000..cfced66829 --- /dev/null +++ b/patches/server-unmapped/0560-PortalCreateEvent-needs-to-know-its-entity.patch @@ -0,0 +1,135 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Fri, 21 Aug 2020 20:57:54 +0200 +Subject: [PATCH] PortalCreateEvent needs to know its entity + + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 800d10db92a956d3ca8a3d569d12862f36044ee9..366ceb65d40c685117d1c79a933864ab91d8aa11 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -368,7 +368,7 @@ public final class ItemStack { + IBlockData block = world.getType(newblockposition); + + if (!(block.getBlock() instanceof BlockTileEntity)) { // Containers get placed automatically +- block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); ++ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true, itemactioncontext); // Paper - pass itemactioncontext + } + + world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getType(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point +diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java +index e6ea1d29c7f3f4cb6039df0e35c8db94b6f38c3e..70c32b7a53a1107cced3491ebac19b0eaf4fec2e 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockFire.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java +@@ -15,6 +15,7 @@ import net.minecraft.core.EnumDirection; + import net.minecraft.server.MCUtil; + import net.minecraft.server.level.WorldServer; + import net.minecraft.world.item.context.BlockActionContext; ++import net.minecraft.world.item.context.ItemActionContext; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.IBlockAccess; +@@ -364,8 +365,10 @@ public class BlockFire extends BlockFireAbstract { + } + + @Override +- public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { +- super.onPlace(iblockdata, world, blockposition, iblockdata1, flag); ++ // Paper start - ItemActionContext param ++ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag, ItemActionContext itemActionContext) { ++ super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext); ++ // Paper end + world.getBlockTickList().a(blockposition, this, a(world.random)); + } + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java +index b86513497b7ca8bde84176f5228ef9c479a73abb..02047bf07c2008c7de8daf3d76b660e25b77bce8 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java +@@ -7,6 +7,7 @@ import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.context.BlockActionContext; ++import net.minecraft.world.item.context.ItemActionContext; + import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.IBlockAccess; + import net.minecraft.world.level.World; +@@ -66,14 +67,17 @@ public abstract class BlockFireAbstract extends Block { + super.a(iblockdata, world, blockposition, entity); + } + ++ // Paper start - ItemActionContext param ++ @Override public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { this.onPlace(iblockdata, world, blockposition, iblockdata1, flag, null); } + @Override +- public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { ++ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag, ItemActionContext itemActionContext) { ++ // Paper end + if (!iblockdata1.a(iblockdata.getBlock())) { + if (a(world)) { + Optional optional = BlockPortalShape.a((GeneratorAccess) world, blockposition, EnumDirection.EnumAxis.X); + + if (optional.isPresent()) { +- ((BlockPortalShape) optional.get()).createPortal(); ++ ((BlockPortalShape) optional.get()).createPortal(itemActionContext); // Paper - pass ItemActionContext param + return; + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +index 2a785ea58a7bdc80c703a60bc6ed602dc8040aa0..9af91784544dbb0555824a91088257659bdf2c3d 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +@@ -32,6 +32,7 @@ import net.minecraft.world.item.EnumColor; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockActionContext; ++import net.minecraft.world.item.context.ItemActionContext; + import net.minecraft.world.level.BlockAccessAir; + import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.IBlockAccess; +@@ -120,6 +121,12 @@ public abstract class BlockBase { + PacketDebug.a(world, blockposition); + } + ++ // Paper start - add ItemActionContext param ++ @Deprecated ++ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag, ItemActionContext itemActionContext) { ++ this.onPlace(iblockdata, world, blockposition, iblockdata1, flag); ++ } ++ // Paper end + @Deprecated + public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { + org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot +diff --git a/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java b/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java +index 7c43a12f86cce829b2afb42ebcc95c2449985c10..0bce061d5a0dd0fc08f0aa4d46ead9326beb4bc7 100644 +--- a/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java ++++ b/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java +@@ -11,6 +11,7 @@ import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsBlock; + import net.minecraft.util.MathHelper; + import net.minecraft.world.entity.EntitySize; ++import net.minecraft.world.item.context.ItemActionContext; + import net.minecraft.world.level.GeneratorAccess; + import net.minecraft.world.level.block.BlockPortal; + import net.minecraft.world.level.block.Blocks; +@@ -182,7 +183,10 @@ public class BlockPortalShape { + } + + // CraftBukkit start - return boolean +- public boolean createPortal() { ++ // Paper start - ItemActionContext param ++ @Deprecated public boolean createPortal() { return this.createPortal(null); } ++ public boolean createPortal(ItemActionContext itemActionContext) { ++ // Paper end + org.bukkit.World bworld = this.b.getMinecraftWorld().getWorld(); + + // Copy below for loop +@@ -191,8 +195,7 @@ public class BlockPortalShape { + BlockPosition.a(this.position, this.position.shift(EnumDirection.UP, this.height - 1).shift(this.d, this.width - 1)).forEach((blockposition) -> { + blocks.setTypeAndData(blockposition, iblockdata, 18); + }); +- +- PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); ++ PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, itemActionContext == null || itemActionContext.getEntity() == null ? null : itemActionContext.getEntity().getBukkitEntity(), PortalCreateEvent.CreateReason.FIRE); // Paper - pass entity param + this.b.getMinecraftWorld().getMinecraftServer().server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { diff --git a/patches/server-unmapped/0561-Fix-CraftTeam-null-check.patch b/patches/server-unmapped/0561-Fix-CraftTeam-null-check.patch new file mode 100644 index 0000000000..52281e3135 --- /dev/null +++ b/patches/server-unmapped/0561-Fix-CraftTeam-null-check.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: foss-mc <69294560+foss-mc@users.noreply.github.com> +Date: Sun, 30 Aug 2020 15:30:29 +0800 +Subject: [PATCH] Fix CraftTeam null check + + +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +index c631934fe9d205a06956c900d5b58a1d8a781c19..d637c2941ad0680299378b58ba0db7f7a6be07dc 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +@@ -254,7 +254,7 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { + + @Override + public boolean hasEntry(String entry) throws IllegalArgumentException, IllegalStateException { +- Validate.notNull("Entry cannot be null"); ++ Validate.notNull(entry, "Entry cannot be null"); // Paper + + CraftScoreboard scoreboard = checkState(); + diff --git a/patches/server-unmapped/0562-Add-more-Evoker-API.patch b/patches/server-unmapped/0562-Add-more-Evoker-API.patch new file mode 100644 index 0000000000..ccde2ad0c9 --- /dev/null +++ b/patches/server-unmapped/0562-Add-more-Evoker-API.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Aug 2020 15:28:35 +0200 +Subject: [PATCH] Add more Evoker API + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java +index 64bfd84e8a5a0c2b1fec7044b688c7cc1083f18a..2aa6b6ca93c25c59ad224348aad1bb34d9bbc6a3 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java +@@ -40,7 +40,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; + + public class EntityEvoker extends EntityIllagerWizard { + +- private EntitySheep bo; ++ private EntitySheep bo; public final EntitySheep getWololoTarget() { return this.bo; } public final void setWololoTarget(EntitySheep sheep) { this.bo = sheep; } // Paper - OBFHELPER + + public EntityEvoker(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -59,7 +59,7 @@ public class EntityEvoker extends EntityIllagerWizard { + this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D)); + this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F)); + this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); +- this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a()); ++ this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix + this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300)); + this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300)); + this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, false)); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java +index 5e8e9d95068342661a962aae9878a7eafaa06207..75a7832e9841921497a9a2d1cfd1b05807fe6ede 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import net.minecraft.world.entity.animal.EntitySheep; + import net.minecraft.world.entity.monster.EntityEvoker; + import net.minecraft.world.entity.monster.EntityIllagerWizard; + import org.bukkit.craftbukkit.CraftServer; +@@ -36,4 +37,17 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { + public void setCurrentSpell(Evoker.Spell spell) { + getHandle().setSpell(spell == null ? EntityIllagerWizard.Spell.NONE : EntityIllagerWizard.Spell.a(spell.ordinal())); + } ++ ++ // Paper start ++ @Override ++ public org.bukkit.entity.Sheep getWololoTarget() { ++ EntitySheep sheep = getHandle().getWololoTarget(); ++ return sheep == null ? null : (org.bukkit.entity.Sheep) sheep.getBukkitEntity(); ++ } ++ ++ @Override ++ public void setWololoTarget(org.bukkit.entity.Sheep sheep) { ++ getHandle().setWololoTarget(sheep == null ? null : ((org.bukkit.craftbukkit.entity.CraftSheep) sheep).getHandle()); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/server-unmapped/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch new file mode 100644 index 0000000000..c34765c878 --- /dev/null +++ b/patches/server-unmapped/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch @@ -0,0 +1,126 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Tue, 11 Aug 2020 19:16:09 +0200 +Subject: [PATCH] Add a way to get translation keys for blocks, entities and + materials + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index 9d2955f05aadd4bbc6dcfec068a55d7fe6950ba0..f2cf33d42839710a3bbdf0c8ea0be28af6fcb19d 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -278,6 +278,7 @@ public class EntityTypes { + return IRegistry.ENTITY_TYPE.getKey(entitytypes); + } + ++ public static Optional> getByName(String name) { return a(name); } // Paper - OBFHELPER + public static Optional> a(String s) { + return IRegistry.ENTITY_TYPE.getOptional(MinecraftKey.a(s)); + } +@@ -431,6 +432,7 @@ public class EntityTypes { + return this.bg; + } + ++ public String getDescriptionId() { return f(); } // Paper - OBFHELPER + public String f() { + if (this.bo == null) { + this.bo = SystemUtils.a("entity", IRegistry.ENTITY_TYPE.getKey(this)); +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index ca513e7b0a416860aba89e41de6a7c5ff42baa69..467121839b94e09f59c64300de9f26d3c6caf1e5 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -56,7 +56,7 @@ public class Item implements IMaterial { + private final FoodInfo foodInfo; + + public static int getId(Item item) { +- return item == null ? 0 : IRegistry.ITEM.a((Object) item); ++ return item == null ? 0 : IRegistry.ITEM.a(item); // Paper - Fix Decompiler Issue + } + + public static Item getById(int i) { +@@ -152,6 +152,7 @@ public class Item implements IMaterial { + return IRegistry.ITEM.getKey(this).getKey(); + } + ++ public String getOrCreateDescriptionId() { return m(); } // Paper - OBFHELPER + protected String m() { + if (this.name == null) { + this.name = SystemUtils.a("item", IRegistry.ITEM.getKey(this)); +@@ -164,6 +165,7 @@ public class Item implements IMaterial { + return this.m(); + } + ++ public String getDescriptionId(ItemStack itemStack) { return f(itemStack); } // Paper - OBFHELPER + public String f(ItemStack itemstack) { + return this.getName(); + } +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index cc512bd2e89382e7fdbc59b41640e95ccafbbfe9..d4903842aebeff3e32dbf7d3f4b670af4ebad174 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -318,6 +318,7 @@ public class Block extends BlockBase implements IMaterial { + return !this.material.isBuildable() && !this.material.isLiquid(); + } + ++ public String getOrCreateDescriptionId() { return i(); } // Paper - OBFHELPER + public String i() { + if (this.name == null) { + this.name = SystemUtils.a("block", IRegistry.BLOCK.getKey(this)); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index e3ab0b76e5003553b29215a43bc5a762f2663648..ee8977a1e4a83598ba7873c4c482fea828c6b26c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -764,5 +764,10 @@ public class CraftBlock implements Block { + public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { + return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().getBlockData().getStepSound()); + } ++ ++ @Override ++ public String getTranslationKey() { ++ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); ++ } + // 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 2519dbce9717ff647d50c31aed6aca68b9f4e3af..8049063ea37f3e0eac3f3a26703adc80fc99341a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -45,6 +45,7 @@ import org.bukkit.Registry; + import org.bukkit.UnsafeValues; + import org.bukkit.advancement.Advancement; + import org.bukkit.block.data.BlockData; ++import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.block.data.CraftBlockData; + import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.craftbukkit.legacy.CraftLegacy; +@@ -420,6 +421,30 @@ public final class CraftMagicNumbers implements UnsafeValues { + throw new RuntimeException(); + } + } ++ ++ @Override ++ public String getTranslationKey(Material mat) { ++ if (mat.isBlock()) { ++ return getBlock(mat).getOrCreateDescriptionId(); ++ } ++ return getItem(mat).getName(); ++ } ++ ++ @Override ++ public String getTranslationKey(org.bukkit.block.Block block) { ++ return ((org.bukkit.craftbukkit.block.CraftBlock)block).getNMS().getBlock().getOrCreateDescriptionId(); ++ } ++ ++ @Override ++ public String getTranslationKey(org.bukkit.entity.EntityType type) { ++ return net.minecraft.world.entity.EntityTypes.getByName(type.getName()).map(net.minecraft.world.entity.EntityTypes::getDescriptionId).orElse(null); ++ } ++ ++ @Override ++ public String getTranslationKey(org.bukkit.inventory.ItemStack itemStack) { ++ net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); ++ return nmsItemStack.getItem().getDescriptionId(nmsItemStack); ++ } + // Paper end + + /** diff --git a/patches/server-unmapped/0564-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server-unmapped/0564-Create-HoverEvent-from-ItemStack-Entity.patch new file mode 100644 index 0000000000..1e4c77c2c5 --- /dev/null +++ b/patches/server-unmapped/0564-Create-HoverEvent-from-ItemStack-Entity.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ysl3000 +Date: Mon, 6 Jul 2020 22:18:04 +0200 +Subject: [PATCH] Create HoverEvent from ItemStack Entity + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index 910c6109783dfef86e127a0a5b7d7d3865150d89..347c23d4b7d47198f214c3f95354e8abb660b191 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -365,5 +365,40 @@ public final class CraftItemFactory implements ItemFactory { + + return nms != null ? net.minecraft.locale.LocaleLanguage.getInstance().translateKey(nms.getItem().getName()) : null; + } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(ItemStack itemStack) { ++ net.md_5.bungee.api.chat.ItemTag itemTag = net.md_5.bungee.api.chat.ItemTag.ofNbt(CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString()); ++ return new net.md_5.bungee.api.chat.hover.content.Item( ++ itemStack.getType().getKey().toString(), ++ itemStack.getAmount(), ++ itemTag); ++ } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity) { ++ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(entity.getCustomName()) ? null : new net.md_5.bungee.api.chat.TextComponent(entity.getCustomName())); ++ } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, String customName) { ++ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(customName) ? null : new net.md_5.bungee.api.chat.TextComponent(customName)); ++ } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent customName) { ++ return new net.md_5.bungee.api.chat.hover.content.Entity( ++ entity.getType().getKey().toString(), ++ entity.getUniqueId().toString(), ++ customName); ++ } ++ ++ @Override ++ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent[] customName) { ++ return new net.md_5.bungee.api.chat.hover.content.Entity( ++ entity.getType().getKey().toString(), ++ entity.getUniqueId().toString(), ++ new net.md_5.bungee.api.chat.TextComponent(customName)); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0565-Cache-block-data-strings.patch b/patches/server-unmapped/0565-Cache-block-data-strings.patch new file mode 100644 index 0000000000..34db53bb63 --- /dev/null +++ b/patches/server-unmapped/0565-Cache-block-data-strings.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: miclebrick +Date: Thu, 6 Dec 2018 19:52:50 -0500 +Subject: [PATCH] Cache block data strings + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 5acc6cfa96084728f45cfbec0ff9571e5dd0b844..1af99b938382d3d229f1fbf6250e1f0e09da4819 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1955,6 +1955,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant%s", nms, bukkit); + } + ++ // Paper start - cache block data strings ++ private static Map stringDataCache = new HashMap<>(); ++ ++ static { ++ // cache all of the default states at startup, will not cache ones with the custom states inside of the ++ // brackets in a different order, though ++ reloadCache(); ++ } ++ ++ public static void reloadCache() { ++ stringDataCache.clear(); ++ Block.REGISTRY_ID.forEach(blockData -> stringDataCache.put(blockData.toString(), blockData.createCraftBlockData())); ++ } ++ // Paper end ++ + public static CraftBlockData newData(Material material, String data) { + Preconditions.checkArgument(material == null || material.isBlock(), "Cannot get data for not block %s", material); + ++ // Paper start - cache block data strings ++ if (material != null) { ++ Block block = CraftMagicNumbers.getBlock(material); ++ if (block != null) { ++ MinecraftKey key = IRegistry.BLOCK.getKey(block); ++ data = data == null ? key.toString() : key + data; ++ } ++ } ++ ++ CraftBlockData cached = stringDataCache.computeIfAbsent(data, s -> createNewData(null, s)); ++ return (CraftBlockData) cached.clone(); ++ } ++ ++ private static CraftBlockData createNewData(Material material, String data) { ++ // Paper end - cache block data strings + IBlockData blockData; + Block block = CraftMagicNumbers.getBlock(material); + Map, Comparable> parsed = null; diff --git a/patches/server-unmapped/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/patches/server-unmapped/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch new file mode 100644 index 0000000000..2e575c4648 --- /dev/null +++ b/patches/server-unmapped/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 25 Aug 2020 20:45:36 -0400 +Subject: [PATCH] Fix Entity Teleportation and cancel velocity if teleported + +Uses correct setPositionRotation for Entity teleporting instead of setLocation +as this is how Vanilla teleports entities. + +Cancel any pending motion when teleported. + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index d3449dc9eeba0d8022c3a7b0280eaffcd42e7265..fe3bd1c54a7e366bd4f02b417f7725bae60a3ca2 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -693,7 +693,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + public void a(PacketPlayInTeleportAccept packetplayinteleportaccept) { + PlayerConnectionUtils.ensureMainThread(packetplayinteleportaccept, this, this.player.getWorldServer()); + if (packetplayinteleportaccept.b() == this.teleportAwait && this.teleportPos != null) { // CraftBukkit +- this.player.setLocation(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); ++ this.player.setPositionRotation(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); // Paper - use proper setPositionRotation for teleportation + this.o = this.teleportPos.x; + this.p = this.teleportPos.y; + this.q = this.teleportPos.z; +@@ -1538,7 +1538,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + // CraftBukkit end + + this.A = this.e; +- this.player.setLocation(d0, d1, d2, f, f1); ++ this.player.setPositionRotation(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation + this.player.forceCheckHighPriority(); // Paper + this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.teleportAwait)); + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index f5bb9313a249bfd4e63ab77e19cfd6f997d22fb1..a1fb19d45ee3809ee6a515669ba64ea45b31428c 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -145,6 +145,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + // CraftBukkit start + private static final int CURRENT_LEVEL = 2; ++ public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation + static boolean isLevelAtLeast(NBTTagCompound tag, int level) { + return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; + } +@@ -1408,6 +1409,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public void setPositionRotation(double d0, double d1, double d2, float f, float f1) { ++ // Paper - cancel entity velocity if teleported ++ if (!preserveMotion) { ++ this.mot = Vec3D.ORIGIN; ++ } else { ++ this.preserveMotion = false; ++ } ++ // Paper end + this.g(d0, d1, d2); + this.yaw = f; + this.pitch = f1; +diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +index 5538404456dfee42257fad9040fcc0fefdfc5fab..33a5dbcc11455f81088d9fd685a8c4b1b8f4b1f2 100644 +--- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java ++++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java +@@ -165,6 +165,7 @@ public abstract class MobSpawnerAbstract { + return; + } + ++ entity.preserveMotion = true; // Paper - preserve entity motion from tag + entity.setPositionRotation(entity.locX(), entity.locY(), entity.locZ(), world.random.nextFloat() * 360.0F, 0.0F); + if (entity instanceof EntityInsentient) { + EntityInsentient entityinsentient = (EntityInsentient) entity; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 387f6f6fa9bbb1cce544cfb907f68c7993752dd7..fb52a60437d48282f3e99e7eccb0e76b446155f9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -558,7 +558,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + } + + // entity.setLocation() throws no event, and so cannot be cancelled +- entity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); ++ entity.setPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); // Paper - use proper setPosition, as per vanilla teleporting + // SPIGOT-619: Force sync head rotation also + entity.setHeadRotation(location.getYaw()); + ((net.minecraft.server.level.WorldServer) entity.world).chunkCheck(entity); // Spigot - register to new chunk diff --git a/patches/server-unmapped/0567-Add-additional-open-container-api-to-HumanEntity.patch b/patches/server-unmapped/0567-Add-additional-open-container-api-to-HumanEntity.patch new file mode 100644 index 0000000000..467260a9f3 --- /dev/null +++ b/patches/server-unmapped/0567-Add-additional-open-container-api-to-HumanEntity.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 26 Aug 2020 02:12:31 -0400 +Subject: [PATCH] Add additional open container api 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 4028f4bd87a183a808f4c9a19d51ee1c9b9e30f7..0a0e9df604723802fe65d871ff48aa9fd9b756bf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -460,6 +460,70 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + return this.getHandle().activeContainer.getBukkitView(); + } + ++ // Paper start - Add additional containers ++ @Override ++ public InventoryView openAnvil(Location location, boolean force) { ++ return openInventory(location, force, Material.ANVIL); ++ } ++ ++ @Override ++ public InventoryView openCartographyTable(Location location, boolean force) { ++ return openInventory(location, force, Material.CARTOGRAPHY_TABLE); ++ } ++ ++ @Override ++ public InventoryView openGrindstone(Location location, boolean force) { ++ return openInventory(location, force, Material.GRINDSTONE); ++ } ++ ++ @Override ++ public InventoryView openLoom(Location location, boolean force) { ++ return openInventory(location, force, Material.LOOM); ++ } ++ ++ @Override ++ public InventoryView openSmithingTable(Location location, boolean force) { ++ return openInventory(location, force, Material.SMITHING_TABLE); ++ } ++ ++ @Override ++ public InventoryView openStonecutter(Location location, boolean force) { ++ return openInventory(location, force, Material.STONECUTTER); ++ } ++ ++ private InventoryView openInventory(Location location, boolean force, Material material) { ++ org.spigotmc.AsyncCatcher.catchOp("open" + material); ++ if (location == null) { ++ location = getLocation(); ++ } ++ if (!force) { ++ Block block = location.getBlock(); ++ if (block.getType() != material) { ++ return null; ++ } ++ } ++ net.minecraft.world.level.block.Block block; ++ if (material == Material.ANVIL) { ++ block = Blocks.ANVIL; ++ } else if (material == Material.CARTOGRAPHY_TABLE) { ++ block = Blocks.CARTOGRAPHY_TABLE; ++ } else if (material == Material.GRINDSTONE) { ++ block = Blocks.GRINDSTONE; ++ } else if (material == Material.LOOM) { ++ block = Blocks.LOOM; ++ } else if (material == Material.SMITHING_TABLE) { ++ block = Blocks.SMITHING_TABLE; ++ } else if (material == Material.STONECUTTER) { ++ block = Blocks.STONECUTTER; ++ } else { ++ throw new IllegalArgumentException("Unsupported inventory type: " + material); ++ } ++ getHandle().openContainer(block.getInventory(null, getHandle().world, new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()))); ++ getHandle().activeContainer.checkReachable = !force; ++ return getHandle().activeContainer.getBukkitView(); ++ } ++ // Paper end ++ + @Override + public void closeInventory() { + // Paper start diff --git a/patches/server-unmapped/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/patches/server-unmapped/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch new file mode 100644 index 0000000000..a02addc375 --- /dev/null +++ b/patches/server-unmapped/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 12 Sep 2020 17:21:38 -0400 +Subject: [PATCH] Cache DataFixerUpper Rewrite Rules on demand + +Mojang precaches every single potential rewrite rule that could ever +exist on server startup. This includes rules from all the way back to versions from 6+ years ago. + +This is the source of why the server hogs every CPU core at 100% every start. + +For anyone who hard resets for updates or has force upgraded their entire world, this +results in completely wasted cpu cycles. + +This massive CPU usage also delays server startup time. + +We improve this by making "min version to precache" that defaults to a future version +so that no rewrite rules are precached. + +someone who expects to be converting a lot chunks could theoretically set +-DPaper.minPrecachedDatafixVersion= as a startup +parameter and only build from that point on. + +However this will likely never be needed as the server will still run +the same cache logic on demand when it's actually needed. The only +cost would be some delay on the FIRST chunk conversion, but paper already +runs chunk conversions on another thread so this will likely never be +a concern for TPS. + +This patch will significantly reduce CPU use on startup, reduce memory usage, +and improve server startup time. + +diff --git a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java +index edb77982d273e9492ab1a669ca1ad89da2ec3c3e..abc265b00044b14abb55c2628d454ee01fef467b 100644 +--- a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java ++++ b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java +@@ -26,8 +26,10 @@ public class DataFixerBuilder { + private final Int2ObjectSortedMap schemas = new Int2ObjectAVLTreeMap<>(); + private final List globalList = Lists.newArrayList(); + private final IntSortedSet fixerVersions = new IntAVLTreeSet(); ++ private final int minDataFixPrecacheVersion; // Paper + + public DataFixerBuilder(final int dataVersion) { ++ minDataFixPrecacheVersion = Integer.getInteger("Paper.minPrecachedDatafixVersion", dataVersion+1) * 10; // Paper - default to precache nothing - mojang stores versions * 10 to allow for 'sub versions' + this.dataVersion = dataVersion; + } + +@@ -65,6 +67,7 @@ public class DataFixerBuilder { + final IntBidirectionalIterator iterator = fixerUpper.fixerVersions().iterator(); + while (iterator.hasNext()) { + final int versionKey = iterator.nextInt(); ++ if (versionKey < minDataFixPrecacheVersion) continue; // Paper + final Schema schema = schemas.get(versionKey); + for (final String typeName : schema.types()) { + CompletableFuture.runAsync(() -> { diff --git a/patches/server-unmapped/0569-Extend-block-drop-capture-to-capture-all-items-added.patch b/patches/server-unmapped/0569-Extend-block-drop-capture-to-capture-all-items-added.patch new file mode 100644 index 0000000000..679487e3af --- /dev/null +++ b/patches/server-unmapped/0569-Extend-block-drop-capture-to-capture-all-items-added.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 17 Sep 2020 00:36:05 +0100 +Subject: [PATCH] Extend block drop capture to capture all items added to the + world + + +diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +index 984209e4f66ad23d85d2c5d02318caab1aff7324..31012963815a5c7355753b8cd2749976282ef0d2 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java ++++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +@@ -12,6 +12,7 @@ import net.minecraft.world.EnumHand; + import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.ITileInventory; + import net.minecraft.world.InteractionResultWrapper; ++import net.minecraft.world.entity.item.EntityItem; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.ItemActionContext; +@@ -419,10 +420,12 @@ public class PlayerInteractManager { + // return true; // CraftBukkit + } + // CraftBukkit start ++ java.util.List itemsToDrop = world.captureDrops; // Paper - store current list ++ world.captureDrops = null; // Paper - Remove this earlier so that we can actually drop stuff + if (event.isDropItems()) { +- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, world.captureDrops); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - use stored ref + } +- world.captureDrops = null; ++ //world.captureDrops = null; // Paper - move up + + // Drop event experience + if (flag && event != null) { +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 70f8fbff2ac825b61c5c9f7c6830de3106e7926c..0f0a3b3776c607217a15c5f61d60f6a98f1c7584 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -99,6 +99,7 @@ import net.minecraft.world.entity.animal.EntityWaterAnimal; + import net.minecraft.world.entity.animal.horse.EntityHorseSkeleton; + import net.minecraft.world.entity.boss.EntityComplexPart; + import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; ++import net.minecraft.world.entity.item.EntityItem; + import net.minecraft.world.entity.npc.NPC; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.entity.raid.PersistentRaid; +@@ -1290,6 +1291,13 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } else if (this.isUUIDTaken(entity)) { + return false; + } else { ++ // Paper start - capture all item additions to the world ++ if (captureDrops != null && entity instanceof EntityItem) { ++ captureDrops.add((EntityItem) entity); ++ return true; ++ } ++ // Paper end ++ + if (!CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { + return false; + } diff --git a/patches/server-unmapped/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server-unmapped/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch new file mode 100644 index 0000000000..974a34ff2f --- /dev/null +++ b/patches/server-unmapped/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sun, 27 Sep 2020 16:25:24 +0200 +Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086) + + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java +index 00cebd33101916f29bbc192d531ac0fba31e037b..a323b76f68c273a73cb3f20167a668b2100f4944 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java +@@ -389,6 +389,7 @@ public class PlayerChunk { + } + + public void a(BlockPosition blockposition) { ++ if (!blockposition.isValidLocation()) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks + Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { diff --git a/patches/server-unmapped/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server-unmapped/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch new file mode 100644 index 0000000000..f2eed564bc --- /dev/null +++ b/patches/server-unmapped/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Fri, 28 Aug 2020 01:41:26 +0200 +Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and + non-conflicting Entity Ids + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a1fb19d45ee3809ee6a515669ba64ea45b31428c..9b6e5f279a22efc2d015e2d31076a8c06e6b3886 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -3478,4 +3478,10 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + void accept(Entity entity, double d0, double d1, double d2); + } ++ ++ // Paper start ++ public static int nextEntityId() { ++ return entityCount.incrementAndGet(); ++ } ++ // 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 8049063ea37f3e0eac3f3a26703adc80fc99341a..5b03187f4d76e3052ee9abe0ee2774218d41b864 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -445,6 +445,10 @@ public final class CraftMagicNumbers implements UnsafeValues { + net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); + return nmsItemStack.getItem().getDescriptionId(nmsItemStack); + } ++ ++ public int nextEntityId() { ++ return net.minecraft.world.entity.Entity.nextEntityId(); ++ } + // Paper end + + /** diff --git a/patches/server-unmapped/0572-Lazily-track-plugin-scoreboards-by-default.patch b/patches/server-unmapped/0572-Lazily-track-plugin-scoreboards-by-default.patch new file mode 100644 index 0000000000..974e02ca68 --- /dev/null +++ b/patches/server-unmapped/0572-Lazily-track-plugin-scoreboards-by-default.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Sat, 3 Oct 2020 04:15:09 -0400 +Subject: [PATCH] Lazily track plugin scoreboards by default + +On servers with plugins that constantly churn through scoreboards, there is a risk of +degraded GC performance due to the number of scoreboards held on by weak references. +Most plugins don't even need the (vanilla) functionality that requires all plugin +scoreboards to be tracked by the server. Instead, only track scoreboards when an +objective is added with a non-dummy criteria. + +This is a breaking change, however the change is a much more sensible default. In case +this breaks your workflow you can always force all scoreboards to be tracked with +settings.track-plugin-scoreboards in paper.yml. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 545948f20efd6c8dd42140b565af94cd6b52b661..7d50aded88f5b7dfebaea1aebc86231f7b5c4e25 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -462,4 +462,9 @@ public class PaperConfig { + private static void maxJoinsPerTick() { + maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); + } ++ ++ public static boolean trackPluginScoreboards; ++ private static void trackPluginScoreboards() { ++ trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +index 6ea491f6308317059c4bc6735abbdce370df0f34..3dfb6ad1ed5fae773b88cbe9ad540fd2520b8b50 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +@@ -19,6 +19,7 @@ import org.bukkit.scoreboard.Team; + + public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + final Scoreboard board; ++ boolean registeredGlobally = false; // Paper + + CraftScoreboard(Scoreboard board) { + this.board = board; +@@ -45,6 +46,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); + Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); + CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); ++ // Paper start - the block comment from the old registerNewObjective didnt cause a conflict when rebasing, so this block wasn't added to the adventure registerNewObjective ++ if (craftCriteria.criteria != net.minecraft.world.scores.criteria.IScoreboardCriteria.DUMMY && !registeredGlobally) { ++ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); ++ registeredGlobally = true; ++ } ++ // Paper end + ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); + return new CraftObjective(this, objective); + } +@@ -66,6 +73,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); + + CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); ++ // Paper start ++ if (craftCriteria.criteria != net.minecraft.server.IScoreboardCriteria.DUMMY && !registeredGlobally) { ++ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); ++ registeredGlobally = true; ++ } ++ // Paper end + ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); + return new CraftObjective(this, objective);*/ // Paper + return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +index 73663bcea163cda26f531902141a9ad3ad7eba57..9c30a79cc55c6455aa18e3798728deaacc3434ca 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +@@ -30,6 +30,7 @@ public final class CraftScoreboardManager implements ScoreboardManager { + + public CraftScoreboardManager(MinecraftServer minecraftserver, net.minecraft.world.scores.Scoreboard scoreboardServer) { + mainScoreboard = new CraftScoreboard(scoreboardServer); ++ mainScoreboard.registeredGlobally = true; // Paper + server = minecraftserver; + scoreboards.add(mainScoreboard); + } +@@ -43,10 +44,22 @@ public final class CraftScoreboardManager implements ScoreboardManager { + public CraftScoreboard getNewScoreboard() { + org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot + CraftScoreboard scoreboard = new CraftScoreboard(new ScoreboardServer(server)); ++ // Paper start ++ if (com.destroystokyo.paper.PaperConfig.trackPluginScoreboards) { ++ scoreboard.registeredGlobally = true; + scoreboards.add(scoreboard); ++ } ++ // Paper end + return scoreboard; + } + ++ // Paper start ++ public void registerScoreboardForVanilla(CraftScoreboard scoreboard) { ++ org.spigotmc.AsyncCatcher.catchOp("scoreboard registration"); ++ scoreboards.add(scoreboard); ++ } ++ // Paper end ++ + // CraftBukkit method + public CraftScoreboard getPlayerBoard(CraftPlayer player) { + CraftScoreboard board = playerBoards.get(player); diff --git a/patches/server-unmapped/0573-Entity-isTicking.patch b/patches/server-unmapped/0573-Entity-isTicking.patch new file mode 100644 index 0000000000..c92576011d --- /dev/null +++ b/patches/server-unmapped/0573-Entity-isTicking.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 3 Oct 2020 21:39:16 -0500 +Subject: [PATCH] Entity#isTicking + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 9b6e5f279a22efc2d015e2d31076a8c06e6b3886..d072e3fb26f32db80be68f0e23526e34f57ff331 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -48,6 +48,7 @@ import net.minecraft.resources.MinecraftKey; + import net.minecraft.resources.ResourceKey; + import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ChunkProviderServer; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.server.level.PlayerChunkMap; + import net.minecraft.server.level.TicketType; +@@ -3483,5 +3484,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public static int nextEntityId() { + return entityCount.incrementAndGet(); + } ++ ++ public boolean isTicking() { ++ return ((ChunkProviderServer) world.getChunkProvider()).isInEntityTickingChunk(this); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index fb52a60437d48282f3e99e7eccb0e76b446155f9..295ffab08672d77d88aca368cb5b56f80bc4f1b5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1161,5 +1161,9 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public boolean isInLava() { + return getHandle().isInLava(); + } ++ ++ public boolean isTicking() { ++ return getHandle().isTicking(); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/patches/server-unmapped/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch new file mode 100644 index 0000000000..b5c0ba6314 --- /dev/null +++ b/patches/server-unmapped/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 3 Oct 2020 22:00:27 -0500 +Subject: [PATCH] Fix deop kicking non-whitelisted player when white list is + not enabled + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 1af99b938382d3d229f1fbf6250e1f0e09da4819..bea7887c1adee93cfef17d910c3df3eb60cb681c 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2020,6 +2020,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant list = Lists.newArrayList(playerlist.getPlayers()); + Iterator iterator = list.iterator(); + diff --git a/patches/server-unmapped/0575-Fix-Not-a-string-Map-Conversion-spam.patch b/patches/server-unmapped/0575-Fix-Not-a-string-Map-Conversion-spam.patch new file mode 100644 index 0000000000..26697d6feb --- /dev/null +++ b/patches/server-unmapped/0575-Fix-Not-a-string-Map-Conversion-spam.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 8 Oct 2020 00:00:25 -0400 +Subject: [PATCH] Fix "Not a string" Map Conversion spam + +The maps did convert successfully, but had noisy logs due to Spigot +implementing this logic incorrectly. + +This stops the spam by converting the old format to new before +requesting the world. + +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java +index d470af1814af332595c1c0beb1cdc552e186a6bb..1f9b710f2af3c5067b3c2b73bebb11f8e22c403e 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java +@@ -11,8 +11,10 @@ import javax.annotation.Nullable; + import net.minecraft.core.BlockPosition; + import net.minecraft.nbt.DynamicOpsNBT; + import net.minecraft.nbt.NBTBase; ++import net.minecraft.nbt.NBTNumber; + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.nbt.NBTTagList; ++import net.minecraft.nbt.NBTTagString; + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.PacketPlayOutMap; +@@ -94,7 +96,26 @@ public class WorldMap extends PersistentBase { + + @Override + public void a(NBTTagCompound nbttagcompound) { +- DataResult> dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, nbttagcompound.get("dimension"))); // CraftBukkit - decompile error ++ // Paper start - fix "Not a string" spam ++ NBTBase dimension = nbttagcompound.get("dimension"); ++ if (dimension instanceof NBTNumber && ((NBTNumber) dimension).asInt() >= CraftWorld.CUSTOM_DIMENSION_OFFSET) { ++ long least = nbttagcompound.getLong("UUIDLeast"); ++ long most = nbttagcompound.getLong("UUIDMost"); ++ ++ if (least != 0L && most != 0L) { ++ this.uniqueId = new UUID(most, least); ++ CraftWorld world = (CraftWorld) server.getWorld(this.uniqueId); ++ if (world != null) { ++ dimension = NBTTagString.create("minecraft:" + world.getName().toLowerCase(java.util.Locale.ENGLISH)); ++ } else { ++ dimension = NBTTagString.create("bukkit:_invalidworld_"); ++ } ++ } else { ++ dimension = NBTTagString.create("bukkit:_invalidworld_"); ++ } ++ } ++ DataResult> dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, dimension)); // CraftBukkit - decompile error ++ // Paper end - fix "Not a string" spam + Logger logger = WorldMap.LOGGER; + + logger.getClass(); diff --git a/patches/server-unmapped/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/patches/server-unmapped/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch new file mode 100644 index 0000000000..6958041776 --- /dev/null +++ b/patches/server-unmapped/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Sun, 4 Oct 2020 19:55:25 -0700 +Subject: [PATCH] Fix CME on adding a passenger in CreatureSpawnEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d072e3fb26f32db80be68f0e23526e34f57ff331..0841cf7e968a8a3b577e91f6dcd0487169474329 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -3182,7 +3182,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public Stream recursiveStream() { +- return Stream.concat(Stream.of(this), this.passengers.stream().flatMap(Entity::recursiveStream)); ++ return Stream.concat(Stream.of(this), com.google.common.collect.ImmutableList.copyOf(this.passengers).stream().flatMap(Entity::recursiveStream)); // Paper + } + + public boolean hasSinglePlayerPassenger() { diff --git a/patches/server-unmapped/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch b/patches/server-unmapped/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch new file mode 100644 index 0000000000..42d7399da7 --- /dev/null +++ b/patches/server-unmapped/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Wed, 18 Mar 2020 00:07:46 -0500 +Subject: [PATCH] MC-147729: Drop items that are extra from a crafting recipe + + +diff --git a/src/main/java/net/minecraft/recipebook/AutoRecipe.java b/src/main/java/net/minecraft/recipebook/AutoRecipe.java +index 897f7270bae601b39d74d6a56a60f0ac7f1f6090..3bcd2c5a5352b8fb92d09b0a6914a1013569c8d6 100644 +--- a/src/main/java/net/minecraft/recipebook/AutoRecipe.java ++++ b/src/main/java/net/minecraft/recipebook/AutoRecipe.java +@@ -71,7 +71,12 @@ public class AutoRecipe implements AutoRecipeAbstract +Date: Wed, 1 Jun 2016 23:29:17 -0400 +Subject: [PATCH] Reset Ender Crystals on Dragon Spawn + +Crystals can end up in a bad state in certain conditions which causes +an exception on the expected number of crystals going negative. + +This ensures the crystals/pillars are in expected state when the dragon spawns. + +See #3522 + +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +index 0869af4670f040344f5b6c2c10bff5e5226f707c..c6283489dcb6e13f0d618971614aeadaee2e3007 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +@@ -445,6 +445,7 @@ public class EnderDragonBattle { + entityenderdragon.setPositionRotation(0.0D, 128.0D, 0.0D, this.world.random.nextFloat() * 360.0F, 0.0F); + this.world.addEntity(entityenderdragon); + this.dragonUUID = entityenderdragon.getUniqueID(); ++ this.resetCrystals(); // Paper + return entityenderdragon; + } + diff --git a/patches/server-unmapped/0579-Fix-for-large-move-vectors-crashing-server.patch b/patches/server-unmapped/0579-Fix-for-large-move-vectors-crashing-server.patch new file mode 100644 index 0000000000..ba892e4738 --- /dev/null +++ b/patches/server-unmapped/0579-Fix-for-large-move-vectors-crashing-server.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 17 May 2020 23:47:33 -0700 +Subject: [PATCH] Fix for large move vectors crashing server + +Check movement distance also based on current position. + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index fe3bd1c54a7e366bd4f02b417f7725bae60a3ca2..73a1730f1c683b2345a9c3d4f2288ceab20a6625 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -518,19 +518,24 @@ public class PlayerConnection implements PacketListenerPlayIn { + + if (entity != this.player && entity.getRidingPassenger() == this.player && entity == this.r) { + WorldServer worldserver = this.player.getWorldServer(); +- double d0 = entity.locX(); +- double d1 = entity.locY(); +- double d2 = entity.locZ(); +- double d3 = packetplayinvehiclemove.getX(); +- double d4 = packetplayinvehiclemove.getY(); +- double d5 = packetplayinvehiclemove.getZ(); ++ double d0 = entity.locX();double fromX = d0; // Paper - OBFHELPER ++ double d1 = entity.locY();double fromY = d1; // Paper - OBFHELPER ++ double d2 = entity.locZ();double fromZ = d2; // Paper - OBFHELPER ++ double d3 = packetplayinvehiclemove.getX();double toX = d3; // Paper - OBFHELPER ++ double d4 = packetplayinvehiclemove.getY();double toY = d4; // Paper - OBFHELPER ++ double d5 = packetplayinvehiclemove.getZ();double toZ = d5; // Paper - OBFHELPER + float f = packetplayinvehiclemove.getYaw(); + float f1 = packetplayinvehiclemove.getPitch(); + double d6 = d3 - this.s; + double d7 = d4 - this.t; + double d8 = d5 - this.u; + double d9 = entity.getMot().g(); +- double d10 = d6 * d6 + d7 * d7 + d8 * d8; ++ // Paper start - fix large move vectors killing the server ++ double currDeltaX = toX - fromX; ++ double currDeltaY = toY - fromY; ++ double currDeltaZ = toZ - fromZ; ++ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); ++ // Paper end - fix large move vectors killing the server + + + // CraftBukkit start - handle custom speeds and skipped ticks +@@ -1232,7 +1237,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + double d2 = this.player.locZ(); + double d3 = this.player.locY(); + double d4 = packetplayinflying.a(this.player.locX());double toX = d4; // Paper - OBFHELPER +- double d5 = packetplayinflying.b(this.player.locY()); ++ double d5 = packetplayinflying.b(this.player.locY());double toY = d5; // Paper - OBFHELPER + double d6 = packetplayinflying.c(this.player.locZ());double toZ = d6; // Paper - OBFHELPER + float f = packetplayinflying.a(this.player.yaw); + float f1 = packetplayinflying.b(this.player.pitch); +@@ -1240,7 +1245,12 @@ public class PlayerConnection implements PacketListenerPlayIn { + double d8 = d5 - this.m; + double d9 = d6 - this.n; + double d10 = this.player.getMot().g(); +- double d11 = d7 * d7 + d8 * d8 + d9 * d9; ++ // Paper start - fix large move vectors killing the server ++ double currDeltaX = toX - prevX; ++ double currDeltaY = toY - prevY; ++ double currDeltaZ = toZ - prevZ; ++ double d11 = Math.max(d7 * d7 + d8 * d8 + d9 * d9, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); ++ // Paper end - fix large move vectors killing the server + + if (this.player.isSleeping()) { + if (d11 > 1.0D) { diff --git a/patches/server-unmapped/0580-Optimise-getType-calls.patch b/patches/server-unmapped/0580-Optimise-getType-calls.patch new file mode 100644 index 0000000000..16993ab18d --- /dev/null +++ b/patches/server-unmapped/0580-Optimise-getType-calls.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 3 Jun 2020 11:37:13 -0700 +Subject: [PATCH] Optimise getType calls + +Remove the map lookup for converting from Block->Bukkit Material + +diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockData.java b/src/main/java/net/minecraft/world/level/block/state/IBlockData.java +index 9e1ebfd7befe9e2fc3396b4dcd5e8fc7c23ee305..ed28710fefee4fad96290b2d166ac9dfe3d1fa6e 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/IBlockData.java ++++ b/src/main/java/net/minecraft/world/level/block/state/IBlockData.java +@@ -11,6 +11,19 @@ public class IBlockData extends BlockBase.BlockData { + + public static final Codec b = a((Codec) IRegistry.BLOCK, Block::getBlockData).stable(); + ++ ++ // Paper start - optimise getType calls ++ org.bukkit.Material cachedMaterial; ++ ++ public final org.bukkit.Material getBukkitMaterial() { ++ if (this.cachedMaterial == null) { ++ this.cachedMaterial = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(this.getBlock()); ++ } ++ ++ return this.cachedMaterial; ++ } ++ // Paper end - optimise getType calls ++ + public IBlockData(Block block, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { + super(block, immutablemap, mapcodec); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java +index aa20cecc93ac53ce7f1b956ea5065ae80b55cff5..fc65c138bab242d5b533381ea496a2a48fcd91ea 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java +@@ -79,7 +79,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot { + public Material getBlockType(int x, int y, int z) { + CraftChunk.validateChunkCoordinates(x, y, z); + +- return CraftMagicNumbers.getMaterial(blockids[y >> 4].a(x, y & 0xF, z).getBlock()); ++ return blockids[y >> 4].a(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index ee8977a1e4a83598ba7873c4c482fea828c6b26c..f1f03bd0162a158761f300cbd96aa32101542abb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -214,7 +214,7 @@ public class CraftBlock implements Block { + + @Override + public Material getType() { +- return CraftMagicNumbers.getMaterial(world.getType(position).getBlock()); ++ return world.getType(position).getBukkitMaterial(); // Paper - optimise getType calls + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +index b7ce677572f1f5ed01f3a8caf9368222e03bb69c..1960f01b5e4d7bff96d466e9a48f1d5300f261d1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +@@ -135,7 +135,7 @@ public class CraftBlockState implements BlockState { + + @Override + public Material getType() { +- return CraftMagicNumbers.getMaterial(data.getBlock()); ++ return data.getBukkitMaterial(); // Paper - optimise getType calls + } + + public void setFlag(int flag) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +index 58f892478de74b853cd35ef2fec8c462e3a9ecee..1fe9b32c2a3717652be70786090a61c5fa7430cf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +@@ -45,7 +45,7 @@ public class CraftBlockData implements BlockData { + + @Override + public Material getMaterial() { +- return CraftMagicNumbers.getMaterial(state.getBlock()); ++ return state.getBukkitMaterial(); // Paper - optimise getType calls + } + + public IBlockData getState() { +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +index d02281f954aac8d8b65f5d36ec70f0352e4c7cdd..2194232200e90fa894b45eb265b5ed08ce1e35a3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +@@ -73,7 +73,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + + @Override + public Material getType(int x, int y, int z) { +- return CraftMagicNumbers.getMaterial(getTypeId(x, y, z).getBlock()); ++ return getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls + } + + @Override diff --git a/patches/server-unmapped/0581-Villager-resetOffers.patch b/patches/server-unmapped/0581-Villager-resetOffers.patch new file mode 100644 index 0000000000..5c18995906 --- /dev/null +++ b/patches/server-unmapped/0581-Villager-resetOffers.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Mon, 7 Oct 2019 00:15:37 -0500 +Subject: [PATCH] Villager#resetOffers + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java +index 3dd80fcf9237f15bb3bf38d1529340e178f09388..a614f5d5817bf999aca0f0b50f343031c8168392 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java +@@ -113,6 +113,13 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP + return this.tradingPlayer != null; + } + ++ // Paper start ++ public void resetOffers() { ++ this.trades = new MerchantRecipeList(); ++ this.updateTrades(); ++ } ++ // Paper end ++ + @Override + public MerchantRecipeList getOffers() { + if (this.trades == null) { +@@ -235,6 +242,7 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP + return this.world; + } + ++ protected final void updateTrades() { eW(); } // Paper - OBFHELPER + protected abstract void eW(); + + protected void a(MerchantRecipeList merchantrecipelist, VillagerTrades.IMerchantRecipeOption[] avillagertrades_imerchantrecipeoption, int i) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java +index 01285d555ed084fa2e818e1f02955f8aa28002b3..ee751ed4f9f386bf9926347fe2f0958015aecffa 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java +@@ -71,4 +71,11 @@ public class CraftAbstractVillager extends CraftAgeable implements AbstractVilla + public HumanEntity getTrader() { + return getMerchant().getTrader(); + } ++ ++ // Paper start ++ @Override ++ public void resetOffers() { ++ getHandle().resetOffers(); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/patches/server-unmapped/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch new file mode 100644 index 0000000000..124a856cdf --- /dev/null +++ b/patches/server-unmapped/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Jul 2020 20:46:50 -0700 +Subject: [PATCH] Improve inlinig for some hot IBlockData methods + + +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +index 9af91784544dbb0555824a91088257659bdf2c3d..3fdafc0ff0c4148ec844dbdc1455d17cdcb4a75a 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +@@ -391,7 +391,14 @@ public abstract class BlockBase { + } + // Paper end + ++ // Paper start ++ protected boolean isTicking; ++ protected Fluid fluid; ++ // Paper end ++ + public void a() { ++ this.fluid = this.getBlock().d(this.p()); // Paper - moved from getFluid() ++ this.isTicking = this.getBlock().isTicking(this.p()); // Paper - moved from isTicking() + if (!this.getBlock().o()) { + this.a = new BlockBase.BlockData.Cache(this.p()); + } +@@ -430,19 +437,19 @@ public abstract class BlockBase { + return this.getBlock().d(this.p(), iblockaccess, blockposition); + } + +- public boolean d() { ++ public final boolean d() { // Paper + return this.a == null || this.a.c; + } + +- public boolean e() { ++ public final boolean e() { // Paper + return this.e; + } + +- public int f() { ++ public final int f() { // Paper + return this.b; + } + +- public boolean isAir() { ++ public final boolean isAir() { // Paper + return this.f; + } + +@@ -508,7 +515,7 @@ public abstract class BlockBase { + } + } + +- public boolean l() { ++ public final boolean l() { // Paper + return this.k; + } + +@@ -680,12 +687,12 @@ public abstract class BlockBase { + return this.getBlock().a(block); + } + +- public Fluid getFluid() { +- return this.getBlock().d(this.p()); ++ public final Fluid getFluid() { // Paper ++ return this.fluid; // Paper - moved into init + } + +- public boolean isTicking() { +- return this.getBlock().isTicking(this.p()); ++ public final boolean isTicking() { // Paper ++ return this.isTicking; // Paper - moved into init + } + + public SoundEffectType getStepSound() { +diff --git a/src/main/java/net/minecraft/world/level/material/Fluid.java b/src/main/java/net/minecraft/world/level/material/Fluid.java +index 9a93b204973eef4c02a52f33fd9578a43603ed98..147e628bd562da4cf6f07218724a9d6c79d26e38 100644 +--- a/src/main/java/net/minecraft/world/level/material/Fluid.java ++++ b/src/main/java/net/minecraft/world/level/material/Fluid.java +@@ -20,8 +20,12 @@ public final class Fluid extends IBlockDataHolder { + + public static final Codec a = a((Codec) IRegistry.FLUID, FluidType::h).stable(); + ++ // Paper start ++ protected final boolean isEmpty; ++ // Paper end + public Fluid(FluidType fluidtype, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { + super(fluidtype, immutablemap, mapcodec); ++ this.isEmpty = fluidtype.b(); // Paper - moved from isEmpty() + } + + public FluidType getType() { +@@ -33,7 +37,7 @@ public final class Fluid extends IBlockDataHolder { + } + + public boolean isEmpty() { +- return this.getType().b(); ++ return this.isEmpty; // Paper - moved into constructor + } + + public float getHeight(IBlockAccess iblockaccess, BlockPosition blockposition) { diff --git a/patches/server-unmapped/0583-Retain-block-place-order-when-capturing-blockstates.patch b/patches/server-unmapped/0583-Retain-block-place-order-when-capturing-blockstates.patch new file mode 100644 index 0000000000..418df80756 --- /dev/null +++ b/patches/server-unmapped/0583-Retain-block-place-order-when-capturing-blockstates.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 7 Aug 2020 04:27:56 -0700 +Subject: [PATCH] Retain block place order when capturing blockstates + +Fixes twisted vines not connecting properly when grown via +bonemeal by a player. + +In general, look at making this logic more robust (i.e properly handling +cases where a captured entry is overriden) - but for now this will do. + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 307a89c431739ed15d8869faace7b08927626f60..ae5f9a6af810b524f6dcbed64bc943122f0536cc 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -135,7 +135,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public boolean captureBlockStates = false; + public boolean captureTreeGeneration = false; + public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper +- public Map capturedTileEntities = new HashMap<>(); ++ public Map capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper + public List captureDrops; + public long ticksPerAnimalSpawns; + public long ticksPerMonsterSpawns; diff --git a/patches/server-unmapped/0584-Reduce-blockpos-allocation-from-pathfinding.patch b/patches/server-unmapped/0584-Reduce-blockpos-allocation-from-pathfinding.patch new file mode 100644 index 0000000000..2640189324 --- /dev/null +++ b/patches/server-unmapped/0584-Reduce-blockpos-allocation-from-pathfinding.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 25 Apr 2020 17:10:55 -0700 +Subject: [PATCH] Reduce blockpos allocation from pathfinding + + +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java +index d14f2800237c2a80912bf6f2d418a9ba9031070d..a0c7d3ab747ba1a3cf07e716f3591663a8a9e14b 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java +@@ -498,7 +498,7 @@ public class PathfinderNormal extends PathfinderAbstract { + return PathType.DANGER_FIRE; + } + +- if (iblockaccess.getFluid(blockposition_mutableblockposition).a((Tag) TagsFluid.WATER)) { ++ if (iblockdata.getFluid().a((Tag) TagsFluid.WATER)) { // Paper - remove another getType call + return PathType.WATER_BORDER; + } + } // Paper +@@ -528,7 +528,7 @@ public class PathfinderNormal extends PathfinderAbstract { + } else if (iblockdata.a(Blocks.COCOA)) { + return PathType.COCOA; + } else { +- Fluid fluid = iblockaccess.getFluid(blockposition); ++ Fluid fluid = iblockdata.getFluid(); // Paper - remove another get type call + + return fluid.a((Tag) TagsFluid.WATER) ? PathType.WATER : (fluid.a((Tag) TagsFluid.LAVA) ? PathType.LAVA : (a(iblockdata) ? PathType.DAMAGE_FIRE : (BlockDoor.l(iblockdata) && !(Boolean) iblockdata.get(BlockDoor.OPEN) ? PathType.DOOR_WOOD_CLOSED : (block instanceof BlockDoor && material == Material.ORE && !(Boolean) iblockdata.get(BlockDoor.OPEN) ? PathType.DOOR_IRON_CLOSED : (block instanceof BlockDoor && (Boolean) iblockdata.get(BlockDoor.OPEN) ? PathType.DOOR_OPEN : (block instanceof BlockMinecartTrackAbstract ? PathType.RAIL : (block instanceof BlockLeaves ? PathType.LEAVES : (!block.a((Tag) TagsBlock.FENCES) && !block.a((Tag) TagsBlock.WALLS) && (!(block instanceof BlockFenceGate) || (Boolean) iblockdata.get(BlockFenceGate.OPEN)) ? (!iblockdata.a(iblockaccess, blockposition, PathMode.LAND) ? PathType.BLOCKED : PathType.OPEN) : PathType.FENCE)))))))); + } diff --git a/patches/server-unmapped/0585-Fix-item-locations-dropped-from-campfires.patch b/patches/server-unmapped/0585-Fix-item-locations-dropped-from-campfires.patch new file mode 100644 index 0000000000..764f6d7979 --- /dev/null +++ b/patches/server-unmapped/0585-Fix-item-locations-dropped-from-campfires.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 3 Oct 2020 20:32:25 -0500 +Subject: [PATCH] Fix item locations dropped from campfires + +Fixes #4259 by not flooring the blockposition among other weirdness + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java +index df010dc740f2dd647a418ba4e425ce3a3b1d79e2..62a19f39405cff27f34a3b98fb9310b1c9c27563 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java +@@ -14,6 +14,7 @@ import net.minecraft.world.Clearable; + import net.minecraft.world.ContainerUtil; + import net.minecraft.world.InventorySubcontainer; + import net.minecraft.world.InventoryUtils; ++import net.minecraft.world.entity.item.EntityItem; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.RecipeCampfire; + import net.minecraft.world.item.crafting.Recipes; +@@ -92,7 +93,11 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab + result = blockCookEvent.getResult(); + itemstack1 = CraftItemStack.asNMSCopy(result); + // CraftBukkit end +- InventoryUtils.dropItem(this.world, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack1); ++ // Paper start ++ EntityItem droppedItem = new EntityItem(this.world, blockposition.getX() + 0.5D, blockposition.getY() + 0.5D, blockposition.getZ() + 0.5D, itemstack1.cloneAndSubtract(this.world.random.nextInt(21) + 10)); ++ droppedItem.setMot(this.world.random.nextGaussian() * 0.05D, this.world.random.nextGaussian() * 0.05D + 0.2D, this.world.random.nextGaussian() * 0.05D); ++ this.world.addEntity(droppedItem); ++ // Paper end + this.items.set(i, ItemStack.b); + this.k(); + } diff --git a/patches/server-unmapped/0586-Player-elytra-boost-API.patch b/patches/server-unmapped/0586-Player-elytra-boost-API.patch new file mode 100644 index 0000000000..aed9bb2247 --- /dev/null +++ b/patches/server-unmapped/0586-Player-elytra-boost-API.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Tue, 14 Apr 2020 12:05:22 +0200 +Subject: [PATCH] Player elytra boost API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 18d7cf6e783843d44715210b7c8db7bf0a5c89ae..8337ed8bb20b8d887bcd71ddc5f29bce346c7cff 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -69,12 +69,14 @@ import net.minecraft.world.entity.ai.attributes.AttributeMapBase; + import net.minecraft.world.entity.ai.attributes.AttributeModifiable; + import net.minecraft.world.entity.ai.attributes.GenericAttributes; + import net.minecraft.world.entity.player.EntityHuman; ++import net.minecraft.world.entity.projectile.EntityFireworks; + import net.minecraft.world.inventory.Container; + import net.minecraft.world.item.EnumColor; + import net.minecraft.world.item.enchantment.EnchantmentManager; + import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.EnumGamemode; ++import net.minecraft.world.level.World; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.entity.TileEntitySign; + import net.minecraft.world.level.saveddata.maps.MapIcon; +@@ -2284,6 +2286,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + throw new RuntimeException("Unknown settings type"); + } ++ ++ @Override ++ public org.bukkit.entity.Firework boostElytra(ItemStack firework) { ++ Validate.isTrue(isGliding(), "Player must be gliding"); ++ Validate.isTrue(firework != null, "firework == null"); ++ Validate.isTrue(firework.getType() == Material.FIREWORK_ROCKET, "Firework must be Material.FIREWORK_ROCKET"); ++ ++ net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(firework); ++ World world = ((CraftWorld) getWorld()).getHandle(); ++ EntityFireworks entity = new EntityFireworks(world, item, getHandle()); ++ return world.addEntity(entity) ++ ? (org.bukkit.entity.Firework) entity.getBukkitEntity() ++ : null; ++ } + // Paper end + + // Spigot start diff --git a/patches/server-unmapped/0587-Fixed-TileEntityBell-memory-leak.patch b/patches/server-unmapped/0587-Fixed-TileEntityBell-memory-leak.patch new file mode 100644 index 0000000000..879f752716 --- /dev/null +++ b/patches/server-unmapped/0587-Fixed-TileEntityBell-memory-leak.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: giacomo <32515303+giacomozama@users.noreply.github.com> +Date: Sat, 10 Oct 2020 12:15:33 +0200 +Subject: [PATCH] Fixed TileEntityBell memory leak + +TileEntityBell has a list of entities (entitiesAtRing) that was not being cleared at the right time, causing leaks whenever a bell would be rung near a crowd of entities. + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java +index e97d229da3cf7631555f418a73bc74255494cc01..84f9f52c5b632621b509448ac1c760f64de6b062 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java +@@ -27,8 +27,8 @@ public class TileEntityBell extends TileEntity implements ITickable { + public int a; + public boolean b; + public EnumDirection c; +- private List h; +- private boolean i; ++ private List h; private List getEntitiesAtRing() { return this.h; } // Paper - OBFHELPER ++ private boolean i; private boolean getShouldReveal() { return this.i; } // Paper - OBFHELPER + private int j; + + public TileEntityBell() { +@@ -57,6 +57,11 @@ public class TileEntityBell extends TileEntity implements ITickable { + + if (this.a >= 50) { + this.b = false; ++ // Paper start ++ if (!this.getShouldReveal()) { ++ this.getEntitiesAtRing().clear(); ++ } ++ // Paper end + this.a = 0; + } + +@@ -71,6 +76,7 @@ public class TileEntityBell extends TileEntity implements ITickable { + } else { + this.a(this.world); + this.b(this.world); ++ this.getEntitiesAtRing().clear(); // Paper + this.i = false; + } + } +@@ -111,11 +117,12 @@ public class TileEntityBell extends TileEntity implements ITickable { + EntityLiving entityliving = (EntityLiving) iterator.next(); + + if (entityliving.isAlive() && !entityliving.dead && blockposition.a((IPosition) entityliving.getPositionVector(), 32.0D)) { +- entityliving.getBehaviorController().setMemory(MemoryModuleType.HEARD_BELL_TIME, (Object) this.world.getTime()); ++ entityliving.getBehaviorController().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.world.getTime()); // Paper - decompile fix + } + } + } + ++ this.getEntitiesAtRing().removeIf(e -> !e.isAlive()); // Paper + } + + private boolean h() { diff --git a/patches/server-unmapped/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/patches/server-unmapped/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch new file mode 100644 index 0000000000..183a7c372f --- /dev/null +++ b/patches/server-unmapped/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Toon Schoenmakers +Date: Fri, 23 Oct 2020 15:01:44 +0200 +Subject: [PATCH] Avoid error bubbling up when item stack is empty in fishing + loot + +This can realistically only happen if there's custom loot active on fishing +which can return 0 items. This would disconnect the player who's fishing. + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +index 38bcc5a4435c4018b3233cc5e4c9142259e4396d..45f0f004e97b20e5c6c5b1f205b088bf8aa86017 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java +@@ -484,9 +484,15 @@ public class EntityFishingHook extends IProjectile { + + while (iterator.hasNext()) { + ItemStack itemstack1 = (ItemStack) iterator.next(); +- EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY(), this.locZ(), itemstack1); ++ // Paper start, new EntityItem would throw if for whatever reason (mostly shitty datapacks) the itemstack1 turns out to be empty ++ // if the item stack is empty we instead just have our entityitem as null ++ EntityItem entityitem = null; ++ if (!itemstack1.isEmpty()) { ++ entityitem = new EntityItem(this.world, this.locX(), this.locY(), this.locZ(), itemstack1); ++ } ++ // Paper end + // CraftBukkit start +- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null + playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); + this.world.getServer().getPluginManager().callEvent(playerFishEvent); + +@@ -499,8 +505,12 @@ public class EntityFishingHook extends IProjectile { + double d2 = entityhuman.locZ() - this.locZ(); + double d3 = 0.1D; + +- entityitem.setMot(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); +- this.world.addEntity(entityitem); ++ // Paper start, entity item can be null, so we need to check against this ++ if (entityitem != null) { ++ entityitem.setMot(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); ++ this.world.addEntity(entityitem); ++ } ++ // Paper end + // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() + if (playerFishEvent.getExpToDrop() > 0) { + entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getOwner(), this)); // Paper diff --git a/patches/server-unmapped/0589-Add-getOfflinePlayerIfCached-String.patch b/patches/server-unmapped/0589-Add-getOfflinePlayerIfCached-String.patch new file mode 100644 index 0000000000..0661e01e89 --- /dev/null +++ b/patches/server-unmapped/0589-Add-getOfflinePlayerIfCached-String.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: oxygencraft <21054297+oxygencraft@users.noreply.github.com> +Date: Sun, 25 Oct 2020 18:34:50 +1100 +Subject: [PATCH] Add getOfflinePlayerIfCached(String) + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 4dceb2d0beb6f91526b101d4947556049a0f3251..7277fd5807254020054cdbfb97fbd334e05da832 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1613,6 +1613,28 @@ public final class CraftServer implements Server { + return result; + } + ++ // Paper start ++ @Override ++ @Nullable ++ public OfflinePlayer getOfflinePlayerIfCached(String name) { ++ Validate.notNull(name, "Name cannot be null"); ++ Validate.notEmpty(name, "Name cannot be empty"); ++ ++ OfflinePlayer result = getPlayerExact(name); ++ if (result == null) { ++ GameProfile profile = console.getUserCache().getProfileIfCached(name); ++ ++ if (profile != null) { ++ result = getOfflinePlayer(profile); ++ } ++ } else { ++ offlinePlayers.remove(result.getUniqueId()); ++ } ++ ++ return result; ++ } ++ // Paper end ++ + @Override + public OfflinePlayer getOfflinePlayer(UUID id) { + Validate.notNull(id, "UUID cannot be null"); diff --git a/patches/server-unmapped/0590-Add-ignore-discounts-API.patch b/patches/server-unmapped/0590-Add-ignore-discounts-API.patch new file mode 100644 index 0000000000..1736070f08 --- /dev/null +++ b/patches/server-unmapped/0590-Add-ignore-discounts-API.patch @@ -0,0 +1,143 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Mon, 9 Nov 2020 20:44:51 +0100 +Subject: [PATCH] Add ignore discounts API + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index 5e84e33ffdda85be96c3d31fbd6a2aa3eab1106a..d1ddb12e8bd83d2218165340fe323c6be7bc83dd 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -460,6 +460,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + + while (iterator.hasNext()) { + MerchantRecipe merchantrecipe = (MerchantRecipe) iterator.next(); ++ if (merchantrecipe.ignoreDiscounts) continue; // Paper + + // CraftBukkit start + int bonus = -MathHelper.d((float) i * merchantrecipe.getPriceMultiplier()); +@@ -479,6 +480,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + + while (iterator1.hasNext()) { + MerchantRecipe merchantrecipe1 = (MerchantRecipe) iterator1.next(); ++ if (merchantrecipe1.ignoreDiscounts) continue; // Paper + double d0 = 0.3D + 0.0625D * (double) j; + int k = (int) Math.floor(d0 * (double) merchantrecipe1.a().getCount()); + +diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java +index 9e2fe0d5e6d4ea1f4c9cea96b755ddcd1e3c9009..605d1b2514c272c0fcf3cb9d7575ad8066dad31b 100644 +--- a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java ++++ b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java +@@ -19,6 +19,7 @@ public class MerchantRecipe { + private int demand; + public float priceMultiplier; + public int xp; ++ public boolean ignoreDiscounts; // Paper + // CraftBukkit start + private CraftMerchantRecipe bukkitHandle; + +@@ -27,7 +28,12 @@ public class MerchantRecipe { + } + + public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { +- this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier); ++ // Paper start - add ignoreDiscounts param ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, false, bukkit); ++ } ++ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, ignoreDiscounts); ++ // Paper end + this.bukkitHandle = bukkit; + } + // CraftBukkit end +@@ -59,6 +65,7 @@ public class MerchantRecipe { + + this.specialPrice = nbttagcompound.getInt("specialPrice"); + this.demand = nbttagcompound.getInt("demand"); ++ this.ignoreDiscounts = nbttagcompound.getBoolean("Paper.IgnoreDiscounts"); // Paper + } + + public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, int i, int j, float f) { +@@ -70,10 +77,19 @@ public class MerchantRecipe { + } + + public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f) { +- this(itemstack, itemstack1, itemstack2, i, j, k, f, 0); ++ // Paper start - add ignoreDiscounts param ++ this(itemstack, itemstack1, itemstack2, i, j, k, f, false); ++ } ++ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, boolean ignoreDiscounts) { ++ this(itemstack, itemstack1, itemstack2, i, j, k, f, 0, ignoreDiscounts); + } + + public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l) { ++ this(itemstack, itemstack1, itemstack2, i, j, k, f, l, false); ++ } ++ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l, boolean ignoreDiscounts) { ++ this.ignoreDiscounts = ignoreDiscounts; ++ // Paper end + this.rewardExp = true; + this.xp = 1; + this.buyingItem1 = itemstack; +@@ -189,6 +205,7 @@ public class MerchantRecipe { + nbttagcompound.setFloat("priceMultiplier", this.priceMultiplier); + nbttagcompound.setInt("specialPrice", this.specialPrice); + nbttagcompound.setInt("demand", this.demand); ++ nbttagcompound.setBoolean("Paper.IgnoreDiscounts", this.ignoreDiscounts); // Paper + return nbttagcompound; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java +index e3b9a0ebe5cec5b47d9d225887656e00e999960b..0c8728bd8272e36d70cf8f05fcd7656ea5a48702 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java +@@ -17,7 +17,12 @@ public class CraftMerchantRecipe extends MerchantRecipe { + } + + public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier) { +- super(result, uses, maxUses, experienceReward, experience, priceMultiplier); ++ // Paper start - add ignoreDiscounts param ++ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, false); ++ } ++ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, boolean ignoreDiscounts) { ++ super(result, uses, maxUses, experienceReward, experience, priceMultiplier, ignoreDiscounts); ++ // Paper end + this.handle = new net.minecraft.world.item.trading.MerchantRecipe( + net.minecraft.world.item.ItemStack.b, + net.minecraft.world.item.ItemStack.b, +@@ -26,6 +31,7 @@ public class CraftMerchantRecipe extends MerchantRecipe { + maxUses, + experience, + priceMultiplier, ++ ignoreDiscounts, // Paper - add ignoreDiscounts param + this + ); + this.setExperienceReward(experienceReward); +@@ -81,6 +87,18 @@ public class CraftMerchantRecipe extends MerchantRecipe { + handle.priceMultiplier = priceMultiplier; + } + ++ // Paper start ++ @Override ++ public boolean shouldIgnoreDiscounts() { ++ return this.handle.ignoreDiscounts; ++ } ++ ++ @Override ++ public void setIgnoreDiscounts(boolean ignoreDiscounts) { ++ this.handle.ignoreDiscounts = ignoreDiscounts; ++ } ++ // Paper end ++ + public net.minecraft.world.item.trading.MerchantRecipe toMinecraft() { + List ingredients = getIngredients(); + Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients"); +@@ -95,7 +113,7 @@ public class CraftMerchantRecipe extends MerchantRecipe { + if (recipe instanceof CraftMerchantRecipe) { + return (CraftMerchantRecipe) recipe; + } else { +- CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier()); ++ CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.shouldIgnoreDiscounts()); // Paper - shouldIgnoreDiscounts + craft.setIngredients(recipe.getIngredients()); + + return craft; diff --git a/patches/server-unmapped/0591-Toggle-for-removing-existing-dragon.patch b/patches/server-unmapped/0591-Toggle-for-removing-existing-dragon.patch new file mode 100644 index 0000000000..724d1c2111 --- /dev/null +++ b/patches/server-unmapped/0591-Toggle-for-removing-existing-dragon.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 30 Sep 2020 22:49:14 +0200 +Subject: [PATCH] Toggle for removing existing dragon + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 02bb85364560784adea47c877c13291c3d016b86..424754a0183b071d20c86f0420cec784a8992e2b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -683,4 +683,12 @@ public class PaperWorldConfig { + log("Using vanilla redstone algorithm."); + } + } ++ ++ public boolean shouldRemoveDragon = false; ++ private void shouldRemoveDragon() { ++ shouldRemoveDragon = getBoolean("should-remove-dragon", shouldRemoveDragon); ++ if (shouldRemoveDragon) { ++ log("The Ender Dragon will be removed if she already exists without a portal."); ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +index c6283489dcb6e13f0d618971614aeadaee2e3007..c0a6b340810b8ea4f454290b1ac22316ff0e6e22 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +@@ -214,7 +214,7 @@ public class EnderDragonBattle { + this.dragonUUID = entityenderdragon.getUniqueID(); + EnderDragonBattle.LOGGER.info("Found that there's a dragon still alive ({})", entityenderdragon); + this.dragonKilled = false; +- if (!flag) { ++ if (!flag && this.world.paperConfig.shouldRemoveDragon) { // Paper + EnderDragonBattle.LOGGER.info("But we didn't have a portal, let's remove it."); + entityenderdragon.die(); + this.dragonUUID = null; diff --git a/patches/server-unmapped/0592-Fix-client-lag-on-advancement-loading.patch b/patches/server-unmapped/0592-Fix-client-lag-on-advancement-loading.patch new file mode 100644 index 0000000000..c2ef60d3c7 --- /dev/null +++ b/patches/server-unmapped/0592-Fix-client-lag-on-advancement-loading.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Sat, 31 Oct 2020 11:49:01 -0700 +Subject: [PATCH] Fix client lag on advancement loading + +When new advancements are added via the UnsafeValues#loadAdvancement +API, it triggers a full datapack reload when this is not necessary. The +advancement is already loaded directly into the advancement registry, +and the point of saving the advancement to the Bukkit datapack seems to +be for persistence. By removing the call to reload datapacks when an +advancement is loaded, the client no longer completely freezes up when +adding a new advancement. +To ensure the client still receives the updated advancement data, we +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/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java +index 8e760445885f6ab92f60db0ee2a02d098b5e5f03..7a8a1960882e291c46301d07da3e1c5415516893 100644 +--- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java ++++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java +@@ -97,6 +97,7 @@ public class AdvancementDataPlayer { + + } + ++ public final void reload(AdvancementDataWorld advancementDataWorld) { this.a(advancementDataWorld); } // Paper - OBFHELPER + public void a(AdvancementDataWorld advancementdataworld) { + this.a(); + this.data.clear(); +@@ -393,6 +394,7 @@ public class AdvancementDataPlayer { + + } + ++ public final void sendUpdateIfNeeded(EntityPlayer entityPlayer) { this.b(entityPlayer); } // Paper - OBFHELPER + public void b(EntityPlayer entityplayer) { + if (this.m || !this.i.isEmpty() || !this.j.isEmpty()) { + Map map = Maps.newHashMap(); +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 5b03187f4d76e3052ee9abe0ee2774218d41b864..36ad77a5a3987c1de5d0de7cbcb94cb6fe841d44 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -309,7 +309,13 @@ public final class CraftMagicNumbers implements UnsafeValues { + Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex); + } + +- MinecraftServer.getServer().getPlayerList().reload(); ++ // Paper start ++ //MinecraftServer.getServer().getPlayerList().reload(); ++ MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> { ++ player.getAdvancementData().reload(MinecraftServer.getServer().getAdvancementData()); ++ player.getAdvancementData().sendUpdateIfNeeded(player); ++ }); ++ // Paper end + + return bukkit; + } diff --git a/patches/server-unmapped/0593-Item-no-age-no-player-pickup.patch b/patches/server-unmapped/0593-Item-no-age-no-player-pickup.patch new file mode 100644 index 0000000000..84124da98a --- /dev/null +++ b/patches/server-unmapped/0593-Item-no-age-no-player-pickup.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Smith +Date: Sat, 7 Nov 2020 01:20:33 +0000 +Subject: [PATCH] Item no age & no player pickup + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +index 5988cdd18b7e4bfca0075fd2356cfe9c4e673954..7a78ef2f6f673568c0528fa46168c69d21f51a66 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +@@ -10,6 +10,12 @@ import org.bukkit.entity.Item; + import org.bukkit.inventory.ItemStack; + + public class CraftItem extends CraftEntity implements Item { ++ ++ // Paper start ++ private final static int NO_AGE_TIME = (int) Short.MIN_VALUE; ++ private final static int NO_PICKUP_TIME = (int) Short.MAX_VALUE; ++ // Paper end ++ + private final EntityItem item; + + public CraftItem(CraftServer server, Entity entity, EntityItem item) { +@@ -57,6 +63,26 @@ public class CraftItem extends CraftEntity implements Item { + public void setCanMobPickup(boolean canMobPickup) { + item.canMobPickup = canMobPickup; + } ++ ++ @Override ++ public boolean canPlayerPickup() { ++ return item.pickupDelay != NO_PICKUP_TIME; ++ } ++ ++ @Override ++ public void setCanPlayerPickup(boolean canPlayerPickup) { ++ item.pickupDelay = canPlayerPickup ? 0 : NO_PICKUP_TIME; ++ } ++ ++ @Override ++ public boolean willAge() { ++ return item.age != NO_AGE_TIME; ++ } ++ ++ @Override ++ public void setWillAge(boolean willAge) { ++ item.age = willAge ? 0 : NO_AGE_TIME; ++ } + // Paper End + + @Override diff --git a/patches/server-unmapped/0594-Beacon-API-custom-effect-ranges.patch b/patches/server-unmapped/0594-Beacon-API-custom-effect-ranges.patch new file mode 100644 index 0000000000..7b77b21a0d --- /dev/null +++ b/patches/server-unmapped/0594-Beacon-API-custom-effect-ranges.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 24 Jun 2020 12:39:08 -0600 +Subject: [PATCH] Beacon API - custom effect ranges + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java +index 4098357d60165a4c670a7bc5134abf66178124c6..cd28a731a56eb7534faae5b120195b62d5d15bd4 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java +@@ -73,6 +73,26 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic + return (hasSecondaryEffect()) ? CraftPotionUtil.toBukkit(new MobEffect(this.secondaryEffect, getLevel(), getAmplification(), true, true)) : null; + } + // CraftBukkit end ++ // Paper start - add field/methods for custom range ++ private final String PAPER_RANGE_TAG = "Paper.Range"; ++ private double effectRange = -1; ++ ++ public double getEffectRange() { ++ if (this.effectRange < 0) { ++ return this.levels * 10 + 10; ++ } else { ++ return effectRange; ++ } ++ } ++ ++ public void setEffectRange(double range) { ++ this.effectRange = range; ++ } ++ ++ public void resetEffectRange() { ++ this.effectRange = -1; ++ } ++ // Paper end + + public TileEntityBeacon() { + super(TileEntityTypes.BEACON); +@@ -263,7 +283,8 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic + + public List getHumansInRange() { + { +- double d0 = (double) (this.levels * 10 + 10); ++ // Paper - custom beacon ranges ++ double d0 = this.getEffectRange(); + + AxisAlignedBB axisalignedbb = (new AxisAlignedBB(this.position)).g(d0).b(0.0D, (double) this.world.getBuildHeight(), 0.0D); + List list = this.world.a(EntityHuman.class, axisalignedbb); +@@ -363,6 +384,9 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic + this.secondaryEffect = MobEffectList.fromId(nbttagcompound.getInt("Secondary")); + this.levels = nbttagcompound.getInt("Levels"); // SPIGOT-5053, use where available + // CraftBukkit end ++ // Paper ++ this.effectRange = nbttagcompound.hasKeyOfType(PAPER_RANGE_TAG, 6) ? nbttagcompound.getDouble(PAPER_RANGE_TAG) : -1; ++ + if (nbttagcompound.hasKeyOfType("CustomName", 8)) { + this.customName = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName")); + } +@@ -379,6 +403,8 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic + if (this.customName != null) { + nbttagcompound.setString("CustomName", IChatBaseComponent.ChatSerializer.a(this.customName)); + } ++ // Paper ++ nbttagcompound.setDouble(PAPER_RANGE_TAG, this.effectRange); + + this.chestLock.a(nbttagcompound); + return nbttagcompound; +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +index d3ae5cadd88f9012203d2c04cbe38af9b215ef0b..c2e054853cba891326d45e9129bbc09e32fa3cc7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +@@ -108,4 +108,19 @@ public class CraftBeacon extends CraftBlockEntityState impleme + public void setLock(String key) { + this.getSnapshot().chestLock = (key == null) ? ChestLock.a : new ChestLock(key); + } ++ ++ @Override ++ public double getEffectRange() { ++ return this.getSnapshot().getEffectRange(); ++ } ++ ++ @Override ++ public void setEffectRange(double range) { ++ this.getSnapshot().setEffectRange(range); ++ } ++ ++ @Override ++ public void resetEffectRange() { ++ this.getSnapshot().resetEffectRange(); ++ } + } diff --git a/patches/server-unmapped/0595-Add-API-for-quit-reason.patch b/patches/server-unmapped/0595-Add-API-for-quit-reason.patch new file mode 100644 index 0000000000..be191ccc04 --- /dev/null +++ b/patches/server-unmapped/0595-Add-API-for-quit-reason.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 14 Nov 2020 16:19:52 +0100 +Subject: [PATCH] Add API for quit reason + + +diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +index 878f879f8d410c428ad8a4c49e0c86c559bc47a9..f86f430598026a3a7e27fb8d40cfc5fe7b9b845d 100644 +--- a/src/main/java/net/minecraft/network/NetworkManager.java ++++ b/src/main/java/net/minecraft/network/NetworkManager.java +@@ -137,12 +137,15 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + + this.u = true; + if (this.channel.isOpen()) { ++ EntityPlayer player = this.getPlayer(); // Paper + if (throwable instanceof TimeoutException) { + NetworkManager.LOGGER.debug("Timeout", throwable); ++ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper + this.close(new ChatMessage("disconnect.timeout")); + } else { + ChatMessage chatmessage = new ChatMessage("disconnect.genericReason", new Object[]{"Internal Exception: " + throwable}); + ++ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper + if (flag) { + NetworkManager.LOGGER.debug("Failed to sent packet", throwable); + this.sendPacket(new PacketPlayOutKickDisconnect(chatmessage), (future) -> { +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 3908dc27a5cf127ab3c3630da47318da1bf4e3c9..78fcb90c86700ee6feef0d40753fc8d8a943777f 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -261,6 +261,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks + + boolean needsChunkCenterUpdate; // Paper - no-tick view distance ++ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event + + public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { + super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 73a1730f1c683b2345a9c3d4f2288ceab20a6625..cf81710e41420f6cd027231998ebf5305f23f3d5 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -449,6 +449,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + final IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure + // CraftBukkit end + ++ this.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper + this.networkManager.sendPacket(new PacketPlayOutKickDisconnect(ichatbasecomponent), (future) -> { + this.networkManager.close(ichatbasecomponent); + }); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 8bd55e3d2b5142081a7dfe1dbbd36f2f995e5856..e0bbb7f3ea7ce4902cd14e64357472087ce6912a 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -590,7 +590,7 @@ public abstract class PlayerList { + entityplayer.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper + } + +- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName())), entityplayer.quitReason); // Paper - quit reason + if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + diff --git a/patches/server-unmapped/0596-Seed-based-feature-search.patch b/patches/server-unmapped/0596-Seed-based-feature-search.patch new file mode 100644 index 0000000000..29bb86682d --- /dev/null +++ b/patches/server-unmapped/0596-Seed-based-feature-search.patch @@ -0,0 +1,115 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Mon, 13 Jan 2020 15:40:32 +0100 +Subject: [PATCH] Seed based feature search + +This tries to work around the issue where the server will load +surrounding chunks up to a radius of 100 chunks in order to search for +features e.g. when running the /locate command or for treasure maps +(issue #2312). +This is done by backporting Mojang's change in 1.17 which makes it so +that the biome (generated by the seed) is checked first if the feature +can be generated before actually to load the chunk. + +Additionally to that the center location of the target chunk is simply +returned if the chunk is not loaded to avoid the sync chunk load. +As this can lead to less precise locations a toggle is provided to +enable the sync loading of the target chunk again. + +The main downside of this is that it breaks once the seed or generator +changes but this should usually not happen. A config option to disable +this completely is added though in case that should ever be necessary. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 424754a0183b071d20c86f0420cec784a8992e2b..97870622e41cca36d9c7493bfad796f35f3831f4 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -337,6 +337,14 @@ public class PaperWorldConfig { + } + } + ++ public boolean seedBasedFeatureSearch = true; ++ public boolean seedBasedFeatureSearchLoadsChunks = false; ++ private void seedBasedFeatureSearch() { ++ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch); ++ seedBasedFeatureSearchLoadsChunks = getBoolean("seed-based-feature-search-loads-chunks", seedBasedFeatureSearchLoadsChunks); ++ log("Feature search is based on seed: " + seedBasedFeatureSearch + ", loads chunks:" + seedBasedFeatureSearchLoadsChunks); ++ } ++ + public int maxCollisionsPerEntity; + private void maxEntityCollision() { + maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); +diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java +index e41d63596c32eee5f0c04a6f043d576d8021ff1a..53eb5b65683a2ab208edfc3f3bbf78ffee61bc85 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java ++++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java +@@ -68,10 +68,12 @@ public class ChunkCoordIntPair { + } + } + ++ public int getBlockX() { return d(); } // Paper - OBFHELPER + public int d() { + return this.x << 4; + } + ++ public int getBlockZ() { return e(); } // Paper - OBFHELPER + public int e() { + return this.z << 4; + } +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index ae5f9a6af810b524f6dcbed64bc943122f0536cc..f40be366ebc5f98b417b677565fa89d3f817f3fb 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -1511,8 +1511,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return this.methodProfiler; + } + +- @Override +- public BiomeManager d() { ++ public BiomeManager getBiomeManager() { return d(); } // Paper - OBFHELPER ++ @Override public BiomeManager d() { + return this.biomeManager; + } + +diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java +index 340508e0ba8b8883a3037ecaa2d4e09e61e709d3..3b1d9b26ba3249b1df0c15a22428e4211ae0e024 100644 +--- a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java ++++ b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java +@@ -23,6 +23,7 @@ public class BiomeManager { + return new BiomeManager(worldchunkmanager, this.b, this.c); + } + ++ public BiomeBase getBiome(BlockPosition blockposition) { return a(blockposition); } // Paper - OBFHELPER + public BiomeBase a(BlockPosition blockposition) { + return this.c.a(this.b, blockposition.getX(), blockposition.getY(), blockposition.getZ(), this.a); + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java +index ea7e3e15fa778c573d24f956f72f60579ea0b1a1..e5c22e92a305050df0eae2da53217ea2c3249e03 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java +@@ -176,7 +176,24 @@ public abstract class StructureGenerator + int j2 = i1 + k * l1; + ChunkCoordIntPair chunkcoordintpair = this.a(structuresettingsfeature, j, seededrandom, i2, j2); + if (!iworldreader.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper +- IChunkAccess ichunkaccess = iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); ++ // Paper start - seed based feature search ++ IChunkAccess ichunkaccess = null; ++ if (structuremanager.getWorld().paperConfig.seedBasedFeatureSearch) { ++ BiomeBase biomeBase = structuremanager.getWorld().getBiomeManager().getBiome(new BlockPosition(chunkcoordintpair.getBlockX() + 9, 0, chunkcoordintpair.getBlockZ() + 9)); ++ if (!biomeBase.e().a(this)) { ++ continue; ++ } ++ if (!structuremanager.getWorld().paperConfig.seedBasedFeatureSearchLoadsChunks) { ++ ichunkaccess = structuremanager.getWorld().getChunkIfLoaded(chunkcoordintpair.x, chunkcoordintpair.z); ++ if (ichunkaccess == null) { ++ return chunkcoordintpair.asPosition().add(8, blockposition.getY(), 8); ++ } ++ } ++ } ++ if (ichunkaccess == null) { ++ ichunkaccess = iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); ++ } ++ // Paper end + StructureStart structurestart = structuremanager.a(SectionPosition.a(ichunkaccess.getPos(), 0), this, ichunkaccess); + + if (structurestart != null && structurestart.e()) { diff --git a/patches/server-unmapped/0597-Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server-unmapped/0597-Add-Wandering-Trader-spawn-rate-config-options.patch new file mode 100644 index 0000000000..0b28af3165 --- /dev/null +++ b/patches/server-unmapped/0597-Add-Wandering-Trader-spawn-rate-config-options.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Thu, 20 Aug 2020 11:20:12 -0700 +Subject: [PATCH] Add Wandering Trader spawn rate config options + +Adds config options for modifying the spawn rates of Wandering Traders. +These values are all easy to understand and configure after a quick read of this +page on the Minecraft wiki: https://minecraft.gamepedia.com/Wandering_Trader#Spawning +Usages of the vanilla WanderingTraderSpawnDelay and WanderingTraderSpawnChance values +in IWorldServerData are removed as they were only used in certain places, with hardcoded +values used in other places. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 97870622e41cca36d9c7493bfad796f35f3831f4..5a451cc855de57f79a57670ba38e3af2343cb510 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -699,4 +699,17 @@ public class PaperWorldConfig { + log("The Ender Dragon will be removed if she already exists without a portal."); + } + } ++ ++ public int wanderingTraderSpawnMinuteTicks = 1200; ++ public int wanderingTraderSpawnDayTicks = 24000; ++ public int wanderingTraderSpawnChanceFailureIncrement = 25; ++ public int wanderingTraderSpawnChanceMin = 25; ++ public int wanderingTraderSpawnChanceMax = 75; ++ private void wanderingTraderSettings() { ++ wanderingTraderSpawnMinuteTicks = getInt("wandering-trader.spawn-minute-length", wanderingTraderSpawnMinuteTicks); ++ wanderingTraderSpawnDayTicks = getInt("wandering-trader.spawn-day-length", wanderingTraderSpawnDayTicks); ++ wanderingTraderSpawnChanceFailureIncrement = getInt("wandering-trader.spawn-chance-failure-increment", wanderingTraderSpawnChanceFailureIncrement); ++ wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); ++ wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java +index b74a262a62642f63fdbd17579d58d5eae68ed169..e57938b4591bb103b9dd0d0145a62b5a901f2c63 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java +@@ -30,49 +30,59 @@ public class MobSpawnerTrader implements MobSpawner { + + private final Random a = new Random(); + private final IWorldDataServer b; +- private int c; +- private int d; +- private int e; ++ private int c; public final int getMinuteTimer() { return this.c; } public final void setMinuteTimer(int x) { this.c = x; } // Paper - OBFHELPER ++ private int d; public final int getDayTimer() { return this.d; } public final void setDayTimer(int x) { this.d = x; } // Paper - OBFHELPER ++ private int e; public final int getSpawnChance() { return this.e; } public final void setSpawnChance(int x) { this.e = x; } // Paper - OBFHELPER + + public MobSpawnerTrader(IWorldDataServer iworlddataserver) { + this.b = iworlddataserver; +- this.c = 1200; +- this.d = iworlddataserver.v(); +- this.e = iworlddataserver.w(); +- if (this.d == 0 && this.e == 0) { +- this.d = 24000; +- iworlddataserver.g(this.d); +- this.e = 25; +- iworlddataserver.h(this.e); +- } ++ // Paper start ++ this.setMinuteTimer(Integer.MIN_VALUE); ++ //this.d = iworlddataserver.v(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value ++ //this.e = iworlddataserver.w(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value ++ //if (this.d == 0 && this.e == 0) { ++ // this.d = 24000; ++ // iworlddataserver.g(this.d); ++ // this.e = 25; ++ // iworlddataserver.h(this.e); ++ //} ++ // Paper end + + } + + @Override + public int a(WorldServer worldserver, boolean flag, boolean flag1) { ++ // Paper start ++ if (this.getMinuteTimer() == Integer.MIN_VALUE) { ++ this.setMinuteTimer(worldserver.paperConfig.wanderingTraderSpawnMinuteTicks); ++ this.setDayTimer(worldserver.paperConfig.wanderingTraderSpawnDayTicks); ++ this.setSpawnChance(worldserver.paperConfig.wanderingTraderSpawnChanceMin); ++ } + if (!worldserver.getGameRules().getBoolean(GameRules.DO_TRADER_SPAWNING)) { + return 0; +- } else if (--this.c > 0) { ++ } else if (this.getMinuteTimer() - 1 > 0) { ++ this.setMinuteTimer(this.getMinuteTimer() - 1); + return 0; + } else { +- this.c = 1200; +- this.d -= 1200; +- this.b.g(this.d); +- if (this.d > 0) { ++ this.setMinuteTimer(worldserver.paperConfig.wanderingTraderSpawnMinuteTicks); ++ this.setDayTimer(getDayTimer() - worldserver.paperConfig.wanderingTraderSpawnMinuteTicks); ++ //this.b.g(this.d); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways ++ if (this.getDayTimer() > 0) { + return 0; + } else { +- this.d = 24000; ++ this.setDayTimer(worldserver.paperConfig.wanderingTraderSpawnDayTicks); + if (!worldserver.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING)) { + return 0; + } else { +- int i = this.e; ++ int i = this.getSpawnChance(); + +- this.e = MathHelper.clamp(this.e + 25, 25, 75); +- this.b.h(this.e); ++ this.setSpawnChance(MathHelper.clamp(i + worldserver.paperConfig.wanderingTraderSpawnChanceFailureIncrement, worldserver.paperConfig.wanderingTraderSpawnChanceMin, worldserver.paperConfig.wanderingTraderSpawnChanceMax)); ++ //this.b.h(this.e); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways + if (this.a.nextInt(100) > i) { + return 0; + } else if (this.a(worldserver)) { +- this.e = 25; ++ this.setSpawnChance(worldserver.paperConfig.wanderingTraderSpawnChanceMin); ++ // Paper end + return 1; + } else { + return 0; diff --git a/patches/server-unmapped/0598-Significantly-improve-performance-of-the-end-generat.patch b/patches/server-unmapped/0598-Significantly-improve-performance-of-the-end-generat.patch new file mode 100644 index 0000000000..b205a133b3 --- /dev/null +++ b/patches/server-unmapped/0598-Significantly-improve-performance-of-the-end-generat.patch @@ -0,0 +1,77 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com> +Date: Tue, 3 Nov 2020 23:48:05 -0600 +Subject: [PATCH] Significantly improve performance of the end generation + +This patch implements a noise cache for the end which significantly reduces the computation time of generation. This results in about a 3x improvement. + +Original code by SuperCoder7979 and Gegy in Lithium, licensed under LGPL-3.0 (Source: https://github.com/jellysquid3/lithium-fabric) + +Co-authored-by: Gegy +Co-authored-by: Dylan Xaldin +Co-authored-by: pop4959 + +diff --git a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java +index 1077972d694d604c3ec97d333d34a9ab81819c33..62fe4cc00a24e330443d2f006a88dbab3798fb28 100644 +--- a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java ++++ b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java +@@ -3,10 +3,12 @@ package net.minecraft.world.level.biome; + import com.google.common.collect.ImmutableList; + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; ++import it.unimi.dsi.fastutil.HashCommon; // Paper + import java.util.List; + import net.minecraft.core.IRegistry; + import net.minecraft.resources.RegistryLookupCodec; + import net.minecraft.util.MathHelper; ++import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.levelgen.SeededRandom; + import net.minecraft.world.level.levelgen.synth.NoiseGenerator3Handler; + +@@ -27,6 +29,16 @@ public class WorldChunkManagerTheEnd extends WorldChunkManager { + private final BiomeBase k; + private final BiomeBase l; + private final BiomeBase m; ++ // Paper start ++ private static final class NoiseCache { ++ public long[] keys = new long[8192]; ++ public float[] values = new float[8192]; ++ public NoiseCache() { ++ java.util.Arrays.fill(keys, Long.MIN_VALUE); ++ } ++ } ++ private static final ThreadLocal> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new); ++ // Paper end + + public WorldChunkManagerTheEnd(IRegistry iregistry, long i) { + this(iregistry, i, (BiomeBase) iregistry.d(Biomes.THE_END), (BiomeBase) iregistry.d(Biomes.END_HIGHLANDS), (BiomeBase) iregistry.d(Biomes.END_MIDLANDS), (BiomeBase) iregistry.d(Biomes.SMALL_END_ISLANDS), (BiomeBase) iregistry.d(Biomes.END_BARRENS)); +@@ -81,13 +93,27 @@ public class WorldChunkManagerTheEnd extends WorldChunkManager { + + f = MathHelper.a(f, -100.0F, 80.0F); + ++ NoiseCache cache = noiseCache.get().computeIfAbsent(noisegenerator3handler, m -> new NoiseCache()); // Paper + for (int k1 = -12; k1 <= 12; ++k1) { + for (int l1 = -12; l1 <= 12; ++l1) { + long i2 = (long) (k + k1); + long j2 = (long) (l + l1); + +- if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.a((double) i2, (double) j2) < -0.8999999761581421D) { +- float f1 = (MathHelper.e((float) i2) * 3439.0F + MathHelper.e((float) j2) * 147.0F) % 13.0F + 9.0F; ++ // Paper start - Significantly improve end generation performance by using a noise cache ++ long key = ChunkCoordIntPair.pair((int) i2, (int) j2); ++ int index = (int) HashCommon.mix(key) & 8191; ++ float f1 = Float.MIN_VALUE; ++ if (cache.keys[index] == key) { ++ f1 = cache.values[index]; ++ } else { ++ if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.a((double) i2, (double) j2) < -0.8999999761581421D) { ++ f1 = (MathHelper.e((float) i2) * 3439.0F + MathHelper.e((float) j2) * 147.0F) % 13.0F + 9.0F; ++ } ++ cache.keys[index] = key; ++ cache.values[index] = f1; ++ } ++ if (f1 != Float.MIN_VALUE) { ++ // Paper end + float f2 = (float) (i1 - k1 * 2); + float f3 = (float) (j1 - l1 * 2); + float f4 = 100.0F - MathHelper.c(f2 * f2 + f3 * f3) * f1; diff --git a/patches/server-unmapped/0599-Expose-world-spawn-angle.patch b/patches/server-unmapped/0599-Expose-world-spawn-angle.patch new file mode 100644 index 0000000000..881cbed405 --- /dev/null +++ b/patches/server-unmapped/0599-Expose-world-spawn-angle.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Tue, 17 Nov 2020 19:13:09 +0200 +Subject: [PATCH] Expose world spawn angle + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index e0bbb7f3ea7ce4902cd14e64357472087ce6912a..66fbbc4c91e16a3dfb4bb756972e667121693501 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -894,7 +894,7 @@ public abstract class PlayerList { + if (location == null) { + worldserver1 = this.server.getWorldServer(World.OVERWORLD); + blockposition = entityplayer1.getSpawnPoint(worldserver1); +- location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F)); ++ location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F), worldserver1.worldData.getSpawnAngle(), 0.0F); // Paper - use world spawn angle + } + + Player respawnPlayer = cserver.getPlayer(entityplayer1); +diff --git a/src/main/java/net/minecraft/world/level/storage/WorldData.java b/src/main/java/net/minecraft/world/level/storage/WorldData.java +index 81ad90ba93481decdfaa38fc9fa81bca0e402781..7599488f7d4b168c92078c2d2987cb38f0dee8a9 100644 +--- a/src/main/java/net/minecraft/world/level/storage/WorldData.java ++++ b/src/main/java/net/minecraft/world/level/storage/WorldData.java +@@ -12,6 +12,7 @@ public interface WorldData { + + int c(); + ++ default float getSpawnAngle() { return d(); } // Paper - OBFHELPER + float d(); + + long getTime(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 76a7889b49a16ddeb8f310d3a79cfee80ad9a1db..776733a4a913d232126b48f2d0eadbe27aa84e59 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -380,7 +380,7 @@ public class CraftWorld implements World { + @Override + public Location getSpawnLocation() { + BlockPosition spawn = world.getSpawn(); +- return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); ++ return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ(), world.worldData.getSpawnAngle(), 0.0F); // Paper - expose world spawn angle + } + + @Override diff --git a/patches/server-unmapped/0600-Add-Destroy-Speed-API.patch b/patches/server-unmapped/0600-Add-Destroy-Speed-API.patch new file mode 100644 index 0000000000..bdeb073a85 --- /dev/null +++ b/patches/server-unmapped/0600-Add-Destroy-Speed-API.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ineusia +Date: Mon, 26 Oct 2020 11:48:06 -0500 +Subject: [PATCH] Add Destroy Speed API + +Co-authored-by: Jake Potrebic + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index f1f03bd0162a158761f300cbd96aa32101542abb..fab9e1e5d63c22faceae093dc88769d203d359c6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -769,5 +769,23 @@ public class CraftBlock implements Block { + public String getTranslationKey() { + return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); + } ++ ++ @Override ++ public float getDestroySpeed(ItemStack itemStack, boolean considerEnchants) { ++ net.minecraft.world.item.ItemStack nmsItemStack; ++ if (itemStack instanceof CraftItemStack) { ++ nmsItemStack = ((CraftItemStack) itemStack).getHandle(); ++ } else { ++ nmsItemStack = CraftItemStack.asNMSCopy(itemStack); ++ } ++ float speed = nmsItemStack.getItem().getDestroySpeed(nmsItemStack, this.getNMSBlock().getBlockData()); ++ if (speed > 1.0F && considerEnchants) { ++ int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentManager.getEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.DIG_SPEED, nmsItemStack); ++ if (enchantLevel > 0) { ++ speed += enchantLevel * enchantLevel + 1; ++ } ++ } ++ return speed; ++ } + // Paper end + } diff --git a/patches/server-unmapped/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/patches/server-unmapped/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch new file mode 100644 index 0000000000..54e629a54c --- /dev/null +++ b/patches/server-unmapped/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Esophose +Date: Sat, 3 Oct 2020 18:57:47 -0600 +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 8337ed8bb20b8d887bcd71ddc5f29bce346c7cff..41987716afa8ec34214868373df97d0e8f8b27c1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2012,7 +2012,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + if (data != null && !particle.getDataType().isInstance(data)) { + throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); + } +- PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(CraftParticle.toNMS(particle, data), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); ++ PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(CraftParticle.toNMS(particle, data), true, x, y, z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); // Paper - Fix x/y/z coordinate precision loss + getHandle().playerConnection.sendPacket(packetplayoutworldparticles); + + } diff --git a/patches/server-unmapped/0602-Add-LivingEntity-clearActiveItem.patch b/patches/server-unmapped/0602-Add-LivingEntity-clearActiveItem.patch new file mode 100644 index 0000000000..c2455803ab --- /dev/null +++ b/patches/server-unmapped/0602-Add-LivingEntity-clearActiveItem.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Anrza +Date: Wed, 15 Jul 2020 12:08:49 +0200 +Subject: [PATCH] Add LivingEntity#clearActiveItem + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index de12a050739b8d12d268cc9ca496259ea2c46569..3bee6903a591bbfe312c6d7e276d7cef3dafc852 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -785,6 +785,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return getHandle().activeItem.asBukkitMirror(); + } + ++ // Paper start ++ @Override ++ public void clearActiveItem() { ++ getHandle().clearActiveItem(); ++ } ++ // Paper end ++ + @Override + public int getItemUseRemainingTime() { + return getHandle().getItemUseRemainingTime(); diff --git a/patches/server-unmapped/0603-Add-PlayerItemCooldownEvent.patch b/patches/server-unmapped/0603-Add-PlayerItemCooldownEvent.patch new file mode 100644 index 0000000000..81581680ce --- /dev/null +++ b/patches/server-unmapped/0603-Add-PlayerItemCooldownEvent.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Tue, 25 Aug 2020 13:48:33 +0200 +Subject: [PATCH] Add PlayerItemCooldownEvent + + +diff --git a/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java b/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java +index 5f70e39f4da2880a6f734a225be83061b00847c8..ef9ffad211473f1cbcd0b8fd200ff04ec2051f94 100644 +--- a/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java ++++ b/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java +@@ -3,14 +3,26 @@ package net.minecraft.world.item; + import net.minecraft.network.protocol.game.PacketPlayOutSetCooldown; + import net.minecraft.server.level.EntityPlayer; + ++import io.papermc.paper.event.player.PlayerItemCooldownEvent; // Paper ++ + public class ItemCooldownPlayer extends ItemCooldown { + +- private final EntityPlayer a; ++ private final EntityPlayer a; public EntityPlayer getEntityPlayer() { return a; } // Paper - OBFHELPER + + public ItemCooldownPlayer(EntityPlayer entityplayer) { + this.a = entityplayer; + } + ++ // Paper start ++ @Override ++ public void setCooldown(Item item, int ticks) { ++ PlayerItemCooldownEvent event = new PlayerItemCooldownEvent(getEntityPlayer().getBukkitEntity(), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(item), ticks); ++ if (event.callEvent()) { ++ super.setCooldown(item, event.getCooldown()); ++ } ++ } ++ // Paper end ++ + @Override + protected void b(Item item, int i) { + super.b(item, i); diff --git a/patches/server-unmapped/0604-More-lightning-API.patch b/patches/server-unmapped/0604-More-lightning-API.patch new file mode 100644 index 0000000000..e08b3251e5 --- /dev/null +++ b/patches/server-unmapped/0604-More-lightning-API.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Sun, 26 Jul 2020 14:44:09 +0200 +Subject: [PATCH] More lightning API + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLightning.java b/src/main/java/net/minecraft/world/entity/EntityLightning.java +index 834ced9d9b385c8f1d66355244313d62a97d9c98..85f571a791bce63989890f277857bc7bdeec0cb5 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLightning.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLightning.java +@@ -31,7 +31,7 @@ public class EntityLightning extends Entity { + + private int lifeTicks; + public long b; +- private int d; ++ private int d; public int getFlashCount() { return d; } public void setFlashCount(int flashes) { this.d = flashes; } // Paper - OBFHELPER + public boolean isEffect; + @Nullable + private EntityPlayer f; +@@ -49,6 +49,16 @@ public class EntityLightning extends Entity { + this.isEffect = flag; + } + ++ // Paper start ++ public int getLifeTicks() { ++ return lifeTicks; ++ } ++ ++ public void setLifeTicks(int lifeTicks) { ++ this.lifeTicks = lifeTicks; ++ } ++ // Paper end ++ + @Override + public SoundCategory getSoundCategory() { + return SoundCategory.WEATHER; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java +index 3e054592cef6526b769d14460a671ea78a5ef58a..395f702b14425d85ff3a7938c32f7bfd5523f3ca 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java +@@ -45,4 +45,27 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike + return spigot; + } + // Spigot end ++ ++ // Paper start ++ @Override ++ public int getFlashCount() { ++ return getHandle().getFlashCount(); ++ } ++ ++ @Override ++ public void setFlashCount(int flashes) { ++ com.google.common.base.Preconditions.checkArgument(flashes >= 0, "Flashes has to be a positive number!"); ++ getHandle().setFlashCount(flashes); ++ } ++ ++ @Override ++ public int getLifeTicks() { ++ return getHandle().getLifeTicks(); ++ } ++ ++ @Override ++ public void setLifeTicks(int lifeTicks) { ++ getHandle().setLifeTicks(lifeTicks); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0605-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server-unmapped/0605-Climbing-should-not-bypass-cramming-gamerule.patch new file mode 100644 index 0000000000..f9842f65c3 --- /dev/null +++ b/patches/server-unmapped/0605-Climbing-should-not-bypass-cramming-gamerule.patch @@ -0,0 +1,179 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 23 Aug 2020 20:59:00 +0200 +Subject: [PATCH] Climbing should not bypass cramming gamerule + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5a451cc855de57f79a57670ba38e3af2343cb510..7d3207a9af8360ddad228281d6aa65e1a0d24157 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -712,4 +712,9 @@ public class PaperWorldConfig { + wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); + wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); + } ++ ++ public boolean fixClimbingBypassingCrammingRule = false; ++ private void fixClimbingBypassingCrammingRule() { ++ fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 0841cf7e968a8a3b577e91f6dcd0487169474329..dc0e2a1348062ea79b1ec3a9fdb985d9d3fca790 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1575,6 +1575,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public boolean isCollidable() { ++ // Paper start ++ return isCollidable(false); ++ } ++ ++ public boolean isCollidable(boolean ignoreClimbing) { ++ // Paper end + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 60dfa764898b59b60aec2da9580a80634e624dbe..b56c801c02e4f206b72db7dd74672727104bf246 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -137,7 +137,6 @@ import org.bukkit.event.entity.EntityTeleportEvent; + import org.bukkit.event.player.PlayerItemConsumeEvent; + // CraftBukkit end + +-import co.aikar.timings.MinecraftTimings; // Paper + + public abstract class EntityLiving extends Entity { + +@@ -2959,7 +2958,7 @@ public abstract class EntityLiving extends Entity { + return; + } + // Paper - end don't run getEntities if we're not going to use its result +- List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.a(this)); ++ List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.pushable(this, world.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule + + if (!list.isEmpty()) { + // Paper - move up +@@ -3097,9 +3096,16 @@ public abstract class EntityLiving extends Entity { + return !this.dead && this.collides; // CraftBukkit + } + ++ // Paper start + @Override + public boolean isCollidable() { +- return this.isAlive() && !this.isSpectator() && !this.isClimbing() && this.collides; // CraftBukkit ++ return this.isCollidable(world.paperConfig.fixClimbingBypassingCrammingRule); ++ } ++ ++ @Override ++ public boolean isCollidable(boolean ignoreClimbing) { ++ return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.isClimbing()) && this.collides; // CraftBukkit ++ // Paper end + } + + // CraftBukkit start - collidable API +diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +index c8d7ea8cfa4945af4a6675172b931a4cc3ca2801..f5e32faeb6d937cf90b1f3ea251b5cfc91f2338d 100644 +--- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java +@@ -51,11 +51,17 @@ public final class IEntitySelector { + } + + public static Predicate a(Entity entity) { ++ // Paper start - ignoreClimbing param ++ return pushable(entity, false); ++ } ++ ++ public static Predicate pushable(Entity entity, boolean ignoreClimbing) { ++ // Paper end + ScoreboardTeamBase scoreboardteambase = entity.getScoreboardTeam(); + ScoreboardTeamBase.EnumTeamPush scoreboardteambase_enumteampush = scoreboardteambase == null ? ScoreboardTeamBase.EnumTeamPush.ALWAYS : scoreboardteambase.getCollisionRule(); + + return (Predicate) (scoreboardteambase_enumteampush == ScoreboardTeamBase.EnumTeamPush.NEVER ? Predicates.alwaysFalse() : IEntitySelector.g.and((entity1) -> { +- if (!entity1.canCollideWith(entity) || !entity.canCollideWith(entity1)) { // CraftBukkit - collidable API ++ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWith(entity) || !entity.canCollideWith(entity1)) { // CraftBukkit - collidable API // Paper - isCollidable + return false; + } else if (entity.world.isClientSide && (!(entity1 instanceof EntityHuman) || !((EntityHuman) entity1).ez())) { + return false; +diff --git a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java +index 2167590677c68d261b804a16853bd943f16a76dd..61ebb278cf4ef57ae7a86c6c6ef1fa14559f21e2 100644 +--- a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java ++++ b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java +@@ -76,7 +76,7 @@ public class EntityBat extends EntityAmbient { + } + + @Override +- public boolean isCollidable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java +index e93375171462b95e270230f5f72f7eb5c6b0ff58..699dd0ac1f8d0d340ab1a560106336fc7cc95d5b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java +@@ -368,8 +368,8 @@ public class EntityParrot extends EntityPerchable implements EntityBird { + } + + @Override +- public boolean isCollidable() { +- return super.isCollidable(); // CraftBukkit - collidable API ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper ++ return super.isCollidable(ignoreClimbing); // CraftBukkit - collidable API // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java +index d05391290dc11440aae5f38328a0530c500ac601..d678e3164ecdb7f0c600597bcb39d1054dfbc4b2 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java +@@ -227,7 +227,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven + } + + @Override +- public boolean isCollidable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return !this.isVehicle(); + } + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +index 5eb900619951083b9a777b1645cb5495b99968ec..c0e0750adef0ae6aff7635c84f6585f06c5fc38d 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java +@@ -362,7 +362,7 @@ public class EntityArmorStand extends EntityLiving { + } + + @Override +- public boolean isCollidable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +index 25a6f53888293994a50128bcbcbb88ff141c5395..add2aef0192a3b3767c1e477145978b9702c0fb4 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +@@ -150,7 +150,7 @@ public class EntityBoat extends Entity { + } + + @Override +- public boolean isCollidable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return true; + } + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +index 7d91e6b75a8a827853b0ca8e53b8ec19e2cf1092..2e3ceab3e34f7756764b3471b13d48d1263ecba9 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +@@ -145,7 +145,7 @@ public abstract class EntityMinecartAbstract extends Entity { + } + + @Override +- public boolean isCollidable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return true; + } + diff --git a/patches/server-unmapped/0606-Added-missing-default-perms-for-commands.patch b/patches/server-unmapped/0606-Added-missing-default-perms-for-commands.patch new file mode 100644 index 0000000000..25843d00d1 --- /dev/null +++ b/patches/server-unmapped/0606-Added-missing-default-perms-for-commands.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 16 Nov 2020 12:01:52 -0800 +Subject: [PATCH] Added missing default perms for commands + + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java +index d5f4ece060b61de9ca5292d1f2411c709de5ece2..f0a57d225b81a505ff12425155ba838d8fad990c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java +@@ -31,6 +31,59 @@ public final class CommandPermissions { + DefaultPermissions.registerPermission(PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands); ++ // Paper start ++ DefaultPermissions.registerPermission(PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "ban", "Allows the user to add players to banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "ban-ip", "Allows the user to add ip address to banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "banlist", "Allows the user to display banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "pardon", "Allows the user to remove entries from the banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "replaceitem", "Allows the user to replace items in inventories", PermissionDefault.OP, commands); // Remove in 1.17 (replaced by /item) ++ DefaultPermissions.registerPermission(PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands); ++ DefaultPermissions.registerPermission(PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands); ++ // Paper end + + DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands); + diff --git a/patches/server-unmapped/0607-Add-PlayerShearBlockEvent.patch b/patches/server-unmapped/0607-Add-PlayerShearBlockEvent.patch new file mode 100644 index 0000000000..3404ded8f3 --- /dev/null +++ b/patches/server-unmapped/0607-Add-PlayerShearBlockEvent.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Thu, 27 Aug 2020 15:02:48 -0400 +Subject: [PATCH] Add PlayerShearBlockEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index d4903842aebeff3e32dbf7d3f4b670af4ebad174..7279893d599351785652279c8827fe0efbd72f12 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -262,7 +262,7 @@ public class Block extends BlockBase implements IMaterial { + + } + +- public static void a(World world, BlockPosition blockposition, ItemStack itemstack) { ++ public static void a(World world, BlockPosition blockposition, ItemStack itemstack) { dropItem(world, blockposition, itemstack); } public static void dropItem(World world, BlockPosition blockposition, ItemStack itemstack) { // Paper - OBFHELPER + if (!world.isClientSide && !itemstack.isEmpty() && world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) { + float f = 0.5F; + double d0 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; +diff --git a/src/main/java/net/minecraft/world/level/block/BlockBeehive.java b/src/main/java/net/minecraft/world/level/block/BlockBeehive.java +index ff521e64384281fc88b78bb908d19049743cf63b..828d231a963f1962d88fe170ac86590d86e1df40 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockBeehive.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockBeehive.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.level.block; + ++import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts ++ + import java.util.Iterator; + import java.util.List; + import java.util.Random; +@@ -10,6 +12,7 @@ import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; + import net.minecraft.nbt.NBTBase; + import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffects; +@@ -116,8 +119,19 @@ public class BlockBeehive extends BlockTileEntity { + + if (i >= 5) { + if (itemstack.getItem() == Items.SHEARS) { ++ // Paper start - Add PlayerShearBlockEvent ++ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), MCUtil.toBukkitBlock(world, blockposition), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (enumhand == EnumHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); ++ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3))); ++ if (!event.callEvent()) { ++ return EnumInteractionResult.PASS; ++ } ++ // Paper end + world.playSound(entityhuman, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.BLOCK_BEEHIVE_SHEAR, SoundCategory.NEUTRAL, 1.0F, 1.0F); +- a(world, blockposition); ++ // Paper start - Add PlayerShearBlockEvent ++ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { ++ dropItem(world, blockposition, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); ++ } ++ // Paper end + itemstack.damage(1, entityhuman, (entityhuman1) -> { + entityhuman1.broadcastItemBreak(enumhand); + }); +diff --git a/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java b/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java +index 130b768ac7155c2960694dfa12163e46315f7797..11a9c3e76baaa50317a3cd7d81541a3666028c16 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; + + import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.world.EnumHand; +@@ -15,6 +16,8 @@ import net.minecraft.world.level.block.state.BlockBase; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.MovingObjectPositionBlock; + ++import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts ++ + public class BlockPumpkin extends BlockStemmed { + + protected BlockPumpkin(BlockBase.Info blockbase_info) { +@@ -27,15 +30,26 @@ public class BlockPumpkin extends BlockStemmed { + + if (itemstack.getItem() == Items.SHEARS) { + if (!world.isClientSide) { ++ // Paper start - Add PlayerShearBlockEvent ++ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), MCUtil.toBukkitBlock(world, blockposition), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (enumhand == EnumHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); ++ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4))); ++ if (!event.callEvent()) { ++ return EnumInteractionResult.PASS; ++ } ++ // Paper end + EnumDirection enumdirection = movingobjectpositionblock.getDirection(); + EnumDirection enumdirection1 = enumdirection.n() == EnumDirection.EnumAxis.Y ? entityhuman.getDirection().opposite() : enumdirection; + + world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_PUMPKIN_CARVE, SoundCategory.BLOCKS, 1.0F, 1.0F); + world.setTypeAndData(blockposition, (IBlockData) Blocks.CARVED_PUMPKIN.getBlockData().set(BlockPumpkinCarved.a, enumdirection1), 11); +- EntityItem entityitem = new EntityItem(world, (double) blockposition.getX() + 0.5D + (double) enumdirection1.getAdjacentX() * 0.65D, (double) blockposition.getY() + 0.1D, (double) blockposition.getZ() + 0.5D + (double) enumdirection1.getAdjacentZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4)); ++ // Paper start - Add PlayerShearBlockEvent ++ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { ++ EntityItem entityitem = new EntityItem(world, (double) blockposition.getX() + 0.5D + (double) enumdirection1.getAdjacentX() * 0.65D, (double) blockposition.getY() + 0.1D, (double) blockposition.getZ() + 0.5D + (double) enumdirection1.getAdjacentZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); ++ // Paper end + + entityitem.setMot(0.05D * (double) enumdirection1.getAdjacentX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double) enumdirection1.getAdjacentZ() + world.random.nextDouble() * 0.02D); + world.addEntity(entityitem); ++ } // Paper - Add PlayerShearBlockEvent + itemstack.damage(1, entityhuman, (entityhuman1) -> { + entityhuman1.broadcastItemBreak(enumhand); + }); diff --git a/patches/server-unmapped/0608-Add-warning-for-servers-not-running-on-Java-16.patch b/patches/server-unmapped/0608-Add-warning-for-servers-not-running-on-Java-16.patch new file mode 100644 index 0000000000..426ebae0e9 --- /dev/null +++ b/patches/server-unmapped/0608-Add-warning-for-servers-not-running-on-Java-16.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Wed, 2 Dec 2020 21:58:45 -0800 +Subject: [PATCH] Add warning for servers not running on Java 16 + + +diff --git a/src/main/java/io/papermc/paper/util/PaperJvmChecker.java b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fdf3ff8894e5e202229d1be52fe3c92ea039ef15 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java +@@ -0,0 +1,48 @@ ++package io.papermc.paper.util; ++ ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++ ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++public class PaperJvmChecker { ++ ++ private static int getJvmVersion() { ++ String javaVersion = System.getProperty("java.version"); ++ final Matcher matcher = Pattern.compile("(?:1\\.)?(\\d+)").matcher(javaVersion); ++ if (!matcher.find()) { ++ LogManager.getLogger().warn("Failed to determine Java version; Could not parse: {}", javaVersion); ++ return -1; ++ } ++ ++ final String version = matcher.group(1); ++ try { ++ return Integer.parseInt(version); ++ } catch (final NumberFormatException e) { ++ LogManager.getLogger().warn("Failed to determine Java version; Could not parse {} from {}", version, javaVersion, e); ++ return -1; ++ } ++ } ++ ++ public static void checkJvm() { ++ if (getJvmVersion() < 16) { ++ final Logger logger = LogManager.getLogger(); ++ logger.warn("************************************************************"); ++ logger.warn("* WARNING - YOU ARE RUNNING AN OUTDATED VERSION OF JAVA."); ++ logger.warn("* PAPER WILL STOP BEING COMPATIBLE WITH THIS VERSION OF"); ++ logger.warn("* JAVA WHEN MINECRAFT 1.17 IS RELEASED."); ++ logger.warn("*"); ++ logger.warn("* Please update the version of Java you use to run Paper"); ++ logger.warn("* to at least Java 16. When Paper for Minecraft 1.17 is"); ++ logger.warn("* released support for versions of Java before 16 will"); ++ logger.warn("* be dropped."); ++ logger.warn("*"); ++ logger.warn("* Current Java version: {}", System.getProperty("java.version")); ++ logger.warn("*"); ++ logger.warn("* Check this forum post for more information: "); ++ logger.warn("* https://papermc.io/java16"); ++ logger.warn("************************************************************"); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index bea7887c1adee93cfef17d910c3df3eb60cb681c..e43fcdc806ff4e2db22d031006c96e68fc81f5fd 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -182,6 +182,7 @@ import org.bukkit.event.server.ServerLoadEvent; + + import co.aikar.timings.MinecraftTimings; // Paper + import org.spigotmc.SlackActivityAccountant; // Spigot ++import io.papermc.paper.util.PaperJvmChecker; // Paper + + public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { + +@@ -1077,6 +1078,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant +Date: Wed, 2 Dec 2020 20:17:54 -0800 +Subject: [PATCH] Set spigots verbose world setting to false by def + + +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index 6b015c1f26facb4e82d75b252164dec05731ca6c..094a934c168d232b0550c3efe722f2ebfbdf8e24 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -20,7 +20,7 @@ public class SpigotWorldConfig + + public void init() + { +- this.verbose = getBoolean( "verbose", true ); ++ this.verbose = getBoolean( "verbose", false ); // Paper + + log( "-------- World Settings For [" + worldName + "] --------" ); + SpigotConfig.readConfig( SpigotWorldConfig.class, this ); diff --git a/patches/server-unmapped/0610-Fix-curing-zombie-villager-discount-exploit.patch b/patches/server-unmapped/0610-Fix-curing-zombie-villager-discount-exploit.patch new file mode 100644 index 0000000000..889f7bbbd2 --- /dev/null +++ b/patches/server-unmapped/0610-Fix-curing-zombie-villager-discount-exploit.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 8 Dec 2020 20:14:20 -0600 +Subject: [PATCH] Fix curing zombie villager discount exploit + +This fixes the exploit used to gain absurd trading discounts with infecting +and curing a villager on repeat by simply resetting the relevant part of +the reputation when it is cured. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 7d3207a9af8360ddad228281d6aa65e1a0d24157..a3b3e3e04b7a5e3a351992e06870cc91fbd8adc8 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -717,4 +717,9 @@ public class PaperWorldConfig { + private void fixClimbingBypassingCrammingRule() { + fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); + } ++ ++ public boolean fixCuringZombieVillagerDiscountExploit = true; ++ private void fixCuringExploit() { ++ fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java +index 7d34d1157786227ac210edc1595a024ccb61a3e9..ce8a4cc9f642a740947c4e63d6eb78ad93a0fd44 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java +@@ -223,6 +223,7 @@ public class Reputation { + + } + ++ public final void removeReputationForType(ReputationType reputationType) { this.b(reputationType); } // Paper - OBFHELPER + public void b(ReputationType reputationtype) { + this.a.removeInt(reputationtype); + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index d1ddb12e8bd83d2218165340fe323c6be7bc83dd..c29f05b6fd0664345d8d09f898777a3e44f866c4 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -1014,6 +1014,15 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + @Override + public void a(ReputationEvent reputationevent, Entity entity) { + if (reputationevent == ReputationEvent.a) { ++ // Paper start - fix MC-181190 ++ if (world.paperConfig.fixCuringZombieVillagerDiscountExploit) { ++ final Reputation.a playerReputation = this.getReputation().getReputations().get(entity.getUniqueID()); ++ if (playerReputation != null) { ++ playerReputation.removeReputationForType(ReputationType.MAJOR_POSITIVE); ++ playerReputation.removeReputationForType(ReputationType.MINOR_POSITIVE); ++ } ++ } ++ // Paper end + this.by.a(entity.getUniqueID(), ReputationType.MAJOR_POSITIVE, 20); + this.by.a(entity.getUniqueID(), ReputationType.MINOR_POSITIVE, 25); + } else if (reputationevent == ReputationEvent.e) { diff --git a/patches/server-unmapped/0611-Limit-recipe-packets.patch b/patches/server-unmapped/0611-Limit-recipe-packets.patch new file mode 100644 index 0000000000..68ff3fe062 --- /dev/null +++ b/patches/server-unmapped/0611-Limit-recipe-packets.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 12 Dec 2020 23:45:28 +0000 +Subject: [PATCH] Limit recipe packets + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 7d50aded88f5b7dfebaea1aebc86231f7b5c4e25..652d87fc5d566dba8018c81676329f0e0bca471b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -334,6 +334,13 @@ public class PaperConfig { + tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); + } + ++ public static int autoRecipeIncrement = 1; ++ public static int autoRecipeLimit = 20; ++ private static void autoRecipieLimiters() { ++ autoRecipeIncrement = getInt("settings.spam-limiter.recipe-spam-increment", autoRecipeIncrement); ++ autoRecipeLimit = getInt("settings.spam-limiter.recipe-spam-limit", autoRecipeLimit); ++ } ++ + public static boolean velocitySupport; + public static boolean velocityOnlineMode; + public static byte[] velocitySecretKey; +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index cf81710e41420f6cd027231998ebf5305f23f3d5..ef38900107cc62222b303517ea4a65bff06c66b1 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1,5 +1,6 @@ + package net.minecraft.server.network; + ++import com.destroystokyo.paper.PaperConfig; + import com.google.common.collect.Lists; + import com.google.common.primitives.Doubles; + import com.google.common.primitives.Floats; +@@ -176,6 +177,7 @@ import net.minecraft.world.inventory.InventoryClickType; + import net.minecraft.world.item.crafting.IRecipe; + import net.minecraft.world.level.RayTrace; + import net.minecraft.world.phys.MovingObjectPosition; ++import org.bukkit.Bukkit; // Paper + import org.bukkit.Location; + import org.bukkit.craftbukkit.entity.CraftPlayer; + import org.bukkit.craftbukkit.event.CraftEventFactory; +@@ -234,6 +236,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + private volatile int chatThrottle; + private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); + private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits ++ private final java.util.concurrent.atomic.AtomicInteger recipeSpamPackets = new java.util.concurrent.atomic.AtomicInteger(); // Paper - auto recipe limit + // CraftBukkit end + private int j; + private final Int2ShortMap k = new Int2ShortOpenHashMap(); +@@ -382,6 +385,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + // CraftBukkit start + for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; + if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable ++ if (recipeSpamPackets.get() > 0) recipeSpamPackets.getAndDecrement(); // Paper + /* Use thread-safe field access instead + if (this.chatThrottle > 0) { + --this.chatThrottle; +@@ -2788,6 +2792,14 @@ public class PlayerConnection implements PacketListenerPlayIn { + + @Override + public void a(PacketPlayInAutoRecipe packetplayinautorecipe) { ++ // Paper start ++ if (!Bukkit.isPrimaryThread()) { ++ if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { ++ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper ++ return; ++ } ++ } ++ // Paper end + PlayerConnectionUtils.ensureMainThread(packetplayinautorecipe, this, this.player.getWorldServer()); + this.player.resetIdleTimer(); + if (!this.player.isSpectator() && this.player.activeContainer.windowId == packetplayinautorecipe.b() && this.player.activeContainer.c(this.player) && this.player.activeContainer instanceof ContainerRecipeBook) { diff --git a/patches/server-unmapped/0612-Fix-CraftSound-backwards-compatibility.patch b/patches/server-unmapped/0612-Fix-CraftSound-backwards-compatibility.patch new file mode 100644 index 0000000000..8a131ca40a --- /dev/null +++ b/patches/server-unmapped/0612-Fix-CraftSound-backwards-compatibility.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Thu, 17 Dec 2020 15:25:49 -0600 +Subject: [PATCH] Fix CraftSound backwards compatibility + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java +index e839d50c7b1cc3c9a6e463c497489ad580aceabd..84fb7d96bea3b47f2f6c6dc8d0086fee13d07ada 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java +@@ -27,4 +27,10 @@ public class CraftSound { + public static Sound getBukkit(SoundEffect soundEffect) { + return Registry.SOUNDS.get(CraftNamespacedKey.fromMinecraft(IRegistry.SOUND_EVENT.getKey(soundEffect))); + } ++ ++ // Paper start ++ public static String getSound(Sound sound) { ++ return sound.getKey().getKey(); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0613-MC-4-Fix-item-position-desync.patch b/patches/server-unmapped/0613-MC-4-Fix-item-position-desync.patch new file mode 100644 index 0000000000..abc309a820 --- /dev/null +++ b/patches/server-unmapped/0613-MC-4-Fix-item-position-desync.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 8 Dec 2020 20:24:52 -0600 +Subject: [PATCH] MC-4: Fix item position desync + +This fixes item position desync (MC-4) by running the item coordinates +through the encode/decode methods of the packet that causes the precision +loss, which forces the server to lose the same precision as the client +keeping them in sync. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 652d87fc5d566dba8018c81676329f0e0bca471b..c56e7fb18f9a56c8025eb70a524f028b5942da37 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -474,4 +474,9 @@ public class PaperConfig { + private static void trackPluginScoreboards() { + trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); + } ++ ++ public static boolean fixEntityPositionDesync = true; ++ private static void fixEntityPositionDesync() { ++ fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); ++ } + } +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java +index e80429368afced0299d9f41b97251cd6c64b1759..0eed10a6c4e0c7245f219d19ed1e2e5c94364db9 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java +@@ -19,11 +19,11 @@ public class PacketPlayOutEntity implements Packet { + protected boolean i; + + public static long a(double d0) { +- return MathHelper.d(d0 * 4096.0D); ++ return MathHelper.d(d0 * 4096.0D); // Paper - check EntityItem#setPositionRaw on update + } + + public static Vec3D a(long i, long j, long k) { +- return (new Vec3D((double) i, (double) j, (double) k)).a(2.44140625E-4D); ++ return (new Vec3D((double) i, (double) j, (double) k)).a(2.44140625E-4D); // Paper - check EntityItem#setPositionRaw on update + } + + public PacketPlayOutEntity() {} +diff --git a/src/main/java/net/minecraft/util/MathHelper.java b/src/main/java/net/minecraft/util/MathHelper.java +index caa628417bb9c1c65b037e4f3f762b08272c6d09..cc566784c7dd21cc2c44e0f351347f657e57ddcf 100644 +--- a/src/main/java/net/minecraft/util/MathHelper.java ++++ b/src/main/java/net/minecraft/util/MathHelper.java +@@ -9,7 +9,7 @@ import net.minecraft.core.BaseBlockPosition; + public class MathHelper { + + public static final float a = c(2.0F); +- private static final float[] b = (float[]) SystemUtils.a((Object) (new float[65536]), (afloat) -> { ++ private static final float[] b = (float[]) SystemUtils.a((new float[65536]), (afloat) -> { // Paper - decompile error + for (int i = 0; i < afloat.length; ++i) { + afloat[i] = (float) Math.sin((double) i * 3.141592653589793D * 2.0D / 65536.0D); + } +@@ -49,6 +49,7 @@ public class MathHelper { + return d0 < (double) i ? i - 1 : i; + } + ++ public static long floorLong(double d0) { return d(d0); } // Paper - OBFHELPER + public static long d(double d0) { + long i = (long) d0; + +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index 11e029f6f97f1dd9c32e311d1a3800f2fa54b91f..575833807ff647f30d7c2b7abcd01701c7dec85b 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -550,4 +550,16 @@ public class EntityItem extends Entity { + public Packet P() { + return new PacketPlayOutSpawnEntity(this); + } ++ ++ // Paper start - fix MC-4 ++ public void setPositionRaw(double x, double y, double z) { ++ if (com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) { ++ // encode/decode from PacketPlayOutEntity ++ x = MathHelper.floorLong(x * 4096.0D) * (1 / 4096.0D); ++ y = MathHelper.floorLong(y * 4096.0D) * (1 / 4096.0D); ++ z = MathHelper.floorLong(z * 4096.0D) * (1 / 4096.0D); ++ } ++ super.setPositionRaw(x, y, z); ++ } ++ // Paper end - fix MC-4 + } diff --git a/patches/server-unmapped/0614-Player-Chunk-Load-Unload-Events.patch b/patches/server-unmapped/0614-Player-Chunk-Load-Unload-Events.patch new file mode 100644 index 0000000000..a1a05e716f --- /dev/null +++ b/patches/server-unmapped/0614-Player-Chunk-Load-Unload-Events.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ysl3000 +Date: Mon, 5 Oct 2020 21:25:16 +0200 +Subject: [PATCH] Player Chunk Load/Unload Events + + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 78fcb90c86700ee6feef0d40753fc8d8a943777f..c0446ed3c7cc24fae2880dfba71228f5edee66d6 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -139,6 +139,8 @@ import net.minecraft.world.scores.ScoreboardScore; + import net.minecraft.world.scores.ScoreboardTeam; + import net.minecraft.world.scores.ScoreboardTeamBase; + import net.minecraft.world.scores.criteria.IScoreboardCriteria; ++import io.papermc.paper.event.packet.PlayerChunkLoadEvent; // Paper ++import io.papermc.paper.event.packet.PlayerChunkUnloadEvent; // Paper + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +@@ -2098,11 +2100,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + public void a(ChunkCoordIntPair chunkcoordintpair, Packet packet, Packet packet1) { + this.playerConnection.sendPacket(packet1); + this.playerConnection.sendPacket(packet); ++ // Paper start ++ if(PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0){ ++ new PlayerChunkLoadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); ++ } ++ // Paper end + } + + public void a(ChunkCoordIntPair chunkcoordintpair) { + if (this.isAlive()) { + this.playerConnection.sendPacket(new PacketPlayOutUnloadChunk(chunkcoordintpair.x, chunkcoordintpair.z)); ++ // Paper start ++ if(PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0){ ++ new PlayerChunkUnloadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); ++ } ++ // Paper end + } + + } diff --git a/patches/server-unmapped/0615-Optimize-Dynamic-get-Missing-Keys.patch b/patches/server-unmapped/0615-Optimize-Dynamic-get-Missing-Keys.patch new file mode 100644 index 0000000000..5a4efe035c --- /dev/null +++ b/patches/server-unmapped/0615-Optimize-Dynamic-get-Missing-Keys.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 21 Dec 2020 11:01:42 -0500 +Subject: [PATCH] Optimize Dynamic#get Missing Keys + +get was calling toString() on every NBT object that was ever asked for an optional +key from the object to build a string for the error text. + +When done on large NBT objects, this was using a ton of computation time building the +JSON representation of the NBT object. + +Now we will just skip the value when 99.9999% of the time the text is never even printed. + +diff --git a/src/main/java/com/mojang/serialization/Dynamic.java b/src/main/java/com/mojang/serialization/Dynamic.java +index a75d3db046dc985a03b4b870c91f41de1bd66bad..044facc9de9e8e582d7953d681c0c051578979c3 100644 +--- a/src/main/java/com/mojang/serialization/Dynamic.java ++++ b/src/main/java/com/mojang/serialization/Dynamic.java +@@ -17,6 +17,7 @@ import java.util.stream.Stream; + + @SuppressWarnings("unused") + public class Dynamic extends DynamicLike { ++ private static final boolean DEBUG_MISSING_KEYS = Boolean.getBoolean("Paper.debugDynamicMissingKeys"); // Paper + private final T value; + + public Dynamic(final DynamicOps ops) { +@@ -113,7 +114,7 @@ public class Dynamic extends DynamicLike { + return new OptionalDynamic<>(ops, ops.getMap(value).flatMap(m -> { + final T value = m.get(key); + if (value == null) { +- return DataResult.error("key missing: " + key + " in " + this.value); ++ return DataResult.error(DEBUG_MISSING_KEYS ? "key missing: " + key + " in " + this.value : "key missing: " + key); // Paper + } + return DataResult.success(new Dynamic<>(ops, value)); + })); diff --git a/patches/server-unmapped/0616-Expose-LivingEntity-hurt-direction.patch b/patches/server-unmapped/0616-Expose-LivingEntity-hurt-direction.patch new file mode 100644 index 0000000000..85a61eeb6e --- /dev/null +++ b/patches/server-unmapped/0616-Expose-LivingEntity-hurt-direction.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 13 Dec 2020 05:32:05 +0200 +Subject: [PATCH] Expose LivingEntity hurt direction + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index b56c801c02e4f206b72db7dd74672727104bf246..b1adb0ddfeb94de6f92f40a7e9e586e00455160d 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -163,7 +163,7 @@ public abstract class EntityLiving extends Entity { + public int am; + public int hurtTicks; + public int hurtDuration; +- public float ap; ++ public float ap; public final float getHurtDirection() { return ap; } public final void setHurtDirection(float hurtDirection) { this.ap = hurtDirection; } // Paper - OBFHELPER + public int deathTicks; + public float ar; + public float as; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 3bee6903a591bbfe312c6d7e276d7cef3dafc852..278a1c886f15b75e62bfe4c872fc779eda83c988 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -830,5 +830,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { + getHandle().receive(((CraftItem) item).getHandle(), quantity); + } ++ ++ @Override ++ public float getHurtDirection() { ++ return getHandle().getHurtDirection(); ++ } ++ ++ @Override ++ public void setHurtDirection(float hurtDirection) { ++ getHandle().setHurtDirection(hurtDirection); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server-unmapped/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch new file mode 100644 index 0000000000..a29c90ad3c --- /dev/null +++ b/patches/server-unmapped/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 24 Dec 2020 12:43:39 -0800 +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 55619fbc3fdb9393d7c47a23dc337b06ce4495d6..94476dfc0178f924fdad51b15f131ed266268776 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -271,6 +271,10 @@ public class CraftEventFactory { + return BedEnterResult.TOO_FAR_AWAY; + case NOT_SAFE: + return BedEnterResult.NOT_SAFE; ++ // Paper start ++ case OBSTRUCTED: ++ return BedEnterResult.OBSTRUCTED; ++ // Paper end + default: + return BedEnterResult.OTHER_PROBLEM; + } diff --git a/patches/server-unmapped/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server-unmapped/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch new file mode 100644 index 0000000000..3addc9816c --- /dev/null +++ b/patches/server-unmapped/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 27 Dec 2020 11:31:06 +0000 +Subject: [PATCH] Do not crash from invalid ingredient lists in + VillagerAcquireTradeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java +index a614f5d5817bf999aca0f0b50f343031c8168392..10067731e6289211cb11b2b368527a1c45603314 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java +@@ -273,7 +273,11 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP + Bukkit.getPluginManager().callEvent(event); + } + if (!event.isCancelled()) { +- merchantrecipelist.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ // Paper start ++ final CraftMerchantRecipe craftMerchantRecipe = CraftMerchantRecipe.fromBukkit(event.getRecipe()); ++ if (craftMerchantRecipe.getIngredients().isEmpty()) return; ++ merchantrecipelist.add(craftMerchantRecipe.toMinecraft()); ++ // Paper end + } + // CraftBukkit end + } diff --git a/patches/server-unmapped/0619-added-PlayerTradeEvent.patch b/patches/server-unmapped/0619-added-PlayerTradeEvent.patch new file mode 100644 index 0000000000..7ebc2efe3b --- /dev/null +++ b/patches/server-unmapped/0619-added-PlayerTradeEvent.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 2 Jul 2020 16:12:10 -0700 +Subject: [PATCH] added PlayerTradeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index da190d0b21098e327fab42e79a4ae18629bcf6e5..969e5fa3080a98850f03ba64c5662c32a8d501a6 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -93,7 +93,7 @@ import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; + public abstract class EntityInsentient extends EntityLiving { + + private static final DataWatcherObject b = DataWatcher.a(EntityInsentient.class, DataWatcherRegistry.a); +- public int e; ++ public int e;public void setAmbientSoundTime(int time) { this.e = time; } // Paper - OBFHELPER + protected int f; + protected ControllerLook lookController; + protected ControllerMove moveController; +@@ -295,6 +295,7 @@ public abstract class EntityInsentient extends EntityLiving { + this.datawatcher.register(EntityInsentient.b, (byte) 0); + } + ++ public int getAmbientSoundInterval() { return D(); } // Paper - OBFHELPER + public int D() { + return 80; + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java +index 10067731e6289211cb11b2b368527a1c45603314..49821f0f26864c35be84a4a4288857a04668fbba 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java +@@ -39,6 +39,9 @@ import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; + import org.bukkit.entity.AbstractVillager; + import org.bukkit.event.entity.VillagerAcquireTradeEvent; + // CraftBukkit end ++// Paper start ++import io.papermc.paper.event.player.PlayerTradeEvent; ++// Paper end + + public abstract class EntityVillagerAbstract extends EntityAgeable implements NPC, IMerchant { + +@@ -135,16 +138,27 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP + + @Override + public void a(MerchantRecipe merchantrecipe) { +- merchantrecipe.increaseUses(); +- this.e = -this.D(); +- this.b(merchantrecipe); ++ // Paper - moved down ++ // Paper start + if (this.tradingPlayer instanceof EntityPlayer) { +- CriterionTriggers.s.a((EntityPlayer) this.tradingPlayer, this, merchantrecipe.getSellingItem()); ++ PlayerTradeEvent event = new PlayerTradeEvent(((EntityPlayer) this.tradingPlayer).getBukkitEntity(), (AbstractVillager) this.getBukkitEntity(), merchantrecipe.asBukkit(), true, true); ++ event.callEvent(); ++ if (!event.isCancelled()) { ++ MerchantRecipe recipe = CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft(); ++ if (event.willIncreaseTradeUses()) recipe.increaseUses(); ++ this.setAmbientSoundTime(-getAmbientSoundInterval()); ++ if (event.isRewardingExp()) this.rewardTradeXp(recipe); ++ CriterionTriggers.s.a((EntityPlayer) this.tradingPlayer, this, recipe.getSellingItem()); ++ } ++ } else { ++ merchantrecipe.increaseUses(); ++ this.setAmbientSoundTime(-getAmbientSoundInterval()); ++ this.rewardTradeXp(merchantrecipe); + } +- ++ // Paper end + } + +- protected abstract void b(MerchantRecipe merchantrecipe); ++ protected abstract void b(MerchantRecipe merchantrecipe); public void rewardTradeXp(MerchantRecipe merchantrecipe) { this.b(merchantrecipe); } // Paper - OBFHELPER + + @Override + public boolean isRegularVillager() { diff --git a/patches/server-unmapped/0620-Implement-TargetHitEvent.patch b/patches/server-unmapped/0620-Implement-TargetHitEvent.patch new file mode 100644 index 0000000000..eebdc5aa97 --- /dev/null +++ b/patches/server-unmapped/0620-Implement-TargetHitEvent.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Wed, 25 Nov 2020 23:20:44 -0800 +Subject: [PATCH] Implement TargetHitEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockTarget.java b/src/main/java/net/minecraft/world/level/block/BlockTarget.java +index c336490815dc17991d3d84d8c6f0fc58571a3e3a..a9316ce8eb3d8a645f4c0e41ac668a90f584c263 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockTarget.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockTarget.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.block; + ++import io.papermc.paper.event.block.TargetHitEvent; // Paper - Need to import because 'io' class exists in nms + import java.util.Random; + import net.minecraft.advancements.CriterionTriggers; + import net.minecraft.core.BlockPosition; +@@ -34,6 +35,10 @@ public class BlockTarget extends Block { + @Override + public void a(World world, IBlockData iblockdata, MovingObjectPositionBlock movingobjectpositionblock, IProjectile iprojectile) { + int i = a((GeneratorAccess) world, iblockdata, movingobjectpositionblock, (Entity) iprojectile); ++ // Paper start ++ } ++ private static void awardTargetHitCriteria(IProjectile iprojectile, MovingObjectPositionBlock movingobjectpositionblock, int i) { ++ // Paper end + Entity entity = iprojectile.getShooter(); + + if (entity instanceof EntityPlayer) { +@@ -49,6 +54,20 @@ public class BlockTarget extends Block { + int i = a(movingobjectpositionblock, movingobjectpositionblock.getPos()); + int j = entity instanceof EntityArrow ? 20 : 8; + ++ // Paper start ++ if (entity instanceof IProjectile) { ++ final IProjectile projectile = (IProjectile) entity; ++ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(generatoraccess, movingobjectpositionblock.getBlockPosition()); ++ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(movingobjectpositionblock.getDirection()); ++ final TargetHitEvent targetHitEvent = new TargetHitEvent((org.bukkit.entity.Projectile) projectile.getBukkitEntity(), craftBlock, blockFace, i); ++ if (targetHitEvent.callEvent()) { ++ i = targetHitEvent.getSignalStrength(); ++ awardTargetHitCriteria(projectile, movingobjectpositionblock, i); ++ } else { ++ return i; ++ } ++ } ++ // Paper end + if (!generatoraccess.getBlockTickList().a(movingobjectpositionblock.getBlockPosition(), iblockdata.getBlock())) { + a(generatoraccess, iblockdata, i, movingobjectpositionblock.getBlockPosition(), j); + } diff --git a/patches/server-unmapped/0621-Additional-Block-Material-API-s.patch b/patches/server-unmapped/0621-Additional-Block-Material-API-s.patch new file mode 100644 index 0000000000..ba38cd24b0 --- /dev/null +++ b/patches/server-unmapped/0621-Additional-Block-Material-API-s.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 30 Dec 2020 19:43:01 -0500 +Subject: [PATCH] Additional Block Material API's + +Faster version for isSolid() that utilizes NMS's state for isSolid instead of the slower +process to do this in the Bukkit API + +Adds API for buildable, replaceable, burnable too. + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index fab9e1e5d63c22faceae093dc88769d203d359c6..ed1c92d9f2770f7d0503c6facebc51ddcbdf75cf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -621,6 +621,25 @@ public class CraftBlock implements Block { + return getNMS().getMaterial().isLiquid(); + } + ++ // Paper start ++ @Override ++ public boolean isBuildable() { ++ return getNMS().getMaterial().isBuildable(); ++ } ++ @Override ++ public boolean isBurnable() { ++ return getNMS().getMaterial().isBurnable(); ++ } ++ @Override ++ public boolean isReplaceable() { ++ return getNMS().getMaterial().isReplaceable(); ++ } ++ @Override ++ public boolean isSolid() { ++ return getNMS().getMaterial().isSolid(); ++ } ++ // Paper end ++ + @Override + public PistonMoveReaction getPistonMoveReaction() { + return PistonMoveReaction.getById(getNMS().getPushReaction().ordinal()); diff --git a/patches/server-unmapped/0622-Fix-harming-potion-dupe.patch b/patches/server-unmapped/0622-Fix-harming-potion-dupe.patch new file mode 100644 index 0000000000..0e9ad1d647 --- /dev/null +++ b/patches/server-unmapped/0622-Fix-harming-potion-dupe.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> +Date: Thu, 23 Jul 2020 14:25:07 -0700 +Subject: [PATCH] Fix harming potion dupe + +EntityLiving#applyInstantEffect() immediately kills the player and drops their inventory. +Before this patch, instant effects would be applied before the potion ItemStack is removed and replaced with a glass bottle. This caused the potion ItemStack to be dropped before it was supposed to be removed from the inventory. It also caused the glass bottle to be put into a dead player's inventory. +This patch makes it so that instant effects are applied after the potion ItemStack is removed, and the glass bottle is only put into the player's inventory if the player is not dead. Otherwise, the glass bottle is dropped on the ground. + +diff --git a/src/main/java/net/minecraft/world/item/ItemPotion.java b/src/main/java/net/minecraft/world/item/ItemPotion.java +index b197fe561ab735e80d8bf29ac16eacfaf3fc2d21..ca2f8d522d7f2305f161cb4aa611226355ea5789 100644 +--- a/src/main/java/net/minecraft/world/item/ItemPotion.java ++++ b/src/main/java/net/minecraft/world/item/ItemPotion.java +@@ -15,6 +15,7 @@ import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.alchemy.PotionRegistry; + import net.minecraft.world.item.alchemy.PotionUtil; + import net.minecraft.world.item.alchemy.Potions; ++import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.World; + + public class ItemPotion extends Item { +@@ -36,6 +37,7 @@ public class ItemPotion extends Item { + CriterionTriggers.z.a((EntityPlayer) entityhuman, itemstack); + } + ++ List instantLater = new java.util.ArrayList<>(); // Paper - Fix harming potion dupe + if (!world.isClientSide) { + List list = PotionUtil.getEffects(itemstack); + Iterator iterator = list.iterator(); +@@ -44,7 +46,7 @@ public class ItemPotion extends Item { + MobEffect mobeffect = (MobEffect) iterator.next(); + + if (mobeffect.getMobEffect().isInstant()) { +- mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, entityliving, mobeffect.getAmplifier(), 1.0D); ++ instantLater.add(mobeffect); // Paper - Fix harming potion dupe + } else { + entityliving.addEffect(new MobEffect(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit + } +@@ -58,7 +60,20 @@ public class ItemPotion extends Item { + } + } + ++ // Paper start - Fix harming potion dupe ++ for (MobEffect mobeffect : instantLater) { ++ mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, entityliving, mobeffect.getAmplifier(), 1.0D); ++ } ++ // Paper end ++ + if (entityhuman == null || !entityhuman.abilities.canInstantlyBuild) { ++ // Paper start - Fix harming potion dupe ++ if (entityliving.getHealth() <= 0 && !entityliving.world.getGameRules().getBoolean(GameRules.KEEP_INVENTORY)) { ++ entityliving.dropItem(new ItemStack(Items.GLASS_BOTTLE), 0); ++ return ItemStack.NULL_ITEM; ++ } ++ // Paper end ++ + if (itemstack.isEmpty()) { + return new ItemStack(Items.GLASS_BOTTLE); + } diff --git a/patches/server-unmapped/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/patches/server-unmapped/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch new file mode 100644 index 0000000000..02569905c0 --- /dev/null +++ b/patches/server-unmapped/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Thu, 31 Dec 2020 12:48:19 +1000 +Subject: [PATCH] Implement API to get Material from Boats and Minecarts + + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +index add2aef0192a3b3767c1e477145978b9702c0fb4..2609b83573e0e8532e6c4c36d4f475bf0da6a354 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +@@ -260,6 +260,7 @@ public class EntityBoat extends Entity { + + } + ++ public final Item getBoatItem() { return this.g(); } // Paper - OBFHELPER + public Item g() { + switch (this.getType()) { + case OAK: +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java +index c7a459c0c860724ef1890b8fb9a59a5508b3f6d6..16799dc565c5ca42d1fdb3122594d9dae21c74e0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java +@@ -1,8 +1,10 @@ + package org.bukkit.craftbukkit.entity; + + import net.minecraft.world.entity.vehicle.EntityBoat; ++import org.bukkit.Material; // Paper + import org.bukkit.TreeSpecies; + import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper + import org.bukkit.entity.Boat; + import org.bukkit.entity.EntityType; + +@@ -66,6 +68,13 @@ public class CraftBoat extends CraftVehicle implements Boat { + getHandle().landBoats = workOnLand; + } + ++ // Paper start ++ @Override ++ public Material getBoatMaterial() { ++ return CraftMagicNumbers.getMaterial(getHandle().getBoatItem()); ++ } ++ // Paper end ++ + @Override + public EntityBoat getHandle() { + return (EntityBoat) entity; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java +index 69415f5a838345826fa5cf1d855e057794520f2c..e5ebb80a44da775df6f3d5a9db5cf58295e2e960 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java +@@ -1,8 +1,10 @@ + package org.bukkit.craftbukkit.entity; + + import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; ++import net.minecraft.world.item.Items; // Paper + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.IBlockData; ++import org.bukkit.Material; // Paper + import org.bukkit.block.data.BlockData; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.block.data.CraftBlockData; +@@ -68,6 +70,38 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart { + getHandle().setDerailedVelocityMod(derailed); + } + ++ // Paper start ++ @Override ++ public Material getMinecartMaterial() { ++ net.minecraft.world.item.Item minecartItem; ++ switch (getHandle().getMinecartType()) { ++ case CHEST: ++ minecartItem = Items.CHEST_MINECART; ++ break; ++ case FURNACE: ++ minecartItem = Items.FURNACE_MINECART; ++ break; ++ case TNT: ++ minecartItem = Items.TNT_MINECART; ++ break; ++ case HOPPER: ++ minecartItem = Items.HOPPER_MINECART; ++ break; ++ case COMMAND_BLOCK: ++ minecartItem = Items.COMMAND_BLOCK_MINECART; ++ break; ++ case RIDEABLE: ++ case SPAWNER: ++ minecartItem = Items.MINECART; ++ break; ++ default: ++ throw new IllegalStateException("Unexpected value: " + getHandle().getMinecartType()); ++ } ++ ++ return CraftMagicNumbers.getMaterial(minecartItem); ++ } ++ // Paper end ++ + @Override + public EntityMinecartAbstract getHandle() { + return (EntityMinecartAbstract) entity; diff --git a/patches/server-unmapped/0624-Optimized-tick-ready-check.patch b/patches/server-unmapped/0624-Optimized-tick-ready-check.patch new file mode 100644 index 0000000000..522f5db773 --- /dev/null +++ b/patches/server-unmapped/0624-Optimized-tick-ready-check.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas +Date: Sun, 27 Dec 2020 17:19:51 +0100 +Subject: [PATCH] Optimized tick ready check + + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index f40be366ebc5f98b417b677565fa89d3f817f3fb..78dcba08d6d796d5d97c8304bf1f1e7d1e650d5d 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -854,13 +854,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + if (!tileentity.isRemoved() && tileentity.hasWorld()) { + BlockPosition blockposition = tileentity.getPosition(); + +- if (this.getChunkProvider().a(blockposition) && this.getWorldBorder().a(blockposition)) { ++ Chunk chunk; PlayerChunk playerChunk; if ((chunk = tileentity.getCurrentChunk()) != null && (playerChunk = chunk.playerChunk) != null && playerChunk.isTickingReady() && this.getWorldBorder().isInBounds(blockposition)) { // Paper - optimized tick ready check by inlining ChunkProviderServer.a(BlockPosition). Chunk lookup is no longer required and we can use the PlayerChunk directly available through the tile entity + try { + gameprofilerfiller.a(() -> { + return String.valueOf(TileEntityTypes.a(tileentity.getTileType())); + }); + tileentity.tickTimer.startTiming(); // Spigot +- if (tileentity.getTileType().isValidBlock(this.getType(blockposition).getBlock())) { ++ if (tileentity.getTileType().isValidBlock(chunk.getType(blockposition).getBlock())) { // Paper - reuse the chunk from above, do not look it up again + ((ITickable) tileentity).tick(); + } else { + tileentity.w(); +@@ -893,9 +893,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + this.tileEntityListTick.remove(tileTickPosition--); + // Spigot end + //this.tileEntityList.remove(tileentity); // Paper - remove unused list +- if (this.isLoaded(tileentity.getPosition())) { +- this.getChunkAtWorldCoords(tileentity.getPosition()).removeTileEntity(tileentity.getPosition()); ++ // Paper - prevent double chunk lookups ++ Chunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getPosition())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again ++ chunk.removeTileEntity(tileentity.getPosition()); + } ++ // Paper end + } + } + +@@ -914,8 +916,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + } + // CraftBukkit end */ + +- if (this.isLoaded(tileentity1.getPosition())) { +- Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); ++ Chunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity1.getPosition())) != null) { // Paper - inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again ++ // Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); // Paper - already computed above + IBlockData iblockdata = chunk.getType(tileentity1.getPosition()); + + chunk.setTileEntity(tileentity1.getPosition(), tileentity1); diff --git a/patches/server-unmapped/0625-Cache-burn-durations.patch b/patches/server-unmapped/0625-Cache-burn-durations.patch new file mode 100644 index 0000000000..1c9afd6350 --- /dev/null +++ b/patches/server-unmapped/0625-Cache-burn-durations.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas +Date: Sun, 27 Dec 2020 16:47:00 +0100 +Subject: [PATCH] Cache burn durations + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +index e630e8d3e115d2a0177849ad8258a2304b9d3e9d..54316a8079b4331a48cac3c43f3f8c506a4af091 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.block.entity; + ++import com.google.common.collect.ImmutableMap; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; +@@ -113,7 +114,15 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + this.c = recipes; + } + ++ private static Map cachedBurnDurations = null; // Paper - cache burn durations ++ ++ public static Map getBurnDurations() { return f(); } // Paper - OBFHELPER + public static Map f() { ++ // Paper start - cache burn durations ++ if(cachedBurnDurations != null) { ++ return cachedBurnDurations; ++ } ++ // Paper end + Map map = Maps.newLinkedHashMap(); + + a(map, (IMaterial) Items.LAVA_BUCKET, 20000); +@@ -176,7 +185,10 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + a(map, (IMaterial) Blocks.FLETCHING_TABLE, 300); + a(map, (IMaterial) Blocks.SMITHING_TABLE, 300); + a(map, (IMaterial) Blocks.COMPOSTER, 300); +- return map; ++ // Paper start - cache burn durations ++ cachedBurnDurations = ImmutableMap.copyOf(map); ++ return cachedBurnDurations; ++ // Paper end + } + + // CraftBukkit start - add fields and methods +@@ -430,7 +442,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + } else { + Item item = itemstack.getItem(); + +- return (Integer) f().getOrDefault(item, 0); ++ return getBurnDurations().getOrDefault(item, 0); // Paper - cache burn durations + } + } + +@@ -443,7 +455,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + // Paper end + + public static boolean isFuel(ItemStack itemstack) { +- return f().containsKey(itemstack.getItem()); ++ return getBurnDurations().containsKey(itemstack.getItem()); // Paper - cache burn durations + } + + @Override diff --git a/patches/server-unmapped/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server-unmapped/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch new file mode 100644 index 0000000000..115f473843 --- /dev/null +++ b/patches/server-unmapped/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BrodyBeckwith +Date: Fri, 9 Oct 2020 20:30:12 -0400 +Subject: [PATCH] Allow disabling mob spawner spawn egg transformation + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index a3b3e3e04b7a5e3a351992e06870cc91fbd8adc8..b48067c71f9de18ba40e970e2832f6245984a218 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -722,4 +722,9 @@ public class PaperWorldConfig { + private void fixCuringExploit() { + fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); + } ++ ++ public boolean disableMobSpawnerSpawnEggTransformation = false; ++ private void disableMobSpawnerSpawnEggTransformation() { ++ disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); ++ } + } +diff --git a/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java b/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java +index c170d2141504d80624e3c1a7f78f7968ea8a80ee..4d965e504a40eb52777575df839856c825a0900a 100644 +--- a/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java ++++ b/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java +@@ -60,7 +60,7 @@ public class ItemMonsterEgg extends Item { + EnumDirection enumdirection = itemactioncontext.getClickedFace(); + IBlockData iblockdata = world.getType(blockposition); + +- if (iblockdata.a(Blocks.SPAWNER)) { ++ if (!world.paperConfig.disableMobSpawnerSpawnEggTransformation && iblockdata.a(Blocks.SPAWNER)) { // Paper + TileEntity tileentity = world.getTileEntity(blockposition); + + if (tileentity instanceof TileEntityMobSpawner) { diff --git a/patches/server-unmapped/0627-Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server-unmapped/0627-Implement-PlayerFlowerPotManipulateEvent.patch new file mode 100644 index 0000000000..43503c58f0 --- /dev/null +++ b/patches/server-unmapped/0627-Implement-PlayerFlowerPotManipulateEvent.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MisterVector +Date: Tue, 13 Aug 2019 19:45:06 -0700 +Subject: [PATCH] Implement PlayerFlowerPotManipulateEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java b/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java +index a61d1ffeebfd00a5fcd5faf95200b0640da8ea82..18fefad056d92a6fa498ab3764cd391446c26b60 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java +@@ -21,6 +21,8 @@ import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++import io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent; // Paper ++ + public class BlockFlowerPot extends Block { + + private static final Map b = Maps.newHashMap(); +@@ -52,6 +54,27 @@ public class BlockFlowerPot extends Block { + boolean flag1 = this.c == Blocks.AIR; + + if (flag != flag1) { ++ // Paper start ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) entityhuman.getBukkitEntity(); ++ boolean placing = flag1; ++ org.bukkit.block.Block bukkitblock = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition); ++ org.bukkit.inventory.ItemStack bukkititemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack); ++ org.bukkit.Material mat = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(c); ++ org.bukkit.inventory.ItemStack bukkititemstack1 = new org.bukkit.inventory.ItemStack(mat, 1); ++ org.bukkit.inventory.ItemStack whichitem = placing ? bukkititemstack : bukkititemstack1; ++ ++ PlayerFlowerPotManipulateEvent event = new PlayerFlowerPotManipulateEvent(player, bukkitblock, whichitem, placing); ++ player.getServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ // Update client ++ player.sendBlockChange(bukkitblock.getLocation(), bukkitblock.getBlockData()); ++ player.updateInventory(); ++ ++ return EnumInteractionResult.PASS; ++ } ++ // Paper end ++ + if (flag1) { + world.setTypeAndData(blockposition, block.getBlockData(), 3); + entityhuman.a(StatisticList.POT_FLOWER); diff --git a/patches/server-unmapped/0628-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server-unmapped/0628-Fix-interact-event-not-being-called-in-adventure.patch new file mode 100644 index 0000000000..011f84bd00 --- /dev/null +++ b/patches/server-unmapped/0628-Fix-interact-event-not-being-called-in-adventure.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheMolkaPL +Date: Sun, 21 Jun 2020 17:21:46 +0200 +Subject: [PATCH] Fix interact event not being called in adventure + +Call PlayerInteractEvent when left-clicking on a block in adventure mode + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index ef38900107cc62222b303517ea4a65bff06c66b1..c68e56562076a2ca3d099a1112404f11a5473397 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1703,7 +1703,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + IChatMutableComponent ichatmutablecomponent = (new ChatMessage("build.tooHigh", new Object[]{this.minecraftServer.getMaxBuildHeight()})).a(EnumChatFormat.RED); + + this.player.playerConnection.sendPacket(new PacketPlayOutChat(ichatmutablecomponent, ChatMessageType.GAME_INFO, SystemUtils.b)); +- } else if (enuminteractionresult.b()) { ++ } else if (enuminteractionresult.b() && !this.player.playerInteractManager.interactResult) { + this.player.swingHand(enumhand, true); + } + } +@@ -2204,7 +2204,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + Vec3D vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); + MovingObjectPosition movingobjectposition = this.player.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.OUTLINE, RayTrace.FluidCollisionOption.NONE, player)); + +- if (movingobjectposition == null || movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.BLOCK) { ++ if (movingobjectposition == null || movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.BLOCK || this.player.playerInteractManager.getGameMode() == EnumGamemode.ADVENTURE) { // Paper - call PlayerInteractEvent when left-clicking on a block in adventure mode + CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.inventory.getItemInHand(), EnumHand.MAIN_HAND); + } + diff --git a/patches/server-unmapped/0629-Zombie-API-breaking-doors.patch b/patches/server-unmapped/0629-Zombie-API-breaking-doors.patch new file mode 100644 index 0000000000..da61412550 --- /dev/null +++ b/patches/server-unmapped/0629-Zombie-API-breaking-doors.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 18 Nov 2020 11:32:46 -0800 +Subject: [PATCH] Zombie API - breaking doors + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index 87acbdee03edf8bc35f4b3bcb9b82855ed4a3c33..5b0c79d752d616e5824393968136f3844ce52c22 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -140,10 +140,12 @@ public class EntityZombie extends EntityMonster { + return (Boolean) this.getDataWatcher().get(EntityZombie.DROWN_CONVERTING); + } + ++ public boolean canBreakDoors() { return this.eU(); } // Paper - OBFHELPER + public boolean eU() { + return this.bs; + } + ++ public void setCanBreakDoors(boolean canBreakDoors) { this.u(canBreakDoors); } // Paper - OBFHELPER + public void u(boolean flag) { + if (this.eK() && PathfinderGoalUtil.a(this)) { + if (this.bs != flag) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +index 42d98d798bb8fe2d3c7cc2bfcf2ec38d97d99bd2..e1589ef97222f5e29a3628db354d4406a443a613 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +@@ -129,6 +129,16 @@ public class CraftZombie extends CraftMonster implements Zombie { + public void setShouldBurnInDay(boolean shouldBurnInDay) { + getHandle().setShouldBurnInDay(shouldBurnInDay); + } ++ ++ @Override ++ public boolean canBreakDoors() { ++ return getHandle().canBreakDoors(); ++ } ++ ++ @Override ++ public void setCanBreakDoors(boolean canBreakDoors) { ++ getHandle().setCanBreakDoors(canBreakDoors); ++ } + // Paper end + + @Override diff --git a/patches/server-unmapped/0630-Fix-nerfed-slime-when-splitting.patch b/patches/server-unmapped/0630-Fix-nerfed-slime-when-splitting.patch new file mode 100644 index 0000000000..875960eb0b --- /dev/null +++ b/patches/server-unmapped/0630-Fix-nerfed-slime-when-splitting.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 24 Aug 2020 08:39:06 -0700 +Subject: [PATCH] Fix nerfed slime when splitting + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java +index 40e39e382092b1a8f831da0cea1557a781c98600..0af0b232ff1b6f1d58cf3fb543d32bd108be0af7 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java +@@ -246,6 +246,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { + entityslime.setPersistent(); + } + ++ entityslime.aware = this.aware; // Paper + entityslime.setCustomName(ichatbasecomponent); + entityslime.setNoAI(flag); + entityslime.setInvulnerable(this.isInvulnerable()); diff --git a/patches/server-unmapped/0631-Add-EntityLoadCrossbowEvent.patch b/patches/server-unmapped/0631-Add-EntityLoadCrossbowEvent.patch new file mode 100644 index 0000000000..5e9ae2150b --- /dev/null +++ b/patches/server-unmapped/0631-Add-EntityLoadCrossbowEvent.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 7 Oct 2020 12:04:01 -0400 +Subject: [PATCH] Add EntityLoadCrossbowEvent + + +diff --git a/src/main/java/net/minecraft/world/item/ItemCrossbow.java b/src/main/java/net/minecraft/world/item/ItemCrossbow.java +index ec6c0836f02e7ac5b72fd224a3022a844dce55cb..4e1e819c8535e8a6b9aa5f76afe568ea171b939f 100644 +--- a/src/main/java/net/minecraft/world/item/ItemCrossbow.java ++++ b/src/main/java/net/minecraft/world/item/ItemCrossbow.java +@@ -3,6 +3,8 @@ package net.minecraft.world.item; + import com.google.common.collect.Lists; + import com.mojang.math.Quaternion; + import com.mojang.math.Vector3fa; ++import org.bukkit.inventory.EquipmentSlot; // Paper ++import io.papermc.paper.event.entity.EntityLoadCrossbowEvent; // Paper - EntityLoadCrossbowEvent namespace conflicts + import java.util.List; + import java.util.Random; + import java.util.function.Predicate; +@@ -73,7 +75,11 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable + int j = this.e_(itemstack) - i; + float f = a(j, itemstack); + +- if (f >= 1.0F && !d(itemstack) && a(entityliving, itemstack)) { ++ // Paper start - EntityLoadCrossbowEvent ++ if (f >= 1.0F && !d(itemstack) /*&& a(entityliving, itemstack)*/) { ++ final EntityLoadCrossbowEvent event = new EntityLoadCrossbowEvent(entityliving.getBukkitLivingEntity(), itemstack.asBukkitMirror(), entityliving.getRaisedHand() == EnumHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND); ++ if (!event.callEvent() || !attemptProjectileLoad(entityliving, itemstack, event.shouldConsumeItem())) return; ++ // Paper end + a(itemstack, true); + SoundCategory soundcategory = entityliving instanceof EntityHuman ? SoundCategory.PLAYERS : SoundCategory.HOSTILE; + +@@ -82,10 +88,13 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable + + } + +- private static boolean a(EntityLiving entityliving, ItemStack itemstack) { ++ private static boolean attemptProjectileLoad(EntityLiving ent, ItemStack bow) { return a(ent, bow); } // Paper - EntityLoadCrossbowEvent - OBFHELPER ++ private static boolean attemptProjectileLoad(EntityLiving ent, ItemStack bow, boolean consume) { return a(ent, bow, consume); } // Paper - EntityLoadCrossbowEvent - OBFHELPER ++ private static boolean a(EntityLiving entityliving, ItemStack itemstack) { return a(entityliving, itemstack, true); };// Paper - add consume ++ private static boolean a(EntityLiving entityliving, ItemStack itemstack, boolean consume) { // Paper - add consume + int i = EnchantmentManager.getEnchantmentLevel(Enchantments.MULTISHOT, itemstack); + int j = i == 0 ? 1 : 3; +- boolean flag = entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.canInstantlyBuild; ++ boolean flag = !consume || entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.canInstantlyBuild; // Paper - add consme + ItemStack itemstack1 = entityliving.f(itemstack); + ItemStack itemstack2 = itemstack1.cloneItemStack(); + diff --git a/patches/server-unmapped/0632-Guardian-beam-workaround.patch b/patches/server-unmapped/0632-Guardian-beam-workaround.patch new file mode 100644 index 0000000000..4439204159 --- /dev/null +++ b/patches/server-unmapped/0632-Guardian-beam-workaround.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gabscap +Date: Sat, 19 Mar 2016 22:25:11 +0100 +Subject: [PATCH] Guardian beam workaround + +This patch is a workaround for MC-165595 + +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java +index a69e60a8934493f6786ce3d425f6dccb6e4befdd..3086ee023685781d94e2fb99fc8dff5264f01165 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java +@@ -6,7 +6,7 @@ import net.minecraft.network.protocol.Packet; + + public class PacketPlayOutUpdateTime implements Packet { + +- private long a; ++ private long a; private final void setWorldAge(final long age) { this.a = age; } private final long getWorldAge() { return this.a; } // Paper - OBFHELPER + private long b; + + public PacketPlayOutUpdateTime() {} +@@ -21,6 +21,9 @@ public class PacketPlayOutUpdateTime implements Packet { + } + } + ++ // Paper start ++ this.setWorldAge(this.getWorldAge() % 192000); ++ // Paper end + } + + @Override diff --git a/patches/server-unmapped/0633-Added-WorldGameRuleChangeEvent.patch b/patches/server-unmapped/0633-Added-WorldGameRuleChangeEvent.patch new file mode 100644 index 0000000000..6eec095679 --- /dev/null +++ b/patches/server-unmapped/0633-Added-WorldGameRuleChangeEvent.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 20 Dec 2020 16:41:44 -0800 +Subject: [PATCH] Added WorldGameRuleChangeEvent + + +diff --git a/src/main/java/net/minecraft/server/commands/CommandGamerule.java b/src/main/java/net/minecraft/server/commands/CommandGamerule.java +index 5b5c5d1299c267f620f5c59873b261a7b7e382a9..feebe4812ff7aec17a50cb5f2789fe88e10a5032 100644 +--- a/src/main/java/net/minecraft/server/commands/CommandGamerule.java ++++ b/src/main/java/net/minecraft/server/commands/CommandGamerule.java +@@ -31,7 +31,7 @@ public class CommandGamerule { + CommandListenerWrapper commandlistenerwrapper = (CommandListenerWrapper) commandcontext.getSource(); + T t0 = commandlistenerwrapper.getWorld().getGameRules().get(gamerules_gamerulekey); // CraftBukkit + +- t0.b(commandcontext, "value"); ++ t0.setValue(commandcontext, "value", gamerules_gamerulekey); // Paper + commandlistenerwrapper.sendMessage(new ChatMessage("commands.gamerule.set", new Object[]{gamerules_gamerulekey.a(), t0.toString()}), true); + return t0.getIntValue(); + } +diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java +index 276c28170b2a177dab6b2a0d5425044cd9f8df22..3783f3a83e3e70d77cf0fa1021f62a89c5950af5 100644 +--- a/src/main/java/net/minecraft/world/level/GameRules.java ++++ b/src/main/java/net/minecraft/world/level/GameRules.java +@@ -25,6 +25,7 @@ import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.EntityPlayer; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import io.papermc.paper.event.world.WorldGameRuleChangeEvent; // Paper + + public class GameRules { + +@@ -177,8 +178,11 @@ public class GameRules { + } + + @Override +- protected void a(CommandContext commandcontext, String s) { +- this.b = BoolArgumentType.getBool(commandcontext, s); ++ protected void a(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { // Paper start ++ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(commandcontext, s))); ++ if (!event.callEvent()) return; ++ this.b = Boolean.parseBoolean(event.getValue()); ++ // Paper end + } + + public boolean a() { +@@ -237,8 +241,11 @@ public class GameRules { + } + + @Override +- protected void a(CommandContext commandcontext, String s) { +- this.b = IntegerArgumentType.getInteger(commandcontext, s); ++ protected void a(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { // Paper start ++ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(commandcontext, s))); ++ if (!event.callEvent()) return; ++ this.b = Integer.parseInt(event.getValue()); ++ // Paper end + } + + public int a() { +@@ -291,10 +298,12 @@ public class GameRules { + this.a = gamerules_gameruledefinition; + } + +- protected abstract void a(CommandContext commandcontext, String s); ++ protected void updateValue(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { this.a(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER ++ protected abstract void a(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey); // Paper + +- public void b(CommandContext commandcontext, String s) { +- this.a(commandcontext, s); ++ public void setValue(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { this.b(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER ++ public void b(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { // Paper ++ this.updateValue(commandcontext, s, gameRuleKey); // Paper + this.onChange(((CommandListenerWrapper) commandcontext.getSource()).getServer()); + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 776733a4a913d232126b48f2d0eadbe27aa84e59..05a7f5f61330bd52705640345524cdedbf105285 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2363,8 +2363,13 @@ public class CraftWorld implements World { + + if (!isGameRule(rule)) return false; + ++ // Paper start ++ GameRule gameRule = GameRule.getByName(rule); ++ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, gameRule, value); ++ if (!event.callEvent()) return false; ++ // Paper end + GameRules.GameRuleValue handle = getHandle().getGameRules().get(getGameRulesNMS().get(rule)); +- handle.setValue(value); ++ handle.setValue(event.getValue().toString()); // Paper + handle.onChange(getHandle().getMinecraftServer()); + return true; + } +@@ -2399,8 +2404,12 @@ public class CraftWorld implements World { + + if (!isGameRule(rule.getName())) return false; + ++ // Paper start ++ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, rule, String.valueOf(newValue)); ++ if (!event.callEvent()) return false; ++ // Paper end + GameRules.GameRuleValue handle = getHandle().getGameRules().get(getGameRulesNMS().get(rule.getName())); +- handle.setValue(newValue.toString()); ++ handle.setValue(event.getValue().toString()); // Paper + handle.onChange(getHandle().getMinecraftServer()); + return true; + } diff --git a/patches/server-unmapped/0634-Added-ServerResourcesReloadedEvent.patch b/patches/server-unmapped/0634-Added-ServerResourcesReloadedEvent.patch new file mode 100644 index 0000000000..7d280a01e0 --- /dev/null +++ b/patches/server-unmapped/0634-Added-ServerResourcesReloadedEvent.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 2 Dec 2020 20:04:01 -0800 +Subject: [PATCH] Added ServerResourcesReloadedEvent + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index e43fcdc806ff4e2db22d031006c96e68fc81f5fd..fe02a46df9c652acf4a4bc0ed194522f400cda34 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2,9 +2,6 @@ package net.minecraft.server; + + import com.google.common.base.Splitter; + import com.google.common.collect.ImmutableList; +-import co.aikar.timings.Timings; +-import com.destroystokyo.paper.event.server.PaperServerListPingEvent; +-import com.google.common.base.Stopwatch; + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; +@@ -183,6 +180,7 @@ import org.bukkit.event.server.ServerLoadEvent; + import co.aikar.timings.MinecraftTimings; // Paper + import org.spigotmc.SlackActivityAccountant; // Spigot + import io.papermc.paper.util.PaperJvmChecker; // Paper ++import io.papermc.paper.event.server.ServerResourcesReloadedEvent; // Paper + + public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { + +@@ -1936,7 +1934,13 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant a(Collection collection) { ++ return this.reloadServerResources(collection, ServerResourcesReloadedEvent.Cause.PLUGIN); ++ } ++ public CompletableFuture reloadServerResources(Collection collection, ServerResourcesReloadedEvent.Cause cause) { ++ // Paper end + CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { + Stream stream = collection.stream(); // CraftBukkit - decompile error + ResourcePackRepository resourcepackrepository = this.resourcePackRepository; +@@ -1952,6 +1956,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant collection, CommandListenerWrapper commandlistenerwrapper) { +- commandlistenerwrapper.getServer().a(collection).exceptionally((throwable) -> { ++ commandlistenerwrapper.getServer().reloadServerResources(collection, ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally((throwable) -> { // Paper + CommandReload.LOGGER.warn("Failed to execute reload", throwable); + commandlistenerwrapper.sendFailureMessage(new ChatMessage("commands.reload.failure")); + return null; +@@ -48,7 +49,7 @@ public class CommandReload { + SaveData savedata = minecraftserver.getSaveData(); + Collection collection = resourcepackrepository.d(); + Collection collection1 = a(resourcepackrepository, savedata, collection); +- minecraftserver.a(collection1); ++ minecraftserver.reloadServerResources(collection1, ServerResourcesReloadedEvent.Cause.PLUGIN); // Paper + } + // CraftBukkit end + diff --git a/patches/server-unmapped/0635-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server-unmapped/0635-Added-world-settings-for-mobs-picking-up-loot.patch new file mode 100644 index 0000000000..10e2cd6329 --- /dev/null +++ b/patches/server-unmapped/0635-Added-world-settings-for-mobs-picking-up-loot.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 28 Nov 2020 18:43:52 -0800 +Subject: [PATCH] Added world settings for mobs picking up loot + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index b48067c71f9de18ba40e970e2832f6245984a218..23a23e2ea133ce81d3dedc4ffd17435a995497ef 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -363,6 +363,14 @@ public class PaperWorldConfig { + log("Creeper lingering effect: " + disableCreeperLingeringEffect); + } + ++ public boolean zombiesAlwaysCanPickUpLoot; ++ public boolean skeletonsAlwaysCanPickUpLoot; ++ private void setMobsAlwaysCanPickUpLoot() { ++ zombiesAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.zombies", false); ++ skeletonsAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.skeletons", false); ++ log("Zombies can always pick up loot: " + zombiesAlwaysCanPickUpLoot + ". Skeletons can always pick up loot: " + skeletonsAlwaysCanPickUpLoot + "."); ++ } ++ + public int expMergeMaxValue; + private void expMergeMaxValue() { + expMergeMaxValue = getInt("experience-merge-max-value", -1); +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java +index 4dca5ea9127c15b2739483b2ad74a5296a6b96ad..06d50b22ede102556fdb3e2a6f1424f7ff13f120 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java +@@ -149,7 +149,7 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR + this.a(difficultydamagescaler); + this.b(difficultydamagescaler); + this.eL(); +- this.setCanPickupLoot(this.random.nextFloat() < 0.55F * difficultydamagescaler.d()); ++ this.setCanPickupLoot(this.world.paperConfig.skeletonsAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * difficultydamagescaler.d()); // Paper + if (this.getEquipment(EnumItemSlot.HEAD).isEmpty()) { + LocalDate localdate = LocalDate.now(); + int i = localdate.get(ChronoField.DAY_OF_MONTH); +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index 5b0c79d752d616e5824393968136f3844ce52c22..fb98609a38d665659076b8949b59eaf084408a17 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -497,7 +497,7 @@ public class EntityZombie extends EntityMonster { + Object object = super.prepare(worldaccess, difficultydamagescaler, enummobspawn, groupdataentity, nbttagcompound); + float f = difficultydamagescaler.d(); + +- this.setCanPickupLoot(this.random.nextFloat() < 0.55F * f); ++ this.setCanPickupLoot(this.world.paperConfig.zombiesAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * f); // Paper + if (object == null) { + object = new EntityZombie.GroupDataZombie(a(worldaccess.getRandom()), true); + } diff --git a/patches/server-unmapped/0636-Implemented-BlockFailedDispenseEvent.patch b/patches/server-unmapped/0636-Implemented-BlockFailedDispenseEvent.patch new file mode 100644 index 0000000000..c2620d5836 --- /dev/null +++ b/patches/server-unmapped/0636-Implemented-BlockFailedDispenseEvent.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheViperShow <29604693+TheViperShow@users.noreply.github.com> +Date: Wed, 22 Apr 2020 09:40:38 +0200 +Subject: [PATCH] Implemented BlockFailedDispenseEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java +index 0ab6186ba3cfd7f7115c71b3982f46c5d2c921c0..966051ab3e720e5b3f0fb9ab852c8908c5f23f3b 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java +@@ -81,6 +81,7 @@ public class BlockDispenser extends BlockTileEntity { + int i = tileentitydispenser.h(); + + if (i < 0) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, blockposition)) // Paper - BlockFailedDispenseEvent is called here + worldserver.triggerEffect(1001, blockposition, 0); + } else { + ItemStack itemstack = tileentitydispenser.getItem(i); +diff --git a/src/main/java/net/minecraft/world/level/block/BlockDropper.java b/src/main/java/net/minecraft/world/level/block/BlockDropper.java +index ccab4714bf5a6be8afd92430874fd6f881d4f92f..223cc0ba06cf4b007049880daad881e55ac4e448 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockDropper.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockDropper.java +@@ -47,6 +47,7 @@ public class BlockDropper extends BlockDispenser { + int i = tileentitydispenser.h(); + + if (i < 0) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, blockposition)) // Paper - BlockFailedDispenseEvent is called here + worldserver.triggerEffect(1001, blockposition, 0); + } 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 94476dfc0178f924fdad51b15f131ed266268776..a7f8e08dcbc102041891e51cbe9c984d6f43747b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -4,6 +4,7 @@ import com.google.common.base.Function; + import com.google.common.base.Functions; + import com.google.common.collect.Lists; + import com.mojang.datafixers.util.Either; ++import io.papermc.paper.event.block.BlockFailedDispenseEvent; + import java.net.InetAddress; + import java.util.ArrayList; + import java.util.Collections; +@@ -123,7 +124,6 @@ import org.bukkit.entity.ThrownPotion; + import org.bukkit.entity.Vehicle; + import org.bukkit.entity.Villager; + import org.bukkit.entity.Villager.Profession; +-import org.bukkit.entity.ExperienceOrb; // Paper + import org.bukkit.event.Cancellable; + import org.bukkit.event.Event; + import org.bukkit.event.Event.Result; +@@ -1796,4 +1796,12 @@ public class CraftEventFactory { + Bukkit.getPluginManager().callEvent(event); + return event; + } ++ ++ // Paper start ++ public static boolean handleBlockFailedDispenseEvent(WorldServer worldserver, BlockPosition blockposition) { ++ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); ++ return event.callEvent(); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0637-Added-PlayerLecternPageChangeEvent.patch b/patches/server-unmapped/0637-Added-PlayerLecternPageChangeEvent.patch new file mode 100644 index 0000000000..eb926aff50 --- /dev/null +++ b/patches/server-unmapped/0637-Added-PlayerLecternPageChangeEvent.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 23 Nov 2020 12:58:51 -0800 +Subject: [PATCH] Added PlayerLecternPageChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java +index e7c29d194d5c3e3b1b79228758f7a3d8aa060fbd..9c6330da4e026a7753698b5d103c009730154c3e 100644 +--- a/src/main/java/net/minecraft/world/inventory/Container.java ++++ b/src/main/java/net/minecraft/world/inventory/Container.java +@@ -562,6 +562,7 @@ public abstract class Container { + this.getSlot(i).set(itemstack); + } + ++ public void setData(int index, int value) { this.a(index, value); } // Paper - OBFHELPER + public void a(int i, int j) { + ((ContainerProperty) this.d.get(i)).set(j); + } +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLectern.java b/src/main/java/net/minecraft/world/inventory/ContainerLectern.java +index 70d9ebca8d176d6483f104bd03598753811fc154..65687792351fbd561b1f4d6f88bc7288b6d8346f 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerLectern.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerLectern.java +@@ -14,6 +14,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryView; + import org.bukkit.entity.Player; + import org.bukkit.event.player.PlayerTakeLecternBookEvent; + // CraftBukkit end ++import io.papermc.paper.event.player.PlayerLecternPageChangeEvent; // Paper + + public class ContainerLectern extends Container { + +@@ -61,6 +62,7 @@ public class ContainerLectern extends Container { + @Override + public boolean a(EntityHuman entityhuman, int i) { + int j; ++ PlayerLecternPageChangeEvent playerLecternPageChangeEvent; CraftInventoryLectern bukkitView; // Paper + + if (i >= 100) { + j = i - 100; +@@ -70,11 +72,25 @@ public class ContainerLectern extends Container { + switch (i) { + case 1: + j = this.containerProperties.getProperty(0); +- this.a(0, j - 1); ++ // Paper start ++ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); ++ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, j, j - 1); ++ if (!playerLecternPageChangeEvent.callEvent()) { ++ return false; ++ } ++ this.setData(0, playerLecternPageChangeEvent.getNewPage()); ++ // Paper end + return true; + case 2: + j = this.containerProperties.getProperty(0); +- this.a(0, j + 1); ++ // Paper start ++ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); ++ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, j, j + 1); ++ if (!playerLecternPageChangeEvent.callEvent()) { ++ return false; ++ } ++ this.setData(0, playerLecternPageChangeEvent.getNewPage()); ++ // Paper end + return true; + case 3: + if (!entityhuman.eK()) { diff --git a/patches/server-unmapped/0638-Fire-event-on-GS4-query.patch b/patches/server-unmapped/0638-Fire-event-on-GS4-query.patch new file mode 100644 index 0000000000..24dd766968 --- /dev/null +++ b/patches/server-unmapped/0638-Fire-event-on-GS4-query.patch @@ -0,0 +1,204 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 17 Mar 2019 21:46:56 +0200 +Subject: [PATCH] Fire event on GS4 query + + +diff --git a/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java b/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java +index 57ff3db0a0199ef03045b880e598407886b0306b..1b6761f75d97c49b1bf1ce3db631b7250c9489bd 100644 +--- a/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java ++++ b/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java +@@ -18,15 +18,27 @@ public class RemoteStatusReply { + this.b.write(abyte, 0, abyte.length); + } + ++ public void writeString(String string) throws IOException { this.a(string); } // Paper - OBFHELPER + public void a(String s) throws IOException { + this.b.writeBytes(s); + this.b.write(0); + } ++ // Paper start - unchecked exception variant to use in Stream API ++ public void writeStringUnchecked(String string) { ++ try { ++ writeString(string); ++ } catch (IOException e) { ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(e); ++ } ++ } ++ // Paper end + ++ public void writeInt(int i) throws IOException { this.a(i); } // Paper - OBFHELPER + public void a(int i) throws IOException { + this.b.write(i); + } + ++ public void writeShort(short i) throws IOException { this.a(i); } // Paper - OBFHELPER + public void a(short short0) throws IOException { + this.b.writeShort(Short.reverseBytes(short0)); + } +diff --git a/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java b/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java +index 55b379af2e0c8c3513a76a346d381cd3dbcabe40..59769f7ea808b952cd02192c7121c248756998e9 100644 +--- a/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java ++++ b/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java +@@ -16,6 +16,7 @@ import java.util.Random; + import javax.annotation.Nullable; + import net.minecraft.SystemUtils; + import net.minecraft.server.IMinecraftServer; ++import net.minecraft.server.dedicated.DedicatedServer; + import net.minecraft.server.rcon.RemoteStatusReply; + import net.minecraft.server.rcon.StatusChallengeUtils; + import org.apache.logging.log4j.LogManager; +@@ -26,18 +27,18 @@ public class RemoteStatusListener extends RemoteConnectionThread { + private static final Logger LOGGER = LogManager.getLogger(); + private long e; + private final int f; +- private final int g; +- private final int h; +- private final String i; +- private final String j; ++ private final int g; private final int getServerPort() { return this.g; } // Paper - OBFHELPER ++ private final int h; private final int getMaxPlayers() { return this.h; } // Paper - OBFHELPER ++ private final String i; private final String getMotd() { return this.i; } // Paper - OBFHELPER ++ private final String j; private final String getWorldName() { return this.j; } // Paper - OBFHELPER + private DatagramSocket k; + private final byte[] l = new byte[1460]; +- private String m; ++ private String m; public final String getServerHost() { return this.m; } // Paper - OBFHELPER + private String n; + private final Map o; +- private final RemoteStatusReply p; ++ private final RemoteStatusReply p; private final RemoteStatusReply getCachedFullResponse() { return this.p; } // Paper - OBFHELPER + private long q; +- private final IMinecraftServer r; ++ private final IMinecraftServer r; private final IMinecraftServer getServer() { return this.r; } // Paper - OBFHELPER + + private RemoteStatusListener(IMinecraftServer iminecraftserver, int i) { + super("Query Listener"); +@@ -107,6 +108,7 @@ public class RemoteStatusListener extends RemoteConnectionThread { + + remotestatusreply.a((int) 0); + remotestatusreply.a(this.a(datagrampacket.getSocketAddress())); ++ /* Paper start - GS4 Query event + remotestatusreply.a(this.i); + remotestatusreply.a("SMP"); + remotestatusreply.a(this.j); +@@ -114,6 +116,31 @@ public class RemoteStatusListener extends RemoteConnectionThread { + remotestatusreply.a(Integer.toString(this.h)); + remotestatusreply.a((short) this.g); + remotestatusreply.a(this.m); ++ */ ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.BASIC; ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() ++ .motd(this.getMotd()) ++ .map(this.getWorldName()) ++ .currentPlayers(this.getServer().getPlayerCount()) ++ .maxPlayers(this.getMaxPlayers()) ++ .port(this.getServerPort()) ++ .hostname(this.getServerHost()) ++ .gameVersion(this.getServer().getVersion()) ++ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) ++ .build(); ++ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = ++ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, datagrampacket.getAddress(), queryResponse); ++ queryEvent.callEvent(); ++ queryResponse = queryEvent.getResponse(); ++ remotestatusreply.writeString(queryResponse.getMotd()); ++ remotestatusreply.writeString("SMP"); ++ remotestatusreply.writeString(queryResponse.getMap()); ++ remotestatusreply.writeString(Integer.toString(queryResponse.getCurrentPlayers())); ++ remotestatusreply.writeString(Integer.toString(queryResponse.getMaxPlayers())); ++ remotestatusreply.writeShort((short) queryResponse.getPort()); ++ remotestatusreply.writeString(queryResponse.getHostname()); ++ // Paper end + this.a(remotestatusreply.a(), datagrampacket); + RemoteStatusListener.LOGGER.debug("Status [{}]", socketaddress); + } +@@ -150,6 +177,7 @@ public class RemoteStatusListener extends RemoteConnectionThread { + this.p.a("splitnum"); + this.p.a((int) 128); + this.p.a((int) 0); ++ /* Paper start - GS4 Query event + this.p.a("hostname"); + this.p.a(this.i); + this.p.a("gametype"); +@@ -185,6 +213,79 @@ public class RemoteStatusListener extends RemoteConnectionThread { + } + + this.p.a((int) 0); ++ */ ++ // Pack plugins ++ java.util.List plugins = java.util.Collections.emptyList(); ++ org.bukkit.plugin.Plugin[] bukkitPlugins; ++ if (((DedicatedServer) this.getServer()).server.getQueryPlugins() && (bukkitPlugins = org.bukkit.Bukkit.getPluginManager().getPlugins()).length > 0) { ++ plugins = java.util.stream.Stream.of(bukkitPlugins) ++ .map(plugin -> com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation.of(plugin.getName(), plugin.getDescription().getVersion())) ++ .collect(java.util.stream.Collectors.toList()); ++ } ++ ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() ++ .motd(this.getMotd()) ++ .map(this.getWorldName()) ++ .currentPlayers(this.getServer().getPlayerCount()) ++ .maxPlayers(this.getMaxPlayers()) ++ .port(this.getServerPort()) ++ .hostname(this.getServerHost()) ++ .plugins(plugins) ++ .players(this.getServer().getPlayers()) ++ .gameVersion(this.getServer().getVersion()) ++ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) ++ .build(); ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.FULL; ++ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = ++ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, datagrampacket.getAddress(), queryResponse); ++ queryEvent.callEvent(); ++ queryResponse = queryEvent.getResponse(); ++ this.getCachedFullResponse().writeString("hostname"); ++ this.getCachedFullResponse().writeString(queryResponse.getMotd()); ++ this.getCachedFullResponse().writeString("gametype"); ++ this.getCachedFullResponse().writeString("SMP"); ++ this.getCachedFullResponse().writeString("game_id"); ++ this.getCachedFullResponse().writeString("MINECRAFT"); ++ this.getCachedFullResponse().writeString("version"); ++ this.getCachedFullResponse().writeString(queryResponse.getGameVersion()); ++ this.getCachedFullResponse().writeString("plugins"); ++ java.lang.StringBuilder pluginsString = new java.lang.StringBuilder(); ++ pluginsString.append(queryResponse.getServerVersion()); ++ if (!queryResponse.getPlugins().isEmpty()) { ++ pluginsString.append(": "); ++ java.util.Iterator iter = queryResponse.getPlugins().iterator(); ++ while (iter.hasNext()) { ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation info = iter.next(); ++ pluginsString.append(info.getName()); ++ if (info.getVersion() != null) { ++ pluginsString.append(' ').append(info.getVersion().replace(";", ",")); ++ } ++ if (iter.hasNext()) { ++ pluginsString.append(';').append(' '); ++ } ++ } ++ } ++ this.getCachedFullResponse().writeString(pluginsString.toString()); ++ this.getCachedFullResponse().writeString("map"); ++ this.getCachedFullResponse().writeString(queryResponse.getMap()); ++ this.getCachedFullResponse().writeString("numplayers"); ++ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getCurrentPlayers())); ++ this.getCachedFullResponse().writeString("maxplayers"); ++ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getMaxPlayers())); ++ this.getCachedFullResponse().writeString("hostport"); ++ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getPort())); ++ this.getCachedFullResponse().writeString("hostip"); ++ this.getCachedFullResponse().writeString(queryResponse.getHostname()); ++ // The "meaningless data" start, copied from above ++ this.getCachedFullResponse().writeInt(0); ++ this.getCachedFullResponse().writeInt(1); ++ this.getCachedFullResponse().writeString("player_"); ++ this.getCachedFullResponse().writeInt(0); ++ // "Meaningless data" end ++ queryResponse.getPlayers().forEach(this.getCachedFullResponse()::writeStringUnchecked); ++ this.getCachedFullResponse().writeInt(0); ++ // Paper end + return this.p.a(); + } + } diff --git a/patches/server-unmapped/0639-Added-PlayerLoomPatternSelectEvent.patch b/patches/server-unmapped/0639-Added-PlayerLoomPatternSelectEvent.patch new file mode 100644 index 0000000000..c6d4f6121a --- /dev/null +++ b/patches/server-unmapped/0639-Added-PlayerLoomPatternSelectEvent.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 25 Nov 2020 16:33:27 -0800 +Subject: [PATCH] Added PlayerLoomPatternSelectEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java +index 7980930cc712e37a788f894bf2d2ee2b1cfc1196..5e5367710d43fc421806bda31cd611a9cb5869f3 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java +@@ -22,6 +22,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; + import org.bukkit.craftbukkit.inventory.CraftInventoryView; + import org.bukkit.entity.Player; + // CraftBukkit end ++import io.papermc.paper.event.player.PlayerLoomPatternSelectEvent; // Paper + + public class ContainerLoom extends Container { + +@@ -41,7 +42,7 @@ public class ContainerLoom extends Container { + } + // CraftBukkit end + private final ContainerAccess containerAccess; +- private final ContainerProperty d; ++ private final ContainerProperty d; public final ContainerProperty getSelectedBannerPattern() { return this.d; }; // Paper - OBFHELPER + private Runnable e; + private final Slot f; + private final Slot g; +@@ -160,7 +161,22 @@ public class ContainerLoom extends Container { + @Override + public boolean a(EntityHuman entityhuman, int i) { + if (i > 0 && i <= EnumBannerPatternType.R) { +- this.d.set(i); ++ // Paper start ++ int enumBannerPatternTypeOrdinal = i; ++ PlayerLoomPatternSelectEvent event = new PlayerLoomPatternSelectEvent((Player) entityhuman.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.block.banner.PatternType.getByIdentifier(EnumBannerPatternType.values()[i].getIdentifier())); ++ if (!event.callEvent()) { ++ ((Player) entityhuman.getBukkitEntity()).updateInventory(); ++ return false; ++ } ++ for (EnumBannerPatternType nms : EnumBannerPatternType.values()) { ++ if (event.getPatternType().getIdentifier().equals(nms.getIdentifier())) { ++ enumBannerPatternTypeOrdinal = nms.ordinal(); ++ break; ++ } ++ } ++ ((Player) entityhuman.getBukkitEntity()).updateInventory(); ++ this.getSelectedBannerPattern().set(enumBannerPatternTypeOrdinal); ++ // Paper end + this.j(); + return true; + } else { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java b/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java +index 988e52c675dbb5ef368c8dbb5fb6d4229eb30174..9bc27e727d11d4ac9055a0bc02d8a2ef606ff9c4 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java +@@ -33,6 +33,7 @@ public enum EnumBannerPatternType { + this.T = flag; + } + ++ public String getIdentifier() { return this.b(); } // Paper - OBFHELPER + public String b() { + return this.V; + } diff --git a/patches/server-unmapped/0640-Configurable-door-breaking-difficulty.patch b/patches/server-unmapped/0640-Configurable-door-breaking-difficulty.patch new file mode 100644 index 0000000000..d52bdc76ed --- /dev/null +++ b/patches/server-unmapped/0640-Configurable-door-breaking-difficulty.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 3 Jan 2021 22:27:43 -0800 +Subject: [PATCH] Configurable door breaking difficulty + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 23a23e2ea133ce81d3dedc4ffd17435a995497ef..497f32e4e1c82c0403669b612d07098c625288ce 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -5,8 +5,12 @@ import java.util.EnumMap; + import java.util.HashMap; + import java.util.List; + import java.util.Map; ++import java.util.stream.Collectors; + + import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; ++import net.minecraft.world.EnumDifficulty; ++import net.minecraft.world.entity.monster.EntityVindicator; ++import net.minecraft.world.entity.monster.EntityZombie; + import org.bukkit.Bukkit; + import org.bukkit.Material; + import org.bukkit.configuration.ConfigurationSection; +@@ -73,6 +77,11 @@ public class PaperWorldConfig { + return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); + } + ++ private > List getEnumList(String path, List def, Class type) { ++ config.addDefault("world-settings.default." + path, def.stream().map(Enum::name).collect(Collectors.toList())); ++ return ((List) (config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)))).stream().map(s -> Enum.valueOf(type, s)).collect(Collectors.toList()); ++ } ++ + public int cactusMaxHeight; + public int reedMaxHeight; + public int bambooMaxHeight; +@@ -735,4 +744,23 @@ public class PaperWorldConfig { + private void disableMobSpawnerSpawnEggTransformation() { + disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); + } ++ ++ public List zombieBreakDoors; ++ public List vindicatorBreakDoors; ++ private void setupEntityBreakingDoors() { ++ zombieBreakDoors = getEnumList( ++ "door-breaking-difficulty.zombie", ++ Arrays.stream(EnumDifficulty.values()) ++ .filter(EntityZombie.getDoorBreakingPredicate()) ++ .collect(Collectors.toList()), ++ EnumDifficulty.class ++ ); ++ vindicatorBreakDoors = getEnumList( ++ "door-breaking-difficulty.vindicator", ++ Arrays.stream(EnumDifficulty.values()) ++ .filter(EntityVindicator.getDoorBreakingPredicate()) ++ .collect(Collectors.toList()), ++ EnumDifficulty.class ++ ); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java +index c45dcb56af95f3e87e292b92b697a336461f01bc..f0eda0b83bab8e3a8adbb569b5997402b0e08e9a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java +@@ -48,6 +48,7 @@ import net.minecraft.world.level.WorldAccess; + + public class EntityVindicator extends EntityIllagerAbstract { + ++ public static final Predicate getDoorBreakingPredicate() { return b; } // Paper - OBFHELPER + private static final Predicate b = (enumdifficulty) -> { + return enumdifficulty == EnumDifficulty.NORMAL || enumdifficulty == EnumDifficulty.HARD; + }; +@@ -204,7 +205,7 @@ public class EntityVindicator extends EntityIllagerAbstract { + static class a extends PathfinderGoalBreakDoor { + + public a(EntityInsentient entityinsentient) { +- super(entityinsentient, 6, EntityVindicator.b); ++ super(entityinsentient, 6, com.google.common.base.Predicates.in(entityinsentient.world.paperConfig.vindicatorBreakDoors)); // Paper + this.a(EnumSet.of(PathfinderGoal.Type.MOVE)); + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index fb98609a38d665659076b8949b59eaf084408a17..634416c354184bc6a2348c27c55e9868009ccd28 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -86,6 +86,7 @@ public class EntityZombie extends EntityMonster { + private static final DataWatcherObject d = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); + private static final DataWatcherObject bo = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.b); + public static final DataWatcherObject DROWN_CONVERTING = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); ++ public static final Predicate getDoorBreakingPredicate() { return bq; } // Paper - OBFHELPER + private static final Predicate bq = (enumdifficulty) -> { + return enumdifficulty == EnumDifficulty.HARD; + }; +@@ -98,7 +99,7 @@ public class EntityZombie extends EntityMonster { + + public EntityZombie(EntityTypes entitytypes, World world) { + super(entitytypes, world); +- this.br = new PathfinderGoalBreakDoor(this, EntityZombie.bq); ++ this.br = new PathfinderGoalBreakDoor(this, com.google.common.base.Predicates.in(world.paperConfig.zombieBreakDoors)); // Paper + } + + public EntityZombie(World world) { diff --git a/patches/server-unmapped/0641-Empty-commands-shall-not-be-dispatched.patch b/patches/server-unmapped/0641-Empty-commands-shall-not-be-dispatched.patch new file mode 100644 index 0000000000..300a04163a --- /dev/null +++ b/patches/server-unmapped/0641-Empty-commands-shall-not-be-dispatched.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Wed, 6 Jan 2021 23:38:43 +0100 +Subject: [PATCH] Empty commands shall not be dispatched + + +diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java +index a13c684e1360169993f323aa4aa91078c5e8b031..978d3b79b5f953e67263598dff09bcb40b6e3f31 100644 +--- a/src/main/java/net/minecraft/commands/CommandDispatcher.java ++++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java +@@ -223,6 +223,7 @@ public class CommandDispatcher { + command = event.getCommand(); + + String[] args = command.split(" "); ++ if (args.length == 0) return 0; // Paper - empty commands shall not be dispatched + + String cmd = args[0]; + if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); diff --git a/patches/server-unmapped/0642-Implement-API-to-expose-exact-interaction-point.patch b/patches/server-unmapped/0642-Implement-API-to-expose-exact-interaction-point.patch new file mode 100644 index 0000000000..ab1364a6c0 --- /dev/null +++ b/patches/server-unmapped/0642-Implement-API-to-expose-exact-interaction-point.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Mon, 4 Jan 2021 16:40:27 +1000 +Subject: [PATCH] Implement API to expose exact interaction point + + +diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +index 31012963815a5c7355753b8cd2749976282ef0d2..87722285690d9d3370610e2a2eb809e0d1f497c9 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java ++++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java +@@ -496,7 +496,7 @@ public class PlayerInteractManager { + cancelledBlock = true; + } + +- PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(entityplayer, Action.RIGHT_CLICK_BLOCK, blockposition, movingobjectpositionblock.getDirection(), itemstack, cancelledBlock, enumhand); ++ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(entityplayer, Action.RIGHT_CLICK_BLOCK, blockposition, movingobjectpositionblock.getDirection(), itemstack, cancelledBlock, enumhand, movingobjectpositionblock.getPos()); // Paper + firedInteract = true; + interactResult = event.useItemInHand() == Event.Result.DENY; + interactPosition = blockposition.immutableCopy(); +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index a7f8e08dcbc102041891e51cbe9c984d6f43747b..365d186c5a6d985ed08e09112b74f44b7cfad688 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -70,7 +70,9 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; + import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.MovingObjectPositionEntity; ++import net.minecraft.world.phys.Vec3D; + import org.bukkit.Bukkit; ++import org.bukkit.Location; // Paper + import org.bukkit.Material; + import org.bukkit.NamespacedKey; + import org.bukkit.Server; +@@ -487,7 +489,13 @@ public class CraftEventFactory { + return callPlayerInteractEvent(who, action, position, direction, itemstack, false, hand); + } + ++ // Paper start - Add interactionPoint + public static PlayerInteractEvent callPlayerInteractEvent(EntityHuman who, Action action, BlockPosition position, EnumDirection direction, ItemStack itemstack, boolean cancelledBlock, EnumHand hand) { ++ return callPlayerInteractEvent(who, action, position, direction, itemstack, cancelledBlock, hand, null); ++ } ++ ++ public static PlayerInteractEvent callPlayerInteractEvent(EntityHuman who, Action action, BlockPosition position, EnumDirection direction, ItemStack itemstack, boolean cancelledBlock, EnumHand hand, Vec3D hitVec) { ++ // Paper end + Player player = (who == null) ? null : (Player) who.getBukkitEntity(); + CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack); + +@@ -513,7 +521,10 @@ public class CraftEventFactory { + itemInHand = null; + } + +- PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); ++ // Paper start ++ Location interactionPoint = hitVec == null ? null : new Location(craftWorld, hitVec.x, hitVec.y, hitVec.z); ++ PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND), interactionPoint); ++ // Paper end + if (cancelledBlock) { + event.setUseInteractedBlock(Event.Result.DENY); + } diff --git a/patches/server-unmapped/0643-Remove-stale-POIs.patch b/patches/server-unmapped/0643-Remove-stale-POIs.patch new file mode 100644 index 0000000000..20a7ee92ef --- /dev/null +++ b/patches/server-unmapped/0643-Remove-stale-POIs.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 9 Jan 2021 14:17:07 +0100 +Subject: [PATCH] Remove stale POIs + + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 0f0a3b3776c607217a15c5f61d60f6a98f1c7584..ac62e4e6842a474a1284ae7ac8890cc00b55aa64 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -2077,6 +2077,11 @@ public class WorldServer extends World implements GeneratorAccessSeed { + }); + optional1.ifPresent((villageplacetype) -> { + this.getMinecraftServer().execute(() -> { ++ // Paper start ++ if (!optional.isPresent() && this.getPoiStorage().test(blockposition1, com.google.common.base.Predicates.alwaysTrue())) { ++ this.getPoiStorage().remove(blockposition1); ++ } ++ // Paper end + this.y().a(blockposition1, villageplacetype); + PacketDebug.a(this, blockposition1); + }); +@@ -2084,6 +2089,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + } + ++ public final VillagePlace getPoiStorage() { return this.y(); } // Paper - OBFHELPER + public VillagePlace y() { + return this.getChunkProvider().j(); + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java +index 04b01cb841dc4f34ded5aaa4ea7a8e6d4b470183..ce165233739c7b92a76031b949f269bd0a11149c 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java +@@ -54,6 +54,7 @@ public class VillagePlace extends RegionFileSection { + ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).a(blockposition, villageplacetype); + } + ++ public void remove(BlockPosition blockposition) { this.a(blockposition); } // Paper - OBFHELPER + public void a(BlockPosition blockposition) { + ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).a(blockposition); + } +@@ -138,6 +139,7 @@ public class VillagePlace extends RegionFileSection { + return ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).c(blockposition); + } + ++ public final boolean test(BlockPosition blockposition, Predicate predicate) { return this.a(blockposition, predicate); } // Paper - OBFHELPER + public boolean a(BlockPosition blockposition, Predicate predicate) { + return (Boolean) this.d(SectionPosition.a(blockposition).s()).map((villageplacesection) -> { + return villageplacesection.a(blockposition, predicate); diff --git a/patches/server-unmapped/0644-Fix-villager-boat-exploit.patch b/patches/server-unmapped/0644-Fix-villager-boat-exploit.patch new file mode 100644 index 0000000000..06ed0a695a --- /dev/null +++ b/patches/server-unmapped/0644-Fix-villager-boat-exploit.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Mon, 11 Jan 2021 12:43:51 -0800 +Subject: [PATCH] Fix villager boat exploit + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 66fbbc4c91e16a3dfb4bb756972e667121693501..cf457f6b6ee2968f68f4eede30bb703a6a4f990b 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -77,6 +77,7 @@ import net.minecraft.util.MathHelper; + import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityTypes; ++import net.minecraft.world.entity.npc.EntityVillagerAbstract; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.EnumGamemode; +@@ -621,6 +622,15 @@ public abstract class PlayerList { + + for (Iterator iterator = entity.getAllPassengers().iterator(); iterator.hasNext(); entity1.dead = true) { + entity1 = (Entity) iterator.next(); ++ // Paper start ++ if (entity1 instanceof EntityVillagerAbstract) { ++ final EntityVillagerAbstract villager = (EntityVillagerAbstract) entity1; ++ final EntityHuman human = villager.getTrader(); ++ if (human != null) { ++ villager.setTradingPlayer(null); ++ } ++ } ++ // Paper end + worldserver.removeEntity(entity1); + } + diff --git a/patches/server-unmapped/0645-Entity-load-save-limit-per-chunk.patch b/patches/server-unmapped/0645-Entity-load-save-limit-per-chunk.patch new file mode 100644 index 0000000000..b122f40024 --- /dev/null +++ b/patches/server-unmapped/0645-Entity-load-save-limit-per-chunk.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Wed, 18 Nov 2020 20:52:25 -0800 +Subject: [PATCH] Entity load/save limit per chunk + +Adds a config option to limit the number of entities saved and loaded +to a chunk. The default values of -1 disable the limit. Although +defaults are only included for certain entites, this allows setting +limits for any entity type. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 497f32e4e1c82c0403669b612d07098c625288ce..d052d53771d868e6fa25d8854fc675a808722c65 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -9,6 +9,7 @@ import java.util.stream.Collectors; + + import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; + import net.minecraft.world.EnumDifficulty; ++import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.monster.EntityVindicator; + import net.minecraft.world.entity.monster.EntityZombie; + import org.bukkit.Bukkit; +@@ -763,4 +764,18 @@ public class PaperWorldConfig { + EnumDifficulty.class + ); + } ++ ++ public Map, Integer> entityPerChunkSaveLimits = new HashMap<>(); ++ private void entityPerChunkSaveLimits() { ++ getInt("entity-per-chunk-save-limit.experience_orb", -1); ++ getInt("entity-per-chunk-save-limit.snowball", -1); ++ getInt("entity-per-chunk-save-limit.ender_pearl", -1); ++ getInt("entity-per-chunk-save-limit.arrow", -1); ++ EntityTypes.getEntityNameList().forEach(name -> { ++ final EntityTypes type = EntityTypes.getByName(name.getKey()).orElseThrow(() -> new IllegalStateException("Unknown Entity Type: " + name.toString())); ++ final String path = ".entity-per-chunk-save-limit." + name.getKey(); ++ final int value = config.getInt("world-settings." + worldName + path, config.getInt("world-settings.default" + path, -1)); // get without setting defaults ++ if (value != -1) entityPerChunkSaveLimits.put(type, value); ++ }); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +index 2e5221bc1b9e260e33f2cef2653dc59d05e2680d..4eaf497d048324a85ce49fc1c6e9559991c20df7 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -539,11 +539,22 @@ public class ChunkRegionLoader { + + chunk.d(false); + ++ // Paper start ++ final Map, Integer> savedEntityCounts = Maps.newHashMap(); + for (int j = 0; j < chunk.getEntitySlices().length; ++j) { + Iterator iterator1 = chunk.getEntitySlices()[j].iterator(); + + while (iterator1.hasNext()) { + Entity entity = (Entity) iterator1.next(); ++ final EntityTypes entityType = entity.getEntityType(); ++ final int saveLimit = worldserver.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ continue; ++ } ++ savedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end + NBTTagCompound nbttagcompound4 = new NBTTagCompound(); + // Paper start + if (asyncsavedata == null && !entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { +@@ -674,10 +685,21 @@ public class ChunkRegionLoader { + NBTTagList nbttaglist = nbttagcompound.getList("Entities", 10); + World world = chunk.getWorld(); + ++ // Paper start ++ final Map, Integer> loadedEntityCounts = Maps.newHashMap(); + for (int i = 0; i < nbttaglist.size(); ++i) { + NBTTagCompound nbttagcompound1 = nbttaglist.getCompound(i); + + EntityTypes.a(nbttagcompound1, world, (entity) -> { ++ final EntityTypes entityType = entity.getEntityType(); ++ final int saveLimit = world.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ return null; ++ } ++ loadedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end + chunk.a(entity); + return entity; + }); diff --git a/patches/server-unmapped/0646-Add-sendOpLevel-API.patch b/patches/server-unmapped/0646-Add-sendOpLevel-API.patch new file mode 100644 index 0000000000..382d088024 --- /dev/null +++ b/patches/server-unmapped/0646-Add-sendOpLevel-API.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Tue, 29 Dec 2020 15:03:03 +0100 +Subject: [PATCH] Add sendOpLevel API + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index cf457f6b6ee2968f68f4eede30bb703a6a4f990b..1358993217e601e3bab6e0a4e8c55d555865a13e 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -1138,6 +1138,11 @@ public abstract class PlayerList { + } + + private void a(EntityPlayer entityplayer, int i) { ++ // Paper start - add recalculatePermissions parameter ++ this.sendPlayerOperatorStatus(entityplayer, i, true); ++ } ++ public void sendPlayerOperatorStatus(EntityPlayer entityplayer, int i, boolean recalculatePermissions) { ++ // Paper end + if (entityplayer.playerConnection != null) { + byte b0; + +@@ -1152,8 +1157,10 @@ public abstract class PlayerList { + entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, b0)); + } + ++ if (recalculatePermissions) { // Paper + entityplayer.getBukkitEntity().recalculatePermissions(); // CraftBukkit + this.server.getCommandDispatcher().a(entityplayer); ++ } // Paper + } + + // Paper start +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 41987716afa8ec34214868373df97d0e8f8b27c1..e81de526a847c730abf86016354c1dc57780ec8b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2300,6 +2300,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + ? (org.bukkit.entity.Firework) entity.getBukkitEntity() + : null; + } ++ ++ @Override ++ public void sendOpLevel(byte level) { ++ Preconditions.checkArgument(level >= 0 && level <= 4, "Level must be within [0, 4]"); ++ ++ this.getHandle().getMinecraftServer().getPlayerList().sendPlayerOperatorStatus(this.getHandle(), level, false); ++ } + // Paper end + + // Spigot start diff --git a/patches/server-unmapped/0647-Add-StructureLocateEvent.patch b/patches/server-unmapped/0647-Add-StructureLocateEvent.patch new file mode 100644 index 0000000000..3e68e76756 --- /dev/null +++ b/patches/server-unmapped/0647-Add-StructureLocateEvent.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: dfsek +Date: Wed, 16 Sep 2020 01:12:29 -0700 +Subject: [PATCH] Add StructureLocateEvent + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +index b1f2c424ef358f79c7fced88a61560d3ce32a2b6..f2621f61cb372ec436fe81e7a93f1aef7d360f3f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.chunk; + + import com.google.common.collect.Lists; + import com.mojang.serialization.Codec; ++import io.papermc.paper.event.world.StructureLocateEvent; // Paper - Add import due to naming conflict. + import java.util.BitSet; + import java.util.Iterator; + import java.util.List; +@@ -160,6 +161,22 @@ public abstract class ChunkGenerator { + + @Nullable + public BlockPosition findNearestMapFeature(WorldServer worldserver, StructureGenerator structuregenerator, BlockPosition blockposition, int i, boolean flag) { ++ // Paper start ++ org.bukkit.World world = worldserver.getWorld(); ++ org.bukkit.Location originLocation = new org.bukkit.Location(world, blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ StructureLocateEvent event = new StructureLocateEvent(world, originLocation, org.bukkit.StructureType.getStructureTypes().get(structuregenerator.i()), i, flag); ++ if(!event.callEvent()) return null; ++ // If event call set a final location, skip structure finding and just return set result. ++ if(event.getResult() != null) return new BlockPosition(event.getResult().getBlockX(), event.getResult().getBlockY(), event.getResult().getBlockZ()); ++ // Get origin location (re)defined by event call. ++ blockposition = new BlockPosition(event.getOrigin().getBlockX(), event.getOrigin().getBlockY(), event.getOrigin().getBlockZ()); ++ // Get world (re)defined by event call. ++ worldserver = ((org.bukkit.craftbukkit.CraftWorld) event.getOrigin().getWorld()).getHandle(); ++ // Get radius and whether to find unexplored structures (re)defined by event call. ++ i = event.getRadius(); ++ flag = event.shouldFindUnexplored(); ++ structuregenerator = StructureGenerator.a.get(event.getType().getName()); ++ // Paper end + if (!this.b.a(structuregenerator)) { + return null; + } else if (structuregenerator == StructureGenerator.STRONGHOLD) { diff --git a/patches/server-unmapped/0648-Collision-option-for-requiring-a-player-participant.patch b/patches/server-unmapped/0648-Collision-option-for-requiring-a-player-participant.patch new file mode 100644 index 0000000000..b26885d17e --- /dev/null +++ b/patches/server-unmapped/0648-Collision-option-for-requiring-a-player-participant.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sat, 14 Nov 2020 16:48:37 +0100 +Subject: [PATCH] Collision option for requiring a player participant + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index d052d53771d868e6fa25d8854fc675a808722c65..c293efaa70c67d7a4227d779eac5d3a510a79ee0 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -718,6 +718,18 @@ public class PaperWorldConfig { + } + } + ++ public boolean onlyPlayersCollide = false; ++ public boolean allowVehicleCollisions = true; ++ private void onlyPlayersCollide() { ++ onlyPlayersCollide = getBoolean("only-players-collide", onlyPlayersCollide); ++ allowVehicleCollisions = getBoolean("allow-vehicle-collisions", allowVehicleCollisions); ++ if (onlyPlayersCollide && !allowVehicleCollisions) { ++ log("Collisions will only work if a player is one of the two entities colliding."); ++ } else if (onlyPlayersCollide) { ++ log("Collisions will only work if a player OR a vehicle is one of the two entities colliding."); ++ } ++ } ++ + public int wanderingTraderSpawnMinuteTicks = 1200; + public int wanderingTraderSpawnDayTicks = 24000; + public int wanderingTraderSpawnChanceFailureIncrement = 25; +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index dc0e2a1348062ea79b1ec3a9fdb985d9d3fca790..881db84a1afe2da5d30732c282f36b294c721c41 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1467,6 +1467,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public void collide(Entity entity) { + if (!this.isSameVehicle(entity)) { + if (!entity.noclip && !this.noclip) { ++ if (this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer || this instanceof EntityPlayer)) return; // Paper + double d0 = entity.locX() - this.locX(); + double d1 = entity.locZ() - this.locZ(); + double d2 = MathHelper.a(d0, d1); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +index 2609b83573e0e8532e6c4c36d4f475bf0da6a354..069076d3c7165440217a7632b089ab2aa0fbdb1d 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +@@ -14,6 +14,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.sounds.SoundEffect; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.tags.Tag; +@@ -230,6 +231,7 @@ public class EntityBoat extends Entity { + + @Override + public void collide(Entity entity) { ++ if (!this.world.paperConfig.allowVehicleCollisions && this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer)) return; // Paper + if (entity instanceof EntityBoat) { + if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +index 2e3ceab3e34f7756764b3471b13d48d1263ecba9..57821301ef031995e6044a17b46c70a693322455 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +@@ -21,6 +21,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsBlock; + import net.minecraft.util.MathHelper; +@@ -767,6 +768,7 @@ public abstract class EntityMinecartAbstract extends Entity { + public void collide(Entity entity) { + if (!this.world.isClientSide) { + if (!entity.noclip && !this.noclip) { ++ if (!this.world.paperConfig.allowVehicleCollisions && this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer)) return; // Paper + if (!this.w(entity)) { + // CraftBukkit start + VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); diff --git a/patches/server-unmapped/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/patches/server-unmapped/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch new file mode 100644 index 0000000000..21e396674c --- /dev/null +++ b/patches/server-unmapped/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 16 Jan 2021 14:30:12 -0500 +Subject: [PATCH] Remove ProjectileHitEvent call when fireballs dead + +The duplicate ProjectileHitEvent in EntityFireball was removed. The +event was always called before the duplicate call. + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java +index 9660dc2263c48a5818b767843658eeb9ee1748ea..ba3b52691db79c83d4482664b7a9615ab9be2761 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java +@@ -87,7 +87,7 @@ public abstract class EntityFireball extends IProjectile { + + // CraftBukkit start - Fire ProjectileHitEvent + if (this.dead) { +- CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ // CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); // Paper - this is an undesired duplicate event + } + // CraftBukkit end + } diff --git a/patches/server-unmapped/0650-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/server-unmapped/0650-Return-chat-component-with-empty-text-instead-of-thr.patch new file mode 100644 index 0000000000..812ef9c07e --- /dev/null +++ b/patches/server-unmapped/0650-Return-chat-component-with-empty-text-instead-of-thr.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: CDFN +Date: Tue, 7 Jul 2020 17:53:23 +0200 +Subject: [PATCH] Return chat component with empty text instead of throwing + exception + + +diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java +index 9c6330da4e026a7753698b5d103c009730154c3e..bdd00608a72dd81003731ff5fbe774dfdc5220e5 100644 +--- a/src/main/java/net/minecraft/world/inventory/Container.java ++++ b/src/main/java/net/minecraft/world/inventory/Container.java +@@ -11,6 +11,7 @@ import net.minecraft.CrashReportSystemDetails; + import net.minecraft.ReportedException; + import net.minecraft.core.IRegistry; + import net.minecraft.core.NonNullList; ++import net.minecraft.network.chat.ChatComponentText; + import net.minecraft.server.level.EntityPlayer; + import net.minecraft.util.MathHelper; + import net.minecraft.world.IInventory; +@@ -61,7 +62,12 @@ public abstract class Container { + } + private IChatBaseComponent title; + public final IChatBaseComponent getTitle() { +- Preconditions.checkState(this.title != null, "Title not set"); ++ // Paper start - return chat component with empty text instead of throwing error ++ // Preconditions.checkState(this.title != null, "Title not set"); ++ if(this.title == null){ ++ return new ChatComponentText(""); ++ } ++ // Paper end + return this.title; + } + public final void setTitle(IChatBaseComponent title) { diff --git a/patches/server-unmapped/0651-Make-schedule-command-per-world.patch b/patches/server-unmapped/0651-Make-schedule-command-per-world.patch new file mode 100644 index 0000000000..87d12b6191 --- /dev/null +++ b/patches/server-unmapped/0651-Make-schedule-command-per-world.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 4 Jan 2021 19:52:44 -0800 +Subject: [PATCH] Make schedule command per-world + + +diff --git a/src/main/java/net/minecraft/server/commands/CommandSchedule.java b/src/main/java/net/minecraft/server/commands/CommandSchedule.java +index b88a91072032b75f83d811d63e1b5e3808faa9be..440b25dde0299037032d535c4c751f252775d6ad 100644 +--- a/src/main/java/net/minecraft/server/commands/CommandSchedule.java ++++ b/src/main/java/net/minecraft/server/commands/CommandSchedule.java +@@ -32,7 +32,7 @@ public class CommandSchedule { + return new ChatMessage("commands.schedule.cleared.failure", new Object[]{object}); + }); + private static final SuggestionProvider c = (commandcontext, suggestionsbuilder) -> { +- return ICompletionProvider.b((Iterable) ((CommandListenerWrapper) commandcontext.getSource()).getServer().getSaveData().H().u().a(), suggestionsbuilder); ++ return ICompletionProvider.b((Iterable) ((CommandListenerWrapper) commandcontext.getSource()).getWorld().worldDataServer.H().u().a(), suggestionsbuilder); // Paper + }; + + public static void a(CommandDispatcher commanddispatcher) { +@@ -55,7 +55,7 @@ public class CommandSchedule { + } else { + long j = commandlistenerwrapper.getWorld().getTime() + (long) i; + MinecraftKey minecraftkey = (MinecraftKey) pair.getFirst(); +- CustomFunctionCallbackTimerQueue customfunctioncallbacktimerqueue = commandlistenerwrapper.getServer().getSaveData().H().u(); ++ CustomFunctionCallbackTimerQueue customfunctioncallbacktimerqueue = commandlistenerwrapper.getWorld().worldDataServer.H().u(); // Paper + + ((Either) pair.getSecond()).ifLeft((customfunction) -> { + String s = minecraftkey.toString(); +@@ -81,7 +81,7 @@ public class CommandSchedule { + } + + private static int a(CommandListenerWrapper commandlistenerwrapper, String s) throws CommandSyntaxException { +- int i = commandlistenerwrapper.getServer().getSaveData().H().u().a(s); ++ int i = commandlistenerwrapper.getWorld().worldDataServer.H().u().a(s); // Paper + + if (i == 0) { + throw CommandSchedule.b.create(s); diff --git a/patches/server-unmapped/0652-Configurable-max-leash-distance.patch b/patches/server-unmapped/0652-Configurable-max-leash-distance.patch new file mode 100644 index 0000000000..73febd3af8 --- /dev/null +++ b/patches/server-unmapped/0652-Configurable-max-leash-distance.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 3 Jan 2021 21:04:03 -0800 +Subject: [PATCH] Configurable max leash distance + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index c293efaa70c67d7a4227d779eac5d3a510a79ee0..af7e93cb64eff1448653b27c2c9aea2d278d3ab7 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -167,6 +167,12 @@ public class PaperWorldConfig { + } + } + ++ public float maxLeashDistance = 10f; ++ private void maxLeashDistance() { ++ maxLeashDistance = getFloat("max-leash-distance", maxLeashDistance); ++ log("Max leash distance: " + maxLeashDistance); ++ } ++ + public boolean disableEndCredits; + private void disableEndCredits() { + disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); +diff --git a/src/main/java/net/minecraft/world/entity/EntityCreature.java b/src/main/java/net/minecraft/world/entity/EntityCreature.java +index bbf0f345bfdd8a3a1f7fe902a42b2b18cdcf07a5..20570580367697e37e6c45147168c3beb6c8d31b 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityCreature.java ++++ b/src/main/java/net/minecraft/world/entity/EntityCreature.java +@@ -47,7 +47,7 @@ public abstract class EntityCreature extends EntityInsentient { + float f = this.g(entity); + + if (this instanceof EntityTameableAnimal && ((EntityTameableAnimal) this).isSitting()) { +- if (f > 10.0F) { ++ if (f > entity.world.paperConfig.maxLeashDistance) { // Paper + this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.unleash(true, true); + } +@@ -56,7 +56,7 @@ public abstract class EntityCreature extends EntityInsentient { + } + + this.x(f); +- if (f > 10.0F) { ++ if (f > entity.world.paperConfig.maxLeashDistance) { // Paper + this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.unleash(true, true); + this.goalSelector.a(PathfinderGoal.Type.MOVE); diff --git a/patches/server-unmapped/0653-Implement-BlockPreDispenseEvent.patch b/patches/server-unmapped/0653-Implement-BlockPreDispenseEvent.patch new file mode 100644 index 0000000000..f35aec4e6d --- /dev/null +++ b/patches/server-unmapped/0653-Implement-BlockPreDispenseEvent.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Sun, 17 Jan 2021 13:16:09 +1000 +Subject: [PATCH] Implement BlockPreDispenseEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java +index 966051ab3e720e5b3f0fb9ab852c8908c5f23f3b..9b92824f1c2797e321ced953d33d2c2fd339374a 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java +@@ -88,6 +88,7 @@ public class BlockDispenser extends BlockTileEntity { + IDispenseBehavior idispensebehavior = this.a(itemstack); + + if (idispensebehavior != IDispenseBehavior.NONE) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(worldserver, blockposition, itemstack, i)) return; // Paper - BlockPreDispenseEvent is called here + eventFired = false; // CraftBukkit - reset event status + tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 365d186c5a6d985ed08e09112b74f44b7cfad688..c109bbec67bd683077f0ab7331116a240a475827 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -71,6 +71,7 @@ import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.MovingObjectPositionEntity; + import net.minecraft.world.phys.Vec3D; ++import io.papermc.paper.event.block.BlockPreDispenseEvent; // Paper + import org.bukkit.Bukkit; + import org.bukkit.Location; // Paper + import org.bukkit.Material; +@@ -1814,5 +1815,11 @@ public class CraftEventFactory { + BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); + return event.callEvent(); + } ++ ++ public static boolean handleBlockPreDispenseEvent(WorldServer worldserver, BlockPosition blockposition, ItemStack itemStack, int slot) { ++ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ BlockPreDispenseEvent event = new BlockPreDispenseEvent(block, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), slot); ++ return event.callEvent(); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0654-Added-Vanilla-Entity-Tags.patch b/patches/server-unmapped/0654-Added-Vanilla-Entity-Tags.patch new file mode 100644 index 0000000000..4d3da07cb2 --- /dev/null +++ b/patches/server-unmapped/0654-Added-Vanilla-Entity-Tags.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 3 Jan 2021 20:03:35 -0800 +Subject: [PATCH] Added Vanilla Entity Tags + + +diff --git a/src/main/java/io/papermc/paper/CraftEntityTag.java b/src/main/java/io/papermc/paper/CraftEntityTag.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2ca8e1bade5450a14125b77540792e0b18c3e19b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/CraftEntityTag.java +@@ -0,0 +1,29 @@ ++package io.papermc.paper; ++ ++import net.minecraft.resources.MinecraftKey; ++import net.minecraft.tags.Tags; ++import net.minecraft.world.entity.EntityTypes; ++import org.bukkit.craftbukkit.tag.CraftTag; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.entity.EntityType; ++ ++import java.util.Collections; ++import java.util.Set; ++import java.util.stream.Collectors; ++ ++public class CraftEntityTag extends CraftTag, EntityType> { ++ ++ public CraftEntityTag(Tags> registry, MinecraftKey tag) { ++ super(registry, tag); ++ } ++ ++ @Override ++ public boolean isTagged(EntityType item) { ++ return getHandle().isTagged(CraftMagicNumbers.getEntityTypes(item)); ++ } ++ ++ @Override ++ public Set getValues() { ++ return Collections.unmodifiableSet(getHandle().getTagged().stream().map(CraftMagicNumbers::getEntityType).collect(Collectors.toSet())); ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 7277fd5807254020054cdbfb97fbd334e05da832..0f04ba41df95986b71524995738831223080cb88 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -2222,6 +2222,11 @@ public final class CraftServer implements Server { + Preconditions.checkArgument(clazz == org.bukkit.Fluid.class, "Fluid namespace must have fluid type"); + + return (org.bukkit.Tag) new CraftFluidTag(console.getTagRegistry().getFluidTags(), key); ++ // Paper start ++ case org.bukkit.Tag.REGISTRY_ENTITIES: ++ Preconditions.checkArgument(clazz == org.bukkit.entity.EntityType.class, "Entity namespace must have entitytype type"); ++ return (org.bukkit.Tag) new io.papermc.paper.CraftEntityTag(console.getTagRegistry().getEntityTags(), key); ++ // Paper end + default: + throw new IllegalArgumentException(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 36ad77a5a3987c1de5d0de7cbcb94cb6fe841d44..848a704fa100c39098a5716bb25b6a9ed85d7a8c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -118,8 +118,17 @@ public final class CraftMagicNumbers implements UnsafeValues { + private static final Map MATERIAL_ITEM = new HashMap<>(); + private static final Map MATERIAL_BLOCK = new HashMap<>(); + private static final Map MATERIAL_FLUID = new HashMap<>(); ++ // Paper start ++ private static final Map> ENTITY_TYPE_ENTITY_TYPES = new HashMap<>(); ++ private static final Map, org.bukkit.entity.EntityType> ENTITY_TYPES_ENTITY_TYPE = new HashMap<>(); + + static { ++ for (org.bukkit.entity.EntityType type : org.bukkit.entity.EntityType.values()) { ++ if (type == org.bukkit.entity.EntityType.UNKNOWN) continue; ++ ENTITY_TYPE_ENTITY_TYPES.put(type, IRegistry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey()))); ++ ENTITY_TYPES_ENTITY_TYPE.put(IRegistry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey())), type); ++ } ++ // Paper end + for (Block block : IRegistry.BLOCK) { + BLOCK_MATERIAL.put(block, Material.getMaterial(IRegistry.BLOCK.getKey(block).getKey().toUpperCase(Locale.ROOT))); + } +@@ -185,6 +194,14 @@ public final class CraftMagicNumbers implements UnsafeValues { + public static MinecraftKey key(Material mat) { + return CraftNamespacedKey.toMinecraft(mat.getKey()); + } ++ // Paper start ++ public static net.minecraft.world.entity.EntityTypes getEntityTypes(org.bukkit.entity.EntityType type) { ++ return ENTITY_TYPE_ENTITY_TYPES.get(type); ++ } ++ public static org.bukkit.entity.EntityType getEntityType(net.minecraft.world.entity.EntityTypes entityTypes) { ++ return ENTITY_TYPES_ENTITY_TYPE.get(entityTypes); ++ } ++ // Paper end + // ======================================================================== + // Paper start + @Override diff --git a/patches/server-unmapped/0655-added-Wither-API.patch b/patches/server-unmapped/0655-added-Wither-API.patch new file mode 100644 index 0000000000..e4d69e8e8e --- /dev/null +++ b/patches/server-unmapped/0655-added-Wither-API.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 5 Jul 2020 15:39:19 -0700 +Subject: [PATCH] added Wither API + + +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +index 30290c0208a4725b2eb0e7764465c354e592e4ee..170b085c76e092f6d7b14095c66c84fa9a96a1fc 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +@@ -82,6 +82,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + return entityliving.getMonsterType() != EnumMonsterType.UNDEAD && entityliving.ei(); + }; + private static final PathfinderTargetCondition bz = (new PathfinderTargetCondition()).a(20.0D).a(EntityWither.by); ++ // Paper start ++ private boolean canPortal = false; ++ ++ public void setCanTravelThroughPortals(boolean canPortal) { this.canPortal = canPortal; } ++ // Paper end + + public EntityWither(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -580,6 +585,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + this.datawatcher.set((DataWatcherObject) EntityWither.bo.get(i), j); + } + ++ public final boolean isPowered() { return this.S_(); } // Paper - OBFHELPER + public boolean S_() { + return this.getHealth() <= this.getMaxHealth() / 2.0F; + } +@@ -596,7 +602,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + + @Override + public boolean canPortal() { +- return false; ++ return super.canPortal() && canPortal; // Paper + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +index 1d94aeec37dcb9758d88ef25a5cad1333bbfbf6c..adf4ce8afa3a42ea8a184905969e03b6b756830f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +@@ -38,4 +38,31 @@ public class CraftWither extends CraftMonster implements Wither, com.destroystok + public BossBar getBossBar() { + return bossBar; + } ++ ++ // Paper start ++ @Override ++ public boolean isCharged() { ++ return getHandle().isPowered(); ++ } ++ ++ @Override ++ public int getInvulnerableTicks() { ++ return getHandle().getInvul(); ++ } ++ ++ @Override ++ public void setInvulnerableTicks(int ticks) { ++ getHandle().setInvul(ticks); ++ } ++ ++ @Override ++ public boolean canTravelThroughPortals() { ++ return getHandle().canPortal(); ++ } ++ ++ @Override ++ public void setCanTravelThroughPortals(boolean value) { ++ getHandle().setCanTravelThroughPortals(value); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/patches/server-unmapped/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch new file mode 100644 index 0000000000..8300eca18e --- /dev/null +++ b/patches/server-unmapped/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 24 Jun 2020 15:14:51 -0600 +Subject: [PATCH] Added firing of PlayerChangeBeaconEffectEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java b/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java +index 7e5a0bad616d9477e01426ab1604184ef3fab1c1..085298a9c3837dfa48dfbbf02d6261db12c79036 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java +@@ -13,6 +13,10 @@ import net.minecraft.world.entity.player.PlayerInventory; + import org.bukkit.craftbukkit.inventory.CraftInventoryView; + // CraftBukkit end + ++// Paper start ++import io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent; ++// Paper end ++ + public class ContainerBeacon extends Container { + + private final IInventory beacon; +@@ -139,9 +143,15 @@ public class ContainerBeacon extends Container { + + public void c(int i, int j) { + if (this.d.hasItem()) { +- this.containerProperties.setProperty(1, i); +- this.containerProperties.setProperty(2, j); ++ // Paper start ++ PlayerChangeBeaconEffectEvent event = new PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), org.bukkit.potion.PotionEffectType.getById(i), org.bukkit.potion.PotionEffectType.getById(j), this.containerAccess.getLocation().getBlock()); ++ if (event.callEvent()) { ++ this.containerProperties.setProperty(1, event.getPrimary() == null ? 0 : event.getPrimary().getId()); ++ this.containerProperties.setProperty(2, event.getSecondary() == null ? 0 : event.getSecondary().getId()); ++ if (!event.willConsumeItem()) return; + this.d.a(1); ++ } ++ // Paper end + } + + } diff --git a/patches/server-unmapped/0657-Fix-console-spam-when-removing-chests-in-water.patch b/patches/server-unmapped/0657-Fix-console-spam-when-removing-chests-in-water.patch new file mode 100644 index 0000000000..d05dbe7aff --- /dev/null +++ b/patches/server-unmapped/0657-Fix-console-spam-when-removing-chests-in-water.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Thu, 19 Nov 2020 02:07:10 +0000 +Subject: [PATCH] Fix console spam when removing chests in water + + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java +index b2c29cff5883868cb56a4e376ab946ac929abc94..a45ee959f41e7f349ff2c309f21fa44ec671cb87 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockChest.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java +@@ -239,7 +239,7 @@ public class BlockChest extends BlockChestAbstract implements I + @Override + public void remove(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { + if (!iblockdata.a(iblockdata1.getBlock())) { +- TileEntity tileentity = world.getTileEntity(blockposition); ++ TileEntity tileentity = world.getTileEntity(blockposition, false); // Paper - Don't validate TE - Fix console spam when removing chests in water + + if (tileentity instanceof IInventory) { + InventoryUtils.dropInventory(world, blockposition, (IInventory) tileentity); diff --git a/patches/server-unmapped/0658-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server-unmapped/0658-Add-toggle-for-always-placing-the-dragon-egg.patch new file mode 100644 index 0000000000..8f200eeb9d --- /dev/null +++ b/patches/server-unmapped/0658-Add-toggle-for-always-placing-the-dragon-egg.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 26 Nov 2020 11:47:24 +0000 +Subject: [PATCH] Add toggle for always placing the dragon egg + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index af7e93cb64eff1448653b27c2c9aea2d278d3ab7..cfe617e1a08b9c6e6c12bfe89bc9effd819eaff1 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -796,4 +796,9 @@ public class PaperWorldConfig { + if (value != -1) entityPerChunkSaveLimits.put(type, value); + }); + } ++ ++ public boolean enderDragonsDeathAlwaysPlacesDragonEgg = false; ++ private void enderDragonsDeathAlwaysPlacesDragonEgg() { ++ enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +index c0a6b340810b8ea4f454290b1ac22316ff0e6e22..80fcceec519ef59d057d27a81fcd0649a20447da 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +@@ -400,7 +400,7 @@ public class EnderDragonBattle { + this.bossBattle.setVisible(false); + this.generateExitPortal(true); + this.n(); +- if (!this.previouslyKilled) { ++ if (this.world.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg + this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); + } + diff --git a/patches/server-unmapped/0659-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server-unmapped/0659-Added-PlayerStonecutterRecipeSelectEvent.patch new file mode 100644 index 0000000000..6444ee5cbe --- /dev/null +++ b/patches/server-unmapped/0659-Added-PlayerStonecutterRecipeSelectEvent.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 27 Nov 2020 17:14:27 -0800 +Subject: [PATCH] Added PlayerStonecutterRecipeSelectEvent + +Co-Authored-By: MiniDigger + +diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java +index bdd00608a72dd81003731ff5fbe774dfdc5220e5..b58ec4abff2840556eb06e08b241a2eaa85c2c7f 100644 +--- a/src/main/java/net/minecraft/world/inventory/Container.java ++++ b/src/main/java/net/minecraft/world/inventory/Container.java +@@ -118,7 +118,7 @@ public abstract class Container { + return slot; + } + +- protected ContainerProperty a(ContainerProperty containerproperty) { ++ protected ContainerProperty addDataSlot(ContainerProperty containerproperty) { return a(containerproperty); } protected ContainerProperty a(ContainerProperty containerproperty) { // Paper - OBFHELPER + this.d.add(containerproperty); + return containerproperty; + } +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerProperty.java b/src/main/java/net/minecraft/world/inventory/ContainerProperty.java +index 67c3b7ddb0b0f10c82577cbea7506c9d80d41368..b9c82e68a811c2ef6bf2d5ce3ae9f858bcb263d5 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerProperty.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerProperty.java +@@ -20,7 +20,7 @@ public abstract class ContainerProperty { + }; + } + +- public static ContainerProperty a(final int[] aint, final int i) { ++ public static ContainerProperty shared(final int[] aint, final int i) { return a(aint, i); } public static ContainerProperty a(final int[] aint, final int i) { // Paper - OBFHELPER + return new ContainerProperty() { + @Override + public int get() { +@@ -54,7 +54,7 @@ public abstract class ContainerProperty { + + public abstract void set(int i); + +- public boolean c() { ++ public boolean checkAndClearUpdateFlag() { return c(); } public boolean c() { // Paper - OBFHELPER + int i = this.get(); + boolean flag = i != this.a; + +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java +index 1589d9ca201d386d11d9fd57fa8ba6848bae215c..dc667dd5d8514ae4c8a2087cb913f44320ebfc48 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java +@@ -22,13 +22,14 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; + import org.bukkit.craftbukkit.inventory.CraftInventoryView; + import org.bukkit.entity.Player; + // CraftBukkit end ++import io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent; // Paper + + public class ContainerStonecutter extends Container { + + private final ContainerAccess containerAccess; + private final ContainerProperty containerProperty; + private final World world; +- private List i; ++ private List i; public final List getRecipes() { return this.i; } // Paper - OBFHELPER + private ItemStack j; + private long k; + final Slot c; +@@ -58,7 +59,7 @@ public class ContainerStonecutter extends Container { + + public ContainerStonecutter(int i, PlayerInventory playerinventory, final ContainerAccess containeraccess) { + super(Containers.STONECUTTER, i); +- this.containerProperty = ContainerProperty.a(); ++ this.containerProperty = addDataSlot(ContainerProperty.shared(new int[1], 0)); // Paper - allow replication + this.i = Lists.newArrayList(); + this.j = ItemStack.b; + this.l = () -> { +@@ -136,13 +137,36 @@ public class ContainerStonecutter extends Container { + @Override + public boolean a(EntityHuman entityhuman, int i) { + if (this.d(i)) { +- this.containerProperty.set(i); ++ // Paper start ++ int recipeIndex = i; ++ this.containerProperty.set(recipeIndex); ++ this.containerProperty.checkAndClearUpdateFlag(); // mark as changed ++ if (this.isValidRecipeIndex(i)) { ++ PlayerStonecutterRecipeSelectEvent event = new PlayerStonecutterRecipeSelectEvent((Player) entityhuman.getBukkitEntity(), (org.bukkit.inventory.StonecutterInventory) getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) this.getRecipes().get(i).toBukkitRecipe()); ++ if (!event.callEvent()) { ++ ((Player) entityhuman.getBukkitEntity()).updateInventory(); ++ return false; ++ } ++ int newRecipeIndex; ++ if (!this.getRecipes().get(recipeIndex).getKey().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { // If the recipe did NOT stay the same ++ for (newRecipeIndex = 0; newRecipeIndex < this.getRecipes().size(); newRecipeIndex++) { ++ if (this.getRecipes().get(newRecipeIndex).getKey().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { ++ recipeIndex = newRecipeIndex; ++ break; ++ } ++ } ++ } ++ } ++ ((Player) entityhuman.getBukkitEntity()).updateInventory(); ++ this.containerProperty.set(recipeIndex); // set new index, so that listeners can read it ++ // Paper end + this.i(); + } + + return true; + } + ++ private boolean isValidRecipeIndex(int index) { return this.d(index); } // Paper - OBFHELPER + private boolean d(int i) { + return i >= 0 && i < this.i.size(); + } diff --git a/patches/server-unmapped/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/server-unmapped/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch new file mode 100644 index 0000000000..5677ee280f --- /dev/null +++ b/patches/server-unmapped/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch @@ -0,0 +1,156 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Fri, 29 Jan 2021 15:13:11 +0100 +Subject: [PATCH] Add dropLeash variable to EntityUnleashEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityCreature.java b/src/main/java/net/minecraft/world/entity/EntityCreature.java +index 20570580367697e37e6c45147168c3beb6c8d31b..831414980d40f4382cf7370db28dd8fae534384b 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityCreature.java ++++ b/src/main/java/net/minecraft/world/entity/EntityCreature.java +@@ -48,8 +48,11 @@ public abstract class EntityCreature extends EntityInsentient { + + if (this instanceof EntityTameableAnimal && ((EntityTameableAnimal) this).isSitting()) { + if (f > entity.world.paperConfig.maxLeashDistance) { // Paper +- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit +- this.unleash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); ++ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.unleash(true, event.isDropLeash()); ++ // Paper end + } + + return; +@@ -57,8 +60,11 @@ public abstract class EntityCreature extends EntityInsentient { + + this.x(f); + if (f > entity.world.paperConfig.maxLeashDistance) { // Paper +- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit +- this.unleash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); ++ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.unleash(true, event.isDropLeash()); ++ // Paper end + this.goalSelector.a(PathfinderGoal.Type.MOVE); + } else if (f > 6.0F) { + double d0 = (entity.locX() - this.locX()) / (double) f; +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index 969e5fa3080a98850f03ba64c5662c32a8d501a6..5c7fafeb7fab584eded30ebe415584132f4ab8af 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -88,6 +88,7 @@ import org.bukkit.event.entity.EntityTargetEvent; + import org.bukkit.event.entity.EntityTransformEvent; + import org.bukkit.event.entity.EntityUnleashEvent; + import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; ++import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper + // CraftBukkit end + + public abstract class EntityInsentient extends EntityLiving { +@@ -1207,12 +1208,15 @@ public abstract class EntityInsentient extends EntityLiving { + return EnumInteractionResult.PASS; + } else if (this.getLeashHolder() == entityhuman) { + // CraftBukkit start - fire PlayerUnleashEntityEvent +- if (CraftEventFactory.callPlayerUnleashEntityEvent(this, entityhuman).isCancelled()) { ++ // Paper start - drop leash variable ++ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, entityhuman, !entityhuman.abilities.canInstantlyBuild); ++ if (event.isCancelled()) { ++ // Paper end + ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutAttachEntity(this, this.getLeashHolder())); + return EnumInteractionResult.PASS; + } + // CraftBukkit end +- this.unleash(true, !entityhuman.abilities.canInstantlyBuild); ++ this.unleash(true, event.isDropLeash()); // Paper - drop leash variable + return EnumInteractionResult.a(this.world.isClientSide); + } else { + EnumInteractionResult enuminteractionresult = this.c(entityhuman, enumhand); +@@ -1366,8 +1370,11 @@ public abstract class EntityInsentient extends EntityLiving { + + if (this.leashHolder != null) { + if (!this.isAlive() || !this.leashHolder.isAlive()) { +- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit +- this.unleash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE, true); ++ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.unleash(true, event.isDropLeash()); ++ // Paper end + } + + } +@@ -1435,8 +1442,11 @@ public abstract class EntityInsentient extends EntityLiving { + boolean flag1 = super.a(entity, flag); + + if (flag1 && this.isLeashed()) { +- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit +- this.unleash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, true); ++ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.unleash(true, event.isDropLeash()); ++ // Paper end + } + + return flag1; +@@ -1638,7 +1648,10 @@ public abstract class EntityInsentient extends EntityLiving { + @Override + protected void bN() { + super.bN(); +- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit +- this.unleash(true, false); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, false); ++ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.unleash(true, event.isDropLeash()); ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java b/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java +index 8f6d2a6a388021f437ac5554e9ece8eca89e1f46..519f0cabadcf97a44a112fd963a8d3ab194650c4 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java +@@ -30,6 +30,8 @@ import net.minecraft.server.level.WorldServer; + import org.bukkit.craftbukkit.event.CraftEventFactory; + // CraftBukkit end + ++import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper ++ + public class EntityLeash extends EntityHanging { + + public EntityLeash(EntityTypes entitytypes, World world) { +@@ -125,11 +127,14 @@ public class EntityLeash extends EntityHanging { + entityinsentient = (EntityInsentient) iterator.next(); + if (entityinsentient.isLeashed() && entityinsentient.getLeashHolder() == this) { + // CraftBukkit start +- if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, entityhuman).isCancelled()) { ++ // Paper start - drop leash variable ++ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, entityhuman, !entityhuman.abilities.canInstantlyBuild); ++ if (event.isCancelled()) { ++ // Paper end + die = false; + continue; + } +- entityinsentient.unleash(true, !entityhuman.abilities.canInstantlyBuild); // false -> survival mode boolean ++ entityinsentient.unleash(true, event.isDropLeash()); // false -> survival mode boolean // Paper - drop leash variable + // CraftBukkit end + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index c109bbec67bd683077f0ab7331116a240a475827..e45a635b9d0948c71d5d3fcb317d2c8a228148ea 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1472,8 +1472,10 @@ public class CraftEventFactory { + return itemInHand; + } + +- public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(EntityInsentient entity, EntityHuman player) { +- PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity()); ++ // Paper start - drop leash variable ++ public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(EntityInsentient entity, EntityHuman player, boolean dropLeash) { ++ PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), dropLeash); ++ // Paper end + entity.world.getServer().getPluginManager().callEvent(event); + return event; + } diff --git a/patches/server-unmapped/0661-Skip-distance-map-update-when-spawning-disabled.patch b/patches/server-unmapped/0661-Skip-distance-map-update-when-spawning-disabled.patch new file mode 100644 index 0000000000..091e48b00a --- /dev/null +++ b/patches/server-unmapped/0661-Skip-distance-map-update-when-spawning-disabled.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Beech Horn +Date: Fri, 14 Feb 2020 19:39:59 +0000 +Subject: [PATCH] Skip distance map update when spawning disabled. + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +index 6770307d69c6b3934bfa804fd713cade22f0fb5c..4a71f9a8a57ed123b31c725a8bd5f94ab0e2174d 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +@@ -825,7 +825,7 @@ public class ChunkProviderServer extends IChunkProvider { + int l = this.chunkMapDistance.b(); + // Paper start - per player mob spawning + SpawnerCreature.d spawnercreature_d; // moved down +- if (this.playerChunkMap.playerMobDistanceMap != null) { ++ if ((this.allowAnimals || this.allowMonsters) && this.playerChunkMap.playerMobDistanceMap != null) { // don't update when animals and monsters are disabled + // update distance map + this.world.timings.playerMobDistanceMapUpdate.startTiming(); + this.playerChunkMap.playerMobDistanceMap.update(this.world.players, this.playerChunkMap.viewDistance); diff --git a/patches/server-unmapped/0662-Reset-shield-blocking-on-dimension-change.patch b/patches/server-unmapped/0662-Reset-shield-blocking-on-dimension-change.patch new file mode 100644 index 0000000000..93084291cf --- /dev/null +++ b/patches/server-unmapped/0662-Reset-shield-blocking-on-dimension-change.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Yive +Date: Sun, 24 Jan 2021 08:55:19 -0800 +Subject: [PATCH] Reset shield blocking on dimension change + + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index c0446ed3c7cc24fae2880dfba71228f5edee66d6..3f44d5b8e3bc4f897a5dda473532004078fe0ebe 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1118,6 +1118,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.world.getServer().getPluginManager().callEvent(changeEvent); + // CraftBukkit end + } ++ // Paper start ++ if (this.isBlocking()) { ++ this.clearActiveItem(); ++ } ++ // Paper end + + return this; + } diff --git a/patches/server-unmapped/0663-add-DragonEggFormEvent.patch b/patches/server-unmapped/0663-add-DragonEggFormEvent.patch new file mode 100644 index 0000000000..609439176d --- /dev/null +++ b/patches/server-unmapped/0663-add-DragonEggFormEvent.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Mon, 25 Jan 2021 14:53:57 +0100 +Subject: [PATCH] add DragonEggFormEvent + + +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +index 80fcceec519ef59d057d27a81fcd0649a20447da..0ab6319aa3e4e1f5679f37be36999ca56ca2484c 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +@@ -57,6 +57,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.WorldGenFeature + import net.minecraft.world.phys.AxisAlignedBB; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import io.papermc.paper.event.block.DragonEggFormEvent; // Paper - DragonEggFormEvent + + public class EnderDragonBattle { + +@@ -400,9 +401,24 @@ public class EnderDragonBattle { + this.bossBattle.setVisible(false); + this.generateExitPortal(true); + this.n(); ++ // Paper start - DragonEggFormEvent ++ BlockPosition eggPosition = this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.getPosition()); ++ org.bukkit.craftbukkit.block.CraftBlock eggBlock = org.bukkit.craftbukkit.block.CraftBlock.at(this.world, eggPosition); ++ org.bukkit.craftbukkit.block.CraftBlockState eggState = new org.bukkit.craftbukkit.block.CraftBlockState(eggBlock); ++ eggState.setData(Blocks.DRAGON_EGG.getBlockData()); ++ DragonEggFormEvent eggEvent = new DragonEggFormEvent(eggBlock, eggState, ++ new org.bukkit.craftbukkit.boss.CraftDragonBattle(this)); ++ // Paper end - DragonEggFormEvent + if (this.world.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg +- this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); ++ // Paper start - DragonEggFormEvent ++ //this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); ++ } else { ++ eggEvent.setCancelled(true); ++ } ++ if (eggEvent.callEvent()) { ++ eggEvent.getNewState().update(true); + } ++ // Paper end - DragonEggFormEvent + + this.previouslyKilled = true; + this.dragonKilled = true; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java +index 18395a3b4a7df1c99e952b9c8e738f165648eba5..851b8c2a86d7155278b49c44c6db8b1cbd2065f2 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java +@@ -14,7 +14,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.WorldGenFeature + + public class WorldGenEndTrophy extends WorldGenerator { + +- public static final BlockPosition a = BlockPosition.ZERO; ++ public static final BlockPosition a = BlockPosition.ZERO; public static BlockPosition getPosition() { return a; } // Paper - OBFHELPER + private final boolean ab; + + public WorldGenEndTrophy(boolean flag) { +@@ -22,7 +22,7 @@ public class WorldGenEndTrophy extends WorldGenerator +Date: Tue, 11 Feb 2020 21:56:48 -0600 +Subject: [PATCH] EntityMoveEvent + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index fe02a46df9c652acf4a4bc0ed194522f400cda34..454bc4c7b2e54a75dd0510263165e41cf26b1751 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -13,6 +13,7 @@ import io.netty.buffer.ByteBuf; + import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; + import io.papermc.paper.adventure.PaperAdventure; // Paper ++import io.papermc.paper.event.entity.EntityMoveEvent; + import it.unimi.dsi.fastutil.longs.LongIterator; + import java.awt.image.BufferedImage; + import java.io.BufferedWriter; +@@ -1460,6 +1461,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper ++ worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper + TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + + this.methodProfiler.a(() -> { +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index ac62e4e6842a474a1284ae7ac8890cc00b55aa64..9720f60d6a58df5f5a9b2c92e2209537aab7f010 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -213,6 +213,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + public final Convertable.ConversionSession convertable; + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper ++ public boolean hasEntityMoveEvent = false; // Paper + private static Throwable getAddToWorldStackTrace(Entity entity) { + return new Throwable(entity + " Added to world at " + new java.util.Date()); + } +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index b1adb0ddfeb94de6f92f40a7e9e586e00455160d..78d874c44cf8311af06b085db12fbe0cacd6cf7d 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -10,6 +10,7 @@ import com.mojang.datafixers.util.Pair; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import com.mojang.serialization.DynamicOps; ++import io.papermc.paper.event.entity.EntityMoveEvent; + import java.util.Collection; + import java.util.ConcurrentModificationException; + import java.util.Iterator; +@@ -2912,6 +2913,20 @@ public abstract class EntityLiving extends Entity { + + this.collideNearby(); + this.world.getMethodProfiler().exit(); ++ // Paper start ++ if (((WorldServer) world).hasEntityMoveEvent) { ++ if (lastX != locX() || lastY != locY() || lastZ != locZ() || lastYaw != yaw || lastPitch != pitch) { ++ Location from = new Location(world.getWorld(), lastX, lastY, lastZ, lastYaw, lastPitch); ++ Location to = new Location (world.getWorld(), locX(), locY(), locZ(), yaw, pitch); ++ EntityMoveEvent event = new EntityMoveEvent(getBukkitLivingEntity(), from, to.clone()); ++ if (!event.callEvent()) { ++ setLocation(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); ++ } else if (!to.equals(event.getTo())) { ++ setLocation(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); ++ } ++ } ++ } ++ // Paper end + if (!this.world.isClientSide && this.dO() && this.aG()) { + this.damageEntity(DamageSource.DROWN, 1.0F); + } diff --git a/patches/server-unmapped/0665-added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server-unmapped/0665-added-option-to-disable-pathfinding-updates-on-block.patch new file mode 100644 index 0000000000..972a1dc051 --- /dev/null +++ b/patches/server-unmapped/0665-added-option-to-disable-pathfinding-updates-on-block.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas81298 +Date: Mon, 25 Jan 2021 14:37:57 +0100 +Subject: [PATCH] added option to disable pathfinding updates on block changes + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index cfe617e1a08b9c6e6c12bfe89bc9effd819eaff1..f1d384d2e235c52a00f4b6d5643ef3c1d163e94b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -801,4 +801,9 @@ public class PaperWorldConfig { + private void enderDragonsDeathAlwaysPlacesDragonEgg() { + enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); + } ++ ++ public boolean updatePathfindingOnBlockUpdate = true; ++ private void setUpdatePathfindingOnBlockUpdate() { ++ updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 9720f60d6a58df5f5a9b2c92e2209537aab7f010..fd204ab68d8245503c0a8c4e7ce1a0a6bac7d138 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1684,6 +1684,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + @Override + public void notify(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1, int i) { + this.getChunkProvider().flagDirty(blockposition); ++ if(this.paperConfig.updatePathfindingOnBlockUpdate) { // Paper - option to disable pathfinding updates + VoxelShape voxelshape = iblockdata.getCollisionShape(this, blockposition); + VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition); + +@@ -1712,6 +1713,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + this.tickingEntities = wasTicking; // Paper + } ++ } // Paper + } + + @Override diff --git a/patches/server-unmapped/0666-Inline-shift-direction-fields.patch b/patches/server-unmapped/0666-Inline-shift-direction-fields.patch new file mode 100644 index 0000000000..e044ac5972 --- /dev/null +++ b/patches/server-unmapped/0666-Inline-shift-direction-fields.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Mon, 18 Jan 2021 20:45:25 -0500 +Subject: [PATCH] Inline shift direction fields + +Removes a layer of indirection for EnumDirection.getAdjacent(X|Y|Z)(), which is in the +critical section for much of the server, including the lighting engine. + +diff --git a/src/main/java/net/minecraft/core/EnumDirection.java b/src/main/java/net/minecraft/core/EnumDirection.java +index a699005582293326076eaa80655c5343e6c22ff0..703bdefeb615ef8d15b428a893b5e4939d726f13 100644 +--- a/src/main/java/net/minecraft/core/EnumDirection.java ++++ b/src/main/java/net/minecraft/core/EnumDirection.java +@@ -53,6 +53,11 @@ public enum EnumDirection implements INamable { + }, (enumdirection, enumdirection1) -> { + throw new IllegalArgumentException("Duplicate keys"); + }, Long2ObjectOpenHashMap::new)); ++ // Paper start ++ private final int adjX; ++ private final int adjY; ++ private final int adjZ; ++ // Paper end + + private EnumDirection(int i, int j, int k, String s, EnumDirection.EnumAxisDirection enumdirection_enumaxisdirection, EnumDirection.EnumAxis enumdirection_enumaxis, BaseBlockPosition baseblockposition) { + this.g = i; +@@ -62,6 +67,11 @@ public enum EnumDirection implements INamable { + this.k = enumdirection_enumaxis; + this.l = enumdirection_enumaxisdirection; + this.m = baseblockposition; ++ // Paper start ++ this.adjX = baseblockposition.getX(); ++ this.adjY = baseblockposition.getY(); ++ this.adjZ = baseblockposition.getZ(); ++ // Paper end + } + + public static EnumDirection[] a(Entity entity) { +@@ -137,15 +147,15 @@ public enum EnumDirection implements INamable { + } + + public int getAdjacentX() { +- return this.m.getX(); ++ return this.adjX; // Paper + } + + public int getAdjacentY() { +- return this.m.getY(); ++ return this.adjY; // Paper + } + + public int getAdjacentZ() { +- return this.m.getZ(); ++ return this.adjZ; // Paper + } + + public String m() { diff --git a/patches/server-unmapped/0667-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server-unmapped/0667-Allow-adding-items-to-BlockDropItemEvent.patch new file mode 100644 index 0000000000..dda47780e0 --- /dev/null +++ b/patches/server-unmapped/0667-Allow-adding-items-to-BlockDropItemEvent.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Wed, 20 Jan 2021 14:23:37 -0600 +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 e45a635b9d0948c71d5d3fcb317d2c8a228148ea..a678277416cd71e01cd6980bcfaf9a9803e7ea17 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -401,13 +401,30 @@ public class CraftEventFactory { + } + + public static void handleBlockDropItemEvent(Block block, BlockState state, EntityPlayer player, List items) { +- BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), Lists.transform(items, (item) -> (org.bukkit.entity.Item) item.getBukkitEntity())); ++ // Paper start ++ List list = new ArrayList<>(); ++ for (EntityItem item : items) { ++ list.add((Item) item.getBukkitEntity()); ++ } ++ BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), list); ++ // Paper end + Bukkit.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { +- for (EntityItem item : items) { +- item.world.addEntity(item); ++ // Paper start ++ for (Item bukkit : list) { ++ if (!bukkit.isValid()) { ++ Entity item = ((org.bukkit.craftbukkit.entity.CraftItem) bukkit).getHandle(); ++ item.world.addEntity(item); ++ } ++ } ++ } else { ++ for (Item bukkit : list) { ++ if (bukkit.isValid()) { ++ bukkit.remove(); ++ } + } ++ // Paper end + } + } + diff --git a/patches/server-unmapped/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/server-unmapped/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch new file mode 100644 index 0000000000..f2acd9e212 --- /dev/null +++ b/patches/server-unmapped/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aleksander Jagiello +Date: Sun, 24 Jan 2021 22:17:54 +0100 +Subject: [PATCH] Add getMainThreadExecutor to BukkitScheduler + + +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 13e461ffb2ee2e7d0440c0f60809ea99629b843c..0be39dac4b9dd69d7d73d86d64cf1e33e4086e81 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -635,4 +635,15 @@ public class CraftScheduler implements BukkitScheduler { + public BukkitTask runTaskTimerAsynchronously(Plugin plugin, BukkitRunnable task, long delay, long period) throws IllegalArgumentException { + throw new UnsupportedOperationException("Use BukkitRunnable#runTaskTimerAsynchronously(Plugin, long, long)"); + } ++ ++ // Paper start - add getMainThreadExecutor ++ @Override ++ public Executor getMainThreadExecutor(Plugin plugin) { ++ Validate.notNull(plugin, "Plugin cannot be null"); ++ return command -> { ++ Validate.notNull(command, "Command cannot be null"); ++ this.runTask(plugin, command); ++ }; ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0669-living-entity-allow-attribute-registration.patch b/patches/server-unmapped/0669-living-entity-allow-attribute-registration.patch new file mode 100644 index 0000000000..d30fda385f --- /dev/null +++ b/patches/server-unmapped/0669-living-entity-allow-attribute-registration.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ysl3000 +Date: Sat, 24 Oct 2020 16:37:44 +0200 +Subject: [PATCH] living entity allow attribute registration + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java +index 8f6b78c68da555f96033df567da581af52195e6c..e4cd1848e8700de4ab64f3037bb0c41d99e7c97d 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java ++++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java +@@ -21,7 +21,7 @@ import org.apache.logging.log4j.Logger; + public class AttributeMapBase { + + private static final Logger LOGGER = LogManager.getLogger(); +- private final Map b = Maps.newHashMap(); ++ private final Map b = Maps.newHashMap(); private final Map attributeMap = b; // Paper - OBFHELPER + private final Set c = Sets.newHashSet(); + private final AttributeProvider d; + +@@ -135,4 +135,12 @@ public class AttributeMapBase { + } + + } ++ ++ // Paper - start ++ public void registerAttribute(AttributeBase attributeBase) { ++ AttributeModifiable attributeModifiable = new AttributeModifiable(attributeBase, AttributeModifiable::getAttribute); ++ attributeMap.put(attributeBase, attributeModifiable); ++ } ++ // Paper - end ++ + } +diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +index 673948947bd918c1dbb6c4c99486b4200e3c09fe..2e83b8855070077e90e5ab2c4beae819c620e480 100644 +--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java ++++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +@@ -40,6 +40,14 @@ public class CraftAttributeMap implements Attributable { + return (nms == null) ? null : new CraftAttributeInstance(nms, attribute); + } + ++ // Paper start ++ @Override ++ public void registerAttribute(Attribute attribute) { ++ Preconditions.checkArgument(attribute != null, "attribute"); ++ handle.registerAttribute(CraftAttributeMap.toMinecraft(attribute)); ++ } ++ // Paper end ++ + public static AttributeBase toMinecraft(Attribute attribute) { + return IRegistry.ATTRIBUTE.get(CraftNamespacedKey.toMinecraft(attribute.getKey())); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 278a1c886f15b75e62bfe4c872fc779eda83c988..9865eee8ec5e43f291968bfb2c4473260e5baf7c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -675,6 +675,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return getHandle().craftAttributes.getAttribute(attribute); + } + ++ // Paper start ++ @Override ++ public void registerAttribute(Attribute attribute) { ++ getHandle().craftAttributes.registerAttribute(attribute); ++ } ++ // Paper end ++ + @Override + public void setAI(boolean ai) { + if (this.getHandle() instanceof EntityInsentient) { diff --git a/patches/server-unmapped/0670-fix-dead-slime-setSize-invincibility.patch b/patches/server-unmapped/0670-fix-dead-slime-setSize-invincibility.patch new file mode 100644 index 0000000000..33f5d17581 --- /dev/null +++ b/patches/server-unmapped/0670-fix-dead-slime-setSize-invincibility.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Fri, 5 Feb 2021 22:12:13 +0100 +Subject: [PATCH] fix dead slime setSize invincibility + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +index cf5c6030105e56813f526e710e5db0c59d88c99e..13ab1a430f9ad2ece73ab50455bfcddbc9b236e2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +@@ -18,7 +18,7 @@ public class CraftSlime extends CraftMob implements Slime { + + @Override + public void setSize(int size) { +- getHandle().setSize(size, true); ++ getHandle().setSize(size, /* true */ getHandle().isAlive()); // Paper - fix dead slime setSize invincibility + } + + @Override diff --git a/patches/server-unmapped/0671-Merchant-getRecipes-should-return-an-immutable-list.patch b/patches/server-unmapped/0671-Merchant-getRecipes-should-return-an-immutable-list.patch new file mode 100644 index 0000000000..f368eba156 --- /dev/null +++ b/patches/server-unmapped/0671-Merchant-getRecipes-should-return-an-immutable-list.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Wed, 10 Feb 2021 14:53:36 -0800 +Subject: [PATCH] Merchant#getRecipes should return an immutable list + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java +index 00d43e4a77ed03bc9672cbaccad50b48aed0fb93..3c66d9217eb0b60595a59e2f296de332095d4a4c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java +@@ -25,7 +25,7 @@ public class CraftMerchant implements Merchant { + + @Override + public List getRecipes() { +- return Collections.unmodifiableList(Lists.transform(merchant.getOffers(), new Function() { ++ return com.google.common.collect.ImmutableList.copyOf(Lists.transform(merchant.getOffers(), new Function() { // Paper - javadoc says 'an immutable list of trades' - not 'an unmodifiable view of a list of trades'. fixes issue with setRecipes(getRecipes()) + @Override + public MerchantRecipe apply(net.minecraft.world.item.trading.MerchantRecipe recipe) { + return recipe.asBukkit(); diff --git a/patches/server-unmapped/0672-misc-debugging-dumps.patch b/patches/server-unmapped/0672-misc-debugging-dumps.patch new file mode 100644 index 0000000000..da0840fc4c --- /dev/null +++ b/patches/server-unmapped/0672-misc-debugging-dumps.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 18 Feb 2021 20:23:28 +0000 +Subject: [PATCH] misc debugging dumps + + +diff --git a/src/main/java/io/papermc/paper/util/TraceUtil.java b/src/main/java/io/papermc/paper/util/TraceUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2d5494d2813b773e60ddba6790b750a9a08f21f8 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/util/TraceUtil.java +@@ -0,0 +1,18 @@ ++package io.papermc.paper.util; ++ ++import org.bukkit.Bukkit; ++ ++public final class TraceUtil { ++ ++ public static void dumpTraceForThread(Thread thread, String reason) { ++ Bukkit.getLogger().warning(thread.getName() + ": " + reason); ++ StackTraceElement[] trace = thread.getStackTrace(); ++ for (StackTraceElement traceElement : trace) { ++ Bukkit.getLogger().warning("\tat " + traceElement); ++ } ++ } ++ ++ public static void dumpTraceForThread(String reason) { ++ new Throwable(reason).printStackTrace(); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 454bc4c7b2e54a75dd0510263165e41cf26b1751..879074df54e56a9275957a83c92b467094e95cd4 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -14,6 +14,7 @@ import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; + import io.papermc.paper.adventure.PaperAdventure; // Paper + import io.papermc.paper.event.entity.EntityMoveEvent; ++import io.papermc.paper.util.TraceUtil; + import it.unimi.dsi.fastutil.longs.LongIterator; + import java.awt.image.BufferedImage; + import java.io.BufferedWriter; +@@ -857,6 +858,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant +Date: Sat, 20 Feb 2021 13:09:59 -0500 +Subject: [PATCH] Add support for hex color codes in console + +Converts upstream's hex color code legacy format into actual hex color codes in the console. + +diff --git a/src/main/java/io/papermc/paper/console/HexFormattingConverter.java b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a4315961b7a465fb4872a4d67e7c26d4b4ed1fb9 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java +@@ -0,0 +1,178 @@ ++package io.papermc.paper.console; ++ ++import net.minecrell.terminalconsole.TerminalConsoleAppender; ++import org.apache.logging.log4j.core.LogEvent; ++import org.apache.logging.log4j.core.config.Configuration; ++import org.apache.logging.log4j.core.config.plugins.Plugin; ++import org.apache.logging.log4j.core.layout.PatternLayout; ++import org.apache.logging.log4j.core.pattern.*; ++import org.apache.logging.log4j.util.PerformanceSensitive; ++import org.apache.logging.log4j.util.PropertiesUtil; ++ ++import java.util.List; ++import java.util.regex.Matcher; ++import java.util.regex.Pattern; ++ ++import static net.minecrell.terminalconsole.MinecraftFormattingConverter.KEEP_FORMATTING_PROPERTY; ++ ++/** ++ * Modified version of ++ * TerminalConsoleAppender's MinecraftFormattingConverter to support hex color codes using the md_5 &x&r&r&g&g&b&b format. ++ */ ++@Plugin(name = "paperMinecraftFormatting", category = PatternConverter.CATEGORY) ++@ConverterKeys({ "paperMinecraftFormatting" }) ++@PerformanceSensitive("allocation") ++public final class HexFormattingConverter extends LogEventPatternConverter { ++ ++ private static final boolean KEEP_FORMATTING = PropertiesUtil.getProperties().getBooleanProperty(KEEP_FORMATTING_PROPERTY); ++ ++ private static final String ANSI_RESET = "\u001B[m"; ++ ++ private static final char COLOR_CHAR = '§'; ++ private static final String LOOKUP = "0123456789abcdefklmnor"; ++ ++ private static final String RGB_ANSI = "\u001B[38;2;%d;%d;%dm"; ++ private static final Pattern NAMED_PATTERN = Pattern.compile(COLOR_CHAR + "[0-9a-fk-orA-FK-OR]"); ++ private static final Pattern RGB_PATTERN = Pattern.compile(COLOR_CHAR + "x(" + COLOR_CHAR + "[0-9a-fA-F]){6}"); ++ ++ private static final String[] ansiCodes = new String[] { ++ "\u001B[0;30m", // Black §0 ++ "\u001B[0;34m", // Dark Blue §1 ++ "\u001B[0;32m", // Dark Green §2 ++ "\u001B[0;36m", // Dark Aqua §3 ++ "\u001B[0;31m", // Dark Red §4 ++ "\u001B[0;35m", // Dark Purple §5 ++ "\u001B[0;33m", // Gold §6 ++ "\u001B[0;37m", // Gray §7 ++ "\u001B[0;30;1m", // Dark Gray §8 ++ "\u001B[0;34;1m", // Blue §9 ++ "\u001B[0;32;1m", // Green §a ++ "\u001B[0;36;1m", // Aqua §b ++ "\u001B[0;31;1m", // Red §c ++ "\u001B[0;35;1m", // Light Purple §d ++ "\u001B[0;33;1m", // Yellow §e ++ "\u001B[0;37;1m", // White §f ++ "\u001B[5m", // Obfuscated §k ++ "\u001B[21m", // Bold §l ++ "\u001B[9m", // Strikethrough §m ++ "\u001B[4m", // Underline §n ++ "\u001B[3m", // Italic §o ++ ANSI_RESET, // Reset §r ++ }; ++ ++ private final boolean ansi; ++ private final List formatters; ++ ++ /** ++ * Construct the converter. ++ * ++ * @param formatters The pattern formatters to generate the text to manipulate ++ * @param strip If true, the converter will strip all formatting codes ++ */ ++ protected HexFormattingConverter(List formatters, boolean strip) { ++ super("paperMinecraftFormatting", null); ++ this.formatters = formatters; ++ this.ansi = !strip; ++ } ++ ++ @Override ++ public void format(LogEvent event, StringBuilder toAppendTo) { ++ int start = toAppendTo.length(); ++ //noinspection ForLoopReplaceableByForEach ++ for (int i = 0, size = formatters.size(); i < size; i++) { ++ formatters.get(i).format(event, toAppendTo); ++ } ++ ++ if (KEEP_FORMATTING || toAppendTo.length() == start) { ++ // Skip replacement if disabled or if the content is empty ++ return; ++ } ++ ++ boolean useAnsi = ansi && TerminalConsoleAppender.isAnsiSupported(); ++ String content = toAppendTo.substring(start); ++ content = useAnsi ? convertRGBColors(content) : stripRGBColors(content); ++ format(content, toAppendTo, start, useAnsi); ++ } ++ ++ private static String convertRGBColors(String input) { ++ Matcher matcher = RGB_PATTERN.matcher(input); ++ StringBuffer buffer = new StringBuffer(); ++ while (matcher.find()) { ++ String s = matcher.group().replace(String.valueOf(COLOR_CHAR), "").replace('x', '#'); ++ int hex = Integer.decode(s); ++ int red = (hex >> 16) & 0xFF; ++ int green = (hex >> 8) & 0xFF; ++ int blue = hex & 0xFF; ++ String replacement = String.format(RGB_ANSI, red, green, blue); ++ matcher.appendReplacement(buffer, replacement); ++ } ++ matcher.appendTail(buffer); ++ return buffer.toString(); ++ } ++ ++ private static String stripRGBColors(String input) { ++ Matcher matcher = RGB_PATTERN.matcher(input); ++ StringBuffer buffer = new StringBuffer(); ++ while (matcher.find()) { ++ matcher.appendReplacement(buffer, ""); ++ } ++ matcher.appendTail(buffer); ++ return buffer.toString(); ++ } ++ ++ static void format(String content, StringBuilder result, int start, boolean ansi) { ++ int next = content.indexOf(COLOR_CHAR); ++ int last = content.length() - 1; ++ if (next == -1 || next == last) { ++ result.setLength(start); ++ result.append(content); ++ if (ansi) { ++ result.append(ANSI_RESET); ++ } ++ return; ++ } ++ ++ Matcher matcher = NAMED_PATTERN.matcher(content); ++ StringBuffer buffer = new StringBuffer(); ++ while (matcher.find()) { ++ int format = LOOKUP.indexOf(Character.toLowerCase(matcher.group().charAt(1))); ++ if (format != -1) { ++ matcher.appendReplacement(buffer, ansi ? ansiCodes[format] : ""); ++ } ++ } ++ matcher.appendTail(buffer); ++ ++ result.setLength(start); ++ result.append(buffer.toString()); ++ if (ansi) { ++ result.append(ANSI_RESET); ++ } ++ } ++ ++ /** ++ * Gets a new instance of the {@link HexFormattingConverter} with the ++ * specified options. ++ * ++ * @param config The current configuration ++ * @param options The pattern options ++ * @return The new instance ++ * ++ * @see HexFormattingConverter ++ */ ++ public static HexFormattingConverter newInstance(Configuration config, String[] options) { ++ if (options.length < 1 || options.length > 2) { ++ LOGGER.error("Incorrect number of options on paperMinecraftFormatting. Expected at least 1, max 2 received " + options.length); ++ return null; ++ } ++ if (options[0] == null) { ++ LOGGER.error("No pattern supplied on paperMinecraftFormatting"); ++ return null; ++ } ++ ++ PatternParser parser = PatternLayout.createPatternParser(config); ++ List formatters = parser.parse(options[0]); ++ boolean strip = options.length > 1 && "strip".equals(options[1]); ++ return new HexFormattingConverter(formatters, strip); ++ } ++ ++} +diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml +index 8af159abd3d0cc94cf155fec5b384c42f69551bf..67da1aa7a21622fb231d19dede3775a282a4a12e 100644 +--- a/src/main/resources/log4j2.xml ++++ b/src/main/resources/log4j2.xml +@@ -6,21 +6,21 @@ + + + +- ++ + + + ++ pattern="%highlightError{[%d{HH:mm:ss} %level]: %paperMinecraftFormatting{%msg}%n%xEx{full}}" /> + + + + + +- ++ + + + ++ pattern="[%d{HH:mm:ss}] [%t/%level]: %paperMinecraftFormatting{%msg}{strip}%n%xEx{full}" /> + + + diff --git a/patches/server-unmapped/0674-Clear-SyncLoadInfo.patch b/patches/server-unmapped/0674-Clear-SyncLoadInfo.patch new file mode 100644 index 0000000000..5f1ef784b9 --- /dev/null +++ b/patches/server-unmapped/0674-Clear-SyncLoadInfo.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tom +Date: Fri, 26 Feb 2021 16:10:53 -0600 +Subject: [PATCH] Clear SyncLoadInfo + +This patch merely adds the extra argument "clear" after /paper syncloadinfo to clear currently stored syncload info. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java +index 4b3efe01750d79bcc27a42b5a145d9aa6b124d18..12313a37ceeb6a0b6a539c38fdba67e5e43d7413 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java ++++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java +@@ -295,6 +295,13 @@ public class PaperCommand extends Command { + sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); + return; + } ++ ++ if (args.length > 1 && args[1].equals("clear")) { ++ SyncLoadFinder.clear(); ++ sender.sendMessage(ChatColor.GRAY + "Sync load data cleared."); ++ return; ++ } ++ + File file = new File(new File(new File("."), "debug"), + "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); + file.getParentFile().mkdirs(); +diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java +index d381f91cf105bfc01846ada90da8971a3618e784..c51401bcfac0a1e45099af1dd355073c19790476 100644 +--- a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java ++++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java +@@ -26,6 +26,10 @@ public class SyncLoadFinder { + public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); + } + ++ public static void clear() { ++ SYNC_LOADS.clear(); ++ } ++ + public static void logSyncLoad(final World world, final int chunkX, final int chunkZ) { + if (!ENABLED) { + return; diff --git a/patches/server-unmapped/0675-Expose-Tracked-Players.patch b/patches/server-unmapped/0675-Expose-Tracked-Players.patch new file mode 100644 index 0000000000..2ee6abd643 --- /dev/null +++ b/patches/server-unmapped/0675-Expose-Tracked-Players.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tom +Date: Fri, 26 Feb 2021 16:24:25 -0600 +Subject: [PATCH] Expose Tracked Players + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 881db84a1afe2da5d30732c282f36b294c721c41..d62179765f93738e8444b507238b4fd79a1e9443 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -172,7 +172,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper + private CraftEntity bukkitEntity; + +- PlayerChunkMap.EntityTracker tracker; // Paper ++ public PlayerChunkMap.EntityTracker tracker; // Paper package private -> public + public boolean collisionLoadChunks = false; // Paper + public Throwable addedToWorldStack; // Paper - entity debug + public CraftEntity getBukkitEntity() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index e81de526a847c730abf86016354c1dc57780ec8b..05248f560d643080a3eac581c01aa89fb3709e6c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -16,6 +16,7 @@ import java.net.InetSocketAddress; + import java.net.SocketAddress; + import java.util.ArrayList; + import java.util.Collection; ++import java.util.Collections; // Paper + import java.util.HashMap; + import java.util.HashSet; + import java.util.LinkedHashMap; +@@ -2309,6 +2310,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + // Paper end + ++ // Paper start ++ @Override ++ public Set getTrackedPlayers() { ++ if (entity.tracker == null) { ++ return Collections.emptySet(); ++ } ++ ++ Set set = new HashSet<>(entity.tracker.trackedPlayers.size()); ++ for (EntityPlayer entityPlayer : entity.tracker.trackedPlayers) { ++ set.add(entityPlayer.getBukkitEntity().getPlayer()); ++ } ++ return set; ++ } ++ // Paper end ++ + // Spigot start + private final Player.Spigot spigot = new Player.Spigot() + { diff --git a/patches/server-unmapped/0676-Remove-streams-from-SensorNearest.patch b/patches/server-unmapped/0676-Remove-streams-from-SensorNearest.patch new file mode 100644 index 0000000000..d5ee1c60ca --- /dev/null +++ b/patches/server-unmapped/0676-Remove-streams-from-SensorNearest.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Bjarne Koll +Date: Wed, 3 Mar 2021 12:48:48 +0100 +Subject: [PATCH] Remove streams from SensorNearest + +The behavioural nearby sensors are validated every tick on the entities +that registered the respective sensors and are therefore a good subject +to performance improvements. + +More specifically this commit replaces the Stream#filter usage with +ArrayList#removeIf as the removeIf method on an array list is heavily +optimized towards a single internal array re-allocation without any +further overhead on the removeIf call. + +The only negative of this change is the rather agressive diff these +patches introduce as the methods are basically being reimplemented +compared to the previous stream-based implementation. + +See: https://nipafx.dev/java-stream-performance/ + +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java +index 418cd6d8b40d35aa3be73eb12f2e3b75597238b9..2e3149a0b15299468079796bd3ea56eabdb4998c 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java +@@ -27,18 +27,16 @@ public class SensorNearestItems extends Sensor { + List list = worldserver.a(EntityItem.class, entityinsentient.getBoundingBox().grow(8.0D, 4.0D, 8.0D), (entityitem) -> { + return true; + }); +- +- entityinsentient.getClass(); ++ // Paper start - remove streams in favour of lists + list.sort(Comparator.comparingDouble(entityinsentient::h)); +- Stream stream = list.stream().filter((entityitem) -> { +- return entityinsentient.i(entityitem.getItemStack()); +- }).filter((entityitem) -> { +- return entityitem.a((Entity) entityinsentient, 9.0D); +- }); +- +- entityinsentient.getClass(); +- Optional optional = stream.filter(entityinsentient::hasLineOfSight).findFirst(); +- +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); ++ EntityItem nearest = null; ++ for (EntityItem entityItem : list) { ++ if (entityinsentient.i(entityItem.getItemStack()) && entityItem.a(entityinsentient, 9.0D) && entityinsentient.hasLineOfSight(entityItem)) { ++ nearest = entityItem; ++ break; ++ } ++ } ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java +index d3bb1c02d80fcd3586030b07f84e7ebdd97d873e..0bc17d148e91277efdf72541e5470fa56d455670 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java +@@ -26,10 +26,12 @@ public class SensorNearestLivingEntities extends Sensor { + list.sort(Comparator.comparingDouble(entityliving::h)); + BehaviorController behaviorcontroller = entityliving.getBehaviorController(); + +- behaviorcontroller.setMemory(MemoryModuleType.MOBS, (Object) list); +- behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, list.stream().filter((entityliving1) -> { +- return a(entityliving, entityliving1); +- }).collect(Collectors.toList())); ++ behaviorcontroller.setMemory(MemoryModuleType.MOBS, list); // Paper - decompile error ++ // Paper start - remove streams in favour of lists ++ List visibleMobs = new java.util.ArrayList<>(list); ++ visibleMobs.removeIf(otherEntityLiving -> !Sensor.a(entityliving, otherEntityLiving)); ++ behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, visibleMobs); ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java +index 29abc7feec5358dce7d16958f0c5807f4bda992f..60e4da9217d4d950b5077baf6b50eaee20f8df09 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java +@@ -26,22 +26,26 @@ public class SensorNearestPlayers extends Sensor { + + @Override + protected void a(WorldServer worldserver, EntityLiving entityliving) { +- Stream stream = worldserver.getPlayers().stream().filter(IEntitySelector.g).filter((entityplayer) -> { +- return entityliving.a((Entity) entityplayer, 16.0D); +- }); ++ // Paper start - remove streams in favour of lists ++ List players = new java.util.ArrayList<>(worldserver.getPlayers()); ++ players.removeIf(player -> !IEntitySelector.notSpectator().test(player) || !entityliving.a(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator ++ players.sort(Comparator.comparingDouble(entityliving::h)); + +- entityliving.getClass(); +- List list = (List) stream.sorted(Comparator.comparingDouble(entityliving::h)).collect(Collectors.toList()); + BehaviorController behaviorcontroller = entityliving.getBehaviorController(); +- +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, (Object) list); +- List list1 = (List) list.stream().filter((entityhuman) -> { +- return a(entityliving, (EntityLiving) entityhuman); +- }).collect(Collectors.toList()); +- +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, (Object) (list1.isEmpty() ? null : (EntityHuman) list1.get(0))); +- Optional optional = list1.stream().filter(IEntitySelector.f).findFirst(); +- +- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, optional); ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); ++ ++ EntityHuman nearest = null, nearestTargetable = null; ++ for (EntityHuman player : players) { ++ if (Sensor.a(entityliving, player)) { ++ if (nearest == null) nearest = player; ++ if (IEntitySelector.canAITarget().test(player)) { ++ nearestTargetable = player; ++ break; // Both variables are assigned, no reason to loop further ++ } ++ } ++ } ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); ++ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, nearestTargetable); ++ // Paper end + } + } diff --git a/patches/server-unmapped/0677-do-not-create-unnecessary-copies-of-passenger-list.patch b/patches/server-unmapped/0677-do-not-create-unnecessary-copies-of-passenger-list.patch new file mode 100644 index 0000000000..98382964ad --- /dev/null +++ b/patches/server-unmapped/0677-do-not-create-unnecessary-copies-of-passenger-list.patch @@ -0,0 +1,239 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas81298 +Date: Sun, 13 Dec 2020 13:42:55 +0100 +Subject: [PATCH] do not create unnecessary copies of passenger list + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java +index edc6fff87c4abad2c123b1a46d6e5b792602b3be..5e739b26b6b5490b2c7651d3e9ff8649e776137e 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java +@@ -15,7 +15,7 @@ public class PacketPlayOutMount implements Packet { + + public PacketPlayOutMount(Entity entity) { + this.a = entity.getId(); +- List list = entity.getPassengers(); ++ List list = entity.passengers; // Paper - do not create a copy of the list + + this.b = new int[list.size()]; + +diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +index 58dd349adf2bc9bac6569464ef7a7aec81729e79..1df8fb8cb3fcf8201e1c5fa8ca13f7a9c632c379 100644 +--- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java ++++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java +@@ -103,10 +103,10 @@ public class EntityTrackerEntry { + + public final void tick() { this.a(); } // Paper - OBFHELPER + public void a() { +- List list = this.tracker.getPassengers(); ++ List list = this.tracker.passengers; // Paper - do not copy list + + if (!list.equals(this.p)) { +- this.p = list; ++ this.p = com.google.common.collect.ImmutableList.copyOf(list); // Paper - only copy list if something has changed + this.broadcastIncludingSelf(new PacketPlayOutMount(this.tracker)); // CraftBukkit + } + +@@ -376,7 +376,7 @@ public class EntityTrackerEntry { + } + } + +- if (!this.tracker.getPassengers().isEmpty()) { ++ if (!this.tracker.passengers.isEmpty()) { // Paper - do not create copy of list + consumer.accept(new PacketPlayOutMount(this.tracker)); + } + +diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +index 169fa174f86f8a8dc42d3b9c4954a39d0a738c06..6835401bd7863bbd655502547a9fd4ae0f298da1 100644 +--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +@@ -2315,7 +2315,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + list.add(entity); + } + +- if (!entity.getPassengers().isEmpty()) { ++ if (!entity.passengers.isEmpty()) { // Paper - do not copy list + list1.add(entity); + } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d62179765f93738e8444b507238b4fd79a1e9443..89b2be0e9e42d65b7d2d2833de4e6cd1c6e17e8e 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2235,7 +2235,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + protected boolean q(Entity entity) { +- return this.getPassengers().size() < 1; ++ return this.passengers.size() < 1; // Paper - do not copy list + } + + public final float getCollisionBorderSize() { return bg(); } // Paper - OBFHELPER +@@ -2331,7 +2331,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public boolean isVehicle() { +- return !this.getPassengers().isEmpty(); ++ return !this.passengers.isEmpty(); // Paper - do not copy list + } + + public boolean bt() { +@@ -3143,7 +3143,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public boolean w(Entity entity) { +- Iterator iterator = this.getPassengers().iterator(); ++ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list + + Entity entity1; + +@@ -3159,7 +3159,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public boolean a(Class oclass) { +- Iterator iterator = this.getPassengers().iterator(); ++ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list + + Entity entity; + +@@ -3176,7 +3176,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + public Collection getAllPassengers() { + Set set = Sets.newHashSet(); +- Iterator iterator = this.getPassengers().iterator(); ++ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +@@ -3202,7 +3202,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + private void a(boolean flag, Set set) { + Entity entity; + +- for (Iterator iterator = this.getPassengers().iterator(); iterator.hasNext(); entity.a(flag, set)) { ++ for (Iterator iterator = this.passengers.iterator(); iterator.hasNext(); entity.a(flag, set)) { // Paper - do not copy list + entity = (Entity) iterator.next(); + if (!flag || EntityPlayer.class.isAssignableFrom(entity.getClass())) { + set.add(entity); +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java +index ec51a5532576ce25465bacf61c716ddaffca514e..d285f5aa66fa81a2f56920c05afb4506cb82fa54 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java +@@ -52,7 +52,7 @@ public class PathfinderGoalTame extends PathfinderGoal { + @Override + public void e() { + if (!this.entity.isTamed() && this.entity.getRandom().nextInt(50) == 0) { +- Entity entity = (Entity) this.entity.getPassengers().get(0); ++ Entity entity = this.entity.passengers.isEmpty() ? null : this.entity.passengers.get(0); // Paper - do not copy list, fixed array out of bounds exception as well + + if (entity == null) { + return; +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java +index d6e1697f64e60f2a567288c604a1690159955f37..676ca381a5e111fc15f319e73504e4e60dbf0d2b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java +@@ -86,7 +86,7 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { + @Nullable + @Override + public Entity getRidingPassenger() { +- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); ++ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java +index d678e3164ecdb7f0c600597bcb39d1054dfbc4b2..1e41c45af6dbcf097d7d6104e63db637f199301a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java +@@ -972,7 +972,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven + @Nullable + @Override + public Entity getRidingPassenger() { +- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); ++ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list + } + + @Nullable +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java +index 7781386da593a1c4f3ad7e7e8761767dda7cb66c..16d5cae64887b82e67eeb61ccb714e6125ff0c09 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java +@@ -134,7 +134,7 @@ public class EntityRavager extends EntityRaider { + @Nullable + @Override + public Entity getRidingPassenger() { +- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); ++ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +index 069076d3c7165440217a7632b089ab2aa0fbdb1d..5e2c13bd6e52ffe182ef034e05ba6fe1cb301005 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java +@@ -317,7 +317,7 @@ public class EntityBoat extends Entity { + super.tick(); + this.r(); + if (this.cs()) { +- if (this.getPassengers().isEmpty() || !(this.getPassengers().get(0) instanceof EntityHuman)) { ++ if (this.passengers.isEmpty() || !(this.passengers.get(0) instanceof EntityHuman)) { // Paper - do not copy list + this.a(false, false); + } + +@@ -380,7 +380,7 @@ public class EntityBoat extends Entity { + Entity entity = (Entity) list.get(j); + + if (!entity.w(this)) { +- if (flag && this.getPassengers().size() < 2 && !entity.isPassenger() && entity.getWidth() < this.getWidth() && entity instanceof EntityLiving && !(entity instanceof EntityWaterAnimal) && !(entity instanceof EntityHuman)) { ++ if (flag && this.passengers.size() < 2 && !entity.isPassenger() && entity.getWidth() < this.getWidth() && entity instanceof EntityLiving && !(entity instanceof EntityWaterAnimal) && !(entity instanceof EntityHuman)) { // Paper - do not copy passenger list + entity.startRiding(this); + } else { + this.collide(entity); +@@ -727,8 +727,8 @@ public class EntityBoat extends Entity { + float f = 0.0F; + float f1 = (float) ((this.dead ? 0.009999999776482582D : this.bc()) + entity.bb()); + +- if (this.getPassengers().size() > 1) { +- int i = this.getPassengers().indexOf(entity); ++ if (this.passengers.size() > 1) { // Paper - do not copy list ++ int i = this.passengers.indexOf(entity); // Paper - do not copy list + + if (i == 0) { + f = 0.2F; +@@ -747,7 +747,7 @@ public class EntityBoat extends Entity { + entity.yaw += this.ak; + entity.setHeadRotation(entity.getHeadRotation() + this.ak); + this.a(entity); +- if (entity instanceof EntityAnimal && this.getPassengers().size() > 1) { ++ if (entity instanceof EntityAnimal && this.passengers.size() > 1) { // Paper - do not copy list + int j = entity.getId() % 2 == 0 ? 90 : 270; + + entity.n(((EntityAnimal) entity).aA + (float) j); +@@ -907,13 +907,13 @@ public class EntityBoat extends Entity { + + @Override + protected boolean q(Entity entity) { +- return this.getPassengers().size() < 2 && !this.a((Tag) TagsFluid.WATER); ++ return this.passengers.size() < 2 && !this.a((Tag) TagsFluid.WATER); // Paper - do not copy list + } + + @Nullable + @Override + public Entity getRidingPassenger() { +- List list = this.getPassengers(); ++ List list = this.passengers; // Paper - do not copy list + + return list.isEmpty() ? null : (Entity) list.get(0); + } +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +index 57821301ef031995e6044a17b46c70a693322455..75a88ab5d5b0fdb98ea8d61bb6b82049b21101f3 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +@@ -561,7 +561,7 @@ public abstract class EntityMinecartAbstract extends Entity { + + vec3d1 = new Vec3D(d8 * d4 / d6, vec3d1.y, d8 * d5 / d6); + this.setMot(vec3d1); +- Entity entity = this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); ++ Entity entity = this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list + + if (entity instanceof EntityHuman) { + Vec3D vec3d2 = entity.getMot(); diff --git a/patches/server-unmapped/0678-MC-29274-Fix-Wither-hostility-towards-players.patch b/patches/server-unmapped/0678-MC-29274-Fix-Wither-hostility-towards-players.patch new file mode 100644 index 0000000000..78875ff589 --- /dev/null +++ b/patches/server-unmapped/0678-MC-29274-Fix-Wither-hostility-towards-players.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheShermanTanker +Date: Thu, 1 Oct 2020 01:11:03 +0800 +Subject: [PATCH] MC-29274: Fix Wither hostility towards players + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index f1d384d2e235c52a00f4b6d5643ef3c1d163e94b..7ddeecc6496926350d59d9b8725a4b161750f1e1 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -806,4 +806,10 @@ public class PaperWorldConfig { + private void setUpdatePathfindingOnBlockUpdate() { + updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); + } ++ ++ public boolean fixWitherTargetingBug = false; ++ private void witherSettings() { ++ fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); ++ log("Withers properly target players: " + fixWitherTargetingBug); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +index 170b085c76e092f6d7b14095c66c84fa9a96a1fc..635b1493eeb6c13cc5ef489bd747ac557bc131d8 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java +@@ -104,6 +104,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { + this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); + this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this)); + this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0])); ++ if(this.world.paperConfig.fixWitherTargetingBug) this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 0, false, false, null)); // Paper - Fix MC-29274 + this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityInsentient.class, 0, false, false, EntityWither.by)); + } + diff --git a/patches/server-unmapped/0679-Throw-proper-exception-on-empty-JsonList-file.patch b/patches/server-unmapped/0679-Throw-proper-exception-on-empty-JsonList-file.patch new file mode 100644 index 0000000000..a65efb398f --- /dev/null +++ b/patches/server-unmapped/0679-Throw-proper-exception-on-empty-JsonList-file.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sun, 1 Nov 2020 16:43:11 +0100 +Subject: [PATCH] Throw proper exception on empty JsonList file + + +diff --git a/src/main/java/net/minecraft/server/players/JsonList.java b/src/main/java/net/minecraft/server/players/JsonList.java +index cd35b833d3047a38be980ee550641e87bd3b9b01..c960852dc60d0598012c5eef0d139fe38bde63fb 100644 +--- a/src/main/java/net/minecraft/server/players/JsonList.java ++++ b/src/main/java/net/minecraft/server/players/JsonList.java +@@ -189,6 +189,7 @@ public abstract class JsonList> { + + try { + JsonArray jsonarray = (JsonArray) JsonList.b.fromJson(bufferedreader, JsonArray.class); ++ com.google.common.base.Preconditions.checkState(jsonarray != null, "The file \"" + this.c.getName() + "\" is either empty or corrupt"); // Paper + + this.d.clear(); + Iterator iterator = jsonarray.iterator(); diff --git a/patches/server-unmapped/0680-Improve-ServerGUI.patch b/patches/server-unmapped/0680-Improve-ServerGUI.patch new file mode 100644 index 0000000000..ae8862a977 --- /dev/null +++ b/patches/server-unmapped/0680-Improve-ServerGUI.patch @@ -0,0 +1,400 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com> +Date: Sat, 3 Oct 2020 08:27:40 +0200 +Subject: [PATCH] Improve ServerGUI + +- Added logo to server frame +- Show tps in the server stats + +diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +index 67d064e3959ed8d886df30ce9d97f86c2443fa39..dc6bc1910ad0f9b27144d5750078c3ca607d03d3 100644 +--- a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java ++++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +@@ -57,9 +57,18 @@ public class RAMDetails extends JList { + public void update() { + GraphData data = RAMGraph.DATA.peekLast(); + Vector vector = new Vector<>(); ++ ++ double[] tps = new double[] {server.tps1.getAverage(), server.tps5.getAverage(), server.tps15.getAverage()}; ++ String[] tpsAvg = new String[tps.length]; ++ ++ for ( int g = 0; g < tps.length; g++) { ++ tpsAvg[g] = format( tps[g] ); ++ } + vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); + vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); + vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); ++ vector.add("TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg)); ++ + setListData(vector); + } + +@@ -70,4 +79,9 @@ public class RAMDetails extends JList { + } + return ((double) total / (double) tickTimes.length) * 1.0E-6D; + } ++ ++ private static String format(double tps) ++ { ++ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); ++ } + } +diff --git a/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java b/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java +index f85a4079bb2931fd29a526379ba350eb7e8ae636..79cc587d8ad9f576f9e4478a41baabcaf690c568 100644 +--- a/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java ++++ b/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java +@@ -18,7 +18,7 @@ public class GuiStatsComponent extends JComponent { + }); + private final int[] b = new int[256]; + private int c; +- private final String[] d = new String[11]; ++ private final String[] d = new String[12]; public String[] getStatEntries() { return this.d; } // Paper - change size, OBFHELPER + private final MinecraftServer e; + private final Timer f; + +@@ -37,8 +37,18 @@ public class GuiStatsComponent extends JComponent { + private void b() { + long i = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + ++ // Paper start - Add tps entry ++ double[] tps = org.bukkit.Bukkit.getTPS(); ++ String[] tpsAvg = new String[tps.length]; ++ ++ for ( int g = 0; g < tps.length; g++) { ++ tpsAvg[g] = format( tps[g] ); ++ } + this.d[0] = "Memory use: " + i / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)"; + this.d[1] = "Avg tick: " + GuiStatsComponent.a.format(this.a(this.e.h) * 1.0E-6D) + " ms"; ++ getStatEntries()[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg); ++ // Paper end ++ + this.b[this.c++ & 255] = (int) (i * 100L / Runtime.getRuntime().maxMemory()); + this.repaint(); + } +@@ -85,4 +95,10 @@ public class GuiStatsComponent extends JComponent { + public void a() { + this.f.stop(); + } ++ ++ // Paper - start Add tps entry ++ private static String format(double tps) { ++ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/server/gui/ServerGUI.java b/src/main/java/net/minecraft/server/gui/ServerGUI.java +index c2c075b9e3b70f863b6c450e4f31d6fde2935be6..d1d98c2f192514a3f511bebb00c088b03e6be84c 100644 +--- a/src/main/java/net/minecraft/server/gui/ServerGUI.java ++++ b/src/main/java/net/minecraft/server/gui/ServerGUI.java +@@ -31,6 +31,11 @@ import net.minecraft.DefaultUncaughtExceptionHandler; + import net.minecraft.server.dedicated.DedicatedServer; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++// Paper start ++import java.io.IOException; ++import java.util.Objects; ++import javax.imageio.ImageIO; ++// Paper end + + public class ServerGUI extends JComponent { + +@@ -56,6 +61,15 @@ public class ServerGUI extends JComponent { + jframe.pack(); + jframe.setLocationRelativeTo((Component) null); + jframe.setVisible(true); ++ jframe.setName("Minecraft server"); // Paper ++ ++ // Paper start - Add logo as frame image ++ try { ++ jframe.setIconImage(ImageIO.read(Objects.requireNonNull(ServerGUI.class.getClassLoader().getResourceAsStream("logo.png")))); ++ } catch (IOException ignore) { ++ } ++ // Paper end ++ + jframe.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent windowevent) { + if (!servergui.f.getAndSet(true)) { +diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png +new file mode 100644 +index 0000000000000000000000000000000000000000..a7d785f60c884ee4ee487cc364402d66c3dc2ecc +GIT binary patch +literal 14310 +zcmXY21yoy2uugDycPmm{N^yd_Q`}vP7YOd|PH`>8wLo!q*HRn`6f5rV?*HD)IX5{c +zxpy-=`|Zxo_svGBD$Agwkf4A-AaprdNp;|J21vifLD%hMrT$lZeEex|7Xe0mqFAZArC{!qp)zJmbab@utqA`6 +z61Z~|e!k$IbXNT?PvGuuzT7G514$8e!}lsR>%nURMm+~pde``@(!O=ISt0%B93;Ez +za-qRi4n0Q>zQ2#2^_y08QOl3jT*!Ir5@<8VrFx(6f9sP|H8ttjftN;wrX>jP4BcG1;MfU5x^L`zc09u!bDBt#+ll=7@ +zB;}A$BKgu}V?#qfHvm`~pt%wG2y{MOc%B!8I`p|pc +zO#?sq!Zd&j8UPmvY4RQnfo>!6{a}GFV!}g@qu<3Wu$07X(O`vikNW$~q!ngF23Ls2 +z53p8js<-B_Qd?xX6rtq43Mdz(jOg2QXx#Wng_9^1^^~KqFNq{Kvb@Ap9}bf&xFA-C +z5+#cQ`#v$A=kd0O=agATcleBaxXf_(dnqbQz|cL9R&&Ni1omTs+6~YApmk)MCghxj +z1}mq&IU>1nEiF=q=PI`%jQbyRd=hVI83Sm{E-4uTc#w;NNwEW)C(C`xvWzY_%`_MmO +zD&g-sEaE)}6(&g)y-N&rNy;5@+{M`}!{60Y8wMgF5;HmO#B~hG`W$;7xLG*yF((rq +zxP6I#r#o`B3FppK{v(q1!C+YLFSfySDcHyoW!}EfzuCB1B|C5+oP}dtocnwkcNy1EZ6#5JX4=ePl&cu~0tMnt&79+I4%PaK>VqFx;r!QdNmnxlEqdU-QR%Nmu{aWP +zJxwXvt5fFTCOVgB)Zq +z%H0U=9q7Y0lu&1kc4zYT3*lHA@XJfoK>3WFM&WWf2u6^+wCm8##D$x@Gkw+t^HoO( +z4pxDRqg;$5S=t^k22H5^V3V0Qfy%Ogl8I%LD$52=7)J>Ki9Ej1HyEi_ujELlz8$-+?cdD1Zxi02kW0 +zaY=caFq4~s^R?zxcc3Z0X|az}Aww<{P$>6rk+5Di5J7$kWor0{Q&>+DWSBH^Gf`SP +zT{4}IOFh-hB7xwBdewq%de)q6QvxorV(()2>@j8i!kj)=^hN +zl_N{$9xTHHA;V&Zx#tX&1pOO;v^NiOP#_UK@J;;lp+OOhOOO2mlMdxM;Qv-mWG+^vzox|8t`w| +z=gPlM3)y6G*hfV1WwuMe>bO-vP9g`h5BqgO9x{ROBD;aPl>XDmvt(3PUxt|4RFRpK +z5OEtRz{(Oa_W_!Z4XHf#h;Z-~71XM7wlF*L!-#h_Uy2tGuy-rAZ)4{qE~feNkp}qf +zgvBtLkFPI~I7%C=OHZfPZz$j>L9)rb;l +z@J^dxncy52;wmHg=wC3|Xn6jPYCR7xc}~D0wNjoYxmoRh_zh=6@8coM1UQIa_z*1)cZPw4v40qoZQp-uy#DLv=oP +zX9b3vzFA2r8}|_AO8W1(OMG__0{1AUD&Z%&7-(>s+Z-X6Sv}G5QguIbZ3mYa--?09 +z;wNw?n=yAag4%m#w$$-YZ{(ZJUcwHfzu&!gykNjG)e}!=q8xy2_KS=ULsQwv45NK! +zVqqD8#S{vRjg4(Q6HM_F&tihNIQns<%DVjE$cv33ET>Dvc^#{z&#u&&9RgXO?ZLuebczKv#;! +zCS|2lIa37Bp#3RWj0$V3=I2>o40{(J^LD|EUH?!2;Z&HS*>7*V%{v1)wHaUP85mcX +z%q!K}Ntr*IzJD%++btJ;VQO*OjJL1t{GvR3cy@OC-~pe^bV?N`z0QKCr?Tom)4u%A +z3mi2k&eIgh0^rGI#Di+&3lrsy-r+}zwBkDQtswtPbkj!Y^l`{f!# +zLseC0M;DiifDa!({-G4{W$Wxsgv*(NX%HMyXhArVwY105dUHg?+=@6Sy8n@slS76x +zU7%PI8ToKm#qahfR;7kn#|t@9y(0EkooWBDqA1(mpO)>BBz))giBi8xVHlj#dR9U8 +zRo%`iBdlj8%_tRn^qa%T>{nsLLwTNld&WHLyfbPzv2W62m6q=Nsdxnk +z#{P==5!Lidx3bcr_qlUl%BX!xjywA?jv>FU^mJDa0zQT9Kw8RRHq>7B +zb~DXw0(oqBrOQunsm2ghWV2i1VmN{F?)U;0%*j{FEUxazAJ3)KSWomuhklkDi?5h*MTLDS5ma_Nk1sNZYzZ#$maGRyiXBzjG@(G__fuyBl(^A>s&{jF+J%5| +zv#7nD1XK806#_U_4#N2ANAxznk%;U$Y$z#{K*O07mADqx6LjACqwP<`HFV#C6Q*wx +z8JVP_qGF}V7B?^8)f*2F5AON7v$L~Kr?2}oPai_kG!_6MI(U`LS~+Mo*CSyrw>pPE +zllqxy +z^&rnDn4XA@AUY7~`1lwTCrm8KlVRqX&!kZFH&;i9@=R}UDxNSh*)Iq2U+#9}@ag1t +z%KUOEw0DXT)>hQoLTprY^z=BC=8NAyi3pZWT7A`?;rI<3%65Nqb93%pJ=!+dNtB>W +z7f3O-e-S7ZBgBntcyt~wOG_p$AU2zlGH8=%TEm+z8kLYReEMTkIo#2YiA=iKWrH); +zS%uT3xAyyY=!U)0Evpgx{{38MPR2nN<3913M<0O#YCO=TSt^4IzV3^D%2zC>t_OO} +z_h~AVOk+IIi$Ov;-g93a4j@WaekCC#HFm2_Vu9s)8-GbYtr{LgrxnSIN^PW9)!jYX +z?%-yssA~&R3F)C)wj5i|@!atCx?Qy%P1QEGSZm;iUNai`-F(8a%y+_a>CMzx$XEKx +z>sW|JbN36s+Y{4SZsrspH%UH=+Q6J`c&_-JLGL&5|$XUA1vFOC+rgoc&xT{dFT&pMaEBKwyD;plX0>2nla;jTlQ{!fn2M=Ak*=K*g% +zBm0-$ly1~}CT-5gv){jex9)7&b8u!a+vYHXU>=NF2>g3+_rN{(LUMGwRWKk49sS$v +zazyX8zZ1hwZ|U*5{fK@i@hRl*U%Q2cg+!iIfb)6W%S5F{91qinEZE%~4Gl>rBw9S< +zMP5$exl1jESyt}d~jo?hf`z^32b!}UGtJH+w9(0UrI#~Ei*ii&6z(AVE?(}k_A +zE9Z@mj7HF-ch46I0ipe3gapRj{=zk_J1E^b_JwdrhKi4ytBuwP)m>e$@9v`A{1N{h +zwUN6H=_W+h(a?rGaQ%%LP5C4)XiZ*`1uUwgqWvk`LyDD!Ps#Q5oI($KDJ%8n5kBi- +zghsLx`~mf<>WT)6-cJBbp|htk1NfkZ@e#B4@l?UH7!MDMpO?1NETGk_Eg{z!N3!D< +zWg8gtgS%b(0Bg7dw9u35xq)1vNdnM8iu7Eje*u?#sZ~%^q*HDaZC?5z4ZzhSA%ndS +z4&$M&7(|(9nWY%QShCnuN0 +z`n9&UeypypUgx;R+x;XM#8uDM{p`9~j<49)^dotHJVO*A@HL&g7F={FP#trj@{dzm +zeQUiqRWJ&pkKkA1O-|vOf8O1UQ$$0lIExffio|}F@ROV#MXcPH$ +z?$$kxAF@B#KT}u;R@SVyIO>1sw1!i?C(_013w9@?8$bKaLQi34zC$g*^}F&(%NEO6 +zQzD-^6}HQMnGJ{h$J*)HjSxjblWegsW&rLC8Ov_r_20jLjUS$Ptnm|p9fK%r0j+4; +z57^mjL&lISh8>DC;eB$B69$h4XxE3qU4T&zUpDeV@4g>or%D-x@qhie>6mqD959ck74(h?S0BA0}YQ18d?hr6}%}y{%ZNJ^-(?=Op~; +z#2-UNh)jH9>RXmvPJ(Y!8(uhyW|sFpyvv)AaNeljHj^Fx+RC +z!`@c->W1C^FUKHmG2w_atkdsMnzY+l!CV8havQ8-Gu)<8t{#V*2Pwp4h?ayXsi5Z> +zo!guta>TA~iv#iJpQkN>#)QF%As@2WgU&V_Y^qm#E*O}M_ijJfFWq}ts)-l4>D)kCqJJ@MG2$69ph0jzwI8ry1u8D@CyinC$oT?7S*Z}Eg +zYs}PWLqr4u@)w}#!{cMx;KxO6W2H6~3k$laJjAt+C{0mmCRnfs=OJYbh}HMh&e`#> +zj;jrpjqKCh41OK{FOS`@_sPP$iCm46G^EMNk8(l-1f>!gEV+4vMVRZ#8infUenP+k +zL^tBOHF^=)k&U-Tw{gfijqQ&^ +z-RHHII5yp}2|o8pTsf6x7$teW9Em!~iy2DN?D@|U)g%I6VG%JBO$|~;c~1Q^3|x`1 +z6HRbq1#~Ke)wWpALcc&@P;m+*sGavR0{aOx3=IwUE3YPWAwV45pzD$~02inxi7(6X +z$zk683M=_r#M*+6fQ)&FK0y|lm7JLwS)K=t&ZJk!U_-y%_o@fhr{s37MUEQOF*M)3 +zB$;4>Zx;Xk*(hwFjb>1iJ1f*D#nyWL{=>{2|9*^vCNN!%bF8Oe<`xz#s;jFz?;I}4M3lL;!fy_;J-E96Of+;sG%K=fZdR)99pJ}fM( +zq%(s8UrsEL{NrdF`!#RY+VjFyPpE_vtqPMM!MQ+QnE)+_g9Z^{4^;k&Sa^=w*yuxB_*Z!U%!3{_9Qr)Jfz4IeS#io4oj_Kqhq`HCUub|Ke!v$1-$v=kc+O#rlCej?%dhY +zxxKUTsFPG1nfoFp3%7@gh9S?vM0N27#*fpJyaX;Vy{!pt*}!9_mX9uC#J5RyjknW2Dm3dCvZYU +zSW?0kvI9!o2un}*%`AYhr^CQT1aZF=-Nt^atn@Kt%b2!hT(pK!|MclbBv3-<+6{>_ +z8toMfWc9rpOk(8|KW>Z-k>Fr(xc_+q9ocf`8!_n}XYUrW?Ax|*_|=5m*4F0V+46wJ +z1IGS^Z5t=0Zj86J2MfJc +zUq#WKCfhoB<;P2&&`*_G4^_0uqDR20m!>T8ay_rxSzA&9_v5##g6tzXTkx+KRfz32 +z9vvpp?+YxHTxDthCBu7)&Q052y4s9*$M4_2w-OdPyK?F-EBoUuSsIk@@(!gA*A_!0 +z2eu1y;-Q$Ut(M>8FCOtw?vZR-%*ly^x)<95vK@P0tJoZws@+M*NGhg_NU`!}DZnWBHQz%*@6))$BWN;EM0xAF+B4Mph#S??J?K+&viwPmes*n^HGDL9iBf +zCk|mDu46wwughN!isu&G((DO>Ws`(VLY?^#w=RONxUgFGby--Y=5NJ|(>qXOS`;lZhmXyMEyBdVM@jJh71E-})~`?t4w8^Kwy) +z<+KACjs!F^TS-;FT24_iWF+=l(nR}j7U#;Vd +z)IT3=b&}A}1PUKFa6DKfgHkJci!~7u?a%k9h7Rri^{y`|;;xNDoQbV}+oJ=LdApL}|77o@C= +z;~aed)XpbrMtt1x3gHPWxbliQH4nKBCew{9 +z*-_PTyn~`1VrwKcc4ZrhI^!MsZ{D0O0%O2!SHHi^Dfyr9*x*DGFKwc()b;q6nM*M7 +zvA$x_?$BMJJHN5HIn9Ps{_7-sn79~BZegaa5V;s(BA<5BnU?^AeJHXtd)cIj_UCjA +zW|N@MjV~vrJz{sE0Dzv}tXxUDQAXm)1(kX7C_ZVFX%!TlZ850i(P1A0BxaJu)#LcH +zoxMFRzxoxw$bM=B6gpuMD#vcsa^00?%=D+T9-dQqV*=zD|)W!3BLun2&^n)~$ +z2_^{i9~sGXOAsF_S=k&4mWJ@`mD+G%MiPTlhuomboeFNwHb(< +zVpVR!mwf;JmpO3JL|B%L-!;@7TG}+`HZA;-{VIlQGY|T=f|!9!S=!c?sq5|KeEQ*~ +zm!1xeZcJPbSsfjU9e>K|=Ni<+YgrIG!|5@|Z>4bjx+`1j^O-{QK8XARf +zUG$nLRiTEtt;)9F30rvw>nj)@vCF{$d7>o2n>}~Y2^^C79l@s`uXRZOcuy>^%2@t- +zRGv={pKlDXFUgvG_^DWGR==il1rIzn{$p4r(FVOQxZi!_*Ksfl2hR{Aj>01RbFAM= +zpr0wzMwlOwlkt4|JLK)$>VL+{4nv>^`yMa)T;(9f*B(9;{T+)_=M4dN>M&&hS-#(G +z)-sW(WxVkHR)`x#g)25Lu7qnN;~Q-bvKDZ=;^fyLy@okDpvt&ZU{!U)WVtmnp +zAN-CzM{jPFWep9NAKDDq@=kynkGi_GQ@Z2y_Wn)xc_q3-&+9`qdGy_{PF-2c^$)%x +zd0sonEJhtG*2|P*Q-f_3`Akk96HzBz2 +z!5tnJaCcA2hGQrSw*{F)epvfYX?7toP=O0dN +zizY2w`>O@4Vqff!dBhQ^><#TjMP}loM9ProiD-Og@$V=*zQ|Avg0D!+96lr^u(1fl +z3J52PHoJYDdvdiIW?q?JIC*r?88VruLx#bp0lys39v$(c6uC*j}2IFFh +zViOX|K+DH18cd9%Rgjs$*sXuoW<>p^Fv-7CV|zpgTUnj812pyyX-nhA4TZ^UyYY9; +z?}BOarTT1q;0xSTjV_DPWE11?Y2+wSA*ybzebDoy8JwhznKa6SvYxE$WswX7Z6pG$ +zsA2GgHFFL3^zA@XTYK{a+6$Q8di%@1-|q9U15y+~R-L7Kwx8*xr(FP{g*JDPa`e((jSl#~?Rx=3ne(nLfeP9k0grubJK +zU4euzZqt~$Cl%k^{-!e6YQZi|D3#+MUS}VsYZ)0S>y@)kyqRI?A_esvAu-{`1Uq@! +zC+b`wnMK&<_mitl+k@e*$*{&S>vayX*>D>Q5sw2FZ?l(8ff%(8lo<^mBMrwQXOXe+ +z*7sZdWzBTIwZO$y^F)qZL1XbOMY<@M_a56y{({Vg@YN<_y}toq41V%~w=+4ZQvg)X +zVw~l$z-sId^nKU%dlk7W(mG}eS&KV2BdYqNJnX-p=YrG&&`_m0fzA_|iKD${5?oL* +zdS$heR@%Q+(3!!T&k;tIN|v2j=UI))rgkvyC7MTTrKP3g>Fma@_R0`GE5(tL%sS$7 +zG41ag%(Y(xZ5cjlk=R~(3XC+$25r*Fo=G5OhGgR}i!nDoG?^sult?Eo*x$x6CH-3L@LtZ0dfq!Bbbw-S}RwlN%lpH8c=4l2qH +z1wRszHSPh~=esnWvXD8B{D4<}?}6cA+@Ob1760Is6`g!zl@WL(L&={LA}SxAt0>Tw +z%b7i^&yNKM;(vGcNwuxAK{g|S3Y1&pH_6U1G +z3M4zx5FU=O;=l_?VzQ-~bx~xN1axPgYI0am3d25BjYmfSTX7Q}==Vcryl6@Se0(Jv +zxKW_o%H`jdnC7QXlkFbCsACHN1Dx=0gf<~@PW-&<=`1Hd)@#ypH7%OpalDj-P=ts+3^~yWs~TV}BD20HjkW6zc1L +z0#HzMkn3JV%7N-18_@tgE82*YnmEzxirriDSx#_|<|q1vL{k}7>^mRzO(ueTSN2~H +zG}kxp)Qn!&)><3|e>62+GXSpQKcemfqU!&BHZ5Ca;DT<63bBM&uV1BDS?MM$M;x8w>gShAPMxJM^BbMZn}Unm{OC9^4x3%% +zlmX8!km-u$N4fQXQ>jRe`7)3+RFGjhz +z18zf(Fo2<>YV^7LJO^UTZ2Ivd#mpN}o?7pBV&q=f%ID>haV7M8R3jsF*@a%iwIy>| +zsZ!-y{!%&j7`B?W8TcF4NH-RHH1xZ{;7BsA<#APu!;cND)te)FhoXz$BIU}2&^7WP +zT}TX>ZO58$VNPuh6JV7~s(W$vAj`^%AtUamex3YdVl3~4+pqk?G)qUibNMrj0*M25 +zY>5Ac|Dnv6xBQmV#$3JA?&HTN(lYl~J}@$l{*TY^kORrCB)3dDO}^^v!dcLf^CHty +zanjllIQeSLmpuG+h&ae`r*v!C*0A&W^a&q>93?BAXzG7n +z2*3TGPIcN`-_hY9&oaiv#fiv~>}7`T`4=pInEqWX*3e8+yPm^9h-tr&ts55$l+388 +zW)~F}2JH!}VLbQ>?6~H@&k`MnSsTeVj0TRVP4jGbP*!!CwM6`Z11c)yI2w$+R0zxo +zT|obYS1&&`{>>Z9(jnVU&=yI*%PGe*f78ie*_9oap?sd7fx7{r^WT>=XHF +zl`f{=UJEn2?tRw`Fem?eRE6#*nOes(ebRcmaK3~a3{a3EyE1zXSF0p7I_iDJ&%;3V +zU;AS}e?*mH#Yh2P9E3QBigIqu2iXf=@t)2+I~f*_E^JtEP1@IR{CBfTj%T}E3e#n% +zUa{@vU?D$l4DEANwkkK@ruP4ta)E*e^KLGg%$PizyPmHvKNMWtuJQ6sPXY=(1m#>W +z7V?9E!Vj}>a|KfQx5ESpH+q6$@gAp-P#~lbz`aj1_?xinN>3o8b2-Z3w>UZ3QZ}W0 +zWg-!>p>AADDcU^4;0*L4UFgB0QLlXd^y1E&4>txV!T|!`RwjZGl`;-4ZgFf>luHIy +zZ8d8Rh{I3r!g-ht6mAZxMB6VxRqnA0UY`h|mJZy2 +z17BazT$jMKFL3J6Ue_HL1^)4s%$Jj~Qx~1HG#tS@kwL(KP_ZI3dWz0SH(sqj#-*TNGsIWqPj>cj?!GyWvfdEiNOu4$>MIqL=F&Cc0{g*~L5 +zA1wt)=_zMFUkCT5$l!G{1-Y9QtGQ#qm5E(3fYPms_EP*sSVI)bfXN|uNO`BqVuCvd +zv)z8IGRgtM1<_trndVhQ^xA)wn~*W~#d*X@E=W)jcQWI8+?kdzHe;DZ`%+JE%gE}m +z6H=FO8rJxM{N90S=Gi!Mel)TyanxPa;E}C?hJl@e9UWad->;S|v;axgFjrY$z3(rV{MiJ}3M)t;Q?P5wZy0e3G{dcDO7n}3slDXLMrB$;#*W@Qv)D$=?Xs$F(8eTcyGIQ~IWgD%Gn&E>F9y#o>cR-7spE;Rur<_E~Pu)e0I +z#&y1|@8D~8c55<|KMf;&x;hg!A%VOZ38_+uk`jH4#=b9M&xcpxV-7cMN{jXVRnKSe +zlKJJ%=VBV{$DNeI1QkiA;DfdVT?$;O#22z6v6bTK9)fjrfIh!Hq__l~KzuNqT{&kA +zKs@YV6^1ZLGjTgR%(=NHS-DvWnnP)NM#qbHINqmQdCE5??co$3nuikqgm=s7*#Kd*+j_weKrZjMeLeHEoiJm>zuDRU` +zh~ggr^knneWU!Nn}AQt=0Id6Hk; +z4bJqse|V$H`stT?NS0yreYvaZ9YF!fw+N}{3#yXRU!C7?exl35BDC%+!jDMGT^DN# +zN9FGd#5t#;$h}5UgQ?q-Gr15>C6=nLUszle9<+_!!oi_m@_L^-R>_Qty7_g|C%m|5 +z-7^5X5V_ARi?h9_LW%2vByD3X_IvUktqBv{%SYXO1&;e&O#Ll_cfC`Wv1u+l_#RI< +zQ5Kly0;P`%TXaQN(heOg~>V&L{d+ZDA%eq-UKo#1)$rkjSm=nzAE2r +z5--RyKhxfXoGVU3^ab{5XGlyL1+26foG)4HZvN +zG@&I3h0fnK5lIjcrg*XxPy1(gK3_TN`&VYnxP;C|j$~0rT$0f|*#=OzM^NbE-1T5D +z%Csnt)n!sx3N#b(8G&+G3W~Q_B#StA6jZZ=p#wuu`DrAMXm{T@#S;ku4Dme@{Njmk +zCtrh3z6O>o)~o{&Htx+6kn*)$NNBH-biu^aYtWUq +z(G>4rCEKr#tO>!x8A@%W@6g)Xs%2Hq!y#Mbb@9R2@GDWi&!{jhZvzQ1D9nMuPoOS+ +z+cj{9nx5X{jJOIavbFf)Kz5Jnbe5Bu#(XE-z$j&iaP%c9W59OoT0~|N#D*(N2kz={ +zs(|)nH!_+_g1)#ZH2xk>ZTG#6WN#qa3BxZM{NWxq`*#$H255k6Ky?hw*hSA6`c_fl +zT@Ua%E5Ez3;~`kQFmrC#$Nlvc_Uy3#yzhd-6UYuuIwgIBZZC-`dwOBJbfurL(FfhH +z{YkjE+9OrOveY`{t{sGw&51YO1@{iO4)Ki=!Z5#q=m_Hi)_j0`>?;t2j);vv%BUif +z;wpTZdLQLsGvZ()DCdxYudn^Pt;BZ}Rin$4F8h{R`HxT2z`uc&aMXIQOvwgA5%{&) +zFW52MiN!$!EXgx}Px~e1!EMp;#&kY65oDho95j~!qD%YJr`+aK4jCJ4UJ^;q>w@Lf +zvDfg|M`S^@DGxu+7aR3Cx#;%?advj&1~L-m +zJqCP9&TW3migV*`Z$#)Qa>3>Jf)g9D6Ki28P@iX(uso)hic8Dp1F< +zeF;(n8Po8A*~^T{De(J)Z2nqLl@Vv3yoSlGwq0aeOg4ymI(KIkTeur-=J-yp9z?qe)it6gq-wl@I +z0D-_I{|T<5kwD9uH3yf1GWXp5*8eOgJf*q0IRoK|+r{}Fug&0WpNDKMTC@(Xc)9K8 +zy`lByMn!1fnY)1KYP(0Je1)c~WilUuh<&Q8^OE?L9Q^xK*Y@M$`6D6TDCZ^@l8{|} +zxmmNw)mng$hYBii+&ZqedxWT0dnV#LG4zC%+kzcK+-??vEHT>Q-T8zu|s_1IbA#OV)^+1pg1OmmZn` + +literal 0 +HcmV?d00001 + diff --git a/patches/server-unmapped/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/patches/server-unmapped/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch new file mode 100644 index 0000000000..852ff8decb --- /dev/null +++ b/patches/server-unmapped/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Tue, 2 Feb 2021 09:17:59 +0100 +Subject: [PATCH] stop firing pressure plate EntityInteractEvent for ignored + entities + + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java +index 4c4c8b23c39d26c646b1950023a20446ac798c6f..fba720bf2349a69d0f93642eea4e77063f83380c 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java +@@ -82,6 +82,7 @@ public class BlockPressurePlateBinary extends BlockPressurePlateAbstract { + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); ++ if (entity.isIgnoreBlockTrigger()) continue; // Paper - don't call event for ignored entities + + // CraftBukkit start - Call interact event when turning on a pressure plate + if (this.getPower(world.getType(blockposition)) == 0) { diff --git a/patches/server-unmapped/0682-fix-converting-txt-to-json-file.patch b/patches/server-unmapped/0682-fix-converting-txt-to-json-file.patch new file mode 100644 index 0000000000..ef2fcdd893 --- /dev/null +++ b/patches/server-unmapped/0682-fix-converting-txt-to-json-file.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 4 Jan 2021 19:49:15 -0800 +Subject: [PATCH] fix converting txt to json file + + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java +index b13e6f9923a9c5703f4eaeab2d0c112e4726b496..a762cf4c4a52bcbc8dbfd60b3ad7fef5489ba5c5 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java +@@ -18,6 +18,11 @@ public class DedicatedPlayerList extends PlayerList { + + this.a(dedicatedserverproperties.viewDistance); + super.setHasWhitelist((Boolean) dedicatedserverproperties.whiteList.get()); ++ // Paper start - moved from constructor ++ } ++ @Override ++ public void loadAndSaveFiles() { ++ // Paper end + this.y(); + this.w(); + this.x(); +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index a5b1f33473e8c82511fdd0c218f4fe744f584de8..cac3df2ca054b3b2fb5b6437ab2950afc3ace8fb 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -198,6 +198,12 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); + org.spigotmc.SpigotConfig.registerCommands(); + // Spigot end ++ // Paper start - moved up to right after PlayerList creation but before file load/save ++ if (this.convertNames()) { ++ this.getUserCache().save(false); // Paper ++ } ++ this.getPlayerList().loadAndSaveFiles(); // Must be after convertNames ++ // Paper end + // Paper start + try { + com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); +@@ -260,10 +266,6 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + DedicatedServer.LOGGER.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file."); + } + +- if (this.convertNames()) { +- this.getUserCache().b(false); // Paper +- } +- + if (!NameReferencingFileConverter.e(this)) { + return false; + } else { +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 1358993217e601e3bab6e0a4e8c55d555865a13e..484c7cea458dda38e4816fe5f1c05c6836fa38b9 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -175,6 +175,7 @@ public abstract class PlayerList { + this.maxPlayers = i; + this.playerFileData = worldnbtstorage; + } ++ abstract public void loadAndSaveFiles(); // Paper - moved from DedicatedPlayerList constructor + + public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { + EntityPlayer prev = pendingPlayers.put(entityplayer.getUniqueID(), entityplayer);// Paper +diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java +index 692d95c94df85d752a3ddc66e1f2af765565b160..c617b7dd5a992770fc87113987807947ae68be81 100644 +--- a/src/main/java/net/minecraft/server/players/UserCache.java ++++ b/src/main/java/net/minecraft/server/players/UserCache.java +@@ -243,6 +243,7 @@ public class UserCache { + return arraylist; + } + ++ public void save(boolean asyncSave) { b(asyncSave); } // Paper - OBFHELPER + public void b(boolean asyncSave) { // Paper + JsonArray jsonarray = new JsonArray(); + DateFormat dateformat = e(); diff --git a/patches/server-unmapped/0683-Add-worldborder-events.patch b/patches/server-unmapped/0683-Add-worldborder-events.patch new file mode 100644 index 0000000000..49bf0c1ca5 --- /dev/null +++ b/patches/server-unmapped/0683-Add-worldborder-events.patch @@ -0,0 +1,122 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 4 Jan 2021 22:40:34 -0800 +Subject: [PATCH] Add worldborder events + + +diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +index bedaa9dd6390e81df5872c2dd6e202a038367bf6..3c25021835d6d8fd112fc89636616bfd744e7f1a 100644 +--- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java ++++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java +@@ -14,6 +14,9 @@ import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.shapes.OperatorBoolean; + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapes; ++import io.papermc.paper.event.world.border.WorldBorderBoundsChangeFinishEvent; // Paper ++import io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent; // Paper ++import io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent; // Paper + + public class WorldBorder { + +@@ -102,15 +105,19 @@ public class WorldBorder { + } + + public void setCenter(double d0, double d1) { +- this.g = d0; +- this.h = d1; ++ // Paper start ++ WorldBorderCenterChangeEvent event = new WorldBorderCenterChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), new org.bukkit.Location(world.getWorld(), this.getCenterX(), 0, this.getCenterZ()), new org.bukkit.Location(world.getWorld(), d0, 0, d1)); ++ if (!event.callEvent()) return; ++ this.g = event.getNewCenter().getX(); ++ this.h = event.getNewCenter().getZ(); ++ // Paper end + this.j.k(); + Iterator iterator = this.l().iterator(); + + while (iterator.hasNext()) { + IWorldBorderListener iworldborderlistener = (IWorldBorderListener) iterator.next(); + +- iworldborderlistener.a(this, d0, d1); ++ iworldborderlistener.a(this, event.getNewCenter().getX(), event.getNewCenter().getZ()); // Paper + } + + } +@@ -128,25 +135,43 @@ public class WorldBorder { + } + + public void setSize(double d0) { +- this.j = new WorldBorder.d(d0); ++ // Paper start ++ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE, getSize(), d0, 0); ++ if (!event.callEvent()) return; ++ if (event.getType() == WorldBorderBoundsChangeEvent.Type.STARTED_MOVE && event.getDuration() > 0) { // If changed to a timed transition ++ transitionSizeBetween(event.getOldSize(), event.getNewSize(), event.getDuration()); ++ return; ++ } ++ this.j = new WorldBorder.d(event.getNewSize()); ++ // Paper end + Iterator iterator = this.l().iterator(); + + while (iterator.hasNext()) { + IWorldBorderListener iworldborderlistener = (IWorldBorderListener) iterator.next(); + +- iworldborderlistener.a(this, d0); ++ iworldborderlistener.a(this, event.getNewSize()); // Paper + } + + } + + public void transitionSizeBetween(double d0, double d1, long i) { +- this.j = (WorldBorder.a) (d0 == d1 ? new WorldBorder.d(d1) : new WorldBorder.b(d0, d1, i)); ++ // Paper start ++ WorldBorderBoundsChangeEvent.Type type; ++ if (d0 == d1) { // new size = old size ++ type = WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE; // Use INSTANT_MOVE because below it creates a Static border if they are equal. ++ } else { ++ type = WorldBorderBoundsChangeEvent.Type.STARTED_MOVE; ++ } ++ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), type, d0, d1, i); ++ if (!event.callEvent()) return; ++ this.j = (WorldBorder.a) (d0 == event.getNewSize() ? new WorldBorder.d(event.getNewSize()) : new WorldBorder.b(d0, event.getNewSize(), event.getDuration())); ++ // Paper end + Iterator iterator = this.l().iterator(); + + while (iterator.hasNext()) { + IWorldBorderListener iworldborderlistener = (IWorldBorderListener) iterator.next(); + +- iworldborderlistener.a(this, d0, d1, i); ++ iworldborderlistener.a(this, d0, event.getNewSize(), event.getDuration()); // Paper + } + + } +@@ -434,11 +459,11 @@ public class WorldBorder { + + class b implements WorldBorder.a { + +- private final double b; +- private final double c; ++ private final double b; public final double getOldSize() { return this.b; } // Paper - OBFHELPER ++ private final double c; public final double getNewSize() { return this.c; } // Paper - OBFHELPER + private final long d; + private final long e; +- private final double f; ++ private final double f; public final double getDuration() { return this.f; } // Paper - OBFHELPER + + private b(double d0, double d1, long i) { + this.b = d0; +@@ -493,6 +518,7 @@ public class WorldBorder { + + @Override + public WorldBorder.a l() { ++ if (this.getLerpTimeRemaining() <= 0L) new WorldBorderBoundsChangeFinishEvent(world.getWorld(), world.getWorld().getWorldBorder(), getOldSize(), getNewSize(), getDuration()).callEvent(); // Paper + return (WorldBorder.a) (this.g() <= 0L ? WorldBorder.this.new d(this.c) : this); + } + +@@ -514,6 +540,7 @@ public class WorldBorder { + + double e(); + ++ default long getLerpTimeRemaining() { return g(); } // Paper - OBFHELPER + long g(); + + double h(); diff --git a/patches/server-unmapped/0684-added-PlayerNameEntityEvent.patch b/patches/server-unmapped/0684-added-PlayerNameEntityEvent.patch new file mode 100644 index 0000000000..c4ab87d789 --- /dev/null +++ b/patches/server-unmapped/0684-added-PlayerNameEntityEvent.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 5 Jul 2020 00:33:54 -0700 +Subject: [PATCH] added PlayerNameEntityEvent + + +diff --git a/src/main/java/net/minecraft/world/item/ItemNameTag.java b/src/main/java/net/minecraft/world/item/ItemNameTag.java +index 140a865f4f8fb3e4f787cf8d334d20fac6cb5eef..b9b2b27e534ba87a1aae3c521f393a066a18a199 100644 +--- a/src/main/java/net/minecraft/world/item/ItemNameTag.java ++++ b/src/main/java/net/minecraft/world/item/ItemNameTag.java +@@ -1,11 +1,17 @@ + package net.minecraft.world.item; + ++import net.minecraft.server.level.EntityPlayer; + import net.minecraft.world.EnumHand; + import net.minecraft.world.EnumInteractionResult; + import net.minecraft.world.entity.EntityInsentient; + import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.player.EntityHuman; + ++// Paper start ++import io.papermc.paper.adventure.PaperAdventure; ++import io.papermc.paper.event.player.PlayerNameEntityEvent; ++// Paper end ++ + public class ItemNameTag extends Item { + + public ItemNameTag(Item.Info item_info) { +@@ -16,11 +22,15 @@ public class ItemNameTag extends Item { + public EnumInteractionResult a(ItemStack itemstack, EntityHuman entityhuman, EntityLiving entityliving, EnumHand enumhand) { + if (itemstack.hasName() && !(entityliving instanceof EntityHuman)) { + if (!entityhuman.world.isClientSide && entityliving.isAlive()) { +- entityliving.setCustomName(itemstack.getName()); +- if (entityliving instanceof EntityInsentient) { +- ((EntityInsentient) entityliving).setPersistent(); ++ // Paper start ++ PlayerNameEntityEvent event = new PlayerNameEntityEvent(((EntityPlayer) entityhuman).getBukkitEntity(), entityliving.getBukkitLivingEntity(), PaperAdventure.asAdventure(itemstack.getName()), true); ++ if (!event.callEvent()) return EnumInteractionResult.PASS; ++ EntityLiving newEntityLiving = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle(); ++ newEntityLiving.setCustomName(event.getName() != null ? PaperAdventure.asVanilla(event.getName()) : null); ++ if (event.isPersistent() && newEntityLiving instanceof EntityInsentient) { ++ ((EntityInsentient) newEntityLiving).setPersistent(); + } +- ++ // Paper end + itemstack.subtract(1); + } + diff --git a/patches/server-unmapped/0685-Prevent-grindstones-from-overstacking-items.patch b/patches/server-unmapped/0685-Prevent-grindstones-from-overstacking-items.patch new file mode 100644 index 0000000000..7eba41fbef --- /dev/null +++ b/patches/server-unmapped/0685-Prevent-grindstones-from-overstacking-items.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Tue, 16 Feb 2021 21:37:51 -0600 +Subject: [PATCH] Prevent grindstones from overstacking items + + +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java +index 1d5dcbbd3870eb8e1013a97f6ce882bfc096bf95..a841c47c25287080738b04352ea4e8eaa77dacdd 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java +@@ -196,13 +196,13 @@ public class ContainerGrindstone extends Container { + i = Math.max(item.getMaxDurability() - l, 0); + itemstack2 = this.b(itemstack, itemstack1); + if (!itemstack2.e()) { +- if (!ItemStack.matches(itemstack, itemstack1)) { ++ if (!ItemStack.matches(itemstack, itemstack1) || itemstack2.getMaxStackSize() == 1) { // Paper - add max stack size check + this.resultInventory.setItem(0, ItemStack.b); + this.c(); + return; + } + +- b0 = 2; ++ b0 = 2; // Paper - the problem line for above change, causing over-stacking + } + } else { + boolean flag3 = !itemstack.isEmpty(); diff --git a/patches/server-unmapped/0686-Add-recipe-to-cook-events.patch b/patches/server-unmapped/0686-Add-recipe-to-cook-events.patch new file mode 100644 index 0000000000..41d4ad4460 --- /dev/null +++ b/patches/server-unmapped/0686-Add-recipe-to-cook-events.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> +Date: Wed, 6 Jan 2021 12:04:03 -0800 +Subject: [PATCH] Add recipe to cook events + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java +index 62a19f39405cff27f34a3b98fb9310b1c9c27563..08759f461ec947c0d5655557f49d8717afee6f00 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java +@@ -74,7 +74,10 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab + + if (this.cookingTimes[i] >= this.cookingTotalTimes[i]) { + InventorySubcontainer inventorysubcontainer = new InventorySubcontainer(new ItemStack[]{itemstack}); +- ItemStack itemstack1 = (ItemStack) this.world.getCraftingManager().craft(Recipes.CAMPFIRE_COOKING, inventorysubcontainer, this.world).map((recipecampfire) -> { ++ // Paper start ++ Optional recipe = this.world.getCraftingManager().craft(Recipes.CAMPFIRE_COOKING, inventorysubcontainer, this.world); ++ ItemStack itemstack1 = (ItemStack) recipe.map((recipecampfire) -> { ++ // Paper end + return recipecampfire.a(inventorysubcontainer); + }).orElse(itemstack); + BlockPosition blockposition = this.getPosition(); +@@ -83,7 +86,7 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab + CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); + org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); + +- BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.world, this.position), source, result); ++ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.world, this.position), source, result, (org.bukkit.inventory.CookingRecipe) recipe.map(RecipeCampfire::toBukkitRecipe).orElse(null)); // Paper + this.world.getServer().getPluginManager().callEvent(blockCookEvent); + + if (blockCookEvent.isCancelled()) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +index 54316a8079b4331a48cac3c43f3f8c506a4af091..1997139fb87dc1947acfdf02e1f116577c3fa943 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +@@ -395,7 +395,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); + org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); + +- FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()), source, result); ++ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()), source, result, (org.bukkit.inventory.CookingRecipe) irecipe.toBukkitRecipe()); // Paper + this.world.getServer().getPluginManager().callEvent(furnaceSmeltEvent); + + if (furnaceSmeltEvent.isCancelled()) { diff --git a/patches/server-unmapped/0687-Add-Block-isValidTool.patch b/patches/server-unmapped/0687-Add-Block-isValidTool.patch new file mode 100644 index 0000000000..6cfa745ab3 --- /dev/null +++ b/patches/server-unmapped/0687-Add-Block-isValidTool.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 6 Jul 2020 12:44:31 -0700 +Subject: [PATCH] Add Block#isValidTool + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index ed1c92d9f2770f7d0503c6facebc51ddcbdf75cf..0006b3cad5fe46e50b0efeae99102f9d80276d61 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -806,5 +806,9 @@ public class CraftBlock implements Block { + } + return speed; + } ++ ++ public boolean isValidTool(ItemStack itemStack) { ++ return getDrops(itemStack).size() != 0; ++ } + // Paper end + } diff --git a/patches/server-unmapped/0688-Allow-using-signs-inside-spawn-protection.patch b/patches/server-unmapped/0688-Allow-using-signs-inside-spawn-protection.patch new file mode 100644 index 0000000000..2cec392ea8 --- /dev/null +++ b/patches/server-unmapped/0688-Allow-using-signs-inside-spawn-protection.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Anton Lindroth +Date: Wed, 15 Apr 2020 01:54:02 +0200 +Subject: [PATCH] Allow using signs inside spawn protection + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 7ddeecc6496926350d59d9b8725a4b161750f1e1..0dd0795af0d0deeff5637a2a1a4a165dec26af15 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -812,4 +812,9 @@ public class PaperWorldConfig { + fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); + log("Withers properly target players: " + fixWitherTargetingBug); + } ++ ++ public boolean allowUsingSignsInsideSpawnProtection = false; ++ private void allowUsingSignsInsideSpawnProtection() { ++ allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); ++ } + } +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index c68e56562076a2ca3d099a1112404f11a5473397..7d584e6d7b4e7b27ca0d51e0eb52a47169aa4b58 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -143,6 +143,7 @@ import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.IWorldReader; + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.BlockCommand; ++import net.minecraft.world.level.block.BlockSign; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.TileEntity; + import net.minecraft.world.level.block.entity.TileEntityCommand; +@@ -1692,7 +1693,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + + this.player.resetIdleTimer(); + if (blockposition.getY() < this.minecraftServer.getMaxBuildHeight()) { +- if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.a((EntityHuman) this.player, blockposition)) { ++ if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && (worldserver.a((EntityHuman) this.player, blockposition) || (worldserver.paperConfig.allowUsingSignsInsideSpawnProtection && worldserver.getType(blockposition).getBlock() instanceof BlockSign))) { // Paper + // CraftBukkit start - Check if we can actually do something over this large a distance + // Paper - move check up + this.player.clearActiveItem(); // SPIGOT-4706 diff --git a/patches/server-unmapped/0689-Implement-Keyed-on-World.patch b/patches/server-unmapped/0689-Implement-Keyed-on-World.patch new file mode 100644 index 0000000000..914a3c28d5 --- /dev/null +++ b/patches/server-unmapped/0689-Implement-Keyed-on-World.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 6 Jan 2021 00:34:04 -0800 +Subject: [PATCH] Implement Keyed on World + + +diff --git a/src/main/java/net/minecraft/core/IRegistry.java b/src/main/java/net/minecraft/core/IRegistry.java +index 3e9ebeffdf66f8a959630b344149d17137c6901c..4f04d8081912e0fe771f0db9e086c789328f246f 100644 +--- a/src/main/java/net/minecraft/core/IRegistry.java ++++ b/src/main/java/net/minecraft/core/IRegistry.java +@@ -130,7 +130,7 @@ public abstract class IRegistry implements Codec, Keyable, Registry { + public static final ResourceKey> I = a("loot_function_type"); + public static final ResourceKey> J = a("loot_condition_type"); + public static final ResourceKey> K = a("dimension_type"); +- public static final ResourceKey> L = a("dimension"); ++ public static final ResourceKey> L = a("dimension"); public static final ResourceKey> getWorldRegistry() { return L; } // Paper - OBFHELPER + public static final ResourceKey> M = a("dimension"); + public static final IRegistry SOUND_EVENT = a(IRegistry.g, () -> { + return SoundEffects.ENTITY_ITEM_PICKUP; +@@ -339,9 +339,9 @@ public abstract class IRegistry implements Codec, Keyable, Registry { + MinecraftKey minecraftkey = resourcekey.a(); + + IRegistry.a.put(minecraftkey, supplier); +- IRegistryWritable iregistrywritable = IRegistry.e; ++ IRegistryWritable iregistrywritable = IRegistry.e; // Paper - decompile fix + +- return (IRegistryWritable) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); ++ return (R) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); // Paper - decompile fix + } + + protected IRegistry(ResourceKey> resourcekey, Lifecycle lifecycle) { +@@ -428,11 +428,11 @@ public abstract class IRegistry implements Codec, Keyable, Registry { + } + + public static T a(IRegistry iregistry, MinecraftKey minecraftkey, T t0) { +- return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.b, minecraftkey), t0, Lifecycle.stable()); ++ return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.b, minecraftkey), t0, Lifecycle.stable()); // Paper - decompile fix + } + + public static T a(IRegistry iregistry, int i, String s, T t0) { +- return ((IRegistryWritable) iregistry).a(i, ResourceKey.a(iregistry.b, new MinecraftKey(s)), t0, Lifecycle.stable()); ++ return ((IRegistryWritable) iregistry).a(i, ResourceKey.a(iregistry.b, new MinecraftKey(s)), t0, Lifecycle.stable()); // Paper - decompile fix + } + + static { +diff --git a/src/main/java/net/minecraft/resources/ResourceKey.java b/src/main/java/net/minecraft/resources/ResourceKey.java +index 760579921927b4c8b0f20b2611b95fd626e4b27f..3075700dfa992da81b10246fcf7c7ad1115c4ba3 100644 +--- a/src/main/java/net/minecraft/resources/ResourceKey.java ++++ b/src/main/java/net/minecraft/resources/ResourceKey.java +@@ -12,6 +12,7 @@ public class ResourceKey { + private final MinecraftKey b; + private final MinecraftKey c; + ++ public static ResourceKey newResourceKey(ResourceKey> registryKey, MinecraftKey minecraftKey) { return a(registryKey, minecraftKey); } // Paper - OBFHELPER + public static ResourceKey a(ResourceKey> resourcekey, MinecraftKey minecraftkey) { + return a(resourcekey.c, minecraftkey); + } +@@ -41,6 +42,7 @@ public class ResourceKey { + return this.b.equals(resourcekey.a()); + } + ++ public MinecraftKey getLocation() { return a(); } // Paper - OBFHELPER + public MinecraftKey a() { + return this.c; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index e5c78b4e7537c8a042dcc41ca6b77c000c4317de..706dad235de3b7ffe014f564e1c68f18e1edeefc 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1157,7 +1157,7 @@ public final class CraftServer implements Server { + } else if (name.equals(levelName + "_the_end")) { + worldKey = net.minecraft.world.level.World.THE_END; + } else { +- worldKey = ResourceKey.a(IRegistry.L, new MinecraftKey(name.toLowerCase(java.util.Locale.ENGLISH))); ++ worldKey = ResourceKey.newResourceKey(IRegistry.getWorldRegistry(), new net.minecraft.resources.MinecraftKey(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper + } + + WorldServer internal = (WorldServer) new WorldServer(console, console.executorService, worldSession, worlddata, worldKey, dimensionmanager, getServer().worldLoadListenerFactory.create(11), +@@ -1247,6 +1247,15 @@ public final class CraftServer implements Server { + return null; + } + ++ // Paper start ++ @Override ++ public World getWorld(NamespacedKey worldKey) { ++ WorldServer worldServer = console.getWorldServer(ResourceKey.newResourceKey(IRegistry.getWorldRegistry(), CraftNamespacedKey.toMinecraft(worldKey))); ++ if (worldServer == null) return null; ++ return worldServer.getWorld(); ++ } ++ // Paper end ++ + public void addWorld(World world) { + // Check if a World already exists with the UID. + if (getWorld(world.getUID()) != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 05a7f5f61330bd52705640345524cdedbf105285..a152d5bec8bf0dd87239b0a3432fb589cea61bd8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2584,6 +2584,11 @@ public class CraftWorld implements World { + return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + }, net.minecraft.server.MinecraftServer.getServer()); + } ++ ++ @Override ++ public org.bukkit.NamespacedKey getKey() { ++ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(world.getDimensionKey().getLocation()); ++ } + // Paper end + + // Spigot start diff --git a/patches/server-unmapped/0690-Add-fast-alternative-constructor-for-Vector3f.patch b/patches/server-unmapped/0690-Add-fast-alternative-constructor-for-Vector3f.patch new file mode 100644 index 0000000000..65430ea1e7 --- /dev/null +++ b/patches/server-unmapped/0690-Add-fast-alternative-constructor-for-Vector3f.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Irmo van den Berge +Date: Wed, 10 Mar 2021 21:26:31 +0100 +Subject: [PATCH] Add fast alternative constructor for Vector3f + +Signed-off-by: Irmo van den Berge + +diff --git a/src/main/java/net/minecraft/core/Vector3f.java b/src/main/java/net/minecraft/core/Vector3f.java +index 93590ceb0bbe369a1bda987f0c4c21ea6a3b3a1a..da53e294fa5e28406b25614039db49b48c2dcdac 100644 +--- a/src/main/java/net/minecraft/core/Vector3f.java ++++ b/src/main/java/net/minecraft/core/Vector3f.java +@@ -19,6 +19,18 @@ public class Vector3f { + this(nbttaglist.i(0), nbttaglist.i(1), nbttaglist.i(2)); + } + ++ // Paper start - faster alternative constructor ++ private Vector3f(float x, float y, float z, Void dummy_var) { ++ this.x = x; ++ this.y = y; ++ this.z = z; ++ } ++ ++ public static Vector3f createWithoutValidityChecks(float x, float y, float z) { ++ return new Vector3f(x, y, z, null); ++ } ++ // Paper end ++ + public NBTTagList a() { + NBTTagList nbttaglist = new NBTTagList(); + diff --git a/patches/server-unmapped/0691-Item-Rarity-API.patch b/patches/server-unmapped/0691-Item-Rarity-API.patch new file mode 100644 index 0000000000..d98d46c7ed --- /dev/null +++ b/patches/server-unmapped/0691-Item-Rarity-API.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 12 Mar 2021 17:09:42 -0800 +Subject: [PATCH] Item Rarity API + + +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index 467121839b94e09f59c64300de9f26d3c6caf1e5..f7758ee4aa8bbb31a80ec2e331b3fd3c55069808 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -45,7 +45,7 @@ public class Item implements IMaterial { + protected static final UUID g = UUID.fromString("FA233E1C-4180-4865-B01B-BCCE9785ACA3"); + protected static final Random RANDOM = new Random(); + protected final CreativeModeTab i; +- private final EnumItemRarity a; ++ private final EnumItemRarity a; public final EnumItemRarity getItemRarity() { return a; } // Paper - OBFHELPER + private final int maxStackSize; + private final int durability; + private final boolean d; +@@ -209,6 +209,7 @@ public class Item implements IMaterial { + return itemstack.hasEnchantments(); + } + ++ public EnumItemRarity getItemStackRarity(ItemStack itemStack) { return i(itemStack); } // Paper - OBFHELPER + public EnumItemRarity i(ItemStack itemstack) { + if (!itemstack.hasEnchantments()) { + return this.a; +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 848a704fa100c39098a5716bb25b6a9ed85d7a8c..de6a9d795ebaf9c608944415c7dc18c6aee23245 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -472,6 +472,20 @@ public final class CraftMagicNumbers implements UnsafeValues { + public int nextEntityId() { + return net.minecraft.world.entity.Entity.nextEntityId(); + } ++ ++ @Override ++ public io.papermc.paper.inventory.ItemRarity getItemRarity(org.bukkit.Material material) { ++ Item item = getItem(material); ++ if (item == null) { ++ throw new IllegalArgumentException(material + " is not an item, and rarity does not apply to blocks"); ++ } ++ return io.papermc.paper.inventory.ItemRarity.values()[item.getItemRarity().ordinal()]; ++ } ++ ++ @Override ++ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { ++ return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; ++ } + // Paper end + + /** diff --git a/patches/server-unmapped/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/patches/server-unmapped/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch new file mode 100644 index 0000000000..61d73b8e95 --- /dev/null +++ b/patches/server-unmapped/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Fri, 19 Mar 2021 16:07:21 -0700 +Subject: [PATCH] Only set despawnTimer for Wandering Traders spawned by + MobSpawnerTrader + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java +index f2cf33d42839710a3bbdf0c8ea0be28af6fcb19d..80c229c1852199fda85c03453d64cae33e413e89 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java ++++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java +@@ -319,6 +319,12 @@ public class EntityTypes { + + @Nullable + public T spawnCreature(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // Paper start - add consumer to modify entity before spawn ++ return this.spawnCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1, spawnReason, null); ++ } ++ @Nullable ++ public T spawnCreature(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason, @Nullable java.util.function.Consumer op) { ++ // Paper end + // Paper start - Call PreCreatureSpawnEvent + org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(this).getKey()); + if (type != null) { +@@ -334,6 +340,7 @@ public class EntityTypes { + } + // Paper end + T t0 = this.createCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); ++ if (t0 != null && op != null) op.accept(t0); // Paper + + if (t0 != null) { + worldserver.addAllEntities(t0, spawnReason); +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +index 4f81a97b1451fec0bb5fd1479acad97846c40c7c..37e1b2bf33510c3603efadf219b462e667f573c2 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +@@ -62,7 +62,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { + public EntityVillagerTrader(EntityTypes entitytypes, World world) { + super(entitytypes, world); + this.attachedToPlayer = true; +- this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader ++ //this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set. + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java +index e57938b4591bb103b9dd0d0145a62b5a901f2c63..7c8a2151be8a0f48cba1c15d231d5dbdb500b4d6 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java +@@ -114,7 +114,7 @@ public class MobSpawnerTrader implements MobSpawner { + return false; + } + +- EntityVillagerTrader entityvillagertrader = (EntityVillagerTrader) EntityTypes.WANDERING_TRADER.spawnCreature(worldserver, (NBTTagCompound) null, (IChatBaseComponent) null, (EntityHuman) null, blockposition2, EnumMobSpawn.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit ++ EntityVillagerTrader entityvillagertrader = EntityTypes.WANDERING_TRADER.spawnCreature(worldserver, null, null, null, blockposition2, EnumMobSpawn.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, trader -> trader.setDespawnDelay(48000)); // CraftBukkit // Paper - set despawnTimer before spawn events called + + if (entityvillagertrader != null) { + for (int i = 0; i < 2; ++i) { diff --git a/patches/server-unmapped/0693-copy-TESign-isEditable-from-snapshots.patch b/patches/server-unmapped/0693-copy-TESign-isEditable-from-snapshots.patch new file mode 100644 index 0000000000..25bfef8508 --- /dev/null +++ b/patches/server-unmapped/0693-copy-TESign-isEditable-from-snapshots.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 23 Mar 2021 06:43:30 +0000 +Subject: [PATCH] copy TESign#isEditable from snapshots + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java +index f4b601277ef75e5bc39d541a0d13c6eed3b1ef2c..f7e2e23e7468928b6bd6961f223c50ca2826a813 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java +@@ -110,6 +110,7 @@ public class CraftSign extends CraftBlockEntityState implements + } + // Paper end + } ++ sign.isEditable = getSnapshot().isEditable; // Paper - copy manually + } + + // Paper start diff --git a/patches/server-unmapped/0694-Drop-carried-item-when-player-has-disconnected.patch b/patches/server-unmapped/0694-Drop-carried-item-when-player-has-disconnected.patch new file mode 100644 index 0000000000..06a6b95c91 --- /dev/null +++ b/patches/server-unmapped/0694-Drop-carried-item-when-player-has-disconnected.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Thu, 4 Feb 2021 20:32:01 +0300 +Subject: [PATCH] Drop carried item when player has disconnected + +Fixes disappearance of held items, when a player gets disconnected and PlayerDropItemEvent is cancelled. +Closes #5036 + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 484c7cea458dda38e4816fe5f1c05c6836fa38b9..b257d58a298e82f255b09e9575ee42a56a4b7cee 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -79,6 +79,7 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityTypes; + import net.minecraft.world.entity.npc.EntityVillagerAbstract; + import net.minecraft.world.entity.player.EntityHuman; ++import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.level.EnumGamemode; + import net.minecraft.world.level.GameRules; +@@ -609,6 +610,14 @@ public abstract class PlayerList { + } + // Paper end + ++ // Paper - Drop carried item when player has disconnected ++ if (!entityplayer.inventory.getCarried().isEmpty()) { ++ ItemStack carried = entityplayer.inventory.getCarried(); ++ entityplayer.inventory.setCarried(ItemStack.NULL_ITEM); ++ entityplayer.drop(carried, false); ++ } ++ // Paper end ++ + this.savePlayerFile(entityplayer); + if (entityplayer.isPassenger()) { + Entity entity = entityplayer.getRootVehicle(); diff --git a/patches/server-unmapped/0695-forced-whitelist-use-configurable-kick-message.patch b/patches/server-unmapped/0695-forced-whitelist-use-configurable-kick-message.patch new file mode 100644 index 0000000000..70f01cbb40 --- /dev/null +++ b/patches/server-unmapped/0695-forced-whitelist-use-configurable-kick-message.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Sat, 27 Mar 2021 09:24:23 +0100 +Subject: [PATCH] forced whitelist: use configurable kick message + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 879074df54e56a9275957a83c92b467094e95cd4..b3ebf5cd59c827b7426069eda0cb3d47b4386792 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2042,7 +2042,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant +Date: Mon, 29 Mar 2021 09:07:25 +0200 +Subject: [PATCH] Make sure to remove correct TE during TE tick + +This looks like it can cause premature TE removal. + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 78dcba08d6d796d5d97c8304bf1f1e7d1e650d5d..6581fe0d93a5c2e7b444a44c01726e02d4a28e63 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -895,7 +895,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + //this.tileEntityList.remove(tileentity); // Paper - remove unused list + // Paper - prevent double chunk lookups + Chunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getPosition())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again +- chunk.removeTileEntity(tileentity.getPosition()); ++ chunk.removeTileEntity(tileentity.getPosition(), tileentity); // Paper - remove correct TE + } + // Paper end + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +index 34a9f7b2f998f77b1279516cd09397ab6c2ac1cc..0727b12b5ff146b4efa9204bf4f495f2f1aa20b9 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java +@@ -819,10 +819,18 @@ public class Chunk implements IChunkAccess { + + @Override + public void removeTileEntity(BlockPosition blockposition) { ++ // Paper start - remove correct TE ++ removeTileEntity(blockposition, null); ++ } ++ public void removeTileEntity(BlockPosition blockposition, TileEntity match) { ++ // Paper end + if (this.loaded || this.world.s_()) { +- TileEntity tileentity = (TileEntity) this.tileEntities.remove(blockposition); ++ // Paper start ++ TileEntity tileentity = (TileEntity) this.tileEntities.get(blockposition); + +- if (tileentity != null) { ++ if (tileentity != null && (match == null || match == tileentity)) { ++ this.tileEntities.remove(blockposition); ++ // Paper end + tileentity.al_(); + } + } diff --git a/patches/server-unmapped/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/patches/server-unmapped/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch new file mode 100644 index 0000000000..2dc26ac6f5 --- /dev/null +++ b/patches/server-unmapped/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Mon, 5 Apr 2021 18:35:15 -0700 +Subject: [PATCH] Don't ignore result of PlayerEditBookEvent + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 7d584e6d7b4e7b27ca0d51e0eb52a47169aa4b58..ed1e24f12590b8c37d2bd8e234f043bc30dd6cc8 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1146,7 +1146,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + list.stream().map(NBTTagString::a).forEach(nbttaglist::add); + ItemStack old = itemstack.cloneItemStack(); // CraftBukkit + itemstack.a("pages", (NBTBase) nbttaglist); +- CraftEventFactory.handleEditBookEvent(player, i, old, itemstack); // CraftBukkit ++ this.player.inventory.setItem(i, CraftEventFactory.handleEditBookEvent(player, i, old, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) + } + } + diff --git a/patches/server-unmapped/0698-fix-cancelling-block-falling-causing-client-desync.patch b/patches/server-unmapped/0698-fix-cancelling-block-falling-causing-client-desync.patch new file mode 100644 index 0000000000..099ef07a97 --- /dev/null +++ b/patches/server-unmapped/0698-fix-cancelling-block-falling-causing-client-desync.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Sat, 27 Mar 2021 11:13:30 +0100 +Subject: [PATCH] fix cancelling block falling causing client desync + + +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java +index 62d8b53c024888aa43b8fddf8a475dfb8284a4cc..2a61c24dd26edf4c72e977c6024fe233bab08a2f 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java +@@ -14,6 +14,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; + import net.minecraft.network.syncher.DataWatcher; + import net.minecraft.network.syncher.DataWatcherObject; + import net.minecraft.network.syncher.DataWatcherRegistry; ++import net.minecraft.server.level.WorldServer; + import net.minecraft.tags.Tag; + import net.minecraft.tags.TagsBlock; + import net.minecraft.tags.TagsFluid; +@@ -43,6 +44,7 @@ import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.Vec3D; + ++import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class EntityFallingBlock extends Entity { +@@ -116,8 +118,18 @@ public class EntityFallingBlock extends Entity { + + if (this.ticksLived++ == 0) { + blockposition = this.getChunkCoordinates(); +- if (this.world.getType(blockposition).a(block) && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { +- this.world.a(blockposition, false); ++ // Paper start - fix cancelling block falling causing client desync ++ if (this.world.getType(blockposition).isSameInstance(block)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { ++ if (this.world.getType(blockposition).isSameInstance(block)) { //if listener didn't update the block ++ ((WorldServer) world).getChunkProvider().flagDirty(blockposition); ++ } ++ this.die(); ++ return; ++ } else { ++ this.world.setAir(blockposition, false); ++ } ++ // Paper end - fix cancelling block falling causing client desync + } else if (!this.world.isClientSide) { + this.die(); + return; +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +index 3fdafc0ff0c4148ec844dbdc1455d17cdcb4a75a..0d26250887f80d0c250bcd6bc7de303362427d3e 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +@@ -683,6 +683,7 @@ public abstract class BlockBase { + return this.getBlock().a(tag) && predicate.test(this); + } + ++ public final boolean isSameInstance(Block block) { return a(block); } // Paper - OBFHELPER + public boolean a(Block block) { + return this.getBlock().a(block); + } diff --git a/patches/server-unmapped/0699-Expose-protocol-version.patch b/patches/server-unmapped/0699-Expose-protocol-version.patch new file mode 100644 index 0000000000..529b859804 --- /dev/null +++ b/patches/server-unmapped/0699-Expose-protocol-version.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Fri, 26 Mar 2021 11:23:17 +0100 +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 de6a9d795ebaf9c608944415c7dc18c6aee23245..697949abbe662a55fc31ad811863717e35b9d1b6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -486,6 +486,11 @@ public final class CraftMagicNumbers implements UnsafeValues { + public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { + return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; + } ++ ++ @Override ++ public int getProtocolVersion() { ++ return net.minecraft.SharedConstants.getGameVersion().getProtocolVersion(); ++ } + // Paper end + + /** diff --git a/patches/server-unmapped/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/server-unmapped/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch new file mode 100644 index 0000000000..069a5fb10f --- /dev/null +++ b/patches/server-unmapped/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch @@ -0,0 +1,132 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Thu, 1 Apr 2021 00:34:02 -0700 +Subject: [PATCH] Allow for Component suggestion tooltips in + AsyncTabCompleteEvent + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index ed1e24f12590b8c37d2bd8e234f043bc30dd6cc8..a0d48ef2b27267da0864baa9059c7c3e5aef6f48 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -771,12 +771,11 @@ public class PlayerConnection implements PacketListenerPlayIn { + + // Paper start - async tab completion + com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; +- java.util.List completions = new java.util.ArrayList<>(); + String buffer = packetplayintabcomplete.c(); +- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), + buffer, true, null); + event.callEvent(); +- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); ++ java.util.List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); + // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server + if (!event.isHandled()) { + if (!event.isCancelled()) { +@@ -795,10 +794,16 @@ public class PlayerConnection implements PacketListenerPlayIn { + }); + } + } else if (!completions.isEmpty()) { +- com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); ++ com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); + +- builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); +- completions.forEach(builder::suggest); ++ final com.mojang.brigadier.suggestion.SuggestionsBuilder builder = builder0.createOffset(builder0.getInput().lastIndexOf(' ') + 1); ++ completions.forEach(completion -> { ++ if (completion.tooltip() == null) { ++ builder.suggest(completion.suggestion()); ++ } else { ++ builder.suggest(completion.suggestion(), PaperAdventure.asVanilla(completion.tooltip())); ++ } ++ }); + com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); + com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); + suggestEvent.setCancelled(suggestions.isEmpty()); +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index c5e00bd9e2790992202aadf8eec2002fc88c78f1..dd8e87ad192c19743577bb95253a127072ea196c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -29,34 +29,56 @@ public class ConsoleCommandCompleter implements Completer { + final CraftServer server = this.server.server; + final String buffer = line.line(); + // Async Tab Complete +- com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; +- java.util.List completions = new java.util.ArrayList<>(); +- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, +- buffer, true, null); ++ final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event = ++ new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), buffer, true, null); + event.callEvent(); +- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); ++ final List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); + + if (event.isCancelled() || event.isHandled()) { + // Still fire sync event with the provided completions, if someone is listening + if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { +- List finalCompletions = completions; ++ List finalCompletions = new java.util.ArrayList<>(completions); + Waitable> syncCompletions = new Waitable>() { + @Override + protected List evaluate() { +- org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); ++ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, ++ finalCompletions.stream() ++ .map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::suggestion) ++ .collect(java.util.stream.Collectors.toList())); + return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); + } + }; + server.getServer().processQueue.add(syncCompletions); + try { +- completions = syncCompletions.get(); ++ final List legacyCompletions = syncCompletions.get(); ++ completions.removeIf(it -> !legacyCompletions.contains(it.suggestion())); // remove any suggestions that were removed ++ // add any new suggestions ++ for (final String completion : legacyCompletions) { ++ if (notNewSuggestion(completions, completion)) { ++ continue; ++ } ++ completions.add(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion(completion)); ++ } + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } + } + + if (!completions.isEmpty()) { +- candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); ++ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { ++ if (completion.suggestion().isEmpty()) { ++ continue; ++ } ++ candidates.add(new Candidate( ++ completion.suggestion(), ++ completion.suggestion(), ++ null, ++ io.papermc.paper.adventure.PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null), ++ null, ++ null, ++ false ++ )); ++ } + } + return; + } +@@ -106,4 +128,15 @@ public class ConsoleCommandCompleter implements Completer { + Thread.currentThread().interrupt(); + } + } ++ ++ // Paper start ++ private boolean notNewSuggestion(final List completions, final String completion) { ++ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion it : completions) { ++ if (it.suggestion().equals(completion)) { ++ return true; ++ } ++ } ++ return false; ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0701-Enhance-console-tab-completions-for-brigadier-comman.patch b/patches/server-unmapped/0701-Enhance-console-tab-completions-for-brigadier-comman.patch new file mode 100644 index 0000000000..9b4a89bc49 --- /dev/null +++ b/patches/server-unmapped/0701-Enhance-console-tab-completions-for-brigadier-comman.patch @@ -0,0 +1,316 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Tue, 30 Mar 2021 16:06:08 -0700 +Subject: [PATCH] Enhance console tab completions for brigadier commands + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index c56e7fb18f9a56c8025eb70a524f028b5942da37..efc1e42d606e1c9feb1a4871c0714933ae92a1b2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -479,4 +479,11 @@ public class PaperConfig { + private static void fixEntityPositionDesync() { + fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); + } ++ ++ public static boolean enableBrigadierConsoleHighlighting = true; ++ public static boolean enableBrigadierConsoleCompletions = true; ++ private static void consoleSettings() { ++ enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); ++ enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +index 89eeb9d202405747409e65fcf226d95379987e29..ad87b575a0261200b280884e054a59e3ce59c41c 100644 +--- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java ++++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +@@ -1,5 +1,7 @@ + package com.destroystokyo.paper.console; + ++import com.destroystokyo.paper.PaperConfig; ++import io.papermc.paper.console.BrigadierCommandHighlighter; + import net.minecraft.server.dedicated.DedicatedServer; + import net.minecrell.terminalconsole.SimpleTerminalConsole; + import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; +@@ -16,11 +18,15 @@ public final class PaperConsole extends SimpleTerminalConsole { + + @Override + protected LineReader buildReader(LineReaderBuilder builder) { +- return super.buildReader(builder ++ builder + .appName("Paper") + .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) + .completer(new ConsoleCommandCompleter(this.server)) +- ); ++ .option(LineReader.Option.COMPLETE_IN_WORD, true); ++ if (PaperConfig.enableBrigadierConsoleHighlighting) { ++ builder.highlighter(new BrigadierCommandHighlighter(this.server, this.server.getServerCommandListener())); ++ } ++ return super.buildReader(builder); + } + + @Override +diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..edd231d95a04a1c4832f1ca8a3da6a56e9472ca1 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java +@@ -0,0 +1,95 @@ ++package io.papermc.paper.console; ++ ++import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion; ++import com.mojang.brigadier.CommandDispatcher; ++import com.mojang.brigadier.ParseResults; ++import com.mojang.brigadier.StringReader; ++import com.mojang.brigadier.suggestion.Suggestion; ++import io.papermc.paper.adventure.PaperAdventure; ++import net.minecraft.commands.CommandListenerWrapper; ++import net.minecraft.network.chat.ChatComponentUtils; ++import net.minecraft.server.dedicated.DedicatedServer; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jline.reader.Candidate; ++import org.jline.reader.LineReader; ++import org.jline.reader.ParsedLine; ++ ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++ ++import static com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion; ++ ++public final class BrigadierCommandCompleter { ++ private final CommandListenerWrapper commandSourceStack; ++ private final DedicatedServer server; ++ ++ public BrigadierCommandCompleter(final @NonNull DedicatedServer server, final @NonNull CommandListenerWrapper commandSourceStack) { ++ this.server = server; ++ this.commandSourceStack = commandSourceStack; ++ } ++ ++ public void complete(final @NonNull LineReader reader, final @NonNull ParsedLine line, final @NonNull List candidates, final @NonNull List existing) { ++ if (!com.destroystokyo.paper.PaperConfig.enableBrigadierConsoleCompletions) { ++ this.addCandidates(candidates, Collections.emptyList(), existing); ++ return; ++ } ++ final CommandDispatcher dispatcher = this.server.getCommandDispatcher().dispatcher(); ++ final ParseResults results = dispatcher.parse(prepareStringReader(line.line()), this.commandSourceStack); ++ this.addCandidates( ++ candidates, ++ dispatcher.getCompletionSuggestions(results, line.cursor()).join().getList(), ++ existing ++ ); ++ } ++ ++ private void addCandidates( ++ final @NonNull List candidates, ++ final @NonNull List brigSuggestions, ++ final @NonNull List existing ++ ) { ++ final List completions = new ArrayList<>(); ++ brigSuggestions.forEach(it -> completions.add(toCompletion(it))); ++ for (final Completion completion : existing) { ++ if (completion.suggestion().isEmpty() || brigSuggestions.stream().anyMatch(it -> it.getText().equals(completion.suggestion()))) { ++ continue; ++ } ++ completions.add(completion); ++ } ++ for (final Completion completion : completions) { ++ if (completion.suggestion().isEmpty()) { ++ continue; ++ } ++ candidates.add(toCandidate(completion)); ++ } ++ } ++ ++ private static @NonNull Candidate toCandidate(final @NonNull Completion completion) { ++ final String suggestionText = completion.suggestion(); ++ final String suggestionTooltip = PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null); ++ return new Candidate( ++ suggestionText, ++ suggestionText, ++ null, ++ suggestionTooltip, ++ null, ++ null, ++ false ++ ); ++ } ++ ++ private static @NonNull Completion toCompletion(final @NonNull Suggestion suggestion) { ++ if (suggestion.getTooltip() == null) { ++ return completion(suggestion.getText()); ++ } ++ return completion(suggestion.getText(), PaperAdventure.asAdventure(ChatComponentUtils.fromMessage(suggestion.getTooltip()))); ++ } ++ ++ static @NonNull StringReader prepareStringReader(final @NonNull String line) { ++ final StringReader stringReader = new StringReader(line); ++ if (stringReader.canRead() && stringReader.peek() == '/') { ++ stringReader.skip(); ++ } ++ return stringReader; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d51d20a6d1c0c956cdf425503a6c1401acd9c854 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java +@@ -0,0 +1,57 @@ ++package io.papermc.paper.console; ++ ++import com.mojang.brigadier.ParseResults; ++import com.mojang.brigadier.context.ParsedCommandNode; ++import com.mojang.brigadier.tree.LiteralCommandNode; ++import net.minecraft.commands.CommandListenerWrapper; ++import net.minecraft.server.dedicated.DedicatedServer; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jline.reader.Highlighter; ++import org.jline.reader.LineReader; ++import org.jline.utils.AttributedString; ++import org.jline.utils.AttributedStringBuilder; ++import org.jline.utils.AttributedStyle; ++ ++public final class BrigadierCommandHighlighter implements Highlighter { ++ private static final int[] COLORS = {AttributedStyle.CYAN, AttributedStyle.YELLOW, AttributedStyle.GREEN, AttributedStyle.MAGENTA, /* Client uses GOLD here, not BLUE, however there is no GOLD AttributedStyle. */ AttributedStyle.BLUE}; ++ private final CommandListenerWrapper commandSourceStack; ++ private final DedicatedServer server; ++ ++ public BrigadierCommandHighlighter(final @NonNull DedicatedServer server, final @NonNull CommandListenerWrapper commandSourceStack) { ++ this.server = server; ++ this.commandSourceStack = commandSourceStack; ++ } ++ ++ @Override ++ public AttributedString highlight(final @NonNull LineReader reader, final @NonNull String buffer) { ++ final AttributedStringBuilder builder = new AttributedStringBuilder(); ++ final ParseResults results = this.server.getCommandDispatcher().dispatcher().parse(BrigadierCommandCompleter.prepareStringReader(buffer), this.commandSourceStack); ++ int pos = 0; ++ if (buffer.startsWith("/")) { ++ builder.append("/", AttributedStyle.DEFAULT); ++ pos = 1; ++ } ++ int component = -1; ++ for (final ParsedCommandNode node : results.getContext().getLastChild().getNodes()) { ++ if (node.getRange().getStart() >= buffer.length()) { ++ break; ++ } ++ final int start = node.getRange().getStart(); ++ final int end = Math.min(node.getRange().getEnd(), buffer.length()); ++ builder.append(buffer.substring(pos, start), AttributedStyle.DEFAULT); ++ if (node.getNode() instanceof LiteralCommandNode) { ++ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT); ++ } else { ++ if (++component >= COLORS.length) { ++ component = 0; ++ } ++ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT.foreground(COLORS[component])); ++ } ++ pos = end; ++ } ++ if (pos < buffer.length()) { ++ builder.append((buffer.substring(pos)), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)); ++ } ++ return builder.toAttributedString(); ++ } ++} +diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java +index 978d3b79b5f953e67263598dff09bcb40b6e3f31..47dc8450fff5583d70c969c0b92b96a665a02305 100644 +--- a/src/main/java/net/minecraft/commands/CommandDispatcher.java ++++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java +@@ -440,7 +440,7 @@ public class CommandDispatcher { + }; + } + +- public com.mojang.brigadier.CommandDispatcher a() { ++ public com.mojang.brigadier.CommandDispatcher a() { return this.dispatcher(); } public com.mojang.brigadier.CommandDispatcher dispatcher() { // Paper - OBFHELPER + return this.b; + } + +diff --git a/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java b/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java +index b00e5d811ddfa12937f57bac4debb2fdd057d6e1..d14e4bf09bc43e78a9da07ea062ed886d27c7cc0 100644 +--- a/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java ++++ b/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java +@@ -90,7 +90,7 @@ public class ChatComponentUtils { + ChatComponentText chatcomponenttext = new ChatComponentText(""); + boolean flag = true; + +- for (Iterator iterator = collection.iterator(); iterator.hasNext(); flag = false) { ++ for (Iterator iterator = collection.iterator(); iterator.hasNext(); flag = false) { // Paper - decompile fix + T t0 = iterator.next(); + + if (!flag) { +@@ -108,7 +108,7 @@ public class ChatComponentUtils { + return new ChatMessage("chat.square_brackets", new Object[]{ichatbasecomponent}); + } + +- public static IChatBaseComponent a(Message message) { ++ public static IChatBaseComponent a(Message message) { return fromMessage(message); } public static IChatBaseComponent fromMessage(final @org.checkerframework.checker.nullness.qual.NonNull Message message) { // Paper - OBFHELPER + return (IChatBaseComponent) (message instanceof IChatBaseComponent ? (IChatBaseComponent) message : new ChatComponentText(message.getString())); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +index dd8e87ad192c19743577bb95253a127072ea196c..5e1312941f9a554fc83adc02e81980069b8d015d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java ++++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +@@ -18,9 +18,11 @@ import org.bukkit.event.server.TabCompleteEvent; + + public class ConsoleCommandCompleter implements Completer { + private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer ++ private final io.papermc.paper.console.BrigadierCommandCompleter brigadierCompleter; // Paper + + public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer + this.server = server; ++ this.brigadierCompleter = new io.papermc.paper.console.BrigadierCommandCompleter(this.server, this.server.getServerCommandListener()); // Paper + } + + // Paper start - Change method signature for JLine update +@@ -64,7 +66,7 @@ public class ConsoleCommandCompleter implements Completer { + } + } + +- if (!completions.isEmpty()) { ++ if (false && !completions.isEmpty()) { + for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { + if (completion.suggestion().isEmpty()) { + continue; +@@ -80,6 +82,7 @@ public class ConsoleCommandCompleter implements Completer { + )); + } + } ++ this.addCompletions(reader, line, candidates, completions); + return; + } + +@@ -99,10 +102,12 @@ public class ConsoleCommandCompleter implements Completer { + try { + List offers = waitable.get(); + if (offers == null) { ++ this.addCompletions(reader, line, candidates, Collections.emptyList()); // Paper + return; // Paper - Method returns void + } + + // Paper start - JLine update ++ /* + for (String completion : offers) { + if (completion.isEmpty()) { + continue; +@@ -110,6 +115,8 @@ public class ConsoleCommandCompleter implements Completer { + + candidates.add(new Candidate(completion)); + } ++ */ ++ this.addCompletions(reader, line, candidates, offers.stream().map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::completion).collect(java.util.stream.Collectors.toList())); + // Paper end + + // Paper start - JLine handles cursor now +@@ -138,5 +145,9 @@ public class ConsoleCommandCompleter implements Completer { + } + return false; + } ++ ++ private void addCompletions(final LineReader reader, final ParsedLine line, final List candidates, final List existing) { ++ this.brigadierCompleter.complete(reader, line, candidates, existing); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/patches/server-unmapped/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch new file mode 100644 index 0000000000..05cbf1582f --- /dev/null +++ b/patches/server-unmapped/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Fri, 19 Mar 2021 00:33:15 -0500 +Subject: [PATCH] Fix PlayerItemConsumeEvent cancelling properly + +When the active item is not cleared, the item is still readied +for use and will repeatedly trigger the PlayerItemConsumeEvent +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/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 78d874c44cf8311af06b085db12fbe0cacd6cf7d..2657dd71213455e2da3a4ff4d338a33896ffe855 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -3351,6 +3351,7 @@ public abstract class EntityLiving extends Entity { + world.getServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { ++ this.clearActiveItem(); // Paper - event is using an item, clear active item to reset its use + // Update client + ((EntityPlayer) this).getBukkitEntity().updateInventory(); + ((EntityPlayer) this).getBukkitEntity().updateScaledHealth(); diff --git a/patches/server-unmapped/0703-Add-bypass-host-check.patch b/patches/server-unmapped/0703-Add-bypass-host-check.patch new file mode 100644 index 0000000000..b28224aedf --- /dev/null +++ b/patches/server-unmapped/0703-Add-bypass-host-check.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 18 Apr 2021 21:27:01 +0100 +Subject: [PATCH] Add bypass host check + +Paper.bypassHostCheck + +Seriously, fix your firewalls. -.- + +diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java +index 26fe1f612e9dab37e5bf6bc431eb362bd7e4803a..74006c0af831c0e6a2b84b3638e397ab54984dc5 100644 +--- a/src/main/java/net/minecraft/server/network/HandshakeListener.java ++++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java +@@ -30,6 +30,7 @@ public class HandshakeListener implements PacketHandshakingInListener { + private static final IChatBaseComponent a = new ChatComponentText("Ignoring status request"); + private final MinecraftServer b; + private final NetworkManager c; final NetworkManager getNetworkManager() { return this.c; } // Paper - OBFHELPER ++ private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper + + public HandshakeListener(MinecraftServer minecraftserver, NetworkManager networkmanager) { + this.b = minecraftserver; +@@ -118,7 +119,7 @@ public class HandshakeListener implements PacketHandshakingInListener { + // Spigot Start + //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! + String[] split = packethandshakinginsetprotocol.hostname.split("\00"); +- if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { ++ if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper + packethandshakinginsetprotocol.hostname = split[0]; + c.socketAddress = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) c.getSocketAddress()).getPort()); + c.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); diff --git a/patches/server-unmapped/0704-don-t-throw-when-loading-invalid-TEs.patch b/patches/server-unmapped/0704-don-t-throw-when-loading-invalid-TEs.patch new file mode 100644 index 0000000000..eb77500117 --- /dev/null +++ b/patches/server-unmapped/0704-don-t-throw-when-loading-invalid-TEs.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Tue, 20 Apr 2021 01:15:04 +0100 +Subject: [PATCH] don't throw when loading invalid TEs + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +index f1e586754396439dfb70a4d63e3b8b34fb36ebf4..93d02ccb87c17404c55884f52ae40c7b7ddfb103 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +@@ -2,6 +2,7 @@ package net.minecraft.world.level.block.entity; + + import javax.annotation.Nullable; + import net.minecraft.CrashReportSystemDetails; ++import net.minecraft.ResourceKeyInvalidException; + import net.minecraft.core.BlockPosition; + import net.minecraft.core.IRegistry; + import net.minecraft.nbt.NBTTagCompound; +@@ -133,7 +134,13 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / + public static TileEntity create(IBlockData iblockdata, NBTTagCompound nbttagcompound) { + String s = nbttagcompound.getString("id"); + +- return (TileEntity) IRegistry.BLOCK_ENTITY_TYPE.getOptional(new MinecraftKey(s)).map((tileentitytypes) -> { ++ // Paper ++ MinecraftKey minecraftKey = null; ++ try { ++ minecraftKey = new MinecraftKey(s); ++ } catch (ResourceKeyInvalidException ex) {} ++ // Paper end ++ return (TileEntity) IRegistry.BLOCK_ENTITY_TYPE.getOptional(minecraftKey).map((tileentitytypes) -> { + try { + return tileentitytypes.a(); + } catch (Throwable throwable) { diff --git a/patches/server-unmapped/0705-Set-area-affect-cloud-rotation.patch b/patches/server-unmapped/0705-Set-area-affect-cloud-rotation.patch new file mode 100644 index 0000000000..25e0a9b5a8 --- /dev/null +++ b/patches/server-unmapped/0705-Set-area-affect-cloud-rotation.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Mon, 5 Apr 2021 16:58:20 -0400 +Subject: [PATCH] Set area affect cloud rotation + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index a152d5bec8bf0dd87239b0a3432fb589cea61bd8..42417aee4796d39d110e69cb707bd3b7bac30027 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1977,6 +1977,7 @@ public class CraftWorld implements World { + entity = EntityTypes.LIGHTNING_BOLT.a(world); + } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { + entity = new EntityAreaEffectCloud(world, x, y, z); ++ entity.setPositionRotation(x, y, z, yaw, pitch); // Paper - Set area effect cloud Rotation + } else if (EvokerFangs.class.isAssignableFrom(clazz)) { + entity = new EntityEvokerFangs(world, x, y, z, (float) Math.toRadians(yaw), 0, null); + } diff --git a/patches/server-unmapped/0706-add-isDeeplySleeping-to-HumanEntity.patch b/patches/server-unmapped/0706-add-isDeeplySleeping-to-HumanEntity.patch new file mode 100644 index 0000000000..fe93a5a26e --- /dev/null +++ b/patches/server-unmapped/0706-add-isDeeplySleeping-to-HumanEntity.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 8 Apr 2021 17:36:10 -0700 +Subject: [PATCH] add isDeeplySleeping 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 0a0e9df604723802fe65d871ff48aa9fd9b756bf..6e28e0247200fbbc470ba317575f0c714f74d5bf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -123,6 +123,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + } + } + ++ // Paper start ++ @Override ++ public boolean isDeeplySleeping() { ++ return getHandle().isDeeplySleeping(); ++ } ++ // Paper end ++ + @Override + public int getSleepTicks() { + return getHandle().sleepTicks; diff --git a/patches/server-unmapped/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch b/patches/server-unmapped/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch new file mode 100644 index 0000000000..cee651ba1d --- /dev/null +++ b/patches/server-unmapped/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alphaesia +Date: Fri, 23 Apr 2021 09:57:56 +1200 +Subject: [PATCH] Fix duplicating /give items on item drop cancel + +Fixes SPIGOT-2942 (Give command fires PlayerDropItemEvent, cancelling it causes item duplication). + +For every stack of items to give, /give puts the item stack straight +into the player's inventory. However, it also summons a "fake item" +at the player's location. When the PlayerDropItemEvent for this fake +item is cancelled, the server attempts to put the item back into the +player's inventory. The result is that the fake item, which is never +meant to be obtained, is combined with the real items injected directly +into the player's inventory. This means more items than the amount +specified in /give are given to the player - one for every stack of +items given. (e.g. /give @s dirt 1 gives you 2 dirt). + +While this isn't a big issue for general building usage, it can affect +e.g. adventure maps where the number of items the player receives is +important (and you want to restrict the player from throwing items). + +If there are any overflow items that didn't make it into the inventory +(insufficient space), those items are dropped as a real item instead +of a fake one. While cancelling this drop would also result in the +server attempting to put those items into the inventory, since it is +full this has no effect. + +Just ignoring cancellation of the PlayerDropItemEvent seems like the +cleanest and least intrusive way to fix it. + +diff --git a/src/main/java/net/minecraft/server/commands/CommandGive.java b/src/main/java/net/minecraft/server/commands/CommandGive.java +index 6685bf1757458d908e32d4069f7a8a22a28c28d7..a10207f7cb9455e29db7e6906cb2138ad5609a1f 100644 +--- a/src/main/java/net/minecraft/server/commands/CommandGive.java ++++ b/src/main/java/net/minecraft/server/commands/CommandGive.java +@@ -49,7 +49,7 @@ public class CommandGive { + + if (flag && itemstack.isEmpty()) { + itemstack.setCount(1); +- entityitem = entityplayer.drop(itemstack, false); ++ entityitem = entityplayer.drop(itemstack, false, false, true); // Paper - Fix duplicating /give items on item drop cancel + if (entityitem != null) { + entityitem.s(); + } +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index ec0956a98c133bcd3d4f92f696c667eab6ff98f1..3a62bde04d7fbb6c571cfef11d4f6891e11c7ac8 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -642,6 +642,13 @@ public abstract class EntityHuman extends EntityLiving { + + @Nullable + public EntityItem a(ItemStack itemstack, boolean flag, boolean flag1) { ++ // Paper start - Fix duplicating /give items on item drop cancel ++ return this.drop(itemstack, flag, flag1, false); ++ } ++ ++ @Nullable ++ public EntityItem drop(ItemStack itemstack, boolean flag, boolean flag1, boolean alwaysSucceed) { ++ // Paper end + if (itemstack.isEmpty()) { + return null; + } else { +@@ -683,7 +690,7 @@ public abstract class EntityHuman extends EntityLiving { + PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); + this.world.getServer().getPluginManager().callEvent(event); + +- if (event.isCancelled()) { ++ if (event.isCancelled() && !alwaysSucceed) { // Paper - Fix duplicating /give items on item drop cancel + org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); + if (flag1 && (cur == null || cur.getAmount() == 0)) { + // The complete stack was dropped diff --git a/patches/server-unmapped/0708-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/server-unmapped/0708-add-consumeFuel-to-FurnaceBurnEvent.patch new file mode 100644 index 0000000000..410ceaf296 --- /dev/null +++ b/patches/server-unmapped/0708-add-consumeFuel-to-FurnaceBurnEvent.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 22 Apr 2021 16:45:28 -0700 +Subject: [PATCH] add consumeFuel to FurnaceBurnEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +index 1997139fb87dc1947acfdf02e1f116577c3fa943..9ce19b89c16eb6edd3d5d5cc87a966a37f66895c 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +@@ -331,7 +331,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + if (this.isBurning() && furnaceBurnEvent.isBurning()) { + // CraftBukkit end + flag1 = true; +- if (!itemstack.isEmpty()) { ++ if (!itemstack.isEmpty() && furnaceBurnEvent.willConsumeFuel()) { // Paper + Item item = itemstack.getItem(); + + itemstack.subtract(1); diff --git a/patches/server-unmapped/0709-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/server-unmapped/0709-add-get-set-drop-chance-to-EntityEquipment.patch new file mode 100644 index 0000000000..c205b0e09c --- /dev/null +++ b/patches/server-unmapped/0709-add-get-set-drop-chance-to-EntityEquipment.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 22 Apr 2021 00:28:11 -0700 +Subject: [PATCH] add get-set drop chance to EntityEquipment + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java +index 27e0e2767b11195231055f64446afb7ae5e08988..064d8adb47404b0fb839cfa646dfe04f2a2eefb6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java +@@ -245,6 +245,17 @@ public class CraftEntityEquipment implements EntityEquipment { + public void setBootsDropChance(float chance) { + setDropChance(EnumItemSlot.FEET, chance); + } ++ // Paper start ++ @Override ++ public float getDropChance(EquipmentSlot slot) { ++ return getDropChance(CraftEquipmentSlot.getNMS(slot)); ++ } ++ ++ @Override ++ public void setDropChance(EquipmentSlot slot, float chance) { ++ setDropChance(CraftEquipmentSlot.getNMS(slot), chance); ++ } ++ // Paper end + + private void setDropChance(EnumItemSlot slot, float chance) { + if (slot == EnumItemSlot.MAINHAND || slot == EnumItemSlot.OFFHAND) { +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +index b812e1af411dd7f4509620b6b49b7897603dc970..dacb8e127403ef5234d6bca62aa4a35431724e9e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +@@ -354,4 +354,15 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i + public void setBootsDropChance(float chance) { + throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); + } ++ // Paper start ++ @Override ++ public float getDropChance(EquipmentSlot slot) { ++ return 1; ++ } ++ ++ @Override ++ public void setDropChance(EquipmentSlot slot, float chance) { ++ throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0710-fix-PigZombieAngerEvent-cancellation.patch b/patches/server-unmapped/0710-fix-PigZombieAngerEvent-cancellation.patch new file mode 100644 index 0000000000..532dace60c --- /dev/null +++ b/patches/server-unmapped/0710-fix-PigZombieAngerEvent-cancellation.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Thu, 18 Mar 2021 21:38:01 +0100 +Subject: [PATCH] fix PigZombieAngerEvent cancellation + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java +index 59ea1432152051ce8a60c0a526db787593f0e744..1212c8e2af1f7e658d8bec7e5474a35190b1949e 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java +@@ -28,6 +28,7 @@ public abstract class PathfinderGoal { + + public void c() { this.start(); } public void start() {} // Paper - OBFHELPER + ++ public final void onTaskResetObfHelper() { d(); } // Paper - OBFHELPER + public void d() { + onTaskReset(); // Paper + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java +index cc1bff409cad2eb6264d4b691599576960080ccd..d10d1b768601236b9892461ee41d61c7239d1a07 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java +@@ -49,6 +49,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { + private UUID br; + private static final IntRange bs = TimeRange.a(4, 6); + private int bt; ++ private PathfinderGoalHurtByTarget pathfinderGoalHurtByTarget; // Paper + + public EntityPigZombie(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -69,7 +70,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { + protected void m() { + this.goalSelector.a(2, new PathfinderGoalZombieAttack(this, 1.0D, false)); + this.goalSelector.a(7, new PathfinderGoalRandomStrollLand(this, 1.0D)); +- this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this).a(new Class[0])); // CraftBukkit - decompile error ++ this.targetSelector.a(1, pathfinderGoalHurtByTarget = new PathfinderGoalHurtByTarget(this).a(new Class[0])); // CraftBukkit - decompile error // Paper - assign field + this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_)); + this.targetSelector.a(3, new PathfinderGoalUniversalAngerReset<>(this, true)); + } +@@ -172,6 +173,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { + this.world.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.setAngerTarget(null); ++ pathfinderGoalHurtByTarget.onTaskResetObfHelper(); // Paper - clear goalTargets to fix cancellation + return; + } + this.setAnger(event.getNewAnger()); diff --git a/patches/server-unmapped/0711-Fix-checkReach-check-for-Shulker-boxes.patch b/patches/server-unmapped/0711-Fix-checkReach-check-for-Shulker-boxes.patch new file mode 100644 index 0000000000..0a4779d24e --- /dev/null +++ b/patches/server-unmapped/0711-Fix-checkReach-check-for-Shulker-boxes.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sun, 4 Apr 2021 14:25:04 -0400 +Subject: [PATCH] Fix checkReach check for Shulker boxes + + +diff --git a/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java b/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java +index fdc47411aa3e0e27d3a20c18274fef0a0db9a5b1..6ef70e209a8e282f7c00d80678636c2b8aa49b7a 100644 +--- a/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java ++++ b/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java +@@ -65,6 +65,7 @@ public class ContainerShulkerBox extends Container { + + @Override + public boolean canUse(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // Paper - Add reachable override for ContainerShulkerBox + return this.c.a(entityhuman); + } + diff --git a/patches/server-unmapped/0712-fix-PlayerItemHeldEvent-firing-twice.patch b/patches/server-unmapped/0712-fix-PlayerItemHeldEvent-firing-twice.patch new file mode 100644 index 0000000000..83d6c945b5 --- /dev/null +++ b/patches/server-unmapped/0712-fix-PlayerItemHeldEvent-firing-twice.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Thu, 22 Apr 2021 19:02:07 -0700 +Subject: [PATCH] fix PlayerItemHeldEvent firing twice + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java +index d68f3e6b35f0af846c8a66710c5752508c095179..0e8ee44d0104ca7c666f57bdb54e0957935d5b34 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java +@@ -24,6 +24,7 @@ public class PacketPlayInHeldItemSlot implements Packet { + packetlistenerplayin.a(this); + } + ++ public int getItemInHandIndex() { return b(); } // Paper - OBFHELPER + public int b() { + return this.itemInHandIndex; + } +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index a0d48ef2b27267da0864baa9059c7c3e5aef6f48..957d3b56aea116f947ca8fb74127f652de72b701 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -1909,6 +1909,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + PlayerConnectionUtils.ensureMainThread(packetplayinhelditemslot, this, this.player.getWorldServer()); + if (this.player.isFrozen()) return; // CraftBukkit + if (packetplayinhelditemslot.b() >= 0 && packetplayinhelditemslot.b() < PlayerInventory.getHotbarSize()) { ++ if (packetplayinhelditemslot.getItemInHandIndex() == this.player.inventory.itemInHandIndex) { return; } // Paper - don't fire itemheldevent when there wasn't a slot change + PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.itemInHandIndex, packetplayinhelditemslot.b()); + this.server.getPluginManager().callEvent(event); + if (event.isCancelled()) { diff --git a/patches/server-unmapped/0713-Added-PlayerDeepSleepEvent.patch b/patches/server-unmapped/0713-Added-PlayerDeepSleepEvent.patch new file mode 100644 index 0000000000..cf56b0987c --- /dev/null +++ b/patches/server-unmapped/0713-Added-PlayerDeepSleepEvent.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 21 Apr 2021 15:58:19 -0700 +Subject: [PATCH] Added PlayerDeepSleepEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 3a62bde04d7fbb6c571cfef11d4f6891e11c7ac8..3a13e7a050db7f5c93d810afe56325495cec7aa4 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -235,6 +235,11 @@ public abstract class EntityHuman extends EntityLiving { + + if (this.isSleeping()) { + ++this.sleepTicks; ++ // Paper start ++ if (this.sleepTicks == 100) { ++ if (!new io.papermc.paper.event.player.PlayerDeepSleepEvent((Player) getBukkitEntity()).callEvent()) { this.sleepTicks = Integer.MIN_VALUE; } ++ } ++ // Paper end + if (this.sleepTicks > 100) { + this.sleepTicks = 100; + } diff --git a/patches/server-unmapped/0714-More-World-API.patch b/patches/server-unmapped/0714-More-World-API.patch new file mode 100644 index 0000000000..5fbdab5402 --- /dev/null +++ b/patches/server-unmapped/0714-More-World-API.patch @@ -0,0 +1,146 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 7 Jul 2020 10:52:34 -0700 +Subject: [PATCH] More World API + + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index fd204ab68d8245503c0a8c4e7ce1a0a6bac7d138..6aace2155258d8257d53ebfcb20c37ea7497c02c 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1869,6 +1869,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + return !this.worldDataServer.getGeneratorSettings().shouldGenerateMapFeatures() ? null : this.getChunkProvider().getChunkGenerator().findNearestMapFeature(this, structuregenerator, blockposition, i, flag); // CraftBukkit + } + ++ public BlockPosition getNearestBiome(BiomeBase biomeBase, BlockPosition blockPosition, int radius, int step) { return this.a(biomeBase, blockPosition, radius, step); } // Paper - OBFHELPER + @Nullable + public BlockPosition a(BiomeBase biomebase, BlockPosition blockposition, int i, int j) { + return this.getChunkProvider().getChunkGenerator().getWorldChunkManager().a(blockposition.getX(), blockposition.getY(), blockposition.getZ(), i, j, (biomebase1) -> { +@@ -1891,6 +1892,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + return this.savingDisabled; + } + ++ public IRegistryCustom getWorldCustomRegistry() { return r(); } // Paper - OBFHELPER + @Override + public IRegistryCustom r() { + return this.server.getCustomRegistry(); +diff --git a/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java b/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java +index 72bc1a1e1c2153550313e93cf7df901a514a9bef..be6d63bcf15027e02a0bfbee0792c24f2300b27e 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java ++++ b/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java +@@ -142,10 +142,10 @@ public class DimensionManager { + public static IRegistryCustom.Dimension a(IRegistryCustom.Dimension iregistrycustom_dimension) { + IRegistryWritable iregistrywritable = iregistrycustom_dimension.b(IRegistry.K); + +- iregistrywritable.a(DimensionManager.OVERWORLD, (Object) DimensionManager.OVERWORLD_IMPL, Lifecycle.stable()); +- iregistrywritable.a(DimensionManager.l, (Object) DimensionManager.m, Lifecycle.stable()); +- iregistrywritable.a(DimensionManager.THE_NETHER, (Object) DimensionManager.THE_NETHER_IMPL, Lifecycle.stable()); +- iregistrywritable.a(DimensionManager.THE_END, (Object) DimensionManager.THE_END_IMPL, Lifecycle.stable()); ++ iregistrywritable.a(DimensionManager.OVERWORLD, DimensionManager.OVERWORLD_IMPL, Lifecycle.stable()); // Paper - decompile fix ++ iregistrywritable.a(DimensionManager.l, DimensionManager.m, Lifecycle.stable()); // Paper - decompile fix ++ iregistrywritable.a(DimensionManager.THE_NETHER, DimensionManager.THE_NETHER_IMPL, Lifecycle.stable()); // Paper - decompile fix ++ iregistrywritable.a(DimensionManager.THE_END, DimensionManager.THE_END_IMPL, Lifecycle.stable()); // Paper - decompile fix + return iregistrycustom_dimension; + } + +@@ -164,10 +164,10 @@ public class DimensionManager { + public static RegistryMaterials a(IRegistry iregistry, IRegistry iregistry1, IRegistry iregistry2, long i) { + RegistryMaterials registrymaterials = new RegistryMaterials<>(IRegistry.M, Lifecycle.experimental()); + +- registrymaterials.a(WorldDimension.THE_NETHER, (Object) (new WorldDimension(() -> { ++ registrymaterials.a(WorldDimension.THE_NETHER, (new WorldDimension(() -> { // Paper - decompile fix + return (DimensionManager) iregistry.d(DimensionManager.THE_NETHER); + }, b(iregistry1, iregistry2, i))), Lifecycle.stable()); +- registrymaterials.a(WorldDimension.THE_END, (Object) (new WorldDimension(() -> { ++ registrymaterials.a(WorldDimension.THE_END, (new WorldDimension(() -> { // Paper - decompile fix + return (DimensionManager) iregistry.d(DimensionManager.THE_END); + }, a(iregistry1, iregistry2, i))), Lifecycle.stable()); + return registrymaterials; +@@ -256,6 +256,7 @@ public class DimensionManager { + return this.E[i]; + } + ++ public Tag getInfiniburnTag() { return o(); } // Paper - OBFHELPER + public Tag o() { + Tag tag = TagsBlock.a().a(this.infiniburn); + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 42417aee4796d39d110e69cb707bd3b7bac30027..3b3eda95c0ff8b129adedbae6561bba2d01c2f3a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2533,6 +2533,75 @@ public class CraftWorld implements World { + return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); + } + ++ // Paper start ++ @Override ++ public Location locateNearestBiome(Location origin, Biome biome, int radius) { ++ return this.locateNearestBiome(origin, biome, radius, 8); ++ } ++ ++ @Override ++ public Location locateNearestBiome(Location origin, Biome biome, int radius, int step) { ++ BlockPosition originPos = new BlockPosition(origin.getX(), origin.getY(), origin.getZ()); ++ BlockPosition nearest = getHandle().getNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().getWorldCustomRegistry().b(IRegistry.ay), biome), originPos, radius, step); ++ return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); ++ } ++ ++ @Override ++ public boolean isUltrawarm() { ++ return getHandle().getDimensionManager().isNether(); ++ } ++ ++ @Override ++ public boolean isNatural() { ++ return getHandle().getDimensionManager().isNatural(); ++ } ++ ++ @Override ++ public double getCoordinateScale() { ++ return getHandle().getDimensionManager().getCoordinateScale(); ++ } ++ ++ @Override ++ public boolean hasSkylight() { ++ return getHandle().getDimensionManager().hasSkyLight(); ++ } ++ ++ @Override ++ public boolean hasBedrockCeiling() { ++ return getHandle().getDimensionManager().hasSkyLight(); ++ } ++ ++ @Override ++ public boolean isPiglinSafe() { ++ return getHandle().getDimensionManager().isPiglinSafe(); ++ } ++ ++ @Override ++ public boolean doesBedWork() { ++ return getHandle().getDimensionManager().isBedWorks(); ++ } ++ ++ @Override ++ public boolean doesRespawnAnchorWork() { ++ return getHandle().getDimensionManager().isRespawnAnchorWorks(); ++ } ++ ++ @Override ++ public boolean hasRaids() { ++ return getHandle().getDimensionManager().hasRaids(); ++ } ++ ++ @Override ++ public boolean isFixedTime() { ++ return getHandle().getDimensionManager().isFixedTime(); ++ } ++ ++ @Override ++ public Collection getInfiniburn() { ++ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().getDimensionManager().getInfiniburnTag().getTagged().iterator(), CraftMagicNumbers::getMaterial)); ++ } ++ // Paper end ++ + @Override + public Raid locateNearestRaid(Location location, int radius) { + Validate.notNull(location, "Location cannot be null"); diff --git a/patches/server-unmapped/0715-Added-PlayerBedFailEnterEvent.patch b/patches/server-unmapped/0715-Added-PlayerBedFailEnterEvent.patch new file mode 100644 index 0000000000..16189aeee4 --- /dev/null +++ b/patches/server-unmapped/0715-Added-PlayerBedFailEnterEvent.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 24 Dec 2020 12:27:41 -0800 +Subject: [PATCH] Added PlayerBedFailEnterEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 3a13e7a050db7f5c93d810afe56325495cec7aa4..c39c50e53549e9cb9d3520bc7e8b7e89cfa20163 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -2233,6 +2233,7 @@ public abstract class EntityHuman extends EntityLiving { + this.g = ichatbasecomponent; + } + ++ public @Nullable IChatBaseComponent getChatComponent() { return this.a(); }; // Paper - OBFHELPER + @Nullable + public IChatBaseComponent a() { + return this.g; +diff --git a/src/main/java/net/minecraft/world/level/block/BlockBed.java b/src/main/java/net/minecraft/world/level/block/BlockBed.java +index eca84595342756e3550883551e487aaf79574fde..00a01a157deec004bcf2f8587723a0ecd0bfef85 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockBed.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockBed.java +@@ -43,6 +43,8 @@ import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + import net.minecraft.world.phys.shapes.VoxelShapes; + import org.apache.commons.lang3.ArrayUtils; ++import io.papermc.paper.event.player.PlayerBedFailEnterEvent; // Paper ++import io.papermc.paper.adventure.PaperAdventure; // Paper + + public class BlockBed extends BlockFacingHorizontal implements ITileEntity { + +@@ -101,14 +103,23 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity { + BlockPosition finalblockposition = blockposition; + // CraftBukkit end + entityhuman.sleep(blockposition).ifLeft((entityhuman_enumbedresult) -> { ++ // Paper start - PlayerBedFailEnterEvent ++ if (entityhuman_enumbedresult != null) { ++ PlayerBedFailEnterEvent event = new PlayerBedFailEnterEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), PlayerBedFailEnterEvent.FailReason.VALUES[entityhuman_enumbedresult.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(world, finalblockposition), entityhuman_enumbedresult == EntityHuman.EnumBedResult.NOT_POSSIBLE_HERE, PaperAdventure.asAdventure(entityhuman_enumbedresult.getChatComponent())); ++ if (!event.callEvent()) { ++ return; ++ } ++ // Paper end + // CraftBukkit start - handling bed explosion from below here +- if (entityhuman_enumbedresult == EntityHuman.EnumBedResult.NOT_POSSIBLE_HERE) { ++ if (event.getWillExplode()) { // Paper + this.explodeBed(finaliblockdata, world, finalblockposition); + } else + // CraftBukkit end + if (entityhuman_enumbedresult != null) { +- entityhuman.a(entityhuman_enumbedresult.a(), true); ++ final net.kyori.adventure.text.Component message = event.getMessage(); // Paper ++ if(message != null) entityhuman.a(PaperAdventure.asVanilla(message), true); // Paper + } ++ } // Paper + + }); + return EnumInteractionResult.SUCCESS; diff --git a/patches/server-unmapped/0716-Implement-methods-to-convert-between-Component-and-B.patch b/patches/server-unmapped/0716-Implement-methods-to-convert-between-Component-and-B.patch new file mode 100644 index 0000000000..4726476710 --- /dev/null +++ b/patches/server-unmapped/0716-Implement-methods-to-convert-between-Component-and-B.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Sat, 24 Apr 2021 02:09:32 -0700 +Subject: [PATCH] Implement methods to convert between Component and + Brigadier's Message + + +diff --git a/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fb1d6632788ae886b7a0e56fb490920c6ba2ce22 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java +@@ -0,0 +1,30 @@ ++package io.papermc.paper.brigadier; ++ ++import com.mojang.brigadier.Message; ++import io.papermc.paper.adventure.PaperAdventure; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.ComponentLike; ++import net.minecraft.network.chat.ChatComponentUtils; ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++import static java.util.Objects.requireNonNull; ++ ++public enum PaperBrigadierProviderImpl implements PaperBrigadierProvider { ++ INSTANCE; ++ ++ PaperBrigadierProviderImpl() { ++ PaperBrigadierProvider.initialize(this); ++ } ++ ++ @Override ++ public @NonNull Message message(final @NonNull ComponentLike componentLike) { ++ requireNonNull(componentLike, "componentLike"); ++ return PaperAdventure.asVanilla(componentLike.asComponent()); ++ } ++ ++ @Override ++ public @NonNull Component componentFromMessage(final @NonNull Message message) { ++ requireNonNull(message, "message"); ++ return PaperAdventure.asAdventure(ChatComponentUtils.fromMessage(message)); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index cac3df2ca054b3b2fb5b6437ab2950afc3ace8fb..04ca3ed64d8fb9bce38d715d3618ab5c73d8cbfa 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -213,6 +213,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + } + com.destroystokyo.paper.PaperConfig.registerCommands(); + com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now ++ io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider + // Paper end + + this.setPVP(dedicatedserverproperties.pvp); diff --git a/patches/server-unmapped/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/patches/server-unmapped/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch new file mode 100644 index 0000000000..3d7c4fd05d --- /dev/null +++ b/patches/server-unmapped/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Fri, 23 Apr 2021 22:42:42 +0100 +Subject: [PATCH] Fix anchor respawn acting as a bed respawn from the end + portal + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index b257d58a298e82f255b09e9575ee42a56a4b7cee..a83d8cfac8c5ed84dd5224cc3f18f55dba4741af 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -871,6 +871,7 @@ public abstract class PlayerList { + + // Paper start + boolean isBedSpawn = false; ++ boolean isAnchorSpawn = false; + boolean isRespawn = false; + boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 + // Paper end +@@ -891,6 +892,7 @@ public abstract class PlayerList { + if (optional.isPresent()) { + IBlockData iblockdata = worldserver1.getType(blockposition); + boolean flag3 = iblockdata.a(Blocks.RESPAWN_ANCHOR); ++ isAnchorSpawn = flag3; // Paper - Fix anchor respawn acting as a bed respawn from the end portal + Vec3D vec3d = (Vec3D) optional.get(); + float f1; + +@@ -918,7 +920,7 @@ public abstract class PlayerList { + } + + Player respawnPlayer = cserver.getPlayer(entityplayer1); +- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag2, flag2); ++ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal + cserver.getPluginManager().callEvent(respawnEvent); + // Spigot Start + if (entityplayer.playerConnection.isDisconnected()) { diff --git a/patches/server-unmapped/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/server-unmapped/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch new file mode 100644 index 0000000000..fc6f31d8c9 --- /dev/null +++ b/patches/server-unmapped/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 22 Apr 2021 17:17:47 -0700 +Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 957d3b56aea116f947ca8fb74127f652de72b701..d1073b69e3fcee219123e4fe0c7ab5374dd71d32 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2442,7 +2442,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + case PERFORM_RESPAWN: + if (this.player.viewingCredits) { + this.player.viewingCredits = false; +- this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, true); ++ this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, this.minecraftServer.getWorldServer(this.player.getSpawnDimension()), true, null, true, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); // Paper - add isEndCreditsRespawn argument + CriterionTriggers.v.a(this.player, World.THE_END, World.OVERWORLD); + } else { + if (this.player.getHealth() > 0.0F) { +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index a83d8cfac8c5ed84dd5224cc3f18f55dba4741af..2a76c3624c64e93509a96579f48c507e29901625 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -820,7 +820,13 @@ public abstract class PlayerList { + return this.moveToWorld(entityplayer, this.server.getWorldServer(entityplayer.getSpawnDimension()), flag, null, true); + } + ++ // Paper start + public EntityPlayer moveToWorld(EntityPlayer entityplayer, WorldServer worldserver, boolean flag, Location location, boolean avoidSuffocation) { ++ return moveToWorld(entityplayer, worldserver, flag, location, avoidSuffocation, new org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag[0]); ++ } ++ ++ public EntityPlayer moveToWorld(EntityPlayer entityplayer, WorldServer worldserver, boolean flag, Location location, boolean avoidSuffocation, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag...respawnFlags) { ++ // Paper end + entityplayer.stopRiding(); // CraftBukkit + this.players.remove(entityplayer); + this.playersByName.remove(entityplayer.getName().toLowerCase(java.util.Locale.ROOT)); // Spigot +@@ -920,7 +926,7 @@ public abstract class PlayerList { + } + + Player respawnPlayer = cserver.getPlayer(entityplayer1); +- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal ++ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn, com.google.common.collect.ImmutableSet.builder().add(respawnFlags)); // Paper - Fix anchor respawn acting as a bed respawn from the end portal + cserver.getPluginManager().callEvent(respawnEvent); + // Spigot Start + if (entityplayer.playerConnection.isDisconnected()) { diff --git a/patches/server-unmapped/0719-Introduce-beacon-activation-deactivation-events.patch b/patches/server-unmapped/0719-Introduce-beacon-activation-deactivation-events.patch new file mode 100644 index 0000000000..f8c74eacff --- /dev/null +++ b/patches/server-unmapped/0719-Introduce-beacon-activation-deactivation-events.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spyridon Pagkalos +Date: Thu, 25 Mar 2021 20:28:04 +0200 +Subject: [PATCH] Introduce beacon activation/deactivation events + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java +index cd28a731a56eb7534faae5b120195b62d5d15bd4..f7b210e6d60533d9faf60183a80a562b25f945d0 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java +@@ -201,6 +201,15 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic + this.a(SoundEffects.BLOCK_BEACON_AMBIENT); + } + } ++ // Paper start - beacon activation/deactivation events ++ if (!(i1 > 0) && this.levels > 0) { ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); ++ new io.papermc.paper.event.block.BeaconActivatedEvent(block).callEvent(); ++ } else if (i1 > 0 && !(this.levels > 0)) { ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); ++ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); ++ } ++ // Paper end + + if (this.i >= l) { + this.i = -1; +@@ -257,6 +266,10 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic + + @Override + public void al_() { ++ // Paper start - BeaconDeactivatedEvent ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); ++ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); ++ // Paper end + this.a(SoundEffects.BLOCK_BEACON_DEACTIVATE); + super.al_(); + } diff --git a/patches/server-unmapped/0720-Add-Channel-initialization-listeners.patch b/patches/server-unmapped/0720-Add-Channel-initialization-listeners.patch new file mode 100644 index 0000000000..0f5e146c08 --- /dev/null +++ b/patches/server-unmapped/0720-Add-Channel-initialization-listeners.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KennyTV +Date: Thu, 29 Apr 2021 21:19:33 +0200 +Subject: [PATCH] Add Channel initialization listeners + + +diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java +new file mode 100644 +index 0000000000000000000000000000000000000000..88099df34c2d74daba9645aadf65b446ca795a91 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java +@@ -0,0 +1,15 @@ ++package io.papermc.paper.network; ++ ++import io.netty.channel.Channel; ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++/** ++ * Internal API to register channel initialization listeners. ++ *

    ++ * This is not officially supported API and we make no guarantees to the existence or state of this interface. ++ */ ++@FunctionalInterface ++public interface ChannelInitializeListener { ++ ++ void afterInitChannel(@NonNull Channel channel); ++} +diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..30e62719e0a83525daa33cf41cb61df360c0e046 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java +@@ -0,0 +1,74 @@ ++package io.papermc.paper.network; ++ ++import io.netty.channel.Channel; ++import net.kyori.adventure.key.Key; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++ ++import java.util.Collections; ++import java.util.HashMap; ++import java.util.Map; ++ ++/** ++ * Internal API to register channel initialization listeners. ++ *

    ++ * This is not officially supported API and we make no guarantees to the existence or state of this class. ++ */ ++public final class ChannelInitializeListenerHolder { ++ ++ private static final Map LISTENERS = new HashMap<>(); ++ private static final Map IMMUTABLE_VIEW = Collections.unmodifiableMap(LISTENERS); ++ ++ private ChannelInitializeListenerHolder() { ++ } ++ ++ /** ++ * Registers whether an initialization listener is registered under the given key. ++ * ++ * @param key key ++ * @return whether an initialization listener is registered under the given key ++ */ ++ public static boolean hasListener(@NonNull Key key) { ++ return LISTENERS.containsKey(key); ++ } ++ ++ /** ++ * Registers a channel initialization listener called after ServerConnection is initialized. ++ * ++ * @param key key ++ * @param listener initialization listeners ++ */ ++ public static void addListener(@NonNull Key key, @NonNull ChannelInitializeListener listener) { ++ LISTENERS.put(key, listener); ++ } ++ ++ /** ++ * Removes and returns an initialization listener registered by the given key if present. ++ * ++ * @param key key ++ * @return removed initialization listener if present ++ */ ++ public static @Nullable ChannelInitializeListener removeListener(@NonNull Key key) { ++ return LISTENERS.remove(key); ++ } ++ ++ /** ++ * Returns an immutable map of registered initialization listeners. ++ * ++ * @return immutable map of registered initialization listeners ++ */ ++ public static @NonNull Map getListeners() { ++ return IMMUTABLE_VIEW; ++ } ++ ++ /** ++ * Calls the registered listeners with the given channel. ++ * ++ * @param channel channel ++ */ ++ public static void callListeners(@NonNull Channel channel) { ++ for (ChannelInitializeListener listener : LISTENERS.values()) { ++ listener.afterInitChannel(channel); ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java +index dc362724ea0cc1b2f9d9ceffff483217b4356c40..69fc2789df88344587b6052f93661ed38f24a503 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnection.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnection.java +@@ -104,6 +104,7 @@ public class ServerConnection { + pending.add((NetworkManager) object); // Paper + channel.pipeline().addLast("packet_handler", (ChannelHandler) object); + ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object)); ++ io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper + } + }).group((EventLoopGroup) lazyinitvar.a()).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit + } diff --git a/patches/server-unmapped/0721-Send-empty-commands-if-tab-completion-is-disabled.patch b/patches/server-unmapped/0721-Send-empty-commands-if-tab-completion-is-disabled.patch new file mode 100644 index 0000000000..2fefc38db3 --- /dev/null +++ b/patches/server-unmapped/0721-Send-empty-commands-if-tab-completion-is-disabled.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Mon, 26 Apr 2021 01:27:08 +0100 +Subject: [PATCH] Send empty commands if tab completion is disabled + + +diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java +index 47dc8450fff5583d70c969c0b92b96a665a02305..7e30ec9a08d919d2ae9218ee0a11f77719129f07 100644 +--- a/src/main/java/net/minecraft/commands/CommandDispatcher.java ++++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java +@@ -327,7 +327,12 @@ public class CommandDispatcher { + } + + public void a(EntityPlayer entityplayer) { +- if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot ++ // Paper start - Send empty commands if tab completion is disabled ++ if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) { //return; // Spigot ++ entityplayer.playerConnection.sendPacket(new PacketPlayOutCommands(new RootCommandNode<>())); ++ return; ++ } ++ // Paper end + // CraftBukkit start + // Register Vanilla commands into builtRoot as before + // Paper start - Async command map building diff --git a/patches/server-unmapped/0722-Add-more-WanderingTrader-API.patch b/patches/server-unmapped/0722-Add-more-WanderingTrader-API.patch new file mode 100644 index 0000000000..4679f25de7 --- /dev/null +++ b/patches/server-unmapped/0722-Add-more-WanderingTrader-API.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Thu, 6 May 2021 14:56:43 +0100 +Subject: [PATCH] Add more WanderingTrader API + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +index 37e1b2bf33510c3603efadf219b462e667f573c2..69044827ed6b34924ffd89a977afa06df0dcefc3 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java +@@ -58,6 +58,10 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { + @Nullable + private BlockPosition bp; + private int despawnDelay; ++ // Paper start - Add more WanderingTrader API ++ public boolean canDrinkPotion = true; ++ public boolean canDrinkMilk = true; ++ // Paper end + + public EntityVillagerTrader(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -69,10 +73,10 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { + protected void initPathfinder() { + this.goalSelector.a(0, new PathfinderGoalFloat(this)); + this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, PotionUtil.a(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEffects.ENTITY_WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { +- return this.world.isNight() && !entityvillagertrader.isInvisible(); ++ return canDrinkPotion && this.world.isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API + })); + this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, new ItemStack(Items.MILK_BUCKET), SoundEffects.ENTITY_WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { +- return this.world.isDay() && entityvillagertrader.isInvisible(); ++ return canDrinkMilk && this.world.isDay() && entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API + })); + this.goalSelector.a(1, new PathfinderGoalTradeWithPlayer(this)); + this.goalSelector.a(1, new PathfinderGoalAvoidTarget<>(this, EntityZombie.class, 8.0F, 0.5D, 0.5D)); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java +index c8344ce0a85030b12139d0b2bbe45acdcd33e1e7..6dad8ca649a2fa0a80a4b88c8a3e284fe218f31f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java +@@ -35,4 +35,26 @@ public class CraftWanderingTrader extends CraftAbstractVillager implements Wande + public void setDespawnDelay(int despawnDelay) { + getHandle().setDespawnDelay(despawnDelay); + } ++ ++ // Paper start - Add more WanderingTrader API ++ @Override ++ public void setCanDrinkPotion(boolean bool) { ++ getHandle().canDrinkPotion = bool; ++ } ++ ++ @Override ++ public boolean canDrinkPotion() { ++ return getHandle().canDrinkPotion; ++ } ++ ++ @Override ++ public void setCanDrinkMilk(boolean bool) { ++ getHandle().canDrinkMilk = bool; ++ } ++ ++ @Override ++ public boolean canDrinkMilk() { ++ return getHandle().canDrinkMilk; ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0723-Add-EntityBlockStorage-clearEntities.patch b/patches/server-unmapped/0723-Add-EntityBlockStorage-clearEntities.patch new file mode 100644 index 0000000000..3fc2d1a337 --- /dev/null +++ b/patches/server-unmapped/0723-Add-EntityBlockStorage-clearEntities.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Mon, 5 Apr 2021 18:12:29 -0400 +Subject: [PATCH] Add EntityBlockStorage#clearEntities() + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java +index 3cbcbb028b864f1d14e004628bbc0829f71ab476..80083a6666a28372946cf0e68ded44d075357f7d 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java +@@ -120,6 +120,11 @@ public class TileEntityBeehive extends TileEntity implements ITickable { + return this.bees.size(); + } + ++ // Paper start - Add EntityBlockStorage clearEntities ++ public void clearBees() { ++ this.bees.clear(); ++ } ++ // Paper end + public static int a(IBlockData iblockdata) { + return (Integer) iblockdata.get(BlockBeehive.b); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java +index af691b28b38e388617d241008c2e9d403bc5c15d..9f4fb1ff9c945799d10d6905c8b73376e4133d23 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java +@@ -83,4 +83,10 @@ public class CraftBeehive extends CraftBlockEntityState imple + + getSnapshot().addBee(((CraftBee) entity).getHandle(), false); + } ++ // Paper start - Add EntityBlockStorage clearEntities ++ @Override ++ public void clearEntities() { ++ getSnapshot().clearBees(); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/server-unmapped/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch new file mode 100644 index 0000000000..07309399fa --- /dev/null +++ b/patches/server-unmapped/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alvinn8 <42838560+Alvinn8@users.noreply.github.com> +Date: Fri, 8 Jan 2021 20:31:13 +0100 +Subject: [PATCH] Add Adventure message to PlayerAdvancementDoneEvent + + +diff --git a/src/main/java/net/minecraft/advancements/Advancement.java b/src/main/java/net/minecraft/advancements/Advancement.java +index e3d5d55a2fe5d86db621d3e0c9322f553386d731..2f3d9e5b849093027d3c2ef434494cd600f52a31 100644 +--- a/src/main/java/net/minecraft/advancements/Advancement.java ++++ b/src/main/java/net/minecraft/advancements/Advancement.java +@@ -76,6 +76,7 @@ public class Advancement { + return this.parent; + } + ++ public final @Nullable AdvancementDisplay getAdvancementDisplay() { return this.c(); } // Paper - OBFHELPER + @Nullable + public AdvancementDisplay c() { + return this.display; +@@ -125,6 +126,7 @@ public class Advancement { + return this.requirements; + } + ++ public final IChatBaseComponent getChatComponent() { return this.j(); } // Paper - OBFHELPER + public IChatBaseComponent j() { + return this.chatComponent; + } +diff --git a/src/main/java/net/minecraft/advancements/AdvancementDisplay.java b/src/main/java/net/minecraft/advancements/AdvancementDisplay.java +index 721d7fbab447117349994f710338ca616ab11067..adc6779e53e7b2ee04a80e2ea714e3378b8e6f39 100644 +--- a/src/main/java/net/minecraft/advancements/AdvancementDisplay.java ++++ b/src/main/java/net/minecraft/advancements/AdvancementDisplay.java +@@ -54,10 +54,12 @@ public class AdvancementDisplay { + return this.b; + } + ++ public final AdvancementFrameType getFrameType() { return this.e(); } // Paper - OBFHELPER + public AdvancementFrameType e() { + return this.e; + } + ++ public final boolean shouldAnnounceToChat() { return this.i(); } // Paper - OBFHELPER + public boolean i() { + return this.g; + } +diff --git a/src/main/java/net/minecraft/advancements/AdvancementFrameType.java b/src/main/java/net/minecraft/advancements/AdvancementFrameType.java +index f5d24950d317c78a971472821595fc1b44befc6e..32380346555e194227423999a79f1ebcbbe38d3b 100644 +--- a/src/main/java/net/minecraft/advancements/AdvancementFrameType.java ++++ b/src/main/java/net/minecraft/advancements/AdvancementFrameType.java +@@ -20,6 +20,7 @@ public enum AdvancementFrameType { + this.g = new ChatMessage("advancements.toast." + s); + } + ++ public final String getId() { return this.a(); } // Paper - OBFHELPER + public String a() { + return this.d; + } +diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java +index 7a8a1960882e291c46301d07da3e1c5415516893..dfdbc028f68ced197ad179248ed3b1e9d70ba057 100644 +--- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java ++++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java +@@ -51,6 +51,7 @@ import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.level.GameRules; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import io.papermc.paper.adventure.PaperAdventure; // Paper + + public class AdvancementDataPlayer { + +@@ -313,10 +314,18 @@ public class AdvancementDataPlayer { + this.j.add(advancement); + flag = true; + if (!flag1 && advancementprogress.isDone()) { +- this.player.world.getServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit)); // CraftBukkit ++ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent ++ boolean announceToChat = advancement.getAdvancementDisplay() != null && advancement.getAdvancementDisplay().shouldAnnounceToChat(); ++ net.kyori.adventure.text.Component message = announceToChat ? PaperAdventure.asAdventure(new ChatMessage("chat.type.advancement." + advancement.getAdvancementDisplay().getFrameType().getId(), this.player.getScoreboardDisplayName(), advancement.getChatComponent())) : null; ++ org.bukkit.event.player.PlayerAdvancementDoneEvent event = new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit, message); ++ this.player.world.getServer().getPluginManager().callEvent(event); ++ message = event.message(); ++ // Paper end + advancement.d().a(this.player); +- if (advancement.c() != null && advancement.c().i() && this.player.world.getGameRules().getBoolean(GameRules.ANNOUNCE_ADVANCEMENTS)) { +- this.e.sendMessage(new ChatMessage("chat.type.advancement." + advancement.c().e().a(), new Object[]{this.player.getScoreboardDisplayName(), advancement.j()}), ChatMessageType.SYSTEM, SystemUtils.b); ++ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent ++ if (message != null && this.player.world.getGameRules().getBoolean(GameRules.ANNOUNCE_ADVANCEMENTS)) { ++ this.e.sendMessage(PaperAdventure.asVanilla(message), ChatMessageType.SYSTEM, SystemUtils.getNullUUID()); ++ // Paper end + } + } + } diff --git a/patches/server-unmapped/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/server-unmapped/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch new file mode 100644 index 0000000000..5e64169b09 --- /dev/null +++ b/patches/server-unmapped/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Connor Linfoot +Date: Wed, 12 May 2021 08:09:19 +0100 +Subject: [PATCH] Add raw address to AsyncPlayerPreLoginEvent + + +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index 190fc9f764420ea5fd20d629101644aeda2d8239..5b69126142140c7fc96435a4d246752581f47c33 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -327,12 +327,13 @@ public class LoginListener implements PacketLoginInListener { + // Paper end + String playerName = i.getName(); + java.net.InetAddress address = ((java.net.InetSocketAddress) networkManager.getSocketAddress()).getAddress(); ++ java.net.InetAddress rawAddress = ((java.net.InetSocketAddress) networkManager.getRawAddress()).getAddress(); // Paper + java.util.UUID uniqueId = i.getId(); + final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; + + // Paper start + PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); +- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); ++ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile); + server.getPluginManager().callEvent(asyncEvent); + profile = asyncEvent.getPlayerProfile(); + profile.complete(true); diff --git a/patches/server-unmapped/0726-Inventory-close.patch b/patches/server-unmapped/0726-Inventory-close.patch new file mode 100644 index 0000000000..79f0c20686 --- /dev/null +++ b/patches/server-unmapped/0726-Inventory-close.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 11 May 2021 14:54:56 -0700 +Subject: [PATCH] Inventory#close + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +index c3fa97ac34e1fc61ae02f224f8afe5a0b486fb4d..f6001047ada8308cfa1d9b26677a7a5d7774de51 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +@@ -449,6 +449,14 @@ public class CraftInventory implements Inventory { + clear(i); + } + } ++ // Paper start ++ @Override ++ public int close() { ++ int count = this.inventory.getViewers().size(); ++ com.google.common.collect.Lists.newArrayList(this.inventory.getViewers()).forEach(HumanEntity::closeInventory); ++ return count; ++ } ++ // Paper end + + @Override + public ListIterator iterator() { diff --git a/patches/server-unmapped/0727-call-PortalCreateEvent-players-and-end-platform.patch b/patches/server-unmapped/0727-call-PortalCreateEvent-players-and-end-platform.patch new file mode 100644 index 0000000000..21890b59ca --- /dev/null +++ b/patches/server-unmapped/0727-call-PortalCreateEvent-players-and-end-platform.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 12 May 2021 03:21:22 -0700 +Subject: [PATCH] call PortalCreateEvent players and end platform + + +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index eb67af795dd716d9f92ac32843accc1ec4efd647..4abc87b7e737bc652e84f76a508ab85501d1556f 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -496,6 +496,7 @@ public class BlockPosition extends BaseBlockPosition { + return this.d(this.getX() + enumdirection.getAdjacentX() * i, this.getY() + enumdirection.getAdjacentY() * i, this.getZ() + enumdirection.getAdjacentZ() * i); + } + ++ public BlockPosition.MutableBlockPosition withOffset(int x, int y, int z) { return e(x, y, z); } // Paper - OBFHELPER + public BlockPosition.MutableBlockPosition e(int i, int j, int k) { + return this.d(this.getX() + i, this.getY() + j, this.getZ() + k); + } +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 3f44d5b8e3bc4f897a5dda473532004078fe0ebe..8683d6ddc5d8ce4a302fa6e2665b7dcd64f6a00a 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1145,15 +1145,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + private void a(WorldServer worldserver, BlockPosition blockposition) { + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = blockposition.i(); + ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(worldserver); // Paper + for (int i = -2; i <= 2; ++i) { + for (int j = -2; j <= 2; ++j) { + for (int k = -1; k < 3; ++k) { + IBlockData iblockdata = k == -1 ? Blocks.OBSIDIAN.getBlockData() : Blocks.AIR.getBlockData(); + +- worldserver.setTypeUpdate(blockposition_mutableblockposition.g(blockposition).e(j, k, i), iblockdata); ++ blockList.setTypeAndData(blockposition_mutableblockposition.setValues(blockposition).withOffset(j, k, i), iblockdata, 3); // Paper + } + } + } ++ // Paper start ++ if (new org.bukkit.event.world.PortalCreateEvent((List< org.bukkit.block.BlockState>) (List) blockList.getList(), worldserver.getWorld(), this.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM).callEvent()) { ++ blockList.updateList(); ++ } ++ // Paper end + + } + diff --git a/patches/server-unmapped/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/server-unmapped/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch new file mode 100644 index 0000000000..70f7b8aa41 --- /dev/null +++ b/patches/server-unmapped/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch @@ -0,0 +1,126 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MeFisto94 +Date: Tue, 11 May 2021 00:48:33 +0200 +Subject: [PATCH] Add a "should burn in sunlight" API for Phantoms and + Skeletons + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +index 42cf3fa42b73739182d26fbb524ee5b304c799b2..16c0c960aa1e4d35093b810c7648b5638175e106 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java +@@ -134,7 +134,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { + + @Override + public void movementTick() { +- if (this.isAlive() && this.eG()) { ++ if (this.isAlive() && shouldBurnInDay && this.eG()) { // Paper - Configurable Burning + this.setOnFire(8); + } + +@@ -165,6 +165,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { + if (nbttagcompound.hasUUID("Paper.SpawningEntity")) { + this.spawningEntity = nbttagcompound.getUUID("Paper.SpawningEntity"); + } ++ this.shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); + // Paper end + } + +@@ -179,6 +180,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { + if (this.spawningEntity != null) { + nbttagcompound.setUUID("Paper.SpawningEntity", this.spawningEntity); + } ++ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); + // Paper end + } + +@@ -233,6 +235,10 @@ public class EntityPhantom extends EntityFlying implements IMonster { + return spawningEntity; + } + public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } ++ ++ private boolean shouldBurnInDay = true; ++ public boolean shouldBurnInDay() { return shouldBurnInDay; } ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } + // Paper end + + class b extends PathfinderGoal { +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java +index 06d50b22ede102556fdb3e2a6f1424f7ff13f120..f8358e40c42f219232bf928f4e0073339a5e19d5 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java +@@ -98,9 +98,15 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR + return EnumMonsterType.UNDEAD; + } + ++ // Paper start ++ private boolean shouldBurnInDay = true; ++ public boolean shouldBurnInDay() { return shouldBurnInDay; } ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } ++ // Paper end ++ + @Override + public void movementTick() { +- boolean flag = this.eG(); ++ boolean flag = shouldBurnInDay && this.eG(); // Paper - Configurable Burning + + if (flag) { + ItemStack itemstack = this.getEquipment(EnumItemSlot.HEAD); +@@ -224,7 +230,16 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR + public void loadData(NBTTagCompound nbttagcompound) { + super.loadData(nbttagcompound); + this.eL(); ++ this.shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); // Paper ++ } ++ ++ // Paper start ++ @Override ++ public void saveData(NBTTagCompound nbttagcompound) { ++ super.saveData(nbttagcompound); ++ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); + } ++ // Paper end + + @Override + public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +index 0cea1d8e23da3a79ef06e43752665a5401b01b4b..476339ef8cafad2d6c78bccb6fd9f3c882b89148 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +@@ -40,5 +40,15 @@ public class CraftPhantom extends CraftFlying implements Phantom { + public java.util.UUID getSpawningEntity() { + return getHandle().getSpawningEntity(); + } ++ ++ @Override ++ public boolean shouldBurnInDay() { ++ return getHandle().shouldBurnInDay(); ++ } ++ ++ @Override ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { ++ getHandle().setShouldBurnInDay(shouldBurnInDay); ++ } + // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +index c2acfa2cc27a187154e17b7f45908682b41b52af..f48c4225dbc3467aaf8d14bc4047430548cc7c78 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +@@ -36,4 +36,16 @@ public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroy + public void setSkeletonType(SkeletonType type) { + throw new UnsupportedOperationException("Not supported."); + } ++ ++ // Paper start ++ @Override ++ public boolean shouldBurnInDay() { ++ return getHandle().shouldBurnInDay(); ++ } ++ ++ @Override ++ public void setShouldBurnInDay(boolean shouldBurnInDay) { ++ getHandle().setShouldBurnInDay(shouldBurnInDay); ++ } ++ // Paper end + } diff --git a/patches/server-unmapped/0729-Fix-CraftPotionBrewer-cache.patch b/patches/server-unmapped/0729-Fix-CraftPotionBrewer-cache.patch new file mode 100644 index 0000000000..e2ecdf706b --- /dev/null +++ b/patches/server-unmapped/0729-Fix-CraftPotionBrewer-cache.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sceri +Date: Fri, 14 May 2021 19:06:51 +0500 +Subject: [PATCH] Fix CraftPotionBrewer cache + + +diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java +index 7156bd1c8938a0b111be11d93ed2645a58d75611..4d108ed58a768a5a5e2e33213921f0a89487b6a2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java ++++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java +@@ -15,12 +15,18 @@ import org.bukkit.potion.PotionEffectType; + import org.bukkit.potion.PotionType; + + public class CraftPotionBrewer implements PotionBrewer { +- private static final Map> cache = Maps.newHashMap(); ++ private static final Map> cache = Maps.newHashMap(); // Paper + + @Override + public Collection getEffects(PotionType damage, boolean upgraded, boolean extended) { +- if (cache.containsKey(damage)) +- return cache.get(damage); ++ // Paper start ++ int key = damage.ordinal() << 2; ++ key |= (upgraded ? 1 : 0) << 1; ++ key |= extended ? 1 : 0; ++ ++ if (cache.containsKey(key)) ++ return cache.get(key); ++ // Paper end + + List mcEffects = PotionRegistry.a(CraftPotionUtil.fromBukkit(new PotionData(damage, extended, upgraded))).a(); + +@@ -29,9 +35,9 @@ public class CraftPotionBrewer implements PotionBrewer { + builder.add(CraftPotionUtil.toBukkit(effect)); + } + +- cache.put(damage, builder.build()); ++ cache.put(key, builder.build()); // Paper + +- return cache.get(damage); ++ return cache.get(key); // Paper + } + + @Override diff --git a/patches/server-unmapped/0730-Add-basic-Datapack-API.patch b/patches/server-unmapped/0730-Add-basic-Datapack-API.patch new file mode 100644 index 0000000000..7d34bf75bc --- /dev/null +++ b/patches/server-unmapped/0730-Add-basic-Datapack-API.patch @@ -0,0 +1,175 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Connor Linfoot +Date: Sun, 16 May 2021 15:07:34 +0100 +Subject: [PATCH] Add basic Datapack API + + +diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6426f646afdd2a75df89d522068a36cf170d697d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java +@@ -0,0 +1,51 @@ ++package io.papermc.paper.datapack; ++ ++import io.papermc.paper.event.server.ServerResourcesReloadedEvent; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.packs.repository.ResourcePackLoader; ++ ++import java.util.List; ++import java.util.stream.Collectors; ++ ++public class PaperDatapack implements Datapack { ++ private final String name; ++ private final Compatibility compatibility; ++ private final boolean enabled; ++ ++ PaperDatapack(ResourcePackLoader loader, boolean enabled) { ++ this.name = loader.getName(); ++ this.compatibility = Compatibility.valueOf(loader.getVersion().name()); ++ this.enabled = enabled; ++ } ++ ++ @Override ++ public String getName() { ++ return name; ++ } ++ ++ @Override ++ public Compatibility getCompatibility() { ++ return compatibility; ++ } ++ ++ @Override ++ public boolean isEnabled() { ++ return enabled; ++ } ++ ++ @Override ++ public void setEnabled(boolean enabled) { ++ if (enabled == this.enabled) { ++ return; ++ } ++ ++ MinecraftServer server = MinecraftServer.getServer(); ++ List enabledKeys = server.getResourcePackRepository().getEnabledPacks().stream().map(ResourcePackLoader::getName).collect(Collectors.toList()); ++ if (enabled) { ++ enabledKeys.add(this.name); ++ } else { ++ enabledKeys.remove(this.name); ++ } ++ server.reloadServerResources(enabledKeys, ServerResourcesReloadedEvent.Cause.PLUGIN); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..378aaeebd7e011565fdc505da68c5b5285339add +--- /dev/null ++++ b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java +@@ -0,0 +1,26 @@ ++package io.papermc.paper.datapack; ++ ++import net.minecraft.server.packs.repository.ResourcePackLoader; ++import net.minecraft.server.packs.repository.ResourcePackRepository; ++ ++import java.util.Collection; ++import java.util.stream.Collectors; ++ ++public class PaperDatapackManager implements DatapackManager { ++ private final ResourcePackRepository repository; ++ ++ public PaperDatapackManager(ResourcePackRepository repository) { ++ this.repository = repository; ++ } ++ ++ @Override ++ public Collection getPacks() { ++ Collection enabledPacks = repository.getEnabledPacks(); ++ return repository.getPacks().stream().map(loader -> new PaperDatapack(loader, enabledPacks.contains(loader))).collect(Collectors.toList()); ++ } ++ ++ @Override ++ public Collection getEnabledPacks() { ++ return repository.getEnabledPacks().stream().map(loader -> new PaperDatapack(loader, true)).collect(Collectors.toList()); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java b/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java +index 5c038c02955d8517db0686f3b73c8573d3770466..01c4fda33a138b2d1f6b7c1335378445423a66a9 100644 +--- a/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java ++++ b/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java +@@ -102,6 +102,7 @@ public class ResourcePackLoader implements AutoCloseable { + }); + } + ++ public final EnumResourcePackVersion getVersion() { return this.c(); } // Paper - OBFHELPER + public EnumResourcePackVersion c() { + return this.g; + } +@@ -110,6 +111,7 @@ public class ResourcePackLoader implements AutoCloseable { + return (IResourcePack) this.d.get(); + } + ++ public final String getName() { return this.e(); } // Paper - OBFHELPER + public String e() { + return this.c; + } +diff --git a/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java b/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java +index e87523612d0423d71eab7b9af851c1c268cdf84f..568da9686c41a41e43ede3fe15e0ca53c9688f8b 100644 +--- a/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java ++++ b/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java +@@ -88,6 +88,7 @@ public class ResourcePackRepository implements AutoCloseable { + return this.b.keySet(); + } + ++ public final Collection getPacks() { return this.c(); } // Paper - OBFHELPER + public Collection c() { + return this.b.values(); + } +@@ -96,6 +97,7 @@ public class ResourcePackRepository implements AutoCloseable { + return (Collection) this.c.stream().map(ResourcePackLoader::e).collect(ImmutableSet.toImmutableSet()); + } + ++ public final Collection getEnabledPacks() { return this.e(); } // Paper - OBFHELPER + public Collection e() { + return this.c; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 706dad235de3b7ffe014f564e1c68f18e1edeefc..89244c152665c97cb539bea07fedd1774ed626f1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -18,6 +18,7 @@ import com.mojang.serialization.Lifecycle; + import io.netty.buffer.ByteBuf; + import io.netty.buffer.ByteBufOutputStream; + import io.netty.buffer.Unpooled; ++import io.papermc.paper.datapack.PaperDatapackManager; // Paper + import io.papermc.paper.util.TraceUtil; + import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; + import java.awt.image.BufferedImage; +@@ -265,6 +266,7 @@ public final class CraftServer implements Server { + public boolean ignoreVanillaPermissions = false; + private final List playerView; + public int reloadCount; ++ private final PaperDatapackManager datapackManager; // Paper + public static Exception excessiveVelEx; // Paper - Velocity warnings + + static { +@@ -347,6 +349,7 @@ public final class CraftServer implements Server { + TicketType.PLUGIN.loadPeriod = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + minimumAPI = configuration.getString("settings.minimum-api"); + loadIcon(); ++ datapackManager = new PaperDatapackManager(console.getResourcePackRepository()); // Paper + } + + public boolean getCommandBlockOverride(String command) { +@@ -2497,5 +2500,11 @@ public final class CraftServer implements Server { + public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { + return mobGoals; + } ++ ++ @Override ++ public PaperDatapackManager getDatapackManager() { ++ return datapackManager; ++ } ++ + // Paper end + } diff --git a/patches/server-unmapped/0731-Add-environment-variable-to-disable-server-gui.patch b/patches/server-unmapped/0731-Add-environment-variable-to-disable-server-gui.patch new file mode 100644 index 0000000000..272a91a04d --- /dev/null +++ b/patches/server-unmapped/0731-Add-environment-variable-to-disable-server-gui.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Riley Park +Date: Mon, 17 May 2021 00:34:55 -0700 +Subject: [PATCH] Add environment variable to disable server gui + + +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 6818f8496ab76ee6ffc747bd6848b43830ec8914..bf4051349917cc1d727fc5544237e0291cb6f1e6 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -233,6 +233,7 @@ public class Main { + */ + boolean flag1 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui"); + ++ if(!Boolean.parseBoolean(System.getenv().getOrDefault("PAPER_DISABLE_SERVER_GUI", String.valueOf(false)))) // Paper + if (flag1 && !GraphicsEnvironment.isHeadless()) { + dedicatedserver1.bd(); + } diff --git a/patches/server-unmapped/0732-additions-to-PlayerGameModeChangeEvent.patch b/patches/server-unmapped/0732-additions-to-PlayerGameModeChangeEvent.patch new file mode 100644 index 0000000000..fdf582f3e8 --- /dev/null +++ b/patches/server-unmapped/0732-additions-to-PlayerGameModeChangeEvent.patch @@ -0,0 +1,128 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 10:04:43 -0700 +Subject: [PATCH] additions to PlayerGameModeChangeEvent + + +diff --git a/src/main/java/net/minecraft/server/commands/CommandGamemode.java b/src/main/java/net/minecraft/server/commands/CommandGamemode.java +index 376d5eac9c17365266d8a4986bf4c19030454c9a..8da48d9cbadfbe83ae8410cf49d78df49f50fb08 100644 +--- a/src/main/java/net/minecraft/server/commands/CommandGamemode.java ++++ b/src/main/java/net/minecraft/server/commands/CommandGamemode.java +@@ -62,13 +62,13 @@ public class CommandGamemode { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); + + if (entityplayer.playerInteractManager.getGameMode() != enumgamemode) { +- entityplayer.a(enumgamemode); +- // CraftBukkit start - handle event cancelling the change +- if (entityplayer.playerInteractManager.getGameMode() != enumgamemode) { +- commandcontext.getSource().sendFailureMessage(new net.minecraft.network.chat.ChatComponentText("Failed to set the gamemode of '" + entityplayer.getName() + "'")); ++ // Paper start - handle event cancelling the change ++ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); ++ if (event != null && event.isCancelled()) { ++ commandcontext.getSource().sendMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); + continue; + } +- // CraftBukkit end ++ // Paper end + a((CommandListenerWrapper) commandcontext.getSource(), entityplayer, enumgamemode); + ++i; + } +diff --git a/src/main/java/net/minecraft/server/commands/CommandGamemodeDefault.java b/src/main/java/net/minecraft/server/commands/CommandGamemodeDefault.java +index 5790699b3898910dfde46f588996dd8af42757d1..2a731594c22bb266d3dfef4d64d55b9772565cca 100644 +--- a/src/main/java/net/minecraft/server/commands/CommandGamemodeDefault.java ++++ b/src/main/java/net/minecraft/server/commands/CommandGamemodeDefault.java +@@ -43,7 +43,13 @@ public class CommandGamemodeDefault { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); + + if (entityplayer.playerInteractManager.getGameMode() != enumgamemode) { +- entityplayer.a(enumgamemode); ++ // Paper start - handle event cancelling the change ++ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); ++ if (event != null && event.isCancelled()) { ++ commandlistenerwrapper.sendMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); ++ continue; ++ } ++ // Paper end + ++i; + } + } +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 8683d6ddc5d8ce4a302fa6e2665b7dcd64f6a00a..558af73ac16550ee6964c4dce681a404633b2552 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -396,7 +396,16 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + if (this.locY() > 300) this.setPositionRaw(locX(), 257, locZ()); // Paper - bring down to a saner Y level if out of world + if (nbttagcompound.hasKeyOfType("playerGameType", 99)) { + if (this.getMinecraftServer().getForceGamemode()) { ++ // Paper start - call PlayerGameModeChangeEvent on join for players that do not have the correct gamemode ++ if (this.getMinecraftServer().getGamemode() != EnumGamemode.getById(nbttagcompound.getInt("playerGameType"))) { ++ if (new org.bukkit.event.player.PlayerGameModeChangeEvent(this.getBukkitEntity(), GameMode.getByValue(this.getMinecraftServer().getGamemode().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) { + this.playerInteractManager.a(this.getMinecraftServer().getGamemode(), EnumGamemode.NOT_SET); ++ } else { ++ this.playerInteractManager.a(EnumGamemode.getById(nbttagcompound.getInt("playerGameType")), nbttagcompound.hasKeyOfType("previousPlayerGameType", 3) ? EnumGamemode.getById(nbttagcompound.getInt("previousPlayerGameType")) : EnumGamemode.NOT_SET); // copied from below; if cancelled, set gamemode normally ++ } ++ } else { ++ this.playerInteractManager.a(EnumGamemode.getById(nbttagcompound.getInt("playerGameType")), nbttagcompound.hasKeyOfType("previousPlayerGameType", 3) ? EnumGamemode.getById(nbttagcompound.getInt("previousPlayerGameType")) : EnumGamemode.NOT_SET); // copied from below; if no change needed, set gamemode normally ++ } // Paper end + } else { + this.playerInteractManager.a(EnumGamemode.getById(nbttagcompound.getInt("playerGameType")), nbttagcompound.hasKeyOfType("previousPlayerGameType", 3) ? EnumGamemode.getById(nbttagcompound.getInt("previousPlayerGameType")) : EnumGamemode.NOT_SET); + } +@@ -1792,15 +1801,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + @Override + public void a(EnumGamemode enumgamemode) { ++ // Paper start - Add cause and nullable message to event ++ setGamemode(enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null); ++ } ++ ++ public PlayerGameModeChangeEvent setGamemode(EnumGamemode enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component message) { ++ // Paper end + // CraftBukkit start + if (enumgamemode == this.playerInteractManager.getGameMode()) { +- return; ++ return null; // Paper + } + +- PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(enumgamemode.getId())); ++ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(enumgamemode.getId()), cause, message); // Paper + world.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { +- return; ++ return event; // Paper + } + // CraftBukkit end + +@@ -1815,6 +1830,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + this.updateAbilities(); + this.dU(); ++ return event; // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index d1073b69e3fcee219123e4fe0c7ab5374dd71d32..304310cad03bce78a25ab0fb3e5e5f62ebd5558b 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -2451,7 +2451,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + + this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, false); + if (this.minecraftServer.isHardcore()) { +- this.player.a(EnumGamemode.SPECTATOR); ++ this.player.setGamemode(EnumGamemode.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper + ((GameRules.GameRuleBoolean) this.player.getWorldServer().getGameRules().get(GameRules.SPECTATORS_GENERATE_CHUNKS)).a(false, this.minecraftServer); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 05248f560d643080a3eac581c01aa89fb3709e6c..34395248e3daea47178cb40aad53680fbce73600 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1193,7 +1193,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + throw new IllegalArgumentException("Mode cannot be null"); + } + +- getHandle().a(EnumGamemode.getById(mode.getValue())); ++ getHandle().setGamemode(EnumGamemode.getById(mode.getValue()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.PLUGIN, null); // Paper + } + + @Override diff --git a/patches/server-unmapped/0733-ItemStack-repair-check-API.patch b/patches/server-unmapped/0733-ItemStack-repair-check-API.patch new file mode 100644 index 0000000000..006fed82d1 --- /dev/null +++ b/patches/server-unmapped/0733-ItemStack-repair-check-API.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 22:11:11 -0700 +Subject: [PATCH] ItemStack repair check API + + +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index f7758ee4aa8bbb31a80ec2e331b3fd3c55069808..7c9ef73983c2c7f4b7386a472e5a79dce7fa7ea7 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -269,6 +269,7 @@ public class Item implements IMaterial { + return this.i; + } + ++ public boolean canRepair(ItemStack toBeRepaired, ItemStack repairMaterial) { return a(toBeRepaired, repairMaterial); } // Paper - OBFHELPER + public boolean a(ItemStack itemstack, ItemStack itemstack1) { + return false; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 697949abbe662a55fc31ad811863717e35b9d1b6..a386beea01056a7fb448596ba45342d832a4c63d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -487,6 +487,14 @@ public final class CraftMagicNumbers implements UnsafeValues { + return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; + } + ++ @Override ++ public boolean isValidRepairItemStack(org.bukkit.inventory.ItemStack itemToBeRepaired, org.bukkit.inventory.ItemStack repairMaterial) { ++ if (!itemToBeRepaired.getType().isItem() || !repairMaterial.getType().isItem()) { ++ return false; ++ } ++ return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); ++ } ++ + @Override + public int getProtocolVersion() { + return net.minecraft.SharedConstants.getGameVersion().getProtocolVersion(); +diff --git a/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8d9c9b3bd53d407391d4fcb7fc773153d1a7b402 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java +@@ -0,0 +1,48 @@ ++package io.papermc.paper.util; ++ ++import org.bukkit.Material; ++import org.bukkit.inventory.ItemStack; ++import org.bukkit.support.AbstractTestingBase; ++import org.junit.Test; ++ ++import static org.junit.Assert.assertFalse; ++import static org.junit.Assert.assertThrows; ++import static org.junit.Assert.assertTrue; ++ ++public class ItemStackRepairCheckTest extends AbstractTestingBase { ++ ++ @Test ++ public void testIsRepariableBy() { ++ ItemStack diamondPick = new ItemStack(Material.DIAMOND_PICKAXE); ++ ++ assertTrue("diamond pick isn't repairable by a diamond", diamondPick.isRepairableBy(new ItemStack(Material.DIAMOND))); ++ } ++ ++ @Test ++ public void testCanRepair() { ++ ItemStack diamond = new ItemStack(Material.DIAMOND); ++ ++ assertTrue("diamond can't repair a diamond axe", diamond.canRepair(new ItemStack(Material.DIAMOND_AXE))); ++ } ++ ++ @Test ++ public void testIsNotRepairableBy() { ++ ItemStack notDiamondPick = new ItemStack(Material.ACACIA_SAPLING); ++ ++ assertFalse("acacia sapling is repairable by a diamond", notDiamondPick.isRepairableBy(new ItemStack(Material.DIAMOND))); ++ } ++ ++ @Test ++ public void testCanNotRepair() { ++ ItemStack diamond = new ItemStack(Material.DIAMOND); ++ ++ assertFalse("diamond can repair oak button", diamond.canRepair(new ItemStack(Material.OAK_BUTTON))); ++ } ++ ++ @Test ++ public void testInvalidItem() { ++ ItemStack badItemStack = new ItemStack(Material.ACACIA_WALL_SIGN); ++ ++ assertFalse("acacia wall sign is repairable by diamond", badItemStack.isRepairableBy(new ItemStack(Material.DIAMOND))); ++ } ++} diff --git a/patches/server-unmapped/0734-More-Enchantment-API.patch b/patches/server-unmapped/0734-More-Enchantment-API.patch new file mode 100644 index 0000000000..6cca0743b1 --- /dev/null +++ b/patches/server-unmapped/0734-More-Enchantment-API.patch @@ -0,0 +1,202 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 6 May 2021 19:57:58 -0700 +Subject: [PATCH] More Enchantment API + + +diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +index b76ef55145336cc8dc4857b79767f5a738ad5144..c719c1c1f837753f61eb7be83b6ec2a214ab6819 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +@@ -17,7 +17,7 @@ import net.minecraft.world.item.ItemStack; + + public abstract class Enchantment { + +- private final EnumItemSlot[] a; ++ private final EnumItemSlot[] a; public final EnumItemSlot[] getSlots() { return this.a; } // Paper - OBFHELPER + private final Enchantment.Rarity d; + public final EnchantmentSlotType itemTarget; + @Nullable +@@ -46,6 +46,7 @@ public abstract class Enchantment { + return map; + } + ++ public Enchantment.Rarity getRarity() { return d(); } // Paper - OBFHELPER + public Enchantment.Rarity d() { + return this.d; + } +@@ -70,6 +71,7 @@ public abstract class Enchantment { + return 0; + } + ++ public float getDamageIncrease(int level, EnumMonsterType enumMonsterType) { return a(level, enumMonsterType); } // Paper - OBFHELPER + public float a(int i, EnumMonsterType enummonstertype) { + return 0.0F; + } +@@ -123,14 +125,17 @@ public abstract class Enchantment { + return false; + } + ++ public boolean isCursed() { return c(); } // Paper - OBFHELPER + public boolean c() { + return false; + } + ++ public boolean isTradeable() { return h(); } // Paper - OBFHELPER + public boolean h() { + return true; + } + ++ public boolean isDiscoverable() { return i(); } // Paper - OBFHELPER + public boolean i() { + return true; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +index 5a14430f63894bbe9daa42900cf5a6519bea4f45..3b83852249e56609074ef1e8cdad6416db66007b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java ++++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +@@ -71,7 +71,7 @@ public class CraftEnchantment extends Enchantment { + + @Override + public boolean isCursed() { +- return target instanceof EnchantmentBinding || target instanceof EnchantmentVanishing; ++ return target.isCursed(); // Paper + } + + @Override +@@ -192,6 +192,45 @@ public class CraftEnchantment extends Enchantment { + public net.kyori.adventure.text.Component displayName(int level) { + return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); + } ++ ++ @Override ++ public boolean isTradeable() { ++ return target.isTradeable(); ++ } ++ ++ @Override ++ public boolean isDiscoverable() { ++ return target.isDiscoverable(); ++ } ++ ++ @Override ++ public io.papermc.paper.enchantments.EnchantmentRarity getRarity() { ++ return fromNMSRarity(target.getRarity()); ++ } ++ ++ @Override ++ public float getDamageIncrease(int level, org.bukkit.entity.EntityCategory entityCategory) { ++ return target.getDamageIncrease(level, org.bukkit.craftbukkit.entity.CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); ++ } ++ ++ @Override ++ public java.util.Set getActiveSlots() { ++ return java.util.stream.Stream.of(target.getSlots()).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet()); ++ } ++ ++ public static io.papermc.paper.enchantments.EnchantmentRarity fromNMSRarity(net.minecraft.world.item.enchantment.Enchantment.Rarity nmsRarity) { ++ if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.COMMON) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.COMMON; ++ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.UNCOMMON) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.UNCOMMON; ++ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.RARE) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.RARE; ++ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.VERY_RARE) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.VERY_RARE; ++ } ++ ++ throw new IllegalArgumentException(String.format("Unable to convert %s to a enum value of %s.", nmsRarity, io.papermc.paper.enchantments.EnchantmentRarity.class)); ++ } + // Paper end + + public net.minecraft.world.item.enchantment.Enchantment getHandle() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 9865eee8ec5e43f291968bfb2c4473260e5baf7c..32428b1260bbc4bae67ec74969c67f71272de418 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -847,5 +847,21 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setHurtDirection(float hurtDirection) { + getHandle().setHurtDirection(hurtDirection); + } ++ ++ public static EnumMonsterType fromBukkitEntityCategory(EntityCategory entityCategory) { ++ switch (entityCategory) { ++ case NONE: ++ return EnumMonsterType.UNDEFINED; ++ case UNDEAD: ++ return EnumMonsterType.UNDEAD; ++ case ARTHROPOD: ++ return EnumMonsterType.ARTHROPOD; ++ case ILLAGER: ++ return EnumMonsterType.ILLAGER; ++ case WATER: ++ return EnumMonsterType.WATER_MOB; ++ } ++ throw new IllegalArgumentException(entityCategory + " is an unrecognized entity category"); ++ } + // Paper end + } +diff --git a/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..62b56b5b43696b03fc72cac59f986d006edc3f76 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java +@@ -0,0 +1,18 @@ ++package io.papermc.paper.enchantments; ++ ++import net.minecraft.world.item.enchantment.Enchantment.Rarity; ++import org.bukkit.craftbukkit.enchantments.CraftEnchantment; ++import org.junit.Test; ++ ++import static org.junit.Assert.assertNotNull; ++ ++public class EnchantmentRarityTest { ++ ++ @Test ++ public void test() { ++ for (Rarity nmsRarity : Rarity.values()) { ++ // Will throw exception if a bukkit counterpart is not found ++ CraftEnchantment.fromNMSRarity(nmsRarity); ++ } ++ } ++} +diff --git a/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..adb0e5b4268fa115b814143cf29d9a3688e4bc17 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java +@@ -0,0 +1,34 @@ ++package io.papermc.paper.entity; ++ ++import com.google.common.base.Joiner; ++import com.google.common.collect.Maps; ++import com.google.common.collect.Sets; ++import net.minecraft.world.entity.EnumMonsterType; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.EntityCategory; ++import org.junit.Test; ++ ++import java.lang.reflect.Field; ++import java.util.Map; ++import java.util.Set; ++ ++import static org.junit.Assert.assertTrue; ++ ++public class EntityCategoryTest { ++ ++ @Test ++ public void test() throws IllegalAccessException { ++ ++ Map enumMonsterTypeFieldMap = Maps.newHashMap(); ++ for (Field field : EnumMonsterType.class.getDeclaredFields()) { ++ if (field.getType() == EnumMonsterType.class) { ++ enumMonsterTypeFieldMap.put( (EnumMonsterType) field.get(null), field.getName()); ++ } ++ } ++ ++ for (EntityCategory entityCategory : EntityCategory.values()) { ++ enumMonsterTypeFieldMap.remove(CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); ++ } ++ assertTrue(EnumMonsterType.class.getName() + " instance(s): " + Joiner.on(", ").join(enumMonsterTypeFieldMap.values()) + " do not have bukkit equivalents", enumMonsterTypeFieldMap.size() == 0); ++ } ++} diff --git a/patches/server-unmapped/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/server-unmapped/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch new file mode 100644 index 0000000000..d91f63378b --- /dev/null +++ b/patches/server-unmapped/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Tue, 18 May 2021 14:39:44 -0700 +Subject: [PATCH] Add command line option to load extra plugin jars not in the + plugins folder + +ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 89244c152665c97cb539bea07fedd1774ed626f1..8209f188dbc932114268486a2ebd77df989a86ec 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -385,8 +385,13 @@ public final class CraftServer implements Server { + + File pluginFolder = (File) console.options.valueOf("plugins"); + +- if (pluginFolder.exists()) { +- Plugin[] plugins = pluginManager.loadPlugins(pluginFolder); ++ // Paper start ++ if (true || pluginFolder.exists()) { ++ if (!pluginFolder.exists()) { ++ pluginFolder.mkdirs(); ++ } ++ Plugin[] plugins = pluginManager.loadPlugins(pluginFolder, this.extraPluginJars()); ++ // Paper end + for (Plugin plugin : plugins) { + try { + String message = String.format("Loading %s", plugin.getDescription().getFullName()); +@@ -401,6 +406,18 @@ public final class CraftServer implements Server { + } + } + ++ // Paper start ++ private List extraPluginJars() { ++ @SuppressWarnings("unchecked") ++ final List jars = (List) this.console.options.valuesOf("add-plugin"); ++ return jars.stream() ++ .filter(File::exists) ++ .filter(File::isFile) ++ .filter(file -> file.getName().endsWith(".jar")) ++ .collect(java.util.stream.Collectors.toList()); ++ } ++ // Paper end ++ + public void enablePlugins(PluginLoadOrder type) { + if (type == PluginLoadOrder.STARTUP) { + helpMap.clear(); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 6459ec144fa54a1e6ad1f0c40776321e95b41197..ecd1f0784493dfc758483b7912ce086c3b0d7aa0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -153,6 +153,12 @@ public class Main { + .ofType(String.class) + .defaultsTo("Unknown Server") + .describedAs("Name"); ++ ++ acceptsAll(asList("add-plugin", "add-extra-plugin-jar")) ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File[] {}) ++ .describedAs("Specify paths to extra plugin jars to be loaded in addition to those in the plugins folder. This argument can be specified multiple times, once for each extra plugin jar path."); + // Paper end + } + }; diff --git a/patches/server-unmapped/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/patches/server-unmapped/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch new file mode 100644 index 0000000000..8f6ee51048 --- /dev/null +++ b/patches/server-unmapped/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 10 May 2021 15:46:57 -0700 +Subject: [PATCH] Fix incorrect status dataconverter for pre 1.13 chunks + +Vanilla was setting non-populated OR non-lit chunks to empty, but +really this is just completely wrong. It should be set to "carved" +at minmum, because pre 1.13 chunks went through 3 distinct stages +of generation: carving, population, and lighting - in this order. +There is no "empty" status, because a chunk was simply carved +or it didn't exist. So mapping any chunk data to empty is simply +invalid. + +If the chunk is terrain populated, then obviously it must be at +minmum "decorated." If the chunk is lit and populated, then it is marked +"mobs_spawned" (which is what Vanilla is doing, and this is the last +stage before moving to full so it looks correct). + +So now here is a table representing the new status conversion: + +Chunk is lit Chunk is populated Vanilla + F F empty + T F empty + F T empty + T T mobs_spawned + +Chunk is lit Chunk is populated Paper + F F carved + T F carved + F T decorated + T T mobs_spawned + +This should fix some problems converting old data, as the +changes here are going to prevent the chunk from being regenerated +incorrectly. + +diff --git a/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java b/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java +index 3a114931cb88791bf73d08accf13993ba8842af2..7c0efe98af0bf99b04c0be6d6208d13af6e3cee4 100644 +--- a/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java ++++ b/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java +@@ -43,13 +43,21 @@ public class DataConverterProtoChunk extends DataFix { + return dynamic.asStreamOpt().result(); + }); + Dynamic dynamic = (Dynamic) typed1.get(DSL.remainderFinder()); +- boolean flag = dynamic.get("TerrainPopulated").asBoolean(false) && (!dynamic.get("LightPopulated").asNumber().result().isPresent() || dynamic.get("LightPopulated").asBoolean(false)); +- +- dynamic = dynamic.set("Status", dynamic.createString(flag ? "mobs_spawned" : "empty")); ++ // Paper start - fix incorrect status conversion ++ // Vanilla is setting chunks to incorrect status here, they should be using at minimum carved. ++ // for populated chunks, it should be at minimum decorated ++ // and for lit and populated, mobs_spawned is correct (technically mobs_spawned should be for populated, ++ // but if it's not lit then it can't be set above lit) ++ final boolean terrainPopulated = dynamic.get("TerrainPopulated").asBoolean(false); ++ final boolean lightPopulated = dynamic.get("LightPopulated").asBoolean(false) || dynamic.get("LightPopulated").asNumber().result().isPresent(); ++ final String newStatus = !terrainPopulated ? "carved" : (lightPopulated ? "mobs_spawned" : "decorated"); ++ ++ dynamic = dynamic.set("Status", dynamic.createString(newStatus)); + dynamic = dynamic.set("hasLegacyStructureData", dynamic.createBoolean(true)); +- Dynamic dynamic1; ++ // Paper end - fix incorrect status conversion ++ Dynamic dynamic1; // Paper - decompile fix + +- if (flag) { ++ if (true) { // Paper - fix incorrect status conversion + Optional optional1 = dynamic.get("Biomes").asByteBufferOpt().result(); + + if (optional1.isPresent()) { +@@ -70,7 +78,7 @@ public class DataConverterProtoChunk extends DataFix { + }).collect(Collectors.toList()); + + if (optional.isPresent()) { +- ((Stream) optional.get()).forEach((dynamic2) -> { ++ optional.get().forEach((dynamic2) -> { // Paper - decompile fix + int j = dynamic2.get("x").asInt(0); + int k = dynamic2.get("y").asInt(0); + int l = dynamic2.get("z").asInt(0); +@@ -78,11 +86,11 @@ public class DataConverterProtoChunk extends DataFix { + + ((ShortList) list.get(k >> 4)).add(short0); + }); ++ Dynamic finalDynamic = dynamic; // Paper - decompile fix + dynamic = dynamic.set("ToBeTicked", dynamic.createList(list.stream().map((shortlist) -> { +- Stream stream = shortlist.stream(); ++ Stream stream = shortlist.stream(); // Paper - decompile fix + +- dynamic.getClass(); +- return dynamic.createList(stream.map(dynamic::createShort)); ++ return finalDynamic.createList(stream.map(finalDynamic::createShort)); + }))); + } + diff --git a/patches/server-unmapped/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch b/patches/server-unmapped/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch new file mode 100644 index 0000000000..5eb9b4adc2 --- /dev/null +++ b/patches/server-unmapped/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SamB440 +Date: Fri, 21 May 2021 00:22:09 +0100 +Subject: [PATCH] Fix MC-148809: Increase structure block data length to 128 + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInStruct.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInStruct.java +index 2e19ac6b4e27c5d1bbefd5e99f8298650919d917..de3c33ae24e38471ab34d905f07992cb75dc0789 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInStruct.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInStruct.java +@@ -43,7 +43,7 @@ public class PacketPlayInStruct implements Packet { + this.f = new BlockPosition(MathHelper.clamp(packetdataserializer.readByte(), 0, 48), MathHelper.clamp(packetdataserializer.readByte(), 0, 48), MathHelper.clamp(packetdataserializer.readByte(), 0, 48)); + this.g = (EnumBlockMirror) packetdataserializer.a(EnumBlockMirror.class); + this.h = (EnumBlockRotation) packetdataserializer.a(EnumBlockRotation.class); +- this.i = packetdataserializer.e(12); ++ this.i = packetdataserializer.e(128); // Paper - Fix MC-148809, increase max character input to 128 + this.m = MathHelper.a(packetdataserializer.readFloat(), 0.0F, 1.0F); + this.n = packetdataserializer.j(); + byte b0 = packetdataserializer.readByte(); diff --git a/patches/server-unmapped/0738-Fix-and-optimise-world-force-upgrading.patch b/patches/server-unmapped/0738-Fix-and-optimise-world-force-upgrading.patch new file mode 100644 index 0000000000..74f1536633 --- /dev/null +++ b/patches/server-unmapped/0738-Fix-and-optimise-world-force-upgrading.patch @@ -0,0 +1,411 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Thu, 20 May 2021 07:02:22 -0700 +Subject: [PATCH] Fix and optimise world force upgrading + +The WorldUpgrader class was incorrectly modified by +CB. It will store an IChunkLoader instance for all +dimension types in the world, but obviously with how +CB shifts around worlds only one dimension type exists +per world. But this would be OK if CB did this +change correctly. All IChunkLoader instances +will point to the same regionfiles. And all +IChunkLoader instances are going to be read from. + +This problem hasn't really been reported because +it relies on the persistent legacy data to be converted +as well to cause corruption. Why? Because the legacy +data is also shared, it will result in different +outputs from conversion (as once conversion for legacy +persistent data takes place, it is REMOVED - so the next +convert will _not_ have the data). Which means different +sizes on disk. Which means different regionfile sector +allocations. Which means there are 3 different possible +regionfile sector allocations in memory, and none of them +are going to be correct. + +I've fixed this by writing a world upgrader suited to +CB's changes to world folder format. It was brain dead +easy to add threading, so I did. + +diff --git a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..db9f1241094a7529662ed643ba651d86ec86e09c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java +@@ -0,0 +1,200 @@ ++package io.papermc.paper.world; ++ ++import com.mojang.datafixers.DataFixer; ++import net.minecraft.SharedConstants; ++import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.resources.ResourceKey; ++import net.minecraft.util.worldupdate.WorldUpgrader; ++import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.level.chunk.storage.IChunkLoader; ++import net.minecraft.world.level.chunk.storage.RegionFileCache; ++import net.minecraft.world.level.dimension.DimensionManager; ++import net.minecraft.world.level.dimension.WorldDimension; ++import net.minecraft.world.level.storage.Convertable; ++import net.minecraft.world.level.storage.WorldPersistentData; ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++import java.io.File; ++import java.io.IOException; ++import java.text.DecimalFormat; ++import java.util.concurrent.ExecutorService; ++import java.util.concurrent.Executors; ++import java.util.concurrent.ThreadFactory; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.concurrent.atomic.AtomicLong; ++import java.util.function.Supplier; ++ ++public class ThreadedWorldUpgrader { ++ ++ private static final Logger LOGGER = LogManager.getLogger(); ++ ++ private final ResourceKey dimensionType; ++ private final ResourceKey worldKey; ++ private final String worldName; ++ private final ExecutorService threadPool; ++ private final DataFixer dataFixer; ++ private final boolean removeCaches; ++ ++ public ThreadedWorldUpgrader(final ResourceKey dimensionType, final ResourceKey worldKey, final String worldName, final int threads, ++ final DataFixer dataFixer, final boolean removeCaches) { ++ this.dimensionType = dimensionType; ++ this.worldKey = worldKey; ++ this.worldName = worldName; ++ this.threadPool = Executors.newFixedThreadPool(Math.max(1, threads), new ThreadFactory() { ++ private final AtomicInteger threadCounter = new AtomicInteger(); ++ ++ @Override ++ public Thread newThread(final Runnable run) { ++ final Thread ret = new Thread(run); ++ ++ ret.setName("World upgrader thread for world " + ThreadedWorldUpgrader.this.worldName + " #" + this.threadCounter.getAndIncrement()); ++ ret.setUncaughtExceptionHandler((thread, throwable) -> { ++ LOGGER.fatal("Error upgrading world", throwable); ++ }); ++ ++ return ret; ++ } ++ }); ++ this.dataFixer = dataFixer; ++ this.removeCaches = removeCaches; ++ } ++ ++ public void convert() { ++ final File worldFolder = Convertable.getFolder(new File(this.worldName), this.dimensionType); ++ final WorldPersistentData worldPersistentData = new WorldPersistentData(new File(worldFolder, "data"), this.dataFixer); ++ ++ final File regionFolder = new File(worldFolder, "region"); ++ ++ LOGGER.info("Force upgrading " + this.worldName); ++ LOGGER.info("Counting regionfiles for " + this.worldName); ++ final File[] regionFiles = regionFolder.listFiles((final File dir, final String name) -> { ++ return WorldUpgrader.getRegionfileRegex().matcher(name).matches(); ++ }); ++ if (regionFiles == null) { ++ LOGGER.info("Found no regionfiles to convert for world " + this.worldName); ++ return; ++ } ++ LOGGER.info("Found " + regionFiles.length + " regionfiles to convert"); ++ LOGGER.info("Starting conversion now for world " + this.worldName); ++ ++ final WorldInfo info = new WorldInfo(() -> worldPersistentData, ++ new IChunkLoader(regionFolder, this.dataFixer, false), this.removeCaches, this.worldKey); ++ ++ long expectedChunks = (long)regionFiles.length * (32L * 32L); ++ ++ for (final File regionFile : regionFiles) { ++ final ChunkCoordIntPair regionPos = RegionFileCache.getRegionFileCoordinates(regionFile); ++ if (regionPos == null) { ++ expectedChunks -= (32L * 32L); ++ continue; ++ } ++ ++ this.threadPool.execute(new ConvertTask(info, regionPos.x >> 5, regionPos.z >> 5)); ++ } ++ this.threadPool.shutdown(); ++ ++ final DecimalFormat format = new DecimalFormat("#0.00"); ++ ++ final long start = System.nanoTime(); ++ ++ while (!this.threadPool.isTerminated()) { ++ final long current = info.convertedChunks.get(); ++ ++ LOGGER.info("{}% completed ({} / {} chunks)...", format.format((double)current / (double)expectedChunks * 100.0), current, expectedChunks); ++ ++ try { ++ Thread.sleep(1000L); ++ } catch (final InterruptedException ignore) {} ++ } ++ ++ final long end = System.nanoTime(); ++ ++ try { ++ info.loader.close(); ++ } catch (final IOException ex) { ++ LOGGER.fatal("Failed to close chunk loader", ex); ++ } ++ LOGGER.info("Completed conversion. Took {}s, {} out of {} chunks needed to be converted/modified ({}%)", ++ (int)Math.ceil((end - start) * 1.0e-9), info.modifiedChunks.get(), expectedChunks, format.format((double)info.modifiedChunks.get() / (double)expectedChunks * 100.0)); ++ } ++ ++ private static final class WorldInfo { ++ ++ public final Supplier persistentDataSupplier; ++ public final IChunkLoader loader; ++ public final boolean removeCaches; ++ public final ResourceKey worldKey; ++ public final AtomicLong convertedChunks = new AtomicLong(); ++ public final AtomicLong modifiedChunks = new AtomicLong(); ++ ++ private WorldInfo(final Supplier persistentDataSupplier, final IChunkLoader loader, final boolean removeCaches, ++ final ResourceKey worldKey) { ++ this.persistentDataSupplier = persistentDataSupplier; ++ this.loader = loader; ++ this.removeCaches = removeCaches; ++ this.worldKey = worldKey; ++ } ++ } ++ ++ private static final class ConvertTask implements Runnable { ++ ++ private final WorldInfo worldInfo; ++ private final int regionX; ++ private final int regionZ; ++ ++ public ConvertTask(final WorldInfo worldInfo, final int regionX, final int regionZ) { ++ this.worldInfo = worldInfo; ++ this.regionX = regionX; ++ this.regionZ = regionZ; ++ } ++ ++ @Override ++ public void run() { ++ final int regionCX = this.regionX << 5; ++ final int regionCZ = this.regionZ << 5; ++ ++ final Supplier persistentDataSupplier = this.worldInfo.persistentDataSupplier; ++ final IChunkLoader loader = this.worldInfo.loader; ++ final boolean removeCaches = this.worldInfo.removeCaches; ++ final ResourceKey worldKey = this.worldInfo.worldKey; ++ ++ for (int cz = regionCZ; cz < (regionCZ + 32); ++cz) { ++ for (int cx = regionCX; cx < (regionCX + 32); ++cx) { ++ final ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(cx, cz); ++ try { ++ // no need to check the coordinate of the chunk, the regionfilecache does that for us ++ ++ NBTTagCompound chunkNBT = loader.read(chunkPos); ++ ++ if (chunkNBT == null) { ++ continue; ++ } ++ ++ final int versionBefore = IChunkLoader.getVersion(chunkNBT); ++ ++ chunkNBT = loader.getChunkData(worldKey, persistentDataSupplier, chunkNBT, chunkPos, null); ++ ++ boolean modified = versionBefore < SharedConstants.getGameVersion().getWorldVersion(); ++ ++ if (removeCaches) { ++ final NBTTagCompound level = chunkNBT.getCompound("Level"); ++ modified |= level.hasKey("Heightmaps"); ++ level.remove("Heightmaps"); ++ modified |= level.hasKey("isLightOn"); ++ level.remove("isLightOn"); ++ } ++ ++ if (modified) { ++ this.worldInfo.modifiedChunks.getAndIncrement(); ++ loader.write(chunkPos, chunkNBT); ++ } ++ } catch (final Exception ex) { ++ LOGGER.error("Error upgrading chunk {}", chunkPos, ex); ++ } finally { ++ this.worldInfo.convertedChunks.getAndIncrement(); ++ } ++ } ++ } ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index bf4051349917cc1d727fc5544237e0291cb6f1e6..15b972b4a93b8fe3655acec47bc84b0f2c4620a6 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -15,6 +15,7 @@ import java.nio.file.Paths; + import java.util.Optional; + import java.util.concurrent.CompletableFuture; + import java.util.function.BooleanSupplier; ++import io.papermc.paper.world.ThreadedWorldUpgrader; + import joptsimple.NonOptionArgumentSpec; + import joptsimple.OptionParser; + import joptsimple.OptionSet; +@@ -277,6 +278,15 @@ public class Main { + } + // Paper end + ++ // Paper start - fix and optimise world upgrading ++ public static void convertWorldButItWorks(ResourceKey dimensionType, ResourceKey worldKey, String worldName, ++ DataFixer dataFixer, boolean removeCaches) { ++ int threads = Runtime.getRuntime().availableProcessors() * 3 / 8; ++ final ThreadedWorldUpgrader worldUpgrader = new ThreadedWorldUpgrader(dimensionType, worldKey, worldName, threads, dataFixer, removeCaches); ++ worldUpgrader.convert(); ++ } ++ // Paper end - fix and optimise world upgrading ++ + public static void convertWorld(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, boolean flag, BooleanSupplier booleansupplier, ImmutableSet> immutableset) { // CraftBukkit + Main.LOGGER.info("Forcing world upgrade! {}", convertable_conversionsession.getLevelName()); // CraftBukkit + WorldUpgrader worldupgrader = new WorldUpgrader(convertable_conversionsession, datafixer, immutableset, flag); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index b3ebf5cd59c827b7426069eda0cb3d47b4386792..e47c9b7b64095f2a5cf6cb365550398eeeed724f 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -515,13 +515,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { +- return true; +- }, worlddata.getGeneratorSettings().d().d().stream().map((entry1) -> { +- return ResourceKey.a(IRegistry.K, ((ResourceKey) entry1.getKey()).a()); +- }).collect(ImmutableSet.toImmutableSet())); +- } ++ // Paper - move down + + IWorldDataServer iworlddataserver = worlddata; + GeneratorSettings generatorsettings = worlddata.getGeneratorSettings(); +@@ -541,6 +535,14 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant worldKey = ResourceKey.a(IRegistry.L, dimensionKey.a()); + + if (dimensionKey == WorldDimension.OVERWORLD) { +diff --git a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java +index a4970654496c52fcd02c5c055ff5ac551bd19da3..dca2e9e45116df22d8c95d1be8f0a7e3c2d2b6b1 100644 +--- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java ++++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java +@@ -55,7 +55,7 @@ public class WorldUpgrader { + private volatile int m; + private final Object2FloatMap> n = Object2FloatMaps.synchronize(new Object2FloatOpenCustomHashMap(SystemUtils.k())); // CraftBukkit + private volatile IChatBaseComponent o = new ChatMessage("optimizeWorld.stage.counting"); +- private static final Pattern p = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); ++ private static final Pattern p = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); public static final Pattern getRegionfileRegex() { return p; } // Paper - OBFHELPER + private final WorldPersistentData q; + + public WorldUpgrader(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, ImmutableSet> immutableset, boolean flag) { // CraftBukkit +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index 6581fe0d93a5c2e7b444a44c01726e02d4a28e63..f7f593a9e58b537109fa6ca1c783f6614f4bfad5 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -181,6 +181,15 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + return typeKey; + } + ++ // Paper start - fix and optimise world upgrading ++ // copied from below ++ public static ResourceKey getDimensionKey(DimensionManager manager) { ++ return ((org.bukkit.craftbukkit.CraftServer)org.bukkit.Bukkit.getServer()).getHandle().getServer().customRegistry.a().c(manager).orElseThrow(() -> { ++ return new IllegalStateException("Unregistered dimension type: " + manager); ++ }); ++ } ++ // Paper end - fix and optimise world upgrading ++ + protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName()); // Spigot + this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java +index 890362d28ab9cb760c73fe5014e144fb08ada6b8..e20b9e6c46093d48d5fa5eb3006087d4e998c205 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java +@@ -113,6 +113,7 @@ public class IChunkLoader implements AutoCloseable { + return nbttagcompound; + } + ++ public static int getVersion(NBTTagCompound nbttagcompound) { return a(nbttagcompound); } // Paper - OBFHELPER + public static int a(NBTTagCompound nbttagcompound) { + return nbttagcompound.hasKeyOfType("DataVersion", 99) ? nbttagcompound.getInt("DataVersion") : -1; + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +index ebb0d6988f87013ea5d523ab4a1b31cb669ccc43..74d826853389b8e01ffe2b076cf2b179d29da216 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java +@@ -30,6 +30,28 @@ public class RegionFileCache implements AutoCloseable { // Paper - no final + + + // Paper start ++ public static ChunkCoordIntPair getRegionFileCoordinates(File file) { ++ String fileName = file.getName(); ++ if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) { ++ return null; ++ } ++ ++ String[] split = fileName.split("\\."); ++ ++ if (split.length != 4) { ++ return null; ++ } ++ ++ try { ++ int x = Integer.parseInt(split[1]); ++ int z = Integer.parseInt(split[2]); ++ ++ return new ChunkCoordIntPair(x << 5, z << 5); ++ } catch (NumberFormatException ex) { ++ return null; ++ } ++ } ++ + public synchronized RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronize for async io + return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 8209f188dbc932114268486a2ebd77df989a86ec..cebecee640ed5a7fc2b978e00ff7eb012228267d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1146,14 +1146,7 @@ public final class CraftServer implements Server { + } + worlddata.checkName(name); + worlddata.a(console.getServerModName(), console.getModded().isPresent()); +- +- if (console.options.has("forceUpgrade")) { +- net.minecraft.server.Main.convertWorld(worldSession, DataConverterRegistry.a(), console.options.has("eraseCache"), () -> { +- return true; +- }, worlddata.getGeneratorSettings().d().d().stream().map((entry) -> { +- return ResourceKey.a(IRegistry.K, ((ResourceKey) entry.getKey()).a()); +- }).collect(ImmutableSet.toImmutableSet())); +- } ++ // Paper - move down + + long j = BiomeManager.a(creator.seed()); + List list = ImmutableList.of(new MobSpawnerPhantom(), new MobSpawnerPatrol(), new MobSpawnerCat(), new VillageSiege(), new MobSpawnerTrader(worlddata)); +@@ -1170,6 +1163,14 @@ public final class CraftServer implements Server { + chunkgenerator = worlddimension.c(); + } + ++ // Paper start - fix and optimise world upgrading ++ if (console.options.has("forceUpgrade")) { ++ net.minecraft.server.Main.convertWorldButItWorks( ++ actualDimension, net.minecraft.world.level.World.getDimensionKey(dimensionmanager), worldSession.getLevelName(), DataConverterRegistry.getDataFixer(), console.options.has("eraseCache") ++ ); ++ } ++ // Paper end - fix and optimise world upgrading ++ + ResourceKey worldKey; + String levelName = this.getServer().getDedicatedServerProperties().levelName; + if (name.equals(levelName + "_nether")) { diff --git a/patches/server-unmapped/0739-Add-Mob-lookAt-API.patch b/patches/server-unmapped/0739-Add-Mob-lookAt-API.patch new file mode 100644 index 0000000000..ba3abe238f --- /dev/null +++ b/patches/server-unmapped/0739-Add-Mob-lookAt-API.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 14 May 2021 13:42:17 -0500 +Subject: [PATCH] Add Mob#lookAt API + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +index 5c7fafeb7fab584eded30ebe415584132f4ab8af..6c024a5fdd290e5eb219e677e28718d663b72f25 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java ++++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java +@@ -852,14 +852,17 @@ public abstract class EntityInsentient extends EntityLiving { + + protected void mobTick() {} + ++ public int getMaxHeadXRot() { return O(); } // Paper - OBFHELPER + public int O() { + return 40; + } + ++ public int getMaxHeadYRot() { return Q(); } // Paper - OBFHELPER + public int Q() { + return 75; + } + ++ public int getHeadRotSpeed() { return ep(); } // Paper - OBFHELPER + public int ep() { + return 10; + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerLook.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerLook.java +index 3ce9edde641c8b8eea75479615bcd2866ffd2198..dadbaa7f43b8678b09c649e19a6eac8ec8b47d9d 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerLook.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerLook.java +@@ -20,18 +20,28 @@ public class ControllerLook { + this.a = entityinsentient; + } + ++ public void lookAt(Vec3D vec3d) { a(vec3d); } // Paper - OBFHELPER + public void a(Vec3D vec3d) { + this.a(vec3d.x, vec3d.y, vec3d.z); + } + ++ // Paper start ++ public void lookAt(Entity entity) { ++ this.lookAt(entity.locX(), getWantedY(entity), entity.locZ()); ++ } ++ // Paper end ++ ++ public void lookAt(Entity entity, float f, float f1) { a(entity, f, f1); } // Paper - OBFHELPER + public void a(Entity entity, float f, float f1) { + this.a(entity.locX(), b(entity), entity.locZ(), f, f1); + } + ++ public void lookAt(double d0, double d1, double d2) { a(d0, d1, d2); } // Paper - OBFHELPER + public void a(double d0, double d1, double d2) { + this.a(d0, d1, d2, (float) this.a.ep(), (float) this.a.O()); + } + ++ public void lookAt(double d0, double d1, double d2, float f, float f1) { a(d0, d1, d2, f, f1); } // Paper - OBFHELPER + public void a(double d0, double d1, double d2, float f, float f1) { + this.e = d0; + this.f = d1; +@@ -103,6 +113,7 @@ public class ControllerLook { + return f + f4; + } + ++ public static double getWantedY(Entity entity) { return b(entity); } // Paper - OBFHELPER + private static double b(Entity entity) { + return entity instanceof EntityLiving ? entity.getHeadY() : (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0D; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +index 06cbe63ef04e0de824ac0b9d545b6da1f53701b3..125be4ca56d38c6cba1d1f4e7587abda075ee491 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +@@ -84,5 +84,53 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { + public boolean isInDaylight() { + return getHandle().isInDaylight(); + } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location) { ++ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); ++ getHandle().getControllerLook().lookAt(location.getX(), location.getY(), location.getZ()); ++ } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location, float headRotationSpeed, float maxHeadPitch) { ++ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); ++ getHandle().getControllerLook().lookAt(location.getX(), location.getY(), location.getZ(), headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity) { ++ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); ++ getHandle().getControllerLook().lookAt(((CraftEntity) entity).getHandle()); ++ } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity, float headRotationSpeed, float maxHeadPitch) { ++ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); ++ getHandle().getControllerLook().lookAt(((CraftEntity) entity).getHandle(), headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public void lookAt(double x, double y, double z) { ++ getHandle().getControllerLook().lookAt(x, y, z); ++ } ++ ++ @Override ++ public void lookAt(double x, double y, double z, float headRotationSpeed, float maxHeadPitch) { ++ getHandle().getControllerLook().lookAt(x, y, z, headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public int getHeadRotationSpeed() { ++ return getHandle().getHeadRotSpeed(); ++ } ++ ++ @Override ++ public int getMaxHeadPitch() { ++ return getHandle().getMaxHeadXRot(); ++ } + // Paper end + } diff --git a/patches/server-unmapped/0740-Add-Unix-domain-socket-support.patch b/patches/server-unmapped/0740-Add-Unix-domain-socket-support.patch new file mode 100644 index 0000000000..0d2f573873 --- /dev/null +++ b/patches/server-unmapped/0740-Add-Unix-domain-socket-support.patch @@ -0,0 +1,141 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Tue, 11 May 2021 17:39:22 -0400 +Subject: [PATCH] Add Unix domain socket support + +For Windows and ARM support, JEP-380 is required: +https://inside.java/2021/02/03/jep380-unix-domain-sockets-channels/ +This will be possible as of the Minecraft 1.17 Java version bump. + +Tested-by: Mariell Hoversholm +Reviewed-by: Mariell Hoversholm + +diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +index f86f430598026a3a7e27fb8d40cfc5fe7b9b845d..bf0c01eaf593972bbb18c22cfdb3abd658ec6498 100644 +--- a/src/main/java/net/minecraft/network/NetworkManager.java ++++ b/src/main/java/net/minecraft/network/NetworkManager.java +@@ -564,6 +564,11 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + // Spigot Start + public SocketAddress getRawAddress() + { ++ // Paper start - this can be nullable in the case of a Unix domain socket, so if it is, fake something ++ if (this.channel.remoteAddress() == null) { ++ return new java.net.InetSocketAddress(java.net.InetAddress.getLoopbackAddress(), 0); ++ } ++ // Paper end + return this.channel.remoteAddress(); + } + // Spigot End +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 04ca3ed64d8fb9bce38d715d3618ab5c73d8cbfa..1929b992be3aeaa37c7b04c458f0ee41a60c692e 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -225,6 +225,20 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + this.i(dedicatedserverproperties.enforceWhitelist); + // this.saveData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading + DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode); ++ // Paper start - Unix domain socket support ++ java.net.SocketAddress bindAddress; ++ if (this.getServerIp().startsWith("unix:")) { ++ if (!io.netty.channel.epoll.Epoll.isAvailable()) { ++ DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!"); ++ DedicatedServer.LOGGER.fatal("You are trying to use a Unix domain socket but you're not on a supported OS."); ++ return false; ++ } else if (!com.destroystokyo.paper.PaperConfig.velocitySupport && !org.spigotmc.SpigotConfig.bungee) { ++ DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!"); ++ DedicatedServer.LOGGER.fatal("Unix domain sockets require IPs to be forwarded from a proxy."); ++ return false; ++ } ++ bindAddress = new io.netty.channel.unix.DomainSocketAddress(this.getServerIp().substring("unix:".length())); ++ } else { + InetAddress inetaddress = null; + + if (!this.getServerIp().isEmpty()) { +@@ -234,12 +248,15 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + if (this.getPort() < 0) { + this.setPort(dedicatedserverproperties.serverPort); + } ++ bindAddress = new java.net.InetSocketAddress(inetaddress, this.getPort()); ++ } ++ // Paper end + + this.P(); + DedicatedServer.LOGGER.info("Starting Minecraft server on {}:{}", this.getServerIp().isEmpty() ? "*" : this.getServerIp(), this.getPort()); + + try { +- this.getServerConnection().a(inetaddress, this.getPort()); ++ this.getServerConnection().bind(bindAddress); // Paper - Unix domain socket support + } catch (IOException ioexception) { + DedicatedServer.LOGGER.warn("**** FAILED TO BIND TO PORT!"); + DedicatedServer.LOGGER.warn("The exception was: {}", ioexception.toString()); +diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java +index 74006c0af831c0e6a2b84b3638e397ab54984dc5..82540af8170f0b8cb52b13061ae8f956f1a6e46f 100644 +--- a/src/main/java/net/minecraft/server/network/HandshakeListener.java ++++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java +@@ -44,6 +44,7 @@ public class HandshakeListener implements PacketHandshakingInListener { + this.c.setProtocol(EnumProtocol.LOGIN); + // CraftBukkit start - Connection throttle + try { ++ if (!(this.c.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress)) { // Paper - the connection throttle is useless when you have a Unix domain socket + long currentTime = System.currentTimeMillis(); + long connectionThrottle = this.b.server.getConnectionThrottle(); + InetAddress address = ((java.net.InetSocketAddress) this.c.getSocketAddress()).getAddress(); +@@ -72,6 +73,7 @@ public class HandshakeListener implements PacketHandshakingInListener { + } + } + } ++ } // Paper - add closing bracket for if check above + } catch (Throwable t) { + org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); + } +@@ -120,8 +122,11 @@ public class HandshakeListener implements PacketHandshakingInListener { + //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! + String[] split = packethandshakinginsetprotocol.hostname.split("\00"); + if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper ++ // Paper start - Unix domain socket support ++ java.net.SocketAddress socketAddress = c.getSocketAddress(); + packethandshakinginsetprotocol.hostname = split[0]; +- c.socketAddress = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) c.getSocketAddress()).getPort()); ++ c.socketAddress = new java.net.InetSocketAddress(split[1], socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); ++ // Paper end + c.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); + } else + { +diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java +index 69fc2789df88344587b6052f93661ed38f24a503..06b0ed65905b9829564dfddd29012218af0f403d 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnection.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnection.java +@@ -70,7 +70,12 @@ public class ServerConnection { + this.c = true; + } + ++ // Paper start + public void a(@Nullable InetAddress inetaddress, int i) throws IOException { ++ bind(new java.net.InetSocketAddress(inetaddress, i)); ++ } ++ public void bind(java.net.SocketAddress address) throws IOException { ++ // Paper end + List list = this.listeningChannels; + + synchronized (this.listeningChannels) { +@@ -78,7 +83,11 @@ public class ServerConnection { + LazyInitVar lazyinitvar; + + if (Epoll.isAvailable() && this.e.l()) { ++ if (address instanceof io.netty.channel.unix.DomainSocketAddress) { ++ oclass = io.netty.channel.epoll.EpollServerDomainSocketChannel.class; ++ } else { + oclass = EpollServerSocketChannel.class; ++ } + lazyinitvar = ServerConnection.b; + ServerConnection.LOGGER.info("Using epoll channel type"); + } else { +@@ -106,7 +115,7 @@ public class ServerConnection { + ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object)); + io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper + } +- }).group((EventLoopGroup) lazyinitvar.a()).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit ++ }).group((EventLoopGroup) lazyinitvar.a()).localAddress(address)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit // Paper + } + } + diff --git a/patches/server-unmapped/0741-Add-EntityInsideBlockEvent.patch b/patches/server-unmapped/0741-Add-EntityInsideBlockEvent.patch new file mode 100644 index 0000000000..20d8b726d4 --- /dev/null +++ b/patches/server-unmapped/0741-Add-EntityInsideBlockEvent.patch @@ -0,0 +1,222 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 8 May 2021 18:02:36 -0700 +Subject: [PATCH] Add EntityInsideBlockEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockBubbleColumn.java b/src/main/java/net/minecraft/world/level/block/BlockBubbleColumn.java +index efeae8cd002a3f801b8d5054389f9a0c74187fc4..e117853e8255cc4702e33ea7491a4e8d0d9b554a 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockBubbleColumn.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockBubbleColumn.java +@@ -33,6 +33,7 @@ public class BlockBubbleColumn extends Block implements IFluidSource { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + IBlockData iblockdata1 = world.getType(blockposition.up()); + + if (iblockdata1.isAir()) { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockButtonAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockButtonAbstract.java +index e62112f00d5c9c444aef4a142290ad28caa05264..be8e175e4f4fb2606a0393739d1a470bdacdb440 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockButtonAbstract.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockButtonAbstract.java +@@ -180,6 +180,7 @@ public abstract class BlockButtonAbstract extends BlockAttachable { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (!world.isClientSide && this.v && !(Boolean) iblockdata.get(BlockButtonAbstract.POWERED)) { + this.e(iblockdata, world, blockposition); + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockCactus.java b/src/main/java/net/minecraft/world/level/block/BlockCactus.java +index 9f1e9fc5361cd051b909e2e1b2095722064185da..dc0e87b2f7d2923822e45efb129c7c6da2790298 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockCactus.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockCactus.java +@@ -116,6 +116,7 @@ public class BlockCactus extends Block { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + CraftEventFactory.blockDamage = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); // CraftBukkit + entity.damageEntity(DamageSource.CACTUS, 1.0F); + CraftEventFactory.blockDamage = null; // CraftBukkit +diff --git a/src/main/java/net/minecraft/world/level/block/BlockCampfire.java b/src/main/java/net/minecraft/world/level/block/BlockCampfire.java +index 21baa8fb99b0587da503e14e2b04abf3134d03bc..023128e5c737ad26e40e4019e70df856395addcb 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockCampfire.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockCampfire.java +@@ -88,6 +88,7 @@ public class BlockCampfire extends BlockTileEntity implements IBlockWaterlogged + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (!entity.isFireProof() && (Boolean) iblockdata.get(BlockCampfire.LIT) && entity instanceof EntityLiving && !EnchantmentManager.i((EntityLiving) entity)) { + entity.damageEntity(DamageSource.FIRE, (float) this.h); + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockCauldron.java b/src/main/java/net/minecraft/world/level/block/BlockCauldron.java +index 66d0a08f250fc947ec2d978a527ad77e32114b84..7fc66d4bf6b6f84ce7c7bda282788abc855b3ea8 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockCauldron.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockCauldron.java +@@ -59,6 +59,7 @@ public class BlockCauldron extends Block { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + int i = (Integer) iblockdata.get(BlockCauldron.LEVEL); + float f = (float) blockposition.getY() + (6.0F + (float) (3 * i)) / 16.0F; + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockCrops.java b/src/main/java/net/minecraft/world/level/block/BlockCrops.java +index 09f15d9087f1c40e5d50cb56f8c764ddaa992e41..32d71b6fc3fd0300386fb80e6d12d5f7c2361efe 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockCrops.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockCrops.java +@@ -160,6 +160,7 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (entity instanceof EntityRavager && !CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.getBlockData(), !world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { // CraftBukkit + world.a(blockposition, true, entity); + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java +index fc89b3bf5075497596885548d80e4ed0b800ea89..ed916f69747b44b75eb06db4cf27adaf5e47fd1e 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java +@@ -43,6 +43,7 @@ public class BlockEnderPortal extends BlockTileEntity { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (world instanceof WorldServer && !entity.isPassenger() && !entity.isVehicle() && entity.canPortal() && VoxelShapes.c(VoxelShapes.a(entity.getBoundingBox().d((double) (-blockposition.getX()), (double) (-blockposition.getY()), (double) (-blockposition.getZ()))), iblockdata.getShape(world, blockposition), OperatorBoolean.AND)) { + ResourceKey resourcekey = world.getTypeKey() == DimensionManager.THE_END ? World.OVERWORLD : World.THE_END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends + WorldServer worldserver = ((WorldServer) world).getMinecraftServer().getWorldServer(resourcekey); +diff --git a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java +index 02047bf07c2008c7de8daf3d76b660e25b77bce8..a256ab003d3798407d2e9432006bfea161bec1d2 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java +@@ -48,6 +48,7 @@ public abstract class BlockFireAbstract extends Block { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (!entity.isFireProof()) { + entity.setFireTicks(entity.getFireTicks() + 1); + if (entity.getFireTicks() == 0) { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockHoney.java b/src/main/java/net/minecraft/world/level/block/BlockHoney.java +index d62cd3717f05c014f0ba26fc459318e10519def4..47b0ef3796413025cd5e10628f6ab92fead92ea9 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockHoney.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockHoney.java +@@ -49,6 +49,7 @@ public class BlockHoney extends BlockHalfTransparent { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (this.a(blockposition, entity)) { + this.a(entity, blockposition); + this.d(entity); +diff --git a/src/main/java/net/minecraft/world/level/block/BlockHopper.java b/src/main/java/net/minecraft/world/level/block/BlockHopper.java +index f9f5d11dee04f4056395fb8edb61a4616051350a..3555c2bdba01bcfadbd72459d69a850da35d3bdc 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockHopper.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockHopper.java +@@ -197,6 +197,7 @@ public class BlockHopper extends BlockTileEntity { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + TileEntity tileentity = world.getTileEntity(blockposition); + + if (tileentity instanceof TileEntityHopper) { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java +index 27573a0334b06f4b6ada672057695d8f8a2bcfc4..5bff21c47c608eeddf564270ba433f83ccaea1ea 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java +@@ -45,6 +45,7 @@ public class BlockMinecartDetector extends BlockMinecartTrackAbstract { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (!world.isClientSide) { + if (!(Boolean) iblockdata.get(BlockMinecartDetector.POWERED)) { + this.a(world, blockposition, iblockdata); +diff --git a/src/main/java/net/minecraft/world/level/block/BlockPortal.java b/src/main/java/net/minecraft/world/level/block/BlockPortal.java +index 5f797260eff317409a5039b88b01ad79ee2fdd91..f030aa3ddd001e018539ae93c238f2afb26e0fc2 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockPortal.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockPortal.java +@@ -82,6 +82,7 @@ public class BlockPortal extends Block { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (!entity.isPassenger() && !entity.isVehicle() && entity.canPortal()) { + // CraftBukkit start - Entity in portal + EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ())); +diff --git a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateAbstract.java +index 5b03e2ddf31db372607e6a997840ebe7f179801f..4fc3cf7c255a183f3da19fd91c13cd5e3c0550b6 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateAbstract.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateAbstract.java +@@ -66,6 +66,7 @@ public abstract class BlockPressurePlateAbstract extends Block { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (!world.isClientSide) { + int i = this.getPower(iblockdata); + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockSweetBerryBush.java b/src/main/java/net/minecraft/world/level/block/BlockSweetBerryBush.java +index 46459c3840ea23d11d2f44befc687018be2cf7e5..24c9863bd063390aa2911a86dc9c9d6c77f7ecd7 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockSweetBerryBush.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockSweetBerryBush.java +@@ -67,6 +67,7 @@ public class BlockSweetBerryBush extends BlockPlant implements IBlockFragilePlan + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (entity instanceof EntityLiving && entity.getEntityType() != EntityTypes.FOX && entity.getEntityType() != EntityTypes.BEE) { + entity.a(iblockdata, new Vec3D(0.800000011920929D, 0.75D, 0.800000011920929D)); + if (!world.isClientSide && (Integer) iblockdata.get(BlockSweetBerryBush.a) > 0 && (entity.D != entity.locX() || entity.F != entity.locZ())) { +diff --git a/src/main/java/net/minecraft/world/level/block/BlockTripwire.java b/src/main/java/net/minecraft/world/level/block/BlockTripwire.java +index 74037572010c40b363af62fd251d3f514a0940e9..46a4dd932d84bf72c1837e36add56f219d6b5e77 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockTripwire.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockTripwire.java +@@ -119,6 +119,7 @@ public class BlockTripwire extends Block { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (!world.isClientSide) { + if (!(Boolean) iblockdata.get(BlockTripwire.POWERED)) { + this.a(world, blockposition); +diff --git a/src/main/java/net/minecraft/world/level/block/BlockWaterLily.java b/src/main/java/net/minecraft/world/level/block/BlockWaterLily.java +index f32993d037bad535ef9867ae7634da5d53681dba..97bb8c7677ca56692666e54bf67ec43d403d3eec 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockWaterLily.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockWaterLily.java +@@ -25,6 +25,7 @@ public class BlockWaterLily extends BlockPlant { + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { + super.a(iblockdata, world, blockposition, entity); ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (world instanceof WorldServer && entity instanceof EntityBoat && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { // CraftBukkit + world.a(new BlockPosition(blockposition), true, entity); + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockWeb.java b/src/main/java/net/minecraft/world/level/block/BlockWeb.java +index a574878b1e69538430d9967b708e8d6a5060233d..d88663610c4833004c2fd33b8570a67fc884d380 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockWeb.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockWeb.java +@@ -15,6 +15,7 @@ public class BlockWeb extends Block { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + entity.a(iblockdata, new Vec3D(0.25D, 0.05000000074505806D, 0.25D)); + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/BlockWitherRose.java b/src/main/java/net/minecraft/world/level/block/BlockWitherRose.java +index 3c43e498fb3aa61fb7ee6592623581764b27f160..2692c205d099880205ccd73a739679f3946839ab 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockWitherRose.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockWitherRose.java +@@ -26,6 +26,7 @@ public class BlockWitherRose extends BlockFlowers { + + @Override + public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper + if (!world.isClientSide && world.getDifficulty() != EnumDifficulty.PEACEFUL) { + if (entity instanceof EntityLiving) { + EntityLiving entityliving = (EntityLiving) entity; diff --git a/patches/server-unmapped/0742-Attributes-API-for-item-defaults.patch b/patches/server-unmapped/0742-Attributes-API-for-item-defaults.patch new file mode 100644 index 0000000000..7c9a583959 --- /dev/null +++ b/patches/server-unmapped/0742-Attributes-API-for-item-defaults.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 8 May 2021 15:01:54 -0700 +Subject: [PATCH] Attributes API for item defaults + + +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index 7c9ef73983c2c7f4b7386a472e5a79dce7fa7ea7..0486a3158eb81947f78cef11aa4d4f141c40dfb5 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -274,6 +274,7 @@ public class Item implements IMaterial { + return false; + } + ++ public Multimap getAttributesForSlot(EnumItemSlot enumItemSlot) { return a(enumItemSlot); } // Paper - OBFHELPER + public Multimap a(EnumItemSlot enumitemslot) { + return ImmutableMultimap.of(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index a386beea01056a7fb448596ba45342d832a4c63d..6cb8608f8238c4a8c346b92ba672c8cc1c0cbcc4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -495,6 +495,19 @@ public final class CraftMagicNumbers implements UnsafeValues { + return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); + } + ++ @Override ++ public com.google.common.collect.Multimap getItemAttributes(org.bukkit.Material material, org.bukkit.inventory.EquipmentSlot equipmentSlot) { ++ Item item = this.getItem(material); ++ if (item == null) { ++ throw new IllegalArgumentException(material + " is not an item and therefore does not have attributes"); ++ } ++ com.google.common.collect.ImmutableMultimap.Builder attributeMapBuilder = com.google.common.collect.ImmutableMultimap.builder(); ++ item.getAttributesForSlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(equipmentSlot)).forEach((attributeBase, attributeModifier) -> { ++ attributeMapBuilder.put(org.bukkit.Registry.ATTRIBUTE.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.IRegistry.ATTRIBUTE.getKey(attributeBase))), org.bukkit.craftbukkit.attribute.CraftAttributeInstance.convert(attributeModifier)); ++ }); ++ return attributeMapBuilder.build(); ++ } ++ + @Override + public int getProtocolVersion() { + return net.minecraft.SharedConstants.getGameVersion().getProtocolVersion(); diff --git a/patches/server-unmapped/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/patches/server-unmapped/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch new file mode 100644 index 0000000000..154ff25eb1 --- /dev/null +++ b/patches/server-unmapped/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexander +Date: Thu, 6 May 2021 13:01:25 +0100 +Subject: [PATCH] Have CraftMerchantCustom emit PlayerPurchaseEvent + + +diff --git a/src/main/java/net/minecraft/world/item/trading/IMerchant.java b/src/main/java/net/minecraft/world/item/trading/IMerchant.java +index 5644affeadc51ac3209ee9a087b3d2dd887e401c..7c54ca6af424b9d31f73187df9015f5df84762f4 100644 +--- a/src/main/java/net/minecraft/world/item/trading/IMerchant.java ++++ b/src/main/java/net/minecraft/world/item/trading/IMerchant.java +@@ -19,7 +19,7 @@ public interface IMerchant { + + MerchantRecipeList getOffers(); + +- void a(MerchantRecipe merchantrecipe); ++ void a(MerchantRecipe merchantrecipe); default void handlePurchase(MerchantRecipe merchantRecipe) { a(merchantRecipe); } // Paper - OBFHELPER + + void k(ItemStack itemstack); + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +index 206c133ebc6c44038585236b0628543b8bed278c..a7230776b8e85d5d1873ab2dc4e10c5bf78889bb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +@@ -81,6 +81,35 @@ public class CraftMerchantCustom extends CraftMerchant { + + @Override + public void a(MerchantRecipe merchantrecipe) { ++ // Paper start ++ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerAbstract#b(MerchantRecipe)} */ ++ if (getTrader() instanceof net.minecraft.server.level.EntityPlayer) { ++ final net.minecraft.server.level.EntityPlayer trader = (net.minecraft.server.level.EntityPlayer) getTrader(); ++ final io.papermc.paper.event.player.PlayerPurchaseEvent event = new io.papermc.paper.event.player.PlayerPurchaseEvent( ++ trader.getBukkitEntity(), ++ merchantrecipe.asBukkit(), ++ false, // reward xp? ++ true); // should increase uses? ++ event.callEvent(); ++ if (event.isCancelled()) { ++ return; ++ } ++ final org.bukkit.inventory.MerchantRecipe eventTrade = event.getTrade(); ++ if (event.willIncreaseTradeUses()) { ++ eventTrade.setUses(eventTrade.getUses() + 1); ++ } ++ if (event.isRewardingExp() && eventTrade.hasExperienceReward()) { ++ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerTrader#b(MerchantRecipe)} */ ++ final int xp = 3 + net.minecraft.world.entity.Entity.SHARED_RANDOM.nextInt(4); ++ final World world = trader.getWorld(); ++ world.addEntity(new net.minecraft.world.entity.EntityExperienceOrb( ++ world, trader.locX(), trader.locY() + 0.5d, trader.locZ(), xp, ++ org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, trader, null)); ++ } ++ return; ++ } ++ // Paper end ++ + // increase recipe's uses + merchantrecipe.increaseUses(); + } diff --git a/patches/server-unmapped/0744-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/server-unmapped/0744-Add-cause-to-Weather-ThunderChangeEvents.patch new file mode 100644 index 0000000000..291410ed1d --- /dev/null +++ b/patches/server-unmapped/0744-Add-cause-to-Weather-ThunderChangeEvents.patch @@ -0,0 +1,118 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 2 Dec 2020 18:23:26 -0800 +Subject: [PATCH] Add cause to Weather/ThunderChangeEvents + + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 6aace2155258d8257d53ebfcb20c37ea7497c02c..f68a252378a94c8fcab622d2d89d738aceab45a4 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -419,8 +419,8 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.worldDataServer.setClearWeatherTime(i); + this.worldDataServer.setWeatherDuration(j); + this.worldDataServer.setThunderDuration(j); +- this.worldDataServer.setStorm(flag); +- this.worldDataServer.setThundering(flag1); ++ this.worldDataServer.setStorm(flag, org.bukkit.event.weather.WeatherChangeEvent.Cause.COMMAND); // Paper ++ this.worldDataServer.setThundering(flag1, org.bukkit.event.weather.ThunderChangeEvent.Cause.COMMAND); // Paper + } + + public BiomeBase getBiomeBySeed(int i, int j, int k) { return a(i, j, k); } // Paper - OBFHELPER +@@ -482,8 +482,8 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.worldDataServer.setThunderDuration(j); + this.worldDataServer.setWeatherDuration(k); + this.worldDataServer.setClearWeatherTime(i); +- this.worldDataServer.setThundering(flag1); +- this.worldDataServer.setStorm(flag2); ++ this.worldDataServer.setThundering(flag1, org.bukkit.event.weather.ThunderChangeEvent.Cause.NATURAL); // Paper ++ this.worldDataServer.setStorm(flag2, org.bukkit.event.weather.WeatherChangeEvent.Cause.NATURAL); // Paper + } + + this.lastThunderLevel = this.thunderLevel; +@@ -885,14 +885,14 @@ public class WorldServer extends World implements GeneratorAccessSeed { + + private void clearWeather() { + // CraftBukkit start +- this.worldDataServer.setStorm(false); ++ this.worldDataServer.setStorm(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - when passing the night + // If we stop due to everyone sleeping we should reset the weather duration to some other random value. + // Not that everyone ever manages to get the whole server to sleep at the same time.... + if (!this.worldDataServer.hasStorm()) { + this.worldDataServer.setWeatherDuration(0); + } + // CraftBukkit end +- this.worldDataServer.setThundering(false); ++ this.worldDataServer.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - when passing the night + // CraftBukkit start + // If we stop due to everyone sleeping we should reset the weather duration to some other random value. + // Not that everyone ever manages to get the whole server to sleep at the same time.... +diff --git a/src/main/java/net/minecraft/world/level/storage/WorldDataServer.java b/src/main/java/net/minecraft/world/level/storage/WorldDataServer.java +index 202d0aea445003a6dc3355ff2f2663cc675d4504..16ebfe8d873ba05521e0a49156325f14e8bd6eb9 100644 +--- a/src/main/java/net/minecraft/world/level/storage/WorldDataServer.java ++++ b/src/main/java/net/minecraft/world/level/storage/WorldDataServer.java +@@ -327,6 +327,11 @@ public class WorldDataServer implements IWorldDataServer, SaveData { + + @Override + public void setThundering(boolean flag) { ++ // Paper start ++ this.setThundering(flag, org.bukkit.event.weather.ThunderChangeEvent.Cause.UNKNOWN); ++ } ++ public void setThundering(boolean flag, org.bukkit.event.weather.ThunderChangeEvent.Cause cause) { ++ // Paper end + // CraftBukkit start + if (this.thundering == flag) { + return; +@@ -334,7 +339,7 @@ public class WorldDataServer implements IWorldDataServer, SaveData { + + org.bukkit.World world = Bukkit.getWorld(getName()); + if (world != null) { +- ThunderChangeEvent thunder = new ThunderChangeEvent(world, flag); ++ ThunderChangeEvent thunder = new ThunderChangeEvent(world, flag, cause); // Paper + Bukkit.getServer().getPluginManager().callEvent(thunder); + if (thunder.isCancelled()) { + return; +@@ -361,6 +366,12 @@ public class WorldDataServer implements IWorldDataServer, SaveData { + + @Override + public void setStorm(boolean flag) { ++ // Paper start ++ this.setStorm(flag, org.bukkit.event.weather.WeatherChangeEvent.Cause.UNKNOWN); ++ } ++ ++ public void setStorm(boolean flag, org.bukkit.event.weather.WeatherChangeEvent.Cause cause) { ++ // Paper end + // CraftBukkit start + if (this.raining == flag) { + return; +@@ -368,7 +379,7 @@ public class WorldDataServer implements IWorldDataServer, SaveData { + + org.bukkit.World world = Bukkit.getWorld(getName()); + if (world != null) { +- WeatherChangeEvent weather = new WeatherChangeEvent(world, flag); ++ WeatherChangeEvent weather = new WeatherChangeEvent(world, flag, cause); // Paper + Bukkit.getServer().getPluginManager().callEvent(weather); + if (weather.isCancelled()) { + return; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 3b3eda95c0ff8b129adedbae6561bba2d01c2f3a..9d858f91828d6c2787ff1dc677a247bcab172701 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1470,7 +1470,7 @@ public class CraftWorld implements World { + + @Override + public void setStorm(boolean hasStorm) { +- world.worldData.setStorm(hasStorm); ++ world.worldDataServer.setStorm(hasStorm, org.bukkit.event.weather.WeatherChangeEvent.Cause.PLUGIN); // Paper + setWeatherDuration(0); // Reset weather duration (legacy behaviour) + setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) + } +@@ -1492,7 +1492,7 @@ public class CraftWorld implements World { + + @Override + public void setThundering(boolean thundering) { +- world.worldDataServer.setThundering(thundering); ++ world.worldDataServer.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.PLUGIN); // Paper + setThunderDuration(0); // Reset weather duration (legacy behaviour) + setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) + } diff --git a/patches/server-unmapped/0745-More-Lidded-Block-API.patch b/patches/server-unmapped/0745-More-Lidded-Block-API.patch new file mode 100644 index 0000000000..a6ca6b4eca --- /dev/null +++ b/patches/server-unmapped/0745-More-Lidded-Block-API.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: LemonCaramel +Date: Sun, 23 May 2021 17:49:51 +0900 +Subject: [PATCH] More Lidded Block API + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java +index 2bc4213c70be47ca8bbc24898cc92e43f4228821..d03c4d100783b5d9f882c010a63dda3451db3c2e 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java +@@ -10,8 +10,9 @@ public class TileEntityEnderChest extends TileEntity { // Paper - Remove ITickab + + public float a; + public float b; +- public int c; ++ public int c; public int getViewerCount() { return c; } // Paper - OBFHELPER + private int g; ++ public boolean opened; // Paper - More Lidded Block API + + public TileEntityEnderChest() { + super(TileEntityTypes.ENDER_CHEST); +@@ -106,12 +107,14 @@ public class TileEntityEnderChest extends TileEntity { // Paper - Remove ITickab + + public void d() { + ++this.c; ++ if (opened) return; // Paper - More Lidded Block API + this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); + doOpenLogic(); // Paper + } + + public void f() { + --this.c; ++ if (opened) return; // Paper - More Lidded Block API + this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); + doCloseLogic(); // Paper + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java +index e27f5d689d689d4f65c285802bf327e96c113c46..f47fd41981bd89879627c2f0bb05d0ff70cc20fe 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java +@@ -59,4 +59,11 @@ public class CraftBarrel extends CraftLootable implements Barr + } + getTileEntity().opened = false; + } ++ ++ // Paper start - More Lidded Block API ++ @Override ++ public boolean isOpen() { ++ return getTileEntity().opened; ++ } ++ // Paper end - More Lidded Block API + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +index 54eb170fd533b0e91572601268fcbc167ed9bb5c..374034e659f856895843f3e33cce750d5cca0244 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +@@ -78,4 +78,11 @@ public class CraftChest extends CraftLootable implements Chest, + } + getTileEntity().opened = false; + } ++ ++ // Paper start - More Lidded Block API ++ @Override ++ public boolean isOpen() { ++ return getTileEntity().opened; ++ } ++ // Paper end - More Lidded Block API + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java +index 3c0b28faa86fb2ebb6165ff9efb0e7e41230c5e4..01192a3a1354d36c1d5541ddcf4037e983fd3cf9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java +@@ -14,4 +14,33 @@ public class CraftEnderChest extends CraftBlockEntityState + public CraftEnderChest(final Material material, final TileEntityEnderChest te) { + super(material, te); + } ++ ++ // Paper start - More Lidded Block API ++ @Override ++ public void open() { ++ requirePlaced(); ++ if (!getTileEntity().opened) { ++ net.minecraft.world.level.World world = getTileEntity().getWorld(); ++ world.playBlockAction(getTileEntity().getPosition(), getTileEntity().getBlock().getBlock(), 1, getTileEntity().getViewerCount() + 1); ++ world.playSound(null, getPosition(), net.minecraft.sounds.SoundEffects.BLOCK_ENDER_CHEST_OPEN, net.minecraft.sounds.SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); ++ } ++ getTileEntity().opened = true; ++ } ++ ++ @Override ++ public void close() { ++ requirePlaced(); ++ if (getTileEntity().opened) { ++ net.minecraft.world.level.World world = getTileEntity().getWorld(); ++ world.playBlockAction(getTileEntity().getPosition(), getTileEntity().getBlock().getBlock(), 1, 0); ++ world.playSound(null, getPosition(), net.minecraft.sounds.SoundEffects.BLOCK_ENDER_CHEST_CLOSE, net.minecraft.sounds.SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); ++ } ++ getTileEntity().opened = false; ++ } ++ ++ @Override ++ public boolean isOpen() { ++ return getTileEntity().opened; ++ } ++ // Paper end - More Lidded Block API + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java +index fcf2a1810729fda56e4064702f5f3b4d2b3f1523..ffd10dfdaf348625e1653e2fd8add5e58f895bdd 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java +@@ -62,8 +62,15 @@ public class CraftShulkerBox extends CraftLootable impleme + if (getTileEntity().opened) { + World world = getTileEntity().getWorld(); + world.playBlockAction(getPosition(), getTileEntity().getBlock().getBlock(), 1, 0); +- world.playSound(null, getPosition(), SoundEffects.BLOCK_SHULKER_BOX_OPEN, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); ++ world.playSound(null, getPosition(), SoundEffects.BLOCK_SHULKER_BOX_CLOSE, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); // Paper - More Lidded Block API (Wrong sound) + } + getTileEntity().opened = false; + } ++ ++ // Paper start - More Lidded Block API ++ @Override ++ public boolean isOpen() { ++ return getTileEntity().opened; ++ } ++ // Paper end - More Lidded Block API + } diff --git a/patches/server-unmapped/0746-Add-PlayerKickEvent-causes.patch b/patches/server-unmapped/0746-Add-PlayerKickEvent-causes.patch new file mode 100644 index 0000000000..7c600c021d --- /dev/null +++ b/patches/server-unmapped/0746-Add-PlayerKickEvent-causes.patch @@ -0,0 +1,393 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 20:30:45 -0700 +Subject: [PATCH] Add PlayerKickEvent causes + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index e47c9b7b64095f2a5cf6cb365550398eeeed724f..bf80e870e6a2a6fe1d4ae1bea355bcd7a0735d3b 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2044,7 +2044,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 80) { + PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", this.player.getDisplayName().getString()); +- this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_PLAYER); // Paper - use configurable kick message & kick event cause + return; + } + } else { +@@ -348,7 +348,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + if (this.D && this.player.getRootVehicle().getRidingPassenger() == this.player) { + if (++this.E > 80) { + PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getDisplayName().getString()); +- this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message ++ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_VEHICLE); // Paper - use configurable kick message & kick event cause + return; + } + } else { +@@ -370,7 +370,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + if (this.isPendingPing()) { + if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected + PlayerConnection.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getName()); // more info +- this.disconnect(new ChatMessage("disconnect.timeout", new Object[0])); ++ this.disconnect(new ChatMessage("disconnect.timeout", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause + } + } else { + if (elapsedTime >= 15000L) { // 15 seconds +@@ -400,7 +400,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + + if (this.player.F() > 0L && this.minecraftServer.getIdleTimeout() > 0 && SystemUtils.getMonotonicMillis() - this.player.F() > (long) (this.minecraftServer.getIdleTimeout() * 1000 * 60)) { + this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854 +- this.disconnect(new ChatMessage("multiplayer.disconnect.idling")); ++ this.disconnect(new ChatMessage("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause + } + + } +@@ -425,14 +425,22 @@ public class PlayerConnection implements PacketListenerPlayIn { + + public void disconnect(String s) { + // Paper start +- this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); ++ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); ++ } ++ ++ public void disconnect(String s, PlayerKickEvent.Cause cause) { ++ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s), cause); + } + + public void disconnect(final IChatBaseComponent reason) { +- this.disconnect(PaperAdventure.asAdventure(reason)); ++ this.disconnect(PaperAdventure.asAdventure(reason), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); ++ } ++ ++ public void disconnect(final IChatBaseComponent reason, PlayerKickEvent.Cause cause) { ++ this.disconnect(PaperAdventure.asAdventure(reason), cause); + } + +- public void disconnect(net.kyori.adventure.text.Component reason) { ++ public void disconnect(net.kyori.adventure.text.Component reason, org.bukkit.event.player.PlayerKickEvent.Cause cause) { + // Paper end + // CraftBukkit start - fire PlayerKickEvent + if (this.processedDisconnect) { +@@ -440,7 +448,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure + +- PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure ++ PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), reason, leaveMessage, cause); // Paper - Adventure & kick event reason + + if (this.server.getServer().isRunning()) { + this.server.getPluginManager().callEvent(event); +@@ -518,7 +526,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + public void a(PacketPlayInVehicleMove packetplayinvehiclemove) { + PlayerConnectionUtils.ensureMainThread(packetplayinvehiclemove, this, this.player.getWorldServer()); + if (b(packetplayinvehiclemove)) { +- this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_vehicle_movement")); ++ this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_vehicle_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_VEHICLE_MOVEMENT); // Paper - kick event cause + } else { + Entity entity = this.player.getRootVehicle(); + +@@ -752,13 +760,13 @@ public class PlayerConnection implements PacketListenerPlayIn { + // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async + // CraftBukkit start + if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { // Paper start - split and make configurable +- minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper ++ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause + return; + } + // Paper start + String str = packetplayintabcomplete.c(); int index = -1; + if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { +- minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper ++ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause + return; + } + // Paper end +@@ -906,7 +914,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + // Paper start - validate pick item position + if (!(packetplayinpickitem.b() >= 0 && packetplayinpickitem.b() < this.player.inventory.items.size())) { + PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getDisplayName().getString()); +- this.disconnect("Invalid hotbar selection (Hacking?)"); ++ this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause + return; + } + this.player.inventory.c(packetplayinpickitem.b()); // Paper - Diff above if changed +@@ -1060,7 +1068,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + NBTTagList pageList = testStack.getTag().getList("pages", 8); + if (pageList.size() > 100) { + PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with too many pages"); +- minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause + return; + } + long byteTotal = 0; +@@ -1072,7 +1080,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; + if (byteLength > 256 * 4) { + PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with with a page too large!"); +- minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause + return; + } + byteTotal += byteLength; +@@ -1095,14 +1103,14 @@ public class PlayerConnection implements PacketListenerPlayIn { + + if (byteTotal > byteAllowed) { + PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); +- minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause + return; + } + } + // Paper end + // CraftBukkit start + if (this.lastBookTick + 20 > MinecraftServer.currentTick) { +- this.disconnect("Book edited too quickly!"); ++ this.disconnect("Book edited too quickly!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause + return; + } + this.lastBookTick = MinecraftServer.currentTick; +@@ -1214,7 +1222,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + public void a(PacketPlayInFlying packetplayinflying) { + PlayerConnectionUtils.ensureMainThread(packetplayinflying, this, this.player.getWorldServer()); + if (b(packetplayinflying)) { +- this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_player_movement")); ++ this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause + } else { + WorldServer worldserver = this.player.getWorldServer(); + +@@ -1613,7 +1621,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + this.dropCount++; + if (this.dropCount >= 20) { + LOGGER.warn(this.player.getName() + " dropped their items too quickly!"); +- this.disconnect("You dropped your items too quickly (Hacking?)"); ++ this.disconnect("You dropped your items too quickly (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause + return; + } + } +@@ -1926,7 +1934,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + this.player.resetIdleTimer(); + } else { + PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getDisplayName().getString()); +- this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit ++ this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // CraftBukkit // Paper - kick event cause + } + } + +@@ -1963,7 +1971,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + Waitable waitable = new Waitable() { + @Override + protected Object evaluate() { +- PlayerConnection.this.disconnect(new ChatMessage("multiplayer.disconnect.illegal_characters")); ++ PlayerConnection.this.disconnect(new ChatMessage("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause + return null; + } + }; +@@ -1978,7 +1986,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + throw new RuntimeException(e); + } + } else { +- this.disconnect(new ChatMessage("multiplayer.disconnect.illegal_characters")); ++ this.disconnect(new ChatMessage("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause + } + // CraftBukkit end + return; +@@ -2032,7 +2040,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + Waitable waitable = new Waitable() { + @Override + protected Object evaluate() { +- PlayerConnection.this.disconnect(new ChatMessage("disconnect.spam")); ++ PlayerConnection.this.disconnect(new ChatMessage("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause + return null; + } + }; +@@ -2047,7 +2055,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + throw new RuntimeException(e); + } + } else { +- this.disconnect(new ChatMessage("disconnect.spam")); ++ this.disconnect(new ChatMessage("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause + } + // CraftBukkit end + } +@@ -2320,7 +2328,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + // Spigot Start + if ( entity == player && !player.isSpectator() ) + { +- disconnect( "Cannot interact with self!" ); ++ disconnect( "Cannot interact with self!", org.bukkit.event.player.PlayerKickEvent.Cause.SELF_INTERACTION ); // Paper - kick event cause + return; + } + // Spigot End +@@ -2397,7 +2405,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + // CraftBukkit end + } else if (packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { + if (entity instanceof EntityItem || entity instanceof EntityExperienceOrb || entity instanceof EntityArrow || (entity == this.player && !player.isSpectator())) { // CraftBukkit +- this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_entity_attacked")); ++ this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_entity_attacked"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_ENTITY_ATTACKED); // Paper - kick event cause + PlayerConnection.LOGGER.warn("Player {} tried to attack an invalid entity", this.player.getDisplayName().getString()); + return; + } +@@ -2802,7 +2810,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + // Paper start + if (!Bukkit.isPrimaryThread()) { + if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { +- minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper ++ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause + return; + } + } +@@ -3001,7 +3009,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + } else if (!this.isExemptPlayer()) { + // Paper start - This needs to be handled on the main thread for plugins + minecraftServer.scheduleOnMain(() -> { +- this.disconnect(new ChatMessage("disconnect.timeout")); ++ this.disconnect(new ChatMessage("disconnect.timeout"), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause + }); + // Paper end + } +@@ -3047,7 +3055,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + } catch (Exception ex) { + PlayerConnection.LOGGER.error("Couldn\'t register custom payload", ex); +- this.disconnect("Invalid payload REGISTER!"); ++ this.disconnect("Invalid payload REGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause + } + } else if (packetplayincustompayload.tag.equals(CUSTOM_UNREGISTER)) { + try { +@@ -3057,7 +3065,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + } catch (Exception ex) { + PlayerConnection.LOGGER.error("Couldn\'t unregister custom payload", ex); +- this.disconnect("Invalid payload UNREGISTER!"); ++ this.disconnect("Invalid payload UNREGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause + } + } else { + try { +@@ -3076,7 +3084,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + server.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packetplayincustompayload.tag.toString(), data); + } catch (Exception ex) { + PlayerConnection.LOGGER.error("Couldn\'t dispatch custom payload", ex); +- this.disconnect("Invalid custom payload!"); ++ this.disconnect("Invalid custom payload!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause + } + } + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 2a76c3624c64e93509a96579f48c507e29901625..90776231b1faffb11e4394f555f336ca248e3004 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -720,7 +720,7 @@ public abstract class PlayerList { + while (iterator.hasNext()) { + entityplayer = (EntityPlayer) iterator.next(); + savePlayerFile(entityplayer); // CraftBukkit - Force the player's inventory to be saved +- entityplayer.playerConnection.disconnect(new ChatMessage("multiplayer.disconnect.duplicate_login", new Object[0])); ++ entityplayer.playerConnection.disconnect(new ChatMessage("multiplayer.disconnect.duplicate_login", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause + } + + // Instead of kicking then returning, we need to store the kick reason +@@ -1389,8 +1389,8 @@ public abstract class PlayerList { + public void shutdown(boolean isRestarting) { + // CraftBukkit start - disconnect safely + for (EntityPlayer player : this.players) { +- if (isRestarting) player.playerConnection.disconnect(org.spigotmc.SpigotConfig.restartMessage); else // Paper +- player.playerConnection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure ++ if (isRestarting) player.playerConnection.disconnect(org.spigotmc.SpigotConfig.restartMessage, org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); else // Paper - kick event cause (cause is never used here) ++ player.playerConnection.disconnect(this.server.server.shutdownMessage(), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); // CraftBukkit - add custom shutdown message // Paper - Adventure & KickEventCause (cause is never used here) + } + // CraftBukkit end + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 34395248e3daea47178cb40aad53680fbce73600..cfe6898dc373fe55a08acf5c90e200061aa7d0fc 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -499,16 +499,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + org.spigotmc.AsyncCatcher.catchOp("player kick"); // Spigot + if (getHandle().playerConnection == null) return; + +- getHandle().playerConnection.disconnect(message == null ? "" : message); ++ getHandle().playerConnection.disconnect(message == null ? "" : message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause + } + + // Paper start + @Override + public void kick(final net.kyori.adventure.text.Component message) { ++ kick(message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); ++ } ++ ++ @Override ++ public void kick(net.kyori.adventure.text.Component message, org.bukkit.event.player.PlayerKickEvent.Cause cause) { + org.spigotmc.AsyncCatcher.catchOp("player kick"); + final PlayerConnection connection = this.getHandle().playerConnection; + if (connection != null) { +- connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); ++ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message, cause); + } + } + // Paper end +diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java +index 6a408dc9286a60c3ca7830f88171919fb0fe6363..dc8da0448193a5fbf16cfe3b070923cfb8a23c6d 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 ( EntityPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) + { +- p.playerConnection.disconnect(SpigotConfig.restartMessage); ++ p.playerConnection.disconnect(SpigotConfig.restartMessage, 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-unmapped/0747-Limit-item-frame-cursors-on-maps.patch b/patches/server-unmapped/0747-Limit-item-frame-cursors-on-maps.patch new file mode 100644 index 0000000000..93cb1e1686 --- /dev/null +++ b/patches/server-unmapped/0747-Limit-item-frame-cursors-on-maps.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Yive +Date: Wed, 26 May 2021 15:09:33 -0700 +Subject: [PATCH] Limit item frame cursors on maps + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 0dd0795af0d0deeff5637a2a1a4a165dec26af15..467f4bd13c58f6724cdda580b95a0d58f516ec12 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -817,4 +817,9 @@ public class PaperWorldConfig { + private void allowUsingSignsInsideSpawnProtection() { + allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); + } ++ ++ public int mapItemFrameCursorLimit = 128; ++ private void mapItemFrameCursorLimit() { ++ mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java +index 1f9b710f2af3c5067b3c2b73bebb11f8e22c403e..97fe61dcd066ec0ee05e81fc22409d6aa6b3a6d5 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java +@@ -279,8 +279,12 @@ public class WorldMap extends PersistentBase { + + WorldMapFrame worldmapframe1 = new WorldMapFrame(blockposition, entityitemframe.getDirection().get2DRotationValue() * 90, entityitemframe.getId()); + ++ // Paper start ++ if (this.decorations.size() < entityhuman.world.paperConfig.mapItemFrameCursorLimit) { + this.a(MapIcon.Type.FRAME, entityhuman.world, "frame-" + entityitemframe.getId(), (double) blockposition.getX(), (double) blockposition.getZ(), (double) (entityitemframe.getDirection().get2DRotationValue() * 90), (IChatBaseComponent) null); + this.n.put(worldmapframe1.e(), worldmapframe1); ++ } ++ // Paper end + } + + NBTTagCompound nbttagcompound = itemstack.getTag(); diff --git a/patches/server-unmapped/0748-Add-PufferFishStateChangeEvent.patch b/patches/server-unmapped/0748-Add-PufferFishStateChangeEvent.patch new file mode 100644 index 0000000000..df5245c824 --- /dev/null +++ b/patches/server-unmapped/0748-Add-PufferFishStateChangeEvent.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Mon, 10 May 2021 16:59:05 +0100 +Subject: [PATCH] Add PufferFishStateChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java +index e9f20d387ccdacfbb1a48dc31e2a6cd4843a0d7b..4e4327b3cb84367534c6f5855cf8b89763b1419d 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java +@@ -89,25 +89,39 @@ public class EntityPufferFish extends EntityFish { + public void tick() { + if (!this.world.isClientSide && this.isAlive() && this.doAITick()) { + if (this.c > 0) { ++ boolean increase = true; // Paper - Add PufferFishStateChangeEvent + if (this.getPuffState() == 0) { ++ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent + this.playSound(SoundEffects.ENTITY_PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.dH()); + this.setPuffState(1); ++ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent + } else if (this.c > 40 && this.getPuffState() == 1) { ++ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 2).callEvent()) { // Paper - Add PufferFishStateChangeEvent + this.playSound(SoundEffects.ENTITY_PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.dH()); + this.setPuffState(2); ++ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent + } + ++ if (increase) { // Paper - Add PufferFishStateChangeEvent + ++this.c; ++ } // Paper - Add PufferFishStateChangeEvent + } else if (this.getPuffState() != 0) { ++ boolean increase = true; // Paper - Add PufferFishStateChangeEvent + if (this.d > 60 && this.getPuffState() == 2) { ++ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent + this.playSound(SoundEffects.ENTITY_PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.dH()); + this.setPuffState(1); ++ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent + } else if (this.d > 100 && this.getPuffState() == 1) { ++ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 0).callEvent()) { // Paper - Add PufferFishStateChangeEvent + this.playSound(SoundEffects.ENTITY_PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.dH()); + this.setPuffState(0); ++ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent + } + ++ if (increase) { // Paper - Add PufferFishStateChangeEvent + ++this.d; ++ } // Paper - Add PufferFishStateChangeEvent + } + } + diff --git a/patches/server-unmapped/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/patches/server-unmapped/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch new file mode 100644 index 0000000000..841559fd82 --- /dev/null +++ b/patches/server-unmapped/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 20 May 2021 22:16:37 -0700 +Subject: [PATCH] Fix PlayerBucketEmptyEvent result itemstack + +Fixes SPIGOT-2560: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-2560 + +diff --git a/src/main/java/net/minecraft/world/item/ItemBucket.java b/src/main/java/net/minecraft/world/item/ItemBucket.java +index d126f668828e0788e369294c0b376ef52b344f2c..f97447d77890cd65b5613899c389483bcf82be01 100644 +--- a/src/main/java/net/minecraft/world/item/ItemBucket.java ++++ b/src/main/java/net/minecraft/world/item/ItemBucket.java +@@ -118,6 +118,13 @@ public class ItemBucket extends Item { + } + + protected ItemStack a(ItemStack itemstack, EntityHuman entityhuman) { ++ // Paper ++ if (itemLeftInHandAfterPlayerBucketEmptyEvent != null) { ++ ItemStack itemInHand = itemLeftInHandAfterPlayerBucketEmptyEvent; ++ itemLeftInHandAfterPlayerBucketEmptyEvent = null; ++ return itemInHand; ++ } ++ // Paper + return !entityhuman.abilities.canInstantlyBuild ? new ItemStack(Items.BUCKET) : itemstack; + } + +@@ -128,6 +135,7 @@ public class ItemBucket extends Item { + return a(entityhuman, world, blockposition, movingobjectpositionblock, null, null, null, null); + } + ++ private ItemStack itemLeftInHandAfterPlayerBucketEmptyEvent = null; // Paper + public boolean a(EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock, EnumDirection enumdirection, BlockPosition clicked, ItemStack itemstack, EnumHand enumhand) { + // Paper end + // CraftBukkit end +@@ -148,6 +156,9 @@ public class ItemBucket extends Item { + ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 + return false; + } ++ // Paper start ++ itemLeftInHandAfterPlayerBucketEmptyEvent = event.getItemStack().equals(CraftItemStack.asNewCraftStack(net.minecraft.world.item.Items.BUCKET)) ? null : CraftItemStack.asNMSCopy(event.getItemStack()); ++ // Paper end + } + // CraftBukkit end + if (!flag1) { diff --git a/patches/server-unmapped/0750-Add-option-to-fix-items-merging-through-walls.patch b/patches/server-unmapped/0750-Add-option-to-fix-items-merging-through-walls.patch new file mode 100644 index 0000000000..a407870cd4 --- /dev/null +++ b/patches/server-unmapped/0750-Add-option-to-fix-items-merging-through-walls.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: GioSDA +Date: Wed, 10 Mar 2021 10:06:45 -0800 +Subject: [PATCH] Add option to fix items merging through walls + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 467f4bd13c58f6724cdda580b95a0d58f516ec12..25db335f457eefd13798394ebfb6b6684be26610 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -822,4 +822,9 @@ public class PaperWorldConfig { + private void mapItemFrameCursorLimit() { + mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); + } ++ ++ public boolean fixItemsMergingThroughWalls; ++ private void fixItemsMergingThroughWalls() { ++ fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index 575833807ff647f30d7c2b7abcd01701c7dec85b..8b79220c27292f9b92d9884bbbe4b16d7762343c 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -228,6 +228,14 @@ public class EntityItem extends Entity { + EntityItem entityitem = (EntityItem) iterator.next(); + + if (entityitem.z()) { ++ // Paper Start - Fix items merging through walls ++ if (this.world.paperConfig.fixItemsMergingThroughWalls) { ++ net.minecraft.world.level.RayTrace rayTrace = new net.minecraft.world.level.RayTrace(this.getPositionVector(), entityitem.getPositionVector(), ++ net.minecraft.world.level.RayTrace.BlockCollisionOption.COLLIDER, net.minecraft.world.level.RayTrace.FluidCollisionOption.NONE, this); ++ net.minecraft.world.phys.MovingObjectPositionBlock rayTraceResult = world.rayTrace(rayTrace); ++ if (rayTraceResult.getType() == net.minecraft.world.phys.MovingObjectPosition.EnumMovingObjectType.BLOCK) continue; ++ } ++ // Paper End + this.a(entityitem); + if (this.dead) { + break; diff --git a/patches/server-unmapped/0751-Add-BellRevealRaiderEvent.patch b/patches/server-unmapped/0751-Add-BellRevealRaiderEvent.patch new file mode 100644 index 0000000000..a19790a857 --- /dev/null +++ b/patches/server-unmapped/0751-Add-BellRevealRaiderEvent.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Wed, 26 May 2021 17:09:07 -0400 +Subject: [PATCH] Add BellRevealRaiderEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java +index 84f9f52c5b632621b509448ac1c760f64de6b062..83626417aa9a00096680851a9a14f52f84fc7887 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java +@@ -6,6 +6,7 @@ import net.minecraft.core.BlockPosition; + import net.minecraft.core.EnumDirection; + import net.minecraft.core.IPosition; + import net.minecraft.core.particles.Particles; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundCategory; + import net.minecraft.sounds.SoundEffects; + import net.minecraft.tags.Tag; +@@ -181,6 +182,7 @@ public class TileEntityBell extends TileEntity implements ITickable { + } + + private void b(EntityLiving entityliving) { ++ if (!new io.papermc.paper.event.block.BellRevealRaiderEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, position)), entityliving.getBukkitEntity()).callEvent()) return; // Paper - BellRevealRaiderEvent + entityliving.addEffect(new MobEffect(MobEffects.GLOWING, 60)); + } + } diff --git a/patches/server-unmapped/0752-Fix-invulnerable-end-crystals.patch b/patches/server-unmapped/0752-Fix-invulnerable-end-crystals.patch new file mode 100644 index 0000000000..35b32af72a --- /dev/null +++ b/patches/server-unmapped/0752-Fix-invulnerable-end-crystals.patch @@ -0,0 +1,88 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Max Lee +Date: Thu, 27 May 2021 14:52:30 -0700 +Subject: [PATCH] Fix invulnerable end crystals + +MC-108513 + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 25db335f457eefd13798394ebfb6b6684be26610..5c91c007691efeea1d4383efcd1ca06990d0660c 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -827,4 +827,9 @@ public class PaperWorldConfig { + private void fixItemsMergingThroughWalls() { + fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); + } ++ ++ public boolean fixInvulnerableEndCrystalExploit = true; ++ private void fixInvulnerableEndCrystalExploit() { ++ fixInvulnerableEndCrystalExploit = getBoolean("unsupported-settings.fix-invulnerable-end-crystal-exploit", fixInvulnerableEndCrystalExploit); ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java +index 9658d93615a51375204481cfe0a1fce6f105fd70..5d48c2640f776c9e29598e19afe779ed6997acfc 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java +@@ -30,6 +30,7 @@ public class EntityEnderCrystal extends Entity { + private static final DataWatcherObject> c = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.m); + private static final DataWatcherObject d = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.i); + public int b; ++ public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals + + public EntityEnderCrystal(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -66,6 +67,17 @@ public class EntityEnderCrystal extends Entity { + } + // CraftBukkit end + } ++ // Paper start - Fix invulnerable end crystals ++ if (this.world.paperConfig.fixInvulnerableEndCrystalExploit && this.generatedByDragonFight && this.isInvulnerable()) { ++ if ((this.origin.getWorld() != null && !((WorldServer) this.world).uuid.equals(this.origin.getWorld().getUID())) ++ || ((WorldServer) this.world).getDragonBattle() == null ++ || ((WorldServer) this.world).getDragonBattle().respawnPhase == null ++ || ((WorldServer) this.world).getDragonBattle().respawnPhase.ordinal() > net.minecraft.world.level.dimension.end.EnumDragonRespawn.SUMMONING_DRAGON.ordinal()) { ++ this.setInvulnerable(false); ++ this.setBeamTarget(null); ++ } ++ } ++ // Paper end + } + + } +@@ -77,6 +89,7 @@ public class EntityEnderCrystal extends Entity { + } + + nbttagcompound.setBoolean("ShowBottom", this.isShowingBottom()); ++ if (this.generatedByDragonFight) nbttagcompound.setBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals + } + + @Override +@@ -88,6 +101,7 @@ public class EntityEnderCrystal extends Entity { + if (nbttagcompound.hasKeyOfType("ShowBottom", 1)) { + this.setShowingBottom(nbttagcompound.getBoolean("ShowBottom")); + } ++ if (nbttagcompound.hasKeyOfType("Paper.GeneratedByDragonFight", 1)) this.generatedByDragonFight = nbttagcompound.getBoolean("Paper.GeneratedByDragonFight"); // Paper - Fix invulnerable end crystals + + } + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEnder.java b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEnder.java +index dd623702131eaa1a65937a19a0e986e865322258..1bf09c99ba318813755ea3d3456d0fbb60847e5c 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEnder.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEnder.java +@@ -42,7 +42,7 @@ public class WorldGenEnder extends WorldGenerator list = worldgenfeatureendspikeconfiguration.c(); + + if (list.isEmpty()) { +@@ -106,6 +106,7 @@ public class WorldGenEnder extends WorldGenerator +Date: Fri, 19 Mar 2021 23:39:09 -0400 +Subject: [PATCH] Add ElderGuardianAppearanceEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java +index 9bd6f5d988c1e50e1bb729c407178b9cbcc62115..300efeb98bb68b24faa68a4af9d703bf2b8c405c 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java +@@ -77,10 +77,12 @@ public class EntityGuardianElder extends EntityGuardian { + while (iterator.hasNext()) { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); + ++ if (new io.papermc.paper.event.entity.ElderGuardianAppearanceEvent(getBukkitEntity(), entityplayer.getBukkitEntity()).callEvent()) { // Paper - Add Guardian Appearance Event + if (!entityplayer.hasEffect(mobeffectlist) || entityplayer.getEffect(mobeffectlist).getAmplifier() < 2 || entityplayer.getEffect(mobeffectlist).getDuration() < 1200) { + entityplayer.playerConnection.sendPacket(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.k, this.isSilent() ? 0.0F : 1.0F)); + entityplayer.addEffect(new MobEffect(mobeffectlist, 6000, 2), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } ++ } // Paper - Add Guardian Appearance Event + } + } + diff --git a/patches/server-unmapped/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch b/patches/server-unmapped/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch new file mode 100644 index 0000000000..4839fe3bfb --- /dev/null +++ b/patches/server-unmapped/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 1 Jun 2021 22:05:08 -0500 +Subject: [PATCH] Reset villager inventory on cancelled pickup event + + +diff --git a/src/main/java/net/minecraft/world/InventorySubcontainer.java b/src/main/java/net/minecraft/world/InventorySubcontainer.java +index 12dad3fe0eee8b0cd8959df6dba449d90bc95844..b8aca5f1c950c8ab28c432d93a6cec5d32e48b9e 100644 +--- a/src/main/java/net/minecraft/world/InventorySubcontainer.java ++++ b/src/main/java/net/minecraft/world/InventorySubcontainer.java +@@ -34,6 +34,16 @@ public class InventorySubcontainer implements IInventory, AutoRecipeOutput { + return this.items; + } + ++ // Paper start ++ public void setContents(List items) { ++ this.items.clear(); ++ for(int i = 0; i < items.size(); i++) { ++ this.items.set(i, items.get(i)); ++ } ++ this.update(); ++ } ++ // Paper end ++ + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } +@@ -148,6 +158,7 @@ public class InventorySubcontainer implements IInventory, AutoRecipeOutput { + return itemstack; + } + ++ public ItemStack addItem(ItemStack itemstack) { return a(itemstack); } // Paper - OBFHELPER + public ItemStack a(ItemStack itemstack) { + ItemStack itemstack1 = itemstack.cloneItemStack(); + +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index c29f05b6fd0664345d8d09f898777a3e44f866c4..85374ac8f5460790de03b47d7c3ce19ed5596afe 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -845,15 +845,19 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + } + + // CraftBukkit start +- ItemStack remaining = new InventorySubcontainer(inventorysubcontainer).a(itemstack); +- if (CraftEventFactory.callEntityPickupItemEvent(this, entityitem, remaining.getCount(), false).isCancelled()) { ++ // Paper start ++ List contentsSnapshot = new java.util.ArrayList<>(inventorysubcontainer.getContents()); ++ ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); ++ if (CraftEventFactory.callEntityPickupItemEvent(this, entityitem, itemstack1.getCount(), false).isCancelled()) { ++ inventorysubcontainer.setContents(contentsSnapshot); ++ // Paper end + return; + } + // CraftBukkit end + + this.a(entityitem); + this.receive(entityitem, itemstack.getCount()); +- ItemStack itemstack1 = inventorysubcontainer.a(itemstack); ++ // ItemStack itemstack1 = inventorysubcontainer.a(itemstack); // Paper - moved up + + if (itemstack1.isEmpty()) { + entityitem.die(); diff --git a/patches/server-unmapped/0755-Fix-dangerous-end-portal-logic.patch b/patches/server-unmapped/0755-Fix-dangerous-end-portal-logic.patch new file mode 100644 index 0000000000..211ffbfc31 --- /dev/null +++ b/patches/server-unmapped/0755-Fix-dangerous-end-portal-logic.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 4 Jun 2021 17:06:52 -0400 +Subject: [PATCH] Fix dangerous end portal logic + +End portals could teleport entities during move calls. Stupid +logic given the caller will never expect that kind of thing, +and will result in all kinds of dupes. + +Move the tick logic into the post tick, where portaling was +designed to happen in the first place. + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 558af73ac16550ee6964c4dce681a404633b2552..75bcfb3a2b4a104aeebb2fe3298714b2e5b569d2 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -1023,6 +1023,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + return b(worldserver, TeleportCause.UNKNOWN); + } + ++ @Nullable public final Entity changeDimension(WorldServer worldserver, PlayerTeleportEvent.TeleportCause cause) { return this.b(worldserver, cause); } // Paper - OBFHELPER + @Nullable + public Entity b(WorldServer worldserver, PlayerTeleportEvent.TeleportCause cause) { + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 89b2be0e9e42d65b7d2d2833de4e6cd1c6e17e8e..6e1304f7169c11f67c573b2c8dc11825bcc7da0d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -314,6 +314,37 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + // Paper end - optimise entity tracking + ++ // Paper start - make end portalling safe ++ public BlockPosition portalBlock; ++ public WorldServer portalWorld; ++ public void tickEndPortal() { ++ BlockPosition pos = this.portalBlock; ++ WorldServer world = this.portalWorld; ++ this.portalBlock = null; ++ this.portalWorld = null; ++ ++ if (pos == null || world == null || world != this.world) { ++ return; ++ } ++ ++ if (this.isPassenger() || this.isVehicle() || !this.canPortal() || this.dead || !this.valid || !this.isAlive()) { ++ return; ++ } ++ ++ ResourceKey resourcekey = world.getTypeKey() == DimensionManager.THE_END ? World.OVERWORLD : World.THE_END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends ++ WorldServer worldserver = world.getMinecraftServer().getWorldServer(resourcekey); ++ ++ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(this.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); ++ event.callEvent(); ++ ++ if (this instanceof EntityPlayer) { ++ ((EntityPlayer)this).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); ++ return; ++ } ++ this.teleportTo(worldserver, null); ++ } ++ // Paper end - make end portalling safe ++ + public Entity(EntityTypes entitytypes, World world) { + this.id = Entity.entityCount.incrementAndGet(); + this.passengers = Lists.newArrayList(); +@@ -2299,6 +2330,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + this.E(); ++ this.tickEndPortal(); // Paper - make end portalling safe + } + } + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java +index ed916f69747b44b75eb06db4cf27adaf5e47fd1e..9483d75fbe2a8c8f7cce00355e93ff1f943f3444 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java +@@ -52,16 +52,10 @@ public class BlockEnderPortal extends BlockTileEntity { + // return; // CraftBukkit - always fire event in case plugins wish to change it + } + +- // CraftBukkit start - Entity in portal +- EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ())); +- world.getServer().getPluginManager().callEvent(event); +- +- if (entity instanceof EntityPlayer) { +- ((EntityPlayer) entity).b(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); +- return; +- } +- // CraftBukkit end +- entity.b(worldserver); ++ // Paper start - move all of this logic into portal tick ++ entity.portalWorld = ((WorldServer)world); ++ entity.portalBlock = blockposition.immutableCopy(); ++ // Paper end - move all of this logic into portal tick + } + + } diff --git a/patches/server-unmapped/0756-Make-item-validations-configurable.patch b/patches/server-unmapped/0756-Make-item-validations-configurable.patch new file mode 100644 index 0000000000..de1cd74d97 --- /dev/null +++ b/patches/server-unmapped/0756-Make-item-validations-configurable.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 4 Jun 2021 12:12:35 -0700 +Subject: [PATCH] Make item validations configurable + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index efc1e42d606e1c9feb1a4871c0714933ae92a1b2..7acf077bc131af718c7548cc29deef558c04e463 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -486,4 +486,19 @@ public class PaperConfig { + enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); + enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); + } ++ ++ public static int itemValidationDisplayNameLength = 8192; ++ public static int itemValidationLocNameLength = 8192; ++ public static int itemValidationLoreLineLength = 8192; ++ public static int itemValidationBookTitleLength = 8192; ++ public static int itemValidationBookAuthorLength = 8192; ++ public static int itemValidationBookPageLength = 16384; ++ private static void itemValidationSettings() { ++ itemValidationDisplayNameLength = getInt("settings.item-validation.display-name", itemValidationDisplayNameLength); ++ itemValidationLocNameLength = getInt("settings.item-validation.loc-name", itemValidationLocNameLength); ++ itemValidationLoreLineLength = getInt("settings.item-validation.lore-line", itemValidationLoreLineLength); ++ itemValidationBookTitleLength = getInt("settings.item-validation.book.title", itemValidationBookTitleLength); ++ itemValidationBookAuthorLength = getInt("settings.item-validation.book.author", itemValidationBookAuthorLength); ++ itemValidationBookPageLength = getInt("settings.item-validation.book.page", itemValidationBookPageLength); ++ } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +index 1a4c1763e883e445433b3780fe20db7f62b780e8..bf1b6fa34b32730b493c37d3a0aa69a904c2d2b6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +@@ -92,11 +92,11 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + super(tag); + + if (tag.hasKey(BOOK_TITLE.NBT)) { +- this.title = limit( tag.getString(BOOK_TITLE.NBT), 8192 ); // Spigot ++ this.title = limit( tag.getString(BOOK_TITLE.NBT), com.destroystokyo.paper.PaperConfig.itemValidationBookTitleLength); // Spigot // Paper - make configurable + } + + if (tag.hasKey(BOOK_AUTHOR.NBT)) { +- this.author = limit( tag.getString(BOOK_AUTHOR.NBT), 8192 ); // Spigot ++ this.author = limit( tag.getString(BOOK_AUTHOR.NBT), com.destroystokyo.paper.PaperConfig.itemValidationBookAuthorLength ); // Spigot // Paper - make configurable + } + + if (tag.hasKey(RESOLVED.NBT)) { +@@ -124,7 +124,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { + } else { + page = validatePage(page); + } +- this.pages.add( limit( page, 16384 ) ); // Spigot ++ this.pages.add( limit( page, com.destroystokyo.paper.PaperConfig.itemValidationBookPageLength ) ); // Spigot // Paper - make configurable + } + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index 5c1319a86f6314c1d0a979af34424ee025a8030f..3db4826139f3e1f3859c04bae72310bfe2c53c1d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -358,18 +358,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + NBTTagCompound display = tag.getCompound(DISPLAY.NBT); + + if (display.hasKey(NAME.NBT)) { +- displayName = limit( display.getString(NAME.NBT), 8192 ); // Spigot ++ displayName = limit( display.getString(NAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationDisplayNameLength); // Spigot // Paper - make configurable + } + + if (display.hasKey(LOCNAME.NBT)) { +- locName = limit( display.getString(LOCNAME.NBT), 8192 ); // Spigot ++ locName = limit( display.getString(LOCNAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationLocNameLength ); // Spigot // Paper - make configurable + } + + if (display.hasKey(LORE.NBT)) { + NBTTagList list = display.getList(LORE.NBT, CraftMagicNumbers.NBT.TAG_STRING); + lore = new ArrayList(list.size()); + for (int index = 0; index < list.size(); index++) { +- String line = limit( list.getString(index), 8192 ); // Spigot ++ String line = limit( list.getString(index), com.destroystokyo.paper.PaperConfig.itemValidationLoreLineLength ); // Spigot // Paper - make configurable + lore.add(line); + } + } diff --git a/patches/server-unmapped/0757-Add-more-line-of-sight-methods.patch b/patches/server-unmapped/0757-Add-more-line-of-sight-methods.patch new file mode 100644 index 0000000000..7398a6e72f --- /dev/null +++ b/patches/server-unmapped/0757-Add-more-line-of-sight-methods.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TwoLeggedCat <80929284+TwoLeggedCat@users.noreply.github.com> +Date: Sat, 29 May 2021 14:33:25 -0500 +Subject: [PATCH] Add more line of sight methods + + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 2657dd71213455e2da3a4ff4d338a33896ffe855..b7b07b652b29e6f84f87fc92add99ce68f8bbd09 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -3094,6 +3094,7 @@ public abstract class EntityLiving extends Entity { + Vec3D vec3d = new Vec3D(this.locX(), this.getHeadY(), this.locZ()); + Vec3D vec3d1 = new Vec3D(entity.locX(), entity.getHeadY(), entity.locZ()); + ++ // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists + return this.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, this)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 9d858f91828d6c2787ff1dc677a247bcab172701..02198dbe9e80c2990e8a09b2b763748dae727a03 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -333,6 +333,17 @@ public class CraftWorld implements World { + public io.papermc.paper.world.MoonPhase getMoonPhase() { + return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); + } ++ ++ @Override ++ public boolean lineOfSightExists(Location from, Location to) { ++ Validate.notNull(from, "from parameter in lineOfSightExists cannot be null"); ++ Validate.notNull(to, "to parameter in lineOfSightExists cannot be null"); ++ if (from.getWorld() != to.getWorld()) return false; ++ Vec3D vec3d = new Vec3D(from.getX(), from.getY(), from.getZ()); ++ Vec3D vec3d1 = new Vec3D(to.getX(), to.getY(), to.getZ()); ++ ++ return this.getHandle().rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, null)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS; ++ } + // Paper end + + private static final Random rand = new Random(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 32428b1260bbc4bae67ec74969c67f71272de418..592dacf8cc924caac339a8810ba5b0d85448ed90 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -561,6 +561,17 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return getHandle().hasLineOfSight(((CraftEntity) other).getHandle()); + } + ++ // Paper start ++ @Override ++ public boolean hasLineOfSight(Location loc) { ++ if (this.getHandle().world != ((CraftWorld) loc.getWorld()).getHandle()) return false; ++ Vec3D vec3d = new Vec3D(this.getHandle().locX(), this.getHandle().getHeadY(), this.getHandle().locZ()); ++ Vec3D vec3d1 = new Vec3D(loc.getX(), loc.getY(), loc.getZ()); ++ ++ return this.getHandle().world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, this.getHandle())).getType() == MovingObjectPosition.EnumMovingObjectType.MISS; ++ } ++ // Paper end ++ + @Override + public boolean getRemoveWhenFarAway() { + return getHandle() instanceof EntityInsentient && !((EntityInsentient) getHandle()).persistent; diff --git a/patches/server-unmapped/0758-add-per-world-spawn-limits.patch b/patches/server-unmapped/0758-add-per-world-spawn-limits.patch new file mode 100644 index 0000000000..0dcc7093e4 --- /dev/null +++ b/patches/server-unmapped/0758-add-per-world-spawn-limits.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chase +Date: Wed, 2 Dec 2020 22:43:39 -0800 +Subject: [PATCH] add per world spawn limits + +Taken from #2982. Credit to Chasewhip8 + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 5c91c007691efeea1d4383efcd1ca06990d0660c..fcacc08db8f5a58ddd06be7f9f2cb2cf6b2231c3 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -653,6 +653,19 @@ public class PaperWorldConfig { + zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); + } + ++ public int spawnLimitMonsters = -1; ++ public int spawnLimitAnimals = -1; ++ public int spawnLimitWaterAnimals = -1; ++ public int spawnLimitWaterAmbient = -1; ++ public int spawnLimitAmbient = -1; ++ private void perWorldSpawnLimits() { ++ spawnLimitMonsters = getInt("spawn-limits.monsters", spawnLimitMonsters); ++ spawnLimitAnimals = getInt("spawn-limits.animals", spawnLimitAnimals); ++ spawnLimitWaterAnimals = getInt("spawn-limits.water-animals", spawnLimitWaterAnimals); ++ spawnLimitWaterAmbient = getInt("spawn-limits.water-ambient", spawnLimitWaterAmbient); ++ spawnLimitAmbient = getInt("spawn-limits.ambient", spawnLimitAmbient); ++ } ++ + public int lightQueueSize = 20; + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 02198dbe9e80c2990e8a09b2b763748dae727a03..c0b49a0eaeda06b89a4fb425eec3d5bfa9717379 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -353,6 +353,13 @@ public class CraftWorld implements World { + this.generator = gen; + + environment = env; ++ // Paper start - per world spawn limits ++ this.monsterSpawn = this.world.paperConfig.spawnLimitMonsters; ++ this.animalSpawn = this.world.paperConfig.spawnLimitAnimals; ++ this.waterAnimalSpawn = this.world.paperConfig.spawnLimitWaterAnimals; ++ this.waterAmbientSpawn = this.world.paperConfig.spawnLimitWaterAmbient; ++ this.ambientSpawn = this.world.paperConfig.spawnLimitAmbient; ++ // Paper end + } + + @Override diff --git a/patches/server-unmapped/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch b/patches/server-unmapped/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch new file mode 100644 index 0000000000..a6d7f10ad8 --- /dev/null +++ b/patches/server-unmapped/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 20 May 2021 20:40:53 -0700 +Subject: [PATCH] Fix PotionSplashEvent for water splash potions + +Fixes SPIGOT-6221: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-6221 + +diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java +index 53ea8a6d90faf4f7f8fd0819be4499422bdd4cbe..e6bf78f46acc37d9515d58cec3587e236ac0733c 100644 +--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java ++++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java +@@ -99,6 +99,7 @@ public class DamageSource { + return (new EntityDamageSourceIndirect("thrown", entity, entity1)).c(); + } + ++ public static DamageSource indirectMagic(Entity target, Entity cause) { return c(target, cause); } // Paper - OBFHELPER + public static DamageSource c(Entity entity, @Nullable Entity entity1) { + return (new EntityDamageSourceIndirect("indirectMagic", entity, entity1)).setIgnoreArmor().setMagic(); + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java b/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java +index dbc0afc5fb9e358a3e6d596692f57fb28303c4da..9348288fb752e758fe7aee8c2a630ea0fb7b9a8c 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java +@@ -124,6 +124,7 @@ public class EntityPotion extends EntityProjectileThrowable { + private void splash() { + AxisAlignedBB axisalignedbb = this.getBoundingBox().grow(4.0D, 2.0D, 4.0D); + List list = this.world.a(EntityLiving.class, axisalignedbb, EntityPotion.b); ++ Map affected = new HashMap<>(); // Paper + + if (!list.isEmpty()) { + Iterator iterator = list.iterator(); +@@ -133,11 +134,22 @@ public class EntityPotion extends EntityProjectileThrowable { + double d0 = this.h(entityliving); + + if (d0 < 16.0D && entityliving.dO()) { +- entityliving.damageEntity(DamageSource.c(entityliving, this.getShooter()), 1.0F); ++ // Paper start ++ double intensity = 1.0D - Math.sqrt(d0) / 4.0D; ++ affected.put(entityliving.getBukkitLivingEntity(), intensity); ++ // entityliving.damageEntity(DamageSource.c(entityliving, this.getShooter()), 1.0F); // Paper - moved down + } + } + } + ++ org.bukkit.event.entity.PotionSplashEvent event = CraftEventFactory.callPotionSplashEvent(this, affected); ++ if (!event.isCancelled()) { ++ for (LivingEntity affectedEntity : event.getAffectedEntities()) { ++ EntityLiving entityliving = ((CraftLivingEntity) affectedEntity).getHandle(); ++ entityliving.damageEntity(DamageSource.indirectMagic(entityliving, this.getShooter()), 1.0F); ++ } ++ } ++ // Paper end + } + + private void a(List list, @Nullable Entity entity) { +@@ -155,6 +167,7 @@ public class EntityPotion extends EntityProjectileThrowable { + double d0 = this.h(entityliving); + + if (d0 < 16.0D) { ++ // Paper - diff on change, used when calling the splash event for water splash potions + double d1 = 1.0D - Math.sqrt(d0) / 4.0D; + + if (entityliving == entity) { diff --git a/patches/server/0001-Setup-Gradle-project.patch b/patches/server/0001-Setup-Gradle-project.patch new file mode 100644 index 0000000000..9e12bf0e6d --- /dev/null +++ b/patches/server/0001-Setup-Gradle-project.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Thu, 10 Dec 2020 20:54:19 -0800 +Subject: [PATCH] Setup Gradle project + + +diff --git a/.gitignore b/.gitignore +index 67fb370cad6924895a6b27052dbd5c1767e3f0c9..3e05459f27c4c5697ae65da504d67a6a2f617b57 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -1,3 +1,6 @@ ++.gradle/ ++build/ ++ + # Eclipse stuff + /.classpath + /.project +diff --git a/build.gradle.kts b/build.gradle.kts +new file mode 100644 +index 0000000000000000000000000000000000000000..fddf2f440356425d948f40dcf9d9853a374ddc8e +--- /dev/null ++++ b/build.gradle.kts +@@ -0,0 +1,72 @@ ++import com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer ++import java.time.Instant ++ ++plugins { ++ java ++ id("com.github.johnrengelman.shadow") ++} ++ ++val packageVersion = providers.gradleProperty("packageVersion").forUseAtConfigurationTime().get() ++ ++repositories { ++ maven("https://libraries.minecraft.net/") ++} ++ ++dependencies { ++ implementation(project(":Paper-API")) ++ implementation("jline:jline:2.12.1") ++ implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") { ++ exclude(group = "org.apache.logging.log4j", module = "log4j-api") ++ } ++ implementation("org.ow2.asm:asm:9.1") ++ implementation("com.googlecode.json-simple:json-simple:1.1.1") { ++ // This includes junit transitively for whatever reason ++ isTransitive = false ++ } ++ runtimeOnly("org.xerial:sqlite-jdbc:3.34.0") ++ runtimeOnly("mysql:mysql-connector-java:5.1.49") ++ ++ runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.1") ++ runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") ++ runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") ++ ++ testImplementation("junit:junit:4.13.1") ++ testImplementation("org.hamcrest:hamcrest-library:1.3") ++} ++ ++tasks.jar { ++ manifest { ++ attributes(mapOf( ++ "Main-Class" to "org.bukkit.craftbukkit.Main", ++ "Implementation-Title" to "CraftBukkit", ++ "Implementation-Vendor" to Instant.now().epochSecond, ++ "Specification-Title" to "Bukkit", ++ "Specification-Version" to project.version, ++ "Specification-Vendor" to "Bukkit Team" ++ )) ++ for (tld in listOf("net", "com", "org")) { ++ attributes(mapOf( ++ "Sealed" to "true" ++ ), "$tld/bukkit") ++ } ++ } ++} ++ ++tasks.shadowJar { ++ listOf( ++ "jline", "it.unimi", "org.apache.commons.codec", "org.apache.commons.io", ++ "org.apache.commons.lang3", "org.objectweb.asm" ++ ).forEach { pack -> ++ relocate(pack, "org.bukkit.craftbukkit.libs.$pack") ++ } ++ relocate("org.bukkit.craftbukkit", "org.bukkit.craftbukkit.v$packageVersion") { ++ exclude("org.bukkit.craftbukkit.Main*") ++ } ++ transform(AppendingTransformer::class.java) { ++ resource = "META-INF/services/java.sql.Driver" ++ } ++} ++ ++tasks.test { ++ exclude("org/bukkit/craftbukkit/inventory/ItemStack*Test.class") ++} diff --git a/patches/server/0002-Decompile-fixes.patch b/patches/server/0002-Decompile-fixes.patch new file mode 100644 index 0000000000..ce714be18b --- /dev/null +++ b/patches/server/0002-Decompile-fixes.patch @@ -0,0 +1,77 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Fri, 11 Jun 2021 05:25:03 -0500 +Subject: [PATCH] Decompile fixes + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 3aecce56bdac0a316742a55e340c522bea737321..6b4d84faba50d9f3f87e48251cf1294479d4a3a0 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1138,7 +1138,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +- entity1.moveTo(pos.x, pos.y, pos.z, entity1.getYRot(), entity1.getXRot()); +- return entity1; ++ Entity entity1 = EntityType.loadEntityRecursive(nbttagcompound1, worldserver, (loadedEntity) -> { // Paper - decomp fix ++ loadedEntity.moveTo(pos.x, pos.y, pos.z, loadedEntity.getYRot(), loadedEntity.getXRot()); // Paper - decomp fix ++ return loadedEntity; // Paper - decomp fix + }); + + if (entity1 == null) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java +index 88a8c2bc4aa30f478122a05fd119486a0107db82..5f00e3f4c86196db47bf1007973445d40866afdd 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java +@@ -169,8 +169,8 @@ public class BehaviorUtils { + + return optional.map((uuid) -> { + return ((ServerLevel) entity.level).getEntity(uuid); +- }).map((entity) -> { +- return entity instanceof LivingEntity ? (LivingEntity) entity : null; ++ }).map((entity2) -> { // Paper - decomp fix ++ return entity2 instanceof LivingEntity ? (LivingEntity) entity2 : null; // Paper - decomp fix + }); + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index c88dc823ca0c2f83bc10886208d498ea77523d68..dcfd0b107ac7bd1633f3b681cd5f5e26ce87bd63 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -522,7 +522,7 @@ public class Phantom extends FlyingMob implements Enemy { + List list = Phantom.this.level.getNearbyPlayers(this.attackTargeting, (LivingEntity) Phantom.this, Phantom.this.getBoundingBox().inflate(16.0D, 64.0D, 16.0D)); + + if (!list.isEmpty()) { +- list.sort(Comparator.comparing(Entity::getY).reversed()); ++ list.sort(Comparator.comparing(Entity::getY).reversed()); // Paper - decomp fix + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +index b4a5709b03e400d00504f33a9b34019d2b7bf115..2d79d4014770081fcd58a929e5fe0a26ac1b8023 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java ++++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +@@ -172,7 +172,7 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { + Map, Object2ObjectLinkedOpenHashMap>> map = Maps.newHashMap(); // CraftBukkit + + recipes.forEach((irecipe) -> { +- Map> map1 = (Map) map.computeIfAbsent(irecipe.getType(), (recipes) -> { ++ Map> map1 = (Map) map.computeIfAbsent(irecipe.getType(), (recipes_) -> { // Paper - decomp fix + return new Object2ObjectLinkedOpenHashMap<>(); // CraftBukkit + }); + Recipe irecipe1 = (Recipe) map1.put(irecipe.getId(), irecipe); From 1eedd5991a691374da044f5f86d6ac2d17faa16c Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 14:31:17 +0200 Subject: [PATCH 008/226] Remap POM changes patch Signed-off-by: Mariell Hoversholm --- build-data/library-imports.txt | 2 +- .../server-remapped/0001-POM-Changes.patch | 291 ------------------ patches/server/0003-POM-Changes.patch | 84 +++++ 3 files changed, 85 insertions(+), 292 deletions(-) delete mode 100644 patches/server-remapped/0001-POM-Changes.patch create mode 100644 patches/server/0003-POM-Changes.patch diff --git a/build-data/library-imports.txt b/build-data/library-imports.txt index 68b9b8022c..aa3c46be31 100644 --- a/build-data/library-imports.txt +++ b/build-data/library-imports.txt @@ -2,4 +2,4 @@ authlib com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java datafixerupper com/mojang/datafixers/DataFixerBuilder.java datafixerupper com/mojang/datafixers/util/Either.java datafixerupper com/mojang/serialization/codecs/KeyDispatchCodec.java -datafixerupper com/mojang/serialization Dynamic.java +datafixerupper com/mojang/serialization/Dynamic.java diff --git a/patches/server-remapped/0001-POM-Changes.patch b/patches/server-remapped/0001-POM-Changes.patch deleted file mode 100644 index 8d0da0d549..0000000000 --- a/patches/server-remapped/0001-POM-Changes.patch +++ /dev/null @@ -1,291 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 29 Feb 2016 20:40:33 -0600 -Subject: [PATCH] POM Changes - - -diff --git a/pom.xml b/pom.xml -index 3fc047371e8f8a626e69697fad549d689c5dce89..a5d87d22cb1588d15e08da3b37e51c5e261c7799 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -1,15 +1,14 @@ - - 4.0.0 -- org.spigotmc -- spigot -+ paper - jar - 1.16.5-R0.1-SNAPSHOT -- Spigot -- https://www.spigotmc.org/ -+ Paper -+ https://papermc.io - - -- true -+ - UTF-8 - unknown - git -@@ -20,21 +19,39 @@ - - - -- org.spigotmc -- spigot-parent -+ com.destroystokyo.paper -+ paper-parent - dev-SNAPSHOT - ../pom.xml - - -+ -+ -+ -+ org.apache.logging.log4j -+ log4j-bom -+ 2.11.2 -+ pom -+ import -+ -+ -+ -+ - - -- org.spigotmc -- spigot-api -+ com.destroystokyo.paper -+ paper-api -+ ${project.version} -+ compile -+ -+ -+ com.destroystokyo.paper -+ paper-mojangapi - ${project.version} - compile - - -- org.spigotmc -+ io.papermc - minecraft-server - ${minecraft.version}-SNAPSHOT - compile -@@ -45,18 +62,15 @@ - 2.12.1 - compile - -+ -+ org.apache.logging.log4j -+ log4j-api -+ compile -+ - - org.apache.logging.log4j - log4j-iostreams -- 2.8.1 - compile -- -- -- -- org.apache.logging.log4j -- log4j-api -- -- - - - org.ow2.asm -@@ -64,12 +78,23 @@ - 9.1 - compile - -+ -+ -+ co.aikar -+ cleaner -+ 1.0-SNAPSHOT -+ -+ -+ io.netty -+ netty-all -+ 4.1.50.Final -+ - - - com.googlecode.json-simple - json-simple - 1.1.1 -- runtime -+ compile - - - org.xerial -@@ -80,7 +105,7 @@ - - mysql - mysql-connector-java -- 5.1.49 -+ 8.0.23 - runtime - - -@@ -105,7 +130,7 @@ - - org.apache.logging.log4j - log4j-slf4j-impl -- 2.8.1 -+ - runtime - - -@@ -132,34 +157,22 @@ - - - -+ paper-${minecraft.version} -+ clean install - - -- net.md-5 -- scriptus -- 0.4.1 -+ com.lukegb.mojo -+ gitdescribe-maven-plugin -+ 1.3 -+ -+ git-Paper- -+ .. -+ - - -- ex-spigot -- -- ${bt.name}-Spigot-%s -- ../ -- spigot.desc -- -- initialize -- -- describe -- -- -- -- ex-craftbukkit -- -- -%s -- ../../CraftBukkit -- craftbukkit.desc -- -- initialize -+ compile - -- describe -+ gitdescribe - - - -@@ -169,6 +182,7 @@ - maven-jar-plugin - 3.2.0 - -+ true - - - false -@@ -176,11 +190,13 @@ - - org.bukkit.craftbukkit.Main - CraftBukkit -- ${spigot.desc}${craftbukkit.desc} -- ${project.build.outputTimestamp} -+ -+ ${describe} -+ ${maven.build.timestamp} - Bukkit - ${api.version} - Bukkit Team -+ true - - - -@@ -216,14 +232,24 @@ - shade - - -+ ${project.build.directory}/dependency-reduced-pom.xml - ${shadeSourcesJar} - - -- org.spigotmc:minecraft-server -+ io.papermc:minecraft-server - - com/google/common/** - com/google/gson/** - com/google/thirdparty/** -+ -+ io/netty/** -+ META-INF/native/libnetty* -+ com/mojang/brigadier/** -+ META-INF/MANIFEST.MF -+ com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.class -+ com/mojang/datafixers/util/Either* -+ org/apache/logging/log4j/** -+ META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat - - - -@@ -245,10 +271,11 @@ - jline - org.bukkit.craftbukkit.libs.jline - -- -- it.unimi -- org.bukkit.craftbukkit.libs.it.unimi -- -+ -+ -+ -+ -+ - - org.apache.commons.codec - org.bukkit.craftbukkit.libs.org.apache.commons.codec -@@ -316,10 +343,6 @@ - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 -- -- -- eclipse -- - - - org.codehaus.plexus -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 4452427d0a8298d119ca29ef397b7a94f19eec28..46a16e31775b28c44f95a8ac5545ebcb656c74b6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -186,7 +186,7 @@ public class Main { - } - - if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { -- Date buildDate = new Date(Integer.parseInt(Main.class.getPackage().getImplementationVendor()) * 1000L); -+ Date buildDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(Main.class.getPackage().getImplementationVendor()); // Paper - - Calendar deadline = Calendar.getInstance(); - deadline.add(Calendar.DAY_OF_YEAR, -28); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 93046379d0cefd5d3236fc59e698809acdc18f80..674096cab190d62622f9947853b056f57d43a2a5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -@@ -11,7 +11,7 @@ public final class Versioning { - public static String getBukkitVersion() { - String result = "Unknown-Version"; - -- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties"); -+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.destroystokyo.paper/paper-api/pom.properties"); - Properties properties = new Properties(); - - if (stream != null) { diff --git a/patches/server/0003-POM-Changes.patch b/patches/server/0003-POM-Changes.patch new file mode 100644 index 0000000000..5639cd97f9 --- /dev/null +++ b/patches/server/0003-POM-Changes.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 29 Feb 2016 20:40:33 -0600 +Subject: [PATCH] POM Changes + + +diff --git a/build.gradle.kts b/build.gradle.kts +index fddf2f440356425d948f40dcf9d9853a374ddc8e..332930391943da8b1601401f70e13f076b205e7c 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -15,21 +15,24 @@ repositories { + dependencies { + implementation(project(":Paper-API")) + implementation("jline:jline:2.12.1") +- implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") { +- exclude(group = "org.apache.logging.log4j", module = "log4j-api") +- } ++ implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper ++ implementation("org.apache.logging.log4j:log4j-api:2.14.1") // Paper ++ implementation("org.apache.logging.log4j:log4j-slf4j-impl:2.14.1") // Paper + implementation("org.ow2.asm:asm:9.1") + implementation("com.googlecode.json-simple:json-simple:1.1.1") { + // This includes junit transitively for whatever reason + isTransitive = false + } + runtimeOnly("org.xerial:sqlite-jdbc:3.34.0") +- runtimeOnly("mysql:mysql-connector-java:5.1.49") ++ runtimeOnly("mysql:mysql-connector-java:8.0.23") // Paper + + runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.1") + runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") + runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") + ++ implementation("co.aikar:cleaner:1.0-SNAPSHOT") // Paper ++ implementation("io.netty:netty-all:4.1.50-Final") // Paper ++ + testImplementation("junit:junit:4.13.1") + testImplementation("org.hamcrest:hamcrest-library:1.3") + } +@@ -42,7 +45,8 @@ tasks.jar { + "Implementation-Vendor" to Instant.now().epochSecond, + "Specification-Title" to "Bukkit", + "Specification-Version" to project.version, +- "Specification-Vendor" to "Bukkit Team" ++ "Specification-Vendor" to "Bukkit Team", ++ "Multi-Release" to "true" // Paper + )) + for (tld in listOf("net", "com", "org")) { + attributes(mapOf( +@@ -54,7 +58,7 @@ tasks.jar { + + tasks.shadowJar { + listOf( +- "jline", "it.unimi", "org.apache.commons.codec", "org.apache.commons.io", ++ "jline", "org.apache.commons.codec", "org.apache.commons.io", // Paper - don't relocate fastutil + "org.apache.commons.lang3", "org.objectweb.asm" + ).forEach { pack -> + relocate(pack, "org.bukkit.craftbukkit.libs.$pack") +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index dfe101d9f5db1bd7cfc59dfe9adc9abb643586cc..24e08ca0fca3e87f8a6b7670b266f3c2900b798c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -190,7 +190,7 @@ public class Main { + } + + if (Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { +- Date buildDate = new Date(Integer.parseInt(Main.class.getPackage().getImplementationVendor()) * 1000L); ++ Date buildDate = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(Main.class.getPackage().getImplementationVendor()); // Paper + + Calendar deadline = Calendar.getInstance(); + deadline.add(Calendar.DAY_OF_YEAR, -3); +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 ++++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +@@ -11,7 +11,7 @@ public final class Versioning { + public static String getBukkitVersion() { + String result = "Unknown-Version"; + +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties"); ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/io.papermc.paper/paper-api/pom.properties"); + Properties properties = new Properties(); + + if (stream != null) { From 648fec34e466acb2aba6036add206ebda6e41d11 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 14:33:08 +0200 Subject: [PATCH 009/226] Rename POM changes to build system changes Signed-off-by: Mariell Hoversholm --- .../{0003-POM-Changes.patch => 0003-Build-system-changes.patch} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename patches/server/{0003-POM-Changes.patch => 0003-Build-system-changes.patch} (99%) diff --git a/patches/server/0003-POM-Changes.patch b/patches/server/0003-Build-system-changes.patch similarity index 99% rename from patches/server/0003-POM-Changes.patch rename to patches/server/0003-Build-system-changes.patch index 5639cd97f9..3554e7bd36 100644 --- a/patches/server/0003-POM-Changes.patch +++ b/patches/server/0003-Build-system-changes.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 29 Feb 2016 20:40:33 -0600 -Subject: [PATCH] POM Changes +Subject: [PATCH] Build system changes diff --git a/build.gradle.kts b/build.gradle.kts From 35487dbfccff8947d0c8a3635f944e54d8fec9ec Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 15:46:25 +0200 Subject: [PATCH 010/226] Apply a few more patches Signed-off-by: Mariell Hoversholm --- .../server-remapped/0003-MC-Dev-fixes.patch | 929 ------------------ .../server/0003-Build-system-changes.patch | 4 +- .../0004-Paper-config-files.patch} | 133 +-- patches/server/0005-MC-Dev-fixes.patch | 358 +++++++ 4 files changed, 427 insertions(+), 997 deletions(-) delete mode 100644 patches/server-remapped/0003-MC-Dev-fixes.patch rename patches/{server-remapped/0002-Paper-config-files.patch => server/0004-Paper-config-files.patch} (87%) create mode 100644 patches/server/0005-MC-Dev-fixes.patch diff --git a/patches/server-remapped/0003-MC-Dev-fixes.patch b/patches/server-remapped/0003-MC-Dev-fixes.patch deleted file mode 100644 index 10c424b9a6..0000000000 --- a/patches/server-remapped/0003-MC-Dev-fixes.patch +++ /dev/null @@ -1,929 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 30 Mar 2016 19:36:20 -0400 -Subject: [PATCH] MC Dev fixes - - -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index 16220ce9a7db722c8b351f8016fd1df066ffcb98..8c378d3f3138953b3b22b289fecdb6b40a09ab63 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -65,8 +65,8 @@ public class Util { - return Collectors.toMap(Entry::getKey, Entry::getValue); - } - -- public static > String getPropertyName(Property iblockstate, Object object) { -- return iblockstate.value((Comparable) object); -+ public static > String a(Property iblockstate, T object) { // Paper - decompile fix -+ return iblockstate.getName(object); // Paper - decompile fix - } - - public static String makeDescriptionId(String type, @Nullable ResourceLocation id) { -@@ -234,8 +234,8 @@ public class Util { - public static T findPreviousInIterable(Iterable iterable, @Nullable T t0) { - Iterator iterator = iterable.iterator(); - -- Object object; -- Object object1; -+ T object; // Paper - decompile fix -+ T object1; // Paper - decompile fix - - for (object1 = null; iterator.hasNext(); object1 = object) { - object = iterator.next(); -@@ -260,7 +260,7 @@ public class Util { - } - - public static Strategy identityStrategy() { -- return Util.IdentityStrategy.INSTANCE; -+ return (Strategy) Util.IdentityStrategy.INSTANCE; // Paper - decompile fix - } - - public static CompletableFuture> sequence(List> futures) { -@@ -271,7 +271,7 @@ public class Util { - futures.forEach((completablefuture1) -> { - int i = list1.size(); - -- list1.add((Object) null); -+ list1.add(null); // Paper - decompile fix - acompletablefuture[i] = completablefuture1.whenComplete((object, throwable) -> { - if (throwable != null) { - completablefuture.completeExceptionally(throwable); -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index aa35d67cc27a4f982575eab3be46f4187f29d3fe..88147a1f25cf2fd549412b653b8f0eb5c60bb55d 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -241,8 +241,8 @@ public class BlockPos extends Vec3i { - }; - } - -- public static Iterable withinManhattan(BlockPos center, int xRange, int yRange, int zRange) { -- int l = xRange + yRange + zRange; -+ public static Iterable withinManhattan(BlockPos center, int xRange, int yRange, int zRange) { // Paper - decompile issues - variable name conflicts to inner class field refs -+ int l_decompiled = xRange + yRange + zRange; // Paper - decompile issues - int i1 = center.getX(); - int j1 = center.getY(); - int k1 = center.getZ(); -@@ -270,15 +270,15 @@ public class BlockPos extends Vec3i { - ++this.x; - if (this.x > this.maxX) { - ++this.currentDepth; -- if (this.currentDepth > x) { -+ if (this.currentDepth > l_decompiled) { // Paper - use proper l above (first line of this method) - return (BlockPos) this.endOfData(); - } - -- this.maxX = Math.min(currentDepth, this.currentDepth); -+ this.maxX = Math.min(xRange, this.currentDepth); // Paper - decompile issues - this.x = -this.maxX; - } - -- this.maxY = Math.min(maxX, this.currentDepth - Math.abs(this.x)); -+ this.maxY = Math.min(yRange, this.currentDepth - Math.abs(this.x)); // Paper - decompile issues - this.y = -this.maxY; - } - -@@ -286,7 +286,7 @@ public class BlockPos extends Vec3i { - int i2 = this.y; - int j2 = this.currentDepth - Math.abs(l1) - Math.abs(i2); - -- if (j2 <= maxY) { -+ if (j2 <= zRange) { // Paper - decompile issues - this.zMirror = j2 != 0; - blockposition_mutableblockposition = this.cursor.set(i1 + l1, j1 + i2, k1 + j2); - } -@@ -355,13 +355,13 @@ public class BlockPos extends Vec3i { - }; - } - -- public static Iterable spiralAround(BlockPos blockposition, int i, Direction enumdirection, Direction enumdirection1) { -+ public static Iterable spiralAround(BlockPos blockposition, int I, Direction enumdirection, Direction enumdirection1) { // Paper - decompile fix - Validate.validState(enumdirection.getAxis() != enumdirection1.getAxis(), "The two directions cannot be on the same axis", new Object[0]); - return () -> { - return new AbstractIterator() { - private final Direction[] directions = new Direction[]{enumdirection, enumdirection1, enumdirection.getOpposite(), enumdirection1.getOpposite()}; - private final BlockPos.MutableBlockPos cursor = blockposition.mutable().move(enumdirection1); -- private final int legs = 4 * legSize; -+ private final int legs = 4 * I; - private int leg = -1; - private int legSize; - private int legIndex; -diff --git a/src/main/java/net/minecraft/core/IdMapper.java b/src/main/java/net/minecraft/core/IdMapper.java -index 71c591487853bec3cecf5777c09ddc05bd658b64..424c6cacc2e7c7b1c9d0b92fe198237033a3fcbd 100644 ---- a/src/main/java/net/minecraft/core/IdMapper.java -+++ b/src/main/java/net/minecraft/core/IdMapper.java -@@ -27,7 +27,7 @@ public class IdMapper implements IdMap { - this.tToId.put(value, id); - - while (this.idToT.size() <= id) { -- this.idToT.add((Object) null); -+ this.idToT.add(null); // Paper - decompile fix - } - - this.idToT.set(id, value); -@@ -41,6 +41,13 @@ public class IdMapper implements IdMap { - this.addMapping(value, this.nextId); - } - -+ // Paper start - decompile fix -+ @Override -+ public int a(T t) { -+ return getId(t); -+ } -+ // Paper end -+ - public int getId(T entry) { - Integer integer = (Integer) this.tToId.get(entry); - -diff --git a/src/main/java/net/minecraft/nbt/ListTag.java b/src/main/java/net/minecraft/nbt/ListTag.java -index efc632a8ac13f77aaf2229a09e84416c09c86255..084340dc73acb3d972e0717b48da820c027a5137 100644 ---- a/src/main/java/net/minecraft/nbt/ListTag.java -+++ b/src/main/java/net/minecraft/nbt/ListTag.java -@@ -53,7 +53,7 @@ public class ListTag extends CollectionTag { - return "TAG_List"; - } - }; -- private static final ByteSet INLINE_ELEMENT_TYPES = new ByteOpenHashSet(Arrays.asList(1, 2, 3, 4, 5, 6)); -+ private static final ByteSet INLINE_ELEMENT_TYPES = new ByteOpenHashSet(Arrays.asList((byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6)); // Paper - decompiler fix - private final List list; - private byte type; - -diff --git a/src/main/java/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java -index 5494db9e8e04d976aa1b005a108b452cd481d0bb..c4fbc0bc8b80d16f09d3c6642acc7476a0817868 100644 ---- a/src/main/java/net/minecraft/nbt/NbtIo.java -+++ b/src/main/java/net/minecraft/nbt/NbtIo.java -@@ -18,6 +18,7 @@ import java.util.zip.GZIPOutputStream; - import net.minecraft.CrashReport; - import net.minecraft.CrashReportCategory; - import net.minecraft.ReportedException; -+import io.netty.buffer.ByteBufInputStream; // Paper - - public class NbtIo { - -@@ -137,7 +138,7 @@ public class NbtIo { - - public static CompoundTag read(DataInput input, NbtAccounter tracker) throws IOException { - // Spigot start -- if ( input instanceof io.netty.buffer.ByteBufInputStream ) -+ if ( input instanceof ByteBufInputStream) // Paper - { - input = new DataInputStream(new org.spigotmc.LimitStream((InputStream) input, tracker)); - } -diff --git a/src/main/java/net/minecraft/nbt/Tag.java b/src/main/java/net/minecraft/nbt/Tag.java -index 483c33e9b2d64c1a003d3bb543486b8a545bc96a..85e9c5f4620fcf48cb3655fbb2db58b3fb31aa74 100644 ---- a/src/main/java/net/minecraft/nbt/Tag.java -+++ b/src/main/java/net/minecraft/nbt/Tag.java -@@ -20,7 +20,7 @@ public interface Tag { - - TagType getType(); - -- Tag copy(); -+ public Tag copy(); // Paper - decompile fix - - default String getAsString() { - return this.toString(); -diff --git a/src/main/java/net/minecraft/network/ConnectionProtocol.java b/src/main/java/net/minecraft/network/ConnectionProtocol.java -index a12d169edf4e087b18fedf7199d6eb7ee58f0305..fca778d131aa10e88d5f7ed8d57eda6803318184 100644 ---- a/src/main/java/net/minecraft/network/ConnectionProtocol.java -+++ b/src/main/java/net/minecraft/network/ConnectionProtocol.java -@@ -14,23 +14,29 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.PacketFlow; - import net.minecraft.network.protocol.game.*; - import net.minecraft.network.protocol.handshake.ClientIntentionPacket; -+import net.minecraft.network.protocol.handshake.ServerHandshakePacketListener; -+import net.minecraft.network.protocol.login.ClientLoginPacketListener; - import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; - import net.minecraft.network.protocol.login.ClientboundGameProfilePacket; - import net.minecraft.network.protocol.login.ClientboundHelloPacket; - import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; - import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; -+import net.minecraft.network.protocol.login.ServerLoginPacketListener; - import net.minecraft.network.protocol.login.ServerboundCustomQueryPacket; - import net.minecraft.network.protocol.login.ServerboundHelloPacket; - import net.minecraft.network.protocol.login.ServerboundKeyPacket; -+import net.minecraft.network.protocol.status.ClientStatusPacketListener; - import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; - import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; -+import net.minecraft.network.protocol.status.ServerStatusPacketListener; - import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; - import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; - import org.apache.logging.log4j.LogManager; - - public enum ConnectionProtocol { - -- HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))), PLAY(0, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new).a(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new).a(ClientboundAddMobPacket.class, ClientboundAddMobPacket::new).a(ClientboundAddPaintingPacket.class, ClientboundAddPaintingPacket::new).a(ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new).a(ClientboundAnimatePacket.class, ClientboundAnimatePacket::new).a(ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new).a(ClientboundBlockBreakAckPacket.class, ClientboundBlockBreakAckPacket::new).a(ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new).a(ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new).a(ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new).a(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new).a(ClientboundBossEventPacket.class, ClientboundBossEventPacket::new).a(ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new).a(ClientboundChatPacket.class, ClientboundChatPacket::new).a(ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new).a(ClientboundCommandsPacket.class, ClientboundCommandsPacket::new).a(ClientboundContainerAckPacket.class, ClientboundContainerAckPacket::new).a(ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new).a(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new).a(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new).a(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new).a(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new).a(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new).a(ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new).a(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new).a(ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new).a(ClientboundExplodePacket.class, ClientboundExplodePacket::new).a(ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new).a(ClientboundGameEventPacket.class, ClientboundGameEventPacket::new).a(ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new).a(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new).a(ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new).a(ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new).a(ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new).a(ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new).a(ClientboundLoginPacket.class, ClientboundLoginPacket::new).a(ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new).a(ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new).a(ClientboundMoveEntityPacket.Pos.class, ClientboundMoveEntityPacket.Pos::new).a(ClientboundMoveEntityPacket.PosRot.class, ClientboundMoveEntityPacket.PosRot::new).a(ClientboundMoveEntityPacket.Rot.class, ClientboundMoveEntityPacket.Rot::new).a(ClientboundMoveEntityPacket.class, ClientboundMoveEntityPacket::new).a(ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new).a(ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new).a(ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new).a(ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new).a(ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new).a(ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new).a(ClientboundPlayerCombatPacket.class, ClientboundPlayerCombatPacket::new).a(ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new).a(ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new).a(ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new).a(ClientboundRecipePacket.class, ClientboundRecipePacket::new).a(ClientboundRemoveEntitiesPacket.class, ClientboundRemoveEntitiesPacket::new).a(ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new).a(ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new).a(ClientboundRespawnPacket.class, ClientboundRespawnPacket::new).a(ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new).a(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new).a(ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new).a(ClientboundSetBorderPacket.class, ClientboundSetBorderPacket::new).a(ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new).a(ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new).a(ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new).a(ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new).a(ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new).a(ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new).a(ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new).a(ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new).a(ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new).a(ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new).a(ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new).a(ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new).a(ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new).a(ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new).a(ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new).a(ClientboundSetScorePacket.class, ClientboundSetScorePacket::new).a(ClientboundSetTimePacket.class, ClientboundSetTimePacket::new).a(ClientboundSetTitlesPacket.class, ClientboundSetTitlesPacket::new).a(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new).a(ClientboundSoundPacket.class, ClientboundSoundPacket::new).a(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new).a(ClientboundTabListPacket.class, ClientboundTabListPacket::new).a(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new).a(ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new).a(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new).a(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new).a(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new).a(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new).a(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new).a(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new)).a(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new).a(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new).a(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new).a(ServerboundChatPacket.class, ServerboundChatPacket::new).a(ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new).a(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new).a(ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new).a(ServerboundContainerAckPacket.class, ServerboundContainerAckPacket::new).a(ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new).a(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new).a(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new).a(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new).a(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new).a(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new).a(ServerboundInteractPacket.class, ServerboundInteractPacket::new).a(ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new).a(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new).a(ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new).a(ServerboundMovePlayerPacket.Pos.class, ServerboundMovePlayerPacket.Pos::new).a(ServerboundMovePlayerPacket.PosRot.class, ServerboundMovePlayerPacket.PosRot::new).a(ServerboundMovePlayerPacket.Rot.class, ServerboundMovePlayerPacket.Rot::new).a(ServerboundMovePlayerPacket.class, ServerboundMovePlayerPacket::new).a(ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new).a(ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new).a(ServerboundPickItemPacket.class, ServerboundPickItemPacket::new).a(ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new).a(ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new).a(ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new).a(ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new).a(ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new).a(ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new).a(ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new).a(ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new).a(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new).a(ServerboundSeenAdvancementsPacket.class, ServerboundSeenAdvancementsPacket::new).a(ServerboundSelectTradePacket.class, ServerboundSelectTradePacket::new).a(ServerboundSetBeaconPacket.class, ServerboundSetBeaconPacket::new).a(ServerboundSetCarriedItemPacket.class, ServerboundSetCarriedItemPacket::new).a(ServerboundSetCommandBlockPacket.class, ServerboundSetCommandBlockPacket::new).a(ServerboundSetCommandMinecartPacket.class, ServerboundSetCommandMinecartPacket::new).a(ServerboundSetCreativeModeSlotPacket.class, ServerboundSetCreativeModeSlotPacket::new).a(ServerboundSetJigsawBlockPacket.class, ServerboundSetJigsawBlockPacket::new).a(ServerboundSetStructureBlockPacket.class, ServerboundSetStructureBlockPacket::new).a(ServerboundSignUpdatePacket.class, ServerboundSignUpdatePacket::new).a(ServerboundSwingPacket.class, ServerboundSwingPacket::new).a(ServerboundTeleportToEntityPacket.class, ServerboundTeleportToEntityPacket::new).a(ServerboundUseItemOnPacket.class, ServerboundUseItemOnPacket::new).a(ServerboundUseItemPacket.class, ServerboundUseItemPacket::new))), STATUS(1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new).a(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)).a(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new).a(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new))), LOGIN(2, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new).a(ClientboundHelloPacket.class, ClientboundHelloPacket::new).a(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new).a(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new).a(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new)).a(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new).a(ServerboundKeyPacket.class, ServerboundKeyPacket::new).a(ServerboundCustomQueryPacket.class, ServerboundCustomQueryPacket::new))); -+ // Paper - fix decompile error - add generic names to < > like PacketListenerPlayOut -+ HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))), PLAY(0, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new).addPacket(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new).addPacket(ClientboundAddMobPacket.class, ClientboundAddMobPacket::new).addPacket(ClientboundAddPaintingPacket.class, ClientboundAddPaintingPacket::new).addPacket(ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new).addPacket(ClientboundAnimatePacket.class, ClientboundAnimatePacket::new).addPacket(ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new).addPacket(ClientboundBlockBreakAckPacket.class, ClientboundBlockBreakAckPacket::new).addPacket(ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new).addPacket(ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new).addPacket(ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new).addPacket(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new).addPacket(ClientboundBossEventPacket.class, ClientboundBossEventPacket::new).addPacket(ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new).addPacket(ClientboundChatPacket.class, ClientboundChatPacket::new).addPacket(ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new).addPacket(ClientboundCommandsPacket.class, ClientboundCommandsPacket::new).addPacket(ClientboundContainerAckPacket.class, ClientboundContainerAckPacket::new).addPacket(ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new).addPacket(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new).addPacket(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new).addPacket(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new).addPacket(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new).addPacket(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new).addPacket(ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new).addPacket(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new).addPacket(ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new).addPacket(ClientboundExplodePacket.class, ClientboundExplodePacket::new).addPacket(ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new).addPacket(ClientboundGameEventPacket.class, ClientboundGameEventPacket::new).addPacket(ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new).addPacket(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new).addPacket(ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new).addPacket(ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new).addPacket(ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new).addPacket(ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new).addPacket(ClientboundLoginPacket.class, ClientboundLoginPacket::new).addPacket(ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new).addPacket(ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new).addPacket(ClientboundMoveEntityPacket.Pos.class, ClientboundMoveEntityPacket.Pos::new).addPacket(ClientboundMoveEntityPacket.PosRot.class, ClientboundMoveEntityPacket.PosRot::new).addPacket(ClientboundMoveEntityPacket.Rot.class, ClientboundMoveEntityPacket.Rot::new).addPacket(ClientboundMoveEntityPacket.class, ClientboundMoveEntityPacket::new).addPacket(ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new).addPacket(ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new).addPacket(ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new).addPacket(ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new).addPacket(ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new).addPacket(ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new).addPacket(ClientboundPlayerCombatPacket.class, ClientboundPlayerCombatPacket::new).addPacket(ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new).addPacket(ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new).addPacket(ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new).addPacket(ClientboundRecipePacket.class, ClientboundRecipePacket::new).addPacket(ClientboundRemoveEntitiesPacket.class, ClientboundRemoveEntitiesPacket::new).addPacket(ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new).addPacket(ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new).addPacket(ClientboundRespawnPacket.class, ClientboundRespawnPacket::new).addPacket(ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new).addPacket(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new).addPacket(ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new).addPacket(ClientboundSetBorderPacket.class, ClientboundSetBorderPacket::new).addPacket(ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new).addPacket(ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new).addPacket(ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new).addPacket(ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new).addPacket(ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new).addPacket(ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new).addPacket(ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new).addPacket(ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new).addPacket(ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new).addPacket(ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new).addPacket(ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new).addPacket(ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new).addPacket(ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new).addPacket(ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new).addPacket(ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new).addPacket(ClientboundSetScorePacket.class, ClientboundSetScorePacket::new).addPacket(ClientboundSetTimePacket.class, ClientboundSetTimePacket::new).addPacket(ClientboundSetTitlesPacket.class, ClientboundSetTitlesPacket::new).addPacket(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new).addPacket(ClientboundSoundPacket.class, ClientboundSoundPacket::new).addPacket(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new).addPacket(ClientboundTabListPacket.class, ClientboundTabListPacket::new).addPacket(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new).addPacket(ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new).addPacket(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new).addPacket(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new).addPacket(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new).addPacket(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new).addPacket(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new).addPacket(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new).addPacket(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new).addPacket(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new).addPacket(ServerboundChatPacket.class, ServerboundChatPacket::new).addPacket(ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new).addPacket(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new).addPacket(ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new).addPacket(ServerboundContainerAckPacket.class, ServerboundContainerAckPacket::new).addPacket(ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new).addPacket(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new).addPacket(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new).addPacket(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new).addPacket(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new).addPacket(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new).addPacket(ServerboundInteractPacket.class, ServerboundInteractPacket::new).addPacket(ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new).addPacket(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new).addPacket(ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new).addPacket(ServerboundMovePlayerPacket.Pos.class, ServerboundMovePlayerPacket.Pos::new).addPacket(ServerboundMovePlayerPacket.PosRot.class, ServerboundMovePlayerPacket.PosRot::new).addPacket(ServerboundMovePlayerPacket.Rot.class, ServerboundMovePlayerPacket.Rot::new).addPacket(ServerboundMovePlayerPacket.class, ServerboundMovePlayerPacket::new).addPacket(ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new).addPacket(ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new).addPacket(ServerboundPickItemPacket.class, ServerboundPickItemPacket::new).addPacket(ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new).addPacket(ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new).addPacket(ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new).addPacket(ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new).addPacket(ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new).addPacket(ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new).addPacket(ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new).addPacket(ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new).addPacket(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new).addPacket(ServerboundSeenAdvancementsPacket.class, ServerboundSeenAdvancementsPacket::new).addPacket(ServerboundSelectTradePacket.class, ServerboundSelectTradePacket::new).addPacket(ServerboundSetBeaconPacket.class, ServerboundSetBeaconPacket::new).addPacket(ServerboundSetCarriedItemPacket.class, ServerboundSetCarriedItemPacket::new).addPacket(ServerboundSetCommandBlockPacket.class, ServerboundSetCommandBlockPacket::new).addPacket(ServerboundSetCommandMinecartPacket.class, ServerboundSetCommandMinecartPacket::new).addPacket(ServerboundSetCreativeModeSlotPacket.class, ServerboundSetCreativeModeSlotPacket::new).addPacket(ServerboundSetJigsawBlockPacket.class, ServerboundSetJigsawBlockPacket::new).addPacket(ServerboundSetStructureBlockPacket.class, ServerboundSetStructureBlockPacket::new).addPacket(ServerboundSignUpdatePacket.class, ServerboundSignUpdatePacket::new).addPacket(ServerboundSwingPacket.class, ServerboundSwingPacket::new).addPacket(ServerboundTeleportToEntityPacket.class, ServerboundTeleportToEntityPacket::new).addPacket(ServerboundUseItemOnPacket.class, ServerboundUseItemOnPacket::new).addPacket(ServerboundUseItemPacket.class, ServerboundUseItemPacket::new))), STATUS(1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new).addPacket(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)).addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new).addPacket(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new))), LOGIN(2, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new).addPacket(ClientboundHelloPacket.class, ClientboundHelloPacket::new).addPacket(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new).addPacket(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new).addPacket(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new).addPacket(ServerboundKeyPacket.class, ServerboundKeyPacket::new).addPacket(ServerboundCustomQueryPacket.class, ServerboundCustomQueryPacket::new))); - - private static final ConnectionProtocol[] LOOKUP = new ConnectionProtocol[4]; - private static final Map>, ConnectionProtocol> PROTOCOL_BY_PACKET = Maps.newHashMap(); -@@ -115,7 +121,7 @@ public enum ConnectionProtocol { - private final List>> idToConstructor; - - private PacketSet() { -- this.classToId = (Object2IntMap) Util.make((Object) (new Object2IntOpenHashMap()), (object2intopenhashmap) -> { -+ this.classToId = (Object2IntMap) Util.make(new Object2IntOpenHashMap(), (object2intopenhashmap) -> { // Paper - fix decompile error - object2intopenhashmap.defaultReturnValue(-1); - }); - this.idToConstructor = Lists.newArrayList(); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 21f461ce884bc547dbe81c5430be530423c1605c..37a51dee4cd37844e80fdd5c9853947201151dfc 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1673,9 +1673,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoopmap(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error - }, this).thenCompose((immutablelist) -> { -- return ServerResources.loadResources(immutablelist, this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this); -+ return ServerResources.loadResources(immutablelist, this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this); // Paper - decompile error - }).thenAcceptAsync((datapackresources) -> { - this.resources.close(); - this.resources = datapackresources; -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 37e938b258ee4eb5f5bab56145e83b640d80bcc7..23506a8903ce64fbfe849bb94e589bdbb6e61a74 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1913,7 +1913,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - // CraftBukkit - decompile error -- return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(it.unimi.dsi.fastutil.objects.Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { -+ return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { // Paper - decompile fix - return it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey() + ":" + it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue(); - }).collect(Collectors.joining(",")); - } catch (Exception exception) { -diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java -index ad8a9d14e17b5e40b2cc3a83154931734d6c73d7..cc4190b3a8904d1eaae0f542a3b3090583f5ff82 100644 ---- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java -+++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java -@@ -179,9 +179,9 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl - - public void tryScheduleUpdate() { - if ((!this.lightTasks.isEmpty() || super.hasLightWork()) && this.scheduled.compareAndSet(false, true)) { -- this.taskMailbox.tell((Object) (() -> { -- this.b(); -- this.g.set(false); -+ this.taskMailbox.tell((() -> { // Paper - decompile error -+ this.runUpdate(); -+ this.scheduled.set(false); - })); - } - -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 90df41ec5081fe4ef2bc507e7289b18e0fea6e53..0c118d482e304c567fe7fe778c6ff386f960bdde 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -23,7 +23,7 @@ public final class Ticket implements Comparable> { - } else { - int j = Integer.compare(System.identityHashCode(this.type), System.identityHashCode(ticket.type)); - -- return j != 0 ? j : this.type.getComparator().compare(this.key, ticket.key); -+ return j != 0 ? j : this.type.getComparator().compare(this.key, (T)ticket.key); // Paper - decompile fix - } - } - -diff --git a/src/main/java/net/minecraft/stats/ServerStatsCounter.java b/src/main/java/net/minecraft/stats/ServerStatsCounter.java -index d624c390f8550c6aa44ca5920d127c901903ce27..7d435998680a363ad06c2e08139010c2573f7fb3 100644 ---- a/src/main/java/net/minecraft/stats/ServerStatsCounter.java -+++ b/src/main/java/net/minecraft/stats/ServerStatsCounter.java -@@ -203,7 +203,7 @@ public class ServerStatsCounter extends StatsCounter { - ObjectIterator objectiterator = this.stats.object2IntEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); -+ Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix - Stat statistic = (Stat) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); - - ((JsonObject) map.computeIfAbsent(statistic.getType(), (statisticwrapper) -> { -diff --git a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java -index 74eb1ed6b3fafeaca7e65a88a982d759d6836853..66ad412e4368a8615cc66a97ac442c572813a3dd 100644 ---- a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java -+++ b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java -@@ -18,11 +18,18 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { - - public CrudeIncrementalIntIdentityHashBiMap(int size) { - size = (int) ((float) size / 0.8F); -- this.keys = (Object[]) (new Object[size]); -+ this.keys = (K[]) (new Object[size]); // Paper - decompile fix - this.values = new int[size]; -- this.byId = (Object[]) (new Object[size]); -+ this.byId = (K[]) (new Object[size]); // Paper - decompile fix - } - -+ // Paper start - decompile fix -+ @Override -+ public int a(K k) { -+ return getId(k); -+ } -+ // Paper end -+ - public int getId(@Nullable K entry) { - return this.getValue(this.indexOf(entry, this.hash(entry))); - } -@@ -56,9 +63,9 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { - K[] ak = this.keys; - int[] aint = this.values; - -- this.keys = (Object[]) (new Object[newSize]); -+ this.keys = (K[]) (new Object[newSize]); // Paper - decompile fix - this.values = new int[newSize]; -- this.byId = (Object[]) (new Object[newSize]); -+ this.byId = (K[]) (new Object[newSize]); // Paper - decompile fix - this.nextId = 0; - this.size = 0; - -diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java -index be40fc388c501c311d661927025f1c572f3b3493..93813a508be1e1e600a8211f9822f2087328de70 100644 ---- a/src/main/java/net/minecraft/util/SortedArraySet.java -+++ b/src/main/java/net/minecraft/util/SortedArraySet.java -@@ -23,11 +23,11 @@ public class SortedArraySet extends AbstractSet { - } - - public static > SortedArraySet create(int initialCapacity) { -- return new SortedArraySet<>(initialCapacity, Comparator.naturalOrder()); -+ return new SortedArraySet<>(initialCapacity, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix - } - - private static T[] castRawArray(Object[] array) { -- return (Object[]) array; -+ return (T[])array; // Paper - decompile fix - } - - private int findIndex(T object) { -@@ -101,7 +101,7 @@ public class SortedArraySet extends AbstractSet { - } - - public boolean remove(Object object) { -- int i = this.findIndex(object); -+ int i = this.findIndex((T)object); // Paper - decompile fix - - if (i >= 0) { - this.removeInternal(i); -@@ -116,7 +116,7 @@ public class SortedArraySet extends AbstractSet { - } - - public boolean contains(Object object) { -- int i = this.findIndex(object); -+ int i = this.findIndex((T)object); // Paper - decompile fix - - return i >= 0; - } -@@ -135,7 +135,7 @@ public class SortedArraySet extends AbstractSet { - - public U[] toArray(U[] au) { - if (au.length < this.size) { -- return (Object[]) Arrays.copyOf(this.contents, this.size, au.getClass()); -+ return (U[])Arrays.copyOf(this.contents, this.size, au.getClass()); // Paper - decompile fix - } else { - System.arraycopy(this.contents, 0, au, 0, this.size); - if (au.length > this.size) { -diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -index d9375f83de6d069f603f8a48cc5b02194e940052..03831adce7905916423d8c3834c42c90f3a1ca8f 100644 ---- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -+++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -@@ -55,7 +55,7 @@ public abstract class BlockableEventLoop implements Processo - return this.submitAsync(task); - } else { - task.run(); -- return CompletableFuture.completedFuture((Object) null); -+ return CompletableFuture.completedFuture(null); // Paper - decompile fix - } - } - -@@ -90,14 +90,14 @@ public abstract class BlockableEventLoop implements Processo - } - - protected boolean pollTask() { -- R r0 = (Runnable) this.pendingRunnables.peek(); -+ R r0 = this.pendingRunnables.peek(); // Paper - decompile fix - - if (r0 == null) { - return false; - } else if (this.blockingCount == 0 && !this.shouldRun(r0)) { - return false; - } else { -- this.doRunTask((Runnable) this.pendingRunnables.remove()); -+ this.doRunTask(this.pendingRunnables.remove()); // Paper - decompile fix - return true; - } - } -diff --git a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java -index cc77767947e458e7205e616dce3bea8da09ca0cf..c763aa0c0cf49dd844af94a820103258b49021ae 100644 ---- a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java -+++ b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java -@@ -100,7 +100,7 @@ public class ProcessorMailbox implements ProcessorHandle, AutoCloseable, R - - public void run() { - try { -- this.pollUntil((i) -> { -+ this.pollUntil((int i) -> { // Paper - decompile fix - return i == 0; - }); - } finally { -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -index 8f686f8608771d0a444dfd51dd4eabc90c6b2262..33a8604fa6c6431ccc5f61e484c163e09f1625a0 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -@@ -191,9 +191,9 @@ public class PoiManager extends SectionStorage { - } - - private static boolean mayHavePoi(LevelChunkSection chunksection) { -- Set set = PoiType.ALL_STATES; -+ Set set = PoiType.ALL_STATES; // Paper - decompile error - -- set.getClass(); -+ //set.getClass(); // Paper - decompile error - return chunksection.maybeHas(set::contains); - } - -@@ -211,7 +211,7 @@ public class PoiManager extends SectionStorage { - SectionPos.aroundChunk(new ChunkPos(pos), Math.floorDiv(radius, 16)).map((sectionposition) -> { - return Pair.of(sectionposition, this.getOrLoad(sectionposition.asLong())); - }).filter((pair) -> { -- return !(Boolean) ((Optional) pair.getSecond()).map(PoiSection::a).orElse(false); -+ return !(Boolean) (pair.getSecond()).map(PoiSection::isValid).orElse(false); // Paper - decompile fix - }).map((pair) -> { - return ((SectionPos) pair.getFirst()).chunk(); - }).filter((chunkcoordintpair) -> { -@@ -257,13 +257,13 @@ public class PoiManager extends SectionStorage { - - public static enum Occupancy { - -- HAS_SPACE(PoiRecord::d), IS_OCCUPIED(PoiRecord::e), ANY((villageplacerecord) -> { -+ HAS_SPACE(PoiRecord::hasSpace), IS_OCCUPIED(PoiRecord::isOccupied), ANY((villageplacerecord) -> { - return true; - }); - - private final Predicate test; - -- private Occupancy(Predicate predicate) { -+ private Occupancy(Predicate predicate) { // Paper - decompile fix - this.test = predicate; - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -index 97317517a729877e307407ca9fab5fa58657fe38..a41f61daf6cbbb13d0b86cdbad8a4cae00368653 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -@@ -65,7 +65,7 @@ public class Vindicator extends AbstractIllager { - this.goalSelector.addGoal(2, new AbstractIllager.RaiderOpenDoorGoal(this)); - this.goalSelector.addGoal(3, new Raider.HoldGroundAttackGoal(this, 10.0F)); - this.goalSelector.addGoal(4, new Vindicator.VindicatorMeleeAttackGoal(this)); -- this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).canUse()); -+ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers(new Class[0])); // Paper - decompile fix - this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true)); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); -diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -index ad4e181b24829980dc12f46807ec1c5226bd8e0c..fd1b84baae5f333c58dbbdcbfaa9198328f0961d 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -+++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -@@ -47,12 +47,12 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; - - public class VillagerTrades { - -- public static final Map> TRADES = (Map) Util.make((Object) Maps.newHashMap(), (hashmap) -> { -+ public static final Map> TRADES = Util.make(Maps.newHashMap(), (hashmap) -> { // Paper - decompile fix - hashmap.put(VillagerProfession.FARMER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WHEAT, 20, 16, 2), new VillagerTrades.EmeraldForItems(Items.POTATO, 26, 16, 2), new VillagerTrades.EmeraldForItems(Items.CARROT, 22, 16, 2), new VillagerTrades.EmeraldForItems(Items.BEETROOT, 15, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.BREAD, 1, 6, 16, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Blocks.PUMPKIN, 6, 12, 10), new VillagerTrades.ItemsForEmeralds(Items.PUMPKIN_PIE, 1, 4, 5), new VillagerTrades.ItemsForEmeralds(Items.APPLE, 1, 4, 16, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.COOKIE, 3, 18, 10), new VillagerTrades.EmeraldForItems(Blocks.MELON, 4, 12, 20)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Blocks.CAKE, 1, 1, 12, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.NIGHT_VISION, 100, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.JUMP, 160, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.WEAKNESS, 140, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.BLINDNESS, 120, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.POISON, 280, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.SATURATION, 7, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.GOLDEN_CARROT, 3, 3, 30), new VillagerTrades.ItemsForEmeralds(Items.GLISTERING_MELON_SLICE, 4, 3, 30)}))); -- hashmap.put(VillagerProfession.FISHERMAN, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STRING, 20, 16, 2), new VillagerTrades.EmeraldForItems(Items.COAL, 10, 16, 2), new VillagerTrades.ItemsAndEmeraldsToItems(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.ItemsForEmeralds(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COD, 15, 16, 10), new VillagerTrades.ItemsAndEmeraldsToItems(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.ItemsForEmeralds(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.SALMON, 13, 16, 20), new VillagerTrades.EnchantedItemForEmeralds(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.EmeraldsForVillagerTypeItem(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); -+ hashmap.put(VillagerProfession.FISHERMAN, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STRING, 20, 16, 2), new VillagerTrades.EmeraldForItems(Items.COAL, 10, 16, 2), new VillagerTrades.ItemsAndEmeraldsToItems(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.ItemsForEmeralds(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COD, 15, 16, 10), new VillagerTrades.ItemsAndEmeraldsToItems(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.ItemsForEmeralds(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.SALMON, 13, 16, 20), new VillagerTrades.EnchantedItemForEmeralds(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.EmeraldsForVillagerTypeItem(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); // Paper - add to ImmutableMap..builder() - hashmap.put(VillagerProfession.SHEPHERD, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Blocks.WHITE_WOOL, 18, 16, 2), new VillagerTrades.EmeraldForItems(Blocks.BROWN_WOOL, 18, 16, 2), new VillagerTrades.EmeraldForItems(Blocks.BLACK_WOOL, 18, 16, 2), new VillagerTrades.EmeraldForItems(Blocks.GRAY_WOOL, 18, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.SHEARS, 2, 1, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WHITE_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.GRAY_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.BLACK_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.LIGHT_BLUE_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.LIME_DYE, 12, 16, 10), new VillagerTrades.ItemsForEmeralds(Blocks.WHITE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.ORANGE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.MAGENTA_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.YELLOW_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIME_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PINK_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.CYAN_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PURPLE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BROWN_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GREEN_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.RED_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLACK_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.WHITE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.ORANGE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.MAGENTA_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.YELLOW_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIME_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PINK_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.CYAN_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PURPLE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BROWN_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GREEN_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.RED_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLACK_CARPET, 1, 4, 16, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.YELLOW_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.LIGHT_GRAY_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.ORANGE_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.RED_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.PINK_DYE, 12, 16, 20), new VillagerTrades.ItemsForEmeralds(Blocks.WHITE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.YELLOW_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.RED_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.BLACK_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.BLUE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.BROWN_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.CYAN_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.GRAY_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.GREEN_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_BLUE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_GRAY_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.LIME_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.MAGENTA_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.ORANGE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.PINK_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.PURPLE_BED, 3, 1, 12, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.BROWN_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.PURPLE_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.BLUE_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.GREEN_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.MAGENTA_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.CYAN_DYE, 12, 16, 30), new VillagerTrades.ItemsForEmeralds(Items.WHITE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.RED_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.PINK_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.GREEN_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.LIME_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.GRAY_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.BLACK_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.PURPLE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.MAGENTA_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.CYAN_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.BROWN_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.YELLOW_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.ORANGE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_GRAY_BANNER, 3, 1, 12, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.PAINTING, 2, 3, 30)}))); - hashmap.put(VillagerProfession.FLETCHER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STICK, 32, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.ARROW, 1, 16, 1), new VillagerTrades.ItemsAndEmeraldsToItems(Blocks.GRAVEL, 10, Items.FLINT, 10, 12, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.FLINT, 26, 12, 10), new VillagerTrades.ItemsForEmeralds(Items.BOW, 2, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STRING, 14, 16, 20), new VillagerTrades.ItemsForEmeralds(Items.CROSSBOW, 3, 1, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.FEATHER, 24, 16, 30), new VillagerTrades.EnchantedItemForEmeralds(Items.BOW, 2, 3, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.es, 8, 12, 30), new VillagerTrades.EnchantedItemForEmeralds(Items.CROSSBOW, 3, 3, 15), new VillagerTrades.TippedArrowForItemsAndEmeralds(Items.ARROW, 5, Items.TIPPED_ARROW, 5, 2, 12, 30)}))); -- hashmap.put(VillagerProfession.LIBRARIAN, toIntMap(ImmutableMap.builder().put(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PAPER, 24, 16, 2), new VillagerTrades.EnchantBookForEmeralds(1), new VillagerTrades.ItemsForEmeralds(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.BOOK, 4, 12, 10), new VillagerTrades.EnchantBookForEmeralds(5), new VillagerTrades.ItemsForEmeralds(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.INK_SAC, 5, 12, 20), new VillagerTrades.EnchantBookForEmeralds(10), new VillagerTrades.ItemsForEmeralds(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.EnchantBookForEmeralds(15), new VillagerTrades.ItemsForEmeralds(Items.CLOCK, 5, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.NAME_TAG, 20, 1, 30)}).build())); -+ hashmap.put(VillagerProfession.LIBRARIAN, toIntMap(ImmutableMap.builder().put(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PAPER, 24, 16, 2), new VillagerTrades.EnchantBookForEmeralds(1), new VillagerTrades.ItemsForEmeralds(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.BOOK, 4, 12, 10), new VillagerTrades.EnchantBookForEmeralds(5), new VillagerTrades.ItemsForEmeralds(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.INK_SAC, 5, 12, 20), new VillagerTrades.EnchantBookForEmeralds(10), new VillagerTrades.ItemsForEmeralds(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.EnchantBookForEmeralds(15), new VillagerTrades.ItemsForEmeralds(Items.CLOCK, 5, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.NAME_TAG, 20, 1, 30)}).build())); // Paper - add to ImmutableMap..builder() - hashmap.put(VillagerProfession.CARTOGRAPHER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PAPER, 24, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.MAP, 7, 1, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.dP, 11, 16, 10), new VillagerTrades.TreasureMapForEmeralds(13, StructureFeature.OCEAN_MONUMENT, MapDecoration.Type.MONUMENT, 12, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COMPASS, 1, 12, 20), new VillagerTrades.TreasureMapForEmeralds(14, StructureFeature.WOODLAND_MANSION, MapDecoration.Type.MANSION, 12, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.ITEM_FRAME, 7, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.WHITE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.BLUE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_BLUE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.RED_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.PINK_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.GREEN_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.LIME_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.GRAY_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.BLACK_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.PURPLE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.MAGENTA_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.CYAN_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.BROWN_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.YELLOW_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.ORANGE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_GRAY_BANNER, 3, 1, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.GLOBE_BANNER_PATTERN, 8, 1, 30)}))); - hashmap.put(VillagerProfession.CLERIC, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.ROTTEN_FLESH, 32, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.REDSTONE, 1, 2, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.GOLD_INGOT, 3, 12, 10), new VillagerTrades.ItemsForEmeralds(Items.LAPIS_LAZULI, 1, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.RABBIT_FOOT, 2, 12, 20), new VillagerTrades.ItemsForEmeralds(Blocks.GLOWSTONE, 4, 1, 12, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.SCUTE, 4, 12, 30), new VillagerTrades.EmeraldForItems(Items.GLASS_BOTTLE, 9, 12, 30), new VillagerTrades.ItemsForEmeralds(Items.ENDER_PEARL, 5, 1, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.NETHER_WART, 22, 12, 30), new VillagerTrades.ItemsForEmeralds(Items.EXPERIENCE_BOTTLE, 3, 1, 30)}))); - hashmap.put(VillagerProfession.ARMORER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COAL, 15, 16, 2), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_LEGGINGS), 7, 1, 12, 1, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_BOOTS), 4, 1, 12, 1, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_HELMET), 5, 1, 12, 1, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_CHESTPLATE), 9, 1, 12, 1, 0.2F)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.IRON_INGOT, 4, 12, 10), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.rj), 36, 1, 12, 5, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_BOOTS), 1, 1, 12, 5, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_LEGGINGS), 3, 1, 12, 5, 0.2F)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.LAVA_BUCKET, 1, 12, 20), new VillagerTrades.EmeraldForItems(Items.DIAMOND, 1, 12, 20), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_HELMET), 1, 1, 12, 10, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_CHESTPLATE), 4, 1, 12, 10, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.SHIELD), 5, 1, 12, 10, 0.2F)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_LEGGINGS, 14, 3, 15, 0.2F), new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_BOOTS, 8, 3, 15, 0.2F)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_HELMET, 8, 3, 30, 0.2F), new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_CHESTPLATE, 16, 3, 30, 0.2F)}))); -diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java -index 86d7af20fad04405f95c71e078d41070abdc43ad..c4777997cfff364818fbaee70afd7c79099213fb 100644 ---- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java -+++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java -@@ -75,7 +75,7 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { - } - - this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { -- return (entry1.getValue()); // CraftBukkit -+ return entry1.getValue(); // CraftBukkit // Paper - decompile fix - *shrugs internally* - })); - RecipeManager.LOGGER.info("Loaded {} recipes", map1.size()); - } -diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index 1276769b22ae21f0ff4271ecc72d4aa39ddff23f..7e7a58b9a9ececdcc37fc33b33703428eb1d5faf 100644 ---- a/src/main/java/net/minecraft/world/level/EntityGetter.java -+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -167,22 +167,22 @@ public interface EntityGetter { - - @Nullable - default T getNearestEntity(Class entityClass, TargetingConditions targetPredicate, @Nullable LivingEntity entity, double x, double y, double z, AABB box) { -- return this.getNearestEntity(this.getEntitiesOfClass(entityClass, box, (Predicate) null), targetPredicate, entity, x, y, z); -+ return this.getNearestEntity(this.getEntitiesOfClass(entityClass, box, null), targetPredicate, entity, x, y, z); // Paper - decompile fix - } - - @Nullable - default T getNearestLoadedEntity(Class entityClass, TargetingConditions targetPredicate, @Nullable LivingEntity entity, double x, double y, double z, AABB box) { -- return this.getNearestEntity(this.getLoadedEntitiesOfClass(entityClass, box, (Predicate) null), targetPredicate, entity, x, y, z); -+ return this.getNearestEntity(this.getLoadedEntitiesOfClass(entityClass, box, null), targetPredicate, entity, x, y, z); // Paper - decompile fix - } - - @Nullable - default T getNearestEntity(List entityList, TargetingConditions targetPredicate, @Nullable LivingEntity entity, double x, double y, double z) { - double d3 = -1.0D; - T t0 = null; -- Iterator iterator = entityList.iterator(); -+ Iterator iterator = entityList.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t1 = (LivingEntity) iterator.next(); -+ T t1 = iterator.next(); // Paper - decompile fix - - if (targetPredicate.test(entity, t1)) { - double d4 = t1.distanceToSqr(x, y, z); -@@ -215,10 +215,10 @@ public interface EntityGetter { - default List getNearbyEntities(Class entityClass, TargetingConditions targetPredicate, LivingEntity targetingEntity, AABB box) { - List list = this.getEntitiesOfClass(entityClass, box, (Predicate) null); - List list1 = Lists.newArrayList(); -- Iterator iterator = list.iterator(); -+ Iterator iterator = list.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t0 = (LivingEntity) iterator.next(); -+ T t0 = iterator.next(); // Paper - decompile fix - - if (targetPredicate.test(targetingEntity, t0)) { - list1.add(t0); -diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java -index c6e64c5182d564664464e26df27e6b5f7da418e6..d97e266b83bb331fcd4031046a5843d29ce53164 100644 ---- a/src/main/java/net/minecraft/world/level/TickNextTickData.java -+++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java -@@ -38,13 +38,13 @@ public class TickNextTickData { - return this.pos.hashCode(); - } - -- public static Comparator> createTimeComparator() { -+ public static Comparator createTimeComparator() { // Paper - decompile fix - return Comparator.comparingLong((nextticklistentry) -> { -- return nextticklistentry.b; -+ return ((TickNextTickData) nextticklistentry).triggerTick; // Paper - decompile fix - }).thenComparing((nextticklistentry) -> { -- return nextticklistentry.c; -+ return ((TickNextTickData) nextticklistentry).priority; // Paper - decompile fix - }).thenComparingLong((nextticklistentry) -> { -- return nextticklistentry.f; -+ return ((TickNextTickData) nextticklistentry).c; // Paper - decompile fix - }); - } - -diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java -index 79be56c26b66351bcfcd96c9967f0ce91e40d5ce..ed83335175bb882741dfaef251ab30ce1590f74c 100644 ---- a/src/main/java/net/minecraft/world/level/biome/Biome.java -+++ b/src/main/java/net/minecraft/world/level/biome/Biome.java -@@ -49,36 +49,43 @@ import org.apache.logging.log4j.Logger; - public final class Biome { - - public static final Logger LOGGER = LogManager.getLogger(); -+ // Paper start -+ private static class dProxy extends Biome.ClimateSettings { -+ private dProxy(Precipitation precipitation, float temperature, TemperatureModifier temperatureModifier, float downfall) { -+ super(precipitation, temperature, temperatureModifier, downfall); -+ } -+ }; -+ // Paper end - public static final Codec DIRECT_CODEC = RecordCodecBuilder.create((instance) -> { -- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { -- return biomebase.j; -+ return instance.group(dProxy.CODEC.forGetter((biomebase) -> { // Paper -+ return biomebase.climateSettings; - }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biomebase) -> { -- return biomebase.o; -+ return biomebase.biomeCategory; - }), Codec.FLOAT.fieldOf("depth").forGetter((biomebase) -> { -- return biomebase.m; -+ return biomebase.depth; - }), Codec.FLOAT.fieldOf("scale").forGetter((biomebase) -> { -- return biomebase.n; -+ return biomebase.scale; - }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biomebase) -> { -- return biomebase.p; -+ return biomebase.specialEffects; - }), BiomeGenerationSettings.CODEC.forGetter((biomebase) -> { -- return biomebase.k; -+ return biomebase.generationSettings; - }), MobSpawnSettings.CODEC.forGetter((biomebase) -> { -- return biomebase.l; -+ return biomebase.mobSettings; - })).apply(instance, Biome::new); - }); - public static final Codec NETWORK_CODEC = RecordCodecBuilder.create((instance) -> { -- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { -- return biomebase.j; -+ return instance.group(dProxy.CODEC.forGetter((biomebase) -> { // Paper -+ return biomebase.climateSettings; - }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biomebase) -> { -- return biomebase.o; -+ return biomebase.biomeCategory; - }), Codec.FLOAT.fieldOf("depth").forGetter((biomebase) -> { -- return biomebase.m; -+ return biomebase.depth; - }), Codec.FLOAT.fieldOf("scale").forGetter((biomebase) -> { -- return biomebase.n; -+ return biomebase.scale; - }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biomebase) -> { -- return biomebase.p; -+ return biomebase.specialEffects; - })).apply(instance, (biomebase_d, biomebase_geography, ofloat, ofloat1, biomefog) -> { -- return new BiomeBase(biomebase_d, biomebase_geography, ofloat, ofloat1, biomefog, BiomeSettingsGeneration.b, BiomeSettingsMobs.b); -+ return new Biome(biomebase_d, biomebase_geography, ofloat, ofloat1, biomefog, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY); - }); - }); - public static final Codec> CODEC = RegistryFileCodec.a(Registry.BIOME_REGISTRY, Biome.DIRECT_CODEC); -diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -index 94a02cb23a210ee0cc789db15853b6672ec673f4..73888713746e7ddd72ba9ac9d33d8e616eb3bd25 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -@@ -160,7 +160,7 @@ public class PistonMovingBlockEntity extends BlockEntity implements TickableBloc - private static void moveEntityByPiston(Direction enumdirection, Entity entity, double d0, Direction enumdirection1) { - PistonMovingBlockEntity.NOCLIP.set(enumdirection); - entity.move(MoverType.PISTON, new Vec3(d0 * (double) enumdirection1.getStepX(), d0 * (double) enumdirection1.getStepY(), d0 * (double) enumdirection1.getStepZ())); -- PistonMovingBlockEntity.NOCLIP.set((Object) null); -+ PistonMovingBlockEntity.NOCLIP.set(null); // Paper - decompile fix - } - - private void moveStuckEntities(float f) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java -index 95ad396fc46a587d08b87943aa05dd72d35efd3a..60ce75c7f94c995d3753c40bc8d1ec09b4d37b1a 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java -+++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java -@@ -28,12 +28,12 @@ public abstract class StateHolder { - } else { - Property iblockstate = (Property) entry.getKey(); - -- return iblockstate.getName() + "=" + this.getName(iblockstate, (Comparable) entry.getValue()); -+ return iblockstate.getName() + "=" + this.getName((Property) iblockstate, (Comparable) entry.getValue()); // Paper - decompile fix - } - } - -- private > String getName(Property property, Comparable value) { -- return property.value(value); -+ private > String getName(Property property, T value) { // Paper - decompile error -+ return property.getName(value); - } - }; - protected final O owner; -@@ -48,11 +48,11 @@ public abstract class StateHolder { - } - - public > S cycle(Property property) { -- return this.setValue(property, (Comparable) findNextInCollection(property.getPossibleValues(), (Object) this.getValue(property))); -+ return this.setValue(property, findNextInCollection(property.getPossibleValues(), this.getValue(property))); // Paper - decompile error - } - - protected static T findNextInCollection(Collection values, T value) { -- Iterator iterator = values.iterator(); -+ Iterator iterator = values.iterator(); // Paper - - do { - if (!iterator.hasNext()) { -@@ -94,7 +94,7 @@ public abstract class StateHolder { - if (comparable == null) { - throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner); - } else { -- return (Comparable) property.getValueClass().cast(comparable); -+ return property.getValueClass().cast(comparable); // Paper - decompile error - } - } - -@@ -110,7 +110,7 @@ public abstract class StateHolder { - if (comparable == null) { - throw new IllegalArgumentException("Cannot set property " + property + " as it does not exist in " + this.owner); - } else if (comparable == value) { -- return this; -+ return (S) this; // Paper - decompile error - } else { - S s0 = this.neighbours.get(property, value); - -@@ -162,7 +162,7 @@ public abstract class StateHolder { - return codec.dispatch("Name", (iblockdataholder) -> { - return iblockdataholder.owner; - }, (object) -> { -- S s0 = (StateHolder) ownerToStateFunction.apply(object); -+ S s0 = ownerToStateFunction.apply(object); // Paper - decompile error - - return s0.getValues().isEmpty() ? Codec.unit(s0) : s0.propertiesCodec.fieldOf("Properties").codec(); - }); -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java -index 9e0724c4bf06d207898e477e35412c09f3aa0f74..b5817645727f2af2785e0987ba824f431d4e9e32 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java -@@ -21,10 +21,10 @@ public class EnumProperty & StringRepresentable> extends Prope - protected EnumProperty(String name, Class type, Collection values) { - super(name, type); - this.values = ImmutableSet.copyOf(values); -- Iterator iterator = values.iterator(); -+ Iterator iterator = values.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t0 = (Enum) iterator.next(); -+ T t0 = iterator.next(); // Paper - Decompile fix - String s1 = ((StringRepresentable) t0).getSerializedName(); - - if (this.names.containsKey(s1)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java -index 5a16a0079bc297fb4572d2e6e9b07a9d1a53c906..8cc07c70fde81e44679f3ea7d9a4c6b2447885d4 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java -@@ -17,12 +17,10 @@ public abstract class Property> { - private final Codec> valueCodec; - - protected Property(String name, Class type) { -- this.codec = Codec.STRING.comapFlatMap((s1) -> { -- return (DataResult) this.getValue(s1).map(DataResult::success).orElseGet(() -> { -- return DataResult.error("Unable to read property: " + this + " with value: " + s1); -- }); -- }, this::getName); -- this.valueCodec = this.codec.xmap(this::b, Property.clazz::b); -+ this.codec = Codec.STRING.comapFlatMap((s1) -> this.getValue(s1).map(DataResult::success).orElseGet(() -> { // Paper - decompile error -+ return DataResult.error("Unable to read property: " + this + " with value: " + s1); -+ }), this::getName); -+ this.valueCodec = this.codec.xmap(this::value, (Property.Value param) -> param.value()); // Paper - decompile fix - this.clazz = type; - this.name = name; - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -index 977ac6db5fbdd001c306ee6aa396bb395384dd8f..7de765786b3504dcffab98bb0d9dac64b30b3325 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -@@ -89,7 +89,7 @@ public class IOWorker implements AutoCloseable { - return this.submitTask(() -> { - try { - this.storage.flush(); -- return Either.left((Object) null); -+ return Either.left(null); // Paper - decompile error - } catch (Exception exception) { - IOWorker.LOGGER.warn("Failed to synchronized chunks", exception); - return Either.right(exception); -@@ -123,13 +123,13 @@ public class IOWorker implements AutoCloseable { - } - - private void tellStorePending() { -- this.mailbox.tell((Object) (new StrictQueue.IntRunnable(IOWorker.Priority.LOW.ordinal(), this::storePendingChunk))); -+ this.mailbox.tell((new StrictQueue.IntRunnable(IOWorker.Priority.LOW.ordinal(), this::storePendingChunk))); // Paper - decompile error - } - - private void runStore(ChunkPos pos, IOWorker.PendingStore ioworker_a) { - try { - this.storage.write(pos, ioworker_a.data); -- ioworker_a.result.complete((Object) null); -+ ioworker_a.result.complete(null); // Paper - decompile fix - } catch (Exception exception) { - IOWorker.LOGGER.error("Failed to store chunk {}", pos, exception); - ioworker_a.result.completeExceptionally(exception); -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 217065b88178342159154490ffabe0fe7d32d7bf..2386ffeec60851ba192b89bc6fd7ffff9c56aff5 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -430,7 +430,7 @@ public class EndDragonFight { - } - } - -- worldgenendtrophy.configured((FeatureConfiguration) FeatureConfiguration.NONE).a(this.level, this.level.getChunkSource().getGenerator(), new Random(), this.portalLocation); -+ worldgenendtrophy.configured(FeatureConfiguration.NONE).place(this.level, this.level.getChunkSource().getGenerator(), new Random(), this.portalLocation); // Paper - decompile fix - } - - private EnderDragon createNewDragon() { -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -index 418abfdc85de157d23807059670a2dfc964cbd5f..9f60abfe0a37e30c5528a1ca0546295b00598798 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -@@ -71,13 +71,13 @@ public abstract class StructureFeature { - public static final StructureFeature BASTION_REMNANT = register("Bastion_Remnant", new BastionFeature(JigsawConfiguration.CODEC), GenerationStep.Decoration.SURFACE_STRUCTURES); - public static final List> NOISE_AFFECTING_FEATURES = ImmutableList.of(StructureFeature.PILLAGER_OUTPOST, StructureFeature.VILLAGE, StructureFeature.NETHER_FOSSIL); - private static final ResourceLocation JIGSAW_RENAME = new ResourceLocation("jigsaw"); -- private static final Map RENAMES = ImmutableMap.builder().put(new ResourceLocation("nvi"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("pcp"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("bastionremnant"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("runtime"), StructureFeature.JIGSAW_RENAME).build(); -+ private static final Map RENAMES = ImmutableMap.builder().put(new ResourceLocation("nvi"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("pcp"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("bastionremnant"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("runtime"), StructureFeature.JIGSAW_RENAME).build(); // Paper - decompile fix - private final Codec>> y; - - private static > F register(String name, F structureFeature, GenerationStep.Decoration step) { - StructureFeature.STRUCTURES_REGISTRY.put(name.toLowerCase(Locale.ROOT), structureFeature); - StructureFeature.STEP.put(structureFeature, step); -- return (StructureFeature) Registry.registerDefaulted(Registry.STRUCTURE_FEATURE, name.toLowerCase(Locale.ROOT), (Object) structureFeature); -+ return (F) Registry.>register(Registry.STRUCTURE_FEATURE, name.toLowerCase(Locale.ROOT), structureFeature); // Paper - decomp fix - } - - public StructureFeature(Codec codec) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -index cd2efdd5802605de5d3d636ce1b4a796e0c13310..c304637ae8f80c65b58e8ba8a27609b532bb1184 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -@@ -34,10 +34,10 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage= l) { -diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -index b106f2458361fc2a9168bbef8c9e5b35d8e359fb..60b7fdf9c092e8105d41f4af02a08651624f3eb9 100644 ---- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -+++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -@@ -44,7 +44,7 @@ public class DimensionDataStorage { - if (t0 != null) { - return t0; - } else { -- T t1 = (SavedData) factory.get(); -+ T t1 = factory.get(); // Paper - decompile fix - - this.set(t1); - return t1; -@@ -53,7 +53,7 @@ public class DimensionDataStorage { - - @Nullable - public T get(Supplier factory, String id) { -- SavedData persistentbase = (SavedData) this.cache.get(id); -+ T persistentbase = (T) this.cache.get(id); // Paper - decompile fix - - if (persistentbase == null && !this.cache.containsKey(id)) { - persistentbase = this.readSavedData(factory, id); -@@ -69,7 +69,7 @@ public class DimensionDataStorage { - File file = this.getDataFile(id); - - if (file.exists()) { -- T t0 = (SavedData) factory.get(); -+ T t0 = factory.get(); // Paper - decompile fix - CompoundTag nbttagcompound = this.readTagFromDisk(id, SharedConstants.getCurrentVersion().getWorldVersion()); - - t0.load(nbttagcompound.getCompound("data")); -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java -index 4093a4a1f924ac722d60599be9688a88d26a5c1a..802eb7fe690adae03c80db3fc0f72ea2788a3b2c 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java -@@ -42,7 +42,7 @@ public abstract class LootPoolEntryContainer implements ComposableEntryContainer - - // CraftBukkit start - @Override -- public final void serialize(JsonObject json, T entry, JsonSerializationContext context) { -+ public void serialize(JsonObject json, T entry, JsonSerializationContext context) { // Paper - remove final - if (!org.apache.commons.lang3.ArrayUtils.isEmpty(entry.conditions)) { - json.add("conditions", context.serialize(entry.conditions)); - } -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java -index c942459e0a492dd9fab296ef60d272651d13f049..ceb5e5405ed20c8de954847bbb269109107a43fc 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java -@@ -132,7 +132,7 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer - @Override - public T b(LootItemFunction.Builder lootitemfunction_a) { - this.functions.add(lootitemfunction_a.b()); -- return (LootPoolSingletonContainer.Builder) this.getThis(); -+ return this.getThis(); // Paper - decompile fix - } - - protected LootItemFunction[] getFunctions() { -@@ -141,12 +141,12 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer - - public T setWeight(int weight) { - this.weight = weight; -- return (LootPoolSingletonContainer.Builder) this.getThis(); -+ return this.getThis(); // Paper - decompile fix - } - - public T setQuality(int quality) { - this.quality = quality; -- return (LootPoolSingletonContainer.Builder) this.getThis(); -+ return this.getThis(); // Paper - decompile fix - } - } - -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java -index b77c921548ff55bab62bf37fa411ad1fd8d38f82..a3ce120b0da62f9be938c58c3414ce997f5d30ea 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java -@@ -89,7 +89,7 @@ public class ExplorationMapFunction extends LootItemConditionalFunction { - public Serializer() {} - - public void serialize(JsonObject json, ExplorationMapFunction object, JsonSerializationContext context) { -- super.serialize(json, (LootItemConditionalFunction) object, context); -+ super.serialize(json, object, context); // Paper - decompile fix - if (!object.destination.equals(ExplorationMapFunction.DEFAULT_FEATURE)) { - json.add("destination", context.serialize(object.destination.getFeatureName())); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java -index bc1798f130184d6b107d7a9ba972cab686534439..f0e74daa5bb9e88c028225e7c71deb04c481a7ac 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java -@@ -38,7 +38,7 @@ public final class IndirectMerger implements IndexMerger { - double d1 = flag4 ? first.getDouble(i++) : second.getDouble(j++); - - if ((i != 0 && flag2 || flag4 || includeSecondOnly) && (j != 0 && flag3 || !flag4 || includeFirstOnly)) { -- if (d0 < d1 - 1.0E-7D) { -+ if (!(d0 >= d1 - 1.0E-7D)) { // Paper - decompile error - welcome to hell - this.firstIndices.add(i - 1); - this.secondIndices.add(j - 1); - this.result.add(d1); diff --git a/patches/server/0003-Build-system-changes.patch b/patches/server/0003-Build-system-changes.patch index 3554e7bd36..92b74cc17a 100644 --- a/patches/server/0003-Build-system-changes.patch +++ b/patches/server/0003-Build-system-changes.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Build system changes diff --git a/build.gradle.kts b/build.gradle.kts -index fddf2f440356425d948f40dcf9d9853a374ddc8e..332930391943da8b1601401f70e13f076b205e7c 100644 +index fddf2f440356425d948f40dcf9d9853a374ddc8e..32fee49011b630407d6fd1c66838a833a706741a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,21 +15,24 @@ repositories { @@ -32,7 +32,7 @@ index fddf2f440356425d948f40dcf9d9853a374ddc8e..332930391943da8b1601401f70e13f07 runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") + implementation("co.aikar:cleaner:1.0-SNAPSHOT") // Paper -+ implementation("io.netty:netty-all:4.1.50-Final") // Paper ++ implementation("io.netty:netty-all:4.1.65.Final") // Paper + testImplementation("junit:junit:4.13.1") testImplementation("org.hamcrest:hamcrest-library:1.3") diff --git a/patches/server-remapped/0002-Paper-config-files.patch b/patches/server/0004-Paper-config-files.patch similarity index 87% rename from patches/server-remapped/0002-Paper-config-files.patch rename to patches/server/0004-Paper-config-files.patch index 363f09b241..351a727884 100644 --- a/patches/server-remapped/0002-Paper-config-files.patch +++ b/patches/server/0004-Paper-config-files.patch @@ -7,7 +7,7 @@ Loads each yml file for early init too so it can be used for early options diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java new file mode 100644 -index 0000000000000000000000000000000000000000..d05eeaa711a09bb121b530654821894e795ff4ea +index 0000000000000000000000000000000000000000..94cc5b494cdbc163fb70d0f4a6708d6ca2f42288 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java @@ -0,0 +1,286 @@ @@ -227,7 +227,7 @@ index 0000000000000000000000000000000000000000..d05eeaa711a09bb121b530654821894e + ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); + info.left++; + info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1); -+ if (!chunkProviderServer.isInEntityTickingChunk(e)) { ++ if (!chunkProviderServer.isPositionTicking(e)) { + nonEntityTicking.merge(key, Integer.valueOf(1), Integer::sum); + } + }); @@ -243,7 +243,7 @@ index 0000000000000000000000000000000000000000..d05eeaa711a09bb121b530654821894e + sender.sendMessage("Entity: " + name + " Total Ticking: " + (info.getLeft() - nonTicking) + ", Total Non-Ticking: " + nonTicking); + info.getRight().entrySet().stream() + .sorted((a, b) -> !a.getValue().equals(b.getValue()) ? b.getValue() - a.getValue() : a.getKey().toString().compareTo(b.getKey().toString())) -+ .limit(10).forEach(e -> sender.sendMessage(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z + (chunkProviderServer.isEntityTickingChunk(e.getKey()) ? " (Ticking)" : " (Non-Ticking)"))); ++ .limit(10).forEach(e -> sender.sendMessage(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z + (chunkProviderServer.isPositionTicking(e.getKey().toLong()) ? " (Ticking)" : " (Non-Ticking)"))); + } else { + List> info = list.entrySet().stream() + .filter(e -> names.contains(e.getKey())) @@ -563,11 +563,11 @@ index 0000000000000000000000000000000000000000..b31109d2dadd29e8852468c19265066b + } +} diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 9366b5551047e87e455fafbf45be5fb145aa875b..5d83a8d4c69144219219877c521c364d912d2452 100644 +index 1707449cbbfa5eab585657cdde811b34a92e1d17..c8385460701395cb5c65fba41335469ffb2d9b9a 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java -@@ -95,6 +95,12 @@ public class Main { - DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(iregistrycustom_dimension, optionset); // CraftBukkit - CLI argument support +@@ -101,6 +101,12 @@ public class Main { + DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(optionset); // CraftBukkit - CLI argument support dedicatedserversettings.forceSave(); + // Paper start - load config files for access below if needed @@ -576,10 +576,10 @@ index 9366b5551047e87e455fafbf45be5fb145aa875b..5d83a8d4c69144219219877c521c364d + org.bukkit.configuration.file.YamlConfiguration paperConfiguration = loadConfigFile((File) optionset.valueOf("paper-settings")); + // Paper end + - java.nio.file.Path java_nio_file_path1 = Paths.get("eula.txt"); - Eula eula = new Eula(java_nio_file_path1); + Path path1 = Paths.get("eula.txt"); + Eula eula = new Eula(path1); -@@ -236,6 +242,20 @@ public class Main { +@@ -251,6 +257,20 @@ public class Main { } @@ -601,10 +601,10 @@ index 9366b5551047e87e455fafbf45be5fb145aa875b..5d83a8d4c69144219219877c521c364d Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, worlds, eraseCache); diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 2228f83f251851aa683f739ac5ce2ec98f059f3f..23d6f803eafa78fd51ea4cdc4ca25c78661bc80b 100644 +index 7bad75bd86fcb484e253fca8077d017d3161158b..fe83f13d71f84591f5506e1c6b9dfbf9fba680bd 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -184,6 +184,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -193,6 +193,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); org.spigotmc.SpigotConfig.registerCommands(); // Spigot end @@ -621,44 +621,45 @@ index 2228f83f251851aa683f739ac5ce2ec98f059f3f..23d6f803eafa78fd51ea4cdc4ca25c78 this.setPvpAllowed(dedicatedserverproperties.pvp); this.setFlightAllowed(dedicatedserverproperties.allowFlight); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index aa7bf54e4b93a9b6085aa943500f5dec5f60a117..7cc5070f70a4f740add9d971385ceaa4d44275a2 100644 +index 108432435aac34fadfd899941e6d2b951f509971..623b938177cc7287bccc55f34e644bda984a7b65 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -307,15 +307,15 @@ public class ServerChunkCache extends ChunkSource { +@@ -23,6 +23,7 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; + import net.minecraft.network.protocol.Packet; + import net.minecraft.server.level.progress.ChunkProgressListener; ++import net.minecraft.util.Mth; + import net.minecraft.util.VisibleForDebug; + import net.minecraft.util.profiling.ProfilerFiller; + import net.minecraft.util.thread.BlockableEventLoop; +@@ -334,6 +335,12 @@ public class ServerChunkCache extends ChunkSource { } } -- @Override -- public boolean isEntityTickingChunk(Entity entity) { -+ public final boolean isInEntityTickingChunk(Entity entity) { return this.isEntityTickingChunk(entity); } // Paper - OBFHELPER -+ @Override public boolean isEntityTickingChunk(Entity entity) { - long i = ChunkPos.asLong(Mth.floor(entity.getX()) >> 4, Mth.floor(entity.getZ()) >> 4); - - return this.checkChunkFuture(i, (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error ++ // Paper start - helper ++ public boolean isPositionTicking(Entity entity) { ++ return this.isPositionTicking(ChunkPos.asLong(Mth.floor(entity.getX()) >> 4, Mth.floor(entity.getZ()) >> 4)); ++ } ++ // Paper end ++ + public boolean isPositionTicking(long i) { + return this.checkChunkFuture(i, (Function>>) ChunkHolder::getTickingChunkFuture); // CraftBukkit - decompile error } - -- @Override -- public boolean isEntityTickingChunk(ChunkPos pos) { -+ public final boolean isEntityTickingChunk(ChunkPos chunkcoordintpair) { return this.isEntityTickingChunk(chunkcoordintpair); } // Paper - OBFHELPER -+ @Override public boolean isEntityTickingChunk(ChunkPos pos) { - return this.checkChunkFuture(pos.toLong(), (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error - } - diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index f82fd4a50921c3c4791be18a43778e6fd216f557..ff482d0349c18d0d1ba902ea0d10611b1ca4e588 100644 +index 067216078c7b50390957d1fcfbfbaaeb81cfba21..7f3d83d3d071f6b441ad119b1c93be035e911e70 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -2,6 +2,7 @@ package net.minecraft.world.entity; - - import com.google.common.collect.ImmutableSet; +@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableSet; + import java.util.List; import java.util.Optional; + import java.util.Spliterator; +import java.util.Set; // Paper import java.util.UUID; + import java.util.function.Consumer; import java.util.function.Function; - import java.util.stream.Stream; -@@ -599,4 +600,10 @@ public class EntityType { - return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval); - } +@@ -666,4 +667,10 @@ public class EntityType implements EntityTypeTest { + + T create(EntityType type, Level world); } + + // Paper start @@ -668,10 +669,10 @@ index f82fd4a50921c3c4791be18a43778e6fd216f557..ff482d0349c18d0d1ba902ea0d10611b + // Paper end } diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index b7c64fcf49ea50fa38a121d906ec6df20a1be31b..f08de81dcc4acd5a3e44407b431ce827a19b2e9c 100644 +index b2083d26e3b239d0f26da77955db6a34b622a1bb..90854842fda0f91ac68c70efbcf8ad9e3297ceb4 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -129,6 +129,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -146,6 +146,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public boolean populating; public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot @@ -680,7 +681,7 @@ index b7c64fcf49ea50fa38a121d906ec6df20a1be31b..f08de81dcc4acd5a3e44407b431ce827 public final SpigotTimings.WorldTimingsHandler timings; // Spigot public static BlockPos lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; -@@ -149,6 +151,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -166,6 +168,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot @@ -689,35 +690,35 @@ index b7c64fcf49ea50fa38a121d906ec6df20a1be31b..f08de81dcc4acd5a3e44407b431ce827 this.world = new CraftWorld((ServerLevel) this, gen, env); this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns(); // CraftBukkit diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 761ad2d7e538d1e299d3050446274addcde7d772..328d1e2b128b62f24917719c79823c9fb64a0dcf 100644 +index 69617d4da7d69fa45e189dc4b94fbd136e5d547c..743c9f11dbbb66db97bcb3b8fecd97290a7c9f61 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -806,6 +806,7 @@ public final class CraftServer implements Server { +@@ -809,6 +809,7 @@ public final class CraftServer implements Server { } org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot + com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper - for (ServerLevel world : console.getAllLevels()) { - world.worldDataServer.setDifficulty(config.difficulty); + for (ServerLevel world : this.console.getAllLevels()) { + world.serverLevelData.setDifficulty(config.difficulty); world.setSpawnSettings(config.spawnMonsters, config.spawnAnimals); -@@ -839,6 +840,7 @@ public final class CraftServer implements Server { +@@ -842,6 +843,7 @@ public final class CraftServer implements Server { world.ticksPerAmbientSpawns = this.getTicksPerAmbientSpawns(); } world.spigotConfig.init(); // Spigot + world.paperConfig.init(); // Paper } - pluginManager.clearPlugins(); -@@ -846,6 +848,7 @@ public final class CraftServer implements Server { - resetRecipes(); - reloadData(); + this.pluginManager.clearPlugins(); +@@ -849,6 +851,7 @@ public final class CraftServer implements Server { + this.resetRecipes(); + this.reloadData(); org.spigotmc.SpigotConfig.registerCommands(); // Spigot + com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper - overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); - ignoreVanillaPermissions = commandsConfiguration.getBoolean("ignore-vanilla-permissions"); + this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); + this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); -@@ -2101,4 +2104,35 @@ public final class CraftServer implements Server { - return spigot; +@@ -2104,4 +2107,35 @@ public final class CraftServer implements Server { + return this.spigot; } // Spigot end + @@ -753,7 +754,7 @@ index 761ad2d7e538d1e299d3050446274addcde7d772..328d1e2b128b62f24917719c79823c9f + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 46a16e31775b28c44f95a8ac5545ebcb656c74b6..05aedca561919a12ced1925c5cc9af585bb04523 100644 +index 24e08ca0fca3e87f8a6b7670b266f3c2900b798c..3c4281ad770598ecf3b9fae0d6ed6e9130136dbb 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -129,6 +129,14 @@ public class Main { @@ -772,49 +773,49 @@ index 46a16e31775b28c44f95a8ac5545ebcb656c74b6..05aedca561919a12ced1925c5cc9af58 }; diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 83d83ff7ceffbb77723da721b869dfd0091e496d..0efcbab8f8806aeb8dd8bd6384e5a7cee375d100 100644 +index c7bfa5fe5f7945883bd41461247e0efb04f5e9e8..9a31d8b709b28bba658603106c623560c5362947 100644 --- a/src/main/java/org/spigotmc/SpigotWorldConfig.java +++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java @@ -39,36 +39,36 @@ public class SpigotWorldConfig - config.set( "world-settings.default." + path, val ); + this.config.set( "world-settings.default." + path, val ); } - private boolean getBoolean(String path, boolean def) + public boolean getBoolean(String path, boolean def) // Paper - private -> public { - config.addDefault( "world-settings.default." + path, def ); - return config.getBoolean( "world-settings." + worldName + "." + path, config.getBoolean( "world-settings.default." + path ) ); + this.config.addDefault( "world-settings.default." + path, def ); + return this.config.getBoolean( "world-settings." + this.worldName + "." + path, this.config.getBoolean( "world-settings.default." + path ) ); } - private double getDouble(String path, double def) + public double getDouble(String path, double def) // Paper - private -> public { - config.addDefault( "world-settings.default." + path, def ); - return config.getDouble( "world-settings." + worldName + "." + path, config.getDouble( "world-settings.default." + path ) ); + this.config.addDefault( "world-settings.default." + path, def ); + return this.config.getDouble( "world-settings." + this.worldName + "." + path, this.config.getDouble( "world-settings.default." + path ) ); } - private int getInt(String path) + public int getInt(String path) // Paper - private -> public { - return config.getInt( "world-settings." + worldName + "." + path ); + return this.config.getInt( "world-settings." + this.worldName + "." + path ); } - private int getInt(String path, int def) + public int getInt(String path, int def) // Paper - private -> public { - config.addDefault( "world-settings.default." + path, def ); - return config.getInt( "world-settings." + worldName + "." + path, config.getInt( "world-settings.default." + path ) ); + this.config.addDefault( "world-settings.default." + path, def ); + return this.config.getInt( "world-settings." + this.worldName + "." + path, this.config.getInt( "world-settings.default." + path ) ); } - private List getList(String path, T def) + public List getList(String path, T def) // Paper - private -> public { - config.addDefault( "world-settings.default." + path, def ); - return (List) config.getList( "world-settings." + worldName + "." + path, config.getList( "world-settings.default." + path ) ); + this.config.addDefault( "world-settings.default." + path, def ); + return (List) this.config.getList( "world-settings." + this.worldName + "." + path, this.config.getList( "world-settings.default." + path ) ); } - private String getString(String path, String def) + public String getString(String path, String def) // Paper - private -> public { - config.addDefault( "world-settings.default." + path, def ); - return config.getString( "world-settings." + worldName + "." + path, config.getString( "world-settings.default." + path ) ); + this.config.addDefault( "world-settings.default." + path, def ); + return this.config.getString( "world-settings." + this.worldName + "." + path, this.config.getString( "world-settings.default." + path ) ); diff --git a/patches/server/0005-MC-Dev-fixes.patch b/patches/server/0005-MC-Dev-fixes.patch new file mode 100644 index 0000000000..4b44bab5c1 --- /dev/null +++ b/patches/server/0005-MC-Dev-fixes.patch @@ -0,0 +1,358 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 30 Mar 2016 19:36:20 -0400 +Subject: [PATCH] MC Dev fixes + + +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index 255b39848a4071775a7f2f0dd2e54eb4be18e109..8ba68f03c1dd87826185808e9e7080647a55c2dd 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -306,7 +306,7 @@ public class Util { + } + + public static Strategy identityStrategy() { +- return Util.IdentityStrategy.INSTANCE; ++ return (Strategy) Util.IdentityStrategy.INSTANCE; // Paper - decompile fix + } + + public static CompletableFuture> sequence(List> futures) { +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 1bd6ef643b17b059eb525035496b816a098279c4..3cf71f85da94bcda5d4527b5f3e18d959c6c4634 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -367,12 +367,12 @@ public class BlockPos extends Vec3i { + if (this.index == l) { + return this.endOfData(); + } else { +- int i = this.index % i; +- int j = this.index / i; +- int k = j % j; +- int l = j / j; ++ int offsetX = this.index % i; // Paper - decomp fix ++ int u = this.index / i; // Paper - decomp fix ++ int offsetY = u % j; // Paper - decomp fix ++ int offsetZ = u / j; // Paper - decomp fix + ++this.index; +- return this.cursor.set(startX + i, startY + k, startZ + l); ++ return this.cursor.set(startX + offsetX, startY + offsetY, startZ + offsetZ); // Paper - decomp fix + } + } + }; +diff --git a/src/main/java/net/minecraft/nbt/ListTag.java b/src/main/java/net/minecraft/nbt/ListTag.java +index 2f8443ba50d34ff961ae5345c470e809c720fd29..88bac72edf19c578902f49d20353989ed4d96f8f 100644 +--- a/src/main/java/net/minecraft/nbt/ListTag.java ++++ b/src/main/java/net/minecraft/nbt/ListTag.java +@@ -2,9 +2,13 @@ package net.minecraft.nbt; + + import com.google.common.collect.Iterables; + import com.google.common.collect.Lists; ++import it.unimi.dsi.fastutil.bytes.ByteOpenHashSet; ++import it.unimi.dsi.fastutil.bytes.ByteSet; ++ + import java.io.DataInput; + import java.io.DataOutput; + import java.io.IOException; ++import java.util.Arrays; + import java.util.List; + import java.util.Objects; + +@@ -45,6 +49,7 @@ public class ListTag extends CollectionTag { + return "TAG_List"; + } + }; ++ private static final ByteSet INLINE_ELEMENT_TYPES = new ByteOpenHashSet(Arrays.asList((byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6)); // Paper - decompiler fix + private final List list; + private byte type; + +diff --git a/src/main/java/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java +index 58443139562d1f90465be43e9be42f5cca7fc80d..0f4d9e94438d62cb5eeb9ca0e430d8dd7ba54ef7 100644 +--- a/src/main/java/net/minecraft/nbt/NbtIo.java ++++ b/src/main/java/net/minecraft/nbt/NbtIo.java +@@ -19,6 +19,7 @@ import javax.annotation.Nullable; + import net.minecraft.CrashReport; + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; ++import io.netty.buffer.ByteBufInputStream; // Paper + + public class NbtIo { + +@@ -180,7 +181,7 @@ public class NbtIo { + + public static CompoundTag read(DataInput input, NbtAccounter tracker) throws IOException { + // Spigot start +- if ( input instanceof io.netty.buffer.ByteBufInputStream ) ++ if ( input instanceof ByteBufInputStream) // Paper + { + input = new DataInputStream(new org.spigotmc.LimitStream((InputStream) input, tracker)); + } +diff --git a/src/main/java/net/minecraft/nbt/Tag.java b/src/main/java/net/minecraft/nbt/Tag.java +index 440aa82b4488ed20f9fcf60f1e87cc84ea74e370..08a0327feacd81c6e4c66182cee926c6068b8aa8 100644 +--- a/src/main/java/net/minecraft/nbt/Tag.java ++++ b/src/main/java/net/minecraft/nbt/Tag.java +@@ -33,7 +33,7 @@ public interface Tag { + + TagType getType(); + +- Tag copy(); ++ public Tag copy(); // Paper - decompile fix + + default String getAsString() { + return (new StringTagVisitor()).visit(this); +diff --git a/src/main/java/net/minecraft/network/ConnectionProtocol.java b/src/main/java/net/minecraft/network/ConnectionProtocol.java +index 6b66e1ad66dccacb5c959da924d7857358488678..e722cf3a8e816b0c7405e6282591d9fa8d5bfa61 100644 +--- a/src/main/java/net/minecraft/network/ConnectionProtocol.java ++++ b/src/main/java/net/minecraft/network/ConnectionProtocol.java +@@ -12,6 +12,7 @@ import javax.annotation.Nullable; + import net.minecraft.Util; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketFlow; ++import net.minecraft.network.protocol.game.ClientGamePacketListener; + import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; + import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; + import net.minecraft.network.protocol.game.ClientboundAddMobPacket; +@@ -113,6 +114,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket; ++import net.minecraft.network.protocol.game.ServerGamePacketListener; + import net.minecraft.network.protocol.game.ServerboundAcceptTeleportationPacket; + import net.minecraft.network.protocol.game.ServerboundBlockEntityTagQuery; + import net.minecraft.network.protocol.game.ServerboundChangeDifficultyPacket; +@@ -159,25 +161,32 @@ import net.minecraft.network.protocol.game.ServerboundTeleportToEntityPacket; + import net.minecraft.network.protocol.game.ServerboundUseItemOnPacket; + import net.minecraft.network.protocol.game.ServerboundUseItemPacket; + import net.minecraft.network.protocol.handshake.ClientIntentionPacket; ++import net.minecraft.network.protocol.handshake.ServerHandshakePacketListener; ++import net.minecraft.network.protocol.login.ClientLoginPacketListener; + import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; + import net.minecraft.network.protocol.login.ClientboundGameProfilePacket; + import net.minecraft.network.protocol.login.ClientboundHelloPacket; + import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; + import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; ++import net.minecraft.network.protocol.login.ServerLoginPacketListener; + import net.minecraft.network.protocol.login.ServerboundCustomQueryPacket; + import net.minecraft.network.protocol.login.ServerboundHelloPacket; + import net.minecraft.network.protocol.login.ServerboundKeyPacket; ++import net.minecraft.network.protocol.status.ClientStatusPacketListener; + import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; + import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; ++import net.minecraft.network.protocol.status.ServerStatusPacketListener; + import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; + import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; + import org.apache.logging.log4j.LogManager; + + public enum ConnectionProtocol { +- HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))), +- PLAY(0, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new).addPacket(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new).addPacket(ClientboundAddMobPacket.class, ClientboundAddMobPacket::new).addPacket(ClientboundAddPaintingPacket.class, ClientboundAddPaintingPacket::new).addPacket(ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new).addPacket(ClientboundAddVibrationSignalPacket.class, ClientboundAddVibrationSignalPacket::new).addPacket(ClientboundAnimatePacket.class, ClientboundAnimatePacket::new).addPacket(ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new).addPacket(ClientboundBlockBreakAckPacket.class, ClientboundBlockBreakAckPacket::new).addPacket(ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new).addPacket(ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new).addPacket(ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new).addPacket(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new).addPacket(ClientboundBossEventPacket.class, ClientboundBossEventPacket::new).addPacket(ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new).addPacket(ClientboundChatPacket.class, ClientboundChatPacket::new).addPacket(ClientboundClearTitlesPacket.class, ClientboundClearTitlesPacket::new).addPacket(ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new).addPacket(ClientboundCommandsPacket.class, ClientboundCommandsPacket::new).addPacket(ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new).addPacket(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new).addPacket(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new).addPacket(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new).addPacket(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new).addPacket(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new).addPacket(ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new).addPacket(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new).addPacket(ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new).addPacket(ClientboundExplodePacket.class, ClientboundExplodePacket::new).addPacket(ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new).addPacket(ClientboundGameEventPacket.class, ClientboundGameEventPacket::new).addPacket(ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new).addPacket(ClientboundInitializeBorderPacket.class, ClientboundInitializeBorderPacket::new).addPacket(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new).addPacket(ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new).addPacket(ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new).addPacket(ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new).addPacket(ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new).addPacket(ClientboundLoginPacket.class, ClientboundLoginPacket::new).addPacket(ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new).addPacket(ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new).addPacket(ClientboundMoveEntityPacket.Pos.class, ClientboundMoveEntityPacket.Pos::read).addPacket(ClientboundMoveEntityPacket.PosRot.class, ClientboundMoveEntityPacket.PosRot::read).addPacket(ClientboundMoveEntityPacket.Rot.class, ClientboundMoveEntityPacket.Rot::read).addPacket(ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new).addPacket(ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new).addPacket(ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new).addPacket(ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new).addPacket(ClientboundPingPacket.class, ClientboundPingPacket::new).addPacket(ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new).addPacket(ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new).addPacket(ClientboundPlayerCombatEndPacket.class, ClientboundPlayerCombatEndPacket::new).addPacket(ClientboundPlayerCombatEnterPacket.class, ClientboundPlayerCombatEnterPacket::new).addPacket(ClientboundPlayerCombatKillPacket.class, ClientboundPlayerCombatKillPacket::new).addPacket(ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new).addPacket(ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new).addPacket(ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new).addPacket(ClientboundRecipePacket.class, ClientboundRecipePacket::new).addPacket(ClientboundRemoveEntityPacket.class, ClientboundRemoveEntityPacket::new).addPacket(ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new).addPacket(ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new).addPacket(ClientboundRespawnPacket.class, ClientboundRespawnPacket::new).addPacket(ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new).addPacket(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new).addPacket(ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new).addPacket(ClientboundSetActionBarTextPacket.class, ClientboundSetActionBarTextPacket::new).addPacket(ClientboundSetBorderCenterPacket.class, ClientboundSetBorderCenterPacket::new).addPacket(ClientboundSetBorderLerpSizePacket.class, ClientboundSetBorderLerpSizePacket::new).addPacket(ClientboundSetBorderSizePacket.class, ClientboundSetBorderSizePacket::new).addPacket(ClientboundSetBorderWarningDelayPacket.class, ClientboundSetBorderWarningDelayPacket::new).addPacket(ClientboundSetBorderWarningDistancePacket.class, ClientboundSetBorderWarningDistancePacket::new).addPacket(ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new).addPacket(ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new).addPacket(ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new).addPacket(ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new).addPacket(ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new).addPacket(ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new).addPacket(ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new).addPacket(ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new).addPacket(ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new).addPacket(ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new).addPacket(ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new).addPacket(ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new).addPacket(ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new).addPacket(ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new).addPacket(ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new).addPacket(ClientboundSetScorePacket.class, ClientboundSetScorePacket::new).addPacket(ClientboundSetSubtitleTextPacket.class, ClientboundSetSubtitleTextPacket::new).addPacket(ClientboundSetTimePacket.class, ClientboundSetTimePacket::new).addPacket(ClientboundSetTitleTextPacket.class, ClientboundSetTitleTextPacket::new).addPacket(ClientboundSetTitlesAnimationPacket.class, ClientboundSetTitlesAnimationPacket::new).addPacket(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new).addPacket(ClientboundSoundPacket.class, ClientboundSoundPacket::new).addPacket(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new).addPacket(ClientboundTabListPacket.class, ClientboundTabListPacket::new).addPacket(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new).addPacket(ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new).addPacket(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new).addPacket(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new).addPacket(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new).addPacket(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new).addPacket(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new).addPacket(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new).addPacket(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new).addPacket(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new).addPacket(ServerboundChatPacket.class, ServerboundChatPacket::new).addPacket(ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new).addPacket(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new).addPacket(ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new).addPacket(ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new).addPacket(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new).addPacket(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new).addPacket(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new).addPacket(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new).addPacket(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new).addPacket(ServerboundInteractPacket.class, ServerboundInteractPacket::new).addPacket(ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new).addPacket(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new).addPacket(ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new).addPacket(ServerboundMovePlayerPacket.Pos.class, ServerboundMovePlayerPacket.Pos::read).addPacket(ServerboundMovePlayerPacket.PosRot.class, ServerboundMovePlayerPacket.PosRot::read).addPacket(ServerboundMovePlayerPacket.Rot.class, ServerboundMovePlayerPacket.Rot::read).addPacket(ServerboundMovePlayerPacket.StatusOnly.class, ServerboundMovePlayerPacket.StatusOnly::read).addPacket(ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new).addPacket(ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new).addPacket(ServerboundPickItemPacket.class, ServerboundPickItemPacket::new).addPacket(ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new).addPacket(ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new).addPacket(ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new).addPacket(ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new).addPacket(ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new).addPacket(ServerboundPongPacket.class, ServerboundPongPacket::new).addPacket(ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new).addPacket(ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new).addPacket(ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new).addPacket(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new).addPacket(ServerboundSeenAdvancementsPacket.class, ServerboundSeenAdvancementsPacket::new).addPacket(ServerboundSelectTradePacket.class, ServerboundSelectTradePacket::new).addPacket(ServerboundSetBeaconPacket.class, ServerboundSetBeaconPacket::new).addPacket(ServerboundSetCarriedItemPacket.class, ServerboundSetCarriedItemPacket::new).addPacket(ServerboundSetCommandBlockPacket.class, ServerboundSetCommandBlockPacket::new).addPacket(ServerboundSetCommandMinecartPacket.class, ServerboundSetCommandMinecartPacket::new).addPacket(ServerboundSetCreativeModeSlotPacket.class, ServerboundSetCreativeModeSlotPacket::new).addPacket(ServerboundSetJigsawBlockPacket.class, ServerboundSetJigsawBlockPacket::new).addPacket(ServerboundSetStructureBlockPacket.class, ServerboundSetStructureBlockPacket::new).addPacket(ServerboundSignUpdatePacket.class, ServerboundSignUpdatePacket::new).addPacket(ServerboundSwingPacket.class, ServerboundSwingPacket::new).addPacket(ServerboundTeleportToEntityPacket.class, ServerboundTeleportToEntityPacket::new).addPacket(ServerboundUseItemOnPacket.class, ServerboundUseItemOnPacket::new).addPacket(ServerboundUseItemPacket.class, ServerboundUseItemPacket::new))), +- STATUS(1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new).addPacket(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)).addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new).addPacket(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new))), +- LOGIN(2, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new).addPacket(ClientboundHelloPacket.class, ClientboundHelloPacket::new).addPacket(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new).addPacket(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new).addPacket(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new).addPacket(ServerboundKeyPacket.class, ServerboundKeyPacket::new).addPacket(ServerboundCustomQueryPacket.class, ServerboundCustomQueryPacket::new))); ++ // Paper start - fix decompile error - add correct generic packet listeners (e.g. ServerHandshakePacketListener) to PacketSet's generic type, matching the packet flow direction ++ HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))), ++ PLAY(0, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new).addPacket(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new).addPacket(ClientboundAddMobPacket.class, ClientboundAddMobPacket::new).addPacket(ClientboundAddPaintingPacket.class, ClientboundAddPaintingPacket::new).addPacket(ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new).addPacket(ClientboundAddVibrationSignalPacket.class, ClientboundAddVibrationSignalPacket::new).addPacket(ClientboundAnimatePacket.class, ClientboundAnimatePacket::new).addPacket(ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new).addPacket(ClientboundBlockBreakAckPacket.class, ClientboundBlockBreakAckPacket::new).addPacket(ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new).addPacket(ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new).addPacket(ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new).addPacket(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new).addPacket(ClientboundBossEventPacket.class, ClientboundBossEventPacket::new).addPacket(ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new).addPacket(ClientboundChatPacket.class, ClientboundChatPacket::new).addPacket(ClientboundClearTitlesPacket.class, ClientboundClearTitlesPacket::new).addPacket(ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new).addPacket(ClientboundCommandsPacket.class, ClientboundCommandsPacket::new).addPacket(ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new).addPacket(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new).addPacket(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new).addPacket(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new).addPacket(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new).addPacket(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new).addPacket(ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new).addPacket(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new).addPacket(ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new).addPacket(ClientboundExplodePacket.class, ClientboundExplodePacket::new).addPacket(ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new).addPacket(ClientboundGameEventPacket.class, ClientboundGameEventPacket::new).addPacket(ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new).addPacket(ClientboundInitializeBorderPacket.class, ClientboundInitializeBorderPacket::new).addPacket(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new).addPacket(ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new).addPacket(ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new).addPacket(ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new).addPacket(ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new).addPacket(ClientboundLoginPacket.class, ClientboundLoginPacket::new).addPacket(ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new).addPacket(ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new).addPacket(ClientboundMoveEntityPacket.Pos.class, ClientboundMoveEntityPacket.Pos::read).addPacket(ClientboundMoveEntityPacket.PosRot.class, ClientboundMoveEntityPacket.PosRot::read).addPacket(ClientboundMoveEntityPacket.Rot.class, ClientboundMoveEntityPacket.Rot::read).addPacket(ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new).addPacket(ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new).addPacket(ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new).addPacket(ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new).addPacket(ClientboundPingPacket.class, ClientboundPingPacket::new).addPacket(ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new).addPacket(ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new).addPacket(ClientboundPlayerCombatEndPacket.class, ClientboundPlayerCombatEndPacket::new).addPacket(ClientboundPlayerCombatEnterPacket.class, ClientboundPlayerCombatEnterPacket::new).addPacket(ClientboundPlayerCombatKillPacket.class, ClientboundPlayerCombatKillPacket::new).addPacket(ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new).addPacket(ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new).addPacket(ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new).addPacket(ClientboundRecipePacket.class, ClientboundRecipePacket::new).addPacket(ClientboundRemoveEntityPacket.class, ClientboundRemoveEntityPacket::new).addPacket(ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new).addPacket(ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new).addPacket(ClientboundRespawnPacket.class, ClientboundRespawnPacket::new).addPacket(ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new).addPacket(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new).addPacket(ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new).addPacket(ClientboundSetActionBarTextPacket.class, ClientboundSetActionBarTextPacket::new).addPacket(ClientboundSetBorderCenterPacket.class, ClientboundSetBorderCenterPacket::new).addPacket(ClientboundSetBorderLerpSizePacket.class, ClientboundSetBorderLerpSizePacket::new).addPacket(ClientboundSetBorderSizePacket.class, ClientboundSetBorderSizePacket::new).addPacket(ClientboundSetBorderWarningDelayPacket.class, ClientboundSetBorderWarningDelayPacket::new).addPacket(ClientboundSetBorderWarningDistancePacket.class, ClientboundSetBorderWarningDistancePacket::new).addPacket(ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new).addPacket(ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new).addPacket(ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new).addPacket(ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new).addPacket(ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new).addPacket(ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new).addPacket(ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new).addPacket(ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new).addPacket(ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new).addPacket(ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new).addPacket(ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new).addPacket(ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new).addPacket(ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new).addPacket(ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new).addPacket(ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new).addPacket(ClientboundSetScorePacket.class, ClientboundSetScorePacket::new).addPacket(ClientboundSetSubtitleTextPacket.class, ClientboundSetSubtitleTextPacket::new).addPacket(ClientboundSetTimePacket.class, ClientboundSetTimePacket::new).addPacket(ClientboundSetTitleTextPacket.class, ClientboundSetTitleTextPacket::new).addPacket(ClientboundSetTitlesAnimationPacket.class, ClientboundSetTitlesAnimationPacket::new).addPacket(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new).addPacket(ClientboundSoundPacket.class, ClientboundSoundPacket::new).addPacket(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new).addPacket(ClientboundTabListPacket.class, ClientboundTabListPacket::new).addPacket(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new).addPacket(ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new).addPacket(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new).addPacket(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new).addPacket(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new).addPacket(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new).addPacket(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new).addPacket(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new).addPacket(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new).addPacket(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new).addPacket(ServerboundChatPacket.class, ServerboundChatPacket::new).addPacket(ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new).addPacket(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new).addPacket(ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new).addPacket(ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new).addPacket(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new).addPacket(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new).addPacket(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new).addPacket(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new).addPacket(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new).addPacket(ServerboundInteractPacket.class, ServerboundInteractPacket::new).addPacket(ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new).addPacket(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new).addPacket(ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new).addPacket(ServerboundMovePlayerPacket.Pos.class, ServerboundMovePlayerPacket.Pos::read).addPacket(ServerboundMovePlayerPacket.PosRot.class, ServerboundMovePlayerPacket.PosRot::read).addPacket(ServerboundMovePlayerPacket.Rot.class, ServerboundMovePlayerPacket.Rot::read).addPacket(ServerboundMovePlayerPacket.StatusOnly.class, ServerboundMovePlayerPacket.StatusOnly::read).addPacket(ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new).addPacket(ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new).addPacket(ServerboundPickItemPacket.class, ServerboundPickItemPacket::new).addPacket(ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new).addPacket(ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new).addPacket(ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new).addPacket(ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new).addPacket(ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new).addPacket(ServerboundPongPacket.class, ServerboundPongPacket::new).addPacket(ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new).addPacket(ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new).addPacket(ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new).addPacket(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new).addPacket(ServerboundSeenAdvancementsPacket.class, ServerboundSeenAdvancementsPacket::new).addPacket(ServerboundSelectTradePacket.class, ServerboundSelectTradePacket::new).addPacket(ServerboundSetBeaconPacket.class, ServerboundSetBeaconPacket::new).addPacket(ServerboundSetCarriedItemPacket.class, ServerboundSetCarriedItemPacket::new).addPacket(ServerboundSetCommandBlockPacket.class, ServerboundSetCommandBlockPacket::new).addPacket(ServerboundSetCommandMinecartPacket.class, ServerboundSetCommandMinecartPacket::new).addPacket(ServerboundSetCreativeModeSlotPacket.class, ServerboundSetCreativeModeSlotPacket::new).addPacket(ServerboundSetJigsawBlockPacket.class, ServerboundSetJigsawBlockPacket::new).addPacket(ServerboundSetStructureBlockPacket.class, ServerboundSetStructureBlockPacket::new).addPacket(ServerboundSignUpdatePacket.class, ServerboundSignUpdatePacket::new).addPacket(ServerboundSwingPacket.class, ServerboundSwingPacket::new).addPacket(ServerboundTeleportToEntityPacket.class, ServerboundTeleportToEntityPacket::new).addPacket(ServerboundUseItemOnPacket.class, ServerboundUseItemOnPacket::new).addPacket(ServerboundUseItemPacket.class, ServerboundUseItemPacket::new))), ++ STATUS(1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new).addPacket(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)).addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new).addPacket(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new))), ++ LOGIN(2, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new).addPacket(ClientboundHelloPacket.class, ClientboundHelloPacket::new).addPacket(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new).addPacket(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new).addPacket(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new).addPacket(ServerboundKeyPacket.class, ServerboundKeyPacket::new).addPacket(ServerboundCustomQueryPacket.class, ServerboundCustomQueryPacket::new))); ++ // Paper end + + private static final int MIN_PROTOCOL_ID = -1; + private static final int MAX_PROTOCOL_ID = 2; +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 8ae7218512a7aa7c26c49da83cbb923ba0ecdf09..ecb775edb17d629855f1be37943f9bc933d93d63 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1765,7 +1765,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoopmap(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error + }, this).thenCompose((immutablelist) -> { + return ServerResources.loadResources(immutablelist, this.registryHolder, this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this); + }).thenAcceptAsync((datapackresources) -> { +diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java +index 2f66abf62d303342f5fe614fb3e35e7844497ffc..b346fa94b23d81da7da073f71dd12e672e0f079c 100644 +--- a/src/main/java/net/minecraft/server/level/Ticket.java ++++ b/src/main/java/net/minecraft/server/level/Ticket.java +@@ -21,7 +21,7 @@ public final class Ticket implements Comparable> { + return i; + } else { + int j = Integer.compare(System.identityHashCode(this.type), System.identityHashCode(ticket.type)); +- return j != 0 ? j : this.type.getComparator().compare(this.key, ticket.key); ++ return j != 0 ? j : this.type.getComparator().compare(this.key, (T)ticket.key); // Paper - decompile fix + } + } + +diff --git a/src/main/java/net/minecraft/stats/ServerStatsCounter.java b/src/main/java/net/minecraft/stats/ServerStatsCounter.java +index ee5bb1a8edb812d48d5af45ea8485f574dcb2ad5..9f3355dbbbab1ab88cf2b7034130c2888e38d7a7 100644 +--- a/src/main/java/net/minecraft/stats/ServerStatsCounter.java ++++ b/src/main/java/net/minecraft/stats/ServerStatsCounter.java +@@ -206,7 +206,7 @@ public class ServerStatsCounter extends StatsCounter { + ObjectIterator objectiterator = this.stats.object2IntEntrySet().iterator(); + + while (objectiterator.hasNext()) { +- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); ++ Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix + Stat statistic = (Stat) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); + + ((JsonObject) map.computeIfAbsent(statistic.getType(), (statisticwrapper) -> { +diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java +index d0f6eb3981a171c0f34870cb0472599d6cca9642..d1b2ba24ef54e01c6249c3b2ca16e80f03c001a6 100644 +--- a/src/main/java/net/minecraft/util/SortedArraySet.java ++++ b/src/main/java/net/minecraft/util/SortedArraySet.java +@@ -28,7 +28,7 @@ public class SortedArraySet extends AbstractSet { + } + + public static > SortedArraySet create(int initialCapacity) { +- return new SortedArraySet<>(initialCapacity, Comparator.naturalOrder()); ++ return new SortedArraySet<>(initialCapacity, Comparator.naturalOrder()); // Paper - decompile fix + } + + public static SortedArraySet create(Comparator comparator) { +diff --git a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java +index d4488ebc4d4f50e1c3ccfeeb8bb82d06a7a90c30..37110c535b9fe25b53b5ebe9aa448ade6dcda2f9 100644 +--- a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java ++++ b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java +@@ -93,7 +93,7 @@ public class ProcessorMailbox implements ProfilerMeasured, ProcessorHandle + @Override + public void run() { + try { +- this.pollUntil((i) -> { ++ this.pollUntil((int i) -> { // Paper - decompile fix + return i == 0; + }); + } finally { +diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +index 2d79d4014770081fcd58a929e5fe0a26ac1b8023..f39a82bb231f5623fc69b044e6c17e742f56171a 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java ++++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +@@ -75,7 +75,7 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { + } + + this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { +- return (entry1.getValue()); // CraftBukkit ++ return entry1.getValue(); // CraftBukkit // Paper - decompile fix - *shrugs internally* + })); + RecipeManager.LOGGER.info("Loaded {} recipes", map1.size()); + } +diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java +index eb07e63f3c40fd8914cde50dfa789b1ed20b755a..3af31dc2c82c11ee78d497c5777615c17cb13c7a 100644 +--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java ++++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java +@@ -39,7 +39,7 @@ public class TickNextTickData { + } + + public static Comparator> createTimeComparator() { +- return Comparator.comparingLong((tickNextTickData) -> { ++ return Comparator.>comparingLong((tickNextTickData) -> { // Paper - decompile fix + return tickNextTickData.triggerTick; + }).thenComparing((tickNextTickData) -> { + return tickNextTickData.priority; +diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java +index eb870fba1d54201664f4a384fa45db99b65a252f..3f3b4e4ea8231fdcc799bd9de3e20747a5634603 100644 +--- a/src/main/java/net/minecraft/world/level/biome/Biome.java ++++ b/src/main/java/net/minecraft/world/level/biome/Biome.java +@@ -53,8 +53,40 @@ import org.apache.logging.log4j.Logger; + + public final class Biome { + public static final Logger LOGGER = LogManager.getLogger(); +- public static final Codec DIRECT_CODEC; +- public static final Codec NETWORK_CODEC; ++ // Paper start - decompile fix: move up verbatim from static block ++ public static final Codec DIRECT_CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(Biome.ClimateSettings.CODEC.forGetter((biome) -> { ++ return biome.climateSettings; ++ }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biome) -> { ++ return biome.biomeCategory; ++ }), Codec.FLOAT.fieldOf("depth").forGetter((biome) -> { ++ return biome.depth; ++ }), Codec.FLOAT.fieldOf("scale").forGetter((biome) -> { ++ return biome.scale; ++ }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biome) -> { ++ return biome.specialEffects; ++ }), BiomeGenerationSettings.CODEC.forGetter((biome) -> { ++ return biome.generationSettings; ++ }), MobSpawnSettings.CODEC.forGetter((biome) -> { ++ return biome.mobSettings; ++ })).apply(instance, Biome::new); ++ }); ++ public static final Codec NETWORK_CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(Biome.ClimateSettings.CODEC.forGetter((biome) -> { ++ return biome.climateSettings; ++ }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biome) -> { ++ return biome.biomeCategory; ++ }), Codec.FLOAT.fieldOf("depth").forGetter((biome) -> { ++ return biome.depth; ++ }), Codec.FLOAT.fieldOf("scale").forGetter((biome) -> { ++ return biome.scale; ++ }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biome) -> { ++ return biome.specialEffects; ++ })).apply(instance, (climateSettings, biomeCategory, float_, float2, biomeSpecialEffects) -> { ++ return new Biome(climateSettings, biomeCategory, float_, float2, biomeSpecialEffects, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY); ++ }); ++ }); ++ // Paper end + public static final Codec> CODEC = RegistryFileCodec.create(Registry.BIOME_REGISTRY, DIRECT_CODEC); + public static final Codec>> LIST_CODEC = RegistryFileCodec.homogeneousList(Registry.BIOME_REGISTRY, DIRECT_CODEC); + private final Map>> structuresByStep = Registry.STRUCTURE_FEATURE.stream().collect(Collectors.groupingBy((structureFeature) -> { +@@ -336,41 +368,6 @@ public final class Biome { + return resourceLocation == null ? super.toString() : resourceLocation.toString(); + } + +- static { +- DIRECT_CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(Biome.ClimateSettings.CODEC.forGetter((biome) -> { +- return biome.climateSettings; +- }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biome) -> { +- return biome.biomeCategory; +- }), Codec.FLOAT.fieldOf("depth").forGetter((biome) -> { +- return biome.depth; +- }), Codec.FLOAT.fieldOf("scale").forGetter((biome) -> { +- return biome.scale; +- }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biome) -> { +- return biome.specialEffects; +- }), BiomeGenerationSettings.CODEC.forGetter((biome) -> { +- return biome.generationSettings; +- }), MobSpawnSettings.CODEC.forGetter((biome) -> { +- return biome.mobSettings; +- })).apply(instance, Biome::new); +- }); +- NETWORK_CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(Biome.ClimateSettings.CODEC.forGetter((biome) -> { +- return biome.climateSettings; +- }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biome) -> { +- return biome.biomeCategory; +- }), Codec.FLOAT.fieldOf("depth").forGetter((biome) -> { +- return biome.depth; +- }), Codec.FLOAT.fieldOf("scale").forGetter((biome) -> { +- return biome.scale; +- }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biome) -> { +- return biome.specialEffects; +- })).apply(instance, (climateSettings, biomeCategory, float_, float2, biomeSpecialEffects) -> { +- return new Biome(climateSettings, biomeCategory, float_, float2, biomeSpecialEffects, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY); +- }); +- }); +- } +- + public static class BiomeBuilder { + @Nullable + private Biome.Precipitation precipitation; +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +index f1ba8da158963f01c63412370a31aec617e0c7da..e76591dec764d92e1a760c5208714f3c80ea8fc7 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +@@ -6,6 +6,7 @@ import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import java.util.Arrays; + import java.util.Collection; ++import java.util.Iterator; + import java.util.Map; + import java.util.Optional; + import java.util.function.Predicate; +@@ -19,6 +20,7 @@ public class EnumProperty & StringRepresentable> extends Prope + protected EnumProperty(String name, Class type, Collection values) { + super(name, type); + this.values = ImmutableSet.copyOf(values); ++ Iterator iterator = values.iterator(); // Paper - decompile fix + + for(T enum_ : values) { + String string = enum_.getSerializedName(); From a207d14a0eaf5500f971d582454a132f9946a4e5 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 15:46:44 +0200 Subject: [PATCH 011/226] Rename all patches to correct numbering scheme Signed-off-by: Mariell Hoversholm --- build.gradle.kts | 2 +- .../{0004-MC-Utils.patch => 0006-MC-Utils.patch} | 0 .../{0005-Paper-Metrics.patch => 0007-Paper-Metrics.patch} | 0 ...patch => 0008-Add-MinecraftKey-Information-to-Objects.patch} | 0 ...-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch} | 0 ...> 0010-Store-counts-for-each-Entity-Block-Entity-Type.patch} | 0 .../{0009-Timings-v2.patch => 0011-Timings-v2.patch} | 0 .../{0010-Adventure.patch => 0012-Adventure.patch} | 0 ...13-Configurable-cactus-bamboo-and-reed-growth-heights.patch} | 0 ...patch => 0014-Configurable-baby-zombie-movement-speed.patch} | 0 ...ranges.patch => 0015-Configurable-fishing-time-ranges.patch} | 0 ... 0016-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch} | 0 ...-Add-configurable-despawn-distances-for-living-entiti.patch} | 0 ...unks.patch => 0018-Allow-for-toggling-of-spawn-chunks.patch} | 0 ...-Drop-falling-block-and-tnt-entities-at-the-specified.patch} | 0 ...-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch} | 0 ...nChecker.patch => 0021-Implement-Paper-VersionChecker.patch} | 0 ....patch => 0022-Add-version-history-to-version-command.patch} | 0 ...pawning-API.patch => 0023-Player-affects-spawning-API.patch} | 0 ...atch => 0024-Remove-invalid-mob-spawner-tile-entities.patch} | 0 ...ity-Ticking.patch => 0025-Optimize-TileEntity-Ticking.patch} | 0 ...k-loop.patch => 0026-Further-improve-server-tick-loop.patch} | 0 ...needed.patch => 0027-Only-refresh-abilities-if-needed.patch} | 0 ...026-Entity-Origin-API.patch => 0028-Entity-Origin-API.patch} | 0 ....patch => 0029-Prevent-tile-entity-and-entity-crashes.patch} | 0 ....patch => 0030-Configurable-top-of-nether-void-damage.patch} | 0 ...-Check-online-mode-before-converting-and-renaming-pla.patch} | 0 ...lling-blocks.patch => 0032-Always-tick-falling-blocks.patch} | 0 ...le-end-credits.patch => 0033-Configurable-end-credits.patch} | 0 ...0034-Fix-lag-from-explosions-processing-dead-entities.patch} | 0 ...Optimize-explosions.patch => 0035-Optimize-explosions.patch} | 0 ...n-knockback.patch => 0036-Disable-explosion-knockback.patch} | 0 .../{0035-Disable-thunder.patch => 0037-Disable-thunder.patch} | 0 ...sable-ice-and-snow.patch => 0038-Disable-ice-and-snow.patch} | 0 ...rate.patch => 0039-Configurable-mob-spawner-tick-rate.patch} | 0 ...-Send-absolute-position-the-first-time-an-entity-is-s.patch} | 0 ...BeaconEffectEvent.patch => 0041-Add-BeaconEffectEvent.patch} | 0 ...patch => 0042-Configurable-container-update-tick-rate.patch} | 0 ...er-heads.patch => 0043-Use-UserCache-for-player-heads.patch} | 0 ...k-limiters.patch => 0044-Disable-spigot-tick-limiters.patch} | 0 ...lSpawnEvent.patch => 0045-Add-PlayerInitialSpawnEvent.patch} | 0 ...ch => 0046-Configurable-Disabling-Cat-Chest-Detection.patch} | 0 ...async.patch => 0047-Ensure-commands-are-not-ran-async.patch} | 0 ...atch => 0048-All-chunks-are-slime-spawn-chunks-toggle.patch} | 0 ...ver-CommandMap.patch => 0049-Expose-server-CommandMap.patch} | 0 ...0050-Be-a-bit-more-informative-in-maxHealth-exception.patch} | 0 ...tle-APIs.patch => 0051-Player-Tab-List-and-Title-APIs.patch} | 0 ...-in-bounds.patch => 0052-Ensure-inv-drag-is-in-bounds.patch} | 0 ...053-Change-implementation-of-tile-entity-removal-list.patch} | 0 ...s.patch => 0054-Add-configurable-portal-search-radius.patch} | 0 ...velocity-warnings.patch => 0055-Add-velocity-warnings.patch} | 0 ...=> 0056-Configurable-inter-world-teleportation-safety.patch} | 0 ...ing-event.patch => 0057-Add-exception-reporting-event.patch} | 0 ...-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch} | 0 ...> 0059-Disable-Scoreboards-for-non-players-by-default.patch} | 0 ...-Add-methods-for-working-with-arrows-stuck-in-living-.patch} | 0 ...rce-pack-API.patch => 0061-Complete-resource-pack-API.patch} | 0 ...unk-Save-Reattempt.patch => 0062-Chunk-Save-Reattempt.patch} | 0 ...> 0063-Default-loading-permissions.yml-before-plugins.patch} | 0 ...s.patch => 0064-Allow-Reloading-of-Custom-Permissions.patch} | 0 ...ata-on-reload.patch => 0065-Remove-Metadata-on-reload.patch} | 0 ...encies.patch => 0066-Handle-Item-Meta-Inconsistencies.patch} | 0 ...ch => 0067-Configurable-Non-Player-Arrow-Despawn-Rate.patch} | 0 ...rld-Util-Methods.patch => 0068-Add-World-Util-Methods.patch} | 0 ...tems.patch => 0069-Custom-replacement-for-eaten-items.patch} | 0 ...0-handle-NaN-health-absorb-values-and-repair-bad-data.patch} | 0 ...tities.patch => 0071-Use-a-Shared-Random-for-Entities.patch} | 0 ...> 0072-Configurable-spawn-chances-for-skeleton-horses.patch} | 0 ...-Optimize-isValidLocation-getType-and-getBlockData-fo.patch} | 0 ...-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch} | 0 ...ts.patch => 0075-Entity-AddTo-RemoveFrom-World-Events.patch} | 0 ...-Time.patch => 0076-Configurable-Chunk-Inhabited-Time.patch} | 0 ...EntityPathfindEvent.patch => 0077-EntityPathfindEvent.patch} | 0 ...> 0078-Sanitise-RegionFileCache-and-make-configurable.patch} | 0 ...ding.patch => 0079-Do-not-load-chunks-for-Pathfinding.patch} | 0 ...tyEvent.patch => 0080-Add-PlayerUseUnknownEntityEvent.patch} | 0 ...> 0081-Fix-reducedDebugInfo-not-initialized-on-client.patch} | 0 ...ate.patch => 0082-Configurable-Grass-Spread-Tick-Rate.patch} | 0 ...083-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch} | 0 ...082-Optimize-DataBits.patch => 0084-Optimize-DataBits.patch} | 0 ...-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch} | 0 ... => 0086-Workaround-for-setting-passengers-on-players.patch} | 0 ...st.patch => 0087-Remove-unused-World-Tile-Entity-List.patch} | 0 ...used-code.patch => 0088-Don-t-tick-Skulls-unused-code.patch} | 0 ...Collision.patch => 0089-Configurable-Player-Collision.patch} | 0 ...-Add-handshake-event-to-allow-plugins-to-handle-clien.patch} | 0 ...IP-address.patch => 0091-Configurable-RCON-IP-address.patch} | 0 ... 0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch} | 0 ...Event.patch => 0093-Implement-PlayerLocaleChangeEvent.patch} | 0 ...patch => 0094-EntityRegainHealthEvent-isFastRegen-API.patch} | 0 ... 0095-Add-ability-to-configure-frosted_ice-properties.patch} | 0 ... 0096-remove-null-possibility-for-getServer-singleton.patch} | 0 ...-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch} | 0 ...=> 0098-LootTable-API-Replenishable-Lootables-Feature.patch} | 0 ...9-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch} | 0 ...patch => 0100-System-property-for-disabling-watchdoge.patch} | 0 ...ead-Safe.patch => 0101-Optimize-UserCache-Thread-Safe.patch} | 0 ...ch => 0102-Avoid-blocking-on-Network-Manager-creation.patch} | 0 ...ater.patch => 0103-Optional-TNT-doesn-t-move-in-water.patch} | 0 ...tch => 0104-Faster-redstone-torch-rapid-clock-removal.patch} | 0 ...ame-parameter.patch => 0105-Add-server-name-parameter.patch} | 0 ...06-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch} | 0 ...-Add-issues.patch => 0107-Fix-Double-World-Add-issues.patch} | 0 ...Sign-Conversion.patch => 0108-Fix-Old-Sign-Conversion.patch} | 0 ...-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch} | 0 ...atch => 0110-Add-setting-for-proxy-online-mode-status.patch} | 0 ...s.patch => 0111-Optimise-BlockState-s-hashCode-equals.patch} | 0 ...d.patch => 0112-Configurable-packet-in-spam-threshold.patch} | 0 ...sages.patch => 0113-Configurable-flying-kick-messages.patch} | 0 ...stration-fixes.patch => 0114-Chunk-registration-fixes.patch} | 0 ...-Remove-FishingHook-reference-on-Craft-Entity-removal.patch} | 0 ...n.patch => 0116-Auto-fix-bad-Y-levels-on-player-login.patch} | 0 ....patch => 0117-Option-to-remove-corrupt-tile-entities.patch} | 0 ...6-Add-EntityZapEvent.patch => 0118-Add-EntityZapEvent.patch} | 0 ...19-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch} | 0 ...hreads.patch => 0120-Cache-user-authenticator-threads.patch} | 0 ...timise-removeQueue.patch => 0121-Optimise-removeQueue.patch} | 0 ...ases.patch => 0122-Allow-Reloading-of-Command-Aliases.patch} | 0 ...vent.patch => 0123-Add-source-to-PlayerExpChangeEvent.patch} | 0 ...tals.patch => 0124-Don-t-let-fishinghooks-use-portals.patch} | 0 ...CollideEvent.patch => 0125-Add-ProjectileCollideEvent.patch} | 0 ...patch => 0126-Prevent-Pathfinding-out-of-World-Border.patch} | 0 ...patch => 0127-Optimize-World.isLoaded-BlockPosition-Z.patch} | 0 ...der.patch => 0128-Bound-Treasure-Maps-to-World-Border.patch} | 0 ...patch => 0129-Configurable-Cartographer-Treasure-Maps.patch} | 0 ...tack.isEmpty.patch => 0130-Optimize-ItemStack.isEmpty.patch} | 0 ...-Add-API-methods-to-control-if-armour-stands-can-move.patch} | 0 ...n-bug.patch => 0132-Properly-fix-item-duplication-bug.patch} | 0 ...ion-Bar-API.patch => 0133-String-based-Action-Bar-API.patch} | 0 .../{0132-Firework-API-s.patch => 0134-Firework-API-s.patch} | 0 ...ewayEvent.patch => 0135-PlayerTeleportEndGatewayEvent.patch} | 0 ...s.patch => 0136-Provide-E-TE-Chunk-count-stat-methods.patch} | 0 ...-Player-Saves.patch => 0137-Enforce-Sync-Player-Saves.patch} | 0 ...h => 0138-Don-t-allow-entities-to-ride-themselves-572.patch} | 0 ...-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch} | 0 ...Entity-Collisions.patch => 0140-Cap-Entity-Collisions.patch} | 0 ...tch => 0141-Remove-CraftScheduler-Async-Task-Debugger.patch} | 0 ...-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch} | 0 ...ands-drown.patch => 0143-Do-not-let-armorstands-drown.patch} | 0 ...144-Properly-handle-async-calls-to-restart-the-server.patch} | 0 ... 0145-Add-system-property-to-disable-book-size-limits.patch} | 0 ...-Add-option-to-make-parrots-stay-on-shoulders-despite.patch} | 0 ...-Add-configuration-option-to-prevent-player-names-fro.patch} | 0 ...-Use-TerminalConsoleAppender-for-console-improvements.patch} | 0 ...-provide-a-configurable-option-to-disable-creeper-lin.patch} | 0 ...em-canEntityPickup.patch => 0150-Item-canEntityPickup.patch} | 0 ...er.patch => 0151-PlayerPickupItemEvent-setFlyAtPlayer.patch} | 0 ...pItemEvent.patch => 0152-PlayerAttemptPickupItemEvent.patch} | 0 ...ownCommandEvent.patch => 0153-Add-UnknownCommandEvent.patch} | 0 ...ayerProfile-API.patch => 0154-Basic-PlayerProfile-API.patch} | 0 ...lease-API.patch => 0155-Shoulder-Entities-Release-API.patch} | 0 ...ile-Lookup-Events.patch => 0156-Profile-Lookup-Events.patch} | 0 ...ch => 0157-Block-player-logins-during-server-shutdown.patch} | 0 ...ty-fromMobSpawner.patch => 0158-Entity-fromMobSpawner.patch} | 0 ...orses.patch => 0159-Improve-the-Saddle-API-for-Horses.patch} | 0 ...I.patch => 0160-Implement-ensureServerConversions-API.patch} | 0 ...isplayName.patch => 0161-Implement-getI18NDisplayName.patch} | 0 ...VerifyEvent.patch => 0162-ProfileWhitelistVerifyEvent.patch} | 0 ...tupid-bullshit.patch => 0163-Fix-this-stupid-bullshit.patch} | 0 ... 0164-Ocelot-despawns-should-honor-nametags-and-leash.patch} | 0 ...5-Reset-spawner-timer-when-spawner-event-is-cancelled.patch} | 0 ...Spike.patch => 0166-Fix-MC-117075-TE-Unload-Lag-Spike.patch} | 0 ...-Allow-specifying-a-custom-authentication-servers-dow.patch} | 0 ...Entity-setKiller.patch => 0168-LivingEntity-setKiller.patch} | 0 ...0169-Handle-plugin-prefixes-using-Log4J-configuration.patch} | 0 ...ch => 0170-Improve-Log4J-Configuration-Plugin-Loggers.patch} | 0 ...Add-PlayerJumpEvent.patch => 0171-Add-PlayerJumpEvent.patch} | 0 ...sync.patch => 0172-handle-PacketPlayInKeepAlive-async.patch} | 0 ... 0173-Expose-client-protocol-version-and-virtual-host.patch} | 0 ...atch => 0174-revert-serverside-behavior-of-keepalives.patch} | 0 ...-Send-attack-SoundEffects-only-to-players-who-can-see.patch} | 0 ...> 0176-Option-for-maximum-exp-value-when-merging-orbs.patch} | 0 ...rChangeEvent.patch => 0177-Add-PlayerArmorChangeEvent.patch} | 0 ...-Prevent-logins-from-being-processed-when-the-player-.patch} | 0 ...-use-CB-BlockState-implementations-for-captured-block.patch} | 0 ...ch => 0180-API-to-get-a-BlockState-without-a-snapshot.patch} | 0 ...cTabCompleteEvent.patch => 0181-AsyncTabCompleteEvent.patch} | 0 ...lTempt.patch => 0182-Avoid-NPE-in-PathfinderGoalTempt.patch} | 0 ...rienceEvent.patch => 0183-PlayerPickupExperienceEvent.patch} | 0 ...ceOrbMergeEvent.patch => 0184-ExperienceOrbMergeEvent.patch} | 0 ...-API.patch => 0185-Ability-to-apply-mending-to-XP-API.patch} | 0 ...atch => 0186-Make-max-squid-spawn-height-configurable.patch} | 0 ...reatureSpawnEvent.patch => 0187-PreCreatureSpawnEvent.patch} | 0 ...vent.patch => 0188-PlayerNaturallySpawnCreaturesEvent.patch} | 0 ...lls.patch => 0189-Add-setPlayerProfile-API-for-Skulls.patch} | 0 ...rty-Events.patch => 0190-Fill-Profile-Property-Events.patch} | 0 ...nt.patch => 0191-PlayerAdvancementCriterionGrantEvent.patch} | 0 ...tand-Item-Meta.patch => 0192-Add-ArmorStand-Item-Meta.patch} | 0 ...ion.patch => 0193-Extend-Player-Interact-cancellation.patch} | 0 ...queId-API.patch => 0194-Tameable-getOwnerUniqueId-API.patch} | 0 ...-Toggleable-player-crits-helps-mitigate-hacked-client.patch} | 0 ... 0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch} | 0 ...tch => 0197-Disable-Explicit-Network-Manager-Flushing.patch} | 0 ...h => 0198-Implement-extended-PaperServerListPingEvent.patch} | 0 ...Scheduler.patch => 0199-Improved-Async-Task-Scheduler.patch} | 0 ...-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch} | 0 ...Profile-API.patch => 0201-Player.setPlayerProfile-API.patch} | 0 ...erver-Crashes.patch => 0202-Fix-Dragon-Server-Crashes.patch} | 0 ...layerUniqueId-API.patch => 0203-getPlayerUniqueId-API.patch} | 0 ...le.patch => 0204-Make-player-data-saving-configurable.patch} | 0 ....patch => 0205-Make-legacy-ping-handler-more-reliable.patch} | 0 ...> 0206-Call-PaperServerListPingEvent-for-legacy-pings.patch} | 0 ...limit.patch => 0207-Flag-to-disable-the-channel-limit.patch} | 0 ....patch => 0208-Add-method-to-open-already-placed-sign.patch} | 0 ...ch => 0209-Configurable-sprint-interruption-on-attack.patch} | 0 ...-Fix-exploit-that-allowed-colored-signs-to-be-created.patch} | 0 ...EndermanEscapeEvent.patch => 0211-EndermanEscapeEvent.patch} | 0 ...eportRandomly.patch => 0212-Enderman.teleportRandomly.patch} | 0 ...Exploit.patch => 0213-Block-Enderpearl-Travel-Exploit.patch} | 0 ...> 0214-Expand-World.spawnParticle-API-and-add-Builder.patch} | 0 ...ckPlayerEvent.patch => 0215-EndermanAttackPlayerEvent.patch} | 0 ...sumePotionEvent.patch => 0216-WitchConsumePotionEvent.patch} | 0 ...hThrowPotionEvent.patch => 0217-WitchThrowPotionEvent.patch} | 0 ...8-Allow-spawning-Item-entities-with-World.spawnEntity.patch} | 0 ...hReadyPotionEvent.patch => 0219-WitchReadyPotionEvent.patch} | 0 ...uration.patch => 0220-ItemStack-getMaxItemUseDuration.patch} | 0 ...patch => 0221-Implement-EntityTeleportEndGatewayEvent.patch} | 0 ... 0222-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch} | 0 ...ntity-hashCode.patch => 0223-Fix-CraftEntity-hashCode.patch} | 0 ...> 0224-Configurable-Alternative-LootPool-Luck-Formula.patch} | 0 ...-Print-Error-details-when-failing-to-save-player-data.patch} | 0 ...patch => 0226-Make-shield-blocking-delay-configurable.patch} | 0 ...ootBowEvent.patch => 0227-Improve-EntityShootBowEvent.patch} | 0 ...erReadyArrowEvent.patch => 0228-PlayerReadyArrowEvent.patch} | 0 ....patch => 0229-Implement-EntityKnockbackByEntityEvent.patch} | 0 ...nd-Explosions-API.patch => 0230-Expand-Explosions-API.patch} | 0 ...I.patch => 0231-LivingEntity-Hand-Raised-Item-Use-API.patch} | 0 ...{0230-RangedEntity-API.patch => 0232-RangedEntity-API.patch} | 0 ... 0233-Add-config-to-disable-ender-dragon-legacy-check.patch} | 0 ...-API.patch => 0234-Implement-World.getEntity-UUID-API.patch} | 0 ...ason-API.patch => 0235-InventoryCloseEvent-Reason-API.patch} | 0 ...Vex-getSummoner-API.patch => 0236-Vex-getSummoner-API.patch} | 0 ...-Refresh-player-inventory-when-cancelling-PlayerInter.patch} | 0 ...> 0238-Don-t-change-the-Entity-Random-seed-for-squids.patch} | 0 ...=> 0239-Re-add-vanilla-entity-warnings-for-duplicates.patch} | 0 ...0-Avoid-item-merge-if-stack-size-above-max-stack-size.patch} | 0 ...oggers.patch => 0241-Use-asynchronous-Log4j-2-loggers.patch} | 0 ...patch => 0242-add-more-information-to-Entity.toString.patch} | 0 ...3-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch} | 0 ...2-EnderDragon-Events.patch => 0244-EnderDragon-Events.patch} | 0 ...ElytraBoostEvent.patch => 0245-PlayerElytraBoostEvent.patch} | 0 ...inlining.patch => 0246-Improve-BlockPosition-inlining.patch} | 0 ...mize-RegistryID.c.patch => 0247-Optimize-RegistryID.c.patch} | 0 ...-Option-to-prevent-armor-stands-from-doing-entity-loo.patch} | 0 ...ghts.patch => 0249-Vanished-players-don-t-have-rights.patch} | 0 ...-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch} | 0 ...s.patch => 0251-Add-some-Debug-to-Chunk-Entity-slices.patch} | 0 ...Horse-Additions.patch => 0252-SkeletonHorse-Additions.patch} | 0 ...s.patch => 0253-Prevent-Saving-Bad-entities-to-chunks.patch} | 0 ...a.patch => 0254-Don-t-call-getItemMeta-on-hasItemMeta.patch} | 0 ... => 0255-Ignore-Dead-Entities-in-entityList-iteration.patch} | 0 ...d-API.patch => 0256-Implement-Expanded-ArmorStand-API.patch} | 0 ...{0255-AnvilDamageEvent.patch => 0257-AnvilDamageEvent.patch} | 0 ...256-Add-TNTPrimeEvent.patch => 0258-Add-TNTPrimeEvent.patch} | 0 ...> 0259-Break-up-and-make-tab-spam-limits-configurable.patch} | 0 ...bucket-events.patch => 0260-Add-hand-to-bucket-events.patch} | 0 ... => 0261-MC-135506-Experience-should-save-as-Integers.patch} | 0 ...ch => 0262-Fix-client-rendering-skulls-from-same-user.patch} | 0 ...g.patch => 0263-Add-Early-Warning-Feature-to-WatchDog.patch} | 0 ...ment-Mob.patch => 0264-Make-EnderDragon-implement-Mob.patch} | 0 ...nList.patch => 0265-Use-ConcurrentHashMap-in-JsonList.patch} | 0 ...mands.patch => 0266-Use-a-Queue-for-Queueing-Commands.patch} | 0 ...-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch} | 0 ...ng.patch => 0268-Allow-disabling-armour-stand-ticking.patch} | 0 ...s.patch => 0269-Optimize-BlockPosition-helper-methods.patch} | 0 ...-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch} | 0 ...thfinder-Events.patch => 0271-Slime-Pathfinder-Events.patch} | 0 ...> 0272-Configurable-speed-for-water-flowing-over-lava.patch} | 0 ...eation.patch => 0273-Optimize-CraftBlockData-Creation.patch} | 0 ...tryMaterials.patch => 0274-Optimize-RegistryMaterials.patch} | 0 ...mPreSpawnEvent.patch => 0275-Add-PhantomPreSpawnEvent.patch} | 0 ...d-More-Creeper-API.patch => 0276-Add-More-Creeper-API.patch} | 0 ...ItemAnySlot.patch => 0277-Inventory-removeItemAnySlot.patch} | 0 ...-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch} | 0 ...patch => 0279-Add-ray-tracing-methods-to-LivingEntity.patch} | 0 ...tch => 0280-Expose-attack-cooldown-methods-for-Player.patch} | 0 ...prove-death-events.patch => 0281-Improve-death-events.patch} | 0 ...patch => 0282-Allow-chests-to-be-placed-with-NBT-data.patch} | 0 ...Mob-Pathfinding-API.patch => 0283-Mob-Pathfinding-API.patch} | 0 ...atch => 0284-Prevent-chunk-loading-from-Fluid-Flowing.patch} | 0 ...-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch} | 0 ...atch => 0286-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch} | 0 ...7-Prevent-mob-spawning-from-loading-generating-chunks.patch} | 0 ...h => 0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch} | 0 ...h => 0289-Implement-furnace-cook-speed-multiplier-API.patch} | 0 ...eSpawnerSpawnEvent.patch => 0290-PreSpawnerSpawnEvent.patch} | 0 ... 0291-Catch-JsonParseException-in-Entity-and-TE-names.patch} | 0 ...ble.ageLock.patch => 0292-Honor-EntityAgeable.ageLock.patch} | 0 ...=> 0293-Configurable-connection-throttle-kick-message.patch} | 0 ...n-rewrites.patch => 0294-Hook-into-CB-plugin-rewrites.patch} | 0 ...mmoner.patch => 0295-Allow-setting-the-vex-s-summoner.patch} | 0 ...Add-sun-related-API.patch => 0296-Add-sun-related-API.patch} | 0 .../{0295-Turtle-API.patch => 0297-Turtle-API.patch} | 0 ...-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch} | 0 ...-Call-player-spectator-target-events-and-improve-impl.patch} | 0 ...port.patch => 0300-Add-Velocity-IP-Forwarding-Support.patch} | 0 ...9-Add-more-Witch-API.patch => 0301-Add-more-Witch-API.patch} | 0 ... => 0302-Check-Drowned-for-Villager-Aggression-Config.patch} | 0 .../{0301-Here-s-Johnny.patch => 0303-Here-s-Johnny.patch} | 0 ...-Add-option-to-prevent-players-from-moving-into-unloa.patch} | 0 ...spawn.patch => 0305-Reset-players-airTicks-on-respawn.patch} | 0 ... 0306-Don-t-sleep-after-profile-lookups-if-not-needed.patch} | 0 ...0307-Improve-Server-Thread-Pool-and-Thread-Priorities.patch} | 0 ...ime-Updates.patch => 0308-Optimize-World-Time-Updates.patch} | 0 ....patch => 0309-Restore-custom-InventoryHolder-support.patch} | 0 ...cart-Speeds.patch => 0310-Use-Vanilla-Minecart-Speeds.patch} | 0 ...handling.patch => 0311-Fix-SpongeAbsortEvent-handling.patch} | 0 ...atch => 0312-Don-t-allow-digging-into-unloaded-chunks.patch} | 0 ...{0311-Book-Size-Limits.patch => 0313-Book-Size-Limits.patch} | 0 ...0314-Make-the-default-permission-message-configurable.patch} | 0 ...ks.patch => 0315-Prevent-rayTrace-from-loading-chunks.patch} | 0 ...tch => 0316-Handle-Large-Packets-disconnecting-client.patch} | 0 ...ch => 0317-force-entity-dismount-during-teleportation.patch} | 0 ...Add-more-Zombie-API.patch => 0318-Add-more-Zombie-API.patch} | 0 ...oseEvent.patch => 0319-Add-PlayerConnectionCloseEvent.patch} | 0 ...ks.patch => 0320-Prevent-Enderman-from-loading-chunks.patch} | 0 ... 0321-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch} | 0 ...2-Workaround-for-vehicle-tracking-issue-on-disconnect.patch} | 0 ...23-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch} | 0 ...0324-Block-Entity-remove-from-being-called-on-Players.patch} | 0 ...323-BlockDestroyEvent.patch => 0325-BlockDestroyEvent.patch} | 0 ... => 0326-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch} | 0 ...t-memory-leak.patch => 0327-Fix-sign-edit-memory-leak.patch} | 0 ...ngth-more.patch => 0328-Limit-Client-Sign-length-more.patch} | 0 ...0329-Don-t-check-ConvertSigns-boolean-every-sign-save.patch} | 0 ...-Optimize-Network-Manager-and-add-advanced-packet-sup.patch} | 0 ...atch => 0331-Handle-Oversized-Tile-Entities-in-chunks.patch} | 0 ... => 0332-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch} | 0 ...333-Set-Zombie-last-tick-at-start-of-drowning-process.patch} | 0 ...Chunks.patch => 0334-Allow-Saving-of-Oversized-Chunks.patch} | 0 ...5-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch} | 0 ...Entity.patch => 0336-Add-LivingEntity-getTargetEntity.patch} | 0 ...-Use-proper-max-length-when-serialising-BungeeCord-te.patch} | 0 ...SpawnReason.patch => 0338-Entity-getEntitySpawnReason.patch} | 0 ...> 0339-Update-entity-Metadata-for-all-tracked-players.patch} | 0 ...nEvent.patch => 0340-Implement-PlayerPostRespawnEvent.patch} | 0 ...-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch} | 0 ...0-Server-Tick-Events.patch => 0342-Server-Tick-Events.patch} | 0 ...sToKeep.patch => 0343-PlayerDeathEvent-getItemsToKeep.patch} | 0 ...kup.patch => 0344-Optimize-Captured-TileEntity-Lookup.patch} | 0 ...343-Add-Heightmap-API.patch => 0345-Add-Heightmap-API.patch} | 0 ...hancements.patch => 0346-Mob-Spawner-API-Enhancements.patch} | 0 ...tch => 0347-Per-Player-View-Distance-API-placeholders.patch} | 0 ...> 0348-Fix-CB-call-to-changed-postToMainThread-method.patch} | 0 ...49-Fix-sounds-when-item-frames-are-modified-MC-123450.patch} | 0 ...-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch} | 0 ...51-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch} | 0 ...ve-Option.patch => 0352-Duplicate-UUID-Resolve-Option.patch} | 0 ...Loaded.patch => 0353-improve-CraftWorld-isChunkLoaded.patch} | 0 ...> 0354-Configurable-Keep-Spawn-Loaded-range-per-world.patch} | 0 ...-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch} | 0 ...unkMapDistance-CME.patch => 0356-ChunkMapDistance-CME.patch} | 0 ...undGroup.patch => 0357-Implement-CraftBlockSoundGroup.patch} | 0 ...Chunk-debug-command.patch => 0358-Chunk-debug-command.patch} | 0 ...=> 0359-Catch-exceptions-from-dispenser-entity-spawns.patch} | 0 ...-calls.patch => 0360-Fix-World-isChunkGenerated-calls.patch} | 0 ...0361-Show-blockstate-location-if-we-failed-to-read-it.patch} | 0 ...-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch} | 0 ...l-chunk-saving.patch => 0363-incremental-chunk-saving.patch} | 0 .../{0362-Anti-Xray.patch => 0364-Anti-Xray.patch} | 0 ...-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch} | 0 ...tch => 0366-Configurable-projectile-relative-velocity.patch} | 0 ...-Mark-entities-as-being-ticked-when-notifying-navigat.patch} | 0 ...frame-ticking.patch => 0368-offset-item-frame-ticking.patch} | 0 ...h => 0369-Avoid-hopper-searches-if-there-are-no-items.patch} | 0 ...ading.patch => 0370-Asynchronous-chunk-IO-and-loading.patch} | 0 ...tch => 0371-Use-getChunkIfLoadedImmediately-in-places.patch} | 0 ...370-Reduce-sync-loads.patch => 0372-Reduce-sync-loads.patch} | 0 ...patch => 0373-Implement-alternative-item-despawn-rate.patch} | 0 ...374-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch} | 0 .../{0373-Fix-MC-158900.patch => 0375-Fix-MC-158900.patch} | 0 ...atch => 0376-implement-optional-per-player-mob-spawns.patch} | 0 ...k.patch => 0377-Prevent-consuming-the-wrong-itemstack.patch} | 0 ...6-Generator-Settings.patch => 0378-Generator-Settings.patch} | 0 .../{0377-Fix-MC-161754.patch => 0379-Fix-MC-161754.patch} | 0 ...=> 0380-Performance-improvement-for-Chunk.getEntities.patch} | 0 ...-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch} | 0 ...t-tick.patch => 0382-Expose-the-internal-current-tick.patch} | 0 ...0383-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch} | 0 ....patch => 0384-Add-option-to-disable-pillager-patrols.patch} | 0 ...-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch} | 0 ...ectileEvent.patch => 0386-PlayerLaunchProjectileEvent.patch} | 0 ...h => 0387-Add-CraftMagicNumbers.isSupportedApiVersion.patch} | 0 ...-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch} | 0 ...tch => 0389-MC-145656-Fix-Follow-Range-Initial-Target.patch} | 0 ...{0388-Optimize-Hoppers.patch => 0390-Optimize-Hoppers.patch} | 0 ...e.patch => 0391-PlayerDeathEvent-shouldDropExperience.patch} | 0 ...92-Prevent-bees-loading-chunks-checking-hive-position.patch} | 0 ... 0393-Don-t-load-Chunks-from-Hoppers-and-other-things.patch} | 0 ...-Guard-against-serializing-mismatching-chunk-coordina.patch} | 0 ....patch => 0395-Optimise-IEntityAccess-getPlayerByUUID.patch} | 0 ...rrectly.patch => 0396-Fix-items-not-falling-correctly.patch} | 0 ...compensate-eating.patch => 0397-Lag-compensate-eating.patch} | 0 ...atch => 0398-Optimize-call-to-getFluid-for-explosions.patch} | 0 ...-Fix-last-firework-in-stack-not-having-effects-when-d.patch} | 0 ...lly.patch => 0400-Add-effect-to-block-break-naturally.patch} | 0 ...mprovements.patch => 0401-Tracking-Range-Improvements.patch} | 0 ...n-Range-2.0.patch => 0402-Entity-Activation-Range-2.0.patch} | 0 ....patch => 0403-Fix-items-vanishing-through-end-portal.patch} | 0 ...tch => 0404-Bees-get-gravity-in-void.-Fixes-MC-167279.patch} | 0 ...h => 0405-Optimise-getChunkAt-calls-for-loaded-chunks.patch} | 0 ...patch => 0406-Allow-overriding-the-java-version-check.patch} | 0 ...wnEggHatchEvent.patch => 0407-Add-ThrownEggHatchEvent.patch} | 0 ...k-ticking.patch => 0408-Optimise-random-block-ticking.patch} | 0 .../{0407-Entity-Jump-API.patch => 0409-Entity-Jump-API.patch} | 0 ...=> 0410-Add-option-to-nerf-pigmen-from-nether-portals.patch} | 0 ...raph-fancier.patch => 0411-Make-the-GUI-graph-fancier.patch} | 0 ...eEvent.patch => 0412-add-hand-to-BlockMultiPlaceEvent.patch} | 0 ...ities.patch => 0413-Prevent-teleporting-dead-entities.patch} | 0 ...> 0414-Validate-tripwire-hook-placement-before-update.patch} | 0 ... 0415-Add-option-to-allow-iron-golems-to-spawn-in-air.patch} | 0 ...0416-Configurable-chance-of-villager-zombie-infection.patch} | 0 ...-Chunk-getFluid.patch => 0417-Optimise-Chunk-getFluid.patch} | 0 ...patch => 0418-Optimise-TickListServer-by-rewriting-it.patch} | 0 ...-Pillager-patrol-spawn-settings-and-per-player-option.patch} | 0 ...atch => 0420-Ensure-Entity-is-never-double-registered.patch} | 0 ...0421-Fix-unregistering-entities-from-unloading-chunks.patch} | 0 ...=> 0422-Remote-Connections-shouldn-t-hold-up-shutdown.patch} | 0 ...=> 0423-Do-not-allow-bees-to-load-chunks-for-beehives.patch} | 0 ...24-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch} | 0 ...s.patch => 0425-Optimize-Collision-to-not-load-chunks.patch} | 0 ...ck-dead-players.patch => 0426-Don-t-tick-dead-players.patch} | 0 ...patch => 0427-Dead-Player-s-shouldn-t-be-able-to-move.patch} | 0 ...-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch} | 0 ...ht-Queue-Size.patch => 0429-Increase-Light-Queue-Size.patch} | 0 ...-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch} | 0 ...ch => 0431-Don-t-move-existing-players-to-world-spawn.patch} | 0 ...and.patch => 0432-Add-tick-times-API-and-mspt-command.patch} | 0 ...unning.patch => 0433-Expose-MinecraftServer-isRunning.patch} | 0 ...on.patch => 0434-Add-Raw-Byte-ItemStack-Serialization.patch} | 0 ...ystem.patch => 0435-Remove-streams-from-Mob-AI-System.patch} | 0 ...-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch} | 0 ...map-building.patch => 0437-Async-command-map-building.patch} | 0 ...chdog-Support.patch => 0438-Improved-Watchdog-Support.patch} | 0 ...timize-Pathfinding.patch => 0439-Optimize-Pathfinding.patch} | 0 ...ation.patch => 0440-Reduce-Either-Optional-allocation.patch} | 0 ...edQueue.patch => 0441-Remove-streams-from-PairedQueue.patch} | 0 ...tch => 0442-Reduce-memory-footprint-of-NBTTagCompound.patch} | 0 ...patch => 0443-Prevent-opening-inventories-when-frozen.patch} | 0 ...moveIf.patch => 0444-Optimise-ArraySetSorted-removeIf.patch} | 0 ...=> 0445-Don-t-run-entity-collision-code-if-not-needed.patch} | 0 ...-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch} | 0 ...-Restrict-vanilla-teleport-command-to-valid-locations.patch} | 0 ...API.patch => 0448-Implement-Player-Client-Options-API.patch} | 0 ...patch => 0449-Fix-Chunk-Post-Processing-deadlock-risk.patch} | 0 ...-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch} | 0 ...nsole.patch => 0451-Broadcast-join-message-to-console.patch} | 0 ...2-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch} | 0 ...ly.patch => 0453-Load-Chunks-for-Login-Asynchronously.patch} | 0 ...-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch} | 0 ...atch => 0455-Add-PlayerAttackEntityCooldownResetEvent.patch} | 0 ...-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch} | 0 ...atch => 0457-Don-t-fire-BlockFade-on-worldgen-threads.patch} | 0 ...h => 0458-Add-phantom-creative-and-insomniac-controls.patch} | 0 ...-Fix-numerous-item-duplication-issues-and-teleport-is.patch} | 0 ...jang-API.patch => 0460-Implement-Brigadier-Mojang-API.patch} | 0 ...ager-Restocks-API.patch => 0461-Villager-Restocks-API.patch} | 0 ...=> 0462-Validate-PickItem-Packet-and-kick-for-invalid.patch} | 0 ...Expose-game-version.patch => 0463-Expose-game-version.patch} | 0 ...pe-Merging.patch => 0464-Optimize-Voxel-Shape-Merging.patch} | 0 ...65-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch} | 0 ...ent-Mob-Goal-API.patch => 0466-Implement-Mob-Goal-API.patch} | 0 ...h => 0467-Use-distance-map-to-optimise-entity-tracker.patch} | 0 ... => 0468-Optimize-isOutsideRange-to-use-distance-maps.patch} | 0 ...-Stop-copy-on-write-operations-for-updating-light-dat.patch} | 0 ...on.patch => 0470-No-Tick-view-distance-implementation.patch} | 0 ...utation-API.patch => 0471-Add-villager-reputation-API.patch} | 0 ...470-Fix-Light-Command.patch => 0472-Fix-Light-Command.patch} | 0 ...flag.patch => 0473-Fix-PotionEffect-ignores-icon-flag.patch} | 0 ... => 0474-Optimize-brigadier-child-sorting-performance.patch} | 0 ...473-Potential-bed-API.patch => 0475-Potential-bed-API.patch} | 0 ...wn.patch => 0476-Wait-for-Async-Tasks-during-shutdown.patch} | 0 ...-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch} | 0 ...-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch} | 0 ...ch => 0479-Optimize-NibbleArray-to-use-pooled-buffers.patch} | 0 ... 0480-Reduce-MutableInt-allocations-from-light-engine.patch} | 0 ... => 0481-Reduce-allocation-of-Vec3D-by-entity-tracker.patch} | 0 ...y-teleport.patch => 0482-Ensure-safe-gateway-teleport.patch} | 0 ...=> 0483-Add-option-for-console-having-all-permissions.patch} | 0 ...tch => 0484-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch} | 0 ...ch => 0485-Workaround-for-Client-Lag-Spikes-MC-162253.patch} | 0 ...86-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch} | 0 ...-Optimize-sending-packets-to-nearby-locations-sounds-.patch} | 0 ...d.patch => 0488-Improve-Chunk-Status-Transition-Speed.patch} | 0 ...2.patch => 0489-Fix-villager-trading-demand-MC-163962.patch} | 0 ...-load-chunks.patch => 0490-Maps-shouldn-t-load-chunks.patch} | 0 ...-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch} | 0 ...ing.patch => 0492-Optimize-Bit-Operations-by-inlining.patch} | 0 ...mize-Light-Engine.patch => 0493-Optimize-Light-Engine.patch} | 0 ... => 0494-Delay-Chunk-Unloads-based-on-Player-Movement.patch} | 0 ...patch => 0495-Add-Plugin-Tickets-to-API-Chunk-Methods.patch} | 0 ...ch => 0496-Fix-missing-chunks-due-to-integer-overflow.patch} | 0 ...-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch} | 0 ...ch => 0498-Fix-piston-physics-inconsistency-MC-188840.patch} | 0 .../{0497-Fix-sand-duping.patch => 0499-Fix-sand-duping.patch} | 0 ...-Prevent-position-desync-in-playerconnection-causing-.patch} | 0 ...ragon-exp-dupe.patch => 0501-Fix-enderdragon-exp-dupe.patch} | 0 ...502-Inventory-getHolder-method-without-block-snapshot.patch} | 0 ...-getItemStack.patch => 0503-Expose-Arrow-getItemStack.patch} | 0 ... => 0504-Add-and-implement-PlayerRecipeBookClickEvent.patch} | 0 ...flag.patch => 0505-Hide-sync-chunk-writes-behind-flag.patch} | 0 ....patch => 0506-Limit-lightning-strike-effect-distance.patch} | 0 ...locks.patch => 0507-Add-permission-for-command-blocks.patch} | 0 ....patch => 0508-Ensure-Entity-AABB-s-are-never-invalid.patch} | 0 ...=> 0509-Optimize-WorldBorder-collision-checks-and-air.patch} | 0 ... 0510-Fix-Per-World-Difficulty-Remembering-Difficulty.patch} | 0 ...dumpitem-command.patch => 0511-Paper-dumpitem-command.patch} | 0 ...r-chat.patch => 0512-Don-t-allow-null-UUID-s-for-chat.patch} | 0 ...h => 0513-Improve-Legacy-Component-serialization-size.patch} | 0 ...for-NBT.patch => 0514-Support-old-UUID-format-for-NBT.patch} | 0 ...ch => 0515-Clean-up-duplicated-GameProfile-Properties.patch} | 0 ....patch => 0516-Convert-legacy-attributes-in-Item-Meta.patch} | 0 ...res.patch => 0517-Remove-some-streams-from-structures.patch} | 0 ...8-Remove-streams-from-classes-related-villager-gossip.patch} | 0 ...ItemMeta.patch => 0519-Support-components-in-ItemMeta.patch} | 0 ...0-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch} | 0 ...entity-liquid-API.patch => 0521-Add-entity-liquid-API.patch} | 0 ...e.patch => 0522-Update-itemstack-legacy-name-and-lore.patch} | 0 ....patch => 0523-Spawn-player-in-correct-world-on-login.patch} | 0 ...epareResultEvent.patch => 0524-Add-PrepareResultEvent.patch} | 0 ...n.patch => 0525-Allow-delegation-to-vanilla-chunk-gen.patch} | 0 ...-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch} | 0 ...ch => 0527-Optimize-NetworkManager-Exception-Handling.patch} | 0 ...t.patch => 0528-Fix-Concurrency-issue-in-WeightedList.patch} | 0 ...-Optimize-the-advancement-data-player-iteration-to-be.patch} | 0 ...7.patch => 0530-Fix-arrows-never-despawning-MC-125757.patch} | 0 ... 0531-Thread-Safe-Vanilla-Command-permission-checking.patch} | 0 ...p.patch => 0532-Move-range-check-for-block-placing-up.patch} | 0 .../{0531-Fix-SPIGOT-5989.patch => 0533-Fix-SPIGOT-5989.patch} | 0 ...34-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch} | 0 ...> 0535-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch} | 0 ...-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch} | 0 ...-Add-missing-strikeLighting-call-to-World-spigot-stri.patch} | 0 ...ly.patch => 0538-Fix-some-rails-connecting-improperly.patch} | 0 ...-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch} | 0 ...player-saving.patch => 0540-Incremental-player-saving.patch} | 0 ...astutil-classes.patch => 0541-Import-fastutil-classes.patch} | 0 ...0542-Don-t-mark-null-chunk-sections-for-block-updates.patch} | 0 ...patch => 0543-Remove-armour-stand-double-add-to-world.patch} | 0 ...ght.patch => 0544-Fix-MC-187716-Use-configured-height.patch} | 0 ... 0545-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch} | 0 ...-Do-not-let-the-server-load-chunks-from-newer-version.patch} | 0 .../{0545-Brand-support.patch => 0547-Brand-support.patch} | 0 ...-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch} | 0 .../{0547-Fix-MC-197271.patch => 0549-Fix-MC-197271.patch} | 0 ...de-issue.patch => 0550-MC-197883-Bandaid-decode-issue.patch} | 0 ...setMaxPlayers-API.patch => 0551-Add-setMaxPlayers-API.patch} | 0 ...h => 0552-Add-playPickupItemAnimation-to-LivingEntity.patch} | 0 ...e-FACING-data.patch => 0553-Don-t-require-FACING-data.patch} | 0 ...554-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch} | 0 ...3-Add-moon-phase-API.patch => 0555-Add-moon-phase-API.patch} | 0 ...h => 0556-Prevent-headless-pistons-from-being-created.patch} | 0 ...555-Add-BellRingEvent.patch => 0557-Add-BellRingEvent.patch} | 0 ...ig.patch => 0558-Add-zombie-targets-turtle-egg-config.patch} | 0 ...er-joins-to-world.patch => 0559-Buffer-joins-to-world.patch} | 0 ...e-algorithm.patch => 0560-Optimize-redstone-algorithm.patch} | 0 ...0561-Fix-hex-colors-not-working-in-some-kick-messages.patch} | 0 ...ch => 0562-PortalCreateEvent-needs-to-know-its-entity.patch} | 0 ...eam-null-check.patch => 0563-Fix-CraftTeam-null-check.patch} | 0 ...Add-more-Evoker-API.patch => 0564-Add-more-Evoker-API.patch} | 0 ...-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch} | 0 ...patch => 0566-Create-HoverEvent-from-ItemStack-Entity.patch} | 0 ...k-data-strings.patch => 0567-Cache-block-data-strings.patch} | 0 ...-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch} | 0 ...0569-Add-additional-open-container-api-to-HumanEntity.patch} | 0 ... => 0570-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch} | 0 ...-Extend-block-drop-capture-to-capture-all-items-added.patch} | 0 ...572-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch} | 0 ...-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch} | 0 ...ch => 0574-Lazily-track-plugin-scoreboards-by-default.patch} | 0 ...{0573-Entity-isTicking.patch => 0575-Entity-isTicking.patch} | 0 ...-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch} | 0 ...am.patch => 0577-Fix-Not-a-string-Map-Conversion-spam.patch} | 0 ...8-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch} | 0 ...-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch} | 0 ...wn.patch => 0580-Reset-Ender-Crystals-on-Dragon-Spawn.patch} | 0 ...ch => 0581-Fix-for-large-move-vectors-crashing-server.patch} | 0 ...se-getType-calls.patch => 0582-Optimise-getType-calls.patch} | 0 ...llager-resetOffers.patch => 0583-Villager-resetOffers.patch} | 0 ... 0584-Improve-inlinig-for-some-hot-IBlockData-methods.patch} | 0 ...5-Retain-block-place-order-when-capturing-blockstates.patch} | 0 ...h => 0586-Reduce-blockpos-allocation-from-pathfinding.patch} | 0 ...tch => 0587-Fix-item-locations-dropped-from-campfires.patch} | 0 ...lytra-boost-API.patch => 0588-Player-elytra-boost-API.patch} | 0 ...y-leak.patch => 0589-Fixed-TileEntityBell-memory-leak.patch} | 0 ...-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch} | 0 ...ing.patch => 0591-Add-getOfflinePlayerIfCached-String.patch} | 0 ...-discounts-API.patch => 0592-Add-ignore-discounts-API.patch} | 0 ...gon.patch => 0593-Toggle-for-removing-existing-dragon.patch} | 0 ...g.patch => 0594-Fix-client-lag-on-advancement-loading.patch} | 0 ...yer-pickup.patch => 0595-Item-no-age-no-player-pickup.patch} | 0 ...-ranges.patch => 0596-Beacon-API-custom-effect-ranges.patch} | 0 ...for-quit-reason.patch => 0597-Add-API-for-quit-reason.patch} | 0 ...eature-search.patch => 0598-Seed-based-feature-search.patch} | 0 ...> 0599-Add-Wandering-Trader-spawn-rate-config-options.patch} | 0 ...-Significantly-improve-performance-of-the-end-generat.patch} | 0 ...ld-spawn-angle.patch => 0601-Expose-world-spawn-angle.patch} | 0 ...Destroy-Speed-API.patch => 0602-Add-Destroy-Speed-API.patch} | 0 ...=> 0603-Fix-Player-spawnParticle-x-y-z-precision-loss.patch} | 0 ...veItem.patch => 0604-Add-LivingEntity-clearActiveItem.patch} | 0 ...oldownEvent.patch => 0605-Add-PlayerItemCooldownEvent.patch} | 0 ...4-More-lightning-API.patch => 0606-More-lightning-API.patch} | 0 ... => 0607-Climbing-should-not-bypass-cramming-gamerule.patch} | 0 ...atch => 0608-Added-missing-default-perms-for-commands.patch} | 0 ...earBlockEvent.patch => 0609-Add-PlayerShearBlockEvent.patch} | 0 ...> 0610-Add-warning-for-servers-not-running-on-Java-16.patch} | 0 ...611-Set-spigots-verbose-world-setting-to-false-by-def.patch} | 0 ...h => 0612-Fix-curing-zombie-villager-discount-exploit.patch} | 0 ...mit-recipe-packets.patch => 0613-Limit-recipe-packets.patch} | 0 ....patch => 0614-Fix-CraftSound-backwards-compatibility.patch} | 0 ...on-desync.patch => 0615-MC-4-Fix-item-position-desync.patch} | 0 ...-Events.patch => 0616-Player-Chunk-Load-Unload-Events.patch} | 0 ...-Keys.patch => 0617-Optimize-Dynamic-get-Missing-Keys.patch} | 0 ...tion.patch => 0618-Expose-LivingEntity-hurt-direction.patch} | 0 ...patch => 0619-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} | 0 ...-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch} | 0 ...PlayerTradeEvent.patch => 0621-added-PlayerTradeEvent.patch} | 0 ...TargetHitEvent.patch => 0622-Implement-TargetHitEvent.patch} | 0 ...l-API-s.patch => 0623-Additional-Block-Material-API-s.patch} | 0 ...ing-potion-dupe.patch => 0624-Fix-harming-potion-dupe.patch} | 0 ...-Implement-API-to-get-Material-from-Boats-and-Minecar.patch} | 0 ...-ready-check.patch => 0626-Optimized-tick-ready-check.patch} | 0 ...che-burn-durations.patch => 0627-Cache-burn-durations.patch} | 0 ...-Allow-disabling-mob-spawner-spawn-egg-transformation.patch} | 0 ...atch => 0629-Implement-PlayerFlowerPotManipulateEvent.patch} | 0 ...0630-Fix-interact-event-not-being-called-in-adventure.patch} | 0 ...reaking-doors.patch => 0631-Zombie-API-breaking-doors.patch} | 0 ...litting.patch => 0632-Fix-nerfed-slime-when-splitting.patch} | 0 ...ossbowEvent.patch => 0633-Add-EntityLoadCrossbowEvent.patch} | 0 ...eam-workaround.patch => 0634-Guardian-beam-workaround.patch} | 0 ...ngeEvent.patch => 0635-Added-WorldGameRuleChangeEvent.patch} | 0 ...vent.patch => 0636-Added-ServerResourcesReloadedEvent.patch} | 0 ...=> 0637-Added-world-settings-for-mobs-picking-up-loot.patch} | 0 ...nt.patch => 0638-Implemented-BlockFailedDispenseEvent.patch} | 0 ...vent.patch => 0639-Added-PlayerLecternPageChangeEvent.patch} | 0 ...nt-on-GS4-query.patch => 0640-Fire-event-on-GS4-query.patch} | 0 ...vent.patch => 0641-Added-PlayerLoomPatternSelectEvent.patch} | 0 ...y.patch => 0642-Configurable-door-breaking-difficulty.patch} | 0 ....patch => 0643-Empty-commands-shall-not-be-dispatched.patch} | 0 ... 0644-Implement-API-to-expose-exact-interaction-point.patch} | 0 ...643-Remove-stale-POIs.patch => 0645-Remove-stale-POIs.patch} | 0 ...-boat-exploit.patch => 0646-Fix-villager-boat-exploit.patch} | 0 ...-chunk.patch => 0647-Entity-load-save-limit-per-chunk.patch} | 0 ...Add-sendOpLevel-API.patch => 0648-Add-sendOpLevel-API.patch} | 0 ...ureLocateEvent.patch => 0649-Add-StructureLocateEvent.patch} | 0 ...0-Collision-option-for-requiring-a-player-participant.patch} | 0 ...51-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch} | 0 ...-Return-chat-component-with-empty-text-instead-of-thr.patch} | 0 ...r-world.patch => 0653-Make-schedule-command-per-world.patch} | 0 ...istance.patch => 0654-Configurable-max-leash-distance.patch} | 0 ...seEvent.patch => 0655-Implement-BlockPreDispenseEvent.patch} | 0 ...a-Entity-Tags.patch => 0656-Added-Vanilla-Entity-Tags.patch} | 0 ...{0655-added-Wither-API.patch => 0657-added-Wither-API.patch} | 0 ...=> 0658-Added-firing-of-PlayerChangeBeaconEffectEvent.patch} | 0 ...> 0659-Fix-console-spam-when-removing-chests-in-water.patch} | 0 ... => 0660-Add-toggle-for-always-placing-the-dragon-egg.patch} | 0 ...atch => 0661-Added-PlayerStonecutterRecipeSelectEvent.patch} | 0 ... => 0662-Add-dropLeash-variable-to-EntityUnleashEvent.patch} | 0 ... 0663-Skip-distance-map-update-when-spawning-disabled.patch} | 0 ...tch => 0664-Reset-shield-blocking-on-dimension-change.patch} | 0 ...agonEggFormEvent.patch => 0665-add-DragonEggFormEvent.patch} | 0 .../{0664-EntityMoveEvent.patch => 0666-EntityMoveEvent.patch} | 0 ...-added-option-to-disable-pathfinding-updates-on-block.patch} | 0 ...on-fields.patch => 0668-Inline-shift-direction-fields.patch} | 0 ...atch => 0669-Allow-adding-items-to-BlockDropItemEvent.patch} | 0 ... => 0670-Add-getMainThreadExecutor-to-BukkitScheduler.patch} | 0 ...ch => 0671-living-entity-allow-attribute-registration.patch} | 0 ...ty.patch => 0672-fix-dead-slime-setSize-invincibility.patch} | 0 ...3-Merchant-getRecipes-should-return-an-immutable-list.patch} | 0 ...sc-debugging-dumps.patch => 0674-misc-debugging-dumps.patch} | 0 ...ch => 0675-Add-support-for-hex-color-codes-in-console.patch} | 0 ...4-Clear-SyncLoadInfo.patch => 0676-Clear-SyncLoadInfo.patch} | 0 ...-Tracked-Players.patch => 0677-Expose-Tracked-Players.patch} | 0 ...arest.patch => 0678-Remove-streams-from-SensorNearest.patch} | 0 ...79-do-not-create-unnecessary-copies-of-passenger-list.patch} | 0 ...=> 0680-MC-29274-Fix-Wither-hostility-towards-players.patch} | 0 ...=> 0681-Throw-proper-exception-on-empty-JsonList-file.patch} | 0 ...680-Improve-ServerGUI.patch => 0682-Improve-ServerGUI.patch} | 0 ...-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch} | 0 ...on-file.patch => 0684-fix-converting-txt-to-json-file.patch} | 0 ...rldborder-events.patch => 0685-Add-worldborder-events.patch} | 0 ...EntityEvent.patch => 0686-added-PlayerNameEntityEvent.patch} | 0 ...h => 0687-Prevent-grindstones-from-overstacking-items.patch} | 0 ...o-cook-events.patch => 0688-Add-recipe-to-cook-events.patch} | 0 ...Block-isValidTool.patch => 0689-Add-Block-isValidTool.patch} | 0 ...tch => 0690-Allow-using-signs-inside-spawn-protection.patch} | 0 ...Keyed-on-World.patch => 0691-Implement-Keyed-on-World.patch} | 0 ...=> 0692-Add-fast-alternative-constructor-for-Vector3f.patch} | 0 .../{0691-Item-Rarity-API.patch => 0693-Item-Rarity-API.patch} | 0 ...-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch} | 0 ...s.patch => 0695-copy-TESign-isEditable-from-snapshots.patch} | 0 ...> 0696-Drop-carried-item-when-player-has-disconnected.patch} | 0 ...> 0697-forced-whitelist-use-configurable-kick-message.patch} | 0 ...=> 0698-Make-sure-to-remove-correct-TE-during-TE-tick.patch} | 0 ...ch => 0699-Don-t-ignore-result-of-PlayerEditBookEvent.patch} | 0 ...00-fix-cancelling-block-falling-causing-client-desync.patch} | 0 ...rotocol-version.patch => 0701-Expose-protocol-version.patch} | 0 ...-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} | 0 ...-Enhance-console-tab-completions-for-brigadier-comman.patch} | 0 ...> 0704-Fix-PlayerItemConsumeEvent-cancelling-properly.patch} | 0 ...bypass-host-check.patch => 0705-Add-bypass-host-check.patch} | 0 ...Es.patch => 0706-don-t-throw-when-loading-invalid-TEs.patch} | 0 ...rotation.patch => 0707-Set-area-affect-cloud-rotation.patch} | 0 ...ity.patch => 0708-add-isDeeplySleeping-to-HumanEntity.patch} | 0 ...> 0709-Fix-duplicating-give-items-on-item-drop-cancel.patch} | 0 ...ent.patch => 0710-add-consumeFuel-to-FurnaceBurnEvent.patch} | 0 ...ch => 0711-add-get-set-drop-chance-to-EntityEquipment.patch} | 0 ...on.patch => 0712-fix-PigZombieAngerEvent-cancellation.patch} | 0 ....patch => 0713-Fix-checkReach-check-for-Shulker-boxes.patch} | 0 ...ce.patch => 0714-fix-PlayerItemHeldEvent-firing-twice.patch} | 0 ...epSleepEvent.patch => 0715-Added-PlayerDeepSleepEvent.patch} | 0 .../{0714-More-World-API.patch => 0716-More-World-API.patch} | 0 ...nterEvent.patch => 0717-Added-PlayerBedFailEnterEvent.patch} | 0 ...-Implement-methods-to-convert-between-Component-and-B.patch} | 0 ...-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch} | 0 ....patch => 0720-add-RespawnFlags-to-PlayerRespawnEvent.patch} | 0 ... 0721-Introduce-beacon-activation-deactivation-events.patch} | 0 ...rs.patch => 0722-Add-Channel-initialization-listeners.patch} | 0 ...723-Send-empty-commands-if-tab-completion-is-disabled.patch} | 0 ...Trader-API.patch => 0724-Add-more-WanderingTrader-API.patch} | 0 ...es.patch => 0725-Add-EntityBlockStorage-clearEntities.patch} | 0 ...6-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch} | 0 ...h => 0727-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch} | 0 .../{0726-Inventory-close.patch => 0728-Inventory-close.patch} | 0 ... 0729-call-PortalCreateEvent-players-and-end-platform.patch} | 0 ...-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch} | 0 ...rewer-cache.patch => 0731-Fix-CraftPotionBrewer-cache.patch} | 0 ...sic-Datapack-API.patch => 0732-Add-basic-Datapack-API.patch} | 0 ...> 0733-Add-environment-variable-to-disable-server-gui.patch} | 0 ....patch => 0734-additions-to-PlayerGameModeChangeEvent.patch} | 0 ...ir-check-API.patch => 0735-ItemStack-repair-check-API.patch} | 0 ...re-Enchantment-API.patch => 0736-More-Enchantment-API.patch} | 0 ...-Add-command-line-option-to-load-extra-plugin-jars-no.patch} | 0 ...-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch} | 0 ...-Fix-MC-148809-Increase-structure-block-data-length-t.patch} | 0 ....patch => 0740-Fix-and-optimise-world-force-upgrading.patch} | 0 ...9-Add-Mob-lookAt-API.patch => 0741-Add-Mob-lookAt-API.patch} | 0 ...-support.patch => 0742-Add-Unix-domain-socket-support.patch} | 0 ...deBlockEvent.patch => 0743-Add-EntityInsideBlockEvent.patch} | 0 ...faults.patch => 0744-Attributes-API-for-item-defaults.patch} | 0 ...745-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch} | 0 ...atch => 0746-Add-cause-to-Weather-ThunderChangeEvents.patch} | 0 ...-Lidded-Block-API.patch => 0747-More-Lidded-Block-API.patch} | 0 ...Event-causes.patch => 0748-Add-PlayerKickEvent-causes.patch} | 0 ...n-maps.patch => 0749-Limit-item-frame-cursors-on-maps.patch} | 0 ...ngeEvent.patch => 0750-Add-PufferFishStateChangeEvent.patch} | 0 ...h => 0751-Fix-PlayerBucketEmptyEvent-result-itemstack.patch} | 0 ...=> 0752-Add-option-to-fix-items-merging-through-walls.patch} | 0 ...alRaiderEvent.patch => 0753-Add-BellRevealRaiderEvent.patch} | 0 ...-crystals.patch => 0754-Fix-invulnerable-end-crystals.patch} | 0 ...eEvent.patch => 0755-Add-ElderGuardianAppearanceEvent.patch} | 0 ...56-Reset-villager-inventory-on-cancelled-pickup-event.patch} | 0 ...al-logic.patch => 0757-Fix-dangerous-end-portal-logic.patch} | 0 ...able.patch => 0758-Make-item-validations-configurable.patch} | 0 ...-methods.patch => 0759-Add-more-line-of-sight-methods.patch} | 0 ...spawn-limits.patch => 0760-add-per-world-spawn-limits.patch} | 0 ...> 0761-Fix-PotionSplashEvent-for-water-splash-potions.patch} | 0 757 files changed, 1 insertion(+), 1 deletion(-) rename patches/server-remapped/{0004-MC-Utils.patch => 0006-MC-Utils.patch} (100%) rename patches/server-remapped/{0005-Paper-Metrics.patch => 0007-Paper-Metrics.patch} (100%) rename patches/server-remapped/{0006-Add-MinecraftKey-Information-to-Objects.patch => 0008-Add-MinecraftKey-Information-to-Objects.patch} (100%) rename patches/server-remapped/{0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch => 0009-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch} (100%) rename patches/server-remapped/{0008-Store-counts-for-each-Entity-Block-Entity-Type.patch => 0010-Store-counts-for-each-Entity-Block-Entity-Type.patch} (100%) rename patches/server-remapped/{0009-Timings-v2.patch => 0011-Timings-v2.patch} (100%) rename patches/server-remapped/{0010-Adventure.patch => 0012-Adventure.patch} (100%) rename patches/server-remapped/{0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch => 0013-Configurable-cactus-bamboo-and-reed-growth-heights.patch} (100%) rename patches/server-remapped/{0012-Configurable-baby-zombie-movement-speed.patch => 0014-Configurable-baby-zombie-movement-speed.patch} (100%) rename patches/server-remapped/{0013-Configurable-fishing-time-ranges.patch => 0015-Configurable-fishing-time-ranges.patch} (100%) rename patches/server-remapped/{0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch => 0016-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch} (100%) rename patches/server-remapped/{0015-Add-configurable-despawn-distances-for-living-entiti.patch => 0017-Add-configurable-despawn-distances-for-living-entiti.patch} (100%) rename patches/server-remapped/{0016-Allow-for-toggling-of-spawn-chunks.patch => 0018-Allow-for-toggling-of-spawn-chunks.patch} (100%) rename patches/server-remapped/{0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch => 0019-Drop-falling-block-and-tnt-entities-at-the-specified.patch} (100%) rename patches/server-remapped/{0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch => 0020-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch} (100%) rename patches/server-remapped/{0019-Implement-Paper-VersionChecker.patch => 0021-Implement-Paper-VersionChecker.patch} (100%) rename patches/server-remapped/{0020-Add-version-history-to-version-command.patch => 0022-Add-version-history-to-version-command.patch} (100%) rename patches/server-remapped/{0021-Player-affects-spawning-API.patch => 0023-Player-affects-spawning-API.patch} (100%) rename patches/server-remapped/{0022-Remove-invalid-mob-spawner-tile-entities.patch => 0024-Remove-invalid-mob-spawner-tile-entities.patch} (100%) rename patches/server-remapped/{0023-Optimize-TileEntity-Ticking.patch => 0025-Optimize-TileEntity-Ticking.patch} (100%) rename patches/server-remapped/{0024-Further-improve-server-tick-loop.patch => 0026-Further-improve-server-tick-loop.patch} (100%) rename patches/server-remapped/{0025-Only-refresh-abilities-if-needed.patch => 0027-Only-refresh-abilities-if-needed.patch} (100%) rename patches/server-remapped/{0026-Entity-Origin-API.patch => 0028-Entity-Origin-API.patch} (100%) rename patches/server-remapped/{0027-Prevent-tile-entity-and-entity-crashes.patch => 0029-Prevent-tile-entity-and-entity-crashes.patch} (100%) rename patches/server-remapped/{0028-Configurable-top-of-nether-void-damage.patch => 0030-Configurable-top-of-nether-void-damage.patch} (100%) rename patches/server-remapped/{0029-Check-online-mode-before-converting-and-renaming-pla.patch => 0031-Check-online-mode-before-converting-and-renaming-pla.patch} (100%) rename patches/server-remapped/{0030-Always-tick-falling-blocks.patch => 0032-Always-tick-falling-blocks.patch} (100%) rename patches/server-remapped/{0031-Configurable-end-credits.patch => 0033-Configurable-end-credits.patch} (100%) rename patches/server-remapped/{0032-Fix-lag-from-explosions-processing-dead-entities.patch => 0034-Fix-lag-from-explosions-processing-dead-entities.patch} (100%) rename patches/server-remapped/{0033-Optimize-explosions.patch => 0035-Optimize-explosions.patch} (100%) rename patches/server-remapped/{0034-Disable-explosion-knockback.patch => 0036-Disable-explosion-knockback.patch} (100%) rename patches/server-remapped/{0035-Disable-thunder.patch => 0037-Disable-thunder.patch} (100%) rename patches/server-remapped/{0036-Disable-ice-and-snow.patch => 0038-Disable-ice-and-snow.patch} (100%) rename patches/server-remapped/{0037-Configurable-mob-spawner-tick-rate.patch => 0039-Configurable-mob-spawner-tick-rate.patch} (100%) rename patches/server-remapped/{0038-Send-absolute-position-the-first-time-an-entity-is-s.patch => 0040-Send-absolute-position-the-first-time-an-entity-is-s.patch} (100%) rename patches/server-remapped/{0039-Add-BeaconEffectEvent.patch => 0041-Add-BeaconEffectEvent.patch} (100%) rename patches/server-remapped/{0040-Configurable-container-update-tick-rate.patch => 0042-Configurable-container-update-tick-rate.patch} (100%) rename patches/server-remapped/{0041-Use-UserCache-for-player-heads.patch => 0043-Use-UserCache-for-player-heads.patch} (100%) rename patches/server-remapped/{0042-Disable-spigot-tick-limiters.patch => 0044-Disable-spigot-tick-limiters.patch} (100%) rename patches/server-remapped/{0043-Add-PlayerInitialSpawnEvent.patch => 0045-Add-PlayerInitialSpawnEvent.patch} (100%) rename patches/server-remapped/{0044-Configurable-Disabling-Cat-Chest-Detection.patch => 0046-Configurable-Disabling-Cat-Chest-Detection.patch} (100%) rename patches/server-remapped/{0045-Ensure-commands-are-not-ran-async.patch => 0047-Ensure-commands-are-not-ran-async.patch} (100%) rename patches/server-remapped/{0046-All-chunks-are-slime-spawn-chunks-toggle.patch => 0048-All-chunks-are-slime-spawn-chunks-toggle.patch} (100%) rename patches/server-remapped/{0047-Expose-server-CommandMap.patch => 0049-Expose-server-CommandMap.patch} (100%) rename patches/server-remapped/{0048-Be-a-bit-more-informative-in-maxHealth-exception.patch => 0050-Be-a-bit-more-informative-in-maxHealth-exception.patch} (100%) rename patches/server-remapped/{0049-Player-Tab-List-and-Title-APIs.patch => 0051-Player-Tab-List-and-Title-APIs.patch} (100%) rename patches/server-remapped/{0050-Ensure-inv-drag-is-in-bounds.patch => 0052-Ensure-inv-drag-is-in-bounds.patch} (100%) rename patches/server-remapped/{0051-Change-implementation-of-tile-entity-removal-list.patch => 0053-Change-implementation-of-tile-entity-removal-list.patch} (100%) rename patches/server-remapped/{0052-Add-configurable-portal-search-radius.patch => 0054-Add-configurable-portal-search-radius.patch} (100%) rename patches/server-remapped/{0053-Add-velocity-warnings.patch => 0055-Add-velocity-warnings.patch} (100%) rename patches/server-remapped/{0054-Configurable-inter-world-teleportation-safety.patch => 0056-Configurable-inter-world-teleportation-safety.patch} (100%) rename patches/server-remapped/{0055-Add-exception-reporting-event.patch => 0057-Add-exception-reporting-event.patch} (100%) rename patches/server-remapped/{0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch => 0058-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch} (100%) rename patches/server-remapped/{0057-Disable-Scoreboards-for-non-players-by-default.patch => 0059-Disable-Scoreboards-for-non-players-by-default.patch} (100%) rename patches/server-remapped/{0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch => 0060-Add-methods-for-working-with-arrows-stuck-in-living-.patch} (100%) rename patches/server-remapped/{0059-Complete-resource-pack-API.patch => 0061-Complete-resource-pack-API.patch} (100%) rename patches/server-remapped/{0060-Chunk-Save-Reattempt.patch => 0062-Chunk-Save-Reattempt.patch} (100%) rename patches/server-remapped/{0061-Default-loading-permissions.yml-before-plugins.patch => 0063-Default-loading-permissions.yml-before-plugins.patch} (100%) rename patches/server-remapped/{0062-Allow-Reloading-of-Custom-Permissions.patch => 0064-Allow-Reloading-of-Custom-Permissions.patch} (100%) rename patches/server-remapped/{0063-Remove-Metadata-on-reload.patch => 0065-Remove-Metadata-on-reload.patch} (100%) rename patches/server-remapped/{0064-Handle-Item-Meta-Inconsistencies.patch => 0066-Handle-Item-Meta-Inconsistencies.patch} (100%) rename patches/server-remapped/{0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch => 0067-Configurable-Non-Player-Arrow-Despawn-Rate.patch} (100%) rename patches/server-remapped/{0066-Add-World-Util-Methods.patch => 0068-Add-World-Util-Methods.patch} (100%) rename patches/server-remapped/{0067-Custom-replacement-for-eaten-items.patch => 0069-Custom-replacement-for-eaten-items.patch} (100%) rename patches/server-remapped/{0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch => 0070-handle-NaN-health-absorb-values-and-repair-bad-data.patch} (100%) rename patches/server-remapped/{0069-Use-a-Shared-Random-for-Entities.patch => 0071-Use-a-Shared-Random-for-Entities.patch} (100%) rename patches/server-remapped/{0070-Configurable-spawn-chances-for-skeleton-horses.patch => 0072-Configurable-spawn-chances-for-skeleton-horses.patch} (100%) rename patches/server-remapped/{0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch => 0073-Optimize-isValidLocation-getType-and-getBlockData-fo.patch} (100%) rename patches/server-remapped/{0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch => 0074-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch} (100%) rename patches/server-remapped/{0073-Entity-AddTo-RemoveFrom-World-Events.patch => 0075-Entity-AddTo-RemoveFrom-World-Events.patch} (100%) rename patches/server-remapped/{0074-Configurable-Chunk-Inhabited-Time.patch => 0076-Configurable-Chunk-Inhabited-Time.patch} (100%) rename patches/server-remapped/{0075-EntityPathfindEvent.patch => 0077-EntityPathfindEvent.patch} (100%) rename patches/server-remapped/{0076-Sanitise-RegionFileCache-and-make-configurable.patch => 0078-Sanitise-RegionFileCache-and-make-configurable.patch} (100%) rename patches/server-remapped/{0077-Do-not-load-chunks-for-Pathfinding.patch => 0079-Do-not-load-chunks-for-Pathfinding.patch} (100%) rename patches/server-remapped/{0078-Add-PlayerUseUnknownEntityEvent.patch => 0080-Add-PlayerUseUnknownEntityEvent.patch} (100%) rename patches/server-remapped/{0079-Fix-reducedDebugInfo-not-initialized-on-client.patch => 0081-Fix-reducedDebugInfo-not-initialized-on-client.patch} (100%) rename patches/server-remapped/{0080-Configurable-Grass-Spread-Tick-Rate.patch => 0082-Configurable-Grass-Spread-Tick-Rate.patch} (100%) rename patches/server-remapped/{0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch => 0083-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch} (100%) rename patches/server-remapped/{0082-Optimize-DataBits.patch => 0084-Optimize-DataBits.patch} (100%) rename patches/server-remapped/{0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch => 0085-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch} (100%) rename patches/server-remapped/{0084-Workaround-for-setting-passengers-on-players.patch => 0086-Workaround-for-setting-passengers-on-players.patch} (100%) rename patches/server-remapped/{0085-Remove-unused-World-Tile-Entity-List.patch => 0087-Remove-unused-World-Tile-Entity-List.patch} (100%) rename patches/server-remapped/{0086-Don-t-tick-Skulls-unused-code.patch => 0088-Don-t-tick-Skulls-unused-code.patch} (100%) rename patches/server-remapped/{0087-Configurable-Player-Collision.patch => 0089-Configurable-Player-Collision.patch} (100%) rename patches/server-remapped/{0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch => 0090-Add-handshake-event-to-allow-plugins-to-handle-clien.patch} (100%) rename patches/server-remapped/{0089-Configurable-RCON-IP-address.patch => 0091-Configurable-RCON-IP-address.patch} (100%) rename patches/server-remapped/{0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch => 0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch} (100%) rename patches/server-remapped/{0091-Implement-PlayerLocaleChangeEvent.patch => 0093-Implement-PlayerLocaleChangeEvent.patch} (100%) rename patches/server-remapped/{0092-EntityRegainHealthEvent-isFastRegen-API.patch => 0094-EntityRegainHealthEvent-isFastRegen-API.patch} (100%) rename patches/server-remapped/{0093-Add-ability-to-configure-frosted_ice-properties.patch => 0095-Add-ability-to-configure-frosted_ice-properties.patch} (100%) rename patches/server-remapped/{0094-remove-null-possibility-for-getServer-singleton.patch => 0096-remove-null-possibility-for-getServer-singleton.patch} (100%) rename patches/server-remapped/{0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch => 0097-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch} (100%) rename patches/server-remapped/{0096-LootTable-API-Replenishable-Lootables-Feature.patch => 0098-LootTable-API-Replenishable-Lootables-Feature.patch} (100%) rename patches/server-remapped/{0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch => 0099-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch} (100%) rename patches/server-remapped/{0098-System-property-for-disabling-watchdoge.patch => 0100-System-property-for-disabling-watchdoge.patch} (100%) rename patches/server-remapped/{0099-Optimize-UserCache-Thread-Safe.patch => 0101-Optimize-UserCache-Thread-Safe.patch} (100%) rename patches/server-remapped/{0100-Avoid-blocking-on-Network-Manager-creation.patch => 0102-Avoid-blocking-on-Network-Manager-creation.patch} (100%) rename patches/server-remapped/{0101-Optional-TNT-doesn-t-move-in-water.patch => 0103-Optional-TNT-doesn-t-move-in-water.patch} (100%) rename patches/server-remapped/{0102-Faster-redstone-torch-rapid-clock-removal.patch => 0104-Faster-redstone-torch-rapid-clock-removal.patch} (100%) rename patches/server-remapped/{0103-Add-server-name-parameter.patch => 0105-Add-server-name-parameter.patch} (100%) rename patches/server-remapped/{0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch => 0106-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch} (100%) rename patches/server-remapped/{0105-Fix-Double-World-Add-issues.patch => 0107-Fix-Double-World-Add-issues.patch} (100%) rename patches/server-remapped/{0106-Fix-Old-Sign-Conversion.patch => 0108-Fix-Old-Sign-Conversion.patch} (100%) rename patches/server-remapped/{0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch => 0109-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch} (100%) rename patches/server-remapped/{0108-Add-setting-for-proxy-online-mode-status.patch => 0110-Add-setting-for-proxy-online-mode-status.patch} (100%) rename patches/server-remapped/{0109-Optimise-BlockState-s-hashCode-equals.patch => 0111-Optimise-BlockState-s-hashCode-equals.patch} (100%) rename patches/server-remapped/{0110-Configurable-packet-in-spam-threshold.patch => 0112-Configurable-packet-in-spam-threshold.patch} (100%) rename patches/server-remapped/{0111-Configurable-flying-kick-messages.patch => 0113-Configurable-flying-kick-messages.patch} (100%) rename patches/server-remapped/{0112-Chunk-registration-fixes.patch => 0114-Chunk-registration-fixes.patch} (100%) rename patches/server-remapped/{0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch => 0115-Remove-FishingHook-reference-on-Craft-Entity-removal.patch} (100%) rename patches/server-remapped/{0114-Auto-fix-bad-Y-levels-on-player-login.patch => 0116-Auto-fix-bad-Y-levels-on-player-login.patch} (100%) rename patches/server-remapped/{0115-Option-to-remove-corrupt-tile-entities.patch => 0117-Option-to-remove-corrupt-tile-entities.patch} (100%) rename patches/server-remapped/{0116-Add-EntityZapEvent.patch => 0118-Add-EntityZapEvent.patch} (100%) rename patches/server-remapped/{0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch => 0119-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch} (100%) rename patches/server-remapped/{0118-Cache-user-authenticator-threads.patch => 0120-Cache-user-authenticator-threads.patch} (100%) rename patches/server-remapped/{0119-Optimise-removeQueue.patch => 0121-Optimise-removeQueue.patch} (100%) rename patches/server-remapped/{0120-Allow-Reloading-of-Command-Aliases.patch => 0122-Allow-Reloading-of-Command-Aliases.patch} (100%) rename patches/server-remapped/{0121-Add-source-to-PlayerExpChangeEvent.patch => 0123-Add-source-to-PlayerExpChangeEvent.patch} (100%) rename patches/server-remapped/{0122-Don-t-let-fishinghooks-use-portals.patch => 0124-Don-t-let-fishinghooks-use-portals.patch} (100%) rename patches/server-remapped/{0123-Add-ProjectileCollideEvent.patch => 0125-Add-ProjectileCollideEvent.patch} (100%) rename patches/server-remapped/{0124-Prevent-Pathfinding-out-of-World-Border.patch => 0126-Prevent-Pathfinding-out-of-World-Border.patch} (100%) rename patches/server-remapped/{0125-Optimize-World.isLoaded-BlockPosition-Z.patch => 0127-Optimize-World.isLoaded-BlockPosition-Z.patch} (100%) rename patches/server-remapped/{0126-Bound-Treasure-Maps-to-World-Border.patch => 0128-Bound-Treasure-Maps-to-World-Border.patch} (100%) rename patches/server-remapped/{0127-Configurable-Cartographer-Treasure-Maps.patch => 0129-Configurable-Cartographer-Treasure-Maps.patch} (100%) rename patches/server-remapped/{0128-Optimize-ItemStack.isEmpty.patch => 0130-Optimize-ItemStack.isEmpty.patch} (100%) rename patches/server-remapped/{0129-Add-API-methods-to-control-if-armour-stands-can-move.patch => 0131-Add-API-methods-to-control-if-armour-stands-can-move.patch} (100%) rename patches/server-remapped/{0130-Properly-fix-item-duplication-bug.patch => 0132-Properly-fix-item-duplication-bug.patch} (100%) rename patches/server-remapped/{0131-String-based-Action-Bar-API.patch => 0133-String-based-Action-Bar-API.patch} (100%) rename patches/server-remapped/{0132-Firework-API-s.patch => 0134-Firework-API-s.patch} (100%) rename patches/server-remapped/{0133-PlayerTeleportEndGatewayEvent.patch => 0135-PlayerTeleportEndGatewayEvent.patch} (100%) rename patches/server-remapped/{0134-Provide-E-TE-Chunk-count-stat-methods.patch => 0136-Provide-E-TE-Chunk-count-stat-methods.patch} (100%) rename patches/server-remapped/{0135-Enforce-Sync-Player-Saves.patch => 0137-Enforce-Sync-Player-Saves.patch} (100%) rename patches/server-remapped/{0136-Don-t-allow-entities-to-ride-themselves-572.patch => 0138-Don-t-allow-entities-to-ride-themselves-572.patch} (100%) rename patches/server-remapped/{0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch => 0139-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch} (100%) rename patches/server-remapped/{0138-Cap-Entity-Collisions.patch => 0140-Cap-Entity-Collisions.patch} (100%) rename patches/server-remapped/{0139-Remove-CraftScheduler-Async-Task-Debugger.patch => 0141-Remove-CraftScheduler-Async-Task-Debugger.patch} (100%) rename patches/server-remapped/{0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch => 0142-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch} (100%) rename patches/server-remapped/{0141-Do-not-let-armorstands-drown.patch => 0143-Do-not-let-armorstands-drown.patch} (100%) rename patches/server-remapped/{0142-Properly-handle-async-calls-to-restart-the-server.patch => 0144-Properly-handle-async-calls-to-restart-the-server.patch} (100%) rename patches/server-remapped/{0143-Add-system-property-to-disable-book-size-limits.patch => 0145-Add-system-property-to-disable-book-size-limits.patch} (100%) rename patches/server-remapped/{0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch => 0146-Add-option-to-make-parrots-stay-on-shoulders-despite.patch} (100%) rename patches/server-remapped/{0145-Add-configuration-option-to-prevent-player-names-fro.patch => 0147-Add-configuration-option-to-prevent-player-names-fro.patch} (100%) rename patches/server-remapped/{0146-Use-TerminalConsoleAppender-for-console-improvements.patch => 0148-Use-TerminalConsoleAppender-for-console-improvements.patch} (100%) rename patches/server-remapped/{0147-provide-a-configurable-option-to-disable-creeper-lin.patch => 0149-provide-a-configurable-option-to-disable-creeper-lin.patch} (100%) rename patches/server-remapped/{0148-Item-canEntityPickup.patch => 0150-Item-canEntityPickup.patch} (100%) rename patches/server-remapped/{0149-PlayerPickupItemEvent-setFlyAtPlayer.patch => 0151-PlayerPickupItemEvent-setFlyAtPlayer.patch} (100%) rename patches/server-remapped/{0150-PlayerAttemptPickupItemEvent.patch => 0152-PlayerAttemptPickupItemEvent.patch} (100%) rename patches/server-remapped/{0151-Add-UnknownCommandEvent.patch => 0153-Add-UnknownCommandEvent.patch} (100%) rename patches/server-remapped/{0152-Basic-PlayerProfile-API.patch => 0154-Basic-PlayerProfile-API.patch} (100%) rename patches/server-remapped/{0153-Shoulder-Entities-Release-API.patch => 0155-Shoulder-Entities-Release-API.patch} (100%) rename patches/server-remapped/{0154-Profile-Lookup-Events.patch => 0156-Profile-Lookup-Events.patch} (100%) rename patches/server-remapped/{0155-Block-player-logins-during-server-shutdown.patch => 0157-Block-player-logins-during-server-shutdown.patch} (100%) rename patches/server-remapped/{0156-Entity-fromMobSpawner.patch => 0158-Entity-fromMobSpawner.patch} (100%) rename patches/server-remapped/{0157-Improve-the-Saddle-API-for-Horses.patch => 0159-Improve-the-Saddle-API-for-Horses.patch} (100%) rename patches/server-remapped/{0158-Implement-ensureServerConversions-API.patch => 0160-Implement-ensureServerConversions-API.patch} (100%) rename patches/server-remapped/{0159-Implement-getI18NDisplayName.patch => 0161-Implement-getI18NDisplayName.patch} (100%) rename patches/server-remapped/{0160-ProfileWhitelistVerifyEvent.patch => 0162-ProfileWhitelistVerifyEvent.patch} (100%) rename patches/server-remapped/{0161-Fix-this-stupid-bullshit.patch => 0163-Fix-this-stupid-bullshit.patch} (100%) rename patches/server-remapped/{0162-Ocelot-despawns-should-honor-nametags-and-leash.patch => 0164-Ocelot-despawns-should-honor-nametags-and-leash.patch} (100%) rename patches/server-remapped/{0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch => 0165-Reset-spawner-timer-when-spawner-event-is-cancelled.patch} (100%) rename patches/server-remapped/{0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch => 0166-Fix-MC-117075-TE-Unload-Lag-Spike.patch} (100%) rename patches/server-remapped/{0165-Allow-specifying-a-custom-authentication-servers-dow.patch => 0167-Allow-specifying-a-custom-authentication-servers-dow.patch} (100%) rename patches/server-remapped/{0166-LivingEntity-setKiller.patch => 0168-LivingEntity-setKiller.patch} (100%) rename patches/server-remapped/{0167-Handle-plugin-prefixes-using-Log4J-configuration.patch => 0169-Handle-plugin-prefixes-using-Log4J-configuration.patch} (100%) rename patches/server-remapped/{0168-Improve-Log4J-Configuration-Plugin-Loggers.patch => 0170-Improve-Log4J-Configuration-Plugin-Loggers.patch} (100%) rename patches/server-remapped/{0169-Add-PlayerJumpEvent.patch => 0171-Add-PlayerJumpEvent.patch} (100%) rename patches/server-remapped/{0170-handle-PacketPlayInKeepAlive-async.patch => 0172-handle-PacketPlayInKeepAlive-async.patch} (100%) rename patches/server-remapped/{0171-Expose-client-protocol-version-and-virtual-host.patch => 0173-Expose-client-protocol-version-and-virtual-host.patch} (100%) rename patches/server-remapped/{0172-revert-serverside-behavior-of-keepalives.patch => 0174-revert-serverside-behavior-of-keepalives.patch} (100%) rename patches/server-remapped/{0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch => 0175-Send-attack-SoundEffects-only-to-players-who-can-see.patch} (100%) rename patches/server-remapped/{0174-Option-for-maximum-exp-value-when-merging-orbs.patch => 0176-Option-for-maximum-exp-value-when-merging-orbs.patch} (100%) rename patches/server-remapped/{0175-Add-PlayerArmorChangeEvent.patch => 0177-Add-PlayerArmorChangeEvent.patch} (100%) rename patches/server-remapped/{0176-Prevent-logins-from-being-processed-when-the-player-.patch => 0178-Prevent-logins-from-being-processed-when-the-player-.patch} (100%) rename patches/server-remapped/{0177-use-CB-BlockState-implementations-for-captured-block.patch => 0179-use-CB-BlockState-implementations-for-captured-block.patch} (100%) rename patches/server-remapped/{0178-API-to-get-a-BlockState-without-a-snapshot.patch => 0180-API-to-get-a-BlockState-without-a-snapshot.patch} (100%) rename patches/server-remapped/{0179-AsyncTabCompleteEvent.patch => 0181-AsyncTabCompleteEvent.patch} (100%) rename patches/server-remapped/{0180-Avoid-NPE-in-PathfinderGoalTempt.patch => 0182-Avoid-NPE-in-PathfinderGoalTempt.patch} (100%) rename patches/server-remapped/{0181-PlayerPickupExperienceEvent.patch => 0183-PlayerPickupExperienceEvent.patch} (100%) rename patches/server-remapped/{0182-ExperienceOrbMergeEvent.patch => 0184-ExperienceOrbMergeEvent.patch} (100%) rename patches/server-remapped/{0183-Ability-to-apply-mending-to-XP-API.patch => 0185-Ability-to-apply-mending-to-XP-API.patch} (100%) rename patches/server-remapped/{0184-Make-max-squid-spawn-height-configurable.patch => 0186-Make-max-squid-spawn-height-configurable.patch} (100%) rename patches/server-remapped/{0185-PreCreatureSpawnEvent.patch => 0187-PreCreatureSpawnEvent.patch} (100%) rename patches/server-remapped/{0186-PlayerNaturallySpawnCreaturesEvent.patch => 0188-PlayerNaturallySpawnCreaturesEvent.patch} (100%) rename patches/server-remapped/{0187-Add-setPlayerProfile-API-for-Skulls.patch => 0189-Add-setPlayerProfile-API-for-Skulls.patch} (100%) rename patches/server-remapped/{0188-Fill-Profile-Property-Events.patch => 0190-Fill-Profile-Property-Events.patch} (100%) rename patches/server-remapped/{0189-PlayerAdvancementCriterionGrantEvent.patch => 0191-PlayerAdvancementCriterionGrantEvent.patch} (100%) rename patches/server-remapped/{0190-Add-ArmorStand-Item-Meta.patch => 0192-Add-ArmorStand-Item-Meta.patch} (100%) rename patches/server-remapped/{0191-Extend-Player-Interact-cancellation.patch => 0193-Extend-Player-Interact-cancellation.patch} (100%) rename patches/server-remapped/{0192-Tameable-getOwnerUniqueId-API.patch => 0194-Tameable-getOwnerUniqueId-API.patch} (100%) rename patches/server-remapped/{0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch => 0195-Toggleable-player-crits-helps-mitigate-hacked-client.patch} (100%) rename patches/server-remapped/{0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch => 0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch} (100%) rename patches/server-remapped/{0195-Disable-Explicit-Network-Manager-Flushing.patch => 0197-Disable-Explicit-Network-Manager-Flushing.patch} (100%) rename patches/server-remapped/{0196-Implement-extended-PaperServerListPingEvent.patch => 0198-Implement-extended-PaperServerListPingEvent.patch} (100%) rename patches/server-remapped/{0197-Improved-Async-Task-Scheduler.patch => 0199-Improved-Async-Task-Scheduler.patch} (100%) rename patches/server-remapped/{0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch => 0200-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch} (100%) rename patches/server-remapped/{0199-Player.setPlayerProfile-API.patch => 0201-Player.setPlayerProfile-API.patch} (100%) rename patches/server-remapped/{0200-Fix-Dragon-Server-Crashes.patch => 0202-Fix-Dragon-Server-Crashes.patch} (100%) rename patches/server-remapped/{0201-getPlayerUniqueId-API.patch => 0203-getPlayerUniqueId-API.patch} (100%) rename patches/server-remapped/{0202-Make-player-data-saving-configurable.patch => 0204-Make-player-data-saving-configurable.patch} (100%) rename patches/server-remapped/{0203-Make-legacy-ping-handler-more-reliable.patch => 0205-Make-legacy-ping-handler-more-reliable.patch} (100%) rename patches/server-remapped/{0204-Call-PaperServerListPingEvent-for-legacy-pings.patch => 0206-Call-PaperServerListPingEvent-for-legacy-pings.patch} (100%) rename patches/server-remapped/{0205-Flag-to-disable-the-channel-limit.patch => 0207-Flag-to-disable-the-channel-limit.patch} (100%) rename patches/server-remapped/{0206-Add-method-to-open-already-placed-sign.patch => 0208-Add-method-to-open-already-placed-sign.patch} (100%) rename patches/server-remapped/{0207-Configurable-sprint-interruption-on-attack.patch => 0209-Configurable-sprint-interruption-on-attack.patch} (100%) rename patches/server-remapped/{0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch => 0210-Fix-exploit-that-allowed-colored-signs-to-be-created.patch} (100%) rename patches/server-remapped/{0209-EndermanEscapeEvent.patch => 0211-EndermanEscapeEvent.patch} (100%) rename patches/server-remapped/{0210-Enderman.teleportRandomly.patch => 0212-Enderman.teleportRandomly.patch} (100%) rename patches/server-remapped/{0211-Block-Enderpearl-Travel-Exploit.patch => 0213-Block-Enderpearl-Travel-Exploit.patch} (100%) rename patches/server-remapped/{0212-Expand-World.spawnParticle-API-and-add-Builder.patch => 0214-Expand-World.spawnParticle-API-and-add-Builder.patch} (100%) rename patches/server-remapped/{0213-EndermanAttackPlayerEvent.patch => 0215-EndermanAttackPlayerEvent.patch} (100%) rename patches/server-remapped/{0214-WitchConsumePotionEvent.patch => 0216-WitchConsumePotionEvent.patch} (100%) rename patches/server-remapped/{0215-WitchThrowPotionEvent.patch => 0217-WitchThrowPotionEvent.patch} (100%) rename patches/server-remapped/{0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch => 0218-Allow-spawning-Item-entities-with-World.spawnEntity.patch} (100%) rename patches/server-remapped/{0217-WitchReadyPotionEvent.patch => 0219-WitchReadyPotionEvent.patch} (100%) rename patches/server-remapped/{0218-ItemStack-getMaxItemUseDuration.patch => 0220-ItemStack-getMaxItemUseDuration.patch} (100%) rename patches/server-remapped/{0219-Implement-EntityTeleportEndGatewayEvent.patch => 0221-Implement-EntityTeleportEndGatewayEvent.patch} (100%) rename patches/server-remapped/{0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch => 0222-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch} (100%) rename patches/server-remapped/{0221-Fix-CraftEntity-hashCode.patch => 0223-Fix-CraftEntity-hashCode.patch} (100%) rename patches/server-remapped/{0222-Configurable-Alternative-LootPool-Luck-Formula.patch => 0224-Configurable-Alternative-LootPool-Luck-Formula.patch} (100%) rename patches/server-remapped/{0223-Print-Error-details-when-failing-to-save-player-data.patch => 0225-Print-Error-details-when-failing-to-save-player-data.patch} (100%) rename patches/server-remapped/{0224-Make-shield-blocking-delay-configurable.patch => 0226-Make-shield-blocking-delay-configurable.patch} (100%) rename patches/server-remapped/{0225-Improve-EntityShootBowEvent.patch => 0227-Improve-EntityShootBowEvent.patch} (100%) rename patches/server-remapped/{0226-PlayerReadyArrowEvent.patch => 0228-PlayerReadyArrowEvent.patch} (100%) rename patches/server-remapped/{0227-Implement-EntityKnockbackByEntityEvent.patch => 0229-Implement-EntityKnockbackByEntityEvent.patch} (100%) rename patches/server-remapped/{0228-Expand-Explosions-API.patch => 0230-Expand-Explosions-API.patch} (100%) rename patches/server-remapped/{0229-LivingEntity-Hand-Raised-Item-Use-API.patch => 0231-LivingEntity-Hand-Raised-Item-Use-API.patch} (100%) rename patches/server-remapped/{0230-RangedEntity-API.patch => 0232-RangedEntity-API.patch} (100%) rename patches/server-remapped/{0231-Add-config-to-disable-ender-dragon-legacy-check.patch => 0233-Add-config-to-disable-ender-dragon-legacy-check.patch} (100%) rename patches/server-remapped/{0232-Implement-World.getEntity-UUID-API.patch => 0234-Implement-World.getEntity-UUID-API.patch} (100%) rename patches/server-remapped/{0233-InventoryCloseEvent-Reason-API.patch => 0235-InventoryCloseEvent-Reason-API.patch} (100%) rename patches/server-remapped/{0234-Vex-getSummoner-API.patch => 0236-Vex-getSummoner-API.patch} (100%) rename patches/server-remapped/{0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch => 0237-Refresh-player-inventory-when-cancelling-PlayerInter.patch} (100%) rename patches/server-remapped/{0236-Don-t-change-the-Entity-Random-seed-for-squids.patch => 0238-Don-t-change-the-Entity-Random-seed-for-squids.patch} (100%) rename patches/server-remapped/{0237-Re-add-vanilla-entity-warnings-for-duplicates.patch => 0239-Re-add-vanilla-entity-warnings-for-duplicates.patch} (100%) rename patches/server-remapped/{0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch => 0240-Avoid-item-merge-if-stack-size-above-max-stack-size.patch} (100%) rename patches/server-remapped/{0239-Use-asynchronous-Log4j-2-loggers.patch => 0241-Use-asynchronous-Log4j-2-loggers.patch} (100%) rename patches/server-remapped/{0240-add-more-information-to-Entity.toString.patch => 0242-add-more-information-to-Entity.toString.patch} (100%) rename patches/server-remapped/{0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch => 0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch} (100%) rename patches/server-remapped/{0242-EnderDragon-Events.patch => 0244-EnderDragon-Events.patch} (100%) rename patches/server-remapped/{0243-PlayerElytraBoostEvent.patch => 0245-PlayerElytraBoostEvent.patch} (100%) rename patches/server-remapped/{0244-Improve-BlockPosition-inlining.patch => 0246-Improve-BlockPosition-inlining.patch} (100%) rename patches/server-remapped/{0245-Optimize-RegistryID.c.patch => 0247-Optimize-RegistryID.c.patch} (100%) rename patches/server-remapped/{0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch => 0248-Option-to-prevent-armor-stands-from-doing-entity-loo.patch} (100%) rename patches/server-remapped/{0247-Vanished-players-don-t-have-rights.patch => 0249-Vanished-players-don-t-have-rights.patch} (100%) rename patches/server-remapped/{0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch => 0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch} (100%) rename patches/server-remapped/{0249-Add-some-Debug-to-Chunk-Entity-slices.patch => 0251-Add-some-Debug-to-Chunk-Entity-slices.patch} (100%) rename patches/server-remapped/{0250-SkeletonHorse-Additions.patch => 0252-SkeletonHorse-Additions.patch} (100%) rename patches/server-remapped/{0251-Prevent-Saving-Bad-entities-to-chunks.patch => 0253-Prevent-Saving-Bad-entities-to-chunks.patch} (100%) rename patches/server-remapped/{0252-Don-t-call-getItemMeta-on-hasItemMeta.patch => 0254-Don-t-call-getItemMeta-on-hasItemMeta.patch} (100%) rename patches/server-remapped/{0253-Ignore-Dead-Entities-in-entityList-iteration.patch => 0255-Ignore-Dead-Entities-in-entityList-iteration.patch} (100%) rename patches/server-remapped/{0254-Implement-Expanded-ArmorStand-API.patch => 0256-Implement-Expanded-ArmorStand-API.patch} (100%) rename patches/server-remapped/{0255-AnvilDamageEvent.patch => 0257-AnvilDamageEvent.patch} (100%) rename patches/server-remapped/{0256-Add-TNTPrimeEvent.patch => 0258-Add-TNTPrimeEvent.patch} (100%) rename patches/server-remapped/{0257-Break-up-and-make-tab-spam-limits-configurable.patch => 0259-Break-up-and-make-tab-spam-limits-configurable.patch} (100%) rename patches/server-remapped/{0258-Add-hand-to-bucket-events.patch => 0260-Add-hand-to-bucket-events.patch} (100%) rename patches/server-remapped/{0259-MC-135506-Experience-should-save-as-Integers.patch => 0261-MC-135506-Experience-should-save-as-Integers.patch} (100%) rename patches/server-remapped/{0260-Fix-client-rendering-skulls-from-same-user.patch => 0262-Fix-client-rendering-skulls-from-same-user.patch} (100%) rename patches/server-remapped/{0261-Add-Early-Warning-Feature-to-WatchDog.patch => 0263-Add-Early-Warning-Feature-to-WatchDog.patch} (100%) rename patches/server-remapped/{0262-Make-EnderDragon-implement-Mob.patch => 0264-Make-EnderDragon-implement-Mob.patch} (100%) rename patches/server-remapped/{0263-Use-ConcurrentHashMap-in-JsonList.patch => 0265-Use-ConcurrentHashMap-in-JsonList.patch} (100%) rename patches/server-remapped/{0264-Use-a-Queue-for-Queueing-Commands.patch => 0266-Use-a-Queue-for-Queueing-Commands.patch} (100%) rename patches/server-remapped/{0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch => 0267-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch} (100%) rename patches/server-remapped/{0266-Allow-disabling-armour-stand-ticking.patch => 0268-Allow-disabling-armour-stand-ticking.patch} (100%) rename patches/server-remapped/{0267-Optimize-BlockPosition-helper-methods.patch => 0269-Optimize-BlockPosition-helper-methods.patch} (100%) rename patches/server-remapped/{0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch => 0270-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch} (100%) rename patches/server-remapped/{0269-Slime-Pathfinder-Events.patch => 0271-Slime-Pathfinder-Events.patch} (100%) rename patches/server-remapped/{0270-Configurable-speed-for-water-flowing-over-lava.patch => 0272-Configurable-speed-for-water-flowing-over-lava.patch} (100%) rename patches/server-remapped/{0271-Optimize-CraftBlockData-Creation.patch => 0273-Optimize-CraftBlockData-Creation.patch} (100%) rename patches/server-remapped/{0272-Optimize-RegistryMaterials.patch => 0274-Optimize-RegistryMaterials.patch} (100%) rename patches/server-remapped/{0273-Add-PhantomPreSpawnEvent.patch => 0275-Add-PhantomPreSpawnEvent.patch} (100%) rename patches/server-remapped/{0274-Add-More-Creeper-API.patch => 0276-Add-More-Creeper-API.patch} (100%) rename patches/server-remapped/{0275-Inventory-removeItemAnySlot.patch => 0277-Inventory-removeItemAnySlot.patch} (100%) rename patches/server-remapped/{0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch => 0278-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch} (100%) rename patches/server-remapped/{0277-Add-ray-tracing-methods-to-LivingEntity.patch => 0279-Add-ray-tracing-methods-to-LivingEntity.patch} (100%) rename patches/server-remapped/{0278-Expose-attack-cooldown-methods-for-Player.patch => 0280-Expose-attack-cooldown-methods-for-Player.patch} (100%) rename patches/server-remapped/{0279-Improve-death-events.patch => 0281-Improve-death-events.patch} (100%) rename patches/server-remapped/{0280-Allow-chests-to-be-placed-with-NBT-data.patch => 0282-Allow-chests-to-be-placed-with-NBT-data.patch} (100%) rename patches/server-remapped/{0281-Mob-Pathfinding-API.patch => 0283-Mob-Pathfinding-API.patch} (100%) rename patches/server-remapped/{0282-Prevent-chunk-loading-from-Fluid-Flowing.patch => 0284-Prevent-chunk-loading-from-Fluid-Flowing.patch} (100%) rename patches/server-remapped/{0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch => 0285-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch} (100%) rename patches/server-remapped/{0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch => 0286-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch} (100%) rename patches/server-remapped/{0285-Prevent-mob-spawning-from-loading-generating-chunks.patch => 0287-Prevent-mob-spawning-from-loading-generating-chunks.patch} (100%) rename patches/server-remapped/{0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch => 0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch} (100%) rename patches/server-remapped/{0287-Implement-furnace-cook-speed-multiplier-API.patch => 0289-Implement-furnace-cook-speed-multiplier-API.patch} (100%) rename patches/server-remapped/{0288-PreSpawnerSpawnEvent.patch => 0290-PreSpawnerSpawnEvent.patch} (100%) rename patches/server-remapped/{0289-Catch-JsonParseException-in-Entity-and-TE-names.patch => 0291-Catch-JsonParseException-in-Entity-and-TE-names.patch} (100%) rename patches/server-remapped/{0290-Honor-EntityAgeable.ageLock.patch => 0292-Honor-EntityAgeable.ageLock.patch} (100%) rename patches/server-remapped/{0291-Configurable-connection-throttle-kick-message.patch => 0293-Configurable-connection-throttle-kick-message.patch} (100%) rename patches/server-remapped/{0292-Hook-into-CB-plugin-rewrites.patch => 0294-Hook-into-CB-plugin-rewrites.patch} (100%) rename patches/server-remapped/{0293-Allow-setting-the-vex-s-summoner.patch => 0295-Allow-setting-the-vex-s-summoner.patch} (100%) rename patches/server-remapped/{0294-Add-sun-related-API.patch => 0296-Add-sun-related-API.patch} (100%) rename patches/server-remapped/{0295-Turtle-API.patch => 0297-Turtle-API.patch} (100%) rename patches/server-remapped/{0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch => 0298-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch} (100%) rename patches/server-remapped/{0297-Call-player-spectator-target-events-and-improve-impl.patch => 0299-Call-player-spectator-target-events-and-improve-impl.patch} (100%) rename patches/server-remapped/{0298-Add-Velocity-IP-Forwarding-Support.patch => 0300-Add-Velocity-IP-Forwarding-Support.patch} (100%) rename patches/server-remapped/{0299-Add-more-Witch-API.patch => 0301-Add-more-Witch-API.patch} (100%) rename patches/server-remapped/{0300-Check-Drowned-for-Villager-Aggression-Config.patch => 0302-Check-Drowned-for-Villager-Aggression-Config.patch} (100%) rename patches/server-remapped/{0301-Here-s-Johnny.patch => 0303-Here-s-Johnny.patch} (100%) rename patches/server-remapped/{0302-Add-option-to-prevent-players-from-moving-into-unloa.patch => 0304-Add-option-to-prevent-players-from-moving-into-unloa.patch} (100%) rename patches/server-remapped/{0303-Reset-players-airTicks-on-respawn.patch => 0305-Reset-players-airTicks-on-respawn.patch} (100%) rename patches/server-remapped/{0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch => 0306-Don-t-sleep-after-profile-lookups-if-not-needed.patch} (100%) rename patches/server-remapped/{0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch => 0307-Improve-Server-Thread-Pool-and-Thread-Priorities.patch} (100%) rename patches/server-remapped/{0306-Optimize-World-Time-Updates.patch => 0308-Optimize-World-Time-Updates.patch} (100%) rename patches/server-remapped/{0307-Restore-custom-InventoryHolder-support.patch => 0309-Restore-custom-InventoryHolder-support.patch} (100%) rename patches/server-remapped/{0308-Use-Vanilla-Minecart-Speeds.patch => 0310-Use-Vanilla-Minecart-Speeds.patch} (100%) rename patches/server-remapped/{0309-Fix-SpongeAbsortEvent-handling.patch => 0311-Fix-SpongeAbsortEvent-handling.patch} (100%) rename patches/server-remapped/{0310-Don-t-allow-digging-into-unloaded-chunks.patch => 0312-Don-t-allow-digging-into-unloaded-chunks.patch} (100%) rename patches/server-remapped/{0311-Book-Size-Limits.patch => 0313-Book-Size-Limits.patch} (100%) rename patches/server-remapped/{0312-Make-the-default-permission-message-configurable.patch => 0314-Make-the-default-permission-message-configurable.patch} (100%) rename patches/server-remapped/{0313-Prevent-rayTrace-from-loading-chunks.patch => 0315-Prevent-rayTrace-from-loading-chunks.patch} (100%) rename patches/server-remapped/{0314-Handle-Large-Packets-disconnecting-client.patch => 0316-Handle-Large-Packets-disconnecting-client.patch} (100%) rename patches/server-remapped/{0315-force-entity-dismount-during-teleportation.patch => 0317-force-entity-dismount-during-teleportation.patch} (100%) rename patches/server-remapped/{0316-Add-more-Zombie-API.patch => 0318-Add-more-Zombie-API.patch} (100%) rename patches/server-remapped/{0317-Add-PlayerConnectionCloseEvent.patch => 0319-Add-PlayerConnectionCloseEvent.patch} (100%) rename patches/server-remapped/{0318-Prevent-Enderman-from-loading-chunks.patch => 0320-Prevent-Enderman-from-loading-chunks.patch} (100%) rename patches/server-remapped/{0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch => 0321-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch} (100%) rename patches/server-remapped/{0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch => 0322-Workaround-for-vehicle-tracking-issue-on-disconnect.patch} (100%) rename patches/server-remapped/{0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch => 0323-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch} (100%) rename patches/server-remapped/{0322-Block-Entity-remove-from-being-called-on-Players.patch => 0324-Block-Entity-remove-from-being-called-on-Players.patch} (100%) rename patches/server-remapped/{0323-BlockDestroyEvent.patch => 0325-BlockDestroyEvent.patch} (100%) rename patches/server-remapped/{0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch => 0326-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch} (100%) rename patches/server-remapped/{0325-Fix-sign-edit-memory-leak.patch => 0327-Fix-sign-edit-memory-leak.patch} (100%) rename patches/server-remapped/{0326-Limit-Client-Sign-length-more.patch => 0328-Limit-Client-Sign-length-more.patch} (100%) rename patches/server-remapped/{0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch => 0329-Don-t-check-ConvertSigns-boolean-every-sign-save.patch} (100%) rename patches/server-remapped/{0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch => 0330-Optimize-Network-Manager-and-add-advanced-packet-sup.patch} (100%) rename patches/server-remapped/{0329-Handle-Oversized-Tile-Entities-in-chunks.patch => 0331-Handle-Oversized-Tile-Entities-in-chunks.patch} (100%) rename patches/server-remapped/{0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch => 0332-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch} (100%) rename patches/server-remapped/{0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch => 0333-Set-Zombie-last-tick-at-start-of-drowning-process.patch} (100%) rename patches/server-remapped/{0332-Allow-Saving-of-Oversized-Chunks.patch => 0334-Allow-Saving-of-Oversized-Chunks.patch} (100%) rename patches/server-remapped/{0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch => 0335-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch} (100%) rename patches/server-remapped/{0334-Add-LivingEntity-getTargetEntity.patch => 0336-Add-LivingEntity-getTargetEntity.patch} (100%) rename patches/server-remapped/{0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch => 0337-Use-proper-max-length-when-serialising-BungeeCord-te.patch} (100%) rename patches/server-remapped/{0336-Entity-getEntitySpawnReason.patch => 0338-Entity-getEntitySpawnReason.patch} (100%) rename patches/server-remapped/{0337-Update-entity-Metadata-for-all-tracked-players.patch => 0339-Update-entity-Metadata-for-all-tracked-players.patch} (100%) rename patches/server-remapped/{0338-Implement-PlayerPostRespawnEvent.patch => 0340-Implement-PlayerPostRespawnEvent.patch} (100%) rename patches/server-remapped/{0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch => 0341-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch} (100%) rename patches/server-remapped/{0340-Server-Tick-Events.patch => 0342-Server-Tick-Events.patch} (100%) rename patches/server-remapped/{0341-PlayerDeathEvent-getItemsToKeep.patch => 0343-PlayerDeathEvent-getItemsToKeep.patch} (100%) rename patches/server-remapped/{0342-Optimize-Captured-TileEntity-Lookup.patch => 0344-Optimize-Captured-TileEntity-Lookup.patch} (100%) rename patches/server-remapped/{0343-Add-Heightmap-API.patch => 0345-Add-Heightmap-API.patch} (100%) rename patches/server-remapped/{0344-Mob-Spawner-API-Enhancements.patch => 0346-Mob-Spawner-API-Enhancements.patch} (100%) rename patches/server-remapped/{0345-Per-Player-View-Distance-API-placeholders.patch => 0347-Per-Player-View-Distance-API-placeholders.patch} (100%) rename patches/server-remapped/{0346-Fix-CB-call-to-changed-postToMainThread-method.patch => 0348-Fix-CB-call-to-changed-postToMainThread-method.patch} (100%) rename patches/server-remapped/{0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch => 0349-Fix-sounds-when-item-frames-are-modified-MC-123450.patch} (100%) rename patches/server-remapped/{0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch => 0350-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch} (100%) rename patches/server-remapped/{0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch => 0351-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch} (100%) rename patches/server-remapped/{0350-Duplicate-UUID-Resolve-Option.patch => 0352-Duplicate-UUID-Resolve-Option.patch} (100%) rename patches/server-remapped/{0351-improve-CraftWorld-isChunkLoaded.patch => 0353-improve-CraftWorld-isChunkLoaded.patch} (100%) rename patches/server-remapped/{0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch => 0354-Configurable-Keep-Spawn-Loaded-range-per-world.patch} (100%) rename patches/server-remapped/{0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch => 0355-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch} (100%) rename patches/server-remapped/{0354-ChunkMapDistance-CME.patch => 0356-ChunkMapDistance-CME.patch} (100%) rename patches/server-remapped/{0355-Implement-CraftBlockSoundGroup.patch => 0357-Implement-CraftBlockSoundGroup.patch} (100%) rename patches/server-remapped/{0356-Chunk-debug-command.patch => 0358-Chunk-debug-command.patch} (100%) rename patches/server-remapped/{0357-Catch-exceptions-from-dispenser-entity-spawns.patch => 0359-Catch-exceptions-from-dispenser-entity-spawns.patch} (100%) rename patches/server-remapped/{0358-Fix-World-isChunkGenerated-calls.patch => 0360-Fix-World-isChunkGenerated-calls.patch} (100%) rename patches/server-remapped/{0359-Show-blockstate-location-if-we-failed-to-read-it.patch => 0361-Show-blockstate-location-if-we-failed-to-read-it.patch} (100%) rename patches/server-remapped/{0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch => 0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch} (100%) rename patches/server-remapped/{0361-incremental-chunk-saving.patch => 0363-incremental-chunk-saving.patch} (100%) rename patches/server-remapped/{0362-Anti-Xray.patch => 0364-Anti-Xray.patch} (100%) rename patches/server-remapped/{0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch => 0365-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch} (100%) rename patches/server-remapped/{0364-Configurable-projectile-relative-velocity.patch => 0366-Configurable-projectile-relative-velocity.patch} (100%) rename patches/server-remapped/{0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch => 0367-Mark-entities-as-being-ticked-when-notifying-navigat.patch} (100%) rename patches/server-remapped/{0366-offset-item-frame-ticking.patch => 0368-offset-item-frame-ticking.patch} (100%) rename patches/server-remapped/{0367-Avoid-hopper-searches-if-there-are-no-items.patch => 0369-Avoid-hopper-searches-if-there-are-no-items.patch} (100%) rename patches/server-remapped/{0368-Asynchronous-chunk-IO-and-loading.patch => 0370-Asynchronous-chunk-IO-and-loading.patch} (100%) rename patches/server-remapped/{0369-Use-getChunkIfLoadedImmediately-in-places.patch => 0371-Use-getChunkIfLoadedImmediately-in-places.patch} (100%) rename patches/server-remapped/{0370-Reduce-sync-loads.patch => 0372-Reduce-sync-loads.patch} (100%) rename patches/server-remapped/{0371-Implement-alternative-item-despawn-rate.patch => 0373-Implement-alternative-item-despawn-rate.patch} (100%) rename patches/server-remapped/{0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch => 0374-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch} (100%) rename patches/server-remapped/{0373-Fix-MC-158900.patch => 0375-Fix-MC-158900.patch} (100%) rename patches/server-remapped/{0374-implement-optional-per-player-mob-spawns.patch => 0376-implement-optional-per-player-mob-spawns.patch} (100%) rename patches/server-remapped/{0375-Prevent-consuming-the-wrong-itemstack.patch => 0377-Prevent-consuming-the-wrong-itemstack.patch} (100%) rename patches/server-remapped/{0376-Generator-Settings.patch => 0378-Generator-Settings.patch} (100%) rename patches/server-remapped/{0377-Fix-MC-161754.patch => 0379-Fix-MC-161754.patch} (100%) rename patches/server-remapped/{0378-Performance-improvement-for-Chunk.getEntities.patch => 0380-Performance-improvement-for-Chunk.getEntities.patch} (100%) rename patches/server-remapped/{0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch => 0381-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch} (100%) rename patches/server-remapped/{0380-Expose-the-internal-current-tick.patch => 0382-Expose-the-internal-current-tick.patch} (100%) rename patches/server-remapped/{0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch => 0383-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch} (100%) rename patches/server-remapped/{0382-Add-option-to-disable-pillager-patrols.patch => 0384-Add-option-to-disable-pillager-patrols.patch} (100%) rename patches/server-remapped/{0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch => 0385-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch} (100%) rename patches/server-remapped/{0384-PlayerLaunchProjectileEvent.patch => 0386-PlayerLaunchProjectileEvent.patch} (100%) rename patches/server-remapped/{0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch => 0387-Add-CraftMagicNumbers.isSupportedApiVersion.patch} (100%) rename patches/server-remapped/{0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch => 0388-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch} (100%) rename patches/server-remapped/{0387-MC-145656-Fix-Follow-Range-Initial-Target.patch => 0389-MC-145656-Fix-Follow-Range-Initial-Target.patch} (100%) rename patches/server-remapped/{0388-Optimize-Hoppers.patch => 0390-Optimize-Hoppers.patch} (100%) rename patches/server-remapped/{0389-PlayerDeathEvent-shouldDropExperience.patch => 0391-PlayerDeathEvent-shouldDropExperience.patch} (100%) rename patches/server-remapped/{0390-Prevent-bees-loading-chunks-checking-hive-position.patch => 0392-Prevent-bees-loading-chunks-checking-hive-position.patch} (100%) rename patches/server-remapped/{0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch => 0393-Don-t-load-Chunks-from-Hoppers-and-other-things.patch} (100%) rename patches/server-remapped/{0392-Guard-against-serializing-mismatching-chunk-coordina.patch => 0394-Guard-against-serializing-mismatching-chunk-coordina.patch} (100%) rename patches/server-remapped/{0393-Optimise-IEntityAccess-getPlayerByUUID.patch => 0395-Optimise-IEntityAccess-getPlayerByUUID.patch} (100%) rename patches/server-remapped/{0394-Fix-items-not-falling-correctly.patch => 0396-Fix-items-not-falling-correctly.patch} (100%) rename patches/server-remapped/{0395-Lag-compensate-eating.patch => 0397-Lag-compensate-eating.patch} (100%) rename patches/server-remapped/{0396-Optimize-call-to-getFluid-for-explosions.patch => 0398-Optimize-call-to-getFluid-for-explosions.patch} (100%) rename patches/server-remapped/{0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch => 0399-Fix-last-firework-in-stack-not-having-effects-when-d.patch} (100%) rename patches/server-remapped/{0398-Add-effect-to-block-break-naturally.patch => 0400-Add-effect-to-block-break-naturally.patch} (100%) rename patches/server-remapped/{0399-Tracking-Range-Improvements.patch => 0401-Tracking-Range-Improvements.patch} (100%) rename patches/server-remapped/{0400-Entity-Activation-Range-2.0.patch => 0402-Entity-Activation-Range-2.0.patch} (100%) rename patches/server-remapped/{0401-Fix-items-vanishing-through-end-portal.patch => 0403-Fix-items-vanishing-through-end-portal.patch} (100%) rename patches/server-remapped/{0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch => 0404-Bees-get-gravity-in-void.-Fixes-MC-167279.patch} (100%) rename patches/server-remapped/{0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch => 0405-Optimise-getChunkAt-calls-for-loaded-chunks.patch} (100%) rename patches/server-remapped/{0404-Allow-overriding-the-java-version-check.patch => 0406-Allow-overriding-the-java-version-check.patch} (100%) rename patches/server-remapped/{0405-Add-ThrownEggHatchEvent.patch => 0407-Add-ThrownEggHatchEvent.patch} (100%) rename patches/server-remapped/{0406-Optimise-random-block-ticking.patch => 0408-Optimise-random-block-ticking.patch} (100%) rename patches/server-remapped/{0407-Entity-Jump-API.patch => 0409-Entity-Jump-API.patch} (100%) rename patches/server-remapped/{0408-Add-option-to-nerf-pigmen-from-nether-portals.patch => 0410-Add-option-to-nerf-pigmen-from-nether-portals.patch} (100%) rename patches/server-remapped/{0409-Make-the-GUI-graph-fancier.patch => 0411-Make-the-GUI-graph-fancier.patch} (100%) rename patches/server-remapped/{0410-add-hand-to-BlockMultiPlaceEvent.patch => 0412-add-hand-to-BlockMultiPlaceEvent.patch} (100%) rename patches/server-remapped/{0411-Prevent-teleporting-dead-entities.patch => 0413-Prevent-teleporting-dead-entities.patch} (100%) rename patches/server-remapped/{0412-Validate-tripwire-hook-placement-before-update.patch => 0414-Validate-tripwire-hook-placement-before-update.patch} (100%) rename patches/server-remapped/{0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch => 0415-Add-option-to-allow-iron-golems-to-spawn-in-air.patch} (100%) rename patches/server-remapped/{0414-Configurable-chance-of-villager-zombie-infection.patch => 0416-Configurable-chance-of-villager-zombie-infection.patch} (100%) rename patches/server-remapped/{0415-Optimise-Chunk-getFluid.patch => 0417-Optimise-Chunk-getFluid.patch} (100%) rename patches/server-remapped/{0416-Optimise-TickListServer-by-rewriting-it.patch => 0418-Optimise-TickListServer-by-rewriting-it.patch} (100%) rename patches/server-remapped/{0417-Pillager-patrol-spawn-settings-and-per-player-option.patch => 0419-Pillager-patrol-spawn-settings-and-per-player-option.patch} (100%) rename patches/server-remapped/{0418-Ensure-Entity-is-never-double-registered.patch => 0420-Ensure-Entity-is-never-double-registered.patch} (100%) rename patches/server-remapped/{0419-Fix-unregistering-entities-from-unloading-chunks.patch => 0421-Fix-unregistering-entities-from-unloading-chunks.patch} (100%) rename patches/server-remapped/{0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch => 0422-Remote-Connections-shouldn-t-hold-up-shutdown.patch} (100%) rename patches/server-remapped/{0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch => 0423-Do-not-allow-bees-to-load-chunks-for-beehives.patch} (100%) rename patches/server-remapped/{0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch => 0424-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch} (100%) rename patches/server-remapped/{0423-Optimize-Collision-to-not-load-chunks.patch => 0425-Optimize-Collision-to-not-load-chunks.patch} (100%) rename patches/server-remapped/{0424-Don-t-tick-dead-players.patch => 0426-Don-t-tick-dead-players.patch} (100%) rename patches/server-remapped/{0425-Dead-Player-s-shouldn-t-be-able-to-move.patch => 0427-Dead-Player-s-shouldn-t-be-able-to-move.patch} (100%) rename patches/server-remapped/{0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch => 0428-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch} (100%) rename patches/server-remapped/{0427-Increase-Light-Queue-Size.patch => 0429-Increase-Light-Queue-Size.patch} (100%) rename patches/server-remapped/{0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch => 0430-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch} (100%) rename patches/server-remapped/{0429-Don-t-move-existing-players-to-world-spawn.patch => 0431-Don-t-move-existing-players-to-world-spawn.patch} (100%) rename patches/server-remapped/{0430-Add-tick-times-API-and-mspt-command.patch => 0432-Add-tick-times-API-and-mspt-command.patch} (100%) rename patches/server-remapped/{0431-Expose-MinecraftServer-isRunning.patch => 0433-Expose-MinecraftServer-isRunning.patch} (100%) rename patches/server-remapped/{0432-Add-Raw-Byte-ItemStack-Serialization.patch => 0434-Add-Raw-Byte-ItemStack-Serialization.patch} (100%) rename patches/server-remapped/{0433-Remove-streams-from-Mob-AI-System.patch => 0435-Remove-streams-from-Mob-AI-System.patch} (100%) rename patches/server-remapped/{0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch => 0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch} (100%) rename patches/server-remapped/{0435-Async-command-map-building.patch => 0437-Async-command-map-building.patch} (100%) rename patches/server-remapped/{0436-Improved-Watchdog-Support.patch => 0438-Improved-Watchdog-Support.patch} (100%) rename patches/server-remapped/{0437-Optimize-Pathfinding.patch => 0439-Optimize-Pathfinding.patch} (100%) rename patches/server-remapped/{0438-Reduce-Either-Optional-allocation.patch => 0440-Reduce-Either-Optional-allocation.patch} (100%) rename patches/server-remapped/{0439-Remove-streams-from-PairedQueue.patch => 0441-Remove-streams-from-PairedQueue.patch} (100%) rename patches/server-remapped/{0440-Reduce-memory-footprint-of-NBTTagCompound.patch => 0442-Reduce-memory-footprint-of-NBTTagCompound.patch} (100%) rename patches/server-remapped/{0441-Prevent-opening-inventories-when-frozen.patch => 0443-Prevent-opening-inventories-when-frozen.patch} (100%) rename patches/server-remapped/{0442-Optimise-ArraySetSorted-removeIf.patch => 0444-Optimise-ArraySetSorted-removeIf.patch} (100%) rename patches/server-remapped/{0443-Don-t-run-entity-collision-code-if-not-needed.patch => 0445-Don-t-run-entity-collision-code-if-not-needed.patch} (100%) rename patches/server-remapped/{0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch => 0446-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch} (100%) rename patches/server-remapped/{0445-Restrict-vanilla-teleport-command-to-valid-locations.patch => 0447-Restrict-vanilla-teleport-command-to-valid-locations.patch} (100%) rename patches/server-remapped/{0446-Implement-Player-Client-Options-API.patch => 0448-Implement-Player-Client-Options-API.patch} (100%) rename patches/server-remapped/{0447-Fix-Chunk-Post-Processing-deadlock-risk.patch => 0449-Fix-Chunk-Post-Processing-deadlock-risk.patch} (100%) rename patches/server-remapped/{0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch => 0450-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch} (100%) rename patches/server-remapped/{0449-Broadcast-join-message-to-console.patch => 0451-Broadcast-join-message-to-console.patch} (100%) rename patches/server-remapped/{0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch => 0452-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch} (100%) rename patches/server-remapped/{0451-Load-Chunks-for-Login-Asynchronously.patch => 0453-Load-Chunks-for-Login-Asynchronously.patch} (100%) rename patches/server-remapped/{0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch => 0454-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch} (100%) rename patches/server-remapped/{0453-Add-PlayerAttackEntityCooldownResetEvent.patch => 0455-Add-PlayerAttackEntityCooldownResetEvent.patch} (100%) rename patches/server-remapped/{0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch => 0456-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch} (100%) rename patches/server-remapped/{0455-Don-t-fire-BlockFade-on-worldgen-threads.patch => 0457-Don-t-fire-BlockFade-on-worldgen-threads.patch} (100%) rename patches/server-remapped/{0456-Add-phantom-creative-and-insomniac-controls.patch => 0458-Add-phantom-creative-and-insomniac-controls.patch} (100%) rename patches/server-remapped/{0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch => 0459-Fix-numerous-item-duplication-issues-and-teleport-is.patch} (100%) rename patches/server-remapped/{0458-Implement-Brigadier-Mojang-API.patch => 0460-Implement-Brigadier-Mojang-API.patch} (100%) rename patches/server-remapped/{0459-Villager-Restocks-API.patch => 0461-Villager-Restocks-API.patch} (100%) rename patches/server-remapped/{0460-Validate-PickItem-Packet-and-kick-for-invalid.patch => 0462-Validate-PickItem-Packet-and-kick-for-invalid.patch} (100%) rename patches/server-remapped/{0461-Expose-game-version.patch => 0463-Expose-game-version.patch} (100%) rename patches/server-remapped/{0462-Optimize-Voxel-Shape-Merging.patch => 0464-Optimize-Voxel-Shape-Merging.patch} (100%) rename patches/server-remapped/{0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch => 0465-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch} (100%) rename patches/server-remapped/{0464-Implement-Mob-Goal-API.patch => 0466-Implement-Mob-Goal-API.patch} (100%) rename patches/server-remapped/{0465-Use-distance-map-to-optimise-entity-tracker.patch => 0467-Use-distance-map-to-optimise-entity-tracker.patch} (100%) rename patches/server-remapped/{0466-Optimize-isOutsideRange-to-use-distance-maps.patch => 0468-Optimize-isOutsideRange-to-use-distance-maps.patch} (100%) rename patches/server-remapped/{0467-Stop-copy-on-write-operations-for-updating-light-dat.patch => 0469-Stop-copy-on-write-operations-for-updating-light-dat.patch} (100%) rename patches/server-remapped/{0468-No-Tick-view-distance-implementation.patch => 0470-No-Tick-view-distance-implementation.patch} (100%) rename patches/server-remapped/{0469-Add-villager-reputation-API.patch => 0471-Add-villager-reputation-API.patch} (100%) rename patches/server-remapped/{0470-Fix-Light-Command.patch => 0472-Fix-Light-Command.patch} (100%) rename patches/server-remapped/{0471-Fix-PotionEffect-ignores-icon-flag.patch => 0473-Fix-PotionEffect-ignores-icon-flag.patch} (100%) rename patches/server-remapped/{0472-Optimize-brigadier-child-sorting-performance.patch => 0474-Optimize-brigadier-child-sorting-performance.patch} (100%) rename patches/server-remapped/{0473-Potential-bed-API.patch => 0475-Potential-bed-API.patch} (100%) rename patches/server-remapped/{0474-Wait-for-Async-Tasks-during-shutdown.patch => 0476-Wait-for-Async-Tasks-during-shutdown.patch} (100%) rename patches/server-remapped/{0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch => 0477-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch} (100%) rename patches/server-remapped/{0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch => 0478-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch} (100%) rename patches/server-remapped/{0477-Optimize-NibbleArray-to-use-pooled-buffers.patch => 0479-Optimize-NibbleArray-to-use-pooled-buffers.patch} (100%) rename patches/server-remapped/{0478-Reduce-MutableInt-allocations-from-light-engine.patch => 0480-Reduce-MutableInt-allocations-from-light-engine.patch} (100%) rename patches/server-remapped/{0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch => 0481-Reduce-allocation-of-Vec3D-by-entity-tracker.patch} (100%) rename patches/server-remapped/{0480-Ensure-safe-gateway-teleport.patch => 0482-Ensure-safe-gateway-teleport.patch} (100%) rename patches/server-remapped/{0481-Add-option-for-console-having-all-permissions.patch => 0483-Add-option-for-console-having-all-permissions.patch} (100%) rename patches/server-remapped/{0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch => 0484-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch} (100%) rename patches/server-remapped/{0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch => 0485-Workaround-for-Client-Lag-Spikes-MC-162253.patch} (100%) rename patches/server-remapped/{0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch => 0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch} (100%) rename patches/server-remapped/{0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch => 0487-Optimize-sending-packets-to-nearby-locations-sounds-.patch} (100%) rename patches/server-remapped/{0486-Improve-Chunk-Status-Transition-Speed.patch => 0488-Improve-Chunk-Status-Transition-Speed.patch} (100%) rename patches/server-remapped/{0487-Fix-villager-trading-demand-MC-163962.patch => 0489-Fix-villager-trading-demand-MC-163962.patch} (100%) rename patches/server-remapped/{0488-Maps-shouldn-t-load-chunks.patch => 0490-Maps-shouldn-t-load-chunks.patch} (100%) rename patches/server-remapped/{0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch => 0491-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch} (100%) rename patches/server-remapped/{0490-Optimize-Bit-Operations-by-inlining.patch => 0492-Optimize-Bit-Operations-by-inlining.patch} (100%) rename patches/server-remapped/{0491-Optimize-Light-Engine.patch => 0493-Optimize-Light-Engine.patch} (100%) rename patches/server-remapped/{0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch => 0494-Delay-Chunk-Unloads-based-on-Player-Movement.patch} (100%) rename patches/server-remapped/{0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch => 0495-Add-Plugin-Tickets-to-API-Chunk-Methods.patch} (100%) rename patches/server-remapped/{0494-Fix-missing-chunks-due-to-integer-overflow.patch => 0496-Fix-missing-chunks-due-to-integer-overflow.patch} (100%) rename patches/server-remapped/{0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch => 0497-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch} (100%) rename patches/server-remapped/{0496-Fix-piston-physics-inconsistency-MC-188840.patch => 0498-Fix-piston-physics-inconsistency-MC-188840.patch} (100%) rename patches/server-remapped/{0497-Fix-sand-duping.patch => 0499-Fix-sand-duping.patch} (100%) rename patches/server-remapped/{0498-Prevent-position-desync-in-playerconnection-causing-.patch => 0500-Prevent-position-desync-in-playerconnection-causing-.patch} (100%) rename patches/server-remapped/{0499-Fix-enderdragon-exp-dupe.patch => 0501-Fix-enderdragon-exp-dupe.patch} (100%) rename patches/server-remapped/{0500-Inventory-getHolder-method-without-block-snapshot.patch => 0502-Inventory-getHolder-method-without-block-snapshot.patch} (100%) rename patches/server-remapped/{0501-Expose-Arrow-getItemStack.patch => 0503-Expose-Arrow-getItemStack.patch} (100%) rename patches/server-remapped/{0502-Add-and-implement-PlayerRecipeBookClickEvent.patch => 0504-Add-and-implement-PlayerRecipeBookClickEvent.patch} (100%) rename patches/server-remapped/{0503-Hide-sync-chunk-writes-behind-flag.patch => 0505-Hide-sync-chunk-writes-behind-flag.patch} (100%) rename patches/server-remapped/{0504-Limit-lightning-strike-effect-distance.patch => 0506-Limit-lightning-strike-effect-distance.patch} (100%) rename patches/server-remapped/{0505-Add-permission-for-command-blocks.patch => 0507-Add-permission-for-command-blocks.patch} (100%) rename patches/server-remapped/{0506-Ensure-Entity-AABB-s-are-never-invalid.patch => 0508-Ensure-Entity-AABB-s-are-never-invalid.patch} (100%) rename patches/server-remapped/{0507-Optimize-WorldBorder-collision-checks-and-air.patch => 0509-Optimize-WorldBorder-collision-checks-and-air.patch} (100%) rename patches/server-remapped/{0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch => 0510-Fix-Per-World-Difficulty-Remembering-Difficulty.patch} (100%) rename patches/server-remapped/{0509-Paper-dumpitem-command.patch => 0511-Paper-dumpitem-command.patch} (100%) rename patches/server-remapped/{0510-Don-t-allow-null-UUID-s-for-chat.patch => 0512-Don-t-allow-null-UUID-s-for-chat.patch} (100%) rename patches/server-remapped/{0511-Improve-Legacy-Component-serialization-size.patch => 0513-Improve-Legacy-Component-serialization-size.patch} (100%) rename patches/server-remapped/{0512-Support-old-UUID-format-for-NBT.patch => 0514-Support-old-UUID-format-for-NBT.patch} (100%) rename patches/server-remapped/{0513-Clean-up-duplicated-GameProfile-Properties.patch => 0515-Clean-up-duplicated-GameProfile-Properties.patch} (100%) rename patches/server-remapped/{0514-Convert-legacy-attributes-in-Item-Meta.patch => 0516-Convert-legacy-attributes-in-Item-Meta.patch} (100%) rename patches/server-remapped/{0515-Remove-some-streams-from-structures.patch => 0517-Remove-some-streams-from-structures.patch} (100%) rename patches/server-remapped/{0516-Remove-streams-from-classes-related-villager-gossip.patch => 0518-Remove-streams-from-classes-related-villager-gossip.patch} (100%) rename patches/server-remapped/{0517-Support-components-in-ItemMeta.patch => 0519-Support-components-in-ItemMeta.patch} (100%) rename patches/server-remapped/{0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch => 0520-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch} (100%) rename patches/server-remapped/{0519-Add-entity-liquid-API.patch => 0521-Add-entity-liquid-API.patch} (100%) rename patches/server-remapped/{0520-Update-itemstack-legacy-name-and-lore.patch => 0522-Update-itemstack-legacy-name-and-lore.patch} (100%) rename patches/server-remapped/{0521-Spawn-player-in-correct-world-on-login.patch => 0523-Spawn-player-in-correct-world-on-login.patch} (100%) rename patches/server-remapped/{0522-Add-PrepareResultEvent.patch => 0524-Add-PrepareResultEvent.patch} (100%) rename patches/server-remapped/{0523-Allow-delegation-to-vanilla-chunk-gen.patch => 0525-Allow-delegation-to-vanilla-chunk-gen.patch} (100%) rename patches/server-remapped/{0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch => 0526-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch} (100%) rename patches/server-remapped/{0525-Optimize-NetworkManager-Exception-Handling.patch => 0527-Optimize-NetworkManager-Exception-Handling.patch} (100%) rename patches/server-remapped/{0526-Fix-Concurrency-issue-in-WeightedList.patch => 0528-Fix-Concurrency-issue-in-WeightedList.patch} (100%) rename patches/server-remapped/{0527-Optimize-the-advancement-data-player-iteration-to-be.patch => 0529-Optimize-the-advancement-data-player-iteration-to-be.patch} (100%) rename patches/server-remapped/{0528-Fix-arrows-never-despawning-MC-125757.patch => 0530-Fix-arrows-never-despawning-MC-125757.patch} (100%) rename patches/server-remapped/{0529-Thread-Safe-Vanilla-Command-permission-checking.patch => 0531-Thread-Safe-Vanilla-Command-permission-checking.patch} (100%) rename patches/server-remapped/{0530-Move-range-check-for-block-placing-up.patch => 0532-Move-range-check-for-block-placing-up.patch} (100%) rename patches/server-remapped/{0531-Fix-SPIGOT-5989.patch => 0533-Fix-SPIGOT-5989.patch} (100%) rename patches/server-remapped/{0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch => 0534-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch} (100%) rename patches/server-remapped/{0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch => 0535-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch} (100%) rename patches/server-remapped/{0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch => 0536-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch} (100%) rename patches/server-remapped/{0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch => 0537-Add-missing-strikeLighting-call-to-World-spigot-stri.patch} (100%) rename patches/server-remapped/{0536-Fix-some-rails-connecting-improperly.patch => 0538-Fix-some-rails-connecting-improperly.patch} (100%) rename patches/server-remapped/{0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch => 0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch} (100%) rename patches/server-remapped/{0538-Incremental-player-saving.patch => 0540-Incremental-player-saving.patch} (100%) rename patches/server-remapped/{0539-Import-fastutil-classes.patch => 0541-Import-fastutil-classes.patch} (100%) rename patches/server-remapped/{0540-Don-t-mark-null-chunk-sections-for-block-updates.patch => 0542-Don-t-mark-null-chunk-sections-for-block-updates.patch} (100%) rename patches/server-remapped/{0541-Remove-armour-stand-double-add-to-world.patch => 0543-Remove-armour-stand-double-add-to-world.patch} (100%) rename patches/server-remapped/{0542-Fix-MC-187716-Use-configured-height.patch => 0544-Fix-MC-187716-Use-configured-height.patch} (100%) rename patches/server-remapped/{0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch => 0545-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch} (100%) rename patches/server-remapped/{0544-Do-not-let-the-server-load-chunks-from-newer-version.patch => 0546-Do-not-let-the-server-load-chunks-from-newer-version.patch} (100%) rename patches/server-remapped/{0545-Brand-support.patch => 0547-Brand-support.patch} (100%) rename patches/server-remapped/{0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch => 0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch} (100%) rename patches/server-remapped/{0547-Fix-MC-197271.patch => 0549-Fix-MC-197271.patch} (100%) rename patches/server-remapped/{0548-MC-197883-Bandaid-decode-issue.patch => 0550-MC-197883-Bandaid-decode-issue.patch} (100%) rename patches/server-remapped/{0549-Add-setMaxPlayers-API.patch => 0551-Add-setMaxPlayers-API.patch} (100%) rename patches/server-remapped/{0550-Add-playPickupItemAnimation-to-LivingEntity.patch => 0552-Add-playPickupItemAnimation-to-LivingEntity.patch} (100%) rename patches/server-remapped/{0551-Don-t-require-FACING-data.patch => 0553-Don-t-require-FACING-data.patch} (100%) rename patches/server-remapped/{0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch => 0554-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch} (100%) rename patches/server-remapped/{0553-Add-moon-phase-API.patch => 0555-Add-moon-phase-API.patch} (100%) rename patches/server-remapped/{0554-Prevent-headless-pistons-from-being-created.patch => 0556-Prevent-headless-pistons-from-being-created.patch} (100%) rename patches/server-remapped/{0555-Add-BellRingEvent.patch => 0557-Add-BellRingEvent.patch} (100%) rename patches/server-remapped/{0556-Add-zombie-targets-turtle-egg-config.patch => 0558-Add-zombie-targets-turtle-egg-config.patch} (100%) rename patches/server-remapped/{0557-Buffer-joins-to-world.patch => 0559-Buffer-joins-to-world.patch} (100%) rename patches/server-remapped/{0558-Optimize-redstone-algorithm.patch => 0560-Optimize-redstone-algorithm.patch} (100%) rename patches/server-remapped/{0559-Fix-hex-colors-not-working-in-some-kick-messages.patch => 0561-Fix-hex-colors-not-working-in-some-kick-messages.patch} (100%) rename patches/server-remapped/{0560-PortalCreateEvent-needs-to-know-its-entity.patch => 0562-PortalCreateEvent-needs-to-know-its-entity.patch} (100%) rename patches/server-remapped/{0561-Fix-CraftTeam-null-check.patch => 0563-Fix-CraftTeam-null-check.patch} (100%) rename patches/server-remapped/{0562-Add-more-Evoker-API.patch => 0564-Add-more-Evoker-API.patch} (100%) rename patches/server-remapped/{0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch => 0565-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch} (100%) rename patches/server-remapped/{0564-Create-HoverEvent-from-ItemStack-Entity.patch => 0566-Create-HoverEvent-from-ItemStack-Entity.patch} (100%) rename patches/server-remapped/{0565-Cache-block-data-strings.patch => 0567-Cache-block-data-strings.patch} (100%) rename patches/server-remapped/{0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch => 0568-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch} (100%) rename patches/server-remapped/{0567-Add-additional-open-container-api-to-HumanEntity.patch => 0569-Add-additional-open-container-api-to-HumanEntity.patch} (100%) rename patches/server-remapped/{0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch => 0570-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch} (100%) rename patches/server-remapped/{0569-Extend-block-drop-capture-to-capture-all-items-added.patch => 0571-Extend-block-drop-capture-to-capture-all-items-added.patch} (100%) rename patches/server-remapped/{0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch => 0572-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch} (100%) rename patches/server-remapped/{0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch => 0573-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch} (100%) rename patches/server-remapped/{0572-Lazily-track-plugin-scoreboards-by-default.patch => 0574-Lazily-track-plugin-scoreboards-by-default.patch} (100%) rename patches/server-remapped/{0573-Entity-isTicking.patch => 0575-Entity-isTicking.patch} (100%) rename patches/server-remapped/{0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch => 0576-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch} (100%) rename patches/server-remapped/{0575-Fix-Not-a-string-Map-Conversion-spam.patch => 0577-Fix-Not-a-string-Map-Conversion-spam.patch} (100%) rename patches/server-remapped/{0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch => 0578-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch} (100%) rename patches/server-remapped/{0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch => 0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch} (100%) rename patches/server-remapped/{0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch => 0580-Reset-Ender-Crystals-on-Dragon-Spawn.patch} (100%) rename patches/server-remapped/{0579-Fix-for-large-move-vectors-crashing-server.patch => 0581-Fix-for-large-move-vectors-crashing-server.patch} (100%) rename patches/server-remapped/{0580-Optimise-getType-calls.patch => 0582-Optimise-getType-calls.patch} (100%) rename patches/server-remapped/{0581-Villager-resetOffers.patch => 0583-Villager-resetOffers.patch} (100%) rename patches/server-remapped/{0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch => 0584-Improve-inlinig-for-some-hot-IBlockData-methods.patch} (100%) rename patches/server-remapped/{0583-Retain-block-place-order-when-capturing-blockstates.patch => 0585-Retain-block-place-order-when-capturing-blockstates.patch} (100%) rename patches/server-remapped/{0584-Reduce-blockpos-allocation-from-pathfinding.patch => 0586-Reduce-blockpos-allocation-from-pathfinding.patch} (100%) rename patches/server-remapped/{0585-Fix-item-locations-dropped-from-campfires.patch => 0587-Fix-item-locations-dropped-from-campfires.patch} (100%) rename patches/server-remapped/{0586-Player-elytra-boost-API.patch => 0588-Player-elytra-boost-API.patch} (100%) rename patches/server-remapped/{0587-Fixed-TileEntityBell-memory-leak.patch => 0589-Fixed-TileEntityBell-memory-leak.patch} (100%) rename patches/server-remapped/{0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch => 0590-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch} (100%) rename patches/server-remapped/{0589-Add-getOfflinePlayerIfCached-String.patch => 0591-Add-getOfflinePlayerIfCached-String.patch} (100%) rename patches/server-remapped/{0590-Add-ignore-discounts-API.patch => 0592-Add-ignore-discounts-API.patch} (100%) rename patches/server-remapped/{0591-Toggle-for-removing-existing-dragon.patch => 0593-Toggle-for-removing-existing-dragon.patch} (100%) rename patches/server-remapped/{0592-Fix-client-lag-on-advancement-loading.patch => 0594-Fix-client-lag-on-advancement-loading.patch} (100%) rename patches/server-remapped/{0593-Item-no-age-no-player-pickup.patch => 0595-Item-no-age-no-player-pickup.patch} (100%) rename patches/server-remapped/{0594-Beacon-API-custom-effect-ranges.patch => 0596-Beacon-API-custom-effect-ranges.patch} (100%) rename patches/server-remapped/{0595-Add-API-for-quit-reason.patch => 0597-Add-API-for-quit-reason.patch} (100%) rename patches/server-remapped/{0596-Seed-based-feature-search.patch => 0598-Seed-based-feature-search.patch} (100%) rename patches/server-remapped/{0597-Add-Wandering-Trader-spawn-rate-config-options.patch => 0599-Add-Wandering-Trader-spawn-rate-config-options.patch} (100%) rename patches/server-remapped/{0598-Significantly-improve-performance-of-the-end-generat.patch => 0600-Significantly-improve-performance-of-the-end-generat.patch} (100%) rename patches/server-remapped/{0599-Expose-world-spawn-angle.patch => 0601-Expose-world-spawn-angle.patch} (100%) rename patches/server-remapped/{0600-Add-Destroy-Speed-API.patch => 0602-Add-Destroy-Speed-API.patch} (100%) rename patches/server-remapped/{0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch => 0603-Fix-Player-spawnParticle-x-y-z-precision-loss.patch} (100%) rename patches/server-remapped/{0602-Add-LivingEntity-clearActiveItem.patch => 0604-Add-LivingEntity-clearActiveItem.patch} (100%) rename patches/server-remapped/{0603-Add-PlayerItemCooldownEvent.patch => 0605-Add-PlayerItemCooldownEvent.patch} (100%) rename patches/server-remapped/{0604-More-lightning-API.patch => 0606-More-lightning-API.patch} (100%) rename patches/server-remapped/{0605-Climbing-should-not-bypass-cramming-gamerule.patch => 0607-Climbing-should-not-bypass-cramming-gamerule.patch} (100%) rename patches/server-remapped/{0606-Added-missing-default-perms-for-commands.patch => 0608-Added-missing-default-perms-for-commands.patch} (100%) rename patches/server-remapped/{0607-Add-PlayerShearBlockEvent.patch => 0609-Add-PlayerShearBlockEvent.patch} (100%) rename patches/server-remapped/{0608-Add-warning-for-servers-not-running-on-Java-16.patch => 0610-Add-warning-for-servers-not-running-on-Java-16.patch} (100%) rename patches/server-remapped/{0609-Set-spigots-verbose-world-setting-to-false-by-def.patch => 0611-Set-spigots-verbose-world-setting-to-false-by-def.patch} (100%) rename patches/server-remapped/{0610-Fix-curing-zombie-villager-discount-exploit.patch => 0612-Fix-curing-zombie-villager-discount-exploit.patch} (100%) rename patches/server-remapped/{0611-Limit-recipe-packets.patch => 0613-Limit-recipe-packets.patch} (100%) rename patches/server-remapped/{0612-Fix-CraftSound-backwards-compatibility.patch => 0614-Fix-CraftSound-backwards-compatibility.patch} (100%) rename patches/server-remapped/{0613-MC-4-Fix-item-position-desync.patch => 0615-MC-4-Fix-item-position-desync.patch} (100%) rename patches/server-remapped/{0614-Player-Chunk-Load-Unload-Events.patch => 0616-Player-Chunk-Load-Unload-Events.patch} (100%) rename patches/server-remapped/{0615-Optimize-Dynamic-get-Missing-Keys.patch => 0617-Optimize-Dynamic-get-Missing-Keys.patch} (100%) rename patches/server-remapped/{0616-Expose-LivingEntity-hurt-direction.patch => 0618-Expose-LivingEntity-hurt-direction.patch} (100%) rename patches/server-remapped/{0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch => 0619-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} (100%) rename patches/server-remapped/{0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch => 0620-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch} (100%) rename patches/server-remapped/{0619-added-PlayerTradeEvent.patch => 0621-added-PlayerTradeEvent.patch} (100%) rename patches/server-remapped/{0620-Implement-TargetHitEvent.patch => 0622-Implement-TargetHitEvent.patch} (100%) rename patches/server-remapped/{0621-Additional-Block-Material-API-s.patch => 0623-Additional-Block-Material-API-s.patch} (100%) rename patches/server-remapped/{0622-Fix-harming-potion-dupe.patch => 0624-Fix-harming-potion-dupe.patch} (100%) rename patches/server-remapped/{0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch => 0625-Implement-API-to-get-Material-from-Boats-and-Minecar.patch} (100%) rename patches/server-remapped/{0624-Optimized-tick-ready-check.patch => 0626-Optimized-tick-ready-check.patch} (100%) rename patches/server-remapped/{0625-Cache-burn-durations.patch => 0627-Cache-burn-durations.patch} (100%) rename patches/server-remapped/{0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch => 0628-Allow-disabling-mob-spawner-spawn-egg-transformation.patch} (100%) rename patches/server-remapped/{0627-Implement-PlayerFlowerPotManipulateEvent.patch => 0629-Implement-PlayerFlowerPotManipulateEvent.patch} (100%) rename patches/server-remapped/{0628-Fix-interact-event-not-being-called-in-adventure.patch => 0630-Fix-interact-event-not-being-called-in-adventure.patch} (100%) rename patches/server-remapped/{0629-Zombie-API-breaking-doors.patch => 0631-Zombie-API-breaking-doors.patch} (100%) rename patches/server-remapped/{0630-Fix-nerfed-slime-when-splitting.patch => 0632-Fix-nerfed-slime-when-splitting.patch} (100%) rename patches/server-remapped/{0631-Add-EntityLoadCrossbowEvent.patch => 0633-Add-EntityLoadCrossbowEvent.patch} (100%) rename patches/server-remapped/{0632-Guardian-beam-workaround.patch => 0634-Guardian-beam-workaround.patch} (100%) rename patches/server-remapped/{0633-Added-WorldGameRuleChangeEvent.patch => 0635-Added-WorldGameRuleChangeEvent.patch} (100%) rename patches/server-remapped/{0634-Added-ServerResourcesReloadedEvent.patch => 0636-Added-ServerResourcesReloadedEvent.patch} (100%) rename patches/server-remapped/{0635-Added-world-settings-for-mobs-picking-up-loot.patch => 0637-Added-world-settings-for-mobs-picking-up-loot.patch} (100%) rename patches/server-remapped/{0636-Implemented-BlockFailedDispenseEvent.patch => 0638-Implemented-BlockFailedDispenseEvent.patch} (100%) rename patches/server-remapped/{0637-Added-PlayerLecternPageChangeEvent.patch => 0639-Added-PlayerLecternPageChangeEvent.patch} (100%) rename patches/server-remapped/{0638-Fire-event-on-GS4-query.patch => 0640-Fire-event-on-GS4-query.patch} (100%) rename patches/server-remapped/{0639-Added-PlayerLoomPatternSelectEvent.patch => 0641-Added-PlayerLoomPatternSelectEvent.patch} (100%) rename patches/server-remapped/{0640-Configurable-door-breaking-difficulty.patch => 0642-Configurable-door-breaking-difficulty.patch} (100%) rename patches/server-remapped/{0641-Empty-commands-shall-not-be-dispatched.patch => 0643-Empty-commands-shall-not-be-dispatched.patch} (100%) rename patches/server-remapped/{0642-Implement-API-to-expose-exact-interaction-point.patch => 0644-Implement-API-to-expose-exact-interaction-point.patch} (100%) rename patches/server-remapped/{0643-Remove-stale-POIs.patch => 0645-Remove-stale-POIs.patch} (100%) rename patches/server-remapped/{0644-Fix-villager-boat-exploit.patch => 0646-Fix-villager-boat-exploit.patch} (100%) rename patches/server-remapped/{0645-Entity-load-save-limit-per-chunk.patch => 0647-Entity-load-save-limit-per-chunk.patch} (100%) rename patches/server-remapped/{0646-Add-sendOpLevel-API.patch => 0648-Add-sendOpLevel-API.patch} (100%) rename patches/server-remapped/{0647-Add-StructureLocateEvent.patch => 0649-Add-StructureLocateEvent.patch} (100%) rename patches/server-remapped/{0648-Collision-option-for-requiring-a-player-participant.patch => 0650-Collision-option-for-requiring-a-player-participant.patch} (100%) rename patches/server-remapped/{0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch => 0651-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch} (100%) rename patches/server-remapped/{0650-Return-chat-component-with-empty-text-instead-of-thr.patch => 0652-Return-chat-component-with-empty-text-instead-of-thr.patch} (100%) rename patches/server-remapped/{0651-Make-schedule-command-per-world.patch => 0653-Make-schedule-command-per-world.patch} (100%) rename patches/server-remapped/{0652-Configurable-max-leash-distance.patch => 0654-Configurable-max-leash-distance.patch} (100%) rename patches/server-remapped/{0653-Implement-BlockPreDispenseEvent.patch => 0655-Implement-BlockPreDispenseEvent.patch} (100%) rename patches/server-remapped/{0654-Added-Vanilla-Entity-Tags.patch => 0656-Added-Vanilla-Entity-Tags.patch} (100%) rename patches/server-remapped/{0655-added-Wither-API.patch => 0657-added-Wither-API.patch} (100%) rename patches/server-remapped/{0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch => 0658-Added-firing-of-PlayerChangeBeaconEffectEvent.patch} (100%) rename patches/server-remapped/{0657-Fix-console-spam-when-removing-chests-in-water.patch => 0659-Fix-console-spam-when-removing-chests-in-water.patch} (100%) rename patches/server-remapped/{0658-Add-toggle-for-always-placing-the-dragon-egg.patch => 0660-Add-toggle-for-always-placing-the-dragon-egg.patch} (100%) rename patches/server-remapped/{0659-Added-PlayerStonecutterRecipeSelectEvent.patch => 0661-Added-PlayerStonecutterRecipeSelectEvent.patch} (100%) rename patches/server-remapped/{0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch => 0662-Add-dropLeash-variable-to-EntityUnleashEvent.patch} (100%) rename patches/server-remapped/{0661-Skip-distance-map-update-when-spawning-disabled.patch => 0663-Skip-distance-map-update-when-spawning-disabled.patch} (100%) rename patches/server-remapped/{0662-Reset-shield-blocking-on-dimension-change.patch => 0664-Reset-shield-blocking-on-dimension-change.patch} (100%) rename patches/server-remapped/{0663-add-DragonEggFormEvent.patch => 0665-add-DragonEggFormEvent.patch} (100%) rename patches/server-remapped/{0664-EntityMoveEvent.patch => 0666-EntityMoveEvent.patch} (100%) rename patches/server-remapped/{0665-added-option-to-disable-pathfinding-updates-on-block.patch => 0667-added-option-to-disable-pathfinding-updates-on-block.patch} (100%) rename patches/server-remapped/{0666-Inline-shift-direction-fields.patch => 0668-Inline-shift-direction-fields.patch} (100%) rename patches/server-remapped/{0667-Allow-adding-items-to-BlockDropItemEvent.patch => 0669-Allow-adding-items-to-BlockDropItemEvent.patch} (100%) rename patches/server-remapped/{0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch => 0670-Add-getMainThreadExecutor-to-BukkitScheduler.patch} (100%) rename patches/server-remapped/{0669-living-entity-allow-attribute-registration.patch => 0671-living-entity-allow-attribute-registration.patch} (100%) rename patches/server-remapped/{0670-fix-dead-slime-setSize-invincibility.patch => 0672-fix-dead-slime-setSize-invincibility.patch} (100%) rename patches/server-remapped/{0671-Merchant-getRecipes-should-return-an-immutable-list.patch => 0673-Merchant-getRecipes-should-return-an-immutable-list.patch} (100%) rename patches/server-remapped/{0672-misc-debugging-dumps.patch => 0674-misc-debugging-dumps.patch} (100%) rename patches/server-remapped/{0673-Add-support-for-hex-color-codes-in-console.patch => 0675-Add-support-for-hex-color-codes-in-console.patch} (100%) rename patches/server-remapped/{0674-Clear-SyncLoadInfo.patch => 0676-Clear-SyncLoadInfo.patch} (100%) rename patches/server-remapped/{0675-Expose-Tracked-Players.patch => 0677-Expose-Tracked-Players.patch} (100%) rename patches/server-remapped/{0676-Remove-streams-from-SensorNearest.patch => 0678-Remove-streams-from-SensorNearest.patch} (100%) rename patches/server-remapped/{0677-do-not-create-unnecessary-copies-of-passenger-list.patch => 0679-do-not-create-unnecessary-copies-of-passenger-list.patch} (100%) rename patches/server-remapped/{0678-MC-29274-Fix-Wither-hostility-towards-players.patch => 0680-MC-29274-Fix-Wither-hostility-towards-players.patch} (100%) rename patches/server-remapped/{0679-Throw-proper-exception-on-empty-JsonList-file.patch => 0681-Throw-proper-exception-on-empty-JsonList-file.patch} (100%) rename patches/server-remapped/{0680-Improve-ServerGUI.patch => 0682-Improve-ServerGUI.patch} (100%) rename patches/server-remapped/{0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch => 0683-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch} (100%) rename patches/server-remapped/{0682-fix-converting-txt-to-json-file.patch => 0684-fix-converting-txt-to-json-file.patch} (100%) rename patches/server-remapped/{0683-Add-worldborder-events.patch => 0685-Add-worldborder-events.patch} (100%) rename patches/server-remapped/{0684-added-PlayerNameEntityEvent.patch => 0686-added-PlayerNameEntityEvent.patch} (100%) rename patches/server-remapped/{0685-Prevent-grindstones-from-overstacking-items.patch => 0687-Prevent-grindstones-from-overstacking-items.patch} (100%) rename patches/server-remapped/{0686-Add-recipe-to-cook-events.patch => 0688-Add-recipe-to-cook-events.patch} (100%) rename patches/server-remapped/{0687-Add-Block-isValidTool.patch => 0689-Add-Block-isValidTool.patch} (100%) rename patches/server-remapped/{0688-Allow-using-signs-inside-spawn-protection.patch => 0690-Allow-using-signs-inside-spawn-protection.patch} (100%) rename patches/server-remapped/{0689-Implement-Keyed-on-World.patch => 0691-Implement-Keyed-on-World.patch} (100%) rename patches/server-remapped/{0690-Add-fast-alternative-constructor-for-Vector3f.patch => 0692-Add-fast-alternative-constructor-for-Vector3f.patch} (100%) rename patches/server-remapped/{0691-Item-Rarity-API.patch => 0693-Item-Rarity-API.patch} (100%) rename patches/server-remapped/{0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch => 0694-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch} (100%) rename patches/server-remapped/{0693-copy-TESign-isEditable-from-snapshots.patch => 0695-copy-TESign-isEditable-from-snapshots.patch} (100%) rename patches/server-remapped/{0694-Drop-carried-item-when-player-has-disconnected.patch => 0696-Drop-carried-item-when-player-has-disconnected.patch} (100%) rename patches/server-remapped/{0695-forced-whitelist-use-configurable-kick-message.patch => 0697-forced-whitelist-use-configurable-kick-message.patch} (100%) rename patches/server-remapped/{0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch => 0698-Make-sure-to-remove-correct-TE-during-TE-tick.patch} (100%) rename patches/server-remapped/{0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch => 0699-Don-t-ignore-result-of-PlayerEditBookEvent.patch} (100%) rename patches/server-remapped/{0698-fix-cancelling-block-falling-causing-client-desync.patch => 0700-fix-cancelling-block-falling-causing-client-desync.patch} (100%) rename patches/server-remapped/{0699-Expose-protocol-version.patch => 0701-Expose-protocol-version.patch} (100%) rename patches/server-remapped/{0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch => 0702-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} (100%) rename patches/server-remapped/{0701-Enhance-console-tab-completions-for-brigadier-comman.patch => 0703-Enhance-console-tab-completions-for-brigadier-comman.patch} (100%) rename patches/server-remapped/{0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch => 0704-Fix-PlayerItemConsumeEvent-cancelling-properly.patch} (100%) rename patches/server-remapped/{0703-Add-bypass-host-check.patch => 0705-Add-bypass-host-check.patch} (100%) rename patches/server-remapped/{0704-don-t-throw-when-loading-invalid-TEs.patch => 0706-don-t-throw-when-loading-invalid-TEs.patch} (100%) rename patches/server-remapped/{0705-Set-area-affect-cloud-rotation.patch => 0707-Set-area-affect-cloud-rotation.patch} (100%) rename patches/server-remapped/{0706-add-isDeeplySleeping-to-HumanEntity.patch => 0708-add-isDeeplySleeping-to-HumanEntity.patch} (100%) rename patches/server-remapped/{0707-Fix-duplicating-give-items-on-item-drop-cancel.patch => 0709-Fix-duplicating-give-items-on-item-drop-cancel.patch} (100%) rename patches/server-remapped/{0708-add-consumeFuel-to-FurnaceBurnEvent.patch => 0710-add-consumeFuel-to-FurnaceBurnEvent.patch} (100%) rename patches/server-remapped/{0709-add-get-set-drop-chance-to-EntityEquipment.patch => 0711-add-get-set-drop-chance-to-EntityEquipment.patch} (100%) rename patches/server-remapped/{0710-fix-PigZombieAngerEvent-cancellation.patch => 0712-fix-PigZombieAngerEvent-cancellation.patch} (100%) rename patches/server-remapped/{0711-Fix-checkReach-check-for-Shulker-boxes.patch => 0713-Fix-checkReach-check-for-Shulker-boxes.patch} (100%) rename patches/server-remapped/{0712-fix-PlayerItemHeldEvent-firing-twice.patch => 0714-fix-PlayerItemHeldEvent-firing-twice.patch} (100%) rename patches/server-remapped/{0713-Added-PlayerDeepSleepEvent.patch => 0715-Added-PlayerDeepSleepEvent.patch} (100%) rename patches/server-remapped/{0714-More-World-API.patch => 0716-More-World-API.patch} (100%) rename patches/server-remapped/{0715-Added-PlayerBedFailEnterEvent.patch => 0717-Added-PlayerBedFailEnterEvent.patch} (100%) rename patches/server-remapped/{0716-Implement-methods-to-convert-between-Component-and-B.patch => 0718-Implement-methods-to-convert-between-Component-and-B.patch} (100%) rename patches/server-remapped/{0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch => 0719-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch} (100%) rename patches/server-remapped/{0718-add-RespawnFlags-to-PlayerRespawnEvent.patch => 0720-add-RespawnFlags-to-PlayerRespawnEvent.patch} (100%) rename patches/server-remapped/{0719-Introduce-beacon-activation-deactivation-events.patch => 0721-Introduce-beacon-activation-deactivation-events.patch} (100%) rename patches/server-remapped/{0720-Add-Channel-initialization-listeners.patch => 0722-Add-Channel-initialization-listeners.patch} (100%) rename patches/server-remapped/{0721-Send-empty-commands-if-tab-completion-is-disabled.patch => 0723-Send-empty-commands-if-tab-completion-is-disabled.patch} (100%) rename patches/server-remapped/{0722-Add-more-WanderingTrader-API.patch => 0724-Add-more-WanderingTrader-API.patch} (100%) rename patches/server-remapped/{0723-Add-EntityBlockStorage-clearEntities.patch => 0725-Add-EntityBlockStorage-clearEntities.patch} (100%) rename patches/server-remapped/{0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch => 0726-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch} (100%) rename patches/server-remapped/{0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch => 0727-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch} (100%) rename patches/server-remapped/{0726-Inventory-close.patch => 0728-Inventory-close.patch} (100%) rename patches/server-remapped/{0727-call-PortalCreateEvent-players-and-end-platform.patch => 0729-call-PortalCreateEvent-players-and-end-platform.patch} (100%) rename patches/server-remapped/{0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch => 0730-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch} (100%) rename patches/server-remapped/{0729-Fix-CraftPotionBrewer-cache.patch => 0731-Fix-CraftPotionBrewer-cache.patch} (100%) rename patches/server-remapped/{0730-Add-basic-Datapack-API.patch => 0732-Add-basic-Datapack-API.patch} (100%) rename patches/server-remapped/{0731-Add-environment-variable-to-disable-server-gui.patch => 0733-Add-environment-variable-to-disable-server-gui.patch} (100%) rename patches/server-remapped/{0732-additions-to-PlayerGameModeChangeEvent.patch => 0734-additions-to-PlayerGameModeChangeEvent.patch} (100%) rename patches/server-remapped/{0733-ItemStack-repair-check-API.patch => 0735-ItemStack-repair-check-API.patch} (100%) rename patches/server-remapped/{0734-More-Enchantment-API.patch => 0736-More-Enchantment-API.patch} (100%) rename patches/server-remapped/{0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch => 0737-Add-command-line-option-to-load-extra-plugin-jars-no.patch} (100%) rename patches/server-remapped/{0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch => 0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch} (100%) rename patches/server-remapped/{0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch => 0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch} (100%) rename patches/server-remapped/{0738-Fix-and-optimise-world-force-upgrading.patch => 0740-Fix-and-optimise-world-force-upgrading.patch} (100%) rename patches/server-remapped/{0739-Add-Mob-lookAt-API.patch => 0741-Add-Mob-lookAt-API.patch} (100%) rename patches/server-remapped/{0740-Add-Unix-domain-socket-support.patch => 0742-Add-Unix-domain-socket-support.patch} (100%) rename patches/server-remapped/{0741-Add-EntityInsideBlockEvent.patch => 0743-Add-EntityInsideBlockEvent.patch} (100%) rename patches/server-remapped/{0742-Attributes-API-for-item-defaults.patch => 0744-Attributes-API-for-item-defaults.patch} (100%) rename patches/server-remapped/{0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch => 0745-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch} (100%) rename patches/server-remapped/{0744-Add-cause-to-Weather-ThunderChangeEvents.patch => 0746-Add-cause-to-Weather-ThunderChangeEvents.patch} (100%) rename patches/server-remapped/{0745-More-Lidded-Block-API.patch => 0747-More-Lidded-Block-API.patch} (100%) rename patches/server-remapped/{0746-Add-PlayerKickEvent-causes.patch => 0748-Add-PlayerKickEvent-causes.patch} (100%) rename patches/server-remapped/{0747-Limit-item-frame-cursors-on-maps.patch => 0749-Limit-item-frame-cursors-on-maps.patch} (100%) rename patches/server-remapped/{0748-Add-PufferFishStateChangeEvent.patch => 0750-Add-PufferFishStateChangeEvent.patch} (100%) rename patches/server-remapped/{0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch => 0751-Fix-PlayerBucketEmptyEvent-result-itemstack.patch} (100%) rename patches/server-remapped/{0750-Add-option-to-fix-items-merging-through-walls.patch => 0752-Add-option-to-fix-items-merging-through-walls.patch} (100%) rename patches/server-remapped/{0751-Add-BellRevealRaiderEvent.patch => 0753-Add-BellRevealRaiderEvent.patch} (100%) rename patches/server-remapped/{0752-Fix-invulnerable-end-crystals.patch => 0754-Fix-invulnerable-end-crystals.patch} (100%) rename patches/server-remapped/{0753-Add-ElderGuardianAppearanceEvent.patch => 0755-Add-ElderGuardianAppearanceEvent.patch} (100%) rename patches/server-remapped/{0754-Reset-villager-inventory-on-cancelled-pickup-event.patch => 0756-Reset-villager-inventory-on-cancelled-pickup-event.patch} (100%) rename patches/server-remapped/{0755-Fix-dangerous-end-portal-logic.patch => 0757-Fix-dangerous-end-portal-logic.patch} (100%) rename patches/server-remapped/{0756-Make-item-validations-configurable.patch => 0758-Make-item-validations-configurable.patch} (100%) rename patches/server-remapped/{0757-Add-more-line-of-sight-methods.patch => 0759-Add-more-line-of-sight-methods.patch} (100%) rename patches/server-remapped/{0758-add-per-world-spawn-limits.patch => 0760-add-per-world-spawn-limits.patch} (100%) rename patches/server-remapped/{0759-Fix-PotionSplashEvent-for-water-splash-potions.patch => 0761-Fix-PotionSplashEvent-for-water-splash-potions.patch} (100%) diff --git a/build.gradle.kts b/build.gradle.kts index 0687edd2a5..d84c9ca484 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -64,7 +64,7 @@ repositories { dependencies { paramMappings("org.quiltmc:yarn:1.17+build.2:mergedv2") remapper("org.quiltmc:tiny-remapper:0.3.2:fat@jar") - decompiler("net.minecraftforge:forgeflower:1.5.498.5@jar") + decompiler("net.minecraftforge:forgeflower:1.5.498.12@jar") paperclip("io.papermc:paperclip:2.0.0-SNAPSHOT@jar") } diff --git a/patches/server-remapped/0004-MC-Utils.patch b/patches/server-remapped/0006-MC-Utils.patch similarity index 100% rename from patches/server-remapped/0004-MC-Utils.patch rename to patches/server-remapped/0006-MC-Utils.patch diff --git a/patches/server-remapped/0005-Paper-Metrics.patch b/patches/server-remapped/0007-Paper-Metrics.patch similarity index 100% rename from patches/server-remapped/0005-Paper-Metrics.patch rename to patches/server-remapped/0007-Paper-Metrics.patch diff --git a/patches/server-remapped/0006-Add-MinecraftKey-Information-to-Objects.patch b/patches/server-remapped/0008-Add-MinecraftKey-Information-to-Objects.patch similarity index 100% rename from patches/server-remapped/0006-Add-MinecraftKey-Information-to-Objects.patch rename to patches/server-remapped/0008-Add-MinecraftKey-Information-to-Objects.patch diff --git a/patches/server-remapped/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch b/patches/server-remapped/0009-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch similarity index 100% rename from patches/server-remapped/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch rename to patches/server-remapped/0009-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch diff --git a/patches/server-remapped/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch b/patches/server-remapped/0010-Store-counts-for-each-Entity-Block-Entity-Type.patch similarity index 100% rename from patches/server-remapped/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch rename to patches/server-remapped/0010-Store-counts-for-each-Entity-Block-Entity-Type.patch diff --git a/patches/server-remapped/0009-Timings-v2.patch b/patches/server-remapped/0011-Timings-v2.patch similarity index 100% rename from patches/server-remapped/0009-Timings-v2.patch rename to patches/server-remapped/0011-Timings-v2.patch diff --git a/patches/server-remapped/0010-Adventure.patch b/patches/server-remapped/0012-Adventure.patch similarity index 100% rename from patches/server-remapped/0010-Adventure.patch rename to patches/server-remapped/0012-Adventure.patch diff --git a/patches/server-remapped/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch b/patches/server-remapped/0013-Configurable-cactus-bamboo-and-reed-growth-heights.patch similarity index 100% rename from patches/server-remapped/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch rename to patches/server-remapped/0013-Configurable-cactus-bamboo-and-reed-growth-heights.patch diff --git a/patches/server-remapped/0012-Configurable-baby-zombie-movement-speed.patch b/patches/server-remapped/0014-Configurable-baby-zombie-movement-speed.patch similarity index 100% rename from patches/server-remapped/0012-Configurable-baby-zombie-movement-speed.patch rename to patches/server-remapped/0014-Configurable-baby-zombie-movement-speed.patch diff --git a/patches/server-remapped/0013-Configurable-fishing-time-ranges.patch b/patches/server-remapped/0015-Configurable-fishing-time-ranges.patch similarity index 100% rename from patches/server-remapped/0013-Configurable-fishing-time-ranges.patch rename to patches/server-remapped/0015-Configurable-fishing-time-ranges.patch diff --git a/patches/server-remapped/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/patches/server-remapped/0016-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch similarity index 100% rename from patches/server-remapped/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch rename to patches/server-remapped/0016-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch diff --git a/patches/server-remapped/0015-Add-configurable-despawn-distances-for-living-entiti.patch b/patches/server-remapped/0017-Add-configurable-despawn-distances-for-living-entiti.patch similarity index 100% rename from patches/server-remapped/0015-Add-configurable-despawn-distances-for-living-entiti.patch rename to patches/server-remapped/0017-Add-configurable-despawn-distances-for-living-entiti.patch diff --git a/patches/server-remapped/0016-Allow-for-toggling-of-spawn-chunks.patch b/patches/server-remapped/0018-Allow-for-toggling-of-spawn-chunks.patch similarity index 100% rename from patches/server-remapped/0016-Allow-for-toggling-of-spawn-chunks.patch rename to patches/server-remapped/0018-Allow-for-toggling-of-spawn-chunks.patch diff --git a/patches/server-remapped/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch b/patches/server-remapped/0019-Drop-falling-block-and-tnt-entities-at-the-specified.patch similarity index 100% rename from patches/server-remapped/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch rename to patches/server-remapped/0019-Drop-falling-block-and-tnt-entities-at-the-specified.patch diff --git a/patches/server-remapped/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/patches/server-remapped/0020-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch similarity index 100% rename from patches/server-remapped/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch rename to patches/server-remapped/0020-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch diff --git a/patches/server-remapped/0019-Implement-Paper-VersionChecker.patch b/patches/server-remapped/0021-Implement-Paper-VersionChecker.patch similarity index 100% rename from patches/server-remapped/0019-Implement-Paper-VersionChecker.patch rename to patches/server-remapped/0021-Implement-Paper-VersionChecker.patch diff --git a/patches/server-remapped/0020-Add-version-history-to-version-command.patch b/patches/server-remapped/0022-Add-version-history-to-version-command.patch similarity index 100% rename from patches/server-remapped/0020-Add-version-history-to-version-command.patch rename to patches/server-remapped/0022-Add-version-history-to-version-command.patch diff --git a/patches/server-remapped/0021-Player-affects-spawning-API.patch b/patches/server-remapped/0023-Player-affects-spawning-API.patch similarity index 100% rename from patches/server-remapped/0021-Player-affects-spawning-API.patch rename to patches/server-remapped/0023-Player-affects-spawning-API.patch diff --git a/patches/server-remapped/0022-Remove-invalid-mob-spawner-tile-entities.patch b/patches/server-remapped/0024-Remove-invalid-mob-spawner-tile-entities.patch similarity index 100% rename from patches/server-remapped/0022-Remove-invalid-mob-spawner-tile-entities.patch rename to patches/server-remapped/0024-Remove-invalid-mob-spawner-tile-entities.patch diff --git a/patches/server-remapped/0023-Optimize-TileEntity-Ticking.patch b/patches/server-remapped/0025-Optimize-TileEntity-Ticking.patch similarity index 100% rename from patches/server-remapped/0023-Optimize-TileEntity-Ticking.patch rename to patches/server-remapped/0025-Optimize-TileEntity-Ticking.patch diff --git a/patches/server-remapped/0024-Further-improve-server-tick-loop.patch b/patches/server-remapped/0026-Further-improve-server-tick-loop.patch similarity index 100% rename from patches/server-remapped/0024-Further-improve-server-tick-loop.patch rename to patches/server-remapped/0026-Further-improve-server-tick-loop.patch diff --git a/patches/server-remapped/0025-Only-refresh-abilities-if-needed.patch b/patches/server-remapped/0027-Only-refresh-abilities-if-needed.patch similarity index 100% rename from patches/server-remapped/0025-Only-refresh-abilities-if-needed.patch rename to patches/server-remapped/0027-Only-refresh-abilities-if-needed.patch diff --git a/patches/server-remapped/0026-Entity-Origin-API.patch b/patches/server-remapped/0028-Entity-Origin-API.patch similarity index 100% rename from patches/server-remapped/0026-Entity-Origin-API.patch rename to patches/server-remapped/0028-Entity-Origin-API.patch diff --git a/patches/server-remapped/0027-Prevent-tile-entity-and-entity-crashes.patch b/patches/server-remapped/0029-Prevent-tile-entity-and-entity-crashes.patch similarity index 100% rename from patches/server-remapped/0027-Prevent-tile-entity-and-entity-crashes.patch rename to patches/server-remapped/0029-Prevent-tile-entity-and-entity-crashes.patch diff --git a/patches/server-remapped/0028-Configurable-top-of-nether-void-damage.patch b/patches/server-remapped/0030-Configurable-top-of-nether-void-damage.patch similarity index 100% rename from patches/server-remapped/0028-Configurable-top-of-nether-void-damage.patch rename to patches/server-remapped/0030-Configurable-top-of-nether-void-damage.patch diff --git a/patches/server-remapped/0029-Check-online-mode-before-converting-and-renaming-pla.patch b/patches/server-remapped/0031-Check-online-mode-before-converting-and-renaming-pla.patch similarity index 100% rename from patches/server-remapped/0029-Check-online-mode-before-converting-and-renaming-pla.patch rename to patches/server-remapped/0031-Check-online-mode-before-converting-and-renaming-pla.patch diff --git a/patches/server-remapped/0030-Always-tick-falling-blocks.patch b/patches/server-remapped/0032-Always-tick-falling-blocks.patch similarity index 100% rename from patches/server-remapped/0030-Always-tick-falling-blocks.patch rename to patches/server-remapped/0032-Always-tick-falling-blocks.patch diff --git a/patches/server-remapped/0031-Configurable-end-credits.patch b/patches/server-remapped/0033-Configurable-end-credits.patch similarity index 100% rename from patches/server-remapped/0031-Configurable-end-credits.patch rename to patches/server-remapped/0033-Configurable-end-credits.patch diff --git a/patches/server-remapped/0032-Fix-lag-from-explosions-processing-dead-entities.patch b/patches/server-remapped/0034-Fix-lag-from-explosions-processing-dead-entities.patch similarity index 100% rename from patches/server-remapped/0032-Fix-lag-from-explosions-processing-dead-entities.patch rename to patches/server-remapped/0034-Fix-lag-from-explosions-processing-dead-entities.patch diff --git a/patches/server-remapped/0033-Optimize-explosions.patch b/patches/server-remapped/0035-Optimize-explosions.patch similarity index 100% rename from patches/server-remapped/0033-Optimize-explosions.patch rename to patches/server-remapped/0035-Optimize-explosions.patch diff --git a/patches/server-remapped/0034-Disable-explosion-knockback.patch b/patches/server-remapped/0036-Disable-explosion-knockback.patch similarity index 100% rename from patches/server-remapped/0034-Disable-explosion-knockback.patch rename to patches/server-remapped/0036-Disable-explosion-knockback.patch diff --git a/patches/server-remapped/0035-Disable-thunder.patch b/patches/server-remapped/0037-Disable-thunder.patch similarity index 100% rename from patches/server-remapped/0035-Disable-thunder.patch rename to patches/server-remapped/0037-Disable-thunder.patch diff --git a/patches/server-remapped/0036-Disable-ice-and-snow.patch b/patches/server-remapped/0038-Disable-ice-and-snow.patch similarity index 100% rename from patches/server-remapped/0036-Disable-ice-and-snow.patch rename to patches/server-remapped/0038-Disable-ice-and-snow.patch diff --git a/patches/server-remapped/0037-Configurable-mob-spawner-tick-rate.patch b/patches/server-remapped/0039-Configurable-mob-spawner-tick-rate.patch similarity index 100% rename from patches/server-remapped/0037-Configurable-mob-spawner-tick-rate.patch rename to patches/server-remapped/0039-Configurable-mob-spawner-tick-rate.patch diff --git a/patches/server-remapped/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch b/patches/server-remapped/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch similarity index 100% rename from patches/server-remapped/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch rename to patches/server-remapped/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch diff --git a/patches/server-remapped/0039-Add-BeaconEffectEvent.patch b/patches/server-remapped/0041-Add-BeaconEffectEvent.patch similarity index 100% rename from patches/server-remapped/0039-Add-BeaconEffectEvent.patch rename to patches/server-remapped/0041-Add-BeaconEffectEvent.patch diff --git a/patches/server-remapped/0040-Configurable-container-update-tick-rate.patch b/patches/server-remapped/0042-Configurable-container-update-tick-rate.patch similarity index 100% rename from patches/server-remapped/0040-Configurable-container-update-tick-rate.patch rename to patches/server-remapped/0042-Configurable-container-update-tick-rate.patch diff --git a/patches/server-remapped/0041-Use-UserCache-for-player-heads.patch b/patches/server-remapped/0043-Use-UserCache-for-player-heads.patch similarity index 100% rename from patches/server-remapped/0041-Use-UserCache-for-player-heads.patch rename to patches/server-remapped/0043-Use-UserCache-for-player-heads.patch diff --git a/patches/server-remapped/0042-Disable-spigot-tick-limiters.patch b/patches/server-remapped/0044-Disable-spigot-tick-limiters.patch similarity index 100% rename from patches/server-remapped/0042-Disable-spigot-tick-limiters.patch rename to patches/server-remapped/0044-Disable-spigot-tick-limiters.patch diff --git a/patches/server-remapped/0043-Add-PlayerInitialSpawnEvent.patch b/patches/server-remapped/0045-Add-PlayerInitialSpawnEvent.patch similarity index 100% rename from patches/server-remapped/0043-Add-PlayerInitialSpawnEvent.patch rename to patches/server-remapped/0045-Add-PlayerInitialSpawnEvent.patch diff --git a/patches/server-remapped/0044-Configurable-Disabling-Cat-Chest-Detection.patch b/patches/server-remapped/0046-Configurable-Disabling-Cat-Chest-Detection.patch similarity index 100% rename from patches/server-remapped/0044-Configurable-Disabling-Cat-Chest-Detection.patch rename to patches/server-remapped/0046-Configurable-Disabling-Cat-Chest-Detection.patch diff --git a/patches/server-remapped/0045-Ensure-commands-are-not-ran-async.patch b/patches/server-remapped/0047-Ensure-commands-are-not-ran-async.patch similarity index 100% rename from patches/server-remapped/0045-Ensure-commands-are-not-ran-async.patch rename to patches/server-remapped/0047-Ensure-commands-are-not-ran-async.patch diff --git a/patches/server-remapped/0046-All-chunks-are-slime-spawn-chunks-toggle.patch b/patches/server-remapped/0048-All-chunks-are-slime-spawn-chunks-toggle.patch similarity index 100% rename from patches/server-remapped/0046-All-chunks-are-slime-spawn-chunks-toggle.patch rename to patches/server-remapped/0048-All-chunks-are-slime-spawn-chunks-toggle.patch diff --git a/patches/server-remapped/0047-Expose-server-CommandMap.patch b/patches/server-remapped/0049-Expose-server-CommandMap.patch similarity index 100% rename from patches/server-remapped/0047-Expose-server-CommandMap.patch rename to patches/server-remapped/0049-Expose-server-CommandMap.patch diff --git a/patches/server-remapped/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch b/patches/server-remapped/0050-Be-a-bit-more-informative-in-maxHealth-exception.patch similarity index 100% rename from patches/server-remapped/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch rename to patches/server-remapped/0050-Be-a-bit-more-informative-in-maxHealth-exception.patch diff --git a/patches/server-remapped/0049-Player-Tab-List-and-Title-APIs.patch b/patches/server-remapped/0051-Player-Tab-List-and-Title-APIs.patch similarity index 100% rename from patches/server-remapped/0049-Player-Tab-List-and-Title-APIs.patch rename to patches/server-remapped/0051-Player-Tab-List-and-Title-APIs.patch diff --git a/patches/server-remapped/0050-Ensure-inv-drag-is-in-bounds.patch b/patches/server-remapped/0052-Ensure-inv-drag-is-in-bounds.patch similarity index 100% rename from patches/server-remapped/0050-Ensure-inv-drag-is-in-bounds.patch rename to patches/server-remapped/0052-Ensure-inv-drag-is-in-bounds.patch diff --git a/patches/server-remapped/0051-Change-implementation-of-tile-entity-removal-list.patch b/patches/server-remapped/0053-Change-implementation-of-tile-entity-removal-list.patch similarity index 100% rename from patches/server-remapped/0051-Change-implementation-of-tile-entity-removal-list.patch rename to patches/server-remapped/0053-Change-implementation-of-tile-entity-removal-list.patch diff --git a/patches/server-remapped/0052-Add-configurable-portal-search-radius.patch b/patches/server-remapped/0054-Add-configurable-portal-search-radius.patch similarity index 100% rename from patches/server-remapped/0052-Add-configurable-portal-search-radius.patch rename to patches/server-remapped/0054-Add-configurable-portal-search-radius.patch diff --git a/patches/server-remapped/0053-Add-velocity-warnings.patch b/patches/server-remapped/0055-Add-velocity-warnings.patch similarity index 100% rename from patches/server-remapped/0053-Add-velocity-warnings.patch rename to patches/server-remapped/0055-Add-velocity-warnings.patch diff --git a/patches/server-remapped/0054-Configurable-inter-world-teleportation-safety.patch b/patches/server-remapped/0056-Configurable-inter-world-teleportation-safety.patch similarity index 100% rename from patches/server-remapped/0054-Configurable-inter-world-teleportation-safety.patch rename to patches/server-remapped/0056-Configurable-inter-world-teleportation-safety.patch diff --git a/patches/server-remapped/0055-Add-exception-reporting-event.patch b/patches/server-remapped/0057-Add-exception-reporting-event.patch similarity index 100% rename from patches/server-remapped/0055-Add-exception-reporting-event.patch rename to patches/server-remapped/0057-Add-exception-reporting-event.patch diff --git a/patches/server-remapped/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/patches/server-remapped/0058-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch similarity index 100% rename from patches/server-remapped/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch rename to patches/server-remapped/0058-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch diff --git a/patches/server-remapped/0057-Disable-Scoreboards-for-non-players-by-default.patch b/patches/server-remapped/0059-Disable-Scoreboards-for-non-players-by-default.patch similarity index 100% rename from patches/server-remapped/0057-Disable-Scoreboards-for-non-players-by-default.patch rename to patches/server-remapped/0059-Disable-Scoreboards-for-non-players-by-default.patch diff --git a/patches/server-remapped/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/server-remapped/0060-Add-methods-for-working-with-arrows-stuck-in-living-.patch similarity index 100% rename from patches/server-remapped/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch rename to patches/server-remapped/0060-Add-methods-for-working-with-arrows-stuck-in-living-.patch diff --git a/patches/server-remapped/0059-Complete-resource-pack-API.patch b/patches/server-remapped/0061-Complete-resource-pack-API.patch similarity index 100% rename from patches/server-remapped/0059-Complete-resource-pack-API.patch rename to patches/server-remapped/0061-Complete-resource-pack-API.patch diff --git a/patches/server-remapped/0060-Chunk-Save-Reattempt.patch b/patches/server-remapped/0062-Chunk-Save-Reattempt.patch similarity index 100% rename from patches/server-remapped/0060-Chunk-Save-Reattempt.patch rename to patches/server-remapped/0062-Chunk-Save-Reattempt.patch diff --git a/patches/server-remapped/0061-Default-loading-permissions.yml-before-plugins.patch b/patches/server-remapped/0063-Default-loading-permissions.yml-before-plugins.patch similarity index 100% rename from patches/server-remapped/0061-Default-loading-permissions.yml-before-plugins.patch rename to patches/server-remapped/0063-Default-loading-permissions.yml-before-plugins.patch diff --git a/patches/server-remapped/0062-Allow-Reloading-of-Custom-Permissions.patch b/patches/server-remapped/0064-Allow-Reloading-of-Custom-Permissions.patch similarity index 100% rename from patches/server-remapped/0062-Allow-Reloading-of-Custom-Permissions.patch rename to patches/server-remapped/0064-Allow-Reloading-of-Custom-Permissions.patch diff --git a/patches/server-remapped/0063-Remove-Metadata-on-reload.patch b/patches/server-remapped/0065-Remove-Metadata-on-reload.patch similarity index 100% rename from patches/server-remapped/0063-Remove-Metadata-on-reload.patch rename to patches/server-remapped/0065-Remove-Metadata-on-reload.patch diff --git a/patches/server-remapped/0064-Handle-Item-Meta-Inconsistencies.patch b/patches/server-remapped/0066-Handle-Item-Meta-Inconsistencies.patch similarity index 100% rename from patches/server-remapped/0064-Handle-Item-Meta-Inconsistencies.patch rename to patches/server-remapped/0066-Handle-Item-Meta-Inconsistencies.patch diff --git a/patches/server-remapped/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/patches/server-remapped/0067-Configurable-Non-Player-Arrow-Despawn-Rate.patch similarity index 100% rename from patches/server-remapped/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch rename to patches/server-remapped/0067-Configurable-Non-Player-Arrow-Despawn-Rate.patch diff --git a/patches/server-remapped/0066-Add-World-Util-Methods.patch b/patches/server-remapped/0068-Add-World-Util-Methods.patch similarity index 100% rename from patches/server-remapped/0066-Add-World-Util-Methods.patch rename to patches/server-remapped/0068-Add-World-Util-Methods.patch diff --git a/patches/server-remapped/0067-Custom-replacement-for-eaten-items.patch b/patches/server-remapped/0069-Custom-replacement-for-eaten-items.patch similarity index 100% rename from patches/server-remapped/0067-Custom-replacement-for-eaten-items.patch rename to patches/server-remapped/0069-Custom-replacement-for-eaten-items.patch diff --git a/patches/server-remapped/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/patches/server-remapped/0070-handle-NaN-health-absorb-values-and-repair-bad-data.patch similarity index 100% rename from patches/server-remapped/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch rename to patches/server-remapped/0070-handle-NaN-health-absorb-values-and-repair-bad-data.patch diff --git a/patches/server-remapped/0069-Use-a-Shared-Random-for-Entities.patch b/patches/server-remapped/0071-Use-a-Shared-Random-for-Entities.patch similarity index 100% rename from patches/server-remapped/0069-Use-a-Shared-Random-for-Entities.patch rename to patches/server-remapped/0071-Use-a-Shared-Random-for-Entities.patch diff --git a/patches/server-remapped/0070-Configurable-spawn-chances-for-skeleton-horses.patch b/patches/server-remapped/0072-Configurable-spawn-chances-for-skeleton-horses.patch similarity index 100% rename from patches/server-remapped/0070-Configurable-spawn-chances-for-skeleton-horses.patch rename to patches/server-remapped/0072-Configurable-spawn-chances-for-skeleton-horses.patch diff --git a/patches/server-remapped/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/patches/server-remapped/0073-Optimize-isValidLocation-getType-and-getBlockData-fo.patch similarity index 100% rename from patches/server-remapped/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch rename to patches/server-remapped/0073-Optimize-isValidLocation-getType-and-getBlockData-fo.patch diff --git a/patches/server-remapped/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/patches/server-remapped/0074-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch similarity index 100% rename from patches/server-remapped/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch rename to patches/server-remapped/0074-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch diff --git a/patches/server-remapped/0073-Entity-AddTo-RemoveFrom-World-Events.patch b/patches/server-remapped/0075-Entity-AddTo-RemoveFrom-World-Events.patch similarity index 100% rename from patches/server-remapped/0073-Entity-AddTo-RemoveFrom-World-Events.patch rename to patches/server-remapped/0075-Entity-AddTo-RemoveFrom-World-Events.patch diff --git a/patches/server-remapped/0074-Configurable-Chunk-Inhabited-Time.patch b/patches/server-remapped/0076-Configurable-Chunk-Inhabited-Time.patch similarity index 100% rename from patches/server-remapped/0074-Configurable-Chunk-Inhabited-Time.patch rename to patches/server-remapped/0076-Configurable-Chunk-Inhabited-Time.patch diff --git a/patches/server-remapped/0075-EntityPathfindEvent.patch b/patches/server-remapped/0077-EntityPathfindEvent.patch similarity index 100% rename from patches/server-remapped/0075-EntityPathfindEvent.patch rename to patches/server-remapped/0077-EntityPathfindEvent.patch diff --git a/patches/server-remapped/0076-Sanitise-RegionFileCache-and-make-configurable.patch b/patches/server-remapped/0078-Sanitise-RegionFileCache-and-make-configurable.patch similarity index 100% rename from patches/server-remapped/0076-Sanitise-RegionFileCache-and-make-configurable.patch rename to patches/server-remapped/0078-Sanitise-RegionFileCache-and-make-configurable.patch diff --git a/patches/server-remapped/0077-Do-not-load-chunks-for-Pathfinding.patch b/patches/server-remapped/0079-Do-not-load-chunks-for-Pathfinding.patch similarity index 100% rename from patches/server-remapped/0077-Do-not-load-chunks-for-Pathfinding.patch rename to patches/server-remapped/0079-Do-not-load-chunks-for-Pathfinding.patch diff --git a/patches/server-remapped/0078-Add-PlayerUseUnknownEntityEvent.patch b/patches/server-remapped/0080-Add-PlayerUseUnknownEntityEvent.patch similarity index 100% rename from patches/server-remapped/0078-Add-PlayerUseUnknownEntityEvent.patch rename to patches/server-remapped/0080-Add-PlayerUseUnknownEntityEvent.patch diff --git a/patches/server-remapped/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch b/patches/server-remapped/0081-Fix-reducedDebugInfo-not-initialized-on-client.patch similarity index 100% rename from patches/server-remapped/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch rename to patches/server-remapped/0081-Fix-reducedDebugInfo-not-initialized-on-client.patch diff --git a/patches/server-remapped/0080-Configurable-Grass-Spread-Tick-Rate.patch b/patches/server-remapped/0082-Configurable-Grass-Spread-Tick-Rate.patch similarity index 100% rename from patches/server-remapped/0080-Configurable-Grass-Spread-Tick-Rate.patch rename to patches/server-remapped/0082-Configurable-Grass-Spread-Tick-Rate.patch diff --git a/patches/server-remapped/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/patches/server-remapped/0083-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch similarity index 100% rename from patches/server-remapped/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch rename to patches/server-remapped/0083-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch diff --git a/patches/server-remapped/0082-Optimize-DataBits.patch b/patches/server-remapped/0084-Optimize-DataBits.patch similarity index 100% rename from patches/server-remapped/0082-Optimize-DataBits.patch rename to patches/server-remapped/0084-Optimize-DataBits.patch diff --git a/patches/server-remapped/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/patches/server-remapped/0085-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch similarity index 100% rename from patches/server-remapped/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch rename to patches/server-remapped/0085-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch diff --git a/patches/server-remapped/0084-Workaround-for-setting-passengers-on-players.patch b/patches/server-remapped/0086-Workaround-for-setting-passengers-on-players.patch similarity index 100% rename from patches/server-remapped/0084-Workaround-for-setting-passengers-on-players.patch rename to patches/server-remapped/0086-Workaround-for-setting-passengers-on-players.patch diff --git a/patches/server-remapped/0085-Remove-unused-World-Tile-Entity-List.patch b/patches/server-remapped/0087-Remove-unused-World-Tile-Entity-List.patch similarity index 100% rename from patches/server-remapped/0085-Remove-unused-World-Tile-Entity-List.patch rename to patches/server-remapped/0087-Remove-unused-World-Tile-Entity-List.patch diff --git a/patches/server-remapped/0086-Don-t-tick-Skulls-unused-code.patch b/patches/server-remapped/0088-Don-t-tick-Skulls-unused-code.patch similarity index 100% rename from patches/server-remapped/0086-Don-t-tick-Skulls-unused-code.patch rename to patches/server-remapped/0088-Don-t-tick-Skulls-unused-code.patch diff --git a/patches/server-remapped/0087-Configurable-Player-Collision.patch b/patches/server-remapped/0089-Configurable-Player-Collision.patch similarity index 100% rename from patches/server-remapped/0087-Configurable-Player-Collision.patch rename to patches/server-remapped/0089-Configurable-Player-Collision.patch diff --git a/patches/server-remapped/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/patches/server-remapped/0090-Add-handshake-event-to-allow-plugins-to-handle-clien.patch similarity index 100% rename from patches/server-remapped/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch rename to patches/server-remapped/0090-Add-handshake-event-to-allow-plugins-to-handle-clien.patch diff --git a/patches/server-remapped/0089-Configurable-RCON-IP-address.patch b/patches/server-remapped/0091-Configurable-RCON-IP-address.patch similarity index 100% rename from patches/server-remapped/0089-Configurable-RCON-IP-address.patch rename to patches/server-remapped/0091-Configurable-RCON-IP-address.patch diff --git a/patches/server-remapped/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch b/patches/server-remapped/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch similarity index 100% rename from patches/server-remapped/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch rename to patches/server-remapped/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch diff --git a/patches/server-remapped/0091-Implement-PlayerLocaleChangeEvent.patch b/patches/server-remapped/0093-Implement-PlayerLocaleChangeEvent.patch similarity index 100% rename from patches/server-remapped/0091-Implement-PlayerLocaleChangeEvent.patch rename to patches/server-remapped/0093-Implement-PlayerLocaleChangeEvent.patch diff --git a/patches/server-remapped/0092-EntityRegainHealthEvent-isFastRegen-API.patch b/patches/server-remapped/0094-EntityRegainHealthEvent-isFastRegen-API.patch similarity index 100% rename from patches/server-remapped/0092-EntityRegainHealthEvent-isFastRegen-API.patch rename to patches/server-remapped/0094-EntityRegainHealthEvent-isFastRegen-API.patch diff --git a/patches/server-remapped/0093-Add-ability-to-configure-frosted_ice-properties.patch b/patches/server-remapped/0095-Add-ability-to-configure-frosted_ice-properties.patch similarity index 100% rename from patches/server-remapped/0093-Add-ability-to-configure-frosted_ice-properties.patch rename to patches/server-remapped/0095-Add-ability-to-configure-frosted_ice-properties.patch diff --git a/patches/server-remapped/0094-remove-null-possibility-for-getServer-singleton.patch b/patches/server-remapped/0096-remove-null-possibility-for-getServer-singleton.patch similarity index 100% rename from patches/server-remapped/0094-remove-null-possibility-for-getServer-singleton.patch rename to patches/server-remapped/0096-remove-null-possibility-for-getServer-singleton.patch diff --git a/patches/server-remapped/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch b/patches/server-remapped/0097-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch similarity index 100% rename from patches/server-remapped/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch rename to patches/server-remapped/0097-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch diff --git a/patches/server-remapped/0096-LootTable-API-Replenishable-Lootables-Feature.patch b/patches/server-remapped/0098-LootTable-API-Replenishable-Lootables-Feature.patch similarity index 100% rename from patches/server-remapped/0096-LootTable-API-Replenishable-Lootables-Feature.patch rename to patches/server-remapped/0098-LootTable-API-Replenishable-Lootables-Feature.patch diff --git a/patches/server-remapped/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/patches/server-remapped/0099-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch similarity index 100% rename from patches/server-remapped/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch rename to patches/server-remapped/0099-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch diff --git a/patches/server-remapped/0098-System-property-for-disabling-watchdoge.patch b/patches/server-remapped/0100-System-property-for-disabling-watchdoge.patch similarity index 100% rename from patches/server-remapped/0098-System-property-for-disabling-watchdoge.patch rename to patches/server-remapped/0100-System-property-for-disabling-watchdoge.patch diff --git a/patches/server-remapped/0099-Optimize-UserCache-Thread-Safe.patch b/patches/server-remapped/0101-Optimize-UserCache-Thread-Safe.patch similarity index 100% rename from patches/server-remapped/0099-Optimize-UserCache-Thread-Safe.patch rename to patches/server-remapped/0101-Optimize-UserCache-Thread-Safe.patch diff --git a/patches/server-remapped/0100-Avoid-blocking-on-Network-Manager-creation.patch b/patches/server-remapped/0102-Avoid-blocking-on-Network-Manager-creation.patch similarity index 100% rename from patches/server-remapped/0100-Avoid-blocking-on-Network-Manager-creation.patch rename to patches/server-remapped/0102-Avoid-blocking-on-Network-Manager-creation.patch diff --git a/patches/server-remapped/0101-Optional-TNT-doesn-t-move-in-water.patch b/patches/server-remapped/0103-Optional-TNT-doesn-t-move-in-water.patch similarity index 100% rename from patches/server-remapped/0101-Optional-TNT-doesn-t-move-in-water.patch rename to patches/server-remapped/0103-Optional-TNT-doesn-t-move-in-water.patch diff --git a/patches/server-remapped/0102-Faster-redstone-torch-rapid-clock-removal.patch b/patches/server-remapped/0104-Faster-redstone-torch-rapid-clock-removal.patch similarity index 100% rename from patches/server-remapped/0102-Faster-redstone-torch-rapid-clock-removal.patch rename to patches/server-remapped/0104-Faster-redstone-torch-rapid-clock-removal.patch diff --git a/patches/server-remapped/0103-Add-server-name-parameter.patch b/patches/server-remapped/0105-Add-server-name-parameter.patch similarity index 100% rename from patches/server-remapped/0103-Add-server-name-parameter.patch rename to patches/server-remapped/0105-Add-server-name-parameter.patch diff --git a/patches/server-remapped/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/patches/server-remapped/0106-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch similarity index 100% rename from patches/server-remapped/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch rename to patches/server-remapped/0106-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch diff --git a/patches/server-remapped/0105-Fix-Double-World-Add-issues.patch b/patches/server-remapped/0107-Fix-Double-World-Add-issues.patch similarity index 100% rename from patches/server-remapped/0105-Fix-Double-World-Add-issues.patch rename to patches/server-remapped/0107-Fix-Double-World-Add-issues.patch diff --git a/patches/server-remapped/0106-Fix-Old-Sign-Conversion.patch b/patches/server-remapped/0108-Fix-Old-Sign-Conversion.patch similarity index 100% rename from patches/server-remapped/0106-Fix-Old-Sign-Conversion.patch rename to patches/server-remapped/0108-Fix-Old-Sign-Conversion.patch diff --git a/patches/server-remapped/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/patches/server-remapped/0109-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch similarity index 100% rename from patches/server-remapped/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch rename to patches/server-remapped/0109-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch diff --git a/patches/server-remapped/0108-Add-setting-for-proxy-online-mode-status.patch b/patches/server-remapped/0110-Add-setting-for-proxy-online-mode-status.patch similarity index 100% rename from patches/server-remapped/0108-Add-setting-for-proxy-online-mode-status.patch rename to patches/server-remapped/0110-Add-setting-for-proxy-online-mode-status.patch diff --git a/patches/server-remapped/0109-Optimise-BlockState-s-hashCode-equals.patch b/patches/server-remapped/0111-Optimise-BlockState-s-hashCode-equals.patch similarity index 100% rename from patches/server-remapped/0109-Optimise-BlockState-s-hashCode-equals.patch rename to patches/server-remapped/0111-Optimise-BlockState-s-hashCode-equals.patch diff --git a/patches/server-remapped/0110-Configurable-packet-in-spam-threshold.patch b/patches/server-remapped/0112-Configurable-packet-in-spam-threshold.patch similarity index 100% rename from patches/server-remapped/0110-Configurable-packet-in-spam-threshold.patch rename to patches/server-remapped/0112-Configurable-packet-in-spam-threshold.patch diff --git a/patches/server-remapped/0111-Configurable-flying-kick-messages.patch b/patches/server-remapped/0113-Configurable-flying-kick-messages.patch similarity index 100% rename from patches/server-remapped/0111-Configurable-flying-kick-messages.patch rename to patches/server-remapped/0113-Configurable-flying-kick-messages.patch diff --git a/patches/server-remapped/0112-Chunk-registration-fixes.patch b/patches/server-remapped/0114-Chunk-registration-fixes.patch similarity index 100% rename from patches/server-remapped/0112-Chunk-registration-fixes.patch rename to patches/server-remapped/0114-Chunk-registration-fixes.patch diff --git a/patches/server-remapped/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/patches/server-remapped/0115-Remove-FishingHook-reference-on-Craft-Entity-removal.patch similarity index 100% rename from patches/server-remapped/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch rename to patches/server-remapped/0115-Remove-FishingHook-reference-on-Craft-Entity-removal.patch diff --git a/patches/server-remapped/0114-Auto-fix-bad-Y-levels-on-player-login.patch b/patches/server-remapped/0116-Auto-fix-bad-Y-levels-on-player-login.patch similarity index 100% rename from patches/server-remapped/0114-Auto-fix-bad-Y-levels-on-player-login.patch rename to patches/server-remapped/0116-Auto-fix-bad-Y-levels-on-player-login.patch diff --git a/patches/server-remapped/0115-Option-to-remove-corrupt-tile-entities.patch b/patches/server-remapped/0117-Option-to-remove-corrupt-tile-entities.patch similarity index 100% rename from patches/server-remapped/0115-Option-to-remove-corrupt-tile-entities.patch rename to patches/server-remapped/0117-Option-to-remove-corrupt-tile-entities.patch diff --git a/patches/server-remapped/0116-Add-EntityZapEvent.patch b/patches/server-remapped/0118-Add-EntityZapEvent.patch similarity index 100% rename from patches/server-remapped/0116-Add-EntityZapEvent.patch rename to patches/server-remapped/0118-Add-EntityZapEvent.patch diff --git a/patches/server-remapped/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/patches/server-remapped/0119-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch similarity index 100% rename from patches/server-remapped/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch rename to patches/server-remapped/0119-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch diff --git a/patches/server-remapped/0118-Cache-user-authenticator-threads.patch b/patches/server-remapped/0120-Cache-user-authenticator-threads.patch similarity index 100% rename from patches/server-remapped/0118-Cache-user-authenticator-threads.patch rename to patches/server-remapped/0120-Cache-user-authenticator-threads.patch diff --git a/patches/server-remapped/0119-Optimise-removeQueue.patch b/patches/server-remapped/0121-Optimise-removeQueue.patch similarity index 100% rename from patches/server-remapped/0119-Optimise-removeQueue.patch rename to patches/server-remapped/0121-Optimise-removeQueue.patch diff --git a/patches/server-remapped/0120-Allow-Reloading-of-Command-Aliases.patch b/patches/server-remapped/0122-Allow-Reloading-of-Command-Aliases.patch similarity index 100% rename from patches/server-remapped/0120-Allow-Reloading-of-Command-Aliases.patch rename to patches/server-remapped/0122-Allow-Reloading-of-Command-Aliases.patch diff --git a/patches/server-remapped/0121-Add-source-to-PlayerExpChangeEvent.patch b/patches/server-remapped/0123-Add-source-to-PlayerExpChangeEvent.patch similarity index 100% rename from patches/server-remapped/0121-Add-source-to-PlayerExpChangeEvent.patch rename to patches/server-remapped/0123-Add-source-to-PlayerExpChangeEvent.patch diff --git a/patches/server-remapped/0122-Don-t-let-fishinghooks-use-portals.patch b/patches/server-remapped/0124-Don-t-let-fishinghooks-use-portals.patch similarity index 100% rename from patches/server-remapped/0122-Don-t-let-fishinghooks-use-portals.patch rename to patches/server-remapped/0124-Don-t-let-fishinghooks-use-portals.patch diff --git a/patches/server-remapped/0123-Add-ProjectileCollideEvent.patch b/patches/server-remapped/0125-Add-ProjectileCollideEvent.patch similarity index 100% rename from patches/server-remapped/0123-Add-ProjectileCollideEvent.patch rename to patches/server-remapped/0125-Add-ProjectileCollideEvent.patch diff --git a/patches/server-remapped/0124-Prevent-Pathfinding-out-of-World-Border.patch b/patches/server-remapped/0126-Prevent-Pathfinding-out-of-World-Border.patch similarity index 100% rename from patches/server-remapped/0124-Prevent-Pathfinding-out-of-World-Border.patch rename to patches/server-remapped/0126-Prevent-Pathfinding-out-of-World-Border.patch diff --git a/patches/server-remapped/0125-Optimize-World.isLoaded-BlockPosition-Z.patch b/patches/server-remapped/0127-Optimize-World.isLoaded-BlockPosition-Z.patch similarity index 100% rename from patches/server-remapped/0125-Optimize-World.isLoaded-BlockPosition-Z.patch rename to patches/server-remapped/0127-Optimize-World.isLoaded-BlockPosition-Z.patch diff --git a/patches/server-remapped/0126-Bound-Treasure-Maps-to-World-Border.patch b/patches/server-remapped/0128-Bound-Treasure-Maps-to-World-Border.patch similarity index 100% rename from patches/server-remapped/0126-Bound-Treasure-Maps-to-World-Border.patch rename to patches/server-remapped/0128-Bound-Treasure-Maps-to-World-Border.patch diff --git a/patches/server-remapped/0127-Configurable-Cartographer-Treasure-Maps.patch b/patches/server-remapped/0129-Configurable-Cartographer-Treasure-Maps.patch similarity index 100% rename from patches/server-remapped/0127-Configurable-Cartographer-Treasure-Maps.patch rename to patches/server-remapped/0129-Configurable-Cartographer-Treasure-Maps.patch diff --git a/patches/server-remapped/0128-Optimize-ItemStack.isEmpty.patch b/patches/server-remapped/0130-Optimize-ItemStack.isEmpty.patch similarity index 100% rename from patches/server-remapped/0128-Optimize-ItemStack.isEmpty.patch rename to patches/server-remapped/0130-Optimize-ItemStack.isEmpty.patch diff --git a/patches/server-remapped/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch b/patches/server-remapped/0131-Add-API-methods-to-control-if-armour-stands-can-move.patch similarity index 100% rename from patches/server-remapped/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch rename to patches/server-remapped/0131-Add-API-methods-to-control-if-armour-stands-can-move.patch diff --git a/patches/server-remapped/0130-Properly-fix-item-duplication-bug.patch b/patches/server-remapped/0132-Properly-fix-item-duplication-bug.patch similarity index 100% rename from patches/server-remapped/0130-Properly-fix-item-duplication-bug.patch rename to patches/server-remapped/0132-Properly-fix-item-duplication-bug.patch diff --git a/patches/server-remapped/0131-String-based-Action-Bar-API.patch b/patches/server-remapped/0133-String-based-Action-Bar-API.patch similarity index 100% rename from patches/server-remapped/0131-String-based-Action-Bar-API.patch rename to patches/server-remapped/0133-String-based-Action-Bar-API.patch diff --git a/patches/server-remapped/0132-Firework-API-s.patch b/patches/server-remapped/0134-Firework-API-s.patch similarity index 100% rename from patches/server-remapped/0132-Firework-API-s.patch rename to patches/server-remapped/0134-Firework-API-s.patch diff --git a/patches/server-remapped/0133-PlayerTeleportEndGatewayEvent.patch b/patches/server-remapped/0135-PlayerTeleportEndGatewayEvent.patch similarity index 100% rename from patches/server-remapped/0133-PlayerTeleportEndGatewayEvent.patch rename to patches/server-remapped/0135-PlayerTeleportEndGatewayEvent.patch diff --git a/patches/server-remapped/0134-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/server-remapped/0136-Provide-E-TE-Chunk-count-stat-methods.patch similarity index 100% rename from patches/server-remapped/0134-Provide-E-TE-Chunk-count-stat-methods.patch rename to patches/server-remapped/0136-Provide-E-TE-Chunk-count-stat-methods.patch diff --git a/patches/server-remapped/0135-Enforce-Sync-Player-Saves.patch b/patches/server-remapped/0137-Enforce-Sync-Player-Saves.patch similarity index 100% rename from patches/server-remapped/0135-Enforce-Sync-Player-Saves.patch rename to patches/server-remapped/0137-Enforce-Sync-Player-Saves.patch diff --git a/patches/server-remapped/0136-Don-t-allow-entities-to-ride-themselves-572.patch b/patches/server-remapped/0138-Don-t-allow-entities-to-ride-themselves-572.patch similarity index 100% rename from patches/server-remapped/0136-Don-t-allow-entities-to-ride-themselves-572.patch rename to patches/server-remapped/0138-Don-t-allow-entities-to-ride-themselves-572.patch diff --git a/patches/server-remapped/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server-remapped/0139-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch similarity index 100% rename from patches/server-remapped/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch rename to patches/server-remapped/0139-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch diff --git a/patches/server-remapped/0138-Cap-Entity-Collisions.patch b/patches/server-remapped/0140-Cap-Entity-Collisions.patch similarity index 100% rename from patches/server-remapped/0138-Cap-Entity-Collisions.patch rename to patches/server-remapped/0140-Cap-Entity-Collisions.patch diff --git a/patches/server-remapped/0139-Remove-CraftScheduler-Async-Task-Debugger.patch b/patches/server-remapped/0141-Remove-CraftScheduler-Async-Task-Debugger.patch similarity index 100% rename from patches/server-remapped/0139-Remove-CraftScheduler-Async-Task-Debugger.patch rename to patches/server-remapped/0141-Remove-CraftScheduler-Async-Task-Debugger.patch diff --git a/patches/server-remapped/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/patches/server-remapped/0142-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch similarity index 100% rename from patches/server-remapped/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch rename to patches/server-remapped/0142-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch diff --git a/patches/server-remapped/0141-Do-not-let-armorstands-drown.patch b/patches/server-remapped/0143-Do-not-let-armorstands-drown.patch similarity index 100% rename from patches/server-remapped/0141-Do-not-let-armorstands-drown.patch rename to patches/server-remapped/0143-Do-not-let-armorstands-drown.patch diff --git a/patches/server-remapped/0142-Properly-handle-async-calls-to-restart-the-server.patch b/patches/server-remapped/0144-Properly-handle-async-calls-to-restart-the-server.patch similarity index 100% rename from patches/server-remapped/0142-Properly-handle-async-calls-to-restart-the-server.patch rename to patches/server-remapped/0144-Properly-handle-async-calls-to-restart-the-server.patch diff --git a/patches/server-remapped/0143-Add-system-property-to-disable-book-size-limits.patch b/patches/server-remapped/0145-Add-system-property-to-disable-book-size-limits.patch similarity index 100% rename from patches/server-remapped/0143-Add-system-property-to-disable-book-size-limits.patch rename to patches/server-remapped/0145-Add-system-property-to-disable-book-size-limits.patch diff --git a/patches/server-remapped/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/patches/server-remapped/0146-Add-option-to-make-parrots-stay-on-shoulders-despite.patch similarity index 100% rename from patches/server-remapped/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch rename to patches/server-remapped/0146-Add-option-to-make-parrots-stay-on-shoulders-despite.patch diff --git a/patches/server-remapped/0145-Add-configuration-option-to-prevent-player-names-fro.patch b/patches/server-remapped/0147-Add-configuration-option-to-prevent-player-names-fro.patch similarity index 100% rename from patches/server-remapped/0145-Add-configuration-option-to-prevent-player-names-fro.patch rename to patches/server-remapped/0147-Add-configuration-option-to-prevent-player-names-fro.patch diff --git a/patches/server-remapped/0146-Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server-remapped/0148-Use-TerminalConsoleAppender-for-console-improvements.patch similarity index 100% rename from patches/server-remapped/0146-Use-TerminalConsoleAppender-for-console-improvements.patch rename to patches/server-remapped/0148-Use-TerminalConsoleAppender-for-console-improvements.patch diff --git a/patches/server-remapped/0147-provide-a-configurable-option-to-disable-creeper-lin.patch b/patches/server-remapped/0149-provide-a-configurable-option-to-disable-creeper-lin.patch similarity index 100% rename from patches/server-remapped/0147-provide-a-configurable-option-to-disable-creeper-lin.patch rename to patches/server-remapped/0149-provide-a-configurable-option-to-disable-creeper-lin.patch diff --git a/patches/server-remapped/0148-Item-canEntityPickup.patch b/patches/server-remapped/0150-Item-canEntityPickup.patch similarity index 100% rename from patches/server-remapped/0148-Item-canEntityPickup.patch rename to patches/server-remapped/0150-Item-canEntityPickup.patch diff --git a/patches/server-remapped/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch b/patches/server-remapped/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch similarity index 100% rename from patches/server-remapped/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch rename to patches/server-remapped/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch diff --git a/patches/server-remapped/0150-PlayerAttemptPickupItemEvent.patch b/patches/server-remapped/0152-PlayerAttemptPickupItemEvent.patch similarity index 100% rename from patches/server-remapped/0150-PlayerAttemptPickupItemEvent.patch rename to patches/server-remapped/0152-PlayerAttemptPickupItemEvent.patch diff --git a/patches/server-remapped/0151-Add-UnknownCommandEvent.patch b/patches/server-remapped/0153-Add-UnknownCommandEvent.patch similarity index 100% rename from patches/server-remapped/0151-Add-UnknownCommandEvent.patch rename to patches/server-remapped/0153-Add-UnknownCommandEvent.patch diff --git a/patches/server-remapped/0152-Basic-PlayerProfile-API.patch b/patches/server-remapped/0154-Basic-PlayerProfile-API.patch similarity index 100% rename from patches/server-remapped/0152-Basic-PlayerProfile-API.patch rename to patches/server-remapped/0154-Basic-PlayerProfile-API.patch diff --git a/patches/server-remapped/0153-Shoulder-Entities-Release-API.patch b/patches/server-remapped/0155-Shoulder-Entities-Release-API.patch similarity index 100% rename from patches/server-remapped/0153-Shoulder-Entities-Release-API.patch rename to patches/server-remapped/0155-Shoulder-Entities-Release-API.patch diff --git a/patches/server-remapped/0154-Profile-Lookup-Events.patch b/patches/server-remapped/0156-Profile-Lookup-Events.patch similarity index 100% rename from patches/server-remapped/0154-Profile-Lookup-Events.patch rename to patches/server-remapped/0156-Profile-Lookup-Events.patch diff --git a/patches/server-remapped/0155-Block-player-logins-during-server-shutdown.patch b/patches/server-remapped/0157-Block-player-logins-during-server-shutdown.patch similarity index 100% rename from patches/server-remapped/0155-Block-player-logins-during-server-shutdown.patch rename to patches/server-remapped/0157-Block-player-logins-during-server-shutdown.patch diff --git a/patches/server-remapped/0156-Entity-fromMobSpawner.patch b/patches/server-remapped/0158-Entity-fromMobSpawner.patch similarity index 100% rename from patches/server-remapped/0156-Entity-fromMobSpawner.patch rename to patches/server-remapped/0158-Entity-fromMobSpawner.patch diff --git a/patches/server-remapped/0157-Improve-the-Saddle-API-for-Horses.patch b/patches/server-remapped/0159-Improve-the-Saddle-API-for-Horses.patch similarity index 100% rename from patches/server-remapped/0157-Improve-the-Saddle-API-for-Horses.patch rename to patches/server-remapped/0159-Improve-the-Saddle-API-for-Horses.patch diff --git a/patches/server-remapped/0158-Implement-ensureServerConversions-API.patch b/patches/server-remapped/0160-Implement-ensureServerConversions-API.patch similarity index 100% rename from patches/server-remapped/0158-Implement-ensureServerConversions-API.patch rename to patches/server-remapped/0160-Implement-ensureServerConversions-API.patch diff --git a/patches/server-remapped/0159-Implement-getI18NDisplayName.patch b/patches/server-remapped/0161-Implement-getI18NDisplayName.patch similarity index 100% rename from patches/server-remapped/0159-Implement-getI18NDisplayName.patch rename to patches/server-remapped/0161-Implement-getI18NDisplayName.patch diff --git a/patches/server-remapped/0160-ProfileWhitelistVerifyEvent.patch b/patches/server-remapped/0162-ProfileWhitelistVerifyEvent.patch similarity index 100% rename from patches/server-remapped/0160-ProfileWhitelistVerifyEvent.patch rename to patches/server-remapped/0162-ProfileWhitelistVerifyEvent.patch diff --git a/patches/server-remapped/0161-Fix-this-stupid-bullshit.patch b/patches/server-remapped/0163-Fix-this-stupid-bullshit.patch similarity index 100% rename from patches/server-remapped/0161-Fix-this-stupid-bullshit.patch rename to patches/server-remapped/0163-Fix-this-stupid-bullshit.patch diff --git a/patches/server-remapped/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch b/patches/server-remapped/0164-Ocelot-despawns-should-honor-nametags-and-leash.patch similarity index 100% rename from patches/server-remapped/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch rename to patches/server-remapped/0164-Ocelot-despawns-should-honor-nametags-and-leash.patch diff --git a/patches/server-remapped/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/patches/server-remapped/0165-Reset-spawner-timer-when-spawner-event-is-cancelled.patch similarity index 100% rename from patches/server-remapped/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch rename to patches/server-remapped/0165-Reset-spawner-timer-when-spawner-event-is-cancelled.patch diff --git a/patches/server-remapped/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/patches/server-remapped/0166-Fix-MC-117075-TE-Unload-Lag-Spike.patch similarity index 100% rename from patches/server-remapped/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch rename to patches/server-remapped/0166-Fix-MC-117075-TE-Unload-Lag-Spike.patch diff --git a/patches/server-remapped/0165-Allow-specifying-a-custom-authentication-servers-dow.patch b/patches/server-remapped/0167-Allow-specifying-a-custom-authentication-servers-dow.patch similarity index 100% rename from patches/server-remapped/0165-Allow-specifying-a-custom-authentication-servers-dow.patch rename to patches/server-remapped/0167-Allow-specifying-a-custom-authentication-servers-dow.patch diff --git a/patches/server-remapped/0166-LivingEntity-setKiller.patch b/patches/server-remapped/0168-LivingEntity-setKiller.patch similarity index 100% rename from patches/server-remapped/0166-LivingEntity-setKiller.patch rename to patches/server-remapped/0168-LivingEntity-setKiller.patch diff --git a/patches/server-remapped/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch b/patches/server-remapped/0169-Handle-plugin-prefixes-using-Log4J-configuration.patch similarity index 100% rename from patches/server-remapped/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch rename to patches/server-remapped/0169-Handle-plugin-prefixes-using-Log4J-configuration.patch diff --git a/patches/server-remapped/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch b/patches/server-remapped/0170-Improve-Log4J-Configuration-Plugin-Loggers.patch similarity index 100% rename from patches/server-remapped/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch rename to patches/server-remapped/0170-Improve-Log4J-Configuration-Plugin-Loggers.patch diff --git a/patches/server-remapped/0169-Add-PlayerJumpEvent.patch b/patches/server-remapped/0171-Add-PlayerJumpEvent.patch similarity index 100% rename from patches/server-remapped/0169-Add-PlayerJumpEvent.patch rename to patches/server-remapped/0171-Add-PlayerJumpEvent.patch diff --git a/patches/server-remapped/0170-handle-PacketPlayInKeepAlive-async.patch b/patches/server-remapped/0172-handle-PacketPlayInKeepAlive-async.patch similarity index 100% rename from patches/server-remapped/0170-handle-PacketPlayInKeepAlive-async.patch rename to patches/server-remapped/0172-handle-PacketPlayInKeepAlive-async.patch diff --git a/patches/server-remapped/0171-Expose-client-protocol-version-and-virtual-host.patch b/patches/server-remapped/0173-Expose-client-protocol-version-and-virtual-host.patch similarity index 100% rename from patches/server-remapped/0171-Expose-client-protocol-version-and-virtual-host.patch rename to patches/server-remapped/0173-Expose-client-protocol-version-and-virtual-host.patch diff --git a/patches/server-remapped/0172-revert-serverside-behavior-of-keepalives.patch b/patches/server-remapped/0174-revert-serverside-behavior-of-keepalives.patch similarity index 100% rename from patches/server-remapped/0172-revert-serverside-behavior-of-keepalives.patch rename to patches/server-remapped/0174-revert-serverside-behavior-of-keepalives.patch diff --git a/patches/server-remapped/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch b/patches/server-remapped/0175-Send-attack-SoundEffects-only-to-players-who-can-see.patch similarity index 100% rename from patches/server-remapped/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch rename to patches/server-remapped/0175-Send-attack-SoundEffects-only-to-players-who-can-see.patch diff --git a/patches/server-remapped/0174-Option-for-maximum-exp-value-when-merging-orbs.patch b/patches/server-remapped/0176-Option-for-maximum-exp-value-when-merging-orbs.patch similarity index 100% rename from patches/server-remapped/0174-Option-for-maximum-exp-value-when-merging-orbs.patch rename to patches/server-remapped/0176-Option-for-maximum-exp-value-when-merging-orbs.patch diff --git a/patches/server-remapped/0175-Add-PlayerArmorChangeEvent.patch b/patches/server-remapped/0177-Add-PlayerArmorChangeEvent.patch similarity index 100% rename from patches/server-remapped/0175-Add-PlayerArmorChangeEvent.patch rename to patches/server-remapped/0177-Add-PlayerArmorChangeEvent.patch diff --git a/patches/server-remapped/0176-Prevent-logins-from-being-processed-when-the-player-.patch b/patches/server-remapped/0178-Prevent-logins-from-being-processed-when-the-player-.patch similarity index 100% rename from patches/server-remapped/0176-Prevent-logins-from-being-processed-when-the-player-.patch rename to patches/server-remapped/0178-Prevent-logins-from-being-processed-when-the-player-.patch diff --git a/patches/server-remapped/0177-use-CB-BlockState-implementations-for-captured-block.patch b/patches/server-remapped/0179-use-CB-BlockState-implementations-for-captured-block.patch similarity index 100% rename from patches/server-remapped/0177-use-CB-BlockState-implementations-for-captured-block.patch rename to patches/server-remapped/0179-use-CB-BlockState-implementations-for-captured-block.patch diff --git a/patches/server-remapped/0178-API-to-get-a-BlockState-without-a-snapshot.patch b/patches/server-remapped/0180-API-to-get-a-BlockState-without-a-snapshot.patch similarity index 100% rename from patches/server-remapped/0178-API-to-get-a-BlockState-without-a-snapshot.patch rename to patches/server-remapped/0180-API-to-get-a-BlockState-without-a-snapshot.patch diff --git a/patches/server-remapped/0179-AsyncTabCompleteEvent.patch b/patches/server-remapped/0181-AsyncTabCompleteEvent.patch similarity index 100% rename from patches/server-remapped/0179-AsyncTabCompleteEvent.patch rename to patches/server-remapped/0181-AsyncTabCompleteEvent.patch diff --git a/patches/server-remapped/0180-Avoid-NPE-in-PathfinderGoalTempt.patch b/patches/server-remapped/0182-Avoid-NPE-in-PathfinderGoalTempt.patch similarity index 100% rename from patches/server-remapped/0180-Avoid-NPE-in-PathfinderGoalTempt.patch rename to patches/server-remapped/0182-Avoid-NPE-in-PathfinderGoalTempt.patch diff --git a/patches/server-remapped/0181-PlayerPickupExperienceEvent.patch b/patches/server-remapped/0183-PlayerPickupExperienceEvent.patch similarity index 100% rename from patches/server-remapped/0181-PlayerPickupExperienceEvent.patch rename to patches/server-remapped/0183-PlayerPickupExperienceEvent.patch diff --git a/patches/server-remapped/0182-ExperienceOrbMergeEvent.patch b/patches/server-remapped/0184-ExperienceOrbMergeEvent.patch similarity index 100% rename from patches/server-remapped/0182-ExperienceOrbMergeEvent.patch rename to patches/server-remapped/0184-ExperienceOrbMergeEvent.patch diff --git a/patches/server-remapped/0183-Ability-to-apply-mending-to-XP-API.patch b/patches/server-remapped/0185-Ability-to-apply-mending-to-XP-API.patch similarity index 100% rename from patches/server-remapped/0183-Ability-to-apply-mending-to-XP-API.patch rename to patches/server-remapped/0185-Ability-to-apply-mending-to-XP-API.patch diff --git a/patches/server-remapped/0184-Make-max-squid-spawn-height-configurable.patch b/patches/server-remapped/0186-Make-max-squid-spawn-height-configurable.patch similarity index 100% rename from patches/server-remapped/0184-Make-max-squid-spawn-height-configurable.patch rename to patches/server-remapped/0186-Make-max-squid-spawn-height-configurable.patch diff --git a/patches/server-remapped/0185-PreCreatureSpawnEvent.patch b/patches/server-remapped/0187-PreCreatureSpawnEvent.patch similarity index 100% rename from patches/server-remapped/0185-PreCreatureSpawnEvent.patch rename to patches/server-remapped/0187-PreCreatureSpawnEvent.patch diff --git a/patches/server-remapped/0186-PlayerNaturallySpawnCreaturesEvent.patch b/patches/server-remapped/0188-PlayerNaturallySpawnCreaturesEvent.patch similarity index 100% rename from patches/server-remapped/0186-PlayerNaturallySpawnCreaturesEvent.patch rename to patches/server-remapped/0188-PlayerNaturallySpawnCreaturesEvent.patch diff --git a/patches/server-remapped/0187-Add-setPlayerProfile-API-for-Skulls.patch b/patches/server-remapped/0189-Add-setPlayerProfile-API-for-Skulls.patch similarity index 100% rename from patches/server-remapped/0187-Add-setPlayerProfile-API-for-Skulls.patch rename to patches/server-remapped/0189-Add-setPlayerProfile-API-for-Skulls.patch diff --git a/patches/server-remapped/0188-Fill-Profile-Property-Events.patch b/patches/server-remapped/0190-Fill-Profile-Property-Events.patch similarity index 100% rename from patches/server-remapped/0188-Fill-Profile-Property-Events.patch rename to patches/server-remapped/0190-Fill-Profile-Property-Events.patch diff --git a/patches/server-remapped/0189-PlayerAdvancementCriterionGrantEvent.patch b/patches/server-remapped/0191-PlayerAdvancementCriterionGrantEvent.patch similarity index 100% rename from patches/server-remapped/0189-PlayerAdvancementCriterionGrantEvent.patch rename to patches/server-remapped/0191-PlayerAdvancementCriterionGrantEvent.patch diff --git a/patches/server-remapped/0190-Add-ArmorStand-Item-Meta.patch b/patches/server-remapped/0192-Add-ArmorStand-Item-Meta.patch similarity index 100% rename from patches/server-remapped/0190-Add-ArmorStand-Item-Meta.patch rename to patches/server-remapped/0192-Add-ArmorStand-Item-Meta.patch diff --git a/patches/server-remapped/0191-Extend-Player-Interact-cancellation.patch b/patches/server-remapped/0193-Extend-Player-Interact-cancellation.patch similarity index 100% rename from patches/server-remapped/0191-Extend-Player-Interact-cancellation.patch rename to patches/server-remapped/0193-Extend-Player-Interact-cancellation.patch diff --git a/patches/server-remapped/0192-Tameable-getOwnerUniqueId-API.patch b/patches/server-remapped/0194-Tameable-getOwnerUniqueId-API.patch similarity index 100% rename from patches/server-remapped/0192-Tameable-getOwnerUniqueId-API.patch rename to patches/server-remapped/0194-Tameable-getOwnerUniqueId-API.patch diff --git a/patches/server-remapped/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch b/patches/server-remapped/0195-Toggleable-player-crits-helps-mitigate-hacked-client.patch similarity index 100% rename from patches/server-remapped/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch rename to patches/server-remapped/0195-Toggleable-player-crits-helps-mitigate-hacked-client.patch diff --git a/patches/server-remapped/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/patches/server-remapped/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch similarity index 100% rename from patches/server-remapped/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch rename to patches/server-remapped/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch diff --git a/patches/server-remapped/0195-Disable-Explicit-Network-Manager-Flushing.patch b/patches/server-remapped/0197-Disable-Explicit-Network-Manager-Flushing.patch similarity index 100% rename from patches/server-remapped/0195-Disable-Explicit-Network-Manager-Flushing.patch rename to patches/server-remapped/0197-Disable-Explicit-Network-Manager-Flushing.patch diff --git a/patches/server-remapped/0196-Implement-extended-PaperServerListPingEvent.patch b/patches/server-remapped/0198-Implement-extended-PaperServerListPingEvent.patch similarity index 100% rename from patches/server-remapped/0196-Implement-extended-PaperServerListPingEvent.patch rename to patches/server-remapped/0198-Implement-extended-PaperServerListPingEvent.patch diff --git a/patches/server-remapped/0197-Improved-Async-Task-Scheduler.patch b/patches/server-remapped/0199-Improved-Async-Task-Scheduler.patch similarity index 100% rename from patches/server-remapped/0197-Improved-Async-Task-Scheduler.patch rename to patches/server-remapped/0199-Improved-Async-Task-Scheduler.patch diff --git a/patches/server-remapped/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/patches/server-remapped/0200-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch similarity index 100% rename from patches/server-remapped/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch rename to patches/server-remapped/0200-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch diff --git a/patches/server-remapped/0199-Player.setPlayerProfile-API.patch b/patches/server-remapped/0201-Player.setPlayerProfile-API.patch similarity index 100% rename from patches/server-remapped/0199-Player.setPlayerProfile-API.patch rename to patches/server-remapped/0201-Player.setPlayerProfile-API.patch diff --git a/patches/server-remapped/0200-Fix-Dragon-Server-Crashes.patch b/patches/server-remapped/0202-Fix-Dragon-Server-Crashes.patch similarity index 100% rename from patches/server-remapped/0200-Fix-Dragon-Server-Crashes.patch rename to patches/server-remapped/0202-Fix-Dragon-Server-Crashes.patch diff --git a/patches/server-remapped/0201-getPlayerUniqueId-API.patch b/patches/server-remapped/0203-getPlayerUniqueId-API.patch similarity index 100% rename from patches/server-remapped/0201-getPlayerUniqueId-API.patch rename to patches/server-remapped/0203-getPlayerUniqueId-API.patch diff --git a/patches/server-remapped/0202-Make-player-data-saving-configurable.patch b/patches/server-remapped/0204-Make-player-data-saving-configurable.patch similarity index 100% rename from patches/server-remapped/0202-Make-player-data-saving-configurable.patch rename to patches/server-remapped/0204-Make-player-data-saving-configurable.patch diff --git a/patches/server-remapped/0203-Make-legacy-ping-handler-more-reliable.patch b/patches/server-remapped/0205-Make-legacy-ping-handler-more-reliable.patch similarity index 100% rename from patches/server-remapped/0203-Make-legacy-ping-handler-more-reliable.patch rename to patches/server-remapped/0205-Make-legacy-ping-handler-more-reliable.patch diff --git a/patches/server-remapped/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch b/patches/server-remapped/0206-Call-PaperServerListPingEvent-for-legacy-pings.patch similarity index 100% rename from patches/server-remapped/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch rename to patches/server-remapped/0206-Call-PaperServerListPingEvent-for-legacy-pings.patch diff --git a/patches/server-remapped/0205-Flag-to-disable-the-channel-limit.patch b/patches/server-remapped/0207-Flag-to-disable-the-channel-limit.patch similarity index 100% rename from patches/server-remapped/0205-Flag-to-disable-the-channel-limit.patch rename to patches/server-remapped/0207-Flag-to-disable-the-channel-limit.patch diff --git a/patches/server-remapped/0206-Add-method-to-open-already-placed-sign.patch b/patches/server-remapped/0208-Add-method-to-open-already-placed-sign.patch similarity index 100% rename from patches/server-remapped/0206-Add-method-to-open-already-placed-sign.patch rename to patches/server-remapped/0208-Add-method-to-open-already-placed-sign.patch diff --git a/patches/server-remapped/0207-Configurable-sprint-interruption-on-attack.patch b/patches/server-remapped/0209-Configurable-sprint-interruption-on-attack.patch similarity index 100% rename from patches/server-remapped/0207-Configurable-sprint-interruption-on-attack.patch rename to patches/server-remapped/0209-Configurable-sprint-interruption-on-attack.patch diff --git a/patches/server-remapped/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/patches/server-remapped/0210-Fix-exploit-that-allowed-colored-signs-to-be-created.patch similarity index 100% rename from patches/server-remapped/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch rename to patches/server-remapped/0210-Fix-exploit-that-allowed-colored-signs-to-be-created.patch diff --git a/patches/server-remapped/0209-EndermanEscapeEvent.patch b/patches/server-remapped/0211-EndermanEscapeEvent.patch similarity index 100% rename from patches/server-remapped/0209-EndermanEscapeEvent.patch rename to patches/server-remapped/0211-EndermanEscapeEvent.patch diff --git a/patches/server-remapped/0210-Enderman.teleportRandomly.patch b/patches/server-remapped/0212-Enderman.teleportRandomly.patch similarity index 100% rename from patches/server-remapped/0210-Enderman.teleportRandomly.patch rename to patches/server-remapped/0212-Enderman.teleportRandomly.patch diff --git a/patches/server-remapped/0211-Block-Enderpearl-Travel-Exploit.patch b/patches/server-remapped/0213-Block-Enderpearl-Travel-Exploit.patch similarity index 100% rename from patches/server-remapped/0211-Block-Enderpearl-Travel-Exploit.patch rename to patches/server-remapped/0213-Block-Enderpearl-Travel-Exploit.patch diff --git a/patches/server-remapped/0212-Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/server-remapped/0214-Expand-World.spawnParticle-API-and-add-Builder.patch similarity index 100% rename from patches/server-remapped/0212-Expand-World.spawnParticle-API-and-add-Builder.patch rename to patches/server-remapped/0214-Expand-World.spawnParticle-API-and-add-Builder.patch diff --git a/patches/server-remapped/0213-EndermanAttackPlayerEvent.patch b/patches/server-remapped/0215-EndermanAttackPlayerEvent.patch similarity index 100% rename from patches/server-remapped/0213-EndermanAttackPlayerEvent.patch rename to patches/server-remapped/0215-EndermanAttackPlayerEvent.patch diff --git a/patches/server-remapped/0214-WitchConsumePotionEvent.patch b/patches/server-remapped/0216-WitchConsumePotionEvent.patch similarity index 100% rename from patches/server-remapped/0214-WitchConsumePotionEvent.patch rename to patches/server-remapped/0216-WitchConsumePotionEvent.patch diff --git a/patches/server-remapped/0215-WitchThrowPotionEvent.patch b/patches/server-remapped/0217-WitchThrowPotionEvent.patch similarity index 100% rename from patches/server-remapped/0215-WitchThrowPotionEvent.patch rename to patches/server-remapped/0217-WitchThrowPotionEvent.patch diff --git a/patches/server-remapped/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/patches/server-remapped/0218-Allow-spawning-Item-entities-with-World.spawnEntity.patch similarity index 100% rename from patches/server-remapped/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch rename to patches/server-remapped/0218-Allow-spawning-Item-entities-with-World.spawnEntity.patch diff --git a/patches/server-remapped/0217-WitchReadyPotionEvent.patch b/patches/server-remapped/0219-WitchReadyPotionEvent.patch similarity index 100% rename from patches/server-remapped/0217-WitchReadyPotionEvent.patch rename to patches/server-remapped/0219-WitchReadyPotionEvent.patch diff --git a/patches/server-remapped/0218-ItemStack-getMaxItemUseDuration.patch b/patches/server-remapped/0220-ItemStack-getMaxItemUseDuration.patch similarity index 100% rename from patches/server-remapped/0218-ItemStack-getMaxItemUseDuration.patch rename to patches/server-remapped/0220-ItemStack-getMaxItemUseDuration.patch diff --git a/patches/server-remapped/0219-Implement-EntityTeleportEndGatewayEvent.patch b/patches/server-remapped/0221-Implement-EntityTeleportEndGatewayEvent.patch similarity index 100% rename from patches/server-remapped/0219-Implement-EntityTeleportEndGatewayEvent.patch rename to patches/server-remapped/0221-Implement-EntityTeleportEndGatewayEvent.patch diff --git a/patches/server-remapped/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/patches/server-remapped/0222-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch similarity index 100% rename from patches/server-remapped/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch rename to patches/server-remapped/0222-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch diff --git a/patches/server-remapped/0221-Fix-CraftEntity-hashCode.patch b/patches/server-remapped/0223-Fix-CraftEntity-hashCode.patch similarity index 100% rename from patches/server-remapped/0221-Fix-CraftEntity-hashCode.patch rename to patches/server-remapped/0223-Fix-CraftEntity-hashCode.patch diff --git a/patches/server-remapped/0222-Configurable-Alternative-LootPool-Luck-Formula.patch b/patches/server-remapped/0224-Configurable-Alternative-LootPool-Luck-Formula.patch similarity index 100% rename from patches/server-remapped/0222-Configurable-Alternative-LootPool-Luck-Formula.patch rename to patches/server-remapped/0224-Configurable-Alternative-LootPool-Luck-Formula.patch diff --git a/patches/server-remapped/0223-Print-Error-details-when-failing-to-save-player-data.patch b/patches/server-remapped/0225-Print-Error-details-when-failing-to-save-player-data.patch similarity index 100% rename from patches/server-remapped/0223-Print-Error-details-when-failing-to-save-player-data.patch rename to patches/server-remapped/0225-Print-Error-details-when-failing-to-save-player-data.patch diff --git a/patches/server-remapped/0224-Make-shield-blocking-delay-configurable.patch b/patches/server-remapped/0226-Make-shield-blocking-delay-configurable.patch similarity index 100% rename from patches/server-remapped/0224-Make-shield-blocking-delay-configurable.patch rename to patches/server-remapped/0226-Make-shield-blocking-delay-configurable.patch diff --git a/patches/server-remapped/0225-Improve-EntityShootBowEvent.patch b/patches/server-remapped/0227-Improve-EntityShootBowEvent.patch similarity index 100% rename from patches/server-remapped/0225-Improve-EntityShootBowEvent.patch rename to patches/server-remapped/0227-Improve-EntityShootBowEvent.patch diff --git a/patches/server-remapped/0226-PlayerReadyArrowEvent.patch b/patches/server-remapped/0228-PlayerReadyArrowEvent.patch similarity index 100% rename from patches/server-remapped/0226-PlayerReadyArrowEvent.patch rename to patches/server-remapped/0228-PlayerReadyArrowEvent.patch diff --git a/patches/server-remapped/0227-Implement-EntityKnockbackByEntityEvent.patch b/patches/server-remapped/0229-Implement-EntityKnockbackByEntityEvent.patch similarity index 100% rename from patches/server-remapped/0227-Implement-EntityKnockbackByEntityEvent.patch rename to patches/server-remapped/0229-Implement-EntityKnockbackByEntityEvent.patch diff --git a/patches/server-remapped/0228-Expand-Explosions-API.patch b/patches/server-remapped/0230-Expand-Explosions-API.patch similarity index 100% rename from patches/server-remapped/0228-Expand-Explosions-API.patch rename to patches/server-remapped/0230-Expand-Explosions-API.patch diff --git a/patches/server-remapped/0229-LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/server-remapped/0231-LivingEntity-Hand-Raised-Item-Use-API.patch similarity index 100% rename from patches/server-remapped/0229-LivingEntity-Hand-Raised-Item-Use-API.patch rename to patches/server-remapped/0231-LivingEntity-Hand-Raised-Item-Use-API.patch diff --git a/patches/server-remapped/0230-RangedEntity-API.patch b/patches/server-remapped/0232-RangedEntity-API.patch similarity index 100% rename from patches/server-remapped/0230-RangedEntity-API.patch rename to patches/server-remapped/0232-RangedEntity-API.patch diff --git a/patches/server-remapped/0231-Add-config-to-disable-ender-dragon-legacy-check.patch b/patches/server-remapped/0233-Add-config-to-disable-ender-dragon-legacy-check.patch similarity index 100% rename from patches/server-remapped/0231-Add-config-to-disable-ender-dragon-legacy-check.patch rename to patches/server-remapped/0233-Add-config-to-disable-ender-dragon-legacy-check.patch diff --git a/patches/server-remapped/0232-Implement-World.getEntity-UUID-API.patch b/patches/server-remapped/0234-Implement-World.getEntity-UUID-API.patch similarity index 100% rename from patches/server-remapped/0232-Implement-World.getEntity-UUID-API.patch rename to patches/server-remapped/0234-Implement-World.getEntity-UUID-API.patch diff --git a/patches/server-remapped/0233-InventoryCloseEvent-Reason-API.patch b/patches/server-remapped/0235-InventoryCloseEvent-Reason-API.patch similarity index 100% rename from patches/server-remapped/0233-InventoryCloseEvent-Reason-API.patch rename to patches/server-remapped/0235-InventoryCloseEvent-Reason-API.patch diff --git a/patches/server-remapped/0234-Vex-getSummoner-API.patch b/patches/server-remapped/0236-Vex-getSummoner-API.patch similarity index 100% rename from patches/server-remapped/0234-Vex-getSummoner-API.patch rename to patches/server-remapped/0236-Vex-getSummoner-API.patch diff --git a/patches/server-remapped/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/patches/server-remapped/0237-Refresh-player-inventory-when-cancelling-PlayerInter.patch similarity index 100% rename from patches/server-remapped/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch rename to patches/server-remapped/0237-Refresh-player-inventory-when-cancelling-PlayerInter.patch diff --git a/patches/server-remapped/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch b/patches/server-remapped/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch similarity index 100% rename from patches/server-remapped/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch rename to patches/server-remapped/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch diff --git a/patches/server-remapped/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch b/patches/server-remapped/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch similarity index 100% rename from patches/server-remapped/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch rename to patches/server-remapped/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch diff --git a/patches/server-remapped/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch b/patches/server-remapped/0240-Avoid-item-merge-if-stack-size-above-max-stack-size.patch similarity index 100% rename from patches/server-remapped/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch rename to patches/server-remapped/0240-Avoid-item-merge-if-stack-size-above-max-stack-size.patch diff --git a/patches/server-remapped/0239-Use-asynchronous-Log4j-2-loggers.patch b/patches/server-remapped/0241-Use-asynchronous-Log4j-2-loggers.patch similarity index 100% rename from patches/server-remapped/0239-Use-asynchronous-Log4j-2-loggers.patch rename to patches/server-remapped/0241-Use-asynchronous-Log4j-2-loggers.patch diff --git a/patches/server-remapped/0240-add-more-information-to-Entity.toString.patch b/patches/server-remapped/0242-add-more-information-to-Entity.toString.patch similarity index 100% rename from patches/server-remapped/0240-add-more-information-to-Entity.toString.patch rename to patches/server-remapped/0242-add-more-information-to-Entity.toString.patch diff --git a/patches/server-remapped/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/patches/server-remapped/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch similarity index 100% rename from patches/server-remapped/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch rename to patches/server-remapped/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch diff --git a/patches/server-remapped/0242-EnderDragon-Events.patch b/patches/server-remapped/0244-EnderDragon-Events.patch similarity index 100% rename from patches/server-remapped/0242-EnderDragon-Events.patch rename to patches/server-remapped/0244-EnderDragon-Events.patch diff --git a/patches/server-remapped/0243-PlayerElytraBoostEvent.patch b/patches/server-remapped/0245-PlayerElytraBoostEvent.patch similarity index 100% rename from patches/server-remapped/0243-PlayerElytraBoostEvent.patch rename to patches/server-remapped/0245-PlayerElytraBoostEvent.patch diff --git a/patches/server-remapped/0244-Improve-BlockPosition-inlining.patch b/patches/server-remapped/0246-Improve-BlockPosition-inlining.patch similarity index 100% rename from patches/server-remapped/0244-Improve-BlockPosition-inlining.patch rename to patches/server-remapped/0246-Improve-BlockPosition-inlining.patch diff --git a/patches/server-remapped/0245-Optimize-RegistryID.c.patch b/patches/server-remapped/0247-Optimize-RegistryID.c.patch similarity index 100% rename from patches/server-remapped/0245-Optimize-RegistryID.c.patch rename to patches/server-remapped/0247-Optimize-RegistryID.c.patch diff --git a/patches/server-remapped/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/patches/server-remapped/0248-Option-to-prevent-armor-stands-from-doing-entity-loo.patch similarity index 100% rename from patches/server-remapped/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch rename to patches/server-remapped/0248-Option-to-prevent-armor-stands-from-doing-entity-loo.patch diff --git a/patches/server-remapped/0247-Vanished-players-don-t-have-rights.patch b/patches/server-remapped/0249-Vanished-players-don-t-have-rights.patch similarity index 100% rename from patches/server-remapped/0247-Vanished-players-don-t-have-rights.patch rename to patches/server-remapped/0249-Vanished-players-don-t-have-rights.patch diff --git a/patches/server-remapped/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch b/patches/server-remapped/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch similarity index 100% rename from patches/server-remapped/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch rename to patches/server-remapped/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch diff --git a/patches/server-remapped/0249-Add-some-Debug-to-Chunk-Entity-slices.patch b/patches/server-remapped/0251-Add-some-Debug-to-Chunk-Entity-slices.patch similarity index 100% rename from patches/server-remapped/0249-Add-some-Debug-to-Chunk-Entity-slices.patch rename to patches/server-remapped/0251-Add-some-Debug-to-Chunk-Entity-slices.patch diff --git a/patches/server-remapped/0250-SkeletonHorse-Additions.patch b/patches/server-remapped/0252-SkeletonHorse-Additions.patch similarity index 100% rename from patches/server-remapped/0250-SkeletonHorse-Additions.patch rename to patches/server-remapped/0252-SkeletonHorse-Additions.patch diff --git a/patches/server-remapped/0251-Prevent-Saving-Bad-entities-to-chunks.patch b/patches/server-remapped/0253-Prevent-Saving-Bad-entities-to-chunks.patch similarity index 100% rename from patches/server-remapped/0251-Prevent-Saving-Bad-entities-to-chunks.patch rename to patches/server-remapped/0253-Prevent-Saving-Bad-entities-to-chunks.patch diff --git a/patches/server-remapped/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch b/patches/server-remapped/0254-Don-t-call-getItemMeta-on-hasItemMeta.patch similarity index 100% rename from patches/server-remapped/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch rename to patches/server-remapped/0254-Don-t-call-getItemMeta-on-hasItemMeta.patch diff --git a/patches/server-remapped/0253-Ignore-Dead-Entities-in-entityList-iteration.patch b/patches/server-remapped/0255-Ignore-Dead-Entities-in-entityList-iteration.patch similarity index 100% rename from patches/server-remapped/0253-Ignore-Dead-Entities-in-entityList-iteration.patch rename to patches/server-remapped/0255-Ignore-Dead-Entities-in-entityList-iteration.patch diff --git a/patches/server-remapped/0254-Implement-Expanded-ArmorStand-API.patch b/patches/server-remapped/0256-Implement-Expanded-ArmorStand-API.patch similarity index 100% rename from patches/server-remapped/0254-Implement-Expanded-ArmorStand-API.patch rename to patches/server-remapped/0256-Implement-Expanded-ArmorStand-API.patch diff --git a/patches/server-remapped/0255-AnvilDamageEvent.patch b/patches/server-remapped/0257-AnvilDamageEvent.patch similarity index 100% rename from patches/server-remapped/0255-AnvilDamageEvent.patch rename to patches/server-remapped/0257-AnvilDamageEvent.patch diff --git a/patches/server-remapped/0256-Add-TNTPrimeEvent.patch b/patches/server-remapped/0258-Add-TNTPrimeEvent.patch similarity index 100% rename from patches/server-remapped/0256-Add-TNTPrimeEvent.patch rename to patches/server-remapped/0258-Add-TNTPrimeEvent.patch diff --git a/patches/server-remapped/0257-Break-up-and-make-tab-spam-limits-configurable.patch b/patches/server-remapped/0259-Break-up-and-make-tab-spam-limits-configurable.patch similarity index 100% rename from patches/server-remapped/0257-Break-up-and-make-tab-spam-limits-configurable.patch rename to patches/server-remapped/0259-Break-up-and-make-tab-spam-limits-configurable.patch diff --git a/patches/server-remapped/0258-Add-hand-to-bucket-events.patch b/patches/server-remapped/0260-Add-hand-to-bucket-events.patch similarity index 100% rename from patches/server-remapped/0258-Add-hand-to-bucket-events.patch rename to patches/server-remapped/0260-Add-hand-to-bucket-events.patch diff --git a/patches/server-remapped/0259-MC-135506-Experience-should-save-as-Integers.patch b/patches/server-remapped/0261-MC-135506-Experience-should-save-as-Integers.patch similarity index 100% rename from patches/server-remapped/0259-MC-135506-Experience-should-save-as-Integers.patch rename to patches/server-remapped/0261-MC-135506-Experience-should-save-as-Integers.patch diff --git a/patches/server-remapped/0260-Fix-client-rendering-skulls-from-same-user.patch b/patches/server-remapped/0262-Fix-client-rendering-skulls-from-same-user.patch similarity index 100% rename from patches/server-remapped/0260-Fix-client-rendering-skulls-from-same-user.patch rename to patches/server-remapped/0262-Fix-client-rendering-skulls-from-same-user.patch diff --git a/patches/server-remapped/0261-Add-Early-Warning-Feature-to-WatchDog.patch b/patches/server-remapped/0263-Add-Early-Warning-Feature-to-WatchDog.patch similarity index 100% rename from patches/server-remapped/0261-Add-Early-Warning-Feature-to-WatchDog.patch rename to patches/server-remapped/0263-Add-Early-Warning-Feature-to-WatchDog.patch diff --git a/patches/server-remapped/0262-Make-EnderDragon-implement-Mob.patch b/patches/server-remapped/0264-Make-EnderDragon-implement-Mob.patch similarity index 100% rename from patches/server-remapped/0262-Make-EnderDragon-implement-Mob.patch rename to patches/server-remapped/0264-Make-EnderDragon-implement-Mob.patch diff --git a/patches/server-remapped/0263-Use-ConcurrentHashMap-in-JsonList.patch b/patches/server-remapped/0265-Use-ConcurrentHashMap-in-JsonList.patch similarity index 100% rename from patches/server-remapped/0263-Use-ConcurrentHashMap-in-JsonList.patch rename to patches/server-remapped/0265-Use-ConcurrentHashMap-in-JsonList.patch diff --git a/patches/server-remapped/0264-Use-a-Queue-for-Queueing-Commands.patch b/patches/server-remapped/0266-Use-a-Queue-for-Queueing-Commands.patch similarity index 100% rename from patches/server-remapped/0264-Use-a-Queue-for-Queueing-Commands.patch rename to patches/server-remapped/0266-Use-a-Queue-for-Queueing-Commands.patch diff --git a/patches/server-remapped/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/patches/server-remapped/0267-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch similarity index 100% rename from patches/server-remapped/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch rename to patches/server-remapped/0267-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch diff --git a/patches/server-remapped/0266-Allow-disabling-armour-stand-ticking.patch b/patches/server-remapped/0268-Allow-disabling-armour-stand-ticking.patch similarity index 100% rename from patches/server-remapped/0266-Allow-disabling-armour-stand-ticking.patch rename to patches/server-remapped/0268-Allow-disabling-armour-stand-ticking.patch diff --git a/patches/server-remapped/0267-Optimize-BlockPosition-helper-methods.patch b/patches/server-remapped/0269-Optimize-BlockPosition-helper-methods.patch similarity index 100% rename from patches/server-remapped/0267-Optimize-BlockPosition-helper-methods.patch rename to patches/server-remapped/0269-Optimize-BlockPosition-helper-methods.patch diff --git a/patches/server-remapped/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/patches/server-remapped/0270-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch similarity index 100% rename from patches/server-remapped/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch rename to patches/server-remapped/0270-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch diff --git a/patches/server-remapped/0269-Slime-Pathfinder-Events.patch b/patches/server-remapped/0271-Slime-Pathfinder-Events.patch similarity index 100% rename from patches/server-remapped/0269-Slime-Pathfinder-Events.patch rename to patches/server-remapped/0271-Slime-Pathfinder-Events.patch diff --git a/patches/server-remapped/0270-Configurable-speed-for-water-flowing-over-lava.patch b/patches/server-remapped/0272-Configurable-speed-for-water-flowing-over-lava.patch similarity index 100% rename from patches/server-remapped/0270-Configurable-speed-for-water-flowing-over-lava.patch rename to patches/server-remapped/0272-Configurable-speed-for-water-flowing-over-lava.patch diff --git a/patches/server-remapped/0271-Optimize-CraftBlockData-Creation.patch b/patches/server-remapped/0273-Optimize-CraftBlockData-Creation.patch similarity index 100% rename from patches/server-remapped/0271-Optimize-CraftBlockData-Creation.patch rename to patches/server-remapped/0273-Optimize-CraftBlockData-Creation.patch diff --git a/patches/server-remapped/0272-Optimize-RegistryMaterials.patch b/patches/server-remapped/0274-Optimize-RegistryMaterials.patch similarity index 100% rename from patches/server-remapped/0272-Optimize-RegistryMaterials.patch rename to patches/server-remapped/0274-Optimize-RegistryMaterials.patch diff --git a/patches/server-remapped/0273-Add-PhantomPreSpawnEvent.patch b/patches/server-remapped/0275-Add-PhantomPreSpawnEvent.patch similarity index 100% rename from patches/server-remapped/0273-Add-PhantomPreSpawnEvent.patch rename to patches/server-remapped/0275-Add-PhantomPreSpawnEvent.patch diff --git a/patches/server-remapped/0274-Add-More-Creeper-API.patch b/patches/server-remapped/0276-Add-More-Creeper-API.patch similarity index 100% rename from patches/server-remapped/0274-Add-More-Creeper-API.patch rename to patches/server-remapped/0276-Add-More-Creeper-API.patch diff --git a/patches/server-remapped/0275-Inventory-removeItemAnySlot.patch b/patches/server-remapped/0277-Inventory-removeItemAnySlot.patch similarity index 100% rename from patches/server-remapped/0275-Inventory-removeItemAnySlot.patch rename to patches/server-remapped/0277-Inventory-removeItemAnySlot.patch diff --git a/patches/server-remapped/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/patches/server-remapped/0278-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch similarity index 100% rename from patches/server-remapped/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch rename to patches/server-remapped/0278-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch diff --git a/patches/server-remapped/0277-Add-ray-tracing-methods-to-LivingEntity.patch b/patches/server-remapped/0279-Add-ray-tracing-methods-to-LivingEntity.patch similarity index 100% rename from patches/server-remapped/0277-Add-ray-tracing-methods-to-LivingEntity.patch rename to patches/server-remapped/0279-Add-ray-tracing-methods-to-LivingEntity.patch diff --git a/patches/server-remapped/0278-Expose-attack-cooldown-methods-for-Player.patch b/patches/server-remapped/0280-Expose-attack-cooldown-methods-for-Player.patch similarity index 100% rename from patches/server-remapped/0278-Expose-attack-cooldown-methods-for-Player.patch rename to patches/server-remapped/0280-Expose-attack-cooldown-methods-for-Player.patch diff --git a/patches/server-remapped/0279-Improve-death-events.patch b/patches/server-remapped/0281-Improve-death-events.patch similarity index 100% rename from patches/server-remapped/0279-Improve-death-events.patch rename to patches/server-remapped/0281-Improve-death-events.patch diff --git a/patches/server-remapped/0280-Allow-chests-to-be-placed-with-NBT-data.patch b/patches/server-remapped/0282-Allow-chests-to-be-placed-with-NBT-data.patch similarity index 100% rename from patches/server-remapped/0280-Allow-chests-to-be-placed-with-NBT-data.patch rename to patches/server-remapped/0282-Allow-chests-to-be-placed-with-NBT-data.patch diff --git a/patches/server-remapped/0281-Mob-Pathfinding-API.patch b/patches/server-remapped/0283-Mob-Pathfinding-API.patch similarity index 100% rename from patches/server-remapped/0281-Mob-Pathfinding-API.patch rename to patches/server-remapped/0283-Mob-Pathfinding-API.patch diff --git a/patches/server-remapped/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch b/patches/server-remapped/0284-Prevent-chunk-loading-from-Fluid-Flowing.patch similarity index 100% rename from patches/server-remapped/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch rename to patches/server-remapped/0284-Prevent-chunk-loading-from-Fluid-Flowing.patch diff --git a/patches/server-remapped/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/patches/server-remapped/0285-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch similarity index 100% rename from patches/server-remapped/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch rename to patches/server-remapped/0285-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch diff --git a/patches/server-remapped/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/patches/server-remapped/0286-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch similarity index 100% rename from patches/server-remapped/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch rename to patches/server-remapped/0286-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch diff --git a/patches/server-remapped/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch b/patches/server-remapped/0287-Prevent-mob-spawning-from-loading-generating-chunks.patch similarity index 100% rename from patches/server-remapped/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch rename to patches/server-remapped/0287-Prevent-mob-spawning-from-loading-generating-chunks.patch diff --git a/patches/server-remapped/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/server-remapped/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch similarity index 100% rename from patches/server-remapped/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch rename to patches/server-remapped/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch diff --git a/patches/server-remapped/0287-Implement-furnace-cook-speed-multiplier-API.patch b/patches/server-remapped/0289-Implement-furnace-cook-speed-multiplier-API.patch similarity index 100% rename from patches/server-remapped/0287-Implement-furnace-cook-speed-multiplier-API.patch rename to patches/server-remapped/0289-Implement-furnace-cook-speed-multiplier-API.patch diff --git a/patches/server-remapped/0288-PreSpawnerSpawnEvent.patch b/patches/server-remapped/0290-PreSpawnerSpawnEvent.patch similarity index 100% rename from patches/server-remapped/0288-PreSpawnerSpawnEvent.patch rename to patches/server-remapped/0290-PreSpawnerSpawnEvent.patch diff --git a/patches/server-remapped/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch b/patches/server-remapped/0291-Catch-JsonParseException-in-Entity-and-TE-names.patch similarity index 100% rename from patches/server-remapped/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch rename to patches/server-remapped/0291-Catch-JsonParseException-in-Entity-and-TE-names.patch diff --git a/patches/server-remapped/0290-Honor-EntityAgeable.ageLock.patch b/patches/server-remapped/0292-Honor-EntityAgeable.ageLock.patch similarity index 100% rename from patches/server-remapped/0290-Honor-EntityAgeable.ageLock.patch rename to patches/server-remapped/0292-Honor-EntityAgeable.ageLock.patch diff --git a/patches/server-remapped/0291-Configurable-connection-throttle-kick-message.patch b/patches/server-remapped/0293-Configurable-connection-throttle-kick-message.patch similarity index 100% rename from patches/server-remapped/0291-Configurable-connection-throttle-kick-message.patch rename to patches/server-remapped/0293-Configurable-connection-throttle-kick-message.patch diff --git a/patches/server-remapped/0292-Hook-into-CB-plugin-rewrites.patch b/patches/server-remapped/0294-Hook-into-CB-plugin-rewrites.patch similarity index 100% rename from patches/server-remapped/0292-Hook-into-CB-plugin-rewrites.patch rename to patches/server-remapped/0294-Hook-into-CB-plugin-rewrites.patch diff --git a/patches/server-remapped/0293-Allow-setting-the-vex-s-summoner.patch b/patches/server-remapped/0295-Allow-setting-the-vex-s-summoner.patch similarity index 100% rename from patches/server-remapped/0293-Allow-setting-the-vex-s-summoner.patch rename to patches/server-remapped/0295-Allow-setting-the-vex-s-summoner.patch diff --git a/patches/server-remapped/0294-Add-sun-related-API.patch b/patches/server-remapped/0296-Add-sun-related-API.patch similarity index 100% rename from patches/server-remapped/0294-Add-sun-related-API.patch rename to patches/server-remapped/0296-Add-sun-related-API.patch diff --git a/patches/server-remapped/0295-Turtle-API.patch b/patches/server-remapped/0297-Turtle-API.patch similarity index 100% rename from patches/server-remapped/0295-Turtle-API.patch rename to patches/server-remapped/0297-Turtle-API.patch diff --git a/patches/server-remapped/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/patches/server-remapped/0298-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch similarity index 100% rename from patches/server-remapped/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch rename to patches/server-remapped/0298-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch diff --git a/patches/server-remapped/0297-Call-player-spectator-target-events-and-improve-impl.patch b/patches/server-remapped/0299-Call-player-spectator-target-events-and-improve-impl.patch similarity index 100% rename from patches/server-remapped/0297-Call-player-spectator-target-events-and-improve-impl.patch rename to patches/server-remapped/0299-Call-player-spectator-target-events-and-improve-impl.patch diff --git a/patches/server-remapped/0298-Add-Velocity-IP-Forwarding-Support.patch b/patches/server-remapped/0300-Add-Velocity-IP-Forwarding-Support.patch similarity index 100% rename from patches/server-remapped/0298-Add-Velocity-IP-Forwarding-Support.patch rename to patches/server-remapped/0300-Add-Velocity-IP-Forwarding-Support.patch diff --git a/patches/server-remapped/0299-Add-more-Witch-API.patch b/patches/server-remapped/0301-Add-more-Witch-API.patch similarity index 100% rename from patches/server-remapped/0299-Add-more-Witch-API.patch rename to patches/server-remapped/0301-Add-more-Witch-API.patch diff --git a/patches/server-remapped/0300-Check-Drowned-for-Villager-Aggression-Config.patch b/patches/server-remapped/0302-Check-Drowned-for-Villager-Aggression-Config.patch similarity index 100% rename from patches/server-remapped/0300-Check-Drowned-for-Villager-Aggression-Config.patch rename to patches/server-remapped/0302-Check-Drowned-for-Villager-Aggression-Config.patch diff --git a/patches/server-remapped/0301-Here-s-Johnny.patch b/patches/server-remapped/0303-Here-s-Johnny.patch similarity index 100% rename from patches/server-remapped/0301-Here-s-Johnny.patch rename to patches/server-remapped/0303-Here-s-Johnny.patch diff --git a/patches/server-remapped/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch b/patches/server-remapped/0304-Add-option-to-prevent-players-from-moving-into-unloa.patch similarity index 100% rename from patches/server-remapped/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch rename to patches/server-remapped/0304-Add-option-to-prevent-players-from-moving-into-unloa.patch diff --git a/patches/server-remapped/0303-Reset-players-airTicks-on-respawn.patch b/patches/server-remapped/0305-Reset-players-airTicks-on-respawn.patch similarity index 100% rename from patches/server-remapped/0303-Reset-players-airTicks-on-respawn.patch rename to patches/server-remapped/0305-Reset-players-airTicks-on-respawn.patch diff --git a/patches/server-remapped/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch b/patches/server-remapped/0306-Don-t-sleep-after-profile-lookups-if-not-needed.patch similarity index 100% rename from patches/server-remapped/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch rename to patches/server-remapped/0306-Don-t-sleep-after-profile-lookups-if-not-needed.patch diff --git a/patches/server-remapped/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/patches/server-remapped/0307-Improve-Server-Thread-Pool-and-Thread-Priorities.patch similarity index 100% rename from patches/server-remapped/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch rename to patches/server-remapped/0307-Improve-Server-Thread-Pool-and-Thread-Priorities.patch diff --git a/patches/server-remapped/0306-Optimize-World-Time-Updates.patch b/patches/server-remapped/0308-Optimize-World-Time-Updates.patch similarity index 100% rename from patches/server-remapped/0306-Optimize-World-Time-Updates.patch rename to patches/server-remapped/0308-Optimize-World-Time-Updates.patch diff --git a/patches/server-remapped/0307-Restore-custom-InventoryHolder-support.patch b/patches/server-remapped/0309-Restore-custom-InventoryHolder-support.patch similarity index 100% rename from patches/server-remapped/0307-Restore-custom-InventoryHolder-support.patch rename to patches/server-remapped/0309-Restore-custom-InventoryHolder-support.patch diff --git a/patches/server-remapped/0308-Use-Vanilla-Minecart-Speeds.patch b/patches/server-remapped/0310-Use-Vanilla-Minecart-Speeds.patch similarity index 100% rename from patches/server-remapped/0308-Use-Vanilla-Minecart-Speeds.patch rename to patches/server-remapped/0310-Use-Vanilla-Minecart-Speeds.patch diff --git a/patches/server-remapped/0309-Fix-SpongeAbsortEvent-handling.patch b/patches/server-remapped/0311-Fix-SpongeAbsortEvent-handling.patch similarity index 100% rename from patches/server-remapped/0309-Fix-SpongeAbsortEvent-handling.patch rename to patches/server-remapped/0311-Fix-SpongeAbsortEvent-handling.patch diff --git a/patches/server-remapped/0310-Don-t-allow-digging-into-unloaded-chunks.patch b/patches/server-remapped/0312-Don-t-allow-digging-into-unloaded-chunks.patch similarity index 100% rename from patches/server-remapped/0310-Don-t-allow-digging-into-unloaded-chunks.patch rename to patches/server-remapped/0312-Don-t-allow-digging-into-unloaded-chunks.patch diff --git a/patches/server-remapped/0311-Book-Size-Limits.patch b/patches/server-remapped/0313-Book-Size-Limits.patch similarity index 100% rename from patches/server-remapped/0311-Book-Size-Limits.patch rename to patches/server-remapped/0313-Book-Size-Limits.patch diff --git a/patches/server-remapped/0312-Make-the-default-permission-message-configurable.patch b/patches/server-remapped/0314-Make-the-default-permission-message-configurable.patch similarity index 100% rename from patches/server-remapped/0312-Make-the-default-permission-message-configurable.patch rename to patches/server-remapped/0314-Make-the-default-permission-message-configurable.patch diff --git a/patches/server-remapped/0313-Prevent-rayTrace-from-loading-chunks.patch b/patches/server-remapped/0315-Prevent-rayTrace-from-loading-chunks.patch similarity index 100% rename from patches/server-remapped/0313-Prevent-rayTrace-from-loading-chunks.patch rename to patches/server-remapped/0315-Prevent-rayTrace-from-loading-chunks.patch diff --git a/patches/server-remapped/0314-Handle-Large-Packets-disconnecting-client.patch b/patches/server-remapped/0316-Handle-Large-Packets-disconnecting-client.patch similarity index 100% rename from patches/server-remapped/0314-Handle-Large-Packets-disconnecting-client.patch rename to patches/server-remapped/0316-Handle-Large-Packets-disconnecting-client.patch diff --git a/patches/server-remapped/0315-force-entity-dismount-during-teleportation.patch b/patches/server-remapped/0317-force-entity-dismount-during-teleportation.patch similarity index 100% rename from patches/server-remapped/0315-force-entity-dismount-during-teleportation.patch rename to patches/server-remapped/0317-force-entity-dismount-during-teleportation.patch diff --git a/patches/server-remapped/0316-Add-more-Zombie-API.patch b/patches/server-remapped/0318-Add-more-Zombie-API.patch similarity index 100% rename from patches/server-remapped/0316-Add-more-Zombie-API.patch rename to patches/server-remapped/0318-Add-more-Zombie-API.patch diff --git a/patches/server-remapped/0317-Add-PlayerConnectionCloseEvent.patch b/patches/server-remapped/0319-Add-PlayerConnectionCloseEvent.patch similarity index 100% rename from patches/server-remapped/0317-Add-PlayerConnectionCloseEvent.patch rename to patches/server-remapped/0319-Add-PlayerConnectionCloseEvent.patch diff --git a/patches/server-remapped/0318-Prevent-Enderman-from-loading-chunks.patch b/patches/server-remapped/0320-Prevent-Enderman-from-loading-chunks.patch similarity index 100% rename from patches/server-remapped/0318-Prevent-Enderman-from-loading-chunks.patch rename to patches/server-remapped/0320-Prevent-Enderman-from-loading-chunks.patch diff --git a/patches/server-remapped/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/patches/server-remapped/0321-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 100% rename from patches/server-remapped/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to patches/server-remapped/0321-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch diff --git a/patches/server-remapped/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/patches/server-remapped/0322-Workaround-for-vehicle-tracking-issue-on-disconnect.patch similarity index 100% rename from patches/server-remapped/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch rename to patches/server-remapped/0322-Workaround-for-vehicle-tracking-issue-on-disconnect.patch diff --git a/patches/server-remapped/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/patches/server-remapped/0323-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch similarity index 100% rename from patches/server-remapped/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch rename to patches/server-remapped/0323-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch diff --git a/patches/server-remapped/0322-Block-Entity-remove-from-being-called-on-Players.patch b/patches/server-remapped/0324-Block-Entity-remove-from-being-called-on-Players.patch similarity index 100% rename from patches/server-remapped/0322-Block-Entity-remove-from-being-called-on-Players.patch rename to patches/server-remapped/0324-Block-Entity-remove-from-being-called-on-Players.patch diff --git a/patches/server-remapped/0323-BlockDestroyEvent.patch b/patches/server-remapped/0325-BlockDestroyEvent.patch similarity index 100% rename from patches/server-remapped/0323-BlockDestroyEvent.patch rename to patches/server-remapped/0325-BlockDestroyEvent.patch diff --git a/patches/server-remapped/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/patches/server-remapped/0326-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch similarity index 100% rename from patches/server-remapped/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch rename to patches/server-remapped/0326-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch diff --git a/patches/server-remapped/0325-Fix-sign-edit-memory-leak.patch b/patches/server-remapped/0327-Fix-sign-edit-memory-leak.patch similarity index 100% rename from patches/server-remapped/0325-Fix-sign-edit-memory-leak.patch rename to patches/server-remapped/0327-Fix-sign-edit-memory-leak.patch diff --git a/patches/server-remapped/0326-Limit-Client-Sign-length-more.patch b/patches/server-remapped/0328-Limit-Client-Sign-length-more.patch similarity index 100% rename from patches/server-remapped/0326-Limit-Client-Sign-length-more.patch rename to patches/server-remapped/0328-Limit-Client-Sign-length-more.patch diff --git a/patches/server-remapped/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/patches/server-remapped/0329-Don-t-check-ConvertSigns-boolean-every-sign-save.patch similarity index 100% rename from patches/server-remapped/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch rename to patches/server-remapped/0329-Don-t-check-ConvertSigns-boolean-every-sign-save.patch diff --git a/patches/server-remapped/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server-remapped/0330-Optimize-Network-Manager-and-add-advanced-packet-sup.patch similarity index 100% rename from patches/server-remapped/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch rename to patches/server-remapped/0330-Optimize-Network-Manager-and-add-advanced-packet-sup.patch diff --git a/patches/server-remapped/0329-Handle-Oversized-Tile-Entities-in-chunks.patch b/patches/server-remapped/0331-Handle-Oversized-Tile-Entities-in-chunks.patch similarity index 100% rename from patches/server-remapped/0329-Handle-Oversized-Tile-Entities-in-chunks.patch rename to patches/server-remapped/0331-Handle-Oversized-Tile-Entities-in-chunks.patch diff --git a/patches/server-remapped/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/patches/server-remapped/0332-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch similarity index 100% rename from patches/server-remapped/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch rename to patches/server-remapped/0332-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch diff --git a/patches/server-remapped/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/patches/server-remapped/0333-Set-Zombie-last-tick-at-start-of-drowning-process.patch similarity index 100% rename from patches/server-remapped/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch rename to patches/server-remapped/0333-Set-Zombie-last-tick-at-start-of-drowning-process.patch diff --git a/patches/server-remapped/0332-Allow-Saving-of-Oversized-Chunks.patch b/patches/server-remapped/0334-Allow-Saving-of-Oversized-Chunks.patch similarity index 100% rename from patches/server-remapped/0332-Allow-Saving-of-Oversized-Chunks.patch rename to patches/server-remapped/0334-Allow-Saving-of-Oversized-Chunks.patch diff --git a/patches/server-remapped/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/patches/server-remapped/0335-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch similarity index 100% rename from patches/server-remapped/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch rename to patches/server-remapped/0335-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch diff --git a/patches/server-remapped/0334-Add-LivingEntity-getTargetEntity.patch b/patches/server-remapped/0336-Add-LivingEntity-getTargetEntity.patch similarity index 100% rename from patches/server-remapped/0334-Add-LivingEntity-getTargetEntity.patch rename to patches/server-remapped/0336-Add-LivingEntity-getTargetEntity.patch diff --git a/patches/server-remapped/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/patches/server-remapped/0337-Use-proper-max-length-when-serialising-BungeeCord-te.patch similarity index 100% rename from patches/server-remapped/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch rename to patches/server-remapped/0337-Use-proper-max-length-when-serialising-BungeeCord-te.patch diff --git a/patches/server-remapped/0336-Entity-getEntitySpawnReason.patch b/patches/server-remapped/0338-Entity-getEntitySpawnReason.patch similarity index 100% rename from patches/server-remapped/0336-Entity-getEntitySpawnReason.patch rename to patches/server-remapped/0338-Entity-getEntitySpawnReason.patch diff --git a/patches/server-remapped/0337-Update-entity-Metadata-for-all-tracked-players.patch b/patches/server-remapped/0339-Update-entity-Metadata-for-all-tracked-players.patch similarity index 100% rename from patches/server-remapped/0337-Update-entity-Metadata-for-all-tracked-players.patch rename to patches/server-remapped/0339-Update-entity-Metadata-for-all-tracked-players.patch diff --git a/patches/server-remapped/0338-Implement-PlayerPostRespawnEvent.patch b/patches/server-remapped/0340-Implement-PlayerPostRespawnEvent.patch similarity index 100% rename from patches/server-remapped/0338-Implement-PlayerPostRespawnEvent.patch rename to patches/server-remapped/0340-Implement-PlayerPostRespawnEvent.patch diff --git a/patches/server-remapped/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/patches/server-remapped/0341-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch similarity index 100% rename from patches/server-remapped/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch rename to patches/server-remapped/0341-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch diff --git a/patches/server-remapped/0340-Server-Tick-Events.patch b/patches/server-remapped/0342-Server-Tick-Events.patch similarity index 100% rename from patches/server-remapped/0340-Server-Tick-Events.patch rename to patches/server-remapped/0342-Server-Tick-Events.patch diff --git a/patches/server-remapped/0341-PlayerDeathEvent-getItemsToKeep.patch b/patches/server-remapped/0343-PlayerDeathEvent-getItemsToKeep.patch similarity index 100% rename from patches/server-remapped/0341-PlayerDeathEvent-getItemsToKeep.patch rename to patches/server-remapped/0343-PlayerDeathEvent-getItemsToKeep.patch diff --git a/patches/server-remapped/0342-Optimize-Captured-TileEntity-Lookup.patch b/patches/server-remapped/0344-Optimize-Captured-TileEntity-Lookup.patch similarity index 100% rename from patches/server-remapped/0342-Optimize-Captured-TileEntity-Lookup.patch rename to patches/server-remapped/0344-Optimize-Captured-TileEntity-Lookup.patch diff --git a/patches/server-remapped/0343-Add-Heightmap-API.patch b/patches/server-remapped/0345-Add-Heightmap-API.patch similarity index 100% rename from patches/server-remapped/0343-Add-Heightmap-API.patch rename to patches/server-remapped/0345-Add-Heightmap-API.patch diff --git a/patches/server-remapped/0344-Mob-Spawner-API-Enhancements.patch b/patches/server-remapped/0346-Mob-Spawner-API-Enhancements.patch similarity index 100% rename from patches/server-remapped/0344-Mob-Spawner-API-Enhancements.patch rename to patches/server-remapped/0346-Mob-Spawner-API-Enhancements.patch diff --git a/patches/server-remapped/0345-Per-Player-View-Distance-API-placeholders.patch b/patches/server-remapped/0347-Per-Player-View-Distance-API-placeholders.patch similarity index 100% rename from patches/server-remapped/0345-Per-Player-View-Distance-API-placeholders.patch rename to patches/server-remapped/0347-Per-Player-View-Distance-API-placeholders.patch diff --git a/patches/server-remapped/0346-Fix-CB-call-to-changed-postToMainThread-method.patch b/patches/server-remapped/0348-Fix-CB-call-to-changed-postToMainThread-method.patch similarity index 100% rename from patches/server-remapped/0346-Fix-CB-call-to-changed-postToMainThread-method.patch rename to patches/server-remapped/0348-Fix-CB-call-to-changed-postToMainThread-method.patch diff --git a/patches/server-remapped/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/patches/server-remapped/0349-Fix-sounds-when-item-frames-are-modified-MC-123450.patch similarity index 100% rename from patches/server-remapped/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch rename to patches/server-remapped/0349-Fix-sounds-when-item-frames-are-modified-MC-123450.patch diff --git a/patches/server-remapped/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/patches/server-remapped/0350-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch similarity index 100% rename from patches/server-remapped/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch rename to patches/server-remapped/0350-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch diff --git a/patches/server-remapped/0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch b/patches/server-remapped/0351-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch similarity index 100% rename from patches/server-remapped/0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch rename to patches/server-remapped/0351-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch diff --git a/patches/server-remapped/0350-Duplicate-UUID-Resolve-Option.patch b/patches/server-remapped/0352-Duplicate-UUID-Resolve-Option.patch similarity index 100% rename from patches/server-remapped/0350-Duplicate-UUID-Resolve-Option.patch rename to patches/server-remapped/0352-Duplicate-UUID-Resolve-Option.patch diff --git a/patches/server-remapped/0351-improve-CraftWorld-isChunkLoaded.patch b/patches/server-remapped/0353-improve-CraftWorld-isChunkLoaded.patch similarity index 100% rename from patches/server-remapped/0351-improve-CraftWorld-isChunkLoaded.patch rename to patches/server-remapped/0353-improve-CraftWorld-isChunkLoaded.patch diff --git a/patches/server-remapped/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server-remapped/0354-Configurable-Keep-Spawn-Loaded-range-per-world.patch similarity index 100% rename from patches/server-remapped/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch rename to patches/server-remapped/0354-Configurable-Keep-Spawn-Loaded-range-per-world.patch diff --git a/patches/server-remapped/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch b/patches/server-remapped/0355-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch similarity index 100% rename from patches/server-remapped/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch rename to patches/server-remapped/0355-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch diff --git a/patches/server-remapped/0354-ChunkMapDistance-CME.patch b/patches/server-remapped/0356-ChunkMapDistance-CME.patch similarity index 100% rename from patches/server-remapped/0354-ChunkMapDistance-CME.patch rename to patches/server-remapped/0356-ChunkMapDistance-CME.patch diff --git a/patches/server-remapped/0355-Implement-CraftBlockSoundGroup.patch b/patches/server-remapped/0357-Implement-CraftBlockSoundGroup.patch similarity index 100% rename from patches/server-remapped/0355-Implement-CraftBlockSoundGroup.patch rename to patches/server-remapped/0357-Implement-CraftBlockSoundGroup.patch diff --git a/patches/server-remapped/0356-Chunk-debug-command.patch b/patches/server-remapped/0358-Chunk-debug-command.patch similarity index 100% rename from patches/server-remapped/0356-Chunk-debug-command.patch rename to patches/server-remapped/0358-Chunk-debug-command.patch diff --git a/patches/server-remapped/0357-Catch-exceptions-from-dispenser-entity-spawns.patch b/patches/server-remapped/0359-Catch-exceptions-from-dispenser-entity-spawns.patch similarity index 100% rename from patches/server-remapped/0357-Catch-exceptions-from-dispenser-entity-spawns.patch rename to patches/server-remapped/0359-Catch-exceptions-from-dispenser-entity-spawns.patch diff --git a/patches/server-remapped/0358-Fix-World-isChunkGenerated-calls.patch b/patches/server-remapped/0360-Fix-World-isChunkGenerated-calls.patch similarity index 100% rename from patches/server-remapped/0358-Fix-World-isChunkGenerated-calls.patch rename to patches/server-remapped/0360-Fix-World-isChunkGenerated-calls.patch diff --git a/patches/server-remapped/0359-Show-blockstate-location-if-we-failed-to-read-it.patch b/patches/server-remapped/0361-Show-blockstate-location-if-we-failed-to-read-it.patch similarity index 100% rename from patches/server-remapped/0359-Show-blockstate-location-if-we-failed-to-read-it.patch rename to patches/server-remapped/0361-Show-blockstate-location-if-we-failed-to-read-it.patch diff --git a/patches/server-remapped/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch b/patches/server-remapped/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch similarity index 100% rename from patches/server-remapped/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch rename to patches/server-remapped/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch diff --git a/patches/server-remapped/0361-incremental-chunk-saving.patch b/patches/server-remapped/0363-incremental-chunk-saving.patch similarity index 100% rename from patches/server-remapped/0361-incremental-chunk-saving.patch rename to patches/server-remapped/0363-incremental-chunk-saving.patch diff --git a/patches/server-remapped/0362-Anti-Xray.patch b/patches/server-remapped/0364-Anti-Xray.patch similarity index 100% rename from patches/server-remapped/0362-Anti-Xray.patch rename to patches/server-remapped/0364-Anti-Xray.patch diff --git a/patches/server-remapped/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/patches/server-remapped/0365-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch similarity index 100% rename from patches/server-remapped/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch rename to patches/server-remapped/0365-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch diff --git a/patches/server-remapped/0364-Configurable-projectile-relative-velocity.patch b/patches/server-remapped/0366-Configurable-projectile-relative-velocity.patch similarity index 100% rename from patches/server-remapped/0364-Configurable-projectile-relative-velocity.patch rename to patches/server-remapped/0366-Configurable-projectile-relative-velocity.patch diff --git a/patches/server-remapped/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch b/patches/server-remapped/0367-Mark-entities-as-being-ticked-when-notifying-navigat.patch similarity index 100% rename from patches/server-remapped/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch rename to patches/server-remapped/0367-Mark-entities-as-being-ticked-when-notifying-navigat.patch diff --git a/patches/server-remapped/0366-offset-item-frame-ticking.patch b/patches/server-remapped/0368-offset-item-frame-ticking.patch similarity index 100% rename from patches/server-remapped/0366-offset-item-frame-ticking.patch rename to patches/server-remapped/0368-offset-item-frame-ticking.patch diff --git a/patches/server-remapped/0367-Avoid-hopper-searches-if-there-are-no-items.patch b/patches/server-remapped/0369-Avoid-hopper-searches-if-there-are-no-items.patch similarity index 100% rename from patches/server-remapped/0367-Avoid-hopper-searches-if-there-are-no-items.patch rename to patches/server-remapped/0369-Avoid-hopper-searches-if-there-are-no-items.patch diff --git a/patches/server-remapped/0368-Asynchronous-chunk-IO-and-loading.patch b/patches/server-remapped/0370-Asynchronous-chunk-IO-and-loading.patch similarity index 100% rename from patches/server-remapped/0368-Asynchronous-chunk-IO-and-loading.patch rename to patches/server-remapped/0370-Asynchronous-chunk-IO-and-loading.patch diff --git a/patches/server-remapped/0369-Use-getChunkIfLoadedImmediately-in-places.patch b/patches/server-remapped/0371-Use-getChunkIfLoadedImmediately-in-places.patch similarity index 100% rename from patches/server-remapped/0369-Use-getChunkIfLoadedImmediately-in-places.patch rename to patches/server-remapped/0371-Use-getChunkIfLoadedImmediately-in-places.patch diff --git a/patches/server-remapped/0370-Reduce-sync-loads.patch b/patches/server-remapped/0372-Reduce-sync-loads.patch similarity index 100% rename from patches/server-remapped/0370-Reduce-sync-loads.patch rename to patches/server-remapped/0372-Reduce-sync-loads.patch diff --git a/patches/server-remapped/0371-Implement-alternative-item-despawn-rate.patch b/patches/server-remapped/0373-Implement-alternative-item-despawn-rate.patch similarity index 100% rename from patches/server-remapped/0371-Implement-alternative-item-despawn-rate.patch rename to patches/server-remapped/0373-Implement-alternative-item-despawn-rate.patch diff --git a/patches/server-remapped/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/patches/server-remapped/0374-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch similarity index 100% rename from patches/server-remapped/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch rename to patches/server-remapped/0374-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch diff --git a/patches/server-remapped/0373-Fix-MC-158900.patch b/patches/server-remapped/0375-Fix-MC-158900.patch similarity index 100% rename from patches/server-remapped/0373-Fix-MC-158900.patch rename to patches/server-remapped/0375-Fix-MC-158900.patch diff --git a/patches/server-remapped/0374-implement-optional-per-player-mob-spawns.patch b/patches/server-remapped/0376-implement-optional-per-player-mob-spawns.patch similarity index 100% rename from patches/server-remapped/0374-implement-optional-per-player-mob-spawns.patch rename to patches/server-remapped/0376-implement-optional-per-player-mob-spawns.patch diff --git a/patches/server-remapped/0375-Prevent-consuming-the-wrong-itemstack.patch b/patches/server-remapped/0377-Prevent-consuming-the-wrong-itemstack.patch similarity index 100% rename from patches/server-remapped/0375-Prevent-consuming-the-wrong-itemstack.patch rename to patches/server-remapped/0377-Prevent-consuming-the-wrong-itemstack.patch diff --git a/patches/server-remapped/0376-Generator-Settings.patch b/patches/server-remapped/0378-Generator-Settings.patch similarity index 100% rename from patches/server-remapped/0376-Generator-Settings.patch rename to patches/server-remapped/0378-Generator-Settings.patch diff --git a/patches/server-remapped/0377-Fix-MC-161754.patch b/patches/server-remapped/0379-Fix-MC-161754.patch similarity index 100% rename from patches/server-remapped/0377-Fix-MC-161754.patch rename to patches/server-remapped/0379-Fix-MC-161754.patch diff --git a/patches/server-remapped/0378-Performance-improvement-for-Chunk.getEntities.patch b/patches/server-remapped/0380-Performance-improvement-for-Chunk.getEntities.patch similarity index 100% rename from patches/server-remapped/0378-Performance-improvement-for-Chunk.getEntities.patch rename to patches/server-remapped/0380-Performance-improvement-for-Chunk.getEntities.patch diff --git a/patches/server-remapped/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/patches/server-remapped/0381-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch similarity index 100% rename from patches/server-remapped/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch rename to patches/server-remapped/0381-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch diff --git a/patches/server-remapped/0380-Expose-the-internal-current-tick.patch b/patches/server-remapped/0382-Expose-the-internal-current-tick.patch similarity index 100% rename from patches/server-remapped/0380-Expose-the-internal-current-tick.patch rename to patches/server-remapped/0382-Expose-the-internal-current-tick.patch diff --git a/patches/server-remapped/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/patches/server-remapped/0383-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch similarity index 100% rename from patches/server-remapped/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch rename to patches/server-remapped/0383-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch diff --git a/patches/server-remapped/0382-Add-option-to-disable-pillager-patrols.patch b/patches/server-remapped/0384-Add-option-to-disable-pillager-patrols.patch similarity index 100% rename from patches/server-remapped/0382-Add-option-to-disable-pillager-patrols.patch rename to patches/server-remapped/0384-Add-option-to-disable-pillager-patrols.patch diff --git a/patches/server-remapped/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/patches/server-remapped/0385-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch similarity index 100% rename from patches/server-remapped/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch rename to patches/server-remapped/0385-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch diff --git a/patches/server-remapped/0384-PlayerLaunchProjectileEvent.patch b/patches/server-remapped/0386-PlayerLaunchProjectileEvent.patch similarity index 100% rename from patches/server-remapped/0384-PlayerLaunchProjectileEvent.patch rename to patches/server-remapped/0386-PlayerLaunchProjectileEvent.patch diff --git a/patches/server-remapped/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch b/patches/server-remapped/0387-Add-CraftMagicNumbers.isSupportedApiVersion.patch similarity index 100% rename from patches/server-remapped/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch rename to patches/server-remapped/0387-Add-CraftMagicNumbers.isSupportedApiVersion.patch diff --git a/patches/server-remapped/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/patches/server-remapped/0388-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch similarity index 100% rename from patches/server-remapped/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch rename to patches/server-remapped/0388-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch diff --git a/patches/server-remapped/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch b/patches/server-remapped/0389-MC-145656-Fix-Follow-Range-Initial-Target.patch similarity index 100% rename from patches/server-remapped/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch rename to patches/server-remapped/0389-MC-145656-Fix-Follow-Range-Initial-Target.patch diff --git a/patches/server-remapped/0388-Optimize-Hoppers.patch b/patches/server-remapped/0390-Optimize-Hoppers.patch similarity index 100% rename from patches/server-remapped/0388-Optimize-Hoppers.patch rename to patches/server-remapped/0390-Optimize-Hoppers.patch diff --git a/patches/server-remapped/0389-PlayerDeathEvent-shouldDropExperience.patch b/patches/server-remapped/0391-PlayerDeathEvent-shouldDropExperience.patch similarity index 100% rename from patches/server-remapped/0389-PlayerDeathEvent-shouldDropExperience.patch rename to patches/server-remapped/0391-PlayerDeathEvent-shouldDropExperience.patch diff --git a/patches/server-remapped/0390-Prevent-bees-loading-chunks-checking-hive-position.patch b/patches/server-remapped/0392-Prevent-bees-loading-chunks-checking-hive-position.patch similarity index 100% rename from patches/server-remapped/0390-Prevent-bees-loading-chunks-checking-hive-position.patch rename to patches/server-remapped/0392-Prevent-bees-loading-chunks-checking-hive-position.patch diff --git a/patches/server-remapped/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/patches/server-remapped/0393-Don-t-load-Chunks-from-Hoppers-and-other-things.patch similarity index 100% rename from patches/server-remapped/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch rename to patches/server-remapped/0393-Don-t-load-Chunks-from-Hoppers-and-other-things.patch diff --git a/patches/server-remapped/0392-Guard-against-serializing-mismatching-chunk-coordina.patch b/patches/server-remapped/0394-Guard-against-serializing-mismatching-chunk-coordina.patch similarity index 100% rename from patches/server-remapped/0392-Guard-against-serializing-mismatching-chunk-coordina.patch rename to patches/server-remapped/0394-Guard-against-serializing-mismatching-chunk-coordina.patch diff --git a/patches/server-remapped/0393-Optimise-IEntityAccess-getPlayerByUUID.patch b/patches/server-remapped/0395-Optimise-IEntityAccess-getPlayerByUUID.patch similarity index 100% rename from patches/server-remapped/0393-Optimise-IEntityAccess-getPlayerByUUID.patch rename to patches/server-remapped/0395-Optimise-IEntityAccess-getPlayerByUUID.patch diff --git a/patches/server-remapped/0394-Fix-items-not-falling-correctly.patch b/patches/server-remapped/0396-Fix-items-not-falling-correctly.patch similarity index 100% rename from patches/server-remapped/0394-Fix-items-not-falling-correctly.patch rename to patches/server-remapped/0396-Fix-items-not-falling-correctly.patch diff --git a/patches/server-remapped/0395-Lag-compensate-eating.patch b/patches/server-remapped/0397-Lag-compensate-eating.patch similarity index 100% rename from patches/server-remapped/0395-Lag-compensate-eating.patch rename to patches/server-remapped/0397-Lag-compensate-eating.patch diff --git a/patches/server-remapped/0396-Optimize-call-to-getFluid-for-explosions.patch b/patches/server-remapped/0398-Optimize-call-to-getFluid-for-explosions.patch similarity index 100% rename from patches/server-remapped/0396-Optimize-call-to-getFluid-for-explosions.patch rename to patches/server-remapped/0398-Optimize-call-to-getFluid-for-explosions.patch diff --git a/patches/server-remapped/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch b/patches/server-remapped/0399-Fix-last-firework-in-stack-not-having-effects-when-d.patch similarity index 100% rename from patches/server-remapped/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch rename to patches/server-remapped/0399-Fix-last-firework-in-stack-not-having-effects-when-d.patch diff --git a/patches/server-remapped/0398-Add-effect-to-block-break-naturally.patch b/patches/server-remapped/0400-Add-effect-to-block-break-naturally.patch similarity index 100% rename from patches/server-remapped/0398-Add-effect-to-block-break-naturally.patch rename to patches/server-remapped/0400-Add-effect-to-block-break-naturally.patch diff --git a/patches/server-remapped/0399-Tracking-Range-Improvements.patch b/patches/server-remapped/0401-Tracking-Range-Improvements.patch similarity index 100% rename from patches/server-remapped/0399-Tracking-Range-Improvements.patch rename to patches/server-remapped/0401-Tracking-Range-Improvements.patch diff --git a/patches/server-remapped/0400-Entity-Activation-Range-2.0.patch b/patches/server-remapped/0402-Entity-Activation-Range-2.0.patch similarity index 100% rename from patches/server-remapped/0400-Entity-Activation-Range-2.0.patch rename to patches/server-remapped/0402-Entity-Activation-Range-2.0.patch diff --git a/patches/server-remapped/0401-Fix-items-vanishing-through-end-portal.patch b/patches/server-remapped/0403-Fix-items-vanishing-through-end-portal.patch similarity index 100% rename from patches/server-remapped/0401-Fix-items-vanishing-through-end-portal.patch rename to patches/server-remapped/0403-Fix-items-vanishing-through-end-portal.patch diff --git a/patches/server-remapped/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server-remapped/0404-Bees-get-gravity-in-void.-Fixes-MC-167279.patch similarity index 100% rename from patches/server-remapped/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch rename to patches/server-remapped/0404-Bees-get-gravity-in-void.-Fixes-MC-167279.patch diff --git a/patches/server-remapped/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server-remapped/0405-Optimise-getChunkAt-calls-for-loaded-chunks.patch similarity index 100% rename from patches/server-remapped/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch rename to patches/server-remapped/0405-Optimise-getChunkAt-calls-for-loaded-chunks.patch diff --git a/patches/server-remapped/0404-Allow-overriding-the-java-version-check.patch b/patches/server-remapped/0406-Allow-overriding-the-java-version-check.patch similarity index 100% rename from patches/server-remapped/0404-Allow-overriding-the-java-version-check.patch rename to patches/server-remapped/0406-Allow-overriding-the-java-version-check.patch diff --git a/patches/server-remapped/0405-Add-ThrownEggHatchEvent.patch b/patches/server-remapped/0407-Add-ThrownEggHatchEvent.patch similarity index 100% rename from patches/server-remapped/0405-Add-ThrownEggHatchEvent.patch rename to patches/server-remapped/0407-Add-ThrownEggHatchEvent.patch diff --git a/patches/server-remapped/0406-Optimise-random-block-ticking.patch b/patches/server-remapped/0408-Optimise-random-block-ticking.patch similarity index 100% rename from patches/server-remapped/0406-Optimise-random-block-ticking.patch rename to patches/server-remapped/0408-Optimise-random-block-ticking.patch diff --git a/patches/server-remapped/0407-Entity-Jump-API.patch b/patches/server-remapped/0409-Entity-Jump-API.patch similarity index 100% rename from patches/server-remapped/0407-Entity-Jump-API.patch rename to patches/server-remapped/0409-Entity-Jump-API.patch diff --git a/patches/server-remapped/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server-remapped/0410-Add-option-to-nerf-pigmen-from-nether-portals.patch similarity index 100% rename from patches/server-remapped/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch rename to patches/server-remapped/0410-Add-option-to-nerf-pigmen-from-nether-portals.patch diff --git a/patches/server-remapped/0409-Make-the-GUI-graph-fancier.patch b/patches/server-remapped/0411-Make-the-GUI-graph-fancier.patch similarity index 100% rename from patches/server-remapped/0409-Make-the-GUI-graph-fancier.patch rename to patches/server-remapped/0411-Make-the-GUI-graph-fancier.patch diff --git a/patches/server-remapped/0410-add-hand-to-BlockMultiPlaceEvent.patch b/patches/server-remapped/0412-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from patches/server-remapped/0410-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/server-remapped/0412-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/patches/server-remapped/0411-Prevent-teleporting-dead-entities.patch b/patches/server-remapped/0413-Prevent-teleporting-dead-entities.patch similarity index 100% rename from patches/server-remapped/0411-Prevent-teleporting-dead-entities.patch rename to patches/server-remapped/0413-Prevent-teleporting-dead-entities.patch diff --git a/patches/server-remapped/0412-Validate-tripwire-hook-placement-before-update.patch b/patches/server-remapped/0414-Validate-tripwire-hook-placement-before-update.patch similarity index 100% rename from patches/server-remapped/0412-Validate-tripwire-hook-placement-before-update.patch rename to patches/server-remapped/0414-Validate-tripwire-hook-placement-before-update.patch diff --git a/patches/server-remapped/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server-remapped/0415-Add-option-to-allow-iron-golems-to-spawn-in-air.patch similarity index 100% rename from patches/server-remapped/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch rename to patches/server-remapped/0415-Add-option-to-allow-iron-golems-to-spawn-in-air.patch diff --git a/patches/server-remapped/0414-Configurable-chance-of-villager-zombie-infection.patch b/patches/server-remapped/0416-Configurable-chance-of-villager-zombie-infection.patch similarity index 100% rename from patches/server-remapped/0414-Configurable-chance-of-villager-zombie-infection.patch rename to patches/server-remapped/0416-Configurable-chance-of-villager-zombie-infection.patch diff --git a/patches/server-remapped/0415-Optimise-Chunk-getFluid.patch b/patches/server-remapped/0417-Optimise-Chunk-getFluid.patch similarity index 100% rename from patches/server-remapped/0415-Optimise-Chunk-getFluid.patch rename to patches/server-remapped/0417-Optimise-Chunk-getFluid.patch diff --git a/patches/server-remapped/0416-Optimise-TickListServer-by-rewriting-it.patch b/patches/server-remapped/0418-Optimise-TickListServer-by-rewriting-it.patch similarity index 100% rename from patches/server-remapped/0416-Optimise-TickListServer-by-rewriting-it.patch rename to patches/server-remapped/0418-Optimise-TickListServer-by-rewriting-it.patch diff --git a/patches/server-remapped/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server-remapped/0419-Pillager-patrol-spawn-settings-and-per-player-option.patch similarity index 100% rename from patches/server-remapped/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch rename to patches/server-remapped/0419-Pillager-patrol-spawn-settings-and-per-player-option.patch diff --git a/patches/server-remapped/0418-Ensure-Entity-is-never-double-registered.patch b/patches/server-remapped/0420-Ensure-Entity-is-never-double-registered.patch similarity index 100% rename from patches/server-remapped/0418-Ensure-Entity-is-never-double-registered.patch rename to patches/server-remapped/0420-Ensure-Entity-is-never-double-registered.patch diff --git a/patches/server-remapped/0419-Fix-unregistering-entities-from-unloading-chunks.patch b/patches/server-remapped/0421-Fix-unregistering-entities-from-unloading-chunks.patch similarity index 100% rename from patches/server-remapped/0419-Fix-unregistering-entities-from-unloading-chunks.patch rename to patches/server-remapped/0421-Fix-unregistering-entities-from-unloading-chunks.patch diff --git a/patches/server-remapped/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server-remapped/0422-Remote-Connections-shouldn-t-hold-up-shutdown.patch similarity index 100% rename from patches/server-remapped/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch rename to patches/server-remapped/0422-Remote-Connections-shouldn-t-hold-up-shutdown.patch diff --git a/patches/server-remapped/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server-remapped/0423-Do-not-allow-bees-to-load-chunks-for-beehives.patch similarity index 100% rename from patches/server-remapped/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch rename to patches/server-remapped/0423-Do-not-allow-bees-to-load-chunks-for-beehives.patch diff --git a/patches/server-remapped/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server-remapped/0424-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch similarity index 100% rename from patches/server-remapped/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch rename to patches/server-remapped/0424-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch diff --git a/patches/server-remapped/0423-Optimize-Collision-to-not-load-chunks.patch b/patches/server-remapped/0425-Optimize-Collision-to-not-load-chunks.patch similarity index 100% rename from patches/server-remapped/0423-Optimize-Collision-to-not-load-chunks.patch rename to patches/server-remapped/0425-Optimize-Collision-to-not-load-chunks.patch diff --git a/patches/server-remapped/0424-Don-t-tick-dead-players.patch b/patches/server-remapped/0426-Don-t-tick-dead-players.patch similarity index 100% rename from patches/server-remapped/0424-Don-t-tick-dead-players.patch rename to patches/server-remapped/0426-Don-t-tick-dead-players.patch diff --git a/patches/server-remapped/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server-remapped/0427-Dead-Player-s-shouldn-t-be-able-to-move.patch similarity index 100% rename from patches/server-remapped/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch rename to patches/server-remapped/0427-Dead-Player-s-shouldn-t-be-able-to-move.patch diff --git a/patches/server-remapped/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server-remapped/0428-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch similarity index 100% rename from patches/server-remapped/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch rename to patches/server-remapped/0428-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch diff --git a/patches/server-remapped/0427-Increase-Light-Queue-Size.patch b/patches/server-remapped/0429-Increase-Light-Queue-Size.patch similarity index 100% rename from patches/server-remapped/0427-Increase-Light-Queue-Size.patch rename to patches/server-remapped/0429-Increase-Light-Queue-Size.patch diff --git a/patches/server-remapped/0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/patches/server-remapped/0430-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch similarity index 100% rename from patches/server-remapped/0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch rename to patches/server-remapped/0430-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch diff --git a/patches/server-remapped/0429-Don-t-move-existing-players-to-world-spawn.patch b/patches/server-remapped/0431-Don-t-move-existing-players-to-world-spawn.patch similarity index 100% rename from patches/server-remapped/0429-Don-t-move-existing-players-to-world-spawn.patch rename to patches/server-remapped/0431-Don-t-move-existing-players-to-world-spawn.patch diff --git a/patches/server-remapped/0430-Add-tick-times-API-and-mspt-command.patch b/patches/server-remapped/0432-Add-tick-times-API-and-mspt-command.patch similarity index 100% rename from patches/server-remapped/0430-Add-tick-times-API-and-mspt-command.patch rename to patches/server-remapped/0432-Add-tick-times-API-and-mspt-command.patch diff --git a/patches/server-remapped/0431-Expose-MinecraftServer-isRunning.patch b/patches/server-remapped/0433-Expose-MinecraftServer-isRunning.patch similarity index 100% rename from patches/server-remapped/0431-Expose-MinecraftServer-isRunning.patch rename to patches/server-remapped/0433-Expose-MinecraftServer-isRunning.patch diff --git a/patches/server-remapped/0432-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server-remapped/0434-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 100% rename from patches/server-remapped/0432-Add-Raw-Byte-ItemStack-Serialization.patch rename to patches/server-remapped/0434-Add-Raw-Byte-ItemStack-Serialization.patch diff --git a/patches/server-remapped/0433-Remove-streams-from-Mob-AI-System.patch b/patches/server-remapped/0435-Remove-streams-from-Mob-AI-System.patch similarity index 100% rename from patches/server-remapped/0433-Remove-streams-from-Mob-AI-System.patch rename to patches/server-remapped/0435-Remove-streams-from-Mob-AI-System.patch diff --git a/patches/server-remapped/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch b/patches/server-remapped/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch similarity index 100% rename from patches/server-remapped/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch rename to patches/server-remapped/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch diff --git a/patches/server-remapped/0435-Async-command-map-building.patch b/patches/server-remapped/0437-Async-command-map-building.patch similarity index 100% rename from patches/server-remapped/0435-Async-command-map-building.patch rename to patches/server-remapped/0437-Async-command-map-building.patch diff --git a/patches/server-remapped/0436-Improved-Watchdog-Support.patch b/patches/server-remapped/0438-Improved-Watchdog-Support.patch similarity index 100% rename from patches/server-remapped/0436-Improved-Watchdog-Support.patch rename to patches/server-remapped/0438-Improved-Watchdog-Support.patch diff --git a/patches/server-remapped/0437-Optimize-Pathfinding.patch b/patches/server-remapped/0439-Optimize-Pathfinding.patch similarity index 100% rename from patches/server-remapped/0437-Optimize-Pathfinding.patch rename to patches/server-remapped/0439-Optimize-Pathfinding.patch diff --git a/patches/server-remapped/0438-Reduce-Either-Optional-allocation.patch b/patches/server-remapped/0440-Reduce-Either-Optional-allocation.patch similarity index 100% rename from patches/server-remapped/0438-Reduce-Either-Optional-allocation.patch rename to patches/server-remapped/0440-Reduce-Either-Optional-allocation.patch diff --git a/patches/server-remapped/0439-Remove-streams-from-PairedQueue.patch b/patches/server-remapped/0441-Remove-streams-from-PairedQueue.patch similarity index 100% rename from patches/server-remapped/0439-Remove-streams-from-PairedQueue.patch rename to patches/server-remapped/0441-Remove-streams-from-PairedQueue.patch diff --git a/patches/server-remapped/0440-Reduce-memory-footprint-of-NBTTagCompound.patch b/patches/server-remapped/0442-Reduce-memory-footprint-of-NBTTagCompound.patch similarity index 100% rename from patches/server-remapped/0440-Reduce-memory-footprint-of-NBTTagCompound.patch rename to patches/server-remapped/0442-Reduce-memory-footprint-of-NBTTagCompound.patch diff --git a/patches/server-remapped/0441-Prevent-opening-inventories-when-frozen.patch b/patches/server-remapped/0443-Prevent-opening-inventories-when-frozen.patch similarity index 100% rename from patches/server-remapped/0441-Prevent-opening-inventories-when-frozen.patch rename to patches/server-remapped/0443-Prevent-opening-inventories-when-frozen.patch diff --git a/patches/server-remapped/0442-Optimise-ArraySetSorted-removeIf.patch b/patches/server-remapped/0444-Optimise-ArraySetSorted-removeIf.patch similarity index 100% rename from patches/server-remapped/0442-Optimise-ArraySetSorted-removeIf.patch rename to patches/server-remapped/0444-Optimise-ArraySetSorted-removeIf.patch diff --git a/patches/server-remapped/0443-Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server-remapped/0445-Don-t-run-entity-collision-code-if-not-needed.patch similarity index 100% rename from patches/server-remapped/0443-Don-t-run-entity-collision-code-if-not-needed.patch rename to patches/server-remapped/0445-Don-t-run-entity-collision-code-if-not-needed.patch diff --git a/patches/server-remapped/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch b/patches/server-remapped/0446-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch similarity index 100% rename from patches/server-remapped/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch rename to patches/server-remapped/0446-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch diff --git a/patches/server-remapped/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch b/patches/server-remapped/0447-Restrict-vanilla-teleport-command-to-valid-locations.patch similarity index 100% rename from patches/server-remapped/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch rename to patches/server-remapped/0447-Restrict-vanilla-teleport-command-to-valid-locations.patch diff --git a/patches/server-remapped/0446-Implement-Player-Client-Options-API.patch b/patches/server-remapped/0448-Implement-Player-Client-Options-API.patch similarity index 100% rename from patches/server-remapped/0446-Implement-Player-Client-Options-API.patch rename to patches/server-remapped/0448-Implement-Player-Client-Options-API.patch diff --git a/patches/server-remapped/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server-remapped/0449-Fix-Chunk-Post-Processing-deadlock-risk.patch similarity index 100% rename from patches/server-remapped/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch rename to patches/server-remapped/0449-Fix-Chunk-Post-Processing-deadlock-risk.patch diff --git a/patches/server-remapped/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/patches/server-remapped/0450-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch similarity index 100% rename from patches/server-remapped/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch rename to patches/server-remapped/0450-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch diff --git a/patches/server-remapped/0449-Broadcast-join-message-to-console.patch b/patches/server-remapped/0451-Broadcast-join-message-to-console.patch similarity index 100% rename from patches/server-remapped/0449-Broadcast-join-message-to-console.patch rename to patches/server-remapped/0451-Broadcast-join-message-to-console.patch diff --git a/patches/server-remapped/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/patches/server-remapped/0452-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch similarity index 100% rename from patches/server-remapped/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch rename to patches/server-remapped/0452-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch diff --git a/patches/server-remapped/0451-Load-Chunks-for-Login-Asynchronously.patch b/patches/server-remapped/0453-Load-Chunks-for-Login-Asynchronously.patch similarity index 100% rename from patches/server-remapped/0451-Load-Chunks-for-Login-Asynchronously.patch rename to patches/server-remapped/0453-Load-Chunks-for-Login-Asynchronously.patch diff --git a/patches/server-remapped/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/patches/server-remapped/0454-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch similarity index 100% rename from patches/server-remapped/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch rename to patches/server-remapped/0454-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch diff --git a/patches/server-remapped/0453-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server-remapped/0455-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from patches/server-remapped/0453-Add-PlayerAttackEntityCooldownResetEvent.patch rename to patches/server-remapped/0455-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/patches/server-remapped/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/patches/server-remapped/0456-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch similarity index 100% rename from patches/server-remapped/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch rename to patches/server-remapped/0456-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch diff --git a/patches/server-remapped/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch b/patches/server-remapped/0457-Don-t-fire-BlockFade-on-worldgen-threads.patch similarity index 100% rename from patches/server-remapped/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch rename to patches/server-remapped/0457-Don-t-fire-BlockFade-on-worldgen-threads.patch diff --git a/patches/server-remapped/0456-Add-phantom-creative-and-insomniac-controls.patch b/patches/server-remapped/0458-Add-phantom-creative-and-insomniac-controls.patch similarity index 100% rename from patches/server-remapped/0456-Add-phantom-creative-and-insomniac-controls.patch rename to patches/server-remapped/0458-Add-phantom-creative-and-insomniac-controls.patch diff --git a/patches/server-remapped/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/patches/server-remapped/0459-Fix-numerous-item-duplication-issues-and-teleport-is.patch similarity index 100% rename from patches/server-remapped/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch rename to patches/server-remapped/0459-Fix-numerous-item-duplication-issues-and-teleport-is.patch diff --git a/patches/server-remapped/0458-Implement-Brigadier-Mojang-API.patch b/patches/server-remapped/0460-Implement-Brigadier-Mojang-API.patch similarity index 100% rename from patches/server-remapped/0458-Implement-Brigadier-Mojang-API.patch rename to patches/server-remapped/0460-Implement-Brigadier-Mojang-API.patch diff --git a/patches/server-remapped/0459-Villager-Restocks-API.patch b/patches/server-remapped/0461-Villager-Restocks-API.patch similarity index 100% rename from patches/server-remapped/0459-Villager-Restocks-API.patch rename to patches/server-remapped/0461-Villager-Restocks-API.patch diff --git a/patches/server-remapped/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch b/patches/server-remapped/0462-Validate-PickItem-Packet-and-kick-for-invalid.patch similarity index 100% rename from patches/server-remapped/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch rename to patches/server-remapped/0462-Validate-PickItem-Packet-and-kick-for-invalid.patch diff --git a/patches/server-remapped/0461-Expose-game-version.patch b/patches/server-remapped/0463-Expose-game-version.patch similarity index 100% rename from patches/server-remapped/0461-Expose-game-version.patch rename to patches/server-remapped/0463-Expose-game-version.patch diff --git a/patches/server-remapped/0462-Optimize-Voxel-Shape-Merging.patch b/patches/server-remapped/0464-Optimize-Voxel-Shape-Merging.patch similarity index 100% rename from patches/server-remapped/0462-Optimize-Voxel-Shape-Merging.patch rename to patches/server-remapped/0464-Optimize-Voxel-Shape-Merging.patch diff --git a/patches/server-remapped/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/patches/server-remapped/0465-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch similarity index 100% rename from patches/server-remapped/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch rename to patches/server-remapped/0465-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch diff --git a/patches/server-remapped/0464-Implement-Mob-Goal-API.patch b/patches/server-remapped/0466-Implement-Mob-Goal-API.patch similarity index 100% rename from patches/server-remapped/0464-Implement-Mob-Goal-API.patch rename to patches/server-remapped/0466-Implement-Mob-Goal-API.patch diff --git a/patches/server-remapped/0465-Use-distance-map-to-optimise-entity-tracker.patch b/patches/server-remapped/0467-Use-distance-map-to-optimise-entity-tracker.patch similarity index 100% rename from patches/server-remapped/0465-Use-distance-map-to-optimise-entity-tracker.patch rename to patches/server-remapped/0467-Use-distance-map-to-optimise-entity-tracker.patch diff --git a/patches/server-remapped/0466-Optimize-isOutsideRange-to-use-distance-maps.patch b/patches/server-remapped/0468-Optimize-isOutsideRange-to-use-distance-maps.patch similarity index 100% rename from patches/server-remapped/0466-Optimize-isOutsideRange-to-use-distance-maps.patch rename to patches/server-remapped/0468-Optimize-isOutsideRange-to-use-distance-maps.patch diff --git a/patches/server-remapped/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch b/patches/server-remapped/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch similarity index 100% rename from patches/server-remapped/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch rename to patches/server-remapped/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch diff --git a/patches/server-remapped/0468-No-Tick-view-distance-implementation.patch b/patches/server-remapped/0470-No-Tick-view-distance-implementation.patch similarity index 100% rename from patches/server-remapped/0468-No-Tick-view-distance-implementation.patch rename to patches/server-remapped/0470-No-Tick-view-distance-implementation.patch diff --git a/patches/server-remapped/0469-Add-villager-reputation-API.patch b/patches/server-remapped/0471-Add-villager-reputation-API.patch similarity index 100% rename from patches/server-remapped/0469-Add-villager-reputation-API.patch rename to patches/server-remapped/0471-Add-villager-reputation-API.patch diff --git a/patches/server-remapped/0470-Fix-Light-Command.patch b/patches/server-remapped/0472-Fix-Light-Command.patch similarity index 100% rename from patches/server-remapped/0470-Fix-Light-Command.patch rename to patches/server-remapped/0472-Fix-Light-Command.patch diff --git a/patches/server-remapped/0471-Fix-PotionEffect-ignores-icon-flag.patch b/patches/server-remapped/0473-Fix-PotionEffect-ignores-icon-flag.patch similarity index 100% rename from patches/server-remapped/0471-Fix-PotionEffect-ignores-icon-flag.patch rename to patches/server-remapped/0473-Fix-PotionEffect-ignores-icon-flag.patch diff --git a/patches/server-remapped/0472-Optimize-brigadier-child-sorting-performance.patch b/patches/server-remapped/0474-Optimize-brigadier-child-sorting-performance.patch similarity index 100% rename from patches/server-remapped/0472-Optimize-brigadier-child-sorting-performance.patch rename to patches/server-remapped/0474-Optimize-brigadier-child-sorting-performance.patch diff --git a/patches/server-remapped/0473-Potential-bed-API.patch b/patches/server-remapped/0475-Potential-bed-API.patch similarity index 100% rename from patches/server-remapped/0473-Potential-bed-API.patch rename to patches/server-remapped/0475-Potential-bed-API.patch diff --git a/patches/server-remapped/0474-Wait-for-Async-Tasks-during-shutdown.patch b/patches/server-remapped/0476-Wait-for-Async-Tasks-during-shutdown.patch similarity index 100% rename from patches/server-remapped/0474-Wait-for-Async-Tasks-during-shutdown.patch rename to patches/server-remapped/0476-Wait-for-Async-Tasks-during-shutdown.patch diff --git a/patches/server-remapped/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/patches/server-remapped/0477-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch similarity index 100% rename from patches/server-remapped/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch rename to patches/server-remapped/0477-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch diff --git a/patches/server-remapped/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server-remapped/0478-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch similarity index 100% rename from patches/server-remapped/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch rename to patches/server-remapped/0478-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch diff --git a/patches/server-remapped/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch b/patches/server-remapped/0479-Optimize-NibbleArray-to-use-pooled-buffers.patch similarity index 100% rename from patches/server-remapped/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch rename to patches/server-remapped/0479-Optimize-NibbleArray-to-use-pooled-buffers.patch diff --git a/patches/server-remapped/0478-Reduce-MutableInt-allocations-from-light-engine.patch b/patches/server-remapped/0480-Reduce-MutableInt-allocations-from-light-engine.patch similarity index 100% rename from patches/server-remapped/0478-Reduce-MutableInt-allocations-from-light-engine.patch rename to patches/server-remapped/0480-Reduce-MutableInt-allocations-from-light-engine.patch diff --git a/patches/server-remapped/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/patches/server-remapped/0481-Reduce-allocation-of-Vec3D-by-entity-tracker.patch similarity index 100% rename from patches/server-remapped/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch rename to patches/server-remapped/0481-Reduce-allocation-of-Vec3D-by-entity-tracker.patch diff --git a/patches/server-remapped/0480-Ensure-safe-gateway-teleport.patch b/patches/server-remapped/0482-Ensure-safe-gateway-teleport.patch similarity index 100% rename from patches/server-remapped/0480-Ensure-safe-gateway-teleport.patch rename to patches/server-remapped/0482-Ensure-safe-gateway-teleport.patch diff --git a/patches/server-remapped/0481-Add-option-for-console-having-all-permissions.patch b/patches/server-remapped/0483-Add-option-for-console-having-all-permissions.patch similarity index 100% rename from patches/server-remapped/0481-Add-option-for-console-having-all-permissions.patch rename to patches/server-remapped/0483-Add-option-for-console-having-all-permissions.patch diff --git a/patches/server-remapped/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/patches/server-remapped/0484-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch similarity index 100% rename from patches/server-remapped/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch rename to patches/server-remapped/0484-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch diff --git a/patches/server-remapped/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch b/patches/server-remapped/0485-Workaround-for-Client-Lag-Spikes-MC-162253.patch similarity index 100% rename from patches/server-remapped/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch rename to patches/server-remapped/0485-Workaround-for-Client-Lag-Spikes-MC-162253.patch diff --git a/patches/server-remapped/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server-remapped/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch similarity index 100% rename from patches/server-remapped/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch rename to patches/server-remapped/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch diff --git a/patches/server-remapped/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/patches/server-remapped/0487-Optimize-sending-packets-to-nearby-locations-sounds-.patch similarity index 100% rename from patches/server-remapped/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch rename to patches/server-remapped/0487-Optimize-sending-packets-to-nearby-locations-sounds-.patch diff --git a/patches/server-remapped/0486-Improve-Chunk-Status-Transition-Speed.patch b/patches/server-remapped/0488-Improve-Chunk-Status-Transition-Speed.patch similarity index 100% rename from patches/server-remapped/0486-Improve-Chunk-Status-Transition-Speed.patch rename to patches/server-remapped/0488-Improve-Chunk-Status-Transition-Speed.patch diff --git a/patches/server-remapped/0487-Fix-villager-trading-demand-MC-163962.patch b/patches/server-remapped/0489-Fix-villager-trading-demand-MC-163962.patch similarity index 100% rename from patches/server-remapped/0487-Fix-villager-trading-demand-MC-163962.patch rename to patches/server-remapped/0489-Fix-villager-trading-demand-MC-163962.patch diff --git a/patches/server-remapped/0488-Maps-shouldn-t-load-chunks.patch b/patches/server-remapped/0490-Maps-shouldn-t-load-chunks.patch similarity index 100% rename from patches/server-remapped/0488-Maps-shouldn-t-load-chunks.patch rename to patches/server-remapped/0490-Maps-shouldn-t-load-chunks.patch diff --git a/patches/server-remapped/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/patches/server-remapped/0491-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch similarity index 100% rename from patches/server-remapped/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch rename to patches/server-remapped/0491-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch diff --git a/patches/server-remapped/0490-Optimize-Bit-Operations-by-inlining.patch b/patches/server-remapped/0492-Optimize-Bit-Operations-by-inlining.patch similarity index 100% rename from patches/server-remapped/0490-Optimize-Bit-Operations-by-inlining.patch rename to patches/server-remapped/0492-Optimize-Bit-Operations-by-inlining.patch diff --git a/patches/server-remapped/0491-Optimize-Light-Engine.patch b/patches/server-remapped/0493-Optimize-Light-Engine.patch similarity index 100% rename from patches/server-remapped/0491-Optimize-Light-Engine.patch rename to patches/server-remapped/0493-Optimize-Light-Engine.patch diff --git a/patches/server-remapped/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/patches/server-remapped/0494-Delay-Chunk-Unloads-based-on-Player-Movement.patch similarity index 100% rename from patches/server-remapped/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch rename to patches/server-remapped/0494-Delay-Chunk-Unloads-based-on-Player-Movement.patch diff --git a/patches/server-remapped/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/patches/server-remapped/0495-Add-Plugin-Tickets-to-API-Chunk-Methods.patch similarity index 100% rename from patches/server-remapped/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch rename to patches/server-remapped/0495-Add-Plugin-Tickets-to-API-Chunk-Methods.patch diff --git a/patches/server-remapped/0494-Fix-missing-chunks-due-to-integer-overflow.patch b/patches/server-remapped/0496-Fix-missing-chunks-due-to-integer-overflow.patch similarity index 100% rename from patches/server-remapped/0494-Fix-missing-chunks-due-to-integer-overflow.patch rename to patches/server-remapped/0496-Fix-missing-chunks-due-to-integer-overflow.patch diff --git a/patches/server-remapped/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/patches/server-remapped/0497-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch similarity index 100% rename from patches/server-remapped/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch rename to patches/server-remapped/0497-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch diff --git a/patches/server-remapped/0496-Fix-piston-physics-inconsistency-MC-188840.patch b/patches/server-remapped/0498-Fix-piston-physics-inconsistency-MC-188840.patch similarity index 100% rename from patches/server-remapped/0496-Fix-piston-physics-inconsistency-MC-188840.patch rename to patches/server-remapped/0498-Fix-piston-physics-inconsistency-MC-188840.patch diff --git a/patches/server-remapped/0497-Fix-sand-duping.patch b/patches/server-remapped/0499-Fix-sand-duping.patch similarity index 100% rename from patches/server-remapped/0497-Fix-sand-duping.patch rename to patches/server-remapped/0499-Fix-sand-duping.patch diff --git a/patches/server-remapped/0498-Prevent-position-desync-in-playerconnection-causing-.patch b/patches/server-remapped/0500-Prevent-position-desync-in-playerconnection-causing-.patch similarity index 100% rename from patches/server-remapped/0498-Prevent-position-desync-in-playerconnection-causing-.patch rename to patches/server-remapped/0500-Prevent-position-desync-in-playerconnection-causing-.patch diff --git a/patches/server-remapped/0499-Fix-enderdragon-exp-dupe.patch b/patches/server-remapped/0501-Fix-enderdragon-exp-dupe.patch similarity index 100% rename from patches/server-remapped/0499-Fix-enderdragon-exp-dupe.patch rename to patches/server-remapped/0501-Fix-enderdragon-exp-dupe.patch diff --git a/patches/server-remapped/0500-Inventory-getHolder-method-without-block-snapshot.patch b/patches/server-remapped/0502-Inventory-getHolder-method-without-block-snapshot.patch similarity index 100% rename from patches/server-remapped/0500-Inventory-getHolder-method-without-block-snapshot.patch rename to patches/server-remapped/0502-Inventory-getHolder-method-without-block-snapshot.patch diff --git a/patches/server-remapped/0501-Expose-Arrow-getItemStack.patch b/patches/server-remapped/0503-Expose-Arrow-getItemStack.patch similarity index 100% rename from patches/server-remapped/0501-Expose-Arrow-getItemStack.patch rename to patches/server-remapped/0503-Expose-Arrow-getItemStack.patch diff --git a/patches/server-remapped/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/server-remapped/0504-Add-and-implement-PlayerRecipeBookClickEvent.patch similarity index 100% rename from patches/server-remapped/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch rename to patches/server-remapped/0504-Add-and-implement-PlayerRecipeBookClickEvent.patch diff --git a/patches/server-remapped/0503-Hide-sync-chunk-writes-behind-flag.patch b/patches/server-remapped/0505-Hide-sync-chunk-writes-behind-flag.patch similarity index 100% rename from patches/server-remapped/0503-Hide-sync-chunk-writes-behind-flag.patch rename to patches/server-remapped/0505-Hide-sync-chunk-writes-behind-flag.patch diff --git a/patches/server-remapped/0504-Limit-lightning-strike-effect-distance.patch b/patches/server-remapped/0506-Limit-lightning-strike-effect-distance.patch similarity index 100% rename from patches/server-remapped/0504-Limit-lightning-strike-effect-distance.patch rename to patches/server-remapped/0506-Limit-lightning-strike-effect-distance.patch diff --git a/patches/server-remapped/0505-Add-permission-for-command-blocks.patch b/patches/server-remapped/0507-Add-permission-for-command-blocks.patch similarity index 100% rename from patches/server-remapped/0505-Add-permission-for-command-blocks.patch rename to patches/server-remapped/0507-Add-permission-for-command-blocks.patch diff --git a/patches/server-remapped/0506-Ensure-Entity-AABB-s-are-never-invalid.patch b/patches/server-remapped/0508-Ensure-Entity-AABB-s-are-never-invalid.patch similarity index 100% rename from patches/server-remapped/0506-Ensure-Entity-AABB-s-are-never-invalid.patch rename to patches/server-remapped/0508-Ensure-Entity-AABB-s-are-never-invalid.patch diff --git a/patches/server-remapped/0507-Optimize-WorldBorder-collision-checks-and-air.patch b/patches/server-remapped/0509-Optimize-WorldBorder-collision-checks-and-air.patch similarity index 100% rename from patches/server-remapped/0507-Optimize-WorldBorder-collision-checks-and-air.patch rename to patches/server-remapped/0509-Optimize-WorldBorder-collision-checks-and-air.patch diff --git a/patches/server-remapped/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/patches/server-remapped/0510-Fix-Per-World-Difficulty-Remembering-Difficulty.patch similarity index 100% rename from patches/server-remapped/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch rename to patches/server-remapped/0510-Fix-Per-World-Difficulty-Remembering-Difficulty.patch diff --git a/patches/server-remapped/0509-Paper-dumpitem-command.patch b/patches/server-remapped/0511-Paper-dumpitem-command.patch similarity index 100% rename from patches/server-remapped/0509-Paper-dumpitem-command.patch rename to patches/server-remapped/0511-Paper-dumpitem-command.patch diff --git a/patches/server-remapped/0510-Don-t-allow-null-UUID-s-for-chat.patch b/patches/server-remapped/0512-Don-t-allow-null-UUID-s-for-chat.patch similarity index 100% rename from patches/server-remapped/0510-Don-t-allow-null-UUID-s-for-chat.patch rename to patches/server-remapped/0512-Don-t-allow-null-UUID-s-for-chat.patch diff --git a/patches/server-remapped/0511-Improve-Legacy-Component-serialization-size.patch b/patches/server-remapped/0513-Improve-Legacy-Component-serialization-size.patch similarity index 100% rename from patches/server-remapped/0511-Improve-Legacy-Component-serialization-size.patch rename to patches/server-remapped/0513-Improve-Legacy-Component-serialization-size.patch diff --git a/patches/server-remapped/0512-Support-old-UUID-format-for-NBT.patch b/patches/server-remapped/0514-Support-old-UUID-format-for-NBT.patch similarity index 100% rename from patches/server-remapped/0512-Support-old-UUID-format-for-NBT.patch rename to patches/server-remapped/0514-Support-old-UUID-format-for-NBT.patch diff --git a/patches/server-remapped/0513-Clean-up-duplicated-GameProfile-Properties.patch b/patches/server-remapped/0515-Clean-up-duplicated-GameProfile-Properties.patch similarity index 100% rename from patches/server-remapped/0513-Clean-up-duplicated-GameProfile-Properties.patch rename to patches/server-remapped/0515-Clean-up-duplicated-GameProfile-Properties.patch diff --git a/patches/server-remapped/0514-Convert-legacy-attributes-in-Item-Meta.patch b/patches/server-remapped/0516-Convert-legacy-attributes-in-Item-Meta.patch similarity index 100% rename from patches/server-remapped/0514-Convert-legacy-attributes-in-Item-Meta.patch rename to patches/server-remapped/0516-Convert-legacy-attributes-in-Item-Meta.patch diff --git a/patches/server-remapped/0515-Remove-some-streams-from-structures.patch b/patches/server-remapped/0517-Remove-some-streams-from-structures.patch similarity index 100% rename from patches/server-remapped/0515-Remove-some-streams-from-structures.patch rename to patches/server-remapped/0517-Remove-some-streams-from-structures.patch diff --git a/patches/server-remapped/0516-Remove-streams-from-classes-related-villager-gossip.patch b/patches/server-remapped/0518-Remove-streams-from-classes-related-villager-gossip.patch similarity index 100% rename from patches/server-remapped/0516-Remove-streams-from-classes-related-villager-gossip.patch rename to patches/server-remapped/0518-Remove-streams-from-classes-related-villager-gossip.patch diff --git a/patches/server-remapped/0517-Support-components-in-ItemMeta.patch b/patches/server-remapped/0519-Support-components-in-ItemMeta.patch similarity index 100% rename from patches/server-remapped/0517-Support-components-in-ItemMeta.patch rename to patches/server-remapped/0519-Support-components-in-ItemMeta.patch diff --git a/patches/server-remapped/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/patches/server-remapped/0520-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch similarity index 100% rename from patches/server-remapped/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch rename to patches/server-remapped/0520-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch diff --git a/patches/server-remapped/0519-Add-entity-liquid-API.patch b/patches/server-remapped/0521-Add-entity-liquid-API.patch similarity index 100% rename from patches/server-remapped/0519-Add-entity-liquid-API.patch rename to patches/server-remapped/0521-Add-entity-liquid-API.patch diff --git a/patches/server-remapped/0520-Update-itemstack-legacy-name-and-lore.patch b/patches/server-remapped/0522-Update-itemstack-legacy-name-and-lore.patch similarity index 100% rename from patches/server-remapped/0520-Update-itemstack-legacy-name-and-lore.patch rename to patches/server-remapped/0522-Update-itemstack-legacy-name-and-lore.patch diff --git a/patches/server-remapped/0521-Spawn-player-in-correct-world-on-login.patch b/patches/server-remapped/0523-Spawn-player-in-correct-world-on-login.patch similarity index 100% rename from patches/server-remapped/0521-Spawn-player-in-correct-world-on-login.patch rename to patches/server-remapped/0523-Spawn-player-in-correct-world-on-login.patch diff --git a/patches/server-remapped/0522-Add-PrepareResultEvent.patch b/patches/server-remapped/0524-Add-PrepareResultEvent.patch similarity index 100% rename from patches/server-remapped/0522-Add-PrepareResultEvent.patch rename to patches/server-remapped/0524-Add-PrepareResultEvent.patch diff --git a/patches/server-remapped/0523-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server-remapped/0525-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 100% rename from patches/server-remapped/0523-Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/server-remapped/0525-Allow-delegation-to-vanilla-chunk-gen.patch diff --git a/patches/server-remapped/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server-remapped/0526-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch similarity index 100% rename from patches/server-remapped/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch rename to patches/server-remapped/0526-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch diff --git a/patches/server-remapped/0525-Optimize-NetworkManager-Exception-Handling.patch b/patches/server-remapped/0527-Optimize-NetworkManager-Exception-Handling.patch similarity index 100% rename from patches/server-remapped/0525-Optimize-NetworkManager-Exception-Handling.patch rename to patches/server-remapped/0527-Optimize-NetworkManager-Exception-Handling.patch diff --git a/patches/server-remapped/0526-Fix-Concurrency-issue-in-WeightedList.patch b/patches/server-remapped/0528-Fix-Concurrency-issue-in-WeightedList.patch similarity index 100% rename from patches/server-remapped/0526-Fix-Concurrency-issue-in-WeightedList.patch rename to patches/server-remapped/0528-Fix-Concurrency-issue-in-WeightedList.patch diff --git a/patches/server-remapped/0527-Optimize-the-advancement-data-player-iteration-to-be.patch b/patches/server-remapped/0529-Optimize-the-advancement-data-player-iteration-to-be.patch similarity index 100% rename from patches/server-remapped/0527-Optimize-the-advancement-data-player-iteration-to-be.patch rename to patches/server-remapped/0529-Optimize-the-advancement-data-player-iteration-to-be.patch diff --git a/patches/server-remapped/0528-Fix-arrows-never-despawning-MC-125757.patch b/patches/server-remapped/0530-Fix-arrows-never-despawning-MC-125757.patch similarity index 100% rename from patches/server-remapped/0528-Fix-arrows-never-despawning-MC-125757.patch rename to patches/server-remapped/0530-Fix-arrows-never-despawning-MC-125757.patch diff --git a/patches/server-remapped/0529-Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server-remapped/0531-Thread-Safe-Vanilla-Command-permission-checking.patch similarity index 100% rename from patches/server-remapped/0529-Thread-Safe-Vanilla-Command-permission-checking.patch rename to patches/server-remapped/0531-Thread-Safe-Vanilla-Command-permission-checking.patch diff --git a/patches/server-remapped/0530-Move-range-check-for-block-placing-up.patch b/patches/server-remapped/0532-Move-range-check-for-block-placing-up.patch similarity index 100% rename from patches/server-remapped/0530-Move-range-check-for-block-placing-up.patch rename to patches/server-remapped/0532-Move-range-check-for-block-placing-up.patch diff --git a/patches/server-remapped/0531-Fix-SPIGOT-5989.patch b/patches/server-remapped/0533-Fix-SPIGOT-5989.patch similarity index 100% rename from patches/server-remapped/0531-Fix-SPIGOT-5989.patch rename to patches/server-remapped/0533-Fix-SPIGOT-5989.patch diff --git a/patches/server-remapped/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/patches/server-remapped/0534-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch similarity index 100% rename from patches/server-remapped/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch rename to patches/server-remapped/0534-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch diff --git a/patches/server-remapped/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/patches/server-remapped/0535-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch similarity index 100% rename from patches/server-remapped/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch rename to patches/server-remapped/0535-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch diff --git a/patches/server-remapped/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/patches/server-remapped/0536-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch similarity index 100% rename from patches/server-remapped/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch rename to patches/server-remapped/0536-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch diff --git a/patches/server-remapped/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/patches/server-remapped/0537-Add-missing-strikeLighting-call-to-World-spigot-stri.patch similarity index 100% rename from patches/server-remapped/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch rename to patches/server-remapped/0537-Add-missing-strikeLighting-call-to-World-spigot-stri.patch diff --git a/patches/server-remapped/0536-Fix-some-rails-connecting-improperly.patch b/patches/server-remapped/0538-Fix-some-rails-connecting-improperly.patch similarity index 100% rename from patches/server-remapped/0536-Fix-some-rails-connecting-improperly.patch rename to patches/server-remapped/0538-Fix-some-rails-connecting-improperly.patch diff --git a/patches/server-remapped/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/patches/server-remapped/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch similarity index 100% rename from patches/server-remapped/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch rename to patches/server-remapped/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch diff --git a/patches/server-remapped/0538-Incremental-player-saving.patch b/patches/server-remapped/0540-Incremental-player-saving.patch similarity index 100% rename from patches/server-remapped/0538-Incremental-player-saving.patch rename to patches/server-remapped/0540-Incremental-player-saving.patch diff --git a/patches/server-remapped/0539-Import-fastutil-classes.patch b/patches/server-remapped/0541-Import-fastutil-classes.patch similarity index 100% rename from patches/server-remapped/0539-Import-fastutil-classes.patch rename to patches/server-remapped/0541-Import-fastutil-classes.patch diff --git a/patches/server-remapped/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch b/patches/server-remapped/0542-Don-t-mark-null-chunk-sections-for-block-updates.patch similarity index 100% rename from patches/server-remapped/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch rename to patches/server-remapped/0542-Don-t-mark-null-chunk-sections-for-block-updates.patch diff --git a/patches/server-remapped/0541-Remove-armour-stand-double-add-to-world.patch b/patches/server-remapped/0543-Remove-armour-stand-double-add-to-world.patch similarity index 100% rename from patches/server-remapped/0541-Remove-armour-stand-double-add-to-world.patch rename to patches/server-remapped/0543-Remove-armour-stand-double-add-to-world.patch diff --git a/patches/server-remapped/0542-Fix-MC-187716-Use-configured-height.patch b/patches/server-remapped/0544-Fix-MC-187716-Use-configured-height.patch similarity index 100% rename from patches/server-remapped/0542-Fix-MC-187716-Use-configured-height.patch rename to patches/server-remapped/0544-Fix-MC-187716-Use-configured-height.patch diff --git a/patches/server-remapped/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/patches/server-remapped/0545-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch similarity index 100% rename from patches/server-remapped/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch rename to patches/server-remapped/0545-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch diff --git a/patches/server-remapped/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server-remapped/0546-Do-not-let-the-server-load-chunks-from-newer-version.patch similarity index 100% rename from patches/server-remapped/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch rename to patches/server-remapped/0546-Do-not-let-the-server-load-chunks-from-newer-version.patch diff --git a/patches/server-remapped/0545-Brand-support.patch b/patches/server-remapped/0547-Brand-support.patch similarity index 100% rename from patches/server-remapped/0545-Brand-support.patch rename to patches/server-remapped/0547-Brand-support.patch diff --git a/patches/server-remapped/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch b/patches/server-remapped/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch similarity index 100% rename from patches/server-remapped/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch rename to patches/server-remapped/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch diff --git a/patches/server-remapped/0547-Fix-MC-197271.patch b/patches/server-remapped/0549-Fix-MC-197271.patch similarity index 100% rename from patches/server-remapped/0547-Fix-MC-197271.patch rename to patches/server-remapped/0549-Fix-MC-197271.patch diff --git a/patches/server-remapped/0548-MC-197883-Bandaid-decode-issue.patch b/patches/server-remapped/0550-MC-197883-Bandaid-decode-issue.patch similarity index 100% rename from patches/server-remapped/0548-MC-197883-Bandaid-decode-issue.patch rename to patches/server-remapped/0550-MC-197883-Bandaid-decode-issue.patch diff --git a/patches/server-remapped/0549-Add-setMaxPlayers-API.patch b/patches/server-remapped/0551-Add-setMaxPlayers-API.patch similarity index 100% rename from patches/server-remapped/0549-Add-setMaxPlayers-API.patch rename to patches/server-remapped/0551-Add-setMaxPlayers-API.patch diff --git a/patches/server-remapped/0550-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server-remapped/0552-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from patches/server-remapped/0550-Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/server-remapped/0552-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/patches/server-remapped/0551-Don-t-require-FACING-data.patch b/patches/server-remapped/0553-Don-t-require-FACING-data.patch similarity index 100% rename from patches/server-remapped/0551-Don-t-require-FACING-data.patch rename to patches/server-remapped/0553-Don-t-require-FACING-data.patch diff --git a/patches/server-remapped/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server-remapped/0554-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch similarity index 100% rename from patches/server-remapped/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch rename to patches/server-remapped/0554-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch diff --git a/patches/server-remapped/0553-Add-moon-phase-API.patch b/patches/server-remapped/0555-Add-moon-phase-API.patch similarity index 100% rename from patches/server-remapped/0553-Add-moon-phase-API.patch rename to patches/server-remapped/0555-Add-moon-phase-API.patch diff --git a/patches/server-remapped/0554-Prevent-headless-pistons-from-being-created.patch b/patches/server-remapped/0556-Prevent-headless-pistons-from-being-created.patch similarity index 100% rename from patches/server-remapped/0554-Prevent-headless-pistons-from-being-created.patch rename to patches/server-remapped/0556-Prevent-headless-pistons-from-being-created.patch diff --git a/patches/server-remapped/0555-Add-BellRingEvent.patch b/patches/server-remapped/0557-Add-BellRingEvent.patch similarity index 100% rename from patches/server-remapped/0555-Add-BellRingEvent.patch rename to patches/server-remapped/0557-Add-BellRingEvent.patch diff --git a/patches/server-remapped/0556-Add-zombie-targets-turtle-egg-config.patch b/patches/server-remapped/0558-Add-zombie-targets-turtle-egg-config.patch similarity index 100% rename from patches/server-remapped/0556-Add-zombie-targets-turtle-egg-config.patch rename to patches/server-remapped/0558-Add-zombie-targets-turtle-egg-config.patch diff --git a/patches/server-remapped/0557-Buffer-joins-to-world.patch b/patches/server-remapped/0559-Buffer-joins-to-world.patch similarity index 100% rename from patches/server-remapped/0557-Buffer-joins-to-world.patch rename to patches/server-remapped/0559-Buffer-joins-to-world.patch diff --git a/patches/server-remapped/0558-Optimize-redstone-algorithm.patch b/patches/server-remapped/0560-Optimize-redstone-algorithm.patch similarity index 100% rename from patches/server-remapped/0558-Optimize-redstone-algorithm.patch rename to patches/server-remapped/0560-Optimize-redstone-algorithm.patch diff --git a/patches/server-remapped/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch b/patches/server-remapped/0561-Fix-hex-colors-not-working-in-some-kick-messages.patch similarity index 100% rename from patches/server-remapped/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch rename to patches/server-remapped/0561-Fix-hex-colors-not-working-in-some-kick-messages.patch diff --git a/patches/server-remapped/0560-PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server-remapped/0562-PortalCreateEvent-needs-to-know-its-entity.patch similarity index 100% rename from patches/server-remapped/0560-PortalCreateEvent-needs-to-know-its-entity.patch rename to patches/server-remapped/0562-PortalCreateEvent-needs-to-know-its-entity.patch diff --git a/patches/server-remapped/0561-Fix-CraftTeam-null-check.patch b/patches/server-remapped/0563-Fix-CraftTeam-null-check.patch similarity index 100% rename from patches/server-remapped/0561-Fix-CraftTeam-null-check.patch rename to patches/server-remapped/0563-Fix-CraftTeam-null-check.patch diff --git a/patches/server-remapped/0562-Add-more-Evoker-API.patch b/patches/server-remapped/0564-Add-more-Evoker-API.patch similarity index 100% rename from patches/server-remapped/0562-Add-more-Evoker-API.patch rename to patches/server-remapped/0564-Add-more-Evoker-API.patch diff --git a/patches/server-remapped/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/server-remapped/0565-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 100% rename from patches/server-remapped/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to patches/server-remapped/0565-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch diff --git a/patches/server-remapped/0564-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server-remapped/0566-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 100% rename from patches/server-remapped/0564-Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/server-remapped/0566-Create-HoverEvent-from-ItemStack-Entity.patch diff --git a/patches/server-remapped/0565-Cache-block-data-strings.patch b/patches/server-remapped/0567-Cache-block-data-strings.patch similarity index 100% rename from patches/server-remapped/0565-Cache-block-data-strings.patch rename to patches/server-remapped/0567-Cache-block-data-strings.patch diff --git a/patches/server-remapped/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/patches/server-remapped/0568-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch similarity index 100% rename from patches/server-remapped/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch rename to patches/server-remapped/0568-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch diff --git a/patches/server-remapped/0567-Add-additional-open-container-api-to-HumanEntity.patch b/patches/server-remapped/0569-Add-additional-open-container-api-to-HumanEntity.patch similarity index 100% rename from patches/server-remapped/0567-Add-additional-open-container-api-to-HumanEntity.patch rename to patches/server-remapped/0569-Add-additional-open-container-api-to-HumanEntity.patch diff --git a/patches/server-remapped/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/patches/server-remapped/0570-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch similarity index 100% rename from patches/server-remapped/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch rename to patches/server-remapped/0570-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch diff --git a/patches/server-remapped/0569-Extend-block-drop-capture-to-capture-all-items-added.patch b/patches/server-remapped/0571-Extend-block-drop-capture-to-capture-all-items-added.patch similarity index 100% rename from patches/server-remapped/0569-Extend-block-drop-capture-to-capture-all-items-added.patch rename to patches/server-remapped/0571-Extend-block-drop-capture-to-capture-all-items-added.patch diff --git a/patches/server-remapped/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server-remapped/0572-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch similarity index 100% rename from patches/server-remapped/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch rename to patches/server-remapped/0572-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch diff --git a/patches/server-remapped/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server-remapped/0573-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 100% rename from patches/server-remapped/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to patches/server-remapped/0573-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch diff --git a/patches/server-remapped/0572-Lazily-track-plugin-scoreboards-by-default.patch b/patches/server-remapped/0574-Lazily-track-plugin-scoreboards-by-default.patch similarity index 100% rename from patches/server-remapped/0572-Lazily-track-plugin-scoreboards-by-default.patch rename to patches/server-remapped/0574-Lazily-track-plugin-scoreboards-by-default.patch diff --git a/patches/server-remapped/0573-Entity-isTicking.patch b/patches/server-remapped/0575-Entity-isTicking.patch similarity index 100% rename from patches/server-remapped/0573-Entity-isTicking.patch rename to patches/server-remapped/0575-Entity-isTicking.patch diff --git a/patches/server-remapped/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/patches/server-remapped/0576-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch similarity index 100% rename from patches/server-remapped/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch rename to patches/server-remapped/0576-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch diff --git a/patches/server-remapped/0575-Fix-Not-a-string-Map-Conversion-spam.patch b/patches/server-remapped/0577-Fix-Not-a-string-Map-Conversion-spam.patch similarity index 100% rename from patches/server-remapped/0575-Fix-Not-a-string-Map-Conversion-spam.patch rename to patches/server-remapped/0577-Fix-Not-a-string-Map-Conversion-spam.patch diff --git a/patches/server-remapped/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/patches/server-remapped/0578-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch similarity index 100% rename from patches/server-remapped/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch rename to patches/server-remapped/0578-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch diff --git a/patches/server-remapped/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch b/patches/server-remapped/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch similarity index 100% rename from patches/server-remapped/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch rename to patches/server-remapped/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch diff --git a/patches/server-remapped/0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch b/patches/server-remapped/0580-Reset-Ender-Crystals-on-Dragon-Spawn.patch similarity index 100% rename from patches/server-remapped/0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch rename to patches/server-remapped/0580-Reset-Ender-Crystals-on-Dragon-Spawn.patch diff --git a/patches/server-remapped/0579-Fix-for-large-move-vectors-crashing-server.patch b/patches/server-remapped/0581-Fix-for-large-move-vectors-crashing-server.patch similarity index 100% rename from patches/server-remapped/0579-Fix-for-large-move-vectors-crashing-server.patch rename to patches/server-remapped/0581-Fix-for-large-move-vectors-crashing-server.patch diff --git a/patches/server-remapped/0580-Optimise-getType-calls.patch b/patches/server-remapped/0582-Optimise-getType-calls.patch similarity index 100% rename from patches/server-remapped/0580-Optimise-getType-calls.patch rename to patches/server-remapped/0582-Optimise-getType-calls.patch diff --git a/patches/server-remapped/0581-Villager-resetOffers.patch b/patches/server-remapped/0583-Villager-resetOffers.patch similarity index 100% rename from patches/server-remapped/0581-Villager-resetOffers.patch rename to patches/server-remapped/0583-Villager-resetOffers.patch diff --git a/patches/server-remapped/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/patches/server-remapped/0584-Improve-inlinig-for-some-hot-IBlockData-methods.patch similarity index 100% rename from patches/server-remapped/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch rename to patches/server-remapped/0584-Improve-inlinig-for-some-hot-IBlockData-methods.patch diff --git a/patches/server-remapped/0583-Retain-block-place-order-when-capturing-blockstates.patch b/patches/server-remapped/0585-Retain-block-place-order-when-capturing-blockstates.patch similarity index 100% rename from patches/server-remapped/0583-Retain-block-place-order-when-capturing-blockstates.patch rename to patches/server-remapped/0585-Retain-block-place-order-when-capturing-blockstates.patch diff --git a/patches/server-remapped/0584-Reduce-blockpos-allocation-from-pathfinding.patch b/patches/server-remapped/0586-Reduce-blockpos-allocation-from-pathfinding.patch similarity index 100% rename from patches/server-remapped/0584-Reduce-blockpos-allocation-from-pathfinding.patch rename to patches/server-remapped/0586-Reduce-blockpos-allocation-from-pathfinding.patch diff --git a/patches/server-remapped/0585-Fix-item-locations-dropped-from-campfires.patch b/patches/server-remapped/0587-Fix-item-locations-dropped-from-campfires.patch similarity index 100% rename from patches/server-remapped/0585-Fix-item-locations-dropped-from-campfires.patch rename to patches/server-remapped/0587-Fix-item-locations-dropped-from-campfires.patch diff --git a/patches/server-remapped/0586-Player-elytra-boost-API.patch b/patches/server-remapped/0588-Player-elytra-boost-API.patch similarity index 100% rename from patches/server-remapped/0586-Player-elytra-boost-API.patch rename to patches/server-remapped/0588-Player-elytra-boost-API.patch diff --git a/patches/server-remapped/0587-Fixed-TileEntityBell-memory-leak.patch b/patches/server-remapped/0589-Fixed-TileEntityBell-memory-leak.patch similarity index 100% rename from patches/server-remapped/0587-Fixed-TileEntityBell-memory-leak.patch rename to patches/server-remapped/0589-Fixed-TileEntityBell-memory-leak.patch diff --git a/patches/server-remapped/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/patches/server-remapped/0590-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch similarity index 100% rename from patches/server-remapped/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch rename to patches/server-remapped/0590-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch diff --git a/patches/server-remapped/0589-Add-getOfflinePlayerIfCached-String.patch b/patches/server-remapped/0591-Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from patches/server-remapped/0589-Add-getOfflinePlayerIfCached-String.patch rename to patches/server-remapped/0591-Add-getOfflinePlayerIfCached-String.patch diff --git a/patches/server-remapped/0590-Add-ignore-discounts-API.patch b/patches/server-remapped/0592-Add-ignore-discounts-API.patch similarity index 100% rename from patches/server-remapped/0590-Add-ignore-discounts-API.patch rename to patches/server-remapped/0592-Add-ignore-discounts-API.patch diff --git a/patches/server-remapped/0591-Toggle-for-removing-existing-dragon.patch b/patches/server-remapped/0593-Toggle-for-removing-existing-dragon.patch similarity index 100% rename from patches/server-remapped/0591-Toggle-for-removing-existing-dragon.patch rename to patches/server-remapped/0593-Toggle-for-removing-existing-dragon.patch diff --git a/patches/server-remapped/0592-Fix-client-lag-on-advancement-loading.patch b/patches/server-remapped/0594-Fix-client-lag-on-advancement-loading.patch similarity index 100% rename from patches/server-remapped/0592-Fix-client-lag-on-advancement-loading.patch rename to patches/server-remapped/0594-Fix-client-lag-on-advancement-loading.patch diff --git a/patches/server-remapped/0593-Item-no-age-no-player-pickup.patch b/patches/server-remapped/0595-Item-no-age-no-player-pickup.patch similarity index 100% rename from patches/server-remapped/0593-Item-no-age-no-player-pickup.patch rename to patches/server-remapped/0595-Item-no-age-no-player-pickup.patch diff --git a/patches/server-remapped/0594-Beacon-API-custom-effect-ranges.patch b/patches/server-remapped/0596-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from patches/server-remapped/0594-Beacon-API-custom-effect-ranges.patch rename to patches/server-remapped/0596-Beacon-API-custom-effect-ranges.patch diff --git a/patches/server-remapped/0595-Add-API-for-quit-reason.patch b/patches/server-remapped/0597-Add-API-for-quit-reason.patch similarity index 100% rename from patches/server-remapped/0595-Add-API-for-quit-reason.patch rename to patches/server-remapped/0597-Add-API-for-quit-reason.patch diff --git a/patches/server-remapped/0596-Seed-based-feature-search.patch b/patches/server-remapped/0598-Seed-based-feature-search.patch similarity index 100% rename from patches/server-remapped/0596-Seed-based-feature-search.patch rename to patches/server-remapped/0598-Seed-based-feature-search.patch diff --git a/patches/server-remapped/0597-Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server-remapped/0599-Add-Wandering-Trader-spawn-rate-config-options.patch similarity index 100% rename from patches/server-remapped/0597-Add-Wandering-Trader-spawn-rate-config-options.patch rename to patches/server-remapped/0599-Add-Wandering-Trader-spawn-rate-config-options.patch diff --git a/patches/server-remapped/0598-Significantly-improve-performance-of-the-end-generat.patch b/patches/server-remapped/0600-Significantly-improve-performance-of-the-end-generat.patch similarity index 100% rename from patches/server-remapped/0598-Significantly-improve-performance-of-the-end-generat.patch rename to patches/server-remapped/0600-Significantly-improve-performance-of-the-end-generat.patch diff --git a/patches/server-remapped/0599-Expose-world-spawn-angle.patch b/patches/server-remapped/0601-Expose-world-spawn-angle.patch similarity index 100% rename from patches/server-remapped/0599-Expose-world-spawn-angle.patch rename to patches/server-remapped/0601-Expose-world-spawn-angle.patch diff --git a/patches/server-remapped/0600-Add-Destroy-Speed-API.patch b/patches/server-remapped/0602-Add-Destroy-Speed-API.patch similarity index 100% rename from patches/server-remapped/0600-Add-Destroy-Speed-API.patch rename to patches/server-remapped/0602-Add-Destroy-Speed-API.patch diff --git a/patches/server-remapped/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/patches/server-remapped/0603-Fix-Player-spawnParticle-x-y-z-precision-loss.patch similarity index 100% rename from patches/server-remapped/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch rename to patches/server-remapped/0603-Fix-Player-spawnParticle-x-y-z-precision-loss.patch diff --git a/patches/server-remapped/0602-Add-LivingEntity-clearActiveItem.patch b/patches/server-remapped/0604-Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from patches/server-remapped/0602-Add-LivingEntity-clearActiveItem.patch rename to patches/server-remapped/0604-Add-LivingEntity-clearActiveItem.patch diff --git a/patches/server-remapped/0603-Add-PlayerItemCooldownEvent.patch b/patches/server-remapped/0605-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from patches/server-remapped/0603-Add-PlayerItemCooldownEvent.patch rename to patches/server-remapped/0605-Add-PlayerItemCooldownEvent.patch diff --git a/patches/server-remapped/0604-More-lightning-API.patch b/patches/server-remapped/0606-More-lightning-API.patch similarity index 100% rename from patches/server-remapped/0604-More-lightning-API.patch rename to patches/server-remapped/0606-More-lightning-API.patch diff --git a/patches/server-remapped/0605-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server-remapped/0607-Climbing-should-not-bypass-cramming-gamerule.patch similarity index 100% rename from patches/server-remapped/0605-Climbing-should-not-bypass-cramming-gamerule.patch rename to patches/server-remapped/0607-Climbing-should-not-bypass-cramming-gamerule.patch diff --git a/patches/server-remapped/0606-Added-missing-default-perms-for-commands.patch b/patches/server-remapped/0608-Added-missing-default-perms-for-commands.patch similarity index 100% rename from patches/server-remapped/0606-Added-missing-default-perms-for-commands.patch rename to patches/server-remapped/0608-Added-missing-default-perms-for-commands.patch diff --git a/patches/server-remapped/0607-Add-PlayerShearBlockEvent.patch b/patches/server-remapped/0609-Add-PlayerShearBlockEvent.patch similarity index 100% rename from patches/server-remapped/0607-Add-PlayerShearBlockEvent.patch rename to patches/server-remapped/0609-Add-PlayerShearBlockEvent.patch diff --git a/patches/server-remapped/0608-Add-warning-for-servers-not-running-on-Java-16.patch b/patches/server-remapped/0610-Add-warning-for-servers-not-running-on-Java-16.patch similarity index 100% rename from patches/server-remapped/0608-Add-warning-for-servers-not-running-on-Java-16.patch rename to patches/server-remapped/0610-Add-warning-for-servers-not-running-on-Java-16.patch diff --git a/patches/server-remapped/0609-Set-spigots-verbose-world-setting-to-false-by-def.patch b/patches/server-remapped/0611-Set-spigots-verbose-world-setting-to-false-by-def.patch similarity index 100% rename from patches/server-remapped/0609-Set-spigots-verbose-world-setting-to-false-by-def.patch rename to patches/server-remapped/0611-Set-spigots-verbose-world-setting-to-false-by-def.patch diff --git a/patches/server-remapped/0610-Fix-curing-zombie-villager-discount-exploit.patch b/patches/server-remapped/0612-Fix-curing-zombie-villager-discount-exploit.patch similarity index 100% rename from patches/server-remapped/0610-Fix-curing-zombie-villager-discount-exploit.patch rename to patches/server-remapped/0612-Fix-curing-zombie-villager-discount-exploit.patch diff --git a/patches/server-remapped/0611-Limit-recipe-packets.patch b/patches/server-remapped/0613-Limit-recipe-packets.patch similarity index 100% rename from patches/server-remapped/0611-Limit-recipe-packets.patch rename to patches/server-remapped/0613-Limit-recipe-packets.patch diff --git a/patches/server-remapped/0612-Fix-CraftSound-backwards-compatibility.patch b/patches/server-remapped/0614-Fix-CraftSound-backwards-compatibility.patch similarity index 100% rename from patches/server-remapped/0612-Fix-CraftSound-backwards-compatibility.patch rename to patches/server-remapped/0614-Fix-CraftSound-backwards-compatibility.patch diff --git a/patches/server-remapped/0613-MC-4-Fix-item-position-desync.patch b/patches/server-remapped/0615-MC-4-Fix-item-position-desync.patch similarity index 100% rename from patches/server-remapped/0613-MC-4-Fix-item-position-desync.patch rename to patches/server-remapped/0615-MC-4-Fix-item-position-desync.patch diff --git a/patches/server-remapped/0614-Player-Chunk-Load-Unload-Events.patch b/patches/server-remapped/0616-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from patches/server-remapped/0614-Player-Chunk-Load-Unload-Events.patch rename to patches/server-remapped/0616-Player-Chunk-Load-Unload-Events.patch diff --git a/patches/server-remapped/0615-Optimize-Dynamic-get-Missing-Keys.patch b/patches/server-remapped/0617-Optimize-Dynamic-get-Missing-Keys.patch similarity index 100% rename from patches/server-remapped/0615-Optimize-Dynamic-get-Missing-Keys.patch rename to patches/server-remapped/0617-Optimize-Dynamic-get-Missing-Keys.patch diff --git a/patches/server-remapped/0616-Expose-LivingEntity-hurt-direction.patch b/patches/server-remapped/0618-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from patches/server-remapped/0616-Expose-LivingEntity-hurt-direction.patch rename to patches/server-remapped/0618-Expose-LivingEntity-hurt-direction.patch diff --git a/patches/server-remapped/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server-remapped/0619-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from patches/server-remapped/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/server-remapped/0619-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/patches/server-remapped/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server-remapped/0620-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch similarity index 100% rename from patches/server-remapped/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch rename to patches/server-remapped/0620-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch diff --git a/patches/server-remapped/0619-added-PlayerTradeEvent.patch b/patches/server-remapped/0621-added-PlayerTradeEvent.patch similarity index 100% rename from patches/server-remapped/0619-added-PlayerTradeEvent.patch rename to patches/server-remapped/0621-added-PlayerTradeEvent.patch diff --git a/patches/server-remapped/0620-Implement-TargetHitEvent.patch b/patches/server-remapped/0622-Implement-TargetHitEvent.patch similarity index 100% rename from patches/server-remapped/0620-Implement-TargetHitEvent.patch rename to patches/server-remapped/0622-Implement-TargetHitEvent.patch diff --git a/patches/server-remapped/0621-Additional-Block-Material-API-s.patch b/patches/server-remapped/0623-Additional-Block-Material-API-s.patch similarity index 100% rename from patches/server-remapped/0621-Additional-Block-Material-API-s.patch rename to patches/server-remapped/0623-Additional-Block-Material-API-s.patch diff --git a/patches/server-remapped/0622-Fix-harming-potion-dupe.patch b/patches/server-remapped/0624-Fix-harming-potion-dupe.patch similarity index 100% rename from patches/server-remapped/0622-Fix-harming-potion-dupe.patch rename to patches/server-remapped/0624-Fix-harming-potion-dupe.patch diff --git a/patches/server-remapped/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/patches/server-remapped/0625-Implement-API-to-get-Material-from-Boats-and-Minecar.patch similarity index 100% rename from patches/server-remapped/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch rename to patches/server-remapped/0625-Implement-API-to-get-Material-from-Boats-and-Minecar.patch diff --git a/patches/server-remapped/0624-Optimized-tick-ready-check.patch b/patches/server-remapped/0626-Optimized-tick-ready-check.patch similarity index 100% rename from patches/server-remapped/0624-Optimized-tick-ready-check.patch rename to patches/server-remapped/0626-Optimized-tick-ready-check.patch diff --git a/patches/server-remapped/0625-Cache-burn-durations.patch b/patches/server-remapped/0627-Cache-burn-durations.patch similarity index 100% rename from patches/server-remapped/0625-Cache-burn-durations.patch rename to patches/server-remapped/0627-Cache-burn-durations.patch diff --git a/patches/server-remapped/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server-remapped/0628-Allow-disabling-mob-spawner-spawn-egg-transformation.patch similarity index 100% rename from patches/server-remapped/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch rename to patches/server-remapped/0628-Allow-disabling-mob-spawner-spawn-egg-transformation.patch diff --git a/patches/server-remapped/0627-Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server-remapped/0629-Implement-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from patches/server-remapped/0627-Implement-PlayerFlowerPotManipulateEvent.patch rename to patches/server-remapped/0629-Implement-PlayerFlowerPotManipulateEvent.patch diff --git a/patches/server-remapped/0628-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server-remapped/0630-Fix-interact-event-not-being-called-in-adventure.patch similarity index 100% rename from patches/server-remapped/0628-Fix-interact-event-not-being-called-in-adventure.patch rename to patches/server-remapped/0630-Fix-interact-event-not-being-called-in-adventure.patch diff --git a/patches/server-remapped/0629-Zombie-API-breaking-doors.patch b/patches/server-remapped/0631-Zombie-API-breaking-doors.patch similarity index 100% rename from patches/server-remapped/0629-Zombie-API-breaking-doors.patch rename to patches/server-remapped/0631-Zombie-API-breaking-doors.patch diff --git a/patches/server-remapped/0630-Fix-nerfed-slime-when-splitting.patch b/patches/server-remapped/0632-Fix-nerfed-slime-when-splitting.patch similarity index 100% rename from patches/server-remapped/0630-Fix-nerfed-slime-when-splitting.patch rename to patches/server-remapped/0632-Fix-nerfed-slime-when-splitting.patch diff --git a/patches/server-remapped/0631-Add-EntityLoadCrossbowEvent.patch b/patches/server-remapped/0633-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from patches/server-remapped/0631-Add-EntityLoadCrossbowEvent.patch rename to patches/server-remapped/0633-Add-EntityLoadCrossbowEvent.patch diff --git a/patches/server-remapped/0632-Guardian-beam-workaround.patch b/patches/server-remapped/0634-Guardian-beam-workaround.patch similarity index 100% rename from patches/server-remapped/0632-Guardian-beam-workaround.patch rename to patches/server-remapped/0634-Guardian-beam-workaround.patch diff --git a/patches/server-remapped/0633-Added-WorldGameRuleChangeEvent.patch b/patches/server-remapped/0635-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from patches/server-remapped/0633-Added-WorldGameRuleChangeEvent.patch rename to patches/server-remapped/0635-Added-WorldGameRuleChangeEvent.patch diff --git a/patches/server-remapped/0634-Added-ServerResourcesReloadedEvent.patch b/patches/server-remapped/0636-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from patches/server-remapped/0634-Added-ServerResourcesReloadedEvent.patch rename to patches/server-remapped/0636-Added-ServerResourcesReloadedEvent.patch diff --git a/patches/server-remapped/0635-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server-remapped/0637-Added-world-settings-for-mobs-picking-up-loot.patch similarity index 100% rename from patches/server-remapped/0635-Added-world-settings-for-mobs-picking-up-loot.patch rename to patches/server-remapped/0637-Added-world-settings-for-mobs-picking-up-loot.patch diff --git a/patches/server-remapped/0636-Implemented-BlockFailedDispenseEvent.patch b/patches/server-remapped/0638-Implemented-BlockFailedDispenseEvent.patch similarity index 100% rename from patches/server-remapped/0636-Implemented-BlockFailedDispenseEvent.patch rename to patches/server-remapped/0638-Implemented-BlockFailedDispenseEvent.patch diff --git a/patches/server-remapped/0637-Added-PlayerLecternPageChangeEvent.patch b/patches/server-remapped/0639-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from patches/server-remapped/0637-Added-PlayerLecternPageChangeEvent.patch rename to patches/server-remapped/0639-Added-PlayerLecternPageChangeEvent.patch diff --git a/patches/server-remapped/0638-Fire-event-on-GS4-query.patch b/patches/server-remapped/0640-Fire-event-on-GS4-query.patch similarity index 100% rename from patches/server-remapped/0638-Fire-event-on-GS4-query.patch rename to patches/server-remapped/0640-Fire-event-on-GS4-query.patch diff --git a/patches/server-remapped/0639-Added-PlayerLoomPatternSelectEvent.patch b/patches/server-remapped/0641-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from patches/server-remapped/0639-Added-PlayerLoomPatternSelectEvent.patch rename to patches/server-remapped/0641-Added-PlayerLoomPatternSelectEvent.patch diff --git a/patches/server-remapped/0640-Configurable-door-breaking-difficulty.patch b/patches/server-remapped/0642-Configurable-door-breaking-difficulty.patch similarity index 100% rename from patches/server-remapped/0640-Configurable-door-breaking-difficulty.patch rename to patches/server-remapped/0642-Configurable-door-breaking-difficulty.patch diff --git a/patches/server-remapped/0641-Empty-commands-shall-not-be-dispatched.patch b/patches/server-remapped/0643-Empty-commands-shall-not-be-dispatched.patch similarity index 100% rename from patches/server-remapped/0641-Empty-commands-shall-not-be-dispatched.patch rename to patches/server-remapped/0643-Empty-commands-shall-not-be-dispatched.patch diff --git a/patches/server-remapped/0642-Implement-API-to-expose-exact-interaction-point.patch b/patches/server-remapped/0644-Implement-API-to-expose-exact-interaction-point.patch similarity index 100% rename from patches/server-remapped/0642-Implement-API-to-expose-exact-interaction-point.patch rename to patches/server-remapped/0644-Implement-API-to-expose-exact-interaction-point.patch diff --git a/patches/server-remapped/0643-Remove-stale-POIs.patch b/patches/server-remapped/0645-Remove-stale-POIs.patch similarity index 100% rename from patches/server-remapped/0643-Remove-stale-POIs.patch rename to patches/server-remapped/0645-Remove-stale-POIs.patch diff --git a/patches/server-remapped/0644-Fix-villager-boat-exploit.patch b/patches/server-remapped/0646-Fix-villager-boat-exploit.patch similarity index 100% rename from patches/server-remapped/0644-Fix-villager-boat-exploit.patch rename to patches/server-remapped/0646-Fix-villager-boat-exploit.patch diff --git a/patches/server-remapped/0645-Entity-load-save-limit-per-chunk.patch b/patches/server-remapped/0647-Entity-load-save-limit-per-chunk.patch similarity index 100% rename from patches/server-remapped/0645-Entity-load-save-limit-per-chunk.patch rename to patches/server-remapped/0647-Entity-load-save-limit-per-chunk.patch diff --git a/patches/server-remapped/0646-Add-sendOpLevel-API.patch b/patches/server-remapped/0648-Add-sendOpLevel-API.patch similarity index 100% rename from patches/server-remapped/0646-Add-sendOpLevel-API.patch rename to patches/server-remapped/0648-Add-sendOpLevel-API.patch diff --git a/patches/server-remapped/0647-Add-StructureLocateEvent.patch b/patches/server-remapped/0649-Add-StructureLocateEvent.patch similarity index 100% rename from patches/server-remapped/0647-Add-StructureLocateEvent.patch rename to patches/server-remapped/0649-Add-StructureLocateEvent.patch diff --git a/patches/server-remapped/0648-Collision-option-for-requiring-a-player-participant.patch b/patches/server-remapped/0650-Collision-option-for-requiring-a-player-participant.patch similarity index 100% rename from patches/server-remapped/0648-Collision-option-for-requiring-a-player-participant.patch rename to patches/server-remapped/0650-Collision-option-for-requiring-a-player-participant.patch diff --git a/patches/server-remapped/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/patches/server-remapped/0651-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch similarity index 100% rename from patches/server-remapped/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch rename to patches/server-remapped/0651-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch diff --git a/patches/server-remapped/0650-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/server-remapped/0652-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from patches/server-remapped/0650-Return-chat-component-with-empty-text-instead-of-thr.patch rename to patches/server-remapped/0652-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/patches/server-remapped/0651-Make-schedule-command-per-world.patch b/patches/server-remapped/0653-Make-schedule-command-per-world.patch similarity index 100% rename from patches/server-remapped/0651-Make-schedule-command-per-world.patch rename to patches/server-remapped/0653-Make-schedule-command-per-world.patch diff --git a/patches/server-remapped/0652-Configurable-max-leash-distance.patch b/patches/server-remapped/0654-Configurable-max-leash-distance.patch similarity index 100% rename from patches/server-remapped/0652-Configurable-max-leash-distance.patch rename to patches/server-remapped/0654-Configurable-max-leash-distance.patch diff --git a/patches/server-remapped/0653-Implement-BlockPreDispenseEvent.patch b/patches/server-remapped/0655-Implement-BlockPreDispenseEvent.patch similarity index 100% rename from patches/server-remapped/0653-Implement-BlockPreDispenseEvent.patch rename to patches/server-remapped/0655-Implement-BlockPreDispenseEvent.patch diff --git a/patches/server-remapped/0654-Added-Vanilla-Entity-Tags.patch b/patches/server-remapped/0656-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from patches/server-remapped/0654-Added-Vanilla-Entity-Tags.patch rename to patches/server-remapped/0656-Added-Vanilla-Entity-Tags.patch diff --git a/patches/server-remapped/0655-added-Wither-API.patch b/patches/server-remapped/0657-added-Wither-API.patch similarity index 100% rename from patches/server-remapped/0655-added-Wither-API.patch rename to patches/server-remapped/0657-added-Wither-API.patch diff --git a/patches/server-remapped/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/patches/server-remapped/0658-Added-firing-of-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from patches/server-remapped/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch rename to patches/server-remapped/0658-Added-firing-of-PlayerChangeBeaconEffectEvent.patch diff --git a/patches/server-remapped/0657-Fix-console-spam-when-removing-chests-in-water.patch b/patches/server-remapped/0659-Fix-console-spam-when-removing-chests-in-water.patch similarity index 100% rename from patches/server-remapped/0657-Fix-console-spam-when-removing-chests-in-water.patch rename to patches/server-remapped/0659-Fix-console-spam-when-removing-chests-in-water.patch diff --git a/patches/server-remapped/0658-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server-remapped/0660-Add-toggle-for-always-placing-the-dragon-egg.patch similarity index 100% rename from patches/server-remapped/0658-Add-toggle-for-always-placing-the-dragon-egg.patch rename to patches/server-remapped/0660-Add-toggle-for-always-placing-the-dragon-egg.patch diff --git a/patches/server-remapped/0659-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server-remapped/0661-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from patches/server-remapped/0659-Added-PlayerStonecutterRecipeSelectEvent.patch rename to patches/server-remapped/0661-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/patches/server-remapped/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/server-remapped/0662-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from patches/server-remapped/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/server-remapped/0662-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/patches/server-remapped/0661-Skip-distance-map-update-when-spawning-disabled.patch b/patches/server-remapped/0663-Skip-distance-map-update-when-spawning-disabled.patch similarity index 100% rename from patches/server-remapped/0661-Skip-distance-map-update-when-spawning-disabled.patch rename to patches/server-remapped/0663-Skip-distance-map-update-when-spawning-disabled.patch diff --git a/patches/server-remapped/0662-Reset-shield-blocking-on-dimension-change.patch b/patches/server-remapped/0664-Reset-shield-blocking-on-dimension-change.patch similarity index 100% rename from patches/server-remapped/0662-Reset-shield-blocking-on-dimension-change.patch rename to patches/server-remapped/0664-Reset-shield-blocking-on-dimension-change.patch diff --git a/patches/server-remapped/0663-add-DragonEggFormEvent.patch b/patches/server-remapped/0665-add-DragonEggFormEvent.patch similarity index 100% rename from patches/server-remapped/0663-add-DragonEggFormEvent.patch rename to patches/server-remapped/0665-add-DragonEggFormEvent.patch diff --git a/patches/server-remapped/0664-EntityMoveEvent.patch b/patches/server-remapped/0666-EntityMoveEvent.patch similarity index 100% rename from patches/server-remapped/0664-EntityMoveEvent.patch rename to patches/server-remapped/0666-EntityMoveEvent.patch diff --git a/patches/server-remapped/0665-added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server-remapped/0667-added-option-to-disable-pathfinding-updates-on-block.patch similarity index 100% rename from patches/server-remapped/0665-added-option-to-disable-pathfinding-updates-on-block.patch rename to patches/server-remapped/0667-added-option-to-disable-pathfinding-updates-on-block.patch diff --git a/patches/server-remapped/0666-Inline-shift-direction-fields.patch b/patches/server-remapped/0668-Inline-shift-direction-fields.patch similarity index 100% rename from patches/server-remapped/0666-Inline-shift-direction-fields.patch rename to patches/server-remapped/0668-Inline-shift-direction-fields.patch diff --git a/patches/server-remapped/0667-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server-remapped/0669-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from patches/server-remapped/0667-Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/server-remapped/0669-Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/patches/server-remapped/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/server-remapped/0670-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from patches/server-remapped/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/server-remapped/0670-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/patches/server-remapped/0669-living-entity-allow-attribute-registration.patch b/patches/server-remapped/0671-living-entity-allow-attribute-registration.patch similarity index 100% rename from patches/server-remapped/0669-living-entity-allow-attribute-registration.patch rename to patches/server-remapped/0671-living-entity-allow-attribute-registration.patch diff --git a/patches/server-remapped/0670-fix-dead-slime-setSize-invincibility.patch b/patches/server-remapped/0672-fix-dead-slime-setSize-invincibility.patch similarity index 100% rename from patches/server-remapped/0670-fix-dead-slime-setSize-invincibility.patch rename to patches/server-remapped/0672-fix-dead-slime-setSize-invincibility.patch diff --git a/patches/server-remapped/0671-Merchant-getRecipes-should-return-an-immutable-list.patch b/patches/server-remapped/0673-Merchant-getRecipes-should-return-an-immutable-list.patch similarity index 100% rename from patches/server-remapped/0671-Merchant-getRecipes-should-return-an-immutable-list.patch rename to patches/server-remapped/0673-Merchant-getRecipes-should-return-an-immutable-list.patch diff --git a/patches/server-remapped/0672-misc-debugging-dumps.patch b/patches/server-remapped/0674-misc-debugging-dumps.patch similarity index 100% rename from patches/server-remapped/0672-misc-debugging-dumps.patch rename to patches/server-remapped/0674-misc-debugging-dumps.patch diff --git a/patches/server-remapped/0673-Add-support-for-hex-color-codes-in-console.patch b/patches/server-remapped/0675-Add-support-for-hex-color-codes-in-console.patch similarity index 100% rename from patches/server-remapped/0673-Add-support-for-hex-color-codes-in-console.patch rename to patches/server-remapped/0675-Add-support-for-hex-color-codes-in-console.patch diff --git a/patches/server-remapped/0674-Clear-SyncLoadInfo.patch b/patches/server-remapped/0676-Clear-SyncLoadInfo.patch similarity index 100% rename from patches/server-remapped/0674-Clear-SyncLoadInfo.patch rename to patches/server-remapped/0676-Clear-SyncLoadInfo.patch diff --git a/patches/server-remapped/0675-Expose-Tracked-Players.patch b/patches/server-remapped/0677-Expose-Tracked-Players.patch similarity index 100% rename from patches/server-remapped/0675-Expose-Tracked-Players.patch rename to patches/server-remapped/0677-Expose-Tracked-Players.patch diff --git a/patches/server-remapped/0676-Remove-streams-from-SensorNearest.patch b/patches/server-remapped/0678-Remove-streams-from-SensorNearest.patch similarity index 100% rename from patches/server-remapped/0676-Remove-streams-from-SensorNearest.patch rename to patches/server-remapped/0678-Remove-streams-from-SensorNearest.patch diff --git a/patches/server-remapped/0677-do-not-create-unnecessary-copies-of-passenger-list.patch b/patches/server-remapped/0679-do-not-create-unnecessary-copies-of-passenger-list.patch similarity index 100% rename from patches/server-remapped/0677-do-not-create-unnecessary-copies-of-passenger-list.patch rename to patches/server-remapped/0679-do-not-create-unnecessary-copies-of-passenger-list.patch diff --git a/patches/server-remapped/0678-MC-29274-Fix-Wither-hostility-towards-players.patch b/patches/server-remapped/0680-MC-29274-Fix-Wither-hostility-towards-players.patch similarity index 100% rename from patches/server-remapped/0678-MC-29274-Fix-Wither-hostility-towards-players.patch rename to patches/server-remapped/0680-MC-29274-Fix-Wither-hostility-towards-players.patch diff --git a/patches/server-remapped/0679-Throw-proper-exception-on-empty-JsonList-file.patch b/patches/server-remapped/0681-Throw-proper-exception-on-empty-JsonList-file.patch similarity index 100% rename from patches/server-remapped/0679-Throw-proper-exception-on-empty-JsonList-file.patch rename to patches/server-remapped/0681-Throw-proper-exception-on-empty-JsonList-file.patch diff --git a/patches/server-remapped/0680-Improve-ServerGUI.patch b/patches/server-remapped/0682-Improve-ServerGUI.patch similarity index 100% rename from patches/server-remapped/0680-Improve-ServerGUI.patch rename to patches/server-remapped/0682-Improve-ServerGUI.patch diff --git a/patches/server-remapped/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/patches/server-remapped/0683-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch similarity index 100% rename from patches/server-remapped/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch rename to patches/server-remapped/0683-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch diff --git a/patches/server-remapped/0682-fix-converting-txt-to-json-file.patch b/patches/server-remapped/0684-fix-converting-txt-to-json-file.patch similarity index 100% rename from patches/server-remapped/0682-fix-converting-txt-to-json-file.patch rename to patches/server-remapped/0684-fix-converting-txt-to-json-file.patch diff --git a/patches/server-remapped/0683-Add-worldborder-events.patch b/patches/server-remapped/0685-Add-worldborder-events.patch similarity index 100% rename from patches/server-remapped/0683-Add-worldborder-events.patch rename to patches/server-remapped/0685-Add-worldborder-events.patch diff --git a/patches/server-remapped/0684-added-PlayerNameEntityEvent.patch b/patches/server-remapped/0686-added-PlayerNameEntityEvent.patch similarity index 100% rename from patches/server-remapped/0684-added-PlayerNameEntityEvent.patch rename to patches/server-remapped/0686-added-PlayerNameEntityEvent.patch diff --git a/patches/server-remapped/0685-Prevent-grindstones-from-overstacking-items.patch b/patches/server-remapped/0687-Prevent-grindstones-from-overstacking-items.patch similarity index 100% rename from patches/server-remapped/0685-Prevent-grindstones-from-overstacking-items.patch rename to patches/server-remapped/0687-Prevent-grindstones-from-overstacking-items.patch diff --git a/patches/server-remapped/0686-Add-recipe-to-cook-events.patch b/patches/server-remapped/0688-Add-recipe-to-cook-events.patch similarity index 100% rename from patches/server-remapped/0686-Add-recipe-to-cook-events.patch rename to patches/server-remapped/0688-Add-recipe-to-cook-events.patch diff --git a/patches/server-remapped/0687-Add-Block-isValidTool.patch b/patches/server-remapped/0689-Add-Block-isValidTool.patch similarity index 100% rename from patches/server-remapped/0687-Add-Block-isValidTool.patch rename to patches/server-remapped/0689-Add-Block-isValidTool.patch diff --git a/patches/server-remapped/0688-Allow-using-signs-inside-spawn-protection.patch b/patches/server-remapped/0690-Allow-using-signs-inside-spawn-protection.patch similarity index 100% rename from patches/server-remapped/0688-Allow-using-signs-inside-spawn-protection.patch rename to patches/server-remapped/0690-Allow-using-signs-inside-spawn-protection.patch diff --git a/patches/server-remapped/0689-Implement-Keyed-on-World.patch b/patches/server-remapped/0691-Implement-Keyed-on-World.patch similarity index 100% rename from patches/server-remapped/0689-Implement-Keyed-on-World.patch rename to patches/server-remapped/0691-Implement-Keyed-on-World.patch diff --git a/patches/server-remapped/0690-Add-fast-alternative-constructor-for-Vector3f.patch b/patches/server-remapped/0692-Add-fast-alternative-constructor-for-Vector3f.patch similarity index 100% rename from patches/server-remapped/0690-Add-fast-alternative-constructor-for-Vector3f.patch rename to patches/server-remapped/0692-Add-fast-alternative-constructor-for-Vector3f.patch diff --git a/patches/server-remapped/0691-Item-Rarity-API.patch b/patches/server-remapped/0693-Item-Rarity-API.patch similarity index 100% rename from patches/server-remapped/0691-Item-Rarity-API.patch rename to patches/server-remapped/0693-Item-Rarity-API.patch diff --git a/patches/server-remapped/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/patches/server-remapped/0694-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch similarity index 100% rename from patches/server-remapped/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch rename to patches/server-remapped/0694-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch diff --git a/patches/server-remapped/0693-copy-TESign-isEditable-from-snapshots.patch b/patches/server-remapped/0695-copy-TESign-isEditable-from-snapshots.patch similarity index 100% rename from patches/server-remapped/0693-copy-TESign-isEditable-from-snapshots.patch rename to patches/server-remapped/0695-copy-TESign-isEditable-from-snapshots.patch diff --git a/patches/server-remapped/0694-Drop-carried-item-when-player-has-disconnected.patch b/patches/server-remapped/0696-Drop-carried-item-when-player-has-disconnected.patch similarity index 100% rename from patches/server-remapped/0694-Drop-carried-item-when-player-has-disconnected.patch rename to patches/server-remapped/0696-Drop-carried-item-when-player-has-disconnected.patch diff --git a/patches/server-remapped/0695-forced-whitelist-use-configurable-kick-message.patch b/patches/server-remapped/0697-forced-whitelist-use-configurable-kick-message.patch similarity index 100% rename from patches/server-remapped/0695-forced-whitelist-use-configurable-kick-message.patch rename to patches/server-remapped/0697-forced-whitelist-use-configurable-kick-message.patch diff --git a/patches/server-remapped/0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch b/patches/server-remapped/0698-Make-sure-to-remove-correct-TE-during-TE-tick.patch similarity index 100% rename from patches/server-remapped/0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch rename to patches/server-remapped/0698-Make-sure-to-remove-correct-TE-during-TE-tick.patch diff --git a/patches/server-remapped/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/patches/server-remapped/0699-Don-t-ignore-result-of-PlayerEditBookEvent.patch similarity index 100% rename from patches/server-remapped/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch rename to patches/server-remapped/0699-Don-t-ignore-result-of-PlayerEditBookEvent.patch diff --git a/patches/server-remapped/0698-fix-cancelling-block-falling-causing-client-desync.patch b/patches/server-remapped/0700-fix-cancelling-block-falling-causing-client-desync.patch similarity index 100% rename from patches/server-remapped/0698-fix-cancelling-block-falling-causing-client-desync.patch rename to patches/server-remapped/0700-fix-cancelling-block-falling-causing-client-desync.patch diff --git a/patches/server-remapped/0699-Expose-protocol-version.patch b/patches/server-remapped/0701-Expose-protocol-version.patch similarity index 100% rename from patches/server-remapped/0699-Expose-protocol-version.patch rename to patches/server-remapped/0701-Expose-protocol-version.patch diff --git a/patches/server-remapped/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/server-remapped/0702-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 100% rename from patches/server-remapped/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to patches/server-remapped/0702-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch diff --git a/patches/server-remapped/0701-Enhance-console-tab-completions-for-brigadier-comman.patch b/patches/server-remapped/0703-Enhance-console-tab-completions-for-brigadier-comman.patch similarity index 100% rename from patches/server-remapped/0701-Enhance-console-tab-completions-for-brigadier-comman.patch rename to patches/server-remapped/0703-Enhance-console-tab-completions-for-brigadier-comman.patch diff --git a/patches/server-remapped/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/patches/server-remapped/0704-Fix-PlayerItemConsumeEvent-cancelling-properly.patch similarity index 100% rename from patches/server-remapped/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch rename to patches/server-remapped/0704-Fix-PlayerItemConsumeEvent-cancelling-properly.patch diff --git a/patches/server-remapped/0703-Add-bypass-host-check.patch b/patches/server-remapped/0705-Add-bypass-host-check.patch similarity index 100% rename from patches/server-remapped/0703-Add-bypass-host-check.patch rename to patches/server-remapped/0705-Add-bypass-host-check.patch diff --git a/patches/server-remapped/0704-don-t-throw-when-loading-invalid-TEs.patch b/patches/server-remapped/0706-don-t-throw-when-loading-invalid-TEs.patch similarity index 100% rename from patches/server-remapped/0704-don-t-throw-when-loading-invalid-TEs.patch rename to patches/server-remapped/0706-don-t-throw-when-loading-invalid-TEs.patch diff --git a/patches/server-remapped/0705-Set-area-affect-cloud-rotation.patch b/patches/server-remapped/0707-Set-area-affect-cloud-rotation.patch similarity index 100% rename from patches/server-remapped/0705-Set-area-affect-cloud-rotation.patch rename to patches/server-remapped/0707-Set-area-affect-cloud-rotation.patch diff --git a/patches/server-remapped/0706-add-isDeeplySleeping-to-HumanEntity.patch b/patches/server-remapped/0708-add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from patches/server-remapped/0706-add-isDeeplySleeping-to-HumanEntity.patch rename to patches/server-remapped/0708-add-isDeeplySleeping-to-HumanEntity.patch diff --git a/patches/server-remapped/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch b/patches/server-remapped/0709-Fix-duplicating-give-items-on-item-drop-cancel.patch similarity index 100% rename from patches/server-remapped/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch rename to patches/server-remapped/0709-Fix-duplicating-give-items-on-item-drop-cancel.patch diff --git a/patches/server-remapped/0708-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/server-remapped/0710-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from patches/server-remapped/0708-add-consumeFuel-to-FurnaceBurnEvent.patch rename to patches/server-remapped/0710-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/patches/server-remapped/0709-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/server-remapped/0711-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from patches/server-remapped/0709-add-get-set-drop-chance-to-EntityEquipment.patch rename to patches/server-remapped/0711-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/patches/server-remapped/0710-fix-PigZombieAngerEvent-cancellation.patch b/patches/server-remapped/0712-fix-PigZombieAngerEvent-cancellation.patch similarity index 100% rename from patches/server-remapped/0710-fix-PigZombieAngerEvent-cancellation.patch rename to patches/server-remapped/0712-fix-PigZombieAngerEvent-cancellation.patch diff --git a/patches/server-remapped/0711-Fix-checkReach-check-for-Shulker-boxes.patch b/patches/server-remapped/0713-Fix-checkReach-check-for-Shulker-boxes.patch similarity index 100% rename from patches/server-remapped/0711-Fix-checkReach-check-for-Shulker-boxes.patch rename to patches/server-remapped/0713-Fix-checkReach-check-for-Shulker-boxes.patch diff --git a/patches/server-remapped/0712-fix-PlayerItemHeldEvent-firing-twice.patch b/patches/server-remapped/0714-fix-PlayerItemHeldEvent-firing-twice.patch similarity index 100% rename from patches/server-remapped/0712-fix-PlayerItemHeldEvent-firing-twice.patch rename to patches/server-remapped/0714-fix-PlayerItemHeldEvent-firing-twice.patch diff --git a/patches/server-remapped/0713-Added-PlayerDeepSleepEvent.patch b/patches/server-remapped/0715-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from patches/server-remapped/0713-Added-PlayerDeepSleepEvent.patch rename to patches/server-remapped/0715-Added-PlayerDeepSleepEvent.patch diff --git a/patches/server-remapped/0714-More-World-API.patch b/patches/server-remapped/0716-More-World-API.patch similarity index 100% rename from patches/server-remapped/0714-More-World-API.patch rename to patches/server-remapped/0716-More-World-API.patch diff --git a/patches/server-remapped/0715-Added-PlayerBedFailEnterEvent.patch b/patches/server-remapped/0717-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from patches/server-remapped/0715-Added-PlayerBedFailEnterEvent.patch rename to patches/server-remapped/0717-Added-PlayerBedFailEnterEvent.patch diff --git a/patches/server-remapped/0716-Implement-methods-to-convert-between-Component-and-B.patch b/patches/server-remapped/0718-Implement-methods-to-convert-between-Component-and-B.patch similarity index 100% rename from patches/server-remapped/0716-Implement-methods-to-convert-between-Component-and-B.patch rename to patches/server-remapped/0718-Implement-methods-to-convert-between-Component-and-B.patch diff --git a/patches/server-remapped/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/patches/server-remapped/0719-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch similarity index 100% rename from patches/server-remapped/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch rename to patches/server-remapped/0719-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch diff --git a/patches/server-remapped/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/server-remapped/0720-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from patches/server-remapped/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/server-remapped/0720-add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/patches/server-remapped/0719-Introduce-beacon-activation-deactivation-events.patch b/patches/server-remapped/0721-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from patches/server-remapped/0719-Introduce-beacon-activation-deactivation-events.patch rename to patches/server-remapped/0721-Introduce-beacon-activation-deactivation-events.patch diff --git a/patches/server-remapped/0720-Add-Channel-initialization-listeners.patch b/patches/server-remapped/0722-Add-Channel-initialization-listeners.patch similarity index 100% rename from patches/server-remapped/0720-Add-Channel-initialization-listeners.patch rename to patches/server-remapped/0722-Add-Channel-initialization-listeners.patch diff --git a/patches/server-remapped/0721-Send-empty-commands-if-tab-completion-is-disabled.patch b/patches/server-remapped/0723-Send-empty-commands-if-tab-completion-is-disabled.patch similarity index 100% rename from patches/server-remapped/0721-Send-empty-commands-if-tab-completion-is-disabled.patch rename to patches/server-remapped/0723-Send-empty-commands-if-tab-completion-is-disabled.patch diff --git a/patches/server-remapped/0722-Add-more-WanderingTrader-API.patch b/patches/server-remapped/0724-Add-more-WanderingTrader-API.patch similarity index 100% rename from patches/server-remapped/0722-Add-more-WanderingTrader-API.patch rename to patches/server-remapped/0724-Add-more-WanderingTrader-API.patch diff --git a/patches/server-remapped/0723-Add-EntityBlockStorage-clearEntities.patch b/patches/server-remapped/0725-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from patches/server-remapped/0723-Add-EntityBlockStorage-clearEntities.patch rename to patches/server-remapped/0725-Add-EntityBlockStorage-clearEntities.patch diff --git a/patches/server-remapped/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/server-remapped/0726-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from patches/server-remapped/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to patches/server-remapped/0726-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/patches/server-remapped/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/server-remapped/0727-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from patches/server-remapped/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/server-remapped/0727-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/patches/server-remapped/0726-Inventory-close.patch b/patches/server-remapped/0728-Inventory-close.patch similarity index 100% rename from patches/server-remapped/0726-Inventory-close.patch rename to patches/server-remapped/0728-Inventory-close.patch diff --git a/patches/server-remapped/0727-call-PortalCreateEvent-players-and-end-platform.patch b/patches/server-remapped/0729-call-PortalCreateEvent-players-and-end-platform.patch similarity index 100% rename from patches/server-remapped/0727-call-PortalCreateEvent-players-and-end-platform.patch rename to patches/server-remapped/0729-call-PortalCreateEvent-players-and-end-platform.patch diff --git a/patches/server-remapped/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/server-remapped/0730-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 100% rename from patches/server-remapped/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/server-remapped/0730-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch diff --git a/patches/server-remapped/0729-Fix-CraftPotionBrewer-cache.patch b/patches/server-remapped/0731-Fix-CraftPotionBrewer-cache.patch similarity index 100% rename from patches/server-remapped/0729-Fix-CraftPotionBrewer-cache.patch rename to patches/server-remapped/0731-Fix-CraftPotionBrewer-cache.patch diff --git a/patches/server-remapped/0730-Add-basic-Datapack-API.patch b/patches/server-remapped/0732-Add-basic-Datapack-API.patch similarity index 100% rename from patches/server-remapped/0730-Add-basic-Datapack-API.patch rename to patches/server-remapped/0732-Add-basic-Datapack-API.patch diff --git a/patches/server-remapped/0731-Add-environment-variable-to-disable-server-gui.patch b/patches/server-remapped/0733-Add-environment-variable-to-disable-server-gui.patch similarity index 100% rename from patches/server-remapped/0731-Add-environment-variable-to-disable-server-gui.patch rename to patches/server-remapped/0733-Add-environment-variable-to-disable-server-gui.patch diff --git a/patches/server-remapped/0732-additions-to-PlayerGameModeChangeEvent.patch b/patches/server-remapped/0734-additions-to-PlayerGameModeChangeEvent.patch similarity index 100% rename from patches/server-remapped/0732-additions-to-PlayerGameModeChangeEvent.patch rename to patches/server-remapped/0734-additions-to-PlayerGameModeChangeEvent.patch diff --git a/patches/server-remapped/0733-ItemStack-repair-check-API.patch b/patches/server-remapped/0735-ItemStack-repair-check-API.patch similarity index 100% rename from patches/server-remapped/0733-ItemStack-repair-check-API.patch rename to patches/server-remapped/0735-ItemStack-repair-check-API.patch diff --git a/patches/server-remapped/0734-More-Enchantment-API.patch b/patches/server-remapped/0736-More-Enchantment-API.patch similarity index 100% rename from patches/server-remapped/0734-More-Enchantment-API.patch rename to patches/server-remapped/0736-More-Enchantment-API.patch diff --git a/patches/server-remapped/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/server-remapped/0737-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 100% rename from patches/server-remapped/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to patches/server-remapped/0737-Add-command-line-option-to-load-extra-plugin-jars-no.patch diff --git a/patches/server-remapped/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/patches/server-remapped/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch similarity index 100% rename from patches/server-remapped/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch rename to patches/server-remapped/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch diff --git a/patches/server-remapped/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch b/patches/server-remapped/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch similarity index 100% rename from patches/server-remapped/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch rename to patches/server-remapped/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch diff --git a/patches/server-remapped/0738-Fix-and-optimise-world-force-upgrading.patch b/patches/server-remapped/0740-Fix-and-optimise-world-force-upgrading.patch similarity index 100% rename from patches/server-remapped/0738-Fix-and-optimise-world-force-upgrading.patch rename to patches/server-remapped/0740-Fix-and-optimise-world-force-upgrading.patch diff --git a/patches/server-remapped/0739-Add-Mob-lookAt-API.patch b/patches/server-remapped/0741-Add-Mob-lookAt-API.patch similarity index 100% rename from patches/server-remapped/0739-Add-Mob-lookAt-API.patch rename to patches/server-remapped/0741-Add-Mob-lookAt-API.patch diff --git a/patches/server-remapped/0740-Add-Unix-domain-socket-support.patch b/patches/server-remapped/0742-Add-Unix-domain-socket-support.patch similarity index 100% rename from patches/server-remapped/0740-Add-Unix-domain-socket-support.patch rename to patches/server-remapped/0742-Add-Unix-domain-socket-support.patch diff --git a/patches/server-remapped/0741-Add-EntityInsideBlockEvent.patch b/patches/server-remapped/0743-Add-EntityInsideBlockEvent.patch similarity index 100% rename from patches/server-remapped/0741-Add-EntityInsideBlockEvent.patch rename to patches/server-remapped/0743-Add-EntityInsideBlockEvent.patch diff --git a/patches/server-remapped/0742-Attributes-API-for-item-defaults.patch b/patches/server-remapped/0744-Attributes-API-for-item-defaults.patch similarity index 100% rename from patches/server-remapped/0742-Attributes-API-for-item-defaults.patch rename to patches/server-remapped/0744-Attributes-API-for-item-defaults.patch diff --git a/patches/server-remapped/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/patches/server-remapped/0745-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch similarity index 100% rename from patches/server-remapped/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch rename to patches/server-remapped/0745-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch diff --git a/patches/server-remapped/0744-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/server-remapped/0746-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from patches/server-remapped/0744-Add-cause-to-Weather-ThunderChangeEvents.patch rename to patches/server-remapped/0746-Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/patches/server-remapped/0745-More-Lidded-Block-API.patch b/patches/server-remapped/0747-More-Lidded-Block-API.patch similarity index 100% rename from patches/server-remapped/0745-More-Lidded-Block-API.patch rename to patches/server-remapped/0747-More-Lidded-Block-API.patch diff --git a/patches/server-remapped/0746-Add-PlayerKickEvent-causes.patch b/patches/server-remapped/0748-Add-PlayerKickEvent-causes.patch similarity index 100% rename from patches/server-remapped/0746-Add-PlayerKickEvent-causes.patch rename to patches/server-remapped/0748-Add-PlayerKickEvent-causes.patch diff --git a/patches/server-remapped/0747-Limit-item-frame-cursors-on-maps.patch b/patches/server-remapped/0749-Limit-item-frame-cursors-on-maps.patch similarity index 100% rename from patches/server-remapped/0747-Limit-item-frame-cursors-on-maps.patch rename to patches/server-remapped/0749-Limit-item-frame-cursors-on-maps.patch diff --git a/patches/server-remapped/0748-Add-PufferFishStateChangeEvent.patch b/patches/server-remapped/0750-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from patches/server-remapped/0748-Add-PufferFishStateChangeEvent.patch rename to patches/server-remapped/0750-Add-PufferFishStateChangeEvent.patch diff --git a/patches/server-remapped/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/patches/server-remapped/0751-Fix-PlayerBucketEmptyEvent-result-itemstack.patch similarity index 100% rename from patches/server-remapped/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch rename to patches/server-remapped/0751-Fix-PlayerBucketEmptyEvent-result-itemstack.patch diff --git a/patches/server-remapped/0750-Add-option-to-fix-items-merging-through-walls.patch b/patches/server-remapped/0752-Add-option-to-fix-items-merging-through-walls.patch similarity index 100% rename from patches/server-remapped/0750-Add-option-to-fix-items-merging-through-walls.patch rename to patches/server-remapped/0752-Add-option-to-fix-items-merging-through-walls.patch diff --git a/patches/server-remapped/0751-Add-BellRevealRaiderEvent.patch b/patches/server-remapped/0753-Add-BellRevealRaiderEvent.patch similarity index 100% rename from patches/server-remapped/0751-Add-BellRevealRaiderEvent.patch rename to patches/server-remapped/0753-Add-BellRevealRaiderEvent.patch diff --git a/patches/server-remapped/0752-Fix-invulnerable-end-crystals.patch b/patches/server-remapped/0754-Fix-invulnerable-end-crystals.patch similarity index 100% rename from patches/server-remapped/0752-Fix-invulnerable-end-crystals.patch rename to patches/server-remapped/0754-Fix-invulnerable-end-crystals.patch diff --git a/patches/server-remapped/0753-Add-ElderGuardianAppearanceEvent.patch b/patches/server-remapped/0755-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from patches/server-remapped/0753-Add-ElderGuardianAppearanceEvent.patch rename to patches/server-remapped/0755-Add-ElderGuardianAppearanceEvent.patch diff --git a/patches/server-remapped/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch b/patches/server-remapped/0756-Reset-villager-inventory-on-cancelled-pickup-event.patch similarity index 100% rename from patches/server-remapped/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch rename to patches/server-remapped/0756-Reset-villager-inventory-on-cancelled-pickup-event.patch diff --git a/patches/server-remapped/0755-Fix-dangerous-end-portal-logic.patch b/patches/server-remapped/0757-Fix-dangerous-end-portal-logic.patch similarity index 100% rename from patches/server-remapped/0755-Fix-dangerous-end-portal-logic.patch rename to patches/server-remapped/0757-Fix-dangerous-end-portal-logic.patch diff --git a/patches/server-remapped/0756-Make-item-validations-configurable.patch b/patches/server-remapped/0758-Make-item-validations-configurable.patch similarity index 100% rename from patches/server-remapped/0756-Make-item-validations-configurable.patch rename to patches/server-remapped/0758-Make-item-validations-configurable.patch diff --git a/patches/server-remapped/0757-Add-more-line-of-sight-methods.patch b/patches/server-remapped/0759-Add-more-line-of-sight-methods.patch similarity index 100% rename from patches/server-remapped/0757-Add-more-line-of-sight-methods.patch rename to patches/server-remapped/0759-Add-more-line-of-sight-methods.patch diff --git a/patches/server-remapped/0758-add-per-world-spawn-limits.patch b/patches/server-remapped/0760-add-per-world-spawn-limits.patch similarity index 100% rename from patches/server-remapped/0758-add-per-world-spawn-limits.patch rename to patches/server-remapped/0760-add-per-world-spawn-limits.patch diff --git a/patches/server-remapped/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch b/patches/server-remapped/0761-Fix-PotionSplashEvent-for-water-splash-potions.patch similarity index 100% rename from patches/server-remapped/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch rename to patches/server-remapped/0761-Fix-PotionSplashEvent-for-water-splash-potions.patch From 132382dca35f60d63655ea956e1de5fb0ed535ba Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 17:52:05 +0200 Subject: [PATCH 012/226] More remapped patches Signed-off-by: Mariell Hoversholm --- build.gradle.kts | 3 +- .../0001-POM-changes.patch | 0 .../0002-Add-FastUtil-to-Bukkit.patch | 0 .../0003-Paper-Utils.patch | 0 ...to-current-Chunk-for-Entity-and-Bloc.patch | 0 ...ts-for-each-Entity-Block-Entity-Type.patch | 0 patches/removed/1.17/state.txt | 1 + ...setting-for-proxy-online-mode-status.patch | 1 + ...ault-permission-message-configurable.patch | 1 + .../0006-MC-Utils.patch | 918 +++++++----------- .../0007-Paper-Metrics.patch | 4 +- ...-MinecraftKey-Information-to-Objects.patch | 35 +- settings.gradle.kts | 1 + 13 files changed, 380 insertions(+), 584 deletions(-) rename patches/{api-unmapped => api}/0001-POM-changes.patch (100%) rename patches/{api-unmapped => api}/0002-Add-FastUtil-to-Bukkit.patch (100%) rename patches/{api-unmapped => api}/0003-Paper-Utils.patch (100%) rename patches/{server-remapped => removed/1.17}/0009-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch (100%) rename patches/{server-remapped => removed/1.17}/0010-Store-counts-for-each-Entity-Block-Entity-Type.patch (100%) create mode 100644 patches/removed/1.17/state.txt rename patches/{server-remapped => server}/0006-MC-Utils.patch (83%) rename patches/{server-remapped => server}/0007-Paper-Metrics.patch (99%) rename patches/{server-remapped => server}/0008-Add-MinecraftKey-Information-to-Objects.patch (80%) diff --git a/build.gradle.kts b/build.gradle.kts index d84c9ca484..4b0538ff68 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight.core") version "1.0.0-SNAPSHOT" + id("io.papermc.paperweight.core") version "1.0.0-LOCAL-SNAPSHOT" } group = "com.destroystokyo.paper" @@ -36,6 +36,7 @@ subprojects { maven("https://oss.sonatype.org/content/groups/public/") maven("https://papermc.io/repo/repository/maven-public/") maven("https://ci.emc.gs/nexus/content/groups/aikar/") + maven("https://repo.aikar.co/content/groups/aikar") maven("https://repo.md-5.net/content/repositories/releases/") maven("https://hub.spigotmc.org/nexus/content/groups/public/") } diff --git a/patches/api-unmapped/0001-POM-changes.patch b/patches/api/0001-POM-changes.patch similarity index 100% rename from patches/api-unmapped/0001-POM-changes.patch rename to patches/api/0001-POM-changes.patch diff --git a/patches/api-unmapped/0002-Add-FastUtil-to-Bukkit.patch b/patches/api/0002-Add-FastUtil-to-Bukkit.patch similarity index 100% rename from patches/api-unmapped/0002-Add-FastUtil-to-Bukkit.patch rename to patches/api/0002-Add-FastUtil-to-Bukkit.patch diff --git a/patches/api-unmapped/0003-Paper-Utils.patch b/patches/api/0003-Paper-Utils.patch similarity index 100% rename from patches/api-unmapped/0003-Paper-Utils.patch rename to patches/api/0003-Paper-Utils.patch diff --git a/patches/server-remapped/0009-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch b/patches/removed/1.17/0009-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch similarity index 100% rename from patches/server-remapped/0009-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch rename to patches/removed/1.17/0009-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch diff --git a/patches/server-remapped/0010-Store-counts-for-each-Entity-Block-Entity-Type.patch b/patches/removed/1.17/0010-Store-counts-for-each-Entity-Block-Entity-Type.patch similarity index 100% rename from patches/server-remapped/0010-Store-counts-for-each-Entity-Block-Entity-Type.patch rename to patches/removed/1.17/0010-Store-counts-for-each-Entity-Block-Entity-Type.patch diff --git a/patches/removed/1.17/state.txt b/patches/removed/1.17/state.txt new file mode 100644 index 0000000000..6b0cb60cde --- /dev/null +++ b/patches/removed/1.17/state.txt @@ -0,0 +1 @@ +Patch 10 depends on Patch 9. diff --git a/patches/server-remapped/0110-Add-setting-for-proxy-online-mode-status.patch b/patches/server-remapped/0110-Add-setting-for-proxy-online-mode-status.patch index 067e04850c..0dde210c76 100644 --- a/patches/server-remapped/0110-Add-setting-for-proxy-online-mode-status.patch +++ b/patches/server-remapped/0110-Add-setting-for-proxy-online-mode-status.patch @@ -3,6 +3,7 @@ From: Gabriele C Date: Fri, 5 Aug 2016 01:03:08 +0200 Subject: [PATCH] Add setting for proxy online mode status +TODO: Add isProxyOnlineMode check to Metrics diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java index 1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2..c52dc0346f93527965ef29a0ccdc4bf3debe302e 100644 diff --git a/patches/server-remapped/0314-Make-the-default-permission-message-configurable.patch b/patches/server-remapped/0314-Make-the-default-permission-message-configurable.patch index 8d9bfec2a6..f6e041b266 100644 --- a/patches/server-remapped/0314-Make-the-default-permission-message-configurable.patch +++ b/patches/server-remapped/0314-Make-the-default-permission-message-configurable.patch @@ -3,6 +3,7 @@ From: Shane Freeder Date: Sun, 18 Nov 2018 19:49:56 +0000 Subject: [PATCH] Make the default permission message configurable +TODO: Change the message in PaperCommand diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java index 13edb435b3fa65b4980bd7472aa5a5196f4d5b2b..469f78775b03cf363d88e35c69c0dc185c22547c 100644 diff --git a/patches/server-remapped/0006-MC-Utils.patch b/patches/server/0006-MC-Utils.patch similarity index 83% rename from patches/server-remapped/0006-MC-Utils.patch rename to patches/server/0006-MC-Utils.patch index cccd5824cd..35ee5a4ba9 100644 --- a/patches/server-remapped/0006-MC-Utils.patch +++ b/patches/server/0006-MC-Utils.patch @@ -2258,145 +2258,109 @@ index 0000000000000000000000000000000000000000..9df0006c1a283f77c4d01d9fce9062fc + } +} diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index 8c378d3f3138953b3b22b289fecdb6b40a09ab63..67fa685f4b8de3eae1431c0de399c246678b542a 100644 +index 8ba68f03c1dd87826185808e9e7080647a55c2dd..4a1c6217e7d04880f577d5d47d77f6414e775cad 100644 --- a/src/main/java/net/minecraft/Util.java +++ b/src/main/java/net/minecraft/Util.java -@@ -78,7 +78,7 @@ public class Util { +@@ -94,7 +94,7 @@ public class Util { } public static long getNanos() { -- return Util.timeSource.getAsLong(); +- return timeSource.getAsLong(); + return System.nanoTime(); // Paper } public static long getEpochMillis() { diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 88147a1f25cf2fd549412b653b8f0eb5c60bb55d..6a58059a05e16d96894b67a544c2f595d9546c78 100644 +index 3cf71f85da94bcda5d4527b5f3e18d959c6c4634..9322a516df45c4a4cb83acf8e5f6792f219ae183 100644 --- a/src/main/java/net/minecraft/core/BlockPos.java +++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -105,6 +105,7 @@ public class BlockPos extends Vec3i { - return x == 0.0D && y == 0.0D && z == 0.0D ? this : new BlockPos((double) this.getX() + x, (double) this.getY() + y, (double) this.getZ() + z); +@@ -104,6 +104,7 @@ public class BlockPos extends Vec3i { + return d == 0.0D && e == 0.0D && f == 0.0D ? this : new BlockPos((double)this.getX() + d, (double)this.getY() + e, (double)this.getZ() + f); } -+ public final BlockPos add(int i, int j, int k) {return offset(i, j, k);} // Paper - OBFHELPER - public BlockPos offset(int x, int y, int z) { - return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.getX() + x, this.getY() + y, this.getZ() + z); - } -@@ -436,6 +437,7 @@ public class BlockPos extends Vec3i { ++ @Deprecated public final BlockPos add(int i, int j, int k) {return this.offset(i, j, k);} // Paper - OBFHELPER + @Override + public BlockPos offset(int i, int j, int k) { + return i == 0 && j == 0 && k == 0 ? this : new BlockPos(this.getX() + i, this.getY() + j, this.getZ() + k); +@@ -459,6 +460,7 @@ public class BlockPos extends Vec3i { return super.rotate(rotation).immutable(); } -+ public final BlockPos.MutableBlockPos setValues(int i, int j, int k) { return set(i, j, k);} // Paper - OBFHELPER ++ @Deprecated public final BlockPos.MutableBlockPos setValues(int i, int j, int k) { return set(i, j, k);} // Paper - OBFHELPER public BlockPos.MutableBlockPos set(int x, int y, int z) { this.setX(x); this.setY(y); -@@ -443,6 +445,7 @@ public class BlockPos extends Vec3i { +@@ -466,6 +468,7 @@ public class BlockPos extends Vec3i { return this; } -+ public final BlockPos.MutableBlockPos setValues(double d0, double d1, double d2) { return set(d0, d1, d2);} // Paper - OBFHELPER ++ @Deprecated public final BlockPos.MutableBlockPos setValues(double d0, double d1, double d2) { return set(d0, d1, d2);} // Paper - OBFHELPER public BlockPos.MutableBlockPos set(double x, double y, double z) { return this.set(Mth.floor(x), Mth.floor(y), Mth.floor(z)); } -@@ -496,20 +499,21 @@ public class BlockPos extends Vec3i { +@@ -523,6 +526,7 @@ public class BlockPos extends Vec3i { } } + /* // Paper start - comment out useless overrides @Override @Override -- public void setX(int x) { -- super.setX(x); -+ public void o(int i) { -+ super.o(i); - } - - @Override -- public void setY(int y) { -- super.setY(y); -+ public void p(int i) { -+ super.p(i); - } - -- @Override -- public void setZ(int z) { -- super.setZ(z); -+ public void q(int i) { -+ super.q(i); + public BlockPos.MutableBlockPos setX(int i) { + super.setX(i); +@@ -540,6 +544,7 @@ public class BlockPos extends Vec3i { + super.setZ(i); + return this; } + */ // Paper end @Override public BlockPos immutable() { -diff --git a/src/main/java/net/minecraft/core/IdMapper.java b/src/main/java/net/minecraft/core/IdMapper.java -index 424c6cacc2e7c7b1c9d0b92fe198237033a3fcbd..e7358721e9d78bc9cbbfc3e71ce927ea4b82ce7c 100644 ---- a/src/main/java/net/minecraft/core/IdMapper.java -+++ b/src/main/java/net/minecraft/core/IdMapper.java -@@ -64,6 +64,7 @@ public class IdMapper implements IdMap { - return Iterators.filter(this.idToT.iterator(), Predicates.notNull()); - } - -+ public int size() { return this.size(); } // Paper - OBFHELPER - public int size() { - return this.tToId.size(); - } diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java -index 9bd2120bdcfe204184eb9a9e1daa5e3338665e51..3e79b274b8e0406a3cbdd94c7cec091b583109ca 100644 +index f484cf19e1ed6f4e14a6c324c59511e822335ba7..f4b5792e080d5181184eb661d005ce6cab649bf3 100644 --- a/src/main/java/net/minecraft/core/Vec3i.java +++ b/src/main/java/net/minecraft/core/Vec3i.java -@@ -18,9 +18,9 @@ public class Vec3i implements Comparable { - return IntStream.of(new int[]{baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()}); - }); - public static final Vec3i ZERO = new Vec3i(0, 0, 0); -- private int x; -- private int y; -- private int z; -+ private int x;public final void setX(final int x) { this.x = x; } // Paper - OBFHELPER -+ private int y;public final void setY(final int y) { this.y = y; } // Paper - OBFHELPER -+ private int z;public final void setZ(final int z) { this.z = z; } // Paper - OBFHELPER - - public Vec3i(int x, int y, int z) { - this.x = x; -@@ -64,15 +64,15 @@ public class Vec3i implements Comparable { +@@ -75,17 +75,17 @@ public class Vec3i implements Comparable { return this.z; } -- protected void setX(int x) { -+ public void setX(int x) { // Paper - protected -> public +- protected Vec3i setX(int x) { ++ public Vec3i setX(int x) { // Paper - protected -> public this.x = x; + return this; } -- protected void setY(int y) { -+ public void setY(int y) { // Paper - protected -> public +- protected Vec3i setY(int y) { ++ public Vec3i setY(int y) { // Paper - protected -> public this.y = y; + return this; } -- protected void setZ(int z) { -+ public void setZ(int z) { // Paper - protected -> public +- protected Vec3i setZ(int z) { ++ public Vec3i setZ(int z) { // Paper - protected -> public this.z = z; + return this; } - -@@ -108,6 +108,7 @@ public class Vec3i implements Comparable { +@@ -193,6 +193,7 @@ public class Vec3i implements Comparable { return this.distSqr(pos.x(), pos.y(), pos.z(), true) < distance * distance; } -+ public final double distanceSquared(Vec3i baseblockposition) { return distSqr(baseblockposition); } // Paper - OBFHELPER ++ @Deprecated public final double distanceSquared(Vec3i baseblockposition) { return distSqr(baseblockposition); } // Paper - OBFHELPER public double distSqr(Vec3i vec) { - return this.distSqr((double) vec.getX(), (double) vec.getY(), (double) vec.getZ(), true); + return this.distSqr((double)vec.getX(), (double)vec.getY(), (double)vec.getZ(), true); } diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java -index 077383bd9af79851351eba50e7d7ea31cc106cad..4c8f249e45e5deb7628997d4dbd9dab613ac5241 100644 +index 3d374000cd61d4a29dae21035c5ee9a93a1ff0f9..4760fc27b1d4938a248c05af17fc93ab37084c00 100644 --- a/src/main/java/net/minecraft/nbt/CompoundTag.java +++ b/src/main/java/net/minecraft/nbt/CompoundTag.java -@@ -76,7 +76,7 @@ public class CompoundTag implements Tag { +@@ -60,7 +60,7 @@ public class CompoundTag implements Tag { return "TAG_Compound"; } }; - private final Map tags; + public final Map tags; // Paper - protected CompoundTag(Map tags) { - this.tags = tags; -@@ -139,10 +139,16 @@ public class CompoundTag implements Tag { + protected CompoundTag(Map entries) { + this.tags = entries; +@@ -119,10 +119,16 @@ public class CompoundTag implements Tag { this.tags.put(key, LongTag.valueOf(value)); } @@ -2413,96 +2377,30 @@ index 077383bd9af79851351eba50e7d7ea31cc106cad..4c8f249e45e5deb7628997d4dbd9dab6 public UUID getUUID(String key) { return NbtUtils.loadUUID(this.get(key)); } -diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 8ce3a74821a0e540423a2e8e67be640b8b876035..92c5c5bbcfe364475578b6a0eddfaa85858ace8a 100644 ---- a/src/main/java/net/minecraft/network/Connection.java -+++ b/src/main/java/net/minecraft/network/Connection.java -@@ -168,6 +168,7 @@ public class Connection extends SimpleChannelInboundHandler> { - - } - -+ private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.sendPacket(packet, genericFutureListener); } // Paper - OBFHELPER - private void sendPacket(Packet packet, @Nullable GenericFutureListener> callback) { - ConnectionProtocol enumprotocol = ConnectionProtocol.getProtocolForPacket(packet); - ConnectionProtocol enumprotocol1 = (ConnectionProtocol) this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).get(); -@@ -208,6 +209,7 @@ public class Connection extends SimpleChannelInboundHandler> { - - } - -+ private void sendPacketQueue() { this.flushQueue(); } // Paper - OBFHELPER - private void flushQueue() { - if (this.channel != null && this.channel.isOpen()) { - Queue queue = this.queue; -@@ -344,9 +346,9 @@ public class Connection extends SimpleChannelInboundHandler> { - - static class PacketHolder { - -- private final Packet packet; -+ private final Packet packet; private final Packet getPacket() { return this.packet; } // Paper - OBFHELPER - @Nullable -- private final GenericFutureListener> listener; -+ private final GenericFutureListener> listener; private final GenericFutureListener> getGenericFutureListener() { return this.listener; } // Paper - OBFHELPER - - public PacketHolder(Packet packet, @Nullable GenericFutureListener> callback) { - this.packet = packet; diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -index e0dc41a8f408b7fa0b8554833ea4d09e7e604913..50f14acb062c2f90266279dbd1945a3297396f0b 100644 +index 0ae24c8080391410756f101a1e40c2eef887c739..3b8207046d38d3d14719ff6761a22e60a93628b7 100644 --- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java +++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -@@ -48,6 +48,7 @@ public class FriendlyByteBuf extends ByteBuf { - this.source = bytebuf; +@@ -68,6 +68,7 @@ public class FriendlyByteBuf extends ByteBuf { + this.source = parent; } -+ public static int countBytes(int i) { return FriendlyByteBuf.getVarIntSize(i); } // Paper - OBFHELPER - public static int getVarIntSize(int i) { ++ @Deprecated public static int countBytes(int i) { return FriendlyByteBuf.getVarIntSize(i); } // Paper - OBFHELPER + public static int getVarIntSize(int value) { for (int j = 1; j < 5; ++j) { - if ((i & -1 << j * 7) == 0) { + if ((value & -1 << j * 7) == 0) { diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index 7af36e5a889d04f6e80c80f7335bf149a4b5d224..14fa1371e52b9af5a7550a9aa144fa406b754046 100644 +index f189a72bd101a99d9350072a06953665fc5d6fee..02d253243eb66c30d4f7f6b0e7361518516eefec 100644 --- a/src/main/java/net/minecraft/network/PacketEncoder.java +++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -44,6 +44,7 @@ public class PacketEncoder extends MessageToByteEncoder> { - packet.write(packetdataserializer); - } catch (Throwable throwable) { - PacketEncoder.LOGGER.error(throwable); +@@ -46,6 +46,7 @@ public class PacketEncoder extends MessageToByteEncoder> { + } + } catch (Throwable var9) { + LOGGER.error(var9); + throwable.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? if (packet.isSkippable()) { - throw new SkipPacketException(throwable); + throw new SkipPacketException(var9); } else { -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -index bda189ab2b3b934e6bf9fd11da5d95bd9b37ba70..e5d4363edb8c494d2db69d2e0223a2db1519f64b 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -@@ -28,7 +28,7 @@ public class ClientboundLevelChunkPacket implements Packet blockEntitiesTags; - private boolean fullChunk; - -@@ -140,6 +140,7 @@ public class ClientboundLevelChunkPacket implements Packet { - -- private ItemStack book; -+ private ItemStack book; public ItemStack getBook() { return book; } // Paper - OBFHELPER - private boolean signing; - private int slot; - diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..d29fe67b7d39e368a873368a6be16042429e9209 @@ -3020,10 +2918,10 @@ index 0000000000000000000000000000000000000000..d29fe67b7d39e368a873368a6be16042 + } +} diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 37a51dee4cd37844e80fdd5c9853947201151dfc..2406879e76a110e96a4753e66366432a4bc52d9b 100644 +index ecb775edb17d629855f1be37943f9bc933d93d63..2c13b8565b606a26b305fd44cfc0bd339df8f6be 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -882,6 +882,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop CHUNK_STATUSES = ChunkStatus.getStatusList(); - private static final ChunkHolder.FullChunkStatus[] FULL_CHUNK_STATUSES = ChunkHolder.FullChunkStatus.values(); +@@ -52,9 +52,9 @@ public class ChunkHolder { + private static final int BLOCKS_BEFORE_RESEND_FUDGE = 64; private final AtomicReferenceArray>> futures; + private final LevelHeightAccessor levelHeightAccessor; - private volatile CompletableFuture> fullChunkFuture; - private volatile CompletableFuture> tickingChunkFuture; - private volatile CompletableFuture> entityTickingChunkFuture; @@ -3048,101 +2946,52 @@ index 5b460dadc12ca2018c8ed8d49555d2fa79f949d2..0b8cbf75ff01b9825141be00d63679f7 + private volatile CompletableFuture> tickingChunkFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage + private volatile CompletableFuture> entityTickingChunkFuture; private volatile boolean isEntityTickingReady; // Paper - cache chunk ticking stage private CompletableFuture chunkToSave; - public int oldTicketLevel; - private int ticketLevel; -@@ -63,6 +63,8 @@ public class ChunkHolder { - private boolean wasAccessibleSinceLastSave; + @Nullable + private final DebugBuffer chunkToSaveHistory; +@@ -73,6 +73,8 @@ public class ChunkHolder { private boolean resendLight; + private CompletableFuture pendingFullStateConfirmation; + private final ChunkMap chunkMap; // Paper + - public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; -@@ -78,10 +80,49 @@ public class ChunkHolder { - this.ticketLevel = this.oldTicketLevel; +@@ -93,14 +95,16 @@ public class ChunkHolder { this.queueLevel = this.oldTicketLevel; this.setTicketLevel(level); + this.changedBlocksPerSection = new ShortSet[world.getSectionsCount()]; + this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper -+ } -+ -+ // Paper start -+ @Nullable -+ public final LevelChunk getEntityTickingChunk() { -+ CompletableFuture> completablefuture = this.entityTickingChunkFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ @Nullable -+ public final LevelChunk getTickingChunk() { -+ CompletableFuture> completablefuture = this.tickingChunkFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ @Nullable -+ public final LevelChunk getFullReadyChunk() { -+ CompletableFuture> completablefuture = this.fullChunkFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ public final boolean isEntityTickingReady() { -+ return this.isEntityTickingReady; -+ } -+ -+ public final boolean isTickingReady() { -+ return this.isTickingReady; -+ } -+ -+ public final boolean isFullChunkReady() { -+ return this.isFullChunkReady; } -+ // Paper end // CraftBukkit start - public LevelChunk getFullChunk() { + public final LevelChunk getFullChunk() { // Paper - final for inline - if (!getFullChunkStatus(this.oldTicketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) return null; // note: using oldTicketLevel for isLoaded checks + if (!ChunkHolder.getFullChunkStatus(this.oldTicketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) return null; // note: using oldTicketLevel for isLoaded checks return this.getFullChunkUnchecked(); } -@@ -92,6 +133,14 @@ public class ChunkHolder { - return (either == null) ? null : (LevelChunk) either.left().orElse(null); - } - // CraftBukkit end -+ // Paper start - "real" get full chunk immediately -+ public final LevelChunk getFullChunkIfCached() { -+ // Note: Copied from above without ticket level check -+ CompletableFuture> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL); -+ Either either = (Either) statusFuture.getNow(null); -+ return either == null ? null : (LevelChunk) either.left().orElse(null); -+ } -+ // Paper end - public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { - CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(leastStatus.getIndex()); -@@ -103,20 +152,23 @@ public class ChunkHolder { - return getStatus(this.ticketLevel).isOrAfter(leastStatus) ? this.getFutureIfPresentUnchecked(leastStatus) : ChunkHolder.UNLOADED_CHUNK_FUTURE; ++ @Deprecated public final LevelChunk getFullChunkIfCached() { return this.getFullChunkUnchecked(); } // Paper - OBFHELPER + public LevelChunk getFullChunkUnchecked() { + CompletableFuture> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL); + Either either = (Either) statusFuture.getNow(null); +@@ -118,20 +122,22 @@ public class ChunkHolder { + return ChunkHolder.getStatus(this.ticketLevel).isOrAfter(leastStatus) ? this.getFutureIfPresentUnchecked(leastStatus) : ChunkHolder.UNLOADED_CHUNK_FUTURE; } - public CompletableFuture> getTickingChunkFuture() { -+ public final CompletableFuture> getTickingFuture() { return this.getTickingChunkFuture(); } // Paper - OBFHELPER ++ @Deprecated public final CompletableFuture> getTickingFuture() { return this.getTickingChunkFuture(); } // Paper - OBFHELPER + public final CompletableFuture> getTickingChunkFuture() { // Paper - final for inline return this.tickingChunkFuture; } - public CompletableFuture> getEntityTickingChunkFuture() { -+ public final CompletableFuture> getEntityTickingFuture() { return this.getEntityTickingChunkFuture(); } // Paper - OBFHELPER ++ @Deprecated public final CompletableFuture> getEntityTickingFuture() { return this.getEntityTickingChunkFuture(); } // Paper - OBFHELPER + public final CompletableFuture> getEntityTickingChunkFuture() { // Paper - final for inline return this.entityTickingChunkFuture; } - public CompletableFuture> getFullChunkFuture() { -+ public final CompletableFuture> getFullChunkFuture() { return this.getFullChunkFuture(); } // Paper - OBFHELPER + public final CompletableFuture> getFullChunkFuture() { // Paper - final for inline return this.fullChunkFuture; } @@ -3153,7 +3002,7 @@ index 5b460dadc12ca2018c8ed8d49555d2fa79f949d2..0b8cbf75ff01b9825141be00d63679f7 CompletableFuture> completablefuture = this.getTickingChunkFuture(); Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error -@@ -141,7 +193,7 @@ public class ChunkHolder { +@@ -170,7 +176,7 @@ public class ChunkHolder { return null; } @@ -3162,8 +3011,8 @@ index 5b460dadc12ca2018c8ed8d49555d2fa79f949d2..0b8cbf75ff01b9825141be00d63679f7 return this.chunkToSave; } -@@ -282,11 +334,11 @@ public class ChunkHolder { - }); +@@ -328,11 +334,11 @@ public class ChunkHolder { + return ChunkHolder.getFullChunkStatus(this.ticketLevel); } - public ChunkPos getPos() { @@ -3176,25 +3025,24 @@ index 5b460dadc12ca2018c8ed8d49555d2fa79f949d2..0b8cbf75ff01b9825141be00d63679f7 return this.ticketLevel; } -@@ -357,13 +409,27 @@ public class ChunkHolder { +@@ -421,14 +427,27 @@ public class ChunkHolder { this.wasAccessibleSinceLastSave |= flag3; if (!flag2 && flag3) { -- this.fullChunkFuture = chunkStorage.unpackTicks(this); ++ int expectCreateCount = ++this.fullChunkCreateCount; // Paper + this.fullChunkFuture = chunkStorage.prepareAccessibleChunk(this); + this.scheduleFullChunkPromotion(chunkStorage, this.fullChunkFuture, executor, ChunkHolder.FullChunkStatus.BORDER); + // Paper start - cache ticking ready status -+ int expectCreateCount = ++this.fullChunkCreateCount; -+ this.fullChunkFuture = chunkStorage.unpackTicks(this); this.fullChunkFuture.thenAccept((either) -> { -+ if (either.left().isPresent() && ChunkHolder.this.fullChunkCreateCount == expectCreateCount) { ++ this.fullChunkFuture.thenAccept(either -> { ++ final Optional left = either.left(); ++ if (left.isPresent() && ChunkHolder.this.fullChunkCreateCount == expectCreateCount) { + // note: Here is a very good place to add callbacks to logic waiting on this. + LevelChunk fullChunk = either.left().get(); + ChunkHolder.this.isFullChunkReady = true; + fullChunk.playerChunk = ChunkHolder.this; -+ -+ + } + }); -+ // Paper end - this.updateChunkToSave(this.fullChunkFuture); + this.updateChunkToSave(this.fullChunkFuture, "full"); } if (flag2 && !flag3) { @@ -3203,27 +3051,21 @@ index 5b460dadc12ca2018c8ed8d49555d2fa79f949d2..0b8cbf75ff01b9825141be00d63679f7 + ++this.fullChunkCreateCount; // Paper - cache ticking ready status + this.isFullChunkReady = false; // Paper - cache ticking ready status this.updateChunkToSave(((CompletableFuture>) completablefuture).thenApply((either1) -> { // CraftBukkit - decompile error - chunkStorage.getClass(); + Objects.requireNonNull(chunkStorage); return either1.ifLeft(chunkStorage::packTicks); -@@ -374,12 +440,24 @@ public class ChunkHolder { - boolean flag5 = playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.TICKING); - +@@ -441,11 +460,19 @@ public class ChunkHolder { if (!flag4 && flag5) { -- this.tickingChunkFuture = chunkStorage.postProcess(this); + this.tickingChunkFuture = chunkStorage.prepareTickingChunk(this); + this.scheduleFullChunkPromotion(chunkStorage, this.tickingChunkFuture, executor, ChunkHolder.FullChunkStatus.TICKING); + // Paper start - cache ticking ready status -+ this.tickingChunkFuture = chunkStorage.postProcess(this); this.tickingChunkFuture.thenAccept((either) -> { -+ if (either.left().isPresent()) { ++ this.tickingChunkFuture.thenAccept(either -> { ++ either.ifLeft(chunk -> { + // note: Here is a very good place to add callbacks to logic waiting on this. -+ LevelChunk tickingChunk = either.left().get(); + ChunkHolder.this.isTickingReady = true; -+ -+ -+ -+ -+ } ++ }); + }); + // Paper end - this.updateChunkToSave(this.tickingChunkFuture); + this.updateChunkToSave(this.tickingChunkFuture, "ticking"); } if (flag4 && !flag5) { @@ -3232,25 +3074,18 @@ index 5b460dadc12ca2018c8ed8d49555d2fa79f949d2..0b8cbf75ff01b9825141be00d63679f7 this.tickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; } -@@ -391,12 +469,24 @@ public class ChunkHolder { - throw (IllegalStateException) Util.pauseInIde((Throwable) (new IllegalStateException())); - } +@@ -459,11 +486,18 @@ public class ChunkHolder { -- this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); + this.entityTickingChunkFuture = chunkStorage.prepareEntityTickingChunk(this.pos); + this.scheduleFullChunkPromotion(chunkStorage, this.entityTickingChunkFuture, executor, ChunkHolder.FullChunkStatus.ENTITY_TICKING); + // Paper start - cache ticking ready status -+ this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); this.entityTickingChunkFuture.thenAccept((either) -> { -+ if (either.left().isPresent()) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ LevelChunk entityTickingChunk = either.left().get(); ++ this.entityTickingChunkFuture.thenAccept(either -> { ++ either.ifLeft(chunk -> { + ChunkHolder.this.isEntityTickingReady = true; -+ -+ -+ -+ -+ } ++ }); + }); + // Paper end - this.updateChunkToSave(this.entityTickingChunkFuture); + this.updateChunkToSave(this.entityTickingChunkFuture, "entity ticking"); } if (flag6 && !flag7) { @@ -3260,18 +3095,18 @@ index 5b460dadc12ca2018c8ed8d49555d2fa79f949d2..0b8cbf75ff01b9825141be00d63679f7 } diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index aaa56d121cdb66066e869b7cbdc2c863974d51b0..d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465 100644 +index 474d71813740f8ad61339a67bfa5bceae4331a77..cbaafa2024a36fbdaf9f753c58ca974831af9fdf 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -54,6 +54,7 @@ import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; +@@ -55,6 +55,7 @@ import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; import net.minecraft.network.protocol.game.DebugPackets; +import net.minecraft.server.MCUtil; import net.minecraft.server.level.progress.ChunkProgressListener; + import net.minecraft.server.network.ServerPlayerConnection; import net.minecraft.util.CsvOutput; - import net.minecraft.util.Mth; -@@ -144,6 +145,26 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -152,6 +153,26 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider }; // CraftBukkit end @@ -3295,11 +3130,11 @@ index aaa56d121cdb66066e869b7cbdc2c863974d51b0..d9d76d2ee43adc2b46d49f7fc3d9aef6 + } + // Paper end + - public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag); + public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { + super(new File(session.getDimensionPath(world.dimension()), "region"), dataFixer, dsync); this.visibleChunkMap = this.updatingChunkMap.clone(); -@@ -233,6 +254,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - }; +@@ -271,6 +292,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } } + // Paper start @@ -3313,7 +3148,7 @@ index aaa56d121cdb66066e869b7cbdc2c863974d51b0..d9d76d2ee43adc2b46d49f7fc3d9aef6 private CompletableFuture, ChunkHolder.ChunkLoadingFailure>> getChunkRangeFuture(ChunkPos centerChunk, int margin, IntFunction distanceToStatus) { List>> list = Lists.newArrayList(); int j = centerChunk.x; -@@ -951,6 +980,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -961,6 +990,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (!flag1) { this.distanceManager.addPlayer(SectionPos.of((Entity) player), player); } @@ -3321,7 +3156,7 @@ index aaa56d121cdb66066e869b7cbdc2c863974d51b0..d9d76d2ee43adc2b46d49f7fc3d9aef6 } else { SectionPos sectionposition = player.getLastSectionPos(); -@@ -958,6 +988,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -968,6 +998,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (!flag2) { this.distanceManager.removePlayer(sectionposition, player); } @@ -3329,7 +3164,7 @@ index aaa56d121cdb66066e869b7cbdc2c863974d51b0..d9d76d2ee43adc2b46d49f7fc3d9aef6 } for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { -@@ -1068,6 +1099,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1078,6 +1109,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } } @@ -3339,10 +3174,10 @@ index aaa56d121cdb66066e869b7cbdc2c863974d51b0..d9d76d2ee43adc2b46d49f7fc3d9aef6 @Override diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 7cc5070f70a4f740add9d971385ceaa4d44275a2..ef336645f3bd7a86129ad1dff7e1a15dc93d1e3e 100644 +index 623b938177cc7287bccc55f34e644bda984a7b65..2cc633e6d03ae37a6d0785e0a3dcc4fe9350b10a 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -42,6 +42,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana +@@ -45,6 +45,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana import net.minecraft.world.level.storage.DimensionDataStorage; import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.LevelStorageSource; @@ -3350,18 +3185,18 @@ index 7cc5070f70a4f740add9d971385ceaa4d44275a2..ef336645f3bd7a86129ad1dff7e1a15d public class ServerChunkCache extends ChunkSource { -@@ -49,7 +50,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -52,7 +53,7 @@ public class ServerChunkCache extends ChunkSource { private final DistanceManager distanceManager; public final ChunkGenerator generator; - private final ServerLevel level; -- private final Thread mainThread; -+ public final Thread mainThread; // Paper - private -> public - private final ThreadedLevelLightEngine lightEngine; + final ServerLevel level; +- final Thread mainThread; ++ public final Thread mainThread; // Paper - package-private -> public + final ThreadedLevelLightEngine lightEngine; private final ServerChunkCache.MainThreadExecutor mainThreadProcessor; public final ChunkMap chunkMap; -@@ -62,6 +63,158 @@ public class ServerChunkCache extends ChunkSource { - private final ChunkAccess[] lastChunk = new ChunkAccess[4]; +@@ -67,6 +68,158 @@ public class ServerChunkCache extends ChunkSource { @Nullable + @VisibleForDebug private NaturalSpawner.SpawnState lastSpawnState; + // Paper start + final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock(); @@ -3516,9 +3351,9 @@ index 7cc5070f70a4f740add9d971385ceaa4d44275a2..ef336645f3bd7a86129ad1dff7e1a15d + } + // Paper end - public ServerChunkCache(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldloadlistener, Supplier supplier) { - this.level = worldserver; -@@ -123,6 +276,49 @@ public class ServerChunkCache extends ChunkSource { + public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier supplier) { + this.level = world; +@@ -128,6 +281,49 @@ public class ServerChunkCache extends ChunkSource { this.lastChunk[0] = chunk; } @@ -3568,7 +3403,7 @@ index 7cc5070f70a4f740add9d971385ceaa4d44275a2..ef336645f3bd7a86129ad1dff7e1a15d @Nullable @Override public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) { -@@ -406,10 +602,9 @@ public class ServerChunkCache extends ChunkSource { +@@ -426,10 +622,9 @@ public class ServerChunkCache extends ChunkSource { this.lastSpawnState = spawnercreature_d; this.level.getProfiler().pop(); @@ -3583,74 +3418,65 @@ index 7cc5070f70a4f740add9d971385ceaa4d44275a2..ef336645f3bd7a86129ad1dff7e1a15d if (optional.isPresent()) { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 23506a8903ce64fbfe849bb94e589bdbb6e61a74..34ed8f0d348e7bc2339660ebc6490057ba9ef214 100644 +index d14e656bd77efcbb211ceb3c50465072938bdb4d..d7bf5d3bb3524410e49bd54372ddd7613ec0dd4b 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -12,6 +12,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry; - import it.unimi.dsi.fastutil.longs.LongSet; +@@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.longs.LongSet; import it.unimi.dsi.fastutil.longs.LongSets; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.ObjectIterator; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; - import java.io.BufferedWriter; -@@ -163,7 +164,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - private final Map entitiesByUuid = Maps.newHashMap(); - private final Queue toAddAfterTick = Queues.newArrayDeque(); - private final List players = Lists.newArrayList(); + import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +@@ -172,7 +173,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + private static final Logger LOGGER = LogManager.getLogger(); + private static final int EMPTY_TIME_NO_TICK = 300; + final List players; - private final ServerChunkCache chunkSource; + public final ServerChunkCache chunkSource; // Paper - public - boolean tickingEntities; private final MinecraftServer server; - public final PrimaryLevelData worldDataServer; // CraftBukkit - type -@@ -1682,7 +1683,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - ObjectIterator objectiterator = spawnercreature_d.getMobCategoryCounts().object2IntEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); -+ Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix - - bufferedwriter.write(String.format("spawn_count.%s: %d\n", ((MobCategory) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey()).getName(), it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue())); - } + public final PrimaryLevelData serverLevelData; // CraftBukkit - type + final EntityTickList entityTickList; diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index d62c74318ac3bb139570fe2b5f12cdb6e900d70d..8d7fa186b0b47688f2822038b46c33b3f32d28ae 100644 +index eb99eb7633bb9524dac43a9c075b8ea8db449232..52e536c3497a3145f8fdf47e2b6cb0b6295cd1b5 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -221,6 +221,8 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -228,6 +228,8 @@ public class ServerPlayer extends Player { public Integer clientViewDistance; // CraftBukkit end + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + - public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) { super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); - this.respawnDimension = Level.OVERWORLD; -@@ -233,6 +235,8 @@ public class ServerPlayer extends Player implements ContainerListener { + this.chatVisibility = ChatVisiblity.FULL; +@@ -295,6 +297,8 @@ public class ServerPlayer extends Player { + this.maxUpStep = 1.0F; this.fudgeSpawnLocation(world); - this.textFilter = server.createTextFilterForPlayer(this); + this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper + // CraftBukkit start this.displayName = this.getScoreboardName(); - this.canPickUpLoot = true; + this.bukkitPickUpLoot = true; diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 34dd10908101a6709e389bfa1d1c2a6599e8b102..cf3ced15c9a87e7a4dbccba17c57a7b32b77566c 100644 +index 3a4f026c73cdd22d30bdadabbcf24bef969b73e4..0d536d72ac918fbd403397ff369d10143ee9c204 100644 --- a/src/main/java/net/minecraft/server/level/TicketType.java +++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -25,6 +25,7 @@ public class TicketType { - public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); - public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit - public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit +@@ -7,6 +7,7 @@ import net.minecraft.util.Unit; + import net.minecraft.world.level.ChunkPos; + + public class TicketType { + public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper - public static TicketType create(String name, Comparator comparator) { - return new TicketType<>(name, comparator, 0L); + private final String name; + private final Comparator comparator; diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java -index 0a9f76b7aef5c12879a408954384b4e70ac5b484..fdc56d602ef0bf3c50842f3081a3e6523b9765b0 100644 +index 391bae98e542333a431fb48bf0675c0e8a1873ac..0f6b534a4c789a2f09f6c4624e5d58b99c7ed0e6 100644 --- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java +++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java -@@ -141,6 +141,26 @@ public class WorldGenRegion implements WorldGenLevel { +@@ -150,6 +150,26 @@ public class WorldGenRegion implements WorldGenLevel { return chunkX >= this.firstPos.x && chunkX <= this.lastPos.x && chunkZ >= this.firstPos.z && chunkZ <= this.lastPos.z; } @@ -3676,12 +3502,12 @@ index 0a9f76b7aef5c12879a408954384b4e70ac5b484..fdc56d602ef0bf3c50842f3081a3e652 + @Override public BlockState getBlockState(BlockPos pos) { - return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4).getBlockState(pos); + return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())).getBlockState(pos); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 8766e79c1ed7a8557ef5fd91e8f3c65c3467efcd..35f3940cebb00ee29da54b1ee148ee931fa11636 100644 +index 8d15c6aeea47d90abf67b8f89bef5aa7923fefb4..ef8e601412933c7065ce1968b45381b02b14275a 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -218,9 +218,9 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -219,9 +219,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser private final MinecraftServer server; public ServerPlayer player; private int tickCount; @@ -3692,53 +3518,33 @@ index 8766e79c1ed7a8557ef5fd91e8f3c65c3467efcd..35f3940cebb00ee29da54b1ee148ee93 + private boolean keepAlivePending; private void setPendingPing(boolean isPending) { this.keepAlivePending = isPending;}; private boolean isPendingPing() { return this.keepAlivePending;}; // Paper - OBFHELPER + private long keepAliveChallenge; private void setKeepAliveID(long keepAliveID) { this.keepAliveChallenge = keepAliveID;}; private long getKeepAliveID() {return this.keepAliveChallenge; }; // Paper - OBFHELPER // CraftBukkit start - multithreaded fields - private volatile int chatSpamTickCount; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(ServerGamePacketListenerImpl.class, "chatThrottle"); + private AtomicInteger chatSpamTickCount = new AtomicInteger(); + // CraftBukkit end diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java -index 497e23e4ebf0d8b4e1a90ea3909608cdc066265f..97bde5f8402452e59b0da94edfe1b970cdb86748 100644 +index 65bd706ca96f5c0ec4573da9fb144fb51d2de919..3a2e8bdc215a6af604bfaad01b670a361eb8068d 100644 --- a/src/main/java/net/minecraft/util/BitStorage.java +++ b/src/main/java/net/minecraft/util/BitStorage.java -@@ -84,6 +84,7 @@ public class BitStorage { - return (int) (k >> l & this.mask); +@@ -77,6 +77,7 @@ public class BitStorage { + return (int)(l >> j & this.mask); } + public final long[] getDataBits() { return this.getRaw(); } // Paper - OBFHELPER public long[] getRaw() { return this.data; } -diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -index 03831adce7905916423d8c3834c42c90f3a1ca8f..e48fcfe2e4ff151258ae1d84cc0995d2cd54e9a6 100644 ---- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -+++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -@@ -68,6 +68,15 @@ public abstract class BlockableEventLoop implements Processo - - } - -+ // Paper start -+ public void scheduleOnMain(Runnable r0) { -+ // postToMainThread does not work the same as older versions of mc -+ // This method is actually used to create a TickTask, which can then be posted onto main -+ this.addTask(this.wrapRunnable(r0)); -+ } -+ // Paper end -+ -+ public final void addTask(R r0) { tell(r0); }; // Paper - OBFHELPER - public void tell(R r0) { - this.pendingRunnables.add(r0); - LockSupport.unpark(this.getRunningThread()); diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index ff482d0349c18d0d1ba902ea0d10611b1ca4e588..102298d57cf3143092d04ab1d5d0d69b28d696ea 100644 +index 7f3d83d3d071f6b441ad119b1c93be035e911e70..89e7d02b88404ac5dce06595432ae95c9a4e5015 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -3,6 +3,7 @@ package net.minecraft.world.entity; - import com.google.common.collect.ImmutableSet; +@@ -5,6 +5,7 @@ import java.util.List; import java.util.Optional; + import java.util.Spliterator; import java.util.Set; // Paper +import java.util.Map; // Paper import java.util.UUID; + import java.util.function.Consumer; import java.util.function.Function; - import java.util.stream.Stream; -@@ -441,8 +442,8 @@ public class EntityType { +@@ -461,8 +462,8 @@ public class EntityType implements EntityTypeTest { return this.dimensions.height; } @@ -3750,29 +3556,29 @@ index ff482d0349c18d0d1ba902ea0d10611b1ca4e588..102298d57cf3143092d04ab1d5d0d69b } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 3245c0d7310285dd423c5c1d44c26fb8c3d7bf7f..9e5dde73bd65bf4e51352c628fba024c36e29ef1 100644 +index d067e2477231e145af88aa21d9173512c3a053cf..3b2b57f5049d26a14e45eb4ec88a5b498005d372 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -228,6 +228,7 @@ public abstract class LivingEntity extends Entity { +@@ -259,6 +259,7 @@ public abstract class LivingEntity extends Entity { public boolean collides = true; public Set collidableExemptions = new HashSet<>(); - public boolean canPickUpLoot; + public boolean bukkitPickUpLoot; + public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper @Override public float getBukkitYaw() { diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index f268b7e6f89068267ea2f07f7505e0dc69968b73..99cb4dc1a1009d4a29e651c94d21babcc61388ed 100644 +index bbc126bdea2e8b0b6781f257ebc34791e7405094..e4f3dbff2605243039f9f59f025c931b3fb309c5 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -223,6 +223,7 @@ public abstract class Mob extends LivingEntity { +@@ -230,6 +230,7 @@ public abstract class Mob extends LivingEntity { return this.target; } + public org.bukkit.craftbukkit.entity.CraftMob getBukkitMob() { return (org.bukkit.craftbukkit.entity.CraftMob) super.getBukkitEntity(); } // Paper public void setTarget(@Nullable LivingEntity target) { // CraftBukkit start - fire event - setGoalTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true); + this.setGoalTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true); diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java index d090ffcf08e32a08d4b815b79ed58fc00bc26fd0..920ae9af8985705a0ada7da5b7085a1ed8ca7f27 100644 --- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java @@ -3787,22 +3593,22 @@ index d090ffcf08e32a08d4b815b79ed58fc00bc26fd0..920ae9af8985705a0ada7da5b7085a1e super(type, world); } diff --git a/src/main/java/net/minecraft/world/entity/monster/Monster.java b/src/main/java/net/minecraft/world/entity/monster/Monster.java -index fa886a89195312acfe53605169216ce95642ba87..407b7168b7e8d4408824039c06d02792d3c7e534 100644 +index d31c62b612a5a8016ffbfbb9dc85d9a941c08cf4..fc34cfa8bfb3b82a8e1b28d261f0e901d837467e 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Monster.java +++ b/src/main/java/net/minecraft/world/entity/monster/Monster.java -@@ -27,6 +27,7 @@ import net.minecraft.world.level.ServerLevelAccessor; +@@ -25,6 +25,7 @@ import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.ServerLevelAccessor; public abstract class Monster extends PathfinderMob implements Enemy { - + public org.bukkit.craftbukkit.entity.CraftMonster getBukkitMonster() { return (org.bukkit.craftbukkit.entity.CraftMonster) super.getBukkitEntity(); } // Paper protected Monster(EntityType type, Level world) { super(type, world); this.xpReward = 5; diff --git a/src/main/java/net/minecraft/world/entity/player/Inventory.java b/src/main/java/net/minecraft/world/entity/player/Inventory.java -index c0e0a8deabf3dffcc974f9e5bea2332d0d6e57a5..7d06838c4c8eef7ebff64ae094cd12404b9edd53 100644 +index 6d0b9f8834e86a465cae3fa2af830b797c65a4fb..a193358bf274bf13bfa090dd7f796d8d64cbfb39 100644 --- a/src/main/java/net/minecraft/world/entity/player/Inventory.java +++ b/src/main/java/net/minecraft/world/entity/player/Inventory.java -@@ -37,7 +37,7 @@ public class Inventory implements Container, Nameable { +@@ -44,7 +44,7 @@ public class Inventory implements Container, Nameable { public final NonNullList items; public final NonNullList armor; public final NonNullList offhand; @@ -3810,21 +3616,12 @@ index c0e0a8deabf3dffcc974f9e5bea2332d0d6e57a5..7d06838c4c8eef7ebff64ae094cd1240 + private final List> compartments; public final List> getComponents() { return compartments; } // Paper - OBFHELPER public int selected; public final Player player; - private ItemStack carried; + private int timesChanged; diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index da0fabafad0aa6c124abf52f8da68c73b7264fe9..2a6a6e291efbd7cc8fed6532f18321bd141e1306 100644 +index e5eab8bd104b84a9583cf28b1a89f3fe357a4004..d5b8931243e2f9cac9b0f92ab8df043a831bbe70 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -101,7 +101,7 @@ public final class ItemStack { - })).apply(instance, ItemStack::new); - }); - private static final Logger LOGGER = LogManager.getLogger(); -- public static final ItemStack EMPTY = new ItemStack((Item) null); -+ public static final ItemStack EMPTY = new ItemStack((Item) null);public static final ItemStack NULL_ITEM = EMPTY; // Paper - OBFHELPER - public static final DecimalFormat ATTRIBUTE_MODIFIER_FORMAT = (DecimalFormat) Util.make((new DecimalFormat("#.##")), (decimalformat) -> { // CraftBukkit - decompile error - decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); - }); -@@ -658,6 +658,24 @@ public final class ItemStack { +@@ -725,6 +725,24 @@ public final class ItemStack { return this.tag != null ? this.tag.getList("Enchantments", 10) : new ListTag(); } @@ -3849,15 +3646,15 @@ index da0fabafad0aa6c124abf52f8da68c73b7264fe9..2a6a6e291efbd7cc8fed6532f18321bd public void setTag(@Nullable CompoundTag tag) { this.tag = tag; if (this.getItem().canBeDepleted()) { -@@ -756,6 +774,7 @@ public final class ItemStack { +@@ -1043,6 +1061,7 @@ public final class ItemStack { return this.tag != null && this.tag.contains("Enchantments", 9) ? !this.tag.getList("Enchantments", 10).isEmpty() : false; } -+ public void getOrCreateTagAndSet(String s, Tag nbtbase) { addTagElement(s, nbtbase);} // Paper - OBFHELPER - public void addTagElement(String key, Tag tag) { ++ @Deprecated public void getOrCreateTagAndSet(String s, net.minecraft.nbt.Tag nbtbase) { addTagElement(s, nbtbase);} // Paper - OBFHELPER + public void addTagElement(String key, net.minecraft.nbt.Tag tag) { this.getOrCreateTag().put(key, tag); } -@@ -841,6 +860,7 @@ public final class ItemStack { +@@ -1128,6 +1147,7 @@ public final class ItemStack { // CraftBukkit start @Deprecated public void setItem(Item item) { @@ -3866,35 +3663,36 @@ index da0fabafad0aa6c124abf52f8da68c73b7264fe9..2a6a6e291efbd7cc8fed6532f18321bd } // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java b/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java -index e38c38c7d7679f267283a5ac6245e2261829aa05..2285a0cf6a35d06de77f94ad8a14ae91c1a7929f 100644 +index 3d9fffa3f07264743b9323557a0b2ac360e01fb9..c68cf35dc89b22f349aeb2faab45f6057aac5333 100644 --- a/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java +++ b/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java -@@ -121,6 +121,7 @@ public class PotionUtils { +@@ -126,6 +126,7 @@ public class PotionUtils { return compound == null ? Potions.EMPTY : Potion.byName(compound.getString("Potion")); } + public static ItemStack addPotionToItemStack(ItemStack itemstack, Potion potionregistry) { return setPotion(itemstack, potionregistry); } // Paper - OBFHELPER public static ItemStack setPotion(ItemStack stack, Potion potion) { - ResourceLocation minecraftkey = Registry.POTION.getKey(potion); - + ResourceLocation resourceLocation = Registry.POTION.getKey(potion); + if (potion == Potions.EMPTY) { diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java -index 3bbee667743d9a249c1513ea426e7a51d9185c4c..2feb187f62be5cf5d354a1e806087417cc189ab1 100644 +index 083122a2e051b23b2cb9bdb8eb70af01af9df400..e85e4a2dfceb0aa40e73b43a5e122a5906cac585 100644 --- a/src/main/java/net/minecraft/world/level/BlockGetter.java +++ b/src/main/java/net/minecraft/world/level/BlockGetter.java -@@ -8,9 +8,11 @@ import javax.annotation.Nullable; +@@ -9,10 +9,12 @@ import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.Mth; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Material; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; -@@ -22,6 +24,19 @@ public interface BlockGetter { - BlockEntity getBlockEntity(BlockPos pos); +@@ -30,6 +32,19 @@ public interface BlockGetter extends LevelHeightAccessor { + } BlockState getBlockState(BlockPos pos); + // Paper start - if loaded util @@ -3914,15 +3712,18 @@ index 3bbee667743d9a249c1513ea426e7a51d9185c4c..2feb187f62be5cf5d354a1e806087417 FluidState getFluidState(BlockPos pos); diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java -index 0caf067f9d888f9769db1503284d444e97c60c9c..7ccf830146c252cff8e22553d293e02d4b53dad8 100644 +index 23d1612f85ea8cb8c29fc8f4ec322f775e2a039b..9130fcb35d7dd8f92e0f1659bb98da4648f662b5 100644 --- a/src/main/java/net/minecraft/world/level/ChunkPos.java +++ b/src/main/java/net/minecraft/world/level/ChunkPos.java -@@ -12,27 +12,32 @@ public class ChunkPos { - public static final long INVALID_CHUNK_POS = asLong(1875016, 1875016); +@@ -16,6 +16,7 @@ public class ChunkPos { + private static final int REGION_MASK = 31; public final int x; public final int z; + public final long longKey; // Paper - + private static final int HASH_A = 1664525; + private static final int HASH_C = 1013904223; + private static final int HASH_Z_XOR = -559038737; +@@ -23,23 +24,27 @@ public class ChunkPos { public ChunkPos(int x, int z) { this.x = x; this.z = z; @@ -3930,14 +3731,14 @@ index 0caf067f9d888f9769db1503284d444e97c60c9c..7ccf830146c252cff8e22553d293e02d } public ChunkPos(BlockPos pos) { - this.x = pos.getX() >> 4; - this.z = pos.getZ() >> 4; + this.x = SectionPos.blockToSectionCoord(pos.getX()); + this.z = SectionPos.blockToSectionCoord(pos.getZ()); + this.longKey = asLong(this.x, this.z); // Paper } public ChunkPos(long pos) { - this.x = (int) pos; - this.z = (int) (pos >> 32); + this.x = (int)pos; + this.z = (int)(pos >> 32); + this.longKey = asLong(this.x, this.z); // Paper } @@ -3947,16 +3748,16 @@ index 0caf067f9d888f9769db1503284d444e97c60c9c..7ccf830146c252cff8e22553d293e02d } - public static long asLong(int chunkX, int chunkZ) { -+ public static long pair(final BlockPos pos) { return asLong(pos.getX() >> 4, pos.getZ() >> 4); } // Paper - OBFHELPER ++ @Deprecated public static long pair(final BlockPos pos) { return asLong(pos.getX() >> 4, pos.getZ() >> 4); } // Paper - OBFHELPER + public static long asLong(int chunkX, int chunkZ) { - return (long) chunkX & 4294967295L | ((long) chunkZ & 4294967295L) << 32; + return (long)chunkX & 4294967295L | ((long)chunkZ & 4294967295L) << 32; } diff --git a/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java b/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java -index 82c14e1ac66792137ab9e647c868a698c1ec9929..2b4f9849d668dede4d1f7d10f3a6ec9ef7a6d828 100644 +index 3c707d6674b2594b09503b959a31c1f4ad3981e6..c7d499bfc22152e0a49f50a2a8133f31a1be20ff 100644 --- a/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java +++ b/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java -@@ -20,6 +20,18 @@ public enum EmptyBlockGetter implements BlockGetter { +@@ -17,6 +17,18 @@ public enum EmptyBlockGetter implements BlockGetter { return null; } @@ -3976,24 +3777,38 @@ index 82c14e1ac66792137ab9e647c868a698c1ec9929..2b4f9849d668dede4d1f7d10f3a6ec9e public BlockState getBlockState(BlockPos pos) { return Blocks.AIR.defaultBlockState(); diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index f08de81dcc4acd5a3e44407b431ce827a19b2e9c..5cc4c2668df72f83fb1526f4586b71d2ae0103dc 100644 +index 90854842fda0f91ac68c70efbcf8ad9e3297ceb4..c9c8ce20e3adff1fe49489a6ac2d2e6be2795949 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -74,6 +74,7 @@ import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.CraftServer; +@@ -84,6 +84,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.SpigotTimings; // Spigot import org.bukkit.craftbukkit.block.CapturedBlockState; +import org.bukkit.craftbukkit.block.CraftBlockState; import org.bukkit.craftbukkit.block.data.CraftBlockData; + import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.event.block.BlockPhysicsEvent; - // CraftBukkit end -@@ -255,17 +256,50 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return y < 0 || y >= 256; +@@ -228,9 +229,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + Level.this.getCraftServer().getHandle().sendAll(new ClientboundSetBorderWarningDistancePacket(border), border.world); + } + +- public void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) {} ++ public void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) { ++ } + +- public void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) {} ++ public void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) { ++ } + }); + // CraftBukkit end + this.timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings +@@ -265,18 +268,50 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return y < -20000000 || y >= 20000000; } - public LevelChunk getChunkAt(BlockPos pos) { + public final LevelChunk getChunkAt(BlockPos pos) { // Paper - help inline - return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); + return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())); } @Override @@ -4001,17 +3816,17 @@ index f08de81dcc4acd5a3e44407b431ce827a19b2e9c..5cc4c2668df72f83fb1526f4586b71d2 - return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL); + public final LevelChunk getChunk(int chunkX, int chunkZ) { // Paper - final to help inline + return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true); // Paper - avoid a method jump -+ } -+ -+ // Paper start - if loaded -+ @Nullable -+ @Override -+ public final ChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ return ((ServerLevel)this).chunkSource.getChunkAtIfLoadedImmediately(x, z); } ++ // Paper start - if loaded + @Nullable @Override - public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { ++ public final ChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ return ((ServerLevel)this).chunkSource.getChunkAtIfLoadedImmediately(x, z); ++ } ++ ++ @Override + public final BlockState getTypeIfLoaded(BlockPos blockposition) { + // CraftBukkit start - tree generation + if (captureTreeGeneration) { @@ -4042,7 +3857,7 @@ index f08de81dcc4acd5a3e44407b431ce827a19b2e9c..5cc4c2668df72f83fb1526f4586b71d2 ChunkAccess ichunkaccess = this.getChunkSource().getChunk(chunkX, chunkZ, leastStatus, create); if (ichunkaccess == null && create) { -@@ -276,7 +310,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -287,7 +322,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } @Override @@ -4051,7 +3866,7 @@ index f08de81dcc4acd5a3e44407b431ce827a19b2e9c..5cc4c2668df72f83fb1526f4586b71d2 return this.setBlock(pos, state, flags, 512); } -@@ -422,8 +456,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -433,8 +468,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public void onBlockStateChange(BlockPos pos, BlockState oldBlock, BlockState newBlock) {} @@ -4063,67 +3878,40 @@ index f08de81dcc4acd5a3e44407b431ce827a19b2e9c..5cc4c2668df72f83fb1526f4586b71d2 FluidState fluid = this.getFluidState(pos); return this.setBlock(pos, fluid.createLegacyBlock(), 3 | (move ? 64 : 0)); -@@ -569,7 +604,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - if (isOutsideBuildHeight(pos)) { +@@ -588,7 +624,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + if (this.isOutsideBuildHeight(pos)) { return Blocks.VOID_AIR.defaultBlockState(); } else { -- LevelChunk chunk = this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); -+ LevelChunk chunk = (LevelChunk) this.getChunkSource().getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, true); // Paper - manually inline to reduce hops and avoid unnecessary null check to reduce total byte code size, this should never return null and if it does we will see it the next line but the real stack trace will matter in the chunk engine +- LevelChunk chunk = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())); ++ ChunkAccess chunk = this.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, true); // Paper - manually inline to reduce hops and avoid unnecessary null check to reduce total byte code size, this should never return null and if it does we will see it the next line but the real stack trace will matter in the chunk engine return chunk.getBlockState(pos); } diff --git a/src/main/java/net/minecraft/world/level/LevelReader.java b/src/main/java/net/minecraft/world/level/LevelReader.java -index b6877b78bf6ecf2069e59028f8910826c8b4eafe..6e4a53291ee87fac6d81d4ab9746906b6ae1b453 100644 +index 6cf167bc60a7150a0b84188b39f5b54f741ee7ed..660c7c40e8239063cc0b775628f941af99a76073 100644 --- a/src/main/java/net/minecraft/world/level/LevelReader.java +++ b/src/main/java/net/minecraft/world/level/LevelReader.java -@@ -18,6 +18,7 @@ import net.minecraft.world.phys.AABB; +@@ -18,6 +18,7 @@ import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.phys.AABB; public interface LevelReader extends BlockAndTintGetter, CollisionGetter, BiomeManager.NoiseBiomeSource { - + @Nullable ChunkAccess getChunkIfLoadedImmediately(int x, int z); // Paper - ifLoaded api (we need this since current impl blocks if the chunk is loading) @Nullable ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create); diff --git a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java b/src/main/java/net/minecraft/world/level/PathNavigationRegion.java -index f1d759d87291f469bde3b433031a6e7c6a19fbf2..6db3f4efa6ea4a09aad7684a3b7cc7479fad2f5c 100644 +index 00118cc80ebc31e5fac95c31c07634f0e2904263..138b6792bc6ee26e0b9aaaef7bf58fb231eae9d6 100644 --- a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java +++ b/src/main/java/net/minecraft/world/level/PathNavigationRegion.java -@@ -4,6 +4,7 @@ import java.util.function.Predicate; - import java.util.stream.Stream; - import javax.annotation.Nullable; +@@ -6,6 +6,7 @@ import javax.annotation.Nullable; import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; + import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; -@@ -23,7 +24,7 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { - protected final int centerZ; - protected final ChunkAccess[][] chunks; - protected boolean allEmpty; -- protected final Level level; -+ protected final Level level; protected final Level getWorld() { return level; } // Paper - OBFHELPER - - public PathNavigationRegion(Level world, BlockPos minPos, BlockPos maxPos) { - this.level = world; -@@ -42,7 +43,7 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { - - for (k = this.centerX; k <= i; ++k) { - for (l = this.centerZ; l <= j; ++l) { -- this.chunks[k - this.centerX][l - this.centerZ] = ichunkprovider.getChunkNow(k, l); -+ this.chunks[k - this.centerX][l - this.centerZ] = ((ServerLevel)world).getChunkSource().getChunkAtIfLoadedMainThreadNoCache(k, l); // Paper - } - } - -@@ -67,7 +68,7 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { - int k = i - this.centerX; - int l = j - this.centerZ; - -- if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { -+ if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { // Paper - if this changes, update getChunkIfLoaded below - ChunkAccess ichunkaccess = this.chunks[k][l]; - - return (ChunkAccess) (ichunkaccess != null ? ichunkaccess : new EmptyLevelChunk(this.level, new ChunkPos(i, j))); -@@ -86,6 +87,29 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { +@@ -79,6 +80,29 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { return this.getChunk(chunkX, chunkZ); } @@ -4132,7 +3920,7 @@ index f1d759d87291f469bde3b433031a6e7c6a19fbf2..6db3f4efa6ea4a09aad7684a3b7cc747 + int k = x - this.centerX; + int l = z - this.centerZ; + -+ if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { ++ if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { // Paper - if this changes, update getChunkIfLoaded below + return this.chunks[k][l]; + } + return null; @@ -4154,11 +3942,11 @@ index f1d759d87291f469bde3b433031a6e7c6a19fbf2..6db3f4efa6ea4a09aad7684a3b7cc747 @Override public BlockEntity getBlockEntity(BlockPos pos) { diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index c9713d1ab6498c09790503f673b31b5ef30ce4f3..e6928557a79f51302975f2832ec911c2692eaaeb 100644 +index 505731735126e81a4cc768311dce337385e5503f..549eb8a5f0f20db88abd17136f69f7bb00883011 100644 --- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -687,6 +687,7 @@ public abstract class BlockBehaviour { - return this.cache != null ? this.cache.isCollisionShapeFullBlock : Block.isShapeFullBlock(this.getCollisionShape(world, pos)); +@@ -984,6 +984,7 @@ public abstract class BlockBehaviour { + return this.cache != null ? this.cache.isCollisionShapeFullBlock : this.getBlock().isCollisionShapeFullBlock(this.asState(), world, pos); } + public final BlockState getBlockData() { return asState(); } // Paper - OBFHELPER @@ -4166,10 +3954,10 @@ index c9713d1ab6498c09790503f673b31b5ef30ce4f3..e6928557a79f51302975f2832ec911c2 public boolean requiresCorrectToolForDrops() { diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index fe1c10e5eeb434cd24e94b3247abbf5f73fce9cc..31f17956b3b031d1a47bda4d282554c8a7853097 100644 +index a0c4bc4eb42a3d2de6f66510d88f92c06b535353..72087476c65b69c86af67424a15708c463d69a43 100644 --- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java +++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -47,6 +47,7 @@ public class WorldBorder { +@@ -52,6 +52,7 @@ public class WorldBorder { return this.getDistanceToBorder(entity.getX(), entity.getZ()); } @@ -4178,39 +3966,47 @@ index fe1c10e5eeb434cd24e94b3247abbf5f73fce9cc..31f17956b3b031d1a47bda4d282554c8 return this.extent.getCollisionShape(); } diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 5a91d74f0acf393dbf098719b0924a4c00cf7128..e2c5a17aa72d1a5412d76881187d4d9ad1763297 100644 +index 62417156dd3e7e68e657f322c089fb6f30a11c0e..57f32618d6c95734fa4b45274afaf2319c7608ae 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -59,7 +59,7 @@ public class LevelChunk implements ChunkAccess { - - private static final Logger LOGGER = LogManager.getLogger(); +@@ -33,6 +33,7 @@ import net.minecraft.core.SectionPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.profiling.ProfilerFiller; + import net.minecraft.world.entity.Entity; +@@ -86,7 +87,7 @@ public class LevelChunk implements ChunkAccess { + } + }; @Nullable - public static final LevelChunkSection EMPTY_SECTION = null; + public static final LevelChunkSection EMPTY_SECTION = null; public static final LevelChunkSection EMPTY_CHUNK_SECTION = EMPTY_SECTION; // Paper - OBFHELPER private final LevelChunkSection[] sections; private ChunkBiomeContainer biomes; private final Map pendingBlockEntities; -@@ -82,7 +82,7 @@ public class LevelChunk implements ChunkAccess { +@@ -107,7 +108,7 @@ public class LevelChunk implements ChunkAccess { private Supplier fullStatus; @Nullable private Consumer postLoad; - private final ChunkPos chunkPos; + private final ChunkPos chunkPos; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key private volatile boolean isLightCorrect; + private final Int2ObjectMap gameEventDispatcherSections; - public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes) { -@@ -99,7 +99,8 @@ public class LevelChunk implements ChunkAccess { - this.postProcessing = new ShortList[16]; - this.entitySlices = (List[]) (new List[16]); // Spigot - this.world = (ServerLevel) world; // CraftBukkit - type +@@ -123,7 +124,8 @@ public class LevelChunk implements ChunkAccess { + this.structureStarts = Maps.newHashMap(); + this.structuresRefences = Maps.newHashMap(); + this.level = (ServerLevel) world; // CraftBukkit - type - this.chunkPos = pos; + this.locX = pos.x; this.locZ = pos.z; // Paper - reduce need for field look ups + this.chunkPos = pos; this.coordinateKey = ChunkPos.asLong(locX, locZ); // Paper - cache long key this.upgradeData = upgradeData; + this.gameEventDispatcherSections = new Int2ObjectOpenHashMap(); Heightmap.Types[] aheightmap_type = Heightmap.Types.values(); - int j = aheightmap_type.length; -@@ -145,6 +146,110 @@ public class LevelChunk implements ChunkAccess { - public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY); +@@ -168,6 +170,110 @@ public class LevelChunk implements ChunkAccess { + public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(LevelChunk.DATA_TYPE_REGISTRY); // CraftBukkit end + // Paper start @@ -4317,10 +4113,10 @@ index 5a91d74f0acf393dbf098719b0924a4c00cf7128..e2c5a17aa72d1a5412d76881187d4d9a + } + // Paper end + - public LevelChunk(Level world, ProtoChunk protoChunk) { - this(world, protoChunk.getPos(), protoChunk.getBiomes(), protoChunk.getUpgradeData(), protoChunk.getBlockTicks(), protoChunk.getLiquidTicks(), protoChunk.getInhabitedTime(), protoChunk.getSections(), (Consumer) null); - Iterator iterator = protoChunk.getEntities().iterator(); -@@ -250,6 +355,18 @@ public class LevelChunk implements ChunkAccess { + public LevelChunk(ServerLevel worldserver, ProtoChunk protoChunk, @Nullable Consumer consumer) { + this(worldserver, protoChunk.getPos(), protoChunk.getBiomes(), protoChunk.getUpgradeData(), protoChunk.getBlockTicks(), protoChunk.getLiquidTicks(), protoChunk.getInhabitedTime(), protoChunk.getSections(), consumer); + Iterator iterator = protoChunk.getBlockEntities().values().iterator(); +@@ -271,6 +377,18 @@ public class LevelChunk implements ChunkAccess { } } @@ -4339,23 +4135,7 @@ index 5a91d74f0acf393dbf098719b0924a4c00cf7128..e2c5a17aa72d1a5412d76881187d4d9a @Override public FluidState getFluidState(BlockPos pos) { return this.getFluidState(pos.getX(), pos.getY(), pos.getZ()); -@@ -390,6 +507,7 @@ public class LevelChunk implements ChunkAccess { - entity.xChunk = this.chunkPos.x; - entity.yChunk = k; - entity.zChunk = this.chunkPos.z; -+ this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); - } - -@@ -413,6 +531,7 @@ public class LevelChunk implements ChunkAccess { - } - - this.entitySlices[section].remove(entity); -+ this.entities.remove(entity); // Paper - } - - @Override -@@ -434,6 +553,7 @@ public class LevelChunk implements ChunkAccess { +@@ -422,6 +540,7 @@ public class LevelChunk implements ChunkAccess { return this.getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); } @@ -4363,14 +4143,14 @@ index 5a91d74f0acf393dbf098719b0924a4c00cf7128..e2c5a17aa72d1a5412d76881187d4d9a @Nullable public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType) { // CraftBukkit start -@@ -545,7 +665,25 @@ public class LevelChunk implements ChunkAccess { +@@ -578,7 +697,25 @@ public class LevelChunk implements ChunkAccess { // CraftBukkit start public void loadCallback() { + // Paper start - neighbour cache + int chunkX = this.chunkPos.x; + int chunkZ = this.chunkPos.z; -+ ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); ++ ServerChunkCache chunkProvider = this.level.getChunkSource(); + for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { + for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { + LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); @@ -4384,20 +4164,20 @@ index 5a91d74f0acf393dbf098719b0924a4c00cf7128..e2c5a17aa72d1a5412d76881187d4d9a + this.setNeighbourLoaded(0, 0, this); + this.loadedTicketLevel = true; + // Paper end - neighbour cache - org.bukkit.Server server = this.world.getCraftServer(); -+ ((ServerLevel)this.world).getChunkSource().addLoadedChunk(this); // Paper + org.bukkit.Server server = this.level.getCraftServer(); ++ this.level.getChunkSource().addLoadedChunk(this); // Paper if (server != null) { /* * If it's a new world, the first few chunks are generated inside -@@ -584,6 +722,22 @@ public class LevelChunk implements ChunkAccess { +@@ -617,6 +754,22 @@ public class LevelChunk implements ChunkAccess { server.getPluginManager().callEvent(unloadEvent); // note: saving can be prevented, but not forced if no saving is actually required this.mustNotSave = !unloadEvent.isSaveChunk(); -+ ((ServerLevel)this.world).getChunkSource().removeLoadedChunk(this); // Paper ++ this.level.getChunkSource().removeLoadedChunk(this); // Paper + // Paper start - neighbour cache + int chunkX = this.chunkPos.x; + int chunkZ = this.chunkPos.z; -+ ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); ++ ServerChunkCache chunkProvider = this.level.getChunkSource(); + for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { + for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { + LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); @@ -4412,26 +4192,36 @@ index 5a91d74f0acf393dbf098719b0924a4c00cf7128..e2c5a17aa72d1a5412d76881187d4d9a } // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index 8a4fca9f4882e65b831dd3f82f242e1113859fe0..b54d82e0f41a03c91e0de8df8249a91da3c04d0e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -139,6 +139,7 @@ public class LevelChunkSection { - return this.states; +@@ -896,19 +1049,13 @@ public class LevelChunk implements ChunkAccess { } -+ public void writeChunkSection(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER - public void write(FriendlyByteBuf packetdataserializer) { - packetdataserializer.writeShort(this.nonEmptyBlockCount); - this.states.write(packetdataserializer); + public void packTicks(ServerLevel world) { +- DefaultedRegistry registryblocks; +- + if (this.blockTicks == EmptyTickList.empty()) { // CraftBukkit - decompile error +- registryblocks = Registry.BLOCK; +- Objects.requireNonNull(registryblocks); +- this.blockTicks = new ChunkTickList<>(registryblocks::getKey, world.getBlockTicks().fetchTicksInChunk(this.chunkPos, true, false), world.getGameTime()); ++ this.blockTicks = new ChunkTickList<>(Registry.BLOCK::getKey, world.getBlockTicks().fetchTicksInChunk(this.chunkPos, true, false), world.getGameTime()); // Paper - decompile fix: inline Registry.BLOCK + this.setUnsaved(true); + } + + if (this.liquidTicks == EmptyTickList.empty()) { // CraftBukkit - decompile error +- registryblocks = Registry.FLUID; +- Objects.requireNonNull(registryblocks); +- this.liquidTicks = new ChunkTickList<>(registryblocks::getKey, world.getLiquidTicks().fetchTicksInChunk(this.chunkPos, true, false), world.getGameTime()); ++ this.liquidTicks = new ChunkTickList<>(Registry.FLUID::getKey, world.getLiquidTicks().fetchTicksInChunk(this.chunkPos, true, false), world.getGameTime()); // Paper - decompile fix: inline Registry.FLUID + this.setUnsaved(true); + } + diff --git a/src/main/java/net/minecraft/world/level/chunk/Palette.java b/src/main/java/net/minecraft/world/level/chunk/Palette.java -index dcc030f4801b4c6e1fe5b8c2718ddfd7ba6bb248..78c56e1e2af50e923fb0b07c6ddd860c4aa77195 100644 +index 967cc874eacdb8f589e548b0ee3d60efff72392e..2d95baf6f93b9710dd0910b0c6634ffc3d94d11f 100644 --- a/src/main/java/net/minecraft/world/level/chunk/Palette.java +++ b/src/main/java/net/minecraft/world/level/chunk/Palette.java -@@ -7,10 +7,12 @@ import net.minecraft.network.FriendlyByteBuf; +@@ -6,10 +6,12 @@ import net.minecraft.nbt.ListTag; + import net.minecraft.network.FriendlyByteBuf; public interface Palette { - + default int getOrCreateIdFor(T object) { return this.idFor(object); } // Paper - OBFHELPER int idFor(T object); @@ -4442,19 +4232,19 @@ index dcc030f4801b4c6e1fe5b8c2718ddfd7ba6bb248..78c56e1e2af50e923fb0b07c6ddd860c T valueFor(int index); diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index f14f89f8916c832feaa3887bd28a5cf6b2f6ff1d..d4db27421736f665739436c1ac4d3c6d5cae95cd 100644 +index 527238373b944a1e4a6e3a408534c72dd4c84035..4a6781919eb78abc33f549693d88019b42ef6e95 100644 --- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -19,7 +19,7 @@ import net.minecraft.util.Mth; - - public class PalettedContainer implements PaletteResize { - +@@ -20,7 +20,7 @@ public class PalettedContainer implements PaletteResize { + private static final int SIZE = 4096; + public static final int GLOBAL_PALETTE_BITS = 9; + public static final int MIN_PALETTE_SIZE = 4; - private final Palette globalPalette; + private final Palette globalPalette; private final Palette getDataPaletteGlobal() { return this.globalPalette; } // Paper - OBFHELPER - private final PaletteResize dummyPaletteResize = (i, object) -> { + private final PaletteResize dummyPaletteResize = (newSize, added) -> { return 0; }; -@@ -27,9 +27,9 @@ public class PalettedContainer implements PaletteResize { +@@ -28,9 +28,9 @@ public class PalettedContainer implements PaletteResize { private final Function reader; private final Function writer; private final T defaultValue; @@ -4464,10 +4254,10 @@ index f14f89f8916c832feaa3887bd28a5cf6b2f6ff1d..d4db27421736f665739436c1ac4d3c6d + protected BitStorage storage; public final BitStorage getDataBits() { return this.storage; } // Paper - OBFHELPER + private Palette palette; private Palette getDataPalette() { return this.palette; } // Paper - OBFHELPER + private int bits; private int getBitsPerObject() { return this.bits; } // Paper - OBFHELPER - private final ReentrantLock lock = new ReentrantLock(); - - public void acquire() { -@@ -64,6 +64,7 @@ public class PalettedContainer implements PaletteResize { + private final Semaphore lock = new Semaphore(1); + @Nullable + private final DebugBuffer> traces = null; +@@ -61,6 +61,7 @@ public class PalettedContainer implements PaletteResize { return y << 8 | z << 4 | x; } @@ -4475,20 +4265,20 @@ index f14f89f8916c832feaa3887bd28a5cf6b2f6ff1d..d4db27421736f665739436c1ac4d3c6d private void setBits(int size) { if (size != this.bits) { this.bits = size; -@@ -141,6 +142,7 @@ public class PalettedContainer implements PaletteResize { - return t0 == null ? this.defaultValue : t0; +@@ -159,6 +160,7 @@ public class PalettedContainer implements PaletteResize { + } + public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER public void write(FriendlyByteBuf buf) { - this.acquire(); - buf.writeByte(this.bits); + try { + this.acquire(); diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index cecf8a68f215d85e84fba157930f6987ffd21e50..7cd3f89004b0a64772fc3dfbdd132ba5a850b63e 100644 +index c0b68bd470d245121e14b75e2c97f6616b83c92a..39fe8f64528ad08594aaaa88e5c989c82e4e29d3 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -99,6 +99,18 @@ public class ProtoChunk implements ChunkAccess { - +@@ -90,6 +90,18 @@ public class ProtoChunk implements ChunkAccess { + this.postProcessing = new ShortList[world.getSectionsCount()]; } + // Paper start - If loaded util @@ -4507,10 +4297,10 @@ index cecf8a68f215d85e84fba157930f6987ffd21e50..7cd3f89004b0a64772fc3dfbdd132ba5 public BlockState getBlockState(BlockPos pos) { int i = pos.getY(); diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -index 7de765786b3504dcffab98bb0d9dac64b30b3325..5bd34b136f2892f541ba686debca19e0a4eef0be 100644 +index ed4539f25dbd5b1c5c48b70a8d1e9f63fff5d964..7fae9cd0c7c515426b437435117585924983bf45 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -@@ -27,7 +27,7 @@ public class IOWorker implements AutoCloseable { +@@ -26,7 +26,7 @@ public class IOWorker implements AutoCloseable { private static final Logger LOGGER = LogManager.getLogger(); private final AtomicBoolean shutdownRequested = new AtomicBoolean(); private final ProcessorMailbox mailbox; @@ -4518,12 +4308,12 @@ index 7de765786b3504dcffab98bb0d9dac64b30b3325..5bd34b136f2892f541ba686debca19e0 + private final RegionFileStorage storage;public RegionFileStorage getRegionFileCache() { return storage; } // Paper - OBFHELPER private final Map pendingWrites = Maps.newLinkedHashMap(); - protected IOWorker(File file, boolean flag, String s) { + protected IOWorker(File directory, boolean dsync, String name) { diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index aa3d6db08e4d744cc94de71d0f8dceb99948e2ab..60f410a4f838048bbfd2cde52caa7c4c9434b0ba 100644 +index 1441888430687b9de2a67f21ed426f16d5b30538..2da42f1bc6922adae32d782aac780a7e0e94e352 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -112,6 +112,7 @@ public class RegionFile implements AutoCloseable { +@@ -121,6 +121,7 @@ public class RegionFile implements AutoCloseable { return this.externalFileDir.resolve(s); } @@ -4532,11 +4322,11 @@ index aa3d6db08e4d744cc94de71d0f8dceb99948e2ab..60f410a4f838048bbfd2cde52caa7c4c public synchronized DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException { int i = this.getOffset(pos); diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java -index 022fafff8b476f8bc1830bf5494760b0fef65297..983d0495ec35128ca3ef68566ada065bc4b21efc 100644 +index 120498a39b7ca7aee9763084507508d4a1c425aa..aa33a12b8b8ce6bb9a3278bcfa5b9017b3b432da 100644 --- a/src/main/java/net/minecraft/world/phys/AABB.java +++ b/src/main/java/net/minecraft/world/phys/AABB.java -@@ -194,10 +194,12 @@ public class AABB { - return this.move(vec3d.x, vec3d.y, vec3d.z); +@@ -223,10 +223,12 @@ public class AABB { + return this.move(vec.x, vec.y, vec.z); } + public final boolean intersects(AABB axisalignedbb) { return this.intersects(axisalignedbb); } // Paper - OBFHELPER @@ -4548,33 +4338,33 @@ index 022fafff8b476f8bc1830bf5494760b0fef65297..983d0495ec35128ca3ef68566ada065b public boolean intersects(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ; } -@@ -210,6 +212,7 @@ public class AABB { +@@ -243,6 +245,7 @@ public class AABB { return x >= this.minX && x < this.maxX && y >= this.minY && y < this.maxY && z >= this.minZ && z < this.maxZ; } + public final double getAverageSideLength(){return getSize();} // Paper - OBFHELPER public double getSize() { - double d0 = this.getXsize(); - double d1 = this.getYsize(); + double d = this.getXsize(); + double e = this.getYsize(); diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -index eb07309be171ccadcae21f4096c44d2b700d22b3..2371b52b450e2b43fa9b9549a91f853c702a9dc0 100644 +index 5af90e0f7222356cb0e905a9b6e0c4eac5617a41..4f466cc1b196abdfd3a0282cae58f66de0a6be4f 100644 --- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -@@ -31,10 +31,12 @@ public final class Shapes { +@@ -30,10 +30,12 @@ public final class Shapes { public static final VoxelShape INFINITY = box(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); - private static final VoxelShape EMPTY = new ArrayVoxelShape(new BitSetDiscreteVoxelShape(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); + private static final VoxelShape EMPTY = new ArrayVoxelShape(new BitSetDiscreteVoxelShape(0, 0, 0), (DoubleList)(new DoubleArrayList(new double[]{0.0D})), (DoubleList)(new DoubleArrayList(new double[]{0.0D})), (DoubleList)(new DoubleArrayList(new double[]{0.0D}))); + public static final VoxelShape empty() {return empty();} // Paper - OBFHELPER public static VoxelShape empty() { - return Shapes.EMPTY; + return EMPTY; } + public static final VoxelShape fullCube() {return block();} // Paper - OBFHELPER public static VoxelShape block() { - return Shapes.BLOCK; + return BLOCK; } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index c34f63eaf3deca4623ca4dfbee863771014847ba..01df5263d77771a296ca091a0feec620e6e37229 100644 +index 5a247fcd7398d83f37df4aa3103b55611dc87e66..1818be091ce06c1f347396a8a5b9e05f9ceca2c9 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java @@ -85,6 +85,7 @@ public final class CraftItemStack extends ItemStack { @@ -4586,7 +4376,7 @@ index c34f63eaf3deca4623ca4dfbee863771014847ba..01df5263d77771a296ca091a0feec620 /** * Mirror diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 9ad17c560c8d99a396543ab9f97c34de648f6544..4bf48f77f3f7cd62a91590543f5af441c8268029 100644 +index 836ee63b7ea73165257acbcdf5c7336a2a2e36f3..2b4a922b84eeb2b1b64e43a2ca8bf16dcf58218e 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java @@ -43,6 +43,7 @@ import org.bukkit.scheduler.BukkitWorker; @@ -4598,7 +4388,7 @@ index 9ad17c560c8d99a396543ab9f97c34de648f6544..4bf48f77f3f7cd62a91590543f5af441 * Counter for IDs. Order doesn't matter, only uniqueness. */ @@ -177,6 +178,11 @@ public class CraftScheduler implements BukkitScheduler { - runTaskTimer(plugin, (Object) task, delay, period); + this.runTaskTimer(plugin, (Object) task, delay, period); } + public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { @@ -4607,7 +4397,7 @@ index 9ad17c560c8d99a396543ab9f97c34de648f6544..4bf48f77f3f7cd62a91590543f5af441 + } + public BukkitTask runTaskTimer(Plugin plugin, Object runnable, long delay, long period) { - validate(plugin, runnable); + CraftScheduler.validate(plugin, runnable); if (delay < 0L) { @@ -400,13 +406,20 @@ public class CraftScheduler implements BukkitScheduler { task.run(); @@ -4633,10 +4423,10 @@ index 9ad17c560c8d99a396543ab9f97c34de648f6544..4bf48f77f3f7cd62a91590543f5af441 + } + // Paper end } finally { - currentTask = null; + this.currentTask = null; } diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -index 3c7066192ea4c05c101404bb56cbc839771f4200..09aa6809c5400ce8548ac902908b750ce7c964ec 100644 +index 40f00ccb4b7be6fcf9d4eaa38aba778bf61df6bb..aec92f03951ef15bdf8af84b9b1526a788fd7f4d 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java @@ -39,6 +39,21 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot @@ -4800,10 +4590,10 @@ index 0000000000000000000000000000000000000000..49dc0c441b9dd7e7745cf15ced67f383 + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -index 33cd17c415ae19bc9028934257b396907995cb9a..40a2ad3e180cc50a755f44a8ff6d8261734bf733 100644 +index edb73162efb09092b6b1faefd4543cd3f8a9106e..22ed8ab5bf311ac0b788d891c654baba89623a23 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java +++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -@@ -168,7 +168,23 @@ public class DummyGeneratorAccess implements LevelAccessor { +@@ -187,7 +187,23 @@ public class DummyGeneratorAccess implements LevelAccessor { public FluidState getFluidState(BlockPos pos) { throw new UnsupportedOperationException("Not supported yet."); } @@ -4828,7 +4618,7 @@ index 33cd17c415ae19bc9028934257b396907995cb9a..40a2ad3e180cc50a755f44a8ff6d8261 public WorldBorder getWorldBorder() { throw new UnsupportedOperationException("Not supported yet."); diff --git a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -index 1aec70a1f1a9d8fd2cd06bde4033e19e769ab331..f72c13bedaa6fa45e26f5dcad564835bdd4af61f 100644 +index d40c0d8be1b0153d62021b8bcb6e8b37fd0acb4e..b0897aba0ac2aa62c2f3d1268f38fef1440b230c 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java +++ b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java @@ -17,7 +17,7 @@ import java.util.RandomAccess; @@ -4841,7 +4631,7 @@ index 1aec70a1f1a9d8fd2cd06bde4033e19e769ab331..f72c13bedaa6fa45e26f5dcad564835b private int initialCapacity; diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 8d6f4d76d6f04a322a98faecaca6b1b69c5f49d6..dc11dab14624ca25e78bf0b919ecf461e0be430d 100644 +index 87f4d952843654927779a16047da9d601d994fc2..e38b5957b015be3c835ca28a9fe6ee75d7954393 100644 --- a/src/main/java/org/spigotmc/SpigotConfig.java +++ b/src/main/java/org/spigotmc/SpigotConfig.java @@ -118,7 +118,11 @@ public class SpigotConfig @@ -4856,4 +4646,4 @@ index 8d6f4d76d6f04a322a98faecaca6b1b69c5f49d6..dc11dab14624ca25e78bf0b919ecf461 + // Paper end try { - config.save( CONFIG_FILE ); + SpigotConfig.config.save( CONFIG_FILE ); diff --git a/patches/server-remapped/0007-Paper-Metrics.patch b/patches/server/0007-Paper-Metrics.patch similarity index 99% rename from patches/server-remapped/0007-Paper-Metrics.patch rename to patches/server/0007-Paper-Metrics.patch index 82a9c9a2d4..38a4e27283 100644 --- a/patches/server-remapped/0007-Paper-Metrics.patch +++ b/patches/server/0007-Paper-Metrics.patch @@ -714,7 +714,7 @@ index 2c0514892d3993bef57ecf677cf8bb0fbe0216e4..da922f395f0fff0881ead893c900c5b2 static void readConfig(Class clazz, Object instance) { diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index dc11dab14624ca25e78bf0b919ecf461e0be430d..0083f979933d4a9035efb992ab0a2f250a56a979 100644 +index e38b5957b015be3c835ca28a9fe6ee75d7954393..2d226fd06759ed92bf5591259fc86f34f606a3ec 100644 --- a/src/main/java/org/spigotmc/SpigotConfig.java +++ b/src/main/java/org/spigotmc/SpigotConfig.java @@ -83,6 +83,7 @@ public class SpigotConfig @@ -722,7 +722,7 @@ index dc11dab14624ca25e78bf0b919ecf461e0be430d..0083f979933d4a9035efb992ab0a2f25 } + /* // Paper - Replace with our own - if ( metrics == null ) + if ( SpigotConfig.metrics == null ) { try @@ -94,6 +95,7 @@ public class SpigotConfig diff --git a/patches/server-remapped/0008-Add-MinecraftKey-Information-to-Objects.patch b/patches/server/0008-Add-MinecraftKey-Information-to-Objects.patch similarity index 80% rename from patches/server-remapped/0008-Add-MinecraftKey-Information-to-Objects.patch rename to patches/server/0008-Add-MinecraftKey-Information-to-Objects.patch index 91f564fb1b..5d6c20956d 100644 --- a/patches/server-remapped/0008-Add-MinecraftKey-Information-to-Objects.patch +++ b/patches/server/0008-Add-MinecraftKey-Information-to-Objects.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Add MinecraftKey Information to Objects Stores the reference to the objects respective MinecraftKey diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index d05eeaa711a09bb121b530654821894e795ff4ea..e95b91cefb0374bd5bb57cc090f5ecd566d7a618 100644 +index 94cc5b494cdbc163fb70d0f4a6708d6ca2f42288..3ef396c0a543b5724769e0b83314f332739bdff0 100644 --- a/src/main/java/com/destroystokyo/paper/PaperCommand.java +++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java @@ -208,7 +208,7 @@ public class PaperCommand extends Command { @@ -20,14 +20,15 @@ index d05eeaa711a09bb121b530654821894e795ff4ea..e95b91cefb0374bd5bb57cc090f5ecd5 ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); diff --git a/src/main/java/net/minecraft/server/KeyedObject.java b/src/main/java/net/minecraft/server/KeyedObject.java new file mode 100644 -index 0000000000000000000000000000000000000000..3c9933050ca0a7453ba7950cb3cf4cc8b5b7081d +index 0000000000000000000000000000000000000000..d02bd109399d6b32cbbb5e6f9ec7e650e8299a26 --- /dev/null +++ b/src/main/java/net/minecraft/server/KeyedObject.java -@@ -0,0 +1,11 @@ +@@ -0,0 +1,12 @@ +package net.minecraft.server; + +import net.minecraft.resources.ResourceLocation; + ++// TODO(Mariell Hoversholm): Move stupid ass class +public interface KeyedObject { + ResourceLocation getMinecraftKey(); + default String getMinecraftKeyString() { @@ -36,19 +37,19 @@ index 0000000000000000000000000000000000000000..3c9933050ca0a7453ba7950cb3cf4cc8 + } +} diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c7008fcbd4d805fe0e743f1d4ad948dcd86ceae3..48c9d2b7d56832ebd13749a394b8b715f0b1704d 100644 +index f62223f11e4be40350ca0ff0beb46fa68a1582fe..b494980b4a3303b2f19002d44f81a2707e6916a5 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -135,7 +135,7 @@ import org.bukkit.event.player.PlayerTeleportEvent; +@@ -146,7 +146,7 @@ import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.plugin.PluginManager; // CraftBukkit end --public abstract class Entity implements Nameable, CommandSource { -+public abstract class Entity implements Nameable, CommandSource, net.minecraft.server.KeyedObject { // Paper +-public abstract class Entity implements Nameable, EntityAccess, CommandSource { ++public abstract class Entity implements Nameable, EntityAccess, CommandSource, net.minecraft.server.KeyedObject { // Paper // CraftBukkit start private static final int CURRENT_LEVEL = 2; -@@ -1761,12 +1761,31 @@ public abstract class Entity implements Nameable, CommandSource { +@@ -1954,12 +1954,31 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { return true; } @@ -80,12 +81,12 @@ index c7008fcbd4d805fe0e743f1d4ad948dcd86ceae3..48c9d2b7d56832ebd13749a394b8b715 + // Paper end } - protected abstract void readAdditionalSaveData(CompoundTag tag); + protected abstract void readAdditionalSaveData(CompoundTag nbt); diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index 102298d57cf3143092d04ab1d5d0d69b28d696ea..2cb86de4bfc87a709f0cfa2c4e550d8e7928a3f0 100644 +index 89e7d02b88404ac5dce06595432ae95c9a4e5015..3ffaeb72be8cda7a2b9398b8909db5c220e8b6c9 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -384,6 +384,7 @@ public class EntityType { +@@ -398,6 +398,7 @@ public class EntityType implements EntityTypeTest { } } @@ -94,10 +95,10 @@ index 102298d57cf3143092d04ab1d5d0d69b28d696ea..2cb86de4bfc87a709f0cfa2c4e550d8e return this.serialize; } diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 8928a1ae51d24fd15aaae93bc8ea573548f2b012..846fc0f36377337630b2ec2a5f7a5a54c39c2965 100644 +index 33884161de688c47c90a7b86196234acc80f9434..e4601134598e509a158ceacec6099a78bbabe89d 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -23,7 +23,7 @@ import org.bukkit.inventory.InventoryHolder; +@@ -20,7 +20,7 @@ import org.bukkit.inventory.InventoryHolder; import org.spigotmc.CustomTimingsHandler; // Spigot @@ -106,7 +107,7 @@ index 8928a1ae51d24fd15aaae93bc8ea573548f2b012..846fc0f36377337630b2ec2a5f7a5a54 public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot // CraftBukkit start - data containers -@@ -31,7 +31,7 @@ public abstract class BlockEntity { +@@ -28,7 +28,7 @@ public abstract class BlockEntity { public CraftPersistentDataContainer persistentDataContainer; // CraftBukkit end private static final Logger LOGGER = LogManager.getLogger(); @@ -114,9 +115,9 @@ index 8928a1ae51d24fd15aaae93bc8ea573548f2b012..846fc0f36377337630b2ec2a5f7a5a54 + private final BlockEntityType type; public BlockEntityType getTileEntityType() { return type; } // Paper - OBFHELPER @Nullable protected Level level; - protected BlockPos worldPosition; -@@ -45,6 +45,26 @@ public abstract class BlockEntity { - this.type = type; + protected final BlockPos worldPosition; +@@ -41,6 +41,26 @@ public abstract class BlockEntity { + this.blockState = state; } + // Paper start diff --git a/settings.gradle.kts b/settings.gradle.kts index 54bb957497..302bcb31ab 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,6 @@ pluginManagement { repositories { + mavenLocal() gradlePluginPortal() maven("https://wav.jfrog.io/artifactory/repo/") } From 3d21ab7adb3f6dce14a3d4184682955405894ee6 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 19:56:25 +0200 Subject: [PATCH 013/226] ci: remove java 8 build Signed-off-by: Mariell Hoversholm --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a94f849ec9..0da3c7e06f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [16, 8] + java: [16] fail-fast: true steps: - uses: actions/checkout@v2 From 3f10bf116306fac75cbd2bfd4295134f7d797cdd Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Fri, 11 Jun 2021 11:02:16 -0700 Subject: [PATCH 014/226] Update Timings patch (#5796) --- ...M-changes.patch => 0002-POM-changes.patch} | 0 ...atch => 0003-Add-FastUtil-to-Bukkit.patch} | 2 +- ...per-Utils.patch => 0004-Paper-Utils.patch} | 0 .../0005-Timings-v2.patch} | 2 +- .../0009-Timings-v2.patch} | 709 +++++++----------- 5 files changed, 273 insertions(+), 440 deletions(-) rename patches/api/{0001-POM-changes.patch => 0002-POM-changes.patch} (100%) rename patches/api/{0002-Add-FastUtil-to-Bukkit.patch => 0003-Add-FastUtil-to-Bukkit.patch} (88%) rename patches/api/{0003-Paper-Utils.patch => 0004-Paper-Utils.patch} (100%) rename patches/{api-unmapped/0004-Timings-v2.patch => api/0005-Timings-v2.patch} (99%) rename patches/{server-remapped/0011-Timings-v2.patch => server/0009-Timings-v2.patch} (77%) diff --git a/patches/api/0001-POM-changes.patch b/patches/api/0002-POM-changes.patch similarity index 100% rename from patches/api/0001-POM-changes.patch rename to patches/api/0002-POM-changes.patch diff --git a/patches/api/0002-Add-FastUtil-to-Bukkit.patch b/patches/api/0003-Add-FastUtil-to-Bukkit.patch similarity index 88% rename from patches/api/0002-Add-FastUtil-to-Bukkit.patch rename to patches/api/0003-Add-FastUtil-to-Bukkit.patch index a5e6eda88d..1a80b26e31 100644 --- a/patches/api/0002-Add-FastUtil-to-Bukkit.patch +++ b/patches/api/0003-Add-FastUtil-to-Bukkit.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Add FastUtil to Bukkit Doesn't expose to plugins, just allows Paper-API to use it for optimization diff --git a/pom.xml b/pom.xml -index 61b8ee4e3e122dd2671f50ea3b432e4abd4600a2..12306d830c6889c2c9b12699abebe0411262aef6 100644 +index d7cf64f05d0a2f5b186ca13b2b88e390abe84226..1ebc4c096638128194cea9c2a4131f901e7d6896 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,12 @@ diff --git a/patches/api/0003-Paper-Utils.patch b/patches/api/0004-Paper-Utils.patch similarity index 100% rename from patches/api/0003-Paper-Utils.patch rename to patches/api/0004-Paper-Utils.patch diff --git a/patches/api-unmapped/0004-Timings-v2.patch b/patches/api/0005-Timings-v2.patch similarity index 99% rename from patches/api-unmapped/0004-Timings-v2.patch rename to patches/api/0005-Timings-v2.patch index 9cfffce81e..ec3f6cb55f 100644 --- a/patches/api-unmapped/0004-Timings-v2.patch +++ b/patches/api/0005-Timings-v2.patch @@ -3497,7 +3497,7 @@ index a09c3f71ca563b6f40a118ce1344d0eb273bed40..cf2f517765d8f2a23cc4a17d9ee2dcd8 eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); } else { diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 6843e32438492f380e2e72bb40dd49d45fe675cb..5ffa98bb9c76d802a9d0ea6c572a704a2732c67c 100644 +index b0a347ab4be868ca92a1a0a8318da658e7194069..13100c688bfccb826b3072aaa92901f8634cf9ab 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java @@ -29,7 +29,8 @@ import org.jetbrains.annotations.Nullable; diff --git a/patches/server-remapped/0011-Timings-v2.patch b/patches/server/0009-Timings-v2.patch similarity index 77% rename from patches/server-remapped/0011-Timings-v2.patch rename to patches/server/0009-Timings-v2.patch index dc683eaeec..79950f0d62 100644 --- a/patches/server-remapped/0011-Timings-v2.patch +++ b/patches/server/0009-Timings-v2.patch @@ -729,13 +729,13 @@ index da922f395f0fff0881ead893c900c5b2623f48f0..1d03a79e9010bc514b72a81ba0ad4a62 + } } diff --git a/src/main/java/net/minecraft/commands/CommandFunction.java b/src/main/java/net/minecraft/commands/CommandFunction.java -index cf57de0e791a9362fe95b65134d9fe4f4e95adf4..07b891075191161a8a903876b02caa75d4db1366 100644 +index ca1a9884ab09fc7e575b1d30e2dd0aaff324fb73..81b36a20f57d92644a91bac9b7089ec23c211a6f 100644 --- a/src/main/java/net/minecraft/commands/CommandFunction.java +++ b/src/main/java/net/minecraft/commands/CommandFunction.java -@@ -15,12 +15,22 @@ public class CommandFunction { - +@@ -16,12 +16,22 @@ import net.minecraft.server.ServerFunctionManager; + public class CommandFunction { private final CommandFunction.Entry[] entries; - private final ResourceLocation id; + final ResourceLocation id; + // Paper start + public co.aikar.timings.Timing timing; + public co.aikar.timings.Timing getTiming() { @@ -756,7 +756,7 @@ index cf57de0e791a9362fe95b65134d9fe4f4e95adf4..07b891075191161a8a903876b02caa75 return this.id; } diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -index 23ccd095ad99fe90a6f2a16bcca368804b16101a..4ae8201d7dcffeb3298a4e593f978e15ffc5ac15 100644 +index b3a6aeba2363d283f03982cf749f25cfa11a5052..449f1b2f5dca350dc0912e14c8c2bf3eb4652b92 100644 --- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java +++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java @@ -3,6 +3,8 @@ package net.minecraft.network.protocol; @@ -768,25 +768,25 @@ index 23ccd095ad99fe90a6f2a16bcca368804b16101a..4ae8201d7dcffeb3298a4e593f978e15 // CraftBukkit start import net.minecraft.server.MinecraftServer; -@@ -21,10 +23,13 @@ public class PacketUtils { +@@ -23,10 +25,13 @@ public class PacketUtils { public static void ensureRunningOnSameThread(Packet packet, T listener, BlockableEventLoop engine) throws RunningOnDifferentThreadException { if (!engine.isSameThread()) { + Timing timing = MinecraftTimings.getPacketTiming(packet); // Paper - timings engine.execute(() -> { if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerGamePacketListenerImpl && ((ServerGamePacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590 - if (listener.a().isConnected()) { + if (listener.getConnection().isConnected()) { + try (Timing ignored = timing.startTiming()) { // Paper - timings packet.handle(listener); + } // Paper - timings } else { - PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); + PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: {}", packet); } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 2406879e76a110e96a4753e66366432a4bc52d9b..a456b9cbf0e5eea4e888e0e3d07ed17558650371 100644 +index 2c13b8565b606a26b305fd44cfc0bd339df8f6be..6a6249ad58cc90782d526d89c899f30a59b980b2 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -172,7 +172,7 @@ import org.bukkit.craftbukkit.Main; +@@ -183,7 +183,7 @@ import org.bukkit.craftbukkit.Main; import org.bukkit.event.server.ServerLoadEvent; // CraftBukkit end @@ -795,7 +795,7 @@ index 2406879e76a110e96a4753e66366432a4bc52d9b..a456b9cbf0e5eea4e888e0e3d07ed175 import org.spigotmc.SlackActivityAccountant; // Spigot public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { -@@ -226,8 +226,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= 5000000000L) { -@@ -1141,14 +1162,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % autosavePeriod == 0) { // CraftBukkit + if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // CraftBukkit - SpigotTimings.worldSaveTimer.startTiming(); // Spigot MinecraftServer.LOGGER.debug("Autosave started"); this.profiler.push("save"); @@ -883,7 +883,7 @@ index 2406879e76a110e96a4753e66366432a4bc52d9b..a456b9cbf0e5eea4e888e0e3d07ed175 } this.profiler.push("snooper"); -@@ -1161,6 +1180,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // CraftBukkit start - fire RemoteServerCommandEvent -@@ -677,10 +679,39 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -719,10 +721,39 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface if (event.isCancelled()) { return; } @@ -1047,7 +1047,7 @@ index 23d6f803eafa78fd51ea4cdc4ca25c78661bc80b..40fe03c844c8bf6a9c4c5ae028b259f0 + co.aikar.timings.Timings.generateReport(new co.aikar.timings.TimingsReportListener(sender, waitable)); + } else { + // Paper end - ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), rconConsoleSource.createCommandSourceStack()); + ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), this.rconConsoleSource.createCommandSourceStack()); server.dispatchServerCommand(remoteConsole, serverCommand); + } // Paper // CraftBukkit end @@ -1071,7 +1071,7 @@ index 23d6f803eafa78fd51ea4cdc4ca25c78661bc80b..40fe03c844c8bf6a9c4c5ae028b259f0 } diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465..59a5f82c9f57d760ba4959a040ce8cbf0f49e4aa 100644 +index cbaafa2024a36fbdaf9f753c58ca974831af9fdf..39cfa8211f02acaa0851e0cfc1c2890475d609f4 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -1,7 +1,9 @@ @@ -1084,7 +1084,7 @@ index d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465..59a5f82c9f57d760ba4959a040ce8cbf import com.google.common.collect.Lists; import com.google.common.collect.Queues; import com.google.common.collect.Sets; -@@ -552,11 +554,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -579,11 +581,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider private CompletableFuture> scheduleChunkLoad(ChunkPos pos) { return CompletableFuture.supplyAsync(() -> { @@ -1102,7 +1102,7 @@ index d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465..59a5f82c9f57d760ba4959a040ce8cbf boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8); if (flag) { -@@ -568,7 +573,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -594,7 +599,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } ChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", pos); @@ -1111,24 +1111,15 @@ index d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465..59a5f82c9f57d760ba4959a040ce8cbf } catch (ReportedException reportedexception) { Throwable throwable = reportedexception.getCause(); -@@ -605,7 +610,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return "chunkGenerate " + requiredStatus.getName(); - }); - return completablefuture.thenComposeAsync((either) -> { -- return (CompletableFuture) either.map((list) -> { -+ return either.map((list) -> { // Paper - Shut up. - try { - CompletableFuture> completablefuture1 = requiredStatus.generate(this.level, this.generator, this.structureManager, this.lightEngine, (ichunkaccess) -> { - return this.protoChunkToFullChunk(holder); -@@ -658,6 +663,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -708,6 +713,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider ChunkStatus chunkstatus = ChunkHolder.getStatus(playerchunk.getTicketLevel()); return !chunkstatus.isOrAfter(ChunkStatus.FULL) ? ChunkHolder.UNLOADED_CHUNK : either.mapLeft((ichunkaccess) -> { + try (Timing ignored = level.timings.chunkPostLoad.startTimingIfSync()) { // Paper ChunkPos chunkcoordintpair = playerchunk.getPos(); + ProtoChunk protochunk = (ProtoChunk) ichunkaccess; LevelChunk chunk; - -@@ -717,6 +723,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -731,6 +737,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } return chunk; @@ -1136,7 +1127,7 @@ index d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465..59a5f82c9f57d760ba4959a040ce8cbf }); }, (runnable) -> { ProcessorHandle mailbox = this.mainThreadMailbox; -@@ -1175,6 +1182,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1188,6 +1195,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider ChunkMap.TrackedEntity playerchunkmap_entitytracker; ObjectIterator objectiterator; @@ -1144,7 +1135,7 @@ index d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465..59a5f82c9f57d760ba4959a040ce8cbf for (objectiterator = this.entityMap.values().iterator(); objectiterator.hasNext(); playerchunkmap_entitytracker.serverEntity.sendChanges()) { playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); -@@ -1192,16 +1200,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1205,16 +1213,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider playerchunkmap_entitytracker.lastSectionPos = sectionposition1; } } @@ -1164,28 +1155,30 @@ index d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465..59a5f82c9f57d760ba4959a040ce8cbf + } - protected void broadcast(Entity entity, Packet packet) { + public void broadcast(Entity entity, Packet packet) { diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index ef336645f3bd7a86129ad1dff7e1a15dc93d1e3e..d0b0fdaf5451bcc7f7ac7dab28aa59ef77e6dd97 100644 +index 2cc633e6d03ae37a6d0785e0a3dcc4fe9350b10a..2cea8b1e8c414c8715ce61d61168dfb9d5c2200c 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -344,11 +344,13 @@ public class ServerChunkCache extends ChunkSource { +@@ -349,13 +349,15 @@ public class ServerChunkCache extends ChunkSource { } gameprofilerfiller.incrementCounter("getChunkCacheMiss"); - level.timings.syncChunkLoadTimer.startTiming(); // Spigot CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); + ServerChunkCache.MainThreadExecutor chunkproviderserver_a = this.mainThreadProcessor; + Objects.requireNonNull(completablefuture); + if (!completablefuture.isDone()) { // Paper + this.level.timings.syncChunkLoad.startTiming(); // Paper - this.mainThreadProcessor.managedBlock(completablefuture::isDone); + chunkproviderserver_a.managedBlock(completablefuture::isDone); - level.timings.syncChunkLoadTimer.stopTiming(); // Spigot + this.level.timings.syncChunkLoad.stopTiming(); // Paper + } // Paper ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { return ichunkaccess1; }, (playerchunk_failure) -> { -@@ -536,7 +538,9 @@ public class ServerChunkCache extends ChunkSource { +@@ -555,7 +557,9 @@ public class ServerChunkCache extends ChunkSource { public void save(boolean flush) { this.runDistanceManagerUpdates(); @@ -1195,7 +1188,7 @@ index ef336645f3bd7a86129ad1dff7e1a15dc93d1e3e..d0b0fdaf5451bcc7f7ac7dab28aa59ef } @Override -@@ -573,7 +577,9 @@ public class ServerChunkCache extends ChunkSource { +@@ -593,7 +597,9 @@ public class ServerChunkCache extends ChunkSource { this.runDistanceManagerUpdates(); this.level.timings.doChunkMap.stopTiming(); // Spigot this.level.getProfiler().popPush("chunks"); @@ -1204,8 +1197,8 @@ index ef336645f3bd7a86129ad1dff7e1a15dc93d1e3e..d0b0fdaf5451bcc7f7ac7dab28aa59ef + this.level.timings.chunks.stopTiming(); // Paper - timings this.level.timings.doChunkUnload.startTiming(); // Spigot this.level.getProfiler().popPush("unload"); - this.chunkMap.tick(shouldKeepTicking); -@@ -597,19 +603,24 @@ public class ServerChunkCache extends ChunkSource { + this.chunkMap.tick(booleansupplier); +@@ -617,13 +623,16 @@ public class ServerChunkCache extends ChunkSource { boolean flag2 = level.ticksPerAnimalSpawns != 0L && worlddata.getGameTime() % level.ticksPerAnimalSpawns == 0L; // CraftBukkit this.level.getProfiler().push("naturalSpawnCount"); @@ -1222,24 +1215,25 @@ index ef336645f3bd7a86129ad1dff7e1a15dc93d1e3e..d0b0fdaf5451bcc7f7ac7dab28aa59ef this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); - if (optional.isPresent()) { +@@ -631,7 +640,9 @@ public class ServerChunkCache extends ChunkSource { this.level.getProfiler().push("broadcast"); + LevelChunk chunk = (LevelChunk) optional.get(); + + this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timings - playerchunk.broadcastChanges((LevelChunk) optional.get()); + playerchunk.broadcastChanges(chunk); + this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings this.level.getProfiler().pop(); - Optional optional1 = ((Either) playerchunk.getEntityTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + ChunkPos chunkcoordintpair = chunk.getPos(); -@@ -623,25 +634,26 @@ public class ServerChunkCache extends ChunkSource { - NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); - } - -- this.level.timings.doTickTiles.startTiming(); // Spigot -+ //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper - this.level.tickChunk(chunk, k); -- this.level.timings.doTickTiles.stopTiming(); // Spigot -+ //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper +@@ -641,24 +652,25 @@ public class ServerChunkCache extends ChunkSource { + NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); } + +- this.level.timings.doTickTiles.startTiming(); // Spigot ++ // this.level.timings.doTickTiles.startTiming(); // Spigot // Paper + this.level.tickChunk(chunk, k); +- this.level.timings.doTickTiles.stopTiming(); // Spigot ++ // this.level.timings.doTickTiles.stopTiming(); // Spigot // Paper } } }); @@ -1262,19 +1256,19 @@ index ef336645f3bd7a86129ad1dff7e1a15dc93d1e3e..d0b0fdaf5451bcc7f7ac7dab28aa59ef private void getFullChunk(long pos, Consumer chunkConsumer) { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 34ed8f0d348e7bc2339660ebc6490057ba9ef214..0cc86ca4ea4a2e1b5acc3c0507397eef85dec0c1 100644 +index d7bf5d3bb3524410e49bd54372ddd7613ec0dd4b..c89c983e6f64718dabb2893996f7eb4a111c97c9 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -2,6 +2,8 @@ package net.minecraft.server.level; +@@ -1,6 +1,8 @@ + package net.minecraft.server.level; import com.google.common.annotations.VisibleForTesting; - import com.google.common.collect.Iterables; +import co.aikar.timings.TimingHistory; // Paper +import co.aikar.timings.Timings; // Paper import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Queues; -@@ -147,7 +149,6 @@ import org.apache.logging.log4j.Logger; + import com.mojang.datafixers.DataFixer; + import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +@@ -158,7 +160,6 @@ import org.apache.logging.log4j.Logger; import java.util.logging.Level; import org.bukkit.Bukkit; import org.bukkit.WeatherType; @@ -1282,20 +1276,23 @@ index 34ed8f0d348e7bc2339660ebc6490057ba9ef214..0cc86ca4ea4a2e1b5acc3c0507397eef import org.bukkit.craftbukkit.event.CraftEventFactory; import org.bukkit.craftbukkit.util.WorldUUID; import org.bukkit.event.entity.CreatureSpawnEvent; -@@ -203,10 +204,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - // CraftBukkit end - this.blockTicks = new ServerTickList<>(this, (block) -> { - return block == null || block.defaultBlockState().isAir(); -- }, Registry.BLOCK::getKey, this::tickBlock); -+ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings - this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { +@@ -221,13 +222,13 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + DefaultedRegistry registryblocks = Registry.BLOCK; + + Objects.requireNonNull(registryblocks); +- this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock); // CraftBukkit - decompile error ++ this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings + Predicate predicate2 = (fluidtype) -> { // CraftBukkit - decompile error return fluidtype == null || fluidtype == Fluids.EMPTY; -- }, Registry.FLUID::getKey, this::tickLiquid); -+ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings - this.navigations = Sets.newHashSet(); + }; + registryblocks = Registry.FLUID; + Objects.requireNonNull(registryblocks); +- this.liquidTicks = new ServerTickList<>(this, predicate2, Registry.FLUID::getKey, this::tickLiquid); // CraftBukkit - decompile error ++ this.liquidTicks = new ServerTickList<>(this, predicate2, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // CraftBukkit - decompile error // Paper - Timings + this.navigatingMobs = new ObjectOpenHashSet(); this.blockEvents = new ObjectLinkedOpenHashSet(); - this.tickTime = flag1; -@@ -436,17 +437,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.dragonParts = new Int2ObjectOpenHashMap(); +@@ -469,17 +470,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl this.updateSkyBrightness(); this.tickTime(); gameprofilerfiller.popPush("chunkSource"); @@ -1319,7 +1316,7 @@ index 34ed8f0d348e7bc2339660ebc6490057ba9ef214..0cc86ca4ea4a2e1b5acc3c0507397eef gameprofilerfiller.popPush("blockEvents"); timings.doSounds.startTiming(); // Spigot this.runBlockEvents(); -@@ -618,6 +623,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -637,6 +642,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } gameprofilerfiller.popPush("tickBlocks"); @@ -1327,7 +1324,7 @@ index 34ed8f0d348e7bc2339660ebc6490057ba9ef214..0cc86ca4ea4a2e1b5acc3c0507397eef if (randomTickSpeed > 0) { LevelChunkSection[] achunksection = chunk.getSections(); int l = achunksection.length; -@@ -649,7 +655,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -668,7 +674,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } } } @@ -1336,40 +1333,41 @@ index 34ed8f0d348e7bc2339660ebc6490057ba9ef214..0cc86ca4ea4a2e1b5acc3c0507397eef gameprofilerfiller.pop(); } -@@ -747,14 +753,22 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - if (!(entity instanceof Player) && !this.getChunkSource().isEntityTickingChunk(entity)) { - this.updateChunkPos(entity); - } else { -+ ++TimingHistory.entityTicks; // Paper - timings - // Spigot start -+ co.aikar.timings.Timing timer; // Paper - if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { - entity.tickCount++; -+ timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings - entity.inactiveTick(); -+ } finally { timer.stopTiming(); } // Paper - return; - } - // Spigot end -- entity.tickTimer.startTiming(); // Spigot -+ // Paper start- timings -+ TimingHistory.activatedEntityTicks++; -+ timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); -+ try { -+ // Paper end - timings - entity.setPosAndOldPos(entity.getX(), entity.getY(), entity.getZ()); - entity.yRotO = entity.yRot; - entity.xRotO = entity.xRot; -@@ -781,7 +795,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.tickPassenger(entity, entity1); - } - } -- entity.tickTimer.stopTiming(); // Spigot -+ } finally { timer.stopTiming(); } // Paper - timings - - } +@@ -794,14 +800,22 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } -@@ -859,6 +873,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + public void tickNonPassenger(Entity entity) { ++ ++TimingHistory.entityTicks; // Paper - timings + // Spigot start ++ co.aikar.timings.Timing timer; // Paper + if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { + entity.tickCount++; ++ timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings + entity.inactiveTick(); ++ } finally { timer.stopTiming(); } // Paper + return; + } + // Spigot end +- entity.tickTimer.startTiming(); // Spigot ++ // Paper start- timings ++ TimingHistory.activatedEntityTicks++; ++ timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); ++ try { ++ // Paper end - timings + entity.isInLava(); + ProfilerFiller gameprofilerfiller = this.getProfiler(); + +@@ -820,7 +834,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + this.tickPassenger(entity, entity1); + } +- entity.tickTimer.stopTiming(); // Spigot ++ ++ } finally { timer.stopTiming(); } // Paper - timings + + } + +@@ -862,6 +877,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl if (!flag1) { org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit @@ -1377,19 +1375,19 @@ index 34ed8f0d348e7bc2339660ebc6490057ba9ef214..0cc86ca4ea4a2e1b5acc3c0507397eef if (progressListener != null) { progressListener.progressStartNoAbort(new TranslatableComponent("menu.savingLevel")); } -@@ -868,7 +883,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -871,7 +887,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl progressListener.progressStage(new TranslatableComponent("menu.savingChunks")); } -+ timings.worldSaveChunks.startTiming(); // Paper ++ timings.worldSaveChunks.startTiming(); // Paper chunkproviderserver.save(flush); -+ timings.worldSaveChunks.stopTiming(); // Paper -+ } // Paper - } - - // CraftBukkit start - moved from MinecraftServer.saveChunks ++ timings.worldSaveChunks.stopTiming(); // Paper ++ }// Paper + if (flush) { + this.entityManager.saveAll(); + } else { diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 35f3940cebb00ee29da54b1ee148ee931fa11636..466c4322803bedf1fa61be281b954bf94fb8ff02 100644 +index ef8e601412933c7065ce1968b45381b02b14275a..4ada0aaca513cbac51b93b298f4e2587de46f0d8 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -209,6 +209,7 @@ import org.bukkit.inventory.EquipmentSlot; @@ -1399,8 +1397,8 @@ index 35f3940cebb00ee29da54b1ee148ee931fa11636..466c4322803bedf1fa61be281b954bf9 +import co.aikar.timings.MinecraftTimings; // Paper // CraftBukkit end - public class ServerGamePacketListenerImpl implements ServerGamePacketListener { -@@ -291,7 +292,6 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + public class ServerGamePacketListenerImpl implements ServerPlayerConnection, ServerGamePacketListener { +@@ -288,7 +289,6 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // CraftBukkit end public void tick() { @@ -1408,7 +1406,7 @@ index 35f3940cebb00ee29da54b1ee148ee931fa11636..466c4322803bedf1fa61be281b954bf9 this.resetPosition(); this.player.xo = this.player.getX(); this.player.yo = this.player.getY(); -@@ -367,7 +367,6 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -364,7 +364,6 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling")); } @@ -1416,7 +1414,7 @@ index 35f3940cebb00ee29da54b1ee148ee931fa11636..466c4322803bedf1fa61be281b954bf9 } -@@ -1915,7 +1914,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1921,7 +1920,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // CraftBukkit end private void handleCommand(String input) { @@ -1425,8 +1423,8 @@ index 35f3940cebb00ee29da54b1ee148ee931fa11636..466c4322803bedf1fa61be281b954bf9 // CraftBukkit start - whole method if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + input); -@@ -1926,7 +1925,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - this.craftServer.getPluginManager().callEvent(event); +@@ -1932,7 +1931,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + this.cserver.getPluginManager().callEvent(event); if (event.isCancelled()) { - org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot @@ -1434,7 +1432,7 @@ index 35f3940cebb00ee29da54b1ee148ee931fa11636..466c4322803bedf1fa61be281b954bf9 return; } -@@ -1939,7 +1938,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1945,7 +1944,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); return; } finally { @@ -1444,7 +1442,7 @@ index 35f3940cebb00ee29da54b1ee148ee931fa11636..466c4322803bedf1fa61be281b954bf9 // this.minecraftServer.getCommandDispatcher().a(this.player.getCommandListener(), s); // CraftBukkit end diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 28121e2fee9d862057042261d25360f0d4ee4530..88af57699d7f9e45ad1366243049e4f3565703ff 100644 +index 01f3267c086837cbbc311d62974ecb034e429c23..34e386efda7ea52fb6f53333eda0f015b0666ff3 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -1,5 +1,6 @@ @@ -1454,7 +1452,7 @@ index 28121e2fee9d862057042261d25360f0d4ee4530..88af57699d7f9e45ad1366243049e4f3 import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -@@ -1018,10 +1019,11 @@ public abstract class PlayerList { +@@ -1002,10 +1003,11 @@ public abstract class PlayerList { } public void saveAll() { @@ -1468,10 +1466,10 @@ index 28121e2fee9d862057042261d25360f0d4ee4530..88af57699d7f9e45ad1366243049e4f3 public UserWhiteList getWhiteList() { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b633f6b3a36b793e6dbc1b8b554bfba74c719570..2a7f587e19fcdd6d01b360d6b47d9eadd9df92cc 100644 +index b494980b4a3303b2f19002d44f81a2707e6916a5..c8ebce55b4e3838bf70b115ffb0b634b3548a7dd 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -115,7 +115,6 @@ import org.bukkit.craftbukkit.event.CraftPortalEvent; +@@ -126,7 +126,6 @@ import org.bukkit.craftbukkit.event.CraftPortalEvent; import org.bukkit.entity.Hanging; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Vehicle; @@ -1479,7 +1477,7 @@ index b633f6b3a36b793e6dbc1b8b554bfba74c719570..2a7f587e19fcdd6d01b360d6b47d9ead import org.bukkit.event.entity.EntityCombustByEntityEvent; import org.bukkit.event.hanging.HangingBreakByEntityEvent; import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; -@@ -247,7 +246,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -281,7 +280,6 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only public boolean forceExplosionKnockback; // SPIGOT-949 public boolean persistentInvisibility = false; @@ -1487,50 +1485,52 @@ index b633f6b3a36b793e6dbc1b8b554bfba74c719570..2a7f587e19fcdd6d01b360d6b47d9ead // Spigot start public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); public final boolean defaultActivationState; -@@ -616,7 +614,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -716,7 +714,6 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } - public void move(MoverType type, Vec3 movement) { + public void move(MoverType movementType, Vec3 movement) { - org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot if (this.noPhysics) { - this.setBoundingBox(this.getBoundingBox().move(movement)); - this.setLocationFromBoundingbox(); -@@ -752,7 +749,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - - this.level.getProfiler().pop(); + this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z); + } else { +@@ -863,7 +860,6 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + this.level.getProfiler().pop(); + } } - org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot } - protected BlockPos getOnPos() { + protected void tryCheckInsideBlocks() { diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index 2cb86de4bfc87a709f0cfa2c4e550d8e7928a3f0..e3d92d1d35911b2960a7ca82bd4f324d285d0533 100644 +index 3ffaeb72be8cda7a2b9398b8909db5c220e8b6c9..9f5f2bd9bdfce14da030b09f56c821ec1989e12f 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -281,17 +281,27 @@ public class EntityType { +@@ -295,17 +295,29 @@ public class EntityType implements EntityTypeTest { return Registry.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(id)); } -- public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet immutableset, EntityDimensions entitysize, int i, int j) { +- public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet canSpawnInside, EntityDimensions dimensions, int maxTrackDistance, int trackTickInterval) { - this.factory = factory; - this.category = spawnGroup; - this.canSpawnFarFromPlayer = spawnableFarFromPlayer; - this.serialize = saveable; - this.summon = summonable; - this.fireImmune = fireImmune; ++ public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet canSpawnInside, EntityDimensions dimensions, int maxTrackDistance, int trackTickInterval) { this(factory, spawnGroup, saveable, summonable, fireImmune, spawnableFarFromPlayer, canSpawnInside, dimensions, maxTrackDistance, trackTickInterval, "custom"); } // Paper - old signature ++ + public final String id; -+ public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet immutableset, EntityDimensions entitysize, int i, int j) { this(factory, spawnGroup, saveable, summonable, fireImmune, spawnableFarFromPlayer, immutableset, entitysize, i, j, "custom"); } // Paper - old signature -+ public EntityType(EntityType.EntityFactory entitytypes_b, MobCategory enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntityDimensions entitysize, int i, int j, String id) { // Paper - add id ++ ++ public EntityType(EntityType.EntityFactory entitytypes_b, MobCategory enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet canSpawnInside, EntityDimensions dimensions, int maxTrackDistance, int trackTickInterval, String id) { // Paper - add id + this.factory = entitytypes_b; + this.category = enumcreaturetype; + this.canSpawnFarFromPlayer = flag3; + this.serialize = flag; + this.summon = flag1; + this.fireImmune = flag2; - this.immuneTo = immutableset; - this.dimensions = entitysize; - this.clientTrackingRange = i; - this.updateInterval = j; + this.immuneTo = canSpawnInside; + this.dimensions = dimensions; + this.clientTrackingRange = maxTrackDistance; + this.updateInterval = trackTickInterval; + + // Paper start - timings + this.id = id; @@ -1542,7 +1542,15 @@ index 2cb86de4bfc87a709f0cfa2c4e550d8e7928a3f0..e3d92d1d35911b2960a7ca82bd4f324d } @Nullable -@@ -512,6 +522,12 @@ public class EntityType { +@@ -463,7 +475,6 @@ public class EntityType implements EntityTypeTest { + return this.dimensions.height; + } + +- public T create(Level world) { return this.create(world); } // Paper - OBFHELPER + @Nullable public T create(Level world) { // Paper - OBFHELPER + return this.factory.create(this, world); + } +@@ -569,6 +580,12 @@ public class EntityType implements EntityTypeTest { return this.updateInterval; } @@ -1553,9 +1561,9 @@ index 2cb86de4bfc87a709f0cfa2c4e550d8e7928a3f0..e3d92d1d35911b2960a7ca82bd4f324d + public final co.aikar.timings.Timing passengerInactiveTickTimer; + // Paper end public boolean trackDeltas() { - return this != EntityType.PLAYER && this != EntityType.LLAMA_SPIT && this != EntityType.WITHER && this != EntityType.BAT && this != EntityType.ITEM_FRAME && this != EntityType.LEASH_KNOT && this != EntityType.PAINTING && this != EntityType.END_CRYSTAL && this != EntityType.EVOKER_FANGS; + return this != EntityType.PLAYER && this != EntityType.LLAMA_SPIT && this != EntityType.WITHER && this != EntityType.BAT && this != EntityType.ITEM_FRAME && this != EntityType.GLOW_ITEM_FRAME && this != EntityType.LEASH_KNOT && this != EntityType.PAINTING && this != EntityType.END_CRYSTAL && this != EntityType.EVOKER_FANGS; } -@@ -599,7 +615,7 @@ public class EntityType { +@@ -661,7 +678,7 @@ public class EntityType implements EntityTypeTest { Util.fetchChoiceType(References.ENTITY_TREE, id); } @@ -1565,10 +1573,10 @@ index 2cb86de4bfc87a709f0cfa2c4e550d8e7928a3f0..e3d92d1d35911b2960a7ca82bd4f324d } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 9e5dde73bd65bf4e51352c628fba024c36e29ef1..e5f8cee6726ea9a90c540bb10fd8594a35bb5e40 100644 +index 3b2b57f5049d26a14e45eb4ec88a5b498005d372..ebe33c891e25c729c4373190da86c7a8198b6a55 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -132,7 +132,7 @@ import org.bukkit.event.entity.EntityTeleportEvent; +@@ -140,7 +140,7 @@ import org.bukkit.event.entity.EntityTeleportEvent; import org.bukkit.event.player.PlayerItemConsumeEvent; // CraftBukkit end @@ -1577,7 +1585,7 @@ index 9e5dde73bd65bf4e51352c628fba024c36e29ef1..e5f8cee6726ea9a90c540bb10fd8594a public abstract class LivingEntity extends Entity { -@@ -2455,7 +2455,6 @@ public abstract class LivingEntity extends Entity { +@@ -2758,7 +2758,6 @@ public abstract class LivingEntity extends Entity { @Override public void tick() { @@ -1585,7 +1593,7 @@ index 9e5dde73bd65bf4e51352c628fba024c36e29ef1..e5f8cee6726ea9a90c540bb10fd8594a super.tick(); this.updatingUsingItem(); this.updateSwimAmount(); -@@ -2504,9 +2503,7 @@ public abstract class LivingEntity extends Entity { +@@ -2799,9 +2798,7 @@ public abstract class LivingEntity extends Entity { } } @@ -1595,16 +1603,16 @@ index 9e5dde73bd65bf4e51352c628fba024c36e29ef1..e5f8cee6726ea9a90c540bb10fd8594a double d0 = this.getX() - this.xo; double d1 = this.getZ() - this.zo; float f = (float) (d0 * d0 + d1 * d1); -@@ -2586,8 +2583,6 @@ public abstract class LivingEntity extends Entity { +@@ -2881,8 +2878,6 @@ public abstract class LivingEntity extends Entity { if (this.isSleeping()) { - this.xRot = 0.0F; + this.setXRot(0.0F); } - - SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot } public void detectEquipmentUpdates() { -@@ -2769,7 +2764,6 @@ public abstract class LivingEntity extends Entity { +@@ -3064,7 +3059,6 @@ public abstract class LivingEntity extends Entity { this.setDeltaMovement(d4, d5, d6); this.level.getProfiler().push("ai"); @@ -1612,7 +1620,7 @@ index 9e5dde73bd65bf4e51352c628fba024c36e29ef1..e5f8cee6726ea9a90c540bb10fd8594a if (this.isImmobile()) { this.jumping = false; this.xxa = 0.0F; -@@ -2779,7 +2773,6 @@ public abstract class LivingEntity extends Entity { +@@ -3074,7 +3068,6 @@ public abstract class LivingEntity extends Entity { this.serverAiStep(); this.level.getProfiler().pop(); } @@ -1620,7 +1628,7 @@ index 9e5dde73bd65bf4e51352c628fba024c36e29ef1..e5f8cee6726ea9a90c540bb10fd8594a this.level.getProfiler().pop(); this.level.getProfiler().push("jump"); -@@ -2814,9 +2807,9 @@ public abstract class LivingEntity extends Entity { +@@ -3109,9 +3102,9 @@ public abstract class LivingEntity extends Entity { this.updateFallFlying(); AABB axisalignedbb = this.getBoundingBox(); @@ -1630,9 +1638,9 @@ index 9e5dde73bd65bf4e51352c628fba024c36e29ef1..e5f8cee6726ea9a90c540bb10fd8594a - SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot + // SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot // Paper this.level.getProfiler().pop(); - this.level.getProfiler().push("push"); - if (this.autoSpinAttackTicks > 0) { -@@ -2824,9 +2817,7 @@ public abstract class LivingEntity extends Entity { + this.level.getProfiler().push("freezing"); + boolean flag1 = this.getType().is((Tag) EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES); +@@ -3140,9 +3133,7 @@ public abstract class LivingEntity extends Entity { this.checkAutoSpinAttack(axisalignedbb, this.getBoundingBox()); } @@ -1643,18 +1651,10 @@ index 9e5dde73bd65bf4e51352c628fba024c36e29ef1..e5f8cee6726ea9a90c540bb10fd8594a if (!this.level.isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { this.hurt(DamageSource.DROWN, 1.0F); diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 5cc4c2668df72f83fb1526f4586b71d2ae0103dc..c153df1f4dea3dc0ae744bde01e334b3bd3b50af 100644 +index c9c8ce20e3adff1fe49489a6ac2d2e6be2795949..931a22bfce05716d6a6c0030c790f2338f7edd9f 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -70,7 +70,6 @@ import org.apache.logging.log4j.Logger; - import java.util.HashMap; - import java.util.Map; - import org.bukkit.Bukkit; --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.block.CapturedBlockState; -@@ -132,7 +131,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -149,7 +149,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper @@ -1663,25 +1663,25 @@ index 5cc4c2668df72f83fb1526f4586b71d2ae0103dc..c153df1f4dea3dc0ae744bde01e334b3 public static BlockPos lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; private org.spigotmc.TickLimiter tileLimiter; -@@ -217,7 +216,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) {} +@@ -236,7 +236,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } }); // CraftBukkit end -- timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings +- this.timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings + timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); } -@@ -797,15 +796,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } +@@ -721,15 +721,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - timings.tileEntityPending.stopTiming(); // Spigot -+ co.aikar.timings.TimingHistory.tileEntityTicks += this.tickableBlockEntities.size(); // Paper + timings.tileEntityTick.stopTiming(); // Spigot + this.tickingBlockEntities = false; ++ co.aikar.timings.TimingHistory.tileEntityTicks += this.getBlockTicks().size(); // Paper gameprofilerfiller.pop(); spigotConfig.currentPrimedTnt = 0; // Spigot } - public void guardEntityTick(Consumer tickConsumer, Entity entity) { + public void guardEntityTick(Consumer tickConsumer, T entity) { try { - SpigotTimings.tickEntityTimer.startTiming(); // Spigot tickConsumer.accept(entity); @@ -1690,22 +1690,23 @@ index 5cc4c2668df72f83fb1526f4586b71d2ae0103dc..c153df1f4dea3dc0ae744bde01e334b3 CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); diff --git a/src/main/java/net/minecraft/world/level/ServerTickList.java b/src/main/java/net/minecraft/world/level/ServerTickList.java -index 0519d5adf392dd46b4a93c5c1b977c8355163c2e..10ac1ba0a3d192486f22c2127d5bc30353f0edb6 100644 +index 0be0c9a9f29f29e2622df49861d30a7edbaf0515..702203f4a4fa4fc03c35ec974a97e08ed0f3c67c 100644 --- a/src/main/java/net/minecraft/world/level/ServerTickList.java +++ b/src/main/java/net/minecraft/world/level/ServerTickList.java -@@ -38,12 +38,17 @@ public class ServerTickList implements TickList { +@@ -37,12 +37,17 @@ public class ServerTickList implements TickList { private final List> alreadyTicked = Lists.newArrayList(); private final Consumer> ticker; -- public ServerTickList(ServerLevel world, Predicate invalidObjPredicate, Function idToName, Consumer> consumer) { +- public ServerTickList(ServerLevel world, Predicate invalidObjPredicate, Function idToName, Consumer> tickConsumer) { - this.ignore = invalidObjPredicate; - this.toId = idToName; - this.level = world; -+ public ServerTickList(ServerLevel worldserver, Predicate predicate, Function function, Consumer> consumer, String timingsType) { // Paper +- this.ticker = tickConsumer; ++ public ServerTickList(ServerLevel worldserver, Predicate predicate, Function function, Consumer> consumer, String timingsType) { + this.ignore = predicate; + this.toId = function; + this.level = worldserver; - this.ticker = consumer; ++ this.ticker = consumer; + this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Cleanup"); + this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Ticking"); } @@ -1715,7 +1716,7 @@ index 0519d5adf392dd46b4a93c5c1b977c8355163c2e..10ac1ba0a3d192486f22c2127d5bc303 public void tick() { int i = this.tickNextTickList.size(); -@@ -66,6 +71,7 @@ public class ServerTickList implements TickList { +@@ -64,6 +69,7 @@ public class ServerTickList implements TickList { this.level.getProfiler().push("cleaning"); @@ -1723,7 +1724,7 @@ index 0519d5adf392dd46b4a93c5c1b977c8355163c2e..10ac1ba0a3d192486f22c2127d5bc303 TickNextTickData nextticklistentry; while (i > 0 && iterator.hasNext()) { -@@ -81,7 +87,9 @@ public class ServerTickList implements TickList { +@@ -79,7 +85,9 @@ public class ServerTickList implements TickList { --i; } } @@ -1733,7 +1734,7 @@ index 0519d5adf392dd46b4a93c5c1b977c8355163c2e..10ac1ba0a3d192486f22c2127d5bc303 this.level.getProfiler().popPush("ticking"); while ((nextticklistentry = (TickNextTickData) this.currentlyTicking.poll()) != null) { -@@ -101,6 +109,7 @@ public class ServerTickList implements TickList { +@@ -99,6 +107,7 @@ public class ServerTickList implements TickList { } } @@ -1742,11 +1743,11 @@ index 0519d5adf392dd46b4a93c5c1b977c8355163c2e..10ac1ba0a3d192486f22c2127d5bc303 this.alreadyTicked.clear(); this.currentlyTicking.clear(); diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 73a271a1fccd6f82dac8d33c0d378f0d84ceb5e5..2ae786b8fc6da19ca2a40252b0606f9e06d31ded 100644 +index 198c1092e7db6e0023df77e4707c376696fdbafd..c27e755f93a2b2e203b305e0cae2c782a34e38cc 100644 --- a/src/main/java/net/minecraft/world/level/block/Block.java +++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -61,6 +61,15 @@ public class Block extends BlockBehaviour implements ItemLike { - }); +@@ -90,6 +90,15 @@ public class Block extends BlockBehaviour implements ItemLike { + public static final int UPDATE_LIMIT = 512; protected final StateDefinition stateDefinition; private BlockState defaultBlockState; + // Paper start @@ -1762,10 +1763,10 @@ index 73a271a1fccd6f82dac8d33c0d378f0d84ceb5e5..2ae786b8fc6da19ca2a40252b0606f9e private String descriptionId; @Nullable diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index bb60c9da9f3ba0d5c5bad22512675ccb841a60e5..d445a1b7b7605eed66923789c5d8e2199c31c5ac 100644 +index e4601134598e509a158ceacec6099a78bbabe89d..0e70d9df226e0843a943b3a57d1319ce1bca2543 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -23,10 +23,12 @@ import org.bukkit.inventory.InventoryHolder; +@@ -19,10 +19,12 @@ import org.bukkit.inventory.InventoryHolder; // CraftBukkit end import org.spigotmc.CustomTimingsHandler; // Spigot @@ -1780,54 +1781,55 @@ index bb60c9da9f3ba0d5c5bad22512675ccb841a60e5..d445a1b7b7605eed66923789c5d8e219 private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); public CraftPersistentDataContainer persistentDataContainer; diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 00ce55c17980da87a3834f952475a766543506b0..f30793b81dfd9018b4879d655c7c18a9f9c25267 100644 +index 57f32618d6c95734fa4b45274afaf2319c7608ae..0aa56efbfe42cad7840dae2f1f8ab3dc365128fd 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -732,6 +732,7 @@ public class LevelChunk implements ChunkAccess { +@@ -725,6 +725,7 @@ public class LevelChunk implements ChunkAccess { server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(this.bukkitChunk, this.needsDecoration)); if (this.needsDecoration) { + try (co.aikar.timings.Timing ignored = this.world.timings.chunkLoadPopulate.startTiming()) { // Paper this.needsDecoration = false; java.util.Random random = new java.util.Random(); - random.setSeed(world.getSeed()); -@@ -751,6 +752,7 @@ public class LevelChunk implements ChunkAccess { + random.setSeed(this.level.getSeed()); +@@ -744,6 +745,7 @@ public class LevelChunk implements ChunkAccess { } } - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); + server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(this.bukkitChunk)); + } // Paper } } } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 7e13a438bd80ab5452eacf107d418c42c2e5c727..0efaf4d0f58bcf38b427e76bf09b96e354294159 100644 +index 468b67babc628f7ff7c6fa138ed7944a8d77f0a6..22d5c4cc3aea19cbf53ea320765ecceb4daf7428 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -1,5 +1,6 @@ +@@ -1,5 +1,7 @@ package net.minecraft.world.level.chunk.storage; ++ +import co.aikar.timings.Timings; import com.google.common.collect.Maps; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import it.unimi.dsi.fastutil.longs.LongSet; -@@ -446,7 +447,6 @@ public class ChunkSerializer { - private static void postLoadChunk(CompoundTag tag, LevelChunk chunk) { - ListTag nbttaglist = tag.getList("Entities", 10); - Level world = chunk.getLevel(); -- world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot +@@ -433,7 +435,6 @@ public class ChunkSerializer { + private static void postLoadChunk(ServerLevel world, CompoundTag nbt, LevelChunk chunk) { + ListTag nbttaglist; - for (int i = 0; i < nbttaglist.size(); ++i) { - CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); -@@ -458,8 +458,6 @@ public class ChunkSerializer { - chunk.setLastSaveHadEntities(true); +- world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot + if (nbt.contains("Entities", 9)) { + nbttaglist = nbt.getList("Entities", 10); + if (!nbttaglist.isEmpty()) { +@@ -441,8 +442,6 @@ public class ChunkSerializer { + } } - world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot - world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot - ListTag nbttaglist1 = tag.getList("TileEntities", 10); + nbttaglist = nbt.getList("TileEntities", 10); - for (int j = 0; j < nbttaglist1.size(); ++j) { -@@ -477,8 +475,6 @@ public class ChunkSerializer { + for (int i = 0; i < nbttaglist.size(); ++i) { +@@ -460,8 +459,6 @@ public class ChunkSerializer { } } } @@ -1835,12 +1837,12 @@ index 7e13a438bd80ab5452eacf107d418c42c2e5c727..0efaf4d0f58bcf38b427e76bf09b96e3 - } - private static CompoundTag packStructureData(ChunkPos pos, Map, StructureStart> structureStarts, Map, LongSet> structureReferences) { + private static CompoundTag packStructureData(ServerLevel world, ChunkPos chunkcoordintpair, Map, StructureStart> map, Map, LongSet> map1) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 328d1e2b128b62f24917719c79823c9fb64a0dcf..c4cf1394fe4c2782b1fea8b3653a817157d857eb 100644 +index 743c9f11dbbb66db97bcb3b8fecd97290a7c9f61..c85f69cc6ef8a61ca1b07beb5f2b2159fbaa887d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2073,12 +2073,31 @@ public final class CraftServer implements Server { +@@ -2076,12 +2076,31 @@ public final class CraftServer implements Server { private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() { @@ -1872,182 +1874,13 @@ index 328d1e2b128b62f24917719c79823c9fb64a0dcf..c4cf1394fe4c2782b1fea8b3653a8171 @Override public void restart() { org.spigotmc.RestartCommand.restart(); -diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -deleted file mode 100644 -index 56b644e272ddad0e5410061e0a202daaebb734b8..0000000000000000000000000000000000000000 ---- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -+++ /dev/null -@@ -1,163 +0,0 @@ --package org.bukkit.craftbukkit; -- --import java.util.HashMap; --import net.minecraft.world.entity.Entity; --import net.minecraft.world.level.Level; --import net.minecraft.world.level.block.entity.BlockEntity; --import net.minecraft.world.level.storage.PrimaryLevelData; --import org.bukkit.craftbukkit.scheduler.CraftTask; --import org.bukkit.plugin.java.JavaPluginLoader; --import org.bukkit.scheduler.BukkitTask; --import org.spigotmc.CustomTimingsHandler; -- --public class SpigotTimings { -- -- public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); -- public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); -- public static final CustomTimingsHandler commandFunctionsTimer = new CustomTimingsHandler("Command Functions"); -- public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler"); -- public static final CustomTimingsHandler playerConnectionTimer = new CustomTimingsHandler("** PlayerConnection"); -- public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); -- public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); -- public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update"); -- public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command"); -- public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save"); -- -- public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); -- public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); -- public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); -- public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); -- -- public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); -- public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); -- public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); -- public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); -- public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); -- -- public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue"); -- public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer); -- -- public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); -- -- public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); -- public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); -- -- public static final HashMap entityTypeTimingMap = new HashMap(); -- public static final HashMap tileEntityTypeTimingMap = new HashMap(); -- public static final HashMap pluginTaskTimingMap = new HashMap(); -- -- /** -- * Gets a timer associated with a plugins tasks. -- * @param task -- * @param period -- * @return -- */ -- public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { -- if (!task.isSync()) { -- return null; -- } -- String plugin; -- final CraftTask ctask = (CraftTask) task; -- -- if (task.getOwner() != null) { -- plugin = task.getOwner().getDescription().getFullName(); -- } else { -- plugin = "Unknown"; -- } -- String taskname = ctask.getTaskName(); -- -- String name = "Task: " + plugin + " Runnable: " + taskname; -- if (period > 0) { -- name += "(interval:" + period + ")"; -- } else { -- name += "(Single)"; -- } -- CustomTimingsHandler result = pluginTaskTimingMap.get(name); -- if (result == null) { -- result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); -- pluginTaskTimingMap.put(name, result); -- } -- return result; -- } -- -- /** -- * Get a named timer for the specified entity type to track type specific timings. -- * @param entity -- * @return -- */ -- public static CustomTimingsHandler getEntityTimings(Entity entity) { -- String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = entityTypeTimingMap.get(entityType); -- if (result == null) { -- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), activatedEntityTimer); -- entityTypeTimingMap.put(entityType, result); -- } -- return result; -- } -- -- /** -- * Get a named timer for the specified tile entity type to track type specific timings. -- * @param entity -- * @return -- */ -- public static CustomTimingsHandler getTileEntityTimings(BlockEntity entity) { -- String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = tileEntityTypeTimingMap.get(entityType); -- if (result == null) { -- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), tickTileEntityTimer); -- tileEntityTypeTimingMap.put(entityType, result); -- } -- return result; -- } -- -- /** -- * Set of timers per world, to track world specific timings. -- */ -- public static class WorldTimingsHandler { -- public final CustomTimingsHandler mobSpawn; -- public final CustomTimingsHandler doChunkUnload; -- public final CustomTimingsHandler doTickPending; -- public final CustomTimingsHandler doTickTiles; -- public final CustomTimingsHandler doChunkMap; -- public final CustomTimingsHandler doSounds; -- public final CustomTimingsHandler entityTick; -- public final CustomTimingsHandler tileEntityTick; -- public final CustomTimingsHandler tileEntityPending; -- public final CustomTimingsHandler tracker; -- public final CustomTimingsHandler doTick; -- public final CustomTimingsHandler tickEntities; -- -- public final CustomTimingsHandler syncChunkLoadTimer; -- public final CustomTimingsHandler syncChunkLoadStructuresTimer; -- public final CustomTimingsHandler syncChunkLoadEntitiesTimer; -- public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer; -- public final CustomTimingsHandler syncChunkLoadTileTicksTimer; -- public final CustomTimingsHandler syncChunkLoadPostTimer; -- -- public WorldTimingsHandler(Level server) { -- String name = ((PrimaryLevelData) server.levelData).getLevelName() + " - "; -- -- mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); -- doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); -- doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); -- doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); -- doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); -- doSounds = new CustomTimingsHandler("** " + name + "doSounds"); -- entityTick = new CustomTimingsHandler("** " + name + "entityTick"); -- tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); -- tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending"); -- -- syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); -- syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); -- syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); -- syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); -- syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); -- syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); -- -- -- tracker = new CustomTimingsHandler(name + "tracker"); -- doTick = new CustomTimingsHandler(name + "doTick"); -- tickEntities = new CustomTimingsHandler(name + "tickEntities"); -- } -- } --} diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 8fbf6c56d8820f3fa86e70a2636c0b58043232c3..61e2d92471d1498eb97d42dc642605a2e00e6089 100644 +index 06d071d43337f2b919144a8db28684f4a3c826cf..457506210f041291be6bcdef7286d0860cb85946 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1806,6 +1806,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1810,6 +1810,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { packet.components = components; - getHandle().connection.send(packet); + CraftPlayer.this.getHandle().connection.send(packet); } + + // Paper start @@ -2061,7 +1894,7 @@ index 8fbf6c56d8820f3fa86e70a2636c0b58043232c3..61e2d92471d1498eb97d42dc642605a2 public Player.Spigot spigot() diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 4bf48f77f3f7cd62a91590543f5af441c8268029..ffe9cc1011226d604dc5499e7692e9a9a5132b72 100644 +index 2b4a922b84eeb2b1b64e43a2ca8bf16dcf58218e..e6a09ed5db245eaecd787503dbfb1ef5fea5bb70 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java @@ -1,5 +1,6 @@ @@ -2087,8 +1920,8 @@ index 4bf48f77f3f7cd62a91590543f5af441c8268029..ffe9cc1011226d604dc5499e7692e9a9 } - }); + }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer();}}; // Paper - handle(task, 0L); - for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { + this.handle(task, 0L); + for (CraftTask taskPending = this.head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { if (taskPending == task) { @@ -295,7 +297,7 @@ public class CraftScheduler implements BukkitScheduler { } @@ -2096,12 +1929,12 @@ index 4bf48f77f3f7cd62a91590543f5af441c8268029..ffe9cc1011226d604dc5499e7692e9a9 } - }); + }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer(plugin);}}; // Paper - handle(task, 0L); - for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { + this.handle(task, 0L); + for (CraftTask taskPending = this.head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { if (taskPending == task) { @@ -402,9 +404,7 @@ public class CraftScheduler implements BukkitScheduler { if (task.isSync()) { - currentTask = task; + this.currentTask = task; try { - task.timings.startTiming(); // Spigot task.run(); @@ -2110,14 +1943,14 @@ index 4bf48f77f3f7cd62a91590543f5af441c8268029..ffe9cc1011226d604dc5499e7692e9a9 // Paper start String msg = String.format( @@ -438,8 +438,10 @@ public class CraftScheduler implements BukkitScheduler { - runners.remove(task.getTaskId()); + this.runners.remove(task.getTaskId()); } } -+ MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); - pending.addAll(temp); ++ MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); // Paper + this.pending.addAll(temp); temp.clear(); -+ MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); - debugHead = debugHead.getNextHead(currentTick); ++ MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); // Paper + this.debugHead = this.debugHead.getNextHead(currentTick); } @@ -472,6 +474,7 @@ public class CraftScheduler implements BukkitScheduler { @@ -2137,7 +1970,7 @@ index 4bf48f77f3f7cd62a91590543f5af441c8268029..ffe9cc1011226d604dc5499e7692e9a9 private boolean isReady(final int currentTick) { diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -index 09aa6809c5400ce8548ac902908b750ce7c964ec..3c96807e97657502849093e4371e9fef3584a346 100644 +index aec92f03951ef15bdf8af84b9b1526a788fd7f4d..0da2c5ef6180fe4da1be7376ba0fb9d2e4efc2a7 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java @@ -1,12 +1,15 @@ @@ -2196,10 +2029,10 @@ index 09aa6809c5400ce8548ac902908b750ce7c964ec..3c96807e97657502849093e4371e9fef @Override public void run() { + try (Timing ignored = timings.startTiming()) { // Paper - if (rTask != null) { - rTask.run(); + if (this.rTask != null) { + this.rTask.run(); } else { - cTask.accept(this); + this.cTask.accept(this); } + } // Paper } @@ -2210,8 +2043,8 @@ index 09aa6809c5400ce8548ac902908b750ce7c964ec..3c96807e97657502849093e4371e9fef } - Class getTaskClass() { -+ public Class getTaskClass() { - return (rTask != null) ? rTask.getClass() : ((cTask != null) ? cTask.getClass() : null); ++ public Class getTaskClass() { // Paper + return (this.rTask != null) ? this.rTask.getClass() : ((this.cTask != null) ? this.cTask.getClass() : null); } @@ -147,9 +152,4 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot @@ -2220,7 +2053,7 @@ index 09aa6809c5400ce8548ac902908b750ce7c964ec..3c96807e97657502849093e4371e9fef - // Spigot start - public String getTaskName() { -- return (getTaskClass() == null) ? "Unknown" : getTaskClass().getName(); +- return (this.getTaskClass() == null) ? "Unknown" : this.getTaskClass().getName(); - } - // Spigot end } @@ -2237,7 +2070,7 @@ index e52ef47b783785dc214746b678e7b549aea9a274..3d90b3426873a3528af14f7f1ab0adae this.value = value; } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index ec3d663886eb134eb9ecc87e7517a73bcfb9ec02..ef7715774fbdc4c42b217d8192784e09a43fe66f 100644 +index 456f0e9e827f61ebdcb42dbc00f5d374e318597f..0f0ffedd2cc3cf1b30b338d8ae3a8ad388dfde53 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -156,6 +156,12 @@ public final class CraftMagicNumbers implements UnsafeValues { @@ -2268,19 +2101,19 @@ index ec3d663886eb134eb9ecc87e7517a73bcfb9ec02..ef7715774fbdc4c42b217d8192784e09 * This helper class represents the different NBT Tags. *

    diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index ac6fc546931f7884952058b42e7e3fab3ce42998..9bb35ec64e1538aabec9ff7831706c4717239449 100644 +index e73db1031c40f6bdf422dcefaa55721caf3cb4e9..f023f3a0d1671398363f0caa432ffb61fd07c9b2 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -29,7 +29,7 @@ import net.minecraft.world.entity.raid.Raider; +@@ -27,7 +27,7 @@ import net.minecraft.world.entity.projectile.ThrownTrident; + import net.minecraft.world.entity.raid.Raider; import net.minecraft.world.level.Level; - import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.phys.AABB; -import org.bukkit.craftbukkit.SpigotTimings; +import co.aikar.timings.MinecraftTimings; public class ActivationRange { -@@ -73,8 +73,8 @@ public class ActivationRange +@@ -71,8 +71,8 @@ public class ActivationRange /** * These entities are excluded from Activation range checks. * @@ -2291,7 +2124,7 @@ index ac6fc546931f7884952058b42e7e3fab3ce42998..9bb35ec64e1538aabec9ff7831706c47 * @return boolean If it should always tick. */ public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) -@@ -109,7 +109,7 @@ public class ActivationRange +@@ -107,7 +107,7 @@ public class ActivationRange */ public static void activateEntities(Level world) { @@ -2300,27 +2133,27 @@ index ac6fc546931f7884952058b42e7e3fab3ce42998..9bb35ec64e1538aabec9ff7831706c47 final int miscActivationRange = world.spigotConfig.miscActivationRange; final int raiderActivationRange = world.spigotConfig.raiderActivationRange; final int animalActivationRange = world.spigotConfig.animalActivationRange; -@@ -146,7 +146,7 @@ public class ActivationRange - } - } +@@ -130,7 +130,7 @@ public class ActivationRange + + world.getEntities().get(maxBB, ActivationRange::activateEntity); } - SpigotTimings.entityActivationCheckTimer.stopTiming(); + MinecraftTimings.entityActivationCheckTimer.stopTiming(); } /** -@@ -243,10 +243,8 @@ public class ActivationRange +@@ -221,10 +221,8 @@ public class ActivationRange */ public static boolean checkIfActive(Entity entity) { - SpigotTimings.checkIfActiveTimer.startTiming(); // Never safe to skip fireworks or entities not yet added to chunk - if ( !entity.inChunk || entity instanceof FireworkRocketEntity ) { + if ( entity instanceof FireworkRocketEntity ) { - SpigotTimings.checkIfActiveTimer.stopTiming(); return true; } -@@ -270,7 +268,6 @@ public class ActivationRange +@@ -248,7 +246,6 @@ public class ActivationRange { isActive = false; } From 82eb9fffc85492ec90c8fbbc5d51c2127e1c5b74 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 20:02:47 +0200 Subject: [PATCH 015/226] fix: up the max memory for gradle Signed-off-by: Mariell Hoversholm --- gradle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/gradle.properties b/gradle.properties index b26ff13432..c26ed1b3da 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,4 @@ mcVersion = 1.17 projectVersion = 1.17-R0.1-SNAPSHOT packageVersion = 1_17_R1 +org.gradle.jvmargs=-Xmx3G From 87ee3b4d67aabd9cb9489fbf8e36d707f681b428 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 20:06:01 +0200 Subject: [PATCH 016/226] fix: add pom changes to gradle Signed-off-by: Mariell Hoversholm --- patches/api/0002-POM-changes.patch | 17 +++++++++++++++++ patches/api/0003-Add-FastUtil-to-Bukkit.patch | 12 ++++++++++++ 2 files changed, 29 insertions(+) diff --git a/patches/api/0002-POM-changes.patch b/patches/api/0002-POM-changes.patch index b6c98e0a08..274e996a2c 100644 --- a/patches/api/0002-POM-changes.patch +++ b/patches/api/0002-POM-changes.patch @@ -4,6 +4,23 @@ Date: Tue, 1 Mar 2016 00:16:08 +0100 Subject: [PATCH] POM changes +diff --git a/build.gradle.kts b/build.gradle.kts +index a0f1c1d1ac63fdcce942922ffe68a8d44c712513..fd47081fbc8cc5d88a57689d1beee5eddc78f845 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -15,10 +15,12 @@ dependencies { + api("com.google.code.gson:gson:2.8.0") + api("net.md-5:bungeecord-chat:1.16-R0.4") + api("org.yaml:snakeyaml:1.29") ++ api("com.googlecode.json-simple:json-simple:1.1.1") // Paper + + compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") + compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") ++ compileOnly("com.google.code.findbugs:jsr305:1.3.9") // Paper + + val annotations = "org.jetbrains:annotations-java5:21.0.1" + compileOnly(annotations) diff --git a/pom.xml b/pom.xml index debe5bd7adb1f41e8a6878a8545de4bfcad1a590..d7cf64f05d0a2f5b186ca13b2b88e390abe84226 100644 --- a/pom.xml diff --git a/patches/api/0003-Add-FastUtil-to-Bukkit.patch b/patches/api/0003-Add-FastUtil-to-Bukkit.patch index 1a80b26e31..5ce84dd993 100644 --- a/patches/api/0003-Add-FastUtil-to-Bukkit.patch +++ b/patches/api/0003-Add-FastUtil-to-Bukkit.patch @@ -5,6 +5,18 @@ Subject: [PATCH] Add FastUtil to Bukkit Doesn't expose to plugins, just allows Paper-API to use it for optimization +diff --git a/build.gradle.kts b/build.gradle.kts +index fd47081fbc8cc5d88a57689d1beee5eddc78f845..95327c3971cd57e01da2a62e1b72ba15fcbb63f4 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -16,6 +16,7 @@ dependencies { + api("net.md-5:bungeecord-chat:1.16-R0.4") + api("org.yaml:snakeyaml:1.29") + api("com.googlecode.json-simple:json-simple:1.1.1") // Paper ++ api("it.unimi.dsi:fastutil:8.2.2") + + compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/pom.xml b/pom.xml index d7cf64f05d0a2f5b186ca13b2b88e390abe84226..1ebc4c096638128194cea9c2a4131f901e7d6896 100644 --- a/pom.xml From d8d7c8c8aa748456d281fb99918ead360b04ebbf Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 20:08:26 +0200 Subject: [PATCH 017/226] fix: remove empty java file Signed-off-by: Mariell Hoversholm --- patches/server/0009-Timings-v2.patch | 3 --- 1 file changed, 3 deletions(-) diff --git a/patches/server/0009-Timings-v2.patch b/patches/server/0009-Timings-v2.patch index 79950f0d62..383793b26f 100644 --- a/patches/server/0009-Timings-v2.patch +++ b/patches/server/0009-Timings-v2.patch @@ -4,9 +4,6 @@ Date: Thu, 3 Mar 2016 04:00:11 -0600 Subject: [PATCH] Timings v2 -diff --git a/src/main/java/SpigotTimings.java b/src/main/java/SpigotTimings.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java new file mode 100644 index 0000000000000000000000000000000000000000..be3a62f543a5fec4739c14821fe5a443c1fa3f5b From 9c2a18af9212249c195c3884ee6b3e1b5f6345cc Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 20:16:11 +0200 Subject: [PATCH 018/226] fix: remove #isStopping check Signed-off-by: Mariell Hoversholm --- patches/api/0005-Timings-v2.patch | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/patches/api/0005-Timings-v2.patch b/patches/api/0005-Timings-v2.patch index ec3f6cb55f..9d4a3c6e40 100644 --- a/patches/api/0005-Timings-v2.patch +++ b/patches/api/0005-Timings-v2.patch @@ -3,10 +3,12 @@ From: Aikar Date: Mon, 29 Feb 2016 18:48:17 -0600 Subject: [PATCH] Timings v2 +TODO: Add #isStopping to FullServerTickHandler#stopTiming in patch 191 +expose isRunning diff --git a/src/main/java/co/aikar/timings/FullServerTickHandler.java b/src/main/java/co/aikar/timings/FullServerTickHandler.java new file mode 100644 -index 0000000000000000000000000000000000000000..dfaa266ff53e43ad48dc5a5a5657fe70600f539a +index 0000000000000000000000000000000000000000..43b85ce3a6c27a2f92c67d62bee7484c2652b72a --- /dev/null +++ b/src/main/java/co/aikar/timings/FullServerTickHandler.java @@ -0,0 +1,85 @@ @@ -43,7 +45,7 @@ index 0000000000000000000000000000000000000000..dfaa266ff53e43ad48dc5a5a5657fe70 + @Override + public void stopTiming() { + super.stopTiming(); -+ if (!isEnabled() || Bukkit.isStopping()) { ++ if (!isEnabled()) { + return; + } + if (TimingHistory.timedTicks % 20 == 0) { From 088e980a8063f05009b885681b4a29e19399a232 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 20:26:56 +0200 Subject: [PATCH 019/226] fix: closer to compilable Signed-off-by: Mariell Hoversholm --- patches/server/0006-MC-Utils.patch | 58 +++++++--------------------- patches/server/0009-Timings-v2.patch | 28 ++++++-------- 2 files changed, 24 insertions(+), 62 deletions(-) diff --git a/patches/server/0006-MC-Utils.patch b/patches/server/0006-MC-Utils.patch index 35ee5a4ba9..cfdaa85ede 100644 --- a/patches/server/0006-MC-Utils.patch +++ b/patches/server/0006-MC-Utils.patch @@ -2348,7 +2348,7 @@ index f484cf19e1ed6f4e14a6c324c59511e822335ba7..f4b5792e080d5181184eb661d005ce6c return this.distSqr((double)vec.getX(), (double)vec.getY(), (double)vec.getZ(), true); } diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java -index 3d374000cd61d4a29dae21035c5ee9a93a1ff0f9..4760fc27b1d4938a248c05af17fc93ab37084c00 100644 +index 3d374000cd61d4a29dae21035c5ee9a93a1ff0f9..750df4ab2fbfdcf759f4d3451340e66b6764391d 100644 --- a/src/main/java/net/minecraft/nbt/CompoundTag.java +++ b/src/main/java/net/minecraft/nbt/CompoundTag.java @@ -60,7 +60,7 @@ public class CompoundTag implements Tag { @@ -2360,7 +2360,7 @@ index 3d374000cd61d4a29dae21035c5ee9a93a1ff0f9..4760fc27b1d4938a248c05af17fc93ab protected CompoundTag(Map entries) { this.tags = entries; -@@ -119,10 +119,16 @@ public class CompoundTag implements Tag { +@@ -119,10 +119,15 @@ public class CompoundTag implements Tag { this.tags.put(key, LongTag.valueOf(value)); } @@ -2373,7 +2373,6 @@ index 3d374000cd61d4a29dae21035c5ee9a93a1ff0f9..4760fc27b1d4938a248c05af17fc93ab + /** + * You must use {@link #hasUUID(String)} before or else it will throw an NPE. + */ -+ public UUID getUUID(String prefix) { return getUUID(prefix); } // Paper - OBFHELPER public UUID getUUID(String key) { return NbtUtils.loadUUID(this.get(key)); } @@ -2390,26 +2389,26 @@ index 0ae24c8080391410756f101a1e40c2eef887c739..3b8207046d38d3d14719ff6761a22e60 for (int j = 1; j < 5; ++j) { if ((value & -1 << j * 7) == 0) { diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index f189a72bd101a99d9350072a06953665fc5d6fee..02d253243eb66c30d4f7f6b0e7361518516eefec 100644 +index f189a72bd101a99d9350072a06953665fc5d6fee..83e99af925c87433b59f9bed30dfbf4e490c1b84 100644 --- a/src/main/java/net/minecraft/network/PacketEncoder.java +++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -46,6 +46,7 @@ public class PacketEncoder extends MessageToByteEncoder> { +@@ -45,7 +45,7 @@ public class PacketEncoder extends MessageToByteEncoder> { + throw new IllegalArgumentException("Packet too big (is " + j + ", should be less than 2097152): " + packet); } } catch (Throwable var9) { - LOGGER.error(var9); -+ throwable.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? +- LOGGER.error(var9); ++ LOGGER.error("Packet encoding of packet ID {} threw (skippable? {})", integer, packet.isSkippable(), var9); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? if (packet.isSkippable()) { throw new SkipPacketException(var9); } else { diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java new file mode 100644 -index 0000000000000000000000000000000000000000..d29fe67b7d39e368a873368a6be16042429e9209 +index 0000000000000000000000000000000000000000..80f8d6ce6dd717d4b37b78539c65b6ac814ec93d --- /dev/null +++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -0,0 +1,510 @@ +@@ -0,0 +1,496 @@ +package net.minecraft.server; + -+import com.destroystokyo.paper.block.TargetBlockInfo; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; +import net.minecraft.core.BlockPos; @@ -2885,19 +2884,6 @@ index 0000000000000000000000000000000000000000..d29fe67b7d39e368a873368a6be16042 + return getNMSWorld(entity.getWorld()); + } + -+ public static ClipContext.Fluid getNMSFluidCollisionOption(TargetBlockInfo.FluidMode fluidMode) { -+ if (fluidMode == TargetBlockInfo.FluidMode.NEVER) { -+ return ClipContext.Fluid.NONE; -+ } -+ if (fluidMode == TargetBlockInfo.FluidMode.SOURCE_ONLY) { -+ return ClipContext.Fluid.SOURCE_ONLY; -+ } -+ if (fluidMode == TargetBlockInfo.FluidMode.ALWAYS) { -+ return ClipContext.Fluid.ANY; -+ } -+ return null; -+ } -+ + public static BlockFace toBukkitBlockFace(Direction enumDirection) { + switch (enumDirection) { + case DOWN: @@ -4322,23 +4308,10 @@ index 1441888430687b9de2a67f21ed426f16d5b30538..2da42f1bc6922adae32d782aac780a7e public synchronized DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException { int i = this.getOffset(pos); diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java -index 120498a39b7ca7aee9763084507508d4a1c425aa..aa33a12b8b8ce6bb9a3278bcfa5b9017b3b432da 100644 +index 120498a39b7ca7aee9763084507508d4a1c425aa..4eeb186231551a9df453ec9d6a8a9dc9f8835464 100644 --- a/src/main/java/net/minecraft/world/phys/AABB.java +++ b/src/main/java/net/minecraft/world/phys/AABB.java -@@ -223,10 +223,12 @@ public class AABB { - return this.move(vec.x, vec.y, vec.z); - } - -+ public final boolean intersects(AABB axisalignedbb) { return this.intersects(axisalignedbb); } // Paper - OBFHELPER - public boolean intersects(AABB box) { - return this.intersects(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ); - } - -+ public final boolean intersects(double d0, double d1, double d2, double d3, double d4, double d5) { return intersects(d0, d1, d2, d3, d4, d5); } // Paper - OBFHELPER - public boolean intersects(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { - return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ; - } -@@ -243,6 +245,7 @@ public class AABB { +@@ -243,6 +243,7 @@ public class AABB { return x >= this.minX && x < this.maxX && y >= this.minY && y < this.maxY && z >= this.minZ && z < this.maxZ; } @@ -4347,15 +4320,10 @@ index 120498a39b7ca7aee9763084507508d4a1c425aa..aa33a12b8b8ce6bb9a3278bcfa5b9017 double d = this.getXsize(); double e = this.getYsize(); diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -index 5af90e0f7222356cb0e905a9b6e0c4eac5617a41..4f466cc1b196abdfd3a0282cae58f66de0a6be4f 100644 +index 5af90e0f7222356cb0e905a9b6e0c4eac5617a41..5d4d953f197afc402248ab73daeb6ef59134f48f 100644 --- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -@@ -30,10 +30,12 @@ public final class Shapes { - public static final VoxelShape INFINITY = box(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); - private static final VoxelShape EMPTY = new ArrayVoxelShape(new BitSetDiscreteVoxelShape(0, 0, 0), (DoubleList)(new DoubleArrayList(new double[]{0.0D})), (DoubleList)(new DoubleArrayList(new double[]{0.0D})), (DoubleList)(new DoubleArrayList(new double[]{0.0D}))); - -+ public static final VoxelShape empty() {return empty();} // Paper - OBFHELPER - public static VoxelShape empty() { +@@ -34,6 +34,7 @@ public final class Shapes { return EMPTY; } diff --git a/patches/server/0009-Timings-v2.patch b/patches/server/0009-Timings-v2.patch index 383793b26f..c9ed1235fa 100644 --- a/patches/server/0009-Timings-v2.patch +++ b/patches/server/0009-Timings-v2.patch @@ -6,13 +6,12 @@ Subject: [PATCH] Timings v2 diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java new file mode 100644 -index 0000000000000000000000000000000000000000..be3a62f543a5fec4739c14821fe5a443c1fa3f5b +index 0000000000000000000000000000000000000000..72f9e1978394afb6e5cc1c0d085d41586d69b84e --- /dev/null +++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -0,0 +1,152 @@ +@@ -0,0 +1,151 @@ +package co.aikar.timings; + -+import Timing; +import com.google.common.collect.MapMaker; +import net.minecraft.commands.CommandFunction; +import net.minecraft.network.protocol.Packet; @@ -164,10 +163,10 @@ index 0000000000000000000000000000000000000000..be3a62f543a5fec4739c14821fe5a443 +} diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java new file mode 100644 -index 0000000000000000000000000000000000000000..94adf0275a2e7093c152cc3b8b0a5747b3a13a86 +index 0000000000000000000000000000000000000000..2afec58d8eadc9357d8aa6b171d9249cdc5b8c4a --- /dev/null +++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -0,0 +1,380 @@ +@@ -0,0 +1,376 @@ +/* + * This file is licensed under the MIT License (MIT). + * @@ -230,9 +229,6 @@ index 0000000000000000000000000000000000000000..94adf0275a2e7093c152cc3b8b0a5747 +import static co.aikar.util.JSONUtil.toArrayMapper; +import static co.aikar.util.JSONUtil.toObjectMapper; + -+import TimingHistory; -+import TimingsReportListener; -+ +@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) +public class TimingsExport extends Thread { + @@ -282,9 +278,8 @@ index 0000000000000000000000000000000000000000..94adf0275a2e7093c152cc3b8b0a5747 + pair("end", System.currentTimeMillis() / 1000), + pair("online-mode", Bukkit.getServer().getOnlineMode()), + pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), -+ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedIds(), pack -> { -+ // Don't feel like obf helper'ing these, non fatal if its temp missed. -+ return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); ++ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedPacks(), pack -> { ++ return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.getChatLink(true))); + })) + ); + if (!TimingsManager.privacy) { @@ -321,12 +316,12 @@ index 0000000000000000000000000000000000000000..94adf0275a2e7093c152cc3b8b0a5747 + ); + + parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getAllLevels(), world -> { -+ if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; -+ return pair(world.getWorldData().getName(), createObject( ++ if (world.serverLevelData.getLevelName().equals("worldeditregentempworld")) return null; ++ return pair(world.serverLevelData.getLevelName(), createObject( + pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { + return pair(rule, world.getWorld().getGameRuleValue(rule)); + })), -+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) ++ pair("ticking-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance()) + )); + })); + @@ -550,13 +545,12 @@ index 0000000000000000000000000000000000000000..94adf0275a2e7093c152cc3b8b0a5747 +} diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java new file mode 100644 -index 0000000000000000000000000000000000000000..79ede25e4fe7a648b1d29c49d876482a2158f892 +index 0000000000000000000000000000000000000000..0fda52841b5e1643efeda92106124998abc4e0aa --- /dev/null +++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -0,0 +1,120 @@ +@@ -0,0 +1,119 @@ +package co.aikar.timings; + -+import Timing; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.storage.PrimaryLevelData; From a79616b9cc5aeb2860fe5eaa1c7f33344af52303 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 20:33:36 +0200 Subject: [PATCH 020/226] fix: the server compiles Signed-off-by: Mariell Hoversholm --- patches/server/0004-Paper-config-files.patch | 13 +- patches/server/0007-Paper-Metrics.patch | 4 +- ...-MinecraftKey-Information-to-Objects.patch | 10 +- patches/server/0009-Timings-v2.patch | 189 +++++++++++++++++- 4 files changed, 196 insertions(+), 20 deletions(-) diff --git a/patches/server/0004-Paper-config-files.patch b/patches/server/0004-Paper-config-files.patch index 351a727884..e616c9efc8 100644 --- a/patches/server/0004-Paper-config-files.patch +++ b/patches/server/0004-Paper-config-files.patch @@ -7,10 +7,10 @@ Loads each yml file for early init too so it can be used for early options diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java new file mode 100644 -index 0000000000000000000000000000000000000000..94cc5b494cdbc163fb70d0f4a6708d6ca2f42288 +index 0000000000000000000000000000000000000000..bee2fa2bfbb61209381f24ed6508d3d1c73a344a --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +1,286 @@ +@@ -0,0 +1,285 @@ +package com.destroystokyo.paper; + +import com.google.common.base.Functions; @@ -65,7 +65,7 @@ index 0000000000000000000000000000000000000000..94cc5b494cdbc163fb70d0f4a6708d6c + + private static boolean testPermission(CommandSender commandSender, String permission) { + if (commandSender.hasPermission(BASE_PERM + permission) || commandSender.hasPermission("bukkit.command.paper")) return true; -+ commandSender.sendMessage(Bukkit.getPermissionMessage()); ++ commandSender.sendMessage(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error."); // Sorry, kashike + return false; + } + @@ -151,7 +151,7 @@ index 0000000000000000000000000000000000000000..94cc5b494cdbc163fb70d0f4a6708d6c + case "ver": + if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) + case "version": -+ Command ver = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version"); ++ Command ver = MinecraftServer.getServer().server.getCommandMap().getCommand("version"); + if (ver != null) { + ver.execute(sender, commandLabel, new String[0]); + break; @@ -219,12 +219,11 @@ index 0000000000000000000000000000000000000000..94cc5b494cdbc163fb70d0f4a6708d6c + Map nonEntityTicking = Maps.newHashMap(); + ServerChunkCache chunkProviderServer = world.getChunkSource(); + -+ Collection entities = world.entitiesById.values(); -+ entities.forEach(e -> { ++ world.getAllEntities().forEach(e -> { + ResourceLocation key = new ResourceLocation(""); // TODO: update in next patch + + MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); -+ ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); ++ ChunkPos chunk = e.chunkPosition(); + info.left++; + info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1); + if (!chunkProviderServer.isPositionTicking(e)) { diff --git a/patches/server/0007-Paper-Metrics.patch b/patches/server/0007-Paper-Metrics.patch index 38a4e27283..c94eb31fa6 100644 --- a/patches/server/0007-Paper-Metrics.patch +++ b/patches/server/0007-Paper-Metrics.patch @@ -15,7 +15,7 @@ decisions on behalf of the project. diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java new file mode 100644 -index 0000000000000000000000000000000000000000..0b9e689d57705965721b5c55bc45d36657f360e4 +index 0000000000000000000000000000000000000000..e3b74dbdf8e14219a56fab939f3174e0c2f66de6 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/Metrics.java @@ -0,0 +1,670 @@ @@ -618,7 +618,7 @@ index 0000000000000000000000000000000000000000..0b9e689d57705965721b5c55bc45d366 + })); + + metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); -+ metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() || PaperConfig.isProxyOnlineMode() ? "online" : "offline")); ++ metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() ? "online" : "offline")); + metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); + + metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { diff --git a/patches/server/0008-Add-MinecraftKey-Information-to-Objects.patch b/patches/server/0008-Add-MinecraftKey-Information-to-Objects.patch index 5d6c20956d..b96b5157a6 100644 --- a/patches/server/0008-Add-MinecraftKey-Information-to-Objects.patch +++ b/patches/server/0008-Add-MinecraftKey-Information-to-Objects.patch @@ -6,18 +6,18 @@ Subject: [PATCH] Add MinecraftKey Information to Objects Stores the reference to the objects respective MinecraftKey diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 94cc5b494cdbc163fb70d0f4a6708d6ca2f42288..3ef396c0a543b5724769e0b83314f332739bdff0 100644 +index bee2fa2bfbb61209381f24ed6508d3d1c73a344a..1fa190e098079522e0fe3593fa261c1b7ad4e24b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperCommand.java +++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -208,7 +208,7 @@ public class PaperCommand extends Command { +@@ -207,7 +207,7 @@ public class PaperCommand extends Command { + ServerChunkCache chunkProviderServer = world.getChunkSource(); - Collection entities = world.entitiesById.values(); - entities.forEach(e -> { + world.getAllEntities().forEach(e -> { - ResourceLocation key = new ResourceLocation(""); // TODO: update in next patch + ResourceLocation key = e.getMinecraftKey(); MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); - ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); + ChunkPos chunk = e.chunkPosition(); diff --git a/src/main/java/net/minecraft/server/KeyedObject.java b/src/main/java/net/minecraft/server/KeyedObject.java new file mode 100644 index 0000000000000000000000000000000000000000..d02bd109399d6b32cbbb5e6f9ec7e650e8299a26 diff --git a/patches/server/0009-Timings-v2.patch b/patches/server/0009-Timings-v2.patch index c9ed1235fa..77a87bfdee 100644 --- a/patches/server/0009-Timings-v2.patch +++ b/patches/server/0009-Timings-v2.patch @@ -1642,10 +1642,18 @@ index 3b2b57f5049d26a14e45eb4ec88a5b498005d372..ebe33c891e25c729c4373190da86c7a8 if (!this.level.isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { this.hurt(DamageSource.DROWN, 1.0F); diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index c9c8ce20e3adff1fe49489a6ac2d2e6be2795949..931a22bfce05716d6a6c0030c790f2338f7edd9f 100644 +index c9c8ce20e3adff1fe49489a6ac2d2e6be2795949..59730455fcdf22bada7288833cf7e8b6c9b4096a 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -149,7 +149,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -82,7 +82,6 @@ import org.bukkit.Bukkit; + import org.bukkit.Location; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.block.CapturedBlockState; + import org.bukkit.craftbukkit.block.CraftBlockState; + import org.bukkit.craftbukkit.block.data.CraftBlockData; +@@ -149,7 +148,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper @@ -1654,7 +1662,7 @@ index c9c8ce20e3adff1fe49489a6ac2d2e6be2795949..931a22bfce05716d6a6c0030c790f233 public static BlockPos lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; private org.spigotmc.TickLimiter tileLimiter; -@@ -236,7 +236,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -236,7 +235,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } }); // CraftBukkit end @@ -1663,7 +1671,7 @@ index c9c8ce20e3adff1fe49489a6ac2d2e6be2795949..931a22bfce05716d6a6c0030c790f233 this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); } -@@ -721,15 +721,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -721,15 +720,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { timings.tileEntityTick.stopTiming(); // Spigot this.tickingBlockEntities = false; @@ -1772,14 +1780,14 @@ index e4601134598e509a158ceacec6099a78bbabe89d..0e70d9df226e0843a943b3a57d1319ce private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); public CraftPersistentDataContainer persistentDataContainer; diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 57f32618d6c95734fa4b45274afaf2319c7608ae..0aa56efbfe42cad7840dae2f1f8ab3dc365128fd 100644 +index 57f32618d6c95734fa4b45274afaf2319c7608ae..485cb87e83dd4b4b052905fb7f5f83d3c26f542f 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -725,6 +725,7 @@ public class LevelChunk implements ChunkAccess { server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(this.bukkitChunk, this.needsDecoration)); if (this.needsDecoration) { -+ try (co.aikar.timings.Timing ignored = this.world.timings.chunkLoadPopulate.startTiming()) { // Paper ++ try (co.aikar.timings.Timing ignored = this.level.timings.chunkLoadPopulate.startTiming()) { // Paper this.needsDecoration = false; java.util.Random random = new java.util.Random(); random.setSeed(this.level.getSeed()); @@ -1865,6 +1873,175 @@ index 743c9f11dbbb66db97bcb3b8fecd97290a7c9f61..c85f69cc6ef8a61ca1b07beb5f2b2159 @Override public void restart() { org.spigotmc.RestartCommand.restart(); +diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +deleted file mode 100644 +index b0ffa23faf62629043dfd613315eaf9c5fcc2cfe..0000000000000000000000000000000000000000 +--- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java ++++ /dev/null +@@ -1,163 +0,0 @@ +-package org.bukkit.craftbukkit; +- +-import java.util.HashMap; +-import net.minecraft.world.entity.Entity; +-import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.storage.PrimaryLevelData; +-import org.bukkit.craftbukkit.scheduler.CraftTask; +-import org.bukkit.plugin.java.JavaPluginLoader; +-import org.bukkit.scheduler.BukkitTask; +-import org.spigotmc.CustomTimingsHandler; +- +-public class SpigotTimings { +- +- public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); +- public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); +- public static final CustomTimingsHandler commandFunctionsTimer = new CustomTimingsHandler("Command Functions"); +- public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler"); +- public static final CustomTimingsHandler playerConnectionTimer = new CustomTimingsHandler("** PlayerConnection"); +- public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); +- public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); +- public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update"); +- public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command"); +- public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save"); +- +- public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); +- public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); +- public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); +- public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); +- +- public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); +- public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); +- public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); +- public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); +- public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); +- +- public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue"); +- public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer); +- +- public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); +- +- public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); +- public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); +- +- public static final HashMap entityTypeTimingMap = new HashMap(); +- public static final HashMap tileEntityTypeTimingMap = new HashMap(); +- public static final HashMap pluginTaskTimingMap = new HashMap(); +- +- /** +- * Gets a timer associated with a plugins tasks. +- * @param task +- * @param period +- * @return +- */ +- public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { +- if (!task.isSync()) { +- return null; +- } +- String plugin; +- final CraftTask ctask = (CraftTask) task; +- +- if (task.getOwner() != null) { +- plugin = task.getOwner().getDescription().getFullName(); +- } else { +- plugin = "Unknown"; +- } +- String taskname = ctask.getTaskName(); +- +- String name = "Task: " + plugin + " Runnable: " + taskname; +- if (period > 0) { +- name += "(interval:" + period + ")"; +- } else { +- name += "(Single)"; +- } +- CustomTimingsHandler result = SpigotTimings.pluginTaskTimingMap.get(name); +- if (result == null) { +- result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); +- SpigotTimings.pluginTaskTimingMap.put(name, result); +- } +- return result; +- } +- +- /** +- * Get a named timer for the specified entity type to track type specific timings. +- * @param entity +- * @return +- */ +- public static CustomTimingsHandler getEntityTimings(Entity entity) { +- String entityType = entity.getClass().getName(); +- CustomTimingsHandler result = SpigotTimings.entityTypeTimingMap.get(entityType); +- if (result == null) { +- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), SpigotTimings.activatedEntityTimer); +- SpigotTimings.entityTypeTimingMap.put(entityType, result); +- } +- return result; +- } +- +- /** +- * Get a named timer for the specified tile entity type to track type specific timings. +- * @param entity +- * @return +- */ +- public static CustomTimingsHandler getTileEntityTimings(BlockEntity entity) { +- String entityType = entity.getClass().getName(); +- CustomTimingsHandler result = SpigotTimings.tileEntityTypeTimingMap.get(entityType); +- if (result == null) { +- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), SpigotTimings.tickTileEntityTimer); +- SpigotTimings.tileEntityTypeTimingMap.put(entityType, result); +- } +- return result; +- } +- +- /** +- * Set of timers per world, to track world specific timings. +- */ +- public static class WorldTimingsHandler { +- public final CustomTimingsHandler mobSpawn; +- public final CustomTimingsHandler doChunkUnload; +- public final CustomTimingsHandler doTickPending; +- public final CustomTimingsHandler doTickTiles; +- public final CustomTimingsHandler doChunkMap; +- public final CustomTimingsHandler doSounds; +- public final CustomTimingsHandler entityTick; +- public final CustomTimingsHandler tileEntityTick; +- public final CustomTimingsHandler tileEntityPending; +- public final CustomTimingsHandler tracker; +- public final CustomTimingsHandler doTick; +- public final CustomTimingsHandler tickEntities; +- +- public final CustomTimingsHandler syncChunkLoadTimer; +- public final CustomTimingsHandler syncChunkLoadStructuresTimer; +- public final CustomTimingsHandler syncChunkLoadEntitiesTimer; +- public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer; +- public final CustomTimingsHandler syncChunkLoadTileTicksTimer; +- public final CustomTimingsHandler syncChunkLoadPostTimer; +- +- public WorldTimingsHandler(Level server) { +- String name = ((PrimaryLevelData) server.levelData).getLevelName() + " - "; +- +- this.mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); +- this.doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); +- this.doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); +- this.doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); +- this.doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); +- this.doSounds = new CustomTimingsHandler("** " + name + "doSounds"); +- this.entityTick = new CustomTimingsHandler("** " + name + "entityTick"); +- this.tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); +- this.tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending"); +- +- this.syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); +- this.syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); +- this.syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); +- this.syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); +- this.syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); +- this.syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); +- +- +- this.tracker = new CustomTimingsHandler(name + "tracker"); +- this.doTick = new CustomTimingsHandler(name + "doTick"); +- this.tickEntities = new CustomTimingsHandler(name + "tickEntities"); +- } +- } +-} diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 06d071d43337f2b919144a8db28684f4a3c826cf..457506210f041291be6bcdef7286d0860cb85946 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java From eccd156d12c072c966ea438b3b6f6680e254fdb0 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 21:08:51 +0200 Subject: [PATCH 021/226] fix: map parent method where CB does not Signed-off-by: Mariell Hoversholm --- build-data/additional-spigot-member-mappings.csrg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-data/additional-spigot-member-mappings.csrg b/build-data/additional-spigot-member-mappings.csrg index 9528baf294..962d83c9a2 100644 --- a/build-data/additional-spigot-member-mappings.csrg +++ b/build-data/additional-spigot-member-mappings.csrg @@ -19,4 +19,4 @@ net/minecraft/world/entity/npc/EntityVillagerAbstract fD ()Lnet/minecraft/world/ # net/minecraft/world/level/chunk/IChunkProvider b (II)Z isLoaded # BehaviorWorkComposter -> BehaviorWork -# net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter a (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/npc/EntityVillager;)V doWork +net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter a (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/npc/EntityVillager;)V doWork From a58819078001aa79e264790de758bd1c1577042e Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 11 Jun 2021 21:35:53 +0200 Subject: [PATCH 022/226] feat: new maven group: io.papermc.paper Signed-off-by: Mariell Hoversholm --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4b0538ff68..e0b14dc32d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { id("io.papermc.paperweight.core") version "1.0.0-LOCAL-SNAPSHOT" } -group = "com.destroystokyo.paper" +group = "io.papermc.paper" version = providers.gradleProperty("projectVersion").forUseAtConfigurationTime().get() val mcVersion = providers.gradleProperty("mcVersion") From 7ea73d48d46c0208908748067b6955b01891d042 Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Fri, 11 Jun 2021 15:17:37 -0500 Subject: [PATCH 023/226] fix: Update paperweight mcdev and fix CraftBukkit patch --- .../BehaviorWorkComposter.patch.patch | 17 +++++++++++++++++ build.gradle.kts | 3 ++- settings.gradle.kts | 1 - 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch diff --git a/build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch b/build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch new file mode 100644 index 0000000000..9f2bdc4a2c --- /dev/null +++ b/build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.patch ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.patch +@@ -1,14 +1,5 @@ + --- a/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.java + +++ b/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.java +-@@ -23,7 +23,7 @@ +- public BehaviorWorkComposter() {} +- +- @Override +-- protected void a(WorldServer worldserver, EntityVillager entityvillager) { +-+ protected void doWork(WorldServer worldserver, EntityVillager entityvillager) { // PAIL +- Optional optional = entityvillager.getBehaviorController().getMemory(MemoryModuleType.JOB_SITE); +- +- if (optional.isPresent()) { + @@ -42,7 +42,7 @@ + BlockPosition blockposition = globalpos.getBlockPosition(); + diff --git a/build.gradle.kts b/build.gradle.kts index e0b14dc32d..c72aad1bc8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight.core") version "1.0.0-LOCAL-SNAPSHOT" + id("io.papermc.paperweight.core") version "1.0.0-SNAPSHOT" } group = "io.papermc.paper" @@ -81,5 +81,6 @@ paperweight { mappingsPatch.set(file("build-data/mappings-patch.tiny")) additionalSpigotMemberMappings.set(file("build-data/additional-spigot-member-mappings.csrg")) + craftBukkitPatchPatchesDir.set(file("build-data/craftbukkit-patch-patches")) } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 302bcb31ab..54bb957497 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,5 @@ pluginManagement { repositories { - mavenLocal() gradlePluginPortal() maven("https://wav.jfrog.io/artifactory/repo/") } From a22a0e56ef103ff7ed672981f1d1f667bc197c50 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Sat, 12 Jun 2021 02:22:53 +0200 Subject: [PATCH 024/226] few fixes to make it actually run --- build-data/mappings-patch.tiny | 4 ++++ .../server/0001-Setup-Gradle-project.patch | 20 +++++++++++++++---- .../server/0003-Build-system-changes.patch | 10 +++++----- patches/server/0006-MC-Utils.patch | 6 +++--- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/build-data/mappings-patch.tiny b/build-data/mappings-patch.tiny index 73cc8abcdf..572cb1137b 100644 --- a/build-data/mappings-patch.tiny +++ b/build-data/mappings-patch.tiny @@ -74,3 +74,7 @@ c net/minecraft/world/entity/projectile/EntityTippedArrow net/minecraft/world/en # p 1 entry # p 2 context # m (Lcom/google/gson/JsonObject;Lnet/minecraft/world/level/storage/loot/entries/LootEntryAbstract;Lcom/google/gson/JsonSerializationContext;)V serializeType serializeCustom + +# missed mapping? +c net/minecraft/world/level/block/MultifaceBlock net/minecraft/world/level/block/MultifaceBlock + m (Lnet/minecraft/world/level/block/state/IBlockData;Lnet/minecraft/world/level/IBlockAccess;Lnet/minecraft/core/BlockPosition;Lnet/minecraft/core/EnumDirection;)Lnet/minecraft/world/level/block/state/IBlockData; c getStateForPlacement diff --git a/patches/server/0001-Setup-Gradle-project.patch b/patches/server/0001-Setup-Gradle-project.patch index 9e12bf0e6d..e69ca18a15 100644 --- a/patches/server/0001-Setup-Gradle-project.patch +++ b/patches/server/0001-Setup-Gradle-project.patch @@ -17,12 +17,17 @@ index 67fb370cad6924895a6b27052dbd5c1767e3f0c9..3e05459f27c4c5697ae65da504d67a6a /.project diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 -index 0000000000000000000000000000000000000000..fddf2f440356425d948f40dcf9d9853a374ddc8e +index 0000000000000000000000000000000000000000..b038528ba5ab9790a6bdb1c51ff072f9b8a64bf8 --- /dev/null +++ b/build.gradle.kts -@@ -0,0 +1,72 @@ +@@ -0,0 +1,84 @@ +import com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer -+import java.time.Instant ++import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer ++import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer ++import org.gradle.api.file.FileTreeElement ++import shadow.org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor.PLUGIN_CACHE_FILE ++import java.util.Date ++import java.text.SimpleDateFormat + +plugins { + java @@ -62,7 +67,7 @@ index 0000000000000000000000000000000000000000..fddf2f440356425d948f40dcf9d9853a + attributes(mapOf( + "Main-Class" to "org.bukkit.craftbukkit.Main", + "Implementation-Title" to "CraftBukkit", -+ "Implementation-Vendor" to Instant.now().epochSecond, ++ "Implementation-Vendor" to SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date()), // Paper + "Specification-Title" to "Bukkit", + "Specification-Version" to project.version, + "Specification-Vendor" to "Bukkit Team" @@ -88,8 +93,15 @@ index 0000000000000000000000000000000000000000..fddf2f440356425d948f40dcf9d9853a + transform(AppendingTransformer::class.java) { + resource = "META-INF/services/java.sql.Driver" + } ++ transform(ModifiedLog4j2PluginsCacheFileTransformer::class.java) +} + +tasks.test { + exclude("org/bukkit/craftbukkit/inventory/ItemStack*Test.class") +} ++ ++class ModifiedLog4j2PluginsCacheFileTransformer : Transformer by Log4j2PluginsCacheFileTransformer() { ++ override fun canTransformResource(element: FileTreeElement): Boolean { ++ return PLUGIN_CACHE_FILE == element.name || element.name == "Log4j2Plugins.dat" ++ } ++} diff --git a/patches/server/0003-Build-system-changes.patch b/patches/server/0003-Build-system-changes.patch index 92b74cc17a..3c91de463b 100644 --- a/patches/server/0003-Build-system-changes.patch +++ b/patches/server/0003-Build-system-changes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Build system changes diff --git a/build.gradle.kts b/build.gradle.kts -index fddf2f440356425d948f40dcf9d9853a374ddc8e..32fee49011b630407d6fd1c66838a833a706741a 100644 +index b038528ba5ab9790a6bdb1c51ff072f9b8a64bf8..25fa56d26bd88e4647b4c25ad6783ff90a05b2c4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -15,21 +15,24 @@ repositories { +@@ -20,21 +20,24 @@ repositories { dependencies { implementation(project(":Paper-API")) implementation("jline:jline:2.12.1") @@ -37,8 +37,8 @@ index fddf2f440356425d948f40dcf9d9853a374ddc8e..32fee49011b630407d6fd1c66838a833 testImplementation("junit:junit:4.13.1") testImplementation("org.hamcrest:hamcrest-library:1.3") } -@@ -42,7 +45,8 @@ tasks.jar { - "Implementation-Vendor" to Instant.now().epochSecond, +@@ -47,7 +50,8 @@ tasks.jar { + "Implementation-Vendor" to SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date()), // Paper "Specification-Title" to "Bukkit", "Specification-Version" to project.version, - "Specification-Vendor" to "Bukkit Team" @@ -47,7 +47,7 @@ index fddf2f440356425d948f40dcf9d9853a374ddc8e..32fee49011b630407d6fd1c66838a833 )) for (tld in listOf("net", "com", "org")) { attributes(mapOf( -@@ -54,7 +58,7 @@ tasks.jar { +@@ -59,7 +63,7 @@ tasks.jar { tasks.shadowJar { listOf( diff --git a/patches/server/0006-MC-Utils.patch b/patches/server/0006-MC-Utils.patch index cfdaa85ede..3101a34f9a 100644 --- a/patches/server/0006-MC-Utils.patch +++ b/patches/server/0006-MC-Utils.patch @@ -2271,7 +2271,7 @@ index 8ba68f03c1dd87826185808e9e7080647a55c2dd..4a1c6217e7d04880f577d5d47d77f641 public static long getEpochMillis() { diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 3cf71f85da94bcda5d4527b5f3e18d959c6c4634..9322a516df45c4a4cb83acf8e5f6792f219ae183 100644 +index 3cf71f85da94bcda5d4527b5f3e18d959c6c4634..c2309751e3798874eee6b469129121c2e317fbc3 100644 --- a/src/main/java/net/minecraft/core/BlockPos.java +++ b/src/main/java/net/minecraft/core/BlockPos.java @@ -104,6 +104,7 @@ public class BlockPos extends Vec3i { @@ -2302,7 +2302,7 @@ index 3cf71f85da94bcda5d4527b5f3e18d959c6c4634..9322a516df45c4a4cb83acf8e5f6792f } } -+ /* // Paper start - comment out useless overrides @Override ++ // Paper start - comment out useless overrides @Override - TODO figure out why this is suddenly important to keep @Override public BlockPos.MutableBlockPos setX(int i) { super.setX(i); @@ -2310,7 +2310,7 @@ index 3cf71f85da94bcda5d4527b5f3e18d959c6c4634..9322a516df45c4a4cb83acf8e5f6792f super.setZ(i); return this; } -+ */ // Paper end ++ // Paper end @Override public BlockPos immutable() { From 9188180d7a8b5cd16734a2352faca52ef9532580 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Fri, 11 Jun 2021 18:10:12 -0700 Subject: [PATCH 025/226] Add Paper version back to manifest, add `runShadow`, `runReobf`, and `runDev` tasks for testing --- .../server/0001-Setup-Gradle-project.patch | 41 ++++++++++++++++++- .../server/0003-Build-system-changes.patch | 8 ++-- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/patches/server/0001-Setup-Gradle-project.patch b/patches/server/0001-Setup-Gradle-project.patch index e69ca18a15..cd9ca86451 100644 --- a/patches/server/0001-Setup-Gradle-project.patch +++ b/patches/server/0001-Setup-Gradle-project.patch @@ -17,13 +17,15 @@ index 67fb370cad6924895a6b27052dbd5c1767e3f0c9..3e05459f27c4c5697ae65da504d67a6a /.project diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 -index 0000000000000000000000000000000000000000..b038528ba5ab9790a6bdb1c51ff072f9b8a64bf8 +index 0000000000000000000000000000000000000000..ccb67fe90e25010f7c8ca168d60d096ef95c4429 --- /dev/null +++ b/build.gradle.kts -@@ -0,0 +1,84 @@ +@@ -0,0 +1,121 @@ +import com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer +import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer +import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer ++import io.papermc.paperweight.util.Git ++import io.papermc.paperweight.util.path +import org.gradle.api.file.FileTreeElement +import shadow.org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor.PLUGIN_CACHE_FILE +import java.util.Date @@ -64,9 +66,13 @@ index 0000000000000000000000000000000000000000..b038528ba5ab9790a6bdb1c51ff072f9 + +tasks.jar { + manifest { ++ val git = Git(rootProject.layout.projectDirectory.path) ++ val gitHashCmd = git("rev-parse", "HEAD") ++ val gitHash = gitHashCmd.getText().substring(0, 7) + attributes(mapOf( + "Main-Class" to "org.bukkit.craftbukkit.Main", + "Implementation-Title" to "CraftBukkit", ++ "Implementation-Version" to "git-Paper-\"$gitHash\"", + "Implementation-Vendor" to SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date()), // Paper + "Specification-Title" to "Bukkit", + "Specification-Version" to project.version, @@ -100,6 +106,37 @@ index 0000000000000000000000000000000000000000..b038528ba5ab9790a6bdb1c51ff072f9 + exclude("org/bukkit/craftbukkit/inventory/ItemStack*Test.class") +} + ++fun TaskContainer.registerRunTask(name: String, block: JavaExec.() -> Unit): TaskProvider = ++ register(name) { ++ group = "Paper" ++ workingDir = rootProject.projectDir.resolve("run") ++ doFirst { ++ if (!workingDir.exists()) workingDir.mkdir() ++ } ++ standardInput = System.`in` ++ args("--nogui") ++ systemProperty("net.kyori.adventure.text.warnWhenLegacyFormattingDetected", true) ++ block(this) ++ } ++ ++tasks.registerRunTask("runShadow") { ++ description = "Spin up a test server from the shadowJar archiveFile" ++ classpath(tasks.shadowJar.flatMap { it.archiveFile }) ++} ++ ++tasks.registerRunTask("runReobf") { ++ description = "Spin up a test server from the reobfJar output jar" ++ classpath(tasks.reobfJar.flatMap { it.outputJar }) ++} ++ ++tasks.registerRunTask("runDev") { ++ description = "Spin up a non-shaded non-remapped test server" ++ classpath = project.convention.getPlugin(JavaPluginConvention::class.java) ++ .sourceSets.getByName("main").runtimeClasspath ++ main = "org.bukkit.craftbukkit.Main" ++ systemProperty("disable.watchdog", true) ++} ++ +class ModifiedLog4j2PluginsCacheFileTransformer : Transformer by Log4j2PluginsCacheFileTransformer() { + override fun canTransformResource(element: FileTreeElement): Boolean { + return PLUGIN_CACHE_FILE == element.name || element.name == "Log4j2Plugins.dat" diff --git a/patches/server/0003-Build-system-changes.patch b/patches/server/0003-Build-system-changes.patch index 3c91de463b..29cd18e973 100644 --- a/patches/server/0003-Build-system-changes.patch +++ b/patches/server/0003-Build-system-changes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Build system changes diff --git a/build.gradle.kts b/build.gradle.kts -index b038528ba5ab9790a6bdb1c51ff072f9b8a64bf8..25fa56d26bd88e4647b4c25ad6783ff90a05b2c4 100644 +index ccb67fe90e25010f7c8ca168d60d096ef95c4429..f353524ada2caa05824b1e7ded17a1c00473d906 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -20,21 +20,24 @@ repositories { +@@ -22,21 +22,24 @@ repositories { dependencies { implementation(project(":Paper-API")) implementation("jline:jline:2.12.1") @@ -37,7 +37,7 @@ index b038528ba5ab9790a6bdb1c51ff072f9b8a64bf8..25fa56d26bd88e4647b4c25ad6783ff9 testImplementation("junit:junit:4.13.1") testImplementation("org.hamcrest:hamcrest-library:1.3") } -@@ -47,7 +50,8 @@ tasks.jar { +@@ -53,7 +56,8 @@ tasks.jar { "Implementation-Vendor" to SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date()), // Paper "Specification-Title" to "Bukkit", "Specification-Version" to project.version, @@ -47,7 +47,7 @@ index b038528ba5ab9790a6bdb1c51ff072f9b8a64bf8..25fa56d26bd88e4647b4c25ad6783ff9 )) for (tld in listOf("net", "com", "org")) { attributes(mapOf( -@@ -59,7 +63,7 @@ tasks.jar { +@@ -65,7 +69,7 @@ tasks.jar { tasks.shadowJar { listOf( From a9f38a878987c33dd4fcee2ead82c4b7eed927b5 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Fri, 11 Jun 2021 12:23:46 -0700 Subject: [PATCH 026/226] fix adventure patch --- .../0006-Adventure.patch} | 0 patches/removed/1.17/0012-Adventure.patch | 23 + .../0010-Adventure.patch} | 748 ++++++++---------- 3 files changed, 360 insertions(+), 411 deletions(-) rename patches/{api-unmapped/0005-Adventure.patch => api/0006-Adventure.patch} (100%) create mode 100644 patches/removed/1.17/0012-Adventure.patch rename patches/{server-remapped/0012-Adventure.patch => server/0010-Adventure.patch} (82%) diff --git a/patches/api-unmapped/0005-Adventure.patch b/patches/api/0006-Adventure.patch similarity index 100% rename from patches/api-unmapped/0005-Adventure.patch rename to patches/api/0006-Adventure.patch diff --git a/patches/removed/1.17/0012-Adventure.patch b/patches/removed/1.17/0012-Adventure.patch new file mode 100644 index 0000000000..d0d6c9d6b6 --- /dev/null +++ b/patches/removed/1.17/0012-Adventure.patch @@ -0,0 +1,23 @@ +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java +index 915120cc505c70153f7b70f07d8d42c13eb77ea7..69ff8df7340e60c476803256750a48f0b43414d3 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java +@@ -10,6 +10,7 @@ public class ClientboundSetTitlesPacket implements Packet { -+ final @NonNull String translated = LocaleLanguage.a().a(translatable.key()); ++ final @NonNull String translated = net.minecraft.locale.Language.getInstance().getOrDefault(translatable.key()); + + final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated); + final List args = translatable.args(); @@ -934,19 +934,19 @@ index 0000000000000000000000000000000000000000..2dc92d8d2764d3e9b621d5c7d5e30c30 + } +} diff --git a/src/main/java/net/minecraft/ChatFormatting.java b/src/main/java/net/minecraft/ChatFormatting.java -index e888a90226c30757b190a3b89a56c1a312f32850..1720eba650c959810c6e4a3522979e75e10a1bb8 100644 +index b82b218be1bd849fa280ea1fe0336e279bebfc18..77e35e18754bd2380e1d5f93c62e1d47d21a0a18 100644 --- a/src/main/java/net/minecraft/ChatFormatting.java +++ b/src/main/java/net/minecraft/ChatFormatting.java -@@ -61,6 +61,7 @@ public enum ChatFormatting { - return !this.isFormat && this != ChatFormatting.RESET; +@@ -86,6 +86,7 @@ public enum ChatFormatting { + return !this.isFormat && this != RESET; } + @Nullable public Integer getHexValue() { return this.getColor(); } // Paper - OBFHELPER @Nullable public Integer getColor() { return this.color; -@@ -84,6 +85,18 @@ public enum ChatFormatting { - return name == null ? null : (ChatFormatting) ChatFormatting.FORMATTING_BY_NAME.get(cleanName(name)); +@@ -110,6 +111,18 @@ public enum ChatFormatting { + return name == null ? null : FORMATTING_BY_NAME.get(cleanName(name)); } + // Paper start @@ -964,8 +964,20 @@ index e888a90226c30757b190a3b89a56c1a312f32850..1720eba650c959810c6e4a3522979e75 @Nullable public static ChatFormatting getById(int colorIndex) { if (colorIndex < 0) { +diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java +index 4760fc27b1d4938a248c05af17fc93ab37084c00..750df4ab2fbfdcf759f4d3451340e66b6764391d 100644 +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -128,7 +128,6 @@ public class CompoundTag implements Tag { + /** + * You must use {@link #hasUUID(String)} before or else it will throw an NPE. + */ +- public UUID getUUID(String prefix) { return getUUID(prefix); } // Paper - OBFHELPER + public UUID getUUID(String key) { + return NbtUtils.loadUUID(this.get(key)); + } diff --git a/src/main/java/net/minecraft/nbt/StringTag.java b/src/main/java/net/minecraft/nbt/StringTag.java -index 620e10b5ba9e57ff4d0d7967bf4240fafadb2be7..dab8983fa65b97ecf0fe20fdc06cc8ec60d8fe95 100644 +index ad1c1fbb15cbd744afe54e1c3b533e51021a89eb..b15cfb9374402d4b42d163bf8e3ec838f19004bc 100644 --- a/src/main/java/net/minecraft/nbt/StringTag.java +++ b/src/main/java/net/minecraft/nbt/StringTag.java @@ -43,6 +43,7 @@ public class StringTag implements Tag { @@ -974,29 +986,29 @@ index 620e10b5ba9e57ff4d0d7967bf4240fafadb2be7..dab8983fa65b97ecf0fe20fdc06cc8ec + public static StringTag create(final String value) { return valueOf(value); } // Paper - OBFHELPER public static StringTag valueOf(String value) { - return value.isEmpty() ? StringTag.EMPTY : new StringTag(value); + return value.isEmpty() ? EMPTY : new StringTag(value); } diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -index 50f14acb062c2f90266279dbd1945a3297396f0b..59788eaef0dae5ee01ceba1bf45e85cb07f88e53 100644 +index 3b8207046d38d3d14719ff6761a22e60a93628b7..c15860c77c7c24b1946c22f140f1b5c12b052ade 100644 --- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java +++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -@@ -10,6 +10,7 @@ import io.netty.buffer.ByteBufOutputStream; - import io.netty.handler.codec.DecoderException; - import io.netty.handler.codec.EncoderException; +@@ -14,6 +14,7 @@ import io.netty.handler.codec.EncoderException; import io.netty.util.ByteProcessor; + import it.unimi.dsi.fastutil.ints.IntArrayList; + import it.unimi.dsi.fastutil.ints.IntList; +import io.papermc.paper.adventure.PaperAdventure; // Paper import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -@@ -43,6 +44,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit - public class FriendlyByteBuf extends ByteBuf { - +@@ -61,6 +62,7 @@ public class FriendlyByteBuf extends ByteBuf { + private static final int MAX_VARLONG_SIZE = 10; + private static final int DEFAULT_NBT_QUOTA = 2097152; private final ByteBuf source; + public java.util.Locale adventure$locale; // Paper + public static final short MAX_STRING_LENGTH = 32767; + public static final int MAX_COMPONENT_STRING_LENGTH = 262144; - public FriendlyByteBuf(ByteBuf bytebuf) { - this.source = bytebuf; -@@ -164,8 +166,15 @@ public class FriendlyByteBuf extends ByteBuf { +@@ -327,8 +329,15 @@ public class FriendlyByteBuf extends ByteBuf { return Component.Serializer.fromJson(this.readUtf(262144)); } @@ -1012,17 +1024,9 @@ index 50f14acb062c2f90266279dbd1945a3297396f0b..59788eaef0dae5ee01ceba1bf45e85cb + return this.writeUtf(PaperAdventure.asJsonString(text, this.adventure$locale), 262144); // Paper } - public > T readEnum(Class oclass) { -@@ -348,6 +357,7 @@ public class FriendlyByteBuf extends ByteBuf { - return this.writeUtf(s, 32767); - } - -+ public FriendlyByteBuf writeUtf(final String string, final int maxLength) { return this.writeUtf(string, maxLength); } // Paper - OBFHELPER - public FriendlyByteBuf writeUtf(String s, int i) { - byte[] abyte = s.getBytes(StandardCharsets.UTF_8); - + public > T readEnum(Class enumClass) { diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index 14fa1371e52b9af5a7550a9aa144fa406b754046..d36d0424bcd4811af892f5f76fdcefda2af1ad33 100644 +index 02d253243eb66c30d4f7f6b0e7361518516eefec..847c59dd1b4673f4a03d77717468e07e99fc80a4 100644 --- a/src/main/java/net/minecraft/network/PacketEncoder.java +++ b/src/main/java/net/minecraft/network/PacketEncoder.java @@ -3,6 +3,7 @@ package net.minecraft.network; @@ -1033,26 +1037,36 @@ index 14fa1371e52b9af5a7550a9aa144fa406b754046..d36d0424bcd4811af892f5f76fdcefda import java.io.IOException; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.PacketFlow; -@@ -37,6 +38,7 @@ public class PacketEncoder extends MessageToByteEncoder> { - throw new IOException("Can't serialize unregistered packet"); +@@ -36,6 +37,7 @@ public class PacketEncoder extends MessageToByteEncoder> { } else { - FriendlyByteBuf packetdataserializer = new FriendlyByteBuf(bytebuf); -+ packetdataserializer.adventure$locale = channelhandlercontext.channel().attr(PaperAdventure.LOCALE_ATTRIBUTE).get(); // Paper - - packetdataserializer.writeVarInt(integer); + FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf); + friendlyByteBuf.writeVarInt(integer); ++ friendlyByteBuf.adventure$locale = channelHandlerContext.channel().attr(PaperAdventure.LOCALE_ATTRIBUTE).get(); // Paper + try { + int i = friendlyByteBuf.writerIndex(); +@@ -46,7 +48,7 @@ public class PacketEncoder extends MessageToByteEncoder> { + } + } catch (Throwable var9) { + LOGGER.error(var9); +- throwable.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? ++ var9.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? + if (packet.isSkippable()) { + throw new SkipPacketException(var9); + } else { diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java -index 819ea90ea116dea396c225539fc0fbebd6176ba5..54d186a195aca6d0a4c412ed609d8c86dcc76072 100644 +index d9aac575213f3bda9c44ea2b3b6d1969ff82f09d..02d19fa4abdee0c8331734932a83e64694356030 100644 --- a/src/main/java/net/minecraft/network/chat/Component.java +++ b/src/main/java/net/minecraft/network/chat/Component.java -@@ -1,5 +1,6 @@ +@@ -1,6 +1,7 @@ package net.minecraft.network.chat; + import com.google.common.collect.Lists; +import io.papermc.paper.adventure.AdventureComponent; // Paper import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; -@@ -110,6 +111,7 @@ public interface Component extends Message, FormattedText, Iterable { +@@ -161,6 +162,7 @@ public interface Component extends Message, FormattedText, Iterable { GsonBuilder gsonbuilder = new GsonBuilder(); gsonbuilder.disableHtmlEscaping(); @@ -1060,7 +1074,7 @@ index 819ea90ea116dea396c225539fc0fbebd6176ba5..54d186a195aca6d0a4c412ed609d8c86 gsonbuilder.registerTypeHierarchyAdapter(Component.class, new Component.Serializer()); gsonbuilder.registerTypeHierarchyAdapter(Style.class, new Style.Serializer()); gsonbuilder.registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()); -@@ -262,6 +264,7 @@ public interface Component extends Message, FormattedText, Iterable { +@@ -320,6 +322,7 @@ public interface Component extends Message, FormattedText, Iterable { } public JsonElement serialize(Component ichatbasecomponent, Type type, JsonSerializationContext jsonserializationcontext) { @@ -1068,20 +1082,15 @@ index 819ea90ea116dea396c225539fc0fbebd6176ba5..54d186a195aca6d0a4c412ed609d8c86 JsonObject jsonobject = new JsonObject(); if (!ichatbasecomponent.getStyle().isEmpty()) { -@@ -350,10 +353,12 @@ public interface Component extends Message, FormattedText, Iterable { - return jsonobject; +@@ -416,6 +419,7 @@ public interface Component extends Message, FormattedText, Iterable { + }); } + public static String componentToJson(final Component component) { return toJson(component); } // Paper - OBFHELPER public static String toJson(Component text) { return Component.Serializer.GSON.toJson(text); } - -+ public static JsonElement toJsonTree(final Component component) { return toJsonTree(component); } // Paper - OBFHELPER - public static JsonElement toJsonTree(Component text) { - return Component.Serializer.GSON.toJsonTree(text); - } -@@ -363,6 +368,7 @@ public interface Component extends Message, FormattedText, Iterable { +@@ -429,6 +433,7 @@ public interface Component extends Message, FormattedText, Iterable { return (MutableComponent) GsonHelper.fromJson(Component.Serializer.GSON, json, MutableComponent.class, false); } @@ -1090,72 +1099,48 @@ index 819ea90ea116dea396c225539fc0fbebd6176ba5..54d186a195aca6d0a4c412ed609d8c86 public static MutableComponent fromJson(JsonElement json) { return (MutableComponent) Component.Serializer.GSON.fromJson(json, MutableComponent.class); diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -index ce64931b5c363352f03baddbc747246469d56a84..e47102cadb40ed8a9c011386445f15fd30de7596 100644 +index d63a712126973fd1bea547d30c7d116c622669ee..1f5050e6c1d932aa196ab9524f7f1f9bd1b45fce 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -@@ -11,6 +11,7 @@ import net.minecraft.network.protocol.Packet; +@@ -10,6 +10,7 @@ import net.minecraft.network.protocol.Packet; public class ClientboundChatPacket implements Packet { - private Component message; + private final Component message; + public net.kyori.adventure.text.Component adventure$message; // Paper public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot - private ChatType type; - private UUID sender; -@@ -32,6 +33,11 @@ public class ClientboundChatPacket implements Packet { + private final ChatType type; + private final UUID sender; +@@ -28,6 +29,11 @@ public class ClientboundChatPacket implements Packet { @Override - public void write(FriendlyByteBuf buf) throws IOException { + public void write(FriendlyByteBuf buf) { + // Paper start + if (this.adventure$message != null) { + buf.writeComponent(this.adventure$message); + } else + // Paper end // Spigot start - if (components != null) { - buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(components)); -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -index 915120cc505c70153f7b70f07d8d42c13eb77ea7..69ff8df7340e60c476803256750a48f0b43414d3 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -@@ -10,6 +10,7 @@ public class ClientboundSetTitlesPacket implements Packet { + public final Component header; + public final Component footer; + // Paper start + public net.kyori.adventure.text.Component adventure$header; + public net.kyori.adventure.text.Component adventure$footer; + // Paper end - public ClientboundTabListPacket() {} - + public ClientboundTabListPacket(Component header, Component footer) { + this.header = header; @@ -20,6 +24,13 @@ public class ClientboundTabListPacket implements Packet { + this.connection.send((Packet) (new ClientboundPlayerCombatKillPacket(this.getCombatTracker(), ichatbasecomponent)), (future) -> { if (!future.isSuccess()) { -@@ -1666,6 +1663,7 @@ public class ServerPlayer extends Player implements ContainerListener { - this.sendMessage(message, ChatType.SYSTEM, senderUuid); - } - -+ public void sendMessage(final Component message, final ChatType type, final UUID sender) { this.sendMessage(message, type, sender); } // Paper - OBFHELPER - public void sendMessage(Component message, ChatType type, UUID senderUuid) { - this.connection.send((Packet) (new ClientboundChatPacket(message, type, senderUuid)), (future) -> { - if (!future.isSuccess() && (type == ChatType.GAME_INFO || type == ChatType.SYSTEM)) { -@@ -1688,6 +1686,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1709,6 +1706,7 @@ public class ServerPlayer extends Player { } public String locale = "en_us"; // CraftBukkit - add, lowercase @@ -1238,7 +1215,7 @@ index 8d7fa186b0b47688f2822038b46c33b3f32d28ae..ca647b3afbe8da5847dc8fa890ae9ca5 public void updateOptions(ServerboundClientInformationPacket packet) { // CraftBukkit start if (getMainArm() != packet.getMainHand()) { -@@ -1699,6 +1698,10 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1720,6 +1718,10 @@ public class ServerPlayer extends Player { this.server.server.getPluginManager().callEvent(event); } this.locale = packet.language; @@ -1250,26 +1227,26 @@ index 8d7fa186b0b47688f2822038b46c33b3f32d28ae..ca647b3afbe8da5847dc8fa890ae9ca5 // CraftBukkit end this.chatVisibility = packet.getChatVisibility(); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 466c4322803bedf1fa61be281b954bf94fb8ff02..016e91a6ca1c8457e3e367ac0597b73e81919b68 100644 +index 4ada0aaca513cbac51b93b298f4e2587de46f0d8..94ebbcb7731c01fcb93f053eea109f544132139a 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -168,6 +168,8 @@ import org.apache.logging.log4j.LogManager; +@@ -162,6 +162,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; // CraftBukkit start +import io.papermc.paper.adventure.ChatProcessor; // Paper +import io.papermc.paper.adventure.PaperAdventure; // Paper import java.util.concurrent.ExecutionException; - import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - import org.bukkit.Location; -@@ -388,21 +390,24 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + import java.util.concurrent.atomic.AtomicInteger; + import net.minecraft.world.inventory.AbstractContainerMenu; +@@ -385,21 +387,24 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser return this.server.isSingleplayerOwner(this.player.getGameProfile()); } - // CraftBukkit start - @Deprecated - public void disconnect(Component reason) { -- disconnect(CraftChatMessage.fromComponent(reason)); +- this.disconnect(CraftChatMessage.fromComponent(reason)); + public void disconnect(String s) { + // Paper start + this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); @@ -1290,12 +1267,12 @@ index 466c4322803bedf1fa61be281b954bf94fb8ff02..016e91a6ca1c8457e3e367ac0597b73e - String leaveMessage = ChatFormatting.YELLOW + this.player.getScoreboardName() + " left the game."; + net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure -- PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), s, leaveMessage); -+ PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure +- PlayerKickEvent event = new PlayerKickEvent(this.cserver.getPlayer(this.player), s, leaveMessage); ++ PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), reason, leaveMessage); // Paper - Adventure - if (this.craftServer.getServer().isRunning()) { - this.craftServer.getPluginManager().callEvent(event); -@@ -413,8 +418,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + if (this.cserver.getServer().isRunning()) { + this.cserver.getPluginManager().callEvent(event); +@@ -410,8 +415,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser return; } // Send the possibly modified leave message @@ -1305,7 +1282,7 @@ index 466c4322803bedf1fa61be281b954bf94fb8ff02..016e91a6ca1c8457e3e367ac0597b73e // CraftBukkit end this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> { -@@ -1631,9 +1635,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1671,9 +1675,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser */ this.player.disconnect(); @@ -1315,62 +1292,68 @@ index 466c4322803bedf1fa61be281b954bf94fb8ff02..016e91a6ca1c8457e3e367ac0597b73e + // Paper start - Adventure + net.kyori.adventure.text.Component quitMessage = this.server.getPlayerList().disconnect(this.player); + if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) { -+ this.server.getPlayerList().sendMessage(PaperAdventure.asVanilla(quitMessage)); ++ this.server.getPlayerList().broadcastMessage(PaperAdventure.asVanilla(quitMessage), ChatType.SYSTEM, Util.NIL_UUID); + // Paper end } // CraftBukkit end - TextFilter itextfilter = this.player.getTextFilter(); -@@ -1849,8 +1855,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.player.getTextFilter().leave(); +@@ -1855,7 +1861,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.handleCommand(s); } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { // Do nothing, this is coming from a plugin - } else { -- Player player = this.getPlayer(); + // Paper start + } else if (true) { + final ChatProcessor cp = new ChatProcessor(this.server, this.player, s, async); + cp.process(); -+ // Paper end ++ // Paper end + } else if (false) { // Paper -+ Player player = this.getPlayer(); // Paper - AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(server)); - this.craftServer.getPluginManager().callEvent(event); - -@@ -2668,21 +2679,20 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + Player player = this.getCraftPlayer(); + AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(this.server)); + this.cserver.getPluginManager().callEvent(event); +@@ -2646,30 +2657,28 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser return; } - // CraftBukkit start -- Player player = this.craftServer.getPlayer(this.player); -- int x = packetplayinupdatesign.getPos().getX(); -- int y = packetplayinupdatesign.getPos().getY(); -- int z = packetplayinupdatesign.getPos().getZ(); -- String[] lines = new String[4]; + // CraftBukkit start // Paper start - Adventure + Player player = this.cserver.getPlayer(this.player); + int x = packetplayinupdatesign.getPos().getX(); + int y = packetplayinupdatesign.getPos().getY(); + int z = packetplayinupdatesign.getPos().getZ(); +- String[] lines = new String[4]; + List lines = new java.util.ArrayList<>(); for (int i = 0; i < list.size(); ++i) { -- lines[i] = ChatFormatting.stripFormatting(new TextComponent(ChatFormatting.stripFormatting((String) list.get(i))).getString()); -+ lines.add(net.kyori.adventure.text.Component.text(list.get(i))); +- TextFilter.FilteredText itextfilter_a = (TextFilter.FilteredText) list.get(i); +- + if (this.player.isTextFilteringEnabled()) { +- lines[i] = ChatFormatting.stripFormatting(new TextComponent(ChatFormatting.stripFormatting(itextfilter_a.getFiltered())).getString()); ++ lines.add(net.kyori.adventure.text.Component.text(list.get(i).getFiltered())); + } else { +- lines[i] = ChatFormatting.stripFormatting(new TextComponent(ChatFormatting.stripFormatting(itextfilter_a.getRaw())).getString()); ++ lines.add(net.kyori.adventure.text.Component.text(list.get(i).getRaw())); + } } -- SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.craftServer.getPlayer(this.player), lines); -+ SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.craftServer.getPluginManager().callEvent(event); + SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.cserver.getPlayer(this.player), lines); + this.cserver.getPluginManager().callEvent(event); if (!event.isCancelled()) { -- System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.messages, 0, 4); +- Component[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()); +- for (int i = 0; i < components.length; i++) { +- tileentitysign.setMessage(i, components[i]); + for (int i = 0; i < 4; i++) { + tileentitysign.setMessage(i, PaperAdventure.asVanilla(event.line(i))); -+ } + } + // Paper end tileentitysign.isEditable = false; - } + } // CraftBukkit end diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index a1dd76f49c59ed0a0b7f2b68fbd1a9a70a89128b..9dbb3bb79ae2de6635f71e5ee5bebeb5e57b624e 100644 +index 89d3a7ab019e735c5057568aa2971018f1a05324..11c0da9b36aecc1a7d3acb2dccdae962426dd2e7 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -35,6 +35,7 @@ import net.minecraft.world.entity.player.Player; +@@ -36,6 +36,7 @@ import net.minecraft.world.entity.player.Player; import org.apache.commons.lang3.Validate; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -1378,7 +1361,7 @@ index a1dd76f49c59ed0a0b7f2b68fbd1a9a70a89128b..9dbb3bb79ae2de6635f71e5ee5bebeb5 import org.bukkit.craftbukkit.util.Waitable; import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.PlayerPreLoginEvent; -@@ -299,7 +300,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -315,7 +316,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { @@ -1387,36 +1370,36 @@ index a1dd76f49c59ed0a0b7f2b68fbd1a9a70a89128b..9dbb3bb79ae2de6635f71e5ee5bebeb5 } Waitable waitable = new Waitable() { @Override -@@ -310,12 +311,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -326,12 +327,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener ServerLoginPacketListenerImpl.this.server.processQueue.add(waitable); if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { -- disconnect(event.getKickMessage()); -+ disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure +- ServerLoginPacketListenerImpl.this.disconnect(event.getKickMessage()); ++ ServerLoginPacketListenerImpl.this.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure return; } } else { if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { -- disconnect(asyncEvent.getKickMessage()); -+ disconnect(PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure +- ServerLoginPacketListenerImpl.this.disconnect(asyncEvent.getKickMessage()); ++ ServerLoginPacketListenerImpl.this.disconnect(PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure return; } } diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java -index de19aa66e7b6ddde17e9acf65643b4a71573d759..223df8d27c2ff1cbff634bca3dbde5cc24de7f98 100644 +index b632280e057ae6893bf5ebcde75cefac3ee62a09..9baa56d6da9c24706f1dbc8851fd68ca752cab26 100644 --- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java @@ -55,7 +55,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene CraftIconCache icon = server.server.getServerIcon(); ServerListPingEvent() { -- super(((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.getMotd(), server.getPlayerList().getMaxPlayers()); -+ super(((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.server.motd(), server.getPlayerList().getMaxPlayers()); // Paper - Adventure +- super(((InetSocketAddress) ServerStatusPacketListenerImpl.this.connection.getRemoteAddress()).getAddress(), ServerStatusPacketListenerImpl.this.server.getMotd(), ServerStatusPacketListenerImpl.this.server.getPlayerList().getMaxPlayers()); ++ super(((InetSocketAddress) ServerStatusPacketListenerImpl.this.connection.getRemoteAddress()).getAddress(), ServerStatusPacketListenerImpl.this.server.server.getMotd(), ServerStatusPacketListenerImpl.this.server.getPlayerList().getMaxPlayers()); // Paper - Adventure } @Override diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 88af57699d7f9e45ad1366243049e4f3565703ff..8cdecaf2f63c78196e0c5046fe2431b40e072c8a 100644 +index 34e386efda7ea52fb6f53333eda0f015b0666ff3..446dd8c15d4ccdced316deeaba379cb6937496ca 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -8,6 +8,7 @@ import com.mojang.authlib.GameProfile; @@ -1427,30 +1410,30 @@ index 88af57699d7f9e45ad1366243049e4f3565703ff..8cdecaf2f63c78196e0c5046fe2431b4 import java.io.File; import java.net.SocketAddress; import java.text.SimpleDateFormat; -@@ -83,6 +84,7 @@ import org.apache.logging.log4j.LogManager; +@@ -89,6 +90,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; // CraftBukkit start +import io.papermc.paper.adventure.PaperAdventure; // Paper import com.google.common.base.Predicate; - import com.google.common.collect.Iterables; + import java.util.stream.Collectors; import net.minecraft.server.dedicated.DedicatedServer; -@@ -251,7 +253,7 @@ public abstract class PlayerList { +@@ -255,7 +257,7 @@ public abstract class PlayerList { } // CraftBukkit start chatmessage.withStyle(ChatFormatting.YELLOW); - String joinMessage = CraftChatMessage.fromComponent(chatmessage); + Component joinMessage = chatmessage; // Paper - Adventure - playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.yRot, player.xRot); + playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot()); this.players.add(player); -@@ -260,19 +262,18 @@ public abstract class PlayerList { +@@ -264,19 +266,18 @@ public abstract class PlayerList { // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below // CraftBukkit start -- PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(cserver.getPlayer(player), joinMessage); -+ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - cserver.getPluginManager().callEvent(playerJoinEvent); +- PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(this.cserver.getPlayer(player), joinMessage); ++ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(this.cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + this.cserver.getPluginManager().callEvent(playerJoinEvent); if (!player.connection.connection.isConnected()) { return; @@ -1461,15 +1444,15 @@ index 88af57699d7f9e45ad1366243049e4f3565703ff..8cdecaf2f63c78196e0c5046fe2431b4 - if (joinMessage != null && joinMessage.length() > 0) { - for (Component line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { -- server.getPlayerList().broadcastAll(new ClientboundChatPacket(line, ChatType.SYSTEM, Util.NIL_UUID)); +- this.server.getPlayerList().broadcastAll(new ClientboundChatPacket(line, ChatType.SYSTEM, Util.NIL_UUID)); - } + if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure + joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure -+ server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure ++ this.server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure } // CraftBukkit end -@@ -469,7 +470,7 @@ public abstract class PlayerList { +@@ -473,7 +474,7 @@ public abstract class PlayerList { } @@ -1478,17 +1461,17 @@ index 88af57699d7f9e45ad1366243049e4f3565703ff..8cdecaf2f63c78196e0c5046fe2431b4 ServerLevel worldserver = entityplayer.getLevel(); entityplayer.awardStat(Stats.LEAVE_GAME); -@@ -480,7 +481,7 @@ public abstract class PlayerList { +@@ -484,7 +485,7 @@ public abstract class PlayerList { entityplayer.closeContainer(); } -- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getScoreboardName() + " left the game"); -+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); - cserver.getPluginManager().callEvent(playerQuitEvent); +- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(this.cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getScoreboardName() + " left the game"); ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(this.cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); + this.cserver.getPluginManager().callEvent(playerQuitEvent); entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); -@@ -541,7 +542,7 @@ public abstract class PlayerList { - cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); +@@ -537,7 +538,7 @@ public abstract class PlayerList { + this.cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); // CraftBukkit end - return playerQuitEvent.getQuitMessage(); // CraftBukkit @@ -1496,7 +1479,7 @@ index 88af57699d7f9e45ad1366243049e4f3565703ff..8cdecaf2f63c78196e0c5046fe2431b4 } // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer -@@ -587,10 +588,10 @@ public abstract class PlayerList { +@@ -583,10 +584,10 @@ public abstract class PlayerList { } // return chatmessage; @@ -1506,31 +1489,31 @@ index 88af57699d7f9e45ad1366243049e4f3565703ff..8cdecaf2f63c78196e0c5046fe2431b4 chatmessage = new TranslatableComponent("multiplayer.disconnect.not_whitelisted"); - event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot + event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure - } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { + } else if (this.getIpBans().isBanned(socketaddress) && !this.getIpBans().get(socketaddress).hasExpired()) { IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); -@@ -600,17 +601,17 @@ public abstract class PlayerList { +@@ -596,17 +597,17 @@ public abstract class PlayerList { } // return chatmessage; - event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); + event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure } else { - // return this.players.size() >= this.maxPlayers && !this.f(gameprofile) ? new ChatMessage("multiplayer.disconnect.server_full") : null; + // return this.players.size() >= this.maxPlayers && !this.d(gameprofile) ? new ChatMessage("multiplayer.disconnect.server_full") : null; if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) { - event.disallow(PlayerLoginEvent.Result.KICK_FULL, org.spigotmc.SpigotConfig.serverFullMessage); // Spigot + event.disallow(PlayerLoginEvent.Result.KICK_FULL, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure } } - cserver.getPluginManager().callEvent(event); + this.cserver.getPluginManager().callEvent(event); if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { - loginlistener.disconnect(event.getKickMessage()); + loginlistener.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure return null; } return entity; -@@ -1131,7 +1132,7 @@ public abstract class PlayerList { +@@ -1109,7 +1110,7 @@ public abstract class PlayerList { public void removeAll() { // CraftBukkit start - disconnect safely for (ServerPlayer player : this.players) { @@ -1540,7 +1523,7 @@ index 88af57699d7f9e45ad1366243049e4f3565703ff..8cdecaf2f63c78196e0c5046fe2431b4 // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/BossEvent.java b/src/main/java/net/minecraft/world/BossEvent.java -index 8718449abc08ed7795ac70c2bef12d15b94d4127..adb7c8db8e173801a83e5ff1f4cad0dda2abeb82 100644 +index d289e8321a62f7c8d1e5b83f038e7331a26fc24e..658aff27155b32a0323f55152c7315fdc7b4a82d 100644 --- a/src/main/java/net/minecraft/world/BossEvent.java +++ b/src/main/java/net/minecraft/world/BossEvent.java @@ -1,5 +1,6 @@ @@ -1550,7 +1533,7 @@ index 8718449abc08ed7795ac70c2bef12d15b94d4127..adb7c8db8e173801a83e5ff1f4cad0dd import java.util.UUID; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; -@@ -14,6 +15,7 @@ public abstract class BossEvent { +@@ -13,6 +14,7 @@ public abstract class BossEvent { protected boolean darkenScreen; protected boolean playBossMusic; protected boolean createWorldFog; @@ -1559,10 +1542,10 @@ index 8718449abc08ed7795ac70c2bef12d15b94d4127..adb7c8db8e173801a83e5ff1f4cad0dd public BossEvent(UUID uuid, Component name, BossEvent.BossBarColor color, BossEvent.BossBarOverlay style) { this.id = uuid; diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 2a6a6e291efbd7cc8fed6532f18321bd141e1306..3faf52e7ac5e7e22d09cfb73cfda6b9f622137d4 100644 +index d5b8931243e2f9cac9b0f92ab8df043a831bbe70..ac05b201167d8e17f39d3df732adf676dc24b409 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -865,6 +865,7 @@ public final class ItemStack { +@@ -1152,6 +1152,7 @@ public final class ItemStack { } // CraftBukkit end @@ -1571,56 +1554,55 @@ index 2a6a6e291efbd7cc8fed6532f18321bd141e1306..3faf52e7ac5e7e22d09cfb73cfda6b9f MutableComponent ichatmutablecomponent = (new TextComponent("")).append(this.getHoverName()); diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -index 72367311f79e3ef2868c05b38bae98c5a9fb129c..c23ec1b31950471905c65e46273ae105de853d9b 100644 +index 75d52cc90a015588ffbbae77b4c272f938a7c0a9..6d3df3d1bcaa016611320e7ba1f005e71bf0bfdf 100644 --- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -@@ -94,6 +94,7 @@ public abstract class Enchantment { +@@ -95,6 +95,7 @@ public abstract class Enchantment { return this.getOrCreateDescriptionId(); } + public final Component getTranslationComponentForLevel(int level) { return this.getFullname(level); } // Paper - OBFHELPER public Component getFullname(int level) { - TranslatableComponent chatmessage = new TranslatableComponent(this.getDescriptionId()); - + MutableComponent mutableComponent = new TranslatableComponent(this.getDescriptionId()); + if (this.isCurse()) { diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -index 2cccec66fbc7114c65336769e354fe6f756c9fca..d44505b3ee2a35422568e9bce0d868191e348fc0 100644 +index 7a0e7961df1e62b311ea2ecc76d7343a8646723b..6859fafa42527d45366018f737c19e6c3777d152 100644 --- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -@@ -32,6 +32,7 @@ import org.apache.logging.log4j.LogManager; +@@ -33,6 +33,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; // CraftBukkit start +import io.papermc.paper.adventure.PaperAdventure; // Paper import java.util.UUID; - import org.bukkit.craftbukkit.CraftServer; -@@ -473,7 +474,7 @@ public class MapItemSavedData extends SavedData { - for ( org.bukkit.map.MapCursor cursor : render.cursors) { + import org.bukkit.Bukkit; +@@ -599,7 +600,7 @@ public class MapItemSavedData extends SavedData { - if (cursor.isVisible()) { -- icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); -+ icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure + for (org.bukkit.map.MapCursor cursor : render.cursors) { + if (cursor.isVisible()) { +- icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); ++ icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure + } } - } - + collection = icons; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c4cf1394fe4c2782b1fea8b3653a817157d857eb..f7f5457d20586e0ba72368e64ff6025f6755e61e 100644 +index c85f69cc6ef8a61ca1b07beb5f2b2159fbaa887d..ea8d5d95d9aa2d0036f82eca782cb5a633cbc388 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -561,8 +561,10 @@ public final class CraftServer implements Server { +@@ -564,8 +564,10 @@ public final class CraftServer implements Server { } @Override + @Deprecated // Paper start public int broadcastMessage(String message) { -- return broadcast(message, BROADCAST_CHANNEL_USERS); -+ return this.broadcast(message, BROADCAST_CHANNEL_USERS); + return this.broadcast(message, BROADCAST_CHANNEL_USERS); + // Paper end } public Player getPlayer(final ServerPlayer entity) { -@@ -1306,7 +1308,15 @@ public final class CraftServer implements Server { - return configuration.getInt("settings.spawn-radius", -1); +@@ -1309,7 +1311,15 @@ public final class CraftServer implements Server { + return this.configuration.getInt("settings.spawn-radius", -1); } + // Paper start @@ -1633,9 +1615,9 @@ index c4cf1394fe4c2782b1fea8b3653a817157d857eb..f7f5457d20586e0ba72368e64ff6025f + @Override + @Deprecated // Paper public String getShutdownMessage() { - return configuration.getString("settings.shutdown-message"); + return this.configuration.getString("settings.shutdown-message"); } -@@ -1422,7 +1432,20 @@ public final class CraftServer implements Server { +@@ -1425,7 +1435,20 @@ public final class CraftServer implements Server { } @Override @@ -1654,15 +1636,15 @@ index c4cf1394fe4c2782b1fea8b3653a817157d857eb..f7f5457d20586e0ba72368e64ff6025f + public int broadcast(net.kyori.adventure.text.Component message, String permission) { + // Paper end Set recipients = new HashSet<>(); - for (Permissible permissible : getPluginManager().getPermissionSubscriptions(permission)) { + for (Permissible permissible : this.getPluginManager().getPermissionSubscriptions(permission)) { if (permissible instanceof CommandSender && permissible.hasPermission(permission)) { -@@ -1430,14 +1453,14 @@ public final class CraftServer implements Server { +@@ -1433,14 +1456,14 @@ public final class CraftServer implements Server { } } - BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); + BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); // Paper - Adventure - getPluginManager().callEvent(broadcastMessageEvent); + this.getPluginManager().callEvent(broadcastMessageEvent); if (broadcastMessageEvent.isCancelled()) { return 0; @@ -1673,7 +1655,7 @@ index c4cf1394fe4c2782b1fea8b3653a817157d857eb..f7f5457d20586e0ba72368e64ff6025f for (CommandSender recipient : recipients) { recipient.sendMessage(message); -@@ -1663,6 +1686,14 @@ public final class CraftServer implements Server { +@@ -1666,6 +1689,14 @@ public final class CraftServer implements Server { return CraftInventoryCreator.INSTANCE.createInventory(owner, type); } @@ -1688,7 +1670,7 @@ index c4cf1394fe4c2782b1fea8b3653a817157d857eb..f7f5457d20586e0ba72368e64ff6025f @Override public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); -@@ -1675,13 +1706,28 @@ public final class CraftServer implements Server { +@@ -1678,13 +1709,28 @@ public final class CraftServer implements Server { return CraftInventoryCreator.INSTANCE.createInventory(owner, size); } @@ -1717,8 +1699,8 @@ index c4cf1394fe4c2782b1fea8b3653a817157d857eb..f7f5457d20586e0ba72368e64ff6025f public Merchant createMerchant(String title) { return new CraftMerchantCustom(title == null ? InventoryType.MERCHANT.getDefaultTitle() : title); } -@@ -1725,6 +1771,12 @@ public final class CraftServer implements Server { - return Thread.currentThread().equals(console.serverThread) || console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog) +@@ -1728,6 +1774,12 @@ public final class CraftServer implements Server { + return Thread.currentThread().equals(console.serverThread) || this.console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog) } + // Paper start @@ -1729,8 +1711,8 @@ index c4cf1394fe4c2782b1fea8b3653a817157d857eb..f7f5457d20586e0ba72368e64ff6025f + // Paper end @Override public String getMotd() { - return console.getMotd(); -@@ -2153,5 +2205,15 @@ public final class CraftServer implements Server { + return this.console.getMotd(); +@@ -2156,5 +2208,15 @@ public final class CraftServer implements Server { return null; } } @@ -1747,7 +1729,7 @@ index c4cf1394fe4c2782b1fea8b3653a817157d857eb..f7f5457d20586e0ba72368e64ff6025f // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 05aedca561919a12ced1925c5cc9af585bb04523..ce9f10f890a5866ab6208c7253b15b09fe323a81 100644 +index 3c4281ad770598ecf3b9fae0d6ed6e9130136dbb..4df6b2a155a610953d8d5789bffa33d290d62aaa 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -19,6 +19,12 @@ public class Main { @@ -1764,7 +1746,7 @@ index 05aedca561919a12ced1925c5cc9af585bb04523..ce9f10f890a5866ab6208c7253b15b09 OptionParser parser = new OptionParser() { { diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -index 639577ab8b6467302a243c99ba5a4eede3aed655..940fef58f14e06213c7f305f67dcb8918976c03d 100644 +index 95b8d32adedf579172187c594e18177f3a84850e..5abf219e86c6b4cf0c6b2e8ea72d7ed7b4f612e3 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java @@ -70,6 +70,19 @@ public class CraftBeacon extends CraftBlockEntityState implem @@ -1836,7 +1818,7 @@ index add5b68d5fbd887e3fc2d226eff9ab00ed01ce73..2c3d6ba06d876df168aae4cc09b7b440 public String getCustomName() { EnchantmentTableBlockEntity enchant = this.getSnapshot(); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -index 7157facf2df5f3fe6377513cd353e96584788bd8..65e8a349c80a700f63dd27b11bb2099f65cbc069 100644 +index 2509a39bec5edd38b54709fec241c7c18e0d1c26..6e89b039479a034d98d1ec183b06d5418ab51733 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java @@ -12,8 +12,10 @@ import org.bukkit.craftbukkit.util.CraftChatMessage; @@ -1852,25 +1834,26 @@ index 7157facf2df5f3fe6377513cd353e96584788bd8..65e8a349c80a700f63dd27b11bb2099f public CraftSign(final Block block) { super(block, SignBlockEntity.class); -@@ -23,27 +25,52 @@ public class CraftSign extends CraftBlockEntityState implements +@@ -23,27 +25,51 @@ public class CraftSign extends CraftBlockEntityState implements super(material, te); } + // Paper start @Override - public String[] getLines() { -- if (lines == null) { +- if (this.lines == null) { - // Lazy initialization: - SignBlockEntity sign = this.getSnapshot(); -- lines = new String[sign.messages.length]; -- System.arraycopy(revertComponents(sign.messages), 0, lines, 0, lines.length); -- originalLines = new String[lines.length]; +- this.lines = new String[sign.messages.length]; +- System.arraycopy(CraftSign.revertComponents(sign.messages), 0, lines, 0, lines.length); +- this.originalLines = new String[lines.length]; - System.arraycopy(lines, 0, originalLines, 0, originalLines.length); +- } + public java.util.List lines() { + this.loadLines(); -+ return this.lines; -+ } -+ + return this.lines; + } + + @Override + public net.kyori.adventure.text.Component line(int index) { + this.loadLines(); @@ -1886,9 +1869,7 @@ index 7157facf2df5f3fe6377513cd353e96584788bd8..65e8a349c80a700f63dd27b11bb2099f + private void loadLines() { + if (lines != null) { + return; - } -- return lines; -+ ++ } + // Lazy initialization: + SignBlockEntity sign = this.getSnapshot(); + lines = io.papermc.paper.adventure.PaperAdventure.asAdventure(com.google.common.collect.Lists.newArrayList(sign.messages)); @@ -1899,30 +1880,30 @@ index 7157facf2df5f3fe6377513cd353e96584788bd8..65e8a349c80a700f63dd27b11bb2099f + public String[] getLines() { + this.loadLines(); + return this.lines.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).toArray(String[]::new); // Paper - } - ++ } ++ @Override public String getLine(int index) throws IndexOutOfBoundsException { -- return getLines()[index]; +- return this.getLines()[index]; + this.loadLines(); + return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(this.lines.get(index)); // Paper } @Override public void setLine(int index, String line) throws IndexOutOfBoundsException { -- getLines()[index] = line; +- this.getLines()[index] = line; + this.loadLines(); + this.lines.set(index, line != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(line) : net.kyori.adventure.text.Component.empty()); // Paper } @Override -@@ -71,16 +98,32 @@ public class CraftSign extends CraftBlockEntityState implements +@@ -81,16 +107,32 @@ public class CraftSign extends CraftBlockEntityState implements super.applyTo(sign); - if (lines != null) { + if (this.lines != null) { - for (int i = 0; i < lines.length; i++) { -- String line = (lines[i] == null) ? "" : lines[i]; -- if (line.equals(originalLines[i])) { +- String line = (this.lines[i] == null) ? "" : this.lines[i]; +- if (line.equals(this.originalLines[i])) { + // Paper start + for (int i = 0; i < this.lines.size(); ++i) { + net.kyori.adventure.text.Component component = this.lines.get(i); @@ -1930,7 +1911,7 @@ index 7157facf2df5f3fe6377513cd353e96584788bd8..65e8a349c80a700f63dd27b11bb2099f + if (component.equals(origComp)) { continue; // The line contents are still the same, skip. } -- sign.messages[i] = CraftChatMessage.fromString(line)[0]; +- sign.setMessage(i, CraftChatMessage.fromString(line)[0]); + sign.messages[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(component); } + // Paper end @@ -1954,12 +1935,12 @@ index 7157facf2df5f3fe6377513cd353e96584788bd8..65e8a349c80a700f63dd27b11bb2099f Component[] components = new Component[4]; diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -index 089fe4a3458ed3106fa214f89a7004a5d3c6bb95..af986adfdb547cb61fbd52f0f89858f1a9e52cc3 100644 +index 8bf9dd8f83c5e17447d8603fa5551e1fea06705d..a885eb537d6475eefe7d06f8312ecf0a278c5a00 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java @@ -80,4 +80,11 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co public boolean isConversing() { - return conversationTracker.isConversing(); + return this.conversationTracker.isConversing(); } + + // Paper start @@ -1970,12 +1951,12 @@ index 089fe4a3458ed3106fa214f89a7004a5d3c6bb95..af986adfdb547cb61fbd52f0f89858f1 + // 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 fd473d213f4050f420bd7d729fe0df757d5398bc..b1ffe6c7a5915f00a476e88f3a38349b740b4910 100644 +index cf69a45f038c2b8336010f5fe277313fd0513b5b..a7966aa0846637efdc43df1ca97cbc5d29616953 100644 --- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java @@ -187,6 +187,12 @@ public class CraftEnchantment extends Enchantment { CraftEnchantment ench = (CraftEnchantment) other; - return !target.isCompatibleWith(ench.target); + return !this.target.isCompatibleWith(ench.target); } + // Paper start + @Override @@ -1985,13 +1966,13 @@ index fd473d213f4050f420bd7d729fe0df757d5398bc..b1ffe6c7a5915f00a476e88f3a38349b + // Paper end public net.minecraft.world.item.enchantment.Enchantment getHandle() { - return target; + return this.target; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index eb61c803cf74c5ca2c51d5027a02ed3db6b53096..53c231925ef1b17e48c5863570e3c54124874621 100644 +index fdd3a7990cd63d44a154698449a472969ed9efdc..f4bcf48060bc704e0b6c690f78faaecfe90d8db3 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -768,6 +768,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return getHandle().getVehicle().getBukkitEntity(); +@@ -806,6 +806,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return this.getHandle().getVehicle().getBukkitEntity(); } + // Paper start @@ -2011,7 +1992,7 @@ index eb61c803cf74c5ca2c51d5027a02ed3db6b53096..53c231925ef1b17e48c5863570e3c541 public void setCustomName(String name) { // sane limit for name length diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 7c200e43bdc170ecf8b8fbfadd7bb38c66133443..b5c0f3d91cf451a972f0cf293db03a306073c493 100644 +index 450eea6e518de0493d4af4ad384d24217a3c7acf..d27a7ac64d1daf85319ab0069b9196f1958f6f46 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -317,9 +317,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @@ -2026,8 +2007,8 @@ index 7c200e43bdc170ecf8b8fbfadd7bb38c66133443..b5c0f3d91cf451a972f0cf293db03a30 - player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); + //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment + player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - getHandle().containerMenu = container; - getHandle().containerMenu.addSlotListener(player); + player.containerMenu = container; + player.initMenu(container); } @@ -388,8 +391,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @@ -2042,24 +2023,24 @@ index 7c200e43bdc170ecf8b8fbfadd7bb38c66133443..b5c0f3d91cf451a972f0cf293db03a30 + //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment + player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper player.containerMenu = container; - player.containerMenu.addSlotListener(player); + player.initMenu(container); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05b891167b 100644 +index 457506210f041291be6bcdef7286d0860cb85946..f4dff38b0f9e33be3495433559935765f77d662e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -238,14 +238,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -243,14 +243,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public String getDisplayName() { + if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper - return getHandle().displayName; + return this.getHandle().displayName; } @Override public void setDisplayName(final String name) { + this.getHandle().adventure$displayName = name != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(name) : net.kyori.adventure.text.Component.text(this.getName()); // Paper - getHandle().displayName = name == null ? getName() : name; + this.getHandle().displayName = name == null ? getName() : name; } + // Paper start @@ -2087,8 +2068,8 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 + // Paper end @Override public String getPlayerListName() { - return getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(getHandle().listName); -@@ -264,35 +289,35 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return this.getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(this.getHandle().listName); +@@ -269,42 +294,42 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } } @@ -2099,28 +2080,28 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 @Override public String getPlayerListHeader() { -- return (playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader); -+ return (playerListHeader == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListHeader); // Paper - Adventure +- return (this.playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader); ++ return (this.playerListHeader == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListHeader); } @Override public String getPlayerListFooter() { -- return (playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter); -+ return (playerListFooter == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListFooter); // Paper - Adventure +- return (this.playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter); ++ return (this.playerListFooter == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListFooter); // Paper - Adventure } @Override public void setPlayerListHeader(String header) { - this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); + this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure - updatePlayerListHeaderFooter(); + this.updatePlayerListHeaderFooter(); } @Override public void setPlayerListFooter(String footer) { - this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); + this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure - updatePlayerListHeaderFooter(); + this.updatePlayerListHeaderFooter(); } @Override @@ -2129,22 +2110,19 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 - this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); + this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure + this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure - updatePlayerListHeaderFooter(); + this.updatePlayerListHeaderFooter(); } -@@ -300,8 +325,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (getHandle().connection == null) return; + private void updatePlayerListHeaderFooter() { + if (this.getHandle().connection == null) return; - ClientboundTabListPacket packet = new ClientboundTabListPacket(); -- packet.header = (this.playerListHeader == null) ? new TextComponent("") : this.playerListHeader; -- packet.footer = (this.playerListFooter == null) ? new TextComponent("") : this.playerListFooter; -+ packet.header = (this.playerListHeader == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListHeader); // Paper - Adventure -+ packet.footer = (this.playerListFooter == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListFooter); // Paper - Adventure - getHandle().connection.send(packet); +- ClientboundTabListPacket packet = new ClientboundTabListPacket((this.playerListHeader == null) ? new TextComponent("") : this.playerListHeader, (this.playerListFooter == null) ? new TextComponent("") : this.playerListFooter); ++ ClientboundTabListPacket packet = new ClientboundTabListPacket((this.playerListHeader == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListHeader), (this.playerListFooter == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListFooter)); + this.getHandle().connection.send(packet); } -@@ -333,6 +358,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getHandle().connection.disconnect(message == null ? "" : message); +@@ -336,6 +361,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + this.getHandle().connection.disconnect(message == null ? "" : message); } + // Paper start @@ -2160,9 +2138,9 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 + @Override public void setCompassTarget(Location loc) { - if (getHandle().connection == null) return; -@@ -559,6 +595,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getHandle().connection.send(packet); + if (this.getHandle().connection == null) return; +@@ -562,6 +598,36 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + this.getHandle().connection.send(packet); } + // Paper start @@ -2188,8 +2166,7 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 + } + + private void sendSignChange0(Component[] components, Location loc, DyeColor dyeColor) { -+ SignBlockEntity sign = new SignBlockEntity(); -+ sign.setPosition(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); ++ SignBlockEntity sign = new SignBlockEntity(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), Blocks.OAK_SIGN.defaultBlockState()); + sign.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData())); + System.arraycopy(components, 0, sign.messages, 0, sign.messages.length); + @@ -2198,28 +2175,28 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 + // Paper end @Override public void sendSignChange(Location loc, String[] lines) { - sendSignChange(loc, lines, DyeColor.BLACK); -@@ -581,12 +648,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + this.sendSignChange(loc, lines, DyeColor.BLACK); +@@ -584,13 +650,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } Component[] components = CraftSign.sanitizeLines(lines); -- SignBlockEntity sign = new SignBlockEntity(); -- sign.setPosition(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); +- SignBlockEntity sign = new SignBlockEntity(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), Blocks.OAK_SIGN.defaultBlockState()); - sign.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData())); -- System.arraycopy(components, 0, sign.messages, 0, sign.messages.length); -+ /*TileEntitySign sign = new TileEntitySign(); // Paper -+ sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); +- for (int i = 0; i < components.length; i++) { +- sign.setMessage(i, components[i]); +- } ++ /*SignBlockEntity sign = new SignBlockEntity(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), Blocks.OAK_SIGN.defaultBlockState()); + sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); + System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); -- getHandle().connection.send(sign.getUpdatePacket()); -+ getHandle().playerConnection.sendPacket(sign.getUpdatePacket());*/ // Paper +- this.getHandle().connection.send(sign.getUpdatePacket()); ++ this.getHandle().connection.send(sign.getUpdatePacket());*/ // Paper + this.sendSignChange0(components, loc, dyeColor); // Paper } @Override -@@ -1686,6 +1754,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return (getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : getHandle().clientViewDistance; +@@ -1690,6 +1755,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return (this.getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : this.getHandle().clientViewDistance; } + // Paper start @@ -2230,8 +2207,8 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 + // Paper end @Override public int getPing() { - return getHandle().latency; -@@ -1714,6 +1788,138 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return this.getHandle().latency; +@@ -1718,6 +1789,138 @@ public class CraftPlayer extends CraftHumanEntity implements Player { getInventory().setItemInMainHand(hand); } @@ -2256,8 +2233,8 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 + + @Override + public void sendActionBar(final net.kyori.adventure.text.Component message) { -+ final ClientboundSetTitlesPacket packet = new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.ACTIONBAR, null); -+ packet.adventure$text = message; ++ final net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket packet = new net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket(io.papermc.paper.adventure.PaperAdventure.asVanilla(message)); ++ // packet.adventure$text = message; // TODO: kashike add fields to packet + this.getHandle().connection.send(packet); + } + @@ -2283,9 +2260,9 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 + private void adventure$sendPlayerListHeaderAndFooter() { + final ServerGamePacketListenerImpl connection = this.getHandle().connection; + if (connection == null) return; -+ final ClientboundTabListPacket packet = new ClientboundTabListPacket(); -+ packet.adventure$header = (this.playerListHeader == null) ? net.kyori.adventure.text.Component.empty() : this.playerListHeader; -+ packet.adventure$footer = (this.playerListFooter == null) ? net.kyori.adventure.text.Component.empty() : this.playerListFooter; ++ final ClientboundTabListPacket packet = new net.minecraft.network.protocol.game.ClientboundTabListPacket(io.papermc.paper.adventure.PaperAdventure.asVanilla((this.playerListHeader == null) ? net.kyori.adventure.text.Component.empty() : this.playerListHeader), io.papermc.paper.adventure.PaperAdventure.asVanilla((this.playerListFooter == null) ? net.kyori.adventure.text.Component.empty() : this.playerListFooter)); ++ // packet.adventure$header = (this.playerListHeader == null) ? net.kyori.adventure.text.Component.empty() : this.playerListHeader; // TODO: kashike add fields to packet ++ // packet.adventure$footer = (this.playerListFooter == null) ? net.kyori.adventure.text.Component.empty() : this.playerListFooter; + connection.send(packet); + } + @@ -2294,13 +2271,13 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 + final ServerGamePacketListenerImpl connection = this.getHandle().connection; + final net.kyori.adventure.title.Title.Times times = title.times(); + if (times != null) { -+ connection.send(new ClientboundSetTitlesPacket(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut()))); ++ connection.send(new ClientboundSetTitlesAnimationPacket(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut()))); + } -+ final ClientboundSetTitlesPacket sp = new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.SUBTITLE, null); -+ sp.adventure$text = title.subtitle(); ++ final ClientboundSetSubtitleTextPacket sp = new ClientboundSetSubtitleTextPacket(io.papermc.paper.adventure.PaperAdventure.asVanilla(title.subtitle())); ++ // sp.adventure$text = title.subtitle(); // TODO: kashike add fields to packet + connection.send(sp); -+ final ClientboundSetTitlesPacket tp = new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.TITLE, null); -+ tp.adventure$text = title.title(); ++ final ClientboundSetTitleTextPacket tp = new ClientboundSetTitleTextPacket(io.papermc.paper.adventure.PaperAdventure.asVanilla(title.title())); ++ // tp.adventure$text = title.title(); + connection.send(tp); + } + @@ -2313,7 +2290,7 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 + + @Override + public void clearTitle() { -+ this.getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.CLEAR, null)); ++ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundClearTitlesPacket(false)); + } + + // resetTitle implemented above @@ -2359,7 +2336,7 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 + final net.minecraft.world.item.ItemStack item = io.papermc.paper.adventure.PaperAdventure.asItemStack(book, locale); + final ServerPlayer player = this.getHandle(); + final ServerGamePacketListenerImpl connection = player.connection; -+ final net.minecraft.world.entity.player.Inventory inventory = player.inventory; ++ final net.minecraft.world.entity.player.Inventory inventory = player.getInventory(); + final int slot = inventory.items.size() + inventory.selected; + connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, item)); + connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND)); @@ -2371,10 +2348,10 @@ index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05 private final Player.Spigot spigot = new Player.Spigot() { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index abd65693aca1964b65d091e633a36c97513c1d69..7fde1bb7587e567270e3f936381c6d361870211f 100644 +index cd54ba211070d34581068d6c1f3cceb858411415..fdb97878a6e73b729dbf09292d214e42c57d720a 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -776,9 +776,9 @@ public class CraftEventFactory { +@@ -770,9 +770,9 @@ public class CraftEventFactory { return event; } @@ -2386,7 +2363,7 @@ index abd65693aca1964b65d091e633a36c97513c1d69..7fde1bb7587e567270e3f936381c6d36 event.setKeepInventory(keepInventory); org.bukkit.World world = entity.getWorld(); Bukkit.getServer().getPluginManager().callEvent(event); -@@ -802,7 +802,7 @@ public class CraftEventFactory { +@@ -796,7 +796,7 @@ public class CraftEventFactory { * Server methods */ public static ServerListPingEvent callServerListPingEvent(Server craftServer, InetAddress address, String motd, int numPlayers, int maxPlayers) { @@ -2396,36 +2373,10 @@ index abd65693aca1964b65d091e633a36c97513c1d69..7fde1bb7587e567270e3f936381c6d36 return event; } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -index a393bdae6ef588289c8814a1896146a993c92e71..680c7818a7097355158eb76662ecebbae6dd6637 100644 +index 25826a4f019a3084517f84cd3e5a7810c7958f0e..dfca1161da8009e508c5c5ef788422441145cfdf 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -@@ -1,6 +1,5 @@ - package org.bukkit.craftbukkit.inventory; - --import net.minecraft.network.chat.TextComponent; - import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; - import net.minecraft.world.Container; - import net.minecraft.world.entity.player.Player; -@@ -38,6 +37,7 @@ public class CraftContainer extends AbstractContainerMenu { - - private final InventoryView view; - private InventoryType cachedType; -+ private net.kyori.adventure.text.Component adventure$title; // Paper - private String cachedTitle; - private AbstractContainerMenu delegate; - private final int cachedSize; -@@ -49,7 +49,9 @@ public class CraftContainer extends AbstractContainerMenu { - Container top = ((CraftInventory) view.getTopInventory()).getInventory(); - net.minecraft.world.entity.player.Inventory bottom = (net.minecraft.world.entity.player.Inventory) ((CraftInventory) view.getBottomInventory()).getInventory(); - cachedType = view.getType(); -- cachedTitle = view.getTitle(); -+ this.adventure$title = view.title(); // Paper -+ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper -+ //cachedTitle = view.getTitle(); // Paper - comment - cachedSize = getSize(); - setupSlots(top, bottom, player); - } -@@ -76,6 +78,13 @@ public class CraftContainer extends AbstractContainerMenu { +@@ -69,6 +69,13 @@ public class CraftContainer extends AbstractContainerMenu { return inventory.getType(); } @@ -2439,39 +2390,11 @@ index a393bdae6ef588289c8814a1896146a993c92e71..680c7818a7097355158eb76662ecebba @Override public String getTitle() { return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).getTitle() : inventory.getType().getDefaultTitle(); -@@ -94,7 +103,8 @@ public class CraftContainer extends AbstractContainerMenu { - - @Override - public boolean isSynched(Player player) { -- if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { -+ if (cachedType == view.getType() && cachedSize == getSize() && this.adventure$title.equals(view.title())) { // Paper -+ //if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { // Paper - comment - return true; - } - // If the window type has changed for some reason, update the player -@@ -102,7 +112,9 @@ public class CraftContainer extends AbstractContainerMenu { - // as good a place as any to put something like this. - boolean typeChanged = (cachedType != view.getType()); - cachedType = view.getType(); -- cachedTitle = view.getTitle(); -+ this.adventure$title = view.title(); // Paper -+ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper -+ //cachedTitle = view.getTitle(); // Paper - comment - if (view.getPlayer() instanceof CraftPlayer) { - CraftPlayer player1 = (CraftPlayer) view.getPlayer(); - MenuType type = getNotchInventoryType(view.getTopInventory()); -@@ -114,7 +126,8 @@ public class CraftContainer extends AbstractContainerMenu { - setupSlots(top, bottom, player1.getHandle()); - } - int size = getSize(); -- player1.getHandle().connection.send(new ClientboundOpenScreenPacket(this.containerId, type, new TextComponent(cachedTitle))); -+ player1.getHandle().connection.send(new ClientboundOpenScreenPacket(this.containerId, type, io.papermc.paper.adventure.PaperAdventure.asVanilla(this.adventure$title))); // Paper -+ //player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, new ChatComponentText(cachedTitle))); // Paper - comment - player1.updateInventory(); - } - return true; +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.javaED5zI7 b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.javaED5zI7 +new file mode 100644 +index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -index 397cd9651381a8a0ddb4ca173690e9b80428b182..46805a25c0273b76c19a3bbd40078d78c5379f43 100644 +index 6486a76466691f958349a4706d7c9caff9cb8f64..1a4e2534e8a2114125c505f46868ba4e3f2880a0 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java @@ -19,6 +19,12 @@ public class CraftInventoryCustom extends CraftInventory { @@ -2520,7 +2443,7 @@ index 397cd9651381a8a0ddb4ca173690e9b80428b182..46805a25c0273b76c19a3bbd40078d78 this.type = type; @@ -57,11 +77,24 @@ public class CraftInventoryCustom extends CraftInventory { Validate.notNull(title, "Title cannot be null"); - this.items = NonNullList.a(size, ItemStack.EMPTY); + this.items = NonNullList.withSize(size, ItemStack.EMPTY); this.title = title; + this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(title); this.viewers = new ArrayList(); @@ -2542,7 +2465,7 @@ index 397cd9651381a8a0ddb4ca173690e9b80428b182..46805a25c0273b76c19a3bbd40078d78 + @Override public int getContainerSize() { - return items.size(); + return this.items.size(); @@ -183,6 +216,12 @@ public class CraftInventoryCustom extends CraftInventory { return null; } @@ -2554,14 +2477,14 @@ index 397cd9651381a8a0ddb4ca173690e9b80428b182..46805a25c0273b76c19a3bbd40078d78 + // Paper end + public String getTitle() { - return title; + return this.title; } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -index 326e8eb49e67ccfbf8f9b23bd6f03ea3576b9d35..945a80ca026c12e16a7ac5bebe56f846a437f847 100644 +index 6a64fbb8b4937f39d5fdc2e2cbec26c83c74c486..7d6b5fdb00a5c1614849735634262a36a4efbd66 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java @@ -64,6 +64,13 @@ public class CraftInventoryView extends InventoryView { - return CraftItemStack.asCraftMirror(container.getSlot(slot).getItem()); + return CraftItemStack.asCraftMirror(this.container.getSlot(slot).getItem()); } + // Paper start @@ -2573,12 +2496,12 @@ index 326e8eb49e67ccfbf8f9b23bd6f03ea3576b9d35..945a80ca026c12e16a7ac5bebe56f846 + @Override public String getTitle() { - return CraftChatMessage.fromComponent(container.getTitle()); + return CraftChatMessage.fromComponent(this.container.getTitle()); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 89a3617068421bb86baf4e8bfd9df2d0626adff7..32fa5ca0df07466e40817341d85d359b282f3078 100644 +index 27bbec5f779e7193818e546dbf02a761ff950719..921d838afc5b7ae47a9ee81b7ae4450543a32d98 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -334,4 +334,17 @@ public final class CraftItemFactory implements ItemFactory { +@@ -337,4 +337,17 @@ public final class CraftItemFactory implements ItemFactory { public Material updateMaterial(ItemMeta meta, Material material) throws IllegalArgumentException { return ((CraftMetaItem) meta).updateMaterial(material); } @@ -2597,7 +2520,7 @@ index 89a3617068421bb86baf4e8bfd9df2d0626adff7..32fa5ca0df07466e40817341d85d359b + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -index 71136bb009d6c8c92595f957ee7680a771ea9a63..306c6483708ae1b41bd16f122d36beec1916a776 100644 +index b7cb3c94d88b2753fd1fc17c2842607576fd7874..f40d6a0048ad5b3f6e31d83894ee89f5ca64fb3a 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java @@ -14,10 +14,17 @@ import org.apache.commons.lang.Validate; @@ -2607,7 +2530,7 @@ index 71136bb009d6c8c92595f957ee7680a771ea9a63..306c6483708ae1b41bd16f122d36beec + @Deprecated // Paper - Adventure public CraftMerchantCustom(String title) { super(new MinecraftMerchant(title)); - getMerchant().craftMerchant = this; + this.getMerchant().craftMerchant = this; } + // Paper start + public CraftMerchantCustom(net.kyori.adventure.text.Component title) { @@ -2637,7 +2560,7 @@ index 71136bb009d6c8c92595f957ee7680a771ea9a63..306c6483708ae1b41bd16f122d36beec @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 6dba12c4f58a462c8d466461eb8b804dd045766d..a592d4a286a775a61192dde2a4d21a0681090415 100644 +index ca359cb1ac5f48d4f75d33946fcddedb270407c2..f8796e5b450cfcd5091d7bd50e873f45bcdbf484 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java @@ -1,8 +1,9 @@ @@ -2805,7 +2728,7 @@ index 6dba12c4f58a462c8d466461eb8b804dd045766d..a592d4a286a775a61192dde2a4d21a06 + // Paper end @Override public String getPage(final int page) { - Validate.isTrue(isValidPage(page), "Invalid page number"); + Validate.isTrue(this.isValidPage(page), "Invalid page number"); @@ -413,7 +552,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { } @@ -2814,7 +2737,7 @@ index 6dba12c4f58a462c8d466461eb8b804dd045766d..a592d4a286a775a61192dde2a4d21a06 + ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { super.serialize(builder); - if (hasTitle()) { + if (this.hasTitle()) { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java index 00445fc7373c70f4cecc4114f9bcfb4b6f27c0e8..0cf60eb9b6ba1a79c9b603c4349debd478101f9a 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java @@ -2837,11 +2760,11 @@ index 00445fc7373c70f4cecc4114f9bcfb4b6f27c0e8..0cf60eb9b6ba1a79c9b603c4349debd4 return builder; } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 2e819849e83967d751f7b0612a7cf4edb5a7264b..cca04daf84e506382365c0ba945cb024bd4d4475 100644 +index 2d775fe575e61a6503aee1bc9623aebce75143cc..970fa1e98c873ea4dfd4b58c56b7ea88283b0512 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -744,6 +744,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); +@@ -745,6 +745,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return !(this.hasDisplayName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isUnbreakable() || this.hasDamage() || this.hasAttributeModifiers()); } + // Paper start @@ -2859,7 +2782,7 @@ index 2e819849e83967d751f7b0612a7cf4edb5a7264b..cca04daf84e506382365c0ba945cb024 @Override public String getDisplayName() { return CraftChatMessage.fromJSONComponent(displayName); -@@ -779,6 +791,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -780,6 +792,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { return this.lore != null && !this.lore.isEmpty(); } @@ -2877,7 +2800,7 @@ index 2e819849e83967d751f7b0612a7cf4edb5a7264b..cca04daf84e506382365c0ba945cb024 + @Override public boolean hasRepairCost() { - return repairCost > 0; + return this.repairCost > 0; diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java index ed4415f6dd588c08c922efd5beebb3b124beb9d6..78a7ac47f20e84ccd67ff44d0bc7a2f2faa0d476 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java @@ -2910,11 +2833,11 @@ index ed4415f6dd588c08c922efd5beebb3b124beb9d6..78a7ac47f20e84ccd67ff44d0bc7a2f2 return new CraftInventoryCustom(owner, size, title); } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b833806a0 100644 +index 4e705b7367b78c2da98d0b174807ecbce75f3a59..0899afd175f969da0df9371d96d3b5e1de4c8533 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java @@ -43,6 +43,17 @@ public final class CraftInventoryCreator { - return converterMap.get(type).createInventory(holder, type); + return this.converterMap.get(type).createInventory(holder, type); } + // Paper start @@ -2929,10 +2852,10 @@ index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b + // Paper end + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - return converterMap.get(type).createInventory(holder, type, title); + return this.converterMap.get(type).createInventory(holder, type, title); } @@ -51,6 +62,12 @@ public final class CraftInventoryCreator { - return DEFAULT_CONVERTER.createInventory(holder, size); + return this.DEFAULT_CONVERTER.createInventory(holder, size); } + // Paper start @@ -2942,7 +2865,7 @@ index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b + // Paper end + public Inventory createInventory(InventoryHolder holder, int size, String title) { - return DEFAULT_CONVERTER.createInventory(holder, size, title); + return this.DEFAULT_CONVERTER.createInventory(holder, size, title); } @@ -59,6 +76,10 @@ public final class CraftInventoryCreator { @@ -2956,11 +2879,11 @@ index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b } } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -index 0395a6235d62126540e370d6ef77e6966c50ca1d..3ef9742a68084d159ea8ed5709298f9863e04a67 100644 +index 1980240d3dc0331ddf2ff56e163e2bfbd3b231ab..7a7f3f53aef601f124d474d9890e23d87dd96900 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java @@ -31,6 +31,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return getInventory(getTileEntity()); + return this.getInventory(this.getTileEntity()); } + // Paper start @@ -2977,8 +2900,8 @@ index 0395a6235d62126540e370d6ef77e6966c50ca1d..3ef9742a68084d159ea8ed5709298f98 + @Override public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - Container te = getTileEntity(); -@@ -54,6 +66,15 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat + Container te = this.getTileEntity(); +@@ -53,6 +65,15 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat return furnace; } @@ -2993,9 +2916,9 @@ index 0395a6235d62126540e370d6ef77e6966c50ca1d..3ef9742a68084d159ea8ed5709298f98 + @Override public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - Container tileEntity = getTileEntity(); -@@ -74,6 +95,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return new BrewingStandBlockEntity(); + Container tileEntity = this.getTileEntity(); +@@ -73,6 +94,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat + return new BrewingStandBlockEntity(BlockPos.ZERO, Blocks.BREWING_STAND.defaultBlockState()); } + // Paper start @@ -3014,11 +2937,11 @@ index 0395a6235d62126540e370d6ef77e6966c50ca1d..3ef9742a68084d159ea8ed5709298f98 public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { // BrewingStand does not extend TileEntityLootable diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -index d5ebb11447a8effa41138a13874fd3e5246dfe71..96ba508c87336d012c1ed5aa982588f55782a2fe 100644 +index c80424fa0494272900ee141eefbf2522ee66d657..2477bb1f2b37406e2c73f18956201762a61ca324 100644 --- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java +++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java @@ -30,6 +30,21 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective - return objective.getName(); + return this.objective.getName(); } + // Paper start @@ -3038,14 +2961,14 @@ index d5ebb11447a8effa41138a13874fd3e5246dfe71..96ba508c87336d012c1ed5aa982588f5 + // Paper end @Override public String getDisplayName() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + CraftScoreboard scoreboard = this.checkState(); diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -index af160d3bdb82f07c6c836a438b8ab37b803c29e2..4c93be31fd95d731327479519ecb34a08785c1ca 100644 +index 589cb3bebb4bb193477cc5064c66830eec3e9138..68aa66c340b7a686a353e2a15084d811a3955a0a 100644 --- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java @@ -27,6 +27,27 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { public CraftObjective registerNewObjective(String name, String criteria) throws IllegalArgumentException { - return registerNewObjective(name, criteria, name); + return this.registerNewObjective(name, criteria, name); } + // Paper start + @Override @@ -3064,7 +2987,7 @@ index af160d3bdb82f07c6c836a438b8ab37b803c29e2..4c93be31fd95d731327479519ecb34a0 + Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); + Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); + CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ net.minecraft.world.scores.Objective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); ++ net.minecraft.world.scores.Objective objective = board.addObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); + return new CraftObjective(this, objective); + } + // Paper end @@ -3080,12 +3003,13 @@ index af160d3bdb82f07c6c836a438b8ab37b803c29e2..4c93be31fd95d731327479519ecb34a0 Validate.notNull(criteria, "Criteria cannot be null"); Validate.notNull(displayName, "Display name cannot be null"); Validate.notNull(renderType, "RenderType cannot be null"); -@@ -44,8 +65,9 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); +@@ -45,7 +66,11 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -- net.minecraft.world.scores.Objective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); + net.minecraft.world.scores.Objective objective = this.board.addObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); - return new CraftObjective(this, objective); ++ ++ CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); + ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); + return new CraftObjective(this, objective);*/ // Paper + return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper @@ -3093,12 +3017,12 @@ index af160d3bdb82f07c6c836a438b8ab37b803c29e2..4c93be31fd95d731327479519ecb34a0 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -index f5237ff19d8b26be0b762659ad0ea6887205b3f9..7ebcba4ada42f5599d56cfdeb75dbf62f2a09b78 100644 +index 81f16dc1ed6e102af298600db75cab21a09bc00f..c2dc4d65170eba2d914cf2efdcc231254fec7c02 100644 --- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java @@ -28,6 +28,55 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { - return team.getName(); + return this.team.getName(); } + // Paper start + @Override @@ -3153,7 +3077,7 @@ index f5237ff19d8b26be0b762659ad0ea6887205b3f9..7ebcba4ada42f5599d56cfdeb75dbf62 @Override public String getDisplayName() throws IllegalStateException { diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -index 35e6ce5f33b3d6b86c3654e6a207e26aa44badb5..b27af66795d902a2e95d692fa0ff18eccbef8a75 100644 +index f9b7b8f7ccc95b73967a51420fd6ce88d80d75fe..0de5a46423ae0403dcbfca630dfd7c5ac1e1761d 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java @@ -290,6 +290,7 @@ public final class CraftChatMessage { @@ -3165,7 +3089,7 @@ index 35e6ce5f33b3d6b86c3654e6a207e26aa44badb5..b27af66795d902a2e95d692fa0ff18ec 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 ef7715774fbdc4c42b217d8192784e09a43fe66f..2d4faef5a2b9c4fe8b65ff4f1346b8375e0e02c8 100644 +index 0f0ffedd2cc3cf1b30b338d8ae3a8ad388dfde53..409515c406f5b5cfac9872f925dbc67159a5d41f 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -57,6 +57,33 @@ public final class CraftMagicNumbers implements UnsafeValues { @@ -3200,26 +3124,26 @@ index ef7715774fbdc4c42b217d8192784e09a43fe66f..2d4faef5a2b9c4fe8b65ff4f1346b837 + // Paper end + public static BlockState getBlock(MaterialData material) { - return getBlock(material.getItemType(), material.getData()); + return CraftMagicNumbers.getBlock(material.getItemType(), material.getData()); } diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java -index f194cf2663919ea18309a0501ddfab5e2ed639dd..4b110d6c6f22ff7c2fa0fd4b459820797066199d 100644 +index 62c66e3179b9557cdba46242df0fb15bce7e7710..73a37638abacdffbff8274291a64ea6cd0be7a5e 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java +++ b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java @@ -80,7 +80,7 @@ public abstract class LazyHashSet implements Set { - return this.reference = makeReference(); + return this.reference = this.makeReference(); } - abstract Set makeReference(); + protected abstract Set makeReference(); // Paper - protected public boolean isLazy() { - return reference == null; + return this.reference == null; diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java -index 103c1407b2946e9cae2271646178e5f243c8abb1..b22b7603f3f66e1b64f413106e7989b30475110b 100644 +index 838d5b877c01be3ef353f434d98e27b46c0a3fb4..5c4c0ba05f10d2d83b22d3e86805cfa85c3b50a9 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java +++ b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java -@@ -15,10 +15,15 @@ public class LazyPlayerSet extends LazyHashSet { +@@ -15,11 +15,17 @@ public class LazyPlayerSet extends LazyHashSet { } @Override @@ -3228,11 +3152,13 @@ index 103c1407b2946e9cae2271646178e5f243c8abb1..b22b7603f3f66e1b64f413106e7989b3 if (reference != null) { throw new IllegalStateException("Reference already created!"); } + List players = this.server.getPlayerList().players; + // Paper start + return makePlayerSet(this.server); + } + public static HashSet makePlayerSet(final MinecraftServer server) { + // Paper end - List players = server.getPlayerList().players; ++ List players = server.getPlayerList().players; HashSet reference = new HashSet(players.size()); for (ServerPlayer player : players) { + reference.add(player.getBukkitEntity()); From 1f8e76b185b321f9dccd4a3eae03f99e725fec84 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Fri, 11 Jun 2021 13:42:57 -0700 Subject: [PATCH 027/226] rebase --- patches/server/0010-Adventure.patch | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/patches/server/0010-Adventure.patch b/patches/server/0010-Adventure.patch index 1260d43d8d..91f7f04894 100644 --- a/patches/server/0010-Adventure.patch +++ b/patches/server/0010-Adventure.patch @@ -964,18 +964,6 @@ index b82b218be1bd849fa280ea1fe0336e279bebfc18..77e35e18754bd2380e1d5f93c62e1d47 @Nullable public static ChatFormatting getById(int colorIndex) { if (colorIndex < 0) { -diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java -index 4760fc27b1d4938a248c05af17fc93ab37084c00..750df4ab2fbfdcf759f4d3451340e66b6764391d 100644 ---- a/src/main/java/net/minecraft/nbt/CompoundTag.java -+++ b/src/main/java/net/minecraft/nbt/CompoundTag.java -@@ -128,7 +128,6 @@ public class CompoundTag implements Tag { - /** - * You must use {@link #hasUUID(String)} before or else it will throw an NPE. - */ -- public UUID getUUID(String prefix) { return getUUID(prefix); } // Paper - OBFHELPER - public UUID getUUID(String key) { - return NbtUtils.loadUUID(this.get(key)); - } diff --git a/src/main/java/net/minecraft/nbt/StringTag.java b/src/main/java/net/minecraft/nbt/StringTag.java index ad1c1fbb15cbd744afe54e1c3b533e51021a89eb..b15cfb9374402d4b42d163bf8e3ec838f19004bc 100644 --- a/src/main/java/net/minecraft/nbt/StringTag.java @@ -1026,7 +1014,7 @@ index 3b8207046d38d3d14719ff6761a22e60a93628b7..c15860c77c7c24b1946c22f140f1b5c1 public > T readEnum(Class enumClass) { diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index 02d253243eb66c30d4f7f6b0e7361518516eefec..847c59dd1b4673f4a03d77717468e07e99fc80a4 100644 +index 83e99af925c87433b59f9bed30dfbf4e490c1b84..b8a0c0411fd2caab21672de7f3e721645b61a8ba 100644 --- a/src/main/java/net/minecraft/network/PacketEncoder.java +++ b/src/main/java/net/minecraft/network/PacketEncoder.java @@ -3,6 +3,7 @@ package net.minecraft.network; @@ -1045,15 +1033,6 @@ index 02d253243eb66c30d4f7f6b0e7361518516eefec..847c59dd1b4673f4a03d77717468e07e try { int i = friendlyByteBuf.writerIndex(); -@@ -46,7 +48,7 @@ public class PacketEncoder extends MessageToByteEncoder> { - } - } catch (Throwable var9) { - LOGGER.error(var9); -- throwable.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? -+ var9.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? - if (packet.isSkippable()) { - throw new SkipPacketException(var9); - } else { diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java index d9aac575213f3bda9c44ea2b3b6d1969ff82f09d..02d19fa4abdee0c8331734932a83e64694356030 100644 --- a/src/main/java/net/minecraft/network/chat/Component.java From 3a3831d6aacf627da6e674afcbb59aae45b4a032 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Fri, 11 Jun 2021 15:37:16 -0700 Subject: [PATCH 028/226] more patches --- patches/api/0006-Adventure.patch | 16 ++++ .../0007-Player-affects-spawning-API.patch} | 0 .../0008-Add-getTPS-method.patch} | 4 +- .../0009-Entity-Origin-API.patch} | 0 .../0010-Version-Command-2.0.patch} | 0 .../0025-Optimize-TileEntity-Ticking.patch | 2 + ...nfigurable-top-of-nether-void-damage.patch | 93 ------------------- patches/server/0009-Timings-v2.patch | 6 +- patches/server/0010-Adventure.patch | 48 ++++++---- ...ctus-bamboo-and-reed-growth-heights.patch} | 24 ++--- ...igurable-baby-zombie-movement-speed.patch} | 4 +- ...13-Configurable-fishing-time-ranges.patch} | 8 +- ...-mobs-to-jump-and-take-water-damage.patch} | 31 +++---- ...despawn-distances-for-living-entiti.patch} | 8 +- ...-Allow-for-toggling-of-spawn-chunks.patch} | 4 +- ...k-and-tnt-entities-at-the-specified.patch} | 30 ++---- ...ent-crashes-server-lists-and-Mojang.patch} | 38 ++++---- ...0019-Implement-Paper-VersionChecker.patch} | 2 +- ...-version-history-to-version-command.patch} | 4 +- .../0021-Player-affects-spawning-API.patch} | 73 +++++++-------- ...e-invalid-mob-spawner-tile-entities.patch} | 19 ++-- ...23-Further-improve-server-tick-loop.patch} | 49 +++++----- ...24-Only-refresh-abilities-if-needed.patch} | 14 +-- .../0025-Entity-Origin-API.patch} | 82 ++++++++-------- ...vent-tile-entity-and-entity-crashes.patch} | 59 ++++++------ ...nfigurable-top-of-nether-void-damage.patch | 47 ++++++++++ ...-before-converting-and-renaming-pla.patch} | 6 +- .../0029-Always-tick-falling-blocks.patch} | 6 +- .../0030-Configurable-end-credits.patch} | 17 +--- ...explosions-processing-dead-entities.patch} | 4 +- .../0032-Optimize-explosions.patch} | 16 ++-- 31 files changed, 332 insertions(+), 382 deletions(-) rename patches/{api-unmapped/0006-Player-affects-spawning-API.patch => api/0007-Player-affects-spawning-API.patch} (100%) rename patches/{api-unmapped/0007-Add-getTPS-method.patch => api/0008-Add-getTPS-method.patch} (87%) rename patches/{api-unmapped/0008-Entity-Origin-API.patch => api/0009-Entity-Origin-API.patch} (100%) rename patches/{api-unmapped/0009-Version-Command-2.0.patch => api/0010-Version-Command-2.0.patch} (100%) rename patches/{server-remapped => removed/1.17}/0025-Optimize-TileEntity-Ticking.patch (99%) delete mode 100644 patches/server-remapped/0030-Configurable-top-of-nether-void-damage.patch rename patches/{server-remapped/0013-Configurable-cactus-bamboo-and-reed-growth-heights.patch => server/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch} (87%) rename patches/{server-remapped/0014-Configurable-baby-zombie-movement-speed.patch => server/0012-Configurable-baby-zombie-movement-speed.patch} (95%) rename patches/{server-remapped/0015-Configurable-fishing-time-ranges.patch => server/0013-Configurable-fishing-time-ranges.patch} (83%) rename patches/{server-remapped/0016-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch => server/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch} (78%) rename patches/{server-remapped/0017-Add-configurable-despawn-distances-for-living-entiti.patch => server/0015-Add-configurable-despawn-distances-for-living-entiti.patch} (92%) rename patches/{server-remapped/0018-Allow-for-toggling-of-spawn-chunks.patch => server/0016-Allow-for-toggling-of-spawn-chunks.patch} (91%) rename patches/{server-remapped/0019-Drop-falling-block-and-tnt-entities-at-the-specified.patch => server/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch} (74%) rename patches/{server-remapped/0020-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch => server/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch} (84%) rename patches/{server-remapped/0021-Implement-Paper-VersionChecker.patch => server/0019-Implement-Paper-VersionChecker.patch} (98%) rename patches/{server-remapped/0022-Add-version-history-to-version-command.patch => server/0020-Add-version-history-to-version-command.patch} (98%) rename patches/{server-remapped/0023-Player-affects-spawning-API.patch => server/0021-Player-affects-spawning-API.patch} (71%) rename patches/{server-remapped/0024-Remove-invalid-mob-spawner-tile-entities.patch => server/0022-Remove-invalid-mob-spawner-tile-entities.patch} (62%) rename patches/{server-remapped/0026-Further-improve-server-tick-loop.patch => server/0023-Further-improve-server-tick-loop.patch} (82%) rename patches/{server-remapped/0027-Only-refresh-abilities-if-needed.patch => server/0024-Only-refresh-abilities-if-needed.patch} (56%) rename patches/{server-remapped/0028-Entity-Origin-API.patch => server/0025-Entity-Origin-API.patch} (61%) rename patches/{server-remapped/0029-Prevent-tile-entity-and-entity-crashes.patch => server/0026-Prevent-tile-entity-and-entity-crashes.patch} (60%) create mode 100644 patches/server/0027-Configurable-top-of-nether-void-damage.patch rename patches/{server-remapped/0031-Check-online-mode-before-converting-and-renaming-pla.patch => server/0028-Check-online-mode-before-converting-and-renaming-pla.patch} (75%) rename patches/{server-remapped/0032-Always-tick-falling-blocks.patch => server/0029-Always-tick-falling-blocks.patch} (73%) rename patches/{server-remapped/0033-Configurable-end-credits.patch => server/0030-Configurable-end-credits.patch} (63%) rename patches/{server-remapped/0034-Fix-lag-from-explosions-processing-dead-entities.patch => server/0031-Fix-lag-from-explosions-processing-dead-entities.patch} (89%) rename patches/{server-remapped/0035-Optimize-explosions.patch => server/0032-Optimize-explosions.patch} (91%) diff --git a/patches/api/0006-Adventure.patch b/patches/api/0006-Adventure.patch index bbfafdf464..002a345853 100644 --- a/patches/api/0006-Adventure.patch +++ b/patches/api/0006-Adventure.patch @@ -6,6 +6,22 @@ Subject: [PATCH] Adventure Co-authored-by: zml Co-authored-by: Jake Potrebic +diff --git a/build.gradle.kts b/build.gradle.kts +index 95327c3971cd57e01da2a62e1b72ba15fcbb63f4..4c197e7d9966f8789e6709461e59fc89355afd9c 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -17,6 +17,11 @@ dependencies { + api("org.yaml:snakeyaml:1.29") + api("com.googlecode.json-simple:json-simple:1.1.1") // Paper + api("it.unimi.dsi:fastutil:8.2.2") ++ api(platform("net.kyori:adventure-bom:4.7.0")) ++ api("net.kyori:adventure-api") ++ api("net.kyori:adventure-text-serializer-gson") ++ api("net.kyori:adventure-text-serializer-legacy") ++ api("net.kyori:adventure-text-serializer-plain") + + compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/pom.xml b/pom.xml index 1ebc4c096638128194cea9c2a4131f901e7d6896..cae43ce5c1287a4cd117fd069d34ebc1b64b7fdb 100644 --- a/pom.xml diff --git a/patches/api-unmapped/0006-Player-affects-spawning-API.patch b/patches/api/0007-Player-affects-spawning-API.patch similarity index 100% rename from patches/api-unmapped/0006-Player-affects-spawning-API.patch rename to patches/api/0007-Player-affects-spawning-API.patch diff --git a/patches/api-unmapped/0007-Add-getTPS-method.patch b/patches/api/0008-Add-getTPS-method.patch similarity index 87% rename from patches/api-unmapped/0007-Add-getTPS-method.patch rename to patches/api/0008-Add-getTPS-method.patch index 22aef5d962..fc33d04f13 100644 --- a/patches/api-unmapped/0007-Add-getTPS-method.patch +++ b/patches/api/0008-Add-getTPS-method.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add getTPS method diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index ab4d5aca6251b620ef5d654fa4ea3fc31783c2f2..0636edd8d9121eabfa60957c8c224261d228a16b 100644 +index f3b07f0f1b3be14c8ecd059e1f3594cc90f84442..1014871a3d7bfcf2b749d20e6ef8096876f9b4d7 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1543,6 +1543,17 @@ public final class Bukkit { @@ -27,7 +27,7 @@ index ab4d5aca6251b620ef5d654fa4ea3fc31783c2f2..0636edd8d9121eabfa60957c8c224261 * 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 b862f22d5f31934eb46b50ecf04f8c1bf23c5044..5c638e0d45e8896382bdbf9b9c10474b05a97df5 100644 +index 7abdbf43e2f52e8e9e0f7bd7c7a58baf347e3929..3f74dc04df61e7d038c99ad9c1c3bfff086a019a 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1301,6 +1301,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api-unmapped/0008-Entity-Origin-API.patch b/patches/api/0009-Entity-Origin-API.patch similarity index 100% rename from patches/api-unmapped/0008-Entity-Origin-API.patch rename to patches/api/0009-Entity-Origin-API.patch diff --git a/patches/api-unmapped/0009-Version-Command-2.0.patch b/patches/api/0010-Version-Command-2.0.patch similarity index 100% rename from patches/api-unmapped/0009-Version-Command-2.0.patch rename to patches/api/0010-Version-Command-2.0.patch diff --git a/patches/server-remapped/0025-Optimize-TileEntity-Ticking.patch b/patches/removed/1.17/0025-Optimize-TileEntity-Ticking.patch similarity index 99% rename from patches/server-remapped/0025-Optimize-TileEntity-Ticking.patch rename to patches/removed/1.17/0025-Optimize-TileEntity-Ticking.patch index db2d2e1d05..79f438b892 100644 --- a/patches/server-remapped/0025-Optimize-TileEntity-Ticking.patch +++ b/patches/removed/1.17/0025-Optimize-TileEntity-Ticking.patch @@ -3,6 +3,8 @@ From: Aikar Date: Sun, 8 Mar 2015 22:55:25 -0600 Subject: [PATCH] Optimize TileEntity Ticking +ticking logic changes implemented by mojang + diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java index 94adf0275a2e7093c152cc3b8b0a5747b3a13a86..5bcf9cefc29eb20e2cfbfb49e2b2662ec394a87e 100644 diff --git a/patches/server-remapped/0030-Configurable-top-of-nether-void-damage.patch b/patches/server-remapped/0030-Configurable-top-of-nether-void-damage.patch deleted file mode 100644 index 805929cc33..0000000000 --- a/patches/server-remapped/0030-Configurable-top-of-nether-void-damage.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 23:58:50 -0600 -Subject: [PATCH] Configurable top of nether void damage - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index d16ae924bcbe31c964f7fb448757c748e5c4418c..4bba6977a0287837b8927718c040ac61463f0469 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -134,4 +134,19 @@ public class PaperWorldConfig { - if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); - if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); - } -+ -+ public int netherVoidTopDamageHeight; -+ public boolean doNetherTopVoidDamage() { return netherVoidTopDamageHeight > 0; } -+ private void netherVoidTopDamageHeight() { -+ netherVoidTopDamageHeight = getInt("nether-ceiling-void-damage-height", 0); -+ log("Top of the nether void damage height: " + netherVoidTopDamageHeight); -+ -+ if (PaperConfig.version < 18) { -+ boolean legacy = getBoolean("nether-ceiling-void-damage", false); -+ if (legacy) { -+ netherVoidTopDamageHeight = 128; -+ set("nether-ceiling-void-damage-height", netherVoidTopDamageHeight); -+ } -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index fd5b41ceb97dc8aa975f1c0ae05b58d0b09f2cd6..f3f48c268639937874dd39eea9bd8e119eebdce7 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -499,9 +499,16 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.fallDistance *= 0.5F; - } - -- if (this.getY() < -64.0D) { -- this.outOfWorld(); -+ // Paper start - Configurable nether ceiling damage -+ -+ // Extracted to own function -+ /* -+ if (this.locY() < -64.0D) { -+ this.an(); - } -+ */ -+ this.performVoidDamage(); -+ // Paper end - - if (!this.level.isClientSide) { - this.setSharedFlag(0, this.remainingFireTicks > 0); -@@ -594,6 +601,17 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.setRemainingFireTicks(0); - } - -+ // Paper start -+ protected void performVoidDamage() { -+ if (this.getY() < -64.0D || (this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER -+ && level.paperConfig.doNetherTopVoidDamage() -+ && this.getY() >= level.paperConfig.netherVoidTopDamageHeight)) { -+ this.doVoidDamage(); -+ } -+ } -+ // Paper end -+ -+ protected final void doVoidDamage() { this.outOfWorld(); } // Paper - OBFHELPER - protected void outOfWorld() { - this.remove(); - } -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -index 9503376895d90e8db0d4f7b164e2d813dd1a4a3a..7ba74b0a9319e29077b5afe3019a463ed3004813 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -@@ -329,9 +329,15 @@ public abstract class AbstractMinecart extends Entity { - this.setDamage(this.getDamage() - 1.0F); - } - -- if (this.getY() < -64.0D) { -- this.outOfWorld(); -+ // Paper start - Configurable nether ceiling damage -+ // Extracted to own function -+ /* -+ if (this.locY() < -64.0D) { -+ this.an(); - } -+ */ -+ this.performVoidDamage(); -+ // Paper end - - // this.doPortalTick(); // CraftBukkit - handled in postTick - if (this.level.isClientSide) { diff --git a/patches/server/0009-Timings-v2.patch b/patches/server/0009-Timings-v2.patch index 77a87bfdee..0c79786b74 100644 --- a/patches/server/0009-Timings-v2.patch +++ b/patches/server/0009-Timings-v2.patch @@ -163,7 +163,7 @@ index 0000000000000000000000000000000000000000..72f9e1978394afb6e5cc1c0d085d4158 +} diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java new file mode 100644 -index 0000000000000000000000000000000000000000..2afec58d8eadc9357d8aa6b171d9249cdc5b8c4a +index 0000000000000000000000000000000000000000..f27fadc15cb7f5c782e45885ec6a5a69963beade --- /dev/null +++ b/src/main/java/co/aikar/timings/TimingsExport.java @@ -0,0 +1,376 @@ @@ -316,8 +316,8 @@ index 0000000000000000000000000000000000000000..2afec58d8eadc9357d8aa6b171d9249c + ); + + parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getAllLevels(), world -> { -+ if (world.serverLevelData.getLevelName().equals("worldeditregentempworld")) return null; -+ return pair(world.serverLevelData.getLevelName(), createObject( ++ if (world.getWorld().getName().equals("worldeditregentempworld")) return null; ++ return pair(world.getWorld().getName(), createObject( + pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { + return pair(rule, world.getWorld().getGameRuleValue(rule)); + })), diff --git a/patches/server/0010-Adventure.patch b/patches/server/0010-Adventure.patch index 91f7f04894..1b8b859d8f 100644 --- a/patches/server/0010-Adventure.patch +++ b/patches/server/0010-Adventure.patch @@ -22,10 +22,10 @@ index 1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7..429b74474ced04d8dd8f038b8590b8df } diff --git a/src/main/java/io/papermc/paper/adventure/AdventureComponent.java b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java new file mode 100644 -index 0000000000000000000000000000000000000000..4b4cec054ad0146773b722c7e3708f988aeeb76d +index 0000000000000000000000000000000000000000..e597a90def72c5903382d7169fb7a2fb667b8a69 --- /dev/null +++ b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java -@@ -0,0 +1,76 @@ +@@ -0,0 +1,82 @@ +package io.papermc.paper.adventure; + +import com.google.gson.JsonElement; @@ -37,12 +37,13 @@ index 0000000000000000000000000000000000000000..4b4cec054ad0146773b722c7e3708f98 +import net.kyori.adventure.text.TextComponent; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Style; ++import net.minecraft.util.FormattedCharSequence; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +public final class AdventureComponent implements net.minecraft.network.chat.Component { + final Component wrapped; -+ private @MonotonicNonNull net.minecraft.network.chat.Component converted; ++ private net.minecraft.network.chat.@MonotonicNonNull Component converted; + + public AdventureComponent(final Component wrapped) { + this.wrapped = wrapped; @@ -57,7 +58,7 @@ index 0000000000000000000000000000000000000000..4b4cec054ad0146773b722c7e3708f98 + return converted; + } + -+ public @Nullable net.minecraft.network.chat.Component deepConvertedIfPresent() { ++ public net.minecraft.network.chat.@Nullable Component deepConvertedIfPresent() { + return this.converted; + } + @@ -95,6 +96,11 @@ index 0000000000000000000000000000000000000000..4b4cec054ad0146773b722c7e3708f98 + return this.deepConverted().copy(); + } + ++ @Override ++ public FormattedCharSequence getVisualOrderText() { ++ return this.deepConverted().getVisualOrderText(); ++ } ++ + public static class Serializer implements JsonSerializer { + @Override + public JsonElement serialize(final AdventureComponent src, final Type type, final JsonSerializationContext context) { @@ -821,49 +827,52 @@ index 0000000000000000000000000000000000000000..f72511a71c01718be48ee6b714e902d0 +} diff --git a/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java new file mode 100644 -index 0000000000000000000000000000000000000000..ee6d9d5c072d68cace63068a8e2ed603ad475378 +index 0000000000000000000000000000000000000000..7493efba31403cbe7f26e493f165f1b83aa847bb --- /dev/null +++ b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java -@@ -0,0 +1,41 @@ +@@ -0,0 +1,44 @@ +package io.papermc.paper.adventure; + +import java.util.Set; +import java.util.function.Consumer; ++import java.util.function.Function; ++ +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; +import net.minecraft.network.protocol.game.ClientboundBossEventPacket; ++import net.minecraft.world.BossEvent; +import org.checkerframework.checker.nullness.qual.NonNull; + +public final class VanillaBossBarListener implements BossBar.Listener { -+ private final Consumer action; ++ private final Consumer> action; + -+ public VanillaBossBarListener(final Consumer action) { ++ public VanillaBossBarListener(final Consumer> action) { + this.action = action; + } + + @Override + public void bossBarNameChanged(final @NonNull BossBar bar, final @NonNull Component oldName, final @NonNull Component newName) { -+ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_NAME); ++ this.action.accept(ClientboundBossEventPacket::createUpdateNamePacket); + } + + @Override + public void bossBarProgressChanged(final @NonNull BossBar bar, final float oldProgress, final float newProgress) { -+ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_PCT); ++ this.action.accept(ClientboundBossEventPacket::createUpdateProgressPacket); + } + + @Override + public void bossBarColorChanged(final @NonNull BossBar bar, final BossBar.@NonNull Color oldColor, final BossBar.@NonNull Color newColor) { -+ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_STYLE); ++ this.action.accept(ClientboundBossEventPacket::createUpdateStylePacket); + } + + @Override + public void bossBarOverlayChanged(final @NonNull BossBar bar, final BossBar.@NonNull Overlay oldOverlay, final BossBar.@NonNull Overlay newOverlay) { -+ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_STYLE); ++ this.action.accept(ClientboundBossEventPacket::createUpdateStylePacket); + } + + @Override + public void bossBarFlagsChanged(final @NonNull BossBar bar, final @NonNull Set flagsAdded, final @NonNull Set flagsRemoved) { -+ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_PROPERTIES); ++ this.action.accept(ClientboundBossEventPacket::createUpdatePropertiesPacket); + } +} diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java @@ -2373,7 +2382,7 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.javaE new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -index 6486a76466691f958349a4706d7c9caff9cb8f64..1a4e2534e8a2114125c505f46868ba4e3f2880a0 100644 +index 6486a76466691f958349a4706d7c9caff9cb8f64..08fc05836b26f5f93ae74324705d5f593b57315a 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java @@ -19,6 +19,12 @@ public class CraftInventoryCustom extends CraftInventory { @@ -2433,7 +2442,7 @@ index 6486a76466691f958349a4706d7c9caff9cb8f64..1a4e2534e8a2114125c505f46868ba4e + // Paper start + public MinecraftInventory(final InventoryHolder owner, final int size, final net.kyori.adventure.text.Component title) { + Validate.notNull(title, "Title cannot be null"); -+ this.items = NonNullList.a(size, ItemStack.EMPTY); ++ this.items = NonNullList.withSize(size, ItemStack.EMPTY); + this.title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); + this.adventure$title = title; + this.viewers = new ArrayList(); @@ -2539,7 +2548,7 @@ index b7cb3c94d88b2753fd1fc17c2842607576fd7874..f40d6a0048ad5b3f6e31d83894ee89f5 @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 ca359cb1ac5f48d4f75d33946fcddedb270407c2..f8796e5b450cfcd5091d7bd50e873f45bcdbf484 100644 +index ca359cb1ac5f48d4f75d33946fcddedb270407c2..a33dd184ea51df7e59ed08e5e2b0ea4ed9dadff5 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java @@ -1,8 +1,9 @@ @@ -2553,7 +2562,7 @@ index ca359cb1ac5f48d4f75d33946fcddedb270407c2..f8796e5b450cfcd5091d7bd50e873f45 import java.util.ArrayList; import java.util.Arrays; import java.util.List; -@@ -17,9 +18,12 @@ import org.bukkit.craftbukkit.util.CraftChatMessage; +@@ -17,9 +18,11 @@ import org.bukkit.craftbukkit.util.CraftChatMessage; import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.BookMeta.Generation; @@ -2562,11 +2571,10 @@ index ca359cb1ac5f48d4f75d33946fcddedb270407c2..f8796e5b450cfcd5091d7bd50e873f45 // Spigot start import static org.spigotmc.ValidateUtils.*; + -+import BookMetaBuilder; import java.util.AbstractList; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.chat.ComponentSerializer; -@@ -269,6 +273,141 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { +@@ -269,6 +272,141 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { this.generation = (generation == null) ? null : generation.ordinal(); } @@ -2708,7 +2716,7 @@ index ca359cb1ac5f48d4f75d33946fcddedb270407c2..f8796e5b450cfcd5091d7bd50e873f45 @Override public String getPage(final int page) { Validate.isTrue(this.isValidPage(page), "Invalid page number"); -@@ -413,7 +552,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { +@@ -413,7 +551,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { } @Override diff --git a/patches/server-remapped/0013-Configurable-cactus-bamboo-and-reed-growth-heights.patch b/patches/server/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch similarity index 87% rename from patches/server-remapped/0013-Configurable-cactus-bamboo-and-reed-growth-heights.patch rename to patches/server/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch index 2bef4fada9..39e3250118 100644 --- a/patches/server-remapped/0013-Configurable-cactus-bamboo-and-reed-growth-heights.patch +++ b/patches/server/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch @@ -29,19 +29,19 @@ index b31109d2dadd29e8852468c19265066b773d2be0..3618cc017feb60e257a28f67cbddca3f + } } diff --git a/src/main/java/net/minecraft/world/level/block/BambooBlock.java b/src/main/java/net/minecraft/world/level/block/BambooBlock.java -index 8f423ae6261434a670bb94aa70b6bc1694f1fc45..36583c189aa5e55de7f5eba362285e57c8279176 100644 +index 7f40f6206f10a78fb74c19bd62c584f9f5c3e635..878b8fb992b448f0a644f7fa2c2bded191ff8268 100644 --- a/src/main/java/net/minecraft/world/level/block/BambooBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BambooBlock.java -@@ -124,7 +124,7 @@ public class BambooBlock extends Block implements BonemealableBlock { +@@ -137,7 +137,7 @@ public class BambooBlock extends Block implements BonemealableBlock { if (random.nextInt(Math.max(1, (int) (100.0F / world.spigotConfig.bambooModifier) * 3)) == 0 && world.isEmptyBlock(pos.above()) && world.getRawBrightness(pos.above(), 0) >= 9) { // Spigot - int i = this.getHeightBelowUpToMax(world, pos) + 1; + int i = this.getHeightBelowUpToMax((BlockGetter) world, pos) + 1; - if (i < 16) { + if (i < world.paperConfig.bambooMaxHeight) { // Paper this.growBamboo(state, (Level) world, pos, random, i); } } -@@ -155,7 +155,7 @@ public class BambooBlock extends Block implements BonemealableBlock { +@@ -168,7 +168,7 @@ public class BambooBlock extends Block implements BonemealableBlock { int i = this.getHeightAboveUpToMax(world, pos); int j = this.getHeightBelowUpToMax(world, pos); @@ -50,7 +50,7 @@ index 8f423ae6261434a670bb94aa70b6bc1694f1fc45..36583c189aa5e55de7f5eba362285e57 } @Override -@@ -174,7 +174,7 @@ public class BambooBlock extends Block implements BonemealableBlock { +@@ -187,7 +187,7 @@ public class BambooBlock extends Block implements BonemealableBlock { BlockPos blockposition1 = pos.above(i); BlockState iblockdata1 = world.getBlockState(blockposition1); @@ -59,7 +59,7 @@ index 8f423ae6261434a670bb94aa70b6bc1694f1fc45..36583c189aa5e55de7f5eba362285e57 return; } -@@ -215,7 +215,7 @@ public class BambooBlock extends Block implements BonemealableBlock { +@@ -228,7 +228,7 @@ public class BambooBlock extends Block implements BonemealableBlock { } int j = (Integer) state.getValue(BambooBlock.AGE) != 1 && !iblockdata2.is(Blocks.BAMBOO) ? 0 : 1; @@ -68,7 +68,7 @@ index 8f423ae6261434a670bb94aa70b6bc1694f1fc45..36583c189aa5e55de7f5eba362285e57 // CraftBukkit start if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, pos.above(), (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(BambooBlock.AGE, j)).setValue(BambooBlock.LEAVES, blockpropertybamboosize)).setValue(BambooBlock.STAGE, k), 3)) { -@@ -230,7 +230,7 @@ public class BambooBlock extends Block implements BonemealableBlock { +@@ -243,7 +243,7 @@ public class BambooBlock extends Block implements BonemealableBlock { protected int getHeightAboveUpToMax(BlockGetter world, BlockPos pos) { int i; @@ -77,7 +77,7 @@ index 8f423ae6261434a670bb94aa70b6bc1694f1fc45..36583c189aa5e55de7f5eba362285e57 ; } -@@ -240,7 +240,7 @@ public class BambooBlock extends Block implements BonemealableBlock { +@@ -253,7 +253,7 @@ public class BambooBlock extends Block implements BonemealableBlock { protected int getHeightBelowUpToMax(BlockGetter world, BlockPos pos) { int i; @@ -87,10 +87,10 @@ index 8f423ae6261434a670bb94aa70b6bc1694f1fc45..36583c189aa5e55de7f5eba362285e57 } diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java -index d07fd9c1f726b1d45992352408499034c12683e6..de61393e3f702554817d81ff10693ec3fb63d492 100644 +index d6aad164b4910f86ff613db9b337ff174e69e4d7..722f1816cd4130fa4b1e2310badedc77ab96eee6 100644 --- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java +++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java -@@ -54,7 +54,7 @@ public class CactusBlock extends Block { +@@ -56,7 +56,7 @@ public class CactusBlock extends Block { ; } @@ -100,10 +100,10 @@ index d07fd9c1f726b1d45992352408499034c12683e6..de61393e3f702554817d81ff10693ec3 if (j >= (byte) range(3, ((100.0F / world.spigotConfig.cactusModifier) * 15) + 0.5F, 15)) { // Spigot diff --git a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java -index 25f634ee93fa4678eaf09694d98783f2aef9d0f0..a795732af122204b88a01311e73892658132da25 100644 +index 77e9c50d2c64e7c7a6e658a2dba8919953c1842c..dbd0147ad08fb825b10665859054f17c9125b621 100644 --- a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java +++ b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java -@@ -51,7 +51,7 @@ public class SugarCaneBlock extends Block { +@@ -53,7 +53,7 @@ public class SugarCaneBlock extends Block { ; } diff --git a/patches/server-remapped/0014-Configurable-baby-zombie-movement-speed.patch b/patches/server/0012-Configurable-baby-zombie-movement-speed.patch similarity index 95% rename from patches/server-remapped/0014-Configurable-baby-zombie-movement-speed.patch rename to patches/server/0012-Configurable-baby-zombie-movement-speed.patch index 1b143bb4a0..11104d0177 100644 --- a/patches/server-remapped/0014-Configurable-baby-zombie-movement-speed.patch +++ b/patches/server/0012-Configurable-baby-zombie-movement-speed.patch @@ -25,7 +25,7 @@ index 3618cc017feb60e257a28f67cbddca3f792a9833..796c17e0941922a9716212c6eae91643 + } } diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 992c9646c274350b30c1abb75e0469adc471397f..94e2a8f74e74d68d4a9b82b667fbff24b7e9e629 100644 +index 84a8269060acaa5bf55a1d0a3f79e093bf2e30e5..017d8de4d09f524aed2ee03af7ef79468503edf0 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java @@ -79,7 +79,7 @@ import org.bukkit.event.entity.EntityTransformEvent; @@ -37,7 +37,7 @@ index 992c9646c274350b30c1abb75e0469adc471397f..94e2a8f74e74d68d4a9b82b667fbff24 private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); private static final EntityDataAccessor DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT); public static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); -@@ -182,9 +182,9 @@ public class Zombie extends Monster { +@@ -187,9 +187,9 @@ public class Zombie extends Monster { if (this.level != null && !this.level.isClientSide) { AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); diff --git a/patches/server-remapped/0015-Configurable-fishing-time-ranges.patch b/patches/server/0013-Configurable-fishing-time-ranges.patch similarity index 83% rename from patches/server-remapped/0015-Configurable-fishing-time-ranges.patch rename to patches/server/0013-Configurable-fishing-time-ranges.patch index 33edff1ef7..067aef2db8 100644 --- a/patches/server-remapped/0015-Configurable-fishing-time-ranges.patch +++ b/patches/server/0013-Configurable-fishing-time-ranges.patch @@ -22,11 +22,11 @@ index 796c17e0941922a9716212c6eae91643d8360418..78948c42b13194005bdbbbc69c2b7ae0 + } } diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -index d74dae6d7bd78c082b39a4e38da640a57c40b341..2f67c2065ef29f17f12190b25bd1ea53e1fb55b4 100644 +index dde25bf5e4e6e6514a8141e4dee473d96eee83f5..c30b53d07bcd2575d65c323d8170573bbe85f212 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -@@ -82,6 +82,10 @@ public class FishingHook extends Projectile { - owner.fishing = this; +@@ -83,6 +83,10 @@ public class FishingHook extends Projectile { + this.noCulling = true; this.luck = Math.max(0, lureLevel); this.lureSpeed = Math.max(0, luckOfTheSeaLevel); + // Paper start @@ -35,4 +35,4 @@ index d74dae6d7bd78c082b39a4e38da640a57c40b341..2f67c2065ef29f17f12190b25bd1ea53 + // paper end } - public FishingHook(net.minecraft.world.entity.player.Player thrower, Level world, int lureLevel, int luckOfTheSeaLevel) { + public FishingHook(EntityType type, Level world) { diff --git a/patches/server-remapped/0016-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/patches/server/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch similarity index 78% rename from patches/server-remapped/0016-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch rename to patches/server/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch index 6f5fd676df..c8750f1179 100644 --- a/patches/server-remapped/0016-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch +++ b/patches/server/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch @@ -19,10 +19,10 @@ index 78948c42b13194005bdbbbc69c2b7ae0732a78c5..b41e7922dd96c3358eb849ab39982a75 + } } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 2a7f587e19fcdd6d01b360d6b47d9eadd9df92cc..584e83441a9fef88eb1b0a29bec8bda29d6a0c9c 100644 +index c8ebce55b4e3838bf70b115ffb0b634b3548a7dd..b82dd96147224057ea0e0dc92506b27ffbc9f034 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1104,6 +1104,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1264,6 +1264,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n return this.isInWater() || this.isInRain(); } @@ -31,25 +31,18 @@ index 2a7f587e19fcdd6d01b360d6b47d9eadd9df92cc..584e83441a9fef88eb1b0a29bec8bda2 return this.isInWater() || this.isInRain() || this.isInBubbleColumn(); } diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 99cb4dc1a1009d4a29e651c94d21babcc61388ed..151ebcffc1f2ae02fa55ab83d2ae7d8a0057f29d 100644 +index e4f3dbff2605243039f9f59f025c931b3fb309c5..a5d90af5275c9c8069932f711069a6d422303d05 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.entity; - -+import PathfinderGoalFloat; - import com.google.common.collect.Maps; - import java.util.Arrays; - import java.util.Iterator; -@@ -96,6 +97,7 @@ public abstract class Mob extends LivingEntity { +@@ -103,6 +103,7 @@ public abstract class Mob extends LivingEntity { private final BodyRotationControl bodyRotationControl; protected PathNavigation navigation; public GoalSelector goalSelector; -+ @Nullable public PathfinderGoalFloat goalFloat; // Paper ++ @Nullable public net.minecraft.world.entity.ai.goal.FloatGoal goalFloat; // Paper public GoalSelector targetSelector; private LivingEntity target; private final Sensing sensing; -@@ -782,7 +784,17 @@ public abstract class Mob extends LivingEntity { +@@ -794,7 +795,17 @@ public abstract class Mob extends LivingEntity { @Override protected final void serverAiStep() { ++this.noActionTime; @@ -59,7 +52,7 @@ index 99cb4dc1a1009d4a29e651c94d21babcc61388ed..151ebcffc1f2ae02fa55ab83d2ae7d8a + if (goalFloat.validConditions()) goalFloat.update(); + this.getJumpControl().jumpIfSet(); + } -+ if ((this instanceof EntityBlaze || this instanceof EntityEnderman) && isInWaterOrRainOrBubble()) { ++ if ((this instanceof net.minecraft.world.entity.monster.Blaze || this instanceof net.minecraft.world.entity.monster.EnderMan) && isInWaterOrRainOrBubble()) { + hurt(DamageSource.DROWN, 1.0F); + } + return; @@ -69,10 +62,10 @@ index 99cb4dc1a1009d4a29e651c94d21babcc61388ed..151ebcffc1f2ae02fa55ab83d2ae7d8a this.sensing.tick(); this.level.getProfiler().pop(); diff --git a/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java b/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java -index 5f7ad2b57d8d8f0f6a7d880f55e08b52f017cf51..09d1cda50ce9076e9236d124aa7766a26a50dae1 100644 +index 4b85418a53018ce9a70fddde2ab18d52d2fc97d1..83c68b492d4596583160e3c6d56080a11777719c 100644 --- a/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java +++ b/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java -@@ -15,6 +15,7 @@ public class JumpControl { +@@ -14,6 +14,7 @@ public class JumpControl implements Control { this.jump = true; } @@ -81,10 +74,10 @@ index 5f7ad2b57d8d8f0f6a7d880f55e08b52f017cf51..09d1cda50ce9076e9236d124aa7766a2 this.mob.setJumping(this.jump); this.jump = false; diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java -index 7ea5cb5a92ff3b66859ebcd53031aa06689bd329..790b5646683247ef757095a0763dc52701afe97b 100644 +index 54085b104547f2fe7c08ff8aa4839b1230877bca..5a2e3cc833b3fa7d6fcea1474e25c469a53b3bae 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java -@@ -11,15 +11,18 @@ public class FloatGoal extends Goal { +@@ -9,15 +9,18 @@ public class FloatGoal extends Goal { public FloatGoal(Mob mob) { this.mob = mob; @@ -96,7 +89,7 @@ index 7ea5cb5a92ff3b66859ebcd53031aa06689bd329..790b5646683247ef757095a0763dc527 + public final boolean validConditions() { return this.canUse(); } // Paper - OBFHELPER @Override public boolean canUse() { - return this.mob.isInWater() && this.mob.getFluidHeight((Tag) FluidTags.WATER) > this.mob.getFluidJumpThreshold() || this.mob.isInLava(); + return this.mob.isInWater() && this.mob.getFluidHeight(FluidTags.WATER) > this.mob.getFluidJumpThreshold() || this.mob.isInLava(); } + public void update() { this.tick(); } // Paper - OBFHELPER diff --git a/patches/server-remapped/0017-Add-configurable-despawn-distances-for-living-entiti.patch b/patches/server/0015-Add-configurable-despawn-distances-for-living-entiti.patch similarity index 92% rename from patches/server-remapped/0017-Add-configurable-despawn-distances-for-living-entiti.patch rename to patches/server/0015-Add-configurable-despawn-distances-for-living-entiti.patch index 4a3d5d60ea..c304874a50 100644 --- a/patches/server-remapped/0017-Add-configurable-despawn-distances-for-living-entiti.patch +++ b/patches/server/0015-Add-configurable-despawn-distances-for-living-entiti.patch @@ -30,16 +30,16 @@ index b41e7922dd96c3358eb849ab39982a75736e3476..2f0d582baf0eb2bb477944d0cb1369db + } } diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 151ebcffc1f2ae02fa55ab83d2ae7d8a0057f29d..4d3000067ae3d46b7ed4dda6146a21993199c6d9 100644 +index a5d90af5275c9c8069932f711069a6d422303d05..697f73cabfe89e716c9fceeb8362237d27ca3d02 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -762,16 +762,16 @@ public abstract class Mob extends LivingEntity { +@@ -773,16 +773,16 @@ public abstract class Mob extends LivingEntity { int i = this.getType().getCategory().getDespawnDistance(); int j = i * i; - if (d0 > (double) j) { // CraftBukkit - remove isTypeNotPersistent() check + if (d0 > (double) level.paperConfig.hardDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances - this.remove(); + this.discard(); } int k = this.getType().getCategory().getNoDespawnDistance(); @@ -47,7 +47,7 @@ index 151ebcffc1f2ae02fa55ab83d2ae7d8a0057f29d..4d3000067ae3d46b7ed4dda6146a2199 - if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > (double) l) { // CraftBukkit - remove isTypeNotPersistent() check + if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > level.paperConfig.softDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances - this.remove(); + this.discard(); - } else if (d0 < (double) l) { + } else if (d0 < level.paperConfig.softDespawnDistance) { // Paper - custom despawn distances this.noActionTime = 0; diff --git a/patches/server-remapped/0018-Allow-for-toggling-of-spawn-chunks.patch b/patches/server/0016-Allow-for-toggling-of-spawn-chunks.patch similarity index 91% rename from patches/server-remapped/0018-Allow-for-toggling-of-spawn-chunks.patch rename to patches/server/0016-Allow-for-toggling-of-spawn-chunks.patch index 91cd6d02b8..a1cd24c0d5 100644 --- a/patches/server-remapped/0018-Allow-for-toggling-of-spawn-chunks.patch +++ b/patches/server/0016-Allow-for-toggling-of-spawn-chunks.patch @@ -20,10 +20,10 @@ index 2f0d582baf0eb2bb477944d0cb1369db6ca33956..89e76dd73811fd0f6f8c8e7e5af804d5 + } } diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index c153df1f4dea3dc0ae744bde01e334b3bd3b50af..832abf73bdab2488c5814ea6e57888aac1b26154 100644 +index 59730455fcdf22bada7288833cf7e8b6c9b4096a..d106ab5bbe0647aa2ad285baaabb62b79ced3c06 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -217,6 +217,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -236,6 +236,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { }); // CraftBukkit end timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings diff --git a/patches/server-remapped/0019-Drop-falling-block-and-tnt-entities-at-the-specified.patch b/patches/server/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch similarity index 74% rename from patches/server-remapped/0019-Drop-falling-block-and-tnt-entities-at-the-specified.patch rename to patches/server/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch index 91e53448a3..6530418157 100644 --- a/patches/server-remapped/0019-Drop-falling-block-and-tnt-entities-at-the-specified.patch +++ b/patches/server/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch @@ -24,23 +24,11 @@ index 89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75..d16ae924bcbe31c964f7fb448757c748 + if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); + } } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 584e83441a9fef88eb1b0a29bec8bda29d6a0c9c..706417f44c1eebc7cc5e8e7053fa0ab21f4caeba 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1849,6 +1849,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.spawnAtLocation(stack, 0.0F); - } - -+ @Nullable public final ItemEntity dropItem(ItemStack itemstack, float offset) { return this.spawnAtLocation(itemstack, offset); } // Paper - OBFHELPER - @Nullable - public ItemEntity spawnAtLocation(ItemStack stack, float yOffset) { - if (stack.isEmpty()) { diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -index 8a9e2316b9f5756503dc06e27981525d2cd7d1a5..5394bc6336cb84025c1c748fb5b3d38e0648a590 100644 +index 86493f18913f6d3a560de2e3f8690bd227d73cee..11ed0127e2ea268f16c6b4b380d132a71ec9b3dc 100644 --- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -122,6 +122,17 @@ public class FallingBlockEntity extends Entity { +@@ -127,6 +127,17 @@ public class FallingBlockEntity extends Entity { } this.move(MoverType.SELF, this.getDeltaMovement()); @@ -51,7 +39,7 @@ index 8a9e2316b9f5756503dc06e27981525d2cd7d1a5..5394bc6336cb84025c1c748fb5b3d38e + this.spawnAtLocation(block); + } + -+ this.remove(); ++ this.discard(); + return; + } + // Paper end @@ -59,16 +47,16 @@ index 8a9e2316b9f5756503dc06e27981525d2cd7d1a5..5394bc6336cb84025c1c748fb5b3d38e blockposition = this.blockPosition(); boolean flag = this.blockState.getBlock() instanceof ConcretePowderBlock; diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -index ff15a372b7cad5fa88b7ef6de1f3441d93f9c67e..4c4262b8f0cb44b8cea8cb46194a6e70d4ce56f4 100644 +index 540fe28b16ff0208e23ecdd50fc5fa05960c0299..394164f50256ad9a167e15531a9202875abb6cb6 100644 --- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -@@ -69,6 +69,12 @@ public class PrimedTnt extends Entity { +@@ -68,6 +68,12 @@ public class PrimedTnt extends Entity { } this.move(MoverType.SELF, this.getDeltaMovement()); + // Paper start - Configurable TNT entity height nerf + if (this.level.paperConfig.entityTNTHeightNerf != 0 && this.getY() > this.level.paperConfig.entityTNTHeightNerf) { -+ this.remove(); ++ this.discard(); + return; + } + // Paper end @@ -76,16 +64,16 @@ index ff15a372b7cad5fa88b7ef6de1f3441d93f9c67e..4c4262b8f0cb44b8cea8cb46194a6e70 if (this.onGround) { this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D)); diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java -index c2ed3ba42d29a50386c94b109fdd3b2f2f1b433b..3b5e96f2325e14a94de0fb2d6da86812cecc7395 100644 +index 01d3247501ad228882e9e0a03f964a18e051d4c4..4572a3cf0a067b64f2bd6c31139a773cddf4e872 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java -@@ -47,6 +47,12 @@ public class MinecartTNT extends AbstractMinecart { +@@ -45,6 +45,12 @@ public class MinecartTNT extends AbstractMinecart { public void tick() { super.tick(); if (this.fuse > 0) { + // Paper start - Configurable TNT entity height nerf + if (this.level.paperConfig.entityTNTHeightNerf != 0 && this.getY() > this.level.paperConfig.entityTNTHeightNerf) { -+ this.remove(); ++ this.discard(); + return; + } + // Paper end diff --git a/patches/server-remapped/0020-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/patches/server/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch similarity index 84% rename from patches/server-remapped/0020-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch rename to patches/server/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch index e00adead2f..a6742d2967 100644 --- a/patches/server-remapped/0020-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch +++ b/patches/server/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch @@ -6,36 +6,36 @@ Subject: [PATCH] Show 'Paper' in client crashes, server lists, and Mojang diff --git a/src/main/java/net/minecraft/server/Eula.java b/src/main/java/net/minecraft/server/Eula.java -index 6934b0fdfe11ef673a3e4ae7564d04acee169252..9f104b1bd05d9f344579f086b2b9c00af1750690 100644 +index 2c53a400611c78236c5a1c1270d27c02e94251bf..a1d5c0f8fe2adb2ee56f3217e089211ec7c61eb0 100644 --- a/src/main/java/net/minecraft/server/Eula.java +++ b/src/main/java/net/minecraft/server/Eula.java -@@ -72,7 +72,7 @@ public class Eula { +@@ -64,7 +64,7 @@ public class Eula { + try { Properties properties = new Properties(); - properties.setProperty("eula", "false"); -- properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula)."); -+ properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\nYou also agree that tacos are tasty, and the best food in the world."); // Paper - fix lag; - } catch (Throwable throwable1) { - throwable = throwable1; - throw throwable1; +- properties.store(outputStream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula)."); ++ properties.store(outputStream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\nYou also agree that tacos are tasty, and the best food in the world."); // Paper - fix lag; + } catch (Throwable var5) { + if (outputStream != null) { + try { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index a456b9cbf0e5eea4e888e0e3d07ed17558650371..fa29790600021809f31092a90e1a3a9b84d5e0c4 100644 +index 6a6249ad58cc90782d526d89c899f30a59b980b2..e8d732933ddd2b670ff0b9c8d9be84a332f06482 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1340,7 +1340,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop // CraftBukkit - cb > vanilla! + return "Paper"; //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! } - public CrashReport fillReport(CrashReport report) { + public SystemReport fillSystemReport(SystemReport systemreport) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f7f5457d20586e0ba72368e64ff6025f6755e61e..f81def94a1a7ab3a24b74a8bbd5f3e8ebae2c0d5 100644 +index ea8d5d95d9aa2d0036f82eca782cb5a633cbc388..6628000abc628efb71c9a0391a429b20920575b9 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -224,7 +224,7 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; +@@ -227,7 +227,7 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; import net.md_5.bungee.api.chat.BaseComponent; // Spigot public final class CraftServer implements Server { @@ -45,11 +45,11 @@ index f7f5457d20586e0ba72368e64ff6025f6755e61e..f81def94a1a7ab3a24b74a8bbd5f3e8e private final String bukkitVersion = Versioning.getBukkitVersion(); private final Logger logger = Logger.getLogger("Minecraft"); diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index ce9f10f890a5866ab6208c7253b15b09fe323a81..e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2 100644 +index 4df6b2a155a610953d8d5789bffa33d290d62aaa..399cb06c7ae3570d08430e8675f141657d1026d4 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -206,12 +206,25 @@ public class Main { - deadline.add(Calendar.DAY_OF_YEAR, -28); +@@ -210,12 +210,25 @@ public class Main { + deadline.add(Calendar.DAY_OF_YEAR, -3); 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 ***"); @@ -76,7 +76,7 @@ index ce9f10f890a5866ab6208c7253b15b09fe323a81..e8c225fcd1a3fa5a7e1971683b1876dd net.minecraft.server.Main.main(options); } catch (Throwable t) { diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 9a695b80ef57d677fbdee1bfc59f0f9125a7ebd4..21d7b483920841456707fe3f08b180c1f072b7f7 100644 +index 335120afc88a8fc1543c2e6df516fd728e3ab032..d5863b0b06384b25eaa33572fa02649795463ed8 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java @@ -19,7 +19,7 @@ public class WatchdogThread extends Thread @@ -112,6 +112,6 @@ index 9a695b80ef57d677fbdee1bfc59f0f9125a7ebd4..21d7b483920841456707fe3f08b180c1 log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); log.log( Level.SEVERE, "------------------------------" ); // diff --git a/patches/server-remapped/0021-Implement-Paper-VersionChecker.patch b/patches/server/0019-Implement-Paper-VersionChecker.patch similarity index 98% rename from patches/server-remapped/0021-Implement-Paper-VersionChecker.patch rename to patches/server/0019-Implement-Paper-VersionChecker.patch index 66c45ee1f0..947adba5b8 100644 --- a/patches/server-remapped/0021-Implement-Paper-VersionChecker.patch +++ b/patches/server/0019-Implement-Paper-VersionChecker.patch @@ -133,7 +133,7 @@ index 0000000000000000000000000000000000000000..1a1b50e475b9ede544b2f6d0d36632b2 + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 2d4faef5a2b9c4fe8b65ff4f1346b8375e0e02c8..21052d0e88351b075733331d71e07b086354b820 100644 +index 409515c406f5b5cfac9872f925dbc67159a5d41f..c49d2dd323e7164ded499e561821da2c0e4be9da 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -368,6 +368,11 @@ public final class CraftMagicNumbers implements UnsafeValues { diff --git a/patches/server-remapped/0022-Add-version-history-to-version-command.patch b/patches/server/0020-Add-version-history-to-version-command.patch similarity index 98% rename from patches/server-remapped/0022-Add-version-history-to-version-command.patch rename to patches/server/0020-Add-version-history-to-version-command.patch index 4985c3e747..332461d12c 100644 --- a/patches/server-remapped/0022-Add-version-history-to-version-command.patch +++ b/patches/server/0020-Add-version-history-to-version-command.patch @@ -202,10 +202,10 @@ index 0000000000000000000000000000000000000000..aac3f66cb23d260729c2a48d8710a9de + } +} diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 40fe03c844c8bf6a9c4c5ae028b259f01a81eead..c7655883262f122b373ac30a33ddb4c06cd9aebe 100644 +index 844d3b910cfb1c073b8b58b0eff3f28af5453701..566390d02b2af4a0f2c867b7ff8116a8301e8497 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -193,6 +193,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -202,6 +202,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface return false; } com.destroystokyo.paper.PaperConfig.registerCommands(); diff --git a/patches/server-remapped/0023-Player-affects-spawning-API.patch b/patches/server/0021-Player-affects-spawning-API.patch similarity index 71% rename from patches/server-remapped/0023-Player-affects-spawning-API.patch rename to patches/server/0021-Player-affects-spawning-API.patch index 08d7ac1c4a..4b0545775d 100644 --- a/patches/server-remapped/0023-Player-affects-spawning-API.patch +++ b/patches/server/0021-Player-affects-spawning-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Player affects spawning API diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 706417f44c1eebc7cc5e8e7053fa0ab21f4caeba..392f2f2d67b688d5b37f77c8e4b3036348472d77 100644 +index b82dd96147224057ea0e0dc92506b27ffbc9f034..568ce924efcad6ab6b986f1a450eb56c80e89b02 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1353,6 +1353,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1498,6 +1498,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n return Mth.sqrt(f * f + f1 * f1 + f2 * f2); } @@ -17,29 +17,28 @@ index 706417f44c1eebc7cc5e8e7053fa0ab21f4caeba..392f2f2d67b688d5b37f77c8e4b30363 double d3 = this.getX() - x; double d4 = this.getY() - y; diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index f8c13881f59ccaccf8d8e5496d2f8f49ba7d7343..a3bad391a719363077740aa810c9412df34b4ae5 100644 +index 195989667c7d844399a72787819f62a3fd0d9c78..d17b75ad13bbc8a38cdc2f2d77ee5d88438cec31 100644 --- a/src/main/java/net/minecraft/world/entity/EntitySelector.java +++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -29,6 +29,12 @@ public final class EntitySelector { - return !entity.isSpectator(); +@@ -28,6 +28,11 @@ public final class EntitySelector { }; + private EntitySelector() {} + // Paper start + public static final Predicate affectsSpawning = (entity) -> { -+ return !entity.isSpectator() && entity.isAlive() && (entity instanceof EntityPlayer) && ((EntityPlayer) entity).affectsSpawning; ++ return !entity.isSpectator() && entity.isAlive() && (entity instanceof net.minecraft.server.level.ServerPlayer) && ((net.minecraft.server.level.ServerPlayer) entity).affectsSpawning; + }; + // Paper end -+ - public static Predicate withinDistance(double x, double y, double z, double d3) { - double d4 = d3 * d3; + public static Predicate withinDistance(double x, double y, double z, double max) { + double d4 = max * max; diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 4d3000067ae3d46b7ed4dda6146a21993199c6d9..09d39b73e8a3987e58a502bd914a6451b807421b 100644 +index 697f73cabfe89e716c9fceeb8362237d27ca3d02..b13774873f795b149c15fddb8053d9419f1841ca 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -755,7 +755,7 @@ public abstract class Mob extends LivingEntity { +@@ -766,7 +766,7 @@ public abstract class Mob extends LivingEntity { if (this.level.getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) { - this.remove(); + this.discard(); } else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) { - Player entityhuman = this.level.getNearestPlayer(this, -1.0D); + Player entityhuman = this.level.findNearbyPlayer(this, -1.0D, EntitySelector.affectsSpawning); // Paper @@ -47,10 +46,10 @@ index 4d3000067ae3d46b7ed4dda6146a21993199c6d9..09d39b73e8a3987e58a502bd914a6451 if (entityhuman != null) { double d0 = entityhuman.distanceToSqr((Entity) this); // CraftBukkit - decompile error diff --git a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java -index 4ce9e37d7334ba0557c397c0ebd2cb7928c7c564..cfdbaec1de6add7a189c26eb66701dfa5f40fe4f 100644 +index 7d741c2aebbc1c6cf1ff59cca6480325db6ca29c..2459ae800a5f6b234a4f4bb1cd3738e4e9cac67d 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java +++ b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java -@@ -122,7 +122,7 @@ public class Silverfish extends Monster { +@@ -123,7 +123,7 @@ public class Silverfish extends Monster { if (checkAnyLightMonsterSpawnRules(type, world, spawnReason, pos, random)) { Player entityhuman = world.getNearestPlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0D, true); @@ -60,10 +59,10 @@ index 4ce9e37d7334ba0557c397c0ebd2cb7928c7c564..cfdbaec1de6add7a189c26eb66701dfa return 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 91f605c803c021c8743de87b67dcb0fb9fc807e9..3b451e75a7f49ea6b543aee9f0a51c0be3c4dfba 100644 +index 24530af0382be01e26516d8fa29f61c912ebb9aa..a76f1cab566a3c8c8d1b0204b5c2c8492312c9f0 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -161,6 +161,9 @@ public abstract class Player extends LivingEntity { +@@ -176,6 +176,9 @@ public abstract class Player extends LivingEntity { private final ItemCooldowns cooldowns; @Nullable public FishingHook fishing; @@ -74,23 +73,23 @@ index 91f605c803c021c8743de87b67dcb0fb9fc807e9..3b451e75a7f49ea6b543aee9f0a51c0b // CraftBukkit start public boolean fauxSleeping; diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 98f85d59bc48451ef6381a47fe341f77b9920981..10058d3c3565382faa893b79119c5caf845bf29a 100644 +index 03bdbb832ff6a86f2dac9c008de45f3bb53aa688..a003e1c0d99a4d4c88269ea5bad250ba73bbc9c9 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -66,7 +66,7 @@ public abstract class BaseSpawner { - private boolean isNearPlayer() { - BlockPos blockposition = this.getPos(); - -- return this.getLevel().hasNearbyAlivePlayer((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); -+ return this.getLevel().isAffectsSpawningPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper +@@ -77,7 +77,7 @@ public abstract class BaseSpawner { } - public void tick() { + private boolean isNearPlayer(Level world, BlockPos pos) { +- return world.hasNearbyAlivePlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); ++ return world.isAffectsSpawningPlayerNearby((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper + } + + public void clientTick(Level world, BlockPos pos) { diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index 7e7a58b9a9ececdcc37fc33b33703428eb1d5faf..66681b9f0e2531d3da25629e44180417b32b4d66 100644 +index 389985e022b82c675fb21f363422471bd15b84b0..0b6e5ee9872a73823219bff7f642375fdc4ec243 100644 --- a/src/main/java/net/minecraft/world/level/EntityGetter.java +++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -92,8 +92,9 @@ public interface EntityGetter { +@@ -71,8 +71,9 @@ public interface EntityGetter { } } @@ -99,16 +98,16 @@ index 7e7a58b9a9ececdcc37fc33b33703428eb1d5faf..66681b9f0e2531d3da25629e44180417 + default Player findNearbyPlayer(Entity entity, double d0, @Nullable Predicate predicate) { return this.findNearbyPlayer(entity.getX(), entity.getY(), entity.getZ(), d0, predicate); } // Paper + @Nullable default Player findNearbyPlayer(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { return getNearestPlayer(d0, d1, d2, d3, predicate); } // Paper - OBFHELPER + @Nullable default Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate targetPredicate) { // Paper - double d4 = -1.0D; - Player entityhuman = null; - Iterator iterator = this.players().iterator(); -@@ -126,6 +127,27 @@ public interface EntityGetter { + double d = -1.0D; + Player player = null; + +@@ -100,6 +101,27 @@ public interface EntityGetter { return this.getNearestPlayer(x, y, z, maxDistance, predicate); } + // Paper end + default boolean isAffectsSpawningPlayerNearby(double d0, double d1, double d2, double d3) { -+ Iterator iterator = this.players().iterator(); ++ java.util.Iterator iterator = this.players().iterator(); + double d4; + do { + Player entityhuman; @@ -128,16 +127,16 @@ index 7e7a58b9a9ececdcc37fc33b33703428eb1d5faf..66681b9f0e2531d3da25629e44180417 + // Paper end + default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) { - Iterator iterator = this.players().iterator(); - + 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 50d11611702e3d1f0e980fb8f2280b05b891167b..e6c39c822c6a910f63e9b4899d53b7d75e1b77cf 100644 +index f4dff38b0f9e33be3495433559935765f77d662e..531ebabd1682539c453825111ba46a9a07f9dc8f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1768,8 +1768,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1769,8 +1769,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public String getLocale() { - return getHandle().locale; + return this.getHandle().locale; + + } + @@ -154,4 +153,4 @@ index 50d11611702e3d1f0e980fb8f2280b05b891167b..e6c39c822c6a910f63e9b4899d53b7d7 + @Override public void updateCommands() { - if (getHandle().connection == null) return; + if (this.getHandle().connection == null) return; diff --git a/patches/server-remapped/0024-Remove-invalid-mob-spawner-tile-entities.patch b/patches/server/0022-Remove-invalid-mob-spawner-tile-entities.patch similarity index 62% rename from patches/server-remapped/0024-Remove-invalid-mob-spawner-tile-entities.patch rename to patches/server/0022-Remove-invalid-mob-spawner-tile-entities.patch index 23323c9803..c4cfd682ed 100644 --- a/patches/server-remapped/0024-Remove-invalid-mob-spawner-tile-entities.patch +++ b/patches/server/0022-Remove-invalid-mob-spawner-tile-entities.patch @@ -5,27 +5,30 @@ Subject: [PATCH] Remove invalid mob spawner tile entities diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index f30793b81dfd9018b4879d655c7c18a9f9c25267..300749822d52f9f973e71c6ec9c8bf29d6a6938e 100644 +index 485cb87e83dd4b4b052905fb7f5f83d3c26f542f..ee2df7de72c75e4fbf8a681ff254260554969b66 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -41,7 +41,9 @@ import net.minecraft.world.level.TickList; +@@ -46,10 +46,12 @@ import net.minecraft.world.level.TickList; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.SpawnerBlock; import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityTicker; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.TickingBlockEntity; +import net.minecraft.world.level.block.entity.SpawnerBlockEntity; import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.level.levelgen.DebugLevelSource; - import net.minecraft.world.level.levelgen.Heightmap; -@@ -647,6 +649,10 @@ public class LevelChunk implements ChunkAccess { + import net.minecraft.world.level.gameevent.EuclideanGameEventDispatcher; + import net.minecraft.world.level.gameevent.GameEventDispatcher; +@@ -608,6 +610,10 @@ public class LevelChunk implements ChunkAccess { } // CraftBukkit start + // Paper start - Remove invalid mob spawner tile entities -+ } else if (blockEntity instanceof SpawnerBlockEntity && !(getBlockData(pos.getX(), pos.getY(), pos.getZ()).getBlock() instanceof SpawnerBlock)) { -+ this.blockEntities.remove(pos); ++ } else if (blockEntity instanceof SpawnerBlockEntity && !(getBlockState(blockposition).getBlock() instanceof SpawnerBlock)) { ++ this.blockEntities.remove(blockposition); + // Paper end } else { System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() - + " (" + getBlockState(pos) + ") where there was no entity tile!"); + + " (" + this.getBlockState(blockposition) + ") where there was no entity tile!"); diff --git a/patches/server-remapped/0026-Further-improve-server-tick-loop.patch b/patches/server/0023-Further-improve-server-tick-loop.patch similarity index 82% rename from patches/server-remapped/0026-Further-improve-server-tick-loop.patch rename to patches/server/0023-Further-improve-server-tick-loop.patch index ee0ab66ab5..12d66e5007 100644 --- a/patches/server-remapped/0026-Further-improve-server-tick-loop.patch +++ b/patches/server/0023-Further-improve-server-tick-loop.patch @@ -12,10 +12,10 @@ Previous implementation did not calculate TPS correctly. Switch to a realistic rolling average and factor in std deviation as an extra reporting variable diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index fa29790600021809f31092a90e1a3a9b84d5e0c4..526d6c0fa45bfba92a3f964f72e4965fd5c841c1 100644 +index e8d732933ddd2b670ff0b9c8d9be84a332f06482..400aac6a37c63f34bf0038780e2137d82bc3416d 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -251,7 +251,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; public Commands vanillaCommandDispatcher; -@@ -260,7 +260,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 5000L && this.nextTickTime - this.lastOverloadWarning >= 30000L) { // CraftBukkit long j = i / 50L; - if (server.getWarnOnOverload()) // CraftBukkit + if (this.server.getWarnOnOverload()) // CraftBukkit - MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); + MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); this.nextTickTime += j * 50L; this.lastOverloadWarning = this.nextTickTime; } -- if ( tickCount++ % SAMPLE_INTERVAL == 0 ) -+ if ( ++MinecraftServer.currentTick % SAMPLE_INTERVAL == 0 ) +- if ( tickCount++ % MinecraftServer.SAMPLE_INTERVAL == 0 ) ++ if ( ++MinecraftServer.currentTick % MinecraftServer.SAMPLE_INTERVAL == 0 ) { -- double currentTps = 1E3 / ( curTime - tickSection ) * SAMPLE_INTERVAL; -- recentTps[0] = calcTps( recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min) -- recentTps[1] = calcTps( recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min) -- recentTps[2] = calcTps( recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min) +- double currentTps = 1E3 / ( curTime - tickSection ) * MinecraftServer.SAMPLE_INTERVAL; +- this.recentTps[0] = MinecraftServer.calcTps( this.recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min) +- this.recentTps[1] = MinecraftServer.calcTps( this.recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min) +- this.recentTps[2] = MinecraftServer.calcTps( this.recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min) + final long diff = curTime - tickSection; + java.math.BigDecimal currentTps = TPS_BASE.divide(new java.math.BigDecimal(diff), 30, java.math.RoundingMode.HALF_UP); + tps1.add(currentTps, diff); + tps5.add(currentTps, diff); + tps15.add(currentTps, diff); + // Backwards compat with bad plugins -+ recentTps[0] = tps1.getAverage(); -+ recentTps[1] = tps5.getAverage(); -+ recentTps[2] = tps15.getAverage(); ++ this.recentTps[0] = tps1.getAverage(); ++ this.recentTps[1] = tps5.getAverage(); ++ this.recentTps[2] = tps15.getAverage(); + // Paper end tickSection = curTime; } // Spigot end +@@ -1021,7 +1079,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) { diff --git a/patches/server-remapped/0027-Only-refresh-abilities-if-needed.patch b/patches/server/0024-Only-refresh-abilities-if-needed.patch similarity index 56% rename from patches/server-remapped/0027-Only-refresh-abilities-if-needed.patch rename to patches/server/0024-Only-refresh-abilities-if-needed.patch index b310cdcaa1..6c1175df0c 100644 --- a/patches/server-remapped/0027-Only-refresh-abilities-if-needed.patch +++ b/patches/server/0024-Only-refresh-abilities-if-needed.patch @@ -5,21 +5,21 @@ 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 e6c39c822c6a910f63e9b4899d53b7d75e1b77cf..2920ba3d8eeb62670897ea19b50aaf395ab84c5a 100644 +index 531ebabd1682539c453825111ba46a9a07f9dc8f..1392d4d5027b3d972b2196af7b19fb409977fb8d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1437,12 +1437,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1438,12 +1438,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void setFlying(boolean value) { -+ boolean needsUpdate = getHandle().abilities.flying != value; // Paper - Only refresh abilities if needed - if (!getAllowFlight() && value) { ++ boolean needsUpdate = getHandle().getAbilities().flying != value; // Paper - Only refresh abilities if needed + if (!this.getAllowFlight() && value) { throw new IllegalArgumentException("Cannot make player fly if getAllowFlight() is false"); } - getHandle().abilities.flying = value; -- getHandle().onUpdateAbilities(); -+ if (needsUpdate) getHandle().onUpdateAbilities(); // Paper - Only refresh abilities if needed + this.getHandle().getAbilities().flying = value; +- this.getHandle().onUpdateAbilities(); ++ if (needsUpdate) this.getHandle().onUpdateAbilities(); // Paper - Only refresh abilities if needed } @Override diff --git a/patches/server-remapped/0028-Entity-Origin-API.patch b/patches/server/0025-Entity-Origin-API.patch similarity index 61% rename from patches/server-remapped/0028-Entity-Origin-API.patch rename to patches/server/0025-Entity-Origin-API.patch index cc2e7adc4a..225f30bfa1 100644 --- a/patches/server-remapped/0028-Entity-Origin-API.patch +++ b/patches/server/0025-Entity-Origin-API.patch @@ -5,25 +5,25 @@ Subject: [PATCH] Entity Origin API diff --git a/src/main/java/net/minecraft/nbt/ListTag.java b/src/main/java/net/minecraft/nbt/ListTag.java -index 084340dc73acb3d972e0717b48da820c027a5137..7927ebac41eb1f257738238500cfe0c06031fcaf 100644 +index 88bac72edf19c578902f49d20353989ed4d96f8f..e79faeb26d079de0108268fd2607cf9eb885c003 100644 --- a/src/main/java/net/minecraft/nbt/ListTag.java +++ b/src/main/java/net/minecraft/nbt/ListTag.java -@@ -190,6 +190,7 @@ public class ListTag extends CollectionTag { - return new int[0]; +@@ -179,6 +179,7 @@ public class ListTag extends CollectionTag { + return new long[0]; } + public final double getDoubleAt(int i) { return this.getDouble(i); } // Paper - OBFHELPER public double getDouble(int index) { if (index >= 0 && index < this.list.size()) { - Tag nbtbase = (Tag) this.list.get(index); + Tag tag = this.list.get(index); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 0cc86ca4ea4a2e1b5acc3c0507397eef85dec0c1..d2bb9385fbc21cdef6cef06680fac685d3da3570 100644 +index c89c983e6f64718dabb2893996f7eb4a111c97c9..d26e8803222276fb7bb1bedd9fd13a8861ce671c 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1240,6 +1240,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.navigations.add(((Mob) entity).getNavigation()); +@@ -1110,6 +1110,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + entityplayer.connection.send(new ClientboundBlockDestructionPacket(entityId, pos, progress)); + } } - entity.valid = true; // CraftBukkit + // Paper start - Set origin location when the entity is being added to the world + if (entity.origin == null) { + entity.origin = entity.getBukkitEntity().getLocation(); @@ -33,10 +33,10 @@ index 0cc86ca4ea4a2e1b5acc3c0507397eef85dec0c1..d2bb9385fbc21cdef6cef06680fac685 } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 392f2f2d67b688d5b37f77c8e4b3036348472d77..fd5b41ceb97dc8aa975f1c0ae05b58d0b09f2cd6 100644 +index 568ce924efcad6ab6b986f1a450eb56c80e89b02..84c2a14d7336d57d5db66d01c75e31a58860d96c 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -246,6 +246,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -280,6 +280,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only public boolean forceExplosionKnockback; // SPIGOT-949 public boolean persistentInvisibility = false; @@ -44,29 +44,29 @@ index 392f2f2d67b688d5b37f77c8e4b3036348472d77..fd5b41ceb97dc8aa975f1c0ae05b58d0 // Spigot start public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); public final boolean defaultActivationState; -@@ -1624,6 +1625,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.bukkitEntity.storeBukkitValues(tag); +@@ -1813,6 +1814,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + this.bukkitEntity.storeBukkitValues(nbt); } // CraftBukkit end + // Paper start - Save the entity's origin location + if (this.origin != null) { -+ tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); -+ tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); ++ nbt.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); ++ nbt.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ())); + } + // Paper end - return tag; + return nbt; } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); -@@ -1746,6 +1753,17 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1939,6 +1946,17 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } // CraftBukkit end + // Paper start - Restore the entity's origin location -+ ListTag originTag = tag.getList("Paper.Origin", 6); ++ ListTag originTag = nbt.getList("Paper.Origin", 6); + if (!originTag.isEmpty()) { + org.bukkit.World originWorld = level.getWorld(); -+ if (tag.contains("Paper.OriginWorld")) { -+ originWorld = Bukkit.getWorld(tag.getUUID("Paper.OriginWorld")); ++ if (nbt.contains("Paper.OriginWorld")) { ++ originWorld = Bukkit.getWorld(nbt.getUUID("Paper.OriginWorld")); + } + origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); + } @@ -75,46 +75,38 @@ index 392f2f2d67b688d5b37f77c8e4b3036348472d77..fd5b41ceb97dc8aa975f1c0ae05b58d0 } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded"); -@@ -1807,6 +1825,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - - protected abstract void addAdditionalSaveData(CompoundTag tag); - -+ protected final ListTag createList(double... adouble) { return newDoubleList(adouble); } // Paper - OBFHELPER - protected ListTag newDoubleList(double... values) { - ListTag nbttaglist = new ListTag(); - double[] adouble1 = values; diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -index 5394bc6336cb84025c1c748fb5b3d38e0648a590..1d87717cc9002ea202ee2ca614aaa8a4c7ea3cb2 100644 +index 11ed0127e2ea268f16c6b4b380d132a71ec9b3dc..eb838fcad0593573f536d5e043cbd3f4bbe25d74 100644 --- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -291,6 +291,14 @@ public class FallingBlockEntity extends Entity { +@@ -329,6 +329,14 @@ public class FallingBlockEntity extends Entity { this.blockState = Blocks.SAND.defaultBlockState(); } + // Paper start - Try and load origin location from the old NBT tags for backwards compatibility -+ if (tag.contains("SourceLoc_x")) { -+ int srcX = tag.getInt("SourceLoc_x"); -+ int srcY = tag.getInt("SourceLoc_y"); -+ int srcZ = tag.getInt("SourceLoc_z"); ++ if (nbt.contains("SourceLoc_x")) { ++ int srcX = nbt.getInt("SourceLoc_x"); ++ int srcY = nbt.getInt("SourceLoc_y"); ++ int srcZ = nbt.getInt("SourceLoc_z"); + origin = new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ); + } + // Paper end } - public void setHurtsEntities(boolean hurtEntities) { + public Level getLevel() { diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -index 4c4262b8f0cb44b8cea8cb46194a6e70d4ce56f4..661848084fd986321ef782317934dac19ed4dce3 100644 +index 394164f50256ad9a167e15531a9202875abb6cb6..abc62c560816d945642d830a020deb28ff2efa37 100644 --- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -@@ -119,6 +119,14 @@ public class PrimedTnt extends Entity { +@@ -120,6 +120,14 @@ public class PrimedTnt extends Entity { @Override - protected void readAdditionalSaveData(CompoundTag tag) { - this.setFuse(tag.getShort("Fuse")); + protected void readAdditionalSaveData(CompoundTag nbt) { + this.setFuse(nbt.getShort("Fuse")); + // Paper start - Try and load origin location from the old NBT tags for backwards compatibility -+ if (tag.contains("SourceLoc_x")) { -+ int srcX = tag.getInt("SourceLoc_x"); -+ int srcY = tag.getInt("SourceLoc_y"); -+ int srcZ = tag.getInt("SourceLoc_z"); ++ if (nbt.contains("SourceLoc_x")) { ++ int srcX = nbt.getInt("SourceLoc_x"); ++ int srcY = nbt.getInt("SourceLoc_y"); ++ int srcZ = nbt.getInt("SourceLoc_z"); + origin = new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ); + } + // Paper end @@ -122,11 +114,11 @@ index 4c4262b8f0cb44b8cea8cb46194a6e70d4ce56f4..661848084fd986321ef782317934dac1 @Nullable diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 53c231925ef1b17e48c5863570e3c54124874621..e7a59a8e0424a0839dfa73fc65f44c5b04bd3dec 100644 +index f4bcf48060bc704e0b6c690f78faaecfe90d8db3..bac39ee51f36ad86d6a4978306b6612d9376adbf 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1062,4 +1062,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return spigot; +@@ -1096,4 +1096,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return this.spigot; } // Spigot end + diff --git a/patches/server-remapped/0029-Prevent-tile-entity-and-entity-crashes.patch b/patches/server/0026-Prevent-tile-entity-and-entity-crashes.patch similarity index 60% rename from patches/server-remapped/0029-Prevent-tile-entity-and-entity-crashes.patch rename to patches/server/0026-Prevent-tile-entity-and-entity-crashes.patch index cf3cf1beaa..ca201ec1e4 100644 --- a/patches/server-remapped/0029-Prevent-tile-entity-and-entity-crashes.patch +++ b/patches/server/0026-Prevent-tile-entity-and-entity-crashes.patch @@ -5,29 +5,10 @@ Subject: [PATCH] Prevent tile entity and entity crashes diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 832abf73bdab2488c5814ea6e57888aac1b26154..870843254d1c1fc49bc101a49cdf9d300ae3ca1b 100644 +index d106ab5bbe0647aa2ad285baaabb62b79ced3c06..c427c105c653a0b0de6ad33d1d6f622a31a5a680 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -737,11 +737,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - gameprofilerfiller.pop(); - } catch (Throwable throwable) { -- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking block entity"); -- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block entity being ticked"); -- -- tileentity.fillCrashReportCategory(crashreportsystemdetails); -- throw new ReportedException(crashreport); -+ // Paper start - Prevent tile entity and entity crashes -+ System.err.println("TileEntity threw exception at " + tileentity.level.getWorld().getName() + ":" + tileentity.worldPosition.getX() + "," + tileentity.worldPosition.getY() + "," + tileentity.worldPosition.getZ()); -+ throwable.printStackTrace(); -+ tilesThisCycle--; -+ this.tickableBlockEntities.remove(tileTickPosition--); -+ continue; -+ // Paper end - // Spigot start - } finally { - tileentity.tickTimer.stopTiming(); -@@ -806,11 +808,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -730,11 +730,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { try { tickConsumer.accept(entity); } catch (Throwable throwable) { @@ -39,27 +20,47 @@ index 832abf73bdab2488c5814ea6e57888aac1b26154..870843254d1c1fc49bc101a49cdf9d30 + // Paper start - Prevent tile entity and entity crashes + System.err.println("Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ()); + throwable.printStackTrace(); -+ entity.removed = true; -+ return; ++ entity.discard(); + // Paper end } } diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index d445a1b7b7605eed66923789c5d8e2199c31c5ac..13115d1b28dfa2d87b45a50bd0feaa7f57769122 100644 +index 0e70d9df226e0843a943b3a57d1319ce1bca2543..d6a4a2a59f1be0cc2e373dc326287b60db5559d2 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -208,7 +208,12 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - return Registry.BLOCK_ENTITY_TYPE.getKey(this.getType()) + " // " + this.getClass().getCanonicalName(); +@@ -196,7 +196,12 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + return minecraftkey + " // " + this.getClass().getCanonicalName(); }); if (this.level != null) { -- CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.worldPosition, this.getBlockState()); +- CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, this.getBlockState()); + // Paper start - Prevent TileEntity and Entity crashes + BlockState block = this.getBlockState(); + if (block != null) { -+ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.worldPosition, block); ++ CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, block); + } + // Paper end - CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.worldPosition, this.level.getBlockState(this.worldPosition)); + CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, this.level.getBlockState(this.worldPosition)); } } +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index ee2df7de72c75e4fbf8a681ff254260554969b66..a6e8a8de17acc6c7c0bdeea01544a334797b69b6 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -1241,11 +1241,11 @@ public class LevelChunk implements ChunkAccess { + + gameprofilerfiller.pop(); + } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking block entity"); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block entity being ticked"); +- +- this.blockEntity.fillCrashReportCategory(crashreportsystemdetails); +- throw new ReportedException(crashreport); ++ // Paper start - Prevent tile entity and entity crashes ++ System.err.println("TileEntity threw exception at " + LevelChunk.this.getLevel().getWorld().getName() + ":" + this.getPos().getX() + "," + this.getPos().getY() + "," + this.getPos().getZ()); ++ throwable.printStackTrace(); ++ LevelChunk.this.removeBlockEntity(this.getPos()); ++ // Paper end + // Spigot start + } finally { + this.blockEntity.tickTimer.stopTiming(); diff --git a/patches/server/0027-Configurable-top-of-nether-void-damage.patch b/patches/server/0027-Configurable-top-of-nether-void-damage.patch new file mode 100644 index 0000000000..594a2b6100 --- /dev/null +++ b/patches/server/0027-Configurable-top-of-nether-void-damage.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 23:58:50 -0600 +Subject: [PATCH] Configurable top of nether void damage + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index d16ae924bcbe31c964f7fb448757c748e5c4418c..4bba6977a0287837b8927718c040ac61463f0469 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -134,4 +134,19 @@ public class PaperWorldConfig { + if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); + if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); + } ++ ++ public int netherVoidTopDamageHeight; ++ public boolean doNetherTopVoidDamage() { return netherVoidTopDamageHeight > 0; } ++ private void netherVoidTopDamageHeight() { ++ netherVoidTopDamageHeight = getInt("nether-ceiling-void-damage-height", 0); ++ log("Top of the nether void damage height: " + netherVoidTopDamageHeight); ++ ++ if (PaperConfig.version < 18) { ++ boolean legacy = getBoolean("nether-ceiling-void-damage", false); ++ if (legacy) { ++ netherVoidTopDamageHeight = 128; ++ set("nether-ceiling-void-damage-height", netherVoidTopDamageHeight); ++ } ++ } ++ } + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 84c2a14d7336d57d5db66d01c75e31a58860d96c..7e7291cc41735a6c251738492a4cdd1c7798066f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -602,7 +602,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + } + + public void checkOutOfWorld() { +- if (this.getY() < (double) (this.level.getMinBuildHeight() - 64)) { ++ // Paper start - Configurable nether ceiling damage ++ if (this.getY() < (double) (this.level.getMinBuildHeight() - 64) || (this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER ++ && level.paperConfig.doNetherTopVoidDamage() ++ && this.getY() >= this.level.paperConfig.netherVoidTopDamageHeight)) { ++ // Paper end + this.outOfWorld(); + } + diff --git a/patches/server-remapped/0031-Check-online-mode-before-converting-and-renaming-pla.patch b/patches/server/0028-Check-online-mode-before-converting-and-renaming-pla.patch similarity index 75% rename from patches/server-remapped/0031-Check-online-mode-before-converting-and-renaming-pla.patch rename to patches/server/0028-Check-online-mode-before-converting-and-renaming-pla.patch index 56a96d8cfe..cc4f224bfd 100644 --- a/patches/server-remapped/0031-Check-online-mode-before-converting-and-renaming-pla.patch +++ b/patches/server/0028-Check-online-mode-before-converting-and-renaming-pla.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Check online mode before converting and renaming player data diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java -index 067c5acd4aad346ac9ccf6d1b5aa6691b0ccd348..60fe01e824e4657d2601797d7858d5de339ab255 100644 +index 4dcdfda78966df2596b44f7e2d3b1d61c45f17af..7b367e273c2a6869f8d8929c24ee45efdf6d4b1e 100644 --- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java @@ -56,7 +56,7 @@ public class PlayerDataStorage { - File file = new File(this.playerDir, entityhuman.getStringUUID() + ".dat"); + File file = new File(this.playerDir, player.getStringUUID() + ".dat"); // Spigot Start boolean usingWrongFile = false; - if ( !file.exists() ) + if ( org.bukkit.Bukkit.getOnlineMode() && !file.exists() ) // Paper - Check online mode first { - file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + entityhuman.getScoreboardName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); + file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + player.getScoreboardName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); if ( file.exists() ) diff --git a/patches/server-remapped/0032-Always-tick-falling-blocks.patch b/patches/server/0029-Always-tick-falling-blocks.patch similarity index 73% rename from patches/server-remapped/0032-Always-tick-falling-blocks.patch rename to patches/server/0029-Always-tick-falling-blocks.patch index 29eba4b28a..204256a0af 100644 --- a/patches/server-remapped/0032-Always-tick-falling-blocks.patch +++ b/patches/server/0029-Always-tick-falling-blocks.patch @@ -5,14 +5,14 @@ Subject: [PATCH] Always tick falling blocks diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 9bb35ec64e1538aabec9ff7831706c4717239449..0a9bd85e0308e962df3b24a74bd5aac919744d6d 100644 +index f023f3a0d1671398363f0caa432ffb61fd07c9b2..84ce3d38d5decb4a2f9fae78e0ef5d715860dc7d 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -91,6 +91,7 @@ public class ActivationRange +@@ -89,6 +89,7 @@ public class ActivationRange || entity instanceof AbstractHurtingProjectile || entity instanceof LightningBolt || entity instanceof PrimedTnt -+ || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks ++ || entity instanceof net.minecraft.world.entity.item.FallingBlockEntity // Paper - Always tick falling blocks || entity instanceof EndCrystal || entity instanceof FireworkRocketEntity || entity instanceof ThrownTrident ) diff --git a/patches/server-remapped/0033-Configurable-end-credits.patch b/patches/server/0030-Configurable-end-credits.patch similarity index 63% rename from patches/server-remapped/0033-Configurable-end-credits.patch rename to patches/server/0030-Configurable-end-credits.patch index 201a2e7284..b39189f118 100644 --- a/patches/server-remapped/0033-Configurable-end-credits.patch +++ b/patches/server/0030-Configurable-end-credits.patch @@ -20,23 +20,14 @@ index 4bba6977a0287837b8927718c040ac61463f0469..e6e18f309dc09ea9416ea37dcc697ddc + } } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index ca647b3afbe8da5847dc8fa890ae9ca5c18e03d9..f3797bd761c2c6782cce3fca25bc9ef37e5c4978 100644 +index ae04883b57d44fdfb748f1aad0b7a2e24120ebeb..b25f9a2d2d7f0af0fef60c4f1817cf165fed9cd6 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -188,7 +188,7 @@ public class ServerPlayer extends Player implements ContainerListener { - private long lastActionTime = Util.getMillis(); - private Entity camera; - public boolean isChangingDimension; -- private boolean seenCredits; -+ private boolean seenCredits; private void setHasSeenCredits(boolean has) { this.seenCredits = has; } // Paper - OBFHELPER - private final ServerRecipeBook recipeBook = new ServerRecipeBook(); - private Vec3 levitationStartPos; - private int levitationStartTime; -@@ -893,6 +893,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -938,6 +938,7 @@ public class ServerPlayer extends Player { this.unRide(); - this.getLevel().removePlayerImmediately(this); + this.getLevel().removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); if (!this.wonGame) { -+ if (level.paperConfig.disableEndCredits) this.setHasSeenCredits(true); // Paper - Toggle to always disable end credits ++ if (level.paperConfig.disableEndCredits) this.seenCredits = true; // Paper - Toggle to always disable end credits this.wonGame = true; this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.WIN_GAME, this.seenCredits ? 0.0F : 1.0F)); this.seenCredits = true; diff --git a/patches/server-remapped/0034-Fix-lag-from-explosions-processing-dead-entities.patch b/patches/server/0031-Fix-lag-from-explosions-processing-dead-entities.patch similarity index 89% rename from patches/server-remapped/0034-Fix-lag-from-explosions-processing-dead-entities.patch rename to patches/server/0031-Fix-lag-from-explosions-processing-dead-entities.patch index a9fb2be3bd..aad2c0790d 100644 --- a/patches/server-remapped/0034-Fix-lag-from-explosions-processing-dead-entities.patch +++ b/patches/server/0031-Fix-lag-from-explosions-processing-dead-entities.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix lag from explosions processing dead entities diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 54c3bfead8497f64c183f5612676803d91fc557b..8d6cd2a5b16d99cb8e754ce04b2d12fee7ffb4d0 100644 +index d8cd0bb88a5e4de0f7c7731684f5c9829f853f33..a723b60bdb4b90b30b0b26c9488ede2b1177208f 100644 --- a/src/main/java/net/minecraft/world/level/Explosion.java +++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -180,7 +180,7 @@ public class Explosion { +@@ -208,7 +208,7 @@ public class Explosion { int i1 = Mth.floor(this.y + (double) f2 + 1.0D); int j1 = Mth.floor(this.z - (double) f2 - 1.0D); int k1 = Mth.floor(this.z + (double) f2 + 1.0D); diff --git a/patches/server-remapped/0035-Optimize-explosions.patch b/patches/server/0032-Optimize-explosions.patch similarity index 91% rename from patches/server-remapped/0035-Optimize-explosions.patch rename to patches/server/0032-Optimize-explosions.patch index ec1e34fc38..d6ac9e859f 100644 --- a/patches/server-remapped/0035-Optimize-explosions.patch +++ b/patches/server/0032-Optimize-explosions.patch @@ -25,10 +25,10 @@ index e6e18f309dc09ea9416ea37dcc697ddc2b571a96..4881b03d470646843bad1bc343eb6a6a + } } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 526d6c0fa45bfba92a3f964f72e4965fd5c841c1..901d5497667706c049718dc4fca37a1bc489c465 100644 +index 400aac6a37c63f34bf0038780e2137d82bc3416d..c6a59fa4b30d54baa638c931f045b2d546da021a 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1324,6 +1324,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop Date: Fri, 11 Jun 2021 17:57:04 -0700 Subject: [PATCH 029/226] more patches --- .../0011-Add-PlayerLocaleChangeEvent.patch} | 0 .../0012-Add-player-view-distance-API.patch} | 0 .../0013-Add-BeaconEffectEvent.patch} | 0 .../0014-Add-PlayerInitialSpawnEvent.patch} | 0 ...y-disable-plugins-that-fail-to-load.patch} | 0 .../0016-Expose-server-CommandMap.patch} | 4 +- ...ord-chat-API-from-spigot-subclasses.patch} | 6 +- .../0018-Add-exception-reporting-event.patch | 2 +- ...0019-Player-Tab-List-and-Title-APIs.patch} | 2 +- ...rverListPingEvent-flagging-as-Async.patch} | 0 ...-sendMessage-methods-to-CommandSend.patch} | 0 ...orking-with-arrows-stuck-in-living-.patch} | 0 .../0023-Complete-resource-pack-API.patch} | 0 .../0024-Use-ASM-for-event-executors.patch} | 2 +- .../0025-Add-a-call-helper-to-Event.patch} | 0 ...er-name-to-commands.yml-replacement.patch} | 0 ...load-permissions.yml-and-require-co.patch} | 0 ...-Custom-replacement-for-eaten-items.patch} | 0 ...ntity-AddTo-RemoveFrom-World-Events.patch} | 0 .../0030-EntityPathfindEvent.patch} | 0 ...ynchronization-in-MetadataStoreBase.patch} | 0 ...-MetadataStoreBase.removeAll-Plugin.patch} | 0 ...sition-the-first-time-an-entity-is-s.patch | 2 + .../0051-Player-Tab-List-and-Title-APIs.patch | 31 +++++ ...entation-of-tile-entity-removal-list.patch | 2 + ...9-Configurable-mob-spawner-tick-rate.patch | 65 --------- .../0041-Add-BeaconEffectEvent.patch | 103 -------------- .../0044-Disable-spigot-tick-limiters.patch | 21 --- .../0052-Ensure-inv-drag-is-in-bounds.patch | 19 --- .../0033-Disable-explosion-knockback.patch} | 16 +-- .../0034-Disable-thunder.patch} | 6 +- .../0035-Disable-ice-and-snow.patch} | 4 +- ...6-Configurable-mob-spawner-tick-rate.patch | 62 +++++++++ .../server/0037-Add-BeaconEffectEvent.patch | 62 +++++++++ ...igurable-container-update-tick-rate.patch} | 8 +- ...0039-Use-UserCache-for-player-heads.patch} | 12 +- .../0040-Disable-spigot-tick-limiters.patch | 21 +++ .../0041-Add-PlayerInitialSpawnEvent.patch} | 12 +- ...rable-Disabling-Cat-Chest-Detection.patch} | 4 +- ...3-Ensure-commands-are-not-ran-async.patch} | 19 ++- ...hunks-are-slime-spawn-chunks-toggle.patch} | 8 +- .../0045-Expose-server-CommandMap.patch} | 8 +- ...-informative-in-maxHealth-exception.patch} | 12 +- ...0047-Player-Tab-List-and-Title-APIs.patch} | 43 +----- .../0048-Ensure-inv-drag-is-in-bounds.patch | 19 +++ ...d-configurable-portal-search-radius.patch} | 18 +-- .../0050-Add-velocity-warnings.patch} | 17 ++- ...le-inter-world-teleportation-safety.patch} | 4 +- .../0052-Add-exception-reporting-event.patch} | 128 +++++++++--------- ...don-t-need-to-when-cerealising-text.patch} | 14 +- ...reboards-for-non-players-by-default.patch} | 16 +-- ...orking-with-arrows-stuck-in-living-.patch} | 8 +- .../0056-Complete-resource-pack-API.patch} | 25 ++-- .../0057-Chunk-Save-Reattempt.patch} | 18 +-- ...ding-permissions.yml-before-plugins.patch} | 24 ++-- ...low-Reloading-of-Custom-Permissions.patch} | 4 +- .../0060-Remove-Metadata-on-reload.patch} | 14 +- ...61-Handle-Item-Meta-Inconsistencies.patch} | 102 +++++++------- ...rable-Non-Player-Arrow-Despawn-Rate.patch} | 6 +- .../0063-Add-World-Util-Methods.patch} | 12 +- ...-Custom-replacement-for-eaten-items.patch} | 8 +- ...h-absorb-values-and-repair-bad-data.patch} | 27 ++-- 62 files changed, 491 insertions(+), 529 deletions(-) rename patches/{api-unmapped/0010-Add-PlayerLocaleChangeEvent.patch => api/0011-Add-PlayerLocaleChangeEvent.patch} (100%) rename patches/{api-unmapped/0011-Add-player-view-distance-API.patch => api/0012-Add-player-view-distance-API.patch} (100%) rename patches/{api-unmapped/0012-Add-BeaconEffectEvent.patch => api/0013-Add-BeaconEffectEvent.patch} (100%) rename patches/{api-unmapped/0013-Add-PlayerInitialSpawnEvent.patch => api/0014-Add-PlayerInitialSpawnEvent.patch} (100%) rename patches/{api-unmapped/0014-Automatically-disable-plugins-that-fail-to-load.patch => api/0015-Automatically-disable-plugins-that-fail-to-load.patch} (100%) rename patches/{api-unmapped/0015-Expose-server-CommandMap.patch => api/0016-Expose-server-CommandMap.patch} (88%) rename patches/{api-unmapped/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch => api/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch} (94%) rename patches/{api-unmapped => api}/0018-Add-exception-reporting-event.patch (99%) rename patches/{api-unmapped/0017-Player-Tab-List-and-Title-APIs.patch => api/0019-Player-Tab-List-and-Title-APIs.patch} (99%) rename patches/{api-unmapped/0019-Fix-ServerListPingEvent-flagging-as-Async.patch => api/0020-Fix-ServerListPingEvent-flagging-as-Async.patch} (100%) rename patches/{api-unmapped/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch => api/0021-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch} (100%) rename patches/{api-unmapped/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch => api/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch} (100%) rename patches/{api-unmapped/0022-Complete-resource-pack-API.patch => api/0023-Complete-resource-pack-API.patch} (100%) rename patches/{api-unmapped/0023-Use-ASM-for-event-executors.patch => api/0024-Use-ASM-for-event-executors.patch} (99%) rename patches/{api-unmapped/0024-Add-a-call-helper-to-Event.patch => api/0025-Add-a-call-helper-to-Event.patch} (100%) rename patches/{api-unmapped/0025-Add-sender-name-to-commands.yml-replacement.patch => api/0026-Add-sender-name-to-commands.yml-replacement.patch} (100%) rename patches/{api-unmapped/0026-Add-command-to-reload-permissions.yml-and-require-co.patch => api/0027-Add-command-to-reload-permissions.yml-and-require-co.patch} (100%) rename patches/{api-unmapped/0027-Custom-replacement-for-eaten-items.patch => api/0028-Custom-replacement-for-eaten-items.patch} (100%) rename patches/{api-unmapped/0028-Entity-AddTo-RemoveFrom-World-Events.patch => api/0029-Entity-AddTo-RemoveFrom-World-Events.patch} (100%) rename patches/{api-unmapped/0029-EntityPathfindEvent.patch => api/0030-EntityPathfindEvent.patch} (100%) rename patches/{api-unmapped/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch => api/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch} (100%) rename patches/{api-unmapped/0031-Add-MetadataStoreBase.removeAll-Plugin.patch => api/0032-Add-MetadataStoreBase.removeAll-Plugin.patch} (100%) rename patches/{server-remapped => removed/1.17}/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch (99%) create mode 100644 patches/removed/1.17/0051-Player-Tab-List-and-Title-APIs.patch rename patches/{server-remapped => removed/1.17}/0053-Change-implementation-of-tile-entity-removal-list.patch (98%) delete mode 100644 patches/server-remapped/0039-Configurable-mob-spawner-tick-rate.patch delete mode 100644 patches/server-remapped/0041-Add-BeaconEffectEvent.patch delete mode 100644 patches/server-remapped/0044-Disable-spigot-tick-limiters.patch delete mode 100644 patches/server-remapped/0052-Ensure-inv-drag-is-in-bounds.patch rename patches/{server-remapped/0036-Disable-explosion-knockback.patch => server/0033-Disable-explosion-knockback.patch} (84%) rename patches/{server-remapped/0037-Disable-thunder.patch => server/0034-Disable-thunder.patch} (86%) rename patches/{server-remapped/0038-Disable-ice-and-snow.patch => server/0035-Disable-ice-and-snow.patch} (91%) create mode 100644 patches/server/0036-Configurable-mob-spawner-tick-rate.patch create mode 100644 patches/server/0037-Add-BeaconEffectEvent.patch rename patches/{server-remapped/0042-Configurable-container-update-tick-rate.patch => server/0038-Configurable-container-update-tick-rate.patch} (85%) rename patches/{server-remapped/0043-Use-UserCache-for-player-heads.patch => server/0039-Use-UserCache-for-player-heads.patch} (65%) create mode 100644 patches/server/0040-Disable-spigot-tick-limiters.patch rename patches/{server-remapped/0045-Add-PlayerInitialSpawnEvent.patch => server/0041-Add-PlayerInitialSpawnEvent.patch} (83%) rename patches/{server-remapped/0046-Configurable-Disabling-Cat-Chest-Detection.patch => server/0042-Configurable-Disabling-Cat-Chest-Detection.patch} (92%) rename patches/{server-remapped/0047-Ensure-commands-are-not-ran-async.patch => server/0043-Ensure-commands-are-not-ran-async.patch} (88%) rename patches/{server-remapped/0048-All-chunks-are-slime-spawn-chunks-toggle.patch => server/0044-All-chunks-are-slime-spawn-chunks-toggle.patch} (74%) rename patches/{server-remapped/0049-Expose-server-CommandMap.patch => server/0045-Expose-server-CommandMap.patch} (70%) rename patches/{server-remapped/0050-Be-a-bit-more-informative-in-maxHealth-exception.patch => server/0046-Be-a-bit-more-informative-in-maxHealth-exception.patch} (65%) rename patches/{server-remapped/0051-Player-Tab-List-and-Title-APIs.patch => server/0047-Player-Tab-List-and-Title-APIs.patch} (74%) create mode 100644 patches/server/0048-Ensure-inv-drag-is-in-bounds.patch rename patches/{server-remapped/0054-Add-configurable-portal-search-radius.patch => server/0049-Add-configurable-portal-search-radius.patch} (71%) rename patches/{server-remapped/0055-Add-velocity-warnings.patch => server/0050-Add-velocity-warnings.patch} (85%) rename patches/{server-remapped/0056-Configurable-inter-world-teleportation-safety.patch => server/0051-Configurable-inter-world-teleportation-safety.patch} (93%) rename patches/{server-remapped/0057-Add-exception-reporting-event.patch => server/0052-Add-exception-reporting-event.patch} (72%) rename patches/{server-remapped/0058-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch => server/0053-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch} (58%) rename patches/{server-remapped/0059-Disable-Scoreboards-for-non-players-by-default.patch => server/0054-Disable-Scoreboards-for-non-players-by-default.patch} (80%) rename patches/{server-remapped/0060-Add-methods-for-working-with-arrows-stuck-in-living-.patch => server/0055-Add-methods-for-working-with-arrows-stuck-in-living-.patch} (74%) rename patches/{server-remapped/0061-Complete-resource-pack-API.patch => server/0056-Complete-resource-pack-API.patch} (68%) rename patches/{server-remapped/0062-Chunk-Save-Reattempt.patch => server/0057-Chunk-Save-Reattempt.patch} (79%) rename patches/{server-remapped/0063-Default-loading-permissions.yml-before-plugins.patch => server/0058-Default-loading-permissions.yml-before-plugins.patch} (76%) rename patches/{server-remapped/0064-Allow-Reloading-of-Custom-Permissions.patch => server/0059-Allow-Reloading-of-Custom-Permissions.patch} (90%) rename patches/{server-remapped/0065-Remove-Metadata-on-reload.patch => server/0060-Remove-Metadata-on-reload.patch} (77%) rename patches/{server-remapped/0066-Handle-Item-Meta-Inconsistencies.patch => server/0061-Handle-Item-Meta-Inconsistencies.patch} (79%) rename patches/{server-remapped/0067-Configurable-Non-Player-Arrow-Despawn-Rate.patch => server/0062-Configurable-Non-Player-Arrow-Despawn-Rate.patch} (92%) rename patches/{server-remapped/0068-Add-World-Util-Methods.patch => server/0063-Add-World-Util-Methods.patch} (87%) rename patches/{server-remapped/0069-Custom-replacement-for-eaten-items.patch => server/0064-Custom-replacement-for-eaten-items.patch} (88%) rename patches/{server-remapped/0070-handle-NaN-health-absorb-values-and-repair-bad-data.patch => server/0065-handle-NaN-health-absorb-values-and-repair-bad-data.patch} (65%) diff --git a/patches/api-unmapped/0010-Add-PlayerLocaleChangeEvent.patch b/patches/api/0011-Add-PlayerLocaleChangeEvent.patch similarity index 100% rename from patches/api-unmapped/0010-Add-PlayerLocaleChangeEvent.patch rename to patches/api/0011-Add-PlayerLocaleChangeEvent.patch diff --git a/patches/api-unmapped/0011-Add-player-view-distance-API.patch b/patches/api/0012-Add-player-view-distance-API.patch similarity index 100% rename from patches/api-unmapped/0011-Add-player-view-distance-API.patch rename to patches/api/0012-Add-player-view-distance-API.patch diff --git a/patches/api-unmapped/0012-Add-BeaconEffectEvent.patch b/patches/api/0013-Add-BeaconEffectEvent.patch similarity index 100% rename from patches/api-unmapped/0012-Add-BeaconEffectEvent.patch rename to patches/api/0013-Add-BeaconEffectEvent.patch diff --git a/patches/api-unmapped/0013-Add-PlayerInitialSpawnEvent.patch b/patches/api/0014-Add-PlayerInitialSpawnEvent.patch similarity index 100% rename from patches/api-unmapped/0013-Add-PlayerInitialSpawnEvent.patch rename to patches/api/0014-Add-PlayerInitialSpawnEvent.patch diff --git a/patches/api-unmapped/0014-Automatically-disable-plugins-that-fail-to-load.patch b/patches/api/0015-Automatically-disable-plugins-that-fail-to-load.patch similarity index 100% rename from patches/api-unmapped/0014-Automatically-disable-plugins-that-fail-to-load.patch rename to patches/api/0015-Automatically-disable-plugins-that-fail-to-load.patch diff --git a/patches/api-unmapped/0015-Expose-server-CommandMap.patch b/patches/api/0016-Expose-server-CommandMap.patch similarity index 88% rename from patches/api-unmapped/0015-Expose-server-CommandMap.patch rename to patches/api/0016-Expose-server-CommandMap.patch index 6d7e3f1431..539c236ad6 100644 --- a/patches/api-unmapped/0015-Expose-server-CommandMap.patch +++ b/patches/api/0016-Expose-server-CommandMap.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Expose server CommandMap diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 0636edd8d9121eabfa60957c8c224261d228a16b..8d707e117035d5bc0d8c9a5fd386ee8355359259 100644 +index 1014871a3d7bfcf2b749d20e6ef8096876f9b4d7..72f0268e70382a258aeac9a9d6d860e0284378ad 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1717,6 +1717,19 @@ public final class Bukkit { @@ -29,7 +29,7 @@ index 0636edd8d9121eabfa60957c8c224261d228a16b..8d707e117035d5bc0d8c9a5fd386ee83 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 5c638e0d45e8896382bdbf9b9c10474b05a97df5..24bcc63afbda5f27aad385dc707f262d1a3a3399 100644 +index 3f74dc04df61e7d038c99ad9c1c3bfff086a019a..8fc591b16da774d60e85e3f13e44e9b5be671a3b 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1311,6 +1311,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api-unmapped/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch b/patches/api/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch similarity index 94% rename from patches/api-unmapped/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch rename to patches/api/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch index 28128cfb69..84e54e9f5e 100644 --- a/patches/api-unmapped/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch +++ b/patches/api/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Graduate bungeecord chat API from spigot subclasses Change Javadoc to be accurate diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 10274053320f1ec690a65d3794abb44b58658059..22b83b142de97dcba28fa9a49730de7880d0b5d2 100644 +index 72f0268e70382a258aeac9a9d6d860e0284378ad..8646fc0987a8833996c5d977c36fe0d01bf72992 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -285,6 +285,30 @@ public final class Bukkit { @@ -41,7 +41,7 @@ index 10274053320f1ec690a65d3794abb44b58658059..22b83b142de97dcba28fa9a49730de78 * Gets the name of the update folder. The update folder is used to safely * update plugins at the right moment on a plugin load. diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 7e4a728ceb943b6a32b9ba9b84bada34e71c0980..9ce9b4ce2da6c57c62607502ae2042e30fc26d88 100644 +index 8fc591b16da774d60e85e3f13e44e9b5be671a3b..599347ef656acad9a40be15fc5030e5d0f1630df 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -234,6 +234,30 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @@ -76,7 +76,7 @@ index 7e4a728ceb943b6a32b9ba9b84bada34e71c0980..9ce9b4ce2da6c57c62607502ae2042e3 * Gets the name of the update folder. The update folder is used to safely * update plugins at the right moment on a plugin load. diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 68795a48cb15d322906ce0569b7701231c1f94c2..88853cc165c67fd60a0a8f87e4ce356e4ca045f9 100644 +index f34601480a3b3069c30c52d258a35a2a79c981fb..4686212255e8de3e5a6f43d86f28fad595f687ed 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -614,6 +614,42 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM diff --git a/patches/api-unmapped/0018-Add-exception-reporting-event.patch b/patches/api/0018-Add-exception-reporting-event.patch similarity index 99% rename from patches/api-unmapped/0018-Add-exception-reporting-event.patch rename to patches/api/0018-Add-exception-reporting-event.patch index b295b466fc..0b5258ca98 100644 --- a/patches/api-unmapped/0018-Add-exception-reporting-event.patch +++ b/patches/api/0018-Add-exception-reporting-event.patch @@ -506,7 +506,7 @@ index f020cb04eba27a2e70fc7cf799ebbfb434b9d974..adfc7aae2c0f49bbcdd358e83b04a0cf } diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 745eaa8f2f2ff83536301db8ca47a8af30df7a73..d0fec44d2546290091649879450761ce08514fcb 100644 +index 7548e40af8043c1b5716f2d7d0122833466854c4..c2c49ee9b5531bc4761d2da54cd707c57fc647bf 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -23,6 +23,10 @@ import java.util.WeakHashMap; diff --git a/patches/api-unmapped/0017-Player-Tab-List-and-Title-APIs.patch b/patches/api/0019-Player-Tab-List-and-Title-APIs.patch similarity index 99% rename from patches/api-unmapped/0017-Player-Tab-List-and-Title-APIs.patch rename to patches/api/0019-Player-Tab-List-and-Title-APIs.patch index 90316cae1d..e808ed413d 100644 --- a/patches/api-unmapped/0017-Player-Tab-List-and-Title-APIs.patch +++ b/patches/api/0019-Player-Tab-List-and-Title-APIs.patch @@ -432,7 +432,7 @@ index 0000000000000000000000000000000000000000..9e90c3df567a65b48a0b9341f784eb90 + } +} diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 88853cc165c67fd60a0a8f87e4ce356e4ca045f9..c9e4cb2d153fc0c6853fe520263a0073e7504e38 100644 +index 4686212255e8de3e5a6f43d86f28fad595f687ed..769ad98fd7a6a866b320e1ccffd7962228d564cf 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -2,6 +2,7 @@ package org.bukkit.entity; diff --git a/patches/api-unmapped/0019-Fix-ServerListPingEvent-flagging-as-Async.patch b/patches/api/0020-Fix-ServerListPingEvent-flagging-as-Async.patch similarity index 100% rename from patches/api-unmapped/0019-Fix-ServerListPingEvent-flagging-as-Async.patch rename to patches/api/0020-Fix-ServerListPingEvent-flagging-as-Async.patch diff --git a/patches/api-unmapped/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch b/patches/api/0021-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch similarity index 100% rename from patches/api-unmapped/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch rename to patches/api/0021-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch diff --git a/patches/api-unmapped/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/api/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch similarity index 100% rename from patches/api-unmapped/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch rename to patches/api/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch diff --git a/patches/api-unmapped/0022-Complete-resource-pack-API.patch b/patches/api/0023-Complete-resource-pack-API.patch similarity index 100% rename from patches/api-unmapped/0022-Complete-resource-pack-API.patch rename to patches/api/0023-Complete-resource-pack-API.patch diff --git a/patches/api-unmapped/0023-Use-ASM-for-event-executors.patch b/patches/api/0024-Use-ASM-for-event-executors.patch similarity index 99% rename from patches/api-unmapped/0023-Use-ASM-for-event-executors.patch rename to patches/api/0024-Use-ASM-for-event-executors.patch index bcbe8ec071..5ecb88e4ba 100644 --- a/patches/api-unmapped/0023-Use-ASM-for-event-executors.patch +++ b/patches/api/0024-Use-ASM-for-event-executors.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Use ASM for event executors. Uses method handles for private or static methods. diff --git a/pom.xml b/pom.xml -index 1ced7a212684cee8faf07fa9a083adcd47be7fcb..7ec7e6047193a6b390d24f6d2722e35d1d36830d 100644 +index cae43ce5c1287a4cd117fd069d34ebc1b64b7fdb..2c757ffb2253748c6a81f9b373290108209b6ff2 100644 --- a/pom.xml +++ b/pom.xml @@ -163,6 +163,17 @@ diff --git a/patches/api-unmapped/0024-Add-a-call-helper-to-Event.patch b/patches/api/0025-Add-a-call-helper-to-Event.patch similarity index 100% rename from patches/api-unmapped/0024-Add-a-call-helper-to-Event.patch rename to patches/api/0025-Add-a-call-helper-to-Event.patch diff --git a/patches/api-unmapped/0025-Add-sender-name-to-commands.yml-replacement.patch b/patches/api/0026-Add-sender-name-to-commands.yml-replacement.patch similarity index 100% rename from patches/api-unmapped/0025-Add-sender-name-to-commands.yml-replacement.patch rename to patches/api/0026-Add-sender-name-to-commands.yml-replacement.patch diff --git a/patches/api-unmapped/0026-Add-command-to-reload-permissions.yml-and-require-co.patch b/patches/api/0027-Add-command-to-reload-permissions.yml-and-require-co.patch similarity index 100% rename from patches/api-unmapped/0026-Add-command-to-reload-permissions.yml-and-require-co.patch rename to patches/api/0027-Add-command-to-reload-permissions.yml-and-require-co.patch diff --git a/patches/api-unmapped/0027-Custom-replacement-for-eaten-items.patch b/patches/api/0028-Custom-replacement-for-eaten-items.patch similarity index 100% rename from patches/api-unmapped/0027-Custom-replacement-for-eaten-items.patch rename to patches/api/0028-Custom-replacement-for-eaten-items.patch diff --git a/patches/api-unmapped/0028-Entity-AddTo-RemoveFrom-World-Events.patch b/patches/api/0029-Entity-AddTo-RemoveFrom-World-Events.patch similarity index 100% rename from patches/api-unmapped/0028-Entity-AddTo-RemoveFrom-World-Events.patch rename to patches/api/0029-Entity-AddTo-RemoveFrom-World-Events.patch diff --git a/patches/api-unmapped/0029-EntityPathfindEvent.patch b/patches/api/0030-EntityPathfindEvent.patch similarity index 100% rename from patches/api-unmapped/0029-EntityPathfindEvent.patch rename to patches/api/0030-EntityPathfindEvent.patch diff --git a/patches/api-unmapped/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch b/patches/api/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch similarity index 100% rename from patches/api-unmapped/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch rename to patches/api/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch diff --git a/patches/api-unmapped/0031-Add-MetadataStoreBase.removeAll-Plugin.patch b/patches/api/0032-Add-MetadataStoreBase.removeAll-Plugin.patch similarity index 100% rename from patches/api-unmapped/0031-Add-MetadataStoreBase.removeAll-Plugin.patch rename to patches/api/0032-Add-MetadataStoreBase.removeAll-Plugin.patch diff --git a/patches/server-remapped/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch b/patches/removed/1.17/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch similarity index 99% rename from patches/server-remapped/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch rename to patches/removed/1.17/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch index c77faa1999..d8dbfa7a24 100644 --- a/patches/server-remapped/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch +++ b/patches/removed/1.17/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch @@ -3,6 +3,8 @@ From: Jedediah Smith Date: Wed, 2 Mar 2016 23:13:07 -0600 Subject: [PATCH] Send absolute position the first time an entity is seen +Not needed anymore, packet spawn sends full position + diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java index 59a5f82c9f57d760ba4959a040ce8cbf0f49e4aa..d1bc927c8b429f43de2cdad98f8b329ff4c8b4db 100644 diff --git a/patches/removed/1.17/0051-Player-Tab-List-and-Title-APIs.patch b/patches/removed/1.17/0051-Player-Tab-List-and-Title-APIs.patch new file mode 100644 index 0000000000..3ad1a77c63 --- /dev/null +++ b/patches/removed/1.17/0051-Player-Tab-List-and-Title-APIs.patch @@ -0,0 +1,31 @@ +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java +index 69ff8df7340e60c476803256750a48f0b43414d3..df444daeb181ff78170f7b92bd02f1f1862dfa2e 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java +@@ -47,6 +47,17 @@ public class ClientboundSetTitlesPacket implements Packet -Date: Wed, 2 Mar 2016 15:03:53 -0600 -Subject: [PATCH] Configurable mob spawner tick rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2..4de86b09c6bc3c1974ce61b550ccb73d37f6f170 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -176,4 +176,9 @@ public class PaperWorldConfig { - private void disableIceAndSnow(){ - disableIceAndSnow = getBoolean("disable-ice-and-snow", false); - } -+ -+ public int mobSpawnerTickRate; -+ private void mobSpawnerTickRate() { -+ mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 10058d3c3565382faa893b79119c5caf845bf29a..ed631d5bfba5d2543e8eed017a7c484ad3ddb453 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -41,6 +41,7 @@ public abstract class BaseSpawner { - public int maxNearbyEntities = 6; - public int requiredPlayerRange = 16; - public int spawnRange = 4; -+ private int tickDelay = 0; // Paper - - public BaseSpawner() {} - -@@ -70,6 +71,10 @@ public abstract class BaseSpawner { - } - - public void tick() { -+ // Paper start - Configurable mob spawner tick rate -+ if (spawnDelay > 0 && --tickDelay > 0) return; -+ tickDelay = this.getLevel().paperConfig.mobSpawnerTickRate; -+ // Paper end - if (!this.isNearPlayer()) { - this.oSpin = this.spin; - } else { -@@ -84,18 +89,18 @@ public abstract class BaseSpawner { - world.addParticle(ParticleTypes.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); - world.addParticle(ParticleTypes.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D); - if (this.spawnDelay > 0) { -- --this.spawnDelay; -+ this.spawnDelay -= tickDelay; // Paper - } - - this.oSpin = this.spin; - this.spin = (this.spin + (double) (1000.0F / ((float) this.spawnDelay + 200.0F))) % 360.0D; - } else { -- if (this.spawnDelay == -1) { -+ if (this.spawnDelay < -tickDelay) { // Paper - this.delay(); - } - - if (this.spawnDelay > 0) { -- --this.spawnDelay; -+ this.spawnDelay -= tickDelay; // Paper - return; - } - diff --git a/patches/server-remapped/0041-Add-BeaconEffectEvent.patch b/patches/server-remapped/0041-Add-BeaconEffectEvent.patch deleted file mode 100644 index d61c3cadc2..0000000000 --- a/patches/server-remapped/0041-Add-BeaconEffectEvent.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 23:30:53 -0600 -Subject: [PATCH] Add BeaconEffectEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -index c91f7bcfab2da6a23114a3cff63ca31dab443393..5f75c6d653a31f65fcf9c0e280d796e15d059c00 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -@@ -25,7 +25,6 @@ import net.minecraft.world.effect.MobEffect; - import net.minecraft.world.effect.MobEffectInstance; - import net.minecraft.world.effect.MobEffects; - import net.minecraft.world.entity.player.Inventory; --import net.minecraft.world.entity.player.Player; - import net.minecraft.world.inventory.AbstractContainerMenu; - import net.minecraft.world.inventory.BeaconMenu; - import net.minecraft.world.inventory.ContainerData; -@@ -41,6 +40,11 @@ import net.minecraft.world.phys.AABB; - import org.bukkit.craftbukkit.potion.CraftPotionUtil; - import org.bukkit.potion.PotionEffect; - // CraftBukkit end -+// Paper start -+import org.bukkit.craftbukkit.event.CraftEventFactory; -+import org.bukkit.entity.Player; -+import com.destroystokyo.paper.event.block.BeaconEffectEvent; -+// Paper end - - public class BeaconBlockEntity extends BlockEntity implements MenuProvider, TickableBlockEntity { - -@@ -260,21 +264,37 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - double d0 = (double) (this.levels * 10 + 10); - - AABB axisalignedbb = (new AABB(this.worldPosition)).inflate(d0).expandTowards(0.0D, (double) this.level.getMaxBuildHeight(), 0.0D); -- List list = this.level.getEntitiesOfClass(Player.class, axisalignedbb); -+ List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.player.Player.class, axisalignedbb); - - return list; - } - } - - private void applyEffect(List list, MobEffect effects, int i, int b0) { -+ // Paper - BeaconEffectEvent -+ applyEffect(list, effects, i, b0, true); -+ } -+ -+ private void applyEffect(List list, MobEffect effects, int i, int b0, boolean isPrimary) { -+ // Paper - BeaconEffectEvent - { - Iterator iterator = list.iterator(); - -- Player entityhuman; -+ net.minecraft.world.entity.player.Player entityhuman; -+ -+ // Paper start - BeaconEffectEvent -+ org.bukkit.block.Block block = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); -+ PotionEffect effect = CraftPotionUtil.toBukkit(new MobEffectInstance(effects, i, b0, true, true)); -+ // Paper end - - while (iterator.hasNext()) { -- entityhuman = (Player) iterator.next(); -- entityhuman.addEffect(new MobEffectInstance(effects, i, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); -+ entityhuman = (net.minecraft.world.entity.player.Player) iterator.next(); -+ -+ // Paper start - BeaconEffectEvent -+ BeaconEffectEvent event = new BeaconEffectEvent(block, effect, (Player) entityhuman.getBukkitEntity(), isPrimary); -+ if (CraftEventFactory.callEvent(event).isCancelled()) continue; -+ entityhuman.addEffect(new MobEffectInstance(CraftPotionUtil.fromBukkit(event.getEffect())), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); -+ // Paper end - } - } - } -@@ -297,10 +317,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - int i = getLevelCb(); - List list = getHumansInRange(); - -- applyEffect(list, this.primaryPower, i, b0); -+ applyEffect(list, this.primaryPower, i, b0, true); // Paper - BeaconEffectEvent - - if (hasSecondaryEffect()) { -- applyEffect(list, this.secondaryPower, i, 0); -+ applyEffect(list, this.secondaryPower, i, 0, false); // Paper - BeaconEffectEvent - } - } - -@@ -308,7 +328,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - // CraftBukkit end - - public void playSound(SoundEvent soundeffect) { -- this.level.playSound((Player) null, this.worldPosition, soundeffect, SoundSource.BLOCKS, 1.0F, 1.0F); -+ this.level.playSound((net.minecraft.world.entity.player.Player) null, this.worldPosition, soundeffect, SoundSource.BLOCKS, 1.0F, 1.0F); - } - - public int getLevels() { -@@ -368,7 +388,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - - @Nullable - @Override -- public AbstractContainerMenu createMenu(int syncId, Inventory inv, Player player) { -+ public AbstractContainerMenu createMenu(int syncId, Inventory inv, net.minecraft.world.entity.player.Player player) { - return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName()) ? new BeaconMenu(syncId, inv, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; - } - diff --git a/patches/server-remapped/0044-Disable-spigot-tick-limiters.patch b/patches/server-remapped/0044-Disable-spigot-tick-limiters.patch deleted file mode 100644 index 703b1b0774..0000000000 --- a/patches/server-remapped/0044-Disable-spigot-tick-limiters.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Mar 2016 23:45:17 -0600 -Subject: [PATCH] Disable spigot tick limiters - - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index f71b56fa079e2c7b2123061a8e1a7cb41935bab6..e25666328dbf433b8358f2637d93b4128034bbaa 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -707,9 +707,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - // Spigot start - // Iterator iterator = this.tileEntityListTick.iterator(); - int tilesThisCycle = 0; -- for (tileLimiter.initTick(); -- tilesThisCycle < tickableBlockEntities.size() && (tilesThisCycle % 10 != 0 || tileLimiter.shouldContinue()); -- tileTickPosition++, tilesThisCycle++) { -+ for (tileTickPosition = 0; tileTickPosition < tickableBlockEntities.size(); tileTickPosition++) { // Paper - Disable tick limiters - tileTickPosition = (tileTickPosition < tickableBlockEntities.size()) ? tileTickPosition : 0; - BlockEntity tileentity = (BlockEntity) this.tickableBlockEntities.get(tileTickPosition); - // Spigot start diff --git a/patches/server-remapped/0052-Ensure-inv-drag-is-in-bounds.patch b/patches/server-remapped/0052-Ensure-inv-drag-is-in-bounds.patch deleted file mode 100644 index 63c52e2842..0000000000 --- a/patches/server-remapped/0052-Ensure-inv-drag-is-in-bounds.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:33:53 -0600 -Subject: [PATCH] Ensure inv drag is in bounds - - -diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -index c377a425dc3274b8aa25f94ce8f76efda2652def..72b0cfcc5aab03e14e63440c734436e9c1432111 100644 ---- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -238,7 +238,7 @@ public abstract class AbstractContainerMenu { - this.resetQuickCraft(); - } - } else if (this.quickcraftStatus == 1) { -- Slot slot = (Slot) this.slots.get(i); -+ Slot slot = i < this.slots.size() ? this.slots.get(i) : null; // Paper - Ensure drag in bounds - - itemstack1 = playerinventory.getCarried(); - if (slot != null && canItemQuickReplace(slot, itemstack1, true) && slot.isAllowed(itemstack1) && (this.quickcraftType == 2 || itemstack1.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) { diff --git a/patches/server-remapped/0036-Disable-explosion-knockback.patch b/patches/server/0033-Disable-explosion-knockback.patch similarity index 84% rename from patches/server-remapped/0036-Disable-explosion-knockback.patch rename to patches/server/0033-Disable-explosion-knockback.patch index d9f4ff9678..ee685ef82c 100644 --- a/patches/server-remapped/0036-Disable-explosion-knockback.patch +++ b/patches/server/0033-Disable-explosion-knockback.patch @@ -19,10 +19,10 @@ index 4881b03d470646843bad1bc343eb6a6ab9072d8e..2222c1bb5f8625eee4d88946e4bfdfa2 + } } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index e5f8cee6726ea9a90c540bb10fd8594a35bb5e40..afd114e1ce00db72534d470fed12101bb237f266 100644 +index ebe33c891e25c729c4373190da86c7a8198b6a55..cc8fb033ca8241acb984e3440a44c7a083e2f3f6 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1280,6 +1280,7 @@ public abstract class LivingEntity extends Entity { +@@ -1380,6 +1380,7 @@ public abstract class LivingEntity extends Entity { } } @@ -30,7 +30,7 @@ index e5f8cee6726ea9a90c540bb10fd8594a35bb5e40..afd114e1ce00db72534d470fed12101b if (flag1) { if (flag) { this.level.broadcastEntityEvent(this, (byte) 29); -@@ -1298,6 +1299,7 @@ public abstract class LivingEntity extends Entity { +@@ -1400,6 +1401,7 @@ public abstract class LivingEntity extends Entity { b0 = 2; } @@ -38,7 +38,7 @@ index e5f8cee6726ea9a90c540bb10fd8594a35bb5e40..afd114e1ce00db72534d470fed12101b this.level.broadcastEntityEvent(this, b0); } -@@ -1321,6 +1323,7 @@ public abstract class LivingEntity extends Entity { +@@ -1423,6 +1425,7 @@ public abstract class LivingEntity extends Entity { } } @@ -47,10 +47,10 @@ index e5f8cee6726ea9a90c540bb10fd8594a35bb5e40..afd114e1ce00db72534d470fed12101b if (!this.checkTotemDeathProtection(source)) { SoundEvent soundeffect = this.getDeathSound(); diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index db46caaa5ad5f129d313c65c5006cb24853768be..45a75f7be308678336e192828becf6cf5c9047bc 100644 +index 5e06fa58bd5064fea4154f7f34fdef6aa08a2daf..edc0845ae735a9cf3e0f1a3a2b7eabf726d62744 100644 --- a/src/main/java/net/minecraft/world/level/Explosion.java +++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -215,14 +215,14 @@ public class Explosion { +@@ -243,14 +243,14 @@ public class Explosion { double d14 = d13; if (entity instanceof LivingEntity) { @@ -62,8 +62,8 @@ index db46caaa5ad5f129d313c65c5006cb24853768be..45a75f7be308678336e192828becf6cf if (entity instanceof Player) { Player entityhuman = (Player) entity; -- if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.flying)) { -+ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.flying) && !level.paperConfig.disableExplosionKnockback) { // Paper - Disable explosion knockback +- if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.getAbilities().flying)) { ++ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.getAbilities().flying) && !level.paperConfig.disableExplosionKnockback) { // Paper - Disable explosion knockback this.hitPlayers.put(entityhuman, new Vec3(d8 * d13, d9 * d13, d10 * d13)); } } diff --git a/patches/server-remapped/0037-Disable-thunder.patch b/patches/server/0034-Disable-thunder.patch similarity index 86% rename from patches/server-remapped/0037-Disable-thunder.patch rename to patches/server/0034-Disable-thunder.patch index d5971380bb..cabba0e9c2 100644 --- a/patches/server-remapped/0037-Disable-thunder.patch +++ b/patches/server/0034-Disable-thunder.patch @@ -19,15 +19,15 @@ index 2222c1bb5f8625eee4d88946e4bfdfa2fe598977..083e421f8496b5336af473b108498ed2 + } } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index d2bb9385fbc21cdef6cef06680fac685d3da3570..3fc8fb197400c63bc85f57ff484803659619f775 100644 +index d26e8803222276fb7bb1bedd9fd13a8861ce671c..4792280988ac13593d59f6a10fa111eafa08328f 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -580,7 +580,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -592,7 +592,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl gameprofilerfiller.push("thunder"); BlockPos blockposition; - if (flag && this.isThundering() && this.random.nextInt(100000) == 0) { + if (!this.paperConfig.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder - blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); + blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15)); if (this.isRainingAt(blockposition)) { DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); diff --git a/patches/server-remapped/0038-Disable-ice-and-snow.patch b/patches/server/0035-Disable-ice-and-snow.patch similarity index 91% rename from patches/server-remapped/0038-Disable-ice-and-snow.patch rename to patches/server/0035-Disable-ice-and-snow.patch index 9d2d87a6b0..54110b08c5 100644 --- a/patches/server-remapped/0038-Disable-ice-and-snow.patch +++ b/patches/server/0035-Disable-ice-and-snow.patch @@ -19,10 +19,10 @@ index 083e421f8496b5336af473b108498ed28b984774..2f7a5a4a5a7b29750cfd777e0bc5d19a + } } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 3fc8fb197400c63bc85f57ff484803659619f775..6c6098731752d61b5241710b075d4ffe3826daac 100644 +index 4792280988ac13593d59f6a10fa111eafa08328f..b0ecf3c491e802aa292a0a8b7be37362c38ce084 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -604,7 +604,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -616,7 +616,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } gameprofilerfiller.popPush("iceandsnow"); diff --git a/patches/server/0036-Configurable-mob-spawner-tick-rate.patch b/patches/server/0036-Configurable-mob-spawner-tick-rate.patch new file mode 100644 index 0000000000..92dd72b2a9 --- /dev/null +++ b/patches/server/0036-Configurable-mob-spawner-tick-rate.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudzzy +Date: Wed, 2 Mar 2016 15:03:53 -0600 +Subject: [PATCH] Configurable mob spawner tick rate + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2..4de86b09c6bc3c1974ce61b550ccb73d37f6f170 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -176,4 +176,9 @@ public class PaperWorldConfig { + private void disableIceAndSnow(){ + disableIceAndSnow = getBoolean("disable-ice-and-snow", false); + } ++ ++ public int mobSpawnerTickRate; ++ private void mobSpawnerTickRate() { ++ mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); ++ } + } +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index a003e1c0d99a4d4c88269ea5bad250ba73bbc9c9..037dafb59e54047d1d54474c44897d35b8f46c98 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -46,6 +46,7 @@ public abstract class BaseSpawner { + public int requiredPlayerRange; + public int spawnRange; + private final Random random; ++ private int tickDelay = 0; // Paper + + public BaseSpawner() { + this.spawnPotentials = BaseSpawner.EMPTY_POTENTIALS; +@@ -101,13 +102,17 @@ public abstract class BaseSpawner { + } + + public void serverTick(ServerLevel world, BlockPos pos) { ++ // Paper start - Configurable mob spawner tick rate ++ if (spawnDelay > 0 && --tickDelay > 0) return; ++ tickDelay = world.paperConfig.mobSpawnerTickRate; ++ // Paper end + if (this.isNearPlayer(world, pos)) { +- if (this.spawnDelay == -1) { ++ if (this.spawnDelay < -tickDelay) { + this.delay(world, pos); + } + + if (this.spawnDelay > 0) { +- --this.spawnDelay; ++ this.spawnDelay -= tickDelay; // Paper + } else { + boolean flag = false; + +@@ -156,8 +161,7 @@ public abstract class BaseSpawner { + ((Mob) entity).finalizeSpawn(world, world.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.SPAWNER, (SpawnGroupData) null, (CompoundTag) null); + } + // Spigot Start +- if ( entityinsentient.level.spigotConfig.nerfSpawnerMobs ) +- { ++ if (entityinsentient.level.spigotConfig.nerfSpawnerMobs) { + entityinsentient.aware = false; + } + // Spigot End diff --git a/patches/server/0037-Add-BeaconEffectEvent.patch b/patches/server/0037-Add-BeaconEffectEvent.patch new file mode 100644 index 0000000000..16a674c5ba --- /dev/null +++ b/patches/server/0037-Add-BeaconEffectEvent.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 2 Mar 2016 23:30:53 -0600 +Subject: [PATCH] Add BeaconEffectEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +index 5406ca495dd3dcb23929605d5b27bb4370a63d4d..0fa01b98f4a2ce2a7d34437a71d8c1cc7e718fb1 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -43,6 +43,10 @@ import net.minecraft.world.phys.AABB; + import org.bukkit.craftbukkit.potion.CraftPotionUtil; + import org.bukkit.potion.PotionEffect; + // CraftBukkit end ++// Paper start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import com.destroystokyo.paper.event.block.BeaconEffectEvent; ++// Paper end + + public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + +@@ -274,15 +278,23 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + } + } + +- private static void applyEffect(List list, MobEffect mobeffectlist, int j, int b0) { +- { ++ private static void applyEffect(List list, MobEffect effects, int i, int b0, boolean isPrimary, BlockPos worldPosition) { // Paper - BeaconEffectEvent ++ if (!list.isEmpty()) { // Paper - BeaconEffectEvent + Iterator iterator = list.iterator(); + + Player entityhuman; ++ // Paper start - BeaconEffectEvent ++ org.bukkit.block.Block block = ((Player) list.get(0)).level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ PotionEffect effect = CraftPotionUtil.toBukkit(new MobEffectInstance(effects, i, b0, true, true)); ++ // Paper end + + while (iterator.hasNext()) { +- entityhuman = (Player) iterator.next(); +- entityhuman.addEffect(new MobEffectInstance(mobeffectlist, j, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); ++ // Paper start - BeaconEffectEvent ++ entityhuman = (ServerPlayer) iterator.next(); ++ BeaconEffectEvent event = new BeaconEffectEvent(block, effect, (org.bukkit.entity.Player) entityhuman.getBukkitEntity(), isPrimary); ++ if (CraftEventFactory.callEvent(event).isCancelled()) continue; ++ entityhuman.addEffect(new MobEffectInstance(CraftPotionUtil.fromBukkit(event.getEffect())), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); ++ // Paper end + } + } + } +@@ -305,10 +317,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + int j = BeaconBlockEntity.getLevel(beaconLevel); + List list = BeaconBlockEntity.getHumansInRange(world, pos, beaconLevel); + +- BeaconBlockEntity.applyEffect(list, primaryEffect, j, b0); ++ BeaconBlockEntity.applyEffect(list, primaryEffect, j, b0, true, pos); // Paper - BeaconEffectEvent + + if (BeaconBlockEntity.hasSecondaryEffect(beaconLevel, primaryEffect, secondaryEffect)) { +- BeaconBlockEntity.applyEffect(list, secondaryEffect, j, 0); ++ BeaconBlockEntity.applyEffect(list, secondaryEffect, j, 0, false, pos); // Paper - BeaconEffectEvent + } + } + diff --git a/patches/server-remapped/0042-Configurable-container-update-tick-rate.patch b/patches/server/0038-Configurable-container-update-tick-rate.patch similarity index 85% rename from patches/server-remapped/0042-Configurable-container-update-tick-rate.patch rename to patches/server/0038-Configurable-container-update-tick-rate.patch index 3344a83459..3fb2e0b00b 100644 --- a/patches/server-remapped/0042-Configurable-container-update-tick-rate.patch +++ b/patches/server/0038-Configurable-container-update-tick-rate.patch @@ -19,18 +19,18 @@ index 4de86b09c6bc3c1974ce61b550ccb73d37f6f170..5a4c3a8c511f22c8c3240c9c7cd83a65 + } } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index f3797bd761c2c6782cce3fca25bc9ef37e5c4978..ffad931c72e52855a3f139354f5e85c460e2a80b 100644 +index b25f9a2d2d7f0af0fef60c4f1817cf165fed9cd6..b68a58abf254289a806636ca28521be39c13a82f 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -207,6 +207,7 @@ public class ServerPlayer extends Player implements ContainerListener { - public boolean ignoreSlotUpdateHack; +@@ -214,6 +214,7 @@ public class ServerPlayer extends Player { + private int containerCounter; public int latency; public boolean wonGame; + private int containerUpdateDelay; // Paper // CraftBukkit start public String displayName; -@@ -531,7 +532,12 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -589,7 +590,12 @@ public class ServerPlayer extends Player { --this.invulnerableTime; } diff --git a/patches/server-remapped/0043-Use-UserCache-for-player-heads.patch b/patches/server/0039-Use-UserCache-for-player-heads.patch similarity index 65% rename from patches/server-remapped/0043-Use-UserCache-for-player-heads.patch rename to patches/server/0039-Use-UserCache-for-player-heads.patch index 1c9a8dab7e..3be79b3496 100644 --- a/patches/server-remapped/0043-Use-UserCache-for-player-heads.patch +++ b/patches/server/0039-Use-UserCache-for-player-heads.patch @@ -5,20 +5,20 @@ Subject: [PATCH] Use UserCache for player heads diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index 11baf6fd5f7e408a570d5a48ae6b2fc05cd7e243..313ddd6b64e395a8caab77b3da005e52006ab2d7 100644 +index 354dcb1ddf74f39e367d50a8b8e2beeb9b2f9d02..b19d50bbe6c944ff66230ac013178bd036a438c8 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java @@ -166,7 +166,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { if (name == null) { - setProfile(null); + this.setProfile(null); } else { -- setProfile(new GameProfile(null, name)); +- this.setProfile(new GameProfile(null, name)); + // Paper start - Use Online Players Skull + GameProfile newProfile = null; -+ net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); -+ if (player != null) newProfile = player.getProfile(); ++ net.minecraft.server.level.ServerPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); ++ if (player != null) newProfile = player.getGameProfile(); + if (newProfile == null) newProfile = new GameProfile(null, name); -+ setProfile(newProfile); ++ this.setProfile(newProfile); + // Paper end } diff --git a/patches/server/0040-Disable-spigot-tick-limiters.patch b/patches/server/0040-Disable-spigot-tick-limiters.patch new file mode 100644 index 0000000000..82542b3c23 --- /dev/null +++ b/patches/server/0040-Disable-spigot-tick-limiters.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Wed, 2 Mar 2016 23:45:17 -0600 +Subject: [PATCH] Disable spigot tick limiters + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 794d43e6f1a2019f67daf7a93498225924c4394b..56362678e8de38c541fc851abf783f385a7903bf 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -696,9 +696,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Spigot start + // Iterator iterator = this.blockEntityTickers.iterator(); + int tilesThisCycle = 0; +- for (this.tileLimiter.initTick(); +- tilesThisCycle < this.blockEntityTickers.size() && (tilesThisCycle % 10 != 0 || this.tileLimiter.shouldContinue()); +- this.tileTickPosition++, tilesThisCycle++) { ++ for (tileTickPosition = 0; tileTickPosition < this.blockEntityTickers.size(); tileTickPosition++) { // Paper - Disable tick limiters + this.tileTickPosition = (this.tileTickPosition < this.blockEntityTickers.size()) ? this.tileTickPosition : 0; + TickingBlockEntity tickingblockentity = (TickingBlockEntity) this.blockEntityTickers.get(tileTickPosition); + // Spigot start diff --git a/patches/server-remapped/0045-Add-PlayerInitialSpawnEvent.patch b/patches/server/0041-Add-PlayerInitialSpawnEvent.patch similarity index 83% rename from patches/server-remapped/0045-Add-PlayerInitialSpawnEvent.patch rename to patches/server/0041-Add-PlayerInitialSpawnEvent.patch index 7e6b238460..f45f72f84e 100644 --- a/patches/server-remapped/0045-Add-PlayerInitialSpawnEvent.patch +++ b/patches/server/0041-Add-PlayerInitialSpawnEvent.patch @@ -9,19 +9,19 @@ This is a duplicate API from spigot, so use our duplicate subclass and improve setPosition to use raw diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8cdecaf2f63c78196e0c5046fe2431b40e072c8a..a63babe123fad398b07685ec57cd88756435457c 100644 +index 446dd8c15d4ccdced316deeaba379cb6937496ca..8e9d0ca8aa2b1403fc65ed8d792525047a610a3a 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -209,7 +209,7 @@ public abstract class PlayerList { +@@ -213,7 +213,7 @@ public abstract class PlayerList { // Spigot start - spawn location event Player bukkitPlayer = player.getBukkitEntity(); - org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(bukkitPlayer, bukkitPlayer.getLocation()); + org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(bukkitPlayer, bukkitPlayer.getLocation()); // Paper use our duplicate event - cserver.getPluginManager().callEvent(ev); + this.cserver.getPluginManager().callEvent(ev); Location loc = ev.getSpawnLocation(); -@@ -217,7 +217,10 @@ public abstract class PlayerList { +@@ -221,7 +221,10 @@ public abstract class PlayerList { player.setLevel(worldserver1); player.gameMode.setLevel((ServerLevel) player.level); @@ -34,10 +34,10 @@ index 8cdecaf2f63c78196e0c5046fe2431b40e072c8a..a63babe123fad398b07685ec57cd8875 // CraftBukkit - Moved message to after join diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f3f48c268639937874dd39eea9bd8e119eebdce7..72eb40f748c33572c2828f48ebd1ca7d5d5712c8 100644 +index 7e7291cc41735a6c251738492a4cdd1c7798066f..cb65a20d34196866eead7844b93c65bfb853f74c 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -397,7 +397,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -460,7 +460,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n return d1 * d1 + d2 * d2 + d3 * d3 < radius * radius; } diff --git a/patches/server-remapped/0046-Configurable-Disabling-Cat-Chest-Detection.patch b/patches/server/0042-Configurable-Disabling-Cat-Chest-Detection.patch similarity index 92% rename from patches/server-remapped/0046-Configurable-Disabling-Cat-Chest-Detection.patch rename to patches/server/0042-Configurable-Disabling-Cat-Chest-Detection.patch index 88836aa6a1..e900aa450b 100644 --- a/patches/server-remapped/0046-Configurable-Disabling-Cat-Chest-Detection.patch +++ b/patches/server/0042-Configurable-Disabling-Cat-Chest-Detection.patch @@ -20,10 +20,10 @@ index 5a4c3a8c511f22c8c3240c9c7cd83a65119c1054..70e074cdf2087e638af8e0f3878d0ef8 + } } diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java -index 1bda9a158eb4372b9ab7cf3097732e64810aefc6..6b95cd2e2af66eef324dfcc8f7642da2f9e39d4e 100644 +index 41186ae6c68e86f28e2858e17d926dcfdf30f9a2..eecb8c089b5f426b1395b47f714af32c210555ef 100644 --- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java +++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java -@@ -312,6 +312,11 @@ public class ChestBlock extends AbstractChestBlock implements +@@ -355,6 +355,11 @@ public class ChestBlock extends AbstractChestBlock implements } private static boolean isCatSittingOnChest(LevelAccessor world, BlockPos pos) { diff --git a/patches/server-remapped/0047-Ensure-commands-are-not-ran-async.patch b/patches/server/0043-Ensure-commands-are-not-ran-async.patch similarity index 88% rename from patches/server-remapped/0047-Ensure-commands-are-not-ran-async.patch rename to patches/server/0043-Ensure-commands-are-not-ran-async.patch index b0605d0e7a..c64f352663 100644 --- a/patches/server-remapped/0047-Ensure-commands-are-not-ran-async.patch +++ b/patches/server/0043-Ensure-commands-are-not-ran-async.patch @@ -14,10 +14,10 @@ big slowdown in execution but throwing an exception at same time to raise awaren that it is happening so that plugin authors can fix their code to stop executing commands async. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 016e91a6ca1c8457e3e367ac0597b73e81919b68..00689dc07625a02781052c5df2e466e8abe85708 100644 +index 94ebbcb7731c01fcb93f053eea109f544132139a..b38ca69d37d7f1af0e34297f45e63a98da754e35 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1852,6 +1852,29 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1858,6 +1858,29 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } if (!async && s.startsWith("/")) { @@ -48,10 +48,10 @@ index 016e91a6ca1c8457e3e367ac0597b73e81919b68..00689dc07625a02781052c5df2e466e8 } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { // Do nothing, this is coming from a plugin diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6fa31ca31128b1094eebd5f848c5b506dfeedeeb..783da25e189c0264ebf31e244677a6b653ff7b26 100644 +index 9949267091453726b737a1d673db34dacaeed369..70ba011fda5bba9ee30061825b8a0db82be288b1 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -759,6 +759,29 @@ public final class CraftServer implements Server { +@@ -762,6 +762,28 @@ public final class CraftServer implements Server { Validate.notNull(commandLine, "CommandLine cannot be null"); org.spigotmc.AsyncCatcher.catchOp("command dispatch"); // Spigot @@ -77,12 +77,11 @@ index 6fa31ca31128b1094eebd5f848c5b506dfeedeeb..783da25e189c0264ebf31e244677a6b6 + } + } + // Paper End -+ - if (commandMap.dispatch(sender, commandLine)) { + if (this.commandMap.dispatch(sender, commandLine)) { return true; } diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index ddef523ea8762c927f37f7d16d581e43367e8c6b..70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe 100644 +index 19c44daaa407b7c1c7a7ffe56fef8c8814c6d5b2..6a073a9dc44d93eba296a0e18a9c7be8a7881725 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java @@ -13,6 +13,7 @@ public class ServerShutdownThread extends Thread { @@ -90,11 +89,11 @@ index ddef523ea8762c927f37f7d16d581e43367e8c6b..70f8d42992aa348ef7b2d03d22cdd59d try { org.spigotmc.AsyncCatcher.enabled = false; // Spigot + org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper - server.close(); + this.server.close(); } finally { try { diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java -index aeed7697254af17ffefe8e578353ad216e15f9f3..9f7d2ef932ab41cef5d3d0736d20a7c7e4a2c888 100644 +index bbf0d9d9c44fe8d7add2f978994ec129420814c7..7a23b56752f6733ee626a8b1e4c3b78591855c4e 100644 --- a/src/main/java/org/spigotmc/AsyncCatcher.java +++ b/src/main/java/org/spigotmc/AsyncCatcher.java @@ -6,6 +6,7 @@ public class AsyncCatcher @@ -106,7 +105,7 @@ index aeed7697254af17ffefe8e578353ad216e15f9f3..9f7d2ef932ab41cef5d3d0736d20a7c7 public static void catchOp(String reason) { diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index a4223094802a7e996cc57c617df92d23bc48f5b5..04ae5fec376af006ec828d1ae568338af5cfe6ce 100644 +index 882e93ad4471e3688f2fcfb1e6f16926786ee5e7..94d8ba376cd1f024b244654cac9bb62bb19e3060 100644 --- a/src/main/java/org/spigotmc/RestartCommand.java +++ b/src/main/java/org/spigotmc/RestartCommand.java @@ -43,6 +43,7 @@ public class RestartCommand extends Command diff --git a/patches/server-remapped/0048-All-chunks-are-slime-spawn-chunks-toggle.patch b/patches/server/0044-All-chunks-are-slime-spawn-chunks-toggle.patch similarity index 74% rename from patches/server-remapped/0048-All-chunks-are-slime-spawn-chunks-toggle.patch rename to patches/server/0044-All-chunks-are-slime-spawn-chunks-toggle.patch index cee1933ce4..8fa3c30ec9 100644 --- a/patches/server-remapped/0048-All-chunks-are-slime-spawn-chunks-toggle.patch +++ b/patches/server/0044-All-chunks-are-slime-spawn-chunks-toggle.patch @@ -19,15 +19,15 @@ index 70e074cdf2087e638af8e0f3878d0ef8eb7305cc..416a6760883cb40367535c7c5acd7797 + } } diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java -index 8ff8c19f0b258623b9f0a3cfd0ad5595a92f5899..fc8f26e988f1e4826dcfdcf071293bb356163e62 100644 +index 0b0fb2331b126b6c0c7c3b2af81f3f9d2ad1f081..53130b34e5964acec191e1d8de6bde996f498699 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Slime.java +++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java -@@ -323,7 +323,7 @@ public class Slime extends Mob implements Enemy { +@@ -322,7 +322,7 @@ public class Slime extends Mob implements Enemy { } ChunkPos chunkcoordintpair = new ChunkPos(pos); -- boolean flag = WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getLevel().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot -+ boolean flag = world.getLevel().paperConfig.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getLevel().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper +- boolean flag = WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot ++ boolean flag = world.getMinecraftWorld().paperConfig.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper if (random.nextInt(10) == 0 && flag && pos.getY() < 40) { return checkMobSpawnRules(type, world, spawnReason, pos, random); diff --git a/patches/server-remapped/0049-Expose-server-CommandMap.patch b/patches/server/0045-Expose-server-CommandMap.patch similarity index 70% rename from patches/server-remapped/0049-Expose-server-CommandMap.patch rename to patches/server/0045-Expose-server-CommandMap.patch index c633af2298..8ae6b6d418 100644 --- a/patches/server-remapped/0049-Expose-server-CommandMap.patch +++ b/patches/server/0045-Expose-server-CommandMap.patch @@ -5,14 +5,14 @@ Subject: [PATCH] Expose server CommandMap diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 783da25e189c0264ebf31e244677a6b653ff7b26..95d32f37db663a37f8fde927bdf9d3d4802ba1b4 100644 +index 70ba011fda5bba9ee30061825b8a0db82be288b1..38e07f62b1e4d7b1e7e0acde17f168345a820c21 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1760,6 +1760,7 @@ public final class CraftServer implements Server { - return helpMap; +@@ -1762,6 +1762,7 @@ public final class CraftServer implements Server { + return this.helpMap; } + @Override // Paper - add override public SimpleCommandMap getCommandMap() { - return commandMap; + return this.commandMap; } diff --git a/patches/server-remapped/0050-Be-a-bit-more-informative-in-maxHealth-exception.patch b/patches/server/0046-Be-a-bit-more-informative-in-maxHealth-exception.patch similarity index 65% rename from patches/server-remapped/0050-Be-a-bit-more-informative-in-maxHealth-exception.patch rename to patches/server/0046-Be-a-bit-more-informative-in-maxHealth-exception.patch index b47fa12664..062eb4de43 100644 --- a/patches/server-remapped/0050-Be-a-bit-more-informative-in-maxHealth-exception.patch +++ b/patches/server/0046-Be-a-bit-more-informative-in-maxHealth-exception.patch @@ -5,18 +5,18 @@ Subject: [PATCH] Be a bit more informative in maxHealth exception diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index d8bfb0953f0b23c64f4e27fc84a6c5f3eb0cc8b8..3afdcb3013263a7e06876821d7d889fa48404041 100644 +index 4d125e6830684930d78afb99f4865347b8b3e011..b2a91fdff5960975787d4cd8f340f631275290fe 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -99,7 +99,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { public void setHealth(double health) { health = (float) health; - if ((health < 0) || (health > getMaxHealth())) { -- throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + "(" + health + ")"); + if ((health < 0) || (health > this.getMaxHealth())) { +- throw new IllegalArgumentException("Health must be between 0 and " + this.getMaxHealth() + "(" + health + ")"); + // Paper - Be more informative + throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + ", but was " + health -+ + ". (attribute base value: " + this.getHandle().getAttribute(Attributes.MAX_HEALTH).getBaseValue() -+ + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); ++ + ". (attribute base value: " + this.getHandle().getAttribute(Attributes.MAX_HEALTH).getBaseValue() ++ + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); } - getHandle().setHealth((float) health); + this.getHandle().setHealth((float) health); diff --git a/patches/server-remapped/0051-Player-Tab-List-and-Title-APIs.patch b/patches/server/0047-Player-Tab-List-and-Title-APIs.patch similarity index 74% rename from patches/server-remapped/0051-Player-Tab-List-and-Title-APIs.patch rename to patches/server/0047-Player-Tab-List-and-Title-APIs.patch index c26e87ac6e..2e8c67a029 100644 --- a/patches/server-remapped/0051-Player-Tab-List-and-Title-APIs.patch +++ b/patches/server/0047-Player-Tab-List-and-Title-APIs.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Player Tab List and Title APIs diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -index 59788eaef0dae5ee01ceba1bf45e85cb07f88e53..b4542ce6a8c37ab31e6ecaeb4cbad4742cca0f9b 100644 +index c15860c77c7c24b1946c22f140f1b5c12b052ade..c0966a873ea5e265936e17796bf6bbee62eea9b4 100644 --- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java +++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -@@ -170,6 +170,11 @@ public class FriendlyByteBuf extends ByteBuf { +@@ -333,6 +333,11 @@ public class FriendlyByteBuf extends ByteBuf { public FriendlyByteBuf writeComponent(final net.kyori.adventure.text.Component component) { return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); } @@ -21,10 +21,10 @@ index 59788eaef0dae5ee01ceba1bf45e85cb07f88e53..b4542ce6a8c37ab31e6ecaeb4cbad474 public FriendlyByteBuf writeComponent(Component text) { diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java -index 54d186a195aca6d0a4c412ed609d8c86dcc76072..06e9246f05e130be6a63ebb0c9def10c6c9675b7 100644 +index 02d19fa4abdee0c8331734932a83e64694356030..969aea457e76b853e34a67a8fd07e0ea3207005b 100644 --- a/src/main/java/net/minecraft/network/chat/Component.java +++ b/src/main/java/net/minecraft/network/chat/Component.java -@@ -363,6 +363,7 @@ public interface Component extends Message, FormattedText, Iterable { +@@ -428,6 +428,7 @@ public interface Component extends Message, FormattedText, Iterable { return Component.Serializer.GSON.toJsonTree(text); } @@ -32,39 +32,8 @@ index 54d186a195aca6d0a4c412ed609d8c86dcc76072..06e9246f05e130be6a63ebb0c9def10c @Nullable public static MutableComponent fromJson(String json) { return (MutableComponent) GsonHelper.fromJson(Component.Serializer.GSON, json, MutableComponent.class, false); -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -index 69ff8df7340e60c476803256750a48f0b43414d3..df444daeb181ff78170f7b92bd02f1f1862dfa2e 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -@@ -47,6 +47,17 @@ public class ClientboundSetTitlesPacket implements Packet +Date: Thu, 3 Mar 2016 02:33:53 -0600 +Subject: [PATCH] Ensure inv drag is in bounds + + +diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index eaf2c55328e5dd6b7b55b5701501e4441923f060..0d832c4f0c62f56b9208720afcdcc02044662c90 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -374,7 +374,7 @@ public abstract class AbstractContainerMenu { + this.resetQuickCraft(); + } + } else if (this.quickcraftStatus == 1) { +- slot = (Slot) this.slots.get(slotIndex); ++ slot = slotIndex < this.slots.size() ? this.slots.get(slotIndex) : null; // Paper - Ensure drag in bounds + itemstack = this.getCarried(); + if (AbstractContainerMenu.canItemQuickReplace(slot, itemstack, true) && slot.mayPlace(itemstack) && (this.quickcraftType == 2 || itemstack.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) { + this.quickcraftSlots.add(slot); diff --git a/patches/server-remapped/0054-Add-configurable-portal-search-radius.patch b/patches/server/0049-Add-configurable-portal-search-radius.patch similarity index 71% rename from patches/server-remapped/0054-Add-configurable-portal-search-radius.patch rename to patches/server/0049-Add-configurable-portal-search-radius.patch index 8bbb23e407..4766d2cce8 100644 --- a/patches/server-remapped/0054-Add-configurable-portal-search-radius.patch +++ b/patches/server/0049-Add-configurable-portal-search-radius.patch @@ -23,34 +23,34 @@ index 416a6760883cb40367535c7c5acd779742bb8af5..670efbe53241a0ae32d618c83da601cc + } } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 72eb40f748c33572c2828f48ebd1ca7d5d5712c8..a6f2e671cc9b2ef086dfa3d127a7b33272acbd56 100644 +index cb65a20d34196866eead7844b93c65bfb853f74c..daac0e45a1c5307489831638f54472eaee4b2282 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2617,7 +2617,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2875,7 +2875,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n double d4 = DimensionType.getTeleportationScale(this.level.dimensionType(), destination.dimensionType()); BlockPos blockposition = new BlockPos(Mth.clamp(this.getX() * d4, d0, d2), this.getY(), Mth.clamp(this.getZ() * d4, d1, d3)); // CraftBukkit start -- CraftPortalEvent event = callPortalEvent(this, destination, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); +- CraftPortalEvent event = this.callPortalEvent(this, destination, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); + // Paper start + int portalSearchRadius = destination.paperConfig.portalSearchRadius; + if (level.paperConfig.portalSearchVanillaDimensionScaling && flag2) { // == THE_NETHER + portalSearchRadius = (int) (portalSearchRadius / destination.dimensionType().coordinateScale()); + } + // Paper end -+ CraftPortalEvent event = callPortalEvent(this, destination, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, portalSearchRadius, destination.paperConfig.portalCreateRadius); // Paper start - configurable portal radius ++ CraftPortalEvent event = this.callPortalEvent(this, destination, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, portalSearchRadius, destination.paperConfig.portalCreateRadius); // Paper start - configurable portal radius if (event == null) { return null; } diff --git a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java -index 948d031627435bfce442b1fe7d3eff4addc85bc4..21c01302635d23bc21e6bb373cbe277ea1eb6a56 100644 +index 4d186a7d6ccf09092c5e1577e4b49e0975787980..d5ba2e679ed1858ea18e18feffce50544ae036c2 100644 --- a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java +++ b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java -@@ -30,7 +30,7 @@ public class PortalForcer { +@@ -44,7 +44,7 @@ public class PortalForcer { - public Optional findPortalAround(BlockPos blockposition, boolean flag) { + public Optional findPortalAround(BlockPos destPos, boolean destIsNether) { // CraftBukkit start -- return findPortalAround(blockposition, flag ? 16 : 128); // Search Radius -+ return findPortalAround(blockposition, flag ? level.paperConfig.portalCreateRadius : level.paperConfig.portalSearchRadius); // Paper - search Radius +- return this.findPortal(destPos, destIsNether ? 16 : 128); // Search Radius ++ return this.findPortal(destPos, destIsNether ? level.paperConfig.portalCreateRadius : level.paperConfig.portalSearchRadius); // Search Radius // Paper - search Radius } public Optional findPortal(BlockPos blockposition, int i) { diff --git a/patches/server-remapped/0055-Add-velocity-warnings.patch b/patches/server/0050-Add-velocity-warnings.patch similarity index 85% rename from patches/server-remapped/0055-Add-velocity-warnings.patch rename to patches/server/0050-Add-velocity-warnings.patch index 3a11078735..1db441c45c 100644 --- a/patches/server-remapped/0055-Add-velocity-warnings.patch +++ b/patches/server/0050-Add-velocity-warnings.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add velocity warnings diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 95d32f37db663a37f8fde927bdf9d3d4802ba1b4..35d3df7ded4904414a9a61895950b56be530d244 100644 +index 38e07f62b1e4d7b1e7e0acde17f168345a820c21..2d84d6a18ef93f591d7eb3ef1bf80e88a1a096f5 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -260,6 +260,7 @@ public final class CraftServer implements Server { +@@ -263,6 +263,7 @@ public final class CraftServer implements Server { public boolean ignoreVanillaPermissions = false; private final List playerView; public int reloadCount; @@ -17,10 +17,10 @@ index 95d32f37db663a37f8fde927bdf9d3d4802ba1b4..35d3df7ded4904414a9a61895950b56b static { ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index e7a59a8e0424a0839dfa73fc65f44c5b04bd3dec..b028946de7c8f52091635fe154c816453f1ddc93 100644 +index bac39ee51f36ad86d6a4978306b6612d9376adbf..271b4e3354c3885e38ae0c547edba48bf06f1e19 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -424,10 +424,41 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -431,10 +431,40 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { public void setVelocity(Vector velocity) { Preconditions.checkArgument(velocity != null, "velocity"); velocity.checkFinite(); @@ -29,8 +29,7 @@ index e7a59a8e0424a0839dfa73fc65f44c5b04bd3dec..b028946de7c8f52091635fe154c81645 + CraftServer.excessiveVelEx = new Exception("Excessive velocity set detected: tried to set velocity of entity " + entity.getScoreboardName() + " id #" + getEntityId() + " to (" + velocity.getX() + "," + velocity.getY() + "," + velocity.getZ() + ")."); + } + // Paper end -+ - entity.setDeltaMovement(CraftVector.toNMS(velocity)); + this.entity.setDeltaMovement(CraftVector.toNMS(velocity)); entity.hurtMarked = true; } @@ -61,9 +60,9 @@ index e7a59a8e0424a0839dfa73fc65f44c5b04bd3dec..b028946de7c8f52091635fe154c81645 + @Override public double getHeight() { - return getHandle().getBbHeight(); + return this.getHandle().getBbHeight(); diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 21d7b483920841456707fe3f08b180c1f072b7f7..0ed95268364ea7f6a92a39b726a1e03bc815be07 100644 +index d5863b0b06384b25eaa33572fa02649795463ed8..2693cc933d746e40d8a47d96c6cb6799f0a2472f 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java @@ -80,7 +80,19 @@ public class WatchdogThread extends Thread @@ -86,4 +85,4 @@ index 21d7b483920841456707fe3f08b180c1f072b7f7..0ed95268364ea7f6a92a39b726a1e03b + // Paper end log.log( Level.SEVERE, "------------------------------" ); log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); diff --git a/patches/server-remapped/0056-Configurable-inter-world-teleportation-safety.patch b/patches/server/0051-Configurable-inter-world-teleportation-safety.patch similarity index 93% rename from patches/server-remapped/0056-Configurable-inter-world-teleportation-safety.patch rename to patches/server/0051-Configurable-inter-world-teleportation-safety.patch index c0826d9b39..0e975fba21 100644 --- a/patches/server-remapped/0056-Configurable-inter-world-teleportation-safety.patch +++ b/patches/server/0051-Configurable-inter-world-teleportation-safety.patch @@ -30,10 +30,10 @@ index 670efbe53241a0ae32d618c83da601ccc1f26e37..abbbe1786eb68af02f9d39650aad730a + } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 63933bd455ad72a772d4db160e946600b84a1791..3b9d61b524441f65646edf7d403b6c5b5345b1e5 100644 +index 6401bdeeaa42ffe1e415553c94f0ec597b85df0c..d7c3bb17faf667ec90c967fe3c5ea6094faf0226 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -861,7 +861,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -862,7 +862,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (fromWorld == toWorld) { entity.connection.teleport(to); } else { diff --git a/patches/server-remapped/0057-Add-exception-reporting-event.patch b/patches/server/0052-Add-exception-reporting-event.patch similarity index 72% rename from patches/server-remapped/0057-Add-exception-reporting-event.patch rename to patches/server/0052-Add-exception-reporting-event.patch index 7b87e0d39f..34c4746f16 100644 --- a/patches/server-remapped/0057-Add-exception-reporting-event.patch +++ b/patches/server/0052-Add-exception-reporting-event.patch @@ -49,10 +49,10 @@ index 0000000000000000000000000000000000000000..f699ce18ca044f813e194ef2786b7ea8 + } +} diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index d1bc927c8b429f43de2cdad98f8b329ff4c8b4db..0597c0c3e881dd43cf91bd3088ed30dfecfe8098 100644 +index 39cfa8211f02acaa0851e0cfc1c2890475d609f4..da97afe93a98daac33f143c6da0b42f71db25dba 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -813,6 +813,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -825,6 +825,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return true; } catch (Exception exception) { ChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception); @@ -61,7 +61,7 @@ index d1bc927c8b429f43de2cdad98f8b329ff4c8b4db..0597c0c3e881dd43cf91bd3088ed30df } } diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java -index c167d2fd99a7a352e69e2930551678bd9c9def83..09c5fa2dbcbed05da51ef2d63e6d6112d22d7877 100644 +index 60a6d35e8467545e211aa1756cd1494f440f1d78..da515ac94aa3c294855f28e6deb9094cc7187dd9 100644 --- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java +++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java @@ -1,5 +1,6 @@ @@ -71,7 +71,7 @@ index c167d2fd99a7a352e69e2930551678bd9c9def83..09c5fa2dbcbed05da51ef2d63e6d6112 import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.io.Files; -@@ -360,6 +361,7 @@ public class OldUsersConverter { +@@ -362,6 +363,7 @@ public class OldUsersConverter { root = NbtIo.readCompressed(new java.io.FileInputStream(file5)); } catch (Exception exception) { exception.printStackTrace(); @@ -79,7 +79,7 @@ index c167d2fd99a7a352e69e2930551678bd9c9def83..09c5fa2dbcbed05da51ef2d63e6d6112 } if (root != null) { -@@ -373,6 +375,7 @@ public class OldUsersConverter { +@@ -375,6 +377,7 @@ public class OldUsersConverter { NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2)); } catch (Exception exception) { exception.printStackTrace(); @@ -88,7 +88,7 @@ index c167d2fd99a7a352e69e2930551678bd9c9def83..09c5fa2dbcbed05da51ef2d63e6d6112 } // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -index 78cea15142f9fd7988f5df397061b90625070eef..f50774f022c78813982bfe08f764b54bde779e04 100644 +index 08c5f6fd1a307c89cf8365f56314a0c6d3e89e4b..26e0f03f2e736ed6ba86e2510a7962deee180ef3 100644 --- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java +++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java @@ -1,5 +1,7 @@ @@ -108,7 +108,7 @@ index 78cea15142f9fd7988f5df397061b90625070eef..f50774f022c78813982bfe08f764b54b } diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 7b4475807cca0e92ea9ae6ea49a82a8634cc0ff5..94e268a05b4601c29b6d2845f0fc2311643a161f 100644 +index 56362678e8de38c541fc851abf783f385a7903bf..a6b1572a82fd22eea5b3d4124c510d94fea5917d 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -1,5 +1,10 @@ @@ -122,20 +122,7 @@ index 7b4475807cca0e92ea9ae6ea49a82a8634cc0ff5..94e268a05b4601c29b6d2845f0fc2311 import com.google.common.collect.Lists; import com.mojang.serialization.Codec; import java.io.IOException; -@@ -737,8 +742,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - gameprofilerfiller.pop(); - } catch (Throwable throwable) { - // Paper start - Prevent tile entity and entity crashes -- System.err.println("TileEntity threw exception at " + tileentity.level.getWorld().getName() + ":" + tileentity.worldPosition.getX() + "," + tileentity.worldPosition.getY() + "," + tileentity.worldPosition.getZ()); -+ String msg = "TileEntity threw exception at " + tileentity.getLevel().getWorld().getName() + ":" + tileentity.getBlockPos().getX() + "," + tileentity.getBlockPos().getY() + "," + tileentity.getBlockPos().getZ(); -+ System.err.println(msg); - throwable.printStackTrace(); -+ getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); -+ // Paper end - tilesThisCycle--; - this.tickableBlockEntities.remove(tileTickPosition--); - continue; -@@ -808,8 +816,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -730,8 +735,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { tickConsumer.accept(entity); } catch (Throwable throwable) { // Paper start - Prevent tile entity and entity crashes @@ -144,14 +131,14 @@ index 7b4475807cca0e92ea9ae6ea49a82a8634cc0ff5..94e268a05b4601c29b6d2845f0fc2311 + System.err.println(msg); throwable.printStackTrace(); + getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); - entity.removed = true; - return; + entity.discard(); // Paper end + } diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index fc134b916e95231af8478a4f97bf11a0f37f7f0b..a19ac1cb7e4d8d478648a048b2bfa0daf85a80c9 100644 +index b4a7776ba9486bbca42ffb596c8a8bcdf6471ce3..59fae60116167baf989e85596334824e9004e6fb 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -299,6 +299,7 @@ public final class NaturalSpawner { +@@ -308,6 +308,7 @@ public final class NaturalSpawner { } } catch (Exception exception) { NaturalSpawner.LOGGER.warn("Failed to create mob", exception); @@ -159,50 +146,63 @@ index fc134b916e95231af8478a4f97bf11a0f37f7f0b..a19ac1cb7e4d8d478648a048b2bfa0da return null; } } -@@ -405,6 +406,7 @@ public final class NaturalSpawner { - entity = biomesettingsmobs_c.type.create((Level) worldaccess.getLevel()); - } catch (Exception exception) { - NaturalSpawner.LOGGER.warn("Failed to create mob", exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - continue; - } +@@ -410,6 +411,7 @@ public final class NaturalSpawner { + entity = biomesettingsmobs_c.type.create((Level) world.getLevel()); + } catch (Exception exception) { + NaturalSpawner.LOGGER.warn("Failed to create mob", exception); ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper + continue; + } diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 300749822d52f9f973e71c6ec9c8bf29d6a6938e..9ca05aa06696883adc8b67a68ca6d2d850e95d25 100644 +index a6e8a8de17acc6c7c0bdeea01544a334797b69b6..9939c4c39549771afe971a6433dfd57e36050dd8 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -1,5 +1,6 @@ +@@ -1,6 +1,7 @@ package net.minecraft.world.level.chunk; + import com.google.common.collect.ImmutableList; +import com.destroystokyo.paper.exception.ServerInternalException; import com.google.common.collect.Maps; import com.google.common.collect.Sets; - import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -@@ -654,10 +655,15 @@ public class LevelChunk implements ChunkAccess { - this.blockEntities.remove(pos); + import com.google.common.collect.UnmodifiableIterator; +@@ -615,10 +616,15 @@ public class LevelChunk implements ChunkAccess { + this.blockEntities.remove(blockposition); // Paper end } else { - System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() -- + " (" + getBlockState(pos) + ") where there was no entity tile!"); +- + " (" + this.getBlockState(blockposition) + ") where there was no entity tile!"); - System.out.println("Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); - new Exception().printStackTrace(); + // Paper start + ServerInternalException e = new ServerInternalException( -+ "Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," -+ + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() -+ + " (" + getBlockState(pos) + ") where there was no entity tile!\n" + -+ "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); ++ "Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," ++ + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() ++ + " (" + getBlockState(blockposition) + ") where there was no entity tile!\n" + ++ "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); + e.printStackTrace(); + ServerInternalException.reportInternalException(e); + // Paper end // CraftBukkit end } } +@@ -1242,8 +1248,10 @@ public class LevelChunk implements ChunkAccess { + gameprofilerfiller.pop(); + } catch (Throwable throwable) { + // Paper start - Prevent tile entity and entity crashes +- System.err.println("TileEntity threw exception at " + LevelChunk.this.getLevel().getWorld().getName() + ":" + this.getPos().getX() + "," + this.getPos().getY() + "," + this.getPos().getZ()); ++ String msg = "TileEntity threw exception at " + LevelChunk.this.getLevel().getWorld().getName() + ":" + this.getPos().getX() + "," + this.getPos().getY() + "," + this.getPos().getZ(); ++ System.err.println(msg); + throwable.printStackTrace(); ++ net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new ServerInternalException(msg, throwable))); + LevelChunk.this.removeBlockEntity(this.getPos()); + // Paper end + // Spigot start diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 60f410a4f838048bbfd2cde52caa7c4c9434b0ba..1598da3449ee1c559cf503e1b20a0daaf6a033dd 100644 +index 2da42f1bc6922adae32d782aac780a7e0e94e352..659305865e9c6d9996fcf2596d086050508059cd 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -265,6 +265,7 @@ public class RegionFile implements AutoCloseable { +@@ -278,6 +278,7 @@ public class RegionFile implements AutoCloseable { return true; } } catch (IOException ioexception) { @@ -210,28 +210,28 @@ index 60f410a4f838048bbfd2cde52caa7c4c9434b0ba..1598da3449ee1c559cf503e1b20a0daa return false; } } -@@ -337,6 +338,7 @@ public class RegionFile implements AutoCloseable { +@@ -359,6 +360,7 @@ public class RegionFile implements AutoCloseable { + ((java.nio.Buffer) bytebuffer).position(5); // CraftBukkit - decompile error filechannel.write(bytebuffer); - } catch (Throwable throwable1) { - throwable = throwable1; + } catch (Throwable throwable) { + com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper - throw throwable1; - } finally { if (filechannel != null) { + try { + filechannel.close(); diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -index 60b7fdf9c092e8105d41f4af02a08651624f3eb9..99cfd693ea705d45a5eab181cb80c354a2d1159f 100644 +index 2fdb313e8eaed868c36f68c9b7f6a6f9f4864575..c8ed0673ff819cb88d0ee6f53f2a2b9b46b203d4 100644 --- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -@@ -150,6 +150,7 @@ public class DimensionDataStorage { - } - } catch (Throwable throwable6) { - throwable = throwable6; -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper - throw throwable6; - } finally { - if (fileinputstream != null) { +@@ -120,6 +120,7 @@ public class DimensionDataStorage { + + pushbackInputStream.close(); + } catch (Throwable var15) { ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(var15); // Paper + try { + fileInputStream.close(); + } catch (Throwable var10) { diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index ffe9cc1011226d604dc5499e7692e9a9a5132b72..9b6d9373abb59a30c2835ca891282d07559281f5 100644 +index e6a09ed5db245eaecd787503dbfb1ef5fea5bb70..0735c2fe139ce8d47a04fdba045fe462492723eb 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java @@ -16,6 +16,9 @@ import java.util.concurrent.atomic.AtomicInteger; @@ -252,13 +252,13 @@ index ffe9cc1011226d604dc5499e7692e9a9a5132b72..9b6d9373abb59a30c2835ca891282d07 + new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task))); // Paper end } finally { - currentTask = null; + this.currentTask = null; @@ -426,7 +431,7 @@ public class CraftScheduler implements BukkitScheduler { - parsePending(); + this.parsePending(); } else { - debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); -- executor.execute(task); -+ executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper + this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); +- this.executor.execute(task); ++ this.executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper // We don't need to parse pending // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) } diff --git a/patches/server-remapped/0058-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/patches/server/0053-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch similarity index 58% rename from patches/server-remapped/0058-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch rename to patches/server/0053-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch index f1642d7a3b..0fbaf13f1e 100644 --- a/patches/server-remapped/0058-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch +++ b/patches/server/0053-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch @@ -6,20 +6,20 @@ Subject: [PATCH] Don't nest if we don't need to when cerealising text diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -index e47102cadb40ed8a9c011386445f15fd30de7596..f13da9e7d014bc00fbabf0a495b548bba2f59468 100644 +index 1f5050e6c1d932aa196ab9524f7f1f9bd1b45fce..a64780b4b49d01322d8f755ff540a9622c89e983 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -@@ -40,7 +40,14 @@ public class ClientboundChatPacket implements Packet { +@@ -36,7 +36,14 @@ public class ClientboundChatPacket implements Packet { // Paper end // Spigot start - if (components != null) { -- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(components)); -+ //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below + if (this.components != null) { +- buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(components)); ++ // buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below + // Paper start - don't nest if we don't need to so that we can preserve formatting + if (this.components.length == 1) { -+ buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); ++ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); + } else { -+ buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); ++ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); + } + // Paper end } else { diff --git a/patches/server-remapped/0059-Disable-Scoreboards-for-non-players-by-default.patch b/patches/server/0054-Disable-Scoreboards-for-non-players-by-default.patch similarity index 80% rename from patches/server-remapped/0059-Disable-Scoreboards-for-non-players-by-default.patch rename to patches/server/0054-Disable-Scoreboards-for-non-players-by-default.patch index d1cae6e603..d5c90826d9 100644 --- a/patches/server-remapped/0059-Disable-Scoreboards-for-non-players-by-default.patch +++ b/patches/server/0054-Disable-Scoreboards-for-non-players-by-default.patch @@ -25,25 +25,25 @@ index abbbe1786eb68af02f9d39650aad730ac44aac8a..3ac2ac3db9b1c271b3c21930bb137166 + } } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a6f2e671cc9b2ef086dfa3d127a7b33272acbd56..93d3408231a177cf6d2086594756adffe3efa702 100644 +index daac0e45a1c5307489831638f54472eaee4b2282..e9e87dc8c80d83dc7c472b0611077d8f9f4e5fcf 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2288,6 +2288,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2524,6 +2524,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @Nullable public Team getTeam() { + if (!this.level.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof Player)) { return null; } // Paper - return this.level.getScoreboard().getPlayerTeam(this.getScoreboardName()); + return this.level.getScoreboard().getPlayersTeam(this.getScoreboardName()); } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index afd114e1ce00db72534d470fed12101bb237f266..d483d552092c901fec262c43e488784d9cd8acb9 100644 +index cc8fb033ca8241acb984e3440a44c7a083e2f3f6..46e514bfe80d999f50173866b59fbc9419bbf3d0 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -738,6 +738,7 @@ public abstract class LivingEntity extends Entity { - if (tag.contains("Team", 8)) { - String s = tag.getString("Team"); - PlayerTeam scoreboardteam = this.level.getScoreboard().getTeam(s); +@@ -803,6 +803,7 @@ public abstract class LivingEntity extends Entity { + if (nbt.contains("Team", 8)) { + String s = nbt.getString("Team"); + PlayerTeam scoreboardteam = this.level.getScoreboard().getPlayerTeam(s); + if (!level.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof net.minecraft.world.entity.player.Player)) { scoreboardteam = null; } // Paper boolean flag = scoreboardteam != null && this.level.getScoreboard().addPlayerToTeam(this.getStringUUID(), scoreboardteam); diff --git a/patches/server-remapped/0060-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/server/0055-Add-methods-for-working-with-arrows-stuck-in-living-.patch similarity index 74% rename from patches/server-remapped/0060-Add-methods-for-working-with-arrows-stuck-in-living-.patch rename to patches/server/0055-Add-methods-for-working-with-arrows-stuck-in-living-.patch index e0d5759239..2c5f3c5b06 100644 --- a/patches/server-remapped/0060-Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ b/patches/server/0055-Add-methods-for-working-with-arrows-stuck-in-living-.patch @@ -5,12 +5,12 @@ Subject: [PATCH] Add methods for working with arrows stuck in living entities diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 3afdcb3013263a7e06876821d7d889fa48404041..d8cd88d62f9abfc7960c187dd74239f61267ca57 100644 +index b2a91fdff5960975787d4cd8f340f631275290fe..ea94dc9a3b8bd3da5f8ccbeb216384723db668aa 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -677,4 +677,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - getHandle().persistentInvisibility = invisible; - getHandle().setSharedFlag(5, invisible); +@@ -685,4 +685,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + this.getHandle().persistentInvisibility = invisible; + this.getHandle().setSharedFlag(5, invisible); } + + // Paper start diff --git a/patches/server-remapped/0061-Complete-resource-pack-API.patch b/patches/server/0056-Complete-resource-pack-API.patch similarity index 68% rename from patches/server-remapped/0061-Complete-resource-pack-API.patch rename to patches/server/0056-Complete-resource-pack-API.patch index 6be95196f1..d2e790a554 100644 --- a/patches/server-remapped/0061-Complete-resource-pack-API.patch +++ b/patches/server/0056-Complete-resource-pack-API.patch @@ -5,27 +5,28 @@ Subject: [PATCH] Complete resource pack API diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 00689dc07625a02781052c5df2e466e8abe85708..73683ba59d0aff3a61f555b4ae15753e9e4e6141 100644 +index b38ca69d37d7f1af0e34297f45e63a98da754e35..714fb0d766b654ad05134dea9b1e1b628a939993 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1603,7 +1603,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // CraftBukkit start - public void handleResourcePackResponse(ServerboundResourcePackPacket packet) { - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); -- this.craftServer.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()])); +@@ -1640,8 +1640,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + ServerGamePacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack rejection", this.player.getName()); + this.disconnect(new TranslatableComponent("multiplayer.requiredTexturePrompt.disconnect")); + } +- this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(this.getCraftPlayer(), PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()])); // CraftBukkit +- + // Paper start + PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()]; + player.getBukkitEntity().setResourcePackStatus(packStatus); -+ this.craftServer.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), packStatus)); ++ this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(this.getCraftPlayer(), packStatus)); // CraftBukkit + // Paper end } - // CraftBukkit end + @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 3b9d61b524441f65646edf7d403b6c5b5345b1e5..dd29038778d73fae84df360515f3c670915f1d48 100644 +index d7c3bb17faf667ec90c967fe3c5ea6094faf0226..074b9e2aa9162aec64007cbf235ccc965db70055 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -136,6 +136,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -141,6 +141,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { private double health = 20; private boolean scaledHealth = false; private double healthScale = 20; @@ -36,7 +37,7 @@ index 3b9d61b524441f65646edf7d403b6c5b5345b1e5..dd29038778d73fae84df360515f3c670 public CraftPlayer(CraftServer server, ServerPlayer entity) { super(server, entity); -@@ -1872,6 +1876,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1873,6 +1877,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public boolean getAffectsSpawning() { return this.getHandle().affectsSpawning; } @@ -45,7 +46,7 @@ index 3b9d61b524441f65646edf7d403b6c5b5345b1e5..dd29038778d73fae84df360515f3c670 + public void setResourcePack(String url, String hash) { + Validate.notNull(url, "Resource pack URL cannot be null"); + Validate.notNull(hash, "Hash cannot be null"); -+ this.getHandle().sendTexturePack(url, hash); ++ this.getHandle().sendTexturePack(url, hash, false, new net.minecraft.network.chat.TextComponent("")); + } + + @Override diff --git a/patches/server-remapped/0062-Chunk-Save-Reattempt.patch b/patches/server/0057-Chunk-Save-Reattempt.patch similarity index 79% rename from patches/server-remapped/0062-Chunk-Save-Reattempt.patch rename to patches/server/0057-Chunk-Save-Reattempt.patch index db35b14461..fc84b1d660 100644 --- a/patches/server-remapped/0062-Chunk-Save-Reattempt.patch +++ b/patches/server/0057-Chunk-Save-Reattempt.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Chunk Save Reattempt We commonly have "Stream Closed" errors on chunk saving, so this code should re-try to save the chunk in the event of failure and hopefully prevent rollbacks. diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 1598da3449ee1c559cf503e1b20a0daaf6a033dd..1aa4d342b97f8be71c108194a6f1e0e2828aa364 100644 +index 659305865e9c6d9996fcf2596d086050508059cd..1a35ef48c487c92f55fcbbfc19a708ededc6a32d 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -265,7 +265,7 @@ public class RegionFile implements AutoCloseable { +@@ -278,7 +278,7 @@ public class RegionFile implements AutoCloseable { return true; } } catch (IOException ioexception) { @@ -19,7 +19,7 @@ index 1598da3449ee1c559cf503e1b20a0daaf6a033dd..1aa4d342b97f8be71c108194a6f1e0e2 } } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 1e49d17b54704e1b99c3ded458c4bc6842bd32bd..97a58da9d64d812942ceb71426d35b490bbbe817 100644 +index 7aa1f693c5f44a265ccb442c2c9e995cc3e7418d..1ed8232493c94bc0cf28ef8d4b647cb84bd3fe32 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java @@ -11,6 +11,7 @@ import java.io.IOException; @@ -30,16 +30,16 @@ index 1e49d17b54704e1b99c3ded458c4bc6842bd32bd..97a58da9d64d812942ceb71426d35b49 import net.minecraft.util.ExceptionCollector; import net.minecraft.world.level.ChunkPos; -@@ -92,6 +93,7 @@ public final class RegionFileStorage implements AutoCloseable { +@@ -101,6 +102,7 @@ public final class RegionFileStorage implements AutoCloseable { - protected void write(ChunkPos pos, CompoundTag tag) throws IOException { + protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException { RegionFile regionfile = this.getFile(pos, false); // CraftBukkit + int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper - DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(pos); - Throwable throwable = null; - -@@ -115,6 +117,18 @@ public final class RegionFileStorage implements AutoCloseable { + if (nbt == null) { + regionfile.clear(pos); +@@ -126,6 +128,18 @@ public final class RegionFileStorage implements AutoCloseable { + } } + // Paper start diff --git a/patches/server-remapped/0063-Default-loading-permissions.yml-before-plugins.patch b/patches/server/0058-Default-loading-permissions.yml-before-plugins.patch similarity index 76% rename from patches/server-remapped/0063-Default-loading-permissions.yml-before-plugins.patch rename to patches/server/0058-Default-loading-permissions.yml-before-plugins.patch index 3df2a1e2a2..47863187c1 100644 --- a/patches/server-remapped/0063-Default-loading-permissions.yml-before-plugins.patch +++ b/patches/server/0058-Default-loading-permissions.yml-before-plugins.patch @@ -30,23 +30,23 @@ index 429b74474ced04d8dd8f038b8590b8dfe178bf4d..716f285e67019b8a62922d09c15883c9 + } } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 35d3df7ded4904414a9a61895950b56be530d244..662fc88e2e118a57a6c35a8981d4622188adec3b 100644 +index 2d84d6a18ef93f591d7eb3ef1bf80e88a1a096f5..6bf6183d318e277f0dd2d448edea73d90c42cfd3 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -397,6 +397,7 @@ public final class CraftServer implements Server { - if (type == PluginLoadOrder.STARTUP) { - helpMap.clear(); - helpMap.initializeGeneralTopics(); +@@ -294,6 +294,7 @@ public final class CraftServer implements Server { + + if (!Main.useConsole) { + this.getLogger().info("Console input is disabled due to --noconsole command argument"); + if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper } - Plugin[] plugins = pluginManager.getPlugins(); -@@ -416,7 +417,7 @@ public final class CraftServer implements Server { - commandMap.registerServerAliases(); + this.configuration = YamlConfiguration.loadConfiguration(this.getConfigFile()); +@@ -419,7 +420,7 @@ public final class CraftServer implements Server { + this.commandMap.registerServerAliases(); DefaultPermissions.registerCorePermissions(); CraftDefaultPermissions.registerCorePermissions(); -- loadCustomPermissions(); -+ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper - helpMap.initializeCommands(); - syncCommands(); +- this.loadCustomPermissions(); ++ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) this.loadCustomPermissions(); // Paper + this.helpMap.initializeCommands(); + this.syncCommands(); } diff --git a/patches/server-remapped/0064-Allow-Reloading-of-Custom-Permissions.patch b/patches/server/0059-Allow-Reloading-of-Custom-Permissions.patch similarity index 90% rename from patches/server-remapped/0064-Allow-Reloading-of-Custom-Permissions.patch rename to patches/server/0059-Allow-Reloading-of-Custom-Permissions.patch index e43351be69..46a6866d37 100644 --- a/patches/server-remapped/0064-Allow-Reloading-of-Custom-Permissions.patch +++ b/patches/server/0059-Allow-Reloading-of-Custom-Permissions.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Allow Reloading of Custom Permissions https://github.com/PaperMC/Paper/issues/49 diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 662fc88e2e118a57a6c35a8981d4622188adec3b..50da8e292c131176c263f0bc140ff4f6d890c737 100644 +index 6bf6183d318e277f0dd2d448edea73d90c42cfd3..448e750974f9e15e5222ffa1c2d342c1f0a84a1e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2252,5 +2252,23 @@ public final class CraftServer implements Server { +@@ -2254,5 +2254,23 @@ public final class CraftServer implements Server { } return this.adventure$audiences; } diff --git a/patches/server-remapped/0065-Remove-Metadata-on-reload.patch b/patches/server/0060-Remove-Metadata-on-reload.patch similarity index 77% rename from patches/server-remapped/0065-Remove-Metadata-on-reload.patch rename to patches/server/0060-Remove-Metadata-on-reload.patch index bad86d108d..b19a0304d8 100644 --- a/patches/server-remapped/0065-Remove-Metadata-on-reload.patch +++ b/patches/server/0060-Remove-Metadata-on-reload.patch @@ -7,17 +7,16 @@ Metadata is not meant to persist reload as things break badly with non primitive This will remove metadata on reload so it does not crash everything if a plugin uses it. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 50da8e292c131176c263f0bc140ff4f6d890c737..2828936fe294d9d6750a8838da49ec8398835214 100644 +index 448e750974f9e15e5222ffa1c2d342c1f0a84a1e..95689d11668e37a894b70517270849c2c4e162aa 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -870,8 +870,18 @@ public final class CraftServer implements Server { +@@ -872,8 +872,16 @@ public final class CraftServer implements Server { world.paperConfig.init(); // Paper } + Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper - pluginManager.clearPlugins(); - commandMap.clearCommands(); -+ + this.pluginManager.clearPlugins(); + this.commandMap.clearCommands(); + // Paper start + for (Plugin plugin : pluginClone) { + entityMetadata.removeAll(plugin); @@ -25,7 +24,6 @@ index 50da8e292c131176c263f0bc140ff4f6d890c737..2828936fe294d9d6750a8838da49ec83 + playerMetadata.removeAll(plugin); + } + // Paper end -+ - resetRecipes(); - reloadData(); + this.resetRecipes(); + this.reloadData(); org.spigotmc.SpigotConfig.registerCommands(); // Spigot diff --git a/patches/server-remapped/0066-Handle-Item-Meta-Inconsistencies.patch b/patches/server/0061-Handle-Item-Meta-Inconsistencies.patch similarity index 79% rename from patches/server-remapped/0066-Handle-Item-Meta-Inconsistencies.patch rename to patches/server/0061-Handle-Item-Meta-Inconsistencies.patch index 32698665bc..d7baa47ee7 100644 --- a/patches/server-remapped/0066-Handle-Item-Meta-Inconsistencies.patch +++ b/patches/server/0061-Handle-Item-Meta-Inconsistencies.patch @@ -18,21 +18,21 @@ For consistency, the old API methods now forward to use the ItemMeta API equivalents, and should deprecate the old API's. diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 3faf52e7ac5e7e22d09cfb73cfda6b9f622137d4..123025c6dc9a2eea56c7db5cb508cdfd7c6cc97b 100644 +index ac05b201167d8e17f39d3df732adf676dc24b409..d3267cdef523b62f9985e49b768e6ad22fbe874d 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -9,6 +9,8 @@ import com.mojang.serialization.Codec; - import com.mojang.serialization.codecs.RecordCodecBuilder; - import java.text.DecimalFormat; - import java.text.DecimalFormatSymbols; +@@ -13,6 +13,8 @@ import java.text.DecimalFormatSymbols; + import java.util.Collection; + import java.util.Iterator; + import java.util.List; +import java.util.Collections; +import java.util.Comparator; import java.util.Locale; + import java.util.Map.Entry; import java.util.Objects; - import java.util.Optional; -@@ -118,6 +120,23 @@ public final class ItemStack { - private BlockInWorld cachedPlaceBlock; - private boolean cachedPlaceBlockResult; +@@ -153,6 +155,23 @@ public final class ItemStack { + return this.getItem().getTooltipImage(this); + } + // Paper start + private static final java.util.Comparator enchantSorter = java.util.Comparator.comparing(o -> o.getString("id")); @@ -46,7 +46,7 @@ index 3faf52e7ac5e7e22d09cfb73cfda6b9f622137d4..123025c6dc9a2eea56c7db5cb508cdfd + } + try { + //noinspection unchecked -+ list.sort((Comparator) enchantSorter); // Paper ++ list.sort((Comparator) enchantSorter); // Paper + } catch (Exception ignored) {} + } + // Paper end @@ -54,15 +54,15 @@ index 3faf52e7ac5e7e22d09cfb73cfda6b9f622137d4..123025c6dc9a2eea56c7db5cb508cdfd public ItemStack(ItemLike item) { this(item, 1); } -@@ -160,6 +179,7 @@ public final class ItemStack { - if (nbttagcompound.contains("tag", 10)) { +@@ -196,6 +215,7 @@ public final class ItemStack { // CraftBukkit start - make defensive copy as this data may be coming from the save thread this.tag = (CompoundTag) nbttagcompound.getCompound("tag").copy(); -+ processEnchantOrder(this.tag); // Paper - this.getItem().verifyTagAfterLoad(this.tag); // CraftBukkit end ++ this.processEnchantOrder(this.tag); // Paper + this.getItem().verifyTagAfterLoad(this.tag); } -@@ -678,6 +698,7 @@ public final class ItemStack { + +@@ -745,6 +765,7 @@ public final class ItemStack { // Paper end public void setTag(@Nullable CompoundTag tag) { this.tag = tag; @@ -70,7 +70,7 @@ index 3faf52e7ac5e7e22d09cfb73cfda6b9f622137d4..123025c6dc9a2eea56c7db5cb508cdfd if (this.getItem().canBeDepleted()) { this.setDamageValue(this.getDamageValue()); } -@@ -768,6 +789,7 @@ public final class ItemStack { +@@ -1055,6 +1076,7 @@ public final class ItemStack { nbttagcompound.putString("id", String.valueOf(Registry.ENCHANTMENT.getKey(enchantment))); nbttagcompound.putShort("lvl", (short) ((byte) level)); nbttaglist.add(nbttagcompound); @@ -79,7 +79,7 @@ index 3faf52e7ac5e7e22d09cfb73cfda6b9f622137d4..123025c6dc9a2eea56c7db5cb508cdfd public boolean isEnchanted() { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 01df5263d77771a296ca091a0feec620e6e37229..5f0ccdeb8565505278caa591f7390047eab49cf4 100644 +index 1818be091ce06c1f347396a8a5b9e05f9ceca2c9..51c1f62af5c25fe620f1d8a9cb03473e849db68d 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java @@ -6,7 +6,6 @@ import java.util.Map; @@ -94,13 +94,13 @@ index 01df5263d77771a296ca091a0feec620e6e37229..5f0ccdeb8565505278caa591f7390047 public void addUnsafeEnchantment(Enchantment ench, int level) { Validate.notNull(ench, "Cannot add null enchantment"); -- if (!makeTag(handle)) { +- if (!CraftItemStack.makeTag(this.handle)) { - return; - } -- ListTag list = getEnchantmentList(handle); +- ListTag list = CraftItemStack.getEnchantmentList(this.handle); - if (list == null) { - list = new ListTag(); -- handle.getTag().put(ENCHANTMENTS.NBT, list); +- this.handle.getTag().put(ENCHANTMENTS.NBT, list); - } - int size = list.size(); - @@ -117,9 +117,9 @@ index 01df5263d77771a296ca091a0feec620e6e37229..5f0ccdeb8565505278caa591f7390047 - tag.putShort(ENCHANTMENTS_LVL.NBT, (short) level); - list.add(tag); + // Paper start - Replace whole method -+ final ItemMeta itemMeta = getItemMeta(); ++ final ItemMeta itemMeta = this.getItemMeta(); + itemMeta.addEnchant(ench, level, true); -+ setItemMeta(itemMeta); ++ this.setItemMeta(itemMeta); + // Paper end } @@ -128,25 +128,25 @@ index 01df5263d77771a296ca091a0feec620e6e37229..5f0ccdeb8565505278caa591f7390047 @Override public boolean containsEnchantment(Enchantment ench) { -- return getEnchantmentLevel(ench) > 0; -+ return hasItemMeta() && getItemMeta().hasEnchant(ench); // Paper - use meta +- return this.getEnchantmentLevel(ench) > 0; ++ return this.hasItemMeta() && this.getItemMeta().hasEnchant(ench); // Paper - use meta } @Override public int getEnchantmentLevel(Enchantment ench) { - Validate.notNull(ench, "Cannot find null enchantment"); -- if (handle == null) { +- if (this.handle == null) { - return 0; - } - return EnchantmentHelper.getItemEnchantmentLevel(CraftEnchantment.getRaw(ench), handle); -+ return hasItemMeta() ? getItemMeta().getEnchantLevel(ench) : 0; // Paper - replace entire method with meta ++ return this.hasItemMeta() ? this.getItemMeta().getEnchantLevel(ench) : 0; // Paper - replace entire method with meta } @Override public int removeEnchantment(Enchantment ench) { Validate.notNull(ench, "Cannot remove null enchantment"); -- ListTag list = getEnchantmentList(handle), listCopy; +- ListTag list = CraftItemStack.getEnchantmentList(this.handle), listCopy; - if (list == null) { - return 0; - } @@ -168,9 +168,9 @@ index 01df5263d77771a296ca091a0feec620e6e37229..5f0ccdeb8565505278caa591f7390047 - return 0; - } - if (size == 1) { -- handle.getTag().remove(ENCHANTMENTS.NBT); -- if (handle.getTag().isEmpty()) { -- handle.setTag(null); +- this.handle.getTag().remove(ENCHANTMENTS.NBT); +- if (this.handle.getTag().isEmpty()) { +- this.handle.setTag(null); - } - return level; - } @@ -182,13 +182,13 @@ index 01df5263d77771a296ca091a0feec620e6e37229..5f0ccdeb8565505278caa591f7390047 - listCopy.add(list.get(i)); - } + // Paper start - replace entire method -+ final ItemMeta itemMeta = getItemMeta(); ++ final ItemMeta itemMeta = this.getItemMeta(); + int level = itemMeta.getEnchantLevel(ench); + if (level > 0) { + itemMeta.removeEnchant(ench); -+ setItemMeta(itemMeta); ++ this.setItemMeta(itemMeta); } -- handle.getTag().put(ENCHANTMENTS.NBT, listCopy); +- this.handle.getTag().put(ENCHANTMENTS.NBT, listCopy); + // Paper end return level; @@ -196,13 +196,13 @@ index 01df5263d77771a296ca091a0feec620e6e37229..5f0ccdeb8565505278caa591f7390047 @Override public Map getEnchantments() { -- return getEnchantments(handle); -+ return hasItemMeta() ? getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta +- return CraftItemStack.getEnchantments(this.handle); ++ return this.hasItemMeta() ? this.getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta } 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 cca04daf84e506382365c0ba945cb024bd4d4475..521699615778c4b724d10edfee1d3915e036eb2e 100644 +index 970fa1e98c873ea4dfd4b58c56b7ea88283b0512..45f4f8265c51a5b08db8aa7f53915c4bd0536d39 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; @@ -229,7 +229,7 @@ index cca04daf84e506382365c0ba945cb024bd4d4475..521699615778c4b724d10edfee1d3915 import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nonnull; -@@ -270,7 +273,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -271,7 +274,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { private List lore; // null and empty are two different states internally private Integer customModelData; private CompoundTag blockData; @@ -238,16 +238,16 @@ index cca04daf84e506382365c0ba945cb024bd4d4475..521699615778c4b724d10edfee1d3915 private Multimap attributeModifiers; private int repairCost; private int hideFlag; -@@ -281,7 +284,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -282,7 +285,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); private CompoundTag internalTag; - private final Map unhandledTags = new HashMap(); + private final Map unhandledTags = new TreeMap<>(); // Paper - private CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); + private CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftMetaItem.DATA_TYPE_REGISTRY); private int version = CraftMagicNumbers.INSTANCE.getDataVersion(); // Internal use only -@@ -302,7 +305,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -303,7 +306,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { this.blockData = meta.blockData; if (meta.enchantments != null) { // Spigot @@ -256,7 +256,7 @@ index cca04daf84e506382365c0ba945cb024bd4d4475..521699615778c4b724d10edfee1d3915 } if (meta.hasAttributeModifiers()) { -@@ -385,13 +388,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -386,13 +389,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { } } @@ -272,7 +272,7 @@ index cca04daf84e506382365c0ba945cb024bd4d4475..521699615778c4b724d10edfee1d3915 for (int i = 0; i < ench.size(); i++) { String id = ((CompoundTag) ench.get(i)).getString(ENCHANTMENTS_ID.NBT); -@@ -544,13 +547,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -545,13 +548,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { } } @@ -288,24 +288,24 @@ index cca04daf84e506382365c0ba945cb024bd4d4475..521699615778c4b724d10edfee1d3915 for (Map.Entry entry : ench.entrySet()) { // Doctor older enchants String enchantKey = entry.getKey().toString(); -@@ -826,14 +829,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -827,14 +830,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { @Override public Map getEnchants() { -- return hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); -+ return hasEnchants() ? ImmutableSortedMap.copyOfSorted(enchantments) : ImmutableMap.of(); // Paper +- return this.hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); ++ return this.hasEnchants() ? ImmutableSortedMap.copyOfSorted(this.enchantments) : ImmutableMap.of(); // Paper } @Override public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { Validate.notNull(ench, "Enchantment cannot be null"); - if (enchantments == null) { -- enchantments = new LinkedHashMap(4); -+ enchantments = new EnchantmentMap(); // Paper + if (this.enchantments == null) { +- this.enchantments = new LinkedHashMap(4); ++ this.enchantments = new EnchantmentMap(); // Paper } if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { -@@ -1214,7 +1217,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -1215,7 +1218,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { clone.customModelData = this.customModelData; clone.blockData = this.blockData; if (this.enchantments != null) { @@ -314,8 +314,8 @@ index cca04daf84e506382365c0ba945cb024bd4d4475..521699615778c4b724d10edfee1d3915 } if (this.hasAttributeModifiers()) { clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); -@@ -1446,4 +1449,22 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return HANDLED_TAGS; +@@ -1448,4 +1451,22 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return CraftMetaItem.HANDLED_TAGS; } } + diff --git a/patches/server-remapped/0067-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/patches/server/0062-Configurable-Non-Player-Arrow-Despawn-Rate.patch similarity index 92% rename from patches/server-remapped/0067-Configurable-Non-Player-Arrow-Despawn-Rate.patch rename to patches/server/0062-Configurable-Non-Player-Arrow-Despawn-Rate.patch index a940748e3b..faf974b965 100644 --- a/patches/server-remapped/0067-Configurable-Non-Player-Arrow-Despawn-Rate.patch +++ b/patches/server/0062-Configurable-Non-Player-Arrow-Despawn-Rate.patch @@ -30,15 +30,15 @@ index 3ac2ac3db9b1c271b3c21930bb13716669ff64d3..3c78d3234054ce2dc46ef77decb6adb0 + } } 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 371fdcbf1f9c01f6a356393f6c3767511f230930..0dc5792d542658107c9c22c1f920986decd13920 100644 +index aa679dd070b9efd4b4450cfdb5e4d849f5793534..676e5ad3a23bfdccd8f5f7bb9e79c3fa004dc95f 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -281,7 +281,7 @@ public abstract class AbstractArrow extends Projectile { +@@ -310,7 +310,7 @@ public abstract class AbstractArrow extends Projectile { protected void tickDespawn() { ++this.life; - if (this.life >= ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)) { // Spigot + if (this.life >= (pickup == Pickup.CREATIVE_ONLY ? level.paperConfig.creativeArrowDespawnRate : (pickup == Pickup.DISALLOWED ? level.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? - this.remove(); + this.discard(); } diff --git a/patches/server-remapped/0068-Add-World-Util-Methods.patch b/patches/server/0063-Add-World-Util-Methods.patch similarity index 87% rename from patches/server-remapped/0068-Add-World-Util-Methods.patch rename to patches/server/0063-Add-World-Util-Methods.patch index 83f43bb54a..9ee7105fb9 100644 --- a/patches/server-remapped/0068-Add-World-Util-Methods.patch +++ b/patches/server/0063-Add-World-Util-Methods.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add World Util Methods Methods that can be used for other patches to help improve logic. diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 89472b6e8f38921db50440d0213e40ac893892f1..e1f9a12c7fb4818a785b9a4819f94fccde02b6a2 100644 +index b0ecf3c491e802aa292a0a8b7be37362c38ce084..6aab4ba5da83f523632a0a39d45a0bcb2405f0cc 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -191,7 +191,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -202,7 +202,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl public final LevelStorageSource.LevelStorageAccess convertable; public final UUID uuid; @@ -19,10 +19,10 @@ index 89472b6e8f38921db50440d0213e40ac893892f1..e1f9a12c7fb4818a785b9a4819f94fcc } diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 94e268a05b4601c29b6d2845f0fc2311643a161f..799721ac63f0c08dd03a788b87eafa9a8cc976cc 100644 +index a6b1572a82fd22eea5b3d4124c510d94fea5917d..aee97243cc3e73f9e07ba8ed5d6dbe8c73ba016e 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -297,11 +297,27 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -309,11 +309,27 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } @Override @@ -52,10 +52,10 @@ index 94e268a05b4601c29b6d2845f0fc2311643a161f..799721ac63f0c08dd03a788b87eafa9a @Override diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 31f17956b3b031d1a47bda4d282554c8a7853097..0846f649dca3422dbab3bb0a4826e27430cc8186 100644 +index 72087476c65b69c86af67424a15708c463d69a43..02b10be4878b871742efb0f65980d9672f32b388 100644 --- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java +++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -31,6 +31,7 @@ public class WorldBorder { +@@ -32,6 +32,7 @@ public class WorldBorder { public WorldBorder() {} diff --git a/patches/server-remapped/0069-Custom-replacement-for-eaten-items.patch b/patches/server/0064-Custom-replacement-for-eaten-items.patch similarity index 88% rename from patches/server-remapped/0069-Custom-replacement-for-eaten-items.patch rename to patches/server/0064-Custom-replacement-for-eaten-items.patch index 2e91f18d2b..434a686c67 100644 --- a/patches/server-remapped/0069-Custom-replacement-for-eaten-items.patch +++ b/patches/server/0064-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 d483d552092c901fec262c43e488784d9cd8acb9..3c707ca6b56e89b671db6316d4db90a2903f33b4 100644 +index 46e514bfe80d999f50173866b59fbc9419bbf3d0..89db2afd198366ab94c9c074890aa668d3771a79 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3202,9 +3202,10 @@ public abstract class LivingEntity extends Entity { +@@ -3560,9 +3560,10 @@ public abstract class LivingEntity extends Entity { this.triggerItemUseEffects(this.useItem, 16); // CraftBukkit start - fire PlayerItemConsumeEvent ItemStack itemstack; @@ -20,7 +20,7 @@ index d483d552092c901fec262c43e488784d9cd8acb9..3c707ca6b56e89b671db6316d4db90a2 level.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { -@@ -3218,6 +3219,13 @@ public abstract class LivingEntity extends Entity { +@@ -3576,6 +3577,13 @@ public abstract class LivingEntity extends Entity { } else { itemstack = this.useItem.finishUsingItem(this.level, this); } @@ -34,7 +34,7 @@ index d483d552092c901fec262c43e488784d9cd8acb9..3c707ca6b56e89b671db6316d4db90a2 // CraftBukkit end if (itemstack != this.useItem) { -@@ -3225,6 +3233,11 @@ public abstract class LivingEntity extends Entity { +@@ -3583,6 +3591,11 @@ public abstract class LivingEntity extends Entity { } this.stopUsingItem(); diff --git a/patches/server-remapped/0070-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/patches/server/0065-handle-NaN-health-absorb-values-and-repair-bad-data.patch similarity index 65% rename from patches/server-remapped/0070-handle-NaN-health-absorb-values-and-repair-bad-data.patch rename to patches/server/0065-handle-NaN-health-absorb-values-and-repair-bad-data.patch index 0d5d5d19aa..2addfbb9df 100644 --- a/patches/server-remapped/0070-handle-NaN-health-absorb-values-and-repair-bad-data.patch +++ b/patches/server/0065-handle-NaN-health-absorb-values-and-repair-bad-data.patch @@ -5,25 +5,25 @@ 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 3c707ca6b56e89b671db6316d4db90a2903f33b4..a326e5b4ac055f2f8a95c6eaccd8d0a97762da1f 100644 +index 89db2afd198366ab94c9c074890aa668d3771a79..83eaa3c6581c1a3f588278124fed4c811e81e53c 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -699,7 +699,13 @@ public abstract class LivingEntity extends Entity { +@@ -764,7 +764,13 @@ public abstract class LivingEntity extends Entity { @Override - public void readAdditionalSaveData(CompoundTag tag) { -- this.setAbsorptionAmount(tag.getFloat("AbsorptionAmount")); + public void readAdditionalSaveData(CompoundTag nbt) { +- this.setAbsorptionAmount(nbt.getFloat("AbsorptionAmount")); + // Paper start - jvm keeps optimizing the setter -+ float absorptionAmount = tag.getFloat("AbsorptionAmount"); ++ float absorptionAmount = nbt.getFloat("AbsorptionAmount"); + if (Float.isNaN(absorptionAmount)) { + absorptionAmount = 0; + } + this.setAbsorptionAmount(absorptionAmount); + // Paper end - if (tag.contains("Attributes", 9) && this.level != null && !this.level.isClientSide) { - this.getAttributes().load(tag.getList("Attributes", 10)); + if (nbt.contains("Attributes", 9) && this.level != null && !this.level.isClientSide) { + this.getAttributes().load(nbt.getList("Attributes", 10)); } -@@ -1148,6 +1154,10 @@ public abstract class LivingEntity extends Entity { +@@ -1251,6 +1257,10 @@ public abstract class LivingEntity extends Entity { } public void setHealth(float health) { @@ -34,7 +34,7 @@ index 3c707ca6b56e89b671db6316d4db90a2903f33b4..a326e5b4ac055f2f8a95c6eaccd8d0a9 // CraftBukkit start - Handle scaled health if (this instanceof ServerPlayer) { org.bukkit.craftbukkit.entity.CraftPlayer player = ((ServerPlayer) this).getBukkitEntity(); -@@ -3042,7 +3052,7 @@ public abstract class LivingEntity extends Entity { +@@ -3395,7 +3405,7 @@ public abstract class LivingEntity extends Entity { } public void setAbsorptionAmount(float amount) { @@ -43,11 +43,16 @@ index 3c707ca6b56e89b671db6316d4db90a2903f33b4..a326e5b4ac055f2f8a95c6eaccd8d0a9 amount = 0.0F; } +@@ -4000,3 +4010,4 @@ public abstract class LivingEntity extends Entity { + this.setDeltaMovement((double) ((float) packet.getXd() / 8000.0F), (double) ((float) packet.getYd() / 8000.0F), (double) ((float) packet.getZd() / 8000.0F)); + } + } ++ diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index dd29038778d73fae84df360515f3c670915f1d48..b7d5a718375083a4162df4bb41de3acd57b297fb 100644 +index 074b9e2aa9162aec64007cbf235ccc965db70055..7d19f877e66ef10c977b8072732bb16bd978e0de 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1678,6 +1678,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1679,6 +1679,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void setRealHealth(double health) { From 933a189a049fe47787a087599d692e514a0883a7 Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Fri, 11 Jun 2021 19:24:43 -0700 Subject: [PATCH 030/226] more patches (#5799) --- ...66-Use-a-Shared-Random-for-Entities.patch} | 8 +- ...e-spawn-chances-for-skeleton-horses.patch} | 10 +- ...ocation-getType-and-getBlockData-fo.patch} | 109 ++++++++---------- ...kPhysicsEvent-if-a-plugin-has-a-lis.patch} | 36 +++--- ...ntity-AddTo-RemoveFrom-World-Events.patch} | 21 ++-- ...1-Configurable-Chunk-Inhabited-Time.patch} | 6 +- .../0072-EntityPathfindEvent.patch} | 81 ++++++------- ...gionFileCache-and-make-configurable.patch} | 4 +- ...-Do-not-load-chunks-for-Pathfinding.patch} | 56 ++++----- 9 files changed, 155 insertions(+), 176 deletions(-) rename patches/{server-remapped/0071-Use-a-Shared-Random-for-Entities.patch => server/0066-Use-a-Shared-Random-for-Entities.patch} (81%) rename patches/{server-remapped/0072-Configurable-spawn-chances-for-skeleton-horses.patch => server/0067-Configurable-spawn-chances-for-skeleton-horses.patch} (80%) rename patches/{server-remapped/0073-Optimize-isValidLocation-getType-and-getBlockData-fo.patch => server/0068-Optimize-isValidLocation-getType-and-getBlockData-fo.patch} (63%) rename patches/{server-remapped/0074-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch => server/0069-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch} (79%) rename patches/{server-remapped/0075-Entity-AddTo-RemoveFrom-World-Events.patch => server/0070-Entity-AddTo-RemoveFrom-World-Events.patch} (61%) rename patches/{server-remapped/0076-Configurable-Chunk-Inhabited-Time.patch => server/0071-Configurable-Chunk-Inhabited-Time.patch} (86%) rename patches/{server-remapped/0077-EntityPathfindEvent.patch => server/0072-EntityPathfindEvent.patch} (60%) rename patches/{server-remapped/0078-Sanitise-RegionFileCache-and-make-configurable.patch => server/0073-Sanitise-RegionFileCache-and-make-configurable.patch} (92%) rename patches/{server-remapped/0079-Do-not-load-chunks-for-Pathfinding.patch => server/0074-Do-not-load-chunks-for-Pathfinding.patch} (55%) diff --git a/patches/server-remapped/0071-Use-a-Shared-Random-for-Entities.patch b/patches/server/0066-Use-a-Shared-Random-for-Entities.patch similarity index 81% rename from patches/server-remapped/0071-Use-a-Shared-Random-for-Entities.patch rename to patches/server/0066-Use-a-Shared-Random-for-Entities.patch index ddca7a2d46..27b07b1be0 100644 --- a/patches/server-remapped/0071-Use-a-Shared-Random-for-Entities.patch +++ b/patches/server/0066-Use-a-Shared-Random-for-Entities.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Use a Shared Random for Entities Reduces memory usage and provides ensures more randomness, Especially since a lot of garbage entity objects get created. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 93d3408231a177cf6d2086594756adffe3efa702..61048140cf0adca03bfb57193ada0adaee73b1bb 100644 +index e9e87dc8c80d83dc7c472b0611077d8f9f4e5fcf..eceaeed527f34860e1c55b9f96863f140055faa7 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -142,6 +142,21 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -153,6 +153,21 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; } @@ -31,10 +31,10 @@ index 93d3408231a177cf6d2086594756adffe3efa702..61048140cf0adca03bfb57193ada0ada private CraftEntity bukkitEntity; public CraftEntity getBukkitEntity() { -@@ -271,7 +286,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -304,7 +319,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + this.bb = Entity.INITIAL_AABB; this.stuckSpeedMultiplier = Vec3.ZERO; this.nextStep = 1.0F; - this.nextFlap = 1.0F; - this.random = new Random(); + this.random = SHARED_RANDOM; // Paper this.remainingFireTicks = -this.getFireImmuneTicks(); diff --git a/patches/server-remapped/0072-Configurable-spawn-chances-for-skeleton-horses.patch b/patches/server/0067-Configurable-spawn-chances-for-skeleton-horses.patch similarity index 80% rename from patches/server-remapped/0072-Configurable-spawn-chances-for-skeleton-horses.patch rename to patches/server/0067-Configurable-spawn-chances-for-skeleton-horses.patch index 59b6c7f72a..9ca8482661 100644 --- a/patches/server-remapped/0072-Configurable-spawn-chances-for-skeleton-horses.patch +++ b/patches/server/0067-Configurable-spawn-chances-for-skeleton-horses.patch @@ -22,15 +22,15 @@ index 3c78d3234054ce2dc46ef77decb6adb0cbd10620..cd64fb9d0c6d123e1c86cb33f12cd9ce + } } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index e1f9a12c7fb4818a785b9a4819f94fccde02b6a2..22c687e3db79bcfbc512ce3993d6e8a6db062360 100644 +index 6aab4ba5da83f523632a0a39d45a0bcb2405f0cc..69b52097eede1a5c408aa7f34442e42255386436 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -584,7 +584,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); +@@ -596,7 +596,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15)); if (this.isRainingAt(blockposition)) { DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); -- boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * 0.01D; -+ boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance; // Paper +- boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * 0.01D && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); ++ boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper if (flag1) { SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create((net.minecraft.world.level.Level) this); diff --git a/patches/server-remapped/0073-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/patches/server/0068-Optimize-isValidLocation-getType-and-getBlockData-fo.patch similarity index 63% rename from patches/server-remapped/0073-Optimize-isValidLocation-getType-and-getBlockData-fo.patch rename to patches/server/0068-Optimize-isValidLocation-getType-and-getBlockData-fo.patch index 2c0ed8f7cd..6096bf4e20 100644 --- a/patches/server-remapped/0073-Optimize-isValidLocation-getType-and-getBlockData-fo.patch +++ b/patches/server/0068-Optimize-isValidLocation-getType-and-getBlockData-fo.patch @@ -13,19 +13,19 @@ Replace all calls to the new place to the unnecessary forward. Optimize getType and getBlockData to manually inline and optimize the calls diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java -index 3e79b274b8e0406a3cbdd94c7cec091b583109ca..c22de593be404c4e921724bba6a69c13759a95fd 100644 +index f4b5792e080d5181184eb661d005ce6cab649bf3..c66ae4d9eea993f3b7fcc6e253259db3346229d1 100644 --- a/src/main/java/net/minecraft/core/Vec3i.java +++ b/src/main/java/net/minecraft/core/Vec3i.java -@@ -22,6 +22,15 @@ public class Vec3i implements Comparable { - private int y;public final void setY(final int y) { this.y = y; } // Paper - OBFHELPER - private int z;public final void setZ(final int z) { this.z = z; } // Paper - OBFHELPER +@@ -21,6 +21,15 @@ public class Vec3i implements Comparable { + private int y; + private int z; + // Paper start -+ public boolean isValidLocation() { -+ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && getY() >= 0 && getY() < 256; ++ public boolean isValidLocation(net.minecraft.world.level.Level level) { ++ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && !level.isOutsideBuildHeight(getY()); + } -+ public boolean isInvalidYLocation() { -+ return y < 0 || y >= 256; ++ public boolean isInvalidYLocation(net.minecraft.world.level.Level level) { ++ return level.isOutsideBuildHeight(getY()); + } + // Paper end + @@ -33,45 +33,36 @@ index 3e79b274b8e0406a3cbdd94c7cec091b583109ca..c22de593be404c4e921724bba6a69c13 this.x = x; this.y = y; diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 799721ac63f0c08dd03a788b87eafa9a8cc976cc..24a6429059f58f51c97386ca2823ca0910288dec 100644 +index aee97243cc3e73f9e07ba8ed5d6dbe8c73ba016e..fdab998241a682bc3d75094e0893f98886e06266 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -239,7 +239,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -259,7 +259,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } - public static boolean isInWorldBounds(BlockPos pos) { -- return !isOutsideBuildHeight(pos) && isInWorldBoundsHorizontal(pos); -+ return pos.isValidLocation(); // Paper - use better/optimized check + public boolean isInWorldBounds(BlockPos pos) { +- return !this.isOutsideBuildHeight(pos) && Level.isInWorldBoundsHorizontal(pos); ++ return pos.isValidLocation(this); // Paper - use better/optimized check } public static boolean isInSpawnableBounds(BlockPos pos) { diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -index 3ca6289ba4952b5036367451b50cd90a78c0f938..e6303cdb433ee2b6782e2a0bd6b03e4f6ecb18ba 100644 +index 6a3f98edbc2b4056c5baf00277caee327e444a77..974ab04b08bbd3c27a394b37c1af112be5f28f43 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -@@ -25,6 +25,7 @@ import org.apache.logging.log4j.LogManager; - - public interface ChunkAccess extends BlockGetter, FeatureAccess { +@@ -29,6 +29,7 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { + return GameEventDispatcher.NOOP; + } + BlockState getType(final int x, final int y, final int z); // Paper @Nullable BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java -index a26de06252207cf333ea4a8d73f0af6ddc239103..e369730ac6909ff5343468bd685c9ea2b6b3cfed 100644 +index 84ebfdfc4350fb57ca2959e000b33b8d5efa6e0b..69c2454533e6f21c70792b555ec02c6bc6d169b3 100644 --- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java -@@ -23,7 +23,7 @@ import net.minecraft.world.phys.AABB; - - public class EmptyLevelChunk extends LevelChunk { - -- private static final Biome[] BIOMES = (Biome[]) Util.make((Object) (new Biome[ChunkBiomeContainer.BIOMES_SIZE]), (abiomebase) -> { -+ private static final Biome[] BIOMES = Util.make((new Biome[ChunkBiomeContainer.BIOMES_SIZE]), (abiomebase) -> { // Paper - decompile error - Arrays.fill(abiomebase, Biomes.PLAINS); - }); - -@@ -31,6 +31,11 @@ public class EmptyLevelChunk extends LevelChunk { - super(world, pos, new ChunkBiomeContainer(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), EmptyLevelChunk.BIOMES)); +@@ -19,6 +19,11 @@ public class EmptyLevelChunk extends LevelChunk { + super(world, pos, new EmptyLevelChunk.EmptyChunkBiomeContainer(world)); } + // Paper start @@ -83,10 +74,10 @@ index a26de06252207cf333ea4a8d73f0af6ddc239103..e369730ac6909ff5343468bd685c9ea2 public BlockState getBlockState(BlockPos pos) { return Blocks.VOID_AIR.defaultBlockState(); diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -index 04940ab2814cf39157d234dc4615646d7c760460..17fa8b23d1000ae53f2b4f1a6e8817c1005c1c81 100644 +index c1beb6d5fc3cabfeacf0ffbf563e53ff7984c5d3..452b513e8b89d865a396066adaf4feb1140e1c62 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -@@ -42,6 +42,11 @@ public class ImposterProtoChunk extends ProtoChunk { +@@ -40,6 +40,11 @@ public class ImposterProtoChunk extends ProtoChunk { public BlockState getBlockState(BlockPos pos) { return this.wrapped.getBlockState(pos); } @@ -99,47 +90,47 @@ index 04940ab2814cf39157d234dc4615646d7c760460..17fa8b23d1000ae53f2b4f1a6e8817c1 @Override public FluidState getFluidState(BlockPos pos) { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 9ca05aa06696883adc8b67a68ca6d2d850e95d25..546fb2f42e6bf333582b504d0a29991698505df3 100644 +index 9939c4c39549771afe971a6433dfd57e36050dd8..7e5e16fd61b39d2093459766e8aaa10bb05f6763 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -347,12 +347,27 @@ public class LevelChunk implements ChunkAccess { +@@ -337,12 +337,28 @@ public class LevelChunk implements ChunkAccess { return this.sections; } -- @Override + // Paper start - Optimize getBlockData to reduce instructions -+ public final BlockState getBlockData(BlockPos pos) { return getBlockData(pos.getX(), pos.getY(), pos.getZ()); } // Paper + @Override public BlockState getBlockState(BlockPos pos) { - int i = pos.getX(); - int j = pos.getY(); - int k = pos.getZ(); + return this.getBlockData(pos.getX(), pos.getY(), pos.getZ()); + } - ++ + public BlockState getType(final int x, final int y, final int z) { -+ return getBlockData(x, y, z); ++ return this.getBlockData(x, y, z); + } + public final BlockState getBlockData(final int x, final int y, final int z) { + // Method body / logic copied from below -+ final int i = y >> 4; -+ if (y < 0 || i >= this.sections.length || this.sections[i] == null || this.sections[i].nonEmptyBlockCount == 0) { ++ final int i = this.getSectionIndex(y); ++ if (i < 0 || i >= this.sections.length || this.sections[i] == null || this.sections[i].nonEmptyBlockCount == 0) { + return Blocks.AIR.defaultBlockState(); + } + // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) + return this.sections[i].states.get((y & 15) << 8 | (z & 15) << 4 | x & 15); + + } + + public BlockState getBlockData_unused(int i, int j, int k) { + // Paper end - if (this.world.isDebug()) { + if (this.level.isDebug()) { BlockState iblockdata = null; diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index b54d82e0f41a03c91e0de8df8249a91da3c04d0e..f5db97fb0dac78e1d9aa68d0417aa13f39914f52 100644 +index 03fd5684aec8fa0d87963f2adcd8244e92840917..5fd66020a937b641e2a060cf38df731a43f3bf55 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -13,10 +13,10 @@ public class LevelChunkSection { - +@@ -15,10 +15,10 @@ public class LevelChunkSection { + public static final int SECTION_SIZE = 4096; public static final Palette GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState()); private final int bottomBlockY; - private short nonEmptyBlockCount; @@ -150,23 +141,21 @@ index b54d82e0f41a03c91e0de8df8249a91da3c04d0e..f5db97fb0dac78e1d9aa68d0417aa13f + final PalettedContainer states; // Paper - package-private public LevelChunkSection(int yOffset) { - this(yOffset, (short) 0, (short) 0, (short) 0); -@@ -30,8 +30,8 @@ public class LevelChunkSection { - this.states = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); + this(yOffset, (short)0, (short)0, (short)0); +@@ -37,7 +37,7 @@ public class LevelChunkSection { } -- public BlockState getBlockState(int x, int y, int z) { -- return (BlockState) this.states.get(x, y, z); -+ public final BlockState getBlockState(int x, int y, int z) { // Paper + public BlockState getBlockState(int x, int y, int z) { +- return this.states.get(x, y, z); + return this.states.get(y << 8 | z << 4 | x); // Paper - inline } public FluidState getFluidState(int x, int y, int z) { diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index d4db27421736f665739436c1ac4d3c6d5cae95cd..6d3dcd19ce1abc9d502903b8008949b5174a13c3 100644 +index 4a6781919eb78abc33f549693d88019b42ef6e95..5ea60bbb56450502f1ceb41959239ab579458ac2 100644 --- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -133,7 +133,7 @@ public class PalettedContainer implements PaletteResize { +@@ -136,7 +136,7 @@ public class PalettedContainer implements PaletteResize { } public T get(int x, int y, int z) { @@ -176,27 +165,25 @@ index d4db27421736f665739436c1ac4d3c6d5cae95cd..6d3dcd19ce1abc9d502903b8008949b5 protected T get(int index) { diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 7cd3f89004b0a64772fc3dfbdd132ba5a850b63e..d8b7b210484079c9ca2c34831c84102cba6692f5 100644 +index 39fe8f64528ad08594aaaa88e5c989c82e4e29d3..da36e6d40ad3e8b7cdbe09ef911d1e5b8c28670f 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -113,16 +113,18 @@ public class ProtoChunk implements ChunkAccess { +@@ -104,14 +104,18 @@ public class ProtoChunk implements ChunkAccess { @Override public BlockState getBlockState(BlockPos pos) { - int i = pos.getY(); -- -- if (Level.isOutsideBuildHeight(i)) { +- if (this.isOutsideBuildHeight(i)) { ++ // Paper start + return getType(pos.getX(), pos.getY(), pos.getZ()); + } -+ // Paper start + public BlockState getType(final int x, final int y, final int z) { -+ if (y < 0 || y >= 256) { ++ if (this.isOutsideBuildHeight(y)) { return Blocks.VOID_AIR.defaultBlockState(); } else { -- LevelChunkSection chunksection = this.getSections()[i >> 4]; -- -- return LevelChunkSection.isEmpty(chunksection) ? Blocks.AIR.defaultBlockState() : chunksection.getBlockState(pos.getX() & 15, i & 15, pos.getZ() & 15); -+ LevelChunkSection chunksection = this.getSections()[y >> 4]; +- LevelChunkSection levelChunkSection = this.getSections()[this.getSectionIndex(i)]; +- return LevelChunkSection.isEmpty(levelChunkSection) ? Blocks.AIR.defaultBlockState() : levelChunkSection.getBlockState(pos.getX() & 15, i & 15, pos.getZ() & 15); ++ LevelChunkSection chunksection = this.getSections()[this.getSectionIndex(y)]; + return chunksection == LevelChunk.EMPTY_CHUNK_SECTION || chunksection.isEmpty() ? Blocks.AIR.defaultBlockState() : chunksection.getBlockState(x & 15, y & 15, z & 15); } } diff --git a/patches/server-remapped/0074-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/patches/server/0069-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch similarity index 79% rename from patches/server-remapped/0074-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch rename to patches/server/0069-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch index 1bc2cb3b6f..e99e63b0b1 100644 --- a/patches/server-remapped/0074-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch +++ b/patches/server/0069-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Only process BlockPhysicsEvent if a plugin has a listener Saves on some object allocation and processing when no plugin listens to this diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 901d5497667706c049718dc4fca37a1bc489c465..f7763a773bce4d8d947c8c859fe84d8a601034c5 100644 +index c6a59fa4b30d54baa638c931f045b2d546da021a..591f7452005cbfb567b611b3ba71c16596f9edfa 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1290,6 +1290,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { return worldserver + " " + worldserver.dimension().location(); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 22c687e3db79bcfbc512ce3993d6e8a6db062360..8b0a384caa09848d61b3a6259dd56590cd52d0a0 100644 +index 69b52097eede1a5c408aa7f34442e42255386436..9394dd781bb27b273c442972c5923615ac406507 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -190,6 +190,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -201,6 +201,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl private int tickPosition; public final LevelStorageSource.LevelStorageAccess convertable; public final UUID uuid; @@ -30,10 +30,10 @@ index 22c687e3db79bcfbc512ce3993d6e8a6db062360..8b0a384caa09848d61b3a6259dd56590 @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI return this.chunkSource.getChunk(x, z, false); diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 24a6429059f58f51c97386ca2823ca0910288dec..d47ed15382f98aabd509e32a3c202a91088adf6b 100644 +index fdab998241a682bc3d75094e0893f98886e06266..81a8e314b5073a5888a3c04d53ff279c8142a7d4 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -458,7 +458,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -470,7 +470,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { // CraftBukkit start iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam CraftWorld world = ((ServerLevel) this).getWorld(); @@ -42,29 +42,29 @@ index 24a6429059f58f51c97386ca2823ca0910288dec..d47ed15382f98aabd509e32a3c202a91 BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); this.getCraftServer().getPluginManager().callEvent(event); -@@ -560,7 +560,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -580,7 +580,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { try { // CraftBukkit start CraftWorld world = ((ServerLevel) this).getWorld(); - if (world != null) { + if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(sourcePos.getX(), sourcePos.getY(), sourcePos.getZ()), CraftBlockData.fromData(iblockdata), world.getBlockAt(neighborPos.getX(), neighborPos.getY(), neighborPos.getZ())); + BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftBlockData.fromData(iblockdata), world.getBlockAt(neighborPos.getX(), neighborPos.getY(), neighborPos.getZ())); this.getCraftServer().getPluginManager().callEvent(event); diff --git a/src/main/java/net/minecraft/world/level/block/BushBlock.java b/src/main/java/net/minecraft/world/level/block/BushBlock.java -index d6cb341d4d8e20b77979a241dd2e4346455796d7..42635b6115187abeffb290ca040350fd97cf89f7 100644 +index 24227939493f852a88477c84160bda1605291eb0..1f8cf302d2309aec2955832ffafd87f14934e141 100644 --- a/src/main/java/net/minecraft/world/level/block/BushBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BushBlock.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; - - import net.minecraft.core.BlockPos; +@@ -4,6 +4,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.Tag; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelReader; -@@ -23,7 +24,7 @@ public class BushBlock extends Block { - public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { +@@ -25,7 +26,7 @@ public class BushBlock extends Block { + public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { // CraftBukkit start if (!state.canSurvive(world, pos)) { - if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { @@ -73,18 +73,18 @@ index d6cb341d4d8e20b77979a241dd2e4346455796d7..42635b6115187abeffb290ca040350fd } } diff --git a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java -index db444689092f537dd736dc73c532bd540fadcf86..86c5025d1b21dc35782124eca66288c63626147a 100644 +index 08870ea2431ba27474a275006071801c01cc9b1c..9c010d8359a36f3b2d4af3d828bc2dca792ef2f4 100644 --- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java -@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; - import javax.annotation.Nullable; +@@ -4,6 +4,7 @@ import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; + import net.minecraft.util.Mth; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -@@ -83,7 +84,7 @@ public class DoublePlantBlock extends BushBlock { +@@ -85,7 +86,7 @@ public class DoublePlantBlock extends BushBlock { protected static void preventCreativeDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) { // CraftBukkit start diff --git a/patches/server-remapped/0075-Entity-AddTo-RemoveFrom-World-Events.patch b/patches/server/0070-Entity-AddTo-RemoveFrom-World-Events.patch similarity index 61% rename from patches/server-remapped/0075-Entity-AddTo-RemoveFrom-World-Events.patch rename to patches/server/0070-Entity-AddTo-RemoveFrom-World-Events.patch index 0b9b2867e9..f0c9ea7c3a 100644 --- a/patches/server-remapped/0075-Entity-AddTo-RemoveFrom-World-Events.patch +++ b/patches/server/0070-Entity-AddTo-RemoveFrom-World-Events.patch @@ -5,19 +5,10 @@ Subject: [PATCH] Entity AddTo/RemoveFrom World Events diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 8b0a384caa09848d61b3a6259dd56590cd52d0a0..f7eddb39985072afeb79ec0cbfc084d7e84638e6 100644 +index 9394dd781bb27b273c442972c5923615ac406507..b1c9a21574d6adba5d01caea0abac16a0e214a8f 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1208,7 +1208,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - if (entity instanceof Mob) { - this.navigations.remove(((Mob) entity).getNavigation()); - } -- -+ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - entity.valid = false; // CraftBukkit - } - -@@ -1246,6 +1246,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1116,6 +1116,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl entity.origin = entity.getBukkitEntity().getLocation(); } // Paper end @@ -25,3 +16,11 @@ index 8b0a384caa09848d61b3a6259dd56590cd52d0a0..f7eddb39985072afeb79ec0cbfc084d7 } } +@@ -1964,6 +1965,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + entity.valid = false; // CraftBukkit ++ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + } + } + } diff --git a/patches/server-remapped/0076-Configurable-Chunk-Inhabited-Time.patch b/patches/server/0071-Configurable-Chunk-Inhabited-Time.patch similarity index 86% rename from patches/server-remapped/0076-Configurable-Chunk-Inhabited-Time.patch rename to patches/server/0071-Configurable-Chunk-Inhabited-Time.patch index 126102b49a..a9a9402014 100644 --- a/patches/server-remapped/0076-Configurable-Chunk-Inhabited-Time.patch +++ b/patches/server/0071-Configurable-Chunk-Inhabited-Time.patch @@ -30,15 +30,15 @@ index cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0..74ba5dbb83c13ce1721619b755036a78 + } } diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 546fb2f42e6bf333582b504d0a29991698505df3..70f5b025c2b803df3de8a51cbcfafbe915866f42 100644 +index 7e5e16fd61b39d2093459766e8aaa10bb05f6763..5c5a55003658d75ad8295cbd7ff0450e08600d68 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -1021,7 +1021,7 @@ public class LevelChunk implements ChunkAccess { +@@ -978,7 +978,7 @@ public class LevelChunk implements ChunkAccess { @Override public long getInhabitedTime() { - return this.inhabitedTime; -+ return world.paperConfig.fixedInhabitedTime < 0 ? this.inhabitedTime : world.paperConfig.fixedInhabitedTime; // Paper ++ return this.level.paperConfig.fixedInhabitedTime < 0 ? this.inhabitedTime : this.level.paperConfig.fixedInhabitedTime; // Paper } @Override diff --git a/patches/server-remapped/0077-EntityPathfindEvent.patch b/patches/server/0072-EntityPathfindEvent.patch similarity index 60% rename from patches/server-remapped/0077-EntityPathfindEvent.patch rename to patches/server/0072-EntityPathfindEvent.patch index e784dacc5f..1f2104c785 100644 --- a/patches/server-remapped/0077-EntityPathfindEvent.patch +++ b/patches/server/0072-EntityPathfindEvent.patch @@ -6,10 +6,10 @@ Subject: [PATCH] EntityPathfindEvent Fires when an Entity decides to start moving to a location. diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java -index 0af2c5dde41043a6fb2fcd07db96288c7f96e0c7..5e7e678c4469e34c7ae39656f547243fbcf1d0da 100644 +index 3afe97f4e330016164e741934c888f5b85824e67..48a42a8374641f4737d5eb6a460bf80a12c2cae5 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java -@@ -37,7 +37,7 @@ public class FlyingPathNavigation extends PathNavigation { +@@ -35,7 +35,7 @@ public class FlyingPathNavigation extends PathNavigation { @Override public Path createPath(Entity entity, int distance) { @@ -19,10 +19,10 @@ index 0af2c5dde41043a6fb2fcd07db96288c7f96e0c7..5e7e678c4469e34c7ae39656f547243f @Override diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java -index cd7cb7cbe55a36282de394efc95f4ba7cc6a75cf..01be1de9d9ca0a86d69b2e82693bd0fea61a969f 100644 +index d2e71f1e70a8b3360110f7e5e6c5ec278218ae27..0ac90b5fefa9720a9d0130f5438e5ef55fccf29a 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java -@@ -75,7 +75,7 @@ public class GroundPathNavigation extends PathNavigation { +@@ -70,7 +70,7 @@ public class GroundPathNavigation extends PathNavigation { @Override public Path createPath(Entity entity, int distance) { @@ -32,27 +32,27 @@ index cd7cb7cbe55a36282de394efc95f4ba7cc6a75cf..01be1de9d9ca0a86d69b2e82693bd0fe private int getSurfaceY() { diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index 3cfd913e31236e35e7225ba19d292cacb8b4134a..ae8d430382b20ddd837c47e39515c7995f25312a 100644 +index 92e1c43b0b7d901636b7fee7136e573f440e0179..e6a2f836e70a267da36ec87e0df68e36bae3626c 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java @@ -10,6 +10,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Position; import net.minecraft.core.Vec3i; import net.minecraft.network.protocol.game.DebugPackets; + import net.minecraft.tags.BlockTags; +import net.minecraft.server.MCUtil; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Mob; -@@ -28,7 +29,7 @@ import net.minecraft.world.phys.Vec3; +@@ -26,7 +27,7 @@ import net.minecraft.world.phys.Vec3; public abstract class PathNavigation { - + private static final int MAX_TIME_RECOMPUTE = 20; - protected final Mob mob; + protected final Mob mob; public Entity getEntity() { return mob; } // Paper - OBFHELPER protected final Level level; @Nullable protected Path path; -@@ -115,36 +116,63 @@ public abstract class PathNavigation { +@@ -108,7 +109,12 @@ public abstract class PathNavigation { @Nullable public Path createPath(BlockPos target, int distance) { @@ -60,66 +60,59 @@ index 3cfd913e31236e35e7225ba19d292cacb8b4134a..ae8d430382b20ddd837c47e39515c799 + // Paper start - add target parameter + return this.a(target, null, distance); + } -+ @Nullable public Path a(BlockPos blockposition, Entity target, int i) { -+ return this.a(ImmutableSet.of(blockposition), target, 8, false, i); ++ @Nullable public Path a(BlockPos blockposition, Entity target, int distance) { ++ return this.createPath(ImmutableSet.of(blockposition), target, 8, false, distance); + // Paper end } + @Nullable +@@ -118,7 +124,7 @@ public abstract class PathNavigation { + @Nullable public Path createPath(Entity entity, int distance) { - return this.createPath(ImmutableSet.of(entity.blockPosition()), 16, true, distance); -+ return this.a(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper ++ return this.createPath(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper } @Nullable -+ // Paper start - Add target - protected Path createPath(Set positions, int range, boolean flag, int distance) { -- if (positions.isEmpty()) { -+ return this.a(positions, null, range, flag, distance); +@@ -128,6 +134,16 @@ public abstract class PathNavigation { + + @Nullable + protected Path createPath(Set positions, int range, boolean useHeadPos, int distance, float followRange) { ++ return this.createPath(positions, null, range, useHeadPos, distance, (float) this.mob.getAttributeValue(Attributes.FOLLOW_RANGE)); + } -+ @Nullable protected Path a(Set set, Entity target, int i, boolean flag, int j) { ++ ++ @Nullable ++ protected Path createPath(Set positions, Entity target, int range, boolean useHeadPos, int distance) { ++ return this.createPath(positions, target, range, useHeadPos, distance, (float) this.mob.getAttributeValue(Attributes.FOLLOW_RANGE)); ++ } ++ ++ @Nullable protected Path createPath(Set positions, Entity target, int range, boolean useHeadPos, int distance, float followRange) { + // Paper end -+ if (set.isEmpty()) { + if (positions.isEmpty()) { return null; - } else if (this.mob.getY() < 0.0D) { - return null; - } else if (!this.canUpdatePath()) { - return null; -- } else if (this.path != null && !this.path.isDone() && positions.contains(this.targetPos)) { -+ } else if (this.path != null && !this.path.isDone() && set.contains(this.targetPos)) { + } else if (this.mob.getY() < (double)this.level.getMinBuildHeight()) { +@@ -137,6 +153,23 @@ public abstract class PathNavigation { + } else if (this.path != null && !this.path.isDone() && positions.contains(this.targetPos)) { return this.path; } else { + // Paper start - Pathfind event + boolean copiedSet = false; -+ for (BlockPos possibleTarget : set) { ++ for (BlockPos possibleTarget : positions) { + if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), + MCUtil.toLocation(getEntity().level, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { + if (!copiedSet) { + copiedSet = true; -+ set = new java.util.HashSet<>(set); ++ positions = new java.util.HashSet<>(positions); + } + // note: since we copy the set this remove call is safe, since we're iterating over the old copy -+ set.remove(possibleTarget); -+ if (set.isEmpty()) { ++ positions.remove(possibleTarget); ++ if (positions.isEmpty()) { + return null; + } + } + } + // Paper end this.level.getProfiler().push("pathfind"); - float f = (float) this.mob.getAttributeValue(Attributes.FOLLOW_RANGE); - BlockPos blockposition = flag ? this.mob.blockPosition().above() : this.mob.blockPosition(); -- int k = (int) (f + (float) range); -+ int k = (int) (f + (float) i); - PathNavigationRegion chunkcache = new PathNavigationRegion(this.level, blockposition.offset(-k, -k, -k), blockposition.offset(k, k, k)); -- Path pathentity = this.pathFinder.findPath(chunkcache, this.mob, positions, f, distance, this.maxVisitedNodesMultiplier); -+ Path pathentity = this.pathFinder.findPath(chunkcache, this.mob, set, f, j, this.maxVisitedNodesMultiplier); - - this.level.getProfiler().pop(); - if (pathentity != null && pathentity.getTarget() != null) { - this.targetPos = pathentity.getTarget(); -- this.reachRange = distance; -+ this.reachRange = j; - this.resetStuckTimeout(); - } - + BlockPos blockPos = useHeadPos ? this.mob.blockPosition().above() : this.mob.blockPosition(); + int i = (int)(followRange + (float)range); diff --git a/patches/server-remapped/0078-Sanitise-RegionFileCache-and-make-configurable.patch b/patches/server/0073-Sanitise-RegionFileCache-and-make-configurable.patch similarity index 92% rename from patches/server-remapped/0078-Sanitise-RegionFileCache-and-make-configurable.patch rename to patches/server/0073-Sanitise-RegionFileCache-and-make-configurable.patch index 95fc3262c8..b31cdf5814 100644 --- a/patches/server-remapped/0078-Sanitise-RegionFileCache-and-make-configurable.patch +++ b/patches/server/0073-Sanitise-RegionFileCache-and-make-configurable.patch @@ -25,10 +25,10 @@ index 716f285e67019b8a62922d09c15883c99f9421aa..439dcc6effdc91830d2b7ede90639829 + } } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 97a58da9d64d812942ceb71426d35b490bbbe817..f33a5fc725d1d5e895f8878d82ebc4172237ad29 100644 +index 1ed8232493c94bc0cf28ef8d4b647cb84bd3fe32..3c82f98a34a5911fdb9e3ba66c54d25f6944fd07 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -33,7 +33,7 @@ public final class RegionFileStorage implements AutoCloseable { +@@ -35,7 +35,7 @@ public final class RegionFileStorage implements AutoCloseable { if (regionfile != null) { return regionfile; } else { diff --git a/patches/server-remapped/0079-Do-not-load-chunks-for-Pathfinding.patch b/patches/server/0074-Do-not-load-chunks-for-Pathfinding.patch similarity index 55% rename from patches/server-remapped/0079-Do-not-load-chunks-for-Pathfinding.patch rename to patches/server/0074-Do-not-load-chunks-for-Pathfinding.patch index dcc5c72d1e..98b2ec3b26 100644 --- a/patches/server-remapped/0079-Do-not-load-chunks-for-Pathfinding.patch +++ b/patches/server/0074-Do-not-load-chunks-for-Pathfinding.patch @@ -5,64 +5,64 @@ Subject: [PATCH] Do not load chunks for Pathfinding diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index ae8d430382b20ddd837c47e39515c7995f25312a..25bc3adfad956157cef0953e6e632b7b7e352f3a 100644 +index e6a2f836e70a267da36ec87e0df68e36bae3626c..6c063351c76e92a8a91142a12db846d1c1f11921 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -48,7 +48,7 @@ public abstract class PathNavigation { +@@ -46,7 +46,7 @@ public abstract class PathNavigation { private BlockPos targetPos; private int reachRange; - private float maxVisitedNodesMultiplier; + private float maxVisitedNodesMultiplier = 1.0F; - private final PathFinder pathFinder; + private final PathFinder pathFinder; public PathFinder getPathfinder() { return this.pathFinder; } // Paper - OBFHELPER private boolean isStuck; public PathNavigation(Mob mob, Level world) { diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -index 99f3f0b895295229b75d93e98141c0cd75789b69..ba8ee93032aabe7ec4ecf52d452e1a580d6ebc20 100644 +index e855754bdb8431efc06c77b42d9a90b870abab8d..800d464207026d145056b39b298045121342b899 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -@@ -20,7 +20,7 @@ public class PathFinder { - +@@ -21,7 +21,7 @@ public class PathFinder { + private static final float FUDGING = 1.5F; private final Node[] neighbors = new Node[32]; private final int maxVisitedNodes; - private final NodeEvaluator nodeEvaluator; + private final NodeEvaluator nodeEvaluator; public NodeEvaluator getPathfinder() { return this.nodeEvaluator; } // Paper - OBFHELPER + private static final boolean DEBUG = false; private final BinaryHeap openSet = new BinaryHeap(); - public PathFinder(NodeEvaluator pathNodeMaker, int range) { diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java -index 0b378348cb9e9576e2a209e651264e2caccfd182..7ae24381b91c282745b7fe5f6897865e74bc0acf 100644 +index 204ed5665adf2df7252fe2d21872db6956415311..b37acb6e6e253529a38f44a518a02c7747d3145e 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java -@@ -479,7 +479,12 @@ public class WalkNodeEvaluator extends NodeEvaluator { - for (int j1 = -1; j1 <= 1; ++j1) { - if (l != 0 || j1 != 0) { - blockposition_mutableblockposition.set(i + l, j + i1, k + j1); -- BlockState iblockdata = iblockaccess.getBlockState(blockposition_mutableblockposition); +@@ -453,7 +453,12 @@ public class WalkNodeEvaluator extends NodeEvaluator { + for(int n = -1; n <= 1; ++n) { + if (l != 0 || n != 0) { + pos.set(i + l, j + m, k + n); +- BlockState blockState = world.getBlockState(pos); + // Paper start -+ BlockState iblockdata = iblockaccess.getTypeIfLoaded(blockposition_mutableblockposition); -+ if (iblockdata == null) { -+ pathtype = BlockPathTypes.BLOCKED; ++ BlockState blockState = world.getTypeIfLoaded(pos); ++ if (blockState == null) { ++ return BlockPathTypes.BLOCKED; + } else { + // Paper end - - if (iblockdata.is(Blocks.CACTUS)) { + if (blockState.is(Blocks.CACTUS)) { return BlockPathTypes.DANGER_CACTUS; -@@ -496,6 +501,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { - if (iblockaccess.getFluidState(blockposition_mutableblockposition).is((Tag) FluidTags.WATER)) { + } +@@ -469,6 +474,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { + if (world.getFluidState(pos).is(FluidTags.WATER)) { return BlockPathTypes.WATER_BORDER; } + } // Paper } } } -@@ -505,7 +511,8 @@ public class WalkNodeEvaluator extends NodeEvaluator { +@@ -478,7 +484,8 @@ public class WalkNodeEvaluator extends NodeEvaluator { } - protected static BlockPathTypes getBlockPathTypeRaw(BlockGetter iblockaccess, BlockPos blockposition) { -- BlockState iblockdata = iblockaccess.getBlockState(blockposition); -+ BlockState iblockdata = iblockaccess.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return BlockPathTypes.BLOCKED; // Paper - Block block = iblockdata.getBlock(); - Material material = iblockdata.getMaterial(); - + protected static BlockPathTypes getBlockPathTypeRaw(BlockGetter world, BlockPos pos) { +- BlockState blockState = world.getBlockState(pos); ++ BlockState blockState = world.getTypeIfLoaded(pos); // Paper ++ if (blockState == null) return BlockPathTypes.BLOCKED; // Paper + Block block = blockState.getBlock(); + Material material = blockState.getMaterial(); + if (blockState.isAir()) { From c56800c6fbe5d03beeef79613e12789a653a5608 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Fri, 11 Jun 2021 19:23:18 -0700 Subject: [PATCH 031/226] Add ASM dep to API and fix issues from title packet changes with bungee api --- patches/api/0024-Use-ASM-for-event-executors.patch | 13 +++++++++++++ .../0047-Player-Tab-List-and-Title-APIs.patch | 14 ++++++++------ ...igurable-inter-world-teleportation-safety.patch | 4 ++-- .../server/0056-Complete-resource-pack-API.patch | 4 ++-- ...-health-absorb-values-and-repair-bad-data.patch | 4 ++-- 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/patches/api/0024-Use-ASM-for-event-executors.patch b/patches/api/0024-Use-ASM-for-event-executors.patch index 5ecb88e4ba..6c76c6b4f0 100644 --- a/patches/api/0024-Use-ASM-for-event-executors.patch +++ b/patches/api/0024-Use-ASM-for-event-executors.patch @@ -5,6 +5,19 @@ Subject: [PATCH] Use ASM for event executors. Uses method handles for private or static methods. +diff --git a/build.gradle.kts b/build.gradle.kts +index 4c197e7d9966f8789e6709461e59fc89355afd9c..9451f8660ec248619383d516df4b95e20e24828a 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -22,6 +22,8 @@ dependencies { + api("net.kyori:adventure-text-serializer-gson") + api("net.kyori:adventure-text-serializer-legacy") + api("net.kyori:adventure-text-serializer-plain") ++ api("org.ow2.asm:asm:9.0") ++ api("org.ow2.asm:asm-commons:9.0") + + compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/pom.xml b/pom.xml index cae43ce5c1287a4cd117fd069d34ebc1b64b7fdb..2c757ffb2253748c6a81f9b373290108209b6ff2 100644 --- a/pom.xml diff --git a/patches/server/0047-Player-Tab-List-and-Title-APIs.patch b/patches/server/0047-Player-Tab-List-and-Title-APIs.patch index 2e8c67a029..5a6bb6c55d 100644 --- a/patches/server/0047-Player-Tab-List-and-Title-APIs.patch +++ b/patches/server/0047-Player-Tab-List-and-Title-APIs.patch @@ -33,7 +33,7 @@ index 02d19fa4abdee0c8331734932a83e64694356030..969aea457e76b853e34a67a8fd07e0ea public static MutableComponent fromJson(String json) { return (MutableComponent) GsonHelper.fromJson(Component.Serializer.GSON, json, MutableComponent.class, false); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 1392d4d5027b3d972b2196af7b19fb409977fb8d..6401bdeeaa42ffe1e415553c94f0ec597b85df0c 100644 +index 1392d4d5027b3d972b2196af7b19fb409977fb8d..145f1ae878a6a6d91f291573f150c66363f151fd 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1,5 +1,6 @@ @@ -43,7 +43,7 @@ index 1392d4d5027b3d972b2196af7b19fb409977fb8d..6401bdeeaa42ffe1e415553c94f0ec59 import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import com.google.common.io.BaseEncoding; -@@ -241,6 +242,96 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -241,6 +242,98 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } } @@ -76,12 +76,13 @@ index 1392d4d5027b3d972b2196af7b19fb409977fb8d..6401bdeeaa42ffe1e415553c94f0ec59 + + @Override + public void setTitleTimes(int fadeInTicks, int stayTicks, int fadeOutTicks) { -+ getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.TIMES, (BaseComponent[]) null, fadeInTicks, stayTicks, fadeOutTicks)); ++ getHandle().connection.send(new ClientboundSetTitlesAnimationPacket(fadeInTicks, stayTicks, fadeOutTicks)); + } + + @Override + public void setSubtitle(BaseComponent[] subtitle) { -+ getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.SUBTITLE, subtitle, 0, 0, 0)); ++ final String json = net.md_5.bungee.chat.ComponentSerializer.toString(subtitle); ++ getHandle().connection.send(new ClientboundSetSubtitleTextPacket(Component.Serializer.fromJson(json))); + } + + @Override @@ -91,7 +92,8 @@ index 1392d4d5027b3d972b2196af7b19fb409977fb8d..6401bdeeaa42ffe1e415553c94f0ec59 + + @Override + public void showTitle(BaseComponent[] title) { -+ getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.TITLE, title, 0, 0, 0)); ++ final String json = net.md_5.bungee.chat.ComponentSerializer.toString(title); ++ getHandle().connection.send(new ClientboundSetTitleTextPacket(Component.Serializer.fromJson(json))); + } + + @Override @@ -133,7 +135,7 @@ index 1392d4d5027b3d972b2196af7b19fb409977fb8d..6401bdeeaa42ffe1e415553c94f0ec59 + + @Override + public void hideTitle() { -+ getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.CLEAR, (BaseComponent[]) null, 0, 0, 0)); ++ getHandle().connection.send(new ClientboundClearTitlesPacket(false)); + } + // Paper end + diff --git a/patches/server/0051-Configurable-inter-world-teleportation-safety.patch b/patches/server/0051-Configurable-inter-world-teleportation-safety.patch index 0e975fba21..d8ac211487 100644 --- a/patches/server/0051-Configurable-inter-world-teleportation-safety.patch +++ b/patches/server/0051-Configurable-inter-world-teleportation-safety.patch @@ -30,10 +30,10 @@ index 670efbe53241a0ae32d618c83da601ccc1f26e37..abbbe1786eb68af02f9d39650aad730a + } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 6401bdeeaa42ffe1e415553c94f0ec597b85df0c..d7c3bb17faf667ec90c967fe3c5ea6094faf0226 100644 +index 145f1ae878a6a6d91f291573f150c66363f151fd..34c249bff7f32aa3e58c04a1bc0f65f5f410d714 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -862,7 +862,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -864,7 +864,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (fromWorld == toWorld) { entity.connection.teleport(to); } else { diff --git a/patches/server/0056-Complete-resource-pack-API.patch b/patches/server/0056-Complete-resource-pack-API.patch index d2e790a554..be7144661d 100644 --- a/patches/server/0056-Complete-resource-pack-API.patch +++ b/patches/server/0056-Complete-resource-pack-API.patch @@ -23,7 +23,7 @@ index b38ca69d37d7f1af0e34297f45e63a98da754e35..714fb0d766b654ad05134dea9b1e1b62 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index d7c3bb17faf667ec90c967fe3c5ea6094faf0226..074b9e2aa9162aec64007cbf235ccc965db70055 100644 +index 34c249bff7f32aa3e58c04a1bc0f65f5f410d714..6aabe32512abc974e114e273a41e09804b349cb9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -141,6 +141,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @@ -37,7 +37,7 @@ index d7c3bb17faf667ec90c967fe3c5ea6094faf0226..074b9e2aa9162aec64007cbf235ccc96 public CraftPlayer(CraftServer server, ServerPlayer entity) { super(server, entity); -@@ -1873,6 +1877,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1875,6 +1879,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public boolean getAffectsSpawning() { return this.getHandle().affectsSpawning; } diff --git a/patches/server/0065-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/patches/server/0065-handle-NaN-health-absorb-values-and-repair-bad-data.patch index 2addfbb9df..d2ec2e60a6 100644 --- a/patches/server/0065-handle-NaN-health-absorb-values-and-repair-bad-data.patch +++ b/patches/server/0065-handle-NaN-health-absorb-values-and-repair-bad-data.patch @@ -49,10 +49,10 @@ index 89db2afd198366ab94c9c074890aa668d3771a79..83eaa3c6581c1a3f588278124fed4c81 } + diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 074b9e2aa9162aec64007cbf235ccc965db70055..7d19f877e66ef10c977b8072732bb16bd978e0de 100644 +index 6aabe32512abc974e114e273a41e09804b349cb9..2f8bcf5290d02cfc41496fd3ae8a63c08d514af8 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1679,6 +1679,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1681,6 +1681,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void setRealHealth(double health) { From d43c31d1419a9d8f8a8459f91982ef37cbe3de43 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Fri, 11 Jun 2021 20:07:57 -0700 Subject: [PATCH 032/226] patches --- ...Remove-unused-World-Tile-Entity-List.patch | 2 + .../0088-Don-t-tick-Skulls-unused-code.patch | 1 + .../0084-Optimize-DataBits.patch | 84 ------------------- ...075-Add-PlayerUseUnknownEntityEvent.patch} | 20 ++--- ...DebugInfo-not-initialized-on-client.patch} | 8 +- ...Configurable-Grass-Spread-Tick-Rate.patch} | 4 +- ...-BlockPlaceEvent-triggering-physics.patch} | 4 +- patches/server/0079-Optimize-DataBits.patch | 82 ++++++++++++++++++ ...illa-per-world-scoreboard-coloring-.patch} | 0 ...d-for-setting-passengers-on-players.patch} | 6 +- 10 files changed, 106 insertions(+), 105 deletions(-) rename patches/{server-remapped => removed/1.17}/0087-Remove-unused-World-Tile-Entity-List.patch (99%) rename patches/{server-remapped => removed/1.17}/0088-Don-t-tick-Skulls-unused-code.patch (98%) delete mode 100644 patches/server-remapped/0084-Optimize-DataBits.patch rename patches/{server-remapped/0080-Add-PlayerUseUnknownEntityEvent.patch => server/0075-Add-PlayerUseUnknownEntityEvent.patch} (66%) rename patches/{server-remapped/0081-Fix-reducedDebugInfo-not-initialized-on-client.patch => server/0076-Fix-reducedDebugInfo-not-initialized-on-client.patch} (80%) rename patches/{server-remapped/0082-Configurable-Grass-Spread-Tick-Rate.patch => server/0077-Configurable-Grass-Spread-Tick-Rate.patch} (92%) rename patches/{server-remapped/0083-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch => server/0078-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch} (84%) create mode 100644 patches/server/0079-Optimize-DataBits.patch rename patches/{server-remapped/0085-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch => server/0080-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch} (100%) rename patches/{server-remapped/0086-Workaround-for-setting-passengers-on-players.patch => server/0081-Workaround-for-setting-passengers-on-players.patch} (83%) diff --git a/patches/server-remapped/0087-Remove-unused-World-Tile-Entity-List.patch b/patches/removed/1.17/0087-Remove-unused-World-Tile-Entity-List.patch similarity index 99% rename from patches/server-remapped/0087-Remove-unused-World-Tile-Entity-List.patch rename to patches/removed/1.17/0087-Remove-unused-World-Tile-Entity-List.patch index d96a9f686a..46f6aa73e4 100644 --- a/patches/server-remapped/0087-Remove-unused-World-Tile-Entity-List.patch +++ b/patches/removed/1.17/0087-Remove-unused-World-Tile-Entity-List.patch @@ -5,6 +5,8 @@ Subject: [PATCH] Remove unused World Tile Entity List Massive hit to performance and it is completely unnecessary. +Removed during 1.17 update - no longer logically applies + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index f7eddb39985072afeb79ec0cbfc084d7e84638e6..bb99d9fe5e274318d8480a6de2c45b0a57351f77 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/server-remapped/0088-Don-t-tick-Skulls-unused-code.patch b/patches/removed/1.17/0088-Don-t-tick-Skulls-unused-code.patch similarity index 98% rename from patches/server-remapped/0088-Don-t-tick-Skulls-unused-code.patch rename to patches/removed/1.17/0088-Don-t-tick-Skulls-unused-code.patch index 42e534b702..a3fc8b95d3 100644 --- a/patches/server-remapped/0088-Don-t-tick-Skulls-unused-code.patch +++ b/patches/removed/1.17/0088-Don-t-tick-Skulls-unused-code.patch @@ -3,6 +3,7 @@ From: Aikar Date: Wed, 13 Apr 2016 00:30:10 -0400 Subject: [PATCH] Don't tick Skulls - unused code +No longer needed in 1.17 diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java index 6a46517e4026971d8c050c685c710883b5976fa3..eebaeaccc3ba1a9ec089d84b8de6c9d36034868f 100644 diff --git a/patches/server-remapped/0084-Optimize-DataBits.patch b/patches/server-remapped/0084-Optimize-DataBits.patch deleted file mode 100644 index 7b5057a4e9..0000000000 --- a/patches/server-remapped/0084-Optimize-DataBits.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Apr 2016 21:38:58 -0400 -Subject: [PATCH] Optimize DataBits - -Remove Debug checks as these are super hot and causing noticeable hits - -Before: http://i.imgur.com/nQsMzAE.png -After: http://i.imgur.com/nJ46crB.png - -Optimize redundant converting of static fields into an unsigned long each call by precomputing it in ctor - -diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java -index 97bde5f8402452e59b0da94edfe1b970cdb86748..dd84984f28484cf7129c294222696784e128221a 100644 ---- a/src/main/java/net/minecraft/util/BitStorage.java -+++ b/src/main/java/net/minecraft/util/BitStorage.java -@@ -13,8 +13,8 @@ public class BitStorage { - private final long mask; - private final int size; - private final int valuesPerLong; -- private final int divideMul; -- private final int divideAdd; -+ private final int divideMul;private final long g_unsigned; // Paper - referenced in b(int) with 2 Integer.toUnsignedLong calls -+ private final int divideAdd;private final long h_unsigned; // Paper - private final int divideShift; - - public BitStorage(int elementBits, int size) { -@@ -29,8 +29,8 @@ public class BitStorage { - this.valuesPerLong = (char) (64 / elementBits); - int k = 3 * (this.valuesPerLong - 1); - -- this.divideMul = BitStorage.MAGIC[k + 0]; -- this.divideAdd = BitStorage.MAGIC[k + 1]; -+ this.divideMul = BitStorage.MAGIC[k + 0]; this.g_unsigned = Integer.toUnsignedLong(this.divideMul); // Paper -+ this.divideAdd = BitStorage.MAGIC[k + 1]; this.h_unsigned = Integer.toUnsignedLong(this.divideAdd); // Paper - this.divideShift = BitStorage.MAGIC[k + 2]; - int l = (size + this.valuesPerLong - 1) / this.valuesPerLong; - -@@ -47,15 +47,15 @@ public class BitStorage { - } - - private int cellIndex(int i) { -- long j = Integer.toUnsignedLong(this.divideMul); -- long k = Integer.toUnsignedLong(this.divideAdd); -+ //long j = Integer.toUnsignedLong(this.g); // Paper -+ //long k = Integer.toUnsignedLong(this.h); // Paper - -- return (int) ((long) i * j + k >> 32 >> this.divideShift); -+ return (int) ((long) i * this.g_unsigned + this.h_unsigned >> 32 >> this.divideShift); // Paper - } - -- public int getAndSet(int index, int value) { -- Validate.inclusiveBetween(0L, (long) (this.size - 1), (long) index); -- Validate.inclusiveBetween(0L, this.mask, (long) value); -+ public final int getAndSet(int index, int value) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper -+ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper - int k = this.cellIndex(index); - long l = this.data[k]; - int i1 = (index - k * this.valuesPerLong) * this.bits; -@@ -65,9 +65,9 @@ public class BitStorage { - return j1; - } - -- public void set(int index, int value) { -- Validate.inclusiveBetween(0L, (long) (this.size - 1), (long) index); -- Validate.inclusiveBetween(0L, this.mask, (long) value); -+ public final void set(int index, int value) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper -+ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper - int k = this.cellIndex(index); - long l = this.data[k]; - int i1 = (index - k * this.valuesPerLong) * this.bits; -@@ -75,8 +75,8 @@ public class BitStorage { - this.data[k] = l & ~(this.mask << i1) | ((long) value & this.mask) << i1; - } - -- public int get(int index) { -- Validate.inclusiveBetween(0L, (long) (this.size - 1), (long) index); -+ public final int get(int index) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper - int j = this.cellIndex(index); - long k = this.data[j]; - int l = (index - j * this.valuesPerLong) * this.bits; diff --git a/patches/server-remapped/0080-Add-PlayerUseUnknownEntityEvent.patch b/patches/server/0075-Add-PlayerUseUnknownEntityEvent.patch similarity index 66% rename from patches/server-remapped/0080-Add-PlayerUseUnknownEntityEvent.patch rename to patches/server/0075-Add-PlayerUseUnknownEntityEvent.patch index c91bb4d9ec..ee592bd203 100644 --- a/patches/server-remapped/0080-Add-PlayerUseUnknownEntityEvent.patch +++ b/patches/server/0075-Add-PlayerUseUnknownEntityEvent.patch @@ -5,23 +5,23 @@ Subject: [PATCH] Add PlayerUseUnknownEntityEvent diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java -index 9ff5b938f97da5ca1f13fd2bcbf3d13e8b8f760c..e1d219550006d22b0a8e949e820488c6ed96dc58 100644 +index 1b316ecf2d8725b9c91a4869e6c2362c1443160d..964101d314f182574efba09bfe3907fbbf97fb13 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java -@@ -11,7 +11,7 @@ import net.minecraft.world.phys.Vec3; +@@ -10,7 +10,7 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.phys.Vec3; public class ServerboundInteractPacket implements Packet { - -- private int entityId; -+ private int entityId; public int getEntityId() { return this.entityId; } // Paper - add accessor - private ServerboundInteractPacket.Action action; - private Vec3 location; - private InteractionHand hand; +- private final int entityId; ++ private final int entityId; public final int getEntityId() { return this.entityId; } // Paper - add accessor + private final ServerboundInteractPacket.Action action; + private final boolean usingSecondaryAction; + static final ServerboundInteractPacket.Action ATTACK_ACTION = new ServerboundInteractPacket.Action() { diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 73683ba59d0aff3a61f555b4ae15753e9e4e6141..e2bfe8e916c9e59af81627ea0ee449970527034d 100644 +index 714fb0d766b654ad05134dea9b1e1b628a939993..c8f17466fe4ccfd8fa727e15281d015c2de2aaee 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2198,6 +2198,16 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1630,6 +1630,16 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } } } diff --git a/patches/server-remapped/0081-Fix-reducedDebugInfo-not-initialized-on-client.patch b/patches/server/0076-Fix-reducedDebugInfo-not-initialized-on-client.patch similarity index 80% rename from patches/server-remapped/0081-Fix-reducedDebugInfo-not-initialized-on-client.patch rename to patches/server/0076-Fix-reducedDebugInfo-not-initialized-on-client.patch index d10d109cb2..ff403ff94d 100644 --- a/patches/server-remapped/0081-Fix-reducedDebugInfo-not-initialized-on-client.patch +++ b/patches/server/0076-Fix-reducedDebugInfo-not-initialized-on-client.patch @@ -5,13 +5,13 @@ Subject: [PATCH] Fix reducedDebugInfo not initialized on client diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index a63babe123fad398b07685ec57cd88756435457c..aa440a6341a6d30aba8fd5f6bcd122bd5d8760cd 100644 +index 8e9d0ca8aa2b1403fc65ed8d792525047a610a3a..ce72102870075fffd8be6f32230ceae269ea4f9c 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -242,6 +242,7 @@ public abstract class PlayerList { - playerconnection.send(new ClientboundSetCarriedItemPacket(player.inventory.selected)); +@@ -246,6 +246,7 @@ public abstract class PlayerList { + playerconnection.send(new ClientboundSetCarriedItemPacket(player.getInventory().selected)); playerconnection.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); - playerconnection.send(new ClientboundUpdateTagsPacket(this.server.getTags())); + playerconnection.send(new ClientboundUpdateTagsPacket(this.server.getTags().serializeToNetwork((RegistryAccess) this.registryHolder))); + playerconnection.send(new ClientboundEntityEventPacket(player, (byte) (worldserver1.getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23))); // Paper - fix this rule not being initialized on the client this.sendPlayerPermissionLevel(player); player.getStats().markAllDirty(); diff --git a/patches/server-remapped/0082-Configurable-Grass-Spread-Tick-Rate.patch b/patches/server/0077-Configurable-Grass-Spread-Tick-Rate.patch similarity index 92% rename from patches/server-remapped/0082-Configurable-Grass-Spread-Tick-Rate.patch rename to patches/server/0077-Configurable-Grass-Spread-Tick-Rate.patch index 8481cb94a1..a6141f1b5a 100644 --- a/patches/server-remapped/0082-Configurable-Grass-Spread-Tick-Rate.patch +++ b/patches/server/0077-Configurable-Grass-Spread-Tick-Rate.patch @@ -20,7 +20,7 @@ index 74ba5dbb83c13ce1721619b755036a7864a1fb90..db2dddd12f54e6d15916c4cee6236765 + } } diff --git a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java -index d54f097afc455a01486d7f7459b0cfc4ab4f3970..813a5b0598eca28aa173cd6e34bc16381f313604 100644 +index 4c6c91deacddc4f383ecb6986e8e265a4e8eb7e6..d8c29bc282365b68951a39b4b2590b19957d578b 100644 --- a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java +++ b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java @@ -3,6 +3,7 @@ package net.minecraft.world.level.block; @@ -36,6 +36,6 @@ index d54f097afc455a01486d7f7459b0cfc4ab4f3970..813a5b0598eca28aa173cd6e34bc1638 @Override public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) { + if (this instanceof GrassBlock && world.paperConfig.grassUpdateRate != 1 && (world.paperConfig.grassUpdateRate < 1 || (MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig.grassUpdateRate != 0)) { return; } // Paper - if (!canBeGrass(state, (LevelReader) world, pos)) { + if (!SpreadingSnowyDirtBlock.canBeGrass(state, (LevelReader) world, pos)) { // CraftBukkit start if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { diff --git a/patches/server-remapped/0083-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/patches/server/0078-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch similarity index 84% rename from patches/server-remapped/0083-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch rename to patches/server/0078-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch index 5d706f6263..93acbbfe0a 100644 --- a/patches/server-remapped/0083-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch +++ b/patches/server/0078-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix Cancelling BlockPlaceEvent triggering physics diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index d47ed15382f98aabd509e32a3c202a91088adf6b..89a6a0b4235cfcc1d3ad68ff59a21fa60df4508f 100644 +index 81a8e314b5073a5888a3c04d53ff279c8142a7d4..fa567322ca3f09d81479826b0119ddc922c41d11 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -518,6 +518,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -538,6 +538,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public void setBlocksDirty(BlockPos pos, BlockState old, BlockState updated) {} public void updateNeighborsAt(BlockPos pos, Block block) { diff --git a/patches/server/0079-Optimize-DataBits.patch b/patches/server/0079-Optimize-DataBits.patch new file mode 100644 index 0000000000..2e60c8aeec --- /dev/null +++ b/patches/server/0079-Optimize-DataBits.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Apr 2016 21:38:58 -0400 +Subject: [PATCH] Optimize DataBits + +Remove Debug checks as these are super hot and causing noticeable hits + +Before: http://i.imgur.com/nQsMzAE.png +After: http://i.imgur.com/nJ46crB.png + +Optimize redundant converting of static fields into an unsigned long each call by precomputing it in ctor + +diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java +index 3a2e8bdc215a6af604bfaad01b670a361eb8068d..9b955a027bd2c3cbcfa659a41a6687221c5fea63 100644 +--- a/src/main/java/net/minecraft/util/BitStorage.java ++++ b/src/main/java/net/minecraft/util/BitStorage.java +@@ -12,8 +12,8 @@ public class BitStorage { + private final long mask; + private final int size; + private final int valuesPerLong; +- private final int divideMul; +- private final int divideAdd; ++ private final int divideMul; private final long divideMulUnsigned; // Paper - referenced in b(int) with 2 Integer.toUnsignedLong calls ++ private final int divideAdd; private final long divideAddUnsigned; // Paper + private final int divideShift; + + public BitStorage(int elementBits, int size) { +@@ -27,8 +27,8 @@ public class BitStorage { + this.mask = (1L << elementBits) - 1L; + this.valuesPerLong = (char)(64 / elementBits); + int i = 3 * (this.valuesPerLong - 1); +- this.divideMul = MAGIC[i + 0]; +- this.divideAdd = MAGIC[i + 1]; ++ this.divideMul = BitStorage.MAGIC[i + 0]; this.divideMulUnsigned = Integer.toUnsignedLong(this.divideMul); // Paper ++ this.divideAdd = BitStorage.MAGIC[i + 1]; this.divideAddUnsigned = Integer.toUnsignedLong(this.divideAdd); // Paper + this.divideShift = MAGIC[i + 2]; + int j = (size + this.valuesPerLong - 1) / this.valuesPerLong; + if (storage != null) { +@@ -44,14 +44,14 @@ public class BitStorage { + } + + private int cellIndex(int index) { +- long l = Integer.toUnsignedLong(this.divideMul); +- long m = Integer.toUnsignedLong(this.divideAdd); +- return (int)((long)index * l + m >> 32 >> this.divideShift); ++ //long l = Integer.toUnsignedLong(this.divideMul); // Paper ++ //long m = Integer.toUnsignedLong(this.divideAdd); // Paper ++ return (int) ((long) index * this.divideMulUnsigned + this.divideAddUnsigned >> 32 >> this.divideShift); // Paper + } + +- public int getAndSet(int index, int value) { +- Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); +- Validate.inclusiveBetween(0L, this.mask, (long)value); ++ public final int getAndSet(int index, int value) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); // Paper ++ //Validate.inclusiveBetween(0L, this.mask, (long)value); // Paper + int i = this.cellIndex(index); + long l = this.data[i]; + int j = (index - i * this.valuesPerLong) * this.bits; +@@ -60,17 +60,17 @@ public class BitStorage { + return k; + } + +- public void set(int index, int value) { +- Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); +- Validate.inclusiveBetween(0L, this.mask, (long)value); ++ public final void set(int index, int value) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); // Paper ++ //Validate.inclusiveBetween(0L, this.mask, (long)value); // Paper + int i = this.cellIndex(index); + long l = this.data[i]; + int j = (index - i * this.valuesPerLong) * this.bits; + this.data[i] = l & ~(this.mask << j) | ((long)value & this.mask) << j; + } + +- public int get(int index) { +- Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); ++ public final int get(int index) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); + int i = this.cellIndex(index); + long l = this.data[i]; + int j = (index - i * this.valuesPerLong) * this.bits; diff --git a/patches/server-remapped/0085-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/patches/server/0080-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch similarity index 100% rename from patches/server-remapped/0085-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch rename to patches/server/0080-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch diff --git a/patches/server-remapped/0086-Workaround-for-setting-passengers-on-players.patch b/patches/server/0081-Workaround-for-setting-passengers-on-players.patch similarity index 83% rename from patches/server-remapped/0086-Workaround-for-setting-passengers-on-players.patch rename to patches/server/0081-Workaround-for-setting-passengers-on-players.patch index c2fdc7667a..0a081245dd 100644 --- a/patches/server-remapped/0086-Workaround-for-setting-passengers-on-players.patch +++ b/patches/server/0081-Workaround-for-setting-passengers-on-players.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Workaround for setting passengers on players SPIGOT-1915 & GH-114 diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b7d5a718375083a4162df4bb41de3acd57b297fb..b264cbe5f91da9e31c5fd00ee285735a19aaad35 100644 +index 2f8bcf5290d02cfc41496fd3ae8a63c08d514af8..b93a02dce55952321874528016ea48e5a35bd772 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -870,6 +870,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -873,6 +873,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return true; } @@ -26,4 +26,4 @@ index b7d5a718375083a4162df4bb41de3acd57b297fb..b264cbe5f91da9e31c5fd00ee285735a + @Override public void setSneaking(boolean sneak) { - getHandle().setShiftKeyDown(sneak); + this.getHandle().setShiftKeyDown(sneak); From 2dc0a31f5ce6d493b0d786b1d7c4a9645489815e Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Fri, 11 Jun 2021 20:37:02 -0700 Subject: [PATCH 033/226] fix PlayerUseUnknownEntityEvent patch (#5800) --- ...033-Add-PlayerUseUnknownEntityEvent.patch} | 0 ...0075-Add-PlayerUseUnknownEntityEvent.patch | 58 ++++++++++++++----- 2 files changed, 45 insertions(+), 13 deletions(-) rename patches/{api-unmapped/0032-Add-PlayerUseUnknownEntityEvent.patch => api/0033-Add-PlayerUseUnknownEntityEvent.patch} (100%) diff --git a/patches/api-unmapped/0032-Add-PlayerUseUnknownEntityEvent.patch b/patches/api/0033-Add-PlayerUseUnknownEntityEvent.patch similarity index 100% rename from patches/api-unmapped/0032-Add-PlayerUseUnknownEntityEvent.patch rename to patches/api/0033-Add-PlayerUseUnknownEntityEvent.patch diff --git a/patches/server/0075-Add-PlayerUseUnknownEntityEvent.patch b/patches/server/0075-Add-PlayerUseUnknownEntityEvent.patch index ee592bd203..cb09c9b1c8 100644 --- a/patches/server/0075-Add-PlayerUseUnknownEntityEvent.patch +++ b/patches/server/0075-Add-PlayerUseUnknownEntityEvent.patch @@ -5,36 +5,68 @@ Subject: [PATCH] Add PlayerUseUnknownEntityEvent diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java -index 1b316ecf2d8725b9c91a4869e6c2362c1443160d..964101d314f182574efba09bfe3907fbbf97fb13 100644 +index 1b316ecf2d8725b9c91a4869e6c2362c1443160d..70d309ddb215c62805b6ee13be50d8f93cdc38ba 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java -@@ -10,7 +10,7 @@ import net.minecraft.world.entity.Entity; +@@ -10,8 +10,8 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; public class ServerboundInteractPacket implements Packet { - private final int entityId; +- private final ServerboundInteractPacket.Action action; + private final int entityId; public final int getEntityId() { return this.entityId; } // Paper - add accessor - private final ServerboundInteractPacket.Action action; ++ private final ServerboundInteractPacket.Action action; public final ServerboundInteractPacket.ActionType getActionType() { return this.action.getType(); } // Paper - add accessor private final boolean usingSecondaryAction; static final ServerboundInteractPacket.Action ATTACK_ACTION = new ServerboundInteractPacket.Action() { + @Override +@@ -88,7 +88,7 @@ public class ServerboundInteractPacket implements Packet public + INTERACT(ServerboundInteractPacket.InteractionAction::new), + ATTACK((friendlyByteBuf) -> { + return ServerboundInteractPacket.ATTACK_ACTION; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 714fb0d766b654ad05134dea9b1e1b628a939993..c8f17466fe4ccfd8fa727e15281d015c2de2aaee 100644 +index 714fb0d766b654ad05134dea9b1e1b628a939993..6cd0fd57503723a58b30a7c33b1c863afc2401e2 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1630,6 +1630,16 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser - } +@@ -2202,8 +2202,37 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + }); } } + // Paper start - fire event + else { -+ this.craftServer.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( -+ this.getPlayer(), -+ packet.getEntityId(), -+ packet.getAction() == ServerboundInteractPacket.Action.ATTACK, -+ packet.getHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND -+ )); ++ packet.dispatch(new net.minecraft.network.protocol.game.ServerboundInteractPacket.Handler() { ++ @Override ++ public void onInteraction(net.minecraft.world.InteractionHand hand) { ++ ServerGamePacketListenerImpl.this.callPlayerUseUnknownEntityEvent(packet, hand); ++ } ++ ++ @Override ++ public void onInteraction(net.minecraft.world.InteractionHand hand, net.minecraft.world.phys.Vec3 pos) { ++ ServerGamePacketListenerImpl.this.callPlayerUseUnknownEntityEvent(packet, hand); ++ } ++ ++ @Override ++ public void onAttack() { ++ ServerGamePacketListenerImpl.this.callPlayerUseUnknownEntityEvent(packet, net.minecraft.world.InteractionHand.MAIN_HAND); ++ } ++ }); + } -+ // Paper end ++ ++ } ++ private void callPlayerUseUnknownEntityEvent(ServerboundInteractPacket packet, InteractionHand hand) { ++ this.cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( ++ this.getCraftPlayer(), ++ packet.getEntityId(), ++ packet.getActionType() == ServerboundInteractPacket.ActionType.ATTACK, ++ hand == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND ++ )); } ++ // Paper end + @Override + public void handleClientCommand(ServerboundClientCommandPacket packet) { From 2920f9b9e5a66f896f5bc0f093015c9921015fd9 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Fri, 11 Jun 2021 21:38:04 -0700 Subject: [PATCH 034/226] some patches --- ...nt-to-allow-plugins-to-handle-clien.patch} | 0 .../0035-Arrow-pickup-rule-API.patch} | 0 ...tyRegainHealthEvent-isFastRegen-API.patch} | 0 .../0037-LootTable-API.patch} | 0 ...e-from-loading-chunks-wrongly-spread.patch | 5 + .../0082-Configurable-Player-Collision.patch} | 56 ++++---- ...nt-to-allow-plugins-to-handle-clien.patch} | 27 ++-- .../0084-Configurable-RCON-IP-address.patch} | 42 +++--- ...5-Implement-PlayerLocaleChangeEvent.patch} | 18 +-- ...tyRegainHealthEvent-isFastRegen-API.patch} | 6 +- ...to-configure-frosted_ice-properties.patch} | 20 +-- ...possibility-for-getServer-singleton.patch} | 20 +-- ...tem-frames-performance-and-bug-fixe.patch} | 86 ++++++------ ...API-Replenishable-Lootables-Feature.patch} | 128 +++++++++--------- 14 files changed, 197 insertions(+), 211 deletions(-) rename patches/{api-unmapped/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch => api/0034-Add-handshake-event-to-allow-plugins-to-handle-clien.patch} (100%) rename patches/{api-unmapped/0034-Arrow-pickup-rule-API.patch => api/0035-Arrow-pickup-rule-API.patch} (100%) rename patches/{api-unmapped/0035-EntityRegainHealthEvent-isFastRegen-API.patch => api/0036-EntityRegainHealthEvent-isFastRegen-API.patch} (100%) rename patches/{api-unmapped/0036-LootTable-API.patch => api/0037-LootTable-API.patch} (100%) rename patches/{server-remapped => removed/1.17}/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch (97%) rename patches/{server-remapped/0089-Configurable-Player-Collision.patch => server/0082-Configurable-Player-Collision.patch} (75%) rename patches/{server-remapped/0090-Add-handshake-event-to-allow-plugins-to-handle-clien.patch => server/0083-Add-handshake-event-to-allow-plugins-to-handle-clien.patch} (65%) rename patches/{server-remapped/0091-Configurable-RCON-IP-address.patch => server/0084-Configurable-RCON-IP-address.patch} (57%) rename patches/{server-remapped/0093-Implement-PlayerLocaleChangeEvent.patch => server/0085-Implement-PlayerLocaleChangeEvent.patch} (74%) rename patches/{server-remapped/0094-EntityRegainHealthEvent-isFastRegen-API.patch => server/0086-EntityRegainHealthEvent-isFastRegen-API.patch} (89%) rename patches/{server-remapped/0095-Add-ability-to-configure-frosted_ice-properties.patch => server/0087-Add-ability-to-configure-frosted_ice-properties.patch} (66%) rename patches/{server-remapped/0096-remove-null-possibility-for-getServer-singleton.patch => server/0088-remove-null-possibility-for-getServer-singleton.patch} (61%) rename patches/{server-remapped/0097-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch => server/0089-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch} (65%) rename patches/{server-remapped/0098-LootTable-API-Replenishable-Lootables-Feature.patch => server/0090-LootTable-API-Replenishable-Lootables-Feature.patch} (87%) diff --git a/patches/api-unmapped/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/patches/api/0034-Add-handshake-event-to-allow-plugins-to-handle-clien.patch similarity index 100% rename from patches/api-unmapped/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch rename to patches/api/0034-Add-handshake-event-to-allow-plugins-to-handle-clien.patch diff --git a/patches/api-unmapped/0034-Arrow-pickup-rule-API.patch b/patches/api/0035-Arrow-pickup-rule-API.patch similarity index 100% rename from patches/api-unmapped/0034-Arrow-pickup-rule-API.patch rename to patches/api/0035-Arrow-pickup-rule-API.patch diff --git a/patches/api-unmapped/0035-EntityRegainHealthEvent-isFastRegen-API.patch b/patches/api/0036-EntityRegainHealthEvent-isFastRegen-API.patch similarity index 100% rename from patches/api-unmapped/0035-EntityRegainHealthEvent-isFastRegen-API.patch rename to patches/api/0036-EntityRegainHealthEvent-isFastRegen-API.patch diff --git a/patches/api-unmapped/0036-LootTable-API.patch b/patches/api/0037-LootTable-API.patch similarity index 100% rename from patches/api-unmapped/0036-LootTable-API.patch rename to patches/api/0037-LootTable-API.patch diff --git a/patches/server-remapped/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch b/patches/removed/1.17/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch similarity index 97% rename from patches/server-remapped/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch rename to patches/removed/1.17/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch index 04b43eed1b..6301e162a3 100644 --- a/patches/server-remapped/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch +++ b/patches/removed/1.17/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch @@ -8,6 +8,11 @@ bad behavior. This also stops fire from spreading to illegal locations. + + +This shouldn't need to be included in post 1.14 versions, as blocks no longer tick without at least 1 radius +chunk loaded. + diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java index 700078c2fd536cc22351eadf51503efb9acd9df9..85170008de6e77cfb8e4f55ae440a8428d868af4 100644 --- a/src/main/java/net/minecraft/world/level/block/FireBlock.java diff --git a/patches/server-remapped/0089-Configurable-Player-Collision.patch b/patches/server/0082-Configurable-Player-Collision.patch similarity index 75% rename from patches/server-remapped/0089-Configurable-Player-Collision.patch rename to patches/server/0082-Configurable-Player-Collision.patch index 3ed6659147..655a296152 100644 --- a/patches/server-remapped/0089-Configurable-Player-Collision.patch +++ b/patches/server/0082-Configurable-Player-Collision.patch @@ -19,44 +19,44 @@ index 439dcc6effdc91830d2b7ede9063982998b37120..504efea7b6f50a0d17f4f353781953df + } } diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java -index 53f284b720d97ba8ce8fac90bc26e7930dcec6b2..d70e7079ea2c84edbc2a8501f115194e2a4ef2e4 100644 +index 8885220e4813b34627b42523834bbec995d8950d..4c9660176e783999301565790b8cf6f47b0d02a2 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java -@@ -112,7 +112,7 @@ public class ClientboundSetPlayerTeamPacket implements Packet toRemove = scoreboard.getTeams().stream().filter(team -> team.getName().startsWith("collideRule_")).map(PlayerTeam::getName).collect(java.util.stream.Collectors.toList()); ++ final ServerScoreboard scoreboard = this.getScoreboard(); ++ final java.util.Collection toRemove = scoreboard.getPlayerTeams().stream().filter(team -> team.getName().startsWith("collideRule_")).map(PlayerTeam::getName).collect(java.util.stream.Collectors.toList()); + for (String teamName : toRemove) { -+ scoreboard.removeTeam(scoreboard.getTeam(teamName)); // Clean up after ourselves ++ scoreboard.removePlayerTeam(scoreboard.getPlayersTeam(teamName)); // Clean up after ourselves + } + + if (!com.destroystokyo.paper.PaperConfig.enablePlayerCollisions) { + this.getPlayerList().collideRuleTeamName = org.apache.commons.lang3.StringUtils.left("collideRule_" + java.util.concurrent.ThreadLocalRandom.current().nextInt(), 16); -+ PlayerTeam collideTeam = scoreboard.createTeam(this.getPlayerList().collideRuleTeamName); ++ PlayerTeam collideTeam = scoreboard.addPlayerTeam(this.getPlayerList().collideRuleTeamName); + collideTeam.setSeeFriendlyInvisibles(false); // Because we want to mimic them not being on a team at all + } + // Paper end @@ -65,18 +65,18 @@ index f7763a773bce4d8d947c8c859fe84d8a601034c5..d639ead95c36985fa0f5a9c51898c423 this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); this.connection.acceptConnections(); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index aa440a6341a6d30aba8fd5f6bcd122bd5d8760cd..59fb19cfebe4f488fd02f02db31029d44b65e408 100644 +index ce72102870075fffd8be6f32230ceae269ea4f9c..b9c4428bc9653e81ed046bda94e248218c1fa9c9 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -79,6 +79,7 @@ import net.minecraft.world.level.storage.PlayerDataStorage; +@@ -85,6 +85,7 @@ import net.minecraft.world.level.storage.PlayerDataStorage; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.Objective; import net.minecraft.world.scores.PlayerTeam; -+import net.minecraft.world.scores.Scoreboard; ++import net.minecraft.world.scores.Scoreboard; // Paper import net.minecraft.world.scores.Team; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -@@ -141,6 +142,7 @@ public abstract class PlayerList { +@@ -146,6 +147,7 @@ public abstract class PlayerList { // CraftBukkit start private CraftServer cserver; private final Map playersByName = new java.util.HashMap<>(); @@ -84,28 +84,28 @@ index aa440a6341a6d30aba8fd5f6bcd122bd5d8760cd..59fb19cfebe4f488fd02f02db31029d4 public PlayerList(MinecraftServer server, RegistryAccess.RegistryHolder registryManager, PlayerDataStorage saveHandler, int maxPlayers) { this.cserver = server.server = new CraftServer((DedicatedServer) server, this); -@@ -372,6 +374,13 @@ public abstract class PlayerList { - } +@@ -377,6 +379,13 @@ public abstract class PlayerList { - player.initMenu(); + player.initInventoryMenu(); + // CraftBukkit - Moved from above, added world + // Paper start - Add to collideRule team if needed + final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); -+ final PlayerTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName); ++ final PlayerTeam collideRuleTeam = scoreboard.getPlayersTeam(this.collideRuleTeamName); + if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) { + scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); + } + // Paper end - // CraftBukkit - Moved from above, added world - PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.worldDataServer.getLevelName(), player.getX(), player.getY(), player.getZ()); + PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ()); } -@@ -492,6 +501,16 @@ public abstract class PlayerList { + +@@ -496,6 +505,16 @@ public abstract class PlayerList { entityplayer.doTick(); // SPIGOT-924 // CraftBukkit end + // Paper start - Remove from collideRule team if needed + if (this.collideRuleTeamName != null) { + final Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard(); -+ final PlayerTeam team = scoreBoard.getTeam(this.collideRuleTeamName); ++ final PlayerTeam team = scoreBoard.getPlayersTeam(this.collideRuleTeamName); + if (entityplayer.getTeam() == team && team != null) { + scoreBoard.removePlayerFromTeam(entityplayer.getScoreboardName(), team); + } @@ -115,15 +115,15 @@ index aa440a6341a6d30aba8fd5f6bcd122bd5d8760cd..59fb19cfebe4f488fd02f02db31029d4 this.save(entityplayer); if (entityplayer.isPassenger()) { Entity entity = entityplayer.getRootVehicle(); -@@ -1140,6 +1159,13 @@ public abstract class PlayerList { +@@ -1118,6 +1137,13 @@ public abstract class PlayerList { } // CraftBukkit end + // Paper start - Remove collideRule team if it exists + if (this.collideRuleTeamName != null) { + final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); -+ final PlayerTeam team = scoreboard.getTeam(this.collideRuleTeamName); -+ if (team != null) scoreboard.removeTeam(team); ++ final PlayerTeam team = scoreboard.getPlayersTeam(this.collideRuleTeamName); ++ if (team != null) scoreboard.removePlayerTeam(team); + } + // Paper end } diff --git a/patches/server-remapped/0090-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/patches/server/0083-Add-handshake-event-to-allow-plugins-to-handle-clien.patch similarity index 65% rename from patches/server-remapped/0090-Add-handshake-event-to-allow-plugins-to-handle-clien.patch rename to patches/server/0083-Add-handshake-event-to-allow-plugins-to-handle-clien.patch index 56a3be043d..9ba4220aed 100644 --- a/patches/server-remapped/0090-Add-handshake-event-to-allow-plugins-to-handle-clien.patch +++ b/patches/server/0083-Add-handshake-event-to-allow-plugins-to-handle-clien.patch @@ -6,18 +6,9 @@ Subject: [PATCH] Add handshake event to allow plugins to handle client diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -index 55b6412bb978abb6f8eaff83a7dd40fbc1ed8b9a..e56ab94ce65e81bb0383a1626a1790c43bd6920e 100644 +index 94d0111f35cb025024da10e2fb4ea0cb802d4ff2..c4ba069f5124ec151e05813beddf293fddc3b804 100644 --- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -@@ -29,7 +29,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - // CraftBukkit end - private static final Component IGNORE_STATUS_REASON = new TextComponent("Ignoring status request"); - private final MinecraftServer server; -- private final Connection connection; -+ private final Connection connection; final Connection getNetworkManager() { return this.connection; } // Paper - OBFHELPER - - public ServerHandshakePacketListenerImpl(MinecraftServer server, Connection connection) { - this.server = server; @@ -88,8 +88,35 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL this.connection.disconnect(chatmessage); } else { @@ -27,22 +18,22 @@ index 55b6412bb978abb6f8eaff83a7dd40fbc1ed8b9a..e56ab94ce65e81bb0383a1626a1790c4 + boolean handledByEvent = false; + // Try and handle the handshake through the event + if (com.destroystokyo.paper.event.player.PlayerHandshakeEvent.getHandlerList().getRegisteredListeners().length != 0) { // Hello? Can you hear me? -+ java.net.SocketAddress socketAddress = this.getNetworkManager().address; ++ java.net.SocketAddress socketAddress = this.connection.address; + String hostnameOfRemote = socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getHostString() : InetAddress.getLoopbackAddress().getHostAddress(); + com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packet.hostName, hostnameOfRemote, !proxyLogicEnabled); + if (event.callEvent()) { + // If we've failed somehow, let the client know so and go no further. + if (event.isFailed()) { -+ chatmessage = new TranslatableComponent(event.getFailMessage()); -+ this.getNetworkManager().send(new ClientboundLoginDisconnectPacket(chatmessage)); -+ this.getNetworkManager().disconnect(chatmessage); ++ TranslatableComponent chatmessage = new TranslatableComponent(event.getFailMessage()); ++ this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); ++ this.connection.disconnect(chatmessage); + return; + } + + if (event.getServerHostname() != null) packet.hostName = event.getServerHostname(); -+ if (event.getSocketAddressHostname() != null) this.getNetworkManager().address = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); -+ this.getNetworkManager().spoofedUUID = event.getUniqueId(); -+ this.getNetworkManager().spoofedProfile = gson.fromJson(event.getPropertiesJson(), com.mojang.authlib.properties.Property[].class); ++ if (event.getSocketAddressHostname() != null) this.connection.address = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); ++ this.connection.spoofedUUID = event.getUniqueId(); ++ this.connection.spoofedProfile = gson.fromJson(event.getPropertiesJson(), com.mojang.authlib.properties.Property[].class); + handledByEvent = true; // Hooray, we did it! + } + } @@ -53,5 +44,5 @@ index 55b6412bb978abb6f8eaff83a7dd40fbc1ed8b9a..e56ab94ce65e81bb0383a1626a1790c4 - if (org.spigotmc.SpigotConfig.bungee) { + //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! String[] split = packet.hostName.split("\00"); - if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { + if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.HOST_PATTERN.matcher( split[1] ).matches() ) ) { packet.hostName = split[0]; diff --git a/patches/server-remapped/0091-Configurable-RCON-IP-address.patch b/patches/server/0084-Configurable-RCON-IP-address.patch similarity index 57% rename from patches/server-remapped/0091-Configurable-RCON-IP-address.patch rename to patches/server/0084-Configurable-RCON-IP-address.patch index 4bc15f3f2f..2e6902174f 100644 --- a/patches/server-remapped/0091-Configurable-RCON-IP-address.patch +++ b/patches/server/0084-Configurable-RCON-IP-address.patch @@ -6,54 +6,52 @@ Subject: [PATCH] Configurable RCON IP address For servers with multiple IP's, ability to bind to a specific interface. diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index d10f2e5a13a9e86c32ef5dd8c6732ad8b51ed6a0..545096d9ba403396b6aaa7bb6d912f2de08a967e 100644 +index 3dc2187035fff8c0c338b35c07ca2164ed753b04..e3409d5f4ddcaa4edecfa4b3c638a12624b09f1b 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -@@ -64,6 +64,8 @@ public class DedicatedServerProperties extends Settings.MutableValue whiteList; - public final WorldGenSettings worldGenSettings; +@@ -67,6 +67,8 @@ public class DedicatedServerProperties extends Settings> { - }; +@@ -124,7 +124,7 @@ public abstract class Settings> { } -- @Nullable + @Nullable - private String getStringRaw(String key) { -+ @Nullable String getSettingIfExists(final String path) { return this.getStringRaw(path); } // Paper - OBFHELPER -+ @Nullable private String getStringRaw(String key) { // Paper - OBFHELPER - return (String) getOverride(key, this.properties.getProperty(key)); // CraftBukkit ++ public String getStringRaw(String key) { // Paper - private -> public + return (String) this.getOverride(key, this.properties.getProperty(key)); // CraftBukkit } diff --git a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java b/src/main/java/net/minecraft/server/rcon/thread/RconThread.java -index f2a94e9d9b57ece16873972bc5292f7cf3928848..ef9f659ae5f53a8effa807ecb955ef47d53aacd2 100644 +index 5e642ab9947f054c1741e13170a36f8fe300cdbe..a93e0eb67a78abb2eabd549cd5240095a24e5545 100644 --- a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java +++ b/src/main/java/net/minecraft/server/rcon/thread/RconThread.java -@@ -62,7 +62,7 @@ public class RconThread extends GenericThread { +@@ -60,7 +60,7 @@ public class RconThread extends GenericThread { @Nullable public static RconThread create(ServerInterface server) { - DedicatedServerProperties dedicatedserverproperties = server.getProperties(); -- String s = server.getServerIp(); -+ String s = dedicatedserverproperties.rconIp; // Paper - Configurable rcon ip - - if (s.isEmpty()) { - s = "0.0.0.0"; + DedicatedServerProperties dedicatedServerProperties = server.getProperties(); +- String string = server.getServerIp(); ++ String string = dedicatedServerProperties.rconIp; // Paper - Configurable rcon ip + if (string.isEmpty()) { + string = "0.0.0.0"; + } diff --git a/patches/server-remapped/0093-Implement-PlayerLocaleChangeEvent.patch b/patches/server/0085-Implement-PlayerLocaleChangeEvent.patch similarity index 74% rename from patches/server-remapped/0093-Implement-PlayerLocaleChangeEvent.patch rename to patches/server/0085-Implement-PlayerLocaleChangeEvent.patch index c52d99a313..8aa65a2052 100644 --- a/patches/server-remapped/0093-Implement-PlayerLocaleChangeEvent.patch +++ b/patches/server/0085-Implement-PlayerLocaleChangeEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Implement PlayerLocaleChangeEvent diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index ffad931c72e52855a3f139354f5e85c460e2a80b..bd3d9182dfb2c0ae1d8c3b9aa360f94c33252592 100644 +index b68a58abf254289a806636ca28521be39c13a82f..0a59e3b405d5074ab326e6ddb265a714e4038e86 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1692,7 +1692,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1712,7 +1712,7 @@ public class ServerPlayer extends Player { return s; } @@ -17,30 +17,30 @@ index ffad931c72e52855a3f139354f5e85c460e2a80b..bd3d9182dfb2c0ae1d8c3b9aa360f94c public java.util.Locale adventure$locale = java.util.Locale.US; // Paper public void updateOptions(ServerboundClientInformationPacket packet) { // CraftBukkit start -@@ -1700,9 +1700,10 @@ public class ServerPlayer extends Player implements ContainerListener { - PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); +@@ -1720,9 +1720,10 @@ public class ServerPlayer extends Player { + PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(this.getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); this.server.server.getPluginManager().callEvent(event); } - if (!this.locale.equals(packet.language)) { + if (this.locale == null || !this.locale.equals(packet.language)) { // Paper - check for null - PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), packet.language); + PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(this.getBukkitEntity(), packet.language); this.server.server.getPluginManager().callEvent(event); + new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.locale, packet.language).callEvent(); // Paper } this.locale = packet.language; // Paper start diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b264cbe5f91da9e31c5fd00ee285735a19aaad35..fc19b4cacd223b928fbdf922b828beaed630bf2e 100644 +index b93a02dce55952321874528016ea48e5a35bd772..b9320aa8e3fc3216753f7d4e3d4b2bda9ec403ef 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1875,8 +1875,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1878,8 +1878,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public String getLocale() { -- return getHandle().locale; +- return this.getHandle().locale; - + // Paper start - Locale change event -+ final String locale = getHandle().locale; ++ final String locale = this.getHandle().locale; + return locale != null ? locale : "en_us"; + // Paper end } diff --git a/patches/server-remapped/0094-EntityRegainHealthEvent-isFastRegen-API.patch b/patches/server/0086-EntityRegainHealthEvent-isFastRegen-API.patch similarity index 89% rename from patches/server-remapped/0094-EntityRegainHealthEvent-isFastRegen-API.patch rename to patches/server/0086-EntityRegainHealthEvent-isFastRegen-API.patch index 386b74cf50..92fd7f6aa5 100644 --- a/patches/server-remapped/0094-EntityRegainHealthEvent-isFastRegen-API.patch +++ b/patches/server/0086-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 a326e5b4ac055f2f8a95c6eaccd8d0a97762da1f..1131d86080b3100437aa18a00c6277fcea4b7ea8 100644 +index 83eaa3c6581c1a3f588278124fed4c811e81e53c..041a61e037e7f6fddd94567f2954be600c737811 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1127,10 +1127,16 @@ public abstract class LivingEntity extends Entity { +@@ -1230,10 +1230,16 @@ public abstract class LivingEntity extends Entity { } public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { @@ -28,7 +28,7 @@ index a326e5b4ac055f2f8a95c6eaccd8d0a97762da1f..1131d86080b3100437aa18a00c6277fc if (this.valid) { this.level.getCraftServer().getPluginManager().callEvent(event); diff --git a/src/main/java/net/minecraft/world/food/FoodData.java b/src/main/java/net/minecraft/world/food/FoodData.java -index 269392592f5271b1bb8c37661fbe685e76e32b74..d18b7d2c22312fc6ec3977ce38a1f04e0b5c8ad4 100644 +index 4957366784799fb204ecec735655c3440734ca57..97133bd4af30d0ba92cbf884b83140f3399f92e2 100644 --- a/src/main/java/net/minecraft/world/food/FoodData.java +++ b/src/main/java/net/minecraft/world/food/FoodData.java @@ -84,7 +84,7 @@ public class FoodData { diff --git a/patches/server-remapped/0095-Add-ability-to-configure-frosted_ice-properties.patch b/patches/server/0087-Add-ability-to-configure-frosted_ice-properties.patch similarity index 66% rename from patches/server-remapped/0095-Add-ability-to-configure-frosted_ice-properties.patch rename to patches/server/0087-Add-ability-to-configure-frosted_ice-properties.patch index e5bee625dc..f1f6980267 100644 --- a/patches/server-remapped/0095-Add-ability-to-configure-frosted_ice-properties.patch +++ b/patches/server/0087-Add-ability-to-configure-frosted_ice-properties.patch @@ -24,23 +24,23 @@ index 1942f5224aaebb18adb591d6f70a419cfc1a7bdd..5baccb8d50c135ab20c38ffd0690f585 + } } diff --git a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java -index 0727cc36c99cb5ca5019c71f4540de76b78c7a80..ae2f5acd008d5d7163b56cb4a2d29354299959ca 100644 +index 958d84d0046814a4a5715d9c8be09318f483aa22..54eb7ba0265bb155dd1c753661242fa9d299ff80 100644 --- a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +++ b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java -@@ -30,6 +30,7 @@ public class FrostedIceBlock extends IceBlock { +@@ -32,6 +32,7 @@ public class FrostedIceBlock extends IceBlock { @Override public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) { + if (!world.paperConfig.frostedIceEnabled) return; // Paper - add ability to disable frosted ice - if ((random.nextInt(3) == 0 || this.fewerNeigboursThan(world, pos, 4)) && world.getMaxLocalRawBrightness(pos) > 11 - (Integer) state.getValue(FrostedIceBlock.AGE) - state.getLightBlock((BlockGetter) world, pos) && this.slightlyMelt(state, (Level) world, pos)) { - BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); - Direction[] aenumdirection = Direction.values(); -@@ -42,12 +43,12 @@ public class FrostedIceBlock extends IceBlock { - BlockState iblockdata1 = world.getBlockState(blockposition_mutableblockposition); + if ((random.nextInt(3) == 0 || this.fewerNeigboursThan(world, pos, 4)) && world.getMaxLocalRawBrightness(pos) > 11 - state.getValue(AGE) - state.getLightBlock(world, pos) && this.slightlyMelt(state, world, pos)) { + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); - if (iblockdata1.is((Block) this) && !this.slightlyMelt(iblockdata1, (Level) world, blockposition_mutableblockposition)) { -- world.getBlockTicks().scheduleTick(blockposition_mutableblockposition, this, Mth.nextInt(random, 20, 40)); -+ world.getBlockTicks().scheduleTick(blockposition_mutableblockposition, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay +@@ -39,12 +40,12 @@ public class FrostedIceBlock extends IceBlock { + mutableBlockPos.setWithOffset(pos, direction); + BlockState blockState = world.getBlockState(mutableBlockPos); + if (blockState.is(this) && !this.slightlyMelt(blockState, world, mutableBlockPos)) { +- world.getBlockTicks().scheduleTick(mutableBlockPos, this, Mth.nextInt(random, 20, 40)); ++ world.getBlockTicks().scheduleTick(mutableBlockPos, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay } } diff --git a/patches/server-remapped/0096-remove-null-possibility-for-getServer-singleton.patch b/patches/server/0088-remove-null-possibility-for-getServer-singleton.patch similarity index 61% rename from patches/server-remapped/0096-remove-null-possibility-for-getServer-singleton.patch rename to patches/server/0088-remove-null-possibility-for-getServer-singleton.patch index 2a17e8f4af..10bda99865 100644 --- a/patches/server-remapped/0096-remove-null-possibility-for-getServer-singleton.patch +++ b/patches/server/0088-remove-null-possibility-for-getServer-singleton.patch @@ -6,26 +6,26 @@ Subject: [PATCH] remove null possibility for getServer singleton to stop IDE complaining about potential NPE diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index d639ead95c36985fa0f5a9c51898c4237e373f0e..4e468cb7ccf683b8fc9e04a48cfc25779775e25f 100644 +index f1868ef9111f25a1d4232587c0c5145c7cd50ef4..ef231e11b90b24418a77b62f5fe766c9ac10c09b 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -178,6 +178,7 @@ import org.spigotmc.SlackActivityAccountant; // Spigot +@@ -189,6 +189,7 @@ import org.spigotmc.SlackActivityAccountant; // Spigot public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { + private static MinecraftServer SERVER; // Paper public static final Logger LOGGER = LogManager.getLogger(); - public static final File USERID_CACHE_FILE = new File("usercache.json"); - public static final LevelSettings DEMO_SETTINGS = new LevelSettings("Demo World", GameType.SURVIVAL, false, Difficulty.NORMAL, false, new GameRules(), DataPackConfig.DEFAULT); -@@ -284,6 +285,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +@@ -2232,7 +2234,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop bannerMarkers = Maps.newHashMap(); +@@ -64,6 +64,7 @@ public class MapItemSavedData extends SavedData { public final Map decorations = Maps.newLinkedHashMap(); private final Map frameMarkers = Maps.newHashMap(); + private int trackedDecorationCount; + private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper // CraftBukkit start public final CraftMapView mapView; -@@ -69,6 +70,7 @@ public class MapItemSavedData extends SavedData { +@@ -84,6 +85,7 @@ public class MapItemSavedData extends SavedData { // CraftBukkit start - mapView = new CraftMapView(this); - server = (CraftServer) org.bukkit.Bukkit.getServer(); -+ vanillaRender.buffer = colors; // Paper + this.mapView = new CraftMapView(this); + this.server = (CraftServer) org.bukkit.Bukkit.getServer(); ++ this.vanillaRender.buffer = colors; // Paper // CraftBukkit end } -@@ -136,6 +138,7 @@ public class MapItemSavedData extends SavedData { - this.bannerMarkers.put(mapiconbanner.getId(), mapiconbanner); - this.addDecoration(mapiconbanner.getDecoration(), (LevelAccessor) null, mapiconbanner.getId(), (double) mapiconbanner.getPos().getX(), (double) mapiconbanner.getPos().getZ(), 180.0D, mapiconbanner.getName()); +@@ -139,6 +141,7 @@ public class MapItemSavedData extends SavedData { + if (abyte.length == 16384) { + worldmap.colors = abyte; } -+ this.vanillaRender.buffer = colors; // Paper ++ worldmap.vanillaRender.buffer = abyte; // Paper - ListTag nbttaglist1 = tag.getList("frames", 10); + ListTag nbttaglist = nbt.getList("banners", 10); -@@ -216,6 +219,7 @@ public class MapItemSavedData extends SavedData { - this.setDirty(); - } - -+ public void updateSeenPlayers(Player entityhuman, ItemStack itemstack) { this.tickCarriedBy(entityhuman, itemstack); } // Paper - OBFHELPER - public void tickCarriedBy(Player player, ItemStack stack) { - if (!this.carriedByPlayers.containsKey(player)) { - MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = new MapItemSavedData.HoldingPlayer(player); -@@ -451,6 +455,21 @@ public class MapItemSavedData extends SavedData { +@@ -549,6 +552,21 @@ public class MapItemSavedData extends SavedData { public class HoldingPlayer { + // Paper start + private void addSeenPlayers(java.util.Collection icons) { -+ org.bukkit.entity.Player player = (org.bukkit.entity.Player) player.getBukkitEntity(); ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) this.player.getBukkitEntity(); + MapItemSavedData.this.decorations.forEach((name, mapIcon) -> { + // If this cursor is for a player check visibility with vanish system + org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayerExact(name); // Spigot @@ -115,20 +107,26 @@ index d44505b3ee2a35422568e9bce0d868191e348fc0..7582c7cd4235d212a0cf66a4c59ce0ce public final Player player; private boolean dirtyData = true; private int minDirtyX; -@@ -467,9 +486,12 @@ public class MapItemSavedData extends SavedData { +@@ -582,7 +600,9 @@ public class MapItemSavedData extends SavedData { @Nullable - public Packet nextUpdatePacket(ItemStack stack) { - // CraftBukkit start + Packet nextUpdatePacket(int mapId) { + MapItemSavedData.MapPatch worldmap_b; - org.bukkit.craftbukkit.map.RenderData render = MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit + if (!this.dirtyData && this.tick % 5 != 0) { this.tick++; return null; } // Paper - this won't end up sending, so don't render it! + boolean vanillaMaps = shouldUseVanillaMap(); // Paper + org.bukkit.craftbukkit.map.RenderData render = !vanillaMaps ? MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()) : MapItemSavedData.this.vanillaRender; // CraftBukkit // Paper - java.util.Collection icons = new java.util.ArrayList(); -+ if (vanillaMaps) addSeenPlayers(icons); // Paper - - for ( org.bukkit.map.MapCursor cursor : render.cursors) { + if (this.dirtyData) { + this.dirtyData = false; +@@ -598,6 +618,8 @@ public class MapItemSavedData extends SavedData { + // CraftBukkit start + java.util.Collection icons = new java.util.ArrayList(); ++ if (vanillaMaps) addSeenPlayers(icons); // Paper ++ + for (org.bukkit.map.MapCursor cursor : render.cursors) { + if (cursor.isVisible()) { + icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure diff --git a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java index 256a131781721c86dd6cdbc329335964570cbe8c..5768cd512ec166f1e8d1f4a28792015347297c3f 100644 --- a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java diff --git a/patches/server-remapped/0098-LootTable-API-Replenishable-Lootables-Feature.patch b/patches/server/0090-LootTable-API-Replenishable-Lootables-Feature.patch similarity index 87% rename from patches/server-remapped/0098-LootTable-API-Replenishable-Lootables-Feature.patch rename to patches/server/0090-LootTable-API-Replenishable-Lootables-Feature.patch index 4e9c15788b..8b4517c77d 100644 --- a/patches/server-remapped/0098-LootTable-API-Replenishable-Lootables-Feature.patch +++ b/patches/server/0090-LootTable-API-Replenishable-Lootables-Feature.patch @@ -43,13 +43,12 @@ index 5baccb8d50c135ab20c38ffd0690f585514ce5af..eb04fdb172a50ec1f5b7fe78fa0e7655 } diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java new file mode 100644 -index 0000000000000000000000000000000000000000..fda64b8860cb696e209eedcfb200e7193d216732 +index 0000000000000000000000000000000000000000..70ca5625ff5d13a8e9cd64953066a7e1547ff223 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java -@@ -0,0 +1,34 @@ +@@ -0,0 +1,33 @@ +package com.destroystokyo.paper.loottable; + -+import LootableInventory; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; @@ -118,14 +117,13 @@ index 0000000000000000000000000000000000000000..292d5ef8a1c428893af729b298eecd32 +} diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java new file mode 100644 -index 0000000000000000000000000000000000000000..b3def19a50081cfa758b6e25707b2fc6fed8d3ca +index 0000000000000000000000000000000000000000..16b3527d7bc782c47e6f6c3ecd7165bd16b0ab0a --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java -@@ -0,0 +1,71 @@ +@@ -0,0 +1,70 @@ +package com.destroystokyo.paper.loottable; + +import org.bukkit.loot.Lootable; -+import LootableInventory; +import java.util.UUID; +import net.minecraft.world.level.Level; + @@ -195,16 +193,15 @@ index 0000000000000000000000000000000000000000..b3def19a50081cfa758b6e25707b2fc6 +} diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java new file mode 100644 -index 0000000000000000000000000000000000000000..88542462d34ba24e8590294bd896d7e73932ef9c +index 0000000000000000000000000000000000000000..115a6fad53655f356866032054db36777a791b4e --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java -@@ -0,0 +1,180 @@ +@@ -0,0 +1,179 @@ +package com.destroystokyo.paper.loottable; + +import com.destroystokyo.paper.PaperWorldConfig; +import org.bukkit.entity.Player; +import org.bukkit.loot.LootTable; -+ +import javax.annotation.Nullable; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; @@ -381,13 +378,12 @@ index 0000000000000000000000000000000000000000..88542462d34ba24e8590294bd896d7e7 +} diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java new file mode 100644 -index 0000000000000000000000000000000000000000..d9b31c8a21fdffb33d1f75b1a16606f218145b39 +index 0000000000000000000000000000000000000000..6d2e0493729b7b4e109ff103a6ac36c9901568c0 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java -@@ -0,0 +1,63 @@ +@@ -0,0 +1,62 @@ +package com.destroystokyo.paper.loottable; + -+import LootableInventory; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; +import net.minecraft.world.level.Level; @@ -450,13 +446,12 @@ index 0000000000000000000000000000000000000000..d9b31c8a21fdffb33d1f75b1a16606f2 +} diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java new file mode 100644 -index 0000000000000000000000000000000000000000..6bc899ec4dc03b09cc978bc7a763a9755a3d2dc4 +index 0000000000000000000000000000000000000000..3377b86c337d0234bbb9b0349e4034a7cd450a97 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java -@@ -0,0 +1,66 @@ +@@ -0,0 +1,65 @@ +package com.destroystokyo.paper.loottable; + -+import LootableInventory; +import net.minecraft.server.MCUtil; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; @@ -521,10 +516,10 @@ index 0000000000000000000000000000000000000000..6bc899ec4dc03b09cc978bc7a763a975 + } +} diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 61048140cf0adca03bfb57193ada0adaee73b1bb..171697e88f5a4d8c0be2a47b67b865bbdc4dfe8c 100644 +index eceaeed527f34860e1c55b9f96863f140055faa7..416dd12638540312aa48b530e24ba3ad7ab6079c 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -157,6 +157,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -168,6 +168,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n }; // Paper end @@ -533,10 +528,10 @@ index 61048140cf0adca03bfb57193ada0adaee73b1bb..171697e88f5a4d8c0be2a47b67b865bb public CraftEntity getBukkitEntity() { diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java -index f4758251e58fbb36526cea5c4825561d62c9665a..5b96b1e7428a43c8c5f4a96ea37d5189f0d84f56 100644 +index e347f30d7c5be460788cc815da2f4f8742488713..f57864ce919ef4721cfb5913c636fe8903ce4cc1 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java -@@ -45,6 +45,7 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme +@@ -46,6 +46,7 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme public long lootTableSeed; // CraftBukkit start @@ -544,36 +539,36 @@ index f4758251e58fbb36526cea5c4825561d62c9665a..5b96b1e7428a43c8c5f4a96ea37d5189 public List transaction = new java.util.ArrayList(); private int maxStack = MAX_STACK; -@@ -202,12 +203,13 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme +@@ -200,12 +201,13 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme @Override - protected void addAdditionalSaveData(CompoundTag tag) { - super.addAdditionalSaveData(tag); -+ this.lootableData.saveNbt(tag); // Paper + protected void addAdditionalSaveData(CompoundTag nbt) { + super.addAdditionalSaveData(nbt); ++ this.lootableData.saveNbt(nbt); // Paper if (this.lootTable != null) { - tag.putString("LootTable", this.lootTable.toString()); + nbt.putString("LootTable", this.lootTable.toString()); if (this.lootTableSeed != 0L) { - tag.putLong("LootTableSeed", this.lootTableSeed); + nbt.putLong("LootTableSeed", this.lootTableSeed); } - } else { + } if (true) { // Paper - Always save the items, Table may stick around - ContainerHelper.saveAllItems(tag, this.itemStacks); + ContainerHelper.saveAllItems(nbt, this.itemStacks); } -@@ -216,11 +218,12 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme +@@ -214,11 +216,12 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme @Override - protected void readAdditionalSaveData(CompoundTag tag) { - super.readAdditionalSaveData(tag); -+ this.lootableData.loadNbt(tag); // Paper - this.itemStacks = NonNullList.a(this.getContainerSize(), ItemStack.EMPTY); - if (tag.contains("LootTable", 8)) { - this.lootTable = new ResourceLocation(tag.getString("LootTable")); - this.lootTableSeed = tag.getLong("LootTableSeed"); + protected void readAdditionalSaveData(CompoundTag nbt) { + super.readAdditionalSaveData(nbt); ++ this.lootableData.loadNbt(nbt); // Paper + this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); + if (nbt.contains("LootTable", 8)) { + this.lootTable = new ResourceLocation(nbt.getString("LootTable")); + this.lootTableSeed = nbt.getLong("LootTableSeed"); - } else { + } if (true) { // Paper - always load the items, table may still remain - ContainerHelper.loadAllItems(tag, this.itemStacks); + ContainerHelper.loadAllItems(nbt, this.itemStacks); } -@@ -251,14 +254,15 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme +@@ -254,14 +257,15 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme } public void unpackLootTable(@Nullable Player player) { @@ -592,26 +587,26 @@ index f4758251e58fbb36526cea5c4825561d62c9665a..5b96b1e7428a43c8c5f4a96ea37d5189 if (player != null) { diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java -index 9d33bc31c8088bfba66be1aecbf20e7ee86e4f83..5ad419941ff1113ef29b9a4593f44d8f35ba8424 100644 +index b79d9d26a8e60f9c0ecd69e9c2f9cfd087e21d23..f23fff80d07ac7d06715efe67cb49ebbe704967b 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java -@@ -27,6 +27,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc +@@ -28,6 +28,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc @Nullable public ResourceLocation lootTable; public long lootTableSeed; + public final com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperTileEntityLootableInventory(this)); // Paper - protected RandomizableContainerBlockEntity(BlockEntityType type) { - super(type); + protected RandomizableContainerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); @@ -42,16 +43,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc } - protected boolean tryLoadLootTable(CompoundTag nbttagcompound) { -+ this.lootableData.loadNbt(nbttagcompound); // Paper - if (nbttagcompound.contains("LootTable", 8)) { - this.lootTable = new ResourceLocation(nbttagcompound.getString("LootTable")); + protected boolean tryLoadLootTable(CompoundTag nbt) { ++ this.lootableData.loadNbt(nbt); // Paper + if (nbt.contains("LootTable", 8)) { + this.lootTable = new ResourceLocation(nbt.getString("LootTable")); + try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate - this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); + this.lootTableSeed = nbt.getLong("LootTableSeed"); - return true; + return false; // Paper - always load the items, table may still remain } else { @@ -619,13 +614,13 @@ index 9d33bc31c8088bfba66be1aecbf20e7ee86e4f83..5ad419941ff1113ef29b9a4593f44d8f } } - protected boolean trySaveLootTable(CompoundTag nbttagcompound) { -+ this.lootableData.saveNbt(nbttagcompound); // Paper + protected boolean trySaveLootTable(CompoundTag nbt) { ++ this.lootableData.saveNbt(nbt); // Paper if (this.lootTable == null) { return false; } else { -@@ -60,19 +64,20 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc - nbttagcompound.putLong("LootTableSeed", this.lootTableSeed); +@@ -60,18 +64,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + nbt.putLong("LootTableSeed", this.lootTableSeed); } - return true; @@ -636,36 +631,35 @@ index 9d33bc31c8088bfba66be1aecbf20e7ee86e4f83..5ad419941ff1113ef29b9a4593f44d8f public void unpackLootTable(@Nullable Player player) { - if (this.lootTable != null && this.level.getServer() != null) { + if (this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper - LootTable loottable = this.level.getServer().getLootTables().get(this.lootTable); - + LootTable lootTable = this.level.getServer().getLootTables().get(this.lootTable); if (player instanceof ServerPlayer) { - CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer) player, this.lootTable); + CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer)player, this.lootTable); } - this.lootTable = null; + //this.lootTable = null; // Paper + this.lootableData.processRefill(player); // Paper - LootContext.Builder loottableinfo_builder = (new LootContext.Builder((ServerLevel) this.level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf((Vec3i) this.worldPosition)).withOptionalRandomSeed(this.lootTableSeed); - + LootContext.Builder builder = (new LootContext.Builder((ServerLevel)this.level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(this.worldPosition)).withOptionalRandomSeed(this.lootTableSeed); if (player != null) { + builder.withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 1e2e94b0cd2ede8fb7ae5902dcd0b639bd8dcf52..e89a93082fe07fdb14df8ffef5beca5bd52d7866 100644 +index 90f44b49d2728c8a1110270fa8c52104355e45c4..d57b32090cebfc952ac0a71b8aada85f49275241 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -64,7 +64,7 @@ public class CraftBlockEntityState extends CraftBlockStat +@@ -61,7 +61,7 @@ public class CraftBlockEntityState extends CraftBlockStat } // gets the wrapped TileEntity - protected T getTileEntity() { + public T getTileEntity() { // Paper - protected -> public - return tileEntity; + return this.tileEntity; } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -index 20d9a192ff102e04687a8aa3eff1ba36a69b6c03..a821df3e13e2ddc479dc5f55540671f43563cdac 100644 +index 5cb17e8289db0ab38fd36318e2957701d6dfb341..f48b830a9ae8160388cb0d0220a44b1ec9f0d214 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -@@ -12,8 +12,9 @@ import org.bukkit.craftbukkit.CraftWorld; +@@ -13,8 +13,9 @@ import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.inventory.CraftInventory; import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest; import org.bukkit.inventory.Inventory; @@ -677,7 +671,7 @@ index 20d9a192ff102e04687a8aa3eff1ba36a69b6c03..a821df3e13e2ddc479dc5f55540671f4 public CraftChest(final Block block) { super(block, ChestBlockEntity.class); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -index 309650aad43d8b6ce4bb13f8c172028f3feab299..5babbcfcacb89e62f00f8184af2ceea227f9ff69 100644 +index 28b9a42d43522cde9d0be4d98a8a5f8fdf6c3abd..055ffe404c37e1daab61b821b590f8c7038076eb 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java @@ -10,7 +10,7 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; @@ -690,7 +684,7 @@ index 309650aad43d8b6ce4bb13f8c172028f3feab299..5babbcfcacb89e62f00f8184af2ceea2 public CraftLootable(Block block, Class tileEntityClass) { super(block, tileEntityClass); @@ -54,7 +54,7 @@ public abstract class CraftLootable - setLootTable(getLootTable(), seed); + this.setLootTable(this.getLootTable(), seed); } - private void setLootTable(LootTable table, long seed) { @@ -699,7 +693,7 @@ index 309650aad43d8b6ce4bb13f8c172028f3feab299..5babbcfcacb89e62f00f8184af2ceea2 getSnapshot().setLootTable(key, seed); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -index f0a30acb0199e396d6863a473db433cbe112d8a5..293b222565d8e0592f9f355a2ee8cdfbc868a08e 100644 +index eb21b8457774d5ac765fa9008157cb29d9b72509..abf58bef2042a9efba5a78fd7f97339deceaa780 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java @@ -8,7 +8,7 @@ import org.bukkit.entity.minecart.StorageMinecart; @@ -712,20 +706,20 @@ index f0a30acb0199e396d6863a473db433cbe112d8a5..293b222565d8e0592f9f355a2ee8cdfb public CraftMinecartChest(CraftServer server, MinecartChest entity) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -index 12044062cb746bd5c77abacf8acddc67e08e78ce..ce14bc4791bd282d16af0ee91fc431acefa3b909 100644 +index 097d8bd479a0800114964725da8bfd19415a2956..4893d8e67025d919a455b44bb41d914a39ab5aa9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java @@ -47,7 +47,7 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo - return getHandle().lootTableSeed; + return this.getHandle().lootTableSeed; } - private void setLootTable(LootTable table, long seed) { -+ public void setLootTable(LootTable table, long seed) { // Paper ++ @Override public void setLootTable(LootTable table, long seed) { // Paper ResourceLocation newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); - getHandle().setLootTable(newKey, seed); + this.getHandle().setLootTable(newKey, seed); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -index c1af739369715d8c628c466b269fdde99a2f6286..c8c5f60b6b32248696363d9b63bbbe43810743d3 100644 +index 34b8f103625f087bb725bed595dd9c30f4a6f70c..ee9648739fb39c5842063d7442df6eb5c9336d7f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java @@ -7,7 +7,7 @@ import org.bukkit.entity.EntityType; From 8599f95b4f62869804cbb313b7ac6a83b8b6f65a Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Fri, 11 Jun 2021 22:20:08 -0700 Subject: [PATCH 035/226] even more progress --- ...blocking-on-Network-Manager-creation.patch | 45 ------- ...3-Optional-TNT-doesn-t-move-in-water.patch | 121 ------------------ ...layer-View-Distance-API-placeholders.patch | 70 ---------- ...layer-View-Distance-API-placeholders.patch | 42 ++++++ ...patch => 0038-Add-BeaconEffectEvent.patch} | 0 ...igurable-container-update-tick-rate.patch} | 6 +- ...0040-Use-UserCache-for-player-heads.patch} | 0 ...> 0041-Disable-spigot-tick-limiters.patch} | 0 ...=> 0042-Add-PlayerInitialSpawnEvent.patch} | 0 ...rable-Disabling-Cat-Chest-Detection.patch} | 0 ...4-Ensure-commands-are-not-ran-async.patch} | 0 ...hunks-are-slime-spawn-chunks-toggle.patch} | 0 ...ch => 0046-Expose-server-CommandMap.patch} | 0 ...-informative-in-maxHealth-exception.patch} | 0 ...0048-Player-Tab-List-and-Title-APIs.patch} | 2 +- ...> 0049-Ensure-inv-drag-is-in-bounds.patch} | 0 ...d-configurable-portal-search-radius.patch} | 0 ...patch => 0051-Add-velocity-warnings.patch} | 0 ...le-inter-world-teleportation-safety.patch} | 4 +- ... 0053-Add-exception-reporting-event.patch} | 0 ...don-t-need-to-when-cerealising-text.patch} | 0 ...reboards-for-non-players-by-default.patch} | 0 ...orking-with-arrows-stuck-in-living-.patch} | 0 ... => 0057-Complete-resource-pack-API.patch} | 4 +- ....patch => 0058-Chunk-Save-Reattempt.patch} | 0 ...ding-permissions.yml-before-plugins.patch} | 0 ...low-Reloading-of-Custom-Permissions.patch} | 0 ...h => 0061-Remove-Metadata-on-reload.patch} | 0 ...62-Handle-Item-Meta-Inconsistencies.patch} | 0 ...rable-Non-Player-Arrow-Despawn-Rate.patch} | 0 ...atch => 0064-Add-World-Util-Methods.patch} | 0 ...-Custom-replacement-for-eaten-items.patch} | 0 ...h-absorb-values-and-repair-bad-data.patch} | 4 +- ...67-Use-a-Shared-Random-for-Entities.patch} | 0 ...e-spawn-chances-for-skeleton-horses.patch} | 0 ...ocation-getType-and-getBlockData-fo.patch} | 0 ...kPhysicsEvent-if-a-plugin-has-a-lis.patch} | 0 ...ntity-AddTo-RemoveFrom-World-Events.patch} | 0 ...2-Configurable-Chunk-Inhabited-Time.patch} | 0 ...t.patch => 0073-EntityPathfindEvent.patch} | 0 ...gionFileCache-and-make-configurable.patch} | 0 ...-Do-not-load-chunks-for-Pathfinding.patch} | 0 ...076-Add-PlayerUseUnknownEntityEvent.patch} | 0 ...DebugInfo-not-initialized-on-client.patch} | 0 ...Configurable-Grass-Spread-Tick-Rate.patch} | 0 ...-BlockPlaceEvent-triggering-physics.patch} | 0 ...its.patch => 0080-Optimize-DataBits.patch} | 0 ...illa-per-world-scoreboard-coloring-.patch} | 0 ...d-for-setting-passengers-on-players.patch} | 4 +- ... 0083-Configurable-Player-Collision.patch} | 0 ...nt-to-allow-plugins-to-handle-clien.patch} | 0 ...> 0085-Configurable-RCON-IP-address.patch} | 0 ...6-Implement-PlayerLocaleChangeEvent.patch} | 10 +- ...tyRegainHealthEvent-isFastRegen-API.patch} | 0 ...to-configure-frosted_ice-properties.patch} | 0 ...possibility-for-getServer-singleton.patch} | 0 ...tem-frames-performance-and-bug-fixe.patch} | 0 ...API-Replenishable-Lootables-Feature.patch} | 5 +- ...-scoreboard-teams-to-scoreboard.dat.patch} | 16 +-- ...em-property-for-disabling-watchdoge.patch} | 8 +- ...0094-Optimize-UserCache-Thread-Safe.patch} | 62 ++++----- ...5-Optional-TNT-doesn-t-move-in-water.patch | 82 ++++++++++++ ...-redstone-torch-rapid-clock-removal.patch} | 39 ++---- .../0097-Add-server-name-parameter.patch} | 2 +- ...n-Wither-Death-sounds-to-same-world.patch} | 16 +-- 65 files changed, 199 insertions(+), 343 deletions(-) delete mode 100644 patches/server-remapped/0102-Avoid-blocking-on-Network-Manager-creation.patch delete mode 100644 patches/server-remapped/0103-Optional-TNT-doesn-t-move-in-water.patch delete mode 100644 patches/server-remapped/0347-Per-Player-View-Distance-API-placeholders.patch create mode 100644 patches/server/0037-Per-Player-View-Distance-API-placeholders.patch rename patches/server/{0037-Add-BeaconEffectEvent.patch => 0038-Add-BeaconEffectEvent.patch} (100%) rename patches/server/{0038-Configurable-container-update-tick-rate.patch => 0039-Configurable-container-update-tick-rate.patch} (89%) rename patches/server/{0039-Use-UserCache-for-player-heads.patch => 0040-Use-UserCache-for-player-heads.patch} (100%) rename patches/server/{0040-Disable-spigot-tick-limiters.patch => 0041-Disable-spigot-tick-limiters.patch} (100%) rename patches/server/{0041-Add-PlayerInitialSpawnEvent.patch => 0042-Add-PlayerInitialSpawnEvent.patch} (100%) rename patches/server/{0042-Configurable-Disabling-Cat-Chest-Detection.patch => 0043-Configurable-Disabling-Cat-Chest-Detection.patch} (100%) rename patches/server/{0043-Ensure-commands-are-not-ran-async.patch => 0044-Ensure-commands-are-not-ran-async.patch} (100%) rename patches/server/{0044-All-chunks-are-slime-spawn-chunks-toggle.patch => 0045-All-chunks-are-slime-spawn-chunks-toggle.patch} (100%) rename patches/server/{0045-Expose-server-CommandMap.patch => 0046-Expose-server-CommandMap.patch} (100%) rename patches/server/{0046-Be-a-bit-more-informative-in-maxHealth-exception.patch => 0047-Be-a-bit-more-informative-in-maxHealth-exception.patch} (100%) rename patches/server/{0047-Player-Tab-List-and-Title-APIs.patch => 0048-Player-Tab-List-and-Title-APIs.patch} (98%) rename patches/server/{0048-Ensure-inv-drag-is-in-bounds.patch => 0049-Ensure-inv-drag-is-in-bounds.patch} (100%) rename patches/server/{0049-Add-configurable-portal-search-radius.patch => 0050-Add-configurable-portal-search-radius.patch} (100%) rename patches/server/{0050-Add-velocity-warnings.patch => 0051-Add-velocity-warnings.patch} (100%) rename patches/server/{0051-Configurable-inter-world-teleportation-safety.patch => 0052-Configurable-inter-world-teleportation-safety.patch} (93%) rename patches/server/{0052-Add-exception-reporting-event.patch => 0053-Add-exception-reporting-event.patch} (100%) rename patches/server/{0053-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch => 0054-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch} (100%) rename patches/server/{0054-Disable-Scoreboards-for-non-players-by-default.patch => 0055-Disable-Scoreboards-for-non-players-by-default.patch} (100%) rename patches/server/{0055-Add-methods-for-working-with-arrows-stuck-in-living-.patch => 0056-Add-methods-for-working-with-arrows-stuck-in-living-.patch} (100%) rename patches/server/{0056-Complete-resource-pack-API.patch => 0057-Complete-resource-pack-API.patch} (95%) rename patches/server/{0057-Chunk-Save-Reattempt.patch => 0058-Chunk-Save-Reattempt.patch} (100%) rename patches/server/{0058-Default-loading-permissions.yml-before-plugins.patch => 0059-Default-loading-permissions.yml-before-plugins.patch} (100%) rename patches/server/{0059-Allow-Reloading-of-Custom-Permissions.patch => 0060-Allow-Reloading-of-Custom-Permissions.patch} (100%) rename patches/server/{0060-Remove-Metadata-on-reload.patch => 0061-Remove-Metadata-on-reload.patch} (100%) rename patches/server/{0061-Handle-Item-Meta-Inconsistencies.patch => 0062-Handle-Item-Meta-Inconsistencies.patch} (100%) rename patches/server/{0062-Configurable-Non-Player-Arrow-Despawn-Rate.patch => 0063-Configurable-Non-Player-Arrow-Despawn-Rate.patch} (100%) rename patches/server/{0063-Add-World-Util-Methods.patch => 0064-Add-World-Util-Methods.patch} (100%) rename patches/server/{0064-Custom-replacement-for-eaten-items.patch => 0065-Custom-replacement-for-eaten-items.patch} (100%) rename patches/server/{0065-handle-NaN-health-absorb-values-and-repair-bad-data.patch => 0066-handle-NaN-health-absorb-values-and-repair-bad-data.patch} (94%) rename patches/server/{0066-Use-a-Shared-Random-for-Entities.patch => 0067-Use-a-Shared-Random-for-Entities.patch} (100%) rename patches/server/{0067-Configurable-spawn-chances-for-skeleton-horses.patch => 0068-Configurable-spawn-chances-for-skeleton-horses.patch} (100%) rename patches/server/{0068-Optimize-isValidLocation-getType-and-getBlockData-fo.patch => 0069-Optimize-isValidLocation-getType-and-getBlockData-fo.patch} (100%) rename patches/server/{0069-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch => 0070-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch} (100%) rename patches/server/{0070-Entity-AddTo-RemoveFrom-World-Events.patch => 0071-Entity-AddTo-RemoveFrom-World-Events.patch} (100%) rename patches/server/{0071-Configurable-Chunk-Inhabited-Time.patch => 0072-Configurable-Chunk-Inhabited-Time.patch} (100%) rename patches/server/{0072-EntityPathfindEvent.patch => 0073-EntityPathfindEvent.patch} (100%) rename patches/server/{0073-Sanitise-RegionFileCache-and-make-configurable.patch => 0074-Sanitise-RegionFileCache-and-make-configurable.patch} (100%) rename patches/server/{0074-Do-not-load-chunks-for-Pathfinding.patch => 0075-Do-not-load-chunks-for-Pathfinding.patch} (100%) rename patches/server/{0075-Add-PlayerUseUnknownEntityEvent.patch => 0076-Add-PlayerUseUnknownEntityEvent.patch} (100%) rename patches/server/{0076-Fix-reducedDebugInfo-not-initialized-on-client.patch => 0077-Fix-reducedDebugInfo-not-initialized-on-client.patch} (100%) rename patches/server/{0077-Configurable-Grass-Spread-Tick-Rate.patch => 0078-Configurable-Grass-Spread-Tick-Rate.patch} (100%) rename patches/server/{0078-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch => 0079-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch} (100%) rename patches/server/{0079-Optimize-DataBits.patch => 0080-Optimize-DataBits.patch} (100%) rename patches/server/{0080-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch => 0081-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch} (100%) rename patches/server/{0081-Workaround-for-setting-passengers-on-players.patch => 0082-Workaround-for-setting-passengers-on-players.patch} (87%) rename patches/server/{0082-Configurable-Player-Collision.patch => 0083-Configurable-Player-Collision.patch} (100%) rename patches/server/{0083-Add-handshake-event-to-allow-plugins-to-handle-clien.patch => 0084-Add-handshake-event-to-allow-plugins-to-handle-clien.patch} (100%) rename patches/server/{0084-Configurable-RCON-IP-address.patch => 0085-Configurable-RCON-IP-address.patch} (100%) rename patches/server/{0085-Implement-PlayerLocaleChangeEvent.patch => 0086-Implement-PlayerLocaleChangeEvent.patch} (85%) rename patches/server/{0086-EntityRegainHealthEvent-isFastRegen-API.patch => 0087-EntityRegainHealthEvent-isFastRegen-API.patch} (100%) rename patches/server/{0087-Add-ability-to-configure-frosted_ice-properties.patch => 0088-Add-ability-to-configure-frosted_ice-properties.patch} (100%) rename patches/server/{0088-remove-null-possibility-for-getServer-singleton.patch => 0089-remove-null-possibility-for-getServer-singleton.patch} (100%) rename patches/server/{0089-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch => 0090-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch} (100%) rename patches/server/{0090-LootTable-API-Replenishable-Lootables-Feature.patch => 0091-LootTable-API-Replenishable-Lootables-Feature.patch} (99%) rename patches/{server-remapped/0099-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch => server/0092-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch} (69%) rename patches/{server-remapped/0100-System-property-for-disabling-watchdoge.patch => server/0093-System-property-for-disabling-watchdoge.patch} (58%) rename patches/{server-remapped/0101-Optimize-UserCache-Thread-Safe.patch => server/0094-Optimize-UserCache-Thread-Safe.patch} (62%) create mode 100644 patches/server/0095-Optional-TNT-doesn-t-move-in-water.patch rename patches/{server-remapped/0104-Faster-redstone-torch-rapid-clock-removal.patch => server/0096-Faster-redstone-torch-rapid-clock-removal.patch} (69%) rename patches/{server-remapped/0105-Add-server-name-parameter.patch => server/0097-Add-server-name-parameter.patch} (90%) rename patches/{server-remapped/0106-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch => server/0098-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch} (80%) diff --git a/patches/server-remapped/0102-Avoid-blocking-on-Network-Manager-creation.patch b/patches/server-remapped/0102-Avoid-blocking-on-Network-Manager-creation.patch deleted file mode 100644 index ba69589d2f..0000000000 --- a/patches/server-remapped/0102-Avoid-blocking-on-Network-Manager-creation.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 16 May 2016 23:19:16 -0400 -Subject: [PATCH] Avoid blocking on Network Manager creation - -Per Paper issue 294 - -diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -index 9680b0b3879c72776d6225a6a5a89fdfa3520598..6cb51a4fe3c11f53fbb556ce6b0d64b735254d51 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -@@ -52,6 +52,15 @@ public class ServerConnectionListener { - public volatile boolean running; - private final List channels = Collections.synchronizedList(Lists.newArrayList()); - private final List connections = Collections.synchronizedList(Lists.newArrayList()); -+ // Paper start - prevent blocking on adding a new network manager while the server is ticking -+ private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private void addPending() { -+ Connection manager = null; -+ while ((manager = pending.poll()) != null) { -+ connections.add(manager); -+ } -+ } -+ // Paper end - - public ServerConnectionListener(MinecraftServer server) { - this.server = server; -@@ -87,7 +96,8 @@ public class ServerConnectionListener { - int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); - Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); - -- ServerConnectionListener.this.connections.add((Connection) object); // CraftBukkit - decompile error -+ //ServerConnection.this.connectedChannels.add((NetworkManager) object); // CraftBukkit - decompile error -+ pending.add((Connection) object); // Paper - channel.pipeline().addLast("packet_handler", (ChannelHandler) object); - ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); - } -@@ -126,6 +136,7 @@ public class ServerConnectionListener { - - synchronized (this.connections) { - // Spigot Start -+ this.addPending(); // Paper - // This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order - if ( org.spigotmc.SpigotConfig.playerShuffle > 0 && MinecraftServer.currentTick % org.spigotmc.SpigotConfig.playerShuffle == 0 ) - { diff --git a/patches/server-remapped/0103-Optional-TNT-doesn-t-move-in-water.patch b/patches/server-remapped/0103-Optional-TNT-doesn-t-move-in-water.patch deleted file mode 100644 index cd8e56460f..0000000000 --- a/patches/server-remapped/0103-Optional-TNT-doesn-t-move-in-water.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 22 May 2016 20:20:55 -0500 -Subject: [PATCH] Optional TNT doesn't move in water - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index eb04fdb172a50ec1f5b7fe78fa0e7655246abd60..6eca3f300020006f02dd36253b522db442e3cc33 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -2,7 +2,6 @@ package com.destroystokyo.paper; - - import java.util.List; - --import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -291,4 +290,14 @@ public class PaperWorldConfig { - ); - } - } -+ -+ public boolean preventTntFromMovingInWater; -+ private void preventTntFromMovingInWater() { -+ if (PaperConfig.version < 13) { -+ boolean oldVal = getBoolean("enable-old-tnt-cannon-behaviors", false); -+ set("prevent-tnt-from-moving-in-water", oldVal); -+ } -+ preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); -+ log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index fa6893055fa5617742bfb4b7eff60c8139395cb6..49c71b21b6b88bc41ca6ddf4c76186ce522ee456 100644 ---- a/src/main/java/net/minecraft/server/level/ServerEntity.java -+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -66,7 +66,7 @@ public class ServerEntity { - private boolean wasRiding; - private boolean wasOnGround; - // CraftBukkit start -- private final Set trackedPlayers; -+ final Set trackedPlayers; // Paper - private -> package - // Paper start - private java.util.Map trackedPlayerMap = null; - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 171697e88f5a4d8c0be2a47b67b865bbdc4dfe8c..c3aece8e5001828edea304b2a8377e9a28b34cfe 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2770,6 +2770,11 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public boolean isPushedByFluid() { -+ // Paper start -+ return this.pushedByWater(); -+ } -+ public boolean pushedByWater() { -+ // Paper end - return true; - } - -diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -index 661848084fd986321ef782317934dac19ed4dce3..347ac17643de8bcb0c8496c2ea5eb18c2e4d856b 100644 ---- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -@@ -5,9 +5,13 @@ import net.minecraft.core.particles.ParticleTypes; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; -+import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; -+import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket; - import net.minecraft.network.syncher.EntityDataAccessor; - import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; -+import net.minecraft.server.level.ChunkMap; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityDimensions; - import net.minecraft.world.entity.EntityType; -@@ -95,7 +99,27 @@ public class PrimedTnt extends Entity { - this.level.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D); - } - } -- -+ // Paper start - Optional prevent TNT from moving in water -+ if (!this.removed && this.wasTouchingWater && this.level.paperConfig.preventTntFromMovingInWater) { -+ /* -+ * Author: Jedediah Smith -+ */ -+ // Send position and velocity updates to nearby players on every tick while the TNT is in water. -+ // This does pretty well at keeping their clients in sync with the server. -+ ChunkMap.TrackedEntity ete = ((ServerLevel)this.level).getChunkSource().chunkMap.entityMap.get(this.getId()); -+ if (ete != null) { -+ ClientboundSetEntityMotionPacket velocityPacket = new ClientboundSetEntityMotionPacket(this); -+ ClientboundTeleportEntityPacket positionPacket = new ClientboundTeleportEntityPacket(this); -+ -+ ete.seenBy.stream() -+ .filter(viewer -> (viewer.getX() - this.getX()) * (viewer.getY() - this.getY()) * (viewer.getZ() - this.getZ()) < 16 * 16) -+ .forEach(viewer -> { -+ viewer.connection.send(velocityPacket); -+ viewer.connection.send(positionPacket); -+ }); -+ } -+ } -+ // Paper end - } - - private void explode() { -@@ -164,4 +188,11 @@ public class PrimedTnt extends Entity { - public Packet getAddEntityPacket() { - return new ClientboundAddEntityPacket(this); - } -+ -+ // Paper start - Optional prevent TNT from moving in water -+ @Override -+ public boolean pushedByWater() { -+ return !level.paperConfig.preventTntFromMovingInWater && super.pushedByWater(); -+ } -+ // Paper end - } diff --git a/patches/server-remapped/0347-Per-Player-View-Distance-API-placeholders.patch b/patches/server-remapped/0347-Per-Player-View-Distance-API-placeholders.patch deleted file mode 100644 index 1dcd6ab30d..0000000000 --- a/patches/server-remapped/0347-Per-Player-View-Distance-API-placeholders.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 6 May 2019 01:29:25 -0400 -Subject: [PATCH] Per-Player View Distance API placeholders - -I hope to look at this more in-depth soon. It appears doable. -However this should not block the update. - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index 37a9e9df7f7f816c214c37e545288bf9329626ed..ec9436005a3a6fdfb4783d1092bb361224eb6414 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -625,9 +625,10 @@ public class EnderDragon extends Mob implements Enemy { - if (this.dragonDeathTime == 1 && !this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1028, this.getChunkCoordinates(), 0); -- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API - for (net.minecraft.server.level.ServerPlayer player : (List) ((ServerLevel)level).players()) { -- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // Paper end - double deltaX = this.getX() - player.getX(); - double deltaZ = this.getZ() - player.getZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 3a80869dc3c16cb81ac87100f28d63eee722067f..edd231568b75330d0cffbecb03a7e9dbc55d5f94 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -46,6 +46,7 @@ import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerBossEvent; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvent; - import net.minecraft.sounds.SoundEvents; -@@ -255,9 +256,9 @@ public class WitherBoss extends Monster implements RangedAttackMob { - if (!this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1023, new BlockPosition(this), 0); -- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API - for (ServerPlayer player : (List)this.level.players()) { -- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.getX() - player.getX(); - double deltaZ = this.getZ() - player.getZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index c2c6eb54096ef85b01c0b700cbe6a8054b62729f..20de8e358789d05bb5ac15e4cdd7dda85b61b7f8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2240,6 +2240,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - super.remove(); - } - } -+ -+ @Override -+ public int getViewDistance() { -+ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO -+ } -+ -+ @Override -+ public void setViewDistance(int viewDistance) { -+ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO -+ } - // Paper end - - // Spigot start diff --git a/patches/server/0037-Per-Player-View-Distance-API-placeholders.patch b/patches/server/0037-Per-Player-View-Distance-API-placeholders.patch new file mode 100644 index 0000000000..4aaa11ddec --- /dev/null +++ b/patches/server/0037-Per-Player-View-Distance-API-placeholders.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 6 May 2019 01:29:25 -0400 +Subject: [PATCH] Per-Player View Distance API placeholders + +I hope to look at this more in-depth soon. It appears doable. +However this should not block the update. + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index b25f9a2d2d7f0af0fef60c4f1817cf165fed9cd6..74b38b853bd7a59f4cf42afed5ee7ca86b34a8c7 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -170,6 +170,8 @@ import org.bukkit.inventory.MainHand; + + public class ServerPlayer extends Player { + ++ public final int getViewDistance() { return this.getLevel().getChunkSource().chunkMap.viewDistance - 1; } // Paper - placeholder ++ + private static final Logger LOGGER = LogManager.getLogger(); + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 1392d4d5027b3d972b2196af7b19fb409977fb8d..9b4e113b542ca2fc00cf7206d2f50781755119e3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -370,6 +370,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); + } + } ++ ++ @Override ++ public int getViewDistance() { ++ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO ++ } ++ ++ @Override ++ public void setViewDistance(int viewDistance) { ++ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO ++ } + // Paper end + + @Override diff --git a/patches/server/0037-Add-BeaconEffectEvent.patch b/patches/server/0038-Add-BeaconEffectEvent.patch similarity index 100% rename from patches/server/0037-Add-BeaconEffectEvent.patch rename to patches/server/0038-Add-BeaconEffectEvent.patch diff --git a/patches/server/0038-Configurable-container-update-tick-rate.patch b/patches/server/0039-Configurable-container-update-tick-rate.patch similarity index 89% rename from patches/server/0038-Configurable-container-update-tick-rate.patch rename to patches/server/0039-Configurable-container-update-tick-rate.patch index 3fb2e0b00b..789bc82526 100644 --- a/patches/server/0038-Configurable-container-update-tick-rate.patch +++ b/patches/server/0039-Configurable-container-update-tick-rate.patch @@ -19,10 +19,10 @@ index 4de86b09c6bc3c1974ce61b550ccb73d37f6f170..5a4c3a8c511f22c8c3240c9c7cd83a65 + } } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index b25f9a2d2d7f0af0fef60c4f1817cf165fed9cd6..b68a58abf254289a806636ca28521be39c13a82f 100644 +index 74b38b853bd7a59f4cf42afed5ee7ca86b34a8c7..f222721c7bfa555a45c34b489a9e7af59a1f183c 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -214,6 +214,7 @@ public class ServerPlayer extends Player { +@@ -216,6 +216,7 @@ public class ServerPlayer extends Player { private int containerCounter; public int latency; public boolean wonGame; @@ -30,7 +30,7 @@ index b25f9a2d2d7f0af0fef60c4f1817cf165fed9cd6..b68a58abf254289a806636ca28521be3 // CraftBukkit start public String displayName; -@@ -589,7 +590,12 @@ public class ServerPlayer extends Player { +@@ -591,7 +592,12 @@ public class ServerPlayer extends Player { --this.invulnerableTime; } diff --git a/patches/server/0039-Use-UserCache-for-player-heads.patch b/patches/server/0040-Use-UserCache-for-player-heads.patch similarity index 100% rename from patches/server/0039-Use-UserCache-for-player-heads.patch rename to patches/server/0040-Use-UserCache-for-player-heads.patch diff --git a/patches/server/0040-Disable-spigot-tick-limiters.patch b/patches/server/0041-Disable-spigot-tick-limiters.patch similarity index 100% rename from patches/server/0040-Disable-spigot-tick-limiters.patch rename to patches/server/0041-Disable-spigot-tick-limiters.patch diff --git a/patches/server/0041-Add-PlayerInitialSpawnEvent.patch b/patches/server/0042-Add-PlayerInitialSpawnEvent.patch similarity index 100% rename from patches/server/0041-Add-PlayerInitialSpawnEvent.patch rename to patches/server/0042-Add-PlayerInitialSpawnEvent.patch diff --git a/patches/server/0042-Configurable-Disabling-Cat-Chest-Detection.patch b/patches/server/0043-Configurable-Disabling-Cat-Chest-Detection.patch similarity index 100% rename from patches/server/0042-Configurable-Disabling-Cat-Chest-Detection.patch rename to patches/server/0043-Configurable-Disabling-Cat-Chest-Detection.patch diff --git a/patches/server/0043-Ensure-commands-are-not-ran-async.patch b/patches/server/0044-Ensure-commands-are-not-ran-async.patch similarity index 100% rename from patches/server/0043-Ensure-commands-are-not-ran-async.patch rename to patches/server/0044-Ensure-commands-are-not-ran-async.patch diff --git a/patches/server/0044-All-chunks-are-slime-spawn-chunks-toggle.patch b/patches/server/0045-All-chunks-are-slime-spawn-chunks-toggle.patch similarity index 100% rename from patches/server/0044-All-chunks-are-slime-spawn-chunks-toggle.patch rename to patches/server/0045-All-chunks-are-slime-spawn-chunks-toggle.patch diff --git a/patches/server/0045-Expose-server-CommandMap.patch b/patches/server/0046-Expose-server-CommandMap.patch similarity index 100% rename from patches/server/0045-Expose-server-CommandMap.patch rename to patches/server/0046-Expose-server-CommandMap.patch diff --git a/patches/server/0046-Be-a-bit-more-informative-in-maxHealth-exception.patch b/patches/server/0047-Be-a-bit-more-informative-in-maxHealth-exception.patch similarity index 100% rename from patches/server/0046-Be-a-bit-more-informative-in-maxHealth-exception.patch rename to patches/server/0047-Be-a-bit-more-informative-in-maxHealth-exception.patch diff --git a/patches/server/0047-Player-Tab-List-and-Title-APIs.patch b/patches/server/0048-Player-Tab-List-and-Title-APIs.patch similarity index 98% rename from patches/server/0047-Player-Tab-List-and-Title-APIs.patch rename to patches/server/0048-Player-Tab-List-and-Title-APIs.patch index 5a6bb6c55d..9c38b3fa48 100644 --- a/patches/server/0047-Player-Tab-List-and-Title-APIs.patch +++ b/patches/server/0048-Player-Tab-List-and-Title-APIs.patch @@ -33,7 +33,7 @@ index 02d19fa4abdee0c8331734932a83e64694356030..969aea457e76b853e34a67a8fd07e0ea public static MutableComponent fromJson(String json) { return (MutableComponent) GsonHelper.fromJson(Component.Serializer.GSON, json, MutableComponent.class, false); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 1392d4d5027b3d972b2196af7b19fb409977fb8d..145f1ae878a6a6d91f291573f150c66363f151fd 100644 +index 9b4e113b542ca2fc00cf7206d2f50781755119e3..9d29db04e3d83e98ae3819b34cbb19f3ec3bf43c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1,5 +1,6 @@ diff --git a/patches/server/0048-Ensure-inv-drag-is-in-bounds.patch b/patches/server/0049-Ensure-inv-drag-is-in-bounds.patch similarity index 100% rename from patches/server/0048-Ensure-inv-drag-is-in-bounds.patch rename to patches/server/0049-Ensure-inv-drag-is-in-bounds.patch diff --git a/patches/server/0049-Add-configurable-portal-search-radius.patch b/patches/server/0050-Add-configurable-portal-search-radius.patch similarity index 100% rename from patches/server/0049-Add-configurable-portal-search-radius.patch rename to patches/server/0050-Add-configurable-portal-search-radius.patch diff --git a/patches/server/0050-Add-velocity-warnings.patch b/patches/server/0051-Add-velocity-warnings.patch similarity index 100% rename from patches/server/0050-Add-velocity-warnings.patch rename to patches/server/0051-Add-velocity-warnings.patch diff --git a/patches/server/0051-Configurable-inter-world-teleportation-safety.patch b/patches/server/0052-Configurable-inter-world-teleportation-safety.patch similarity index 93% rename from patches/server/0051-Configurable-inter-world-teleportation-safety.patch rename to patches/server/0052-Configurable-inter-world-teleportation-safety.patch index d8ac211487..0571aa165d 100644 --- a/patches/server/0051-Configurable-inter-world-teleportation-safety.patch +++ b/patches/server/0052-Configurable-inter-world-teleportation-safety.patch @@ -30,10 +30,10 @@ index 670efbe53241a0ae32d618c83da601ccc1f26e37..abbbe1786eb68af02f9d39650aad730a + } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 145f1ae878a6a6d91f291573f150c66363f151fd..34c249bff7f32aa3e58c04a1bc0f65f5f410d714 100644 +index 9d29db04e3d83e98ae3819b34cbb19f3ec3bf43c..7a256faba6946f4f3847dd439e6c520e022b4354 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -864,7 +864,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -874,7 +874,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (fromWorld == toWorld) { entity.connection.teleport(to); } else { diff --git a/patches/server/0052-Add-exception-reporting-event.patch b/patches/server/0053-Add-exception-reporting-event.patch similarity index 100% rename from patches/server/0052-Add-exception-reporting-event.patch rename to patches/server/0053-Add-exception-reporting-event.patch diff --git a/patches/server/0053-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/patches/server/0054-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch similarity index 100% rename from patches/server/0053-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch rename to patches/server/0054-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch diff --git a/patches/server/0054-Disable-Scoreboards-for-non-players-by-default.patch b/patches/server/0055-Disable-Scoreboards-for-non-players-by-default.patch similarity index 100% rename from patches/server/0054-Disable-Scoreboards-for-non-players-by-default.patch rename to patches/server/0055-Disable-Scoreboards-for-non-players-by-default.patch diff --git a/patches/server/0055-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/server/0056-Add-methods-for-working-with-arrows-stuck-in-living-.patch similarity index 100% rename from patches/server/0055-Add-methods-for-working-with-arrows-stuck-in-living-.patch rename to patches/server/0056-Add-methods-for-working-with-arrows-stuck-in-living-.patch diff --git a/patches/server/0056-Complete-resource-pack-API.patch b/patches/server/0057-Complete-resource-pack-API.patch similarity index 95% rename from patches/server/0056-Complete-resource-pack-API.patch rename to patches/server/0057-Complete-resource-pack-API.patch index be7144661d..9a7ef1068c 100644 --- a/patches/server/0056-Complete-resource-pack-API.patch +++ b/patches/server/0057-Complete-resource-pack-API.patch @@ -23,7 +23,7 @@ index b38ca69d37d7f1af0e34297f45e63a98da754e35..714fb0d766b654ad05134dea9b1e1b62 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 34c249bff7f32aa3e58c04a1bc0f65f5f410d714..6aabe32512abc974e114e273a41e09804b349cb9 100644 +index 7a256faba6946f4f3847dd439e6c520e022b4354..56bdc8ba0e3bd09a12f6572542e99a1ea3a76670 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -141,6 +141,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @@ -37,7 +37,7 @@ index 34c249bff7f32aa3e58c04a1bc0f65f5f410d714..6aabe32512abc974e114e273a41e0980 public CraftPlayer(CraftServer server, ServerPlayer entity) { super(server, entity); -@@ -1875,6 +1879,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1885,6 +1889,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public boolean getAffectsSpawning() { return this.getHandle().affectsSpawning; } diff --git a/patches/server/0057-Chunk-Save-Reattempt.patch b/patches/server/0058-Chunk-Save-Reattempt.patch similarity index 100% rename from patches/server/0057-Chunk-Save-Reattempt.patch rename to patches/server/0058-Chunk-Save-Reattempt.patch diff --git a/patches/server/0058-Default-loading-permissions.yml-before-plugins.patch b/patches/server/0059-Default-loading-permissions.yml-before-plugins.patch similarity index 100% rename from patches/server/0058-Default-loading-permissions.yml-before-plugins.patch rename to patches/server/0059-Default-loading-permissions.yml-before-plugins.patch diff --git a/patches/server/0059-Allow-Reloading-of-Custom-Permissions.patch b/patches/server/0060-Allow-Reloading-of-Custom-Permissions.patch similarity index 100% rename from patches/server/0059-Allow-Reloading-of-Custom-Permissions.patch rename to patches/server/0060-Allow-Reloading-of-Custom-Permissions.patch diff --git a/patches/server/0060-Remove-Metadata-on-reload.patch b/patches/server/0061-Remove-Metadata-on-reload.patch similarity index 100% rename from patches/server/0060-Remove-Metadata-on-reload.patch rename to patches/server/0061-Remove-Metadata-on-reload.patch diff --git a/patches/server/0061-Handle-Item-Meta-Inconsistencies.patch b/patches/server/0062-Handle-Item-Meta-Inconsistencies.patch similarity index 100% rename from patches/server/0061-Handle-Item-Meta-Inconsistencies.patch rename to patches/server/0062-Handle-Item-Meta-Inconsistencies.patch diff --git a/patches/server/0062-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/patches/server/0063-Configurable-Non-Player-Arrow-Despawn-Rate.patch similarity index 100% rename from patches/server/0062-Configurable-Non-Player-Arrow-Despawn-Rate.patch rename to patches/server/0063-Configurable-Non-Player-Arrow-Despawn-Rate.patch diff --git a/patches/server/0063-Add-World-Util-Methods.patch b/patches/server/0064-Add-World-Util-Methods.patch similarity index 100% rename from patches/server/0063-Add-World-Util-Methods.patch rename to patches/server/0064-Add-World-Util-Methods.patch diff --git a/patches/server/0064-Custom-replacement-for-eaten-items.patch b/patches/server/0065-Custom-replacement-for-eaten-items.patch similarity index 100% rename from patches/server/0064-Custom-replacement-for-eaten-items.patch rename to patches/server/0065-Custom-replacement-for-eaten-items.patch diff --git a/patches/server/0065-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/patches/server/0066-handle-NaN-health-absorb-values-and-repair-bad-data.patch similarity index 94% rename from patches/server/0065-handle-NaN-health-absorb-values-and-repair-bad-data.patch rename to patches/server/0066-handle-NaN-health-absorb-values-and-repair-bad-data.patch index d2ec2e60a6..26d4160aff 100644 --- a/patches/server/0065-handle-NaN-health-absorb-values-and-repair-bad-data.patch +++ b/patches/server/0066-handle-NaN-health-absorb-values-and-repair-bad-data.patch @@ -49,10 +49,10 @@ index 89db2afd198366ab94c9c074890aa668d3771a79..83eaa3c6581c1a3f588278124fed4c81 } + diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 6aabe32512abc974e114e273a41e09804b349cb9..2f8bcf5290d02cfc41496fd3ae8a63c08d514af8 100644 +index 56bdc8ba0e3bd09a12f6572542e99a1ea3a76670..836692160077935c45b25f7002079111ebb91a6e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1681,6 +1681,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1691,6 +1691,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void setRealHealth(double health) { diff --git a/patches/server/0066-Use-a-Shared-Random-for-Entities.patch b/patches/server/0067-Use-a-Shared-Random-for-Entities.patch similarity index 100% rename from patches/server/0066-Use-a-Shared-Random-for-Entities.patch rename to patches/server/0067-Use-a-Shared-Random-for-Entities.patch diff --git a/patches/server/0067-Configurable-spawn-chances-for-skeleton-horses.patch b/patches/server/0068-Configurable-spawn-chances-for-skeleton-horses.patch similarity index 100% rename from patches/server/0067-Configurable-spawn-chances-for-skeleton-horses.patch rename to patches/server/0068-Configurable-spawn-chances-for-skeleton-horses.patch diff --git a/patches/server/0068-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/patches/server/0069-Optimize-isValidLocation-getType-and-getBlockData-fo.patch similarity index 100% rename from patches/server/0068-Optimize-isValidLocation-getType-and-getBlockData-fo.patch rename to patches/server/0069-Optimize-isValidLocation-getType-and-getBlockData-fo.patch diff --git a/patches/server/0069-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/patches/server/0070-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch similarity index 100% rename from patches/server/0069-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch rename to patches/server/0070-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch diff --git a/patches/server/0070-Entity-AddTo-RemoveFrom-World-Events.patch b/patches/server/0071-Entity-AddTo-RemoveFrom-World-Events.patch similarity index 100% rename from patches/server/0070-Entity-AddTo-RemoveFrom-World-Events.patch rename to patches/server/0071-Entity-AddTo-RemoveFrom-World-Events.patch diff --git a/patches/server/0071-Configurable-Chunk-Inhabited-Time.patch b/patches/server/0072-Configurable-Chunk-Inhabited-Time.patch similarity index 100% rename from patches/server/0071-Configurable-Chunk-Inhabited-Time.patch rename to patches/server/0072-Configurable-Chunk-Inhabited-Time.patch diff --git a/patches/server/0072-EntityPathfindEvent.patch b/patches/server/0073-EntityPathfindEvent.patch similarity index 100% rename from patches/server/0072-EntityPathfindEvent.patch rename to patches/server/0073-EntityPathfindEvent.patch diff --git a/patches/server/0073-Sanitise-RegionFileCache-and-make-configurable.patch b/patches/server/0074-Sanitise-RegionFileCache-and-make-configurable.patch similarity index 100% rename from patches/server/0073-Sanitise-RegionFileCache-and-make-configurable.patch rename to patches/server/0074-Sanitise-RegionFileCache-and-make-configurable.patch diff --git a/patches/server/0074-Do-not-load-chunks-for-Pathfinding.patch b/patches/server/0075-Do-not-load-chunks-for-Pathfinding.patch similarity index 100% rename from patches/server/0074-Do-not-load-chunks-for-Pathfinding.patch rename to patches/server/0075-Do-not-load-chunks-for-Pathfinding.patch diff --git a/patches/server/0075-Add-PlayerUseUnknownEntityEvent.patch b/patches/server/0076-Add-PlayerUseUnknownEntityEvent.patch similarity index 100% rename from patches/server/0075-Add-PlayerUseUnknownEntityEvent.patch rename to patches/server/0076-Add-PlayerUseUnknownEntityEvent.patch diff --git a/patches/server/0076-Fix-reducedDebugInfo-not-initialized-on-client.patch b/patches/server/0077-Fix-reducedDebugInfo-not-initialized-on-client.patch similarity index 100% rename from patches/server/0076-Fix-reducedDebugInfo-not-initialized-on-client.patch rename to patches/server/0077-Fix-reducedDebugInfo-not-initialized-on-client.patch diff --git a/patches/server/0077-Configurable-Grass-Spread-Tick-Rate.patch b/patches/server/0078-Configurable-Grass-Spread-Tick-Rate.patch similarity index 100% rename from patches/server/0077-Configurable-Grass-Spread-Tick-Rate.patch rename to patches/server/0078-Configurable-Grass-Spread-Tick-Rate.patch diff --git a/patches/server/0078-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/patches/server/0079-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch similarity index 100% rename from patches/server/0078-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch rename to patches/server/0079-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch diff --git a/patches/server/0079-Optimize-DataBits.patch b/patches/server/0080-Optimize-DataBits.patch similarity index 100% rename from patches/server/0079-Optimize-DataBits.patch rename to patches/server/0080-Optimize-DataBits.patch diff --git a/patches/server/0080-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/patches/server/0081-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch similarity index 100% rename from patches/server/0080-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch rename to patches/server/0081-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch diff --git a/patches/server/0081-Workaround-for-setting-passengers-on-players.patch b/patches/server/0082-Workaround-for-setting-passengers-on-players.patch similarity index 87% rename from patches/server/0081-Workaround-for-setting-passengers-on-players.patch rename to patches/server/0082-Workaround-for-setting-passengers-on-players.patch index 0a081245dd..1a1869f691 100644 --- a/patches/server/0081-Workaround-for-setting-passengers-on-players.patch +++ b/patches/server/0082-Workaround-for-setting-passengers-on-players.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Workaround for setting passengers on players SPIGOT-1915 & GH-114 diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 2f8bcf5290d02cfc41496fd3ae8a63c08d514af8..b93a02dce55952321874528016ea48e5a35bd772 100644 +index 836692160077935c45b25f7002079111ebb91a6e..2605f2b34206f8eaffcb0e5ae0b928261ab366d2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -873,6 +873,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -883,6 +883,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return true; } diff --git a/patches/server/0082-Configurable-Player-Collision.patch b/patches/server/0083-Configurable-Player-Collision.patch similarity index 100% rename from patches/server/0082-Configurable-Player-Collision.patch rename to patches/server/0083-Configurable-Player-Collision.patch diff --git a/patches/server/0083-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/patches/server/0084-Add-handshake-event-to-allow-plugins-to-handle-clien.patch similarity index 100% rename from patches/server/0083-Add-handshake-event-to-allow-plugins-to-handle-clien.patch rename to patches/server/0084-Add-handshake-event-to-allow-plugins-to-handle-clien.patch diff --git a/patches/server/0084-Configurable-RCON-IP-address.patch b/patches/server/0085-Configurable-RCON-IP-address.patch similarity index 100% rename from patches/server/0084-Configurable-RCON-IP-address.patch rename to patches/server/0085-Configurable-RCON-IP-address.patch diff --git a/patches/server/0085-Implement-PlayerLocaleChangeEvent.patch b/patches/server/0086-Implement-PlayerLocaleChangeEvent.patch similarity index 85% rename from patches/server/0085-Implement-PlayerLocaleChangeEvent.patch rename to patches/server/0086-Implement-PlayerLocaleChangeEvent.patch index 8aa65a2052..c633928f6f 100644 --- a/patches/server/0085-Implement-PlayerLocaleChangeEvent.patch +++ b/patches/server/0086-Implement-PlayerLocaleChangeEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Implement PlayerLocaleChangeEvent diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index b68a58abf254289a806636ca28521be39c13a82f..0a59e3b405d5074ab326e6ddb265a714e4038e86 100644 +index f222721c7bfa555a45c34b489a9e7af59a1f183c..f48d7205242fc38c00e496c88090e0e98e394b39 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1712,7 +1712,7 @@ public class ServerPlayer extends Player { +@@ -1714,7 +1714,7 @@ public class ServerPlayer extends Player { return s; } @@ -17,7 +17,7 @@ index b68a58abf254289a806636ca28521be39c13a82f..0a59e3b405d5074ab326e6ddb265a714 public java.util.Locale adventure$locale = java.util.Locale.US; // Paper public void updateOptions(ServerboundClientInformationPacket packet) { // CraftBukkit start -@@ -1720,9 +1720,10 @@ public class ServerPlayer extends Player { +@@ -1722,9 +1722,10 @@ public class ServerPlayer extends Player { PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(this.getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); this.server.server.getPluginManager().callEvent(event); } @@ -30,10 +30,10 @@ index b68a58abf254289a806636ca28521be39c13a82f..0a59e3b405d5074ab326e6ddb265a714 this.locale = packet.language; // Paper start diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b93a02dce55952321874528016ea48e5a35bd772..b9320aa8e3fc3216753f7d4e3d4b2bda9ec403ef 100644 +index 2605f2b34206f8eaffcb0e5ae0b928261ab366d2..d50ce7fc675fcc57f591e90eb0bbb99a4ab21b02 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1878,8 +1878,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1888,8 +1888,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public String getLocale() { diff --git a/patches/server/0086-EntityRegainHealthEvent-isFastRegen-API.patch b/patches/server/0087-EntityRegainHealthEvent-isFastRegen-API.patch similarity index 100% rename from patches/server/0086-EntityRegainHealthEvent-isFastRegen-API.patch rename to patches/server/0087-EntityRegainHealthEvent-isFastRegen-API.patch diff --git a/patches/server/0087-Add-ability-to-configure-frosted_ice-properties.patch b/patches/server/0088-Add-ability-to-configure-frosted_ice-properties.patch similarity index 100% rename from patches/server/0087-Add-ability-to-configure-frosted_ice-properties.patch rename to patches/server/0088-Add-ability-to-configure-frosted_ice-properties.patch diff --git a/patches/server/0088-remove-null-possibility-for-getServer-singleton.patch b/patches/server/0089-remove-null-possibility-for-getServer-singleton.patch similarity index 100% rename from patches/server/0088-remove-null-possibility-for-getServer-singleton.patch rename to patches/server/0089-remove-null-possibility-for-getServer-singleton.patch diff --git a/patches/server/0089-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch b/patches/server/0090-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch similarity index 100% rename from patches/server/0089-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch rename to patches/server/0090-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch diff --git a/patches/server/0090-LootTable-API-Replenishable-Lootables-Feature.patch b/patches/server/0091-LootTable-API-Replenishable-Lootables-Feature.patch similarity index 99% rename from patches/server/0090-LootTable-API-Replenishable-Lootables-Feature.patch rename to patches/server/0091-LootTable-API-Replenishable-Lootables-Feature.patch index 8b4517c77d..d1eee7245f 100644 --- a/patches/server/0090-LootTable-API-Replenishable-Lootables-Feature.patch +++ b/patches/server/0091-LootTable-API-Replenishable-Lootables-Feature.patch @@ -82,13 +82,12 @@ index 0000000000000000000000000000000000000000..70ca5625ff5d13a8e9cd64953066a7e1 +} diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java new file mode 100644 -index 0000000000000000000000000000000000000000..292d5ef8a1c428893af729b298eecd32b4c4659a +index 0000000000000000000000000000000000000000..2fba5bc0f982e143ad5f5bda55d768edc5f847df --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java -@@ -0,0 +1,29 @@ +@@ -0,0 +1,28 @@ +package com.destroystokyo.paper.loottable; + -+import LootableInventory; +import net.minecraft.world.level.Level; +import org.bukkit.entity.Entity; + diff --git a/patches/server-remapped/0099-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/patches/server/0092-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch similarity index 69% rename from patches/server-remapped/0099-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch rename to patches/server/0092-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch index f9fbbc4e75..512d352730 100644 --- a/patches/server-remapped/0099-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch +++ b/patches/server/0092-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch @@ -19,14 +19,14 @@ index 504efea7b6f50a0d17f4f353781953dfb18bdeca..1b8e5671c9dc8c15ce33d351c1bb20f2 + } } diff --git a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java -index 36a922029687b9fa3ca3a986ae42a373ced87a0e..b9e14d1c54b690f0b975bda5733c4cb4f6449f77 100644 +index 90a97a87fe67d8c3bbc60f08c9911faa4259349e..2153e7035535990b5307b85d8bc3dab50c0a3ae8 100644 --- a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java +++ b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java -@@ -182,6 +182,7 @@ public class ScoreboardSaveData extends SavedData { +@@ -144,6 +144,7 @@ public class ScoreboardSaveData extends SavedData { + ListTag listTag = new ListTag(); - while (iterator.hasNext()) { - PlayerTeam scoreboardteam = (PlayerTeam) iterator.next(); -+ if (!com.destroystokyo.paper.PaperConfig.saveEmptyScoreboardTeams && scoreboardteam.getPlayers().isEmpty()) continue; // Paper - CompoundTag nbttagcompound = new CompoundTag(); - - nbttagcompound.putString("Name", scoreboardteam.getName()); + for(PlayerTeam playerTeam : this.scoreboard.getPlayerTeams()) { ++ if (!com.destroystokyo.paper.PaperConfig.saveEmptyScoreboardTeams && playerTeam.getPlayers().isEmpty()) continue; // Paper + CompoundTag compoundTag = new CompoundTag(); + compoundTag.putString("Name", playerTeam.getName()); + compoundTag.putString("DisplayName", Component.Serializer.toJson(playerTeam.getDisplayName())); diff --git a/patches/server-remapped/0100-System-property-for-disabling-watchdoge.patch b/patches/server/0093-System-property-for-disabling-watchdoge.patch similarity index 58% rename from patches/server-remapped/0100-System-property-for-disabling-watchdoge.patch rename to patches/server/0093-System-property-for-disabling-watchdoge.patch index d8a22a7f5f..8d880e6928 100644 --- a/patches/server-remapped/0100-System-property-for-disabling-watchdoge.patch +++ b/patches/server/0093-System-property-for-disabling-watchdoge.patch @@ -5,15 +5,15 @@ Subject: [PATCH] System property for disabling watchdoge diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 0ed95268364ea7f6a92a39b726a1e03bc815be07..ee0cca25ef458f2f0f7e450a2edea2b2adb7e846 100644 +index 2693cc933d746e40d8a47d96c6cb6799f0a2472f..6e1fa4f0616ccfd258acd1b4f5b08fc0ad4c9529 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java @@ -61,7 +61,7 @@ public class WatchdogThread extends Thread - while ( !stopping ) + while ( !this.stopping ) { // -- if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime ) -+ if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable +- if ( this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.monotonicMillis() > this.lastTick + this.timeoutTime ) ++ if ( this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.monotonicMillis() > this.lastTick + this.timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable { Logger log = Bukkit.getServer().getLogger(); log.log( Level.SEVERE, "------------------------------" ); diff --git a/patches/server-remapped/0101-Optimize-UserCache-Thread-Safe.patch b/patches/server/0094-Optimize-UserCache-Thread-Safe.patch similarity index 62% rename from patches/server-remapped/0101-Optimize-UserCache-Thread-Safe.patch rename to patches/server/0094-Optimize-UserCache-Thread-Safe.patch index 4b08a22748..70a622d00d 100644 --- a/patches/server-remapped/0101-Optimize-UserCache-Thread-Safe.patch +++ b/patches/server/0094-Optimize-UserCache-Thread-Safe.patch @@ -9,105 +9,99 @@ easier to do this than replace the entire thing. Additionally, move Saving of the User cache to be done async, incase the user never changed the default setting for Spigot's save on stop only. +1.17: TODO does this need the synchronized blocks anymore? + diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 4e468cb7ccf683b8fc9e04a48cfc25779775e25f..211251fe7cd08074c040df2f4642f37d5f90d856 100644 +index ef231e11b90b24418a77b62f5fe766c9ac10c09b..74073d3f8c9dda6f10e9fb34071dae079b73fb24 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -905,7 +905,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Paper try { BufferedWriter bufferedwriter = Files.newWriter(this.file, StandardCharsets.UTF_8); -@@ -268,6 +270,14 @@ public class GameProfileCache { +@@ -305,6 +306,14 @@ public class GameProfileCache { } catch (IOException ioexception) { ; } + // Paper start + }; + if (asyncSave) { -+ MCUtil.scheduleAsyncTask(save); ++ net.minecraft.server.MCUtil.scheduleAsyncTask(save); + } else { + save.run(); + } diff --git a/patches/server/0095-Optional-TNT-doesn-t-move-in-water.patch b/patches/server/0095-Optional-TNT-doesn-t-move-in-water.patch new file mode 100644 index 0000000000..efbfcf82f0 --- /dev/null +++ b/patches/server/0095-Optional-TNT-doesn-t-move-in-water.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sun, 22 May 2016 20:20:55 -0500 +Subject: [PATCH] Optional TNT doesn't move in water + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index eb04fdb172a50ec1f5b7fe78fa0e7655246abd60..9b2e9a02ff31c3cb37b67135d0a03441f247d8e2 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -291,4 +291,14 @@ public class PaperWorldConfig { + ); + } + } ++ ++ public boolean preventTntFromMovingInWater; ++ private void preventTntFromMovingInWater() { ++ if (PaperConfig.version < 13) { ++ boolean oldVal = getBoolean("enable-old-tnt-cannon-behaviors", false); ++ set("prevent-tnt-from-moving-in-water", oldVal); ++ } ++ preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); ++ log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index ac57bfb00edd9268e89a7fd7cea36097d61d6951..ad9bbda31a4cdb306ca40f2b99e4b815c4f136bd 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -68,7 +68,7 @@ public class ServerEntity { + private boolean wasRiding; + private boolean wasOnGround; + // CraftBukkit start +- private final Set trackedPlayers; ++ final Set trackedPlayers; // Paper - private -> package + + public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { + this.trackedPlayers = trackedPlayers; +diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +index abc62c560816d945642d830a020deb28ff2efa37..5a16de4f080c31d6e278363fd1d3e23d48be3db5 100644 +--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +@@ -97,6 +97,27 @@ public class PrimedTnt extends Entity { + } + } + ++ // Paper start - Optional prevent TNT from moving in water ++ if (!this.isRemoved() && this.wasTouchingWater && this.level.paperConfig.preventTntFromMovingInWater) { ++ /* ++ * Author: Jedediah Smith ++ */ ++ // Send position and velocity updates to nearby players on every tick while the TNT is in water. ++ // This does pretty well at keeping their clients in sync with the server. ++ net.minecraft.server.level.ChunkMap.TrackedEntity ete = ((net.minecraft.server.level.ServerLevel)this.level).getChunkSource().chunkMap.entityMap.get(this.getId()); ++ if (ete != null) { ++ net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket velocityPacket = new net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket(this); ++ net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket positionPacket = new net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket(this); ++ ++ ete.seenBy.stream() ++ .filter(viewer -> (viewer.getPlayer().getX() - this.getX()) * (viewer.getPlayer().getY() - this.getY()) * (viewer.getPlayer().getZ() - this.getZ()) < 16 * 16) ++ .forEach(viewer -> { ++ viewer.send(velocityPacket); ++ viewer.send(positionPacket); ++ }); ++ } ++ } ++ // Paper end + } + + private void explode() { +@@ -152,4 +173,11 @@ public class PrimedTnt extends Entity { + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this); + } ++ ++ // Paper start - Optional prevent TNT from moving in water ++ @Override ++ public boolean isPushedByFluid() { ++ return !level.paperConfig.preventTntFromMovingInWater && super.isPushedByFluid(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0104-Faster-redstone-torch-rapid-clock-removal.patch b/patches/server/0096-Faster-redstone-torch-rapid-clock-removal.patch similarity index 69% rename from patches/server-remapped/0104-Faster-redstone-torch-rapid-clock-removal.patch rename to patches/server/0096-Faster-redstone-torch-rapid-clock-removal.patch index cc437e7353..89a9e109f6 100644 --- a/patches/server-remapped/0104-Faster-redstone-torch-rapid-clock-removal.patch +++ b/patches/server/0096-Faster-redstone-torch-rapid-clock-removal.patch @@ -6,27 +6,19 @@ Subject: [PATCH] Faster redstone torch rapid clock removal Only resize the the redstone torch list once, since resizing arrays / lists is costly diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 8f0fec38b482465285057d3fd27d456cf036f2fd..5f3d17cb247156fc8aaa7a763e402c2bbb42a7ec 100644 +index fa567322ca3f09d81479826b0119ddc922c41d11..e26cb05a91cf2b3ac059dcb55bc52f1e4f30b362 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -48,6 +48,7 @@ import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.BaseFireBlock; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.Blocks; -+import net.minecraft.world.level.block.RedstoneTorchBlock; - import net.minecraft.world.level.block.entity.BlockEntity; - import net.minecraft.world.level.block.entity.BlockEntityType; - import net.minecraft.world.level.block.entity.TickableBlockEntity; -@@ -142,6 +143,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -159,6 +159,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { private org.spigotmc.TickLimiter tileLimiter; private int tileTickPosition; public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions -+ public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here ++ public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here public CraftWorld getWorld() { return this.world; diff --git a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java -index 7d71c99c2268174fbea4297f028b75a3a0f43c11..dd4391086aff05bdea81e62b950b88cfab5ac6b8 100644 +index 28e785813628e5763576812ec6201d1e5b1def23..47df36208d91dad126849e29c0e410f95b168f23 100644 --- a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java +++ b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java @@ -21,7 +21,7 @@ import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit @@ -35,10 +27,10 @@ index 7d71c99c2268174fbea4297f028b75a3a0f43c11..dd4391086aff05bdea81e62b950b88cf public static final BooleanProperty LIT = BlockStateProperties.LIT; - private static final Map> RECENT_TOGGLES = new WeakHashMap(); + // Paper - Move the mapped list to World - - protected RedstoneTorchBlock(BlockBehaviour.Properties settings) { - super(settings, DustParticleOptions.REDSTONE); -@@ -68,11 +68,15 @@ public class RedstoneTorchBlock extends TorchBlock { + public static final int RECENT_TOGGLE_TIMER = 60; + public static final int MAX_RECENT_TOGGLES = 8; + public static final int RESTART_DELAY = 160; +@@ -72,11 +72,15 @@ public class RedstoneTorchBlock extends TorchBlock { @Override public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) { boolean flag = this.hasNeighborSignal((Level) world, pos, state); @@ -50,7 +42,7 @@ index 7d71c99c2268174fbea4297f028b75a3a0f43c11..dd4391086aff05bdea81e62b950b88cf + java.util.ArrayDeque redstoneUpdateInfos = world.redstoneUpdateInfos; + if (redstoneUpdateInfos != null) { + RedstoneTorchBlock.Toggle curr; -+ while ((curr = redstoneUpdateInfos.peek()) != null && world.getGameTime() - curr.getTime() > 60L) { ++ while ((curr = redstoneUpdateInfos.peek()) != null && world.getGameTime() - curr.when > 60L) { + redstoneUpdateInfos.poll(); + } } @@ -58,7 +50,7 @@ index 7d71c99c2268174fbea4297f028b75a3a0f43c11..dd4391086aff05bdea81e62b950b88cf // CraftBukkit start org.bukkit.plugin.PluginManager manager = world.getCraftServer().getPluginManager(); -@@ -137,9 +141,12 @@ public class RedstoneTorchBlock extends TorchBlock { +@@ -152,9 +156,12 @@ public class RedstoneTorchBlock extends TorchBlock { } private static boolean isToggledTooFrequently(Level world, BlockPos pos, boolean addNew) { @@ -74,7 +66,7 @@ index 7d71c99c2268174fbea4297f028b75a3a0f43c11..dd4391086aff05bdea81e62b950b88cf if (addNew) { list.add(new RedstoneTorchBlock.Toggle(pos.immutable(), world.getGameTime())); -@@ -147,9 +154,9 @@ public class RedstoneTorchBlock extends TorchBlock { +@@ -162,9 +169,9 @@ public class RedstoneTorchBlock extends TorchBlock { int i = 0; @@ -87,12 +79,3 @@ index 7d71c99c2268174fbea4297f028b75a3a0f43c11..dd4391086aff05bdea81e62b950b88cf if (blockredstonetorch_redstoneupdateinfo.pos.equals(pos)) { ++i; if (i >= 8) { -@@ -164,7 +171,7 @@ public class RedstoneTorchBlock extends TorchBlock { - public static class Toggle { - - private final BlockPos pos; -- private final long when; -+ private final long when; final long getTime() { return this.when; } // Paper - OBFHELPER - - public Toggle(BlockPos pos, long time) { - this.pos = pos; diff --git a/patches/server-remapped/0105-Add-server-name-parameter.patch b/patches/server/0097-Add-server-name-parameter.patch similarity index 90% rename from patches/server-remapped/0105-Add-server-name-parameter.patch rename to patches/server/0097-Add-server-name-parameter.patch index 50ec621547..91becbdb5d 100644 --- a/patches/server-remapped/0105-Add-server-name-parameter.patch +++ b/patches/server/0097-Add-server-name-parameter.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add server-name parameter diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2..b849b2afd009da433fe6cea5837b3ee9bb5c52b4 100644 +index 399cb06c7ae3570d08430e8675f141657d1026d4..6985e8dc3d520eb65ae7d885138be81836452c01 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -143,6 +143,14 @@ public class Main { diff --git a/patches/server-remapped/0106-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/patches/server/0098-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch similarity index 80% rename from patches/server-remapped/0106-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch rename to patches/server/0098-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch index e84fc6a07e..a8e8cec032 100644 --- a/patches/server-remapped/0106-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch +++ b/patches/server/0098-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Only send Dragon/Wither Death sounds to same world Also fix view distance lookup diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index 8d1b3cbb21fe798c27ad2d39bccffa9cc983cf96..39298b69918da890c3faa516f80d1a69adb88fe2 100644 +index 3a2a20c407374e5e62aa8ef2967a5b189d4e9658..9d6d8bf5f38ec11f26665ae676c46e4ef089670b 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -619,8 +619,9 @@ public class EnderDragon extends Mob implements Enemy { +@@ -640,8 +640,9 @@ public class EnderDragon extends Mob implements Enemy { if (this.dragonDeathTime == 1 && !this.isSilent()) { // CraftBukkit start - Use relative location for far away sounds // this.world.b(1028, this.getChunkCoordinates(), 0); @@ -22,18 +22,10 @@ index 8d1b3cbb21fe798c27ad2d39bccffa9cc983cf96..39298b69918da890c3faa516f80d1a69 double deltaZ = this.getZ() - player.getZ(); double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 61c982ead18334a29438ef8e024d97ead178a2c8..3a80869dc3c16cb81ac87100f28d63eee722067f 100644 +index e231bb4d0bbb19b219ec78e4c1084103c0070733..03263689479d0f163fceb834bda07e7be13b798d 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -46,7 +46,6 @@ import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerBossEvent; --import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvent; - import net.minecraft.sounds.SoundEvents; -@@ -256,8 +255,9 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -260,8 +260,9 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob if (!this.isSilent()) { // CraftBukkit start - Use relative location for far away sounds // this.world.b(1023, new BlockPosition(this), 0); From 42458fbca4a126f0e1cba1012ea0730c9f13d133 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Fri, 11 Jun 2021 23:02:49 -0700 Subject: [PATCH 036/226] even even more progress --- .../0038-Add-EntityZapEvent.patch} | 0 .../0107-Fix-Double-World-Add-issues.patch | 3 ++ .../1.17}/0114-Chunk-registration-fixes.patch | 2 ++ ...ve-invalid-mob-spawner-tile-entities.patch | 4 +-- .../0053-Add-exception-reporting-event.patch | 4 +-- .../0099-Fix-Old-Sign-Conversion.patch} | 36 +++++++------------ ...-profiles-that-have-no-UUID-and-no-.patch} | 8 ++--- ...etting-for-proxy-online-mode-status.patch} | 23 ++++++------ ...timise-BlockState-s-hashCode-equals.patch} | 34 ++++++------------ ...nfigurable-packet-in-spam-threshold.patch} | 16 ++++----- ...4-Configurable-flying-kick-messages.patch} | 6 ++-- ...k-reference-on-Craft-Entity-removal.patch} | 5 +-- ...to-fix-bad-Y-levels-on-player-login.patch} | 14 ++++---- ...ion-to-remove-corrupt-tile-entities.patch} | 12 +++---- .../0108-Add-EntityZapEvent.patch} | 20 +++++++---- 15 files changed, 88 insertions(+), 99 deletions(-) rename patches/{api-unmapped/0037-Add-EntityZapEvent.patch => api/0038-Add-EntityZapEvent.patch} (100%) rename patches/{server-remapped => removed/1.17}/0107-Fix-Double-World-Add-issues.patch (91%) rename patches/{server-remapped => removed/1.17}/0114-Chunk-registration-fixes.patch (97%) rename patches/{server-remapped/0108-Fix-Old-Sign-Conversion.patch => server/0099-Fix-Old-Sign-Conversion.patch} (60%) rename patches/{server-remapped/0109-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch => server/0100-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch} (67%) rename patches/{server-remapped/0110-Add-setting-for-proxy-online-mode-status.patch => server/0101-Add-setting-for-proxy-online-mode-status.patch} (79%) rename patches/{server-remapped/0111-Optimise-BlockState-s-hashCode-equals.patch => server/0102-Optimise-BlockState-s-hashCode-equals.patch} (70%) rename patches/{server-remapped/0112-Configurable-packet-in-spam-threshold.patch => server/0103-Configurable-packet-in-spam-threshold.patch} (70%) rename patches/{server-remapped/0113-Configurable-flying-kick-messages.patch => server/0104-Configurable-flying-kick-messages.patch} (89%) rename patches/{server-remapped/0115-Remove-FishingHook-reference-on-Craft-Entity-removal.patch => server/0105-Remove-FishingHook-reference-on-Craft-Entity-removal.patch} (74%) rename patches/{server-remapped/0116-Auto-fix-bad-Y-levels-on-player-login.patch => server/0106-Auto-fix-bad-Y-levels-on-player-login.patch} (57%) rename patches/{server-remapped/0117-Option-to-remove-corrupt-tile-entities.patch => server/0107-Option-to-remove-corrupt-tile-entities.patch} (75%) rename patches/{server-remapped/0118-Add-EntityZapEvent.patch => server/0108-Add-EntityZapEvent.patch} (77%) diff --git a/patches/api-unmapped/0037-Add-EntityZapEvent.patch b/patches/api/0038-Add-EntityZapEvent.patch similarity index 100% rename from patches/api-unmapped/0037-Add-EntityZapEvent.patch rename to patches/api/0038-Add-EntityZapEvent.patch diff --git a/patches/server-remapped/0107-Fix-Double-World-Add-issues.patch b/patches/removed/1.17/0107-Fix-Double-World-Add-issues.patch similarity index 91% rename from patches/server-remapped/0107-Fix-Double-World-Add-issues.patch rename to patches/removed/1.17/0107-Fix-Double-World-Add-issues.patch index b412753ddd..707d235e76 100644 --- a/patches/server-remapped/0107-Fix-Double-World-Add-issues.patch +++ b/patches/removed/1.17/0107-Fix-Double-World-Add-issues.patch @@ -7,6 +7,9 @@ Vanilla will double add Spider Jockeys to the world, so ignore already added. Also add debug if something else tries to, and abort before world gets bad state +In 1.17 the entire entity state manager was rewritten. no longer applies, needs +further information on new state manager + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 0a613f94d1c796267636e1a343aeee65a49ffed5..335928d60dbfc07644ffeab366900c5e77e99d56 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/server-remapped/0114-Chunk-registration-fixes.patch b/patches/removed/1.17/0114-Chunk-registration-fixes.patch similarity index 97% rename from patches/server-remapped/0114-Chunk-registration-fixes.patch rename to patches/removed/1.17/0114-Chunk-registration-fixes.patch index 4d2da1cd83..295d9a4664 100644 --- a/patches/server-remapped/0114-Chunk-registration-fixes.patch +++ b/patches/removed/1.17/0114-Chunk-registration-fixes.patch @@ -7,6 +7,8 @@ World checks and the Chunk Add logic are inconsistent on how Y > 256, < 0, is tr Keep them consistent +No longer relevant in 1.17 + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 335928d60dbfc07644ffeab366900c5e77e99d56..20650bfd10abfa010e71cfeede06c461d50d19a3 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/server/0022-Remove-invalid-mob-spawner-tile-entities.patch b/patches/server/0022-Remove-invalid-mob-spawner-tile-entities.patch index c4cfd682ed..5c432335e6 100644 --- a/patches/server/0022-Remove-invalid-mob-spawner-tile-entities.patch +++ b/patches/server/0022-Remove-invalid-mob-spawner-tile-entities.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Remove invalid mob spawner tile entities diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 485cb87e83dd4b4b052905fb7f5f83d3c26f542f..ee2df7de72c75e4fbf8a681ff254260554969b66 100644 +index 485cb87e83dd4b4b052905fb7f5f83d3c26f542f..89d280ec732b2d023f9c7ba06b1c3e5be3ef86f5 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -46,10 +46,12 @@ import net.minecraft.world.level.TickList; @@ -27,7 +27,7 @@ index 485cb87e83dd4b4b052905fb7f5f83d3c26f542f..ee2df7de72c75e4fbf8a681ff2542605 // CraftBukkit start + // Paper start - Remove invalid mob spawner tile entities + } else if (blockEntity instanceof SpawnerBlockEntity && !(getBlockState(blockposition).getBlock() instanceof SpawnerBlock)) { -+ this.blockEntities.remove(blockposition); ++ this.removeBlockEntity(blockEntity.getBlockPos()); + // Paper end } else { System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() diff --git a/patches/server/0053-Add-exception-reporting-event.patch b/patches/server/0053-Add-exception-reporting-event.patch index 34c4746f16..f65aaed3b2 100644 --- a/patches/server/0053-Add-exception-reporting-event.patch +++ b/patches/server/0053-Add-exception-reporting-event.patch @@ -155,7 +155,7 @@ index b4a7776ba9486bbca42ffb596c8a8bcdf6471ce3..59fae60116167baf989e85596334824e } diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index a6e8a8de17acc6c7c0bdeea01544a334797b69b6..9939c4c39549771afe971a6433dfd57e36050dd8 100644 +index cbc2a9a3e9943c20cae645fbb18f0aa29415bd63..b36a893ded952d1a5ed1a55eae9c3c406848e1f3 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -1,6 +1,7 @@ @@ -167,7 +167,7 @@ index a6e8a8de17acc6c7c0bdeea01544a334797b69b6..9939c4c39549771afe971a6433dfd57e import com.google.common.collect.Sets; import com.google.common.collect.UnmodifiableIterator; @@ -615,10 +616,15 @@ public class LevelChunk implements ChunkAccess { - this.blockEntities.remove(blockposition); + this.removeBlockEntity(blockEntity.getBlockPos()); // Paper end } else { - System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() diff --git a/patches/server-remapped/0108-Fix-Old-Sign-Conversion.patch b/patches/server/0099-Fix-Old-Sign-Conversion.patch similarity index 60% rename from patches/server-remapped/0108-Fix-Old-Sign-Conversion.patch rename to patches/server/0099-Fix-Old-Sign-Conversion.patch index d08b9cb8ca..017485dabf 100644 --- a/patches/server-remapped/0108-Fix-Old-Sign-Conversion.patch +++ b/patches/server/0099-Fix-Old-Sign-Conversion.patch @@ -9,10 +9,10 @@ Subject: [PATCH] Fix Old Sign Conversion This causes Igloos and such to render broken signs. We fix this by ignoring sign conversion for Defined Structures diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 13115d1b28dfa2d87b45a50bd0feaa7f57769122..d08ed44884726ca2ba4578226b8aa6244778f4c7 100644 +index d6a4a2a59f1be0cc2e373dc326287b60db5559d2..9d777fce673c8f6b3ee2d69f5a6360a8a5ad8e84 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -34,6 +34,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { +@@ -30,6 +30,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { public CraftPersistentDataContainer persistentDataContainer; // CraftBukkit end private static final Logger LOGGER = LogManager.getLogger(); @@ -21,38 +21,28 @@ index 13115d1b28dfa2d87b45a50bd0feaa7f57769122..d08ed44884726ca2ba4578226b8aa624 @Nullable protected Level level; diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -index e747f729326fb3bacfb3f983ac7701c0fb0f0e6a..e4eab82855649fec654c60b2e94ba7b71c2ac5a2 100644 +index dbb59775422b80fb4b60a8cfd2c0bd81c1646e88..589fbdd5c86655244aa92a42e5f45747b5c5026e 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -@@ -78,13 +78,14 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C +@@ -95,7 +95,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + s = "\"\""; } - try { -- MutableComponent ichatmutablecomponent = Component.Serializer.fromJson(s.isEmpty() ? "\"\"" : s); -+ //IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); // Paper - move down - the old format might throw a json error - -- if (oldSign) { -+ if (oldSign && !isLoadingStructure) { // Paper - saved structures will be in the new format, but will not have isConverted - messages[i] = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s)[0]; - continue; - } - // CraftBukkit end -+ MutableComponent ichatmutablecomponent = Component.Serializer.fromJson(s.isEmpty() ? "\"\"" : s); // Paper - after old sign - - if (this.level instanceof ServerLevel) { - try { +- if (oldSign) { ++ if (oldSign && !this.isLoadingStructure) { // Paper - saved structures will be in the new format, but will not have isConverted + this.messages[i] = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s)[0]; + continue; + } diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java -index 8da00ee410e3f8f09b8ac273095a3d22d6c4d92b..d4cf5d3bdbe629081f6ec9d4ea94004560c93ebc 100644 +index e396c3aede9ca22ec98e1bd25c7da35ed6406f4f..80d3787d9c07f8dd740c2e5979e1cc14891b8829 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java +++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java -@@ -278,9 +278,11 @@ public class StructureTemplate { +@@ -283,7 +283,9 @@ public class StructureTemplate { definedstructure_blockinfo.nbt.putLong("LootTableSeed", random.nextLong()); } + tileentity.isLoadingStructure = true; // Paper - tileentity.load(definedstructure_blockinfo.state, definedstructure_blockinfo.nbt); - tileentity.mirror(placementData.getMirror()); - tileentity.rotate(placementData.getRotation()); + tileentity.load(definedstructure_blockinfo.nbt); + tileentity.isLoadingStructure = false; // Paper } } diff --git a/patches/server-remapped/0109-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/patches/server/0100-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch similarity index 67% rename from patches/server-remapped/0109-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch rename to patches/server/0100-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch index 51ddf3745d..24d14ed9f5 100644 --- a/patches/server-remapped/0109-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch +++ b/patches/server/0100-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Don't lookup game profiles that have no UUID and no name diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index 9342fa6b28e805743b8e3a13007605934244d6cd..f3e05fac1b5248ca4ee2cac03263e96c166ed343 100644 +index 95682f63c7ae1460b069e13f11295f72c1f262a8..b2bd204879badfe1cab6bea9db2d6c412505a9ce 100644 --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java +++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java -@@ -92,7 +92,7 @@ public class GameProfileCache { +@@ -100,7 +100,7 @@ public class GameProfileCache { repository.findProfilesByNames(new String[]{name}, Agent.MINECRAFT, profilelookupcallback); GameProfile gameprofile = (GameProfile) atomicreference.get(); -- if (!usesAuthentication() && gameprofile == null) { -+ if (!usesAuthentication() && gameprofile == null && !org.apache.commons.lang3.StringUtils.isBlank(name)) { // Paper - Don't lookup a profile with a blank name +- if (!GameProfileCache.usesAuthentication() && gameprofile == null) { ++ if (!GameProfileCache.usesAuthentication() && gameprofile == null && !org.apache.commons.lang3.StringUtils.isBlank(name)) { // Paper - Don't lookup a profile with a blank name UUID uuid = Player.createPlayerUUID(new GameProfile((UUID) null, name)); gameprofile = new GameProfile(uuid, name); diff --git a/patches/server-remapped/0110-Add-setting-for-proxy-online-mode-status.patch b/patches/server/0101-Add-setting-for-proxy-online-mode-status.patch similarity index 79% rename from patches/server-remapped/0110-Add-setting-for-proxy-online-mode-status.patch rename to patches/server/0101-Add-setting-for-proxy-online-mode-status.patch index 0dde210c76..16e6c2528a 100644 --- a/patches/server-remapped/0110-Add-setting-for-proxy-online-mode-status.patch +++ b/patches/server/0101-Add-setting-for-proxy-online-mode-status.patch @@ -32,10 +32,10 @@ index 1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2..c52dc0346f93527965ef29a0ccdc4bf3 + } } diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index f3e05fac1b5248ca4ee2cac03263e96c166ed343..e8af352f813a5015d216fc590190ae8fdb03f77d 100644 +index b2bd204879badfe1cab6bea9db2d6c412505a9ce..73dbc4db56bbafefd07ad550d006a437b1ed1b95 100644 --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java +++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java -@@ -89,6 +89,7 @@ public class GameProfileCache { +@@ -97,6 +97,7 @@ public class GameProfileCache { } }; @@ -43,7 +43,7 @@ index f3e05fac1b5248ca4ee2cac03263e96c166ed343..e8af352f813a5015d216fc590190ae8f repository.findProfilesByNames(new String[]{name}, Agent.MINECRAFT, profilelookupcallback); GameProfile gameprofile = (GameProfile) atomicreference.get(); -@@ -106,7 +107,7 @@ public class GameProfileCache { +@@ -114,7 +115,7 @@ public class GameProfileCache { } private static boolean usesAuthentication() { @@ -51,12 +51,12 @@ index f3e05fac1b5248ca4ee2cac03263e96c166ed343..e8af352f813a5015d216fc590190ae8f + return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper } - public synchronized void add(GameProfile gameprofile) { // Paper - synchronize + public synchronized void add(GameProfile profile) { // Paper - synchronize diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java -index 09c5fa2dbcbed05da51ef2d63e6d6112d22d7877..e6a26c274616947329a6164e4648486452819b0c 100644 +index da515ac94aa3c294855f28e6deb9094cc7187dd9..b61a3217c70f3f5c4c06131b3c4978534d7d935a 100644 --- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java +++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java -@@ -63,7 +63,8 @@ public class OldUsersConverter { +@@ -65,7 +65,8 @@ public class OldUsersConverter { return new String[i]; }); @@ -67,16 +67,15 @@ index 09c5fa2dbcbed05da51ef2d63e6d6112d22d7877..e6a26c274616947329a6164e46484864 } else { String[] astring1 = astring; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 2828936fe294d9d6750a8838da49ec8398835214..bbe0978f56d23b7defce765d381d4a7c20acd75c 100644 +index 95689d11668e37a894b70517270849c2c4e162aa..91002473f54fd0ac95489b9448fe91072565881d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1515,7 +1515,8 @@ public final class CraftServer implements Server { +@@ -1515,7 +1515,7 @@ public final class CraftServer implements Server { // Spigot Start GameProfile profile = null; // Only fetch an online UUID in online mode -- if ( getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) -+ if ( getOnlineMode() -+ || com.destroystokyo.paper.PaperConfig.isProxyOnlineMode() ) // Paper - Handle via setting +- if ( this.getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) ++ if ( this.getOnlineMode() || com.destroystokyo.paper.PaperConfig.isProxyOnlineMode() ) // Paper - Handle via setting { - profile = console.getProfileCache().get( name ); + profile = this.console.getProfileCache().getProfile( name ); } diff --git a/patches/server-remapped/0111-Optimise-BlockState-s-hashCode-equals.patch b/patches/server/0102-Optimise-BlockState-s-hashCode-equals.patch similarity index 70% rename from patches/server-remapped/0111-Optimise-BlockState-s-hashCode-equals.patch rename to patches/server/0102-Optimise-BlockState-s-hashCode-equals.patch index 6e9e140dc2..1223b0ff35 100644 --- a/patches/server-remapped/0111-Optimise-BlockState-s-hashCode-equals.patch +++ b/patches/server/0102-Optimise-BlockState-s-hashCode-equals.patch @@ -9,7 +9,7 @@ object identity checks safely. Use a simpler optimized hashcode diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java -index c5af36a0279d1e1c951e6f9b34857b0aa934f940..62f11a02e3f5c07e838f425cffb0a28b6d2bc138 100644 +index 6cdb0716f2a4b29f7a5ecd109bf3c4700ebd22ad..ff1a0d125edd2ea10c870cbb62ae9aa23644b6dc 100644 --- a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java +++ b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java @@ -30,8 +30,7 @@ public class BooleanProperty extends Property { @@ -23,11 +23,11 @@ index c5af36a0279d1e1c951e6f9b34857b0aa934f940..62f11a02e3f5c07e838f425cffb0a28b return true; } else if (object instanceof BooleanProperty && super.equals(object)) { diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java -index b5817645727f2af2785e0987ba824f431d4e9e32..2fdfd7d2470ee9f1a96eda7418b104c960df8460 100644 +index e76591dec764d92e1a760c5208714f3c80ea8fc7..bcf8b24e9f9e9870c1a1d27c721a6a433305d55a 100644 --- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java -@@ -50,8 +50,7 @@ public class EnumProperty & StringRepresentable> extends Prope - return ((StringRepresentable) value).getSerializedName(); +@@ -48,8 +48,7 @@ public class EnumProperty & StringRepresentable> extends Prope + return value.getSerializedName(); } - @Override @@ -51,34 +51,22 @@ index c3ec7f91794d802e5b9ddac3fffccce378dace68..72f508321ebffcca31240fbdd068b4d1 return true; } else if (object instanceof IntegerProperty && super.equals(object)) { diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java -index 8cc07c70fde81e44679f3ea7d9a4c6b2447885d4..80f8966ac56e8af4a6c7aa86b2d8dd0f319c7b5d 100644 +index 0dc91cfaef2bc6004270c380e673da1728287433..81b43e0b0146729a8a1c6ade82634c86cde67857 100644 --- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java +++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java -@@ -60,23 +60,17 @@ public abstract class Property> { - } +@@ -66,14 +66,7 @@ public abstract class Property> { + @Override public boolean equals(Object object) { - if (this == object) { - return true; - } else if (!(object instanceof Property)) { - return false; - } else { -- Property iblockstate = (Property) object; -- -- return this.clazz.equals(iblockstate.clazz) && this.name.equals(iblockstate.name); +- Property property = (Property)object; +- return this.clazz.equals(property.clazz) && this.name.equals(property.name); - } -+ return this == object; // Paper - only one instance per configuration ++ return this == object; } -+ private static final java.util.concurrent.atomic.AtomicInteger hashId = new java.util.concurrent.atomic.AtomicInteger(1); // Paper - only one instance per configuration -+ private final int hashCode = 92821 * hashId.getAndIncrement(); // Paper - only one instance per configuration - public final int hashCode() { - if (this.hashCode == null) { - this.hashCode = this.generateHashCode(); - } - -- return this.hashCode; -+ return this.hashCode; // Paper - only one instance per configuration - } - - public int generateHashCode() { + @Override diff --git a/patches/server-remapped/0112-Configurable-packet-in-spam-threshold.patch b/patches/server/0103-Configurable-packet-in-spam-threshold.patch similarity index 70% rename from patches/server-remapped/0112-Configurable-packet-in-spam-threshold.patch rename to patches/server/0103-Configurable-packet-in-spam-threshold.patch index bce5b61b0d..6050a142e9 100644 --- a/patches/server-remapped/0112-Configurable-packet-in-spam-threshold.patch +++ b/patches/server/0103-Configurable-packet-in-spam-threshold.patch @@ -23,23 +23,23 @@ index c52dc0346f93527965ef29a0ccdc4bf3debe302e..64d7c9058ee757a6d3cf3b648596092a + } } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index e2bfe8e916c9e59af81627ea0ee449970527034d..d6f4ccf06c919410e13409433bdfc3aa88a21c30 100644 +index 6cd0fd57503723a58b30a7c33b1c863afc2401e2..37a25af3697e06a7f8aeaf462fbf50f8bc250dd3 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1463,13 +1463,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1495,13 +1495,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // Spigot start - limit place/interactions private int limitedPackets; private long lastLimitedPacket = -1; + private static final int THRESHOLD = com.destroystokyo.paper.PaperConfig.packetInSpamThreshold; // Paper - Configurable threshold private boolean checkLimit(long timestamp) { -- if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < 30 && limitedPackets++ >= 4) { -+ if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < THRESHOLD && limitedPackets++ >= 8) { // Paper - Use threshold, raise packet limit to 8 +- if (this.lastLimitedPacket != -1 && timestamp - this.lastLimitedPacket < 30 && this.limitedPackets++ >= 4) { ++ if (this.lastLimitedPacket != -1 && timestamp - this.lastLimitedPacket < THRESHOLD && this.limitedPackets++ >= 8) { // Paper - Use threshold, raise packet limit to 8 return false; } -- if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= 30) { -+ if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= THRESHOLD) { // Paper - lastLimitedPacket = timestamp; - limitedPackets = 0; +- if (this.lastLimitedPacket == -1 || timestamp - this.lastLimitedPacket >= 30) { ++ if (this.lastLimitedPacket == -1 || timestamp - this.lastLimitedPacket >= THRESHOLD) { // Paper + this.lastLimitedPacket = timestamp; + this.limitedPackets = 0; return true; diff --git a/patches/server-remapped/0113-Configurable-flying-kick-messages.patch b/patches/server/0104-Configurable-flying-kick-messages.patch similarity index 89% rename from patches/server-remapped/0113-Configurable-flying-kick-messages.patch rename to patches/server/0104-Configurable-flying-kick-messages.patch index fc05cbc991..82277164d7 100644 --- a/patches/server-remapped/0113-Configurable-flying-kick-messages.patch +++ b/patches/server/0104-Configurable-flying-kick-messages.patch @@ -21,10 +21,10 @@ index 64d7c9058ee757a6d3cf3b648596092a810e105c..4e2f243faa209925dcb7c3ef89df3ed8 + } } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index d6f4ccf06c919410e13409433bdfc3aa88a21c30..1b92c669bbe69bcc07a554b7b43ee99bfebc1af4 100644 +index 37a25af3697e06a7f8aeaf462fbf50f8bc250dd3..b33ef48a4372dd8ac4a86bdd386a5a7d42583c72 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -305,7 +305,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -302,7 +302,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser if (this.clientIsFloating && !this.player.isSleeping()) { if (++this.aboveGroundTickCount > 80) { ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); @@ -33,7 +33,7 @@ index d6f4ccf06c919410e13409433bdfc3aa88a21c30..1b92c669bbe69bcc07a554b7b43ee99b return; } } else { -@@ -324,7 +324,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -321,7 +321,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) { if (++this.aboveGroundVehicleTickCount > 80) { ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); diff --git a/patches/server-remapped/0115-Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/patches/server/0105-Remove-FishingHook-reference-on-Craft-Entity-removal.patch similarity index 74% rename from patches/server-remapped/0115-Remove-FishingHook-reference-on-Craft-Entity-removal.patch rename to patches/server/0105-Remove-FishingHook-reference-on-Craft-Entity-removal.patch index 0d1bb6c9bb..26fc5942ba 100644 --- a/patches/server-remapped/0115-Remove-FishingHook-reference-on-Craft-Entity-removal.patch +++ b/patches/server/0105-Remove-FishingHook-reference-on-Craft-Entity-removal.patch @@ -3,14 +3,15 @@ From: Aikar Date: Thu, 16 Jun 2016 00:17:23 -0400 Subject: [PATCH] Remove FishingHook reference on Craft Entity removal +TODO 1.17 isn't this supposed to be applied to when the fish hook is removed _in general_? Not just in Bukkit api calls? diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -index 5668facc5bf5c56581c3ebd268f832d77ce5c05b..50322cfc07a7d93c32461faeb5e22e35ceead323 100644 +index 6bfa984781a483d048ef4318761203c701d8a632..3c18712040da8d6ece24fd817b7846836b8353c1 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java @@ -119,4 +119,14 @@ public class CraftFishHook extends CraftProjectile implements FishHook { public HookState getState() { - return HookState.values()[getHandle().currentState.ordinal()]; + return HookState.values()[this.getHandle().currentState.ordinal()]; } + + // Paper start diff --git a/patches/server-remapped/0116-Auto-fix-bad-Y-levels-on-player-login.patch b/patches/server/0106-Auto-fix-bad-Y-levels-on-player-login.patch similarity index 57% rename from patches/server-remapped/0116-Auto-fix-bad-Y-levels-on-player-login.patch rename to patches/server/0106-Auto-fix-bad-Y-levels-on-player-login.patch index a6a274fc00..a26e728784 100644 --- a/patches/server-remapped/0116-Auto-fix-bad-Y-levels-on-player-login.patch +++ b/patches/server/0106-Auto-fix-bad-Y-levels-on-player-login.patch @@ -6,14 +6,14 @@ Subject: [PATCH] Auto fix bad Y levels on player login Bring down to a saner Y level if super high, as this can cause the server to crash diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index bd3d9182dfb2c0ae1d8c3b9aa360f94c33252592..3a2356b3e00098d100a179a05316f402390d4e9b 100644 +index f48d7205242fc38c00e496c88090e0e98e394b39..c60d42c835ed9a1bcc938aa1647c5266b87a05c5 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -337,6 +337,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -401,6 +401,7 @@ public class ServerPlayer extends Player { @Override - public void readAdditionalSaveData(CompoundTag tag) { - super.readAdditionalSaveData(tag); + public void readAdditionalSaveData(CompoundTag nbt) { + super.readAdditionalSaveData(nbt); + if (this.getY() > 300) this.setPosRaw(getX(), 257, getZ()); // Paper - bring down to a saner Y level if out of world - if (tag.contains("playerGameType", 99)) { - if (this.getServer().getForceGameType()) { - this.gameMode.setGameModeForPlayer(this.getServer().getDefaultGameType(), GameType.NOT_SET); + if (nbt.contains("enteredNetherPosition", 10)) { + CompoundTag nbttagcompound1 = nbt.getCompound("enteredNetherPosition"); + diff --git a/patches/server-remapped/0117-Option-to-remove-corrupt-tile-entities.patch b/patches/server/0107-Option-to-remove-corrupt-tile-entities.patch similarity index 75% rename from patches/server-remapped/0117-Option-to-remove-corrupt-tile-entities.patch rename to patches/server/0107-Option-to-remove-corrupt-tile-entities.patch index d6b80297c0..859b981dbb 100644 --- a/patches/server-remapped/0117-Option-to-remove-corrupt-tile-entities.patch +++ b/patches/server/0107-Option-to-remove-corrupt-tile-entities.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Option to remove corrupt tile entities diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6eca3f300020006f02dd36253b522db442e3cc33..622affa0dc3cc1eadaed400511f2ca2cde3fca2a 100644 +index 9b2e9a02ff31c3cb37b67135d0a03441f247d8e2..96247356d7888d5681bff60567add1188aedb18b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -300,4 +300,9 @@ public class PaperWorldConfig { +@@ -301,4 +301,9 @@ public class PaperWorldConfig { preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); } @@ -19,15 +19,15 @@ index 6eca3f300020006f02dd36253b522db442e3cc33..622affa0dc3cc1eadaed400511f2ca2c + } } diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 70f5b025c2b803df3de8a51cbcfafbe915866f42..d69ccb1f31f31ebeee477df20ce1410f9e485eb7 100644 +index eed2ef73c33b76222de0f4fd91525cc03eef19b0..521f199e495f3bec232cc9ca36e51e0392afe737 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -678,6 +678,12 @@ public class LevelChunk implements ChunkAccess { - "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); +@@ -640,6 +640,12 @@ public class LevelChunk implements ChunkAccess { + "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); e.printStackTrace(); ServerInternalException.reportInternalException(e); + -+ if (this.world.paperConfig.removeCorruptTEs) { ++ if (this.level.paperConfig.removeCorruptTEs) { + this.removeBlockEntity(blockEntity.getBlockPos()); + this.markUnsaved(); + org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); diff --git a/patches/server-remapped/0118-Add-EntityZapEvent.patch b/patches/server/0108-Add-EntityZapEvent.patch similarity index 77% rename from patches/server-remapped/0118-Add-EntityZapEvent.patch rename to patches/server/0108-Add-EntityZapEvent.patch index 20a798bf8d..ad3754356b 100644 --- a/patches/server-remapped/0118-Add-EntityZapEvent.patch +++ b/patches/server/0108-Add-EntityZapEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add EntityZapEvent diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.java -index 6ecf7afe5fd7c4c95a17eaed1445d034aa2d5f18..e512a38ccbba93266f0234e3b2fcf7f62693039b 100644 +index d414b111386e18dec8992b510b93c19ece8d60dd..2c95b6eddfe46e5d2ad495bfc86ccc24ae75e704 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Pig.java +++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java @@ -254,6 +254,11 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { @@ -21,11 +21,15 @@ index 6ecf7afe5fd7c4c95a17eaed1445d034aa2d5f18..e512a38ccbba93266f0234e3b2fcf7f6 if (CraftEventFactory.callPigZapEvent(this, lightning, entitypigzombie).isCancelled()) { return; diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 2f99bdaabe1c1a6a4e1a7e2bd533a63b12818be1..5648a4a4d8511ac8c46c61245a7ff83753a3e51f 100644 +index df8c953fffcc6063abd1929b8d3a07943da86e21..731aea63eedb8cb37291bb2238ff8ab2e3a5f6eb 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -786,6 +786,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); +@@ -826,9 +826,17 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + @Override + public void thunderHit(ServerLevel world, LightningBolt lightning) { + if (world.getDifficulty() != Difficulty.PEACEFUL) { +- Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); ++ // Paper - move log down, event can cancel Witch entitywitch = (Witch) EntityType.WITCH.create((Level) world); + // Paper start @@ -34,14 +38,16 @@ index 2f99bdaabe1c1a6a4e1a7e2bd533a63b12818be1..5648a4a4d8511ac8c46c61245a7ff837 + } + // Paper end + - entitywitch.moveTo(this.getX(), this.getY(), this.getZ(), this.yRot, this.xRot); ++ Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); // Paper - move log down, event can cancel ++ + entitywitch.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); entitywitch.finalizeSpawn(world, world.getCurrentDifficultyAt(entitywitch.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null, (CompoundTag) 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 7fde1bb7587e567270e3f936381c6d361870211f..81af3e2e0964b6e179f92a342efdae943be18b75 100644 +index fdb97878a6e73b729dbf09292d214e42c57d720a..cb3f1f71cc5c5a18c0af818679b72583a7edec7c 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1086,6 +1086,14 @@ public class CraftEventFactory { +@@ -1082,6 +1082,14 @@ public class CraftEventFactory { return event; } From 9da160169a9475f9f64304d4c8111bf70a6470df Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Fri, 11 Jun 2021 23:24:50 -0700 Subject: [PATCH 037/226] even even even even even even even more work --- .../0039-Misc-Utils.patch} | 0 ...120-Cache-user-authenticator-threads.patch | 2 ++ ...ge-the-Entity-Random-seed-for-squids.patch | 1 + ...067-Use-a-Shared-Random-for-Entities.patch | 13 +++++++ ...-from-ArmorStand-and-SpawnEgg-items.patch} | 35 +++++++++---------- ...10-Cache-user-authenticator-threads.patch} | 24 ++++++++----- 6 files changed, 47 insertions(+), 28 deletions(-) rename patches/{api-unmapped/0038-Misc-Utils.patch => api/0039-Misc-Utils.patch} (100%) rename patches/{server-remapped => removed/1.17}/0120-Cache-user-authenticator-threads.patch (97%) rename patches/{server-remapped => removed/1.17}/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch (94%) rename patches/{server-remapped/0119-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch => server/0109-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch} (60%) rename patches/{server-remapped/0121-Optimise-removeQueue.patch => server/0110-Cache-user-authenticator-threads.patch} (75%) diff --git a/patches/api-unmapped/0038-Misc-Utils.patch b/patches/api/0039-Misc-Utils.patch similarity index 100% rename from patches/api-unmapped/0038-Misc-Utils.patch rename to patches/api/0039-Misc-Utils.patch diff --git a/patches/server-remapped/0120-Cache-user-authenticator-threads.patch b/patches/removed/1.17/0120-Cache-user-authenticator-threads.patch similarity index 97% rename from patches/server-remapped/0120-Cache-user-authenticator-threads.patch rename to patches/removed/1.17/0120-Cache-user-authenticator-threads.patch index be4de8cb23..fbc0443e78 100644 --- a/patches/server-remapped/0120-Cache-user-authenticator-threads.patch +++ b/patches/removed/1.17/0120-Cache-user-authenticator-threads.patch @@ -4,6 +4,8 @@ Date: Wed, 23 Nov 2016 08:31:45 -0500 Subject: [PATCH] Cache user authenticator threads +TODO it looks like someone royally messed this one up, patch name doesn't remotely +describe contents. Good thing this patch is no longer relevant at all diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java index 0597c0c3e881dd43cf91bd3088ed30dfecfe8098..175bf535066afc42de8a3f0d11c46af66f3e3e52 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java diff --git a/patches/server-remapped/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch b/patches/removed/1.17/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch similarity index 94% rename from patches/server-remapped/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch rename to patches/removed/1.17/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch index 4887c3dd7e..56015aa8db 100644 --- a/patches/server-remapped/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch +++ b/patches/removed/1.17/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch @@ -4,6 +4,7 @@ Date: Thu, 19 Jul 2018 01:05:00 -0400 Subject: [PATCH] Don't change the Entity Random seed for squids +Rebased into the patch to add the shared entity random diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java index 5a7582fd4f8e883d2f08a0227932c17d7576b957..2e5a35565b6b7c4d3f7fdab45095f789c33f8937 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Squid.java diff --git a/patches/server/0067-Use-a-Shared-Random-for-Entities.patch b/patches/server/0067-Use-a-Shared-Random-for-Entities.patch index 27b07b1be0..a8e9435341 100644 --- a/patches/server/0067-Use-a-Shared-Random-for-Entities.patch +++ b/patches/server/0067-Use-a-Shared-Random-for-Entities.patch @@ -40,3 +40,16 @@ index e9e87dc8c80d83dc7c472b0611077d8f9f4e5fcf..eceaeed527f34860e1c55b9f96863f14 this.remainingFireTicks = -this.getFireImmuneTicks(); this.fluidHeight = new Object2DoubleArrayMap(2); this.firstTick = true; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java +index 2b88f5be9bd0766f28e07251175aa353242cf11f..5faa9e05e041a8bdcac88f3c3af7620353c10c3a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java +@@ -50,7 +50,7 @@ public class Squid extends WaterAnimal { + + public Squid(EntityType type, Level world) { + super(type, world); +- this.random.setSeed((long) this.getId()); ++ //this.random.setSeed((long) this.getId()); // Paper - we set the random to shared, do not clobber the seed + this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; + } + diff --git a/patches/server-remapped/0119-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/patches/server/0109-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch similarity index 60% rename from patches/server-remapped/0119-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch rename to patches/server/0109-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch index 782f93006e..0cef3ad756 100644 --- a/patches/server-remapped/0119-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch +++ b/patches/server/0109-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch @@ -5,18 +5,10 @@ Subject: [PATCH] Filter bad data from ArmorStand and SpawnEgg items diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 622affa0dc3cc1eadaed400511f2ca2cde3fca2a..e83216be5a00d5b927d8c2fc364551bd3077c974 100644 +index 96247356d7888d5681bff60567add1188aedb18b..e83216be5a00d5b927d8c2fc364551bd3077c974 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -2,6 +2,7 @@ package com.destroystokyo.paper; - - import java.util.List; - -+import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -305,4 +306,12 @@ public class PaperWorldConfig { +@@ -306,4 +306,12 @@ public class PaperWorldConfig { private void removeCorruptTEs() { removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); } @@ -30,20 +22,25 @@ index 622affa0dc3cc1eadaed400511f2ca2cde3fca2a..e83216be5a00d5b927d8c2fc364551bd + } } diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -index 1d87717cc9002ea202ee2ca614aaa8a4c7ea3cb2..ff8f7e4569a889ead1512b7c9908f9c5cad9eed5 100644 +index eb838fcad0593573f536d5e043cbd3f4bbe25d74..2332a00780edcf054ec63a60a42962033d0cc74a 100644 --- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -270,6 +270,13 @@ public class FallingBlockEntity extends Entity { +@@ -308,6 +308,18 @@ public class FallingBlockEntity extends Entity { @Override - protected void readAdditionalSaveData(CompoundTag tag) { - this.blockState = NbtUtils.readBlockState(tag.getCompound("BlockState")); + protected void readAdditionalSaveData(CompoundTag nbt) { + this.blockState = NbtUtils.readBlockState(nbt.getCompound("BlockState")); + // Paper start - Block FallingBlocks with Command Blocks -+ // Check mappings on update - dc = "repeating_command_block" - dd = "chain_command_block" + final Block b = this.blockState.getBlock(); -+ if (this.level.paperConfig.filterNBTFromSpawnEgg && (b == Blocks.COMMAND_BLOCK || b == Blocks.REPEATING_COMMAND_BLOCK || b == Blocks.CHAIN_COMMAND_BLOCK)) { ++ if (this.level.paperConfig.filterNBTFromSpawnEgg ++ && (b == Blocks.COMMAND_BLOCK ++ || b == Blocks.REPEATING_COMMAND_BLOCK ++ || b == Blocks.CHAIN_COMMAND_BLOCK ++ || b == Blocks.JIGSAW ++ || b == Blocks.STRUCTURE_BLOCK ++ || b instanceof net.minecraft.world.level.block.GameMasterBlock)) { + this.blockState = Blocks.STONE.defaultBlockState(); + } + // Paper end - this.time = tag.getInt("Time"); - if (tag.contains("HurtEntities", 99)) { - this.hurtEntities = tag.getBoolean("HurtEntities"); + this.time = nbt.getInt("Time"); + if (nbt.contains("HurtEntities", 99)) { + this.hurtEntities = nbt.getBoolean("HurtEntities"); diff --git a/patches/server-remapped/0121-Optimise-removeQueue.patch b/patches/server/0110-Cache-user-authenticator-threads.patch similarity index 75% rename from patches/server-remapped/0121-Optimise-removeQueue.patch rename to patches/server/0110-Cache-user-authenticator-threads.patch index f3b8068513..01bdd6b870 100644 --- a/patches/server-remapped/0121-Optimise-removeQueue.patch +++ b/patches/server/0110-Cache-user-authenticator-threads.patch @@ -1,27 +1,33 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alfie Cleveland Date: Fri, 25 Nov 2016 13:22:40 +0000 -Subject: [PATCH] Optimise removeQueue +Subject: [PATCH] Cache user authenticator threads diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 9dbb3bb79ae2de6635f71e5ee5bebeb5e57b624e..e3c1460c580ea348ee6d436018244441a5a1206e 100644 +index 11c0da9b36aecc1a7d3acb2dccdae962426dd2e7..3e57eb2e50f94085fd23b54a54d4cf7a0b7919c7 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -114,6 +114,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -117,6 +117,18 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener } + // Paper start - Cache authenticator threads + private static final AtomicInteger threadId = new AtomicInteger(0); + private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool( -+ r -> new Thread(r, "User Authenticator #" + threadId.incrementAndGet()) ++ r -> { ++ Thread ret = new Thread(r, "User Authenticator #" + threadId.incrementAndGet()); ++ ++ ret.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); ++ ++ return ret; ++ } + ); + // Paper end // Spigot start public void initUUID() { -@@ -193,8 +199,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -209,8 +221,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce)); } else { // Spigot start @@ -32,8 +38,8 @@ index 9dbb3bb79ae2de6635f71e5ee5bebeb5e57b624e..e3c1460c580ea348ee6d436018244441 @Override public void run() { try { -@@ -205,7 +211,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + gameProfile.getName(), ex); +@@ -221,7 +233,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + ServerLoginPacketListenerImpl.this.gameProfile.getName(), ex); } } - }.start(); @@ -42,7 +48,7 @@ index 9dbb3bb79ae2de6635f71e5ee5bebeb5e57b624e..e3c1460c580ea348ee6d436018244441 // Spigot end } -@@ -234,7 +241,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -250,7 +263,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener throw new IllegalStateException("Protocol error", cryptographyexception); } @@ -52,7 +58,7 @@ index 9dbb3bb79ae2de6635f71e5ee5bebeb5e57b624e..e3c1460c580ea348ee6d436018244441 public void run() { GameProfile gameprofile = ServerLoginPacketListenerImpl.this.gameProfile; -@@ -279,10 +287,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -295,10 +309,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener return ServerLoginPacketListenerImpl.this.server.getPreventProxyConnections() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; } From b1517fe9f2d4f87f8ab571e7c798c4ba3a468d51 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sat, 12 Jun 2021 00:24:28 -0700 Subject: [PATCH 038/226] even even even even even even even even even more changes --- ...-Allow-Reloading-of-Command-Aliases.patch} | 4 +- ...-Add-source-to-PlayerExpChangeEvent.patch} | 0 .../0042-Add-ProjectileCollideEvent.patch} | 0 ...043-Add-String-based-Action-Bar-API.patch} | 0 ...o-control-if-armour-stands-can-move.patch} | 2 +- ...to-control-if-armour-stands-can-move.patch | 106 ------------------ .../0133-String-based-Action-Bar-API.patch | 48 -------- ...-Allow-Reloading-of-Command-Aliases.patch} | 4 +- ...-Add-source-to-PlayerExpChangeEvent.patch} | 26 ++--- ...-Don-t-let-fishinghooks-use-portals.patch} | 6 +- .../0114-Add-ProjectileCollideEvent.patch} | 20 ++-- ...ent-Pathfinding-out-of-World-Border.patch} | 13 ++- ...mize-World.isLoaded-BlockPosition-Z.patch} | 5 +- ...Bound-Treasure-Maps-to-World-Border.patch} | 22 ++-- ...igurable-Cartographer-Treasure-Maps.patch} | 40 +++---- .../0119-Optimize-ItemStack.isEmpty.patch} | 8 +- ...to-control-if-armour-stands-can-move.patch | 52 +++++++++ .../0121-String-based-Action-Bar-API.patch | 35 ++++++ 18 files changed, 162 insertions(+), 229 deletions(-) rename patches/{api-unmapped/0039-Allow-Reloading-of-Command-Aliases.patch => api/0040-Allow-Reloading-of-Command-Aliases.patch} (96%) rename patches/{api-unmapped/0040-Add-source-to-PlayerExpChangeEvent.patch => api/0041-Add-source-to-PlayerExpChangeEvent.patch} (100%) rename patches/{api-unmapped/0041-Add-ProjectileCollideEvent.patch => api/0042-Add-ProjectileCollideEvent.patch} (100%) rename patches/{api-unmapped/0042-Add-String-based-Action-Bar-API.patch => api/0043-Add-String-based-Action-Bar-API.patch} (100%) rename patches/{api-unmapped/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch => api/0044-Add-API-methods-to-control-if-armour-stands-can-move.patch} (91%) delete mode 100644 patches/server-remapped/0131-Add-API-methods-to-control-if-armour-stands-can-move.patch delete mode 100644 patches/server-remapped/0133-String-based-Action-Bar-API.patch rename patches/{server-remapped/0122-Allow-Reloading-of-Command-Aliases.patch => server/0111-Allow-Reloading-of-Command-Aliases.patch} (90%) rename patches/{server-remapped/0123-Add-source-to-PlayerExpChangeEvent.patch => server/0112-Add-source-to-PlayerExpChangeEvent.patch} (66%) rename patches/{server-remapped/0124-Don-t-let-fishinghooks-use-portals.patch => server/0113-Don-t-let-fishinghooks-use-portals.patch} (80%) rename patches/{server-remapped/0125-Add-ProjectileCollideEvent.patch => server/0114-Add-ProjectileCollideEvent.patch} (88%) rename patches/{server-remapped/0126-Prevent-Pathfinding-out-of-World-Border.patch => server/0115-Prevent-Pathfinding-out-of-World-Border.patch} (70%) rename patches/{server-remapped/0127-Optimize-World.isLoaded-BlockPosition-Z.patch => server/0116-Optimize-World.isLoaded-BlockPosition-Z.patch} (85%) rename patches/{server-remapped/0128-Bound-Treasure-Maps-to-World-Border.patch => server/0117-Bound-Treasure-Maps-to-World-Border.patch} (68%) rename patches/{server-remapped/0129-Configurable-Cartographer-Treasure-Maps.patch => server/0118-Configurable-Cartographer-Treasure-Maps.patch} (57%) rename patches/{server-remapped/0130-Optimize-ItemStack.isEmpty.patch => server/0119-Optimize-ItemStack.isEmpty.patch} (66%) create mode 100644 patches/server/0120-Add-API-methods-to-control-if-armour-stands-can-move.patch create mode 100644 patches/server/0121-String-based-Action-Bar-API.patch diff --git a/patches/api-unmapped/0039-Allow-Reloading-of-Command-Aliases.patch b/patches/api/0040-Allow-Reloading-of-Command-Aliases.patch similarity index 96% rename from patches/api-unmapped/0039-Allow-Reloading-of-Command-Aliases.patch rename to patches/api/0040-Allow-Reloading-of-Command-Aliases.patch index dcad4e696d..f20d46cd20 100644 --- a/patches/api-unmapped/0039-Allow-Reloading-of-Command-Aliases.patch +++ b/patches/api/0040-Allow-Reloading-of-Command-Aliases.patch @@ -6,7 +6,7 @@ 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 1380a26f34a9d2b162e88fbea14b17118945643c..7b3a0c958b4b4bffb6c19a0e4d3bf4824f8db237 100644 +index 72375883b07ede041a7ea5f7b6785f71aef702c0..55cd39f1e3787bcd34c6d528738122590ec580ec 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1759,6 +1759,15 @@ public final class Bukkit { @@ -26,7 +26,7 @@ index 1380a26f34a9d2b162e88fbea14b17118945643c..7b3a0c958b4b4bffb6c19a0e4d3bf482 @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 4c201097ef98f545acb604fa72d56413553e4d4f..6f4817af249e258905c97f4dac3d2f33804bdfc5 100644 +index a2940eafa61814aae7f766262309495e991533d6..08f451c392682cc0147ba14759c6b7edf7ff533f 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1551,4 +1551,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api-unmapped/0040-Add-source-to-PlayerExpChangeEvent.patch b/patches/api/0041-Add-source-to-PlayerExpChangeEvent.patch similarity index 100% rename from patches/api-unmapped/0040-Add-source-to-PlayerExpChangeEvent.patch rename to patches/api/0041-Add-source-to-PlayerExpChangeEvent.patch diff --git a/patches/api-unmapped/0041-Add-ProjectileCollideEvent.patch b/patches/api/0042-Add-ProjectileCollideEvent.patch similarity index 100% rename from patches/api-unmapped/0041-Add-ProjectileCollideEvent.patch rename to patches/api/0042-Add-ProjectileCollideEvent.patch diff --git a/patches/api-unmapped/0042-Add-String-based-Action-Bar-API.patch b/patches/api/0043-Add-String-based-Action-Bar-API.patch similarity index 100% rename from patches/api-unmapped/0042-Add-String-based-Action-Bar-API.patch rename to patches/api/0043-Add-String-based-Action-Bar-API.patch diff --git a/patches/api-unmapped/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch b/patches/api/0044-Add-API-methods-to-control-if-armour-stands-can-move.patch similarity index 91% rename from patches/api-unmapped/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch rename to patches/api/0044-Add-API-methods-to-control-if-armour-stands-can-move.patch index 3f2a539353..04c2e9c73f 100644 --- a/patches/api-unmapped/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch +++ b/patches/api/0044-Add-API-methods-to-control-if-armour-stands-can-move.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add API methods to control if armour stands can move diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java -index e94ec567fbda93f4f5783f84b4b5136b309d0eab..fddc063798edc8084ca695578a47485204a7f3cd 100644 +index 26223028f68534ee81c6452dd3b0ab7aca03f1e8..de9ddd2c40261486ee8de6693d118cffaa2dd793 100644 --- a/src/main/java/org/bukkit/entity/ArmorStand.java +++ b/src/main/java/org/bukkit/entity/ArmorStand.java @@ -344,4 +344,21 @@ public interface ArmorStand extends LivingEntity { diff --git a/patches/server-remapped/0131-Add-API-methods-to-control-if-armour-stands-can-move.patch b/patches/server-remapped/0131-Add-API-methods-to-control-if-armour-stands-can-move.patch deleted file mode 100644 index 970e858ba4..0000000000 --- a/patches/server-remapped/0131-Add-API-methods-to-control-if-armour-stands-can-move.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 21 Dec 2016 11:47:25 -0600 -Subject: [PATCH] Add API methods to control if armour stands can move - - -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 09d39b73e8a3987e58a502bd914a6451b807421b..46f0ebfc99352ec8b64bdff2c6bb8d17ecfeb619 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -1,6 +1,5 @@ - package net.minecraft.world.entity; - --import PathfinderGoalFloat; - import com.google.common.collect.Maps; - import java.util.Arrays; - import java.util.Iterator; -@@ -39,6 +38,7 @@ import net.minecraft.world.entity.ai.control.BodyRotationControl; - import net.minecraft.world.entity.ai.control.JumpControl; - import net.minecraft.world.entity.ai.control.LookControl; - import net.minecraft.world.entity.ai.control.MoveControl; -+import net.minecraft.world.entity.ai.goal.FloatGoal; - import net.minecraft.world.entity.ai.goal.Goal; - import net.minecraft.world.entity.ai.goal.GoalSelector; - import net.minecraft.world.entity.ai.navigation.GroundPathNavigation; -@@ -47,6 +47,8 @@ import net.minecraft.world.entity.ai.sensing.Sensing; - import net.minecraft.world.entity.decoration.HangingEntity; - import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; - import net.minecraft.world.entity.item.ItemEntity; -+import net.minecraft.world.entity.monster.Blaze; -+import net.minecraft.world.entity.monster.EnderMan; - import net.minecraft.world.entity.monster.Enemy; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.vehicle.Boat; -@@ -97,7 +99,7 @@ public abstract class Mob extends LivingEntity { - private final BodyRotationControl bodyRotationControl; - protected PathNavigation navigation; - public GoalSelector goalSelector; -- @Nullable public PathfinderGoalFloat goalFloat; // Paper -+ @Nullable public FloatGoal goalFloat; // Paper - public GoalSelector targetSelector; - private LivingEntity target; - private final Sensing sensing; -@@ -789,7 +791,7 @@ public abstract class Mob extends LivingEntity { - if (goalFloat.validConditions()) goalFloat.update(); - this.getJumpControl().jumpIfSet(); - } -- if ((this instanceof EntityBlaze || this instanceof EntityEnderman) && isInWaterOrRainOrBubble()) { -+ if ((this instanceof Blaze || this instanceof EnderMan) && isInWaterOrRainOrBubble()) { - hurt(DamageSource.DROWN, 1.0F); - } - return; -diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 438dd75e3adffc395960b34b8bb26cbc07a4291e..8b6ec9ddf0d47bf4369b247e764f75893ab15781 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -26,6 +26,7 @@ import net.minecraft.world.entity.HumanoidArm; - import net.minecraft.world.entity.LightningBolt; - import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.Mob; -+import net.minecraft.world.entity.MoverType; - import net.minecraft.world.entity.Pose; - import net.minecraft.world.entity.projectile.AbstractArrow; - import net.minecraft.world.entity.vehicle.AbstractMinecart; -@@ -75,6 +76,7 @@ public class ArmorStand extends LivingEntity { - public Rotations rightArmPose; - public Rotations leftLegPose; - public Rotations rightLegPose; -+ public boolean canMove = true; // Paper - - public ArmorStand(EntityType type, Level world) { - super(type, world); -@@ -858,4 +860,13 @@ public class ArmorStand extends LivingEntity { - private EntityDimensions getDimensionsMarker(boolean flag) { - return flag ? ArmorStand.MARKER_DIMENSIONS : (this.isBaby() ? ArmorStand.BABY_DIMENSIONS : this.getType().getDimensions()); - } -+ -+ // Paper start -+ @Override -+ public void move(MoverType type, Vec3 movement) { -+ if (this.canMove) { -+ super.move(type, movement); -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 6b292162fb8c6416b1637b7b83e5113f6a35dbac..16f996d505b96da8a40c7709214ebbd2a0d0d9f3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -228,4 +228,15 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public boolean hasEquipmentLock(EquipmentSlot equipmentSlot, LockType lockType) { - return (getHandle().disabledSlots & (1 << CraftEquipmentSlot.getNMS(equipmentSlot).getFilterFlag() + lockType.ordinal() * 8)) != 0; - } -+ // Paper start -+ @Override -+ public boolean canMove() { -+ return getHandle().canMove; -+ } -+ -+ @Override -+ public void setCanMove(boolean move) { -+ getHandle().canMove = move; -+ } -+ // Paper end - } diff --git a/patches/server-remapped/0133-String-based-Action-Bar-API.patch b/patches/server-remapped/0133-String-based-Action-Bar-API.patch deleted file mode 100644 index 416d50b18b..0000000000 --- a/patches/server-remapped/0133-String-based-Action-Bar-API.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 27 Dec 2016 15:02:42 -0500 -Subject: [PATCH] String based Action Bar API - - -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index 67fa685f4b8de3eae1431c0de399c246678b542a..7b36274718b7cce24ac00530697f145648d52590 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -58,7 +58,7 @@ public class Util { - private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main"); - private static final ExecutorService IO_POOL = makeIoExecutor(); - public static LongSupplier timeSource = System::nanoTime; -- public static final UUID NIL_UUID = new UUID(0L, 0L); -+ public static final UUID NIL_UUID = new UUID(0L, 0L); public static final UUID getNullUUID() {return NIL_UUID;} // Paper OBFHELPER - private static final Logger LOGGER = LogManager.getLogger(); - - public static Collector, ?, Map> toMap() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index fc19b4cacd223b928fbdf922b828beaed630bf2e..d6d4e5ab7551f802dc2d3ab055d340d471ed0bc2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -242,6 +242,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - // Paper start -+ @Override -+ public void sendActionBar(BaseComponent[] message) { -+ if (getHandle().connection == null) return; -+ getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.ACTIONBAR, message, -1, -1, -1)); -+ } -+ -+ @Override -+ public void sendActionBar(String message) { -+ if (getHandle().connection == null || message == null || message.isEmpty()) return; -+ getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.ACTIONBAR, CraftChatMessage.fromStringOrNull(message))); -+ } -+ -+ @Override -+ public void sendActionBar(char alternateChar, String message) { -+ if (message == null || message.isEmpty()) return; -+ sendActionBar(org.bukkit.ChatColor.translateAlternateColorCodes(alternateChar, message)); -+ } -+ - @Override - public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { - if (header != null) { diff --git a/patches/server-remapped/0122-Allow-Reloading-of-Command-Aliases.patch b/patches/server/0111-Allow-Reloading-of-Command-Aliases.patch similarity index 90% rename from patches/server-remapped/0122-Allow-Reloading-of-Command-Aliases.patch rename to patches/server/0111-Allow-Reloading-of-Command-Aliases.patch index 360a4a34cc..92da7ddad7 100644 --- a/patches/server-remapped/0122-Allow-Reloading-of-Command-Aliases.patch +++ b/patches/server/0111-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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index bbe0978f56d23b7defce765d381d4a7c20acd75c..9365fd2bcf74755c90c4ae9b550969e97a22c639 100644 +index 91002473f54fd0ac95489b9448fe91072565881d..13993c425daf112393472f791480f9105038f104 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2281,5 +2281,24 @@ public final class CraftServer implements Server { +@@ -2280,5 +2280,24 @@ public final class CraftServer implements Server { DefaultPermissions.registerCorePermissions(); CraftDefaultPermissions.registerCorePermissions(); } diff --git a/patches/server-remapped/0123-Add-source-to-PlayerExpChangeEvent.patch b/patches/server/0112-Add-source-to-PlayerExpChangeEvent.patch similarity index 66% rename from patches/server-remapped/0123-Add-source-to-PlayerExpChangeEvent.patch rename to patches/server/0112-Add-source-to-PlayerExpChangeEvent.patch index 0ab2cb875a..9792aa668a 100644 --- a/patches/server-remapped/0123-Add-source-to-PlayerExpChangeEvent.patch +++ b/patches/server/0112-Add-source-to-PlayerExpChangeEvent.patch @@ -5,31 +5,23 @@ Subject: [PATCH] Add source to PlayerExpChangeEvent diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index a4a1e836767d0b2b71c3277a28eb72418fa76210..f932fc4f8240b48f8e518af05d1521bc8ff9cbee 100644 +index 7df6946dcb2a7fbc625681dfbae1e15be625875b..1953739fd2ead7680273ef63d8506e546758dc9b 100644 --- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -202,7 +202,7 @@ public class ExperienceOrb extends Entity { - } +@@ -249,7 +249,7 @@ public class ExperienceOrb extends Entity { + int i = this.repairPlayerItems(player, this.value); - if (this.value > 0) { -- player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, this.value).getAmount()); // CraftBukkit - this.value -> event.getAmount() + if (i > 0) { +- player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, i).getAmount()); // CraftBukkit - this.value -> event.getAmount() + player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object } - this.remove(); + --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 81af3e2e0964b6e179f92a342efdae943be18b75..c85fcad33e17c8ae2e4ee5cb873dbd4166fcc7f5 100644 +index cb3f1f71cc5c5a18c0af818679b72583a7edec7c..c981bb0e1e7c4c8b7603e2ac8e483ad5b4a2c742 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -109,6 +109,7 @@ import org.bukkit.entity.ThrownPotion; - import org.bukkit.entity.Vehicle; - import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; -+import org.bukkit.entity.ExperienceOrb; // Paper - import org.bukkit.event.Cancellable; - import org.bukkit.event.Event; - import org.bukkit.event.Event.Result; -@@ -1045,6 +1046,17 @@ public class CraftEventFactory { +@@ -1041,6 +1041,17 @@ public class CraftEventFactory { return event; } @@ -45,5 +37,5 @@ index 81af3e2e0964b6e179f92a342efdae943be18b75..c85fcad33e17c8ae2e4ee5cb873dbd41 + // Paper end + public static boolean handleBlockGrowEvent(Level world, BlockPos pos, net.minecraft.world.level.block.state.BlockState block) { - return handleBlockGrowEvent(world, pos, block, 3); + return CraftEventFactory.handleBlockGrowEvent(world, pos, block, 3); } diff --git a/patches/server-remapped/0124-Don-t-let-fishinghooks-use-portals.patch b/patches/server/0113-Don-t-let-fishinghooks-use-portals.patch similarity index 80% rename from patches/server-remapped/0124-Don-t-let-fishinghooks-use-portals.patch rename to patches/server/0113-Don-t-let-fishinghooks-use-portals.patch index 6845784927..09cbca08b9 100644 --- a/patches/server-remapped/0124-Don-t-let-fishinghooks-use-portals.patch +++ b/patches/server/0113-Don-t-let-fishinghooks-use-portals.patch @@ -5,16 +5,16 @@ Subject: [PATCH] Don't let fishinghooks use portals diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -index 2f67c2065ef29f17f12190b25bd1ea53e1fb55b4..fa078167dd9e0cae80516549eef0e554c13938a3 100644 +index c30b53d07bcd2575d65c323d8170573bbe85f212..d25fe9cb2cf755f3e34a79ce87ed38c1ffada53f 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -@@ -237,6 +237,11 @@ public class FishingHook extends Projectile { +@@ -253,6 +253,11 @@ public class FishingHook extends Projectile { this.setDeltaMovement(this.getDeltaMovement().scale(0.92D)); this.reapplyPosition(); + // Paper start - These shouldn't be going through portals + if (this.isInsidePortal) { -+ this.remove(); ++ this.discard(); + } + // Paper end } diff --git a/patches/server-remapped/0125-Add-ProjectileCollideEvent.patch b/patches/server/0114-Add-ProjectileCollideEvent.patch similarity index 88% rename from patches/server-remapped/0125-Add-ProjectileCollideEvent.patch rename to patches/server/0114-Add-ProjectileCollideEvent.patch index 0f4f99f50a..96765a5d30 100644 --- a/patches/server-remapped/0125-Add-ProjectileCollideEvent.patch +++ b/patches/server/0114-Add-ProjectileCollideEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add ProjectileCollideEvent 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 0dc5792d542658107c9c22c1f920986decd13920..3ce431c1fdf1f5bd62b49f26cca188e939e98efa 100644 +index 676e5ad3a23bfdccd8f5f7bb9e79c3fa004dc95f..71f0de893fe0243cc226fd36685f2a3fba02575f 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -196,6 +196,17 @@ public abstract class AbstractArrow extends Projectile { +@@ -225,6 +225,17 @@ public abstract class AbstractArrow extends Projectile { } } @@ -27,10 +27,10 @@ index 0dc5792d542658107c9c22c1f920986decd13920..3ce431c1fdf1f5bd62b49f26cca188e9 this.preOnHit((HitResult) object); // CraftBukkit - projectile hit event this.hasImpulse = true; diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -index bdff1c57f64d1bf29f2050f06c8b585d395b2c5c..872ff430547276e2a41a48aa07ae63b87ab39e5d 100644 +index a8b51bece92676f1964a795112a1d490b437ed0f..dd5209ab2e5b59312349e709392689f25da162c0 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -@@ -12,6 +12,7 @@ import net.minecraft.world.entity.Entity; +@@ -11,6 +11,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.level.Level; @@ -38,7 +38,7 @@ index bdff1c57f64d1bf29f2050f06c8b585d395b2c5c..872ff430547276e2a41a48aa07ae63b8 import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit -@@ -71,7 +72,16 @@ public abstract class AbstractHurtingProjectile extends Projectile { +@@ -82,7 +83,16 @@ public abstract class AbstractHurtingProjectile extends Projectile { HitResult movingobjectposition = ProjectileUtil.getHitResult((Entity) this, this::canHitEntity); @@ -57,10 +57,10 @@ index bdff1c57f64d1bf29f2050f06c8b585d395b2c5c..872ff430547276e2a41a48aa07ae63b8 // CraftBukkit start - Fire ProjectileHitEvent diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java -index 23f255bfa63cd16e2930fc932a2f4df8e522f2dc..becb07cda7388bcf2e987f06557894ae50d70dbf 100644 +index f81be1c6a5efc5090fbb8832f44dbb2ae6aa2f4a..8e81b19706a14c21b5ffdc4f12818fe74adc9ddb 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java -@@ -13,6 +13,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; +@@ -11,6 +11,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; @@ -68,7 +68,7 @@ index 23f255bfa63cd16e2930fc932a2f4df8e522f2dc..becb07cda7388bcf2e987f06557894ae import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; -@@ -57,7 +58,17 @@ public abstract class ThrowableProjectile extends Projectile { +@@ -67,7 +68,17 @@ public abstract class ThrowableProjectile extends Projectile { } if (movingobjectposition.getType() != HitResult.Type.MISS && !flag) { @@ -87,10 +87,10 @@ index 23f255bfa63cd16e2930fc932a2f4df8e522f2dc..becb07cda7388bcf2e987f06557894ae this.checkInsideBlocks(); diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index c85fcad33e17c8ae2e4ee5cb873dbd4166fcc7f5..3f082b7fd50752728917a7da28cba4cb396a9fdf 100644 +index c981bb0e1e7c4c8b7603e2ac8e483ad5b4a2c742..56900b5810db623a49559ad218a5385c110bf479 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1190,6 +1190,16 @@ public class CraftEventFactory { +@@ -1185,6 +1185,16 @@ public class CraftEventFactory { return CraftItemStack.asNMSCopy(bitem); } diff --git a/patches/server-remapped/0126-Prevent-Pathfinding-out-of-World-Border.patch b/patches/server/0115-Prevent-Pathfinding-out-of-World-Border.patch similarity index 70% rename from patches/server-remapped/0126-Prevent-Pathfinding-out-of-World-Border.patch rename to patches/server/0115-Prevent-Pathfinding-out-of-World-Border.patch index f8a0e7b1ea..05d9a4a7be 100644 --- a/patches/server-remapped/0126-Prevent-Pathfinding-out-of-World-Border.patch +++ b/patches/server/0115-Prevent-Pathfinding-out-of-World-Border.patch @@ -5,14 +5,21 @@ Subject: [PATCH] Prevent Pathfinding out of World Border This prevents Entities from trying to run outside of the World Border +TODO: This doesn't prevent the pathfinder from using blocks outside the world border as nodes. We can fix this +by adding code to all overrides in: + NodeEvaluator: + public abstract BlockPathTypes getBlockPathType(BlockGetter world, int x, int y, int z); + +to return BLOCKED if it is outside the world border. + diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index 25bc3adfad956157cef0953e6e632b7b7e352f3a..c3082f5dd64413a47421cb01538bec846bf21d2c 100644 +index 6c063351c76e92a8a91142a12db846d1c1f11921..8212aab2884c2a894bc981850e483ce31814c708 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -148,7 +148,7 @@ public abstract class PathNavigation { +@@ -156,7 +156,7 @@ public abstract class PathNavigation { // Paper start - Pathfind event boolean copiedSet = false; - for (BlockPos possibleTarget : set) { + for (BlockPos possibleTarget : positions) { - if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), + if (!getEntity().getCommandSenderWorld().getWorldBorder().isInBounds(possibleTarget) || !new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), // Paper - don't path out of world border MCUtil.toLocation(getEntity().level, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { diff --git a/patches/server-remapped/0127-Optimize-World.isLoaded-BlockPosition-Z.patch b/patches/server/0116-Optimize-World.isLoaded-BlockPosition-Z.patch similarity index 85% rename from patches/server-remapped/0127-Optimize-World.isLoaded-BlockPosition-Z.patch rename to patches/server/0116-Optimize-World.isLoaded-BlockPosition-Z.patch index 6a3d81e0fe..7b2c7441b8 100644 --- a/patches/server-remapped/0127-Optimize-World.isLoaded-BlockPosition-Z.patch +++ b/patches/server/0116-Optimize-World.isLoaded-BlockPosition-Z.patch @@ -6,13 +6,14 @@ Subject: [PATCH] Optimize World.isLoaded(BlockPosition)Z Reduce method invocations for World.isLoaded(BlockPosition)Z diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 5f3d17cb247156fc8aaa7a763e402c2bbb42a7ec..ecb6378a285dff4b34170410387ebb7a8510a6dc 100644 +index e26cb05a91cf2b3ac059dcb55bc52f1e4f30b362..52d80086deff664fcfd8952b7cabbfa1f48ad131 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -305,6 +305,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -316,6 +316,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { return chunk == null ? null : chunk.getFluidState(blockposition); } ++ @Override + public final boolean hasChunkAt(BlockPos pos) { + return getChunkIfLoaded(pos.getX() >> 4, pos.getZ() >> 4) != null; // Paper + } diff --git a/patches/server-remapped/0128-Bound-Treasure-Maps-to-World-Border.patch b/patches/server/0117-Bound-Treasure-Maps-to-World-Border.patch similarity index 68% rename from patches/server-remapped/0128-Bound-Treasure-Maps-to-World-Border.patch rename to patches/server/0117-Bound-Treasure-Maps-to-World-Border.patch index b839110284..635c6e9001 100644 --- a/patches/server-remapped/0128-Bound-Treasure-Maps-to-World-Border.patch +++ b/patches/server/0117-Bound-Treasure-Maps-to-World-Border.patch @@ -11,10 +11,10 @@ that is outside happens to be closer, but unreachable, yet another reachable one is in border that would of been missed. diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 0846f649dca3422dbab3bb0a4826e27430cc8186..7a728ca96ee2eaf776c391ba8351196a526e18ec 100644 +index 02b10be4878b871742efb0f65980d9672f32b388..4a61153eaf9cf4c8aa532f770c0e449325448107 100644 --- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java +++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -36,6 +36,18 @@ public class WorldBorder { +@@ -37,6 +37,18 @@ public class WorldBorder { return (double) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ(); } @@ -34,14 +34,14 @@ index 0846f649dca3422dbab3bb0a4826e27430cc8186..7a728ca96ee2eaf776c391ba8351196a return (double) pos.getMaxBlockX() > this.getMinX() && (double) pos.getMinBlockX() < this.getMaxX() && (double) pos.getMaxBlockZ() > this.getMinZ() && (double) pos.getMinBlockZ() < this.getMaxZ(); } diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -index 9f60abfe0a37e30c5528a1ca0546295b00598798..0624b8270bc28c83c5479cd51fa4633ed5c36f44 100644 +index a66a02d2d1294060048c3c2b2219af87cdb13060..3878a7f6402a1dff1e019e16dd8772ec7303ebe7 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -@@ -175,6 +175,7 @@ public abstract class StructureFeature { - int i2 = l + k * k1; - int j2 = i1 + k * l1; - ChunkPos chunkcoordintpair = this.getPotentialFeatureChunk(config, worldSeed, seededrandom, i2, j2); -+ if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper - ChunkAccess ichunkaccess = world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); - StructureStart structurestart = structureAccessor.getStartForFeature(SectionPos.of(ichunkaccess.getPos(), 0), this, ichunkaccess); - +@@ -168,6 +168,7 @@ public abstract class StructureFeature { + int o = j + i * m; + int p = k + i * n; + ChunkPos chunkPos = this.getPotentialFeatureChunk(config, worldSeed, worldgenRandom, o, p); ++ if (!world.getWorldBorder().isChunkInBounds(chunkPos.x, chunkPos.z)) { continue; } // Paper + boolean bl3 = world.getBiomeManager().getPrimaryBiomeAtChunk(chunkPos).getGenerationSettings().isValidStart(this); + if (bl3) { + ChunkAccess chunkAccess = world.getChunk(chunkPos.x, chunkPos.z, ChunkStatus.STRUCTURE_STARTS); diff --git a/patches/server-remapped/0129-Configurable-Cartographer-Treasure-Maps.patch b/patches/server/0118-Configurable-Cartographer-Treasure-Maps.patch similarity index 57% rename from patches/server-remapped/0129-Configurable-Cartographer-Treasure-Maps.patch rename to patches/server/0118-Configurable-Cartographer-Treasure-Maps.patch index 2eabafdf57..04c2e1dd34 100644 --- a/patches/server-remapped/0129-Configurable-Cartographer-Treasure-Maps.patch +++ b/patches/server/0118-Configurable-Cartographer-Treasure-Maps.patch @@ -28,30 +28,30 @@ index e83216be5a00d5b927d8c2fc364551bd3077c974..2dc58b9f769ea43b737804456aafab47 + } } diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -index fd1b84baae5f333c58dbbdcbfaa9198328f0961d..7d490e1be772be22c3ab75c7e356465183a5c6b1 100644 +index ae2fba922b5a8c9b4096ea8255ff20db58fcd88f..314617cb0d2df92cc394f7a80011f5b6d075419b 100644 --- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java +++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -@@ -124,7 +124,8 @@ public class VillagerTrades { +@@ -383,7 +383,8 @@ public class VillagerTrades { return null; } else { - ServerLevel worldserver = (ServerLevel) entity.level; -- BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, entity.blockPosition(), 100, true); -+ if (!worldserver.paperConfig.enableTreasureMaps) return null; // Paper -+ BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, entity.blockPosition(), 100, !worldserver.paperConfig.treasureMapsAlreadyDiscovered); // Paper - - if (blockposition != null) { - ItemStack itemstack = MapItem.create(worldserver, blockposition.getX(), blockposition.getZ(), (byte) 2, true, true); + ServerLevel serverLevel = (ServerLevel)entity.level; +- BlockPos blockPos = serverLevel.findNearestMapFeature(this.destination, entity.blockPosition(), 100, true); ++ if (!serverLevel.paperConfig.enableTreasureMaps) return null; // Paper ++ BlockPos blockPos = serverLevel.findNearestMapFeature(this.destination, entity.blockPosition(), 100, !serverLevel.paperConfig.treasureMapsAlreadyDiscovered); // Paper + if (blockPos != null) { + ItemStack itemStack = MapItem.create(serverLevel, blockPos.getX(), blockPos.getZ(), (byte)2, true, true); + MapItem.renderBiomePreviewMap(serverLevel, itemStack); diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java -index a3ce120b0da62f9be938c58c3414ce997f5d30ea..81a8331bfdf30da6ea69952ae42d3c77a2103bfd 100644 +index ce5375dc1974042fd4e81a93a6087d7d286074af..d9452518368c6da097ee142d9b38b52188dc4a5b 100644 --- a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java +++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java -@@ -64,7 +64,16 @@ public class ExplorationMapFunction extends LootItemConditionalFunction { - - if (vec3d != null) { - ServerLevel worldserver = context.getLevel(); -- BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, new BlockPos(vec3d), this.searchRadius, this.skipKnownStructures); +@@ -65,7 +65,16 @@ public class ExplorationMapFunction extends LootItemConditionalFunction { + Vec3 vec3 = context.getParamOrNull(LootContextParams.ORIGIN); + if (vec3 != null) { + ServerLevel serverLevel = context.getLevel(); +- BlockPos blockPos = serverLevel.findNearestMapFeature(this.destination, new BlockPos(vec3), this.searchRadius, this.skipKnownStructures); + // Paper start -+ if (!worldserver.paperConfig.enableTreasureMaps) { ++ if (!serverLevel.paperConfig.enableTreasureMaps) { + /* + * NOTE: I fear users will just get a plain map as their "treasure" + * This is preferable to disrespecting the config. @@ -59,7 +59,7 @@ index a3ce120b0da62f9be938c58c3414ce997f5d30ea..81a8331bfdf30da6ea69952ae42d3c77 + return stack; + } + // Paper end -+ BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, new BlockPos(vec3d), this.searchRadius, !worldserver.paperConfig.treasureMapsAlreadyDiscovered && this.skipKnownStructures); // Paper - - if (blockposition != null) { - ItemStack itemstack1 = MapItem.create(worldserver, blockposition.getX(), blockposition.getZ(), this.zoom, true, true); ++ BlockPos blockPos = serverLevel.findNearestMapFeature(this.destination, new BlockPos(vec3), this.searchRadius, !serverLevel.paperConfig.treasureMapsAlreadyDiscovered && this.skipKnownStructures); // Paper + if (blockPos != null) { + ItemStack itemStack = MapItem.create(serverLevel, blockPos.getX(), blockPos.getZ(), this.zoom, true, true); + MapItem.renderBiomePreviewMap(serverLevel, itemStack); diff --git a/patches/server-remapped/0130-Optimize-ItemStack.isEmpty.patch b/patches/server/0119-Optimize-ItemStack.isEmpty.patch similarity index 66% rename from patches/server-remapped/0130-Optimize-ItemStack.isEmpty.patch rename to patches/server/0119-Optimize-ItemStack.isEmpty.patch index 329afa7401..01d8825e96 100644 --- a/patches/server-remapped/0130-Optimize-ItemStack.isEmpty.patch +++ b/patches/server/0119-Optimize-ItemStack.isEmpty.patch @@ -6,15 +6,15 @@ Subject: [PATCH] Optimize ItemStack.isEmpty() Remove hashMap lookup every check, simplify code to remove ternary diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 123025c6dc9a2eea56c7db5cb508cdfd7c6cc97b..a0815c0d7f68f345dc48c73b8253de637c7a3e0f 100644 +index d3267cdef523b62f9985e49b768e6ad22fbe874d..4d4b471bbfb2d9174391c8adc6075ec11295408b 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -206,7 +206,7 @@ public final class ItemStack { +@@ -241,7 +241,7 @@ public final class ItemStack { } public boolean isEmpty() { -- return this == ItemStack.EMPTY ? true : (this.getItem() != null && this.getItem() != Items.AIR ? this.count <= 0 : true); -+ return this == ItemStack.NULL_ITEM || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper +- return this == ItemStack.EMPTY ? true : (this.getItem() != null && !this.is(Items.AIR) ? this.count <= 0 : true); ++ return this == ItemStack.EMPTY || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper } public ItemStack split(int amount) { diff --git a/patches/server/0120-Add-API-methods-to-control-if-armour-stands-can-move.patch b/patches/server/0120-Add-API-methods-to-control-if-armour-stands-can-move.patch new file mode 100644 index 0000000000..4c9bea0528 --- /dev/null +++ b/patches/server/0120-Add-API-methods-to-control-if-armour-stands-can-move.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 21 Dec 2016 11:47:25 -0600 +Subject: [PATCH] Add API methods to control if armour stands can move + + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index fd2d0eaa190068646250956c4d5e5e9aeee7b1e4..ef382aaeb86ca41356a076ff4adfe5fb652b43c5 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -92,6 +92,7 @@ public class ArmorStand extends LivingEntity { + public Rotations rightArmPose; + public Rotations leftLegPose; + public Rotations rightLegPose; ++ public boolean canMove = true; // Paper + + public ArmorStand(EntityType type, Level world) { + super(type, world); +@@ -927,4 +928,13 @@ public class ArmorStand extends LivingEntity { + public boolean canBeSeenByAnyone() { + return !this.isInvisible() && !this.isMarker(); + } ++ ++ // Paper start ++ @Override ++ public void move(net.minecraft.world.entity.MoverType type, Vec3 movement) { ++ if (this.canMove) { ++ super.move(type, movement); ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +index 47ca72e264950dd950f037a21bb0ad6cc1700751..06cedeea447f53d100e32a6eba6f83b4719cb231 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +@@ -228,4 +228,15 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public boolean hasEquipmentLock(EquipmentSlot equipmentSlot, LockType lockType) { + return (this.getHandle().disabledSlots & (1 << CraftEquipmentSlot.getNMS(equipmentSlot).getFilterFlag() + lockType.ordinal() * 8)) != 0; + } ++ // Paper start ++ @Override ++ public boolean canMove() { ++ return getHandle().canMove; ++ } ++ ++ @Override ++ public void setCanMove(boolean move) { ++ getHandle().canMove = move; ++ } ++ // Paper end + } diff --git a/patches/server/0121-String-based-Action-Bar-API.patch b/patches/server/0121-String-based-Action-Bar-API.patch new file mode 100644 index 0000000000..0ef38a7816 --- /dev/null +++ b/patches/server/0121-String-based-Action-Bar-API.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 27 Dec 2016 15:02:42 -0500 +Subject: [PATCH] String based Action Bar API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index d50ce7fc675fcc57f591e90eb0bbb99a4ab21b02..1da034d28732a5f5b9bd9b31966da21830efdc9f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -247,6 +247,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + + // Paper start ++ @Override ++ public void sendActionBar(BaseComponent[] message) { ++ if (getHandle().connection == null) return; ++ getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket(Component.Serializer.fromJson(net.md_5.bungee.chat.ComponentSerializer.toString(message)))); ++ } ++ ++ @Override ++ public void sendActionBar(String message) { ++ if (getHandle().connection == null || message == null || message.isEmpty()) return; ++ getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket(CraftChatMessage.fromStringOrNull(message))); ++ } ++ ++ @Override ++ public void sendActionBar(char alternateChar, String message) { ++ if (message == null || message.isEmpty()) return; ++ sendActionBar(org.bukkit.ChatColor.translateAlternateColorCodes(alternateChar, message)); ++ } ++ + @Override + public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { + if (header != null) { From 864ef24fc0773429d434d4044186fc430a395c18 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Sat, 12 Jun 2021 09:30:37 +0200 Subject: [PATCH 039/226] fix profile cache mappings let me be OP god dammit! --- build-data/mappings-patch.tiny | 5 +++++ patches/server/0094-Optimize-UserCache-Thread-Safe.patch | 8 ++++---- .../0101-Add-setting-for-proxy-online-mode-status.patch | 8 ++++---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/build-data/mappings-patch.tiny b/build-data/mappings-patch.tiny index 572cb1137b..b15b9e635c 100644 --- a/build-data/mappings-patch.tiny +++ b/build-data/mappings-patch.tiny @@ -78,3 +78,8 @@ c net/minecraft/world/entity/projectile/EntityTippedArrow net/minecraft/world/en # missed mapping? c net/minecraft/world/level/block/MultifaceBlock net/minecraft/world/level/block/MultifaceBlock m (Lnet/minecraft/world/level/block/state/IBlockData;Lnet/minecraft/world/level/IBlockAccess;Lnet/minecraft/core/BlockPosition;Lnet/minecraft/core/EnumDirection;)Lnet/minecraft/world/level/block/state/IBlockData; c getStateForPlacement + +# another missed one +c net/minecraft/server/players/UserCache net/minecraft/server/players/GameProfileCache + m (Ljava/lang/String;)Lcom/mojang/authlib/GameProfile; getProfile get + p 0 name diff --git a/patches/server/0094-Optimize-UserCache-Thread-Safe.patch b/patches/server/0094-Optimize-UserCache-Thread-Safe.patch index 70a622d00d..3104361cd5 100644 --- a/patches/server/0094-Optimize-UserCache-Thread-Safe.patch +++ b/patches/server/0094-Optimize-UserCache-Thread-Safe.patch @@ -38,7 +38,7 @@ index 566390d02b2af4a0f2c867b7ff8116a8301e8497..e2095308a8ec8471b04acce929d314fd if (!OldUsersConverter.serverReadyAfterUserconversion(this)) { diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index 8b972d0fec5636b1979abf4055ea8d29530158f4..95682f63c7ae1460b069e13f11295f72c1f262a8 100644 +index 1dd9b362384543e17b537dd209665d956214916d..c70b4727fe0ae9ff7b9db08a9711272994159b96 100644 --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java +++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java @@ -117,7 +117,7 @@ public class GameProfileCache { @@ -63,9 +63,9 @@ index 8b972d0fec5636b1979abf4055ea8d29530158f4..95682f63c7ae1460b069e13f11295f72 } @Nullable -- public GameProfile getProfile(String s) { -+ public synchronized GameProfile getProfile(String s) { // Paper - synchronize - String s1 = s.toLowerCase(Locale.ROOT); +- public GameProfile get(String name) { ++ public synchronized GameProfile get(String name) { // Paper - synchronize + String s1 = name.toLowerCase(Locale.ROOT); GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1); boolean flag = false; @@ -160,7 +160,7 @@ public class GameProfileCache { diff --git a/patches/server/0101-Add-setting-for-proxy-online-mode-status.patch b/patches/server/0101-Add-setting-for-proxy-online-mode-status.patch index 16e6c2528a..da61f74c62 100644 --- a/patches/server/0101-Add-setting-for-proxy-online-mode-status.patch +++ b/patches/server/0101-Add-setting-for-proxy-online-mode-status.patch @@ -32,7 +32,7 @@ index 1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2..c52dc0346f93527965ef29a0ccdc4bf3 + } } diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index b2bd204879badfe1cab6bea9db2d6c412505a9ce..73dbc4db56bbafefd07ad550d006a437b1ed1b95 100644 +index 87f5f4108796aa12b454bbf39b8c1d699bac78f2..3eb4bee81a8543cc06b9d5898f5f6c0e9dbbf554 100644 --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java +++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java @@ -97,6 +97,7 @@ public class GameProfileCache { @@ -53,7 +53,7 @@ index b2bd204879badfe1cab6bea9db2d6c412505a9ce..73dbc4db56bbafefd07ad550d006a437 public synchronized void add(GameProfile profile) { // Paper - synchronize diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java -index da515ac94aa3c294855f28e6deb9094cc7187dd9..b61a3217c70f3f5c4c06131b3c4978534d7d935a 100644 +index 8e27b43e2f6ce4d7f5007fe02db1722e73c30a58..6aacc724c8c8d6fbe3067226989039ca9cee4929 100644 --- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java +++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java @@ -65,7 +65,8 @@ public class OldUsersConverter { @@ -67,7 +67,7 @@ index da515ac94aa3c294855f28e6deb9094cc7187dd9..b61a3217c70f3f5c4c06131b3c497853 } else { String[] astring1 = astring; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 95689d11668e37a894b70517270849c2c4e162aa..91002473f54fd0ac95489b9448fe91072565881d 100644 +index 290dd0b3f90d57e9fe4ae06e4c4a0a30a1c15bfc..5fafb27748102356cdeb6c5a78bb671a00afccc3 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -1515,7 +1515,7 @@ public final class CraftServer implements Server { @@ -77,5 +77,5 @@ index 95689d11668e37a894b70517270849c2c4e162aa..91002473f54fd0ac95489b9448fe9107 - if ( this.getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) + if ( this.getOnlineMode() || com.destroystokyo.paper.PaperConfig.isProxyOnlineMode() ) // Paper - Handle via setting { - profile = this.console.getProfileCache().getProfile( name ); + profile = this.console.getProfileCache().get( name ); } From 1753b33104c7e6b051b33bddacd1b8197ef90942 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sat, 12 Jun 2021 02:01:04 -0700 Subject: [PATCH 040/226] even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even more work --- .../0045-IllegalPacketEvent.patch} | 0 .../0046-Fireworks-API-s.patch} | 0 .../0047-PlayerTeleportEndGatewayEvent.patch} | 0 ...ovide-E-TE-Chunk-count-stat-methods.patch} | 2 +- ...I-for-Reason-Source-Triggering-play.patch} | 0 .../server-remapped/0134-Firework-API-s.patch | 124 --------- ...rovide-E-TE-Chunk-count-stat-methods.patch | 61 ----- ...more-aggressive-in-the-chunk-unload-.patch | 47 ---- .../0143-Do-not-let-armorstands-drown.patch | 42 ---- ...2-Properly-fix-item-duplication-bug.patch} | 14 +- patches/server/0123-Firework-API-s.patch | 99 ++++++++ .../0124-PlayerTeleportEndGatewayEvent.patch} | 8 +- ...rovide-E-TE-Chunk-count-stat-methods.patch | 96 +++++++ .../0126-Enforce-Sync-Player-Saves.patch} | 8 +- ...low-entities-to-ride-themselves-572.patch} | 4 +- ...I-for-Reason-Source-Triggering-play.patch} | 235 ++++++++++-------- .../0129-Cap-Entity-Collisions.patch} | 14 +- ...-CraftScheduler-Async-Task-Debugger.patch} | 24 +- ...more-aggressive-in-the-chunk-unload-.patch | 38 +++ .../0132-Do-not-let-armorstands-drown.patch | 23 ++ ...e-async-calls-to-restart-the-server.patch} | 47 ++-- 21 files changed, 434 insertions(+), 452 deletions(-) rename patches/{api-unmapped/0044-IllegalPacketEvent.patch => api/0045-IllegalPacketEvent.patch} (100%) rename patches/{api-unmapped/0045-Fireworks-API-s.patch => api/0046-Fireworks-API-s.patch} (100%) rename patches/{api-unmapped/0046-PlayerTeleportEndGatewayEvent.patch => api/0047-PlayerTeleportEndGatewayEvent.patch} (100%) rename patches/{api-unmapped/0047-Provide-E-TE-Chunk-count-stat-methods.patch => api/0048-Provide-E-TE-Chunk-count-stat-methods.patch} (93%) rename patches/{api-unmapped/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch => api/0049-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch} (100%) delete mode 100644 patches/server-remapped/0134-Firework-API-s.patch delete mode 100644 patches/server-remapped/0136-Provide-E-TE-Chunk-count-stat-methods.patch delete mode 100644 patches/server-remapped/0142-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch delete mode 100644 patches/server-remapped/0143-Do-not-let-armorstands-drown.patch rename patches/{server-remapped/0132-Properly-fix-item-duplication-bug.patch => server/0122-Properly-fix-item-duplication-bug.patch} (70%) create mode 100644 patches/server/0123-Firework-API-s.patch rename patches/{server-remapped/0135-PlayerTeleportEndGatewayEvent.patch => server/0124-PlayerTeleportEndGatewayEvent.patch} (80%) create mode 100644 patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch rename patches/{server-remapped/0137-Enforce-Sync-Player-Saves.patch => server/0126-Enforce-Sync-Player-Saves.patch} (75%) rename patches/{server-remapped/0138-Don-t-allow-entities-to-ride-themselves-572.patch => server/0127-Don-t-allow-entities-to-ride-themselves-572.patch} (80%) rename patches/{server-remapped/0139-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch => server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch} (59%) rename patches/{server-remapped/0140-Cap-Entity-Collisions.patch => server/0129-Cap-Entity-Collisions.patch} (78%) rename patches/{server-remapped/0141-Remove-CraftScheduler-Async-Task-Debugger.patch => server/0130-Remove-CraftScheduler-Async-Task-Debugger.patch} (62%) create mode 100644 patches/server/0131-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch create mode 100644 patches/server/0132-Do-not-let-armorstands-drown.patch rename patches/{server-remapped/0144-Properly-handle-async-calls-to-restart-the-server.patch => server/0133-Properly-handle-async-calls-to-restart-the-server.patch} (88%) diff --git a/patches/api-unmapped/0044-IllegalPacketEvent.patch b/patches/api/0045-IllegalPacketEvent.patch similarity index 100% rename from patches/api-unmapped/0044-IllegalPacketEvent.patch rename to patches/api/0045-IllegalPacketEvent.patch diff --git a/patches/api-unmapped/0045-Fireworks-API-s.patch b/patches/api/0046-Fireworks-API-s.patch similarity index 100% rename from patches/api-unmapped/0045-Fireworks-API-s.patch rename to patches/api/0046-Fireworks-API-s.patch diff --git a/patches/api-unmapped/0046-PlayerTeleportEndGatewayEvent.patch b/patches/api/0047-PlayerTeleportEndGatewayEvent.patch similarity index 100% rename from patches/api-unmapped/0046-PlayerTeleportEndGatewayEvent.patch rename to patches/api/0047-PlayerTeleportEndGatewayEvent.patch diff --git a/patches/api-unmapped/0047-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/api/0048-Provide-E-TE-Chunk-count-stat-methods.patch similarity index 93% rename from patches/api-unmapped/0047-Provide-E-TE-Chunk-count-stat-methods.patch rename to patches/api/0048-Provide-E-TE-Chunk-count-stat-methods.patch index fc838a6f02..5cd5541fcb 100644 --- a/patches/api-unmapped/0047-Provide-E-TE-Chunk-count-stat-methods.patch +++ b/patches/api/0048-Provide-E-TE-Chunk-count-stat-methods.patch @@ -7,7 +7,7 @@ Provides counts without the ineffeciency of using .getEntities().size() which creates copy of the collections. diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 6b5dbe4ea711807a1944cfe2aae2ce415d4f2638..789e070f6aee83e4b6426def784e05df98e1bc65 100644 +index d3519fa5b99e2888a194c6382415537785fbeef0..8804be419520859355b69660e6f3166d1aa8b1ea 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -40,6 +40,33 @@ import org.jetbrains.annotations.Nullable; diff --git a/patches/api-unmapped/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/api/0049-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch similarity index 100% rename from patches/api-unmapped/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch rename to patches/api/0049-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch diff --git a/patches/server-remapped/0134-Firework-API-s.patch b/patches/server-remapped/0134-Firework-API-s.patch deleted file mode 100644 index e3dc3d3182..0000000000 --- a/patches/server-remapped/0134-Firework-API-s.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 28 Dec 2016 07:18:33 +0100 -Subject: [PATCH] Firework API's - - -diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java -index 4c8f249e45e5deb7628997d4dbd9dab613ac5241..a91bf94ed9f2f353a685194fc91c4b101ccc1232 100644 ---- a/src/main/java/net/minecraft/nbt/CompoundTag.java -+++ b/src/main/java/net/minecraft/nbt/CompoundTag.java -@@ -153,6 +153,7 @@ public class CompoundTag implements Tag { - return NbtUtils.loadUUID(this.get(key)); - } - -+ public final boolean hasUUID(String s) { return this.hasUUID(s); } // Paper - OBFHELPER - public boolean hasUUID(String key) { - Tag nbtbase = this.get(key); - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -index 28a2c6a0fbc8b4c38f3899698504d8ca0d7ba3af..5669be107b580075fdffbcbb490513593a57fc9f 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -@@ -37,7 +37,8 @@ public class FireworkRocketEntity extends Projectile { - public static final EntityDataAccessor DATA_SHOT_AT_ANGLE = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.BOOLEAN); - private int life; - public int lifetime; -- private LivingEntity attachedToEntity; -+ public LivingEntity attachedToEntity; // Paper - public -+ public java.util.UUID spawningEntity; // Paper - - public FireworkRocketEntity(EntityType type, Level world) { - super(type, world); -@@ -284,6 +285,11 @@ public class FireworkRocketEntity extends Projectile { - } - - tag.putBoolean("ShotAtAngle", (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE)); -+ // Paper start -+ if (this.spawningEntity != null) { -+ tag.setUUID("SpawningEntity", this.spawningEntity); -+ } -+ // Paper end - } - - @Override -@@ -300,7 +306,11 @@ public class FireworkRocketEntity extends Projectile { - if (tag.contains("ShotAtAngle")) { - this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, tag.getBoolean("ShotAtAngle")); - } -- -+ // Paper start -+ if (tag.hasUUID("SpawningEntity")) { -+ this.spawningEntity = tag.getUUID("SpawningEntity"); -+ } -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java -index 8a358872d3c8357775451e7dffe267cf9121f211..e1e58b7035e6dbafdad0a04cc5333464fc4febb8 100644 ---- a/src/main/java/net/minecraft/world/item/CrossbowItem.java -+++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java -@@ -205,6 +205,7 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { - - if (flag1) { - object = new FireworkRocketEntity(world, projectile, shooter, shooter.getX(), shooter.getEyeY() - 0.15000000596046448D, shooter.getZ(), true); -+ ((FireworkRocketEntity) object).spawningEntity = shooter.getUUID(); // Paper - } else { - object = getArrow(world, shooter, crossbow, projectile); - if (creative || simulated != 0.0F) { -diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -index d3a045fc99ef77fa0905aac7c73a2e84772c73cf..dba52063d402eb2371441fa244b730a3313444fc 100644 ---- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -+++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -@@ -27,6 +27,7 @@ public class FireworkRocketItem extends Item { - Vec3 vec3d = context.getClickLocation(); - Direction enumdirection = context.getClickedFace(); - FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, context.getPlayer(), vec3d.x + (double) enumdirection.getStepX() * 0.15D, vec3d.y + (double) enumdirection.getStepY() * 0.15D, vec3d.z + (double) enumdirection.getStepZ() * 0.15D, itemstack); -+ entityfireworks.spawningEntity = context.getPlayer().getUUID(); // Paper - - world.addFreshEntity(entityfireworks); - itemstack.shrink(1); -@@ -41,7 +42,11 @@ public class FireworkRocketItem extends Item { - ItemStack itemstack = user.getItemInHand(hand); - - if (!world.isClientSide) { -- world.addFreshEntity(new FireworkRocketEntity(world, itemstack, user)); -+ // Paper start -+ final FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, itemstack, user); -+ entityfireworks.spawningEntity = user.getUUID(); -+ world.addFreshEntity(entityfireworks); -+ // Paper end - if (!user.abilities.instabuild) { - itemstack.shrink(1); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -index 5901a53b25449430ed02a80b022f83755f83a440..0fbbdd6e3fda3f834d0b0d68d868dbff1aebb673 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -@@ -1,6 +1,7 @@ - package org.bukkit.craftbukkit.entity; - - import java.util.Random; -+import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.projectile.FireworkRocketEntity; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; -@@ -78,4 +79,17 @@ public class CraftFirework extends CraftProjectile implements Firework { - public void setShotAtAngle(boolean shotAtAngle) { - getHandle().getEntityData().set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, shotAtAngle); - } -+ -+ // Paper start -+ @Override -+ public java.util.UUID getSpawningEntity() { -+ return getHandle().spawningEntity; -+ } -+ -+ @Override -+ public org.bukkit.entity.LivingEntity getBoostedEntity() { -+ LivingEntity boostedEntity = getHandle().attachedToEntity; -+ return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null; -+ } -+ // Paper end - } diff --git a/patches/server-remapped/0136-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/server-remapped/0136-Provide-E-TE-Chunk-count-stat-methods.patch deleted file mode 100644 index 7b2dc85ab1..0000000000 --- a/patches/server-remapped/0136-Provide-E-TE-Chunk-count-stat-methods.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 15:24:46 -0500 -Subject: [PATCH] Provide E/TE/Chunk count stat methods - -Provides counts without the ineffeciency of using .getEntities().size() -which creates copy of the collections. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index ca189e5d160d2655175c9fab9366ff93bded2fee..6782888f7df4eea4e6378ee850424e14c5136afd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -264,6 +264,48 @@ public class CraftWorld implements World { - private int waterAmbientSpawn = -1; - private int ambientSpawn = -1; - -+ // Paper start - Provide fast information methods -+ public int getEntityCount() { -+ int ret = 0; -+ for (net.minecraft.world.entity.Entity entity : world.entitiesById.values()) { -+ if (entity.isChunkLoaded()) { -+ ++ret; -+ } -+ } -+ return ret; -+ } -+ public int getTileEntityCount() { -+ // We don't use the full world tile entity list, so we must iterate chunks -+ Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; -+ int size = 0; -+ for (ChunkHolder playerchunk : chunks.values()) { -+ net.minecraft.world.level.chunk.LevelChunk chunk = playerchunk.getTickingChunk(); -+ if (chunk == null) { -+ continue; -+ } -+ size += chunk.blockEntities.size(); -+ } -+ return size; -+ } -+ public int getTickableTileEntityCount() { -+ return world.tickableBlockEntities.size(); -+ } -+ public int getChunkCount() { -+ int ret = 0; -+ -+ for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { -+ if (chunkHolder.getTickingChunk() != null) { -+ ++ret; -+ } -+ } -+ -+ return ret; -+ } -+ public int getPlayerCount() { -+ return world.players.size(); -+ } -+ // Paper end -+ - private static final Random rand = new Random(); - - public CraftWorld(ServerLevel world, ChunkGenerator gen, Environment env) { diff --git a/patches/server-remapped/0142-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/patches/server-remapped/0142-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch deleted file mode 100644 index 740c39b430..0000000000 --- a/patches/server-remapped/0142-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 7 Feb 2017 16:55:35 -0600 -Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 175bf535066afc42de8a3f0d11c46af66f3e3e52..3b6f35b695117bd2b0c71b994efc55fa1084eddc 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -119,7 +119,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private final PlayerMap playerMap; - public final Int2ObjectMap entityMap; - private final Long2ByteMap chunkTypeCache; -- private final Queue unloadQueue; -+ private final Queue unloadQueue; private final Queue getUnloadQueueTasks() { return this.unloadQueue; } // Paper - OBFHELPER - private int viewDistance; - - // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() -@@ -177,7 +177,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.playerMap = new PlayerMap(); - this.entityMap = new Int2ObjectOpenHashMap(); - this.chunkTypeCache = new Long2ByteOpenHashMap(); -- this.unloadQueue = Queues.newConcurrentLinkedQueue(); -+ this.unloadQueue = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size() - this.structureManager = definedstructuremanager; - this.storageFolder = convertable_conversionsession.getDimensionPath(worldserver.dimension()); - this.level = worldserver; -@@ -435,7 +435,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Spigot start - org.spigotmc.SlackActivityAccountant activityAccountant = this.level.getServer().slackActivityAccountant; - activityAccountant.startActivity(0.5); -- int targetSize = (int) (this.toDrop.size() * UNLOAD_QUEUE_RESIZE_FACTOR); -+ int targetSize = Math.min(this.toDrop.size() - 100, (int) (this.toDrop.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive - // Spigot end - while (longiterator.hasNext()) { // Spigot - long j = longiterator.nextLong(); -@@ -457,7 +457,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - Runnable runnable; - -- while ((shouldKeepTicking.getAsBoolean() || this.unloadQueue.size() > 2000) && (runnable = (Runnable) this.unloadQueue.poll()) != null) { -+ int queueTarget = Math.min(this.getUnloadQueueTasks().size() - 100, (int) (this.getUnloadQueueTasks().size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well -+ while ((shouldKeepTicking.getAsBoolean() || this.getUnloadQueueTasks().size() > queueTarget) && (runnable = (Runnable)this.getUnloadQueueTasks().poll()) != null) { // Paper - Target this queue as well - runnable.run(); - } - diff --git a/patches/server-remapped/0143-Do-not-let-armorstands-drown.patch b/patches/server-remapped/0143-Do-not-let-armorstands-drown.patch deleted file mode 100644 index d8f5fab54d..0000000000 --- a/patches/server-remapped/0143-Do-not-let-armorstands-drown.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 18 Feb 2017 19:29:58 -0600 -Subject: [PATCH] Do not let armorstands drown - - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 3908f54e2216c635d47f8256bac455e7207a5bc6..c1786fcabeaee5732e9197db04268c5c4e164339 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -335,6 +335,7 @@ public abstract class LivingEntity extends Entity { - super.checkFallDamage(heightDifference, onGround, landedState, landedPosition); - } - -+ public boolean canBreatheUnderwater() { return this.canBreatheUnderwater(); } // Paper - OBFHELPER - public boolean canBreatheUnderwater() { - return this.getMobType() == MobType.UNDEAD; - } -@@ -378,7 +379,7 @@ public abstract class LivingEntity extends Entity { - - if (this.isAlive()) { - if (this.isEyeInFluid((Tag) FluidTags.WATER) && !this.level.getBlockState(new BlockPos(this.getX(), this.getEyeY(), this.getZ())).is(Blocks.BUBBLE_COLUMN)) { -- if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { -+ if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { // Paper - use OBFHELPER so it can be overridden - this.setAirSupply(this.decreaseAirSupply(this.getAirSupply())); - if (this.getAirSupply() == -20) { - this.setAirSupply(0); -diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 8b6ec9ddf0d47bf4369b247e764f75893ab15781..59239e202e8e99870ce3be515d2f040ad9786892 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -868,5 +868,10 @@ public class ArmorStand extends LivingEntity { - super.move(type, movement); - } - } -+ -+ @Override -+ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization -+ return true; -+ } - // Paper end - } diff --git a/patches/server-remapped/0132-Properly-fix-item-duplication-bug.patch b/patches/server/0122-Properly-fix-item-duplication-bug.patch similarity index 70% rename from patches/server-remapped/0132-Properly-fix-item-duplication-bug.patch rename to patches/server/0122-Properly-fix-item-duplication-bug.patch index aa2398aa87..8262c3fe06 100644 --- a/patches/server-remapped/0132-Properly-fix-item-duplication-bug.patch +++ b/patches/server/0122-Properly-fix-item-duplication-bug.patch @@ -6,25 +6,23 @@ 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 3cde25c2479adcc4ce3014e5ac2ec0710bffeea9..4ff66138fa43cf932b95d6d3dc050a9cd7b28ad4 100644 +index c60d42c835ed9a1bcc938aa1647c5266b87a05c5..1c4f3a1cfe808d59333e45c170caf0d760a709c9 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2066,8 +2066,8 @@ public class ServerPlayer extends Player implements ContainerListener { - } +@@ -2124,7 +2124,7 @@ public class ServerPlayer extends Player { @Override -- public boolean isImmobile() { -- return super.isImmobile() || !getBukkitEntity().isOnline(); -+ protected boolean isImmobile() { + public boolean isImmobile() { +- return super.isImmobile() || !this.getBukkitEntity().isOnline(); + return super.isImmobile() || (this.connection != null && this.connection.isDisconnected()); // Paper } @Override diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 1b92c669bbe69bcc07a554b7b43ee99bfebc1af4..ecc393ad94332ec2a59d29f30bd60bade4e1f18e 100644 +index b33ef48a4372dd8ac4a86bdd386a5a7d42583c72..624776a85a3e3268665571635f0b837cb810a62e 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2818,7 +2818,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2822,7 +2822,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } public final boolean isDisconnected() { diff --git a/patches/server/0123-Firework-API-s.patch b/patches/server/0123-Firework-API-s.patch new file mode 100644 index 0000000000..1b1127a6c4 --- /dev/null +++ b/patches/server/0123-Firework-API-s.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 28 Dec 2016 07:18:33 +0100 +Subject: [PATCH] Firework API's + + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +index 15ba8033dc7b5d533f29ab061b1db6dabfba560f..4cd6e5d62dcd319329d617e075aa3a61cdf01e0d 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +@@ -38,7 +38,8 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { + private int life; + public int lifetime; + @Nullable +- private LivingEntity attachedToEntity; ++ public LivingEntity attachedToEntity; // Paper - private -> public ++ public java.util.UUID spawningEntity; // Paper + + public FireworkRocketEntity(EntityType type, Level world) { + super(type, world); +@@ -315,6 +316,11 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { + } + + nbt.putBoolean("ShotAtAngle", (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE)); ++ // Paper start ++ if (this.spawningEntity != null) { ++ nbt.setUUID("SpawningEntity", this.spawningEntity); ++ } ++ // Paper end + } + + @Override +@@ -331,7 +337,11 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { + if (nbt.contains("ShotAtAngle")) { + this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, nbt.getBoolean("ShotAtAngle")); + } +- ++ // Paper start ++ if (nbt.hasUUID("SpawningEntity")) { ++ this.spawningEntity = nbt.getUUID("SpawningEntity"); ++ } ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java +index d336b44f9486ddc93b57938413d8dec4503710fa..35f3f3887c0696b757553af9a5997506c97b24c0 100644 +--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java ++++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java +@@ -222,6 +222,7 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + + if (flag1) { + object = new FireworkRocketEntity(world, projectile, shooter, shooter.getX(), shooter.getEyeY() - 0.15000000596046448D, shooter.getZ(), true); ++ ((FireworkRocketEntity) object).spawningEntity = shooter.getUUID(); // Paper + } else { + object = CrossbowItem.getArrow(world, shooter, crossbow, projectile); + if (creative || simulated != 0.0F) { +diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index 409b3c50b87cafba69259ab2232ef607bfce755a..10385dcb851bb435821afba322ed11f59e7ad3e6 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -46,6 +46,7 @@ public class FireworkRocketItem extends Item { + Vec3 vec3 = context.getClickLocation(); + Direction direction = context.getClickedFace(); + FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(level, context.getPlayer(), vec3.x + (double)direction.getStepX() * 0.15D, vec3.y + (double)direction.getStepY() * 0.15D, vec3.z + (double)direction.getStepZ() * 0.15D, itemStack); ++ fireworkRocketEntity.spawningEntity = context.getPlayer() == null ? null : context.getPlayer().getUUID(); // Paper + level.addFreshEntity(fireworkRocketEntity); + itemStack.shrink(1); + } +@@ -59,6 +60,7 @@ public class FireworkRocketItem extends Item { + ItemStack itemStack = user.getItemInHand(hand); + if (!world.isClientSide) { + FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(world, itemStack, user); ++ fireworkRocketEntity.spawningEntity = user.getUUID(); // Paper + world.addFreshEntity(fireworkRocketEntity); + if (!user.getAbilities().instabuild) { + itemStack.shrink(1); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +index 3a1c3d20ecc3612421e346edbbb74ab47f16a137..be86114eac3975b82ca74d4d6ed3f0402a642e8a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +@@ -78,4 +78,17 @@ public class CraftFirework extends CraftProjectile implements Firework { + public void setShotAtAngle(boolean shotAtAngle) { + this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, shotAtAngle); + } ++ ++ // Paper start ++ @Override ++ public java.util.UUID getSpawningEntity() { ++ return getHandle().spawningEntity; ++ } ++ ++ @Override ++ public org.bukkit.entity.LivingEntity getBoostedEntity() { ++ net.minecraft.world.entity.LivingEntity boostedEntity = getHandle().attachedToEntity; ++ return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null; ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0135-PlayerTeleportEndGatewayEvent.patch b/patches/server/0124-PlayerTeleportEndGatewayEvent.patch similarity index 80% rename from patches/server-remapped/0135-PlayerTeleportEndGatewayEvent.patch rename to patches/server/0124-PlayerTeleportEndGatewayEvent.patch index 98fb21f40b..99e4760063 100644 --- a/patches/server-remapped/0135-PlayerTeleportEndGatewayEvent.patch +++ b/patches/server/0124-PlayerTeleportEndGatewayEvent.patch @@ -6,10 +6,10 @@ Subject: [PATCH] PlayerTeleportEndGatewayEvent Allows you to access the Gateway being used in a teleport event diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -index 07d89af8111673087b0534ca9fac043d3e89662b..2c974f9801d209907733bed8e6c4c9ef46e2b610 100644 +index cf57c89db3082edf22bad89a3e2f1974f682aaa6..2bf65c8da827c6bdbfb74a9d8ee5754584c40c53 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -@@ -10,6 +10,7 @@ import net.minecraft.data.worldgen.Features; +@@ -11,6 +11,7 @@ import net.minecraft.data.worldgen.Features; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; @@ -17,12 +17,12 @@ index 07d89af8111673087b0534ca9fac043d3e89662b..2c974f9801d209907733bed8e6c4c9ef import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; -@@ -177,7 +178,7 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements +@@ -211,7 +212,7 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { location.setPitch(player.getLocation().getPitch()); location.setYaw(player.getLocation().getYaw()); - PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); -+ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(level, this.getBlockPos()).getBlock())); // Paper ++ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(net.minecraft.server.MCUtil.toLocation(worldserver, blockEntity.getBlockPos()).getBlock())); // Paper Bukkit.getPluginManager().callEvent(teleEvent); if (teleEvent.isCancelled()) { return; diff --git a/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch new file mode 100644 index 0000000000..dacafbaa5b --- /dev/null +++ b/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 Jan 2017 15:24:46 -0500 +Subject: [PATCH] Provide E/TE/Chunk count stat methods + +Provides counts without the ineffeciency of using .getEntities().size() +which creates copy of the collections. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 8323ddb363f49d266dd95f11241a30a9a27250aa..2cd34f326f374e3ad46a4eea8c84be326cd489a0 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -173,7 +173,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public static final BlockPos END_SPAWN_POINT = new BlockPos(100, 50, 0); + private static final Logger LOGGER = LogManager.getLogger(); + private static final int EMPTY_TIME_NO_TICK = 300; +- final List players; ++ final List players; public final int getPlayerListSize() { return this.players.size(); } // Paper + public final ServerChunkCache chunkSource; // Paper - public + private final MinecraftServer server; + public final PrimaryLevelData serverLevelData; // CraftBukkit - type +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 52d80086deff664fcfd8952b7cabbfa1f48ad131..a86b5272c0ac4dd64f796f7fd025c7a34a5d2f8d 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -110,7 +110,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public static final int TICKS_PER_DAY = 24000; + public static final int MAX_ENTITY_SPAWN_Y = 20000000; + public static final int MIN_ENTITY_SPAWN_Y = -20000000; +- protected final List blockEntityTickers = Lists.newArrayList(); ++ protected final List blockEntityTickers = Lists.newArrayList(); public final int getTotalTileEntityTickers() { return this.blockEntityTickers.size(); } // Paper + private final List pendingBlockEntityTickers = Lists.newArrayList(); + private boolean tickingBlockEntities; + public final Thread thread; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 5133febf4b3a83b2870fee2f9e45b1d12894df54..e11a1a21bff1fc5e730d6c63c5b0c623b3b2e037 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -270,6 +270,57 @@ public class CraftWorld implements World { + private int waterAmbientSpawn = -1; + private int ambientSpawn = -1; + ++ // Paper start - Provide fast information methods ++ @Override ++ public int getEntityCount() { ++ int ret = 0; ++ for (net.minecraft.world.entity.Entity entity : world.getEntities().getAll()) { ++ if (entity.isChunkLoaded()) { ++ ++ret; ++ } ++ } ++ return ret; ++ } ++ ++ @Override ++ public int getTileEntityCount() { ++ // We don't use the full world tile entity list, so we must iterate chunks ++ Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; ++ int size = 0; ++ for (ChunkHolder playerchunk : chunks.values()) { ++ net.minecraft.world.level.chunk.LevelChunk chunk = playerchunk.getTickingChunk(); ++ if (chunk == null) { ++ continue; ++ } ++ size += chunk.blockEntities.size(); ++ } ++ return size; ++ } ++ ++ @Override ++ public int getTickableTileEntityCount() { ++ return world.getTotalTileEntityTickers(); ++ } ++ ++ @Override ++ public int getChunkCount() { ++ int ret = 0; ++ ++ for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { ++ if (chunkHolder.getTickingChunk() != null) { ++ ++ret; ++ } ++ } ++ ++ return ret; ++ } ++ ++ @Override ++ public int getPlayerCount() { ++ return world.getPlayerListSize(); ++ } ++ // Paper end ++ + private static final Random rand = new Random(); + + public CraftWorld(ServerLevel world, ChunkGenerator gen, Environment env) { diff --git a/patches/server-remapped/0137-Enforce-Sync-Player-Saves.patch b/patches/server/0126-Enforce-Sync-Player-Saves.patch similarity index 75% rename from patches/server-remapped/0137-Enforce-Sync-Player-Saves.patch rename to patches/server/0126-Enforce-Sync-Player-Saves.patch index 09ab2be15a..5b8d18bd8c 100644 --- a/patches/server-remapped/0137-Enforce-Sync-Player-Saves.patch +++ b/patches/server/0126-Enforce-Sync-Player-Saves.patch @@ -7,18 +7,18 @@ Saving players async is extremely dangerous. This will force it to main the same way we handle async chunk loads. diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 59fb19cfebe4f488fd02f02db31029d44b65e408..cebf536e9d16d44c4b2a91b5b4be053cd7f44045 100644 +index b9c4428bc9653e81ed046bda94e248218c1fa9c9..3eaf106f8f17288857ce1a149d0366cf04235307 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1043,11 +1043,13 @@ public abstract class PlayerList { +@@ -1027,11 +1027,13 @@ public abstract class PlayerList { } public void saveAll() { -+ MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main ++ net.minecraft.server.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main MinecraftTimings.savePlayers.startTiming(); // Paper for (int i = 0; i < this.players.size(); ++i) { - this.save((ServerPlayer) this.players.get(i)); -+ this.savePlayerFile((EntityPlayer) this.players.get(i)); ++ this.save(this.players.get(i)); } MinecraftTimings.savePlayers.stopTiming(); // Paper + return null; }); // Paper - ensure main diff --git a/patches/server-remapped/0138-Don-t-allow-entities-to-ride-themselves-572.patch b/patches/server/0127-Don-t-allow-entities-to-ride-themselves-572.patch similarity index 80% rename from patches/server-remapped/0138-Don-t-allow-entities-to-ride-themselves-572.patch rename to patches/server/0127-Don-t-allow-entities-to-ride-themselves-572.patch index da9f57d585..bd141e95f7 100644 --- a/patches/server-remapped/0138-Don-t-allow-entities-to-ride-themselves-572.patch +++ b/patches/server/0127-Don-t-allow-entities-to-ride-themselves-572.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Don't allow entities to ride themselves - #572 diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c3aece8e5001828edea304b2a8377e9a28b34cfe..a9ed1c3ce6361a86dd58501f5b0ce5d6bbfb8adf 100644 +index 416dd12638540312aa48b530e24ba3ad7ab6079c..ee0efcc86fba880472a6f26f3133d2354a56bf5f 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2045,6 +2045,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2219,6 +2219,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } protected boolean addPassenger(Entity entity) { // CraftBukkit diff --git a/patches/server-remapped/0139-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch similarity index 59% rename from patches/server-remapped/0139-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch rename to patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch index 44aa5bf7e5..d3d79693ea 100644 --- a/patches/server-remapped/0139-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch +++ b/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch @@ -8,26 +8,26 @@ Adds lots of information about why this orb exists. Replaces isFromBottle() with logic that persists entity reloads too. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index ed4309d5e567b20fd4aa025e7c82d8943bf1d8e1..26ce794cb8d089c03fab5dd0a0c910783d10b72e 100644 +index f0462770e5e56b28d734f5d097d95de8faee8bbf..9d303a962950c7464d1d4a2a0ce3f658628cc785 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -409,7 +409,7 @@ public class ServerPlayerGameMode { +@@ -406,7 +406,7 @@ public class ServerPlayerGameMode { // Drop event experience if (flag && event != null) { - iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop()); -+ iblockdata.getBlock().dropExperience(this.level, pos, event.getExpToDrop(), this.player); // Paper ++ iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop(), this.player); // Paper } return true; diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index f932fc4f8240b48f8e518af05d1521bc8ff9cbee..3ddb0a9f15c920c9a2080f76edfda0504c1e287a 100644 +index 1953739fd2ead7680273ef63d8506e546758dc9b..337e861a8b1a89b73560601b704c18dcf446a144 100644 --- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -30,13 +30,63 @@ public class ExperienceOrb extends Entity { +@@ -38,13 +38,63 @@ public class ExperienceOrb extends Entity { public int value; + private int count; private Player followingPlayer; - private int followingTime; + // Paper start + public java.util.UUID sourceEntityId; + public java.util.UUID triggerEntityId; @@ -71,11 +71,11 @@ index f932fc4f8240b48f8e518af05d1521bc8ff9cbee..3ddb0a9f15c920c9a2080f76edfda050 + this(world, x, y, z, amount, null, null); + } + -+ public EntityExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { ++ public ExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { + this(world, d0, d1, d2, i, reason, triggerId, null); + } + -+ public EntityExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { ++ public ExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { this(EntityType.EXPERIENCE_ORB, world); - this.setPos(x, y, z); + this.sourceEntityId = sourceId != null ? sourceId.getUUID() : null; @@ -83,61 +83,83 @@ index f932fc4f8240b48f8e518af05d1521bc8ff9cbee..3ddb0a9f15c920c9a2080f76edfda050 + this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; + // Paper end + this.setPos(d0, d1, d2); - this.yRot = (float) (this.random.nextDouble() * 360.0D); + this.setYRot((float) (this.random.nextDouble() * 360.0D)); this.setDeltaMovement((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D); - this.value = amount; + this.value = i; } public ExperienceOrb(EntityType type, Level world) { -@@ -167,6 +217,7 @@ public class ExperienceOrb extends Entity { - tag.putShort("Health", (short) this.health); - tag.putShort("Age", (short) this.age); - tag.putShort("Value", (short) this.value); -+ this.savePaperNBT(tag); // Paper +@@ -154,12 +204,20 @@ public class ExperienceOrb extends Entity { + } + + public static void award(ServerLevel world, Vec3 pos, int amount) { ++ // Paper start - add reasons for orbs ++ award(world, pos, amount, null, null, null); ++ } ++ public static void award(ServerLevel world, Vec3 pos, int amount, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { ++ award(world, pos, amount, reason, triggerId, null); ++ } ++ public static void award(ServerLevel world, Vec3 pos, int amount, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { ++ // Paper end - add reasons for orbs + while (amount > 0) { + int j = ExperienceOrb.getExperienceValue(amount); + + amount -= j; + if (!ExperienceOrb.tryMergeToExisting(world, pos, j)) { +- world.addFreshEntity(new ExperienceOrb(world, pos.x(), pos.y(), pos.z(), j)); ++ world.addFreshEntity(new ExperienceOrb(world, pos.x(), pos.y(), pos.z(), j, reason, triggerId, sourceId)); // Paper - add reason + } + } + +@@ -230,6 +288,7 @@ public class ExperienceOrb extends Entity { + nbt.putShort("Age", (short) this.age); + nbt.putShort("Value", (short) this.value); + nbt.putInt("Count", this.count); ++ this.savePaperNBT(nbt); // Paper } @Override -@@ -174,6 +225,7 @@ public class ExperienceOrb extends Entity { - this.health = tag.getShort("Health"); - this.age = tag.getShort("Age"); - this.value = tag.getShort("Value"); -+ this.loadPaperNBT(tag); // Paper +@@ -238,6 +297,7 @@ public class ExperienceOrb extends Entity { + this.age = nbt.getShort("Age"); + this.value = nbt.getShort("Value"); + this.count = Math.max(nbt.getInt("Count"), 1); ++ this.loadPaperNBT(nbt); // Paper } @Override diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 1131d86080b3100437aa18a00c6277fcea4b7ea8..c6aa5328907f85cd210b1c20ff407e60d9b03349 100644 +index 041a61e037e7f6fddd94567f2954be600c737811..971e4c6d742e0c63b3c5dfa6d87b2468f8ce5010 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1591,7 +1591,8 @@ public abstract class LivingEntity extends Entity { - int j = ExperienceOrb.getExperienceValue(i); - - i -= j; -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); -+ LivingEntity attacker = lastHurtByPlayer != null ? lastHurtByPlayer : lastHurtByMob; // Paper -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this)); // Paper - } +@@ -1699,7 +1699,8 @@ public abstract class LivingEntity extends Entity { + protected void dropExperience() { + // CraftBukkit start - Update getExpReward() above if the removed if() changes! + if (true) { +- ExperienceOrb.award((ServerLevel) this.level, this.position(), this.expToDrop); ++ LivingEntity attacker = this.lastHurtByPlayer != null ? this.lastHurtByPlayer : this.lastHurtByMob; // Paper ++ ExperienceOrb.award((ServerLevel) this.level, this.position(), this.expToDrop, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this); // Paper this.expToDrop = 0; } + // 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 ab2a19554aa1541e924104a70364f957ff8b33f9..e0f2a70870ff97ae2e8f216a202787bbcba6c6a9 100644 +index b8163a04f5aad326e78416b270dc64ffc913ccc5..5a503a255b4e7e684a8f42d8190430397ca81683 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Animal.java +++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java -@@ -260,7 +260,7 @@ public abstract class Animal extends AgableMob { - if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +@@ -264,7 +264,7 @@ public abstract class Animal extends AgeableMob { + if (world.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // CraftBukkit start - use event experience if (experience > 0) { -- worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience)); -+ worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper +- world.addFreshEntity(new ExperienceOrb(world, this.getX(), this.getY(), this.getZ(), experience)); ++ world.addFreshEntity(new ExperienceOrb(world, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper } // CraftBukkit end } diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java -index 83fcfd888a335e3c054174e1f55e92fea878f7ab..c2d98222f575d7383e4c040730f6d531bdb0d7b6 100644 +index 0fd1dfacca88cd5399e05cb7ebc0150491e8f59c..c1cdb1905536bda76f34ad3fc796996443839767 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Fox.java +++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java -@@ -1306,7 +1306,7 @@ public class Fox extends Animal { +@@ -883,7 +883,7 @@ public class Fox extends Animal { if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // CraftBukkit start - use event experience if (experience > 0) { @@ -147,10 +169,10 @@ index 83fcfd888a335e3c054174e1f55e92fea878f7ab..c2d98222f575d7383e4c040730f6d531 // CraftBukkit end } diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index 2ae59200ed67ab68645b569ba03839e8cedc9aa8..c54f4b83b9f2fdb15ddb363be0a179a05eb3693b 100644 +index 593442f0f2d58e2e0a0a86d6f16aea90cc36d184..b782d278463a72b8514719e9b14986f268828772 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java +++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -@@ -561,7 +561,7 @@ public class Turtle extends Animal { +@@ -455,7 +455,7 @@ public class Turtle extends Animal { Random random = this.animal.getRandom(); if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { @@ -160,23 +182,32 @@ index 2ae59200ed67ab68645b569ba03839e8cedc9aa8..c54f4b83b9f2fdb15ddb363be0a179a0 } diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index 39298b69918da890c3faa516f80d1a69adb88fe2..ae3cf71f14526e1f356216dfaa899c8f5083d46d 100644 +index 9d6d8bf5f38ec11f26665ae676c46e4ef089670b..e286d4ed03eba05b862741cb98db8a031224cd98 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -661,7 +661,7 @@ public class EnderDragon extends Mob implements Enemy { - int j = ExperienceOrb.getExperienceValue(amount); +@@ -634,7 +634,7 @@ public class EnderDragon extends Mob implements Enemy { - amount -= j; -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this)); // Paper - } + if (this.level instanceof ServerLevel) { + if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && flag) { +- ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.08F)); ++ ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.08F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this); // Paper + } - } + if (this.dragonDeathTime == 1 && !this.isSilent()) { +@@ -665,7 +665,7 @@ public class EnderDragon extends Mob implements Enemy { + this.yBodyRot = this.getYRot(); + if (this.dragonDeathTime == 200 && this.level instanceof ServerLevel) { + if (flag) { +- ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.2F)); ++ ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.2F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this); // Paper + } + + if (this.dragonFight != null) { diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 5648a4a4d8511ac8c46c61245a7ff83753a3e51f..a66fab2e04a5d87ced139ed15d2434c5ffcec695 100644 +index 731aea63eedb8cb37291bb2238ff8ab2e3a5f6eb..6a9e2105b2d9a4ee83c0a2516d5ef26dc3b99053 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -599,7 +599,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -616,7 +616,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } if (offer.shouldRewardExp()) { @@ -186,10 +217,10 @@ index 5648a4a4d8511ac8c46c61245a7ff83753a3e51f..a66fab2e04a5d87ced139ed15d2434c5 } diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -index 15570b9ba2443ce8c6f48dfbc13cdf45de8b45ac..69d92590d265abe8a04d8bf48bbe9a6ae606ae50 100644 +index 892603dabb17e77ac0b038617f00f2d3d1c728ac..59c4ab697ef0a336ffce19d215952f3a8ff0852b 100644 --- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -@@ -188,7 +188,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -187,7 +187,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill if (offer.shouldRewardExp()) { int i = 3 + this.random.nextInt(4); @@ -199,10 +230,10 @@ index 15570b9ba2443ce8c6f48dfbc13cdf45de8b45ac..69d92590d265abe8a04d8bf48bbe9a6a } diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -index fa078167dd9e0cae80516549eef0e554c13938a3..7bff012f3cd4458673ee02e5f5f830fc0ef983a3 100644 +index d25fe9cb2cf755f3e34a79ce87ed38c1ffada53f..0258d0699afe7ceec19154c669b10298e6e1bf95 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -@@ -500,7 +500,7 @@ public class FishingHook extends Projectile { +@@ -516,7 +516,7 @@ public class FishingHook extends Projectile { this.level.addFreshEntity(entityitem); // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() if (playerFishEvent.getExpToDrop() > 0) { @@ -210,25 +241,25 @@ index fa078167dd9e0cae80516549eef0e554c13938a3..7bff012f3cd4458673ee02e5f5f830fc + entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper } // CraftBukkit end - if (itemstack1.getItem().is((Tag) ItemTags.FISHES)) { + if (itemstack1.is((Tag) ItemTags.FISHES)) { diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java -index 85b8f8f52c5035054ad9f665fce735260a54c270..42c7371355b6e36e31daf055317f015240761b8b 100644 +index 467f9814e0991d31bff7259f266262c81328f05f..11d1db5ef709dfb6fa596ebc4f5fff1415ad4f6d 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java +++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java -@@ -54,7 +54,7 @@ public class ThrownExperienceBottle extends ThrowableItemProjectile { - int j = ExperienceOrb.getExperienceValue(i); - - i -= j; -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, getOwner(), this)); // Paper +@@ -51,7 +51,7 @@ public class ThrownExperienceBottle extends ThrowableItemProjectile { } + // CraftBukkit end + +- ExperienceOrb.award((ServerLevel) this.level, this.position(), i); ++ ExperienceOrb.award((ServerLevel) this.level, this.position(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, this.getOwner(), this); // Paper + this.discard(); + } - this.remove(); diff --git a/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java b/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java -index ea6e1a96bd1fa9fbb87f65a169aa1e5af0589f34..5b9111d502bc12ab9e5c37e4d66c21aa37007b53 100644 +index d486b8d7d80bc79c5af6106de56a3ba49021258e..6f26688347ff2c206ab0b3ccae30b95ee7475fa2 100644 --- a/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java +++ b/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java -@@ -7,7 +7,7 @@ import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; +@@ -8,7 +8,7 @@ import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; public class FurnaceResultSlot extends Slot { @@ -238,81 +269,69 @@ index ea6e1a96bd1fa9fbb87f65a169aa1e5af0589f34..5b9111d502bc12ab9e5c37e4d66c21aa public FurnaceResultSlot(Player player, Container inventory, int index, int x, int y) { diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -index e8bc37e1f7aebd192f048d7b056a41c50ceef9f5..e9e830117fe3e4e02a51eef8671a3d3b48c2858e 100644 +index 473e17d87637cd1a85880e2956f83de0b510b488..34574f3945d2a7b4ab6a71adb2408b9811a3cb0d 100644 --- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -@@ -93,7 +93,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { - int k = ExperienceOrb.getExperienceValue(j); - - j -= k; -- world.addFreshEntity(new ExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k)); -+ world.addFreshEntity(new ExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k, org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player)); // Paper +@@ -98,7 +98,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { + public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { + context.execute((world, blockposition) -> { + if (world instanceof ServerLevel) { +- ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf((Vec3i) blockposition), this.getExperienceAmount(world)); ++ ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf((Vec3i) blockposition), this.getExperienceAmount(world), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player); // Paper } world.levelEvent(1042, blockposition, 0); diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 2ae786b8fc6da19ca2a40252b0606f9e06d31ded..9d2e4adddae481735053c64eec0ee7259c61f1a4 100644 +index c27e755f93a2b2e203b305e0cae2c782a34e38cc..27016f964d2f6458298a9052d031a44b3d9f5f4b 100644 --- a/src/main/java/net/minecraft/world/level/block/Block.java +++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -267,13 +267,13 @@ public class Block extends BlockBehaviour implements ItemLike { - } +@@ -374,8 +374,13 @@ public class Block extends BlockBehaviour implements ItemLike { } -- public void popExperience(ServerLevel world, BlockPos pos, int size) { -- if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { -- while (size > 0) { -- int j = ExperienceOrb.getExperienceValue(size); -+ public void dropExperience(ServerLevel worldserver, BlockPos blockposition, int i, net.minecraft.server.level.ServerPlayer player) { // Paper -+ if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { -+ while (i > 0) { -+ int j = ExperienceOrb.getExperienceValue(i); - -- size -= j; -- world.addFreshEntity(new ExperienceOrb(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, j)); -+ i -= j; -+ worldserver.addFreshEntity(new ExperienceOrb(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player)); // Paper - } + public void popExperience(ServerLevel world, BlockPos pos, int size) { ++ // Paper start - add player parameter ++ popExperience(world, pos, size, null); ++ } ++ public void popExperience(ServerLevel world, BlockPos pos, int size, net.minecraft.server.level.ServerPlayer player) { ++ // Paper end - add player parameter + if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { +- ExperienceOrb.award(world, Vec3.atCenterOf((Vec3i) pos), size); ++ ExperienceOrb.award(world, Vec3.atCenterOf((Vec3i) pos), size, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player); // Paper } + } diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 7a2554c5cd18e0c5e482ba8ba68a098d533b6a4f..8c55c1d88ef2e20e82bcdae0b9b3d381e562051f 100644 +index 11ed01b3ebe4c71e3d3c767887a5dca6033fdf3c..52b2b27f8f8b542a930d649ed6904b4bf808906c 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -601,7 +601,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - int k = ExperienceOrb.getExperienceValue(j); - - j -= k; -- world.addFreshEntity(new ExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k)); -+ world.addFreshEntity(new ExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman)); // Paper +@@ -606,7 +606,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit } + // CraftBukkit end +- ExperienceOrb.award(worldserver, vec3d, j); ++ ExperienceOrb.award(worldserver, vec3d, j, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman); // Paper } + + @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 6782888f7df4eea4e6378ee850424e14c5136afd..88658d4deacc29128c537e2e02fdc8f684090a2c 100644 +index e11a1a21bff1fc5e730d6c63c5b0c623b3b2e037..e396450366ebee663dd5ad5f59e5d6bccece0679 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1817,7 +1817,7 @@ public class CraftWorld implements World { +@@ -1836,7 +1836,7 @@ public class CraftWorld implements World { } else if (TNTPrimed.class.isAssignableFrom(clazz)) { - entity = new PrimedTnt(world, x, y, z, null); + entity = new PrimedTnt(this.world, x, y, z, null); } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { -- entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0); -+ entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper +- entity = new net.minecraft.world.entity.ExperienceOrb(this.world, x, y, z, 0); ++ entity = new net.minecraft.world.entity.ExperienceOrb(this.world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper } else if (LightningStrike.class.isAssignableFrom(clazz)) { entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(world); } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -index 3b450d97302bab30cdb975c8332b81318470503e..d5b8fd76ec3bd7d2621231480eb3e694a90aa037 100644 +index 40713228b149b4532fcee3a54bbe63e161318258..84899284703baeb04bfc79251941265d52ac07e8 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import SpawnReason; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.ExperienceOrb; -@@ -19,6 +20,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { - getHandle().value = value; +@@ -19,6 +19,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { + this.getHandle().value = value; } + // Paper start diff --git a/patches/server-remapped/0140-Cap-Entity-Collisions.patch b/patches/server/0129-Cap-Entity-Collisions.patch similarity index 78% rename from patches/server-remapped/0140-Cap-Entity-Collisions.patch rename to patches/server/0129-Cap-Entity-Collisions.patch index 7b28bfe328..60e8f97038 100644 --- a/patches/server-remapped/0140-Cap-Entity-Collisions.patch +++ b/patches/server/0129-Cap-Entity-Collisions.patch @@ -27,10 +27,10 @@ index 2dc58b9f769ea43b737804456aafab47ecc143b8..c611b5a63498f5ad1f50a75ccd5d7299 + } } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a9ed1c3ce6361a86dd58501f5b0ce5d6bbfb8adf..a017fa55002d6674124befa3f6e81eb70c9ce8f7 100644 +index ee0efcc86fba880472a6f26f3133d2354a56bf5f..0204bde9802429aca5470c235cb10232e5c8f58a 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -267,6 +267,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -301,6 +301,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); public final boolean defaultActivationState; public long activatedTick = Integer.MIN_VALUE; @@ -39,19 +39,19 @@ index a9ed1c3ce6361a86dd58501f5b0ce5d6bbfb8adf..a017fa55002d6674124befa3f6e81eb7 // Spigot end diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index c6aa5328907f85cd210b1c20ff407e60d9b03349..3908f54e2216c635d47f8256bac455e7207a5bc6 100644 +index 971e4c6d742e0c63b3c5dfa6d87b2468f8ce5010..f0357f9d7b6a39bbdf6486a9d35d890942cc5e4c 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2900,8 +2900,11 @@ public abstract class LivingEntity extends Entity { +@@ -3224,8 +3224,11 @@ public abstract class LivingEntity extends Entity { } } - for (j = 0; j < list.size(); ++j) { -+ numCollisions = Math.max(0, numCollisions - level.paperConfig.maxCollisionsPerEntity); // Paper -+ for (j = 0; j < list.size() && numCollisions < level.paperConfig.maxCollisionsPerEntity; ++j) { // Paper ++ this.numCollisions = Math.max(0, this.numCollisions - this.level.paperConfig.maxCollisionsPerEntity); // Paper ++ for (j = 0; j < list.size() && this.numCollisions < this.level.paperConfig.maxCollisionsPerEntity; ++j) { // Paper Entity entity = (Entity) list.get(j); + entity.numCollisions++; // Paper -+ numCollisions++; // Paper ++ this.numCollisions++; // Paper this.doPush(entity); } diff --git a/patches/server-remapped/0141-Remove-CraftScheduler-Async-Task-Debugger.patch b/patches/server/0130-Remove-CraftScheduler-Async-Task-Debugger.patch similarity index 62% rename from patches/server-remapped/0141-Remove-CraftScheduler-Async-Task-Debugger.patch rename to patches/server/0130-Remove-CraftScheduler-Async-Task-Debugger.patch index db58842a96..7ce11b5799 100644 --- a/patches/server-remapped/0141-Remove-CraftScheduler-Async-Task-Debugger.patch +++ b/patches/server/0130-Remove-CraftScheduler-Async-Task-Debugger.patch @@ -9,24 +9,24 @@ One report of a suspected memory leak with the system. This adds additional overhead to asynchronous task dispatching diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 9b6d9373abb59a30c2835ca891282d07559281f5..0e0f361c3af363539d5d1d865603114bdb84fd67 100644 +index 0735c2fe139ce8d47a04fdba045fe462492723eb..6435d53dcddc1a43420f1ea66fa08e154b82586d 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java @@ -430,7 +430,7 @@ public class CraftScheduler implements BukkitScheduler { } - parsePending(); + this.parsePending(); } else { -- debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); -+ //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper - executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper +- this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); ++ //this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper + this.executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper // We don't need to parse pending // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) @@ -447,7 +447,7 @@ public class CraftScheduler implements BukkitScheduler { - pending.addAll(temp); + this.pending.addAll(temp); temp.clear(); - MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); -- debugHead = debugHead.getNextHead(currentTick); -+ //debugHead = debugHead.getNextHead(currentTick); // Paper + MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); // Paper +- this.debugHead = this.debugHead.getNextHead(currentTick); ++ //this.debugHead = this.debugHead.getNextHead(currentTick); // Paper } private void addTask(final CraftTask task) { @@ -37,9 +37,9 @@ index 9b6d9373abb59a30c2835ca891282d07559281f5..0e0f361c3af363539d5d1d865603114b + // Paper start + return ""; + /* - int debugTick = currentTick; - StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - RECENT_TICKS).append('-').append(debugTick).append('{'); - debugHead.debugTo(string); + int debugTick = this.currentTick; + StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - CraftScheduler.RECENT_TICKS).append('-').append(debugTick).append('{'); + this.debugHead.debugTo(string); return string.append('}').toString(); + */ + // Paper end diff --git a/patches/server/0131-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/patches/server/0131-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch new file mode 100644 index 0000000000..091d6d3c36 --- /dev/null +++ b/patches/server/0131-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Tue, 7 Feb 2017 16:55:35 -0600 +Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index da97afe93a98daac33f143c6da0b42f71db25dba..5a80ea6bee72921454fbbd6ee202dc114c481ea1 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -185,7 +185,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerMap = new PlayerMap(); + this.entityMap = new Int2ObjectOpenHashMap(); + this.chunkTypeCache = new Long2ByteOpenHashMap(); +- this.unloadQueue = Queues.newConcurrentLinkedQueue(); ++ this.unloadQueue = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size() + this.structureManager = structureManager; + this.storageFolder = session.getDimensionPath(world.dimension()); + this.level = world; +@@ -478,7 +478,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Spigot start + org.spigotmc.SlackActivityAccountant activityAccountant = this.level.getServer().slackActivityAccountant; + activityAccountant.startActivity(0.5); +- int targetSize = (int) (this.toDrop.size() * ChunkMap.UNLOAD_QUEUE_RESIZE_FACTOR); ++ int targetSize = Math.min(this.toDrop.size() - 100, (int) (this.toDrop.size() * ChunkMap.UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive + // Spigot end + while (longiterator.hasNext()) { // Spigot + long j = longiterator.nextLong(); +@@ -500,7 +500,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + Runnable runnable; + +- while ((shouldKeepTicking.getAsBoolean() || this.unloadQueue.size() > 2000) && (runnable = (Runnable) this.unloadQueue.poll()) != null) { ++ int queueTarget = Math.min(this.unloadQueue.size() - 100, (int) (this.unloadQueue.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well ++ while ((shouldKeepTicking.getAsBoolean() || this.unloadQueue.size() > queueTarget) && (runnable = (Runnable)this.unloadQueue.poll()) != null) { // Paper - Target this queue as well + runnable.run(); + } + diff --git a/patches/server/0132-Do-not-let-armorstands-drown.patch b/patches/server/0132-Do-not-let-armorstands-drown.patch new file mode 100644 index 0000000000..466f346419 --- /dev/null +++ b/patches/server/0132-Do-not-let-armorstands-drown.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 18 Feb 2017 19:29:58 -0600 +Subject: [PATCH] Do not let armorstands drown + + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index ef382aaeb86ca41356a076ff4adfe5fb652b43c5..cda073a8ab9daed75f284cbbe4459991fba348f0 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -936,5 +936,12 @@ public class ArmorStand extends LivingEntity { + super.move(type, movement); + } + } ++ ++ // Paper start ++ @Override ++ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization ++ return true; ++ } ++ // Paper end + // Paper end + } diff --git a/patches/server-remapped/0144-Properly-handle-async-calls-to-restart-the-server.patch b/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch similarity index 88% rename from patches/server-remapped/0144-Properly-handle-async-calls-to-restart-the-server.patch rename to patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch index 761e1f8b83..71da2cb2bf 100644 --- a/patches/server-remapped/0144-Properly-handle-async-calls-to-restart-the-server.patch +++ b/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch @@ -30,10 +30,10 @@ will have plugins and worlds saving to the disk has a high potential to result in corruption/dataloss. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 211251fe7cd08074c040df2f4642f37d5f90d856..f41d79c6630fd8daae28476ffc854f7e65d841e6 100644 +index 74073d3f8c9dda6f10e9fb34071dae079b73fb24..1617c59bf689e5f67c2af5c3a22ce5791d47b408 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -199,6 +199,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop, ServerLevel> levels; private PlayerList playerList; private volatile boolean running; @@ -41,67 +41,50 @@ index 211251fe7cd08074c040df2f4642f37d5f90d856..f41d79c6630fd8daae28476ffc854f7e private boolean stopped; private int tickCount; protected final Proxy proxy; -@@ -858,7 +859,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop Date: Sat, 12 Jun 2021 02:17:20 -0700 Subject: [PATCH 041/226] even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even more work --- ...rldBorder-isInBounds-Location-check.patch} | 0 ...-option-to-prevent-player-names-fro.patch} | 4 +-- ...roperty-to-disable-book-size-limits.patch} | 22 +++++++------- ...e-parrots-stay-on-shoulders-despite.patch} | 29 ++++++++++++------- ...-option-to-prevent-player-names-fro.patch} | 4 +-- 5 files changed, 34 insertions(+), 25 deletions(-) rename patches/{api-unmapped/0049-Expose-WorldBorder-isInBounds-Location-check.patch => api/0050-Expose-WorldBorder-isInBounds-Location-check.patch} (100%) rename patches/{api-unmapped/0050-Add-configuration-option-to-prevent-player-names-fro.patch => api/0051-Add-configuration-option-to-prevent-player-names-fro.patch} (92%) rename patches/{server-remapped/0145-Add-system-property-to-disable-book-size-limits.patch => server/0134-Add-system-property-to-disable-book-size-limits.patch} (66%) rename patches/{server-remapped/0146-Add-option-to-make-parrots-stay-on-shoulders-despite.patch => server/0135-Add-option-to-make-parrots-stay-on-shoulders-despite.patch} (72%) rename patches/{server-remapped/0147-Add-configuration-option-to-prevent-player-names-fro.patch => server/0136-Add-configuration-option-to-prevent-player-names-fro.patch} (91%) diff --git a/patches/api-unmapped/0049-Expose-WorldBorder-isInBounds-Location-check.patch b/patches/api/0050-Expose-WorldBorder-isInBounds-Location-check.patch similarity index 100% rename from patches/api-unmapped/0049-Expose-WorldBorder-isInBounds-Location-check.patch rename to patches/api/0050-Expose-WorldBorder-isInBounds-Location-check.patch diff --git a/patches/api-unmapped/0050-Add-configuration-option-to-prevent-player-names-fro.patch b/patches/api/0051-Add-configuration-option-to-prevent-player-names-fro.patch similarity index 92% rename from patches/api-unmapped/0050-Add-configuration-option-to-prevent-player-names-fro.patch rename to patches/api/0051-Add-configuration-option-to-prevent-player-names-fro.patch index 195a5c5c39..c69c46b877 100644 --- a/patches/api-unmapped/0050-Add-configuration-option-to-prevent-player-names-fro.patch +++ b/patches/api/0051-Add-configuration-option-to-prevent-player-names-fro.patch @@ -6,7 +6,7 @@ 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 7b3a0c958b4b4bffb6c19a0e4d3bf4824f8db237..e2052baa65ed3525a89b26c065b3e2a58916ab99 100644 +index 55cd39f1e3787bcd34c6d528738122590ec580ec..14786ce10f43cd203544750a073c5efaf8b21348 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1768,6 +1768,16 @@ public final class Bukkit { @@ -27,7 +27,7 @@ index 7b3a0c958b4b4bffb6c19a0e4d3bf4824f8db237..e2052baa65ed3525a89b26c065b3e2a5 @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 6f4817af249e258905c97f4dac3d2f33804bdfc5..8fd026e4ffcdf009365ae04b87f7559bed32c7d3 100644 +index 08f451c392682cc0147ba14759c6b7edf7ff533f..7c44e23a5c370537d5163fd6ea6a1dea4d19d2b7 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1553,4 +1553,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/server-remapped/0145-Add-system-property-to-disable-book-size-limits.patch b/patches/server/0134-Add-system-property-to-disable-book-size-limits.patch similarity index 66% rename from patches/server-remapped/0145-Add-system-property-to-disable-book-size-limits.patch rename to patches/server/0134-Add-system-property-to-disable-book-size-limits.patch index ebfc39ca77..e720e04c6b 100644 --- a/patches/server-remapped/0145-Add-system-property-to-disable-book-size-limits.patch +++ b/patches/server/0134-Add-system-property-to-disable-book-size-limits.patch @@ -11,10 +11,10 @@ to make books with as much data as they want. Do not use this without limiting incoming data from packets in some other way. diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index a592d4a286a775a61192dde2a4d21a0681090415..80397e223990f11c9aa413f3f4ebd7c1b8ce1cff 100644 +index a33dd184ea51df7e59ed08e5e2b0ea4ed9dadff5..1d94d285951faa98ff1f70c3c5330dfaa77cb691 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -43,6 +43,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { +@@ -42,6 +42,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { static final int MAX_PAGES = 100; static final int MAX_PAGE_LENGTH = 320; // 256 limit + 64 characters to allow for psuedo colour codes static final int MAX_TITLE_LENGTH = 32; @@ -22,30 +22,30 @@ index a592d4a286a775a61192dde2a4d21a0681090415..80397e223990f11c9aa413f3f4ebd7c1 protected String title; protected String author; -@@ -245,7 +246,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { +@@ -244,7 +245,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { if (title == null) { this.title = null; return true; -- } else if (title.length() > MAX_TITLE_LENGTH) { -+ } else if (title.length() > MAX_TITLE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override +- } else if (title.length() > CraftMetaBook.MAX_TITLE_LENGTH) { ++ } else if (title.length() > CraftMetaBook.MAX_TITLE_LENGTH && !CraftMetaBook.OVERRIDE_CHECKS) { // Paper - Add override return false; } -@@ -442,7 +443,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { +@@ -441,7 +442,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { String validatePage(String page) { if (page == null) { page = ""; -- } else if (page.length() > MAX_PAGE_LENGTH) { -+ } else if (page.length() > MAX_PAGE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override +- } else if (page.length() > CraftMetaBook.MAX_PAGE_LENGTH) { ++ } else if (page.length() > CraftMetaBook.MAX_PAGE_LENGTH && !CraftMetaBook.OVERRIDE_CHECKS) { // Paper - Add override page = page.substring(0, MAX_PAGE_LENGTH); } return page; -@@ -452,7 +453,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { +@@ -451,7 +452,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { // asserted: page != null if (this.pages == null) { this.pages = new ArrayList(); -- } else if (this.pages.size() >= MAX_PAGES) { -+ } else if (this.pages.size() >= MAX_PAGES && !OVERRIDE_CHECKS) {// Paper - Add override +- } else if (this.pages.size() >= CraftMetaBook.MAX_PAGES) { ++ } else if (this.pages.size() >= CraftMetaBook.MAX_PAGES && !CraftMetaBook.OVERRIDE_CHECKS) { // Paper - Add override return; } this.pages.add(page); diff --git a/patches/server-remapped/0146-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/patches/server/0135-Add-option-to-make-parrots-stay-on-shoulders-despite.patch similarity index 72% rename from patches/server-remapped/0146-Add-option-to-make-parrots-stay-on-shoulders-despite.patch rename to patches/server/0135-Add-option-to-make-parrots-stay-on-shoulders-despite.patch index 0e3605cc72..0209dc0b8a 100644 --- a/patches/server-remapped/0146-Add-option-to-make-parrots-stay-on-shoulders-despite.patch +++ b/patches/server/0135-Add-option-to-make-parrots-stay-on-shoulders-despite.patch @@ -26,33 +26,42 @@ index c611b5a63498f5ad1f50a75ccd5d7299e27df7e3..9d1cddc6038f0fd0286e4a32013ae98f + } } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ecc393ad94332ec2a59d29f30bd60bade4e1f18e..6a922e3522ac99a8e317a5f5f51fbb597baaf63e 100644 +index 624776a85a3e3268665571635f0b837cb810a62e..acee61af1b01c7e66c3b5c7e164ddd9a88e53606 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2051,6 +2051,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2056,6 +2056,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser switch (packet.getAction()) { case PRESS_SHIFT_KEY: this.player.setShiftKeyDown(true); + -+ // Paper start - Hang on! -+ if (this.player.level.paperConfig.parrotsHangOnBetter) { -+ this.player.removeEntitiesOnShoulder(); -+ } -+ // Paper end ++ // Paper start - Hang on! ++ if (this.player.level.paperConfig.parrotsHangOnBetter) { ++ this.player.removeEntitiesOnShoulder(); ++ } ++ // Paper end + break; 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 c11d5aa115d10e3c12863cf9d42c60194d63b690..ae10c531ae69eaf6b78a342dcedb89c39fd8dbcc 100644 +index e8768625e55f849cd31784cb46e67293bcd93abf..73277b04a45444edce02cce3e033741ebaf2ad0c 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -529,7 +529,7 @@ public abstract class Player extends LivingEntity { +@@ -579,7 +579,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()) { + if (!this.level.isClientSide && (this.fallDistance > 0.5F || this.isInWater()) || this.abilities.flying || this.isSleeping() || this.isInPowderSnow) { - this.removeEntitiesOnShoulder(); + if (!this.level.paperConfig.parrotsHangOnBetter) this.removeEntitiesOnShoulder(); // Paper - Hang on! } } +@@ -1939,7 +1939,7 @@ public abstract class Player extends LivingEntity { + } + } + +- protected void removeEntitiesOnShoulder() { ++ public void removeEntitiesOnShoulder() { // Paper - protected -> public + if (this.timeEntitySatOnShoulder + 20L < this.level.getGameTime()) { + // CraftBukkit start + if (this.spawnEntityFromShoulder(this.getShoulderEntityLeft())) { diff --git a/patches/server-remapped/0147-Add-configuration-option-to-prevent-player-names-fro.patch b/patches/server/0136-Add-configuration-option-to-prevent-player-names-fro.patch similarity index 91% rename from patches/server-remapped/0147-Add-configuration-option-to-prevent-player-names-fro.patch rename to patches/server/0136-Add-configuration-option-to-prevent-player-names-fro.patch index 2f0b8509ca..7674c99080 100644 --- a/patches/server-remapped/0147-Add-configuration-option-to-prevent-player-names-fro.patch +++ b/patches/server/0136-Add-configuration-option-to-prevent-player-names-fro.patch @@ -20,10 +20,10 @@ index 4e2f243faa209925dcb7c3ef89df3ed875c5ff78..48319aaf1c525c6fb7bdee5c2f570a0d + } } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 9365fd2bcf74755c90c4ae9b550969e97a22c639..d198dad80e0fb41a5bde66944d0e41509a9c1c43 100644 +index f7b37aff1aa4e8b2f185dcf6a302e9d5e7e0b0a9..654ad4a6a92b11fbed84b091ca4b6e99131b4a20 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2300,5 +2300,10 @@ public final class CraftServer implements Server { +@@ -2299,5 +2299,10 @@ public final class CraftServer implements Server { commandMap.registerServerAliases(); return true; } From 4e99c4e598951cedbcd3b6956d25059c9eba2619 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Sat, 12 Jun 2021 11:23:51 +0200 Subject: [PATCH 042/226] add mcdev imports file --- build-data/mcdev-imports.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 build-data/mcdev-imports.txt diff --git a/build-data/mcdev-imports.txt b/build-data/mcdev-imports.txt new file mode 100644 index 0000000000..6f0ec2fe82 --- /dev/null +++ b/build-data/mcdev-imports.txt @@ -0,0 +1,4 @@ +# You can use this file to import files from vanilla into the project +# both fully qualified and a file based syntax are accepted here: +# net.minecraft.world.level.entity.LevelEntityGetterAdapter +# net/minecraft/world/level/entity/LevelEntityGetter.java From 0ec8b900ba88fa2236114c34a3f9cf520d1c2071 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Sat, 12 Jun 2021 12:26:21 +0200 Subject: [PATCH 043/226] More work --- ...pstream-javadoc-warnings-and-errors.patch} | 2 +- .../0053-Item-canEntityPickup.patch} | 0 ...layerPickupItemEvent-setFlyAtPlayer.patch} | 6 +- ...leAppender-for-console-improvements.patch} | 144 ++++++++---------- ...rable-option-to-disable-creeper-lin.patch} | 4 +- .../0139-Item-canEntityPickup.patch} | 18 ++- ...layerPickupItemEvent-setFlyAtPlayer.patch} | 16 +- 7 files changed, 84 insertions(+), 106 deletions(-) rename patches/{api-unmapped/0051-Fix-upstream-javadoc-warnings-and-errors.patch => api/0052-Fix-upstream-javadoc-warnings-and-errors.patch} (95%) rename patches/{api-unmapped/0052-Item-canEntityPickup.patch => api/0053-Item-canEntityPickup.patch} (100%) rename patches/{api-unmapped/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch => api/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch} (99%) rename patches/{server-remapped/0148-Use-TerminalConsoleAppender-for-console-improvements.patch => server/0137-Use-TerminalConsoleAppender-for-console-improvements.patch} (83%) rename patches/{server-remapped/0149-provide-a-configurable-option-to-disable-creeper-lin.patch => server/0138-provide-a-configurable-option-to-disable-creeper-lin.patch} (91%) rename patches/{server-remapped/0150-Item-canEntityPickup.patch => server/0139-Item-canEntityPickup.patch} (73%) rename patches/{server-remapped/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch => server/0140-PlayerPickupItemEvent-setFlyAtPlayer.patch} (76%) diff --git a/patches/api-unmapped/0051-Fix-upstream-javadoc-warnings-and-errors.patch b/patches/api/0052-Fix-upstream-javadoc-warnings-and-errors.patch similarity index 95% rename from patches/api-unmapped/0051-Fix-upstream-javadoc-warnings-and-errors.patch rename to patches/api/0052-Fix-upstream-javadoc-warnings-and-errors.patch index 083596bdd2..ad9ec8b241 100644 --- a/patches/api-unmapped/0051-Fix-upstream-javadoc-warnings-and-errors.patch +++ b/patches/api/0052-Fix-upstream-javadoc-warnings-and-errors.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Fix upstream javadoc warnings and errors Upstream still refuses to use Java 8 with the API so they are likely unaware these are even issues. diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 3f68baef538098d9ce66b91195b6fa17f26f0d78..e71b048e53ee2db4e768eea2ddf19b00a14d2484 100644 +index 6bb0bb8052c12c5a215abf4bd9602fbefc769523..22cfa703e4f543c26151b33fe9ee1ab445d1c4fe 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -634,7 +634,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM diff --git a/patches/api-unmapped/0052-Item-canEntityPickup.patch b/patches/api/0053-Item-canEntityPickup.patch similarity index 100% rename from patches/api-unmapped/0052-Item-canEntityPickup.patch rename to patches/api/0053-Item-canEntityPickup.patch diff --git a/patches/api-unmapped/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch b/patches/api/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch similarity index 99% rename from patches/api-unmapped/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch rename to patches/api/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch index 353d395911..fbc15c2f8c 100644 --- a/patches/api-unmapped/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch +++ b/patches/api/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch @@ -15,11 +15,11 @@ index 951ea2cc763973655beedcba3c75332d3f297313..18d82c111f30e0279c10a174a51bac01 + private boolean flyAtPlayer = true; // Paper private boolean cancel = false; private final int remaining; - + @@ -45,6 +46,27 @@ public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable { return remaining; } - + + // Paper Start + /** + * Set if the item will fly at the player @@ -50,5 +50,5 @@ index 951ea2cc763973655beedcba3c75332d3f297313..18d82c111f30e0279c10a174a51bac01 this.cancel = cancel; + this.flyAtPlayer = !cancel; // Paper } - + @NotNull diff --git a/patches/server-remapped/0148-Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server/0137-Use-TerminalConsoleAppender-for-console-improvements.patch similarity index 83% rename from patches/server-remapped/0148-Use-TerminalConsoleAppender-for-console-improvements.patch rename to patches/server/0137-Use-TerminalConsoleAppender-for-console-improvements.patch index d43b61bcff..8ae1556c29 100644 --- a/patches/server-remapped/0148-Use-TerminalConsoleAppender-for-console-improvements.patch +++ b/patches/server/0137-Use-TerminalConsoleAppender-for-console-improvements.patch @@ -18,60 +18,29 @@ Other changes: - Server starts 1-2 seconds faster thanks to optimizations in Log4j configuration -diff --git a/pom.xml b/pom.xml -index a5d87d22cb1588d15e08da3b37e51c5e261c7799..3841fe3630c090f8a468333d43caeb2b5841329d 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -57,10 +57,26 @@ - compile - - -- jline -- jline -- 2.12.1 -- compile -+ net.minecrell -+ terminalconsoleappender -+ 1.2.0 -+ -+ -+ org.jline -+ jline-terminal-jansi -+ 3.12.1 -+ runtime -+ -+ -+ -+ org.apache.logging.log4j -+ log4j-core -+ runtime - - - org.apache.logging.log4j -@@ -334,10 +350,18 @@ - - META-INF/services/java.sql.Driver - -+ - - - - -+ -+ -+ com.github.edwgiz -+ maven-shade-plugin.log4j2-cachefile-transformer -+ 2.13.1 -+ -+ - - - org.apache.maven.plugins ++ */ ++ runtimeOnly("org.apache.logging.log4j:log4j-core:2.14.1") ++ // Paper end + implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper + implementation("org.apache.logging.log4j:log4j-api:2.14.1") // Paper + implementation("org.apache.logging.log4j:log4j-slf4j-impl:2.14.1") // Paper diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java new file mode 100644 index 0000000000000000000000000000000000000000..a4070b59e261f0f1ac4beec47b11492f4724bf27 @@ -143,7 +112,7 @@ index 0000000000000000000000000000000000000000..685deaa0e5d1ddc13e3a7c0471b1cfcf + +} diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f41d79c6630fd8daae28476ffc854f7e65d841e6..4b3341877629c7065496fb0f0b4d509f5a48db6d 100644 +index 1617c59bf689e5f67c2af5c3a22ce5791d47b408..fb4385333ef8dd4fa22275753606df3020000539 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -12,6 +12,7 @@ import com.mojang.datafixers.DataFixer; @@ -152,9 +121,9 @@ index f41d79c6630fd8daae28476ffc854f7e65d841e6..4b3341877629c7065496fb0f0b4d509f import io.netty.buffer.Unpooled; +import io.papermc.paper.adventure.PaperAdventure; // Paper import it.unimi.dsi.fastutil.longs.LongIterator; + import java.awt.GraphicsEnvironment; import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -161,7 +162,7 @@ import org.apache.logging.log4j.Logger; +@@ -172,7 +173,7 @@ import org.apache.logging.log4j.Logger; import com.mojang.serialization.DynamicOps; import com.mojang.serialization.Lifecycle; import com.google.common.collect.ImmutableSet; @@ -163,7 +132,7 @@ index f41d79c6630fd8daae28476ffc854f7e65d841e6..4b3341877629c7065496fb0f0b4d509f import joptsimple.OptionSet; import net.minecraft.resources.RegistryReadOps; import net.minecraft.server.bossevents.CustomBossEvents; -@@ -253,7 +254,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; -@@ -322,7 +323,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { // Trim to filter lines which are just spaces @@ -232,7 +201,7 @@ index 77616b5dd3d79221d3460b1db4d90ad37c0f85aa..883e05ba87c3bdec9a0d4bbd035b90c7 } // CraftBukkit end } -@@ -138,6 +141,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -147,6 +150,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface DedicatedServer.LOGGER.error("Exception handling console input", ioexception); } @@ -241,7 +210,7 @@ index 77616b5dd3d79221d3460b1db4d90ad37c0f85aa..883e05ba87c3bdec9a0d4bbd035b90c7 } }; -@@ -149,6 +154,9 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -158,6 +163,9 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler()); @@ -251,7 +220,7 @@ index 77616b5dd3d79221d3460b1db4d90ad37c0f85aa..883e05ba87c3bdec9a0d4bbd035b90c7 final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()); for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) { if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) { -@@ -157,6 +165,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -166,6 +174,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start(); @@ -261,10 +230,10 @@ index 77616b5dd3d79221d3460b1db4d90ad37c0f85aa..883e05ba87c3bdec9a0d4bbd035b90c7 System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream()); System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream()); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index d750bef20312cc97e3446bbb2d2dc03f90d47f1c..7d6256f65d369fcbcfe1fffe7ac264788a38540b 100644 +index 79ebb15bed6eec80c12c1020b2b6b07c758332aa..bf6c3ac7ae37067f345568fb6656cf6b4d864be2 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -146,8 +146,7 @@ public abstract class PlayerList { +@@ -151,8 +151,7 @@ public abstract class PlayerList { public PlayerList(MinecraftServer server, RegistryAccess.RegistryHolder registryManager, PlayerDataStorage saveHandler, int maxPlayers) { this.cserver = server.server = new CraftServer((DedicatedServer) server, this); @@ -275,7 +244,7 @@ index d750bef20312cc97e3446bbb2d2dc03f90d47f1c..7d6256f65d369fcbcfe1fffe7ac26478 this.bans = new UserBanList(PlayerList.USERBANLIST_FILE); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index d198dad80e0fb41a5bde66944d0e41509a9c1c43..7b2ece40c09ba336a0c2a84321401619801c64c8 100644 +index 654ad4a6a92b11fbed84b091ca4b6e99131b4a20..dcc1a3856560ab0eb4de45a358e189134adeac17 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -46,7 +46,6 @@ import java.util.function.Consumer; @@ -295,7 +264,7 @@ index d198dad80e0fb41a5bde66944d0e41509a9c1c43..7b2ece40c09ba336a0c2a84321401619 import net.minecraft.server.bossevents.CustomBossEvent; import net.minecraft.server.commands.ReloadCommand; @@ -1204,9 +1204,13 @@ public final class CraftServer implements Server { - return logger; + return this.logger; } + // Paper start - JLine update @@ -309,7 +278,7 @@ index d198dad80e0fb41a5bde66944d0e41509a9c1c43..7b2ece40c09ba336a0c2a84321401619 @Override public PluginCommand getPluginCommand(String name) { diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index b849b2afd009da433fe6cea5837b3ee9bb5c52b4..60d9980ccca6f1ac55b70f7684b917ddceac380a 100644 +index 6985e8dc3d520eb65ae7d885138be81836452c01..b4bcd34123968b3930bb330f7c2abd9b5518fa31 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -12,7 +12,7 @@ import java.util.logging.Level; @@ -321,7 +290,7 @@ index b849b2afd009da433fe6cea5837b3ee9bb5c52b4..60d9980ccca6f1ac55b70f7684b917dd public class Main { public static boolean useJline = true; -@@ -185,6 +185,8 @@ public class Main { +@@ -189,6 +189,8 @@ public class Main { } try { @@ -330,7 +299,7 @@ index b849b2afd009da433fe6cea5837b3ee9bb5c52b4..60d9980ccca6f1ac55b70f7684b917dd // This trick bypasses Maven Shade's clever rewriting of our getProperty call when using String literals String jline_UnsupportedTerminal = new String(new char[]{'j', 'l', 'i', 'n', 'e', '.', 'U', 'n', 's', 'u', 'p', 'p', 'o', 'r', 't', 'e', 'd', 'T', 'e', 'r', 'm', 'i', 'n', 'a', 'l'}); String jline_terminal = new String(new char[]{'j', 'l', 'i', 'n', 'e', '.', 't', 'e', 'r', 'm', 'i', 'n', 'a', 'l'}); -@@ -202,9 +204,18 @@ public class Main { +@@ -206,9 +208,18 @@ public class Main { // This ensures the terminal literal will always match the jline implementation System.setProperty(jline.TerminalFactory.JLINE_TERMINAL, jline.UnsupportedTerminal.class.getName()); } @@ -343,13 +312,13 @@ index b849b2afd009da433fe6cea5837b3ee9bb5c52b4..60d9980ccca6f1ac55b70f7684b917dd + // Paper end if (options.has("noconsole")) { - useConsole = false; + Main.useConsole = false; + useJline = false; // Paper + System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper } - if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { -@@ -232,7 +243,7 @@ public class Main { + if (Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { +@@ -236,7 +247,7 @@ public class Main { System.out.println("Unable to read system info"); } // Paper end @@ -359,7 +328,7 @@ index b849b2afd009da433fe6cea5837b3ee9bb5c52b4..60d9980ccca6f1ac55b70f7684b917dd net.minecraft.server.Main.main(options); } catch (Throwable t) { diff --git a/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java b/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java -index 4580642e0ee79e6d9c9bef0344e643bbc551205c..829c62b6d55cb5706be3ce6bdc758d6b204844ee 100644 +index 76fb1ecd47cb86b50486effe8cc7fe4abf8e311c..21f889ddec72b40f5954eec07417e08d192b4661 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java +++ b/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java @@ -5,15 +5,13 @@ import java.util.EnumMap; @@ -388,10 +357,10 @@ index 4580642e0ee79e6d9c9bef0344e643bbc551205c..829c62b6d55cb5706be3ce6bdc758d6b + }*/ // Paper } diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index befcc19f9b56df9096b98a23b0020f1db793ea5b..a957695457cf3252848ce6ef37069692841b8e28 100644 +index 0b4c62387c1093652ac15b64a8703249de4cf088..b996fde481cebbbcce80a6c267591136db7cc0bc 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -4,20 +4,31 @@ import java.util.Collections; +@@ -4,50 +4,73 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.logging.Level; @@ -427,7 +396,14 @@ index befcc19f9b56df9096b98a23b0020f1db793ea5b..a957695457cf3252848ce6ef37069692 Waitable> waitable = new Waitable>() { @Override protected List evaluate() { -@@ -29,25 +40,37 @@ public class ConsoleCommandCompleter implements Completer { +- List offers = ConsoleCommandCompleter.this.server.getCommandMap().tabComplete(ConsoleCommandCompleter.this.server.getConsoleSender(), buffer); ++ List offers = server.getCommandMap().tabComplete(server.getConsoleSender(), buffer); // Paper - fix remap + +- TabCompleteEvent tabEvent = new TabCompleteEvent(ConsoleCommandCompleter.this.server.getConsoleSender(), buffer, (offers == null) ? Collections.EMPTY_LIST : offers); +- ConsoleCommandCompleter.this.server.getPluginManager().callEvent(tabEvent); ++ TabCompleteEvent tabEvent = new TabCompleteEvent(server.getConsoleSender(), buffer, (offers == null) ? Collections.EMPTY_LIST : offers); // Paper - fix remap ++ server.getPluginManager().callEvent(tabEvent); // Paper - fix remap + return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); } }; @@ -471,11 +447,11 @@ index befcc19f9b56df9096b98a23b0020f1db793ea5b..a957695457cf3252848ce6ef37069692 } } diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index 70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe..449e99d1b673870ed6892f6ab2c715a2db35c35d 100644 +index 6a073a9dc44d93eba296a0e18a9c7be8a7881725..b4a19d80bbf71591f25729fd0e98590350cb31d0 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java @@ -17,7 +17,7 @@ public class ServerShutdownThread extends Thread { - server.close(); + this.server.close(); } finally { try { - server.reader.getTerminal().restore(); @@ -484,7 +460,7 @@ index 70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe..449e99d1b673870ed6892f6ab2c715a2 } } diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -index 99564fed7ce77e29dbdc591bcfe656af741acf8a..9a2da548b8860b496e396564b2c8f6383f020193 100644 +index 5b63604aeae9a54e2c61cc4a22115a72f34a56bd..fc07f6bd45712ec0f1aec5fe820034e6d54b39c1 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java +++ b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java @@ -5,12 +5,12 @@ import java.io.IOException; diff --git a/patches/server-remapped/0149-provide-a-configurable-option-to-disable-creeper-lin.patch b/patches/server/0138-provide-a-configurable-option-to-disable-creeper-lin.patch similarity index 91% rename from patches/server-remapped/0149-provide-a-configurable-option-to-disable-creeper-lin.patch rename to patches/server/0138-provide-a-configurable-option-to-disable-creeper-lin.patch index a511c4d919..38f524ba3b 100644 --- a/patches/server-remapped/0149-provide-a-configurable-option-to-disable-creeper-lin.patch +++ b/patches/server/0138-provide-a-configurable-option-to-disable-creeper-lin.patch @@ -21,10 +21,10 @@ index 9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1..90ca51dfdbb3045dd528450225cba96f + } } 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 bb3226310158139c9fcfe204554caffcbb62798c..8f8d0a23d011936150854a0606be3d63b18c57af 100644 +index e758c112662f65646fc2966e21bf631d8953a3e1..ddc48d37f962b6743f3f356745c9ebe6a06f79f1 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java +++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -@@ -261,7 +261,7 @@ public class Creeper extends Monster { +@@ -281,7 +281,7 @@ public class Creeper extends Monster implements PowerableMob { private void spawnLingeringCloud() { Collection collection = this.getActiveEffects(); diff --git a/patches/server-remapped/0150-Item-canEntityPickup.patch b/patches/server/0139-Item-canEntityPickup.patch similarity index 73% rename from patches/server-remapped/0150-Item-canEntityPickup.patch rename to patches/server/0139-Item-canEntityPickup.patch index 569a928f31..6f930c25fa 100644 --- a/patches/server-remapped/0150-Item-canEntityPickup.patch +++ b/patches/server/0139-Item-canEntityPickup.patch @@ -5,13 +5,13 @@ Subject: [PATCH] Item#canEntityPickup diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 46f0ebfc99352ec8b64bdff2c6bb8d17ecfeb619..eb35c69bb777ba8d83b2304ff9f862512643e745 100644 +index b13774873f795b149c15fddb8053d9419f1841ca..2ed756c73b0cfddb559126d85316f37c3f958c0c 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -605,6 +605,11 @@ public abstract class Mob extends LivingEntity { +@@ -614,6 +614,11 @@ public abstract class Mob extends LivingEntity { ItemEntity entityitem = (ItemEntity) iterator.next(); - if (!entityitem.removed && !entityitem.getItem().isEmpty() && !entityitem.hasPickUpDelay() && this.wantsToPickUp(entityitem.getItem())) { + if (!entityitem.isRemoved() && !entityitem.getItem().isEmpty() && !entityitem.hasPickUpDelay() && this.wantsToPickUp(entityitem.getItem())) { + // Paper Start + if (!entityitem.canMobPickup) { + continue; @@ -21,10 +21,10 @@ index 46f0ebfc99352ec8b64bdff2c6bb8d17ecfeb619..eb35c69bb777ba8d83b2304ff9f86251 } } diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 78dc5ac986afaba04176f64afbb035442cd41d38..7aba507e171f34e213b3c034e345e7397a44d2b5 100644 +index bf6daeefef5a60ebc612c0347eb34d581fb8851a..9611388a6aeebb86b19d89c526f53dfed4d3ed27 100644 --- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -46,6 +46,7 @@ public class ItemEntity extends Entity { +@@ -51,6 +51,7 @@ public class ItemEntity extends Entity { private UUID owner; public final float bobOffs; private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit @@ -33,18 +33,20 @@ index 78dc5ac986afaba04176f64afbb035442cd41d38..7aba507e171f34e213b3c034e345e739 public ItemEntity(EntityType type, Level world) { super(type, world); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -index 6e394ce6ea4177e1758e27074a4fd54d716edc3d..9a410f557988d737c3b930a79ef2ccb2b5c8b406 100644 +index b9044654d22a47cfa952dcf25754ad0d87fc0844..0d262c99c7e9ef06e297612b1802c493700f64ae 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -@@ -49,6 +49,16 @@ public class CraftItem extends CraftEntity implements Item { +@@ -49,6 +49,18 @@ public class CraftItem extends CraftEntity implements Item { item.age = value; } + // Paper Start ++ @Override + public boolean canMobPickup() { + return item.canMobPickup; + } + ++ @Override + public void setCanMobPickup(boolean canMobPickup) { + item.canMobPickup = canMobPickup; + } @@ -52,4 +54,4 @@ index 6e394ce6ea4177e1758e27074a4fd54d716edc3d..9a410f557988d737c3b930a79ef2ccb2 + @Override public void setOwner(UUID uuid) { - item.setOwner(uuid); + this.item.setOwner(uuid); diff --git a/patches/server-remapped/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch b/patches/server/0140-PlayerPickupItemEvent-setFlyAtPlayer.patch similarity index 76% rename from patches/server-remapped/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch rename to patches/server/0140-PlayerPickupItemEvent-setFlyAtPlayer.patch index a5081735fc..fd524d8436 100644 --- a/patches/server-remapped/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch +++ b/patches/server/0140-PlayerPickupItemEvent-setFlyAtPlayer.patch @@ -5,20 +5,20 @@ Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 7aba507e171f34e213b3c034e345e7397a44d2b5..72d1e83ac5e4ae3c943ca5ec1058f0d7ad2903cd 100644 +index 9611388a6aeebb86b19d89c526f53dfed4d3ed27..d17af2ec8f72bf0cbe5928e7a83c06ba5ad4503d 100644 --- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -362,6 +362,7 @@ public class ItemEntity extends Entity { +@@ -379,6 +379,7 @@ public class ItemEntity extends Entity { // CraftBukkit start - fire PlayerPickupItemEvent - int canHold = player.inventory.canHold(itemstack); + int canHold = player.getInventory().canHold(itemstack); int remaining = i - canHold; + boolean flyAtPlayer = false; // Paper if (this.pickupDelay <= 0 && canHold > 0) { itemstack.setCount(canHold); -@@ -369,8 +370,14 @@ public class ItemEntity extends Entity { +@@ -386,8 +387,14 @@ public class ItemEntity extends Entity { PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); - playerEvent.setCancelled(!player.canPickUpLoot); + playerEvent.setCancelled(!playerEvent.getPlayer().getCanPickupItems()); this.level.getCraftServer().getPluginManager().callEvent(playerEvent); + flyAtPlayer = playerEvent.getFlyAtPlayer(); // Paper if (playerEvent.isCancelled()) { @@ -31,10 +31,10 @@ index 7aba507e171f34e213b3c034e345e7397a44d2b5..72d1e83ac5e4ae3c943ca5ec1058f0d7 return; } -@@ -400,7 +407,11 @@ public class ItemEntity extends Entity { +@@ -417,7 +424,11 @@ public class ItemEntity extends Entity { // CraftBukkit end - if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(player.getUUID())) && player.inventory.add(itemstack)) { + if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(player.getUUID())) && player.getInventory().add(itemstack)) { - player.take(this, i); + // Paper Start + if (flyAtPlayer) { @@ -42,5 +42,5 @@ index 7aba507e171f34e213b3c034e345e7397a44d2b5..72d1e83ac5e4ae3c943ca5ec1058f0d7 + } + // Paper End if (itemstack.isEmpty()) { - this.remove(); + this.discard(); itemstack.setCount(i); From 3c1cd3bdf2a393695086f665f708b93f459902a4 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Sat, 12 Jun 2021 13:18:01 +0200 Subject: [PATCH 044/226] More more work --- ...or-plugins-modifying-the-parent-of-t.patch | 234 +++++++++--------- .../0054-PlayerAttemptPickupItemEvent.patch | 0 .../0055-Add-UnknownCommandEvent.patch | 0 .../0056-Basic-PlayerProfile-API.patch | 4 +- ...layerPickupItemEvent-setFlyAtPlayer.patch} | 6 +- .../0058-Shoulder-Entities-Release-API.patch} | 2 +- .../0059-Entity-fromMobSpawner.patch | 0 .../0060-Profile-Lookup-Events.patch} | 0 ...1-Improve-the-Saddle-API-for-Horses.patch} | 0 .../0062-Add-getI18NDisplayName-API.patch | 14 +- .../0063-ensureServerConversions-API.patch} | 21 +- .../0064-Make-plugins-list-alphabetical.patch | 0 .../0065-LivingEntity-setKiller.patch | 0 .../0066-ProfileWhitelistVerifyEvent.patch} | 0 ...low-plugins-to-use-SLF4J-for-logging.patch | 30 +-- ...fixes-in-implementation-logging-con.patch} | 0 ...or-plugins-modifying-the-parent-of-t.patch | 117 +++++++++ ...66-Fix-MC-117075-TE-Unload-Lag-Spike.patch | 0 ...imer-when-spawner-event-is-cancelled.patch | 27 -- .../0141-PlayerAttemptPickupItemEvent.patch} | 6 +- .../0142-Add-UnknownCommandEvent.patch} | 4 +- .../0143-Basic-PlayerProfile-API.patch} | 61 ++--- .../0144-Shoulder-Entities-Release-API.patch} | 10 +- .../0145-Profile-Lookup-Events.patch} | 0 ...layer-logins-during-server-shutdown.patch} | 4 +- .../0147-Entity-fromMobSpawner.patch} | 34 +-- ...8-Improve-the-Saddle-API-for-Horses.patch} | 4 +- ...plement-ensureServerConversions-API.patch} | 4 +- .../0150-Implement-getI18NDisplayName.patch} | 28 +-- .../0151-ProfileWhitelistVerifyEvent.patch} | 10 +- .../0152-Fix-this-stupid-bullshit.patch} | 6 +- .../0153-LivingEntity-setKiller.patch} | 10 +- ...wns-should-honor-nametags-and-leash.patch} | 4 +- ...imer-when-spawner-event-is-cancelled.patch | 27 ++ ...a-custom-authentication-servers-dow.patch} | 4 +- 35 files changed, 375 insertions(+), 296 deletions(-) rename patches/{api-unmapped => api}/0054-PlayerAttemptPickupItemEvent.patch (100%) rename patches/{api-unmapped => api}/0055-Add-UnknownCommandEvent.patch (100%) rename patches/{api-unmapped => api}/0056-Basic-PlayerProfile-API.patch (98%) rename patches/api/{0151-PlayerPickupItemEvent-setFlyAtPlayer.patch => 0057-PlayerPickupItemEvent-setFlyAtPlayer.patch} (99%) rename patches/{api-unmapped/0057-Shoulder-Entities-Release-API.patch => api/0058-Shoulder-Entities-Release-API.patch} (92%) rename patches/{api-unmapped => api}/0059-Entity-fromMobSpawner.patch (100%) rename patches/{api-unmapped/0058-Profile-Lookup-Events.patch => api/0060-Profile-Lookup-Events.patch} (100%) rename patches/{api-unmapped/0060-Improve-the-Saddle-API-for-Horses.patch => api/0061-Improve-the-Saddle-API-for-Horses.patch} (100%) rename patches/{api-unmapped => api}/0062-Add-getI18NDisplayName-API.patch (76%) rename patches/{api-unmapped/0061-ensureServerConversions-API.patch => api/0063-ensureServerConversions-API.patch} (80%) rename patches/{api-unmapped => api}/0064-Make-plugins-list-alphabetical.patch (100%) rename patches/{api-unmapped => api}/0065-LivingEntity-setKiller.patch (100%) rename patches/{api-unmapped/0063-ProfileWhitelistVerifyEvent.patch => api/0066-ProfileWhitelistVerifyEvent.patch} (100%) rename patches/{api-unmapped => api}/0067-Allow-plugins-to-use-SLF4J-for-logging.patch (69%) rename patches/{api-unmapped/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch => api/0068-Handle-plugin-prefixes-in-implementation-logging-con.patch} (100%) create mode 100644 patches/api/0069-Add-workaround-for-plugins-modifying-the-parent-of-t.patch rename patches/{server-remapped => removed/1.17}/0166-Fix-MC-117075-TE-Unload-Lag-Spike.patch (100%) delete mode 100644 patches/server-remapped/0165-Reset-spawner-timer-when-spawner-event-is-cancelled.patch rename patches/{server-remapped/0152-PlayerAttemptPickupItemEvent.patch => server/0141-PlayerAttemptPickupItemEvent.patch} (88%) rename patches/{server-remapped/0153-Add-UnknownCommandEvent.patch => server/0142-Add-UnknownCommandEvent.patch} (87%) rename patches/{server-remapped/0154-Basic-PlayerProfile-API.patch => server/0143-Basic-PlayerProfile-API.patch} (89%) rename patches/{server-remapped/0155-Shoulder-Entities-Release-API.patch => server/0144-Shoulder-Entities-Release-API.patch} (89%) rename patches/{server-remapped/0156-Profile-Lookup-Events.patch => server/0145-Profile-Lookup-Events.patch} (100%) rename patches/{server-remapped/0157-Block-player-logins-during-server-shutdown.patch => server/0146-Block-player-logins-during-server-shutdown.patch} (87%) rename patches/{server-remapped/0158-Entity-fromMobSpawner.patch => server/0147-Entity-fromMobSpawner.patch} (60%) rename patches/{server-remapped/0159-Improve-the-Saddle-API-for-Horses.patch => server/0148-Improve-the-Saddle-API-for-Horses.patch} (94%) rename patches/{server-remapped/0160-Implement-ensureServerConversions-API.patch => server/0149-Implement-ensureServerConversions-API.patch} (87%) rename patches/{server-remapped/0161-Implement-getI18NDisplayName.patch => server/0150-Implement-getI18NDisplayName.patch} (59%) rename patches/{server-remapped/0162-ProfileWhitelistVerifyEvent.patch => server/0151-ProfileWhitelistVerifyEvent.patch} (85%) rename patches/{server-remapped/0163-Fix-this-stupid-bullshit.patch => server/0152-Fix-this-stupid-bullshit.patch} (88%) rename patches/{server-remapped/0168-LivingEntity-setKiller.patch => server/0153-LivingEntity-setKiller.patch} (82%) rename patches/{server-remapped/0164-Ocelot-despawns-should-honor-nametags-and-leash.patch => server/0154-Ocelot-despawns-should-honor-nametags-and-leash.patch} (85%) create mode 100644 patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch rename patches/{server-remapped/0167-Allow-specifying-a-custom-authentication-servers-dow.patch => server/0156-Allow-specifying-a-custom-authentication-servers-dow.patch} (94%) diff --git a/patches/api-unmapped/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/patches/api-unmapped/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch index 47b6099ab7..f0cce6b67a 100644 --- a/patches/api-unmapped/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch +++ b/patches/api-unmapped/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch @@ -1,117 +1,117 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Thu, 21 Sep 2017 19:41:20 +0200 -Subject: [PATCH] Add workaround for plugins modifying the parent of the plugin - logger - -Essentials uses a custom logger name ("Essentials") instead of the -plugin logger. Log messages are redirected to the plugin logger by -setting the parent of the "Essentials" logger to the plugin logger. - -With our changes, the plugin logger is now also called "Essentials", -resulting in an infinite loop. Make sure plugins can't change the -parent of the plugin logger to avoid this. - -diff --git a/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java -new file mode 100644 -index 0000000000000000000000000000000000000000..76f2cb9cd99cad2a9484eab2becd8c36f1dd91b3 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.utils; -+ -+import org.bukkit.plugin.PluginDescriptionFile; -+ -+import java.util.logging.Level; -+import java.util.logging.LogManager; -+import java.util.logging.Logger; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Prevents plugins (e.g. Essentials) from changing the parent of the plugin logger. -+ */ -+public class PaperPluginLogger extends Logger { -+ -+ @NotNull -+ public static Logger getLogger(@NotNull PluginDescriptionFile description) { -+ Logger logger = new PaperPluginLogger(description); -+ if (!LogManager.getLogManager().addLogger(logger)) { -+ // Disable this if it's going to happen across reloads anyways... -+ //logger.log(Level.WARNING, "Could not insert plugin logger - one was already found: {}", LogManager.getLogManager().getLogger(this.getName())); -+ logger = LogManager.getLogManager().getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); -+ } -+ -+ return logger; -+ } -+ -+ private PaperPluginLogger(@NotNull PluginDescriptionFile description) { -+ super(description.getPrefix() != null ? description.getPrefix() : description.getName(), null); -+ } -+ -+ @Override -+ public void setParent(@NotNull Logger parent) { -+ if (getParent() != null) { -+ warning("Ignoring attempt to change parent of plugin logger"); -+ } else { -+ this.log(Level.FINE, "Setting plugin logger parent to {0}", parent); -+ super.setParent(parent); -+ } -+ } -+ -+} -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -index bb2e55e97bf887a28cac7d4f9a0a23960d22cf56..04fa3991f6ce4e9dad804f28fc6c947695857089 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -@@ -42,7 +42,7 @@ public abstract class JavaPlugin extends PluginBase { - private boolean naggable = true; - private FileConfiguration newConfig = null; - private File configFile = null; -- private Logger logger = null; // Paper - PluginLogger -> Logger -+ Logger logger = null; // Paper - PluginLogger -> Logger, package-private - - public JavaPlugin() { - final ClassLoader classLoader = this.getClass().getClassLoader(); -@@ -276,8 +276,11 @@ public abstract class JavaPlugin extends PluginBase { - this.dataFolder = dataFolder; - this.classLoader = classLoader; - this.configFile = new File(dataFolder, "config.yml"); -- // Paper - Handle plugin prefix in implementation -- this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); -+ // Paper start -+ if (this.logger == null) { -+ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(this.description); -+ } -+ // Paper end - } - - /** -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 13100c688bfccb826b3072aaa92901f8634cf9ab..b9766b9b47547c400ed075f1635bb1461cb5e860 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -44,6 +44,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - private JavaPlugin pluginInit; - private IllegalStateException pluginState; - private final Set seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>()); -+ private java.util.logging.Logger logger; // Paper - add field - - static { - ClassLoader.registerAsParallelCapable(); -@@ -62,6 +63,8 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - this.url = file.toURI().toURL(); - this.libraryLoader = libraryLoader; - -+ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(description); // Paper - Register logger early -+ - try { - Class jarClass; - try { -@@ -222,6 +225,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - pluginState = new IllegalStateException("Initial initialization"); - this.pluginInit = javaPlugin; - -+ javaPlugin.logger = this.logger; // Paper - set logger - javaPlugin.init(loader, loader.server, description, dataFolder, file, this); - } - } +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Thu, 21 Sep 2017 19:41:20 +0200 +Subject: [PATCH] Add workaround for plugins modifying the parent of the plugin + logger + +Essentials uses a custom logger name ("Essentials") instead of the +plugin logger. Log messages are redirected to the plugin logger by +setting the parent of the "Essentials" logger to the plugin logger. + +With our changes, the plugin logger is now also called "Essentials", +resulting in an infinite loop. Make sure plugins can't change the +parent of the plugin logger to avoid this. + +diff --git a/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java +new file mode 100644 +index 0000000000000000000000000000000000000000..76f2cb9cd99cad2a9484eab2becd8c36f1dd91b3 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.utils; ++ ++import org.bukkit.plugin.PluginDescriptionFile; ++ ++import java.util.logging.Level; ++import java.util.logging.LogManager; ++import java.util.logging.Logger; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Prevents plugins (e.g. Essentials) from changing the parent of the plugin logger. ++ */ ++public class PaperPluginLogger extends Logger { ++ ++ @NotNull ++ public static Logger getLogger(@NotNull PluginDescriptionFile description) { ++ Logger logger = new PaperPluginLogger(description); ++ if (!LogManager.getLogManager().addLogger(logger)) { ++ // Disable this if it's going to happen across reloads anyways... ++ //logger.log(Level.WARNING, "Could not insert plugin logger - one was already found: {}", LogManager.getLogManager().getLogger(this.getName())); ++ logger = LogManager.getLogManager().getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); ++ } ++ ++ return logger; ++ } ++ ++ private PaperPluginLogger(@NotNull PluginDescriptionFile description) { ++ super(description.getPrefix() != null ? description.getPrefix() : description.getName(), null); ++ } ++ ++ @Override ++ public void setParent(@NotNull Logger parent) { ++ if (getParent() != null) { ++ warning("Ignoring attempt to change parent of plugin logger"); ++ } else { ++ this.log(Level.FINE, "Setting plugin logger parent to {0}", parent); ++ super.setParent(parent); ++ } ++ } ++ ++} +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +index bb2e55e97bf887a28cac7d4f9a0a23960d22cf56..04fa3991f6ce4e9dad804f28fc6c947695857089 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +@@ -42,7 +42,7 @@ public abstract class JavaPlugin extends PluginBase { + private boolean naggable = true; + private FileConfiguration newConfig = null; + private File configFile = null; +- private Logger logger = null; // Paper - PluginLogger -> Logger ++ Logger logger = null; // Paper - PluginLogger -> Logger, package-private + + public JavaPlugin() { + final ClassLoader classLoader = this.getClass().getClassLoader(); +@@ -276,8 +276,11 @@ public abstract class JavaPlugin extends PluginBase { + this.dataFolder = dataFolder; + this.classLoader = classLoader; + this.configFile = new File(dataFolder, "config.yml"); +- // Paper - Handle plugin prefix in implementation +- this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); ++ // Paper start ++ if (this.logger == null) { ++ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(this.description); ++ } ++ // Paper end + } + + /** +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index 13100c688bfccb826b3072aaa92901f8634cf9ab..b9766b9b47547c400ed075f1635bb1461cb5e860 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -44,6 +44,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + private JavaPlugin pluginInit; + private IllegalStateException pluginState; + private final Set seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>()); ++ private java.util.logging.Logger logger; // Paper - add field + + static { + ClassLoader.registerAsParallelCapable(); +@@ -62,6 +63,8 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + this.url = file.toURI().toURL(); + this.libraryLoader = libraryLoader; + ++ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(description); // Paper - Register logger early ++ + try { + Class jarClass; + try { +@@ -222,6 +225,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + pluginState = new IllegalStateException("Initial initialization"); + this.pluginInit = javaPlugin; + ++ javaPlugin.logger = this.logger; // Paper - set logger + javaPlugin.init(loader, loader.server, description, dataFolder, file, this); + } + } diff --git a/patches/api-unmapped/0054-PlayerAttemptPickupItemEvent.patch b/patches/api/0054-PlayerAttemptPickupItemEvent.patch similarity index 100% rename from patches/api-unmapped/0054-PlayerAttemptPickupItemEvent.patch rename to patches/api/0054-PlayerAttemptPickupItemEvent.patch diff --git a/patches/api-unmapped/0055-Add-UnknownCommandEvent.patch b/patches/api/0055-Add-UnknownCommandEvent.patch similarity index 100% rename from patches/api-unmapped/0055-Add-UnknownCommandEvent.patch rename to patches/api/0055-Add-UnknownCommandEvent.patch diff --git a/patches/api-unmapped/0056-Basic-PlayerProfile-API.patch b/patches/api/0056-Basic-PlayerProfile-API.patch similarity index 98% rename from patches/api-unmapped/0056-Basic-PlayerProfile-API.patch rename to patches/api/0056-Basic-PlayerProfile-API.patch index 1c7a3ce8f5..e39405a942 100644 --- a/patches/api-unmapped/0056-Basic-PlayerProfile-API.patch +++ b/patches/api/0056-Basic-PlayerProfile-API.patch @@ -267,7 +267,7 @@ index 0000000000000000000000000000000000000000..7b3b6ef533d32169fbeca389bd61cfc6 + } +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index e2052baa65ed3525a89b26c065b3e2a58916ab99..39942b4c5683f2dcc40be5a23af36a3bb32badb1 100644 +index 14786ce10f43cd203544750a073c5efaf8b21348..c9f00ffe05c8624619b23ad22cf61233cede440e 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1778,6 +1778,40 @@ public final class Bukkit { @@ -312,7 +312,7 @@ index e2052baa65ed3525a89b26c065b3e2a58916ab99..39942b4c5683f2dcc40be5a23af36a3b @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 8fd026e4ffcdf009365ae04b87f7559bed32c7d3..0c1fbaee08cb614dfdd1de0200dfa7fa351fc52d 100644 +index 7c44e23a5c370537d5163fd6ea6a1dea4d19d2b7..f2448c6dc8ef64393127a13c33eb14b0d5cd92c0 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1562,5 +1562,33 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch b/patches/api/0057-PlayerPickupItemEvent-setFlyAtPlayer.patch similarity index 99% rename from patches/api/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch rename to patches/api/0057-PlayerPickupItemEvent-setFlyAtPlayer.patch index fbc15c2f8c..353d395911 100644 --- a/patches/api/0151-PlayerPickupItemEvent-setFlyAtPlayer.patch +++ b/patches/api/0057-PlayerPickupItemEvent-setFlyAtPlayer.patch @@ -15,11 +15,11 @@ index 951ea2cc763973655beedcba3c75332d3f297313..18d82c111f30e0279c10a174a51bac01 + private boolean flyAtPlayer = true; // Paper private boolean cancel = false; private final int remaining; - + @@ -45,6 +46,27 @@ public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable { return remaining; } - + + // Paper Start + /** + * Set if the item will fly at the player @@ -50,5 +50,5 @@ index 951ea2cc763973655beedcba3c75332d3f297313..18d82c111f30e0279c10a174a51bac01 this.cancel = cancel; + this.flyAtPlayer = !cancel; // Paper } - + @NotNull diff --git a/patches/api-unmapped/0057-Shoulder-Entities-Release-API.patch b/patches/api/0058-Shoulder-Entities-Release-API.patch similarity index 92% rename from patches/api-unmapped/0057-Shoulder-Entities-Release-API.patch rename to patches/api/0058-Shoulder-Entities-Release-API.patch index 249e81f7ad..54cea09655 100644 --- a/patches/api-unmapped/0057-Shoulder-Entities-Release-API.patch +++ b/patches/api/0058-Shoulder-Entities-Release-API.patch @@ -5,7 +5,7 @@ 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 72178c3036f567ceaf15016978a9737eb9c4afc4..d212d5123b6294f7873d72f125505a006c290b05 100644 +index b64e1f5e5aa4ec9bdd5f6976bf9dfdb83398e305..8ba6a59066234b834aedb0fb414ee7391aa2ac18 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java @@ -300,6 +300,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder diff --git a/patches/api-unmapped/0059-Entity-fromMobSpawner.patch b/patches/api/0059-Entity-fromMobSpawner.patch similarity index 100% rename from patches/api-unmapped/0059-Entity-fromMobSpawner.patch rename to patches/api/0059-Entity-fromMobSpawner.patch diff --git a/patches/api-unmapped/0058-Profile-Lookup-Events.patch b/patches/api/0060-Profile-Lookup-Events.patch similarity index 100% rename from patches/api-unmapped/0058-Profile-Lookup-Events.patch rename to patches/api/0060-Profile-Lookup-Events.patch diff --git a/patches/api-unmapped/0060-Improve-the-Saddle-API-for-Horses.patch b/patches/api/0061-Improve-the-Saddle-API-for-Horses.patch similarity index 100% rename from patches/api-unmapped/0060-Improve-the-Saddle-API-for-Horses.patch rename to patches/api/0061-Improve-the-Saddle-API-for-Horses.patch diff --git a/patches/api-unmapped/0062-Add-getI18NDisplayName-API.patch b/patches/api/0062-Add-getI18NDisplayName-API.patch similarity index 76% rename from patches/api-unmapped/0062-Add-getI18NDisplayName-API.patch rename to patches/api/0062-Add-getI18NDisplayName-API.patch index e4dde4f260..8af413093e 100644 --- a/patches/api-unmapped/0062-Add-getI18NDisplayName-API.patch +++ b/patches/api/0062-Add-getI18NDisplayName-API.patch @@ -8,13 +8,13 @@ Currently the server only supports the English language. To override this, You must replace the language file embedded in the server jar. diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index 44a858490f4db37f979fd487ed7a5b2b8b7f1a3f..3fd56a95de7d4cbeaf5d8554fbc7127a627cb977 100644 +index 6cc4bad2ecd19f44a680ff03cbfb99d48ea5c337..b1fbb931148a87f29e8b8796b13851d767cc1d68 100644 --- a/src/main/java/org/bukkit/inventory/ItemFactory.java +++ b/src/main/java/org/bukkit/inventory/ItemFactory.java -@@ -172,5 +172,16 @@ public interface ItemFactory { +@@ -160,5 +160,16 @@ public interface ItemFactory { */ @NotNull - ItemStack ensureServerConversions(@NotNull ItemStack item); + net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); + + /** + * Gets the Display name as seen in the Client. @@ -29,12 +29,12 @@ index 44a858490f4db37f979fd487ed7a5b2b8b7f1a3f..3fd56a95de7d4cbeaf5d8554fbc7127a // Paper end } diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 47d8611221967d32b654ddac0fbf0e405ef62352..82bd3e6701dbd7df9f0f8c3801c5ae1baba4eec5 100644 +index a15abec467bac70116a6fc21a300d4930b909f15..de5bcdb7b84acdd5e22500e367df292f35a86e19 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -624,5 +624,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public ItemStack ensureServerConversions() { - return Bukkit.getServer().getItemFactory().ensureServerConversions(this); +@@ -611,5 +611,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + public @NotNull net.kyori.adventure.text.Component displayName() { + return Bukkit.getServer().getItemFactory().displayName(this); } + + /** diff --git a/patches/api-unmapped/0061-ensureServerConversions-API.patch b/patches/api/0063-ensureServerConversions-API.patch similarity index 80% rename from patches/api-unmapped/0061-ensureServerConversions-API.patch rename to patches/api/0063-ensureServerConversions-API.patch index ed64978a06..82e1a82c86 100644 --- a/patches/api-unmapped/0061-ensureServerConversions-API.patch +++ b/patches/api/0063-ensureServerConversions-API.patch @@ -7,13 +7,13 @@ This will take a Bukkit ItemStack and run it through any conversions a server pr to ensure it meets latest minecraft expectations. diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index 6cc4bad2ecd19f44a680ff03cbfb99d48ea5c337..42551f8aa6666a6144815b619327c6d8f3c3776b 100644 +index b1fbb931148a87f29e8b8796b13851d767cc1d68..71e5ee496a947fbd8e3ec579833b157c76b51833 100644 --- a/src/main/java/org/bukkit/inventory/ItemFactory.java +++ b/src/main/java/org/bukkit/inventory/ItemFactory.java -@@ -160,5 +160,17 @@ public interface ItemFactory { +@@ -171,5 +171,17 @@ public interface ItemFactory { */ - @NotNull - net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); + @Nullable + String getI18NDisplayName(@Nullable ItemStack item); + + /** + * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks. @@ -29,7 +29,7 @@ index 6cc4bad2ecd19f44a680ff03cbfb99d48ea5c337..42551f8aa6666a6144815b619327c6d8 // Paper end } diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index a15abec467bac70116a6fc21a300d4930b909f15..f9d226962f16821d07ac80f1bf69cb01a5de2654 100644 +index de5bcdb7b84acdd5e22500e367df292f35a86e19..e8783b0116f4efd5447a5f6f260506000983ffd2 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -536,7 +536,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor @@ -41,11 +41,10 @@ index a15abec467bac70116a6fc21a300d4930b909f15..f9d226962f16821d07ac80f1bf69cb01 } /** -@@ -611,5 +611,18 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public @NotNull net.kyori.adventure.text.Component displayName() { +@@ -612,6 +612,19 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor return Bukkit.getServer().getItemFactory().displayName(this); } -+ + + /** + * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks. + * @@ -58,5 +57,7 @@ index a15abec467bac70116a6fc21a300d4930b909f15..f9d226962f16821d07ac80f1bf69cb01 + public ItemStack ensureServerConversions() { + return Bukkit.getServer().getItemFactory().ensureServerConversions(this); + } - // Paper end - } ++ + /** + * Gets the Display name as seen in the Client. + * Currently the server only supports the English language. To override this, diff --git a/patches/api-unmapped/0064-Make-plugins-list-alphabetical.patch b/patches/api/0064-Make-plugins-list-alphabetical.patch similarity index 100% rename from patches/api-unmapped/0064-Make-plugins-list-alphabetical.patch rename to patches/api/0064-Make-plugins-list-alphabetical.patch diff --git a/patches/api-unmapped/0065-LivingEntity-setKiller.patch b/patches/api/0065-LivingEntity-setKiller.patch similarity index 100% rename from patches/api-unmapped/0065-LivingEntity-setKiller.patch rename to patches/api/0065-LivingEntity-setKiller.patch diff --git a/patches/api-unmapped/0063-ProfileWhitelistVerifyEvent.patch b/patches/api/0066-ProfileWhitelistVerifyEvent.patch similarity index 100% rename from patches/api-unmapped/0063-ProfileWhitelistVerifyEvent.patch rename to patches/api/0066-ProfileWhitelistVerifyEvent.patch diff --git a/patches/api-unmapped/0067-Allow-plugins-to-use-SLF4J-for-logging.patch b/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch similarity index 69% rename from patches/api-unmapped/0067-Allow-plugins-to-use-SLF4J-for-logging.patch rename to patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch index 58225ea7be..0555a52329 100644 --- a/patches/api-unmapped/0067-Allow-plugins-to-use-SLF4J-for-logging.patch +++ b/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch @@ -13,24 +13,18 @@ Expose SLF4J as optional logging API for plugins, so they can use it without having to shade it in the plugin and going through several layers of logging abstraction. -diff --git a/pom.xml b/pom.xml -index 2c757ffb2253748c6a81f9b373290108209b6ff2..8cf6e1f78d4c1ae388bb478700d5dceaab65c4e7 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -144,6 +144,13 @@ - 21.0.1 - provided - -+ -+ -+ org.slf4j -+ slf4j-api -+ 1.7.25 -+ compile -+ - - - junit +diff --git a/build.gradle.kts b/build.gradle.kts +index 9451f8660ec248619383d516df4b95e20e24828a..9657dcb900267cb5cd1ad7a850eb15bc74479314 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -24,6 +24,7 @@ dependencies { + api("net.kyori:adventure-text-serializer-plain") + api("org.ow2.asm:asm:9.0") + api("org.ow2.asm:asm-commons:9.0") ++ api("org.apache.logging.log4j:log4j-api:2.14.1") // Paper + + compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java index febfec6efafd76bb59b4b43aa223af16f73339b4..79890c68f1ad31f951dfdbd9a16dac500ec58c40 100644 --- a/src/main/java/org/bukkit/plugin/Plugin.java diff --git a/patches/api-unmapped/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch b/patches/api/0068-Handle-plugin-prefixes-in-implementation-logging-con.patch similarity index 100% rename from patches/api-unmapped/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch rename to patches/api/0068-Handle-plugin-prefixes-in-implementation-logging-con.patch diff --git a/patches/api/0069-Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/patches/api/0069-Add-workaround-for-plugins-modifying-the-parent-of-t.patch new file mode 100644 index 0000000000..47b6099ab7 --- /dev/null +++ b/patches/api/0069-Add-workaround-for-plugins-modifying-the-parent-of-t.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Minecrell +Date: Thu, 21 Sep 2017 19:41:20 +0200 +Subject: [PATCH] Add workaround for plugins modifying the parent of the plugin + logger + +Essentials uses a custom logger name ("Essentials") instead of the +plugin logger. Log messages are redirected to the plugin logger by +setting the parent of the "Essentials" logger to the plugin logger. + +With our changes, the plugin logger is now also called "Essentials", +resulting in an infinite loop. Make sure plugins can't change the +parent of the plugin logger to avoid this. + +diff --git a/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java +new file mode 100644 +index 0000000000000000000000000000000000000000..76f2cb9cd99cad2a9484eab2becd8c36f1dd91b3 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java +@@ -0,0 +1,41 @@ ++package com.destroystokyo.paper.utils; ++ ++import org.bukkit.plugin.PluginDescriptionFile; ++ ++import java.util.logging.Level; ++import java.util.logging.LogManager; ++import java.util.logging.Logger; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Prevents plugins (e.g. Essentials) from changing the parent of the plugin logger. ++ */ ++public class PaperPluginLogger extends Logger { ++ ++ @NotNull ++ public static Logger getLogger(@NotNull PluginDescriptionFile description) { ++ Logger logger = new PaperPluginLogger(description); ++ if (!LogManager.getLogManager().addLogger(logger)) { ++ // Disable this if it's going to happen across reloads anyways... ++ //logger.log(Level.WARNING, "Could not insert plugin logger - one was already found: {}", LogManager.getLogManager().getLogger(this.getName())); ++ logger = LogManager.getLogManager().getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); ++ } ++ ++ return logger; ++ } ++ ++ private PaperPluginLogger(@NotNull PluginDescriptionFile description) { ++ super(description.getPrefix() != null ? description.getPrefix() : description.getName(), null); ++ } ++ ++ @Override ++ public void setParent(@NotNull Logger parent) { ++ if (getParent() != null) { ++ warning("Ignoring attempt to change parent of plugin logger"); ++ } else { ++ this.log(Level.FINE, "Setting plugin logger parent to {0}", parent); ++ super.setParent(parent); ++ } ++ } ++ ++} +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +index bb2e55e97bf887a28cac7d4f9a0a23960d22cf56..04fa3991f6ce4e9dad804f28fc6c947695857089 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +@@ -42,7 +42,7 @@ public abstract class JavaPlugin extends PluginBase { + private boolean naggable = true; + private FileConfiguration newConfig = null; + private File configFile = null; +- private Logger logger = null; // Paper - PluginLogger -> Logger ++ Logger logger = null; // Paper - PluginLogger -> Logger, package-private + + public JavaPlugin() { + final ClassLoader classLoader = this.getClass().getClassLoader(); +@@ -276,8 +276,11 @@ public abstract class JavaPlugin extends PluginBase { + this.dataFolder = dataFolder; + this.classLoader = classLoader; + this.configFile = new File(dataFolder, "config.yml"); +- // Paper - Handle plugin prefix in implementation +- this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); ++ // Paper start ++ if (this.logger == null) { ++ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(this.description); ++ } ++ // Paper end + } + + /** +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index 13100c688bfccb826b3072aaa92901f8634cf9ab..b9766b9b47547c400ed075f1635bb1461cb5e860 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -44,6 +44,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + private JavaPlugin pluginInit; + private IllegalStateException pluginState; + private final Set seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>()); ++ private java.util.logging.Logger logger; // Paper - add field + + static { + ClassLoader.registerAsParallelCapable(); +@@ -62,6 +63,8 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + this.url = file.toURI().toURL(); + this.libraryLoader = libraryLoader; + ++ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(description); // Paper - Register logger early ++ + try { + Class jarClass; + try { +@@ -222,6 +225,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + pluginState = new IllegalStateException("Initial initialization"); + this.pluginInit = javaPlugin; + ++ javaPlugin.logger = this.logger; // Paper - set logger + javaPlugin.init(loader, loader.server, description, dataFolder, file, this); + } + } diff --git a/patches/server-remapped/0166-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/patches/removed/1.17/0166-Fix-MC-117075-TE-Unload-Lag-Spike.patch similarity index 100% rename from patches/server-remapped/0166-Fix-MC-117075-TE-Unload-Lag-Spike.patch rename to patches/removed/1.17/0166-Fix-MC-117075-TE-Unload-Lag-Spike.patch diff --git a/patches/server-remapped/0165-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/patches/server-remapped/0165-Reset-spawner-timer-when-spawner-event-is-cancelled.patch deleted file mode 100644 index 3476f2d837..0000000000 --- a/patches/server-remapped/0165-Reset-spawner-timer-when-spawner-event-is-cancelled.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:45:19 -0500 -Subject: [PATCH] Reset spawner timer when spawner event is cancelled - - -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 7541155048744a9af2017ec039cf99a246addb0b..4582fc1bb767214241568fbc22b0ee2cbf3322e0 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -161,6 +161,7 @@ public abstract class BaseSpawner { - // Spigot End - } - entity.spawnedViaMobSpawner = true; // Paper -+ flag = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { - Entity vehicle = entity.getVehicle(); -@@ -184,7 +185,7 @@ public abstract class BaseSpawner { - ((Mob) entity).spawnAnim(); - } - -- flag = true; -+ /*flag = true;*/ // Paper - moved up above cancellable event - } - } - } diff --git a/patches/server-remapped/0152-PlayerAttemptPickupItemEvent.patch b/patches/server/0141-PlayerAttemptPickupItemEvent.patch similarity index 88% rename from patches/server-remapped/0152-PlayerAttemptPickupItemEvent.patch rename to patches/server/0141-PlayerAttemptPickupItemEvent.patch index 1c5b10dcee..34d1b804a7 100644 --- a/patches/server-remapped/0152-PlayerAttemptPickupItemEvent.patch +++ b/patches/server/0141-PlayerAttemptPickupItemEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] PlayerAttemptPickupItemEvent diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 72d1e83ac5e4ae3c943ca5ec1058f0d7ad2903cd..de69f7c3c0ee1e74682b0db91bdaae09175690e9 100644 +index d17af2ec8f72bf0cbe5928e7a83c06ba5ad4503d..54025e401eb02fceb47afb182f0ede620ca23a8d 100644 --- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -35,6 +35,7 @@ import net.minecraft.stats.Stats; +@@ -37,6 +37,7 @@ import net.minecraft.stats.Stats; import org.bukkit.event.entity.EntityPickupItemEvent; import org.bukkit.event.player.PlayerPickupItemEvent; // CraftBukkit end @@ -16,7 +16,7 @@ index 72d1e83ac5e4ae3c943ca5ec1058f0d7ad2903cd..de69f7c3c0ee1e74682b0db91bdaae09 public class ItemEntity extends Entity { -@@ -364,6 +365,22 @@ public class ItemEntity extends Entity { +@@ -381,6 +382,22 @@ public class ItemEntity extends Entity { int remaining = i - canHold; boolean flyAtPlayer = false; // Paper diff --git a/patches/server-remapped/0153-Add-UnknownCommandEvent.patch b/patches/server/0142-Add-UnknownCommandEvent.patch similarity index 87% rename from patches/server-remapped/0153-Add-UnknownCommandEvent.patch rename to patches/server/0142-Add-UnknownCommandEvent.patch index 9979b7ace2..59bbfebad4 100644 --- a/patches/server-remapped/0153-Add-UnknownCommandEvent.patch +++ b/patches/server/0142-Add-UnknownCommandEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add UnknownCommandEvent diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 7b2ece40c09ba336a0c2a84321401619801c64c8..b9e39a4c0aea3de96d1774ae0d0d23ff82162c7e 100644 +index dcc1a3856560ab0eb4de45a358e189134adeac17..55444b51e416857a3854a0f1a41f24390f744119 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -790,7 +790,13 @@ public final class CraftServer implements Server { +@@ -792,7 +792,13 @@ public final class CraftServer implements Server { // Spigot start if (!org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty()) { diff --git a/patches/server-remapped/0154-Basic-PlayerProfile-API.patch b/patches/server/0143-Basic-PlayerProfile-API.patch similarity index 89% rename from patches/server-remapped/0154-Basic-PlayerProfile-API.patch rename to patches/server/0143-Basic-PlayerProfile-API.patch index ce8cf66ee0..a7f1053f59 100644 --- a/patches/server-remapped/0154-Basic-PlayerProfile-API.patch +++ b/patches/server/0143-Basic-PlayerProfile-API.patch @@ -7,14 +7,14 @@ Establishes base extension of profile systems for future edits too diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java new file mode 100644 -index 0000000000000000000000000000000000000000..8f559897e408eee8617af0bb77fa4635e07ccdce +index 0000000000000000000000000000000000000000..ef6aab69daa7ab952408b573bff6c6996cbc349a --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java @@ -0,0 +1,303 @@ +package com.destroystokyo.paper.profile; + -+import PlayerProfile; -+import ProfileProperty; ++import com.destroystokyo.paper.profile.PlayerProfile; ++import com.destroystokyo.paper.profile.ProfileProperty; +import com.destroystokyo.paper.PaperConfig; +import com.google.common.base.Charsets; +import com.mojang.authlib.GameProfile; @@ -207,7 +207,7 @@ index 0000000000000000000000000000000000000000..8f559897e408eee8617af0bb77fa4635 + copyProfileProperties(result, this.profile, true); + } + if (this.profile.isComplete()) { -+ server.getProfileCache().saveProfile(this.profile); ++ server.getProfileCache().add(this.profile); + } + } + return profile.isComplete() && (!onlineMode || !textures || hasTextures()); @@ -430,19 +430,18 @@ index 0000000000000000000000000000000000000000..3cdd06d3af7ff94f1fe1a11b9a9275e1 + } +} diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index d29fe67b7d39e368a873368a6be16042429e9209..68c3f069f8f832ab3d146748348aded69b5ad823 100644 +index 80f8d6ce6dd717d4b37b78539c65b6ac814ec93d..966f0951832040c38fdd2caa58f7eae372aa0f59 100644 --- a/src/main/java/net/minecraft/server/MCUtil.java +++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -1,6 +1,8 @@ +@@ -1,5 +1,7 @@ package net.minecraft.server; - import com.destroystokyo.paper.block.TargetBlockInfo; +import com.destroystokyo.paper.profile.CraftPlayerProfile; +import com.destroystokyo.paper.profile.PlayerProfile; import com.google.common.util.concurrent.ThreadFactoryBuilder; import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; import net.minecraft.core.BlockPos; -@@ -11,6 +13,7 @@ import net.minecraft.world.level.ChunkPos; +@@ -10,6 +12,7 @@ import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ClipContext; import net.minecraft.world.level.Level; import org.apache.commons.lang.exception.ExceptionUtils; @@ -450,7 +449,7 @@ index d29fe67b7d39e368a873368a6be16042429e9209..68c3f069f8f832ab3d146748348aded6 import org.bukkit.Location; import org.bukkit.block.BlockFace; import org.bukkit.craftbukkit.CraftWorld; -@@ -345,6 +348,10 @@ public final class MCUtil { +@@ -344,6 +347,10 @@ public final class MCUtil { return run.get(); } @@ -462,10 +461,10 @@ index d29fe67b7d39e368a873368a6be16042429e9209..68c3f069f8f832ab3d146748348aded6 * Calculates distance between 2 entities * @param e1 diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 5d83a8d4c69144219219877c521c364d912d2452..2bfc54941ec34c75c2d59bda748c75730b9951f7 100644 +index c8385460701395cb5c65fba41335469ffb2d9b9a..fb0b3c5770f66cc3590f5ac4e690a33cb6179be3 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java -@@ -124,7 +124,7 @@ public class Main { +@@ -130,7 +130,7 @@ public class Main { } File file = (File) optionset.valueOf("universe"); // CraftBukkit @@ -475,33 +474,24 @@ index 5d83a8d4c69144219219877c521c364d912d2452..2bfc54941ec34c75c2d59bda748c7573 GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName())); diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index e8af352f813a5015d216fc590190ae8fdb03f77d..941b7e356c377fd8ad4e27409cd74c0046878396 100644 +index 3eb4bee81a8543cc06b9d5898f5f6c0e9dbbf554..8ea7d9a2070074a45d3276b8d2abac6285edbbdb 100644 --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java +++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java -@@ -45,7 +45,7 @@ public class GameProfileCache { - - private static final Logger LOGGER = LogManager.getLogger(); - private static boolean usesAuthentication; -- private final Map profilesByName = Maps.newConcurrentMap(); -+ private final Map profilesByName = Maps.newConcurrentMap();private final Map nameCache = profilesByName; // Paper - OBFHELPER // Paper - private final Map profilesByUUID = Maps.newConcurrentMap(); - private final GameProfileRepository profileRepository; - private final Gson gson = (new GsonBuilder()).create(); -@@ -110,6 +110,7 @@ public class GameProfileCache { +@@ -118,6 +118,7 @@ public class GameProfileCache { return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper } -+ public void saveProfile(GameProfile gameprofile) { add(gameprofile); } // Paper - OBFHELPER - public synchronized void add(GameProfile gameprofile) { // Paper - synchronize ++ @Deprecated public void saveProfile(GameProfile gameprofile) { add(gameprofile); } // Paper - OBFHELPER + public synchronized void add(GameProfile profile) { // Paper - synchronize Calendar calendar = Calendar.getInstance(); -@@ -159,6 +160,13 @@ public class GameProfileCache { - return gameprofile; +@@ -190,6 +191,13 @@ public class GameProfileCache { + } } + // Paper start + @Nullable public GameProfile getProfileIfCached(String name) { -+ GameProfileCache.GameProfileInfo entry = this.nameCache.get(name.toLowerCase(Locale.ROOT)); ++ GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT)); + return entry == null ? null : entry.getProfile(); + } + // Paper end @@ -509,20 +499,11 @@ index e8af352f813a5015d216fc590190ae8fdb03f77d..941b7e356c377fd8ad4e27409cd74c00 @Nullable public GameProfile get(UUID uuid) { GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); -@@ -341,7 +349,7 @@ public class GameProfileCache { - - static class GameProfileInfo { - -- private final GameProfile profile; -+ private final GameProfile profile;public GameProfile getProfile() { return profile; } // Paper - OBFHELPER - private final Date expirationDate; - private volatile long lastAccess; - diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index b9e39a4c0aea3de96d1774ae0d0d23ff82162c7e..df68599520189e2699c8521d6c6ab7235612af33 100644 +index 55444b51e416857a3854a0f1a41f24390f744119..0be8b1727ce57ec0905315922e1d83104a936cd0 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -223,6 +223,9 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; +@@ -226,6 +226,9 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; import net.md_5.bungee.api.chat.BaseComponent; // Spigot @@ -532,7 +513,7 @@ index b9e39a4c0aea3de96d1774ae0d0d23ff82162c7e..df68599520189e2699c8521d6c6ab723 public final class CraftServer implements Server { private final String serverName = "Paper"; // Paper private final String serverVersion; -@@ -2315,5 +2318,24 @@ public final class CraftServer implements Server { +@@ -2314,5 +2317,24 @@ public final class CraftServer implements Server { public boolean suggestPlayerNamesWhenNullTabCompletions() { return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; } @@ -558,7 +539,7 @@ index b9e39a4c0aea3de96d1774ae0d0d23ff82162c7e..df68599520189e2699c8521d6c6ab723 // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index 313ddd6b64e395a8caab77b3da005e52006ab2d7..750661540f55d3c59119dcc909e706e571a2123b 100644 +index b19d50bbe6c944ff66230ac013178bd036a438c8..5e345224e698bd80133dc194385c033369a60a33 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java @@ -80,6 +80,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { diff --git a/patches/server-remapped/0155-Shoulder-Entities-Release-API.patch b/patches/server/0144-Shoulder-Entities-Release-API.patch similarity index 89% rename from patches/server-remapped/0155-Shoulder-Entities-Release-API.patch rename to patches/server/0144-Shoulder-Entities-Release-API.patch index e71eeed527..788c702193 100644 --- a/patches/server-remapped/0155-Shoulder-Entities-Release-API.patch +++ b/patches/server/0144-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 ae10c531ae69eaf6b78a342dcedb89c39fd8dbcc..3205bc2fb6c9031be68ff46dfca927e681163fa8 100644 +index 73277b04a45444edce02cce3e033741ebaf2ad0c..075bbc75d2e33be3a42c6c3ec279eeeba6408333 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1877,20 +1877,44 @@ public abstract class Player extends LivingEntity { +@@ -1953,20 +1953,44 @@ public abstract class Player extends LivingEntity { } @@ -58,11 +58,11 @@ index ae10c531ae69eaf6b78a342dcedb89c39fd8dbcc..3205bc2fb6c9031be68ff46dfca927e6 @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 b5c0f3d91cf451a972f0cf293db03a306073c493..c62d01719f21762aa10294815ab88e450e4dce3f 100644 +index d27a7ac64d1daf85319ab0069b9196f1958f6f46..6c404878e58f68c9ac86a1771c23e528f3817e32 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -494,6 +494,32 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - getHandle().getCooldowns().addCooldown(CraftMagicNumbers.getItem(material), ticks); + this.getHandle().getCooldowns().addCooldown(CraftMagicNumbers.getItem(material), ticks); } + // Paper start @@ -93,4 +93,4 @@ index b5c0f3d91cf451a972f0cf293db03a306073c493..c62d01719f21762aa10294815ab88e45 + @Override public boolean discoverRecipe(NamespacedKey recipe) { - return discoverRecipes(Arrays.asList(recipe)) != 0; + return this.discoverRecipes(Arrays.asList(recipe)) != 0; diff --git a/patches/server-remapped/0156-Profile-Lookup-Events.patch b/patches/server/0145-Profile-Lookup-Events.patch similarity index 100% rename from patches/server-remapped/0156-Profile-Lookup-Events.patch rename to patches/server/0145-Profile-Lookup-Events.patch diff --git a/patches/server-remapped/0157-Block-player-logins-during-server-shutdown.patch b/patches/server/0146-Block-player-logins-during-server-shutdown.patch similarity index 87% rename from patches/server-remapped/0157-Block-player-logins-during-server-shutdown.patch rename to patches/server/0146-Block-player-logins-during-server-shutdown.patch index f43b561da9..588fe4a932 100644 --- a/patches/server-remapped/0157-Block-player-logins-during-server-shutdown.patch +++ b/patches/server/0146-Block-player-logins-during-server-shutdown.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Block player logins during server shutdown diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index e3c1460c580ea348ee6d436018244441a5a1206e..fca291c34c67d552590320c6e6e9c08e21d19fa8 100644 +index 3e57eb2e50f94085fd23b54a54d4cf7a0b7919c7..29555323bcc7d7faa3af6ed4507a1646714ab84a 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -66,6 +66,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -69,6 +69,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener } public void tick() { diff --git a/patches/server-remapped/0158-Entity-fromMobSpawner.patch b/patches/server/0147-Entity-fromMobSpawner.patch similarity index 60% rename from patches/server-remapped/0158-Entity-fromMobSpawner.patch rename to patches/server/0147-Entity-fromMobSpawner.patch index 10fa81134b..389189b26f 100644 --- a/patches/server-remapped/0158-Entity-fromMobSpawner.patch +++ b/patches/server/0147-Entity-fromMobSpawner.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Entity#fromMobSpawner() diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a017fa55002d6674124befa3f6e81eb70c9ce8f7..7e70bae5bc54ad17980789fa965fd539a7f193ea 100644 +index 0204bde9802429aca5470c235cb10232e5c8f58a..bc15a3d8f3807caee357d55952b51326db51253f 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -267,6 +267,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -301,6 +301,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); public final boolean defaultActivationState; public long activatedTick = Integer.MIN_VALUE; @@ -16,43 +16,43 @@ index a017fa55002d6674124befa3f6e81eb70c9ce8f7..7e70bae5bc54ad17980789fa965fd539 protected int numCollisions = 0; // Paper public void inactiveTick() { } // Spigot end -@@ -1665,6 +1666,10 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); - tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); +@@ -1840,6 +1841,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + nbt.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); + nbt.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ())); } + // Save entity's from mob spawner status + if (spawnedViaMobSpawner) { -+ tag.putBoolean("Paper.FromMobSpawner", true); ++ nbt.putBoolean("Paper.FromMobSpawner", true); + } // Paper end - return tag; + return nbt; } catch (Throwable throwable) { -@@ -1797,6 +1802,8 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1976,6 +1981,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); } + -+ spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status // Paper end } catch (Throwable throwable) { diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index ed631d5bfba5d2543e8eed017a7c484ad3ddb453..7541155048744a9af2017ec039cf99a246addb0b 100644 +index 037dafb59e54047d1d54474c44897d35b8f46c98..59996bb75dc050f51cadb31ad57c25eb46485f52 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java @@ -160,6 +160,7 @@ public abstract class BaseSpawner { - } - // Spigot End + if (this.nextSpawnData.getTag().size() == 1 && this.nextSpawnData.getTag().contains("id", 8)) { + ((Mob) entity).finalizeSpawn(world, world.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.SPAWNER, (SpawnGroupData) null, (CompoundTag) null); } -+ entity.spawnedViaMobSpawner = true; // Paper ++ entity.spawnedViaMobSpawner = true; // Paper // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { - Entity vehicle = entity.getVehicle(); + if (entityinsentient.level.spigotConfig.nerfSpawnerMobs) { + entityinsentient.aware = false; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index b028946de7c8f52091635fe154c816453f1ddc93..ecb5f5ca547930f91602d539e541964cd9f10287 100644 +index 271b4e3354c3885e38ae0c547edba48bf06f1e19..1fd891b53c54153c28d636b2679b4a083510ba3c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1100,5 +1100,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1133,5 +1133,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { Location origin = getHandle().origin; return origin == null ? null : origin.clone(); } diff --git a/patches/server-remapped/0159-Improve-the-Saddle-API-for-Horses.patch b/patches/server/0148-Improve-the-Saddle-API-for-Horses.patch similarity index 94% rename from patches/server-remapped/0159-Improve-the-Saddle-API-for-Horses.patch rename to patches/server/0148-Improve-the-Saddle-API-for-Horses.patch index 85d5e4f330..4f3f3977fc 100644 --- a/patches/server-remapped/0159-Improve-the-Saddle-API-for-Horses.patch +++ b/patches/server/0148-Improve-the-Saddle-API-for-Horses.patch @@ -7,7 +7,7 @@ Not all horses with Saddles have armor. This lets us break up the horses with sa and access their saddle state separately from an interface shared with Armor. diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -index 116553ea587ab5ff3bc8a1530f51cd6efb7ae8ca..6136b3322a340d506ce744bcd15f71a158e46ad1 100644 +index 6f473dbf949552afd288382b36223ea036eaa857..27a1ca43792644fc239af81dea5510f25d3328e9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java @@ -5,6 +5,7 @@ import net.minecraft.world.entity.ai.attributes.Attributes; @@ -22,7 +22,7 @@ index 116553ea587ab5ff3bc8a1530f51cd6efb7ae8ca..6136b3322a340d506ce744bcd15f71a1 @Override public AbstractHorseInventory getInventory() { -- return new CraftInventoryAbstractHorse(getHandle().inventory); +- return new CraftInventoryAbstractHorse(this.getHandle().inventory); + return new CraftSaddledInventory(getHandle().inventory); } } diff --git a/patches/server-remapped/0160-Implement-ensureServerConversions-API.patch b/patches/server/0149-Implement-ensureServerConversions-API.patch similarity index 87% rename from patches/server-remapped/0160-Implement-ensureServerConversions-API.patch rename to patches/server/0149-Implement-ensureServerConversions-API.patch index bc3d68abd4..72f70ceb8c 100644 --- a/patches/server-remapped/0160-Implement-ensureServerConversions-API.patch +++ b/patches/server/0149-Implement-ensureServerConversions-API.patch @@ -7,10 +7,10 @@ This will take a Bukkit ItemStack and run it through any conversions a server pr to ensure it meets latest minecraft expectations. diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 32fa5ca0df07466e40817341d85d359b282f3078..41c8bbf93039add43695a52d2bfc0c2cef88463d 100644 +index 921d838afc5b7ae47a9ee81b7ae4450543a32d98..0bf6c27fdcc2a4342c68441670244cabf40f8e7e 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -346,5 +346,11 @@ public final class CraftItemFactory implements ItemFactory { +@@ -349,5 +349,11 @@ public final class CraftItemFactory implements ItemFactory { public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); } diff --git a/patches/server-remapped/0161-Implement-getI18NDisplayName.patch b/patches/server/0150-Implement-getI18NDisplayName.patch similarity index 59% rename from patches/server-remapped/0161-Implement-getI18NDisplayName.patch rename to patches/server/0150-Implement-getI18NDisplayName.patch index c27fb916c9..a8882d517d 100644 --- a/patches/server-remapped/0161-Implement-getI18NDisplayName.patch +++ b/patches/server/0150-Implement-getI18NDisplayName.patch @@ -8,36 +8,22 @@ Currently the server only supports the English language. To override this, You must replace the language file embedded in the server jar. diff --git a/src/main/java/net/minecraft/locale/Language.java b/src/main/java/net/minecraft/locale/Language.java -index 8a0d2e510aee160ec3a817fd72c23bc9dfeb6287..756b78a7dc3d3e76dc0a37375b304db0b6ecf684 100644 +index f06452538f45e2430611aad54d060e040b32bb58..67f5448d0a03c1e018f71bdb76610a85867cc0b8 100644 --- a/src/main/java/net/minecraft/locale/Language.java +++ b/src/main/java/net/minecraft/locale/Language.java -@@ -30,7 +30,7 @@ public abstract class Language { - - private static Language loadDefault() { - Builder builder = ImmutableMap.builder(); -- BiConsumer biconsumer = builder::put; -+ BiConsumer biconsumer = builder::put; // Paper - decompile fix - - try { - InputStream inputstream = Language.class.getResourceAsStream("/assets/minecraft/lang/en_us.json"); -@@ -87,10 +87,12 @@ public abstract class Language { - +@@ -107,6 +107,7 @@ public abstract class Language { + instance = language; } -+ public static Language getInstance() { return getInstance(); } // Paper - OBFHELPER - public static Language getInstance() { - return Language.instance; - } - -+ public String translateKey(String key) { return getOrDefault(key); } // Paper - OBFHELPER ++ @Deprecated public String translateKey(String key) { return getOrDefault(key); } // Paper - OBFHELPER public abstract String getOrDefault(String key); public abstract boolean has(String key); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 41c8bbf93039add43695a52d2bfc0c2cef88463d..746755f76ae177b2eeccf66f8cd95e6ffd5acad9 100644 +index 0bf6c27fdcc2a4342c68441670244cabf40f8e7e..6ec39de514ceed7e5ffe9a8dc94c2ffd2902cd98 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -352,5 +352,18 @@ public final class CraftItemFactory implements ItemFactory { +@@ -355,5 +355,18 @@ public final class CraftItemFactory implements ItemFactory { public ItemStack ensureServerConversions(ItemStack item) { return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); } @@ -52,7 +38,7 @@ index 41c8bbf93039add43695a52d2bfc0c2cef88463d..746755f76ae177b2eeccf66f8cd95e6f + nms = CraftItemStack.asNMSCopy(item); + } + -+ return nms != null ? net.minecraft.locale.Language.getInstance().translateKey(nms.getItem().getDescriptionId()) : null; ++ return nms != null ? net.minecraft.locale.Language.getInstance().getOrDefault(nms.getItem().getDescriptionId()) : null; + } // Paper end } diff --git a/patches/server-remapped/0162-ProfileWhitelistVerifyEvent.patch b/patches/server/0151-ProfileWhitelistVerifyEvent.patch similarity index 85% rename from patches/server-remapped/0162-ProfileWhitelistVerifyEvent.patch rename to patches/server/0151-ProfileWhitelistVerifyEvent.patch index 5051a6a195..83ccd291bb 100644 --- a/patches/server-remapped/0162-ProfileWhitelistVerifyEvent.patch +++ b/patches/server/0151-ProfileWhitelistVerifyEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] ProfileWhitelistVerifyEvent diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7d6256f65d369fcbcfe1fffe7ac264788a38540b..ae60b233c4d56a4964b388f96e9cc66410774e8d 100644 +index bf6c3ac7ae37067f345568fb6656cf6b4d864be2..429e6c7f9a5e5355e26deeae1e89ffea7439cd96 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -611,9 +611,9 @@ public abstract class PlayerList { +@@ -607,9 +607,9 @@ public abstract class PlayerList { // return chatmessage; if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure @@ -18,10 +18,10 @@ index 7d6256f65d369fcbcfe1fffe7ac264788a38540b..ae60b233c4d56a4964b388f96e9cc664 + } else if (!this.isWhitelisted(gameprofile, event)) { // Paper + //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper + //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted - } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { + } else if (this.getIpBans().isBanned(socketaddress) && !this.getIpBans().get(socketaddress).hasExpired()) { IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); -@@ -1005,9 +1005,25 @@ public abstract class PlayerList { +@@ -989,9 +989,25 @@ public abstract class PlayerList { this.server.getCommands().sendCommands(player); } @@ -34,7 +34,7 @@ index 7d6256f65d369fcbcfe1fffe7ac264788a38540b..ae60b233c4d56a4964b388f96e9cc664 + boolean isOp = this.ops.contains(gameprofile); + boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile); + final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; -+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); ++ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(net.minecraft.server.MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); + event.callEvent(); + if (!event.isWhitelisted()) { + if (loginEvent != null) { diff --git a/patches/server-remapped/0163-Fix-this-stupid-bullshit.patch b/patches/server/0152-Fix-this-stupid-bullshit.patch similarity index 88% rename from patches/server-remapped/0163-Fix-this-stupid-bullshit.patch rename to patches/server/0152-Fix-this-stupid-bullshit.patch index 8eacc81f8c..a666a1f647 100644 --- a/patches/server-remapped/0163-Fix-this-stupid-bullshit.patch +++ b/patches/server/0152-Fix-this-stupid-bullshit.patch @@ -9,12 +9,12 @@ modified in order to prevent merge conflicts when Spigot changes/disables the wa and to provide some level of hint without being disruptive. diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 60d9980ccca6f1ac55b70f7684b917ddceac380a..808a7688ed81bdfef623ee0a151ff8f94df2a3d7 100644 +index b4bcd34123968b3930bb330f7c2abd9b5518fa31..f68d44721c91c20a7e4abffe26dabff8b5d2c3ce 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -224,10 +224,12 @@ public class Main { +@@ -228,10 +228,12 @@ public class Main { Calendar deadline = Calendar.getInstance(); - deadline.add(Calendar.DAY_OF_YEAR, -28); + deadline.add(Calendar.DAY_OF_YEAR, -3); 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-remapped/0168-LivingEntity-setKiller.patch b/patches/server/0153-LivingEntity-setKiller.patch similarity index 82% rename from patches/server-remapped/0168-LivingEntity-setKiller.patch rename to patches/server/0153-LivingEntity-setKiller.patch index fdb6acae74..e6db1422e6 100644 --- a/patches/server-remapped/0168-LivingEntity-setKiller.patch +++ b/patches/server/0153-LivingEntity-setKiller.patch @@ -5,10 +5,10 @@ Subject: [PATCH] LivingEntity#setKiller diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index c1786fcabeaee5732e9197db04268c5c4e164339..d6b4fabd232958ae1fd5405c7129551951cd7765 100644 +index f0357f9d7b6a39bbdf6486a9d35d890942cc5e4c..89913edf98d65f08f379d0d201f9963c23573478 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -177,7 +177,7 @@ public abstract class LivingEntity extends Entity { +@@ -207,7 +207,7 @@ public abstract class LivingEntity extends Entity { public float flyingSpeed; @Nullable public net.minecraft.world.entity.player.Player lastHurtByPlayer; @@ -18,7 +18,7 @@ index c1786fcabeaee5732e9197db04268c5c4e164339..d6b4fabd232958ae1fd5405c71295519 protected int noActionTime; protected float oRun; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index d8cd88d62f9abfc7960c187dd74239f61267ca57..006f4c71bbcda61b55815e7ceab91731ab062da0 100644 +index ea94dc9a3b8bd3da5f8ccbeb216384723db668aa..4e9565def5a28a7391f8f541d066c2981d0bbc92 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -8,6 +8,7 @@ import java.util.Iterator; @@ -30,7 +30,7 @@ index d8cd88d62f9abfc7960c187dd74239f61267ca57..006f4c71bbcda61b55815e7ceab91731 import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.effect.MobEffect; @@ -332,6 +333,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().lastHurtByPlayer == null ? null : (Player) getHandle().lastHurtByPlayer.getBukkitEntity(); + return this.getHandle().lastHurtByPlayer == null ? null : (Player) this.getHandle().lastHurtByPlayer.getBukkitEntity(); } + // Paper start @@ -45,4 +45,4 @@ index d8cd88d62f9abfc7960c187dd74239f61267ca57..006f4c71bbcda61b55815e7ceab91731 + @Override public boolean addPotionEffect(PotionEffect effect) { - return addPotionEffect(effect, false); + return this.addPotionEffect(effect, false); diff --git a/patches/server-remapped/0164-Ocelot-despawns-should-honor-nametags-and-leash.patch b/patches/server/0154-Ocelot-despawns-should-honor-nametags-and-leash.patch similarity index 85% rename from patches/server-remapped/0164-Ocelot-despawns-should-honor-nametags-and-leash.patch rename to patches/server/0154-Ocelot-despawns-should-honor-nametags-and-leash.patch index 07571c80e4..d194c656d3 100644 --- a/patches/server-remapped/0164-Ocelot-despawns-should-honor-nametags-and-leash.patch +++ b/patches/server/0154-Ocelot-despawns-should-honor-nametags-and-leash.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Ocelot despawns should honor nametags and leash diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java -index 1b820ca48845cbe4a668cc31582c2ddf6d50c96a..142025cfb75b24dc6df8160f4922086404efa6a7 100644 +index 38ddb72b53fcf0d6a9331d23b11572e9f85e70e3..8104ac0f77e8e94f294b82f7badefccd72419223 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java +++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java -@@ -128,7 +128,7 @@ public class Ocelot extends Animal { +@@ -133,7 +133,7 @@ public class Ocelot extends Animal { @Override public boolean removeWhenFarAway(double distanceSquared) { diff --git a/patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch new file mode 100644 index 0000000000..c0bec5fce6 --- /dev/null +++ b/patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 31 Jul 2017 01:45:19 -0500 +Subject: [PATCH] Reset spawner timer when spawner event is cancelled + + +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 59996bb75dc050f51cadb31ad57c25eb46485f52..a3d829eb2e43f51db0e1282ff32039bca574a752 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -167,6 +167,7 @@ public abstract class BaseSpawner { + } + // Spigot End + } ++ flag = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { + Entity vehicle = entity.getVehicle(); +@@ -190,7 +191,7 @@ public abstract class BaseSpawner { + ((Mob) entity).spawnAnim(); + } + +- flag = true; ++ //flag = true; // Paper - moved up above cancellable event + } + } + diff --git a/patches/server-remapped/0167-Allow-specifying-a-custom-authentication-servers-dow.patch b/patches/server/0156-Allow-specifying-a-custom-authentication-servers-dow.patch similarity index 94% rename from patches/server-remapped/0167-Allow-specifying-a-custom-authentication-servers-dow.patch rename to patches/server/0156-Allow-specifying-a-custom-authentication-servers-dow.patch index 766b536512..c3a07caf8d 100644 --- a/patches/server-remapped/0167-Allow-specifying-a-custom-authentication-servers-dow.patch +++ b/patches/server/0156-Allow-specifying-a-custom-authentication-servers-dow.patch @@ -27,10 +27,10 @@ index 48319aaf1c525c6fb7bdee5c2f570a0d056d4eae..52954fc3bf932cfc9d5ce63e3d3cace3 + } } diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index fca291c34c67d552590320c6e6e9c08e21d19fa8..4b91699ddfa2ee298af5ba25447a85751facf4a4 100644 +index 29555323bcc7d7faa3af6ed4507a1646714ab84a..700ab378f43b3841c82b7aadc1c3818dc0621a58 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -275,6 +275,10 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -297,6 +297,10 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener ServerLoginPacketListenerImpl.this.gameProfile = ServerLoginPacketListenerImpl.this.createFakeProfile(gameprofile); ServerLoginPacketListenerImpl.this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT; } else { From 88bc74ec42dd81d5284167435458cead27991ff3 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Sat, 12 Jun 2021 14:09:11 +0200 Subject: [PATCH 045/226] Fix patch, fix .gitattributes file name --- .giattributes => .gitattributes | 0 ...or-plugins-modifying-the-parent-of-t.patch | 117 ------------------ .../server/0147-Entity-fromMobSpawner.patch | 16 +-- ...imer-when-spawner-event-is-cancelled.patch | 12 +- 4 files changed, 10 insertions(+), 135 deletions(-) rename .giattributes => .gitattributes (100%) delete mode 100644 patches/api-unmapped/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch diff --git a/.giattributes b/.gitattributes similarity index 100% rename from .giattributes rename to .gitattributes diff --git a/patches/api-unmapped/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/patches/api-unmapped/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch deleted file mode 100644 index f0cce6b67a..0000000000 --- a/patches/api-unmapped/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Thu, 21 Sep 2017 19:41:20 +0200 -Subject: [PATCH] Add workaround for plugins modifying the parent of the plugin - logger - -Essentials uses a custom logger name ("Essentials") instead of the -plugin logger. Log messages are redirected to the plugin logger by -setting the parent of the "Essentials" logger to the plugin logger. - -With our changes, the plugin logger is now also called "Essentials", -resulting in an infinite loop. Make sure plugins can't change the -parent of the plugin logger to avoid this. - -diff --git a/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java -new file mode 100644 -index 0000000000000000000000000000000000000000..76f2cb9cd99cad2a9484eab2becd8c36f1dd91b3 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.utils; -+ -+import org.bukkit.plugin.PluginDescriptionFile; -+ -+import java.util.logging.Level; -+import java.util.logging.LogManager; -+import java.util.logging.Logger; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Prevents plugins (e.g. Essentials) from changing the parent of the plugin logger. -+ */ -+public class PaperPluginLogger extends Logger { -+ -+ @NotNull -+ public static Logger getLogger(@NotNull PluginDescriptionFile description) { -+ Logger logger = new PaperPluginLogger(description); -+ if (!LogManager.getLogManager().addLogger(logger)) { -+ // Disable this if it's going to happen across reloads anyways... -+ //logger.log(Level.WARNING, "Could not insert plugin logger - one was already found: {}", LogManager.getLogManager().getLogger(this.getName())); -+ logger = LogManager.getLogManager().getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); -+ } -+ -+ return logger; -+ } -+ -+ private PaperPluginLogger(@NotNull PluginDescriptionFile description) { -+ super(description.getPrefix() != null ? description.getPrefix() : description.getName(), null); -+ } -+ -+ @Override -+ public void setParent(@NotNull Logger parent) { -+ if (getParent() != null) { -+ warning("Ignoring attempt to change parent of plugin logger"); -+ } else { -+ this.log(Level.FINE, "Setting plugin logger parent to {0}", parent); -+ super.setParent(parent); -+ } -+ } -+ -+} -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -index bb2e55e97bf887a28cac7d4f9a0a23960d22cf56..04fa3991f6ce4e9dad804f28fc6c947695857089 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -@@ -42,7 +42,7 @@ public abstract class JavaPlugin extends PluginBase { - private boolean naggable = true; - private FileConfiguration newConfig = null; - private File configFile = null; -- private Logger logger = null; // Paper - PluginLogger -> Logger -+ Logger logger = null; // Paper - PluginLogger -> Logger, package-private - - public JavaPlugin() { - final ClassLoader classLoader = this.getClass().getClassLoader(); -@@ -276,8 +276,11 @@ public abstract class JavaPlugin extends PluginBase { - this.dataFolder = dataFolder; - this.classLoader = classLoader; - this.configFile = new File(dataFolder, "config.yml"); -- // Paper - Handle plugin prefix in implementation -- this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); -+ // Paper start -+ if (this.logger == null) { -+ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(this.description); -+ } -+ // Paper end - } - - /** -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 13100c688bfccb826b3072aaa92901f8634cf9ab..b9766b9b47547c400ed075f1635bb1461cb5e860 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -44,6 +44,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - private JavaPlugin pluginInit; - private IllegalStateException pluginState; - private final Set seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>()); -+ private java.util.logging.Logger logger; // Paper - add field - - static { - ClassLoader.registerAsParallelCapable(); -@@ -62,6 +63,8 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - this.url = file.toURI().toURL(); - this.libraryLoader = libraryLoader; - -+ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(description); // Paper - Register logger early -+ - try { - Class jarClass; - try { -@@ -222,6 +225,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - pluginState = new IllegalStateException("Initial initialization"); - this.pluginInit = javaPlugin; - -+ javaPlugin.logger = this.logger; // Paper - set logger - javaPlugin.init(loader, loader.server, description, dataFolder, file, this); - } - } diff --git a/patches/server/0147-Entity-fromMobSpawner.patch b/patches/server/0147-Entity-fromMobSpawner.patch index 389189b26f..8ae834209b 100644 --- a/patches/server/0147-Entity-fromMobSpawner.patch +++ b/patches/server/0147-Entity-fromMobSpawner.patch @@ -37,17 +37,17 @@ index 0204bde9802429aca5470c235cb10232e5c8f58a..bc15a3d8f3807caee357d55952b51326 } catch (Throwable throwable) { diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 037dafb59e54047d1d54474c44897d35b8f46c98..59996bb75dc050f51cadb31ad57c25eb46485f52 100644 +index 037dafb59e54047d1d54474c44897d35b8f46c98..e310c1eb1108780bcff4d7ba9d49cefa2926287c 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -160,6 +160,7 @@ public abstract class BaseSpawner { - if (this.nextSpawnData.getTag().size() == 1 && this.nextSpawnData.getTag().contains("id", 8)) { - ((Mob) entity).finalizeSpawn(world, world.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.SPAWNER, (SpawnGroupData) null, (CompoundTag) null); +@@ -166,6 +166,7 @@ public abstract class BaseSpawner { } -+ entity.spawnedViaMobSpawner = true; // Paper - // Spigot Start - if (entityinsentient.level.spigotConfig.nerfSpawnerMobs) { - entityinsentient.aware = false; + // Spigot End + } ++ entity.spawnedViaMobSpawner = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { + Entity vehicle = entity.getVehicle(); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java index 271b4e3354c3885e38ae0c547edba48bf06f1e19..1fd891b53c54153c28d636b2679b4a083510ba3c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java diff --git a/patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch index c0bec5fce6..65b65ad963 100644 --- a/patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch +++ b/patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch @@ -5,18 +5,10 @@ Subject: [PATCH] Reset spawner timer when spawner event is cancelled diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 59996bb75dc050f51cadb31ad57c25eb46485f52..a3d829eb2e43f51db0e1282ff32039bca574a752 100644 +index e310c1eb1108780bcff4d7ba9d49cefa2926287c..e3a69ed5ac791d8afb9c5beb924f9cf99dc0b410 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -167,6 +167,7 @@ public abstract class BaseSpawner { - } - // Spigot End - } -+ flag = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { - Entity vehicle = entity.getVehicle(); -@@ -190,7 +191,7 @@ public abstract class BaseSpawner { +@@ -190,7 +190,7 @@ public abstract class BaseSpawner { ((Mob) entity).spawnAnim(); } From 8125b3f1be6c191bd8b443679b2ecfda1b0ac286 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Sat, 12 Jun 2021 14:58:17 +0200 Subject: [PATCH 046/226] More more more work --- UPDATE_NOTES.md | 14 -------- .../0069-Add-PlayerJumpEvent.patch | 0 ...r-plugins-modifying-the-parent-of-t.patch} | 0 ...t-protocol-version-and-virtual-host.patch} | 2 +- ...imer-when-spawner-event-is-cancelled.patch | 12 +++++-- ...-prefixes-using-Log4J-configuration.patch} | 31 +++++++++++----- ...-Log4J-Configuration-Plugin-Loggers.patch} | 0 .../0159-Add-PlayerJumpEvent.patch} | 8 ++--- ...-handle-PacketPlayInKeepAlive-async.patch} | 6 ++-- ...t-protocol-version-and-virtual-host.patch} | 26 ++++---------- ...t-serverside-behavior-of-keepalives.patch} | 36 ++++++++++--------- ...Effects-only-to-players-who-can-see.patch} | 14 ++++---- 12 files changed, 73 insertions(+), 76 deletions(-) delete mode 100644 UPDATE_NOTES.md rename patches/{api-unmapped => api}/0069-Add-PlayerJumpEvent.patch (100%) rename patches/api/{0069-Add-workaround-for-plugins-modifying-the-parent-of-t.patch => 0070-Add-workaround-for-plugins-modifying-the-parent-of-t.patch} (100%) rename patches/{api-unmapped/0070-Expose-client-protocol-version-and-virtual-host.patch => api/0071-Expose-client-protocol-version-and-virtual-host.patch} (96%) rename patches/{server-remapped/0169-Handle-plugin-prefixes-using-Log4J-configuration.patch => server/0157-Handle-plugin-prefixes-using-Log4J-configuration.patch} (73%) rename patches/{server-remapped/0170-Improve-Log4J-Configuration-Plugin-Loggers.patch => server/0158-Improve-Log4J-Configuration-Plugin-Loggers.patch} (100%) rename patches/{server-remapped/0171-Add-PlayerJumpEvent.patch => server/0159-Add-PlayerJumpEvent.patch} (89%) rename patches/{server-remapped/0172-handle-PacketPlayInKeepAlive-async.patch => server/0160-handle-PacketPlayInKeepAlive-async.patch} (88%) rename patches/{server-remapped/0173-Expose-client-protocol-version-and-virtual-host.patch => server/0161-Expose-client-protocol-version-and-virtual-host.patch} (74%) rename patches/{server-remapped/0174-revert-serverside-behavior-of-keepalives.patch => server/0162-revert-serverside-behavior-of-keepalives.patch} (75%) rename patches/{server-remapped/0175-Send-attack-SoundEffects-only-to-players-who-can-see.patch => server/0163-Send-attack-SoundEffects-only-to-players-who-can-see.patch} (91%) diff --git a/UPDATE_NOTES.md b/UPDATE_NOTES.md deleted file mode 100644 index 23c915e195..0000000000 --- a/UPDATE_NOTES.md +++ /dev/null @@ -1,14 +0,0 @@ -# Shit to check - -* Mini: "Optimize World Server Map": Figure out how to fill PaperWorldMap, it needs a dim key which doesnt exist anymore? -* Mini: "MC-50319": fix if still works -* Make sure the flat bedrock setting doesn't do anything stupid -* Check DataBits foreach -* lighting is bork (load chunk, fly away, come back, everything or parts are black) -* chunk generation seems slow with a lot of it happening -* Fix IDE Debug JVM Flag for new versions of minecraft - -* Check if `PlayerEditBookEvent`: https://github.com/PaperMC/Paper/pull/1751 -The PlayerEditBookEvent is straight up not called anymore. -The method to call it must now be `PlayerConnection#a(List, int)` (CB bug). -The item is presumably edited with the new page contents before it ever reaches this method? \ No newline at end of file diff --git a/patches/api-unmapped/0069-Add-PlayerJumpEvent.patch b/patches/api/0069-Add-PlayerJumpEvent.patch similarity index 100% rename from patches/api-unmapped/0069-Add-PlayerJumpEvent.patch rename to patches/api/0069-Add-PlayerJumpEvent.patch diff --git a/patches/api/0069-Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/patches/api/0070-Add-workaround-for-plugins-modifying-the-parent-of-t.patch similarity index 100% rename from patches/api/0069-Add-workaround-for-plugins-modifying-the-parent-of-t.patch rename to patches/api/0070-Add-workaround-for-plugins-modifying-the-parent-of-t.patch diff --git a/patches/api-unmapped/0070-Expose-client-protocol-version-and-virtual-host.patch b/patches/api/0071-Expose-client-protocol-version-and-virtual-host.patch similarity index 96% rename from patches/api-unmapped/0070-Expose-client-protocol-version-and-virtual-host.patch rename to patches/api/0071-Expose-client-protocol-version-and-virtual-host.patch index ff8f83ac14..755988a174 100644 --- a/patches/api-unmapped/0070-Expose-client-protocol-version-and-virtual-host.patch +++ b/patches/api/0071-Expose-client-protocol-version-and-virtual-host.patch @@ -57,7 +57,7 @@ index 0000000000000000000000000000000000000000..7b2af1bd72dfbcf4e962a982940fc49b + +} diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 9cf7adf244335ac7dccbdf11f605a8c6910f7414..04f1a6513711dde8576c9b5c2b04619c56b48d8a 100644 +index 22cfa703e4f543c26151b33fe9ee1ab445d1c4fe..a32c4bd276de797f518771460083050fcddc4c5b 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable; diff --git a/patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch index 65b65ad963..4c940a146a 100644 --- a/patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch +++ b/patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch @@ -5,10 +5,18 @@ Subject: [PATCH] Reset spawner timer when spawner event is cancelled diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index e310c1eb1108780bcff4d7ba9d49cefa2926287c..e3a69ed5ac791d8afb9c5beb924f9cf99dc0b410 100644 +index e310c1eb1108780bcff4d7ba9d49cefa2926287c..12a78685848b7fd945a472902d8200ea1d50b9ec 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -190,7 +190,7 @@ public abstract class BaseSpawner { +@@ -167,6 +167,7 @@ public abstract class BaseSpawner { + // Spigot End + } + entity.spawnedViaMobSpawner = true; // Paper ++ flag = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { + Entity vehicle = entity.getVehicle(); +@@ -190,7 +191,7 @@ public abstract class BaseSpawner { ((Mob) entity).spawnAnim(); } diff --git a/patches/server-remapped/0169-Handle-plugin-prefixes-using-Log4J-configuration.patch b/patches/server/0157-Handle-plugin-prefixes-using-Log4J-configuration.patch similarity index 73% rename from patches/server-remapped/0169-Handle-plugin-prefixes-using-Log4J-configuration.patch rename to patches/server/0157-Handle-plugin-prefixes-using-Log4J-configuration.patch index 8c91986ef3..f95216ecdd 100644 --- a/patches/server-remapped/0169-Handle-plugin-prefixes-using-Log4J-configuration.patch +++ b/patches/server/0157-Handle-plugin-prefixes-using-Log4J-configuration.patch @@ -14,28 +14,41 @@ the root logger, the Minecraft/Mojang loggers and the Bukkit loggers. This may cause additional prefixes to be disabled for plugins bypassing the plugin logger. +diff --git a/build.gradle.kts b/build.gradle.kts +index 7d969b0c2a4c15c7c12ab1dd0b002a7b53cebeed..ac607a3be84bc02dedb95cab9a5eace40e33b511 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -30,7 +30,7 @@ dependencies { + all its classes to check if they are plugins. + Scanning takes about 1-2 seconds so adding this speeds up the server start. + */ +- runtimeOnly("org.apache.logging.log4j:log4j-core:2.14.1") ++ implementation("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - implementation + // Paper end + implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper + implementation("org.apache.logging.log4j:log4j-api:2.14.1") // Paper diff --git a/pom.xml b/pom.xml -index 3841fe3630c090f8a468333d43caeb2b5841329d..f5429f2f1979542fd93956d2f436d20d0e3a66b8 100644 +index 2f0e513c9e5d78a22e7d1e1a5aa64bb8f0f360d2..f5e74f74e32095c4ad1f8094a0dd64be8e193f0c 100644 --- a/pom.xml +++ b/pom.xml -@@ -76,7 +76,7 @@ - - org.apache.logging.log4j - log4j-core +@@ -68,7 +68,7 @@ + com.googlecode.json-simple + json-simple + 1.1.1 - runtime + compile - org.apache.logging.log4j + org.xerial diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 0083f979933d4a9035efb992ab0a2f250a56a979..3981ba5957fdc2929d54515f2b98bb7a4611e938 100644 +index 2d226fd06759ed92bf5591259fc86f34f606a3ec..e7586c325290ceb8669f9f9d430c73080a37dd05 100644 --- a/src/main/java/org/spigotmc/SpigotConfig.java +++ b/src/main/java/org/spigotmc/SpigotConfig.java @@ -290,7 +290,7 @@ public class SpigotConfig private static void playerSample() { - playerSample = getInt( "settings.sample-count", 12 ); -- System.out.println( "Server Ping Player Sample Count: " + playerSample ); + SpigotConfig.playerSample = SpigotConfig.getInt( "settings.sample-count", 12 ); +- System.out.println( "Server Ping Player Sample Count: " + SpigotConfig.playerSample ); + Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger } diff --git a/patches/server-remapped/0170-Improve-Log4J-Configuration-Plugin-Loggers.patch b/patches/server/0158-Improve-Log4J-Configuration-Plugin-Loggers.patch similarity index 100% rename from patches/server-remapped/0170-Improve-Log4J-Configuration-Plugin-Loggers.patch rename to patches/server/0158-Improve-Log4J-Configuration-Plugin-Loggers.patch diff --git a/patches/server-remapped/0171-Add-PlayerJumpEvent.patch b/patches/server/0159-Add-PlayerJumpEvent.patch similarity index 89% rename from patches/server-remapped/0171-Add-PlayerJumpEvent.patch rename to patches/server/0159-Add-PlayerJumpEvent.patch index 9abed7291f..7271b0ea7e 100644 --- a/patches/server-remapped/0171-Add-PlayerJumpEvent.patch +++ b/patches/server/0159-Add-PlayerJumpEvent.patch @@ -5,16 +5,16 @@ Subject: [PATCH] Add PlayerJumpEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 6a922e3522ac99a8e317a5f5f51fbb597baaf63e..f35a976de39f16d100bcbe411b64de357832c5df 100644 +index acee61af1b01c7e66c3b5c7e164ddd9a88e53606..049436f5cc373f6d076a62ae2b548b0154a43b78 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1166,7 +1166,34 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1186,7 +1186,34 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser boolean flag = d8 > 0.0D; if (this.player.isOnGround() && !packet.isOnGround() && flag) { - this.player.jumpFromGround(); + // Paper start - Add player jump event -+ Player player = this.getPlayer(); ++ Player player = this.getCraftPlayer(); + Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. + Location to = player.getLocation().clone(); // Start off the To location as the Players current location. + @@ -37,7 +37,7 @@ index 6a922e3522ac99a8e317a5f5f51fbb597baaf63e..f35a976de39f16d100bcbe411b64de35 + this.player.jumpFromGround(); + } else { + from = event.getFrom(); -+ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet()); ++ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet(), false); + return; + } + // Paper end diff --git a/patches/server-remapped/0172-handle-PacketPlayInKeepAlive-async.patch b/patches/server/0160-handle-PacketPlayInKeepAlive-async.patch similarity index 88% rename from patches/server-remapped/0172-handle-PacketPlayInKeepAlive-async.patch rename to patches/server/0160-handle-PacketPlayInKeepAlive-async.patch index 1a0b7f3089..0399cafb24 100644 --- a/patches/server-remapped/0172-handle-PacketPlayInKeepAlive-async.patch +++ b/patches/server/0160-handle-PacketPlayInKeepAlive-async.patch @@ -15,10 +15,10 @@ also adding some additional logging in order to help work out what is causing random disconnections for clients. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index f35a976de39f16d100bcbe411b64de357832c5df..f0aab8639c7d8440e4d70dd096200313d7958780 100644 +index 049436f5cc373f6d076a62ae2b548b0154a43b78..6049c63b4f7abde0840738638d4bf19172a01200 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2777,14 +2777,18 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2781,14 +2781,18 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @Override public void handleKeepAlive(ServerboundKeepAlivePacket packet) { @@ -31,7 +31,7 @@ index f35a976de39f16d100bcbe411b64de357832c5df..f0aab8639c7d8440e4d70dd096200313 this.keepAlivePending = false; } else if (!this.isSingleplayerOwner()) { + // Paper start - This needs to be handled on the main thread for plugins -+ server.scheduleOnMain(() -> { ++ server.submit(() -> { this.disconnect(new TranslatableComponent("disconnect.timeout")); + }); + // Paper end diff --git a/patches/server-remapped/0173-Expose-client-protocol-version-and-virtual-host.patch b/patches/server/0161-Expose-client-protocol-version-and-virtual-host.patch similarity index 74% rename from patches/server-remapped/0173-Expose-client-protocol-version-and-virtual-host.patch rename to patches/server/0161-Expose-client-protocol-version-and-virtual-host.patch index c18295ef08..ca799c2b52 100644 --- a/patches/server-remapped/0173-Expose-client-protocol-version-and-virtual-host.patch +++ b/patches/server/0161-Expose-client-protocol-version-and-virtual-host.patch @@ -60,10 +60,10 @@ index 0000000000000000000000000000000000000000..a5a7624f1f372a26b982836cd31cff15 + +} diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 92c5c5bbcfe364475578b6a0eddfaa85858ace8a..3429c813a5b471cdfa561bd20849a303e5aacead 100644 +index 242f76a2ee2ca3d67851647bbb14cd123c378e0b..1d46187969b5792c255d0bf1966b427b905cb69c 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java -@@ -70,6 +70,10 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -83,6 +83,10 @@ public class Connection extends SimpleChannelInboundHandler> { private float averageSentPackets; private int tickCount; private boolean handlingFault; @@ -74,20 +74,8 @@ index 92c5c5bbcfe364475578b6a0eddfaa85858ace8a..3429c813a5b471cdfa561bd20849a303 public Connection(PacketFlow side) { this.receiving = side; -diff --git a/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java b/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java -index 1eae2999ecc57f68ac9cd1d745191cba617b0de2..9ad400b15a2eb2d80bc763de28d648e22432b8f2 100644 ---- a/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java -@@ -39,6 +39,7 @@ public class ClientIntentionPacket implements Packet= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info + this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0])); + } + } else { + if (elapsedTime >= 15000L) { // 15 seconds -+ this.setPendingPing(true); -+ this.setLastPing(currentTime); -+ this.setKeepAliveID(currentTime); -+ this.send(new ClientboundKeepAlivePacket(this.getKeepAliveID())); + this.keepAlivePending = true; +- this.keepAliveTime = i; +- this.keepAliveChallenge = i; ++ this.keepAliveTime = currentTime; ++ this.keepAliveChallenge = currentTime; + this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge)); } } + // Paper end diff --git a/patches/server-remapped/0175-Send-attack-SoundEffects-only-to-players-who-can-see.patch b/patches/server/0163-Send-attack-SoundEffects-only-to-players-who-can-see.patch similarity index 91% rename from patches/server-remapped/0175-Send-attack-SoundEffects-only-to-players-who-can-see.patch rename to patches/server/0163-Send-attack-SoundEffects-only-to-players-who-can-see.patch index d30ac6d736..d7dc1deef3 100644 --- a/patches/server-remapped/0175-Send-attack-SoundEffects-only-to-players-who-can-see.patch +++ b/patches/server/0163-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 3205bc2fb6c9031be68ff46dfca927e681163fa8..43868c1e2d2c858a4f02119c3238f615f9b1ee72 100644 +index 075bbc75d2e33be3a42c6c3ec279eeeba6408333..d3fe3eabf4465101760951113b23edf2ce03e57d 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -28,6 +28,7 @@ import net.minecraft.network.chat.MutableComponent; +@@ -30,6 +30,7 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; @@ -17,7 +17,7 @@ index 3205bc2fb6c9031be68ff46dfca927e681163fa8..43868c1e2d2c858a4f02119c3238f615 import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; -@@ -1123,7 +1124,7 @@ public abstract class Player extends LivingEntity { +@@ -1183,7 +1184,7 @@ public abstract class Player extends LivingEntity { int i = b0 + EnchantmentHelper.getKnockbackBonus((LivingEntity) this); if (this.isSprinting() && flag) { @@ -26,7 +26,7 @@ index 3205bc2fb6c9031be68ff46dfca927e681163fa8..43868c1e2d2c858a4f02119c3238f615 ++i; flag1 = true; } -@@ -1198,7 +1199,7 @@ public abstract class Player extends LivingEntity { +@@ -1258,7 +1259,7 @@ public abstract class Player extends LivingEntity { } } @@ -35,7 +35,7 @@ index 3205bc2fb6c9031be68ff46dfca927e681163fa8..43868c1e2d2c858a4f02119c3238f615 this.sweepAttack(); } -@@ -1226,15 +1227,15 @@ public abstract class Player extends LivingEntity { +@@ -1286,15 +1287,15 @@ public abstract class Player extends LivingEntity { } if (flag2) { @@ -54,7 +54,7 @@ index 3205bc2fb6c9031be68ff46dfca927e681163fa8..43868c1e2d2c858a4f02119c3238f615 } } -@@ -1286,7 +1287,7 @@ public abstract class Player extends LivingEntity { +@@ -1346,7 +1347,7 @@ public abstract class Player extends LivingEntity { this.applyExhaustion(level.spigotConfig.combatExhaustion, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value } else { @@ -63,7 +63,7 @@ index 3205bc2fb6c9031be68ff46dfca927e681163fa8..43868c1e2d2c858a4f02119c3238f615 if (flag4) { target.clearFire(); } -@@ -1721,6 +1722,14 @@ public abstract class Player extends LivingEntity { +@@ -1793,6 +1794,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); } From 79da8f0eca4f84d87418113c1f360ff16c91d56c Mon Sep 17 00:00:00 2001 From: Aurora Date: Sat, 12 Jun 2021 17:06:20 +0200 Subject: [PATCH 047/226] even more wooooooooooooooooooooooooork uwu --- .../0071-Add-PlayerArmorChangeEvent.patch | 0 ...-get-a-BlockState-without-a-snapshot.patch | 2 +- .../0073-AsyncTabCompleteEvent.patch | 0 ...t-protocol-version-and-virtual-host.patch} | 0 ...ay-warning-on-deprecated-recipe-API.patch} | 0 .../0076-PlayerPickupExperienceEvent.patch} | 0 .../0077-ExperienceOrbMergeEvent.patch} | 0 ...-Ability-to-apply-mending-to-XP-API.patch} | 2 +- .../0079-PreCreatureSpawnEvent.patch} | 0 ...-PlayerNaturallySpawnCreaturesEvent.patch} | 0 ...-maximum-exp-value-when-merging-orbs.patch | 0 ...182-Avoid-NPE-in-PathfinderGoalTempt.patch | 2 +- .../1.17}/0184-ExperienceOrbMergeEvent.patch | 2 +- .../1.17}/0187-PreCreatureSpawnEvent.patch | 2 +- .../0183-PlayerPickupExperienceEvent.patch | 28 ---------- .../0164-Add-PlayerArmorChangeEvent.patch} | 10 ++-- ...om-being-processed-when-the-player-.patch} | 4 +- ...-implementations-for-captured-block.patch} | 20 +++---- ...get-a-BlockState-without-a-snapshot.patch} | 55 ++++++++++++------- .../0168-AsyncTabCompleteEvent.patch} | 18 +++--- .../0169-PlayerPickupExperienceEvent.patch | 20 +++++++ ...-Ability-to-apply-mending-to-XP-API.patch} | 28 +++++----- ...max-squid-spawn-height-configurable.patch} | 20 +++---- ...-PlayerNaturallySpawnCreaturesEvent.patch} | 21 +++---- 24 files changed, 118 insertions(+), 116 deletions(-) rename patches/{api-unmapped => api}/0071-Add-PlayerArmorChangeEvent.patch (100%) rename patches/{api-unmapped => api}/0072-API-to-get-a-BlockState-without-a-snapshot.patch (91%) rename patches/{api-unmapped => api}/0073-AsyncTabCompleteEvent.patch (100%) rename patches/api/{0071-Expose-client-protocol-version-and-virtual-host.patch => 0074-Expose-client-protocol-version-and-virtual-host.patch} (100%) rename patches/{api-unmapped/0074-Display-warning-on-deprecated-recipe-API.patch => api/0075-Display-warning-on-deprecated-recipe-API.patch} (100%) rename patches/{api-unmapped/0075-PlayerPickupExperienceEvent.patch => api/0076-PlayerPickupExperienceEvent.patch} (100%) rename patches/{api-unmapped/0076-ExperienceOrbMergeEvent.patch => api/0077-ExperienceOrbMergeEvent.patch} (100%) rename patches/{api-unmapped/0077-Ability-to-apply-mending-to-XP-API.patch => api/0078-Ability-to-apply-mending-to-XP-API.patch} (95%) rename patches/{api-unmapped/0078-PreCreatureSpawnEvent.patch => api/0079-PreCreatureSpawnEvent.patch} (100%) rename patches/{api-unmapped/0079-PlayerNaturallySpawnCreaturesEvent.patch => api/0080-PlayerNaturallySpawnCreaturesEvent.patch} (100%) rename patches/{server-remapped => removed/1.17}/0176-Option-for-maximum-exp-value-when-merging-orbs.patch (100%) rename patches/{server-remapped => removed/1.17}/0182-Avoid-NPE-in-PathfinderGoalTempt.patch (98%) rename patches/{server-remapped => removed/1.17}/0184-ExperienceOrbMergeEvent.patch (97%) rename patches/{server-remapped => removed/1.17}/0187-PreCreatureSpawnEvent.patch (99%) delete mode 100644 patches/server-remapped/0183-PlayerPickupExperienceEvent.patch rename patches/{server-remapped/0177-Add-PlayerArmorChangeEvent.patch => server/0164-Add-PlayerArmorChangeEvent.patch} (86%) rename patches/{server-remapped/0178-Prevent-logins-from-being-processed-when-the-player-.patch => server/0165-Prevent-logins-from-being-processed-when-the-player-.patch} (88%) rename patches/{server-remapped/0179-use-CB-BlockState-implementations-for-captured-block.patch => server/0166-use-CB-BlockState-implementations-for-captured-block.patch} (80%) rename patches/{server-remapped/0180-API-to-get-a-BlockState-without-a-snapshot.patch => server/0167-API-to-get-a-BlockState-without-a-snapshot.patch} (73%) rename patches/{server-remapped/0181-AsyncTabCompleteEvent.patch => server/0168-AsyncTabCompleteEvent.patch} (90%) create mode 100644 patches/server/0169-PlayerPickupExperienceEvent.patch rename patches/{server-remapped/0185-Ability-to-apply-mending-to-XP-API.patch => server/0170-Ability-to-apply-mending-to-XP-API.patch} (86%) rename patches/{server-remapped/0186-Make-max-squid-spawn-height-configurable.patch => server/0171-Make-max-squid-spawn-height-configurable.patch} (55%) rename patches/{server-remapped/0188-PlayerNaturallySpawnCreaturesEvent.patch => server/0172-PlayerNaturallySpawnCreaturesEvent.patch} (82%) diff --git a/patches/api-unmapped/0071-Add-PlayerArmorChangeEvent.patch b/patches/api/0071-Add-PlayerArmorChangeEvent.patch similarity index 100% rename from patches/api-unmapped/0071-Add-PlayerArmorChangeEvent.patch rename to patches/api/0071-Add-PlayerArmorChangeEvent.patch diff --git a/patches/api-unmapped/0072-API-to-get-a-BlockState-without-a-snapshot.patch b/patches/api/0072-API-to-get-a-BlockState-without-a-snapshot.patch similarity index 91% rename from patches/api-unmapped/0072-API-to-get-a-BlockState-without-a-snapshot.patch rename to patches/api/0072-API-to-get-a-BlockState-without-a-snapshot.patch index 9d4f264793..17364528bc 100644 --- a/patches/api-unmapped/0072-API-to-get-a-BlockState-without-a-snapshot.patch +++ b/patches/api/0072-API-to-get-a-BlockState-without-a-snapshot.patch @@ -9,7 +9,7 @@ on the real tile entity. This is useful for where performance is needed diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 0cfad6f84eda6f7bfa1fae041341ccb1021b157d..e89c8079625525667f496c06207da655fe43d749 100644 +index d4c69573f250309adc442c7cf67ea6fc2f2e3ace..969a6cf404d99c186e73321659240195b8650ffc 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java @@ -269,6 +269,16 @@ public interface Block extends Metadatable { diff --git a/patches/api-unmapped/0073-AsyncTabCompleteEvent.patch b/patches/api/0073-AsyncTabCompleteEvent.patch similarity index 100% rename from patches/api-unmapped/0073-AsyncTabCompleteEvent.patch rename to patches/api/0073-AsyncTabCompleteEvent.patch diff --git a/patches/api/0071-Expose-client-protocol-version-and-virtual-host.patch b/patches/api/0074-Expose-client-protocol-version-and-virtual-host.patch similarity index 100% rename from patches/api/0071-Expose-client-protocol-version-and-virtual-host.patch rename to patches/api/0074-Expose-client-protocol-version-and-virtual-host.patch diff --git a/patches/api-unmapped/0074-Display-warning-on-deprecated-recipe-API.patch b/patches/api/0075-Display-warning-on-deprecated-recipe-API.patch similarity index 100% rename from patches/api-unmapped/0074-Display-warning-on-deprecated-recipe-API.patch rename to patches/api/0075-Display-warning-on-deprecated-recipe-API.patch diff --git a/patches/api-unmapped/0075-PlayerPickupExperienceEvent.patch b/patches/api/0076-PlayerPickupExperienceEvent.patch similarity index 100% rename from patches/api-unmapped/0075-PlayerPickupExperienceEvent.patch rename to patches/api/0076-PlayerPickupExperienceEvent.patch diff --git a/patches/api-unmapped/0076-ExperienceOrbMergeEvent.patch b/patches/api/0077-ExperienceOrbMergeEvent.patch similarity index 100% rename from patches/api-unmapped/0076-ExperienceOrbMergeEvent.patch rename to patches/api/0077-ExperienceOrbMergeEvent.patch diff --git a/patches/api-unmapped/0077-Ability-to-apply-mending-to-XP-API.patch b/patches/api/0078-Ability-to-apply-mending-to-XP-API.patch similarity index 95% rename from patches/api-unmapped/0077-Ability-to-apply-mending-to-XP-API.patch rename to patches/api/0078-Ability-to-apply-mending-to-XP-API.patch index a225f3dedc..977d682512 100644 --- a/patches/api-unmapped/0077-Ability-to-apply-mending-to-XP-API.patch +++ b/patches/api/0078-Ability-to-apply-mending-to-XP-API.patch @@ -10,7 +10,7 @@ of giving the player experience points. Both an API To standalone mend, and apply mending logic to .giveExp has been added. diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 21bed0d8075335538374fadfdf1cb868e4eebe80..9d1ad67b7d220ab425ac9bf6b1c8d8fb8d5f416c 100644 +index a32c4bd276de797f518771460083050fcddc4c5b..9a262d412b2762a33a60b1e8762a7d9c9c3f933d 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -892,12 +892,33 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM diff --git a/patches/api-unmapped/0078-PreCreatureSpawnEvent.patch b/patches/api/0079-PreCreatureSpawnEvent.patch similarity index 100% rename from patches/api-unmapped/0078-PreCreatureSpawnEvent.patch rename to patches/api/0079-PreCreatureSpawnEvent.patch diff --git a/patches/api-unmapped/0079-PlayerNaturallySpawnCreaturesEvent.patch b/patches/api/0080-PlayerNaturallySpawnCreaturesEvent.patch similarity index 100% rename from patches/api-unmapped/0079-PlayerNaturallySpawnCreaturesEvent.patch rename to patches/api/0080-PlayerNaturallySpawnCreaturesEvent.patch diff --git a/patches/server-remapped/0176-Option-for-maximum-exp-value-when-merging-orbs.patch b/patches/removed/1.17/0176-Option-for-maximum-exp-value-when-merging-orbs.patch similarity index 100% rename from patches/server-remapped/0176-Option-for-maximum-exp-value-when-merging-orbs.patch rename to patches/removed/1.17/0176-Option-for-maximum-exp-value-when-merging-orbs.patch diff --git a/patches/server-remapped/0182-Avoid-NPE-in-PathfinderGoalTempt.patch b/patches/removed/1.17/0182-Avoid-NPE-in-PathfinderGoalTempt.patch similarity index 98% rename from patches/server-remapped/0182-Avoid-NPE-in-PathfinderGoalTempt.patch rename to patches/removed/1.17/0182-Avoid-NPE-in-PathfinderGoalTempt.patch index 5d0147c515..15a2d9eab1 100644 --- a/patches/server-remapped/0182-Avoid-NPE-in-PathfinderGoalTempt.patch +++ b/patches/removed/1.17/0182-Avoid-NPE-in-PathfinderGoalTempt.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Wed, 29 Nov 2017 22:18:54 -0500 Subject: [PATCH] Avoid NPE in PathfinderGoalTempt - +Not needed anymore diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java index 186025458e923d153e9e47c2be147a9bb53db517..11ca6a752bac4ba4bc683bef844d204b739fab63 100644 diff --git a/patches/server-remapped/0184-ExperienceOrbMergeEvent.patch b/patches/removed/1.17/0184-ExperienceOrbMergeEvent.patch similarity index 97% rename from patches/server-remapped/0184-ExperienceOrbMergeEvent.patch rename to patches/removed/1.17/0184-ExperienceOrbMergeEvent.patch index 28b23c94bd..aef031bd77 100644 --- a/patches/server-remapped/0184-ExperienceOrbMergeEvent.patch +++ b/patches/removed/1.17/0184-ExperienceOrbMergeEvent.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Tue, 19 Dec 2017 22:57:26 -0500 Subject: [PATCH] ExperienceOrbMergeEvent - +Has to be reimplemented at one point maybe Fired when the server is about to merge 2 experience orbs Plugins can cancel this if they want to ensure experience orbs do not lose important metadata such as spawn reason, or conditionally move data from source to target. diff --git a/patches/server-remapped/0187-PreCreatureSpawnEvent.patch b/patches/removed/1.17/0187-PreCreatureSpawnEvent.patch similarity index 99% rename from patches/server-remapped/0187-PreCreatureSpawnEvent.patch rename to patches/removed/1.17/0187-PreCreatureSpawnEvent.patch index 341927c26e..c3206f4317 100644 --- a/patches/server-remapped/0187-PreCreatureSpawnEvent.patch +++ b/patches/removed/1.17/0187-PreCreatureSpawnEvent.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 14 Jan 2018 17:01:31 -0500 Subject: [PATCH] PreCreatureSpawnEvent - +1.17: Has to be looked into more Adds an event to fire before an Entity is created, so that plugins that need to cancel CreatureSpawnEvent can do so from this event instead. diff --git a/patches/server-remapped/0183-PlayerPickupExperienceEvent.patch b/patches/server-remapped/0183-PlayerPickupExperienceEvent.patch deleted file mode 100644 index fe7129d330..0000000000 --- a/patches/server-remapped/0183-PlayerPickupExperienceEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:02:53 -0500 -Subject: [PATCH] PlayerPickupExperienceEvent - -Allows plugins to cancel a player picking up an experience orb - -diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index 3ddb0a9f15c920c9a2080f76edfda0504c1e287a..885c5a920204a31b24c7d360390eaf4177c30698 100644 ---- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -5,6 +5,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.tags.FluidTags; - import net.minecraft.tags.Tag; -@@ -231,7 +232,7 @@ public class ExperienceOrb extends Entity { - @Override - public void playerTouch(Player player) { - if (!this.level.isClientSide) { -- if (this.throwTime == 0 && player.takeXpDelay == 0) { -+ if (this.throwTime == 0 && player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((ServerPlayer) player).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - player.takeXpDelay = 2; - player.take(this, 1); - Entry entry = EnchantmentHelper.getRandomItemWith(Enchantments.MENDING, (LivingEntity) player, ItemStack::isDamaged); diff --git a/patches/server-remapped/0177-Add-PlayerArmorChangeEvent.patch b/patches/server/0164-Add-PlayerArmorChangeEvent.patch similarity index 86% rename from patches/server-remapped/0177-Add-PlayerArmorChangeEvent.patch rename to patches/server/0164-Add-PlayerArmorChangeEvent.patch index ae78b560ac..21828275b6 100644 --- a/patches/server-remapped/0177-Add-PlayerArmorChangeEvent.patch +++ b/patches/server/0164-Add-PlayerArmorChangeEvent.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Add PlayerArmorChangeEvent diff --git a/src/main/java/net/minecraft/world/entity/EquipmentSlot.java b/src/main/java/net/minecraft/world/entity/EquipmentSlot.java -index b686b7a2faa4fbce37dcc3598b3c956661b91aaa..17cd5f525a45058ce34c66c87f9c133033bb8f4b 100644 +index c82bb38b5b1c9204daef21455723d21509ad1c44..135a62fcdbd801c9997bc28c071743e8ff8c64c2 100644 --- a/src/main/java/net/minecraft/world/entity/EquipmentSlot.java +++ b/src/main/java/net/minecraft/world/entity/EquipmentSlot.java -@@ -16,6 +16,7 @@ public enum EquipmentSlot { - this.name = s; +@@ -20,6 +20,7 @@ public enum EquipmentSlot { + this.name = name; } + public EquipmentSlot.Type getType() { return this.getType(); } // Paper - OBFHELPER @@ -17,7 +17,7 @@ index b686b7a2faa4fbce37dcc3598b3c956661b91aaa..17cd5f525a45058ce34c66c87f9c1330 return this.type; } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index d6b4fabd232958ae1fd5405c7129551951cd7765..8b0d1f4fbc43a6f37a5f9c453b5dd142a4f69745 100644 +index 89913edf98d65f08f379d0d201f9963c23573478..28de49c8b5771491b168bba26e6033669c48e3c9 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -1,5 +1,6 @@ @@ -27,7 +27,7 @@ index d6b4fabd232958ae1fd5405c7129551951cd7765..8b0d1f4fbc43a6f37a5f9c453b5dd142 import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -@@ -2643,6 +2644,13 @@ public abstract class LivingEntity extends Entity { +@@ -2937,6 +2938,13 @@ public abstract class LivingEntity extends Entity { ItemStack itemstack1 = this.getItemBySlot(enumitemslot); if (!ItemStack.matches(itemstack1, itemstack)) { diff --git a/patches/server-remapped/0178-Prevent-logins-from-being-processed-when-the-player-.patch b/patches/server/0165-Prevent-logins-from-being-processed-when-the-player-.patch similarity index 88% rename from patches/server-remapped/0178-Prevent-logins-from-being-processed-when-the-player-.patch rename to patches/server/0165-Prevent-logins-from-being-processed-when-the-player-.patch index c04d5e61cf..a2050f2e4b 100644 --- a/patches/server-remapped/0178-Prevent-logins-from-being-processed-when-the-player-.patch +++ b/patches/server/0165-Prevent-logins-from-being-processed-when-the-player-.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Prevent logins from being processed when the player has diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 4b91699ddfa2ee298af5ba25447a85751facf4a4..ff83fb15d0d0adb62c630fc7aafc134972bf15fc 100644 +index 700ab378f43b3841c82b7aadc1c3818dc0621a58..7923078a4235a6169eb94b7c0ce85e4cd51eb593 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -73,7 +73,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -76,7 +76,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener } // Paper end if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) { diff --git a/patches/server-remapped/0179-use-CB-BlockState-implementations-for-captured-block.patch b/patches/server/0166-use-CB-BlockState-implementations-for-captured-block.patch similarity index 80% rename from patches/server-remapped/0179-use-CB-BlockState-implementations-for-captured-block.patch rename to patches/server/0166-use-CB-BlockState-implementations-for-captured-block.patch index 939a2fed54..8cc215d1a1 100644 --- a/patches/server-remapped/0179-use-CB-BlockState-implementations-for-captured-block.patch +++ b/patches/server/0166-use-CB-BlockState-implementations-for-captured-block.patch @@ -18,10 +18,10 @@ the blockstate that will be valid for restoration, as opposed to dropping information on restoration when the event is cancelled. diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 81713c97f35263f4ab8d14f8b707aac3d6afea11..b4248d46ccb1a95e21601bca1198512287edcabf 100644 +index a86b5272c0ac4dd64f796f7fd025c7a34a5d2f8d..8859b0483ca71e1a36c164f7d386684540f0bf18 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -124,7 +124,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -140,7 +140,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public boolean captureBlockStates = false; public boolean captureTreeGeneration = false; @@ -30,16 +30,16 @@ index 81713c97f35263f4ab8d14f8b707aac3d6afea11..b4248d46ccb1a95e21601bca11985122 public Map capturedTileEntities = new HashMap<>(); public List captureDrops; public long ticksPerAnimalSpawns; -@@ -346,7 +346,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -358,7 +358,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { // CraftBukkit start - tree generation if (this.captureTreeGeneration) { -- CapturedBlockState blockstate = capturedBlockStates.get(pos); -+ CraftBlockState blockstate = capturedBlockStates.get(pos); +- CapturedBlockState blockstate = this.capturedBlockStates.get(pos); ++ CraftBlockState blockstate = this.capturedBlockStates.get(pos); if (blockstate == null) { blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); this.capturedBlockStates.put(pos.immutable(), blockstate); -@@ -366,7 +366,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -378,7 +378,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { // CraftBukkit start - capture blockstates boolean captured = false; if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) { @@ -49,12 +49,12 @@ index 81713c97f35263f4ab8d14f8b707aac3d6afea11..b4248d46ccb1a95e21601bca11985122 this.capturedBlockStates.put(pos.immutable(), blockstate); captured = true; } -@@ -624,7 +625,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -644,7 +645,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public BlockState getBlockState(BlockPos pos) { // CraftBukkit start - tree generation - if (captureTreeGeneration) { -- CapturedBlockState previous = capturedBlockStates.get(pos); -+ CraftBlockState previous = capturedBlockStates.get(pos); // Paper + if (this.captureTreeGeneration) { +- CapturedBlockState previous = this.capturedBlockStates.get(pos); ++ CraftBlockState previous = this.capturedBlockStates.get(pos); // Paper if (previous != null) { return previous.getHandle(); } diff --git a/patches/server-remapped/0180-API-to-get-a-BlockState-without-a-snapshot.patch b/patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch similarity index 73% rename from patches/server-remapped/0180-API-to-get-a-BlockState-without-a-snapshot.patch rename to patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch index d3837145f0..7b37b5ad1d 100644 --- a/patches/server-remapped/0180-API-to-get-a-BlockState-without-a-snapshot.patch +++ b/patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch @@ -13,40 +13,51 @@ also Avoid NPE during CraftBlockEntityState load if could not get TE If Tile Entity was null, correct Sign to return empty lines instead of null diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index d08ed44884726ca2ba4578226b8aa6244778f4c7..84012c2d12817e657b046bc168cc8eddebcd3831 100644 +index 9d777fce673c8f6b3ee2d69f5a6360a8a5ad8e84..c3706b87ad36332a837caffb58bd4575cbc0172a 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -47,6 +47,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - public BlockEntity(BlockEntityType type) { - this.worldPosition = BlockPos.ZERO; +@@ -31,7 +31,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + // CraftBukkit end + private static final Logger LOGGER = LogManager.getLogger(); + public boolean isLoadingStructure = false; // Paper +- private final BlockEntityType type; public BlockEntityType getTileEntityType() { return type; } // Paper - OBFHELPER ++ private final BlockEntityType type; + @Nullable + protected Level level; + protected final BlockPos worldPosition; +@@ -42,6 +42,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { this.type = type; + this.worldPosition = pos.immutable(); + this.blockState = state; + persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init } // Paper start -@@ -95,7 +96,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - public void load(BlockState state, CompoundTag tag) { - this.worldPosition = new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); - // CraftBukkit start - read container -- this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); -+ this.persistentDataContainer.clear(); // Paper - clear instead of reinit +@@ -79,7 +80,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - net.minecraft.nbt.Tag persistentDataTag = tag.get("PublicBukkitValues"); + // CraftBukkit start - read container + public void load(CompoundTag nbt) { +- this.persistentDataContainer = new CraftPersistentDataContainer(BlockEntity.DATA_TYPE_REGISTRY); ++ this.persistentDataContainer.clear(); + + net.minecraft.nbt.Tag persistentDataTag = nbt.get("PublicBukkitValues"); if (persistentDataTag instanceof CompoundTag) { -@@ -245,7 +246,12 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { +@@ -221,8 +222,13 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { } // CraftBukkit start - add method + // Paper start public InventoryHolder getOwner() { +- if (this.level == null) return null; + return getOwner(true); + } + public InventoryHolder getOwner(boolean useSnapshot) { + // Paper end - if (level == null) return null; ++ if (level == null) return null; // Spigot start - org.bukkit.block.Block block = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); -@@ -254,7 +260,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + org.bukkit.block.Block block = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ()); + if (block == null) { +@@ -230,7 +236,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { return null; } // Spigot end @@ -56,13 +67,14 @@ index d08ed44884726ca2ba4578226b8aa6244778f4c7..84012c2d12817e657b046bc168cc8edd return null; } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 9d5b3801205e2800b0bcf238c5656321e3654f03..d73086970db19531db66c2e8af52da91d0b1ea28 100644 +index 6128eb5a793365822d9b00a86629ad4d86c61da9..ca03ed4b1581df2b7db272d6f330174a9d277153 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -313,6 +313,20 @@ public class CraftBlock implements Block { +@@ -313,7 +313,21 @@ public class CraftBlock implements Block { @Override public BlockState getState() { +- Material material = this.getType(); + // Paper start - allow disabling the use of snapshots + return getState(true); + } @@ -77,11 +89,12 @@ index 9d5b3801205e2800b0bcf238c5656321e3654f03..d73086970db19531db66c2e8af52da91 + } + public BlockState getState0() { + // Paper end - Material material = getType(); ++ Material material = getType(); switch (material) { + case ACACIA_SIGN: diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index e89a93082fe07fdb14df8ffef5beca5bd52d7866..730fda7f0bf02400d349959e9cc2aafaed000b21 100644 +index d57b32090cebfc952ac0a71b8aada85f49275241..9a30770a2f68e1253afe3ca8ecdae19c988248f9 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java @@ -26,20 +26,40 @@ public class CraftBlockEntityState extends CraftBlockStat @@ -131,12 +144,12 @@ index e89a93082fe07fdb14df8ffef5beca5bd52d7866..730fda7f0bf02400d349959e9cc2aafa private T createSnapshot(T tileEntity) { diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -index e3664110bef9315cfde5b61dde98dce77016600e..10ba8b810c1759adc439f753d36108e30cf70140 100644 +index ddd7b63f0452042baa3fca04bb9fbdb42fcecbfd..b638351581fa09c488425a2318b782a5812140ce 100644 --- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java +++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java @@ -155,4 +155,10 @@ public final class CraftPersistentDataContainer implements PersistentDataContain public Map serialize() { - return (Map) CraftNBTTagConfigSerializer.serialize(toTagCompound()); + return (Map) CraftNBTTagConfigSerializer.serialize(this.toTagCompound()); } + + // Paper start diff --git a/patches/server-remapped/0181-AsyncTabCompleteEvent.patch b/patches/server/0168-AsyncTabCompleteEvent.patch similarity index 90% rename from patches/server-remapped/0181-AsyncTabCompleteEvent.patch rename to patches/server/0168-AsyncTabCompleteEvent.patch index 1bd4fdfc05..8cb41e523d 100644 --- a/patches/server-remapped/0181-AsyncTabCompleteEvent.patch +++ b/patches/server/0168-AsyncTabCompleteEvent.patch @@ -14,23 +14,23 @@ completion, such as offline players. Also adds isCommand and getLocation to the sync TabCompleteEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 525728268f56470fdc24c4fd2f19d66943447778..8d0c44b6c2c99d5161c5d4b79209b79ff6db75e4 100644 +index b2bbd25e5572f59add71579b676d5a4c719be239..737296e90e3547505a012fc516a4fc39a565343e 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -711,10 +711,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -703,10 +703,10 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @Override public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async // CraftBukkit start - if (chatSpamField.addAndGet(this, 1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { + if (this.chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { - this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0])); + server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper return; } // CraftBukkit end -@@ -724,12 +724,35 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -716,12 +716,35 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser stringreader.skip(); } @@ -72,20 +72,20 @@ index 525728268f56470fdc24c4fd2f19d66943447778..8d0c44b6c2c99d5161c5d4b79209b79f @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index df68599520189e2699c8521d6c6ab7235612af33..10addb128a357e7719854bf4f9d75f5def32b27d 100644 +index 0be8b1727ce57ec0905315922e1d83104a936cd0..cb09b6170a74984628f2c3dbacad2ddc9fe56faf 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1850,7 +1850,7 @@ public final class CraftServer implements Server { - offers = tabCompleteChat(player, message); +@@ -1849,7 +1849,7 @@ public final class CraftServer implements Server { + offers = this.tabCompleteChat(player, message); } - TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers); + TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? net.minecraft.server.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), new BlockPos(pos)) : null); // Paper - getPluginManager().callEvent(tabEvent); + this.getPluginManager().callEvent(tabEvent); return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index a957695457cf3252848ce6ef37069692841b8e28..c5e00bd9e2790992202aadf8eec2002fc88c78f1 100644 +index b996fde481cebbbcce80a6c267591136db7cc0bc..e5af155d75f717d33c23e22ff8b96bb3ff87844d 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java @@ -28,6 +28,39 @@ public class ConsoleCommandCompleter implements Completer { diff --git a/patches/server/0169-PlayerPickupExperienceEvent.patch b/patches/server/0169-PlayerPickupExperienceEvent.patch new file mode 100644 index 0000000000..f668dc331a --- /dev/null +++ b/patches/server/0169-PlayerPickupExperienceEvent.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 19 Dec 2017 22:02:53 -0500 +Subject: [PATCH] PlayerPickupExperienceEvent + +Allows plugins to cancel a player picking up an experience orb + +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 337e861a8b1a89b73560601b704c18dcf446a144..8203c93dcb56646df2614f2233aaf3a36f745d1c 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -303,7 +303,7 @@ public class ExperienceOrb extends Entity { + @Override + public void playerTouch(Player player) { + if (!this.level.isClientSide) { +- if (player.takeXpDelay == 0) { ++ if (player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper + player.takeXpDelay = 2; + player.take(this, 1); + int i = this.repairPlayerItems(player, this.value); diff --git a/patches/server-remapped/0185-Ability-to-apply-mending-to-XP-API.patch b/patches/server/0170-Ability-to-apply-mending-to-XP-API.patch similarity index 86% rename from patches/server-remapped/0185-Ability-to-apply-mending-to-XP-API.patch rename to patches/server/0170-Ability-to-apply-mending-to-XP-API.patch index 24cf0a602e..06411572db 100644 --- a/patches/server-remapped/0185-Ability-to-apply-mending-to-XP-API.patch +++ b/patches/server/0170-Ability-to-apply-mending-to-XP-API.patch @@ -10,10 +10,10 @@ of giving the player experience points. Both an API To standalone mend, and apply mending logic to .giveExp has been added. diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index 885c5a920204a31b24c7d360390eaf4177c30698..52b90ef3a145325209d3d903a2b7c9a44c332cbe 100644 +index 8203c93dcb56646df2614f2233aaf3a36f745d1c..71fb831ed3359e7986e279c987211f39c581ab23 100644 --- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -264,10 +264,12 @@ public class ExperienceOrb extends Entity { +@@ -344,10 +344,12 @@ public class ExperienceOrb extends Entity { } } @@ -27,10 +27,10 @@ index 885c5a920204a31b24c7d360390eaf4177c30698..52b90ef3a145325209d3d903a2b7c9a4 return experienceAmount * 2; } diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java -index 045f937f0b7acd73469b65897bea2ca9036acf22..c82e1b6e3ec98530099fd6452fdaaefebfd99b33 100644 +index 27cdfbeb6cb2159075b35dd4f9e9557ec0eac7c2..d2d7b303e66bbba489e2003cc130dcd53e2a9854 100644 --- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java +++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java -@@ -269,8 +269,8 @@ public class EnchantmentHelper { +@@ -246,8 +246,8 @@ public class EnchantmentHelper { return getItemEnchantmentLevel(Enchantments.CHANNELING, stack) > 0; } @@ -38,14 +38,14 @@ index 045f937f0b7acd73469b65897bea2ca9036acf22..c82e1b6e3ec98530099fd6452fdaaefe - public static Entry getRandomItemWith(Enchantment enchantment, LivingEntity entity) { + public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, LivingEntity entityliving) { Entry entry = getRandomItemWith(enchantment, entityliving); return entry != null ? entry.getValue() : ItemStack.NULL_ITEM; } // Paper - OBFHELPER + @Nullable public static Entry getRandomItemWith(Enchantment enchantment, LivingEntity entity) { - return getRandomItemWith(enchantment, entity, (itemstack) -> { + return getRandomItemWith(enchantment, entity, (stack) -> { 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 8a5bf0b83c1e65f07e14da0e053a64c34976b91a..efdcb8dac8db15c4bbaed84a7861ce98339e516a 100644 +index ed1c57f22adc8b96012eca426ed1e7b409e7d663..b1778f53de7974e03c7b56b0df69e31cdae8dd62 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -58,11 +58,14 @@ import net.minecraft.server.level.ServerPlayer; +@@ -61,11 +61,14 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.server.players.UserWhiteListEntry; import net.minecraft.world.entity.Entity; @@ -58,15 +58,14 @@ index 8a5bf0b83c1e65f07e14da0e053a64c34976b91a..efdcb8dac8db15c4bbaed84a7861ce98 +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.GameType; + import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.SignBlockEntity; - import net.minecraft.world.level.saveddata.maps.MapDecoration; -@@ -1176,8 +1179,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return GameMode.getByValue(getHandle().gameMode.getGameModeForPlayer().getId()); +@@ -1189,8 +1192,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return GameMode.getByValue(this.getHandle().gameMode.getGameModeForPlayer().getId()); } + // Paper start - @Override -- public void giveExp(int exp) { ++ @Override + public int applyMending(int amount) { + ServerPlayer handle = getHandle(); + // Logic copied from EntityExperienceOrb and remapped to unobfuscated methods/properties @@ -90,12 +89,13 @@ index 8a5bf0b83c1e65f07e14da0e053a64c34976b91a..efdcb8dac8db15c4bbaed84a7861ce98 + return amount; + } + -+ @Override + @Override +- public void giveExp(int exp) { + public void giveExp(int exp, boolean applyMending) { + if (applyMending) { + exp = this.applyMending(exp); + } + // Paper end - getHandle().giveExperiencePoints(exp); + this.getHandle().giveExperiencePoints(exp); } diff --git a/patches/server-remapped/0186-Make-max-squid-spawn-height-configurable.patch b/patches/server/0171-Make-max-squid-spawn-height-configurable.patch similarity index 55% rename from patches/server-remapped/0186-Make-max-squid-spawn-height-configurable.patch rename to patches/server/0171-Make-max-squid-spawn-height-configurable.patch index 94fb614365..c6e51b97e4 100644 --- a/patches/server-remapped/0186-Make-max-squid-spawn-height-configurable.patch +++ b/patches/server/0171-Make-max-squid-spawn-height-configurable.patch @@ -7,12 +7,12 @@ I don't know why upstream made only the minimum height configurable but whatever diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6c692e58cde22003ecbf6dc5695799147c39905a..3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2 100644 +index 90ca51dfdbb3045dd528450225cba96f5834166e..3577100f850975020b74f077d688f59dbca78962 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -348,4 +348,9 @@ public class PaperWorldConfig { - expMergeMaxValue = getInt("experience-merge-max-value", -1); - log("Experience Merge Max Value: " + expMergeMaxValue); +@@ -342,4 +342,9 @@ public class PaperWorldConfig { + disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); + log("Creeper lingering effect: " + disableCreeperLingeringEffect); } + + public double squidMaxSpawnHeight; @@ -21,16 +21,16 @@ index 6c692e58cde22003ecbf6dc5695799147c39905a..3c39f1bb3d88baaaed4dd43c51faeef8 + } } diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java -index 0b782c77f6d93002c35b123044b5a3eb03e63672..5a7582fd4f8e883d2f08a0227932c17d7576b957 100644 +index 5faa9e05e041a8bdcac88f3c3af7620353c10c3a..714e521ee96612bbc479e497f0520097b548472b 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Squid.java +++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java -@@ -196,7 +196,8 @@ public class Squid extends WaterAnimal { +@@ -211,7 +211,8 @@ public class Squid extends WaterAnimal { } public static boolean checkSquidSpawnRules(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) { -- return pos.getY() > world.getLevel().spigotConfig.squidSpawnRangeMin && pos.getY() < world.getSeaLevel(); // Spigot -+ final double maxHeight = world.getLevel().paperConfig.squidMaxSpawnHeight > 0 ? world.getLevel().paperConfig.squidMaxSpawnHeight : world.getSeaLevel(); // Paper -+ return pos.getY() > world.getLevel().spigotConfig.squidSpawnRangeMin && pos.getY() < maxHeight; // Spigot // Paper +- return pos.getY() > world.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && pos.getY() < world.getSeaLevel(); // Spigot ++ final double maxHeight = world.getMinecraftWorld().paperConfig.squidMaxSpawnHeight > 0 ? world.getMinecraftWorld().paperConfig.squidMaxSpawnHeight : world.getSeaLevel(); // Paper ++ return pos.getY() > world.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && pos.getY() < maxHeight; // Spigot // Paper } - public void setMovementVector(float x, float y, float z) { + @Override diff --git a/patches/server-remapped/0188-PlayerNaturallySpawnCreaturesEvent.patch b/patches/server/0172-PlayerNaturallySpawnCreaturesEvent.patch similarity index 82% rename from patches/server-remapped/0188-PlayerNaturallySpawnCreaturesEvent.patch rename to patches/server/0172-PlayerNaturallySpawnCreaturesEvent.patch index 0b2a988e3b..4915467611 100644 --- a/patches/server-remapped/0188-PlayerNaturallySpawnCreaturesEvent.patch +++ b/patches/server/0172-PlayerNaturallySpawnCreaturesEvent.patch @@ -9,10 +9,10 @@ from triggering monster spawns on a server. Also a highly more effecient way to blanket block spawns in a world diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 3b6f35b695117bd2b0c71b994efc55fa1084eddc..97d5437df10a6d0124e944404e88650547b7d8a8 100644 +index 5a80ea6bee72921454fbbd6ee202dc114c481ea1..4b349960daaacd87c042b055adf36c0a66748f7f 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -964,12 +964,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -974,11 +974,21 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; chunkRange = (chunkRange > 8) ? 8 : chunkRange; @@ -22,9 +22,8 @@ index 3b6f35b695117bd2b0c71b994efc55fa1084eddc..97d5437df10a6d0124e944404e886505 // Spigot end long i = chunkcoordintpair.toLong(); - return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { -- return !entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot -+ // Paper start - + return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.getPlayers(i).noneMatch((entityplayer) -> { ++ // Paper start - add PlayerNaturallySpawnCreaturesEvent + com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; + double blockRange = 16384.0D; + if (reducedRange) { @@ -32,17 +31,15 @@ index 3b6f35b695117bd2b0c71b994efc55fa1084eddc..97d5437df10a6d0124e944404e886505 + if (event == null || event.isCancelled()) return false; + blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); + } -+ -+ return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot + // Paper end + return !entityplayer.isSpectator() && ChunkMap.euclideanDistanceSquared(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot }); } - diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index d0b0fdaf5451bcc7f7ac7dab28aa59ef77e6dd97..a7122a0411f4a8656efd4facde3403c8093bc8a6 100644 +index 2cea8b1e8c414c8715ce61d61168dfb9d5c2200c..4a343fa19566f468aca17228379f4d75f3f56f28 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -612,6 +612,15 @@ public class ServerChunkCache extends ChunkSource { +@@ -632,6 +632,15 @@ public class ServerChunkCache extends ChunkSource { this.level.getProfiler().pop(); //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper //Collections.shuffle(list); // Paper @@ -59,7 +56,7 @@ index d0b0fdaf5451bcc7f7ac7dab28aa59ef77e6dd97..a7122a0411f4a8656efd4facde3403c8 this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 4ff66138fa43cf932b95d6d3dc050a9cd7b28ad4..0fa977a31cf945b74f3a046b6be302b10f494ad1 100644 +index 1c4f3a1cfe808d59333e45c170caf0d760a709c9..7159a433e9a264d2151dddc84a74689d0bc7635b 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1,5 +1,6 @@ @@ -69,7 +66,7 @@ index 4ff66138fa43cf932b95d6d3dc050a9cd7b28ad4..0fa977a31cf945b74f3a046b6be302b1 import com.google.common.collect.Lists; import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Either; -@@ -225,6 +226,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -232,6 +233,7 @@ public class ServerPlayer extends Player { public boolean sentListPacket = false; public Integer clientViewDistance; // CraftBukkit end From 2397b86efaebaae59e224654539c63d99da4c5be Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Sat, 12 Jun 2021 09:56:13 -0700 Subject: [PATCH 048/226] more patches (#5807) --- ...Add-setPlayerProfile-API-for-Skulls.patch} | 0 .../0082-Fill-Profile-Property-Events.patch} | 0 ...layerAdvancementCriterionGrantEvent.patch} | 0 .../0084-Add-ArmorStand-Item-Meta.patch} | 0 .../0085-Optimize-Hoppers.patch} | 0 .../0086-Tameable-getOwnerUniqueId-API.patch} | 0 ...-PlayerProfile-in-AsyncPreLoginEven.patch} | 2 +- ...d-extended-PaperServerListPingEvent.patch} | 0 .../0088-Player.setPlayerProfile-API.patch | 0 ...sted-Ice-from-loading-holding-chunks.patch | 1 + patches/server/0006-MC-Utils.patch | 18 ++ ...-MinecraftKey-Information-to-Objects.patch | 13 +- .../server/0099-Fix-Old-Sign-Conversion.patch | 4 +- .../0164-Add-PlayerArmorChangeEvent.patch | 12 -- ...-get-a-BlockState-without-a-snapshot.patch | 11 +- .../server/0168-AsyncTabCompleteEvent.patch | 4 +- ...0-Ability-to-apply-mending-to-XP-API.patch | 13 +- ...Add-setPlayerProfile-API-for-Skulls.patch} | 31 +--- .../0174-Fill-Profile-Property-Events.patch} | 0 ...layerAdvancementCriterionGrantEvent.patch} | 8 +- .../0176-Add-ArmorStand-Item-Meta.patch} | 108 ++++++------ ...Extend-Player-Interact-cancellation.patch} | 32 +--- .../0178-Tameable-getOwnerUniqueId-API.patch} | 14 +- ...-crits-helps-mitigate-hacked-client.patch} | 6 +- ...e-Explicit-Network-Manager-Flushing.patch} | 6 +- ...t-extended-PaperServerListPingEvent.patch} | 162 ++---------------- .../0182-Improved-Async-Task-Scheduler.patch} | 34 ++-- ...-PlayerProfile-in-AsyncPreLoginEven.patch} | 8 +- .../0184-Player.setPlayerProfile-API.patch} | 55 +++--- 29 files changed, 178 insertions(+), 364 deletions(-) rename patches/{api-unmapped/0080-Add-setPlayerProfile-API-for-Skulls.patch => api/0081-Add-setPlayerProfile-API-for-Skulls.patch} (100%) rename patches/{api-unmapped/0081-Fill-Profile-Property-Events.patch => api/0082-Fill-Profile-Property-Events.patch} (100%) rename patches/{api-unmapped/0082-PlayerAdvancementCriterionGrantEvent.patch => api/0083-PlayerAdvancementCriterionGrantEvent.patch} (100%) rename patches/{api-unmapped/0083-Add-ArmorStand-Item-Meta.patch => api/0084-Add-ArmorStand-Item-Meta.patch} (100%) rename patches/{api-unmapped/0084-Optimize-Hoppers.patch => api/0085-Optimize-Hoppers.patch} (100%) rename patches/{api-unmapped/0085-Tameable-getOwnerUniqueId-API.patch => api/0086-Tameable-getOwnerUniqueId-API.patch} (100%) rename patches/{api-unmapped/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch => api/0087-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch} (97%) rename patches/{api-unmapped/0087-Add-extended-PaperServerListPingEvent.patch => api/0088-Add-extended-PaperServerListPingEvent.patch} (100%) rename patches/{api-unmapped => api}/0088-Player.setPlayerProfile-API.patch (100%) rename patches/{server-remapped => removed/1.17}/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch (95%) rename patches/{server-remapped/0189-Add-setPlayerProfile-API-for-Skulls.patch => server/0173-Add-setPlayerProfile-API-for-Skulls.patch} (69%) rename patches/{server-remapped/0190-Fill-Profile-Property-Events.patch => server/0174-Fill-Profile-Property-Events.patch} (100%) rename patches/{server-remapped/0191-PlayerAdvancementCriterionGrantEvent.patch => server/0175-PlayerAdvancementCriterionGrantEvent.patch} (76%) rename patches/{server-remapped/0192-Add-ArmorStand-Item-Meta.patch => server/0176-Add-ArmorStand-Item-Meta.patch} (70%) rename patches/{server-remapped/0193-Extend-Player-Interact-cancellation.patch => server/0177-Extend-Player-Interact-cancellation.patch} (60%) rename patches/{server-remapped/0194-Tameable-getOwnerUniqueId-API.patch => server/0178-Tameable-getOwnerUniqueId-API.patch} (70%) rename patches/{server-remapped/0195-Toggleable-player-crits-helps-mitigate-hacked-client.patch => server/0179-Toggleable-player-crits-helps-mitigate-hacked-client.patch} (87%) rename patches/{server-remapped/0197-Disable-Explicit-Network-Manager-Flushing.patch => server/0180-Disable-Explicit-Network-Manager-Flushing.patch} (86%) rename patches/{server-remapped/0198-Implement-extended-PaperServerListPingEvent.patch => server/0181-Implement-extended-PaperServerListPingEvent.patch} (57%) rename patches/{server-remapped/0199-Improved-Async-Task-Scheduler.patch => server/0182-Improved-Async-Task-Scheduler.patch} (91%) rename patches/{server-remapped/0200-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch => server/0183-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch} (88%) rename patches/{server-remapped/0201-Player.setPlayerProfile-API.patch => server/0184-Player.setPlayerProfile-API.patch} (72%) diff --git a/patches/api-unmapped/0080-Add-setPlayerProfile-API-for-Skulls.patch b/patches/api/0081-Add-setPlayerProfile-API-for-Skulls.patch similarity index 100% rename from patches/api-unmapped/0080-Add-setPlayerProfile-API-for-Skulls.patch rename to patches/api/0081-Add-setPlayerProfile-API-for-Skulls.patch diff --git a/patches/api-unmapped/0081-Fill-Profile-Property-Events.patch b/patches/api/0082-Fill-Profile-Property-Events.patch similarity index 100% rename from patches/api-unmapped/0081-Fill-Profile-Property-Events.patch rename to patches/api/0082-Fill-Profile-Property-Events.patch diff --git a/patches/api-unmapped/0082-PlayerAdvancementCriterionGrantEvent.patch b/patches/api/0083-PlayerAdvancementCriterionGrantEvent.patch similarity index 100% rename from patches/api-unmapped/0082-PlayerAdvancementCriterionGrantEvent.patch rename to patches/api/0083-PlayerAdvancementCriterionGrantEvent.patch diff --git a/patches/api-unmapped/0083-Add-ArmorStand-Item-Meta.patch b/patches/api/0084-Add-ArmorStand-Item-Meta.patch similarity index 100% rename from patches/api-unmapped/0083-Add-ArmorStand-Item-Meta.patch rename to patches/api/0084-Add-ArmorStand-Item-Meta.patch diff --git a/patches/api-unmapped/0084-Optimize-Hoppers.patch b/patches/api/0085-Optimize-Hoppers.patch similarity index 100% rename from patches/api-unmapped/0084-Optimize-Hoppers.patch rename to patches/api/0085-Optimize-Hoppers.patch diff --git a/patches/api-unmapped/0085-Tameable-getOwnerUniqueId-API.patch b/patches/api/0086-Tameable-getOwnerUniqueId-API.patch similarity index 100% rename from patches/api-unmapped/0085-Tameable-getOwnerUniqueId-API.patch rename to patches/api/0086-Tameable-getOwnerUniqueId-API.patch diff --git a/patches/api-unmapped/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/patches/api/0087-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch similarity index 97% rename from patches/api-unmapped/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch rename to patches/api/0087-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch index a2a9f5270f..ca04155516 100644 --- a/patches/api-unmapped/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch +++ b/patches/api/0087-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent This will allow you to change the players name or skin on login. diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -index 992d1025ca02020e87a9ab5db83d249427f41d69..a40b57edb1aeff71fc0b9767d410950da5c06283 100644 +index d3b4219a57fff4519ef8d803c333c854fafa7859..d512c23ad0275061593d99f005c72292dbb07e81 100644 --- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java @@ -2,6 +2,9 @@ package org.bukkit.event.player; diff --git a/patches/api-unmapped/0087-Add-extended-PaperServerListPingEvent.patch b/patches/api/0088-Add-extended-PaperServerListPingEvent.patch similarity index 100% rename from patches/api-unmapped/0087-Add-extended-PaperServerListPingEvent.patch rename to patches/api/0088-Add-extended-PaperServerListPingEvent.patch diff --git a/patches/api-unmapped/0088-Player.setPlayerProfile-API.patch b/patches/api/0088-Player.setPlayerProfile-API.patch similarity index 100% rename from patches/api-unmapped/0088-Player.setPlayerProfile-API.patch rename to patches/api/0088-Player.setPlayerProfile-API.patch diff --git a/patches/server-remapped/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/patches/removed/1.17/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch similarity index 95% rename from patches/server-remapped/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch rename to patches/removed/1.17/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch index 4b912daff9..b7ea1f0c46 100644 --- a/patches/server-remapped/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch +++ b/patches/removed/1.17/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch @@ -3,6 +3,7 @@ From: Aikar Date: Sat, 10 Mar 2018 16:33:15 -0500 Subject: [PATCH] Prevent Frosted Ice from loading/holding chunks +1.17: Shouldn't be needed as blocks no longer tick without at least 1 radius chunk loaded. diff --git a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java index ae2f5acd008d5d7163b56cb4a2d29354299959ca..99843f1ca4737d40ae0626fce931c97bbf5ab81d 100644 diff --git a/patches/server/0006-MC-Utils.patch b/patches/server/0006-MC-Utils.patch index 3101a34f9a..9d1ed65d5c 100644 --- a/patches/server/0006-MC-Utils.patch +++ b/patches/server/0006-MC-Utils.patch @@ -3518,6 +3518,24 @@ index 65bd706ca96f5c0ec4573da9fb144fb51d2de919..3a2e8bdc215a6af604bfaad01b670a36 public long[] getRaw() { return this.data; } +diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +index 08fb847add9f5a2c1ca6dfef31de7e711c8b9840..5b38966093fe60b298844961d015d5a9f03412a2 100644 +--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java ++++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +@@ -78,6 +78,13 @@ public abstract class BlockableEventLoop implements Profiler + } + + } ++ // Paper start ++ public void scheduleOnMain(Runnable r0) { ++ // postToMainThread does not work the same as older versions of mc ++ // This method is actually used to create a TickTask, which can then be posted onto main ++ this.tell(this.wrapRunnable(r0)); ++ } ++ // Paper end + + @Override + public void tell(R runnable) { diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java index 7f3d83d3d071f6b441ad119b1c93be035e911e70..89e7d02b88404ac5dce06595432ae95c9a4e5015 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java diff --git a/patches/server/0008-Add-MinecraftKey-Information-to-Objects.patch b/patches/server/0008-Add-MinecraftKey-Information-to-Objects.patch index b96b5157a6..c0c8c9453a 100644 --- a/patches/server/0008-Add-MinecraftKey-Information-to-Objects.patch +++ b/patches/server/0008-Add-MinecraftKey-Information-to-Objects.patch @@ -95,7 +95,7 @@ index 89e7d02b88404ac5dce06595432ae95c9a4e5015..3ffaeb72be8cda7a2b9398b8909db5c2 return this.serialize; } diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 33884161de688c47c90a7b86196234acc80f9434..e4601134598e509a158ceacec6099a78bbabe89d 100644 +index 33884161de688c47c90a7b86196234acc80f9434..92b042080f06fb95958ff5e824830a84f2d1f2a6 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java @@ -20,7 +20,7 @@ import org.bukkit.inventory.InventoryHolder; @@ -107,15 +107,6 @@ index 33884161de688c47c90a7b86196234acc80f9434..e4601134598e509a158ceacec6099a78 public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot // CraftBukkit start - data containers -@@ -28,7 +28,7 @@ public abstract class BlockEntity { - public CraftPersistentDataContainer persistentDataContainer; - // CraftBukkit end - private static final Logger LOGGER = LogManager.getLogger(); -- private final BlockEntityType type; -+ private final BlockEntityType type; public BlockEntityType getTileEntityType() { return type; } // Paper - OBFHELPER - @Nullable - protected Level level; - protected final BlockPos worldPosition; @@ -41,6 +41,26 @@ public abstract class BlockEntity { this.blockState = state; } @@ -127,7 +118,7 @@ index 33884161de688c47c90a7b86196234acc80f9434..e4601134598e509a158ceacec6099a78 + @Override + public ResourceLocation getMinecraftKey() { + if (tileEntityKey == null) { -+ tileEntityKey = BlockEntityType.getKey(this.getTileEntityType()); ++ tileEntityKey = BlockEntityType.getKey(this.type); + tileEntityKeyString = tileEntityKey != null ? tileEntityKey.toString() : null; + } + return tileEntityKey; diff --git a/patches/server/0099-Fix-Old-Sign-Conversion.patch b/patches/server/0099-Fix-Old-Sign-Conversion.patch index 017485dabf..21eb3aa76c 100644 --- a/patches/server/0099-Fix-Old-Sign-Conversion.patch +++ b/patches/server/0099-Fix-Old-Sign-Conversion.patch @@ -9,7 +9,7 @@ Subject: [PATCH] Fix Old Sign Conversion This causes Igloos and such to render broken signs. We fix this by ignoring sign conversion for Defined Structures diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index d6a4a2a59f1be0cc2e373dc326287b60db5559d2..9d777fce673c8f6b3ee2d69f5a6360a8a5ad8e84 100644 +index 66ab4deedd177f507d170a61ceca4c3ebbac9adc..77645019c88d61dde28b7598d8a29b7d0c23c209 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java @@ -30,6 +30,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { @@ -17,7 +17,7 @@ index d6a4a2a59f1be0cc2e373dc326287b60db5559d2..9d777fce673c8f6b3ee2d69f5a6360a8 // CraftBukkit end private static final Logger LOGGER = LogManager.getLogger(); + public boolean isLoadingStructure = false; // Paper - private final BlockEntityType type; public BlockEntityType getTileEntityType() { return type; } // Paper - OBFHELPER + private final BlockEntityType type; @Nullable protected Level level; diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java diff --git a/patches/server/0164-Add-PlayerArmorChangeEvent.patch b/patches/server/0164-Add-PlayerArmorChangeEvent.patch index 21828275b6..1c55b80d5e 100644 --- a/patches/server/0164-Add-PlayerArmorChangeEvent.patch +++ b/patches/server/0164-Add-PlayerArmorChangeEvent.patch @@ -4,18 +4,6 @@ Date: Fri, 10 Nov 2017 23:46:34 -0500 Subject: [PATCH] Add PlayerArmorChangeEvent -diff --git a/src/main/java/net/minecraft/world/entity/EquipmentSlot.java b/src/main/java/net/minecraft/world/entity/EquipmentSlot.java -index c82bb38b5b1c9204daef21455723d21509ad1c44..135a62fcdbd801c9997bc28c071743e8ff8c64c2 100644 ---- a/src/main/java/net/minecraft/world/entity/EquipmentSlot.java -+++ b/src/main/java/net/minecraft/world/entity/EquipmentSlot.java -@@ -20,6 +20,7 @@ public enum EquipmentSlot { - this.name = name; - } - -+ public EquipmentSlot.Type getType() { return this.getType(); } // Paper - OBFHELPER - public EquipmentSlot.Type getType() { - return this.type; - } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java index 89913edf98d65f08f379d0d201f9963c23573478..28de49c8b5771491b168bba26e6033669c48e3c9 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java diff --git a/patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch b/patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch index 7b37b5ad1d..c5483d657a 100644 --- a/patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch +++ b/patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch @@ -13,18 +13,9 @@ also Avoid NPE during CraftBlockEntityState load if could not get TE If Tile Entity was null, correct Sign to return empty lines instead of null diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 9d777fce673c8f6b3ee2d69f5a6360a8a5ad8e84..c3706b87ad36332a837caffb58bd4575cbc0172a 100644 +index 77645019c88d61dde28b7598d8a29b7d0c23c209..8a079ee3ed243fd19b1dd7eed2de1dd33785faa1 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -31,7 +31,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - // CraftBukkit end - private static final Logger LOGGER = LogManager.getLogger(); - public boolean isLoadingStructure = false; // Paper -- private final BlockEntityType type; public BlockEntityType getTileEntityType() { return type; } // Paper - OBFHELPER -+ private final BlockEntityType type; - @Nullable - protected Level level; - protected final BlockPos worldPosition; @@ -42,6 +42,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { this.type = type; this.worldPosition = pos.immutable(); diff --git a/patches/server/0168-AsyncTabCompleteEvent.patch b/patches/server/0168-AsyncTabCompleteEvent.patch index 8cb41e523d..22bff78e55 100644 --- a/patches/server/0168-AsyncTabCompleteEvent.patch +++ b/patches/server/0168-AsyncTabCompleteEvent.patch @@ -14,7 +14,7 @@ completion, such as offline players. Also adds isCommand and getLocation to the sync TabCompleteEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index b2bbd25e5572f59add71579b676d5a4c719be239..737296e90e3547505a012fc516a4fc39a565343e 100644 +index b2bbd25e5572f59add71579b676d5a4c719be239..205e4ef25f49edc11a408c302d9ba68a59c68a5a 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -703,10 +703,10 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @@ -39,7 +39,7 @@ index b2bbd25e5572f59add71579b676d5a4c719be239..737296e90e3547505a012fc516a4fc39 + com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; + java.util.List completions = new java.util.ArrayList<>(); + String buffer = packet.getCommand(); -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getCraftPlayer(), completions, + buffer, true, null); + event.callEvent(); + completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); diff --git a/patches/server/0170-Ability-to-apply-mending-to-XP-API.patch b/patches/server/0170-Ability-to-apply-mending-to-XP-API.patch index 06411572db..24489b2e5c 100644 --- a/patches/server/0170-Ability-to-apply-mending-to-XP-API.patch +++ b/patches/server/0170-Ability-to-apply-mending-to-XP-API.patch @@ -27,22 +27,25 @@ index 8203c93dcb56646df2614f2233aaf3a36f745d1c..71fb831ed3359e7986e279c987211f39 return experienceAmount * 2; } diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java -index 27cdfbeb6cb2159075b35dd4f9e9557ec0eac7c2..d2d7b303e66bbba489e2003cc130dcd53e2a9854 100644 +index 27cdfbeb6cb2159075b35dd4f9e9557ec0eac7c2..069ce59faab5184ab9da8ca3fe1cebf7449cd7fe 100644 --- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java +++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java -@@ -246,8 +246,8 @@ public class EnchantmentHelper { +@@ -246,8 +246,11 @@ public class EnchantmentHelper { return getItemEnchantmentLevel(Enchantments.CHANNELING, stack) > 0; } - @Nullable - public static Entry getRandomItemWith(Enchantment enchantment, LivingEntity entity) { -+ public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, LivingEntity entityliving) { Entry entry = getRandomItemWith(enchantment, entityliving); return entry != null ? entry.getValue() : ItemStack.NULL_ITEM; } // Paper - OBFHELPER ++ public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, LivingEntity entityliving) { ++ Entry entry = getRandomItemWith(enchantment, entityliving); ++ return entry != null ? entry.getValue() : ItemStack.EMPTY; ++ } // Paper - OBFHELPER + @Nullable public static Entry getRandomItemWith(Enchantment enchantment, LivingEntity entity) { return getRandomItemWith(enchantment, entity, (stack) -> { 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 ed1c57f22adc8b96012eca426ed1e7b409e7d663..b1778f53de7974e03c7b56b0df69e31cdae8dd62 100644 +index ed1c57f22adc8b96012eca426ed1e7b409e7d663..75963a28b39f8835f1daba3d1b44655603124bf3 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -61,11 +61,14 @@ import net.minecraft.server.level.ServerPlayer; @@ -80,7 +83,7 @@ index ed1c57f22adc8b96012eca426ed1e7b409e7d663..b1778f53de7974e03c7b56b0df69e31c + int i = Math.min(orb.xpToDur(amount), itemstack.getDamageValue()); + org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, i); + i = event.getRepairAmount(); -+ orb.removed = true; ++ orb.discard(); + if (!event.isCancelled()) { + amount -= orb.durToXp(i); + itemstack.setDamageValue(itemstack.getDamageValue() - i); diff --git a/patches/server-remapped/0189-Add-setPlayerProfile-API-for-Skulls.patch b/patches/server/0173-Add-setPlayerProfile-API-for-Skulls.patch similarity index 69% rename from patches/server-remapped/0189-Add-setPlayerProfile-API-for-Skulls.patch rename to patches/server/0173-Add-setPlayerProfile-API-for-Skulls.patch index 746bff56a9..8c638a6d93 100644 --- a/patches/server-remapped/0189-Add-setPlayerProfile-API-for-Skulls.patch +++ b/patches/server/0173-Add-setPlayerProfile-API-for-Skulls.patch @@ -7,7 +7,7 @@ This allows you to create already filled textures on Skulls to avoid texture loo which commonly cause rate limit issues with Mojang API diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -index 2047ea32489d03051783d18a0dbaf456bfdbb2a1..a06c51a56846750ce59a70e9698c2b57c3517aad 100644 +index 1879ae835c437883f76330d6e2707460273d02db..df0ba7ed56fc635a4aa30934d1990043dbc3d8dc 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java @@ -1,5 +1,7 @@ @@ -18,15 +18,7 @@ index 2047ea32489d03051783d18a0dbaf456bfdbb2a1..a06c51a56846750ce59a70e9698c2b57 import com.google.common.base.Preconditions; import com.mojang.authlib.GameProfile; import net.minecraft.server.MinecraftServer; -@@ -15,6 +17,7 @@ import org.bukkit.block.data.BlockData; - import org.bukkit.block.data.Directional; - import org.bukkit.block.data.Rotatable; - import org.bukkit.craftbukkit.entity.CraftPlayer; -+import javax.annotation.Nullable; - - public class CraftSkull extends CraftBlockEntityState implements Skull { - -@@ -105,6 +108,20 @@ public class CraftSkull extends CraftBlockEntityState implemen +@@ -105,6 +107,20 @@ public class CraftSkull extends CraftBlockEntityState implemen } } @@ -37,7 +29,7 @@ index 2047ea32489d03051783d18a0dbaf456bfdbb2a1..a06c51a56846750ce59a70e9698c2b57 + this.profile = CraftPlayerProfile.asAuthlibCopy(profile); + } + -+ @Nullable ++ @javax.annotation.Nullable + @Override + public PlayerProfile getPlayerProfile() { + return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; @@ -48,7 +40,7 @@ index 2047ea32489d03051783d18a0dbaf456bfdbb2a1..a06c51a56846750ce59a70e9698c2b57 public BlockFace getRotation() { BlockData blockData = getBlockData(); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index 750661540f55d3c59119dcc909e706e571a2123b..aa64ffc23d8941ff05ea7791ddd628c3c6be90e4 100644 +index 5e345224e698bd80133dc194385c033369a60a33..33994a050826d10d69f375f65ecce2b56116cca0 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java @@ -4,10 +4,8 @@ import com.google.common.collect.ImmutableMap.Builder; @@ -77,7 +69,7 @@ index 750661540f55d3c59119dcc909e706e571a2123b..aa64ffc23d8941ff05ea7791ddd628c3 class CraftMetaSkull extends CraftMetaItem implements SkullMeta { @@ -149,6 +152,19 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - return hasOwner() ? profile.getName() : null; + return this.hasOwner() ? this.profile.getName() : null; } + // Paper start @@ -95,15 +87,4 @@ index 750661540f55d3c59119dcc909e706e571a2123b..aa64ffc23d8941ff05ea7791ddd628c3 + @Override public OfflinePlayer getOwningPlayer() { - if (hasOwner()) { -@@ -175,8 +191,8 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - } else { - // Paper start - Use Online Players Skull - GameProfile newProfile = null; -- net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); -- if (player != null) newProfile = player.getProfile(); -+ net.minecraft.server.level.ServerPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); -+ if (player != null) newProfile = player.getGameProfile(); - if (newProfile == null) newProfile = new GameProfile(null, name); - setProfile(newProfile); - // Paper end + if (this.hasOwner()) { diff --git a/patches/server-remapped/0190-Fill-Profile-Property-Events.patch b/patches/server/0174-Fill-Profile-Property-Events.patch similarity index 100% rename from patches/server-remapped/0190-Fill-Profile-Property-Events.patch rename to patches/server/0174-Fill-Profile-Property-Events.patch diff --git a/patches/server-remapped/0191-PlayerAdvancementCriterionGrantEvent.patch b/patches/server/0175-PlayerAdvancementCriterionGrantEvent.patch similarity index 76% rename from patches/server-remapped/0191-PlayerAdvancementCriterionGrantEvent.patch rename to patches/server/0175-PlayerAdvancementCriterionGrantEvent.patch index 6190b30a26..2db6d486c2 100644 --- a/patches/server-remapped/0191-PlayerAdvancementCriterionGrantEvent.patch +++ b/patches/server/0175-PlayerAdvancementCriterionGrantEvent.patch @@ -5,16 +5,16 @@ Subject: [PATCH] PlayerAdvancementCriterionGrantEvent diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java -index 8df1803754817707a5ad292f65276871dacc4508..5ab62fc74085bbbb0c81b2f4d16a35c9345cd1f1 100644 +index f26bdd3d6eb0ae38c1d7b50f29942fcf2207e3a1..3d82f984648605d58fae3c57f145d0da8a2ae225 100644 --- a/src/main/java/net/minecraft/server/PlayerAdvancements.java +++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java -@@ -297,6 +297,12 @@ public class PlayerAdvancements { +@@ -277,6 +277,12 @@ public class PlayerAdvancements { boolean flag1 = advancementprogress.isDone(); - if (advancementprogress.a(criterionName)) { + if (advancementprogress.grantProgress(criterionName)) { + // Paper start + if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.bukkit, criterionName).callEvent()) { -+ advancementprogress.b(criterionName); ++ advancementprogress.revokeProgress(criterionName); + return false; + } + // Paper end diff --git a/patches/server-remapped/0192-Add-ArmorStand-Item-Meta.patch b/patches/server/0176-Add-ArmorStand-Item-Meta.patch similarity index 70% rename from patches/server-remapped/0192-Add-ArmorStand-Item-Meta.patch rename to patches/server/0176-Add-ArmorStand-Item-Meta.patch index 14798cca5e..636222360f 100644 --- a/patches/server-remapped/0192-Add-ArmorStand-Item-Meta.patch +++ b/patches/server/0176-Add-ArmorStand-Item-Meta.patch @@ -13,7 +13,7 @@ starting point for future additions in this area. Fixes GH-559 diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -index 783b9c7283492fb71776b61f9820c21a39868c47..6521f4f6f660885f59f024640239609fb67d691f 100644 +index aee796567f11c8b93ac9ec0b8cb8f3a8412b23ce..39b98305632271e7375afe6c7001f241c17e103d 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java @@ -9,9 +9,22 @@ import org.bukkit.configuration.serialization.DelegateDeserialization; @@ -54,10 +54,10 @@ index 783b9c7283492fb71776b61f9820c21a39868c47..6521f4f6f660885f59f024640239609f this.entityTag = armorStand.entityTag; } -@@ -30,11 +50,47 @@ public class CraftMetaArmorStand extends CraftMetaItem { +@@ -30,11 +50,40 @@ public class CraftMetaArmorStand extends CraftMetaItem { if (tag.contains(ENTITY_TAG.NBT)) { - entityTag = tag.getCompound(ENTITY_TAG.NBT); + this.entityTag = tag.getCompound(ENTITY_TAG.NBT); + + // Paper start + if (entityTag.contains(INVISIBLE.NBT)) { @@ -85,120 +85,112 @@ index 783b9c7283492fb71776b61f9820c21a39868c47..6521f4f6f660885f59f024640239609f CraftMetaArmorStand(Map map) { super(map); -+ + // Paper start -+ boolean invis = SerializableMeta.getBoolean(map, INVISIBLE.BUKKIT); -+ boolean noBase = SerializableMeta.getBoolean(map, NO_BASE_PLATE.BUKKIT); -+ boolean showArms = SerializableMeta.getBoolean(map, SHOW_ARMS.BUKKIT); -+ boolean small = SerializableMeta.getBoolean(map, SMALL.BUKKIT); -+ boolean marker = SerializableMeta.getBoolean(map, MARKER.BUKKIT); -+ -+ this.invisible = invis; -+ this.noBasePlate = noBase; -+ this.showArms = showArms; -+ this.small = small; -+ this.marker = marker; ++ this.invisible = SerializableMeta.getBoolean(map, INVISIBLE.BUKKIT); ++ this.noBasePlate = SerializableMeta.getBoolean(map, NO_BASE_PLATE.BUKKIT); ++ this.showArms = SerializableMeta.getBoolean(map, SHOW_ARMS.BUKKIT); ++ this.small = SerializableMeta.getBoolean(map, SMALL.BUKKIT); ++ this.marker = SerializableMeta.getBoolean(map, MARKER.BUKKIT); + // Paper end } @Override -@@ -57,6 +113,32 @@ public class CraftMetaArmorStand extends CraftMetaItem { +@@ -57,6 +106,31 @@ public class CraftMetaArmorStand extends CraftMetaItem { void applyToItem(CompoundTag tag) { super.applyToItem(tag); + // Paper start -+ if (!isArmorStandEmpty() && entityTag == null) { -+ entityTag = new CompoundTag(); ++ if (!isArmorStandEmpty() && this.entityTag == null) { ++ this.entityTag = new CompoundTag(); + } + + if (isInvisible()) { -+ entityTag.putBoolean(INVISIBLE.NBT, invisible); ++ this.entityTag.putBoolean(INVISIBLE.NBT, this.invisible); + } + + if (hasNoBasePlate()) { -+ entityTag.putBoolean(NO_BASE_PLATE.NBT, noBasePlate); ++ this.entityTag.putBoolean(NO_BASE_PLATE.NBT, this.noBasePlate); + } + + if (shouldShowArms()) { -+ entityTag.putBoolean(SHOW_ARMS.NBT, showArms); ++ this.entityTag.putBoolean(SHOW_ARMS.NBT, this.showArms); + } + + if (isSmall()) { -+ entityTag.putBoolean(SMALL.NBT, small); ++ this.entityTag.putBoolean(SMALL.NBT, this.small); + } + + if (isMarker()) { -+ entityTag.putBoolean(MARKER.NBT, marker); ++ this.entityTag.putBoolean(MARKER.NBT, this.marker); + } + // Paper end -+ - if (entityTag != null) { + if (this.entityTag != null) { tag.put(ENTITY_TAG.NBT, entityTag); } -@@ -78,7 +160,7 @@ public class CraftMetaArmorStand extends CraftMetaItem { +@@ -78,7 +152,7 @@ public class CraftMetaArmorStand extends CraftMetaItem { } boolean isArmorStandEmpty() { -- return !(entityTag != null); -+ return !(isInvisible() || hasNoBasePlate() || shouldShowArms() || isSmall() || isMarker() || entityTag != null); +- return !(this.entityTag != null); ++ return !(this.isInvisible() || this.hasNoBasePlate() || this.shouldShowArms() || this.isSmall() || this.isMarker() || this.entityTag != null); } @Override -@@ -89,7 +171,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { +@@ -89,7 +163,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { if (meta instanceof CraftMetaArmorStand) { CraftMetaArmorStand that = (CraftMetaArmorStand) meta; -- return entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : entityTag == null; +- return this.entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : this.entityTag == null; + // Paper start -+ return invisible == that.invisible && -+ noBasePlate == that.noBasePlate && -+ showArms == that.showArms && -+ small == that.small && -+ marker == that.marker; ++ return this.invisible == that.invisible && ++ this.noBasePlate == that.noBasePlate && ++ this.showArms == that.showArms && ++ this.small == that.small && ++ this.marker == that.marker; + // Paper end } return true; } -@@ -104,9 +192,14 @@ public class CraftMetaArmorStand extends CraftMetaItem { +@@ -104,9 +184,14 @@ public class CraftMetaArmorStand extends CraftMetaItem { final int original; int hash = original = super.applyHash(); -- if (entityTag != null) { -- hash = 73 * hash + entityTag.hashCode(); +- if (this.entityTag != null) { +- hash = 73 * hash + this.entityTag.hashCode(); - } + // Paper start -+ hash += entityTag != null ? 73 * hash + entityTag.hashCode() : 0; -+ hash += isInvisible() ? 61 * hash + 1231 : 0; -+ hash += hasNoBasePlate() ? 61 * hash + 1231 : 0; -+ hash += shouldShowArms() ? 61 * hash + 1231 : 0; -+ hash += isSmall() ? 61 * hash + 1231 : 0; -+ hash += isMarker() ? 61 * hash + 1231 : 0; ++ hash += this.entityTag != null ? 73 * hash + this.entityTag.hashCode() : 0; ++ hash += this.isInvisible() ? 61 * hash + 1231 : 0; ++ hash += this.hasNoBasePlate() ? 61 * hash + 1231 : 0; ++ hash += this.shouldShowArms() ? 61 * hash + 1231 : 0; ++ hash += this.isSmall() ? 61 * hash + 1231 : 0; ++ hash += this.isMarker() ? 61 * hash + 1231 : 0; + // Paper end return original != hash ? CraftMetaArmorStand.class.hashCode() ^ hash : hash; } -@@ -115,6 +208,28 @@ public class CraftMetaArmorStand extends CraftMetaItem { +@@ -115,6 +200,28 @@ public class CraftMetaArmorStand extends CraftMetaItem { Builder serialize(Builder builder) { super.serialize(builder); + // Paper start -+ if (isInvisible()) { ++ if (this.isInvisible()) { + builder.put(INVISIBLE.BUKKIT, invisible); + } + -+ if (hasNoBasePlate()) { ++ if (this.hasNoBasePlate()) { + builder.put(NO_BASE_PLATE.BUKKIT, noBasePlate); + } + -+ if (shouldShowArms()) { ++ if (this.shouldShowArms()) { + builder.put(SHOW_ARMS.BUKKIT, showArms); + } + -+ if (isSmall()) { ++ if (this.isSmall()) { + builder.put(SMALL.BUKKIT, small); + } + -+ if (isMarker()) { ++ if (this.isMarker()) { + builder.put(MARKER.BUKKIT, marker); + } + // Paper end @@ -206,7 +198,7 @@ index 783b9c7283492fb71776b61f9820c21a39868c47..6521f4f6f660885f59f024640239609f return builder; } -@@ -128,4 +243,56 @@ public class CraftMetaArmorStand extends CraftMetaItem { +@@ -128,4 +235,56 @@ public class CraftMetaArmorStand extends CraftMetaItem { return clone; } @@ -264,10 +256,10 @@ index 783b9c7283492fb71776b61f9820c21a39868c47..6521f4f6f660885f59f024640239609f + // 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 521699615778c4b724d10edfee1d3915e036eb2e..64f166fa93e998a58a895d785ff8c9e62dacb1bb 100644 +index 45f4f8265c51a5b08db8aa7f53915c4bd0536d39..4ad6fd7e110f949f0bd859331ed6a5109ade3008 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -1441,6 +1441,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -1442,6 +1442,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { CraftMetaCrossbow.CHARGED.NBT, CraftMetaCrossbow.CHARGED_PROJECTILES.NBT, CraftMetaSuspiciousStew.EFFECTS.NBT, @@ -281,15 +273,15 @@ index 521699615778c4b724d10edfee1d3915e036eb2e..64f166fa93e998a58a895d785ff8c9e6 + // Paper end CraftMetaCompass.LODESTONE_DIMENSION.NBT, CraftMetaCompass.LODESTONE_POS.NBT, - CraftMetaCompass.LODESTONE_TRACKED.NBT + CraftMetaCompass.LODESTONE_TRACKED.NBT, diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -index 9a351c137776ac622f4df7353bb353142b3a6ccc..42f577ed3508ba5a380648461e149f16ce97c9bd 100644 +index c1fc48881dffa61f461078bea5640f8c1a1f6570..b0bb30aebdba99a8fa929ec3c56e46b59d2467c9 100644 --- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -@@ -313,6 +313,7 @@ public class ItemMetaTest extends AbstractTestingBase { +@@ -314,6 +314,7 @@ public class ItemMetaTest extends AbstractTestingBase { final CraftMetaArmorStand meta = (CraftMetaArmorStand) cleanStack.getItemMeta(); - meta.entityTag = new NBTTagCompound(); - meta.entityTag.setBoolean("Small", true); + meta.entityTag = new CompoundTag(); + meta.entityTag.putBoolean("Small", true); + meta.setInvisible(true); // Paper cleanStack.setItemMeta(meta); return cleanStack; diff --git a/patches/server-remapped/0193-Extend-Player-Interact-cancellation.patch b/patches/server/0177-Extend-Player-Interact-cancellation.patch similarity index 60% rename from patches/server-remapped/0193-Extend-Player-Interact-cancellation.patch rename to patches/server/0177-Extend-Player-Interact-cancellation.patch index 826fede56c..670211c9b7 100644 --- a/patches/server-remapped/0193-Extend-Player-Interact-cancellation.patch +++ b/patches/server/0177-Extend-Player-Interact-cancellation.patch @@ -13,19 +13,11 @@ Update adjacent blocks of doors, double plants, pistons and beds when cancelling interaction. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index 26ce794cb8d089c03fab5dd0a0c910783d10b72e..b1a53093eb5b5f359eedb6c252cf6d0d1ae8e409 100644 +index 9d303a962950c7464d1d4a2a0ce3f658628cc785..a67b7c82236d448bf10c257ab0a10476372ce89c 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -23,6 +23,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; - import net.minecraft.network.protocol.game.ClientboundBlockBreakAckPacket; - import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; -+import net.minecraft.network.protocol.game.ClientboundContainerClosePacket; - import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket; - import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; - import net.minecraft.server.MinecraftServer; -@@ -180,6 +181,11 @@ public class ServerPlayerGameMode { - PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, direction, this.player.inventory.getSelected(), InteractionHand.MAIN_HAND); +@@ -178,6 +178,11 @@ public class ServerPlayerGameMode { + PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, direction, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND); if (event.isCancelled()) { // Let the client know the block still exists + // Paper start - brute force neighbor blocks for any attached blocks @@ -36,23 +28,15 @@ index 26ce794cb8d089c03fab5dd0a0c910783d10b72e..b1a53093eb5b5f359eedb6c252cf6d0d this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); // Update any tile entity data for this block BlockEntity tileentity = this.level.getBlockEntity(pos); -@@ -484,6 +490,7 @@ public class ServerPlayerGameMode { - interactItemStack = stack.copy(); - - if (event.useInteractedBlock() == Event.Result.DENY) { -+ - // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. - if (iblockdata.getBlock() instanceof DoorBlock) { - boolean bottom = iblockdata.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER; -@@ -496,7 +503,13 @@ public class ServerPlayerGameMode { +@@ -493,7 +498,13 @@ public class ServerPlayerGameMode { // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.above())); + // Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method -+ } else if (iblockdata.getBlock() instanceof StructureBlock) { -+ player.connection.send(new ClientboundContainerClosePacket()); -+ } else if (iblockdata.getBlock() instanceof CommandBlock) { -+ player.connection.send(new ClientboundContainerClosePacket()); ++ } else if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.StructureBlock) { ++ player.connection.send(new net.minecraft.network.protocol.game.ClientboundContainerClosePacket(this.player.containerMenu.containerId)); ++ } else if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.CommandBlock) { ++ player.connection.send(new net.minecraft.network.protocol.game.ClientboundContainerClosePacket(this.player.containerMenu.containerId)); } + // Paper end - extend Player Interact cancellation player.getBukkitEntity().updateInventory(); // SPIGOT-2867 diff --git a/patches/server-remapped/0194-Tameable-getOwnerUniqueId-API.patch b/patches/server/0178-Tameable-getOwnerUniqueId-API.patch similarity index 70% rename from patches/server-remapped/0194-Tameable-getOwnerUniqueId-API.patch rename to patches/server/0178-Tameable-getOwnerUniqueId-API.patch index 643044c740..d872f6cd13 100644 --- a/patches/server-remapped/0194-Tameable-getOwnerUniqueId-API.patch +++ b/patches/server/0178-Tameable-getOwnerUniqueId-API.patch @@ -7,30 +7,32 @@ This is faster if all you need is the UUID, as .getOwner() will cause an OfflinePlayer to be loaded from disk. diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -index 6136b3322a340d506ce744bcd15f71a158e46ad1..04b0b2449f20220c74892788080d40e3693151c5 100644 +index 27a1ca43792644fc239af81dea5510f25d3328e9..69c95644b2531c1fe1c4a6cf7fee12e997dd67f4 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -@@ -89,6 +89,9 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac +@@ -89,6 +89,10 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac } } ++ @Override + public UUID getOwnerUniqueId() { + return getOwnerUUID(); + } public UUID getOwnerUUID() { - return getHandle().getOwnerUUID(); + return this.getHandle().getOwnerUUID(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -index 35587fd6d90dfd1da2075c3268692eac7a2eaa25..85fe4f07d35c514f2a7c7920ec416fb651434c83 100644 +index cc90c09c26b04689e4fffa890baf0e89c38665a3..0b152d8d20924fc1ce7f5bafb050216d250f6536 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -@@ -17,6 +17,9 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat +@@ -17,6 +17,10 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat return (TamableAnimal) super.getHandle(); } ++ @Override + public UUID getOwnerUniqueId() { + return getOwnerUUID(); + } public UUID getOwnerUUID() { try { - return getHandle().getOwnerUUID(); + return this.getHandle().getOwnerUUID(); diff --git a/patches/server-remapped/0195-Toggleable-player-crits-helps-mitigate-hacked-client.patch b/patches/server/0179-Toggleable-player-crits-helps-mitigate-hacked-client.patch similarity index 87% rename from patches/server-remapped/0195-Toggleable-player-crits-helps-mitigate-hacked-client.patch rename to patches/server/0179-Toggleable-player-crits-helps-mitigate-hacked-client.patch index 671d7965cc..92ccad3787 100644 --- a/patches/server-remapped/0195-Toggleable-player-crits-helps-mitigate-hacked-client.patch +++ b/patches/server/0179-Toggleable-player-crits-helps-mitigate-hacked-client.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Toggleable player crits, helps mitigate hacked clients. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2..48f0385c7203c7955de5a015f3dc42be2ab7b681 100644 +index 3577100f850975020b74f077d688f59dbca78962..da4a110809eee691c1d5b072de335d75e1516eae 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -192,6 +192,11 @@ public class PaperWorldConfig { @@ -21,10 +21,10 @@ index 3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2..48f0385c7203c7955de5a015f3dc42be private void allChunksAreSlimeChunks() { allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", 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 43868c1e2d2c858a4f02119c3238f615f9b1ee72..63871a3a1981b2e8c7ad74214196e35684acb584 100644 +index d3fe3eabf4465101760951113b23edf2ce03e57d..4e8d38a6379d3dc1b7167b27479e6a27ea19ea19 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1131,6 +1131,7 @@ public abstract class Player extends LivingEntity { +@@ -1191,6 +1191,7 @@ public abstract class Player extends LivingEntity { boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; diff --git a/patches/server-remapped/0197-Disable-Explicit-Network-Manager-Flushing.patch b/patches/server/0180-Disable-Explicit-Network-Manager-Flushing.patch similarity index 86% rename from patches/server-remapped/0197-Disable-Explicit-Network-Manager-Flushing.patch rename to patches/server/0180-Disable-Explicit-Network-Manager-Flushing.patch index 45eef88da2..1d1675c64e 100644 --- a/patches/server-remapped/0197-Disable-Explicit-Network-Manager-Flushing.patch +++ b/patches/server/0180-Disable-Explicit-Network-Manager-Flushing.patch @@ -12,10 +12,10 @@ flushing on the netty event loop, so it won't do the flush on the main thread. Renable flushing by passing -Dpaper.explicit-flush=true diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 3429c813a5b471cdfa561bd20849a303e5aacead..7f4681910751047a26fdfc6b59bc460449c02001 100644 +index 1d46187969b5792c255d0bf1966b427b905cb69c..0c5c62be83223e20f216df84413b8c2438db81ff 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java -@@ -73,6 +73,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -86,6 +86,7 @@ public class Connection extends SimpleChannelInboundHandler> { // Paper start - NetworkClient implementation public int protocolVersion; public java.net.InetSocketAddress virtualHost; @@ -23,7 +23,7 @@ index 3429c813a5b471cdfa561bd20849a303e5aacead..7f4681910751047a26fdfc6b59bc4604 // Paper end public Connection(PacketFlow side) { -@@ -240,7 +241,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -259,7 +260,7 @@ public class Connection extends SimpleChannelInboundHandler> { } if (this.channel != null) { diff --git a/patches/server-remapped/0198-Implement-extended-PaperServerListPingEvent.patch b/patches/server/0181-Implement-extended-PaperServerListPingEvent.patch similarity index 57% rename from patches/server-remapped/0198-Implement-extended-PaperServerListPingEvent.patch rename to patches/server/0181-Implement-extended-PaperServerListPingEvent.patch index 762c35c3ad..31680c41fc 100644 --- a/patches/server-remapped/0198-Implement-extended-PaperServerListPingEvent.patch +++ b/patches/server/0181-Implement-extended-PaperServerListPingEvent.patch @@ -175,55 +175,22 @@ index 0000000000000000000000000000000000000000..4c2351b03b58511b80017b58ee9b20ab + +} diff --git a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java -index b985d238eadf857602636ba5e5c277d4b1992d35..5b2081f920304244df96de78b2c66cf8a49a5b85 100644 +index 67455a5ba75c9b816213e44d6872c5ddf8e27e98..23efad80934930beadf15e65781551d4ba7ff81b 100644 --- a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java +++ b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java -@@ -2,6 +2,7 @@ package net.minecraft.network.protocol.status; - - import com.google.gson.Gson; - import com.google.gson.GsonBuilder; -+import io.papermc.paper.adventure.AdventureComponent; // Paper - import java.io.IOException; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.chat.Component; -@@ -12,7 +13,9 @@ import net.minecraft.util.LowerCaseEnumTypeAdapterFactory; +@@ -10,7 +10,9 @@ import net.minecraft.util.GsonHelper; + import net.minecraft.util.LowerCaseEnumTypeAdapterFactory; public class ClientboundStatusResponsePacket implements Packet { - - private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()).create(); + private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()) -+ .registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()) ++ .registerTypeAdapter(io.papermc.paper.adventure.AdventureComponent.class, new io.papermc.paper.adventure.AdventureComponent.Serializer()) + .create(); - private ServerStatus status; + private final ServerStatus status; - public ClientboundStatusResponsePacket() {} -diff --git a/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java b/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java -index d6be3dd6cfed3f65325398fc33663cb251f87ac7..31d45cd635eae2ff406cb0441f2cd2aee833b945 100644 ---- a/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java -+++ b/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java -@@ -31,6 +31,7 @@ public class ServerStatus { - this.description = description; - } - -+ public Players getPlayers() { return getPlayers(); } // Paper - OBFHELPER - public ServerStatus.Players getPlayers() { - return this.players; - } -@@ -162,10 +163,12 @@ public class ServerStatus { - return this.numPlayers; - } - -+ public GameProfile[] getSample() { return getSample(); } // Paper - OBFHELPER - public GameProfile[] getSample() { - return this.sample; - } - -+ public void setSample(GameProfile[] sample) { setSample(sample); } // Paper - OBFHELPER - public void setSample(GameProfile[] sample) { - this.sample = sample; - } + public ClientboundStatusResponsePacket(ServerStatus metadata) { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 4b3341877629c7065496fb0f0b4d509f5a48db6d..d34da1eb172a7dcda564680afecf3dc145bf09f3 100644 +index fb4385333ef8dd4fa22275753606df3020000539..a0c436fd5e7e03a0a01e59c046e65ebdcd88021a 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -2,6 +2,9 @@ package net.minecraft.server; @@ -236,7 +203,7 @@ index 4b3341877629c7065496fb0f0b4d509f5a48db6d..d34da1eb172a7dcda564680afecf3dc1 import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -@@ -1238,7 +1241,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= 5000000000L) { this.lastServerStatus = i; this.status.setPlayers(new ServerStatus.Players(this.getMaxPlayers(), this.getPlayerCount())); @@ -246,28 +213,10 @@ index 4b3341877629c7065496fb0f0b4d509f5a48db6d..d34da1eb172a7dcda564680afecf3dc1 for (int k = 0; k < agameprofile.length; ++k) { diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java -index 223df8d27c2ff1cbff634bca3dbde5cc24de7f98..f74e3cbdff8c2d83809f04f42717501d7b1a1ed2 100644 +index 9baa56d6da9c24706f1dbc8851fd68ca752cab26..d65191a50349ec86fe35df4ac1070f94fbb77b4c 100644 --- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java -@@ -1,7 +1,7 @@ - package net.minecraft.server.network; - - import net.minecraft.server.MinecraftServer; --import net.minecraft.server.level.ServerPlayer; -+ - // CraftBukkit start - import com.mojang.authlib.GameProfile; - import java.net.InetSocketAddress; -@@ -11,8 +11,6 @@ import net.minecraft.network.Connection; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; --import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; --import net.minecraft.network.protocol.status.ServerStatus; - import net.minecraft.network.protocol.status.ServerStatusPacketListener; - import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; - import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; -@@ -47,15 +45,17 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene +@@ -47,6 +47,8 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON); } else { this.hasRequestedStatus = true; @@ -275,88 +224,11 @@ index 223df8d27c2ff1cbff634bca3dbde5cc24de7f98..f74e3cbdff8c2d83809f04f42717501d + /* // CraftBukkit start // this.networkManager.sendPacket(new PacketStatusOutServerInfo(this.minecraftServer.getServerPing())); -- final Object[] players = server.getPlayerList().players.toArray(); -+ final Object[] players = minecraftServer.getPlayerList().players.toArray(); - class ServerListPingEvent extends org.bukkit.event.server.ServerListPingEvent { + final Object[] players = this.server.getPlayerList().players.toArray(); +@@ -142,6 +144,9 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + ping.setVersion(new ServerStatus.Version(this.server.getServerModName() + " " + this.server.getServerVersion(), version)); -- CraftIconCache icon = server.server.getServerIcon(); -+ CraftIconCache icon = minecraftServer.server.getServerIcon(); - - ServerListPingEvent() { -- super(((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.server.motd(), server.getPlayerList().getMaxPlayers()); // Paper - Adventure -+ super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.server.motd(), minecraftServer.getPlayerList().getMaxPlayers()); // Paper - Adventure - } - - @Override -@@ -71,7 +71,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene - return new Iterator() { - int i; - int ret = Integer.MIN_VALUE; -- ServerPlayer player; -+ EntityPlayer player; - - @Override - public boolean hasNext() { -@@ -80,7 +80,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene - } - final Object[] currentPlayers = players; - for (int length = currentPlayers.length, i = this.i; i < length; i++) { -- final ServerPlayer player = (ServerPlayer) currentPlayers[i]; -+ final EntityPlayer player = (EntityPlayer) currentPlayers[i]; - if (player != null) { - this.i = i + 1; - this.player = player; -@@ -95,7 +95,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene - if (!hasNext()) { - throw new java.util.NoSuchElementException(); - } -- final ServerPlayer player = this.player; -+ final EntityPlayer player = this.player; - this.player = null; - this.ret = this.i - 1; - return player.getBukkitEntity(); -@@ -115,16 +115,16 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene - } - - ServerListPingEvent event = new ServerListPingEvent(); -- this.server.server.getPluginManager().callEvent(event); -+ this.minecraftServer.server.getPluginManager().callEvent(event); - - java.util.List profiles = new java.util.ArrayList(players.length); - for (Object player : players) { - if (player != null) { -- profiles.add(((ServerPlayer) player).getGameProfile()); -+ profiles.add(((EntityPlayer) player).getProfile()); - } - } - -- ServerStatus.Players playerSample = new ServerStatus.Players(event.getMaxPlayers(), profiles.size()); -+ ServerPing.ServerPingPlayerSample playerSample = new ServerPing.ServerPingPlayerSample(event.getMaxPlayers(), profiles.size()); - // Spigot Start - if ( !profiles.isEmpty() ) - { -@@ -132,16 +132,19 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene - profiles = profiles.subList( 0, Math.min( profiles.size(), org.spigotmc.SpigotConfig.playerSample ) ); // Cap the sample to n (or less) displayed players, ie: Vanilla behaviour - } - // Spigot End -- playerSample.setSample(profiles.toArray(new GameProfile[profiles.size()])); -+ playerSample.a(profiles.toArray(new GameProfile[profiles.size()])); - -- ServerStatus ping = new ServerStatus(); -+ ServerPing ping = new ServerPing(); - ping.setFavicon(event.icon.value); -- ping.setDescription(CraftChatMessage.fromString(event.getMotd(), true)[0]); -- ping.setPlayers(playerSample); -- int version = SharedConstants.getCurrentVersion().getProtocolVersion(); -- ping.setVersion(new ServerStatus.Version(server.getServerModName() + " " + server.getServerVersion(), version)); -- -- this.connection.send(new ClientboundStatusResponsePacket(ping)); -+ ping.setMOTD(CraftChatMessage.fromString(event.getMotd(), true)[0]); -+ ping.setPlayerSample(playerSample); -+ int version = SharedConstants.getGameVersion().getProtocolVersion(); -+ ping.setServerInfo(new ServerPing.ServerData(minecraftServer.getServerModName() + " " + minecraftServer.getVersion(), version)); -+ -+ this.networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); + this.connection.send(new ClientboundStatusResponsePacket(ping)); + */ + com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.server, this.connection); + // Paper end @@ -364,15 +236,15 @@ index 223df8d27c2ff1cbff634bca3dbde5cc24de7f98..f74e3cbdff8c2d83809f04f42717501d // CraftBukkit end } diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 3981ba5957fdc2929d54515f2b98bb7a4611e938..652b820a4c0bbf7b6bbb8200927a663665583606 100644 +index e7586c325290ceb8669f9f9d430c73080a37dd05..314fa148fe783a0558ba00b068e0bf69a91577e1 100644 --- a/src/main/java/org/spigotmc/SpigotConfig.java +++ b/src/main/java/org/spigotmc/SpigotConfig.java @@ -289,7 +289,7 @@ public class SpigotConfig public static int playerSample; private static void playerSample() { -- playerSample = getInt( "settings.sample-count", 12 ); -+ playerSample = Math.max( getInt( "settings.sample-count", 12 ), 0 ); // Paper - Avoid negative counts +- SpigotConfig.playerSample = SpigotConfig.getInt( "settings.sample-count", 12 ); ++ SpigotConfig.playerSample = Math.max( SpigotConfig.getInt( "settings.sample-count", 12 ), 0 ); // Paper - Avoid negative counts Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger } diff --git a/patches/server-remapped/0199-Improved-Async-Task-Scheduler.patch b/patches/server/0182-Improved-Async-Task-Scheduler.patch similarity index 91% rename from patches/server-remapped/0199-Improved-Async-Task-Scheduler.patch rename to patches/server/0182-Improved-Async-Task-Scheduler.patch index b0ae823221..ad66d97e35 100644 --- a/patches/server-remapped/0199-Improved-Async-Task-Scheduler.patch +++ b/patches/server/0182-Improved-Async-Task-Scheduler.patch @@ -159,7 +159,7 @@ index 0000000000000000000000000000000000000000..3c1992e212a6d6f1db4d5b807b38d719 + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483ca3c7c2a8 100644 +index 6435d53dcddc1a43420f1ea66fa08e154b82586d..dd1e8b170e87bff2089f642f41dcf7442a8ccd16 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java @@ -63,7 +63,7 @@ public class CraftScheduler implements BukkitScheduler { @@ -190,7 +190,7 @@ index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483c @@ -94,12 +95,31 @@ public class CraftScheduler implements BukkitScheduler { } }; - private CraftAsyncDebugger debugTail = debugHead; + private CraftAsyncDebugger debugTail = this.debugHead; + + */ // Paper end private static final int RECENT_TICKS; @@ -223,8 +223,8 @@ index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483c } else if (period < CraftTask.NO_REPEATING) { period = CraftTask.NO_REPEATING; } -- return handle(new CraftAsyncTask(runners, plugin, runnable, nextId(), period), delay); -+ return handle(new CraftAsyncTask(this.asyncScheduler.runners, plugin, runnable, nextId(), period), delay); // Paper +- return this.handle(new CraftAsyncTask(this.runners, plugin, runnable, this.nextId(), period), delay); ++ return this.handle(new CraftAsyncTask(this.asyncScheduler.runners, plugin, runnable, this.nextId(), period), delay); // Paper } @Override @@ -237,7 +237,7 @@ index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483c + this.asyncScheduler.cancelTask(taskId); + } + // Paper end - CraftTask task = runners.get(taskId); + CraftTask task = this.runners.get(taskId); if (task != null) { task.cancel0(); @@ -280,6 +305,11 @@ public class CraftScheduler implements BukkitScheduler { @@ -257,13 +257,13 @@ index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483c @Override public boolean isCurrentlyRunning(final int taskId) { + // Paper start -+ if (!isAsyncScheduler) { ++ if (!this.isAsyncScheduler) { + if (this.asyncScheduler.isCurrentlyRunning(taskId)) { + return true; + } + } + // Paper end - final CraftTask task = runners.get(taskId); + final CraftTask task = this.runners.get(taskId); if (task == null) { return false; @@ -337,6 +374,11 @@ public class CraftScheduler implements BukkitScheduler { @@ -275,7 +275,7 @@ index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483c + return true; + } + // Paper end - for (CraftTask task = head.getNext(); task != null; task = task.getNext()) { + for (CraftTask task = this.head.getNext(); task != null; task = task.getNext()) { if (task.getTaskId() == taskId) { return task.getPeriod() >= CraftTask.NO_REPEATING; // The task will run @@ -348,6 +390,12 @@ public class CraftScheduler implements BukkitScheduler { @@ -289,7 +289,7 @@ index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483c + } + // Paper end final ArrayList workers = new ArrayList(); - for (final CraftTask taskObj : runners.values()) { + for (final CraftTask taskObj : this.runners.values()) { // Iterator will be a best-effort (may fail to grab very new values) if called from an async thread @@ -385,6 +433,11 @@ public class CraftScheduler implements BukkitScheduler { pending.add(task); @@ -314,18 +314,18 @@ index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483c + // Paper end this.currentTick = currentTick; final List temp = this.temp; - parsePending(); + this.parsePending(); @@ -431,7 +489,7 @@ public class CraftScheduler implements BukkitScheduler { - parsePending(); + this.parsePending(); } else { - //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper -- executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper + //this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper +- this.executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper + task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Paper"); // Paper // We don't need to parse pending // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) } @@ -450,7 +508,7 @@ public class CraftScheduler implements BukkitScheduler { - //debugHead = debugHead.getNextHead(currentTick); // Paper + //this.debugHead = this.debugHead.getNextHead(currentTick); // Paper } - private void addTask(final CraftTask task) { @@ -345,11 +345,11 @@ index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483c + return task; + } + // Paper end - task.setNextRun(currentTick + delay); - addTask(task); + task.setNextRun(this.currentTick + delay); + this.addTask(task); return task; @@ -478,8 +542,8 @@ public class CraftScheduler implements BukkitScheduler { - return ids.incrementAndGet(); + return this.ids.incrementAndGet(); } - private void parsePending() { diff --git a/patches/server-remapped/0200-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/patches/server/0183-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch similarity index 88% rename from patches/server-remapped/0200-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch rename to patches/server/0183-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch index f400637138..6cbe99f5ad 100644 --- a/patches/server-remapped/0200-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch +++ b/patches/server/0183-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent This will allow you to change the players name or skin on login. diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index ff83fb15d0d0adb62c630fc7aafc134972bf15fc..e5be45ac86907c1f8cc154bd38fd624a2320180f 100644 +index 7923078a4235a6169eb94b7c0ce85e4cd51eb593..f39ccd15c037138a933eb529bec17d49349c0264 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -1,5 +1,7 @@ @@ -17,7 +17,7 @@ index ff83fb15d0d0adb62c630fc7aafc134972bf15fc..e5be45ac86907c1f8cc154bd38fd624a import com.mojang.authlib.GameProfile; import com.mojang.authlib.exceptions.AuthenticationUnavailableException; import java.math.BigInteger; -@@ -36,6 +38,7 @@ import org.apache.commons.lang3.Validate; +@@ -37,6 +39,7 @@ import org.apache.commons.lang3.Validate; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import io.papermc.paper.adventure.PaperAdventure; // Paper @@ -25,8 +25,8 @@ index ff83fb15d0d0adb62c630fc7aafc134972bf15fc..e5be45ac86907c1f8cc154bd38fd624a import org.bukkit.craftbukkit.util.Waitable; import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.PlayerPreLoginEvent; -@@ -314,8 +317,16 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - java.util.UUID uniqueId = gameProfile.getId(); +@@ -336,8 +339,16 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + java.util.UUID uniqueId = ServerLoginPacketListenerImpl.this.gameProfile.getId(); final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; - AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); diff --git a/patches/server-remapped/0201-Player.setPlayerProfile-API.patch b/patches/server/0184-Player.setPlayerProfile-API.patch similarity index 72% rename from patches/server-remapped/0201-Player.setPlayerProfile-API.patch rename to patches/server/0184-Player.setPlayerProfile-API.patch index f35f170d57..7ebc1c188e 100644 --- a/patches/server-remapped/0201-Player.setPlayerProfile-API.patch +++ b/patches/server/0184-Player.setPlayerProfile-API.patch @@ -6,61 +6,52 @@ 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/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index e5be45ac86907c1f8cc154bd38fd624a2320180f..0aa3a154d68f00edcc09b947a24b2b59b1e135e6 100644 +index f39ccd15c037138a933eb529bec17d49349c0264..1d05725374bdffad6a8ab1502ee732775345024d 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -54,7 +54,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - public final Connection connection; - private ServerLoginPacketListenerImpl.State state; - private int tick; -- private GameProfile gameProfile; -+ private GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } private GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER - private final String serverId; - private SecretKey secretKey; - private ServerPlayer delayedAcceptPlayer; -@@ -318,12 +318,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -340,12 +340,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; // Paper start - PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); -+ PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); ++ PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile); AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); server.getPluginManager().callEvent(asyncEvent); profile = asyncEvent.getPlayerProfile(); - profile.complete(); - gameProfile = CraftPlayerProfile.asAuthlibCopy(profile); + profile.complete(true); -+ setGameProfile(CraftPlayerProfile.asAuthlib(profile)); ++ ServerLoginPacketListenerImpl.this.gameProfile = CraftPlayerProfile.asAuthlib(profile); playerName = gameProfile.getName(); uniqueId = gameProfile.getId(); // Paper end 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 63871a3a1981b2e8c7ad74214196e35684acb584..c4aa824d03de952fe6b306e539baa47af979add1 100644 +index 4e8d38a6379d3dc1b7167b27479e6a27ea19ea19..3c0aca2b90521da83cf494d9fff953a17a57701d 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -159,7 +159,7 @@ public abstract class Player extends LivingEntity { +@@ -173,7 +173,7 @@ public abstract class Player extends LivingEntity { protected int enchantmentSeed; protected final float defaultFlySpeed = 0.02F; private int lastLevelUpTime; - private final GameProfile gameProfile; -+ private GameProfile gameProfile; public final void setProfile(final GameProfile profile) { this.gameProfile = profile; } // Paper - OBFHELPER ++ public GameProfile gameProfile; // Paper - private->public + private boolean reducedDebugInfo; private ItemStack lastItemInMainHand; private final ItemCooldowns cooldowns; - @Nullable diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index efdcb8dac8db15c4bbaed84a7861ce98339e516a..9d853733ff9054cc48925e22c8bb3c8d9b898808 100644 +index 75963a28b39f8835f1daba3d1b44655603124bf3..8bf0c74ee32e8cb7c0f48bc964552811ad6ee468 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -67,6 +67,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu; - import net.minecraft.world.item.enchantment.EnchantmentHelper; +@@ -71,6 +71,7 @@ import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.GameType; + import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.biome.BiomeManager; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.saveddata.maps.MapDecoration; - import net.minecraft.world.phys.Vec3; -@@ -1307,8 +1308,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - hiddenPlayers.put(player.getUniqueId(), hidingPlugins); + import net.minecraft.world.level.saveddata.maps.MapItemSavedData; +@@ -1320,8 +1321,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + this.hiddenPlayers.put(player.getUniqueId(), hidingPlugins); // Remove this player from the hidden player's EntityTrackerEntry - ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; @@ -73,10 +64,10 @@ index efdcb8dac8db15c4bbaed84a7861ce98339e516a..9d853733ff9054cc48925e22c8bb3c8d + // Paper end ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId()); if (entry != null) { - entry.removePlayer(getHandle()); -@@ -1349,8 +1355,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + entry.removePlayer(this.getHandle()); +@@ -1362,8 +1368,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } - hiddenPlayers.remove(player.getUniqueId()); + this.hiddenPlayers.remove(player.getUniqueId()); - ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; + // Paper start @@ -87,10 +78,10 @@ index efdcb8dac8db15c4bbaed84a7861ce98339e516a..9d853733ff9054cc48925e22c8bb3c8d + ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; + // Paper end - getHandle().connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, other)); + this.getHandle().connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, other)); -@@ -1359,6 +1370,50 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - entry.updatePlayer(getHandle()); +@@ -1372,6 +1383,50 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + entry.updatePlayer(this.getHandle()); } } + // Paper start @@ -102,7 +93,7 @@ index efdcb8dac8db15c4bbaed84a7861ce98339e516a..9d853733ff9054cc48925e22c8bb3c8d + } + public void setPlayerProfile(com.destroystokyo.paper.profile.PlayerProfile profile) { + ServerPlayer self = getHandle(); -+ self.setProfile(com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile)); ++ self.gameProfile = com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile); + if (!self.sentListPacket) { + return; + } @@ -128,7 +119,7 @@ index efdcb8dac8db15c4bbaed84a7861ce98339e516a..9d853733ff9054cc48925e22c8bb3c8d + ServerLevel worldserver = handle.getLevel(); + connection.send(new net.minecraft.network.protocol.game.ClientboundRespawnPacket(worldserver.dimensionType(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), handle.gameMode.getGameModeForPlayer(), handle.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), true)); + handle.onUpdateAbilities(); -+ connection.send(new net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), new HashSet<>(), 0)); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), java.util.Collections.emptySet(), 0, false)); + net.minecraft.server.MinecraftServer.getServer().getPlayerList().sendAllPlayerInfo(handle); + + if (this.isOp()) { @@ -139,4 +130,4 @@ index efdcb8dac8db15c4bbaed84a7861ce98339e516a..9d853733ff9054cc48925e22c8bb3c8d + // Paper end public void removeDisconnectingPlayer(Player player) { - hiddenPlayers.remove(player.getUniqueId()); + this.hiddenPlayers.remove(player.getUniqueId()); From 116a6013c3a8ef2f09b4303b8b93fe5ba27f9674 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Sat, 12 Jun 2021 19:13:23 +0200 Subject: [PATCH 049/226] Fix this stupid bullshit v2 --- .../0152-Fix-this-stupid-bullshit.patch | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/patches/server/0152-Fix-this-stupid-bullshit.patch b/patches/server/0152-Fix-this-stupid-bullshit.patch index a666a1f647..52308387ea 100644 --- a/patches/server/0152-Fix-this-stupid-bullshit.patch +++ b/patches/server/0152-Fix-this-stupid-bullshit.patch @@ -8,6 +8,28 @@ Disable the 15 second sleep when the server jar hasn't been rebuilt within a per modified in order to prevent merge conflicts when Spigot changes/disables the warning, and to provide some level of hint without being disruptive. +diff --git a/src/main/java/net/minecraft/server/Bootstrap.java b/src/main/java/net/minecraft/server/Bootstrap.java +index c7d5018cb6acef12e6da90626c75543ac279a101..64576ddd8363be55755fa50d1c16d95e4e02402d 100644 +--- a/src/main/java/net/minecraft/server/Bootstrap.java ++++ b/src/main/java/net/minecraft/server/Bootstrap.java +@@ -42,7 +42,7 @@ public class Bootstrap { + public static void bootStrap() { + if (!Bootstrap.isBootstrapped) { + // CraftBukkit start +- String name = Bootstrap.class.getSimpleName(); ++ /*String name = Bootstrap.class.getSimpleName(); // Paper - actually, I don't think this class should ever have been called DispenserRegistry, that's a stupid name, bootstrap is waaay better + switch (name) { + case "DispenserRegistry": + break; +@@ -56,7 +56,7 @@ public class Bootstrap { + System.err.println("*** WARNING: This server jar is unsupported, use at your own risk. ***"); + System.err.println("**********************************************************************"); + break; +- } ++ }*/ // Paper + // CraftBukkit end + Bootstrap.isBootstrapped = true; + if (Registry.REGISTRY.keySet().isEmpty()) { diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java index b4bcd34123968b3930bb330f7c2abd9b5518fa31..f68d44721c91c20a7e4abffe26dabff8b5d2c3ce 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java From d7e184d05508d78077cd869671ec73dda4a8dc05 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Sat, 12 Jun 2021 21:24:35 +0200 Subject: [PATCH 050/226] delete unneeded old patches --- .../0001-POM-Changes.patch | 291 - .../0002-Paper-config-files.patch | 820 --- .../0003-MC-Dev-fixes.patch | 929 ---- .../0004-MC-Utils.patch | 4859 ----------------- .../0005-Paper-Metrics.patch | 735 --- ...-MinecraftKey-Information-to-Objects.patch | 144 - ...to-current-Chunk-for-Entity-and-Bloc.patch | 171 - ...ts-for-each-Entity-Block-Entity-Type.patch | 55 - .../0009-Timings-v2.patch | 2330 -------- .../0010-Adventure.patch | 3238 ----------- ...actus-bamboo-and-reed-growth-heights.patch | 114 - ...figurable-baby-zombie-movement-speed.patch | 51 - ...013-Configurable-fishing-time-ranges.patch | 38 - ...d-mobs-to-jump-and-take-water-damage.patch | 105 - ...-despawn-distances-for-living-entiti.patch | 55 - ...6-Allow-for-toggling-of-spawn-chunks.patch | 33 - ...ck-and-tnt-entities-at-the-specified.patch | 94 - ...ient-crashes-server-lists-and-Mojang.patch | 117 - .../0019-Implement-Paper-VersionChecker.patch | 150 - ...d-version-history-to-version-command.patch | 215 - .../0021-Player-affects-spawning-API.patch | 157 - ...ve-invalid-mob-spawner-tile-entities.patch | 31 - .../0023-Optimize-TileEntity-Ticking.patch | 279 - ...024-Further-improve-server-tick-loop.patch | 208 - ...025-Only-refresh-abilities-if-needed.patch | 25 - .../0026-Entity-Origin-API.patch | 140 - ...event-tile-entity-and-entity-crashes.patch | 65 - ...nfigurable-top-of-nether-void-damage.patch | 93 - ...e-before-converting-and-renaming-pla.patch | 19 - .../0030-Always-tick-falling-blocks.patch | 18 - .../0031-Configurable-end-credits.patch | 42 - ...-explosions-processing-dead-entities.patch | 19 - .../0033-Optimize-explosions.patch | 148 - .../0034-Disable-explosion-knockback.patch | 69 - .../0035-Disable-thunder.patch | 33 - .../0036-Disable-ice-and-snow.patch | 33 - ...7-Configurable-mob-spawner-tick-rate.patch | 65 - ...sition-the-first-time-an-entity-is-s.patch | 108 - .../0039-Add-BeaconEffectEvent.patch | 103 - ...figurable-container-update-tick-rate.patch | 46 - .../0041-Use-UserCache-for-player-heads.patch | 25 - .../0042-Disable-spigot-tick-limiters.patch | 21 - .../0043-Add-PlayerInitialSpawnEvent.patch | 48 - ...urable-Disabling-Cat-Chest-Detection.patch | 37 - ...45-Ensure-commands-are-not-ran-async.patch | 119 - ...chunks-are-slime-spawn-chunks-toggle.patch | 33 - .../0047-Expose-server-CommandMap.patch | 18 - ...e-informative-in-maxHealth-exception.patch | 22 - .../0049-Player-Tab-List-and-Title-APIs.patch | 173 - .../0050-Ensure-inv-drag-is-in-bounds.patch | 19 - ...entation-of-tile-entity-removal-list.patch | 48 - ...dd-configurable-portal-search-radius.patch | 56 - .../0053-Add-velocity-warnings.patch | 89 - ...ble-inter-world-teleportation-safety.patch | 44 - .../0055-Add-exception-reporting-event.patch | 264 - ...-don-t-need-to-when-cerealising-text.patch | 27 - ...oreboards-for-non-players-by-default.patch | 50 - ...working-with-arrows-stuck-in-living-.patch | 27 - .../0059-Complete-resource-pack-API.patch | 71 - .../0060-Chunk-Save-Reattempt.patch | 59 - ...ading-permissions.yml-before-plugins.patch | 52 - ...llow-Reloading-of-Custom-Permissions.patch | 35 - .../0063-Remove-Metadata-on-reload.patch | 31 - ...064-Handle-Item-Meta-Inconsistencies.patch | 339 -- ...urable-Non-Player-Arrow-Despawn-Rate.patch | 44 - .../0066-Add-World-Util-Methods.patch | 65 - ...7-Custom-replacement-for-eaten-items.patch | 48 - ...th-absorb-values-and-repair-bad-data.patch | 57 - ...069-Use-a-Shared-Random-for-Entities.patch | 42 - ...le-spawn-chances-for-skeleton-horses.patch | 36 - ...Location-getType-and-getBlockData-fo.patch | 206 - ...ckPhysicsEvent-if-a-plugin-has-a-lis.patch | 95 - ...Entity-AddTo-RemoveFrom-World-Events.patch | 27 - ...74-Configurable-Chunk-Inhabited-Time.patch | 44 - .../0075-EntityPathfindEvent.patch | 125 - ...egionFileCache-and-make-configurable.patch | 39 - ...7-Do-not-load-chunks-for-Pathfinding.patch | 68 - ...0078-Add-PlayerUseUnknownEntityEvent.patch | 40 - ...dDebugInfo-not-initialized-on-client.patch | 18 - ...-Configurable-Grass-Spread-Tick-Rate.patch | 41 - ...g-BlockPlaceEvent-triggering-physics.patch | 18 - .../0082-Optimize-DataBits.patch | 84 - ...nilla-per-world-scoreboard-coloring-.patch | 66 - ...nd-for-setting-passengers-on-players.patch | 29 - ...Remove-unused-World-Tile-Entity-List.patch | 90 - .../0086-Don-t-tick-Skulls-unused-code.patch | 28 - .../0087-Configurable-Player-Collision.patch | 131 - ...ent-to-allow-plugins-to-handle-clien.patch | 57 - .../0089-Configurable-RCON-IP-address.patch | 59 - ...e-from-loading-chunks-wrongly-spread.patch | 82 - ...91-Implement-PlayerLocaleChangeEvent.patch | 48 - ...ityRegainHealthEvent-isFastRegen-API.patch | 42 - ...-to-configure-frosted_ice-properties.patch | 52 - ...-possibility-for-getServer-singleton.patch | 36 - ...item-frames-performance-and-bug-fixe.patch | 144 - ...-API-Replenishable-Lootables-Feature.patch | 739 --- ...y-scoreboard-teams-to-scoreboard.dat.patch | 32 - ...tem-property-for-disabling-watchdoge.patch | 19 - .../0099-Optimize-UserCache-Thread-Safe.patch | 117 - ...blocking-on-Network-Manager-creation.patch | 45 - ...1-Optional-TNT-doesn-t-move-in-water.patch | 121 - ...r-redstone-torch-rapid-clock-removal.patch | 98 - .../0103-Add-server-name-parameter.patch | 25 - ...on-Wither-Death-sounds-to-same-world.patch | 47 - .../0105-Fix-Double-World-Add-issues.patch | 21 - .../0106-Fix-Old-Sign-Conversion.patch | 59 - ...e-profiles-that-have-no-UUID-and-no-.patch | 19 - ...setting-for-proxy-online-mode-status.patch | 81 - ...ptimise-BlockState-s-hashCode-equals.patch | 84 - ...onfigurable-packet-in-spam-threshold.patch | 45 - ...11-Configurable-flying-kick-messages.patch | 44 - .../0112-Chunk-registration-fixes.patch | 22 - ...ok-reference-on-Craft-Entity-removal.patch | 25 - ...uto-fix-bad-Y-levels-on-player-login.patch | 19 - ...tion-to-remove-corrupt-tile-entities.patch | 37 - .../0116-Add-EntityZapEvent.patch | 58 - ...a-from-ArmorStand-and-SpawnEgg-items.patch | 49 - ...118-Cache-user-authenticator-threads.patch | 102 - .../0119-Optimise-removeQueue.patch | 67 - ...0-Allow-Reloading-of-Command-Aliases.patch | 36 - ...1-Add-source-to-PlayerExpChangeEvent.patch | 49 - ...2-Don-t-let-fishinghooks-use-portals.patch | 22 - .../0123-Add-ProjectileCollideEvent.patch | 109 - ...vent-Pathfinding-out-of-World-Border.patch | 20 - ...imize-World.isLoaded-BlockPosition-Z.patch | 22 - ...-Bound-Treasure-Maps-to-World-Border.patch | 47 - ...figurable-Cartographer-Treasure-Maps.patch | 65 - .../0128-Optimize-ItemStack.isEmpty.patch | 20 - ...to-control-if-armour-stands-can-move.patch | 106 - ...30-Properly-fix-item-duplication-bug.patch | 35 - .../0131-String-based-Action-Bar-API.patch | 48 - .../0132-Firework-API-s.patch | 124 - .../0133-PlayerTeleportEndGatewayEvent.patch | 28 - ...rovide-E-TE-Chunk-count-stat-methods.patch | 61 - .../0135-Enforce-Sync-Player-Saves.patch | 27 - ...llow-entities-to-ride-themselves-572.patch | 18 - ...PI-for-Reason-Source-Triggering-play.patch | 332 -- .../0138-Cap-Entity-Collisions.patch | 57 - ...e-CraftScheduler-Async-Task-Debugger.patch | 48 - ...more-aggressive-in-the-chunk-unload-.patch | 47 - .../0141-Do-not-let-armorstands-drown.patch | 42 - ...le-async-calls-to-restart-the-server.patch | 307 -- ...property-to-disable-book-size-limits.patch | 51 - ...ke-parrots-stay-on-shoulders-despite.patch | 58 - ...n-option-to-prevent-player-names-fro.patch | 36 - ...oleAppender-for-console-improvements.patch | 558 -- ...urable-option-to-disable-creeper-lin.patch | 35 - .../0148-Item-canEntityPickup.patch | 55 - ...PlayerPickupItemEvent-setFlyAtPlayer.patch | 46 - .../0150-PlayerAttemptPickupItemEvent.patch | 41 - .../0151-Add-UnknownCommandEvent.patch | 25 - .../0152-Basic-PlayerProfile-API.patch | 577 -- .../0153-Shoulder-Entities-Release-API.patch | 96 - .../0154-Profile-Lookup-Events.patch | 81 - ...player-logins-during-server-shutdown.patch | 23 - .../0156-Entity-fromMobSpawner.patch | 65 - ...57-Improve-the-Saddle-API-for-Horses.patch | 59 - ...mplement-ensureServerConversions-API.patch | 24 - .../0159-Implement-getI18NDisplayName.patch | 58 - .../0160-ProfileWhitelistVerifyEvent.patch | 50 - .../0161-Fix-this-stupid-bullshit.patch | 30 - ...awns-should-honor-nametags-and-leash.patch | 19 - ...imer-when-spawner-event-is-cancelled.patch | 27 - ...64-Fix-MC-117075-TE-Unload-Lag-Spike.patch | 23 - ...-a-custom-authentication-servers-dow.patch | 43 - .../0166-LivingEntity-setKiller.patch | 48 - ...n-prefixes-using-Log4J-configuration.patch | 71 - ...e-Log4J-Configuration-Plugin-Loggers.patch | 47 - .../0169-Add-PlayerJumpEvent.patch | 46 - ...0-handle-PacketPlayInKeepAlive-async.patch | 40 - ...nt-protocol-version-and-virtual-host.patch | 128 - ...rt-serverside-behavior-of-keepalives.patch | 75 - ...dEffects-only-to-players-who-can-see.patch | 80 - ...-maximum-exp-value-when-merging-orbs.patch | 61 - .../0175-Add-PlayerArmorChangeEvent.patch | 43 - ...rom-being-processed-when-the-player-.patch | 24 - ...e-implementations-for-captured-block.patch | 60 - ...-get-a-BlockState-without-a-snapshot.patch | 147 - .../0179-AsyncTabCompleteEvent.patch | 130 - ...180-Avoid-NPE-in-PathfinderGoalTempt.patch | 19 - .../0181-PlayerPickupExperienceEvent.patch | 28 - .../0182-ExperienceOrbMergeEvent.patch | 22 - ...3-Ability-to-apply-mending-to-XP-API.patch | 101 - ...-max-squid-spawn-height-configurable.patch | 36 - .../0185-PreCreatureSpawnEvent.patch | 215 - ...6-PlayerNaturallySpawnCreaturesEvent.patch | 79 - ...-Add-setPlayerProfile-API-for-Skulls.patch | 109 - .../0188-Fill-Profile-Property-Events.patch | 42 - ...PlayerAdvancementCriterionGrantEvent.patch | 23 - .../0190-Add-ArmorStand-Item-Meta.patch | 296 - ...-Extend-Player-Interact-cancellation.patch | 60 - .../0192-Tameable-getOwnerUniqueId-API.patch | 36 - ...r-crits-helps-mitigate-hacked-client.patch | 34 - ...sted-Ice-from-loading-holding-chunks.patch | 31 - ...le-Explicit-Network-Manager-Flushing.patch | 34 - ...nt-extended-PaperServerListPingEvent.patch | 378 -- .../0197-Improved-Async-Task-Scheduler.patch | 370 -- ...e-PlayerProfile-in-AsyncPreLoginEven.patch | 45 - .../0199-Player.setPlayerProfile-API.patch | 142 - .../0200-Fix-Dragon-Server-Crashes.patch | 21 - .../0201-getPlayerUniqueId-API.patch | 40 - ...Make-player-data-saving-configurable.patch | 27 - ...ke-legacy-ping-handler-more-reliable.patch | 181 - ...ServerListPingEvent-for-legacy-pings.patch | 154 - ...05-Flag-to-disable-the-channel-limit.patch | 31 - ...d-method-to-open-already-placed-sign.patch | 36 - ...urable-sprint-interruption-on-attack.patch | 38 - ...-allowed-colored-signs-to-be-created.patch | 31 - .../0209-EndermanEscapeEvent.patch | 82 - .../0210-Enderman.teleportRandomly.patch | 31 - ...0211-Block-Enderpearl-Travel-Exploit.patch | 40 - ...ld.spawnParticle-API-and-add-Builder.patch | 67 - .../0213-EndermanAttackPlayerEvent.patch | 46 - .../0214-WitchConsumePotionEvent.patch | 24 - .../0215-WitchThrowPotionEvent.patch | 30 - ...Item-entities-with-World.spawnEntity.patch | 24 - .../0217-WitchReadyPotionEvent.patch | 23 - ...0218-ItemStack-getMaxItemUseDuration.patch | 37 - ...lement-EntityTeleportEndGatewayEvent.patch | 32 - ...ed-flag-on-cancel-of-Explosion-Event.patch | 28 - .../0221-Fix-CraftEntity-hashCode.patch | 46 - ...le-Alternative-LootPool-Luck-Formula.patch | 118 - ...ils-when-failing-to-save-player-data.patch | 19 - ...e-shield-blocking-delay-configurable.patch | 69 - .../0225-Improve-EntityShootBowEvent.patch | 44 - .../0226-PlayerReadyArrowEvent.patch | 39 - ...plement-EntityKnockbackByEntityEvent.patch | 93 - .../0228-Expand-Explosions-API.patch | 23 - ...ivingEntity-Hand-Raised-Item-Use-API.patch | 68 - .../0230-RangedEntity-API.patch | 171 - ...to-disable-ender-dragon-legacy-check.patch | 33 - ...2-Implement-World.getEntity-UUID-API.patch | 26 - .../0233-InventoryCloseEvent-Reason-API.patch | 228 - .../0234-Vex-getSummoner-API.patch | 37 - ...nventory-when-cancelling-PlayerInter.patch | 29 - ...ge-the-Entity-Random-seed-for-squids.patch | 19 - ...nilla-entity-warnings-for-duplicates.patch | 22 - ...e-if-stack-size-above-max-stack-size.patch | 21 - ...239-Use-asynchronous-Log4j-2-loggers.patch | 55 - ...-more-information-to-Entity.toString.patch | 20 - ...ies-option-to-debug-dupe-uuid-issues.patch | 131 - .../0242-EnderDragon-Events.patch | 62 - .../0243-PlayerElytraBoostEvent.patch | 31 - .../0244-Improve-BlockPosition-inlining.patch | 75 - .../0245-Optimize-RegistryID.c.patch | 67 - ...t-armor-stands-from-doing-entity-loo.patch | 58 - ...7-Vanished-players-don-t-have-rights.patch | 194 - ...-anytime-entities-change-to-guarante.patch | 27 - ...dd-some-Debug-to-Chunk-Entity-slices.patch | 99 - .../0250-SkeletonHorse-Additions.patch | 152 - ...revent-Saving-Bad-entities-to-chunks.patch | 127 - ...on-t-call-getItemMeta-on-hasItemMeta.patch | 64 - ...ead-Entities-in-entityList-iteration.patch | 120 - ...54-Implement-Expanded-ArmorStand-API.patch | 104 - .../0255-AnvilDamageEvent.patch | 28 - .../0256-Add-TNTPrimeEvent.patch | 148 - ...nd-make-tab-spam-limits-configurable.patch | 75 - .../0258-Add-hand-to-bucket-events.patch | 341 -- ...6-Experience-should-save-as-Integers.patch | 28 - ...ient-rendering-skulls-from-same-user.patch | 147 - ...dd-Early-Warning-Feature-to-WatchDog.patch | 184 - .../0262-Make-EnderDragon-implement-Mob.patch | 33 - ...63-Use-ConcurrentHashMap-in-JsonList.patch | 147 - ...64-Use-a-Queue-for-Queueing-Commands.patch | 39 - ...ile-Entities-from-a-chunk-without-sn.patch | 73 - ...Allow-disabling-armour-stand-ticking.patch | 159 - ...ptimize-BlockPosition-helper-methods.patch | 100 - ...efault-mob-spawn-range-and-water-ani.patch | 33 - .../0269-Slime-Pathfinder-Events.patch | 229 - ...le-speed-for-water-flowing-over-lava.patch | 72 - ...271-Optimize-CraftBlockData-Creation.patch | 49 - .../0272-Optimize-RegistryMaterials.patch | 96 - .../0273-Add-PhantomPreSpawnEvent.patch | 96 - .../0274-Add-More-Creeper-API.patch | 49 - .../0275-Inventory-removeItemAnySlot.patch | 58 - ...loadChunk-int-int-false-load-unconve.patch | 20 - ...-ray-tracing-methods-to-LivingEntity.patch | 99 - ...e-attack-cooldown-methods-for-Player.patch | 41 - .../0279-Improve-death-events.patch | 458 -- ...ow-chests-to-be-placed-with-NBT-data.patch | 31 - .../0281-Mob-Pathfinding-API.patch | 290 - ...ent-chunk-loading-from-Fluid-Flowing.patch | 75 - ...-for-CanPlaceOn-and-CanDestroy-NBT-v.patch | 446 -- ...ent-Mob-AI-Rules-from-Loading-Chunks.patch | 83 - ...wning-from-loading-generating-chunks.patch | 32 - ...e-Biome-Mob-Lookups-for-Mob-Spawning.patch | 97 - ...nt-furnace-cook-speed-multiplier-API.patch | 102 - .../0288-PreSpawnerSpawnEvent.patch | 29 - ...arseException-in-Entity-and-TE-names.patch | 110 - .../0290-Honor-EntityAgeable.ageLock.patch | 18 - ...ble-connection-throttle-kick-message.patch | 35 - .../0292-Hook-into-CB-plugin-rewrites.patch | 184 - ...293-Allow-setting-the-vex-s-summoner.patch | 33 - .../0294-Add-sun-related-API.patch | 52 - .../0295-Turtle-API.patch | 150 - ...ther-worlds-for-shooter-of-projectil.patch | 36 - ...tator-target-events-and-improve-impl.patch | 99 - ...8-Add-Velocity-IP-Forwarding-Support.patch | 303 - .../0299-Add-more-Witch-API.patch | 150 - ...owned-for-Villager-Aggression-Config.patch | 19 - .../0301-Here-s-Johnny.patch | 38 - ...event-players-from-moving-into-unloa.patch | 64 - ...03-Reset-players-airTicks-on-respawn.patch | 30 - ...-after-profile-lookups-if-not-needed.patch | 33 - ...er-Thread-Pool-and-Thread-Priorities.patch | 121 - .../0306-Optimize-World-Time-Updates.patch | 42 - ...store-custom-InventoryHolder-support.patch | 46 - .../0308-Use-Vanilla-Minecart-Speeds.patch | 24 - .../0309-Fix-SpongeAbsortEvent-handling.patch | 37 - ...t-allow-digging-into-unloaded-chunks.patch | 68 - .../0311-Book-Size-Limits.patch | 80 - ...ault-permission-message-configurable.patch | 46 - ...Prevent-rayTrace-from-loading-chunks.patch | 29 - ...e-Large-Packets-disconnecting-client.patch | 130 - ...entity-dismount-during-teleportation.patch | 134 - .../0316-Add-more-Zombie-API.patch | 117 - .../0317-Add-PlayerConnectionCloseEvent.patch | 82 - ...Prevent-Enderman-from-loading-chunks.patch | 30 - ...-replace-OfflinePlayer-getLastPlayed.patch | 164 - ...vehicle-tracking-issue-on-disconnect.patch | 24 - ...onRetractEvent-for-all-empty-pistons.patch | 47 - ...-remove-from-being-called-on-Players.patch | 33 - .../0323-BlockDestroyEvent.patch | 46 - ...om-Shapeless-Custom-Crafting-Recipes.patch | 68 - .../0325-Fix-sign-edit-memory-leak.patch | 44 - .../0326-Limit-Client-Sign-length-more.patch | 54 - ...ConvertSigns-boolean-every-sign-save.patch | 29 - ...-Manager-and-add-advanced-packet-sup.patch | 394 -- ...le-Oversized-Tile-Entities-in-chunks.patch | 54 - ...0-Fix-Whitelist-On-Off-inconsistency.patch | 45 - ...st-tick-at-start-of-drowning-process.patch | 19 - ...332-Allow-Saving-of-Oversized-Chunks.patch | 271 - ...oggleEvent-when-whitelist-is-toggled.patch | 18 - ...334-Add-LivingEntity-getTargetEntity.patch | 187 - ...ength-when-serialising-BungeeCord-te.patch | 32 - .../0336-Entity-getEntitySpawnReason.patch | 121 - ...ity-Metadata-for-all-tracked-players.patch | 43 - ...338-Implement-PlayerPostRespawnEvent.patch | 48 - ...-for-pickupDelay-breaks-picking-up-i.patch | 27 - .../0340-Server-Tick-Events.patch | 32 - ...0341-PlayerDeathEvent-getItemsToKeep.patch | 74 - ...-Optimize-Captured-TileEntity-Lookup.patch | 32 - .../0343-Add-Heightmap-API.patch | 55 - .../0344-Mob-Spawner-API-Enhancements.patch | 139 - ...layer-View-Distance-API-placeholders.patch | 70 - ...l-to-changed-postToMainThread-method.patch | 19 - ...n-item-frames-are-modified-MC-123450.patch | 20 - ...isPrimaryThread-and-MinecraftServer-.patch | 43 - ...h-entity-loss-due-to-unloaded-chunks.patch | 53 - .../0350-Duplicate-UUID-Resolve-Option.patch | 249 - ...351-improve-CraftWorld-isChunkLoaded.patch | 30 - ...le-Keep-Spawn-Loaded-range-per-world.patch | 260 - ...tityAreaEffectCloud-from-going-negat.patch | 24 - .../0354-ChunkMapDistance-CME.patch | 93 - .../0355-Implement-CraftBlockSoundGroup.patch | 83 - .../0356-Chunk-debug-command.patch | 490 -- ...eptions-from-dispenser-entity-spawns.patch | 33 - ...358-Fix-World-isChunkGenerated-calls.patch | 390 -- ...ate-location-if-we-failed-to-read-it.patch | 34 - ...PaletteBlock-instead-of-ReentrantLoc.patch | 117 - .../0361-incremental-chunk-saving.patch | 317 -- .../0362-Anti-Xray.patch | 1624 ------ ...al-Spawned-mobs-towards-natural-spaw.patch | 57 - ...gurable-projectile-relative-velocity.patch | 53 - ...-being-ticked-when-notifying-navigat.patch | 26 - .../0366-offset-item-frame-ticking.patch | 19 - ...opper-searches-if-there-are-no-items.patch | 127 - ...68-Asynchronous-chunk-IO-and-loading.patch | 4410 --------------- ...etChunkIfLoadedImmediately-in-places.patch | 119 - .../0370-Reduce-sync-loads.patch | 350 -- ...lement-alternative-item-despawn-rate.patch | 127 - ...if-we-have-a-custom-Bukkit-generator.patch | 42 - .../0373-Fix-MC-158900.patch | 25 - ...ement-optional-per-player-mob-spawns.patch | 924 ---- ...revent-consuming-the-wrong-itemstack.patch | 52 - .../0376-Generator-Settings.patch | 89 - .../0377-Fix-MC-161754.patch | 23 - ...ce-improvement-for-Chunk.getEntities.patch | 35 - ...hanging-entities-that-are-not-ItemFr.patch | 25 - ...380-Expose-the-internal-current-tick.patch | 21 - ...-sneak-when-changing-worlds-MC-10657.patch | 32 - ...d-option-to-disable-pillager-patrols.patch | 32 - ...or-when-player-hand-set-to-empty-typ.patch | 35 - .../0384-PlayerLaunchProjectileEvent.patch | 351 -- ...ftMagicNumbers.isSupportedApiVersion.patch | 22 - ...nk-loads-when-villagers-try-to-find-.patch | 20 - ...5656-Fix-Follow-Range-Initial-Target.patch | 73 - .../0388-Optimize-Hoppers.patch | 605 -- ...layerDeathEvent-shouldDropExperience.patch | 19 - ...oading-chunks-checking-hive-position.patch | 18 - ...Chunks-from-Hoppers-and-other-things.patch | 32 - ...rializing-mismatching-chunk-coordina.patch | 62 - ...timise-IEntityAccess-getPlayerByUUID.patch | 44 - ...0394-Fix-items-not-falling-correctly.patch | 29 - .../0395-Lag-compensate-eating.patch | 83 - ...mize-call-to-getFluid-for-explosions.patch | 19 - ...k-in-stack-not-having-effects-when-d.patch | 23 - ...-Add-effect-to-block-break-naturally.patch | 32 - .../0399-Tracking-Range-Improvements.patch | 75 - .../0400-Entity-Activation-Range-2.0.patch | 908 --- ...x-items-vanishing-through-end-portal.patch | 28 - ...get-gravity-in-void.-Fixes-MC-167279.patch | 55 - ...e-getChunkAt-calls-for-loaded-chunks.patch | 66 - ...ow-overriding-the-java-version-check.patch | 20 - .../0405-Add-ThrownEggHatchEvent.patch | 29 - .../0406-Optimise-random-block-ticking.patch | 407 -- .../0407-Entity-Jump-API.patch | 59 - ...n-to-nerf-pigmen-from-nether-portals.patch | 71 - .../0409-Make-the-GUI-graph-fancier.patch | 439 -- ...410-add-hand-to-BlockMultiPlaceEvent.patch | 30 - ...11-Prevent-teleporting-dead-entities.patch | 21 - ...ripwire-hook-placement-before-update.patch | 18 - ...to-allow-iron-golems-to-spawn-in-air.patch | 35 - ...-chance-of-villager-zombie-infection.patch | 44 - .../0415-Optimise-Chunk-getFluid.patch | 67 - ...imise-TickListServer-by-rewriting-it.patch | 1301 ----- ...spawn-settings-and-per-player-option.patch | 155 - ...re-Entity-is-never-double-registered.patch | 79 - ...ering-entities-from-unloading-chunks.patch | 32 - ...nnections-shouldn-t-hold-up-shutdown.patch | 25 - ...low-bees-to-load-chunks-for-beehives.patch | 42 - ...-PlayerChunkMap-adds-crashing-server.patch | 48 - ...ptimize-Collision-to-not-load-chunks.patch | 185 - .../0424-Don-t-tick-dead-players.patch | 21 - ...d-Player-s-shouldn-t-be-able-to-move.patch | 21 - ...hunkMap-memory-use-for-visibleChunks.patch | 294 - .../0427-Increase-Light-Queue-Size.patch | 42 - ...asks-Speed-up-processing-of-chunk-lo.patch | 271 - ...move-existing-players-to-world-spawn.patch | 54 - ...-Add-tick-times-API-and-mspt-command.patch | 169 - ...431-Expose-MinecraftServer-isRunning.patch | 22 - ...Add-Raw-Byte-ItemStack-Serialization.patch | 102 - ...33-Remove-streams-from-Mob-AI-System.patch | 253 - ...ions-until-after-entity-ticking-is-d.patch | 45 - .../0435-Async-command-map-building.patch | 72 - .../0436-Improved-Watchdog-Support.patch | 608 --- .../0437-Optimize-Pathfinding.patch | 61 - ...38-Reduce-Either-Optional-allocation.patch | 48 - ...0439-Remove-streams-from-PairedQueue.patch | 79 - ...e-memory-footprint-of-NBTTagCompound.patch | 59 - ...vent-opening-inventories-when-frozen.patch | 59 - ...442-Optimise-ArraySetSorted-removeIf.patch | 65 - ...-entity-collision-code-if-not-needed.patch | 30 - ...oviderServer-s-chunk-level-checking-.patch | 59 - ...-teleport-command-to-valid-locations.patch | 24 - ...-Implement-Player-Client-Options-API.patch | 188 - ...-Chunk-Post-Processing-deadlock-risk.patch | 60 - ...layer-is-attempted-to-be-removed-fro.patch | 23 - ...49-Broadcast-join-message-to-console.patch | 21 - ...g-Broken-behavior-of-PlayerJoinEvent.patch | 149 - ...Load-Chunks-for-Login-Asynchronously.patch | 416 -- ...pawn-point-if-spawn-in-unloaded-worl.patch | 27 - ...PlayerAttackEntityCooldownResetEvent.patch | 28 - ...allbacks-to-schedule-for-Callback-Ex.patch | 58 - ...t-fire-BlockFade-on-worldgen-threads.patch | 28 - ...ntom-creative-and-insomniac-controls.patch | 74 - ...m-duplication-issues-and-teleport-is.patch | 117 - .../0458-Implement-Brigadier-Mojang-API.patch | 139 - .../0459-Villager-Restocks-API.patch | 42 - ...PickItem-Packet-and-kick-for-invalid.patch | 26 - .../0461-Expose-game-version.patch | 24 - .../0462-Optimize-Voxel-Shape-Merging.patch | 175 - ...-per-thread-native-byte-buffer-cache.patch | 30 - .../0464-Implement-Mob-Goal-API.patch | 1104 ---- ...tance-map-to-optimise-entity-tracker.patch | 413 -- ...-isOutsideRange-to-use-distance-maps.patch | 384 -- ...te-operations-for-updating-light-dat.patch | 320 -- ...No-Tick-view-distance-implementation.patch | 819 --- .../0469-Add-villager-reputation-API.patch | 155 - .../0470-Fix-Light-Command.patch | 182 - ...1-Fix-PotionEffect-ignores-icon-flag.patch | 19 - ...-brigadier-child-sorting-performance.patch | 29 - .../0473-Potential-bed-API.patch | 44 - ...Wait-for-Async-Tasks-during-shutdown.patch | 63 - ...der-respects-game-and-entity-rules-f.patch | 28 - ...and-End-Portal-Frames-from-being-des.patch | 173 - ...ze-NibbleArray-to-use-pooled-buffers.patch | 394 -- ...bleInt-allocations-from-light-engine.patch | 50 - ...llocation-of-Vec3D-by-entity-tracker.patch | 69 - .../0480-Ensure-safe-gateway-teleport.patch | 27 - ...n-for-console-having-all-permissions.patch | 74 - ...on-Full-Status-Chunk-NBT-Memory-Leak.patch | 99 - ...ound-for-Client-Lag-Spikes-MC-162253.patch | 137 - ...k-Priority-Urgency-System-for-Chunks.patch | 1352 ----- ...-packets-to-nearby-locations-sounds-.patch | 63 - ...mprove-Chunk-Status-Transition-Speed.patch | 99 - ...ix-villager-trading-demand-MC-163962.patch | 20 - .../0488-Maps-shouldn-t-load-chunks.patch | 32 - ...ookup-for-Treasure-Maps-Fixes-lag-fr.patch | 35 - ...-Optimize-Bit-Operations-by-inlining.patch | 220 - .../0491-Optimize-Light-Engine.patch | 1464 ----- ...unk-Unloads-based-on-Player-Movement.patch | 107 - ...-Plugin-Tickets-to-API-Chunk-Methods.patch | 129 - ...ssing-chunks-due-to-integer-overflow.patch | 29 - ...er-runTaskTimerAsynchronously-Plugin.patch | 21 - ...ston-physics-inconsistency-MC-188840.patch | 93 - .../0497-Fix-sand-duping.patch | 37 - ...-desync-in-playerconnection-causing-.patch | 31 - .../0499-Fix-enderdragon-exp-dupe.patch | 28 - ...Holder-method-without-block-snapshot.patch | 50 - .../0501-Expose-Arrow-getItemStack.patch | 36 - ...implement-PlayerRecipeBookClickEvent.patch | 29 - ...3-Hide-sync-chunk-writes-behind-flag.patch | 23 - ...mit-lightning-strike-effect-distance.patch | 76 - ...05-Add-permission-for-command-blocks.patch | 79 - ...sure-Entity-AABB-s-are-never-invalid.patch | 48 - ...WorldBorder-collision-checks-and-air.patch | 71 - ...ld-Difficulty-Remembering-Difficulty.patch | 86 - .../0509-Paper-dumpitem-command.patch | 80 - ...510-Don-t-allow-null-UUID-s-for-chat.patch | 27 - ...-Legacy-Component-serialization-size.patch | 56 - ...0512-Support-old-UUID-format-for-NBT.patch | 64 - ...up-duplicated-GameProfile-Properties.patch | 68 - ...nvert-legacy-attributes-in-Item-Meta.patch | 44 - ...-Remove-some-streams-from-structures.patch | 143 - ...from-classes-related-villager-gossip.patch | 100 - .../0517-Support-components-in-ItemMeta.patch | 83 - ...argetLivingEntityEvent-for-1.16-mobs.patch | 62 - .../0519-Add-entity-liquid-API.patch | 75 - ...pdate-itemstack-legacy-name-and-lore.patch | 79 - ...awn-player-in-correct-world-on-login.patch | 30 - .../0522-Add-PrepareResultEvent.patch | 164 - ...llow-delegation-to-vanilla-chunk-gen.patch | 104 - ...k-for-portal-on-world-gen-entity-add.patch | 19 - ...ze-NetworkManager-Exception-Handling.patch | 117 - ...ix-Concurrency-issue-in-WeightedList.patch | 153 - ...ancement-data-player-iteration-to-be.patch | 54 - ...ix-arrows-never-despawning-MC-125757.patch | 30 - ...-Vanilla-Command-permission-checking.patch | 53 - ...ove-range-check-for-block-placing-up.patch | 35 - .../0531-Fix-SPIGOT-5989.patch | 69 - ...4-Bukkit-world-container-is-not-used.patch | 33 - ...-5885-Unable-to-disable-advancements.patch | 18 - ...ataPlayer-leak-due-from-quitting-ear.patch | 94 - ...keLighting-call-to-World-spigot-stri.patch | 19 - ...Fix-some-rails-connecting-improperly.patch | 95 - ...der-Remove-Streams-Optimized-collect.patch | 159 - .../0538-Incremental-player-saving.patch | 95 - .../0539-Import-fastutil-classes.patch | 27 - ...ull-chunk-sections-for-block-updates.patch | 18 - ...ove-armour-stand-double-add-to-world.patch | 28 - ...-Fix-MC-187716-Use-configured-height.patch | 45 - ...istake-in-CB-NBT-int-deserialization.patch | 27 - ...erver-load-chunks-from-newer-version.patch | 39 - .../0545-Brand-support.patch | 92 - ...her-Boss-Bar-doesn-t-update-until-in.patch | 22 - .../0547-Fix-MC-197271.patch | 51 - .../0548-MC-197883-Bandaid-decode-issue.patch | 28 - .../0549-Add-setMaxPlayers-API.patch | 37 - ...yPickupItemAnimation-to-LivingEntity.patch | 21 - .../0551-Don-t-require-FACING-data.patch | 35 - ...geEvent-not-firing-for-all-use-cases.patch | 46 - .../0553-Add-moon-phase-API.patch | 22 - ...-headless-pistons-from-being-created.patch | 74 - .../0555-Add-BellRingEvent.patch | 58 - ...Add-zombie-targets-turtle-egg-config.patch | 33 - .../0557-Buffer-joins-to-world.patch | 71 - .../0558-Optimize-redstone-algorithm.patch | 1157 ---- ...rs-not-working-in-some-kick-messages.patch | 64 - ...CreateEvent-needs-to-know-its-entity.patch | 147 - .../0561-Fix-CraftTeam-null-check.patch | 19 - .../0562-Add-more-Evoker-API.patch | 57 - ...-translation-keys-for-blocks-entitie.patch | 126 - ...ate-HoverEvent-from-ItemStack-Entity.patch | 51 - .../0565-Cache-block-data-strings.patch | 70 - ...ortation-and-cancel-velocity-if-tele.patch | 83 - ...al-open-container-api-to-HumanEntity.patch | 81 - ...taFixerUpper-Rewrite-Rules-on-demand.patch | 54 - ...p-capture-to-capture-all-items-added.patch | 60 - ...rty-in-invalid-locations-SPIGOT-6086.patch | 18 - ...y-Counter-to-allow-plugins-to-use-va.patch | 37 - ...-track-plugin-scoreboards-by-default.patch | 102 - .../0573-Entity-isTicking.patch | 42 - ...-non-whitelisted-player-when-white-l.patch | 19 - ...Fix-Not-a-string-Map-Conversion-spam.patch | 52 - ...ng-a-passenger-in-CreatureSpawnEvent.patch | 19 - ...tems-that-are-extra-from-a-crafting-.patch | 24 - ...Reset-Ender-Crystals-on-Dragon-Spawn.patch | 24 - ...r-large-move-vectors-crashing-server.patch | 66 - .../0580-Optimise-getType-calls.patch | 96 - .../0581-Villager-resetOffers.patch | 48 - ...inig-for-some-hot-IBlockData-methods.patch | 101 - ...ace-order-when-capturing-blockstates.patch | 24 - ...blockpos-allocation-from-pathfinding.patch | 28 - ...tem-locations-dropped-from-campfires.patch | 32 - .../0586-Player-elytra-boost-API.patch | 39 - ...587-Fixed-TileEntityBell-memory-leak.patch | 56 - ...ling-up-when-item-stack-is-empty-in-.patch | 46 - ...-Add-getOfflinePlayerIfCached-String.patch | 39 - .../0590-Add-ignore-discounts-API.patch | 143 - ...-Toggle-for-removing-existing-dragon.patch | 36 - ...ix-client-lag-on-advancement-loading.patch | 55 - .../0593-Item-no-age-no-player-pickup.patch | 50 - ...0594-Beacon-API-custom-effect-ranges.patch | 90 - .../0595-Add-API-for-quit-reason.patch | 63 - .../0596-Seed-based-feature-search.patch | 115 - ...ing-Trader-spawn-rate-config-options.patch | 120 - ...prove-performance-of-the-end-generat.patch | 77 - .../0599-Expose-world-spawn-angle.patch | 44 - .../0600-Add-Destroy-Speed-API.patch | 35 - ...r-spawnParticle-x-y-z-precision-loss.patch | 19 - ...602-Add-LivingEntity-clearActiveItem.patch | 24 - .../0603-Add-PlayerItemCooldownEvent.patch | 39 - .../0604-More-lightning-API.patch | 68 - ...-should-not-bypass-cramming-gamerule.patch | 179 - ...d-missing-default-perms-for-commands.patch | 70 - .../0607-Add-PlayerShearBlockEvent.patch | 116 - ...g-for-servers-not-running-on-Java-16.patch | 80 - ...erbose-world-setting-to-false-by-def.patch | 19 - ...ing-zombie-villager-discount-exploit.patch | 55 - .../0611-Limit-recipe-packets.patch | 74 - ...x-CraftSound-backwards-compatibility.patch | 21 - .../0613-MC-4-Fix-item-position-desync.patch | 84 - ...0614-Player-Chunk-Load-Unload-Events.patch | 41 - ...15-Optimize-Dynamic-get-Missing-Keys.patch | 34 - ...6-Expose-LivingEntity-hurt-direction.patch | 39 - ...-OBSTRUCTED-reason-to-BedEnterResult.patch | 21 - ...m-invalid-ingredient-lists-in-Villag.patch | 24 - .../0619-added-PlayerTradeEvent.patch | 75 - .../0620-Implement-TargetHitEvent.patch | 58 - ...0621-Additional-Block-Material-API-s.patch | 40 - .../0622-Fix-harming-potion-dupe.patch | 59 - ...-get-Material-from-Boats-and-Minecar.patch | 100 - .../0624-Optimized-tick-ready-check.patch | 51 - .../0625-Cache-burn-durations.patch | 63 - ...mob-spawner-spawn-egg-transformation.patch | 33 - ...ement-PlayerFlowerPotManipulateEvent.patch | 46 - ...-event-not-being-called-in-adventure.patch | 29 - .../0629-Zombie-API-breaking-doors.patch | 44 - ...0630-Fix-nerfed-slime-when-splitting.patch | 18 - .../0631-Add-EntityLoadCrossbowEvent.patch | 60 - .../0632-Guardian-beam-workaround.patch | 30 - .../0633-Added-WorldGameRuleChangeEvent.patch | 110 - ...4-Added-ServerResourcesReloadedEvent.patch | 90 - ...ld-settings-for-mobs-picking-up-loot.patch | 51 - ...Implemented-BlockFailedDispenseEvent.patch | 63 - ...7-Added-PlayerLecternPageChangeEvent.patch | 66 - .../0638-Fire-event-on-GS4-query.patch | 265 - ...9-Added-PlayerLoomPatternSelectEvent.patch | 63 - ...onfigurable-door-breaking-difficulty.patch | 100 - ...pty-commands-shall-not-be-dispatched.patch | 18 - ...PI-to-expose-exact-interaction-point.patch | 59 - .../0643-Remove-stale-POIs.patch | 50 - .../0644-Fix-villager-boat-exploit.patch | 34 - ...645-Entity-load-save-limit-per-chunk.patch | 90 - .../0646-Add-sendOpLevel-API.patch | 65 - .../0647-Add-StructureLocateEvent.patch | 41 - ...n-for-requiring-a-player-participant.patch | 81 - ...ileHitEvent-call-when-fireballs-dead.patch | 21 - ...onent-with-empty-text-instead-of-thr.patch | 33 - ...0651-Make-schedule-command-per-world.patch | 37 - ...0652-Configurable-max-leash-distance.patch | 45 - ...0653-Implement-BlockPreDispenseEvent.patch | 42 - .../0654-Added-Vanilla-Entity-Tags.patch | 93 - .../0655-added-Wither-API.patch | 75 - ...ing-of-PlayerChangeBeaconEffectEvent.patch | 39 - ...e-spam-when-removing-chests-in-water.patch | 19 - ...le-for-always-placing-the-dragon-egg.patch | 33 - ...d-PlayerStonecutterRecipeSelectEvent.patch | 109 - ...Leash-variable-to-EntityUnleashEvent.patch | 156 - ...ce-map-update-when-spawning-disabled.patch | 19 - ...-shield-blocking-on-dimension-change.patch | 22 - .../0663-add-DragonEggFormEvent.patch | 117 - .../0664-EntityMoveEvent.patch | 71 - ...disable-pathfinding-updates-on-block.patch | 40 - .../0666-Inline-shift-direction-fields.patch | 55 - ...w-adding-items-to-BlockDropItemEvent.patch | 44 - ...ainThreadExecutor-to-BukkitScheduler.patch | 26 - ...-entity-allow-attribute-registration.patch | 69 - ...fix-dead-slime-setSize-invincibility.patch | 19 - ...ipes-should-return-an-immutable-list.patch | 19 - .../0672-misc-debugging-dumps.patch | 87 - ...pport-for-hex-color-codes-in-console.patch | 221 - .../0674-Clear-SyncLoadInfo.patch | 40 - .../0675-Expose-Tracked-Players.patch | 53 - ...76-Remove-streams-from-SensorNearest.patch | 120 - ...unnecessary-copies-of-passenger-list.patch | 239 - ...Fix-Wither-hostility-towards-players.patch | 33 - ...per-exception-on-empty-JsonList-file.patch | 18 - .../0680-Improve-ServerGUI.patch | 400 -- ...sure-plate-EntityInteractEvent-for-i.patch | 19 - ...0682-fix-converting-txt-to-json-file.patch | 74 - .../0683-Add-worldborder-events.patch | 122 - .../0684-added-PlayerNameEntityEvent.patch | 41 - ...-grindstones-from-overstacking-items.patch | 26 - .../0686-Add-recipe-to-cook-events.patch | 44 - .../0687-Add-Block-isValidTool.patch | 20 - ...-using-signs-inside-spawn-protection.patch | 41 - .../0689-Implement-Keyed-on-World.patch | 110 - ...alternative-constructor-for-Vector3f.patch | 30 - .../0691-Item-Rarity-API.patch | 52 - ...Timer-for-Wandering-Traders-spawned-.patch | 58 - ...opy-TESign-isEditable-from-snapshots.patch | 18 - ...ed-item-when-player-has-disconnected.patch | 35 - ...telist-use-configurable-kick-message.patch | 27 - ...-to-remove-correct-TE-during-TE-tick.patch | 45 - ...ignore-result-of-PlayerEditBookEvent.patch | 19 - ...-block-falling-causing-client-desync.patch | 59 - .../0699-Expose-protocol-version.patch | 22 - ...ent-suggestion-tooltips-in-AsyncTabC.patch | 132 - ...tab-completions-for-brigadier-comman.patch | 316 -- ...ItemConsumeEvent-cancelling-properly.patch | 22 - .../0703-Add-bypass-host-check.patch | 30 - ...don-t-throw-when-loading-invalid-TEs.patch | 33 - .../0705-Set-area-affect-cloud-rotation.patch | 18 - ...-add-isDeeplySleeping-to-HumanEntity.patch | 24 - ...ating-give-items-on-item-drop-cancel.patch | 113 - ...-add-consumeFuel-to-FurnaceBurnEvent.patch | 19 - ...t-set-drop-chance-to-EntityEquipment.patch | 48 - ...fix-PigZombieAngerEvent-cancellation.patch | 47 - ...x-checkReach-check-for-Shulker-boxes.patch | 18 - ...fix-PlayerItemHeldEvent-firing-twice.patch | 30 - .../0713-Added-PlayerDeepSleepEvent.patch | 22 - .../0714-More-World-API.patch | 146 - .../0715-Added-PlayerBedFailEnterEvent.patch | 57 - ...s-to-convert-between-Component-and-B.patch | 55 - ...wn-acting-as-a-bed-respawn-from-the-.patch | 36 - ...d-RespawnFlags-to-PlayerRespawnEvent.patch | 46 - ...eacon-activation-deactivation-events.patch | 37 - ...Add-Channel-initialization-listeners.patch | 119 - ...mmands-if-tab-completion-is-disabled.patch | 24 - .../0722-Add-more-WanderingTrader-API.patch | 65 - ...Add-EntityBlockStorage-clearEntities.patch | 37 - ...essage-to-PlayerAdvancementDoneEvent.patch | 89 - ...-address-to-AsyncPlayerPreLoginEvent.patch | 25 - .../0726-Inventory-close.patch | 25 - ...CreateEvent-players-and-end-platform.patch | 45 - ...n-in-sunlight-API-for-Phantoms-and-S.patch | 126 - .../0729-Fix-CraftPotionBrewer-cache.patch | 44 - .../0730-Add-basic-Datapack-API.patch | 174 - ...nment-variable-to-disable-server-gui.patch | 18 - ...ditions-to-PlayerGameModeChangeEvent.patch | 138 - .../0733-ItemStack-repair-check-API.patch | 91 - .../0734-More-Enchantment-API.patch | 211 - ...-option-to-load-extra-plugin-jars-no.patch | 64 - ...atus-dataconverter-for-pre-1.13-chun.patch | 91 - ...crease-structure-block-data-length-t.patch | 19 - ...x-and-optimise-world-force-upgrading.patch | 411 -- .../0739-Add-Mob-lookAt-API.patch | 127 - .../0740-Add-Unix-domain-socket-support.patch | 141 - .../0741-Add-EntityInsideBlockEvent.patch | 222 - ...742-Attributes-API-for-item-defaults.patch | 42 - ...chantCustom-emit-PlayerPurchaseEvent.patch | 59 - ...cause-to-Weather-ThunderChangeEvents.patch | 136 - .../0745-More-Lidded-Block-API.patch | 127 - .../0746-Add-PlayerKickEvent-causes.patch | 393 -- ...747-Limit-item-frame-cursors-on-maps.patch | 37 - .../0748-Add-PufferFishStateChangeEvent.patch | 50 - ...yerBucketEmptyEvent-result-itemstack.patch | 43 - ...n-to-fix-items-merging-through-walls.patch | 39 - .../0751-Add-BellRevealRaiderEvent.patch | 26 - .../0752-Fix-invulnerable-end-crystals.patch | 105 - ...753-Add-ElderGuardianAppearanceEvent.patch | 23 - ...-inventory-on-cancelled-pickup-event.patch | 62 - .../0755-Fix-dangerous-end-portal-logic.patch | 107 - ...6-Make-item-validations-configurable.patch | 83 - .../0757-Add-more-line-of-sight-methods.patch | 62 - .../0758-add-per-world-spawn-limits.patch | 49 - ...SplashEvent-for-water-splash-potions.patch | 63 - .../0001-Convert-project-to-Gradle.patch | 76 - .../0001-Setup-Gradle-project.patch | 95 - .../0002-Decompile-fixes.patch | 77 - .../0001-POM-changes.patch | 106 - .../0002-Add-FastUtil-to-Bukkit.patch | 24 - .../0003-Paper-Utils.patch | 28 - .../0004-Timings-v2.patch | 3759 ------------- .../0005-Adventure.patch | 4124 -------------- .../0006-Player-affects-spawning-API.patch | 33 - .../0007-Add-getTPS-method.patch | 49 - .../0008-Entity-Origin-API.patch | 66 - .../0009-Version-Command-2.0.patch | 185 - .../0010-Add-PlayerLocaleChangeEvent.patch | 62 - .../0011-Add-player-view-distance-API.patch | 39 - .../0012-Add-BeaconEffectEvent.patch | 98 - .../0013-Add-PlayerInitialSpawnEvent.patch | 29 - ...ly-disable-plugins-that-fail-to-load.patch | 21 - .../0015-Expose-server-CommandMap.patch | 50 - ...cord-chat-API-from-spigot-subclasses.patch | 124 - .../0017-Player-Tab-List-and-Title-APIs.patch | 577 -- .../0018-Add-exception-reporting-event.patch | 604 -- ...erverListPingEvent-flagging-as-Async.patch | 27 - ...t-sendMessage-methods-to-CommandSend.patch | 54 - ...working-with-arrows-stuck-in-living-.patch | 30 - .../0022-Complete-resource-pack-API.patch | 118 - .../0023-Use-ASM-for-event-executors.patch | 398 -- .../0024-Add-a-call-helper-to-Event.patch | 34 - ...der-name-to-commands.yml-replacement.patch | 43 - ...eload-permissions.yml-and-require-co.patch | 104 - ...7-Custom-replacement-for-eaten-items.patch | 48 - ...Entity-AddTo-RemoveFrom-World-Events.patch | 79 - .../0029-EntityPathfindEvent.patch | 95 - ...synchronization-in-MetadataStoreBase.patch | 90 - ...d-MetadataStoreBase.removeAll-Plugin.patch | 46 - ...0032-Add-PlayerUseUnknownEntityEvent.patch | 58 - ...ent-to-allow-plugins-to-handle-clien.patch | 290 - .../0034-Arrow-pickup-rule-API.patch | 49 - ...ityRegainHealthEvent-isFastRegen-API.patch | 42 - .../0036-LootTable-API.patch | 402 -- .../0037-Add-EntityZapEvent.patch | 123 - .../0038-Misc-Utils.patch | 46 - ...9-Allow-Reloading-of-Command-Aliases.patch | 108 - ...0-Add-source-to-PlayerExpChangeEvent.patch | 54 - .../0041-Add-ProjectileCollideEvent.patch | 79 - ...0042-Add-String-based-Action-Bar-API.patch | 86 - ...to-control-if-armour-stands-can-move.patch | 32 - .../0044-IllegalPacketEvent.patch | 89 - .../0045-Fireworks-API-s.patch | 28 - .../0046-PlayerTeleportEndGatewayEvent.patch | 42 - ...rovide-E-TE-Chunk-count-stat-methods.patch | 46 - ...PI-for-Reason-Source-Triggering-play.patch | 122 - ...orldBorder-isInBounds-Location-check.patch | 29 - ...n-option-to-prevent-player-names-fro.patch | 60 - ...upstream-javadoc-warnings-and-errors.patch | 46 - .../0052-Item-canEntityPickup.patch | 31 - ...PlayerPickupItemEvent-setFlyAtPlayer.patch | 54 - .../0054-PlayerAttemptPickupItemEvent.patch | 102 - .../0055-Add-UnknownCommandEvent.patch | 126 - .../0056-Basic-PlayerProfile-API.patch | 351 -- .../0057-Shoulder-Entities-Release-API.patch | 37 - .../0058-Profile-Lookup-Events.patch | 174 - .../0059-Entity-fromMobSpawner.patch | 23 - ...60-Improve-the-Saddle-API-for-Horses.patch | 83 - .../0061-ensureServerConversions-API.patch | 62 - .../0062-Add-getI18NDisplayName-API.patch | 52 - .../0063-ProfileWhitelistVerifyEvent.patch | 157 - .../0064-Make-plugins-list-alphabetical.patch | 56 - .../0065-LivingEntity-setKiller.patch | 26 - ...efixes-in-implementation-logging-con.patch | 41 - ...low-plugins-to-use-SLF4J-for-logging.patch | 51 - ...or-plugins-modifying-the-parent-of-t.patch | 117 - .../0069-Add-PlayerJumpEvent.patch | 118 - ...nt-protocol-version-and-virtual-host.patch | 71 - .../0071-Add-PlayerArmorChangeEvent.patch | 149 - ...-get-a-BlockState-without-a-snapshot.patch | 31 - .../0073-AsyncTabCompleteEvent.patch | 266 - ...lay-warning-on-deprecated-recipe-API.patch | 35 - .../0075-PlayerPickupExperienceEvent.patch | 93 - .../0076-ExperienceOrbMergeEvent.patch | 102 - ...7-Ability-to-apply-mending-to-XP-API.patch | 50 - .../0078-PreCreatureSpawnEvent.patch | 127 - ...9-PlayerNaturallySpawnCreaturesEvent.patch | 80 - ...-Add-setPlayerProfile-API-for-Skulls.patch | 78 - .../0081-Fill-Profile-Property-Events.patch | 176 - ...PlayerAdvancementCriterionGrantEvent.patch | 75 - .../0083-Add-ArmorStand-Item-Meta.patch | 96 - .../0084-Optimize-Hoppers.patch | 39 - .../0085-Tameable-getOwnerUniqueId-API.patch | 42 - ...e-PlayerProfile-in-AsyncPreLoginEven.patch | 91 - ...dd-extended-PaperServerListPingEvent.patch | 381 -- .../0088-Player.setPlayerProfile-API.patch | 40 - .../0089-getPlayerUniqueId-API.patch | 58 - ...-support-to-PaperServerListPingEvent.patch | 30 - ...d-method-to-open-already-placed-sign.patch | 25 - ...92-Add-Ban-Methods-to-Player-Objects.patch | 253 - .../0093-EndermanEscapeEvent.patch | 102 - .../0094-Enderman.teleportRandomly.patch | 29 - ...tional-world.getNearbyEntities-API-s.patch | 292 - .../0096-Location.isChunkLoaded-API.patch | 18 - ...ld.spawnParticle-API-and-add-Builder.patch | 579 -- .../0098-EndermanAttackPlayerEvent.patch | 116 - ...lose-Plugin-Class-Loaders-on-Disable.patch | 141 - .../0100-WitchConsumePotionEvent.patch | 122 - .../0101-WitchThrowPotionEvent.patch | 93 - ...ion.toBlockLocation-toCenterLocation.patch | 43 - .../0103-PotionEffect-clone-methods.patch | 44 - .../0104-WitchReadyPotionEvent.patch | 93 - ...0105-ItemStack-getMaxItemUseDuration.patch | 25 - ...06-Add-EntityTeleportEndGatewayEvent.patch | 43 - ...e-shield-blocking-delay-configurable.patch | 30 - ...ent-consumeArrow-and-getArrowItem-AP.patch | 44 - ...Add-getNearbyXXX-methods-to-Location.patch | 275 - .../0110-PlayerReadyArrowEvent.patch | 107 - ...111-Add-EntityKnockbackByEntityEvent.patch | 94 - .../0112-Expand-Explosions-API.patch | 200 - ...PI-additions-for-quantity-flags-lore.patch | 206 - ...ivingEntity-Hand-Raised-Item-Use-API.patch | 62 - .../0115-RangedEntity-API.patch | 188 - .../0116-Add-World.getEntity-UUID-API.patch | 28 - .../0117-InventoryCloseEvent-Reason-API.patch | 93 - .../0118-Entity-getChunk-API.patch | 33 - ...dd-an-asterisk-to-legacy-API-plugins.patch | 66 - .../0120-EnderDragon-Events.patch | 225 - .../0121-PlayerLaunchProjectileEvent.patch | 95 - .../0122-PlayerElytraBoostEvent.patch | 97 - .../0123-EntityTransformedEvent.patch | 104 - ...Allow-disabling-armour-stand-ticking.patch | 32 - .../0125-SkeletonHorse-Additions.patch | 92 - ...126-Expand-Location-Manipulation-API.patch | 66 - .../0127-Expand-ArmorStand-API.patch | 103 - .../0128-AnvilDamageEvent.patch | 160 - ...deadlock-risk-in-firing-async-events.patch | 137 - .../0130-Add-hand-to-bucket-events.patch | 130 - .../0131-Add-TNTPrimeEvent.patch | 126 - ...vide-Chunk-Coordinates-as-a-Long-API.patch | 72 - .../0133-Async-Chunks-API.patch | 534 -- .../0134-Make-EnderDragon-extend-Mob.patch | 19 - ...ile-Entities-from-a-chunk-without-sn.patch | 57 - ...hots-for-Timings-Tile-Entity-reports.patch | 19 - ...Blocks-to-be-accessed-via-a-long-key.patch | 169 - .../0138-Slime-Pathfinder-Events.patch | 217 - .../0139-isChunkGenerated-API.patch | 57 - .../0140-Add-More-Creeper-API.patch | 91 - .../0141-Add-PhantomPreSpawnEvent.patch | 71 - ...dd-source-block-to-BlockPhysicsEvent.patch | 24 - .../0143-Inventory-removeItemAnySlot.patch | 45 - ...-ray-tracing-methods-to-LivingEntity.patch | 148 - .../0145-Improve-death-events.patch | 181 - .../0146-Mob-Pathfinding-API.patch | 259 - ...e-attack-cooldown-methods-for-Player.patch | 37 - ...CanPlaceOn-and-CanDestroy-NBT-values.patch | 319 -- ...currency-Improvements-to-Permissions.patch | 113 - ...-Add-ItemStackRecipeChoice-Draft-API.patch | 66 - ...nt-furnace-cook-speed-multiplier-API.patch | 38 - .../0152-PreSpawnerSpawnEvent.patch | 45 - .../0153-Material-API-additions.patch | 41 - .../0154-Add-Material-Tags.patch | 1044 ---- ...155-Allow-setting-the-vex-s-summoner.patch | 40 - ...156-Add-LivingEntity-getTargetEntity.patch | 105 - .../0157-Add-sun-related-API.patch | 45 - .../0158-Here-s-Johnny.patch | 42 - .../0159-Turtle-API.patch | 283 - .../0160-Add-spectator-target-events.patch | 141 - .../0161-Add-more-Witch-API.patch | 64 - ...ault-permission-message-configurable.patch | 57 - ...tion-supression-of-EntityDismount-Ve.patch | 109 - .../0164-Add-more-Zombie-API.patch | 66 - ...eserved-channel-check-to-be-sensible.patch | 34 - .../0166-Add-PlayerConnectionCloseEvent.patch | 136 - ...-replace-OfflinePlayer-getLastPlayed.patch | 62 - .../0168-BlockDestroyEvent.patch | 110 - ...-ItemStack-Recipe-API-helper-methods.patch | 70 - .../0170-Add-WhitelistToggleEvent.patch | 52 - .../0171-Annotation-Test-changes.patch | 29 - .../0172-Entity-getEntitySpawnReason.patch | 27 - .../0173-Add-GS4-Query-event.patch | 424 -- .../0174-Add-PlayerPostRespawnEvent.patch | 64 - ...rivate-methods-for-nullability-annot.patch | 20 - ...lip-some-Spigot-API-null-annotations.patch | 127 - .../0177-Server-Tick-Events.patch | 110 - ...0178-PlayerDeathEvent-getItemsToKeep.patch | 63 - .../0179-Add-Heightmap-API.patch | 196 - .../0180-Mob-Spawner-API-Enhancements.patch | 41 - .../0181-Add-BlockSoundGroup-interface.patch | 94 - ...ractAtEntityEvent-javadoc-for-ArmorS.patch | 20 - ...-custom-payload-channel-message-size.patch | 21 - ...184-Expose-the-internal-current-tick.patch | 38 - ...layerDeathEvent-shouldDropExperience.patch | 79 - ...-Add-effect-to-block-break-naturally.patch | 29 - .../0187-Add-ThrownEggHatchEvent.patch | 129 - .../0188-Entity-Jump-API.patch | 88 - ...189-add-hand-to-BlockMultiPlaceEvent.patch | 29 - .../0190-Add-tick-times-API.patch | 62 - ...191-Expose-MinecraftServer-isRunning.patch | 44 - ...nts-firing-Async-errors-during-shutd.patch | 25 - ...93-Make-JavaPluginLoader-thread-safe.patch | 53 - .../0194-Add-Player-Client-Options-API.patch | 202 - ...PlayerAttackEntityCooldownResetEvent.patch | 88 - ...mStack-swapping-the-extended-and-upg.patch | 21 - .../0197-Villager-Restocks-API.patch | 31 - .../0198-Expose-game-version.patch | 50 - ...99-Add-item-slot-convenience-methods.patch | 283 - .../0200-Add-Mob-Goal-API.patch | 481 -- .../0201-World-view-distance-api.patch | 45 - .../0202-Add-villager-reputation-API.patch | 177 - .../0203-Spawn-Reason-API.patch | 62 - .../0204-Potential-bed-API.patch | 33 - ...rioritise-own-classes-where-possible.patch | 86 - ...Add-Raw-Byte-ItemStack-Serialization.patch | 56 - ...-a-useful-PluginClassLoader-toString.patch | 30 - ...Holder-method-without-block-snapshot.patch | 51 - .../0209-Expose-Arrow-getItemStack.patch | 25 - ...implement-PlayerRecipeBookClickEvent.patch | 96 - .../0211-Support-components-in-ItemMeta.patch | 93 - ...-TargetReasons-for-1.16-mob-behavior.patch | 25 - .../0213-Add-entity-liquid-API.patch | 46 - ...reResultEvent-PrepareGrindstoneEvent.patch | 211 - ...llow-delegation-to-vanilla-chunk-gen.patch | 85 - ...-Support-hex-colors-in-getLastColors.patch | 34 - .../0217-Add-setMaxPlayers-API.patch | 48 - .../0218-Add-moon-phase-API.patch | 65 - ...yPickupItemAnimation-to-LivingEntity.patch | 39 - .../0220-Add-BellRingEvent.patch | 69 - .../0221-Brand-support.patch | 27 - .../0222-Add-more-Evoker-API.patch | 30 - ...-translation-keys-for-blocks-entitie.patch | 127 - ...ate-HoverEvent-from-ItemStack-Entity.patch | 73 - ...al-open-container-api-to-HumanEntity.patch | 103 - ...y-Counter-to-allow-plugins-to-use-va.patch | 24 - .../0227-Entity-isTicking.patch | 21 - ...docs-for-Entity.getEntitySpawnReason.patch | 19 - .../0229-Villager-resetOffers.patch | 22 - .../0230-Player-elytra-boost-API.patch | 30 - ...-Add-getOfflinePlayerIfCached-String.patch | 68 - .../0232-Add-ignore-discounts-API.patch | 52 - .../0233-Item-no-age-no-player-pickup.patch | 45 - ...0234-Beacon-API-custom-effect-ranges.patch | 37 - .../0235-Add-API-for-quit-reason.patch | 79 - .../0236-Add-Destroy-Speed-API.patch | 41 - ...237-Add-LivingEntity-clearActiveItem.patch | 24 - .../0238-Add-PlayerItemCooldownEvent.patch | 89 - .../0239-More-lightning-API.patch | 49 - .../0240-Add-PlayerShearBlockEvent.patch | 120 - ...241-Enable-multi-release-plugin-jars.patch | 30 - ...0242-Player-Chunk-Load-Unload-Events.patch | 100 - ...3-Expose-LivingEntity-hurt-direction.patch | 30 - .../0244-Added-PlayerTradeEvent.patch | 166 - ...-OBSTRUCTED-reason-to-BedEnterResult.patch | 23 - .../0246-Add-TargetHitEvent-API.patch | 81 - ...0247-Additional-Block-Material-API-s.patch | 57 - ...et-Material-from-Boats-and-Minecarts.patch | 58 - ...9-Add-PlayerFlowerPotManipulateEvent.patch | 94 - .../0250-Zombie-API-breaking-doors.patch | 30 - .../0251-Add-EntityLoadCrossbowEvent.patch | 113 - .../0252-Added-WorldGameRuleChangeEvent.patch | 103 - ...3-Added-ServerResourcesReloadedEvent.patch | 60 - .../0254-Add-BlockFailedDispenseEvent.patch | 69 - ...5-Added-PlayerLecternPageChangeEvent.patch | 127 - ...6-Added-PlayerLoomPatternSelectEvent.patch | 89 - .../0257-Better-AnnotationTest-printout.patch | 69 - ...xact-interaction-point-in-PlayerInte.patch | 67 - .../0259-Add-sendOpLevel-API.patch | 28 - .../0260-Add-StructureLocateEvent.patch | 167 - ...onent-with-empty-text-instead-of-thr.patch | 20 - .../0262-Add-BlockPreDispenseEvent.patch | 72 - .../0263-Added-Vanilla-Entity-Tags.patch | 43 - .../0264-added-Wither-API.patch | 45 - ...-Added-PlayerChangeBeaconEffectEvent.patch | 153 - ...Leash-variable-to-EntityUnleashEvent.patch | 78 - ...d-PlayerStonecutterRecipeSelectEvent.patch | 71 - .../0268-EntityMoveEvent.patch | 152 - .../0269-add-DragonEggFormEvent.patch | 75 - ...w-adding-items-to-BlockDropItemEvent.patch | 19 - ...ainThreadExecutor-to-BukkitScheduler.patch | 26 - ...-entity-allow-attribute-registration.patch | 25 - .../0273-Add-missing-effects.patch | 76 - .../0274-Expose-Tracked-Players.patch | 33 - ...Cache-the-result-of-Material-isBlock.patch | 38 - .../0276-Add-worldborder-events.patch | 308 -- .../0277-added-PlayerNameEntityEvent.patch | 130 - .../0278-Add-recipe-to-cook-events.patch | 69 - .../0279-Add-Block-isValidTool.patch | 26 - .../0280-Implement-Keyed-on-World.patch | 164 - ...ventory-getContents-null-annotations.patch | 22 - .../0282-Item-Rarity-API.patch | 109 - .../0283-Expose-protocol-version.patch | 23 - ...-add-isDeeplySleeping-to-HumanEntity.patch | 26 - ...-add-consumeFuel-to-FurnaceBurnEvent.patch | 44 - ...t-set-drop-chance-to-EntityEquipment.patch | 43 - .../0287-Added-PlayerDeepSleepEvent.patch | 58 - .../0288-More-World-API.patch | 131 - .../0289-Added-PlayerBedFailEnterEvent.patch | 131 - ...eacon-activation-deactivation-events.patch | 101 - .../0291-PlayerMoveEvent-Improvements.patch | 64 - ...d-RespawnFlags-to-PlayerRespawnEvent.patch | 73 - .../0293-Add-more-WanderingTrader-API.patch | 41 - ...ent-suggestion-tooltips-in-AsyncTabC.patch | 407 -- ...Add-EntityBlockStorage-clearEntities.patch | 22 - ...essage-to-PlayerAdvancementDoneEvent.patch | 71 - ...-address-to-AsyncPlayerPreLoginEvent.patch | 50 - .../0298-Inventory-close.patch | 26 - ...n-in-sunlight-API-for-Phantoms-and-S.patch | 55 - .../0300-Add-basic-Datapack-API.patch | 106 - ...ditions-to-PlayerGameModeChangeEvent.patch | 111 - .../0302-ItemStack-repair-check-API.patch | 59 - .../0303-More-Enchantment-API.patch | 124 - ...-option-to-load-extra-plugin-jars-no.patch | 142 - ...-missing-hard-depends-not-just-first.patch | 91 - .../0306-Add-Mob-lookAt-API.patch | 99 - .../0307-ItemStack-editMeta.patch | 42 - .../0308-Add-EntityInsideBlockEvent.patch | 92 - ...309-Attributes-API-for-item-defaults.patch | 53 - ...cause-to-Weather-ThunderChangeEvents.patch | 104 - .../0311-More-Lidded-Block-API.patch | 34 - .../0312-Add-PlayerKickEvent-causes.patch | 127 - .../0313-Add-PufferFishStateChangeEvent.patch | 92 - .../0314-Add-BellRevealRaiderEvent.patch | 70 - ...315-Add-ElderGuardianAppearanceEvent.patch | 81 - .../0316-Add-more-line-of-sight-methods.patch | 49 - .../0001-POM-Changes.patch | 291 - .../0002-Paper-config-files.patch | 820 --- .../0003-MC-Dev-fixes.patch | 893 --- .../0004-MC-Utils.patch | 4850 ---------------- .../0005-Paper-Metrics.patch | 735 --- ...-MinecraftKey-Information-to-Objects.patch | 144 - ...to-current-Chunk-for-Entity-and-Bloc.patch | 171 - ...ts-for-each-Entity-Block-Entity-Type.patch | 55 - .../0009-Timings-v2.patch | 2309 -------- .../0010-Adventure.patch | 3278 ----------- ...actus-bamboo-and-reed-growth-heights.patch | 114 - ...figurable-baby-zombie-movement-speed.patch | 51 - ...013-Configurable-fishing-time-ranges.patch | 38 - ...d-mobs-to-jump-and-take-water-damage.patch | 98 - ...-despawn-distances-for-living-entiti.patch | 55 - ...6-Allow-for-toggling-of-spawn-chunks.patch | 33 - ...ck-and-tnt-entities-at-the-specified.patch | 94 - ...ient-crashes-server-lists-and-Mojang.patch | 117 - .../0019-Implement-Paper-VersionChecker.patch | 150 - ...d-version-history-to-version-command.patch | 215 - .../0021-Player-affects-spawning-API.patch | 157 - ...ve-invalid-mob-spawner-tile-entities.patch | 33 - .../0023-Optimize-TileEntity-Ticking.patch | 248 - ...024-Further-improve-server-tick-loop.patch | 208 - ...025-Only-refresh-abilities-if-needed.patch | 25 - .../0026-Entity-Origin-API.patch | 140 - ...event-tile-entity-and-entity-crashes.patch | 65 - ...nfigurable-top-of-nether-void-damage.patch | 89 - ...e-before-converting-and-renaming-pla.patch | 19 - .../0030-Always-tick-falling-blocks.patch | 18 - .../0031-Configurable-end-credits.patch | 42 - ...-explosions-processing-dead-entities.patch | 19 - .../0033-Optimize-explosions.patch | 148 - .../0034-Disable-explosion-knockback.patch | 69 - .../0035-Disable-thunder.patch | 33 - .../0036-Disable-ice-and-snow.patch | 33 - ...7-Configurable-mob-spawner-tick-rate.patch | 65 - ...sition-the-first-time-an-entity-is-s.patch | 108 - .../0039-Add-BeaconEffectEvent.patch | 67 - ...figurable-container-update-tick-rate.patch | 46 - .../0041-Use-UserCache-for-player-heads.patch | 25 - .../0042-Disable-spigot-tick-limiters.patch | 21 - .../0043-Add-PlayerInitialSpawnEvent.patch | 48 - ...urable-Disabling-Cat-Chest-Detection.patch | 37 - ...45-Ensure-commands-are-not-ran-async.patch | 119 - ...chunks-are-slime-spawn-chunks-toggle.patch | 33 - .../0047-Expose-server-CommandMap.patch | 18 - ...e-informative-in-maxHealth-exception.patch | 22 - .../0049-Player-Tab-List-and-Title-APIs.patch | 142 - .../0050-Ensure-inv-drag-is-in-bounds.patch | 19 - ...entation-of-tile-entity-removal-list.patch | 20 - ...dd-configurable-portal-search-radius.patch | 56 - .../0053-Add-velocity-warnings.patch | 89 - ...ble-inter-world-teleportation-safety.patch | 44 - .../0055-Add-exception-reporting-event.patch | 264 - ...-don-t-need-to-when-cerealising-text.patch | 27 - ...oreboards-for-non-players-by-default.patch | 50 - ...working-with-arrows-stuck-in-living-.patch | 27 - .../0059-Complete-resource-pack-API.patch | 71 - .../0060-Chunk-Save-Reattempt.patch | 59 - ...ading-permissions.yml-before-plugins.patch | 52 - ...llow-Reloading-of-Custom-Permissions.patch | 35 - .../0063-Remove-Metadata-on-reload.patch | 31 - ...064-Handle-Item-Meta-Inconsistencies.patch | 331 -- ...urable-Non-Player-Arrow-Despawn-Rate.patch | 44 - .../0066-Add-World-Util-Methods.patch | 65 - ...7-Custom-replacement-for-eaten-items.patch | 48 - ...th-absorb-values-and-repair-bad-data.patch | 57 - ...069-Use-a-Shared-Random-for-Entities.patch | 42 - ...le-spawn-chances-for-skeleton-horses.patch | 36 - ...Location-getType-and-getBlockData-fo.patch | 206 - ...ckPhysicsEvent-if-a-plugin-has-a-lis.patch | 95 - ...Entity-AddTo-RemoveFrom-World-Events.patch | 27 - ...74-Configurable-Chunk-Inhabited-Time.patch | 44 - .../0075-EntityPathfindEvent.patch | 107 - ...egionFileCache-and-make-configurable.patch | 39 - ...7-Do-not-load-chunks-for-Pathfinding.patch | 68 - ...0078-Add-PlayerUseUnknownEntityEvent.patch | 40 - ...dDebugInfo-not-initialized-on-client.patch | 18 - ...-Configurable-Grass-Spread-Tick-Rate.patch | 41 - ...g-BlockPlaceEvent-triggering-physics.patch | 18 - .../0082-Optimize-DataBits.patch | 84 - ...nilla-per-world-scoreboard-coloring-.patch | 66 - ...nd-for-setting-passengers-on-players.patch | 29 - ...Remove-unused-World-Tile-Entity-List.patch | 90 - .../0086-Don-t-tick-Skulls-unused-code.patch | 28 - .../0087-Configurable-Player-Collision.patch | 131 - ...ent-to-allow-plugins-to-handle-clien.patch | 57 - .../0089-Configurable-RCON-IP-address.patch | 59 - ...e-from-loading-chunks-wrongly-spread.patch | 82 - ...91-Implement-PlayerLocaleChangeEvent.patch | 48 - ...ityRegainHealthEvent-isFastRegen-API.patch | 42 - ...-to-configure-frosted_ice-properties.patch | 52 - ...-possibility-for-getServer-singleton.patch | 36 - ...item-frames-performance-and-bug-fixe.patch | 144 - ...-API-Replenishable-Lootables-Feature.patch | 736 --- ...y-scoreboard-teams-to-scoreboard.dat.patch | 32 - ...tem-property-for-disabling-watchdoge.patch | 19 - .../0099-Optimize-UserCache-Thread-Safe.patch | 117 - ...blocking-on-Network-Manager-creation.patch | 45 - ...1-Optional-TNT-doesn-t-move-in-water.patch | 122 - ...r-redstone-torch-rapid-clock-removal.patch | 98 - .../0103-Add-server-name-parameter.patch | 25 - ...on-Wither-Death-sounds-to-same-world.patch | 39 - .../0105-Fix-Double-World-Add-issues.patch | 21 - .../0106-Fix-Old-Sign-Conversion.patch | 59 - ...e-profiles-that-have-no-UUID-and-no-.patch | 19 - ...setting-for-proxy-online-mode-status.patch | 81 - ...ptimise-BlockState-s-hashCode-equals.patch | 84 - ...onfigurable-packet-in-spam-threshold.patch | 45 - ...11-Configurable-flying-kick-messages.patch | 44 - .../0112-Chunk-registration-fixes.patch | 22 - ...ok-reference-on-Craft-Entity-removal.patch | 25 - ...uto-fix-bad-Y-levels-on-player-login.patch | 19 - ...tion-to-remove-corrupt-tile-entities.patch | 37 - .../0116-Add-EntityZapEvent.patch | 58 - ...a-from-ArmorStand-and-SpawnEgg-items.patch | 49 - ...118-Cache-user-authenticator-threads.patch | 68 - .../0119-Optimise-removeQueue.patch | 67 - ...0-Allow-Reloading-of-Command-Aliases.patch | 36 - ...1-Add-source-to-PlayerExpChangeEvent.patch | 49 - ...2-Don-t-let-fishinghooks-use-portals.patch | 22 - .../0123-Add-ProjectileCollideEvent.patch | 109 - ...vent-Pathfinding-out-of-World-Border.patch | 20 - ...imize-World.isLoaded-BlockPosition-Z.patch | 22 - ...-Bound-Treasure-Maps-to-World-Border.patch | 47 - ...figurable-Cartographer-Treasure-Maps.patch | 65 - .../0128-Optimize-ItemStack.isEmpty.patch | 20 - ...to-control-if-armour-stands-can-move.patch | 81 - ...30-Properly-fix-item-duplication-bug.patch | 35 - .../0131-String-based-Action-Bar-API.patch | 48 - .../0132-Firework-API-s.patch | 124 - .../0133-PlayerTeleportEndGatewayEvent.patch | 28 - ...rovide-E-TE-Chunk-count-stat-methods.patch | 61 - .../0135-Enforce-Sync-Player-Saves.patch | 26 - ...llow-entities-to-ride-themselves-572.patch | 18 - ...PI-for-Reason-Source-Triggering-play.patch | 315 -- .../0138-Cap-Entity-Collisions.patch | 57 - ...e-CraftScheduler-Async-Task-Debugger.patch | 48 - ...more-aggressive-in-the-chunk-unload-.patch | 47 - .../0141-Do-not-let-armorstands-drown.patch | 42 - ...le-async-calls-to-restart-the-server.patch | 307 -- ...property-to-disable-book-size-limits.patch | 51 - ...ke-parrots-stay-on-shoulders-despite.patch | 58 - ...n-option-to-prevent-player-names-fro.patch | 36 - ...oleAppender-for-console-improvements.patch | 549 -- ...urable-option-to-disable-creeper-lin.patch | 35 - .../0148-Item-canEntityPickup.patch | 55 - ...PlayerPickupItemEvent-setFlyAtPlayer.patch | 46 - .../0150-PlayerAttemptPickupItemEvent.patch | 41 - .../0151-Add-UnknownCommandEvent.patch | 25 - .../0152-Basic-PlayerProfile-API.patch | 575 -- .../0153-Shoulder-Entities-Release-API.patch | 96 - .../0154-Profile-Lookup-Events.patch | 81 - ...player-logins-during-server-shutdown.patch | 23 - .../0156-Entity-fromMobSpawner.patch | 65 - ...57-Improve-the-Saddle-API-for-Horses.patch | 59 - ...mplement-ensureServerConversions-API.patch | 24 - .../0159-Implement-getI18NDisplayName.patch | 58 - .../0160-ProfileWhitelistVerifyEvent.patch | 50 - .../0161-Fix-this-stupid-bullshit.patch | 30 - ...awns-should-honor-nametags-and-leash.patch | 19 - ...imer-when-spawner-event-is-cancelled.patch | 27 - ...64-Fix-MC-117075-TE-Unload-Lag-Spike.patch | 23 - ...-a-custom-authentication-servers-dow.patch | 43 - .../0166-LivingEntity-setKiller.patch | 48 - ...n-prefixes-using-Log4J-configuration.patch | 71 - ...e-Log4J-Configuration-Plugin-Loggers.patch | 47 - .../0169-Add-PlayerJumpEvent.patch | 46 - ...0-handle-PacketPlayInKeepAlive-async.patch | 40 - ...nt-protocol-version-and-virtual-host.patch | 129 - ...rt-serverside-behavior-of-keepalives.patch | 75 - ...dEffects-only-to-players-who-can-see.patch | 80 - ...-maximum-exp-value-when-merging-orbs.patch | 61 - .../0175-Add-PlayerArmorChangeEvent.patch | 43 - ...rom-being-processed-when-the-player-.patch | 24 - ...e-implementations-for-captured-block.patch | 60 - ...-get-a-BlockState-without-a-snapshot.patch | 147 - .../0179-AsyncTabCompleteEvent.patch | 130 - ...180-Avoid-NPE-in-PathfinderGoalTempt.patch | 19 - .../0181-PlayerPickupExperienceEvent.patch | 28 - .../0182-ExperienceOrbMergeEvent.patch | 22 - ...3-Ability-to-apply-mending-to-XP-API.patch | 104 - ...-max-squid-spawn-height-configurable.patch | 36 - .../0185-PreCreatureSpawnEvent.patch | 200 - ...6-PlayerNaturallySpawnCreaturesEvent.patch | 79 - ...-Add-setPlayerProfile-API-for-Skulls.patch | 99 - .../0188-Fill-Profile-Property-Events.patch | 42 - ...PlayerAdvancementCriterionGrantEvent.patch | 23 - .../0190-Add-ArmorStand-Item-Meta.patch | 296 - ...-Extend-Player-Interact-cancellation.patch | 68 - .../0192-Tameable-getOwnerUniqueId-API.patch | 36 - ...r-crits-helps-mitigate-hacked-client.patch | 34 - ...sted-Ice-from-loading-holding-chunks.patch | 31 - ...le-Explicit-Network-Manager-Flushing.patch | 34 - ...nt-extended-PaperServerListPingEvent.patch | 283 - .../0197-Improved-Async-Task-Scheduler.patch | 370 -- ...e-PlayerProfile-in-AsyncPreLoginEven.patch | 45 - .../0199-Player.setPlayerProfile-API.patch | 142 - .../0200-Fix-Dragon-Server-Crashes.patch | 21 - .../0201-getPlayerUniqueId-API.patch | 40 - ...Make-player-data-saving-configurable.patch | 27 - ...ke-legacy-ping-handler-more-reliable.patch | 168 - ...ServerListPingEvent-for-legacy-pings.patch | 154 - ...05-Flag-to-disable-the-channel-limit.patch | 31 - ...d-method-to-open-already-placed-sign.patch | 36 - ...urable-sprint-interruption-on-attack.patch | 38 - ...-allowed-colored-signs-to-be-created.patch | 31 - .../0209-EndermanEscapeEvent.patch | 82 - .../0210-Enderman.teleportRandomly.patch | 31 - ...0211-Block-Enderpearl-Travel-Exploit.patch | 40 - ...ld.spawnParticle-API-and-add-Builder.patch | 67 - .../0213-EndermanAttackPlayerEvent.patch | 29 - .../0214-WitchConsumePotionEvent.patch | 24 - .../0215-WitchThrowPotionEvent.patch | 30 - ...Item-entities-with-World.spawnEntity.patch | 24 - .../0217-WitchReadyPotionEvent.patch | 23 - ...0218-ItemStack-getMaxItemUseDuration.patch | 37 - ...lement-EntityTeleportEndGatewayEvent.patch | 32 - ...ed-flag-on-cancel-of-Explosion-Event.patch | 28 - .../0221-Fix-CraftEntity-hashCode.patch | 46 - ...le-Alternative-LootPool-Luck-Formula.patch | 110 - ...ils-when-failing-to-save-player-data.patch | 19 - ...e-shield-blocking-delay-configurable.patch | 69 - .../0225-Improve-EntityShootBowEvent.patch | 44 - .../0226-PlayerReadyArrowEvent.patch | 39 - ...plement-EntityKnockbackByEntityEvent.patch | 93 - .../0228-Expand-Explosions-API.patch | 23 - ...ivingEntity-Hand-Raised-Item-Use-API.patch | 68 - .../0230-RangedEntity-API.patch | 171 - ...to-disable-ender-dragon-legacy-check.patch | 44 - ...2-Implement-World.getEntity-UUID-API.patch | 26 - .../0233-InventoryCloseEvent-Reason-API.patch | 227 - .../0234-Vex-getSummoner-API.patch | 37 - ...nventory-when-cancelling-PlayerInter.patch | 29 - ...ge-the-Entity-Random-seed-for-squids.patch | 19 - ...nilla-entity-warnings-for-duplicates.patch | 22 - ...e-if-stack-size-above-max-stack-size.patch | 21 - ...239-Use-asynchronous-Log4j-2-loggers.patch | 55 - ...-more-information-to-Entity.toString.patch | 20 - ...ies-option-to-debug-dupe-uuid-issues.patch | 131 - .../0242-EnderDragon-Events.patch | 62 - .../0243-PlayerElytraBoostEvent.patch | 31 - .../0244-Improve-BlockPosition-inlining.patch | 75 - .../0245-Optimize-RegistryID.c.patch | 65 - ...t-armor-stands-from-doing-entity-loo.patch | 58 - ...7-Vanished-players-don-t-have-rights.patch | 194 - ...-anytime-entities-change-to-guarante.patch | 27 - ...dd-some-Debug-to-Chunk-Entity-slices.patch | 80 - .../0250-SkeletonHorse-Additions.patch | 152 - ...revent-Saving-Bad-entities-to-chunks.patch | 127 - ...on-t-call-getItemMeta-on-hasItemMeta.patch | 64 - ...ead-Entities-in-entityList-iteration.patch | 120 - ...54-Implement-Expanded-ArmorStand-API.patch | 112 - .../0255-AnvilDamageEvent.patch | 28 - .../0256-Add-TNTPrimeEvent.patch | 148 - ...nd-make-tab-spam-limits-configurable.patch | 75 - .../0258-Add-hand-to-bucket-events.patch | 174 - ...6-Experience-should-save-as-Integers.patch | 28 - ...ient-rendering-skulls-from-same-user.patch | 147 - ...dd-Early-Warning-Feature-to-WatchDog.patch | 184 - .../0262-Make-EnderDragon-implement-Mob.patch | 33 - ...63-Use-ConcurrentHashMap-in-JsonList.patch | 136 - ...64-Use-a-Queue-for-Queueing-Commands.patch | 33 - ...ile-Entities-from-a-chunk-without-sn.patch | 73 - ...Allow-disabling-armour-stand-ticking.patch | 159 - ...ptimize-BlockPosition-helper-methods.patch | 100 - ...efault-mob-spawn-range-and-water-ani.patch | 33 - .../0269-Slime-Pathfinder-Events.patch | 167 - ...le-speed-for-water-flowing-over-lava.patch | 72 - ...271-Optimize-CraftBlockData-Creation.patch | 49 - .../0272-Optimize-RegistryMaterials.patch | 61 - .../0273-Add-PhantomPreSpawnEvent.patch | 96 - .../0274-Add-More-Creeper-API.patch | 49 - .../0275-Inventory-removeItemAnySlot.patch | 58 - ...loadChunk-int-int-false-load-unconve.patch | 20 - ...-ray-tracing-methods-to-LivingEntity.patch | 99 - ...e-attack-cooldown-methods-for-Player.patch | 41 - .../0279-Improve-death-events.patch | 425 -- ...ow-chests-to-be-placed-with-NBT-data.patch | 31 - .../0281-Mob-Pathfinding-API.patch | 290 - ...ent-chunk-loading-from-Fluid-Flowing.patch | 75 - ...-for-CanPlaceOn-and-CanDestroy-NBT-v.patch | 446 -- ...ent-Mob-AI-Rules-from-Loading-Chunks.patch | 83 - ...wning-from-loading-generating-chunks.patch | 32 - ...e-Biome-Mob-Lookups-for-Mob-Spawning.patch | 92 - ...nt-furnace-cook-speed-multiplier-API.patch | 102 - .../0288-PreSpawnerSpawnEvent.patch | 29 - ...arseException-in-Entity-and-TE-names.patch | 110 - .../0290-Honor-EntityAgeable.ageLock.patch | 18 - ...ble-connection-throttle-kick-message.patch | 35 - .../0292-Hook-into-CB-plugin-rewrites.patch | 184 - ...293-Allow-setting-the-vex-s-summoner.patch | 33 - .../0294-Add-sun-related-API.patch | 52 - .../0295-Turtle-API.patch | 150 - ...ther-worlds-for-shooter-of-projectil.patch | 36 - ...tator-target-events-and-improve-impl.patch | 101 - ...8-Add-Velocity-IP-Forwarding-Support.patch | 307 -- .../0299-Add-more-Witch-API.patch | 153 - ...owned-for-Villager-Aggression-Config.patch | 19 - .../0301-Here-s-Johnny.patch | 38 - ...event-players-from-moving-into-unloa.patch | 64 - ...03-Reset-players-airTicks-on-respawn.patch | 30 - ...-after-profile-lookups-if-not-needed.patch | 33 - ...er-Thread-Pool-and-Thread-Priorities.patch | 108 - .../0306-Optimize-World-Time-Updates.patch | 42 - ...store-custom-InventoryHolder-support.patch | 46 - .../0308-Use-Vanilla-Minecart-Speeds.patch | 24 - .../0309-Fix-SpongeAbsortEvent-handling.patch | 37 - ...t-allow-digging-into-unloaded-chunks.patch | 68 - .../0311-Book-Size-Limits.patch | 80 - ...ault-permission-message-configurable.patch | 46 - ...Prevent-rayTrace-from-loading-chunks.patch | 29 - ...e-Large-Packets-disconnecting-client.patch | 130 - ...entity-dismount-during-teleportation.patch | 134 - .../0316-Add-more-Zombie-API.patch | 117 - .../0317-Add-PlayerConnectionCloseEvent.patch | 82 - ...Prevent-Enderman-from-loading-chunks.patch | 30 - ...-replace-OfflinePlayer-getLastPlayed.patch | 164 - ...vehicle-tracking-issue-on-disconnect.patch | 24 - ...onRetractEvent-for-all-empty-pistons.patch | 47 - ...-remove-from-being-called-on-Players.patch | 33 - .../0323-BlockDestroyEvent.patch | 46 - ...om-Shapeless-Custom-Crafting-Recipes.patch | 68 - .../0325-Fix-sign-edit-memory-leak.patch | 44 - .../0326-Limit-Client-Sign-length-more.patch | 54 - ...ConvertSigns-boolean-every-sign-save.patch | 29 - ...-Manager-and-add-advanced-packet-sup.patch | 390 -- ...le-Oversized-Tile-Entities-in-chunks.patch | 54 - ...0-Fix-Whitelist-On-Off-inconsistency.patch | 36 - ...st-tick-at-start-of-drowning-process.patch | 19 - ...332-Allow-Saving-of-Oversized-Chunks.patch | 272 - ...oggleEvent-when-whitelist-is-toggled.patch | 18 - ...334-Add-LivingEntity-getTargetEntity.patch | 187 - ...ength-when-serialising-BungeeCord-te.patch | 32 - .../0336-Entity-getEntitySpawnReason.patch | 121 - ...ity-Metadata-for-all-tracked-players.patch | 43 - ...338-Implement-PlayerPostRespawnEvent.patch | 48 - ...-for-pickupDelay-breaks-picking-up-i.patch | 27 - .../0340-Server-Tick-Events.patch | 32 - ...0341-PlayerDeathEvent-getItemsToKeep.patch | 74 - ...-Optimize-Captured-TileEntity-Lookup.patch | 32 - .../0343-Add-Heightmap-API.patch | 55 - .../0344-Mob-Spawner-API-Enhancements.patch | 140 - ...layer-View-Distance-API-placeholders.patch | 62 - ...l-to-changed-postToMainThread-method.patch | 19 - ...n-item-frames-are-modified-MC-123450.patch | 20 - ...isPrimaryThread-and-MinecraftServer-.patch | 43 - ...h-entity-loss-due-to-unloaded-chunks.patch | 53 - .../0350-Duplicate-UUID-Resolve-Option.patch | 249 - ...351-improve-CraftWorld-isChunkLoaded.patch | 30 - ...le-Keep-Spawn-Loaded-range-per-world.patch | 261 - ...tityAreaEffectCloud-from-going-negat.patch | 24 - .../0354-ChunkMapDistance-CME.patch | 83 - .../0355-Implement-CraftBlockSoundGroup.patch | 83 - .../0356-Chunk-debug-command.patch | 486 -- ...eptions-from-dispenser-entity-spawns.patch | 33 - ...358-Fix-World-isChunkGenerated-calls.patch | 390 -- ...ate-location-if-we-failed-to-read-it.patch | 34 - ...PaletteBlock-instead-of-ReentrantLoc.patch | 101 - .../0361-incremental-chunk-saving.patch | 317 -- .../0362-Anti-Xray.patch | 1567 ------ ...al-Spawned-mobs-towards-natural-spaw.patch | 57 - ...gurable-projectile-relative-velocity.patch | 53 - ...-being-ticked-when-notifying-navigat.patch | 26 - .../0366-offset-item-frame-ticking.patch | 19 - ...opper-searches-if-there-are-no-items.patch | 127 - ...68-Asynchronous-chunk-IO-and-loading.patch | 4203 -------------- ...etChunkIfLoadedImmediately-in-places.patch | 96 - .../0370-Reduce-sync-loads.patch | 342 -- ...lement-alternative-item-despawn-rate.patch | 127 - ...if-we-have-a-custom-Bukkit-generator.patch | 42 - .../0373-Fix-MC-158900.patch | 25 - ...ement-optional-per-player-mob-spawns.patch | 848 --- ...revent-consuming-the-wrong-itemstack.patch | 45 - .../0376-Generator-Settings.patch | 89 - .../0377-Fix-MC-161754.patch | 23 - ...ce-improvement-for-Chunk.getEntities.patch | 35 - ...hanging-entities-that-are-not-ItemFr.patch | 25 - ...380-Expose-the-internal-current-tick.patch | 21 - ...-sneak-when-changing-worlds-MC-10657.patch | 32 - ...d-option-to-disable-pillager-patrols.patch | 32 - ...or-when-player-hand-set-to-empty-typ.patch | 35 - .../0384-PlayerLaunchProjectileEvent.patch | 329 -- ...ftMagicNumbers.isSupportedApiVersion.patch | 22 - ...nk-loads-when-villagers-try-to-find-.patch | 20 - ...5656-Fix-Follow-Range-Initial-Target.patch | 73 - .../0388-Optimize-Hoppers.patch | 517 -- ...layerDeathEvent-shouldDropExperience.patch | 19 - ...oading-chunks-checking-hive-position.patch | 18 - ...Chunks-from-Hoppers-and-other-things.patch | 32 - ...rializing-mismatching-chunk-coordina.patch | 62 - ...timise-IEntityAccess-getPlayerByUUID.patch | 44 - ...0394-Fix-items-not-falling-correctly.patch | 29 - .../0395-Lag-compensate-eating.patch | 83 - ...mize-call-to-getFluid-for-explosions.patch | 19 - ...k-in-stack-not-having-effects-when-d.patch | 23 - ...-Add-effect-to-block-break-naturally.patch | 32 - .../0399-Tracking-Range-Improvements.patch | 67 - .../0400-Entity-Activation-Range-2.0.patch | 869 --- ...x-items-vanishing-through-end-portal.patch | 28 - ...get-gravity-in-void.-Fixes-MC-167279.patch | 55 - ...e-getChunkAt-calls-for-loaded-chunks.patch | 66 - ...ow-overriding-the-java-version-check.patch | 20 - .../0405-Add-ThrownEggHatchEvent.patch | 29 - .../0406-Optimise-random-block-ticking.patch | 407 -- .../0407-Entity-Jump-API.patch | 59 - ...n-to-nerf-pigmen-from-nether-portals.patch | 71 - .../0409-Make-the-GUI-graph-fancier.patch | 436 -- ...410-add-hand-to-BlockMultiPlaceEvent.patch | 30 - ...11-Prevent-teleporting-dead-entities.patch | 21 - ...ripwire-hook-placement-before-update.patch | 18 - ...to-allow-iron-golems-to-spawn-in-air.patch | 35 - ...-chance-of-villager-zombie-infection.patch | 44 - .../0415-Optimise-Chunk-getFluid.patch | 62 - ...imise-TickListServer-by-rewriting-it.patch | 1267 ----- ...spawn-settings-and-per-player-option.patch | 151 - ...re-Entity-is-never-double-registered.patch | 79 - ...ering-entities-from-unloading-chunks.patch | 32 - ...nnections-shouldn-t-hold-up-shutdown.patch | 25 - ...low-bees-to-load-chunks-for-beehives.patch | 42 - ...-PlayerChunkMap-adds-crashing-server.patch | 48 - ...ptimize-Collision-to-not-load-chunks.patch | 161 - .../0424-Don-t-tick-dead-players.patch | 21 - ...d-Player-s-shouldn-t-be-able-to-move.patch | 21 - ...hunkMap-memory-use-for-visibleChunks.patch | 294 - .../0427-Increase-Light-Queue-Size.patch | 42 - ...asks-Speed-up-processing-of-chunk-lo.patch | 271 - ...move-existing-players-to-world-spawn.patch | 54 - ...-Add-tick-times-API-and-mspt-command.patch | 169 - ...431-Expose-MinecraftServer-isRunning.patch | 22 - ...Add-Raw-Byte-ItemStack-Serialization.patch | 102 - ...33-Remove-streams-from-Mob-AI-System.patch | 253 - ...ions-until-after-entity-ticking-is-d.patch | 45 - .../0435-Async-command-map-building.patch | 48 - .../0436-Improved-Watchdog-Support.patch | 608 --- .../0437-Optimize-Pathfinding.patch | 61 - ...38-Reduce-Either-Optional-allocation.patch | 48 - ...0439-Remove-streams-from-PairedQueue.patch | 79 - ...e-memory-footprint-of-NBTTagCompound.patch | 59 - ...vent-opening-inventories-when-frozen.patch | 59 - ...442-Optimise-ArraySetSorted-removeIf.patch | 65 - ...-entity-collision-code-if-not-needed.patch | 30 - ...oviderServer-s-chunk-level-checking-.patch | 51 - ...-teleport-command-to-valid-locations.patch | 24 - ...-Implement-Player-Client-Options-API.patch | 188 - ...-Chunk-Post-Processing-deadlock-risk.patch | 60 - ...layer-is-attempted-to-be-removed-fro.patch | 23 - ...49-Broadcast-join-message-to-console.patch | 21 - ...g-Broken-behavior-of-PlayerJoinEvent.patch | 111 - ...Load-Chunks-for-Login-Asynchronously.patch | 306 -- ...pawn-point-if-spawn-in-unloaded-worl.patch | 27 - ...PlayerAttackEntityCooldownResetEvent.patch | 28 - ...allbacks-to-schedule-for-Callback-Ex.patch | 58 - ...t-fire-BlockFade-on-worldgen-threads.patch | 28 - ...ntom-creative-and-insomniac-controls.patch | 69 - ...m-duplication-issues-and-teleport-is.patch | 117 - .../0458-Implement-Brigadier-Mojang-API.patch | 139 - .../0459-Villager-Restocks-API.patch | 42 - ...PickItem-Packet-and-kick-for-invalid.patch | 26 - .../0461-Expose-game-version.patch | 24 - .../0462-Optimize-Voxel-Shape-Merging.patch | 127 - ...-per-thread-native-byte-buffer-cache.patch | 30 - .../0464-Implement-Mob-Goal-API.patch | 1170 ---- ...tance-map-to-optimise-entity-tracker.patch | 413 -- ...-isOutsideRange-to-use-distance-maps.patch | 384 -- ...te-operations-for-updating-light-dat.patch | 319 -- ...No-Tick-view-distance-implementation.patch | 774 --- .../0469-Add-villager-reputation-API.patch | 153 - .../0470-Fix-Light-Command.patch | 185 - ...1-Fix-PotionEffect-ignores-icon-flag.patch | 19 - ...-brigadier-child-sorting-performance.patch | 29 - .../0473-Potential-bed-API.patch | 44 - ...Wait-for-Async-Tasks-during-shutdown.patch | 63 - ...der-respects-game-and-entity-rules-f.patch | 28 - ...and-End-Portal-Frames-from-being-des.patch | 173 - ...ze-NibbleArray-to-use-pooled-buffers.patch | 394 -- ...bleInt-allocations-from-light-engine.patch | 50 - ...llocation-of-Vec3D-by-entity-tracker.patch | 61 - .../0480-Ensure-safe-gateway-teleport.patch | 27 - ...n-for-console-having-all-permissions.patch | 74 - ...on-Full-Status-Chunk-NBT-Memory-Leak.patch | 99 - ...ound-for-Client-Lag-Spikes-MC-162253.patch | 119 - ...k-Priority-Urgency-System-for-Chunks.patch | 1326 ----- ...-packets-to-nearby-locations-sounds-.patch | 63 - ...mprove-Chunk-Status-Transition-Speed.patch | 99 - ...ix-villager-trading-demand-MC-163962.patch | 20 - .../0488-Maps-shouldn-t-load-chunks.patch | 32 - ...ookup-for-Treasure-Maps-Fixes-lag-fr.patch | 35 - ...-Optimize-Bit-Operations-by-inlining.patch | 220 - .../0491-Optimize-Light-Engine.patch | 1433 ----- ...unk-Unloads-based-on-Player-Movement.patch | 107 - ...-Plugin-Tickets-to-API-Chunk-Methods.patch | 129 - ...ssing-chunks-due-to-integer-overflow.patch | 29 - ...er-runTaskTimerAsynchronously-Plugin.patch | 21 - ...ston-physics-inconsistency-MC-188840.patch | 93 - .../0497-Fix-sand-duping.patch | 37 - ...-desync-in-playerconnection-causing-.patch | 31 - .../0499-Fix-enderdragon-exp-dupe.patch | 28 - ...Holder-method-without-block-snapshot.patch | 50 - .../0501-Expose-Arrow-getItemStack.patch | 36 - ...implement-PlayerRecipeBookClickEvent.patch | 29 - ...3-Hide-sync-chunk-writes-behind-flag.patch | 23 - ...mit-lightning-strike-effect-distance.patch | 68 - ...05-Add-permission-for-command-blocks.patch | 79 - ...sure-Entity-AABB-s-are-never-invalid.patch | 48 - ...WorldBorder-collision-checks-and-air.patch | 63 - ...ld-Difficulty-Remembering-Difficulty.patch | 86 - .../0509-Paper-dumpitem-command.patch | 80 - ...510-Don-t-allow-null-UUID-s-for-chat.patch | 27 - ...-Legacy-Component-serialization-size.patch | 56 - ...0512-Support-old-UUID-format-for-NBT.patch | 64 - ...up-duplicated-GameProfile-Properties.patch | 68 - ...nvert-legacy-attributes-in-Item-Meta.patch | 44 - ...-Remove-some-streams-from-structures.patch | 140 - ...from-classes-related-villager-gossip.patch | 100 - .../0517-Support-components-in-ItemMeta.patch | 83 - ...argetLivingEntityEvent-for-1.16-mobs.patch | 59 - .../0519-Add-entity-liquid-API.patch | 75 - ...pdate-itemstack-legacy-name-and-lore.patch | 79 - ...awn-player-in-correct-world-on-login.patch | 30 - .../0522-Add-PrepareResultEvent.patch | 164 - ...llow-delegation-to-vanilla-chunk-gen.patch | 104 - ...k-for-portal-on-world-gen-entity-add.patch | 19 - ...ze-NetworkManager-Exception-Handling.patch | 96 - ...ix-Concurrency-issue-in-WeightedList.patch | 148 - ...ancement-data-player-iteration-to-be.patch | 54 - ...ix-arrows-never-despawning-MC-125757.patch | 30 - ...-Vanilla-Command-permission-checking.patch | 53 - ...ove-range-check-for-block-placing-up.patch | 35 - .../0531-Fix-SPIGOT-5989.patch | 69 - ...4-Bukkit-world-container-is-not-used.patch | 33 - ...-5885-Unable-to-disable-advancements.patch | 18 - ...ataPlayer-leak-due-from-quitting-ear.patch | 94 - ...keLighting-call-to-World-spigot-stri.patch | 19 - ...Fix-some-rails-connecting-improperly.patch | 95 - ...der-Remove-Streams-Optimized-collect.patch | 134 - .../0538-Incremental-player-saving.patch | 95 - .../0539-Import-fastutil-classes.patch | 27 - ...ull-chunk-sections-for-block-updates.patch | 18 - ...ove-armour-stand-double-add-to-world.patch | 28 - ...-Fix-MC-187716-Use-configured-height.patch | 45 - ...istake-in-CB-NBT-int-deserialization.patch | 27 - ...erver-load-chunks-from-newer-version.patch | 39 - .../0545-Brand-support.patch | 92 - ...her-Boss-Bar-doesn-t-update-until-in.patch | 22 - .../0547-Fix-MC-197271.patch | 51 - .../0548-MC-197883-Bandaid-decode-issue.patch | 28 - .../0549-Add-setMaxPlayers-API.patch | 37 - ...yPickupItemAnimation-to-LivingEntity.patch | 21 - .../0551-Don-t-require-FACING-data.patch | 35 - ...geEvent-not-firing-for-all-use-cases.patch | 46 - .../0553-Add-moon-phase-API.patch | 22 - ...-headless-pistons-from-being-created.patch | 74 - .../0555-Add-BellRingEvent.patch | 53 - ...Add-zombie-targets-turtle-egg-config.patch | 33 - .../0557-Buffer-joins-to-world.patch | 71 - .../0558-Optimize-redstone-algorithm.patch | 1158 ---- ...rs-not-working-in-some-kick-messages.patch | 64 - ...CreateEvent-needs-to-know-its-entity.patch | 135 - .../0561-Fix-CraftTeam-null-check.patch | 19 - .../0562-Add-more-Evoker-API.patch | 57 - ...-translation-keys-for-blocks-entitie.patch | 126 - ...ate-HoverEvent-from-ItemStack-Entity.patch | 51 - .../0565-Cache-block-data-strings.patch | 70 - ...ortation-and-cancel-velocity-if-tele.patch | 83 - ...al-open-container-api-to-HumanEntity.patch | 81 - ...taFixerUpper-Rewrite-Rules-on-demand.patch | 54 - ...p-capture-to-capture-all-items-added.patch | 60 - ...rty-in-invalid-locations-SPIGOT-6086.patch | 18 - ...y-Counter-to-allow-plugins-to-use-va.patch | 37 - ...-track-plugin-scoreboards-by-default.patch | 102 - .../0573-Entity-isTicking.patch | 42 - ...-non-whitelisted-player-when-white-l.patch | 19 - ...Fix-Not-a-string-Map-Conversion-spam.patch | 54 - ...ng-a-passenger-in-CreatureSpawnEvent.patch | 19 - ...tems-that-are-extra-from-a-crafting-.patch | 24 - ...Reset-Ender-Crystals-on-Dragon-Spawn.patch | 24 - ...r-large-move-vectors-crashing-server.patch | 66 - .../0580-Optimise-getType-calls.patch | 96 - .../0581-Villager-resetOffers.patch | 48 - ...inig-for-some-hot-IBlockData-methods.patch | 101 - ...ace-order-when-capturing-blockstates.patch | 24 - ...blockpos-allocation-from-pathfinding.patch | 28 - ...tem-locations-dropped-from-campfires.patch | 32 - .../0586-Player-elytra-boost-API.patch | 46 - ...587-Fixed-TileEntityBell-memory-leak.patch | 56 - ...ling-up-when-item-stack-is-empty-in-.patch | 46 - ...-Add-getOfflinePlayerIfCached-String.patch | 39 - .../0590-Add-ignore-discounts-API.patch | 143 - ...-Toggle-for-removing-existing-dragon.patch | 36 - ...ix-client-lag-on-advancement-loading.patch | 55 - .../0593-Item-no-age-no-player-pickup.patch | 50 - ...0594-Beacon-API-custom-effect-ranges.patch | 90 - .../0595-Add-API-for-quit-reason.patch | 63 - .../0596-Seed-based-feature-search.patch | 115 - ...ing-Trader-spawn-rate-config-options.patch | 120 - ...prove-performance-of-the-end-generat.patch | 77 - .../0599-Expose-world-spawn-angle.patch | 44 - .../0600-Add-Destroy-Speed-API.patch | 35 - ...r-spawnParticle-x-y-z-precision-loss.patch | 19 - ...602-Add-LivingEntity-clearActiveItem.patch | 24 - .../0603-Add-PlayerItemCooldownEvent.patch | 38 - .../0604-More-lightning-API.patch | 68 - ...-should-not-bypass-cramming-gamerule.patch | 179 - ...d-missing-default-perms-for-commands.patch | 70 - .../0607-Add-PlayerShearBlockEvent.patch | 109 - ...g-for-servers-not-running-on-Java-16.patch | 80 - ...erbose-world-setting-to-false-by-def.patch | 19 - ...ing-zombie-villager-discount-exploit.patch | 55 - .../0611-Limit-recipe-packets.patch | 74 - ...x-CraftSound-backwards-compatibility.patch | 21 - .../0613-MC-4-Fix-item-position-desync.patch | 84 - ...0614-Player-Chunk-Load-Unload-Events.patch | 41 - ...15-Optimize-Dynamic-get-Missing-Keys.patch | 34 - ...6-Expose-LivingEntity-hurt-direction.patch | 39 - ...-OBSTRUCTED-reason-to-BedEnterResult.patch | 21 - ...m-invalid-ingredient-lists-in-Villag.patch | 24 - .../0619-added-PlayerTradeEvent.patch | 75 - .../0620-Implement-TargetHitEvent.patch | 49 - ...0621-Additional-Block-Material-API-s.patch | 40 - .../0622-Fix-harming-potion-dupe.patch | 59 - ...-get-Material-from-Boats-and-Minecar.patch | 101 - .../0624-Optimized-tick-ready-check.patch | 51 - .../0625-Cache-burn-durations.patch | 63 - ...mob-spawner-spawn-egg-transformation.patch | 33 - ...ement-PlayerFlowerPotManipulateEvent.patch | 47 - ...-event-not-being-called-in-adventure.patch | 29 - .../0629-Zombie-API-breaking-doors.patch | 44 - ...0630-Fix-nerfed-slime-when-splitting.patch | 18 - .../0631-Add-EntityLoadCrossbowEvent.patch | 48 - .../0632-Guardian-beam-workaround.patch | 30 - .../0633-Added-WorldGameRuleChangeEvent.patch | 108 - ...4-Added-ServerResourcesReloadedEvent.patch | 79 - ...ld-settings-for-mobs-picking-up-loot.patch | 51 - ...Implemented-BlockFailedDispenseEvent.patch | 63 - ...7-Added-PlayerLecternPageChangeEvent.patch | 66 - .../0638-Fire-event-on-GS4-query.patch | 204 - ...9-Added-PlayerLoomPatternSelectEvent.patch | 63 - ...onfigurable-door-breaking-difficulty.patch | 101 - ...pty-commands-shall-not-be-dispatched.patch | 18 - ...PI-to-expose-exact-interaction-point.patch | 59 - .../0643-Remove-stale-POIs.patch | 50 - .../0644-Fix-villager-boat-exploit.patch | 34 - ...645-Entity-load-save-limit-per-chunk.patch | 90 - .../0646-Add-sendOpLevel-API.patch | 51 - .../0647-Add-StructureLocateEvent.patch | 41 - ...n-for-requiring-a-player-participant.patch | 81 - ...ileHitEvent-call-when-fireballs-dead.patch | 21 - ...onent-with-empty-text-instead-of-thr.patch | 33 - ...0651-Make-schedule-command-per-world.patch | 37 - ...0652-Configurable-max-leash-distance.patch | 45 - ...0653-Implement-BlockPreDispenseEvent.patch | 42 - .../0654-Added-Vanilla-Entity-Tags.patch | 94 - .../0655-added-Wither-API.patch | 75 - ...ing-of-PlayerChangeBeaconEffectEvent.patch | 39 - ...e-spam-when-removing-chests-in-water.patch | 19 - ...le-for-always-placing-the-dragon-egg.patch | 33 - ...d-PlayerStonecutterRecipeSelectEvent.patch | 109 - ...Leash-variable-to-EntityUnleashEvent.patch | 156 - ...ce-map-update-when-spawning-disabled.patch | 19 - ...-shield-blocking-on-dimension-change.patch | 22 - .../0663-add-DragonEggFormEvent.patch | 66 - .../0664-EntityMoveEvent.patch | 71 - ...disable-pathfinding-updates-on-block.patch | 40 - .../0666-Inline-shift-direction-fields.patch | 55 - ...w-adding-items-to-BlockDropItemEvent.patch | 44 - ...ainThreadExecutor-to-BukkitScheduler.patch | 26 - ...-entity-allow-attribute-registration.patch | 69 - ...fix-dead-slime-setSize-invincibility.patch | 19 - ...ipes-should-return-an-immutable-list.patch | 19 - .../0672-misc-debugging-dumps.patch | 87 - ...pport-for-hex-color-codes-in-console.patch | 221 - .../0674-Clear-SyncLoadInfo.patch | 40 - .../0675-Expose-Tracked-Players.patch | 53 - ...76-Remove-streams-from-SensorNearest.patch | 120 - ...unnecessary-copies-of-passenger-list.patch | 239 - ...Fix-Wither-hostility-towards-players.patch | 33 - ...per-exception-on-empty-JsonList-file.patch | 18 - .../0680-Improve-ServerGUI.patch | 400 -- ...sure-plate-EntityInteractEvent-for-i.patch | 19 - ...0682-fix-converting-txt-to-json-file.patch | 74 - .../0683-Add-worldborder-events.patch | 122 - .../0684-added-PlayerNameEntityEvent.patch | 48 - ...-grindstones-from-overstacking-items.patch | 26 - .../0686-Add-recipe-to-cook-events.patch | 44 - .../0687-Add-Block-isValidTool.patch | 20 - ...-using-signs-inside-spawn-protection.patch | 41 - .../0689-Implement-Keyed-on-World.patch | 110 - ...alternative-constructor-for-Vector3f.patch | 30 - .../0691-Item-Rarity-API.patch | 52 - ...Timer-for-Wandering-Traders-spawned-.patch | 58 - ...opy-TESign-isEditable-from-snapshots.patch | 18 - ...ed-item-when-player-has-disconnected.patch | 35 - ...telist-use-configurable-kick-message.patch | 19 - ...-to-remove-correct-TE-during-TE-tick.patch | 45 - ...ignore-result-of-PlayerEditBookEvent.patch | 19 - ...-block-falling-causing-client-desync.patch | 59 - .../0699-Expose-protocol-version.patch | 22 - ...ent-suggestion-tooltips-in-AsyncTabC.patch | 132 - ...tab-completions-for-brigadier-comman.patch | 316 -- ...ItemConsumeEvent-cancelling-properly.patch | 22 - .../0703-Add-bypass-host-check.patch | 30 - ...don-t-throw-when-loading-invalid-TEs.patch | 33 - .../0705-Set-area-affect-cloud-rotation.patch | 18 - ...-add-isDeeplySleeping-to-HumanEntity.patch | 24 - ...ating-give-items-on-item-drop-cancel.patch | 70 - ...-add-consumeFuel-to-FurnaceBurnEvent.patch | 19 - ...t-set-drop-chance-to-EntityEquipment.patch | 48 - ...fix-PigZombieAngerEvent-cancellation.patch | 47 - ...x-checkReach-check-for-Shulker-boxes.patch | 18 - ...fix-PlayerItemHeldEvent-firing-twice.patch | 30 - .../0713-Added-PlayerDeepSleepEvent.patch | 22 - .../0714-More-World-API.patch | 146 - .../0715-Added-PlayerBedFailEnterEvent.patch | 57 - ...s-to-convert-between-Component-and-B.patch | 55 - ...wn-acting-as-a-bed-respawn-from-the-.patch | 36 - ...d-RespawnFlags-to-PlayerRespawnEvent.patch | 46 - ...eacon-activation-deactivation-events.patch | 37 - ...Add-Channel-initialization-listeners.patch | 119 - ...mmands-if-tab-completion-is-disabled.patch | 24 - .../0722-Add-more-WanderingTrader-API.patch | 65 - ...Add-EntityBlockStorage-clearEntities.patch | 37 - ...essage-to-PlayerAdvancementDoneEvent.patch | 89 - ...-address-to-AsyncPlayerPreLoginEvent.patch | 25 - .../0726-Inventory-close.patch | 25 - ...CreateEvent-players-and-end-platform.patch | 45 - ...n-in-sunlight-API-for-Phantoms-and-S.patch | 126 - .../0729-Fix-CraftPotionBrewer-cache.patch | 44 - .../0730-Add-basic-Datapack-API.patch | 175 - ...nment-variable-to-disable-server-gui.patch | 18 - ...ditions-to-PlayerGameModeChangeEvent.patch | 128 - .../0733-ItemStack-repair-check-API.patch | 91 - .../0734-More-Enchantment-API.patch | 202 - ...-option-to-load-extra-plugin-jars-no.patch | 64 - ...atus-dataconverter-for-pre-1.13-chun.patch | 91 - ...crease-structure-block-data-length-t.patch | 19 - ...x-and-optimise-world-force-upgrading.patch | 411 -- .../0739-Add-Mob-lookAt-API.patch | 127 - .../0740-Add-Unix-domain-socket-support.patch | 141 - .../0741-Add-EntityInsideBlockEvent.patch | 222 - ...742-Attributes-API-for-item-defaults.patch | 42 - ...chantCustom-emit-PlayerPurchaseEvent.patch | 59 - ...cause-to-Weather-ThunderChangeEvents.patch | 118 - .../0745-More-Lidded-Block-API.patch | 127 - .../0746-Add-PlayerKickEvent-causes.patch | 393 -- ...747-Limit-item-frame-cursors-on-maps.patch | 37 - .../0748-Add-PufferFishStateChangeEvent.patch | 50 - ...yerBucketEmptyEvent-result-itemstack.patch | 43 - ...n-to-fix-items-merging-through-walls.patch | 39 - .../0751-Add-BellRevealRaiderEvent.patch | 26 - .../0752-Fix-invulnerable-end-crystals.patch | 88 - ...753-Add-ElderGuardianAppearanceEvent.patch | 23 - ...-inventory-on-cancelled-pickup-event.patch | 62 - .../0755-Fix-dangerous-end-portal-logic.patch | 99 - ...6-Make-item-validations-configurable.patch | 83 - .../0757-Add-more-line-of-sight-methods.patch | 62 - .../0758-add-per-world-spawn-limits.patch | 49 - ...SplashEvent-for-water-splash-potions.patch | 63 - 1837 files changed, 212108 deletions(-) delete mode 100644 Remapped-Spigot-Server-Patches/0001-POM-Changes.patch delete mode 100644 Remapped-Spigot-Server-Patches/0002-Paper-config-files.patch delete mode 100644 Remapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch delete mode 100644 Remapped-Spigot-Server-Patches/0004-MC-Utils.patch delete mode 100644 Remapped-Spigot-Server-Patches/0005-Paper-Metrics.patch delete mode 100644 Remapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch delete mode 100644 Remapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch delete mode 100644 Remapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch delete mode 100644 Remapped-Spigot-Server-Patches/0009-Timings-v2.patch delete mode 100644 Remapped-Spigot-Server-Patches/0010-Adventure.patch delete mode 100644 Remapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch delete mode 100644 Remapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch delete mode 100644 Remapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch delete mode 100644 Remapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch delete mode 100644 Remapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch delete mode 100644 Remapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch delete mode 100644 Remapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch delete mode 100644 Remapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch delete mode 100644 Remapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch delete mode 100644 Remapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch delete mode 100644 Remapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch delete mode 100644 Remapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch delete mode 100644 Remapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch delete mode 100644 Remapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch delete mode 100644 Remapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch delete mode 100644 Remapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch delete mode 100644 Remapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch delete mode 100644 Remapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch delete mode 100644 Remapped-Spigot-Server-Patches/0033-Optimize-explosions.patch delete mode 100644 Remapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch delete mode 100644 Remapped-Spigot-Server-Patches/0035-Disable-thunder.patch delete mode 100644 Remapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch delete mode 100644 Remapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch delete mode 100644 Remapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch delete mode 100644 Remapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch delete mode 100644 Remapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch delete mode 100644 Remapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch delete mode 100644 Remapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch delete mode 100644 Remapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch delete mode 100644 Remapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch delete mode 100644 Remapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch delete mode 100644 Remapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch delete mode 100644 Remapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch delete mode 100644 Remapped-Spigot-Server-Patches/0050-Ensure-inv-drag-is-in-bounds.patch delete mode 100644 Remapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch delete mode 100644 Remapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch delete mode 100644 Remapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch delete mode 100644 Remapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch delete mode 100644 Remapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch delete mode 100644 Remapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch delete mode 100644 Remapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch delete mode 100644 Remapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch delete mode 100644 Remapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch delete mode 100644 Remapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch delete mode 100644 Remapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch delete mode 100644 Remapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch delete mode 100644 Remapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch delete mode 100644 Remapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch delete mode 100644 Remapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch delete mode 100644 Remapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch delete mode 100644 Remapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch delete mode 100644 Remapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch delete mode 100644 Remapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch delete mode 100644 Remapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch delete mode 100644 Remapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch delete mode 100644 Remapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch delete mode 100644 Remapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch delete mode 100644 Remapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch delete mode 100644 Remapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch delete mode 100644 Remapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch delete mode 100644 Remapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch delete mode 100644 Remapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch delete mode 100644 Remapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch delete mode 100644 Remapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch delete mode 100644 Remapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch delete mode 100644 Remapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch delete mode 100644 Remapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch delete mode 100644 Remapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch delete mode 100644 Remapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch delete mode 100644 Remapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch delete mode 100644 Remapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch delete mode 100644 Remapped-Spigot-Server-Patches/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch delete mode 100644 Remapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch delete mode 100644 Remapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch delete mode 100644 Remapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch delete mode 100644 Remapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch delete mode 100644 Remapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch delete mode 100644 Remapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch delete mode 100644 Remapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch delete mode 100644 Remapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch delete mode 100644 Remapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch delete mode 100644 Remapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch delete mode 100644 Remapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch delete mode 100644 Remapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch delete mode 100644 Remapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch delete mode 100644 Remapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch delete mode 100644 Remapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch delete mode 100644 Remapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch delete mode 100644 Remapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch delete mode 100644 Remapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch delete mode 100644 Remapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch delete mode 100644 Remapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch delete mode 100644 Remapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch delete mode 100644 Remapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch delete mode 100644 Remapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch delete mode 100644 Remapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch delete mode 100644 Remapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch delete mode 100644 Remapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch delete mode 100644 Remapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch delete mode 100644 Remapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch delete mode 100644 Remapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch delete mode 100644 Remapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch delete mode 100644 Remapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch delete mode 100644 Remapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0132-Firework-API-s.patch delete mode 100644 Remapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch delete mode 100644 Remapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch delete mode 100644 Remapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch delete mode 100644 Remapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch delete mode 100644 Remapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch delete mode 100644 Remapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch delete mode 100644 Remapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch delete mode 100644 Remapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch delete mode 100644 Remapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch delete mode 100644 Remapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch delete mode 100644 Remapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch delete mode 100644 Remapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch delete mode 100644 Remapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch delete mode 100644 Remapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch delete mode 100644 Remapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch delete mode 100644 Remapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch delete mode 100644 Remapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch delete mode 100644 Remapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch delete mode 100644 Remapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch delete mode 100644 Remapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch delete mode 100644 Remapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch delete mode 100644 Remapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch delete mode 100644 Remapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch delete mode 100644 Remapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch delete mode 100644 Remapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch delete mode 100644 Remapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch delete mode 100644 Remapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch delete mode 100644 Remapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch delete mode 100644 Remapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch delete mode 100644 Remapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch delete mode 100644 Remapped-Spigot-Server-Patches/0172-revert-serverside-behavior-of-keepalives.patch delete mode 100644 Remapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch delete mode 100644 Remapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch delete mode 100644 Remapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch delete mode 100644 Remapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch delete mode 100644 Remapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch delete mode 100644 Remapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch delete mode 100644 Remapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch delete mode 100644 Remapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch delete mode 100644 Remapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch delete mode 100644 Remapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch delete mode 100644 Remapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch delete mode 100644 Remapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch delete mode 100644 Remapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch delete mode 100644 Remapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch delete mode 100644 Remapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch delete mode 100644 Remapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch delete mode 100644 Remapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch delete mode 100644 Remapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch delete mode 100644 Remapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch delete mode 100644 Remapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch delete mode 100644 Remapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch delete mode 100644 Remapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch delete mode 100644 Remapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch delete mode 100644 Remapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch delete mode 100644 Remapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch delete mode 100644 Remapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch delete mode 100644 Remapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch delete mode 100644 Remapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch delete mode 100644 Remapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch delete mode 100644 Remapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch delete mode 100644 Remapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch delete mode 100644 Remapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch delete mode 100644 Remapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0230-RangedEntity-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch delete mode 100644 Remapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch delete mode 100644 Remapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch delete mode 100644 Remapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch delete mode 100644 Remapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch delete mode 100644 Remapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch delete mode 100644 Remapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch delete mode 100644 Remapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch delete mode 100644 Remapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch delete mode 100644 Remapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch delete mode 100644 Remapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch delete mode 100644 Remapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch delete mode 100644 Remapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch delete mode 100644 Remapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch delete mode 100644 Remapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch delete mode 100644 Remapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch delete mode 100644 Remapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch delete mode 100644 Remapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch delete mode 100644 Remapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch delete mode 100644 Remapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch delete mode 100644 Remapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch delete mode 100644 Remapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch delete mode 100644 Remapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch delete mode 100644 Remapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch delete mode 100644 Remapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch delete mode 100644 Remapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch delete mode 100644 Remapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch delete mode 100644 Remapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch delete mode 100644 Remapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch delete mode 100644 Remapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch delete mode 100644 Remapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch delete mode 100644 Remapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch delete mode 100644 Remapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch delete mode 100644 Remapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch delete mode 100644 Remapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch delete mode 100644 Remapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch delete mode 100644 Remapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch delete mode 100644 Remapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch delete mode 100644 Remapped-Spigot-Server-Patches/0279-Improve-death-events.patch delete mode 100644 Remapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch delete mode 100644 Remapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch delete mode 100644 Remapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch delete mode 100644 Remapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch delete mode 100644 Remapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch delete mode 100644 Remapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch delete mode 100644 Remapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch delete mode 100644 Remapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch delete mode 100644 Remapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch delete mode 100644 Remapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0295-Turtle-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch delete mode 100644 Remapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch delete mode 100644 Remapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch delete mode 100644 Remapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch delete mode 100644 Remapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch delete mode 100644 Remapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch delete mode 100644 Remapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch delete mode 100644 Remapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch delete mode 100644 Remapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch delete mode 100644 Remapped-Spigot-Server-Patches/0306-Optimize-World-Time-Updates.patch delete mode 100644 Remapped-Spigot-Server-Patches/0307-Restore-custom-InventoryHolder-support.patch delete mode 100644 Remapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch delete mode 100644 Remapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch delete mode 100644 Remapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch delete mode 100644 Remapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch delete mode 100644 Remapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch delete mode 100644 Remapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch delete mode 100644 Remapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch delete mode 100644 Remapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch delete mode 100644 Remapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch delete mode 100644 Remapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch delete mode 100644 Remapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch delete mode 100644 Remapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch delete mode 100644 Remapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch delete mode 100644 Remapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch delete mode 100644 Remapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch delete mode 100644 Remapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch delete mode 100644 Remapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch delete mode 100644 Remapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch delete mode 100644 Remapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch delete mode 100644 Remapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch delete mode 100644 Remapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch delete mode 100644 Remapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch delete mode 100644 Remapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch delete mode 100644 Remapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch delete mode 100644 Remapped-Spigot-Server-Patches/0341-PlayerDeathEvent-getItemsToKeep.patch delete mode 100644 Remapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch delete mode 100644 Remapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch delete mode 100644 Remapped-Spigot-Server-Patches/0345-Per-Player-View-Distance-API-placeholders.patch delete mode 100644 Remapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch delete mode 100644 Remapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch delete mode 100644 Remapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch delete mode 100644 Remapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch delete mode 100644 Remapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch delete mode 100644 Remapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch delete mode 100644 Remapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch delete mode 100644 Remapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch delete mode 100644 Remapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch delete mode 100644 Remapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch delete mode 100644 Remapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch delete mode 100644 Remapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch delete mode 100644 Remapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch delete mode 100644 Remapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch delete mode 100644 Remapped-Spigot-Server-Patches/0362-Anti-Xray.patch delete mode 100644 Remapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch delete mode 100644 Remapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch delete mode 100644 Remapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch delete mode 100644 Remapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch delete mode 100644 Remapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch delete mode 100644 Remapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch delete mode 100644 Remapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch delete mode 100644 Remapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch delete mode 100644 Remapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch delete mode 100644 Remapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch delete mode 100644 Remapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch delete mode 100644 Remapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch delete mode 100644 Remapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch delete mode 100644 Remapped-Spigot-Server-Patches/0376-Generator-Settings.patch delete mode 100644 Remapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch delete mode 100644 Remapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch delete mode 100644 Remapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch delete mode 100644 Remapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch delete mode 100644 Remapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch delete mode 100644 Remapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch delete mode 100644 Remapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch delete mode 100644 Remapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch delete mode 100644 Remapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch delete mode 100644 Remapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch delete mode 100644 Remapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch delete mode 100644 Remapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch delete mode 100644 Remapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch delete mode 100644 Remapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch delete mode 100644 Remapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch delete mode 100644 Remapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch delete mode 100644 Remapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch delete mode 100644 Remapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch delete mode 100644 Remapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch delete mode 100644 Remapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch delete mode 100644 Remapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch delete mode 100644 Remapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch delete mode 100644 Remapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch delete mode 100644 Remapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch delete mode 100644 Remapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch delete mode 100644 Remapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch delete mode 100644 Remapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch delete mode 100644 Remapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch delete mode 100644 Remapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch delete mode 100644 Remapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch delete mode 100644 Remapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch delete mode 100644 Remapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch delete mode 100644 Remapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch delete mode 100644 Remapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch delete mode 100644 Remapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch delete mode 100644 Remapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch delete mode 100644 Remapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch delete mode 100644 Remapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch delete mode 100644 Remapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch delete mode 100644 Remapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch delete mode 100644 Remapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch delete mode 100644 Remapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch delete mode 100644 Remapped-Spigot-Server-Patches/0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch delete mode 100644 Remapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch delete mode 100644 Remapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch delete mode 100644 Remapped-Spigot-Server-Patches/0431-Expose-MinecraftServer-isRunning.patch delete mode 100644 Remapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch delete mode 100644 Remapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch delete mode 100644 Remapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch delete mode 100644 Remapped-Spigot-Server-Patches/0435-Async-command-map-building.patch delete mode 100644 Remapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch delete mode 100644 Remapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch delete mode 100644 Remapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch delete mode 100644 Remapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch delete mode 100644 Remapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch delete mode 100644 Remapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch delete mode 100644 Remapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch delete mode 100644 Remapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch delete mode 100644 Remapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch delete mode 100644 Remapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch delete mode 100644 Remapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch delete mode 100644 Remapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch delete mode 100644 Remapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch delete mode 100644 Remapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch delete mode 100644 Remapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch delete mode 100644 Remapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch delete mode 100644 Remapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch delete mode 100644 Remapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch delete mode 100644 Remapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch delete mode 100644 Remapped-Spigot-Server-Patches/0461-Expose-game-version.patch delete mode 100644 Remapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch delete mode 100644 Remapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch delete mode 100644 Remapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch delete mode 100644 Remapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch delete mode 100644 Remapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch delete mode 100644 Remapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch delete mode 100644 Remapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch delete mode 100644 Remapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch delete mode 100644 Remapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch delete mode 100644 Remapped-Spigot-Server-Patches/0473-Potential-bed-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch delete mode 100644 Remapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch delete mode 100644 Remapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch delete mode 100644 Remapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch delete mode 100644 Remapped-Spigot-Server-Patches/0478-Reduce-MutableInt-allocations-from-light-engine.patch delete mode 100644 Remapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch delete mode 100644 Remapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch delete mode 100644 Remapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch delete mode 100644 Remapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch delete mode 100644 Remapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch delete mode 100644 Remapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch delete mode 100644 Remapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch delete mode 100644 Remapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch delete mode 100644 Remapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch delete mode 100644 Remapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch delete mode 100644 Remapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch delete mode 100644 Remapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch delete mode 100644 Remapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch delete mode 100644 Remapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch delete mode 100644 Remapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch delete mode 100644 Remapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch delete mode 100644 Remapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch delete mode 100644 Remapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch delete mode 100644 Remapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch delete mode 100644 Remapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch delete mode 100644 Remapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch delete mode 100644 Remapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch delete mode 100644 Remapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch delete mode 100644 Remapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch delete mode 100644 Remapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch delete mode 100644 Remapped-Spigot-Server-Patches/0509-Paper-dumpitem-command.patch delete mode 100644 Remapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch delete mode 100644 Remapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch delete mode 100644 Remapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch delete mode 100644 Remapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch delete mode 100644 Remapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch delete mode 100644 Remapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch delete mode 100644 Remapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch delete mode 100644 Remapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch delete mode 100644 Remapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch delete mode 100644 Remapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch delete mode 100644 Remapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch delete mode 100644 Remapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch delete mode 100644 Remapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch delete mode 100644 Remapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch delete mode 100644 Remapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch delete mode 100644 Remapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch delete mode 100644 Remapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch delete mode 100644 Remapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch delete mode 100644 Remapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch delete mode 100644 Remapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch delete mode 100644 Remapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch delete mode 100644 Remapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch delete mode 100644 Remapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch delete mode 100644 Remapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch delete mode 100644 Remapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch delete mode 100644 Remapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch delete mode 100644 Remapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch delete mode 100644 Remapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch delete mode 100644 Remapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch delete mode 100644 Remapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch delete mode 100644 Remapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch delete mode 100644 Remapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch delete mode 100644 Remapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch delete mode 100644 Remapped-Spigot-Server-Patches/0545-Brand-support.patch delete mode 100644 Remapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch delete mode 100644 Remapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch delete mode 100644 Remapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch delete mode 100644 Remapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch delete mode 100644 Remapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch delete mode 100644 Remapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch delete mode 100644 Remapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch delete mode 100644 Remapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch delete mode 100644 Remapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch delete mode 100644 Remapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch delete mode 100644 Remapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch delete mode 100644 Remapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch delete mode 100644 Remapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch delete mode 100644 Remapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch delete mode 100644 Remapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch delete mode 100644 Remapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch delete mode 100644 Remapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch delete mode 100644 Remapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch delete mode 100644 Remapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch delete mode 100644 Remapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch delete mode 100644 Remapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch delete mode 100644 Remapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch delete mode 100644 Remapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch delete mode 100644 Remapped-Spigot-Server-Patches/0573-Entity-isTicking.patch delete mode 100644 Remapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch delete mode 100644 Remapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch delete mode 100644 Remapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch delete mode 100644 Remapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch delete mode 100644 Remapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch delete mode 100644 Remapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch delete mode 100644 Remapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch delete mode 100644 Remapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch delete mode 100644 Remapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch delete mode 100644 Remapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch delete mode 100644 Remapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch delete mode 100644 Remapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch delete mode 100644 Remapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch delete mode 100644 Remapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch delete mode 100644 Remapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch delete mode 100644 Remapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch delete mode 100644 Remapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch delete mode 100644 Remapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch delete mode 100644 Remapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch delete mode 100644 Remapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch delete mode 100644 Remapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch delete mode 100644 Remapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch delete mode 100644 Remapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch delete mode 100644 Remapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0604-More-lightning-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch delete mode 100644 Remapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch delete mode 100644 Remapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch delete mode 100644 Remapped-Spigot-Server-Patches/0609-Set-spigots-verbose-world-setting-to-false-by-def.patch delete mode 100644 Remapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch delete mode 100644 Remapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch delete mode 100644 Remapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch delete mode 100644 Remapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch delete mode 100644 Remapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch delete mode 100644 Remapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch delete mode 100644 Remapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch delete mode 100644 Remapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch delete mode 100644 Remapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch delete mode 100644 Remapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch delete mode 100644 Remapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch delete mode 100644 Remapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch delete mode 100644 Remapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch delete mode 100644 Remapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch delete mode 100644 Remapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch delete mode 100644 Remapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch delete mode 100644 Remapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch delete mode 100644 Remapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch delete mode 100644 Remapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch delete mode 100644 Remapped-Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch delete mode 100644 Remapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch delete mode 100644 Remapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch delete mode 100644 Remapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch delete mode 100644 Remapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch delete mode 100644 Remapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch delete mode 100644 Remapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch delete mode 100644 Remapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch delete mode 100644 Remapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch delete mode 100644 Remapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch delete mode 100644 Remapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch delete mode 100644 Remapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch delete mode 100644 Remapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch delete mode 100644 Remapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch delete mode 100644 Remapped-Spigot-Server-Patches/0655-added-Wither-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch delete mode 100644 Remapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch delete mode 100644 Remapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch delete mode 100644 Remapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch delete mode 100644 Remapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0664-EntityMoveEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch delete mode 100644 Remapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch delete mode 100644 Remapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch delete mode 100644 Remapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch delete mode 100644 Remapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch delete mode 100644 Remapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch delete mode 100644 Remapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch delete mode 100644 Remapped-Spigot-Server-Patches/0673-Add-support-for-hex-color-codes-in-console.patch delete mode 100644 Remapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch delete mode 100644 Remapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch delete mode 100644 Remapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch delete mode 100644 Remapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch delete mode 100644 Remapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch delete mode 100644 Remapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch delete mode 100644 Remapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch delete mode 100644 Remapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch delete mode 100644 Remapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch delete mode 100644 Remapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch delete mode 100644 Remapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch delete mode 100644 Remapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch delete mode 100644 Remapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch delete mode 100644 Remapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch delete mode 100644 Remapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch delete mode 100644 Remapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch delete mode 100644 Remapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch delete mode 100644 Remapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch delete mode 100644 Remapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch delete mode 100644 Remapped-Spigot-Server-Patches/0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch delete mode 100644 Remapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch delete mode 100644 Remapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch delete mode 100644 Remapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch delete mode 100644 Remapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch delete mode 100644 Remapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch delete mode 100644 Remapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch delete mode 100644 Remapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch delete mode 100644 Remapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch delete mode 100644 Remapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch delete mode 100644 Remapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch delete mode 100644 Remapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch delete mode 100644 Remapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch delete mode 100644 Remapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch delete mode 100644 Remapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch delete mode 100644 Remapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0714-More-World-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch delete mode 100644 Remapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch delete mode 100644 Remapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch delete mode 100644 Remapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch delete mode 100644 Remapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch delete mode 100644 Remapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch delete mode 100644 Remapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0726-Inventory-close.patch delete mode 100644 Remapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch delete mode 100644 Remapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch delete mode 100644 Remapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch delete mode 100644 Remapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch delete mode 100644 Remapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch delete mode 100644 Remapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch delete mode 100644 Remapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch delete mode 100644 Remapped-Spigot-Server-Patches/0738-Fix-and-optimise-world-force-upgrading.patch delete mode 100644 Remapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch delete mode 100644 Remapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch delete mode 100644 Remapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch delete mode 100644 Remapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch delete mode 100644 Remapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch delete mode 100644 Remapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch delete mode 100644 Remapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch delete mode 100644 Remapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch delete mode 100644 Remapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch delete mode 100644 Remapped-Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch delete mode 100644 Remapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch delete mode 100644 Remapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch delete mode 100644 Remapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch delete mode 100644 Remapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch delete mode 100644 Remapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch delete mode 100644 Remapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch delete mode 100644 Spigot-API-Patches/0001-Convert-project-to-Gradle.patch delete mode 100644 Spigot-Server-Patches/0001-Setup-Gradle-project.patch delete mode 100644 Spigot-Server-Patches/0002-Decompile-fixes.patch delete mode 100644 Unmapped-Spigot-API-Patches/0001-POM-changes.patch delete mode 100644 Unmapped-Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch delete mode 100644 Unmapped-Spigot-API-Patches/0003-Paper-Utils.patch delete mode 100644 Unmapped-Spigot-API-Patches/0004-Timings-v2.patch delete mode 100644 Unmapped-Spigot-API-Patches/0005-Adventure.patch delete mode 100644 Unmapped-Spigot-API-Patches/0006-Player-affects-spawning-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0007-Add-getTPS-method.patch delete mode 100644 Unmapped-Spigot-API-Patches/0008-Entity-Origin-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0009-Version-Command-2.0.patch delete mode 100644 Unmapped-Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0011-Add-player-view-distance-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch delete mode 100644 Unmapped-Spigot-API-Patches/0015-Expose-server-CommandMap.patch delete mode 100644 Unmapped-Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch delete mode 100644 Unmapped-Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch delete mode 100644 Unmapped-Spigot-API-Patches/0018-Add-exception-reporting-event.patch delete mode 100644 Unmapped-Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch delete mode 100644 Unmapped-Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch delete mode 100644 Unmapped-Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch delete mode 100644 Unmapped-Spigot-API-Patches/0022-Complete-resource-pack-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch delete mode 100644 Unmapped-Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch delete mode 100644 Unmapped-Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch delete mode 100644 Unmapped-Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch delete mode 100644 Unmapped-Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch delete mode 100644 Unmapped-Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0029-EntityPathfindEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch delete mode 100644 Unmapped-Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch delete mode 100644 Unmapped-Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch delete mode 100644 Unmapped-Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0035-EntityRegainHealthEvent-isFastRegen-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0036-LootTable-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0037-Add-EntityZapEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0038-Misc-Utils.patch delete mode 100644 Unmapped-Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch delete mode 100644 Unmapped-Spigot-API-Patches/0040-Add-source-to-PlayerExpChangeEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch delete mode 100644 Unmapped-Spigot-API-Patches/0044-IllegalPacketEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0045-Fireworks-API-s.patch delete mode 100644 Unmapped-Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch delete mode 100644 Unmapped-Spigot-API-Patches/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch delete mode 100644 Unmapped-Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch delete mode 100644 Unmapped-Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch delete mode 100644 Unmapped-Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch delete mode 100644 Unmapped-Spigot-API-Patches/0052-Item-canEntityPickup.patch delete mode 100644 Unmapped-Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch delete mode 100644 Unmapped-Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0058-Profile-Lookup-Events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0059-Entity-fromMobSpawner.patch delete mode 100644 Unmapped-Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch delete mode 100644 Unmapped-Spigot-API-Patches/0061-ensureServerConversions-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch delete mode 100644 Unmapped-Spigot-API-Patches/0065-LivingEntity-setKiller.patch delete mode 100644 Unmapped-Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch delete mode 100644 Unmapped-Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch delete mode 100644 Unmapped-Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch delete mode 100644 Unmapped-Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch delete mode 100644 Unmapped-Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch delete mode 100644 Unmapped-Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch delete mode 100644 Unmapped-Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch delete mode 100644 Unmapped-Spigot-API-Patches/0084-Optimize-Hoppers.patch delete mode 100644 Unmapped-Spigot-API-Patches/0085-Tameable-getOwnerUniqueId-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch delete mode 100644 Unmapped-Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0089-getPlayerUniqueId-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch delete mode 100644 Unmapped-Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch delete mode 100644 Unmapped-Spigot-API-Patches/0093-EndermanEscapeEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0094-Enderman.teleportRandomly.patch delete mode 100644 Unmapped-Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch delete mode 100644 Unmapped-Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch delete mode 100644 Unmapped-Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch delete mode 100644 Unmapped-Spigot-API-Patches/0100-WitchConsumePotionEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0101-WitchThrowPotionEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0102-Location.toBlockLocation-toCenterLocation.patch delete mode 100644 Unmapped-Spigot-API-Patches/0103-PotionEffect-clone-methods.patch delete mode 100644 Unmapped-Spigot-API-Patches/0104-WitchReadyPotionEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch delete mode 100644 Unmapped-Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0107-Make-shield-blocking-delay-configurable.patch delete mode 100644 Unmapped-Spigot-API-Patches/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch delete mode 100644 Unmapped-Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch delete mode 100644 Unmapped-Spigot-API-Patches/0110-PlayerReadyArrowEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0112-Expand-Explosions-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0113-ItemStack-API-additions-for-quantity-flags-lore.patch delete mode 100644 Unmapped-Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0115-RangedEntity-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0116-Add-World.getEntity-UUID-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0117-InventoryCloseEvent-Reason-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0118-Entity-getChunk-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch delete mode 100644 Unmapped-Spigot-API-Patches/0120-EnderDragon-Events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0123-EntityTransformedEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch delete mode 100644 Unmapped-Spigot-API-Patches/0125-SkeletonHorse-Additions.patch delete mode 100644 Unmapped-Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0127-Expand-ArmorStand-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0128-AnvilDamageEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0133-Async-Chunks-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch delete mode 100644 Unmapped-Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch delete mode 100644 Unmapped-Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch delete mode 100644 Unmapped-Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch delete mode 100644 Unmapped-Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0139-isChunkGenerated-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0140-Add-More-Creeper-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch delete mode 100644 Unmapped-Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch delete mode 100644 Unmapped-Spigot-API-Patches/0145-Improve-death-events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0146-Mob-Pathfinding-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch delete mode 100644 Unmapped-Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch delete mode 100644 Unmapped-Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch delete mode 100644 Unmapped-Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0153-Material-API-additions.patch delete mode 100644 Unmapped-Spigot-API-Patches/0154-Add-Material-Tags.patch delete mode 100644 Unmapped-Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch delete mode 100644 Unmapped-Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch delete mode 100644 Unmapped-Spigot-API-Patches/0157-Add-sun-related-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0158-Here-s-Johnny.patch delete mode 100644 Unmapped-Spigot-API-Patches/0159-Turtle-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0160-Add-spectator-target-events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0161-Add-more-Witch-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch delete mode 100644 Unmapped-Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch delete mode 100644 Unmapped-Spigot-API-Patches/0164-Add-more-Zombie-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch delete mode 100644 Unmapped-Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch delete mode 100644 Unmapped-Spigot-API-Patches/0168-BlockDestroyEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch delete mode 100644 Unmapped-Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0171-Annotation-Test-changes.patch delete mode 100644 Unmapped-Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch delete mode 100644 Unmapped-Spigot-API-Patches/0173-Add-GS4-Query-event.patch delete mode 100644 Unmapped-Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch delete mode 100644 Unmapped-Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch delete mode 100644 Unmapped-Spigot-API-Patches/0177-Server-Tick-Events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch delete mode 100644 Unmapped-Spigot-API-Patches/0179-Add-Heightmap-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch delete mode 100644 Unmapped-Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch delete mode 100644 Unmapped-Spigot-API-Patches/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch delete mode 100644 Unmapped-Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch delete mode 100644 Unmapped-Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch delete mode 100644 Unmapped-Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch delete mode 100644 Unmapped-Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch delete mode 100644 Unmapped-Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0188-Entity-Jump-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0190-Add-tick-times-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch delete mode 100644 Unmapped-Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch delete mode 100644 Unmapped-Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch delete mode 100644 Unmapped-Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch delete mode 100644 Unmapped-Spigot-API-Patches/0197-Villager-Restocks-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0198-Expose-game-version.patch delete mode 100644 Unmapped-Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch delete mode 100644 Unmapped-Spigot-API-Patches/0200-Add-Mob-Goal-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0201-World-view-distance-api.patch delete mode 100644 Unmapped-Spigot-API-Patches/0202-Add-villager-reputation-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0203-Spawn-Reason-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0204-Potential-bed-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch delete mode 100644 Unmapped-Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch delete mode 100644 Unmapped-Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch delete mode 100644 Unmapped-Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch delete mode 100644 Unmapped-Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch delete mode 100644 Unmapped-Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch delete mode 100644 Unmapped-Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch delete mode 100644 Unmapped-Spigot-API-Patches/0213-Add-entity-liquid-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch delete mode 100644 Unmapped-Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch delete mode 100644 Unmapped-Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0218-Add-moon-phase-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch delete mode 100644 Unmapped-Spigot-API-Patches/0220-Add-BellRingEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0221-Brand-support.patch delete mode 100644 Unmapped-Spigot-API-Patches/0222-Add-more-Evoker-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch delete mode 100644 Unmapped-Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch delete mode 100644 Unmapped-Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch delete mode 100644 Unmapped-Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch delete mode 100644 Unmapped-Spigot-API-Patches/0227-Entity-isTicking.patch delete mode 100644 Unmapped-Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch delete mode 100644 Unmapped-Spigot-API-Patches/0229-Villager-resetOffers.patch delete mode 100644 Unmapped-Spigot-API-Patches/0230-Player-elytra-boost-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch delete mode 100644 Unmapped-Spigot-API-Patches/0232-Add-ignore-discounts-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch delete mode 100644 Unmapped-Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch delete mode 100644 Unmapped-Spigot-API-Patches/0235-Add-API-for-quit-reason.patch delete mode 100644 Unmapped-Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch delete mode 100644 Unmapped-Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0239-More-lightning-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch delete mode 100644 Unmapped-Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch delete mode 100644 Unmapped-Spigot-API-Patches/0244-Added-PlayerTradeEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch delete mode 100644 Unmapped-Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch delete mode 100644 Unmapped-Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch delete mode 100644 Unmapped-Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch delete mode 100644 Unmapped-Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch delete mode 100644 Unmapped-Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch delete mode 100644 Unmapped-Spigot-API-Patches/0259-Add-sendOpLevel-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0260-Add-StructureLocateEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch delete mode 100644 Unmapped-Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch delete mode 100644 Unmapped-Spigot-API-Patches/0264-added-Wither-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0268-EntityMoveEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0269-add-DragonEggFormEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch delete mode 100644 Unmapped-Spigot-API-Patches/0272-living-entity-allow-attribute-registration.patch delete mode 100644 Unmapped-Spigot-API-Patches/0273-Add-missing-effects.patch delete mode 100644 Unmapped-Spigot-API-Patches/0274-Expose-Tracked-Players.patch delete mode 100644 Unmapped-Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch delete mode 100644 Unmapped-Spigot-API-Patches/0276-Add-worldborder-events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0279-Add-Block-isValidTool.patch delete mode 100644 Unmapped-Spigot-API-Patches/0280-Implement-Keyed-on-World.patch delete mode 100644 Unmapped-Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch delete mode 100644 Unmapped-Spigot-API-Patches/0282-Item-Rarity-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0283-Expose-protocol-version.patch delete mode 100644 Unmapped-Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch delete mode 100644 Unmapped-Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch delete mode 100644 Unmapped-Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0288-More-World-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch delete mode 100644 Unmapped-Spigot-API-Patches/0291-PlayerMoveEvent-Improvements.patch delete mode 100644 Unmapped-Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0293-Add-more-WanderingTrader-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch delete mode 100644 Unmapped-Spigot-API-Patches/0295-Add-EntityBlockStorage-clearEntities.patch delete mode 100644 Unmapped-Spigot-API-Patches/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0298-Inventory-close.patch delete mode 100644 Unmapped-Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch delete mode 100644 Unmapped-Spigot-API-Patches/0300-Add-basic-Datapack-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0301-additions-to-PlayerGameModeChangeEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0302-ItemStack-repair-check-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0303-More-Enchantment-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch delete mode 100644 Unmapped-Spigot-API-Patches/0305-List-all-missing-hard-depends-not-just-first.patch delete mode 100644 Unmapped-Spigot-API-Patches/0306-Add-Mob-lookAt-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0307-ItemStack-editMeta.patch delete mode 100644 Unmapped-Spigot-API-Patches/0308-Add-EntityInsideBlockEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch delete mode 100644 Unmapped-Spigot-API-Patches/0310-Add-cause-to-Weather-ThunderChangeEvents.patch delete mode 100644 Unmapped-Spigot-API-Patches/0311-More-Lidded-Block-API.patch delete mode 100644 Unmapped-Spigot-API-Patches/0312-Add-PlayerKickEvent-causes.patch delete mode 100644 Unmapped-Spigot-API-Patches/0313-Add-PufferFishStateChangeEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0314-Add-BellRevealRaiderEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0315-Add-ElderGuardianAppearanceEvent.patch delete mode 100644 Unmapped-Spigot-API-Patches/0316-Add-more-line-of-sight-methods.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0001-POM-Changes.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0002-Paper-config-files.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0004-MC-Utils.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0005-Paper-Metrics.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0009-Timings-v2.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0010-Adventure.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0033-Optimize-explosions.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0035-Disable-thunder.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0050-Ensure-inv-drag-is-in-bounds.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0095-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0132-Firework-API-s.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0172-revert-serverside-behavior-of-keepalives.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0230-RangedEntity-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0279-Improve-death-events.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0295-Turtle-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0306-Optimize-World-Time-Updates.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0307-Restore-custom-InventoryHolder-support.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0341-PlayerDeathEvent-getItemsToKeep.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0345-Per-Player-View-Distance-API-placeholders.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0349-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0362-Anti-Xray.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0376-Generator-Settings.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0428-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0431-Expose-MinecraftServer-isRunning.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0435-Async-command-map-building.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0461-Expose-game-version.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0473-Potential-bed-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0478-Reduce-MutableInt-allocations-from-light-engine.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0509-Paper-dumpitem-command.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0545-Brand-support.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0573-Entity-isTicking.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0578-Reset-Ender-Crystals-on-Dragon-Spawn.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0604-More-lightning-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0609-Set-spigots-verbose-world-setting-to-false-by-def.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0655-added-Wither-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0664-EntityMoveEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0673-Add-support-for-hex-color-codes-in-console.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0696-Make-sure-to-remove-correct-TE-during-TE-tick.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0714-More-World-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0726-Inventory-close.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0738-Fix-and-optimise-world-force-upgrading.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch delete mode 100644 Unmapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch diff --git a/Remapped-Spigot-Server-Patches/0001-POM-Changes.patch b/Remapped-Spigot-Server-Patches/0001-POM-Changes.patch deleted file mode 100644 index 8d0da0d549..0000000000 --- a/Remapped-Spigot-Server-Patches/0001-POM-Changes.patch +++ /dev/null @@ -1,291 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 29 Feb 2016 20:40:33 -0600 -Subject: [PATCH] POM Changes - - -diff --git a/pom.xml b/pom.xml -index 3fc047371e8f8a626e69697fad549d689c5dce89..a5d87d22cb1588d15e08da3b37e51c5e261c7799 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -1,15 +1,14 @@ - - 4.0.0 -- org.spigotmc -- spigot -+ paper - jar - 1.16.5-R0.1-SNAPSHOT -- Spigot -- https://www.spigotmc.org/ -+ Paper -+ https://papermc.io - - -- true -+ - UTF-8 - unknown - git -@@ -20,21 +19,39 @@ - - - -- org.spigotmc -- spigot-parent -+ com.destroystokyo.paper -+ paper-parent - dev-SNAPSHOT - ../pom.xml - - -+ -+ -+ -+ org.apache.logging.log4j -+ log4j-bom -+ 2.11.2 -+ pom -+ import -+ -+ -+ -+ - - -- org.spigotmc -- spigot-api -+ com.destroystokyo.paper -+ paper-api -+ ${project.version} -+ compile -+ -+ -+ com.destroystokyo.paper -+ paper-mojangapi - ${project.version} - compile - - -- org.spigotmc -+ io.papermc - minecraft-server - ${minecraft.version}-SNAPSHOT - compile -@@ -45,18 +62,15 @@ - 2.12.1 - compile - -+ -+ org.apache.logging.log4j -+ log4j-api -+ compile -+ - - org.apache.logging.log4j - log4j-iostreams -- 2.8.1 - compile -- -- -- -- org.apache.logging.log4j -- log4j-api -- -- - - - org.ow2.asm -@@ -64,12 +78,23 @@ - 9.1 - compile - -+ -+ -+ co.aikar -+ cleaner -+ 1.0-SNAPSHOT -+ -+ -+ io.netty -+ netty-all -+ 4.1.50.Final -+ - - - com.googlecode.json-simple - json-simple - 1.1.1 -- runtime -+ compile - - - org.xerial -@@ -80,7 +105,7 @@ - - mysql - mysql-connector-java -- 5.1.49 -+ 8.0.23 - runtime - - -@@ -105,7 +130,7 @@ - - org.apache.logging.log4j - log4j-slf4j-impl -- 2.8.1 -+ - runtime - - -@@ -132,34 +157,22 @@ - - - -+ paper-${minecraft.version} -+ clean install - - -- net.md-5 -- scriptus -- 0.4.1 -+ com.lukegb.mojo -+ gitdescribe-maven-plugin -+ 1.3 -+ -+ git-Paper- -+ .. -+ - - -- ex-spigot -- -- ${bt.name}-Spigot-%s -- ../ -- spigot.desc -- -- initialize -- -- describe -- -- -- -- ex-craftbukkit -- -- -%s -- ../../CraftBukkit -- craftbukkit.desc -- -- initialize -+ compile - -- describe -+ gitdescribe - - - -@@ -169,6 +182,7 @@ - maven-jar-plugin - 3.2.0 - -+ true - - - false -@@ -176,11 +190,13 @@ - - org.bukkit.craftbukkit.Main - CraftBukkit -- ${spigot.desc}${craftbukkit.desc} -- ${project.build.outputTimestamp} -+ -+ ${describe} -+ ${maven.build.timestamp} - Bukkit - ${api.version} - Bukkit Team -+ true - - - -@@ -216,14 +232,24 @@ - shade - - -+ ${project.build.directory}/dependency-reduced-pom.xml - ${shadeSourcesJar} - - -- org.spigotmc:minecraft-server -+ io.papermc:minecraft-server - - com/google/common/** - com/google/gson/** - com/google/thirdparty/** -+ -+ io/netty/** -+ META-INF/native/libnetty* -+ com/mojang/brigadier/** -+ META-INF/MANIFEST.MF -+ com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.class -+ com/mojang/datafixers/util/Either* -+ org/apache/logging/log4j/** -+ META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat - - - -@@ -245,10 +271,11 @@ - jline - org.bukkit.craftbukkit.libs.jline - -- -- it.unimi -- org.bukkit.craftbukkit.libs.it.unimi -- -+ -+ -+ -+ -+ - - org.apache.commons.codec - org.bukkit.craftbukkit.libs.org.apache.commons.codec -@@ -316,10 +343,6 @@ - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 -- -- -- eclipse -- - - - org.codehaus.plexus -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 4452427d0a8298d119ca29ef397b7a94f19eec28..46a16e31775b28c44f95a8ac5545ebcb656c74b6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -186,7 +186,7 @@ public class Main { - } - - if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { -- Date buildDate = new Date(Integer.parseInt(Main.class.getPackage().getImplementationVendor()) * 1000L); -+ Date buildDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(Main.class.getPackage().getImplementationVendor()); // Paper - - Calendar deadline = Calendar.getInstance(); - deadline.add(Calendar.DAY_OF_YEAR, -28); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 93046379d0cefd5d3236fc59e698809acdc18f80..674096cab190d62622f9947853b056f57d43a2a5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -@@ -11,7 +11,7 @@ public final class Versioning { - public static String getBukkitVersion() { - String result = "Unknown-Version"; - -- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties"); -+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.destroystokyo.paper/paper-api/pom.properties"); - Properties properties = new Properties(); - - if (stream != null) { diff --git a/Remapped-Spigot-Server-Patches/0002-Paper-config-files.patch b/Remapped-Spigot-Server-Patches/0002-Paper-config-files.patch deleted file mode 100644 index 363f09b241..0000000000 --- a/Remapped-Spigot-Server-Patches/0002-Paper-config-files.patch +++ /dev/null @@ -1,820 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 29 Feb 2016 21:02:09 -0600 -Subject: [PATCH] Paper config files - -Loads each yml file for early init too so it can be used for early options - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d05eeaa711a09bb121b530654821894e795ff4ea ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +1,286 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Functions; -+import com.google.common.base.Joiner; -+import com.google.common.collect.ImmutableSet; -+import com.google.common.collect.Iterables; -+import com.google.common.collect.Lists; -+import com.google.common.collect.Maps; -+import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ServerChunkCache; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.level.ChunkPos; -+import org.apache.commons.lang3.tuple.MutablePair; -+import org.apache.commons.lang3.tuple.Pair; -+import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; -+import org.bukkit.Location; -+import org.bukkit.World; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+import org.bukkit.craftbukkit.CraftServer; -+import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.entity.Player; -+ -+import java.io.File; -+import java.time.LocalDateTime; -+import java.time.format.DateTimeFormatter; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collection; -+import java.util.Collections; -+import java.util.Iterator; -+import java.util.List; -+import java.util.Locale; -+import java.util.Map; -+import java.util.Set; -+import java.util.stream.Collectors; -+ -+public class PaperCommand extends Command { -+ private static final String BASE_PERM = "bukkit.command.paper."; -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); -+ -+ public PaperCommand(String name) { -+ super(name); -+ this.description = "Paper related commands"; -+ this.usageMessage = "/paper [" + Joiner.on(" | ").join(SUBCOMMANDS) + "]"; -+ this.setPermission("bukkit.command.paper;" + Joiner.on(';').join(SUBCOMMANDS.stream().map(s -> BASE_PERM + s).collect(Collectors.toSet()))); -+ } -+ -+ private static boolean testPermission(CommandSender commandSender, String permission) { -+ if (commandSender.hasPermission(BASE_PERM + permission) || commandSender.hasPermission("bukkit.command.paper")) return true; -+ commandSender.sendMessage(Bukkit.getPermissionMessage()); -+ return false; -+ } -+ -+ @Override -+ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { -+ if (args.length <= 1) -+ return getListMatchingLast(sender, args, SUBCOMMANDS); -+ -+ switch (args[0].toLowerCase(Locale.ENGLISH)) -+ { -+ case "entity": -+ if (args.length == 2) -+ return getListMatchingLast(sender, args, "help", "list"); -+ if (args.length == 3) -+ return getListMatchingLast(sender, args, EntityType.getEntityNameList().stream().map(ResourceLocation::toString).sorted().toArray(String[]::new)); -+ break; -+ } -+ return Collections.emptyList(); -+ } -+ -+ // Code from Mojang - copyright them -+ public static List getListMatchingLast(CommandSender sender, String[] args, String... matches) { -+ return getListMatchingLast(sender, args, (Collection) Arrays.asList(matches)); -+ } -+ -+ public static boolean matches(String s, String s1) { -+ return s1.regionMatches(true, 0, s, 0, s.length()); -+ } -+ -+ public static List getListMatchingLast(CommandSender sender, String[] strings, Collection collection) { -+ String last = strings[strings.length - 1]; -+ ArrayList results = Lists.newArrayList(); -+ -+ if (!collection.isEmpty()) { -+ Iterator iterator = Iterables.transform(collection, Functions.toStringFunction()).iterator(); -+ -+ while (iterator.hasNext()) { -+ String s1 = (String) iterator.next(); -+ -+ if (matches(last, s1) && (sender.hasPermission(BASE_PERM + s1) || sender.hasPermission("bukkit.command.paper"))) { -+ results.add(s1); -+ } -+ } -+ -+ if (results.isEmpty()) { -+ iterator = collection.iterator(); -+ -+ while (iterator.hasNext()) { -+ Object object = iterator.next(); -+ -+ if (object instanceof ResourceLocation && matches(last, ((ResourceLocation) object).getPath())) { -+ results.add(String.valueOf(object)); -+ } -+ } -+ } -+ } -+ -+ return results; -+ } -+ // end copy stuff -+ -+ @Override -+ public boolean execute(CommandSender sender, String commandLabel, String[] args) { -+ if (!testPermission(sender)) return true; -+ -+ if (args.length == 0) { -+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -+ return false; -+ } -+ if (SUBCOMMANDS.contains(args[0].toLowerCase(Locale.ENGLISH))) { -+ if (!testPermission(sender, args[0].toLowerCase(Locale.ENGLISH))) return true; -+ } -+ switch (args[0].toLowerCase(Locale.ENGLISH)) { -+ case "heap": -+ dumpHeap(sender); -+ break; -+ case "entity": -+ listEntities(sender, args); -+ break; -+ case "reload": -+ doReload(sender); -+ break; -+ case "ver": -+ if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) -+ case "version": -+ Command ver = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version"); -+ if (ver != null) { -+ ver.execute(sender, commandLabel, new String[0]); -+ break; -+ } -+ // else - fall through to default -+ default: -+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -+ return false; -+ } -+ -+ return true; -+ } -+ -+ /* -+ * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 -+ */ -+ private void listEntities(CommandSender sender, String[] args) { -+ if (args.length < 2 || args[1].toLowerCase(Locale.ENGLISH).equals("help")) { -+ sender.sendMessage(ChatColor.RED + "Use /paper entity [list] help for more information on a specific command."); -+ return; -+ } -+ -+ switch (args[1].toLowerCase(Locale.ENGLISH)) { -+ case "list": -+ String filter = "*"; -+ if (args.length > 2) { -+ if (args[2].toLowerCase(Locale.ENGLISH).equals("help")) { -+ sender.sendMessage(ChatColor.RED + "Use /paper entity list [filter] [worldName] to get entity info that matches the optional filter."); -+ return; -+ } -+ filter = args[2]; -+ } -+ final String cleanfilter = filter.replace("?", ".?").replace("*", ".*?"); -+ Set names = EntityType.getEntityNameList().stream() -+ .filter(n -> n.toString().matches(cleanfilter)) -+ .collect(Collectors.toSet()); -+ -+ if (names.isEmpty()) { -+ sender.sendMessage(ChatColor.RED + "Invalid filter, does not match any entities. Use /paper entity list for a proper list"); -+ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); -+ return; -+ } -+ -+ String worldName; -+ if (args.length > 3) { -+ worldName = args[3]; -+ } else if (sender instanceof Player) { -+ worldName = ((Player) sender).getWorld().getName(); -+ } else { -+ sender.sendMessage(ChatColor.RED + "Please specify the name of a world"); -+ sender.sendMessage(ChatColor.RED + "To do so without a filter, specify '*' as the filter"); -+ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); -+ return; -+ } -+ -+ Map>> list = Maps.newHashMap(); -+ World bukkitWorld = Bukkit.getWorld(worldName); -+ if (bukkitWorld == null) { -+ sender.sendMessage(ChatColor.RED + "Could not load world for " + worldName + ". Please select a valid world."); -+ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); -+ return; -+ } -+ ServerLevel world = ((CraftWorld) Bukkit.getWorld(worldName)).getHandle(); -+ -+ Map nonEntityTicking = Maps.newHashMap(); -+ ServerChunkCache chunkProviderServer = world.getChunkSource(); -+ -+ Collection entities = world.entitiesById.values(); -+ entities.forEach(e -> { -+ ResourceLocation key = new ResourceLocation(""); // TODO: update in next patch -+ -+ MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); -+ ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); -+ info.left++; -+ info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1); -+ if (!chunkProviderServer.isInEntityTickingChunk(e)) { -+ nonEntityTicking.merge(key, Integer.valueOf(1), Integer::sum); -+ } -+ }); -+ -+ if (names.size() == 1) { -+ ResourceLocation name = names.iterator().next(); -+ Pair> info = list.get(name); -+ int nonTicking = nonEntityTicking.getOrDefault(name, Integer.valueOf(0)).intValue(); -+ if (info == null) { -+ sender.sendMessage(ChatColor.RED + "No entities found."); -+ return; -+ } -+ sender.sendMessage("Entity: " + name + " Total Ticking: " + (info.getLeft() - nonTicking) + ", Total Non-Ticking: " + nonTicking); -+ info.getRight().entrySet().stream() -+ .sorted((a, b) -> !a.getValue().equals(b.getValue()) ? b.getValue() - a.getValue() : a.getKey().toString().compareTo(b.getKey().toString())) -+ .limit(10).forEach(e -> sender.sendMessage(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z + (chunkProviderServer.isEntityTickingChunk(e.getKey()) ? " (Ticking)" : " (Non-Ticking)"))); -+ } else { -+ List> info = list.entrySet().stream() -+ .filter(e -> names.contains(e.getKey())) -+ .map(e -> Pair.of(e.getKey(), e.getValue().left)) -+ .sorted((a, b) -> !a.getRight().equals(b.getRight()) ? b.getRight() - a.getRight() : a.getKey().toString().compareTo(b.getKey().toString())) -+ .collect(Collectors.toList()); -+ -+ if (info == null || info.size() == 0) { -+ sender.sendMessage(ChatColor.RED + "No entities found."); -+ return; -+ } -+ -+ int count = info.stream().mapToInt(Pair::getRight).sum(); -+ int nonTickingCount = nonEntityTicking.values().stream().mapToInt(Integer::intValue).sum(); -+ sender.sendMessage("Total Ticking: " + (count - nonTickingCount) + ", Total Non-Ticking: " + nonTickingCount); -+ info.forEach(e -> { -+ int nonTicking = nonEntityTicking.getOrDefault(e.getKey(), Integer.valueOf(0)).intValue(); -+ sender.sendMessage(" " + (e.getValue() - nonTicking) + " (" + nonTicking + ") " + ": " + e.getKey()); -+ }); -+ sender.sendMessage("* First number is ticking entities, second number is non-ticking entities"); -+ } -+ break; -+ } -+ } -+ -+ private void dumpHeap(CommandSender sender) { -+ java.nio.file.Path dir = java.nio.file.Paths.get("./dumps"); -+ String name = "heap-dump-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()); -+ -+ Command.broadcastCommandMessage(sender, ChatColor.YELLOW + "Writing JVM heap data..."); -+ -+ java.nio.file.Path file = CraftServer.dumpHeap(dir, name); -+ if (file != null) { -+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Heap dump saved to " + file); -+ } else { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Failed to write heap dump, see sever log for details"); -+ } -+ } -+ -+ private void doReload(CommandSender sender) { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues."); -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); -+ -+ MinecraftServer console = MinecraftServer.getServer(); -+ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); -+ for (ServerLevel world : console.getAllLevels()) { -+ world.paperConfig.init(); -+ } -+ console.server.reloadCount++; -+ -+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete."); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2c0514892d3993bef57ecf677cf8bb0fbe0216e4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +1,185 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Throwables; -+ -+import java.io.File; -+import java.io.IOException; -+import java.lang.reflect.InvocationTargetException; -+import java.lang.reflect.Method; -+import java.lang.reflect.Modifier; -+import java.util.HashMap; -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.TimeUnit; -+import java.util.logging.Level; -+import java.util.regex.Pattern; -+ -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+import org.bukkit.command.Command; -+import org.bukkit.configuration.ConfigurationSection; -+import org.bukkit.configuration.InvalidConfigurationException; -+import org.bukkit.configuration.file.YamlConfiguration; -+ -+public class PaperConfig { -+ -+ private static File CONFIG_FILE; -+ private static final String HEADER = "This is the main configuration file for Paper.\n" -+ + "As you can see, there's tons to configure. Some options may impact gameplay, so use\n" -+ + "with caution, and make sure you know what each option does before configuring.\n" -+ + "\n" -+ + "If you need help with the configuration or have any questions related to Paper,\n" -+ + "join us in our Discord or IRC channel.\n" -+ + "\n" -+ + "Discord: https://discord.gg/papermc\n" -+ + "IRC: #paper @ irc.esper.net ( https://webchat.esper.net/?channels=paper ) \n" -+ + "Website: https://papermc.io/ \n" -+ + "Docs: https://paper.readthedocs.org/ \n"; -+ /*========================================================================*/ -+ public static YamlConfiguration config; -+ static int version; -+ static Map commands; -+ private static boolean verbose; -+ private static boolean fatalError; -+ /*========================================================================*/ -+ -+ public static void init(File configFile) { -+ CONFIG_FILE = configFile; -+ config = new YamlConfiguration(); -+ try { -+ config.load(CONFIG_FILE); -+ } catch (IOException ex) { -+ } catch (InvalidConfigurationException ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Could not load paper.yml, please correct your syntax errors", ex); -+ throw Throwables.propagate(ex); -+ } -+ config.options().header(HEADER); -+ config.options().copyDefaults(true); -+ verbose = getBoolean("verbose", false); -+ -+ commands = new HashMap(); -+ commands.put("paper", new PaperCommand("paper")); -+ -+ version = getInt("config-version", 20); -+ set("config-version", 20); -+ readConfig(PaperConfig.class, null); -+ } -+ -+ protected static void logError(String s) { -+ Bukkit.getLogger().severe(s); -+ } -+ -+ protected static void fatal(String s) { -+ fatalError = true; -+ throw new RuntimeException("Fatal paper.yml config error: " + s); -+ } -+ -+ protected static void log(String s) { -+ if (verbose) { -+ Bukkit.getLogger().info(s); -+ } -+ } -+ -+ public static void registerCommands() { -+ for (Map.Entry entry : commands.entrySet()) { -+ MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); -+ } -+ } -+ -+ static void readConfig(Class clazz, Object instance) { -+ for (Method method : clazz.getDeclaredMethods()) { -+ if (Modifier.isPrivate(method.getModifiers())) { -+ if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) { -+ try { -+ method.setAccessible(true); -+ method.invoke(instance); -+ } catch (InvocationTargetException ex) { -+ throw Throwables.propagate(ex.getCause()); -+ } catch (Exception ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex); -+ } -+ } -+ } -+ } -+ -+ try { -+ config.save(CONFIG_FILE); -+ } catch (IOException ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex); -+ } -+ } -+ -+ private static final Pattern SPACE = Pattern.compile(" "); -+ private static final Pattern NOT_NUMERIC = Pattern.compile("[^-\\d.]"); -+ public static int getSeconds(String str) { -+ str = SPACE.matcher(str).replaceAll(""); -+ final char unit = str.charAt(str.length() - 1); -+ str = NOT_NUMERIC.matcher(str).replaceAll(""); -+ double num; -+ try { -+ num = Double.parseDouble(str); -+ } catch (Exception e) { -+ num = 0D; -+ } -+ switch (unit) { -+ case 'd': num *= (double) 60*60*24; break; -+ case 'h': num *= (double) 60*60; break; -+ case 'm': num *= (double) 60; break; -+ default: case 's': break; -+ } -+ return (int) num; -+ } -+ -+ protected static String timeSummary(int seconds) { -+ String time = ""; -+ -+ if (seconds > 60 * 60 * 24) { -+ time += TimeUnit.SECONDS.toDays(seconds) + "d"; -+ seconds %= 60 * 60 * 24; -+ } -+ -+ if (seconds > 60 * 60) { -+ time += TimeUnit.SECONDS.toHours(seconds) + "h"; -+ seconds %= 60 * 60; -+ } -+ -+ if (seconds > 0) { -+ time += TimeUnit.SECONDS.toMinutes(seconds) + "m"; -+ } -+ return time; -+ } -+ -+ private static void set(String path, Object val) { -+ config.set(path, val); -+ } -+ -+ private static boolean getBoolean(String path, boolean def) { -+ config.addDefault(path, def); -+ return config.getBoolean(path, config.getBoolean(path)); -+ } -+ -+ private static double getDouble(String path, double def) { -+ config.addDefault(path, def); -+ return config.getDouble(path, config.getDouble(path)); -+ } -+ -+ private static float getFloat(String path, float def) { -+ // TODO: Figure out why getFloat() always returns the default value. -+ return (float) getDouble(path, (double) def); -+ } -+ -+ private static int getInt(String path, int def) { -+ config.addDefault(path, def); -+ return config.getInt(path, config.getInt(path)); -+ } -+ -+ private static List getList(String path, T def) { -+ config.addDefault(path, def); -+ return (List) config.getList(path, config.getList(path)); -+ } -+ -+ private static String getString(String path, String def) { -+ config.addDefault(path, def); -+ return config.getString(path, config.getString(path)); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b31109d2dadd29e8852468c19265066b773d2be0 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +1,68 @@ -+package com.destroystokyo.paper; -+ -+import java.util.List; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.configuration.file.YamlConfiguration; -+import org.spigotmc.SpigotWorldConfig; -+ -+import static com.destroystokyo.paper.PaperConfig.log; -+import static com.destroystokyo.paper.PaperConfig.logError; -+ -+public class PaperWorldConfig { -+ -+ private final String worldName; -+ private final SpigotWorldConfig spigotConfig; -+ private YamlConfiguration config; -+ private boolean verbose; -+ -+ public PaperWorldConfig(String worldName, SpigotWorldConfig spigotConfig) { -+ this.worldName = worldName; -+ this.spigotConfig = spigotConfig; -+ this.config = PaperConfig.config; -+ init(); -+ } -+ -+ public void init() { -+ this.config = PaperConfig.config; // grab updated reference -+ log("-------- World Settings For [" + worldName + "] --------"); -+ PaperConfig.readConfig(PaperWorldConfig.class, this); -+ } -+ -+ private void set(String path, Object val) { -+ config.set("world-settings.default." + path, val); -+ if (config.get("world-settings." + worldName + "." + path) != null) { -+ config.set("world-settings." + worldName + "." + path, val); -+ } -+ } -+ -+ private boolean getBoolean(String path, boolean def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path)); -+ } -+ -+ private double getDouble(String path, double def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getDouble("world-settings." + worldName + "." + path, config.getDouble("world-settings.default." + path)); -+ } -+ -+ private int getInt(String path, int def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getInt("world-settings." + worldName + "." + path, config.getInt("world-settings.default." + path)); -+ } -+ -+ private float getFloat(String path, float def) { -+ // TODO: Figure out why getFloat() always returns the default value. -+ return (float) getDouble(path, (double) def); -+ } -+ -+ private List getList(String path, List def) { -+ config.addDefault("world-settings.default." + path, def); -+ return (List) config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)); -+ } -+ -+ private String getString(String path, String def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 9366b5551047e87e455fafbf45be5fb145aa875b..5d83a8d4c69144219219877c521c364d912d2452 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -95,6 +95,12 @@ public class Main { - DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(iregistrycustom_dimension, optionset); // CraftBukkit - CLI argument support - - dedicatedserversettings.forceSave(); -+ // Paper start - load config files for access below if needed -+ org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = loadConfigFile((File) optionset.valueOf("bukkit-settings")); -+ org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = loadConfigFile((File) optionset.valueOf("spigot-settings")); -+ org.bukkit.configuration.file.YamlConfiguration paperConfiguration = loadConfigFile((File) optionset.valueOf("paper-settings")); -+ // Paper end -+ - java.nio.file.Path java_nio_file_path1 = Paths.get("eula.txt"); - Eula eula = new Eula(java_nio_file_path1); - -@@ -236,6 +242,20 @@ public class Main { - - } - -+ // Paper start - load config files -+ private static org.bukkit.configuration.file.YamlConfiguration loadConfigFile(File configFile) throws Exception { -+ org.bukkit.configuration.file.YamlConfiguration config = new org.bukkit.configuration.file.YamlConfiguration(); -+ if (configFile.exists()) { -+ try { -+ config.load(configFile); -+ } catch (Exception ex) { -+ throw new Exception("Failed to load configuration file: " + configFile.getName(), ex); -+ } -+ } -+ return config; -+ } -+ // Paper end -+ - public static void forceUpgrade(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, boolean eraseCache, BooleanSupplier booleansupplier, ImmutableSet> worlds) { // CraftBukkit - Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit - WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, worlds, eraseCache); -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 2228f83f251851aa683f739ac5ce2ec98f059f3f..23d6f803eafa78fd51ea4cdc4ca25c78661bc80b 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -184,6 +184,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); - org.spigotmc.SpigotConfig.registerCommands(); - // Spigot end -+ // Paper start -+ try { -+ com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); -+ } catch (Exception e) { -+ DedicatedServer.LOGGER.error("Unable to load server configuration", e); -+ return false; -+ } -+ com.destroystokyo.paper.PaperConfig.registerCommands(); -+ // Paper end - - this.setPvpAllowed(dedicatedserverproperties.pvp); - this.setFlightAllowed(dedicatedserverproperties.allowFlight); -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index aa7bf54e4b93a9b6085aa943500f5dec5f60a117..7cc5070f70a4f740add9d971385ceaa4d44275a2 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -307,15 +307,15 @@ public class ServerChunkCache extends ChunkSource { - } - } - -- @Override -- public boolean isEntityTickingChunk(Entity entity) { -+ public final boolean isInEntityTickingChunk(Entity entity) { return this.isEntityTickingChunk(entity); } // Paper - OBFHELPER -+ @Override public boolean isEntityTickingChunk(Entity entity) { - long i = ChunkPos.asLong(Mth.floor(entity.getX()) >> 4, Mth.floor(entity.getZ()) >> 4); - - return this.checkChunkFuture(i, (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error - } - -- @Override -- public boolean isEntityTickingChunk(ChunkPos pos) { -+ public final boolean isEntityTickingChunk(ChunkPos chunkcoordintpair) { return this.isEntityTickingChunk(chunkcoordintpair); } // Paper - OBFHELPER -+ @Override public boolean isEntityTickingChunk(ChunkPos pos) { - return this.checkChunkFuture(pos.toLong(), (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index f82fd4a50921c3c4791be18a43778e6fd216f557..ff482d0349c18d0d1ba902ea0d10611b1ca4e588 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -2,6 +2,7 @@ package net.minecraft.world.entity; - - import com.google.common.collect.ImmutableSet; - import java.util.Optional; -+import java.util.Set; // Paper - import java.util.UUID; - import java.util.function.Function; - import java.util.stream.Stream; -@@ -599,4 +600,10 @@ public class EntityType { - return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval); - } - } -+ -+ // Paper start -+ public static Set getEntityNameList() { -+ return Registry.ENTITY_TYPE.keySet(); -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index b7c64fcf49ea50fa38a121d906ec6df20a1be31b..f08de81dcc4acd5a3e44407b431ce827a19b2e9c 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -129,6 +129,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public boolean populating; - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - -+ public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper -+ - public final SpigotTimings.WorldTimingsHandler timings; // Spigot - public static BlockPos lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; -@@ -149,6 +151,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot -+ this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper - this.generator = gen; - this.world = new CraftWorld((ServerLevel) this, gen, env); - this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns(); // CraftBukkit -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 761ad2d7e538d1e299d3050446274addcde7d772..328d1e2b128b62f24917719c79823c9fb64a0dcf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -806,6 +806,7 @@ public final class CraftServer implements Server { - } - - org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot -+ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper - for (ServerLevel world : console.getAllLevels()) { - world.worldDataServer.setDifficulty(config.difficulty); - world.setSpawnSettings(config.spawnMonsters, config.spawnAnimals); -@@ -839,6 +840,7 @@ public final class CraftServer implements Server { - world.ticksPerAmbientSpawns = this.getTicksPerAmbientSpawns(); - } - world.spigotConfig.init(); // Spigot -+ world.paperConfig.init(); // Paper - } - - pluginManager.clearPlugins(); -@@ -846,6 +848,7 @@ public final class CraftServer implements Server { - resetRecipes(); - reloadData(); - org.spigotmc.SpigotConfig.registerCommands(); // Spigot -+ com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper - overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); - ignoreVanillaPermissions = commandsConfiguration.getBoolean("ignore-vanilla-permissions"); - -@@ -2101,4 +2104,35 @@ public final class CraftServer implements Server { - return spigot; - } - // Spigot end -+ -+ // Paper start -+ @SuppressWarnings({"rawtypes", "unchecked"}) -+ public static java.nio.file.Path dumpHeap(java.nio.file.Path dir, String name) { -+ try { -+ java.nio.file.Files.createDirectories(dir); -+ -+ javax.management.MBeanServer server = java.lang.management.ManagementFactory.getPlatformMBeanServer(); -+ java.nio.file.Path file; -+ -+ try { -+ Class clazz = Class.forName("openj9.lang.management.OpenJ9DiagnosticsMXBean"); -+ Object openj9Mbean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "openj9.lang.management:type=OpenJ9Diagnostics", clazz); -+ java.lang.reflect.Method m = clazz.getMethod("triggerDumpToFile", String.class, String.class); -+ file = dir.resolve(name + ".phd"); -+ m.invoke(openj9Mbean, "heap", file.toString()); -+ } catch (ClassNotFoundException e) { -+ Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean"); -+ Object hotspotMBean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", clazz); -+ java.lang.reflect.Method m = clazz.getMethod("dumpHeap", String.class, boolean.class); -+ file = dir.resolve(name + ".hprof"); -+ m.invoke(hotspotMBean, file.toString(), true); -+ } -+ -+ return file; -+ } catch (Throwable t) { -+ Bukkit.getLogger().log(Level.SEVERE, "Could not write heap", t); -+ return null; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 46a16e31775b28c44f95a8ac5545ebcb656c74b6..05aedca561919a12ced1925c5cc9af585bb04523 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -129,6 +129,14 @@ public class Main { - .defaultsTo(new File("spigot.yml")) - .describedAs("Yml file"); - // Spigot End -+ -+ // Paper Start -+ acceptsAll(asList("paper", "paper-settings"), "File for paper settings") -+ .withRequiredArg() -+ .ofType(File.class) -+ .defaultsTo(new File("paper.yml")) -+ .describedAs("Yml file"); -+ // Paper end - } - }; - -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 83d83ff7ceffbb77723da721b869dfd0091e496d..0efcbab8f8806aeb8dd8bd6384e5a7cee375d100 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -39,36 +39,36 @@ public class SpigotWorldConfig - config.set( "world-settings.default." + path, val ); - } - -- private boolean getBoolean(String path, boolean def) -+ public boolean getBoolean(String path, boolean def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getBoolean( "world-settings." + worldName + "." + path, config.getBoolean( "world-settings.default." + path ) ); - } - -- private double getDouble(String path, double def) -+ public double getDouble(String path, double def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getDouble( "world-settings." + worldName + "." + path, config.getDouble( "world-settings.default." + path ) ); - } - -- private int getInt(String path) -+ public int getInt(String path) // Paper - private -> public - { - return config.getInt( "world-settings." + worldName + "." + path ); - } - -- private int getInt(String path, int def) -+ public int getInt(String path, int def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getInt( "world-settings." + worldName + "." + path, config.getInt( "world-settings.default." + path ) ); - } - -- private List getList(String path, T def) -+ public List getList(String path, T def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return (List) config.getList( "world-settings." + worldName + "." + path, config.getList( "world-settings.default." + path ) ); - } - -- private String getString(String path, String def) -+ public String getString(String path, String def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getString( "world-settings." + worldName + "." + path, config.getString( "world-settings.default." + path ) ); diff --git a/Remapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch b/Remapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch deleted file mode 100644 index 10c424b9a6..0000000000 --- a/Remapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch +++ /dev/null @@ -1,929 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 30 Mar 2016 19:36:20 -0400 -Subject: [PATCH] MC Dev fixes - - -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index 16220ce9a7db722c8b351f8016fd1df066ffcb98..8c378d3f3138953b3b22b289fecdb6b40a09ab63 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -65,8 +65,8 @@ public class Util { - return Collectors.toMap(Entry::getKey, Entry::getValue); - } - -- public static > String getPropertyName(Property iblockstate, Object object) { -- return iblockstate.value((Comparable) object); -+ public static > String a(Property iblockstate, T object) { // Paper - decompile fix -+ return iblockstate.getName(object); // Paper - decompile fix - } - - public static String makeDescriptionId(String type, @Nullable ResourceLocation id) { -@@ -234,8 +234,8 @@ public class Util { - public static T findPreviousInIterable(Iterable iterable, @Nullable T t0) { - Iterator iterator = iterable.iterator(); - -- Object object; -- Object object1; -+ T object; // Paper - decompile fix -+ T object1; // Paper - decompile fix - - for (object1 = null; iterator.hasNext(); object1 = object) { - object = iterator.next(); -@@ -260,7 +260,7 @@ public class Util { - } - - public static Strategy identityStrategy() { -- return Util.IdentityStrategy.INSTANCE; -+ return (Strategy) Util.IdentityStrategy.INSTANCE; // Paper - decompile fix - } - - public static CompletableFuture> sequence(List> futures) { -@@ -271,7 +271,7 @@ public class Util { - futures.forEach((completablefuture1) -> { - int i = list1.size(); - -- list1.add((Object) null); -+ list1.add(null); // Paper - decompile fix - acompletablefuture[i] = completablefuture1.whenComplete((object, throwable) -> { - if (throwable != null) { - completablefuture.completeExceptionally(throwable); -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index aa35d67cc27a4f982575eab3be46f4187f29d3fe..88147a1f25cf2fd549412b653b8f0eb5c60bb55d 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -241,8 +241,8 @@ public class BlockPos extends Vec3i { - }; - } - -- public static Iterable withinManhattan(BlockPos center, int xRange, int yRange, int zRange) { -- int l = xRange + yRange + zRange; -+ public static Iterable withinManhattan(BlockPos center, int xRange, int yRange, int zRange) { // Paper - decompile issues - variable name conflicts to inner class field refs -+ int l_decompiled = xRange + yRange + zRange; // Paper - decompile issues - int i1 = center.getX(); - int j1 = center.getY(); - int k1 = center.getZ(); -@@ -270,15 +270,15 @@ public class BlockPos extends Vec3i { - ++this.x; - if (this.x > this.maxX) { - ++this.currentDepth; -- if (this.currentDepth > x) { -+ if (this.currentDepth > l_decompiled) { // Paper - use proper l above (first line of this method) - return (BlockPos) this.endOfData(); - } - -- this.maxX = Math.min(currentDepth, this.currentDepth); -+ this.maxX = Math.min(xRange, this.currentDepth); // Paper - decompile issues - this.x = -this.maxX; - } - -- this.maxY = Math.min(maxX, this.currentDepth - Math.abs(this.x)); -+ this.maxY = Math.min(yRange, this.currentDepth - Math.abs(this.x)); // Paper - decompile issues - this.y = -this.maxY; - } - -@@ -286,7 +286,7 @@ public class BlockPos extends Vec3i { - int i2 = this.y; - int j2 = this.currentDepth - Math.abs(l1) - Math.abs(i2); - -- if (j2 <= maxY) { -+ if (j2 <= zRange) { // Paper - decompile issues - this.zMirror = j2 != 0; - blockposition_mutableblockposition = this.cursor.set(i1 + l1, j1 + i2, k1 + j2); - } -@@ -355,13 +355,13 @@ public class BlockPos extends Vec3i { - }; - } - -- public static Iterable spiralAround(BlockPos blockposition, int i, Direction enumdirection, Direction enumdirection1) { -+ public static Iterable spiralAround(BlockPos blockposition, int I, Direction enumdirection, Direction enumdirection1) { // Paper - decompile fix - Validate.validState(enumdirection.getAxis() != enumdirection1.getAxis(), "The two directions cannot be on the same axis", new Object[0]); - return () -> { - return new AbstractIterator() { - private final Direction[] directions = new Direction[]{enumdirection, enumdirection1, enumdirection.getOpposite(), enumdirection1.getOpposite()}; - private final BlockPos.MutableBlockPos cursor = blockposition.mutable().move(enumdirection1); -- private final int legs = 4 * legSize; -+ private final int legs = 4 * I; - private int leg = -1; - private int legSize; - private int legIndex; -diff --git a/src/main/java/net/minecraft/core/IdMapper.java b/src/main/java/net/minecraft/core/IdMapper.java -index 71c591487853bec3cecf5777c09ddc05bd658b64..424c6cacc2e7c7b1c9d0b92fe198237033a3fcbd 100644 ---- a/src/main/java/net/minecraft/core/IdMapper.java -+++ b/src/main/java/net/minecraft/core/IdMapper.java -@@ -27,7 +27,7 @@ public class IdMapper implements IdMap { - this.tToId.put(value, id); - - while (this.idToT.size() <= id) { -- this.idToT.add((Object) null); -+ this.idToT.add(null); // Paper - decompile fix - } - - this.idToT.set(id, value); -@@ -41,6 +41,13 @@ public class IdMapper implements IdMap { - this.addMapping(value, this.nextId); - } - -+ // Paper start - decompile fix -+ @Override -+ public int a(T t) { -+ return getId(t); -+ } -+ // Paper end -+ - public int getId(T entry) { - Integer integer = (Integer) this.tToId.get(entry); - -diff --git a/src/main/java/net/minecraft/nbt/ListTag.java b/src/main/java/net/minecraft/nbt/ListTag.java -index efc632a8ac13f77aaf2229a09e84416c09c86255..084340dc73acb3d972e0717b48da820c027a5137 100644 ---- a/src/main/java/net/minecraft/nbt/ListTag.java -+++ b/src/main/java/net/minecraft/nbt/ListTag.java -@@ -53,7 +53,7 @@ public class ListTag extends CollectionTag { - return "TAG_List"; - } - }; -- private static final ByteSet INLINE_ELEMENT_TYPES = new ByteOpenHashSet(Arrays.asList(1, 2, 3, 4, 5, 6)); -+ private static final ByteSet INLINE_ELEMENT_TYPES = new ByteOpenHashSet(Arrays.asList((byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6)); // Paper - decompiler fix - private final List list; - private byte type; - -diff --git a/src/main/java/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java -index 5494db9e8e04d976aa1b005a108b452cd481d0bb..c4fbc0bc8b80d16f09d3c6642acc7476a0817868 100644 ---- a/src/main/java/net/minecraft/nbt/NbtIo.java -+++ b/src/main/java/net/minecraft/nbt/NbtIo.java -@@ -18,6 +18,7 @@ import java.util.zip.GZIPOutputStream; - import net.minecraft.CrashReport; - import net.minecraft.CrashReportCategory; - import net.minecraft.ReportedException; -+import io.netty.buffer.ByteBufInputStream; // Paper - - public class NbtIo { - -@@ -137,7 +138,7 @@ public class NbtIo { - - public static CompoundTag read(DataInput input, NbtAccounter tracker) throws IOException { - // Spigot start -- if ( input instanceof io.netty.buffer.ByteBufInputStream ) -+ if ( input instanceof ByteBufInputStream) // Paper - { - input = new DataInputStream(new org.spigotmc.LimitStream((InputStream) input, tracker)); - } -diff --git a/src/main/java/net/minecraft/nbt/Tag.java b/src/main/java/net/minecraft/nbt/Tag.java -index 483c33e9b2d64c1a003d3bb543486b8a545bc96a..85e9c5f4620fcf48cb3655fbb2db58b3fb31aa74 100644 ---- a/src/main/java/net/minecraft/nbt/Tag.java -+++ b/src/main/java/net/minecraft/nbt/Tag.java -@@ -20,7 +20,7 @@ public interface Tag { - - TagType getType(); - -- Tag copy(); -+ public Tag copy(); // Paper - decompile fix - - default String getAsString() { - return this.toString(); -diff --git a/src/main/java/net/minecraft/network/ConnectionProtocol.java b/src/main/java/net/minecraft/network/ConnectionProtocol.java -index a12d169edf4e087b18fedf7199d6eb7ee58f0305..fca778d131aa10e88d5f7ed8d57eda6803318184 100644 ---- a/src/main/java/net/minecraft/network/ConnectionProtocol.java -+++ b/src/main/java/net/minecraft/network/ConnectionProtocol.java -@@ -14,23 +14,29 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.PacketFlow; - import net.minecraft.network.protocol.game.*; - import net.minecraft.network.protocol.handshake.ClientIntentionPacket; -+import net.minecraft.network.protocol.handshake.ServerHandshakePacketListener; -+import net.minecraft.network.protocol.login.ClientLoginPacketListener; - import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; - import net.minecraft.network.protocol.login.ClientboundGameProfilePacket; - import net.minecraft.network.protocol.login.ClientboundHelloPacket; - import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; - import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; -+import net.minecraft.network.protocol.login.ServerLoginPacketListener; - import net.minecraft.network.protocol.login.ServerboundCustomQueryPacket; - import net.minecraft.network.protocol.login.ServerboundHelloPacket; - import net.minecraft.network.protocol.login.ServerboundKeyPacket; -+import net.minecraft.network.protocol.status.ClientStatusPacketListener; - import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; - import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; -+import net.minecraft.network.protocol.status.ServerStatusPacketListener; - import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; - import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; - import org.apache.logging.log4j.LogManager; - - public enum ConnectionProtocol { - -- HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))), PLAY(0, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new).a(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new).a(ClientboundAddMobPacket.class, ClientboundAddMobPacket::new).a(ClientboundAddPaintingPacket.class, ClientboundAddPaintingPacket::new).a(ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new).a(ClientboundAnimatePacket.class, ClientboundAnimatePacket::new).a(ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new).a(ClientboundBlockBreakAckPacket.class, ClientboundBlockBreakAckPacket::new).a(ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new).a(ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new).a(ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new).a(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new).a(ClientboundBossEventPacket.class, ClientboundBossEventPacket::new).a(ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new).a(ClientboundChatPacket.class, ClientboundChatPacket::new).a(ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new).a(ClientboundCommandsPacket.class, ClientboundCommandsPacket::new).a(ClientboundContainerAckPacket.class, ClientboundContainerAckPacket::new).a(ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new).a(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new).a(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new).a(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new).a(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new).a(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new).a(ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new).a(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new).a(ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new).a(ClientboundExplodePacket.class, ClientboundExplodePacket::new).a(ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new).a(ClientboundGameEventPacket.class, ClientboundGameEventPacket::new).a(ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new).a(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new).a(ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new).a(ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new).a(ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new).a(ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new).a(ClientboundLoginPacket.class, ClientboundLoginPacket::new).a(ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new).a(ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new).a(ClientboundMoveEntityPacket.Pos.class, ClientboundMoveEntityPacket.Pos::new).a(ClientboundMoveEntityPacket.PosRot.class, ClientboundMoveEntityPacket.PosRot::new).a(ClientboundMoveEntityPacket.Rot.class, ClientboundMoveEntityPacket.Rot::new).a(ClientboundMoveEntityPacket.class, ClientboundMoveEntityPacket::new).a(ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new).a(ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new).a(ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new).a(ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new).a(ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new).a(ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new).a(ClientboundPlayerCombatPacket.class, ClientboundPlayerCombatPacket::new).a(ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new).a(ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new).a(ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new).a(ClientboundRecipePacket.class, ClientboundRecipePacket::new).a(ClientboundRemoveEntitiesPacket.class, ClientboundRemoveEntitiesPacket::new).a(ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new).a(ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new).a(ClientboundRespawnPacket.class, ClientboundRespawnPacket::new).a(ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new).a(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new).a(ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new).a(ClientboundSetBorderPacket.class, ClientboundSetBorderPacket::new).a(ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new).a(ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new).a(ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new).a(ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new).a(ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new).a(ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new).a(ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new).a(ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new).a(ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new).a(ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new).a(ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new).a(ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new).a(ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new).a(ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new).a(ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new).a(ClientboundSetScorePacket.class, ClientboundSetScorePacket::new).a(ClientboundSetTimePacket.class, ClientboundSetTimePacket::new).a(ClientboundSetTitlesPacket.class, ClientboundSetTitlesPacket::new).a(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new).a(ClientboundSoundPacket.class, ClientboundSoundPacket::new).a(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new).a(ClientboundTabListPacket.class, ClientboundTabListPacket::new).a(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new).a(ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new).a(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new).a(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new).a(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new).a(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new).a(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new).a(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new)).a(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new).a(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new).a(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new).a(ServerboundChatPacket.class, ServerboundChatPacket::new).a(ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new).a(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new).a(ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new).a(ServerboundContainerAckPacket.class, ServerboundContainerAckPacket::new).a(ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new).a(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new).a(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new).a(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new).a(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new).a(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new).a(ServerboundInteractPacket.class, ServerboundInteractPacket::new).a(ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new).a(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new).a(ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new).a(ServerboundMovePlayerPacket.Pos.class, ServerboundMovePlayerPacket.Pos::new).a(ServerboundMovePlayerPacket.PosRot.class, ServerboundMovePlayerPacket.PosRot::new).a(ServerboundMovePlayerPacket.Rot.class, ServerboundMovePlayerPacket.Rot::new).a(ServerboundMovePlayerPacket.class, ServerboundMovePlayerPacket::new).a(ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new).a(ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new).a(ServerboundPickItemPacket.class, ServerboundPickItemPacket::new).a(ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new).a(ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new).a(ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new).a(ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new).a(ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new).a(ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new).a(ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new).a(ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new).a(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new).a(ServerboundSeenAdvancementsPacket.class, ServerboundSeenAdvancementsPacket::new).a(ServerboundSelectTradePacket.class, ServerboundSelectTradePacket::new).a(ServerboundSetBeaconPacket.class, ServerboundSetBeaconPacket::new).a(ServerboundSetCarriedItemPacket.class, ServerboundSetCarriedItemPacket::new).a(ServerboundSetCommandBlockPacket.class, ServerboundSetCommandBlockPacket::new).a(ServerboundSetCommandMinecartPacket.class, ServerboundSetCommandMinecartPacket::new).a(ServerboundSetCreativeModeSlotPacket.class, ServerboundSetCreativeModeSlotPacket::new).a(ServerboundSetJigsawBlockPacket.class, ServerboundSetJigsawBlockPacket::new).a(ServerboundSetStructureBlockPacket.class, ServerboundSetStructureBlockPacket::new).a(ServerboundSignUpdatePacket.class, ServerboundSignUpdatePacket::new).a(ServerboundSwingPacket.class, ServerboundSwingPacket::new).a(ServerboundTeleportToEntityPacket.class, ServerboundTeleportToEntityPacket::new).a(ServerboundUseItemOnPacket.class, ServerboundUseItemOnPacket::new).a(ServerboundUseItemPacket.class, ServerboundUseItemPacket::new))), STATUS(1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new).a(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)).a(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new).a(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new))), LOGIN(2, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new).a(ClientboundHelloPacket.class, ClientboundHelloPacket::new).a(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new).a(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new).a(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new)).a(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet<>()).addPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new).a(ServerboundKeyPacket.class, ServerboundKeyPacket::new).a(ServerboundCustomQueryPacket.class, ServerboundCustomQueryPacket::new))); -+ // Paper - fix decompile error - add generic names to < > like PacketListenerPlayOut -+ HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))), PLAY(0, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new).addPacket(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new).addPacket(ClientboundAddMobPacket.class, ClientboundAddMobPacket::new).addPacket(ClientboundAddPaintingPacket.class, ClientboundAddPaintingPacket::new).addPacket(ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new).addPacket(ClientboundAnimatePacket.class, ClientboundAnimatePacket::new).addPacket(ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new).addPacket(ClientboundBlockBreakAckPacket.class, ClientboundBlockBreakAckPacket::new).addPacket(ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new).addPacket(ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new).addPacket(ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new).addPacket(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new).addPacket(ClientboundBossEventPacket.class, ClientboundBossEventPacket::new).addPacket(ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new).addPacket(ClientboundChatPacket.class, ClientboundChatPacket::new).addPacket(ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new).addPacket(ClientboundCommandsPacket.class, ClientboundCommandsPacket::new).addPacket(ClientboundContainerAckPacket.class, ClientboundContainerAckPacket::new).addPacket(ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new).addPacket(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new).addPacket(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new).addPacket(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new).addPacket(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new).addPacket(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new).addPacket(ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new).addPacket(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new).addPacket(ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new).addPacket(ClientboundExplodePacket.class, ClientboundExplodePacket::new).addPacket(ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new).addPacket(ClientboundGameEventPacket.class, ClientboundGameEventPacket::new).addPacket(ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new).addPacket(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new).addPacket(ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new).addPacket(ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new).addPacket(ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new).addPacket(ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new).addPacket(ClientboundLoginPacket.class, ClientboundLoginPacket::new).addPacket(ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new).addPacket(ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new).addPacket(ClientboundMoveEntityPacket.Pos.class, ClientboundMoveEntityPacket.Pos::new).addPacket(ClientboundMoveEntityPacket.PosRot.class, ClientboundMoveEntityPacket.PosRot::new).addPacket(ClientboundMoveEntityPacket.Rot.class, ClientboundMoveEntityPacket.Rot::new).addPacket(ClientboundMoveEntityPacket.class, ClientboundMoveEntityPacket::new).addPacket(ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new).addPacket(ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new).addPacket(ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new).addPacket(ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new).addPacket(ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new).addPacket(ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new).addPacket(ClientboundPlayerCombatPacket.class, ClientboundPlayerCombatPacket::new).addPacket(ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new).addPacket(ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new).addPacket(ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new).addPacket(ClientboundRecipePacket.class, ClientboundRecipePacket::new).addPacket(ClientboundRemoveEntitiesPacket.class, ClientboundRemoveEntitiesPacket::new).addPacket(ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new).addPacket(ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new).addPacket(ClientboundRespawnPacket.class, ClientboundRespawnPacket::new).addPacket(ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new).addPacket(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new).addPacket(ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new).addPacket(ClientboundSetBorderPacket.class, ClientboundSetBorderPacket::new).addPacket(ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new).addPacket(ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new).addPacket(ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new).addPacket(ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new).addPacket(ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new).addPacket(ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new).addPacket(ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new).addPacket(ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new).addPacket(ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new).addPacket(ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new).addPacket(ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new).addPacket(ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new).addPacket(ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new).addPacket(ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new).addPacket(ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new).addPacket(ClientboundSetScorePacket.class, ClientboundSetScorePacket::new).addPacket(ClientboundSetTimePacket.class, ClientboundSetTimePacket::new).addPacket(ClientboundSetTitlesPacket.class, ClientboundSetTitlesPacket::new).addPacket(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new).addPacket(ClientboundSoundPacket.class, ClientboundSoundPacket::new).addPacket(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new).addPacket(ClientboundTabListPacket.class, ClientboundTabListPacket::new).addPacket(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new).addPacket(ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new).addPacket(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new).addPacket(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new).addPacket(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new).addPacket(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new).addPacket(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new).addPacket(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new).addPacket(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new).addPacket(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new).addPacket(ServerboundChatPacket.class, ServerboundChatPacket::new).addPacket(ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new).addPacket(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new).addPacket(ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new).addPacket(ServerboundContainerAckPacket.class, ServerboundContainerAckPacket::new).addPacket(ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new).addPacket(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new).addPacket(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new).addPacket(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new).addPacket(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new).addPacket(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new).addPacket(ServerboundInteractPacket.class, ServerboundInteractPacket::new).addPacket(ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new).addPacket(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new).addPacket(ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new).addPacket(ServerboundMovePlayerPacket.Pos.class, ServerboundMovePlayerPacket.Pos::new).addPacket(ServerboundMovePlayerPacket.PosRot.class, ServerboundMovePlayerPacket.PosRot::new).addPacket(ServerboundMovePlayerPacket.Rot.class, ServerboundMovePlayerPacket.Rot::new).addPacket(ServerboundMovePlayerPacket.class, ServerboundMovePlayerPacket::new).addPacket(ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new).addPacket(ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new).addPacket(ServerboundPickItemPacket.class, ServerboundPickItemPacket::new).addPacket(ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new).addPacket(ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new).addPacket(ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new).addPacket(ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new).addPacket(ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new).addPacket(ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new).addPacket(ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new).addPacket(ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new).addPacket(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new).addPacket(ServerboundSeenAdvancementsPacket.class, ServerboundSeenAdvancementsPacket::new).addPacket(ServerboundSelectTradePacket.class, ServerboundSelectTradePacket::new).addPacket(ServerboundSetBeaconPacket.class, ServerboundSetBeaconPacket::new).addPacket(ServerboundSetCarriedItemPacket.class, ServerboundSetCarriedItemPacket::new).addPacket(ServerboundSetCommandBlockPacket.class, ServerboundSetCommandBlockPacket::new).addPacket(ServerboundSetCommandMinecartPacket.class, ServerboundSetCommandMinecartPacket::new).addPacket(ServerboundSetCreativeModeSlotPacket.class, ServerboundSetCreativeModeSlotPacket::new).addPacket(ServerboundSetJigsawBlockPacket.class, ServerboundSetJigsawBlockPacket::new).addPacket(ServerboundSetStructureBlockPacket.class, ServerboundSetStructureBlockPacket::new).addPacket(ServerboundSignUpdatePacket.class, ServerboundSignUpdatePacket::new).addPacket(ServerboundSwingPacket.class, ServerboundSwingPacket::new).addPacket(ServerboundTeleportToEntityPacket.class, ServerboundTeleportToEntityPacket::new).addPacket(ServerboundUseItemOnPacket.class, ServerboundUseItemOnPacket::new).addPacket(ServerboundUseItemPacket.class, ServerboundUseItemPacket::new))), STATUS(1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new).addPacket(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)).addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new).addPacket(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new))), LOGIN(2, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new).addPacket(ClientboundHelloPacket.class, ClientboundHelloPacket::new).addPacket(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new).addPacket(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new).addPacket(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new).addPacket(ServerboundKeyPacket.class, ServerboundKeyPacket::new).addPacket(ServerboundCustomQueryPacket.class, ServerboundCustomQueryPacket::new))); - - private static final ConnectionProtocol[] LOOKUP = new ConnectionProtocol[4]; - private static final Map>, ConnectionProtocol> PROTOCOL_BY_PACKET = Maps.newHashMap(); -@@ -115,7 +121,7 @@ public enum ConnectionProtocol { - private final List>> idToConstructor; - - private PacketSet() { -- this.classToId = (Object2IntMap) Util.make((Object) (new Object2IntOpenHashMap()), (object2intopenhashmap) -> { -+ this.classToId = (Object2IntMap) Util.make(new Object2IntOpenHashMap(), (object2intopenhashmap) -> { // Paper - fix decompile error - object2intopenhashmap.defaultReturnValue(-1); - }); - this.idToConstructor = Lists.newArrayList(); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 21f461ce884bc547dbe81c5430be530423c1605c..37a51dee4cd37844e80fdd5c9853947201151dfc 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1673,9 +1673,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoopmap(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error - }, this).thenCompose((immutablelist) -> { -- return ServerResources.loadResources(immutablelist, this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this); -+ return ServerResources.loadResources(immutablelist, this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this); // Paper - decompile error - }).thenAcceptAsync((datapackresources) -> { - this.resources.close(); - this.resources = datapackresources; -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 37e938b258ee4eb5f5bab56145e83b640d80bcc7..23506a8903ce64fbfe849bb94e589bdbb6e61a74 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1913,7 +1913,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - // CraftBukkit - decompile error -- return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(it.unimi.dsi.fastutil.objects.Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { -+ return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { // Paper - decompile fix - return it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey() + ":" + it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue(); - }).collect(Collectors.joining(",")); - } catch (Exception exception) { -diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java -index ad8a9d14e17b5e40b2cc3a83154931734d6c73d7..cc4190b3a8904d1eaae0f542a3b3090583f5ff82 100644 ---- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java -+++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java -@@ -179,9 +179,9 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl - - public void tryScheduleUpdate() { - if ((!this.lightTasks.isEmpty() || super.hasLightWork()) && this.scheduled.compareAndSet(false, true)) { -- this.taskMailbox.tell((Object) (() -> { -- this.b(); -- this.g.set(false); -+ this.taskMailbox.tell((() -> { // Paper - decompile error -+ this.runUpdate(); -+ this.scheduled.set(false); - })); - } - -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 90df41ec5081fe4ef2bc507e7289b18e0fea6e53..0c118d482e304c567fe7fe778c6ff386f960bdde 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -23,7 +23,7 @@ public final class Ticket implements Comparable> { - } else { - int j = Integer.compare(System.identityHashCode(this.type), System.identityHashCode(ticket.type)); - -- return j != 0 ? j : this.type.getComparator().compare(this.key, ticket.key); -+ return j != 0 ? j : this.type.getComparator().compare(this.key, (T)ticket.key); // Paper - decompile fix - } - } - -diff --git a/src/main/java/net/minecraft/stats/ServerStatsCounter.java b/src/main/java/net/minecraft/stats/ServerStatsCounter.java -index d624c390f8550c6aa44ca5920d127c901903ce27..7d435998680a363ad06c2e08139010c2573f7fb3 100644 ---- a/src/main/java/net/minecraft/stats/ServerStatsCounter.java -+++ b/src/main/java/net/minecraft/stats/ServerStatsCounter.java -@@ -203,7 +203,7 @@ public class ServerStatsCounter extends StatsCounter { - ObjectIterator objectiterator = this.stats.object2IntEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); -+ Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix - Stat statistic = (Stat) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); - - ((JsonObject) map.computeIfAbsent(statistic.getType(), (statisticwrapper) -> { -diff --git a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java -index 74eb1ed6b3fafeaca7e65a88a982d759d6836853..66ad412e4368a8615cc66a97ac442c572813a3dd 100644 ---- a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java -+++ b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java -@@ -18,11 +18,18 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { - - public CrudeIncrementalIntIdentityHashBiMap(int size) { - size = (int) ((float) size / 0.8F); -- this.keys = (Object[]) (new Object[size]); -+ this.keys = (K[]) (new Object[size]); // Paper - decompile fix - this.values = new int[size]; -- this.byId = (Object[]) (new Object[size]); -+ this.byId = (K[]) (new Object[size]); // Paper - decompile fix - } - -+ // Paper start - decompile fix -+ @Override -+ public int a(K k) { -+ return getId(k); -+ } -+ // Paper end -+ - public int getId(@Nullable K entry) { - return this.getValue(this.indexOf(entry, this.hash(entry))); - } -@@ -56,9 +63,9 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { - K[] ak = this.keys; - int[] aint = this.values; - -- this.keys = (Object[]) (new Object[newSize]); -+ this.keys = (K[]) (new Object[newSize]); // Paper - decompile fix - this.values = new int[newSize]; -- this.byId = (Object[]) (new Object[newSize]); -+ this.byId = (K[]) (new Object[newSize]); // Paper - decompile fix - this.nextId = 0; - this.size = 0; - -diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java -index be40fc388c501c311d661927025f1c572f3b3493..93813a508be1e1e600a8211f9822f2087328de70 100644 ---- a/src/main/java/net/minecraft/util/SortedArraySet.java -+++ b/src/main/java/net/minecraft/util/SortedArraySet.java -@@ -23,11 +23,11 @@ public class SortedArraySet extends AbstractSet { - } - - public static > SortedArraySet create(int initialCapacity) { -- return new SortedArraySet<>(initialCapacity, Comparator.naturalOrder()); -+ return new SortedArraySet<>(initialCapacity, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix - } - - private static T[] castRawArray(Object[] array) { -- return (Object[]) array; -+ return (T[])array; // Paper - decompile fix - } - - private int findIndex(T object) { -@@ -101,7 +101,7 @@ public class SortedArraySet extends AbstractSet { - } - - public boolean remove(Object object) { -- int i = this.findIndex(object); -+ int i = this.findIndex((T)object); // Paper - decompile fix - - if (i >= 0) { - this.removeInternal(i); -@@ -116,7 +116,7 @@ public class SortedArraySet extends AbstractSet { - } - - public boolean contains(Object object) { -- int i = this.findIndex(object); -+ int i = this.findIndex((T)object); // Paper - decompile fix - - return i >= 0; - } -@@ -135,7 +135,7 @@ public class SortedArraySet extends AbstractSet { - - public U[] toArray(U[] au) { - if (au.length < this.size) { -- return (Object[]) Arrays.copyOf(this.contents, this.size, au.getClass()); -+ return (U[])Arrays.copyOf(this.contents, this.size, au.getClass()); // Paper - decompile fix - } else { - System.arraycopy(this.contents, 0, au, 0, this.size); - if (au.length > this.size) { -diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -index d9375f83de6d069f603f8a48cc5b02194e940052..03831adce7905916423d8c3834c42c90f3a1ca8f 100644 ---- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -+++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -@@ -55,7 +55,7 @@ public abstract class BlockableEventLoop implements Processo - return this.submitAsync(task); - } else { - task.run(); -- return CompletableFuture.completedFuture((Object) null); -+ return CompletableFuture.completedFuture(null); // Paper - decompile fix - } - } - -@@ -90,14 +90,14 @@ public abstract class BlockableEventLoop implements Processo - } - - protected boolean pollTask() { -- R r0 = (Runnable) this.pendingRunnables.peek(); -+ R r0 = this.pendingRunnables.peek(); // Paper - decompile fix - - if (r0 == null) { - return false; - } else if (this.blockingCount == 0 && !this.shouldRun(r0)) { - return false; - } else { -- this.doRunTask((Runnable) this.pendingRunnables.remove()); -+ this.doRunTask(this.pendingRunnables.remove()); // Paper - decompile fix - return true; - } - } -diff --git a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java -index cc77767947e458e7205e616dce3bea8da09ca0cf..c763aa0c0cf49dd844af94a820103258b49021ae 100644 ---- a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java -+++ b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java -@@ -100,7 +100,7 @@ public class ProcessorMailbox implements ProcessorHandle, AutoCloseable, R - - public void run() { - try { -- this.pollUntil((i) -> { -+ this.pollUntil((int i) -> { // Paper - decompile fix - return i == 0; - }); - } finally { -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -index 8f686f8608771d0a444dfd51dd4eabc90c6b2262..33a8604fa6c6431ccc5f61e484c163e09f1625a0 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -@@ -191,9 +191,9 @@ public class PoiManager extends SectionStorage { - } - - private static boolean mayHavePoi(LevelChunkSection chunksection) { -- Set set = PoiType.ALL_STATES; -+ Set set = PoiType.ALL_STATES; // Paper - decompile error - -- set.getClass(); -+ //set.getClass(); // Paper - decompile error - return chunksection.maybeHas(set::contains); - } - -@@ -211,7 +211,7 @@ public class PoiManager extends SectionStorage { - SectionPos.aroundChunk(new ChunkPos(pos), Math.floorDiv(radius, 16)).map((sectionposition) -> { - return Pair.of(sectionposition, this.getOrLoad(sectionposition.asLong())); - }).filter((pair) -> { -- return !(Boolean) ((Optional) pair.getSecond()).map(PoiSection::a).orElse(false); -+ return !(Boolean) (pair.getSecond()).map(PoiSection::isValid).orElse(false); // Paper - decompile fix - }).map((pair) -> { - return ((SectionPos) pair.getFirst()).chunk(); - }).filter((chunkcoordintpair) -> { -@@ -257,13 +257,13 @@ public class PoiManager extends SectionStorage { - - public static enum Occupancy { - -- HAS_SPACE(PoiRecord::d), IS_OCCUPIED(PoiRecord::e), ANY((villageplacerecord) -> { -+ HAS_SPACE(PoiRecord::hasSpace), IS_OCCUPIED(PoiRecord::isOccupied), ANY((villageplacerecord) -> { - return true; - }); - - private final Predicate test; - -- private Occupancy(Predicate predicate) { -+ private Occupancy(Predicate predicate) { // Paper - decompile fix - this.test = predicate; - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -index 97317517a729877e307407ca9fab5fa58657fe38..a41f61daf6cbbb13d0b86cdbad8a4cae00368653 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -@@ -65,7 +65,7 @@ public class Vindicator extends AbstractIllager { - this.goalSelector.addGoal(2, new AbstractIllager.RaiderOpenDoorGoal(this)); - this.goalSelector.addGoal(3, new Raider.HoldGroundAttackGoal(this, 10.0F)); - this.goalSelector.addGoal(4, new Vindicator.VindicatorMeleeAttackGoal(this)); -- this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).canUse()); -+ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers(new Class[0])); // Paper - decompile fix - this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true)); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); -diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -index ad4e181b24829980dc12f46807ec1c5226bd8e0c..fd1b84baae5f333c58dbbdcbfaa9198328f0961d 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -+++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -@@ -47,12 +47,12 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; - - public class VillagerTrades { - -- public static final Map> TRADES = (Map) Util.make((Object) Maps.newHashMap(), (hashmap) -> { -+ public static final Map> TRADES = Util.make(Maps.newHashMap(), (hashmap) -> { // Paper - decompile fix - hashmap.put(VillagerProfession.FARMER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WHEAT, 20, 16, 2), new VillagerTrades.EmeraldForItems(Items.POTATO, 26, 16, 2), new VillagerTrades.EmeraldForItems(Items.CARROT, 22, 16, 2), new VillagerTrades.EmeraldForItems(Items.BEETROOT, 15, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.BREAD, 1, 6, 16, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Blocks.PUMPKIN, 6, 12, 10), new VillagerTrades.ItemsForEmeralds(Items.PUMPKIN_PIE, 1, 4, 5), new VillagerTrades.ItemsForEmeralds(Items.APPLE, 1, 4, 16, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.COOKIE, 3, 18, 10), new VillagerTrades.EmeraldForItems(Blocks.MELON, 4, 12, 20)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Blocks.CAKE, 1, 1, 12, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.NIGHT_VISION, 100, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.JUMP, 160, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.WEAKNESS, 140, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.BLINDNESS, 120, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.POISON, 280, 15), new VillagerTrades.SuspisciousStewForEmerald(MobEffects.SATURATION, 7, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.GOLDEN_CARROT, 3, 3, 30), new VillagerTrades.ItemsForEmeralds(Items.GLISTERING_MELON_SLICE, 4, 3, 30)}))); -- hashmap.put(VillagerProfession.FISHERMAN, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STRING, 20, 16, 2), new VillagerTrades.EmeraldForItems(Items.COAL, 10, 16, 2), new VillagerTrades.ItemsAndEmeraldsToItems(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.ItemsForEmeralds(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COD, 15, 16, 10), new VillagerTrades.ItemsAndEmeraldsToItems(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.ItemsForEmeralds(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.SALMON, 13, 16, 20), new VillagerTrades.EnchantedItemForEmeralds(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.EmeraldsForVillagerTypeItem(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); -+ hashmap.put(VillagerProfession.FISHERMAN, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STRING, 20, 16, 2), new VillagerTrades.EmeraldForItems(Items.COAL, 10, 16, 2), new VillagerTrades.ItemsAndEmeraldsToItems(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.ItemsForEmeralds(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COD, 15, 16, 10), new VillagerTrades.ItemsAndEmeraldsToItems(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.ItemsForEmeralds(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.SALMON, 13, 16, 20), new VillagerTrades.EnchantedItemForEmeralds(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.EmeraldsForVillagerTypeItem(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); // Paper - add to ImmutableMap..builder() - hashmap.put(VillagerProfession.SHEPHERD, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Blocks.WHITE_WOOL, 18, 16, 2), new VillagerTrades.EmeraldForItems(Blocks.BROWN_WOOL, 18, 16, 2), new VillagerTrades.EmeraldForItems(Blocks.BLACK_WOOL, 18, 16, 2), new VillagerTrades.EmeraldForItems(Blocks.GRAY_WOOL, 18, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.SHEARS, 2, 1, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WHITE_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.GRAY_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.BLACK_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.LIGHT_BLUE_DYE, 12, 16, 10), new VillagerTrades.EmeraldForItems(Items.LIME_DYE, 12, 16, 10), new VillagerTrades.ItemsForEmeralds(Blocks.WHITE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.ORANGE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.MAGENTA_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.YELLOW_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIME_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PINK_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.CYAN_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PURPLE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BROWN_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GREEN_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.RED_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLACK_WOOL, 1, 1, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.WHITE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.ORANGE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.MAGENTA_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.YELLOW_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIME_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PINK_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.CYAN_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.PURPLE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BROWN_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.GREEN_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.RED_CARPET, 1, 4, 16, 5), new VillagerTrades.ItemsForEmeralds(Blocks.BLACK_CARPET, 1, 4, 16, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.YELLOW_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.LIGHT_GRAY_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.ORANGE_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.RED_DYE, 12, 16, 20), new VillagerTrades.EmeraldForItems(Items.PINK_DYE, 12, 16, 20), new VillagerTrades.ItemsForEmeralds(Blocks.WHITE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.YELLOW_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.RED_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.BLACK_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.BLUE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.BROWN_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.CYAN_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.GRAY_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.GREEN_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_BLUE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.LIGHT_GRAY_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.LIME_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.MAGENTA_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.ORANGE_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.PINK_BED, 3, 1, 12, 10), new VillagerTrades.ItemsForEmeralds(Blocks.PURPLE_BED, 3, 1, 12, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.BROWN_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.PURPLE_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.BLUE_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.GREEN_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.MAGENTA_DYE, 12, 16, 30), new VillagerTrades.EmeraldForItems(Items.CYAN_DYE, 12, 16, 30), new VillagerTrades.ItemsForEmeralds(Items.WHITE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.RED_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.PINK_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.GREEN_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.LIME_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.GRAY_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.BLACK_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.PURPLE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.MAGENTA_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.CYAN_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.BROWN_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.YELLOW_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.ORANGE_BANNER, 3, 1, 12, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_GRAY_BANNER, 3, 1, 12, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.PAINTING, 2, 3, 30)}))); - hashmap.put(VillagerProfession.FLETCHER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STICK, 32, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.ARROW, 1, 16, 1), new VillagerTrades.ItemsAndEmeraldsToItems(Blocks.GRAVEL, 10, Items.FLINT, 10, 12, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.FLINT, 26, 12, 10), new VillagerTrades.ItemsForEmeralds(Items.BOW, 2, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.STRING, 14, 16, 20), new VillagerTrades.ItemsForEmeralds(Items.CROSSBOW, 3, 1, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.FEATHER, 24, 16, 30), new VillagerTrades.EnchantedItemForEmeralds(Items.BOW, 2, 3, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.es, 8, 12, 30), new VillagerTrades.EnchantedItemForEmeralds(Items.CROSSBOW, 3, 3, 15), new VillagerTrades.TippedArrowForItemsAndEmeralds(Items.ARROW, 5, Items.TIPPED_ARROW, 5, 2, 12, 30)}))); -- hashmap.put(VillagerProfession.LIBRARIAN, toIntMap(ImmutableMap.builder().put(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PAPER, 24, 16, 2), new VillagerTrades.EnchantBookForEmeralds(1), new VillagerTrades.ItemsForEmeralds(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.BOOK, 4, 12, 10), new VillagerTrades.EnchantBookForEmeralds(5), new VillagerTrades.ItemsForEmeralds(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.INK_SAC, 5, 12, 20), new VillagerTrades.EnchantBookForEmeralds(10), new VillagerTrades.ItemsForEmeralds(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.EnchantBookForEmeralds(15), new VillagerTrades.ItemsForEmeralds(Items.CLOCK, 5, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.NAME_TAG, 20, 1, 30)}).build())); -+ hashmap.put(VillagerProfession.LIBRARIAN, toIntMap(ImmutableMap.builder().put(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PAPER, 24, 16, 2), new VillagerTrades.EnchantBookForEmeralds(1), new VillagerTrades.ItemsForEmeralds(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.BOOK, 4, 12, 10), new VillagerTrades.EnchantBookForEmeralds(5), new VillagerTrades.ItemsForEmeralds(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.INK_SAC, 5, 12, 20), new VillagerTrades.EnchantBookForEmeralds(10), new VillagerTrades.ItemsForEmeralds(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.EnchantBookForEmeralds(15), new VillagerTrades.ItemsForEmeralds(Items.CLOCK, 5, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.NAME_TAG, 20, 1, 30)}).build())); // Paper - add to ImmutableMap..builder() - hashmap.put(VillagerProfession.CARTOGRAPHER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.PAPER, 24, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.MAP, 7, 1, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.dP, 11, 16, 10), new VillagerTrades.TreasureMapForEmeralds(13, StructureFeature.OCEAN_MONUMENT, MapDecoration.Type.MONUMENT, 12, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COMPASS, 1, 12, 20), new VillagerTrades.TreasureMapForEmeralds(14, StructureFeature.WOODLAND_MANSION, MapDecoration.Type.MANSION, 12, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.ITEM_FRAME, 7, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.WHITE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.BLUE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_BLUE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.RED_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.PINK_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.GREEN_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.LIME_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.GRAY_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.BLACK_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.PURPLE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.MAGENTA_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.CYAN_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.BROWN_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.YELLOW_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.ORANGE_BANNER, 3, 1, 15), new VillagerTrades.ItemsForEmeralds(Items.LIGHT_GRAY_BANNER, 3, 1, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.ItemsForEmeralds(Items.GLOBE_BANNER_PATTERN, 8, 1, 30)}))); - hashmap.put(VillagerProfession.CLERIC, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.ROTTEN_FLESH, 32, 16, 2), new VillagerTrades.ItemsForEmeralds(Items.REDSTONE, 1, 2, 1)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.GOLD_INGOT, 3, 12, 10), new VillagerTrades.ItemsForEmeralds(Items.LAPIS_LAZULI, 1, 1, 5)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.RABBIT_FOOT, 2, 12, 20), new VillagerTrades.ItemsForEmeralds(Blocks.GLOWSTONE, 4, 1, 12, 10)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.SCUTE, 4, 12, 30), new VillagerTrades.EmeraldForItems(Items.GLASS_BOTTLE, 9, 12, 30), new VillagerTrades.ItemsForEmeralds(Items.ENDER_PEARL, 5, 1, 15)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.NETHER_WART, 22, 12, 30), new VillagerTrades.ItemsForEmeralds(Items.EXPERIENCE_BOTTLE, 3, 1, 30)}))); - hashmap.put(VillagerProfession.ARMORER, toIntMap(ImmutableMap.of(1, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.COAL, 15, 16, 2), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_LEGGINGS), 7, 1, 12, 1, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_BOOTS), 4, 1, 12, 1, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_HELMET), 5, 1, 12, 1, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.IRON_CHESTPLATE), 9, 1, 12, 1, 0.2F)}, 2, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.IRON_INGOT, 4, 12, 10), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.rj), 36, 1, 12, 5, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_BOOTS), 1, 1, 12, 5, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_LEGGINGS), 3, 1, 12, 5, 0.2F)}, 3, new VillagerTrades.ItemListing[]{new VillagerTrades.EmeraldForItems(Items.LAVA_BUCKET, 1, 12, 20), new VillagerTrades.EmeraldForItems(Items.DIAMOND, 1, 12, 20), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_HELMET), 1, 1, 12, 10, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.CHAINMAIL_CHESTPLATE), 4, 1, 12, 10, 0.2F), new VillagerTrades.ItemsForEmeralds(new ItemStack(Items.SHIELD), 5, 1, 12, 10, 0.2F)}, 4, new VillagerTrades.ItemListing[]{new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_LEGGINGS, 14, 3, 15, 0.2F), new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_BOOTS, 8, 3, 15, 0.2F)}, 5, new VillagerTrades.ItemListing[]{new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_HELMET, 8, 3, 30, 0.2F), new VillagerTrades.EnchantedItemForEmeralds(Items.DIAMOND_CHESTPLATE, 16, 3, 30, 0.2F)}))); -diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java -index 86d7af20fad04405f95c71e078d41070abdc43ad..c4777997cfff364818fbaee70afd7c79099213fb 100644 ---- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java -+++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java -@@ -75,7 +75,7 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { - } - - this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { -- return (entry1.getValue()); // CraftBukkit -+ return entry1.getValue(); // CraftBukkit // Paper - decompile fix - *shrugs internally* - })); - RecipeManager.LOGGER.info("Loaded {} recipes", map1.size()); - } -diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index 1276769b22ae21f0ff4271ecc72d4aa39ddff23f..7e7a58b9a9ececdcc37fc33b33703428eb1d5faf 100644 ---- a/src/main/java/net/minecraft/world/level/EntityGetter.java -+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -167,22 +167,22 @@ public interface EntityGetter { - - @Nullable - default T getNearestEntity(Class entityClass, TargetingConditions targetPredicate, @Nullable LivingEntity entity, double x, double y, double z, AABB box) { -- return this.getNearestEntity(this.getEntitiesOfClass(entityClass, box, (Predicate) null), targetPredicate, entity, x, y, z); -+ return this.getNearestEntity(this.getEntitiesOfClass(entityClass, box, null), targetPredicate, entity, x, y, z); // Paper - decompile fix - } - - @Nullable - default T getNearestLoadedEntity(Class entityClass, TargetingConditions targetPredicate, @Nullable LivingEntity entity, double x, double y, double z, AABB box) { -- return this.getNearestEntity(this.getLoadedEntitiesOfClass(entityClass, box, (Predicate) null), targetPredicate, entity, x, y, z); -+ return this.getNearestEntity(this.getLoadedEntitiesOfClass(entityClass, box, null), targetPredicate, entity, x, y, z); // Paper - decompile fix - } - - @Nullable - default T getNearestEntity(List entityList, TargetingConditions targetPredicate, @Nullable LivingEntity entity, double x, double y, double z) { - double d3 = -1.0D; - T t0 = null; -- Iterator iterator = entityList.iterator(); -+ Iterator iterator = entityList.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t1 = (LivingEntity) iterator.next(); -+ T t1 = iterator.next(); // Paper - decompile fix - - if (targetPredicate.test(entity, t1)) { - double d4 = t1.distanceToSqr(x, y, z); -@@ -215,10 +215,10 @@ public interface EntityGetter { - default List getNearbyEntities(Class entityClass, TargetingConditions targetPredicate, LivingEntity targetingEntity, AABB box) { - List list = this.getEntitiesOfClass(entityClass, box, (Predicate) null); - List list1 = Lists.newArrayList(); -- Iterator iterator = list.iterator(); -+ Iterator iterator = list.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t0 = (LivingEntity) iterator.next(); -+ T t0 = iterator.next(); // Paper - decompile fix - - if (targetPredicate.test(targetingEntity, t0)) { - list1.add(t0); -diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java -index c6e64c5182d564664464e26df27e6b5f7da418e6..d97e266b83bb331fcd4031046a5843d29ce53164 100644 ---- a/src/main/java/net/minecraft/world/level/TickNextTickData.java -+++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java -@@ -38,13 +38,13 @@ public class TickNextTickData { - return this.pos.hashCode(); - } - -- public static Comparator> createTimeComparator() { -+ public static Comparator createTimeComparator() { // Paper - decompile fix - return Comparator.comparingLong((nextticklistentry) -> { -- return nextticklistentry.b; -+ return ((TickNextTickData) nextticklistentry).triggerTick; // Paper - decompile fix - }).thenComparing((nextticklistentry) -> { -- return nextticklistentry.c; -+ return ((TickNextTickData) nextticklistentry).priority; // Paper - decompile fix - }).thenComparingLong((nextticklistentry) -> { -- return nextticklistentry.f; -+ return ((TickNextTickData) nextticklistentry).c; // Paper - decompile fix - }); - } - -diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java -index 79be56c26b66351bcfcd96c9967f0ce91e40d5ce..ed83335175bb882741dfaef251ab30ce1590f74c 100644 ---- a/src/main/java/net/minecraft/world/level/biome/Biome.java -+++ b/src/main/java/net/minecraft/world/level/biome/Biome.java -@@ -49,36 +49,43 @@ import org.apache.logging.log4j.Logger; - public final class Biome { - - public static final Logger LOGGER = LogManager.getLogger(); -+ // Paper start -+ private static class dProxy extends Biome.ClimateSettings { -+ private dProxy(Precipitation precipitation, float temperature, TemperatureModifier temperatureModifier, float downfall) { -+ super(precipitation, temperature, temperatureModifier, downfall); -+ } -+ }; -+ // Paper end - public static final Codec DIRECT_CODEC = RecordCodecBuilder.create((instance) -> { -- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { -- return biomebase.j; -+ return instance.group(dProxy.CODEC.forGetter((biomebase) -> { // Paper -+ return biomebase.climateSettings; - }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biomebase) -> { -- return biomebase.o; -+ return biomebase.biomeCategory; - }), Codec.FLOAT.fieldOf("depth").forGetter((biomebase) -> { -- return biomebase.m; -+ return biomebase.depth; - }), Codec.FLOAT.fieldOf("scale").forGetter((biomebase) -> { -- return biomebase.n; -+ return biomebase.scale; - }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biomebase) -> { -- return biomebase.p; -+ return biomebase.specialEffects; - }), BiomeGenerationSettings.CODEC.forGetter((biomebase) -> { -- return biomebase.k; -+ return biomebase.generationSettings; - }), MobSpawnSettings.CODEC.forGetter((biomebase) -> { -- return biomebase.l; -+ return biomebase.mobSettings; - })).apply(instance, Biome::new); - }); - public static final Codec NETWORK_CODEC = RecordCodecBuilder.create((instance) -> { -- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { -- return biomebase.j; -+ return instance.group(dProxy.CODEC.forGetter((biomebase) -> { // Paper -+ return biomebase.climateSettings; - }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biomebase) -> { -- return biomebase.o; -+ return biomebase.biomeCategory; - }), Codec.FLOAT.fieldOf("depth").forGetter((biomebase) -> { -- return biomebase.m; -+ return biomebase.depth; - }), Codec.FLOAT.fieldOf("scale").forGetter((biomebase) -> { -- return biomebase.n; -+ return biomebase.scale; - }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biomebase) -> { -- return biomebase.p; -+ return biomebase.specialEffects; - })).apply(instance, (biomebase_d, biomebase_geography, ofloat, ofloat1, biomefog) -> { -- return new BiomeBase(biomebase_d, biomebase_geography, ofloat, ofloat1, biomefog, BiomeSettingsGeneration.b, BiomeSettingsMobs.b); -+ return new Biome(biomebase_d, biomebase_geography, ofloat, ofloat1, biomefog, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY); - }); - }); - public static final Codec> CODEC = RegistryFileCodec.a(Registry.BIOME_REGISTRY, Biome.DIRECT_CODEC); -diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -index 94a02cb23a210ee0cc789db15853b6672ec673f4..73888713746e7ddd72ba9ac9d33d8e616eb3bd25 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -@@ -160,7 +160,7 @@ public class PistonMovingBlockEntity extends BlockEntity implements TickableBloc - private static void moveEntityByPiston(Direction enumdirection, Entity entity, double d0, Direction enumdirection1) { - PistonMovingBlockEntity.NOCLIP.set(enumdirection); - entity.move(MoverType.PISTON, new Vec3(d0 * (double) enumdirection1.getStepX(), d0 * (double) enumdirection1.getStepY(), d0 * (double) enumdirection1.getStepZ())); -- PistonMovingBlockEntity.NOCLIP.set((Object) null); -+ PistonMovingBlockEntity.NOCLIP.set(null); // Paper - decompile fix - } - - private void moveStuckEntities(float f) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java -index 95ad396fc46a587d08b87943aa05dd72d35efd3a..60ce75c7f94c995d3753c40bc8d1ec09b4d37b1a 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java -+++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java -@@ -28,12 +28,12 @@ public abstract class StateHolder { - } else { - Property iblockstate = (Property) entry.getKey(); - -- return iblockstate.getName() + "=" + this.getName(iblockstate, (Comparable) entry.getValue()); -+ return iblockstate.getName() + "=" + this.getName((Property) iblockstate, (Comparable) entry.getValue()); // Paper - decompile fix - } - } - -- private > String getName(Property property, Comparable value) { -- return property.value(value); -+ private > String getName(Property property, T value) { // Paper - decompile error -+ return property.getName(value); - } - }; - protected final O owner; -@@ -48,11 +48,11 @@ public abstract class StateHolder { - } - - public > S cycle(Property property) { -- return this.setValue(property, (Comparable) findNextInCollection(property.getPossibleValues(), (Object) this.getValue(property))); -+ return this.setValue(property, findNextInCollection(property.getPossibleValues(), this.getValue(property))); // Paper - decompile error - } - - protected static T findNextInCollection(Collection values, T value) { -- Iterator iterator = values.iterator(); -+ Iterator iterator = values.iterator(); // Paper - - do { - if (!iterator.hasNext()) { -@@ -94,7 +94,7 @@ public abstract class StateHolder { - if (comparable == null) { - throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner); - } else { -- return (Comparable) property.getValueClass().cast(comparable); -+ return property.getValueClass().cast(comparable); // Paper - decompile error - } - } - -@@ -110,7 +110,7 @@ public abstract class StateHolder { - if (comparable == null) { - throw new IllegalArgumentException("Cannot set property " + property + " as it does not exist in " + this.owner); - } else if (comparable == value) { -- return this; -+ return (S) this; // Paper - decompile error - } else { - S s0 = this.neighbours.get(property, value); - -@@ -162,7 +162,7 @@ public abstract class StateHolder { - return codec.dispatch("Name", (iblockdataholder) -> { - return iblockdataholder.owner; - }, (object) -> { -- S s0 = (StateHolder) ownerToStateFunction.apply(object); -+ S s0 = ownerToStateFunction.apply(object); // Paper - decompile error - - return s0.getValues().isEmpty() ? Codec.unit(s0) : s0.propertiesCodec.fieldOf("Properties").codec(); - }); -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java -index 9e0724c4bf06d207898e477e35412c09f3aa0f74..b5817645727f2af2785e0987ba824f431d4e9e32 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java -@@ -21,10 +21,10 @@ public class EnumProperty & StringRepresentable> extends Prope - protected EnumProperty(String name, Class type, Collection values) { - super(name, type); - this.values = ImmutableSet.copyOf(values); -- Iterator iterator = values.iterator(); -+ Iterator iterator = values.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t0 = (Enum) iterator.next(); -+ T t0 = iterator.next(); // Paper - Decompile fix - String s1 = ((StringRepresentable) t0).getSerializedName(); - - if (this.names.containsKey(s1)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java -index 5a16a0079bc297fb4572d2e6e9b07a9d1a53c906..8cc07c70fde81e44679f3ea7d9a4c6b2447885d4 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java -@@ -17,12 +17,10 @@ public abstract class Property> { - private final Codec> valueCodec; - - protected Property(String name, Class type) { -- this.codec = Codec.STRING.comapFlatMap((s1) -> { -- return (DataResult) this.getValue(s1).map(DataResult::success).orElseGet(() -> { -- return DataResult.error("Unable to read property: " + this + " with value: " + s1); -- }); -- }, this::getName); -- this.valueCodec = this.codec.xmap(this::b, Property.clazz::b); -+ this.codec = Codec.STRING.comapFlatMap((s1) -> this.getValue(s1).map(DataResult::success).orElseGet(() -> { // Paper - decompile error -+ return DataResult.error("Unable to read property: " + this + " with value: " + s1); -+ }), this::getName); -+ this.valueCodec = this.codec.xmap(this::value, (Property.Value param) -> param.value()); // Paper - decompile fix - this.clazz = type; - this.name = name; - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -index 977ac6db5fbdd001c306ee6aa396bb395384dd8f..7de765786b3504dcffab98bb0d9dac64b30b3325 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -@@ -89,7 +89,7 @@ public class IOWorker implements AutoCloseable { - return this.submitTask(() -> { - try { - this.storage.flush(); -- return Either.left((Object) null); -+ return Either.left(null); // Paper - decompile error - } catch (Exception exception) { - IOWorker.LOGGER.warn("Failed to synchronized chunks", exception); - return Either.right(exception); -@@ -123,13 +123,13 @@ public class IOWorker implements AutoCloseable { - } - - private void tellStorePending() { -- this.mailbox.tell((Object) (new StrictQueue.IntRunnable(IOWorker.Priority.LOW.ordinal(), this::storePendingChunk))); -+ this.mailbox.tell((new StrictQueue.IntRunnable(IOWorker.Priority.LOW.ordinal(), this::storePendingChunk))); // Paper - decompile error - } - - private void runStore(ChunkPos pos, IOWorker.PendingStore ioworker_a) { - try { - this.storage.write(pos, ioworker_a.data); -- ioworker_a.result.complete((Object) null); -+ ioworker_a.result.complete(null); // Paper - decompile fix - } catch (Exception exception) { - IOWorker.LOGGER.error("Failed to store chunk {}", pos, exception); - ioworker_a.result.completeExceptionally(exception); -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 217065b88178342159154490ffabe0fe7d32d7bf..2386ffeec60851ba192b89bc6fd7ffff9c56aff5 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -430,7 +430,7 @@ public class EndDragonFight { - } - } - -- worldgenendtrophy.configured((FeatureConfiguration) FeatureConfiguration.NONE).a(this.level, this.level.getChunkSource().getGenerator(), new Random(), this.portalLocation); -+ worldgenendtrophy.configured(FeatureConfiguration.NONE).place(this.level, this.level.getChunkSource().getGenerator(), new Random(), this.portalLocation); // Paper - decompile fix - } - - private EnderDragon createNewDragon() { -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -index 418abfdc85de157d23807059670a2dfc964cbd5f..9f60abfe0a37e30c5528a1ca0546295b00598798 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -@@ -71,13 +71,13 @@ public abstract class StructureFeature { - public static final StructureFeature BASTION_REMNANT = register("Bastion_Remnant", new BastionFeature(JigsawConfiguration.CODEC), GenerationStep.Decoration.SURFACE_STRUCTURES); - public static final List> NOISE_AFFECTING_FEATURES = ImmutableList.of(StructureFeature.PILLAGER_OUTPOST, StructureFeature.VILLAGE, StructureFeature.NETHER_FOSSIL); - private static final ResourceLocation JIGSAW_RENAME = new ResourceLocation("jigsaw"); -- private static final Map RENAMES = ImmutableMap.builder().put(new ResourceLocation("nvi"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("pcp"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("bastionremnant"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("runtime"), StructureFeature.JIGSAW_RENAME).build(); -+ private static final Map RENAMES = ImmutableMap.builder().put(new ResourceLocation("nvi"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("pcp"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("bastionremnant"), StructureFeature.JIGSAW_RENAME).put(new ResourceLocation("runtime"), StructureFeature.JIGSAW_RENAME).build(); // Paper - decompile fix - private final Codec>> y; - - private static > F register(String name, F structureFeature, GenerationStep.Decoration step) { - StructureFeature.STRUCTURES_REGISTRY.put(name.toLowerCase(Locale.ROOT), structureFeature); - StructureFeature.STEP.put(structureFeature, step); -- return (StructureFeature) Registry.registerDefaulted(Registry.STRUCTURE_FEATURE, name.toLowerCase(Locale.ROOT), (Object) structureFeature); -+ return (F) Registry.>register(Registry.STRUCTURE_FEATURE, name.toLowerCase(Locale.ROOT), structureFeature); // Paper - decomp fix - } - - public StructureFeature(Codec codec) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -index cd2efdd5802605de5d3d636ce1b4a796e0c13310..c304637ae8f80c65b58e8ba8a27609b532bb1184 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -@@ -34,10 +34,10 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage= l) { -diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -index b106f2458361fc2a9168bbef8c9e5b35d8e359fb..60b7fdf9c092e8105d41f4af02a08651624f3eb9 100644 ---- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -+++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -@@ -44,7 +44,7 @@ public class DimensionDataStorage { - if (t0 != null) { - return t0; - } else { -- T t1 = (SavedData) factory.get(); -+ T t1 = factory.get(); // Paper - decompile fix - - this.set(t1); - return t1; -@@ -53,7 +53,7 @@ public class DimensionDataStorage { - - @Nullable - public T get(Supplier factory, String id) { -- SavedData persistentbase = (SavedData) this.cache.get(id); -+ T persistentbase = (T) this.cache.get(id); // Paper - decompile fix - - if (persistentbase == null && !this.cache.containsKey(id)) { - persistentbase = this.readSavedData(factory, id); -@@ -69,7 +69,7 @@ public class DimensionDataStorage { - File file = this.getDataFile(id); - - if (file.exists()) { -- T t0 = (SavedData) factory.get(); -+ T t0 = factory.get(); // Paper - decompile fix - CompoundTag nbttagcompound = this.readTagFromDisk(id, SharedConstants.getCurrentVersion().getWorldVersion()); - - t0.load(nbttagcompound.getCompound("data")); -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java -index 4093a4a1f924ac722d60599be9688a88d26a5c1a..802eb7fe690adae03c80db3fc0f72ea2788a3b2c 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java -@@ -42,7 +42,7 @@ public abstract class LootPoolEntryContainer implements ComposableEntryContainer - - // CraftBukkit start - @Override -- public final void serialize(JsonObject json, T entry, JsonSerializationContext context) { -+ public void serialize(JsonObject json, T entry, JsonSerializationContext context) { // Paper - remove final - if (!org.apache.commons.lang3.ArrayUtils.isEmpty(entry.conditions)) { - json.add("conditions", context.serialize(entry.conditions)); - } -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java -index c942459e0a492dd9fab296ef60d272651d13f049..ceb5e5405ed20c8de954847bbb269109107a43fc 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java -@@ -132,7 +132,7 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer - @Override - public T b(LootItemFunction.Builder lootitemfunction_a) { - this.functions.add(lootitemfunction_a.b()); -- return (LootPoolSingletonContainer.Builder) this.getThis(); -+ return this.getThis(); // Paper - decompile fix - } - - protected LootItemFunction[] getFunctions() { -@@ -141,12 +141,12 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer - - public T setWeight(int weight) { - this.weight = weight; -- return (LootPoolSingletonContainer.Builder) this.getThis(); -+ return this.getThis(); // Paper - decompile fix - } - - public T setQuality(int quality) { - this.quality = quality; -- return (LootPoolSingletonContainer.Builder) this.getThis(); -+ return this.getThis(); // Paper - decompile fix - } - } - -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java -index b77c921548ff55bab62bf37fa411ad1fd8d38f82..a3ce120b0da62f9be938c58c3414ce997f5d30ea 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java -@@ -89,7 +89,7 @@ public class ExplorationMapFunction extends LootItemConditionalFunction { - public Serializer() {} - - public void serialize(JsonObject json, ExplorationMapFunction object, JsonSerializationContext context) { -- super.serialize(json, (LootItemConditionalFunction) object, context); -+ super.serialize(json, object, context); // Paper - decompile fix - if (!object.destination.equals(ExplorationMapFunction.DEFAULT_FEATURE)) { - json.add("destination", context.serialize(object.destination.getFeatureName())); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java -index bc1798f130184d6b107d7a9ba972cab686534439..f0e74daa5bb9e88c028225e7c71deb04c481a7ac 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java -@@ -38,7 +38,7 @@ public final class IndirectMerger implements IndexMerger { - double d1 = flag4 ? first.getDouble(i++) : second.getDouble(j++); - - if ((i != 0 && flag2 || flag4 || includeSecondOnly) && (j != 0 && flag3 || !flag4 || includeFirstOnly)) { -- if (d0 < d1 - 1.0E-7D) { -+ if (!(d0 >= d1 - 1.0E-7D)) { // Paper - decompile error - welcome to hell - this.firstIndices.add(i - 1); - this.secondIndices.add(j - 1); - this.result.add(d1); diff --git a/Remapped-Spigot-Server-Patches/0004-MC-Utils.patch b/Remapped-Spigot-Server-Patches/0004-MC-Utils.patch deleted file mode 100644 index cccd5824cd..0000000000 --- a/Remapped-Spigot-Server-Patches/0004-MC-Utils.patch +++ /dev/null @@ -1,4859 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:55:47 -0400 -Subject: [PATCH] MC Utils - - -diff --git a/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4029dc68cf35d63aa70c4a76c35bf65a7fc6358f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java -@@ -0,0 +1,68 @@ -+package com.destroystokyo.paper.util.concurrent; -+ -+import java.util.concurrent.atomic.AtomicLong; -+ -+/** -+ * copied from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/lock/WeakSeqLock.java -+ * @author Spottedleaf -+ */ -+public final class WeakSeqLock { -+ // TODO when the switch to J11 is made, nuke this class from orbit -+ -+ protected final AtomicLong lock = new AtomicLong(); -+ -+ public WeakSeqLock() { -+ //VarHandle.storeStoreFence(); // warn: usages must be checked to ensure this behaviour isn't needed -+ } -+ -+ public void acquireWrite() { -+ // must be release-type write -+ this.lock.lazySet(this.lock.get() + 1); -+ } -+ -+ public boolean canRead(final long read) { -+ return (read & 1) == 0; -+ } -+ -+ public boolean tryAcquireWrite() { -+ this.acquireWrite(); -+ return true; -+ } -+ -+ public void releaseWrite() { -+ // must be acquire-type write -+ final long lock = this.lock.get(); // volatile here acts as store-store -+ this.lock.lazySet(lock + 1); -+ } -+ -+ public void abortWrite() { -+ // must be acquire-type write -+ final long lock = this.lock.get(); // volatile here acts as store-store -+ this.lock.lazySet(lock ^ 1); -+ } -+ -+ public long acquireRead() { -+ int failures = 0; -+ long curr; -+ -+ for (curr = this.lock.get(); !this.canRead(curr); curr = this.lock.get()) { -+ // without j11, our only backoff is the yield() call... -+ -+ if (++failures > 5_000) { /* TODO determine a threshold */ -+ Thread.yield(); -+ } -+ /* Better waiting is beyond the scope of this lock; if it is needed the lock is being misused */ -+ } -+ -+ //VarHandle.loadLoadFence(); // volatile acts as the load-load barrier -+ return curr; -+ } -+ -+ public boolean tryReleaseRead(final long read) { -+ return this.lock.get() == read; // volatile acts as the load-load barrier -+ } -+ -+ public long getSequentialCounter() { -+ return this.lock.get(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java -new file mode 100644 -index 0000000000000000000000000000000000000000..59868f37d14bbc0ece0836095cdad148778995e6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java -@@ -0,0 +1,162 @@ -+package com.destroystokyo.paper.util.map; -+ -+import com.destroystokyo.paper.util.concurrent.WeakSeqLock; -+import it.unimi.dsi.fastutil.longs.Long2IntMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import it.unimi.dsi.fastutil.longs.LongIterator; -+import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -+import it.unimi.dsi.fastutil.objects.ObjectIterator; -+ -+/** -+ * @author Spottedleaf -+ */ -+public class QueuedChangesMapLong2Int { -+ -+ protected final Long2IntOpenHashMap updatingMap; -+ protected final Long2IntOpenHashMap visibleMap; -+ protected final Long2IntOpenHashMap queuedPuts; -+ protected final LongOpenHashSet queuedRemove; -+ -+ protected int queuedDefaultReturnValue; -+ -+ // we use a seqlock as writes are not common. -+ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); -+ -+ public QueuedChangesMapLong2Int() { -+ this(16, 0.75f); -+ } -+ -+ public QueuedChangesMapLong2Int(final int capacity, final float loadFactor) { -+ this.updatingMap = new Long2IntOpenHashMap(capacity, loadFactor); -+ this.visibleMap = new Long2IntOpenHashMap(capacity, loadFactor); -+ this.queuedPuts = new Long2IntOpenHashMap(); -+ this.queuedRemove = new LongOpenHashSet(); -+ } -+ -+ public void queueDefaultReturnValue(final int dfl) { -+ this.queuedDefaultReturnValue = dfl; -+ this.updatingMap.defaultReturnValue(dfl); -+ } -+ -+ public int queueUpdate(final long k, final int v) { -+ this.queuedRemove.remove(k); -+ this.queuedPuts.put(k, v); -+ -+ return this.updatingMap.put(k, v); -+ } -+ -+ public int queueRemove(final long k) { -+ this.queuedPuts.remove(k); -+ this.queuedRemove.add(k); -+ -+ return this.updatingMap.remove(k); -+ } -+ -+ public int getUpdating(final long k) { -+ return this.updatingMap.get(k); -+ } -+ -+ public int getVisible(final long k) { -+ return this.visibleMap.get(k); -+ } -+ -+ public int getVisibleAsync(final long k) { -+ long readlock; -+ int ret = 0; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ try { -+ ret = this.visibleMap.get(k); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // ignore... -+ continue; -+ } -+ -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ public boolean performUpdates() { -+ this.updatingMapSeqLock.acquireWrite(); -+ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); -+ this.updatingMapSeqLock.releaseWrite(); -+ -+ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { -+ return false; -+ } -+ -+ // update puts -+ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); -+ while (iterator0.hasNext()) { -+ final Long2IntMap.Entry entry = iterator0.next(); -+ final long key = entry.getLongKey(); -+ final int val = entry.getIntValue(); -+ -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ this.visibleMap.put(key, val); -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+ -+ this.queuedPuts.clear(); -+ -+ final LongIterator iterator1 = this.queuedRemove.iterator(); -+ while (iterator1.hasNext()) { -+ final long key = iterator1.nextLong(); -+ -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ this.visibleMap.remove(key); -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+ -+ this.queuedRemove.clear(); -+ -+ return true; -+ } -+ -+ public boolean performUpdatesLockMap() { -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); -+ -+ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { -+ return false; -+ } -+ -+ // update puts -+ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); -+ while (iterator0.hasNext()) { -+ final Long2IntMap.Entry entry = iterator0.next(); -+ final long key = entry.getLongKey(); -+ final int val = entry.getIntValue(); -+ -+ this.visibleMap.put(key, val); -+ } -+ -+ this.queuedPuts.clear(); -+ -+ final LongIterator iterator1 = this.queuedRemove.iterator(); -+ while (iterator1.hasNext()) { -+ final long key = iterator1.nextLong(); -+ -+ this.visibleMap.remove(key); -+ } -+ -+ this.queuedRemove.clear(); -+ -+ return true; -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7bab31a312463cc963d9621cdc543a281459bd32 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java -@@ -0,0 +1,202 @@ -+package com.destroystokyo.paper.util.map; -+ -+import com.destroystokyo.paper.util.concurrent.WeakSeqLock; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator; -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.List; -+ -+/** -+ * @author Spottedleaf -+ */ -+public class QueuedChangesMapLong2Object { -+ -+ protected static final Object REMOVED = new Object(); -+ -+ protected final Long2ObjectLinkedOpenHashMap updatingMap; -+ protected final Long2ObjectLinkedOpenHashMap visibleMap; -+ protected final Long2ObjectLinkedOpenHashMap queuedChanges; -+ -+ // we use a seqlock as writes are not common. -+ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); -+ -+ public QueuedChangesMapLong2Object() { -+ this(16, 0.75f); // dfl for fastutil -+ } -+ -+ public QueuedChangesMapLong2Object(final int capacity, final float loadFactor) { -+ this.updatingMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); -+ this.visibleMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); -+ this.queuedChanges = new Long2ObjectLinkedOpenHashMap<>(); -+ } -+ -+ public V queueUpdate(final long k, final V value) { -+ this.queuedChanges.put(k, value); -+ return this.updatingMap.put(k, value); -+ } -+ -+ public V queueRemove(final long k) { -+ this.queuedChanges.put(k, REMOVED); -+ return this.updatingMap.remove(k); -+ } -+ -+ public V getUpdating(final long k) { -+ return this.updatingMap.get(k); -+ } -+ -+ public boolean updatingContainsKey(final long k) { -+ return this.updatingMap.containsKey(k); -+ } -+ -+ public V getVisible(final long k) { -+ return this.visibleMap.get(k); -+ } -+ -+ public boolean visibleContainsKey(final long k) { -+ return this.visibleMap.containsKey(k); -+ } -+ -+ public V getVisibleAsync(final long k) { -+ long readlock; -+ V ret = null; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ -+ try { -+ ret = this.visibleMap.get(k); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // ignore... -+ continue; -+ } -+ -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ public boolean visibleContainsKeyAsync(final long k) { -+ long readlock; -+ boolean ret = false; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ -+ try { -+ ret = this.visibleMap.containsKey(k); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // ignore... -+ continue; -+ } -+ -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ public Long2ObjectLinkedOpenHashMap getVisibleMap() { -+ return this.visibleMap; -+ } -+ -+ public Long2ObjectLinkedOpenHashMap getUpdatingMap() { -+ return this.updatingMap; -+ } -+ -+ public int getVisibleSize() { -+ return this.visibleMap.size(); -+ } -+ -+ public int getVisibleSizeAsync() { -+ long readlock; -+ int ret; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ ret = this.visibleMap.size(); -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map -+ public Collection getUpdatingValues() { -+ return this.updatingMap.values(); -+ } -+ -+ public List getUpdatingValuesCopy() { -+ return new ArrayList<>(this.updatingMap.values()); -+ } -+ -+ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map -+ public Collection getVisibleValues() { -+ return this.visibleMap.values(); -+ } -+ -+ public List getVisibleValuesCopy() { -+ return new ArrayList<>(this.visibleMap.values()); -+ } -+ -+ public boolean performUpdates() { -+ if (this.queuedChanges.isEmpty()) { -+ return false; -+ } -+ -+ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); -+ while (iterator.hasNext()) { -+ final Long2ObjectMap.Entry entry = iterator.next(); -+ final long key = entry.getLongKey(); -+ final Object val = entry.getValue(); -+ -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ if (val == REMOVED) { -+ this.visibleMap.remove(key); -+ } else { -+ this.visibleMap.put(key, (V)val); -+ } -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+ -+ this.queuedChanges.clear(); -+ return true; -+ } -+ -+ public boolean performUpdatesLockMap() { -+ if (this.queuedChanges.isEmpty()) { -+ return false; -+ } -+ -+ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); -+ -+ try { -+ this.updatingMapSeqLock.acquireWrite(); -+ -+ while (iterator.hasNext()) { -+ final Long2ObjectMap.Entry entry = iterator.next(); -+ final long key = entry.getLongKey(); -+ final Object val = entry.getValue(); -+ -+ if (val == REMOVED) { -+ this.visibleMap.remove(key); -+ } else { -+ this.visibleMap.put(key, (V)val); -+ } -+ } -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ -+ this.queuedChanges.clear(); -+ return true; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..554f4d4e63c1431721989e6f502a32ccc53a8807 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java -@@ -0,0 +1,128 @@ -+package com.destroystokyo.paper.util.maplist; -+ -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import java.util.Arrays; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+import net.minecraft.world.level.chunk.LevelChunk; -+ -+// list with O(1) remove & contains -+/** -+ * @author Spottedleaf -+ */ -+public final class ChunkList implements Iterable { -+ -+ protected final Long2IntOpenHashMap chunkToIndex = new Long2IntOpenHashMap(2, 0.8f); -+ { -+ this.chunkToIndex.defaultReturnValue(Integer.MIN_VALUE); -+ } -+ -+ protected static final LevelChunk[] EMPTY_LIST = new LevelChunk[0]; -+ -+ protected LevelChunk[] chunks = EMPTY_LIST; -+ protected int count; -+ -+ public int size() { -+ return this.count; -+ } -+ -+ public boolean contains(final LevelChunk chunk) { -+ return this.chunkToIndex.containsKey(chunk.coordinateKey); -+ } -+ -+ public boolean remove(final LevelChunk chunk) { -+ final int index = this.chunkToIndex.remove(chunk.coordinateKey); -+ if (index == Integer.MIN_VALUE) { -+ return false; -+ } -+ -+ // move the entity at the end to this index -+ final int endIndex = --this.count; -+ final LevelChunk end = this.chunks[endIndex]; -+ if (index != endIndex) { -+ // not empty after this call -+ this.chunkToIndex.put(end.coordinateKey, index); // update index -+ } -+ this.chunks[index] = end; -+ this.chunks[endIndex] = null; -+ -+ return true; -+ } -+ -+ public boolean add(final LevelChunk chunk) { -+ final int count = this.count; -+ final int currIndex = this.chunkToIndex.putIfAbsent(chunk.coordinateKey, count); -+ -+ if (currIndex != Integer.MIN_VALUE) { -+ return false; // already in this list -+ } -+ -+ LevelChunk[] list = this.chunks; -+ -+ if (list.length == count) { -+ // resize required -+ list = this.chunks = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative -+ } -+ -+ list[count] = chunk; -+ this.count = count + 1; -+ -+ return true; -+ } -+ -+ public LevelChunk getChecked(final int index) { -+ if (index < 0 || index >= this.count) { -+ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); -+ } -+ return this.chunks[index]; -+ } -+ -+ public LevelChunk getUnchecked(final int index) { -+ return this.chunks[index]; -+ } -+ -+ public LevelChunk[] getRawData() { -+ return this.chunks; -+ } -+ -+ public void clear() { -+ this.chunkToIndex.clear(); -+ Arrays.fill(this.chunks, 0, this.count, null); -+ this.count = 0; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator() { -+ -+ LevelChunk lastRet; -+ int current; -+ -+ @Override -+ public boolean hasNext() { -+ return this.current < ChunkList.this.count; -+ } -+ -+ @Override -+ public LevelChunk next() { -+ if (this.current >= ChunkList.this.count) { -+ throw new NoSuchElementException(); -+ } -+ return this.lastRet = ChunkList.this.chunks[this.current++]; -+ } -+ -+ @Override -+ public void remove() { -+ final LevelChunk lastRet = this.lastRet; -+ -+ if (lastRet == null) { -+ throw new IllegalStateException(); -+ } -+ this.lastRet = null; -+ -+ ChunkList.this.remove(lastRet); -+ --this.current; -+ } -+ }; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0133ea6feb1ab88f021f66855669f58367e7420b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java -@@ -0,0 +1,128 @@ -+package com.destroystokyo.paper.util.maplist; -+ -+import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -+import net.minecraft.world.entity.Entity; -+import java.util.Arrays; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+ -+// list with O(1) remove & contains -+/** -+ * @author Spottedleaf -+ */ -+public final class EntityList implements Iterable { -+ -+ protected final Int2IntOpenHashMap entityToIndex = new Int2IntOpenHashMap(2, 0.8f); -+ { -+ this.entityToIndex.defaultReturnValue(Integer.MIN_VALUE); -+ } -+ -+ protected static final Entity[] EMPTY_LIST = new Entity[0]; -+ -+ protected Entity[] entities = EMPTY_LIST; -+ protected int count; -+ -+ public int size() { -+ return this.count; -+ } -+ -+ public boolean contains(final Entity entity) { -+ return this.entityToIndex.containsKey(entity.getId()); -+ } -+ -+ public boolean remove(final Entity entity) { -+ final int index = this.entityToIndex.remove(entity.getId()); -+ if (index == Integer.MIN_VALUE) { -+ return false; -+ } -+ -+ // move the entity at the end to this index -+ final int endIndex = --this.count; -+ final Entity end = this.entities[endIndex]; -+ if (index != endIndex) { -+ // not empty after this call -+ this.entityToIndex.put(end.getId(), index); // update index -+ } -+ this.entities[index] = end; -+ this.entities[endIndex] = null; -+ -+ return true; -+ } -+ -+ public boolean add(final Entity entity) { -+ final int count = this.count; -+ final int currIndex = this.entityToIndex.putIfAbsent(entity.getId(), count); -+ -+ if (currIndex != Integer.MIN_VALUE) { -+ return false; // already in this list -+ } -+ -+ Entity[] list = this.entities; -+ -+ if (list.length == count) { -+ // resize required -+ list = this.entities = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative -+ } -+ -+ list[count] = entity; -+ this.count = count + 1; -+ -+ return true; -+ } -+ -+ public Entity getChecked(final int index) { -+ if (index < 0 || index >= this.count) { -+ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); -+ } -+ return this.entities[index]; -+ } -+ -+ public Entity getUnchecked(final int index) { -+ return this.entities[index]; -+ } -+ -+ public Entity[] getRawData() { -+ return this.entities; -+ } -+ -+ public void clear() { -+ this.entityToIndex.clear(); -+ Arrays.fill(this.entities, 0, this.count, null); -+ this.count = 0; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator() { -+ -+ Entity lastRet; -+ int current; -+ -+ @Override -+ public boolean hasNext() { -+ return this.current < EntityList.this.count; -+ } -+ -+ @Override -+ public Entity next() { -+ if (this.current >= EntityList.this.count) { -+ throw new NoSuchElementException(); -+ } -+ return this.lastRet = EntityList.this.entities[this.current++]; -+ } -+ -+ @Override -+ public void remove() { -+ final Entity lastRet = this.lastRet; -+ -+ if (lastRet == null) { -+ throw new IllegalStateException(); -+ } -+ this.lastRet = null; -+ -+ EntityList.this.remove(lastRet); -+ --this.current; -+ } -+ }; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..abe7f2f13ab713bf1cb0343059377ab7e1b48b6e ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java -@@ -0,0 +1,128 @@ -+package com.destroystokyo.paper.util.maplist; -+ -+import it.unimi.dsi.fastutil.longs.LongIterator; -+import it.unimi.dsi.fastutil.shorts.Short2LongOpenHashMap; -+import java.util.Arrays; -+import net.minecraft.world.level.block.state.BlockState; -+import net.minecraft.world.level.chunk.GlobalPalette; -+import net.minecraft.world.level.chunk.LevelChunkSection; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class IBlockDataList { -+ -+ static final GlobalPalette GLOBAL_PALETTE = (GlobalPalette) LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE; -+ -+ // map of location -> (index | (location << 16) | (palette id << 32)) -+ private final Short2LongOpenHashMap map = new Short2LongOpenHashMap(2, 0.8f); -+ { -+ this.map.defaultReturnValue(Long.MAX_VALUE); -+ } -+ -+ private static final long[] EMPTY_LIST = new long[0]; -+ -+ private long[] byIndex = EMPTY_LIST; -+ private int size; -+ -+ public static int getLocationKey(final int x, final int y, final int z) { -+ return (x & 15) | (((z & 15) << 4)) | ((y & 255) << (4 + 4)); -+ } -+ -+ public static BlockState getBlockDataFromRaw(final long raw) { -+ return GLOBAL_PALETTE.getObject((int)(raw >>> 32)); -+ } -+ -+ public static int getIndexFromRaw(final long raw) { -+ return (int)(raw & 0xFFFF); -+ } -+ -+ public static int getLocationFromRaw(final long raw) { -+ return (int)((raw >>> 16) & 0xFFFF); -+ } -+ -+ public static long getRawFromValues(final int index, final int location, final BlockState data) { -+ return (long)index | ((long)location << 16) | (((long)GLOBAL_PALETTE.getOrCreateIdFor(data)) << 32); -+ } -+ -+ public static long setIndexRawValues(final long value, final int index) { -+ return value & ~(0xFFFF) | (index); -+ } -+ -+ public long add(final int x, final int y, final int z, final BlockState data) { -+ return this.add(getLocationKey(x, y, z), data); -+ } -+ -+ public long add(final int location, final BlockState data) { -+ final long curr = this.map.get((short)location); -+ -+ if (curr == Long.MAX_VALUE) { -+ final int index = this.size++; -+ final long raw = getRawFromValues(index, location, data); -+ this.map.put((short)location, raw); -+ -+ if (index >= this.byIndex.length) { -+ this.byIndex = Arrays.copyOf(this.byIndex, (int)Math.max(4L, this.byIndex.length * 2L)); -+ } -+ -+ this.byIndex[index] = raw; -+ return raw; -+ } else { -+ final int index = getIndexFromRaw(curr); -+ final long raw = this.byIndex[index] = getRawFromValues(index, location, data); -+ -+ this.map.put((short)location, raw); -+ -+ return raw; -+ } -+ } -+ -+ public long remove(final int x, final int y, final int z) { -+ return this.remove(getLocationKey(x, y, z)); -+ } -+ -+ public long remove(final int location) { -+ final long ret = this.map.remove((short)location); -+ final int index = getIndexFromRaw(ret); -+ if (ret == Long.MAX_VALUE) { -+ return ret; -+ } -+ -+ // move the entry at the end to this index -+ final int endIndex = --this.size; -+ final long end = this.byIndex[endIndex]; -+ if (index != endIndex) { -+ // not empty after this call -+ this.map.put((short)getLocationFromRaw(end), setIndexRawValues(end, index)); -+ } -+ this.byIndex[index] = end; -+ this.byIndex[endIndex] = 0L; -+ -+ return ret; -+ } -+ -+ public int size() { -+ return this.size; -+ } -+ -+ public long getRaw(final int index) { -+ return this.byIndex[index]; -+ } -+ -+ public int getLocation(final int index) { -+ return getLocationFromRaw(this.getRaw(index)); -+ } -+ -+ public BlockState getData(final int index) { -+ return getBlockDataFromRaw(this.getRaw(index)); -+ } -+ -+ public void clear() { -+ this.size = 0; -+ this.map.clear(); -+ } -+ -+ public LongIterator getRawIterator() { -+ return this.map.values().iterator(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c3b936f54b3fff418c265639ef223292ccc89356 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java -@@ -0,0 +1,230 @@ -+package com.destroystokyo.paper.util.math; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class IntegerUtil { -+ -+ public static final int HIGH_BIT_U32 = Integer.MIN_VALUE; -+ public static final long HIGH_BIT_U64 = Long.MIN_VALUE; -+ -+ public static int ceilLog2(final int value) { -+ return Integer.SIZE - Integer.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros -+ } -+ -+ public static long ceilLog2(final long value) { -+ return Long.SIZE - Long.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros -+ } -+ -+ public static int floorLog2(final int value) { -+ // xor is optimized subtract for 2^n -1 -+ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) -+ return (Integer.SIZE - 1) ^ Integer.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros -+ } -+ -+ public static int floorLog2(final long value) { -+ // xor is optimized subtract for 2^n -1 -+ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) -+ return (Long.SIZE - 1) ^ Long.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros -+ } -+ -+ public static int roundCeilLog2(final int value) { -+ // optimized variant of 1 << (32 - leading(val - 1)) -+ // given -+ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) -+ // 1 << (32 - leading(val - 1)) = HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) -+ // HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) -+ // HIGH_BIT_32 >>> (31 - 32 + leading(val - 1)) -+ // HIGH_BIT_32 >>> (-1 + leading(val - 1)) -+ return HIGH_BIT_U32 >>> (Integer.numberOfLeadingZeros(value - 1) - 1); -+ } -+ -+ public static long roundCeilLog2(final long value) { -+ // see logic documented above -+ return HIGH_BIT_U64 >>> (Long.numberOfLeadingZeros(value - 1) - 1); -+ } -+ -+ public static int roundFloorLog2(final int value) { -+ // optimized variant of 1 << (31 - leading(val)) -+ // given -+ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) -+ // 1 << (31 - leading(val)) = HIGH_BIT_32 >> (31 - (31 - leading(val))) -+ // HIGH_BIT_32 >> (31 - (31 - leading(val))) -+ // HIGH_BIT_32 >> (31 - 31 + leading(val)) -+ return HIGH_BIT_U32 >>> Integer.numberOfLeadingZeros(value); -+ } -+ -+ public static long roundFloorLog2(final long value) { -+ // see logic documented above -+ return HIGH_BIT_U64 >>> Long.numberOfLeadingZeros(value); -+ } -+ -+ public static boolean isPowerOfTwo(final int n) { -+ // 2^n has one bit -+ // note: this rets true for 0 still -+ return IntegerUtil.getTrailingBit(n) == n; -+ } -+ -+ public static boolean isPowerOfTwo(final long n) { -+ // 2^n has one bit -+ // note: this rets true for 0 still -+ return IntegerUtil.getTrailingBit(n) == n; -+ } -+ -+ -+ public static int getTrailingBit(final int n) { -+ return -n & n; -+ } -+ -+ public static long getTrailingBit(final long n) { -+ return -n & n; -+ } -+ -+ public static int trailingZeros(final int n) { -+ return Integer.numberOfTrailingZeros(n); -+ } -+ -+ public static long trailingZeros(final long n) { -+ return Long.numberOfTrailingZeros(n); -+ } -+ -+ // from hacker's delight (signed division magic value) -+ public static int getDivisorMultiple(final long numbers) { -+ return (int)(numbers >>> 32); -+ } -+ -+ // from hacker's delight (signed division magic value) -+ public static int getDivisorShift(final long numbers) { -+ return (int)numbers; -+ } -+ -+ // copied from hacker's delight (signed division magic value) -+ // http://www.hackersdelight.org/hdcodetxt/magic.c.txt -+ public static long getDivisorNumbers(final int d) { -+ final int ad = IntegerUtil.branchlessAbs(d); -+ -+ if (ad < 2) { -+ throw new IllegalArgumentException("|number| must be in [2, 2^31 -1], not: " + d); -+ } -+ -+ final int two31 = 0x80000000; -+ final long mask = 0xFFFFFFFFL; // mask for enforcing unsigned behaviour -+ -+ int p = 31; -+ -+ // all these variables are UNSIGNED! -+ int t = two31 + (d >>> 31); -+ int anc = t - 1 - t%ad; -+ int q1 = (int)((two31 & mask)/(anc & mask)); -+ int r1 = two31 - q1*anc; -+ int q2 = (int)((two31 & mask)/(ad & mask)); -+ int r2 = two31 - q2*ad; -+ int delta; -+ -+ do { -+ p = p + 1; -+ q1 = 2*q1; // Update q1 = 2**p/|nc|. -+ r1 = 2*r1; // Update r1 = rem(2**p, |nc|). -+ if ((r1 & mask) >= (anc & mask)) {// (Must be an unsigned comparison here) -+ q1 = q1 + 1; -+ r1 = r1 - anc; -+ } -+ q2 = 2*q2; // Update q2 = 2**p/|d|. -+ r2 = 2*r2; // Update r2 = rem(2**p, |d|). -+ if ((r2 & mask) >= (ad & mask)) {// (Must be an unsigned comparison here) -+ q2 = q2 + 1; -+ r2 = r2 - ad; -+ } -+ delta = ad - r2; -+ } while ((q1 & mask) < (delta & mask) || (q1 == delta && r1 == 0)); -+ -+ int magicNum = q2 + 1; -+ if (d < 0) { -+ magicNum = -magicNum; -+ } -+ int shift = p - 32; -+ return ((long)magicNum << 32) | shift; -+ } -+ -+ public static int branchlessAbs(final int val) { -+ // -n = -1 ^ n + 1 -+ final int mask = val >> (Integer.SIZE - 1); // -1 if < 0, 0 if >= 0 -+ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 -+ } -+ -+ public static long branchlessAbs(final long val) { -+ // -n = -1 ^ n + 1 -+ final long mask = val >> (Long.SIZE - 1); // -1 if < 0, 0 if >= 0 -+ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 -+ } -+ -+ //https://github.com/skeeto/hash-prospector for hash functions -+ -+ //score = ~590.47984224483832 -+ public static int hash0(int x) { -+ x *= 0x36935555; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ //score = ~310.01596637036749 -+ public static int hash1(int x) { -+ x ^= x >>> 15; -+ x *= 0x356aaaad; -+ x ^= x >>> 17; -+ return x; -+ } -+ -+ public static int hash2(int x) { -+ x ^= x >>> 16; -+ x *= 0x7feb352d; -+ x ^= x >>> 15; -+ x *= 0x846ca68b; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ public static int hash3(int x) { -+ x ^= x >>> 17; -+ x *= 0xed5ad4bb; -+ x ^= x >>> 11; -+ x *= 0xac4c1b51; -+ x ^= x >>> 15; -+ x *= 0x31848bab; -+ x ^= x >>> 14; -+ return x; -+ } -+ -+ //score = ~365.79959673201887 -+ public static long hash1(long x) { -+ x ^= x >>> 27; -+ x *= 0xb24924b71d2d354bL; -+ x ^= x >>> 28; -+ return x; -+ } -+ -+ //h2 hash -+ public static long hash2(long x) { -+ x ^= x >>> 32; -+ x *= 0xd6e8feb86659fd93L; -+ x ^= x >>> 32; -+ x *= 0xd6e8feb86659fd93L; -+ x ^= x >>> 32; -+ return x; -+ } -+ -+ public static long hash3(long x) { -+ x ^= x >>> 45; -+ x *= 0xc161abe5704b6c79L; -+ x ^= x >>> 41; -+ x *= 0xe3e5389aedbc90f7L; -+ x ^= x >>> 56; -+ x *= 0x1f9aba75a52db073L; -+ x ^= x >>> 53; -+ return x; -+ } -+ -+ private IntegerUtil() { -+ throw new RuntimeException(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c601f04b9c6dff76606763ea6f4a9a89b7e83203 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java -@@ -0,0 +1,453 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import com.destroystokyo.paper.util.math.IntegerUtil; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.world.level.ChunkPos; -+import javax.annotation.Nullable; -+import java.util.Iterator; -+ -+/** @author Spottedleaf */ -+public abstract class AreaMap { -+ -+ /* Tested via https://gist.github.com/Spottedleaf/520419c6f41ef348fe9926ce674b7217 */ -+ -+ protected final Object2LongOpenHashMap objectToLastCoordinate = new Object2LongOpenHashMap<>(); -+ protected final Object2IntOpenHashMap objectToViewDistance = new Object2IntOpenHashMap<>(); -+ -+ { -+ this.objectToViewDistance.defaultReturnValue(-1); -+ this.objectToLastCoordinate.defaultReturnValue(Long.MIN_VALUE); -+ } -+ -+ // we use linked for better iteration. -+ // map of: coordinate to set of objects in coordinate -+ protected final Long2ObjectOpenHashMap> areaMap = new Long2ObjectOpenHashMap<>(1024, 0.7f); -+ protected final PooledLinkedHashSets pooledHashSets; -+ -+ protected final ChangeCallback addCallback; -+ protected final ChangeCallback removeCallback; -+ protected final ChangeSourceCallback changeSourceCallback; -+ -+ public AreaMap() { -+ this(new PooledLinkedHashSets<>()); -+ } -+ -+ // let users define a "global" or "shared" pooled sets if they wish -+ public AreaMap(final PooledLinkedHashSets pooledHashSets) { -+ this(pooledHashSets, null, null); -+ } -+ -+ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback) { -+ this(pooledHashSets, addCallback, removeCallback, null); -+ } -+ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { -+ this.pooledHashSets = pooledHashSets; -+ this.addCallback = addCallback; -+ this.removeCallback = removeCallback; -+ this.changeSourceCallback = changeSourceCallback; -+ } -+ -+ @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final long key) { -+ return this.areaMap.get(key); -+ } -+ -+ @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final ChunkPos chunkPos) { -+ return this.areaMap.get(MCUtil.getCoordinateKey(chunkPos)); -+ } -+ -+ @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final int chunkX, final int chunkZ) { -+ return this.areaMap.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); -+ } -+ -+ // Long.MIN_VALUE indicates the object is not mapped -+ public final long getLastCoordinate(final E object) { -+ return this.objectToLastCoordinate.getOrDefault(object, Long.MIN_VALUE); -+ } -+ -+ // -1 indicates the object is not mapped -+ public final int getLastViewDistance(final E object) { -+ return this.objectToViewDistance.getOrDefault(object, -1); -+ } -+ -+ // returns the total number of mapped chunks -+ public final int size() { -+ return this.areaMap.size(); -+ } -+ -+ public final void addOrUpdate(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int oldViewDistance = this.objectToViewDistance.put(object, viewDistance); -+ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ final long oldPos = this.objectToLastCoordinate.put(object, newPos); -+ -+ if (oldViewDistance == -1) { -+ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); -+ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); -+ } else { -+ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); -+ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); -+ } -+ //this.validate(object, viewDistance); -+ } -+ -+ public final boolean update(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int oldViewDistance = this.objectToViewDistance.replace(object, viewDistance); -+ if (oldViewDistance == -1) { -+ return false; -+ } else { -+ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ final long oldPos = this.objectToLastCoordinate.put(object, newPos); -+ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); -+ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); -+ } -+ //this.validate(object, viewDistance); -+ return true; -+ } -+ -+ // called after the distance map updates -+ protected void updateObjectCallback(final E Object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { -+ if (newPosition != oldPosition && this.changeSourceCallback != null) { -+ this.changeSourceCallback.accept(Object, oldPosition, newPosition); -+ } -+ } -+ -+ public final boolean add(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int oldViewDistance = this.objectToViewDistance.putIfAbsent(object, viewDistance); -+ if (oldViewDistance != -1) { -+ return false; -+ } -+ -+ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ this.objectToLastCoordinate.put(object, newPos); -+ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); -+ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); -+ -+ //this.validate(object, viewDistance); -+ -+ return true; -+ } -+ -+ // called after the distance map updates -+ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} -+ -+ public final boolean remove(final E object) { -+ final long position = this.objectToLastCoordinate.removeLong(object); -+ final int viewDistance = this.objectToViewDistance.removeInt(object); -+ -+ if (viewDistance == -1) { -+ return false; -+ } -+ -+ final int currentX = MCUtil.getCoordinateX(position); -+ final int currentZ = MCUtil.getCoordinateZ(position); -+ -+ this.removeObject(object, currentX, currentZ, currentX, currentZ, viewDistance); -+ this.removeObjectCallback(object, currentX, currentZ, viewDistance); -+ //this.validate(object, -1); -+ return true; -+ } -+ -+ // called after the distance map updates -+ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} -+ -+ protected abstract PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final E object); -+ -+ // expensive op, only for debug -+ protected void validate(final E object, final int viewDistance) { -+ int entiesGot = 0; -+ int expectedEntries = (2 * viewDistance + 1); -+ expectedEntries *= expectedEntries; -+ if (viewDistance < 0) { -+ expectedEntries = 0; -+ } -+ -+ final long currPosition = this.objectToLastCoordinate.getLong(object); -+ -+ final int centerX = MCUtil.getCoordinateX(currPosition); -+ final int centerZ = MCUtil.getCoordinateZ(currPosition); -+ -+ for (Iterator>> iterator = this.areaMap.long2ObjectEntrySet().fastIterator(); -+ iterator.hasNext();) { -+ -+ final Long2ObjectLinkedOpenHashMap.Entry> entry = iterator.next(); -+ final long key = entry.getLongKey(); -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); -+ -+ if (map.referenceCount == 0) { -+ throw new IllegalStateException("Invalid map"); -+ } -+ -+ if (map.contains(object)) { -+ ++entiesGot; -+ -+ final int chunkX = MCUtil.getCoordinateX(key); -+ final int chunkZ = MCUtil.getCoordinateZ(key); -+ -+ final int dist = Math.max(IntegerUtil.branchlessAbs(chunkX - centerX), IntegerUtil.branchlessAbs(chunkZ - centerZ)); -+ -+ if (dist > viewDistance) { -+ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); -+ } -+ } -+ } -+ -+ if (entiesGot != expectedEntries) { -+ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); -+ } -+ } -+ -+ private void addObjectTo(final E object, final int chunkX, final int chunkZ, final int currChunkX, -+ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { -+ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet empty = this.getEmptySetFor(object); -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.putIfAbsent(key, empty); -+ -+ if (current != null) { -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWith(current, object); -+ if (next == current) { -+ throw new IllegalStateException("Expected different map: got " + next.toString()); -+ } -+ this.areaMap.put(key, next); -+ -+ current = next; -+ // fall through to callback -+ } else { -+ current = empty; -+ } -+ -+ if (this.addCallback != null) { -+ try { -+ this.addCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, current); -+ } catch (final Throwable ex) { -+ if (ex instanceof ThreadDeath) { -+ throw (ThreadDeath)ex; -+ } -+ MinecraftServer.LOGGER.error("Add callback for map threw exception ", ex); -+ } -+ } -+ } -+ -+ private void removeObjectFrom(final E object, final int chunkX, final int chunkZ, final int currChunkX, -+ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { -+ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.get(key); -+ -+ if (current == null) { -+ throw new IllegalStateException("Current map may not be null for " + object + ", (" + chunkX + "," + chunkZ + ")"); -+ } -+ -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWithout(current, object); -+ -+ if (next == current) { -+ throw new IllegalStateException("Current map [" + next.toString() + "] should have contained " + object + ", (" + chunkX + "," + chunkZ + ")"); -+ } -+ -+ if (next != null) { -+ this.areaMap.put(key, next); -+ } else { -+ this.areaMap.remove(key); -+ } -+ -+ if (this.removeCallback != null) { -+ try { -+ this.removeCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, next); -+ } catch (final Throwable ex) { -+ if (ex instanceof ThreadDeath) { -+ throw (ThreadDeath)ex; -+ } -+ MinecraftServer.LOGGER.error("Remove callback for map threw exception ", ex); -+ } -+ } -+ } -+ -+ private void addObject(final E object, final int chunkX, final int chunkZ, final int prevChunkX, final int prevChunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.addObjectTo(object, x, z, chunkX, chunkZ, prevChunkX, prevChunkZ); -+ } -+ } -+ } -+ -+ private void removeObject(final E object, final int chunkX, final int chunkZ, final int currentChunkX, final int currentChunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.removeObjectFrom(object, x, z, currentChunkX, currentChunkZ, chunkX, chunkZ); -+ } -+ } -+ } -+ -+ /* math sign function except 0 returns 1 */ -+ protected static int sign(int val) { -+ return 1 | (val >> (Integer.SIZE - 1)); -+ } -+ -+ private void updateObject(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { -+ final int toX = MCUtil.getCoordinateX(newPosition); -+ final int toZ = MCUtil.getCoordinateZ(newPosition); -+ final int fromX = MCUtil.getCoordinateX(oldPosition); -+ final int fromZ = MCUtil.getCoordinateZ(oldPosition); -+ -+ final int dx = toX - fromX; -+ final int dz = toZ - fromZ; -+ -+ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); -+ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); -+ -+ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { -+ // teleported? -+ this.removeObject(object, fromX, fromZ, fromX, fromZ, oldViewDistance); -+ this.addObject(object, toX, toZ, fromX, fromZ, newViewDistance); -+ return; -+ } -+ -+ if (oldViewDistance != newViewDistance) { -+ // remove loop -+ -+ final int oldMinX = fromX - oldViewDistance; -+ final int oldMinZ = fromZ - oldViewDistance; -+ final int oldMaxX = fromX + oldViewDistance; -+ final int oldMaxZ = fromZ + oldViewDistance; -+ for (int currX = oldMinX; currX <= oldMaxX; ++currX) { -+ for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) { -+ -+ // only remove if we're outside the new view distance... -+ if (Math.max(IntegerUtil.branchlessAbs(currX - toX), IntegerUtil.branchlessAbs(currZ - toZ)) > newViewDistance) { -+ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ // add loop -+ -+ final int newMinX = toX - newViewDistance; -+ final int newMinZ = toZ - newViewDistance; -+ final int newMaxX = toX + newViewDistance; -+ final int newMaxZ = toZ + newViewDistance; -+ for (int currX = newMinX; currX <= newMaxX; ++currX) { -+ for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) { -+ -+ // only add if we're outside the old view distance... -+ if (Math.max(IntegerUtil.branchlessAbs(currX - fromX), IntegerUtil.branchlessAbs(currZ - fromZ)) > oldViewDistance) { -+ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ return; -+ } -+ -+ // x axis is width -+ // z axis is height -+ // right refers to the x axis of where we moved -+ // top refers to the z axis of where we moved -+ -+ // same view distance -+ -+ // used for relative positioning -+ final int up = sign(dz); // 1 if dz >= 0, -1 otherwise -+ final int right = sign(dx); // 1 if dx >= 0, -1 otherwise -+ -+ // The area excluded by overlapping the two view distance squares creates four rectangles: -+ // Two on the left, and two on the right. The ones on the left we consider the "removed" section -+ // and on the right the "added" section. -+ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually -+ // exclusive to the regions they surround. -+ -+ // 4 points of the rectangle -+ int maxX; // exclusive -+ int minX; // inclusive -+ int maxZ; // exclusive -+ int minZ; // inclusive -+ -+ if (dx != 0) { -+ // handle right addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX + (oldViewDistance * right) + right; // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle up addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = toX - (oldViewDistance * right); // inclusive -+ maxZ = toZ + (oldViewDistance * up) + up; // exclusive -+ minZ = fromZ + (oldViewDistance * up) + up; // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ if (dx != 0) { -+ // handle left removal -+ -+ maxX = toX - (oldViewDistance * right); // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle down removal -+ -+ maxX = fromX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = toZ - (oldViewDistance * up); // exclusive -+ minZ = fromZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface ChangeCallback { -+ -+ // if there is no previous position, then prevPos = Integer.MIN_VALUE -+ void accept(final E object, final int rangeX, final int rangeZ, final int currPosX, final int currPosZ, final int prevPosX, final int prevPosZ, -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState); -+ -+ } -+ -+ @FunctionalInterface -+ public static interface ChangeSourceCallback { -+ void accept(final E object, final long prevPos, final long newPos); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9b8cb361767fbcf5f592db32a12186f0bd6373bd ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java -@@ -0,0 +1,175 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import com.destroystokyo.paper.util.math.IntegerUtil; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.ChunkPos; -+ -+/** @author Spottedleaf */ -+public abstract class DistanceTrackingAreaMap extends AreaMap { -+ -+ // use this map only if you need distance tracking, the tracking here is obviously going to hit harder. -+ -+ protected final Long2IntOpenHashMap chunkToNearestDistance = new Long2IntOpenHashMap(1024, 0.7f); -+ { -+ this.chunkToNearestDistance.defaultReturnValue(-1); -+ } -+ -+ protected final DistanceChangeCallback distanceChangeCallback; -+ -+ public DistanceTrackingAreaMap() { -+ this(new PooledLinkedHashSets<>()); -+ } -+ -+ // let users define a "global" or "shared" pooled sets if they wish -+ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { -+ this(pooledHashSets, null, null, null); -+ } -+ -+ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, -+ final DistanceChangeCallback distanceChangeCallback) { -+ super(pooledHashSets, addCallback, removeCallback); -+ this.distanceChangeCallback = distanceChangeCallback; -+ } -+ -+ // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final long key) { -+ return this.chunkToNearestDistance.get(key); -+ } -+ -+ // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final ChunkPos chunkPos) { -+ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkPos)); -+ } -+ -+ // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final int chunkX, final int chunkZ) { -+ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); -+ } -+ -+ protected final void recalculateDistance(final int chunkX, final int chunkZ) { -+ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state = this.areaMap.get(key); -+ if (state == null) { -+ final int oldDistance = this.chunkToNearestDistance.remove(key); -+ // nothing here. -+ if (oldDistance == -1) { -+ // nothing was here previously -+ return; -+ } -+ if (this.distanceChangeCallback != null) { -+ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, -1, null); -+ } -+ return; -+ } -+ -+ int newDistance = Integer.MAX_VALUE; -+ -+ final Object[] rawData = state.getBackingSet(); -+ for (int i = 0, len = rawData.length; i < len; ++i) { -+ final Object raw = rawData[i]; -+ -+ if (raw == null) { -+ continue; -+ } -+ -+ final E object = (E)raw; -+ final long location = this.objectToLastCoordinate.getLong(object); -+ -+ final int distance = Math.max(IntegerUtil.branchlessAbs(chunkX - MCUtil.getCoordinateX(location)), IntegerUtil.branchlessAbs(chunkZ - MCUtil.getCoordinateZ(location))); -+ -+ if (distance < newDistance) { -+ newDistance = distance; -+ } -+ } -+ -+ final int oldDistance = this.chunkToNearestDistance.put(key, newDistance); -+ -+ if (oldDistance != newDistance) { -+ if (this.distanceChangeCallback != null) { -+ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, newDistance, state); -+ } -+ } -+ } -+ -+ @Override -+ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.recalculateDistance(x, z); -+ } -+ } -+ } -+ -+ @Override -+ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.recalculateDistance(x, z); -+ } -+ } -+ } -+ -+ @Override -+ protected void updateObjectCallback(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { -+ if (oldPosition == newPosition && newViewDistance == oldViewDistance) { -+ return; -+ } -+ -+ final int toX = MCUtil.getCoordinateX(newPosition); -+ final int toZ = MCUtil.getCoordinateZ(newPosition); -+ final int fromX = MCUtil.getCoordinateX(oldPosition); -+ final int fromZ = MCUtil.getCoordinateZ(oldPosition); -+ -+ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); -+ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); -+ -+ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { -+ // teleported? -+ this.removeObjectCallback(object, fromX, fromZ, oldViewDistance); -+ this.addObjectCallback(object, toX, toZ, newViewDistance); -+ return; -+ } -+ -+ final int minX = Math.min(fromX - oldViewDistance, toX - newViewDistance); -+ final int maxX = Math.max(fromX + oldViewDistance, toX + newViewDistance); -+ final int minZ = Math.min(fromZ - oldViewDistance, toZ - newViewDistance); -+ final int maxZ = Math.max(fromZ + oldViewDistance, toZ + newViewDistance); -+ -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ final int distXOld = IntegerUtil.branchlessAbs(x - fromX); -+ final int distZOld = IntegerUtil.branchlessAbs(z - fromZ); -+ -+ if (Math.max(distXOld, distZOld) <= oldViewDistance) { -+ this.recalculateDistance(x, z); -+ continue; -+ } -+ -+ final int distXNew = IntegerUtil.branchlessAbs(x - toX); -+ final int distZNew = IntegerUtil.branchlessAbs(z - toZ); -+ -+ if (Math.max(distXNew, distZNew) <= newViewDistance) { -+ this.recalculateDistance(x, z); -+ continue; -+ } -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface DistanceChangeCallback { -+ -+ void accept(final int posX, final int posZ, final int oldNearestDistance, final int newNearestDistance, -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state); -+ -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..46954db7ecd35ac4018fdf476df7c8020d7ce6c8 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java -@@ -0,0 +1,32 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import net.minecraft.server.level.ServerPlayer; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class PlayerAreaMap extends AreaMap { -+ -+ public PlayerAreaMap() { -+ super(); -+ } -+ -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets) { -+ super(pooledHashSets); -+ } -+ -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback) { -+ this(pooledHashSets, addCallback, removeCallback, null); -+ } -+ -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { -+ super(pooledHashSets, addCallback, removeCallback, changeSourceCallback); -+ } -+ -+ @Override -+ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final ServerPlayer player) { -+ return player.cachedSingleHashSet; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d05dcea15f7047b58736c7c0e07920a04d6c5abe ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java -@@ -0,0 +1,24 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import net.minecraft.server.level.ServerPlayer; -+ -+public class PlayerDistanceTrackingAreaMap extends DistanceTrackingAreaMap { -+ -+ public PlayerDistanceTrackingAreaMap() { -+ super(); -+ } -+ -+ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { -+ super(pooledHashSets); -+ } -+ -+ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback, final DistanceChangeCallback distanceChangeCallback) { -+ super(pooledHashSets, addCallback, removeCallback, distanceChangeCallback); -+ } -+ -+ @Override -+ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final ServerPlayer player) { -+ return player.cachedSingleHashSet; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e51104e65a07b6ea7bbbcbb6afb066ef6401cc5b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java -@@ -0,0 +1,287 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -+import java.lang.ref.WeakReference; -+ -+/** @author Spottedleaf */ -+public class PooledLinkedHashSets { -+ -+ /* Tested via https://gist.github.com/Spottedleaf/a93bb7a8993d6ce142d3efc5932bf573 */ -+ -+ // we really want to avoid that equals() check as much as possible... -+ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(128, 0.25f); -+ -+ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { -+ if (current.referenceCount == 0) { -+ throw new IllegalStateException("Cannot decrement reference count for " + current); -+ } -+ if (current.referenceCount == -1 || --current.referenceCount > 0) { -+ return; -+ } -+ -+ this.mapPool.remove(current); -+ return; -+ } -+ -+ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { -+ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); -+ -+ if (cached != null) { -+ decrementReferenceCount(current); -+ -+ if (cached.referenceCount == 0) { -+ // bring the map back from the dead -+ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); -+ if (contending != null) { -+ // a map already exists with the elements we want -+ if (contending.referenceCount != -1) { -+ ++contending.referenceCount; -+ } -+ current.updateAddCache(object, contending); -+ return contending; -+ } -+ -+ cached.referenceCount = 1; -+ } else if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ return cached; -+ } -+ -+ if (!current.add(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.remove(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.remove(object); -+ } -+ -+ current.updateAddCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ // rets null if current.size() == 1 -+ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { -+ if (current.set.size() == 1) { -+ decrementReferenceCount(current); -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); -+ -+ if (cached != null) { -+ decrementReferenceCount(current); -+ -+ if (cached.referenceCount == 0) { -+ // bring the map back from the dead -+ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); -+ if (contending != null) { -+ // a map already exists with the elements we want -+ if (contending.referenceCount != -1) { -+ ++contending.referenceCount; -+ } -+ current.updateRemoveCache(object, contending); -+ return contending; -+ } -+ -+ cached.referenceCount = 1; -+ } else if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ return cached; -+ } -+ -+ if (!current.remove(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.add(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.add(object); -+ } -+ -+ current.updateRemoveCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ static final class RawSetObjectLinkedOpenHashSet extends ObjectOpenHashSet { -+ -+ public RawSetObjectLinkedOpenHashSet() { -+ super(); -+ } -+ -+ public RawSetObjectLinkedOpenHashSet(final int capacity) { -+ super(capacity); -+ } -+ -+ public RawSetObjectLinkedOpenHashSet(final int capacity, final float loadFactor) { -+ super(capacity, loadFactor); -+ } -+ -+ @Override -+ public RawSetObjectLinkedOpenHashSet clone() { -+ return (RawSetObjectLinkedOpenHashSet)super.clone(); -+ } -+ -+ public E[] getRawSet() { -+ return this.key; -+ } -+ } -+ -+ public static final class PooledObjectLinkedOpenHashSet { -+ -+ private static final WeakReference NULL_REFERENCE = new WeakReference<>(null); -+ -+ final RawSetObjectLinkedOpenHashSet set; -+ int referenceCount; // -1 if special -+ int hash; // optimize hashcode -+ -+ // add cache -+ WeakReference lastAddObject = NULL_REFERENCE; -+ WeakReference> lastAddMap = NULL_REFERENCE; -+ -+ // remove cache -+ WeakReference lastRemoveObject = NULL_REFERENCE; -+ WeakReference> lastRemoveMap = NULL_REFERENCE; -+ -+ public PooledObjectLinkedOpenHashSet(final PooledLinkedHashSets pooledSets) { -+ this.set = new RawSetObjectLinkedOpenHashSet<>(2, 0.8f); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final E single) { -+ this((PooledLinkedHashSets)null); -+ this.referenceCount = -1; -+ this.add(single); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { -+ this.set = other.set.clone(); -+ this.hash = other.hash; -+ } -+ -+ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java -+ // generated by https://github.com/skeeto/hash-prospector -+ private static int hash0(int x) { -+ x *= 0x36935555; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ PooledObjectLinkedOpenHashSet getAddCache(final E element) { -+ final E currentAdd = this.lastAddObject.get(); -+ -+ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { -+ return null; -+ } -+ -+ return this.lastAddMap.get(); -+ } -+ -+ PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { -+ final E currentRemove = this.lastRemoveObject.get(); -+ -+ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { -+ return null; -+ } -+ -+ return this.lastRemoveMap.get(); -+ } -+ -+ void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastAddObject = new WeakReference<>(element); -+ this.lastAddMap = new WeakReference<>(map); -+ } -+ -+ void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastRemoveObject = new WeakReference<>(element); -+ this.lastRemoveMap = new WeakReference<>(map); -+ } -+ -+ boolean add(final E element) { -+ boolean added = this.set.add(element); -+ -+ if (added) { -+ this.hash += hash0(element.hashCode()); -+ } -+ -+ return added; -+ } -+ -+ boolean remove(Object element) { -+ boolean removed = this.set.remove(element); -+ -+ if (removed) { -+ this.hash -= hash0(element.hashCode()); -+ } -+ -+ return removed; -+ } -+ -+ public boolean contains(final Object element) { -+ return this.set.contains(element); -+ } -+ -+ public E[] getBackingSet() { -+ return this.set.getRawSet(); -+ } -+ -+ public int size() { -+ return this.set.size(); -+ } -+ -+ @Override -+ public int hashCode() { -+ return this.hash; -+ } -+ -+ @Override -+ public boolean equals(final Object other) { -+ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { -+ return false; -+ } -+ if (this.referenceCount == 0) { -+ return other == this; -+ } else { -+ if (other == this) { -+ // Unfortunately we are never equal to our own instance while in use! -+ return false; -+ } -+ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); -+ } -+ } -+ -+ @Override -+ public String toString() { -+ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + -+ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d0c77068e9a53d1b8bbad0f3f6b420d6bc85f8c8 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java -@@ -0,0 +1,85 @@ -+package com.destroystokyo.paper.util.pooled; -+ -+import net.minecraft.server.MCUtil; -+import org.apache.commons.lang3.mutable.MutableInt; -+ -+import java.util.ArrayDeque; -+import java.util.function.Consumer; -+import java.util.function.Supplier; -+ -+public final class PooledObjects { -+ -+ /** -+ * Wrapper for an object that will be have a cleaner registered for it, and may be automatically returned to pool. -+ */ -+ public class AutoReleased { -+ private final E object; -+ private final Runnable cleaner; -+ -+ public AutoReleased(E object, Runnable cleaner) { -+ this.object = object; -+ this.cleaner = cleaner; -+ } -+ -+ public final E getObject() { -+ return object; -+ } -+ -+ public final Runnable getCleaner() { -+ return cleaner; -+ } -+ } -+ -+ public static final PooledObjects POOLED_MUTABLE_INTEGERS = new PooledObjects<>(MutableInt::new, 1024); -+ -+ private final Supplier creator; -+ private final Consumer releaser; -+ private final int maxPoolSize; -+ private final ArrayDeque queue; -+ -+ public PooledObjects(final Supplier creator, int maxPoolSize) { -+ this(creator, maxPoolSize, null); -+ } -+ public PooledObjects(final Supplier creator, int maxPoolSize, Consumer releaser) { -+ if (creator == null) { -+ throw new NullPointerException("Creator must not be null"); -+ } -+ if (maxPoolSize <= 0) { -+ throw new IllegalArgumentException("Max pool size must be greater-than 0"); -+ } -+ -+ this.queue = new ArrayDeque<>(maxPoolSize); -+ this.maxPoolSize = maxPoolSize; -+ this.creator = creator; -+ this.releaser = releaser; -+ } -+ -+ public AutoReleased acquireCleaner(Object holder) { -+ return acquireCleaner(holder, this::release); -+ } -+ -+ public AutoReleased acquireCleaner(Object holder, Consumer releaser) { -+ E resource = acquire(); -+ Runnable cleaner = MCUtil.registerCleaner(holder, resource, releaser); -+ return new AutoReleased(resource, cleaner); -+ } -+ -+ public final E acquire() { -+ E value; -+ synchronized (queue) { -+ value = this.queue.pollLast(); -+ } -+ return value != null ? value : this.creator.get(); -+ } -+ -+ public final void release(final E value) { -+ if (this.releaser != null) { -+ this.releaser.accept(value); -+ } -+ synchronized (this.queue) { -+ if (queue.size() < this.maxPoolSize) { -+ this.queue.addLast(value); -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -@@ -0,0 +1,67 @@ -+package com.destroystokyo.paper.util.set; -+ -+import java.util.Collection; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class OptimizedSmallEnumSet> { -+ -+ private final Class enumClass; -+ private long backingSet; -+ -+ public OptimizedSmallEnumSet(final Class clazz) { -+ if (clazz == null) { -+ throw new IllegalArgumentException("Null class"); -+ } -+ if (!clazz.isEnum()) { -+ throw new IllegalArgumentException("Class must be enum, not " + clazz.getCanonicalName()); -+ } -+ this.enumClass = clazz; -+ } -+ -+ public boolean addUnchecked(final E element) { -+ final int ordinal = element.ordinal(); -+ final long key = 1L << ordinal; -+ -+ final long prev = this.backingSet; -+ this.backingSet = prev | key; -+ -+ return (prev & key) == 0; -+ } -+ -+ public boolean removeUnchecked(final E element) { -+ final int ordinal = element.ordinal(); -+ final long key = 1L << ordinal; -+ -+ final long prev = this.backingSet; -+ this.backingSet = prev & ~key; -+ -+ return (prev & key) != 0; -+ } -+ -+ public void clear() { -+ this.backingSet = 0L; -+ } -+ -+ public int size() { -+ return Long.bitCount(this.backingSet); -+ } -+ -+ public void addAllUnchecked(final Collection enums) { -+ for (final E element : enums) { -+ if (element == null) { -+ throw new NullPointerException("Null element"); -+ } -+ this.backingSet |= (1L << element.ordinal()); -+ } -+ } -+ -+ public long getBackingSet() { -+ return this.backingSet; -+ } -+ -+ public boolean hasCommonElements(final OptimizedSmallEnumSet other) { -+ return (other.backingSet & this.backingSet) != 0; -+ } -+} -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index 8c378d3f3138953b3b22b289fecdb6b40a09ab63..67fa685f4b8de3eae1431c0de399c246678b542a 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -78,7 +78,7 @@ public class Util { - } - - public static long getNanos() { -- return Util.timeSource.getAsLong(); -+ return System.nanoTime(); // Paper - } - - public static long getEpochMillis() { -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 88147a1f25cf2fd549412b653b8f0eb5c60bb55d..6a58059a05e16d96894b67a544c2f595d9546c78 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -105,6 +105,7 @@ public class BlockPos extends Vec3i { - return x == 0.0D && y == 0.0D && z == 0.0D ? this : new BlockPos((double) this.getX() + x, (double) this.getY() + y, (double) this.getZ() + z); - } - -+ public final BlockPos add(int i, int j, int k) {return offset(i, j, k);} // Paper - OBFHELPER - public BlockPos offset(int x, int y, int z) { - return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.getX() + x, this.getY() + y, this.getZ() + z); - } -@@ -436,6 +437,7 @@ public class BlockPos extends Vec3i { - return super.rotate(rotation).immutable(); - } - -+ public final BlockPos.MutableBlockPos setValues(int i, int j, int k) { return set(i, j, k);} // Paper - OBFHELPER - public BlockPos.MutableBlockPos set(int x, int y, int z) { - this.setX(x); - this.setY(y); -@@ -443,6 +445,7 @@ public class BlockPos extends Vec3i { - return this; - } - -+ public final BlockPos.MutableBlockPos setValues(double d0, double d1, double d2) { return set(d0, d1, d2);} // Paper - OBFHELPER - public BlockPos.MutableBlockPos set(double x, double y, double z) { - return this.set(Mth.floor(x), Mth.floor(y), Mth.floor(z)); - } -@@ -496,20 +499,21 @@ public class BlockPos extends Vec3i { - } - } - -+ /* // Paper start - comment out useless overrides @Override - @Override -- public void setX(int x) { -- super.setX(x); -+ public void o(int i) { -+ super.o(i); - } - - @Override -- public void setY(int y) { -- super.setY(y); -+ public void p(int i) { -+ super.p(i); - } - -- @Override -- public void setZ(int z) { -- super.setZ(z); -+ public void q(int i) { -+ super.q(i); - } -+ */ // Paper end - - @Override - public BlockPos immutable() { -diff --git a/src/main/java/net/minecraft/core/IdMapper.java b/src/main/java/net/minecraft/core/IdMapper.java -index 424c6cacc2e7c7b1c9d0b92fe198237033a3fcbd..e7358721e9d78bc9cbbfc3e71ce927ea4b82ce7c 100644 ---- a/src/main/java/net/minecraft/core/IdMapper.java -+++ b/src/main/java/net/minecraft/core/IdMapper.java -@@ -64,6 +64,7 @@ public class IdMapper implements IdMap { - return Iterators.filter(this.idToT.iterator(), Predicates.notNull()); - } - -+ public int size() { return this.size(); } // Paper - OBFHELPER - public int size() { - return this.tToId.size(); - } -diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java -index 9bd2120bdcfe204184eb9a9e1daa5e3338665e51..3e79b274b8e0406a3cbdd94c7cec091b583109ca 100644 ---- a/src/main/java/net/minecraft/core/Vec3i.java -+++ b/src/main/java/net/minecraft/core/Vec3i.java -@@ -18,9 +18,9 @@ public class Vec3i implements Comparable { - return IntStream.of(new int[]{baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()}); - }); - public static final Vec3i ZERO = new Vec3i(0, 0, 0); -- private int x; -- private int y; -- private int z; -+ private int x;public final void setX(final int x) { this.x = x; } // Paper - OBFHELPER -+ private int y;public final void setY(final int y) { this.y = y; } // Paper - OBFHELPER -+ private int z;public final void setZ(final int z) { this.z = z; } // Paper - OBFHELPER - - public Vec3i(int x, int y, int z) { - this.x = x; -@@ -64,15 +64,15 @@ public class Vec3i implements Comparable { - return this.z; - } - -- protected void setX(int x) { -+ public void setX(int x) { // Paper - protected -> public - this.x = x; - } - -- protected void setY(int y) { -+ public void setY(int y) { // Paper - protected -> public - this.y = y; - } - -- protected void setZ(int z) { -+ public void setZ(int z) { // Paper - protected -> public - this.z = z; - } - -@@ -108,6 +108,7 @@ public class Vec3i implements Comparable { - return this.distSqr(pos.x(), pos.y(), pos.z(), true) < distance * distance; - } - -+ public final double distanceSquared(Vec3i baseblockposition) { return distSqr(baseblockposition); } // Paper - OBFHELPER - public double distSqr(Vec3i vec) { - return this.distSqr((double) vec.getX(), (double) vec.getY(), (double) vec.getZ(), true); - } -diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java -index 077383bd9af79851351eba50e7d7ea31cc106cad..4c8f249e45e5deb7628997d4dbd9dab613ac5241 100644 ---- a/src/main/java/net/minecraft/nbt/CompoundTag.java -+++ b/src/main/java/net/minecraft/nbt/CompoundTag.java -@@ -76,7 +76,7 @@ public class CompoundTag implements Tag { - return "TAG_Compound"; - } - }; -- private final Map tags; -+ public final Map tags; // Paper - - protected CompoundTag(Map tags) { - this.tags = tags; -@@ -139,10 +139,16 @@ public class CompoundTag implements Tag { - this.tags.put(key, LongTag.valueOf(value)); - } - -+ public void setUUID(String prefix, UUID uuid) { putUUID(prefix, uuid); } // Paper - OBFHELPER - public void putUUID(String key, UUID value) { - this.tags.put(key, NbtUtils.createUUID(value)); - } - -+ -+ /** -+ * You must use {@link #hasUUID(String)} before or else it will throw an NPE. -+ */ -+ public UUID getUUID(String prefix) { return getUUID(prefix); } // Paper - OBFHELPER - public UUID getUUID(String key) { - return NbtUtils.loadUUID(this.get(key)); - } -diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 8ce3a74821a0e540423a2e8e67be640b8b876035..92c5c5bbcfe364475578b6a0eddfaa85858ace8a 100644 ---- a/src/main/java/net/minecraft/network/Connection.java -+++ b/src/main/java/net/minecraft/network/Connection.java -@@ -168,6 +168,7 @@ public class Connection extends SimpleChannelInboundHandler> { - - } - -+ private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.sendPacket(packet, genericFutureListener); } // Paper - OBFHELPER - private void sendPacket(Packet packet, @Nullable GenericFutureListener> callback) { - ConnectionProtocol enumprotocol = ConnectionProtocol.getProtocolForPacket(packet); - ConnectionProtocol enumprotocol1 = (ConnectionProtocol) this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).get(); -@@ -208,6 +209,7 @@ public class Connection extends SimpleChannelInboundHandler> { - - } - -+ private void sendPacketQueue() { this.flushQueue(); } // Paper - OBFHELPER - private void flushQueue() { - if (this.channel != null && this.channel.isOpen()) { - Queue queue = this.queue; -@@ -344,9 +346,9 @@ public class Connection extends SimpleChannelInboundHandler> { - - static class PacketHolder { - -- private final Packet packet; -+ private final Packet packet; private final Packet getPacket() { return this.packet; } // Paper - OBFHELPER - @Nullable -- private final GenericFutureListener> listener; -+ private final GenericFutureListener> listener; private final GenericFutureListener> getGenericFutureListener() { return this.listener; } // Paper - OBFHELPER - - public PacketHolder(Packet packet, @Nullable GenericFutureListener> callback) { - this.packet = packet; -diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -index e0dc41a8f408b7fa0b8554833ea4d09e7e604913..50f14acb062c2f90266279dbd1945a3297396f0b 100644 ---- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java -+++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -@@ -48,6 +48,7 @@ public class FriendlyByteBuf extends ByteBuf { - this.source = bytebuf; - } - -+ public static int countBytes(int i) { return FriendlyByteBuf.getVarIntSize(i); } // Paper - OBFHELPER - public static int getVarIntSize(int i) { - for (int j = 1; j < 5; ++j) { - if ((i & -1 << j * 7) == 0) { -diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index 7af36e5a889d04f6e80c80f7335bf149a4b5d224..14fa1371e52b9af5a7550a9aa144fa406b754046 100644 ---- a/src/main/java/net/minecraft/network/PacketEncoder.java -+++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -44,6 +44,7 @@ public class PacketEncoder extends MessageToByteEncoder> { - packet.write(packetdataserializer); - } catch (Throwable throwable) { - PacketEncoder.LOGGER.error(throwable); -+ throwable.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? - if (packet.isSkippable()) { - throw new SkipPacketException(throwable); - } else { -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -index bda189ab2b3b934e6bf9fd11da5d95bd9b37ba70..e5d4363edb8c494d2db69d2e0223a2db1519f64b 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -@@ -28,7 +28,7 @@ public class ClientboundLevelChunkPacket implements Packet blockEntitiesTags; - private boolean fullChunk; - -@@ -140,6 +140,7 @@ public class ClientboundLevelChunkPacket implements Packet { - -- private ItemStack book; -+ private ItemStack book; public ItemStack getBook() { return book; } // Paper - OBFHELPER - private boolean signing; - private int slot; - -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d29fe67b7d39e368a873368a6be16042429e9209 ---- /dev/null -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -0,0 +1,510 @@ -+package net.minecraft.server; -+ -+import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.google.common.util.concurrent.ThreadFactoryBuilder; -+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; -+import net.minecraft.core.BlockPos; -+import net.minecraft.core.Direction; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.level.ChunkPos; -+import net.minecraft.world.level.ClipContext; -+import net.minecraft.world.level.Level; -+import org.apache.commons.lang.exception.ExceptionUtils; -+import org.bukkit.Location; -+import org.bukkit.block.BlockFace; -+import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.util.Waitable; -+import org.spigotmc.AsyncCatcher; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.util.List; -+import java.util.Queue; -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.ExecutionException; -+import java.util.concurrent.LinkedBlockingQueue; -+import java.util.concurrent.ThreadPoolExecutor; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.function.BiConsumer; -+import java.util.function.Consumer; -+import java.util.function.Supplier; -+ -+public final class MCUtil { -+ public static final ThreadPoolExecutor asyncExecutor = new ThreadPoolExecutor( -+ 0, 2, 60L, TimeUnit.SECONDS, -+ new LinkedBlockingQueue(), -+ new ThreadFactoryBuilder().setNameFormat("Paper Async Task Handler Thread - %1$d").build() -+ ); -+ public static final ThreadPoolExecutor cleanerExecutor = new ThreadPoolExecutor( -+ 1, 1, 0L, TimeUnit.SECONDS, -+ new LinkedBlockingQueue(), -+ new ThreadFactoryBuilder().setNameFormat("Paper Object Cleaner").build() -+ ); -+ -+ public static final long INVALID_CHUNK_KEY = getCoordinateKey(Integer.MAX_VALUE, Integer.MAX_VALUE); -+ -+ -+ public static Runnable once(Runnable run) { -+ AtomicBoolean ran = new AtomicBoolean(false); -+ return () -> { -+ if (ran.compareAndSet(false, true)) { -+ run.run(); -+ } -+ }; -+ } -+ -+ public static Runnable once(List list, Consumer cb) { -+ return once(() -> { -+ list.forEach(cb); -+ }); -+ } -+ -+ private static Runnable makeCleanerCallback(Runnable run) { -+ return once(() -> cleanerExecutor.execute(run)); -+ } -+ -+ /** -+ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! -+ * @param obj -+ * @param run -+ * @return -+ */ -+ public static Runnable registerCleaner(Object obj, Runnable run) { -+ // Wrap callback in its own method above or the lambda will leak object -+ Runnable cleaner = makeCleanerCallback(run); -+ co.aikar.cleaner.Cleaner.register(obj, cleaner); -+ return cleaner; -+ } -+ -+ /** -+ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! -+ * @param obj -+ * @param list -+ * @param cleaner -+ * @param -+ * @return -+ */ -+ public static Runnable registerListCleaner(Object obj, List list, Consumer cleaner) { -+ return registerCleaner(obj, () -> { -+ list.forEach(cleaner); -+ list.clear(); -+ }); -+ } -+ -+ /** -+ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! -+ * @param obj -+ * @param resource -+ * @param cleaner -+ * @param -+ * @return -+ */ -+ public static Runnable registerCleaner(Object obj, T resource, java.util.function.Consumer cleaner) { -+ return registerCleaner(obj, () -> cleaner.accept(resource)); -+ } -+ -+ public static List getSpiralOutChunks(BlockPos blockposition, int radius) { -+ List list = com.google.common.collect.Lists.newArrayList(); -+ -+ list.add(new ChunkPos(blockposition.getX() >> 4, blockposition.getZ() >> 4)); -+ for (int r = 1; r <= radius; r++) { -+ int x = -r; -+ int z = r; -+ -+ // Iterates the edge of half of the box; then negates for other half. -+ while (x <= r && z > -r) { -+ list.add(new ChunkPos((blockposition.getX() + (x << 4)) >> 4, (blockposition.getZ() + (z << 4)) >> 4)); -+ list.add(new ChunkPos((blockposition.getX() - (x << 4)) >> 4, (blockposition.getZ() - (z << 4)) >> 4)); -+ -+ if (x < r) { -+ x++; -+ } else { -+ z--; -+ } -+ } -+ } -+ return list; -+ } -+ -+ public static int fastFloor(double x) { -+ int truncated = (int)x; -+ return x < (double)truncated ? truncated - 1 : truncated; -+ } -+ -+ public static int fastFloor(float x) { -+ int truncated = (int)x; -+ return x < (double)truncated ? truncated - 1 : truncated; -+ } -+ -+ public static float normalizeYaw(float f) { -+ float f1 = f % 360.0F; -+ -+ if (f1 >= 180.0F) { -+ f1 -= 360.0F; -+ } -+ -+ if (f1 < -180.0F) { -+ f1 += 360.0F; -+ } -+ -+ return f1; -+ } -+ -+ /** -+ * Quickly generate a stack trace for current location -+ * -+ * @return Stacktrace -+ */ -+ public static String stack() { -+ return ExceptionUtils.getFullStackTrace(new Throwable()); -+ } -+ -+ /** -+ * Quickly generate a stack trace for current location with message -+ * -+ * @param str -+ * @return Stacktrace -+ */ -+ public static String stack(String str) { -+ return ExceptionUtils.getFullStackTrace(new Throwable(str)); -+ } -+ -+ public static long getCoordinateKey(final BlockPos blockPos) { -+ return ((long)(blockPos.getZ() >> 4) << 32) | ((blockPos.getX() >> 4) & 0xFFFFFFFFL); -+ } -+ -+ public static long getCoordinateKey(final Entity entity) { -+ return ((long)(MCUtil.fastFloor(entity.getZ()) >> 4) << 32) | ((MCUtil.fastFloor(entity.getX()) >> 4) & 0xFFFFFFFFL); -+ } -+ -+ public static long getCoordinateKey(final ChunkPos pair) { -+ return ((long)pair.z << 32) | (pair.x & 0xFFFFFFFFL); -+ } -+ -+ public static long getCoordinateKey(final int x, final int z) { -+ return ((long)z << 32) | (x & 0xFFFFFFFFL); -+ } -+ -+ public static int getCoordinateX(final long key) { -+ return (int)key; -+ } -+ -+ public static int getCoordinateZ(final long key) { -+ return (int)(key >>> 32); -+ } -+ -+ public static int getChunkCoordinate(final double coordinate) { -+ return MCUtil.fastFloor(coordinate) >> 4; -+ } -+ -+ public static int getBlockCoordinate(final double coordinate) { -+ return MCUtil.fastFloor(coordinate); -+ } -+ -+ public static long getBlockKey(final int x, final int y, final int z) { -+ return ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54); -+ } -+ -+ public static long getBlockKey(final BlockPos pos) { -+ return ((long)pos.getX() & 0x7FFFFFF) | (((long)pos.getZ() & 0x7FFFFFF) << 27) | ((long)pos.getY() << 54); -+ } -+ -+ public static long getBlockKey(final Entity entity) { -+ return getBlockKey(getBlockCoordinate(entity.getX()), getBlockCoordinate(entity.getY()), getBlockCoordinate(entity.getZ())); -+ } -+ -+ // assumes the sets have the same comparator, and if this comparator is null then assume T is Comparable -+ public static void mergeSortedSets(final java.util.function.Consumer consumer, final java.util.Comparator comparator, final java.util.SortedSet...sets) { -+ final ObjectRBTreeSet all = new ObjectRBTreeSet<>(comparator); -+ // note: this is done in log(n!) ~ nlogn time. It could be improved if it were to mimic what mergesort does. -+ for (java.util.SortedSet set : sets) { -+ if (set != null) { -+ all.addAll(set); -+ } -+ } -+ all.forEach(consumer); -+ } -+ -+ private MCUtil() {} -+ -+ public static final java.util.concurrent.Executor MAIN_EXECUTOR = (run) -> { -+ if (!isMainThread()) { -+ MinecraftServer.getServer().execute(run); -+ } else { -+ run.run(); -+ } -+ }; -+ -+ public static CompletableFuture ensureMain(CompletableFuture future) { -+ return future.thenApplyAsync(r -> r, MAIN_EXECUTOR); -+ } -+ -+ public static void thenOnMain(CompletableFuture future, Consumer consumer) { -+ future.thenAcceptAsync(consumer, MAIN_EXECUTOR); -+ } -+ public static void thenOnMain(CompletableFuture future, BiConsumer consumer) { -+ future.whenCompleteAsync(consumer, MAIN_EXECUTOR); -+ } -+ -+ public static boolean isMainThread() { -+ return MinecraftServer.getServer().isSameThread(); -+ } -+ -+ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable) { -+ return scheduleTask(ticks, runnable, null); -+ } -+ -+ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable, String taskName) { -+ return MinecraftServer.getServer().server.getScheduler().scheduleInternalTask(runnable, ticks, taskName); -+ } -+ -+ public static void processQueue() { -+ Runnable runnable; -+ Queue processQueue = getProcessQueue(); -+ while ((runnable = processQueue.poll()) != null) { -+ try { -+ runnable.run(); -+ } catch (Exception e) { -+ MinecraftServer.LOGGER.error("Error executing task", e); -+ } -+ } -+ } -+ public static T processQueueWhileWaiting(CompletableFuture future) { -+ try { -+ if (isMainThread()) { -+ while (!future.isDone()) { -+ try { -+ return future.get(1, TimeUnit.MILLISECONDS); -+ } catch (TimeoutException ignored) { -+ processQueue(); -+ } -+ } -+ } -+ return future.get(); -+ } catch (Exception e) { -+ throw new RuntimeException(e); -+ } -+ } -+ -+ public static void ensureMain(Runnable run) { -+ ensureMain(null, run); -+ } -+ /** -+ * Ensures the target code is running on the main thread -+ * @param reason -+ * @param run -+ * @return -+ */ -+ public static void ensureMain(String reason, Runnable run) { -+ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { -+ if (reason != null) { -+ new IllegalStateException("Asynchronous " + reason + "!").printStackTrace(); -+ } -+ getProcessQueue().add(run); -+ return; -+ } -+ run.run(); -+ } -+ -+ private static Queue getProcessQueue() { -+ return MinecraftServer.getServer().processQueue; -+ } -+ -+ public static T ensureMain(Supplier run) { -+ return ensureMain(null, run); -+ } -+ /** -+ * Ensures the target code is running on the main thread -+ * @param reason -+ * @param run -+ * @param -+ * @return -+ */ -+ public static T ensureMain(String reason, Supplier run) { -+ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { -+ if (reason != null) { -+ new IllegalStateException("Asynchronous " + reason + "! Blocking thread until it returns ").printStackTrace(); -+ } -+ Waitable wait = new Waitable() { -+ @Override -+ protected T evaluate() { -+ return run.get(); -+ } -+ }; -+ getProcessQueue().add(wait); -+ try { -+ return wait.get(); -+ } catch (InterruptedException | ExecutionException e) { -+ e.printStackTrace(); -+ } -+ return null; -+ } -+ return run.get(); -+ } -+ -+ /** -+ * Calculates distance between 2 entities -+ * @param e1 -+ * @param e2 -+ * @return -+ */ -+ public static double distance(Entity e1, Entity e2) { -+ return Math.sqrt(distanceSq(e1, e2)); -+ } -+ -+ -+ /** -+ * Calculates distance between 2 block positions -+ * @param e1 -+ * @param e2 -+ * @return -+ */ -+ public static double distance(BlockPos e1, BlockPos e2) { -+ return Math.sqrt(distanceSq(e1, e2)); -+ } -+ -+ /** -+ * Gets the distance between 2 positions -+ * @param x1 -+ * @param y1 -+ * @param z1 -+ * @param x2 -+ * @param y2 -+ * @param z2 -+ * @return -+ */ -+ public static double distance(double x1, double y1, double z1, double x2, double y2, double z2) { -+ return Math.sqrt(distanceSq(x1, y1, z1, x2, y2, z2)); -+ } -+ -+ /** -+ * Get's the distance squared between 2 entities -+ * @param e1 -+ * @param e2 -+ * @return -+ */ -+ public static double distanceSq(Entity e1, Entity e2) { -+ return distanceSq(e1.getX(),e1.getY(),e1.getZ(), e2.getX(),e2.getY(),e2.getZ()); -+ } -+ -+ /** -+ * Gets the distance sqaured between 2 block positions -+ * @param pos1 -+ * @param pos2 -+ * @return -+ */ -+ public static double distanceSq(BlockPos pos1, BlockPos pos2) { -+ return distanceSq(pos1.getX(), pos1.getY(), pos1.getZ(), pos2.getX(), pos2.getY(), pos2.getZ()); -+ } -+ -+ /** -+ * Gets the distance squared between 2 positions -+ * @param x1 -+ * @param y1 -+ * @param z1 -+ * @param x2 -+ * @param y2 -+ * @param z2 -+ * @return -+ */ -+ public static double distanceSq(double x1, double y1, double z1, double x2, double y2, double z2) { -+ return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2); -+ } -+ -+ /** -+ * Converts a NMS World/BlockPosition to Bukkit Location -+ * @param world -+ * @param x -+ * @param y -+ * @param z -+ * @return -+ */ -+ public static Location toLocation(Level world, double x, double y, double z) { -+ return new Location(world.getWorld(), x, y, z); -+ } -+ -+ /** -+ * Converts a NMS World/BlockPosition to Bukkit Location -+ * @param world -+ * @param pos -+ * @return -+ */ -+ public static Location toLocation(Level world, BlockPos pos) { -+ return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()); -+ } -+ -+ /** -+ * Converts an NMS entity's current location to a Bukkit Location -+ * @param entity -+ * @return -+ */ -+ public static Location toLocation(Entity entity) { -+ return new Location(entity.getCommandSenderWorld().getWorld(), entity.getX(), entity.getY(), entity.getZ()); -+ } -+ -+ public static org.bukkit.block.Block toBukkitBlock(Level world, BlockPos pos) { -+ return world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); -+ } -+ -+ public static BlockPos toBlockPosition(Location loc) { -+ return new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); -+ } -+ -+ public static boolean isEdgeOfChunk(BlockPos pos) { -+ final int modX = pos.getX() & 15; -+ final int modZ = pos.getZ() & 15; -+ return (modX == 0 || modX == 15 || modZ == 0 || modZ == 15); -+ } -+ -+ /** -+ * Posts a task to be executed asynchronously -+ * @param run -+ */ -+ public static void scheduleAsyncTask(Runnable run) { -+ asyncExecutor.execute(run); -+ } -+ -+ @Nonnull -+ public static ServerLevel getNMSWorld(@Nonnull org.bukkit.World world) { -+ return ((CraftWorld) world).getHandle(); -+ } -+ -+ public static ServerLevel getNMSWorld(@Nonnull org.bukkit.entity.Entity entity) { -+ return getNMSWorld(entity.getWorld()); -+ } -+ -+ public static ClipContext.Fluid getNMSFluidCollisionOption(TargetBlockInfo.FluidMode fluidMode) { -+ if (fluidMode == TargetBlockInfo.FluidMode.NEVER) { -+ return ClipContext.Fluid.NONE; -+ } -+ if (fluidMode == TargetBlockInfo.FluidMode.SOURCE_ONLY) { -+ return ClipContext.Fluid.SOURCE_ONLY; -+ } -+ if (fluidMode == TargetBlockInfo.FluidMode.ALWAYS) { -+ return ClipContext.Fluid.ANY; -+ } -+ return null; -+ } -+ -+ public static BlockFace toBukkitBlockFace(Direction enumDirection) { -+ switch (enumDirection) { -+ case DOWN: -+ return BlockFace.DOWN; -+ case UP: -+ return BlockFace.UP; -+ case NORTH: -+ return BlockFace.NORTH; -+ case SOUTH: -+ return BlockFace.SOUTH; -+ case WEST: -+ return BlockFace.WEST; -+ case EAST: -+ return BlockFace.EAST; -+ default: -+ return null; -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 37a51dee4cd37844e80fdd5c9853947201151dfc..2406879e76a110e96a4753e66366432a4bc52d9b 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -882,6 +882,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop CHUNK_STATUSES = ChunkStatus.getStatusList(); - private static final ChunkHolder.FullChunkStatus[] FULL_CHUNK_STATUSES = ChunkHolder.FullChunkStatus.values(); - private final AtomicReferenceArray>> futures; -- private volatile CompletableFuture> fullChunkFuture; -- private volatile CompletableFuture> tickingChunkFuture; -- private volatile CompletableFuture> entityTickingChunkFuture; -+ private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage -+ private volatile CompletableFuture> tickingChunkFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage -+ private volatile CompletableFuture> entityTickingChunkFuture; private volatile boolean isEntityTickingReady; // Paper - cache chunk ticking stage - private CompletableFuture chunkToSave; - public int oldTicketLevel; - private int ticketLevel; -@@ -63,6 +63,8 @@ public class ChunkHolder { - private boolean wasAccessibleSinceLastSave; - private boolean resendLight; - -+ private final ChunkMap chunkMap; // Paper -+ - public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { - this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); - this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; -@@ -78,10 +80,49 @@ public class ChunkHolder { - this.ticketLevel = this.oldTicketLevel; - this.queueLevel = this.oldTicketLevel; - this.setTicketLevel(level); -+ this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper -+ } -+ -+ // Paper start -+ @Nullable -+ public final LevelChunk getEntityTickingChunk() { -+ CompletableFuture> completablefuture = this.entityTickingChunkFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ @Nullable -+ public final LevelChunk getTickingChunk() { -+ CompletableFuture> completablefuture = this.tickingChunkFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ @Nullable -+ public final LevelChunk getFullReadyChunk() { -+ CompletableFuture> completablefuture = this.fullChunkFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ public final boolean isEntityTickingReady() { -+ return this.isEntityTickingReady; -+ } -+ -+ public final boolean isTickingReady() { -+ return this.isTickingReady; -+ } -+ -+ public final boolean isFullChunkReady() { -+ return this.isFullChunkReady; - } -+ // Paper end - - // CraftBukkit start -- public LevelChunk getFullChunk() { -+ public final LevelChunk getFullChunk() { // Paper - final for inline - if (!getFullChunkStatus(this.oldTicketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) return null; // note: using oldTicketLevel for isLoaded checks - return this.getFullChunkUnchecked(); - } -@@ -92,6 +133,14 @@ public class ChunkHolder { - return (either == null) ? null : (LevelChunk) either.left().orElse(null); - } - // CraftBukkit end -+ // Paper start - "real" get full chunk immediately -+ public final LevelChunk getFullChunkIfCached() { -+ // Note: Copied from above without ticket level check -+ CompletableFuture> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL); -+ Either either = (Either) statusFuture.getNow(null); -+ return either == null ? null : (LevelChunk) either.left().orElse(null); -+ } -+ // Paper end - - public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { - CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(leastStatus.getIndex()); -@@ -103,20 +152,23 @@ public class ChunkHolder { - return getStatus(this.ticketLevel).isOrAfter(leastStatus) ? this.getFutureIfPresentUnchecked(leastStatus) : ChunkHolder.UNLOADED_CHUNK_FUTURE; - } - -- public CompletableFuture> getTickingChunkFuture() { -+ public final CompletableFuture> getTickingFuture() { return this.getTickingChunkFuture(); } // Paper - OBFHELPER -+ public final CompletableFuture> getTickingChunkFuture() { // Paper - final for inline - return this.tickingChunkFuture; - } - -- public CompletableFuture> getEntityTickingChunkFuture() { -+ public final CompletableFuture> getEntityTickingFuture() { return this.getEntityTickingChunkFuture(); } // Paper - OBFHELPER -+ public final CompletableFuture> getEntityTickingChunkFuture() { // Paper - final for inline - return this.entityTickingChunkFuture; - } - -- public CompletableFuture> getFullChunkFuture() { -+ public final CompletableFuture> getFullChunkFuture() { return this.getFullChunkFuture(); } // Paper - OBFHELPER -+ public final CompletableFuture> getFullChunkFuture() { // Paper - final for inline - return this.fullChunkFuture; - } - - @Nullable -- public LevelChunk getTickingChunk() { -+ public final LevelChunk getTickingChunk() { // Paper - final for inline - CompletableFuture> completablefuture = this.getTickingChunkFuture(); - Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error - -@@ -141,7 +193,7 @@ public class ChunkHolder { - return null; - } - -- public CompletableFuture getChunkToSave() { -+ public final CompletableFuture getChunkToSave() { // Paper - final for inline - return this.chunkToSave; - } - -@@ -282,11 +334,11 @@ public class ChunkHolder { - }); - } - -- public ChunkPos getPos() { -+ public final ChunkPos getPos() { // Paper - final for inline - return this.pos; - } - -- public int getTicketLevel() { -+ public final int getTicketLevel() { // Paper - final for inline - return this.ticketLevel; - } - -@@ -357,13 +409,27 @@ public class ChunkHolder { - - this.wasAccessibleSinceLastSave |= flag3; - if (!flag2 && flag3) { -- this.fullChunkFuture = chunkStorage.unpackTicks(this); -+ // Paper start - cache ticking ready status -+ int expectCreateCount = ++this.fullChunkCreateCount; -+ this.fullChunkFuture = chunkStorage.unpackTicks(this); this.fullChunkFuture.thenAccept((either) -> { -+ if (either.left().isPresent() && ChunkHolder.this.fullChunkCreateCount == expectCreateCount) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ LevelChunk fullChunk = either.left().get(); -+ ChunkHolder.this.isFullChunkReady = true; -+ fullChunk.playerChunk = ChunkHolder.this; -+ -+ -+ } -+ }); -+ // Paper end - this.updateChunkToSave(this.fullChunkFuture); - } - - if (flag2 && !flag3) { - completablefuture = this.fullChunkFuture; - this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; -+ ++this.fullChunkCreateCount; // Paper - cache ticking ready status -+ this.isFullChunkReady = false; // Paper - cache ticking ready status - this.updateChunkToSave(((CompletableFuture>) completablefuture).thenApply((either1) -> { // CraftBukkit - decompile error - chunkStorage.getClass(); - return either1.ifLeft(chunkStorage::packTicks); -@@ -374,12 +440,24 @@ public class ChunkHolder { - boolean flag5 = playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.TICKING); - - if (!flag4 && flag5) { -- this.tickingChunkFuture = chunkStorage.postProcess(this); -+ // Paper start - cache ticking ready status -+ this.tickingChunkFuture = chunkStorage.postProcess(this); this.tickingChunkFuture.thenAccept((either) -> { -+ if (either.left().isPresent()) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ LevelChunk tickingChunk = either.left().get(); -+ ChunkHolder.this.isTickingReady = true; -+ -+ -+ -+ -+ } -+ }); -+ // Paper end - this.updateChunkToSave(this.tickingChunkFuture); - } - - if (flag4 && !flag5) { -- this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); -+ this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); this.isTickingReady = false; // Paper - cache chunk ticking stage - this.tickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; - } - -@@ -391,12 +469,24 @@ public class ChunkHolder { - throw (IllegalStateException) Util.pauseInIde((Throwable) (new IllegalStateException())); - } - -- this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); -+ // Paper start - cache ticking ready status -+ this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); this.entityTickingChunkFuture.thenAccept((either) -> { -+ if (either.left().isPresent()) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ LevelChunk entityTickingChunk = either.left().get(); -+ ChunkHolder.this.isEntityTickingReady = true; -+ -+ -+ -+ -+ } -+ }); -+ // Paper end - this.updateChunkToSave(this.entityTickingChunkFuture); - } - - if (flag6 && !flag7) { -- this.entityTickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); -+ this.entityTickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage - this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; - } - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index aaa56d121cdb66066e869b7cbdc2c863974d51b0..d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -54,6 +54,7 @@ import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; - import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; - import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; - import net.minecraft.network.protocol.game.DebugPackets; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.progress.ChunkProgressListener; - import net.minecraft.util.CsvOutput; - import net.minecraft.util.Mth; -@@ -144,6 +145,26 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - }; - // CraftBukkit end - -+ // Paper start - distance maps -+ private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); -+ -+ void addPlayerToDistanceMaps(ServerPlayer player) { -+ int chunkX = MCUtil.getChunkCoordinate(player.getX()); -+ int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); -+ // Note: players need to be explicitly added to distance maps before they can be updated -+ } -+ -+ void removePlayerFromDistanceMaps(ServerPlayer player) { -+ -+ } -+ -+ void updateMaps(ServerPlayer player) { -+ int chunkX = MCUtil.getChunkCoordinate(player.getX()); -+ int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); -+ // Note: players need to be explicitly added to distance maps before they can be updated -+ } -+ // Paper end -+ - public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag); - this.visibleChunkMap = this.updatingChunkMap.clone(); -@@ -233,6 +254,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - }; - } - -+ // Paper start -+ public final int getEffectiveViewDistance() { -+ // TODO this needs to be checked on update -+ // Mojang currently sets it to +1 of the configured view distance. So subtract one to get the one we really want. -+ return this.viewDistance - 1; -+ } -+ // Paper end -+ - private CompletableFuture, ChunkHolder.ChunkLoadingFailure>> getChunkRangeFuture(ChunkPos centerChunk, int margin, IntFunction distanceToStatus) { - List>> list = Lists.newArrayList(); - int j = centerChunk.x; -@@ -951,6 +980,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - if (!flag1) { - this.distanceManager.addPlayer(SectionPos.of((Entity) player), player); - } -+ this.addPlayerToDistanceMaps(player); // Paper - distance maps - } else { - SectionPos sectionposition = player.getLastSectionPos(); - -@@ -958,6 +988,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - if (!flag2) { - this.distanceManager.removePlayer(sectionposition, player); - } -+ this.removePlayerFromDistanceMaps(player); // Paper - distance maps - } - - for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { -@@ -1068,6 +1099,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - } - -+ this.updateMaps(player); // Paper - distance maps -+ - } - - @Override -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 7cc5070f70a4f740add9d971385ceaa4d44275a2..ef336645f3bd7a86129ad1dff7e1a15dc93d1e3e 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -42,6 +42,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana - import net.minecraft.world.level.storage.DimensionDataStorage; - import net.minecraft.world.level.storage.LevelData; - import net.minecraft.world.level.storage.LevelStorageSource; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper - - public class ServerChunkCache extends ChunkSource { - -@@ -49,7 +50,7 @@ public class ServerChunkCache extends ChunkSource { - private final DistanceManager distanceManager; - public final ChunkGenerator generator; - private final ServerLevel level; -- private final Thread mainThread; -+ public final Thread mainThread; // Paper - private -> public - private final ThreadedLevelLightEngine lightEngine; - private final ServerChunkCache.MainThreadExecutor mainThreadProcessor; - public final ChunkMap chunkMap; -@@ -62,6 +63,158 @@ public class ServerChunkCache extends ChunkSource { - private final ChunkAccess[] lastChunk = new ChunkAccess[4]; - @Nullable - private NaturalSpawner.SpawnState lastSpawnState; -+ // Paper start -+ final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock(); -+ final Long2ObjectOpenHashMap loadedChunkMap = new Long2ObjectOpenHashMap<>(8192, 0.5f); -+ -+ private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4]; -+ -+ private static int getChunkCacheKey(int x, int z) { -+ return x & 3 | ((z & 3) << 2); -+ } -+ -+ public void addLoadedChunk(LevelChunk chunk) { -+ this.loadedChunkMapSeqLock.acquireWrite(); -+ try { -+ this.loadedChunkMap.put(chunk.coordinateKey, chunk); -+ } finally { -+ this.loadedChunkMapSeqLock.releaseWrite(); -+ } -+ -+ // rewrite cache if we have to -+ // we do this since we also cache null chunks -+ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); -+ -+ this.lastLoadedChunks[cacheKey] = chunk; -+ } -+ -+ public void removeLoadedChunk(LevelChunk chunk) { -+ this.loadedChunkMapSeqLock.acquireWrite(); -+ try { -+ this.loadedChunkMap.remove(chunk.coordinateKey); -+ } finally { -+ this.loadedChunkMapSeqLock.releaseWrite(); -+ } -+ -+ // rewrite cache if we have to -+ // we do this since we also cache null chunks -+ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); -+ -+ LevelChunk cachedChunk = this.lastLoadedChunks[cacheKey]; -+ if (cachedChunk != null && cachedChunk.coordinateKey == chunk.coordinateKey) { -+ this.lastLoadedChunks[cacheKey] = null; -+ } -+ } -+ -+ public final LevelChunk getChunkAtIfLoadedMainThread(int x, int z) { -+ int cacheKey = getChunkCacheKey(x, z); -+ -+ LevelChunk cachedChunk = this.lastLoadedChunks[cacheKey]; -+ if (cachedChunk != null && cachedChunk.locX == x & cachedChunk.locZ == z) { -+ return this.lastLoadedChunks[cacheKey]; -+ } -+ -+ long chunkKey = ChunkPos.asLong(x, z); -+ -+ cachedChunk = this.loadedChunkMap.get(chunkKey); -+ // Skipping a null check to avoid extra instructions to improve inline capability -+ this.lastLoadedChunks[cacheKey] = cachedChunk; -+ return cachedChunk; -+ } -+ -+ public final LevelChunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) { -+ return this.loadedChunkMap.get(ChunkPos.asLong(x, z)); -+ } -+ -+ public final LevelChunk getChunkAtMainThread(int x, int z) { -+ LevelChunk ret = this.getChunkAtIfLoadedMainThread(x, z); -+ if (ret != null) { -+ return ret; -+ } -+ return (LevelChunk)this.getChunk(x, z, ChunkStatus.FULL, true); -+ } -+ -+ private long chunkFutureAwaitCounter; -+ -+ public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.mainThread) { -+ this.mainThreadProcessor.execute(() -> { -+ ServerChunkCache.this.getEntityTickingChunkAsync(x, z, onLoad); -+ }); -+ return; -+ } -+ this.getChunkFutureAsynchronously(x, z, 31, ChunkHolder::getEntityTickingFuture, onLoad); -+ } -+ -+ public void getTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.mainThread) { -+ this.mainThreadProcessor.execute(() -> { -+ ServerChunkCache.this.getTickingChunkAsync(x, z, onLoad); -+ }); -+ return; -+ } -+ this.getChunkFutureAsynchronously(x, z, 32, ChunkHolder::getTickingFuture, onLoad); -+ } -+ -+ public void getFullChunkAsync(int x, int z, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.mainThread) { -+ this.mainThreadProcessor.execute(() -> { -+ ServerChunkCache.this.getFullChunkAsync(x, z, onLoad); -+ }); -+ return; -+ } -+ this.getChunkFutureAsynchronously(x, z, 33, ChunkHolder::getFullChunkFuture, onLoad); -+ } -+ -+ private void getChunkFutureAsynchronously(int x, int z, int ticketLevel, Function>> futureGet, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.mainThread) { -+ throw new IllegalStateException(); -+ } -+ ChunkPos chunkPos = new ChunkPos(x, z); -+ Long identifier = this.chunkFutureAwaitCounter++; -+ this.distanceManager.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); -+ this.runDistanceManagerUpdates(); -+ -+ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(chunkPos.toLong()); -+ -+ if (chunk == null) { -+ throw new IllegalStateException("Expected playerchunk " + chunkPos + " in world '" + this.level.getWorld().getName() + "'"); -+ } -+ -+ CompletableFuture> future = futureGet.apply(chunk); -+ -+ future.whenCompleteAsync((either, throwable) -> { -+ try { -+ if (throwable != null) { -+ if (throwable instanceof ThreadDeath) { -+ throw (ThreadDeath)throwable; -+ } -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", throwable); -+ } else if (either.right().isPresent()) { -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "': " + either.right().get().toString()); -+ } -+ -+ try { -+ if (onLoad != null) { -+ chunkMap.callbackExecutor.execute(() -> { -+ onLoad.accept(either == null ? null : either.left().orElse(null)); // indicate failure to the callback. -+ }); -+ } -+ } catch (Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Load callback for future await failed " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", thr); -+ return; -+ } -+ } finally { -+ // due to odd behaviour with CB unload implementation we need to have these AFTER the load callback. -+ ServerChunkCache.this.distanceManager.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); -+ ServerChunkCache.this.distanceManager.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); -+ } -+ }, this.mainThreadProcessor); -+ } -+ // Paper end - - public ServerChunkCache(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldloadlistener, Supplier supplier) { - this.level = worldserver; -@@ -123,6 +276,49 @@ public class ServerChunkCache extends ChunkSource { - this.lastChunk[0] = chunk; - } - -+ // Paper start - "real" get chunk if loaded -+ // Note: Partially copied from the getChunkAt method below -+ @Nullable -+ public LevelChunk getChunkAtIfCachedImmediately(int x, int z) { -+ long k = ChunkPos.asLong(x, z); -+ -+ // Note: Bypass cache since we need to check ticket level, and to make this MT-Safe -+ -+ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(k); -+ if (playerChunk == null) { -+ return null; -+ } -+ -+ return playerChunk.getFullChunkIfCached(); -+ } -+ -+ @Nullable -+ public LevelChunk getChunkAtIfLoadedImmediately(int x, int z) { -+ long k = ChunkPos.asLong(x, z); -+ -+ if (Thread.currentThread() == this.mainThread) { -+ return this.getChunkAtIfLoadedMainThread(x, z); -+ } -+ -+ LevelChunk ret = null; -+ long readlock; -+ do { -+ readlock = this.loadedChunkMapSeqLock.acquireRead(); -+ try { -+ ret = this.loadedChunkMap.get(k); -+ } catch (Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // re-try, this means a CME occurred... -+ continue; -+ } -+ } while (!this.loadedChunkMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ // Paper end -+ - @Nullable - @Override - public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) { -@@ -406,10 +602,9 @@ public class ServerChunkCache extends ChunkSource { - - this.lastSpawnState = spawnercreature_d; - this.level.getProfiler().pop(); -- List list = Lists.newArrayList(this.chunkMap.getChunks()); -- -- Collections.shuffle(list); -- list.forEach((playerchunk) -> { -+ //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper -+ //Collections.shuffle(list); // Paper -+ this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... - Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); - - if (optional.isPresent()) { -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 23506a8903ce64fbfe849bb94e589bdbb6e61a74..34ed8f0d348e7bc2339660ebc6490057ba9ef214 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -12,6 +12,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry; - import it.unimi.dsi.fastutil.longs.LongSet; - import it.unimi.dsi.fastutil.longs.LongSets; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.ObjectIterator; - import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; - import java.io.BufferedWriter; -@@ -163,7 +164,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - private final Map entitiesByUuid = Maps.newHashMap(); - private final Queue toAddAfterTick = Queues.newArrayDeque(); - private final List players = Lists.newArrayList(); -- private final ServerChunkCache chunkSource; -+ public final ServerChunkCache chunkSource; // Paper - public - boolean tickingEntities; - private final MinecraftServer server; - public final PrimaryLevelData worldDataServer; // CraftBukkit - type -@@ -1682,7 +1683,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - ObjectIterator objectiterator = spawnercreature_d.getMobCategoryCounts().object2IntEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); -+ Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix - - bufferedwriter.write(String.format("spawn_count.%s: %d\n", ((MobCategory) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey()).getName(), it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue())); - } -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index d62c74318ac3bb139570fe2b5f12cdb6e900d70d..8d7fa186b0b47688f2822038b46c33b3f32d28ae 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -221,6 +221,8 @@ public class ServerPlayer extends Player implements ContainerListener { - public Integer clientViewDistance; - // CraftBukkit end - -+ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper -+ - public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { - super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); - this.respawnDimension = Level.OVERWORLD; -@@ -233,6 +235,8 @@ public class ServerPlayer extends Player implements ContainerListener { - this.fudgeSpawnLocation(world); - this.textFilter = server.createTextFilterForPlayer(this); - -+ this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -+ - // CraftBukkit start - this.displayName = this.getScoreboardName(); - this.canPickUpLoot = true; -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 34dd10908101a6709e389bfa1d1c2a6599e8b102..cf3ced15c9a87e7a4dbccba17c57a7b32b77566c 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -25,6 +25,7 @@ public class TicketType { - public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); - public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit - public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit -+ public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper - - public static TicketType create(String name, Comparator comparator) { - return new TicketType<>(name, comparator, 0L); -diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java -index 0a9f76b7aef5c12879a408954384b4e70ac5b484..fdc56d602ef0bf3c50842f3081a3e6523b9765b0 100644 ---- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java -+++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java -@@ -141,6 +141,26 @@ public class WorldGenRegion implements WorldGenLevel { - return chunkX >= this.firstPos.x && chunkX <= this.lastPos.x && chunkZ >= this.firstPos.z && chunkZ <= this.lastPos.z; - } - -+ // Paper start - if loaded util -+ @Nullable -+ @Override -+ public ChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ return this.getChunk(x, z, ChunkStatus.FULL, false); -+ } -+ -+ @Override -+ public BlockState getTypeIfLoaded(BlockPos blockposition) { -+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getBlockState(blockposition); -+ } -+ -+ @Override -+ public FluidState getFluidIfLoaded(BlockPos blockposition) { -+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getFluidState(blockposition); -+ } -+ // Paper end -+ - @Override - public BlockState getBlockState(BlockPos pos) { - return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4).getBlockState(pos); -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 8766e79c1ed7a8557ef5fd91e8f3c65c3467efcd..35f3940cebb00ee29da54b1ee148ee931fa11636 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -218,9 +218,9 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - private final MinecraftServer server; - public ServerPlayer player; - private int tickCount; -- private long keepAliveTime; -- private boolean keepAlivePending; -- private long keepAliveChallenge; -+ private long keepAliveTime; private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER -+ private boolean keepAlivePending; private void setPendingPing(boolean isPending) { this.keepAlivePending = isPending;}; private boolean isPendingPing() { return this.keepAlivePending;}; // Paper - OBFHELPER -+ private long keepAliveChallenge; private void setKeepAliveID(long keepAliveID) { this.keepAliveChallenge = keepAliveID;}; private long getKeepAliveID() {return this.keepAliveChallenge; }; // Paper - OBFHELPER - // CraftBukkit start - multithreaded fields - private volatile int chatSpamTickCount; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(ServerGamePacketListenerImpl.class, "chatThrottle"); -diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java -index 497e23e4ebf0d8b4e1a90ea3909608cdc066265f..97bde5f8402452e59b0da94edfe1b970cdb86748 100644 ---- a/src/main/java/net/minecraft/util/BitStorage.java -+++ b/src/main/java/net/minecraft/util/BitStorage.java -@@ -84,6 +84,7 @@ public class BitStorage { - return (int) (k >> l & this.mask); - } - -+ public final long[] getDataBits() { return this.getRaw(); } // Paper - OBFHELPER - public long[] getRaw() { - return this.data; - } -diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -index 03831adce7905916423d8c3834c42c90f3a1ca8f..e48fcfe2e4ff151258ae1d84cc0995d2cd54e9a6 100644 ---- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -+++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -@@ -68,6 +68,15 @@ public abstract class BlockableEventLoop implements Processo - - } - -+ // Paper start -+ public void scheduleOnMain(Runnable r0) { -+ // postToMainThread does not work the same as older versions of mc -+ // This method is actually used to create a TickTask, which can then be posted onto main -+ this.addTask(this.wrapRunnable(r0)); -+ } -+ // Paper end -+ -+ public final void addTask(R r0) { tell(r0); }; // Paper - OBFHELPER - public void tell(R r0) { - this.pendingRunnables.add(r0); - LockSupport.unpark(this.getRunningThread()); -diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index ff482d0349c18d0d1ba902ea0d10611b1ca4e588..102298d57cf3143092d04ab1d5d0d69b28d696ea 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -3,6 +3,7 @@ package net.minecraft.world.entity; - import com.google.common.collect.ImmutableSet; - import java.util.Optional; - import java.util.Set; // Paper -+import java.util.Map; // Paper - import java.util.UUID; - import java.util.function.Function; - import java.util.stream.Stream; -@@ -441,8 +442,8 @@ public class EntityType { - return this.dimensions.height; - } - -- @Nullable -- public T create(Level world) { -+ public T create(Level world) { return this.create(world); } // Paper - OBFHELPER -+ @Nullable public T create(Level world) { // Paper - OBFHELPER - return this.factory.create(this, world); - } - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 3245c0d7310285dd423c5c1d44c26fb8c3d7bf7f..9e5dde73bd65bf4e51352c628fba024c36e29ef1 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -228,6 +228,7 @@ public abstract class LivingEntity extends Entity { - public boolean collides = true; - public Set collidableExemptions = new HashSet<>(); - public boolean canPickUpLoot; -+ public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper - - @Override - public float getBukkitYaw() { -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index f268b7e6f89068267ea2f07f7505e0dc69968b73..99cb4dc1a1009d4a29e651c94d21babcc61388ed 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -223,6 +223,7 @@ public abstract class Mob extends LivingEntity { - return this.target; - } - -+ public org.bukkit.craftbukkit.entity.CraftMob getBukkitMob() { return (org.bukkit.craftbukkit.entity.CraftMob) super.getBukkitEntity(); } // Paper - public void setTarget(@Nullable LivingEntity target) { - // CraftBukkit start - fire event - setGoalTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true); -diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java -index d090ffcf08e32a08d4b815b79ed58fc00bc26fd0..920ae9af8985705a0ada7da5b7085a1ed8ca7f27 100644 ---- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java -+++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java -@@ -12,6 +12,8 @@ import org.bukkit.event.entity.EntityUnleashEvent; - - public abstract class PathfinderMob extends Mob { - -+ public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper -+ - protected PathfinderMob(EntityType type, Level world) { - super(type, world); - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/Monster.java b/src/main/java/net/minecraft/world/entity/monster/Monster.java -index fa886a89195312acfe53605169216ce95642ba87..407b7168b7e8d4408824039c06d02792d3c7e534 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Monster.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Monster.java -@@ -27,6 +27,7 @@ import net.minecraft.world.level.ServerLevelAccessor; - - public abstract class Monster extends PathfinderMob implements Enemy { - -+ public org.bukkit.craftbukkit.entity.CraftMonster getBukkitMonster() { return (org.bukkit.craftbukkit.entity.CraftMonster) super.getBukkitEntity(); } // Paper - protected Monster(EntityType type, Level world) { - super(type, world); - this.xpReward = 5; -diff --git a/src/main/java/net/minecraft/world/entity/player/Inventory.java b/src/main/java/net/minecraft/world/entity/player/Inventory.java -index c0e0a8deabf3dffcc974f9e5bea2332d0d6e57a5..7d06838c4c8eef7ebff64ae094cd12404b9edd53 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Inventory.java -+++ b/src/main/java/net/minecraft/world/entity/player/Inventory.java -@@ -37,7 +37,7 @@ public class Inventory implements Container, Nameable { - public final NonNullList items; - public final NonNullList armor; - public final NonNullList offhand; -- private final List> compartments; -+ private final List> compartments; public final List> getComponents() { return compartments; } // Paper - OBFHELPER - public int selected; - public final Player player; - private ItemStack carried; -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index da0fabafad0aa6c124abf52f8da68c73b7264fe9..2a6a6e291efbd7cc8fed6532f18321bd141e1306 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -101,7 +101,7 @@ public final class ItemStack { - })).apply(instance, ItemStack::new); - }); - private static final Logger LOGGER = LogManager.getLogger(); -- public static final ItemStack EMPTY = new ItemStack((Item) null); -+ public static final ItemStack EMPTY = new ItemStack((Item) null);public static final ItemStack NULL_ITEM = EMPTY; // Paper - OBFHELPER - public static final DecimalFormat ATTRIBUTE_MODIFIER_FORMAT = (DecimalFormat) Util.make((new DecimalFormat("#.##")), (decimalformat) -> { // CraftBukkit - decompile error - decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); - }); -@@ -658,6 +658,24 @@ public final class ItemStack { - return this.tag != null ? this.tag.getList("Enchantments", 10) : new ListTag(); - } - -+ // Paper start - (this is just a good no conflict location) -+ public org.bukkit.inventory.ItemStack asBukkitMirror() { -+ return CraftItemStack.asCraftMirror(this); -+ } -+ public org.bukkit.inventory.ItemStack asBukkitCopy() { -+ return CraftItemStack.asCraftMirror(this.copy()); -+ } -+ public static ItemStack fromBukkitCopy(org.bukkit.inventory.ItemStack itemstack) { -+ return CraftItemStack.asNMSCopy(itemstack); -+ } -+ private org.bukkit.craftbukkit.inventory.CraftItemStack bukkitStack; -+ public org.bukkit.inventory.ItemStack getBukkitStack() { -+ if (bukkitStack == null || bukkitStack.getHandle() != this) { -+ bukkitStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this); -+ } -+ return bukkitStack; -+ } -+ // Paper end - public void setTag(@Nullable CompoundTag tag) { - this.tag = tag; - if (this.getItem().canBeDepleted()) { -@@ -756,6 +774,7 @@ public final class ItemStack { - return this.tag != null && this.tag.contains("Enchantments", 9) ? !this.tag.getList("Enchantments", 10).isEmpty() : false; - } - -+ public void getOrCreateTagAndSet(String s, Tag nbtbase) { addTagElement(s, nbtbase);} // Paper - OBFHELPER - public void addTagElement(String key, Tag tag) { - this.getOrCreateTag().put(key, tag); - } -@@ -841,6 +860,7 @@ public final class ItemStack { - // CraftBukkit start - @Deprecated - public void setItem(Item item) { -+ this.bukkitStack = null; // Paper - this.item = item; - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java b/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java -index e38c38c7d7679f267283a5ac6245e2261829aa05..2285a0cf6a35d06de77f94ad8a14ae91c1a7929f 100644 ---- a/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java -+++ b/src/main/java/net/minecraft/world/item/alchemy/PotionUtils.java -@@ -121,6 +121,7 @@ public class PotionUtils { - return compound == null ? Potions.EMPTY : Potion.byName(compound.getString("Potion")); - } - -+ public static ItemStack addPotionToItemStack(ItemStack itemstack, Potion potionregistry) { return setPotion(itemstack, potionregistry); } // Paper - OBFHELPER - public static ItemStack setPotion(ItemStack stack, Potion potion) { - ResourceLocation minecraftkey = Registry.POTION.getKey(potion); - -diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java -index 3bbee667743d9a249c1513ea426e7a51d9185c4c..2feb187f62be5cf5d354a1e806087417cc189ab1 100644 ---- a/src/main/java/net/minecraft/world/level/BlockGetter.java -+++ b/src/main/java/net/minecraft/world/level/BlockGetter.java -@@ -8,9 +8,11 @@ import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; - import net.minecraft.util.Mth; -+import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.entity.BlockEntity; - import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.level.material.FluidState; -+import net.minecraft.world.level.material.Material; - import net.minecraft.world.phys.AABB; - import net.minecraft.world.phys.BlockHitResult; - import net.minecraft.world.phys.Vec3; -@@ -22,6 +24,19 @@ public interface BlockGetter { - BlockEntity getBlockEntity(BlockPos pos); - - BlockState getBlockState(BlockPos pos); -+ // Paper start - if loaded util -+ BlockState getTypeIfLoaded(BlockPos blockposition); -+ default Material getMaterialIfLoaded(BlockPos blockposition) { -+ BlockState type = this.getTypeIfLoaded(blockposition); -+ return type == null ? null : type.getMaterial(); -+ } -+ -+ default Block getBlockIfLoaded(BlockPos blockposition) { -+ BlockState type = this.getTypeIfLoaded(blockposition); -+ return type == null ? null : type.getBlock(); -+ } -+ FluidState getFluidIfLoaded(BlockPos blockposition); -+ // Paper end - - FluidState getFluidState(BlockPos pos); - -diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java -index 0caf067f9d888f9769db1503284d444e97c60c9c..7ccf830146c252cff8e22553d293e02d4b53dad8 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkPos.java -+++ b/src/main/java/net/minecraft/world/level/ChunkPos.java -@@ -12,27 +12,32 @@ public class ChunkPos { - public static final long INVALID_CHUNK_POS = asLong(1875016, 1875016); - public final int x; - public final int z; -+ public final long longKey; // Paper - - public ChunkPos(int x, int z) { - this.x = x; - this.z = z; -+ this.longKey = asLong(this.x, this.z); // Paper - } - - public ChunkPos(BlockPos pos) { - this.x = pos.getX() >> 4; - this.z = pos.getZ() >> 4; -+ this.longKey = asLong(this.x, this.z); // Paper - } - - public ChunkPos(long pos) { - this.x = (int) pos; - this.z = (int) (pos >> 32); -+ this.longKey = asLong(this.x, this.z); // Paper - } - - public long toLong() { -- return asLong(this.x, this.z); -+ return longKey; // Paper - } - -- public static long asLong(int chunkX, int chunkZ) { -+ public static long pair(final BlockPos pos) { return asLong(pos.getX() >> 4, pos.getZ() >> 4); } // Paper - OBFHELPER -+ public static long asLong(int chunkX, int chunkZ) { - return (long) chunkX & 4294967295L | ((long) chunkZ & 4294967295L) << 32; - } - -diff --git a/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java b/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java -index 82c14e1ac66792137ab9e647c868a698c1ec9929..2b4f9849d668dede4d1f7d10f3a6ec9ef7a6d828 100644 ---- a/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java -+++ b/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java -@@ -20,6 +20,18 @@ public enum EmptyBlockGetter implements BlockGetter { - return null; - } - -+ // Paper start - If loaded util -+ @Override -+ public FluidState getFluidIfLoaded(BlockPos blockposition) { -+ return this.getFluidState(blockposition); -+ } -+ -+ @Override -+ public BlockState getTypeIfLoaded(BlockPos blockposition) { -+ return this.getBlockState(blockposition); -+ } -+ // Paper end -+ - @Override - public BlockState getBlockState(BlockPos pos) { - return Blocks.AIR.defaultBlockState(); -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index f08de81dcc4acd5a3e44407b431ce827a19b2e9c..5cc4c2668df72f83fb1526f4586b71d2ae0103dc 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -74,6 +74,7 @@ import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.block.CapturedBlockState; -+import org.bukkit.craftbukkit.block.CraftBlockState; - import org.bukkit.craftbukkit.block.data.CraftBlockData; - import org.bukkit.event.block.BlockPhysicsEvent; - // CraftBukkit end -@@ -255,17 +256,50 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return y < 0 || y >= 256; - } - -- public LevelChunk getChunkAt(BlockPos pos) { -+ public final LevelChunk getChunkAt(BlockPos pos) { // Paper - help inline - return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); - } - - @Override -- public LevelChunk getChunk(int chunkX, int chunkZ) { -- return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL); -+ public final LevelChunk getChunk(int chunkX, int chunkZ) { // Paper - final to help inline -+ return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true); // Paper - avoid a method jump -+ } -+ -+ // Paper start - if loaded -+ @Nullable -+ @Override -+ public final ChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ return ((ServerLevel)this).chunkSource.getChunkAtIfLoadedImmediately(x, z); - } - - @Override -- public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { -+ public final BlockState getTypeIfLoaded(BlockPos blockposition) { -+ // CraftBukkit start - tree generation -+ if (captureTreeGeneration) { -+ CraftBlockState previous = capturedBlockStates.get(blockposition); -+ if (previous != null) { -+ return previous.getHandle(); -+ } -+ } -+ // CraftBukkit end -+ if (!isInWorldBounds(blockposition)) { -+ return Blocks.AIR.defaultBlockState(); -+ } -+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ -+ return chunk == null ? null : chunk.getBlockState(blockposition); -+ } -+ -+ @Override -+ public FluidState getFluidIfLoaded(BlockPos blockposition) { -+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ -+ return chunk == null ? null : chunk.getFluidState(blockposition); -+ } -+ // Paper end -+ -+ @Override -+ public final ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { // Paper - final for inline - ChunkAccess ichunkaccess = this.getChunkSource().getChunk(chunkX, chunkZ, leastStatus, create); - - if (ichunkaccess == null && create) { -@@ -276,7 +310,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - - @Override -- public boolean setBlock(BlockPos pos, BlockState state, int flags) { -+ public final boolean setBlock(BlockPos pos, BlockState state, int flags) { // Paper - final for inline - return this.setBlock(pos, state, flags, 512); - } - -@@ -422,8 +456,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - public void onBlockStateChange(BlockPos pos, BlockState oldBlock, BlockState newBlock) {} - -- @Override -- public boolean removeBlock(BlockPos pos, boolean move) { -+ public boolean setAir(BlockPos blockposition) { return this.removeBlock(blockposition, false); } // Paper - OBFHELPER -+ public boolean setAir(BlockPos blockposition, boolean moved) { return this.removeBlock(blockposition, moved); } // Paper - OBFHELPER -+ @Override public boolean removeBlock(BlockPos pos, boolean move) { // Paper - OBFHELPER - FluidState fluid = this.getFluidState(pos); - - return this.setBlock(pos, fluid.createLegacyBlock(), 3 | (move ? 64 : 0)); -@@ -569,7 +604,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - if (isOutsideBuildHeight(pos)) { - return Blocks.VOID_AIR.defaultBlockState(); - } else { -- LevelChunk chunk = this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); -+ LevelChunk chunk = (LevelChunk) this.getChunkSource().getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, true); // Paper - manually inline to reduce hops and avoid unnecessary null check to reduce total byte code size, this should never return null and if it does we will see it the next line but the real stack trace will matter in the chunk engine - - return chunk.getBlockState(pos); - } -diff --git a/src/main/java/net/minecraft/world/level/LevelReader.java b/src/main/java/net/minecraft/world/level/LevelReader.java -index b6877b78bf6ecf2069e59028f8910826c8b4eafe..6e4a53291ee87fac6d81d4ab9746906b6ae1b453 100644 ---- a/src/main/java/net/minecraft/world/level/LevelReader.java -+++ b/src/main/java/net/minecraft/world/level/LevelReader.java -@@ -18,6 +18,7 @@ import net.minecraft.world.phys.AABB; - - public interface LevelReader extends BlockAndTintGetter, CollisionGetter, BiomeManager.NoiseBiomeSource { - -+ @Nullable ChunkAccess getChunkIfLoadedImmediately(int x, int z); // Paper - ifLoaded api (we need this since current impl blocks if the chunk is loading) - @Nullable - ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create); - -diff --git a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java b/src/main/java/net/minecraft/world/level/PathNavigationRegion.java -index f1d759d87291f469bde3b433031a6e7c6a19fbf2..6db3f4efa6ea4a09aad7684a3b7cc7479fad2f5c 100644 ---- a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java -+++ b/src/main/java/net/minecraft/world/level/PathNavigationRegion.java -@@ -4,6 +4,7 @@ import java.util.function.Predicate; - import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.BlockEntity; -@@ -23,7 +24,7 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { - protected final int centerZ; - protected final ChunkAccess[][] chunks; - protected boolean allEmpty; -- protected final Level level; -+ protected final Level level; protected final Level getWorld() { return level; } // Paper - OBFHELPER - - public PathNavigationRegion(Level world, BlockPos minPos, BlockPos maxPos) { - this.level = world; -@@ -42,7 +43,7 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { - - for (k = this.centerX; k <= i; ++k) { - for (l = this.centerZ; l <= j; ++l) { -- this.chunks[k - this.centerX][l - this.centerZ] = ichunkprovider.getChunkNow(k, l); -+ this.chunks[k - this.centerX][l - this.centerZ] = ((ServerLevel)world).getChunkSource().getChunkAtIfLoadedMainThreadNoCache(k, l); // Paper - } - } - -@@ -67,7 +68,7 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { - int k = i - this.centerX; - int l = j - this.centerZ; - -- if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { -+ if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { // Paper - if this changes, update getChunkIfLoaded below - ChunkAccess ichunkaccess = this.chunks[k][l]; - - return (ChunkAccess) (ichunkaccess != null ? ichunkaccess : new EmptyLevelChunk(this.level, new ChunkPos(i, j))); -@@ -86,6 +87,29 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { - return this.getChunk(chunkX, chunkZ); - } - -+ // Paper start - if loaded util -+ private ChunkAccess getChunkIfLoaded(int x, int z) { -+ int k = x - this.centerX; -+ int l = z - this.centerZ; -+ -+ if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { -+ return this.chunks[k][l]; -+ } -+ return null; -+ } -+ @Override -+ public FluidState getFluidIfLoaded(BlockPos blockposition) { -+ ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getFluidState(blockposition); -+ } -+ -+ @Override -+ public BlockState getTypeIfLoaded(BlockPos blockposition) { -+ ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getBlockState(blockposition); -+ } -+ // Paper end -+ - @Nullable - @Override - public BlockEntity getBlockEntity(BlockPos pos) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index c9713d1ab6498c09790503f673b31b5ef30ce4f3..e6928557a79f51302975f2832ec911c2692eaaeb 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -687,6 +687,7 @@ public abstract class BlockBehaviour { - return this.cache != null ? this.cache.isCollisionShapeFullBlock : Block.isShapeFullBlock(this.getCollisionShape(world, pos)); - } - -+ public final BlockState getBlockData() { return asState(); } // Paper - OBFHELPER - protected abstract BlockState asState(); - - public boolean requiresCorrectToolForDrops() { -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index fe1c10e5eeb434cd24e94b3247abbf5f73fce9cc..31f17956b3b031d1a47bda4d282554c8a7853097 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -47,6 +47,7 @@ public class WorldBorder { - return this.getDistanceToBorder(entity.getX(), entity.getZ()); - } - -+ public final VoxelShape asVoxelShape(){ return getCollisionShape();} // Paper - OBFHELPER - public VoxelShape getCollisionShape() { - return this.extent.getCollisionShape(); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 5a91d74f0acf393dbf098719b0924a4c00cf7128..e2c5a17aa72d1a5412d76881187d4d9ad1763297 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -59,7 +59,7 @@ public class LevelChunk implements ChunkAccess { - - private static final Logger LOGGER = LogManager.getLogger(); - @Nullable -- public static final LevelChunkSection EMPTY_SECTION = null; -+ public static final LevelChunkSection EMPTY_SECTION = null; public static final LevelChunkSection EMPTY_CHUNK_SECTION = EMPTY_SECTION; // Paper - OBFHELPER - private final LevelChunkSection[] sections; - private ChunkBiomeContainer biomes; - private final Map pendingBlockEntities; -@@ -82,7 +82,7 @@ public class LevelChunk implements ChunkAccess { - private Supplier fullStatus; - @Nullable - private Consumer postLoad; -- private final ChunkPos chunkPos; -+ private final ChunkPos chunkPos; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key - private volatile boolean isLightCorrect; - - public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes) { -@@ -99,7 +99,8 @@ public class LevelChunk implements ChunkAccess { - this.postProcessing = new ShortList[16]; - this.entitySlices = (List[]) (new List[16]); // Spigot - this.world = (ServerLevel) world; // CraftBukkit - type -- this.chunkPos = pos; -+ this.locX = pos.x; this.locZ = pos.z; // Paper - reduce need for field look ups -+ this.chunkPos = pos; this.coordinateKey = ChunkPos.asLong(locX, locZ); // Paper - cache long key - this.upgradeData = upgradeData; - Heightmap.Types[] aheightmap_type = Heightmap.Types.values(); - int j = aheightmap_type.length; -@@ -145,6 +146,110 @@ public class LevelChunk implements ChunkAccess { - public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY); - // CraftBukkit end - -+ // Paper start -+ public final com.destroystokyo.paper.util.maplist.EntityList entities = new com.destroystokyo.paper.util.maplist.EntityList(); -+ public ChunkHolder playerChunk; -+ -+ static final int NEIGHBOUR_CACHE_RADIUS = 3; -+ public static int getNeighbourCacheRadius() { -+ return NEIGHBOUR_CACHE_RADIUS; -+ } -+ -+ boolean loadedTicketLevel; -+ private long neighbourChunksLoadedBitset; -+ private final LevelChunk[] loadedNeighbourChunks = new LevelChunk[(NEIGHBOUR_CACHE_RADIUS * 2 + 1) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)]; -+ -+ private static int getNeighbourIndex(final int relativeX, final int relativeZ) { -+ // index = (relativeX + NEIGHBOUR_CACHE_RADIUS) + (relativeZ + NEIGHBOUR_CACHE_RADIUS) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1) -+ // optimised variant of the above by moving some of the ops to compile time -+ return relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))); -+ } -+ -+ public final LevelChunk getRelativeNeighbourIfLoaded(final int relativeX, final int relativeZ) { -+ return this.loadedNeighbourChunks[getNeighbourIndex(relativeX, relativeZ)]; -+ } -+ -+ public final boolean isNeighbourLoaded(final int relativeX, final int relativeZ) { -+ return (this.neighbourChunksLoadedBitset & (1L << getNeighbourIndex(relativeX, relativeZ))) != 0; -+ } -+ -+ public final void setNeighbourLoaded(final int relativeX, final int relativeZ, final LevelChunk chunk) { -+ if (chunk == null) { -+ throw new IllegalArgumentException("Chunk must be non-null, neighbour: (" + relativeX + "," + relativeZ + "), chunk: " + this.chunkPos); -+ } -+ final long before = this.neighbourChunksLoadedBitset; -+ final int index = getNeighbourIndex(relativeX, relativeZ); -+ this.loadedNeighbourChunks[index] = chunk; -+ this.neighbourChunksLoadedBitset |= (1L << index); -+ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); -+ } -+ -+ public final void setNeighbourUnloaded(final int relativeX, final int relativeZ) { -+ final long before = this.neighbourChunksLoadedBitset; -+ final int index = getNeighbourIndex(relativeX, relativeZ); -+ this.loadedNeighbourChunks[index] = null; -+ this.neighbourChunksLoadedBitset &= ~(1L << index); -+ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); -+ } -+ -+ public final void resetNeighbours() { -+ final long before = this.neighbourChunksLoadedBitset; -+ this.neighbourChunksLoadedBitset = 0L; -+ java.util.Arrays.fill(this.loadedNeighbourChunks, null); -+ this.onNeighbourChange(before, 0L); -+ } -+ -+ protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { -+ -+ } -+ -+ public final boolean isAnyNeighborsLoaded() { -+ return neighbourChunksLoadedBitset != 0; -+ } -+ public final boolean areNeighboursLoaded(final int radius) { -+ return LevelChunk.areNeighboursLoaded(this.neighbourChunksLoadedBitset, radius); -+ } -+ -+ public static boolean areNeighboursLoaded(final long bitset, final int radius) { -+ // index = relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))) -+ switch (radius) { -+ case 0: { -+ return (bitset & (1L << getNeighbourIndex(0, 0))) != 0; -+ } -+ case 1: { -+ long mask = 0L; -+ for (int dx = -1; dx <= 1; ++dx) { -+ for (int dz = -1; dz <= 1; ++dz) { -+ mask |= (1L << getNeighbourIndex(dx, dz)); -+ } -+ } -+ return (bitset & mask) == mask; -+ } -+ case 2: { -+ long mask = 0L; -+ for (int dx = -2; dx <= 2; ++dx) { -+ for (int dz = -2; dz <= 2; ++dz) { -+ mask |= (1L << getNeighbourIndex(dx, dz)); -+ } -+ } -+ return (bitset & mask) == mask; -+ } -+ case 3: { -+ long mask = 0L; -+ for (int dx = -3; dx <= 3; ++dx) { -+ for (int dz = -3; dz <= 3; ++dz) { -+ mask |= (1L << getNeighbourIndex(dx, dz)); -+ } -+ } -+ return (bitset & mask) == mask; -+ } -+ -+ default: -+ throw new IllegalArgumentException("Radius not recognized: " + radius); -+ } -+ } -+ // Paper end -+ - public LevelChunk(Level world, ProtoChunk protoChunk) { - this(world, protoChunk.getPos(), protoChunk.getBiomes(), protoChunk.getUpgradeData(), protoChunk.getBlockTicks(), protoChunk.getLiquidTicks(), protoChunk.getInhabitedTime(), protoChunk.getSections(), (Consumer) null); - Iterator iterator = protoChunk.getEntities().iterator(); -@@ -250,6 +355,18 @@ public class LevelChunk implements ChunkAccess { - } - } - -+ // Paper start - If loaded util -+ @Override -+ public FluidState getFluidIfLoaded(BlockPos blockposition) { -+ return this.getFluidState(blockposition); -+ } -+ -+ @Override -+ public BlockState getTypeIfLoaded(BlockPos blockposition) { -+ return this.getBlockState(blockposition); -+ } -+ // Paper end -+ - @Override - public FluidState getFluidState(BlockPos pos) { - return this.getFluidState(pos.getX(), pos.getY(), pos.getZ()); -@@ -390,6 +507,7 @@ public class LevelChunk implements ChunkAccess { - entity.xChunk = this.chunkPos.x; - entity.yChunk = k; - entity.zChunk = this.chunkPos.z; -+ this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); - } - -@@ -413,6 +531,7 @@ public class LevelChunk implements ChunkAccess { - } - - this.entitySlices[section].remove(entity); -+ this.entities.remove(entity); // Paper - } - - @Override -@@ -434,6 +553,7 @@ public class LevelChunk implements ChunkAccess { - return this.getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); - } - -+ @Nullable public final BlockEntity getTileEntityImmediately(BlockPos pos) { return this.getBlockEntity(pos, EntityCreationType.IMMEDIATE); } // Paper - OBFHELPER - @Nullable - public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType) { - // CraftBukkit start -@@ -545,7 +665,25 @@ public class LevelChunk implements ChunkAccess { - - // CraftBukkit start - public void loadCallback() { -+ // Paper start - neighbour cache -+ int chunkX = this.chunkPos.x; -+ int chunkZ = this.chunkPos.z; -+ ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); -+ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { -+ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { -+ LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); -+ if (neighbour != null) { -+ neighbour.setNeighbourLoaded(-dx, -dz, this); -+ // should be in cached already -+ this.setNeighbourLoaded(dx, dz, neighbour); -+ } -+ } -+ } -+ this.setNeighbourLoaded(0, 0, this); -+ this.loadedTicketLevel = true; -+ // Paper end - neighbour cache - org.bukkit.Server server = this.world.getCraftServer(); -+ ((ServerLevel)this.world).getChunkSource().addLoadedChunk(this); // Paper - if (server != null) { - /* - * If it's a new world, the first few chunks are generated inside -@@ -584,6 +722,22 @@ public class LevelChunk implements ChunkAccess { - server.getPluginManager().callEvent(unloadEvent); - // note: saving can be prevented, but not forced if no saving is actually required - this.mustNotSave = !unloadEvent.isSaveChunk(); -+ ((ServerLevel)this.world).getChunkSource().removeLoadedChunk(this); // Paper -+ // Paper start - neighbour cache -+ int chunkX = this.chunkPos.x; -+ int chunkZ = this.chunkPos.z; -+ ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); -+ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { -+ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { -+ LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); -+ if (neighbour != null) { -+ neighbour.setNeighbourUnloaded(-dx, -dz); -+ } -+ } -+ } -+ this.loadedTicketLevel = false; -+ this.resetNeighbours(); -+ // Paper end - } - // CraftBukkit end - -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index 8a4fca9f4882e65b831dd3f82f242e1113859fe0..b54d82e0f41a03c91e0de8df8249a91da3c04d0e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -139,6 +139,7 @@ public class LevelChunkSection { - return this.states; - } - -+ public void writeChunkSection(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER - public void write(FriendlyByteBuf packetdataserializer) { - packetdataserializer.writeShort(this.nonEmptyBlockCount); - this.states.write(packetdataserializer); -diff --git a/src/main/java/net/minecraft/world/level/chunk/Palette.java b/src/main/java/net/minecraft/world/level/chunk/Palette.java -index dcc030f4801b4c6e1fe5b8c2718ddfd7ba6bb248..78c56e1e2af50e923fb0b07c6ddd860c4aa77195 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Palette.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Palette.java -@@ -7,10 +7,12 @@ import net.minecraft.network.FriendlyByteBuf; - - public interface Palette { - -+ default int getOrCreateIdFor(T object) { return this.idFor(object); } // Paper - OBFHELPER - int idFor(T object); - - boolean maybeHas(Predicate predicate); - -+ @Nullable default T getObject(int dataBits) { return this.valueFor(dataBits); } // Paper - OBFHELPER - @Nullable - T valueFor(int index); - -diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index f14f89f8916c832feaa3887bd28a5cf6b2f6ff1d..d4db27421736f665739436c1ac4d3c6d5cae95cd 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -19,7 +19,7 @@ import net.minecraft.util.Mth; - - public class PalettedContainer implements PaletteResize { - -- private final Palette globalPalette; -+ private final Palette globalPalette; private final Palette getDataPaletteGlobal() { return this.globalPalette; } // Paper - OBFHELPER - private final PaletteResize dummyPaletteResize = (i, object) -> { - return 0; - }; -@@ -27,9 +27,9 @@ public class PalettedContainer implements PaletteResize { - private final Function reader; - private final Function writer; - private final T defaultValue; -- protected BitStorage storage; -- private Palette palette; -- private int bits; -+ protected BitStorage storage; public final BitStorage getDataBits() { return this.storage; } // Paper - OBFHELPER -+ private Palette palette; private Palette getDataPalette() { return this.palette; } // Paper - OBFHELPER -+ private int bits; private int getBitsPerObject() { return this.bits; } // Paper - OBFHELPER - private final ReentrantLock lock = new ReentrantLock(); - - public void acquire() { -@@ -64,6 +64,7 @@ public class PalettedContainer implements PaletteResize { - return y << 8 | z << 4 | x; - } - -+ private void initialize(int bitsPerObject) { this.setBits(bitsPerObject); } // Paper - OBFHELPER - private void setBits(int size) { - if (size != this.bits) { - this.bits = size; -@@ -141,6 +142,7 @@ public class PalettedContainer implements PaletteResize { - return t0 == null ? this.defaultValue : t0; - } - -+ public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER - public void write(FriendlyByteBuf buf) { - this.acquire(); - buf.writeByte(this.bits); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index cecf8a68f215d85e84fba157930f6987ffd21e50..7cd3f89004b0a64772fc3dfbdd132ba5a850b63e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -99,6 +99,18 @@ public class ProtoChunk implements ChunkAccess { - - } - -+ // Paper start - If loaded util -+ @Override -+ public FluidState getFluidIfLoaded(BlockPos blockposition) { -+ return this.getFluidState(blockposition); -+ } -+ -+ @Override -+ public BlockState getTypeIfLoaded(BlockPos blockposition) { -+ return this.getBlockState(blockposition); -+ } -+ // Paper end -+ - @Override - public BlockState getBlockState(BlockPos pos) { - int i = pos.getY(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -index 7de765786b3504dcffab98bb0d9dac64b30b3325..5bd34b136f2892f541ba686debca19e0a4eef0be 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -@@ -27,7 +27,7 @@ public class IOWorker implements AutoCloseable { - private static final Logger LOGGER = LogManager.getLogger(); - private final AtomicBoolean shutdownRequested = new AtomicBoolean(); - private final ProcessorMailbox mailbox; -- private final RegionFileStorage storage; -+ private final RegionFileStorage storage;public RegionFileStorage getRegionFileCache() { return storage; } // Paper - OBFHELPER - private final Map pendingWrites = Maps.newLinkedHashMap(); - - protected IOWorker(File file, boolean flag, String s) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index aa3d6db08e4d744cc94de71d0f8dceb99948e2ab..60f410a4f838048bbfd2cde52caa7c4c9434b0ba 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -112,6 +112,7 @@ public class RegionFile implements AutoCloseable { - return this.externalFileDir.resolve(s); - } - -+ @Nullable public synchronized DataInputStream getReadStream(ChunkPos chunkCoordIntPair) throws IOException { return getChunkDataInputStream(chunkCoordIntPair);} // Paper - OBFHELPER - @Nullable - public synchronized DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException { - int i = this.getOffset(pos); -diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java -index 022fafff8b476f8bc1830bf5494760b0fef65297..983d0495ec35128ca3ef68566ada065bc4b21efc 100644 ---- a/src/main/java/net/minecraft/world/phys/AABB.java -+++ b/src/main/java/net/minecraft/world/phys/AABB.java -@@ -194,10 +194,12 @@ public class AABB { - return this.move(vec3d.x, vec3d.y, vec3d.z); - } - -+ public final boolean intersects(AABB axisalignedbb) { return this.intersects(axisalignedbb); } // Paper - OBFHELPER - public boolean intersects(AABB box) { - return this.intersects(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ); - } - -+ public final boolean intersects(double d0, double d1, double d2, double d3, double d4, double d5) { return intersects(d0, d1, d2, d3, d4, d5); } // Paper - OBFHELPER - public boolean intersects(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { - return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ; - } -@@ -210,6 +212,7 @@ public class AABB { - return x >= this.minX && x < this.maxX && y >= this.minY && y < this.maxY && z >= this.minZ && z < this.maxZ; - } - -+ public final double getAverageSideLength(){return getSize();} // Paper - OBFHELPER - public double getSize() { - double d0 = this.getXsize(); - double d1 = this.getYsize(); -diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -index eb07309be171ccadcae21f4096c44d2b700d22b3..2371b52b450e2b43fa9b9549a91f853c702a9dc0 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -@@ -31,10 +31,12 @@ public final class Shapes { - public static final VoxelShape INFINITY = box(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); - private static final VoxelShape EMPTY = new ArrayVoxelShape(new BitSetDiscreteVoxelShape(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); - -+ public static final VoxelShape empty() {return empty();} // Paper - OBFHELPER - public static VoxelShape empty() { - return Shapes.EMPTY; - } - -+ public static final VoxelShape fullCube() {return block();} // Paper - OBFHELPER - public static VoxelShape block() { - return Shapes.BLOCK; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index c34f63eaf3deca4623ca4dfbee863771014847ba..01df5263d77771a296ca091a0feec620e6e37229 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -85,6 +85,7 @@ public final class CraftItemStack extends ItemStack { - } - - net.minecraft.world.item.ItemStack handle; -+ public net.minecraft.world.item.ItemStack getHandle() { return handle; } // Paper - - /** - * Mirror -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 9ad17c560c8d99a396543ab9f97c34de648f6544..4bf48f77f3f7cd62a91590543f5af441c8268029 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -43,6 +43,7 @@ import org.bukkit.scheduler.BukkitWorker; - */ - public class CraftScheduler implements BukkitScheduler { - -+ static Plugin MINECRAFT = new MinecraftInternalPlugin(); - /** - * Counter for IDs. Order doesn't matter, only uniqueness. - */ -@@ -177,6 +178,11 @@ public class CraftScheduler implements BukkitScheduler { - runTaskTimer(plugin, (Object) task, delay, period); - } - -+ public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { -+ final CraftTask task = new CraftTask(run, nextId(), taskName); -+ return handle(task, delay); -+ } -+ - public BukkitTask runTaskTimer(Plugin plugin, Object runnable, long delay, long period) { - validate(plugin, runnable); - if (delay < 0L) { -@@ -400,13 +406,20 @@ public class CraftScheduler implements BukkitScheduler { - task.run(); - task.timings.stopTiming(); // Spigot - } catch (final Throwable throwable) { -- task.getOwner().getLogger().log( -+ // Paper start -+ String msg = String.format( -+ "Task #%s for %s generated an exception", -+ task.getTaskId(), -+ task.getOwner().getDescription().getFullName()); -+ if (task.getOwner() == MINECRAFT) { -+ net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable); -+ } else { -+ task.getOwner().getLogger().log( - Level.WARNING, -- String.format( -- "Task #%s for %s generated an exception", -- task.getTaskId(), -- task.getOwner().getDescription().getFullName()), -+ msg, - throwable); -+ } -+ // Paper end - } finally { - currentTask = null; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -index 3c7066192ea4c05c101404bb56cbc839771f4200..09aa6809c5400ce8548ac902908b750ce7c964ec 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -@@ -39,6 +39,21 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - CraftTask(final Object task) { - this(null, task, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); - } -+ // Paper start -+ public String taskName = null; -+ boolean internal = false; -+ CraftTask(final Object task, int id, String taskName) { -+ this.rTask = (Runnable) task; -+ this.cTask = null; -+ this.plugin = CraftScheduler.MINECRAFT; -+ this.taskName = taskName; -+ this.internal = true; -+ this.id = id; -+ this.period = CraftTask.NO_REPEATING; -+ this.taskName = taskName; -+ this.timings = null; // Will be changed in later patch -+ } -+ // Paper end - - CraftTask(final Plugin plugin, final Object task, final int id, final long period) { - this.plugin = plugin; -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java -new file mode 100644 -index 0000000000000000000000000000000000000000..49dc0c441b9dd7e7745cf15ced67f383ebee1f99 ---- /dev/null -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java -@@ -0,0 +1,132 @@ -+package org.bukkit.craftbukkit.scheduler; -+ -+ -+import org.bukkit.Server; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+import org.bukkit.configuration.file.FileConfiguration; -+import org.bukkit.generator.ChunkGenerator; -+import org.bukkit.plugin.PluginBase; -+import org.bukkit.plugin.PluginDescriptionFile; -+import org.bukkit.plugin.PluginLoader; -+import org.bukkit.plugin.PluginLogger; -+ -+import java.io.File; -+import java.io.InputStream; -+import java.util.List; -+ -+public class MinecraftInternalPlugin extends PluginBase { -+ private boolean enabled = true; -+ -+ private final String pluginName; -+ private PluginDescriptionFile pdf; -+ -+ public MinecraftInternalPlugin() { -+ this.pluginName = "Minecraft"; -+ pdf = new PluginDescriptionFile(pluginName, "1.0", "nms"); -+ } -+ -+ public void setEnabled(boolean enabled) { -+ this.enabled = enabled; -+ } -+ -+ @Override -+ public File getDataFolder() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public PluginDescriptionFile getDescription() { -+ return pdf; -+ } -+ -+ @Override -+ public FileConfiguration getConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public InputStream getResource(String filename) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void saveConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void saveDefaultConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void saveResource(String resourcePath, boolean replace) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void reloadConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public PluginLogger getLogger() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public PluginLoader getPluginLoader() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public Server getServer() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @Override -+ public void onDisable() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void onLoad() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void onEnable() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public boolean isNaggable() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void setNaggable(boolean canNag) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -index 33cd17c415ae19bc9028934257b396907995cb9a..40a2ad3e180cc50a755f44a8ff6d8261734bf733 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -@@ -168,7 +168,23 @@ public class DummyGeneratorAccess implements LevelAccessor { - public FluidState getFluidState(BlockPos pos) { - throw new UnsupportedOperationException("Not supported yet."); - } -+ // Paper start - if loaded util -+ @javax.annotation.Nullable -+ @Override -+ public ChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } -+ -+ @Override -+ public BlockState getTypeIfLoaded(BlockPos blockposition) { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } - -+ @Override -+ public FluidState getFluidIfLoaded(BlockPos blockposition) { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } -+ // Paper end - @Override - public WorldBorder getWorldBorder() { - throw new UnsupportedOperationException("Not supported yet."); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -index 1aec70a1f1a9d8fd2cd06bde4033e19e769ab331..f72c13bedaa6fa45e26f5dcad564835bdd4af61f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -@@ -17,7 +17,7 @@ import java.util.RandomAccess; - public class UnsafeList extends AbstractList implements List, RandomAccess, Cloneable, Serializable { - private static final long serialVersionUID = 8683452581112892191L; - -- private transient Object[] data; -+ private transient Object[] data; public final Object[] getRawDataArray() { return this.data; } // Paper - expose for raw get - private int size; - private int initialCapacity; - -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 8d6f4d76d6f04a322a98faecaca6b1b69c5f49d6..dc11dab14624ca25e78bf0b919ecf461e0be430d 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -118,7 +118,11 @@ public class SpigotConfig - } - } - } -- -+ // Paper start -+ SpigotConfig.save(); -+ } -+ public static void save() { -+ // Paper end - try - { - config.save( CONFIG_FILE ); diff --git a/Remapped-Spigot-Server-Patches/0005-Paper-Metrics.patch b/Remapped-Spigot-Server-Patches/0005-Paper-Metrics.patch deleted file mode 100644 index 82a9c9a2d4..0000000000 --- a/Remapped-Spigot-Server-Patches/0005-Paper-Metrics.patch +++ /dev/null @@ -1,735 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 24 Mar 2017 23:56:01 -0500 -Subject: [PATCH] Paper Metrics - -Removes Spigot's mcstats metrics in favor of a system using bStats - -To disable for privacy or other reasons go to the bStats folder in your plugins folder -and edit the config.yml file present there. - -Please keep in mind the data collected is anonymous and collection should have no -tangible effect on server performance. The data is used to allow the authors of -PaperMC to track version and platform usage so that we can make better management -decisions on behalf of the project. - -diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0b9e689d57705965721b5c55bc45d36657f360e4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/Metrics.java -@@ -0,0 +1,670 @@ -+package com.destroystokyo.paper; -+ -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+import org.bukkit.configuration.file.YamlConfiguration; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.plugin.Plugin; -+ -+import org.json.simple.JSONArray; -+import org.json.simple.JSONObject; -+ -+import javax.net.ssl.HttpsURLConnection; -+import java.io.ByteArrayOutputStream; -+import java.io.DataOutputStream; -+import java.io.File; -+import java.io.IOException; -+import java.net.URL; -+import java.util.*; -+import java.util.concurrent.Callable; -+import java.util.concurrent.Executors; -+import java.util.concurrent.ScheduledExecutorService; -+import java.util.concurrent.TimeUnit; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+import java.util.zip.GZIPOutputStream; -+ -+/** -+ * bStats collects some data for plugin authors. -+ * -+ * Check out https://bStats.org/ to learn more about bStats! -+ */ -+public class Metrics { -+ -+ // Executor service for requests -+ // We use an executor service because the Bukkit scheduler is affected by server lags -+ private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); -+ -+ // The version of this bStats class -+ public static final int B_STATS_VERSION = 1; -+ -+ // The url to which the data is sent -+ private static final String URL = "https://bStats.org/submitData/server-implementation"; -+ -+ // Should failed requests be logged? -+ private static boolean logFailedRequests = false; -+ -+ // The logger for the failed requests -+ private static Logger logger = Logger.getLogger("bStats"); -+ -+ // The name of the server software -+ private final String name; -+ -+ // The uuid of the server -+ private final String serverUUID; -+ -+ // A list with all custom charts -+ private final List charts = new ArrayList<>(); -+ -+ /** -+ * Class constructor. -+ * -+ * @param name The name of the server software. -+ * @param serverUUID The uuid of the server. -+ * @param logFailedRequests Whether failed requests should be logged or not. -+ * @param logger The logger for the failed requests. -+ */ -+ public Metrics(String name, String serverUUID, boolean logFailedRequests, Logger logger) { -+ this.name = name; -+ this.serverUUID = serverUUID; -+ Metrics.logFailedRequests = logFailedRequests; -+ Metrics.logger = logger; -+ -+ // Start submitting the data -+ startSubmitting(); -+ } -+ -+ /** -+ * Adds a custom chart. -+ * -+ * @param chart The chart to add. -+ */ -+ public void addCustomChart(CustomChart chart) { -+ if (chart == null) { -+ throw new IllegalArgumentException("Chart cannot be null!"); -+ } -+ charts.add(chart); -+ } -+ -+ /** -+ * Starts the Scheduler which submits our data every 30 minutes. -+ */ -+ private void startSubmitting() { -+ final Runnable submitTask = this::submitData; -+ -+ // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the -+ // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. -+ // WARNING: You must not modify any part of this Metrics class, including the submit delay or frequency! -+ // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! -+ long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); -+ long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); -+ scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); -+ scheduler.scheduleAtFixedRate(submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); -+ } -+ -+ /** -+ * Gets the plugin specific data. -+ * -+ * @return The plugin specific data. -+ */ -+ private JSONObject getPluginData() { -+ JSONObject data = new JSONObject(); -+ -+ data.put("pluginName", name); // Append the name of the server software -+ JSONArray customCharts = new JSONArray(); -+ for (CustomChart customChart : charts) { -+ // Add the data of the custom charts -+ JSONObject chart = customChart.getRequestJsonObject(); -+ if (chart == null) { // If the chart is null, we skip it -+ continue; -+ } -+ customCharts.add(chart); -+ } -+ data.put("customCharts", customCharts); -+ -+ return data; -+ } -+ -+ /** -+ * Gets the server specific data. -+ * -+ * @return The server specific data. -+ */ -+ private JSONObject getServerData() { -+ // OS specific data -+ String osName = System.getProperty("os.name"); -+ String osArch = System.getProperty("os.arch"); -+ String osVersion = System.getProperty("os.version"); -+ int coreCount = Runtime.getRuntime().availableProcessors(); -+ -+ JSONObject data = new JSONObject(); -+ -+ data.put("serverUUID", serverUUID); -+ -+ data.put("osName", osName); -+ data.put("osArch", osArch); -+ data.put("osVersion", osVersion); -+ data.put("coreCount", coreCount); -+ -+ return data; -+ } -+ -+ /** -+ * Collects the data and sends it afterwards. -+ */ -+ private void submitData() { -+ final JSONObject data = getServerData(); -+ -+ JSONArray pluginData = new JSONArray(); -+ pluginData.add(getPluginData()); -+ data.put("plugins", pluginData); -+ -+ try { -+ // We are still in the Thread of the timer, so nothing get blocked :) -+ sendData(data); -+ } catch (Exception e) { -+ // Something went wrong! :( -+ if (logFailedRequests) { -+ logger.log(Level.WARNING, "Could not submit stats of " + name, e); -+ } -+ } -+ } -+ -+ /** -+ * Sends the data to the bStats server. -+ * -+ * @param data The data to send. -+ * @throws Exception If the request failed. -+ */ -+ private static void sendData(JSONObject data) throws Exception { -+ if (data == null) { -+ throw new IllegalArgumentException("Data cannot be null!"); -+ } -+ HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); -+ -+ // Compress the data to save bandwidth -+ byte[] compressedData = compress(data.toString()); -+ -+ // Add headers -+ connection.setRequestMethod("POST"); -+ connection.addRequestProperty("Accept", "application/json"); -+ connection.addRequestProperty("Connection", "close"); -+ connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request -+ connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); -+ connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format -+ connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); -+ -+ // Send data -+ connection.setDoOutput(true); -+ DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); -+ outputStream.write(compressedData); -+ outputStream.flush(); -+ outputStream.close(); -+ -+ connection.getInputStream().close(); // We don't care about the response - Just send our data :) -+ } -+ -+ /** -+ * Gzips the given String. -+ * -+ * @param str The string to gzip. -+ * @return The gzipped String. -+ * @throws IOException If the compression failed. -+ */ -+ private static byte[] compress(final String str) throws IOException { -+ if (str == null) { -+ return null; -+ } -+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); -+ GZIPOutputStream gzip = new GZIPOutputStream(outputStream); -+ gzip.write(str.getBytes("UTF-8")); -+ gzip.close(); -+ return outputStream.toByteArray(); -+ } -+ -+ /** -+ * Represents a custom chart. -+ */ -+ public static abstract class CustomChart { -+ -+ // The id of the chart -+ final String chartId; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ */ -+ CustomChart(String chartId) { -+ if (chartId == null || chartId.isEmpty()) { -+ throw new IllegalArgumentException("ChartId cannot be null or empty!"); -+ } -+ this.chartId = chartId; -+ } -+ -+ private JSONObject getRequestJsonObject() { -+ JSONObject chart = new JSONObject(); -+ chart.put("chartId", chartId); -+ try { -+ JSONObject data = getChartData(); -+ if (data == null) { -+ // If the data is null we don't send the chart. -+ return null; -+ } -+ chart.put("data", data); -+ } catch (Throwable t) { -+ if (logFailedRequests) { -+ logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t); -+ } -+ return null; -+ } -+ return chart; -+ } -+ -+ protected abstract JSONObject getChartData() throws Exception; -+ -+ } -+ -+ /** -+ * Represents a custom simple pie. -+ */ -+ public static class SimplePie extends CustomChart { -+ -+ private final Callable callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public SimplePie(String chartId, Callable callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ String value = callable.call(); -+ if (value == null || value.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("value", value); -+ return data; -+ } -+ } -+ -+ /** -+ * Represents a custom advanced pie. -+ */ -+ public static class AdvancedPie extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public AdvancedPie(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean allSkipped = true; -+ for (Map.Entry entry : map.entrySet()) { -+ if (entry.getValue() == 0) { -+ continue; // Skip this invalid -+ } -+ allSkipped = false; -+ values.put(entry.getKey(), entry.getValue()); -+ } -+ if (allSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ } -+ -+ /** -+ * Represents a custom drilldown pie. -+ */ -+ public static class DrilldownPie extends CustomChart { -+ -+ private final Callable>> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public DrilldownPie(String chartId, Callable>> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ public JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map> map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean reallyAllSkipped = true; -+ for (Map.Entry> entryValues : map.entrySet()) { -+ JSONObject value = new JSONObject(); -+ boolean allSkipped = true; -+ for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { -+ value.put(valueEntry.getKey(), valueEntry.getValue()); -+ allSkipped = false; -+ } -+ if (!allSkipped) { -+ reallyAllSkipped = false; -+ values.put(entryValues.getKey(), value); -+ } -+ } -+ if (reallyAllSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ } -+ -+ /** -+ * Represents a custom single line chart. -+ */ -+ public static class SingleLineChart extends CustomChart { -+ -+ private final Callable callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public SingleLineChart(String chartId, Callable callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ int value = callable.call(); -+ if (value == 0) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("value", value); -+ return data; -+ } -+ -+ } -+ -+ /** -+ * Represents a custom multi line chart. -+ */ -+ public static class MultiLineChart extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public MultiLineChart(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean allSkipped = true; -+ for (Map.Entry entry : map.entrySet()) { -+ if (entry.getValue() == 0) { -+ continue; // Skip this invalid -+ } -+ allSkipped = false; -+ values.put(entry.getKey(), entry.getValue()); -+ } -+ if (allSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ -+ } -+ -+ /** -+ * Represents a custom simple bar chart. -+ */ -+ public static class SimpleBarChart extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public SimpleBarChart(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ for (Map.Entry entry : map.entrySet()) { -+ JSONArray categoryValues = new JSONArray(); -+ categoryValues.add(entry.getValue()); -+ values.put(entry.getKey(), categoryValues); -+ } -+ data.put("values", values); -+ return data; -+ } -+ -+ } -+ -+ /** -+ * Represents a custom advanced bar chart. -+ */ -+ public static class AdvancedBarChart extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public AdvancedBarChart(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean allSkipped = true; -+ for (Map.Entry entry : map.entrySet()) { -+ if (entry.getValue().length == 0) { -+ continue; // Skip this invalid -+ } -+ allSkipped = false; -+ JSONArray categoryValues = new JSONArray(); -+ for (int categoryValue : entry.getValue()) { -+ categoryValues.add(categoryValue); -+ } -+ values.put(entry.getKey(), categoryValues); -+ } -+ if (allSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ -+ } -+ -+ static class PaperMetrics { -+ static void startMetrics() { -+ // Get the config file -+ File configFile = new File(new File((File) MinecraftServer.getServer().options.valueOf("plugins"), "bStats"), "config.yml"); -+ YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); -+ -+ // Check if the config file exists -+ if (!config.isSet("serverUuid")) { -+ -+ // Add default values -+ config.addDefault("enabled", true); -+ // Every server gets it's unique random id. -+ config.addDefault("serverUuid", UUID.randomUUID().toString()); -+ // Should failed request be logged? -+ config.addDefault("logFailedRequests", false); -+ -+ // Inform the server owners about bStats -+ config.options().header( -+ "bStats collects some data for plugin authors like how many servers are using their plugins.\n" + -+ "To honor their work, you should not disable it.\n" + -+ "This has nearly no effect on the server performance!\n" + -+ "Check out https://bStats.org/ to learn more :)" -+ ).copyDefaults(true); -+ try { -+ config.save(configFile); -+ } catch (IOException ignored) { -+ } -+ } -+ // Load the data -+ String serverUUID = config.getString("serverUuid"); -+ boolean logFailedRequests = config.getBoolean("logFailedRequests", false); -+ // Only start Metrics, if it's enabled in the config -+ if (config.getBoolean("enabled", true)) { -+ Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger()); -+ -+ metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { -+ String minecraftVersion = Bukkit.getVersion(); -+ minecraftVersion = minecraftVersion.substring(minecraftVersion.indexOf("MC: ") + 4, minecraftVersion.length() - 1); -+ return minecraftVersion; -+ })); -+ -+ metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); -+ metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() || PaperConfig.isProxyOnlineMode() ? "online" : "offline")); -+ metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); -+ -+ metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { -+ Map> map = new HashMap<>(); -+ String javaVersion = System.getProperty("java.version"); -+ Map entry = new HashMap<>(); -+ entry.put(javaVersion, 1); -+ -+ // http://openjdk.java.net/jeps/223 -+ // Java decided to change their versioning scheme and in doing so modified the java.version system -+ // property to return $major[.$minor][.$secuity][-ea], as opposed to 1.$major.0_$identifier -+ // we can handle pre-9 by checking if the "major" is equal to "1", otherwise, 9+ -+ String majorVersion = javaVersion.split("\\.")[0]; -+ String release; -+ -+ int indexOf = javaVersion.lastIndexOf('.'); -+ -+ if (majorVersion.equals("1")) { -+ release = "Java " + javaVersion.substring(0, indexOf); -+ } else { -+ // of course, it really wouldn't be all that simple if they didn't add a quirk, now would it -+ // valid strings for the major may potentially include values such as -ea to deannotate a pre release -+ Matcher versionMatcher = Pattern.compile("\\d+").matcher(majorVersion); -+ if (versionMatcher.find()) { -+ majorVersion = versionMatcher.group(0); -+ } -+ release = "Java " + majorVersion; -+ } -+ map.put(release, entry); -+ -+ return map; -+ })); -+ -+ metrics.addCustomChart(new Metrics.DrilldownPie("legacy_plugins", () -> { -+ Map> map = new HashMap<>(); -+ -+ // count legacy plugins -+ int legacy = 0; -+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { -+ if (CraftMagicNumbers.isLegacy(plugin.getDescription())) { -+ legacy++; -+ } -+ } -+ -+ // insert real value as lower dimension -+ Map entry = new HashMap<>(); -+ entry.put(String.valueOf(legacy), 1); -+ -+ // create buckets as higher dimension -+ if (legacy == 0) { -+ map.put("0 \uD83D\uDE0E", entry); // :sunglasses: -+ } else if (legacy <= 5) { -+ map.put("1-5", entry); -+ } else if (legacy <= 10) { -+ map.put("6-10", entry); -+ } else if (legacy <= 25) { -+ map.put("11-25", entry); -+ } else if (legacy <= 50) { -+ map.put("26-50", entry); -+ } else { -+ map.put("50+ \uD83D\uDE2D", entry); // :cry: -+ } -+ -+ return map; -+ })); -+ } -+ -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 2c0514892d3993bef57ecf677cf8bb0fbe0216e4..da922f395f0fff0881ead893c900c5b2623f48f0 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -42,6 +42,7 @@ public class PaperConfig { - private static boolean verbose; - private static boolean fatalError; - /*========================================================================*/ -+ private static boolean metricsStarted; - - public static void init(File configFile) { - CONFIG_FILE = configFile; -@@ -84,6 +85,11 @@ public class PaperConfig { - for (Map.Entry entry : commands.entrySet()) { - MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); - } -+ -+ if (!metricsStarted) { -+ Metrics.PaperMetrics.startMetrics(); -+ metricsStarted = true; -+ } - } - - static void readConfig(Class clazz, Object instance) { -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index dc11dab14624ca25e78bf0b919ecf461e0be430d..0083f979933d4a9035efb992ab0a2f250a56a979 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -83,6 +83,7 @@ public class SpigotConfig - MinecraftServer.getServer().server.getCommandMap().register( entry.getKey(), "Spigot", entry.getValue() ); - } - -+ /* // Paper - Replace with our own - if ( metrics == null ) - { - try -@@ -94,6 +95,7 @@ public class SpigotConfig - Bukkit.getServer().getLogger().log( Level.SEVERE, "Could not start metrics service", ex ); - } - } -+ */ // Paper end - } - - static void readConfig(Class clazz, Object instance) diff --git a/Remapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch b/Remapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch deleted file mode 100644 index 91f564fb1b..0000000000 --- a/Remapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 01:40:13 -0400 -Subject: [PATCH] Add MinecraftKey Information to Objects - -Stores the reference to the objects respective MinecraftKey - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index d05eeaa711a09bb121b530654821894e795ff4ea..e95b91cefb0374bd5bb57cc090f5ecd566d7a618 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -208,7 +208,7 @@ public class PaperCommand extends Command { - - Collection entities = world.entitiesById.values(); - entities.forEach(e -> { -- ResourceLocation key = new ResourceLocation(""); // TODO: update in next patch -+ ResourceLocation key = e.getMinecraftKey(); - - MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); - ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); -diff --git a/src/main/java/net/minecraft/server/KeyedObject.java b/src/main/java/net/minecraft/server/KeyedObject.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3c9933050ca0a7453ba7950cb3cf4cc8b5b7081d ---- /dev/null -+++ b/src/main/java/net/minecraft/server/KeyedObject.java -@@ -0,0 +1,11 @@ -+package net.minecraft.server; -+ -+import net.minecraft.resources.ResourceLocation; -+ -+public interface KeyedObject { -+ ResourceLocation getMinecraftKey(); -+ default String getMinecraftKeyString() { -+ ResourceLocation key = getMinecraftKey(); -+ return key != null ? key.toString() : null; -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c7008fcbd4d805fe0e743f1d4ad948dcd86ceae3..48c9d2b7d56832ebd13749a394b8b715f0b1704d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -135,7 +135,7 @@ import org.bukkit.event.player.PlayerTeleportEvent; - import org.bukkit.plugin.PluginManager; - // CraftBukkit end - --public abstract class Entity implements Nameable, CommandSource { -+public abstract class Entity implements Nameable, CommandSource, net.minecraft.server.KeyedObject { // Paper - - // CraftBukkit start - private static final int CURRENT_LEVEL = 2; -@@ -1761,12 +1761,31 @@ public abstract class Entity implements Nameable, CommandSource { - return true; - } - -+ // Paper start -+ private ResourceLocation entityKey; -+ private String entityKeyString; -+ -+ @Override -+ public ResourceLocation getMinecraftKey() { -+ if (entityKey == null) { -+ this.entityKey = EntityType.getKey(this.getType()); -+ this.entityKeyString = this.entityKey != null ? this.entityKey.toString() : null; -+ } -+ return entityKey; -+ } -+ -+ @Override -+ public String getMinecraftKeyString() { -+ getMinecraftKey(); // Try to load if it doesn't exists. see: https://github.com/PaperMC/Paper/issues/1280 -+ return entityKeyString; -+ } - @Nullable - public final String getEncodeId() { - EntityType entitytypes = this.getType(); - ResourceLocation minecraftkey = EntityType.getKey(entitytypes); - -- return entitytypes.canSerialize() && minecraftkey != null ? minecraftkey.toString() : null; -+ return entitytypes != null && entitytypes.isPersistable() ? getMinecraftKeyString() : null; -+ // Paper end - } - - protected abstract void readAdditionalSaveData(CompoundTag tag); -diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index 102298d57cf3143092d04ab1d5d0d69b28d696ea..2cb86de4bfc87a709f0cfa2c4e550d8e7928a3f0 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -384,6 +384,7 @@ public class EntityType { - } - } - -+ public boolean isPersistable() { return canSerialize(); } // Paper - OBFHELPER - public boolean canSerialize() { - return this.serialize; - } -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 8928a1ae51d24fd15aaae93bc8ea573548f2b012..846fc0f36377337630b2ec2a5f7a5a54c39c2965 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -23,7 +23,7 @@ import org.bukkit.inventory.InventoryHolder; - - import org.spigotmc.CustomTimingsHandler; // Spigot - --public abstract class BlockEntity { -+public abstract class BlockEntity implements net.minecraft.server.KeyedObject { // Paper - - public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot - // CraftBukkit start - data containers -@@ -31,7 +31,7 @@ public abstract class BlockEntity { - public CraftPersistentDataContainer persistentDataContainer; - // CraftBukkit end - private static final Logger LOGGER = LogManager.getLogger(); -- private final BlockEntityType type; -+ private final BlockEntityType type; public BlockEntityType getTileEntityType() { return type; } // Paper - OBFHELPER - @Nullable - protected Level level; - protected BlockPos worldPosition; -@@ -45,6 +45,26 @@ public abstract class BlockEntity { - this.type = type; - } - -+ // Paper start -+ private String tileEntityKeyString = null; -+ private ResourceLocation tileEntityKey = null; -+ -+ @Override -+ public ResourceLocation getMinecraftKey() { -+ if (tileEntityKey == null) { -+ tileEntityKey = BlockEntityType.getKey(this.getTileEntityType()); -+ tileEntityKeyString = tileEntityKey != null ? tileEntityKey.toString() : null; -+ } -+ return tileEntityKey; -+ } -+ -+ @Override -+ public String getMinecraftKeyString() { -+ getMinecraftKey(); // Try to load if it doesn't exists. -+ return tileEntityKeyString; -+ } -+ // Paper end -+ - @Nullable - public Level getLevel() { - return this.level; diff --git a/Remapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch b/Remapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch deleted file mode 100644 index 11ed8248cc..0000000000 --- a/Remapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 02:10:36 -0400 -Subject: [PATCH] Store reference to current Chunk for Entity and Block - Entities - -This enables us a fast reference to the entities current chunk instead -of having to look it up by hashmap lookups. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 48c9d2b7d56832ebd13749a394b8b715f0b1704d..b633f6b3a36b793e6dbc1b8b554bfba74c719570 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -260,7 +260,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public boolean isChunkLoaded() { -- return level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); -+ return getCurrentChunk() != null; - } - // CraftBukkit end - -@@ -1762,6 +1762,23 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - // Paper start -+ public java.lang.ref.WeakReference currentChunk = null; -+ -+ public void setCurrentChunk(net.minecraft.world.level.chunk.LevelChunk chunk) { -+ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; -+ } -+ /** -+ * Returns the entities current registered chunk. If the entity is not added to a chunk yet, it will return null -+ */ -+ public net.minecraft.world.level.chunk.LevelChunk getCurrentChunk() { -+ final net.minecraft.world.level.chunk.LevelChunk chunk = currentChunk != null ? currentChunk.get() : null; -+ if (chunk != null && chunk.loaded) { -+ return chunk; -+ } -+ -+ return !inChunk ? null : ((ServerLevel)level).getChunkSource().getChunkAtIfLoadedMainThreadNoCache(xChunk, zChunk); -+ } -+ - private ResourceLocation entityKey; - private String entityKeyString; - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 846fc0f36377337630b2ec2a5f7a5a54c39c2965..bb60c9da9f3ba0d5c5bad22512675ccb841a60e5 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -11,6 +11,7 @@ import net.minecraft.world.level.Level; - import net.minecraft.world.level.block.Mirror; - import net.minecraft.world.level.block.Rotation; - import net.minecraft.world.level.block.state.BlockState; -+import net.minecraft.world.level.chunk.LevelChunk; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - import org.apache.logging.log4j.util.Supplier; -@@ -63,6 +64,15 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - getMinecraftKey(); // Try to load if it doesn't exists. - return tileEntityKeyString; - } -+ -+ private java.lang.ref.WeakReference currentChunk = null; -+ public LevelChunk getCurrentChunk() { -+ final LevelChunk chunk = currentChunk != null ? currentChunk.get() : null; -+ return chunk != null && chunk.loaded ? chunk : null; -+ } -+ public void setCurrentChunk(LevelChunk chunk) { -+ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; -+ } - // Paper end - - @Nullable -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index e2c5a17aa72d1a5412d76881187d4d9ad1763297..ae08fcce66d50d7f61bc3bd4a0e2547d56f53e82 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -89,11 +89,36 @@ public class LevelChunk implements ChunkAccess { - this(world, pos, biomes, UpgradeData.EMPTY, EmptyTickList.empty(), EmptyTickList.empty(), 0L, (LevelChunkSection[]) null, (Consumer) null); - } - -+ // Paper start -+ private class TileEntityHashMap extends java.util.HashMap { -+ @Override -+ public BlockEntity put(BlockPos key, BlockEntity value) { -+ BlockEntity replaced = super.put(key, value); -+ if (replaced != null) { -+ replaced.setCurrentChunk(null); -+ } -+ if (value != null) { -+ value.setCurrentChunk(LevelChunk.this); -+ } -+ return replaced; -+ } -+ -+ @Override -+ public BlockEntity remove(Object key) { -+ BlockEntity removed = super.remove(key); -+ if (removed != null) { -+ removed.setCurrentChunk(null); -+ } -+ return removed; -+ } -+ } -+ // Paper end -+ - public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes, UpgradeData upgradeData, TickList blockTickScheduler, TickList fluidTickScheduler, long inhabitedTime, @Nullable LevelChunkSection[] sections, @Nullable Consumer loadToWorldConsumer) { - this.sections = new LevelChunkSection[16]; - this.pendingBlockEntities = Maps.newHashMap(); - this.heightmaps = Maps.newEnumMap(Heightmap.Types.class); -- this.blockEntities = Maps.newHashMap(); -+ this.blockEntities = new TileEntityHashMap(); // Paper - this.structureStarts = Maps.newHashMap(); - this.structuresRefences = Maps.newHashMap(); - this.postProcessing = new ShortList[16]; -@@ -504,6 +529,7 @@ public class LevelChunk implements ChunkAccess { - } - - entity.inChunk = true; -+ entity.setCurrentChunk(this); // Paper - entity.xChunk = this.chunkPos.x; - entity.yChunk = k; - entity.zChunk = this.chunkPos.z; -@@ -516,6 +542,7 @@ public class LevelChunk implements ChunkAccess { - ((Heightmap) this.heightmaps.get(type)).setRawData(heightmap); - } - -+ public final void removeEntity(Entity entity) { this.removeEntity(entity); } // Paper - OBFHELPER - public void removeEntity(Entity entity) { - this.removeEntity(entity, entity.yChunk); - } -@@ -530,7 +557,12 @@ public class LevelChunk implements ChunkAccess { - section = this.entitySlices.length - 1; - } - -- this.entitySlices[section].remove(entity); -+ // Paper start -+ if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); -+ if (!this.entitySlices[section].remove(entity)) { -+ return; -+ } -+ // Paper end - this.entities.remove(entity); // Paper - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 080d3292e03c5a179b9eb89da1550718d263f817..eb61c803cf74c5ca2c51d5027a02ed3db6b53096 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -145,6 +145,7 @@ import net.minecraft.world.entity.vehicle.MinecartHopper; - import net.minecraft.world.entity.vehicle.MinecartSpawner; - import net.minecraft.world.entity.vehicle.MinecartTNT; - import net.minecraft.world.phys.AABB; -+import org.bukkit.Chunk; // Paper - import org.bukkit.EntityEffect; - import org.bukkit.Location; - import org.bukkit.Server; -@@ -186,6 +187,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - this.entity = entity; - } - -+ @Override -+ public Chunk getChunk() { -+ net.minecraft.world.level.chunk.LevelChunk currentChunk = entity.getCurrentChunk(); -+ return currentChunk != null ? currentChunk.bukkitChunk : getLocation().getChunk(); -+ } -+ - public static CraftEntity getEntity(CraftServer server, Entity entity) { - /* - * Order is *EXTREMELY* important -- keep it right! =D diff --git a/Remapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch b/Remapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch deleted file mode 100644 index ca1271ce76..0000000000 --- a/Remapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 02:13:59 -0400 -Subject: [PATCH] Store counts for each Entity/Block Entity Type - -Opens door for future patches to optimize performance - -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index ae08fcce66d50d7f61bc3bd4a0e2547d56f53e82..00ce55c17980da87a3834f952475a766543506b0 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -90,15 +90,19 @@ public class LevelChunk implements ChunkAccess { - } - - // Paper start -+ public final co.aikar.util.Counter entityCounts = new co.aikar.util.Counter<>(); -+ public final co.aikar.util.Counter tileEntityCounts = new co.aikar.util.Counter<>(); - private class TileEntityHashMap extends java.util.HashMap { - @Override - public BlockEntity put(BlockPos key, BlockEntity value) { - BlockEntity replaced = super.put(key, value); - if (replaced != null) { - replaced.setCurrentChunk(null); -+ tileEntityCounts.decrement(replaced.getMinecraftKeyString()); - } - if (value != null) { - value.setCurrentChunk(LevelChunk.this); -+ tileEntityCounts.increment(value.getMinecraftKeyString()); - } - return replaced; - } -@@ -108,6 +112,7 @@ public class LevelChunk implements ChunkAccess { - BlockEntity removed = super.remove(key); - if (removed != null) { - removed.setCurrentChunk(null); -+ tileEntityCounts.decrement(removed.getMinecraftKeyString()); - } - return removed; - } -@@ -528,6 +533,7 @@ public class LevelChunk implements ChunkAccess { - k = this.entitySlices.length - 1; - } - -+ if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper - entity.inChunk = true; - entity.setCurrentChunk(this); // Paper - entity.xChunk = this.chunkPos.x; -@@ -562,6 +568,7 @@ public class LevelChunk implements ChunkAccess { - if (!this.entitySlices[section].remove(entity)) { - return; - } -+ entityCounts.decrement(entity.getMinecraftKeyString()); - // Paper end - this.entities.remove(entity); // Paper - } diff --git a/Remapped-Spigot-Server-Patches/0009-Timings-v2.patch b/Remapped-Spigot-Server-Patches/0009-Timings-v2.patch deleted file mode 100644 index dc683eaeec..0000000000 --- a/Remapped-Spigot-Server-Patches/0009-Timings-v2.patch +++ /dev/null @@ -1,2330 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 04:00:11 -0600 -Subject: [PATCH] Timings v2 - - -diff --git a/src/main/java/SpigotTimings.java b/src/main/java/SpigotTimings.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 -diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -new file mode 100644 -index 0000000000000000000000000000000000000000..be3a62f543a5fec4739c14821fe5a443c1fa3f5b ---- /dev/null -+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -0,0 +1,152 @@ -+package co.aikar.timings; -+ -+import Timing; -+import com.google.common.collect.MapMaker; -+import net.minecraft.commands.CommandFunction; -+import net.minecraft.network.protocol.Packet; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.BlockEntity; -+import org.bukkit.plugin.Plugin; -+import org.bukkit.scheduler.BukkitTask; -+ -+import org.bukkit.craftbukkit.scheduler.CraftTask; -+ -+import java.util.Map; -+ -+// TODO: Re-implement missing timers -+public final class MinecraftTimings { -+ -+ public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); -+ public static final Timing playerListTimer = Timings.ofSafe("Player List"); -+ public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); -+ public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); -+ public static final Timing tickablesTimer = Timings.ofSafe("Tickables"); -+ public static final Timing minecraftSchedulerTimer = Timings.ofSafe("Minecraft Scheduler"); -+ public static final Timing bukkitSchedulerTimer = Timings.ofSafe("Bukkit Scheduler"); -+ public static final Timing bukkitSchedulerPendingTimer = Timings.ofSafe("Bukkit Scheduler - Pending"); -+ public static final Timing bukkitSchedulerFinishTimer = Timings.ofSafe("Bukkit Scheduler - Finishing"); -+ public static final Timing chunkIOTickTimer = Timings.ofSafe("ChunkIOTick"); -+ public static final Timing timeUpdateTimer = Timings.ofSafe("Time Update"); -+ public static final Timing serverCommandTimer = Timings.ofSafe("Server Command"); -+ public static final Timing savePlayers = Timings.ofSafe("Save Players"); -+ -+ public static final Timing tickEntityTimer = Timings.ofSafe("## tickEntity"); -+ public static final Timing tickTileEntityTimer = Timings.ofSafe("## tickTileEntity"); -+ public static final Timing packetProcessTimer = Timings.ofSafe("## Packet Processing"); -+ public static final Timing scheduledBlocksTimer = Timings.ofSafe("## Scheduled Blocks"); -+ public static final Timing structureGenerationTimer = Timings.ofSafe("Structure Generation"); -+ -+ public static final Timing processQueueTimer = Timings.ofSafe("processQueue"); -+ public static final Timing processTasksTimer = Timings.ofSafe("processTasks"); -+ -+ public static final Timing playerCommandTimer = Timings.ofSafe("playerCommand"); -+ -+ public static final Timing entityActivationCheckTimer = Timings.ofSafe("entityActivationCheck"); -+ -+ public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update"); -+ public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate"); -+ -+ private static final Map, String> taskNameCache = new MapMaker().weakKeys().makeMap(); -+ -+ private MinecraftTimings() {} -+ -+ public static Timing getInternalTaskName(String taskName) { -+ return Timings.ofSafe(taskName); -+ } -+ -+ /** -+ * Gets a timer associated with a plugins tasks. -+ * @param bukkitTask -+ * @param period -+ * @return -+ */ -+ public static Timing getPluginTaskTimings(BukkitTask bukkitTask, long period) { -+ if (!bukkitTask.isSync()) { -+ return NullTimingHandler.NULL; -+ } -+ Plugin plugin; -+ -+ CraftTask craftTask = (CraftTask) bukkitTask; -+ -+ final Class taskClass = craftTask.getTaskClass(); -+ if (bukkitTask.getOwner() != null) { -+ plugin = bukkitTask.getOwner(); -+ } else { -+ plugin = TimingsManager.getPluginByClassloader(taskClass); -+ } -+ -+ final String taskname = taskNameCache.computeIfAbsent(taskClass, clazz -> { -+ try { -+ String clsName = !clazz.isMemberClass() -+ ? clazz.getName() -+ : clazz.getCanonicalName(); -+ if (clsName != null && clsName.contains("$Lambda$")) { -+ clsName = clsName.replaceAll("(Lambda\\$.*?)/.*", "$1"); -+ } -+ return clsName != null ? clsName : "UnknownTask"; -+ } catch (Throwable ex) { -+ new Exception("Error occurred detecting class name", ex).printStackTrace(); -+ return "MangledClassFile"; -+ } -+ }); -+ -+ StringBuilder name = new StringBuilder(64); -+ name.append("Task: ").append(taskname); -+ if (period > 0) { -+ name.append(" (interval:").append(period).append(")"); -+ } else { -+ name.append(" (Single)"); -+ } -+ -+ if (plugin == null) { -+ return Timings.ofSafe(null, name.toString()); -+ } -+ -+ return Timings.ofSafe(plugin, name.toString()); -+ } -+ -+ /** -+ * Get a named timer for the specified entity type to track type specific timings. -+ * @param entityType -+ * @return -+ */ -+ public static Timing getEntityTimings(String entityType, String type) { -+ return Timings.ofSafe("Minecraft", "## tickEntity - " + entityType + " - " + type, tickEntityTimer); -+ } -+ -+ /** -+ * Get a named timer for the specified tile entity type to track type specific timings. -+ * @param entity -+ * @return -+ */ -+ public static Timing getTileEntityTimings(BlockEntity entity) { -+ String entityType = entity.getClass().getName(); -+ return Timings.ofSafe("Minecraft", "## tickTileEntity - " + entityType, tickTileEntityTimer); -+ } -+ public static Timing getCancelTasksTimer() { -+ return Timings.ofSafe("Cancel Tasks"); -+ } -+ public static Timing getCancelTasksTimer(Plugin plugin) { -+ return Timings.ofSafe(plugin, "Cancel Tasks"); -+ } -+ -+ public static void stopServer() { -+ TimingsManager.stopServer(); -+ } -+ -+ public static Timing getBlockTiming(Block block) { -+ return Timings.ofSafe("## Scheduled Block: " + block.toString(), scheduledBlocksTimer); -+ } -+/* -+ public static Timing getStructureTiming(StructureGenerator structureGenerator) { -+ return Timings.ofSafe("Structure Generator - " + structureGenerator.getName(), structureGenerationTimer); -+ }*/ -+ -+ public static Timing getPacketTiming(Packet packet) { -+ return Timings.ofSafe("## Packet - " + packet.getClass().getName(), packetProcessTimer); -+ } -+ -+ public static Timing getCommandFunctionTiming(CommandFunction function) { -+ return Timings.ofSafe("Command Function - " + function.getMinecraftKey().toString()); -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -new file mode 100644 -index 0000000000000000000000000000000000000000..94adf0275a2e7093c152cc3b8b0a5747b3a13a86 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -0,0 +1,380 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import com.google.common.collect.Sets; -+import net.minecraft.server.MinecraftServer; -+import org.apache.commons.lang.StringUtils; -+import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; -+import org.bukkit.Material; -+import org.bukkit.configuration.ConfigurationSection; -+import org.bukkit.configuration.MemorySection; -+import org.bukkit.craftbukkit.util.CraftChatMessage; -+import org.bukkit.entity.EntityType; -+import org.json.simple.JSONObject; -+import org.json.simple.JSONValue; -+ -+import java.io.ByteArrayOutputStream; -+import java.io.IOException; -+import java.io.InputStream; -+import java.io.OutputStream; -+import java.lang.management.ManagementFactory; -+import java.lang.management.OperatingSystemMXBean; -+import java.lang.management.RuntimeMXBean; -+import java.net.HttpURLConnection; -+import java.net.InetAddress; -+import java.net.URL; -+import java.util.List; -+import java.util.Map; -+import java.util.Set; -+import java.util.logging.Level; -+import java.util.zip.GZIPOutputStream; -+ -+import static co.aikar.timings.TimingsManager.HISTORY; -+import static co.aikar.util.JSONUtil.appendObjectData; -+import static co.aikar.util.JSONUtil.createObject; -+import static co.aikar.util.JSONUtil.pair; -+import static co.aikar.util.JSONUtil.toArray; -+import static co.aikar.util.JSONUtil.toArrayMapper; -+import static co.aikar.util.JSONUtil.toObjectMapper; -+ -+import TimingHistory; -+import TimingsReportListener; -+ -+@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) -+public class TimingsExport extends Thread { -+ -+ private final TimingsReportListener listeners; -+ private final Map out; -+ private final TimingHistory[] history; -+ private static long lastReport = 0; -+ -+ private TimingsExport(TimingsReportListener listeners, Map out, TimingHistory[] history) { -+ super("Timings paste thread"); -+ this.listeners = listeners; -+ this.out = out; -+ this.history = history; -+ } -+ -+ /** -+ * Checks if any pending reports are being requested, and builds one if needed. -+ */ -+ public static void reportTimings() { -+ if (Timings.requestingReport.isEmpty()) { -+ return; -+ } -+ TimingsReportListener listeners = new TimingsReportListener(Timings.requestingReport); -+ listeners.addConsoleIfNeeded(); -+ -+ Timings.requestingReport.clear(); -+ long now = System.currentTimeMillis(); -+ final long lastReportDiff = now - lastReport; -+ if (lastReportDiff < 60000) { -+ listeners.sendMessage(ChatColor.RED + "Please wait at least 1 minute in between Timings reports. (" + (int)((60000 - lastReportDiff) / 1000) + " seconds)"); -+ listeners.done(); -+ return; -+ } -+ final long lastStartDiff = now - TimingsManager.timingStart; -+ if (lastStartDiff < 180000) { -+ listeners.sendMessage(ChatColor.RED + "Please wait at least 3 minutes before generating a Timings report. Unlike Timings v1, v2 benefits from longer timings and is not as useful with short timings. (" + (int)((180000 - lastStartDiff) / 1000) + " seconds)"); -+ listeners.done(); -+ return; -+ } -+ listeners.sendMessage(ChatColor.GREEN + "Preparing Timings Report..."); -+ lastReport = now; -+ Map parent = createObject( -+ // Get some basic system details about the server -+ pair("version", Bukkit.getVersion()), -+ pair("maxplayers", Bukkit.getMaxPlayers()), -+ pair("start", TimingsManager.timingStart / 1000), -+ pair("end", System.currentTimeMillis() / 1000), -+ pair("online-mode", Bukkit.getServer().getOnlineMode()), -+ pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), -+ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedIds(), pack -> { -+ // Don't feel like obf helper'ing these, non fatal if its temp missed. -+ return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); -+ })) -+ ); -+ if (!TimingsManager.privacy) { -+ appendObjectData(parent, -+ pair("server", Bukkit.getUnsafe().getTimingsServerName()), -+ pair("motd", Bukkit.getServer().getMotd()), -+ pair("icon", Bukkit.getServer().getServerIcon().getData()) -+ ); -+ } -+ -+ final Runtime runtime = Runtime.getRuntime(); -+ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); -+ -+ OperatingSystemMXBean osInfo = ManagementFactory.getOperatingSystemMXBean(); -+ -+ parent.put("system", createObject( -+ pair("timingcost", getCost()), -+ pair("loadavg", osInfo.getSystemLoadAverage()), -+ pair("name", System.getProperty("os.name")), -+ pair("version", System.getProperty("os.version")), -+ pair("jvmversion", System.getProperty("java.version")), -+ pair("arch", System.getProperty("os.arch")), -+ pair("maxmem", runtime.maxMemory()), -+ pair("memory", createObject( -+ pair("heap", ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().toString()), -+ pair("nonheap", ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().toString()), -+ pair("finalizing", ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount()) -+ )), -+ pair("cpu", runtime.availableProcessors()), -+ pair("runtime", runtimeBean.getUptime()), -+ pair("flags", StringUtils.join(runtimeBean.getInputArguments(), " ")), -+ pair("gc", toObjectMapper(ManagementFactory.getGarbageCollectorMXBeans(), input -> pair(input.getName(), toArray(input.getCollectionCount(), input.getCollectionTime())))) -+ ) -+ ); -+ -+ parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getAllLevels(), world -> { -+ if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; -+ return pair(world.getWorldData().getName(), createObject( -+ pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { -+ return pair(rule, world.getWorld().getGameRuleValue(rule)); -+ })), -+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) -+ )); -+ })); -+ -+ Set tileEntityTypeSet = Sets.newHashSet(); -+ Set entityTypeSet = Sets.newHashSet(); -+ -+ int size = HISTORY.size(); -+ TimingHistory[] history = new TimingHistory[size + 1]; -+ int i = 0; -+ for (TimingHistory timingHistory : HISTORY) { -+ tileEntityTypeSet.addAll(timingHistory.tileEntityTypeSet); -+ entityTypeSet.addAll(timingHistory.entityTypeSet); -+ history[i++] = timingHistory; -+ } -+ -+ history[i] = new TimingHistory(); // Current snapshot -+ tileEntityTypeSet.addAll(history[i].tileEntityTypeSet); -+ entityTypeSet.addAll(history[i].entityTypeSet); -+ -+ -+ Map handlers = createObject(); -+ Map groupData; -+ synchronized (TimingIdentifier.GROUP_MAP) { -+ for (TimingIdentifier.TimingGroup group : TimingIdentifier.GROUP_MAP.values()) { -+ synchronized (group.handlers) { -+ for (TimingHandler id : group.handlers) { -+ -+ if (!id.isTimed() && !id.isSpecial()) { -+ continue; -+ } -+ -+ String name = id.identifier.name; -+ if (name.startsWith("##")) { -+ name = name.substring(3); -+ } -+ handlers.put(id.id, toArray( -+ group.id, -+ name -+ )); -+ } -+ } -+ } -+ -+ groupData = toObjectMapper( -+ TimingIdentifier.GROUP_MAP.values(), group -> pair(group.id, group.name)); -+ } -+ -+ parent.put("idmap", createObject( -+ pair("groups", groupData), -+ pair("handlers", handlers), -+ pair("worlds", toObjectMapper(TimingHistory.worldMap.entrySet(), input -> pair(input.getValue(), input.getKey()))), -+ pair("tileentity", -+ toObjectMapper(tileEntityTypeSet, input -> pair(input.ordinal(), input.name()))), -+ pair("entity", -+ toObjectMapper(entityTypeSet, input -> pair(input.ordinal(), input.name()))) -+ )); -+ -+ // Information about loaded plugins -+ -+ parent.put("plugins", toObjectMapper(Bukkit.getPluginManager().getPlugins(), -+ plugin -> pair(plugin.getName(), createObject( -+ pair("version", plugin.getDescription().getVersion()), -+ pair("description", String.valueOf(plugin.getDescription().getDescription()).trim()), -+ pair("website", plugin.getDescription().getWebsite()), -+ pair("authors", StringUtils.join(plugin.getDescription().getAuthors(), ", ")) -+ )))); -+ -+ -+ -+ // Information on the users Config -+ -+ parent.put("config", createObject( -+ pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), -+ pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), -+ pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) -+ )); -+ -+ new TimingsExport(listeners, parent, history).start(); -+ } -+ -+ static long getCost() { -+ // Benchmark the users System.nanotime() for cost basis -+ int passes = 100; -+ TimingHandler SAMPLER1 = Timings.ofSafe("Timings Sampler 1"); -+ TimingHandler SAMPLER2 = Timings.ofSafe("Timings Sampler 2"); -+ TimingHandler SAMPLER3 = Timings.ofSafe("Timings Sampler 3"); -+ TimingHandler SAMPLER4 = Timings.ofSafe("Timings Sampler 4"); -+ TimingHandler SAMPLER5 = Timings.ofSafe("Timings Sampler 5"); -+ TimingHandler SAMPLER6 = Timings.ofSafe("Timings Sampler 6"); -+ -+ long start = System.nanoTime(); -+ for (int i = 0; i < passes; i++) { -+ SAMPLER1.startTiming(); -+ SAMPLER2.startTiming(); -+ SAMPLER3.startTiming(); -+ SAMPLER3.stopTiming(); -+ SAMPLER4.startTiming(); -+ SAMPLER5.startTiming(); -+ SAMPLER6.startTiming(); -+ SAMPLER6.stopTiming(); -+ SAMPLER5.stopTiming(); -+ SAMPLER4.stopTiming(); -+ SAMPLER2.stopTiming(); -+ SAMPLER1.stopTiming(); -+ } -+ long timingsCost = (System.nanoTime() - start) / passes / 6; -+ SAMPLER1.reset(true); -+ SAMPLER2.reset(true); -+ SAMPLER3.reset(true); -+ SAMPLER4.reset(true); -+ SAMPLER5.reset(true); -+ SAMPLER6.reset(true); -+ return timingsCost; -+ } -+ -+ private static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) { -+ -+ JSONObject object = new JSONObject(); -+ for (String key : config.getKeys(false)) { -+ String fullKey = (parentKey != null ? parentKey + "." + key : key); -+ if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld")) { -+ continue; -+ } -+ final Object val = config.get(key); -+ -+ object.put(key, valAsJSON(val, fullKey)); -+ } -+ return object; -+ } -+ -+ private static Object valAsJSON(Object val, final String parentKey) { -+ if (!(val instanceof MemorySection)) { -+ if (val instanceof List) { -+ Iterable v = (Iterable) val; -+ return toArrayMapper(v, input -> valAsJSON(input, parentKey)); -+ } else { -+ return String.valueOf(val); -+ } -+ } else { -+ return mapAsJSON((ConfigurationSection) val, parentKey); -+ } -+ } -+ -+ @Override -+ public void run() { -+ out.put("data", toArrayMapper(history, TimingHistory::export)); -+ -+ -+ String response = null; -+ String timingsURL = null; -+ try { -+ HttpURLConnection con = (HttpURLConnection) new URL("http://timings.aikar.co/post").openConnection(); -+ con.setDoOutput(true); -+ String hostName = "BrokenHost"; -+ try { -+ hostName = InetAddress.getLocalHost().getHostName(); -+ } catch (Exception ignored) {} -+ con.setRequestProperty("User-Agent", "Paper/" + Bukkit.getUnsafe().getTimingsServerName() + "/" + hostName); -+ con.setRequestMethod("POST"); -+ con.setInstanceFollowRedirects(false); -+ -+ OutputStream request = new GZIPOutputStream(con.getOutputStream()) {{ -+ this.def.setLevel(7); -+ }}; -+ -+ request.write(JSONValue.toJSONString(out).getBytes("UTF-8")); -+ request.close(); -+ -+ response = getResponse(con); -+ -+ if (con.getResponseCode() != 302) { -+ listeners.sendMessage( -+ ChatColor.RED + "Upload Error: " + con.getResponseCode() + ": " + con.getResponseMessage()); -+ listeners.sendMessage(ChatColor.RED + "Check your logs for more information"); -+ if (response != null) { -+ Bukkit.getLogger().log(Level.SEVERE, response); -+ } -+ return; -+ } -+ -+ timingsURL = con.getHeaderField("Location"); -+ listeners.sendMessage(ChatColor.GREEN + "View Timings Report: " + timingsURL); -+ -+ if (response != null && !response.isEmpty()) { -+ Bukkit.getLogger().log(Level.INFO, "Timing Response: " + response); -+ } -+ } catch (IOException ex) { -+ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); -+ if (response != null) { -+ Bukkit.getLogger().log(Level.SEVERE, response); -+ } -+ Bukkit.getLogger().log(Level.SEVERE, "Could not paste timings", ex); -+ } finally { -+ this.listeners.done(timingsURL); -+ } -+ } -+ -+ private String getResponse(HttpURLConnection con) throws IOException { -+ InputStream is = null; -+ try { -+ is = con.getInputStream(); -+ ByteArrayOutputStream bos = new ByteArrayOutputStream(); -+ -+ byte[] b = new byte[1024]; -+ int bytesRead; -+ while ((bytesRead = is.read(b)) != -1) { -+ bos.write(b, 0, bytesRead); -+ } -+ return bos.toString(); -+ -+ } catch (IOException ex) { -+ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); -+ Bukkit.getLogger().log(Level.WARNING, con.getResponseMessage(), ex); -+ return null; -+ } finally { -+ if (is != null) { -+ is.close(); -+ } -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..79ede25e4fe7a648b1d29c49d876482a2158f892 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -0,0 +1,120 @@ -+package co.aikar.timings; -+ -+import Timing; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.world.level.Level; -+import net.minecraft.world.level.storage.PrimaryLevelData; -+ -+/** -+ * Set of timers per world, to track world specific timings. -+ */ -+// TODO: Re-implement missing timers -+public class WorldTimingsHandler { -+ public final Timing mobSpawn; -+ public final Timing doChunkUnload; -+ public final Timing doPortalForcer; -+ public final Timing scheduledBlocks; -+ public final Timing scheduledBlocksCleanup; -+ public final Timing scheduledBlocksTicking; -+ public final Timing chunkTicks; -+ public final Timing lightChunk; -+ public final Timing chunkTicksBlocks; -+ public final Timing doVillages; -+ public final Timing doChunkMap; -+ public final Timing doChunkMapUpdate; -+ public final Timing doChunkMapToUpdate; -+ public final Timing doChunkMapSortMissing; -+ public final Timing doChunkMapSortSendToPlayers; -+ public final Timing doChunkMapPlayersNeedingChunks; -+ public final Timing doChunkMapPendingSendToPlayers; -+ public final Timing doChunkMapUnloadChunks; -+ public final Timing doChunkGC; -+ public final Timing doSounds; -+ public final Timing entityRemoval; -+ public final Timing entityTick; -+ public final Timing tileEntityTick; -+ public final Timing tileEntityPending; -+ public final Timing tracker1; -+ public final Timing tracker2; -+ public final Timing doTick; -+ public final Timing tickEntities; -+ public final Timing chunks; -+ public final Timing newEntities; -+ public final Timing raids; -+ public final Timing chunkProviderTick; -+ public final Timing broadcastChunkUpdates; -+ public final Timing countNaturalMobs; -+ -+ public final Timing chunkLoad; -+ public final Timing chunkLoadPopulate; -+ public final Timing syncChunkLoad; -+ public final Timing chunkLoadLevelTimer; -+ public final Timing chunkIO; -+ public final Timing chunkPostLoad; -+ public final Timing worldSave; -+ public final Timing worldSaveChunks; -+ public final Timing worldSaveLevel; -+ public final Timing chunkSaveData; -+ -+ -+ public final Timing miscMobSpawning; -+ -+ public WorldTimingsHandler(Level server) { -+ String name = ((PrimaryLevelData) server.getLevelData()).getLevelName() + " - "; -+ -+ mobSpawn = Timings.ofSafe(name + "mobSpawn"); -+ doChunkUnload = Timings.ofSafe(name + "doChunkUnload"); -+ scheduledBlocks = Timings.ofSafe(name + "Scheduled Blocks"); -+ scheduledBlocksCleanup = Timings.ofSafe(name + "Scheduled Blocks - Cleanup"); -+ scheduledBlocksTicking = Timings.ofSafe(name + "Scheduled Blocks - Ticking"); -+ chunkTicks = Timings.ofSafe(name + "Chunk Ticks"); -+ lightChunk = Timings.ofSafe(name + "Light Chunk"); -+ chunkTicksBlocks = Timings.ofSafe(name + "Chunk Ticks - Blocks"); -+ doVillages = Timings.ofSafe(name + "doVillages"); -+ doChunkMap = Timings.ofSafe(name + "doChunkMap"); -+ doChunkMapUpdate = Timings.ofSafe(name + "doChunkMap - Update"); -+ doChunkMapToUpdate = Timings.ofSafe(name + "doChunkMap - To Update"); -+ doChunkMapSortMissing = Timings.ofSafe(name + "doChunkMap - Sort Missing"); -+ doChunkMapSortSendToPlayers = Timings.ofSafe(name + "doChunkMap - Sort Send To Players"); -+ doChunkMapPlayersNeedingChunks = Timings.ofSafe(name + "doChunkMap - Players Needing Chunks"); -+ doChunkMapPendingSendToPlayers = Timings.ofSafe(name + "doChunkMap - Pending Send To Players"); -+ doChunkMapUnloadChunks = Timings.ofSafe(name + "doChunkMap - Unload Chunks"); -+ doSounds = Timings.ofSafe(name + "doSounds"); -+ doChunkGC = Timings.ofSafe(name + "doChunkGC"); -+ doPortalForcer = Timings.ofSafe(name + "doPortalForcer"); -+ entityTick = Timings.ofSafe(name + "entityTick"); -+ entityRemoval = Timings.ofSafe(name + "entityRemoval"); -+ tileEntityTick = Timings.ofSafe(name + "tileEntityTick"); -+ tileEntityPending = Timings.ofSafe(name + "tileEntityPending"); -+ -+ chunkLoad = Timings.ofSafe(name + "Chunk Load"); -+ chunkLoadPopulate = Timings.ofSafe(name + "Chunk Load - Populate"); -+ syncChunkLoad = Timings.ofSafe(name + "Sync Chunk Load"); -+ chunkLoadLevelTimer = Timings.ofSafe(name + "Chunk Load - Load Level"); -+ chunkIO = Timings.ofSafe(name + "Chunk Load - DiskIO"); -+ chunkPostLoad = Timings.ofSafe(name + "Chunk Load - Post Load"); -+ worldSave = Timings.ofSafe(name + "World Save"); -+ worldSaveLevel = Timings.ofSafe(name + "World Save - Level"); -+ worldSaveChunks = Timings.ofSafe(name + "World Save - Chunks"); -+ chunkSaveData = Timings.ofSafe(name + "Chunk Save - Data"); -+ -+ tracker1 = Timings.ofSafe(name + "tracker stage 1"); -+ tracker2 = Timings.ofSafe(name + "tracker stage 2"); -+ doTick = Timings.ofSafe(name + "doTick"); -+ tickEntities = Timings.ofSafe(name + "tickEntities"); -+ -+ chunks = Timings.ofSafe(name + "Chunks"); -+ newEntities = Timings.ofSafe(name + "New entity registration"); -+ raids = Timings.ofSafe(name + "Raids"); -+ chunkProviderTick = Timings.ofSafe(name + "Chunk provider tick"); -+ broadcastChunkUpdates = Timings.ofSafe(name + "Broadcast chunk updates"); -+ countNaturalMobs = Timings.ofSafe(name + "Count natural mobs"); -+ -+ -+ miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ } -+ -+ public static Timing getTickList(ServerLevel worldserver, String timingsType) { -+ return Timings.ofSafe(((PrimaryLevelData) worldserver.getLevelData()).getLevelName() + " - Scheduled " + timingsType); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index da922f395f0fff0881ead893c900c5b2623f48f0..1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -14,12 +14,15 @@ import java.util.concurrent.TimeUnit; - import java.util.logging.Level; - import java.util.regex.Pattern; - -+import com.google.common.collect.Lists; - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; - import org.bukkit.command.Command; - import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.InvalidConfigurationException; - import org.bukkit.configuration.file.YamlConfiguration; -+import co.aikar.timings.Timings; -+import co.aikar.timings.TimingsManager; - - public class PaperConfig { - -@@ -188,4 +191,30 @@ public class PaperConfig { - config.addDefault(path, def); - return config.getString(path, config.getString(path)); - } -+ -+ public static String timingsServerName; -+ private static void timings() { -+ boolean timings = getBoolean("timings.enabled", true); -+ boolean verboseTimings = getBoolean("timings.verbose", true); -+ TimingsManager.privacy = getBoolean("timings.server-name-privacy", false); -+ TimingsManager.hiddenConfigs = getList("timings.hidden-config-entries", Lists.newArrayList("database", "settings.bungeecord-addresses", "settings.velocity-support.secret")); -+ if (!TimingsManager.hiddenConfigs.contains("settings.velocity-support.secret")) { -+ TimingsManager.hiddenConfigs.add("settings.velocity-support.secret"); -+ } -+ int timingHistoryInterval = getInt("timings.history-interval", 300); -+ int timingHistoryLength = getInt("timings.history-length", 3600); -+ timingsServerName = getString("timings.server-name", "Unknown Server"); -+ -+ -+ Timings.setVerboseTimingsEnabled(verboseTimings); -+ Timings.setTimingsEnabled(timings); -+ Timings.setHistoryInterval(timingHistoryInterval * 20); -+ Timings.setHistoryLength(timingHistoryLength * 20); -+ -+ log("Timings: " + timings + -+ " - Verbose: " + verboseTimings + -+ " - Interval: " + timeSummary(Timings.getHistoryInterval() / 20) + -+ " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + -+ " - Server Name: " + timingsServerName); -+ } - } -diff --git a/src/main/java/net/minecraft/commands/CommandFunction.java b/src/main/java/net/minecraft/commands/CommandFunction.java -index cf57de0e791a9362fe95b65134d9fe4f4e95adf4..07b891075191161a8a903876b02caa75d4db1366 100644 ---- a/src/main/java/net/minecraft/commands/CommandFunction.java -+++ b/src/main/java/net/minecraft/commands/CommandFunction.java -@@ -15,12 +15,22 @@ public class CommandFunction { - - private final CommandFunction.Entry[] entries; - private final ResourceLocation id; -+ // Paper start -+ public co.aikar.timings.Timing timing; -+ public co.aikar.timings.Timing getTiming() { -+ if (timing == null) { -+ timing = co.aikar.timings.MinecraftTimings.getCommandFunctionTiming(this); -+ } -+ return timing; -+ } -+ // Paper end - - public CommandFunction(ResourceLocation id, CommandFunction.Entry[] elements) { - this.id = id; - this.entries = elements; - } - -+ public final ResourceLocation getMinecraftKey() { return this.getId(); } // Paper - OBFHELPER - public ResourceLocation getId() { - return this.id; - } -diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -index 23ccd095ad99fe90a6f2a16bcca368804b16101a..4ae8201d7dcffeb3298a4e593f978e15ffc5ac15 100644 ---- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java -+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -@@ -3,6 +3,8 @@ package net.minecraft.network.protocol; - import net.minecraft.network.PacketListener; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - // CraftBukkit start - import net.minecraft.server.MinecraftServer; -@@ -21,10 +23,13 @@ public class PacketUtils { - - public static void ensureRunningOnSameThread(Packet packet, T listener, BlockableEventLoop engine) throws RunningOnDifferentThreadException { - if (!engine.isSameThread()) { -+ Timing timing = MinecraftTimings.getPacketTiming(packet); // Paper - timings - engine.execute(() -> { - if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerGamePacketListenerImpl && ((ServerGamePacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590 - if (listener.a().isConnected()) { -+ try (Timing ignored = timing.startTiming()) { // Paper - timings - packet.handle(listener); -+ } // Paper - timings - } else { - PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 2406879e76a110e96a4753e66366432a4bc52d9b..a456b9cbf0e5eea4e888e0e3d07ed17558650371 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -172,7 +172,7 @@ import org.bukkit.craftbukkit.Main; - import org.bukkit.event.server.ServerLoadEvent; - // CraftBukkit end - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot - - public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { -@@ -226,8 +226,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -- return !this.haveTime(); -+ return !this.canSleepForTickNoOversleep(); // Paper - move oversleep into full server tick - }); - } - -@@ -1120,10 +1133,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -+ return !this.canOversleep(); -+ }); -+ isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -+ // Paper end -+ - ++this.tickCount; - this.tickChildren(shouldKeepTicking); - if (i - this.lastServerStatus >= 5000000000L) { -@@ -1141,14 +1162,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % autosavePeriod == 0) { // CraftBukkit -- SpigotTimings.worldSaveTimer.startTiming(); // Spigot - MinecraftServer.LOGGER.debug("Autosave started"); - this.profiler.push("save"); - this.playerList.saveAll(); - this.saveAllChunks(true, false, false); - this.profiler.pop(); - MinecraftServer.LOGGER.debug("Autosave finished"); -- SpigotTimings.worldSaveTimer.stopTiming(); // Spigot - } - - this.profiler.push("snooper"); -@@ -1161,6 +1180,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { - // CraftBukkit start - fire RemoteServerCommandEvent -@@ -677,10 +679,39 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - if (event.isCancelled()) { - return; - } -+ // Paper start -+ if (command.toLowerCase().startsWith("timings") && command.toLowerCase().matches("timings (report|paste|get|merged|seperate)")) { -+ org.bukkit.command.BufferedCommandSender sender = new org.bukkit.command.BufferedCommandSender(); -+ Waitable waitable = new Waitable() { -+ @Override -+ protected String evaluate() { -+ return sender.getBuffer(); -+ } -+ }; -+ waitableArray[0] = waitable; -+ co.aikar.timings.Timings.generateReport(new co.aikar.timings.TimingsReportListener(sender, waitable)); -+ } else { -+ // Paper end - ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), rconConsoleSource.createCommandSourceStack()); - server.dispatchServerCommand(remoteConsole, serverCommand); -+ } // Paper - // CraftBukkit end - }); -+ // Paper start -+ if (waitableArray[0] != null) { -+ //noinspection unchecked -+ Waitable waitable = waitableArray[0]; -+ try { -+ return waitable.get(); -+ } catch (java.util.concurrent.ExecutionException e) { -+ throw new RuntimeException("Exception processing rcon command " + command, e.getCause()); -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // Maintain interrupted state -+ throw new RuntimeException("Interrupted processing rcon command " + command, e); -+ } -+ -+ } -+ // Paper end - return this.rconConsoleSource.getCommandResponse(); - } - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index d9d76d2ee43adc2b46d49f7fc3d9aef6af95e465..59a5f82c9f57d760ba4959a040ce8cbf0f49e4aa 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1,7 +1,9 @@ - package net.minecraft.server.level; - -+import co.aikar.timings.Timing; // Paper - import com.google.common.collect.ImmutableList; - import com.google.common.collect.Iterables; -+import com.google.common.collect.ComparisonChain; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Queues; - import com.google.common.collect.Sets; -@@ -552,11 +554,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - private CompletableFuture> scheduleChunkLoad(ChunkPos pos) { - return CompletableFuture.supplyAsync(() -> { -- try { -+ try (Timing ignored = this.level.timings.chunkLoad.startTimingIfSync()) { // Paper - this.level.getProfiler().incrementCounter("chunkLoad"); -- CompoundTag nbttagcompound = this.readChunk(pos); -+ CompoundTag nbttagcompound; // Paper -+ try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings -+ nbttagcompound = this.readChunk(pos); -+ } // Paper end - -- if (nbttagcompound != null) { -+ if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings - boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8); - - if (flag) { -@@ -568,7 +573,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - ChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", pos); -- } -+ }} // Paper - } catch (ReportedException reportedexception) { - Throwable throwable = reportedexception.getCause(); - -@@ -605,7 +610,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return "chunkGenerate " + requiredStatus.getName(); - }); - return completablefuture.thenComposeAsync((either) -> { -- return (CompletableFuture) either.map((list) -> { -+ return either.map((list) -> { // Paper - Shut up. - try { - CompletableFuture> completablefuture1 = requiredStatus.generate(this.level, this.generator, this.structureManager, this.lightEngine, (ichunkaccess) -> { - return this.protoChunkToFullChunk(holder); -@@ -658,6 +663,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - ChunkStatus chunkstatus = ChunkHolder.getStatus(playerchunk.getTicketLevel()); - - return !chunkstatus.isOrAfter(ChunkStatus.FULL) ? ChunkHolder.UNLOADED_CHUNK : either.mapLeft((ichunkaccess) -> { -+ try (Timing ignored = level.timings.chunkPostLoad.startTimingIfSync()) { // Paper - ChunkPos chunkcoordintpair = playerchunk.getPos(); - LevelChunk chunk; - -@@ -717,6 +723,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - return chunk; -+ } // Paper - }); - }, (runnable) -> { - ProcessorHandle mailbox = this.mainThreadMailbox; -@@ -1175,6 +1182,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - ChunkMap.TrackedEntity playerchunkmap_entitytracker; - ObjectIterator objectiterator; -+ level.timings.tracker1.startTiming(); // Paper - - for (objectiterator = this.entityMap.values().iterator(); objectiterator.hasNext(); playerchunkmap_entitytracker.serverEntity.sendChanges()) { - playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); -@@ -1192,16 +1200,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - playerchunkmap_entitytracker.lastSectionPos = sectionposition1; - } - } -+ level.timings.tracker1.stopTiming(); // Paper - - if (!list.isEmpty()) { - objectiterator = this.entityMap.values().iterator(); - -+ level.timings.tracker2.startTiming(); // Paper - while (objectiterator.hasNext()) { - playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); - playerchunkmap_entitytracker.updatePlayers(list); - } -+ level.timings.tracker2.stopTiming(); // Paper - } - -+ - } - - protected void broadcast(Entity entity, Packet packet) { -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index ef336645f3bd7a86129ad1dff7e1a15dc93d1e3e..d0b0fdaf5451bcc7f7ac7dab28aa59ef77e6dd97 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -344,11 +344,13 @@ public class ServerChunkCache extends ChunkSource { - } - - gameprofilerfiller.incrementCounter("getChunkCacheMiss"); -- level.timings.syncChunkLoadTimer.startTiming(); // Spigot - CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); - -+ if (!completablefuture.isDone()) { // Paper -+ this.level.timings.syncChunkLoad.startTiming(); // Paper - this.mainThreadProcessor.managedBlock(completablefuture::isDone); -- level.timings.syncChunkLoadTimer.stopTiming(); // Spigot -+ this.level.timings.syncChunkLoad.stopTiming(); // Paper -+ } // Paper - ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { - return ichunkaccess1; - }, (playerchunk_failure) -> { -@@ -536,7 +538,9 @@ public class ServerChunkCache extends ChunkSource { - - public void save(boolean flush) { - this.runDistanceManagerUpdates(); -+ try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings - this.chunkMap.saveAllChunks(flush); -+ } // Paper - Timings - } - - @Override -@@ -573,7 +577,9 @@ public class ServerChunkCache extends ChunkSource { - this.runDistanceManagerUpdates(); - this.level.timings.doChunkMap.stopTiming(); // Spigot - this.level.getProfiler().popPush("chunks"); -+ this.level.timings.chunks.startTiming(); // Paper - timings - this.tickChunks(); -+ this.level.timings.chunks.stopTiming(); // Paper - timings - this.level.timings.doChunkUnload.startTiming(); // Spigot - this.level.getProfiler().popPush("unload"); - this.chunkMap.tick(shouldKeepTicking); -@@ -597,19 +603,24 @@ public class ServerChunkCache extends ChunkSource { - boolean flag2 = level.ticksPerAnimalSpawns != 0L && worlddata.getGameTime() % level.ticksPerAnimalSpawns == 0L; // CraftBukkit - - this.level.getProfiler().push("naturalSpawnCount"); -+ this.level.timings.countNaturalMobs.startTiming(); // Paper - timings - int l = this.distanceManager.getNaturalSpawnChunkCount(); - NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk); -+ this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings - - this.lastSpawnState = spawnercreature_d; - this.level.getProfiler().pop(); - //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper - //Collections.shuffle(list); // Paper -+ this.level.timings.chunkTicks.startTiming(); // Paper - this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... - Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); - - if (optional.isPresent()) { - this.level.getProfiler().push("broadcast"); -+ this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timings - playerchunk.broadcastChanges((LevelChunk) optional.get()); -+ this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings - this.level.getProfiler().pop(); - Optional optional1 = ((Either) playerchunk.getEntityTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); - -@@ -623,25 +634,26 @@ public class ServerChunkCache extends ChunkSource { - NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); - } - -- this.level.timings.doTickTiles.startTiming(); // Spigot -+ //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper - this.level.tickChunk(chunk, k); -- this.level.timings.doTickTiles.stopTiming(); // Spigot -+ //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper - } - } - } - }); -+ this.level.timings.chunkTicks.stopTiming(); // Paper - this.level.getProfiler().push("customSpawners"); - if (flag1) { -+ try (co.aikar.timings.Timing ignored = this.level.timings.miscMobSpawning.startTiming()) { // Paper - timings - this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); -+ } // Paper - timings - } - - this.level.getProfiler().pop(); - this.level.getProfiler().pop(); - } - -- this.level.timings.tracker.startTiming(); // Spigot - this.chunkMap.tick(); -- this.level.timings.tracker.stopTiming(); // Spigot - } - - private void getFullChunk(long pos, Consumer chunkConsumer) { -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 34ed8f0d348e7bc2339660ebc6490057ba9ef214..0cc86ca4ea4a2e1b5acc3c0507397eef85dec0c1 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -2,6 +2,8 @@ package net.minecraft.server.level; - - import com.google.common.annotations.VisibleForTesting; - import com.google.common.collect.Iterables; -+import co.aikar.timings.TimingHistory; // Paper -+import co.aikar.timings.Timings; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Queues; -@@ -147,7 +149,6 @@ import org.apache.logging.log4j.Logger; - import java.util.logging.Level; - import org.bukkit.Bukkit; - import org.bukkit.WeatherType; --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.event.CraftEventFactory; - import org.bukkit.craftbukkit.util.WorldUUID; - import org.bukkit.event.entity.CreatureSpawnEvent; -@@ -203,10 +204,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - // CraftBukkit end - this.blockTicks = new ServerTickList<>(this, (block) -> { - return block == null || block.defaultBlockState().isAir(); -- }, Registry.BLOCK::getKey, this::tickBlock); -+ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings - this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { - return fluidtype == null || fluidtype == Fluids.EMPTY; -- }, Registry.FLUID::getKey, this::tickLiquid); -+ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings - this.navigations = Sets.newHashSet(); - this.blockEvents = new ObjectLinkedOpenHashSet(); - this.tickTime = flag1; -@@ -436,17 +437,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.updateSkyBrightness(); - this.tickTime(); - gameprofilerfiller.popPush("chunkSource"); -+ this.timings.chunkProviderTick.startTiming(); // Paper - timings - this.getChunkSource().tick(shouldKeepTicking); -+ this.timings.chunkProviderTick.stopTiming(); // Paper - timings - gameprofilerfiller.popPush("tickPending"); -- timings.doTickPending.startTiming(); // Spigot -+ timings.scheduledBlocks.startTiming(); // Paper - if (!this.isDebug()) { - this.blockTicks.tick(); - this.liquidTicks.tick(); - } -- timings.doTickPending.stopTiming(); // Spigot -+ timings.scheduledBlocks.stopTiming(); // Paper - - gameprofilerfiller.popPush("raid"); -+ this.timings.raids.startTiming(); // Paper - timings - this.raids.tick(); -+ this.timings.raids.stopTiming(); // Paper - timings - gameprofilerfiller.popPush("blockEvents"); - timings.doSounds.startTiming(); // Spigot - this.runBlockEvents(); -@@ -618,6 +623,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - gameprofilerfiller.popPush("tickBlocks"); -+ timings.chunkTicksBlocks.startTiming(); // Paper - if (randomTickSpeed > 0) { - LevelChunkSection[] achunksection = chunk.getSections(); - int l = achunksection.length; -@@ -649,7 +655,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - } - } -- -+ timings.chunkTicksBlocks.stopTiming(); // Paper - gameprofilerfiller.pop(); - } - -@@ -747,14 +753,22 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - if (!(entity instanceof Player) && !this.getChunkSource().isEntityTickingChunk(entity)) { - this.updateChunkPos(entity); - } else { -+ ++TimingHistory.entityTicks; // Paper - timings - // Spigot start -+ co.aikar.timings.Timing timer; // Paper - if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { - entity.tickCount++; -+ timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings - entity.inactiveTick(); -+ } finally { timer.stopTiming(); } // Paper - return; - } - // Spigot end -- entity.tickTimer.startTiming(); // Spigot -+ // Paper start- timings -+ TimingHistory.activatedEntityTicks++; -+ timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); -+ try { -+ // Paper end - timings - entity.setPosAndOldPos(entity.getX(), entity.getY(), entity.getZ()); - entity.yRotO = entity.yRot; - entity.xRotO = entity.xRot; -@@ -781,7 +795,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.tickPassenger(entity, entity1); - } - } -- entity.tickTimer.stopTiming(); // Spigot -+ } finally { timer.stopTiming(); } // Paper - timings - - } - } -@@ -859,6 +873,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - - if (!flag1) { - org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit -+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper - if (progressListener != null) { - progressListener.progressStartNoAbort(new TranslatableComponent("menu.savingLevel")); - } -@@ -868,7 +883,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - progressListener.progressStage(new TranslatableComponent("menu.savingChunks")); - } - -+ timings.worldSaveChunks.startTiming(); // Paper - chunkproviderserver.save(flush); -+ timings.worldSaveChunks.stopTiming(); // Paper -+ } // Paper - } - - // CraftBukkit start - moved from MinecraftServer.saveChunks -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 35f3940cebb00ee29da54b1ee148ee931fa11636..466c4322803bedf1fa61be281b954bf94fb8ff02 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -209,6 +209,7 @@ import org.bukkit.inventory.EquipmentSlot; - import org.bukkit.inventory.InventoryView; - import org.bukkit.inventory.SmithingInventory; - import org.bukkit.util.NumberConversions; -+import co.aikar.timings.MinecraftTimings; // Paper - // CraftBukkit end - - public class ServerGamePacketListenerImpl implements ServerGamePacketListener { -@@ -291,7 +292,6 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // CraftBukkit end - - public void tick() { -- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.startTiming(); // Spigot - this.resetPosition(); - this.player.xo = this.player.getX(); - this.player.yo = this.player.getY(); -@@ -367,7 +367,6 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 - this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling")); - } -- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.stopTiming(); // Spigot - - } - -@@ -1915,7 +1914,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // CraftBukkit end - - private void handleCommand(String input) { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot -+ MinecraftTimings.playerCommandTimer.startTiming(); // Paper - // CraftBukkit start - whole method - if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot - this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + input); -@@ -1926,7 +1925,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - this.craftServer.getPluginManager().callEvent(event); - - if (event.isCancelled()) { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot -+ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper - return; - } - -@@ -1939,7 +1938,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); - return; - } finally { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot -+ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper - } - // this.minecraftServer.getCommandDispatcher().a(this.player.getCommandListener(), s); - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 28121e2fee9d862057042261d25360f0d4ee4530..88af57699d7f9e45ad1366243049e4f3565703ff 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.players; - -+import co.aikar.timings.MinecraftTimings; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -1018,10 +1019,11 @@ public abstract class PlayerList { - } - - public void saveAll() { -+ MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { - this.save((ServerPlayer) this.players.get(i)); - } -- -+ MinecraftTimings.savePlayers.stopTiming(); // Paper - } - - public UserWhiteList getWhiteList() { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b633f6b3a36b793e6dbc1b8b554bfba74c719570..2a7f587e19fcdd6d01b360d6b47d9eadd9df92cc 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -115,7 +115,6 @@ import org.bukkit.craftbukkit.event.CraftPortalEvent; - import org.bukkit.entity.Hanging; - import org.bukkit.entity.LivingEntity; - import org.bukkit.entity.Vehicle; --import org.spigotmc.CustomTimingsHandler; // Spigot - import org.bukkit.event.entity.EntityCombustByEntityEvent; - import org.bukkit.event.hanging.HangingBreakByEntityEvent; - import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; -@@ -247,7 +246,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only - public boolean forceExplosionKnockback; // SPIGOT-949 - public boolean persistentInvisibility = false; -- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot - // Spigot start - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; -@@ -616,7 +614,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public void move(MoverType type, Vec3 movement) { -- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot - if (this.noPhysics) { - this.setBoundingBox(this.getBoundingBox().move(movement)); - this.setLocationFromBoundingbox(); -@@ -752,7 +749,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - - this.level.getProfiler().pop(); - } -- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot - } - - protected BlockPos getOnPos() { -diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index 2cb86de4bfc87a709f0cfa2c4e550d8e7928a3f0..e3d92d1d35911b2960a7ca82bd4f324d285d0533 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -281,17 +281,27 @@ public class EntityType { - return Registry.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(id)); - } - -- public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet immutableset, EntityDimensions entitysize, int i, int j) { -- this.factory = factory; -- this.category = spawnGroup; -- this.canSpawnFarFromPlayer = spawnableFarFromPlayer; -- this.serialize = saveable; -- this.summon = summonable; -- this.fireImmune = fireImmune; -+ public final String id; -+ public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet immutableset, EntityDimensions entitysize, int i, int j) { this(factory, spawnGroup, saveable, summonable, fireImmune, spawnableFarFromPlayer, immutableset, entitysize, i, j, "custom"); } // Paper - old signature -+ public EntityType(EntityType.EntityFactory entitytypes_b, MobCategory enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntityDimensions entitysize, int i, int j, String id) { // Paper - add id -+ this.factory = entitytypes_b; -+ this.category = enumcreaturetype; -+ this.canSpawnFarFromPlayer = flag3; -+ this.serialize = flag; -+ this.summon = flag1; -+ this.fireImmune = flag2; - this.immuneTo = immutableset; - this.dimensions = entitysize; - this.clientTrackingRange = i; - this.updateInterval = j; -+ -+ // Paper start - timings -+ this.id = id; -+ this.tickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "tick"); -+ this.inactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "inactiveTick"); -+ this.passengerTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerTick"); -+ this.passengerInactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerInactiveTick"); -+ // Paper end - } - - @Nullable -@@ -512,6 +522,12 @@ public class EntityType { - return this.updateInterval; - } - -+ // Paper start - timings -+ public final co.aikar.timings.Timing tickTimer; -+ public final co.aikar.timings.Timing inactiveTickTimer; -+ public final co.aikar.timings.Timing passengerTickTimer; -+ public final co.aikar.timings.Timing passengerInactiveTickTimer; -+ // Paper end - public boolean trackDeltas() { - return this != EntityType.PLAYER && this != EntityType.LLAMA_SPIT && this != EntityType.WITHER && this != EntityType.BAT && this != EntityType.ITEM_FRAME && this != EntityType.LEASH_KNOT && this != EntityType.PAINTING && this != EntityType.END_CRYSTAL && this != EntityType.EVOKER_FANGS; - } -@@ -599,7 +615,7 @@ public class EntityType { - Util.fetchChoiceType(References.ENTITY_TREE, id); - } - -- return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval); -+ return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval, id); // Paper - add id - } - } - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 9e5dde73bd65bf4e51352c628fba024c36e29ef1..e5f8cee6726ea9a90c540bb10fd8594a35bb5e40 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -132,7 +132,7 @@ import org.bukkit.event.entity.EntityTeleportEvent; - import org.bukkit.event.player.PlayerItemConsumeEvent; - // CraftBukkit end - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class LivingEntity extends Entity { - -@@ -2455,7 +2455,6 @@ public abstract class LivingEntity extends Entity { - - @Override - public void tick() { -- SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot - super.tick(); - this.updatingUsingItem(); - this.updateSwimAmount(); -@@ -2504,9 +2503,7 @@ public abstract class LivingEntity extends Entity { - } - } - -- SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot - this.aiStep(); -- SpigotTimings.timerEntityTickRest.startTiming(); // Spigot - double d0 = this.getX() - this.xo; - double d1 = this.getZ() - this.zo; - float f = (float) (d0 * d0 + d1 * d1); -@@ -2586,8 +2583,6 @@ public abstract class LivingEntity extends Entity { - if (this.isSleeping()) { - this.xRot = 0.0F; - } -- -- SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot - } - - public void detectEquipmentUpdates() { -@@ -2769,7 +2764,6 @@ public abstract class LivingEntity extends Entity { - - this.setDeltaMovement(d4, d5, d6); - this.level.getProfiler().push("ai"); -- SpigotTimings.timerEntityAI.startTiming(); // Spigot - if (this.isImmobile()) { - this.jumping = false; - this.xxa = 0.0F; -@@ -2779,7 +2773,6 @@ public abstract class LivingEntity extends Entity { - this.serverAiStep(); - this.level.getProfiler().pop(); - } -- SpigotTimings.timerEntityAI.stopTiming(); // Spigot - - this.level.getProfiler().pop(); - this.level.getProfiler().push("jump"); -@@ -2814,9 +2807,9 @@ public abstract class LivingEntity extends Entity { - this.updateFallFlying(); - AABB axisalignedbb = this.getBoundingBox(); - -- SpigotTimings.timerEntityAIMove.startTiming(); // Spigot -+ // SpigotTimings.timerEntityAIMove.startTiming(); // Spigot // Paper - this.travel(new Vec3((double) this.xxa, (double) this.yya, (double) this.zza)); -- SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot -+ // SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot // Paper - this.level.getProfiler().pop(); - this.level.getProfiler().push("push"); - if (this.autoSpinAttackTicks > 0) { -@@ -2824,9 +2817,7 @@ public abstract class LivingEntity extends Entity { - this.checkAutoSpinAttack(axisalignedbb, this.getBoundingBox()); - } - -- SpigotTimings.timerEntityAICollision.startTiming(); // Spigot - this.pushEntities(); -- SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot - this.level.getProfiler().pop(); - if (!this.level.isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { - this.hurt(DamageSource.DROWN, 1.0F); -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 5cc4c2668df72f83fb1526f4586b71d2ae0103dc..c153df1f4dea3dc0ae744bde01e334b3bd3b50af 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -70,7 +70,6 @@ import org.apache.logging.log4j.Logger; - import java.util.HashMap; - import java.util.Map; - import org.bukkit.Bukkit; --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.block.CapturedBlockState; -@@ -132,7 +131,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper - -- public final SpigotTimings.WorldTimingsHandler timings; // Spigot -+ public final co.aikar.timings.WorldTimingsHandler timings; // Paper - public static BlockPos lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; -@@ -217,7 +216,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) {} - }); - // CraftBukkit end -- timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings -+ timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings - this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } -@@ -797,15 +796,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - - timings.tileEntityPending.stopTiming(); // Spigot -+ co.aikar.timings.TimingHistory.tileEntityTicks += this.tickableBlockEntities.size(); // Paper - gameprofilerfiller.pop(); - spigotConfig.currentPrimedTnt = 0; // Spigot - } - - public void guardEntityTick(Consumer tickConsumer, Entity entity) { - try { -- SpigotTimings.tickEntityTimer.startTiming(); // Spigot - tickConsumer.accept(entity); -- SpigotTimings.tickEntityTimer.stopTiming(); // Spigot - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); - CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); -diff --git a/src/main/java/net/minecraft/world/level/ServerTickList.java b/src/main/java/net/minecraft/world/level/ServerTickList.java -index 0519d5adf392dd46b4a93c5c1b977c8355163c2e..10ac1ba0a3d192486f22c2127d5bc30353f0edb6 100644 ---- a/src/main/java/net/minecraft/world/level/ServerTickList.java -+++ b/src/main/java/net/minecraft/world/level/ServerTickList.java -@@ -38,12 +38,17 @@ public class ServerTickList implements TickList { - private final List> alreadyTicked = Lists.newArrayList(); - private final Consumer> ticker; - -- public ServerTickList(ServerLevel world, Predicate invalidObjPredicate, Function idToName, Consumer> consumer) { -- this.ignore = invalidObjPredicate; -- this.toId = idToName; -- this.level = world; -+ public ServerTickList(ServerLevel worldserver, Predicate predicate, Function function, Consumer> consumer, String timingsType) { // Paper -+ this.ignore = predicate; -+ this.toId = function; -+ this.level = worldserver; - this.ticker = consumer; -+ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Cleanup"); -+ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Ticking"); - } -+ private final co.aikar.timings.Timing timingCleanup; // Paper -+ private final co.aikar.timings.Timing timingTicking; // Paper -+ // Paper end - - public void tick() { - int i = this.tickNextTickList.size(); -@@ -66,6 +71,7 @@ public class ServerTickList implements TickList { - - this.level.getProfiler().push("cleaning"); - -+ this.timingCleanup.startTiming(); // Paper - TickNextTickData nextticklistentry; - - while (i > 0 && iterator.hasNext()) { -@@ -81,7 +87,9 @@ public class ServerTickList implements TickList { - --i; - } - } -+ this.timingCleanup.stopTiming(); // Paper - -+ this.timingTicking.startTiming(); // Paper - this.level.getProfiler().popPush("ticking"); - - while ((nextticklistentry = (TickNextTickData) this.currentlyTicking.poll()) != null) { -@@ -101,6 +109,7 @@ public class ServerTickList implements TickList { - } - } - -+ this.timingTicking.stopTiming(); // Paper - this.level.getProfiler().pop(); - this.alreadyTicked.clear(); - this.currentlyTicking.clear(); -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 73a271a1fccd6f82dac8d33c0d378f0d84ceb5e5..2ae786b8fc6da19ca2a40252b0606f9e06d31ded 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -61,6 +61,15 @@ public class Block extends BlockBehaviour implements ItemLike { - }); - protected final StateDefinition stateDefinition; - private BlockState defaultBlockState; -+ // Paper start -+ public co.aikar.timings.Timing timing; -+ public co.aikar.timings.Timing getTiming() { -+ if (timing == null) { -+ timing = co.aikar.timings.MinecraftTimings.getBlockTiming(this); -+ } -+ return timing; -+ } -+ // Paper end - @Nullable - private String descriptionId; - @Nullable -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index bb60c9da9f3ba0d5c5bad22512675ccb841a60e5..d445a1b7b7605eed66923789c5d8e2199c31c5ac 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -23,10 +23,12 @@ import org.bukkit.inventory.InventoryHolder; - // CraftBukkit end - - import org.spigotmc.CustomTimingsHandler; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - public abstract class BlockEntity implements net.minecraft.server.KeyedObject { // Paper - -- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot -+ public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper - // CraftBukkit start - data containers - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); - public CraftPersistentDataContainer persistentDataContainer; -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 00ce55c17980da87a3834f952475a766543506b0..f30793b81dfd9018b4879d655c7c18a9f9c25267 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -732,6 +732,7 @@ public class LevelChunk implements ChunkAccess { - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(this.bukkitChunk, this.needsDecoration)); - - if (this.needsDecoration) { -+ try (co.aikar.timings.Timing ignored = this.world.timings.chunkLoadPopulate.startTiming()) { // Paper - this.needsDecoration = false; - java.util.Random random = new java.util.Random(); - random.setSeed(world.getSeed()); -@@ -751,6 +752,7 @@ public class LevelChunk implements ChunkAccess { - } - } - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); -+ } // Paper - } - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 7e13a438bd80ab5452eacf107d418c42c2e5c727..0efaf4d0f58bcf38b427e76bf09b96e354294159 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.chunk.storage; - -+import co.aikar.timings.Timings; - import com.google.common.collect.Maps; - import it.unimi.dsi.fastutil.longs.LongOpenHashSet; - import it.unimi.dsi.fastutil.longs.LongSet; -@@ -446,7 +447,6 @@ public class ChunkSerializer { - private static void postLoadChunk(CompoundTag tag, LevelChunk chunk) { - ListTag nbttaglist = tag.getList("Entities", 10); - Level world = chunk.getLevel(); -- world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot - - for (int i = 0; i < nbttaglist.size(); ++i) { - CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); -@@ -458,8 +458,6 @@ public class ChunkSerializer { - chunk.setLastSaveHadEntities(true); - } - -- world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot -- world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot - ListTag nbttaglist1 = tag.getList("TileEntities", 10); - - for (int j = 0; j < nbttaglist1.size(); ++j) { -@@ -477,8 +475,6 @@ public class ChunkSerializer { - } - } - } -- world.timings.syncChunkLoadTileEntitiesTimer.stopTiming(); // Spigot -- - } - - private static CompoundTag packStructureData(ChunkPos pos, Map, StructureStart> structureStarts, Map, LongSet> structureReferences) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 328d1e2b128b62f24917719c79823c9fb64a0dcf..c4cf1394fe4c2782b1fea8b3653a817157d857eb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2073,12 +2073,31 @@ public final class CraftServer implements Server { - private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() - { - -+ @Deprecated - @Override - public YamlConfiguration getConfig() - { - return org.spigotmc.SpigotConfig.config; - } - -+ @Override -+ public YamlConfiguration getBukkitConfig() -+ { -+ return configuration; -+ } -+ -+ @Override -+ public YamlConfiguration getSpigotConfig() -+ { -+ return org.spigotmc.SpigotConfig.config; -+ } -+ -+ @Override -+ public YamlConfiguration getPaperConfig() -+ { -+ return com.destroystokyo.paper.PaperConfig.config; -+ } -+ - @Override - public void restart() { - org.spigotmc.RestartCommand.restart(); -diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -deleted file mode 100644 -index 56b644e272ddad0e5410061e0a202daaebb734b8..0000000000000000000000000000000000000000 ---- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -+++ /dev/null -@@ -1,163 +0,0 @@ --package org.bukkit.craftbukkit; -- --import java.util.HashMap; --import net.minecraft.world.entity.Entity; --import net.minecraft.world.level.Level; --import net.minecraft.world.level.block.entity.BlockEntity; --import net.minecraft.world.level.storage.PrimaryLevelData; --import org.bukkit.craftbukkit.scheduler.CraftTask; --import org.bukkit.plugin.java.JavaPluginLoader; --import org.bukkit.scheduler.BukkitTask; --import org.spigotmc.CustomTimingsHandler; -- --public class SpigotTimings { -- -- public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); -- public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); -- public static final CustomTimingsHandler commandFunctionsTimer = new CustomTimingsHandler("Command Functions"); -- public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler"); -- public static final CustomTimingsHandler playerConnectionTimer = new CustomTimingsHandler("** PlayerConnection"); -- public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); -- public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); -- public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update"); -- public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command"); -- public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save"); -- -- public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); -- public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); -- public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); -- public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); -- -- public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); -- public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); -- public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); -- public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); -- public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); -- -- public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue"); -- public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer); -- -- public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); -- -- public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); -- public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); -- -- public static final HashMap entityTypeTimingMap = new HashMap(); -- public static final HashMap tileEntityTypeTimingMap = new HashMap(); -- public static final HashMap pluginTaskTimingMap = new HashMap(); -- -- /** -- * Gets a timer associated with a plugins tasks. -- * @param task -- * @param period -- * @return -- */ -- public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { -- if (!task.isSync()) { -- return null; -- } -- String plugin; -- final CraftTask ctask = (CraftTask) task; -- -- if (task.getOwner() != null) { -- plugin = task.getOwner().getDescription().getFullName(); -- } else { -- plugin = "Unknown"; -- } -- String taskname = ctask.getTaskName(); -- -- String name = "Task: " + plugin + " Runnable: " + taskname; -- if (period > 0) { -- name += "(interval:" + period + ")"; -- } else { -- name += "(Single)"; -- } -- CustomTimingsHandler result = pluginTaskTimingMap.get(name); -- if (result == null) { -- result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); -- pluginTaskTimingMap.put(name, result); -- } -- return result; -- } -- -- /** -- * Get a named timer for the specified entity type to track type specific timings. -- * @param entity -- * @return -- */ -- public static CustomTimingsHandler getEntityTimings(Entity entity) { -- String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = entityTypeTimingMap.get(entityType); -- if (result == null) { -- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), activatedEntityTimer); -- entityTypeTimingMap.put(entityType, result); -- } -- return result; -- } -- -- /** -- * Get a named timer for the specified tile entity type to track type specific timings. -- * @param entity -- * @return -- */ -- public static CustomTimingsHandler getTileEntityTimings(BlockEntity entity) { -- String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = tileEntityTypeTimingMap.get(entityType); -- if (result == null) { -- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), tickTileEntityTimer); -- tileEntityTypeTimingMap.put(entityType, result); -- } -- return result; -- } -- -- /** -- * Set of timers per world, to track world specific timings. -- */ -- public static class WorldTimingsHandler { -- public final CustomTimingsHandler mobSpawn; -- public final CustomTimingsHandler doChunkUnload; -- public final CustomTimingsHandler doTickPending; -- public final CustomTimingsHandler doTickTiles; -- public final CustomTimingsHandler doChunkMap; -- public final CustomTimingsHandler doSounds; -- public final CustomTimingsHandler entityTick; -- public final CustomTimingsHandler tileEntityTick; -- public final CustomTimingsHandler tileEntityPending; -- public final CustomTimingsHandler tracker; -- public final CustomTimingsHandler doTick; -- public final CustomTimingsHandler tickEntities; -- -- public final CustomTimingsHandler syncChunkLoadTimer; -- public final CustomTimingsHandler syncChunkLoadStructuresTimer; -- public final CustomTimingsHandler syncChunkLoadEntitiesTimer; -- public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer; -- public final CustomTimingsHandler syncChunkLoadTileTicksTimer; -- public final CustomTimingsHandler syncChunkLoadPostTimer; -- -- public WorldTimingsHandler(Level server) { -- String name = ((PrimaryLevelData) server.levelData).getLevelName() + " - "; -- -- mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); -- doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); -- doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); -- doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); -- doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); -- doSounds = new CustomTimingsHandler("** " + name + "doSounds"); -- entityTick = new CustomTimingsHandler("** " + name + "entityTick"); -- tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); -- tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending"); -- -- syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); -- syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); -- syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); -- syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); -- syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); -- syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); -- -- -- tracker = new CustomTimingsHandler(name + "tracker"); -- doTick = new CustomTimingsHandler(name + "doTick"); -- tickEntities = new CustomTimingsHandler(name + "tickEntities"); -- } -- } --} -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 8fbf6c56d8820f3fa86e70a2636c0b58043232c3..61e2d92471d1498eb97d42dc642605a2e00e6089 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1806,6 +1806,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - packet.components = components; - getHandle().connection.send(packet); - } -+ -+ // Paper start -+ @Override -+ public int getPing() -+ { -+ return getHandle().latency; -+ } -+ // Paper end - }; - - public Player.Spigot spigot() -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 4bf48f77f3f7cd62a91590543f5af441c8268029..ffe9cc1011226d604dc5499e7692e9a9a5132b72 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.scheduler; - -+import co.aikar.timings.MinecraftTimings; // Paper - import com.google.common.util.concurrent.ThreadFactoryBuilder; - import java.util.ArrayList; - import java.util.Comparator; -@@ -179,7 +180,8 @@ public class CraftScheduler implements BukkitScheduler { - } - - public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { -- final CraftTask task = new CraftTask(run, nextId(), taskName); -+ final CraftTask task = new CraftTask(run, nextId(), "Internal - " + (taskName != null ? taskName : "Unknown")); -+ task.internal = true; - return handle(task, delay); - } - -@@ -260,7 +262,7 @@ public class CraftScheduler implements BukkitScheduler { - } - return false; - } -- }); -+ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer();}}; // Paper - handle(task, 0L); - for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { - if (taskPending == task) { -@@ -295,7 +297,7 @@ public class CraftScheduler implements BukkitScheduler { - } - } - } -- }); -+ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer(plugin);}}; // Paper - handle(task, 0L); - for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { - if (taskPending == task) { -@@ -402,9 +404,7 @@ public class CraftScheduler implements BukkitScheduler { - if (task.isSync()) { - currentTask = task; - try { -- task.timings.startTiming(); // Spigot - task.run(); -- task.timings.stopTiming(); // Spigot - } catch (final Throwable throwable) { - // Paper start - String msg = String.format( -@@ -438,8 +438,10 @@ public class CraftScheduler implements BukkitScheduler { - runners.remove(task.getTaskId()); - } - } -+ MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); - pending.addAll(temp); - temp.clear(); -+ MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); - debugHead = debugHead.getNextHead(currentTick); - } - -@@ -472,6 +474,7 @@ public class CraftScheduler implements BukkitScheduler { - } - - private void parsePending() { -+ MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); - CraftTask head = this.head; - CraftTask task = head.getNext(); - CraftTask lastTask = head; -@@ -490,6 +493,7 @@ public class CraftScheduler implements BukkitScheduler { - task.setNext(null); - } - this.head = lastTask; -+ MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); - } - - private boolean isReady(final int currentTick) { -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -index 09aa6809c5400ce8548ac902908b750ce7c964ec..3c96807e97657502849093e4371e9fef3584a346 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -@@ -1,12 +1,15 @@ - package org.bukkit.craftbukkit.scheduler; - - import java.util.function.Consumer; -+ -+import co.aikar.timings.NullTimingHandler; - import org.bukkit.Bukkit; - import org.bukkit.plugin.Plugin; - import org.bukkit.scheduler.BukkitTask; - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.spigotmc.CustomTimingsHandler; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - public class CraftTask implements BukkitTask, Runnable { // Spigot - -@@ -26,12 +29,12 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - */ - private volatile long period; - private long nextRun; -- private final Runnable rTask; -- private final Consumer cTask; -+ public final Runnable rTask; // Paper -+ public final Consumer cTask; // Paper -+ public Timing timings; // Paper - private final Plugin plugin; - private final int id; - -- final CustomTimingsHandler timings; // Spigot - CraftTask() { - this(null, null, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); - } -@@ -51,7 +54,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - this.id = id; - this.period = CraftTask.NO_REPEATING; - this.taskName = taskName; -- this.timings = null; // Will be changed in later patch -+ this.timings = MinecraftTimings.getInternalTaskName(taskName); - } - // Paper end - -@@ -72,7 +75,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - } - this.id = id; - this.period = period; -- this.timings = this.isSync() ? SpigotTimings.getPluginTaskTimings(this, period) : null; // Spigot -+ timings = task != null ? MinecraftTimings.getPluginTaskTimings(this, period) : NullTimingHandler.NULL; // Paper - } - - @Override -@@ -92,11 +95,13 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - - @Override - public void run() { -+ try (Timing ignored = timings.startTiming()) { // Paper - if (rTask != null) { - rTask.run(); - } else { - cTask.accept(this); - } -+ } // Paper - } - - long getPeriod() { -@@ -123,7 +128,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - this.next = next; - } - -- Class getTaskClass() { -+ public Class getTaskClass() { - return (rTask != null) ? rTask.getClass() : ((cTask != null) ? cTask.getClass() : null); - } - -@@ -147,9 +152,4 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - return true; - } - -- // Spigot start -- public String getTaskName() { -- return (getTaskClass() == null) ? "Unknown" : getTaskClass().getName(); -- } -- // Spigot end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -index e52ef47b783785dc214746b678e7b549aea9a274..3d90b3426873a3528af14f7f1ab0adae0027da2e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -@@ -5,6 +5,7 @@ import org.bukkit.util.CachedServerIcon; - public class CraftIconCache implements CachedServerIcon { - public final String value; - -+ public String getData() { return value; } // Paper - public CraftIconCache(final String value) { - this.value = value; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index ec3d663886eb134eb9ecc87e7517a73bcfb9ec02..ef7715774fbdc4c42b217d8192784e09a43fe66f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -156,6 +156,12 @@ public final class CraftMagicNumbers implements UnsafeValues { - return CraftNamespacedKey.toMinecraft(mat.getKey()); - } - // ======================================================================== -+ // Paper start -+ @Override -+ public void reportTimings() { -+ co.aikar.timings.TimingsExport.reportTimings(); -+ } -+ // Paper end - - public static byte toLegacyData(BlockState data) { - return CraftLegacy.toLegacyData(data); -@@ -330,6 +336,13 @@ public final class CraftMagicNumbers implements UnsafeValues { - return clazz; - } - -+ // Paper start -+ @Override -+ public String getTimingsServerName() { -+ return com.destroystokyo.paper.PaperConfig.timingsServerName; -+ } -+ // Paper end -+ - /** - * This helper class represents the different NBT Tags. - *

    -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index ac6fc546931f7884952058b42e7e3fab3ce42998..9bb35ec64e1538aabec9ff7831706c4717239449 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -29,7 +29,7 @@ import net.minecraft.world.entity.raid.Raider; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.chunk.LevelChunk; - import net.minecraft.world.phys.AABB; --import org.bukkit.craftbukkit.SpigotTimings; -+import co.aikar.timings.MinecraftTimings; - - public class ActivationRange - { -@@ -73,8 +73,8 @@ public class ActivationRange - /** - * These entities are excluded from Activation range checks. - * -- * @param entity -- * @param config -+ * @param entity Entity to initialize -+ * @param config Spigot config to determine ranges - * @return boolean If it should always tick. - */ - public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) -@@ -109,7 +109,7 @@ public class ActivationRange - */ - public static void activateEntities(Level world) - { -- SpigotTimings.entityActivationCheckTimer.startTiming(); -+ MinecraftTimings.entityActivationCheckTimer.startTiming(); - final int miscActivationRange = world.spigotConfig.miscActivationRange; - final int raiderActivationRange = world.spigotConfig.raiderActivationRange; - final int animalActivationRange = world.spigotConfig.animalActivationRange; -@@ -146,7 +146,7 @@ public class ActivationRange - } - } - } -- SpigotTimings.entityActivationCheckTimer.stopTiming(); -+ MinecraftTimings.entityActivationCheckTimer.stopTiming(); - } - - /** -@@ -243,10 +243,8 @@ public class ActivationRange - */ - public static boolean checkIfActive(Entity entity) - { -- SpigotTimings.checkIfActiveTimer.startTiming(); - // Never safe to skip fireworks or entities not yet added to chunk - if ( !entity.inChunk || entity instanceof FireworkRocketEntity ) { -- SpigotTimings.checkIfActiveTimer.stopTiming(); - return true; - } - -@@ -270,7 +268,6 @@ public class ActivationRange - { - isActive = false; - } -- SpigotTimings.checkIfActiveTimer.stopTiming(); - return isActive; - } - } diff --git a/Remapped-Spigot-Server-Patches/0010-Adventure.patch b/Remapped-Spigot-Server-Patches/0010-Adventure.patch deleted file mode 100644 index 4ad53cc5f6..0000000000 --- a/Remapped-Spigot-Server-Patches/0010-Adventure.patch +++ /dev/null @@ -1,3238 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Fri, 29 Jan 2021 17:54:03 +0100 -Subject: [PATCH] Adventure - -Co-authored-by: zml -Co-authored-by: Jake Potrebic - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7..429b74474ced04d8dd8f038b8590b8dfe178bf4d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -217,4 +217,9 @@ public class PaperConfig { - " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + - " - Server Name: " + timingsServerName); - } -+ -+ public static boolean useDisplayNameInQuit = false; -+ private static void useDisplayNameInQuit() { -+ useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); -+ } - } -diff --git a/src/main/java/io/papermc/paper/adventure/AdventureComponent.java b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4b4cec054ad0146773b722c7e3708f988aeeb76d ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java -@@ -0,0 +1,76 @@ -+package io.papermc.paper.adventure; -+ -+import com.google.gson.JsonElement; -+import com.google.gson.JsonSerializationContext; -+import com.google.gson.JsonSerializer; -+import java.lang.reflect.Type; -+import java.util.List; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextComponent; -+import net.minecraft.network.chat.MutableComponent; -+import net.minecraft.network.chat.Style; -+import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+ -+public final class AdventureComponent implements net.minecraft.network.chat.Component { -+ final Component wrapped; -+ private @MonotonicNonNull net.minecraft.network.chat.Component converted; -+ -+ public AdventureComponent(final Component wrapped) { -+ this.wrapped = wrapped; -+ } -+ -+ public net.minecraft.network.chat.Component deepConverted() { -+ net.minecraft.network.chat.Component converted = this.converted; -+ if (converted == null) { -+ converted = PaperAdventure.WRAPPER_AWARE_SERIALIZER.serialize(this.wrapped); -+ this.converted = converted; -+ } -+ return converted; -+ } -+ -+ public @Nullable net.minecraft.network.chat.Component deepConvertedIfPresent() { -+ return this.converted; -+ } -+ -+ @Override -+ public Style getStyle() { -+ return this.deepConverted().getStyle(); -+ } -+ -+ @Override -+ public String getContents() { -+ if (this.wrapped instanceof TextComponent) { -+ return ((TextComponent) this.wrapped).content(); -+ } else { -+ return this.deepConverted().getContents(); -+ } -+ } -+ -+ @Override -+ public String getString() { -+ return PaperAdventure.PLAIN.serialize(this.wrapped); -+ } -+ -+ @Override -+ public List getSiblings() { -+ return this.deepConverted().getSiblings(); -+ } -+ -+ @Override -+ public MutableComponent plainCopy() { -+ return this.deepConverted().plainCopy(); -+ } -+ -+ @Override -+ public MutableComponent copy() { -+ return this.deepConverted().copy(); -+ } -+ -+ public static class Serializer implements JsonSerializer { -+ @Override -+ public JsonElement serialize(final AdventureComponent src, final Type type, final JsonSerializationContext context) { -+ return PaperAdventure.GSON.serializer().toJsonTree(src.wrapped, Component.class); -+ } -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a29b6aaafd529e56a83dd96c32211f21e4aad348 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -@@ -0,0 +1,214 @@ -+package io.papermc.paper.adventure; -+ -+import io.papermc.paper.chat.ChatRenderer; -+import io.papermc.paper.event.player.AbstractChatEvent; -+import io.papermc.paper.event.player.AsyncChatEvent; -+import io.papermc.paper.event.player.ChatEvent; -+import java.util.Set; -+import java.util.concurrent.ExecutionException; -+import java.util.function.Consumer; -+import java.util.regex.Pattern; -+ -+import net.kyori.adventure.audience.Audience; -+import net.kyori.adventure.audience.MessageType; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextReplacementConfig; -+import net.kyori.adventure.text.event.ClickEvent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ServerPlayer; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+import org.bukkit.craftbukkit.util.LazyPlayerSet; -+import org.bukkit.craftbukkit.util.Waitable; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.AsyncPlayerChatEvent; -+import org.bukkit.event.player.PlayerChatEvent; -+ -+public final class ChatProcessor { -+ // <-- copied from adventure-text-serializer-legacy -+ private static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?"); -+ private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("^[a-z][a-z0-9+\\-.]*:"); -+ private static final TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder() -+ .match(DEFAULT_URL_PATTERN) -+ .replacement(url -> { -+ String clickUrl = url.content(); -+ if (!URL_SCHEME_PATTERN.matcher(clickUrl).find()) { -+ clickUrl = "http://" + clickUrl; -+ } -+ return url.clickEvent(ClickEvent.openUrl(clickUrl)); -+ }) -+ .build(); -+ // copied from adventure-text-serializer-legacy --> -+ final MinecraftServer server; -+ final ServerPlayer player; -+ final String message; -+ final boolean async; -+ final Component originalMessage; -+ -+ public ChatProcessor(final MinecraftServer server, final ServerPlayer player, final String message, final boolean async) { -+ this.server = server; -+ this.player = player; -+ this.message = message; -+ this.async = async; -+ this.originalMessage = Component.text(message); -+ } -+ -+ @SuppressWarnings({"CodeBlock2Expr", "deprecated"}) -+ public void process() { -+ this.processingLegacyFirst( -+ // continuing from AsyncPlayerChatEvent (without PlayerChatEvent) -+ event -> { -+ this.processModern( -+ legacyRenderer(event.getFormat()), -+ event.getRecipients(), -+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), -+ event.isCancelled() -+ ); -+ }, -+ // continuing from AsyncPlayerChatEvent and PlayerChatEvent -+ event -> { -+ this.processModern( -+ legacyRenderer(event.getFormat()), -+ event.getRecipients(), -+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), -+ event.isCancelled() -+ ); -+ }, -+ // no legacy events called, all nice and fresh! -+ () -> { -+ this.processModern( -+ ChatRenderer.defaultRenderer(), -+ new LazyPlayerSet(this.server), -+ Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG), -+ false -+ ); -+ } -+ ); -+ } -+ -+ @SuppressWarnings("deprecation") -+ private void processingLegacyFirst( -+ final Consumer continueAfterAsync, -+ final Consumer continueAfterAsyncAndSync, -+ final Runnable modernOnly -+ ) { -+ final boolean listenersOnAsyncEvent = anyListeners(AsyncPlayerChatEvent.getHandlerList()); -+ final boolean listenersOnSyncEvent = anyListeners(PlayerChatEvent.getHandlerList()); -+ if (listenersOnAsyncEvent || listenersOnSyncEvent) { -+ final CraftPlayer player = this.player.getBukkitEntity(); -+ final AsyncPlayerChatEvent ae = new AsyncPlayerChatEvent(this.async, player, this.message, new LazyPlayerSet(this.server)); -+ post(ae); -+ if (listenersOnSyncEvent) { -+ final PlayerChatEvent se = new PlayerChatEvent(player, ae.getMessage(), ae.getFormat(), ae.getRecipients()); -+ se.setCancelled(ae.isCancelled()); // propagate cancelled state -+ this.queueIfAsyncOrRunImmediately(new Waitable() { -+ @Override -+ protected Void evaluate() { -+ post(se); -+ return null; -+ } -+ }); -+ continueAfterAsyncAndSync.accept(se); -+ } else { -+ continueAfterAsync.accept(ae); -+ } -+ } else { -+ modernOnly.run(); -+ } -+ } -+ -+ private void processModern(final ChatRenderer renderer, final Set recipients, final Component message, final boolean cancelled) { -+ final AsyncChatEvent ae = this.createAsync(renderer, recipients, new LazyChatAudienceSet(), message); -+ ae.setCancelled(cancelled); // propagate cancelled state -+ post(ae); -+ final boolean listenersOnSyncEvent = anyListeners(ChatEvent.getHandlerList()); -+ if (listenersOnSyncEvent) { -+ this.continueWithSyncFromWhereAsyncLeftOff(ae); -+ } else { -+ this.complete(ae); -+ } -+ } -+ -+ private void continueWithSyncFromWhereAsyncLeftOff(final AsyncChatEvent ae) { -+ this.queueIfAsyncOrRunImmediately(new Waitable() { -+ @Override -+ protected Void evaluate() { -+ final ChatEvent se = ChatProcessor.this.createSync(ae.renderer(), ae.recipients(), ae.viewers(), ae.message()); -+ se.setCancelled(ae.isCancelled()); // propagate cancelled state -+ post(se); -+ ChatProcessor.this.complete(se); -+ return null; -+ } -+ }); -+ } -+ -+ private void complete(final AbstractChatEvent event) { -+ if (event.isCancelled()) { -+ return; -+ } -+ -+ final CraftPlayer player = this.player.getBukkitEntity(); -+ final Component displayName = displayName(player); -+ final Component message = event.message(); -+ final ChatRenderer renderer = event.renderer(); -+ -+ final Set viewers = event.viewers(); -+ final Set recipients = event.recipients(); -+ if (viewers instanceof LazyChatAudienceSet && recipients instanceof LazyPlayerSet && -+ (!((LazyChatAudienceSet) viewers).isLazy() || ((LazyPlayerSet) recipients).isLazy())) { -+ for (final Audience viewer : viewers) { -+ viewer.sendMessage(player, renderer.render(player, displayName, message, viewer), MessageType.CHAT); -+ } -+ } else { -+ this.server.console.sendMessage(player, renderer.render(player, displayName, message, this.server.console), MessageType.CHAT); -+ for (final Player recipient : recipients) { -+ recipient.sendMessage(player, renderer.render(player, displayName, message, recipient), MessageType.CHAT); -+ } -+ } -+ } -+ -+ private AsyncChatEvent createAsync(final ChatRenderer renderer, final Set recipients, final Set viewers, final Component message) { -+ return new AsyncChatEvent(this.async, this.player.getBukkitEntity(), recipients, viewers, renderer, message, this.originalMessage); -+ } -+ -+ private ChatEvent createSync(final ChatRenderer renderer, final Set recipients, final Set viewers, final Component message) { -+ return new ChatEvent(this.player.getBukkitEntity(), recipients, viewers, renderer, message, this.originalMessage); -+ } -+ -+ private static String legacyDisplayName(final CraftPlayer player) { -+ return player.getDisplayName(); -+ } -+ -+ private static Component displayName(final CraftPlayer player) { -+ return player.displayName(); -+ } -+ -+ private static ChatRenderer legacyRenderer(final String format) { -+ return (player, displayName, message, recipient) -> PaperAdventure.LEGACY_SECTION_UXRC.deserialize(String.format(format, legacyDisplayName((CraftPlayer) player), PaperAdventure.LEGACY_SECTION_UXRC.serialize(message))).replaceText(URL_REPLACEMENT_CONFIG); -+ } -+ -+ private void queueIfAsyncOrRunImmediately(final Waitable waitable) { -+ if (this.async) { -+ this.server.processQueue.add(waitable); -+ } else { -+ waitable.run(); -+ } -+ try { -+ waitable.get(); -+ } catch (final InterruptedException e) { -+ Thread.currentThread().interrupt(); // tag, you're it -+ } catch (final ExecutionException e) { -+ throw new RuntimeException("Exception processing chat", e.getCause()); -+ } -+ } -+ -+ private static void post(final Event event) { -+ Bukkit.getPluginManager().callEvent(event); -+ } -+ -+ private static boolean anyListeners(final HandlerList handlers) { -+ return handlers.getRegisteredListeners().length > 0; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/DisplayNames.java b/src/main/java/io/papermc/paper/adventure/DisplayNames.java -new file mode 100644 -index 0000000000000000000000000000000000000000..bfaf5d3c5aae8a587c2b11d90089c588b2a2aba0 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/DisplayNames.java -@@ -0,0 +1,22 @@ -+package io.papermc.paper.adventure; -+ -+import net.minecraft.server.level.ServerPlayer; -+import org.bukkit.ChatColor; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+ -+public final class DisplayNames { -+ private DisplayNames() { -+ } -+ -+ public static String getLegacy(final CraftPlayer player) { -+ return getLegacy(player.getHandle()); -+ } -+ -+ public static String getLegacy(final ServerPlayer player) { -+ final String legacy = player.displayName; -+ if (legacy != null) { -+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName) + ChatColor.getLastColors(player.displayName); -+ } -+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..10f08e2b73610ab06928d1f63348920fef8e91fa ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java -@@ -0,0 +1,21 @@ -+package io.papermc.paper.adventure; -+ -+import net.kyori.adventure.audience.Audience; -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.util.LazyHashSet; -+import org.bukkit.craftbukkit.util.LazyPlayerSet; -+import org.bukkit.entity.Player; -+ -+import java.util.HashSet; -+import java.util.Set; -+ -+final class LazyChatAudienceSet extends LazyHashSet { -+ @Override -+ protected Set makeReference() { -+ final Set playerSet = LazyPlayerSet.makePlayerSet(MinecraftServer.getServer()); -+ final HashSet audiences = new HashSet<>(playerSet); -+ audiences.add(Bukkit.getConsoleSender()); -+ return audiences; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..eeedc30a45d9637d68f04f185b3dd90dd711b9e0 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java -@@ -0,0 +1,88 @@ -+package io.papermc.paper.adventure; -+ -+import com.mojang.brigadier.exceptions.CommandSyntaxException; -+import java.io.IOException; -+import java.util.UUID; -+import net.kyori.adventure.key.Key; -+import net.kyori.adventure.nbt.api.BinaryTagHolder; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.event.HoverEvent; -+import net.kyori.adventure.text.serializer.gson.LegacyHoverEventSerializer; -+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; -+import net.kyori.adventure.util.Codec; -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.nbt.Tag; -+import net.minecraft.nbt.TagParser; -+ -+final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer { -+ public static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer(); -+ private static final Codec SNBT_CODEC = Codec.of(TagParser::parseTag, Tag::toString); -+ -+ static final String ITEM_TYPE = "id"; -+ static final String ITEM_COUNT = "Count"; -+ static final String ITEM_TAG = "tag"; -+ -+ static final String ENTITY_NAME = "name"; -+ static final String ENTITY_TYPE = "type"; -+ static final String ENTITY_ID = "id"; -+ -+ NBTLegacyHoverEventSerializer() { -+ } -+ -+ @Override -+ public HoverEvent.ShowItem deserializeShowItem(final Component input) throws IOException { -+ final String raw = PlainComponentSerializer.plain().serialize(input); -+ try { -+ final CompoundTag contents = SNBT_CODEC.decode(raw); -+ final CompoundTag tag = contents.getCompound(ITEM_TAG); -+ return HoverEvent.ShowItem.of( -+ Key.key(contents.getString(ITEM_TYPE)), -+ contents.contains(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1, -+ tag.isEmpty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC) -+ ); -+ } catch (final CommandSyntaxException ex) { -+ throw new IOException(ex); -+ } -+ } -+ -+ @Override -+ public HoverEvent.ShowEntity deserializeShowEntity(final Component input, final Codec.Decoder componentCodec) throws IOException { -+ final String raw = PlainComponentSerializer.plain().serialize(input); -+ try { -+ final CompoundTag contents = SNBT_CODEC.decode(raw); -+ return HoverEvent.ShowEntity.of( -+ Key.key(contents.getString(ENTITY_TYPE)), -+ UUID.fromString(contents.getString(ENTITY_ID)), -+ componentCodec.decode(contents.getString(ENTITY_NAME)) -+ ); -+ } catch (final CommandSyntaxException ex) { -+ throw new IOException(ex); -+ } -+ } -+ -+ @Override -+ public Component serializeShowItem(final HoverEvent.ShowItem input) throws IOException { -+ final CompoundTag tag = new CompoundTag(); -+ tag.putString(ITEM_TYPE, input.item().asString()); -+ tag.putByte(ITEM_COUNT, (byte) input.count()); -+ if (input.nbt() != null) { -+ try { -+ tag.put(ITEM_TAG, input.nbt().get(SNBT_CODEC)); -+ } catch (final CommandSyntaxException ex) { -+ throw new IOException(ex); -+ } -+ } -+ return Component.text(SNBT_CODEC.encode(tag)); -+ } -+ -+ @Override -+ public Component serializeShowEntity(final HoverEvent.ShowEntity input, final Codec.Encoder componentCodec) throws IOException { -+ final CompoundTag tag = new CompoundTag(); -+ tag.putString(ENTITY_ID, input.id().toString()); -+ tag.putString(ENTITY_TYPE, input.type().asString()); -+ if (input.name() != null) { -+ tag.putString(ENTITY_NAME, componentCodec.encode(input.name())); -+ } -+ return Component.text(SNBT_CODEC.encode(tag)); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -new file mode 100644 -index 0000000000000000000000000000000000000000..696b7ad89af4e379d7b8f1961d1ab0cba1c3313f ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -@@ -0,0 +1,342 @@ -+package io.papermc.paper.adventure; -+ -+import com.mojang.brigadier.exceptions.CommandSyntaxException; -+import io.netty.util.AttributeKey; -+import java.io.IOException; -+import java.util.ArrayList; -+import java.util.List; -+import java.util.Locale; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+import net.kyori.adventure.bossbar.BossBar; -+import net.kyori.adventure.inventory.Book; -+import net.kyori.adventure.key.Key; -+import net.kyori.adventure.nbt.api.BinaryTagHolder; -+import net.kyori.adventure.sound.Sound; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TranslatableComponent; -+import net.kyori.adventure.text.flattener.ComponentFlattener; -+import net.kyori.adventure.text.format.TextColor; -+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; -+import net.kyori.adventure.translation.GlobalTranslator; -+import net.kyori.adventure.util.Codec; -+import net.minecraft.ChatFormatting; -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.nbt.ListTag; -+import net.minecraft.nbt.StringTag; -+import net.minecraft.nbt.TagParser; -+import net.minecraft.resources.ResourceLocation; -+import net.minecraft.sounds.SoundSource; -+import net.minecraft.world.BossEvent; -+import net.minecraft.world.item.ItemStack; -+import org.bukkit.ChatColor; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+ -+public final class PaperAdventure { -+ public static final AttributeKey LOCALE_ATTRIBUTE = AttributeKey.valueOf("adventure:locale"); -+ private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s"); -+ public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder() -+ .complexMapper(TranslatableComponent.class, (translatable, consumer) -> { -+ final @NonNull String translated = LocaleLanguage.a().a(translatable.key()); -+ -+ final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated); -+ final List args = translatable.args(); -+ int argPosition = 0; -+ int lastIdx = 0; -+ while (matcher.find()) { -+ // append prior -+ if (lastIdx < matcher.start()) { -+ consumer.accept(Component.text(translated.substring(lastIdx, matcher.start()))); -+ } -+ lastIdx = matcher.end(); -+ -+ final @Nullable String argIdx = matcher.group(1); -+ // calculate argument position -+ if (argIdx != null) { -+ try { -+ final int idx = Integer.parseInt(argIdx) - 1; -+ if (idx < args.size()) { -+ consumer.accept(args.get(idx)); -+ } -+ } catch (final NumberFormatException ex) { -+ // ignore, drop the format placeholder -+ } -+ } else { -+ final int idx = argPosition++; -+ if (idx < args.size()) { -+ consumer.accept(args.get(idx)); -+ } -+ } -+ } -+ -+ // append tail -+ if (lastIdx < translated.length()) { -+ consumer.accept(Component.text(translated.substring(lastIdx))); -+ } -+ }) -+ .build(); -+ public static final LegacyComponentSerializer LEGACY_SECTION_UXRC = LegacyComponentSerializer.builder().flattener(FLATTENER).hexColors().useUnusualXRepeatedCharacterHexFormat().build(); -+ public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build(); -+ public static final GsonComponentSerializer GSON = GsonComponentSerializer.builder() -+ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) -+ .build(); -+ public static final GsonComponentSerializer COLOR_DOWNSAMPLING_GSON = GsonComponentSerializer.builder() -+ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) -+ .downsampleColors() -+ .build(); -+ private static final Codec NBT_CODEC = new Codec() { -+ @Override -+ public @NonNull CompoundTag decode(final @NonNull String encoded) throws IOException { -+ try { -+ return TagParser.parseTag(encoded); -+ } catch (final CommandSyntaxException e) { -+ throw new IOException(e); -+ } -+ } -+ -+ @Override -+ public @NonNull String encode(final @NonNull CompoundTag decoded) { -+ return decoded.toString(); -+ } -+ }; -+ static final WrapperAwareSerializer WRAPPER_AWARE_SERIALIZER = new WrapperAwareSerializer(); -+ -+ private PaperAdventure() { -+ } -+ -+ // Key -+ -+ public static ResourceLocation asVanilla(final Key key) { -+ return new ResourceLocation(key.namespace(), key.value()); -+ } -+ -+ public static ResourceLocation asVanillaNullable(final Key key) { -+ if (key == null) { -+ return null; -+ } -+ return new ResourceLocation(key.namespace(), key.value()); -+ } -+ -+ // Component -+ -+ public static Component asAdventure(final net.minecraft.network.chat.Component component) { -+ return component == null ? Component.empty() : GSON.serializer().fromJson(net.minecraft.network.chat.Component.Serializer.toJsonTree(component), Component.class); -+ } -+ -+ public static ArrayList asAdventure(final List vanillas) { -+ final ArrayList adventures = new ArrayList<>(vanillas.size()); -+ for (final net.minecraft.network.chat.Component vanilla : vanillas) { -+ adventures.add(asAdventure(vanilla)); -+ } -+ return adventures; -+ } -+ -+ public static ArrayList asAdventureFromJson(final List jsonStrings) { -+ final ArrayList adventures = new ArrayList<>(jsonStrings.size()); -+ for (final String json : jsonStrings) { -+ adventures.add(GsonComponentSerializer.gson().deserialize(json)); -+ } -+ return adventures; -+ } -+ -+ public static List asJson(final List adventures) { -+ final List jsons = new ArrayList<>(adventures.size()); -+ for (final Component component : adventures) { -+ jsons.add(GsonComponentSerializer.gson().serialize(component)); -+ } -+ return jsons; -+ } -+ -+ public static net.minecraft.network.chat.Component asVanilla(final Component component) { -+ if (true) return new AdventureComponent(component); -+ return net.minecraft.network.chat.Component.Serializer.fromJsonTree(GSON.serializer().toJsonTree(component)); -+ } -+ -+ public static List asVanilla(final List adventures) { -+ final List vanillas = new ArrayList<>(adventures.size()); -+ for (final Component adventure : adventures) { -+ vanillas.add(asVanilla(adventure)); -+ } -+ return vanillas; -+ } -+ -+ public static String asJsonString(final Component component, final Locale locale) { -+ return GSON.serialize( -+ GlobalTranslator.render( -+ component, -+ // play it safe -+ locale != null -+ ? locale -+ : Locale.US -+ ) -+ ); -+ } -+ -+ public static String asJsonString(final net.minecraft.network.chat.Component component, final Locale locale) { -+ if (component instanceof AdventureComponent) { -+ return asJsonString(((AdventureComponent) component).wrapped, locale); -+ } -+ return net.minecraft.network.chat.Component.Serializer.componentToJson(component); -+ } -+ -+ // thank you for being worse than wet socks, Bukkit -+ public static String superHackyLegacyRepresentationOfComponent(final Component component, final String string) { -+ return LEGACY_SECTION_UXRC.serialize(component) + ChatColor.getLastColors(string); -+ } -+ -+ // BossBar -+ -+ public static BossEvent.BossBarColor asVanilla(final BossBar.Color color) { -+ if (color == BossBar.Color.PINK) { -+ return BossEvent.BossBarColor.PINK; -+ } else if (color == BossBar.Color.BLUE) { -+ return BossEvent.BossBarColor.BLUE; -+ } else if (color == BossBar.Color.RED) { -+ return BossEvent.BossBarColor.RED; -+ } else if (color == BossBar.Color.GREEN) { -+ return BossEvent.BossBarColor.GREEN; -+ } else if (color == BossBar.Color.YELLOW) { -+ return BossEvent.BossBarColor.YELLOW; -+ } else if (color == BossBar.Color.PURPLE) { -+ return BossEvent.BossBarColor.PURPLE; -+ } else if (color == BossBar.Color.WHITE) { -+ return BossEvent.BossBarColor.WHITE; -+ } -+ throw new IllegalArgumentException(color.name()); -+ } -+ -+ public static BossBar.Color asAdventure(final BossEvent.BossBarColor color) { -+ if(color == BossEvent.BossBarColor.PINK) { -+ return BossBar.Color.PINK; -+ } else if(color == BossEvent.BossBarColor.BLUE) { -+ return BossBar.Color.BLUE; -+ } else if(color == BossEvent.BossBarColor.RED) { -+ return BossBar.Color.RED; -+ } else if(color == BossEvent.BossBarColor.GREEN) { -+ return BossBar.Color.GREEN; -+ } else if(color == BossEvent.BossBarColor.YELLOW) { -+ return BossBar.Color.YELLOW; -+ } else if(color == BossEvent.BossBarColor.PURPLE) { -+ return BossBar.Color.PURPLE; -+ } else if(color == BossEvent.BossBarColor.WHITE) { -+ return BossBar.Color.WHITE; -+ } -+ throw new IllegalArgumentException(color.name()); -+ } -+ -+ public static BossEvent.BossBarOverlay asVanilla(final BossBar.Overlay overlay) { -+ if (overlay == BossBar.Overlay.PROGRESS) { -+ return BossEvent.BossBarOverlay.PROGRESS; -+ } else if (overlay == BossBar.Overlay.NOTCHED_6) { -+ return BossEvent.BossBarOverlay.NOTCHED_6; -+ } else if (overlay == BossBar.Overlay.NOTCHED_10) { -+ return BossEvent.BossBarOverlay.NOTCHED_10; -+ } else if (overlay == BossBar.Overlay.NOTCHED_12) { -+ return BossEvent.BossBarOverlay.NOTCHED_12; -+ } else if (overlay == BossBar.Overlay.NOTCHED_20) { -+ return BossEvent.BossBarOverlay.NOTCHED_20; -+ } -+ throw new IllegalArgumentException(overlay.name()); -+ } -+ -+ public static BossBar.Overlay asAdventure(final BossEvent.BossBarOverlay overlay) { -+ if (overlay == BossEvent.BossBarOverlay.PROGRESS) { -+ return BossBar.Overlay.PROGRESS; -+ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_6) { -+ return BossBar.Overlay.NOTCHED_6; -+ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_10) { -+ return BossBar.Overlay.NOTCHED_10; -+ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_12) { -+ return BossBar.Overlay.NOTCHED_12; -+ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_20) { -+ return BossBar.Overlay.NOTCHED_20; -+ } -+ throw new IllegalArgumentException(overlay.name()); -+ } -+ -+ public static void setFlag(final BossBar bar, final BossBar.Flag flag, final boolean value) { -+ if (value) { -+ bar.addFlag(flag); -+ } else { -+ bar.removeFlag(flag); -+ } -+ } -+ -+ // Book -+ -+ public static ItemStack asItemStack(final Book book, final Locale locale) { -+ final ItemStack item = new ItemStack(net.minecraft.world.item.Items.WRITTEN_BOOK, 1); -+ final CompoundTag tag = item.getOrCreateTag(); -+ tag.putString("title", asJsonString(book.title(), locale)); -+ tag.putString("author", asJsonString(book.author(), locale)); -+ final ListTag pages = new ListTag(); -+ for (final Component page : book.pages()) { -+ pages.add(StringTag.create(asJsonString(page, locale))); -+ } -+ tag.put("pages", pages); -+ return item; -+ } -+ -+ // Sounds -+ -+ public static SoundSource asVanilla(final Sound.Source source) { -+ if (source == Sound.Source.MASTER) { -+ return SoundSource.MASTER; -+ } else if (source == Sound.Source.MUSIC) { -+ return SoundSource.MUSIC; -+ } else if (source == Sound.Source.RECORD) { -+ return SoundSource.RECORDS; -+ } else if (source == Sound.Source.WEATHER) { -+ return SoundSource.WEATHER; -+ } else if (source == Sound.Source.BLOCK) { -+ return SoundSource.BLOCKS; -+ } else if (source == Sound.Source.HOSTILE) { -+ return SoundSource.HOSTILE; -+ } else if (source == Sound.Source.NEUTRAL) { -+ return SoundSource.NEUTRAL; -+ } else if (source == Sound.Source.PLAYER) { -+ return SoundSource.PLAYERS; -+ } else if (source == Sound.Source.AMBIENT) { -+ return SoundSource.AMBIENT; -+ } else if (source == Sound.Source.VOICE) { -+ return SoundSource.VOICE; -+ } -+ throw new IllegalArgumentException(source.name()); -+ } -+ -+ public static @Nullable SoundSource asVanillaNullable(final Sound.@Nullable Source source) { -+ if (source == null) { -+ return null; -+ } -+ return asVanilla(source); -+ } -+ -+ // NBT -+ -+ public static @Nullable BinaryTagHolder asBinaryTagHolder(final @Nullable CompoundTag tag) { -+ if (tag == null) { -+ return null; -+ } -+ try { -+ return BinaryTagHolder.encode(tag, NBT_CODEC); -+ } catch (final IOException e) { -+ return null; -+ } -+ } -+ -+ // Colors -+ -+ public static @NonNull TextColor asAdventure(ChatFormatting minecraftColor) { -+ if (minecraftColor.getColor() == null) { -+ throw new IllegalArgumentException("Not a valid color"); -+ } -+ return TextColor.color(minecraftColor.getColor()); -+ } -+ -+ public static @Nullable ChatFormatting asVanilla(TextColor color) { -+ return ChatFormatting.getByHexValue(color.value()); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ee6d9d5c072d68cace63068a8e2ed603ad475378 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java -@@ -0,0 +1,41 @@ -+package io.papermc.paper.adventure; -+ -+import java.util.Set; -+import java.util.function.Consumer; -+import net.kyori.adventure.bossbar.BossBar; -+import net.kyori.adventure.text.Component; -+import net.minecraft.network.protocol.game.ClientboundBossEventPacket; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+public final class VanillaBossBarListener implements BossBar.Listener { -+ private final Consumer action; -+ -+ public VanillaBossBarListener(final Consumer action) { -+ this.action = action; -+ } -+ -+ @Override -+ public void bossBarNameChanged(final @NonNull BossBar bar, final @NonNull Component oldName, final @NonNull Component newName) { -+ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_NAME); -+ } -+ -+ @Override -+ public void bossBarProgressChanged(final @NonNull BossBar bar, final float oldProgress, final float newProgress) { -+ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_PCT); -+ } -+ -+ @Override -+ public void bossBarColorChanged(final @NonNull BossBar bar, final BossBar.@NonNull Color oldColor, final BossBar.@NonNull Color newColor) { -+ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_STYLE); -+ } -+ -+ @Override -+ public void bossBarOverlayChanged(final @NonNull BossBar bar, final BossBar.@NonNull Overlay oldOverlay, final BossBar.@NonNull Overlay newOverlay) { -+ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_STYLE); -+ } -+ -+ @Override -+ public void bossBarFlagsChanged(final @NonNull BossBar bar, final @NonNull Set flagsAdded, final @NonNull Set flagsRemoved) { -+ this.action.accept(ClientboundBossEventPacket.Operation.UPDATE_PROPERTIES); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2e93ac0eb74a89c020f3356f77320cf6459727fd ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java -@@ -0,0 +1,19 @@ -+package io.papermc.paper.adventure; -+ -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.serializer.ComponentSerializer; -+ -+final class WrapperAwareSerializer implements ComponentSerializer { -+ @Override -+ public Component deserialize(final net.minecraft.network.chat.Component input) { -+ if (input instanceof AdventureComponent) { -+ return ((AdventureComponent) input).wrapped; -+ } -+ return PaperAdventure.GSON.serializer().fromJson(net.minecraft.network.chat.Component.Serializer.toJsonTree(input), Component.class); -+ } -+ -+ @Override -+ public net.minecraft.network.chat.Component serialize(final Component component) { -+ return net.minecraft.network.chat.Component.Serializer.fromJsonTree(PaperAdventure.GSON.serializer().toJsonTree(component)); -+ } -+} -diff --git a/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2dc92d8d2764d3e9b621d5c7d5e30c30367b3117 ---- /dev/null -+++ b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java -@@ -0,0 +1,36 @@ -+package net.kyori.adventure.bossbar; -+ -+import io.papermc.paper.adventure.PaperAdventure; -+import io.papermc.paper.adventure.VanillaBossBarListener; -+import net.minecraft.server.level.ServerBossEvent; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+ -+public abstract class HackyBossBarPlatformBridge { -+ public ServerBossEvent vanilla$bar; -+ private VanillaBossBarListener vanilla$listener; -+ -+ public final void paper$playerShow(final CraftPlayer player) { -+ if (this.vanilla$bar == null) { -+ final BossBar $this = (BossBar) this; -+ this.vanilla$bar = new ServerBossEvent( -+ PaperAdventure.asVanilla($this.name()), -+ PaperAdventure.asVanilla($this.color()), -+ PaperAdventure.asVanilla($this.overlay()) -+ ); -+ this.vanilla$bar.adventure = $this; -+ this.vanilla$listener = new VanillaBossBarListener(this.vanilla$bar::broadcast); -+ $this.addListener(this.vanilla$listener); -+ } -+ this.vanilla$bar.addPlayer(player.getHandle()); -+ } -+ -+ public final void paper$playerHide(final CraftPlayer player) { -+ if (this.vanilla$bar != null) { -+ this.vanilla$bar.removePlayer(player.getHandle()); -+ if (this.vanilla$bar.getPlayers().isEmpty()) { -+ ((BossBar) this).removeListener(this.vanilla$listener); -+ this.vanilla$bar = null; -+ } -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/ChatFormatting.java b/src/main/java/net/minecraft/ChatFormatting.java -index e888a90226c30757b190a3b89a56c1a312f32850..1720eba650c959810c6e4a3522979e75e10a1bb8 100644 ---- a/src/main/java/net/minecraft/ChatFormatting.java -+++ b/src/main/java/net/minecraft/ChatFormatting.java -@@ -61,6 +61,7 @@ public enum ChatFormatting { - return !this.isFormat && this != ChatFormatting.RESET; - } - -+ @Nullable public Integer getHexValue() { return this.getColor(); } // Paper - OBFHELPER - @Nullable - public Integer getColor() { - return this.color; -@@ -84,6 +85,18 @@ public enum ChatFormatting { - return name == null ? null : (ChatFormatting) ChatFormatting.FORMATTING_BY_NAME.get(cleanName(name)); - } - -+ // Paper start -+ @Nullable public static ChatFormatting getByHexValue(int i) { -+ for (ChatFormatting value : values()) { -+ if (value.getHexValue() != null && value.getHexValue() == i) { -+ return value; -+ } -+ } -+ -+ return null; -+ } -+ // Paper end -+ - @Nullable - public static ChatFormatting getById(int colorIndex) { - if (colorIndex < 0) { -diff --git a/src/main/java/net/minecraft/nbt/StringTag.java b/src/main/java/net/minecraft/nbt/StringTag.java -index 620e10b5ba9e57ff4d0d7967bf4240fafadb2be7..dab8983fa65b97ecf0fe20fdc06cc8ec60d8fe95 100644 ---- a/src/main/java/net/minecraft/nbt/StringTag.java -+++ b/src/main/java/net/minecraft/nbt/StringTag.java -@@ -43,6 +43,7 @@ public class StringTag implements Tag { - this.data = value; - } - -+ public static StringTag create(final String value) { return valueOf(value); } // Paper - OBFHELPER - public static StringTag valueOf(String value) { - return value.isEmpty() ? StringTag.EMPTY : new StringTag(value); - } -diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -index 50f14acb062c2f90266279dbd1945a3297396f0b..59788eaef0dae5ee01ceba1bf45e85cb07f88e53 100644 ---- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java -+++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -@@ -10,6 +10,7 @@ import io.netty.buffer.ByteBufOutputStream; - import io.netty.handler.codec.DecoderException; - import io.netty.handler.codec.EncoderException; - import io.netty.util.ByteProcessor; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.io.DataInput; - import java.io.DataOutput; - import java.io.IOException; -@@ -43,6 +44,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit - public class FriendlyByteBuf extends ByteBuf { - - private final ByteBuf source; -+ public java.util.Locale adventure$locale; // Paper - - public FriendlyByteBuf(ByteBuf bytebuf) { - this.source = bytebuf; -@@ -164,8 +166,15 @@ public class FriendlyByteBuf extends ByteBuf { - return Component.Serializer.fromJson(this.readUtf(262144)); - } - -+ // Paper start -+ public FriendlyByteBuf writeComponent(final net.kyori.adventure.text.Component component) { -+ return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); -+ } -+ // Paper end -+ - public FriendlyByteBuf writeComponent(Component text) { -- return this.writeUtf(Component.Serializer.toJson(text), 262144); -+ //return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); // Paper - comment -+ return this.writeUtf(PaperAdventure.asJsonString(text, this.adventure$locale), 262144); // Paper - } - - public > T readEnum(Class oclass) { -@@ -348,6 +357,7 @@ public class FriendlyByteBuf extends ByteBuf { - return this.writeUtf(s, 32767); - } - -+ public FriendlyByteBuf writeUtf(final String string, final int maxLength) { return this.writeUtf(string, maxLength); } // Paper - OBFHELPER - public FriendlyByteBuf writeUtf(String s, int i) { - byte[] abyte = s.getBytes(StandardCharsets.UTF_8); - -diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index 14fa1371e52b9af5a7550a9aa144fa406b754046..d36d0424bcd4811af892f5f76fdcefda2af1ad33 100644 ---- a/src/main/java/net/minecraft/network/PacketEncoder.java -+++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -3,6 +3,7 @@ package net.minecraft.network; - import io.netty.buffer.ByteBuf; - import io.netty.channel.ChannelHandlerContext; - import io.netty.handler.codec.MessageToByteEncoder; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.io.IOException; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.PacketFlow; -@@ -37,6 +38,7 @@ public class PacketEncoder extends MessageToByteEncoder> { - throw new IOException("Can't serialize unregistered packet"); - } else { - FriendlyByteBuf packetdataserializer = new FriendlyByteBuf(bytebuf); -+ packetdataserializer.adventure$locale = channelhandlercontext.channel().attr(PaperAdventure.LOCALE_ATTRIBUTE).get(); // Paper - - packetdataserializer.writeVarInt(integer); - -diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java -index 819ea90ea116dea396c225539fc0fbebd6176ba5..54d186a195aca6d0a4c412ed609d8c86dcc76072 100644 ---- a/src/main/java/net/minecraft/network/chat/Component.java -+++ b/src/main/java/net/minecraft/network/chat/Component.java -@@ -1,5 +1,6 @@ - package net.minecraft.network.chat; - -+import io.papermc.paper.adventure.AdventureComponent; // Paper - import com.google.gson.Gson; - import com.google.gson.GsonBuilder; - import com.google.gson.JsonArray; -@@ -110,6 +111,7 @@ public interface Component extends Message, FormattedText, Iterable { - GsonBuilder gsonbuilder = new GsonBuilder(); - - gsonbuilder.disableHtmlEscaping(); -+ gsonbuilder.registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()); // Paper - gsonbuilder.registerTypeHierarchyAdapter(Component.class, new Component.Serializer()); - gsonbuilder.registerTypeHierarchyAdapter(Style.class, new Style.Serializer()); - gsonbuilder.registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()); -@@ -262,6 +264,7 @@ public interface Component extends Message, FormattedText, Iterable { - } - - public JsonElement serialize(Component ichatbasecomponent, Type type, JsonSerializationContext jsonserializationcontext) { -+ if (ichatbasecomponent instanceof AdventureComponent) return jsonserializationcontext.serialize(ichatbasecomponent); // Paper - JsonObject jsonobject = new JsonObject(); - - if (!ichatbasecomponent.getStyle().isEmpty()) { -@@ -350,10 +353,12 @@ public interface Component extends Message, FormattedText, Iterable { - return jsonobject; - } - -+ public static String componentToJson(final Component component) { return toJson(component); } // Paper - OBFHELPER - public static String toJson(Component text) { - return Component.Serializer.GSON.toJson(text); - } - -+ public static JsonElement toJsonTree(final Component component) { return toJsonTree(component); } // Paper - OBFHELPER - public static JsonElement toJsonTree(Component text) { - return Component.Serializer.GSON.toJsonTree(text); - } -@@ -363,6 +368,7 @@ public interface Component extends Message, FormattedText, Iterable { - return (MutableComponent) GsonHelper.fromJson(Component.Serializer.GSON, json, MutableComponent.class, false); - } - -+ public static @Nullable Component fromJsonTree(final JsonElement json) { return fromJson(json); } // Paper - OBFHELPER - @Nullable - public static MutableComponent fromJson(JsonElement json) { - return (MutableComponent) Component.Serializer.GSON.fromJson(json, MutableComponent.class); -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -index ce64931b5c363352f03baddbc747246469d56a84..e47102cadb40ed8a9c011386445f15fd30de7596 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -@@ -11,6 +11,7 @@ import net.minecraft.network.protocol.Packet; - public class ClientboundChatPacket implements Packet { - - private Component message; -+ public net.kyori.adventure.text.Component adventure$message; // Paper - public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot - private ChatType type; - private UUID sender; -@@ -32,6 +33,11 @@ public class ClientboundChatPacket implements Packet { - - @Override - public void write(FriendlyByteBuf buf) throws IOException { -+ // Paper start -+ if (this.adventure$message != null) { -+ buf.writeComponent(this.adventure$message); -+ } else -+ // Paper end - // Spigot start - if (components != null) { - buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(components)); -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -index 915120cc505c70153f7b70f07d8d42c13eb77ea7..69ff8df7340e60c476803256750a48f0b43414d3 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -@@ -10,6 +10,7 @@ public class ClientboundSetTitlesPacket implements Packet 0 && flag) { // TODO: allow plugins to override? -- Component ichatbasecomponent; -- if (deathMessage.equals(deathmessage)) { -- ichatbasecomponent = this.getCombatTracker().getDeathMessage(); -- } else { -- ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage); -- } -+ if (deathMessage != null && deathMessage != net.kyori.adventure.text.Component.empty() && flag) { // Paper - Adventure // TODO: allow plugins to override? -+ Component ichatbasecomponent = PaperAdventure.asVanilla(deathMessage); // Paper - Adventure - - this.connection.send((Packet) (new ClientboundPlayerCombatPacket(this.getCombatTracker(), ClientboundPlayerCombatPacket.Event.ENTITY_DIED, ichatbasecomponent)), (future) -> { - if (!future.isSuccess()) { -@@ -1666,6 +1663,7 @@ public class ServerPlayer extends Player implements ContainerListener { - this.sendMessage(message, ChatType.SYSTEM, senderUuid); - } - -+ public void sendMessage(final Component message, final ChatType type, final UUID sender) { this.sendMessage(message, type, sender); } // Paper - OBFHELPER - public void sendMessage(Component message, ChatType type, UUID senderUuid) { - this.connection.send((Packet) (new ClientboundChatPacket(message, type, senderUuid)), (future) -> { - if (!future.isSuccess() && (type == ChatType.GAME_INFO || type == ChatType.SYSTEM)) { -@@ -1688,6 +1686,7 @@ public class ServerPlayer extends Player implements ContainerListener { - } - - public String locale = "en_us"; // CraftBukkit - add, lowercase -+ public java.util.Locale adventure$locale = java.util.Locale.US; // Paper - public void updateOptions(ServerboundClientInformationPacket packet) { - // CraftBukkit start - if (getMainArm() != packet.getMainHand()) { -@@ -1699,6 +1698,10 @@ public class ServerPlayer extends Player implements ContainerListener { - this.server.server.getPluginManager().callEvent(event); - } - this.locale = packet.language; -+ // Paper start -+ this.adventure$locale = net.kyori.adventure.translation.Translator.parseLocale(this.locale); -+ this.connection.connection.channel.attr(PaperAdventure.LOCALE_ATTRIBUTE).set(this.adventure$locale); -+ // Paper end - this.clientViewDistance = packet.viewDistance; - // CraftBukkit end - this.chatVisibility = packet.getChatVisibility(); -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 466c4322803bedf1fa61be281b954bf94fb8ff02..016e91a6ca1c8457e3e367ac0597b73e81919b68 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -168,6 +168,8 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - // CraftBukkit start -+import io.papermc.paper.adventure.ChatProcessor; // Paper -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.util.concurrent.ExecutionException; - import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - import org.bukkit.Location; -@@ -388,21 +390,24 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - return this.server.isSingleplayerOwner(this.player.getGameProfile()); - } - -- // CraftBukkit start -- @Deprecated -- public void disconnect(Component reason) { -- disconnect(CraftChatMessage.fromComponent(reason)); -+ public void disconnect(String s) { -+ // Paper start -+ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); - } -- // CraftBukkit end - -- public void disconnect(String s) { -+ public void disconnect(final Component reason) { -+ this.disconnect(PaperAdventure.asAdventure(reason)); -+ } -+ -+ public void disconnect(net.kyori.adventure.text.Component reason) { -+ // Paper end - // CraftBukkit start - fire PlayerKickEvent - if (this.processedDisconnect) { - return; - } -- String leaveMessage = ChatFormatting.YELLOW + this.player.getScoreboardName() + " left the game."; -+ net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure - -- PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), s, leaveMessage); -+ PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure - - if (this.craftServer.getServer().isRunning()) { - this.craftServer.getPluginManager().callEvent(event); -@@ -413,8 +418,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - return; - } - // Send the possibly modified leave message -- s = event.getReason(); -- final Component ichatbasecomponent = CraftChatMessage.fromString(s, true)[0]; -+ final Component ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure - // CraftBukkit end - - this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> { -@@ -1631,9 +1635,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - */ - - this.player.disconnect(); -- String quitMessage = this.server.getPlayerList().disconnect(this.player); -- if ((quitMessage != null) && (quitMessage.length() > 0)) { -- this.server.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); -+ // Paper start - Adventure -+ net.kyori.adventure.text.Component quitMessage = this.server.getPlayerList().disconnect(this.player); -+ if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) { -+ this.server.getPlayerList().sendMessage(PaperAdventure.asVanilla(quitMessage)); -+ // Paper end - } - // CraftBukkit end - TextFilter itextfilter = this.player.getTextFilter(); -@@ -1849,8 +1855,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - this.handleCommand(s); - } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { - // Do nothing, this is coming from a plugin -- } else { -- Player player = this.getPlayer(); -+ // Paper start -+ } else if (true) { -+ final ChatProcessor cp = new ChatProcessor(this.server, this.player, s, async); -+ cp.process(); -+ // Paper end -+ } else if (false) { // Paper -+ Player player = this.getPlayer(); // Paper - AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(server)); - this.craftServer.getPluginManager().callEvent(event); - -@@ -2668,21 +2679,20 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - return; - } - -- // CraftBukkit start -- Player player = this.craftServer.getPlayer(this.player); -- int x = packetplayinupdatesign.getPos().getX(); -- int y = packetplayinupdatesign.getPos().getY(); -- int z = packetplayinupdatesign.getPos().getZ(); -- String[] lines = new String[4]; -+ // CraftBukkit start // Paper start - Adventure -+ List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines[i] = ChatFormatting.stripFormatting(new TextComponent(ChatFormatting.stripFormatting((String) list.get(i))).getString()); -+ lines.add(net.kyori.adventure.text.Component.text(list.get(i))); - } -- SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.craftServer.getPlayer(this.player), lines); -+ SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.craftServer.getPluginManager().callEvent(event); - - if (!event.isCancelled()) { -- System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.messages, 0, 4); -+ for (int i = 0; i < 4; i++) { -+ tileentitysign.setMessage(i, PaperAdventure.asVanilla(event.line(i))); -+ } -+ // Paper end - tileentitysign.isEditable = false; - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index a1dd76f49c59ed0a0b7f2b68fbd1a9a70a89128b..9dbb3bb79ae2de6635f71e5ee5bebeb5e57b624e 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -35,6 +35,7 @@ import net.minecraft.world.entity.player.Player; - import org.apache.commons.lang3.Validate; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import org.bukkit.craftbukkit.util.Waitable; - import org.bukkit.event.player.AsyncPlayerPreLoginEvent; - import org.bukkit.event.player.PlayerPreLoginEvent; -@@ -299,7 +300,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { - final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); - if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { -- event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); -+ event.disallow(asyncEvent.getResult(), asyncEvent.kickMessage()); // Paper - Adventure - } - Waitable waitable = new Waitable() { - @Override -@@ -310,12 +311,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - - ServerLoginPacketListenerImpl.this.server.processQueue.add(waitable); - if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { -- disconnect(event.getKickMessage()); -+ disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure - return; - } - } else { - if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { -- disconnect(asyncEvent.getKickMessage()); -+ disconnect(PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure - return; - } - } -diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java -index de19aa66e7b6ddde17e9acf65643b4a71573d759..223df8d27c2ff1cbff634bca3dbde5cc24de7f98 100644 ---- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java -@@ -55,7 +55,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene - CraftIconCache icon = server.server.getServerIcon(); - - ServerListPingEvent() { -- super(((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.getMotd(), server.getPlayerList().getMaxPlayers()); -+ super(((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.server.motd(), server.getPlayerList().getMaxPlayers()); // Paper - Adventure - } - - @Override -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 88af57699d7f9e45ad1366243049e4f3565703ff..8cdecaf2f63c78196e0c5046fe2431b40e072c8a 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -8,6 +8,7 @@ import com.mojang.authlib.GameProfile; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.adventure.PaperAdventure; - import java.io.File; - import java.net.SocketAddress; - import java.text.SimpleDateFormat; -@@ -83,6 +84,7 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - // CraftBukkit start -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import com.google.common.base.Predicate; - import com.google.common.collect.Iterables; - import net.minecraft.server.dedicated.DedicatedServer; -@@ -251,7 +253,7 @@ public abstract class PlayerList { - } - // CraftBukkit start - chatmessage.withStyle(ChatFormatting.YELLOW); -- String joinMessage = CraftChatMessage.fromComponent(chatmessage); -+ Component joinMessage = chatmessage; // Paper - Adventure - - playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.yRot, player.xRot); - this.players.add(player); -@@ -260,19 +262,18 @@ public abstract class PlayerList { - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below - - // CraftBukkit start -- PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(cserver.getPlayer(player), joinMessage); -+ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - cserver.getPluginManager().callEvent(playerJoinEvent); - - if (!player.connection.connection.isConnected()) { - return; - } - -- joinMessage = playerJoinEvent.getJoinMessage(); -+ final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); - -- if (joinMessage != null && joinMessage.length() > 0) { -- for (Component line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { -- server.getPlayerList().broadcastAll(new ClientboundChatPacket(line, ChatType.SYSTEM, Util.NIL_UUID)); -- } -+ if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure -+ joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure -+ server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure - } - // CraftBukkit end - -@@ -469,7 +470,7 @@ public abstract class PlayerList { - - } - -- public String disconnect(ServerPlayer entityplayer) { // CraftBukkit - return string -+ public net.kyori.adventure.text.Component disconnect(ServerPlayer entityplayer) { // Paper - return Component - ServerLevel worldserver = entityplayer.getLevel(); - - entityplayer.awardStat(Stats.LEAVE_GAME); -@@ -480,7 +481,7 @@ public abstract class PlayerList { - entityplayer.closeContainer(); - } - -- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getScoreboardName() + " left the game"); -+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); - cserver.getPluginManager().callEvent(playerQuitEvent); - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - -@@ -541,7 +542,7 @@ public abstract class PlayerList { - cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); - // CraftBukkit end - -- return playerQuitEvent.getQuitMessage(); // CraftBukkit -+ return playerQuitEvent.quitMessage(); // Paper - Adventure - } - - // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer -@@ -587,10 +588,10 @@ public abstract class PlayerList { - } - - // return chatmessage; -- if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); // Spigot -+ if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure - } else if (!this.isWhiteListed(gameprofile)) { - chatmessage = new TranslatableComponent("multiplayer.disconnect.not_whitelisted"); -- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot -+ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure - } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { - IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); - -@@ -600,17 +601,17 @@ public abstract class PlayerList { - } - - // return chatmessage; -- event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); -+ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - } else { - // return this.players.size() >= this.maxPlayers && !this.f(gameprofile) ? new ChatMessage("multiplayer.disconnect.server_full") : null; - if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) { -- event.disallow(PlayerLoginEvent.Result.KICK_FULL, org.spigotmc.SpigotConfig.serverFullMessage); // Spigot -+ event.disallow(PlayerLoginEvent.Result.KICK_FULL, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure - } - } - - cserver.getPluginManager().callEvent(event); - if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { -- loginlistener.disconnect(event.getKickMessage()); -+ loginlistener.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure - return null; - } - return entity; -@@ -1131,7 +1132,7 @@ public abstract class PlayerList { - public void removeAll() { - // CraftBukkit start - disconnect safely - for (ServerPlayer player : this.players) { -- player.connection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message -+ player.connection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure - } - // CraftBukkit end - -diff --git a/src/main/java/net/minecraft/world/BossEvent.java b/src/main/java/net/minecraft/world/BossEvent.java -index 8718449abc08ed7795ac70c2bef12d15b94d4127..adb7c8db8e173801a83e5ff1f4cad0dda2abeb82 100644 ---- a/src/main/java/net/minecraft/world/BossEvent.java -+++ b/src/main/java/net/minecraft/world/BossEvent.java -@@ -1,5 +1,6 @@ - package net.minecraft.world; - -+import io.papermc.paper.adventure.PaperAdventure; - import java.util.UUID; - import net.minecraft.ChatFormatting; - import net.minecraft.network.chat.Component; -@@ -14,6 +15,7 @@ public abstract class BossEvent { - protected boolean darkenScreen; - protected boolean playBossMusic; - protected boolean createWorldFog; -+ public net.kyori.adventure.bossbar.BossBar adventure; // Paper - - public BossEvent(UUID uuid, Component name, BossEvent.BossBarColor color, BossEvent.BossBarOverlay style) { - this.id = uuid; -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 2a6a6e291efbd7cc8fed6532f18321bd141e1306..3faf52e7ac5e7e22d09cfb73cfda6b9f622137d4 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -865,6 +865,7 @@ public final class ItemStack { - } - // CraftBukkit end - -+ public Component displayName() { return this.getDisplayName(); } // Paper - OBFHELPER - public Component getDisplayName() { - MutableComponent ichatmutablecomponent = (new TextComponent("")).append(this.getHoverName()); - -diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -index 72367311f79e3ef2868c05b38bae98c5a9fb129c..c23ec1b31950471905c65e46273ae105de853d9b 100644 ---- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -+++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -@@ -94,6 +94,7 @@ public abstract class Enchantment { - return this.getOrCreateDescriptionId(); - } - -+ public final Component getTranslationComponentForLevel(int level) { return this.getFullname(level); } // Paper - OBFHELPER - public Component getFullname(int level) { - TranslatableComponent chatmessage = new TranslatableComponent(this.getDescriptionId()); - -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -index 2cccec66fbc7114c65336769e354fe6f756c9fca..d44505b3ee2a35422568e9bce0d868191e348fc0 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -@@ -32,6 +32,7 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - // CraftBukkit start -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.util.UUID; - - import org.bukkit.craftbukkit.CraftServer; -@@ -473,7 +474,7 @@ public class MapItemSavedData extends SavedData { - for ( org.bukkit.map.MapCursor cursor : render.cursors) { - - if (cursor.isVisible()) { -- icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); -+ icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure - } - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c4cf1394fe4c2782b1fea8b3653a817157d857eb..f7f5457d20586e0ba72368e64ff6025f6755e61e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -561,8 +561,10 @@ public final class CraftServer implements Server { - } - - @Override -+ @Deprecated // Paper start - public int broadcastMessage(String message) { -- return broadcast(message, BROADCAST_CHANNEL_USERS); -+ return this.broadcast(message, BROADCAST_CHANNEL_USERS); -+ // Paper end - } - - public Player getPlayer(final ServerPlayer entity) { -@@ -1306,7 +1308,15 @@ public final class CraftServer implements Server { - return configuration.getInt("settings.spawn-radius", -1); - } - -+ // Paper start - @Override -+ public net.kyori.adventure.text.Component shutdownMessage() { -+ String msg = getShutdownMessage(); -+ return msg != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(msg) : null; -+ } -+ // Paper end -+ @Override -+ @Deprecated // Paper - public String getShutdownMessage() { - return configuration.getString("settings.shutdown-message"); - } -@@ -1422,7 +1432,20 @@ public final class CraftServer implements Server { - } - - @Override -+ @Deprecated // Paper - public int broadcast(String message, String permission) { -+ // Paper start - Adventure -+ return this.broadcast(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(message), permission); -+ } -+ -+ @Override -+ public int broadcast(net.kyori.adventure.text.Component message) { -+ return this.broadcast(message, BROADCAST_CHANNEL_USERS); -+ } -+ -+ @Override -+ public int broadcast(net.kyori.adventure.text.Component message, String permission) { -+ // Paper end - Set recipients = new HashSet<>(); - for (Permissible permissible : getPluginManager().getPermissionSubscriptions(permission)) { - if (permissible instanceof CommandSender && permissible.hasPermission(permission)) { -@@ -1430,14 +1453,14 @@ public final class CraftServer implements Server { - } - } - -- BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); -+ BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); // Paper - Adventure - getPluginManager().callEvent(broadcastMessageEvent); - - if (broadcastMessageEvent.isCancelled()) { - return 0; - } - -- message = broadcastMessageEvent.getMessage(); -+ message = broadcastMessageEvent.message(); // Paper - Adventure - - for (CommandSender recipient : recipients) { - recipient.sendMessage(message); -@@ -1663,6 +1686,14 @@ public final class CraftServer implements Server { - return CraftInventoryCreator.INSTANCE.createInventory(owner, type); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); -+ return CraftInventoryCreator.INSTANCE.createInventory(owner, type, title); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); -@@ -1675,13 +1706,28 @@ public final class CraftServer implements Server { - return CraftInventoryCreator.INSTANCE.createInventory(owner, size); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) throws IllegalArgumentException { -+ Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); -+ return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, int size, String title) throws IllegalArgumentException { - Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); - return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); - } - -+ // Paper start -+ @Override -+ public Merchant createMerchant(net.kyori.adventure.text.Component title) { -+ return new org.bukkit.craftbukkit.inventory.CraftMerchantCustom(title == null ? InventoryType.MERCHANT.defaultTitle() : title); -+ } -+ // Paper end - @Override -+ @Deprecated // Paper - public Merchant createMerchant(String title) { - return new CraftMerchantCustom(title == null ? InventoryType.MERCHANT.getDefaultTitle() : title); - } -@@ -1725,6 +1771,12 @@ public final class CraftServer implements Server { - return Thread.currentThread().equals(console.serverThread) || console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog) - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component motd() { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(new net.minecraft.network.chat.TextComponent(console.getMotd())); -+ } -+ // Paper end - @Override - public String getMotd() { - return console.getMotd(); -@@ -2153,5 +2205,15 @@ public final class CraftServer implements Server { - return null; - } - } -+ -+ // Paper start -+ private Iterable adventure$audiences; -+ @Override -+ public Iterable audiences() { -+ if (this.adventure$audiences == null) { -+ this.adventure$audiences = com.google.common.collect.Iterables.concat(java.util.Collections.singleton(this.getConsoleSender()), this.getOnlinePlayers()); -+ } -+ return this.adventure$audiences; -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 05aedca561919a12ced1925c5cc9af585bb04523..ce9f10f890a5866ab6208c7253b15b09fe323a81 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -19,6 +19,12 @@ public class Main { - public static boolean useConsole = true; - - public static void main(String[] args) { -+ // Paper start -+ final String warnWhenLegacyFormattingDetected = String.join(".", "net", "kyori", "adventure", "text", "warnWhenLegacyFormattingDetected"); -+ if (false && System.getProperty(warnWhenLegacyFormattingDetected) == null) { -+ System.setProperty(warnWhenLegacyFormattingDetected, String.valueOf(true)); -+ } -+ // Paper end - // Todo: Installation script - OptionParser parser = new OptionParser() { - { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -index 639577ab8b6467302a243c99ba5a4eede3aed655..940fef58f14e06213c7f305f67dcb8918976c03d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -@@ -70,6 +70,19 @@ public class CraftBeacon extends CraftBlockEntityState implem - this.getSnapshot().secondaryPower = (effect != null) ? MobEffect.byId(effect.getId()) : null; - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component customName() { -+ final BeaconBlockEntity be = this.getSnapshot(); -+ return be.name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.name) : null; -+ } -+ -+ @Override -+ public void customName(final net.kyori.adventure.text.Component customName) { -+ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); -+ } -+ // Paper end -+ - @Override - public String getCustomName() { - BeaconBlockEntity beacon = this.getSnapshot(); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java -index 16a0f6e390a7415635e3573c1f79f7d78e5ef859..b1edc96d7e0444e72b79f190982de1d1bb5987f3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java -@@ -32,6 +32,19 @@ public abstract class CraftContainer extends - this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component customName() { -+ final T be = this.getSnapshot(); -+ return be.hasCustomName() ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.getCustomName()) : null; -+ } -+ -+ @Override -+ public void customName(final net.kyori.adventure.text.Component customName) { -+ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); -+ } -+ // Paper end -+ - @Override - public String getCustomName() { - T container = this.getSnapshot(); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java -index add5b68d5fbd887e3fc2d226eff9ab00ed01ce73..2c3d6ba06d876df168aae4cc09b7b4400e2fa33d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java -@@ -16,6 +16,19 @@ public class CraftEnchantingTable extends CraftBlockEntityState implements Sign { - - // Lazily initialized only if requested: -- private String[] originalLines = null; -- private String[] lines = null; -+ // Paper start -+ private java.util.ArrayList originalLines = null; // ArrayList for RandomAccess -+ private java.util.ArrayList lines = null; // ArrayList for RandomAccess -+ // Paper end - - public CraftSign(final Block block) { - super(block, SignBlockEntity.class); -@@ -23,27 +25,52 @@ public class CraftSign extends CraftBlockEntityState implements - super(material, te); - } - -+ // Paper start - @Override -- public String[] getLines() { -- if (lines == null) { -- // Lazy initialization: -- SignBlockEntity sign = this.getSnapshot(); -- lines = new String[sign.messages.length]; -- System.arraycopy(revertComponents(sign.messages), 0, lines, 0, lines.length); -- originalLines = new String[lines.length]; -- System.arraycopy(lines, 0, originalLines, 0, originalLines.length); -+ public java.util.List lines() { -+ this.loadLines(); -+ return this.lines; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.Component line(int index) { -+ this.loadLines(); -+ return this.lines.get(index); -+ } -+ -+ @Override -+ public void line(int index, net.kyori.adventure.text.Component line) { -+ this.loadLines(); -+ this.lines.set(index, line); -+ } -+ -+ private void loadLines() { -+ if (lines != null) { -+ return; - } -- return lines; -+ -+ // Lazy initialization: -+ SignBlockEntity sign = this.getSnapshot(); -+ lines = io.papermc.paper.adventure.PaperAdventure.asAdventure(com.google.common.collect.Lists.newArrayList(sign.messages)); -+ originalLines = new java.util.ArrayList<>(lines); -+ } -+ // Paper end -+ @Override -+ public String[] getLines() { -+ this.loadLines(); -+ return this.lines.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).toArray(String[]::new); // Paper - } - - @Override - public String getLine(int index) throws IndexOutOfBoundsException { -- return getLines()[index]; -+ this.loadLines(); -+ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(this.lines.get(index)); // Paper - } - - @Override - public void setLine(int index, String line) throws IndexOutOfBoundsException { -- getLines()[index] = line; -+ this.loadLines(); -+ this.lines.set(index, line != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(line) : net.kyori.adventure.text.Component.empty()); // Paper - } - - @Override -@@ -71,16 +98,32 @@ public class CraftSign extends CraftBlockEntityState implements - super.applyTo(sign); - - if (lines != null) { -- for (int i = 0; i < lines.length; i++) { -- String line = (lines[i] == null) ? "" : lines[i]; -- if (line.equals(originalLines[i])) { -+ // Paper start -+ for (int i = 0; i < this.lines.size(); ++i) { -+ net.kyori.adventure.text.Component component = this.lines.get(i); -+ net.kyori.adventure.text.Component origComp = this.originalLines.get(i); -+ if (component.equals(origComp)) { - continue; // The line contents are still the same, skip. - } -- sign.messages[i] = CraftChatMessage.fromString(line)[0]; -+ sign.messages[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(component); - } -+ // Paper end - } - } - -+ // Paper start -+ public static Component[] sanitizeLines(java.util.List lines) { -+ Component[] components = new Component[4]; -+ for (int i = 0; i < 4; i++) { -+ if (i < lines.size() && lines.get(i) != null) { -+ components[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(lines.get(i)); -+ } else { -+ components[i] = new TextComponent(""); -+ } -+ } -+ return components; -+ } -+ // Paper end - public static Component[] sanitizeLines(String[] lines) { - Component[] components = new Component[4]; - -diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -index 089fe4a3458ed3106fa214f89a7004a5d3c6bb95..af986adfdb547cb61fbd52f0f89858f1a9e52cc3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -@@ -80,4 +80,11 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co - public boolean isConversing() { - return conversationTracker.isConversing(); - } -+ -+ // Paper start -+ @Override -+ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { -+ this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); -+ } -+ // 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 fd473d213f4050f420bd7d729fe0df757d5398bc..b1ffe6c7a5915f00a476e88f3a38349b740b4910 100644 ---- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -+++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -@@ -187,6 +187,12 @@ public class CraftEnchantment extends Enchantment { - CraftEnchantment ench = (CraftEnchantment) other; - return !target.isCompatibleWith(ench.target); - } -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName(int level) { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); -+ } -+ // Paper end - - public net.minecraft.world.item.enchantment.Enchantment getHandle() { - return target; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index eb61c803cf74c5ca2c51d5027a02ed3db6b53096..53c231925ef1b17e48c5863570e3c54124874621 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -768,6 +768,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return getHandle().getVehicle().getBukkitEntity(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component customName() { -+ final Component name = this.getHandle().getCustomName(); -+ return name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(name) : null; -+ } -+ -+ @Override -+ public void customName(final net.kyori.adventure.text.Component customName) { -+ this.getHandle().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); -+ } -+ // Paper end -+ - @Override - public void setCustomName(String name) { - // sane limit for name length -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 7c200e43bdc170ecf8b8fbfadd7bb38c66133443..b5c0f3d91cf451a972f0cf293db03a306073c493 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -317,9 +317,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - container = CraftEventFactory.callInventoryOpenEvent(player, container); - if (container == null) return; - -- String title = container.getBukkitView().getTitle(); -+ //String title = container.getBukkitView().getTitle(); // Paper - comment -+ net.kyori.adventure.text.Component adventure$title = container.getBukkitView().title(); // Paper -+ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper - -- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); -+ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment -+ player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - getHandle().containerMenu = container; - getHandle().containerMenu.addSlotListener(player); - } -@@ -388,8 +391,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - - // Now open the window - MenuType windowType = CraftContainer.getNotchInventoryType(inventory.getTopInventory()); -- String title = inventory.getTitle(); -- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); -+ -+ //String title = inventory.getTitle(); // Paper - comment -+ net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper -+ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper -+ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment -+ player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - player.containerMenu = container; - player.containerMenu.addSlotListener(player); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 61e2d92471d1498eb97d42dc642605a2e00e6089..50d11611702e3d1f0e980fb8f2280b05b891167b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -238,14 +238,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public String getDisplayName() { -+ if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper - return getHandle().displayName; - } - - @Override - public void setDisplayName(final String name) { -+ this.getHandle().adventure$displayName = name != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(name) : net.kyori.adventure.text.Component.text(this.getName()); // Paper - getHandle().displayName = name == null ? getName() : name; - } - -+ // Paper start -+ @Override -+ public void playerListName(net.kyori.adventure.text.Component name) { -+ getHandle().listName = name == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(name); -+ for (ServerPlayer player : server.getHandle().players) { -+ if (player.getBukkitEntity().canSee(this)) { -+ player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME, getHandle())); -+ } -+ } -+ } -+ @Override -+ public net.kyori.adventure.text.Component playerListName() { -+ return getHandle().listName == null ? net.kyori.adventure.text.Component.text(getName()) : io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().listName); -+ } -+ @Override -+ public net.kyori.adventure.text.Component playerListHeader() { -+ return playerListHeader; -+ } -+ @Override -+ public net.kyori.adventure.text.Component playerListFooter() { -+ return playerListFooter; -+ } -+ // Paper end - @Override - public String getPlayerListName() { - return getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(getHandle().listName); -@@ -264,35 +289,35 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - } - -- private Component playerListHeader; -- private Component playerListFooter; -+ private net.kyori.adventure.text.Component playerListHeader; // Paper - Adventure -+ private net.kyori.adventure.text.Component playerListFooter; // Paper - Adventure - - @Override - public String getPlayerListHeader() { -- return (playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader); -+ return (playerListHeader == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListHeader); // Paper - Adventure - } - - @Override - public String getPlayerListFooter() { -- return (playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter); -+ return (playerListFooter == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListFooter); // Paper - Adventure - } - - @Override - public void setPlayerListHeader(String header) { -- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); -+ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure - updatePlayerListHeaderFooter(); - } - - @Override - public void setPlayerListFooter(String footer) { -- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); -+ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure - updatePlayerListHeaderFooter(); - } - - @Override - public void setPlayerListHeaderFooter(String header, String footer) { -- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); -- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); -+ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure -+ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure - updatePlayerListHeaderFooter(); - } - -@@ -300,8 +325,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (getHandle().connection == null) return; - - ClientboundTabListPacket packet = new ClientboundTabListPacket(); -- packet.header = (this.playerListHeader == null) ? new TextComponent("") : this.playerListHeader; -- packet.footer = (this.playerListFooter == null) ? new TextComponent("") : this.playerListFooter; -+ packet.header = (this.playerListHeader == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListHeader); // Paper - Adventure -+ packet.footer = (this.playerListFooter == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListFooter); // Paper - Adventure - getHandle().connection.send(packet); - } - -@@ -333,6 +358,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getHandle().connection.disconnect(message == null ? "" : message); - } - -+ // Paper start -+ @Override -+ public void kick(final net.kyori.adventure.text.Component message) { -+ org.spigotmc.AsyncCatcher.catchOp("player kick"); -+ final ServerGamePacketListenerImpl connection = this.getHandle().connection; -+ if (connection != null) { -+ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); -+ } -+ } -+ // Paper end -+ - @Override - public void setCompassTarget(Location loc) { - if (getHandle().connection == null) return; -@@ -559,6 +595,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getHandle().connection.send(packet); - } - -+ // Paper start -+ @Override -+ public void sendSignChange(Location loc, List lines) { -+ this.sendSignChange(loc, lines, org.bukkit.DyeColor.BLACK); -+ } -+ @Override -+ public void sendSignChange(Location loc, List lines, DyeColor dyeColor) { -+ if (getHandle().connection == null) { -+ return; -+ } -+ if (lines == null) { -+ lines = new java.util.ArrayList<>(4); -+ } -+ Validate.notNull(loc, "Location cannot be null"); -+ Validate.notNull(dyeColor, "DyeColor cannot be null"); -+ if (lines.size() < 4) { -+ throw new IllegalArgumentException("Must have at least 4 lines"); -+ } -+ Component[] components = CraftSign.sanitizeLines(lines); -+ this.sendSignChange0(components, loc, dyeColor); -+ } -+ -+ private void sendSignChange0(Component[] components, Location loc, DyeColor dyeColor) { -+ SignBlockEntity sign = new SignBlockEntity(); -+ sign.setPosition(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); -+ sign.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData())); -+ System.arraycopy(components, 0, sign.messages, 0, sign.messages.length); -+ -+ getHandle().connection.send(sign.getUpdatePacket()); -+ } -+ // Paper end - @Override - public void sendSignChange(Location loc, String[] lines) { - sendSignChange(loc, lines, DyeColor.BLACK); -@@ -581,12 +648,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - Component[] components = CraftSign.sanitizeLines(lines); -- SignBlockEntity sign = new SignBlockEntity(); -- sign.setPosition(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); -- sign.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData())); -- System.arraycopy(components, 0, sign.messages, 0, sign.messages.length); -+ /*TileEntitySign sign = new TileEntitySign(); // Paper -+ sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); -+ sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); -+ System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); - -- getHandle().connection.send(sign.getUpdatePacket()); -+ getHandle().playerConnection.sendPacket(sign.getUpdatePacket());*/ // Paper -+ this.sendSignChange0(components, loc, dyeColor); // Paper - } - - @Override -@@ -1686,6 +1754,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return (getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : getHandle().clientViewDistance; - } - -+ // Paper start -+ @Override -+ public java.util.Locale locale() { -+ return getHandle().adventure$locale; -+ } -+ // Paper end - @Override - public int getPing() { - return getHandle().latency; -@@ -1714,6 +1788,138 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getInventory().setItemInMainHand(hand); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() { -+ return this.getHandle().adventure$displayName; -+ } -+ -+ @Override -+ public void displayName(final net.kyori.adventure.text.Component displayName) { -+ this.getHandle().adventure$displayName = displayName != null ? displayName : net.kyori.adventure.text.Component.text(this.getName()); -+ this.getHandle().displayName = null; -+ } -+ -+ @Override -+ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { -+ final ClientboundChatPacket packet = new ClientboundChatPacket(null, type == net.kyori.adventure.audience.MessageType.CHAT ? net.minecraft.network.chat.ChatType.CHAT : net.minecraft.network.chat.ChatType.SYSTEM, identity.uuid()); -+ packet.adventure$message = message; -+ this.getHandle().connection.send(packet); -+ } -+ -+ @Override -+ public void sendActionBar(final net.kyori.adventure.text.Component message) { -+ final ClientboundSetTitlesPacket packet = new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.ACTIONBAR, null); -+ packet.adventure$text = message; -+ this.getHandle().connection.send(packet); -+ } -+ -+ @Override -+ public void sendPlayerListHeader(final net.kyori.adventure.text.Component header) { -+ this.playerListHeader = header; -+ this.adventure$sendPlayerListHeaderAndFooter(); -+ } -+ -+ @Override -+ public void sendPlayerListFooter(final net.kyori.adventure.text.Component footer) { -+ this.playerListFooter = footer; -+ this.adventure$sendPlayerListHeaderAndFooter(); -+ } -+ -+ @Override -+ public void sendPlayerListHeaderAndFooter(final net.kyori.adventure.text.Component header, final net.kyori.adventure.text.Component footer) { -+ this.playerListHeader = header; -+ this.playerListFooter = footer; -+ this.adventure$sendPlayerListHeaderAndFooter(); -+ } -+ -+ private void adventure$sendPlayerListHeaderAndFooter() { -+ final ServerGamePacketListenerImpl connection = this.getHandle().connection; -+ if (connection == null) return; -+ final ClientboundTabListPacket packet = new ClientboundTabListPacket(); -+ packet.adventure$header = (this.playerListHeader == null) ? net.kyori.adventure.text.Component.empty() : this.playerListHeader; -+ packet.adventure$footer = (this.playerListFooter == null) ? net.kyori.adventure.text.Component.empty() : this.playerListFooter; -+ connection.send(packet); -+ } -+ -+ @Override -+ public void showTitle(final net.kyori.adventure.title.Title title) { -+ final ServerGamePacketListenerImpl connection = this.getHandle().connection; -+ final net.kyori.adventure.title.Title.Times times = title.times(); -+ if (times != null) { -+ connection.send(new ClientboundSetTitlesPacket(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut()))); -+ } -+ final ClientboundSetTitlesPacket sp = new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.SUBTITLE, null); -+ sp.adventure$text = title.subtitle(); -+ connection.send(sp); -+ final ClientboundSetTitlesPacket tp = new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.TITLE, null); -+ tp.adventure$text = title.title(); -+ connection.send(tp); -+ } -+ -+ private static int ticks(final java.time.Duration duration) { -+ if (duration == null) { -+ return -1; -+ } -+ return (int) (duration.toMillis() / 50L); -+ } -+ -+ @Override -+ public void clearTitle() { -+ this.getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.CLEAR, null)); -+ } -+ -+ // resetTitle implemented above -+ -+ @Override -+ public void showBossBar(final net.kyori.adventure.bossbar.BossBar bar) { -+ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerShow(this); -+ } -+ -+ @Override -+ public void hideBossBar(final net.kyori.adventure.bossbar.BossBar bar) { -+ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerHide(this); -+ } -+ -+ @Override -+ public void playSound(final net.kyori.adventure.sound.Sound sound) { -+ final Vec3 pos = this.getHandle().position(); -+ this.playSound(sound, pos.x, pos.y, pos.z); -+ } -+ -+ @Override -+ public void playSound(final net.kyori.adventure.sound.Sound sound, final double x, final double y, final double z) { -+ final ResourceLocation name = io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.name()); -+ final java.util.Optional event = net.minecraft.core.Registry.SOUND_EVENT.getOptional(name); -+ if (event.isPresent()) { -+ this.getHandle().connection.send(new ClientboundSoundPacket(event.get(), io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), x, y, z, sound.volume(), sound.pitch())); -+ } else { -+ this.getHandle().connection.send(new ClientboundCustomSoundPacket(name, io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), new Vec3(x, y, z), sound.volume(), sound.pitch())); -+ } -+ } -+ -+ @Override -+ public void stopSound(final net.kyori.adventure.sound.SoundStop stop) { -+ this.getHandle().connection.send(new ClientboundStopSoundPacket( -+ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.sound()), -+ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.source()) -+ )); -+ } -+ -+ @Override -+ public void openBook(final net.kyori.adventure.inventory.Book book) { -+ final java.util.Locale locale = this.getHandle().adventure$locale; -+ final net.minecraft.world.item.ItemStack item = io.papermc.paper.adventure.PaperAdventure.asItemStack(book, locale); -+ final ServerPlayer player = this.getHandle(); -+ final ServerGamePacketListenerImpl connection = player.connection; -+ final net.minecraft.world.entity.player.Inventory inventory = player.inventory; -+ final int slot = inventory.items.size() + inventory.selected; -+ connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, item)); -+ connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND)); -+ connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, inventory.getSelected())); -+ } -+ // Paper end -+ - // Spigot start - private final Player.Spigot spigot = new Player.Spigot() - { -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index abd65693aca1964b65d091e633a36c97513c1d69..7fde1bb7587e567270e3f936381c6d361870211f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -776,9 +776,9 @@ public class CraftEventFactory { - return event; - } - -- public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, List drops, String deathMessage, boolean keepInventory) { -+ public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, List drops, net.kyori.adventure.text.Component deathMessage, String stringDeathMessage, boolean keepInventory) { // Paper - Adventure - CraftPlayer entity = victim.getBukkitEntity(); -- PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage); -+ PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure - event.setKeepInventory(keepInventory); - org.bukkit.World world = entity.getWorld(); - Bukkit.getServer().getPluginManager().callEvent(event); -@@ -802,7 +802,7 @@ public class CraftEventFactory { - * Server methods - */ - public static ServerListPingEvent callServerListPingEvent(Server craftServer, InetAddress address, String motd, int numPlayers, int maxPlayers) { -- ServerListPingEvent event = new ServerListPingEvent(address, motd, numPlayers, maxPlayers); -+ ServerListPingEvent event = new ServerListPingEvent(address, craftServer.motd(), numPlayers, maxPlayers); // Paper - Adventure - craftServer.getPluginManager().callEvent(event); - return event; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -index a393bdae6ef588289c8814a1896146a993c92e71..680c7818a7097355158eb76662ecebbae6dd6637 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -@@ -1,6 +1,5 @@ - package org.bukkit.craftbukkit.inventory; - --import net.minecraft.network.chat.TextComponent; - import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; - import net.minecraft.world.Container; - import net.minecraft.world.entity.player.Player; -@@ -38,6 +37,7 @@ public class CraftContainer extends AbstractContainerMenu { - - private final InventoryView view; - private InventoryType cachedType; -+ private net.kyori.adventure.text.Component adventure$title; // Paper - private String cachedTitle; - private AbstractContainerMenu delegate; - private final int cachedSize; -@@ -49,7 +49,9 @@ public class CraftContainer extends AbstractContainerMenu { - Container top = ((CraftInventory) view.getTopInventory()).getInventory(); - net.minecraft.world.entity.player.Inventory bottom = (net.minecraft.world.entity.player.Inventory) ((CraftInventory) view.getBottomInventory()).getInventory(); - cachedType = view.getType(); -- cachedTitle = view.getTitle(); -+ this.adventure$title = view.title(); // Paper -+ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper -+ //cachedTitle = view.getTitle(); // Paper - comment - cachedSize = getSize(); - setupSlots(top, bottom, player); - } -@@ -76,6 +78,13 @@ public class CraftContainer extends AbstractContainerMenu { - return inventory.getType(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component title() { -+ return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).title() : net.kyori.adventure.text.Component.text(inventory.getType().getDefaultTitle()); -+ } -+ // Paper end -+ - @Override - public String getTitle() { - return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).getTitle() : inventory.getType().getDefaultTitle(); -@@ -94,7 +103,8 @@ public class CraftContainer extends AbstractContainerMenu { - - @Override - public boolean isSynched(Player player) { -- if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { -+ if (cachedType == view.getType() && cachedSize == getSize() && this.adventure$title.equals(view.title())) { // Paper -+ //if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { // Paper - comment - return true; - } - // If the window type has changed for some reason, update the player -@@ -102,7 +112,9 @@ public class CraftContainer extends AbstractContainerMenu { - // as good a place as any to put something like this. - boolean typeChanged = (cachedType != view.getType()); - cachedType = view.getType(); -- cachedTitle = view.getTitle(); -+ this.adventure$title = view.title(); // Paper -+ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper -+ //cachedTitle = view.getTitle(); // Paper - comment - if (view.getPlayer() instanceof CraftPlayer) { - CraftPlayer player1 = (CraftPlayer) view.getPlayer(); - MenuType type = getNotchInventoryType(view.getTopInventory()); -@@ -114,7 +126,8 @@ public class CraftContainer extends AbstractContainerMenu { - setupSlots(top, bottom, player1.getHandle()); - } - int size = getSize(); -- player1.getHandle().connection.send(new ClientboundOpenScreenPacket(this.containerId, type, new TextComponent(cachedTitle))); -+ player1.getHandle().connection.send(new ClientboundOpenScreenPacket(this.containerId, type, io.papermc.paper.adventure.PaperAdventure.asVanilla(this.adventure$title))); // Paper -+ //player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, new ChatComponentText(cachedTitle))); // Paper - comment - player1.updateInventory(); - } - return true; -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -index 397cd9651381a8a0ddb4ca173690e9b80428b182..46805a25c0273b76c19a3bbd40078d78c5379f43 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -@@ -19,6 +19,12 @@ public class CraftInventoryCustom extends CraftInventory { - super(new MinecraftInventory(owner, type)); - } - -+ // Paper start -+ public CraftInventoryCustom(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ super(new MinecraftInventory(owner, type, title)); -+ } -+ // Paper end -+ - public CraftInventoryCustom(InventoryHolder owner, InventoryType type, String title) { - super(new MinecraftInventory(owner, type, title)); - } -@@ -27,6 +33,12 @@ public class CraftInventoryCustom extends CraftInventory { - super(new MinecraftInventory(owner, size)); - } - -+ // Paper start -+ public CraftInventoryCustom(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { -+ super(new MinecraftInventory(owner, size, title)); -+ } -+ // Paper end -+ - public CraftInventoryCustom(InventoryHolder owner, int size, String title) { - super(new MinecraftInventory(owner, size, title)); - } -@@ -36,9 +48,17 @@ public class CraftInventoryCustom extends CraftInventory { - private int maxStack = MAX_STACK; - private final List viewers; - private final String title; -+ private final net.kyori.adventure.text.Component adventure$title; // Paper - private InventoryType type; - private final InventoryHolder owner; - -+ // Paper start -+ public MinecraftInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ this(owner, type.getDefaultSize(), title); -+ this.type = type; -+ } -+ // Paper end -+ - public MinecraftInventory(InventoryHolder owner, InventoryType type) { - this(owner, type.getDefaultSize(), type.getDefaultTitle()); - this.type = type; -@@ -57,11 +77,24 @@ public class CraftInventoryCustom extends CraftInventory { - Validate.notNull(title, "Title cannot be null"); - this.items = NonNullList.a(size, ItemStack.EMPTY); - this.title = title; -+ this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(title); - this.viewers = new ArrayList(); - this.owner = owner; - this.type = InventoryType.CHEST; - } - -+ // Paper start -+ public MinecraftInventory(final InventoryHolder owner, final int size, final net.kyori.adventure.text.Component title) { -+ Validate.notNull(title, "Title cannot be null"); -+ this.items = NonNullList.a(size, ItemStack.EMPTY); -+ this.title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); -+ this.adventure$title = title; -+ this.viewers = new ArrayList(); -+ this.owner = owner; -+ this.type = InventoryType.CHEST; -+ } -+ // Paper end -+ - @Override - public int getContainerSize() { - return items.size(); -@@ -183,6 +216,12 @@ public class CraftInventoryCustom extends CraftInventory { - return null; - } - -+ // Paper start -+ public net.kyori.adventure.text.Component title() { -+ return this.adventure$title; -+ } -+ // Paper end -+ - public String getTitle() { - return title; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -index 326e8eb49e67ccfbf8f9b23bd6f03ea3576b9d35..945a80ca026c12e16a7ac5bebe56f846a437f847 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -@@ -64,6 +64,13 @@ public class CraftInventoryView extends InventoryView { - return CraftItemStack.asCraftMirror(container.getSlot(slot).getItem()); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component title() { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.container.getTitle()); -+ } -+ // Paper end -+ - @Override - public String getTitle() { - return CraftChatMessage.fromComponent(container.getTitle()); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 89a3617068421bb86baf4e8bfd9df2d0626adff7..32fa5ca0df07466e40817341d85d359b282f3078 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -334,4 +334,17 @@ public final class CraftItemFactory implements ItemFactory { - public Material updateMaterial(ItemMeta meta, Material material) throws IllegalArgumentException { - return ((CraftMetaItem) meta).updateMaterial(material); - } -+ -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final ItemStack item, final java.util.function.UnaryOperator op) { -+ final net.minecraft.nbt.CompoundTag tag = CraftItemStack.asNMSCopy(item).getTag(); -+ return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowItem.of(item.getType().getKey(), item.getAmount(), io.papermc.paper.adventure.PaperAdventure.asBinaryTagHolder(tag)))); -+ } -+ -+ @Override -+ public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -index 71136bb009d6c8c92595f957ee7680a771ea9a63..306c6483708ae1b41bd16f122d36beec1916a776 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -@@ -14,10 +14,17 @@ import org.apache.commons.lang.Validate; - - public class CraftMerchantCustom extends CraftMerchant { - -+ @Deprecated // Paper - Adventure - public CraftMerchantCustom(String title) { - super(new MinecraftMerchant(title)); - getMerchant().craftMerchant = this; - } -+ // Paper start -+ public CraftMerchantCustom(net.kyori.adventure.text.Component title) { -+ super(new MinecraftMerchant(title)); -+ getMerchant().craftMerchant = this; -+ } -+ // Paper end - - @Override - public String toString() { -@@ -37,10 +44,17 @@ public class CraftMerchantCustom extends CraftMerchant { - private Level tradingWorld; - protected CraftMerchant craftMerchant; - -+ @Deprecated // Paper - Adventure - public MinecraftMerchant(String title) { - Validate.notNull(title, "Title cannot be null"); - this.title = new TextComponent(title); - } -+ // Paper start -+ public MinecraftMerchant(net.kyori.adventure.text.Component title) { -+ Validate.notNull(title, "Title cannot be null"); -+ this.title = io.papermc.paper.adventure.PaperAdventure.asVanilla(title); -+ } -+ // Paper end - - @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 6dba12c4f58a462c8d466461eb8b804dd045766d..a592d4a286a775a61192dde2a4d21a0681090415 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -1,8 +1,9 @@ - package org.bukkit.craftbukkit.inventory; - - import com.google.common.collect.ImmutableList; --import com.google.common.collect.ImmutableMap.Builder; - import com.google.common.collect.Lists; -+ -+import com.google.common.collect.ImmutableMap; // Paper - import java.util.ArrayList; - import java.util.Arrays; - import java.util.List; -@@ -17,9 +18,12 @@ import org.bukkit.craftbukkit.util.CraftChatMessage; - import org.bukkit.craftbukkit.util.CraftMagicNumbers; - import org.bukkit.inventory.meta.BookMeta; - import org.bukkit.inventory.meta.BookMeta.Generation; -+import org.checkerframework.checker.nullness.qual.NonNull; - - // Spigot start - import static org.spigotmc.ValidateUtils.*; -+ -+import BookMetaBuilder; - import java.util.AbstractList; - import net.md_5.bungee.api.chat.BaseComponent; - import net.md_5.bungee.chat.ComponentSerializer; -@@ -269,6 +273,141 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - this.generation = (generation == null) ? null : generation.ordinal(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component title() { -+ return this.title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.title); -+ } -+ -+ @Override -+ public org.bukkit.inventory.meta.BookMeta title(net.kyori.adventure.text.Component title) { -+ this.setTitle(title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title)); -+ return this; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.Component author() { -+ return this.author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.author); -+ } -+ -+ @Override -+ public org.bukkit.inventory.meta.BookMeta author(net.kyori.adventure.text.Component author) { -+ this.setAuthor(author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author)); -+ return this; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.Component page(final int page) { -+ Validate.isTrue(isValidPage(page), "Invalid page number"); -+ return this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(pages.get(page - 1)) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(pages.get(page - 1)); -+ } -+ -+ @Override -+ public void page(final int page, net.kyori.adventure.text.Component data) { -+ if (!isValidPage(page)) { -+ throw new IllegalArgumentException("Invalid page number " + page + "/" + pages.size()); -+ } -+ if (data == null) { -+ data = net.kyori.adventure.text.Component.empty(); -+ } -+ pages.set(page - 1, this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(data) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(data)); -+ } -+ -+ @Override -+ public List pages() { -+ if (this.pages == null) return ImmutableList.of(); -+ if (this instanceof CraftMetaBookSigned) -+ return pages.stream().map(net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson()::deserialize).collect(ImmutableList.toImmutableList()); -+ else -+ return pages.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::deserialize).collect(ImmutableList.toImmutableList()); -+ } -+ -+ @Override -+ public BookMeta pages(List pages) { -+ if (this.pages != null) this.pages.clear(); -+ for (net.kyori.adventure.text.Component page : pages) { -+ addPages(page); -+ } -+ return this; -+ } -+ -+ @Override -+ public BookMeta pages(net.kyori.adventure.text.Component... pages) { -+ if (this.pages != null) this.pages.clear(); -+ addPages(pages); -+ return this; -+ } -+ -+ @Override -+ public void addPages(net.kyori.adventure.text.Component... pages) { -+ if (this.pages == null) this.pages = new ArrayList<>(); -+ for (net.kyori.adventure.text.Component page : pages) { -+ if (this.pages.size() >= MAX_PAGES) { -+ return; -+ } -+ -+ if (page == null) { -+ page = net.kyori.adventure.text.Component.empty(); -+ } -+ -+ this.pages.add(this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(page) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(page)); -+ } -+ } -+ -+ private CraftMetaBook(net.kyori.adventure.text.Component title, net.kyori.adventure.text.Component author, List pages) { -+ super((org.bukkit.craftbukkit.inventory.CraftMetaItem) org.bukkit.Bukkit.getItemFactory().getItemMeta(org.bukkit.Material.WRITABLE_BOOK)); -+ this.title = title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); -+ this.author = author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author); -+ this.pages = pages.subList(0, Math.min(MAX_PAGES, pages.size())).stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).collect(java.util.stream.Collectors.toList()); -+ } -+ -+ static final class CraftMetaBookBuilder implements BookMetaBuilder { -+ private net.kyori.adventure.text.Component title = null; -+ private net.kyori.adventure.text.Component author = null; -+ private final List pages = new java.util.ArrayList<>(); -+ -+ @Override -+ public BookMetaBuilder title(net.kyori.adventure.text.Component title) { -+ this.title = title; -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder author(net.kyori.adventure.text.Component author) { -+ this.author = author; -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder addPage(net.kyori.adventure.text.Component page) { -+ this.pages.add(page); -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder pages(net.kyori.adventure.text.Component... pages) { -+ java.util.Collections.addAll(this.pages, pages); -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder pages(java.util.Collection pages) { -+ this.pages.addAll(pages); -+ return this; -+ } -+ -+ @Override -+ public BookMeta build() { -+ return new CraftMetaBook(title, author, pages); -+ } -+ } -+ -+ @Override -+ public BookMetaBuilder toBuilder() { -+ return new CraftMetaBookBuilder(); -+ } -+ -+ // Paper end - @Override - public String getPage(final int page) { - Validate.isTrue(isValidPage(page), "Invalid page number"); -@@ -413,7 +552,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - } - - @Override -- Builder serialize(Builder builder) { -+ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { - super.serialize(builder); - - if (hasTitle()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -index 00445fc7373c70f4cecc4114f9bcfb4b6f27c0e8..0cf60eb9b6ba1a79c9b603c4349debd478101f9a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -@@ -1,6 +1,6 @@ - package org.bukkit.craftbukkit.inventory; - --import com.google.common.collect.ImmutableMap.Builder; -+import com.google.common.collect.ImmutableMap; // Paper - import java.util.Map; - import net.minecraft.nbt.CompoundTag; - import org.bukkit.Material; -@@ -84,7 +84,7 @@ class CraftMetaBookSigned extends CraftMetaBook implements BookMeta { - } - - @Override -- Builder serialize(Builder builder) { -+ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { - super.serialize(builder); - return builder; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 2e819849e83967d751f7b0612a7cf4edb5a7264b..cca04daf84e506382365c0ba945cb024bd4d4475 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -744,6 +744,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() { -+ return displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(displayName); -+ } -+ -+ @Override -+ public void displayName(final net.kyori.adventure.text.Component displayName) { -+ this.displayName = displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(displayName); -+ } -+ // Paper end -+ - @Override - public String getDisplayName() { - return CraftChatMessage.fromJSONComponent(displayName); -@@ -779,6 +791,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return this.lore != null && !this.lore.isEmpty(); - } - -+ // Paper start -+ @Override -+ public List lore() { -+ return this.lore != null ? io.papermc.paper.adventure.PaperAdventure.asAdventureFromJson(this.lore) : null; -+ } -+ -+ @Override -+ public void lore(final List lore) { -+ this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asJson(lore) : null; -+ } -+ // Paper end -+ - @Override - public boolean hasRepairCost() { - return repairCost > 0; -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java -index ed4415f6dd588c08c922efd5beebb3b124beb9d6..78a7ac47f20e84ccd67ff44d0bc7a2f2faa0d476 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java -@@ -12,6 +12,13 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve - return new CraftInventoryCustom(holder, type); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ return new CraftInventoryCustom(owner, type, title); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - return new CraftInventoryCustom(owner, type, title); -@@ -21,6 +28,12 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve - return new CraftInventoryCustom(owner, size); - } - -+ // Paper start -+ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { -+ return new CraftInventoryCustom(owner, size, title); -+ } -+ // Paper end -+ - public Inventory createInventory(InventoryHolder owner, int size, String title) { - return new CraftInventoryCustom(owner, size, title); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b833806a0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -@@ -43,6 +43,17 @@ public final class CraftInventoryCreator { - return converterMap.get(type).createInventory(holder, type); - } - -+ // Paper start -+ public Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title) { -+ // Paper start -+ if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type, title); -+ } -+ //noinspection ConstantConditions // Paper end -+ return converterMap.get(type).createInventory(holder, type, title); -+ } -+ // Paper end -+ - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - return converterMap.get(type).createInventory(holder, type, title); - } -@@ -51,6 +62,12 @@ public final class CraftInventoryCreator { - return DEFAULT_CONVERTER.createInventory(holder, size); - } - -+ // Paper start -+ public Inventory createInventory(InventoryHolder holder, int size, net.kyori.adventure.text.Component title) { -+ return DEFAULT_CONVERTER.createInventory(holder, size, title); -+ } -+ // Paper end -+ - public Inventory createInventory(InventoryHolder holder, int size, String title) { - return DEFAULT_CONVERTER.createInventory(holder, size, title); - } -@@ -59,6 +76,10 @@ public final class CraftInventoryCreator { - - Inventory createInventory(InventoryHolder holder, InventoryType type); - -+ // Paper start -+ Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title); -+ // Paper end -+ - Inventory createInventory(InventoryHolder holder, InventoryType type, String title); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -index 0395a6235d62126540e370d6ef77e6966c50ca1d..3ef9742a68084d159ea8ed5709298f9863e04a67 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -@@ -31,6 +31,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return getInventory(getTileEntity()); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ Container te = getTileEntity(); -+ if (te instanceof RandomizableContainerBlockEntity) { -+ ((RandomizableContainerBlockEntity) te).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); -+ } -+ -+ return getInventory(te); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - Container te = getTileEntity(); -@@ -54,6 +66,15 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return furnace; - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ Container tileEntity = getTileEntity(); -+ ((AbstractFurnaceBlockEntity) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); -+ return getInventory(tileEntity); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - Container tileEntity = getTileEntity(); -@@ -74,6 +95,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return new BrewingStandBlockEntity(); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ // BrewingStand does not extend TileEntityLootable -+ Container tileEntity = getTileEntity(); -+ if (tileEntity instanceof BrewingStandBlockEntity) { -+ ((BrewingStandBlockEntity) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); -+ } -+ return getInventory(tileEntity); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - // BrewingStand does not extend TileEntityLootable -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -index d5ebb11447a8effa41138a13874fd3e5246dfe71..96ba508c87336d012c1ed5aa982588f55782a2fe 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -@@ -30,6 +30,21 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective - return objective.getName(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(objective.getDisplayName()); -+ } -+ @Override -+ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { -+ if (displayName == null) { -+ displayName = net.kyori.adventure.text.Component.empty(); -+ } -+ CraftScoreboard scoreboard = checkState(); -+ objective.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); -+ } -+ // Paper end - @Override - public String getDisplayName() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -index af160d3bdb82f07c6c836a438b8ab37b803c29e2..4c93be31fd95d731327479519ecb34a08785c1ca 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -@@ -27,6 +27,27 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - public CraftObjective registerNewObjective(String name, String criteria) throws IllegalArgumentException { - return registerNewObjective(name, criteria, name); - } -+ // Paper start -+ @Override -+ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName) { -+ return registerNewObjective(name, criteria, displayName, org.bukkit.scoreboard.RenderType.INTEGER); -+ } -+ @Override -+ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName, RenderType renderType) { -+ if (displayName == null) { -+ displayName = net.kyori.adventure.text.Component.empty(); -+ } -+ Validate.notNull(name, "Objective name cannot be null"); -+ Validate.notNull(criteria, "Criteria cannot be null"); -+ Validate.notNull(displayName, "Display name cannot be null"); -+ Validate.notNull(renderType, "RenderType cannot be null"); -+ Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); -+ Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); -+ CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ net.minecraft.world.scores.Objective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); -+ return new CraftObjective(this, objective); -+ } -+ // Paper end - - @Override - public CraftObjective registerNewObjective(String name, String criteria, String displayName) throws IllegalArgumentException { -@@ -35,7 +56,7 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - - @Override - public CraftObjective registerNewObjective(String name, String criteria, String displayName, RenderType renderType) throws IllegalArgumentException { -- Validate.notNull(name, "Objective name cannot be null"); -+ /*Validate.notNull(name, "Objective name cannot be null"); // Paper - Validate.notNull(criteria, "Criteria cannot be null"); - Validate.notNull(displayName, "Display name cannot be null"); - Validate.notNull(renderType, "RenderType cannot be null"); -@@ -44,8 +65,9 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); - - CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -- net.minecraft.world.scores.Objective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); -- return new CraftObjective(this, objective); -+ ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); -+ return new CraftObjective(this, objective);*/ // Paper -+ return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -index f5237ff19d8b26be0b762659ad0ea6887205b3f9..7ebcba4ada42f5599d56cfdeb75dbf62f2a09b78 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -@@ -28,6 +28,55 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { - - return team.getName(); - } -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getDisplayName()); -+ } -+ @Override -+ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { -+ if (displayName == null) displayName = net.kyori.adventure.text.Component.empty(); -+ CraftScoreboard scoreboard = checkState(); -+ team.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); -+ } -+ @Override -+ public net.kyori.adventure.text.Component prefix() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPlayerPrefix()); -+ } -+ @Override -+ public void prefix(net.kyori.adventure.text.Component prefix) throws IllegalStateException, IllegalArgumentException { -+ if (prefix == null) prefix = net.kyori.adventure.text.Component.empty(); -+ CraftScoreboard scoreboard = checkState(); -+ team.setPlayerPrefix(io.papermc.paper.adventure.PaperAdventure.asVanilla(prefix)); -+ } -+ @Override -+ public net.kyori.adventure.text.Component suffix() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPlayerSuffix()); -+ } -+ @Override -+ public void suffix(net.kyori.adventure.text.Component suffix) throws IllegalStateException, IllegalArgumentException { -+ if (suffix == null) suffix = net.kyori.adventure.text.Component.empty(); -+ CraftScoreboard scoreboard = checkState(); -+ team.setPlayerSuffix(io.papermc.paper.adventure.PaperAdventure.asVanilla(suffix)); -+ } -+ @Override -+ public net.kyori.adventure.text.format.TextColor color() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ if (team.getColor().getHexValue() == null) throw new IllegalStateException("Team colors must have hex values"); -+ net.kyori.adventure.text.format.TextColor color = net.kyori.adventure.text.format.TextColor.color(team.getColor().getHexValue()); -+ if (!(color instanceof net.kyori.adventure.text.format.NamedTextColor)) throw new IllegalStateException("Team doesn't have a NamedTextColor"); -+ return (net.kyori.adventure.text.format.NamedTextColor) color; -+ } -+ @Override -+ public void color(net.kyori.adventure.text.format.NamedTextColor color) { -+ if (color == null) color = net.kyori.adventure.text.format.NamedTextColor.WHITE; -+ CraftScoreboard scoreboard = checkState(); -+ team.setColor(io.papermc.paper.adventure.PaperAdventure.asVanilla(color)); -+ } -+ // Paper end - - @Override - public String getDisplayName() throws IllegalStateException { -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -index 35e6ce5f33b3d6b86c3654e6a207e26aa44badb5..b27af66795d902a2e95d692fa0ff18eccbef8a75 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -@@ -290,6 +290,7 @@ public final class CraftChatMessage { - - public static String fromComponent(Component component) { - if (component == null) return ""; -+ if (component instanceof io.papermc.paper.adventure.AdventureComponent) component = ((io.papermc.paper.adventure.AdventureComponent) component).deepConverted(); - StringBuilder out = new StringBuilder(); - - 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 ef7715774fbdc4c42b217d8192784e09a43fe66f..2d4faef5a2b9c4fe8b65ff4f1346b8375e0e02c8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -57,6 +57,33 @@ public final class CraftMagicNumbers implements UnsafeValues { - - private CraftMagicNumbers() {} - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener() { -+ return io.papermc.paper.adventure.PaperAdventure.FLATTENER; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.COLOR_DOWNSAMPLING_GSON; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.GSON; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.PLAIN; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC; -+ } -+ // Paper end -+ - public static BlockState getBlock(MaterialData material) { - return getBlock(material.getItemType(), material.getData()); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java -index f194cf2663919ea18309a0501ddfab5e2ed639dd..4b110d6c6f22ff7c2fa0fd4b459820797066199d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java -@@ -80,7 +80,7 @@ public abstract class LazyHashSet implements Set { - return this.reference = makeReference(); - } - -- abstract Set makeReference(); -+ protected abstract Set makeReference(); // Paper - protected - - public boolean isLazy() { - return reference == null; -diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java -index 103c1407b2946e9cae2271646178e5f243c8abb1..b22b7603f3f66e1b64f413106e7989b30475110b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java -@@ -15,10 +15,15 @@ public class LazyPlayerSet extends LazyHashSet { - } - - @Override -- HashSet makeReference() { -+ protected HashSet makeReference() { // Paper - protected - if (reference != null) { - throw new IllegalStateException("Reference already created!"); - } -+ // Paper start -+ return makePlayerSet(this.server); -+ } -+ public static HashSet makePlayerSet(final MinecraftServer server) { -+ // Paper end - List players = server.getPlayerList().players; - HashSet reference = new HashSet(players.size()); - for (ServerPlayer player : players) { diff --git a/Remapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch b/Remapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch deleted file mode 100644 index 2bef4fada9..0000000000 --- a/Remapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 13:02:51 -0600 -Subject: [PATCH] Configurable cactus bamboo and reed growth heights - -Bamboo - Both the minimum fully-grown heights and the maximum are configurable -- Machine_Maker - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b31109d2dadd29e8852468c19265066b773d2be0..3618cc017feb60e257a28f67cbddca3f792a9833 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -65,4 +65,17 @@ public class PaperWorldConfig { - config.addDefault("world-settings.default." + path, def); - return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); - } -+ -+ public int cactusMaxHeight; -+ public int reedMaxHeight; -+ public int bambooMaxHeight; -+ public int bambooMinHeight; -+ private void blockGrowthHeight() { -+ cactusMaxHeight = getInt("max-growth-height.cactus", 3); -+ reedMaxHeight = getInt("max-growth-height.reeds", 3); -+ bambooMaxHeight = getInt("max-growth-height.bamboo.max", 16); -+ bambooMinHeight = getInt("max-growth-height.bamboo.min", 11); -+ log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); -+ -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BambooBlock.java b/src/main/java/net/minecraft/world/level/block/BambooBlock.java -index 8f423ae6261434a670bb94aa70b6bc1694f1fc45..36583c189aa5e55de7f5eba362285e57c8279176 100644 ---- a/src/main/java/net/minecraft/world/level/block/BambooBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/BambooBlock.java -@@ -124,7 +124,7 @@ public class BambooBlock extends Block implements BonemealableBlock { - if (random.nextInt(Math.max(1, (int) (100.0F / world.spigotConfig.bambooModifier) * 3)) == 0 && world.isEmptyBlock(pos.above()) && world.getRawBrightness(pos.above(), 0) >= 9) { // Spigot - int i = this.getHeightBelowUpToMax(world, pos) + 1; - -- if (i < 16) { -+ if (i < world.paperConfig.bambooMaxHeight) { // Paper - this.growBamboo(state, (Level) world, pos, random, i); - } - } -@@ -155,7 +155,7 @@ public class BambooBlock extends Block implements BonemealableBlock { - int i = this.getHeightAboveUpToMax(world, pos); - int j = this.getHeightBelowUpToMax(world, pos); - -- return i + j + 1 < 16 && (Integer) world.getBlockState(pos.above(i)).getValue(BambooBlock.STAGE) != 1; -+ return i + j + 1 < ((Level) world).paperConfig.bambooMaxHeight && (Integer) world.getBlockState(pos.above(i)).getValue(BambooBlock.STAGE) != 1; // Paper - } - - @Override -@@ -174,7 +174,7 @@ public class BambooBlock extends Block implements BonemealableBlock { - BlockPos blockposition1 = pos.above(i); - BlockState iblockdata1 = world.getBlockState(blockposition1); - -- if (k >= 16 || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here -+ if (k >= world.paperConfig.bambooMaxHeight || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here // Paper - Configurable cactus bamboo and reed growth heights - return; - } - -@@ -215,7 +215,7 @@ public class BambooBlock extends Block implements BonemealableBlock { - } - - int j = (Integer) state.getValue(BambooBlock.AGE) != 1 && !iblockdata2.is(Blocks.BAMBOO) ? 0 : 1; -- int k = (height < 11 || random.nextFloat() >= 0.25F) && height != 15 ? 0 : 1; -+ int k = (height < world.paperConfig.bambooMinHeight || random.nextFloat() >= 0.25F) && height != (world.paperConfig.bambooMaxHeight - 1) ? 0 : 1; // Paper - - // CraftBukkit start - if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, pos.above(), (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(BambooBlock.AGE, j)).setValue(BambooBlock.LEAVES, blockpropertybamboosize)).setValue(BambooBlock.STAGE, k), 3)) { -@@ -230,7 +230,7 @@ public class BambooBlock extends Block implements BonemealableBlock { - protected int getHeightAboveUpToMax(BlockGetter world, BlockPos pos) { - int i; - -- for (i = 0; i < 16 && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { -+ for (i = 0; i < ((Level) world).paperConfig.bambooMaxHeight && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper - ; - } - -@@ -240,7 +240,7 @@ public class BambooBlock extends Block implements BonemealableBlock { - protected int getHeightBelowUpToMax(BlockGetter world, BlockPos pos) { - int i; - -- for (i = 0; i < 16 && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { -+ for (i = 0; i < ((Level) world).paperConfig.bambooMaxHeight && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper - ; - } - -diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java -index d07fd9c1f726b1d45992352408499034c12683e6..de61393e3f702554817d81ff10693ec3fb63d492 100644 ---- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java -@@ -54,7 +54,7 @@ public class CactusBlock extends Block { - ; - } - -- if (i < 3) { -+ if (i < world.paperConfig.cactusMaxHeight) { // Paper - Configurable growth height - int j = (Integer) state.getValue(CactusBlock.AGE); - - if (j >= (byte) range(3, ((100.0F / world.spigotConfig.cactusModifier) * 15) + 0.5F, 15)) { // Spigot -diff --git a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java -index 25f634ee93fa4678eaf09694d98783f2aef9d0f0..a795732af122204b88a01311e73892658132da25 100644 ---- a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java -@@ -51,7 +51,7 @@ public class SugarCaneBlock extends Block { - ; - } - -- if (i < 3) { -+ if (i < world.paperConfig.reedMaxHeight) { // Paper - Configurable growth height - int j = (Integer) state.getValue(SugarCaneBlock.AGE); - - if (j >= (byte) range(3, ((100.0F / world.spigotConfig.caneModifier) * 15) + 0.5F, 15)) { // Spigot diff --git a/Remapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch b/Remapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch deleted file mode 100644 index 1b143bb4a0..0000000000 --- a/Remapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 13:09:16 -0600 -Subject: [PATCH] Configurable baby zombie movement speed - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3618cc017feb60e257a28f67cbddca3f792a9833..796c17e0941922a9716212c6eae91643d8360418 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -78,4 +78,15 @@ public class PaperWorldConfig { - log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); - - } -+ -+ public double babyZombieMovementModifier; -+ private void babyZombieMovementModifier() { -+ babyZombieMovementModifier = getDouble("baby-zombie-movement-modifier", 0.5D); -+ if (PaperConfig.version < 20) { -+ babyZombieMovementModifier = getDouble("baby-zombie-movement-speed", 0.5D); -+ set("baby-zombie-movement-modifier", babyZombieMovementModifier); -+ } -+ -+ log("Baby zombies will move at the speed of " + babyZombieMovementModifier); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 992c9646c274350b30c1abb75e0469adc471397f..94e2a8f74e74d68d4a9b82b667fbff24b7e9e629 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -79,7 +79,7 @@ import org.bukkit.event.entity.EntityTransformEvent; - public class Zombie extends Monster { - - private static final UUID SPEED_MODIFIER_BABY_UUID = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836"); -- private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); -+ private final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); private final AttributeModifier babyModifier = this.SPEED_MODIFIER_BABY; // Paper - remove static - Make baby speed configurable - private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); - private static final EntityDataAccessor DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT); - public static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); -@@ -182,9 +182,9 @@ public class Zombie extends Monster { - if (this.level != null && !this.level.isClientSide) { - AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); - -- attributemodifiable.removeModifier(Zombie.SPEED_MODIFIER_BABY); -+ attributemodifiable.removeModifier(this.babyModifier); // Paper - if (baby) { -- attributemodifiable.addTransientModifier(Zombie.SPEED_MODIFIER_BABY); -+ attributemodifiable.addTransientModifier(this.babyModifier); // Paper - } - } - diff --git a/Remapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch b/Remapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch deleted file mode 100644 index 33edff1ef7..0000000000 --- a/Remapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 13:14:11 -0600 -Subject: [PATCH] Configurable fishing time ranges - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 796c17e0941922a9716212c6eae91643d8360418..78948c42b13194005bdbbbc69c2b7ae0732a78c5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -89,4 +89,12 @@ public class PaperWorldConfig { - - log("Baby zombies will move at the speed of " + babyZombieMovementModifier); - } -+ -+ public int fishingMinTicks; -+ public int fishingMaxTicks; -+ private void fishingTickRange() { -+ fishingMinTicks = getInt("fishing-time-range.MinimumTicks", 100); -+ fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); -+ log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -index d74dae6d7bd78c082b39a4e38da640a57c40b341..2f67c2065ef29f17f12190b25bd1ea53e1fb55b4 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -@@ -82,6 +82,10 @@ public class FishingHook extends Projectile { - owner.fishing = this; - this.luck = Math.max(0, lureLevel); - this.lureSpeed = Math.max(0, luckOfTheSeaLevel); -+ // Paper start -+ minWaitTime = world.paperConfig.fishingMinTicks; -+ maxWaitTime = world.paperConfig.fishingMaxTicks; -+ // paper end - } - - public FishingHook(net.minecraft.world.entity.player.Player thrower, Level world, int lureLevel, int luckOfTheSeaLevel) { diff --git a/Remapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/Remapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch deleted file mode 100644 index 6f5fd676df..0000000000 --- a/Remapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 13:24:16 -0600 -Subject: [PATCH] Allow nerfed mobs to jump and take water damage - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 78948c42b13194005bdbbbc69c2b7ae0732a78c5..b41e7922dd96c3358eb849ab39982a75736e3476 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -97,4 +97,9 @@ public class PaperWorldConfig { - fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); - log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); - } -+ -+ public boolean nerfedMobsShouldJump; -+ private void nerfedMobsShouldJump() { -+ nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 2a7f587e19fcdd6d01b360d6b47d9eadd9df92cc..584e83441a9fef88eb1b0a29bec8bda29d6a0c9c 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1104,6 +1104,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.isInWater() || this.isInRain(); - } - -+ public final boolean isInWaterOrRainOrBubble() { return isInWaterRainOrBubble(); } // Paper - OBFHELPER - public boolean isInWaterRainOrBubble() { - return this.isInWater() || this.isInRain() || this.isInBubbleColumn(); - } -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 99cb4dc1a1009d4a29e651c94d21babcc61388ed..151ebcffc1f2ae02fa55ab83d2ae7d8a0057f29d 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.entity; - -+import PathfinderGoalFloat; - import com.google.common.collect.Maps; - import java.util.Arrays; - import java.util.Iterator; -@@ -96,6 +97,7 @@ public abstract class Mob extends LivingEntity { - private final BodyRotationControl bodyRotationControl; - protected PathNavigation navigation; - public GoalSelector goalSelector; -+ @Nullable public PathfinderGoalFloat goalFloat; // Paper - public GoalSelector targetSelector; - private LivingEntity target; - private final Sensing sensing; -@@ -782,7 +784,17 @@ public abstract class Mob extends LivingEntity { - @Override - protected final void serverAiStep() { - ++this.noActionTime; -- if (!this.aware) return; // CraftBukkit -+ if (!this.aware) { // Paper start - Allow nerfed mobs to jump, float and take water damage -+ if (goalFloat != null) { -+ if (goalFloat.validConditions()) goalFloat.update(); -+ this.getJumpControl().jumpIfSet(); -+ } -+ if ((this instanceof EntityBlaze || this instanceof EntityEnderman) && isInWaterOrRainOrBubble()) { -+ hurt(DamageSource.DROWN, 1.0F); -+ } -+ return; -+ } -+ // Paper end - this.level.getProfiler().push("sensing"); - this.sensing.tick(); - this.level.getProfiler().pop(); -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java b/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java -index 5f7ad2b57d8d8f0f6a7d880f55e08b52f017cf51..09d1cda50ce9076e9236d124aa7766a26a50dae1 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/JumpControl.java -@@ -15,6 +15,7 @@ public class JumpControl { - this.jump = true; - } - -+ public final void jumpIfSet() { this.tick(); } // Paper - OBFHELPER - public void tick() { - this.mob.setJumping(this.jump); - this.jump = false; -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java -index 7ea5cb5a92ff3b66859ebcd53031aa06689bd329..790b5646683247ef757095a0763dc52701afe97b 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java -@@ -11,15 +11,18 @@ public class FloatGoal extends Goal { - - public FloatGoal(Mob mob) { - this.mob = mob; -+ if (mob.getCommandSenderWorld().paperConfig.nerfedMobsShouldJump) mob.goalFloat = this; // Paper - this.setFlags(EnumSet.of(Goal.Flag.JUMP)); - mob.getNavigation().setCanFloat(true); - } - -+ public final boolean validConditions() { return this.canUse(); } // Paper - OBFHELPER - @Override - public boolean canUse() { - return this.mob.isInWater() && this.mob.getFluidHeight((Tag) FluidTags.WATER) > this.mob.getFluidJumpThreshold() || this.mob.isInLava(); - } - -+ public void update() { this.tick(); } // Paper - OBFHELPER - @Override - public void tick() { - if (this.mob.getRandom().nextFloat() < 0.8F) { diff --git a/Remapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch b/Remapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch deleted file mode 100644 index 4a3d5d60ea..0000000000 --- a/Remapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Suddenly -Date: Tue, 1 Mar 2016 13:51:54 -0600 -Subject: [PATCH] Add configurable despawn distances for living entities - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b41e7922dd96c3358eb849ab39982a75736e3476..2f0d582baf0eb2bb477944d0cb1369db6ca33956 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -102,4 +102,20 @@ public class PaperWorldConfig { - private void nerfedMobsShouldJump() { - nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); - } -+ -+ public int softDespawnDistance; -+ public int hardDespawnDistance; -+ private void despawnDistances() { -+ softDespawnDistance = getInt("despawn-ranges.soft", 32); // 32^2 = 1024, Minecraft Default -+ hardDespawnDistance = getInt("despawn-ranges.hard", 128); // 128^2 = 16384, Minecraft Default -+ -+ if (softDespawnDistance > hardDespawnDistance) { -+ softDespawnDistance = hardDespawnDistance; -+ } -+ -+ log("Living Entity Despawn Ranges: Soft: " + softDespawnDistance + " Hard: " + hardDespawnDistance); -+ -+ softDespawnDistance = softDespawnDistance*softDespawnDistance; -+ hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 151ebcffc1f2ae02fa55ab83d2ae7d8a0057f29d..4d3000067ae3d46b7ed4dda6146a21993199c6d9 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -762,16 +762,16 @@ public abstract class Mob extends LivingEntity { - int i = this.getType().getCategory().getDespawnDistance(); - int j = i * i; - -- if (d0 > (double) j) { // CraftBukkit - remove isTypeNotPersistent() check -+ if (d0 > (double) level.paperConfig.hardDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances - this.remove(); - } - - int k = this.getType().getCategory().getNoDespawnDistance(); - int l = k * k; - -- if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > (double) l) { // CraftBukkit - remove isTypeNotPersistent() check -+ if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > level.paperConfig.softDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances - this.remove(); -- } else if (d0 < (double) l) { -+ } else if (d0 < level.paperConfig.softDespawnDistance) { // Paper - custom despawn distances - this.noActionTime = 0; - } - } diff --git a/Remapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch b/Remapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch deleted file mode 100644 index 91cd6d02b8..0000000000 --- a/Remapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 3 Mar 2016 03:53:43 -0600 -Subject: [PATCH] Allow for toggling of spawn chunks - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2f0d582baf0eb2bb477944d0cb1369db6ca33956..89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -118,4 +118,10 @@ public class PaperWorldConfig { - softDespawnDistance = softDespawnDistance*softDespawnDistance; - hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; - } -+ -+ public boolean keepSpawnInMemory; -+ private void keepSpawnInMemory() { -+ keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); -+ log("Keep spawn chunk loaded: " + keepSpawnInMemory); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index c153df1f4dea3dc0ae744bde01e334b3bd3b50af..832abf73bdab2488c5814ea6e57888aac1b26154 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -217,6 +217,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - }); - // CraftBukkit end - timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings -+ this.keepSpawnInMemory = this.paperConfig.keepSpawnInMemory; // Paper - this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } diff --git a/Remapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch b/Remapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch deleted file mode 100644 index 91e53448a3..0000000000 --- a/Remapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Tue, 1 Mar 2016 14:14:15 -0600 -Subject: [PATCH] Drop falling block and tnt entities at the specified height - -* Dec 2, 2020 Added tnt nerf for tnt minecarts - Machine_Maker - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75..d16ae924bcbe31c964f7fb448757c748e5c4418c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -124,4 +124,14 @@ public class PaperWorldConfig { - keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); - log("Keep spawn chunk loaded: " + keepSpawnInMemory); - } -+ -+ public int fallingBlockHeightNerf; -+ public int entityTNTHeightNerf; -+ private void heightNerfs() { -+ fallingBlockHeightNerf = getInt("falling-block-height-nerf", 0); -+ entityTNTHeightNerf = getInt("tnt-entity-height-nerf", 0); -+ -+ if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); -+ if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 584e83441a9fef88eb1b0a29bec8bda29d6a0c9c..706417f44c1eebc7cc5e8e7053fa0ab21f4caeba 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1849,6 +1849,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.spawnAtLocation(stack, 0.0F); - } - -+ @Nullable public final ItemEntity dropItem(ItemStack itemstack, float offset) { return this.spawnAtLocation(itemstack, offset); } // Paper - OBFHELPER - @Nullable - public ItemEntity spawnAtLocation(ItemStack stack, float yOffset) { - if (stack.isEmpty()) { -diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -index 8a9e2316b9f5756503dc06e27981525d2cd7d1a5..5394bc6336cb84025c1c748fb5b3d38e0648a590 100644 ---- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -122,6 +122,17 @@ public class FallingBlockEntity extends Entity { - } - - this.move(MoverType.SELF, this.getDeltaMovement()); -+ -+ // Paper start - Configurable EntityFallingBlock height nerf -+ if (this.level.paperConfig.fallingBlockHeightNerf != 0 && this.getY() > this.level.paperConfig.fallingBlockHeightNerf) { -+ if (this.dropItem && this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { -+ this.spawnAtLocation(block); -+ } -+ -+ this.remove(); -+ return; -+ } -+ // Paper end - if (!this.level.isClientSide) { - blockposition = this.blockPosition(); - boolean flag = this.blockState.getBlock() instanceof ConcretePowderBlock; -diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -index ff15a372b7cad5fa88b7ef6de1f3441d93f9c67e..4c4262b8f0cb44b8cea8cb46194a6e70d4ce56f4 100644 ---- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -@@ -69,6 +69,12 @@ public class PrimedTnt extends Entity { - } - - this.move(MoverType.SELF, this.getDeltaMovement()); -+ // Paper start - Configurable TNT entity height nerf -+ if (this.level.paperConfig.entityTNTHeightNerf != 0 && this.getY() > this.level.paperConfig.entityTNTHeightNerf) { -+ this.remove(); -+ return; -+ } -+ // Paper end - this.setDeltaMovement(this.getDeltaMovement().scale(0.98D)); - if (this.onGround) { - this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D)); -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java -index c2ed3ba42d29a50386c94b109fdd3b2f2f1b433b..3b5e96f2325e14a94de0fb2d6da86812cecc7395 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java -@@ -47,6 +47,12 @@ public class MinecartTNT extends AbstractMinecart { - public void tick() { - super.tick(); - if (this.fuse > 0) { -+ // Paper start - Configurable TNT entity height nerf -+ if (this.level.paperConfig.entityTNTHeightNerf != 0 && this.getY() > this.level.paperConfig.entityTNTHeightNerf) { -+ this.remove(); -+ return; -+ } -+ // Paper end - --this.fuse; - this.level.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D); - } else if (this.fuse == 0) { diff --git a/Remapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/Remapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch deleted file mode 100644 index e00adead2f..0000000000 --- a/Remapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 14:32:43 -0600 -Subject: [PATCH] Show 'Paper' in client crashes, server lists, and Mojang - stats - - -diff --git a/src/main/java/net/minecraft/server/Eula.java b/src/main/java/net/minecraft/server/Eula.java -index 6934b0fdfe11ef673a3e4ae7564d04acee169252..9f104b1bd05d9f344579f086b2b9c00af1750690 100644 ---- a/src/main/java/net/minecraft/server/Eula.java -+++ b/src/main/java/net/minecraft/server/Eula.java -@@ -72,7 +72,7 @@ public class Eula { - Properties properties = new Properties(); - - properties.setProperty("eula", "false"); -- properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula)."); -+ properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\nYou also agree that tacos are tasty, and the best food in the world."); // Paper - fix lag; - } catch (Throwable throwable1) { - throwable = throwable1; - throw throwable1; -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index a456b9cbf0e5eea4e888e0e3d07ed17558650371..fa29790600021809f31092a90e1a3a9b84d5e0c4 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1340,7 +1340,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop // CraftBukkit - cb > vanilla! -+ return "Paper"; //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! - } - - public CrashReport fillReport(CrashReport report) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f7f5457d20586e0ba72368e64ff6025f6755e61e..f81def94a1a7ab3a24b74a8bbd5f3e8ebae2c0d5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -224,7 +224,7 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; - import net.md_5.bungee.api.chat.BaseComponent; // Spigot - - public final class CraftServer implements Server { -- private final String serverName = "CraftBukkit"; -+ private final String serverName = "Paper"; // Paper - private final String serverVersion; - private final String bukkitVersion = Versioning.getBukkitVersion(); - private final Logger logger = Logger.getLogger("Minecraft"); -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index ce9f10f890a5866ab6208c7253b15b09fe323a81..e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -206,12 +206,25 @@ public class Main { - deadline.add(Calendar.DAY_OF_YEAR, -28); - 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 ***"); -+ System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper - System.err.println("*** Server will start in 20 seconds ***"); - Thread.sleep(TimeUnit.SECONDS.toMillis(20)); - } - } - -+ // Paper start - Log Java and OS versioning to help with debugging plugin issues -+ java.lang.management.RuntimeMXBean runtimeMX = java.lang.management.ManagementFactory.getRuntimeMXBean(); -+ java.lang.management.OperatingSystemMXBean osMX = java.lang.management.ManagementFactory.getOperatingSystemMXBean(); -+ if (runtimeMX != null && osMX != null) { -+ String javaInfo = "Java " + runtimeMX.getSpecVersion() + " (" + runtimeMX.getVmName() + " " + runtimeMX.getVmVersion() + ")"; -+ String osInfo = "Host: " + osMX.getName() + " " + osMX.getVersion() + " (" + osMX.getArch() + ")"; -+ -+ System.out.println("System Info: " + javaInfo + " " + osInfo); -+ } else { -+ System.out.println("Unable to read system info"); -+ } -+ // Paper end -+ - System.out.println("Loading libraries, please wait..."); - net.minecraft.server.Main.main(options); - } catch (Throwable t) { -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 9a695b80ef57d677fbdee1bfc59f0f9125a7ebd4..21d7b483920841456707fe3f08b180c1f072b7f7 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -19,7 +19,7 @@ public class WatchdogThread extends Thread - - private WatchdogThread(long timeoutTime, boolean restart) - { -- super( "Spigot Watchdog Thread" ); -+ super( "Paper Watchdog Thread" ); - this.timeoutTime = timeoutTime; - this.restart = restart; - } -@@ -65,14 +65,14 @@ public class WatchdogThread extends Thread - { - Logger log = Bukkit.getServer().getLogger(); - log.log( Level.SEVERE, "------------------------------" ); -- log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Spigot bug." ); -+ log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper - log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); - log.log( Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring" ); - log.log( Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once" ); - log.log( Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes" ); -- log.log( Level.SEVERE, "If you are unsure or still think this is a Spigot bug, please report to https://www.spigotmc.org/" ); -+ log.log( Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues" ); - log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); -- log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() ); -+ log.log( Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion() ); - // - if ( net.minecraft.world.level.Level.lastPhysicsProblem != null ) - { -@@ -82,7 +82,7 @@ public class WatchdogThread extends Thread - } - // - log.log( Level.SEVERE, "------------------------------" ); -- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" ); -+ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // diff --git a/Remapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch b/Remapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch deleted file mode 100644 index 66c45ee1f0..0000000000 --- a/Remapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 27 May 2019 03:40:05 -0500 -Subject: [PATCH] Implement Paper VersionChecker - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -new file mode 100644 -index 0000000000000000000000000000000000000000..1a1b50e475b9ede544b2f6d0d36632b24b68898c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -@@ -0,0 +1,122 @@ -+package com.destroystokyo.paper; -+ -+import com.destroystokyo.paper.util.VersionFetcher; -+import com.google.common.base.Charsets; -+import com.google.common.io.Resources; -+import com.google.gson.*; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.format.NamedTextColor; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.io.*; -+import java.net.HttpURLConnection; -+import java.net.URL; -+import java.util.stream.StreamSupport; -+ -+public class PaperVersionFetcher implements VersionFetcher { -+ private static final java.util.regex.Pattern VER_PATTERN = java.util.regex.Pattern.compile("^([0-9\\.]*)\\-.*R"); // R is an anchor, will always give '-R' at end -+ private static final String GITHUB_BRANCH_NAME = "master"; -+ private static @Nullable String mcVer; -+ -+ @Override -+ public long getCacheTime() { -+ return 720000; -+ } -+ -+ @Nonnull -+ @Override -+ public Component getVersionMessage(@Nonnull String serverVersion) { -+ String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); -+ return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); -+ } -+ -+ private static @Nullable String getMinecraftVersion() { -+ if (mcVer == null) { -+ java.util.regex.Matcher matcher = VER_PATTERN.matcher(org.bukkit.Bukkit.getBukkitVersion()); -+ if (matcher.find()) { -+ String result = matcher.group(); -+ mcVer = result.substring(0, result.length() - 2); // strip 'R' anchor and trailing '-' -+ } else { -+ org.bukkit.Bukkit.getLogger().warning("Unable to match version to pattern! Report to PaperMC!"); -+ org.bukkit.Bukkit.getLogger().warning("Pattern: " + VER_PATTERN.toString()); -+ org.bukkit.Bukkit.getLogger().warning("Version: " + org.bukkit.Bukkit.getBukkitVersion()); -+ } -+ } -+ -+ return mcVer; -+ } -+ -+ private static Component getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) { -+ int distance; -+ try { -+ int jenkinsBuild = Integer.parseInt(versionInfo); -+ distance = fetchDistanceFromSiteApi(jenkinsBuild, getMinecraftVersion()); -+ } catch (NumberFormatException ignored) { -+ versionInfo = versionInfo.replace("\"", ""); -+ distance = fetchDistanceFromGitHub(repo, branch, versionInfo); -+ } -+ -+ switch (distance) { -+ case -1: -+ return Component.text("Error obtaining version information", NamedTextColor.YELLOW); -+ case 0: -+ return Component.text("You are running the latest version", NamedTextColor.GREEN); -+ case -2: -+ return Component.text("Unknown version", NamedTextColor.YELLOW); -+ default: -+ return Component.text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW); -+ } -+ } -+ -+ private static int fetchDistanceFromSiteApi(int jenkinsBuild, @Nullable String siteApiVersion) { -+ if (siteApiVersion == null) { return -1; } -+ try { -+ try (BufferedReader reader = Resources.asCharSource( -+ new URL("https://papermc.io/api/v2/projects/paper/versions/" + siteApiVersion), -+ Charsets.UTF_8 -+ ).openBufferedStream()) { -+ JsonObject json = new Gson().fromJson(reader, JsonObject.class); -+ JsonArray builds = json.getAsJsonArray("builds"); -+ int latest = StreamSupport.stream(builds.spliterator(), false) -+ .mapToInt(e -> e.getAsInt()) -+ .max() -+ .getAsInt(); -+ return latest - jenkinsBuild; -+ } catch (JsonSyntaxException ex) { -+ ex.printStackTrace(); -+ return -1; -+ } -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return -1; -+ } -+ } -+ -+ // Contributed by Techcable in GH-65 -+ private static int fetchDistanceFromGitHub(@Nonnull String repo, @Nonnull String branch, @Nonnull String hash) { -+ try { -+ HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + repo + "/compare/" + branch + "..." + hash).openConnection(); -+ connection.connect(); -+ if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return -2; // Unknown commit -+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) { -+ JsonObject obj = new Gson().fromJson(reader, JsonObject.class); -+ String status = obj.get("status").getAsString(); -+ switch (status) { -+ case "identical": -+ return 0; -+ case "behind": -+ return obj.get("behind_by").getAsInt(); -+ default: -+ return -1; -+ } -+ } catch (JsonSyntaxException | NumberFormatException e) { -+ e.printStackTrace(); -+ return -1; -+ } -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return -1; -+ } -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 2d4faef5a2b9c4fe8b65ff4f1346b8375e0e02c8..21052d0e88351b075733331d71e07b086354b820 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -368,6 +368,11 @@ public final class CraftMagicNumbers implements UnsafeValues { - public String getTimingsServerName() { - return com.destroystokyo.paper.PaperConfig.timingsServerName; - } -+ -+ @Override -+ public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { -+ return new com.destroystokyo.paper.PaperVersionFetcher(); -+ } - // Paper end - - /** diff --git a/Remapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch b/Remapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch deleted file mode 100644 index 4985c3e747..0000000000 --- a/Remapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Thu, 1 Mar 2018 19:37:52 -0600 -Subject: [PATCH] Add version history to version command - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -index 1a1b50e475b9ede544b2f6d0d36632b24b68898c..580bae0d414d371a07a6bfeefc41fdd989dc0083 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -@@ -5,7 +5,9 @@ import com.google.common.base.Charsets; - import com.google.common.io.Resources; - import com.google.gson.*; - import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextComponent; - import net.kyori.adventure.text.format.NamedTextColor; -+import net.kyori.adventure.text.format.TextDecoration; - - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -@@ -28,7 +30,10 @@ public class PaperVersionFetcher implements VersionFetcher { - @Override - public Component getVersionMessage(@Nonnull String serverVersion) { - String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); -- return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); -+ final Component updateMessage = getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); -+ final Component history = getHistory(); -+ -+ return history != null ? TextComponent.ofChildren(updateMessage, Component.newline(), history) : updateMessage; - } - - private static @Nullable String getMinecraftVersion() { -@@ -119,4 +124,19 @@ public class PaperVersionFetcher implements VersionFetcher { - return -1; - } - } -+ -+ @Nullable -+ private Component getHistory() { -+ final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); -+ if (data == null) { -+ return null; -+ } -+ -+ final String oldVersion = data.getOldVersion(); -+ if (oldVersion == null) { -+ return null; -+ } -+ -+ return Component.text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..aac3f66cb23d260729c2a48d8710a9de2346aa22 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java -@@ -0,0 +1,145 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.MoreObjects; -+import com.google.gson.Gson; -+import com.google.gson.JsonSyntaxException; -+import java.io.BufferedReader; -+import java.io.BufferedWriter; -+import java.io.IOException; -+import java.nio.charset.StandardCharsets; -+import java.nio.file.Files; -+import java.nio.file.Path; -+import java.nio.file.Paths; -+import java.nio.file.StandardOpenOption; -+import java.util.Objects; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+import org.bukkit.Bukkit; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+ -+public enum VersionHistoryManager { -+ INSTANCE; -+ -+ private final Gson gson = new Gson(); -+ -+ private final Logger logger = Bukkit.getLogger(); -+ -+ private VersionData currentData = null; -+ -+ VersionHistoryManager() { -+ final Path path = Paths.get("version_history.json"); -+ -+ if (Files.exists(path)) { -+ // Basic file santiy checks -+ if (!Files.isRegularFile(path)) { -+ if (Files.isDirectory(path)) { -+ logger.severe(path + " is a directory, cannot be used for version history"); -+ } else { -+ logger.severe(path + " is not a regular file, cannot be used for version history"); -+ } -+ // We can't continue -+ return; -+ } -+ -+ try (final BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { -+ currentData = gson.fromJson(reader, VersionData.class); -+ } catch (final IOException e) { -+ logger.log(Level.SEVERE, "Failed to read version history file '" + path + "'", e); -+ return; -+ } catch (final JsonSyntaxException e) { -+ logger.log(Level.SEVERE, "Invalid json syntax for file '" + path + "'", e); -+ return; -+ } -+ -+ final String version = Bukkit.getVersion(); -+ if (version == null) { -+ logger.severe("Failed to retrieve current version"); -+ return; -+ } -+ -+ if (!version.equals(currentData.getCurrentVersion())) { -+ // The version appears to have changed -+ currentData.setOldVersion(currentData.getCurrentVersion()); -+ currentData.setCurrentVersion(version); -+ writeFile(path); -+ } -+ } else { -+ // File doesn't exist, start fresh -+ currentData = new VersionData(); -+ // oldVersion is null -+ currentData.setCurrentVersion(Bukkit.getVersion()); -+ writeFile(path); -+ } -+ } -+ -+ private void writeFile(@Nonnull final Path path) { -+ try (final BufferedWriter writer = Files.newBufferedWriter( -+ path, -+ StandardCharsets.UTF_8, -+ StandardOpenOption.WRITE, -+ StandardOpenOption.CREATE, -+ StandardOpenOption.TRUNCATE_EXISTING -+ )) { -+ gson.toJson(currentData, writer); -+ } catch (final IOException e) { -+ logger.log(Level.SEVERE, "Failed to write to version history file", e); -+ } -+ } -+ -+ @Nullable -+ public VersionData getVersionData() { -+ return currentData; -+ } -+ -+ public static class VersionData { -+ private String oldVersion; -+ -+ private String currentVersion; -+ -+ @Nullable -+ public String getOldVersion() { -+ return oldVersion; -+ } -+ -+ public void setOldVersion(@Nullable String oldVersion) { -+ this.oldVersion = oldVersion; -+ } -+ -+ @Nullable -+ public String getCurrentVersion() { -+ return currentVersion; -+ } -+ -+ public void setCurrentVersion(@Nullable String currentVersion) { -+ this.currentVersion = currentVersion; -+ } -+ -+ @Override -+ public String toString() { -+ return MoreObjects.toStringHelper(this) -+ .add("oldVersion", oldVersion) -+ .add("currentVersion", currentVersion) -+ .toString(); -+ } -+ -+ @Override -+ public boolean equals(@Nullable Object o) { -+ if (this == o) { -+ return true; -+ } -+ if (o == null || getClass() != o.getClass()) { -+ return false; -+ } -+ final VersionData versionData = (VersionData) o; -+ return Objects.equals(oldVersion, versionData.oldVersion) && -+ Objects.equals(currentVersion, versionData.currentVersion); -+ } -+ -+ @Override -+ public int hashCode() { -+ return Objects.hash(oldVersion, currentVersion); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 40fe03c844c8bf6a9c4c5ae028b259f01a81eead..c7655883262f122b373ac30a33ddb4c06cd9aebe 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -193,6 +193,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - return false; - } - com.destroystokyo.paper.PaperConfig.registerCommands(); -+ com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now - // Paper end - - this.setPvpAllowed(dedicatedserverproperties.pvp); diff --git a/Remapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch b/Remapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch deleted file mode 100644 index 08d7ac1c4a..0000000000 --- a/Remapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Tue, 1 Mar 2016 14:47:52 -0600 -Subject: [PATCH] Player affects spawning API - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 706417f44c1eebc7cc5e8e7053fa0ab21f4caeba..392f2f2d67b688d5b37f77c8e4b3036348472d77 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1353,6 +1353,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return Mth.sqrt(f * f + f1 * f1 + f2 * f2); - } - -+ public double getDistanceSquared(double x, double y, double z) { return distanceToSqr(x, y, z); } // Paper - OBFHELPER - public double distanceToSqr(double x, double y, double z) { - double d3 = this.getX() - x; - double d4 = this.getY() - y; -diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index f8c13881f59ccaccf8d8e5496d2f8f49ba7d7343..a3bad391a719363077740aa810c9412df34b4ae5 100644 ---- a/src/main/java/net/minecraft/world/entity/EntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -29,6 +29,12 @@ public final class EntitySelector { - return !entity.isSpectator(); - }; - -+ // Paper start -+ public static final Predicate affectsSpawning = (entity) -> { -+ return !entity.isSpectator() && entity.isAlive() && (entity instanceof EntityPlayer) && ((EntityPlayer) entity).affectsSpawning; -+ }; -+ // Paper end -+ - public static Predicate withinDistance(double x, double y, double z, double d3) { - double d4 = d3 * d3; - -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 4d3000067ae3d46b7ed4dda6146a21993199c6d9..09d39b73e8a3987e58a502bd914a6451b807421b 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -755,7 +755,7 @@ public abstract class Mob extends LivingEntity { - if (this.level.getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) { - this.remove(); - } else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) { -- Player entityhuman = this.level.getNearestPlayer(this, -1.0D); -+ Player entityhuman = this.level.findNearbyPlayer(this, -1.0D, EntitySelector.affectsSpawning); // Paper - - if (entityhuman != null) { - double d0 = entityhuman.distanceToSqr((Entity) this); // CraftBukkit - decompile error -diff --git a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java -index 4ce9e37d7334ba0557c397c0ebd2cb7928c7c564..cfdbaec1de6add7a189c26eb66701dfa5f40fe4f 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java -@@ -122,7 +122,7 @@ public class Silverfish extends Monster { - if (checkAnyLightMonsterSpawnRules(type, world, spawnReason, pos, random)) { - Player entityhuman = world.getNearestPlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0D, true); - -- return entityhuman == null; -+ return !(entityhuman != null && !entityhuman.affectsSpawning) && entityhuman == null; // Paper - Affects Spawning API - } else { - return 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 91f605c803c021c8743de87b67dcb0fb9fc807e9..3b451e75a7f49ea6b543aee9f0a51c0be3c4dfba 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -161,6 +161,9 @@ public abstract class Player extends LivingEntity { - private final ItemCooldowns cooldowns; - @Nullable - public FishingHook fishing; -+ // Paper start -+ public boolean affectsSpawning = true; -+ // Paper end - - // CraftBukkit start - public boolean fauxSleeping; -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 98f85d59bc48451ef6381a47fe341f77b9920981..10058d3c3565382faa893b79119c5caf845bf29a 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -66,7 +66,7 @@ public abstract class BaseSpawner { - private boolean isNearPlayer() { - BlockPos blockposition = this.getPos(); - -- return this.getLevel().hasNearbyAlivePlayer((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); -+ return this.getLevel().isAffectsSpawningPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper - } - - public void tick() { -diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index 7e7a58b9a9ececdcc37fc33b33703428eb1d5faf..66681b9f0e2531d3da25629e44180417b32b4d66 100644 ---- a/src/main/java/net/minecraft/world/level/EntityGetter.java -+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -92,8 +92,9 @@ public interface EntityGetter { - } - } - -- @Nullable -- default Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate targetPredicate) { -+ default Player findNearbyPlayer(Entity entity, double d0, @Nullable Predicate predicate) { return this.findNearbyPlayer(entity.getX(), entity.getY(), entity.getZ(), d0, predicate); } // Paper -+ @Nullable default Player findNearbyPlayer(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { return getNearestPlayer(d0, d1, d2, d3, predicate); } // Paper - OBFHELPER -+ @Nullable default Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate targetPredicate) { // Paper - double d4 = -1.0D; - Player entityhuman = null; - Iterator iterator = this.players().iterator(); -@@ -126,6 +127,27 @@ public interface EntityGetter { - return this.getNearestPlayer(x, y, z, maxDistance, predicate); - } - -+ // Paper end -+ default boolean isAffectsSpawningPlayerNearby(double d0, double d1, double d2, double d3) { -+ Iterator iterator = this.players().iterator(); -+ double d4; -+ do { -+ Player entityhuman; -+ do { -+ if (!iterator.hasNext()) { -+ return false; -+ } -+ -+ entityhuman = (Player) iterator.next(); -+ } while (!EntitySelector.affectsSpawning.test(entityhuman)); -+ -+ d4 = entityhuman.getDistanceSquared(d0, d1, d2); -+ } while (d3 >= 0.0D && d4 >= d3 * d3); -+ -+ return true; -+ } -+ // Paper end -+ - default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) { - Iterator iterator = this.players().iterator(); - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 50d11611702e3d1f0e980fb8f2280b05b891167b..e6c39c822c6a910f63e9b4899d53b7d75e1b77cf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1768,8 +1768,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - @Override - public String getLocale() { - return getHandle().locale; -+ -+ } -+ -+ // Paper start -+ public void setAffectsSpawning(boolean affects) { -+ this.getHandle().affectsSpawning = affects; - } - -+ @Override -+ public boolean getAffectsSpawning() { -+ return this.getHandle().affectsSpawning; -+ } -+ // Paper end -+ - @Override - public void updateCommands() { - if (getHandle().connection == null) return; diff --git a/Remapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch b/Remapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch deleted file mode 100644 index 23323c9803..0000000000 --- a/Remapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Tue, 1 Mar 2016 15:08:03 -0600 -Subject: [PATCH] Remove invalid mob spawner tile entities - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index f30793b81dfd9018b4879d655c7c18a9f9c25267..300749822d52f9f973e71c6ec9c8bf29d6a6938e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -41,7 +41,9 @@ import net.minecraft.world.level.TickList; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.EntityBlock; -+import net.minecraft.world.level.block.SpawnerBlock; - import net.minecraft.world.level.block.entity.BlockEntity; -+import net.minecraft.world.level.block.entity.SpawnerBlockEntity; - import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.level.levelgen.DebugLevelSource; - import net.minecraft.world.level.levelgen.Heightmap; -@@ -647,6 +649,10 @@ public class LevelChunk implements ChunkAccess { - } - - // CraftBukkit start -+ // Paper start - Remove invalid mob spawner tile entities -+ } else if (blockEntity instanceof SpawnerBlockEntity && !(getBlockData(pos.getX(), pos.getY(), pos.getZ()).getBlock() instanceof SpawnerBlock)) { -+ this.blockEntities.remove(pos); -+ // Paper end - } else { - System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() - + " (" + getBlockState(pos) + ") where there was no entity tile!"); diff --git a/Remapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch b/Remapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch deleted file mode 100644 index db2d2e1d05..0000000000 --- a/Remapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch +++ /dev/null @@ -1,279 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 8 Mar 2015 22:55:25 -0600 -Subject: [PATCH] Optimize TileEntity Ticking - - -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index 94adf0275a2e7093c152cc3b8b0a5747b3a13a86..5bcf9cefc29eb20e2cfbfb49e2b2662ec394a87e 100644 ---- a/src/main/java/co/aikar/timings/TimingsExport.java -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -112,7 +112,7 @@ public class TimingsExport extends Thread { - pair("end", System.currentTimeMillis() / 1000), - pair("online-mode", Bukkit.getServer().getOnlineMode()), - pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), -- pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedIds(), pack -> { -+ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedPacks(), pack -> { - // Don't feel like obf helper'ing these, non fatal if its temp missed. - return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); - })) -@@ -151,8 +151,8 @@ public class TimingsExport extends Thread { - ); - - parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getAllLevels(), world -> { -- if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; -- return pair(world.getWorldData().getName(), createObject( -+ if (world.getWorld().getName().equals("worldeditregentempworld")) return null; -+ return pair(world.getWorld().getName(), createObject( - pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { - return pair(rule, world.getWorld().getGameRuleValue(rule)); - })), -diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java -index 56656bf34db07bc717ace8ae9c1b60f9bfd7ff05..1bda9a158eb4372b9ab7cf3097732e64810aefc6 100644 ---- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java -@@ -54,8 +54,8 @@ import net.minecraft.world.phys.shapes.VoxelShape; - public class ChestBlock extends AbstractChestBlock implements SimpleWaterloggedBlock { - - public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; -- public static final EnumProperty TYPE = BlockStateProperties.CHEST_TYPE; -- public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; -+ public static final EnumProperty TYPE = BlockStateProperties.CHEST_TYPE; public static final EnumProperty CHEST_TYPE_PROPERTY = TYPE; // Paper - OBFHELPER -+ public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; public static final BooleanProperty waterlogged() { return WATERLOGGED; } // Paper OBFHELPER - protected static final VoxelShape NORTH_AABB = Block.box(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D); - protected static final VoxelShape SOUTH_AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D); - protected static final VoxelShape WEST_AABB = Block.box(0.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java -index 7b08ee35d2d8dc3fe783d773bf6686a5197006b8..17289d28b6d0023279a573715ee3d182988dd651 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java -@@ -8,6 +8,7 @@ import net.minecraft.core.NonNullList; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundEvent; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; -@@ -32,7 +33,7 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity; - import org.bukkit.entity.HumanEntity; - // CraftBukkit end - --public class ChestBlockEntity extends RandomizableContainerBlockEntity implements TickableBlockEntity { -+public class ChestBlockEntity extends RandomizableContainerBlockEntity { // Paper - Remove ITickable - - private NonNullList items; - protected float openness; -@@ -110,14 +111,20 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement - return tag; - } - -- @Override - public void tick() { - int i = this.worldPosition.getX(); - int j = this.worldPosition.getY(); - int k = this.worldPosition.getZ(); - - ++this.tickInterval; -- this.openCount = getOpenCount(this.level, this, this.tickInterval, i, j, k, this.openCount); -+ } -+ -+ public void doOpenLogic() { -+ int i = this.worldPosition.getX(); -+ int j = this.worldPosition.getY(); -+ int k = this.worldPosition.getZ(); -+ -+ //this.viewingCount = a(this.world, this, this.j, i, j, k, this.viewingCount); // Paper - check is faulty given our logic is called before active container set - this.oOpenness = this.openness; - float f = 0.1F; - -@@ -131,25 +138,31 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement - if (this.openCount > 0 && this.openness == 0.0F) { - this.playSound(SoundEvents.CHEST_OPEN); - } -+ } - -- if (this.openCount == 0 && this.openness > 0.0F || this.openCount > 0 && this.openness < 1.0F) { -- float f1 = this.openness; -+ public void doCloseLogic() { -+ if (this.openCount == 0 /* && this.a > 0.0F || this.viewingCount > 0 && this.a < 1.0F */) { // Paper - disable all but player count check -+ /* // Paper - disable animation stuff -+ float f1 = this.a; - -- if (this.openCount > 0) { -- this.openness += 0.1F; -+ if (this.viewingCount > 0) { -+ this.a += 0.1F; - } else { -- this.openness -= 0.1F; -+ this.a -= 0.1F; - } - -- if (this.openness > 1.0F) { -- this.openness = 1.0F; -+ if (this.a > 1.0F) { -+ this.a = 1.0F; - } - - float f2 = 0.5F; - -- if (this.openness < 0.5F && f1 >= 0.5F) { -+ if (this.a < 0.5F && f1 >= 0.5F) { -+ */ -+ MCUtil.scheduleTask(10, () -> { - this.playSound(SoundEvents.CHEST_CLOSE); -- } -+ }, "Chest Sounds"); -+ //} // Paper end - - if (this.openness < 0.0F) { - this.openness = 0.0F; -@@ -188,6 +201,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement - } - - public void playSound(SoundEvent soundeffect) { -+ if (!this.getBlockState().contains(ChestBlock.CHEST_TYPE_PROPERTY)) { return; } // Paper - this can be delayed, double check exists - Fixes GH-2074 - ChestType blockpropertychesttype = (ChestType) this.getBlockState().getValue(ChestBlock.TYPE); - - if (blockpropertychesttype != ChestType.LEFT) { -@@ -226,6 +240,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement - - ++this.openCount; - if (this.level == null) return; // CraftBukkit -+ doOpenLogic(); // Paper - - // CraftBukkit start - Call redstone event - if (this.getBlockState().getBlock() == Blocks.TRAPPED_CHEST) { -@@ -248,6 +263,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement - --this.openCount; - - // CraftBukkit start - Call redstone event -+ doCloseLogic(); // Paper - if (this.getBlockState().getBlock() == Blocks.TRAPPED_CHEST) { - int newPower = Math.max(0, Math.min(15, this.openCount)); - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java -index b26337770e13c20f57a4e74282710ce697ac0d41..8f0477d9620ef71e10855bbca07f9b6984d5d794 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java -@@ -1,11 +1,12 @@ - package net.minecraft.world.level.block.entity; - -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.level.block.Blocks; - --public class EnderChestBlockEntity extends BlockEntity implements TickableBlockEntity { -+public class EnderChestBlockEntity extends BlockEntity { // Paper - Remove ITickable - - public float openness; - public float oOpenness; -@@ -16,18 +17,28 @@ public class EnderChestBlockEntity extends BlockEntity implements TickableBlockE - super(BlockEntityType.ENDER_CHEST); - } - -- @Override - public void tick() { - if (++this.tickInterval % 20 * 4 == 0) { - this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); - } - - this.oOpenness = this.openness; -+ /* // Paper -+ int i = this.position.getX(); -+ int j = this.position.getY(); -+ int k = this.position.getZ(); -+ float f = 0.1F; -+ double d0; -+ // Paper start -+ */ -+ } -+ -+ private void doOpenLogic() { - int i = this.worldPosition.getX(); - int j = this.worldPosition.getY(); - int k = this.worldPosition.getZ(); -- float f = 0.1F; - double d0; -+ // Paper end - - if (this.openCount > 0 && this.openness == 0.0F) { - double d1 = (double) i + 0.5D; -@@ -35,28 +46,40 @@ public class EnderChestBlockEntity extends BlockEntity implements TickableBlockE - d0 = (double) k + 0.5D; - this.level.playSound((Player) null, d1, (double) j + 0.5D, d0, SoundEvents.ENDER_CHEST_OPEN, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); - } -+ // Paper start -+ } - -- if (this.openCount == 0 && this.openness > 0.0F || this.openCount > 0 && this.openness < 1.0F) { -- float f1 = this.openness; -+ private void doCloseLogic() { -+ int i = this.worldPosition.getX(); -+ int j = this.worldPosition.getY(); -+ int k = this.worldPosition.getZ(); -+ double d0; -+ -+ if (this.openCount == 0) { /* && this.a > 0.0F || this.c > 0 && this.a < 1.0F) { -+ // Paper end -+ float f1 = this.a; - -- if (this.openCount > 0) { -- this.openness += 0.1F; -+ if (this.c > 0) { -+ this.a += 0.1F; - } else { -- this.openness -= 0.1F; -+ this.a -= 0.1F; - } - -- if (this.openness > 1.0F) { -- this.openness = 1.0F; -+ if (this.a > 1.0F) { -+ this.a = 1.0F; - } - - float f2 = 0.5F; - -- if (this.openness < 0.5F && f1 >= 0.5F) { -+ if (this.a < 0.5F && f1 >= 0.5F) { -+ // Paper start -+ */ - d0 = (double) i + 0.5D; - double d2 = (double) k + 0.5D; - -+ MCUtil.scheduleTask(10, () -> { - this.level.playSound((Player) null, d0, (double) j + 0.5D, d2, SoundEvents.ENDER_CHEST_CLOSE, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); -- } -+ }, "Chest Sounds"); - - if (this.openness < 0.0F) { - this.openness = 0.0F; -@@ -84,11 +107,13 @@ public class EnderChestBlockEntity extends BlockEntity implements TickableBlockE - public void startOpen() { - ++this.openCount; - this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); -+ doOpenLogic(); // Paper - } - - public void stopOpen() { - --this.openCount; - this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); -+ doCloseLogic(); // Paper - } - - public boolean stillValid(Player entityhuman) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java -index 60ce75c7f94c995d3753c40bc8d1ec09b4d37b1a..ac10fb9cd4701f0f6477a86bec73cb5ac6496725 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java -+++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java -@@ -84,6 +84,7 @@ public abstract class StateHolder { - return Collections.unmodifiableCollection(this.values.keySet()); - } - -+ public > boolean contains(Property iblockstate) { return this.hasProperty(iblockstate); } // Paper - OBFHELPER - public > boolean hasProperty(Property property) { - return this.values.containsKey(property); - } diff --git a/Remapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch b/Remapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch deleted file mode 100644 index ee0ab66ab5..0000000000 --- a/Remapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch +++ /dev/null @@ -1,208 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 Mar 2016 23:09:29 -0600 -Subject: [PATCH] Further improve server tick loop - -Improves how the catchup buffer is handled, allowing it to roll both ways -increasing the effeciency of the thread sleep so it only will sleep once. - -Also increases the buffer of the catchup to ensure server stays at 20 TPS unless extreme conditions - -Previous implementation did not calculate TPS correctly. -Switch to a realistic rolling average and factor in std deviation as an extra reporting variable - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index fa29790600021809f31092a90e1a3a9b84d5e0c4..526d6c0fa45bfba92a3f964f72e4965fd5c841c1 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -251,7 +251,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; - public Commands vanillaCommandDispatcher; -@@ -260,7 +260,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 5000L && this.nextTickTime - this.lastOverloadWarning >= 30000L) { // CraftBukkit - long j = i / 50L; - - if (server.getWarnOnOverload()) // CraftBukkit -- MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); -+ MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); - this.nextTickTime += j * 50L; - this.lastOverloadWarning = this.nextTickTime; - } - -- if ( tickCount++ % SAMPLE_INTERVAL == 0 ) -+ if ( ++MinecraftServer.currentTick % SAMPLE_INTERVAL == 0 ) - { -- double currentTps = 1E3 / ( curTime - tickSection ) * SAMPLE_INTERVAL; -- recentTps[0] = calcTps( recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min) -- recentTps[1] = calcTps( recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min) -- recentTps[2] = calcTps( recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min) -+ final long diff = curTime - tickSection; -+ java.math.BigDecimal currentTps = TPS_BASE.divide(new java.math.BigDecimal(diff), 30, java.math.RoundingMode.HALF_UP); -+ tps1.add(currentTps, diff); -+ tps5.add(currentTps, diff); -+ tps15.add(currentTps, diff); -+ // Backwards compat with bad plugins -+ recentTps[0] = tps1.getAverage(); -+ recentTps[1] = tps5.getAverage(); -+ recentTps[2] = tps15.getAverage(); -+ // Paper end - tickSection = curTime; - } - // Spigot end - -- MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit -+ //MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit // Paper - don't overwrite current tick time -+ lastTick = curTime; - this.nextTickTime += 50L; - SingleTickProfiler gameprofilertick = SingleTickProfiler.createTickProfiler("Server"); - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f81def94a1a7ab3a24b74a8bbd5f3e8ebae2c0d5..6fa31ca31128b1094eebd5f848c5b506dfeedeeb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2121,6 +2121,17 @@ public final class CraftServer implements Server { - return CraftMagicNumbers.INSTANCE; - } - -+ // Paper - Add getTPS API - Further improve tick loop -+ @Override -+ public double[] getTPS() { -+ return new double[] { -+ net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(), -+ net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(), -+ net.minecraft.server.MinecraftServer.getServer().tps15.getAverage() -+ }; -+ } -+ // Paper end -+ - // Spigot start - private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() - { -diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java -index f5b6dec1cbe7501ce2ee9125920e810bc94670cc..e62890433ffbe0b4e48942fe6c38b599a19e58fd 100644 ---- a/src/main/java/org/spigotmc/TicksPerSecondCommand.java -+++ b/src/main/java/org/spigotmc/TicksPerSecondCommand.java -@@ -24,22 +24,30 @@ public class TicksPerSecondCommand extends Command - return true; - } - -- StringBuilder sb = new StringBuilder( ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " ); -- for ( double tps : MinecraftServer.getServer().recentTps ) -- { -- sb.append( format( tps ) ); -- sb.append( ", " ); -+ // Paper start - Further improve tick handling -+ double[] tps = org.bukkit.Bukkit.getTPS(); -+ String[] tpsAvg = new String[tps.length]; -+ -+ for ( int i = 0; i < tps.length; i++) { -+ tpsAvg[i] = format( tps[i] ); -+ } -+ sender.sendMessage(ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " + org.apache.commons.lang.StringUtils.join(tpsAvg, ", ")); -+ if (args.length > 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) { -+ sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); -+ if (!hasShownMemoryWarning) { -+ sender.sendMessage(ChatColor.RED + "Warning: " + ChatColor.GOLD + " Memory usage on modern garbage collectors is not a stable value and it is perfectly normal to see it reach max. Please do not pay it much attention."); -+ hasShownMemoryWarning = true; -+ } - } -- sender.sendMessage( sb.substring( 0, sb.length() - 2 ) ); -- sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " -- + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); -+ // Paper end - - return true; - } - -- private String format(double tps) -+ private boolean hasShownMemoryWarning; // Paper -+ private static String format(double tps) // Paper - Made static - { - return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString() -- + ( ( tps > 20.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); -+ + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise - } - } diff --git a/Remapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch b/Remapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch deleted file mode 100644 index b310cdcaa1..0000000000 --- a/Remapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 23:12:03 -0600 -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 e6c39c822c6a910f63e9b4899d53b7d75e1b77cf..2920ba3d8eeb62670897ea19b50aaf395ab84c5a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1437,12 +1437,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public void setFlying(boolean value) { -+ boolean needsUpdate = getHandle().abilities.flying != value; // Paper - Only refresh abilities if needed - if (!getAllowFlight() && value) { - throw new IllegalArgumentException("Cannot make player fly if getAllowFlight() is false"); - } - - getHandle().abilities.flying = value; -- getHandle().onUpdateAbilities(); -+ if (needsUpdate) getHandle().onUpdateAbilities(); // Paper - Only refresh abilities if needed - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch b/Remapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch deleted file mode 100644 index cc2e7adc4a..0000000000 --- a/Remapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Tue, 1 Mar 2016 23:45:08 -0600 -Subject: [PATCH] Entity Origin API - - -diff --git a/src/main/java/net/minecraft/nbt/ListTag.java b/src/main/java/net/minecraft/nbt/ListTag.java -index 084340dc73acb3d972e0717b48da820c027a5137..7927ebac41eb1f257738238500cfe0c06031fcaf 100644 ---- a/src/main/java/net/minecraft/nbt/ListTag.java -+++ b/src/main/java/net/minecraft/nbt/ListTag.java -@@ -190,6 +190,7 @@ public class ListTag extends CollectionTag { - return new int[0]; - } - -+ public final double getDoubleAt(int i) { return this.getDouble(i); } // Paper - OBFHELPER - public double getDouble(int index) { - if (index >= 0 && index < this.list.size()) { - Tag nbtbase = (Tag) this.list.get(index); -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 0cc86ca4ea4a2e1b5acc3c0507397eef85dec0c1..d2bb9385fbc21cdef6cef06680fac685d3da3570 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1240,6 +1240,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.navigations.add(((Mob) entity).getNavigation()); - } - entity.valid = true; // CraftBukkit -+ // Paper start - Set origin location when the entity is being added to the world -+ if (entity.origin == null) { -+ entity.origin = entity.getBukkitEntity().getLocation(); -+ } -+ // Paper end - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 392f2f2d67b688d5b37f77c8e4b3036348472d77..fd5b41ceb97dc8aa975f1c0ae05b58d0b09f2cd6 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -246,6 +246,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only - public boolean forceExplosionKnockback; // SPIGOT-949 - public boolean persistentInvisibility = false; -+ public org.bukkit.Location origin; // Paper - // Spigot start - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; -@@ -1624,6 +1625,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.bukkitEntity.storeBukkitValues(tag); - } - // CraftBukkit end -+ // Paper start - Save the entity's origin location -+ if (this.origin != null) { -+ tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); -+ tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); -+ } -+ // Paper end - return tag; - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); -@@ -1746,6 +1753,17 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - // CraftBukkit end - -+ // Paper start - Restore the entity's origin location -+ ListTag originTag = tag.getList("Paper.Origin", 6); -+ if (!originTag.isEmpty()) { -+ org.bukkit.World originWorld = level.getWorld(); -+ if (tag.contains("Paper.OriginWorld")) { -+ originWorld = Bukkit.getWorld(tag.getUUID("Paper.OriginWorld")); -+ } -+ origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); -+ } -+ // Paper end -+ - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); - CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded"); -@@ -1807,6 +1825,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - - protected abstract void addAdditionalSaveData(CompoundTag tag); - -+ protected final ListTag createList(double... adouble) { return newDoubleList(adouble); } // Paper - OBFHELPER - protected ListTag newDoubleList(double... values) { - ListTag nbttaglist = new ListTag(); - double[] adouble1 = values; -diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -index 5394bc6336cb84025c1c748fb5b3d38e0648a590..1d87717cc9002ea202ee2ca614aaa8a4c7ea3cb2 100644 ---- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -291,6 +291,14 @@ public class FallingBlockEntity extends Entity { - this.blockState = Blocks.SAND.defaultBlockState(); - } - -+ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility -+ if (tag.contains("SourceLoc_x")) { -+ int srcX = tag.getInt("SourceLoc_x"); -+ int srcY = tag.getInt("SourceLoc_y"); -+ int srcZ = tag.getInt("SourceLoc_z"); -+ origin = new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ); -+ } -+ // Paper end - } - - public void setHurtsEntities(boolean hurtEntities) { -diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -index 4c4262b8f0cb44b8cea8cb46194a6e70d4ce56f4..661848084fd986321ef782317934dac19ed4dce3 100644 ---- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -@@ -119,6 +119,14 @@ public class PrimedTnt extends Entity { - @Override - protected void readAdditionalSaveData(CompoundTag tag) { - this.setFuse(tag.getShort("Fuse")); -+ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility -+ if (tag.contains("SourceLoc_x")) { -+ int srcX = tag.getInt("SourceLoc_x"); -+ int srcY = tag.getInt("SourceLoc_y"); -+ int srcZ = tag.getInt("SourceLoc_z"); -+ origin = new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ); -+ } -+ // Paper end - } - - @Nullable -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 53c231925ef1b17e48c5863570e3c54124874621..e7a59a8e0424a0839dfa73fc65f44c5b04bd3dec 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1062,4 +1062,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return spigot; - } - // Spigot end -+ -+ // Paper start -+ @Override -+ public Location getOrigin() { -+ Location origin = getHandle().origin; -+ return origin == null ? null : origin.clone(); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch b/Remapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch deleted file mode 100644 index cf3cf1beaa..0000000000 --- a/Remapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 Mar 2016 23:52:34 -0600 -Subject: [PATCH] Prevent tile entity and entity crashes - - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 832abf73bdab2488c5814ea6e57888aac1b26154..870843254d1c1fc49bc101a49cdf9d300ae3ca1b 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -737,11 +737,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - gameprofilerfiller.pop(); - } catch (Throwable throwable) { -- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking block entity"); -- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block entity being ticked"); -- -- tileentity.fillCrashReportCategory(crashreportsystemdetails); -- throw new ReportedException(crashreport); -+ // Paper start - Prevent tile entity and entity crashes -+ System.err.println("TileEntity threw exception at " + tileentity.level.getWorld().getName() + ":" + tileentity.worldPosition.getX() + "," + tileentity.worldPosition.getY() + "," + tileentity.worldPosition.getZ()); -+ throwable.printStackTrace(); -+ tilesThisCycle--; -+ this.tickableBlockEntities.remove(tileTickPosition--); -+ continue; -+ // Paper end - // Spigot start - } finally { - tileentity.tickTimer.stopTiming(); -@@ -806,11 +808,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - try { - tickConsumer.accept(entity); - } catch (Throwable throwable) { -- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); -- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); -- -- entity.fillCrashReportCategory(crashreportsystemdetails); -- throw new ReportedException(crashreport); -+ // Paper start - Prevent tile entity and entity crashes -+ System.err.println("Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ()); -+ throwable.printStackTrace(); -+ entity.removed = true; -+ return; -+ // Paper end - } - } - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index d445a1b7b7605eed66923789c5d8e2199c31c5ac..13115d1b28dfa2d87b45a50bd0feaa7f57769122 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -208,7 +208,12 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - return Registry.BLOCK_ENTITY_TYPE.getKey(this.getType()) + " // " + this.getClass().getCanonicalName(); - }); - if (this.level != null) { -- CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.worldPosition, this.getBlockState()); -+ // Paper start - Prevent TileEntity and Entity crashes -+ BlockState block = this.getBlockState(); -+ if (block != null) { -+ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.worldPosition, block); -+ } -+ // Paper end - CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.worldPosition, this.level.getBlockState(this.worldPosition)); - } - } diff --git a/Remapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch b/Remapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch deleted file mode 100644 index 805929cc33..0000000000 --- a/Remapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 23:58:50 -0600 -Subject: [PATCH] Configurable top of nether void damage - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index d16ae924bcbe31c964f7fb448757c748e5c4418c..4bba6977a0287837b8927718c040ac61463f0469 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -134,4 +134,19 @@ public class PaperWorldConfig { - if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); - if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); - } -+ -+ public int netherVoidTopDamageHeight; -+ public boolean doNetherTopVoidDamage() { return netherVoidTopDamageHeight > 0; } -+ private void netherVoidTopDamageHeight() { -+ netherVoidTopDamageHeight = getInt("nether-ceiling-void-damage-height", 0); -+ log("Top of the nether void damage height: " + netherVoidTopDamageHeight); -+ -+ if (PaperConfig.version < 18) { -+ boolean legacy = getBoolean("nether-ceiling-void-damage", false); -+ if (legacy) { -+ netherVoidTopDamageHeight = 128; -+ set("nether-ceiling-void-damage-height", netherVoidTopDamageHeight); -+ } -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index fd5b41ceb97dc8aa975f1c0ae05b58d0b09f2cd6..f3f48c268639937874dd39eea9bd8e119eebdce7 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -499,9 +499,16 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.fallDistance *= 0.5F; - } - -- if (this.getY() < -64.0D) { -- this.outOfWorld(); -+ // Paper start - Configurable nether ceiling damage -+ -+ // Extracted to own function -+ /* -+ if (this.locY() < -64.0D) { -+ this.an(); - } -+ */ -+ this.performVoidDamage(); -+ // Paper end - - if (!this.level.isClientSide) { - this.setSharedFlag(0, this.remainingFireTicks > 0); -@@ -594,6 +601,17 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.setRemainingFireTicks(0); - } - -+ // Paper start -+ protected void performVoidDamage() { -+ if (this.getY() < -64.0D || (this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER -+ && level.paperConfig.doNetherTopVoidDamage() -+ && this.getY() >= level.paperConfig.netherVoidTopDamageHeight)) { -+ this.doVoidDamage(); -+ } -+ } -+ // Paper end -+ -+ protected final void doVoidDamage() { this.outOfWorld(); } // Paper - OBFHELPER - protected void outOfWorld() { - this.remove(); - } -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -index 9503376895d90e8db0d4f7b164e2d813dd1a4a3a..7ba74b0a9319e29077b5afe3019a463ed3004813 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -@@ -329,9 +329,15 @@ public abstract class AbstractMinecart extends Entity { - this.setDamage(this.getDamage() - 1.0F); - } - -- if (this.getY() < -64.0D) { -- this.outOfWorld(); -+ // Paper start - Configurable nether ceiling damage -+ // Extracted to own function -+ /* -+ if (this.locY() < -64.0D) { -+ this.an(); - } -+ */ -+ this.performVoidDamage(); -+ // Paper end - - // this.doPortalTick(); // CraftBukkit - handled in postTick - if (this.level.isClientSide) { diff --git a/Remapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch b/Remapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch deleted file mode 100644 index 56a96d8cfe..0000000000 --- a/Remapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Mar 2016 00:03:55 -0600 -Subject: [PATCH] Check online mode before converting and renaming player data - - -diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java -index 067c5acd4aad346ac9ccf6d1b5aa6691b0ccd348..60fe01e824e4657d2601797d7858d5de339ab255 100644 ---- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java -+++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java -@@ -56,7 +56,7 @@ public class PlayerDataStorage { - File file = new File(this.playerDir, entityhuman.getStringUUID() + ".dat"); - // Spigot Start - boolean usingWrongFile = false; -- if ( !file.exists() ) -+ if ( org.bukkit.Bukkit.getOnlineMode() && !file.exists() ) // Paper - Check online mode first - { - file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + entityhuman.getScoreboardName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); - if ( file.exists() ) diff --git a/Remapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch b/Remapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch deleted file mode 100644 index 29eba4b28a..0000000000 --- a/Remapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Mar 2016 00:32:25 -0600 -Subject: [PATCH] Always tick falling blocks - - -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 9bb35ec64e1538aabec9ff7831706c4717239449..0a9bd85e0308e962df3b24a74bd5aac919744d6d 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -91,6 +91,7 @@ public class ActivationRange - || entity instanceof AbstractHurtingProjectile - || entity instanceof LightningBolt - || entity instanceof PrimedTnt -+ || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks - || entity instanceof EndCrystal - || entity instanceof FireworkRocketEntity - || entity instanceof ThrownTrident ) diff --git a/Remapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch b/Remapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch deleted file mode 100644 index 201a2e7284..0000000000 --- a/Remapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DoctorDark -Date: Wed, 16 Mar 2016 02:21:39 -0500 -Subject: [PATCH] Configurable end credits - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4bba6977a0287837b8927718c040ac61463f0469..e6e18f309dc09ea9416ea37dcc697ddc2b571a96 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -149,4 +149,10 @@ public class PaperWorldConfig { - } - } - } -+ -+ public boolean disableEndCredits; -+ private void disableEndCredits() { -+ disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); -+ log("End credits disabled: " + disableEndCredits); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index ca647b3afbe8da5847dc8fa890ae9ca5c18e03d9..f3797bd761c2c6782cce3fca25bc9ef37e5c4978 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -188,7 +188,7 @@ public class ServerPlayer extends Player implements ContainerListener { - private long lastActionTime = Util.getMillis(); - private Entity camera; - public boolean isChangingDimension; -- private boolean seenCredits; -+ private boolean seenCredits; private void setHasSeenCredits(boolean has) { this.seenCredits = has; } // Paper - OBFHELPER - private final ServerRecipeBook recipeBook = new ServerRecipeBook(); - private Vec3 levitationStartPos; - private int levitationStartTime; -@@ -893,6 +893,7 @@ public class ServerPlayer extends Player implements ContainerListener { - this.unRide(); - this.getLevel().removePlayerImmediately(this); - if (!this.wonGame) { -+ if (level.paperConfig.disableEndCredits) this.setHasSeenCredits(true); // Paper - Toggle to always disable end credits - this.wonGame = true; - this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.WIN_GAME, this.seenCredits ? 0.0F : 1.0F)); - this.seenCredits = true; diff --git a/Remapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch b/Remapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch deleted file mode 100644 index a9fb2be3bd..0000000000 --- a/Remapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Iceee -Date: Wed, 2 Mar 2016 01:39:52 -0600 -Subject: [PATCH] Fix lag from explosions processing dead entities - - -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 54c3bfead8497f64c183f5612676803d91fc557b..8d6cd2a5b16d99cb8e754ce04b2d12fee7ffb4d0 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -180,7 +180,7 @@ public class Explosion { - int i1 = Mth.floor(this.y + (double) f2 + 1.0D); - int j1 = Mth.floor(this.z - (double) f2 - 1.0D); - int k1 = Mth.floor(this.z + (double) f2 + 1.0D); -- List list = this.level.getEntities(this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1)); -+ List list = this.level.getEntities(this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1), (com.google.common.base.Predicate) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities - Vec3 vec3d = new Vec3(this.x, this.y, this.z); - - for (int l1 = 0; l1 < list.size(); ++l1) { diff --git a/Remapped-Spigot-Server-Patches/0033-Optimize-explosions.patch b/Remapped-Spigot-Server-Patches/0033-Optimize-explosions.patch deleted file mode 100644 index ec1e34fc38..0000000000 --- a/Remapped-Spigot-Server-Patches/0033-Optimize-explosions.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 11:59:48 -0600 -Subject: [PATCH] Optimize explosions - -The process of determining an entity's exposure from explosions can be -expensive when there are hundreds or more entities in range. - -This patch adds a per-tick cache that is used for storing and retrieving -an entity's exposure during an explosion. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e6e18f309dc09ea9416ea37dcc697ddc2b571a96..4881b03d470646843bad1bc343eb6a6ab9072d8e 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -155,4 +155,10 @@ public class PaperWorldConfig { - disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); - log("End credits disabled: " + disableEndCredits); - } -+ -+ public boolean optimizeExplosions; -+ private void optimizeExplosions() { -+ optimizeExplosions = getBoolean("optimize-explosions", false); -+ log("Optimize explosions: " + optimizeExplosions); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 526d6c0fa45bfba92a3f964f72e4965fd5c841c1..901d5497667706c049718dc4fca37a1bc489c465 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1324,6 +1324,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop>> 32)); -+ temp = Double.doubleToLongBits(posY); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(posZ); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(minX); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(minY); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(minZ); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(maxX); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(maxY); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(maxZ); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ return result; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 870843254d1c1fc49bc101a49cdf9d300ae3ca1b..f71b56fa079e2c7b2123061a8e1a7cb41935bab6 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -136,6 +136,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; - private int tileTickPosition; -+ public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions - - public CraftWorld getWorld() { - return this.world; diff --git a/Remapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch b/Remapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch deleted file mode 100644 index d9f4ff9678..0000000000 --- a/Remapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 14:48:03 -0600 -Subject: [PATCH] Disable explosion knockback - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4881b03d470646843bad1bc343eb6a6ab9072d8e..2222c1bb5f8625eee4d88946e4bfdfa2fe598977 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -161,4 +161,9 @@ public class PaperWorldConfig { - optimizeExplosions = getBoolean("optimize-explosions", false); - log("Optimize explosions: " + optimizeExplosions); - } -+ -+ public boolean disableExplosionKnockback; -+ private void disableExplosionKnockback(){ -+ disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index e5f8cee6726ea9a90c540bb10fd8594a35bb5e40..afd114e1ce00db72534d470fed12101bb237f266 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1280,6 +1280,7 @@ public abstract class LivingEntity extends Entity { - } - } - -+ boolean knockbackCancelled = level.paperConfig.disableExplosionKnockback && source.isExplosion() && this instanceof net.minecraft.world.entity.player.Player; // Paper - Disable explosion knockback - if (flag1) { - if (flag) { - this.level.broadcastEntityEvent(this, (byte) 29); -@@ -1298,6 +1299,7 @@ public abstract class LivingEntity extends Entity { - b0 = 2; - } - -+ if (!knockbackCancelled) // Paper - Disable explosion knockback - this.level.broadcastEntityEvent(this, b0); - } - -@@ -1321,6 +1323,7 @@ public abstract class LivingEntity extends Entity { - } - } - -+ if (knockbackCancelled) this.level.broadcastEntityEvent(this, (byte) 2); // Paper - Disable explosion knockback - if (this.isDeadOrDying()) { - if (!this.checkTotemDeathProtection(source)) { - SoundEvent soundeffect = this.getDeathSound(); -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index db46caaa5ad5f129d313c65c5006cb24853768be..45a75f7be308678336e192828becf6cf5c9047bc 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -215,14 +215,14 @@ public class Explosion { - double d14 = d13; - - if (entity instanceof LivingEntity) { -- d14 = ProtectionEnchantment.getExplosionKnockbackAfterDampener((LivingEntity) entity, d13); -+ d14 = entity instanceof Player && level.paperConfig.disableExplosionKnockback ? 0 : ProtectionEnchantment.getExplosionKnockbackAfterDampener((LivingEntity) entity, d13); // Paper - Disable explosion knockback - } - - entity.setDeltaMovement(entity.getDeltaMovement().add(d8 * d14, d9 * d14, d10 * d14)); - if (entity instanceof Player) { - Player entityhuman = (Player) entity; - -- if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.flying)) { -+ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.flying) && !level.paperConfig.disableExplosionKnockback) { // Paper - Disable explosion knockback - this.hitPlayers.put(entityhuman, new Vec3(d8 * d13, d9 * d13, d10 * d13)); - } - } diff --git a/Remapped-Spigot-Server-Patches/0035-Disable-thunder.patch b/Remapped-Spigot-Server-Patches/0035-Disable-thunder.patch deleted file mode 100644 index d5971380bb..0000000000 --- a/Remapped-Spigot-Server-Patches/0035-Disable-thunder.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 14:52:43 -0600 -Subject: [PATCH] Disable thunder - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2222c1bb5f8625eee4d88946e4bfdfa2fe598977..083e421f8496b5336af473b108498ed28b984774 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -166,4 +166,9 @@ public class PaperWorldConfig { - private void disableExplosionKnockback(){ - disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); - } -+ -+ public boolean disableThunder; -+ private void disableThunder() { -+ disableThunder = getBoolean("disable-thunder", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index d2bb9385fbc21cdef6cef06680fac685d3da3570..3fc8fb197400c63bc85f57ff484803659619f775 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -580,7 +580,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - gameprofilerfiller.push("thunder"); - BlockPos blockposition; - -- if (flag && this.isThundering() && this.random.nextInt(100000) == 0) { -+ if (!this.paperConfig.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder - blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); - if (this.isRainingAt(blockposition)) { - DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); diff --git a/Remapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch b/Remapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch deleted file mode 100644 index 9d2d87a6b0..0000000000 --- a/Remapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 14:57:24 -0600 -Subject: [PATCH] Disable ice and snow - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 083e421f8496b5336af473b108498ed28b984774..2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -171,4 +171,9 @@ public class PaperWorldConfig { - private void disableThunder() { - disableThunder = getBoolean("disable-thunder", false); - } -+ -+ public boolean disableIceAndSnow; -+ private void disableIceAndSnow(){ -+ disableIceAndSnow = getBoolean("disable-ice-and-snow", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 3fc8fb197400c63bc85f57ff484803659619f775..6c6098731752d61b5241710b075d4ffe3826daac 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -604,7 +604,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - gameprofilerfiller.popPush("iceandsnow"); -- if (this.random.nextInt(16) == 0) { -+ if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow - blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.getBlockRandomPos(j, 0, k, 15)); - BlockPos blockposition1 = blockposition.below(); - Biome biomebase = this.getBiome(blockposition); diff --git a/Remapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch b/Remapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch deleted file mode 100644 index 454050d2c3..0000000000 --- a/Remapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 15:03:53 -0600 -Subject: [PATCH] Configurable mob spawner tick rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2..4de86b09c6bc3c1974ce61b550ccb73d37f6f170 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -176,4 +176,9 @@ public class PaperWorldConfig { - private void disableIceAndSnow(){ - disableIceAndSnow = getBoolean("disable-ice-and-snow", false); - } -+ -+ public int mobSpawnerTickRate; -+ private void mobSpawnerTickRate() { -+ mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 10058d3c3565382faa893b79119c5caf845bf29a..ed631d5bfba5d2543e8eed017a7c484ad3ddb453 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -41,6 +41,7 @@ public abstract class BaseSpawner { - public int maxNearbyEntities = 6; - public int requiredPlayerRange = 16; - public int spawnRange = 4; -+ private int tickDelay = 0; // Paper - - public BaseSpawner() {} - -@@ -70,6 +71,10 @@ public abstract class BaseSpawner { - } - - public void tick() { -+ // Paper start - Configurable mob spawner tick rate -+ if (spawnDelay > 0 && --tickDelay > 0) return; -+ tickDelay = this.getLevel().paperConfig.mobSpawnerTickRate; -+ // Paper end - if (!this.isNearPlayer()) { - this.oSpin = this.spin; - } else { -@@ -84,18 +89,18 @@ public abstract class BaseSpawner { - world.addParticle(ParticleTypes.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); - world.addParticle(ParticleTypes.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D); - if (this.spawnDelay > 0) { -- --this.spawnDelay; -+ this.spawnDelay -= tickDelay; // Paper - } - - this.oSpin = this.spin; - this.spin = (this.spin + (double) (1000.0F / ((float) this.spawnDelay + 200.0F))) % 360.0D; - } else { -- if (this.spawnDelay == -1) { -+ if (this.spawnDelay < -tickDelay) { // Paper - this.delay(); - } - - if (this.spawnDelay > 0) { -- --this.spawnDelay; -+ this.spawnDelay -= tickDelay; // Paper - return; - } - diff --git a/Remapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch b/Remapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch deleted file mode 100644 index c77faa1999..0000000000 --- a/Remapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Wed, 2 Mar 2016 23:13:07 -0600 -Subject: [PATCH] Send absolute position the first time an entity is seen - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 59a5f82c9f57d760ba4959a040ce8cbf0f49e4aa..d1bc927c8b429f43de2cdad98f8b329ff4c8b4db 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1301,10 +1301,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private final Entity entity; - private final int range; - private SectionPos lastSectionPos; -- public final Set seenBy = Sets.newHashSet(); -+ // Paper start -+ // Replace trackedPlayers Set with a Map. The value is true until the player receives -+ // their first update (which is forced to have absolute coordinates), false afterward. -+ public java.util.Map trackedPlayerMap = new java.util.HashMap<>(); -+ public Set seenBy = trackedPlayerMap.keySet(); - - public TrackedEntity(Entity entity, int i, int j, boolean flag) { -- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, seenBy); // CraftBukkit -+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, trackedPlayerMap); // CraftBukkit // Paper - this.entity = entity; - this.range = i; - this.lastSectionPos = SectionPos.of(entity); -@@ -1386,7 +1390,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - player.entitiesToRemove.remove(Integer.valueOf(this.entity.getId())); - // CraftBukkit end - -- if (flag1 && this.seenBy.add(player)) { -+ if (flag1 && this.trackedPlayerMap.putIfAbsent(player, true) == null) { // Paper - this.serverEntity.addPairing(player); - } - } else if (this.seenBy.remove(player)) { -diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index 3d386627b6d3d33da76372e4a14d0c5000eb8ffc..fa6893055fa5617742bfb4b7eff60c8139395cb6 100644 ---- a/src/main/java/net/minecraft/server/level/ServerEntity.java -+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -4,6 +4,7 @@ import com.google.common.collect.Lists; - import com.mojang.datafixers.util.Pair; - import java.util.Collection; - import java.util.Collections; -+import java.util.HashSet; - import java.util.Iterator; - import java.util.List; - import java.util.Set; -@@ -51,7 +52,7 @@ public class ServerEntity { - private final Entity entity; - private final int updateInterval; - private final boolean trackDelta; -- private final Consumer> broadcast; -+ private final Consumer> broadcast; private Consumer> getPacketConsumer() { return broadcast; } // Paper - OBFHELPER - private long xp; - private long yp; - private long zp; -@@ -66,8 +67,23 @@ public class ServerEntity { - private boolean wasOnGround; - // CraftBukkit start - private final Set trackedPlayers; -+ // Paper start -+ private java.util.Map trackedPlayerMap = null; -+ -+ /** -+ * Requested in https://github.com/PaperMC/Paper/issues/1537 to allow intercepting packets -+ */ -+ public void sendPlayerPacket(ServerPlayer player, Packet packet) { -+ player.connection.send(packet); -+ } -+ -+ public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, java.util.Map trackedPlayers) { -+ this(worldserver, entity, i, flag, consumer, trackedPlayers.keySet()); -+ trackedPlayerMap = trackedPlayers; -+ } - - public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { -+ // Paper end - this.trackedPlayers = trackedPlayers; - // CraftBukkit end - this.ap = Vec3.ZERO; -@@ -188,7 +204,25 @@ public class ServerEntity { - } - - if (packet1 != null) { -- this.broadcast.accept(packet1); -+ // paper start -+ if (trackedPlayerMap == null || packet1 instanceof ClientboundTeleportEntityPacket) { -+ this.broadcast.accept((packet1)); -+ } else { -+ ClientboundTeleportEntityPacket teleportPacket = null; -+ -+ for (java.util.Map.Entry viewer : trackedPlayerMap.entrySet()) { -+ if (viewer.getValue()) { -+ viewer.setValue(false); -+ if (teleportPacket == null) { -+ teleportPacket = new ClientboundTeleportEntityPacket(this.entity); -+ } -+ sendPlayerPacket(viewer.getKey(), teleportPacket); -+ } else { -+ sendPlayerPacket(viewer.getKey(), packet1); -+ } -+ } -+ } -+ // Paper end - } - - this.sendDirtyEntityData(); diff --git a/Remapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch b/Remapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch deleted file mode 100644 index d61c3cadc2..0000000000 --- a/Remapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 23:30:53 -0600 -Subject: [PATCH] Add BeaconEffectEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -index c91f7bcfab2da6a23114a3cff63ca31dab443393..5f75c6d653a31f65fcf9c0e280d796e15d059c00 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -@@ -25,7 +25,6 @@ import net.minecraft.world.effect.MobEffect; - import net.minecraft.world.effect.MobEffectInstance; - import net.minecraft.world.effect.MobEffects; - import net.minecraft.world.entity.player.Inventory; --import net.minecraft.world.entity.player.Player; - import net.minecraft.world.inventory.AbstractContainerMenu; - import net.minecraft.world.inventory.BeaconMenu; - import net.minecraft.world.inventory.ContainerData; -@@ -41,6 +40,11 @@ import net.minecraft.world.phys.AABB; - import org.bukkit.craftbukkit.potion.CraftPotionUtil; - import org.bukkit.potion.PotionEffect; - // CraftBukkit end -+// Paper start -+import org.bukkit.craftbukkit.event.CraftEventFactory; -+import org.bukkit.entity.Player; -+import com.destroystokyo.paper.event.block.BeaconEffectEvent; -+// Paper end - - public class BeaconBlockEntity extends BlockEntity implements MenuProvider, TickableBlockEntity { - -@@ -260,21 +264,37 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - double d0 = (double) (this.levels * 10 + 10); - - AABB axisalignedbb = (new AABB(this.worldPosition)).inflate(d0).expandTowards(0.0D, (double) this.level.getMaxBuildHeight(), 0.0D); -- List list = this.level.getEntitiesOfClass(Player.class, axisalignedbb); -+ List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.player.Player.class, axisalignedbb); - - return list; - } - } - - private void applyEffect(List list, MobEffect effects, int i, int b0) { -+ // Paper - BeaconEffectEvent -+ applyEffect(list, effects, i, b0, true); -+ } -+ -+ private void applyEffect(List list, MobEffect effects, int i, int b0, boolean isPrimary) { -+ // Paper - BeaconEffectEvent - { - Iterator iterator = list.iterator(); - -- Player entityhuman; -+ net.minecraft.world.entity.player.Player entityhuman; -+ -+ // Paper start - BeaconEffectEvent -+ org.bukkit.block.Block block = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); -+ PotionEffect effect = CraftPotionUtil.toBukkit(new MobEffectInstance(effects, i, b0, true, true)); -+ // Paper end - - while (iterator.hasNext()) { -- entityhuman = (Player) iterator.next(); -- entityhuman.addEffect(new MobEffectInstance(effects, i, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); -+ entityhuman = (net.minecraft.world.entity.player.Player) iterator.next(); -+ -+ // Paper start - BeaconEffectEvent -+ BeaconEffectEvent event = new BeaconEffectEvent(block, effect, (Player) entityhuman.getBukkitEntity(), isPrimary); -+ if (CraftEventFactory.callEvent(event).isCancelled()) continue; -+ entityhuman.addEffect(new MobEffectInstance(CraftPotionUtil.fromBukkit(event.getEffect())), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); -+ // Paper end - } - } - } -@@ -297,10 +317,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - int i = getLevelCb(); - List list = getHumansInRange(); - -- applyEffect(list, this.primaryPower, i, b0); -+ applyEffect(list, this.primaryPower, i, b0, true); // Paper - BeaconEffectEvent - - if (hasSecondaryEffect()) { -- applyEffect(list, this.secondaryPower, i, 0); -+ applyEffect(list, this.secondaryPower, i, 0, false); // Paper - BeaconEffectEvent - } - } - -@@ -308,7 +328,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - // CraftBukkit end - - public void playSound(SoundEvent soundeffect) { -- this.level.playSound((Player) null, this.worldPosition, soundeffect, SoundSource.BLOCKS, 1.0F, 1.0F); -+ this.level.playSound((net.minecraft.world.entity.player.Player) null, this.worldPosition, soundeffect, SoundSource.BLOCKS, 1.0F, 1.0F); - } - - public int getLevels() { -@@ -368,7 +388,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - - @Nullable - @Override -- public AbstractContainerMenu createMenu(int syncId, Inventory inv, Player player) { -+ public AbstractContainerMenu createMenu(int syncId, Inventory inv, net.minecraft.world.entity.player.Player player) { - return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName()) ? new BeaconMenu(syncId, inv, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; - } - diff --git a/Remapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch b/Remapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch deleted file mode 100644 index 3344a83459..0000000000 --- a/Remapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 23:34:44 -0600 -Subject: [PATCH] Configurable container update tick rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4de86b09c6bc3c1974ce61b550ccb73d37f6f170..5a4c3a8c511f22c8c3240c9c7cd83a65119c1054 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -181,4 +181,9 @@ public class PaperWorldConfig { - private void mobSpawnerTickRate() { - mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); - } -+ -+ public int containerUpdateTickRate; -+ private void containerUpdateTickRate() { -+ containerUpdateTickRate = getInt("container-update-tick-rate", 1); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index f3797bd761c2c6782cce3fca25bc9ef37e5c4978..ffad931c72e52855a3f139354f5e85c460e2a80b 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -207,6 +207,7 @@ public class ServerPlayer extends Player implements ContainerListener { - public boolean ignoreSlotUpdateHack; - public int latency; - public boolean wonGame; -+ private int containerUpdateDelay; // Paper - - // CraftBukkit start - public String displayName; -@@ -531,7 +532,12 @@ public class ServerPlayer extends Player implements ContainerListener { - --this.invulnerableTime; - } - -- this.containerMenu.broadcastChanges(); -+ // Paper start - Configurable container update tick rate -+ if (--containerUpdateDelay <= 0) { -+ this.containerMenu.broadcastChanges(); -+ containerUpdateDelay = level.paperConfig.containerUpdateTickRate; -+ } -+ // Paper end - if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { - this.closeContainer(); - this.containerMenu = this.inventoryMenu; diff --git a/Remapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch b/Remapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch deleted file mode 100644 index 1c9a8dab7e..0000000000 --- a/Remapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Wed, 2 Mar 2016 23:42:37 -0600 -Subject: [PATCH] Use UserCache for player heads - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index 11baf6fd5f7e408a570d5a48ae6b2fc05cd7e243..313ddd6b64e395a8caab77b3da005e52006ab2d7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -@@ -166,7 +166,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - if (name == null) { - setProfile(null); - } else { -- setProfile(new GameProfile(null, name)); -+ // Paper start - Use Online Players Skull -+ GameProfile newProfile = null; -+ net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); -+ if (player != null) newProfile = player.getProfile(); -+ if (newProfile == null) newProfile = new GameProfile(null, name); -+ setProfile(newProfile); -+ // Paper end - } - - return true; diff --git a/Remapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch b/Remapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch deleted file mode 100644 index 703b1b0774..0000000000 --- a/Remapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Mar 2016 23:45:17 -0600 -Subject: [PATCH] Disable spigot tick limiters - - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index f71b56fa079e2c7b2123061a8e1a7cb41935bab6..e25666328dbf433b8358f2637d93b4128034bbaa 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -707,9 +707,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - // Spigot start - // Iterator iterator = this.tileEntityListTick.iterator(); - int tilesThisCycle = 0; -- for (tileLimiter.initTick(); -- tilesThisCycle < tickableBlockEntities.size() && (tilesThisCycle % 10 != 0 || tileLimiter.shouldContinue()); -- tileTickPosition++, tilesThisCycle++) { -+ for (tileTickPosition = 0; tileTickPosition < tickableBlockEntities.size(); tileTickPosition++) { // Paper - Disable tick limiters - tileTickPosition = (tileTickPosition < tickableBlockEntities.size()) ? tileTickPosition : 0; - BlockEntity tileentity = (BlockEntity) this.tickableBlockEntities.get(tileTickPosition); - // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch b/Remapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch deleted file mode 100644 index 7e6b238460..0000000000 --- a/Remapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Steve Anton -Date: Thu, 3 Mar 2016 00:09:38 -0600 -Subject: [PATCH] Add PlayerInitialSpawnEvent - -For modifying a player's initial spawn location as they join the server - -This is a duplicate API from spigot, so use our duplicate subclass and -improve setPosition to use raw - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8cdecaf2f63c78196e0c5046fe2431b40e072c8a..a63babe123fad398b07685ec57cd88756435457c 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -209,7 +209,7 @@ public abstract class PlayerList { - - // Spigot start - spawn location event - Player bukkitPlayer = player.getBukkitEntity(); -- org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(bukkitPlayer, bukkitPlayer.getLocation()); -+ org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(bukkitPlayer, bukkitPlayer.getLocation()); // Paper use our duplicate event - cserver.getPluginManager().callEvent(ev); - - Location loc = ev.getSpawnLocation(); -@@ -217,7 +217,10 @@ public abstract class PlayerList { - - player.setLevel(worldserver1); - player.gameMode.setLevel((ServerLevel) player.level); -- player.absMoveTo(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); -+ // Paper start - set raw so we aren't fully joined to the world (not added to chunk or world) -+ player.setPosRaw(loc.getX(), loc.getY(), loc.getZ()); -+ player.setRot(loc.getYaw(), loc.getPitch()); -+ // Paper end - // Spigot end - - // CraftBukkit - Moved message to after join -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f3f48c268639937874dd39eea9bd8e119eebdce7..72eb40f748c33572c2828f48ebd1ca7d5d5712c8 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -397,7 +397,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return d1 * d1 + d2 * d2 + d3 * d3 < radius * radius; - } - -- protected void setRot(float yaw, float pitch) { -+ public void setRot(float yaw, float pitch) { // Paper - protected -> public - // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 - if (Float.isNaN(yaw)) { - yaw = 0; diff --git a/Remapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch b/Remapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch deleted file mode 100644 index 88836aa6a1..0000000000 --- a/Remapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 01:13:45 -0600 -Subject: [PATCH] Configurable Disabling Cat Chest Detection - -Offers a gameplay feature to stop cats from blocking chests - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5a4c3a8c511f22c8c3240c9c7cd83a65119c1054..70e074cdf2087e638af8e0f3878d0ef8eb7305cc 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -186,4 +186,9 @@ public class PaperWorldConfig { - private void containerUpdateTickRate() { - containerUpdateTickRate = getInt("container-update-tick-rate", 1); - } -+ -+ public boolean disableChestCatDetection; -+ private void disableChestCatDetection() { -+ disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java -index 1bda9a158eb4372b9ab7cf3097732e64810aefc6..6b95cd2e2af66eef324dfcc8f7642da2f9e39d4e 100644 ---- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java -@@ -312,6 +312,11 @@ public class ChestBlock extends AbstractChestBlock implements - } - - private static boolean isCatSittingOnChest(LevelAccessor world, BlockPos pos) { -+ // Paper start - Option to disable chest cat detection -+ if (((Level) world).paperConfig.disableChestCatDetection) { -+ return false; -+ } -+ // Paper end - List list = world.getEntitiesOfClass(Cat.class, new AABB((double) pos.getX(), (double) (pos.getY() + 1), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 2), (double) (pos.getZ() + 1))); - - if (!list.isEmpty()) { diff --git a/Remapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch b/Remapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch deleted file mode 100644 index b0605d0e7a..0000000000 --- a/Remapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 01:17:12 -0600 -Subject: [PATCH] Ensure commands are not ran async - -Plugins calling Player.chat("/foo") or Server.dispatchCommand() could -trigger the server to execute a command while on another thread. - -These commands would then process EXPECTING to be on the main thread, leaving to -very hard to trace concurrency issues. - -This change will synchronize the command execution back to the main thread, causing a -big slowdown in execution but throwing an exception at same time to raise awareness -that it is happening so that plugin authors can fix their code to stop executing commands async. - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 016e91a6ca1c8457e3e367ac0597b73e81919b68..00689dc07625a02781052c5df2e466e8abe85708 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1852,6 +1852,29 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } - - if (!async && s.startsWith("/")) { -+ // Paper Start -+ if (!org.spigotmc.AsyncCatcher.shuttingDown && !org.bukkit.Bukkit.isPrimaryThread()) { -+ final String fCommandLine = s; -+ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Command Dispatched Async: " + fCommandLine); -+ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); -+ Waitable wait = new Waitable() { -+ @Override -+ protected Object evaluate() { -+ chat(fCommandLine, false); -+ return null; -+ } -+ }; -+ server.processQueue.add(wait); -+ try { -+ wait.get(); -+ return; -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! -+ } catch (Exception e) { -+ throw new RuntimeException("Exception processing chat command", e.getCause()); -+ } -+ } -+ // Paper End - this.handleCommand(s); - } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { - // Do nothing, this is coming from a plugin -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6fa31ca31128b1094eebd5f848c5b506dfeedeeb..783da25e189c0264ebf31e244677a6b653ff7b26 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -759,6 +759,29 @@ public final class CraftServer implements Server { - Validate.notNull(commandLine, "CommandLine cannot be null"); - org.spigotmc.AsyncCatcher.catchOp("command dispatch"); // Spigot - -+ // Paper Start -+ if (!org.spigotmc.AsyncCatcher.shuttingDown && !Bukkit.isPrimaryThread()) { -+ final CommandSender fSender = sender; -+ final String fCommandLine = commandLine; -+ Bukkit.getLogger().log(Level.SEVERE, "Command Dispatched Async: " + commandLine); -+ Bukkit.getLogger().log(Level.SEVERE, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); -+ org.bukkit.craftbukkit.util.Waitable wait = new org.bukkit.craftbukkit.util.Waitable() { -+ @Override -+ protected Boolean evaluate() { -+ return dispatchCommand(fSender, fCommandLine); -+ } -+ }; -+ net.minecraft.server.MinecraftServer.getServer().processQueue.add(wait); -+ try { -+ return wait.get(); -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! -+ } catch (Exception e) { -+ throw new RuntimeException("Exception processing dispatch command", e.getCause()); -+ } -+ } -+ // Paper End -+ - if (commandMap.dispatch(sender, commandLine)) { - return true; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index ddef523ea8762c927f37f7d16d581e43367e8c6b..70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -13,6 +13,7 @@ public class ServerShutdownThread extends Thread { - public void run() { - try { - org.spigotmc.AsyncCatcher.enabled = false; // Spigot -+ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper - server.close(); - } finally { - try { -diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java -index aeed7697254af17ffefe8e578353ad216e15f9f3..9f7d2ef932ab41cef5d3d0736d20a7c7e4a2c888 100644 ---- a/src/main/java/org/spigotmc/AsyncCatcher.java -+++ b/src/main/java/org/spigotmc/AsyncCatcher.java -@@ -6,6 +6,7 @@ public class AsyncCatcher - { - - public static boolean enabled = true; -+ public static boolean shuttingDown = false; // Paper - - public static void catchOp(String reason) - { -diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index a4223094802a7e996cc57c617df92d23bc48f5b5..04ae5fec376af006ec828d1ae568338af5cfe6ce 100644 ---- a/src/main/java/org/spigotmc/RestartCommand.java -+++ b/src/main/java/org/spigotmc/RestartCommand.java -@@ -43,6 +43,7 @@ public class RestartCommand extends Command - private static void restart(final String restartScript) - { - AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us -+ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper - try - { - String[] split = restartScript.split( " " ); diff --git a/Remapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch b/Remapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch deleted file mode 100644 index cee1933ce4..0000000000 --- a/Remapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: vemacs -Date: Thu, 3 Mar 2016 01:19:22 -0600 -Subject: [PATCH] All chunks are slime spawn chunks toggle - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 70e074cdf2087e638af8e0f3878d0ef8eb7305cc..416a6760883cb40367535c7c5acd779742bb8af5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -191,4 +191,9 @@ public class PaperWorldConfig { - private void disableChestCatDetection() { - disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); - } -+ -+ public boolean allChunksAreSlimeChunks; -+ private void allChunksAreSlimeChunks() { -+ allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java -index 8ff8c19f0b258623b9f0a3cfd0ad5595a92f5899..fc8f26e988f1e4826dcfdcf071293bb356163e62 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Slime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java -@@ -323,7 +323,7 @@ public class Slime extends Mob implements Enemy { - } - - ChunkPos chunkcoordintpair = new ChunkPos(pos); -- boolean flag = WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getLevel().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot -+ boolean flag = world.getLevel().paperConfig.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getLevel().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper - - if (random.nextInt(10) == 0 && flag && pos.getY() < 40) { - return checkMobSpawnRules(type, world, spawnReason, pos, random); diff --git a/Remapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch b/Remapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch deleted file mode 100644 index c633af2298..0000000000 --- a/Remapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Thu, 3 Mar 2016 02:15:57 -0600 -Subject: [PATCH] Expose server CommandMap - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 783da25e189c0264ebf31e244677a6b653ff7b26..95d32f37db663a37f8fde927bdf9d3d4802ba1b4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1760,6 +1760,7 @@ public final class CraftServer implements Server { - return helpMap; - } - -+ @Override // Paper - add override - public SimpleCommandMap getCommandMap() { - return commandMap; - } diff --git a/Remapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch b/Remapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch deleted file mode 100644 index b47fa12664..0000000000 --- a/Remapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Thu, 3 Mar 2016 02:18:39 -0600 -Subject: [PATCH] Be a bit more informative in maxHealth exception - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index d8bfb0953f0b23c64f4e27fc84a6c5f3eb0cc8b8..3afdcb3013263a7e06876821d7d889fa48404041 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -99,7 +99,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setHealth(double health) { - health = (float) health; - if ((health < 0) || (health > getMaxHealth())) { -- throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + "(" + health + ")"); -+ // Paper - Be more informative -+ throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + ", but was " + health -+ + ". (attribute base value: " + this.getHandle().getAttribute(Attributes.MAX_HEALTH).getBaseValue() -+ + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); - } - - getHandle().setHealth((float) health); diff --git a/Remapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch b/Remapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch deleted file mode 100644 index c26e87ac6e..0000000000 --- a/Remapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Thu, 3 Mar 2016 02:32:10 -0600 -Subject: [PATCH] Player Tab List and Title APIs - - -diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -index 59788eaef0dae5ee01ceba1bf45e85cb07f88e53..b4542ce6a8c37ab31e6ecaeb4cbad4742cca0f9b 100644 ---- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java -+++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -@@ -170,6 +170,11 @@ public class FriendlyByteBuf extends ByteBuf { - public FriendlyByteBuf writeComponent(final net.kyori.adventure.text.Component component) { - return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); - } -+ -+ @Deprecated -+ public FriendlyByteBuf writeComponent(final net.md_5.bungee.api.chat.BaseComponent[] component) { -+ return this.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(component), 262144); -+ } - // Paper end - - public FriendlyByteBuf writeComponent(Component text) { -diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java -index 54d186a195aca6d0a4c412ed609d8c86dcc76072..06e9246f05e130be6a63ebb0c9def10c6c9675b7 100644 ---- a/src/main/java/net/minecraft/network/chat/Component.java -+++ b/src/main/java/net/minecraft/network/chat/Component.java -@@ -363,6 +363,7 @@ public interface Component extends Message, FormattedText, Iterable { - return Component.Serializer.GSON.toJsonTree(text); - } - -+ @Nullable public static Component jsonToComponent(String json) { return fromJson(json);} // Paper - OBFHELPER - @Nullable - public static MutableComponent fromJson(String json) { - return (MutableComponent) GsonHelper.fromJson(Component.Serializer.GSON, json, MutableComponent.class, false); -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -index 69ff8df7340e60c476803256750a48f0b43414d3..df444daeb181ff78170f7b92bd02f1f1862dfa2e 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -@@ -47,6 +47,17 @@ public class ClientboundSetTitlesPacket implements Packet -Date: Thu, 3 Mar 2016 02:33:53 -0600 -Subject: [PATCH] Ensure inv drag is in bounds - - -diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -index c377a425dc3274b8aa25f94ce8f76efda2652def..72b0cfcc5aab03e14e63440c734436e9c1432111 100644 ---- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -238,7 +238,7 @@ public abstract class AbstractContainerMenu { - this.resetQuickCraft(); - } - } else if (this.quickcraftStatus == 1) { -- Slot slot = (Slot) this.slots.get(i); -+ Slot slot = i < this.slots.size() ? this.slots.get(i) : null; // Paper - Ensure drag in bounds - - itemstack1 = playerinventory.getCarried(); - if (slot != null && canItemQuickReplace(slot, itemstack1, true) && slot.isAllowed(itemstack1) && (this.quickcraftType == 2 || itemstack1.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) { diff --git a/Remapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch b/Remapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch deleted file mode 100644 index 6e0641f0dd..0000000000 --- a/Remapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:39:54 -0600 -Subject: [PATCH] Change implementation of (tile)entity removal list - -use sets for faster removal - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 6c6098731752d61b5241710b075d4ffe3826daac..89472b6e8f38921db50440d0213e40ac893892f1 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1122,7 +1122,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - } - // Spigot End -- this.blockEntitiesToUnload.addAll(chunk.getBlockEntities().values()); -+ this.tileEntityListUnload.addAll(chunk.getBlockEntities().values()); - List[] aentityslice = chunk.getEntitySlices(); // Spigot - int i = aentityslice.length; - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index e25666328dbf433b8358f2637d93b4128034bbaa..7b4475807cca0e92ea9ae6ea49a82a8634cc0ff5 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -89,7 +89,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public final List blockEntityList = Lists.newArrayList(); - public final List tickableBlockEntities = Lists.newArrayList(); - protected final List pendingBlockEntities = Lists.newArrayList(); -- protected final List blockEntitiesToUnload = Lists.newArrayList(); -+ protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); - public final Thread thread; - private final boolean isDebug; - private int skyDarken; -@@ -697,10 +697,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - gameprofilerfiller.push("blockEntities"); - timings.tileEntityTick.startTiming(); // Spigot -- if (!this.blockEntitiesToUnload.isEmpty()) { -- this.tickableBlockEntities.removeAll(this.blockEntitiesToUnload); -- this.blockEntityList.removeAll(this.blockEntitiesToUnload); -- this.blockEntitiesToUnload.clear(); -+ if (!this.tileEntityListUnload.isEmpty()) { -+ this.tickableBlockEntities.removeAll(this.tileEntityListUnload); -+ this.blockEntityList.removeAll(this.tileEntityListUnload); -+ this.tileEntityListUnload.clear(); - } - - this.updatingBlockEntities = true; diff --git a/Remapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch b/Remapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch deleted file mode 100644 index 8bbb23e407..0000000000 --- a/Remapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:46:17 -0600 -Subject: [PATCH] Add configurable portal search radius - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 416a6760883cb40367535c7c5acd779742bb8af5..670efbe53241a0ae32d618c83da601ccc1f26e37 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -196,4 +196,13 @@ public class PaperWorldConfig { - private void allChunksAreSlimeChunks() { - allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); - } -+ -+ public int portalSearchRadius; -+ public int portalCreateRadius; -+ public boolean portalSearchVanillaDimensionScaling; -+ private void portalSearchRadius() { -+ portalSearchRadius = getInt("portal-search-radius", 128); -+ portalCreateRadius = getInt("portal-create-radius", 16); -+ portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 72eb40f748c33572c2828f48ebd1ca7d5d5712c8..a6f2e671cc9b2ef086dfa3d127a7b33272acbd56 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2617,7 +2617,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - double d4 = DimensionType.getTeleportationScale(this.level.dimensionType(), destination.dimensionType()); - BlockPos blockposition = new BlockPos(Mth.clamp(this.getX() * d4, d0, d2), this.getY(), Mth.clamp(this.getZ() * d4, d1, d3)); - // CraftBukkit start -- CraftPortalEvent event = callPortalEvent(this, destination, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); -+ // Paper start -+ int portalSearchRadius = destination.paperConfig.portalSearchRadius; -+ if (level.paperConfig.portalSearchVanillaDimensionScaling && flag2) { // == THE_NETHER -+ portalSearchRadius = (int) (portalSearchRadius / destination.dimensionType().coordinateScale()); -+ } -+ // Paper end -+ CraftPortalEvent event = callPortalEvent(this, destination, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, portalSearchRadius, destination.paperConfig.portalCreateRadius); // Paper start - configurable portal radius - if (event == null) { - return null; - } -diff --git a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java -index 948d031627435bfce442b1fe7d3eff4addc85bc4..21c01302635d23bc21e6bb373cbe277ea1eb6a56 100644 ---- a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java -+++ b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java -@@ -30,7 +30,7 @@ public class PortalForcer { - - public Optional findPortalAround(BlockPos blockposition, boolean flag) { - // CraftBukkit start -- return findPortalAround(blockposition, flag ? 16 : 128); // Search Radius -+ return findPortalAround(blockposition, flag ? level.paperConfig.portalCreateRadius : level.paperConfig.portalSearchRadius); // Paper - search Radius - } - - public Optional findPortal(BlockPos blockposition, int i) { diff --git a/Remapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch b/Remapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch deleted file mode 100644 index 3a11078735..0000000000 --- a/Remapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:48:12 -0600 -Subject: [PATCH] Add velocity warnings - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 95d32f37db663a37f8fde927bdf9d3d4802ba1b4..35d3df7ded4904414a9a61895950b56be530d244 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -260,6 +260,7 @@ public final class CraftServer implements Server { - public boolean ignoreVanillaPermissions = false; - private final List playerView; - public int reloadCount; -+ public static Exception excessiveVelEx; // Paper - Velocity warnings - - static { - ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index e7a59a8e0424a0839dfa73fc65f44c5b04bd3dec..b028946de7c8f52091635fe154c816453f1ddc93 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -424,10 +424,41 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public void setVelocity(Vector velocity) { - Preconditions.checkArgument(velocity != null, "velocity"); - velocity.checkFinite(); -+ // Paper start - Warn server owners when plugins try to set super high velocities -+ if (!(this instanceof org.bukkit.entity.Projectile) && isUnsafeVelocity(velocity)) { -+ CraftServer.excessiveVelEx = new Exception("Excessive velocity set detected: tried to set velocity of entity " + entity.getScoreboardName() + " id #" + getEntityId() + " to (" + velocity.getX() + "," + velocity.getY() + "," + velocity.getZ() + ")."); -+ } -+ // Paper end -+ - entity.setDeltaMovement(CraftVector.toNMS(velocity)); - entity.hurtMarked = true; - } - -+ // Paper start -+ /** -+ * Checks if the given velocity is not necessarily safe in all situations. -+ * This function returning true does not mean the velocity is dangerous or to be avoided, only that it may be -+ * a detriment to performance on the server. -+ * -+ * It is not to be used as a hard rule of any sort. -+ * Paper only uses it to warn server owners in watchdog crashes. -+ * -+ * @param vel incoming velocity to check -+ * @return if the velocity has the potential to be a performance detriment -+ */ -+ private static boolean isUnsafeVelocity(Vector vel) { -+ final double x = vel.getX(); -+ final double y = vel.getY(); -+ final double z = vel.getZ(); -+ -+ if (x > 4 || x < -4 || y > 4 || y < -4 || z > 4 || z < -4) { -+ return true; -+ } -+ -+ return false; -+ } -+ // Paper end -+ - @Override - public double getHeight() { - return getHandle().getBbHeight(); -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 21d7b483920841456707fe3f08b180c1f072b7f7..0ed95268364ea7f6a92a39b726a1e03bc815be07 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -80,7 +80,19 @@ public class WatchdogThread extends Thread - log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" ); - log.log( Level.SEVERE, "near " + net.minecraft.world.level.Level.lastPhysicsProblem ); - } -- // -+ // Paper start - Warn in watchdog if an excessive velocity was ever set -+ if ( org.bukkit.craftbukkit.CraftServer.excessiveVelEx != null ) -+ { -+ log.log( Level.SEVERE, "------------------------------" ); -+ log.log( Level.SEVERE, "During the run of the server, a plugin set an excessive velocity on an entity" ); -+ log.log( Level.SEVERE, "This may be the cause of the issue, or it may be entirely unrelated" ); -+ log.log( Level.SEVERE, org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getMessage()); -+ for ( StackTraceElement stack : org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getStackTrace() ) -+ { -+ log.log( Level.SEVERE, "\t\t" + stack ); -+ } -+ } -+ // Paper end - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); diff --git a/Remapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch b/Remapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch deleted file mode 100644 index c0826d9b39..0000000000 --- a/Remapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Thu, 3 Mar 2016 02:50:31 -0600 -Subject: [PATCH] Configurable inter-world teleportation safety - -People are able to abuse the way Bukkit handles teleportation across worlds since it provides a built in teleportation -safety check. - -To abuse the safety check, players are required to get into a location deemed unsafe by Bukkit e.g. be within a chest -or door block. While they are in this block, they accept a teleport request from a player within a different world. Once -the player teleports, Minecraft will recursively search upwards for a safe location, this could eventually land within a -player's skybase. - -Example setup to perform the glitch: http://puu.sh/ng3PC/cf072dcbdb.png -The wanted destination was on top of the emerald block however the player ended on top of the diamond block. -This only is the case if the player is teleporting between worlds. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 670efbe53241a0ae32d618c83da601ccc1f26e37..abbbe1786eb68af02f9d39650aad730ac44aac8a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -205,4 +205,9 @@ public class PaperWorldConfig { - portalCreateRadius = getInt("portal-create-radius", 16); - portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); - } -+ -+ public boolean disableTeleportationSuffocationCheck; -+ private void disableTeleportationSuffocationCheck() { -+ disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 63933bd455ad72a772d4db160e946600b84a1791..3b9d61b524441f65646edf7d403b6c5b5345b1e5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -861,7 +861,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (fromWorld == toWorld) { - entity.connection.teleport(to); - } else { -- server.getHandle().moveToWorld(entity, toWorld, true, to, true); -+ server.getHandle().moveToWorld(entity, toWorld, true, to, !toWorld.paperConfig.disableTeleportationSuffocationCheck); // Paper - } - return true; - } diff --git a/Remapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch b/Remapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch deleted file mode 100644 index 7b87e0d39f..0000000000 --- a/Remapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch +++ /dev/null @@ -1,264 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 03:15:41 -0600 -Subject: [PATCH] Add exception reporting event - - -diff --git a/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f699ce18ca044f813e194ef2786b7ea853ea86e7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java -@@ -0,0 +1,38 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.craftbukkit.scheduler.CraftTask; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerSchedulerException; -+ -+/** -+ * Reporting wrapper to catch exceptions not natively -+ */ -+public class ServerSchedulerReportingWrapper implements Runnable { -+ -+ private final CraftTask internalTask; -+ -+ public ServerSchedulerReportingWrapper(CraftTask internalTask) { -+ this.internalTask = Preconditions.checkNotNull(internalTask, "internalTask"); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ internalTask.run(); -+ } catch (RuntimeException e) { -+ internalTask.getOwner().getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(e, internalTask)) -+ ); -+ throw e; -+ } catch (Throwable t) { -+ internalTask.getOwner().getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(t, internalTask)) -+ ); //Do not rethrow, since it is not permitted with Runnable#run -+ } -+ } -+ -+ public CraftTask getInternalTask() { -+ return internalTask; -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index d1bc927c8b429f43de2cdad98f8b329ff4c8b4db..0597c0c3e881dd43cf91bd3088ed30dfecfe8098 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -813,6 +813,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return true; - } catch (Exception exception) { - ChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - return false; - } - } -diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java -index c167d2fd99a7a352e69e2930551678bd9c9def83..09c5fa2dbcbed05da51ef2d63e6d6112d22d7877 100644 ---- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java -+++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.players; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.io.Files; -@@ -360,6 +361,7 @@ public class OldUsersConverter { - root = NbtIo.readCompressed(new java.io.FileInputStream(file5)); - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - } - - if (root != null) { -@@ -373,6 +375,7 @@ public class OldUsersConverter { - NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2)); - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -index 78cea15142f9fd7988f5df397061b90625070eef..f50774f022c78813982bfe08f764b54bde779e04 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -@@ -1,5 +1,7 @@ - package net.minecraft.world.entity.ai.village; - -+import com.destroystokyo.paper.exception.ServerInternalException; -+ - import java.util.Iterator; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; -@@ -119,6 +121,7 @@ public class VillageSiege implements CustomSpawner { - entityzombie.finalizeSpawn(world, world.getCurrentDifficultyAt(entityzombie.blockPosition()), MobSpawnType.EVENT, (SpawnGroupData) null, (CompoundTag) null); - } catch (Exception exception) { - VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception); -+ ServerInternalException.reportInternalException(exception); // Paper - return; - } - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 7b4475807cca0e92ea9ae6ea49a82a8634cc0ff5..94e268a05b4601c29b6d2845f0fc2311643a161f 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1,5 +1,10 @@ - package net.minecraft.world.level; - -+import co.aikar.timings.Timing; -+import co.aikar.timings.Timings; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerInternalException; -+import com.google.common.base.MoreObjects; - import com.google.common.collect.Lists; - import com.mojang.serialization.Codec; - import java.io.IOException; -@@ -737,8 +742,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - gameprofilerfiller.pop(); - } catch (Throwable throwable) { - // Paper start - Prevent tile entity and entity crashes -- System.err.println("TileEntity threw exception at " + tileentity.level.getWorld().getName() + ":" + tileentity.worldPosition.getX() + "," + tileentity.worldPosition.getY() + "," + tileentity.worldPosition.getZ()); -+ String msg = "TileEntity threw exception at " + tileentity.getLevel().getWorld().getName() + ":" + tileentity.getBlockPos().getX() + "," + tileentity.getBlockPos().getY() + "," + tileentity.getBlockPos().getZ(); -+ System.err.println(msg); - throwable.printStackTrace(); -+ getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); -+ // Paper end - tilesThisCycle--; - this.tickableBlockEntities.remove(tileTickPosition--); - continue; -@@ -808,8 +816,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - tickConsumer.accept(entity); - } catch (Throwable throwable) { - // Paper start - Prevent tile entity and entity crashes -- System.err.println("Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ()); -+ String msg = "Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ(); -+ System.err.println(msg); - throwable.printStackTrace(); -+ getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); - entity.removed = true; - return; - // Paper end -diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index fc134b916e95231af8478a4f97bf11a0f37f7f0b..a19ac1cb7e4d8d478648a048b2bfa0daf85a80c9 100644 ---- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java -+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -299,6 +299,7 @@ public final class NaturalSpawner { - } - } catch (Exception exception) { - NaturalSpawner.LOGGER.warn("Failed to create mob", exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - return null; - } - } -@@ -405,6 +406,7 @@ public final class NaturalSpawner { - entity = biomesettingsmobs_c.type.create((Level) worldaccess.getLevel()); - } catch (Exception exception) { - NaturalSpawner.LOGGER.warn("Failed to create mob", exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - continue; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 300749822d52f9f973e71c6ec9c8bf29d6a6938e..9ca05aa06696883adc8b67a68ca6d2d850e95d25 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.chunk; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; - import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -@@ -654,10 +655,15 @@ public class LevelChunk implements ChunkAccess { - this.blockEntities.remove(pos); - // Paper end - } else { -- System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() -- + " (" + getBlockState(pos) + ") where there was no entity tile!"); -- System.out.println("Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); -- new Exception().printStackTrace(); -+ // Paper start -+ ServerInternalException e = new ServerInternalException( -+ "Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," -+ + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() -+ + " (" + getBlockState(pos) + ") where there was no entity tile!\n" + -+ "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); -+ e.printStackTrace(); -+ ServerInternalException.reportInternalException(e); -+ // Paper end - // CraftBukkit end - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 60f410a4f838048bbfd2cde52caa7c4c9434b0ba..1598da3449ee1c559cf503e1b20a0daaf6a033dd 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -265,6 +265,7 @@ public class RegionFile implements AutoCloseable { - return true; - } - } catch (IOException ioexception) { -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper - return false; - } - } -@@ -337,6 +338,7 @@ public class RegionFile implements AutoCloseable { - filechannel.write(bytebuffer); - } catch (Throwable throwable1) { - throwable = throwable1; -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper - throw throwable1; - } finally { - if (filechannel != null) { -diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -index 60b7fdf9c092e8105d41f4af02a08651624f3eb9..99cfd693ea705d45a5eab181cb80c354a2d1159f 100644 ---- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -+++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -@@ -150,6 +150,7 @@ public class DimensionDataStorage { - } - } catch (Throwable throwable6) { - throwable = throwable6; -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper - throw throwable6; - } finally { - if (fileinputstream != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index ffe9cc1011226d604dc5499e7692e9a9a5132b72..9b6d9373abb59a30c2835ca891282d07559281f5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -16,6 +16,9 @@ import java.util.concurrent.atomic.AtomicInteger; - import java.util.concurrent.atomic.AtomicReference; - import java.util.function.Consumer; - import java.util.logging.Level; -+import com.destroystokyo.paper.ServerSchedulerReportingWrapper; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerSchedulerException; - import org.apache.commons.lang.Validate; - import org.bukkit.plugin.IllegalPluginAccessException; - import org.bukkit.plugin.Plugin; -@@ -419,6 +422,8 @@ public class CraftScheduler implements BukkitScheduler { - msg, - throwable); - } -+ org.bukkit.Bukkit.getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task))); - // Paper end - } finally { - currentTask = null; -@@ -426,7 +431,7 @@ public class CraftScheduler implements BukkitScheduler { - parsePending(); - } else { - debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); -- executor.execute(task); -+ executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper - // We don't need to parse pending - // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) - } diff --git a/Remapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/Remapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch deleted file mode 100644 index f1642d7a3b..0000000000 --- a/Remapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Tue, 8 Mar 2016 18:28:43 -0800 -Subject: [PATCH] Don't nest if we don't need to when cerealising text - components - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -index e47102cadb40ed8a9c011386445f15fd30de7596..f13da9e7d014bc00fbabf0a495b548bba2f59468 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -@@ -40,7 +40,14 @@ public class ClientboundChatPacket implements Packet { - // Paper end - // Spigot start - if (components != null) { -- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(components)); -+ //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below -+ // Paper start - don't nest if we don't need to so that we can preserve formatting -+ if (this.components.length == 1) { -+ buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); -+ } else { -+ buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); -+ } -+ // Paper end - } else { - buf.writeComponent(this.message); - } diff --git a/Remapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch b/Remapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch deleted file mode 100644 index d1cae6e603..0000000000 --- a/Remapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 8 Mar 2016 23:25:45 -0500 -Subject: [PATCH] Disable Scoreboards for non players by default - -Entities collision is checking for scoreboards setting. -This is very heavy to do map lookups for every collision to check -this setting. - -So avoid looking up scoreboards and short circuit to the "not on a team" -logic which is most likely to be true. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index abbbe1786eb68af02f9d39650aad730ac44aac8a..3ac2ac3db9b1c271b3c21930bb13716669ff64d3 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -210,4 +210,9 @@ public class PaperWorldConfig { - private void disableTeleportationSuffocationCheck() { - disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); - } -+ -+ public boolean nonPlayerEntitiesOnScoreboards = false; -+ private void nonPlayerEntitiesOnScoreboards() { -+ nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a6f2e671cc9b2ef086dfa3d127a7b33272acbd56..93d3408231a177cf6d2086594756adffe3efa702 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2288,6 +2288,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - - @Nullable - public Team getTeam() { -+ if (!this.level.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof Player)) { return null; } // Paper - return this.level.getScoreboard().getPlayerTeam(this.getScoreboardName()); - } - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index afd114e1ce00db72534d470fed12101bb237f266..d483d552092c901fec262c43e488784d9cd8acb9 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -738,6 +738,7 @@ public abstract class LivingEntity extends Entity { - if (tag.contains("Team", 8)) { - String s = tag.getString("Team"); - PlayerTeam scoreboardteam = this.level.getScoreboard().getTeam(s); -+ if (!level.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof net.minecraft.world.entity.player.Player)) { scoreboardteam = null; } // Paper - boolean flag = scoreboardteam != null && this.level.getScoreboard().addPlayerToTeam(this.getStringUUID(), scoreboardteam); - - if (!flag) { diff --git a/Remapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Remapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch deleted file mode 100644 index e0d5759239..0000000000 --- a/Remapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mrapple -Date: Sun, 25 Nov 2012 13:43:39 -0600 -Subject: [PATCH] Add methods for working with arrows stuck in living entities - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 3afdcb3013263a7e06876821d7d889fa48404041..d8cd88d62f9abfc7960c187dd74239f61267ca57 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -677,4 +677,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - getHandle().persistentInvisibility = invisible; - getHandle().setSharedFlag(5, invisible); - } -+ -+ // Paper start -+ @Override -+ public int getArrowsStuck() { -+ return getHandle().getArrowCount(); -+ } -+ -+ @Override -+ public void setArrowsStuck(int arrows) { -+ getHandle().setArrowCount(arrows); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch b/Remapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch deleted file mode 100644 index 6be95196f1..0000000000 --- a/Remapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 4 Apr 2015 23:17:52 -0400 -Subject: [PATCH] Complete resource pack API - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 00689dc07625a02781052c5df2e466e8abe85708..73683ba59d0aff3a61f555b4ae15753e9e4e6141 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1603,7 +1603,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // CraftBukkit start - public void handleResourcePackResponse(ServerboundResourcePackPacket packet) { - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); -- this.craftServer.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()])); -+ // Paper start -+ PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()]; -+ player.getBukkitEntity().setResourcePackStatus(packStatus); -+ this.craftServer.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), packStatus)); -+ // Paper end - } - // CraftBukkit end - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 3b9d61b524441f65646edf7d403b6c5b5345b1e5..dd29038778d73fae84df360515f3c670915f1d48 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -136,6 +136,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - private double health = 20; - private boolean scaledHealth = false; - private double healthScale = 20; -+ // Paper start -+ private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; -+ private String resourcePackHash; -+ // Paper end - - public CraftPlayer(CraftServer server, ServerPlayer entity) { - super(server, entity); -@@ -1872,6 +1876,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public boolean getAffectsSpawning() { - return this.getHandle().affectsSpawning; - } -+ -+ @Override -+ public void setResourcePack(String url, String hash) { -+ Validate.notNull(url, "Resource pack URL cannot be null"); -+ Validate.notNull(hash, "Hash cannot be null"); -+ this.getHandle().sendTexturePack(url, hash); -+ } -+ -+ @Override -+ public org.bukkit.event.player.PlayerResourcePackStatusEvent.Status getResourcePackStatus() { -+ return this.resourcePackStatus; -+ } -+ -+ @Override -+ public String getResourcePackHash() { -+ return this.resourcePackHash; -+ } -+ -+ @Override -+ public boolean hasResourcePack() { -+ return this.resourcePackStatus == org.bukkit.event.player.PlayerResourcePackStatusEvent.Status.SUCCESSFULLY_LOADED; -+ } -+ -+ public void setResourcePackStatus(org.bukkit.event.player.PlayerResourcePackStatusEvent.Status status) { -+ this.resourcePackStatus = status; -+ } - // Paper end - - @Override diff --git a/Remapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch b/Remapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch deleted file mode 100644 index db35b14461..0000000000 --- a/Remapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 4 Mar 2013 23:46:10 -0500 -Subject: [PATCH] Chunk Save Reattempt - -We commonly have "Stream Closed" errors on chunk saving, so this code should re-try to save the chunk in the event of failure and hopefully prevent rollbacks. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 1598da3449ee1c559cf503e1b20a0daaf6a033dd..1aa4d342b97f8be71c108194a6f1e0e2828aa364 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -265,7 +265,7 @@ public class RegionFile implements AutoCloseable { - return true; - } - } catch (IOException ioexception) { -- com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioexception); // Paper - we want the upper try/catch to retry this - return false; - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 1e49d17b54704e1b99c3ded458c4bc6842bd32bd..97a58da9d64d812942ceb71426d35b490bbbe817 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -11,6 +11,7 @@ import java.io.IOException; - import javax.annotation.Nullable; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.NbtIo; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionCollector; - import net.minecraft.world.level.ChunkPos; - -@@ -92,6 +93,7 @@ public final class RegionFileStorage implements AutoCloseable { - - protected void write(ChunkPos pos, CompoundTag tag) throws IOException { - RegionFile regionfile = this.getFile(pos, false); // CraftBukkit -+ int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper - DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(pos); - Throwable throwable = null; - -@@ -115,6 +117,18 @@ public final class RegionFileStorage implements AutoCloseable { - - } - -+ // Paper start -+ return; -+ } catch (Exception ex) { -+ laste = ex; -+ } -+ } -+ -+ if (laste != null) { -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(laste); -+ MinecraftServer.LOGGER.error("Failed to save chunk", laste); -+ } -+ // Paper end - } - - public void close() throws IOException { diff --git a/Remapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch b/Remapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch deleted file mode 100644 index 3df2a1e2a2..0000000000 --- a/Remapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 13:17:38 -0400 -Subject: [PATCH] Default loading permissions.yml before plugins - -Under previous behavior, plugins were not able to check if a player had a permission -if it was defined in permissions.yml. there is no clean way for a plugin to fix that either. - -This will change the order so that by default, permissions.yml loads BEFORE plugins instead of after. - -This gives plugins expected permission checks. - -It also helps improve the expected logic, as servers should set the initial defaults, and then let plugins -modify that. Under the previous logic, plugins were unable (cleanly) override permissions.yml. - -A config option has been added for those who depend on the previous behavior, but I don't expect that. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 429b74474ced04d8dd8f038b8590b8dfe178bf4d..716f285e67019b8a62922d09c15883c99f9421aa 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -222,4 +222,9 @@ public class PaperConfig { - private static void useDisplayNameInQuit() { - useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); - } -+ -+ public static boolean loadPermsBeforePlugins = true; -+ private static void loadPermsBeforePlugins() { -+ loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 35d3df7ded4904414a9a61895950b56be530d244..662fc88e2e118a57a6c35a8981d4622188adec3b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -397,6 +397,7 @@ public final class CraftServer implements Server { - if (type == PluginLoadOrder.STARTUP) { - helpMap.clear(); - helpMap.initializeGeneralTopics(); -+ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper - } - - Plugin[] plugins = pluginManager.getPlugins(); -@@ -416,7 +417,7 @@ public final class CraftServer implements Server { - commandMap.registerServerAliases(); - DefaultPermissions.registerCorePermissions(); - CraftDefaultPermissions.registerCorePermissions(); -- loadCustomPermissions(); -+ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper - helpMap.initializeCommands(); - syncCommands(); - } diff --git a/Remapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch b/Remapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch deleted file mode 100644 index e43351be69..0000000000 --- a/Remapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William -Date: Fri, 18 Mar 2016 03:30:17 -0400 -Subject: [PATCH] Allow Reloading of Custom Permissions - -https://github.com/PaperMC/Paper/issues/49 - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 662fc88e2e118a57a6c35a8981d4622188adec3b..50da8e292c131176c263f0bc140ff4f6d890c737 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2252,5 +2252,23 @@ public final class CraftServer implements Server { - } - return this.adventure$audiences; - } -+ -+ @Override -+ public void reloadPermissions() { -+ pluginManager.clearPermissions(); -+ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); -+ for (Plugin plugin : pluginManager.getPlugins()) { -+ for (Permission perm : plugin.getDescription().getPermissions()) { -+ try { -+ pluginManager.addPermission(perm); -+ } catch (IllegalArgumentException ex) { -+ getLogger().log(Level.WARNING, "Plugin " + plugin.getDescription().getFullName() + " tried to register permission '" + perm.getName() + "' but it's already registered", ex); -+ } -+ } -+ } -+ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); -+ DefaultPermissions.registerCorePermissions(); -+ CraftDefaultPermissions.registerCorePermissions(); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch b/Remapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch deleted file mode 100644 index bad86d108d..0000000000 --- a/Remapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 13:50:14 -0400 -Subject: [PATCH] Remove Metadata on reload - -Metadata is not meant to persist reload as things break badly with non primitive types -This will remove metadata on reload so it does not crash everything if a plugin uses it. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 50da8e292c131176c263f0bc140ff4f6d890c737..2828936fe294d9d6750a8838da49ec8398835214 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -870,8 +870,18 @@ public final class CraftServer implements Server { - world.paperConfig.init(); // Paper - } - -+ Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper - pluginManager.clearPlugins(); - commandMap.clearCommands(); -+ -+ // Paper start -+ for (Plugin plugin : pluginClone) { -+ entityMetadata.removeAll(plugin); -+ worldMetadata.removeAll(plugin); -+ playerMetadata.removeAll(plugin); -+ } -+ // Paper end -+ - resetRecipes(); - reloadData(); - org.spigotmc.SpigotConfig.registerCommands(); // Spigot diff --git a/Remapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch b/Remapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch deleted file mode 100644 index 32698665bc..0000000000 --- a/Remapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch +++ /dev/null @@ -1,339 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 28 May 2015 23:00:19 -0400 -Subject: [PATCH] Handle Item Meta Inconsistencies - -First, Enchantment order would blow away seeing 2 items as the same, -however the Client forces enchantment list in a certain order, as well -as does the /enchant command. Anvils can insert it into forced order, -causing 2 same items to be considered different. - -This change makes unhandled NBT Tags and Enchantments use a sorted tree map, -so they will always be in a consistent order. - -Additionally, the old enchantment API was never updated when ItemMeta -was added, resulting in 2 different ways to modify an items enchantments. - -For consistency, the old API methods now forward to use the -ItemMeta API equivalents, and should deprecate the old API's. - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 3faf52e7ac5e7e22d09cfb73cfda6b9f622137d4..123025c6dc9a2eea56c7db5cb508cdfd7c6cc97b 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -9,6 +9,8 @@ import com.mojang.serialization.Codec; - import com.mojang.serialization.codecs.RecordCodecBuilder; - import java.text.DecimalFormat; - import java.text.DecimalFormatSymbols; -+import java.util.Collections; -+import java.util.Comparator; - import java.util.Locale; - import java.util.Objects; - import java.util.Optional; -@@ -118,6 +120,23 @@ public final class ItemStack { - private BlockInWorld cachedPlaceBlock; - private boolean cachedPlaceBlockResult; - -+ // Paper start -+ private static final java.util.Comparator enchantSorter = java.util.Comparator.comparing(o -> o.getString("id")); -+ private void processEnchantOrder(CompoundTag tag) { -+ if (tag == null || !tag.contains("Enchantments", 9)) { -+ return; -+ } -+ ListTag list = tag.getList("Enchantments", 10); -+ if (list.size() < 2) { -+ return; -+ } -+ try { -+ //noinspection unchecked -+ list.sort((Comparator) enchantSorter); // Paper -+ } catch (Exception ignored) {} -+ } -+ // Paper end -+ - public ItemStack(ItemLike item) { - this(item, 1); - } -@@ -160,6 +179,7 @@ public final class ItemStack { - if (nbttagcompound.contains("tag", 10)) { - // CraftBukkit start - make defensive copy as this data may be coming from the save thread - this.tag = (CompoundTag) nbttagcompound.getCompound("tag").copy(); -+ processEnchantOrder(this.tag); // Paper - this.getItem().verifyTagAfterLoad(this.tag); - // CraftBukkit end - } -@@ -678,6 +698,7 @@ public final class ItemStack { - // Paper end - public void setTag(@Nullable CompoundTag tag) { - this.tag = tag; -+ processEnchantOrder(this.tag); // Paper - if (this.getItem().canBeDepleted()) { - this.setDamageValue(this.getDamageValue()); - } -@@ -768,6 +789,7 @@ public final class ItemStack { - nbttagcompound.putString("id", String.valueOf(Registry.ENCHANTMENT.getKey(enchantment))); - nbttagcompound.putShort("lvl", (short) ((byte) level)); - nbttaglist.add(nbttagcompound); -+ processEnchantOrder(nbttagcompound); // Paper - } - - public boolean isEnchanted() { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 01df5263d77771a296ca091a0feec620e6e37229..5f0ccdeb8565505278caa591f7390047eab49cf4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -6,7 +6,6 @@ import java.util.Map; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.world.item.Item; --import net.minecraft.world.item.enchantment.EnchantmentHelper; - import org.apache.commons.lang.Validate; - import org.bukkit.Material; - import org.bukkit.configuration.serialization.DelegateDeserialization; -@@ -178,28 +177,11 @@ public final class CraftItemStack extends ItemStack { - public void addUnsafeEnchantment(Enchantment ench, int level) { - Validate.notNull(ench, "Cannot add null enchantment"); - -- if (!makeTag(handle)) { -- return; -- } -- ListTag list = getEnchantmentList(handle); -- if (list == null) { -- list = new ListTag(); -- handle.getTag().put(ENCHANTMENTS.NBT, list); -- } -- int size = list.size(); -- -- for (int i = 0; i < size; i++) { -- CompoundTag tag = (CompoundTag) list.get(i); -- String id = tag.getString(ENCHANTMENTS_ID.NBT); -- if (id.equals(ench.getKey().toString())) { -- tag.putShort(ENCHANTMENTS_LVL.NBT, (short) level); -- return; -- } -- } -- CompoundTag tag = new CompoundTag(); -- tag.putString(ENCHANTMENTS_ID.NBT, ench.getKey().toString()); -- tag.putShort(ENCHANTMENTS_LVL.NBT, (short) level); -- list.add(tag); -+ // Paper start - Replace whole method -+ final ItemMeta itemMeta = getItemMeta(); -+ itemMeta.addEnchant(ench, level, true); -+ setItemMeta(itemMeta); -+ // Paper end - } - - static boolean makeTag(net.minecraft.world.item.ItemStack item) { -@@ -216,66 +198,33 @@ public final class CraftItemStack extends ItemStack { - - @Override - public boolean containsEnchantment(Enchantment ench) { -- return getEnchantmentLevel(ench) > 0; -+ return hasItemMeta() && getItemMeta().hasEnchant(ench); // Paper - use meta - } - - @Override - public int getEnchantmentLevel(Enchantment ench) { -- Validate.notNull(ench, "Cannot find null enchantment"); -- if (handle == null) { -- return 0; -- } -- return EnchantmentHelper.getItemEnchantmentLevel(CraftEnchantment.getRaw(ench), handle); -+ return hasItemMeta() ? getItemMeta().getEnchantLevel(ench) : 0; // Paper - replace entire method with meta - } - - @Override - public int removeEnchantment(Enchantment ench) { - Validate.notNull(ench, "Cannot remove null enchantment"); - -- ListTag list = getEnchantmentList(handle), listCopy; -- if (list == null) { -- return 0; -- } -- int index = Integer.MIN_VALUE; -- int level = Integer.MIN_VALUE; -- int size = list.size(); -- -- for (int i = 0; i < size; i++) { -- CompoundTag enchantment = (CompoundTag) list.get(i); -- String id = enchantment.getString(ENCHANTMENTS_ID.NBT); -- if (id.equals(ench.getKey().toString())) { -- index = i; -- level = 0xffff & enchantment.getShort(ENCHANTMENTS_LVL.NBT); -- break; -- } -- } -- -- if (index == Integer.MIN_VALUE) { -- return 0; -- } -- if (size == 1) { -- handle.getTag().remove(ENCHANTMENTS.NBT); -- if (handle.getTag().isEmpty()) { -- handle.setTag(null); -- } -- return level; -- } -- -- // This is workaround for not having an index removal -- listCopy = new ListTag(); -- for (int i = 0; i < size; i++) { -- if (i != index) { -- listCopy.add(list.get(i)); -- } -+ // Paper start - replace entire method -+ final ItemMeta itemMeta = getItemMeta(); -+ int level = itemMeta.getEnchantLevel(ench); -+ if (level > 0) { -+ itemMeta.removeEnchant(ench); -+ setItemMeta(itemMeta); - } -- handle.getTag().put(ENCHANTMENTS.NBT, listCopy); -+ // Paper end - - return level; - } - - @Override - public Map getEnchantments() { -- return getEnchantments(handle); -+ return hasItemMeta() ? getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta - } - - 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 cca04daf84e506382365c0ba945cb024bd4d4475..521699615778c4b724d10edfee1d3915e036eb2e 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; - import com.google.common.collect.ImmutableMap; - import com.google.common.collect.ImmutableMultimap; - import com.google.common.collect.LinkedHashMultimap; -+import com.google.common.collect.ImmutableSortedMap; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Multimap; - import com.google.common.collect.SetMultimap; -@@ -22,6 +23,7 @@ import java.lang.reflect.InvocationTargetException; - import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; -+import java.util.Comparator; // Paper - import java.util.EnumSet; - import java.util.HashMap; - import java.util.Iterator; -@@ -32,6 +34,7 @@ import java.util.Map; - import java.util.NoSuchElementException; - import java.util.Objects; - import java.util.Set; -+import java.util.TreeMap; // Paper - import java.util.logging.Level; - import java.util.logging.Logger; - import javax.annotation.Nonnull; -@@ -270,7 +273,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - private List lore; // null and empty are two different states internally - private Integer customModelData; - private CompoundTag blockData; -- private Map enchantments; -+ private EnchantmentMap enchantments; // Paper - private Multimap attributeModifiers; - private int repairCost; - private int hideFlag; -@@ -281,7 +284,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); - - private CompoundTag internalTag; -- private final Map unhandledTags = new HashMap(); -+ private final Map unhandledTags = new TreeMap<>(); // Paper - private CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); - - private int version = CraftMagicNumbers.INSTANCE.getDataVersion(); // Internal use only -@@ -302,7 +305,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - this.blockData = meta.blockData; - - if (meta.enchantments != null) { // Spigot -- this.enchantments = new LinkedHashMap(meta.enchantments); -+ this.enchantments = new EnchantmentMap(meta.enchantments); // Paper - } - - if (meta.hasAttributeModifiers()) { -@@ -385,13 +388,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -- static Map buildEnchantments(CompoundTag tag, ItemMetaKey key) { -+ static EnchantmentMap buildEnchantments(CompoundTag tag, ItemMetaKey key) { // Paper - if (!tag.contains(key.NBT)) { - return null; - } - - ListTag ench = tag.getList(key.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); -- Map enchantments = new LinkedHashMap(ench.size()); -+ EnchantmentMap enchantments = new EnchantmentMap(); // Paper - - for (int i = 0; i < ench.size(); i++) { - String id = ((CompoundTag) ench.get(i)).getString(ENCHANTMENTS_ID.NBT); -@@ -544,13 +547,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -- static Map buildEnchantments(Map map, ItemMetaKey key) { -+ static EnchantmentMap buildEnchantments(Map map, ItemMetaKey key) { // Paper - Map ench = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); - if (ench == null) { - return null; - } - -- Map enchantments = new LinkedHashMap(ench.size()); -+ EnchantmentMap enchantments = new EnchantmentMap(); // Paper - for (Map.Entry entry : ench.entrySet()) { - // Doctor older enchants - String enchantKey = entry.getKey().toString(); -@@ -826,14 +829,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - - @Override - public Map getEnchants() { -- return hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); -+ return hasEnchants() ? ImmutableSortedMap.copyOfSorted(enchantments) : ImmutableMap.of(); // Paper - } - - @Override - public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { - Validate.notNull(ench, "Enchantment cannot be null"); - if (enchantments == null) { -- enchantments = new LinkedHashMap(4); -+ enchantments = new EnchantmentMap(); // Paper - } - - if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { -@@ -1214,7 +1217,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - clone.customModelData = this.customModelData; - clone.blockData = this.blockData; - if (this.enchantments != null) { -- clone.enchantments = new LinkedHashMap(this.enchantments); -+ clone.enchantments = new EnchantmentMap(this.enchantments); // Paper - } - if (this.hasAttributeModifiers()) { - clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); -@@ -1446,4 +1449,22 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return HANDLED_TAGS; - } - } -+ -+ // Paper start -+ private static class EnchantmentMap extends TreeMap { -+ private EnchantmentMap(Map enchantments) { -+ this(); -+ putAll(enchantments); -+ } -+ -+ private EnchantmentMap() { -+ super(Comparator.comparing(o -> o.getKey().toString())); -+ } -+ -+ public EnchantmentMap clone() { -+ return (EnchantmentMap) super.clone(); -+ } -+ } -+ // Paper end -+ - } diff --git a/Remapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/Remapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch deleted file mode 100644 index a940748e3b..0000000000 --- a/Remapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 15:12:22 -0400 -Subject: [PATCH] Configurable Non Player Arrow Despawn Rate - -Can set a much shorter despawn rate for arrows that players can not pick up. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3ac2ac3db9b1c271b3c21930bb13716669ff64d3..3c78d3234054ce2dc46ef77decb6adb0cbd10620 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -215,4 +215,19 @@ public class PaperWorldConfig { - private void nonPlayerEntitiesOnScoreboards() { - nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); - } -+ -+ public int nonPlayerArrowDespawnRate = -1; -+ public int creativeArrowDespawnRate = -1; -+ private void nonPlayerArrowDespawnRate() { -+ nonPlayerArrowDespawnRate = getInt("non-player-arrow-despawn-rate", -1); -+ if (nonPlayerArrowDespawnRate == -1) { -+ nonPlayerArrowDespawnRate = spigotConfig.arrowDespawnRate; -+ } -+ creativeArrowDespawnRate = getInt("creative-arrow-despawn-rate", -1); -+ if (creativeArrowDespawnRate == -1) { -+ creativeArrowDespawnRate = spigotConfig.arrowDespawnRate; -+ } -+ log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); -+ log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); -+ } - } -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 371fdcbf1f9c01f6a356393f6c3767511f230930..0dc5792d542658107c9c22c1f920986decd13920 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -281,7 +281,7 @@ public abstract class AbstractArrow extends Projectile { - - protected void tickDespawn() { - ++this.life; -- if (this.life >= ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)) { // Spigot -+ if (this.life >= (pickup == Pickup.CREATIVE_ONLY ? level.paperConfig.creativeArrowDespawnRate : (pickup == Pickup.DISALLOWED ? level.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? - this.remove(); - } - diff --git a/Remapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch b/Remapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch deleted file mode 100644 index 83f43bb54a..0000000000 --- a/Remapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 20:16:03 -0400 -Subject: [PATCH] Add World Util Methods - -Methods that can be used for other patches to help improve logic. - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 89472b6e8f38921db50440d0213e40ac893892f1..e1f9a12c7fb4818a785b9a4819f94fccde02b6a2 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -191,7 +191,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - public final LevelStorageSource.LevelStorageAccess convertable; - public final UUID uuid; - -- public LevelChunk getChunkIfLoaded(int x, int z) { -+ @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkSource.getChunk(x, z, false); - } - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 94e268a05b4601c29b6d2845f0fc2311643a161f..799721ac63f0c08dd03a788b87eafa9a8cc976cc 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -297,11 +297,27 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - - @Override -- public FluidState getFluidIfLoaded(BlockPos blockposition) { -+ public final FluidState getFluidIfLoaded(BlockPos blockposition) { - ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); - - return chunk == null ? null : chunk.getFluidState(blockposition); - } -+ -+ public final boolean isLoadedAndInBounds(BlockPos blockposition) { // Paper - final for inline -+ return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; -+ } -+ -+ public LevelChunk getChunkIfLoaded(int x, int z) { // Overridden in WorldServer for ABI compat which has final -+ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(x, z); -+ } -+ public final LevelChunk getChunkIfLoaded(BlockPos blockposition) { -+ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ } -+ -+ // reduces need to do isLoaded before getType -+ public final BlockState getTypeIfLoadedAndInBounds(BlockPos blockposition) { -+ return getWorldBorder().isInBounds(blockposition) ? getTypeIfLoaded(blockposition) : null; -+ } - // Paper end - - @Override -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 31f17956b3b031d1a47bda4d282554c8a7853097..0846f649dca3422dbab3bb0a4826e27430cc8186 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -31,6 +31,7 @@ public class WorldBorder { - - public WorldBorder() {} - -+ public final boolean isInBounds(BlockPos blockposition) { return this.isWithinBounds(blockposition); } // Paper - OBFHELPER - public boolean isWithinBounds(BlockPos pos) { - return (double) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ(); - } diff --git a/Remapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch b/Remapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch deleted file mode 100644 index 2e91f18d2b..0000000000 --- a/Remapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sun, 21 Jun 2015 15:07:20 -0400 -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 d483d552092c901fec262c43e488784d9cd8acb9..3c707ca6b56e89b671db6316d4db90a2903f33b4 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3202,9 +3202,10 @@ public abstract class LivingEntity extends Entity { - this.triggerItemUseEffects(this.useItem, 16); - // CraftBukkit start - fire PlayerItemConsumeEvent - ItemStack itemstack; -+ PlayerItemConsumeEvent event = null; // Paper - if (this instanceof ServerPlayer) { - org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.useItem); -- PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); -+ event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); // Paper - level.getCraftServer().getPluginManager().callEvent(event); - - if (event.isCancelled()) { -@@ -3218,6 +3219,13 @@ public abstract class LivingEntity extends Entity { - } else { - itemstack = this.useItem.finishUsingItem(this.level, this); - } -+ -+ // Paper start - save the default replacement item and change it if necessary -+ final ItemStack defaultReplacement = itemstack; -+ if (event != null && event.getReplacement() != null) { -+ itemstack = CraftItemStack.asNMSCopy(event.getReplacement()); -+ } -+ // Paper end - // CraftBukkit end - - if (itemstack != this.useItem) { -@@ -3225,6 +3233,11 @@ public abstract class LivingEntity extends Entity { - } - - this.stopUsingItem(); -+ // Paper start - if the replacement is anything but the default, update the client inventory -+ if (this instanceof ServerPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { -+ ((ServerPlayer) this).getBukkitEntity().updateInventory(); -+ } -+ // Paper end - } - - } diff --git a/Remapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/Remapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch deleted file mode 100644 index 0d5d5d19aa..0000000000 --- a/Remapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 27 Sep 2015 01:18:02 -0400 -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 3c707ca6b56e89b671db6316d4db90a2903f33b4..a326e5b4ac055f2f8a95c6eaccd8d0a97762da1f 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -699,7 +699,13 @@ public abstract class LivingEntity extends Entity { - - @Override - public void readAdditionalSaveData(CompoundTag tag) { -- this.setAbsorptionAmount(tag.getFloat("AbsorptionAmount")); -+ // Paper start - jvm keeps optimizing the setter -+ float absorptionAmount = tag.getFloat("AbsorptionAmount"); -+ if (Float.isNaN(absorptionAmount)) { -+ absorptionAmount = 0; -+ } -+ this.setAbsorptionAmount(absorptionAmount); -+ // Paper end - if (tag.contains("Attributes", 9) && this.level != null && !this.level.isClientSide) { - this.getAttributes().load(tag.getList("Attributes", 10)); - } -@@ -1148,6 +1154,10 @@ public abstract class LivingEntity extends Entity { - } - - public void setHealth(float health) { -+ // Paper start -+ if (Float.isNaN(health)) { health = getMaxHealth(); if (this.valid) { -+ System.err.println("[NAN-HEALTH] " + getScoreboardName() + " had NaN health set"); -+ } } // Paper end - // CraftBukkit start - Handle scaled health - if (this instanceof ServerPlayer) { - org.bukkit.craftbukkit.entity.CraftPlayer player = ((ServerPlayer) this).getBukkitEntity(); -@@ -3042,7 +3052,7 @@ public abstract class LivingEntity extends Entity { - } - - public void setAbsorptionAmount(float amount) { -- if (amount < 0.0F) { -+ if (amount < 0.0F || Float.isNaN(amount)) { // Paper - amount = 0.0F; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index dd29038778d73fae84df360515f3c670915f1d48..b7d5a718375083a4162df4bb41de3acd57b297fb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1678,6 +1678,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void setRealHealth(double health) { -+ if (Double.isNaN(health)) {return;} // Paper - this.health = health; - } - diff --git a/Remapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch b/Remapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch deleted file mode 100644 index ddca7a2d46..0000000000 --- a/Remapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 22 Mar 2016 00:33:47 -0400 -Subject: [PATCH] Use a Shared Random for Entities - -Reduces memory usage and provides ensures more randomness, Especially since a lot of garbage entity objects get created. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 93d3408231a177cf6d2086594756adffe3efa702..61048140cf0adca03bfb57193ada0adaee73b1bb 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -142,6 +142,21 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; - } - -+ // Paper start -+ public static Random SHARED_RANDOM = new Random() { -+ private boolean locked = false; -+ @Override -+ public synchronized void setSeed(long seed) { -+ if (locked) { -+ LogManager.getLogger().error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable()); -+ } else { -+ super.setSeed(seed); -+ locked = true; -+ } -+ } -+ }; -+ // Paper end -+ - private CraftEntity bukkitEntity; - - public CraftEntity getBukkitEntity() { -@@ -271,7 +286,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.stuckSpeedMultiplier = Vec3.ZERO; - this.nextStep = 1.0F; - this.nextFlap = 1.0F; -- this.random = new Random(); -+ this.random = SHARED_RANDOM; // Paper - this.remainingFireTicks = -this.getFireImmuneTicks(); - this.fluidHeight = new Object2DoubleArrayMap(2); - this.firstTick = true; diff --git a/Remapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch b/Remapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch deleted file mode 100644 index 59b6c7f72a..0000000000 --- a/Remapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 22 Mar 2016 12:04:28 -0500 -Subject: [PATCH] Configurable spawn chances for skeleton horses - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3c78d3234054ce2dc46ef77decb6adb0cbd10620..cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -230,4 +230,12 @@ public class PaperWorldConfig { - log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); - log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); - } -+ -+ public double skeleHorseSpawnChance; -+ private void skeleHorseSpawnChance() { -+ skeleHorseSpawnChance = getDouble("skeleton-horse-thunder-spawn-chance", 0.01D); -+ if (skeleHorseSpawnChance < 0) { -+ skeleHorseSpawnChance = 0.01D; // Vanilla value -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index e1f9a12c7fb4818a785b9a4819f94fccde02b6a2..22c687e3db79bcfbc512ce3993d6e8a6db062360 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -584,7 +584,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); - if (this.isRainingAt(blockposition)) { - DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); -- boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * 0.01D; -+ boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance; // Paper - - if (flag1) { - SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create((net.minecraft.world.level.Level) this); diff --git a/Remapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/Remapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch deleted file mode 100644 index 2c0ed8f7cd..0000000000 --- a/Remapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch +++ /dev/null @@ -1,206 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 02:07:55 -0600 -Subject: [PATCH] Optimize isValidLocation, getType and getBlockData for - inlining - -Hot methods, so reduce # of instructions for the method. - -Move is valid location test to the BlockPosition class so that it can access local variables. - -Replace all calls to the new place to the unnecessary forward. - -Optimize getType and getBlockData to manually inline and optimize the calls - -diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java -index 3e79b274b8e0406a3cbdd94c7cec091b583109ca..c22de593be404c4e921724bba6a69c13759a95fd 100644 ---- a/src/main/java/net/minecraft/core/Vec3i.java -+++ b/src/main/java/net/minecraft/core/Vec3i.java -@@ -22,6 +22,15 @@ public class Vec3i implements Comparable { - private int y;public final void setY(final int y) { this.y = y; } // Paper - OBFHELPER - private int z;public final void setZ(final int z) { this.z = z; } // Paper - OBFHELPER - -+ // Paper start -+ public boolean isValidLocation() { -+ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && getY() >= 0 && getY() < 256; -+ } -+ public boolean isInvalidYLocation() { -+ return y < 0 || y >= 256; -+ } -+ // Paper end -+ - public Vec3i(int x, int y, int z) { - this.x = x; - this.y = y; -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 799721ac63f0c08dd03a788b87eafa9a8cc976cc..24a6429059f58f51c97386ca2823ca0910288dec 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -239,7 +239,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - - public static boolean isInWorldBounds(BlockPos pos) { -- return !isOutsideBuildHeight(pos) && isInWorldBoundsHorizontal(pos); -+ return pos.isValidLocation(); // Paper - use better/optimized check - } - - public static boolean isInSpawnableBounds(BlockPos pos) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -index 3ca6289ba4952b5036367451b50cd90a78c0f938..e6303cdb433ee2b6782e2a0bd6b03e4f6ecb18ba 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -@@ -25,6 +25,7 @@ import org.apache.logging.log4j.LogManager; - - public interface ChunkAccess extends BlockGetter, FeatureAccess { - -+ BlockState getType(final int x, final int y, final int z); // Paper - @Nullable - BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); - -diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java -index a26de06252207cf333ea4a8d73f0af6ddc239103..e369730ac6909ff5343468bd685c9ea2b6b3cfed 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java -@@ -23,7 +23,7 @@ import net.minecraft.world.phys.AABB; - - public class EmptyLevelChunk extends LevelChunk { - -- private static final Biome[] BIOMES = (Biome[]) Util.make((Object) (new Biome[ChunkBiomeContainer.BIOMES_SIZE]), (abiomebase) -> { -+ private static final Biome[] BIOMES = Util.make((new Biome[ChunkBiomeContainer.BIOMES_SIZE]), (abiomebase) -> { // Paper - decompile error - Arrays.fill(abiomebase, Biomes.PLAINS); - }); - -@@ -31,6 +31,11 @@ public class EmptyLevelChunk extends LevelChunk { - super(world, pos, new ChunkBiomeContainer(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), EmptyLevelChunk.BIOMES)); - } - -+ // Paper start -+ @Override public BlockState getType(int x, int y, int z) { -+ return Blocks.VOID_AIR.defaultBlockState(); -+ } -+ // Paper end - @Override - public BlockState getBlockState(BlockPos pos) { - return Blocks.VOID_AIR.defaultBlockState(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -index 04940ab2814cf39157d234dc4615646d7c760460..17fa8b23d1000ae53f2b4f1a6e8817c1005c1c81 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -@@ -42,6 +42,11 @@ public class ImposterProtoChunk extends ProtoChunk { - public BlockState getBlockState(BlockPos pos) { - return this.wrapped.getBlockState(pos); - } -+ // Paper start -+ public final BlockState getType(final int x, final int y, final int z) { -+ return this.wrapped.getBlockData(x, y, z); -+ } -+ // Paper end - - @Override - public FluidState getFluidState(BlockPos pos) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 9ca05aa06696883adc8b67a68ca6d2d850e95d25..546fb2f42e6bf333582b504d0a29991698505df3 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -347,12 +347,27 @@ public class LevelChunk implements ChunkAccess { - return this.sections; - } - -- @Override -+ // Paper start - Optimize getBlockData to reduce instructions -+ public final BlockState getBlockData(BlockPos pos) { return getBlockData(pos.getX(), pos.getY(), pos.getZ()); } // Paper - public BlockState getBlockState(BlockPos pos) { -- int i = pos.getX(); -- int j = pos.getY(); -- int k = pos.getZ(); -+ return this.getBlockData(pos.getX(), pos.getY(), pos.getZ()); -+ } - -+ public BlockState getType(final int x, final int y, final int z) { -+ return getBlockData(x, y, z); -+ } -+ public final BlockState getBlockData(final int x, final int y, final int z) { -+ // Method body / logic copied from below -+ final int i = y >> 4; -+ if (y < 0 || i >= this.sections.length || this.sections[i] == null || this.sections[i].nonEmptyBlockCount == 0) { -+ return Blocks.AIR.defaultBlockState(); -+ } -+ // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) -+ return this.sections[i].states.get((y & 15) << 8 | (z & 15) << 4 | x & 15); -+ } -+ -+ public BlockState getBlockData_unused(int i, int j, int k) { -+ // Paper end - if (this.world.isDebug()) { - BlockState iblockdata = null; - -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index b54d82e0f41a03c91e0de8df8249a91da3c04d0e..f5db97fb0dac78e1d9aa68d0417aa13f39914f52 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -13,10 +13,10 @@ public class LevelChunkSection { - - public static final Palette GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState()); - private final int bottomBlockY; -- private short nonEmptyBlockCount; -+ short nonEmptyBlockCount; // Paper - package-private - private short tickingBlockCount; - private short tickingFluidCount; -- private final PalettedContainer states; -+ final PalettedContainer states; // Paper - package-private - - public LevelChunkSection(int yOffset) { - this(yOffset, (short) 0, (short) 0, (short) 0); -@@ -30,8 +30,8 @@ public class LevelChunkSection { - this.states = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); - } - -- public BlockState getBlockState(int x, int y, int z) { -- return (BlockState) this.states.get(x, y, z); -+ public final BlockState getBlockState(int x, int y, int z) { // Paper -+ return this.states.get(y << 8 | z << 4 | x); // Paper - inline - } - - public FluidState getFluidState(int x, int y, int z) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index d4db27421736f665739436c1ac4d3c6d5cae95cd..6d3dcd19ce1abc9d502903b8008949b5174a13c3 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -133,7 +133,7 @@ public class PalettedContainer implements PaletteResize { - } - - public T get(int x, int y, int z) { -- return this.get(getIndex(x, y, z)); -+ return this.get(y << 8 | z << 4 | x); // Paper - inline - } - - protected T get(int index) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 7cd3f89004b0a64772fc3dfbdd132ba5a850b63e..d8b7b210484079c9ca2c34831c84102cba6692f5 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -113,16 +113,18 @@ public class ProtoChunk implements ChunkAccess { - - @Override - public BlockState getBlockState(BlockPos pos) { -- int i = pos.getY(); -- -- if (Level.isOutsideBuildHeight(i)) { -+ return getType(pos.getX(), pos.getY(), pos.getZ()); -+ } -+ // Paper start -+ public BlockState getType(final int x, final int y, final int z) { -+ if (y < 0 || y >= 256) { - return Blocks.VOID_AIR.defaultBlockState(); - } else { -- LevelChunkSection chunksection = this.getSections()[i >> 4]; -- -- return LevelChunkSection.isEmpty(chunksection) ? Blocks.AIR.defaultBlockState() : chunksection.getBlockState(pos.getX() & 15, i & 15, pos.getZ() & 15); -+ LevelChunkSection chunksection = this.getSections()[y >> 4]; -+ return chunksection == LevelChunk.EMPTY_CHUNK_SECTION || chunksection.isEmpty() ? Blocks.AIR.defaultBlockState() : chunksection.getBlockState(x & 15, y & 15, z & 15); - } - } -+ // Paper end - - @Override - public FluidState getFluidState(BlockPos pos) { diff --git a/Remapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/Remapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch deleted file mode 100644 index 1bc2cb3b6f..0000000000 --- a/Remapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 19:55:45 -0400 -Subject: [PATCH] Only process BlockPhysicsEvent if a plugin has a listener - -Saves on some object allocation and processing when no plugin listens to this - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 901d5497667706c049718dc4fca37a1bc489c465..f7763a773bce4d8d947c8c859fe84d8a601034c5 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1290,6 +1290,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper - - this.profiler.push(() -> { - return worldserver + " " + worldserver.dimension().location(); -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 22c687e3db79bcfbc512ce3993d6e8a6db062360..8b0a384caa09848d61b3a6259dd56590cd52d0a0 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -190,6 +190,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - private int tickPosition; - public final LevelStorageSource.LevelStorageAccess convertable; - public final UUID uuid; -+ public boolean hasPhysicsEvent = true; // Paper - - @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkSource.getChunk(x, z, false); -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 24a6429059f58f51c97386ca2823ca0910288dec..d47ed15382f98aabd509e32a3c202a91088adf6b 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -458,7 +458,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - // CraftBukkit start - iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam - CraftWorld world = ((ServerLevel) this).getWorld(); -- if (world != null) { -+ if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); - this.getCraftServer().getPluginManager().callEvent(event); - -@@ -560,7 +560,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - try { - // CraftBukkit start - CraftWorld world = ((ServerLevel) this).getWorld(); -- if (world != null) { -+ if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(sourcePos.getX(), sourcePos.getY(), sourcePos.getZ()), CraftBlockData.fromData(iblockdata), world.getBlockAt(neighborPos.getX(), neighborPos.getY(), neighborPos.getZ())); - this.getCraftServer().getPluginManager().callEvent(event); - -diff --git a/src/main/java/net/minecraft/world/level/block/BushBlock.java b/src/main/java/net/minecraft/world/level/block/BushBlock.java -index d6cb341d4d8e20b77979a241dd2e4346455796d7..42635b6115187abeffb290ca040350fd97cf89f7 100644 ---- a/src/main/java/net/minecraft/world/level/block/BushBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/BushBlock.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; - - import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.level.BlockGetter; - import net.minecraft.world.level.LevelAccessor; - import net.minecraft.world.level.LevelReader; -@@ -23,7 +24,7 @@ public class BushBlock extends Block { - public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { - // CraftBukkit start - if (!state.canSurvive(world, pos)) { -- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { -+ if (!(world instanceof ServerLevel && ((ServerLevel) world).hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper - return Blocks.AIR.defaultBlockState(); - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java -index db444689092f537dd736dc73c532bd540fadcf86..86c5025d1b21dc35782124eca66288c63626147a 100644 ---- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java -@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; -@@ -83,7 +84,7 @@ public class DoublePlantBlock extends BushBlock { - - protected static void preventCreativeDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) { - // CraftBukkit start -- if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { -+ if (((ServerLevel)world).hasPhysicsEvent && org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper - return; - } - // CraftBukkit end diff --git a/Remapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch b/Remapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch deleted file mode 100644 index 0b9b2867e9..0000000000 --- a/Remapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:32:58 -0400 -Subject: [PATCH] Entity AddTo/RemoveFrom World Events - - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 8b0a384caa09848d61b3a6259dd56590cd52d0a0..f7eddb39985072afeb79ec0cbfc084d7e84638e6 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1208,7 +1208,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - if (entity instanceof Mob) { - this.navigations.remove(((Mob) entity).getNavigation()); - } -- -+ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - entity.valid = false; // CraftBukkit - } - -@@ -1246,6 +1246,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - entity.origin = entity.getBukkitEntity().getLocation(); - } - // Paper end -+ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - } - - } diff --git a/Remapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch b/Remapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch deleted file mode 100644 index 126102b49a..0000000000 --- a/Remapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:46:14 -0400 -Subject: [PATCH] Configurable Chunk Inhabited Time - -Vanilla stores how long a chunk has been active on a server, and dynamically scales some -aspects of vanilla gameplay to this factor. - -For people who want all chunks to be treated equally, you can chose a fixed value. - -This allows to fine-tune vanilla gameplay. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0..74ba5dbb83c13ce1721619b755036a7864a1fb90 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -238,4 +238,14 @@ public class PaperWorldConfig { - skeleHorseSpawnChance = 0.01D; // Vanilla value - } - } -+ -+ public int fixedInhabitedTime; -+ private void fixedInhabitedTime() { -+ if (PaperConfig.version < 16) { -+ if (!config.getBoolean("world-settings.default.use-chunk-inhabited-timer", true)) config.set("world-settings.default.fixed-chunk-inhabited-time", 0); -+ if (!config.getBoolean("world-settings." + worldName + ".use-chunk-inhabited-timer", true)) config.set("world-settings." + worldName + ".fixed-chunk-inhabited-time", 0); -+ set("use-chunk-inhabited-timer", null); -+ } -+ fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 546fb2f42e6bf333582b504d0a29991698505df3..70f5b025c2b803df3de8a51cbcfafbe915866f42 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -1021,7 +1021,7 @@ public class LevelChunk implements ChunkAccess { - - @Override - public long getInhabitedTime() { -- return this.inhabitedTime; -+ return world.paperConfig.fixedInhabitedTime < 0 ? this.inhabitedTime : world.paperConfig.fixedInhabitedTime; // Paper - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch b/Remapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch deleted file mode 100644 index e784dacc5f..0000000000 --- a/Remapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 21:22:26 -0400 -Subject: [PATCH] EntityPathfindEvent - -Fires when an Entity decides to start moving to a location. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java -index 0af2c5dde41043a6fb2fcd07db96288c7f96e0c7..5e7e678c4469e34c7ae39656f547243fbcf1d0da 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java -@@ -37,7 +37,7 @@ public class FlyingPathNavigation extends PathNavigation { - - @Override - public Path createPath(Entity entity, int distance) { -- return this.createPath(entity.blockPosition(), distance); -+ return this.a(entity.blockPosition(), entity, distance); // Paper - Forward target entity - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java -index cd7cb7cbe55a36282de394efc95f4ba7cc6a75cf..01be1de9d9ca0a86d69b2e82693bd0fea61a969f 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java -@@ -75,7 +75,7 @@ public class GroundPathNavigation extends PathNavigation { - - @Override - public Path createPath(Entity entity, int distance) { -- return this.createPath(entity.blockPosition(), distance); -+ return this.a(entity.blockPosition(), entity, distance); // Paper - Forward target entity - } - - private int getSurfaceY() { -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index 3cfd913e31236e35e7225ba19d292cacb8b4134a..ae8d430382b20ddd837c47e39515c7995f25312a 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -10,6 +10,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Position; - import net.minecraft.core.Vec3i; - import net.minecraft.network.protocol.game.DebugPackets; -+import net.minecraft.server.MCUtil; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.Mob; -@@ -28,7 +29,7 @@ import net.minecraft.world.phys.Vec3; - - public abstract class PathNavigation { - -- protected final Mob mob; -+ protected final Mob mob; public Entity getEntity() { return mob; } // Paper - OBFHELPER - protected final Level level; - @Nullable - protected Path path; -@@ -115,36 +116,63 @@ public abstract class PathNavigation { - - @Nullable - public Path createPath(BlockPos target, int distance) { -- return this.createPath(ImmutableSet.of(target), 8, false, distance); -+ // Paper start - add target parameter -+ return this.a(target, null, distance); -+ } -+ @Nullable public Path a(BlockPos blockposition, Entity target, int i) { -+ return this.a(ImmutableSet.of(blockposition), target, 8, false, i); -+ // Paper end - } - - @Nullable - public Path createPath(Entity entity, int distance) { -- return this.createPath(ImmutableSet.of(entity.blockPosition()), 16, true, distance); -+ return this.a(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper - } - - @Nullable -+ // Paper start - Add target - protected Path createPath(Set positions, int range, boolean flag, int distance) { -- if (positions.isEmpty()) { -+ return this.a(positions, null, range, flag, distance); -+ } -+ @Nullable protected Path a(Set set, Entity target, int i, boolean flag, int j) { -+ // Paper end -+ if (set.isEmpty()) { - return null; - } else if (this.mob.getY() < 0.0D) { - return null; - } else if (!this.canUpdatePath()) { - return null; -- } else if (this.path != null && !this.path.isDone() && positions.contains(this.targetPos)) { -+ } else if (this.path != null && !this.path.isDone() && set.contains(this.targetPos)) { - return this.path; - } else { -+ // Paper start - Pathfind event -+ boolean copiedSet = false; -+ for (BlockPos possibleTarget : set) { -+ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), -+ MCUtil.toLocation(getEntity().level, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { -+ if (!copiedSet) { -+ copiedSet = true; -+ set = new java.util.HashSet<>(set); -+ } -+ // note: since we copy the set this remove call is safe, since we're iterating over the old copy -+ set.remove(possibleTarget); -+ if (set.isEmpty()) { -+ return null; -+ } -+ } -+ } -+ // Paper end - this.level.getProfiler().push("pathfind"); - float f = (float) this.mob.getAttributeValue(Attributes.FOLLOW_RANGE); - BlockPos blockposition = flag ? this.mob.blockPosition().above() : this.mob.blockPosition(); -- int k = (int) (f + (float) range); -+ int k = (int) (f + (float) i); - PathNavigationRegion chunkcache = new PathNavigationRegion(this.level, blockposition.offset(-k, -k, -k), blockposition.offset(k, k, k)); -- Path pathentity = this.pathFinder.findPath(chunkcache, this.mob, positions, f, distance, this.maxVisitedNodesMultiplier); -+ Path pathentity = this.pathFinder.findPath(chunkcache, this.mob, set, f, j, this.maxVisitedNodesMultiplier); - - this.level.getProfiler().pop(); - if (pathentity != null && pathentity.getTarget() != null) { - this.targetPos = pathentity.getTarget(); -- this.reachRange = distance; -+ this.reachRange = j; - this.resetStuckTimeout(); - } - diff --git a/Remapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch b/Remapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch deleted file mode 100644 index 95fc3262c8..0000000000 --- a/Remapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Antony Riley -Date: Tue, 29 Mar 2016 08:22:55 +0300 -Subject: [PATCH] Sanitise RegionFileCache and make configurable. - -RegionFileCache prior to this patch would close every single open region -file upon reaching a size of 256. -This patch modifies that behaviour so it closes the the least recently -used RegionFile. -The implementation uses a LinkedHashMap as an LRU cache (modified from HashMap). -The maximum size of the RegionFileCache is also made configurable. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 716f285e67019b8a62922d09c15883c99f9421aa..439dcc6effdc91830d2b7ede9063982998b37120 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -227,4 +227,9 @@ public class PaperConfig { - private static void loadPermsBeforePlugins() { - loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); - } -+ -+ public static int regionFileCacheSize = 256; -+ private static void regionFileCacheSize() { -+ regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 97a58da9d64d812942ceb71426d35b490bbbe817..f33a5fc725d1d5e895f8878d82ebc4172237ad29 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -33,7 +33,7 @@ public final class RegionFileStorage implements AutoCloseable { - if (regionfile != null) { - return regionfile; - } else { -- if (this.regionCache.size() >= 256) { -+ if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable - ((RegionFile) this.regionCache.removeLast()).close(); - } - diff --git a/Remapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch b/Remapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch deleted file mode 100644 index dcc5c72d1e..0000000000 --- a/Remapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 31 Mar 2016 19:17:58 -0400 -Subject: [PATCH] Do not load chunks for Pathfinding - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index ae8d430382b20ddd837c47e39515c7995f25312a..25bc3adfad956157cef0953e6e632b7b7e352f3a 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -48,7 +48,7 @@ public abstract class PathNavigation { - private BlockPos targetPos; - private int reachRange; - private float maxVisitedNodesMultiplier; -- private final PathFinder pathFinder; -+ private final PathFinder pathFinder; public PathFinder getPathfinder() { return this.pathFinder; } // Paper - OBFHELPER - private boolean isStuck; - - public PathNavigation(Mob mob, Level world) { -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -index 99f3f0b895295229b75d93e98141c0cd75789b69..ba8ee93032aabe7ec4ecf52d452e1a580d6ebc20 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -@@ -20,7 +20,7 @@ public class PathFinder { - - private final Node[] neighbors = new Node[32]; - private final int maxVisitedNodes; -- private final NodeEvaluator nodeEvaluator; -+ private final NodeEvaluator nodeEvaluator; public NodeEvaluator getPathfinder() { return this.nodeEvaluator; } // Paper - OBFHELPER - private final BinaryHeap openSet = new BinaryHeap(); - - public PathFinder(NodeEvaluator pathNodeMaker, int range) { -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java -index 0b378348cb9e9576e2a209e651264e2caccfd182..7ae24381b91c282745b7fe5f6897865e74bc0acf 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java -@@ -479,7 +479,12 @@ public class WalkNodeEvaluator extends NodeEvaluator { - for (int j1 = -1; j1 <= 1; ++j1) { - if (l != 0 || j1 != 0) { - blockposition_mutableblockposition.set(i + l, j + i1, k + j1); -- BlockState iblockdata = iblockaccess.getBlockState(blockposition_mutableblockposition); -+ // Paper start -+ BlockState iblockdata = iblockaccess.getTypeIfLoaded(blockposition_mutableblockposition); -+ if (iblockdata == null) { -+ pathtype = BlockPathTypes.BLOCKED; -+ } else { -+ // Paper end - - if (iblockdata.is(Blocks.CACTUS)) { - return BlockPathTypes.DANGER_CACTUS; -@@ -496,6 +501,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { - if (iblockaccess.getFluidState(blockposition_mutableblockposition).is((Tag) FluidTags.WATER)) { - return BlockPathTypes.WATER_BORDER; - } -+ } // Paper - } - } - } -@@ -505,7 +511,8 @@ public class WalkNodeEvaluator extends NodeEvaluator { - } - - protected static BlockPathTypes getBlockPathTypeRaw(BlockGetter iblockaccess, BlockPos blockposition) { -- BlockState iblockdata = iblockaccess.getBlockState(blockposition); -+ BlockState iblockdata = iblockaccess.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return BlockPathTypes.BLOCKED; // Paper - Block block = iblockdata.getBlock(); - Material material = iblockdata.getMaterial(); - diff --git a/Remapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch b/Remapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch deleted file mode 100644 index c91bb4d9ec..0000000000 --- a/Remapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 2 Apr 2016 05:09:16 -0400 -Subject: [PATCH] Add PlayerUseUnknownEntityEvent - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java -index 9ff5b938f97da5ca1f13fd2bcbf3d13e8b8f760c..e1d219550006d22b0a8e949e820488c6ed96dc58 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java -@@ -11,7 +11,7 @@ import net.minecraft.world.phys.Vec3; - - public class ServerboundInteractPacket implements Packet { - -- private int entityId; -+ private int entityId; public int getEntityId() { return this.entityId; } // Paper - add accessor - private ServerboundInteractPacket.Action action; - private Vec3 location; - private InteractionHand hand; -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 73683ba59d0aff3a61f555b4ae15753e9e4e6141..e2bfe8e916c9e59af81627ea0ee449970527034d 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2198,6 +2198,16 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } - } - } -+ // Paper start - fire event -+ else { -+ this.craftServer.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( -+ this.getPlayer(), -+ packet.getEntityId(), -+ packet.getAction() == ServerboundInteractPacket.Action.ATTACK, -+ packet.getHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND -+ )); -+ } -+ // Paper end - - } - diff --git a/Remapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch b/Remapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch deleted file mode 100644 index d10d109cb2..0000000000 --- a/Remapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 2 Apr 2016 20:37:03 -0400 -Subject: [PATCH] Fix reducedDebugInfo not initialized on client - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index a63babe123fad398b07685ec57cd88756435457c..aa440a6341a6d30aba8fd5f6bcd122bd5d8760cd 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -242,6 +242,7 @@ public abstract class PlayerList { - playerconnection.send(new ClientboundSetCarriedItemPacket(player.inventory.selected)); - playerconnection.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); - playerconnection.send(new ClientboundUpdateTagsPacket(this.server.getTags())); -+ playerconnection.send(new ClientboundEntityEventPacket(player, (byte) (worldserver1.getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23))); // Paper - fix this rule not being initialized on the client - this.sendPlayerPermissionLevel(player); - player.getStats().markAllDirty(); - player.getRecipeBook().sendInitialRecipeBook(player); diff --git a/Remapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch b/Remapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch deleted file mode 100644 index 8481cb94a1..0000000000 --- a/Remapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 Apr 2016 16:28:17 -0400 -Subject: [PATCH] Configurable Grass Spread Tick Rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 74ba5dbb83c13ce1721619b755036a7864a1fb90..db2dddd12f54e6d15916c4cee623676541de37fb 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -248,4 +248,10 @@ public class PaperWorldConfig { - } - fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); - } -+ -+ public int grassUpdateRate = 1; -+ private void grassUpdateRate() { -+ grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); -+ log("Grass Spread Tick Rate: " + grassUpdateRate); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java -index d54f097afc455a01486d7f7459b0cfc4ab4f3970..813a5b0598eca28aa173cd6e34bc16381f313604 100644 ---- a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java -@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; - import java.util.Random; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.tags.FluidTags; - import net.minecraft.tags.Tag; -@@ -41,6 +42,7 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock { - - @Override - public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) { -+ if (this instanceof GrassBlock && world.paperConfig.grassUpdateRate != 1 && (world.paperConfig.grassUpdateRate < 1 || (MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig.grassUpdateRate != 0)) { return; } // Paper - if (!canBeGrass(state, (LevelReader) world, pos)) { - // CraftBukkit start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { diff --git a/Remapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/Remapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch deleted file mode 100644 index 5d706f6263..0000000000 --- a/Remapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 Apr 2016 17:48:50 -0400 -Subject: [PATCH] Fix Cancelling BlockPlaceEvent triggering physics - - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index d47ed15382f98aabd509e32a3c202a91088adf6b..89a6a0b4235cfcc1d3ad68ff59a21fa60df4508f 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -518,6 +518,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public void setBlocksDirty(BlockPos pos, BlockState old, BlockState updated) {} - - public void updateNeighborsAt(BlockPos pos, Block block) { -+ if (captureBlockStates) { return; } // Paper - Cancel all physics during placement - this.neighborChanged(pos.west(), block, pos); - this.neighborChanged(pos.east(), block, pos); - this.neighborChanged(pos.below(), block, pos); diff --git a/Remapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch b/Remapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch deleted file mode 100644 index 7b5057a4e9..0000000000 --- a/Remapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Apr 2016 21:38:58 -0400 -Subject: [PATCH] Optimize DataBits - -Remove Debug checks as these are super hot and causing noticeable hits - -Before: http://i.imgur.com/nQsMzAE.png -After: http://i.imgur.com/nJ46crB.png - -Optimize redundant converting of static fields into an unsigned long each call by precomputing it in ctor - -diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java -index 97bde5f8402452e59b0da94edfe1b970cdb86748..dd84984f28484cf7129c294222696784e128221a 100644 ---- a/src/main/java/net/minecraft/util/BitStorage.java -+++ b/src/main/java/net/minecraft/util/BitStorage.java -@@ -13,8 +13,8 @@ public class BitStorage { - private final long mask; - private final int size; - private final int valuesPerLong; -- private final int divideMul; -- private final int divideAdd; -+ private final int divideMul;private final long g_unsigned; // Paper - referenced in b(int) with 2 Integer.toUnsignedLong calls -+ private final int divideAdd;private final long h_unsigned; // Paper - private final int divideShift; - - public BitStorage(int elementBits, int size) { -@@ -29,8 +29,8 @@ public class BitStorage { - this.valuesPerLong = (char) (64 / elementBits); - int k = 3 * (this.valuesPerLong - 1); - -- this.divideMul = BitStorage.MAGIC[k + 0]; -- this.divideAdd = BitStorage.MAGIC[k + 1]; -+ this.divideMul = BitStorage.MAGIC[k + 0]; this.g_unsigned = Integer.toUnsignedLong(this.divideMul); // Paper -+ this.divideAdd = BitStorage.MAGIC[k + 1]; this.h_unsigned = Integer.toUnsignedLong(this.divideAdd); // Paper - this.divideShift = BitStorage.MAGIC[k + 2]; - int l = (size + this.valuesPerLong - 1) / this.valuesPerLong; - -@@ -47,15 +47,15 @@ public class BitStorage { - } - - private int cellIndex(int i) { -- long j = Integer.toUnsignedLong(this.divideMul); -- long k = Integer.toUnsignedLong(this.divideAdd); -+ //long j = Integer.toUnsignedLong(this.g); // Paper -+ //long k = Integer.toUnsignedLong(this.h); // Paper - -- return (int) ((long) i * j + k >> 32 >> this.divideShift); -+ return (int) ((long) i * this.g_unsigned + this.h_unsigned >> 32 >> this.divideShift); // Paper - } - -- public int getAndSet(int index, int value) { -- Validate.inclusiveBetween(0L, (long) (this.size - 1), (long) index); -- Validate.inclusiveBetween(0L, this.mask, (long) value); -+ public final int getAndSet(int index, int value) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper -+ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper - int k = this.cellIndex(index); - long l = this.data[k]; - int i1 = (index - k * this.valuesPerLong) * this.bits; -@@ -65,9 +65,9 @@ public class BitStorage { - return j1; - } - -- public void set(int index, int value) { -- Validate.inclusiveBetween(0L, (long) (this.size - 1), (long) index); -- Validate.inclusiveBetween(0L, this.mask, (long) value); -+ public final void set(int index, int value) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper -+ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper - int k = this.cellIndex(index); - long l = this.data[k]; - int i1 = (index - k * this.valuesPerLong) * this.bits; -@@ -75,8 +75,8 @@ public class BitStorage { - this.data[k] = l & ~(this.mask << i1) | ((long) value & this.mask) << i1; - } - -- public int get(int index) { -- Validate.inclusiveBetween(0L, (long) (this.size - 1), (long) index); -+ public final int get(int index) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper - int j = this.cellIndex(index); - long k = this.data[j]; - int l = (index - j * this.valuesPerLong) * this.bits; diff --git a/Remapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/Remapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch deleted file mode 100644 index ac90c24b3a..0000000000 --- a/Remapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 6 Apr 2016 01:04:23 -0500 -Subject: [PATCH] Option to use vanilla per-world scoreboard coloring on names - -This change is basically a bandaid to fix CB's complete and utter lack -of support for vanilla scoreboard name modifications. - -In the future, finding a way to merge the vanilla expectations in with -bukkit's concept of a display name would be preferable. There was a PR -for this on CB at one point but I can't find it. We may need to do this -ourselves at some point in the future. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index db2dddd12f54e6d15916c4cee623676541de37fb..1942f5224aaebb18adb591d6f70a419cfc1a7bdd 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -254,4 +254,9 @@ public class PaperWorldConfig { - grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); - log("Grass Spread Tick Rate: " + grassUpdateRate); - } -+ -+ public boolean useVanillaScoreboardColoring; -+ private void useVanillaScoreboardColoring() { -+ useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); -+ } - } -diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -index a29b6aaafd529e56a83dd96c32211f21e4aad348..2039f83a718427d0969a1a2e2200f7922097449e 100644 ---- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -@@ -16,7 +16,11 @@ import net.kyori.adventure.text.TextReplacementConfig; - import net.kyori.adventure.text.event.ClickEvent; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.world.scores.PlayerTeam; -+import net.minecraft.world.scores.Team; - import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; -+import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.craftbukkit.util.LazyPlayerSet; - import org.bukkit.craftbukkit.util.Waitable; -@@ -178,10 +182,22 @@ public final class ChatProcessor { - } - - private static String legacyDisplayName(final CraftPlayer player) { -+ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { -+ final ServerPlayer ep = player.getHandle(); -+ net.minecraft.network.chat.Component name = ep.getName(); -+ final Team team = ep.getTeam(); -+ if (team != null) { -+ name = team.getFormattedName(name); -+ } -+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(PaperAdventure.asAdventure(name)) + ChatColor.RESET; -+ } - return player.getDisplayName(); - } - - private static Component displayName(final CraftPlayer player) { -+ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { -+ return PaperAdventure.asAdventure(PlayerTeam.formatNameForTeam(player.getHandle().getTeam(), player.getHandle().getName())); -+ } - return player.displayName(); - } - diff --git a/Remapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch b/Remapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch deleted file mode 100644 index c2fdc7667a..0000000000 --- a/Remapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 10 Apr 2016 03:23:32 -0500 -Subject: [PATCH] Workaround for setting passengers on players - -SPIGOT-1915 & GH-114 - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b7d5a718375083a4162df4bb41de3acd57b297fb..b264cbe5f91da9e31c5fd00ee285735a19aaad35 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -870,6 +870,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return true; - } - -+ // Paper start - Ugly workaround for SPIGOT-1915 & GH-114 -+ @Override -+ public boolean setPassenger(org.bukkit.entity.Entity passenger) { -+ boolean wasSet = super.setPassenger(passenger); -+ if (wasSet) { -+ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSetPassengersPacket(this.getHandle())); -+ } -+ return wasSet; -+ } -+ // Paper end -+ - @Override - public void setSneaking(boolean sneak) { - getHandle().setShiftKeyDown(sneak); diff --git a/Remapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch b/Remapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch deleted file mode 100644 index d96a9f686a..0000000000 --- a/Remapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 Apr 2016 00:25:28 -0400 -Subject: [PATCH] Remove unused World Tile Entity List - -Massive hit to performance and it is completely unnecessary. - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index f7eddb39985072afeb79ec0cbfc084d7e84638e6..bb99d9fe5e274318d8480a6de2c45b0a57351f77 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1715,7 +1715,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - bufferedwriter.write(String.format("entities: %d\n", this.entitiesById.size())); -- bufferedwriter.write(String.format("block_entities: %d\n", this.blockEntityList.size())); -+ bufferedwriter.write(String.format("block_entities: %d\n", this.tickableBlockEntities.size())); // Paper - remove unused list - bufferedwriter.write(String.format("block_ticks: %d\n", this.getBlockTicks().size())); - bufferedwriter.write(String.format("fluid_ticks: %d\n", this.getLiquidTicks().size())); - bufferedwriter.write("distance_manager: " + playerchunkmap.getDistanceManager().getDebugStatus() + "\n"); -@@ -1854,7 +1854,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - - private void dumpBlockEntities(Writer writer) throws IOException { - CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("type").build(writer); -- Iterator iterator = this.blockEntityList.iterator(); -+ Iterator iterator = this.tickableBlockEntities.iterator(); // Paper - remove unused list - - while (iterator.hasNext()) { - BlockEntity tileentity = (BlockEntity) iterator.next(); -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 89a6a0b4235cfcc1d3ad68ff59a21fa60df4508f..8f0fec38b482465285057d3fd27d456cf036f2fd 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -91,7 +91,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public static final ResourceKey NETHER = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation("the_nether")); - public static final ResourceKey END = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation("the_end")); - private static final Direction[] DIRECTIONS = Direction.values(); -- public final List blockEntityList = Lists.newArrayList(); -+ //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list - public final List tickableBlockEntities = Lists.newArrayList(); - protected final List pendingBlockEntities = Lists.newArrayList(); - protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); -@@ -683,9 +683,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - }, blockEntity::getBlockPos}); - } - -- boolean flag = this.blockEntityList.add(blockEntity); -+ boolean flag = true; // Paper - remove unused list - -- if (flag && blockEntity instanceof TickableBlockEntity) { -+ if (flag && blockEntity instanceof TickableBlockEntity && !this.tickableBlockEntities.contains(blockEntity)) { // Paper - this.tickableBlockEntities.add(blockEntity); - } - -@@ -721,7 +721,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - timings.tileEntityTick.startTiming(); // Spigot - if (!this.tileEntityListUnload.isEmpty()) { - this.tickableBlockEntities.removeAll(this.tileEntityListUnload); -- this.blockEntityList.removeAll(this.tileEntityListUnload); -+ //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list - this.tileEntityListUnload.clear(); - } - -@@ -781,7 +781,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - tilesThisCycle--; - this.tickableBlockEntities.remove(tileTickPosition--); - // Spigot end -- this.blockEntityList.remove(tileentity); -+ //this.tileEntityList.remove(tileentity); // Paper - remove unused list - if (this.hasChunkAt(tileentity.getBlockPos())) { - this.getChunkAt(tileentity.getBlockPos()).removeBlockEntity(tileentity.getBlockPos()); - } -@@ -811,7 +811,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - this.sendBlockUpdated(tileentity1.getBlockPos(), iblockdata, iblockdata, 3); - // CraftBukkit start - // From above, don't screw this up - SPIGOT-1746 -- if (!this.blockEntityList.contains(tileentity1)) { -+ if (true) { // Paper - remove unused list - this.addBlockEntity(tileentity1); - } - // CraftBukkit end -@@ -957,7 +957,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } else { - if (tileentity != null) { - this.pendingBlockEntities.remove(tileentity); -- this.blockEntityList.remove(tileentity); -+ //this.tileEntityList.remove(tileentity); // Paper - remove unused list - this.tickableBlockEntities.remove(tileentity); - } - diff --git a/Remapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch b/Remapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch deleted file mode 100644 index 42e534b702..0000000000 --- a/Remapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 Apr 2016 00:30:10 -0400 -Subject: [PATCH] Don't tick Skulls - unused code - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java -index 6a46517e4026971d8c050c685c710883b5976fa3..eebaeaccc3ba1a9ec089d84b8de6c9d36034868f 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java -@@ -31,7 +31,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.server.players.GameProfileCache; - import net.minecraft.util.StringUtil; - --public class SkullBlockEntity extends BlockEntity implements TickableBlockEntity { -+public class SkullBlockEntity extends BlockEntity /*implements ITickable*/ { // Paper - remove tickable - - @Nullable - private static GameProfileCache profileCache; -@@ -134,7 +134,7 @@ public class SkullBlockEntity extends BlockEntity implements TickableBlockEntity - - } - -- @Override -+ // Paper - remove override - public void tick() { - BlockState iblockdata = this.getBlockState(); - diff --git a/Remapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch b/Remapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch deleted file mode 100644 index 3ed6659147..0000000000 --- a/Remapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 Apr 2016 02:10:49 -0400 -Subject: [PATCH] Configurable Player Collision - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 439dcc6effdc91830d2b7ede9063982998b37120..504efea7b6f50a0d17f4f353781953dfb18bdeca 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -232,4 +232,9 @@ public class PaperConfig { - private static void regionFileCacheSize() { - regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); - } -+ -+ public static boolean enablePlayerCollisions = true; -+ private static void enablePlayerCollisions() { -+ enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); -+ } - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java -index 53f284b720d97ba8ce8fac90bc26e7930dcec6b2..d70e7079ea2c84edbc2a8501f115194e2a4ef2e4 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java -@@ -112,7 +112,7 @@ public class ClientboundSetPlayerTeamPacket implements Packet toRemove = scoreboard.getTeams().stream().filter(team -> team.getName().startsWith("collideRule_")).map(PlayerTeam::getName).collect(java.util.stream.Collectors.toList()); -+ for (String teamName : toRemove) { -+ scoreboard.removeTeam(scoreboard.getTeam(teamName)); // Clean up after ourselves -+ } -+ -+ if (!com.destroystokyo.paper.PaperConfig.enablePlayerCollisions) { -+ this.getPlayerList().collideRuleTeamName = org.apache.commons.lang3.StringUtils.left("collideRule_" + java.util.concurrent.ThreadLocalRandom.current().nextInt(), 16); -+ PlayerTeam collideTeam = scoreboard.createTeam(this.getPlayerList().collideRuleTeamName); -+ collideTeam.setSeeFriendlyInvisibles(false); // Because we want to mimic them not being on a team at all -+ } -+ // Paper end -+ - this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); - this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); - this.connection.acceptConnections(); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index aa440a6341a6d30aba8fd5f6bcd122bd5d8760cd..59fb19cfebe4f488fd02f02db31029d44b65e408 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -79,6 +79,7 @@ import net.minecraft.world.level.storage.PlayerDataStorage; - import net.minecraft.world.phys.Vec3; - import net.minecraft.world.scores.Objective; - import net.minecraft.world.scores.PlayerTeam; -+import net.minecraft.world.scores.Scoreboard; - import net.minecraft.world.scores.Team; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -141,6 +142,7 @@ public abstract class PlayerList { - // CraftBukkit start - private CraftServer cserver; - private final Map playersByName = new java.util.HashMap<>(); -+ public @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule - - public PlayerList(MinecraftServer server, RegistryAccess.RegistryHolder registryManager, PlayerDataStorage saveHandler, int maxPlayers) { - this.cserver = server.server = new CraftServer((DedicatedServer) server, this); -@@ -372,6 +374,13 @@ public abstract class PlayerList { - } - - player.initMenu(); -+ // Paper start - Add to collideRule team if needed -+ final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); -+ final PlayerTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName); -+ if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) { -+ scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); -+ } -+ // Paper end - // CraftBukkit - Moved from above, added world - PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.worldDataServer.getLevelName(), player.getX(), player.getY(), player.getZ()); - } -@@ -492,6 +501,16 @@ public abstract class PlayerList { - entityplayer.doTick(); // SPIGOT-924 - // CraftBukkit end - -+ // Paper start - Remove from collideRule team if needed -+ if (this.collideRuleTeamName != null) { -+ final Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard(); -+ final PlayerTeam team = scoreBoard.getTeam(this.collideRuleTeamName); -+ if (entityplayer.getTeam() == team && team != null) { -+ scoreBoard.removePlayerFromTeam(entityplayer.getScoreboardName(), team); -+ } -+ } -+ // Paper end -+ - this.save(entityplayer); - if (entityplayer.isPassenger()) { - Entity entity = entityplayer.getRootVehicle(); -@@ -1140,6 +1159,13 @@ public abstract class PlayerList { - } - // CraftBukkit end - -+ // Paper start - Remove collideRule team if it exists -+ if (this.collideRuleTeamName != null) { -+ final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); -+ final PlayerTeam team = scoreboard.getTeam(this.collideRuleTeamName); -+ if (team != null) scoreboard.removeTeam(team); -+ } -+ // Paper end - } - - // CraftBukkit start diff --git a/Remapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Remapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch deleted file mode 100644 index 56a3be043d..0000000000 --- a/Remapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 13 Apr 2016 20:21:38 -0700 -Subject: [PATCH] Add handshake event to allow plugins to handle client - handshaking logic themselves - - -diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -index 55b6412bb978abb6f8eaff83a7dd40fbc1ed8b9a..e56ab94ce65e81bb0383a1626a1790c43bd6920e 100644 ---- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -@@ -29,7 +29,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - // CraftBukkit end - private static final Component IGNORE_STATUS_REASON = new TextComponent("Ignoring status request"); - private final MinecraftServer server; -- private final Connection connection; -+ private final Connection connection; final Connection getNetworkManager() { return this.connection; } // Paper - OBFHELPER - - public ServerHandshakePacketListenerImpl(MinecraftServer server, Connection connection) { - this.server = server; -@@ -88,8 +88,35 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - this.connection.disconnect(chatmessage); - } else { - this.connection.setListener(new ServerLoginPacketListenerImpl(this.server, this.connection)); -+ // Paper start - handshake event -+ boolean proxyLogicEnabled = org.spigotmc.SpigotConfig.bungee; -+ boolean handledByEvent = false; -+ // Try and handle the handshake through the event -+ if (com.destroystokyo.paper.event.player.PlayerHandshakeEvent.getHandlerList().getRegisteredListeners().length != 0) { // Hello? Can you hear me? -+ java.net.SocketAddress socketAddress = this.getNetworkManager().address; -+ String hostnameOfRemote = socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getHostString() : InetAddress.getLoopbackAddress().getHostAddress(); -+ com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packet.hostName, hostnameOfRemote, !proxyLogicEnabled); -+ if (event.callEvent()) { -+ // If we've failed somehow, let the client know so and go no further. -+ if (event.isFailed()) { -+ chatmessage = new TranslatableComponent(event.getFailMessage()); -+ this.getNetworkManager().send(new ClientboundLoginDisconnectPacket(chatmessage)); -+ this.getNetworkManager().disconnect(chatmessage); -+ return; -+ } -+ -+ if (event.getServerHostname() != null) packet.hostName = event.getServerHostname(); -+ if (event.getSocketAddressHostname() != null) this.getNetworkManager().address = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); -+ this.getNetworkManager().spoofedUUID = event.getUniqueId(); -+ this.getNetworkManager().spoofedProfile = gson.fromJson(event.getPropertiesJson(), com.mojang.authlib.properties.Property[].class); -+ handledByEvent = true; // Hooray, we did it! -+ } -+ } -+ // Don't try and handle default logic if it's been handled by the event. -+ if (!handledByEvent && proxyLogicEnabled) { -+ // Paper end - // Spigot Start -- if (org.spigotmc.SpigotConfig.bungee) { -+ //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! - String[] split = packet.hostName.split("\00"); - if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { - packet.hostName = split[0]; diff --git a/Remapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch b/Remapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch deleted file mode 100644 index 4bc15f3f2f..0000000000 --- a/Remapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 16 Apr 2016 00:39:33 -0400 -Subject: [PATCH] Configurable RCON IP address - -For servers with multiple IP's, ability to bind to a specific interface. - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index d10f2e5a13a9e86c32ef5dd8c6732ad8b51ed6a0..545096d9ba403396b6aaa7bb6d912f2de08a967e 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -@@ -64,6 +64,8 @@ public class DedicatedServerProperties extends Settings.MutableValue whiteList; - public final WorldGenSettings worldGenSettings; - -+ public final String rconIp; // Paper - Add rcon ip -+ - // CraftBukkit start - public DedicatedServerProperties(Properties properties, RegistryAccess iregistrycustom, OptionSet optionset) { - super(properties, optionset); -@@ -115,6 +117,10 @@ public class DedicatedServerProperties extends Settings> { - }; - } - -- @Nullable -- private String getStringRaw(String key) { -+ @Nullable String getSettingIfExists(final String path) { return this.getStringRaw(path); } // Paper - OBFHELPER -+ @Nullable private String getStringRaw(String key) { // Paper - OBFHELPER - return (String) getOverride(key, this.properties.getProperty(key)); // CraftBukkit - } - -diff --git a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java b/src/main/java/net/minecraft/server/rcon/thread/RconThread.java -index f2a94e9d9b57ece16873972bc5292f7cf3928848..ef9f659ae5f53a8effa807ecb955ef47d53aacd2 100644 ---- a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java -+++ b/src/main/java/net/minecraft/server/rcon/thread/RconThread.java -@@ -62,7 +62,7 @@ public class RconThread extends GenericThread { - @Nullable - public static RconThread create(ServerInterface server) { - DedicatedServerProperties dedicatedserverproperties = server.getProperties(); -- String s = server.getServerIp(); -+ String s = dedicatedserverproperties.rconIp; // Paper - Configurable rcon ip - - if (s.isEmpty()) { - s = "0.0.0.0"; diff --git a/Remapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch b/Remapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch deleted file mode 100644 index 04b43eed1b..0000000000 --- a/Remapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 17 Apr 2016 17:27:09 -0400 -Subject: [PATCH] Prevent Fire from loading chunks & wrongly spread - -This causes the nether to spam unload/reload chunks, plus overall -bad behavior. - -This also stops fire from spreading to illegal locations. - -diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java -index 700078c2fd536cc22351eadf51503efb9acd9df9..85170008de6e77cfb8e4f55ae440a8428d868af4 100644 ---- a/src/main/java/net/minecraft/world/level/block/FireBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java -@@ -134,7 +134,7 @@ public class FireBlock extends BaseFireBlock { - BooleanProperty blockstateboolean = (BooleanProperty) FireBlock.PROPERTY_BY_DIRECTION.get(enumdirection); - - if (blockstateboolean != null) { -- iblockdata1 = (BlockState) iblockdata1.setValue(blockstateboolean, this.canBurn(world.getBlockState(pos.relative(enumdirection)))); -+ iblockdata1 = (BlockState) iblockdata1.setValue(blockstateboolean, this.canBurn(world.getTypeIfLoaded(pos.relative(enumdirection)))); // Paper - prevent chunk loads - } - } - -@@ -214,6 +214,7 @@ public class FireBlock extends BaseFireBlock { - } - - blockposition_mutableblockposition.setWithOffset((Vec3i) pos, l, j1, i1); -+ if (blockposition_mutableblockposition.isInvalidYLocation() || !world.hasChunkAt(blockposition_mutableblockposition)) continue; // Paper - int l1 = this.getFireOdds((LevelReader) world, (BlockPos) blockposition_mutableblockposition); - - if (l1 > 0) { -@@ -259,10 +260,16 @@ public class FireBlock extends BaseFireBlock { - } - - private void trySpread(Level world, BlockPos blockposition, int i, Random random, int j, BlockPos sourceposition) { // CraftBukkit add sourceposition -- int k = this.getBurnOdd(world.getBlockState(blockposition)); -+ // Paper start -+ final BlockState iblockdata = world.getTypeIfLoaded(blockposition); -+ if (iblockdata == null) { -+ return; -+ } -+ int k = this.getBurnOdd(iblockdata); -+ // Paper end - - if (random.nextInt(i) < k) { -- BlockState iblockdata = world.getBlockState(blockposition); -+ //IBlockData iblockdata = world.getType(blockposition); // Paper - - // CraftBukkit start - org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -@@ -308,7 +315,7 @@ public class FireBlock extends BaseFireBlock { - for (int j = 0; j < i; ++j) { - Direction enumdirection = aenumdirection[j]; - -- if (this.canBurn(world.getBlockState(pos.relative(enumdirection)))) { -+ if (this.canBurn(world.getTypeIfLoaded(pos.relative(enumdirection)))) { // Paper - prevent chunk loads - return true; - } - } -@@ -326,7 +333,12 @@ public class FireBlock extends BaseFireBlock { - - for (int k = 0; k < j; ++k) { - Direction enumdirection = aenumdirection[k]; -- BlockState iblockdata = iworldreader.getBlockState(pos.relative(enumdirection)); -+ // Paper start -+ BlockState iblockdata = iworldreader.getTypeIfLoaded(pos.relative(enumdirection)); -+ if (iblockdata == null) { -+ continue; -+ } -+ // Paper end - - i = Math.max(this.getFlameOdds(iblockdata), i); - } -@@ -337,7 +349,7 @@ public class FireBlock extends BaseFireBlock { - - @Override - protected boolean canBurn(BlockState state) { -- return this.getFlameOdds(state) > 0; -+ return state != null && this.getFlameOdds(state) > 0; // Paper - iblockdata can be nullable if chunk is unloaded now - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch b/Remapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch deleted file mode 100644 index c52d99a313..0000000000 --- a/Remapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Isaac Moore -Date: Tue, 19 Apr 2016 14:09:31 -0500 -Subject: [PATCH] Implement PlayerLocaleChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index ffad931c72e52855a3f139354f5e85c460e2a80b..bd3d9182dfb2c0ae1d8c3b9aa360f94c33252592 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1692,7 +1692,7 @@ public class ServerPlayer extends Player implements ContainerListener { - return s; - } - -- public String locale = "en_us"; // CraftBukkit - add, lowercase -+ public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null - public java.util.Locale adventure$locale = java.util.Locale.US; // Paper - public void updateOptions(ServerboundClientInformationPacket packet) { - // CraftBukkit start -@@ -1700,9 +1700,10 @@ public class ServerPlayer extends Player implements ContainerListener { - PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); - this.server.server.getPluginManager().callEvent(event); - } -- if (!this.locale.equals(packet.language)) { -+ if (this.locale == null || !this.locale.equals(packet.language)) { // Paper - check for null - PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), packet.language); - this.server.server.getPluginManager().callEvent(event); -+ new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.locale, packet.language).callEvent(); // Paper - } - this.locale = packet.language; - // Paper start -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b264cbe5f91da9e31c5fd00ee285735a19aaad35..fc19b4cacd223b928fbdf922b828beaed630bf2e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1875,8 +1875,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public String getLocale() { -- return getHandle().locale; -- -+ // Paper start - Locale change event -+ final String locale = getHandle().locale; -+ return locale != null ? locale : "en_us"; -+ // Paper end - } - - // Paper start diff --git a/Remapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch b/Remapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch deleted file mode 100644 index 386b74cf50..0000000000 --- a/Remapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 22 Apr 2016 01:43:11 -0500 -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 a326e5b4ac055f2f8a95c6eaccd8d0a97762da1f..1131d86080b3100437aa18a00c6277fcea4b7ea8 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1127,10 +1127,16 @@ public abstract class LivingEntity extends Entity { - } - - public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { -+ // Paper start - Forward -+ heal(f, regainReason, false); -+ } -+ -+ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason, boolean isFastRegen) { -+ // Paper end - float f1 = this.getHealth(); - - if (f1 > 0.0F) { -- EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); -+ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason, isFastRegen); // Paper - // Suppress during worldgen - if (this.valid) { - this.level.getCraftServer().getPluginManager().callEvent(event); -diff --git a/src/main/java/net/minecraft/world/food/FoodData.java b/src/main/java/net/minecraft/world/food/FoodData.java -index 269392592f5271b1bb8c37661fbe685e76e32b74..d18b7d2c22312fc6ec3977ce38a1f04e0b5c8ad4 100644 ---- a/src/main/java/net/minecraft/world/food/FoodData.java -+++ b/src/main/java/net/minecraft/world/food/FoodData.java -@@ -84,7 +84,7 @@ public class FoodData { - if (this.tickTimer >= this.saturatedRegenRate) { // CraftBukkit - float f = Math.min(this.saturationLevel, 6.0F); - -- player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason -+ player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED, true); // CraftBukkit - added RegainReason // Paper - This is fast regen - // this.a(f); CraftBukkit - EntityExhaustionEvent - player.applyExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent - this.tickTimer = 0; diff --git a/Remapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch b/Remapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch deleted file mode 100644 index e5bee625dc..0000000000 --- a/Remapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Thu, 21 Apr 2016 23:51:55 -0700 -Subject: [PATCH] Add ability to configure frosted_ice properties - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1942f5224aaebb18adb591d6f70a419cfc1a7bdd..5baccb8d50c135ab20c38ffd0690f585514ce5af 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -259,4 +259,14 @@ public class PaperWorldConfig { - private void useVanillaScoreboardColoring() { - useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); - } -+ -+ public boolean frostedIceEnabled = true; -+ public int frostedIceDelayMin = 20; -+ public int frostedIceDelayMax = 40; -+ private void frostedIce() { -+ this.frostedIceEnabled = this.getBoolean("frosted-ice.enabled", this.frostedIceEnabled); -+ this.frostedIceDelayMin = this.getInt("frosted-ice.delay.min", this.frostedIceDelayMin); -+ this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); -+ log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java -index 0727cc36c99cb5ca5019c71f4540de76b78c7a80..ae2f5acd008d5d7163b56cb4a2d29354299959ca 100644 ---- a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java -@@ -30,6 +30,7 @@ public class FrostedIceBlock extends IceBlock { - - @Override - public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) { -+ if (!world.paperConfig.frostedIceEnabled) return; // Paper - add ability to disable frosted ice - if ((random.nextInt(3) == 0 || this.fewerNeigboursThan(world, pos, 4)) && world.getMaxLocalRawBrightness(pos) > 11 - (Integer) state.getValue(FrostedIceBlock.AGE) - state.getLightBlock((BlockGetter) world, pos) && this.slightlyMelt(state, (Level) world, pos)) { - BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); - Direction[] aenumdirection = Direction.values(); -@@ -42,12 +43,12 @@ public class FrostedIceBlock extends IceBlock { - BlockState iblockdata1 = world.getBlockState(blockposition_mutableblockposition); - - if (iblockdata1.is((Block) this) && !this.slightlyMelt(iblockdata1, (Level) world, blockposition_mutableblockposition)) { -- world.getBlockTicks().scheduleTick(blockposition_mutableblockposition, this, Mth.nextInt(random, 20, 40)); -+ world.getBlockTicks().scheduleTick(blockposition_mutableblockposition, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay - } - } - - } else { -- world.getBlockTicks().scheduleTick(pos, this, Mth.nextInt(random, 20, 40)); -+ world.getBlockTicks().scheduleTick(pos, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay - } - } - diff --git a/Remapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch b/Remapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch deleted file mode 100644 index 2a17e8f4af..0000000000 --- a/Remapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 28 Apr 2016 00:57:27 -0400 -Subject: [PATCH] remove null possibility for getServer singleton - -to stop IDE complaining about potential NPE - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index d639ead95c36985fa0f5a9c51898c4237e373f0e..4e468cb7ccf683b8fc9e04a48cfc25779775e25f 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -178,6 +178,7 @@ import org.spigotmc.SlackActivityAccountant; // Spigot - - public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { - -+ private static MinecraftServer SERVER; // Paper - public static final Logger LOGGER = LogManager.getLogger(); - public static final File USERID_CACHE_FILE = new File("usercache.json"); - public static final LevelSettings DEMO_SETTINGS = new LevelSettings("Demo World", GameType.SURVIVAL, false, Difficulty.NORMAL, false, new GameRules(), DataPackConfig.DEFAULT); -@@ -284,6 +285,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Fri, 29 Apr 2016 20:02:00 -0400 -Subject: [PATCH] Improve Maps (in item frames) performance and bug fixes - -Maps used a modified version of rendering to support plugin controlled -imaging on maps. The Craft Map Renderer is much slower than Vanilla, -causing maps in item frames to cause a noticeable hit on server performance. - -This updates the map system to not use the Craft system if we detect that no -custom renderers are in use, defaulting to the much simpler Vanilla system. - -Additionally, numerous issues to player position tracking on maps has been fixed. - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index bb99d9fe5e274318d8480a6de2c45b0a57351f77..0a613f94d1c796267636e1a343aeee65a49ffed5 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1164,6 +1164,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - { - if ( iter.next().player == entity ) - { -+ map.decorations.remove(entity.getName().getString()); // Paper - iter.remove(); - } - } -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 3b451e75a7f49ea6b543aee9f0a51c0be3c4dfba..c11d5aa115d10e3c12863cf9d42c60194d63b690 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -85,6 +85,7 @@ import net.minecraft.world.item.ElytraItem; - import net.minecraft.world.item.ItemCooldowns; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; -+import net.minecraft.world.item.MapItem; - import net.minecraft.world.item.ProjectileWeaponItem; - import net.minecraft.world.item.SwordItem; - import net.minecraft.world.item.crafting.Recipe; -@@ -104,6 +105,7 @@ import net.minecraft.world.level.block.entity.SignBlockEntity; - import net.minecraft.world.level.block.entity.StructureBlockEntity; - import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.level.block.state.pattern.BlockInWorld; -+import net.minecraft.world.level.saveddata.maps.MapItemSavedData; - import net.minecraft.world.phys.AABB; - import net.minecraft.world.phys.Vec3; - import net.minecraft.world.scores.PlayerTeam; -@@ -686,6 +688,12 @@ public abstract class Player extends LivingEntity { - return null; - } - // CraftBukkit end -+ // Paper start - remove player from map on drop -+ if (stack.getItem() == Items.FILLED_MAP) { -+ MapItemSavedData worldmap = MapItem.getOrCreateSavedData(stack, this.level); -+ worldmap.updateSeenPlayers(this, stack); -+ } -+ // Paper end - - return entityitem; - } -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -index d44505b3ee2a35422568e9bce0d868191e348fc0..7582c7cd4235d212a0cf66a4c59ce0cedaa360ad 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -@@ -57,6 +57,7 @@ public class MapItemSavedData extends SavedData { - private final Map bannerMarkers = Maps.newHashMap(); - public final Map decorations = Maps.newLinkedHashMap(); - private final Map frameMarkers = Maps.newHashMap(); -+ private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper - - // CraftBukkit start - public final CraftMapView mapView; -@@ -69,6 +70,7 @@ public class MapItemSavedData extends SavedData { - // CraftBukkit start - mapView = new CraftMapView(this); - server = (CraftServer) org.bukkit.Bukkit.getServer(); -+ vanillaRender.buffer = colors; // Paper - // CraftBukkit end - } - -@@ -136,6 +138,7 @@ public class MapItemSavedData extends SavedData { - this.bannerMarkers.put(mapiconbanner.getId(), mapiconbanner); - this.addDecoration(mapiconbanner.getDecoration(), (LevelAccessor) null, mapiconbanner.getId(), (double) mapiconbanner.getPos().getX(), (double) mapiconbanner.getPos().getZ(), 180.0D, mapiconbanner.getName()); - } -+ this.vanillaRender.buffer = colors; // Paper - - ListTag nbttaglist1 = tag.getList("frames", 10); - -@@ -216,6 +219,7 @@ public class MapItemSavedData extends SavedData { - this.setDirty(); - } - -+ public void updateSeenPlayers(Player entityhuman, ItemStack itemstack) { this.tickCarriedBy(entityhuman, itemstack); } // Paper - OBFHELPER - public void tickCarriedBy(Player player, ItemStack stack) { - if (!this.carriedByPlayers.containsKey(player)) { - MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = new MapItemSavedData.HoldingPlayer(player); -@@ -451,6 +455,21 @@ public class MapItemSavedData extends SavedData { - - public class HoldingPlayer { - -+ // Paper start -+ private void addSeenPlayers(java.util.Collection icons) { -+ org.bukkit.entity.Player player = (org.bukkit.entity.Player) player.getBukkitEntity(); -+ MapItemSavedData.this.decorations.forEach((name, mapIcon) -> { -+ // If this cursor is for a player check visibility with vanish system -+ org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayerExact(name); // Spigot -+ if (other == null || player.canSee(other)) { -+ icons.add(mapIcon); -+ } -+ }); -+ } -+ private boolean shouldUseVanillaMap() { -+ return mapView.getRenderers().size() == 1 && mapView.getRenderers().get(0).getClass() == org.bukkit.craftbukkit.map.CraftMapRenderer.class; -+ } -+ // Paper end - public final Player player; - private boolean dirtyData = true; - private int minDirtyX; -@@ -467,9 +486,12 @@ public class MapItemSavedData extends SavedData { - @Nullable - public Packet nextUpdatePacket(ItemStack stack) { - // CraftBukkit start -- org.bukkit.craftbukkit.map.RenderData render = MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit -+ if (!this.dirtyData && this.tick % 5 != 0) { this.tick++; return null; } // Paper - this won't end up sending, so don't render it! -+ boolean vanillaMaps = shouldUseVanillaMap(); // Paper -+ org.bukkit.craftbukkit.map.RenderData render = !vanillaMaps ? MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()) : MapItemSavedData.this.vanillaRender; // CraftBukkit // Paper - - java.util.Collection icons = new java.util.ArrayList(); -+ if (vanillaMaps) addSeenPlayers(icons); // Paper - - for ( org.bukkit.map.MapCursor cursor : render.cursors) { - -diff --git a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java -index 256a131781721c86dd6cdbc329335964570cbe8c..5768cd512ec166f1e8d1f4a28792015347297c3f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java -+++ b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java -@@ -5,7 +5,7 @@ import org.bukkit.map.MapCursor; - - public class RenderData { - -- public final byte[] buffer; -+ public byte[] buffer; // Paper - public final ArrayList cursors; - - public RenderData() { diff --git a/Remapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch b/Remapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch deleted file mode 100644 index 4e9c15788b..0000000000 --- a/Remapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch +++ /dev/null @@ -1,739 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 1 May 2016 21:19:14 -0400 -Subject: [PATCH] LootTable API & Replenishable Lootables Feature - -Provides an API to control the loot table for an object. -Also provides a feature that any Lootable Inventory (Chests in Structures) -can automatically replenish after a given time. - -This feature is good for long term worlds so that newer players -do not suffer with "Every chest has been looted" - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5baccb8d50c135ab20c38ffd0690f585514ce5af..eb04fdb172a50ec1f5b7fe78fa0e7655246abd60 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -269,4 +269,26 @@ public class PaperWorldConfig { - this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); - log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); - } -+ -+ public boolean autoReplenishLootables; -+ public boolean restrictPlayerReloot; -+ public boolean changeLootTableSeedOnFill; -+ public int maxLootableRefills; -+ public int lootableRegenMin; -+ public int lootableRegenMax; -+ private void enhancedLootables() { -+ autoReplenishLootables = getBoolean("lootables.auto-replenish", false); -+ restrictPlayerReloot = getBoolean("lootables.restrict-player-reloot", true); -+ changeLootTableSeedOnFill = getBoolean("lootables.reset-seed-on-fill", true); -+ maxLootableRefills = getInt("lootables.max-refills", -1); -+ lootableRegenMin = PaperConfig.getSeconds(getString("lootables.refresh-min", "12h")); -+ lootableRegenMax = PaperConfig.getSeconds(getString("lootables.refresh-max", "2d")); -+ if (autoReplenishLootables) { -+ log("Lootables: Replenishing every " + -+ PaperConfig.timeSummary(lootableRegenMin) + " to " + -+ PaperConfig.timeSummary(lootableRegenMax) + -+ (restrictPlayerReloot ? " (restricting reloot)" : "") -+ ); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fda64b8860cb696e209eedcfb200e7193d216732 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java -@@ -0,0 +1,34 @@ -+package com.destroystokyo.paper.loottable; -+ -+import LootableInventory; -+import net.minecraft.core.BlockPos; -+import net.minecraft.world.level.Level; -+import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; -+import org.bukkit.Chunk; -+import org.bukkit.block.Block; -+ -+public interface PaperLootableBlockInventory extends LootableBlockInventory, PaperLootableInventory { -+ -+ RandomizableContainerBlockEntity getTileEntity(); -+ -+ @Override -+ default LootableInventory getAPILootableInventory() { -+ return this; -+ } -+ -+ @Override -+ default Level getNMSWorld() { -+ return getTileEntity().getLevel(); -+ } -+ -+ default Block getBlock() { -+ final BlockPos position = getTileEntity().getBlockPos(); -+ final Chunk bukkitChunk = getTileEntity().getLevel().getChunkAt(position).bukkitChunk; -+ return bukkitChunk.getBlock(position.getX(), position.getY(), position.getZ()); -+ } -+ -+ @Override -+ default PaperLootableInventoryData getLootableData() { -+ return getTileEntity().lootableData; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..292d5ef8a1c428893af729b298eecd32b4c4659a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java -@@ -0,0 +1,29 @@ -+package com.destroystokyo.paper.loottable; -+ -+import LootableInventory; -+import net.minecraft.world.level.Level; -+import org.bukkit.entity.Entity; -+ -+public interface PaperLootableEntityInventory extends LootableEntityInventory, PaperLootableInventory { -+ -+ net.minecraft.world.entity.Entity getHandle(); -+ -+ @Override -+ default LootableInventory getAPILootableInventory() { -+ return this; -+ } -+ -+ default Entity getEntity() { -+ return getHandle().getBukkitEntity(); -+ } -+ -+ @Override -+ default Level getNMSWorld() { -+ return getHandle().getCommandSenderWorld(); -+ } -+ -+ @Override -+ default PaperLootableInventoryData getLootableData() { -+ return getHandle().lootableData; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b3def19a50081cfa758b6e25707b2fc6fed8d3ca ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java -@@ -0,0 +1,71 @@ -+package com.destroystokyo.paper.loottable; -+ -+import org.bukkit.loot.Lootable; -+import LootableInventory; -+import java.util.UUID; -+import net.minecraft.world.level.Level; -+ -+public interface PaperLootableInventory extends LootableInventory, Lootable { -+ -+ PaperLootableInventoryData getLootableData(); -+ LootableInventory getAPILootableInventory(); -+ -+ Level getNMSWorld(); -+ -+ default org.bukkit.World getBukkitWorld() { -+ return getNMSWorld().getWorld(); -+ } -+ -+ @Override -+ default boolean isRefillEnabled() { -+ return getNMSWorld().paperConfig.autoReplenishLootables; -+ } -+ -+ @Override -+ default boolean hasBeenFilled() { -+ return getLastFilled() != -1; -+ } -+ -+ @Override -+ default boolean hasPlayerLooted(UUID player) { -+ return getLootableData().hasPlayerLooted(player); -+ } -+ -+ @Override -+ default Long getLastLooted(UUID player) { -+ return getLootableData().getLastLooted(player); -+ } -+ -+ @Override -+ default boolean setHasPlayerLooted(UUID player, boolean looted) { -+ final boolean hasLooted = hasPlayerLooted(player); -+ if (hasLooted != looted) { -+ getLootableData().setPlayerLootedState(player, looted); -+ } -+ return hasLooted; -+ } -+ -+ @Override -+ default boolean hasPendingRefill() { -+ long nextRefill = getLootableData().getNextRefill(); -+ return nextRefill != -1 && nextRefill > getLootableData().getLastFill(); -+ } -+ -+ @Override -+ default long getLastFilled() { -+ return getLootableData().getLastFill(); -+ } -+ -+ @Override -+ default long getNextRefill() { -+ return getLootableData().getNextRefill(); -+ } -+ -+ @Override -+ default long setNextRefill(long refillAt) { -+ if (refillAt < -1) { -+ refillAt = -1; -+ } -+ return getLootableData().setNextRefill(refillAt); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java -new file mode 100644 -index 0000000000000000000000000000000000000000..88542462d34ba24e8590294bd896d7e73932ef9c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java -@@ -0,0 +1,180 @@ -+package com.destroystokyo.paper.loottable; -+ -+import com.destroystokyo.paper.PaperWorldConfig; -+import org.bukkit.entity.Player; -+import org.bukkit.loot.LootTable; -+ -+import javax.annotation.Nullable; -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.nbt.ListTag; -+import java.util.HashMap; -+import java.util.Map; -+import java.util.Random; -+import java.util.UUID; -+ -+public class PaperLootableInventoryData { -+ -+ private static final Random RANDOM = new Random(); -+ -+ private long lastFill = -1; -+ private long nextRefill = -1; -+ private int numRefills = 0; -+ private Map lootedPlayers; -+ private final PaperLootableInventory lootable; -+ -+ public PaperLootableInventoryData(PaperLootableInventory lootable) { -+ this.lootable = lootable; -+ } -+ -+ long getLastFill() { -+ return this.lastFill; -+ } -+ -+ long getNextRefill() { -+ return this.nextRefill; -+ } -+ -+ long setNextRefill(long nextRefill) { -+ long prev = this.nextRefill; -+ this.nextRefill = nextRefill; -+ return prev; -+ } -+ -+ public boolean shouldReplenish(@Nullable net.minecraft.world.entity.player.Player player) { -+ LootTable table = this.lootable.getLootTable(); -+ -+ // No Loot Table associated -+ if (table == null) { -+ return false; -+ } -+ -+ // ALWAYS process the first fill or if the feature is disabled -+ if (this.lastFill == -1 || !this.lootable.getNMSWorld().paperConfig.autoReplenishLootables) { -+ return true; -+ } -+ -+ // Only process refills when a player is set -+ if (player == null) { -+ return false; -+ } -+ -+ // Chest is not scheduled for refill -+ if (this.nextRefill == -1) { -+ return false; -+ } -+ -+ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; -+ -+ // Check if max refills has been hit -+ if (paperConfig.maxLootableRefills != -1 && this.numRefills >= paperConfig.maxLootableRefills) { -+ return false; -+ } -+ -+ // Refill has not been reached -+ if (this.nextRefill > System.currentTimeMillis()) { -+ return false; -+ } -+ -+ -+ final Player bukkitPlayer = (Player) player.getBukkitEntity(); -+ LootableInventoryReplenishEvent event = new LootableInventoryReplenishEvent(bukkitPlayer, lootable.getAPILootableInventory()); -+ if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUUID())) { -+ event.setCancelled(true); -+ } -+ return event.callEvent(); -+ } -+ public void processRefill(@Nullable net.minecraft.world.entity.player.Player player) { -+ this.lastFill = System.currentTimeMillis(); -+ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; -+ if (paperConfig.autoReplenishLootables) { -+ int min = paperConfig.lootableRegenMin; -+ int max = paperConfig.lootableRegenMax; -+ this.nextRefill = this.lastFill + (min + RANDOM.nextInt(max - min + 1)) * 1000L; -+ this.numRefills++; -+ if (paperConfig.changeLootTableSeedOnFill) { -+ this.lootable.setSeed(0); -+ } -+ if (player != null) { // This means that numRefills can be incremented without a player being in the lootedPlayers list - Seems to be EntityMinecartChest specific -+ this.setPlayerLootedState(player.getUUID(), true); -+ } -+ } else { -+ this.lootable.clearLootTable(); -+ } -+ } -+ -+ -+ public void loadNbt(CompoundTag base) { -+ if (!base.contains("Paper.LootableData", 10)) { // 10 = compound -+ return; -+ } -+ CompoundTag comp = base.getCompound("Paper.LootableData"); -+ if (comp.contains("lastFill")) { -+ this.lastFill = comp.getLong("lastFill"); -+ } -+ if (comp.contains("nextRefill")) { -+ this.nextRefill = comp.getLong("nextRefill"); -+ } -+ -+ if (comp.contains("numRefills")) { -+ this.numRefills = comp.getInt("numRefills"); -+ } -+ if (comp.contains("lootedPlayers", 9)) { // 9 = list -+ ListTag list = comp.getList("lootedPlayers", 10); // 10 = compound -+ final int size = list.size(); -+ if (size > 0) { -+ this.lootedPlayers = new HashMap<>(list.size()); -+ } -+ for (int i = 0; i < size; i++) { -+ final CompoundTag cmp = list.getCompound(i); -+ lootedPlayers.put(cmp.getUUID("UUID"), cmp.getLong("Time")); -+ } -+ } -+ } -+ public void saveNbt(CompoundTag base) { -+ CompoundTag comp = new CompoundTag(); -+ if (this.nextRefill != -1) { -+ comp.putLong("nextRefill", this.nextRefill); -+ } -+ if (this.lastFill != -1) { -+ comp.putLong("lastFill", this.lastFill); -+ } -+ if (this.numRefills != 0) { -+ comp.putInt("numRefills", this.numRefills); -+ } -+ if (this.lootedPlayers != null && !this.lootedPlayers.isEmpty()) { -+ ListTag list = new ListTag(); -+ for (Map.Entry entry : this.lootedPlayers.entrySet()) { -+ CompoundTag cmp = new CompoundTag(); -+ cmp.setUUID("UUID", entry.getKey()); -+ cmp.putLong("Time", entry.getValue()); -+ list.add(cmp); -+ } -+ comp.put("lootedPlayers", list); -+ } -+ -+ if (!comp.isEmpty()) { -+ base.put("Paper.LootableData", comp); -+ } -+ } -+ -+ void setPlayerLootedState(UUID player, boolean looted) { -+ if (looted && this.lootedPlayers == null) { -+ this.lootedPlayers = new HashMap<>(); -+ } -+ if (looted) { -+ if (!this.lootedPlayers.containsKey(player)) { -+ this.lootedPlayers.put(player, System.currentTimeMillis()); -+ } -+ } else if (this.lootedPlayers != null) { -+ this.lootedPlayers.remove(player); -+ } -+ } -+ -+ boolean hasPlayerLooted(UUID player) { -+ return this.lootedPlayers != null && this.lootedPlayers.containsKey(player); -+ } -+ -+ Long getLastLooted(UUID player) { -+ return lootedPlayers != null ? lootedPlayers.get(player) : null; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d9b31c8a21fdffb33d1f75b1a16606f218145b39 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java -@@ -0,0 +1,63 @@ -+package com.destroystokyo.paper.loottable; -+ -+import LootableInventory; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; -+import net.minecraft.world.level.Level; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.util.CraftNamespacedKey; -+ -+public class PaperMinecartLootableInventory implements PaperLootableEntityInventory { -+ -+ private AbstractMinecartContainer entity; -+ -+ public PaperMinecartLootableInventory(AbstractMinecartContainer entity) { -+ this.entity = entity; -+ } -+ -+ @Override -+ public org.bukkit.loot.LootTable getLootTable() { -+ return entity.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.lootTable)) : null; -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { -+ setLootTable(table); -+ setSeed(seed); -+ } -+ -+ @Override -+ public void setSeed(long seed) { -+ entity.lootTableSeed = seed; -+ } -+ -+ @Override -+ public long getSeed() { -+ return entity.lootTableSeed; -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table) { -+ entity.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); -+ } -+ -+ @Override -+ public PaperLootableInventoryData getLootableData() { -+ return entity.lootableData; -+ } -+ -+ @Override -+ public Entity getHandle() { -+ return entity; -+ } -+ -+ @Override -+ public LootableInventory getAPILootableInventory() { -+ return (LootableInventory) entity.getBukkitEntity(); -+ } -+ -+ @Override -+ public Level getNMSWorld() { -+ return entity.level; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6bc899ec4dc03b09cc978bc7a763a9755a3d2dc4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java -@@ -0,0 +1,66 @@ -+package com.destroystokyo.paper.loottable; -+ -+import LootableInventory; -+import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.Level; -+import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.util.CraftNamespacedKey; -+ -+public class PaperTileEntityLootableInventory implements PaperLootableBlockInventory { -+ private RandomizableContainerBlockEntity tileEntityLootable; -+ -+ public PaperTileEntityLootableInventory(RandomizableContainerBlockEntity tileEntityLootable) { -+ this.tileEntityLootable = tileEntityLootable; -+ } -+ -+ @Override -+ public org.bukkit.loot.LootTable getLootTable() { -+ return tileEntityLootable.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null; -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { -+ setLootTable(table); -+ setSeed(seed); -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table) { -+ tileEntityLootable.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); -+ } -+ -+ @Override -+ public void setSeed(long seed) { -+ tileEntityLootable.lootTableSeed = seed; -+ } -+ -+ @Override -+ public long getSeed() { -+ return tileEntityLootable.lootTableSeed; -+ } -+ -+ @Override -+ public PaperLootableInventoryData getLootableData() { -+ return tileEntityLootable.lootableData; -+ } -+ -+ @Override -+ public RandomizableContainerBlockEntity getTileEntity() { -+ return tileEntityLootable; -+ } -+ -+ @Override -+ public LootableInventory getAPILootableInventory() { -+ Level world = tileEntityLootable.getLevel(); -+ if (world == null) { -+ return null; -+ } -+ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, tileEntityLootable.getBlockPos())).getState(); -+ } -+ -+ @Override -+ public Level getNMSWorld() { -+ return tileEntityLootable.getLevel(); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 61048140cf0adca03bfb57193ada0adaee73b1bb..171697e88f5a4d8c0be2a47b67b865bbdc4dfe8c 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -157,6 +157,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - }; - // Paper end - -+ public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - - public CraftEntity getBukkitEntity() { -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java -index f4758251e58fbb36526cea5c4825561d62c9665a..5b96b1e7428a43c8c5f4a96ea37d5189f0d84f56 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java -@@ -45,6 +45,7 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme - public long lootTableSeed; - - // CraftBukkit start -+ { this.lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperMinecartLootableInventory(this)); } // Paper - public List transaction = new java.util.ArrayList(); - private int maxStack = MAX_STACK; - -@@ -202,12 +203,13 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme - @Override - protected void addAdditionalSaveData(CompoundTag tag) { - super.addAdditionalSaveData(tag); -+ this.lootableData.saveNbt(tag); // Paper - if (this.lootTable != null) { - tag.putString("LootTable", this.lootTable.toString()); - if (this.lootTableSeed != 0L) { - tag.putLong("LootTableSeed", this.lootTableSeed); - } -- } else { -+ } if (true) { // Paper - Always save the items, Table may stick around - ContainerHelper.saveAllItems(tag, this.itemStacks); - } - -@@ -216,11 +218,12 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme - @Override - protected void readAdditionalSaveData(CompoundTag tag) { - super.readAdditionalSaveData(tag); -+ this.lootableData.loadNbt(tag); // Paper - this.itemStacks = NonNullList.a(this.getContainerSize(), ItemStack.EMPTY); - if (tag.contains("LootTable", 8)) { - this.lootTable = new ResourceLocation(tag.getString("LootTable")); - this.lootTableSeed = tag.getLong("LootTableSeed"); -- } else { -+ } if (true) { // Paper - always load the items, table may still remain - ContainerHelper.loadAllItems(tag, this.itemStacks); - } - -@@ -251,14 +254,15 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme - } - - public void unpackLootTable(@Nullable Player player) { -- if (this.lootTable != null && this.level.getServer() != null) { -+ if (this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper - LootTable loottable = this.level.getServer().getLootTables().get(this.lootTable); - - if (player instanceof ServerPlayer) { - CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer) player, this.lootTable); - } - -- this.lootTable = null; -+ //this.lootTable = null; // Paper -+ this.lootableData.processRefill(player); // Paper - LootContext.Builder loottableinfo_builder = (new LootContext.Builder((ServerLevel) this.level)).withParameter(LootContextParams.ORIGIN, this.position()).withOptionalRandomSeed(this.lootTableSeed); - - if (player != null) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java -index 9d33bc31c8088bfba66be1aecbf20e7ee86e4f83..5ad419941ff1113ef29b9a4593f44d8f35ba8424 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java -@@ -27,6 +27,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc - @Nullable - public ResourceLocation lootTable; - public long lootTableSeed; -+ public final com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperTileEntityLootableInventory(this)); // Paper - - protected RandomizableContainerBlockEntity(BlockEntityType type) { - super(type); -@@ -42,16 +43,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc - } - - protected boolean tryLoadLootTable(CompoundTag nbttagcompound) { -+ this.lootableData.loadNbt(nbttagcompound); // Paper - if (nbttagcompound.contains("LootTable", 8)) { - this.lootTable = new ResourceLocation(nbttagcompound.getString("LootTable")); -+ try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate - this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); -- return true; -+ return false; // Paper - always load the items, table may still remain - } else { - return false; - } - } - - protected boolean trySaveLootTable(CompoundTag nbttagcompound) { -+ this.lootableData.saveNbt(nbttagcompound); // Paper - if (this.lootTable == null) { - return false; - } else { -@@ -60,19 +64,20 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc - nbttagcompound.putLong("LootTableSeed", this.lootTableSeed); - } - -- return true; -+ return false; // Paper - always save the items, table may still remain - } - } - - public void unpackLootTable(@Nullable Player player) { -- if (this.lootTable != null && this.level.getServer() != null) { -+ if (this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper - LootTable loottable = this.level.getServer().getLootTables().get(this.lootTable); - - if (player instanceof ServerPlayer) { - CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer) player, this.lootTable); - } - -- this.lootTable = null; -+ //this.lootTable = null; // Paper -+ this.lootableData.processRefill(player); // Paper - LootContext.Builder loottableinfo_builder = (new LootContext.Builder((ServerLevel) this.level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf((Vec3i) this.worldPosition)).withOptionalRandomSeed(this.lootTableSeed); - - if (player != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 1e2e94b0cd2ede8fb7ae5902dcd0b639bd8dcf52..e89a93082fe07fdb14df8ffef5beca5bd52d7866 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -64,7 +64,7 @@ public class CraftBlockEntityState extends CraftBlockStat - } - - // gets the wrapped TileEntity -- protected T getTileEntity() { -+ public T getTileEntity() { // Paper - protected -> public - return tileEntity; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -index 20d9a192ff102e04687a8aa3eff1ba36a69b6c03..a821df3e13e2ddc479dc5f55540671f43563cdac 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -@@ -12,8 +12,9 @@ import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.inventory.CraftInventory; - import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest; - import org.bukkit.inventory.Inventory; -+import com.destroystokyo.paper.loottable.PaperLootableBlockInventory; // Paper - --public class CraftChest extends CraftLootable implements Chest { -+public class CraftChest extends CraftLootable implements Chest, PaperLootableBlockInventory { // Paper - - public CraftChest(final Block block) { - super(block, ChestBlockEntity.class); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -index 309650aad43d8b6ce4bb13f8c172028f3feab299..5babbcfcacb89e62f00f8184af2ceea227f9ff69 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -@@ -10,7 +10,7 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; - import org.bukkit.loot.LootTable; - import org.bukkit.loot.Lootable; - --public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable { -+public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable, com.destroystokyo.paper.loottable.PaperLootableBlockInventory { // Paper - - public CraftLootable(Block block, Class tileEntityClass) { - super(block, tileEntityClass); -@@ -54,7 +54,7 @@ public abstract class CraftLootable - setLootTable(getLootTable(), seed); - } - -- private void setLootTable(LootTable table, long seed) { -+ public void setLootTable(LootTable table, long seed) { // Paper - public - ResourceLocation key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); - getSnapshot().setLootTable(key, seed); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -index f0a30acb0199e396d6863a473db433cbe112d8a5..293b222565d8e0592f9f355a2ee8cdfbc868a08e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -@@ -8,7 +8,7 @@ import org.bukkit.entity.minecart.StorageMinecart; - import org.bukkit.inventory.Inventory; - - @SuppressWarnings("deprecation") --public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart { -+public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper - private final CraftInventory inventory; - - public CraftMinecartChest(CraftServer server, MinecartChest entity) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -index 12044062cb746bd5c77abacf8acddc67e08e78ce..ce14bc4791bd282d16af0ee91fc431acefa3b909 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -@@ -47,7 +47,7 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo - return getHandle().lootTableSeed; - } - -- private void setLootTable(LootTable table, long seed) { -+ public void setLootTable(LootTable table, long seed) { // Paper - ResourceLocation newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); - getHandle().setLootTable(newKey, seed); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -index c1af739369715d8c628c466b269fdde99a2f6286..c8c5f60b6b32248696363d9b63bbbe43810743d3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -@@ -7,7 +7,7 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.minecart.HopperMinecart; - import org.bukkit.inventory.Inventory; - --public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart { -+public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper - private final CraftInventory inventory; - - public CraftMinecartHopper(CraftServer server, MinecartHopper entity) { diff --git a/Remapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/Remapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch deleted file mode 100644 index f9fbbc4e75..0000000000 --- a/Remapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 May 2016 23:33:08 -0400 -Subject: [PATCH] Don't save empty scoreboard teams to scoreboard.dat - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 504efea7b6f50a0d17f4f353781953dfb18bdeca..1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -237,4 +237,9 @@ public class PaperConfig { - private static void enablePlayerCollisions() { - enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); - } -+ -+ public static boolean saveEmptyScoreboardTeams = false; -+ private static void saveEmptyScoreboardTeams() { -+ saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java -index 36a922029687b9fa3ca3a986ae42a373ced87a0e..b9e14d1c54b690f0b975bda5733c4cb4f6449f77 100644 ---- a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java -+++ b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java -@@ -182,6 +182,7 @@ public class ScoreboardSaveData extends SavedData { - - while (iterator.hasNext()) { - PlayerTeam scoreboardteam = (PlayerTeam) iterator.next(); -+ if (!com.destroystokyo.paper.PaperConfig.saveEmptyScoreboardTeams && scoreboardteam.getPlayers().isEmpty()) continue; // Paper - CompoundTag nbttagcompound = new CompoundTag(); - - nbttagcompound.putString("Name", scoreboardteam.getName()); diff --git a/Remapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch b/Remapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch deleted file mode 100644 index d8a22a7f5f..0000000000 --- a/Remapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 12 May 2016 23:02:58 -0500 -Subject: [PATCH] System property for disabling watchdoge - - -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 0ed95268364ea7f6a92a39b726a1e03bc815be07..ee0cca25ef458f2f0f7e450a2edea2b2adb7e846 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -61,7 +61,7 @@ public class WatchdogThread extends Thread - while ( !stopping ) - { - // -- if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime ) -+ if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable - { - Logger log = Bukkit.getServer().getLogger(); - log.log( Level.SEVERE, "------------------------------" ); diff --git a/Remapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch b/Remapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch deleted file mode 100644 index 4b08a22748..0000000000 --- a/Remapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 16 May 2016 20:47:41 -0400 -Subject: [PATCH] Optimize UserCache / Thread Safe - -Because Techable keeps complaining about how this isn't thread safe, -easier to do this than replace the entire thing. - -Additionally, move Saving of the User cache to be done async, incase -the user never changed the default setting for Spigot's save on stop only. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 4e468cb7ccf683b8fc9e04a48cfc25779775e25f..211251fe7cd08074c040df2f4642f37d5f90d856 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -905,7 +905,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Paper - - try { - BufferedWriter bufferedwriter = Files.newWriter(this.file, StandardCharsets.UTF_8); -@@ -268,6 +270,14 @@ public class GameProfileCache { - } catch (IOException ioexception) { - ; - } -+ // Paper start -+ }; -+ if (asyncSave) { -+ MCUtil.scheduleAsyncTask(save); -+ } else { -+ save.run(); -+ } -+ // Paper end - - } - diff --git a/Remapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch b/Remapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch deleted file mode 100644 index ba69589d2f..0000000000 --- a/Remapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 16 May 2016 23:19:16 -0400 -Subject: [PATCH] Avoid blocking on Network Manager creation - -Per Paper issue 294 - -diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -index 9680b0b3879c72776d6225a6a5a89fdfa3520598..6cb51a4fe3c11f53fbb556ce6b0d64b735254d51 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -@@ -52,6 +52,15 @@ public class ServerConnectionListener { - public volatile boolean running; - private final List channels = Collections.synchronizedList(Lists.newArrayList()); - private final List connections = Collections.synchronizedList(Lists.newArrayList()); -+ // Paper start - prevent blocking on adding a new network manager while the server is ticking -+ private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private void addPending() { -+ Connection manager = null; -+ while ((manager = pending.poll()) != null) { -+ connections.add(manager); -+ } -+ } -+ // Paper end - - public ServerConnectionListener(MinecraftServer server) { - this.server = server; -@@ -87,7 +96,8 @@ public class ServerConnectionListener { - int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); - Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); - -- ServerConnectionListener.this.connections.add((Connection) object); // CraftBukkit - decompile error -+ //ServerConnection.this.connectedChannels.add((NetworkManager) object); // CraftBukkit - decompile error -+ pending.add((Connection) object); // Paper - channel.pipeline().addLast("packet_handler", (ChannelHandler) object); - ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); - } -@@ -126,6 +136,7 @@ public class ServerConnectionListener { - - synchronized (this.connections) { - // Spigot Start -+ this.addPending(); // Paper - // This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order - if ( org.spigotmc.SpigotConfig.playerShuffle > 0 && MinecraftServer.currentTick % org.spigotmc.SpigotConfig.playerShuffle == 0 ) - { diff --git a/Remapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch b/Remapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch deleted file mode 100644 index cd8e56460f..0000000000 --- a/Remapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 22 May 2016 20:20:55 -0500 -Subject: [PATCH] Optional TNT doesn't move in water - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index eb04fdb172a50ec1f5b7fe78fa0e7655246abd60..6eca3f300020006f02dd36253b522db442e3cc33 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -2,7 +2,6 @@ package com.destroystokyo.paper; - - import java.util.List; - --import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -291,4 +290,14 @@ public class PaperWorldConfig { - ); - } - } -+ -+ public boolean preventTntFromMovingInWater; -+ private void preventTntFromMovingInWater() { -+ if (PaperConfig.version < 13) { -+ boolean oldVal = getBoolean("enable-old-tnt-cannon-behaviors", false); -+ set("prevent-tnt-from-moving-in-water", oldVal); -+ } -+ preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); -+ log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index fa6893055fa5617742bfb4b7eff60c8139395cb6..49c71b21b6b88bc41ca6ddf4c76186ce522ee456 100644 ---- a/src/main/java/net/minecraft/server/level/ServerEntity.java -+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -66,7 +66,7 @@ public class ServerEntity { - private boolean wasRiding; - private boolean wasOnGround; - // CraftBukkit start -- private final Set trackedPlayers; -+ final Set trackedPlayers; // Paper - private -> package - // Paper start - private java.util.Map trackedPlayerMap = null; - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 171697e88f5a4d8c0be2a47b67b865bbdc4dfe8c..c3aece8e5001828edea304b2a8377e9a28b34cfe 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2770,6 +2770,11 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public boolean isPushedByFluid() { -+ // Paper start -+ return this.pushedByWater(); -+ } -+ public boolean pushedByWater() { -+ // Paper end - return true; - } - -diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -index 661848084fd986321ef782317934dac19ed4dce3..347ac17643de8bcb0c8496c2ea5eb18c2e4d856b 100644 ---- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -@@ -5,9 +5,13 @@ import net.minecraft.core.particles.ParticleTypes; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; -+import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; -+import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket; - import net.minecraft.network.syncher.EntityDataAccessor; - import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; -+import net.minecraft.server.level.ChunkMap; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityDimensions; - import net.minecraft.world.entity.EntityType; -@@ -95,7 +99,27 @@ public class PrimedTnt extends Entity { - this.level.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D); - } - } -- -+ // Paper start - Optional prevent TNT from moving in water -+ if (!this.removed && this.wasTouchingWater && this.level.paperConfig.preventTntFromMovingInWater) { -+ /* -+ * Author: Jedediah Smith -+ */ -+ // Send position and velocity updates to nearby players on every tick while the TNT is in water. -+ // This does pretty well at keeping their clients in sync with the server. -+ ChunkMap.TrackedEntity ete = ((ServerLevel)this.level).getChunkSource().chunkMap.entityMap.get(this.getId()); -+ if (ete != null) { -+ ClientboundSetEntityMotionPacket velocityPacket = new ClientboundSetEntityMotionPacket(this); -+ ClientboundTeleportEntityPacket positionPacket = new ClientboundTeleportEntityPacket(this); -+ -+ ete.seenBy.stream() -+ .filter(viewer -> (viewer.getX() - this.getX()) * (viewer.getY() - this.getY()) * (viewer.getZ() - this.getZ()) < 16 * 16) -+ .forEach(viewer -> { -+ viewer.connection.send(velocityPacket); -+ viewer.connection.send(positionPacket); -+ }); -+ } -+ } -+ // Paper end - } - - private void explode() { -@@ -164,4 +188,11 @@ public class PrimedTnt extends Entity { - public Packet getAddEntityPacket() { - return new ClientboundAddEntityPacket(this); - } -+ -+ // Paper start - Optional prevent TNT from moving in water -+ @Override -+ public boolean pushedByWater() { -+ return !level.paperConfig.preventTntFromMovingInWater && super.pushedByWater(); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch b/Remapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch deleted file mode 100644 index cc437e7353..0000000000 --- a/Remapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Panzer -Date: Mon, 23 May 2016 12:12:37 +0200 -Subject: [PATCH] Faster redstone torch rapid clock removal - -Only resize the the redstone torch list once, since resizing arrays / lists is costly - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 8f0fec38b482465285057d3fd27d456cf036f2fd..5f3d17cb247156fc8aaa7a763e402c2bbb42a7ec 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -48,6 +48,7 @@ import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.BaseFireBlock; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.Blocks; -+import net.minecraft.world.level.block.RedstoneTorchBlock; - import net.minecraft.world.level.block.entity.BlockEntity; - import net.minecraft.world.level.block.entity.BlockEntityType; - import net.minecraft.world.level.block.entity.TickableBlockEntity; -@@ -142,6 +143,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - private org.spigotmc.TickLimiter tileLimiter; - private int tileTickPosition; - public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions -+ public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here - - public CraftWorld getWorld() { - return this.world; -diff --git a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java -index 7d71c99c2268174fbea4297f028b75a3a0f43c11..dd4391086aff05bdea81e62b950b88cfab5ac6b8 100644 ---- a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java -@@ -21,7 +21,7 @@ import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit - public class RedstoneTorchBlock extends TorchBlock { - - public static final BooleanProperty LIT = BlockStateProperties.LIT; -- private static final Map> RECENT_TOGGLES = new WeakHashMap(); -+ // Paper - Move the mapped list to World - - protected RedstoneTorchBlock(BlockBehaviour.Properties settings) { - super(settings, DustParticleOptions.REDSTONE); -@@ -68,11 +68,15 @@ public class RedstoneTorchBlock extends TorchBlock { - @Override - public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) { - boolean flag = this.hasNeighborSignal((Level) world, pos, state); -- List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.get(world); -- -- while (list != null && !list.isEmpty() && world.getGameTime() - ((RedstoneTorchBlock.Toggle) list.get(0)).when > 60L) { -- list.remove(0); -+ // Paper start -+ java.util.ArrayDeque redstoneUpdateInfos = world.redstoneUpdateInfos; -+ if (redstoneUpdateInfos != null) { -+ RedstoneTorchBlock.Toggle curr; -+ while ((curr = redstoneUpdateInfos.peek()) != null && world.getGameTime() - curr.getTime() > 60L) { -+ redstoneUpdateInfos.poll(); -+ } - } -+ // Paper end - - // CraftBukkit start - org.bukkit.plugin.PluginManager manager = world.getCraftServer().getPluginManager(); -@@ -137,9 +141,12 @@ public class RedstoneTorchBlock extends TorchBlock { - } - - private static boolean isToggledTooFrequently(Level world, BlockPos pos, boolean addNew) { -- List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.computeIfAbsent(world, (iblockaccess) -> { -- return Lists.newArrayList(); -- }); -+ // Paper start -+ java.util.ArrayDeque list = world.redstoneUpdateInfos; -+ if (list == null) { -+ list = world.redstoneUpdateInfos = new java.util.ArrayDeque<>(); -+ } -+ - - if (addNew) { - list.add(new RedstoneTorchBlock.Toggle(pos.immutable(), world.getGameTime())); -@@ -147,9 +154,9 @@ public class RedstoneTorchBlock extends TorchBlock { - - int i = 0; - -- for (int j = 0; j < list.size(); ++j) { -- RedstoneTorchBlock.Toggle blockredstonetorch_redstoneupdateinfo = (RedstoneTorchBlock.Toggle) list.get(j); -- -+ for (java.util.Iterator iterator = list.iterator(); iterator.hasNext();) { -+ RedstoneTorchBlock.Toggle blockredstonetorch_redstoneupdateinfo = iterator.next(); -+ // Paper end - if (blockredstonetorch_redstoneupdateinfo.pos.equals(pos)) { - ++i; - if (i >= 8) { -@@ -164,7 +171,7 @@ public class RedstoneTorchBlock extends TorchBlock { - public static class Toggle { - - private final BlockPos pos; -- private final long when; -+ private final long when; final long getTime() { return this.when; } // Paper - OBFHELPER - - public Toggle(BlockPos pos, long time) { - this.pos = pos; diff --git a/Remapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch b/Remapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch deleted file mode 100644 index 50ec621547..0000000000 --- a/Remapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Panzer -Date: Sat, 28 May 2016 16:54:03 +0200 -Subject: [PATCH] Add server-name parameter - - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2..b849b2afd009da433fe6cea5837b3ee9bb5c52b4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -143,6 +143,14 @@ public class Main { - .defaultsTo(new File("paper.yml")) - .describedAs("Yml file"); - // Paper end -+ -+ // Paper start -+ acceptsAll(asList("server-name"), "Name of the server") -+ .withRequiredArg() -+ .ofType(String.class) -+ .defaultsTo("Unknown Server") -+ .describedAs("Name"); -+ // Paper end - } - }; - diff --git a/Remapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/Remapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch deleted file mode 100644 index e84fc6a07e..0000000000 --- a/Remapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 May 2016 22:53:50 -0400 -Subject: [PATCH] Only send Dragon/Wither Death sounds to same world - -Also fix view distance lookup - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index 8d1b3cbb21fe798c27ad2d39bccffa9cc983cf96..39298b69918da890c3faa516f80d1a69adb88fe2 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -619,8 +619,9 @@ public class EnderDragon extends Mob implements Enemy { - if (this.dragonDeathTime == 1 && !this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1028, this.getChunkCoordinates(), 0); -- int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; -- for (net.minecraft.server.level.ServerPlayer player : this.level.getServer().getPlayerList().players) { -+ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ for (net.minecraft.server.level.ServerPlayer player : (List) ((ServerLevel)level).players()) { -+ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.getX() - player.getX(); - double deltaZ = this.getZ() - player.getZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 61c982ead18334a29438ef8e024d97ead178a2c8..3a80869dc3c16cb81ac87100f28d63eee722067f 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -46,7 +46,6 @@ import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerBossEvent; --import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvent; - import net.minecraft.sounds.SoundEvents; -@@ -256,8 +255,9 @@ public class WitherBoss extends Monster implements RangedAttackMob { - if (!this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1023, new BlockPosition(this), 0); -- int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; -- for (ServerPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { -+ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ for (ServerPlayer player : (List)this.level.players()) { -+ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.getX() - player.getX(); - double deltaZ = this.getZ() - player.getZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; diff --git a/Remapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch b/Remapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch deleted file mode 100644 index b412753ddd..0000000000 --- a/Remapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 21 Jun 2016 22:54:34 -0400 -Subject: [PATCH] Fix Double World Add issues - -Vanilla will double add Spider Jockeys to the world, so ignore already added. - -Also add debug if something else tries to, and abort before world gets bad state - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 0a613f94d1c796267636e1a343aeee65a49ffed5..335928d60dbfc07644ffeab366900c5e77e99d56 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1032,6 +1032,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -+ if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper - if (entity.removed) { - // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit - return false; diff --git a/Remapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch b/Remapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch deleted file mode 100644 index d08b9cb8ca..0000000000 --- a/Remapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 17 Jun 2016 20:50:11 -0400 -Subject: [PATCH] Fix Old Sign Conversion - -1) Sign loading code was trying to parse the JSON before the check for oldSign. - That code could then skip the old sign converting code if it triggers a JSON parse exception. -2) New Mojang Schematic system has Tile Entities in the new converted format, but missing the Bukkit.isConverted flag - This causes Igloos and such to render broken signs. We fix this by ignoring sign conversion for Defined Structures - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 13115d1b28dfa2d87b45a50bd0feaa7f57769122..d08ed44884726ca2ba4578226b8aa6244778f4c7 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -34,6 +34,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - public CraftPersistentDataContainer persistentDataContainer; - // CraftBukkit end - private static final Logger LOGGER = LogManager.getLogger(); -+ public boolean isLoadingStructure = false; // Paper - private final BlockEntityType type; public BlockEntityType getTileEntityType() { return type; } // Paper - OBFHELPER - @Nullable - protected Level level; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -index e747f729326fb3bacfb3f983ac7701c0fb0f0e6a..e4eab82855649fec654c60b2e94ba7b71c2ac5a2 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -@@ -78,13 +78,14 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C - } - - try { -- MutableComponent ichatmutablecomponent = Component.Serializer.fromJson(s.isEmpty() ? "\"\"" : s); -+ //IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); // Paper - move down - the old format might throw a json error - -- if (oldSign) { -+ if (oldSign && !isLoadingStructure) { // Paper - saved structures will be in the new format, but will not have isConverted - messages[i] = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s)[0]; - continue; - } - // CraftBukkit end -+ MutableComponent ichatmutablecomponent = Component.Serializer.fromJson(s.isEmpty() ? "\"\"" : s); // Paper - after old sign - - if (this.level instanceof ServerLevel) { - try { -diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java -index 8da00ee410e3f8f09b8ac273095a3d22d6c4d92b..d4cf5d3bdbe629081f6ec9d4ea94004560c93ebc 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java -@@ -278,9 +278,11 @@ public class StructureTemplate { - definedstructure_blockinfo.nbt.putLong("LootTableSeed", random.nextLong()); - } - -+ tileentity.isLoadingStructure = true; // Paper - tileentity.load(definedstructure_blockinfo.state, definedstructure_blockinfo.nbt); - tileentity.mirror(placementData.getMirror()); - tileentity.rotate(placementData.getRotation()); -+ tileentity.isLoadingStructure = false; // Paper - } - } - diff --git a/Remapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/Remapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch deleted file mode 100644 index 51ddf3745d..0000000000 --- a/Remapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 16 Jul 2016 19:11:17 -0500 -Subject: [PATCH] Don't lookup game profiles that have no UUID and no name - - -diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index 9342fa6b28e805743b8e3a13007605934244d6cd..f3e05fac1b5248ca4ee2cac03263e96c166ed343 100644 ---- a/src/main/java/net/minecraft/server/players/GameProfileCache.java -+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java -@@ -92,7 +92,7 @@ public class GameProfileCache { - repository.findProfilesByNames(new String[]{name}, Agent.MINECRAFT, profilelookupcallback); - GameProfile gameprofile = (GameProfile) atomicreference.get(); - -- if (!usesAuthentication() && gameprofile == null) { -+ if (!usesAuthentication() && gameprofile == null && !org.apache.commons.lang3.StringUtils.isBlank(name)) { // Paper - Don't lookup a profile with a blank name - UUID uuid = Player.createPlayerUUID(new GameProfile((UUID) null, name)); - - gameprofile = new GameProfile(uuid, name); diff --git a/Remapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch b/Remapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch deleted file mode 100644 index 067e04850c..0000000000 --- a/Remapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabriele C -Date: Fri, 5 Aug 2016 01:03:08 +0200 -Subject: [PATCH] Add setting for proxy online mode status - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2..c52dc0346f93527965ef29a0ccdc4bf3debe302e 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -23,6 +23,7 @@ import org.bukkit.configuration.InvalidConfigurationException; - import org.bukkit.configuration.file.YamlConfiguration; - import co.aikar.timings.Timings; - import co.aikar.timings.TimingsManager; -+import org.spigotmc.SpigotConfig; - - public class PaperConfig { - -@@ -242,4 +243,13 @@ public class PaperConfig { - private static void saveEmptyScoreboardTeams() { - saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); - } -+ -+ public static boolean bungeeOnlineMode = true; -+ private static void bungeeOnlineMode() { -+ bungeeOnlineMode = getBoolean("settings.bungee-online-mode", true); -+ } -+ -+ public static boolean isProxyOnlineMode() { -+ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); -+ } - } -diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index f3e05fac1b5248ca4ee2cac03263e96c166ed343..e8af352f813a5015d216fc590190ae8fdb03f77d 100644 ---- a/src/main/java/net/minecraft/server/players/GameProfileCache.java -+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java -@@ -89,6 +89,7 @@ public class GameProfileCache { - } - }; - -+ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) // Paper - only run in online mode - 100 COL - repository.findProfilesByNames(new String[]{name}, Agent.MINECRAFT, profilelookupcallback); - GameProfile gameprofile = (GameProfile) atomicreference.get(); - -@@ -106,7 +107,7 @@ public class GameProfileCache { - } - - private static boolean usesAuthentication() { -- return GameProfileCache.usesAuthentication; -+ return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper - } - - public synchronized void add(GameProfile gameprofile) { // Paper - synchronize -diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java -index 09c5fa2dbcbed05da51ef2d63e6d6112d22d7877..e6a26c274616947329a6164e4648486452819b0c 100644 ---- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java -+++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java -@@ -63,7 +63,8 @@ public class OldUsersConverter { - return new String[i]; - }); - -- if (server.usesAuthentication() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. -+ if (server.usesAuthentication() -+ || (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode())) { // Spigot: bungee = online mode, for now. // Paper - Handle via setting - server.getProfileRepository().findProfilesByNames(astring, Agent.MINECRAFT, callback); - } else { - String[] astring1 = astring; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 2828936fe294d9d6750a8838da49ec8398835214..bbe0978f56d23b7defce765d381d4a7c20acd75c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1515,7 +1515,8 @@ public final class CraftServer implements Server { - // Spigot Start - GameProfile profile = null; - // Only fetch an online UUID in online mode -- if ( getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) -+ if ( getOnlineMode() -+ || com.destroystokyo.paper.PaperConfig.isProxyOnlineMode() ) // Paper - Handle via setting - { - profile = console.getProfileCache().get( name ); - } diff --git a/Remapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch b/Remapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch deleted file mode 100644 index 6e9e140dc2..0000000000 --- a/Remapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Fri, 19 Aug 2016 01:52:56 +0100 -Subject: [PATCH] Optimise BlockState's hashCode/equals - -These are singleton "single instance" objects. We can rely on -object identity checks safely. - -Use a simpler optimized hashcode - -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java -index c5af36a0279d1e1c951e6f9b34857b0aa934f940..62f11a02e3f5c07e838f425cffb0a28b6d2bc138 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java -@@ -30,8 +30,7 @@ public class BooleanProperty extends Property { - return value.toString(); - } - -- @Override -- public boolean equals(Object object) { -+ public boolean equals_unused(Object object) { // Paper - if (this == object) { - return true; - } else if (object instanceof BooleanProperty && super.equals(object)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java -index b5817645727f2af2785e0987ba824f431d4e9e32..2fdfd7d2470ee9f1a96eda7418b104c960df8460 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java -@@ -50,8 +50,7 @@ public class EnumProperty & StringRepresentable> extends Prope - return ((StringRepresentable) value).getSerializedName(); - } - -- @Override -- public boolean equals(Object object) { -+ public boolean equals_unused(Object object) { // Paper - if (this == object) { - return true; - } else if (object instanceof EnumProperty && super.equals(object)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java -index c3ec7f91794d802e5b9ddac3fffccce378dace68..72f508321ebffcca31240fbdd068b4d185454cbc 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java -@@ -38,8 +38,7 @@ public class IntegerProperty extends Property { - return this.values; - } - -- @Override -- public boolean equals(Object object) { -+ public boolean equals_unused(Object object) { // Paper - if (this == object) { - return true; - } else if (object instanceof IntegerProperty && super.equals(object)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java -index 8cc07c70fde81e44679f3ea7d9a4c6b2447885d4..80f8966ac56e8af4a6c7aa86b2d8dd0f319c7b5d 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java -@@ -60,23 +60,17 @@ public abstract class Property> { - } - - public boolean equals(Object object) { -- if (this == object) { -- return true; -- } else if (!(object instanceof Property)) { -- return false; -- } else { -- Property iblockstate = (Property) object; -- -- return this.clazz.equals(iblockstate.clazz) && this.name.equals(iblockstate.name); -- } -+ return this == object; // Paper - only one instance per configuration - } - -+ private static final java.util.concurrent.atomic.AtomicInteger hashId = new java.util.concurrent.atomic.AtomicInteger(1); // Paper - only one instance per configuration -+ private final int hashCode = 92821 * hashId.getAndIncrement(); // Paper - only one instance per configuration - public final int hashCode() { - if (this.hashCode == null) { - this.hashCode = this.generateHashCode(); - } - -- return this.hashCode; -+ return this.hashCode; // Paper - only one instance per configuration - } - - public int generateHashCode() { diff --git a/Remapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch b/Remapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch deleted file mode 100644 index bce5b61b0d..0000000000 --- a/Remapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 11 Sep 2016 14:30:57 -0500 -Subject: [PATCH] Configurable packet in spam threshold - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index c52dc0346f93527965ef29a0ccdc4bf3debe302e..64d7c9058ee757a6d3cf3b648596092a810e105c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -252,4 +252,13 @@ public class PaperConfig { - public static boolean isProxyOnlineMode() { - return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); - } -+ -+ public static int packetInSpamThreshold = 300; -+ private static void packetInSpamThreshold() { -+ if (version < 11) { -+ int oldValue = getInt("settings.play-in-use-item-spam-threshold", 300); -+ set("settings.incoming-packet-spam-threshold", oldValue); -+ } -+ packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index e2bfe8e916c9e59af81627ea0ee449970527034d..d6f4ccf06c919410e13409433bdfc3aa88a21c30 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1463,13 +1463,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // Spigot start - limit place/interactions - private int limitedPackets; - private long lastLimitedPacket = -1; -+ private static final int THRESHOLD = com.destroystokyo.paper.PaperConfig.packetInSpamThreshold; // Paper - Configurable threshold - - private boolean checkLimit(long timestamp) { -- if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < 30 && limitedPackets++ >= 4) { -+ if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < THRESHOLD && limitedPackets++ >= 8) { // Paper - Use threshold, raise packet limit to 8 - return false; - } - -- if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= 30) { -+ if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= THRESHOLD) { // Paper - lastLimitedPacket = timestamp; - limitedPackets = 0; - return true; diff --git a/Remapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch b/Remapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch deleted file mode 100644 index fc05cbc991..0000000000 --- a/Remapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Tue, 20 Sep 2016 00:58:01 +0000 -Subject: [PATCH] Configurable flying kick messages - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 64d7c9058ee757a6d3cf3b648596092a810e105c..4e2f243faa209925dcb7c3ef89df3ed875c5ff78 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -261,4 +261,11 @@ public class PaperConfig { - } - packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); - } -+ -+ public static String flyingKickPlayerMessage = "Flying is not enabled on this server"; -+ public static String flyingKickVehicleMessage = "Flying is not enabled on this server"; -+ private static void flyingKickMessages() { -+ flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); -+ flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index d6f4ccf06c919410e13409433bdfc3aa88a21c30..1b92c669bbe69bcc07a554b7b43ee99bfebc1af4 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -305,7 +305,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - if (this.clientIsFloating && !this.player.isSleeping()) { - if (++this.aboveGroundTickCount > 80) { - ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); -- this.disconnect(new TranslatableComponent("multiplayer.disconnect.flying")); -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message - return; - } - } else { -@@ -324,7 +324,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) { - if (++this.aboveGroundVehicleTickCount > 80) { - ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); -- this.disconnect(new TranslatableComponent("multiplayer.disconnect.flying")); -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message - return; - } - } else { diff --git a/Remapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch b/Remapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch deleted file mode 100644 index 4d2da1cd83..0000000000 --- a/Remapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Sep 2016 22:54:28 -0400 -Subject: [PATCH] Chunk registration fixes - -World checks and the Chunk Add logic are inconsistent on how Y > 256, < 0, is treated - -Keep them consistent - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 335928d60dbfc07644ffeab366900c5e77e99d56..20650bfd10abfa010e71cfeede06c461d50d19a3 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -841,7 +841,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - if (entity.checkAndResetUpdateChunkPos()) { - this.getProfiler().push("chunkCheck"); - int i = Mth.floor(entity.getX() / 16.0D); -- int j = Mth.floor(entity.getY() / 16.0D); -+ int j = Math.min(15, Math.max(0, Mth.floor(entity.getY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior - int k = Mth.floor(entity.getZ() / 16.0D); - - if (!entity.inChunk || entity.xChunk != i || entity.yChunk != j || entity.zChunk != k) { diff --git a/Remapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/Remapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch deleted file mode 100644 index 0d1bb6c9bb..0000000000 --- a/Remapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 16 Jun 2016 00:17:23 -0400 -Subject: [PATCH] Remove FishingHook reference on Craft Entity removal - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -index 5668facc5bf5c56581c3ebd268f832d77ce5c05b..50322cfc07a7d93c32461faeb5e22e35ceead323 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -@@ -119,4 +119,14 @@ public class CraftFishHook extends CraftProjectile implements FishHook { - public HookState getState() { - return HookState.values()[getHandle().currentState.ordinal()]; - } -+ -+ // Paper start -+ @Override -+ public void remove() { -+ super.remove(); -+ if (getHandle().getPlayerOwner() != null) { -+ getHandle().getPlayerOwner().fishing = null; -+ } -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch b/Remapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch deleted file mode 100644 index a6a274fc00..0000000000 --- a/Remapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Sep 2016 23:48:39 -0400 -Subject: [PATCH] Auto fix bad Y levels on player login - -Bring down to a saner Y level if super high, as this can cause the server to crash - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index bd3d9182dfb2c0ae1d8c3b9aa360f94c33252592..3a2356b3e00098d100a179a05316f402390d4e9b 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -337,6 +337,7 @@ public class ServerPlayer extends Player implements ContainerListener { - @Override - public void readAdditionalSaveData(CompoundTag tag) { - super.readAdditionalSaveData(tag); -+ if (this.getY() > 300) this.setPosRaw(getX(), 257, getZ()); // Paper - bring down to a saner Y level if out of world - if (tag.contains("playerGameType", 99)) { - if (this.getServer().getForceGameType()) { - this.gameMode.setGameModeForPlayer(this.getServer().getDefaultGameType(), GameType.NOT_SET); diff --git a/Remapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch b/Remapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch deleted file mode 100644 index d6b80297c0..0000000000 --- a/Remapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 5 Oct 2016 16:27:36 -0500 -Subject: [PATCH] Option to remove corrupt tile entities - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6eca3f300020006f02dd36253b522db442e3cc33..622affa0dc3cc1eadaed400511f2ca2cde3fca2a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -300,4 +300,9 @@ public class PaperWorldConfig { - preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); - log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); - } -+ -+ public boolean removeCorruptTEs = false; -+ private void removeCorruptTEs() { -+ removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 70f5b025c2b803df3de8a51cbcfafbe915866f42..d69ccb1f31f31ebeee477df20ce1410f9e485eb7 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -678,6 +678,12 @@ public class LevelChunk implements ChunkAccess { - "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); - e.printStackTrace(); - ServerInternalException.reportInternalException(e); -+ -+ if (this.world.paperConfig.removeCorruptTEs) { -+ this.removeBlockEntity(blockEntity.getBlockPos()); -+ this.markUnsaved(); -+ org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); -+ } - // Paper end - // CraftBukkit end - } diff --git a/Remapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch b/Remapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch deleted file mode 100644 index 20a798bf8d..0000000000 --- a/Remapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlphaBlend -Date: Sun, 16 Oct 2016 23:19:30 -0700 -Subject: [PATCH] Add EntityZapEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.java -index 6ecf7afe5fd7c4c95a17eaed1445d034aa2d5f18..e512a38ccbba93266f0234e3b2fcf7f62693039b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Pig.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java -@@ -254,6 +254,11 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { - } - - entitypigzombie.setPersistenceRequired(); -+ // Paper start -+ if (CraftEventFactory.callEntityZapEvent(this, lightning, entitypigzombie).isCancelled()) { -+ return; -+ } -+ // Paper end - // CraftBukkit start - if (CraftEventFactory.callPigZapEvent(this, lightning, entitypigzombie).isCancelled()) { - return; -diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 2f99bdaabe1c1a6a4e1a7e2bd533a63b12818be1..5648a4a4d8511ac8c46c61245a7ff83753a3e51f 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/Villager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -786,6 +786,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); - Witch entitywitch = (Witch) EntityType.WITCH.create((Level) world); - -+ // Paper start -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, lightning, entitywitch).isCancelled()) { -+ return; -+ } -+ // Paper end -+ - entitywitch.moveTo(this.getX(), this.getY(), this.getZ(), this.yRot, this.xRot); - entitywitch.finalizeSpawn(world, world.getCurrentDifficultyAt(entitywitch.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null, (CompoundTag) 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 7fde1bb7587e567270e3f936381c6d361870211f..81af3e2e0964b6e179f92a342efdae943be18b75 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1086,6 +1086,14 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start -+ public static com.destroystokyo.paper.event.entity.EntityZapEvent callEntityZapEvent (Entity entity, Entity lightning, Entity changedEntity) { -+ com.destroystokyo.paper.event.entity.EntityZapEvent event = new com.destroystokyo.paper.event.entity.EntityZapEvent(entity.getBukkitEntity(), (LightningStrike) lightning.getBukkitEntity(), changedEntity.getBukkitEntity()); -+ entity.getBukkitEntity().getServer().getPluginManager().callEvent(event); -+ return event; -+ } -+ // Paper end -+ - public static HorseJumpEvent callHorseJumpEvent(Entity horse, float power) { - HorseJumpEvent event = new HorseJumpEvent((AbstractHorse) horse.getBukkitEntity(), power); - horse.getBukkitEntity().getServer().getPluginManager().callEvent(event); diff --git a/Remapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/Remapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch deleted file mode 100644 index 782f93006e..0000000000 --- a/Remapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 12 Nov 2016 23:25:22 -0600 -Subject: [PATCH] Filter bad data from ArmorStand and SpawnEgg items - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 622affa0dc3cc1eadaed400511f2ca2cde3fca2a..e83216be5a00d5b927d8c2fc364551bd3077c974 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -2,6 +2,7 @@ package com.destroystokyo.paper; - - import java.util.List; - -+import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -305,4 +306,12 @@ public class PaperWorldConfig { - private void removeCorruptTEs() { - removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); - } -+ -+ public boolean filterNBTFromSpawnEgg = true; -+ private void fitlerNBTFromSpawnEgg() { -+ filterNBTFromSpawnEgg = getBoolean("filter-nbt-data-from-spawn-eggs-and-related", true); -+ if (!filterNBTFromSpawnEgg) { -+ Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -index 1d87717cc9002ea202ee2ca614aaa8a4c7ea3cb2..ff8f7e4569a889ead1512b7c9908f9c5cad9eed5 100644 ---- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -270,6 +270,13 @@ public class FallingBlockEntity extends Entity { - @Override - protected void readAdditionalSaveData(CompoundTag tag) { - this.blockState = NbtUtils.readBlockState(tag.getCompound("BlockState")); -+ // Paper start - Block FallingBlocks with Command Blocks -+ // Check mappings on update - dc = "repeating_command_block" - dd = "chain_command_block" -+ final Block b = this.blockState.getBlock(); -+ if (this.level.paperConfig.filterNBTFromSpawnEgg && (b == Blocks.COMMAND_BLOCK || b == Blocks.REPEATING_COMMAND_BLOCK || b == Blocks.CHAIN_COMMAND_BLOCK)) { -+ this.blockState = Blocks.STONE.defaultBlockState(); -+ } -+ // Paper end - this.time = tag.getInt("Time"); - if (tag.contains("HurtEntities", 99)) { - this.hurtEntities = tag.getBoolean("HurtEntities"); diff --git a/Remapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch b/Remapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch deleted file mode 100644 index be4de8cb23..0000000000 --- a/Remapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: vemacs -Date: Wed, 23 Nov 2016 08:31:45 -0500 -Subject: [PATCH] Cache user authenticator threads - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 0597c0c3e881dd43cf91bd3088ed30dfecfe8098..175bf535066afc42de8a3f0d11c46af66f3e3e52 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1388,7 +1388,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - } - -- player.entitiesToRemove.remove(Integer.valueOf(this.entity.getId())); -+ player.removeQueue.remove(Integer.valueOf(this.entity.getId())); - // CraftBukkit end - - if (flag1 && this.trackedPlayerMap.putIfAbsent(player, true) == null) { // Paper -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 3a2356b3e00098d100a179a05316f402390d4e9b..3cde25c2479adcc4ce3014e5ac2ec0710bffeea9 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -4,7 +4,9 @@ import com.google.common.collect.Lists; - import com.mojang.authlib.GameProfile; - import com.mojang.datafixers.util.Either; - import com.mojang.serialization.DataResult; -+import java.util.ArrayDeque; // Paper - import java.util.Collection; -+import java.util.Deque; // Paper - import java.util.Iterator; - import java.util.List; - import java.util.Optional; -@@ -169,7 +171,7 @@ public class ServerPlayer extends Player implements ContainerListener { - public ServerGamePacketListenerImpl connection; - public final MinecraftServer server; - public final ServerPlayerGameMode gameMode; -- public final List entitiesToRemove = Lists.newLinkedList(); -+ public final Deque removeQueue = new ArrayDeque<>(); // Paper - private final PlayerAdvancements advancements; - private final ServerStatsCounter stats; - private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE; -@@ -544,16 +546,23 @@ public class ServerPlayer extends Player implements ContainerListener { - this.containerMenu = this.inventoryMenu; - } - -- while (!this.entitiesToRemove.isEmpty()) { -- int i = Math.min(this.entitiesToRemove.size(), Integer.MAX_VALUE); -+ while (!this.removeQueue.isEmpty()) { -+ int i = Math.min(this.removeQueue.size(), Integer.MAX_VALUE); - int[] aint = new int[i]; -- Iterator iterator = this.entitiesToRemove.iterator(); -+ //Iterator iterator = this.removeQueue.iterator(); // Paper - int j = 0; - -- while (iterator.hasNext() && j < i) { -+ // Paper start -+ /* while (iterator.hasNext() && j < i) { - aint[j++] = (Integer) iterator.next(); - iterator.remove(); -+ } */ -+ -+ Integer integer; -+ while (j < i && (integer = this.removeQueue.poll()) != null) { -+ aint[j++] = integer.intValue(); - } -+ // Paper end - - this.connection.send(new ClientboundRemoveEntitiesPacket(aint)); - } -@@ -1558,7 +1567,14 @@ public class ServerPlayer extends Player implements ContainerListener { - this.lastSentHealth = -1.0F; - this.lastSentFood = -1; - // this.recipeBook.a((RecipeBook) entityplayer.recipeBook); // CraftBukkit -- this.entitiesToRemove.addAll(oldPlayer.entitiesToRemove); -+ // Paper start - Optimize remove queue - vanilla copies player objects, but CB doesn't. This method currently only -+ // Applies to the same player, so we need to not duplicate our removal queue. The rest of this method does "resetting" -+ // type logic so it does need to be called, maybe? This is silly. -+ // this.removeQueue.addAll(entityplayer.removeQueue); -+ if (this.removeQueue != oldPlayer.removeQueue) { -+ this.removeQueue.addAll(oldPlayer.removeQueue); -+ } -+ // Paper end - this.seenCredits = oldPlayer.seenCredits; - this.enteredNetherPosition = oldPlayer.enteredNetherPosition; - this.setShoulderEntityLeft(oldPlayer.getShoulderEntityLeft()); -@@ -1748,13 +1764,13 @@ public class ServerPlayer extends Player implements ContainerListener { - if (entity instanceof Player) { - this.connection.send(new ClientboundRemoveEntitiesPacket(new int[]{entity.getId()})); - } else { -- this.entitiesToRemove.add((Integer) entity.getId()); // CraftBukkit - decompile error -+ this.removeQueue.add((Integer) entity.getId()); // CraftBukkit - decompile error - } - - } - - public void cancelRemoveEntity(Entity entity) { -- this.entitiesToRemove.remove((Integer) entity.getId()); // CraftBukkit - decompile error -+ this.removeQueue.remove((Integer) entity.getId()); // CraftBukkit - decompile error - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch b/Remapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch deleted file mode 100644 index f3b8068513..0000000000 --- a/Remapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Fri, 25 Nov 2016 13:22:40 +0000 -Subject: [PATCH] Optimise removeQueue - - -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 9dbb3bb79ae2de6635f71e5ee5bebeb5e57b624e..e3c1460c580ea348ee6d436018244441a5a1206e 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -114,6 +114,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - - } - -+ // Paper start - Cache authenticator threads -+ private static final AtomicInteger threadId = new AtomicInteger(0); -+ private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool( -+ r -> new Thread(r, "User Authenticator #" + threadId.incrementAndGet()) -+ ); -+ // Paper end - // Spigot start - public void initUUID() - { -@@ -193,8 +199,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce)); - } else { - // Spigot start -- new Thread("User Authenticator #" + ServerLoginPacketListenerImpl.UNIQUE_THREAD_ID.incrementAndGet()) { -- -+ // Paper start - Cache authenticator threads -+ authenticatorPool.execute(new Runnable() { - @Override - public void run() { - try { -@@ -205,7 +211,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + gameProfile.getName(), ex); - } - } -- }.start(); -+ }); -+ // Paper end - // Spigot end - } - -@@ -234,7 +241,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - throw new IllegalStateException("Protocol error", cryptographyexception); - } - -- Thread thread = new Thread("User Authenticator #" + ServerLoginPacketListenerImpl.UNIQUE_THREAD_ID.incrementAndGet()) { -+ // Paper start - Cache authenticator threads -+ authenticatorPool.execute(new Runnable() { - public void run() { - GameProfile gameprofile = ServerLoginPacketListenerImpl.this.gameProfile; - -@@ -279,10 +287,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - - return ServerLoginPacketListenerImpl.this.server.getPreventProxyConnections() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; - } -- }; -- -- thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(ServerLoginPacketListenerImpl.LOGGER)); -- thread.start(); -+ }); -+ // Paper end - } - - // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch b/Remapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch deleted file mode 100644 index 360a4a34cc..0000000000 --- a/Remapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: willies952002 -Date: Mon, 28 Nov 2016 10:21:52 -0500 -Subject: [PATCH] Allow Reloading of Command Aliases - -Reload the aliases stored in commands.yml - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index bbe0978f56d23b7defce765d381d4a7c20acd75c..9365fd2bcf74755c90c4ae9b550969e97a22c639 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2281,5 +2281,24 @@ public final class CraftServer implements Server { - DefaultPermissions.registerCorePermissions(); - CraftDefaultPermissions.registerCorePermissions(); - } -+ -+ @Override -+ public boolean reloadCommandAliases() { -+ Set removals = getCommandAliases().keySet().stream() -+ .map(key -> key.toLowerCase(java.util.Locale.ENGLISH)) -+ .collect(java.util.stream.Collectors.toSet()); -+ getCommandMap().getKnownCommands().keySet().removeIf(removals::contains); -+ File file = getCommandsConfigFile(); -+ try { -+ commandsConfiguration.load(file); -+ } catch (FileNotFoundException ex) { -+ return false; -+ } catch (IOException | org.bukkit.configuration.InvalidConfigurationException ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex); -+ return false; -+ } -+ commandMap.registerServerAliases(); -+ return true; -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch b/Remapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch deleted file mode 100644 index 0ab2cb875a..0000000000 --- a/Remapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlphaBlend -Date: Thu, 8 Sep 2016 08:48:33 -0700 -Subject: [PATCH] Add source to PlayerExpChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index a4a1e836767d0b2b71c3277a28eb72418fa76210..f932fc4f8240b48f8e518af05d1521bc8ff9cbee 100644 ---- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -202,7 +202,7 @@ public class ExperienceOrb extends Entity { - } - - if (this.value > 0) { -- player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, this.value).getAmount()); // CraftBukkit - this.value -> event.getAmount() -+ player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object - } - - this.remove(); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 81af3e2e0964b6e179f92a342efdae943be18b75..c85fcad33e17c8ae2e4ee5cb873dbd4166fcc7f5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -109,6 +109,7 @@ import org.bukkit.entity.ThrownPotion; - import org.bukkit.entity.Vehicle; - import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; -+import org.bukkit.entity.ExperienceOrb; // Paper - import org.bukkit.event.Cancellable; - import org.bukkit.event.Event; - import org.bukkit.event.Event.Result; -@@ -1045,6 +1046,17 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start - Add orb -+ public static PlayerExpChangeEvent callPlayerExpChangeEvent(net.minecraft.world.entity.player.Player entity, net.minecraft.world.entity.ExperienceOrb entityOrb) { -+ Player player = (Player) entity.getBukkitEntity(); -+ ExperienceOrb source = (ExperienceOrb) entityOrb.getBukkitEntity(); -+ int expAmount = source.getExperience(); -+ PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, source, expAmount); -+ Bukkit.getPluginManager().callEvent(event); -+ return event; -+ } -+ // Paper end -+ - public static boolean handleBlockGrowEvent(Level world, BlockPos pos, net.minecraft.world.level.block.state.BlockState block) { - return handleBlockGrowEvent(world, pos, block, 3); - } diff --git a/Remapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch b/Remapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch deleted file mode 100644 index 6845784927..0000000000 --- a/Remapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 16 Dec 2016 16:03:19 -0600 -Subject: [PATCH] Don't let fishinghooks use portals - - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -index 2f67c2065ef29f17f12190b25bd1ea53e1fb55b4..fa078167dd9e0cae80516549eef0e554c13938a3 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -@@ -237,6 +237,11 @@ public class FishingHook extends Projectile { - - this.setDeltaMovement(this.getDeltaMovement().scale(0.92D)); - this.reapplyPosition(); -+ // Paper start - These shouldn't be going through portals -+ if (this.isInsidePortal) { -+ this.remove(); -+ } -+ // Paper end - } - } - diff --git a/Remapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch b/Remapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch deleted file mode 100644 index 0f4f99f50a..0000000000 --- a/Remapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Fri, 16 Dec 2016 21:25:39 -0600 -Subject: [PATCH] Add ProjectileCollideEvent - - -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 0dc5792d542658107c9c22c1f920986decd13920..3ce431c1fdf1f5bd62b49f26cca188e939e98efa 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -196,6 +196,17 @@ public abstract class AbstractArrow extends Projectile { - } - } - -+ // Paper start - Call ProjectileCollideEvent -+ // TODO: flag - noclip - call cancelled? -+ if (object instanceof EntityHitResult) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)object); -+ if (event.isCancelled()) { -+ object = null; -+ movingobjectpositionentity = null; -+ } -+ } -+ // Paper end -+ - if (object != null && !flag) { - this.preOnHit((HitResult) object); // CraftBukkit - projectile hit event - this.hasImpulse = true; -diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -index bdff1c57f64d1bf29f2050f06c8b585d395b2c5c..872ff430547276e2a41a48aa07ae63b87ab39e5d 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -@@ -12,6 +12,7 @@ import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; - import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.level.Level; -+import net.minecraft.world.phys.EntityHitResult; - import net.minecraft.world.phys.HitResult; - import net.minecraft.world.phys.Vec3; - import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit -@@ -71,7 +72,16 @@ public abstract class AbstractHurtingProjectile extends Projectile { - - HitResult movingobjectposition = ProjectileUtil.getHitResult((Entity) this, this::canHitEntity); - -- if (movingobjectposition.getType() != HitResult.Type.MISS) { -+ // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition instanceof EntityHitResult) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)movingobjectposition); -+ if (event.isCancelled()) { -+ movingobjectposition = null; -+ } -+ } -+ // Paper end -+ -+ if (movingobjectposition != null && movingobjectposition.getType() != HitResult.Type.MISS) { // Paper - add null check in case cancelled - this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event - - // CraftBukkit start - Fire ProjectileHitEvent -diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java -index 23f255bfa63cd16e2930fc932a2f4df8e522f2dc..becb07cda7388bcf2e987f06557894ae50d70dbf 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java -@@ -13,6 +13,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; - import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity; - import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.phys.BlockHitResult; -+import net.minecraft.world.phys.EntityHitResult; - import net.minecraft.world.phys.HitResult; - import net.minecraft.world.phys.Vec3; - -@@ -57,7 +58,17 @@ public abstract class ThrowableProjectile extends Projectile { - } - - if (movingobjectposition.getType() != HitResult.Type.MISS && !flag) { -+ // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition instanceof EntityHitResult) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)movingobjectposition); -+ if (event.isCancelled()) { -+ movingobjectposition = null; -+ } -+ } -+ if (movingobjectposition != null) { -+ // Paper end - this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event -+ } // Paper - } - - this.checkInsideBlocks(); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index c85fcad33e17c8ae2e4ee5cb873dbd4166fcc7f5..3f082b7fd50752728917a7da28cba4cb396a9fdf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1190,6 +1190,16 @@ public class CraftEventFactory { - return CraftItemStack.asNMSCopy(bitem); - } - -+ // Paper start -+ public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, EntityHitResult position) { -+ 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); -+ Bukkit.getPluginManager().callEvent(event); -+ return event; -+ } -+ // Paper end -+ - public static ProjectileLaunchEvent callProjectileLaunchEvent(Entity entity) { - Projectile bukkitEntity = (Projectile) entity.getBukkitEntity(); - ProjectileLaunchEvent event = new ProjectileLaunchEvent(bukkitEntity); diff --git a/Remapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch b/Remapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch deleted file mode 100644 index f8a0e7b1ea..0000000000 --- a/Remapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 19 Dec 2016 23:07:42 -0500 -Subject: [PATCH] Prevent Pathfinding out of World Border - -This prevents Entities from trying to run outside of the World Border - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index 25bc3adfad956157cef0953e6e632b7b7e352f3a..c3082f5dd64413a47421cb01538bec846bf21d2c 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -148,7 +148,7 @@ public abstract class PathNavigation { - // Paper start - Pathfind event - boolean copiedSet = false; - for (BlockPos possibleTarget : set) { -- if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), -+ if (!getEntity().getCommandSenderWorld().getWorldBorder().isInBounds(possibleTarget) || !new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), // Paper - don't path out of world border - MCUtil.toLocation(getEntity().level, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { - if (!copiedSet) { - copiedSet = true; diff --git a/Remapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch b/Remapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch deleted file mode 100644 index 6a3d81e0fe..0000000000 --- a/Remapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 2 Dec 2016 00:11:43 -0500 -Subject: [PATCH] Optimize World.isLoaded(BlockPosition)Z - -Reduce method invocations for World.isLoaded(BlockPosition)Z - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 5f3d17cb247156fc8aaa7a763e402c2bbb42a7ec..ecb6378a285dff4b34170410387ebb7a8510a6dc 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -305,6 +305,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return chunk == null ? null : chunk.getFluidState(blockposition); - } - -+ public final boolean hasChunkAt(BlockPos pos) { -+ return getChunkIfLoaded(pos.getX() >> 4, pos.getZ() >> 4) != null; // Paper -+ } -+ - public final boolean isLoadedAndInBounds(BlockPos blockposition) { // Paper - final for inline - return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; - } diff --git a/Remapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch b/Remapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch deleted file mode 100644 index b839110284..0000000000 --- a/Remapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 20 Dec 2016 15:15:11 -0500 -Subject: [PATCH] Bound Treasure Maps to World Border - -Make it so a Treasure Map does not target a structure outside of the -World Border, where players are not even able to reach. - -This also would help the case where a players close to the border, and one -that is outside happens to be closer, but unreachable, yet another reachable -one is in border that would of been missed. - -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 0846f649dca3422dbab3bb0a4826e27430cc8186..7a728ca96ee2eaf776c391ba8351196a526e18ec 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -36,6 +36,18 @@ public class WorldBorder { - return (double) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ(); - } - -+ // Paper start -+ private final BlockPos.MutableBlockPos mutPos = new BlockPos.MutableBlockPos(); -+ public boolean isBlockInBounds(int chunkX, int chunkZ) { -+ this.mutPos.setValues(chunkX, 64, chunkZ); -+ return this.isInBounds(this.mutPos); -+ } -+ public boolean isChunkInBounds(int chunkX, int chunkZ) { -+ this.mutPos.setValues(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15); -+ return this.isInBounds(this.mutPos); -+ } -+ // Paper end -+ - public boolean isWithinBounds(ChunkPos pos) { - return (double) pos.getMaxBlockX() > this.getMinX() && (double) pos.getMinBlockX() < this.getMaxX() && (double) pos.getMaxBlockZ() > this.getMinZ() && (double) pos.getMinBlockZ() < this.getMaxZ(); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -index 9f60abfe0a37e30c5528a1ca0546295b00598798..0624b8270bc28c83c5479cd51fa4633ed5c36f44 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -@@ -175,6 +175,7 @@ public abstract class StructureFeature { - int i2 = l + k * k1; - int j2 = i1 + k * l1; - ChunkPos chunkcoordintpair = this.getPotentialFeatureChunk(config, worldSeed, seededrandom, i2, j2); -+ if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper - ChunkAccess ichunkaccess = world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); - StructureStart structurestart = structureAccessor.getStartForFeature(SectionPos.of(ichunkaccess.getPos(), 0), this, ichunkaccess); - diff --git a/Remapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch b/Remapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch deleted file mode 100644 index 2eabafdf57..0000000000 --- a/Remapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 20 Dec 2016 15:26:27 -0500 -Subject: [PATCH] Configurable Cartographer Treasure Maps - -Allow configuring for cartographers to return the same map location - -Also allow turning off treasure maps all together as they can eat up Map ID's -which are limited in quantity. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e83216be5a00d5b927d8c2fc364551bd3077c974..2dc58b9f769ea43b737804456aafab47ecc143b8 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -314,4 +314,14 @@ public class PaperWorldConfig { - Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); - } - } -+ -+ public boolean enableTreasureMaps = true; -+ public boolean treasureMapsAlreadyDiscovered = false; -+ private void treasureMapsAlreadyDiscovered() { -+ enableTreasureMaps = getBoolean("enable-treasure-maps", true); -+ treasureMapsAlreadyDiscovered = getBoolean("treasure-maps-return-already-discovered", false); -+ if (treasureMapsAlreadyDiscovered) { -+ log("Treasure Maps will return already discovered locations"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -index fd1b84baae5f333c58dbbdcbfaa9198328f0961d..7d490e1be772be22c3ab75c7e356465183a5c6b1 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -+++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -@@ -124,7 +124,8 @@ public class VillagerTrades { - return null; - } else { - ServerLevel worldserver = (ServerLevel) entity.level; -- BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, entity.blockPosition(), 100, true); -+ if (!worldserver.paperConfig.enableTreasureMaps) return null; // Paper -+ BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, entity.blockPosition(), 100, !worldserver.paperConfig.treasureMapsAlreadyDiscovered); // Paper - - if (blockposition != null) { - ItemStack itemstack = MapItem.create(worldserver, blockposition.getX(), blockposition.getZ(), (byte) 2, true, true); -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java -index a3ce120b0da62f9be938c58c3414ce997f5d30ea..81a8331bfdf30da6ea69952ae42d3c77a2103bfd 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java -@@ -64,7 +64,16 @@ public class ExplorationMapFunction extends LootItemConditionalFunction { - - if (vec3d != null) { - ServerLevel worldserver = context.getLevel(); -- BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, new BlockPos(vec3d), this.searchRadius, this.skipKnownStructures); -+ // Paper start -+ if (!worldserver.paperConfig.enableTreasureMaps) { -+ /* -+ * NOTE: I fear users will just get a plain map as their "treasure" -+ * This is preferable to disrespecting the config. -+ */ -+ return stack; -+ } -+ // Paper end -+ BlockPos blockposition = worldserver.findNearestMapFeature(this.destination, new BlockPos(vec3d), this.searchRadius, !worldserver.paperConfig.treasureMapsAlreadyDiscovered && this.skipKnownStructures); // Paper - - if (blockposition != null) { - ItemStack itemstack1 = MapItem.create(worldserver, blockposition.getX(), blockposition.getZ(), this.zoom, true, true); diff --git a/Remapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch b/Remapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch deleted file mode 100644 index 329afa7401..0000000000 --- a/Remapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Dec 2016 03:48:29 -0500 -Subject: [PATCH] Optimize ItemStack.isEmpty() - -Remove hashMap lookup every check, simplify code to remove ternary - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 123025c6dc9a2eea56c7db5cb508cdfd7c6cc97b..a0815c0d7f68f345dc48c73b8253de637c7a3e0f 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -206,7 +206,7 @@ public final class ItemStack { - } - - public boolean isEmpty() { -- return this == ItemStack.EMPTY ? true : (this.getItem() != null && this.getItem() != Items.AIR ? this.count <= 0 : true); -+ return this == ItemStack.NULL_ITEM || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper - } - - public ItemStack split(int amount) { diff --git a/Remapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch b/Remapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch deleted file mode 100644 index 970e858ba4..0000000000 --- a/Remapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 21 Dec 2016 11:47:25 -0600 -Subject: [PATCH] Add API methods to control if armour stands can move - - -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 09d39b73e8a3987e58a502bd914a6451b807421b..46f0ebfc99352ec8b64bdff2c6bb8d17ecfeb619 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -1,6 +1,5 @@ - package net.minecraft.world.entity; - --import PathfinderGoalFloat; - import com.google.common.collect.Maps; - import java.util.Arrays; - import java.util.Iterator; -@@ -39,6 +38,7 @@ import net.minecraft.world.entity.ai.control.BodyRotationControl; - import net.minecraft.world.entity.ai.control.JumpControl; - import net.minecraft.world.entity.ai.control.LookControl; - import net.minecraft.world.entity.ai.control.MoveControl; -+import net.minecraft.world.entity.ai.goal.FloatGoal; - import net.minecraft.world.entity.ai.goal.Goal; - import net.minecraft.world.entity.ai.goal.GoalSelector; - import net.minecraft.world.entity.ai.navigation.GroundPathNavigation; -@@ -47,6 +47,8 @@ import net.minecraft.world.entity.ai.sensing.Sensing; - import net.minecraft.world.entity.decoration.HangingEntity; - import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; - import net.minecraft.world.entity.item.ItemEntity; -+import net.minecraft.world.entity.monster.Blaze; -+import net.minecraft.world.entity.monster.EnderMan; - import net.minecraft.world.entity.monster.Enemy; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.vehicle.Boat; -@@ -97,7 +99,7 @@ public abstract class Mob extends LivingEntity { - private final BodyRotationControl bodyRotationControl; - protected PathNavigation navigation; - public GoalSelector goalSelector; -- @Nullable public PathfinderGoalFloat goalFloat; // Paper -+ @Nullable public FloatGoal goalFloat; // Paper - public GoalSelector targetSelector; - private LivingEntity target; - private final Sensing sensing; -@@ -789,7 +791,7 @@ public abstract class Mob extends LivingEntity { - if (goalFloat.validConditions()) goalFloat.update(); - this.getJumpControl().jumpIfSet(); - } -- if ((this instanceof EntityBlaze || this instanceof EntityEnderman) && isInWaterOrRainOrBubble()) { -+ if ((this instanceof Blaze || this instanceof EnderMan) && isInWaterOrRainOrBubble()) { - hurt(DamageSource.DROWN, 1.0F); - } - return; -diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 438dd75e3adffc395960b34b8bb26cbc07a4291e..8b6ec9ddf0d47bf4369b247e764f75893ab15781 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -26,6 +26,7 @@ import net.minecraft.world.entity.HumanoidArm; - import net.minecraft.world.entity.LightningBolt; - import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.Mob; -+import net.minecraft.world.entity.MoverType; - import net.minecraft.world.entity.Pose; - import net.minecraft.world.entity.projectile.AbstractArrow; - import net.minecraft.world.entity.vehicle.AbstractMinecart; -@@ -75,6 +76,7 @@ public class ArmorStand extends LivingEntity { - public Rotations rightArmPose; - public Rotations leftLegPose; - public Rotations rightLegPose; -+ public boolean canMove = true; // Paper - - public ArmorStand(EntityType type, Level world) { - super(type, world); -@@ -858,4 +860,13 @@ public class ArmorStand extends LivingEntity { - private EntityDimensions getDimensionsMarker(boolean flag) { - return flag ? ArmorStand.MARKER_DIMENSIONS : (this.isBaby() ? ArmorStand.BABY_DIMENSIONS : this.getType().getDimensions()); - } -+ -+ // Paper start -+ @Override -+ public void move(MoverType type, Vec3 movement) { -+ if (this.canMove) { -+ super.move(type, movement); -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 6b292162fb8c6416b1637b7b83e5113f6a35dbac..16f996d505b96da8a40c7709214ebbd2a0d0d9f3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -228,4 +228,15 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public boolean hasEquipmentLock(EquipmentSlot equipmentSlot, LockType lockType) { - return (getHandle().disabledSlots & (1 << CraftEquipmentSlot.getNMS(equipmentSlot).getFilterFlag() + lockType.ordinal() * 8)) != 0; - } -+ // Paper start -+ @Override -+ public boolean canMove() { -+ return getHandle().canMove; -+ } -+ -+ @Override -+ public void setCanMove(boolean move) { -+ getHandle().canMove = move; -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch b/Remapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch deleted file mode 100644 index aa2398aa87..0000000000 --- a/Remapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Tue, 27 Dec 2016 01:57:57 +0000 -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 3cde25c2479adcc4ce3014e5ac2ec0710bffeea9..4ff66138fa43cf932b95d6d3dc050a9cd7b28ad4 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2066,8 +2066,8 @@ public class ServerPlayer extends Player implements ContainerListener { - } - - @Override -- public boolean isImmobile() { -- return super.isImmobile() || !getBukkitEntity().isOnline(); -+ protected boolean isImmobile() { -+ return super.isImmobile() || (this.connection != null && this.connection.isDisconnected()); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 1b92c669bbe69bcc07a554b7b43ee99bfebc1af4..ecc393ad94332ec2a59d29f30bd60bade4e1f18e 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2818,7 +2818,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } - - public final boolean isDisconnected() { -- return !this.player.joining && !this.connection.isConnected(); -+ return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper - } - // CraftBukkit end - diff --git a/Remapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch b/Remapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch deleted file mode 100644 index 416d50b18b..0000000000 --- a/Remapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 27 Dec 2016 15:02:42 -0500 -Subject: [PATCH] String based Action Bar API - - -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index 67fa685f4b8de3eae1431c0de399c246678b542a..7b36274718b7cce24ac00530697f145648d52590 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -58,7 +58,7 @@ public class Util { - private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main"); - private static final ExecutorService IO_POOL = makeIoExecutor(); - public static LongSupplier timeSource = System::nanoTime; -- public static final UUID NIL_UUID = new UUID(0L, 0L); -+ public static final UUID NIL_UUID = new UUID(0L, 0L); public static final UUID getNullUUID() {return NIL_UUID;} // Paper OBFHELPER - private static final Logger LOGGER = LogManager.getLogger(); - - public static Collector, ?, Map> toMap() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index fc19b4cacd223b928fbdf922b828beaed630bf2e..d6d4e5ab7551f802dc2d3ab055d340d471ed0bc2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -242,6 +242,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - // Paper start -+ @Override -+ public void sendActionBar(BaseComponent[] message) { -+ if (getHandle().connection == null) return; -+ getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.ACTIONBAR, message, -1, -1, -1)); -+ } -+ -+ @Override -+ public void sendActionBar(String message) { -+ if (getHandle().connection == null || message == null || message.isEmpty()) return; -+ getHandle().connection.send(new ClientboundSetTitlesPacket(ClientboundSetTitlesPacket.Type.ACTIONBAR, CraftChatMessage.fromStringOrNull(message))); -+ } -+ -+ @Override -+ public void sendActionBar(char alternateChar, String message) { -+ if (message == null || message.isEmpty()) return; -+ sendActionBar(org.bukkit.ChatColor.translateAlternateColorCodes(alternateChar, message)); -+ } -+ - @Override - public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { - if (header != null) { diff --git a/Remapped-Spigot-Server-Patches/0132-Firework-API-s.patch b/Remapped-Spigot-Server-Patches/0132-Firework-API-s.patch deleted file mode 100644 index e3dc3d3182..0000000000 --- a/Remapped-Spigot-Server-Patches/0132-Firework-API-s.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 28 Dec 2016 07:18:33 +0100 -Subject: [PATCH] Firework API's - - -diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java -index 4c8f249e45e5deb7628997d4dbd9dab613ac5241..a91bf94ed9f2f353a685194fc91c4b101ccc1232 100644 ---- a/src/main/java/net/minecraft/nbt/CompoundTag.java -+++ b/src/main/java/net/minecraft/nbt/CompoundTag.java -@@ -153,6 +153,7 @@ public class CompoundTag implements Tag { - return NbtUtils.loadUUID(this.get(key)); - } - -+ public final boolean hasUUID(String s) { return this.hasUUID(s); } // Paper - OBFHELPER - public boolean hasUUID(String key) { - Tag nbtbase = this.get(key); - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -index 28a2c6a0fbc8b4c38f3899698504d8ca0d7ba3af..5669be107b580075fdffbcbb490513593a57fc9f 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -@@ -37,7 +37,8 @@ public class FireworkRocketEntity extends Projectile { - public static final EntityDataAccessor DATA_SHOT_AT_ANGLE = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.BOOLEAN); - private int life; - public int lifetime; -- private LivingEntity attachedToEntity; -+ public LivingEntity attachedToEntity; // Paper - public -+ public java.util.UUID spawningEntity; // Paper - - public FireworkRocketEntity(EntityType type, Level world) { - super(type, world); -@@ -284,6 +285,11 @@ public class FireworkRocketEntity extends Projectile { - } - - tag.putBoolean("ShotAtAngle", (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE)); -+ // Paper start -+ if (this.spawningEntity != null) { -+ tag.setUUID("SpawningEntity", this.spawningEntity); -+ } -+ // Paper end - } - - @Override -@@ -300,7 +306,11 @@ public class FireworkRocketEntity extends Projectile { - if (tag.contains("ShotAtAngle")) { - this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, tag.getBoolean("ShotAtAngle")); - } -- -+ // Paper start -+ if (tag.hasUUID("SpawningEntity")) { -+ this.spawningEntity = tag.getUUID("SpawningEntity"); -+ } -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java -index 8a358872d3c8357775451e7dffe267cf9121f211..e1e58b7035e6dbafdad0a04cc5333464fc4febb8 100644 ---- a/src/main/java/net/minecraft/world/item/CrossbowItem.java -+++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java -@@ -205,6 +205,7 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { - - if (flag1) { - object = new FireworkRocketEntity(world, projectile, shooter, shooter.getX(), shooter.getEyeY() - 0.15000000596046448D, shooter.getZ(), true); -+ ((FireworkRocketEntity) object).spawningEntity = shooter.getUUID(); // Paper - } else { - object = getArrow(world, shooter, crossbow, projectile); - if (creative || simulated != 0.0F) { -diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -index d3a045fc99ef77fa0905aac7c73a2e84772c73cf..dba52063d402eb2371441fa244b730a3313444fc 100644 ---- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -+++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -@@ -27,6 +27,7 @@ public class FireworkRocketItem extends Item { - Vec3 vec3d = context.getClickLocation(); - Direction enumdirection = context.getClickedFace(); - FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, context.getPlayer(), vec3d.x + (double) enumdirection.getStepX() * 0.15D, vec3d.y + (double) enumdirection.getStepY() * 0.15D, vec3d.z + (double) enumdirection.getStepZ() * 0.15D, itemstack); -+ entityfireworks.spawningEntity = context.getPlayer().getUUID(); // Paper - - world.addFreshEntity(entityfireworks); - itemstack.shrink(1); -@@ -41,7 +42,11 @@ public class FireworkRocketItem extends Item { - ItemStack itemstack = user.getItemInHand(hand); - - if (!world.isClientSide) { -- world.addFreshEntity(new FireworkRocketEntity(world, itemstack, user)); -+ // Paper start -+ final FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, itemstack, user); -+ entityfireworks.spawningEntity = user.getUUID(); -+ world.addFreshEntity(entityfireworks); -+ // Paper end - if (!user.abilities.instabuild) { - itemstack.shrink(1); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -index 5901a53b25449430ed02a80b022f83755f83a440..0fbbdd6e3fda3f834d0b0d68d868dbff1aebb673 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -@@ -1,6 +1,7 @@ - package org.bukkit.craftbukkit.entity; - - import java.util.Random; -+import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.projectile.FireworkRocketEntity; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; -@@ -78,4 +79,17 @@ public class CraftFirework extends CraftProjectile implements Firework { - public void setShotAtAngle(boolean shotAtAngle) { - getHandle().getEntityData().set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, shotAtAngle); - } -+ -+ // Paper start -+ @Override -+ public java.util.UUID getSpawningEntity() { -+ return getHandle().spawningEntity; -+ } -+ -+ @Override -+ public org.bukkit.entity.LivingEntity getBoostedEntity() { -+ LivingEntity boostedEntity = getHandle().attachedToEntity; -+ return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null; -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch b/Remapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch deleted file mode 100644 index 98fb21f40b..0000000000 --- a/Remapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 31 Dec 2016 21:44:50 -0500 -Subject: [PATCH] PlayerTeleportEndGatewayEvent - -Allows you to access the Gateway being used in a teleport event - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -index 07d89af8111673087b0534ca9fac043d3e89662b..2c974f9801d209907733bed8e6c4c9ef46e2b610 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -@@ -10,6 +10,7 @@ import net.minecraft.data.worldgen.Features; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.NbtUtils; - import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.util.Mth; -@@ -177,7 +178,7 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements - location.setPitch(player.getLocation().getPitch()); - location.setYaw(player.getLocation().getYaw()); - -- PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); -+ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(level, this.getBlockPos()).getBlock())); // Paper - Bukkit.getPluginManager().callEvent(teleEvent); - if (teleEvent.isCancelled()) { - return; diff --git a/Remapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch b/Remapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch deleted file mode 100644 index 7b2dc85ab1..0000000000 --- a/Remapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 15:24:46 -0500 -Subject: [PATCH] Provide E/TE/Chunk count stat methods - -Provides counts without the ineffeciency of using .getEntities().size() -which creates copy of the collections. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index ca189e5d160d2655175c9fab9366ff93bded2fee..6782888f7df4eea4e6378ee850424e14c5136afd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -264,6 +264,48 @@ public class CraftWorld implements World { - private int waterAmbientSpawn = -1; - private int ambientSpawn = -1; - -+ // Paper start - Provide fast information methods -+ public int getEntityCount() { -+ int ret = 0; -+ for (net.minecraft.world.entity.Entity entity : world.entitiesById.values()) { -+ if (entity.isChunkLoaded()) { -+ ++ret; -+ } -+ } -+ return ret; -+ } -+ public int getTileEntityCount() { -+ // We don't use the full world tile entity list, so we must iterate chunks -+ Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; -+ int size = 0; -+ for (ChunkHolder playerchunk : chunks.values()) { -+ net.minecraft.world.level.chunk.LevelChunk chunk = playerchunk.getTickingChunk(); -+ if (chunk == null) { -+ continue; -+ } -+ size += chunk.blockEntities.size(); -+ } -+ return size; -+ } -+ public int getTickableTileEntityCount() { -+ return world.tickableBlockEntities.size(); -+ } -+ public int getChunkCount() { -+ int ret = 0; -+ -+ for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { -+ if (chunkHolder.getTickingChunk() != null) { -+ ++ret; -+ } -+ } -+ -+ return ret; -+ } -+ public int getPlayerCount() { -+ return world.players.size(); -+ } -+ // Paper end -+ - private static final Random rand = new Random(); - - public CraftWorld(ServerLevel world, ChunkGenerator gen, Environment env) { diff --git a/Remapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch b/Remapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch deleted file mode 100644 index 09ab2be15a..0000000000 --- a/Remapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 15:41:58 -0500 -Subject: [PATCH] Enforce Sync Player Saves - -Saving players async is extremely dangerous. This will force it to main -the same way we handle async chunk loads. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 59fb19cfebe4f488fd02f02db31029d44b65e408..cebf536e9d16d44c4b2a91b5b4be053cd7f44045 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1043,11 +1043,13 @@ public abstract class PlayerList { - } - - public void saveAll() { -+ MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { -- this.save((ServerPlayer) this.players.get(i)); -+ this.savePlayerFile((EntityPlayer) this.players.get(i)); - } - MinecraftTimings.savePlayers.stopTiming(); // Paper -+ return null; }); // Paper - ensure main - } - - public UserWhiteList getWhiteList() { diff --git a/Remapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch b/Remapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch deleted file mode 100644 index da9f57d585..0000000000 --- a/Remapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Sun, 8 Jan 2017 04:31:36 +0000 -Subject: [PATCH] Don't allow entities to ride themselves - #572 - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c3aece8e5001828edea304b2a8377e9a28b34cfe..a9ed1c3ce6361a86dd58501f5b0ce5d6bbfb8adf 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2045,6 +2045,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - protected boolean addPassenger(Entity entity) { // CraftBukkit -+ if (entity == this) throw new IllegalArgumentException("Entities cannot become a passenger of themselves"); // Paper - issue 572 - if (entity.getVehicle() != this) { - throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)"); - } else { diff --git a/Remapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/Remapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch deleted file mode 100644 index 44aa5bf7e5..0000000000 --- a/Remapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch +++ /dev/null @@ -1,332 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 16:31:46 -0500 -Subject: [PATCH] ExperienceOrbs API for Reason/Source/Triggering player - -Adds lots of information about why this orb exists. - -Replaces isFromBottle() with logic that persists entity reloads too. - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index ed4309d5e567b20fd4aa025e7c82d8943bf1d8e1..26ce794cb8d089c03fab5dd0a0c910783d10b72e 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -409,7 +409,7 @@ public class ServerPlayerGameMode { - - // Drop event experience - if (flag && event != null) { -- iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop()); -+ iblockdata.getBlock().dropExperience(this.level, pos, event.getExpToDrop(), this.player); // Paper - } - - return true; -diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index f932fc4f8240b48f8e518af05d1521bc8ff9cbee..3ddb0a9f15c920c9a2080f76edfda0504c1e287a 100644 ---- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -30,13 +30,63 @@ public class ExperienceOrb extends Entity { - public int value; - private Player followingPlayer; - private int followingTime; -+ // Paper start -+ public java.util.UUID sourceEntityId; -+ public java.util.UUID triggerEntityId; -+ public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; -+ -+ private void loadPaperNBT(CompoundTag nbttagcompound) { -+ if (!nbttagcompound.contains("Paper.ExpData", 10)) { // 10 = compound -+ return; -+ } -+ CompoundTag comp = nbttagcompound.getCompound("Paper.ExpData"); -+ if (comp.hasUUID("source")) { -+ this.sourceEntityId = comp.getUUID("source"); -+ } -+ if (comp.hasUUID("trigger")) { -+ this.triggerEntityId = comp.getUUID("trigger"); -+ } -+ if (comp.contains("reason")) { -+ String reason = comp.getString("reason"); -+ try { -+ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason); -+ } catch (Exception e) { -+ this.level.getCraftServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason); -+ } -+ } -+ } -+ private void savePaperNBT(CompoundTag nbttagcompound) { -+ CompoundTag comp = new CompoundTag(); -+ if (this.sourceEntityId != null) { -+ comp.setUUID("source", this.sourceEntityId); -+ } -+ if (this.triggerEntityId != null) { -+ comp.setUUID("trigger", triggerEntityId); -+ } -+ if (this.spawnReason != null && this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) { -+ comp.putString("reason", this.spawnReason.name()); -+ } -+ nbttagcompound.put("Paper.ExpData", comp); -+ } - - public ExperienceOrb(Level world, double x, double y, double z, int amount) { -+ this(world, x, y, z, amount, null, null); -+ } -+ -+ public EntityExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { -+ this(world, d0, d1, d2, i, reason, triggerId, null); -+ } -+ -+ public EntityExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { - this(EntityType.EXPERIENCE_ORB, world); -- this.setPos(x, y, z); -+ this.sourceEntityId = sourceId != null ? sourceId.getUUID() : null; -+ this.triggerEntityId = triggerId != null ? triggerId.getUUID() : null; -+ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; -+ // Paper end -+ this.setPos(d0, d1, d2); - this.yRot = (float) (this.random.nextDouble() * 360.0D); - this.setDeltaMovement((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D); -- this.value = amount; -+ this.value = i; - } - - public ExperienceOrb(EntityType type, Level world) { -@@ -167,6 +217,7 @@ public class ExperienceOrb extends Entity { - tag.putShort("Health", (short) this.health); - tag.putShort("Age", (short) this.age); - tag.putShort("Value", (short) this.value); -+ this.savePaperNBT(tag); // Paper - } - - @Override -@@ -174,6 +225,7 @@ public class ExperienceOrb extends Entity { - this.health = tag.getShort("Health"); - this.age = tag.getShort("Age"); - this.value = tag.getShort("Value"); -+ this.loadPaperNBT(tag); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 1131d86080b3100437aa18a00c6277fcea4b7ea8..c6aa5328907f85cd210b1c20ff407e60d9b03349 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1591,7 +1591,8 @@ public abstract class LivingEntity extends Entity { - int j = ExperienceOrb.getExperienceValue(i); - - i -= j; -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); -+ LivingEntity attacker = lastHurtByPlayer != null ? lastHurtByPlayer : lastHurtByMob; // Paper -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this)); // Paper - } - this.expToDrop = 0; - } -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 ab2a19554aa1541e924104a70364f957ff8b33f9..e0f2a70870ff97ae2e8f216a202787bbcba6c6a9 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Animal.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java -@@ -260,7 +260,7 @@ public abstract class Animal extends AgableMob { - if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { - // CraftBukkit start - use event experience - if (experience > 0) { -- worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience)); -+ worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper - } - // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java -index 83fcfd888a335e3c054174e1f55e92fea878f7ab..c2d98222f575d7383e4c040730f6d531bdb0d7b6 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Fox.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java -@@ -1306,7 +1306,7 @@ public class Fox extends Animal { - if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { - // CraftBukkit start - use event experience - if (experience > 0) { -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience)); -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityfox)); // Paper - } - // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index 2ae59200ed67ab68645b569ba03839e8cedc9aa8..c54f4b83b9f2fdb15ddb363be0a179a05eb3693b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -@@ -561,7 +561,7 @@ public class Turtle extends Animal { - Random random = this.animal.getRandom(); - - if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), random.nextInt(7) + 1)); -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), random.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper; - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index 39298b69918da890c3faa516f80d1a69adb88fe2..ae3cf71f14526e1f356216dfaa899c8f5083d46d 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -661,7 +661,7 @@ public class EnderDragon extends Mob implements Enemy { - int j = ExperienceOrb.getExperienceValue(amount); - - amount -= j; -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this)); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 5648a4a4d8511ac8c46c61245a7ff83753a3e51f..a66fab2e04a5d87ced139ed15d2434c5ffcec695 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/Villager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -599,7 +599,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - } - - if (offer.shouldRewardExp()) { -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i)); -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTradingPlayer(), this)); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -index 15570b9ba2443ce8c6f48dfbc13cdf45de8b45ac..69d92590d265abe8a04d8bf48bbe9a6ae606ae50 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -@@ -188,7 +188,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill - if (offer.shouldRewardExp()) { - int i = 3 + this.random.nextInt(4); - -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i)); -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTradingPlayer(), this)); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -index fa078167dd9e0cae80516549eef0e554c13938a3..7bff012f3cd4458673ee02e5f5f830fc0ef983a3 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -@@ -500,7 +500,7 @@ public class FishingHook extends Projectile { - this.level.addFreshEntity(entityitem); - // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() - if (playerFishEvent.getExpToDrop() > 0) { -- entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop())); -+ entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper - } - // CraftBukkit end - if (itemstack1.getItem().is((Tag) ItemTags.FISHES)) { -diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java -index 85b8f8f52c5035054ad9f665fce735260a54c270..42c7371355b6e36e31daf055317f015240761b8b 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java -@@ -54,7 +54,7 @@ public class ThrownExperienceBottle extends ThrowableItemProjectile { - int j = ExperienceOrb.getExperienceValue(i); - - i -= j; -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, getOwner(), this)); // Paper - } - - this.remove(); -diff --git a/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java b/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java -index ea6e1a96bd1fa9fbb87f65a169aa1e5af0589f34..5b9111d502bc12ab9e5c37e4d66c21aa37007b53 100644 ---- a/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java -+++ b/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java -@@ -7,7 +7,7 @@ import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; - - public class FurnaceResultSlot extends Slot { - -- private final Player player; -+ private final Player player; public final Player getPlayer() { return this.player; } // Paper OBFHELPER - private int removeCount; - - public FurnaceResultSlot(Player player, Container inventory, int index, int x, int y) { -diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -index e8bc37e1f7aebd192f048d7b056a41c50ceef9f5..e9e830117fe3e4e02a51eef8671a3d3b48c2858e 100644 ---- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -@@ -93,7 +93,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { - int k = ExperienceOrb.getExperienceValue(j); - - j -= k; -- world.addFreshEntity(new ExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k)); -+ world.addFreshEntity(new ExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k, org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player)); // Paper - } - - world.levelEvent(1042, blockposition, 0); -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 2ae786b8fc6da19ca2a40252b0606f9e06d31ded..9d2e4adddae481735053c64eec0ee7259c61f1a4 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -267,13 +267,13 @@ public class Block extends BlockBehaviour implements ItemLike { - } - } - -- public void popExperience(ServerLevel world, BlockPos pos, int size) { -- if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { -- while (size > 0) { -- int j = ExperienceOrb.getExperienceValue(size); -+ public void dropExperience(ServerLevel worldserver, BlockPos blockposition, int i, net.minecraft.server.level.ServerPlayer player) { // Paper -+ if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { -+ while (i > 0) { -+ int j = ExperienceOrb.getExperienceValue(i); - -- size -= j; -- world.addFreshEntity(new ExperienceOrb(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, j)); -+ i -= j; -+ worldserver.addFreshEntity(new ExperienceOrb(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player)); // Paper - } - } - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 7a2554c5cd18e0c5e482ba8ba68a098d533b6a4f..8c55c1d88ef2e20e82bcdae0b9b3d381e562051f 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -601,7 +601,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - int k = ExperienceOrb.getExperienceValue(j); - - j -= k; -- world.addFreshEntity(new ExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k)); -+ world.addFreshEntity(new ExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman)); // Paper - } - - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 6782888f7df4eea4e6378ee850424e14c5136afd..88658d4deacc29128c537e2e02fdc8f684090a2c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1817,7 +1817,7 @@ public class CraftWorld implements World { - } else if (TNTPrimed.class.isAssignableFrom(clazz)) { - entity = new PrimedTnt(world, x, y, z, null); - } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { -- entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0); -+ entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper - } else if (LightningStrike.class.isAssignableFrom(clazz)) { - entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(world); - } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -index 3b450d97302bab30cdb975c8332b81318470503e..d5b8fd76ec3bd7d2621231480eb3e694a90aa037 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import SpawnReason; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.ExperienceOrb; -@@ -19,6 +20,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { - getHandle().value = value; - } - -+ // Paper start -+ public java.util.UUID getTriggerEntityId() { -+ return getHandle().triggerEntityId; -+ } -+ public java.util.UUID getSourceEntityId() { -+ return getHandle().sourceEntityId; -+ } -+ public SpawnReason getSpawnReason() { -+ return getHandle().spawnReason; -+ } -+ // Paper end -+ - @Override - public net.minecraft.world.entity.ExperienceOrb getHandle() { - return (net.minecraft.world.entity.ExperienceOrb) entity; diff --git a/Remapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch b/Remapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch deleted file mode 100644 index 7b28bfe328..0000000000 --- a/Remapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 22 Jan 2017 18:07:56 -0500 -Subject: [PATCH] Cap Entity Collisions - -Limit a single entity to colliding a max of configurable times per tick. -This will alleviate issues where living entities are hoarded in 1x1 pens - -This is not tied to the maxEntityCramming rule. Cramming will still apply -just as it does in Vanilla, but entity pushing logic will be capped. - -You can set this to 0 to disable collisions. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2dc58b9f769ea43b737804456aafab47ecc143b8..c611b5a63498f5ad1f50a75ccd5d7299e27df7e3 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -324,4 +324,10 @@ public class PaperWorldConfig { - log("Treasure Maps will return already discovered locations"); - } - } -+ -+ public int maxCollisionsPerEntity; -+ private void maxEntityCollision() { -+ maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); -+ log( "Max Entity Collisions: " + maxCollisionsPerEntity ); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a9ed1c3ce6361a86dd58501f5b0ce5d6bbfb8adf..a017fa55002d6674124befa3f6e81eb70c9ce8f7 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -267,6 +267,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; -+ protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index c6aa5328907f85cd210b1c20ff407e60d9b03349..3908f54e2216c635d47f8256bac455e7207a5bc6 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2900,8 +2900,11 @@ public abstract class LivingEntity extends Entity { - } - } - -- for (j = 0; j < list.size(); ++j) { -+ numCollisions = Math.max(0, numCollisions - level.paperConfig.maxCollisionsPerEntity); // Paper -+ for (j = 0; j < list.size() && numCollisions < level.paperConfig.maxCollisionsPerEntity; ++j) { // Paper - Entity entity = (Entity) list.get(j); -+ entity.numCollisions++; // Paper -+ numCollisions++; // Paper - - this.doPush(entity); - } diff --git a/Remapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch b/Remapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch deleted file mode 100644 index db58842a96..0000000000 --- a/Remapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 5 Feb 2017 00:04:04 -0500 -Subject: [PATCH] Remove CraftScheduler Async Task Debugger - -I have not once ever seen this system help debug a crash. -One report of a suspected memory leak with the system. - -This adds additional overhead to asynchronous task dispatching - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 9b6d9373abb59a30c2835ca891282d07559281f5..0e0f361c3af363539d5d1d865603114bdb84fd67 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -430,7 +430,7 @@ public class CraftScheduler implements BukkitScheduler { - } - parsePending(); - } else { -- debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); -+ //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper - executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper - // We don't need to parse pending - // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) -@@ -447,7 +447,7 @@ public class CraftScheduler implements BukkitScheduler { - pending.addAll(temp); - temp.clear(); - MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); -- debugHead = debugHead.getNextHead(currentTick); -+ //debugHead = debugHead.getNextHead(currentTick); // Paper - } - - private void addTask(final CraftTask task) { -@@ -507,10 +507,15 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public String toString() { -+ // Paper start -+ return ""; -+ /* - int debugTick = currentTick; - StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - RECENT_TICKS).append('-').append(debugTick).append('{'); - debugHead.debugTo(string); - return string.append('}').toString(); -+ */ -+ // Paper end - } - - @Deprecated diff --git a/Remapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/Remapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch deleted file mode 100644 index 740c39b430..0000000000 --- a/Remapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 7 Feb 2017 16:55:35 -0600 -Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 175bf535066afc42de8a3f0d11c46af66f3e3e52..3b6f35b695117bd2b0c71b994efc55fa1084eddc 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -119,7 +119,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private final PlayerMap playerMap; - public final Int2ObjectMap entityMap; - private final Long2ByteMap chunkTypeCache; -- private final Queue unloadQueue; -+ private final Queue unloadQueue; private final Queue getUnloadQueueTasks() { return this.unloadQueue; } // Paper - OBFHELPER - private int viewDistance; - - // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() -@@ -177,7 +177,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.playerMap = new PlayerMap(); - this.entityMap = new Int2ObjectOpenHashMap(); - this.chunkTypeCache = new Long2ByteOpenHashMap(); -- this.unloadQueue = Queues.newConcurrentLinkedQueue(); -+ this.unloadQueue = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size() - this.structureManager = definedstructuremanager; - this.storageFolder = convertable_conversionsession.getDimensionPath(worldserver.dimension()); - this.level = worldserver; -@@ -435,7 +435,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Spigot start - org.spigotmc.SlackActivityAccountant activityAccountant = this.level.getServer().slackActivityAccountant; - activityAccountant.startActivity(0.5); -- int targetSize = (int) (this.toDrop.size() * UNLOAD_QUEUE_RESIZE_FACTOR); -+ int targetSize = Math.min(this.toDrop.size() - 100, (int) (this.toDrop.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive - // Spigot end - while (longiterator.hasNext()) { // Spigot - long j = longiterator.nextLong(); -@@ -457,7 +457,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - Runnable runnable; - -- while ((shouldKeepTicking.getAsBoolean() || this.unloadQueue.size() > 2000) && (runnable = (Runnable) this.unloadQueue.poll()) != null) { -+ int queueTarget = Math.min(this.getUnloadQueueTasks().size() - 100, (int) (this.getUnloadQueueTasks().size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well -+ while ((shouldKeepTicking.getAsBoolean() || this.getUnloadQueueTasks().size() > queueTarget) && (runnable = (Runnable)this.getUnloadQueueTasks().poll()) != null) { // Paper - Target this queue as well - runnable.run(); - } - diff --git a/Remapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch b/Remapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch deleted file mode 100644 index d8f5fab54d..0000000000 --- a/Remapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 18 Feb 2017 19:29:58 -0600 -Subject: [PATCH] Do not let armorstands drown - - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 3908f54e2216c635d47f8256bac455e7207a5bc6..c1786fcabeaee5732e9197db04268c5c4e164339 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -335,6 +335,7 @@ public abstract class LivingEntity extends Entity { - super.checkFallDamage(heightDifference, onGround, landedState, landedPosition); - } - -+ public boolean canBreatheUnderwater() { return this.canBreatheUnderwater(); } // Paper - OBFHELPER - public boolean canBreatheUnderwater() { - return this.getMobType() == MobType.UNDEAD; - } -@@ -378,7 +379,7 @@ public abstract class LivingEntity extends Entity { - - if (this.isAlive()) { - if (this.isEyeInFluid((Tag) FluidTags.WATER) && !this.level.getBlockState(new BlockPos(this.getX(), this.getEyeY(), this.getZ())).is(Blocks.BUBBLE_COLUMN)) { -- if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { -+ if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { // Paper - use OBFHELPER so it can be overridden - this.setAirSupply(this.decreaseAirSupply(this.getAirSupply())); - if (this.getAirSupply() == -20) { - this.setAirSupply(0); -diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 8b6ec9ddf0d47bf4369b247e764f75893ab15781..59239e202e8e99870ce3be515d2f040ad9786892 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -868,5 +868,10 @@ public class ArmorStand extends LivingEntity { - super.move(type, movement); - } - } -+ -+ @Override -+ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization -+ return true; -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch b/Remapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch deleted file mode 100644 index 761e1f8b83..0000000000 --- a/Remapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch +++ /dev/null @@ -1,307 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 12 May 2017 23:34:11 -0500 -Subject: [PATCH] Properly handle async calls to restart the server - -The watchdog thread calls the server restart function asynchronously. Prior to -this change, it attempted to do several non-safe operations from the watchdog -thread, rather than the main. Specifically, because of a separate upstream change, -it causes player entities to be ticked asynchronously, among other things. - -This is dangerous. - -This patch moves the old handling into a synchronous variant, for calls from the -restart command, and adds separate handling for async calls, such as those from -the watchdog thread. - -When calling from the watchdog thread, we cannot assume the main thread is in a -tickable state; it may be completely deadlocked. In order to handle this, we mark -the server as stopping, in order to account for situations where the server should -complete a tick reasonbly soon, i.e. 99% of cases. - -Should the server not enter a state where it is stopping within 10 seconds, We -will assume that the server has in fact deadlocked and will proceed to force -kill the server. - -This modification does not force restart the server should we actually enter a -deadlocked state where the server is stopping, whereas this will in most cases -exit within a reasonable amount of time, to put a fixed limit on a process that -will have plugins and worlds saving to the disk has a high potential to result -in corruption/dataloss. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 211251fe7cd08074c040df2f4642f37d5f90d856..f41d79c6630fd8daae28476ffc854f7e65d841e6 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -199,6 +199,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop, ServerLevel> levels; - private PlayerList playerList; - private volatile boolean running; -+ private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart - private boolean stopped; - private int tickCount; - protected final Proxy proxy; -@@ -858,7 +859,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && new File( split[0] ).isFile() ) -+ // Paper - extract method and cleanup -+ boolean isRestarting = addShutdownHook( restartScript ); -+ if ( isRestarting ) - { -- System.out.println( "Attempting to restart with " + restartScript ); -+ System.out.println( "Attempting to restart with " + SpigotConfig.restartScript ); -+ } else -+ { -+ System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); -+ } -+ // Stop the watchdog -+ WatchdogThread.doStop(); - -- // Disable Watchdog -- WatchdogThread.doStop(); -+ shutdownServer( isRestarting ); -+ // Paper end -+ } catch ( Exception ex ) -+ { -+ ex.printStackTrace(); -+ } -+ } - -- // Kick all players -- for ( ServerPlayer p : (List) MinecraftServer.getServer().getPlayerList().players ) -- { -- p.connection.disconnect(SpigotConfig.restartMessage); -- } -- // Give the socket a chance to send the packets -- try -- { -- Thread.sleep( 100 ); -- } catch ( InterruptedException ex ) -- { -- } -- // Close the socket so we can rebind with the new process -- MinecraftServer.getServer().getConnection().stop(); -+ // Paper start - sync copied from above with minor changes, async added -+ private static void shutdownServer(boolean isRestarting) -+ { -+ if ( MinecraftServer.getServer().isSameThread() ) -+ { -+ // Kick all players -+ for ( ServerPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) -+ { -+ p.connection.disconnect(SpigotConfig.restartMessage); -+ } -+ // Give the socket a chance to send the packets -+ try -+ { -+ Thread.sleep( 100 ); -+ } catch ( InterruptedException ex ) -+ { -+ } - -- // Give time for it to kick in -- try -- { -- Thread.sleep( 100 ); -- } catch ( InterruptedException ex ) -- { -- } -+ closeSocket(); - -- // Actually shutdown -- try -- { -- MinecraftServer.getServer().close(); -- } catch ( Throwable t ) -- { -- } -+ // Actually shutdown -+ try -+ { -+ MinecraftServer.getServer().close(); // calls stop() -+ } catch ( Throwable t ) -+ { -+ } -+ -+ // Actually stop the JVM -+ System.exit( 0 ); - -- // This will be done AFTER the server has completely halted -- Thread shutdownHook = new Thread() -+ } else -+ { -+ // Mark the server to shutdown at the end of the tick -+ MinecraftServer.getServer().safeShutdown( false, isRestarting ); -+ -+ // wait 10 seconds to see if we're actually going to try shutdown -+ try -+ { -+ Thread.sleep( 10000 ); -+ } -+ catch (InterruptedException ignored) -+ { -+ } -+ -+ // Check if we've actually hit a state where the server is going to safely shutdown -+ // if we have, let the server stop as usual -+ if (MinecraftServer.getServer().isStopped()) return; -+ -+ // If the server hasn't stopped by now, assume worse case and kill -+ closeSocket(); -+ System.exit( 0 ); -+ } -+ } -+ // Paper end -+ -+ // Paper - Split from moved code -+ private static void closeSocket() -+ { -+ // Close the socket so we can rebind with the new process -+ MinecraftServer.getServer().getConnection().stop(); -+ -+ // Give time for it to kick in -+ try -+ { -+ Thread.sleep( 100 ); -+ } catch ( InterruptedException ex ) -+ { -+ } -+ } -+ // Paper end -+ -+ // Paper start - copied from above and modified to return if the hook registered -+ private static boolean addShutdownHook(String restartScript) -+ { -+ String[] split = restartScript.split( " " ); -+ if ( split.length > 0 && new File( split[0] ).isFile() ) -+ { -+ Thread shutdownHook = new Thread() -+ { -+ @Override -+ public void run() - { -- @Override -- public void run() -+ try - { -- try -+ String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); -+ if ( os.contains( "win" ) ) - { -- String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); -- if ( os.contains( "win" ) ) -- { -- Runtime.getRuntime().exec( "cmd /c start " + restartScript ); -- } else -- { -- Runtime.getRuntime().exec( "sh " + restartScript ); -- } -- } catch ( Exception e ) -+ Runtime.getRuntime().exec( "cmd /c start " + restartScript ); -+ } else - { -- e.printStackTrace(); -+ Runtime.getRuntime().exec( "sh " + restartScript ); - } -+ } catch ( Exception e ) -+ { -+ e.printStackTrace(); - } -- }; -- -- shutdownHook.setDaemon( true ); -- Runtime.getRuntime().addShutdownHook( shutdownHook ); -- } else -- { -- System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); -- -- // Actually shutdown -- try -- { -- MinecraftServer.getServer().close(); -- } catch ( Throwable t ) -- { - } -- } -- System.exit( 0 ); -- } catch ( Exception ex ) -+ }; -+ -+ shutdownHook.setDaemon( true ); -+ Runtime.getRuntime().addShutdownHook( shutdownHook ); -+ return true; -+ } else - { -- ex.printStackTrace(); -+ return false; - } - } -+ // Paper end -+ - } diff --git a/Remapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch b/Remapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch deleted file mode 100644 index ebfc39ca77..0000000000 --- a/Remapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 13 May 2017 20:11:21 -0500 -Subject: [PATCH] Add system property to disable book size limits - -If anyone comes in with a watchdog crash related to books after this patch -you will not only be publicly shamed but also made an example of. - -Disables the security limits on books entirely, allowing plugins AND players -to make books with as much data as they want. Do not use this without -limiting incoming data from packets in some other way. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index a592d4a286a775a61192dde2a4d21a0681090415..80397e223990f11c9aa413f3f4ebd7c1b8ce1cff 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -43,6 +43,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - static final int MAX_PAGES = 100; - static final int MAX_PAGE_LENGTH = 320; // 256 limit + 64 characters to allow for psuedo colour codes - static final int MAX_TITLE_LENGTH = 32; -+ private static final boolean OVERRIDE_CHECKS = Boolean.getBoolean("disable.book-limits"); // Paper - Add override - - protected String title; - protected String author; -@@ -245,7 +246,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - if (title == null) { - this.title = null; - return true; -- } else if (title.length() > MAX_TITLE_LENGTH) { -+ } else if (title.length() > MAX_TITLE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override - return false; - } - -@@ -442,7 +443,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - String validatePage(String page) { - if (page == null) { - page = ""; -- } else if (page.length() > MAX_PAGE_LENGTH) { -+ } else if (page.length() > MAX_PAGE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override - page = page.substring(0, MAX_PAGE_LENGTH); - } - return page; -@@ -452,7 +453,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - // asserted: page != null - if (this.pages == null) { - this.pages = new ArrayList(); -- } else if (this.pages.size() >= MAX_PAGES) { -+ } else if (this.pages.size() >= MAX_PAGES && !OVERRIDE_CHECKS) {// Paper - Add override - return; - } - this.pages.add(page); diff --git a/Remapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/Remapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch deleted file mode 100644 index 0e3605cc72..0000000000 --- a/Remapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 16 May 2017 21:29:08 -0500 -Subject: [PATCH] Add option to make parrots stay on shoulders despite movement - -Makes parrots not fall off whenever the player changes height, or touches water, or gets hit by a passing leaf. -Instead, switches the behavior so that players have to sneak to make the birds leave. - -I suspect Mojang may switch to this behavior before full release. - -To be converted into a Paper-API event at some point in the future? - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c611b5a63498f5ad1f50a75ccd5d7299e27df7e3..9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -330,4 +330,10 @@ public class PaperWorldConfig { - maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); - log( "Max Entity Collisions: " + maxCollisionsPerEntity ); - } -+ -+ public boolean parrotsHangOnBetter; -+ private void parrotsHangOnBetter() { -+ parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); -+ log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ecc393ad94332ec2a59d29f30bd60bade4e1f18e..6a922e3522ac99a8e317a5f5f51fbb597baaf63e 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2051,6 +2051,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - switch (packet.getAction()) { - case PRESS_SHIFT_KEY: - this.player.setShiftKeyDown(true); -+ -+ // Paper start - Hang on! -+ if (this.player.level.paperConfig.parrotsHangOnBetter) { -+ this.player.removeEntitiesOnShoulder(); -+ } -+ // Paper end -+ - break; - 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 c11d5aa115d10e3c12863cf9d42c60194d63b690..ae10c531ae69eaf6b78a342dcedb89c39fd8dbcc 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -529,7 +529,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.removeEntitiesOnShoulder(); -+ if (!this.level.paperConfig.parrotsHangOnBetter) this.removeEntitiesOnShoulder(); // Paper - Hang on! - } - - } diff --git a/Remapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch b/Remapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch deleted file mode 100644 index 2f0b8509ca..0000000000 --- a/Remapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Fri, 9 Jun 2017 07:24:34 -0700 -Subject: [PATCH] Add configuration option to prevent player names from being - suggested - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 4e2f243faa209925dcb7c3ef89df3ed875c5ff78..48319aaf1c525c6fb7bdee5c2f570a0d056d4eae 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -268,4 +268,9 @@ public class PaperConfig { - flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); - flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); - } -+ -+ public static boolean suggestPlayersWhenNullTabCompletions = true; -+ private static void suggestPlayersWhenNull() { -+ suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 9365fd2bcf74755c90c4ae9b550969e97a22c639..d198dad80e0fb41a5bde66944d0e41509a9c1c43 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2300,5 +2300,10 @@ public final class CraftServer implements Server { - commandMap.registerServerAliases(); - return true; - } -+ -+ @Override -+ public boolean suggestPlayerNamesWhenNullTabCompletions() { -+ return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch b/Remapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch deleted file mode 100644 index d43b61bcff..0000000000 --- a/Remapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch +++ /dev/null @@ -1,558 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Fri, 9 Jun 2017 19:03:43 +0200 -Subject: [PATCH] Use TerminalConsoleAppender for console improvements - -Rewrite console improvements (console colors, tab completion, -persistent input line, ...) using JLine 3.x and TerminalConsoleAppender. - -New features: - - Support console colors for Vanilla commands - - Add console colors for warnings and errors - - Server can now be turned off safely using CTRL + C. JLine catches - the signal and the implementation shuts down the server cleanly. - - Support console colors and persistent input line when running in - IntelliJ IDEA - -Other changes: - - Server starts 1-2 seconds faster thanks to optimizations in Log4j - configuration - -diff --git a/pom.xml b/pom.xml -index a5d87d22cb1588d15e08da3b37e51c5e261c7799..3841fe3630c090f8a468333d43caeb2b5841329d 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -57,10 +57,26 @@ - compile - - -- jline -- jline -- 2.12.1 -- compile -+ net.minecrell -+ terminalconsoleappender -+ 1.2.0 -+ -+ -+ org.jline -+ jline-terminal-jansi -+ 3.12.1 -+ runtime -+ -+ -+ -+ org.apache.logging.log4j -+ log4j-core -+ runtime - - - org.apache.logging.log4j -@@ -334,10 +350,18 @@ - - META-INF/services/java.sql.Driver - -+ - - - - -+ -+ -+ com.github.edwgiz -+ maven-shade-plugin.log4j2-cachefile-transformer -+ 2.13.1 -+ -+ - - - org.apache.maven.plugins -diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a4070b59e261f0f1ac4beec47b11492f4724bf27 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.console; -+ -+import net.minecraft.server.dedicated.DedicatedServer; -+import net.minecrell.terminalconsole.SimpleTerminalConsole; -+import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; -+import org.jline.reader.LineReader; -+import org.jline.reader.LineReaderBuilder; -+ -+public final class PaperConsole extends SimpleTerminalConsole { -+ -+ private final DedicatedServer server; -+ -+ public PaperConsole(DedicatedServer server) { -+ this.server = server; -+ } -+ -+ @Override -+ protected LineReader buildReader(LineReaderBuilder builder) { -+ return super.buildReader(builder -+ .appName("Paper") -+ .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) -+ .completer(new ConsoleCommandCompleter(this.server)) -+ ); -+ } -+ -+ @Override -+ protected boolean isRunning() { -+ return !this.server.isStopped() && this.server.isRunning(); -+ } -+ -+ @Override -+ protected void runCommand(String command) { -+ this.server.handleConsoleInput(command, this.server.createCommandSourceStack()); -+ } -+ -+ @Override -+ protected void shutdown() { -+ this.server.halt(false); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java -new file mode 100644 -index 0000000000000000000000000000000000000000..685deaa0e5d1ddc13e3a7c0471b1cfcf1710c869 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.console; -+ -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; -+import org.bukkit.craftbukkit.command.CraftConsoleCommandSender; -+ -+public class TerminalConsoleCommandSender extends CraftConsoleCommandSender { -+ -+ private static final Logger LOGGER = LogManager.getRootLogger(); -+ -+ @Override -+ public void sendRawMessage(String message) { -+ // TerminalConsoleAppender supports color codes directly in log messages -+ LOGGER.info(message); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f41d79c6630fd8daae28476ffc854f7e65d841e6..4b3341877629c7065496fb0f0b4d509f5a48db6d 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -12,6 +12,7 @@ import com.mojang.datafixers.DataFixer; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -161,7 +162,7 @@ import org.apache.logging.log4j.Logger; - import com.mojang.serialization.DynamicOps; - import com.mojang.serialization.Lifecycle; - import com.google.common.collect.ImmutableSet; --import jline.console.ConsoleReader; -+// import jline.console.ConsoleReader; // Paper - import joptsimple.OptionSet; - import net.minecraft.resources.RegistryReadOps; - import net.minecraft.server.bossevents.CustomBossEvents; -@@ -253,7 +254,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; -@@ -322,7 +323,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { // Trim to filter lines which are just spaces -- DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack()); -+ DedicatedServer.this.issueCommand(s, DedicatedServer.this.getServerCommandListener()); - } - // CraftBukkit end - } -@@ -138,6 +141,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - DedicatedServer.LOGGER.error("Exception handling console input", ioexception); - } - -+ */ -+ // Paper end - } - }; - -@@ -149,6 +154,9 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - } - global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler()); - -+ // Paper start - Not needed with TerminalConsoleAppender -+ final org.apache.logging.log4j.Logger logger = LogManager.getRootLogger(); -+ /* - final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()); - for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) { - if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) { -@@ -157,6 +165,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - } - - new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start(); -+ */ -+ // Paper end - - System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream()); - System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream()); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index d750bef20312cc97e3446bbb2d2dc03f90d47f1c..7d6256f65d369fcbcfe1fffe7ac264788a38540b 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -146,8 +146,7 @@ public abstract class PlayerList { - - public PlayerList(MinecraftServer server, RegistryAccess.RegistryHolder registryManager, PlayerDataStorage saveHandler, int maxPlayers) { - this.cserver = server.server = new CraftServer((DedicatedServer) server, this); -- server.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance(); -- server.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(server.server)); -+ server.console = new com.destroystokyo.paper.console.TerminalConsoleCommandSender(); // Paper - // CraftBukkit end - - this.bans = new UserBanList(PlayerList.USERBANLIST_FILE); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index d198dad80e0fb41a5bde66944d0e41509a9c1c43..7b2ece40c09ba336a0c2a84321401619801c64c8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -46,7 +46,6 @@ import java.util.function.Consumer; - import java.util.logging.Level; - import java.util.logging.Logger; - import javax.imageio.ImageIO; --import jline.console.ConsoleReader; - import net.minecraft.advancements.Advancement; - import net.minecraft.commands.CommandSourceStack; - import net.minecraft.commands.Commands; -@@ -60,6 +59,7 @@ import net.minecraft.resources.RegistryReadOps; - import net.minecraft.resources.ResourceKey; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.ConsoleInput; -+//import jline.console.ConsoleReader; // Paper - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.bossevents.CustomBossEvent; - import net.minecraft.server.commands.ReloadCommand; -@@ -1204,9 +1204,13 @@ public final class CraftServer implements Server { - return logger; - } - -+ // Paper start - JLine update -+ /* - public ConsoleReader getReader() { - return console.reader; - } -+ */ -+ // Paper end - - @Override - public PluginCommand getPluginCommand(String name) { -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index b849b2afd009da433fe6cea5837b3ee9bb5c52b4..60d9980ccca6f1ac55b70f7684b917ddceac380a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -12,7 +12,7 @@ import java.util.logging.Level; - import java.util.logging.Logger; - import joptsimple.OptionParser; - import joptsimple.OptionSet; --import org.fusesource.jansi.AnsiConsole; -+import net.minecrell.terminalconsole.TerminalConsoleAppender; // Paper - - public class Main { - public static boolean useJline = true; -@@ -185,6 +185,8 @@ public class Main { - } - - try { -+ // Paper start - Handled by TerminalConsoleAppender -+ /* - // This trick bypasses Maven Shade's clever rewriting of our getProperty call when using String literals - String jline_UnsupportedTerminal = new String(new char[]{'j', 'l', 'i', 'n', 'e', '.', 'U', 'n', 's', 'u', 'p', 'p', 'o', 'r', 't', 'e', 'd', 'T', 'e', 'r', 'm', 'i', 'n', 'a', 'l'}); - String jline_terminal = new String(new char[]{'j', 'l', 'i', 'n', 'e', '.', 't', 'e', 'r', 'm', 'i', 'n', 'a', 'l'}); -@@ -202,9 +204,18 @@ public class Main { - // This ensures the terminal literal will always match the jline implementation - System.setProperty(jline.TerminalFactory.JLINE_TERMINAL, jline.UnsupportedTerminal.class.getName()); - } -+ */ -+ -+ if (options.has("nojline")) { -+ System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); -+ useJline = false; -+ } -+ // Paper end - - if (options.has("noconsole")) { - useConsole = false; -+ useJline = false; // Paper -+ System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper - } - - if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { -@@ -232,7 +243,7 @@ public class Main { - System.out.println("Unable to read system info"); - } - // Paper end -- -+ System.setProperty( "library.jansi.version", "Paper" ); // Paper - set meaningless jansi version to prevent git builds from crashing on Windows - System.out.println("Loading libraries, please wait..."); - net.minecraft.server.Main.main(options); - } catch (Throwable t) { -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java b/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java -index 4580642e0ee79e6d9c9bef0344e643bbc551205c..829c62b6d55cb5706be3ce6bdc758d6b204844ee 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ColouredConsoleSender.java -@@ -5,15 +5,13 @@ import java.util.EnumMap; - import java.util.Map; - import java.util.regex.Matcher; - import java.util.regex.Pattern; --import jline.Terminal; -+//import jline.Terminal; - import org.bukkit.Bukkit; - import org.bukkit.ChatColor; - import org.bukkit.command.ConsoleCommandSender; - import org.bukkit.craftbukkit.CraftServer; --import org.fusesource.jansi.Ansi; --import org.fusesource.jansi.Ansi.Attribute; - --public class ColouredConsoleSender extends CraftConsoleCommandSender { -+public class ColouredConsoleSender /*extends CraftConsoleCommandSender */{/* // Paper - disable - private final Terminal terminal; - private final Map replacements = new EnumMap(ChatColor.class); - private final ChatColor[] colors = ChatColor.values(); -@@ -93,5 +91,5 @@ public class ColouredConsoleSender extends CraftConsoleCommandSender { - } else { - return new ColouredConsoleSender(); - } -- } -+ }*/ // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index befcc19f9b56df9096b98a23b0020f1db793ea5b..a957695457cf3252848ce6ef37069692841b8e28 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -4,20 +4,31 @@ import java.util.Collections; - import java.util.List; - import java.util.concurrent.ExecutionException; - import java.util.logging.Level; --import jline.console.completer.Completer; -+import net.minecraft.server.dedicated.DedicatedServer; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.util.Waitable; -+ -+// Paper start - JLine update -+import org.jline.reader.Candidate; -+import org.jline.reader.Completer; -+import org.jline.reader.LineReader; -+import org.jline.reader.ParsedLine; -+// Paper end - import org.bukkit.event.server.TabCompleteEvent; - - public class ConsoleCommandCompleter implements Completer { -- private final CraftServer server; -+ private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer - -- public ConsoleCommandCompleter(CraftServer server) { -+ public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer - this.server = server; - } - -+ // Paper start - Change method signature for JLine update - @Override -- public int complete(final String buffer, final int cursor, final List candidates) { -+ public void complete(LineReader reader, ParsedLine line, List candidates) { -+ final CraftServer server = this.server.server; -+ final String buffer = line.line(); -+ // Paper end - Waitable> waitable = new Waitable>() { - @Override - protected List evaluate() { -@@ -29,25 +40,37 @@ public class ConsoleCommandCompleter implements Completer { - return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); - } - }; -- this.server.getServer().processQueue.add(waitable); -+ server.getServer().processQueue.add(waitable); // Paper - Remove "this." - try { - List offers = waitable.get(); - if (offers == null) { -- return cursor; -+ return; // Paper - Method returns void -+ } -+ -+ // Paper start - JLine update -+ for (String completion : offers) { -+ if (completion.isEmpty()) { -+ continue; -+ } -+ -+ candidates.add(new Candidate(completion)); - } -- candidates.addAll(offers); -+ // Paper end - -+ // Paper start - JLine handles cursor now -+ /* - final int lastSpace = buffer.lastIndexOf(' '); - if (lastSpace == -1) { - return cursor - buffer.length(); - } else { - return cursor - (buffer.length() - lastSpace - 1); - } -+ */ -+ // Paper end - } catch (ExecutionException e) { -- this.server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); -+ server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); // Paper - Remove "this." - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } -- return cursor; - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index 70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe..449e99d1b673870ed6892f6ab2c715a2db35c35d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -17,7 +17,7 @@ public class ServerShutdownThread extends Thread { - server.close(); - } finally { - try { -- server.reader.getTerminal().restore(); -+ net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender - } catch (Exception e) { - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -index 99564fed7ce77e29dbdc591bcfe656af741acf8a..9a2da548b8860b496e396564b2c8f6383f020193 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -@@ -5,12 +5,12 @@ import java.io.IOException; - import java.io.OutputStream; - import java.util.logging.Level; - import java.util.logging.Logger; --import jline.console.ConsoleReader; -+//import jline.console.ConsoleReader; - import org.bukkit.craftbukkit.Main; --import org.fusesource.jansi.Ansi; --import org.fusesource.jansi.Ansi.Erase; -+//import org.fusesource.jansi.Ansi; -+//import org.fusesource.jansi.Ansi.Erase; - --public class TerminalConsoleWriterThread extends Thread { -+public class TerminalConsoleWriterThread /*extends Thread*/ {/* // Paper - disable - private final ConsoleReader reader; - private final OutputStream output; - -@@ -54,5 +54,5 @@ public class TerminalConsoleWriterThread extends Thread { - Logger.getLogger(TerminalConsoleWriterThread.class.getName()).log(Level.SEVERE, null, ex); - } - } -- } -+ }*/ - } -diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties -new file mode 100644 -index 0000000000000000000000000000000000000000..0694b21465fb9e4164e71862ff24b62241b191f2 ---- /dev/null -+++ b/src/main/resources/log4j2.component.properties -@@ -0,0 +1 @@ -+log4j.skipJansi=true -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 722ca84968cbbbdeffd09939abff0cccd0a84010..620b9490e5f159080e50289d127404a1b56adbef 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -1,17 +1,14 @@ - - - -- -- -- - - - -- -- -- -+ -+ -+ - -- -+ - - - -@@ -24,10 +21,9 @@ - - - -- - -- - -+ - - - diff --git a/Remapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch b/Remapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch deleted file mode 100644 index a511c4d919..0000000000 --- a/Remapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 11 Jun 2017 21:01:18 +0100 -Subject: [PATCH] provide a configurable option to disable creeper lingering - effect spawns - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1..90ca51dfdbb3045dd528450225cba96f5834166e 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -336,4 +336,10 @@ public class PaperWorldConfig { - parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); - log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); - } -+ -+ public boolean disableCreeperLingeringEffect; -+ private void setDisableCreeperLingeringEffect() { -+ disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); -+ log("Creeper lingering effect: " + disableCreeperLingeringEffect); -+ } - } -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 bb3226310158139c9fcfe204554caffcbb62798c..8f8d0a23d011936150854a0606be3d63b18c57af 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -@@ -261,7 +261,7 @@ public class Creeper extends Monster { - private void spawnLingeringCloud() { - Collection collection = this.getActiveEffects(); - -- if (!collection.isEmpty()) { -+ if (!collection.isEmpty() && !level.paperConfig.disableCreeperLingeringEffect) { // Paper - AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level, this.getX(), this.getY(), this.getZ()); - - entityareaeffectcloud.setOwner(this); // CraftBukkit diff --git a/Remapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch b/Remapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch deleted file mode 100644 index 569a928f31..0000000000 --- a/Remapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 5 May 2017 03:57:17 -0500 -Subject: [PATCH] Item#canEntityPickup - - -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 46f0ebfc99352ec8b64bdff2c6bb8d17ecfeb619..eb35c69bb777ba8d83b2304ff9f862512643e745 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -605,6 +605,11 @@ public abstract class Mob extends LivingEntity { - ItemEntity entityitem = (ItemEntity) iterator.next(); - - if (!entityitem.removed && !entityitem.getItem().isEmpty() && !entityitem.hasPickUpDelay() && this.wantsToPickUp(entityitem.getItem())) { -+ // Paper Start -+ if (!entityitem.canMobPickup) { -+ continue; -+ } -+ // Paper End - this.pickUpItem(entityitem); - } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 78dc5ac986afaba04176f64afbb035442cd41d38..7aba507e171f34e213b3c034e345e7397a44d2b5 100644 ---- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -46,6 +46,7 @@ public class ItemEntity extends Entity { - private UUID owner; - public final float bobOffs; - private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit -+ public boolean canMobPickup = true; // Paper - - public ItemEntity(EntityType type, Level world) { - super(type, world); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -index 6e394ce6ea4177e1758e27074a4fd54d716edc3d..9a410f557988d737c3b930a79ef2ccb2b5c8b406 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -@@ -49,6 +49,16 @@ public class CraftItem extends CraftEntity implements Item { - item.age = value; - } - -+ // Paper Start -+ public boolean canMobPickup() { -+ return item.canMobPickup; -+ } -+ -+ public void setCanMobPickup(boolean canMobPickup) { -+ item.canMobPickup = canMobPickup; -+ } -+ // Paper End -+ - @Override - public void setOwner(UUID uuid) { - item.setOwner(uuid); diff --git a/Remapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch b/Remapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch deleted file mode 100644 index a5081735fc..0000000000 --- a/Remapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 May 2017 06:26:09 -0500 -Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer - - -diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 7aba507e171f34e213b3c034e345e7397a44d2b5..72d1e83ac5e4ae3c943ca5ec1058f0d7ad2903cd 100644 ---- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -362,6 +362,7 @@ public class ItemEntity extends Entity { - // CraftBukkit start - fire PlayerPickupItemEvent - int canHold = player.inventory.canHold(itemstack); - int remaining = i - canHold; -+ boolean flyAtPlayer = false; // Paper - - if (this.pickupDelay <= 0 && canHold > 0) { - itemstack.setCount(canHold); -@@ -369,8 +370,14 @@ public class ItemEntity extends Entity { - PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); - playerEvent.setCancelled(!player.canPickUpLoot); - this.level.getCraftServer().getPluginManager().callEvent(playerEvent); -+ flyAtPlayer = playerEvent.getFlyAtPlayer(); // Paper - if (playerEvent.isCancelled()) { - itemstack.setCount(i); // SPIGOT-5294 - restore count -+ // Paper Start -+ if (flyAtPlayer) { -+ player.take(this, i); -+ } -+ // Paper End - return; - } - -@@ -400,7 +407,11 @@ public class ItemEntity extends Entity { - // CraftBukkit end - - if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(player.getUUID())) && player.inventory.add(itemstack)) { -- player.take(this, i); -+ // Paper Start -+ if (flyAtPlayer) { -+ player.take(this, i); -+ } -+ // Paper End - if (itemstack.isEmpty()) { - this.remove(); - itemstack.setCount(i); diff --git a/Remapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch b/Remapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch deleted file mode 100644 index 1c5b10dcee..0000000000 --- a/Remapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 11 Jun 2017 16:30:30 -0500 -Subject: [PATCH] PlayerAttemptPickupItemEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 72d1e83ac5e4ae3c943ca5ec1058f0d7ad2903cd..de69f7c3c0ee1e74682b0db91bdaae09175690e9 100644 ---- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -35,6 +35,7 @@ import net.minecraft.stats.Stats; - import org.bukkit.event.entity.EntityPickupItemEvent; - import org.bukkit.event.player.PlayerPickupItemEvent; - // CraftBukkit end -+import org.bukkit.event.player.PlayerAttemptPickupItemEvent; // Paper - - public class ItemEntity extends Entity { - -@@ -364,6 +365,22 @@ public class ItemEntity extends Entity { - int remaining = i - canHold; - boolean flyAtPlayer = false; // Paper - -+ // Paper start -+ if (this.pickupDelay <= 0) { -+ PlayerAttemptPickupItemEvent attemptEvent = new PlayerAttemptPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); -+ this.level.getCraftServer().getPluginManager().callEvent(attemptEvent); -+ -+ flyAtPlayer = attemptEvent.getFlyAtPlayer(); -+ if (attemptEvent.isCancelled()) { -+ if (flyAtPlayer) { -+ player.take(this, i); -+ } -+ -+ return; -+ } -+ } -+ // Paper end -+ - if (this.pickupDelay <= 0 && canHold > 0) { - itemstack.setCount(canHold); - // Call legacy event diff --git a/Remapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch b/Remapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch deleted file mode 100644 index 9979b7ace2..0000000000 --- a/Remapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sweepyoface -Date: Sat, 17 Jun 2017 18:48:21 -0400 -Subject: [PATCH] Add UnknownCommandEvent - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 7b2ece40c09ba336a0c2a84321401619801c64c8..b9e39a4c0aea3de96d1774ae0d0d23ff82162c7e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -790,7 +790,13 @@ public final class CraftServer implements Server { - - // Spigot start - if (!org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty()) { -- sender.sendMessage(org.spigotmc.SpigotConfig.unknownCommandMessage); -+ // Paper start -+ org.bukkit.event.command.UnknownCommandEvent event = new org.bukkit.event.command.UnknownCommandEvent(sender, commandLine, org.spigotmc.SpigotConfig.unknownCommandMessage); -+ Bukkit.getServer().getPluginManager().callEvent(event); -+ if (event.message() != null) { -+ sender.sendMessage(event.message()); -+ } -+ // Paper end - } - // Spigot end - diff --git a/Remapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch b/Remapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch deleted file mode 100644 index ce8cf66ee0..0000000000 --- a/Remapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch +++ /dev/null @@ -1,577 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 15 Jan 2018 22:11:48 -0500 -Subject: [PATCH] Basic PlayerProfile API - -Establishes base extension of profile systems for future edits too - -diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8f559897e408eee8617af0bb77fa4635e07ccdce ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java -@@ -0,0 +1,303 @@ -+package com.destroystokyo.paper.profile; -+ -+import PlayerProfile; -+import ProfileProperty; -+import com.destroystokyo.paper.PaperConfig; -+import com.google.common.base.Charsets; -+import com.mojang.authlib.GameProfile; -+import com.mojang.authlib.properties.Property; -+import com.mojang.authlib.properties.PropertyMap; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.players.GameProfileCache; -+import org.apache.commons.lang3.Validate; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+import org.spigotmc.SpigotConfig; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.util.AbstractSet; -+import java.util.Collection; -+import java.util.Iterator; -+import java.util.Objects; -+import java.util.Set; -+import java.util.UUID; -+ -+public class CraftPlayerProfile implements PlayerProfile { -+ -+ private GameProfile profile; -+ private final PropertySet properties = new PropertySet(); -+ -+ public CraftPlayerProfile(CraftPlayer player) { -+ this.profile = player.getHandle().getGameProfile(); -+ } -+ -+ public CraftPlayerProfile(UUID id, String name) { -+ this.profile = new GameProfile(id, name); -+ } -+ -+ public CraftPlayerProfile(GameProfile profile) { -+ Validate.notNull(profile, "GameProfile cannot be null!"); -+ this.profile = profile; -+ } -+ -+ @Override -+ public boolean hasProperty(String property) { -+ return profile.getProperties().containsKey(property); -+ } -+ -+ @Override -+ public void setProperty(ProfileProperty property) { -+ String name = property.getName(); -+ PropertyMap properties = profile.getProperties(); -+ properties.removeAll(name); -+ properties.put(name, new Property(name, property.getValue(), property.getSignature())); -+ } -+ -+ public GameProfile getGameProfile() { -+ return profile; -+ } -+ -+ @Nullable -+ @Override -+ public UUID getId() { -+ return profile.getId(); -+ } -+ -+ @Override -+ public UUID setId(@Nullable UUID uuid) { -+ GameProfile prev = this.profile; -+ this.profile = new GameProfile(uuid, prev.getName()); -+ copyProfileProperties(prev, this.profile); -+ return prev.getId(); -+ } -+ -+ @Nullable -+ @Override -+ public String getName() { -+ return profile.getName(); -+ } -+ -+ @Override -+ public String setName(@Nullable String name) { -+ GameProfile prev = this.profile; -+ this.profile = new GameProfile(prev.getId(), name); -+ copyProfileProperties(prev, this.profile); -+ return prev.getName(); -+ } -+ -+ @Nonnull -+ @Override -+ public Set getProperties() { -+ return properties; -+ } -+ -+ @Override -+ public void setProperties(Collection properties) { -+ properties.forEach(this::setProperty); -+ } -+ -+ @Override -+ public void clearProperties() { -+ profile.getProperties().clear(); -+ } -+ -+ @Override -+ public boolean removeProperty(String property) { -+ return !profile.getProperties().removeAll(property).isEmpty(); -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ CraftPlayerProfile that = (CraftPlayerProfile) o; -+ return Objects.equals(profile, that.profile); -+ } -+ -+ @Override -+ public int hashCode() { -+ return profile.hashCode(); -+ } -+ -+ @Override -+ public String toString() { -+ return profile.toString(); -+ } -+ -+ @Override -+ public CraftPlayerProfile clone() { -+ CraftPlayerProfile clone = new CraftPlayerProfile(this.getId(), this.getName()); -+ clone.setProperties(getProperties()); -+ return clone; -+ } -+ -+ @Override -+ public boolean isComplete() { -+ return profile.isComplete(); -+ } -+ -+ @Override -+ public boolean completeFromCache() { -+ MinecraftServer server = MinecraftServer.getServer(); -+ return completeFromCache(false, PaperConfig.isProxyOnlineMode()); -+ } -+ -+ public boolean completeFromCache(boolean onlineMode) { -+ return completeFromCache(false, onlineMode); -+ } -+ -+ public boolean completeFromCache(boolean lookupUUID, boolean onlineMode) { -+ MinecraftServer server = MinecraftServer.getServer(); -+ String name = profile.getName(); -+ GameProfileCache userCache = server.getProfileCache(); -+ if (profile.getId() == null) { -+ final GameProfile profile; -+ if (onlineMode) { -+ profile = lookupUUID ? userCache.get(name) : userCache.getProfileIfCached(name); -+ } else { -+ // Make an OfflinePlayer using an offline mode UUID since the name has no profile -+ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); -+ } -+ if (profile != null) { -+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't -+ copyProfileProperties(this.profile, profile); -+ this.profile = profile; -+ } -+ } -+ -+ if ((profile.getName() == null || !hasTextures()) && profile.getId() != null) { -+ GameProfile profile = userCache.get(this.profile.getId()); -+ if (profile != null) { -+ if (this.profile.getName() == null) { -+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't -+ copyProfileProperties(this.profile, profile); -+ this.profile = profile; -+ } else { -+ copyProfileProperties(profile, this.profile); -+ } -+ } -+ } -+ return this.profile.isComplete(); -+ } -+ -+ public boolean complete(boolean textures) { -+ MinecraftServer server = MinecraftServer.getServer(); -+ return complete(textures, PaperConfig.isProxyOnlineMode()); -+ } -+ public boolean complete(boolean textures, boolean onlineMode) { -+ MinecraftServer server = MinecraftServer.getServer(); -+ -+ boolean isCompleteFromCache = this.completeFromCache(true, onlineMode); -+ if (onlineMode && (!isCompleteFromCache || textures && !hasTextures())) { -+ GameProfile result = server.getSessionService().fillProfileProperties(profile, true); -+ if (result != null) { -+ copyProfileProperties(result, this.profile, true); -+ } -+ if (this.profile.isComplete()) { -+ server.getProfileCache().saveProfile(this.profile); -+ } -+ } -+ return profile.isComplete() && (!onlineMode || !textures || hasTextures()); -+ } -+ -+ private static void copyProfileProperties(GameProfile source, GameProfile target) { -+ copyProfileProperties(source, target, false); -+ } -+ -+ private static void copyProfileProperties(GameProfile source, GameProfile target, boolean clearTarget) { -+ PropertyMap sourceProperties = source.getProperties(); -+ PropertyMap targetProperties = target.getProperties(); -+ if (clearTarget) targetProperties.clear(); -+ if (sourceProperties.isEmpty()) { -+ return; -+ } -+ -+ for (Property property : sourceProperties.values()) { -+ targetProperties.removeAll(property.getName()); -+ targetProperties.put(property.getName(), property); -+ } -+ } -+ -+ private static ProfileProperty toBukkit(Property property) { -+ return new ProfileProperty(property.getName(), property.getValue(), property.getSignature()); -+ } -+ -+ public static PlayerProfile asBukkitCopy(GameProfile gameProfile) { -+ CraftPlayerProfile profile = new CraftPlayerProfile(gameProfile.getId(), gameProfile.getName()); -+ copyProfileProperties(gameProfile, profile.profile); -+ return profile; -+ } -+ -+ public static PlayerProfile asBukkitMirror(GameProfile profile) { -+ return new CraftPlayerProfile(profile); -+ } -+ -+ public static Property asAuthlib(ProfileProperty property) { -+ return new Property(property.getName(), property.getValue(), property.getSignature()); -+ } -+ -+ public static GameProfile asAuthlibCopy(PlayerProfile profile) { -+ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); -+ return asAuthlib(craft.clone()); -+ } -+ -+ public static GameProfile asAuthlib(PlayerProfile profile) { -+ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); -+ return craft.getGameProfile(); -+ } -+ -+ private class PropertySet extends AbstractSet { -+ -+ @Override -+ @Nonnull -+ public Iterator iterator() { -+ return new ProfilePropertyIterator(profile.getProperties().values().iterator()); -+ } -+ -+ @Override -+ public int size() { -+ return profile.getProperties().size(); -+ } -+ -+ @Override -+ public boolean add(ProfileProperty property) { -+ setProperty(property); -+ return true; -+ } -+ -+ @Override -+ public boolean addAll(Collection c) { -+ //noinspection unchecked -+ setProperties((Collection) c); -+ return true; -+ } -+ -+ @Override -+ public boolean contains(Object o) { -+ return o instanceof ProfileProperty && profile.getProperties().containsKey(((ProfileProperty) o).getName()); -+ } -+ -+ private class ProfilePropertyIterator implements Iterator { -+ private final Iterator iterator; -+ -+ ProfilePropertyIterator(Iterator iterator) { -+ this.iterator = iterator; -+ } -+ -+ @Override -+ public boolean hasNext() { -+ return iterator.hasNext(); -+ } -+ -+ @Override -+ public ProfileProperty next() { -+ return toBukkit(iterator.next()); -+ } -+ -+ @Override -+ public void remove() { -+ iterator.remove(); -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d64d45eb01c65864fca1077982d89bc05e0f811b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.*; -+import com.mojang.authlib.minecraft.MinecraftSessionService; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilEnvironment; -+ -+import java.net.Proxy; -+ -+public class PaperAuthenticationService extends YggdrasilAuthenticationService { -+ private final Environment environment; -+ public PaperAuthenticationService(Proxy proxy) { -+ super(proxy); -+ this.environment = (Environment)EnvironmentParser.getEnvironmentFromProperties().orElse(YggdrasilEnvironment.PROD);; -+ } -+ -+ @Override -+ public UserAuthentication createUserAuthentication(Agent agent) { -+ return new PaperUserAuthentication(this, agent); -+ } -+ -+ @Override -+ public MinecraftSessionService createMinecraftSessionService() { -+ return new PaperMinecraftSessionService(this, this.environment); -+ } -+ -+ @Override -+ public GameProfileRepository createProfileRepository() { -+ return new PaperGameProfileRepository(this, this.environment); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -new file mode 100644 -index 0000000000000000000000000000000000000000..582c169c85ac66f1f9430f79042e4655f776c157 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -@@ -0,0 +1,18 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.Agent; -+import com.mojang.authlib.Environment; -+import com.mojang.authlib.ProfileLookupCallback; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; -+ -+public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { -+ public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { -+ super(authenticationService, environment); -+ } -+ -+ @Override -+ public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { -+ super.findProfilesByNames(names, agent, callback); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -new file mode 100644 -index 0000000000000000000000000000000000000000..93d73c27340645c7502acafdc0b2cfbc1a759dd8 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -@@ -0,0 +1,30 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.Environment; -+import com.mojang.authlib.GameProfile; -+import com.mojang.authlib.minecraft.MinecraftProfileTexture; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; -+ -+import java.util.Map; -+ -+public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionService { -+ protected PaperMinecraftSessionService(YggdrasilAuthenticationService authenticationService, Environment environment) { -+ super(authenticationService, environment); -+ } -+ -+ @Override -+ public Map getTextures(GameProfile profile, boolean requireSecure) { -+ return super.getTextures(profile, requireSecure); -+ } -+ -+ @Override -+ public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { -+ return super.fillProfileProperties(profile, requireSecure); -+ } -+ -+ @Override -+ protected GameProfile fillGameProfile(GameProfile profile, boolean requireSecure) { -+ return super.fillGameProfile(profile, requireSecure); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3cdd06d3af7ff94f1fe1a11b9a9275e17c695a38 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java -@@ -0,0 +1,12 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.Agent; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; -+import java.util.UUID; -+ -+public class PaperUserAuthentication extends YggdrasilUserAuthentication { -+ public PaperUserAuthentication(YggdrasilAuthenticationService authenticationService, Agent agent) { -+ super(authenticationService, UUID.randomUUID().toString(), agent); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index d29fe67b7d39e368a873368a6be16042429e9209..68c3f069f8f832ab3d146748348aded69b5ad823 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -1,6 +1,8 @@ - package net.minecraft.server; - - import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import com.google.common.util.concurrent.ThreadFactoryBuilder; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; - import net.minecraft.core.BlockPos; -@@ -11,6 +13,7 @@ import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.ClipContext; - import net.minecraft.world.level.Level; - import org.apache.commons.lang.exception.ExceptionUtils; -+import com.mojang.authlib.GameProfile; - import org.bukkit.Location; - import org.bukkit.block.BlockFace; - import org.bukkit.craftbukkit.CraftWorld; -@@ -345,6 +348,10 @@ public final class MCUtil { - return run.get(); - } - -+ public static PlayerProfile toBukkit(GameProfile profile) { -+ return CraftPlayerProfile.asBukkitMirror(profile); -+ } -+ - /** - * Calculates distance between 2 entities - * @param e1 -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 5d83a8d4c69144219219877c521c364d912d2452..2bfc54941ec34c75c2d59bda748c75730b9951f7 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -124,7 +124,7 @@ public class Main { - } - - File file = (File) optionset.valueOf("universe"); // CraftBukkit -- YggdrasilAuthenticationService yggdrasilauthenticationservice = new YggdrasilAuthenticationService(Proxy.NO_PROXY); -+ YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper - MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); - GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); - GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName())); -diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index e8af352f813a5015d216fc590190ae8fdb03f77d..941b7e356c377fd8ad4e27409cd74c0046878396 100644 ---- a/src/main/java/net/minecraft/server/players/GameProfileCache.java -+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java -@@ -45,7 +45,7 @@ public class GameProfileCache { - - private static final Logger LOGGER = LogManager.getLogger(); - private static boolean usesAuthentication; -- private final Map profilesByName = Maps.newConcurrentMap(); -+ private final Map profilesByName = Maps.newConcurrentMap();private final Map nameCache = profilesByName; // Paper - OBFHELPER // Paper - private final Map profilesByUUID = Maps.newConcurrentMap(); - private final GameProfileRepository profileRepository; - private final Gson gson = (new GsonBuilder()).create(); -@@ -110,6 +110,7 @@ public class GameProfileCache { - return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper - } - -+ public void saveProfile(GameProfile gameprofile) { add(gameprofile); } // Paper - OBFHELPER - public synchronized void add(GameProfile gameprofile) { // Paper - synchronize - Calendar calendar = Calendar.getInstance(); - -@@ -159,6 +160,13 @@ public class GameProfileCache { - return gameprofile; - } - -+ // Paper start -+ @Nullable public GameProfile getProfileIfCached(String name) { -+ GameProfileCache.GameProfileInfo entry = this.nameCache.get(name.toLowerCase(Locale.ROOT)); -+ return entry == null ? null : entry.getProfile(); -+ } -+ // Paper end -+ - @Nullable - public GameProfile get(UUID uuid) { - GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); -@@ -341,7 +349,7 @@ public class GameProfileCache { - - static class GameProfileInfo { - -- private final GameProfile profile; -+ private final GameProfile profile;public GameProfile getProfile() { return profile; } // Paper - OBFHELPER - private final Date expirationDate; - private volatile long lastAccess; - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index b9e39a4c0aea3de96d1774ae0d0d23ff82162c7e..df68599520189e2699c8521d6c6ab7235612af33 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -223,6 +223,9 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; - - import net.md_5.bungee.api.chat.BaseComponent; // Spigot - -+import javax.annotation.Nullable; // Paper -+import javax.annotation.Nonnull; // Paper -+ - public final class CraftServer implements Server { - private final String serverName = "Paper"; // Paper - private final String serverVersion; -@@ -2315,5 +2318,24 @@ public final class CraftServer implements Server { - public boolean suggestPlayerNamesWhenNullTabCompletions() { - return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; - } -+ -+ @Override -+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { -+ return createProfile(uuid, null); -+ } -+ -+ @Override -+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull String name) { -+ return createProfile(null, name); -+ } -+ -+ @Override -+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { -+ Player player = uuid != null ? Bukkit.getPlayer(uuid) : (name != null ? Bukkit.getPlayerExact(name) : null); -+ if (player != null) { -+ return new com.destroystokyo.paper.profile.CraftPlayerProfile((CraftPlayer)player); -+ } -+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index 313ddd6b64e395a8caab77b3da005e52006ab2d7..750661540f55d3c59119dcc909e706e571a2123b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -@@ -80,6 +80,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - } - - private void setProfile(GameProfile profile) { -+ // Paper start -+ if (profile != null) { -+ com.destroystokyo.paper.profile.CraftPlayerProfile paperProfile = new com.destroystokyo.paper.profile.CraftPlayerProfile(profile); -+ paperProfile.completeFromCache(false, true); -+ profile = paperProfile.getGameProfile(); -+ } -+ // Paper end - this.profile = profile; - this.serializedProfile = (profile == null) ? null : NbtUtils.writeGameProfile(new CompoundTag(), profile); - } diff --git a/Remapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch b/Remapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch deleted file mode 100644 index e71eeed527..0000000000 --- a/Remapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 17 Jun 2017 15:18:30 -0400 -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 ae10c531ae69eaf6b78a342dcedb89c39fd8dbcc..3205bc2fb6c9031be68ff46dfca927e681163fa8 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1877,20 +1877,44 @@ public abstract class Player extends LivingEntity { - - } - -+ // Paper start -+ public Entity releaseLeftShoulderEntity() { -+ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityLeft()); -+ if (entity != null) { -+ this.setShoulderEntityLeft(new CompoundTag()); -+ } -+ return entity; -+ } -+ -+ public Entity releaseRightShoulderEntity() { -+ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityRight()); -+ if (entity != null) { -+ this.setShoulderEntityRight(new CompoundTag()); -+ } -+ return entity; -+ } -+ // Paper - maintain old signature - private boolean spawnEntityFromShoulder(CompoundTag nbttagcompound) { // CraftBukkit void->boolean -- if (!this.level.isClientSide && !nbttagcompound.isEmpty()) { -+ return spawnEntityFromShoulder0(nbttagcompound) != null; -+ } -+ -+ // Paper - return entity -+ private Entity spawnEntityFromShoulder0(@Nullable CompoundTag nbttagcompound) { -+ if (!this.level.isClientSide && nbttagcompound != null && !nbttagcompound.isEmpty()) { - return EntityType.create(nbttagcompound, this.level).map((entity) -> { // CraftBukkit - if (entity instanceof TamableAnimal) { - ((TamableAnimal) entity).setOwnerUUID(this.uuid); - } - - entity.setPos(this.getX(), this.getY() + 0.699999988079071D, this.getZ()); -- return ((ServerLevel) this.level).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit -- }).orElse(true); // CraftBukkit -+ boolean addedToWorld = ((ServerLevel) this.level).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit -+ return addedToWorld ? entity : null; -+ }).orElse(null); // CraftBukkit // Paper - false -> null - } - -- return true; // CraftBukkit -+ return null; // Paper - return null - } -+ // Paper end - - @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 b5c0f3d91cf451a972f0cf293db03a306073c493..c62d01719f21762aa10294815ab88e450e4dce3f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -494,6 +494,32 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - getHandle().getCooldowns().addCooldown(CraftMagicNumbers.getItem(material), ticks); - } - -+ // Paper start -+ @Override -+ public org.bukkit.entity.Entity releaseLeftShoulderEntity() { -+ if (!getHandle().getShoulderEntityLeft().isEmpty()) { -+ Entity entity = getHandle().releaseLeftShoulderEntity(); -+ if (entity != null) { -+ return entity.getBukkitEntity(); -+ } -+ } -+ -+ return null; -+ } -+ -+ @Override -+ public org.bukkit.entity.Entity releaseRightShoulderEntity() { -+ if (!getHandle().getShoulderEntityRight().isEmpty()) { -+ Entity entity = getHandle().releaseRightShoulderEntity(); -+ if (entity != null) { -+ return entity.getBukkitEntity(); -+ } -+ } -+ -+ return null; -+ } -+ // Paper end -+ - @Override - public boolean discoverRecipe(NamespacedKey recipe) { - return discoverRecipes(Arrays.asList(recipe)) != 0; diff --git a/Remapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch b/Remapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch deleted file mode 100644 index a9a4210f19..0000000000 --- a/Remapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 17 Jun 2017 17:00:32 -0400 -Subject: [PATCH] Profile Lookup Events - -Adds a Pre Lookup Event and a Post Lookup Event so that plugins may prefill in profile data, and cache the responses from -profiles that had to be looked up. - -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -index 582c169c85ac66f1f9430f79042e4655f776c157..08fdb681a68e8be6e4062af0630957ce3e524806 100644 ---- a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -@@ -1,11 +1,16 @@ - package com.destroystokyo.paper.profile; - -+import com.destroystokyo.paper.event.profile.LookupProfileEvent; -+import com.destroystokyo.paper.event.profile.PreLookupProfileEvent; -+import com.google.common.collect.Sets; - import com.mojang.authlib.Agent; - import com.mojang.authlib.Environment; -+import com.mojang.authlib.GameProfile; - import com.mojang.authlib.ProfileLookupCallback; - import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; - import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; - -+import java.util.Set; - public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { - public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { - super(authenticationService, environment); -@@ -13,6 +18,50 @@ public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { - - @Override - public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { -- super.findProfilesByNames(names, agent, callback); -+ Set unfoundNames = Sets.newHashSet(); -+ for (String name : names) { -+ PreLookupProfileEvent event = new PreLookupProfileEvent(name); -+ event.callEvent(); -+ if (event.getUUID() != null) { -+ // Plugin provided UUI, we can skip network call. -+ GameProfile gameprofile = new GameProfile(event.getUUID(), name); -+ // We might even have properties! -+ Set profileProperties = event.getProfileProperties(); -+ if (!profileProperties.isEmpty()) { -+ for (ProfileProperty property : profileProperties) { -+ gameprofile.getProperties().put(property.getName(), CraftPlayerProfile.asAuthlib(property)); -+ } -+ } -+ callback.onProfileLookupSucceeded(gameprofile); -+ } else { -+ unfoundNames.add(name); -+ } -+ } -+ -+ // Some things were not found.... Proceed to look up. -+ if (!unfoundNames.isEmpty()) { -+ String[] namesArr = unfoundNames.toArray(new String[unfoundNames.size()]); -+ super.findProfilesByNames(namesArr, agent, new PreProfileLookupCallback(callback)); -+ } -+ } -+ -+ private static class PreProfileLookupCallback implements ProfileLookupCallback { -+ private final ProfileLookupCallback callback; -+ -+ PreProfileLookupCallback(ProfileLookupCallback callback) { -+ this.callback = callback; -+ } -+ -+ @Override -+ public void onProfileLookupSucceeded(GameProfile gameProfile) { -+ PlayerProfile from = CraftPlayerProfile.asBukkitMirror(gameProfile); -+ new LookupProfileEvent(from).callEvent(); -+ callback.onProfileLookupSucceeded(gameProfile); -+ } -+ -+ @Override -+ public void onProfileLookupFailed(GameProfile gameProfile, Exception e) { -+ callback.onProfileLookupFailed(gameProfile, e); -+ } - } - } diff --git a/Remapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch b/Remapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch deleted file mode 100644 index f43b561da9..0000000000 --- a/Remapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 2 Jul 2017 21:35:56 -0500 -Subject: [PATCH] Block player logins during server shutdown - - -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index e3c1460c580ea348ee6d436018244441a5a1206e..fca291c34c67d552590320c6e6e9c08e21d19fa8 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -66,6 +66,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - } - - public void tick() { -+ // Paper start - Do not allow logins while the server is shutting down -+ if (!MinecraftServer.getServer().isRunning()) { -+ this.disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(org.spigotmc.SpigotConfig.restartMessage)[0]); -+ return; -+ } -+ // Paper end - if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) { - this.handleAcceptedLogin(); - } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { diff --git a/Remapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch b/Remapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch deleted file mode 100644 index 10fa81134b..0000000000 --- a/Remapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 18 Jun 2017 18:17:05 -0500 -Subject: [PATCH] Entity#fromMobSpawner() - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a017fa55002d6674124befa3f6e81eb70c9ce8f7..7e70bae5bc54ad17980789fa965fd539a7f193ea 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -267,6 +267,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; -+ public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one - protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end -@@ -1665,6 +1666,10 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); - tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); - } -+ // Save entity's from mob spawner status -+ if (spawnedViaMobSpawner) { -+ tag.putBoolean("Paper.FromMobSpawner", true); -+ } - // Paper end - return tag; - } catch (Throwable throwable) { -@@ -1797,6 +1802,8 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); - } -+ -+ spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status - // Paper end - - } catch (Throwable throwable) { -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index ed631d5bfba5d2543e8eed017a7c484ad3ddb453..7541155048744a9af2017ec039cf99a246addb0b 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -160,6 +160,7 @@ public abstract class BaseSpawner { - } - // Spigot End - } -+ entity.spawnedViaMobSpawner = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { - Entity vehicle = entity.getVehicle(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index b028946de7c8f52091635fe154c816453f1ddc93..ecb5f5ca547930f91602d539e541964cd9f10287 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1100,5 +1100,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - Location origin = getHandle().origin; - return origin == null ? null : origin.clone(); - } -+ -+ @Override -+ public boolean fromMobSpawner() { -+ return getHandle().spawnedViaMobSpawner; -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch b/Remapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch deleted file mode 100644 index 85d5e4f330..0000000000 --- a/Remapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 10 Dec 2016 16:24:06 -0500 -Subject: [PATCH] Improve the Saddle API for Horses - -Not all horses with Saddles have armor. This lets us break up the horses with saddles -and access their saddle state separately from an interface shared with Armor. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -index 116553ea587ab5ff3bc8a1530f51cd6efb7ae8ca..6136b3322a340d506ce744bcd15f71a158e46ad1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -@@ -5,6 +5,7 @@ import net.minecraft.world.entity.ai.attributes.Attributes; - import org.apache.commons.lang.Validate; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.inventory.CraftInventoryAbstractHorse; -+import org.bukkit.craftbukkit.inventory.CraftSaddledInventory; - import org.bukkit.entity.AbstractHorse; - import org.bukkit.entity.AnimalTamer; - import org.bukkit.entity.Horse; -@@ -98,6 +99,6 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac - - @Override - public AbstractHorseInventory getInventory() { -- return new CraftInventoryAbstractHorse(getHandle().inventory); -+ return new CraftSaddledInventory(getHandle().inventory); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java -index 7013059856c2471dc34112a1a2068b96b809dd96..b72b4260fc1c0e9928d70f97589d8db00849b9e8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java -@@ -4,7 +4,7 @@ import net.minecraft.world.Container; - import org.bukkit.inventory.HorseInventory; - import org.bukkit.inventory.ItemStack; - --public class CraftInventoryHorse extends CraftInventoryAbstractHorse implements HorseInventory { -+public class CraftInventoryHorse extends CraftSaddledInventory implements HorseInventory { - - public CraftInventoryHorse(Container inventory) { - super(inventory); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3a617c07d445bacf5a13e0e3ff6481823cfc8477 ---- /dev/null -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java -@@ -0,0 +1,12 @@ -+package org.bukkit.craftbukkit.inventory; -+ -+import net.minecraft.world.Container; -+import org.bukkit.inventory.SaddledHorseInventory; -+ -+public class CraftSaddledInventory extends CraftInventoryAbstractHorse implements SaddledHorseInventory { -+ -+ public CraftSaddledInventory(Container inventory) { -+ super(inventory); -+ } -+ -+} diff --git a/Remapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch b/Remapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch deleted file mode 100644 index bc3d68abd4..0000000000 --- a/Remapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 May 2016 22:43:12 -0400 -Subject: [PATCH] Implement ensureServerConversions API - -This will take a Bukkit ItemStack and run it through any conversions a server process would perform on it, -to ensure it meets latest minecraft expectations. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 32fa5ca0df07466e40817341d85d359b282f3078..41c8bbf93039add43695a52d2bfc0c2cef88463d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -346,5 +346,11 @@ public final class CraftItemFactory implements ItemFactory { - public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { - return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); - } -+ -+ // Paper start -+ @Override -+ public ItemStack ensureServerConversions(ItemStack item) { -+ return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch b/Remapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch deleted file mode 100644 index c27fb916c9..0000000000 --- a/Remapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 May 2016 23:59:38 -0400 -Subject: [PATCH] Implement getI18NDisplayName - -Gets the Display name as seen in the Client. -Currently the server only supports the English language. To override this, -You must replace the language file embedded in the server jar. - -diff --git a/src/main/java/net/minecraft/locale/Language.java b/src/main/java/net/minecraft/locale/Language.java -index 8a0d2e510aee160ec3a817fd72c23bc9dfeb6287..756b78a7dc3d3e76dc0a37375b304db0b6ecf684 100644 ---- a/src/main/java/net/minecraft/locale/Language.java -+++ b/src/main/java/net/minecraft/locale/Language.java -@@ -30,7 +30,7 @@ public abstract class Language { - - private static Language loadDefault() { - Builder builder = ImmutableMap.builder(); -- BiConsumer biconsumer = builder::put; -+ BiConsumer biconsumer = builder::put; // Paper - decompile fix - - try { - InputStream inputstream = Language.class.getResourceAsStream("/assets/minecraft/lang/en_us.json"); -@@ -87,10 +87,12 @@ public abstract class Language { - - } - -+ public static Language getInstance() { return getInstance(); } // Paper - OBFHELPER - public static Language getInstance() { - return Language.instance; - } - -+ public String translateKey(String key) { return getOrDefault(key); } // Paper - OBFHELPER - public abstract String getOrDefault(String key); - - public abstract boolean has(String key); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 41c8bbf93039add43695a52d2bfc0c2cef88463d..746755f76ae177b2eeccf66f8cd95e6ffd5acad9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -352,5 +352,18 @@ public final class CraftItemFactory implements ItemFactory { - public ItemStack ensureServerConversions(ItemStack item) { - return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); - } -+ -+ @Override -+ public String getI18NDisplayName(ItemStack item) { -+ net.minecraft.world.item.ItemStack nms = null; -+ if (item instanceof CraftItemStack) { -+ nms = ((CraftItemStack) item).handle; -+ } -+ if (nms == null) { -+ nms = CraftItemStack.asNMSCopy(item); -+ } -+ -+ return nms != null ? net.minecraft.locale.Language.getInstance().translateKey(nms.getItem().getDescriptionId()) : null; -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch b/Remapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch deleted file mode 100644 index 5051a6a195..0000000000 --- a/Remapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 3 Jul 2017 18:11:10 -0500 -Subject: [PATCH] ProfileWhitelistVerifyEvent - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7d6256f65d369fcbcfe1fffe7ac264788a38540b..ae60b233c4d56a4964b388f96e9cc66410774e8d 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -611,9 +611,9 @@ public abstract class PlayerList { - - // return chatmessage; - if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure -- } else if (!this.isWhiteListed(gameprofile)) { -- chatmessage = new TranslatableComponent("multiplayer.disconnect.not_whitelisted"); -- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure -+ } else if (!this.isWhitelisted(gameprofile, event)) { // Paper -+ //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper -+ //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted - } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { - IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); - -@@ -1005,9 +1005,25 @@ public abstract class PlayerList { - this.server.getCommands().sendCommands(player); - } - -+ // Paper start - public boolean isWhiteListed(GameProfile profile) { -- return !this.doWhiteList || this.ops.contains(profile) || this.whitelist.contains(profile); -+ return isWhitelisted(profile, null); - } -+ public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { -+ boolean isOp = this.ops.contains(gameprofile); -+ boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile); -+ final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; -+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); -+ event.callEvent(); -+ if (!event.isWhitelisted()) { -+ if (loginEvent != null) { -+ loginEvent.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getKickMessage() == null ? org.spigotmc.SpigotConfig.whitelistMessage : event.getKickMessage())); -+ } -+ return false; -+ } -+ return true; -+ } -+ // Paper end - - public boolean isOp(GameProfile profile) { - return this.ops.contains(profile) || this.server.isSingleplayerOwner(profile) && this.server.getWorldData().getAllowCommands() || this.allowCheatsForAllPlayers; diff --git a/Remapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch b/Remapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch deleted file mode 100644 index 8eacc81f8c..0000000000 --- a/Remapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DemonWav -Date: Sun, 6 Aug 2017 17:17:53 -0500 -Subject: [PATCH] Fix this stupid bullshit - -Disable the 15 second sleep when the server jar hasn't been rebuilt within a period of time. - -modified in order to prevent merge conflicts when Spigot changes/disables the warning, -and to provide some level of hint without being disruptive. - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 60d9980ccca6f1ac55b70f7684b917ddceac380a..808a7688ed81bdfef623ee0a151ff8f94df2a3d7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -224,10 +224,12 @@ public class Main { - Calendar deadline = Calendar.getInstance(); - deadline.add(Calendar.DAY_OF_YEAR, -28); - if (buildDate.before(deadline.getTime())) { -- System.err.println("*** Error, this build is outdated ***"); -+ // Paper start - This is some stupid bullshit -+ System.err.println("*** Warning, you've not updated in a while! ***"); - System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper -- System.err.println("*** Server will start in 20 seconds ***"); -- Thread.sleep(TimeUnit.SECONDS.toMillis(20)); -+ //System.err.println("*** Server will start in 20 seconds ***"); -+ //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); -+ // Paper End - } - } - diff --git a/Remapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch b/Remapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch deleted file mode 100644 index 07571c80e4..0000000000 --- a/Remapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:54:40 -0500 -Subject: [PATCH] Ocelot despawns should honor nametags and leash - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java -index 1b820ca48845cbe4a668cc31582c2ddf6d50c96a..142025cfb75b24dc6df8160f4922086404efa6a7 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java -@@ -128,7 +128,7 @@ public class Ocelot extends Animal { - - @Override - public boolean removeWhenFarAway(double distanceSquared) { -- return !this.isTrusting() /*&& this.ticksLived > 2400*/; // CraftBukkit -+ return !this.isTrusting() && !this.hasCustomName() && !this.isLeashed() /*&& this.ticksLived > 2400*/; // CraftBukkit // Paper - honor name and leash - } - - public static AttributeSupplier.Builder createAttributes() { diff --git a/Remapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/Remapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch deleted file mode 100644 index 3476f2d837..0000000000 --- a/Remapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:45:19 -0500 -Subject: [PATCH] Reset spawner timer when spawner event is cancelled - - -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 7541155048744a9af2017ec039cf99a246addb0b..4582fc1bb767214241568fbc22b0ee2cbf3322e0 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -161,6 +161,7 @@ public abstract class BaseSpawner { - // Spigot End - } - entity.spawnedViaMobSpawner = true; // Paper -+ flag = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { - Entity vehicle = entity.getVehicle(); -@@ -184,7 +185,7 @@ public abstract class BaseSpawner { - ((Mob) entity).spawnAnim(); - } - -- flag = true; -+ /*flag = true;*/ // Paper - moved up above cancellable event - } - } - } diff --git a/Remapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/Remapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch deleted file mode 100644 index 01e55f74f0..0000000000 --- a/Remapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mezz -Date: Wed, 9 Aug 2017 17:51:22 -0500 -Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike - - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index ecb6378a285dff4b34170410387ebb7a8510a6dc..81713c97f35263f4ab8d14f8b707aac3d6afea11 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -726,7 +726,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - gameprofilerfiller.push("blockEntities"); - timings.tileEntityTick.startTiming(); // Spigot - if (!this.tileEntityListUnload.isEmpty()) { -- this.tickableBlockEntities.removeAll(this.tileEntityListUnload); -+ // Paper start - Use alternate implementation with faster contains -+ java.util.Set toRemove = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); -+ toRemove.addAll(tileEntityListUnload); -+ this.tickableBlockEntities.removeAll(toRemove); -+ // Paper end - //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list - this.tileEntityListUnload.clear(); - } diff --git a/Remapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch b/Remapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch deleted file mode 100644 index 766b536512..0000000000 --- a/Remapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Thu, 17 Aug 2017 16:08:20 -0700 -Subject: [PATCH] Allow specifying a custom "authentication servers down" kick - message - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 48319aaf1c525c6fb7bdee5c2f570a0d056d4eae..52954fc3bf932cfc9d5ce63e3d3cace351305790 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper; - -+import com.google.common.base.Strings; - import com.google.common.base.Throwables; - - import java.io.File; -@@ -273,4 +274,9 @@ public class PaperConfig { - private static void suggestPlayersWhenNull() { - suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); - } -+ -+ public static String authenticationServersDownKickMessage = ""; // empty = use translatable message -+ private static void authenticationServersDownKickMessage() { -+ authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index fca291c34c67d552590320c6e6e9c08e21d19fa8..4b91699ddfa2ee298af5ba25447a85751facf4a4 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -275,6 +275,10 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - ServerLoginPacketListenerImpl.this.gameProfile = ServerLoginPacketListenerImpl.this.createFakeProfile(gameprofile); - ServerLoginPacketListenerImpl.this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT; - } else { -+ // Paper start -+ if (com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage != null) { -+ ServerLoginPacketListenerImpl.this.disconnect(new TextComponent(com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage)); -+ } else // Paper end - ServerLoginPacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.authservers_down")); - ServerLoginPacketListenerImpl.LOGGER.error("Couldn't verify username because servers are unavailable"); - } diff --git a/Remapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch b/Remapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch deleted file mode 100644 index fdb6acae74..0000000000 --- a/Remapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:49:48 -0500 -Subject: [PATCH] LivingEntity#setKiller - - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index c1786fcabeaee5732e9197db04268c5c4e164339..d6b4fabd232958ae1fd5405c7129551951cd7765 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -177,7 +177,7 @@ public abstract class LivingEntity extends Entity { - public float flyingSpeed; - @Nullable - public net.minecraft.world.entity.player.Player lastHurtByPlayer; -- protected int lastHurtByPlayerTime; -+ public int lastHurtByPlayerTime; // Paper - protected -> public - protected boolean dead; - protected int noActionTime; - protected float oRun; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index d8cd88d62f9abfc7960c187dd74239f61267ca57..006f4c71bbcda61b55815e7ceab91731ab062da0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -8,6 +8,7 @@ import java.util.Iterator; - import java.util.List; - import java.util.Set; - import java.util.UUID; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.InteractionHand; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.effect.MobEffect; -@@ -332,6 +333,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().lastHurtByPlayer == null ? null : (Player) getHandle().lastHurtByPlayer.getBukkitEntity(); - } - -+ // Paper start -+ @Override -+ public void setKiller(Player killer) { -+ ServerPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle(); -+ getHandle().lastHurtByPlayer = entityPlayer; -+ getHandle().lastHurtByMob = entityPlayer; -+ getHandle().lastHurtByPlayerTime = entityPlayer == null ? 0 : 100; // 100 value taken from EntityLiving#damageEntity -+ } -+ // Paper end -+ - @Override - public boolean addPotionEffect(PotionEffect effect) { - return addPotionEffect(effect, false); diff --git a/Remapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch b/Remapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch deleted file mode 100644 index 8c91986ef3..0000000000 --- a/Remapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Thu, 21 Sep 2017 16:14:55 +0200 -Subject: [PATCH] Handle plugin prefixes using Log4J configuration - -Display logger name in the console for all loggers except the -root logger, Bukkit's logger ("Minecraft") and Minecraft loggers. -Since plugins now use the plugin name as logger name this will -restore the plugin prefixes without having to prepend them manually -to the log messages. - -Logger prefixes are shown by default for all loggers except for -the root logger, the Minecraft/Mojang loggers and the Bukkit loggers. -This may cause additional prefixes to be disabled for plugins bypassing -the plugin logger. - -diff --git a/pom.xml b/pom.xml -index 3841fe3630c090f8a468333d43caeb2b5841329d..f5429f2f1979542fd93956d2f436d20d0e3a66b8 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -76,7 +76,7 @@ - - org.apache.logging.log4j - log4j-core -- runtime -+ compile - - - org.apache.logging.log4j -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 0083f979933d4a9035efb992ab0a2f250a56a979..3981ba5957fdc2929d54515f2b98bb7a4611e938 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -290,7 +290,7 @@ public class SpigotConfig - private static void playerSample() - { - playerSample = getInt( "settings.sample-count", 12 ); -- System.out.println( "Server Ping Player Sample Count: " + playerSample ); -+ Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger - } - - public static int playerShuffle; -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 620b9490e5f159080e50289d127404a1b56adbef..a8bdaaeaa1a9316848416f0533739b9b083ca151 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -5,10 +5,22 @@ - - - -- -+ -+ -+ -+ -+ -+ - - -- -+ -+ -+ -+ -+ -+ - - - diff --git a/Remapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch b/Remapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch deleted file mode 100644 index 5afb9562c0..0000000000 --- a/Remapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Sat, 23 Sep 2017 21:07:20 +0200 -Subject: [PATCH] Improve Log4J Configuration / Plugin Loggers - -Add full exceptions to log4j to not truncate stack traces - -Disable logger prefix for various plugins bypassing the plugin logger - -Some plugins bypass the plugin logger and add the plugin prefix -manually to the log message. Since they use other logger names -(e.g. qualified class names) these would now also appear in the -log. Disable the logger prefix for these plugins so the messages -show up correctly. - -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index a8bdaaeaa1a9316848416f0533739b9b083ca151..476f4a5cbe664ddd05474cb88553018bd334a5b8 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -6,19 +6,21 @@ - - - -- -+ - -- -+ -+ - - - - - -- -+ - -- -+ -+ - - - diff --git a/Remapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch b/Remapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch deleted file mode 100644 index 9abed7291f..0000000000 --- a/Remapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 28 Sep 2017 17:21:44 -0400 -Subject: [PATCH] Add PlayerJumpEvent - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 6a922e3522ac99a8e317a5f5f51fbb597baaf63e..f35a976de39f16d100bcbe411b64de357832c5df 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1166,7 +1166,34 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - boolean flag = d8 > 0.0D; - - if (this.player.isOnGround() && !packet.isOnGround() && flag) { -- this.player.jumpFromGround(); -+ // Paper start - Add player jump event -+ Player player = this.getPlayer(); -+ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. -+ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. -+ -+ // If the packet contains movement information then we update the To location with the correct XYZ. -+ if (packet.hasPos) { -+ to.setX(packet.x); -+ to.setY(packet.y); -+ to.setZ(packet.z); -+ } -+ -+ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. -+ if (packet.hasRot) { -+ to.setYaw(packet.yRot); -+ to.setPitch(packet.xRot); -+ } -+ -+ com.destroystokyo.paper.event.player.PlayerJumpEvent event = new com.destroystokyo.paper.event.player.PlayerJumpEvent(player, from, to); -+ -+ if (event.callEvent()) { -+ this.player.jumpFromGround(); -+ } else { -+ from = event.getFrom(); -+ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet()); -+ return; -+ } -+ // Paper end - } - - this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9)); diff --git a/Remapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch b/Remapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch deleted file mode 100644 index 1a0b7f3089..0000000000 --- a/Remapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 5 Oct 2017 01:54:07 +0100 -Subject: [PATCH] handle PacketPlayInKeepAlive async - -In 1.12.2, Mojang moved the processing of PacketPlayInKeepAlive off the main -thread, while entirely correct for the server, this causes issues with -plugins which are expecting the PlayerQuitEvent on the main thread. - -In order to counteract some bad behavior, we will post handling of the -disconnection to the main thread, but leave the actual processing of the packet -off the main thread. - -also adding some additional logging in order to help work out what is causing -random disconnections for clients. - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index f35a976de39f16d100bcbe411b64de357832c5df..f0aab8639c7d8440e4d70dd096200313d7958780 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2777,14 +2777,18 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - @Override - public void handleKeepAlive(ServerboundKeepAlivePacket packet) { -- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); // CraftBukkit -+ //PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit // Paper - This shouldn't be on the main thread - if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) { - int i = (int) (Util.getMillis() - this.keepAliveTime); - - this.player.latency = (this.player.latency * 3 + i) / 4; - this.keepAlivePending = false; - } else if (!this.isSingleplayerOwner()) { -+ // Paper start - This needs to be handled on the main thread for plugins -+ server.scheduleOnMain(() -> { - this.disconnect(new TranslatableComponent("disconnect.timeout")); -+ }); -+ // Paper end - } - - } diff --git a/Remapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch b/Remapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch deleted file mode 100644 index c18295ef08..0000000000 --- a/Remapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Tue, 10 Oct 2017 18:45:20 +0200 -Subject: [PATCH] Expose client protocol version and virtual host - - -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a5a7624f1f372a26b982836cd31cff15e2589e9b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java -@@ -0,0 +1,49 @@ -+package com.destroystokyo.paper.network; -+ -+import java.net.InetSocketAddress; -+ -+import javax.annotation.Nullable; -+import net.minecraft.network.Connection; -+ -+public class PaperNetworkClient implements NetworkClient { -+ -+ private final Connection networkManager; -+ -+ PaperNetworkClient(Connection networkManager) { -+ this.networkManager = networkManager; -+ } -+ -+ @Override -+ public InetSocketAddress getAddress() { -+ return (InetSocketAddress) this.networkManager.getRemoteAddress(); -+ } -+ -+ @Override -+ public int getProtocolVersion() { -+ return this.networkManager.protocolVersion; -+ } -+ -+ @Nullable -+ @Override -+ public InetSocketAddress getVirtualHost() { -+ return this.networkManager.virtualHost; -+ } -+ -+ public static InetSocketAddress prepareVirtualHost(String host, int port) { -+ int len = host.length(); -+ -+ // FML appends a marker to the host to recognize FML clients (\0FML\0) -+ int pos = host.indexOf('\0'); -+ if (pos >= 0) { -+ len = pos; -+ } -+ -+ // When clients connect with a SRV record, their host contains a trailing '.' -+ if (len > 0 && host.charAt(len - 1) == '.') { -+ len--; -+ } -+ -+ return InetSocketAddress.createUnresolved(host.substring(0, len), port); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 92c5c5bbcfe364475578b6a0eddfaa85858ace8a..3429c813a5b471cdfa561bd20849a303e5aacead 100644 ---- a/src/main/java/net/minecraft/network/Connection.java -+++ b/src/main/java/net/minecraft/network/Connection.java -@@ -70,6 +70,10 @@ public class Connection extends SimpleChannelInboundHandler> { - private float averageSentPackets; - private int tickCount; - private boolean handlingFault; -+ // Paper start - NetworkClient implementation -+ public int protocolVersion; -+ public java.net.InetSocketAddress virtualHost; -+ // Paper end - - public Connection(PacketFlow side) { - this.receiving = side; -diff --git a/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java b/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java -index 1eae2999ecc57f68ac9cd1d745191cba617b0de2..9ad400b15a2eb2d80bc763de28d648e22432b8f2 100644 ---- a/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java -@@ -39,6 +39,7 @@ public class ClientIntentionPacket implements Packet -Date: Sun, 15 Oct 2017 00:29:07 +0100 -Subject: [PATCH] revert serverside behavior of keepalives - -This patch intends to bump up the time that a client has to reply to the -server back to 30 seconds as per pre 1.12.2, which allowed clients -more than enough time to reply potentially allowing them to be less -tempermental due to lag spikes on the network thread, e.g. that caused -by plugins that are interacting with netty. - -We also add a system property to allow people to tweak how long the server -will wait for a reply. There is a compromise here between lower and higher -values, lower values will mean that dead connections can be closed sooner, -whereas higher values will make this less sensitive to issues such as spikes -from networking or during connections flood of chunk packets on slower clients, - at the cost of dead connections being kept open for longer. - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index f0aab8639c7d8440e4d70dd096200313d7958780..525728268f56470fdc24c4fd2f19d66943447778 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -221,7 +221,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - private final MinecraftServer server; - public ServerPlayer player; - private int tickCount; -- private long keepAliveTime; private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER -+ private long keepAliveTime = Util.getMillis(); private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER - private boolean keepAlivePending; private void setPendingPing(boolean isPending) { this.keepAlivePending = isPending;}; private boolean isPendingPing() { return this.keepAlivePending;}; // Paper - OBFHELPER - private long keepAliveChallenge; private void setKeepAliveID(long keepAliveID) { this.keepAliveChallenge = keepAliveID;}; private long getKeepAliveID() {return this.keepAliveChallenge; }; // Paper - OBFHELPER - // CraftBukkit start - multithreaded fields -@@ -252,6 +252,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - private int aboveGroundVehicleTickCount; - private int receivedMovePacketCount; - private int knownMovePacketCount; -+ private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - - public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { - this.server = server; -@@ -338,18 +339,25 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } - - this.server.getProfiler().push("keepAlive"); -- long i = Util.getMillis(); -- -- if (i - this.keepAliveTime >= 25000L) { // CraftBukkit -- if (this.keepAlivePending) { -- this.disconnect(new TranslatableComponent("disconnect.timeout")); -- } else { -- this.keepAlivePending = true; -- this.keepAliveTime = i; -- this.keepAliveChallenge = i; -- this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge)); -+ // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings -+ // This should effectively place the keepalive handling back to "as it was" before 1.12.2 -+ long currentTime = Util.getMillis(); -+ long elapsedTime = currentTime - this.getLastPing(); -+ -+ if (this.isPendingPing()) { -+ if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected -+ ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info -+ this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0])); -+ } -+ } else { -+ if (elapsedTime >= 15000L) { // 15 seconds -+ this.setPendingPing(true); -+ this.setLastPing(currentTime); -+ this.setKeepAliveID(currentTime); -+ this.send(new ClientboundKeepAlivePacket(this.getKeepAliveID())); - } - } -+ // Paper end - - this.server.getProfiler().pop(); - // CraftBukkit start diff --git a/Remapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch b/Remapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch deleted file mode 100644 index d30ac6d736..0000000000 --- a/Remapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 31 Oct 2017 03:26:18 +0100 -Subject: [PATCH] Send attack SoundEffects only to players who can see the - attacker - - -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 3205bc2fb6c9031be68ff46dfca927e681163fa8..43868c1e2d2c858a4f02119c3238f615f9b1ee72 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -28,6 +28,7 @@ import net.minecraft.network.chat.MutableComponent; - import net.minecraft.network.chat.TextComponent; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; -+import net.minecraft.network.protocol.game.ClientboundSoundPacket; - import net.minecraft.network.syncher.EntityDataAccessor; - import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; -@@ -1123,7 +1124,7 @@ public abstract class Player extends LivingEntity { - int i = b0 + EnchantmentHelper.getKnockbackBonus((LivingEntity) this); - - if (this.isSprinting() && flag) { -- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility - ++i; - flag1 = true; - } -@@ -1198,7 +1199,7 @@ public abstract class Player extends LivingEntity { - } - } - -- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility - this.sweepAttack(); - } - -@@ -1226,15 +1227,15 @@ public abstract class Player extends LivingEntity { - } - - if (flag2) { -- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility - this.crit(target); - } - - if (!flag2 && !flag3) { - if (flag) { -- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility - } else { -- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility - } - } - -@@ -1286,7 +1287,7 @@ public abstract class Player extends LivingEntity { - - this.applyExhaustion(level.spigotConfig.combatExhaustion, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value - } else { -- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility - if (flag4) { - target.clearFire(); - } -@@ -1721,6 +1722,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); - } -+ // Paper start - send SoundEffect to everyone who can see fromEntity -+ private static void sendSoundEffect(Player fromEntity, double x, double y, double z, SoundEvent soundEffect, SoundSource soundCategory, float volume, float pitch) { -+ fromEntity.level.playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself -+ if (fromEntity instanceof ServerPlayer) { -+ ((ServerPlayer) fromEntity).connection.send(new ClientboundSoundPacket(soundEffect, soundCategory, x, y, z, volume, pitch)); -+ } -+ } -+ // Paper end - - // CraftBukkit start - public void causeFoodExhaustion(float exhaustion) { diff --git a/Remapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch b/Remapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch deleted file mode 100644 index c2626fdee4..0000000000 --- a/Remapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 10 Nov 2017 23:03:12 -0500 -Subject: [PATCH] Option for maximum exp value when merging orbs - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 90ca51dfdbb3045dd528450225cba96f5834166e..6c692e58cde22003ecbf6dc5695799147c39905a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -342,4 +342,10 @@ public class PaperWorldConfig { - disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); - log("Creeper lingering effect: " + disableCreeperLingeringEffect); - } -+ -+ public int expMergeMaxValue; -+ private void expMergeMaxValue() { -+ expMergeMaxValue = getInt("experience-merge-max-value", -1); -+ log("Experience Merge Max Value: " + expMergeMaxValue); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 3f082b7fd50752728917a7da28cba4cb396a9fdf..7d6834796259e364196280ffa468b5bf999ec7b9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -587,16 +587,32 @@ public class CraftEventFactory { - net.minecraft.world.entity.ExperienceOrb xp = (net.minecraft.world.entity.ExperienceOrb) entity; - double radius = world.spigotConfig.expMerge; - if (radius > 0) { -+ // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics -+ final int maxValue = world.paperConfig.expMergeMaxValue; -+ final boolean mergeUnconditionally = world.paperConfig.expMergeMaxValue <= 0; -+ if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary -+ - List entities = world.getEntities(entity, entity.getBoundingBox().inflate(radius, radius, radius)); - for (Entity e : entities) { - if (e instanceof net.minecraft.world.entity.ExperienceOrb) { - net.minecraft.world.entity.ExperienceOrb loopItem = (net.minecraft.world.entity.ExperienceOrb) e; -- if (!loopItem.removed) { -- xp.value += loopItem.value; -- loopItem.remove(); -+ // Paper start -+ if (!loopItem.removed && !(maxValue > 0 && loopItem.value >= maxValue)) { -+ long newTotal = (long)xp.value + (long)loopItem.value; -+ if ((int) newTotal < 0) continue; // Overflow -+ if (maxValue > 0 && newTotal > (long)maxValue) { -+ loopItem.value = (int) (newTotal - maxValue); -+ xp.value = maxValue; -+ } else { -+ xp.value += loopItem.value; -+ loopItem.remove(); -+ } -+ // Paper end - } - } - } -+ -+ } // Paper end - End iteration skip check - All tweaking ends here - } - // Spigot end - } else if (!(entity instanceof ServerPlayer)) { diff --git a/Remapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch b/Remapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch deleted file mode 100644 index ae78b560ac..0000000000 --- a/Remapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: pkt77 -Date: Fri, 10 Nov 2017 23:46:34 -0500 -Subject: [PATCH] Add PlayerArmorChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EquipmentSlot.java b/src/main/java/net/minecraft/world/entity/EquipmentSlot.java -index b686b7a2faa4fbce37dcc3598b3c956661b91aaa..17cd5f525a45058ce34c66c87f9c133033bb8f4b 100644 ---- a/src/main/java/net/minecraft/world/entity/EquipmentSlot.java -+++ b/src/main/java/net/minecraft/world/entity/EquipmentSlot.java -@@ -16,6 +16,7 @@ public enum EquipmentSlot { - this.name = s; - } - -+ public EquipmentSlot.Type getType() { return this.getType(); } // Paper - OBFHELPER - public EquipmentSlot.Type getType() { - return this.type; - } -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index d6b4fabd232958ae1fd5405c7129551951cd7765..8b0d1f4fbc43a6f37a5f9c453b5dd142a4f69745 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.entity; - -+import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; // Paper - import com.google.common.base.Objects; - import com.google.common.collect.ImmutableList; - import com.google.common.collect.ImmutableMap; -@@ -2643,6 +2644,13 @@ public abstract class LivingEntity extends Entity { - ItemStack itemstack1 = this.getItemBySlot(enumitemslot); - - if (!ItemStack.matches(itemstack1, itemstack)) { -+ // Paper start - PlayerArmorChangeEvent -+ if (this instanceof ServerPlayer && enumitemslot.getType() == EquipmentSlot.Type.ARMOR) { -+ final org.bukkit.inventory.ItemStack oldItem = CraftItemStack.asBukkitCopy(itemstack); -+ final org.bukkit.inventory.ItemStack newItem = CraftItemStack.asBukkitCopy(itemstack1); -+ new PlayerArmorChangeEvent((Player) this.getBukkitEntity(), PlayerArmorChangeEvent.SlotType.valueOf(enumitemslot.name()), oldItem, newItem).callEvent(); -+ } -+ // Paper end - if (map == null) { - map = Maps.newEnumMap(EquipmentSlot.class); - } diff --git a/Remapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch b/Remapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch deleted file mode 100644 index c04d5e61cf..0000000000 --- a/Remapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: killme -Date: Sun, 12 Nov 2017 19:40:01 +0100 -Subject: [PATCH] Prevent logins from being processed when the player has - disconnected - - -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 4b91699ddfa2ee298af5ba25447a85751facf4a4..ff83fb15d0d0adb62c630fc7aafc134972bf15fc 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -73,7 +73,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - } - // Paper end - if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) { -- this.handleAcceptedLogin(); -+ // Paper start - prevent logins to be processed even though disconnect was called -+ if (connection.isConnected()) { -+ this.handleAcceptedLogin(); -+ } -+ // Paper end - } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { - ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); - diff --git a/Remapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch b/Remapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch deleted file mode 100644 index 939a2fed54..0000000000 --- a/Remapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 16 Nov 2017 12:12:41 +0000 -Subject: [PATCH] use CB BlockState implementations for captured blocks - -When modifying the world, CB will store a copy of the affected -blocks in order to restore their state in the case that the event -is cancelled. This change only modifies the collection of blocks -in the world by normal means, e.g. not during tree population, -as the potentially marginal overheads would serve no advantage. - -CB was using a CraftBlockState for all blocks, which causes issues -should any block that uses information beyond a data ID would suffer -from missing information, e.g. Skulls. - -By using CBs CraftBlock#getState(), we will maintain a proper copy of -the blockstate that will be valid for restoration, as opposed to dropping -information on restoration when the event is cancelled. - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 81713c97f35263f4ab8d14f8b707aac3d6afea11..b4248d46ccb1a95e21601bca1198512287edcabf 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -124,7 +124,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; -- public Map capturedBlockStates = new java.util.LinkedHashMap<>(); -+ public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper - public Map capturedTileEntities = new HashMap<>(); - public List captureDrops; - public long ticksPerAnimalSpawns; -@@ -346,7 +346,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { - // CraftBukkit start - tree generation - if (this.captureTreeGeneration) { -- CapturedBlockState blockstate = capturedBlockStates.get(pos); -+ CraftBlockState blockstate = capturedBlockStates.get(pos); - if (blockstate == null) { - blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); - this.capturedBlockStates.put(pos.immutable(), blockstate); -@@ -366,7 +366,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - // CraftBukkit start - capture blockstates - boolean captured = false; - if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) { -- CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, pos, flags); -+ CraftBlockState blockstate = (CraftBlockState) world.getBlockAt(pos.getX(), pos.getY(), pos.getZ()).getState(); // Paper - use CB getState to get a suitable snapshot -+ blockstate.setFlag(flags); // Paper - set flag - this.capturedBlockStates.put(pos.immutable(), blockstate); - captured = true; - } -@@ -624,7 +625,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public BlockState getBlockState(BlockPos pos) { - // CraftBukkit start - tree generation - if (captureTreeGeneration) { -- CapturedBlockState previous = capturedBlockStates.get(pos); -+ CraftBlockState previous = capturedBlockStates.get(pos); // Paper - if (previous != null) { - return previous.getHandle(); - } diff --git a/Remapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch b/Remapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch deleted file mode 100644 index d3837145f0..0000000000 --- a/Remapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 6 Nov 2017 21:08:22 -0500 -Subject: [PATCH] API to get a BlockState without a snapshot - -This allows you to get a BlockState without creating a snapshot, operating -on the real tile entity. - -This is useful for where performance is needed - -also Avoid NPE during CraftBlockEntityState load if could not get TE - -If Tile Entity was null, correct Sign to return empty lines instead of null - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index d08ed44884726ca2ba4578226b8aa6244778f4c7..84012c2d12817e657b046bc168cc8eddebcd3831 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -47,6 +47,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - public BlockEntity(BlockEntityType type) { - this.worldPosition = BlockPos.ZERO; - this.type = type; -+ persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init - } - - // Paper start -@@ -95,7 +96,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - public void load(BlockState state, CompoundTag tag) { - this.worldPosition = new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); - // CraftBukkit start - read container -- this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); -+ this.persistentDataContainer.clear(); // Paper - clear instead of reinit - - net.minecraft.nbt.Tag persistentDataTag = tag.get("PublicBukkitValues"); - if (persistentDataTag instanceof CompoundTag) { -@@ -245,7 +246,12 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - } - - // CraftBukkit start - add method -+ // Paper start - public InventoryHolder getOwner() { -+ return getOwner(true); -+ } -+ public InventoryHolder getOwner(boolean useSnapshot) { -+ // Paper end - if (level == null) return null; - // Spigot start - org.bukkit.block.Block block = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); -@@ -254,7 +260,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - return null; - } - // Spigot end -- org.bukkit.block.BlockState state = block.getState(); -+ org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper - if (state instanceof InventoryHolder) return (InventoryHolder) state; - return null; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 9d5b3801205e2800b0bcf238c5656321e3654f03..d73086970db19531db66c2e8af52da91d0b1ea28 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -313,6 +313,20 @@ public class CraftBlock implements Block { - - @Override - public BlockState getState() { -+ // Paper start - allow disabling the use of snapshots -+ return getState(true); -+ } -+ public BlockState getState(boolean useSnapshot) { -+ boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT; -+ CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot; -+ try { -+ return getState0(); -+ } finally { -+ CraftBlockEntityState.DISABLE_SNAPSHOT = prev; -+ } -+ } -+ public BlockState getState0() { -+ // Paper end - Material material = getType(); - - switch (material) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index e89a93082fe07fdb14df8ffef5beca5bd52d7866..730fda7f0bf02400d349959e9cc2aafaed000b21 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -26,20 +26,40 @@ public class CraftBlockEntityState extends CraftBlockStat - this.tileEntity = tileEntityClass.cast(world.getHandle().getBlockEntity(this.getPosition())); - Preconditions.checkState(this.tileEntity != null, "Tile is null, asynchronous access? %s", block); - -+ // Paper start -+ this.snapshotDisabled = DISABLE_SNAPSHOT; -+ if (DISABLE_SNAPSHOT) { -+ this.snapshot = this.tileEntity; -+ } else { -+ this.snapshot = this.createSnapshot(this.tileEntity); -+ } - // copy tile entity data: -- this.snapshot = this.createSnapshot(tileEntity); -- this.load(snapshot); -+ if(this.snapshot != null) { -+ this.load(this.snapshot); -+ } -+ // Paper end - } - -+ public final boolean snapshotDisabled; // Paper -+ public static boolean DISABLE_SNAPSHOT = false; // Paper -+ - public CraftBlockEntityState(Material material, T tileEntity) { - super(material); - - this.tileEntityClass = (Class) tileEntity.getClass(); - this.tileEntity = tileEntity; -- -+ // Paper start -+ this.snapshotDisabled = DISABLE_SNAPSHOT; -+ if (DISABLE_SNAPSHOT) { -+ this.snapshot = this.tileEntity; -+ } else { -+ this.snapshot = this.createSnapshot(this.tileEntity); -+ } - // copy tile entity data: -- this.snapshot = this.createSnapshot(tileEntity); -- this.load(snapshot); -+ if(this.snapshot != null) { -+ this.load(this.snapshot); -+ } -+ // Paper end - } - - private T createSnapshot(T tileEntity) { -diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -index e3664110bef9315cfde5b61dde98dce77016600e..10ba8b810c1759adc439f753d36108e30cf70140 100644 ---- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -@@ -155,4 +155,10 @@ public final class CraftPersistentDataContainer implements PersistentDataContain - public Map serialize() { - return (Map) CraftNBTTagConfigSerializer.serialize(toTagCompound()); - } -+ -+ // Paper start -+ public void clear() { -+ this.customDataTags.clear(); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch b/Remapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch deleted file mode 100644 index 1bd4fdfc05..0000000000 --- a/Remapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 26 Nov 2017 13:19:58 -0500 -Subject: [PATCH] AsyncTabCompleteEvent - -Let plugins be able to control tab completion of commands and chat async. - -This will be useful for frameworks like ACF so we can define async safe completion handlers, -and avoid going to main for tab completions. - -Especially useful if you need to query a database in order to obtain the results for tab -completion, such as offline players. - -Also adds isCommand and getLocation to the sync TabCompleteEvent - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 525728268f56470fdc24c4fd2f19d66943447778..8d0c44b6c2c99d5161c5d4b79209b79ff6db75e4 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -711,10 +711,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - @Override - public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { -- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); -+ // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async - // CraftBukkit start - if (chatSpamField.addAndGet(this, 1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { -- this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0])); -+ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper - return; - } - // CraftBukkit end -@@ -724,12 +724,35 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - stringreader.skip(); - } - -- ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); -+ // Paper start - async tab completion -+ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -+ java.util.List completions = new java.util.ArrayList<>(); -+ String buffer = packet.getCommand(); -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, -+ buffer, true, null); -+ event.callEvent(); -+ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server -+ if (!event.isHandled()) { -+ if (!event.isCancelled()) { - -- this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -- this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); -- }); -+ this.server.scheduleOnMain(() -> { // Paper - This needs to be on main -+ ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); -+ -+ this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -+ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -+ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); -+ }); -+ }); -+ } -+ } else if (!completions.isEmpty()) { -+ com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); -+ -+ builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); -+ completions.forEach(builder::suggest); -+ player.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), builder.buildFuture().join())); -+ } -+ // Paper end - async tab completion - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index df68599520189e2699c8521d6c6ab7235612af33..10addb128a357e7719854bf4f9d75f5def32b27d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1850,7 +1850,7 @@ public final class CraftServer implements Server { - offers = tabCompleteChat(player, message); - } - -- TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers); -+ TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? net.minecraft.server.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), new BlockPos(pos)) : null); // Paper - getPluginManager().callEvent(tabEvent); - - return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index a957695457cf3252848ce6ef37069692841b8e28..c5e00bd9e2790992202aadf8eec2002fc88c78f1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -28,6 +28,39 @@ public class ConsoleCommandCompleter implements Completer { - public void complete(LineReader reader, ParsedLine line, List candidates) { - final CraftServer server = this.server.server; - final String buffer = line.line(); -+ // Async Tab Complete -+ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -+ java.util.List completions = new java.util.ArrayList<>(); -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, -+ buffer, true, null); -+ event.callEvent(); -+ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ -+ if (event.isCancelled() || event.isHandled()) { -+ // Still fire sync event with the provided completions, if someone is listening -+ if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { -+ List finalCompletions = completions; -+ Waitable> syncCompletions = new Waitable>() { -+ @Override -+ protected List evaluate() { -+ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); -+ return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); -+ } -+ }; -+ server.getServer().processQueue.add(syncCompletions); -+ try { -+ completions = syncCompletions.get(); -+ } catch (InterruptedException | ExecutionException e1) { -+ e1.printStackTrace(); -+ } -+ } -+ -+ if (!completions.isEmpty()) { -+ candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); -+ } -+ return; -+ } -+ - // Paper end - Waitable> waitable = new Waitable>() { - @Override diff --git a/Remapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch b/Remapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch deleted file mode 100644 index 5d0147c515..0000000000 --- a/Remapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 29 Nov 2017 22:18:54 -0500 -Subject: [PATCH] Avoid NPE in PathfinderGoalTempt - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java -index 186025458e923d153e9e47c2be147a9bb53db517..11ca6a752bac4ba4bc683bef844d204b739fab63 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java -@@ -63,7 +63,7 @@ public class TemptGoal extends Goal { - } - this.target = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle(); - } -- return tempt; -+ return tempt && this.target != null; // Paper - must have target - plugin might of cancelled - // CraftBukkit end - } - } diff --git a/Remapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch b/Remapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch deleted file mode 100644 index fe7129d330..0000000000 --- a/Remapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:02:53 -0500 -Subject: [PATCH] PlayerPickupExperienceEvent - -Allows plugins to cancel a player picking up an experience orb - -diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index 3ddb0a9f15c920c9a2080f76edfda0504c1e287a..885c5a920204a31b24c7d360390eaf4177c30698 100644 ---- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -5,6 +5,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.tags.FluidTags; - import net.minecraft.tags.Tag; -@@ -231,7 +232,7 @@ public class ExperienceOrb extends Entity { - @Override - public void playerTouch(Player player) { - if (!this.level.isClientSide) { -- if (this.throwTime == 0 && player.takeXpDelay == 0) { -+ if (this.throwTime == 0 && player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((ServerPlayer) player).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - player.takeXpDelay = 2; - player.take(this, 1); - Entry entry = EnchantmentHelper.getRandomItemWith(Enchantments.MENDING, (LivingEntity) player, ItemStack::isDamaged); diff --git a/Remapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch b/Remapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch deleted file mode 100644 index 28b23c94bd..0000000000 --- a/Remapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:57:26 -0500 -Subject: [PATCH] ExperienceOrbMergeEvent - -Fired when the server is about to merge 2 experience orbs -Plugins can cancel this if they want to ensure experience orbs do not lose important -metadata such as spawn reason, or conditionally move data from source to target. - -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 7d6834796259e364196280ffa468b5bf999ec7b9..5e8ff18f98b03741ccbb927f87499ae36d775a86 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -597,7 +597,7 @@ public class CraftEventFactory { - if (e instanceof net.minecraft.world.entity.ExperienceOrb) { - net.minecraft.world.entity.ExperienceOrb loopItem = (net.minecraft.world.entity.ExperienceOrb) e; - // Paper start -- if (!loopItem.removed && !(maxValue > 0 && loopItem.value >= maxValue)) { -+ if (!loopItem.removed && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper - long newTotal = (long)xp.value + (long)loopItem.value; - if ((int) newTotal < 0) continue; // Overflow - if (maxValue > 0 && newTotal > (long)maxValue) { diff --git a/Remapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch b/Remapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch deleted file mode 100644 index 24cf0a602e..0000000000 --- a/Remapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 20 Dec 2017 17:36:49 -0500 -Subject: [PATCH] Ability to apply mending to XP API - -This allows plugins that give players the ability to apply the experience -points to the Item Mending formula, which will repair an item instead -of giving the player experience points. - -Both an API To standalone mend, and apply mending logic to .giveExp has been added. - -diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index 885c5a920204a31b24c7d360390eaf4177c30698..52b90ef3a145325209d3d903a2b7c9a44c332cbe 100644 ---- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -264,10 +264,12 @@ public class ExperienceOrb extends Entity { - } - } - -+ public final int durToXp(int i) { return durabilityToXp(i); } // Paper OBFHELPER - private int durabilityToXp(int repairAmount) { - return repairAmount / 2; - } - -+ public final int xpToDur(int i) { return xpToDurability(i); } // Paper OBFHELPER - private int xpToDurability(int experienceAmount) { - return experienceAmount * 2; - } -diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java -index 045f937f0b7acd73469b65897bea2ca9036acf22..c82e1b6e3ec98530099fd6452fdaaefebfd99b33 100644 ---- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java -+++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java -@@ -269,8 +269,8 @@ public class EnchantmentHelper { - return getItemEnchantmentLevel(Enchantments.CHANNELING, stack) > 0; - } - -- @Nullable -- public static Entry getRandomItemWith(Enchantment enchantment, LivingEntity entity) { -+ public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, LivingEntity entityliving) { Entry entry = getRandomItemWith(enchantment, entityliving); return entry != null ? entry.getValue() : ItemStack.NULL_ITEM; } // Paper - OBFHELPER -+ @Nullable public static Entry getRandomItemWith(Enchantment enchantment, LivingEntity entity) { - return getRandomItemWith(enchantment, entity, (itemstack) -> { - 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 8a5bf0b83c1e65f07e14da0e053a64c34976b91a..efdcb8dac8db15c4bbaed84a7861ce98339e516a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -58,11 +58,14 @@ import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.network.ServerGamePacketListenerImpl; - import net.minecraft.server.players.UserWhiteListEntry; - import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.ExperienceOrb; - import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.ai.attributes.AttributeInstance; - import net.minecraft.world.entity.ai.attributes.AttributeMap; - import net.minecraft.world.entity.ai.attributes.Attributes; - import net.minecraft.world.inventory.AbstractContainerMenu; -+import net.minecraft.world.item.enchantment.EnchantmentHelper; -+import net.minecraft.world.item.enchantment.Enchantments; - import net.minecraft.world.level.GameType; - import net.minecraft.world.level.block.entity.SignBlockEntity; - import net.minecraft.world.level.saveddata.maps.MapDecoration; -@@ -1176,8 +1179,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return GameMode.getByValue(getHandle().gameMode.getGameModeForPlayer().getId()); - } - -+ // Paper start - @Override -- public void giveExp(int exp) { -+ public int applyMending(int amount) { -+ ServerPlayer handle = getHandle(); -+ // Logic copied from EntityExperienceOrb and remapped to unobfuscated methods/properties -+ net.minecraft.world.item.ItemStack itemstack = EnchantmentHelper.getRandomEquippedItemWithEnchant(Enchantments.MENDING, handle); -+ if (!itemstack.isEmpty() && itemstack.getItem().canBeDepleted()) { -+ -+ ExperienceOrb orb = net.minecraft.world.entity.EntityType.EXPERIENCE_ORB.create(handle.level); -+ orb.value = amount; -+ orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM; -+ orb.setPosRaw(handle.getX(), handle.getY(), handle.getZ()); -+ -+ int i = Math.min(orb.xpToDur(amount), itemstack.getDamageValue()); -+ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, i); -+ i = event.getRepairAmount(); -+ orb.removed = true; -+ if (!event.isCancelled()) { -+ amount -= orb.durToXp(i); -+ itemstack.setDamageValue(itemstack.getDamageValue() - i); -+ } -+ } -+ return amount; -+ } -+ -+ @Override -+ public void giveExp(int exp, boolean applyMending) { -+ if (applyMending) { -+ exp = this.applyMending(exp); -+ } -+ // Paper end - getHandle().giveExperiencePoints(exp); - } - diff --git a/Remapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch b/Remapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch deleted file mode 100644 index 94fb614365..0000000000 --- a/Remapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 11 Jan 2018 16:47:28 -0600 -Subject: [PATCH] Make max squid spawn height configurable - -I don't know why upstream made only the minimum height configurable but -whatever - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6c692e58cde22003ecbf6dc5695799147c39905a..3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -348,4 +348,9 @@ public class PaperWorldConfig { - expMergeMaxValue = getInt("experience-merge-max-value", -1); - log("Experience Merge Max Value: " + expMergeMaxValue); - } -+ -+ public double squidMaxSpawnHeight; -+ private void squidMaxSpawnHeight() { -+ squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java -index 0b782c77f6d93002c35b123044b5a3eb03e63672..5a7582fd4f8e883d2f08a0227932c17d7576b957 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Squid.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java -@@ -196,7 +196,8 @@ public class Squid extends WaterAnimal { - } - - public static boolean checkSquidSpawnRules(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) { -- return pos.getY() > world.getLevel().spigotConfig.squidSpawnRangeMin && pos.getY() < world.getSeaLevel(); // Spigot -+ final double maxHeight = world.getLevel().paperConfig.squidMaxSpawnHeight > 0 ? world.getLevel().paperConfig.squidMaxSpawnHeight : world.getSeaLevel(); // Paper -+ return pos.getY() > world.getLevel().spigotConfig.squidSpawnRangeMin && pos.getY() < maxHeight; // Spigot // Paper - } - - public void setMovementVector(float x, float y, float z) { diff --git a/Remapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch b/Remapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch deleted file mode 100644 index 341927c26e..0000000000 --- a/Remapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 17:01:31 -0500 -Subject: [PATCH] PreCreatureSpawnEvent - -Adds an event to fire before an Entity is created, so that plugins that need to cancel -CreatureSpawnEvent can do so from this event instead. - -Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste -as it's done after the Entity object has been fully created. - -Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event -instead and save a lot of server resources. - -See: https://github.com/PaperMC/Paper/issues/917 - -diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index e3d92d1d35911b2960a7ca82bd4f324d285d0533..e39d950783599b01271bdb7e67fe68b46af0c49c 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -17,6 +17,7 @@ import net.minecraft.nbt.ListTag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.tags.BlockTags; -@@ -317,6 +318,20 @@ public class EntityType { - - @Nullable - public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ // Paper start - Call PreCreatureSpawnEvent -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath()); -+ if (type != null) { -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(worldserver, blockposition), -+ type, -+ spawnReason -+ ); -+ if (!event.callEvent()) { -+ return null; -+ } -+ } -+ // Paper end - T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); - - if (t0 != null) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java -index f3a7807a20b279056d5640ab02aa77f7b1dabc2a..880d69bad933294a2cfdea9adb3e648e29eb42be 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java -@@ -33,8 +33,8 @@ public class GolemSensor extends Sensor { - Optional> optional = entityliving.getBrain().getMemory(MemoryModuleType.MOBS); - - if (optional.isPresent()) { -- boolean flag = ((List) optional.get()).stream().anyMatch((entityliving1) -> { -- return entityliving1.getEntityType().equals(EntityType.IRON_GOLEM); -+ boolean flag = optional.get().stream().anyMatch((entityliving1) -> { // Paper - decompile fixes -+ return entityliving1.getType().equals(EntityType.IRON_GOLEM); - }); - - if (flag) { -@@ -44,6 +44,7 @@ public class GolemSensor extends Sensor { - } - } - -+ public static void setDetectedRecently(LivingEntity entityLiving) { golemDetected(entityLiving); } // Paper - OBFHELPER - public static void golemDetected(LivingEntity entityliving) { - entityliving.getBrain().setMemoryWithExpiry(MemoryModuleType.GOLEM_DETECTED_RECENTLY, true, 600L); - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index a66fab2e04a5d87ced139ed15d2434c5ffcec695..eed6265dc8275921a18fc5f4970ba131ba782132 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/Villager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.DebugPackets; - import net.minecraft.network.syncher.EntityDataAccessor; - import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.sounds.SoundEvent; -@@ -942,6 +943,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - BlockPos blockposition1 = this.findSpawnPositionForGolemInColumn(blockposition, d0, d1); - - if (blockposition1 != null) { -+ // Paper start - Call PreCreatureSpawnEvent -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(level, blockposition1), -+ org.bukkit.entity.EntityType.IRON_GOLEM, -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE -+ ); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ GolemSensor.golemDetected(this); // Set Golem Last Seen to stop it from spawning another one -+ return null; -+ } -+ break; -+ } -+ // Paper end - IronGolem entityirongolem = (IronGolem) EntityType.IRON_GOLEM.create(world, (CompoundTag) null, (Component) null, (Player) null, blockposition1, MobSpawnType.MOB_SUMMONED, false, false); - - if (entityirongolem != null) { -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 4582fc1bb767214241568fbc22b0ee2cbf3322e0..ac572eba10a7239d71dfae060f623b076d4252ce 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -12,6 +12,7 @@ import net.minecraft.core.particles.ParticleTypes; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.StringUtil; - import net.minecraft.util.WeighedRandom; -@@ -125,6 +126,27 @@ public abstract class BaseSpawner { - ServerLevel worldserver = (ServerLevel) world; - - if (SpawnPlacements.checkSpawnRules((EntityType) optional.get(), worldserver, MobSpawnType.SPAWNER, new BlockPos(d3, d4, d5), world.getRandom())) { -+ // Paper start -+ EntityType entityType = optional.get(); -+ String key = EntityType.getKey(entityType).getPath(); -+ -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); -+ if (type != null) { -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(world, d3, d4, d5), -+ type, -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER -+ ); -+ if (!event.callEvent()) { -+ flag = true; -+ if (event.shouldAbortSpawn()) { -+ break; -+ } -+ continue; -+ } -+ } -+ // Paper end - Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> { - entity1.moveTo(d3, d4, d5, entity1.yRot, entity1.xRot); - return entity1; -diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index a19ac1cb7e4d8d478648a048b2bfa0daf85a80c9..8a71eaf2855be0d415d1f7b18dbec98353fe5b47 100644 ---- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java -+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -15,6 +15,7 @@ import net.minecraft.core.Direction; - import net.minecraft.core.Position; - import net.minecraft.core.Registry; - import net.minecraft.nbt.CompoundTag; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.tags.BlockTags; - import net.minecraft.tags.FluidTags; -@@ -214,9 +215,16 @@ public final class NaturalSpawner { - j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); - } - -- if (isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { -+ // Paper start -+ Boolean doSpawning = a(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); -+ if (doSpawning == null) { -+ return; -+ } -+ if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { -+ // Paper end - Mob entityinsentient = getMobForSpawn(world, biomesettingsmobs_c.type); - -+ - if (entityinsentient == null) { - return; - } -@@ -269,17 +277,33 @@ public final class NaturalSpawner { - } - } - -- private static boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { -- EntityType entitytypes = spawnEntry.type; -+ private static Boolean a(ServerLevel worldserver, MobCategory enumcreaturetype, StructureFeatureManager structuremanager, ChunkGenerator chunkgenerator, MobSpawnSettings.SpawnerData biomesettingsmobs_c, BlockPos.MutableBlockPos blockposition_mutableblockposition, double d0) { // Paper -+ EntityType entitytypes = biomesettingsmobs_c.type; -+ // Paper start -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(entitytypes).getPath()); -+ if (type != null) { -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(worldserver, blockposition_mutableblockposition), -+ type, SpawnReason.NATURAL -+ ); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ return null; -+ } -+ return false; -+ } -+ } -+ // Paper end - - if (entitytypes.getCategory() == MobCategory.MISC) { - return false; -- } else if (!entitytypes.canSpawnFarFromPlayer() && squaredDistance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { -+ } else if (!entitytypes.canSpawnFarFromPlayer() && d0 > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { - return false; -- } else if (entitytypes.canSummon() && canSpawnMobAt(world, structureAccessor, chunkGenerator, group, spawnEntry, (BlockPos) pos)) { -+ } else if (entitytypes.canSummon() && canSpawnMobAt(worldserver, structuremanager, chunkgenerator, enumcreaturetype, biomesettingsmobs_c, (BlockPos) blockposition_mutableblockposition)) { - SpawnPlacements.Type entitypositiontypes_surface = SpawnPlacements.getPlacementType(entitytypes); - -- return !isSpawnPositionOk(entitypositiontypes_surface, (LevelReader) world, pos, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, world, MobSpawnType.NATURAL, pos, world.random) ? false : world.noCollision(entitytypes.getAABB((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D))); -+ return !isSpawnPositionOk(entitypositiontypes_surface, (LevelReader) worldserver, blockposition_mutableblockposition, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, worldserver, MobSpawnType.NATURAL, blockposition_mutableblockposition, worldserver.random) ? false : worldserver.noCollision(entitytypes.getAABB((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D))); - } else { - return false; - } diff --git a/Remapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch b/Remapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch deleted file mode 100644 index 0b2a988e3b..0000000000 --- a/Remapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 17:36:02 -0500 -Subject: [PATCH] PlayerNaturallySpawnCreaturesEvent - -This event can be used for when you want to exclude a certain player -from triggering monster spawns on a server. - -Also a highly more effecient way to blanket block spawns in a world - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 3b6f35b695117bd2b0c71b994efc55fa1084eddc..97d5437df10a6d0124e944404e88650547b7d8a8 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -964,12 +964,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; - chunkRange = (chunkRange > 8) ? 8 : chunkRange; - -- double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; -+ final int finalChunkRange = chunkRange; // Paper for lambda below -+ //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event - // Spigot end - long i = chunkcoordintpair.toLong(); - - return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { -- return !entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot -+ // Paper start - -+ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; -+ double blockRange = 16384.0D; -+ if (reducedRange) { -+ event = entityplayer.playerNaturallySpawnedEvent; -+ if (event == null || event.isCancelled()) return false; -+ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); -+ } -+ -+ return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot -+ // Paper end - }); - } - -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index d0b0fdaf5451bcc7f7ac7dab28aa59ef77e6dd97..a7122a0411f4a8656efd4facde3403c8093bc8a6 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -612,6 +612,15 @@ public class ServerChunkCache extends ChunkSource { - this.level.getProfiler().pop(); - //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper - //Collections.shuffle(list); // Paper -+ //Paper start - call player naturally spawn event -+ int chunkRange = level.spigotConfig.mobSpawnRange; -+ chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; -+ chunkRange = Math.min(chunkRange, 8); -+ for (ServerPlayer entityPlayer : this.level.players()) { -+ entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); -+ entityPlayer.playerNaturallySpawnedEvent.callEvent(); -+ }; -+ // Paper end - this.level.timings.chunkTicks.startTiming(); // Paper - this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... - Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 4ff66138fa43cf932b95d6d3dc050a9cd7b28ad4..0fa977a31cf945b74f3a046b6be302b10f494ad1 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.level; - -+import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent; - import com.google.common.collect.Lists; - import com.mojang.authlib.GameProfile; - import com.mojang.datafixers.util.Either; -@@ -225,6 +226,7 @@ public class ServerPlayer extends Player implements ContainerListener { - public boolean sentListPacket = false; - public Integer clientViewDistance; - // CraftBukkit end -+ public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - - public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper - diff --git a/Remapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch b/Remapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch deleted file mode 100644 index 746bff56a9..0000000000 --- a/Remapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 19 Jan 2018 00:36:25 -0500 -Subject: [PATCH] Add setPlayerProfile API for Skulls - -This allows you to create already filled textures on Skulls to avoid texture lookups -which commonly cause rate limit issues with Mojang API - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -index 2047ea32489d03051783d18a0dbaf456bfdbb2a1..a06c51a56846750ce59a70e9698c2b57c3517aad 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -@@ -1,5 +1,7 @@ - package org.bukkit.craftbukkit.block; - -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import com.google.common.base.Preconditions; - import com.mojang.authlib.GameProfile; - import net.minecraft.server.MinecraftServer; -@@ -15,6 +17,7 @@ import org.bukkit.block.data.BlockData; - import org.bukkit.block.data.Directional; - import org.bukkit.block.data.Rotatable; - import org.bukkit.craftbukkit.entity.CraftPlayer; -+import javax.annotation.Nullable; - - public class CraftSkull extends CraftBlockEntityState implements Skull { - -@@ -105,6 +108,20 @@ public class CraftSkull extends CraftBlockEntityState implemen - } - } - -+ // Paper start -+ @Override -+ public void setPlayerProfile(PlayerProfile profile) { -+ Preconditions.checkNotNull(profile, "profile"); -+ this.profile = CraftPlayerProfile.asAuthlibCopy(profile); -+ } -+ -+ @Nullable -+ @Override -+ public PlayerProfile getPlayerProfile() { -+ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; -+ } -+ // Paper end -+ - @Override - public BlockFace getRotation() { - BlockData blockData = getBlockData(); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index 750661540f55d3c59119dcc909e706e571a2123b..aa64ffc23d8941ff05ea7791ddd628c3c6be90e4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -@@ -4,10 +4,8 @@ import com.google.common.collect.ImmutableMap.Builder; - import com.mojang.authlib.GameProfile; - import java.util.Map; - import java.util.UUID; --import net.minecraft.nbt.CompoundTag; --import net.minecraft.nbt.NbtUtils; --import net.minecraft.nbt.Tag; --import net.minecraft.world.level.block.entity.SkullBlockEntity; -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import org.bukkit.Bukkit; - import org.bukkit.Material; - import org.bukkit.OfflinePlayer; -@@ -18,6 +16,11 @@ import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta; - import org.bukkit.craftbukkit.util.CraftMagicNumbers; - import org.bukkit.inventory.meta.SkullMeta; - -+import javax.annotation.Nullable; -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.nbt.NbtUtils; -+import net.minecraft.nbt.Tag; -+import net.minecraft.world.level.block.entity.SkullBlockEntity; - @DelegateDeserialization(SerializableMeta.class) - class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - -@@ -149,6 +152,19 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - return hasOwner() ? profile.getName() : null; - } - -+ // Paper start -+ @Override -+ public void setPlayerProfile(@Nullable PlayerProfile profile) { -+ setProfile((profile == null) ? null : CraftPlayerProfile.asAuthlibCopy(profile)); -+ } -+ -+ @Nullable -+ @Override -+ public PlayerProfile getPlayerProfile() { -+ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; -+ } -+ // Paper end -+ - @Override - public OfflinePlayer getOwningPlayer() { - if (hasOwner()) { -@@ -175,8 +191,8 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - } else { - // Paper start - Use Online Players Skull - GameProfile newProfile = null; -- net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); -- if (player != null) newProfile = player.getProfile(); -+ net.minecraft.server.level.ServerPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); -+ if (player != null) newProfile = player.getGameProfile(); - if (newProfile == null) newProfile = new GameProfile(null, name); - setProfile(newProfile); - // Paper end diff --git a/Remapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch b/Remapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch deleted file mode 100644 index 30643d081c..0000000000 --- a/Remapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 2 Jan 2018 00:31:26 -0500 -Subject: [PATCH] Fill Profile Property Events - -Allows plugins to populate profile properties from local sources to avoid calls out to Mojang API -to fill in textures for example. - -If Mojang API does need to be hit, event fire so you can get the results. - -This is useful for implementing a ProfileCache for Player Skulls - -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -index 93d73c27340645c7502acafdc0b2cfbc1a759dd8..5c7d2ee19243d0911a3a00af3ae42078a2ccba94 100644 ---- a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -@@ -1,6 +1,8 @@ - package com.destroystokyo.paper.profile; - - import com.mojang.authlib.Environment; -+import com.destroystokyo.paper.event.profile.FillProfileEvent; -+import com.destroystokyo.paper.event.profile.PreFillProfileEvent; - import com.mojang.authlib.GameProfile; - import com.mojang.authlib.minecraft.MinecraftProfileTexture; - import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -@@ -20,7 +22,15 @@ public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionServi - - @Override - public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { -- return super.fillProfileProperties(profile, requireSecure); -+ CraftPlayerProfile playerProfile = (CraftPlayerProfile) CraftPlayerProfile.asBukkitMirror(profile); -+ new PreFillProfileEvent(playerProfile).callEvent(); -+ profile = playerProfile.getGameProfile(); -+ if (profile.isComplete() && profile.getProperties().containsKey("textures")) { -+ return profile; -+ } -+ GameProfile gameProfile = super.fillProfileProperties(profile, requireSecure); -+ new FillProfileEvent(CraftPlayerProfile.asBukkitMirror(gameProfile)).callEvent(); -+ return gameProfile; - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch b/Remapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch deleted file mode 100644 index 6190b30a26..0000000000 --- a/Remapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 19 Jan 2018 08:15:29 -0600 -Subject: [PATCH] PlayerAdvancementCriterionGrantEvent - - -diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java -index 8df1803754817707a5ad292f65276871dacc4508..5ab62fc74085bbbb0c81b2f4d16a35c9345cd1f1 100644 ---- a/src/main/java/net/minecraft/server/PlayerAdvancements.java -+++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java -@@ -297,6 +297,12 @@ public class PlayerAdvancements { - boolean flag1 = advancementprogress.isDone(); - - if (advancementprogress.a(criterionName)) { -+ // Paper start -+ if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.bukkit, criterionName).callEvent()) { -+ advancementprogress.b(criterionName); -+ return false; -+ } -+ // Paper end - this.unregisterListeners(advancement); - this.progressChanged.add(advancement); - flag = true; diff --git a/Remapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch b/Remapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch deleted file mode 100644 index 14798cca5e..0000000000 --- a/Remapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch +++ /dev/null @@ -1,296 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 27 Jan 2018 17:04:14 -0500 -Subject: [PATCH] Add ArmorStand Item Meta - -This is adds basic item meta for armor stands. It does not add all -possible metadata however. - -There are armor, hand, and equipment types, as well as position data -that can also be added here. This initial addition should serve a -starting point for future additions in this area. - -Fixes GH-559 - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -index 783b9c7283492fb71776b61f9820c21a39868c47..6521f4f6f660885f59f024640239609fb67d691f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -@@ -9,9 +9,22 @@ import org.bukkit.configuration.serialization.DelegateDeserialization; - import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey; - - @DelegateDeserialization(CraftMetaItem.SerializableMeta.class) --public class CraftMetaArmorStand extends CraftMetaItem { -+public class CraftMetaArmorStand extends CraftMetaItem implements com.destroystokyo.paper.inventory.meta.ArmorStandMeta { // Paper - - static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag"); -+ // Paper start -+ static final ItemMetaKey INVISIBLE = new ItemMetaKey("Invisible", "invisible"); -+ static final ItemMetaKey NO_BASE_PLATE = new ItemMetaKey("NoBasePlate", "no-base-plate"); -+ static final ItemMetaKey SHOW_ARMS = new ItemMetaKey("ShowArms", "show-arms"); -+ static final ItemMetaKey SMALL = new ItemMetaKey("Small", "small"); -+ static final ItemMetaKey MARKER = new ItemMetaKey("Marker", "marker"); -+ -+ private boolean invisible; -+ private boolean noBasePlate; -+ private boolean showArms; -+ private boolean small; -+ private boolean marker; -+ // Paper end - CompoundTag entityTag; - - CraftMetaArmorStand(CraftMetaItem meta) { -@@ -22,6 +35,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { - } - - CraftMetaArmorStand armorStand = (CraftMetaArmorStand) meta; -+ // Paper start -+ this.invisible = armorStand.invisible; -+ this.noBasePlate = armorStand.noBasePlate; -+ this.showArms = armorStand.showArms; -+ this.small = armorStand.small; -+ this.marker = armorStand.marker; -+ // Paper end - this.entityTag = armorStand.entityTag; - } - -@@ -30,11 +50,47 @@ public class CraftMetaArmorStand extends CraftMetaItem { - - if (tag.contains(ENTITY_TAG.NBT)) { - entityTag = tag.getCompound(ENTITY_TAG.NBT); -+ -+ // Paper start -+ if (entityTag.contains(INVISIBLE.NBT)) { -+ invisible = entityTag.getBoolean(INVISIBLE.NBT); -+ } -+ -+ if (entityTag.contains(NO_BASE_PLATE.NBT)) { -+ noBasePlate = entityTag.getBoolean(NO_BASE_PLATE.NBT); -+ } -+ -+ if (entityTag.contains(SHOW_ARMS.NBT)) { -+ showArms = entityTag.getBoolean(SHOW_ARMS.NBT); -+ } -+ -+ if (entityTag.contains(SMALL.NBT)) { -+ small = entityTag.getBoolean(SMALL.NBT); -+ } -+ -+ if (entityTag.contains(MARKER.NBT)) { -+ marker = entityTag.getBoolean(MARKER.NBT); -+ } -+ // Paper end - } - } - - CraftMetaArmorStand(Map map) { - super(map); -+ -+ // Paper start -+ boolean invis = SerializableMeta.getBoolean(map, INVISIBLE.BUKKIT); -+ boolean noBase = SerializableMeta.getBoolean(map, NO_BASE_PLATE.BUKKIT); -+ boolean showArms = SerializableMeta.getBoolean(map, SHOW_ARMS.BUKKIT); -+ boolean small = SerializableMeta.getBoolean(map, SMALL.BUKKIT); -+ boolean marker = SerializableMeta.getBoolean(map, MARKER.BUKKIT); -+ -+ this.invisible = invis; -+ this.noBasePlate = noBase; -+ this.showArms = showArms; -+ this.small = small; -+ this.marker = marker; -+ // Paper end - } - - @Override -@@ -57,6 +113,32 @@ public class CraftMetaArmorStand extends CraftMetaItem { - void applyToItem(CompoundTag tag) { - super.applyToItem(tag); - -+ // Paper start -+ if (!isArmorStandEmpty() && entityTag == null) { -+ entityTag = new CompoundTag(); -+ } -+ -+ if (isInvisible()) { -+ entityTag.putBoolean(INVISIBLE.NBT, invisible); -+ } -+ -+ if (hasNoBasePlate()) { -+ entityTag.putBoolean(NO_BASE_PLATE.NBT, noBasePlate); -+ } -+ -+ if (shouldShowArms()) { -+ entityTag.putBoolean(SHOW_ARMS.NBT, showArms); -+ } -+ -+ if (isSmall()) { -+ entityTag.putBoolean(SMALL.NBT, small); -+ } -+ -+ if (isMarker()) { -+ entityTag.putBoolean(MARKER.NBT, marker); -+ } -+ // Paper end -+ - if (entityTag != null) { - tag.put(ENTITY_TAG.NBT, entityTag); - } -@@ -78,7 +160,7 @@ public class CraftMetaArmorStand extends CraftMetaItem { - } - - boolean isArmorStandEmpty() { -- return !(entityTag != null); -+ return !(isInvisible() || hasNoBasePlate() || shouldShowArms() || isSmall() || isMarker() || entityTag != null); - } - - @Override -@@ -89,7 +171,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { - if (meta instanceof CraftMetaArmorStand) { - CraftMetaArmorStand that = (CraftMetaArmorStand) meta; - -- return entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : entityTag == null; -+ // Paper start -+ return invisible == that.invisible && -+ noBasePlate == that.noBasePlate && -+ showArms == that.showArms && -+ small == that.small && -+ marker == that.marker; -+ // Paper end - } - return true; - } -@@ -104,9 +192,14 @@ public class CraftMetaArmorStand extends CraftMetaItem { - final int original; - int hash = original = super.applyHash(); - -- if (entityTag != null) { -- hash = 73 * hash + entityTag.hashCode(); -- } -+ // Paper start -+ hash += entityTag != null ? 73 * hash + entityTag.hashCode() : 0; -+ hash += isInvisible() ? 61 * hash + 1231 : 0; -+ hash += hasNoBasePlate() ? 61 * hash + 1231 : 0; -+ hash += shouldShowArms() ? 61 * hash + 1231 : 0; -+ hash += isSmall() ? 61 * hash + 1231 : 0; -+ hash += isMarker() ? 61 * hash + 1231 : 0; -+ // Paper end - - return original != hash ? CraftMetaArmorStand.class.hashCode() ^ hash : hash; - } -@@ -115,6 +208,28 @@ public class CraftMetaArmorStand extends CraftMetaItem { - Builder serialize(Builder builder) { - super.serialize(builder); - -+ // Paper start -+ if (isInvisible()) { -+ builder.put(INVISIBLE.BUKKIT, invisible); -+ } -+ -+ if (hasNoBasePlate()) { -+ builder.put(NO_BASE_PLATE.BUKKIT, noBasePlate); -+ } -+ -+ if (shouldShowArms()) { -+ builder.put(SHOW_ARMS.BUKKIT, showArms); -+ } -+ -+ if (isSmall()) { -+ builder.put(SMALL.BUKKIT, small); -+ } -+ -+ if (isMarker()) { -+ builder.put(MARKER.BUKKIT, marker); -+ } -+ // Paper end -+ - return builder; - } - -@@ -128,4 +243,56 @@ public class CraftMetaArmorStand extends CraftMetaItem { - - return clone; - } -+ -+ // Paper start -+ @Override -+ public boolean isInvisible() { -+ return invisible; -+ } -+ -+ @Override -+ public boolean hasNoBasePlate() { -+ return noBasePlate; -+ } -+ -+ @Override -+ public boolean shouldShowArms() { -+ return showArms; -+ } -+ -+ @Override -+ public boolean isSmall() { -+ return small; -+ } -+ -+ @Override -+ public boolean isMarker() { -+ return marker; -+ } -+ -+ @Override -+ public void setInvisible(boolean invisible) { -+ this.invisible = invisible; -+ } -+ -+ @Override -+ public void setNoBasePlate(boolean noBasePlate) { -+ this.noBasePlate = noBasePlate; -+ } -+ -+ @Override -+ public void setShowArms(boolean showArms) { -+ this.showArms = showArms; -+ } -+ -+ @Override -+ public void setSmall(boolean small) { -+ this.small = small; -+ } -+ -+ @Override -+ public void setMarker(boolean marker) { -+ this.marker = marker; -+ } -+ // 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 521699615778c4b724d10edfee1d3915e036eb2e..64f166fa93e998a58a895d785ff8c9e62dacb1bb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -1441,6 +1441,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - CraftMetaCrossbow.CHARGED.NBT, - CraftMetaCrossbow.CHARGED_PROJECTILES.NBT, - CraftMetaSuspiciousStew.EFFECTS.NBT, -+ // Paper start -+ CraftMetaArmorStand.ENTITY_TAG.NBT, -+ CraftMetaArmorStand.INVISIBLE.NBT, -+ CraftMetaArmorStand.NO_BASE_PLATE.NBT, -+ CraftMetaArmorStand.SHOW_ARMS.NBT, -+ CraftMetaArmorStand.SMALL.NBT, -+ CraftMetaArmorStand.MARKER.NBT, -+ // Paper end - CraftMetaCompass.LODESTONE_DIMENSION.NBT, - CraftMetaCompass.LODESTONE_POS.NBT, - CraftMetaCompass.LODESTONE_TRACKED.NBT -diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -index 9a351c137776ac622f4df7353bb353142b3a6ccc..42f577ed3508ba5a380648461e149f16ce97c9bd 100644 ---- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -@@ -313,6 +313,7 @@ public class ItemMetaTest extends AbstractTestingBase { - final CraftMetaArmorStand meta = (CraftMetaArmorStand) cleanStack.getItemMeta(); - meta.entityTag = new NBTTagCompound(); - meta.entityTag.setBoolean("Small", true); -+ meta.setInvisible(true); // Paper - cleanStack.setItemMeta(meta); - return cleanStack; - } diff --git a/Remapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch b/Remapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch deleted file mode 100644 index 826fede56c..0000000000 --- a/Remapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 11 Feb 2018 10:43:46 +0000 -Subject: [PATCH] Extend Player Interact cancellation - -GUIs are opened on the client, meaning that the server cannot block them from opening, -However, it is possible to close these GUIs from the server. - -Flower pots are also not updated on the client when interaction is cancelled, this patch -also resolves this. - -Update adjacent blocks of doors, double plants, pistons and beds -when cancelling interaction. - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index 26ce794cb8d089c03fab5dd0a0c910783d10b72e..b1a53093eb5b5f359eedb6c252cf6d0d1ae8e409 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -23,6 +23,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; - import net.minecraft.network.protocol.game.ClientboundBlockBreakAckPacket; - import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; -+import net.minecraft.network.protocol.game.ClientboundContainerClosePacket; - import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket; - import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; - import net.minecraft.server.MinecraftServer; -@@ -180,6 +181,11 @@ public class ServerPlayerGameMode { - PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, direction, this.player.inventory.getSelected(), InteractionHand.MAIN_HAND); - if (event.isCancelled()) { - // Let the client know the block still exists -+ // Paper start - brute force neighbor blocks for any attached blocks -+ for (Direction dir : Direction.values()) { -+ this.player.connection.send(new ClientboundBlockUpdatePacket(level, pos.relative(dir))); -+ } -+ // Paper end - this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); - // Update any tile entity data for this block - BlockEntity tileentity = this.level.getBlockEntity(pos); -@@ -484,6 +490,7 @@ public class ServerPlayerGameMode { - interactItemStack = stack.copy(); - - if (event.useInteractedBlock() == Event.Result.DENY) { -+ - // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. - if (iblockdata.getBlock() instanceof DoorBlock) { - boolean bottom = iblockdata.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER; -@@ -496,7 +503,13 @@ public class ServerPlayerGameMode { - - // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) - player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.above())); -+ // Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method -+ } else if (iblockdata.getBlock() instanceof StructureBlock) { -+ player.connection.send(new ClientboundContainerClosePacket()); -+ } else if (iblockdata.getBlock() instanceof CommandBlock) { -+ player.connection.send(new ClientboundContainerClosePacket()); - } -+ // Paper end - extend Player Interact cancellation - player.getBukkitEntity().updateInventory(); // SPIGOT-2867 - enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS; - } else if (this.gameModeForPlayer == GameType.SPECTATOR) { diff --git a/Remapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch b/Remapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch deleted file mode 100644 index 643044c740..0000000000 --- a/Remapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 24 Feb 2018 01:14:55 -0500 -Subject: [PATCH] Tameable#getOwnerUniqueId API - -This is faster if all you need is the UUID, as .getOwner() will cause -an OfflinePlayer to be loaded from disk. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -index 6136b3322a340d506ce744bcd15f71a158e46ad1..04b0b2449f20220c74892788080d40e3693151c5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -@@ -89,6 +89,9 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac - } - } - -+ public UUID getOwnerUniqueId() { -+ return getOwnerUUID(); -+ } - public UUID getOwnerUUID() { - return getHandle().getOwnerUUID(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -index 35587fd6d90dfd1da2075c3268692eac7a2eaa25..85fe4f07d35c514f2a7c7920ec416fb651434c83 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -@@ -17,6 +17,9 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat - return (TamableAnimal) super.getHandle(); - } - -+ public UUID getOwnerUniqueId() { -+ return getOwnerUUID(); -+ } - public UUID getOwnerUUID() { - try { - return getHandle().getOwnerUUID(); diff --git a/Remapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch b/Remapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch deleted file mode 100644 index 671d7965cc..0000000000 --- a/Remapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Sat, 10 Mar 2018 00:50:24 +0100 -Subject: [PATCH] Toggleable player crits, helps mitigate hacked clients. - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2..48f0385c7203c7955de5a015f3dc42be2ab7b681 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -192,6 +192,11 @@ public class PaperWorldConfig { - disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); - } - -+ public boolean disablePlayerCrits; -+ private void disablePlayerCrits() { -+ disablePlayerCrits = getBoolean("game-mechanics.disable-player-crits", false); -+ } -+ - public boolean allChunksAreSlimeChunks; - private void allChunksAreSlimeChunks() { - allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", 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 43868c1e2d2c858a4f02119c3238f615f9b1ee72..63871a3a1981b2e8c7ad74214196e35684acb584 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1131,6 +1131,7 @@ public abstract class Player extends LivingEntity { - - boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; - -+ flag2 = flag2 && !level.paperConfig.disablePlayerCrits; // Paper - flag2 = flag2 && !this.isSprinting(); - if (flag2) { - f *= 1.5F; diff --git a/Remapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/Remapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch deleted file mode 100644 index 4b912daff9..0000000000 --- a/Remapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 10 Mar 2018 16:33:15 -0500 -Subject: [PATCH] Prevent Frosted Ice from loading/holding chunks - - -diff --git a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java -index ae2f5acd008d5d7163b56cb4a2d29354299959ca..99843f1ca4737d40ae0626fce931c97bbf5ab81d 100644 ---- a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java -@@ -40,7 +40,8 @@ public class FrostedIceBlock extends IceBlock { - Direction enumdirection = aenumdirection[j]; - - blockposition_mutableblockposition.setWithOffset((Vec3i) pos, enumdirection); -- BlockState iblockdata1 = world.getBlockState(blockposition_mutableblockposition); -+ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper -+ if (iblockdata1 == null) { continue; } // Paper - - if (iblockdata1.is((Block) this) && !this.slightlyMelt(iblockdata1, (Level) world, blockposition_mutableblockposition)) { - world.getBlockTicks().scheduleTick(blockposition_mutableblockposition, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay -@@ -83,7 +84,9 @@ public class FrostedIceBlock extends IceBlock { - Direction enumdirection = aenumdirection[l]; - - blockposition_mutableblockposition.setWithOffset((Vec3i) pos, enumdirection); -- if (world.getBlockState(blockposition_mutableblockposition).is((Block) this)) { -+ // Paper start -+ BlockState type = world.getTypeIfLoaded(blockposition_mutableblockposition); -+ if (type != null && type.is((Block) this)) { // Paper end - ++j; - if (j >= maxNeighbors) { - return false; diff --git a/Remapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch b/Remapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch deleted file mode 100644 index 45eef88da2..0000000000 --- a/Remapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 11 Mar 2018 14:13:33 -0400 -Subject: [PATCH] Disable Explicit Network Manager Flushing - -This seems completely pointless, as packet dispatch uses .writeAndFlush. - -Things seem to work fine without explicit flushing, but incase issues arise, -provide a System property to re-enable it using improved logic of doing the -flushing on the netty event loop, so it won't do the flush on the main thread. - -Renable flushing by passing -Dpaper.explicit-flush=true - -diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 3429c813a5b471cdfa561bd20849a303e5aacead..7f4681910751047a26fdfc6b59bc460449c02001 100644 ---- a/src/main/java/net/minecraft/network/Connection.java -+++ b/src/main/java/net/minecraft/network/Connection.java -@@ -73,6 +73,7 @@ public class Connection extends SimpleChannelInboundHandler> { - // Paper start - NetworkClient implementation - public int protocolVersion; - public java.net.InetSocketAddress virtualHost; -+ private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); - // Paper end - - public Connection(PacketFlow side) { -@@ -240,7 +241,7 @@ public class Connection extends SimpleChannelInboundHandler> { - } - - if (this.channel != null) { -- this.channel.flush(); -+ if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version - } - - if (this.tickCount++ % 20 == 0) { diff --git a/Remapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch b/Remapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch deleted file mode 100644 index 762c35c3ad..0000000000 --- a/Remapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch +++ /dev/null @@ -1,378 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 15:56:26 +0200 -Subject: [PATCH] Implement extended PaperServerListPingEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4ecd0c5bbea55f68549c85aa27e80e2c7e6265d4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ServerPlayer; -+import org.bukkit.entity.Player; -+import org.bukkit.util.CachedServerIcon; -+ -+import javax.annotation.Nullable; -+ -+class PaperServerListPingEventImpl extends PaperServerListPingEvent { -+ -+ private final MinecraftServer server; -+ -+ PaperServerListPingEventImpl(MinecraftServer server, StatusClient client, int protocolVersion, @Nullable CachedServerIcon icon) { -+ super(client, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers(), -+ server.getServerModName() + ' ' + server.getServerVersion(), protocolVersion, icon); -+ this.server = server; -+ } -+ -+ @Override -+ protected final Object[] getOnlinePlayers() { -+ return this.server.getPlayerList().players.toArray(); -+ } -+ -+ @Override -+ protected final Player getBukkitPlayer(Object player) { -+ return ((ServerPlayer) player).getBukkitEntity(); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d926ad804355ee2fdc5910b2505e8671602acdab ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java -@@ -0,0 +1,11 @@ -+package com.destroystokyo.paper.network; -+ -+import net.minecraft.network.Connection; -+ -+class PaperStatusClient extends PaperNetworkClient implements StatusClient { -+ -+ PaperStatusClient(Connection networkManager) { -+ super(networkManager); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4c2351b03b58511b80017b58ee9b20ab5193adc9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java -@@ -0,0 +1,110 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; -+import com.google.common.base.MoreObjects; -+import com.google.common.base.Strings; -+import com.mojang.authlib.GameProfile; -+import io.papermc.paper.adventure.AdventureComponent; -+import java.util.List; -+import java.util.UUID; -+import javax.annotation.Nonnull; -+import net.minecraft.network.Connection; -+import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; -+import net.minecraft.network.protocol.status.ServerStatus; -+import net.minecraft.server.MinecraftServer; -+ -+public final class StandardPaperServerListPingEventImpl extends PaperServerListPingEventImpl { -+ -+ private static final GameProfile[] EMPTY_PROFILES = new GameProfile[0]; -+ private static final UUID FAKE_UUID = new UUID(0, 0); -+ -+ private GameProfile[] originalSample; -+ -+ private StandardPaperServerListPingEventImpl(MinecraftServer server, Connection networkManager, ServerStatus ping) { -+ super(server, new PaperStatusClient(networkManager), ping.getVersion() != null ? ping.getVersion().getProtocol() : -1, server.server.getServerIcon()); -+ this.originalSample = ping.getPlayers() == null ? null : ping.getPlayers().getSample(); // GH-1473 - pre-tick race condition NPE -+ } -+ -+ @Nonnull -+ @Override -+ public List getPlayerSample() { -+ List sample = super.getPlayerSample(); -+ -+ if (this.originalSample != null) { -+ for (GameProfile profile : this.originalSample) { -+ sample.add(CraftPlayerProfile.asBukkitCopy(profile)); -+ } -+ this.originalSample = null; -+ } -+ -+ return sample; -+ } -+ -+ private GameProfile[] getPlayerSampleHandle() { -+ if (this.originalSample != null) { -+ return this.originalSample; -+ } -+ -+ List entries = super.getPlayerSample(); -+ if (entries.isEmpty()) { -+ return EMPTY_PROFILES; -+ } -+ -+ GameProfile[] profiles = new GameProfile[entries.size()]; -+ for (int i = 0; i < profiles.length; i++) { -+ /* -+ * Avoid null UUIDs/names since that will make the response invalid -+ * on the client. -+ * Instead, fall back to a fake/empty UUID and an empty string as name. -+ * This can be used to create custom lines in the player list that do not -+ * refer to a specific player. -+ */ -+ -+ PlayerProfile profile = entries.get(i); -+ if (profile.getId() != null && profile.getName() != null) { -+ profiles[i] = CraftPlayerProfile.asAuthlib(profile); -+ } else { -+ profiles[i] = new GameProfile(MoreObjects.firstNonNull(profile.getId(), FAKE_UUID), Strings.nullToEmpty(profile.getName())); -+ } -+ } -+ -+ return profiles; -+ } -+ -+ @SuppressWarnings("deprecation") -+ public static void processRequest(MinecraftServer server, Connection networkManager) { -+ StandardPaperServerListPingEventImpl event = new StandardPaperServerListPingEventImpl(server, networkManager, server.getStatus()); -+ server.server.getPluginManager().callEvent(event); -+ -+ // Close connection immediately if event is cancelled -+ if (event.isCancelled()) { -+ networkManager.disconnect(null); -+ return; -+ } -+ -+ // Setup response -+ ServerStatus ping = new ServerStatus(); -+ -+ // Description -+ ping.setDescription(new AdventureComponent(event.motd())); -+ -+ // Players -+ if (!event.shouldHidePlayers()) { -+ ping.setPlayers(new ServerStatus.Players(event.getMaxPlayers(), event.getNumPlayers())); -+ ping.getPlayers().setSample(event.getPlayerSampleHandle()); -+ } -+ -+ // Version -+ ping.setVersion(new ServerStatus.Version(event.getVersion(), event.getProtocolVersion())); -+ -+ // Favicon -+ if (event.getServerIcon() != null) { -+ ping.setFavicon(event.getServerIcon().getData()); -+ } -+ -+ // Send response -+ networkManager.send(new ClientboundStatusResponsePacket(ping)); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java -index b985d238eadf857602636ba5e5c277d4b1992d35..5b2081f920304244df96de78b2c66cf8a49a5b85 100644 ---- a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java -+++ b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java -@@ -2,6 +2,7 @@ package net.minecraft.network.protocol.status; - - import com.google.gson.Gson; - import com.google.gson.GsonBuilder; -+import io.papermc.paper.adventure.AdventureComponent; // Paper - import java.io.IOException; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.chat.Component; -@@ -12,7 +13,9 @@ import net.minecraft.util.LowerCaseEnumTypeAdapterFactory; - - public class ClientboundStatusResponsePacket implements Packet { - -- private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()).create(); -+ private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()) -+ .registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()) -+ .create(); - private ServerStatus status; - - public ClientboundStatusResponsePacket() {} -diff --git a/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java b/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java -index d6be3dd6cfed3f65325398fc33663cb251f87ac7..31d45cd635eae2ff406cb0441f2cd2aee833b945 100644 ---- a/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java -+++ b/src/main/java/net/minecraft/network/protocol/status/ServerStatus.java -@@ -31,6 +31,7 @@ public class ServerStatus { - this.description = description; - } - -+ public Players getPlayers() { return getPlayers(); } // Paper - OBFHELPER - public ServerStatus.Players getPlayers() { - return this.players; - } -@@ -162,10 +163,12 @@ public class ServerStatus { - return this.numPlayers; - } - -+ public GameProfile[] getSample() { return getSample(); } // Paper - OBFHELPER - public GameProfile[] getSample() { - return this.sample; - } - -+ public void setSample(GameProfile[] sample) { setSample(sample); } // Paper - OBFHELPER - public void setSample(GameProfile[] sample) { - this.sample = sample; - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 4b3341877629c7065496fb0f0b4d509f5a48db6d..d34da1eb172a7dcda564680afecf3dc145bf09f3 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2,6 +2,9 @@ package net.minecraft.server; - - import com.google.common.base.Splitter; - import com.google.common.collect.ImmutableList; -+import co.aikar.timings.Timings; -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+import com.google.common.base.Stopwatch; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -1238,7 +1241,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= 5000000000L) { - this.lastServerStatus = i; - this.status.setPlayers(new ServerStatus.Players(this.getMaxPlayers(), this.getPlayerCount())); -- GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), 12)]; -+ GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), org.spigotmc.SpigotConfig.playerSample)]; // Paper - int j = Mth.nextInt(this.random, 0, this.getPlayerCount() - agameprofile.length); - - for (int k = 0; k < agameprofile.length; ++k) { -diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java -index 223df8d27c2ff1cbff634bca3dbde5cc24de7f98..f74e3cbdff8c2d83809f04f42717501d7b1a1ed2 100644 ---- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java -@@ -1,7 +1,7 @@ - package net.minecraft.server.network; - - import net.minecraft.server.MinecraftServer; --import net.minecraft.server.level.ServerPlayer; -+ - // CraftBukkit start - import com.mojang.authlib.GameProfile; - import java.net.InetSocketAddress; -@@ -11,8 +11,6 @@ import net.minecraft.network.Connection; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; --import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; --import net.minecraft.network.protocol.status.ServerStatus; - import net.minecraft.network.protocol.status.ServerStatusPacketListener; - import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; - import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; -@@ -47,15 +45,17 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene - this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON); - } else { - this.hasRequestedStatus = true; -+ // Paper start - Replace everything -+ /* - // CraftBukkit start - // this.networkManager.sendPacket(new PacketStatusOutServerInfo(this.minecraftServer.getServerPing())); -- final Object[] players = server.getPlayerList().players.toArray(); -+ final Object[] players = minecraftServer.getPlayerList().players.toArray(); - class ServerListPingEvent extends org.bukkit.event.server.ServerListPingEvent { - -- CraftIconCache icon = server.server.getServerIcon(); -+ CraftIconCache icon = minecraftServer.server.getServerIcon(); - - ServerListPingEvent() { -- super(((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.server.motd(), server.getPlayerList().getMaxPlayers()); // Paper - Adventure -+ super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.server.motd(), minecraftServer.getPlayerList().getMaxPlayers()); // Paper - Adventure - } - - @Override -@@ -71,7 +71,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene - return new Iterator() { - int i; - int ret = Integer.MIN_VALUE; -- ServerPlayer player; -+ EntityPlayer player; - - @Override - public boolean hasNext() { -@@ -80,7 +80,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene - } - final Object[] currentPlayers = players; - for (int length = currentPlayers.length, i = this.i; i < length; i++) { -- final ServerPlayer player = (ServerPlayer) currentPlayers[i]; -+ final EntityPlayer player = (EntityPlayer) currentPlayers[i]; - if (player != null) { - this.i = i + 1; - this.player = player; -@@ -95,7 +95,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene - if (!hasNext()) { - throw new java.util.NoSuchElementException(); - } -- final ServerPlayer player = this.player; -+ final EntityPlayer player = this.player; - this.player = null; - this.ret = this.i - 1; - return player.getBukkitEntity(); -@@ -115,16 +115,16 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene - } - - ServerListPingEvent event = new ServerListPingEvent(); -- this.server.server.getPluginManager().callEvent(event); -+ this.minecraftServer.server.getPluginManager().callEvent(event); - - java.util.List profiles = new java.util.ArrayList(players.length); - for (Object player : players) { - if (player != null) { -- profiles.add(((ServerPlayer) player).getGameProfile()); -+ profiles.add(((EntityPlayer) player).getProfile()); - } - } - -- ServerStatus.Players playerSample = new ServerStatus.Players(event.getMaxPlayers(), profiles.size()); -+ ServerPing.ServerPingPlayerSample playerSample = new ServerPing.ServerPingPlayerSample(event.getMaxPlayers(), profiles.size()); - // Spigot Start - if ( !profiles.isEmpty() ) - { -@@ -132,16 +132,19 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene - profiles = profiles.subList( 0, Math.min( profiles.size(), org.spigotmc.SpigotConfig.playerSample ) ); // Cap the sample to n (or less) displayed players, ie: Vanilla behaviour - } - // Spigot End -- playerSample.setSample(profiles.toArray(new GameProfile[profiles.size()])); -+ playerSample.a(profiles.toArray(new GameProfile[profiles.size()])); - -- ServerStatus ping = new ServerStatus(); -+ ServerPing ping = new ServerPing(); - ping.setFavicon(event.icon.value); -- ping.setDescription(CraftChatMessage.fromString(event.getMotd(), true)[0]); -- ping.setPlayers(playerSample); -- int version = SharedConstants.getCurrentVersion().getProtocolVersion(); -- ping.setVersion(new ServerStatus.Version(server.getServerModName() + " " + server.getServerVersion(), version)); -- -- this.connection.send(new ClientboundStatusResponsePacket(ping)); -+ ping.setMOTD(CraftChatMessage.fromString(event.getMotd(), true)[0]); -+ ping.setPlayerSample(playerSample); -+ int version = SharedConstants.getGameVersion().getProtocolVersion(); -+ ping.setServerInfo(new ServerPing.ServerData(minecraftServer.getServerModName() + " " + minecraftServer.getVersion(), version)); -+ -+ this.networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); -+ */ -+ com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.server, this.connection); -+ // Paper end - } - // CraftBukkit end - } -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 3981ba5957fdc2929d54515f2b98bb7a4611e938..652b820a4c0bbf7b6bbb8200927a663665583606 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -289,7 +289,7 @@ public class SpigotConfig - public static int playerSample; - private static void playerSample() - { -- playerSample = getInt( "settings.sample-count", 12 ); -+ playerSample = Math.max( getInt( "settings.sample-count", 12 ), 0 ); // Paper - Avoid negative counts - Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger - } - diff --git a/Remapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch b/Remapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch deleted file mode 100644 index b0ae823221..0000000000 --- a/Remapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch +++ /dev/null @@ -1,370 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 16 Mar 2018 22:59:43 -0400 -Subject: [PATCH] Improved Async Task Scheduler - -The Craft Scheduler still uses the primary thread for task scheduling. -This results in the main thread still having to do work as part of the -dispatching of async tasks. - -If plugins make use of lots of async tasks, such as particle emitters -that want to keep the logic off the main thread, the main thread still -receives quite a bit of load from processing all of these queued tasks. - -Additionally, resizing and managing the pending entries for all of -these asynchronous tasks takes up time on the main thread too. - -This commit replaces the implementation of the scheduler when working -with asynchronous tasks, by forwarding calls to the new scheduler. - -The Async Scheduler uses a single thread executor for "management" tasks. -The Management Thread is responsible for all adding and dispatching of -scheduled tasks. - -The mainThreadHeartbeat will send a heartbeat task to the management thread -with the currentTick value, so that it can find which tasks to execute. - -Scheduling of an async tasks also dispatches a management task, ensuring -that any Queue resizing operation occurs off of the main thread. - -The async queue uses a complete separate PriorityQueue, ensuring that resize -operations are decoupled from the sync tasks queue. - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3c1992e212a6d6f1db4d5b807b38d71913619fc0 ---- /dev/null -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java -@@ -0,0 +1,122 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+package org.bukkit.craftbukkit.scheduler; -+ -+import com.destroystokyo.paper.ServerSchedulerReportingWrapper; -+import com.google.common.util.concurrent.ThreadFactoryBuilder; -+import org.bukkit.plugin.Plugin; -+ -+import java.util.ArrayList; -+import java.util.Iterator; -+import java.util.List; -+import java.util.concurrent.Executor; -+import java.util.concurrent.Executors; -+import java.util.concurrent.SynchronousQueue; -+import java.util.concurrent.ThreadPoolExecutor; -+import java.util.concurrent.TimeUnit; -+ -+public class CraftAsyncScheduler extends CraftScheduler { -+ -+ private final ThreadPoolExecutor executor = new ThreadPoolExecutor( -+ 4, Integer.MAX_VALUE,30L, TimeUnit.SECONDS, new SynchronousQueue<>(), -+ new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").build()); -+ private final Executor management = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder() -+ .setNameFormat("Craft Async Scheduler Management Thread").build()); -+ private final List temp = new ArrayList<>(); -+ -+ CraftAsyncScheduler() { -+ super(true); -+ executor.allowCoreThreadTimeOut(true); -+ executor.prestartAllCoreThreads(); -+ } -+ -+ @Override -+ public void cancelTask(int taskId) { -+ this.management.execute(() -> this.removeTask(taskId)); -+ } -+ -+ private synchronized void removeTask(int taskId) { -+ parsePending(); -+ this.pending.removeIf((task) -> { -+ if (task.getTaskId() == taskId) { -+ task.cancel0(); -+ return true; -+ } -+ return false; -+ }); -+ } -+ -+ @Override -+ public void mainThreadHeartbeat(int currentTick) { -+ this.currentTick = currentTick; -+ this.management.execute(() -> this.runTasks(currentTick)); -+ } -+ -+ private synchronized void runTasks(int currentTick) { -+ parsePending(); -+ while (!this.pending.isEmpty() && this.pending.peek().getNextRun() <= currentTick) { -+ CraftTask task = this.pending.remove(); -+ if (executeTask(task)) { -+ final long period = task.getPeriod(); -+ if (period > 0) { -+ task.setNextRun(currentTick + period); -+ temp.add(task); -+ } -+ } -+ parsePending(); -+ } -+ this.pending.addAll(temp); -+ temp.clear(); -+ } -+ -+ private boolean executeTask(CraftTask task) { -+ if (isValid(task)) { -+ this.runners.put(task.getTaskId(), task); -+ this.executor.execute(new ServerSchedulerReportingWrapper(task)); -+ return true; -+ } -+ return false; -+ } -+ -+ @Override -+ public synchronized void cancelTasks(Plugin plugin) { -+ parsePending(); -+ for (Iterator iterator = this.pending.iterator(); iterator.hasNext(); ) { -+ CraftTask task = iterator.next(); -+ if (task.getTaskId() != -1 && (plugin == null || task.getOwner().equals(plugin))) { -+ task.cancel0(); -+ iterator.remove(); -+ } -+ } -+ } -+ -+ /** -+ * Task is not cancelled -+ * @param runningTask -+ * @return -+ */ -+ static boolean isValid(CraftTask runningTask) { -+ return runningTask.getPeriod() >= CraftTask.NO_REPEATING; -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483ca3c7c2a8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -63,7 +63,7 @@ public class CraftScheduler implements BukkitScheduler { - /** - * Main thread logic only - */ -- private final PriorityQueue pending = new PriorityQueue(10, -+ final PriorityQueue pending = new PriorityQueue(10, // Paper - new Comparator() { - @Override - public int compare(final CraftTask o1, final CraftTask o2) { -@@ -80,12 +80,13 @@ public class CraftScheduler implements BukkitScheduler { - /** - * These are tasks that are currently active. It's provided for 'viewing' the current state. - */ -- private final ConcurrentHashMap runners = new ConcurrentHashMap(); -+ final ConcurrentHashMap runners = new ConcurrentHashMap(); // Paper - /** - * The sync task that is currently running on the main thread. - */ - private volatile CraftTask currentTask = null; -- private volatile int currentTick = -1; -+ // Paper start - Improved Async Task Scheduler -+ volatile int currentTick = -1;/* - private final Executor executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %d").build()); - private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) { - @Override -@@ -94,12 +95,31 @@ public class CraftScheduler implements BukkitScheduler { - } - }; - private CraftAsyncDebugger debugTail = debugHead; -+ -+ */ // Paper end - private static final int RECENT_TICKS; - - static { - RECENT_TICKS = 30; - } - -+ -+ // Paper start -+ private final CraftScheduler asyncScheduler; -+ private final boolean isAsyncScheduler; -+ public CraftScheduler() { -+ this(false); -+ } -+ -+ public CraftScheduler(boolean isAsync) { -+ this.isAsyncScheduler = isAsync; -+ if (isAsync) { -+ this.asyncScheduler = this; -+ } else { -+ this.asyncScheduler = new CraftAsyncScheduler(); -+ } -+ } -+ // Paper end - @Override - public int scheduleSyncDelayedTask(final Plugin plugin, final Runnable task) { - return this.scheduleSyncDelayedTask(plugin, task, 0L); -@@ -222,7 +242,7 @@ public class CraftScheduler implements BukkitScheduler { - } else if (period < CraftTask.NO_REPEATING) { - period = CraftTask.NO_REPEATING; - } -- return handle(new CraftAsyncTask(runners, plugin, runnable, nextId(), period), delay); -+ return handle(new CraftAsyncTask(this.asyncScheduler.runners, plugin, runnable, nextId(), period), delay); // Paper - } - - @Override -@@ -238,6 +258,11 @@ public class CraftScheduler implements BukkitScheduler { - if (taskId <= 0) { - return; - } -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ this.asyncScheduler.cancelTask(taskId); -+ } -+ // Paper end - CraftTask task = runners.get(taskId); - if (task != null) { - task.cancel0(); -@@ -280,6 +305,11 @@ public class CraftScheduler implements BukkitScheduler { - @Override - public void cancelTasks(final Plugin plugin) { - Validate.notNull(plugin, "Cannot cancel tasks of null plugin"); -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ this.asyncScheduler.cancelTasks(plugin); -+ } -+ // Paper end - final CraftTask task = new CraftTask( - new Runnable() { - @Override -@@ -319,6 +349,13 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public boolean isCurrentlyRunning(final int taskId) { -+ // Paper start -+ if (!isAsyncScheduler) { -+ if (this.asyncScheduler.isCurrentlyRunning(taskId)) { -+ return true; -+ } -+ } -+ // Paper end - final CraftTask task = runners.get(taskId); - if (task == null) { - return false; -@@ -337,6 +374,11 @@ public class CraftScheduler implements BukkitScheduler { - if (taskId <= 0) { - return false; - } -+ // Paper start -+ if (!this.isAsyncScheduler && this.asyncScheduler.isQueued(taskId)) { -+ return true; -+ } -+ // Paper end - for (CraftTask task = head.getNext(); task != null; task = task.getNext()) { - if (task.getTaskId() == taskId) { - return task.getPeriod() >= CraftTask.NO_REPEATING; // The task will run -@@ -348,6 +390,12 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public List getActiveWorkers() { -+ // Paper start -+ if (!isAsyncScheduler) { -+ //noinspection TailRecursion -+ return this.asyncScheduler.getActiveWorkers(); -+ } -+ // Paper end - final ArrayList workers = new ArrayList(); - for (final CraftTask taskObj : runners.values()) { - // Iterator will be a best-effort (may fail to grab very new values) if called from an async thread -@@ -385,6 +433,11 @@ public class CraftScheduler implements BukkitScheduler { - pending.add(task); - } - } -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ pending.addAll(this.asyncScheduler.getPendingTasks()); -+ } -+ // Paper end - return pending; - } - -@@ -392,6 +445,11 @@ public class CraftScheduler implements BukkitScheduler { - * This method is designed to never block or wait for locks; an immediate execution of all current tasks. - */ - public void mainThreadHeartbeat(final int currentTick) { -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ this.asyncScheduler.mainThreadHeartbeat(currentTick); -+ } -+ // Paper end - this.currentTick = currentTick; - final List temp = this.temp; - parsePending(); -@@ -431,7 +489,7 @@ public class CraftScheduler implements BukkitScheduler { - parsePending(); - } else { - //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper -- executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper -+ task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Paper"); // Paper - // We don't need to parse pending - // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) - } -@@ -450,7 +508,7 @@ public class CraftScheduler implements BukkitScheduler { - //debugHead = debugHead.getNextHead(currentTick); // Paper - } - -- private void addTask(final CraftTask task) { -+ protected void addTask(final CraftTask task) { - final AtomicReference tail = this.tail; - CraftTask tailTask = tail.get(); - while (!tail.compareAndSet(tailTask, task)) { -@@ -459,7 +517,13 @@ public class CraftScheduler implements BukkitScheduler { - tailTask.setNext(task); - } - -- private CraftTask handle(final CraftTask task, final long delay) { -+ protected CraftTask handle(final CraftTask task, final long delay) { // Paper -+ // Paper start -+ if (!this.isAsyncScheduler && !task.isSync()) { -+ this.asyncScheduler.handle(task, delay); -+ return task; -+ } -+ // Paper end - task.setNextRun(currentTick + delay); - addTask(task); - return task; -@@ -478,8 +542,8 @@ public class CraftScheduler implements BukkitScheduler { - return ids.incrementAndGet(); - } - -- private void parsePending() { -- MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); -+ void parsePending() { // Paper -+ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); // Paper - CraftTask head = this.head; - CraftTask task = head.getNext(); - CraftTask lastTask = head; -@@ -498,7 +562,7 @@ public class CraftScheduler implements BukkitScheduler { - task.setNext(null); - } - this.head = lastTask; -- MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); -+ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); // Paper - } - - private boolean isReady(final int currentTick) { diff --git a/Remapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/Remapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch deleted file mode 100644 index f400637138..0000000000 --- a/Remapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 18 Mar 2018 11:45:57 -0400 -Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent - -This will allow you to change the players name or skin on login. - -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index ff83fb15d0d0adb62c630fc7aafc134972bf15fc..e5be45ac86907c1f8cc154bd38fd624a2320180f 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -1,5 +1,7 @@ - package net.minecraft.server.network; - -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import com.mojang.authlib.GameProfile; - import com.mojang.authlib.exceptions.AuthenticationUnavailableException; - import java.math.BigInteger; -@@ -36,6 +38,7 @@ import org.apache.commons.lang3.Validate; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - import io.papermc.paper.adventure.PaperAdventure; // Paper -+import org.bukkit.Bukkit; - import org.bukkit.craftbukkit.util.Waitable; - import org.bukkit.event.player.AsyncPlayerPreLoginEvent; - import org.bukkit.event.player.PlayerPreLoginEvent; -@@ -314,8 +317,16 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - java.util.UUID uniqueId = gameProfile.getId(); - final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; - -- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); -+ // Paper start -+ PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); -+ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); - server.getPluginManager().callEvent(asyncEvent); -+ profile = asyncEvent.getPlayerProfile(); -+ profile.complete(); -+ gameProfile = CraftPlayerProfile.asAuthlibCopy(profile); -+ playerName = gameProfile.getName(); -+ uniqueId = gameProfile.getId(); -+ // Paper end - - if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { - final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); diff --git a/Remapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch b/Remapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch deleted file mode 100644 index f35f170d57..0000000000 --- a/Remapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 18 Mar 2018 12:29:48 -0400 -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/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index e5be45ac86907c1f8cc154bd38fd624a2320180f..0aa3a154d68f00edcc09b947a24b2b59b1e135e6 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -54,7 +54,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - public final Connection connection; - private ServerLoginPacketListenerImpl.State state; - private int tick; -- private GameProfile gameProfile; -+ private GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } private GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER - private final String serverId; - private SecretKey secretKey; - private ServerPlayer delayedAcceptPlayer; -@@ -318,12 +318,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; - - // Paper start -- PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); -+ PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); - AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); - server.getPluginManager().callEvent(asyncEvent); - profile = asyncEvent.getPlayerProfile(); -- profile.complete(); -- gameProfile = CraftPlayerProfile.asAuthlibCopy(profile); -+ profile.complete(true); -+ setGameProfile(CraftPlayerProfile.asAuthlib(profile)); - playerName = gameProfile.getName(); - uniqueId = gameProfile.getId(); - // Paper end -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 63871a3a1981b2e8c7ad74214196e35684acb584..c4aa824d03de952fe6b306e539baa47af979add1 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -159,7 +159,7 @@ public abstract class Player extends LivingEntity { - protected int enchantmentSeed; - protected final float defaultFlySpeed = 0.02F; - private int lastLevelUpTime; -- private final GameProfile gameProfile; -+ private GameProfile gameProfile; public final void setProfile(final GameProfile profile) { this.gameProfile = profile; } // Paper - OBFHELPER - private ItemStack lastItemInMainHand; - private final ItemCooldowns cooldowns; - @Nullable -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index efdcb8dac8db15c4bbaed84a7861ce98339e516a..9d853733ff9054cc48925e22c8bb3c8d9b898808 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -67,6 +67,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu; - import net.minecraft.world.item.enchantment.EnchantmentHelper; - import net.minecraft.world.item.enchantment.Enchantments; - import net.minecraft.world.level.GameType; -+import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.entity.SignBlockEntity; - import net.minecraft.world.level.saveddata.maps.MapDecoration; - import net.minecraft.world.phys.Vec3; -@@ -1307,8 +1308,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - hiddenPlayers.put(player.getUniqueId(), hidingPlugins); - - // Remove this player from the hidden player's EntityTrackerEntry -- ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; -+ // Paper start - ServerPlayer other = ((CraftPlayer) player).getHandle(); -+ unregisterPlayer(other); -+ } -+ private void unregisterPlayer(ServerPlayer other) { -+ ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; -+ // Paper end - ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId()); - if (entry != null) { - entry.removePlayer(getHandle()); -@@ -1349,8 +1355,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - hiddenPlayers.remove(player.getUniqueId()); - -- ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; -+ // Paper start - ServerPlayer other = ((CraftPlayer) player).getHandle(); -+ registerPlayer(other); -+ } -+ private void registerPlayer(ServerPlayer other) { -+ ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; -+ // Paper end - - getHandle().connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, other)); - -@@ -1359,6 +1370,50 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - entry.updatePlayer(getHandle()); - } - } -+ // Paper start -+ private void reregisterPlayer(ServerPlayer player) { -+ if (!hiddenPlayers.containsKey(player.getUUID())) { -+ unregisterPlayer(player); -+ registerPlayer(player); -+ } -+ } -+ public void setPlayerProfile(com.destroystokyo.paper.profile.PlayerProfile profile) { -+ ServerPlayer self = getHandle(); -+ self.setProfile(com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile)); -+ if (!self.sentListPacket) { -+ return; -+ } -+ List players = server.getServer().getPlayerList().players; -+ for (ServerPlayer player : players) { -+ player.getBukkitEntity().reregisterPlayer(self); -+ } -+ refreshPlayer(); -+ } -+ public com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile() { -+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(this).clone(); -+ } -+ -+ private void refreshPlayer() { -+ ServerPlayer handle = getHandle(); -+ -+ Location loc = getLocation(); -+ -+ ServerGamePacketListenerImpl connection = handle.connection; -+ reregisterPlayer(handle); -+ -+ //Respawn the player then update their position and selected slot -+ ServerLevel worldserver = handle.getLevel(); -+ connection.send(new net.minecraft.network.protocol.game.ClientboundRespawnPacket(worldserver.dimensionType(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), handle.gameMode.getGameModeForPlayer(), handle.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), true)); -+ handle.onUpdateAbilities(); -+ connection.send(new net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), new HashSet<>(), 0)); -+ net.minecraft.server.MinecraftServer.getServer().getPlayerList().sendAllPlayerInfo(handle); -+ -+ if (this.isOp()) { -+ this.setOp(false); -+ this.setOp(true); -+ } -+ } -+ // Paper end - - public void removeDisconnectingPlayer(Player player) { - hiddenPlayers.remove(player.getUniqueId()); diff --git a/Remapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch b/Remapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch deleted file mode 100644 index 334aa02f71..0000000000 --- a/Remapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Mar 2018 20:52:07 -0400 -Subject: [PATCH] Fix Dragon Server Crashes - -If the dragon tries to find "ground" and hits a hole, or off edge, -it will infinitely keep looking for non air and eventually crash. - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java -index 5e701b02e464889fe433b08018d13e63b24506eb..0c2a5f5c4d7d7516793eba20205b5703fe1450d5 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java -@@ -63,7 +63,7 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { - double d3 = d2; - BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(d0, d2, d1); - -- while (this.dragon.level.isEmptyBlock(blockposition_mutableblockposition)) { -+ while (this.dragon.level.isEmptyBlock(blockposition_mutableblockposition ) && d2 > 0) { // Paper - --d3; - if (d3 < 0.0D) { - d3 = d2; diff --git a/Remapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch b/Remapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch deleted file mode 100644 index 64d63b916e..0000000000 --- a/Remapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 22 Mar 2018 01:40:24 -0400 -Subject: [PATCH] getPlayerUniqueId API - -Gets the unique ID of the player currently known as the specified player name -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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 10addb128a357e7719854bf4f9d75f5def32b27d..20915e40fbcf28faed603d449a99bf2157fcf972 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1517,6 +1517,25 @@ public final class CraftServer implements Server { - return recipients.size(); - } - -+ // Paper start -+ @Nullable -+ public UUID getPlayerUniqueId(String name) { -+ Player player = Bukkit.getPlayerExact(name); -+ if (player != null) { -+ return player.getUniqueId(); -+ } -+ GameProfile profile; -+ // Only fetch an online UUID in online mode -+ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) { -+ profile = console.getProfileCache().get( name ); -+ } else { -+ // Make an OfflinePlayer using an offline mode UUID since the name has no profile -+ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); -+ } -+ return profile != null ? profile.getId() : null; -+ } -+ // Paper end -+ - @Override - @Deprecated - public OfflinePlayer getOfflinePlayer(String name) { diff --git a/Remapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch b/Remapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch deleted file mode 100644 index 7a7b4d1993..0000000000 --- a/Remapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Mon, 26 Mar 2018 18:30:53 +0300 -Subject: [PATCH] Make player data saving configurable - -Upstream has added a patch which negates the need for this patch, -however, we should still migrate our configuration back upstream, -to prevent unexpected situations - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 52954fc3bf932cfc9d5ce63e3d3cace351305790..05a5abb951abe37f30a719cb75376d2d43c0d252 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -279,4 +279,13 @@ public class PaperConfig { - private static void authenticationServersDownKickMessage() { - authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); - } -+ -+ private static void savePlayerData() { -+ Object val = config.get("settings.save-player-data"); -+ if (val instanceof Boolean) { -+ SpigotConfig.disablePlayerDataSaving = !(Boolean) val; -+ SpigotConfig.config.set("players.disable-saving", SpigotConfig.disableAdvancementSaving); -+ SpigotConfig.save(); -+ } -+ } - } diff --git a/Remapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch b/Remapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch deleted file mode 100644 index 72dfa9fd8e..0000000000 --- a/Remapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 18:22:50 +0200 -Subject: [PATCH] Make legacy ping handler more reliable - -The Minecraft server often fails to respond to old ("legacy") pings -from old Minecraft versions using the protocol used before the switch -to Netty in Minecraft 1.7. - -Due to packet fragmentation[1], we might not have all needed bytes -available when the LegacyPingHandler is called. In this case, it will -run into an error, remove the handler and continue using the modern -protocol. - -This is unlikely to happen for the first two revisions of the legacy -ping protocol (used in Minecraft 1.5.x and older) since the request -consists of only one or two bytes, but happens frequently for the -last/third revision introduced in Minecraft 1.6. - -It has much larger, variable packet sizes due to the inclusion of -the virtual host (the hostname/port used to connect to the server). - -The solution[2] is simple: If we find more than two matching bytes, -we buffer the remaining bytes until we have enough to fully read and -respond to the request. - -[1]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h3-11 -[2]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h4-13 - -diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java -index e2867a3de87a778a897b4963212fa4aab566a643..1d11802876c1a94ecf991cd8249bd6a911c0ac20 100644 ---- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java -+++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java -@@ -15,6 +15,7 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { - - private static final Logger LOGGER = LogManager.getLogger(); - private final ServerConnectionListener serverConnectionListener; -+ private ByteBuf buf; // Paper - - public LegacyQueryHandler(ServerConnectionListener networkIo) { - this.serverConnectionListener = networkIo; -@@ -23,6 +24,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { - public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) throws Exception { - ByteBuf bytebuf = (ByteBuf) object; - -+ // Paper start - Make legacy ping handler more reliable -+ if (this.buf != null) { -+ try { -+ readLegacy1_6(channelhandlercontext, bytebuf); -+ } finally { -+ bytebuf.release(); -+ } -+ return; -+ } -+ // Paper end - bytebuf.markReaderIndex(); - boolean flag = true; - -@@ -53,6 +64,10 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { - this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); - break; - default: -+ // Paper start - Replace with improved version below -+ if (bytebuf.readUnsignedByte() != 0x01 || bytebuf.readUnsignedByte() != 0xFA) return; -+ readLegacy1_6(channelhandlercontext, bytebuf); -+ /* - boolean flag1 = bytebuf.readUnsignedByte() == 1; - - flag1 &= bytebuf.readUnsignedByte() == 250; -@@ -67,15 +82,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { - return; - } - -- LegacyQueryHandler.LOGGER.debug("Ping: (1.6) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); -- String s1 = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit -- ByteBuf bytebuf1 = this.createReply(s1); -+ LegacyPingHandler.LOGGER.debug("Ping: (1.6) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); -+ String s1 = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit -+ ByteBuf bytebuf1 = this.a(s1); - - try { -- this.sendFlushAndClose(channelhandlercontext, bytebuf1); -+ this.a(channelhandlercontext, bytebuf1); - } finally { - bytebuf1.release(); - } -+ */ // Paper end - Replace with improved version below - } - - bytebuf.release(); -@@ -93,6 +109,90 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { - - } - -+ // Paper start -+ private static String readLegacyString(ByteBuf buf) { -+ int size = buf.readShort() * Character.BYTES; -+ if (!buf.isReadable(size)) { -+ return null; -+ } -+ -+ String result = buf.toString(buf.readerIndex(), size, StandardCharsets.UTF_16BE); -+ buf.skipBytes(size); // toString doesn't increase readerIndex automatically -+ return result; -+ } -+ -+ private void readLegacy1_6(ChannelHandlerContext ctx, ByteBuf part) { -+ ByteBuf buf = this.buf; -+ -+ if (buf == null) { -+ this.buf = buf = ctx.alloc().buffer(); -+ buf.markReaderIndex(); -+ } else { -+ buf.resetReaderIndex(); -+ } -+ -+ buf.writeBytes(part); -+ -+ if (!buf.isReadable(Short.BYTES + Short.BYTES + Byte.BYTES + Short.BYTES + Integer.BYTES)) { -+ return; -+ } -+ -+ String s = readLegacyString(buf); -+ if (s == null) { -+ return; -+ } -+ -+ if (!s.equals("MC|PingHost")) { -+ removeHandler(ctx); -+ return; -+ } -+ -+ if (!buf.isReadable(Short.BYTES) || !buf.isReadable(buf.readShort())) { -+ return; -+ } -+ -+ MinecraftServer server = this.serverConnectionListener.getServer(); -+ int protocolVersion = buf.readByte(); -+ String host = readLegacyString(buf); -+ if (host == null) { -+ removeHandler(ctx); -+ return; -+ } -+ int port = buf.readInt(); -+ -+ if (buf.isReadable()) { -+ removeHandler(ctx); -+ return; -+ } -+ -+ buf.release(); -+ this.buf = null; -+ -+ LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); -+ -+ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", -+ Byte.MAX_VALUE, server.getServerVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); -+ this.sendFlushAndClose(ctx, this.createReply(response)); -+ } -+ -+ private void removeHandler(ChannelHandlerContext ctx) { -+ ByteBuf buf = this.buf; -+ this.buf = null; -+ -+ buf.resetReaderIndex(); -+ ctx.pipeline().remove(this); -+ ctx.fireChannelRead(buf); -+ } -+ -+ @Override -+ public void handlerRemoved(ChannelHandlerContext ctx) { -+ if (this.buf != null) { -+ this.buf.release(); -+ this.buf = null; -+ } -+ } -+ // Paper end -+ - private void sendFlushAndClose(ChannelHandlerContext ctx, ByteBuf buf) { - ctx.pipeline().firstContext().writeAndFlush(buf).addListener(ChannelFutureListener.CLOSE); - } diff --git a/Remapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch b/Remapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch deleted file mode 100644 index 90d915afd6..0000000000 --- a/Remapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch +++ /dev/null @@ -1,154 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 19:30:51 +0200 -Subject: [PATCH] Call PaperServerListPingEvent for legacy pings - - -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..74c012fd40491f1d870fbc1aa8c318a2197eb106 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java -@@ -0,0 +1,73 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+import net.minecraft.server.MinecraftServer; -+import org.apache.commons.lang3.StringUtils; -+import org.bukkit.ChatColor; -+ -+import java.net.InetSocketAddress; -+ -+import javax.annotation.Nullable; -+ -+public final class PaperLegacyStatusClient implements StatusClient { -+ -+ private final InetSocketAddress address; -+ private final int protocolVersion; -+ @Nullable private final InetSocketAddress virtualHost; -+ -+ private PaperLegacyStatusClient(InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { -+ this.address = address; -+ this.protocolVersion = protocolVersion; -+ this.virtualHost = virtualHost; -+ } -+ -+ @Override -+ public InetSocketAddress getAddress() { -+ return this.address; -+ } -+ -+ @Override -+ public int getProtocolVersion() { -+ return this.protocolVersion; -+ } -+ -+ @Nullable -+ @Override -+ public InetSocketAddress getVirtualHost() { -+ return this.virtualHost; -+ } -+ -+ @Override -+ public boolean isLegacy() { -+ return true; -+ } -+ -+ public static PaperServerListPingEvent processRequest(MinecraftServer server, -+ InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { -+ -+ PaperServerListPingEvent event = new PaperServerListPingEventImpl(server, -+ new PaperLegacyStatusClient(address, protocolVersion, virtualHost), Byte.MAX_VALUE, null); -+ server.server.getPluginManager().callEvent(event); -+ -+ if (event.isCancelled()) { -+ return null; -+ } -+ -+ return event; -+ } -+ -+ public static String getMotd(PaperServerListPingEvent event) { -+ return getFirstLine(event.getMotd()); -+ } -+ -+ public static String getUnformattedMotd(PaperServerListPingEvent event) { -+ // Strip color codes and all other occurrences of the color char (because it's used as delimiter) -+ return getFirstLine(StringUtils.remove(ChatColor.stripColor(event.getMotd()), ChatColor.COLOR_CHAR)); -+ } -+ -+ private static String getFirstLine(String s) { -+ int pos = s.indexOf('\n'); -+ return pos >= 0 ? s.substring(0, pos) : s; -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java -index 1d11802876c1a94ecf991cd8249bd6a911c0ac20..dfe2cd46f2432dca2028b7436c4108e3f190787f 100644 ---- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java -+++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java -@@ -1,5 +1,7 @@ - package net.minecraft.server.network; - -+import com.destroystokyo.paper.network.PaperLegacyStatusClient; -+ - import io.netty.buffer.ByteBuf; - import io.netty.buffer.Unpooled; - import io.netty.channel.ChannelFutureListener; -@@ -46,12 +48,19 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { - MinecraftServer minecraftserver = this.serverConnectionListener.getServer(); - int i = bytebuf.readableBytes(); - String s; -- org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit -+ //org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit // Paper -+ com.destroystokyo.paper.event.server.PaperServerListPingEvent event; // Paper - - switch (i) { - case 0: - LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); -- s = String.format("%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit -+ // Paper start - Call PaperServerListPingEvent and use results -+ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 39, null); -+ if (event == null) { -+ channelhandlercontext.close(); -+ break; -+ } -+ s = String.format("%s\u00a7%d\u00a7%d", PaperLegacyStatusClient.getUnformattedMotd(event), event.getNumPlayers(), event.getMaxPlayers()); - this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); - break; - case 1: -@@ -60,7 +69,14 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { - } - - LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); -- s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit -+ // Paper start - Call PaperServerListPingEvent and use results -+ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 127, null); // Paper -+ if (event == null) { -+ channelhandlercontext.close(); -+ break; -+ } -+ s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", new Object[] { event.getProtocolVersion(), minecraftserver.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()}); // CraftBukkit -+ // Paper end - this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); - break; - default: -@@ -170,8 +186,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { - - LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); - -- String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", -- Byte.MAX_VALUE, server.getServerVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); -+ InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port); -+ com.destroystokyo.paper.event.server.PaperServerListPingEvent event = PaperLegacyStatusClient.processRequest( -+ server, (InetSocketAddress) ctx.channel().remoteAddress(), protocolVersion, virtualHost); -+ if (event == null) { -+ ctx.close(); -+ return; -+ } -+ -+ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", event.getProtocolVersion(), event.getVersion(), -+ PaperLegacyStatusClient.getMotd(event), event.getNumPlayers(), event.getMaxPlayers()); - this.sendFlushAndClose(ctx, this.createReply(response)); - } - diff --git a/Remapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch b/Remapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch deleted file mode 100644 index 467dda42a9..0000000000 --- a/Remapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 31 Mar 2018 17:04:26 +0100 -Subject: [PATCH] Flag to disable the channel limit - -In some enviroments, the channel limit set by spigot can cause issues, -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 9d853733ff9054cc48925e22c8bb3c8d9b898808..46338fe5693003698de9c7b37a860c3481e06233 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -143,6 +143,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - // Paper start - private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; - private String resourcePackHash; -+ private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit - // Paper end - - public CraftPlayer(CraftServer server, ServerPlayer entity) { -@@ -1576,7 +1577,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void addChannel(String channel) { -- Preconditions.checkState(channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); -+ Preconditions.checkState(DISABLE_CHANNEL_LIMIT || channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); // Paper - flag to disable channel limit - channel = StandardMessenger.validateAndCorrectChannel(channel); - if (channels.add(channel)) { - server.getPluginManager().callEvent(new PlayerRegisterChannelEvent(this, channel)); diff --git a/Remapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch b/Remapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch deleted file mode 100644 index 9a923369d1..0000000000 --- a/Remapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 1 Apr 2018 02:29:37 +0300 -Subject: [PATCH] Add method to open already placed sign - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index c62d01719f21762aa10294815ab88e450e4dce3f..4aec1c2b26d48cb5bea3dfb9e183526763bdb98f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -28,6 +28,7 @@ import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.CraftingTableBlock; - import net.minecraft.world.level.block.EnchantmentTableBlock; - import net.minecraft.world.level.block.entity.BlockEntity; -+import net.minecraft.world.level.block.entity.SignBlockEntity; - import net.minecraft.world.level.block.state.BlockState; - import org.bukkit.GameMode; - import org.bukkit.Location; -@@ -604,6 +605,17 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - } - } - -+ // Paper start - Add method to open already placed sign -+ @Override -+ public void openSign(org.bukkit.block.Sign sign) { -+ org.apache.commons.lang.Validate.isTrue(sign.getWorld().equals(this.getWorld()), "Sign must be in the same world as player is in"); -+ org.bukkit.craftbukkit.block.CraftSign craftSign = (org.bukkit.craftbukkit.block.CraftSign) sign; -+ SignBlockEntity teSign = craftSign.getTileEntity(); -+ // Make sign editable temporarily, will be set back to false in PlayerConnection later -+ teSign.isEditable = true; -+ getHandle().openTextEdit(teSign); -+ } -+ // Paper end - @Override - public boolean dropItem(boolean dropAll) { - return getHandle().drop(dropAll); diff --git a/Remapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch b/Remapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch deleted file mode 100644 index dfe307fc2f..0000000000 --- a/Remapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Sat, 14 Apr 2018 20:20:46 +0200 -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/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 48f0385c7203c7955de5a015f3dc42be2ab7b681..cebf1a623a9bec72d60fdd23dda01868ef6431d4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -358,4 +358,9 @@ public class PaperWorldConfig { - private void squidMaxSpawnHeight() { - squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); - } -+ -+ public boolean disableSprintInterruptionOnAttack; -+ private void disableSprintInterruptionOnAttack() { -+ disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", 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 c4aa824d03de952fe6b306e539baa47af979add1..552920f59aae9de2cad3edcdc8c48a91dff49093 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1180,7 +1180,11 @@ public abstract class Player extends LivingEntity { - } - - this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); -- this.setSprinting(false); -+ // Paper start - Configuration option to disable automatic sprint interruption -+ if (!level.paperConfig.disableSprintInterruptionOnAttack) { -+ this.setSprinting(false); -+ } -+ // Paper end - } - - if (flag3) { diff --git a/Remapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/Remapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch deleted file mode 100644 index 68cdac63bd..0000000000 --- a/Remapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: 0x22 <0x22@futureclient.net> -Date: Thu, 26 Apr 2018 04:41:11 -0400 -Subject: [PATCH] Fix exploit that allowed colored signs to be created - - -diff --git a/src/main/java/net/minecraft/SharedConstants.java b/src/main/java/net/minecraft/SharedConstants.java -index a70c3d25930e7414fc9e897de8d2e0c12f11c0e4..04b8783417bbcd826d6d1c302551fbad9c48bd01 100644 ---- a/src/main/java/net/minecraft/SharedConstants.java -+++ b/src/main/java/net/minecraft/SharedConstants.java -@@ -20,6 +20,7 @@ public class SharedConstants { - return chr != 167 && chr >= ' ' && chr != 127; - } - -+ public static String filterAllowedChatCharacters(String input) { return filterText(input); } // Paper - OBFHELPER - public static String filterText(String s) { - StringBuilder stringbuilder = new StringBuilder(); - char[] achar = s.toCharArray(); -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 8d0c44b6c2c99d5161c5d4b79209b79ff6db75e4..fb36aa08cd2fbe3f7262dccb8cf0f7cae55aea9c 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2786,7 +2786,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines.add(net.kyori.adventure.text.Component.text(list.get(i))); -+ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. - } - SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.craftServer.getPluginManager().callEvent(event); diff --git a/Remapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch b/Remapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch deleted file mode 100644 index 038bdea2df..0000000000 --- a/Remapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 13:15:55 -0400 -Subject: [PATCH] EndermanEscapeEvent - -Fires an event anytime an enderman intends to teleport away from the player - -You may cancel this, enabling ranged attacks to damage the enderman for example. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -index 1c2998c89fd660d6b26b7ff48cddd1862b9b1828..1b9c77666204765a3ed5648b0f8eaa820f578e58 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster; - - import java.util.EnumSet; - import java.util.Optional; -+import com.destroystokyo.paper.event.entity.EndermanEscapeEvent; // Paper - import java.util.Random; - import java.util.UUID; - import java.util.function.Predicate; -@@ -109,6 +110,12 @@ public class EnderMan extends Monster implements NeutralMob { - setGoalTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, true); - } - -+ // Paper start -+ private boolean tryEscape(EndermanEscapeEvent.Reason reason) { -+ return new EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent(); -+ } -+ // Paper end -+ - @Override - public boolean setGoalTarget(LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { - if (!super.setGoalTarget(entityliving, reason, fireEvent)) { -@@ -262,7 +269,7 @@ public class EnderMan extends Monster implements NeutralMob { - if (this.level.isDay() && this.tickCount >= this.targetChangeTime + 600) { - float f = this.getBrightness(); - -- if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) { -+ if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper - this.setTarget((LivingEntity) null); - this.teleport(); - } -@@ -360,17 +367,19 @@ public class EnderMan extends Monster implements NeutralMob { - if (this.isInvulnerableTo(source)) { - return false; - } else if (source instanceof IndirectEntityDamageSource) { -+ if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start - for (int i = 0; i < 64; ++i) { - if (this.teleport()) { - return true; - } - } -+ } // Paper end - - return false; - } else { - boolean flag = super.hurt(source, amount); - -- if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) { -+ if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0 && this.tryEscape(source == DamageSource.DROWN ? EndermanEscapeEvent.Reason.DROWN : EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - use to be critical hits as else, but mojang removed critical hits in 1.16.2 due to MC-185684 - this.teleport(); - } - -@@ -515,7 +524,7 @@ public class EnderMan extends Monster implements NeutralMob { - - static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal { - -- private final EnderMan enderman; -+ private final EnderMan enderman; public final EnderMan getEnderman() { return this.enderman; } // Paper - OBFHELPER - private Player pendingTarget; - private int aggroTime; - private int teleportTime; -@@ -578,7 +587,7 @@ public class EnderMan extends Monster implements NeutralMob { - } else { - if (this.target != null && !this.enderman.isPassenger()) { - if (this.enderman.isLookingAtMe((Player) this.target)) { -- if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D) { -+ if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D && this.getEnderman().tryEscape(EndermanEscapeEvent.Reason.STARE)) { // Paper - this.enderman.teleport(); - } - diff --git a/Remapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch b/Remapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch deleted file mode 100644 index f76f4023f9..0000000000 --- a/Remapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 13:29:44 -0400 -Subject: [PATCH] Enderman.teleportRandomly() - -Ability to trigger the vanilla "teleport randomly" mechanic of an enderman. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -index 1b9c77666204765a3ed5648b0f8eaa820f578e58..1981c08af85b16d45531ffae4fe790bb31edec04 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -@@ -278,6 +278,7 @@ public class EnderMan extends Monster implements NeutralMob { - super.customServerAiStep(); - } - -+ public final boolean teleportRandomly() { return this.teleport(); } // Paper - OBFHELPER - protected boolean teleport() { - if (!this.level.isClientSide() && this.isAlive()) { - double d0 = this.getX() + (this.random.nextDouble() - 0.5D) * 64.0D; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -index d17ed71e800ebcd12b69745f239fa7dbc8a0c808..1edb45490b35b6517201acc8551da8d3c5a489de 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -@@ -16,6 +16,7 @@ public class CraftEnderman extends CraftMonster implements Enderman { - super(server, entity); - } - -+ @Override public boolean teleportRandomly() { return getHandle().teleportRandomly(); } // Paper - @Override - public MaterialData getCarriedMaterial() { - BlockState blockData = getHandle().getCarriedBlock(); diff --git a/Remapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch b/Remapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch deleted file mode 100644 index 47a535288c..0000000000 --- a/Remapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 17:15:26 -0400 -Subject: [PATCH] Block Enderpearl Travel Exploit - -Players are able to use alt accounts and enderpearls to travel -long distances utilizing the pearls in unloaded chunks and loading -the chunk later when convenient. - -This disables that by not saving the thrower when the chunk is unloaded. - -This is mainly useful for survival servers that do not allow freeform teleporting. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index cebf1a623a9bec72d60fdd23dda01868ef6431d4..e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -363,4 +363,10 @@ public class PaperWorldConfig { - private void disableSprintInterruptionOnAttack() { - disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); - } -+ -+ public boolean disableEnderpearlExploit = true; -+ private void disableEnderpearlExploit() { -+ disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); -+ log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index 14ed4f212a9c9c3128c4ddbef7b2e243c925b509..16b554675a276471851846d4f2bea06fdcc166d9 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -62,6 +62,7 @@ public abstract class Projectile extends Entity { - protected void readAdditionalSaveData(CompoundTag tag) { - if (tag.hasUUID("Owner")) { - this.ownerUUID = tag.getUUID("Owner"); -+ if (this instanceof ThrownEnderpearl && this.level != null && this.level.paperConfig.disableEnderpearlExploit) { this.ownerUUID = null; } // Paper - Don't store shooter name for pearls to block enderpearl travel exploit - } - - this.leftOwner = tag.getBoolean("LeftOwner"); diff --git a/Remapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch b/Remapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch deleted file mode 100644 index e2c16b5648..0000000000 --- a/Remapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 15 Aug 2017 22:29:12 -0400 -Subject: [PATCH] Expand World.spawnParticle API and add Builder - -Adds ability to control who receives it and who is the source/sender (vanish API) -the standard API is to send the packet to everyone in the world, which is ineffecient. -Adds an option to control the force mode of the particle. - -This adds a new Builder API which is much friendlier to use. - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 20650bfd10abfa010e71cfeede06c461d50d19a3..5110f2c70d96284e8e7592b3d89266b867b9a466 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -164,7 +164,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - public final Int2ObjectMap entitiesById = new Int2ObjectLinkedOpenHashMap(); - private final Map entitiesByUuid = Maps.newHashMap(); - private final Queue toAddAfterTick = Queues.newArrayDeque(); -- private final List players = Lists.newArrayList(); -+ public final List players = Lists.newArrayList(); // Paper - private -> public - public final ServerChunkCache chunkSource; // Paper - public - boolean tickingEntities; - private final MinecraftServer server; -@@ -1472,12 +1472,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - public int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { -+ // Paper start - Particle API Expansion -+ return sendParticles(players, sender, t0, d0, d1, d2, i, d3, d4, d5, d6, force); -+ } -+ public int sendParticles(List receivers, ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { -+ // Paper end - ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); - // CraftBukkit end - int j = 0; - -- for (int k = 0; k < this.players.size(); ++k) { -- ServerPlayer entityplayer = (ServerPlayer) this.players.get(k); -+ for (Player entityhuman : receivers) { // Paper - Particle API Expansion -+ ServerPlayer entityplayer = (ServerPlayer) entityhuman; // Paper - Particle API Expansion - if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit - - if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 88658d4deacc29128c537e2e02fdc8f684090a2c..beb7219312be5143a50b0841c25efea5dbcc1267 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2334,11 +2334,17 @@ public class CraftWorld implements World { - - @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) { -+ // Paper start - Particle API Expansion -+ spawnParticle(particle, null, null, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, force); -+ } -+ public void spawnParticle(Particle particle, List receivers, Player sender, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) { -+ // Paper end - if (data != null && !particle.getDataType().isInstance(data)) { - throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); - } - getHandle().sendParticles( -- null, // Sender -+ receivers == null ? getHandle().players : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API Expansion -+ sender != null ? ((CraftPlayer) sender).getHandle() : null, // Sender // Paper - Particle API Expansion - CraftParticle.toNMS(particle, data), // Particle - x, y, z, // Position - count, // Count diff --git a/Remapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch b/Remapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch deleted file mode 100644 index 3341055b48..0000000000 --- a/Remapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 May 2018 20:18:54 -0400 -Subject: [PATCH] EndermanAttackPlayerEvent - -Allow control over whether or not an enderman aggros a player. - -This allows you to override/extend the pumpkin/stare logic. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -index 1981c08af85b16d45531ffae4fe790bb31edec04..d190b58bea310f4006ea3deaf0d42c502d441284 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -@@ -221,20 +221,28 @@ public class EnderMan extends Monster implements NeutralMob { - this.readPersistentAngerSaveData((ServerLevel) this.level, tag); - } - -+ // Paper start - OBFHELPER - ok not really, but verify this on updates - private boolean isLookingAtMe(Player player) { -- ItemStack itemstack = (ItemStack) player.inventory.armor.get(3); -+ boolean shouldAttack = g_real(player); -+ com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) player.getBukkitEntity()); -+ event.setCancelled(!shouldAttack); -+ return event.callEvent(); -+ } -+ private boolean g_real(Player entityhuman) { -+ // Paper end -+ ItemStack itemstack = (ItemStack) entityhuman.inventory.armor.get(3); - - if (itemstack.getItem() == Blocks.CARVED_PUMPKIN.asItem()) { - return false; - } else { -- Vec3 vec3d = player.getViewVector(1.0F).normalize(); -- Vec3 vec3d1 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ()); -+ Vec3 vec3d = entityhuman.getViewVector(1.0F).normalize(); -+ Vec3 vec3d1 = new Vec3(this.getX() - entityhuman.getX(), this.getEyeY() - entityhuman.getEyeY(), this.getZ() - entityhuman.getZ()); - double d0 = vec3d1.length(); - - vec3d1 = vec3d1.normalize(); - double d1 = vec3d.dot(vec3d1); - -- return d1 > 1.0D - 0.025D / d0 ? player.canSee(this) : false; -+ return d1 > 1.0D - 0.025D / d0 ? entityhuman.canSee(this) : false; - } - } - diff --git a/Remapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch b/Remapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch deleted file mode 100644 index b17791b352..0000000000 --- a/Remapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 16 May 2018 20:35:16 -0400 -Subject: [PATCH] WitchConsumePotionEvent - -Fires when a witch consumes the potion in their hand - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java -index 9b0269bdd25123f5c0662187de49a869ead3ee81..dd5976d81ff57e8691ba60f425af37572edd26e7 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Witch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java -@@ -124,7 +124,11 @@ public class Witch extends Raider implements RangedAttackMob { - - this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); - if (itemstack.getItem() == Items.POTION) { -- List list = PotionUtils.getMobEffects(itemstack); -+ // Paper start -+ com.destroystokyo.paper.event.entity.WitchConsumePotionEvent event = new com.destroystokyo.paper.event.entity.WitchConsumePotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); -+ -+ List list = event.callEvent() ? PotionUtils.getMobEffects(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion())) : null; -+ // Paper end - - if (list != null) { - Iterator iterator = list.iterator(); diff --git a/Remapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch b/Remapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch deleted file mode 100644 index 0630f7d920..0000000000 --- a/Remapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 16 May 2018 20:44:58 -0400 -Subject: [PATCH] WitchThrowPotionEvent - -Fired when a witch throws a potion at a player - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java -index dd5976d81ff57e8691ba60f425af37572edd26e7..7cefabfb0d8a264cae24f23c06f1c5f552ff0158 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Witch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java -@@ -224,9 +224,16 @@ public class Witch extends Raider implements RangedAttackMob { - potionregistry = Potions.WEAKNESS; - } - -+ // Paper start -+ ItemStack potion = PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potionregistry); -+ com.destroystokyo.paper.event.entity.WitchThrowPotionEvent event = new com.destroystokyo.paper.event.entity.WitchThrowPotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), (org.bukkit.entity.LivingEntity) target.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+ if (!event.callEvent()) { -+ return; -+ } -+ potion = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion()); - ThrownPotion entitypotion = new ThrownPotion(this.level, this); -- -- entitypotion.setItem(PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potionregistry)); -+ entitypotion.setItem(potion); -+ // Paper end - entitypotion.xRot -= -20.0F; - entitypotion.shoot(d0, d1 + (double) (f1 * 0.2F), d2, 0.75F, 8.0F); - if (!this.isSilent()) { diff --git a/Remapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/Remapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch deleted file mode 100644 index 7e80925cf5..0000000000 --- a/Remapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 4 Jun 2018 20:39:20 -0400 -Subject: [PATCH] Allow spawning Item entities with World.spawnEntity - -This API has more capabilities than .dropItem with the Consumer function - -Item can be set inside of the Consumer pre spawn function. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index beb7219312be5143a50b0841c25efea5dbcc1267..2dc9daaeea600fff1f2efddf74b6849fd745a28c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1497,6 +1497,10 @@ public class CraftWorld implements World { - if (Boat.class.isAssignableFrom(clazz)) { - entity = new net.minecraft.world.entity.vehicle.Boat(world, x, y, z); - entity.moveTo(x, y, z, yaw, pitch); -+ // Paper start -+ } else if (org.bukkit.entity.Item.class.isAssignableFrom(clazz)) { -+ entity = new ItemEntity(world, x, y, z, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Item.byBlock(net.minecraft.world.level.block.Blocks.DIRT))); -+ // Paper end - } else if (FallingBlock.class.isAssignableFrom(clazz)) { - entity = new FallingBlockEntity(world, x, y, z, world.getBlockState(new BlockPos(x, y, z))); - } else if (Projectile.class.isAssignableFrom(clazz)) { diff --git a/Remapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch b/Remapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch deleted file mode 100644 index 2177cecc8f..0000000000 --- a/Remapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 22:47:26 -0400 -Subject: [PATCH] WitchReadyPotionEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java -index 7cefabfb0d8a264cae24f23c06f1c5f552ff0158..a37ee32b46aa87be6e3eeca2892b4e7294fd1aef 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Witch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java -@@ -157,7 +157,11 @@ public class Witch extends Raider implements RangedAttackMob { - } - - if (potionregistry != null) { -- this.setItemSlot(EquipmentSlot.MAINHAND, PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry)); -+ // Paper start -+ ItemStack potion = PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry); -+ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+ this.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+ // Paper end - this.usingTime = this.getMainHandItem().getUseDuration(); - this.setUsingItem(true); - if (!this.isSilent()) { diff --git a/Remapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch b/Remapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch deleted file mode 100644 index 2b415bf929..0000000000 --- a/Remapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 23:00:29 -0400 -Subject: [PATCH] ItemStack#getMaxItemUseDuration - -Allows you to determine how long it takes to use a usable/consumable item - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index a0815c0d7f68f345dc48c73b8253de637c7a3e0f..34187197efd5ceff0503682dc6ce313220ca916f 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -604,6 +604,7 @@ public final class ItemStack { - this.getItem().onCraftedBy(this, world, player); - } - -+ public int getItemUseMaxDuration() { return getUseDuration(); } // Paper - OBFHELPER - public int getUseDuration() { - return this.getItem().getUseDuration(this); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 5f0ccdeb8565505278caa591f7390047eab49cf4..44caf00330e4f4f74745973dbe709980f0b61269 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -173,6 +173,13 @@ public final class CraftItemStack extends ItemStack { - return (handle == null) ? Material.AIR.getMaxStackSize() : handle.getItem().getMaxStackSize(); - } - -+ // Paper start -+ @Override -+ public int getMaxItemUseDuration() { -+ return handle == null ? 0 : handle.getItemUseMaxDuration(); -+ } -+ // Paper end -+ - @Override - public void addUnsafeEnchantment(Enchantment ench, int level) { - Validate.notNull(ench, "Cannot add null enchantment"); diff --git a/Remapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch b/Remapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch deleted file mode 100644 index 007bf52a29..0000000000 --- a/Remapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 9 Jun 2018 14:08:39 +0200 -Subject: [PATCH] Implement EntityTeleportEndGatewayEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -index 2c974f9801d209907733bed8e6c4c9ef46e2b610..b70e0633435a272ae1e9fbd12d7f18862de0b951 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -@@ -191,9 +191,20 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements - - } - // CraftBukkit end -+ // Paper start - EntityTeleportEndGatewayEvent - replicated from above -+ org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity = entity.getBukkitEntity(); -+ org.bukkit.Location location = new Location(level.getWorld(), (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); -+ location.setPitch(bukkitEntity.getLocation().getPitch()); -+ location.setYaw(bukkitEntity.getLocation().getYaw()); -+ -+ com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent event = new com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent(bukkitEntity, bukkitEntity.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(level, this.getBlockPos()).getBlock())); -+ if (!event.callEvent()) { -+ return; -+ } -+ // Paper end - - entity1.setPortalCooldown(); -- entity1.teleportToWithTicket((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D); -+ entity1.teleportToWithTicket(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); // Paper - } - - this.triggerCooldown(); diff --git a/Remapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/Remapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch deleted file mode 100644 index 1bda08648d..0000000000 --- a/Remapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 Jun 2018 01:18:49 -0400 -Subject: [PATCH] Unset Ignited flag on cancel of Explosion Event - -Otherwise the creeper infinite explodes - -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 8f8d0a23d011936150854a0606be3d63b18c57af..d9b5cf8ac01289801ded01d928fa7ead96551be5 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -@@ -47,7 +47,7 @@ public class Creeper extends Monster { - - private static final EntityDataAccessor DATA_SWELL_DIR = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.INT); - private static final EntityDataAccessor DATA_IS_POWERED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); -- private static final EntityDataAccessor DATA_IS_IGNITED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); -+ private static final EntityDataAccessor DATA_IS_IGNITED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); private static final EntityDataAccessor isIgnitedDW = DATA_IS_IGNITED; // Paper OBFHELPER - private int oldSwell; - public int swell; // PAIL - public int maxSwell = 30; -@@ -252,6 +252,7 @@ public class Creeper extends Monster { - this.spawnLingeringCloud(); - } else { - swell = 0; -+ this.entityData.set(isIgnitedDW, Boolean.valueOf(false)); // Paper - } - // CraftBukkit end - } diff --git a/Remapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch b/Remapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch deleted file mode 100644 index dbc0942196..0000000000 --- a/Remapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 Jun 2018 20:20:15 -0400 -Subject: [PATCH] Fix CraftEntity hashCode - -hashCodes are not allowed to change, however bukkit used a value -that does change, the entityId. - -When an entity is teleported dimensions, the entity reference is -replaced with a new one with a new entity ID. - -For hashCode, we can simply use the UUID's hashCode to keep -the hashCode from changing. - -equals() is ok to use getEntityId() because equals() should only -be true if both the left and right are the same reference. - -Since entity ids can not duplicate during runtime, this -check is essentially the same as this.getHandle() == other.getHandle() - -However, replaced it too to make it clearer of intent. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index ecb5f5ca547930f91602d539e541964cd9f10287..e1bbaf620f3ed2a6cb9ce8007a78c4cee47b653e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -745,14 +745,15 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return false; - } - final CraftEntity other = (CraftEntity) obj; -- return (this.getEntityId() == other.getEntityId()); -+ return (this.getHandle() == other.getHandle()); // Paper - while logically the same, this is clearer - } - -+ // Paper - Fix hashCode. entity ID's are not static. -+ // A CraftEntity can change reference to a new entity with a new ID, and hash codes should never change - @Override - public int hashCode() { -- int hash = 7; -- hash = 29 * hash + this.getEntityId(); -- return hash; -+ return getUniqueId().hashCode(); -+ // Paper end - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch b/Remapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch deleted file mode 100644 index 5a10f8c4d8..0000000000 --- a/Remapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 15 Jun 2018 00:30:32 -0400 -Subject: [PATCH] Configurable Alternative LootPool Luck Formula - -Rewrites the Vanilla luck application formula so that luck can be -applied to items that do not have any quality defined. - -See: https://luckformula.emc.gs for data and details ------------ - -The rough summary is: -My goal was that in a pool, when luck was applied, the pool -rebalances so the percentages for bigger items is -lowered and smaller items is boosted. - -Do this by boosting and then reducing the weight value, -so that larger numbers are penalized more than smaller numbers. -resulting in a larger reduction of entries for more common -items than the reduction on small weights, -giving smaller weights more of a chance - ------------ - -This work kind of obsoletes quality, but quality would be useful -for 2 items with same weight that you want luck to impact -in varying directions. - -Fishing still falls into that as the weights are closer, so luck -will invalidate junk more. - -This change will result in some major changes to fishing formulas. - ------------ - -I would love to see this change in Vanilla, so Mojang please pull :) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 05a5abb951abe37f30a719cb75376d2d43c0d252..77a03abd59db4a43f6f2d59d4c7ef176e782f205 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -288,4 +288,12 @@ public class PaperConfig { - SpigotConfig.save(); - } - } -+ -+ public static boolean useAlternativeLuckFormula = false; -+ private static void useAlternativeLuckFormula() { -+ useAlternativeLuckFormula = getBoolean("settings.use-alternative-luck-formula", false); -+ if (useAlternativeLuckFormula) { -+ Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java -index ceb5e5405ed20c8de954847bbb269109107a43fc..d99bc0b8a1e9c4749b176a823b879ced9efdd7d6 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java -@@ -8,7 +8,6 @@ import java.util.List; - import java.util.function.BiFunction; - import java.util.function.Consumer; - import net.minecraft.util.GsonHelper; --import net.minecraft.util.Mth; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.level.storage.loot.LootContext; - import net.minecraft.world.level.storage.loot.ValidationContext; -@@ -20,8 +19,8 @@ import org.apache.commons.lang3.ArrayUtils; - - public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer { - -- protected final int weight; -- protected final int quality; -+ protected final int weight; public int getWeight() { return weight; } // Paper - OBFHELPER -+ protected final int quality; public int getQuality() { return quality; } // Paper - OBFHELPER - protected final LootItemFunction[] functions; - private final BiFunction compositeFunction; - private final LootPoolEntry entry = new LootPoolSingletonContainer.EntryBase() { -@@ -152,11 +151,38 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer - - public abstract class EntryBase implements LootPoolEntry { - -- protected EntryBase() {} -+ protected EntryBase() { -+ } - - @Override - public int getWeight(float luck) { -- return Math.max(Mth.floor((float) LootPoolSingletonContainer.this.weight + (float) LootPoolSingletonContainer.this.quality * luck), 0); -+ // Paper start - Offer an alternative loot formula to refactor how luck bonus applies -+ // SEE: https://luckformula.emc.gs for details and data -+ if (lastLuck != null && lastLuck == luck) { -+ return lastWeight; -+ } -+ // This is vanilla -+ float qualityModifer = (float) getQuality() * luck; -+ double baseWeight = (getWeight() + qualityModifer); -+ if (com.destroystokyo.paper.PaperConfig.useAlternativeLuckFormula) { -+ // Random boost to avoid losing precision in the final int cast on return -+ final int weightBoost = 100; -+ baseWeight *= weightBoost; -+ // If we have vanilla 1, bump that down to 0 so nothing is is impacted -+ // vanilla 3 = 300, 200 basis = impact 2% -+ // =($B2*(($B2-100)/100/100)) -+ double impacted = baseWeight * ((baseWeight - weightBoost) / weightBoost / 100); -+ // =($B$7/100) -+ float luckModifier = Math.min(100, luck * 10) / 100; -+ // =B2 - (C2 *($B$7/100)) -+ baseWeight = Math.ceil(baseWeight - (impacted * luckModifier)); -+ } -+ lastLuck = luck; -+ lastWeight = (int) Math.max(0, Math.floor(baseWeight)); -+ return lastWeight; - } - } -+ private Float lastLuck = null; -+ private int lastWeight = 0; -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch b/Remapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch deleted file mode 100644 index 368773ef81..0000000000 --- a/Remapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 15 Jun 2018 20:37:03 -0400 -Subject: [PATCH] Print Error details when failing to save player data - - -diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java -index 60fe01e824e4657d2601797d7858d5de339ab255..5b2a558d4d357d0de033ec2d7a9b4686f202c903 100644 ---- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java -+++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java -@@ -43,7 +43,7 @@ public class PlayerDataStorage { - - Util.safeReplaceFile(file1, file, file2); - } catch (Exception exception) { -- PlayerDataStorage.LOGGER.warn("Failed to save player data for {}", entityhuman.getName().getString()); -+ PlayerDataStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getScoreboardName(), exception); // Paper - } - - } diff --git a/Remapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch b/Remapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch deleted file mode 100644 index 9472536ee6..0000000000 --- a/Remapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 16 Jun 2018 01:18:16 -0500 -Subject: [PATCH] Make shield blocking delay configurable - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec..3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -369,4 +369,9 @@ public class PaperWorldConfig { - disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); - log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); - } -+ -+ public int shieldBlockingDelay = 5; -+ private void shieldBlockingDelay() { -+ shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 8b0d1f4fbc43a6f37a5f9c453b5dd142a4f69745..af2e81137d9c686f8d94a1d0d7241619fa1f352c 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3308,7 +3308,7 @@ public abstract class LivingEntity extends Entity { - if (this.isUsingItem() && !this.useItem.isEmpty()) { - Item item = this.useItem.getItem(); - -- return item.getUseAnimation(this.useItem) != UseAnim.BLOCK ? false : item.getUseDuration(this.useItem) - this.useItemRemaining >= 5; -+ return item.getUseAnimation(this.useItem) != UseAnim.BLOCK ? false : item.getUseDuration(this.useItem) - this.useItemRemaining >= getShieldBlockingDelay(); // Paper - shieldBlockingDelay - } else { - return false; - } -@@ -3587,4 +3587,15 @@ public abstract class LivingEntity extends Entity { - public void broadcastBreakEvent(InteractionHand hand) { - this.broadcastBreakEvent(hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); - } -+ // Paper start -+ public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; -+ -+ public int getShieldBlockingDelay() { -+ return shieldBlockingDelay; -+ } -+ -+ public void setShieldBlockingDelay(int shieldBlockingDelay) { -+ this.shieldBlockingDelay = shieldBlockingDelay; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 006f4c71bbcda61b55815e7ceab91731ab062da0..663887d9aecc2823fe7d02a9b108a291cd27102c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -699,5 +699,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setArrowsStuck(int arrows) { - getHandle().setArrowCount(arrows); - } -+ -+ @Override -+ public int getShieldBlockingDelay() { -+ return getHandle().getShieldBlockingDelay(); -+ } -+ -+ @Override -+ public void setShieldBlockingDelay(int delay) { -+ getHandle().setShieldBlockingDelay(delay); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch b/Remapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch deleted file mode 100644 index 4fc5ab999a..0000000000 --- a/Remapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 15 Jun 2013 19:51:17 -0400 -Subject: [PATCH] Improve EntityShootBowEvent - -Adds missing call to Illagers and also adds Arrow ItemStack to skeltons - -diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -index e8ad820b11dd1b89e442bb057d5761c90c4b1923..76027a7c9615495af64102744e264d7ba7c9b87e 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -+++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -@@ -197,7 +197,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo - - entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level.getDifficulty().getId() * 4)); - // CraftBukkit start -- org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), null, entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getOriginalItemStack(), entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper - if (event.isCancelled()) { - event.getProjectile().remove(); - return; -diff --git a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java -index ab8c41e72c15ee9e5256eba2ba2681a33ce8a8d9..2d07e9cf4c84bc32a7624f65173c4e8a6dc07165 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java -@@ -171,8 +171,18 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { - double d3 = (double) Mth.sqrt(d0 * d0 + d2 * d2); - - entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level.getDifficulty().getId() * 4)); -+ // Paper start -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getOriginalItemStack(), entityarrow, target.getUsedItemHand(), 0.8F, true); -+ if (event.isCancelled()) { -+ event.getProjectile().remove(); -+ return; -+ } -+ -+ if (event.getProjectile() == entityarrow.getBukkitEntity()) { -+ this.level.addFreshEntity(entityarrow); -+ } - this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); -- this.level.addFreshEntity(entityarrow); -+ // Paper end - } - - class IllusionerBlindnessSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { diff --git a/Remapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch b/Remapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch deleted file mode 100644 index 1250005dcb..0000000000 --- a/Remapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 18 Jun 2018 01:12:53 -0400 -Subject: [PATCH] PlayerReadyArrowEvent - -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 552920f59aae9de2cad3edcdc8c48a91dff49093..b88d8f2c377322290002e84e217f3f2f6e4e71e8 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -2139,6 +2139,17 @@ public abstract class Player extends LivingEntity { - return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING); - } - -+ // Paper start -+ protected boolean tryReadyArrow(ItemStack bow, ItemStack itemstack) { -+ return !(this instanceof ServerPlayer) || -+ new com.destroystokyo.paper.event.player.PlayerReadyArrowEvent( -+ ((ServerPlayer) this).getBukkitEntity(), -+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(bow), -+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack) -+ ).callEvent(); -+ // Paper end -+ } -+ - @Override - public ItemStack getProjectile(ItemStack stack) { - if (!(stack.getItem() instanceof ProjectileWeaponItem)) { -@@ -2155,7 +2166,7 @@ public abstract class Player extends LivingEntity { - for (int i = 0; i < this.inventory.getContainerSize(); ++i) { - ItemStack itemstack2 = this.inventory.getItem(i); - -- if (predicate.test(itemstack2)) { -+ if (predicate.test(itemstack2) && tryReadyArrow(stack, itemstack2)) { // Paper - return itemstack2; - } - } diff --git a/Remapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch b/Remapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch deleted file mode 100644 index 79e858a274..0000000000 --- a/Remapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Mon, 18 Jun 2018 15:46:23 +0200 -Subject: [PATCH] Implement EntityKnockbackByEntityEvent - -This event is called when an entity receives knockback by another entity. - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index af2e81137d9c686f8d94a1d0d7241619fa1f352c..04489a915d11ba970a5188a5a913432ab4ef9faa 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1336,7 +1336,7 @@ public abstract class LivingEntity extends Entity { - } - - this.hurtDir = (float) (Mth.atan2(d1, d0) * 57.2957763671875D - (double) this.yRot); -- this.knockback(0.4F, d0, d1); -+ this.doKnockback(0.4F, d0, d1, entity1); // Paper - } else { - this.hurtDir = (float) ((int) (Math.random() * 2.0D) * 180); - } -@@ -1384,7 +1384,7 @@ public abstract class LivingEntity extends Entity { - } - - protected void blockedByShield(LivingEntity target) { -- target.knockback(0.5F, target.getX() - this.getX(), target.getZ() - this.getZ()); -+ target.doKnockback(0.5F, target.getX() - this.getX(), target.getZ() - this.getZ(), this); // Paper - } - - private boolean checkTotemDeathProtection(DamageSource source) { -@@ -1627,6 +1627,11 @@ public abstract class LivingEntity extends Entity { - } - - public void knockback(float f, double d0, double d1) { -+ // Paper start - add knockbacking entity parameter -+ this.doKnockback(f, d0, d1, null); -+ } -+ public void doKnockback(float f, double d0, double d1, Entity knockingBackEntity) { -+ // Paper end - add knockbacking entity parameter - f = (float) ((double) f * (1.0D - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE))); - if (f > 0.0F) { - this.hasImpulse = true; -@@ -1634,6 +1639,16 @@ public abstract class LivingEntity extends Entity { - Vec3 vec3d1 = (new Vec3(d0, 0.0D, d1)).normalize().scale((double) f); - - this.setDeltaMovement(vec3d.x / 2.0D - vec3d1.x, this.onGround ? Math.min(0.4D, vec3d.y / 2.0D + (double) f) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); -+ -+ // Paper start - call EntityKnockbackByEntityEvent -+ Vec3 currentMot = this.getDeltaMovement(); -+ org.bukkit.util.Vector delta = new org.bukkit.util.Vector(currentMot.x - vec3d.x, currentMot.y - vec3d.y, currentMot.z - vec3d.z); -+ // Restore old velocity to be able to access it in the event -+ this.setDeltaMovement(vec3d); -+ if (knockingBackEntity == null || new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent((org.bukkit.entity.LivingEntity) getBukkitEntity(), knockingBackEntity.getBukkitEntity(), f, delta).callEvent()) { -+ this.setDeltaMovement(vec3d.x + delta.getX(), vec3d.y + delta.getY(), vec3d.z + delta.getZ()); -+ } -+ // Paper end - } - } - -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index eb35c69bb777ba8d83b2304ff9f862512643e745..f3690ea49cf90c816b8b3554b47d6f2d9dfbe016 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -1566,7 +1566,7 @@ public abstract class Mob extends LivingEntity { - - if (flag) { - if (f1 > 0.0F && target instanceof LivingEntity) { -- ((LivingEntity) target).knockback(f1 * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F))); -+ ((LivingEntity) target).doKnockback(f1 * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)), this); // Paper - this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); - } - -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 b88d8f2c377322290002e84e217f3f2f6e4e71e8..5e6a86b0b8999a5c47d2f9bdd9857ab5f0772033 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1174,7 +1174,7 @@ public abstract class Player extends LivingEntity { - if (flag5) { - if (i > 0) { - if (target instanceof LivingEntity) { -- ((LivingEntity) target).knockback((float) i * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F))); -+ ((LivingEntity) target).doKnockback((float) i * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)), this); // Paper - } else { - target.push((double) (-Mth.sin(this.yRot * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.yRot * 0.017453292F) * (float) i * 0.5F)); - } -@@ -1198,7 +1198,7 @@ public abstract class Player extends LivingEntity { - if (entityliving != this && entityliving != target && !this.isAlliedTo(entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) { - // CraftBukkit start - Only apply knockback if the damage hits - if (entityliving.hurt(DamageSource.playerAttack(this).sweep(), f4)) { -- entityliving.knockback(0.4F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F))); -+ entityliving.doKnockback(0.4F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)), this); // Paper - } - // CraftBukkit end - } diff --git a/Remapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch b/Remapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch deleted file mode 100644 index 01be1df09c..0000000000 --- a/Remapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 20 Jun 2018 23:17:24 -0400 -Subject: [PATCH] Expand Explosions API - -Add Entity as a Source capability, and add more API choices, and on Location. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 2dc9daaeea600fff1f2efddf74b6849fd745a28c..9b5a1c3ab8ffde524e194fdeaa8eaef6b286b57b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -871,6 +871,11 @@ public class CraftWorld implements World { - public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) { - return !world.explode(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; - } -+ // Paper start -+ public boolean createExplosion(Entity source, Location loc, float power, boolean setFire, boolean breakBlocks) { -+ return !world.explode(source != null ? ((org.bukkit.craftbukkit.entity.CraftEntity) source).getHandle() : null, loc.getX(), loc.getY(), loc.getZ(), power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; -+ } -+ // Paper end - - @Override - public boolean createExplosion(Location loc, float power) { diff --git a/Remapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch b/Remapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch deleted file mode 100644 index 181103a79c..0000000000 --- a/Remapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 Jun 2018 00:21:28 -0400 -Subject: [PATCH] LivingEntity Hand Raised/Item Use API - -How long an entity has raised hands to charge an attack or use an item - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 04489a915d11ba970a5188a5a913432ab4ef9faa..205c639d26652befebae925fc6e40976c370710f 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -209,7 +209,7 @@ public abstract class LivingEntity extends Entity { - private float speed; - private int noJumpDelay; - private float absorptionAmount; -- protected ItemStack useItem; -+ public ItemStack useItem; // Paper - public - protected int useItemRemaining; - protected int fallFlyTicks; - private BlockPos lastPos; -@@ -3291,10 +3291,12 @@ public abstract class LivingEntity extends Entity { - return this.useItem; - } - -+ public int getItemUseRemainingTime() { return this.getUseItemRemainingTicks(); } // Paper - OBFHELPER - public int getUseItemRemainingTicks() { - return this.useItemRemaining; - } - -+ public int getHandRaisedTime() { return this.getTicksUsingItem(); } // Paper - OBFHELPER - public int getTicksUsingItem() { - return this.isUsingItem() ? this.useItem.getUseDuration() - this.getUseItemRemainingTicks() : 0; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 663887d9aecc2823fe7d02a9b108a291cd27102c..6dd7a722e10a2727f68318b880f2726bb816f198 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -709,5 +709,30 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setShieldBlockingDelay(int delay) { - getHandle().setShieldBlockingDelay(delay); - } -+ -+ @Override -+ public ItemStack getActiveItem() { -+ return getHandle().useItem.asBukkitMirror(); -+ } -+ -+ @Override -+ public int getItemUseRemainingTime() { -+ return getHandle().getItemUseRemainingTime(); -+ } -+ -+ @Override -+ public int getHandRaisedTime() { -+ return getHandle().getHandRaisedTime(); -+ } -+ -+ @Override -+ public boolean isHandRaised() { -+ return getHandle().isUsingItem(); -+ } -+ -+ @Override -+ public org.bukkit.inventory.EquipmentSlot getHandRaised() { -+ return getHandle().getUsedItemHand() == net.minecraft.world.InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0230-RangedEntity-API.patch b/Remapped-Spigot-Server-Patches/0230-RangedEntity-API.patch deleted file mode 100644 index 40db6f9590..0000000000 --- a/Remapped-Spigot-Server-Patches/0230-RangedEntity-API.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 26 Jun 2018 22:00:49 -0400 -Subject: [PATCH] RangedEntity API - -Allows you to determine if an entity is capable of ranged attacks, -and to perform an attack. - -diff --git a/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e75e1d0d833c96af139fd955b2585ec24281b294 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java -@@ -0,0 +1,19 @@ -+package com.destroystokyo.paper.entity; -+ -+import net.minecraft.world.entity.monster.RangedAttackMob; -+import org.bukkit.craftbukkit.entity.CraftLivingEntity; -+import org.bukkit.entity.LivingEntity; -+ -+public interface CraftRangedEntity extends RangedEntity { -+ T getHandle(); -+ -+ @Override -+ default void rangedAttack(LivingEntity target, float charge) { -+ getHandle().rangedAttack(((CraftLivingEntity) target).getHandle(), charge); -+ } -+ -+ @Override -+ default void setChargingAttack(boolean raiseHands) { -+ getHandle().setChargingAttack(raiseHands); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java b/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java -index b3ad4d54eeb1b894c24a5a76e8b12b8d9568cd56..ae10f3933fe78f74995952a6a8acf09ef4e99823 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java -+++ b/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java -@@ -4,5 +4,8 @@ import net.minecraft.world.entity.LivingEntity; - - public interface RangedAttackMob { - -- void performRangedAttack(LivingEntity target, float pullProgress); -+ void performRangedAttack(LivingEntity target, float pullProgress); default void rangedAttack(LivingEntity entityliving, float f) { performRangedAttack(entityliving, f); } // Paper - OBFHELPER -+ -+ // - see EntitySkeletonAbstract melee goal -+ void setAggressive(boolean flag); default void setChargingAttack(boolean charging) { setAggressive(charging); }; // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -index 34cb8062168258bfd168826ceeb2fde669f6d1a8..03e2acd4829da449a471b0fa1a311e74aee114d3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -@@ -4,7 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.Drowned; - import org.bukkit.entity.EntityType; - --public class CraftDrowned extends CraftZombie implements Drowned { -+public class CraftDrowned extends CraftZombie implements Drowned, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftDrowned(CraftServer server, net.minecraft.world.entity.monster.Drowned entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -index 59b866e54e0d7e1dd8815ffa85275e36271113da..bbf7189a0fc9921e7a6007494f91229d9fba0846 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -@@ -4,7 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Illusioner; - --public class CraftIllusioner extends CraftSpellcaster implements Illusioner { -+public class CraftIllusioner extends CraftSpellcaster implements Illusioner, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftIllusioner(CraftServer server, net.minecraft.world.entity.monster.Illusioner entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -index 04f716af67939b2dc34875f722816dd1ffdc4966..ed3b8fcc221d6c0789eb92eb4716d640ba0fec9f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.entity.CraftRangedEntity; - import com.google.common.base.Preconditions; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.inventory.CraftInventoryLlama; -@@ -9,7 +10,7 @@ import org.bukkit.entity.Llama; - import org.bukkit.entity.Llama.Color; - import org.bukkit.inventory.LlamaInventory; - --public class CraftLlama extends CraftChestedHorse implements Llama { -+public class CraftLlama extends CraftChestedHorse implements Llama, CraftRangedEntity { // Paper - - public CraftLlama(CraftServer server, net.minecraft.world.entity.animal.horse.Llama entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -index 12bce49fcb164b6311a81024d1749a582ab1be25..c06fea6e0eaf58b8e7441ccf8595d6ca8417526a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -@@ -13,7 +13,7 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.Piglin; - import org.bukkit.inventory.Inventory; - --public class CraftPiglin extends CraftPiglinAbstract implements Piglin { -+public class CraftPiglin extends CraftPiglinAbstract implements Piglin, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftPiglin(CraftServer server, net.minecraft.world.entity.monster.piglin.Piglin entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -index fc86b8ecc349ed59c9eb6de03086d4027cb4e08d..949260d6750e71f148229955c94bcbaad9d54a2d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -@@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.Pillager; - import org.bukkit.inventory.Inventory; - --public class CraftPillager extends CraftIllager implements Pillager { -+public class CraftPillager extends CraftIllager implements Pillager, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftPillager(CraftServer server, net.minecraft.world.entity.monster.Pillager entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -index 4cd3dfd3466f384aab06dacd388e8053b045b046..b2d3244cca4d9d108159f3537d8a9aace3f8e77f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -@@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.Skeleton; - import org.bukkit.entity.Skeleton.SkeletonType; - --public class CraftSkeleton extends CraftMonster implements Skeleton { -+public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftSkeleton(CraftServer server, AbstractSkeleton entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -index fcce4aa391d0c448531815e99e0e32c84203c1b8..a7164a921f479c928049d4e812eab50567e96fc2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Snowman; - --public class CraftSnowman extends CraftGolem implements Snowman { -+public class CraftSnowman extends CraftGolem implements Snowman, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftSnowman(CraftServer server, SnowGolem entity) { - super(server, entity); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -index 60e00e539d214eb8854a53364c92c3cf55ca1062..d4eeb071dbbfca3ecea256228853bcb5c11f49ee 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -@@ -4,7 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Witch; - --public class CraftWitch extends CraftRaider implements Witch { -+public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftWitch(CraftServer server, net.minecraft.world.entity.monster.Witch entity) { - super(server, entity); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -index 728a8c0f5781f33bdb096aefb569e9509dda8c89..fdcd680b972da54f9cdb41dff5563e42bd12d8e3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -@@ -7,7 +7,7 @@ import org.bukkit.craftbukkit.boss.CraftBossBar; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Wither; - --public class CraftWither extends CraftMonster implements Wither { -+public class CraftWither extends CraftMonster implements Wither, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - private BossBar bossBar; - diff --git a/Remapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch b/Remapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch deleted file mode 100644 index 1ba8695871..0000000000 --- a/Remapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 22 Jun 2018 10:38:31 -0500 -Subject: [PATCH] Add config to disable ender dragon legacy check - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77..4813f62d1e382d5ac6971b2244df3f13c80d1950 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -374,4 +374,9 @@ public class PaperWorldConfig { - private void shieldBlockingDelay() { - shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); - } -+ -+ public boolean scanForLegacyEnderDragon = true; -+ private void scanForLegacyEnderDragon() { -+ scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 2386ffeec60851ba192b89bc6fd7ffff9c56aff5..4b18931225ef60dbcffd7fcc20d0e9ce62348a07 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -73,7 +73,7 @@ public class EndDragonFight { - private boolean dragonKilled; - private boolean previouslyKilled; - public UUID dragonUUID; -- private boolean needsStateScanning; -+ private boolean needsStateScanning; private void setScanForLegacyFight(boolean scanForLegacyFight) { this.needsStateScanning = scanForLegacyFight; } private boolean scanForLegacyFight() { return this.needsStateScanning; } // Paper - OBFHELPER - public BlockPos portalLocation; - public DragonRespawnAnimation respawnStage; - private int respawnTime; diff --git a/Remapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch b/Remapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch deleted file mode 100644 index 6bcd99431d..0000000000 --- a/Remapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 3 Jul 2018 16:08:14 +0200 -Subject: [PATCH] Implement World.getEntity(UUID) API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 9b5a1c3ab8ffde524e194fdeaa8eaef6b286b57b..3a3466cd9bbd34dbc0b79567f5579e84a81d6009 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1286,6 +1286,15 @@ public class CraftWorld implements World { - return list; - } - -+ // Paper start - getEntity by UUID API -+ @Override -+ public Entity getEntity(UUID uuid) { -+ Validate.notNull(uuid, "UUID cannot be null"); -+ net.minecraft.world.entity.Entity entity = world.getEntity(uuid); -+ return entity == null ? null : entity.getBukkitEntity(); -+ } -+ // Paper end -+ - @Override - public void save() { - org.spigotmc.AsyncCatcher.catchOp("world save"); // Spigot diff --git a/Remapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch b/Remapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch deleted file mode 100644 index c1daa66bf3..0000000000 --- a/Remapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch +++ /dev/null @@ -1,228 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 3 Jul 2018 21:56:23 -0400 -Subject: [PATCH] InventoryCloseEvent Reason API - -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/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 5110f2c70d96284e8e7592b3d89266b867b9a466..ea1b15495481157912140bf5de9bf4a949c16910 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1119,7 +1119,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - for (BlockEntity tileentity : chunk.getBlockEntities().values()) { - if (tileentity instanceof net.minecraft.world.Container) { - for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((net.minecraft.world.Container) tileentity).getViewers())) { -- h.closeInventory(); -+ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - } - } - } -@@ -1177,7 +1177,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - // Spigot Start - if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder) { - for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) { -- h.closeInventory(); -+ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - } - } - // 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 0fa977a31cf945b74f3a046b6be302b10f494ad1..1441a461e749dbfa303095f6b51d655c45f68ce0 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -544,7 +544,7 @@ public class ServerPlayer extends Player implements ContainerListener { - } - // Paper end - if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { -- this.closeContainer(); -+ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.containerMenu = this.inventoryMenu; - } - -@@ -717,7 +717,7 @@ public class ServerPlayer extends Player implements ContainerListener { - - // SPIGOT-943 - only call if they have an inventory open - if (this.containerMenu != this.inventoryMenu) { -- this.closeContainer(); -+ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DEATH); // Paper - } - - net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure -@@ -1290,7 +1290,7 @@ public class ServerPlayer extends Player implements ContainerListener { - return OptionalInt.empty(); - } else { - if (this.containerMenu != this.inventoryMenu) { -- this.closeContainer(); -+ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - - this.nextContainerCounter(); -@@ -1350,7 +1350,7 @@ public class ServerPlayer extends Player implements ContainerListener { - } - // CraftBukkit end - if (this.containerMenu != this.inventoryMenu) { -- this.closeContainer(); -+ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - - // this.nextContainerCounter(); // CraftBukkit - moved up -@@ -1414,7 +1414,12 @@ public class ServerPlayer extends Player implements ContainerListener { - - @Override - public void closeContainer() { -- CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit -+ // Paper start -+ closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); -+ } -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit -+ // Paper end - this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); - this.doCloseContainer(); - } -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index fb36aa08cd2fbe3f7262dccb8cf0f7cae55aea9c..d322e99170b3cb6594efc824a879ab9a538ea1eb 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -188,6 +188,7 @@ import org.bukkit.event.inventory.ClickType; - import org.bukkit.event.inventory.CraftItemEvent; - import org.bukkit.event.inventory.InventoryAction; - import org.bukkit.event.inventory.InventoryClickEvent; -+import org.bukkit.event.inventory.InventoryCloseEvent; // Paper - import org.bukkit.event.inventory.InventoryCreativeEvent; - import org.bukkit.event.inventory.InventoryType.SlotType; - import org.bukkit.event.inventory.SmithItemEvent; -@@ -2309,10 +2310,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - @Override - public void handleContainerClose(ServerboundContainerClosePacket packet) { -- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); -+ // Paper start -+ handleContainerClose(packet, InventoryCloseEvent.Reason.PLAYER); -+ } -+ public void handleContainerClose(ServerboundContainerClosePacket packetplayinclosewindow, InventoryCloseEvent.Reason reason) { -+ // Paper end -+ PacketUtils.ensureRunningOnSameThread(packetplayinclosewindow, this, this.player.getLevel()); - - if (this.player.isImmobile()) return; // CraftBukkit -- CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit -+ CraftEventFactory.handleInventoryCloseEvent(this.player, reason); // CraftBukkit // Paper - - this.player.doCloseContainer(); - } -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index ae60b233c4d56a4964b388f96e9cc66410774e8d..51b1ce465d23b971f7e08a3175319a33183d0398 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -490,7 +490,7 @@ public abstract class PlayerList { - // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it - // See SPIGOT-5799, SPIGOT-6145 - if (entityplayer.containerMenu != entityplayer.inventoryMenu) { -- entityplayer.closeContainer(); -+ entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - } - - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); -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 5e6a86b0b8999a5c47d2f9bdd9857ab5f0772033..709e930eef7bae5694238ed8c4d0ef59316bb715 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -249,7 +249,7 @@ public abstract class Player extends LivingEntity { - this.updateIsUnderwater(); - super.tick(); - if (!this.level.isClientSide && this.containerMenu != null && !this.containerMenu.stillValid(this)) { -- this.closeContainer(); -+ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.containerMenu = this.inventoryMenu; - } - -@@ -444,6 +444,13 @@ public abstract class Player extends LivingEntity { - return 20; - } - -+ // Paper start - unused code, but to keep signatures aligned -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ closeContainer(); -+ this.containerMenu = this.inventoryMenu; -+ } -+ // Paper end -+ - public void closeContainer() { - 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 4aec1c2b26d48cb5bea3dfb9e183526763bdb98f..a73c6ddd6bf66cc21ae5b25daacdece8cbfeeeac 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -374,7 +374,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - if (((ServerPlayer) getHandle()).connection == null) return; - if (getHandle().containerMenu != getHandle().inventoryMenu) { - // fire INVENTORY_CLOSE if one already open -- ((ServerPlayer) getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(getHandle().containerMenu.containerId)); -+ ((ServerPlayer) getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(getHandle().containerMenu.containerId), org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - ServerPlayer player = (ServerPlayer) getHandle(); - AbstractContainerMenu container; -@@ -444,8 +444,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - - @Override - public void closeInventory() { -- getHandle().closeContainer(); -+ // Paper start -+ getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); - } -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ getHandle().closeContainer(reason); -+ } -+ // Paper end - - @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 46338fe5693003698de9c7b37a860c3481e06233..c7f66dddf0a0850ca4048dd47cd2ded114caa07e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -895,7 +895,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - // Close any foreign inventory - if (getHandle().containerMenu != getHandle().inventoryMenu) { -- getHandle().closeContainer(); -+ getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper - } - - // 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 5e8ff18f98b03741ccbb927f87499ae36d775a86..c2f58b95db41b2205fbf2728c6a99419c6a63dfa 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1175,7 +1175,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 -- player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId)); -+ player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - - CraftServer server = player.level.getCraftServer(); -@@ -1341,8 +1341,18 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start -+ /** -+ * Incase plugins hooked into this or Spigot adds a new inventory close event. Prefer to pass a reason -+ * @param human -+ */ -+ @Deprecated - public static void handleInventoryCloseEvent(net.minecraft.world.entity.player.Player human) { -- InventoryCloseEvent event = new InventoryCloseEvent(human.containerMenu.getBukkitView()); -+ handleInventoryCloseEvent(human, org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); -+ } -+ public static void handleInventoryCloseEvent(net.minecraft.world.entity.player.Player human, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ // Paper end -+ InventoryCloseEvent event = new InventoryCloseEvent(human.containerMenu.getBukkitView(), reason); // Paper - human.level.getCraftServer().getPluginManager().callEvent(event); - human.containerMenu.transferTo(human.inventoryMenu, human.getBukkitEntity()); - } diff --git a/Remapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch b/Remapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch deleted file mode 100644 index 0689023cf1..0000000000 --- a/Remapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 15:30:22 -0400 -Subject: [PATCH] Vex#getSummoner API - -Get's the NPC that summoned this Vex - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java -index 3204ae9a9243818727bedfa060c07bc34d3b4c66..ec4f6d96360e759ffc19de838fdbf3027164a424 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Vex.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java -@@ -124,6 +124,7 @@ public class Vex extends Monster { - - } - -+ public Mob getOwner() { return getOwner(); } // Paper - OBFHELPER - public Mob getOwner() { - return this.owner; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -index 2b4e9ddca5c6429c01d780d65a64ef6a59446c69..56bec4350f36a94d4dfa71a234872a795c2dcb3f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -@@ -15,6 +15,13 @@ public class CraftVex extends CraftMonster implements Vex { - return (net.minecraft.world.entity.monster.Vex) super.getHandle(); - } - -+ // Paper start -+ public org.bukkit.entity.Mob getSummoner() { -+ net.minecraft.world.entity.Mob owner = getHandle().getOwner(); -+ return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; -+ } -+ // Paper end -+ - @Override - public String toString() { - return "CraftVex"; diff --git a/Remapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/Remapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch deleted file mode 100644 index 5cab7fe140..0000000000 --- a/Remapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Fri, 13 Jul 2018 14:54:43 +0200 -Subject: [PATCH] Refresh player inventory when cancelling - PlayerInteractEntityEvent - -When interacting with entities with an item, the client will assume -the interaction is successful, and update the held item on the -client. However, if the interaction is cancelled on the server side, -the client will still mistakenly remove/replace the item in hand. - -Examples for this are milking cows with a bucket or dyeing sheep. -The bucket is replaced with milk and the dye removed from inventory. - -Refresh the player inventory when PlayerInteractEntityEvent is -cancelled to avoid this problem. - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index d322e99170b3cb6594efc824a879ab9a538ea1eb..645f7b7c862acf77d70ca0b05308945424bc4d32 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2222,6 +2222,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } - - if (event.isCancelled()) { -+ this.player.refreshContainer(this.player.containerMenu); // Paper - Refresh player inventory - return; - } - // CraftBukkit end diff --git a/Remapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch b/Remapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch deleted file mode 100644 index 4887c3dd7e..0000000000 --- a/Remapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 19 Jul 2018 01:05:00 -0400 -Subject: [PATCH] Don't change the Entity Random seed for squids - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java -index 5a7582fd4f8e883d2f08a0227932c17d7576b957..2e5a35565b6b7c4d3f7fdab45095f789c33f8937 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Squid.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java -@@ -48,7 +48,7 @@ public class Squid extends WaterAnimal { - - public Squid(EntityType type, Level world) { - super(type, world); -- this.random.setSeed((long) this.getId()); -+ //this.random.setSeed((long) this.getId()); // Paper - this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; - } - diff --git a/Remapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch b/Remapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch deleted file mode 100644 index 4deb8f2bc2..0000000000 --- a/Remapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 19 Jul 2018 01:08:05 -0400 -Subject: [PATCH] Re-add vanilla entity warnings for duplicates - -These are a critical sign that somethin went wrong, and you've lost some data.... - -We should kind of know about these things you know. - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index ea1b15495481157912140bf5de9bf4a949c16910..914241a57c304fde220bc546261d6e959445772a 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1071,7 +1071,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - if (entity1 == null) { - return false; - } else { -- // WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit -+ ServerLevel.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityType.getKey(entity1.getType()), entity1.getId(), EntityType.getKey(entity.getType()), entity.getId()); // CraftBukkit // Paper - return true; - } - } diff --git a/Remapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch b/Remapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch deleted file mode 100644 index b47c9efed4..0000000000 --- a/Remapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 16 Jul 2018 12:42:20 +0200 -Subject: [PATCH] Avoid item merge if stack size above max stack size - - -diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index de69f7c3c0ee1e74682b0db91bdaae09175690e9..70f719ba3c68c8e9414e6b4bc68002f7c962e2b9 100644 ---- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -208,6 +208,10 @@ public class ItemEntity extends Entity { - - private void mergeWithNeighbours() { - if (this.isMergable()) { -+ // Paper start - avoid item merge if stack size above max stack size -+ ItemStack stack = getItem(); -+ if (stack.getCount() >= stack.getMaxStackSize()) return; -+ // Paper end - // Spigot start - double radius = level.spigotConfig.itemMerge; - List list = this.level.getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(radius, radius, radius), (entityitem) -> { diff --git a/Remapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch b/Remapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch deleted file mode 100644 index fd4a4b705a..0000000000 --- a/Remapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Tue, 17 Jul 2018 16:42:17 +0200 -Subject: [PATCH] Use asynchronous Log4j 2 loggers - - -diff --git a/pom.xml b/pom.xml -index f5429f2f1979542fd93956d2f436d20d0e3a66b8..4c8a057e790c96b0ab5123549d0566371acacb46 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -88,6 +88,13 @@ - log4j-iostreams - compile - -+ -+ -+ com.lmax -+ disruptor -+ 3.4.2 -+ runtime -+ - - org.ow2.asm - asm -diff --git a/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java -new file mode 100644 -index 0000000000000000000000000000000000000000..db652a1f7abc80bc751fd94925abaec58ab1a563 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.log; -+ -+import org.apache.logging.log4j.Level; -+import org.apache.logging.log4j.core.async.AsyncQueueFullPolicy; -+import org.apache.logging.log4j.core.async.EventRoute; -+ -+public final class LogFullPolicy implements AsyncQueueFullPolicy { -+ -+ /* -+ * Prevents log calls being logged out of order when the log queue is full. -+ */ -+ -+ @Override -+ public EventRoute getRoute(final long backgroundThreadId, final Level level) { -+ return EventRoute.ENQUEUE; -+ } -+} -diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties -index 0694b21465fb9e4164e71862ff24b62241b191f2..30efeb5faf8e7faccf1b252fa0ed6a9fc31c40a7 100644 ---- a/src/main/resources/log4j2.component.properties -+++ b/src/main/resources/log4j2.component.properties -@@ -1 +1,3 @@ -+Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector -+log4j2.AsyncQueueFullPolicy="com.destroystokyo.paper.log.LogFullPolicy" - log4j.skipJansi=true diff --git a/Remapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch b/Remapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch deleted file mode 100644 index b0de783dec..0000000000 --- a/Remapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 19 Jul 2018 01:13:28 -0400 -Subject: [PATCH] add more information to Entity.toString() - -UUID, ticks lived, valid, dead - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 7e70bae5bc54ad17980789fa965fd539a7f193ea..e49fe2de6a53bdd16f0cd09b691f01f1866ffb4f 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2526,7 +2526,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public String toString() { -- return String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getName().getString(), this.id, this.level == null ? "~NULL~" : this.level.toString(), this.getX(), this.getY(), this.getZ()); -+ return String.format(Locale.ROOT, "%s['%s'/%d, uuid='%s', l='%s', x=%.2f, y=%.2f, z=%.2f, cx=%d, cz=%d, tl=%d, v=%b, d=%b]", new Object[] { this.getClass().getSimpleName(), this.getName().getString(), Integer.valueOf(this.id), this.uuid.toString(), this.level == null ? "~NULL~" : this.level.toString(), Double.valueOf(this.getX()), Double.valueOf(this.getY()), Double.valueOf(this.getZ()), xChunk, zChunk, this.tickCount, this.valid, this.removed}); // Paper - add more information - } - - public boolean isInvulnerableTo(DamageSource damageSource) { diff --git a/Remapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/Remapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch deleted file mode 100644 index be88eeb2df..0000000000 --- a/Remapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 21 Jul 2018 08:25:40 -0400 -Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues - -Add -Ddebug.entities=true to your JVM flags to gain more information - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 97d5437df10a6d0124e944404e88650547b7d8a8..083db6c1899b5391231b6d5d5044a334212f148c 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1145,6 +1145,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } else { - ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas()); - -+ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker - this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); - playerchunkmap_entitytracker.updatePlayers(this.level.players()); - if (entity instanceof ServerPlayer) { -@@ -1186,7 +1187,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - if (playerchunkmap_entitytracker1 != null) { - playerchunkmap_entitytracker1.broadcastRemoved(); - } -- -+ entity.tracker = null; // Paper - We're no longer tracked - } - - protected void tick() { -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 914241a57c304fde220bc546261d6e959445772a..a5d7781b13a6d61238d026f064512f7162e1e868 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -191,6 +191,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - public final LevelStorageSource.LevelStorageAccess convertable; - public final UUID uuid; - public boolean hasPhysicsEvent = true; // Paper -+ private static Throwable getAddToWorldStackTrace(Entity entity) { -+ return new Throwable(entity + " Added to world at " + new java.util.Date()); -+ } - - @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkSource.getChunk(x, z, false); -@@ -1032,8 +1035,28 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -- if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper -+ // Paper start -+ if (entity.valid) { -+ MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); -+ -+ if (DEBUG_ENTITIES) { -+ Throwable thr = entity.addedToWorldStack; -+ if (thr == null) { -+ MinecraftServer.LOGGER.error("Double add entity has no add stacktrace"); -+ } else { -+ MinecraftServer.LOGGER.error("Double add stacktrace: ", thr); -+ } -+ } -+ return true; -+ } -+ // Paper end - if (entity.removed) { -+ // Paper start -+ if (DEBUG_ENTITIES) { -+ new Throwable("Tried to add entity " + entity + " but it was marked as removed already").printStackTrace(); // CraftBukkit -+ getAddToWorldStackTrace(entity).printStackTrace(); -+ } -+ // Paper end - // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit - return false; - } else if (this.isUUIDUsed(entity)) { -@@ -1231,7 +1254,24 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - } - -- this.entitiesByUuid.put(entity.getUUID(), entity); -+ if (DEBUG_ENTITIES) { -+ entity.addedToWorldStack = getAddToWorldStackTrace(entity); -+ } -+ -+ Entity old = this.entitiesByUuid.put(entity.getUUID(), entity); -+ if (old != null && old.getId() != entity.getId() && old.valid) { -+ Logger logger = LogManager.getLogger(); -+ logger.error("Overwrote an existing entity " + old + " with " + entity); -+ if (DEBUG_ENTITIES) { -+ if (old.addedToWorldStack != null) { -+ old.addedToWorldStack.printStackTrace(); -+ } else { -+ logger.error("Oddly, the old entity was not added to the world in the normal way. Plugins?"); -+ } -+ entity.addedToWorldStack.printStackTrace(); -+ } -+ } -+ - this.getChunkSource().addEntity(entity); - // CraftBukkit start - SPIGOT-5278 - if (entity instanceof Drowned) { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index e49fe2de6a53bdd16f0cd09b691f01f1866ffb4f..9d8682d367522bd85894947ad2f2a53cf0aa123a 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -47,6 +47,7 @@ import net.minecraft.network.syncher.SynchedEntityData; - import net.minecraft.resources.ResourceKey; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.level.TicketType; -@@ -160,6 +161,8 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - -+ ChunkMap.TrackedEntity tracker; // Paper -+ public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { - bukkitEntity = CraftEntity.getEntity(level.getCraftServer(), this); -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index b4248d46ccb1a95e21601bca1198512287edcabf..0c6c3b211b05eda8f9ab47ef0a01cc520ae28201 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -121,6 +121,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public boolean pvpMode; - public boolean keepSpawnInMemory = true; - public org.bukkit.generator.ChunkGenerator generator; -+ public static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper - - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; diff --git a/Remapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch b/Remapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch deleted file mode 100644 index 14fc4f84c6..0000000000 --- a/Remapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:51:27 -0500 -Subject: [PATCH] EnderDragon Events - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java -index 0c2a5f5c4d7d7516793eba20205b5703fe1450d5..6b28cfb1e79903c43702f6e78e226dc78e3ccec2 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java -@@ -80,7 +80,11 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { - this.flame.setDuration(200); - this.flame.setParticle(ParticleTypes.DRAGON_BREATH); - this.flame.addEffect(new MobEffectInstance(MobEffects.HARM)); -+ if (new com.destroystokyo.paper.event.entity.EnderDragonFlameEvent((org.bukkit.entity.EnderDragon) this.dragon.getBukkitEntity(), (org.bukkit.entity.AreaEffectCloud) this.flame.getBukkitEntity()).callEvent()) { // Paper - this.dragon.level.addFreshEntity(this.flame); -+ } else { -+ this.removeAreaEffect(); -+ } - } - - } -@@ -91,8 +95,8 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { - ++this.flameCount; - } - -- @Override -- public void end() { -+ public final void removeAreaEffect() { this.end(); } // Paper - OBFHELPER -+ @Override public void end() { - if (this.flame != null) { - this.flame.remove(); - this.flame = null; -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java -index 01442af7b0c7340f0ece2fa0faa0f783b1b81c48..a43ef94f8a5c7a9d1581667beb4516cc26f30a0d 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java -@@ -81,7 +81,9 @@ public class DragonStrafePlayerPhase extends AbstractDragonPhaseInstance { - DragonFireball entitydragonfireball = new DragonFireball(this.dragon.level, this.dragon, d9, d10, d11); - - entitydragonfireball.moveTo(d6, d7, d8, 0.0F, 0.0F); -+ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) dragon.getBukkitEntity(), (org.bukkit.entity.DragonFireball) entitydragonfireball.getBukkitEntity()).callEvent()) // Paper - this.dragon.level.addFreshEntity(entitydragonfireball); -+ else entitydragonfireball.remove(); // Paper - this.fireballCharge = 0; - if (this.currentPath != null) { - while (!this.currentPath.isDone()) { -diff --git a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java -index 76dc15e07ce9ef01ad7908e289a0d695b65b2fc9..1629e409a83b11b76e1627247a838c9ebd11a648 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java -@@ -58,8 +58,10 @@ public class DragonFireball extends AbstractHurtingProjectile { - } - } - -+ if (new com.destroystokyo.paper.event.entity.EnderDragonFireballHitEvent((org.bukkit.entity.DragonFireball) this.getBukkitEntity(), list.stream().map(LivingEntity::getBukkitLivingEntity).collect(java.util.stream.Collectors.toList()), (org.bukkit.entity.AreaEffectCloud) entityareaeffectcloud.getBukkitEntity()).callEvent()) { // Paper - this.level.levelEvent(2006, this.blockPosition(), this.isSilent() ? -1 : 1); - this.level.addFreshEntity(entityareaeffectcloud); -+ } else entityareaeffectcloud.remove(); // Paper - this.remove(); - } - diff --git a/Remapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch b/Remapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch deleted file mode 100644 index be2454e01e..0000000000 --- a/Remapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:59:59 -0500 -Subject: [PATCH] PlayerElytraBoostEvent - - -diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -index dba52063d402eb2371441fa244b730a3313444fc..28cffbe299acccc59c34d5dbd2cf458704be5ee5 100644 ---- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -+++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -@@ -45,11 +45,16 @@ public class FireworkRocketItem extends Item { - // Paper start - final FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, itemstack, user); - entityfireworks.spawningEntity = user.getUUID(); -- world.addFreshEntity(entityfireworks); -- // Paper end -- if (!user.abilities.instabuild) { -- itemstack.shrink(1); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); -+ if (event.callEvent() && world.addFreshEntity(entityfireworks)) { -+ if (event.shouldConsume() && !user.abilities.instabuild) { -+ itemstack.shrink(1); -+ } else ((EntityPlayer) user).getBukkitEntity().updateInventory(); -+ } else if (user instanceof EntityPlayer) { -+ ((EntityPlayer) user).getBukkitEntity().updateInventory(); - } -+ // Paper end - } - - return InteractionResultHolder.sidedSuccess(user.getItemInHand(hand), world.isClientSide()); diff --git a/Remapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch b/Remapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch deleted file mode 100644 index 675f0c0360..0000000000 --- a/Remapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Wed, 30 Nov 2016 20:56:58 -0600 -Subject: [PATCH] Improve BlockPosition inlining - -Normally the JVM can inline virtual getters by having two sets of code, one is the 'optimized' code and the other is the 'deoptimized' code. -If a single type is used 99% of the time, then its worth it to inline, and to revert to 'deoptimized' the 1% of the time we encounter other types. -But if two types are encountered commonly, then the JVM can't inline them both, and the call overhead remains. - -This scenario also occurs with BlockPos and MutableBlockPos. -The variables in BlockPos are final, so MutableBlockPos can't modify them. -MutableBlockPos fixes this by adding custom mutable variables, and overriding the getters to access them. - -This approach with utility methods that operate on MutableBlockPos and BlockPos. -Specific examples are BlockPosition.up(), and World.isValidLocation(). -It makes these simple methods much slower than they need to be. - -This should result in an across the board speedup in anything that accesses blocks or does logic with positions. - -This is based upon conclusions drawn from inspecting the assenmbly generated bythe JIT compiler on my microbenchmarks. -They had 'callq' (invoke) instead of 'mov' (get from memory) instructions. - -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 6a58059a05e16d96894b67a544c2f595d9546c78..c5089b0da33a68e7cadbc4841b07f9d772d224a0 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -88,6 +88,7 @@ public class BlockPos extends Vec3i { - return asLong(this.getX(), this.getY(), this.getZ()); - } - -+ public static long asLong(int x, int y, int z) { return asLong(x, y, z); } // Paper - OBFHELPER - public static long asLong(int x, int y, int z) { - long l = 0L; - -diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java -index c22de593be404c4e921724bba6a69c13759a95fd..fc4e652ada7b228cb99a3c8fb372ae9af5ddfba4 100644 ---- a/src/main/java/net/minecraft/core/Vec3i.java -+++ b/src/main/java/net/minecraft/core/Vec3i.java -@@ -41,7 +41,7 @@ public class Vec3i implements Comparable { - this(Mth.floor(x), Mth.floor(y), Mth.floor(z)); - } - -- public boolean equals(Object object) { -+ public final boolean equals(Object object) { // Paper - if (this == object) { - return true; - } else if (!(object instanceof Vec3i)) { -@@ -53,7 +53,7 @@ public class Vec3i implements Comparable { - } - } - -- public int hashCode() { -+ public final int hashCode() { // Paper - return (this.getY() + this.getZ() * 31) * 31 + this.getX(); - } - -@@ -61,15 +61,15 @@ public class Vec3i implements Comparable { - return this.getY() == baseblockposition.getY() ? (this.getZ() == baseblockposition.getZ() ? this.getX() - baseblockposition.getX() : this.getZ() - baseblockposition.getZ()) : this.getY() - baseblockposition.getY(); - } - -- public int getX() { -+ public final int getX() { // Paper - return this.x; - } - -- public int getY() { -+ public final int getY() { // Paper - return this.y; - } - -- public int getZ() { -+ public final int getZ() { // Paper - return this.z; - } - diff --git a/Remapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch b/Remapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch deleted file mode 100644 index e8d895a808..0000000000 --- a/Remapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Mon, 23 Jul 2018 13:08:19 -0400 -Subject: [PATCH] Optimize RegistryID.c() - -This is a frequent hotspot for world loading/saving. - -diff --git a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java -index 66ad412e4368a8615cc66a97ac442c572813a3dd..fa4a2d29b3b4c20d7396e973801d69c4acadddda 100644 ---- a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java -+++ b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java -@@ -15,12 +15,14 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { - private K[] byId; - private int nextId; - private int size; -+ private java.util.BitSet usedIds; // Paper - - public CrudeIncrementalIntIdentityHashBiMap(int size) { - size = (int) ((float) size / 0.8F); - this.keys = (K[]) (new Object[size]); // Paper - decompile fix - this.values = new int[size]; - this.byId = (K[]) (new Object[size]); // Paper - decompile fix -+ this.usedIds = new java.util.BitSet(); // Paper - } - - // Paper start - decompile fix -@@ -52,9 +54,14 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { - } - - private int nextId() { -- while (this.nextId < this.byId.length && this.byId[this.nextId] != null) { -- ++this.nextId; -+ // Paper start -+ /* -+ while (this.e < this.d.length && this.d[this.e] != null) { -+ ++this.e; - } -+ */ -+ this.nextId = this.usedIds.nextClearBit(0); -+ // Paper end - - return this.nextId; - } -@@ -68,6 +75,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { - this.byId = (K[]) (new Object[newSize]); // Paper - decompile fix - this.nextId = 0; - this.size = 0; -+ this.usedIds.clear(); // Paper - - for (int j = 0; j < ak.length; ++j) { - if (ak[j] != null) { -@@ -93,6 +101,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { - this.keys[k] = value; - this.values[k] = id; - this.byId[id] = value; -+ this.usedIds.set(id); // Paper - ++this.size; - if (id == this.nextId) { - ++this.nextId; -@@ -157,6 +166,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { - Arrays.fill(this.byId, (Object) null); - this.nextId = 0; - this.size = 0; -+ this.usedIds.clear(); // Paper - } - - public int size() { diff --git a/Remapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/Remapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch deleted file mode 100644 index f39334e396..0000000000 --- a/Remapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 23 Jul 2018 12:57:39 +0200 -Subject: [PATCH] Option to prevent armor stands from doing entity lookups - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4813f62d1e382d5ac6971b2244df3f13c80d1950..3562950df4868b1393790b1a1ff1fe0dc589c155 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -379,4 +379,9 @@ public class PaperWorldConfig { - private void scanForLegacyEnderDragon() { - scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); - } -+ -+ public boolean armorStandEntityLookups = true; -+ private void armorStandEntityLookups() { -+ armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 59239e202e8e99870ce3be515d2f040ad9786892..7fc69adc8afa971ee3cf815c6002628ae2149a5b 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -352,6 +352,7 @@ public class ArmorStand extends LivingEntity { - - @Override - protected void pushEntities() { -+ if (!level.paperConfig.armorStandEntityLookups) return; // Paper - List list = this.level.getEntities(this, this.getBoundingBox(), ArmorStand.RIDABLE_MINECARTS); - - for (int i = 0; i < list.size(); ++i) { -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 0c6c3b211b05eda8f9ab47ef0a01cc520ae28201..7b135a3951bc168ccebdbb4e3acdc07397a820d3 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -39,6 +39,7 @@ import net.minecraft.world.DifficultyInstance; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.entity.decoration.ArmorStand; - import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; -@@ -854,6 +855,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - // Paper end - } - } -+ // Paper start - Prevent armor stands from doing entity lookups -+ @Override -+ public boolean noCollision(@Nullable Entity entity, AABB box) { -+ if (entity instanceof ArmorStand && !entity.level.paperConfig.armorStandEntityLookups) return false; -+ return LevelAccessor.super.noCollision(entity, box); -+ } -+ // Paper end - - public Explosion explode(@Nullable Entity entity, double x, double y, double z, float power, Explosion.BlockInteraction destructionType) { - return this.explode(entity, (DamageSource) null, (ExplosionDamageCalculator) null, x, y, z, power, false, destructionType); diff --git a/Remapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch b/Remapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch deleted file mode 100644 index f0b596c503..0000000000 --- a/Remapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch +++ /dev/null @@ -1,194 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 23 Jul 2018 14:22:26 +0200 -Subject: [PATCH] Vanished players don't have rights - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 9d8682d367522bd85894947ad2f2a53cf0aa123a..a2cc3e58d59ed3d9f443b77c44d8200cc09b4da9 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -183,7 +183,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - private static double viewScale = 1.0D; - private final EntityType type; - private int id; -- public boolean blocksBuilding; -+ public boolean blocksBuilding; public final boolean blocksEntitySpawning() { return this.blocksBuilding; } // Paper - OBFHELPER - public final List passengers; - protected int boardingCooldown; - @Nullable -diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index 16b554675a276471851846d4f2bea06fdcc166d9..d1dd173c11d751b15c3afd4309e386931fd9cf8d 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -5,6 +5,7 @@ import java.util.UUID; - import javax.annotation.Nullable; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -@@ -157,8 +158,14 @@ public abstract class Projectile extends Entity { - protected boolean canHitEntity(Entity entity) { - if (!entity.isSpectator() && entity.isAlive() && entity.isPickable()) { - Entity entity1 = this.getOwner(); -- -+ // Paper start - Cancel hit for vanished players -+ if (entity1 instanceof ServerPlayer && entity instanceof ServerPlayer) { -+ org.bukkit.entity.Player collided = (org.bukkit.entity.Player) entity.getBukkitEntity(); -+ org.bukkit.entity.Player shooter = (org.bukkit.entity.Player) entity1.getBukkitEntity(); -+ if (!shooter.canSee(collided)) return false; -+ } - return entity1 == null || this.leftOwner || !entity1.isPassengerOfSameVehicle(entity); -+ // Paper end - } else { - return false; - } -diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java -index 1ba89fa106dc24abf68d5d13c39a8d80f5582f1f..59522e367327224e5fe0fe2307858077ed812ba6 100644 ---- a/src/main/java/net/minecraft/world/item/BlockItem.java -+++ b/src/main/java/net/minecraft/world/item/BlockItem.java -@@ -174,7 +174,8 @@ public class BlockItem extends Item { - Player entityhuman = context.getPlayer(); - CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of((Entity) entityhuman); - // CraftBukkit start - store default return -- boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision); -+ Level world = context.getLevel(); // Paper -+ boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && world.checkEntityCollision(state, entityhuman, voxelshapecollision, context.getClickedPos(), true); // Paper - org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; - - BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn); -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 7b135a3951bc168ccebdbb4e3acdc07397a820d3..7a9ccd203885b9b369767d1fb8c53783201d0f0f 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -30,6 +30,7 @@ import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkHolder; - import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvent; - import net.minecraft.sounds.SoundSource; - import net.minecraft.tags.TagContainer; -@@ -69,6 +70,10 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; - import net.minecraft.world.level.storage.LevelData; - import net.minecraft.world.level.storage.WritableLevelData; - import net.minecraft.world.phys.AABB; -+import net.minecraft.world.phys.shapes.BooleanOp; -+import net.minecraft.world.phys.shapes.CollisionContext; -+import net.minecraft.world.phys.shapes.Shapes; -+import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.scores.Scoreboard; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -232,6 +237,46 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } - -+ // Paper start -+ // ret true if no collision -+ public final boolean checkEntityCollision(BlockState data, Entity source, CollisionContext voxelshapedcollision, -+ BlockPos position, boolean checkCanSee) { -+ // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape) -+ VoxelShape voxelshape = data.getCollisionShape(this, position, voxelshapedcollision); -+ if (voxelshape.isEmpty()) { -+ return true; -+ } -+ -+ voxelshape = voxelshape.offset((double) position.getX(), (double) position.getY(), (double) position.getZ()); -+ if (voxelshape.isEmpty()) { -+ return true; -+ } -+ -+ List entities = this.getEntities(null, voxelshape.bounds()); -+ for (int i = 0, len = entities.size(); i < len; ++i) { -+ Entity entity = entities.get(i); -+ -+ if (checkCanSee && source instanceof ServerPlayer && entity instanceof ServerPlayer -+ && !((ServerPlayer) source).getBukkitEntity().canSee(((ServerPlayer) entity).getBukkitEntity())) { -+ continue; -+ } -+ -+ // !entity1.dead && entity1.i && (entity == null || !entity1.x(entity)); -+ // elide the last check since vanilla calls with entity = null -+ // only we care about the source for the canSee check -+ if (entity.removed || !entity.blocksEntitySpawning()) { -+ continue; -+ } -+ -+ if (Shapes.applyOperation(voxelshape, Shapes.of(entity.getBoundingBox()), BooleanOp.AND)) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ // Paper end -+ - @Override - public boolean isClientSide() { - return this.isClientSide; -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index e6928557a79f51302975f2832ec911c2692eaaeb..5d7794c9533bd37193f196bda616adaaace2bbde 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -504,6 +504,7 @@ public abstract class BlockBehaviour { - return this.cache != null ? this.cache.collisionShape : this.getCollisionShape(world, pos, CollisionContext.empty()); - } - -+ public final VoxelShape getCollisionShape(BlockGetter iblockaccess, BlockPos blockposition, CollisionContext voxelshapecollision) { return this.getCollisionShape(iblockaccess, blockposition, voxelshapecollision); } // Paper - OBFHELPER - public VoxelShape getCollisionShape(BlockGetter world, BlockPos pos, CollisionContext context) { - return this.getBlock().getCollisionShape(this.asState(), world, pos, context); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -index 2371b52b450e2b43fa9b9549a91f853c702a9dc0..fa2942d0b0424390daee2121f8959034c5352e0b 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -@@ -45,6 +45,7 @@ public final class Shapes { - return create(new AABB(xMin, yMin, zMin, xMax, yMax, zMax)); - } - -+ public static final VoxelShape of(AABB axisAlignedbb) { return Shapes.create(axisAlignedbb); } // Paper - OBFHELPER - public static VoxelShape create(AABB box) { - int i = findBits(box.minX, box.maxX); - int j = findBits(box.minY, box.maxY); -@@ -139,6 +140,7 @@ public final class Shapes { - } - } - -+ public static final boolean applyOperation(VoxelShape voxelshape, VoxelShape voxelshape1, BooleanOp operatorboolean) { return Shapes.joinIsNotEmpty(voxelshape, voxelshape1, operatorboolean); } // Paper - OBFHELPER - public static boolean joinIsNotEmpty(VoxelShape shape1, VoxelShape shape2, BooleanOp predicate) { - if (predicate.apply(false, false)) { - throw (IllegalArgumentException) Util.pauseInIde((Throwable) (new IllegalArgumentException())); -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -index 026759567c58b5e7687ed1eec26fb4ffc60f9fa7..67ecdaada9f87304a9ae83d7917c7aca4676d195 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -@@ -54,6 +54,7 @@ public abstract class VoxelShape { - return this.shape.isEmpty(); - } - -+ public final VoxelShape offset(double x, double y, double z) { return this.move(x, y, z); } // Paper - OBFHELPER - public VoxelShape move(double x, double y, double z) { - return (VoxelShape) (this.isEmpty() ? Shapes.empty() : new ArrayVoxelShape(this.shape, new OffsetDoubleList(this.getCoords(Direction.Axis.X), x), new OffsetDoubleList(this.getCoords(Direction.Axis.Y), y), new OffsetDoubleList(this.getCoords(Direction.Axis.Z), z))); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index c2f58b95db41b2205fbf2728c6a99419c6a63dfa..4cd08821305590e21a01cc4dda05370c2b721ac2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1211,6 +1211,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); -+ -+ if (projectile.getShooter() instanceof Player && collided instanceof Player) { -+ if (!((Player) projectile.getShooter()).canSee((Player) collided)) { -+ event.setCancelled(true); -+ return event; -+ } -+ } -+ - Bukkit.getPluginManager().callEvent(event); - return event; - } diff --git a/Remapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch b/Remapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch deleted file mode 100644 index a8a2ab7437..0000000000 --- a/Remapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 23 Jul 2018 22:18:31 -0400 -Subject: [PATCH] Mark chunk dirty anytime entities change to guarantee it - saves - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index d69ccb1f31f31ebeee477df20ce1410f9e485eb7..bd9b19d988ecf72e099efeff6ec3483a352174ec 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -559,6 +559,7 @@ public class LevelChunk implements ChunkAccess { - entity.zChunk = this.chunkPos.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ this.markUnsaved(); // Paper - } - - @Override -@@ -587,6 +588,7 @@ public class LevelChunk implements ChunkAccess { - return; - } - entityCounts.decrement(entity.getMinecraftKeyString()); -+ this.markUnsaved(); // Paper - // Paper end - this.entities.remove(entity); // Paper - } diff --git a/Remapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch b/Remapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch deleted file mode 100644 index 1978f629cd..0000000000 --- a/Remapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 23 Jul 2018 22:44:23 -0400 -Subject: [PATCH] Add some Debug to Chunk Entity slices - -If we detect unexpected state, log and try to recover - -This should hopefully avoid duplicate entities ever being created -if the entity was to end up in 2 different chunk slices - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a2cc3e58d59ed3d9f443b77c44d8200cc09b4da9..7847078c54154e28ab066ea8a329f929df1e1a37 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -156,6 +156,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - } - }; -+ public List entitySlice = null; - // Paper end - - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index bd9b19d988ecf72e099efeff6ec3483a352174ec..09aa608bd303b618ae2c0ebd237bcbdba60a37a8 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -26,7 +26,9 @@ import net.minecraft.ReportedException; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Registry; - import net.minecraft.nbt.CompoundTag; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkHolder; -+import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; -@@ -550,6 +552,25 @@ public class LevelChunk implements ChunkAccess { - if (k >= this.entitySlices.length) { - k = this.entitySlices.length - 1; - } -+ // Paper - remove from any old list if its in one -+ List nextSlice = this.entitySlices[k]; // the next list to be added to -+ List currentSlice = entity.entitySlice; -+ if (nextSlice == currentSlice) { -+ if (Level.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity was already in this chunk!" + entity, new Throwable()); -+ return; // ??? silly plugins -+ } -+ if (currentSlice != null && currentSlice.contains(entity)) { -+ // Still in an old chunk... -+ if (Level.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity is still in another chunk!" + entity, new Throwable()); -+ LevelChunk chunk = entity.getCurrentChunk(); -+ if (chunk != null) { -+ chunk.removeEntity(entity); -+ } else { -+ removeEntity(entity); -+ } -+ currentSlice.remove(entity); // Just incase the above did not remove from the previous slice -+ } -+ // Paper end - - if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper - entity.inChunk = true; -@@ -559,6 +580,7 @@ public class LevelChunk implements ChunkAccess { - entity.zChunk = this.chunkPos.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ entity.entitySlice = this.entitySlices[k]; // Paper - this.markUnsaved(); // Paper - } - -@@ -584,6 +606,10 @@ public class LevelChunk implements ChunkAccess { - - // Paper start - if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); -+ if (entitySlices[section] == entity.entitySlice) { -+ entity.entitySlice = null; -+ entity.inChunk = false; -+ } - if (!this.entitySlices[section].remove(entity)) { - return; - } -@@ -742,7 +768,7 @@ public class LevelChunk implements ChunkAccess { - // Paper start - neighbour cache - int chunkX = this.chunkPos.x; - int chunkZ = this.chunkPos.z; -- ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); -+ ServerChunkCache chunkProvider = ((ServerLevel)this.world).getChunkSource(); - for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { - for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { - LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); -@@ -802,7 +828,7 @@ public class LevelChunk implements ChunkAccess { - // Paper start - neighbour cache - int chunkX = this.chunkPos.x; - int chunkZ = this.chunkPos.z; -- ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource(); -+ ServerChunkCache chunkProvider = ((ServerLevel)this.world).getChunkSource(); - for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { - for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { - LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); diff --git a/Remapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch b/Remapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch deleted file mode 100644 index 6599e06859..0000000000 --- a/Remapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 27 Jul 2018 22:36:31 -0500 -Subject: [PATCH] SkeletonHorse Additions - - -diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index a3bad391a719363077740aa810c9412df34b4ae5..e92a8c4c49c452e1f3f0c06398f2a74e3432262f 100644 ---- a/src/main/java/net/minecraft/world/entity/EntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -25,6 +25,7 @@ public final class EntitySelector { - public static final Predicate ATTACK_ALLOWED = (entity) -> { - return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative() && entity.level.getDifficulty() != Difficulty.PEACEFUL; - }; -+ public static Predicate notSpectator() { return NO_SPECTATORS; } // Paper - OBFHELPER - public static final Predicate NO_SPECTATORS = (entity) -> { - return !entity.isSpectator(); - }; -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java -index 7ef99acaa24525c68b1528bd3232738baab8e1c6..eaab482ae341ddda0754e726357cd845121fb043 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java -@@ -26,7 +26,7 @@ public class SkeletonHorse extends AbstractHorse { - - private final SkeletonTrapGoal skeletonTrapGoal = new SkeletonTrapGoal(this); - private boolean isTrap; -- private int trapTime; -+ private int trapTime; public int getTrapTime() { return this.trapTime; } // Paper - OBFHELPER - - public SkeletonHorse(EntityType type, Level world) { - super(type, world); -@@ -145,10 +145,12 @@ public class SkeletonHorse extends AbstractHorse { - return 0.96F; - } - -+ public boolean isTrap() { return this.isTrap(); } // Paper - OBFHELPER - public boolean isTrap() { - return this.isTrap; - } - -+ public void setTrap(boolean trap) { this.setTrap(trap); } // Paper - OBFHELPER - public void setTrap(boolean trapped) { - if (trapped != this.isTrap) { - this.isTrap = trapped; -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java -index 6c2cbaae2afe076c8b7bc53ffa91fe37e423d120..7f5fb28a7deabe1b62ed21e5ed1ea1ecca0d15b8 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java -@@ -14,10 +14,14 @@ import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; - import net.minecraft.world.item.enchantment.EnchantmentHelper; - import net.minecraft.world.level.Level; -+import org.bukkit.entity.HumanEntity; -+ -+import java.util.List; - - public class SkeletonTrapGoal extends Goal { - - private final SkeletonHorse horse; -+ private List eligiblePlayers; // Paper - - public SkeletonTrapGoal(SkeletonHorse skeletonHorse) { - this.horse = skeletonHorse; -@@ -25,12 +29,13 @@ public class SkeletonTrapGoal extends Goal { - - @Override - public boolean canUse() { -- return this.horse.level.hasNearbyAlivePlayer(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D); -+ return !(eligiblePlayers = this.horse.level.findNearbyBukkitPlayers(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D, false)).isEmpty(); // Paper - } - - @Override - public void tick() { - ServerLevel worldserver = (ServerLevel) this.horse.level; -+ if (!new com.destroystokyo.paper.event.entity.SkeletonHorseTrapEvent((org.bukkit.entity.SkeletonHorse) this.horse.getBukkitEntity(), eligiblePlayers).callEvent()) return; // Paper - DifficultyInstance difficultydamagescaler = worldserver.getCurrentDifficultyAt(this.horse.blockPosition()); - - this.horse.setTrap(false); -diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index 66681b9f0e2531d3da25629e44180417b32b4d66..6a5430fe54a5c8ad119a0f3842961825a54d8d7a 100644 ---- a/src/main/java/net/minecraft/world/level/EntityGetter.java -+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -1,6 +1,9 @@ - package net.minecraft.world.level; - -+import com.google.common.collect.ImmutableList; - import com.google.common.collect.Lists; -+import org.bukkit.entity.HumanEntity; -+ - import java.util.Iterator; - import java.util.List; - import java.util.UUID; -@@ -115,6 +118,28 @@ public interface EntityGetter { - return entityhuman; - } - -+ // Paper start -+ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, boolean notSpectator) { -+ return findNearbyBukkitPlayers(x, y, z, radius, notSpectator ? EntitySelector.notSpectator() : EntitySelector.canAITarget()); -+ } -+ -+ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate predicate) { -+ ImmutableList.Builder builder = ImmutableList.builder(); -+ -+ for (Player human : this.players()) { -+ if (predicate == null || predicate.test(human)) { -+ double distanceSquared = human.getDistanceSquared(x, y, z); -+ -+ if (radius < 0.0D || distanceSquared < radius * radius) { -+ builder.add(human.getBukkitEntity()); -+ } -+ } -+ } -+ -+ return builder.build(); -+ } -+ // Paper end -+ - @Nullable - default Player getNearestPlayer(Entity entity, double maxDistance) { - return this.getNearestPlayer(entity.getX(), entity.getY(), entity.getZ(), maxDistance, false); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -index b52ca4a612e30542ef4029cb1340f616bc4c36e6..7f984639fc2697cad9d0393467b0cb896d1e55a4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -@@ -25,4 +25,26 @@ public class CraftSkeletonHorse extends CraftAbstractHorse implements SkeletonHo - public Variant getVariant() { - return Variant.SKELETON_HORSE; - } -+ -+ // Paper start -+ @Override -+ public net.minecraft.world.entity.animal.horse.SkeletonHorse getHandle() { -+ return (net.minecraft.world.entity.animal.horse.SkeletonHorse) super.getHandle(); -+ } -+ -+ @Override -+ public int getTrapTime() { -+ return getHandle().getTrapTime(); -+ } -+ -+ @Override -+ public boolean isTrap() { -+ return getHandle().isTrap(); -+ } -+ -+ @Override -+ public void setTrap(boolean trap) { -+ getHandle().setTrap(trap); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch b/Remapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch deleted file mode 100644 index 946c608327..0000000000 --- a/Remapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 26 Jul 2018 00:11:12 -0400 -Subject: [PATCH] Prevent Saving Bad entities to chunks - -See https://github.com/PaperMC/Paper/issues/1223 - -Minecraft is saving invalid entities to the chunk files. - -Avoid saving bad data, and also make improvements to handle -loading these chunks. Any invalid entity will be instant killed, -so lets avoid adding it to the world... - -This lets us be safer about the dupe UUID resolver too, as now -we can ignore instant killed entities and avoid risk of duplicating -an invalid entity. - -This should reduce log occurrences of dupe uuid messages. - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index a5d7781b13a6d61238d026f064512f7162e1e868..8e8e5f30c512ed7d8ee987550c22d3e9df845043 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1151,6 +1151,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - List[] aentityslice = chunk.getEntitySlices(); // Spigot - int i = aentityslice.length; - -+ java.util.List toMoveChunks = new java.util.ArrayList<>(); // Paper - for (int j = 0; j < i; ++j) { - List entityslice = aentityslice[j]; // Spigot - Iterator iterator = entityslice.iterator(); -@@ -1163,11 +1164,25 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - throw (IllegalStateException) Util.pauseInIde((Throwable) (new IllegalStateException("Removing entity while ticking!"))); - } - -+ // Paper start - move out entities that shouldn't be in this chunk before it unloads -+ if (!entity.removed && (int) Math.floor(entity.getX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk.getPos().z) { -+ toMoveChunks.add(entity); -+ continue; -+ } -+ // Paper end -+ - this.entitiesById.remove(entity.getId()); - this.onEntityRemoved(entity); -+ -+ if (entity.removed) iterator.remove(); // Paper - don't save dead entities during unload - } - } - } -+ // Paper start - move out entities that shouldn't be in this chunk before it unloads -+ for (Entity entity : toMoveChunks) { -+ this.updateChunkPos(entity); -+ } -+ // Paper end - - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 0efaf4d0f58bcf38b427e76bf09b96e354294159..542d6f322df5f44ad9f504c8e14c88e3fa540657 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -27,6 +27,7 @@ import net.minecraft.nbt.LongArrayTag; - import net.minecraft.nbt.ShortTag; - import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.level.ThreadedLevelLightEngine; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -@@ -349,6 +350,7 @@ public class ChunkSerializer { - nbttagcompound1.put("TileEntities", nbttaglist1); - ListTag nbttaglist2 = new ListTag(); - -+ java.util.List toUpdate = new java.util.ArrayList<>(); // Paper - if (chunk.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { - LevelChunk chunk1 = (LevelChunk) chunk; - -@@ -366,13 +368,28 @@ public class ChunkSerializer { - while (iterator1.hasNext()) { - Entity entity = (Entity) iterator1.next(); - CompoundTag nbttagcompound4 = new CompoundTag(); -- -+ // Paper start -+ if ((int) Math.floor(entity.getX()) >> 4 != chunk1.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk1.getPos().z) { -+ toUpdate.add(entity); -+ continue; -+ } -+ if (entity.removed || hasPlayerPassenger(entity)) { -+ continue; -+ } -+ // Paper end - if (entity.save(nbttagcompound4)) { - chunk1.setLastSaveHadEntities(true); - nbttaglist2.add(nbttagcompound4); - } - } - } -+ -+ // Paper start - move entities to the correct chunk -+ for (Entity entity : toUpdate) { -+ world.updateChunkPos(entity); -+ } -+ // Paper end -+ - } else { - ProtoChunk protochunk = (ProtoChunk) chunk; - -@@ -431,6 +448,19 @@ public class ChunkSerializer { - nbttagcompound1.put("Structures", packStructureData(chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences())); - return nbttagcompound; - } -+ // Paper start - this is saved with the player -+ private static boolean hasPlayerPassenger(Entity entity) { -+ for (Entity passenger : entity.passengers) { -+ if (passenger instanceof ServerPlayer) { -+ return true; -+ } -+ if (hasPlayerPassenger(passenger)) { -+ return true; -+ } -+ } -+ return false; -+ } -+ // Paper end - - public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag tag) { - if (tag != null) { diff --git a/Remapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch b/Remapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch deleted file mode 100644 index 0133184a69..0000000000 --- a/Remapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Thu, 26 Jul 2018 14:10:23 +0200 -Subject: [PATCH] Don't call getItemMeta on hasItemMeta - -Spigot 1.13 checks if any field (which are manually copied from the ItemStack's "tag" NBT tag) on the ItemMeta class of an ItemStack is set. - -We could just check if the "tag" NBT tag is empty, albeit that would break some plugins. The only general tag added on 1.13 is "Damage", and we can just check if the "tag" NBT tag contains any other tag that's not "Damage" (https://minecraft.gamepedia.com/Player.dat_format#Item_structure) making the `hasItemStack` method behave as before. - -Returns true if getDamage() == 0 or has damage tag or other tag is set. -Check the `ItemMetaTest#testTaggedButNotMeta` method to see how this method behaves. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 44caf00330e4f4f74745973dbe709980f0b61269..9e06912b0c13c3d61bc95e526acaa28f96b46fb9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -569,7 +569,7 @@ public final class CraftItemStack extends ItemStack { - - @Override - public boolean hasItemMeta() { -- return hasItemMeta(handle) && !CraftItemFactory.instance().equals(getItemMeta(), null); -+ return hasItemMeta(handle) && (handle.getDamageValue() != 0 || (handle.getTag() != null && handle.getTag().tags.size() >= (handle.getTag().contains(CraftMetaItem.DAMAGE.NBT) ? 2 : 1))); // Paper - keep 1.12 CraftBukkit behavior without calling getItemMeta - } - - static boolean hasItemMeta(net.minecraft.world.item.ItemStack item) { -diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -index 42f577ed3508ba5a380648461e149f16ce97c9bd..b85a0a4c4f134dd6012d9141244ecf97b4300b65 100644 ---- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -@@ -96,6 +96,34 @@ public class ItemMetaTest extends AbstractTestingBase { - assertThat(itemMeta.hasConflictingEnchant(null), is(false)); - } - -+ // Paper start -+ private void testItemMeta(ItemStack stack) { -+ assertThat("Should not have ItemMeta", stack.hasItemMeta(), is(false)); -+ -+ stack.setDurability((short) 0); -+ assertThat("ItemStack with zero durability should not have ItemMeta", stack.hasItemMeta(), is(false)); -+ -+ stack.setDurability((short) 2); -+ assertThat("ItemStack with non-zero durability should have ItemMeta", stack.hasItemMeta(), is(true)); -+ -+ stack.setLore(java.util.Collections.singletonList("Lore")); -+ assertThat("ItemStack with lore and durability should have ItemMeta", stack.hasItemMeta(), is(true)); -+ -+ stack.setDurability((short) 0); -+ assertThat("ItemStack with lore should have ItemMeta", stack.hasItemMeta(), is(true)); -+ -+ stack.setLore(null); -+ } -+ -+ @Test -+ public void testHasItemMeta() { -+ ItemStack itemStack = new ItemStack(Material.SHEARS); -+ -+ testItemMeta(itemStack); -+ testItemMeta(CraftItemStack.asCraftCopy(itemStack)); -+ } -+ // Paper end -+ - @Test - public void testConflictingStoredEnchantment() { - EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) Bukkit.getItemFactory().getItemMeta(Material.ENCHANTED_BOOK); diff --git a/Remapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch b/Remapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch deleted file mode 100644 index ae6ea8935e..0000000000 --- a/Remapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 28 Jul 2018 12:18:27 -0400 -Subject: [PATCH] Ignore Dead Entities in entityList iteration - -A spigot change delays removal of entities from the entity list. -This causes a change in behavior from Vanilla where getEntities type -methods will return dead entities that they shouldn't otherwise be doing. - -This will ensure that dead entities are skipped from iteration since -they shouldn't of been in the list in the first place. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index e95b91cefb0374bd5bb57cc090f5ecd566d7a618..8fd716bf2e1402694798b8be03fd85821153be44 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -209,6 +209,7 @@ public class PaperCommand extends Command { - Collection entities = world.entitiesById.values(); - entities.forEach(e -> { - ResourceLocation key = e.getMinecraftKey(); -+ if (e.shouldBeRemoved) return; // Paper - - MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); - ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk); -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 8e8e5f30c512ed7d8ee987550c22d3e9df845043..84b2cd661697545186677ab7966556d9288c650b 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1303,6 +1303,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - entity.origin = entity.getBukkitEntity().getLocation(); - } - // Paper end -+ entity.shouldBeRemoved = false; // Paper - shouldn't be removed after being re-added - new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - } - -@@ -1315,6 +1316,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.removeFromChunk(entity); - this.entitiesById.remove(entity.getId()); - this.onEntityRemoved(entity); -+ entity.shouldBeRemoved = true; // Paper - } - } - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 7847078c54154e28ab066ea8a329f929df1e1a37..5bf6bc6a01ccde8a4d67b49293bb326cb09248d8 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -275,6 +275,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end -+ public boolean shouldBeRemoved; // Paper - - public float getBukkitYaw() { - return this.yRot; -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 09aa608bd303b618ae2c0ebd237bcbdba60a37a8..db28bfe95c885cdefa855c7aaa3bcf92bc52df26 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -862,6 +862,7 @@ public class LevelChunk implements ChunkAccess { - - for (int i1 = 0; i1 < l; ++i1) { - Entity entity1 = (Entity) list1.get(i1); -+ if (entity1.shouldBeRemoved) continue; // Paper - - if (entity1.getBoundingBox().intersects(box) && entity1 != except) { - if (predicate == null || predicate.test(entity1)) { -@@ -899,6 +900,7 @@ public class LevelChunk implements ChunkAccess { - - while (iterator.hasNext()) { - T entity = (T) iterator.next(); // CraftBukkit - decompile error -+ if (entity.shouldBeRemoved) continue; // Paper - - if ((type == null || entity.getType() == type) && entity.getBoundingBox().intersects(box) && predicate.test(entity)) { - result.add(entity); -@@ -921,6 +923,7 @@ public class LevelChunk implements ChunkAccess { - - while (iterator.hasNext()) { - T t0 = (T) iterator.next(); // CraftBukkit - decompile error -+ if (t0.shouldBeRemoved) continue; // Paper - - if (entityClass.isInstance(t0) && t0.getBoundingBox().intersects(box) && (predicate == null || predicate.test(t0))) { // Spigot - instance check - result.add(t0); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 3a3466cd9bbd34dbc0b79567f5579e84a81d6009..9807612aed6c4393cbe1f4b6078e45bf1ba3deb2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1022,6 +1022,7 @@ public class CraftWorld implements World { - for (Object o : world.entitiesById.values()) { - if (o instanceof net.minecraft.world.entity.Entity) { - net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; -+ if (mcEnt.shouldBeRemoved) continue; // Paper - Entity bukkitEntity = mcEnt.getBukkitEntity(); - - // Assuming that bukkitEntity isn't null -@@ -1041,6 +1042,7 @@ public class CraftWorld implements World { - for (Object o : world.entitiesById.values()) { - if (o instanceof net.minecraft.world.entity.Entity) { - net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; -+ if (mcEnt.shouldBeRemoved) continue; // Paper - Entity bukkitEntity = mcEnt.getBukkitEntity(); - - // Assuming that bukkitEntity isn't null -@@ -1067,6 +1069,7 @@ public class CraftWorld implements World { - - for (Object entity: world.entitiesById.values()) { - if (entity instanceof net.minecraft.world.entity.Entity) { -+ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper - Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); - - if (bukkitEntity == null) { -@@ -1090,6 +1093,7 @@ public class CraftWorld implements World { - - for (Object entity: world.entitiesById.values()) { - if (entity instanceof net.minecraft.world.entity.Entity) { -+ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper - Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); - - if (bukkitEntity == null) { diff --git a/Remapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch b/Remapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch deleted file mode 100644 index 4909987c8f..0000000000 --- a/Remapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: willies952002 -Date: Thu, 26 Jul 2018 02:25:46 -0400 -Subject: [PATCH] Implement Expanded ArmorStand API - -Add the following: -- Add proper methods for getting and setting items in both hands. Deprecates old methods -- Enable/Disable slot interactions - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 7fc69adc8afa971ee3cf815c6002628ae2149a5b..06e52a0c5decf717e35c605d6bcb46c3c7b29656 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -426,6 +426,7 @@ public class ArmorStand extends LivingEntity { - return enumitemslot; - } - -+ public final boolean isSlotDisabled(net.minecraft.world.entity.EquipmentSlot slot) { return this.isDisabled(slot); } // Paper - OBFHELPER - private boolean isDisabled(net.minecraft.world.entity.EquipmentSlot slot) { - return (this.disabledSlots & 1 << slot.getFilterFlag()) != 0 || slot.getType() == net.minecraft.world.entity.EquipmentSlot.Type.HAND && !this.isShowArms(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 16f996d505b96da8a40c7709214ebbd2a0d0d9f3..d4da5214a39b718671dcaf687cb0ff8668ce9728 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -238,5 +238,78 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public void setCanMove(boolean move) { - getHandle().canMove = move; - } -+ -+ @Override -+ public ItemStack getItem(org.bukkit.inventory.EquipmentSlot slot) { -+ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); -+ return getHandle().getItemBySlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)).asBukkitMirror(); -+ } -+ -+ @Override -+ public void setItem(org.bukkit.inventory.EquipmentSlot slot, ItemStack item) { -+ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); -+ switch (slot) { -+ case HAND: -+ getEquipment().setItemInMainHand(item); -+ return; -+ case OFF_HAND: -+ getEquipment().setItemInOffHand(item); -+ return; -+ case FEET: -+ setBoots(item); -+ return; -+ case LEGS: -+ setLeggings(item); -+ return; -+ case CHEST: -+ setChestplate(item); -+ return; -+ case HEAD: -+ setHelmet(item); -+ return; -+ } -+ throw new UnsupportedOperationException(slot.name()); -+ } -+ -+ @Override -+ public java.util.Set getDisabledSlots() { -+ java.util.Set disabled = new java.util.HashSet<>(); -+ for (org.bukkit.inventory.EquipmentSlot slot : org.bukkit.inventory.EquipmentSlot.values()) { -+ if (this.isSlotDisabled(slot)) { -+ disabled.add(slot); -+ } -+ } -+ return disabled; -+ } -+ -+ @Override -+ public void setDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { -+ int disabled = 0; -+ for (org.bukkit.inventory.EquipmentSlot slot : slots) { -+ if (slot == org.bukkit.inventory.EquipmentSlot.OFF_HAND) continue; -+ net.minecraft.world.entity.EquipmentSlot nmsSlot = org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot); -+ disabled += (1 << nmsSlot.getFilterFlag()) + (1 << (nmsSlot.getFilterFlag() + 8)) + (1 << (nmsSlot.getFilterFlag() + 16)); -+ } -+ getHandle().disabledSlots = disabled; -+ } -+ -+ @Override -+ public void addDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { -+ java.util.Set disabled = getDisabledSlots(); -+ java.util.Collections.addAll(disabled, slots); -+ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); -+ } -+ -+ @Override -+ public void removeDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { -+ java.util.Set disabled = getDisabledSlots(); -+ for (final org.bukkit.inventory.EquipmentSlot slot : slots) disabled.remove(slot); -+ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); -+ } -+ -+ @Override -+ public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { -+ return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch b/Remapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch deleted file mode 100644 index 8e4a474184..0000000000 --- a/Remapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 20 Jul 2018 23:37:03 -0500 -Subject: [PATCH] AnvilDamageEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java -index aa4b03dc9a0d6b3f387f081a1887672b90c60ef9..3d53edae7e3d5bb00913384ad0eb67551a65750e 100644 ---- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java -@@ -80,7 +80,16 @@ public class AnvilMenu extends ItemCombinerMenu { - - if (!player.abilities.instabuild && iblockdata.is((Tag) BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { - BlockState iblockdata1 = AnvilBlock.damage(iblockdata); -- -+ // Paper start -+ com.destroystokyo.paper.event.block.AnvilDamagedEvent event = new com.destroystokyo.paper.event.block.AnvilDamagedEvent(getBukkitView(), iblockdata1 != null ? org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(iblockdata1) : null); -+ if (!event.callEvent()) { -+ return; -+ } else if (event.getDamageState() == com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState.BROKEN) { -+ iblockdata1 = null; -+ } else { -+ iblockdata1 = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getDamageState().getMaterial().createBlockData()).getState().setValue(AnvilBlock.FACING, iblockdata.getValue(AnvilBlock.FACING)); -+ } -+ // Paper end - if (iblockdata1 == null) { - world.removeBlock(blockposition, false); - world.levelEvent(1029, blockposition, 0); diff --git a/Remapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch b/Remapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch deleted file mode 100644 index 812624262a..0000000000 --- a/Remapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Mon, 16 Jul 2018 00:05:05 +0300 -Subject: [PATCH] Add TNTPrimeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index ae3cf71f14526e1f356216dfaa899c8f5083d46d..37a9e9df7f7f816c214c37e545288bf9329626ed 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -61,6 +61,7 @@ import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.event.entity.EntityExplodeEvent; - import org.bukkit.event.entity.EntityRegainHealthEvent; - // CraftBukkit end -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - - public class EnderDragon extends Mob implements Enemy { - -@@ -515,6 +516,11 @@ public class EnderDragon extends Mob implements Enemy { - }); - craftBlock.getNMS().spawnAfterBreak((ServerLevel) level, blockposition, ItemStack.EMPTY); - } -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = level.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, explosionSource.getSourceMob().getBukkitEntity()).callEvent()) -+ continue; -+ // Paper end - nmsBlock.wasExploded(level, blockposition, explosionSource); - - this.level.removeBlock(blockposition, false); -diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java -index 85170008de6e77cfb8e4f55ae440a8428d868af4..31b6c1333c7d0af28385e804e94348cef398748b 100644 ---- a/src/main/java/net/minecraft/world/level/block/FireBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java -@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; - import com.google.common.collect.ImmutableMap; - import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - import java.util.Map; - import java.util.Random; - import java.util.function.Function; -@@ -11,6 +12,7 @@ import net.minecraft.Util; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; - import net.minecraft.core.Vec3i; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.item.context.BlockPlaceContext; - import net.minecraft.world.level.BlockGetter; -@@ -288,7 +290,7 @@ public class FireBlock extends BaseFireBlock { - - world.setBlock(blockposition, this.getStateWithAge(world, blockposition, l), 3); - } else { -- world.removeBlock(blockposition, false); -+ if(iblockdata.getBlock() != Blocks.TNT) world.removeBlock(blockposition, false); // Paper - TNTPrimeEvent - We might be cancelling it below, move the setAir down - } - - Block block = iblockdata.getBlock(); -@@ -296,6 +298,13 @@ public class FireBlock extends BaseFireBlock { - if (block instanceof TntBlock) { - TntBlock blocktnt = (TntBlock) block; - -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = MCUtil.toBukkitBlock(world, blockposition); -+ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.FIRE, null).callEvent()) { -+ return; -+ } -+ world.setAir(blockposition, false); -+ // Paper end - TntBlock.explode(world, blockposition); - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/TntBlock.java b/src/main/java/net/minecraft/world/level/block/TntBlock.java -index 5c06e2f69f6c0a03f12fab6accc5f9a79ae37118..76665be4b3f2e2821c35d3d6d6407c4da4f224e7 100644 ---- a/src/main/java/net/minecraft/world/level/block/TntBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/TntBlock.java -@@ -22,6 +22,7 @@ import net.minecraft.world.level.block.state.StateDefinition; - import net.minecraft.world.level.block.state.properties.BlockStateProperties; - import net.minecraft.world.level.block.state.properties.BooleanProperty; - import net.minecraft.world.phys.BlockHitResult; -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - - public class TntBlock extends Block { - -@@ -36,6 +37,11 @@ public class TntBlock extends Block { - public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { - if (!oldState.is(state.getBlock())) { - if (world.hasNeighborSignal(pos)) { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos);; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) -+ return; -+ // Paper end - explode(world, pos); - world.removeBlock(pos, false); - } -@@ -46,6 +52,11 @@ public class TntBlock extends Block { - @Override - public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { - if (world.hasNeighborSignal(pos)) { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos);; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) -+ return; -+ // Paper end - explode(world, pos); - world.removeBlock(pos, false); - } -@@ -64,6 +75,12 @@ public class TntBlock extends Block { - @Override - public void wasExploded(Level world, BlockPos pos, Explosion explosion) { - if (!world.isClientSide) { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos); -+ org.bukkit.entity.Entity source = explosion.source != null ? explosion.source.getBukkitEntity() : null; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) -+ return; -+ // Paper end - PrimedTnt entitytntprimed = new PrimedTnt(world, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, explosion.getSourceMob()); - - entitytntprimed.setFuse((short) (world.random.nextInt(entitytntprimed.getLife() / 4) + entitytntprimed.getLife() / 8)); -@@ -92,6 +109,11 @@ public class TntBlock extends Block { - if (item != Items.FLINT_AND_STEEL && item != Items.FIRE_CHARGE) { - return super.use(state, world, pos, player, hand, hit); - } else { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos); -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.ITEM, player.getBukkitEntity()).callEvent()) -+ return InteractionResult.FAIL; -+ // Paper end - explode(world, pos, (LivingEntity) player); - world.setBlock(pos, Blocks.AIR.defaultBlockState(), 11); - if (!player.isCreative()) { -@@ -121,6 +143,13 @@ public class TntBlock extends Block { - } - // CraftBukkit end - -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); -+ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.PROJECTILE, projectile.getBukkitEntity()).callEvent()) { -+ return; -+ } -+ // Paper end -+ - explode(world, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null); - world.removeBlock(blockposition, false); - } diff --git a/Remapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch b/Remapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch deleted file mode 100644 index a6f013522a..0000000000 --- a/Remapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 29 Jul 2018 05:02:15 +0100 -Subject: [PATCH] Break up and make tab spam limits configurable - -Due to the changes in 1.13, clients will send a tab completion request -for all bukkit commands in order to factor in the lack of support for -brigadier and provide backwards support in the API. - -Craftbukkit, however; has moved the chat spam limiter to also interact -with the tab completion request, which while good for avoiding abuse, -causes 1.13 clients to easilly be kicked from a server in bukkit due -to this. Removing the spam limit could cause issues for servers, however, -there is no way for servers to manipulate this without blindly cancelling -kick events, which only causes additional complications. This also causes -issues in that the tab spam limit and chat share the same field but different -limits, meaning that a player having typed a long command may be kicked from -the server. - -Splitting the field up and making it configurable allows for server owners -to take the burden of this into their own hand without having to rely on -plugins doing unsafe things. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 77a03abd59db4a43f6f2d59d4c7ef176e782f205..bd508025b771424c942fd856c31d520b6f548082 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -296,4 +296,18 @@ public class PaperConfig { - Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); - } - } -+ -+ public static int tabSpamIncrement = 1; -+ public static int tabSpamLimit = 500; -+ private static void tabSpamLimiters() { -+ tabSpamIncrement = getInt("settings.spam-limiter.tab-spam-increment", tabSpamIncrement); -+ // Older versions used a smaller limit, which is too low for 1.13, we'll bump this up if default -+ if (version < 14) { -+ if (tabSpamIncrement == 10) { -+ set("settings.spam-limiter.tab-spam-increment", 2); -+ tabSpamIncrement = 2; -+ } -+ } -+ tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 645f7b7c862acf77d70ca0b05308945424bc4d32..900c9b1106a153bc386f6c3d9c11226f8ac69f86 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -228,6 +228,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // CraftBukkit start - multithreaded fields - private volatile int chatSpamTickCount; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(ServerGamePacketListenerImpl.class, "chatThrottle"); -+ private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits - // CraftBukkit end - private int dropSpamTickCount; - private final Int2ShortMap expectedAcks = new Int2ShortOpenHashMap(); -@@ -363,6 +364,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - this.server.getProfiler().pop(); - // CraftBukkit start - for (int spam; (spam = this.chatSpamTickCount) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; -+ if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable - /* Use thread-safe field access instead - if (this.chatThrottle > 0) { - --this.chatThrottle; -@@ -714,7 +716,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { - // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async - // CraftBukkit start -- if (chatSpamField.addAndGet(this, 1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { -+ if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable - server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper - return; - } diff --git a/Remapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch b/Remapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch deleted file mode 100644 index 80b6896fe7..0000000000 --- a/Remapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch +++ /dev/null @@ -1,341 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Thu, 2 Aug 2018 08:44:35 -0500 -Subject: [PATCH] Add hand to bucket events - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index d34da1eb172a7dcda564680afecf3dc145bf09f3..125a75576442eaa4f1ff6dd153bdb31097497a3f 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -724,7 +724,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop cachedSingleHashSet; // Paper - - public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { -- super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); -+ super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); - this.respawnDimension = Level.OVERWORLD; - interactionManager.player = this; - this.gameMode = interactionManager; -@@ -254,7 +254,7 @@ public class ServerPlayer extends Player implements ContainerListener { - // Yes, this doesn't match Vanilla, but it's the best we can do for now. - // If this is an issue, PRs are welcome - public final BlockPos getSpawnPoint(ServerLevel worldserver) { -- BlockPos blockposition = worldserver.getSharedSpawnPos(); -+ BlockPos blockposition = worldserver.getSpawn(); - - if (worldserver.dimensionType().hasSkyLight() && worldserver.worldDataServer.getGameType() != GameType.ADVENTURE) { - int i = Math.max(0, this.server.getSpawnRadius(worldserver)); -@@ -291,7 +291,7 @@ public class ServerPlayer extends Player implements ContainerListener { - // CraftBukkit end - - private void fudgeSpawnLocation(ServerLevel world) { -- BlockPos blockposition = world.getSharedSpawnPos(); -+ BlockPos blockposition = world.getSpawn(); - - if (world.dimensionType().hasSkyLight() && world.worldDataServer.getGameType() != GameType.ADVENTURE) { // CraftBukkit - int i = Math.max(0, this.server.getSpawnRadius(world)); -@@ -464,7 +464,7 @@ public class ServerPlayer extends Player implements ContainerListener { - } - if (world == null || position == null) { - world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(); -- position = Vec3.atCenterOf(((ServerLevel) world).getSharedSpawnPos()); -+ position = Vec3.atCenterOf(((ServerLevel) world).getSpawn()); - } - this.level = world; - this.setPos(position.x(), position.y(), position.z()); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 51b1ce465d23b971f7e08a3175319a33183d0398..0bb397407b55bd1c464ac603ec4c189045aabbb2 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -808,7 +808,7 @@ public abstract class PlayerList { - entityplayer1.setShiftKeyDown(false); - - // entityplayer1.playerConnection.a(entityplayer1.locX(), entityplayer1.locY(), entityplayer1.locZ(), entityplayer1.yaw, entityplayer1.pitch); -- entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSharedSpawnPos(), worldserver1.getSharedSpawnAngle())); -+ entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSpawn(), worldserver1.getSharedSpawnAngle())); - entityplayer1.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); - entityplayer1.connection.send(new ClientboundSetExperiencePacket(entityplayer1.experienceProgress, entityplayer1.totalExperience, entityplayer1.experienceLevel)); - this.sendLevelInfo(entityplayer1, worldserver1); -@@ -1090,7 +1090,7 @@ public abstract class PlayerList { - - player.connection.send(new ClientboundSetBorderPacket(worldborder, ClientboundSetBorderPacket.Type.INITIALIZE)); - player.connection.send(new ClientboundSetTimePacket(world.getGameTime(), world.getDayTime(), world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); -- player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(world.getSharedSpawnPos(), world.getSharedSpawnAngle())); -+ player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(world.getSpawn(), world.getSharedSpawnAngle())); - if (world.isRaining()) { - // CraftBukkit start - handle player weather - // entityplayer.playerConnection.sendPacket(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.b, 0.0F)); -diff --git a/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java b/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java -index c283ea9528493fb95088870c84c6d6e3963aabb7..2633aca30601682a53b0236b94a12f0f18a87fc2 100644 ---- a/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java -+++ b/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java -@@ -33,7 +33,7 @@ public class RconConsoleSource implements CommandSource { - public CommandSourceStack createCommandSourceStack() { - ServerLevel worldserver = this.server.overworld(); - -- return new CommandSourceStack(this, Vec3.atLowerCornerOf((Vec3i) worldserver.getSharedSpawnPos()), Vec2.ZERO, worldserver, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null); -+ return new CommandSourceStack(this, Vec3.atLowerCornerOf((Vec3i) worldserver.getSpawn()), Vec2.ZERO, worldserver, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null); - } - - // CraftBukkit start - Send a String -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 5bf6bc6a01ccde8a4d67b49293bb326cb09248d8..4503bd65b3454bad94bb7b869f4e72e3121d8a3d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2688,7 +2688,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - if (flag1) { - blockposition1 = ServerLevel.END_SPAWN_POINT; - } else { -- blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos()); -+ blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSpawn()); - } - // CraftBukkit start - CraftPortalEvent event = callPortalEvent(this, destination, blockposition1, PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); -diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java -index 90393bb196c0895f387259c2dccbb29e2ca11c87..9c67b603d4d0ee5cb7f86b25ed8754afaf9cf7b3 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Cow.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Cow.java -@@ -87,7 +87,7 @@ public class Cow extends Animal { - - if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) { - // CraftBukkit start - Got milk? -- org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET); -+ org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); // Paper - add enumHand - - if (event.isCancelled()) { - return InteractionResult.PASS; -diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java -index b426e155d13a1b2eb5ddb24a2d83cd7d1e92026b..d0e847e58483695d2af1c1410826bb25231cd6f6 100644 ---- a/src/main/java/net/minecraft/world/item/BucketItem.java -+++ b/src/main/java/net/minecraft/world/item/BucketItem.java -@@ -69,7 +69,7 @@ public class BucketItem extends Item { - if (iblockdata.getBlock() instanceof BucketPickup) { - // CraftBukkit start - Fluid dummyFluid = ((BucketPickup) iblockdata.getBlock()).takeLiquid(DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); -- PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getBucket()); -+ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getBucket(), hand); // Paper - add enumhand - - if (event.isCancelled()) { - ((ServerPlayer) user).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) -@@ -97,7 +97,7 @@ public class BucketItem extends Item { - iblockdata = world.getBlockState(blockposition); - BlockPos blockposition2 = iblockdata.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockposition : blockposition1; - -- if (this.a(user, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack)) { // CraftBukkit -+ if (this.a(user, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack, hand)) { // CraftBukkit // Paper - add enumhand - this.checkExtraContent(world, itemstack, blockposition2); - if (user instanceof ServerPlayer) { - CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) user, blockposition2, itemstack); -@@ -122,10 +122,12 @@ public class BucketItem extends Item { - public void checkExtraContent(Level world, ItemStack stack, BlockPos pos) {} - - public boolean emptyBucket(@Nullable Player player, Level world, BlockPos pos, @Nullable BlockHitResult movingobjectpositionblock) { -- return a(player, world, pos, movingobjectpositionblock, null, null, null); -+ // Paper start - add enumHand -+ return a(player, world, pos, movingobjectpositionblock, null, null, null, null); - } - -- public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack) { -+ public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, InteractionHand enumhand) { -+ // Paper end - // CraftBukkit end - if (!(this.content instanceof FlowingFluid)) { - return false; -@@ -138,7 +140,7 @@ public class BucketItem extends Item { - - // CraftBukkit start - if (flag1 && entityhuman != null) { -- PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack); -+ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); // Paper - add enumhand - if (event.isCancelled()) { - ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity - ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 -@@ -147,7 +149,7 @@ public class BucketItem extends Item { - } - // CraftBukkit end - if (!flag1) { -- return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack); // CraftBukkit -+ return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit // Paper - add enumhand - } else if (world.dimensionType().ultraWarm() && this.content.is((Tag) FluidTags.WATER)) { - int i = blockposition.getX(); - int j = blockposition.getY(); -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 7a9ccd203885b9b369767d1fb8c53783201d0f0f..b75ffafb6840b6acab6e5b0ef5e222c4fa130977 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -277,6 +277,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - // Paper end - -+ // Paper start - moved up from WorldServer -+ public BlockPos getSpawn() { -+ BlockPos blockposition = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn()); -+ -+ if (!this.getWorldBorder().isWithinBounds(blockposition)) { -+ blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, new BlockPos(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); -+ } -+ -+ return blockposition; -+ } -+ // Paper end - @Override - public boolean isClientSide() { - return this.isClientSide; -diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 8a71eaf2855be0d415d1f7b18dbec98353fe5b47..b90a275a0dc2913809ce16659eed445501e486de 100644 ---- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java -+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -268,7 +268,7 @@ public final class NaturalSpawner { - private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) { - if (squaredDistance <= 576.0D) { - return false; -- } else if (world.getSharedSpawnPos().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D)) { -+ } else if (world.getSpawn().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D)) { - return false; - } else { - ChunkPos chunkcoordintpair = new ChunkPos(pos); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 9807612aed6c4393cbe1f4b6078e45bf1ba3deb2..159c32d6678e83f2d98ea6a1ad48346c9de017e1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -327,7 +327,7 @@ public class CraftWorld implements World { - - @Override - public Location getSpawnLocation() { -- BlockPos spawn = world.getSharedSpawnPos(); -+ BlockPos spawn = world.getSpawn(); - return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); - } - -@@ -1926,7 +1926,7 @@ public class CraftWorld implements World { - public void setKeepSpawnInMemory(boolean keepLoaded) { - world.keepSpawnInMemory = keepLoaded; - // Grab the worlds spawn chunk -- BlockPos chunkcoordinates = this.world.getSharedSpawnPos(); -+ BlockPos chunkcoordinates = this.world.getSpawn(); - if (keepLoaded) { - world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); - } else { -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 4cd08821305590e21a01cc4dda05370c2b721ac2..1877267344df1ff5b4de6a4e0c239f488cd52c1f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -222,7 +222,7 @@ public class CraftEventFactory { - public static Entity entityDamage; // For use in EntityDamageByEntityEvent - - // helper methods -- private static boolean canBuild(ServerLevel world, Player player, int x, int z) { -+ private static boolean canBuild(Level world, Player player, int x, int z) { - int spawnSize = Bukkit.getServer().getSpawnRadius(); - - if (world.dimension() != Level.OVERWORLD) return true; -@@ -230,7 +230,7 @@ public class CraftEventFactory { - if (((CraftServer) Bukkit.getServer()).getHandle().getOps().isEmpty()) return true; - if (player.isOp()) return true; - -- BlockPos chunkcoordinates = world.getSharedSpawnPos(); -+ BlockPos chunkcoordinates = world.getSpawn(); - - int distanceFromSpawn = Math.max(Math.abs(x - chunkcoordinates.getX()), Math.abs(z - chunkcoordinates.getZ())); - return distanceFromSpawn > spawnSize; -@@ -412,6 +412,20 @@ public class CraftEventFactory { - } - - private static PlayerEvent getPlayerBucketEvent(boolean isFilling, ServerLevel world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item) { -+ // Paper start - add enumHand -+ return getPlayerBucketEvent(isFilling, world, who, changed, clicked, clickedFace, itemstack, item, null); -+ } -+ -+ public static PlayerBucketEmptyEvent callPlayerBucketEmptyEvent(Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, InteractionHand enumHand) { -+ return (PlayerBucketEmptyEvent) getPlayerBucketEvent(false, world, who, changed, clicked, clickedFace, itemstack, Items.BUCKET, enumHand); -+ } -+ -+ public static PlayerBucketFillEvent callPlayerBucketFillEvent(Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemInHand, net.minecraft.world.item.Item bucket, InteractionHand enumHand) { -+ return (PlayerBucketFillEvent) getPlayerBucketEvent(true, world, who, clicked, changed, clickedFace, itemInHand, bucket, enumHand); -+ } -+ -+ private static PlayerEvent getPlayerBucketEvent(boolean isFilling, Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item, InteractionHand enumHand) { -+ // Paper end - Player player = (Player) who.getBukkitEntity(); - CraftItemStack itemInHand = CraftItemStack.asNewCraftStack(item); - Material bucket = CraftMagicNumbers.getMaterial(itemstack.getItem()); -@@ -424,10 +438,10 @@ public class CraftEventFactory { - - PlayerEvent event; - if (isFilling) { -- event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand); -+ event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand - ((PlayerBucketFillEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); - } else { -- event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand); -+ event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand - ((PlayerBucketEmptyEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); - } - diff --git a/Remapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch b/Remapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch deleted file mode 100644 index 07dc1c1b3f..0000000000 --- a/Remapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 3 Aug 2018 00:04:54 -0400 -Subject: [PATCH] MC-135506: Experience should save as Integers - - -diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index 52b90ef3a145325209d3d903a2b7c9a44c332cbe..37758cff3c4a8406c2f1496ae827ecdc953cf9f4 100644 ---- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -217,7 +217,7 @@ public class ExperienceOrb extends Entity { - public void addAdditionalSaveData(CompoundTag tag) { - tag.putShort("Health", (short) this.health); - tag.putShort("Age", (short) this.age); -- tag.putShort("Value", (short) this.value); -+ tag.putInt("Value", this.value); // Paper - save as Integer - this.savePaperNBT(tag); // Paper - } - -@@ -225,7 +225,7 @@ public class ExperienceOrb extends Entity { - public void readAdditionalSaveData(CompoundTag tag) { - this.health = tag.getShort("Health"); - this.age = tag.getShort("Age"); -- this.value = tag.getShort("Value"); -+ this.value = tag.getInt("Value"); // Paper - load as Integer - this.loadPaperNBT(tag); // Paper - } - diff --git a/Remapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch b/Remapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch deleted file mode 100644 index 057731ba61..0000000000 --- a/Remapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 22 Nov 2016 00:40:42 -0500 -Subject: [PATCH] Fix client rendering skulls from same user - -See: https://github.com/PaperMC/Paper/issues/1304 - -Changes the UUID sent to client to be based on either -the texture payload, or random. - -This allows the client to render multiple skull textures from the same user, -for when different skins were used when skull was made. - -diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -index b4542ce6a8c37ab31e6ecaeb4cbad4742cca0f9b..10f1e3d761af83507bf71a00092641e22d0c8049 100644 ---- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java -+++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -@@ -37,6 +37,7 @@ import net.minecraft.network.chat.Component; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.world.item.Item; - import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.level.block.entity.SkullBlockEntity; - import net.minecraft.world.phys.BlockHitResult; - import net.minecraft.world.phys.Vec3; - import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit -@@ -310,9 +311,18 @@ public class FriendlyByteBuf extends ByteBuf { - if (item.canBeDepleted() || item.shouldOverrideMultiplayerNbt()) { - // Spigot start - filter - itemstack = itemstack.copy(); -- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); -+ //CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported - // Spigot end - nbttagcompound = itemstack.getTag(); -+ // Paper start -+ if (nbttagcompound != null && nbttagcompound.contains("SkullOwner", 10)) { -+ CompoundTag owner = nbttagcompound.getCompound("SkullOwner"); -+ if (owner.hasUUID("Id")) { -+ nbttagcompound.setUUID("SkullOwnerOrig", owner.getUUID("Id")); -+ SkullBlockEntity.sanitizeUUID(owner); -+ } -+ } -+ // Paper end - } - - this.writeNbt(nbttagcompound); -@@ -332,7 +342,16 @@ public class FriendlyByteBuf extends ByteBuf { - itemstack.setTag(this.readNbt()); - // CraftBukkit start - if (itemstack.getTag() != null) { -- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); -+ // Paper start - Fix skulls of same owner - restore orig ID since we changed it on send to client -+ if (itemstack.tag.contains("SkullOwnerOrig")) { -+ CompoundTag owner = itemstack.tag.getCompound("SkullOwner"); -+ if (itemstack.tag.contains("SkullOwnerOrig")) { -+ owner.tags.put("Id", itemstack.tag.tags.get("SkullOwnerOrig")); -+ itemstack.tag.remove("SkullOwnerOrig"); -+ } -+ } -+ // Paper end -+ // CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported - } - // CraftBukkit end - return itemstack; -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -index e5d4363edb8c494d2db69d2e0223a2db1519f64b..4fe15aa331ca18319ca46d1b426f0d6fd24341f0 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -@@ -15,6 +15,7 @@ import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.protocol.Packet; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.block.entity.BlockEntity; -+import net.minecraft.world.level.block.entity.SkullBlockEntity; - import net.minecraft.world.level.chunk.ChunkBiomeContainer; - import net.minecraft.world.level.chunk.LevelChunk; - import net.minecraft.world.level.chunk.LevelChunkSection; -@@ -69,6 +70,7 @@ public class ClientboundLevelChunkPacket implements Packet public - private boolean emptyCacheFlag; - private Entity entityRepresentation; - private BlockInWorld cachedBreakBlock; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java -index eebaeaccc3ba1a9ec089d84b8de6c9d36034868f..6a1289424421083876d1808b7328cd3f01063a7e 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java -@@ -25,6 +25,7 @@ import java.util.concurrent.Executors; - import java.util.concurrent.Future; - import java.util.concurrent.TimeUnit; - import net.minecraft.nbt.CompoundTag; -+import net.minecraft.nbt.ListTag; - import net.minecraft.nbt.NbtUtils; - import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; - import net.minecraft.server.MinecraftServer; -@@ -152,9 +153,37 @@ public class SkullBlockEntity extends BlockEntity /*implements ITickable*/ { // - @Nullable - @Override - public ClientboundBlockEntityDataPacket getUpdatePacket() { -- return new ClientboundBlockEntityDataPacket(this.worldPosition, 4, this.getUpdateTag()); -+ return new ClientboundBlockEntityDataPacket(this.worldPosition, 4, sanitizeTileEntityUUID(this.getUpdateTag())); // Paper - } - -+ // Paper start -+ public static CompoundTag sanitizeTileEntityUUID(CompoundTag cmp) { -+ CompoundTag owner = cmp.getCompound("Owner"); -+ if (!owner.isEmpty()) { -+ sanitizeUUID(owner); -+ } -+ return cmp; -+ } -+ -+ public static void sanitizeUUID(CompoundTag owner) { -+ CompoundTag properties = owner.getCompound("Properties"); -+ ListTag list = null; -+ if (!properties.isEmpty()) { -+ list = properties.getList("textures", 10); -+ } -+ -+ if (list != null && !list.isEmpty()) { -+ String textures = ((CompoundTag)list.get(0)).getString("Value"); -+ if (textures != null && textures.length() > 3) { -+ UUID uuid = UUID.nameUUIDFromBytes(textures.getBytes()); -+ owner.setUUID("Id", uuid); -+ return; -+ } -+ } -+ owner.setUUID("Id", UUID.randomUUID()); -+ } -+ // Paper end -+ - @Override - public CompoundTag getUpdateTag() { - return this.save(new CompoundTag()); diff --git a/Remapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch b/Remapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch deleted file mode 100644 index 4f9ee3cc3e..0000000000 --- a/Remapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Wed, 8 Aug 2018 15:30:52 -0400 -Subject: [PATCH] Add Early Warning Feature to WatchDog - -Detect when the server has been hung for a long duration, and start printing -thread dumps at an interval until the point of crash. - -This will help diagnose what was going on in that time before the crash. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index bd508025b771424c942fd856c31d520b6f548082..62621562137cba4804f0465c58d25ca2786328e5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -25,6 +25,7 @@ import org.bukkit.configuration.file.YamlConfiguration; - import co.aikar.timings.Timings; - import co.aikar.timings.TimingsManager; - import org.spigotmc.SpigotConfig; -+import org.spigotmc.WatchdogThread; - - public class PaperConfig { - -@@ -297,6 +298,14 @@ public class PaperConfig { - } - } - -+ public static int watchdogPrintEarlyWarningEvery = 5000; -+ public static int watchdogPrintEarlyWarningDelay = 10000; -+ private static void watchdogEarlyWarning() { -+ watchdogPrintEarlyWarningEvery = getInt("settings.watchdog.early-warning-every", 5000); -+ watchdogPrintEarlyWarningDelay = getInt("settings.watchdog.early-warning-delay", 10000); -+ WatchdogThread.doStart(SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash ); -+ } -+ - public static int tabSpamIncrement = 1; - public static int tabSpamLimit = 500; - private static void tabSpamLimiters() { -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 125a75576442eaa4f1ff6dd153bdb31097497a3f..5a76ca77b974ff6fe862c9e05a88b507a34b44be 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1017,6 +1017,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable -+ // Paper start -+ Logger log = Bukkit.getServer().getLogger(); -+ long currentTime = monotonicMillis(); -+ if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) - { -- Logger log = Bukkit.getServer().getLogger(); -+ boolean isLongTimeout = currentTime > lastTick + timeoutTime; -+ // Don't spam early warning dumps -+ if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; -+ if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... -+ lastEarlyWarning = currentTime; -+ if (isLongTimeout) { -+ // Paper end - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper - log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); -@@ -93,29 +108,46 @@ public class WatchdogThread extends Thread - } - } - // Paper end -+ } else -+ { -+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); -+ log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump"); -+ } -+ // Paper end - Different message for short timeout - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // -+ // Paper start - Only print full dump on long timeouts -+ if ( isLongTimeout ) -+ { - log.log( Level.SEVERE, "Entire Thread Dump:" ); - ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); - for ( ThreadInfo thread : threads ) - { - dumpThread( thread, log ); - } -+ } else { -+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---"); -+ } -+ -+ - log.log( Level.SEVERE, "------------------------------" ); - -+ if ( isLongTimeout ) -+ { - if ( restart && !MinecraftServer.getServer().hasStopped() ) - { - RestartCommand.restart(); - } - break; -+ } // Paper end - } - - try - { -- sleep( 10000 ); -+ sleep( 1000 ); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout - } catch ( InterruptedException ex ) - { - interrupt(); diff --git a/Remapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch b/Remapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch deleted file mode 100644 index 8392dc7bad..0000000000 --- a/Remapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 10 Aug 2018 22:11:49 -0400 -Subject: [PATCH] Make EnderDragon implement Mob - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java -index bba2e3152ee7073b75ecce1a4792178db20344db..aea39a6cb778d2ef88f66b632aebd824aaef2ea6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java -@@ -1,17 +1,17 @@ - package org.bukkit.craftbukkit.entity; - --import net.minecraft.world.entity.LivingEntity; -+import net.minecraft.world.entity.Mob; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.ComplexLivingEntity; - --public abstract class CraftComplexLivingEntity extends CraftLivingEntity implements ComplexLivingEntity { -- public CraftComplexLivingEntity(CraftServer server, LivingEntity entity) { -+public abstract class CraftComplexLivingEntity extends CraftMob implements ComplexLivingEntity { // Paper -+ public CraftComplexLivingEntity(CraftServer server, Mob entity) { // Paper - super(server, entity); - } - - @Override -- public LivingEntity getHandle() { -- return (LivingEntity) entity; -+ public Mob getHandle() { // Paper -+ return (Mob) entity; // Paper - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch b/Remapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch deleted file mode 100644 index b981b8b044..0000000000 --- a/Remapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: egg82 -Date: Tue, 7 Aug 2018 01:24:23 -0600 -Subject: [PATCH] Use ConcurrentHashMap in JsonList - -This is specifically aimed at fixing #471 - -Using a ConcurrentHashMap because thread safety -The performance benefit of Map over ConcurrentMap is negligabe at best in this scenaio, as most operations will be get and not add or remove -Even without considering the use-case the benefits are still negligable - -Original ideas for the system included an expiration policy and/or handler -The simpler solution was to use a computeIfPresent in the get method -This will simultaneously have an O(1) lookup time and automatically expire any values -Since the get method (nor other similar methods) don't seem to have a critical need to flush the map to disk at any of these points further processing is simply wasteful -Meaning the original function expired values unrelated to the current value without actually having any explicit need to - -The h method was heavily modified to be much more efficient in its processing -Also instead of being called on every get, it's now called just before a save -This will eliminate stale values being flushed to disk - -Modified isEmpty to use the isEmpty() method instead of the slightly confusing size() < 1 -The point of this is readability, but does have a side-benefit of a small microptimization - -Finally, added a couple obfhelpers for the modified code - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0bb397407b55bd1c464ac603ec4c189045aabbb2..7c307a16ca3962db65be09a0ddd058a4ce81c7be 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -614,7 +614,7 @@ public abstract class PlayerList { - } else if (!this.isWhitelisted(gameprofile, event)) { // Paper - //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper - //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted -- } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { -+ } else if (getIpBans().isBanned(socketaddress) && getIpBans().get(socketaddress) != null && !getIpBans().get(socketaddress).hasExpired()) { // Paper - fix NPE with temp ip bans - IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); - - chatmessage = new TranslatableComponent("multiplayer.disconnect.banned_ip.reason", new Object[]{ipbanentry.getReason()}); -diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java -index 2cb235d695c244863a37454df22d5d94a291524d..e2982a8ac5448110378bc92247952332bdffe12c 100644 ---- a/src/main/java/net/minecraft/server/players/StoredUserList.java -+++ b/src/main/java/net/minecraft/server/players/StoredUserList.java -@@ -12,6 +12,8 @@ import java.io.BufferedReader; - import java.io.BufferedWriter; - import java.io.File; - import java.io.IOException; -+import java.lang.reflect.ParameterizedType; // Paper -+import java.lang.reflect.Type; // Paper - import java.nio.charset.StandardCharsets; - import java.util.Collection; - import java.util.Iterator; -@@ -28,7 +30,22 @@ public abstract class StoredUserList> { - protected static final Logger LOGGER = LogManager.getLogger(); - private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create(); - private final File file; -- private final Map map = Maps.newHashMap(); -+ // Paper - replace HashMap is ConcurrentHashMap -+ private final Map map = Maps.newConcurrentMap(); private final Map getBackingMap() { return this.map; } // Paper - OBFHELPER -+ private boolean e = true; -+ private static final ParameterizedType f = new ParameterizedType() { -+ public Type[] getActualTypeArguments() { -+ return new Type[]{StoredUserEntry.class}; -+ } -+ -+ public Type getRawType() { -+ return List.class; -+ } -+ -+ public Type getOwnerType() { -+ return null; -+ } -+ }; - - public StoredUserList(File file) { - this.file = file; -@@ -51,8 +68,13 @@ public abstract class StoredUserList> { - - @Nullable - public V get(K key) { -- this.removeExpired(); -- return (V) this.map.get(this.getKeyForUser(key)); // CraftBukkit - fix decompile error -+ // Paper start -+ // this.g(); -+ // return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error -+ return (V) this.getBackingMap().computeIfPresent(this.getMappingKey(key), (k, v) -> { -+ return v.hasExpired() ? null : v; -+ }); -+ // Paper end - } - - public void remove(K key) { -@@ -81,9 +103,11 @@ public abstract class StoredUserList> { - // CraftBukkit end - - public boolean isEmpty() { -- return this.map.size() < 1; -+ // return this.d.size() < 1; // Paper -+ return this.getBackingMap().isEmpty(); // Paper - readability is the goal. As an aside, isEmpty() uses only sumCount() and a comparison. size() uses sumCount(), casts, and boolean logic - } - -+ protected final String getMappingKey(K k0) { return getKeyForUser(k0); } // Paper - OBFHELPER - protected String getKeyForUser(K profile) { - return profile.toString(); - } -@@ -92,15 +116,16 @@ public abstract class StoredUserList> { - return this.map.containsKey(this.getKeyForUser(k0)); - } - -+ private void removeStaleEntries() { removeExpired(); } // Paper - OBFHELPER - private void removeExpired() { -- List list = Lists.newArrayList(); -- Iterator iterator = this.map.values().iterator(); -+ /*List list = Lists.newArrayList(); -+ Iterator iterator = this.d.values().iterator(); - - while (iterator.hasNext()) { - V v0 = (V) iterator.next(); // CraftBukkit - decompile error - - if (v0.hasExpired()) { -- list.add(v0.getUser()); -+ list.add(v0.getKey()); - } - } - -@@ -109,9 +134,11 @@ public abstract class StoredUserList> { - while (iterator.hasNext()) { - K k0 = (K) iterator.next(); // CraftBukkit - decompile error - -- this.map.remove(this.getKeyForUser(k0)); -- } -+ this.d.remove(this.a(k0)); -+ }*/ - -+ this.getBackingMap().values().removeIf(StoredUserEntry::hasExpired); -+ // Paper end - } - - protected abstract StoredUserEntry createEntry(JsonObject json); -@@ -121,6 +148,7 @@ public abstract class StoredUserList> { - } - - public void save() throws IOException { -+ this.removeStaleEntries(); // Paper - remove expired values before saving - JsonArray jsonarray = new JsonArray(); - - this.map.values().stream().map((jsonlistentry) -> { diff --git a/Remapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch b/Remapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch deleted file mode 100644 index b220fa4eb9..0000000000 --- a/Remapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 12 Aug 2018 02:33:39 -0400 -Subject: [PATCH] Use a Queue for Queueing Commands - -Lists are bad as Queues mmmkay. - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 9143fe99e43236bf65e6f098a30d522302ad78b7..4862a9519d4ba5f05b634a0335837bea9812edee 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -72,7 +72,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - - private static final Logger LOGGER = LogManager.getLogger(); - private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$"); -- private final List consoleInput = Collections.synchronizedList(Lists.newArrayList()); -+ private final java.util.Queue serverCommandQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Paper - use a proper queue - private QueryThreadGs4 queryThreadGs4; - public final RconConsoleSource rconConsoleSource; - private RconThread rconThread; -@@ -426,13 +426,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - } - - public void handleConsoleInput(String command, CommandSourceStack commandSource) { -- this.consoleInput.add(new ConsoleInput(command, commandSource)); -+ this.serverCommandQueue.add(new ConsoleInput(command, commandSource)); - } - - public void handleConsoleInputs() { - MinecraftTimings.serverCommandTimer.startTiming(); // Spigot -- while (!this.consoleInput.isEmpty()) { -- ConsoleInput servercommand = (ConsoleInput) this.consoleInput.remove(0); -+ // Paper start - use proper queue -+ ConsoleInput servercommand; -+ while ((servercommand = this.serverCommandQueue.poll()) != null) { -+ // Paper end - - // CraftBukkit start - ServerCommand for preprocessing - ServerCommandEvent event = new ServerCommandEvent(console, servercommand.msg); diff --git a/Remapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/Remapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch deleted file mode 100644 index 52dbc8ee7e..0000000000 --- a/Remapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 15 Aug 2018 01:16:34 -0400 -Subject: [PATCH] Ability to get Tile Entities from a chunk without snapshots - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index 93b9e9d5932764f7e946dd3f8ab8191189c5d38f..423594177fe78600755d913f169f28dd1bfa2b37 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -3,8 +3,10 @@ package org.bukkit.craftbukkit; - import com.google.common.base.Preconditions; - import com.google.common.base.Predicates; - import java.lang.ref.WeakReference; -+import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; -+import java.util.List; - import java.util.function.Predicate; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Registry; -@@ -129,9 +131,16 @@ public class CraftChunk implements Chunk { - - @Override - public BlockState[] getTileEntities() { -+ // Paper start -+ return getTileEntities(true); -+ } -+ -+ @Override -+ public BlockState[] getTileEntities(boolean useSnapshot) { - if (!isLoaded()) { - getWorld().getChunkAt(x, z); // Transient load for this tick - } -+ // Paper end - int index = 0; - net.minecraft.world.level.chunk.LevelChunk chunk = getHandle(); - -@@ -143,11 +152,33 @@ public class CraftChunk implements Chunk { - } - - BlockPos position = (BlockPos) obj; -- entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(); -+ entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(useSnapshot); // Paper -+ } -+ -+ return entities; -+ } -+ -+ // Paper start -+ @Override -+ public Collection getTileEntities(Predicate blockPredicate, boolean useSnapshot) { -+ Preconditions.checkNotNull(blockPredicate, "blockPredicate"); -+ if (!isLoaded()) { -+ getWorld().getChunkAt(x, z); // Transient load for this tick -+ } -+ net.minecraft.world.level.chunk.LevelChunk chunk = getHandle(); -+ -+ List entities = new ArrayList<>(); -+ -+ for (BlockPos position : chunk.blockEntities.keySet()) { -+ Block block = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); -+ if (blockPredicate.test(block)) { -+ entities.add(block.getState(useSnapshot)); -+ } - } - - return entities; - } -+ // Paper end - - @Override - public boolean isLoaded() { diff --git a/Remapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch b/Remapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch deleted file mode 100644 index b471e98ef0..0000000000 --- a/Remapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 15 Aug 2018 01:26:09 -0700 -Subject: [PATCH] Allow disabling armour stand ticking - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3562950df4868b1393790b1a1ff1fe0dc589c155..5ab0e7183e48134b7a0f736462516b1a8a333b04 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -384,4 +384,10 @@ public class PaperWorldConfig { - private void armorStandEntityLookups() { - armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); - } -+ -+ public boolean armorStandTick = true; -+ private void armorStandTick() { -+ this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); -+ log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 06e52a0c5decf717e35c605d6bcb46c3c7b29656..2994eee1d381af2c9ff3649dd48a2ae14c38c9d7 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -77,9 +77,16 @@ public class ArmorStand extends LivingEntity { - public Rotations leftLegPose; - public Rotations rightLegPose; - public boolean canMove = true; // Paper -+ // Paper start - Allow ArmorStands not to tick -+ public boolean canTick = true; -+ public boolean canTickSetByAPI = false; -+ private boolean noTickPoseDirty = false; -+ private boolean noTickEquipmentDirty = false; -+ // Paper end - - public ArmorStand(EntityType type, Level world) { - super(type, world); -+ if (world != null) this.canTick = world.paperConfig.armorStandTick; // Paper - armour stand ticking - this.handItems = NonNullList.a(2, ItemStack.EMPTY); - this.armorItems = NonNullList.a(4, ItemStack.EMPTY); - this.headPose = ArmorStand.DEFAULT_HEAD_POSE; -@@ -175,6 +182,7 @@ public class ArmorStand extends LivingEntity { - this.armorItems.set(enumitemslot.getIndex(), itemstack); - } - -+ this.noTickEquipmentDirty = true; // Paper - Allow equipment to be updated even when tick disabled - } - - @Override -@@ -255,6 +263,7 @@ public class ArmorStand extends LivingEntity { - } - - tag.put("Pose", this.writePose()); -+ if (this.canTickSetByAPI) tag.putBoolean("Paper.CanTickOverride", this.canTick); // Paper - persist no tick setting - } - - @Override -@@ -286,6 +295,12 @@ public class ArmorStand extends LivingEntity { - this.setNoBasePlate(tag.getBoolean("NoBasePlate")); - this.setMarker(tag.getBoolean("Marker")); - this.noPhysics = !this.hasPhysics(); -+ // Paper start - persist no tick -+ if (tag.contains("Paper.CanTickOverride")) { -+ this.canTick = tag.getBoolean("Paper.CanTickOverride"); -+ this.canTickSetByAPI = true; -+ } -+ // Paper end - CompoundTag nbttagcompound1 = tag.getCompound("Pose"); - - this.readPose(nbttagcompound1); -@@ -641,7 +656,29 @@ public class ArmorStand extends LivingEntity { - - @Override - public void tick() { -+ // Paper start -+ if (!this.canTick) { -+ if (this.noTickPoseDirty) { -+ this.noTickPoseDirty = false; -+ this.updatePose(); -+ } -+ -+ if (this.noTickEquipmentDirty) { -+ this.noTickEquipmentDirty = false; -+ this.detectEquipmentUpdates(); -+ } -+ -+ return; -+ } -+ // Paper end -+ - super.tick(); -+ // Paper start - Split into separate method -+ updatePose(); -+ } -+ -+ public void updatePose() { -+ // Paper end - Rotations vector3f = (Rotations) this.entityData.get(ArmorStand.DATA_HEAD_POSE); - - if (!this.headPose.equals(vector3f)) { -@@ -764,29 +801,36 @@ public class ArmorStand extends LivingEntity { - public void setHeadPose(Rotations vector3f) { - this.headPose = vector3f; - this.entityData.set(ArmorStand.DATA_HEAD_POSE, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setBodyPose(Rotations vector3f) { - this.bodyPose = vector3f; - this.entityData.set(ArmorStand.DATA_BODY_POSE, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setLeftArmPose(Rotations vector3f) { - this.leftArmPose = vector3f; - this.entityData.set(ArmorStand.DATA_LEFT_ARM_POSE, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setRightArmPose(Rotations vector3f) { - this.rightArmPose = vector3f; - this.entityData.set(ArmorStand.DATA_RIGHT_ARM_POSE, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setLeftLegPose(Rotations vector3f) { -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - this.leftLegPose = vector3f; - this.entityData.set(ArmorStand.DATA_LEFT_LEG_POSE, vector3f); -+ - } - - public void setRightLegPose(Rotations vector3f) { -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - this.rightLegPose = vector3f; - this.entityData.set(ArmorStand.DATA_RIGHT_LEG_POSE, vector3f); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index d4da5214a39b718671dcaf687cb0ff8668ce9728..8363b1b2267da30cda2fb8ea4e844598e20e1422 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -311,5 +311,16 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { - return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); - } -+ -+ @Override -+ public boolean canTick() { -+ return this.getHandle().canTick; -+ } -+ -+ @Override -+ public void setCanTick(final boolean tick) { -+ this.getHandle().canTick = tick; -+ this.getHandle().canTickSetByAPI = true; -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch b/Remapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch deleted file mode 100644 index fa154eb153..0000000000 --- a/Remapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Aug 2018 12:05:12 -0700 -Subject: [PATCH] Optimize BlockPosition helper methods - -Resolves #1338 - -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index c5089b0da33a68e7cadbc4841b07f9d772d224a0..b13e5d05d862ea8c6031b8071f525f00bc48f7e7 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -121,58 +121,75 @@ public class BlockPos extends Vec3i { - - @Override - public BlockPos above() { -- return this.relative(Direction.UP); -+ return new BlockPos(this.getX(), this.getY() + 1, this.getZ()); // Paper - Optimize BlockPosition - } - - @Override - public BlockPos above(int distance) { -- return this.relative(Direction.UP, distance); -+ return distance == 0 ? this : new BlockPos(this.getX(), this.getY() + distance, this.getZ()); // Paper - Optimize BlockPosition - } - - @Override - public BlockPos below() { -- return this.relative(Direction.DOWN); -+ return new BlockPos(this.getX(), this.getY() - 1, this.getZ()); // Paper - Optimize BlockPosition - } - - @Override - public BlockPos below(int distance) { -- return this.relative(Direction.DOWN, distance); -+ return distance == 0 ? this : new BlockPos(this.getX(), this.getY() - distance, this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPos north() { -- return this.relative(Direction.NORTH); -+ return new BlockPos(this.getX(), this.getY(), this.getZ() - 1); // Paper - Optimize BlockPosition - } - - public BlockPos north(int distance) { -- return this.relative(Direction.NORTH, distance); -+ return distance == 0 ? this : new BlockPos(this.getX(), this.getY(), this.getZ() - distance); // Paper - Optimize BlockPosition - } - - public BlockPos south() { -- return this.relative(Direction.SOUTH); -+ return new BlockPos(this.getX(), this.getY(), this.getZ() + 1); // Paper - Optimize BlockPosition - } - - public BlockPos south(int distance) { -- return this.relative(Direction.SOUTH, distance); -+ return distance == 0 ? this : new BlockPos(this.getX(), this.getY(), this.getZ() + distance); // Paper - Optimize BlockPosition - } - - public BlockPos west() { -- return this.relative(Direction.WEST); -+ return new BlockPos(this.getX() - 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPos west(int distance) { -- return this.relative(Direction.WEST, distance); -+ return distance == 0 ? this : new BlockPos(this.getX() - distance, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPos east() { -- return this.relative(Direction.EAST); -+ return new BlockPos(this.getX() + 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPos east(int distance) { -- return this.relative(Direction.EAST, distance); -+ return distance == 0 ? this : new BlockPos(this.getX() + distance, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPos relative(Direction direction) { -- return new BlockPos(this.getX() + direction.getStepX(), this.getY() + direction.getStepY(), this.getZ() + direction.getStepZ()); -+ // Paper Start - Optimize BlockPosition -+ switch(direction) { -+ case UP: -+ return new BlockPos(this.getX(), this.getY() + 1, this.getZ()); -+ case DOWN: -+ return new BlockPos(this.getX(), this.getY() - 1, this.getZ()); -+ case NORTH: -+ return new BlockPos(this.getX(), this.getY(), this.getZ() - 1); -+ case SOUTH: -+ return new BlockPos(this.getX(), this.getY(), this.getZ() + 1); -+ case WEST: -+ return new BlockPos(this.getX() - 1, this.getY(), this.getZ()); -+ case EAST: -+ return new BlockPos(this.getX() + 1, this.getY(), this.getZ()); -+ default: -+ return new BlockPos(this.getX() + direction.getStepX(), this.getY() + direction.getStepY(), this.getZ() + direction.getStepZ()); -+ } -+ // Paper End - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/Remapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch deleted file mode 100644 index 50cfc368af..0000000000 --- a/Remapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Aug 2018 12:43:16 -0400 -Subject: [PATCH] Restore vanlla default mob-spawn-range and water animals - limit - - -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 0efcbab8f8806aeb8dd8bd6384e5a7cee375d100..34ee684901906fc2ef5f0d09680d2686b813e52b 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -165,7 +165,7 @@ public class SpigotWorldConfig - public byte mobSpawnRange; - private void mobSpawnRange() - { -- mobSpawnRange = (byte) getInt( "mob-spawn-range", 6 ); -+ mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla - log( "Mob Spawn Range: " + mobSpawnRange ); - } - -diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml -index 6474a7fb738e1238cc272afc5ff14b645947e688..6d71bd0db752e6f523364ca5351579b6bcb434c8 100644 ---- a/src/main/resources/configurations/bukkit.yml -+++ b/src/main/resources/configurations/bukkit.yml -@@ -26,7 +26,7 @@ settings: - spawn-limits: - monsters: 70 - animals: 10 -- water-animals: 15 -+ water-animals: 5 - water-ambient: 20 - ambient: 15 - chunk-gc: diff --git a/Remapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch b/Remapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch deleted file mode 100644 index 1156074828..0000000000 --- a/Remapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch +++ /dev/null @@ -1,229 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 08:18:42 -0500 -Subject: [PATCH] Slime Pathfinder Events - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java -index fc8f26e988f1e4826dcfdcf071293bb356163e62..120ceb28ee3aee8a09cf67b45ac95d3d6613c133 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Slime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java -@@ -24,7 +24,6 @@ import net.minecraft.world.effect.MobEffects; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityDimensions; - import net.minecraft.world.entity.EntityType; --import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.Mob; - import net.minecraft.world.entity.MobSpawnType; - import net.minecraft.world.entity.Pose; -@@ -43,6 +42,13 @@ import net.minecraft.world.level.WorldGenLevel; - import net.minecraft.world.level.biome.Biomes; - import net.minecraft.world.level.levelgen.WorldgenRandom; - import net.minecraft.world.phys.Vec3; -+// Paper start -+import com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent; -+import com.destroystokyo.paper.event.entity.SlimeSwimEvent; -+import com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent; -+import com.destroystokyo.paper.event.entity.SlimeWanderEvent; -+import org.bukkit.entity.LivingEntity; -+// Paper end - // CraftBukkit start - import java.util.ArrayList; - import java.util.List; -@@ -103,6 +109,7 @@ public class Slime extends Mob implements Enemy { - @Override - public void addAdditionalSaveData(CompoundTag tag) { - super.addAdditionalSaveData(tag); -+ tag.putBoolean("Paper.canWander", this.canWander); // Paper - tag.putInt("Size", this.getSize() - 1); - tag.putBoolean("wasOnGround", this.wasOnGround); - } -@@ -117,6 +124,11 @@ public class Slime extends Mob implements Enemy { - - this.setSize(i + 1, false); - super.readAdditionalSaveData(tag); -+ // Paper start - check exists before loading or this will be loaded as false -+ if (tag.contains("Paper.canWander")) { -+ this.canWander = tag.getBoolean("Paper.canWander"); -+ } -+ // Paper end - this.wasOnGround = tag.getBoolean("wasOnGround"); - } - -@@ -218,7 +230,7 @@ public class Slime extends Mob implements Enemy { - super.remove(); - return; - } -- List slimes = new ArrayList<>(j); -+ List slimes = new ArrayList<>(j); - // CraftBukkit end - - for (int l = 0; l < k; ++l) { -@@ -242,7 +254,7 @@ public class Slime extends Mob implements Enemy { - if (CraftEventFactory.callEntityTransformEvent(this, slimes, EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { - return; - } -- for (LivingEntity living : slimes) { -+ for (net.minecraft.world.entity.LivingEntity living : slimes) { - this.level.addEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason - } - // CraftBukkit end -@@ -255,7 +267,7 @@ public class Slime extends Mob implements Enemy { - public void push(Entity entity) { - super.push(entity); - if (entity instanceof IronGolem && this.isDealsDamage()) { -- this.dealDamage((LivingEntity) entity); -+ this.dealDamage((net.minecraft.world.entity.LivingEntity) entity); - } - - } -@@ -263,18 +275,18 @@ public class Slime extends Mob implements Enemy { - @Override - public void playerTouch(Player player) { - if (this.isDealsDamage()) { -- this.dealDamage((LivingEntity) player); -+ this.dealDamage((net.minecraft.world.entity.LivingEntity) player); - } - - } - -- protected void dealDamage(LivingEntity target) { -+ protected void dealDamage(net.minecraft.world.entity.LivingEntity target) { - if (this.isAlive()) { - int i = this.getSize(); - - if (this.distanceToSqr((Entity) target) < 0.6D * (double) i * 0.6D * (double) i && this.canSee(target) && target.hurt(DamageSource.mobAttack(this), this.getAttackDamage())) { - this.playSound(SoundEvents.SLIME_ATTACK, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); -- this.doEnchantDamageEffects((LivingEntity) this, (Entity) target); -+ this.doEnchantDamageEffects((net.minecraft.world.entity.LivingEntity) this, (Entity) target); - } - } - -@@ -396,7 +408,7 @@ public class Slime extends Mob implements Enemy { - - @Override - public boolean canUse() { -- return !this.slime.isPassenger(); -+ return !this.slime.isPassenger() && this.slime.canWander && new SlimeWanderEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper - } - - @Override -@@ -417,7 +429,7 @@ public class Slime extends Mob implements Enemy { - - @Override - public boolean canUse() { -- return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; -+ return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new SlimeSwimEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper - } - - @Override -@@ -443,14 +455,18 @@ public class Slime extends Mob implements Enemy { - - @Override - public boolean canUse() { -- return this.slime.getTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; -+ return this.slime.getTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander; // Paper - add canWander - } - - @Override - public void tick() { - if (--this.nextRandomizeTime <= 0) { - this.nextRandomizeTime = 40 + this.slime.getRandom().nextInt(60); -- this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); -+ // Paper start -+ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (float) this.slime.getRandom().nextInt(360)); -+ if (!this.slime.canWander || !event.callEvent()) return; -+ this.chosenDegrees = event.getNewYaw(); -+ // Paper end - } - - ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.chosenDegrees, false); -@@ -469,9 +485,17 @@ public class Slime extends Mob implements Enemy { - - @Override - public boolean canUse() { -- LivingEntity entityliving = this.slime.getTarget(); -+ net.minecraft.world.entity.LivingEntity entityliving = this.slime.getTarget(); - -- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable ? false : this.slime.getMoveControl() instanceof Slime.SlimeMoveControl)); -+ // Paper start -+ if (entityliving == null || !entityliving.isAlive()) { -+ return false; -+ } -+ if (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable) { -+ return false; -+ } -+ return this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); -+ // Paper end - } - - @Override -@@ -482,9 +506,17 @@ public class Slime extends Mob implements Enemy { - - @Override - public boolean canContinueToUse() { -- LivingEntity entityliving = this.slime.getTarget(); -+ net.minecraft.world.entity.LivingEntity entityliving = this.slime.getTarget(); - -- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable ? false : --this.growTiredTimer > 0)); -+ // Paper start -+ if (entityliving == null || !entityliving.isAlive()) { -+ return false; -+ } -+ if (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable) { -+ return false; -+ } -+ return --this.growTiredTimer > 0 && this.slime.canWander && new SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); -+ // Paper end - } - - @Override -@@ -492,6 +524,13 @@ public class Slime extends Mob implements Enemy { - this.slime.lookAt((Entity) this.slime.getTarget(), 10.0F, 10.0F); - ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.slime.yRot, this.slime.isDealsDamage()); - } -+ -+ // Paper start - clear timer and target when goal resets -+ public void stop() { -+ this.growTiredTimer = 0; -+ this.slime.setTarget(null); -+ } -+ // Paper end - } - - static class SlimeMoveControl extends MoveControl { -@@ -550,4 +589,15 @@ public class Slime extends Mob implements Enemy { - } - } - } -+ -+ // Paper start -+ private boolean canWander = true; -+ public boolean canWander() { -+ return canWander; -+ } -+ -+ public void setWander(boolean canWander) { -+ this.canWander = canWander; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -index 93af0fd9e15954d7d9f28d7dc29ee18055908348..340036135588d06e43cbd229dd3a6613b04bb9ab 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -@@ -34,4 +34,14 @@ public class CraftSlime extends CraftMob implements Slime { - public EntityType getType() { - return EntityType.SLIME; - } -+ -+ // Paper start -+ public boolean canWander() { -+ return getHandle().canWander(); -+ } -+ -+ public void setWander(boolean canWander) { -+ getHandle().setWander(canWander); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch b/Remapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch deleted file mode 100644 index c8fef8a86f..0000000000 --- a/Remapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 8 Aug 2018 16:33:21 -0600 -Subject: [PATCH] Configurable speed for water flowing over lava - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5ab0e7183e48134b7a0f736462516b1a8a333b04..f280dbff4a09bc611a9ca565c6d697d08801f53b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -390,4 +390,10 @@ public class PaperWorldConfig { - this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); - log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); - } -+ -+ public int waterOverLavaFlowSpeed; -+ private void waterOverLavaFlowSpeed() { -+ waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); -+ log("Water over lava flow speed: " + waterOverLavaFlowSpeed); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java -index f99b90e4b3210747077f2bf3adbcf7b5fb9821ec..97f2d9082e49010fb8780c5fdd8957f71b31e43e 100644 ---- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java -@@ -23,6 +23,7 @@ import net.minecraft.world.level.material.FlowingFluid; - import net.minecraft.world.level.material.Fluid; - import net.minecraft.world.level.material.FluidState; - import net.minecraft.world.level.material.Fluids; -+import net.minecraft.world.level.material.Material; - import net.minecraft.world.level.pathfinder.PathComputationType; - import net.minecraft.world.level.storage.loot.LootContext; - import net.minecraft.world.phys.shapes.CollisionContext; -@@ -100,11 +101,28 @@ public class LiquidBlock extends Block implements BucketPickup { - @Override - public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { - if (this.shouldSpreadLiquid(world, pos, state)) { -- world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); -+ world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper - } - - } - -+ // Paper start - Get flow speed. Throttle if its water and flowing adjacent to lava -+ public int getFlowSpeed(Level world, BlockPos blockposition) { -+ if (this.material == Material.WATER) { -+ if ( -+ world.getMaterialIfLoaded(blockposition.north(1)) == Material.LAVA || -+ world.getMaterialIfLoaded(blockposition.south(1)) == Material.LAVA || -+ world.getMaterialIfLoaded(blockposition.west(1)) == Material.LAVA || -+ world.getMaterialIfLoaded(blockposition.east(1)) == Material.LAVA -+ ) { -+ return world.paperConfig.waterOverLavaFlowSpeed; -+ } -+ } -+ return this.fluid.getTickDelay(world); -+ } -+ // Paper end -+ -+ - @Override - public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { - if (state.getFluidState().isSource() || newState.getFluidState().isSource()) { -@@ -117,7 +135,7 @@ public class LiquidBlock extends Block implements BucketPickup { - @Override - public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { - if (this.shouldSpreadLiquid(world, pos, state)) { -- world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); -+ world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper - } - - } diff --git a/Remapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch b/Remapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch deleted file mode 100644 index b9e1c45f8f..0000000000 --- a/Remapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Thu, 23 Aug 2018 11:45:32 -0400 -Subject: [PATCH] Optimize CraftBlockData Creation - -Avoids a hashmap lookup by cacheing a reference to the CraftBlockData -and cloning it when one is needed. - -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index 5d7794c9533bd37193f196bda616adaaace2bbde..57eedaeedaa24bd274fb55c6e4521f1305382645 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -374,6 +374,14 @@ public abstract class BlockBehaviour { - this.hasPostProcess = blockbase_info.hasPostProcess; - this.emissiveRendering = blockbase_info.emissiveRendering; - } -+ // Paper start - impl cached craft block data, lazy load to fix issue with loading at the wrong time -+ private org.bukkit.craftbukkit.block.data.CraftBlockData cachedCraftBlockData; -+ -+ public org.bukkit.craftbukkit.block.data.CraftBlockData createCraftBlockData() { -+ if (cachedCraftBlockData == null) cachedCraftBlockData = org.bukkit.craftbukkit.block.data.CraftBlockData.createData(getBlockData()); -+ return (org.bukkit.craftbukkit.block.data.CraftBlockData) cachedCraftBlockData.clone(); -+ } -+ // Paper end - - public void initCache() { - if (!this.getBlock().hasDynamicShape()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -index 3a90b504ebbe86350f5fee5baa818e40d884d24f..0b6c6dfc380cea87bd88c3eb8a199e072dcbf56c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -@@ -509,7 +509,17 @@ public class CraftBlockData implements BlockData { - return craft; - } - -+ // Paper start - optimize creating BlockData to not need a map lookup -+ static { -+ // Initialize cached data for all IBlockData instances after registration -+ Block.BLOCK_STATE_REGISTRY.iterator().forEachRemaining(BlockState::createCraftBlockData); -+ } - public static CraftBlockData fromData(BlockState data) { -+ return data.createCraftBlockData(); -+ } -+ -+ public static CraftBlockData createData(BlockState data) { -+ // Paper end - return MAP.getOrDefault(data.getBlock().getClass(), CraftBlockData::new).apply(data); - } - diff --git a/Remapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch b/Remapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch deleted file mode 100644 index 9ee9585d10..0000000000 --- a/Remapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 26 Aug 2018 20:49:50 -0400 -Subject: [PATCH] Optimize RegistryMaterials - -Use larger initial sizes to increase bucket capacity on the BiMap - -BiMap.get was seen to be using a good bit of CPU time. - -diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java -index 928d4b980a1f703915454ffb304dc329fa4223df..da3733db4a5817673703f6c0cf37b5ee3bf91a99 100644 ---- a/src/main/java/net/minecraft/core/MappedRegistry.java -+++ b/src/main/java/net/minecraft/core/MappedRegistry.java -@@ -30,6 +30,7 @@ import net.minecraft.Util; - import net.minecraft.resources.RegistryDataPackCodec; - import net.minecraft.resources.ResourceKey; - import net.minecraft.resources.ResourceLocation; -+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; // Paper - import org.apache.commons.lang3.Validate; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -38,7 +39,7 @@ public class MappedRegistry extends WritableRegistry { - - protected static final Logger LOGGER = LogManager.getLogger(); - private final ObjectList byId = new ObjectArrayList(256); -- private final Object2IntMap toId = new Object2IntOpenCustomHashMap(Util.identityStrategy()); -+ private final Reference2IntOpenHashMap bg = new Reference2IntOpenHashMap(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map - private final BiMap storage; - private final BiMap, T> keyStorage; - private final Map lifecycles; -@@ -48,10 +49,10 @@ public class MappedRegistry extends WritableRegistry { - - public MappedRegistry(ResourceKey> key, Lifecycle lifecycle) { - super(key, lifecycle); -- this.toId.defaultReturnValue(-1); -- this.storage = HashBiMap.create(); -- this.keyStorage = HashBiMap.create(); -- this.lifecycles = Maps.newIdentityHashMap(); -+ this.bg.defaultReturnValue(-1); -+ this.storage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions -+ this.keyStorage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions -+ this.lifecycles = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions - this.elementsLifecycle = lifecycle; - } - -@@ -77,7 +78,7 @@ public class MappedRegistry extends WritableRegistry { - Validate.notNull(entry); - this.byId.size(Math.max(this.byId.size(), rawId + 1)); - this.byId.set(rawId, entry); -- this.toId.put(entry, rawId); -+ this.bg.put(entry, rawId); - this.randomCache = null; - if (checkDuplicateKeys && this.keyStorage.containsKey(key)) { - MappedRegistry.LOGGER.debug("Adding duplicate key '{}' to registry", key); -@@ -113,12 +114,12 @@ public class MappedRegistry extends WritableRegistry { - if (t0 == null) { - i = rawId.isPresent() ? rawId.getAsInt() : this.nextId; - } else { -- i = this.toId.getInt(t0); -+ i = this.bg.getInt(t0); - if (rawId.isPresent() && rawId.getAsInt() != i) { - throw new IllegalStateException("ID mismatch"); - } - -- this.toId.removeInt(t0); -+ this.bg.removeInt(t0); - this.lifecycles.remove(t0); - } - -@@ -138,7 +139,7 @@ public class MappedRegistry extends WritableRegistry { - - @Override - public int getId(@Nullable T entry) { -- return this.toId.getInt(entry); -+ return this.bg.getInt(entry); - } - - @Nullable -@@ -195,7 +196,7 @@ public class MappedRegistry extends WritableRegistry { - this.randomCache = collection.toArray(new Object[collection.size()]); - } - -- return Util.getRandom(this.randomCache, random); -+ return (T) Util.getRandom(this.randomCache, random); // Paper - Decompile fix - } - - public static Codec> networkCodec(ResourceKey> resourcekey, Lifecycle lifecycle, Codec entryCodec) { -@@ -215,7 +216,7 @@ public class MappedRegistry extends WritableRegistry { - Iterator iterator = registrymaterials.iterator(); - - while (iterator.hasNext()) { -- T t0 = iterator.next(); -+ T t0 = (T) iterator.next(); // Paper - Decompile fix - - builder.add(new MappedRegistry.RegistryEntry<>((ResourceKey) registrymaterials.getResourceKey(t0).get(), registrymaterials.getId(t0), t0)); - } diff --git a/Remapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch b/Remapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch deleted file mode 100644 index a3b507be83..0000000000 --- a/Remapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 25 Aug 2018 19:56:51 -0500 -Subject: [PATCH] Add PhantomPreSpawnEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index 4a2fecdfbda34d6360d50e2ac017907a62b4a043..e37137a2890330b92e05d6f76c46ffc99a527803 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -@@ -161,6 +161,11 @@ public class Phantom extends FlyingMob implements Enemy { - } - - this.setPhantomSize(tag.getInt("Size")); -+ // Paper start -+ if (tag.hasUUID("Paper.SpawningEntity")) { -+ this.spawningEntity = tag.getUUID("Paper.SpawningEntity"); -+ } -+ // Paper end - } - - @Override -@@ -170,6 +175,11 @@ public class Phantom extends FlyingMob implements Enemy { - tag.putInt("AY", this.anchorPoint.getY()); - tag.putInt("AZ", this.anchorPoint.getZ()); - tag.putInt("Size", this.getPhantomSize()); -+ // Paper start -+ if (this.spawningEntity != null) { -+ tag.setUUID("Paper.SpawningEntity", this.spawningEntity); -+ } -+ // Paper end - } - - @Override -@@ -216,6 +226,15 @@ public class Phantom extends FlyingMob implements Enemy { - return entitysize.scale(f); - } - -+ // Paper start -+ java.util.UUID spawningEntity; -+ -+ public java.util.UUID getSpawningEntity() { -+ return spawningEntity; -+ } -+ public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } -+ // Paper end -+ - class PhantomAttackPlayerTargetGoal extends Goal { - - private final TargetingConditions attackTargeting; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java -index ee18e2826f6390ef5a29557b733fd00db5bc409f..42effcbd3ca7c38a4e8b1aa835543ad243112a33 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java -@@ -4,6 +4,7 @@ import java.util.Iterator; - import java.util.Random; - import net.minecraft.core.BlockPos; - import net.minecraft.nbt.CompoundTag; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.stats.ServerStatsCounter; -@@ -73,8 +74,17 @@ public class PhantomSpawner implements CustomSpawner { - int k = 1 + random.nextInt(difficultydamagescaler.getDifficulty().getId() + 1); - - for (int l = 0; l < k; ++l) { -+ // Paper start -+ com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(MCUtil.toLocation(world, blockposition1), ((ServerPlayer) entityhuman).getBukkitEntity(), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ break; -+ } -+ continue; -+ } -+ // Paper end - Phantom entityphantom = (Phantom) EntityType.PHANTOM.create((Level) world); -- -+ entityphantom.setSpawningEntity(entityhuman.getUUID()); // Paper - entityphantom.moveTo(blockposition1, 0.0F, 0.0F); - groupdataentity = entityphantom.finalizeSpawn(world, difficultydamagescaler, MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); - world.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -index 15eb09595dad996314c169f9dd7d381e43f77be9..92162fa22f5e98b7837bde5830bd47c31b8b52d8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -@@ -34,4 +34,10 @@ public class CraftPhantom extends CraftFlying implements Phantom { - public EntityType getType() { - return EntityType.PHANTOM; - } -+ -+ // Paper start -+ public java.util.UUID getSpawningEntity() { -+ return getHandle().getSpawningEntity(); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch b/Remapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch deleted file mode 100644 index 3a4091fe8d..0000000000 --- a/Remapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 11:50:26 -0500 -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 d9b5cf8ac01289801ded01d928fa7ead96551be5..336736fae0b49a05e48c1c70a225da316bb73e66 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -@@ -289,7 +289,18 @@ public class Creeper extends Monster { - } - - public void ignite() { -- this.entityData.set(Creeper.DATA_IS_IGNITED, true); -+ // Paper start -+ setIgnited(true); -+ } -+ -+ public void setIgnited(boolean ignited) { -+ if (isIgnited() != ignited) { -+ com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited); -+ if (event.callEvent()) { -+ this.entityData.set(Creeper.DATA_IS_IGNITED, event.isIgnited()); -+ } -+ } -+ // Paper end - } - - 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 ded0b7c1619aada95492e7ec25c0e0f3d008d0ad..9f68beb8c79ed1c429ee9f9efab8b8604258293b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -@@ -100,4 +100,14 @@ public class CraftCreeper extends CraftMonster implements Creeper { - public EntityType getType() { - return EntityType.CREEPER; - } -+ -+ // Paper start -+ public void setIgnited(boolean ignited) { -+ getHandle().setIgnited(ignited); -+ } -+ -+ public boolean isIgnited() { -+ return getHandle().isIgnited(); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch b/Remapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch deleted file mode 100644 index b542a82e8a..0000000000 --- a/Remapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 28 Aug 2018 23:04:15 -0400 -Subject: [PATCH] Inventory#removeItemAnySlot - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index 9d70ef8c3967596491a804e4d66f2ec1b13992c9..ef2d18d19a86b3701855aa1ac126462e663f8fcd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -222,10 +222,16 @@ public class CraftInventory implements Inventory { - } - - private int first(ItemStack item, boolean withAmount) { -+ // Paper start -+ return first(item, withAmount, getStorageContents()); -+ } -+ -+ private int first(ItemStack item, boolean withAmount, ItemStack[] inventory) { -+ // Paper end - if (item == null) { - return -1; - } -- ItemStack[] inventory = getStorageContents(); -+ //ItemStack[] inventory = getStorageContents(); // Paper - let param deal - for (int i = 0; i < inventory.length; i++) { - if (inventory[i] == null) continue; - -@@ -348,6 +354,17 @@ public class CraftInventory implements Inventory { - - @Override - public HashMap removeItem(ItemStack... items) { -+ // Paper start -+ return removeItem(false, items); -+ } -+ -+ @Override -+ public HashMap removeItemAnySlot(ItemStack... items) { -+ return removeItem(true, items); -+ } -+ -+ private HashMap removeItem(boolean searchEntire, ItemStack... items) { -+ // Paper end - Validate.notNull(items, "Items cannot be null"); - HashMap leftover = new HashMap(); - -@@ -358,7 +375,10 @@ public class CraftInventory implements Inventory { - int toDelete = item.getAmount(); - - while (true) { -- int first = first(item, false); -+ // Paper start - Allow searching entire contents -+ ItemStack[] toSearch = searchEntire ? getContents() : getStorageContents(); -+ int first = first(item, false, toSearch); -+ // Paper end - - // Drat! we don't have this type in the inventory - if (first == -1) { diff --git a/Remapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/Remapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch deleted file mode 100644 index 3b436ea5af..0000000000 --- a/Remapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 2 Sep 2018 19:34:33 -0700 -Subject: [PATCH] Make CraftWorld#loadChunk(int, int, false) load unconverted - chunks - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 159c32d6678e83f2d98ea6a1ad48346c9de017e1..57a2af56b53567371fdb6d0a55866e1e4e37cf3b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -490,7 +490,7 @@ public class CraftWorld implements World { - @Override - public boolean loadChunk(int x, int z, boolean generate) { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -- ChunkAccess chunk = world.getChunkSource().getChunk(x, z, generate ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); -+ ChunkAccess chunk = world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper - - // If generate = false, but the chunk already exists, we will get this back. - if (chunk instanceof ImposterProtoChunk) { diff --git a/Remapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch b/Remapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch deleted file mode 100644 index f1edc62517..0000000000 --- a/Remapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 3 Sep 2018 18:20:03 -0500 -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 205c639d26652befebae925fc6e40976c370710f..2e25cb2a04d150d3154bf0d7f0eccb97e65ff53e 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3605,6 +3605,23 @@ public abstract class LivingEntity extends Entity { - this.broadcastBreakEvent(hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); - } - // Paper start -+ public HitResult getRayTrace(int maxDistance) { -+ return getRayTrace(maxDistance, ClipContext.Fluid.NONE); -+ } -+ -+ public HitResult getRayTrace(int maxDistance, ClipContext.Fluid fluidCollisionOption) { -+ if (maxDistance < 1 || maxDistance > 120) { -+ throw new IllegalArgumentException("maxDistance must be between 1-120"); -+ } -+ -+ Vec3 start = new Vec3(getX(), getY() + getEyeHeight(), getZ()); -+ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance); -+ Vec3 end = new Vec3(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ()); -+ ClipContext raytrace = new ClipContext(start, end, ClipContext.Block.OUTLINE, fluidCollisionOption, this); -+ -+ return level.clip(raytrace); -+ } -+ - public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; - - public int getShieldBlockingDelay() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 6dd7a722e10a2727f68318b880f2726bb816f198..7e3a215f1592bed9f35e22076d9e35a5a49a430e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.block.TargetBlockInfo; - import com.google.common.base.Preconditions; - import com.google.common.collect.Sets; - import java.util.ArrayList; -@@ -8,6 +9,7 @@ import java.util.Iterator; - import java.util.List; - import java.util.Set; - import java.util.UUID; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.InteractionHand; - import net.minecraft.world.damagesource.DamageSource; -@@ -28,6 +30,8 @@ import net.minecraft.world.entity.projectile.ThrownEgg; - import net.minecraft.world.entity.projectile.ThrownEnderpearl; - import net.minecraft.world.entity.projectile.ThrownExperienceBottle; - import net.minecraft.world.entity.projectile.ThrownTrident; -+import net.minecraft.world.phys.BlockHitResult; -+import net.minecraft.world.phys.HitResult; - import org.apache.commons.lang.Validate; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -37,6 +41,7 @@ import org.bukkit.attribute.AttributeInstance; - import org.bukkit.block.Block; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.entity.memory.CraftMemoryKey; - import org.bukkit.craftbukkit.entity.memory.CraftMemoryMapper; - import org.bukkit.craftbukkit.inventory.CraftEntityEquipment; -@@ -190,6 +195,28 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return blocks.get(0); - } - -+ // Paper start -+ @Override -+ public Block getTargetBlock(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ HitResult rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof BlockHitResult) ? null : CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()); -+ } -+ -+ @Override -+ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ HitResult rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof BlockHitResult) ? null : MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection()); -+ } -+ -+ @Override -+ public TargetBlockInfo getTargetBlockInfo(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ HitResult rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof BlockHitResult) ? null : -+ new TargetBlockInfo(CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()), -+ MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection())); -+ } -+ // Paper end -+ - @Override - public List getLastTwoTargetBlocks(Set transparent, int maxDistance) { - return getLineOfSight(transparent, maxDistance, 2); diff --git a/Remapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch b/Remapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch deleted file mode 100644 index bfe6717c67..0000000000 --- a/Remapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 4 Sep 2018 15:02:00 -0500 -Subject: [PATCH] Expose attack cooldown methods for Player - - -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 709e930eef7bae5694238ed8c4d0ef59316bb715..14d5acff198338c68162e33d4a90f74be77cb15f 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -2100,6 +2100,7 @@ public abstract class Player extends LivingEntity { - this.entityData.set(Player.DATA_SHOULDER_RIGHT, entityTag); - } - -+ public float getCooldownPeriod() { return this.getCurrentItemAttackStrengthDelay(); } // Paper - OBFHELPER - public float getCurrentItemAttackStrengthDelay() { - return (float) (1.0D / this.getAttributeValue(Attributes.ATTACK_SPEED) * 20.0D); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index c7f66dddf0a0850ca4048dd47cd2ded114caa07e..ee823c4ed5b9fcfaa900b470c582435f0b909ebc 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2186,6 +2186,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND)); - connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, inventory.getSelected())); - } -+ -+ public float getCooldownPeriod() { -+ return getHandle().getCooldownPeriod(); -+ } -+ -+ public float getCooledAttackStrength(float adjustTicks) { -+ return getHandle().getAttackStrengthScale(adjustTicks); -+ } -+ -+ public void resetCooldown() { -+ getHandle().resetAttackStrengthTicker(); -+ } - // Paper end - - // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0279-Improve-death-events.patch b/Remapped-Spigot-Server-Patches/0279-Improve-death-events.patch deleted file mode 100644 index 15db46e30d..0000000000 --- a/Remapped-Spigot-Server-Patches/0279-Improve-death-events.patch +++ /dev/null @@ -1,458 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 21 Aug 2018 01:39:35 +0100 -Subject: [PATCH] Improve death events - -This adds the ability to cancel the death events and to modify the sound -an entity makes when dying. (In cases were no sound should it will be -called with shouldPlaySound set to false allowing unsilencing of silent -entities) - -It makes handling of entity deaths a lot nicer as you no longer need -to listen on the damage event and calculate if the entity dies yourself -to cancel the death which has the benefit of also receiving the dropped -items and experience which is otherwise only properly possible by using -internal code. - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 5664e292046d4fcdb81340df8cee8d04aa27ca55..75419c866641ab654349cde6ca3fbdef701dd8d9 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -211,6 +211,10 @@ public class ServerPlayer extends Player implements ContainerListener { - public int latency; - public boolean wonGame; - private int containerUpdateDelay; // Paper -+ // Paper start - cancellable death event -+ public boolean queueHealthUpdatePacket = false; -+ public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; -+ // Paper end - - // CraftBukkit start - public String displayName; -@@ -714,6 +718,15 @@ public class ServerPlayer extends Player implements ContainerListener { - Component defaultMessage = this.getCombatTracker().getDeathMessage(); - - org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure -+ // Paper start - cancellable death event -+ if (event.isCancelled()) { -+ // make compatible with plugins that might have already set the health in an event listener -+ if (this.getHealth() <= 0) { -+ this.setHealth((float) event.getReviveHealth()); -+ } -+ return; -+ } -+ // Paper end - - // SPIGOT-943 - only call if they have an inventory open - if (this.containerMenu != this.inventoryMenu) { -@@ -860,8 +873,17 @@ public class ServerPlayer extends Player implements ContainerListener { - } - } - } -- -- return super.hurt(source, amount); -+ // Paper start - cancellable death events -+ //return super.damageEntity(damagesource, f); -+ this.queueHealthUpdatePacket = true; -+ boolean damaged = super.hurt(source, amount); -+ this.queueHealthUpdatePacket = false; -+ if (this.queuedHealthUpdatePacket != null) { -+ this.connection.send(this.queuedHealthUpdatePacket); -+ this.queuedHealthUpdatePacket = null; -+ } -+ return damaged; -+ // Paper end - } - } - } -diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -index 8a0863a695bb33698fb3fe6e06599f6f6f47011f..36e665009418d5177016a744eb920fbf99f534fc 100644 ---- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -+++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -@@ -203,6 +203,7 @@ public class CombatTracker { - this.nextLocation = null; - } - -+ public final void reset() { this.recheckStatus(); } // Paper - OBFHELPER - public void recheckStatus() { - int i = this.inCombat ? 300 : 100; - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 4503bd65b3454bad94bb7b869f4e72e3121d8a3d..e7fed1f8bb8ffb164ddcdab51f41c369d6e3103d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1537,6 +1537,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - // CraftBukkit end - -+ public final void runKillTrigger(Entity entity, int kills, DamageSource damageSource) { this.awardKillScore(entity, kills, damageSource); } // Paper - OBFHELPER - public void awardKillScore(Entity killer, int score, DamageSource damageSource) { - if (killer instanceof ServerPlayer) { - CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer) killer, this, damageSource); -@@ -2441,6 +2442,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.fallDistance = 0.0F; - } - -+ public final void onKill(ServerLevel worldserver, net.minecraft.world.entity.LivingEntity entityLiving) { this.killed(worldserver, entityLiving); } // Paper - OBFHELPER - public void killed(ServerLevel worldserver, net.minecraft.world.entity.LivingEntity entityliving) {} - - protected void moveTowardsClosestSpace(double x, double y, double z) { -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 2e25cb2a04d150d3154bf0d7f0eccb97e65ff53e..7a2292e6907a2ae2026bd7243e864bd8300ecafa 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -186,7 +186,7 @@ public abstract class LivingEntity extends Entity { - protected float animStep; - protected float animStepO; - protected float rotOffs; -- protected int deathScore; -+ protected int deathScore;protected int getKillCount() { return this.deathScore; } // Paper - OBFHELPER - public float lastHurt; - protected boolean jumping; - public float xxa; -@@ -230,6 +230,7 @@ public abstract class LivingEntity extends Entity { - public Set collidableExemptions = new HashSet<>(); - public boolean canPickUpLoot; - public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper -+ public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event - - @Override - public float getBukkitYaw() { -@@ -1345,13 +1346,17 @@ public abstract class LivingEntity extends Entity { - if (knockbackCancelled) this.level.broadcastEntityEvent(this, (byte) 2); // Paper - Disable explosion knockback - if (this.isDeadOrDying()) { - if (!this.checkTotemDeathProtection(source)) { -- SoundEvent soundeffect = this.getDeathSound(); -+ // Paper start - moved into CraftEventFactory event caller for cancellable death event -+ //SoundEffect soundeffect = this.getSoundDeath(); - -- if (flag1 && soundeffect != null) { -- this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); -- } -+// if (flag1 && soundeffect != null) { -+// this.playSound(soundeffect, this.getSoundVolume(), this.dH()); -+// } -+ this.silentDeath = !flag1; // mark entity as dying silently -+ // Paper end - - this.die(source); -+ this.silentDeath = false; // Paper - cancellable death event - reset to default - } - } else if (flag1) { - this.playHurtSound(source); -@@ -1490,27 +1495,48 @@ public abstract class LivingEntity extends Entity { - Entity entity = source.getEntity(); - LivingEntity entityliving = this.getKillCredit(); - -- if (this.deathScore >= 0 && entityliving != null) { -- entityliving.awardKillScore(this, this.deathScore, source); -+ /* // Paper - move down to make death event cancellable - this is the runKillTrigger below -+ if (this.aO >= 0 && entityliving != null) { -+ entityliving.a(this, this.aO, damagesource); - } - - if (this.isSleeping()) { -- this.stopSleeping(); -+ this.entityWakeup(); - } -+ */ // Paper - - this.dead = true; -- this.getCombatTracker().recheckStatus(); -+ // this.getCombatTracker().g(); // Paper - moved into if below as .reset() - if (this.level instanceof ServerLevel) { - if (entity != null) { -- entity.killed((ServerLevel) this.level, this); -+ // entity.a((WorldServer) this.world, this); // Paper - move below into if for onKill - } - -- this.dropAllDeathLoot(source); -+ // Paper start -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.d(source); -+ if (deathEvent == null || !deathEvent.isCancelled()) { -+ if (this.getKillCount() >= 0 && entityliving != null) { -+ entityliving.runKillTrigger(this, this.getKillCount(), source); -+ } -+ if (this.isSleeping()) { -+ this.stopSleeping(); -+ } -+ this.getCombatTracker().reset(); -+ if (entity != null) { -+ entity.onKill((ServerLevel) this.level, this); -+ } -+ } else { -+ this.dead = false; -+ this.setHealth((float) deathEvent.getReviveHealth()); -+ } -+ // Paper end - this.createWitherRose(entityliving); - } - -+ if (this.dead) { // Paper - this.level.broadcastEntityEvent(this, (byte) 3); - this.setPose(Pose.DYING); -+ } // Paper - } - } - -@@ -1518,7 +1544,7 @@ public abstract class LivingEntity extends Entity { - if (!this.level.isClientSide) { - boolean flag = false; - -- if (adversary instanceof WitherBoss) { -+ if (this.dead && adversary instanceof WitherBoss) { // Paper - if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { - BlockPos blockposition = this.blockPosition(); - BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState(); -@@ -1546,8 +1572,9 @@ public abstract class LivingEntity extends Entity { - } - } - -- protected void dropAllDeathLoot(DamageSource source) { -- Entity entity = source.getEntity(); -+ protected org.bukkit.event.entity.EntityDeathEvent processDeath(DamageSource damagesource) { return d(damagesource); } // Paper - OBFHELPER -+ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper -+ Entity entity = damagesource.getEntity(); - int i; - - if (entity instanceof net.minecraft.world.entity.player.Player) { -@@ -1560,19 +1587,22 @@ public abstract class LivingEntity extends Entity { - - this.dropEquipment(); // CraftBukkit - from below - if (this.shouldDropLoot() && this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { -- this.dropFromLootTable(source, flag); -- this.dropCustomDeathLoot(source, i, flag); -+ this.dropFromLootTable(damagesource, flag); -+ this.dropCustomDeathLoot(damagesource, i, flag); - } - // CraftBukkit start - Call death event -- CraftEventFactory.callEntityDeathEvent(this, this.drops); -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper -+ this.postDeathDropItems(deathEvent); // Paper - this.drops = new ArrayList<>(); - // CraftBukkit end - - // this.dropInventory();// CraftBukkit - moved up - this.dropExperience(); -+ return deathEvent; // Paper - } - - protected void dropEquipment() {} -+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled - - // CraftBukkit start - public int getExpReward() { -@@ -1657,6 +1687,7 @@ public abstract class LivingEntity extends Entity { - return SoundEvents.GENERIC_HURT; - } - -+ public final SoundEvent getDeathSoundEffect() { return this.getDeathSound(); } // Paper - OBFHELPER - @Nullable - protected SoundEvent getDeathSound() { - return SoundEvents.GENERIC_DEATH; -@@ -2193,10 +2224,12 @@ public abstract class LivingEntity extends Entity { - - } - -+ public final float getDeathSoundVolume() { return this.getSoundVolume(); } // Paper - OBFHELPER - protected float getSoundVolume() { - return 1.0F; - } - -+ public float getSoundPitch() { return getVoicePitch();} // Paper - OBFHELPER - protected float getVoicePitch() { - return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.5F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java -index c2d98222f575d7383e4c040730f6d531bdb0d7b6..46792914f574800c893eb197fa7b3b87ce7e500b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Fox.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java -@@ -647,15 +647,25 @@ public class Fox extends Animal { - } - - @Override -- protected void dropAllDeathLoot(DamageSource source) { -- ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND); -+ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper -+ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND).copy(); // Paper -+ -+ // Paper start - Cancellable death event -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.d(damagesource); -+ -+ // Below is code to drop -+ -+ if (deathEvent == null || deathEvent.isCancelled()) { -+ return deathEvent; -+ } -+ // Paper end - - if (!itemstack.isEmpty()) { - this.spawnAtLocation(itemstack); - this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); - } - -- super.dropAllDeathLoot(source); -+ return deathEvent; // Paper - } - - public static boolean isPathClear(Fox fox, LivingEntity chasedEntity) { -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java -index 34a9843267ef739e5889791fb4899fabe1f864bc..63723044ae6c607e6d36bc0b0c6b525037df34b2 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java -@@ -68,11 +68,19 @@ public abstract class AbstractChestedHorse extends AbstractHorse { - this.spawnAtLocation((ItemLike) Blocks.CHEST); - } - -- this.setChest(false); -+ //this.setCarryingChest(false); // Paper - moved to post death logic - } - - } - -+ // Paper start -+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) { -+ if (this.hasChest() && (event == null || !event.isCancelled())) { -+ this.setChest(false); -+ } -+ } -+ // Paper end -+ - @Override - public void addAdditionalSaveData(CompoundTag tag) { - super.addAdditionalSaveData(tag); -diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 2994eee1d381af2c9ff3649dd48a2ae14c38c9d7..33d51852ed6fe3f5adcdecf8f405a23689f4265a 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -610,7 +610,7 @@ public class ArmorStand extends LivingEntity { - this.armorItems.set(i, ItemStack.EMPTY); - } - } -- this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above -+ this.d(damageSource); // CraftBukkit - moved from above - - } - -@@ -742,7 +742,8 @@ public class ArmorStand extends LivingEntity { - - @Override - public void kill() { -- org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event -+ org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event // Paper - make cancellable -+ if (event.isCancelled()) return; // Paper - make cancellable - this.remove(); - } - -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 14d5acff198338c68162e33d4a90f74be77cb15f..3aadc4ab5fe7b2ee9e20e0789ddcfe750599972f 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -581,7 +581,7 @@ public abstract class Player extends LivingEntity { - super.die(source); - this.reapplyPosition(); - if (!this.isSpectator()) { -- this.dropAllDeathLoot(source); -+ this.d(source); - } - - if (source != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ee823c4ed5b9fcfaa900b470c582435f0b909ebc..a3e65028d3e0c09a65cd9c28b037fe01a2ed1d76 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1836,7 +1836,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void sendHealthUpdate() { -- getHandle().connection.send(new ClientboundSetHealthPacket(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); -+ // Paper start - cancellable death event -+ //getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); -+ ClientboundSetHealthPacket packet = new ClientboundSetHealthPacket(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel()); -+ if (this.getHandle().queueHealthUpdatePacket) { -+ this.getHandle().queuedHealthUpdatePacket = packet; -+ } else { -+ this.getHandle().connection.send(packet); -+ } -+ // Paper end - } - - 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 1877267344df1ff5b4de6a4e0c239f488cd52c1f..e696d2e52532df25d74a1f559e2c9ca0f3d5058d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -18,6 +18,8 @@ import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.sounds.SoundEvent; -+import net.minecraft.sounds.SoundSource; - import net.minecraft.util.Unit; - import net.minecraft.world.Container; - import net.minecraft.world.InteractionHand; -@@ -793,9 +795,16 @@ public class CraftEventFactory { - public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, List drops) { - CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); - EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward()); -+ populateFields(victim, event); // Paper - make cancellable - CraftWorld world = (CraftWorld) entity.getWorld(); - Bukkit.getServer().getPluginManager().callEvent(event); - -+ // Paper start - make cancellable -+ if (event.isCancelled()) { -+ return event; -+ } -+ playDeathSound(victim, event); -+ // Paper end - victim.expToDrop = event.getDroppedExp(); - - for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { -@@ -811,8 +820,15 @@ public class CraftEventFactory { - CraftPlayer entity = victim.getBukkitEntity(); - PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure - event.setKeepInventory(keepInventory); -+ populateFields(victim, event); // Paper - make cancellable - org.bukkit.World world = entity.getWorld(); - Bukkit.getServer().getPluginManager().callEvent(event); -+ // Paper start - make cancellable -+ if (event.isCancelled()) { -+ return event; -+ } -+ playDeathSound(victim, event); -+ // Paper end - - victim.keepLevel = event.getKeepLevel(); - victim.newLevel = event.getNewLevel(); -@@ -829,6 +845,31 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start - helper methods for making death event cancellable -+ // Add information to death event -+ private static void populateFields(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) { -+ event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue()); -+ event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent()); -+ SoundEvent soundEffect = victim.getDeathSoundEffect(); -+ event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null); -+ event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundSource().name())); -+ event.setDeathSoundVolume(victim.getDeathSoundVolume()); -+ event.setDeathSoundPitch(victim.getSoundPitch()); -+ } -+ -+ // Play death sound manually -+ private static void playDeathSound(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) { -+ if (event.shouldPlayDeathSound() && event.getDeathSound() != null && event.getDeathSoundCategory() != null) { -+ net.minecraft.world.entity.player.Player source = victim instanceof net.minecraft.world.entity.player.Player ? (net.minecraft.world.entity.player.Player) victim : null; -+ double x = event.getEntity().getLocation().getX(); -+ double y = event.getEntity().getLocation().getY(); -+ double z = event.getEntity().getLocation().getZ(); -+ SoundEvent soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound()); -+ SoundSource soundCategory = SoundSource.valueOf(event.getDeathSoundCategory().name()); -+ victim.level.playSound(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch()); -+ } -+ } -+ // Paper end - /** - * Server methods - */ diff --git a/Remapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch b/Remapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch deleted file mode 100644 index 59c2f88e09..0000000000 --- a/Remapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 8 Sep 2018 18:43:31 -0500 -Subject: [PATCH] Allow chests to be placed with NBT data - - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 79a7c37f15840dbd97510874ac12437d2b854999..02bfa4fb8055e60a84e878ffbf18303c0ee25b1d 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -296,6 +296,7 @@ public final class ItemStack { - enuminteractionresult = InteractionResult.FAIL; // cancel placement - // PAIL: Remove this when MC-99075 fixed - placeEvent.getPlayer().updateInventory(); -+ world.capturedTileEntities.clear(); // Paper - clear out tile entities as chests and such will pop loot - // revert back all captured blocks - for (BlockState blockstate : blocks) { - blockstate.update(true, false); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java -index 17289d28b6d0023279a573715ee3d182988dd651..ab11c7a5a397047a35245b149d77bf035e718a0c 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java -@@ -326,7 +326,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity { // Pape - // CraftBukkit start - @Override - public boolean onlyOpCanSetNbt() { -- return true; -+ return false; // Paper - } - // CraftBukkit end - } diff --git a/Remapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch b/Remapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch deleted file mode 100644 index 8ae73987bc..0000000000 --- a/Remapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch +++ /dev/null @@ -1,290 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 9 Sep 2018 13:30:00 -0400 -Subject: [PATCH] Mob Pathfinding API - -Implements Pathfinding API for mobs - -diff --git a/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3e7971b7ca5be0442378c9e7482775e05918d0ac ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java -@@ -0,0 +1,141 @@ -+package com.destroystokyo.paper.entity; -+ -+import org.apache.commons.lang.Validate; -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.entity.CraftLivingEntity; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Mob; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import net.minecraft.world.level.pathfinder.Node; -+import net.minecraft.world.level.pathfinder.Path; -+import PathResult; -+import java.util.ArrayList; -+import java.util.List; -+ -+public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder { -+ -+ private final net.minecraft.world.entity.Mob entity; -+ -+ public PaperPathfinder(net.minecraft.world.entity.Mob entity) { -+ this.entity = entity; -+ } -+ -+ @Override -+ public Mob getEntity() { -+ return entity.getBukkitMob(); -+ } -+ -+ @Override -+ public void stopPathfinding() { -+ entity.getNavigation().stopPathfinding(); -+ } -+ -+ @Override -+ public boolean hasPath() { -+ return entity.getNavigation().getPathEntity() != null; -+ } -+ -+ @Nullable -+ @Override -+ public PathResult getCurrentPath() { -+ Path path = entity.getNavigation().getPathEntity(); -+ return path != null ? new PaperPathResult(path) : null; -+ } -+ -+ @Nullable -+ @Override -+ public PathResult findPath(Location loc) { -+ Validate.notNull(loc, "Location can not be null"); -+ Path path = entity.getNavigation().calculateDestination(loc.getX(), loc.getY(), loc.getZ()); -+ return path != null ? new PaperPathResult(path) : null; -+ } -+ -+ @Nullable -+ @Override -+ public PathResult findPath(LivingEntity target) { -+ Validate.notNull(target, "Target can not be null"); -+ Path path = entity.getNavigation().calculateDestination(((CraftLivingEntity) target).getHandle()); -+ return path != null ? new PaperPathResult(path) : null; -+ } -+ -+ @Override -+ public boolean moveTo(@Nonnull PathResult path, double speed) { -+ Validate.notNull(path, "PathResult can not be null"); -+ Path pathEntity = ((PaperPathResult) path).path; -+ return entity.getNavigation().setDestination(pathEntity, speed); -+ } -+ -+ @Override -+ public boolean canOpenDoors() { -+ return entity.getNavigation().getPathfinder().getPathfinder().shouldOpenDoors(); -+ } -+ -+ @Override -+ public void setCanOpenDoors(boolean canOpenDoors) { -+ entity.getNavigation().getPathfinder().getPathfinder().setShouldOpenDoors(canOpenDoors); -+ } -+ -+ @Override -+ public boolean canPassDoors() { -+ return entity.getNavigation().getPathfinder().getPathfinder().shouldPassDoors(); -+ } -+ -+ @Override -+ public void setCanPassDoors(boolean canPassDoors) { -+ entity.getNavigation().getPathfinder().getPathfinder().setShouldPassDoors(canPassDoors); -+ } -+ -+ @Override -+ public boolean canFloat() { -+ return entity.getNavigation().getPathfinder().getPathfinder().shouldFloat(); -+ } -+ -+ @Override -+ public void setCanFloat(boolean canFloat) { -+ entity.getNavigation().getPathfinder().getPathfinder().setShouldFloat(canFloat); -+ } -+ -+ public class PaperPathResult implements com.destroystokyo.paper.entity.PaperPathfinder.PathResult { -+ -+ private final Path path; -+ PaperPathResult(Path path) { -+ this.path = path; -+ } -+ -+ @Nullable -+ @Override -+ public Location getFinalPoint() { -+ Node point = path.getFinalPoint(); -+ return point != null ? toLoc(point) : null; -+ } -+ -+ @Override -+ public List getPoints() { -+ List points = new ArrayList<>(); -+ for (Node point : path.getPoints()) { -+ points.add(toLoc(point)); -+ } -+ return points; -+ } -+ -+ @Override -+ public int getNextPointIndex() { -+ return path.getNextIndex(); -+ } -+ -+ @Nullable -+ @Override -+ public Location getNextPoint() { -+ if (!path.hasNext()) { -+ return null; -+ } -+ return toLoc(path.getPoints().get(path.getNextIndex())); -+ } -+ } -+ -+ private Location toLoc(Node point) { -+ return new Location(entity.level.getWorld(), point.getX(), point.getY(), point.getZ()); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index c3082f5dd64413a47421cb01538bec846bf21d2c..a362506f38e8d30543b6cd6d215db561290dac76 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -100,7 +100,7 @@ public abstract class PathNavigation { - } - - @Nullable -- public final Path createPath(double x, double y, double z, int distance) { -+ public final Path calculateDestination(double d0, double d1, double d2) { return createPath(d0, d1, d2, 0); } public final Path createPath(double x, double y, double z, int distance) { // Paper - OBFHELPER - return this.createPath(new BlockPos(x, y, z), distance); - } - -@@ -125,7 +125,7 @@ public abstract class PathNavigation { - } - - @Nullable -- public Path createPath(Entity entity, int distance) { -+ public final Path calculateDestination(Entity entity) { return createPath(entity, 0); } public Path createPath(Entity entity, int distance) { - return this.a(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper - } - -@@ -190,6 +190,7 @@ public abstract class PathNavigation { - return pathentity != null && this.moveTo(pathentity, speed); - } - -+ public boolean setDestination(@Nullable Path pathentity, double speed) { return moveTo(pathentity, speed); } // Paper - OBFHELPER - public boolean moveTo(@Nullable Path path, double speed) { - if (path == null) { - this.path = null; -@@ -217,7 +218,7 @@ public abstract class PathNavigation { - } - } - -- @Nullable -+ @Nullable public Path getPathEntity() { return getPath(); } @Nullable // Paper - OBFHELPER - public Path getPath() { - return this.path; - } -@@ -341,6 +342,7 @@ public abstract class PathNavigation { - return !this.isDone(); - } - -+ public void stopPathfinding() { stop(); } // Paper - OBFHELPER - public void stop() { - this.path = null; - } -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Node.java b/src/main/java/net/minecraft/world/level/pathfinder/Node.java -index c1ac95d784935f5d3d827e2e390162f594991d2c..27b5d3d02d1f3aa048fefc3ef2222c8031e7661f 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/Node.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/Node.java -@@ -5,9 +5,9 @@ import net.minecraft.util.Mth; - - public class Node { - -- public final int x; -- public final int y; -- public final int z; -+ public final int x; public final int getX() { return x; } // Paper - OBFHELPER -+ public final int y; public final int getY() { return y; } // Paper - OBFHELPER -+ public final int z; public final int getZ() { return z; } // Paper - OBFHELPER - private final int hash; - public int heapIdx = -1; - public float g; -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java -index 0941bd177f65abfed3991267448df7df259d7f04..ddc9a9ececf44ce5524fd98a872e8a53cd7cc4f5 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java -@@ -16,9 +16,9 @@ public abstract class NodeEvaluator { - protected int entityWidth; - protected int entityHeight; - protected int entityDepth; -- protected boolean canPassDoors; -- protected boolean canOpenDoors; -- protected boolean canFloat; -+ protected boolean canPassDoors; public boolean shouldPassDoors() { return canPassDoors; } public void setShouldPassDoors(boolean b) { canPassDoors = b; } // Paper - obfhelper -+ protected boolean canOpenDoors; public boolean shouldOpenDoors() { return canOpenDoors; } public void setShouldOpenDoors(boolean b) { canOpenDoors = b; } // Paper - obfhelper -+ protected boolean canFloat; public boolean shouldFloat() { return canFloat; } public void setShouldFloat(boolean b) { canFloat = b; } // Paper - obfhelper - - public NodeEvaluator() {} - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Path.java b/src/main/java/net/minecraft/world/level/pathfinder/Path.java -index 7bc0787634e3c5a6f76181b166793fb7591767e4..fd5b369b59669b893aaaec17aef1a526fd23d8c0 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/Path.java -@@ -8,13 +8,14 @@ import net.minecraft.world.phys.Vec3; - - public class Path { - -- private final List nodes; -+ private final List nodes; public List getPoints() { return nodes; } // Paper - OBFHELPER - private Node[] openSet = new Node[0]; - private Node[] closedSet = new Node[0]; -- private int nextNodeIndex; -+ private int nextNodeIndex; public int getNextIndex() { return this.nextNodeIndex; } // Paper - OBFHELPER - private final BlockPos target; - private final float distToTarget; - private final boolean reached; -+ public boolean hasNext() { return getNextIndex() < getPoints().size(); } // Paper - - public Path(List nodes, BlockPos target, boolean reachesTarget) { - this.nodes = nodes; -@@ -36,7 +37,7 @@ public class Path { - } - - @Nullable -- public Node getEndNode() { -+ public Node getFinalPoint() { return getEndNode(); } @Nullable public Node getEndNode() { // Paper - OBFHELPER - return !this.nodes.isEmpty() ? (Node) this.nodes.get(this.nodes.size() - 1) : null; - } - -@@ -84,7 +85,7 @@ public class Path { - return this.getEntityPosAtNode(entity, this.nextNodeIndex); - } - -- public BlockPos getNextNodePos() { -+ public BlockPos getNext() { return getNextNodePos(); } public BlockPos getNextNodePos() { // Paper - OBFHELPER - return ((Node) this.nodes.get(this.nextNodeIndex)).asBlockPos(); - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index fd2c5a4e245647f51c1191991dc315b773ff73d4..b5fe55a77c8558cf2ea32689ff57911530df75f9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -11,8 +11,11 @@ import org.bukkit.loot.LootTable; - public abstract class CraftMob extends CraftLivingEntity implements Mob { - public CraftMob(CraftServer server, net.minecraft.world.entity.Mob entity) { - super(server, entity); -+ paperPathfinder = new com.destroystokyo.paper.entity.PaperPathfinder(entity); // Paper - } - -+ private final com.destroystokyo.paper.entity.PaperPathfinder paperPathfinder; // Paper -+ @Override public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { return paperPathfinder; } // Paper - @Override - public void setTarget(LivingEntity target) { - net.minecraft.world.entity.Mob entity = getHandle(); diff --git a/Remapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch b/Remapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch deleted file mode 100644 index 9234ee7b61..0000000000 --- a/Remapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 10 Sep 2018 23:36:16 -0400 -Subject: [PATCH] Prevent chunk loading from Fluid Flowing - - -diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -index 967123992ee86f13f4ca6e336eaf8cebed086a1a..7544bf227b1dded0f854cc1b30d246d120f65b20 100644 ---- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -+++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -@@ -175,7 +175,8 @@ public abstract class FlowingFluid extends Fluid { - Direction enumdirection = (Direction) entry.getKey(); - FluidState fluid1 = (FluidState) entry.getValue(); - BlockPos blockposition1 = pos.relative(enumdirection); -- BlockState iblockdata1 = world.getBlockState(blockposition1); -+ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); // Paper -+ if (iblockdata1 == null) continue; // Paper - - if (this.canSpreadTo(world, pos, blockState, enumdirection, blockposition1, iblockdata1, world.getFluidState(blockposition1), fluid1.getType())) { - // CraftBukkit start -@@ -202,7 +203,8 @@ public abstract class FlowingFluid extends Fluid { - while (iterator.hasNext()) { - Direction enumdirection = (Direction) iterator.next(); - BlockPos blockposition1 = pos.relative(enumdirection); -- BlockState iblockdata1 = world.getBlockState(blockposition1); -+ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); // Paper -+ if (iblockdata1 == null) continue; // Paper - FluidState fluid = iblockdata1.getFluidState(); - - if (fluid.getType().isSame((Fluid) this) && this.canPassThroughWall(enumdirection, (BlockGetter) world, pos, state, blockposition1, iblockdata1)) { -@@ -319,11 +321,18 @@ public abstract class FlowingFluid extends Fluid { - if (enumdirection1 != enumdirection) { - BlockPos blockposition2 = blockposition.relative(enumdirection1); - short short0 = getCacheKey(blockposition1, blockposition2); -- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (k) -> { -- BlockState iblockdata1 = world.getBlockState(blockposition2); -+ // Paper start - avoid loading chunks -+ Pair pair = short2objectmap.get(short0); -+ if (pair == null) { -+ BlockState iblockdatax = world.getTypeIfLoaded(blockposition2); -+ if (iblockdatax == null) { -+ continue; -+ } - -- return Pair.of(iblockdata1, iblockdata1.getFluidState()); -- }); -+ pair = Pair.of(iblockdatax, iblockdatax.getFluidState()); -+ short2objectmap.put(short0, pair); -+ } -+ // Paper end - BlockState iblockdata1 = (BlockState) pair.getFirst(); - FluidState fluid = (FluidState) pair.getSecond(); - -@@ -395,11 +404,16 @@ public abstract class FlowingFluid extends Fluid { - Direction enumdirection = (Direction) iterator.next(); - BlockPos blockposition1 = pos.relative(enumdirection); - short short0 = getCacheKey(pos, blockposition1); -- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (j) -> { -- BlockState iblockdata1 = world.getBlockState(blockposition1); -- -- return Pair.of(iblockdata1, iblockdata1.getFluidState()); -- }); -+ // Paper start -+ Pair pair = (Pair) short2objectmap.get(short0); -+ if (pair == null) { -+ BlockState iblockdatax = world.getTypeIfLoaded(blockposition1); -+ if (iblockdatax == null) continue; -+ -+ pair = Pair.of(iblockdatax, iblockdatax.getFluidState()); -+ short2objectmap.put(short0, pair); -+ } -+ // Paper end - BlockState iblockdata1 = (BlockState) pair.getFirst(); - FluidState fluid = (FluidState) pair.getSecond(); - FluidState fluid1 = this.getNewLiquid(world, blockposition1, iblockdata1); diff --git a/Remapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/Remapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch deleted file mode 100644 index 30b7b72f6c..0000000000 --- a/Remapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch +++ /dev/null @@ -1,446 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Wed, 12 Sep 2018 18:53:55 +0300 -Subject: [PATCH] Implement an API for CanPlaceOn and CanDestroy NBT values - - -diff --git a/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java b/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java -index 9175c74c2119e7052d744db77badcae6be05f3b4..52f8ad848a22ddca856f6f256276ea59416f9664 100644 ---- a/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java -+++ b/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java -@@ -57,7 +57,7 @@ public class BlockStateParser { - private final boolean forTesting; - private final Map, Comparable> properties = Maps.newLinkedHashMap(); // CraftBukkit - stable - private final Map vagueProperties = Maps.newHashMap(); -- private ResourceLocation id = new ResourceLocation(""); -+ private ResourceLocation id = new ResourceLocation(""); public final ResourceLocation getBlockKey() { return this.id; } // Paper - OBFHELPER - private StateDefinition definition; - private BlockState state; - @Nullable -@@ -86,11 +86,13 @@ public class BlockStateParser { - return this.nbt; - } - -+ public final @Nullable ResourceLocation getTagKey() { return getTag(); } // Paper - OBFHELPER - @Nullable - public ResourceLocation getTag() { - return this.tag; - } - -+ public final BlockStateParser parse(boolean parseTile) throws CommandSyntaxException { return this.parse(parseTile); } // Paper - OBFHELPER - public BlockStateParser parse(boolean allowNbt) throws CommandSyntaxException { - this.suggestions = this::suggestBlockIdOrTag; - if (this.reader.canRead() && this.reader.peek() == '#') { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba918f044e51 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -39,12 +39,14 @@ import java.util.logging.Level; - import java.util.logging.Logger; - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -+import net.minecraft.commands.arguments.blocks.BlockStateParser; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.nbt.NbtIo; - import net.minecraft.nbt.StringTag; - import net.minecraft.nbt.Tag; - import net.minecraft.network.chat.TextComponent; -+import net.minecraft.resources.ResourceLocation; - import net.minecraft.world.item.BlockItem; - import org.apache.commons.codec.binary.Base64; - import org.apache.commons.lang.Validate; -@@ -83,6 +85,12 @@ import org.bukkit.persistence.PersistentDataContainer; - import static org.spigotmc.ValidateUtils.*; - // Spigot end - -+// Paper start -+import com.destroystokyo.paper.Namespaced; -+import com.destroystokyo.paper.NamespacedTag; -+import java.util.Collections; -+// Paper end -+ - /** - * Children must include the following: - * -@@ -266,6 +274,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Specific(Specific.To.NBT) - static final ItemMetaKey BLOCK_DATA = new ItemMetaKey("BlockStateTag"); - static final ItemMetaKey BUKKIT_CUSTOM_TAG = new ItemMetaKey("PublicBukkitValues"); -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ static final ItemMetaKey CAN_DESTROY = new ItemMetaKey("CanDestroy"); -+ static final ItemMetaKey CAN_PLACE_ON = new ItemMetaKey("CanPlaceOn"); -+ // Paper end - - // We store the raw original JSON representation of all text data. See SPIGOT-5063, SPIGOT-5656, SPIGOT-5304 - private String displayName; -@@ -279,6 +291,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - private int hideFlag; - private boolean unbreakable; - private int damage; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ private Set placeableKeys = Sets.newHashSet(); -+ private Set destroyableKeys = Sets.newHashSet(); -+ // Paper end - - private static final Set HANDLED_TAGS = Sets.newHashSet(); - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); -@@ -316,6 +332,15 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - this.hideFlag = meta.hideFlag; - this.unbreakable = meta.unbreakable; - this.damage = meta.damage; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (meta.hasPlaceableKeys()) { -+ this.placeableKeys = new java.util.HashSet<>(meta.placeableKeys); -+ } -+ -+ if (meta.hasDestroyableKeys()) { -+ this.destroyableKeys = new java.util.HashSet<>(meta.destroyableKeys); -+ } -+ // Paper end - this.unhandledTags.putAll(meta.unhandledTags); - this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw()); - -@@ -379,6 +404,31 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - persistentDataContainer.put(key, compound.get(key)); - } - } -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (tag.contains(CAN_DESTROY.NBT)) { -+ ListTag list = tag.getList(CAN_DESTROY.NBT, CraftMagicNumbers.NBT.TAG_STRING); -+ for (int i = 0; i < list.size(); i++) { -+ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); -+ if (namespaced == null) { -+ continue; -+ } -+ -+ this.destroyableKeys.add(namespaced); -+ } -+ } -+ -+ if (tag.contains(CAN_PLACE_ON.NBT)) { -+ ListTag list = tag.getList(CAN_PLACE_ON.NBT, CraftMagicNumbers.NBT.TAG_STRING); -+ for (int i = 0; i < list.size(); i++) { -+ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); -+ if (namespaced == null) { -+ continue; -+ } -+ -+ this.placeableKeys.add(namespaced); -+ } -+ } -+ // Paper end - - Set keys = tag.getAllKeys(); - for (String key : keys) { -@@ -517,6 +567,34 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - setDamage(damage); - } - -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ Iterable canPlaceOnSerialized = SerializableMeta.getObject(Iterable.class, map, CAN_PLACE_ON.BUKKIT, true); -+ if (canPlaceOnSerialized != null) { -+ for (Object canPlaceOnElement : canPlaceOnSerialized) { -+ String canPlaceOnRaw = (String) canPlaceOnElement; -+ Namespaced value = this.deserializeNamespaced(canPlaceOnRaw); -+ if (value == null) { -+ continue; -+ } -+ -+ this.placeableKeys.add(value); -+ } -+ } -+ -+ Iterable canDestroySerialized = SerializableMeta.getObject(Iterable.class, map, CAN_DESTROY.BUKKIT, true); -+ if (canDestroySerialized != null) { -+ for (Object canDestroyElement : canDestroySerialized) { -+ String canDestroyRaw = (String) canDestroyElement; -+ Namespaced value = this.deserializeNamespaced(canDestroyRaw); -+ if (value == null) { -+ continue; -+ } -+ -+ this.destroyableKeys.add(value); -+ } -+ } -+ // Paper end -+ - String internal = SerializableMeta.getString(map, "internal", true); - if (internal != null) { - ByteArrayInputStream buf = new ByteArrayInputStream(Base64.decodeBase64(internal)); -@@ -645,6 +723,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - if (hasDamage()) { - itemTag.putInt(DAMAGE.NBT, damage); - } -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (hasPlaceableKeys()) { -+ List items = this.placeableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ itemTag.put(CAN_PLACE_ON.NBT, createNonComponentStringList(items)); -+ } -+ -+ if (hasDestroyableKeys()) { -+ List items = this.destroyableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ itemTag.put(CAN_DESTROY.NBT, createNonComponentStringList(items)); -+ } -+ // Paper end - - for (Map.Entry e : unhandledTags.entrySet()) { - itemTag.put(e.getKey(), e.getValue()); -@@ -661,6 +756,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -+ // Paper start -+ static ListTag createNonComponentStringList(List list) { -+ if (list == null || list.isEmpty()) { -+ return null; -+ } -+ -+ ListTag tagList = new ListTag(); -+ for (String value : list) { -+ tagList.add(StringTag.valueOf(value)); // Paper - NBTTagString.of(String str) -+ } -+ -+ return tagList; -+ } -+ // Paper end -+ - ListTag createStringList(List list) { - if (list == null) { - return null; -@@ -744,7 +854,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - - @Overridden - boolean isEmpty() { -- return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); -+ return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers() || hasPlaceableKeys() || hasDestroyableKeys()); // Paper - Implement an API for CanPlaceOn and CanDestroy NBT values - } - - // Paper start -@@ -1168,7 +1278,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - && (this.hideFlag == that.hideFlag) - && (this.isUnbreakable() == that.isUnbreakable()) - && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) -- && (this.version == that.version); -+ && (this.version == that.version) -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ && (this.hasPlaceableKeys() ? that.hasPlaceableKeys() && this.placeableKeys.equals(that.placeableKeys) : !that.hasPlaceableKeys()) -+ && (this.hasDestroyableKeys() ? that.hasDestroyableKeys() && this.destroyableKeys.equals(that.destroyableKeys) : !that.hasDestroyableKeys()); -+ // Paper end - } - - /** -@@ -1203,6 +1317,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - hash = 61 * hash + (hasDamage() ? this.damage : 0); - hash = 61 * hash + (hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); - hash = 61 * hash + version; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ hash = 61 * hash + (hasPlaceableKeys() ? this.placeableKeys.hashCode() : 0); -+ hash = 61 * hash + (hasDestroyableKeys() ? this.destroyableKeys.hashCode() : 0); -+ // Paper end - return hash; - } - -@@ -1227,6 +1345,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - clone.unbreakable = this.unbreakable; - clone.damage = this.damage; - clone.version = this.version; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (this.placeableKeys != null) { -+ clone.placeableKeys = Sets.newHashSet(this.placeableKeys); -+ } -+ if (this.destroyableKeys != null) { -+ clone.destroyableKeys = Sets.newHashSet(this.destroyableKeys); -+ } -+ // Paper end - return clone; - } catch (CloneNotSupportedException e) { - throw new Error(e); -@@ -1284,6 +1410,24 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - builder.put(DAMAGE.BUKKIT, damage); - } - -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (hasPlaceableKeys()) { -+ List cerealPlaceable = this.placeableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ builder.put(CAN_PLACE_ON.BUKKIT, cerealPlaceable); -+ } -+ -+ if (hasDestroyableKeys()) { -+ List cerealDestroyable = this.destroyableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ builder.put(CAN_DESTROY.BUKKIT, cerealDestroyable); -+ } -+ // Paper end -+ - final Map internalTags = new HashMap(unhandledTags); - serializeInternal(internalTags); - if (!internalTags.isEmpty()) { -@@ -1448,6 +1592,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - CraftMetaArmorStand.SHOW_ARMS.NBT, - CraftMetaArmorStand.SMALL.NBT, - CraftMetaArmorStand.MARKER.NBT, -+ CAN_DESTROY.NBT, -+ CAN_PLACE_ON.NBT, - // Paper end - CraftMetaCompass.LODESTONE_DIMENSION.NBT, - CraftMetaCompass.LODESTONE_POS.NBT, -@@ -1475,4 +1621,147 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - // Paper end - -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ @Override -+ @SuppressWarnings("deprecation") -+ public Set getCanDestroy() { -+ return !hasDestroyableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.destroyableKeys); -+ } -+ -+ @Override -+ @SuppressWarnings("deprecation") -+ public void setCanDestroy(Set canDestroy) { -+ Validate.notNull(canDestroy, "Cannot replace with null set!"); -+ legacyClearAndReplaceKeys(this.destroyableKeys, canDestroy); -+ } -+ -+ @Override -+ @SuppressWarnings("deprecation") -+ public Set getCanPlaceOn() { -+ return !hasPlaceableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.placeableKeys); -+ } -+ -+ @Override -+ @SuppressWarnings("deprecation") -+ public void setCanPlaceOn(Set canPlaceOn) { -+ Validate.notNull(canPlaceOn, "Cannot replace with null set!"); -+ legacyClearAndReplaceKeys(this.placeableKeys, canPlaceOn); -+ } -+ -+ @Override -+ public Set getDestroyableKeys() { -+ return !hasDestroyableKeys() ? Collections.emptySet() : Sets.newHashSet(this.destroyableKeys); -+ } -+ -+ @Override -+ public void setDestroyableKeys(Collection canDestroy) { -+ Validate.notNull(canDestroy, "Cannot replace with null collection!"); -+ Validate.isTrue(ofAcceptableType(canDestroy), "Can only use NamespacedKey or NamespacedTag objects!"); -+ this.destroyableKeys.clear(); -+ this.destroyableKeys.addAll(canDestroy); -+ } -+ -+ @Override -+ public Set getPlaceableKeys() { -+ return !hasPlaceableKeys() ? Collections.emptySet() : Sets.newHashSet(this.placeableKeys); -+ } -+ -+ @Override -+ public void setPlaceableKeys(Collection canPlaceOn) { -+ Validate.notNull(canPlaceOn, "Cannot replace with null collection!"); -+ Validate.isTrue(ofAcceptableType(canPlaceOn), "Can only use NamespacedKey or NamespacedTag objects!"); -+ this.placeableKeys.clear(); -+ this.placeableKeys.addAll(canPlaceOn); -+ } -+ -+ @Override -+ public boolean hasPlaceableKeys() { -+ return this.placeableKeys != null && !this.placeableKeys.isEmpty(); -+ } -+ -+ @Override -+ public boolean hasDestroyableKeys() { -+ return this.destroyableKeys != null && !this.destroyableKeys.isEmpty(); -+ } -+ -+ @Deprecated -+ private void legacyClearAndReplaceKeys(Collection toUpdate, Collection beingSet) { -+ if (beingSet.stream().anyMatch(Material::isLegacy)) { -+ throw new IllegalArgumentException("Set must not contain any legacy materials!"); -+ } -+ -+ toUpdate.clear(); -+ toUpdate.addAll(beingSet.stream().map(Material::getKey).collect(java.util.stream.Collectors.toSet())); -+ } -+ -+ @Deprecated -+ private Set legacyGetMatsFromKeys(Collection names) { -+ Set mats = Sets.newHashSet(); -+ for (Namespaced key : names) { -+ if (!(key instanceof org.bukkit.NamespacedKey)) { -+ continue; -+ } -+ -+ Material material = Material.matchMaterial(key.toString(), false); -+ if (material != null) { -+ mats.add(material); -+ } -+ } -+ -+ return mats; -+ } -+ -+ private @Nullable Namespaced deserializeNamespaced(String raw) { -+ boolean isTag = raw.length() > 0 && raw.codePointAt(0) == '#'; -+ BlockStateParser blockParser = new BlockStateParser(new com.mojang.brigadier.StringReader(raw), true); -+ try { -+ blockParser = blockParser.parse(false); -+ } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) { -+ e.printStackTrace(); -+ return null; -+ } -+ -+ ResourceLocation key; -+ if (isTag) { -+ key = blockParser.getTagKey(); -+ } else { -+ key = blockParser.getBlockKey(); -+ } -+ -+ if (key == null) { -+ return null; -+ } -+ -+ // don't DC the player if something slips through somehow -+ Namespaced resource = null; -+ try { -+ if (isTag) { -+ resource = new NamespacedTag(key.getNamespace(), key.getPath()); -+ } else { -+ resource = CraftNamespacedKey.fromMinecraft(key); -+ } -+ } catch (IllegalArgumentException ex) { -+ org.bukkit.Bukkit.getLogger().warning("Namespaced resource does not validate: " + key.toString()); -+ ex.printStackTrace(); -+ } -+ -+ return resource; -+ } -+ -+ private @Nonnull String serializeNamespaced(Namespaced resource) { -+ return resource.toString(); -+ } -+ -+ // not a fan of this -+ private boolean ofAcceptableType(Collection namespacedResources) { -+ -+ for (Namespaced resource : namespacedResources) { -+ if (!(resource instanceof org.bukkit.NamespacedKey || resource instanceof com.destroystokyo.paper.NamespacedTag)) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/Remapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch deleted file mode 100644 index dff6bf782c..0000000000 --- a/Remapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 10 Sep 2018 23:56:36 -0400 -Subject: [PATCH] Prevent Mob AI Rules from Loading Chunks - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java -index 415661c61eb85ac57dd2ba81fb62f8d9df54153f..c9825bc1894904fab34bec8223adf8e343bb6623 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java -@@ -29,11 +29,13 @@ public class RemoveBlockGoal extends MoveToBlockGoal { - private final Block blockToRemove; - private final Mob removerMob; - private int ticksSinceReachedGoal; -+ private Level world; // Paper - - public RemoveBlockGoal(Block targetBlock, PathfinderMob mob, double speed, int maxYDifference) { - super(mob, speed, 24, maxYDifference); - this.blockToRemove = targetBlock; - this.removerMob = mob; -+ this.world = mob.level; // Paper - } - - @Override -@@ -131,7 +133,9 @@ public class RemoveBlockGoal extends MoveToBlockGoal { - - @Nullable - private BlockPos getPosWithBlock(BlockPos pos, BlockGetter world) { -- if (world.getBlockState(pos).is(this.blockToRemove)) { -+ Block block = world.getBlockIfLoaded(pos); // Paper -+ if (block == null) return null; // Paper -+ if (block.is(this.blockToRemove)) { // Paper - return pos; - } else { - BlockPos[] ablockposition = new BlockPos[]{pos.below(), pos.west(), pos.east(), pos.north(), pos.south(), pos.below().below()}; -@@ -141,7 +145,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal { - for (int j = 0; j < i; ++j) { - BlockPos blockposition1 = ablockposition1[j]; - -- if (world.getBlockState(blockposition1).is(this.blockToRemove)) { -+ if (world.getBlockIfLoaded(blockposition1).is(this.blockToRemove)) { // Paper - return blockposition1; - } - } -@@ -152,7 +156,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal { - - @Override - protected boolean isValidTarget(LevelReader world, BlockPos pos) { -- ChunkAccess ichunkaccess = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, false); -+ ChunkAccess ichunkaccess = world.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4); // Paper - - return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).is(this.blockToRemove) && ichunkaccess.getBlockState(pos.above()).isAir() && ichunkaccess.getBlockState(pos.above(2)).isAir(); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java b/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java -index 246cbddb23781e323d022db2fbeef72c9eeaad2b..55d484fd4774cfad8f8ba3263b387243540e31b1 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java -+++ b/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java -@@ -13,6 +13,7 @@ import net.minecraft.util.Mth; - import net.minecraft.world.entity.PathfinderMob; - import net.minecraft.world.entity.ai.navigation.PathNavigation; - import net.minecraft.world.level.BlockGetter; -+import net.minecraft.world.level.material.FluidState; - import net.minecraft.world.level.pathfinder.BlockPathTypes; - import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; - import net.minecraft.world.phys.Vec3; -@@ -128,6 +129,7 @@ public class RandomPos { - } - - blockposition2 = new BlockPos((double) k1 + mob.getX(), (double) l1 + mob.getY(), (double) i2 + mob.getZ()); -+ if (!mob.level.hasChunkAt(blockposition2)) continue; // Paper - if (blockposition2.getY() >= 0 && blockposition2.getY() <= mob.level.getMaxBuildHeight() && (!flag3 || mob.isWithinRestriction(blockposition2)) && (!validPositionsOnly || navigationabstract.isStableDestination(blockposition2))) { - if (aboveGround) { - blockposition2 = moveUpToAboveSolid(blockposition2, random.nextInt(distanceAboveGroundRange + 1) + minDistanceAboveGround, mob.level.getMaxBuildHeight(), (blockposition3) -> { -@@ -135,7 +137,8 @@ public class RandomPos { - }); - } - -- if (notInWater || !mob.level.getFluidState(blockposition2).is((Tag) FluidTags.WATER)) { -+ FluidState fluid = mob.level.getFluidIfLoaded(blockposition2); // Paper -+ if (notInWater || (fluid != null && !fluid.is((Tag) FluidTags.WATER))) { // Paper - BlockPathTypes pathtype = WalkNodeEvaluator.getBlockPathTypeStatic((BlockGetter) mob.level, blockposition2.mutable()); - - if (mob.getPathfindingMalus(pathtype) == 0.0F) { diff --git a/Remapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch b/Remapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch deleted file mode 100644 index 759560db06..0000000000 --- a/Remapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 12 Sep 2018 21:12:57 -0400 -Subject: [PATCH] Prevent mob spawning from loading/generating chunks - -also prevents if out of world border bounds - -diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index b90a275a0dc2913809ce16659eed445501e486de..e23875ae07c23fed1161ea070e63bbc3a30168a0 100644 ---- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java -+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -174,9 +174,9 @@ public final class NaturalSpawner { - StructureFeatureManager structuremanager = world.structureFeatureManager(); - ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); - int i = pos.getY(); -- BlockState iblockdata = chunk.getBlockState(pos); -+ BlockState iblockdata = world.getTypeIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn - -- if (!iblockdata.isRedstoneConductor(chunk, pos)) { -+ if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn - BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); - int j = 0; - int k = 0; -@@ -205,7 +205,7 @@ public final class NaturalSpawner { - if (entityhuman != null) { - double d2 = entityhuman.distanceToSqr(d0, (double) i, d1); - -- if (isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2)) { -+ if (isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2) && world.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn - if (biomesettingsmobs_c == null) { - biomesettingsmobs_c = getRandomSpawnMobAt(world, structuremanager, chunkgenerator, group, world.random, (BlockPos) blockposition_mutableblockposition); - if (biomesettingsmobs_c == null) { diff --git a/Remapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/Remapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch deleted file mode 100644 index db7b1e6312..0000000000 --- a/Remapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 12 Sep 2018 21:47:01 -0400 -Subject: [PATCH] Optimize Biome Mob Lookups for Mob Spawning - -Uses an EnumMap as well as a Set paired List for O(1) contains calls. - -diff --git a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java -index 58ee27a994b4cd845b8bb28e80cc2102c860f097..528f42c63a1186b8827bfe7cf6193e14da938cb3 100644 ---- a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java -+++ b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java -@@ -30,19 +30,28 @@ public class MobSpawnSettings { - }, (enumcreaturetype) -> { - return ImmutableList.of(); - })), ImmutableMap.of(), false); -+ // Paper start- decompile error workaround -+ private static class bProxy extends MobSpawnSettings.MobSpawnCost { -+ private bProxy(double gravityLimit, double mass) { -+ super(gravityLimit, mass); -+ } -+ } -+ private static class cProxy extends MobSpawnSettings.SpawnerData { -+ public cProxy(EntityType type, int weight, int minGroupSize, int maxGroupSize) { -+ super(type, weight, minGroupSize, maxGroupSize); -+ } -+ }; -+ // Paper end - public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { -- RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { -- return biomesettingsmobs.d; -+ RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { // Paper - add type to builder -+ return biomesettingsmobs.creatureGenerationProbability; - }); -- Codec codec = MobCategory.CODEC; -- Codec codec1 = BiomeSettingsMobs.c.b.listOf(); -- Logger logger = MobSpawnSettings.LOGGER; -- -- logger.getClass(); -- return instance.group(recordcodecbuilder, Codec.simpleMap(codec, codec1.promotePartial(Util.prefix("Spawn data: ", logger::error)), StringRepresentable.keys(MobCategory.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { -- return biomesettingsmobs.e; -- }), Codec.simpleMap(Registry.ENTITY_TYPE, BiomeSettingsMobs.b.a, Registry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { -- return biomesettingsmobs.f; -+ // Paper - remove unused vars -+ -+ return instance.group(recordcodecbuilder, Codec.simpleMap(MobCategory.CODEC, cProxy.CODEC.listOf().promotePartial(Util.prefix("Spawn data: ", MobSpawnSettings.LOGGER::error)), StringRepresentable.keys(MobCategory.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { // Paper - inline codec, cProxy, LOGGER -+ return biomesettingsmobs.spawners; -+ }), Codec.simpleMap(Registry.ENTITY_TYPE, bProxy.CODEC, Registry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { // Paper - decompile error - bProxy -+ return biomesettingsmobs.mobSpawnCosts; - }), Codec.BOOL.fieldOf("player_spawn_friendly").orElse(false).forGetter(MobSpawnSettings::playerSpawnFriendly)).apply(instance, MobSpawnSettings::new); - }); - private final float creatureGenerationProbability; -@@ -76,11 +85,43 @@ public class MobSpawnSettings { - - public static class Builder { - -- private final Map> spawners = (Map) Stream.of(MobCategory.values()).collect(ImmutableMap.toImmutableMap((enumcreaturetype) -> { -+ // Paper start - keep track of data in a pair set to give O(1) contains calls - we have to hook removals incase plugins mess with it -+ public static class MobList extends java.util.ArrayList { -+ java.util.Set biomes = new java.util.HashSet<>(); -+ -+ @Override -+ public boolean contains(Object o) { -+ return biomes.contains(o); -+ } -+ -+ @Override -+ public boolean add(MobSpawnSettings.SpawnerData BiomeSettingsMobs) { -+ biomes.add(BiomeSettingsMobs); -+ return super.add(BiomeSettingsMobs); -+ } -+ -+ @Override -+ public MobSpawnSettings.SpawnerData remove(int index) { -+ MobSpawnSettings.SpawnerData removed = super.remove(index); -+ if (removed != null) { -+ biomes.remove(removed); -+ } -+ return removed; -+ } -+ -+ @Override -+ public void clear() { -+ biomes.clear(); -+ super.clear(); -+ } -+ } -+ // use toImmutableEnumMap collector -+ private final Map> spawners = (Map) Stream.of(MobCategory.values()).collect(Maps.toImmutableEnumMap((enumcreaturetype) -> { - return enumcreaturetype; - }, (enumcreaturetype) -> { -- return Lists.newArrayList(); -+ return new MobList(); // Use MobList instead of ArrayList - })); -+ // Paper end - private final Map, MobSpawnSettings.MobSpawnCost> mobSpawnCosts = Maps.newLinkedHashMap(); - private float creatureGenerationProbability = 0.1F; - private boolean playerCanSpawn; diff --git a/Remapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch b/Remapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch deleted file mode 100644 index 4b104b38ec..0000000000 --- a/Remapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tassu -Date: Thu, 13 Sep 2018 08:45:21 +0300 -Subject: [PATCH] Implement furnace cook speed multiplier API - -Signed-off-by: Tassu - -Fixed an issue where a furnace's cook-speed multiplier rounds down -to the nearest Integer when updating its current cook time. - -Modified by: Eric Su - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 8c55c1d88ef2e20e82bcdae0b9b3d381e562051f..4126a36dbc7750108a883f0be14dcb0d2e6d7ae8 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -38,6 +38,7 @@ import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.phys.Vec3; - // CraftBukkit start -+import java.util.List; - import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.entity.CraftHumanEntity; - import org.bukkit.craftbukkit.inventory.CraftItemStack; -@@ -56,6 +57,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - protected NonNullList items; - public int litTime; - private int litDuration; -+ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API - public int cookingProgress; - public int cookingTotalTime; - protected final ContainerData dataAccess; -@@ -256,6 +258,11 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - this.recipesUsed.put(new ResourceLocation(s), nbttagcompound1.getInt(s)); - } - -+ // Paper start - cook speed API -+ if (tag.contains("Paper.CookSpeedMultiplier")) { -+ this.cookSpeedMultiplier = tag.getDouble("Paper.CookSpeedMultiplier"); -+ } -+ // Paper end - } - - @Override -@@ -264,6 +271,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - tag.putShort("BurnTime", (short) this.litTime); - tag.putShort("CookTime", (short) this.cookingProgress); - tag.putShort("CookTimeTotal", (short) this.cookingTotalTime); -+ tag.putDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API - ContainerHelper.saveAllItems(tag, this.items); - CompoundTag nbttagcompound1 = new CompoundTag(); - -@@ -324,7 +332,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - - if (this.isLit() && this.canBurn(irecipe)) { - ++this.cookingProgress; -- if (this.cookingProgress == this.cookingTotalTime) { -+ if (this.cookingProgress >= this.cookingTotalTime) { // Paper - cook speed multiplier API - this.cookingProgress = 0; - this.cookingTotalTime = this.getTotalCookTime(); - this.burn(irecipe); -@@ -424,9 +432,13 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - } - } - -- protected int getTotalCookTime() { -- return (this.hasLevel()) ? (Integer) this.level.getRecipeManager().getRecipeFor((RecipeType) this.recipeType, this, this.level).map(AbstractCookingRecipe::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail -+ // Paper begin - Expose this function so CraftFurnace can correctly scale the total cooking time to a new multiplier -+ public int getTotalCookTime() { -+ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */ -+ int cookTime = (this.hasLevel()) ? (Integer) this.level.getRecipeManager().getRecipeFor((RecipeType) this.recipeType, this, this.level).map(AbstractCookingRecipe::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail -+ return (int) Math.ceil (cookTime / this.cookSpeedMultiplier); - } -+ // Paper end - - public static boolean isFuel(ItemStack stack) { - return getFuel().containsKey(stack.getItem()); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -index 5028a6388f95a14df8d1590cddd7414d8de5bf78..a69785c331c6cee34ba4e93f47865ab8e29ec9b8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -@@ -63,4 +63,20 @@ public abstract class CraftFurnace extends - public void setCookTimeTotal(int cookTimeTotal) { - this.getSnapshot().cookingTotalTime = cookTimeTotal; - } -+ -+ // Paper start - cook speed multiplier API -+ @Override -+ public double getCookSpeedMultiplier() { -+ return this.getSnapshot().cookSpeedMultiplier; -+ } -+ -+ @Override -+ public void setCookSpeedMultiplier(double multiplier) { -+ com.google.common.base.Preconditions.checkArgument(multiplier >= 0, "Furnace speed multiplier cannot be negative"); -+ com.google.common.base.Preconditions.checkArgument(multiplier <= 200, "Furnace speed multiplier cannot more than 200"); -+ T snapshot = this.getSnapshot(); -+ snapshot.cookSpeedMultiplier = multiplier; -+ snapshot.cookingTotalTime = snapshot.getTotalCookTime(); // Update the snapshot's current total cook time to scale with the newly set multiplier -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch b/Remapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch deleted file mode 100644 index cb777e4c22..0000000000 --- a/Remapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 18 Sep 2018 23:53:23 +0100 -Subject: [PATCH] PreSpawnerSpawnEvent - -This adds a separate event before an entity is spawned by a spawner -which contains the location of the spawner too similarly to how the -SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for -spawners. - -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index ac572eba10a7239d71dfae060f623b076d4252ce..1ce675d0d24ceb5724f5ac2d8f671e38f2735f74 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -132,11 +132,11 @@ public abstract class BaseSpawner { - - org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); - if (type != null) { -- com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -- event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent( - MCUtil.toLocation(world, d3, d4, d5), - type, -- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER -+ MCUtil.toLocation(world, blockposition) - ); - if (!event.callEvent()) { - flag = true; diff --git a/Remapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch b/Remapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch deleted file mode 100644 index a418dc54d3..0000000000 --- a/Remapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 22 Sep 2018 15:56:59 -0400 -Subject: [PATCH] Catch JsonParseException in Entity and TE names - -As a result, data that no longer parses correctly will not crash the server -instead just logging the exception and continuing (and in most cases should -fix the data) - -Player data is fixed pretty much immediately but some block data (like -Shulkers) may need to be changed in order for it to re-save properly - -No more crashing though. - -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 68c3f069f8f832ab3d146748348aded69b5ad823..1fecc81b25109592907623741225a6222a8c5ccc 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -7,6 +7,8 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.network.chat.Component; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkPos; -@@ -514,4 +516,19 @@ public final class MCUtil { - return null; - } - } -+ -+ @Nullable -+ public static Component getBaseComponentFromNbt(String key, CompoundTag compound) { -+ if (!compound.contains(key)) { -+ return null; -+ } -+ String string = compound.getString(key); -+ try { -+ return Component.Serializer.jsonToComponent(string); -+ } catch (com.google.gson.JsonParseException e) { -+ org.bukkit.Bukkit.getLogger().warning("Unable to parse " + key + " from " + compound +": " + e.getMessage()); -+ } -+ -+ return null; -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java -index 9ad077259563a3d960d32a59d4b6fc3cfbe3440c..00dc4cd436023b946d7005f17a7ba983a4bbdfb6 100644 ---- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java -+++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java -@@ -12,6 +12,7 @@ import net.minecraft.commands.CommandSourceStack; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TextComponent; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.StringUtil; -@@ -72,7 +73,7 @@ public abstract class BaseCommandBlock implements CommandSource { - this.command = tag.getString("Command"); - this.successCount = tag.getInt("SuccessCount"); - if (tag.contains("CustomName", 8)) { -- this.setName(Component.Serializer.fromJson(tag.getString("CustomName"))); -+ this.setName(MCUtil.getBaseComponentFromNbt("CustomName", tag)); // Paper - Catch ParseException - } - - if (tag.contains("TrackOutput", 1)) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java -index 2e3ec85e7bd1c375db0662dba2617d8924dbd2a6..2c885be67b9c992b96f5caf78130d46abb455ceb 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java -@@ -9,6 +9,7 @@ import net.minecraft.nbt.ListTag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; -+import net.minecraft.server.MCUtil; - import net.minecraft.world.Nameable; - import net.minecraft.world.item.DyeColor; - import net.minecraft.world.item.ItemStack; -@@ -70,7 +71,7 @@ public class BannerBlockEntity extends BlockEntity implements Nameable { - public void load(BlockState state, CompoundTag tag) { - super.load(state, tag); - if (tag.contains("CustomName", 8)) { -- this.name = Component.Serializer.fromJson(tag.getString("CustomName")); -+ this.name = MCUtil.getBaseComponentFromNbt("CustomName", tag); // Paper - Catch ParseException - } - - if (this.hasLevel()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -index a7358274fe367a113b304a5ce332b8dcf721b7af..2b420109e9bed184aaa4ffbcee666b4c325c5a28 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -@@ -4,6 +4,7 @@ import javax.annotation.Nullable; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.world.Container; -@@ -30,7 +31,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co - super.load(state, tag); - this.lockKey = LockCode.fromTag(tag); - if (tag.contains("CustomName", 8)) { -- this.name = Component.Serializer.fromJson(tag.getString("CustomName")); -+ this.name = MCUtil.getBaseComponentFromNbt("CustomName", tag); // Paper - Catch ParseException - } - - } diff --git a/Remapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch b/Remapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch deleted file mode 100644 index a2b0c4fa76..0000000000 --- a/Remapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Sep 2018 20:59:53 -0500 -Subject: [PATCH] Honor EntityAgeable.ageLock - - -diff --git a/src/main/java/net/minecraft/world/entity/AgableMob.java b/src/main/java/net/minecraft/world/entity/AgableMob.java -index d7c19e5607bcf92c874b3656c2742f4c84dceb12..354311dc541588212a2eacba38e60c7e34aa4c2b 100644 ---- a/src/main/java/net/minecraft/world/entity/AgableMob.java -+++ b/src/main/java/net/minecraft/world/entity/AgableMob.java -@@ -82,6 +82,7 @@ public abstract class AgableMob extends PathfinderMob { - } - - public void ageUp(int age, boolean overGrow) { -+ if (ageLocked) return; // Paper - GH-1459 - int j = this.getAge(); - int k = j; - diff --git a/Remapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch b/Remapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch deleted file mode 100644 index 354aa4e66c..0000000000 --- a/Remapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 2 Oct 2018 09:57:50 +0100 -Subject: [PATCH] Configurable connection throttle kick message - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 62621562137cba4804f0465c58d25ca2786328e5..7178b37f7978c7e9031a22726005c5099fd78fe0 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -281,6 +281,11 @@ public class PaperConfig { - authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); - } - -+ public static String connectionThrottleKickMessage = "Connection throttled! Please wait before reconnecting."; -+ private static void connectionThrottleKickMessage() { -+ connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); -+ } -+ - private static void savePlayerData() { - Object val = config.get("settings.save-player-data"); - if (val instanceof Boolean) { -diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -index 45c9dc9c2a580a5cd57fd4e891fbaa2b1336f5c5..6f98be2b9b00f71dd041e7511c70166fdecf0749 100644 ---- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -@@ -50,7 +50,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - synchronized (throttleTracker) { - if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { - throttleTracker.put(address, currentTime); -- TranslatableComponent chatmessage = new TranslatableComponent("Connection throttled! Please wait before reconnecting."); -+ TranslatableComponent chatmessage = new TranslatableComponent(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message - this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); - this.connection.disconnect(chatmessage); - return; diff --git a/Remapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch b/Remapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch deleted file mode 100644 index 06025aa8c5..0000000000 --- a/Remapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 3 Oct 2018 20:09:18 -0400 -Subject: [PATCH] Hook into CB plugin rewrites - -Allows us to do fun stuff like rewrite the OBC util fastutil location to -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 45cbdcfc131bbc0e2bf23cc30a572df72eecd51c..49e5a86c223f1b28ce7da6ced276b2f880777856 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -@@ -6,7 +6,9 @@ import java.io.FileOutputStream; - import java.io.InputStream; - import java.util.Arrays; - import java.util.Enumeration; -+import java.util.HashMap; - import java.util.HashSet; -+import java.util.Map; - import java.util.Set; - import java.util.jar.JarEntry; - import java.util.jar.JarFile; -@@ -20,10 +22,15 @@ import org.bukkit.plugin.AuthorNagException; - import org.objectweb.asm.ClassReader; - import org.objectweb.asm.ClassVisitor; - import org.objectweb.asm.ClassWriter; -+import org.objectweb.asm.FieldVisitor; -+import org.objectweb.asm.Handle; -+import org.objectweb.asm.Label; - import org.objectweb.asm.MethodVisitor; - import org.objectweb.asm.Opcodes; - import org.objectweb.asm.Type; - -+import javax.annotation.Nonnull; -+ - /** - * This file is imported from Commodore. - * -@@ -46,6 +53,42 @@ public class Commodore - "org/bukkit/inventory/ItemStack (I)V setTypeId" - ) ); - -+ // Paper start - Plugin rewrites -+ private static final Map SEARCH_AND_REMOVE = initReplacementsMap(); -+ private static Map initReplacementsMap() -+ { -+ Map getAndRemove = new HashMap<>(); -+ // Be wary of maven shade's relocations -+ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/libs/it/unimi/dsi/fastutil/" ), "org/bukkit/".concat( "craftbukkit/libs/" ) ); // Remap fastutil to our location -+ -+ if ( Boolean.getBoolean( "debug.rewriteForIde" ) ) -+ { -+ // unversion incoming calls for pre-relocate debug work -+ final String NMS_REVISION_PACKAGE = "v1_16_R3/"; -+ -+ getAndRemove.put( "net/minecraft/".concat( "server/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); -+ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); -+ } -+ -+ return getAndRemove; -+ } -+ -+ @Nonnull -+ private static String getOriginalOrRewrite(@Nonnull String original) -+ { -+ String rewrite = null; -+ for ( Map.Entry entry : SEARCH_AND_REMOVE.entrySet() ) -+ { -+ if ( original.contains( entry.getKey() ) ) -+ { -+ rewrite = original.replace( entry.getValue(), "" ); -+ } -+ } -+ -+ return rewrite != null ? rewrite : original; -+ } -+ // Paper end -+ - public static void main(String[] args) - { - OptionParser parser = new OptionParser(); -@@ -130,15 +173,86 @@ public class Commodore - - cr.accept( new ClassVisitor( Opcodes.ASM9, cw ) - { -+ // Paper start - Rewrite plugins -+ @Override -+ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) -+ { -+ desc = getOriginalOrRewrite( desc ); -+ if ( signature != null ) { -+ signature = getOriginalOrRewrite( signature ); -+ } -+ -+ return super.visitField( access, name, desc, signature, value) ; -+ } -+ // Paper end -+ - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) - { - return new MethodVisitor( api, super.visitMethod( access, name, desc, signature, exceptions ) ) - { -+ // Paper start - Plugin rewrites -+ @Override -+ public void visitInvokeDynamicInsn(String name, String desc, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) -+ { -+ // Paper start - Rewrite plugins -+ name = getOriginalOrRewrite( name ); -+ if ( desc != null ) -+ { -+ desc = getOriginalOrRewrite( desc ); -+ } -+ // Paper end -+ -+ super.visitInvokeDynamicInsn( name, desc, bootstrapMethodHandle, bootstrapMethodArguments ); -+ } -+ -+ @Override -+ public void visitTypeInsn(int opcode, String type) -+ { -+ type = getOriginalOrRewrite( type ); -+ -+ super.visitTypeInsn( opcode, type ); -+ } -+ -+ @Override -+ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { -+ for ( int i = 0; i < local.length; i++ ) -+ { -+ if ( !( local[i] instanceof String ) ) { continue; } -+ -+ local[i] = getOriginalOrRewrite( (String) local[i] ); -+ } -+ -+ for ( int i = 0; i < stack.length; i++ ) -+ { -+ if ( !( stack[i] instanceof String ) ) { continue; } -+ -+ stack[i] = getOriginalOrRewrite( (String) stack[i] ); -+ } -+ -+ super.visitFrame( type, nLocal, local, nStack, stack ); -+ } -+ -+ @Override -+ public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) -+ { -+ descriptor = getOriginalOrRewrite( descriptor ); -+ -+ super.visitLocalVariable( name, descriptor, signature, start, end, index ); -+ } -+ // Paper end - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) - { -+ // Paper start - Rewrite plugins -+ owner = getOriginalOrRewrite( owner ); -+ if ( desc != null ) -+ { -+ desc = getOriginalOrRewrite( desc ); -+ } -+ // Paper end -+ - if ( owner.equals( "org/bukkit/block/Biome" ) ) - { - switch ( name ) -@@ -270,6 +384,14 @@ public class Commodore - return; - } - -+ // Paper start - Rewrite plugins -+ owner = getOriginalOrRewrite( owner) ; -+ if (desc != null) -+ { -+ desc = getOriginalOrRewrite(desc); -+ } -+ // Paper end -+ - if ( modern ) - { - if ( owner.equals( "org/bukkit/Material" ) ) diff --git a/Remapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch b/Remapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch deleted file mode 100644 index ee472ab644..0000000000 --- a/Remapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 6 Oct 2018 21:47:44 -0500 -Subject: [PATCH] Allow setting the vex's summoner - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java -index ec4f6d96360e759ffc19de838fdbf3027164a424..a4be2bddc5f51601d419647a280c89f7101371f2 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Vex.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java -@@ -165,6 +165,7 @@ public class Vex extends Monster { - this.setVexFlag(1, charging); - } - -+ public void setOwner(Mob entityinsentient) { setOwner(entityinsentient); } // Paper - OBFHELPER - public void setOwner(Mob owner) { - this.owner = owner; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -index 56bec4350f36a94d4dfa71a234872a795c2dcb3f..07c470f8b049bea930337abc1cc87f4669d2f11a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -@@ -20,6 +20,10 @@ public class CraftVex extends CraftMonster implements Vex { - net.minecraft.world.entity.Mob owner = getHandle().getOwner(); - return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; - } -+ -+ public void setSummoner(org.bukkit.entity.Mob summoner) { -+ getHandle().setOwner(summoner == null ? null : ((CraftMob) summoner).getHandle()); -+ } - // Paper end - - @Override diff --git a/Remapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch b/Remapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch deleted file mode 100644 index 32037c620c..0000000000 --- a/Remapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 Oct 2018 00:54:21 -0500 -Subject: [PATCH] Add sun related API - - -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index f3690ea49cf90c816b8b3554b47d6f2d9dfbe016..29a2eeee9f2011ed6fcc44f19041f616decfdb38 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -1595,6 +1595,7 @@ public abstract class Mob extends LivingEntity { - - } - -+ public boolean isInDaylight() { return this.isSunBurnTick(); } // Paper - OBFHELPER - protected boolean isSunBurnTick() { - if (this.level.isDay() && !this.level.isClientSide) { - float f = this.getBrightness(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 57a2af56b53567371fdb6d0a55866e1e4e37cf3b..7b5abccac9793811bd56340c8f9d23806e832365 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -847,6 +847,13 @@ public class CraftWorld implements World { - } - } - -+ // Paper start -+ @Override -+ public boolean isDayTime() { -+ return getHandle().isDay(); -+ } -+ // Paper end -+ - @Override - public long getGameTime() { - return world.levelData.getGameTime(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index b5fe55a77c8558cf2ea32689ff57911530df75f9..1e3a0851c75d8067d2699f00bb3f6621d1d739d8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -77,4 +77,11 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { - public long getSeed() { - return getHandle().lootTableSeed; - } -+ -+ // Paper start -+ @Override -+ public boolean isInDaylight() { -+ return getHandle().isInDaylight(); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0295-Turtle-API.patch b/Remapped-Spigot-Server-Patches/0295-Turtle-API.patch deleted file mode 100644 index 042449088a..0000000000 --- a/Remapped-Spigot-Server-Patches/0295-Turtle-API.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 29 Sep 2018 16:08:23 -0500 -Subject: [PATCH] Turtle API - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -index 4584fad16a65f06e77e97a0804d88dbe83f7c5c1..c8680e795deeb68e0662eac7c760a103d1c767b4 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -@@ -14,7 +14,7 @@ public abstract class MoveToBlockGoal extends Goal { - protected int nextStartTick; - protected int tryTicks; - private int maxStayTicks; -- protected BlockPos blockPos; -+ protected BlockPos blockPos;public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER - private boolean reachedTarget; - private final int searchRange; - private final int verticalSearchRange; -diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index c54f4b83b9f2fdb15ddb363be0a179a05eb3693b..42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -@@ -14,6 +14,7 @@ import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.syncher.EntityDataAccessor; - import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvent; -@@ -93,7 +94,7 @@ public class Turtle extends Animal { - this.entityData.set(Turtle.HOME_POS, pos); - } - -- private BlockPos getHomePos() { -+ public BlockPos getHomePos() { // Paper - public - return (BlockPos) this.entityData.get(Turtle.HOME_POS); - } - -@@ -109,31 +110,37 @@ public class Turtle extends Animal { - return (Boolean) this.entityData.get(Turtle.HAS_EGG); - } - -- private void setHasEgg(boolean hasEgg) { -+ public void setHasEgg(boolean hasEgg) { // Paper - this.entityData.set(Turtle.HAS_EGG, hasEgg); - } - -+ public final boolean isDigging() { return this.isLayingEgg(); } // Paper - OBFHELPER - public boolean isLayingEgg() { - return (Boolean) this.entityData.get(Turtle.LAYING_EGG); - } - -+ public final void setDigging(boolean digging) { this.setLayingEgg(digging); } // Paper - OBFHELPER - private void setLayingEgg(boolean diggingSand) { - this.layEggCounter = diggingSand ? 1 : 0; - this.entityData.set(Turtle.LAYING_EGG, diggingSand); - } - -+ public final boolean isGoingHome() { return this.isGoingHome(); } // Paper - OBFHELPER - private boolean isGoingHome() { - return (Boolean) this.entityData.get(Turtle.GOING_HOME); - } - -+ public final void setGoingHome(boolean goingHome) { this.setGoingHome(goingHome); } // Paper - OBFHELPER - private void setGoingHome(boolean landBound) { - this.entityData.set(Turtle.GOING_HOME, landBound); - } - -+ public final boolean isTravelling() { return this.isTravelling(); } // Paper - OBFHELPER - private boolean isTravelling() { - return (Boolean) this.entityData.get(Turtle.TRAVELLING); - } - -+ public final void setTravelling(boolean travelling) { this.setTravelling(travelling); } // Paper - OBFHELPER - private void setTravelling(boolean travelling) { - this.entityData.set(Turtle.TRAVELLING, travelling); - } -@@ -500,14 +507,17 @@ public class Turtle extends Animal { - - if (!this.turtle.isInWater() && this.isReachedTarget()) { - if (this.turtle.layEggCounter < 1) { -- this.turtle.setLayingEgg(true); -+ this.turtle.setDigging(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), MCUtil.toLocation(this.turtle.level, this.getTargetPosition())).callEvent()); // Paper - } else if (this.turtle.layEggCounter > 200) { - Level world = this.turtle.level; - - // CraftBukkit start -- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1)).isCancelled()) { -+ // Paper start -+ int eggCount = this.turtle.random.nextInt(4) + 1; -+ com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), MCUtil.toLocation(this.turtle.level, this.blockPos.above()), eggCount); -+ if (layEggEvent.callEvent() && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount())).isCancelled()) { - world.playSound((Player) null, blockposition, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); -- world.setBlock(this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1), 3); -+ world.setBlock(this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()), 3); - } - // CraftBukkit end - this.turtle.setHasEgg(false); -@@ -636,7 +646,7 @@ public class Turtle extends Animal { - - @Override - public boolean canUse() { -- return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(700) != 0 ? false : !this.turtle.getHomePos().closerThan((Position) this.turtle.position(), 64.0D))); -+ return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(700) != 0 ? false : !this.turtle.getHomePos().closerThan((Position) this.turtle.position(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity()).callEvent(); // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -index ed08089f21c8958fc9fc7e6e73a2b6ff9108242c..e50f6051baf34981707adce56ab2d3e1f341fb4c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -@@ -24,4 +24,36 @@ public class CraftTurtle extends CraftAnimals implements Turtle { - public EntityType getType() { - return EntityType.TURTLE; - } -+ -+ // Paper start -+ @Override -+ public org.bukkit.Location getHome() { -+ return net.minecraft.server.MCUtil.toLocation(getHandle().level, getHandle().getHomePos()); -+ } -+ -+ @Override -+ public void setHome(org.bukkit.Location location) { -+ getHandle().setHomePos(net.minecraft.server.MCUtil.toBlockPosition(location)); -+ } -+ -+ @Override -+ public boolean isGoingHome() { -+ return getHandle().isGoingHome(); -+ } -+ -+ @Override -+ public boolean isDigging() { -+ return getHandle().isDigging(); -+ } -+ -+ @Override -+ public boolean hasEgg() { -+ return getHandle().hasEgg(); -+ } -+ -+ @Override -+ public void setHasEgg(boolean hasEgg) { -+ getHandle().setHasEgg(hasEgg); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/Remapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch deleted file mode 100644 index 685d458bbb..0000000000 --- a/Remapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 17 Oct 2018 19:17:27 -0400 -Subject: [PATCH] MC-50319: Check other worlds for shooter of projectiles - -Say a player shoots an arrow through a nether portal, the game -would lose the shooter for determining things such as Player Kills, -because the entity is in another world. - -If the projectile fails to find the shooter in the current world, check -other worlds. - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index d1dd173c11d751b15c3afd4309e386931fd9cf8d..d385fb6eee5000951c350b6ced5669dc3dcce725 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -44,7 +44,18 @@ public abstract class Projectile extends Entity { - - @Nullable - public Entity getOwner() { -- return this.ownerUUID != null && this.level instanceof ServerLevel ? ((ServerLevel) this.level).getEntity(this.ownerUUID) : (this.ownerNetworkId != 0 ? this.level.getEntity(this.ownerNetworkId) : null); -+ // Paper start - MC-50319 - shooter might be in another world (arrows through portals) -+ Entity entity = this.ownerUUID != null && this.level instanceof ServerLevel ? ((ServerLevel) this.level).getEntity(this.ownerUUID) : (this.ownerNetworkId != 0 ? this.level.getEntity(this.ownerNetworkId) : null); -+ if (entity == null) { -+ for (ServerLevel world : level.getServer().getAllLevels()) { -+ entity = world.getEntity(this.ownerUUID); -+ if (entity != null) { -+ break; -+ } -+ } -+ } -+ return entity; -+ // Paper end - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch b/Remapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch deleted file mode 100644 index 4b6ccafcaa..0000000000 --- a/Remapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Caleb Bassham -Date: Fri, 28 Sep 2018 02:32:19 -0500 -Subject: [PATCH] Call player spectator target events and improve - implementation - -Use a proper teleport for teleporting to entities in different -worlds. - -Implementation improvements authored by Spottedleaf -Validate that the target entity is valid and deny spectate -requests from frozen players. - -Also, make sure the entity is spawned to the client before -sending the camera packet. If the entity isn't spawned clientside -when it receives the camera packet, then the client will not -spectate the target entity. - -Co-authored-by: Spottedleaf - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 75419c866641ab654349cde6ca3fbdef701dd8d9..92139b271eb6c305787662ef8c7d221fb42296f7 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1818,14 +1818,58 @@ public class ServerPlayer extends Player implements ContainerListener { - } - - public void setCamera(Entity entity) { -+ // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event and improve implementation - Entity entity1 = this.getCamera(); - -- this.camera = (Entity) (entity == null ? this : entity); -- if (entity1 != this.camera) { -- this.connection.send(new ClientboundSetCameraPacket(this.camera)); -- this.connection.a(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.yRot, this.xRot, TeleportCause.SPECTATE); // CraftBukkit -+ if (entity == null) { -+ entity = this; - } - -+ if (entity1 == entity) return; // new spec target is the current spec target -+ -+ if (entity == this) { -+ com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent playerStopSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity()); -+ -+ if (!playerStopSpectatingEntityEvent.callEvent()) { -+ return; -+ } -+ } else { -+ com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent playerStartSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity(), entity.getBukkitEntity()); -+ -+ if (!playerStartSpectatingEntityEvent.callEvent()) { -+ return; -+ } -+ } -+ // Validate -+ if (entity != this) { -+ if (entity.removed || entity.shouldBeRemoved || !entity.valid || entity.level == null) { -+ MinecraftServer.LOGGER.info("Blocking player " + this.toString() + " from spectating invalid entity " + entity.toString()); -+ return; -+ } -+ if (this.isImmobile()) { -+ // use debug: clients might maliciously spam this -+ MinecraftServer.LOGGER.debug("Blocking frozen player " + this.toString() + " from spectating entity " + entity.toString()); -+ return; -+ } -+ } -+ -+ this.camera = entity; // only set after validating state -+ -+ if (entity != this) { -+ // Make sure we're in the right place -+ this.ejectPassengers(); // teleport can fail if we have passengers... -+ this.getBukkitEntity().teleport(new Location(entity.getCommandSenderWorld().getWorld(), entity.getX(), entity.getY(), entity.getZ(), this.yRot, this.xRot), TeleportCause.SPECTATE); // Correctly handle cross-world entities from api calls by using CB teleport -+ -+ // Make sure we're tracking the entity before sending -+ ChunkMap.TrackedEntity tracker = ((ServerLevel)entity.level).getChunkSource().chunkMap.entityMap.get(entity.getId()); -+ if (tracker != null) { // dumb plugins... -+ tracker.updatePlayer(this); -+ } -+ } else { -+ this.connection.teleport(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.yRot, this.xRot, TeleportCause.SPECTATE); // CraftBukkit -+ } -+ this.connection.send(new ClientboundSetCameraPacket(entity)); -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 900c9b1106a153bc386f6c3d9c11226f8ac69f86..4fd8d775790c037e82f9b0d29ed0eccf03c2dc66 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1353,6 +1353,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } - - // CraftBukkit start - Delegate to teleport(Location) -+ public final void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { this.a(d0, d1, d2, f, f1, cause); } // Paper - OBFHELPER - public void a(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { - this.a(d0, d1, d2, f, f1, Collections.emptySet(), cause); - } diff --git a/Remapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch b/Remapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch deleted file mode 100644 index f1b44575c0..0000000000 --- a/Remapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch +++ /dev/null @@ -1,303 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Mon, 8 Oct 2018 14:36:14 -0400 -Subject: [PATCH] Add Velocity IP Forwarding Support - -While Velocity supports BungeeCord-style IP forwarding, it is not secure. Users -have a lot of problems setting up firewalls or setting up plugins like IPWhitelist. -Further, the BungeeCord IP forwarding protocol still retains essentially its original -form, when there is brand new support for custom login plugin messages in 1.13. - -Velocity's modern IP forwarding uses an HMAC-SHA256 code to ensure authenticity -of messages, is packed into a binary format that is smaller than BungeeCord's -forwarding, and is integrated into the Minecraft login process by using the 1.13 -login plugin message packet. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 7178b37f7978c7e9031a22726005c5099fd78fe0..3139c194f9b1bc3510d51a81f13ae43d00a3dc29 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -8,6 +8,7 @@ import java.io.IOException; - import java.lang.reflect.InvocationTargetException; - import java.lang.reflect.Method; - import java.lang.reflect.Modifier; -+import java.nio.charset.StandardCharsets; - import java.util.HashMap; - import java.util.List; - import java.util.Map; -@@ -252,7 +253,7 @@ public class PaperConfig { - } - - public static boolean isProxyOnlineMode() { -- return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); -+ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode) || (velocitySupport && velocityOnlineMode); - } - - public static int packetInSpamThreshold = 300; -@@ -324,4 +325,18 @@ public class PaperConfig { - } - tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); - } -+ -+ public static boolean velocitySupport; -+ public static boolean velocityOnlineMode; -+ public static byte[] velocitySecretKey; -+ private static void velocitySupport() { -+ velocitySupport = getBoolean("settings.velocity-support.enabled", false); -+ velocityOnlineMode = getBoolean("settings.velocity-support.online-mode", false); -+ String secret = getString("settings.velocity-support.secret", ""); -+ if (velocitySupport && secret.isEmpty()) { -+ fatal("Velocity support is enabled, but no secret key was specified. A secret key is required!"); -+ } else { -+ velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5490ddb9f2ff1fc3e6088e703c246a06594076bc ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java -@@ -0,0 +1,66 @@ -+package com.destroystokyo.paper.proxy; -+ -+import com.destroystokyo.paper.PaperConfig; -+import com.google.common.net.InetAddresses; -+import com.mojang.authlib.GameProfile; -+import com.mojang.authlib.properties.Property; -+import java.net.InetAddress; -+import java.security.InvalidKeyException; -+import java.security.MessageDigest; -+import java.security.NoSuchAlgorithmException; -+ -+import javax.crypto.Mac; -+import javax.crypto.spec.SecretKeySpec; -+import net.minecraft.network.FriendlyByteBuf; -+import net.minecraft.resources.ResourceLocation; -+ -+public class VelocityProxy { -+ private static final int SUPPORTED_FORWARDING_VERSION = 1; -+ public static final ResourceLocation PLAYER_INFO_CHANNEL = new ResourceLocation("velocity", "player_info"); -+ -+ public static boolean checkIntegrity(final FriendlyByteBuf buf) { -+ final byte[] signature = new byte[32]; -+ buf.readBytes(signature); -+ -+ final byte[] data = new byte[buf.readableBytes()]; -+ buf.getBytes(buf.readerIndex(), data); -+ -+ try { -+ final Mac mac = Mac.getInstance("HmacSHA256"); -+ mac.init(new SecretKeySpec(PaperConfig.velocitySecretKey, "HmacSHA256")); -+ final byte[] mySignature = mac.doFinal(data); -+ if (!MessageDigest.isEqual(signature, mySignature)) { -+ return false; -+ } -+ } catch (final InvalidKeyException | NoSuchAlgorithmException e) { -+ throw new AssertionError(e); -+ } -+ -+ int version = buf.readVarInt(); -+ if (version != SUPPORTED_FORWARDING_VERSION) { -+ throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted " + SUPPORTED_FORWARDING_VERSION); -+ } -+ -+ return true; -+ } -+ -+ public static InetAddress readAddress(final FriendlyByteBuf buf) { -+ return InetAddresses.forString(buf.readUTF(Short.MAX_VALUE)); -+ } -+ -+ public static GameProfile createProfile(final FriendlyByteBuf buf) { -+ final GameProfile profile = new GameProfile(buf.readUUID(), buf.readUTF(16)); -+ readProperties(buf, profile); -+ return profile; -+ } -+ -+ private static void readProperties(final FriendlyByteBuf buf, final GameProfile profile) { -+ final int properties = buf.readVarInt(); -+ for (int i1 = 0; i1 < properties; i1++) { -+ final String name = buf.readUTF(Short.MAX_VALUE); -+ final String value = buf.readUTF(Short.MAX_VALUE); -+ final String signature = buf.readBoolean() ? buf.readUTF(Short.MAX_VALUE) : null; -+ profile.getProperties().put(name, new Property(name, value, signature)); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -index 10f1e3d761af83507bf71a00092641e22d0c8049..a295845409824b930992426451ef26856d6e7c36 100644 ---- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java -+++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -@@ -191,6 +191,7 @@ public class FriendlyByteBuf extends ByteBuf { - return this.writeVarInt(oenum.ordinal()); - } - -+ public int readVarInt() { return readVarInt(); } // Paper - OBFHELPER - public int readVarInt() { - int i = 0; - int j = 0; -@@ -231,6 +232,7 @@ public class FriendlyByteBuf extends ByteBuf { - return this; - } - -+ public UUID readUUID() { return readUUID(); } // Paper - OBFHELPER - public UUID readUUID() { - return new UUID(this.readLong(), this.readLong()); - } -@@ -358,6 +360,7 @@ public class FriendlyByteBuf extends ByteBuf { - } - } - -+ public String readUTF(int maxLength) { return this.readUtf(maxLength); } // Paper - OBFHELPER - public String readUtf(int i) { - int j = this.readVarInt(); - -diff --git a/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java b/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java -index 8a0301cc4a411c4f9384331d68794ca73b797f5f..88a63635d73983afe58406c66f4ea81cd823c627 100644 ---- a/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java -@@ -13,6 +13,14 @@ public class ClientboundCustomQueryPacket implements Packet { - -- private int transactionId; -- private FriendlyByteBuf data; -+ private int transactionId; public int getId() { return transactionId; } // Paper - OBFHELPER -+ private FriendlyByteBuf data; public FriendlyByteBuf getBuf() { return data; } // Paper - OBFHELPER - - public ServerboundCustomQueryPacket() {} - -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 0aa3a154d68f00edcc09b947a24b2b59b1e135e6..22d6f41001977917ec75046252cbf7157b92396d 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -18,9 +18,11 @@ import javax.crypto.Cipher; - import javax.crypto.SecretKey; - import net.minecraft.DefaultUncaughtExceptionHandler; - import net.minecraft.network.Connection; -+import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TextComponent; - import net.minecraft.network.chat.TranslatableComponent; -+import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; - import net.minecraft.network.protocol.login.ClientboundGameProfilePacket; - import net.minecraft.network.protocol.login.ClientboundHelloPacket; - import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; -@@ -43,6 +45,7 @@ import org.bukkit.craftbukkit.util.Waitable; - import org.bukkit.event.player.AsyncPlayerPreLoginEvent; - import org.bukkit.event.player.PlayerPreLoginEvent; - // CraftBukkit end -+import io.netty.buffer.Unpooled; // Paper - - public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener { - -@@ -59,6 +62,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - private SecretKey secretKey; - private ServerPlayer delayedAcceptPlayer; - public String hostname = ""; // CraftBukkit - add field -+ private int velocityLoginMessageId = -1; // Paper - Velocity support - - public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection) { - this.state = ServerLoginPacketListenerImpl.State.HELLO; -@@ -211,6 +215,14 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - this.state = ServerLoginPacketListenerImpl.State.KEY; - this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce)); - } else { -+ // Paper start - Velocity support -+ if (com.destroystokyo.paper.PaperConfig.velocitySupport) { -+ this.velocityLoginMessageId = java.util.concurrent.ThreadLocalRandom.current().nextInt(); -+ ClientboundCustomQueryPacket packet1 = new ClientboundCustomQueryPacket(this.velocityLoginMessageId, com.destroystokyo.paper.proxy.VelocityProxy.PLAYER_INFO_CHANNEL, new FriendlyByteBuf(Unpooled.EMPTY_BUFFER)); -+ this.connection.send(packet1); -+ return; -+ } -+ // Paper end - // Spigot start - // Paper start - Cache authenticator threads - authenticatorPool.execute(new Runnable() { -@@ -312,6 +324,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - public class LoginHandler { - - public void fireEvents() throws Exception { -+ // Paper start - Velocity support -+ if (ServerLoginPacketListenerImpl.this.velocityLoginMessageId == -1 && com.destroystokyo.paper.PaperConfig.velocitySupport) { -+ disconnect("This server requires you to connect with Velocity."); -+ return; -+ } -+ // Paper end - String playerName = gameProfile.getName(); - java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); - java.util.UUID uniqueId = gameProfile.getId(); -@@ -359,6 +377,40 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - // Spigot end - - public void handleCustomQueryPacket(ServerboundCustomQueryPacket packet) { -+ // Paper start - Velocity support -+ if (com.destroystokyo.paper.PaperConfig.velocitySupport && packet.getId() == this.velocityLoginMessageId) { -+ FriendlyByteBuf buf = packet.getBuf(); -+ if (buf == null) { -+ this.disconnect("This server requires you to connect with Velocity."); -+ return; -+ } -+ -+ if (!com.destroystokyo.paper.proxy.VelocityProxy.checkIntegrity(buf)) { -+ this.disconnect("Unable to verify player details"); -+ return; -+ } -+ -+ java.net.SocketAddress listening = this.connection.getRemoteAddress(); -+ int port = 0; -+ if (listening instanceof java.net.InetSocketAddress) { -+ port = ((java.net.InetSocketAddress) listening).getPort(); -+ } -+ this.connection.address = new java.net.InetSocketAddress(com.destroystokyo.paper.proxy.VelocityProxy.readAddress(buf), port); -+ -+ this.setGameProfile(com.destroystokyo.paper.proxy.VelocityProxy.createProfile(buf)); -+ -+ // Proceed with login -+ authenticatorPool.execute(() -> { -+ try { -+ new LoginHandler().fireEvents(); -+ } catch (Exception ex) { -+ disconnect("Failed to verify username!"); -+ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + gameProfile.getName(), ex); -+ } -+ }); -+ return; -+ } -+ // Paper end - this.disconnect(new TranslatableComponent("multiplayer.disconnect.unexpected_query_response")); - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 5e36d705c56384f507fd85f704eae634379a27f1..c06b35f114a8d243198b66c44ef57d8c2b201361 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -680,7 +680,7 @@ public final class CraftServer implements Server { - @Override - public long getConnectionThrottle() { - // Spigot Start - Automatically set connection throttle for bungee configurations -- if (org.spigotmc.SpigotConfig.bungee) { -+ if (org.spigotmc.SpigotConfig.bungee || com.destroystokyo.paper.PaperConfig.velocitySupport) { // Paper - Velocity support - return -1; - } else { - return this.configuration.getInt("settings.connection-throttle"); diff --git a/Remapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch b/Remapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch deleted file mode 100644 index 099a0f9cff..0000000000 --- a/Remapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 12 Oct 2018 14:10:46 -0500 -Subject: [PATCH] Add more Witch API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java -index a37ee32b46aa87be6e3eeca2892b4e7294fd1aef..bc9380782c2afba359852542837e7154c4c6cf8b 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Witch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java -@@ -1,5 +1,8 @@ - package net.minecraft.world.entity.monster; - -+// Paper start -+import com.destroystokyo.paper.event.entity.WitchReadyPotionEvent; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; - import java.util.Iterator; - import java.util.List; - import java.util.UUID; -@@ -49,7 +52,7 @@ public class Witch extends Raider implements RangedAttackMob { - private static final UUID SPEED_MODIFIER_DRINKING_UUID = UUID.fromString("5CD17E52-A79A-43D3-A529-90FDE04B181E"); - private static final AttributeModifier SPEED_MODIFIER_DRINKING = new AttributeModifier(Witch.SPEED_MODIFIER_DRINKING_UUID, "Drinking speed penalty", -0.25D, AttributeModifier.Operation.ADDITION); - private static final EntityDataAccessor DATA_USING_ITEM = SynchedEntityData.defineId(Witch.class, EntityDataSerializers.BOOLEAN); -- private int usingTime; -+ private int usingTime; public int getPotionUseTimeLeft() { return usingTime; } public void setPotionUseTimeLeft(int timeLeft) { usingTime = timeLeft; } // Paper - OBFHELPER - private NearestHealableRaiderTargetGoal healRaidersGoal; - private NearestAttackableWitchTargetGoal attackPlayersGoal; - -@@ -95,10 +98,12 @@ public class Witch extends Raider implements RangedAttackMob { - return SoundEvents.WITCH_DEATH; - } - -+ public void setDrinkingPotion(boolean drinkingPotion) { setUsingItem(drinkingPotion); } // Paper - OBFHELPER - public void setUsingItem(boolean drinking) { - this.getEntityData().set(Witch.DATA_USING_ITEM, drinking); - } - -+ public boolean isDrinkingPotion() { return isDrinkingPotion(); } // Paper - OBFHELPER - public boolean isDrinkingPotion() { - return (Boolean) this.getEntityData().get(Witch.DATA_USING_ITEM); - } -@@ -157,21 +162,24 @@ public class Witch extends Raider implements RangedAttackMob { - } - - if (potionregistry != null) { -- // Paper start - ItemStack potion = PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry); -- org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -- this.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+ // Paper start - logic moved into setDrinkingPotion, copy exact impl into the method and then comment out -+ this.setDrinkingPotion(potion); -+// org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+// this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+// // Paper end -+// this.bq = this.getItemInMainHand().k(); -+// this.v(true); -+// if (!this.isSilent()) { -+// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); -+// } -+// -+// AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); -+// -+// attributemodifiable.removeModifier(EntityWitch.bo); -+// attributemodifiable.b(EntityWitch.bo); - // Paper end -- this.usingTime = this.getMainHandItem().getUseDuration(); -- this.setUsingItem(true); -- if (!this.isSilent()) { -- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); -- } -- -- AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); - -- attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING); -- attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); - } - } - -@@ -183,6 +191,24 @@ public class Witch extends Raider implements RangedAttackMob { - super.aiStep(); - } - -+ // Paper start - moved to its own method -+ public void setDrinkingPotion(ItemStack potion) { -+ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+ this.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+ // Paper end -+ this.usingTime = this.getMainHandItem().getUseDuration(); -+ this.setUsingItem(true); -+ if (!this.isSilent()) { -+ this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); -+ } -+ -+ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); -+ -+ attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING); -+ attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); -+ } -+ // Paper end -+ - @Override - public SoundEvent getCelebrateSound() { - return SoundEvents.WITCH_CELEBRATE; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -index d4eeb071dbbfca3ecea256228853bcb5c11f49ee..bb40b5af0f2a6a971f78350394099e3a48d5d04a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -@@ -3,6 +3,13 @@ package org.bukkit.craftbukkit.entity; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Witch; -+// Paper start -+import com.destroystokyo.paper.entity.CraftRangedEntity; -+import com.google.common.base.Preconditions; -+import org.bukkit.Material; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.inventory.ItemStack; -+// Paper end - - public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftWitch(CraftServer server, net.minecraft.world.entity.monster.Witch entity) { -@@ -23,4 +30,28 @@ public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo. - public EntityType getType() { - return EntityType.WITCH; - } -+ -+ // Paper start -+ public boolean isDrinkingPotion() { -+ return getHandle().isDrinkingPotion(); -+ } -+ -+ public int getPotionUseTimeLeft() { -+ return getHandle().getPotionUseTimeLeft(); -+ } -+ -+ @Override -+ public void setPotionUseTimeLeft(int ticks) { -+ getHandle().setPotionUseTimeLeft(ticks); -+ } -+ -+ public ItemStack getDrinkingPotion() { -+ return CraftItemStack.asCraftMirror(getHandle().getMainHandItem()); -+ } -+ -+ public void setDrinkingPotion(ItemStack potion) { -+ Preconditions.checkArgument(potion == null || potion.getType().isEmpty() || potion.getType() == Material.POTION, "must be potion, air, or null"); -+ getHandle().setDrinkingPotion(CraftItemStack.asNMSCopy(potion)); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch b/Remapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch deleted file mode 100644 index cbace85cba..0000000000 --- a/Remapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Wed, 10 Oct 2018 21:22:44 -0500 -Subject: [PATCH] Check Drowned for Villager Aggression Config - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -index cc9cd34f77e1f568572f312655fb2fe8e83bd733..0addfd6a1421fc99840d9229bad3ba04e524317b 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -@@ -82,7 +82,7 @@ public class Drowned extends Zombie implements RangedAttackMob { - this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D)); - this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Drowned.class})).setAlertOthers(ZombifiedPiglin.class)); - this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::okTarget)); -- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); -+ if ( level.spigotConfig.zombieAggressiveTowardsVillager ) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Paper - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); - this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); - } diff --git a/Remapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch b/Remapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch deleted file mode 100644 index e6a6846d1e..0000000000 --- a/Remapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 12 Oct 2018 01:37:22 -0500 -Subject: [PATCH] Here's Johnny! - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -index a41f61daf6cbbb13d0b86cdbad8a4cae00368653..623de661f3b56062792e3a7dbc508637aa58aca5 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -@@ -51,7 +51,7 @@ public class Vindicator extends AbstractIllager { - private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { - return enumdifficulty == Difficulty.NORMAL || enumdifficulty == Difficulty.HARD; - }; -- private boolean isJohnny; -+ private boolean isJohnny; public boolean isJohnny() { return isJohnny; } public void setJohnny(boolean johnny) { isJohnny = johnny; } // Paper - OBFHELPER - - public Vindicator(EntityType type, Level world) { - super(type, world); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -index 3c5994e9862e5caa257ee6a21f8fba2df39c98c5..6c1569340317f7bed39eaf6e858d602234993eb3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -@@ -24,4 +24,14 @@ public class CraftVindicator extends CraftIllager implements Vindicator { - public EntityType getType() { - return EntityType.VINDICATOR; - } -+ -+ // Paper start -+ public boolean isJohnny() { -+ return getHandle().isJohnny(); -+ } -+ -+ public void setJohnny(boolean johnny) { -+ getHandle().setJohnny(johnny); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch b/Remapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch deleted file mode 100644 index 565724bd30..0000000000 --- a/Remapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabriele C -Date: Mon, 22 Oct 2018 17:34:10 +0200 -Subject: [PATCH] Add option to prevent players from moving into unloaded - chunks #1551 - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index f280dbff4a09bc611a9ca565c6d697d08801f53b..fbf3ccfb347a5ba6e895339e9576629d940d1aa4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -396,4 +396,9 @@ public class PaperWorldConfig { - waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); - log("Water over lava flow speed: " + waterOverLavaFlowSpeed); - } -+ -+ public boolean preventMovingIntoUnloadedChunks = false; -+ private void preventMovingIntoUnloadedChunks() { -+ preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 4fd8d775790c037e82f9b0d29ed0eccf03c2dc66..b5593300516fad767f603084aca4abcda4424db3 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -541,6 +541,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } - speed *= 2f; // TODO: Get the speed of the vehicle instead of the player - -+ // Paper start - Prevent moving into unloaded chunks -+ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && worldserver.getChunkIfLoadedImmediately((int) Math.floor(packet.getX()) >> 4, (int) Math.floor(packet.getZ()) >> 4) == null) { -+ this.connection.send(new ClientboundMoveVehiclePacket(entity)); -+ return; -+ } -+ // Paper end -+ - if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { - // CraftBukkit end - ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getName().getString(), this.player.getName().getString(), d6, d7, d8); -@@ -1139,9 +1146,9 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - double d1 = this.player.getY(); - double d2 = this.player.getZ(); - double d3 = this.player.getY(); -- double d4 = packet.getX(this.player.getX()); -+ double d4 = packet.getX(this.player.getX());double toX = d4; // Paper - OBFHELPER - double d5 = packet.getY(this.player.getY()); -- double d6 = packet.getZ(this.player.getZ()); -+ double d6 = packet.getZ(this.player.getZ());double toZ = d6; // Paper - OBFHELPER - float f = packet.getYRot(this.player.yRot); - float f1 = packet.getXRot(this.player.xRot); - double d7 = d4 - this.firstGoodX; -@@ -1180,6 +1187,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } else { - speed = player.abilities.walkingSpeed * 10f; - } -+ // Paper start - Prevent moving into unloaded chunks -+ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.hasChunk((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { -+ this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.yRot, this.player.xRot, Collections.emptySet()); -+ return; -+ } -+ // Paper end - - if (!this.player.isChangingDimension() && (!this.player.getLevel().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying())) { - float f2 = this.player.isFallFlying() ? 300.0F : 100.0F; diff --git a/Remapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch b/Remapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch deleted file mode 100644 index b3525e04cd..0000000000 --- a/Remapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: GreenMeanie -Date: Sat, 20 Oct 2018 22:34:02 -0400 -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 92139b271eb6c305787662ef8c7d221fb42296f7..b68acf219fc61e2ea811d0c732393824fa44db2d 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2159,6 +2159,7 @@ public class ServerPlayer extends Player implements ContainerListener { - } - - this.setHealth(this.getMaxHealth()); -+ this.setAirSupply(this.getMaxAirTicks()); // Paper - this.remainingFireTicks = 0; - this.fallDistance = 0; - this.foodData = new FoodData(this); -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index e7fed1f8bb8ffb164ddcdab51f41c369d6e3103d..460c6fd61bb45247715d99445821e15e98e4c465 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2354,6 +2354,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - - } - -+ public final int getMaxAirTicks() { return getMaxAirSupply(); } // Paper - OBFHELPER - public int getMaxAirSupply() { - return 300; - } diff --git a/Remapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch b/Remapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch deleted file mode 100644 index 01be147e24..0000000000 --- a/Remapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 23 Oct 2018 20:25:05 -0400 -Subject: [PATCH] Don't sleep after profile lookups if not needed - -Mojang was sleeping even if we had no more requests to go after -the current one finished, resulting in 100ms lost per profile lookup - -diff --git a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -index a3ab666b5fa89aad7ee167d9aeff2f62019a4a78..8e182fdd69dba6e1c52e2f6a893534d77fb3bfaa 100644 ---- a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -+++ b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -@@ -43,6 +43,7 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { - } - - final int page = 0; -+ boolean hasRequested = false; // Paper - - for (final List request : Iterables.partition(criteria, ENTRIES_PER_PAGE)) { - int failCount = 0; -@@ -68,6 +69,12 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { - LOGGER.debug("Couldn't find profile {}", name); - callback.onProfileLookupFailed(new GameProfile(null, name), new ProfileNotFoundException("Server did not find the requested profile")); - } -+ // Paper start -+ if (!hasRequested) { -+ hasRequested = true; -+ continue; -+ } -+ // Paper end - - try { - Thread.sleep(DELAY_BETWEEN_PAGES); diff --git a/Remapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/Remapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch deleted file mode 100644 index 04594148fc..0000000000 --- a/Remapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 23 Oct 2018 23:14:38 -0400 -Subject: [PATCH] Improve Server Thread Pool and Thread Priorities - -Use a simple executor since Fork join is a much more complex pool -type and we are not using its capabilities. - -Set thread priorities so main thread has above normal priority over -server threads - -Allow usage of a single thread executor by not using ForkJoin so single core CPU's. - -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index 7b36274718b7cce24ac00530697f145648d52590..cec5ad5052c8cf6059e9b117117846bdb217748f 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -45,7 +45,7 @@ import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.Bootstrap; --import net.minecraft.util.Mth; -+import net.minecraft.server.ServerWorkerThread; - import net.minecraft.util.datafix.DataFixers; - import net.minecraft.world.level.block.state.properties.Property; - import org.apache.logging.log4j.LogManager; -@@ -54,8 +54,8 @@ import org.apache.logging.log4j.Logger; - public class Util { - - private static final AtomicInteger WORKER_COUNT = new AtomicInteger(1); -- private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap"); -- private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main"); -+ private static final ExecutorService BOOTSTRAP_EXECUTOR = a("Bootstrap", -2); // Paper - add -2 priority -+ private static final ExecutorService BACKGROUND_EXECUTOR = a("Main", -1); // Paper - add -1 priority - private static final ExecutorService IO_POOL = makeIoExecutor(); - public static LongSupplier timeSource = System::nanoTime; - public static final UUID NIL_UUID = new UUID(0L, 0L); public static final UUID getNullUUID() {return NIL_UUID;} // Paper OBFHELPER -@@ -85,30 +85,34 @@ public class Util { - return Instant.now().toEpochMilli(); - } - -- private static ExecutorService makeExecutor(String name) { -- int i = Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, 7); -- Object object; -+ private static ExecutorService a(String s, int priorityModifier) { // Paper - add priority -+ // Paper start - use simpler thread pool that allows 1 thread -+ int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1)); -+ i = Integer.getInteger("Paper.WorkerThreadCount", i); -+ ExecutorService object; - - if (i <= 0) { - object = MoreExecutors.newDirectExecutorService(); - } else { -- object = new ForkJoinPool(i, (forkjoinpool) -> { -- ForkJoinWorkerThread forkjoinworkerthread = new ForkJoinWorkerThread(forkjoinpool) { -+ object = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue(), target -> new ServerWorkerThread(target, s, priorityModifier)); -+ } -+ /* - protected void onTermination(Throwable throwable) { - if (throwable != null) { -- Util.LOGGER.warn("{} died", this.getName(), throwable); -+ SystemUtils.LOGGER.warn("{} died", this.getName(), throwable); - } else { -- Util.LOGGER.debug("{} shutdown", this.getName()); -+ SystemUtils.LOGGER.debug("{} shutdown", this.getName()); - } - - super.onTermination(throwable); - } - }; - -- forkjoinworkerthread.setName("Worker-" + name + "-" + Util.WORKER_COUNT.getAndIncrement()); -+ forkjoinworkerthread.setName("Worker-" + s + "-" + SystemUtils.c.getAndIncrement()); - return forkjoinworkerthread; -- }, Util::onThreadException, true); -+ }, SystemUtils::a, true); - } -+ }*/ // Paper end - - return (ExecutorService) object; - } -@@ -157,6 +161,7 @@ public class Util { - }); - } - -+ public static void onThreadError(Thread thread, Throwable throwable) { onThreadException(thread, throwable); } // Paper - OBFHELPER - private static void onThreadException(Thread thread, Throwable throwable) { - pauseInIde(throwable); - if (throwable instanceof CompletionException) { -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 5a76ca77b974ff6fe862c9e05a88b507a34b44be..5faa8f3cc251b6687e33e40009db98d2aee48f2c 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -284,6 +284,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Fri, 2 Nov 2018 23:11:51 -0400 -Subject: [PATCH] Optimize World Time Updates - -Splits time updates into incremental updates as well as does -the updates per world, so that we can re-use the same packet -object for every player unless they have per-player time enabled. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 5faa8f3cc251b6687e33e40009db98d2aee48f2c..6ccc0be795e3ac7689de0eff6f9142d13161a29c 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1314,12 +1314,24 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Mon, 5 Nov 2018 04:23:51 +0000 -Subject: [PATCH] Restore custom InventoryHolder support - -Upstream removed the ability to consistently use a custom InventoryHolder, -However, the implementation does not use an InventoryHolder in any form -outside of custom inventories. - -We can take that knowledge and apply some expected behavior, if we're given -an inventory holder, we should use it and return a custom inventory with the -holder, otherwise, create an inventory backed by the intended inventory, as -per upstream behavior. - -This provides a "best of both worlds" scenario: plugins with InventoryHolder's -will always work as intended in the past, those without will create implementation -based inventories. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -index 94d807c5d09f165c6eedd0a1c4026c2b833806a0..3e56de295be0d03dddd3e54fcd7b05d4b9c74dc4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -@@ -40,6 +40,11 @@ public final class CraftInventoryCreator { - } - - public Inventory createInventory(InventoryHolder holder, InventoryType type) { -+ // Paper start -+ if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type); -+ } -+ //noinspection ConstantConditions // Paper end - return converterMap.get(type).createInventory(holder, type); - } - -@@ -55,6 +60,11 @@ public final class CraftInventoryCreator { - // Paper end - - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { -+ // Paper start -+ if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type, title); -+ } -+ //noinspection ConstantConditions // Paper end - return converterMap.get(type).createInventory(holder, type, title); - } - diff --git a/Remapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch b/Remapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch deleted file mode 100644 index 1eeb5272ca..0000000000 --- a/Remapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 8 Nov 2018 21:33:09 -0500 -Subject: [PATCH] Use Vanilla Minecart Speeds - -CraftBukkit changed the values on flying speed, restore back to vanilla - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -index 7ba74b0a9319e29077b5afe3019a463ed3004813..1257a740a4ab79870fe89057782e8ffc6c658c14 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -@@ -99,9 +99,9 @@ public abstract class AbstractMinecart extends Entity { - private double derailedX = 0.5; - private double derailedY = 0.5; - private double derailedZ = 0.5; -- private double flyingX = 0.95; -- private double flyingY = 0.95; -- private double flyingZ = 0.95; -+ private double flyingX = 0.949999988079071D; // Paper - restore vanilla precision -+ private double flyingY = 0.949999988079071D; // Paper - restore vanilla precision -+ private double flyingZ = 0.949999988079071D; // Paper - restore vanilla precision - public double maxSpeed = 0.4D; - // CraftBukkit end - diff --git a/Remapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch b/Remapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch deleted file mode 100644 index 169c739faa..0000000000 --- a/Remapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 10 Nov 2018 05:15:21 +0000 -Subject: [PATCH] Fix SpongeAbsortEvent handling - -Only process drops when the block is actually going to be removed - -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 9d2e4adddae481735053c64eec0ee7259c61f1a4..fca5d175cbef24fb0ee2d0bbedc8d1c0af3eb528 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -228,6 +228,7 @@ public class Block extends BlockBehaviour implements ItemLike { - - } - -+ public static void dropNaturally(BlockState iblockdata, LevelAccessor generatoraccess, BlockPos blockposition, @Nullable BlockEntity tileentity) { dropResources(iblockdata, generatoraccess, blockposition, tileentity); } - public static void dropResources(BlockState state, LevelAccessor world, BlockPos pos, @Nullable BlockEntity blockEntity) { - if (world instanceof ServerLevel) { - getDrops(state, (ServerLevel) world, pos, blockEntity).forEach((itemstack) -> { -diff --git a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java -index c453963ec90cd4eeec845fd0c2137e60dfdd6225..1895c75deee8da40624ba3abbd08ba7cd4f0f503 100644 ---- a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java -@@ -128,8 +128,11 @@ public class SpongeBlock extends Block { - // NOP - } else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) { - BlockEntity tileentity = iblockdata.getBlock().isEntityBlock() ? world.getBlockEntity(blockposition2) : null; -- -- dropResources(iblockdata, world, blockposition2, tileentity); -+ // Paper start -+ if (block.getHandle().getMaterial() == Material.AIR) { -+ dropNaturally(iblockdata, world, blockposition2, tileentity); -+ } -+ // Paper end - } - } - world.setBlock(blockposition2, block.getHandle(), block.getFlag()); diff --git a/Remapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch b/Remapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch deleted file mode 100644 index f5420a15fd..0000000000 --- a/Remapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 11 Nov 2018 21:01:09 +0000 -Subject: [PATCH] Don't allow digging into unloaded chunks - - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index b1a53093eb5b5f359eedb6c252cf6d0d1ae8e409..d97607f2ded4977b253d3afa3bafcbe6d7f98837 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -113,8 +113,8 @@ public class ServerPlayerGameMode { - BlockState iblockdata; - - if (this.hasDelayedDestroy) { -- iblockdata = this.level.getBlockState(this.delayedDestroyPos); -- if (iblockdata.isAir()) { -+ iblockdata = this.level.getTypeIfLoaded(this.delayedDestroyPos); // Paper -+ if (iblockdata == null || iblockdata.isAir()) { // Paper - this.hasDelayedDestroy = false; - } else { - float f = this.incrementDestroyProgress(iblockdata, this.delayedDestroyPos, this.delayedTickStart); -@@ -125,7 +125,13 @@ public class ServerPlayerGameMode { - } - } - } else if (this.isDestroyingBlock) { -- iblockdata = this.level.getBlockState(this.destroyPos); -+ // Paper start - don't want to do same logic as above, return instead -+ iblockdata = this.level.getTypeIfLoaded(this.destroyPos); -+ if (iblockdata == null) { -+ this.isDestroyingBlock = false; -+ return; -+ } -+ // Paper end - if (iblockdata.isAir()) { - this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); - this.lastSentState = -1; -@@ -289,10 +295,12 @@ public class ServerPlayerGameMode { - this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, "stopped destroying")); - } else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) { - this.isDestroyingBlock = false; -- if (!Objects.equals(this.destroyPos, pos)) { -+ if (!Objects.equals(this.destroyPos, pos) && !BlockPos.ZERO.equals(this.destroyPos)) { - ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: " + this.destroyPos + " " + pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled -- this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); -- this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, this.level.getBlockState(this.destroyPos), action, true, "aborted mismatched destroying")); -+ BlockState type = this.level.getTypeIfLoaded(this.destroyPos); // Paper - don't load unloaded chunks for stale records here -+ if (type != null) this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); // Paper -+ if (type != null) this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, type, action, true, "aborted mismatched destroying")); // Paper -+ this.destroyPos = BlockPos.ZERO; // Paper - } - - this.level.destroyBlockProgress(this.player.getId(), pos, -1); -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index b5593300516fad767f603084aca4abcda4424db3..a6ad7747396f94def688b4d2783137180dc2bb84 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1518,6 +1518,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - case START_DESTROY_BLOCK: - case ABORT_DESTROY_BLOCK: - case STOP_DESTROY_BLOCK: -+ // Paper start - Don't allow digging in unloaded chunks -+ if (this.player.level.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { -+ return; -+ } -+ // Paper end - Don't allow digging in unloaded chunks - this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packet.getDirection(), this.server.getMaxBuildHeight()); - return; - default: diff --git a/Remapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch b/Remapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch deleted file mode 100644 index ef45bdd8d0..0000000000 --- a/Remapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 16 Nov 2018 23:08:50 -0500 -Subject: [PATCH] Book Size Limits - -Puts some limits on the size of books. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 3139c194f9b1bc3510d51a81f13ae43d00a3dc29..13edb435b3fa65b4980bd7472aa5a5196f4d5b2b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -339,4 +339,11 @@ public class PaperConfig { - velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); - } - } -+ -+ public static int maxBookPageSize = 2560; -+ public static double maxBookTotalSizeMultiplier = 0.98D; -+ private static void maxBookSize() { -+ maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); -+ maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index a6ad7747396f94def688b4d2783137180dc2bb84..b1c505d3fdcc2fb3496f80bee85e4895b9069dcb 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -999,6 +999,52 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - @Override - public void handleEditBook(ServerboundEditBookPacket packet) { -+ // Paper start -+ ItemStack testStack = packet.getBook(); -+ if (!craftServer.isPrimaryThread() && !testStack.isEmpty() && testStack.getTag() != null) { -+ ListTag pageList = testStack.getTag().getList("pages", 8); -+ if (pageList.size() > 100) { -+ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with too many pages"); -+ server.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ return; -+ } -+ long byteTotal = 0; -+ int maxBookPageSize = com.destroystokyo.paper.PaperConfig.maxBookPageSize; -+ double multiplier = Math.max(0.3D, Math.min(1D, com.destroystokyo.paper.PaperConfig.maxBookTotalSizeMultiplier)); -+ long byteAllowed = maxBookPageSize; -+ for (int i = 0; i < pageList.size(); ++i) { -+ String testString = pageList.getString(i); -+ int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; -+ if (byteLength > 256 * 4) { -+ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!"); -+ server.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ return; -+ } -+ byteTotal += byteLength; -+ int length = testString.length(); -+ int multibytes = 0; -+ if (byteLength != length) { -+ for (char c : testString.toCharArray()) { -+ if (c > 127) { -+ multibytes++; -+ } -+ } -+ } -+ byteAllowed += (maxBookPageSize * Math.min(1, Math.max(0.1D, (double) length / 255D))) * multiplier; -+ -+ if (multibytes > 1) { -+ // penalize MB -+ byteAllowed -= multibytes; -+ } -+ } -+ -+ if (byteTotal > byteAllowed) { -+ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); -+ server.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ return; -+ } -+ } -+ // Paper end - // CraftBukkit start - if (this.lastBookTick + 20 > MinecraftServer.currentTick) { - this.disconnect("Book edited too quickly!"); diff --git a/Remapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch b/Remapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch deleted file mode 100644 index 8d9bfec2a6..0000000000 --- a/Remapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 18 Nov 2018 19:49:56 +0000 -Subject: [PATCH] Make the default permission message configurable - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 13edb435b3fa65b4980bd7472aa5a5196f4d5b2b..469f78775b03cf363d88e35c69c0dc185c22547c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -19,6 +19,7 @@ import java.util.regex.Pattern; - import com.google.common.collect.Lists; - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; - import org.bukkit.command.Command; - import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.InvalidConfigurationException; -@@ -287,6 +288,11 @@ public class PaperConfig { - connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); - } - -+ public static String noPermissionMessage = "&cI'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error."; -+ private static void noPermissionMessage() { -+ noPermissionMessage = ChatColor.translateAlternateColorCodes('&', getString("messages.no-permission", noPermissionMessage)); -+ } -+ - private static void savePlayerData() { - Object val = config.get("settings.save-player-data"); - if (val instanceof Boolean) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c06b35f114a8d243198b66c44ef57d8c2b201361..590687d5941cbed3a330bcd749f8d52cd4b5e3ae 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2340,6 +2340,11 @@ public final class CraftServer implements Server { - return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; - } - -+ @Override -+ public String getPermissionMessage() { -+ return com.destroystokyo.paper.PaperConfig.noPermissionMessage; -+ } -+ - @Override - public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { - return createProfile(uuid, null); diff --git a/Remapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch b/Remapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch deleted file mode 100644 index d300ff7c9e..0000000000 --- a/Remapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 26 Nov 2018 19:21:58 -0500 -Subject: [PATCH] Prevent rayTrace from loading chunks - -ray tracing into an unloaded chunk should be treated as a miss -this saves a ton of lag for when AI tries to raytrace near unloaded chunks. - -diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java -index 2feb187f62be5cf5d354a1e806087417cc189ab1..07fe8e72a7ff01d872dd5b04ccbc435e82ebe990 100644 ---- a/src/main/java/net/minecraft/world/level/BlockGetter.java -+++ b/src/main/java/net/minecraft/world/level/BlockGetter.java -@@ -58,7 +58,15 @@ public interface BlockGetter { - - // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace - default BlockHitResult rayTraceBlock(ClipContext raytrace1, BlockPos blockposition) { -- BlockState iblockdata = this.getBlockState(blockposition); -+ // Paper start - Prevent raytrace from loading chunks -+ BlockState iblockdata = this.getTypeIfLoaded(blockposition); -+ if (iblockdata == null) { -+ // copied the last function parameter (listed below) -+ Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo()); -+ -+ return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), new BlockPos(raytrace1.getTo())); -+ } -+ // Paper end - FluidState fluid = this.getFluidState(blockposition); - Vec3 vec3d = raytrace1.getFrom(); - Vec3 vec3d1 = raytrace1.getTo(); diff --git a/Remapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch b/Remapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch deleted file mode 100644 index 3b9703f204..0000000000 --- a/Remapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 27 Nov 2018 21:18:06 -0500 -Subject: [PATCH] Handle Large Packets disconnecting client - -If a players inventory is too big to send in a single packet, -split the inventory set into multiple packets instead. - -diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 7f4681910751047a26fdfc6b59bc460449c02001..35191d968fd30db16213540ef7121f4dede68e68 100644 ---- a/src/main/java/net/minecraft/network/Connection.java -+++ b/src/main/java/net/minecraft/network/Connection.java -@@ -12,6 +12,7 @@ import io.netty.channel.epoll.EpollEventLoopGroup; - import io.netty.channel.local.LocalChannel; - import io.netty.channel.local.LocalServerChannel; - import io.netty.channel.nio.NioEventLoopGroup; -+import io.netty.handler.codec.EncoderException; // Paper - import io.netty.handler.timeout.TimeoutException; - import io.netty.util.AttributeKey; - import io.netty.util.concurrent.Future; -@@ -107,6 +108,15 @@ public class Connection extends SimpleChannelInboundHandler> { - } - - public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { -+ // Paper start -+ if (throwable instanceof EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) { -+ if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) { -+ return; -+ } else { -+ throwable = throwable.getCause(); -+ } -+ } -+ // Paper end - if (throwable instanceof SkipPacketException) { - Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause()); - } else { -diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index d36d0424bcd4811af892f5f76fdcefda2af1ad33..a58c4fa8be7193b8acae5ea18a9780866312d768 100644 ---- a/src/main/java/net/minecraft/network/PacketEncoder.java -+++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -53,7 +53,31 @@ public class PacketEncoder extends MessageToByteEncoder> { - throw throwable; - } - } -+ -+ // Paper start -+ int packetLength = bytebuf.readableBytes(); -+ if (packetLength > MAX_PACKET_SIZE) { -+ throw new PacketTooLargeException(packet, packetLength); -+ } -+ // Paper end - } - } - } -+ -+ // Paper start -+ private static int MAX_PACKET_SIZE = 2097152; -+ -+ public static class PacketTooLargeException extends RuntimeException { -+ private final Packet packet; -+ -+ PacketTooLargeException(Packet packet, int packetLength) { -+ super("PacketTooLarge - " + packet.getClass().getSimpleName() + " is " + packetLength + ". Max is " + MAX_PACKET_SIZE); -+ this.packet = packet; -+ } -+ -+ public Packet getPacket() { -+ return packet; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index 29f10af7feabe2765f576586db4e3dba320dceda..9914a82ba0ec146ab13fe94c4dbf0ebf64926536 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -12,6 +12,12 @@ public interface Packet { - - void handle(T listener); - -+ // Paper start -+ default boolean packetTooLarge(NetworkManager manager) { -+ return false; -+ } -+ // Paper end -+ - default boolean isSkippable() { - return false; - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java -index 70684318c562a9c3ce566b16cd0e68cfe95cbd50..64a15dcaef40c4e16458ab71d648f9fff169a3b2 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java -@@ -4,6 +4,7 @@ import java.io.IOException; - import java.util.Iterator; - import java.util.List; - import net.minecraft.core.NonNullList; -+import net.minecraft.network.Connection; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.protocol.Packet; - import net.minecraft.world.item.ItemStack; -@@ -13,6 +14,15 @@ public class ClientboundContainerSetContentPacket implements Packet items; - -+ //Paper start -+ @Override -+ public boolean packetTooLarge(Connection manager) { -+ for (int i = 0 ; i < this.items.size() ; i++) { -+ manager.send(new ClientboundContainerSetSlotPacket(this.containerId, i, this.items.get(i))); -+ } -+ return true; -+ } -+ // Paper end - public ClientboundContainerSetContentPacket() {} - - public ClientboundContainerSetContentPacket(int syncId, NonNullList contents) { -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -index 4fe15aa331ca18319ca46d1b426f0d6fd24341f0..b7d303b5f51a35504888933efef74564fa01e59d 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -@@ -91,7 +91,7 @@ public class ClientboundLevelChunkPacket implements Packet 2097152) { -+ if (i > 2097152) { // Paper - if this changes, update PacketEncoder - throw new RuntimeException("Chunk Packet trying to allocate too much memory on read."); - } else { - this.buffer = new byte[i]; diff --git a/Remapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch b/Remapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch deleted file mode 100644 index abee5b71e8..0000000000 --- a/Remapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 15 Nov 2018 13:38:37 +0000 -Subject: [PATCH] force entity dismount during teleportation - -Entities must be dismounted before teleportation in order to avoid -multiple issues in the server with regards to teleportation, shamefully, -too many plugins rely on the events firing, which means that not firing -these events caues more issues than it solves; - -In order to counteract this, Entity dismount/exit vehicle events have -been modified to supress cancellation (and has a method to allow plugins -to check if this has been set), noting that cancellation will be silently -surpressed given that plugins are not expecting this event to not be cancellable. - -This is a far from ideal scenario, however: given the current state of this -event and other alternatives causing issues elsewhere, I believe that -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 b68acf219fc61e2ea811d0c732393824fa44db2d..416c21f0a6be8d71a654e18f7ea0fa074f8fc5ff 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1258,11 +1258,13 @@ public class ServerPlayer extends Player implements ContainerListener { - } - } - -- @Override -- public void stopRiding() { -+ // Paper start -+ @Override public void stopRiding() { stopRiding(false); } -+ @Override public void stopRiding(boolean suppressCancellation) { -+ // paper end - Entity entity = this.getVehicle(); - -- super.stopRiding(); -+ super.stopRiding(suppressCancellation); // Paper - Entity entity1 = this.getVehicle(); - - if (entity1 != entity && this.connection != null) { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 460c6fd61bb45247715d99445821e15e98e4c465..c5d6235a132818dfc78105e9d03d0687f697bb00 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2044,12 +2044,15 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - - } - -- public void removeVehicle() { -+ // Paper start -+ public void removeVehicle() { stopRiding(false); } -+ public void stopRiding(boolean suppressCancellation) { -+ // Paper end - if (this.vehicle != null) { - Entity entity = this.vehicle; - - this.vehicle = null; -- if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit -+ if (!entity.removePassenger(this, suppressCancellation)) this.vehicle = entity; // CraftBukkit // Paper - } - - } -@@ -2104,7 +2107,10 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return true; // CraftBukkit - } - -- protected boolean removePassenger(Entity entity) { // CraftBukkit -+ // Paper start -+ protected boolean removePassenger(Entity entity) { return removePassenger(entity, false);} -+ protected boolean removePassenger(Entity entity, boolean suppressCancellation) { // CraftBukkit -+ // Paper end - if (entity.getVehicle() == this) { - throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); - } else { -@@ -2114,7 +2120,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { - VehicleExitEvent event = new VehicleExitEvent( - (Vehicle) getBukkitEntity(), -- (LivingEntity) entity.getBukkitEntity() -+ (LivingEntity) entity.getBukkitEntity(), !suppressCancellation // Paper - ); - // Suppress during worldgen - if (this.valid) { -@@ -2128,7 +2134,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - // CraftBukkit end - // Spigot start -- org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity()); -+ org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity(), !suppressCancellation); // Paper - // Suppress during worldgen - 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 7a2292e6907a2ae2026bd7243e864bd8300ecafa..29d4ed42e5d763639a50d849ef274c4d848bc9c9 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3012,11 +3012,13 @@ public abstract class LivingEntity extends Entity { - return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 4) != 0; - } - -- @Override -- public void stopRiding() { -+ // Paper start -+ @Override public void stopRiding() { stopRiding(false); } -+ @Override public void stopRiding(boolean suppressCancellation) { -+ // Paper end - Entity entity = this.getVehicle(); - -- super.stopRiding(); -+ super.stopRiding(suppressCancellation); // Paper - suppress - if (entity != null && entity != this.getVehicle() && !this.level.isClientSide) { - this.dismountVehicle(entity); - } -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 3aadc4ab5fe7b2ee9e20e0789ddcfe750599972f..0685920073a6a2b2c6a80018d0c9009b2ef860c4 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1036,9 +1036,11 @@ public abstract class Player extends LivingEntity { - return -0.35D; - } - -- @Override -- public void removeVehicle() { -- super.removeVehicle(); -+ // Paper start -+ @Override public void removeVehicle() { stopRiding(false); } -+ @Override public void stopRiding(boolean suppressCancellation) { -+ // Paper end -+ super.stopRiding(suppressCancellation); // Paper - suppress - this.boardingCooldown = 0; - } - diff --git a/Remapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch b/Remapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch deleted file mode 100644 index 324b101062..0000000000 --- a/Remapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 Oct 2018 04:29:59 -0500 -Subject: [PATCH] Add more Zombie API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 94e2a8f74e74d68d4a9b82b667fbff24b7e9e629..ad4eeb15771750193a28116117992270c72a3644 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -91,6 +91,7 @@ public class Zombie extends Monster { - private int inWaterTime; - public int conversionTime; - private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field -+ private boolean shouldBurnInDay = true; // Paper - - public Zombie(EntityType type, Level world) { - super(type, world); -@@ -259,6 +260,12 @@ public class Zombie extends Monster { - super.aiStep(); - } - -+ // Paper start -+ public void stopDrowning() { -+ this.conversionTime = -1; -+ this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, false); -+ } -+ // Paper end - public void startUnderWaterConversion(int ticksUntilWaterConversion) { - this.lastTick = MinecraftServer.currentTick; // CraftBukkit - this.conversionTime = ticksUntilWaterConversion; -@@ -287,9 +294,16 @@ public class Zombie extends Monster { - - } - -+ public boolean shouldBurnInDay() { return isSunSensitive(); } // Paper - OBFHELPER - protected boolean isSunSensitive() { -- return true; -+ return this.shouldBurnInDay; // Paper - use api value instead -+ } -+ -+ // Paper start -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ this.shouldBurnInDay = shouldBurnInDay; - } -+ // Paper end - - @Override - public boolean hurt(DamageSource source, float amount) { -@@ -410,6 +424,7 @@ public class Zombie extends Monster { - tag.putBoolean("CanBreakDoors", this.canBreakDoors()); - tag.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1); - tag.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1); -+ tag.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); // Paper - } - - @Override -@@ -421,7 +436,11 @@ public class Zombie extends Monster { - if (tag.contains("DrownedConversionTime", 99) && tag.getInt("DrownedConversionTime") > -1) { - this.startUnderWaterConversion(tag.getInt("DrownedConversionTime")); - } -- -+ // Paper start -+ if (tag.contains("Paper.ShouldBurnInDay")) { -+ shouldBurnInDay = tag.getBoolean("Paper.ShouldBurnInDay"); -+ } -+ // Paper end - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 038793987338c2e4b73784a10836f85c7061175a..86f65c07806a118c49e900c59be86c2bd2eb124c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -@@ -93,6 +93,42 @@ public class CraftZombie extends CraftMonster implements Zombie { - @Override - public void setAgeLock(boolean b) { - } -+ // Paper start -+ @Override -+ public boolean isDrowning() { -+ return getHandle().isUnderWaterConverting(); -+ } -+ -+ @Override -+ public void startDrowning(int drownedConversionTime) { -+ getHandle().startUnderWaterConversion(drownedConversionTime); -+ } -+ -+ @Override -+ public void stopDrowning() { -+ getHandle().stopDrowning(); -+ } -+ -+ @Override -+ public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); -+ } -+ -+ @Override -+ public boolean isArmsRaised() { -+ return getHandle().isAggressive(); -+ } -+ -+ @Override -+ public void setArmsRaised(final boolean raised) { -+ getHandle().setAggressive(raised); -+ } -+ -+ @Override -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ getHandle().setShouldBurnInDay(shouldBurnInDay); -+ } -+ // Paper end - - @Override - public boolean getAgeLock() { diff --git a/Remapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch b/Remapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch deleted file mode 100644 index 12d0a9084e..0000000000 --- a/Remapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 7 Oct 2018 12:05:28 -0700 -Subject: [PATCH] Add PlayerConnectionCloseEvent - -This event is invoked when a player has disconnected. It is guaranteed that, -if the server is in online-mode, that the provided uuid and username have been -validated. - -The event is invoked for players who have not yet logged into the world, whereas -PlayerQuitEvent is only invoked on players who have logged into the world. - -The event is invoked for players who have already logged into the world, -although whether or not the player exists in the world at the time of -firing is undefined. (That is, whether the plugin can retrieve a Player object -using the event parameters is undefined). However, it is guaranteed that this -event is invoked AFTER PlayerQuitEvent, if the player has already logged into -the world. - -This event is guaranteed to never fire unless AsyncPlayerPreLoginEvent has -been called beforehand, and this event may not be called in parallel with -AsyncPlayerPreLoginEvent for the same connection. - -Cancelling the AsyncPlayerPreLoginEvent guarantees the corresponding -PlayerConnectionCloseEvent is never called. - -The event may be invoked asynchronously or synchronously. As it stands, -it is never invoked asynchronously. However, plugins should check -Event#isAsynchronous to be future-proof. - -On purpose, the deprecated PlayerPreLoginEvent event is left out of the -API spec for this event. Plugins should not be using that event, and -how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent -is undefined. - -diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 35191d968fd30db16213540ef7121f4dede68e68..3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4 100644 ---- a/src/main/java/net/minecraft/network/Connection.java -+++ b/src/main/java/net/minecraft/network/Connection.java -@@ -350,6 +350,26 @@ public class Connection extends SimpleChannelInboundHandler> { - this.getPacketListener().a(new TranslatableComponent("multiplayer.disconnect.generic")); - } - this.queue.clear(); // Free up packet queue. -+ // Paper start - Add PlayerConnectionCloseEvent -+ final PacketListener packetListener = this.getPacketListener(); -+ if (packetListener instanceof ServerGamePacketListenerImpl) { -+ /* Player was logged in */ -+ final ServerGamePacketListenerImpl playerConnection = (ServerGamePacketListenerImpl) packetListener; -+ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(playerConnection.player.getUUID(), -+ playerConnection.player.getScoreboardName(), ((java.net.InetSocketAddress)address).getAddress(), false).callEvent(); -+ } else if (packetListener instanceof ServerLoginPacketListenerImpl) { -+ /* Player is login stage */ -+ final ServerLoginPacketListenerImpl loginListener = (ServerLoginPacketListenerImpl) packetListener; -+ switch (loginListener.getLoginState()) { -+ case READY_TO_ACCEPT: -+ case DELAY_ACCEPT: -+ case ACCEPTED: -+ final com.mojang.authlib.GameProfile profile = loginListener.getGameProfile(); /* Should be non-null at this stage */ -+ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(profile.getId(), profile.getName(), -+ ((java.net.InetSocketAddress)address).getAddress(), false).callEvent(); -+ } -+ } -+ // Paper end - } - - } -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 22d6f41001977917ec75046252cbf7157b92396d..9631fa93b821c7f6bc6dc707c2c82cce2ae8291e 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -55,9 +55,9 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - private final byte[] nonce = new byte[4]; - private final MinecraftServer server; - public final Connection connection; -- private ServerLoginPacketListenerImpl.State state; -+ private ServerLoginPacketListenerImpl.State state; public final ServerLoginPacketListenerImpl.State getLoginState() { return this.state; }; // Paper - OBFHELPER - private int tick; -- private GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } private GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER -+ private GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } public GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER - private final String serverId; - private SecretKey secretKey; - private ServerPlayer delayedAcceptPlayer; diff --git a/Remapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch b/Remapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch deleted file mode 100644 index b1074d223b..0000000000 --- a/Remapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 18 Dec 2018 02:15:08 +0000 -Subject: [PATCH] Prevent Enderman from loading chunks - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -index d190b58bea310f4006ea3deaf0d42c502d441284..dae35d3f758e40c1edf31b11c6e11f1b7bb2dfae 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -@@ -434,7 +434,8 @@ public class EnderMan extends Monster implements NeutralMob { - int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 3.0D); - int k = Mth.floor(this.enderman.getZ() - 2.0D + random.nextDouble() * 4.0D); - BlockPos blockposition = new BlockPos(i, j, k); -- BlockState iblockdata = world.getBlockState(blockposition); -+ BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return; // Paper - Block block = iblockdata.getBlock(); - Vec3 vec3d = new Vec3((double) Mth.floor(this.enderman.getX()) + 0.5D, (double) j + 0.5D, (double) Mth.floor(this.enderman.getZ()) + 0.5D); - Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); -@@ -474,7 +475,8 @@ public class EnderMan extends Monster implements NeutralMob { - int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 2.0D); - int k = Mth.floor(this.enderman.getZ() - 1.0D + random.nextDouble() * 2.0D); - BlockPos blockposition = new BlockPos(i, j, k); -- BlockState iblockdata = world.getBlockState(blockposition); -+ BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return; // Paper - BlockPos blockposition1 = blockposition.below(); - BlockState iblockdata1 = world.getBlockState(blockposition1); - BlockState iblockdata2 = this.enderman.getCarriedBlock(); diff --git a/Remapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/Remapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch deleted file mode 100644 index 491b5bd0f8..0000000000 --- a/Remapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Jan 2019 00:35:43 -0600 -Subject: [PATCH] Add APIs to replace OfflinePlayer#getLastPlayed - -Currently OfflinePlayer#getLastPlayed could more accurately be described -as "OfflinePlayer#getLastTimeTheirDataWasSaved". - -The API doc says it should return the last time the server "witnessed" -the player, whilst also saying it should return the last time they -logged in. The current implementation does neither. - -Given this interesting contradiction in the API documentation and the -current defacto implementation, I've elected to deprecate (with no -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 416c21f0a6be8d71a654e18f7ea0fa074f8fc5ff..1fa4f58658ff98396eb5abfc27e19e5832d56f5a 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -211,6 +211,7 @@ public class ServerPlayer extends Player implements ContainerListener { - public int latency; - public boolean wonGame; - private int containerUpdateDelay; // Paper -+ public long loginTime; // Paper - // Paper start - cancellable death event - public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7c307a16ca3962db65be09a0ddd058a4ce81c7be..5b71b487836cdd2ddc75b2039f4dc0177719d345 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -164,6 +164,7 @@ public abstract class PlayerList { - } - - public void placeNewPlayer(Connection connection, ServerPlayer player) { -+ player.loginTime = System.currentTimeMillis(); // Paper - GameProfile gameprofile = player.getGameProfile(); - GameProfileCache usercache = this.server.getProfileCache(); - GameProfile gameprofile1 = usercache.get(gameprofile.getId()); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -index 1eeb1d1fe54eba68652be8dba52dce8ca91d948d..19aee8c6d0989bcf263e27adab42b3e6e411b66f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -@@ -244,6 +244,61 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa - return getData() != null; - } - -+ // Paper start -+ @Override -+ public long getLastLogin() { -+ Player player = getPlayer(); -+ if (player != null) return player.getLastLogin(); -+ -+ CompoundTag data = getPaperData(); -+ -+ if (data != null) { -+ if (data.contains("LastLogin")) { -+ return data.getLong("LastLogin"); -+ } else { -+ // if the player file cannot provide accurate data, this is probably the closest we can approximate -+ File file = getDataFile(); -+ return file.lastModified(); -+ } -+ } else { -+ return 0; -+ } -+ } -+ -+ @Override -+ public long getLastSeen() { -+ Player player = getPlayer(); -+ if (player != null) return player.getLastSeen(); -+ -+ CompoundTag data = getPaperData(); -+ -+ if (data != null) { -+ if (data.contains("LastSeen")) { -+ return data.getLong("LastSeen"); -+ } else { -+ // if the player file cannot provide accurate data, this is probably the closest we can approximate -+ File file = getDataFile(); -+ return file.lastModified(); -+ } -+ } else { -+ return 0; -+ } -+ } -+ -+ private CompoundTag getPaperData() { -+ CompoundTag result = getData(); -+ -+ if (result != null) { -+ if (!result.contains("Paper")) { -+ result.put("Paper", new CompoundTag()); -+ } -+ result = result.getCompound("Paper"); -+ } -+ -+ return result; -+ } -+ // Paper end -+ - @Override - public Location getBedSpawnLocation() { - CompoundTag data = getData(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index a3e65028d3e0c09a65cd9c28b037fe01a2ed1d76..ba03a1cdac68dc08ed878e311adeebc531e8f2f1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -144,6 +144,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; - private String resourcePackHash; - private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit -+ private long lastSaveTime; - // Paper end - - public CraftPlayer(CraftServer server, ServerPlayer entity) { -@@ -1480,6 +1481,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - this.firstPlayed = firstPlayed; - } - -+ // Paper start -+ @Override -+ public long getLastLogin() { -+ return getHandle().loginTime; -+ } -+ -+ @Override -+ public long getLastSeen() { -+ return isOnline() ? System.currentTimeMillis() : this.lastSaveTime; -+ } -+ // Paper end -+ - public void readExtraData(CompoundTag nbttagcompound) { - hasPlayedBefore = true; - if (nbttagcompound.contains("bukkit")) { -@@ -1502,6 +1515,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void setExtraData(CompoundTag nbttagcompound) { -+ this.lastSaveTime = System.currentTimeMillis(); // Paper -+ - if (!nbttagcompound.contains("bukkit")) { - nbttagcompound.put("bukkit", new CompoundTag()); - } -@@ -1516,6 +1531,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - data.putLong("firstPlayed", getFirstPlayed()); - data.putLong("lastPlayed", System.currentTimeMillis()); - data.putString("lastKnownName", handle.getScoreboardName()); -+ -+ // Paper start - persist for use in offline save data -+ if (!nbttagcompound.contains("Paper")) { -+ nbttagcompound.put("Paper", new CompoundTag()); -+ } -+ -+ CompoundTag paper = nbttagcompound.getCompound("Paper"); -+ paper.putLong("LastLogin", handle.loginTime); -+ paper.putLong("LastSeen", System.currentTimeMillis()); -+ // Paper end - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/Remapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch deleted file mode 100644 index 4645205240..0000000000 --- a/Remapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: connorhartley -Date: Mon, 7 Jan 2019 14:43:48 -0600 -Subject: [PATCH] Workaround for vehicle tracking issue on disconnect - - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 1fa4f58658ff98396eb5abfc27e19e5832d56f5a..fd2717a00a85f91ee23a1c0f929f856972892a9b 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1524,6 +1524,13 @@ public class ServerPlayer extends Player implements ContainerListener { - public void disconnect() { - this.disconnected = true; - this.ejectPassengers(); -+ -+ // Paper start - Workaround an issue where the vehicle doesn't track the passenger disconnection dismount. -+ if (this.isPassenger() && this.getVehicle() instanceof ServerPlayer) { -+ this.stopRiding(); -+ } -+ // Paper end -+ - if (this.isSleeping()) { - this.stopSleepInBed(true, false); - } diff --git a/Remapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/Remapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch deleted file mode 100644 index 7b22e86252..0000000000 --- a/Remapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 31 Jan 2019 16:33:36 -0500 -Subject: [PATCH] Fire BlockPistonRetractEvent for all empty pistons - -There is an explicit check in the handling code for empty pistons that -prevents sticky pistons from firing the event. However when we look back -at the history we see that this check was originally added so that ONLY -sticky pistons would fire the retract event. I'm not sure why. -https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1092acbddf07edfa4100bc6824504ac75088e913 - -Over the course of several updates, the meaning of that field appears to -have changed from "is NOT sticky" to "is sticky". So now its having the -opposite effect. Only normal pistons fire the retraction event. And like -all things in CB, it's just been carried around since. - -If we are to believe the history, the correct fix for this issue is to -flip it so it only fires for sticky pistons, but that puts us in a -bind. It's already firing for non-sticky pistons, changing it now would -likely result in breakage. Furthermore, there is little documentation as -to WHY that was ever intended to be the case. - -Instead we opt to remove the check entirely so that the event fires for -all piston types. - -diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -index 878cec21b52fb62369310c2f85001e859a270dd8..dc9584a30c18d964afd9cc118c81c24a80beba63 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -@@ -140,7 +140,7 @@ public class PistonBaseBlock extends DirectionalBlock { - } - - // CraftBukkit start -- if (!this.isSticky) { -+ //if (!this.sticky) { // Paper - Prevents empty sticky pistons from firing retract - history behind is odd - org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); - BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); - world.getCraftServer().getPluginManager().callEvent(event); -@@ -148,7 +148,7 @@ public class PistonBaseBlock extends DirectionalBlock { - if (event.isCancelled()) { - return; - } -- } -+ //} // Paper - // PAIL: checkME - what happened to setTypeAndData? - // CraftBukkit end - world.blockEvent(pos, this, b0, enumdirection.get3DDataValue()); diff --git a/Remapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch b/Remapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch deleted file mode 100644 index 8ac3978e9f..0000000000 --- a/Remapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 4 Feb 2019 23:33:24 -0500 -Subject: [PATCH] Block Entity#remove from being called on Players - -This doesn't result in the same behavior as other entities and causes -several problems. Anyone ever complain about the "Cannot send chat -message" thing? That's one of the issues this causes, among others. - -If a plugin developer can come up with a valid reason to call this on a -Player we will look at limiting the scope of this change. It appears to -be unintentional in the few cases we've seen so far. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ba03a1cdac68dc08ed878e311adeebc531e8f2f1..c2c6eb54096ef85b01c0b700cbe6a8054b62729f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2231,6 +2231,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public void resetCooldown() { - getHandle().resetAttackStrengthTicker(); - } -+ -+ @Override -+ public void remove() { -+ if (this.getHandle().getClass().equals(ServerPlayer.class)) { // special case for NMS plugins inheriting -+ throw new UnsupportedOperationException("Calling Entity#remove on players produces undefined (bad) behavior"); -+ } else { -+ super.remove(); -+ } -+ } - // Paper end - - // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch b/Remapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch deleted file mode 100644 index 497abbdeb1..0000000000 --- a/Remapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 Feb 2019 00:20:33 -0500 -Subject: [PATCH] BlockDestroyEvent - -Adds an event for when the server is going to destroy a current block, -potentially causing it to drop. This event can be cancelled to avoid -the block destruction, such as preventing signs from popping when -floating in the air. - -This can replace many uses of BlockPhysicsEvent - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index b75ffafb6840b6acab6e5b0ef5e222c4fa130977..c8542636e89748699d608eb29569cacb6321d334 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -27,6 +27,7 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.ClientboundSetBorderPacket; - import net.minecraft.resources.ResourceKey; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkHolder; - import net.minecraft.server.level.ServerLevel; -@@ -559,8 +560,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return false; - } else { - FluidState fluid = this.getFluidState(pos); -+ // Paper start - while the above setAir method is named same and looks very similar -+ // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent, -+ // it doesn't imply destruction of a block that plays a sound effect / drops an item. -+ boolean playEffect = true; -+ if (com.destroystokyo.paper.event.block.BlockDestroyEvent.getHandlerList().getRegisteredListeners().length > 0) { -+ com.destroystokyo.paper.event.block.BlockDestroyEvent event = new com.destroystokyo.paper.event.block.BlockDestroyEvent(MCUtil.toBukkitBlock(this, pos), fluid.createLegacyBlock().createCraftBlockData(), drop); -+ if (!event.callEvent()) { -+ return false; -+ } -+ playEffect = event.playEffect(); -+ } -+ // Paper end - -- if (!(iblockdata.getBlock() instanceof BaseFireBlock)) { -+ if (playEffect && !(iblockdata.getBlock() instanceof BaseFireBlock)) { // Paper - this.levelEvent(2001, pos, Block.getId(iblockdata)); - } - diff --git a/Remapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/Remapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch deleted file mode 100644 index 941fce8c3e..0000000000 --- a/Remapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Jan 2019 00:08:15 -0500 -Subject: [PATCH] Fix Custom Shapeless Custom Crafting Recipes - -Mojang implemented Shapeless different than Shaped - -This made the Bukkit RecipeChoice API not work for Shapeless. - -This reimplements vanilla logic using the same test logic as Shaped - -diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java -index 7bd62f598f3fff7520c276bdc45e538bd3260bc9..a8d0a90d36d58515bb6f6128de1ef15b72c20c17 100644 ---- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java -+++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java -@@ -71,16 +71,49 @@ public class ShapelessRecipe implements CraftingRecipe { - StackedContents autorecipestackmanager = new StackedContents(); - int i = 0; - -+ // Paper start -+ java.util.List providedItems = new java.util.ArrayList<>(); -+ co.aikar.util.Counter matchedProvided = new co.aikar.util.Counter<>(); -+ co.aikar.util.Counter matchedIngredients = new co.aikar.util.Counter<>(); -+ // Paper end - for (int j = 0; j < inv.getContainerSize(); ++j) { - ItemStack itemstack = inv.getItem(j); - - if (!itemstack.isEmpty()) { -- ++i; -- autorecipestackmanager.accountStack(itemstack, 1); -+ // Paper start -+ itemstack = itemstack.copy(); -+ providedItems.add(itemstack); -+ for (Ingredient ingredient : ingredients) { -+ if (ingredient.test(itemstack)) { -+ matchedProvided.increment(itemstack); -+ matchedIngredients.increment(ingredient); -+ } -+ } -+ // Paper end - } - } - -- return i == this.ingredients.size() && autorecipestackmanager.canCraft(this, (IntList) null); -+ // Paper start -+ if (matchedProvided.isEmpty() || matchedIngredients.isEmpty()) { -+ return false; -+ } -+ java.util.List ingredients = new java.util.ArrayList<>(this.ingredients); -+ providedItems.sort(java.util.Comparator.comparingInt((ItemStack c) -> (int) matchedProvided.getCount(c)).reversed()); -+ ingredients.sort(java.util.Comparator.comparingInt((Ingredient c) -> (int) matchedIngredients.getCount(c))); -+ -+ PROVIDED: -+ for (ItemStack provided : providedItems) { -+ for (Iterator itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) { -+ Ingredient ingredient = itIngredient.next(); -+ if (ingredient.test(provided)) { -+ itIngredient.remove(); -+ continue PROVIDED; -+ } -+ } -+ return false; -+ } -+ return ingredients.isEmpty(); -+ // Paper end - } - - public ItemStack assemble(CraftingContainer inv) { diff --git a/Remapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch b/Remapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch deleted file mode 100644 index cdc4ad71f6..0000000000 --- a/Remapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 28 Feb 2019 00:15:28 -0500 -Subject: [PATCH] Fix sign edit memory leak - -when a player edits a sign, a reference to their Entity is never cleand up. - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index b1c505d3fdcc2fb3496f80bee85e4895b9069dcb..276773e17149f57038cd21485fd9d9061670ff2d 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2850,7 +2850,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; - -- if (!tileentitysign.isEditable() || tileentitysign.getPlayerWhoMayEdit() != this.player) { -+ if (!tileentitysign.isEditable() || tileentitysign.signEditor == null || !tileentitysign.signEditor.equals(this.player.getUUID())) { - ServerGamePacketListenerImpl.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getName().getString()); - this.send(tileentity.getUpdatePacket()); // CraftBukkit - return; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -index e4eab82855649fec654c60b2e94ba7b71c2ac5a2..0b26d3ab2db66d6baaa95d1d5f6c756595d31495 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -@@ -30,6 +30,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C - private Player playerWhoMayEdit; - private final FormattedCharSequence[] renderMessages; - private DyeColor color; -+ public java.util.UUID signEditor; // Paper - - public SignBlockEntity() { - super(BlockEntityType.SIGN); -@@ -131,7 +132,10 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C - } - - public void setAllowedPlayerEditor(Player player) { -- this.playerWhoMayEdit = player; -+ // Paper start -+ //this.c = entityhuman; -+ signEditor = player != null ? player.getUUID() : null; -+ // Paper end - } - - public Player getPlayerWhoMayEdit() { diff --git a/Remapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch b/Remapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch deleted file mode 100644 index da033509aa..0000000000 --- a/Remapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Feb 2019 22:18:40 -0500 -Subject: [PATCH] Limit Client Sign length more - -modified clients can send more data from the client -to the server and it would get stored on the sign as sent. - -Mojang has a limit of 384 which is much higher than reasonable. - -the client can barely render around 16 characters as-is, but formatting -codes can get it to be more than 16 actual length. - -Set a limit of 80 which should give an average of 16 characters 2 -sets of legacy formatting codes which should be plenty for all uses. - -This does not strip any existing data from the NBT as plugins -may use this for storing data out of the rendered area. - -it only impacts data sent from the client. - -Set -DPaper.maxSignLength=XX to change limit or -1 to disable - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 276773e17149f57038cd21485fd9d9061670ff2d..d6d8d83bc16572474d56a278dd119eacc2c52476 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -254,6 +254,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - private int aboveGroundVehicleTickCount; - private int receivedMovePacketCount; - private int knownMovePacketCount; -+ private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); - private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - - public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { -@@ -2860,7 +2861,17 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. -+ // Paper start - cap line length - modified clients can send longer data than normal -+ String currentLine = list.get(i); -+ if (MAX_SIGN_LINE_LENGTH > 0 && currentLine.length() > MAX_SIGN_LINE_LENGTH) { -+ // This handles multibyte characters as 1 -+ int offset = currentLine.codePoints().limit(MAX_SIGN_LINE_LENGTH).map(Character::charCount).sum(); -+ if (offset < currentLine.length()) { -+ list.set(i, currentLine = currentLine.substring(0, offset)); -+ } -+ } -+ // Paper end -+ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(currentLine))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. - } - SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.craftServer.getPluginManager().callEvent(event); diff --git a/Remapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/Remapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch deleted file mode 100644 index e847f69596..0000000000 --- a/Remapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 2 Mar 2019 11:11:29 -0500 -Subject: [PATCH] Don't check ConvertSigns boolean every sign save - -property lookups arent super cheap. they synchronize, validate -and check security managers. - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -index 0b26d3ab2db66d6baaa95d1d5f6c756595d31495..8d619e0bf8bcf7d6d4e7f23f11d648ccfb65cac4 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -@@ -31,6 +31,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C - private final FormattedCharSequence[] renderMessages; - private DyeColor color; - public java.util.UUID signEditor; // Paper -+ private static final boolean CONVERT_LEGACY_SIGNS = Boolean.getBoolean("convertLegacySigns"); // Paper - - public SignBlockEntity() { - super(BlockEntityType.SIGN); -@@ -51,7 +52,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C - } - - // CraftBukkit start -- if (Boolean.getBoolean("convertLegacySigns")) { -+ if (CONVERT_LEGACY_SIGNS) { // Paper - tag.putBoolean("Bukkit.isConverted", true); - } - // CraftBukkit end diff --git a/Remapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/Remapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch deleted file mode 100644 index 0dc4b2e085..0000000000 --- a/Remapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch +++ /dev/null @@ -1,394 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 04:53:35 -0400 -Subject: [PATCH] Optimize Network Manager and add advanced packet support - -Adds ability for 1 packet to bundle other packets to follow it -Adds ability for a packet to delay sending more packets until a state is ready. - -Removes synchronization from sending packets -Removes processing packet queue off of main thread - - for the few cases where it is allowed, order is not necessary nor - should it even be happening concurrently in first place (handshaking/login/status) - -Ensures packets sent asynchronously are dispatched on main thread - -This helps ensure safety for ProtocolLib as packet listeners -are commonly accessing world state. This will allow you to schedule -a packet to be sent async, but itll be dispatched sync for packet -listeners to process. - -This should solve some deadlock risks - -Also adds Netty Channel Flush Consolidation to reduce the amount of flushing - -Also avoids spamming closed channel exception by rechecking closed state in dispatch -and then catch exceptions and close if they fire. - -Part of this commit was authored by: Spottedleaf - -diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed0b562c1b 100644 ---- a/src/main/java/net/minecraft/network/Connection.java -+++ b/src/main/java/net/minecraft/network/Connection.java -@@ -25,8 +25,15 @@ import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.PacketFlow; -+import net.minecraft.network.protocol.game.ClientboundBossEventPacket; -+import net.minecraft.network.protocol.game.ClientboundChatPacket; -+import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket; - import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; -+import net.minecraft.network.protocol.game.ClientboundKeepAlivePacket; -+import net.minecraft.network.protocol.game.ClientboundSetTitlesPacket; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.RunningOnDifferentThreadException; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.network.ServerGamePacketListenerImpl; - import net.minecraft.server.network.ServerLoginPacketListenerImpl; - import net.minecraft.util.LazyLoadedValue; -@@ -75,6 +82,10 @@ public class Connection extends SimpleChannelInboundHandler> { - public int protocolVersion; - public java.net.InetSocketAddress virtualHost; - private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); -+ // Optimize network -+ public boolean isPending = true; -+ public boolean queueImmunity = false; -+ public ConnectionProtocol protocol; - // Paper end - - public Connection(PacketFlow side) { -@@ -98,6 +109,7 @@ public class Connection extends SimpleChannelInboundHandler> { - } - - public void setProtocol(ConnectionProtocol state) { -+ protocol = state; // Paper - this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).set(state); - this.channel.config().setAutoRead(true); - Connection.LOGGER.debug("Enabled auto read"); -@@ -168,19 +180,84 @@ public class Connection extends SimpleChannelInboundHandler> { - Validate.notNull(listener, "packetListener", new Object[0]); - this.packetListener = listener; - } -+ // Paper start -+ public ServerPlayer getPlayer() { -+ if (packetListener instanceof ServerGamePacketListenerImpl) { -+ return ((ServerGamePacketListenerImpl) packetListener).player; -+ } else { -+ return null; -+ } -+ } -+ private static class InnerUtil { // Attempt to hide these methods from ProtocolLib so it doesn't accidently pick them up. -+ private static java.util.List buildExtraPackets(Packet packet) { -+ java.util.List extra = packet.getExtraPackets(); -+ if (extra == null || extra.isEmpty()) { -+ return null; -+ } -+ java.util.List ret = new java.util.ArrayList<>(1 + extra.size()); -+ buildExtraPackets0(extra, ret); -+ return ret; -+ } -+ -+ private static void buildExtraPackets0(java.util.List extraPackets, java.util.List into) { -+ for (Packet extra : extraPackets) { -+ into.add(extra); -+ java.util.List extraExtra = extra.getExtraPackets(); -+ if (extraExtra != null && !extraExtra.isEmpty()) { -+ buildExtraPackets0(extraExtra, into); -+ } -+ } -+ } -+ // Paper start -+ private static boolean canSendImmediate(Connection networkManager, Packet packet) { -+ return networkManager.isPending || networkManager.protocol != ConnectionProtocol.PLAY || -+ packet instanceof ClientboundKeepAlivePacket || -+ packet instanceof ClientboundChatPacket || -+ packet instanceof ClientboundCommandSuggestionsPacket || -+ packet instanceof ClientboundSetTitlesPacket || -+ packet instanceof ClientboundBossEventPacket; -+ } -+ // Paper end -+ } -+ // Paper end - - public void send(Packet packet) { - this.send(packet, (GenericFutureListener) null); - } - - public void send(Packet packet, @Nullable GenericFutureListener> callback) { -- if (this.isConnected()) { -- this.flushQueue(); -- this.sendPacket(packet, callback); -- } else { -- this.queue.add(new Connection.PacketHolder(packet, callback)); -+ // Paper start - handle oversized packets better -+ boolean connected = this.isConnected(); -+ if (!connected && !preparing) { -+ return; // Do nothing -+ } -+ packet.onPacketDispatch(getPlayer()); -+ if (connected && (InnerUtil.canSendImmediate(this, packet) || ( -+ MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() && -+ (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) -+ ))) { -+ this.dispatchPacket(packet, callback); -+ return; - } -+ // write the packets to the queue, then flush - antixray hooks there already -+ java.util.List extraPackets = InnerUtil.buildExtraPackets(packet); -+ boolean hasExtraPackets = extraPackets != null && !extraPackets.isEmpty(); -+ if (!hasExtraPackets) { -+ this.queue.add(new Connection.PacketHolder(packet, callback)); -+ } else { -+ java.util.List packets = new java.util.ArrayList<>(1 + extraPackets.size()); -+ packets.add(new Connection.PacketHolder(packet, null)); // delay the future listener until the end of the extra packets -+ -+ for (int i = 0, len = extraPackets.size(); i < len;) { -+ Packet extra = extraPackets.get(i); -+ boolean end = ++i == len; -+ packets.add(new Connection.PacketHolder(extra, end ? callback : null)); // append listener to the end -+ } - -+ this.queue.addAll(packets); // atomic -+ } -+ this.sendPacketQueue(); -+ // Paper end - } - - private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.sendPacket(packet, genericFutureListener); } // Paper - OBFHELPER -@@ -194,54 +271,119 @@ public class Connection extends SimpleChannelInboundHandler> { - this.channel.config().setAutoRead(false); - } - -+ ServerPlayer player = getPlayer(); // Paper - if (this.channel.eventLoop().inEventLoop()) { - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end - - ChannelFuture channelfuture = this.channel.writeAndFlush(packet); - - if (callback != null) { - channelfuture.addListener(callback); - } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end - - channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ disconnect(new TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end - } else { - this.channel.eventLoop().execute(() -> { - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } - -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end - ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet); - -+ - if (callback != null) { - channelfuture1.addListener(callback); - } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end - - channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ disconnect(new TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end - }); - } - - } - -- private void sendPacketQueue() { this.flushQueue(); } // Paper - OBFHELPER -- private void flushQueue() { -- if (this.channel != null && this.channel.isOpen()) { -- Queue queue = this.queue; -- -+ // Paper start - rewrite this to be safer if ran off main thread -+ private boolean sendPacketQueue() { return this.p(); } // OBFHELPER // void -> boolean -+ private boolean p() { // void -> boolean -+ if (!isConnected()) { -+ return true; -+ } -+ if (MCUtil.isMainThread()) { -+ return processQueue(); -+ } else if (isPending) { -+ // Should only happen during login/status stages - synchronized (this.queue) { -- Connection.PacketHolder networkmanager_queuedpacket; -- -- while ((networkmanager_queuedpacket = (Connection.PacketHolder) this.queue.poll()) != null) { -- this.sendPacket(networkmanager_queuedpacket.packet, networkmanager_queuedpacket.listener); -- } -+ return this.processQueue(); -+ } -+ } -+ return false; -+ } -+ private boolean processQueue() { -+ if (this.queue.isEmpty()) return true; -+ // If we are on main, we are safe here in that nothing else should be processing queue off main anymore -+ // But if we are not on main due to login/status, the parent is synchronized on packetQueue -+ java.util.Iterator iterator = this.queue.iterator(); -+ while (iterator.hasNext()) { -+ Connection.PacketHolder queued = iterator.next(); // poll -> peek -+ -+ // Fix NPE (Spigot bug caused by handleDisconnection()) -+ if (queued == null) { -+ return true; -+ } - -+ Packet packet = queued.getPacket(); -+ if (!packet.isReady()) { -+ return false; -+ } else { -+ iterator.remove(); -+ this.dispatchPacket(packet, queued.getGenericFutureListener()); - } - } -+ return true; - } -+ // Paper end - - public void tick() { -- this.flushQueue(); -+ this.p(); - if (this.packetListener instanceof ServerLoginPacketListenerImpl) { - ((ServerLoginPacketListenerImpl) this.packetListener).tick(); - } -@@ -271,9 +413,21 @@ public class Connection extends SimpleChannelInboundHandler> { - return this.address; - } - -+ // Paper start -+ public void clearPacketQueue() { -+ ServerPlayer player = getPlayer(); -+ queue.forEach(queuedPacket -> { -+ Packet packet = queuedPacket.getPacket(); -+ if (packet.hasFinishListener()) { -+ packet.onPacketDispatchFinish(player, null); -+ } -+ }); -+ queue.clear(); -+ } // Paper end - public void disconnect(Component disconnectReason) { - // Spigot Start - this.preparing = false; -+ clearPacketQueue(); // Paper - // Spigot End - if (this.channel.isOpen()) { - this.channel.close(); // We can't wait as this may be called from an event loop. -@@ -341,7 +495,7 @@ public class Connection extends SimpleChannelInboundHandler> { - public void handleDisconnection() { - if (this.channel != null && !this.channel.isOpen()) { - if (this.disconnectionHandled) { -- Connection.LOGGER.warn("handleDisconnection() called twice"); -+ //NetworkManager.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message - } else { - this.disconnectionHandled = true; - if (this.getDisconnectedReason() != null) { -@@ -349,7 +503,7 @@ public class Connection extends SimpleChannelInboundHandler> { - } else if (this.getPacketListener() != null) { - this.getPacketListener().a(new TranslatableComponent("multiplayer.disconnect.generic")); - } -- this.queue.clear(); // Free up packet queue. -+ clearPacketQueue(); // Paper - // Paper start - Add PlayerConnectionCloseEvent - final PacketListener packetListener = this.getPacketListener(); - if (packetListener instanceof ServerGamePacketListenerImpl) { -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index 9914a82ba0ec146ab13fe94c4dbf0ebf64926536..22db5d0d2cc33498ca40162c66aa3b5fbf2f569f 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -1,5 +1,6 @@ - package net.minecraft.network.protocol; - -+import io.netty.channel.ChannelFuture; // Paper - import java.io.IOException; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.PacketListener; -@@ -13,6 +14,20 @@ public interface Packet { - void handle(T listener); - - // Paper start -+ -+ /** -+ * @param player Null if not at PLAY stage yet -+ */ -+ default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} -+ -+ /** -+ * @param player Null if not at PLAY stage yet -+ * @param future Can be null if packet was cancelled -+ */ -+ default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} -+ default boolean hasFinishListener() { return false; } -+ default boolean isReady() { return true; } -+ default java.util.List getExtraPackets() { return null; } - default boolean packetTooLarge(NetworkManager manager) { - return false; - } -diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -index 6cb51a4fe3c11f53fbb556ce6b0d64b735254d51..d46910cfdc0aef046a0c79731a85d381953c328a 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -@@ -16,6 +16,7 @@ import io.netty.channel.epoll.EpollServerSocketChannel; - import io.netty.channel.nio.NioEventLoopGroup; - import io.netty.channel.socket.ServerSocketChannel; - import io.netty.channel.socket.nio.NioServerSocketChannel; -+import io.netty.handler.flush.FlushConsolidationHandler; // Paper - import io.netty.handler.timeout.ReadTimeoutHandler; - import java.io.IOException; - import java.net.InetAddress; -@@ -54,10 +55,12 @@ public class ServerConnectionListener { - private final List connections = Collections.synchronizedList(Lists.newArrayList()); - // Paper start - prevent blocking on adding a new network manager while the server is ticking - private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private static final boolean disableFlushConsolidation = Boolean.getBoolean("Paper.disableFlushConsolidate"); // Paper - private void addPending() { - Connection manager = null; - while ((manager = pending.poll()) != null) { - connections.add(manager); -+ manager.isPending = false; - } - } - // Paper end -@@ -92,6 +95,7 @@ public class ServerConnectionListener { - ; - } - -+ if (!disableFlushConsolidation) channel.pipeline().addFirst(new FlushConsolidationHandler()); // Paper - channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyQueryHandler(ServerConnectionListener.this)).addLast("splitter", new Varint21FrameDecoder()).addLast("decoder", new PacketDecoder(PacketFlow.SERVERBOUND)).addLast("prepender", new Varint21LengthFieldPrepender()).addLast("encoder", new PacketEncoder(PacketFlow.CLIENTBOUND)); - int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); - Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); diff --git a/Remapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch b/Remapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch deleted file mode 100644 index 83303e9b30..0000000000 --- a/Remapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 05:00:57 -0400 -Subject: [PATCH] Handle Oversized Tile Entities in chunks - -Splits out Extra Packets if too many TE's are encountered to prevent -creating too large of a packet to sed. - -Co authored by Spottedleaf - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -index b7d303b5f51a35504888933efef74564fa01e59d..b587f774c8f88f2a1c3ea489f7e4fe0bbdeb5a41 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -@@ -34,7 +34,15 @@ public class ClientboundLevelChunkPacket implements Packet extraPackets = new java.util.ArrayList<>(); -+ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); - -+ @Override -+ public java.util.List getExtraPackets() { -+ return extraPackets; -+ } -+ // Paper end - public ClientboundLevelChunkPacket(LevelChunk chunk, int includedSectionsMask) { - ChunkPos chunkcoordintpair = chunk.getPos(); - -@@ -61,6 +69,7 @@ public class ClientboundLevelChunkPacket implements Packet> 4; - - if (this.isFullChunk() || (includedSectionsMask & 1 << j) != 0) { -+ // Paper start - improve oversized chunk data packet handling -+ if (++totalTileEntities > TE_LIMIT) { -+ ClientboundBlockEntityDataPacket updatePacket = tileentity.getUpdatePacket(); -+ if (updatePacket != null) { -+ this.extraPackets.add(updatePacket); -+ continue; -+ } -+ } -+ // Paper end - CompoundTag nbttagcompound = tileentity.getUpdateTag(); - if (tileentity instanceof SkullBlockEntity) { SkullBlockEntity.sanitizeTileEntityUUID(nbttagcompound); } // Paper - diff --git a/Remapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/Remapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch deleted file mode 100644 index 1209aa99ea..0000000000 --- a/Remapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 2 Mar 2019 16:12:35 -0500 -Subject: [PATCH] MC-145260: Fix Whitelist On/Off inconsistency - -mojang stored whitelist state in 2 places (Whitelist Object, PlayerList) - -some things checked PlayerList, some checked object. This moves -everything to the Whitelist object. - -https://github.com/PaperMC/Paper/issues/1880 - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 5b71b487836cdd2ddc75b2039f4dc0177719d345..8d133d3c825f7747081de99ee67d4556e5c19cdd 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -55,6 +55,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; - import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket; - import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.PlayerAdvancements; - import net.minecraft.server.ServerScoreboard; -@@ -1012,9 +1013,9 @@ public abstract class PlayerList { - } - public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { - boolean isOp = this.ops.contains(gameprofile); -- boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile); -+ boolean isWhitelisted = !this.isUsingWhitelist() || isOp || this.whitelist.contains(gameprofile); - final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; -- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); -+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.isUsingWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); - event.callEvent(); - if (!event.isWhitelisted()) { - if (loginEvent != null) { -@@ -1062,7 +1063,7 @@ public abstract class PlayerList { - MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { -- this.savePlayerFile((EntityPlayer) this.players.get(i)); -+ this.save((ServerPlayer) this.players.get(i)); - } - MinecraftTimings.savePlayers.stopTiming(); // Paper - return null; }); // Paper - ensure main diff --git a/Remapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/Remapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch deleted file mode 100644 index eb4f5ff56c..0000000000 --- a/Remapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 4 Mar 2019 02:23:28 -0500 -Subject: [PATCH] Set Zombie last tick at start of drowning process - -Fixes GH-1887 - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index ad4eeb15771750193a28116117992270c72a3644..6fecf4188fc0247143edc688c03e645376960687 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -220,6 +220,7 @@ public class Zombie extends Monster { - ++this.inWaterTime; - if (this.inWaterTime >= 600) { - this.startUnderWaterConversion(300); -+ this.lastTick = MinecraftServer.currentTick; // Paper - Make sure this is set at start of process - GH-1887 - } - } else { - this.inWaterTime = -1; diff --git a/Remapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch b/Remapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch deleted file mode 100644 index c23cb450e8..0000000000 --- a/Remapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch +++ /dev/null @@ -1,271 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 15 Feb 2019 01:08:19 -0500 -Subject: [PATCH] Allow Saving of Oversized Chunks - -The Minecraft World Region File format has a hard cap of 1MB per chunk. -This is due to the fact that the header of the file format only allocates -a single byte for sector count, meaning a maximum of 256 sectors, at 4k per sector. - -This limit can be reached fairly easily with books, resulting in the chunk being unable -to save to the world. Worse off, is that nothing printed when this occured, and silently -performed a chunk rollback on next load. - -This leads to security risk with duplication and is being actively exploited. - -This patch catches the too large scenario, falls back and moves any large Entity -or Tile Entity into a new compound, and this compound is saved into a different file. - -On Chunk Load, we check for oversized status, and if so, we load the extra file and -merge the Entities and Tile Entities from the oversized chunk back into the level to -then be loaded as normal. - -Once a chunk is returned back to normal size, the oversized flag will clear, and no -extra data file will exist. - -This fix maintains compatability with all existing Anvil Region Format tools as it -does not alter the save format. They will just not know about the extra entities. - -This fix also maintains compatability if someone switches server jars to one without -this fix, as the data will remain in the oversized file. Once the server returns -to a jar with this fix, the data will be restored. - -diff --git a/src/main/java/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java -index c4fbc0bc8b80d16f09d3c6642acc7476a0817868..b3838e709c1581c25da7738c9a03a827761845b1 100644 ---- a/src/main/java/net/minecraft/nbt/NbtIo.java -+++ b/src/main/java/net/minecraft/nbt/NbtIo.java -@@ -132,6 +132,7 @@ public class NbtIo { - - } - -+ public static CompoundTag readNBT(DataInput datainput) throws IOException { return read(datainput); } // Paper - OBFHELPER - public static CompoundTag read(DataInput input) throws IOException { - return read(input, NbtAccounter.UNLIMITED); - } -@@ -152,6 +153,7 @@ public class NbtIo { - } - } - -+ public static void writeNBT(CompoundTag nbttagcompound, DataOutput dataoutput) throws IOException { write(nbttagcompound, dataoutput); } // Paper - OBFHELPER - public static void write(CompoundTag tag, DataOutput output) throws IOException { - writeUnnamedTag((Tag) tag, output); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 1aa4d342b97f8be71c108194a6f1e0e2828aa364..424628c9588c02454558bc7e7c5bad3a3e75ec9f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -20,8 +20,12 @@ import java.nio.file.LinkOption; - import java.nio.file.Path; - import java.nio.file.StandardCopyOption; - import java.nio.file.StandardOpenOption; -+import java.util.zip.InflaterInputStream; // Paper -+ - import javax.annotation.Nullable; - import net.minecraft.Util; -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.nbt.NbtIo; - import net.minecraft.world.level.ChunkPos; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -38,6 +42,7 @@ public class RegionFile implements AutoCloseable { - private final IntBuffer timestamps; - @VisibleForTesting - protected final RegionBitmap usedSectors; -+ public final File file; // Paper - - public RegionFile(File file, File directory, boolean dsync) throws IOException { - this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); -@@ -45,6 +50,8 @@ public class RegionFile implements AutoCloseable { - - public RegionFile(Path file, Path directory, RegionFileVersion outputChunkStreamVersion, boolean dsync) throws IOException { - this.header = ByteBuffer.allocateDirect(8192); -+ this.file = file.toFile(); // Paper -+ initOversizedState(); // Paper - this.usedSectors = new RegionBitmap(); - this.version = outputChunkStreamVersion; - if (!Files.isDirectory(directory, new LinkOption[0])) { -@@ -408,6 +415,74 @@ public class RegionFile implements AutoCloseable { - void run() throws IOException; - } - -+ // Paper start -+ private final byte[] oversized = new byte[1024]; -+ private int oversizedCount = 0; -+ -+ private synchronized void initOversizedState() throws IOException { -+ File metaFile = getOversizedMetaFile(); -+ if (metaFile.exists()) { -+ final byte[] read = java.nio.file.Files.readAllBytes(metaFile.toPath()); -+ System.arraycopy(read, 0, oversized, 0, oversized.length); -+ for (byte temp : oversized) { -+ oversizedCount += temp; -+ } -+ } -+ } -+ -+ private static int getChunkIndex(int x, int z) { -+ return (x & 31) + (z & 31) * 32; -+ } -+ synchronized boolean isOversized(int x, int z) { -+ return this.oversized[getChunkIndex(x, z)] == 1; -+ } -+ synchronized void setOversized(int x, int z, boolean oversized) throws IOException { -+ final int offset = getChunkIndex(x, z); -+ boolean previous = this.oversized[offset] == 1; -+ this.oversized[offset] = (byte) (oversized ? 1 : 0); -+ if (!previous && oversized) { -+ oversizedCount++; -+ } else if (!oversized && previous) { -+ oversizedCount--; -+ } -+ if (previous && !oversized) { -+ File oversizedFile = getOversizedFile(x, z); -+ if (oversizedFile.exists()) { -+ oversizedFile.delete(); -+ } -+ } -+ if (oversizedCount > 0) { -+ if (previous != oversized) { -+ writeOversizedMeta(); -+ } -+ } else if (previous) { -+ File oversizedMetaFile = getOversizedMetaFile(); -+ if (oversizedMetaFile.exists()) { -+ oversizedMetaFile.delete(); -+ } -+ } -+ } -+ -+ private void writeOversizedMeta() throws IOException { -+ java.nio.file.Files.write(getOversizedMetaFile().toPath(), oversized); -+ } -+ -+ private File getOversizedMetaFile() { -+ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + ".oversized.nbt"); -+ } -+ -+ private File getOversizedFile(int x, int z) { -+ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); -+ } -+ -+ synchronized CompoundTag getOversizedData(int x, int z) throws IOException { -+ File file = getOversizedFile(x, z); -+ try (DataInputStream out = new DataInputStream(new BufferedInputStream(new InflaterInputStream(new java.io.FileInputStream(file))))) { -+ return NbtIo.readNBT((java.io.DataInput) out); -+ } -+ -+ } -+ // Paper end - class ChunkBuffer extends ByteArrayOutputStream { - - private final ChunkPos pos; -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index f33a5fc725d1d5e895f8878d82ebc4172237ad29..6d3e1bb20d1ab8ce5c9ea613322042d80550761a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -10,7 +10,9 @@ import java.io.File; - import java.io.IOException; - import javax.annotation.Nullable; - import net.minecraft.nbt.CompoundTag; -+import net.minecraft.nbt.ListTag; - import net.minecraft.nbt.NbtIo; -+import net.minecraft.nbt.Tag; - import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionCollector; - import net.minecraft.world.level.ChunkPos; -@@ -50,6 +52,74 @@ public final class RegionFileStorage implements AutoCloseable { - } - } - -+ // Paper start -+ private static void printOversizedLog(String msg, File file, int x, int z) { -+ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); -+ } -+ -+ private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 8; -+ private static final int OVERZEALOUS_TOTAL_THRESHOLD = 1024 * 64; -+ private static final int OVERZEALOUS_THRESHOLD = 1024; -+ private static int SIZE_THRESHOLD = DEFAULT_SIZE_THRESHOLD; -+ private static void resetFilterThresholds() { -+ SIZE_THRESHOLD = Math.max(1024 * 4, Integer.getInteger("Paper.FilterThreshhold", DEFAULT_SIZE_THRESHOLD)); -+ } -+ static { -+ resetFilterThresholds(); -+ } -+ -+ static boolean isOverzealous() { -+ return SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD; -+ } -+ -+ -+ private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException { -+ synchronized (regionfile) { -+ try (DataInputStream datainputstream = regionfile.getReadStream(chunkCoordinate)) { -+ CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); -+ CompoundTag chunk = NbtIo.readNBT((DataInput) datainputstream); -+ if (oversizedData == null) { -+ return chunk; -+ } -+ CompoundTag oversizedLevel = oversizedData.getCompound("Level"); -+ CompoundTag level = chunk.getCompound("Level"); -+ -+ mergeChunkList(level, oversizedLevel, "Entities"); -+ mergeChunkList(level, oversizedLevel, "TileEntities"); -+ -+ chunk.put("Level", level); -+ -+ return chunk; -+ } catch (Throwable throwable) { -+ throwable.printStackTrace(); -+ throw throwable; -+ } -+ } -+ } -+ -+ private static void mergeChunkList(CompoundTag level, CompoundTag oversizedLevel, String key) { -+ ListTag levelList = level.getList(key, 10); -+ ListTag oversizedList = oversizedLevel.getList(key, 10); -+ -+ if (!oversizedList.isEmpty()) { -+ levelList.addAll(oversizedList); -+ level.put(key, levelList); -+ } -+ } -+ -+ private static int getNBTSize(Tag nbtBase) { -+ DataOutputStream test = new DataOutputStream(new org.apache.commons.io.output.NullOutputStream()); -+ try { -+ nbtBase.write(test); -+ return test.size(); -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return 0; -+ } -+ } -+ -+ // Paper End -+ - @Nullable - public CompoundTag read(ChunkPos pos) throws IOException { - // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing -@@ -59,6 +129,12 @@ public final class RegionFileStorage implements AutoCloseable { - } - // CraftBukkit end - DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); -+ // Paper start -+ if (regionfile.isOversized(pos.x, pos.z)) { -+ printOversizedLog("Loading Oversized Chunk!", regionfile.file, pos.x, pos.z); -+ return readOversizedChunk(regionfile, pos); -+ } -+ // Paper end - Throwable throwable = null; - - CompoundTag nbttagcompound; -@@ -99,6 +175,7 @@ public final class RegionFileStorage implements AutoCloseable { - - try { - NbtIo.write(tag, (DataOutput) dataoutputstream); -+ regionfile.setOversized(pos.x, pos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone - } catch (Throwable throwable1) { - throwable = throwable1; - throw throwable1; diff --git a/Remapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/Remapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch deleted file mode 100644 index 5fcbc4df8c..0000000000 --- a/Remapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Wed, 13 Mar 2019 20:08:09 +0200 -Subject: [PATCH] Call WhitelistToggleEvent when whitelist is toggled - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8d133d3c825f7747081de99ee67d4556e5c19cdd..728eaadd3dc619e414ec30feb38c7d4a84b2e539 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1131,6 +1131,7 @@ public abstract class PlayerList { - } - - public void setUsingWhiteList(boolean whitelistEnabled) { -+ new com.destroystokyo.paper.event.server.WhitelistToggleEvent(whitelistEnabled).callEvent(); - this.doWhiteList = whitelistEnabled; - } - diff --git a/Remapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch b/Remapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch deleted file mode 100644 index d02aab104b..0000000000 --- a/Remapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch +++ /dev/null @@ -1,187 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 22 Sep 2018 00:33:08 -0500 -Subject: [PATCH] Add LivingEntity#getTargetEntity - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c5d6235a132818dfc78105e9d03d0687f697bb00..d106118dbf4fb270f8526e40a767dd4c563a333f 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1503,6 +1503,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.calculateViewVector(pitch - 90.0F, yaw); - } - -+ public final Vec3 getEyePosition(float partialTicks) { return getEyePosition(partialTicks); } // Paper - OBFHELPER - public final Vec3 getEyePosition(float tickDelta) { - if (tickDelta == 1.0F) { - return new Vec3(this.getX(), this.getEyeY(), this.getZ()); -@@ -2153,6 +2154,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.getPassengers().size() < 1; - } - -+ public final float getCollisionBorderSize() { return getPickRadius(); } // Paper - OBFHELPER - public float getPickRadius() { - return 0.0F; - } -diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index e92a8c4c49c452e1f3f0c06398f2a74e3432262f..d3640975c5a33b4911428760691215905b987385 100644 ---- a/src/main/java/net/minecraft/world/entity/EntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -22,6 +22,7 @@ public final class EntitySelector { - public static final Predicate NO_CREATIVE_OR_SPECTATOR = (entity) -> { - return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative(); - }; -+ public static Predicate canAITarget() { return ATTACK_ALLOWED; } // Paper - OBFHELPER - public static final Predicate ATTACK_ALLOWED = (entity) -> { - return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative() && entity.level.getDifficulty() != Difficulty.PEACEFUL; - }; -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 29d4ed42e5d763639a50d849ef274c4d848bc9c9..046a05925739005080af35c4be984303b575bf68 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -108,6 +108,7 @@ import net.minecraft.world.level.storage.loot.LootTable; - import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; - import net.minecraft.world.level.storage.loot.parameters.LootContextParams; - import net.minecraft.world.phys.AABB; -+import net.minecraft.world.phys.EntityHitResult; - import net.minecraft.world.phys.HitResult; - import net.minecraft.world.phys.Vec3; - import net.minecraft.world.scores.PlayerTeam; -@@ -3657,6 +3658,37 @@ public abstract class LivingEntity extends Entity { - return level.clip(raytrace); - } - -+ public EntityHitResult getTargetEntity(int maxDistance) { -+ if (maxDistance < 1 || maxDistance > 120) { -+ throw new IllegalArgumentException("maxDistance must be between 1-120"); -+ } -+ -+ Vec3 start = this.getEyePosition(1.0F); -+ Vec3 direction = this.getLookAngle(); -+ Vec3 end = start.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance); -+ -+ List entityList = level.getEntities(this, getBoundingBox().expand(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance).inflate(1.0D, 1.0D, 1.0D), EntitySelector.canAITarget().and(Entity::isPickable)); -+ -+ double distance = 0.0D; -+ EntityHitResult result = null; -+ -+ for (Entity entity : entityList) { -+ AABB aabb = entity.getBoundingBox().grow((double) entity.getCollisionBorderSize()); -+ Optional rayTraceResult = aabb.calculateIntercept(start, end); -+ -+ if (rayTraceResult.isPresent()) { -+ Vec3 rayTrace = rayTraceResult.get(); -+ double distanceTo = start.distanceToSqr(rayTrace); -+ if (distanceTo < distance || distance == 0.0D) { -+ result = new EntityHitResult(entity, rayTrace); -+ distance = distanceTo; -+ } -+ } -+ } -+ -+ return result; -+ } -+ - public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; - - public int getShieldBlockingDelay() { -diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java -index 983d0495ec35128ca3ef68566ada065bc4b21efc..143a160a7577e9e34d34a9f3b900db03d3f297af 100644 ---- a/src/main/java/net/minecraft/world/phys/AABB.java -+++ b/src/main/java/net/minecraft/world/phys/AABB.java -@@ -116,6 +116,7 @@ public class AABB { - return this.expandTowards(scale.x, scale.y, scale.z); - } - -+ public final AABB expand(double x, double y, double z) { return expandTowards(x, y, z); } // Paper - OBFHELPER - public AABB expandTowards(double x, double y, double z) { - double d3 = this.minX; - double d4 = this.minY; -@@ -145,6 +146,12 @@ public class AABB { - return new AABB(d3, d4, d5, d6, d7, d8); - } - -+ // Paper start -+ public AABB grow(double d0) { -+ return inflate(d0, d0, d0); -+ } -+ // Paper end -+ - public AABB inflate(double x, double y, double z) { - double d3 = this.minX - x; - double d4 = this.minY - y; -@@ -204,6 +211,7 @@ public class AABB { - return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ; - } - -+ public final boolean contains(Vec3 vec3d) { return contains(vec3d); } // Paper - OBFHELPER - public boolean contains(Vec3 vec) { - return this.contains(vec.x, vec.y, vec.z); - } -@@ -237,6 +245,7 @@ public class AABB { - return this.inflate(-value); - } - -+ public final Optional calculateIntercept(Vec3 vec3d, Vec3 vec3d1) { return clip(vec3d, vec3d1); } // Paper - OBFHELPER - public Optional clip(Vec3 min, Vec3 max) { - double[] adouble = new double[]{1.0D}; - double d0 = max.x - min.x; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 7e3a215f1592bed9f35e22076d9e35a5a49a430e..a01bd035846df0e2e28dc55e2ef2f5f35b83f905 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -1,6 +1,7 @@ - package org.bukkit.craftbukkit.entity; - - import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.destroystokyo.paper.entity.TargetEntityInfo; - import com.google.common.base.Preconditions; - import com.google.common.collect.Sets; - import java.util.ArrayList; -@@ -30,8 +31,11 @@ import net.minecraft.world.entity.projectile.ThrownEgg; - import net.minecraft.world.entity.projectile.ThrownEnderpearl; - import net.minecraft.world.entity.projectile.ThrownExperienceBottle; - import net.minecraft.world.entity.projectile.ThrownTrident; -+import net.minecraft.world.level.ClipContext; - import net.minecraft.world.phys.BlockHitResult; -+import net.minecraft.world.phys.EntityHitResult; - import net.minecraft.world.phys.HitResult; -+import net.minecraft.world.phys.Vec3; - import org.apache.commons.lang.Validate; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -215,6 +219,33 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - new TargetBlockInfo(CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()), - MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection())); - } -+ -+ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks) { -+ EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); -+ return rayTrace == null ? null : rayTrace.getEntity().getBukkitEntity(); -+ } -+ -+ public TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks) { -+ EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); -+ return rayTrace == null ? null : new TargetEntityInfo(rayTrace.getEntity().getBukkitEntity(), new org.bukkit.util.Vector(rayTrace.getLocation().x, rayTrace.getLocation().y, rayTrace.getLocation().z)); -+ } -+ -+ public EntityHitResult rayTraceEntity(int maxDistance, boolean ignoreBlocks) { -+ EntityHitResult rayTrace = getHandle().getTargetEntity(maxDistance); -+ if (rayTrace == null) { -+ return null; -+ } -+ if (!ignoreBlocks) { -+ HitResult rayTraceBlocks = getHandle().getRayTrace(maxDistance, ClipContext.Fluid.NONE); -+ if (rayTraceBlocks != null) { -+ Vec3 eye = getHandle().getEyePosition(1.0F); -+ if (eye.distanceToSqr(rayTraceBlocks.getLocation()) <= eye.distanceToSqr(rayTrace.getLocation())) { -+ return null; -+ } -+ } -+ } -+ return rayTrace; -+ } - // Paper end - - @Override diff --git a/Remapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/Remapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch deleted file mode 100644 index c6e42c264d..0000000000 --- a/Remapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 20 Mar 2019 21:19:29 -0700 -Subject: [PATCH] Use proper max length when serialising BungeeCord text - component - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -index f13da9e7d014bc00fbabf0a495b548bba2f59468..002a6c7933f64405707d7d34d3e5c17584539623 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -@@ -9,7 +9,7 @@ import net.minecraft.network.chat.Component; - import net.minecraft.network.protocol.Packet; - - public class ClientboundChatPacket implements Packet { -- -+ private static final int MAX_LENGTH = Short.MAX_VALUE * 8 + 8; // Paper - private Component message; - public net.kyori.adventure.text.Component adventure$message; // Paper - public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot -@@ -43,9 +43,9 @@ public class ClientboundChatPacket implements Packet { - //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below - // Paper start - don't nest if we don't need to so that we can preserve formatting - if (this.components.length == 1) { -- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); -+ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]), MAX_LENGTH); // Paper - use proper max length - } else { -- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); -+ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components), MAX_LENGTH); // Paper - use proper max length - } - // Paper end - } else { diff --git a/Remapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch b/Remapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch deleted file mode 100644 index 18095e343f..0000000000 --- a/Remapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 00:24:52 -0400 -Subject: [PATCH] Entity#getEntitySpawnReason - -Allows you to return the SpawnReason for why an Entity Spawned - -Pre existing entities will return NATURAL if it was a non -persistenting Living Entity, SPAWNER for spawners, -or DEFAULT since data was not stored. - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 2ab221e5315dde4e556ee49a6962ae0091ccf616..d03b4f97102dfb88927a94ee5a5d397ac493eaa1 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1035,6 +1035,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -+ if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper - // Paper start - if (entity.valid) { - MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 728eaadd3dc619e414ec30feb38c7d4a84b2e539..4d813b6556030354f51c1ee5f18eac2166b44576 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -331,7 +331,7 @@ public abstract class PlayerList { - // CraftBukkit start - ServerLevel finalWorldServer = worldserver1; - Entity entity = EntityType.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { -- return !finalWorldServer.addWithUUID(entity1) ? null : entity1; -+ return !finalWorldServer.addEntitySerialized(entity1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity1; // Paper - // CraftBukkit end - }); - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f311e197f6e 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -63,6 +63,8 @@ import net.minecraft.world.InteractionHand; - import net.minecraft.world.InteractionResult; - import net.minecraft.world.Nameable; - import net.minecraft.world.damagesource.DamageSource; -+import net.minecraft.world.entity.animal.AbstractFish; -+import net.minecraft.world.entity.animal.Animal; - import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.vehicle.Boat; -@@ -157,6 +159,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - }; - public List entitySlice = null; -+ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; - // Paper end - - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper -@@ -1673,6 +1676,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); - tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); - } -+ if (spawnReason != null) { -+ tag.putString("Paper.SpawnReason", spawnReason.name()); -+ } - // Save entity's from mob spawner status - if (spawnedViaMobSpawner) { - tag.putBoolean("Paper.FromMobSpawner", true); -@@ -1811,6 +1817,26 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ if (tag.contains("Paper.SpawnReason")) { -+ String spawnReasonName = tag.getString("Paper.SpawnReason"); -+ try { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName); -+ } catch (Exception ignored) { -+ LogManager.getLogger().error("Unknown SpawnReason " + spawnReasonName + " for " + this); -+ } -+ } -+ if (spawnReason == null) { -+ if (spawnedViaMobSpawner) { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; -+ } else if (this instanceof Mob && (this instanceof Animal || this instanceof AbstractFish) && !((Mob) this).removeWhenFarAway(0.0)) { -+ if (!tag.getBoolean("PersistenceRequired")) { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL; -+ } -+ } -+ } -+ if (spawnReason == null) { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; -+ } - // Paper end - - } catch (Throwable throwable) { -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 1ce675d0d24ceb5724f5ac2d8f671e38f2735f74..3a7aec9bd2f3fd1b4a1981fb6a8c64b69e4875f8 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -183,6 +183,7 @@ public abstract class BaseSpawner { - // Spigot End - } - entity.spawnedViaMobSpawner = true; // Paper -+ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper - flag = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index e1bbaf620f3ed2a6cb9ce8007a78c4cee47b653e..7ad4fb57af32cc1b8278688381e1b058ed8437db 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1106,5 +1106,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public boolean fromMobSpawner() { - return getHandle().spawnedViaMobSpawner; - } -+ -+ @Override -+ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { -+ return getHandle().spawnReason; -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch b/Remapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch deleted file mode 100644 index 8f0ddb740c..0000000000 --- a/Remapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AgentTroll -Date: Fri, 22 Mar 2019 22:24:03 -0700 -Subject: [PATCH] Update entity Metadata for all tracked players - - -diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index 49c71b21b6b88bc41ca6ddf4c76186ce522ee456..1609ab94c86e964421f996d4d46aef30f8b8e696 100644 ---- a/src/main/java/net/minecraft/server/level/ServerEntity.java -+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -420,6 +420,12 @@ public class ServerEntity { - return ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp); - } - -+ // Paper start - Add broadcast method -+ void broadcast(Packet packet) { -+ this.getPacketConsumer().accept(packet); -+ } -+ // Paper end -+ - private void broadcastAndSend(Packet packet) { - this.broadcast.accept(packet); - if (this.entity instanceof ServerPlayer) { -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index d6d8d83bc16572474d56a278dd119eacc2c52476..ed4129a51351aff16455960d71a0add1b8209c02 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2286,7 +2286,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - if (event.isCancelled() || this.player.inventory.getSelected() == null || this.player.inventory.getSelected().getItem() != origItem) { - // Refresh the current entity metadata -- this.send(new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true)); -+ // Paper start - update entity for all players -+ ClientboundSetEntityDataPacket packet1 = new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true); -+ if (entity.tracker != null) { -+ entity.tracker.broadcast(packet1); -+ } else { -+ this.send(packet1); -+ } -+ // Paper end - } - - if (event.isCancelled()) { diff --git a/Remapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch b/Remapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch deleted file mode 100644 index dbfcbf2e3f..0000000000 --- a/Remapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterVector -Date: Fri, 26 Oct 2018 21:31:00 -0700 -Subject: [PATCH] Implement PlayerPostRespawnEvent - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 4d813b6556030354f51c1ee5f18eac2166b44576..7412765020854caabd32fb6f4fffcf7f4bf6dba7 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -737,9 +737,14 @@ public abstract class PlayerList { - // this.a(entityplayer1, entityplayer, worldserver1); // CraftBukkit - removed - boolean flag2 = false; - -+ // Paper start -+ boolean isBedSpawn = false; -+ boolean isRespawn = false; -+ // Paper end -+ - // CraftBukkit start - fire PlayerRespawnEvent - if (location == null) { -- boolean isBedSpawn = false; -+ // boolean isBedSpawn = false; // Paper - moved up - ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); - if (worldserver1 != null) { - Optional optional; -@@ -790,6 +795,7 @@ public abstract class PlayerList { - - location = respawnEvent.getRespawnLocation(); - if (!flag) entityplayer.reset(); // SPIGOT-4785 -+ isRespawn = true; // Paper - } else { - location.setWorld(worldserver.getWorld()); - } -@@ -847,6 +853,13 @@ public abstract class PlayerList { - if (entityplayer.connection.isDisconnected()) { - this.save(entityplayer); - } -+ -+ // Paper start -+ if (isRespawn) { -+ cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(entityplayer.getBukkitEntity(), location, isBedSpawn)); -+ } -+ // Paper end -+ - // CraftBukkit end - return entityplayer1; - } diff --git a/Remapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/Remapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch deleted file mode 100644 index df8e4e2e9a..0000000000 --- a/Remapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 18:09:20 -0400 -Subject: [PATCH] don't go below 0 for pickupDelay, breaks picking up items - -vanilla checks for == 0 - -diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 70f719ba3c68c8e9414e6b4bc68002f7c962e2b9..281f5646980afc70890bdafd358ff9b20d32420d 100644 ---- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -86,6 +86,7 @@ public class ItemEntity extends Entity { - // CraftBukkit start - Use wall time for pickup and despawn timers - int elapsedTicks = MinecraftServer.currentTick - this.lastTick; - if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; -+ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 - if (this.age != -32768) this.age += elapsedTicks; - this.lastTick = MinecraftServer.currentTick; - // CraftBukkit end -@@ -178,6 +179,7 @@ public class ItemEntity extends Entity { - // CraftBukkit start - Use wall time for pickup and despawn timers - int elapsedTicks = MinecraftServer.currentTick - this.lastTick; - if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; -+ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 - if (this.age != -32768) this.age += elapsedTicks; - this.lastTick = MinecraftServer.currentTick; - // CraftBukkit end diff --git a/Remapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch b/Remapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch deleted file mode 100644 index 9fb3057ffc..0000000000 --- a/Remapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Mar 2019 22:48:45 -0400 -Subject: [PATCH] Server Tick Events - -Fires event at start and end of a server tick - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 6ccc0be795e3ac7689de0eff6f9142d13161a29c..35984c7e994570a909ed4ffaabe64ae941b15e71 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1237,6 +1237,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Wed, 27 Mar 2019 23:01:33 -0400 -Subject: [PATCH] PlayerDeathEvent#getItemsToKeep - -Exposes a mutable array on items a player should keep on death - -Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4 - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index fd2717a00a85f91ee23a1c0f929f856972892a9b..d6cfe68be1a944ff5d5780666467f5fd8e2794e3 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -692,6 +692,46 @@ public class ServerPlayer extends Player implements ContainerListener { - }); - } - -+ // Paper start - process inventory -+ private static void processKeep(org.bukkit.event.entity.PlayerDeathEvent event, NonNullList inv) { -+ List itemsToKeep = event.getItemsToKeep(); -+ if (inv == null) { -+ // remainder of items left in toKeep - plugin added stuff on death that wasn't in the initial loot? -+ if (!itemsToKeep.isEmpty()) { -+ for (org.bukkit.inventory.ItemStack itemStack : itemsToKeep) { -+ event.getEntity().getInventory().addItem(itemStack); -+ } -+ } -+ -+ return; -+ } -+ -+ for (int i = 0; i < inv.size(); ++i) { -+ ItemStack item = inv.get(i); -+ if (EnchantmentHelper.hasVanishingCurse(item) || itemsToKeep.isEmpty() || item.isEmpty()) { -+ inv.set(i, ItemStack.NULL_ITEM); -+ continue; -+ } -+ -+ final org.bukkit.inventory.ItemStack bukkitStack = item.getBukkitStack(); -+ boolean keep = false; -+ final Iterator iterator = itemsToKeep.iterator(); -+ while (iterator.hasNext()) { -+ final org.bukkit.inventory.ItemStack itemStack = iterator.next(); -+ if (bukkitStack.equals(itemStack)) { -+ iterator.remove(); -+ keep = true; -+ break; -+ } -+ } -+ -+ if (!keep) { -+ inv.set(i, ItemStack.NULL_ITEM); -+ } -+ } -+ } -+ // Paper end -+ - @Override - public void die(DamageSource source) { - boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); -@@ -775,7 +815,12 @@ public class ServerPlayer extends Player implements ContainerListener { - this.dropExperience(); - // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. - if (!event.getKeepInventory()) { -- this.inventory.clearContent(); -+ // Paper start - replace logic -+ for (NonNullList inv : this.inventory.getComponents()) { -+ processKeep(event, inv); -+ } -+ processKeep(event, null); -+ // Paper end - } - - this.setCamera(this); // Remove spectated target diff --git a/Remapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch b/Remapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch deleted file mode 100644 index 5c22ff496a..0000000000 --- a/Remapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 6 Apr 2019 10:16:48 -0400 -Subject: [PATCH] Optimize Captured TileEntity Lookup - -upstream was doing a containsKey/get pattern, and always doing it at that. -that scenario is only even valid if were in the middle of a block place. - -Optimize to check if the captured list even has values in it, and also to -just do a get call since the value can never be null. - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index c8542636e89748699d608eb29569cacb6321d334..5193271bc257248e0d2bc9d9a477e999a97deada 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -968,12 +968,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return null; - } else { - // CraftBukkit start -- if (capturedTileEntities.containsKey(blockposition)) { -- return capturedTileEntities.get(blockposition); -+ BlockEntity tileentity = null; // Paper -+ if (!capturedTileEntities.isEmpty() && (tileentity = capturedTileEntities.get(blockposition)) != null) { // Paper -+ return tileentity; // Paper - } - // CraftBukkit end - -- BlockEntity tileentity = null; -+ //TileEntity tileentity = null; // Paper - move up - - if (this.updatingBlockEntities) { - tileentity = this.getPendingBlockEntityAt(blockposition); diff --git a/Remapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch b/Remapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch deleted file mode 100644 index 2926bb8ee6..0000000000 --- a/Remapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 1 Jan 2019 02:22:01 -0800 -Subject: [PATCH] Add Heightmap API - - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 5193271bc257248e0d2bc9d9a477e999a97deada..eb88d830fb45a6b8c990e8bdc1943d80f63c8b93 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -670,8 +670,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - } - -- @Override -- public int getHeight(Heightmap.Types heightmap, int x, int z) { -+ public final int getHighestBlockY(final Heightmap.Types heightmap, final int x, final int z) { return this.getHeight(heightmap, x, z); } // Paper - OBFHELPER -+ @Override public int getHeight(Heightmap.Types heightmap, int x, int z) { // Paper - OBFHELPER - int k; - - if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 7b5abccac9793811bd56340c8f9d23806e832365..a4231e1c3d468355c0b55ac9d2c239f1b4c54594 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -325,6 +325,29 @@ public class CraftWorld implements World { - return getHighestBlockYAt(x, z, org.bukkit.HeightMap.MOTION_BLOCKING); - } - -+ // Paper start - Implement heightmap api -+ @Override -+ public int getHighestBlockYAt(final int x, final int z, final com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { -+ this.getChunkAt(x >> 4, z >> 4); // heightmap will ret 0 on unloaded areas -+ -+ switch (heightmap) { -+ case LIGHT_BLOCKING: -+ throw new UnsupportedOperationException(); // TODO -+ //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z); -+ case ANY: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE, x, z); -+ case SOLID: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR, x, z); -+ case SOLID_OR_LIQUID: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING, x, z); -+ case SOLID_OR_LIQUID_NO_LEAVES: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z); -+ default: -+ throw new UnsupportedOperationException(); -+ } -+ } -+ // Paper end -+ - @Override - public Location getSpawnLocation() { - BlockPos spawn = world.getSpawn(); diff --git a/Remapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch b/Remapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch deleted file mode 100644 index b3ee864737..0000000000 --- a/Remapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 19 Apr 2019 12:41:13 -0500 -Subject: [PATCH] Mob Spawner API Enhancements - - -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 3a7aec9bd2f3fd1b4a1981fb6a8c64b69e4875f8..6ca378ec7868b855d46c749910c656f82ddb009f 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -65,6 +65,7 @@ public abstract class BaseSpawner { - this.spawnPotentials.clear(); // CraftBukkit - SPIGOT-3496, MC-92282 - } - -+ public boolean isActivated() { return isNearPlayer(); } // Paper - OBFHELPER - private boolean isNearPlayer() { - BlockPos blockposition = this.getPos(); - -@@ -221,6 +222,7 @@ public abstract class BaseSpawner { - } - } - -+ public void resetTimer() { delay(); } // Paper - OBFHELPER - private void delay() { - if (this.maxSpawnDelay <= this.minSpawnDelay) { - this.spawnDelay = this.minSpawnDelay; -@@ -238,7 +240,13 @@ public abstract class BaseSpawner { - } - - public void load(CompoundTag tag) { -+ // Paper start - use larger int if set -+ if (tag.contains("Paper.Delay")) { -+ this.spawnDelay = tag.getInt("Paper.Delay"); -+ } else { - this.spawnDelay = tag.getShort("Delay"); -+ } -+ // Paper end - this.spawnPotentials.clear(); - if (tag.contains("SpawnPotentials", 9)) { - ListTag nbttaglist = tag.getList("SpawnPotentials", 10); -@@ -253,10 +261,15 @@ public abstract class BaseSpawner { - } else if (!this.spawnPotentials.isEmpty()) { - this.setNextSpawnData((SpawnData) WeighedRandom.getRandomItem(this.getLevel().random, this.spawnPotentials)); - } -- -+ // Paper start - use ints if set -+ if (tag.contains("Paper.MinSpawnDelay", 99)) { -+ this.minSpawnDelay = tag.getInt("Paper.MinSpawnDelay"); -+ this.maxSpawnDelay = tag.getInt("Paper.MaxSpawnDelay"); -+ this.spawnCount = tag.getShort("SpawnCount"); -+ } else // Paper end - if (tag.contains("MinSpawnDelay", 99)) { -- this.minSpawnDelay = tag.getShort("MinSpawnDelay"); -- this.maxSpawnDelay = tag.getShort("MaxSpawnDelay"); -+ this.minSpawnDelay = tag.getInt("MinSpawnDelay"); -+ this.maxSpawnDelay = tag.getInt("MaxSpawnDelay"); - this.spawnCount = tag.getShort("SpawnCount"); - } - -@@ -281,9 +294,20 @@ public abstract class BaseSpawner { - if (minecraftkey == null) { - return tag; - } else { -- tag.putShort("Delay", (short) this.spawnDelay); -- tag.putShort("MinSpawnDelay", (short) this.minSpawnDelay); -- tag.putShort("MaxSpawnDelay", (short) this.maxSpawnDelay); -+ // Paper start -+ if (spawnDelay > Short.MAX_VALUE) { -+ tag.putInt("Paper.Delay", this.spawnDelay); -+ } -+ tag.putShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay)); -+ -+ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) { -+ tag.putInt("Paper.MinSpawnDelay", this.minSpawnDelay); -+ tag.putInt("Paper.MaxSpawnDelay", this.maxSpawnDelay); -+ } -+ -+ tag.putShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay)); -+ tag.putShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay)); -+ // Paper end - tag.putShort("SpawnCount", (short) this.spawnCount); - tag.putShort("MaxNearbyEntities", (short) this.maxNearbyEntities); - tag.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 daaf861041cf7c8f59c85535ecb99e402ab4f658..a5b88b545e08eaabf894305a9bee31c55c5b1b87 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -@@ -1,12 +1,20 @@ - package org.bukkit.craftbukkit.block; - - import com.google.common.base.Preconditions; -+import net.minecraft.core.Registry; -+import net.minecraft.nbt.CompoundTag; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.world.level.SpawnData; - import net.minecraft.world.level.block.entity.SpawnerBlockEntity; - import org.bukkit.Material; - import org.bukkit.block.Block; - import org.bukkit.block.CreatureSpawner; - import org.bukkit.entity.EntityType; -+// Paper start -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.inventory.ItemStack; -+// Paper end - - public class CraftCreatureSpawner extends CraftBlockEntityState implements CreatureSpawner { - -@@ -120,4 +128,30 @@ public class CraftCreatureSpawner extends CraftBlockEntityState -Date: Mon, 6 May 2019 01:29:25 -0400 -Subject: [PATCH] Per-Player View Distance API placeholders - -I hope to look at this more in-depth soon. It appears doable. -However this should not block the update. - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index 37a9e9df7f7f816c214c37e545288bf9329626ed..ec9436005a3a6fdfb4783d1092bb361224eb6414 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -625,9 +625,10 @@ public class EnderDragon extends Mob implements Enemy { - if (this.dragonDeathTime == 1 && !this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1028, this.getChunkCoordinates(), 0); -- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API - for (net.minecraft.server.level.ServerPlayer player : (List) ((ServerLevel)level).players()) { -- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // Paper end - double deltaX = this.getX() - player.getX(); - double deltaZ = this.getZ() - player.getZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 3a80869dc3c16cb81ac87100f28d63eee722067f..edd231568b75330d0cffbecb03a7e9dbc55d5f94 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -46,6 +46,7 @@ import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerBossEvent; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvent; - import net.minecraft.sounds.SoundEvents; -@@ -255,9 +256,9 @@ public class WitherBoss extends Monster implements RangedAttackMob { - if (!this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1023, new BlockPosition(this), 0); -- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ int viewDistance = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API - for (ServerPlayer player : (List)this.level.players()) { -- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.getX() - player.getX(); - double deltaZ = this.getZ() - player.getZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index c2c6eb54096ef85b01c0b700cbe6a8054b62729f..20de8e358789d05bb5ac15e4cdd7dda85b61b7f8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2240,6 +2240,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - super.remove(); - } - } -+ -+ @Override -+ public int getViewDistance() { -+ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO -+ } -+ -+ @Override -+ public void setViewDistance(int viewDistance) { -+ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO -+ } - // Paper end - - // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch b/Remapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch deleted file mode 100644 index 5853bd79ee..0000000000 --- a/Remapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Fri, 10 May 2019 18:38:19 +0100 -Subject: [PATCH] Fix CB call to changed postToMainThread method - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ed4129a51351aff16455960d71a0add1b8209c02..4f99c3d06e3b994708c699395adf481a6828e097 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -443,7 +443,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - this.connection.getClass(); - // CraftBukkit - Don't wait -- minecraftserver.wrapRunnable(networkmanager::handleDisconnection); -+ minecraftserver.scheduleOnMain(networkmanager::handleDisconnection); // Paper - } - - private void filterTextPacket(T text, Consumer consumer, BiFunction>> backingFilterer) { diff --git a/Remapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/Remapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch deleted file mode 100644 index 262820c228..0000000000 --- a/Remapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sat, 27 Apr 2019 20:00:43 +0100 -Subject: [PATCH] Fix sounds when item frames are modified (MC-123450) - -This also fixes the adding sound playing when the item frame direction is changed. - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java -index d6e6846a12a889222ced67937c09d184a64c60b9..429d8a50a35f07bfc16dbedf28560fa6df817644 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java -@@ -277,7 +277,7 @@ public class ItemFrame extends HangingEntity { - } - - this.getEntityData().set(ItemFrame.DATA_ITEM, itemstack); -- if (!itemstack.isEmpty() && playSound) { // CraftBukkit -+ if (!itemstack.isEmpty() && flag && playSound) { // CraftBukkit // Paper - only play sound when update flag is set - this.playSound(SoundEvents.ITEM_FRAME_ADD_ITEM, 1.0F, 1.0F); - } - diff --git a/Remapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/Remapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch deleted file mode 100644 index 367d2e18c9..0000000000 --- a/Remapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 13 May 2019 21:10:59 -0700 -Subject: [PATCH] Fix CraftServer#isPrimaryThread and MinecraftServer - isMainThread - -md_5 changed it so he could shut down the server asynchronously -from watchdog, although we have patches that prevent that type -of behavior for this exact reason. - -md_5 also placed code in PlayerConnectionUtils that would have -solved https://bugs.mojang.com/browse/MC-142590, making the change -to MinecraftServer#isMainThread irrelevant. -By reverting his change to MinecraftServer#isMainThread packet -handling that should have been handled synchronously will be handled -synchronously when the server gets shut down. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 35984c7e994570a909ed4ffaabe64ae941b15e71..9beda5e429b5c520a41d9c7f536dc48dbb6f6f9e 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2190,7 +2190,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Fri, 28 Sep 2018 21:49:53 -0400 -Subject: [PATCH] Fix issues with entity loss due to unloaded chunks - -Vanilla has risk of losing entities by causing them to be -removed from all chunks if they try to move into an unloaded chunk. - -This pretty much means high chance this entity will be lost in this -scenario. - -There is another case that adding an entity to the world can fail if -the chunk isn't loaded. - -Lots of the server is designed around addEntity never expecting to fail -for these reasons, nor is it really logical. - -This change ensures the chunks are always loaded when entities are -added to the world, or a valid entity moves between chunks. - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index d03b4f97102dfb88927a94ee5a5d397ac493eaa1..99883c83c126405fc93becefed8a1d0727b94aa7 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -848,11 +848,18 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - int k = Mth.floor(entity.getZ() / 16.0D); - - if (!entity.inChunk || entity.xChunk != i || entity.yChunk != j || entity.zChunk != k) { -+ // Paper start - remove entity if its in a chunk more correctly. -+ LevelChunk currentChunk = entity.getCurrentChunk(); -+ if (currentChunk != null) { -+ currentChunk.removeEntity(entity); -+ } -+ // Paper end -+ - if (entity.inChunk && this.hasChunk(entity.xChunk, entity.zChunk)) { - this.getChunk(entity.xChunk, entity.zChunk).removeEntity(entity, entity.yChunk); - } - -- if (!entity.checkAndResetForcedChunkAdditionFlag() && !this.hasChunk(i, k)) { -+ if (!entity.valid && !entity.checkAndResetForcedChunkAdditionFlag() && !this.hasChunk(i, k)) { // Paper - always load chunks to register valid entities location - if (entity.inChunk) { - ServerLevel.LOGGER.warn("Entity {} left loaded chunk area", entity); - } -@@ -1067,7 +1074,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return false; - } - // CraftBukkit end -- ChunkAccess ichunkaccess = this.getChunk(Mth.floor(entity.getX() / 16.0D), Mth.floor(entity.getZ() / 16.0D), ChunkStatus.FULL, entity.forcedLoading); -+ ChunkAccess ichunkaccess = this.getChunk(Mth.floor(entity.getX() / 16.0D), Mth.floor(entity.getZ() / 16.0D), ChunkStatus.FULL, true); // Paper - always load chunks for entity adds - - if (!(ichunkaccess instanceof LevelChunk)) { - return false; diff --git a/Remapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch b/Remapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch deleted file mode 100644 index 29914b85b0..0000000000 --- a/Remapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch +++ /dev/null @@ -1,249 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 21 Jul 2018 14:27:34 -0400 -Subject: [PATCH] Duplicate UUID Resolve Option - -Due to a bug in https://github.com/PaperMC/Paper/commit/2e29af3df05ec0a383f48be549d1c03200756d24 -which was added all the way back in March of 2016, it was unknown (potentially not at the time) -that an entity might actually change the seed of the random object. - -At some point, EntitySquid did start setting the seed. Due to this shared random, this caused -every entity to use a Random object with a predictable seed. - -This has caused entities to potentially generate with the same UUID.... - -Over the years, servers have had entities disappear, but no sign of trouble -because CraftBukkit removed the log lines indicating that something was wrong. - -We have fixed the root issue causing duplicate UUID's, however we now have chunk -files full of entities that have the same UUID as another entity! - -When these chunks load, the 2nd entity will not be added to the world correctly. - -If that chunk loads in a different order in the future, then it will reverse and the -missing one is now the one added to the world and not the other. This results in very -inconsistent entity behavior. - -This change allows you to recover any duplicate entity by generating a new UUID for it. -This also lets you delete them instead if you don't want to risk having new entities added to -the world that you previously did not see. - -But for those who are ok with leaving this inconsistent behavior, you may use WARN or NOTHING options. - -It is recommended you regenerate the entities, as these were legit entities, and deserve your love. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index fbf3ccfb347a5ba6e895339e9576629d940d1aa4..38d25a12c6a52d8a83214e2a0f43a218cf15ceac 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -401,4 +401,43 @@ public class PaperWorldConfig { - private void preventMovingIntoUnloadedChunks() { - preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); - } -+ -+ public enum DuplicateUUIDMode { -+ SAFE_REGEN, DELETE, NOTHING, WARN -+ } -+ public DuplicateUUIDMode duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; -+ public int duplicateUUIDDeleteRange = 32; -+ private void repairDuplicateUUID() { -+ String desiredMode = getString("duplicate-uuid-resolver", "saferegen").toLowerCase().trim(); -+ duplicateUUIDDeleteRange = getInt("duplicate-uuid-saferegen-delete-range", duplicateUUIDDeleteRange); -+ switch (desiredMode.toLowerCase()) { -+ case "regen": -+ case "regenerate": -+ case "saferegen": -+ case "saferegenerate": -+ duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; -+ log("Duplicate UUID Resolve: Regenerate New UUID if distant (Delete likely duplicates within " + duplicateUUIDDeleteRange + " blocks)"); -+ break; -+ case "remove": -+ case "delete": -+ duplicateUUIDMode = DuplicateUUIDMode.DELETE; -+ log("Duplicate UUID Resolve: Delete Entity"); -+ break; -+ case "silent": -+ case "nothing": -+ duplicateUUIDMode = DuplicateUUIDMode.NOTHING; -+ logError("Duplicate UUID Resolve: Do Nothing (no logs) - Warning, may lose indication of bad things happening"); -+ break; -+ case "log": -+ case "warn": -+ duplicateUUIDMode = DuplicateUUIDMode.WARN; -+ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); -+ break; -+ default: -+ duplicateUUIDMode = DuplicateUUIDMode.WARN; -+ logError("Warning: Invalid duplicate-uuid-resolver config " + desiredMode + " - must be one of: regen, delete, nothing, warn"); -+ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); -+ break; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 083db6c1899b5391231b6d5d5044a334212f148c..5d87a282042d7112415b7d7175031f734219f2c9 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1,6 +1,7 @@ - package net.minecraft.server.level; - - import co.aikar.timings.Timing; // Paper -+import com.destroystokyo.paper.PaperWorldConfig; // Paper - import com.google.common.collect.ImmutableList; - import com.google.common.collect.Iterables; - import com.google.common.collect.ComparisonChain; // Paper -@@ -23,14 +24,17 @@ import it.unimi.dsi.fastutil.objects.ObjectIterator; - import java.io.File; - import java.io.IOException; - import java.io.Writer; -+import java.util.HashMap; // Paper - import java.util.Collection; - import java.util.Iterator; - import java.util.List; -+import java.util.Map; // Paper - import java.util.Objects; - import java.util.Optional; - import java.util.Queue; - import java.util.Set; - import java.util.concurrent.CancellationException; -+import java.util.UUID; // Paper - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.CompletionException; - import java.util.concurrent.Executor; -@@ -71,6 +75,7 @@ import net.minecraft.world.entity.ai.village.poi.PoiManager; - import net.minecraft.world.entity.boss.EnderDragonPart; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.GameRules; -+import net.minecraft.world.level.Level; - import net.minecraft.world.level.chunk.ChunkAccess; - import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.chunk.ChunkStatus; -@@ -697,18 +702,18 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - if (chunk.needsDecoration) { - net.minecraft.server.dedicated.DedicatedServer server = this.level.getCraftServer().getServer(); - if (!server.areNpcsEnabled() && entity instanceof net.minecraft.world.entity.npc.Npc) { -- entity.remove(); -+ entity.removed = true; // Paper - needsRemoval = true; - } - - if (!server.isSpawningAnimals() && (entity instanceof net.minecraft.world.entity.animal.Animal || entity instanceof net.minecraft.world.entity.animal.WaterAnimal)) { -- entity.remove(); -+ entity.removed = true; // Paper - needsRemoval = true; - } - } -- -- if (!(entity instanceof net.minecraft.world.entity.player.Player) && (needsRemoval || !this.level.loadFromChunk(entity))) { -- // CraftBukkit end -+ // CraftBukkit end -+ checkDupeUUID(entity); // Paper -+ if (!(entity instanceof net.minecraft.world.entity.player.Player) && (entity.removed || !this.level.loadFromChunk(entity))) { // Paper - if (list == null) { - list = Lists.newArrayList(new Entity[]{entity}); - } else { -@@ -735,6 +740,44 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - }); - } - -+ // Paper start -+ private void checkDupeUUID(Entity entity) { -+ PaperWorldConfig.DuplicateUUIDMode mode = level.paperConfig.duplicateUUIDMode; -+ if (mode != PaperWorldConfig.DuplicateUUIDMode.WARN -+ && mode != PaperWorldConfig.DuplicateUUIDMode.DELETE -+ && mode != PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN) { -+ return; -+ } -+ Entity other = level.getEntity(entity.getUUID()); -+ -+ if (mode == PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN && other != null && !other.removed -+ && Objects.equals(other.getEncodeId(), entity.getEncodeId()) -+ && entity.getBukkitEntity().getLocation().distance(other.getBukkitEntity().getLocation()) < level.paperConfig.duplicateUUIDDeleteRange -+ ) { -+ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + " because it was near the duplicate and likely an actual duplicate. See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ entity.removed = true; -+ return; -+ } -+ if (other != null && !other.removed) { -+ switch (mode) { -+ case SAFE_REGEN: { -+ entity.setUUID(UUID.randomUUID()); -+ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", regenerated UUID for " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ break; -+ } -+ case DELETE: { -+ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ entity.removed = true; -+ break; -+ } -+ default: -+ if (Level.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", doing nothing to " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ break; -+ } -+ } -+ } -+ // Paper end -+ - public CompletableFuture> postProcess(ChunkHolder holder) { - ChunkPos chunkcoordintpair = holder.getPos(); - CompletableFuture, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkRangeFuture(chunkcoordintpair, 1, (i) -> { -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 99883c83c126405fc93becefed8a1d0727b94aa7..20b74fc8e1273fcd07ea4417eaedc8bd9aba93b3 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -4,6 +4,8 @@ import com.google.common.annotations.VisibleForTesting; - import com.google.common.collect.Iterables; - import co.aikar.timings.TimingHistory; // Paper - import co.aikar.timings.Timings; // Paper -+ -+import com.destroystokyo.paper.PaperWorldConfig; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Queues; -@@ -1102,7 +1104,22 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - if (entity1 == null) { - return false; - } else { -+ // Paper start -+ if (entity1.removed) { -+ onEntityRemoved(entity1); // remove the existing entity -+ return false; -+ } -+ // Paper end - ServerLevel.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityType.getKey(entity1.getType()), entity1.getId(), EntityType.getKey(entity.getType()), entity.getId()); // CraftBukkit // Paper -+ // Paper start -+ if (DEBUG_ENTITIES && entity.level.paperConfig.duplicateUUIDMode != PaperWorldConfig.DuplicateUUIDMode.NOTHING) { -+ if (entity1.addedToWorldStack != null) { -+ entity1.addedToWorldStack.printStackTrace(); -+ } -+ -+ getAddToWorldStackTrace(entity).printStackTrace(); -+ } -+ // Paper end - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 6faac8773136412ca129dfa884178f311e197f6e..af86c370c6f834514115a8e40659f5e1aaabec75 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2803,6 +2803,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - }); - } - -+ public final void setUUID(UUID uuid) { setUUID(uuid); } // Paper - OBFHELPER - public void setUUID(UUID uuid) { - this.uuid = uuid; - this.stringUUID = this.uuid.toString(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index db28bfe95c885cdefa855c7aaa3bcf92bc52df26..55872a17060a35b727a597bc414fecec3ada3515 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -541,6 +541,7 @@ public class LevelChunk implements ChunkAccess { - if (i != this.chunkPos.x || j != this.chunkPos.z) { - LevelChunk.LOGGER.warn("Wrong location! ({}, {}) should be ({}, {}), {}", i, j, this.chunkPos.x, this.chunkPos.z, entity); - entity.removed = true; -+ return; // Paper - } - - int k = Mth.floor(entity.getY() / 16.0D); diff --git a/Remapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch b/Remapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch deleted file mode 100644 index 40d4c9c49d..0000000000 --- a/Remapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 21 May 2019 02:34:04 +0100 -Subject: [PATCH] improve CraftWorld#isChunkLoaded - -getChunkAt will request the chunk using vanillas chunk loading system, -which while we're not going to load the chunk, does involve the server -waiting for the execution queue to get to our request; We can just query -the chunk status and get a response now, vs having to wait - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index a4231e1c3d468355c0b55ac9d2c239f1b4c54594..6e9e2149d854f26826d030ee6e655ca8fa7b5141 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -396,13 +396,13 @@ public class CraftWorld implements World { - - @Override - public boolean isChunkLoaded(int x, int z) { -- return world.getChunkSource().isChunkLoaded(x, z); -+ return world.getChunkSource().getChunkAtIfLoadedImmediately(x, z) != null; // Paper - } - - @Override - public boolean isChunkGenerated(int x, int z) { - try { -- return isChunkLoaded(x, z) || world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; -+ return world.getChunkSource().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; // Paper (TODO check if the first part can be removed) - } catch (IOException ex) { - throw new RuntimeException(ex); - } diff --git a/Remapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/Remapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch deleted file mode 100644 index ad03456870..0000000000 --- a/Remapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ /dev/null @@ -1,260 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 13 Sep 2014 23:14:43 -0400 -Subject: [PATCH] Configurable Keep Spawn Loaded range per world - -This lets you disable it for some worlds and lower it for others. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 38d25a12c6a52d8a83214e2a0f43a218cf15ceac..ffe9b1a63d78925e1d77b9e730aef42fed6d58fa 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -440,4 +440,10 @@ public class PaperWorldConfig { - break; - } - } -+ -+ public short keepLoadedRange; -+ private void keepLoadedRange() { -+ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); -+ log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 9beda5e429b5c520a41d9c7f536dc48dbb6f6f9e..0efe7024493f96bb54e7d8c1ea7b233a1b481a04 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -716,35 +716,36 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> 4).forEach(pair -> { -+ getChunkSource().getChunkAtMainThread(pair.x, pair.z); -+ }); -+ } -+ public void removeTicketsForSpawn(int radiusInBlocks, BlockPos spawn) { -+ // In order to respect vanilla behavior, which is ensuring everything but the spawn border can tick, we added tickets -+ // with level 31 for the non-border spawn chunks -+ ServerChunkCache chunkproviderserver = this.getChunkSource(); -+ int tickRadius = radiusInBlocks - 16; -+ -+ // remove ticking chunks -+ for (int x = -tickRadius; x <= tickRadius; x += 16) { -+ for (int z = -tickRadius; z <= tickRadius; z += 16) { -+ // radius of 2 will have the current chunk be level 31 -+ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(x, 0, z)), 2, Unit.INSTANCE); -+ } -+ } -+ -+ // remove border chunks -+ -+ // remove border along x axis (including corner chunks) -+ for (int x = -radiusInBlocks; x <= radiusInBlocks; x += 16) { -+ // top -+ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32 -+ // bottom -+ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(x, 0, -radiusInBlocks)), 1, Unit.INSTANCE); // level 32 -+ } -+ -+ // remove border along z axis (excluding corner chunks) -+ for (int z = -radiusInBlocks + 16; z < radiusInBlocks; z += 16) { -+ // right -+ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 -+ // left -+ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.add(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 -+ } -+ } -+ // Paper end -+ - public void setDefaultSpawnPos(BlockPos pos, float angle) { -- ChunkPos chunkcoordintpair = new ChunkPos(new BlockPos(this.levelData.getXSpawn(), 0, this.levelData.getZSpawn())); -+ // Paper - configurable spawn radius -+ BlockPos prevSpawn = this.getSpawn(); -+ //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); - - this.levelData.setSpawn(pos, angle); -- this.getChunkSource().removeRegionTicket(TicketType.START, chunkcoordintpair, 11, Unit.INSTANCE); -- this.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(pos), 11, Unit.INSTANCE); -+ if (this.keepSpawnInMemory) { -+ // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add -+ this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); -+ this.addTicketsForSpawn(this.paperConfig.keepLoadedRange, pos); -+ } - this.getServer().getPlayerList().broadcastAll(new ClientboundSetDefaultSpawnPositionPacket(pos, angle)); - } - -diff --git a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java -index 2860a16c80e56edb333115f6f64f65d0e56feb11..85863211a666b299cae8a3791c182ae5094b94d9 100644 ---- a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java -+++ b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java -@@ -11,4 +11,6 @@ public interface ChunkProgressListener { - void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status); - - void stop(); -+ -+ void setChunkRadius(int radius); // Paper - allow changing chunk radius - } -diff --git a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java -index 4a541f0b2582430abda6e5ff8f492e37fc903483..e810843fae13d3e83e8f509810b781859217c48b 100644 ---- a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java -+++ b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java -@@ -12,16 +12,24 @@ import org.apache.logging.log4j.Logger; - public class LoggerChunkProgressListener implements ChunkProgressListener { - - private static final Logger LOGGER = LogManager.getLogger(); -- private final int maxCount; -+ private int maxCount; // Paper - remove final - private int count; - private long startTime; - private long nextTickTime = Long.MAX_VALUE; - - public LoggerChunkProgressListener(int radius) { -+ // Paper start - Allow changing radius later for configurable spawn patch -+ this.setChunkRadius(radius); // Move to method -+ } -+ -+ @Override -+ public void setChunkRadius(int radius) { -+ // Paper - copied from above - int j = radius * 2 + 1; - - this.maxCount = j * j; - } -+ // Paper end - - @Override - public void updateSpawnPos(ChunkPos spawnPos) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 6e9e2149d854f26826d030ee6e655ca8fa7b5141..0cb0021fac211996c5bdbb2cfc8f54addc3b49f6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1954,15 +1954,21 @@ public class CraftWorld implements World { - - @Override - public void setKeepSpawnInMemory(boolean keepLoaded) { -+ // Paper start - Configurable spawn radius -+ if (keepLoaded == world.keepSpawnInMemory) { -+ // do nothing, nothing has changed -+ return; -+ } - world.keepSpawnInMemory = keepLoaded; - // Grab the worlds spawn chunk -- BlockPos chunkcoordinates = this.world.getSpawn(); -+ BlockPos prevSpawn = this.world.getSpawn(); - if (keepLoaded) { -- world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); -+ world.addTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); - } else { -- // TODO: doesn't work well if spawn changed.... -- world.getChunkSource().removeRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); -+ // TODO: doesn't work well if spawn changed.... // paper - resolved -+ world.removeTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); - } -+ // Paper end - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch b/Remapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch deleted file mode 100644 index 3475c01271..0000000000 --- a/Remapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Mon, 27 May 2019 17:35:39 -0500 -Subject: [PATCH] MC-114618 - Fix EntityAreaEffectCloud from going negative - size - - -diff --git a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java -index 949553229a55f8c8b9a5c0141409d1520eff22c7..fe4312a58b0b2ffd63db14068d99c5391e0eb0a0 100644 ---- a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java -+++ b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java -@@ -194,6 +194,12 @@ public class AreaEffectCloud extends Entity { - super.tick(); - boolean flag = this.isWaiting(); - float f = this.getRadius(); -+ // Paper start - fix MC-114618 -+ if (f < 0.0F) { -+ this.remove(); -+ return; -+ } -+ // Paper end - - if (this.level.isClientSide) { - ParticleOptions particleparam = this.getParticle(); diff --git a/Remapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch b/Remapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch deleted file mode 100644 index 09a7ae7ee7..0000000000 --- a/Remapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Wed, 29 May 2019 04:01:22 +0100 -Subject: [PATCH] ChunkMapDistance CME - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 0b8cbf75ff01b9825141be00d63679f7bcc58a9f..89e90806b78d94d5c1d781113da420dafa47930a 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -44,6 +44,7 @@ public class ChunkHolder { - private static final CompletableFuture> UNLOADED_LEVEL_CHUNK_FUTURE = CompletableFuture.completedFuture(ChunkHolder.UNLOADED_LEVEL_CHUNK); - private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); - private static final ChunkHolder.FullChunkStatus[] FULL_CHUNK_STATUSES = ChunkHolder.FullChunkStatus.values(); -+ boolean isUpdateQueued = false; // Paper - private final AtomicReferenceArray>> futures; - private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage - private volatile CompletableFuture> tickingChunkFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage -diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index 8f993f15ae02c2e4af9cc732cd1b040cce0a67e8..71a51cc99e26579e765f88340588e23956888929 100644 ---- a/src/main/java/net/minecraft/server/level/DistanceManager.java -+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -39,7 +39,16 @@ public abstract class DistanceManager { - private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); - private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); - private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); -- private final Set chunksToUpdateFutures = Sets.newHashSet(); -+ // Paper start use a queue, but still keep unique requirement -+ public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { -+ @Override -+ public boolean add(ChunkHolder o) { -+ if (o.isUpdateQueued) return true; -+ o.isUpdateQueued = true; -+ return super.add(o); -+ } -+ }; -+ // Paper end - private final ChunkTaskPriorityQueueSorter ticketThrottler; - private final ProcessorHandle> ticketThrottlerInput; - private final ProcessorHandle ticketThrottlerReleaser; -@@ -100,26 +109,14 @@ public abstract class DistanceManager { - ; - } - -- if (!this.chunksToUpdateFutures.isEmpty()) { -- // CraftBukkit start -- // Iterate pending chunk updates with protection against concurrent modification exceptions -- java.util.Iterator iter = this.chunksToUpdateFutures.iterator(); -- int expectedSize = this.chunksToUpdateFutures.size(); -- do { -- ChunkHolder playerchunk = iter.next(); -- iter.remove(); -- expectedSize--; -- -- playerchunk.updateFutures(chunkStorage); -- -- // Reset iterator if set was modified using add() -- if (this.chunksToUpdateFutures.size() != expectedSize) { -- expectedSize = this.chunksToUpdateFutures.size(); -- iter = this.chunksToUpdateFutures.iterator(); -- } -- } while (iter.hasNext()); -- // CraftBukkit end -- -+ // Paper start -+ if (!this.pendingChunkUpdates.isEmpty()) { -+ while(!this.pendingChunkUpdates.isEmpty()) { -+ ChunkHolder remove = this.pendingChunkUpdates.remove(); -+ remove.isUpdateQueued = false; -+ remove.updateFutures(chunkStorage); -+ } -+ // Paper end - return true; - } else { - if (!this.ticketsToRelease.isEmpty()) { -@@ -342,7 +339,7 @@ public abstract class DistanceManager { - if (k != level) { - playerchunk = DistanceManager.this.updateChunkScheduling(id, level, playerchunk, k); - if (playerchunk != null) { -- DistanceManager.this.chunksToUpdateFutures.add(playerchunk); -+ DistanceManager.this.pendingChunkUpdates.add(playerchunk); - } - - } -@@ -373,7 +370,7 @@ public abstract class DistanceManager { - ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); -+ Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix - byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); - long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); - diff --git a/Remapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch b/Remapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch deleted file mode 100644 index 0fd2f20b1d..0000000000 --- a/Remapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: simpleauthority -Date: Tue, 28 May 2019 03:48:51 -0700 -Subject: [PATCH] Implement CraftBlockSoundGroup - - -diff --git a/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9a516520d975f52169e346adc4ec6d9db843db2f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java -@@ -0,0 +1,38 @@ -+package com.destroystokyo.paper.block; -+ -+import net.minecraft.world.level.block.SoundType; -+import org.bukkit.Sound; -+import org.bukkit.craftbukkit.CraftSound; -+ -+public class CraftBlockSoundGroup implements BlockSoundGroup { -+ private final SoundType soundEffectType; -+ -+ public CraftBlockSoundGroup(SoundType soundEffectType) { -+ this.soundEffectType = soundEffectType; -+ } -+ -+ @Override -+ public Sound getBreakSound() { -+ return CraftSound.getBukkit(soundEffectType.getBreakSound()); -+ } -+ -+ @Override -+ public Sound getStepSound() { -+ return CraftSound.getBukkit(soundEffectType.getStepSound()); -+ } -+ -+ @Override -+ public Sound getPlaceSound() { -+ return CraftSound.getBukkit(soundEffectType.getPlaceSound()); -+ } -+ -+ @Override -+ public Sound getHitSound() { -+ return CraftSound.getBukkit(soundEffectType.getHitSound()); -+ } -+ -+ @Override -+ public Sound getFallSound() { -+ return CraftSound.getBukkit(soundEffectType.getFallSound()); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/level/block/SoundType.java b/src/main/java/net/minecraft/world/level/block/SoundType.java -index 1d3acbbc80a38998fb38e0ce37af52103f677721..44394adbe60b5e9c4654ee2f437d465bef5909a8 100644 ---- a/src/main/java/net/minecraft/world/level/block/SoundType.java -+++ b/src/main/java/net/minecraft/world/level/block/SoundType.java -@@ -54,10 +54,10 @@ public class SoundType { - public static final SoundType GILDED_BLACKSTONE = new SoundType(1.0F, 1.0F, SoundEvents.GILDED_BLACKSTONE_BREAK, SoundEvents.GILDED_BLACKSTONE_STEP, SoundEvents.GILDED_BLACKSTONE_PLACE, SoundEvents.GILDED_BLACKSTONE_HIT, SoundEvents.GILDED_BLACKSTONE_FALL); - public final float volume; - public final float pitch; -- public final SoundEvent breakSound; -+ public final SoundEvent breakSound; public final SoundEvent getBreakSound() { return this.breakSound; } // Paper - OBFHELPER // PAIL private -> public, rename breakSound - private final SoundEvent stepSound; - private final SoundEvent placeSound; -- public final SoundEvent hitSound; -+ public final SoundEvent hitSound; public final SoundEvent getHitSound() { return this.hitSound; } // Paper - OBFHELPER // PAIL private -> public, rename hitSound - private final SoundEvent fallSound; - - public SoundType(float volume, float pitch, SoundEvent breakSound, SoundEvent stepSound, SoundEvent placeSound, SoundEvent hitSound, SoundEvent fallSound) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index d73086970db19531db66c2e8af52da91d0b1ea28..5bff313dbbb3049105874846d995883e827fbc00 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -747,4 +747,11 @@ public class CraftBlock implements Block { - AABB aabb = shape.bounds(); - return new BoundingBox(getX() + aabb.minX, getY() + aabb.minY, getZ() + aabb.minZ, getX() + aabb.maxX, getY() + aabb.maxY, getZ() + aabb.maxZ); - } -+ -+ // Paper start -+ @Override -+ public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { -+ return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().defaultBlockState().getSoundType()); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch b/Remapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch deleted file mode 100644 index a8a34d2b86..0000000000 --- a/Remapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch +++ /dev/null @@ -1,490 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 1 Jun 2019 13:00:55 -0700 -Subject: [PATCH] Chunk debug command - -Prints all chunk information to a text file into the debug -folder in the root server folder. The format is in JSON, and -the data format is described in MCUtil#dumpChunks(File) - -The command will output server version and all online players to the -file as well. We do not log anything but the location, world and -username of the player. - -Also logs the value of these config values (note not all are paper's): -- keep spawn loaded value -- spawn radius -- view distance - -Each chunk has the following logged: -- Coordinate -- Ticket level & its corresponding state -- Whether it is queued for unload -- Chunk status (may be unloaded) -- All tickets on the chunk - -Example log: -https://gist.githubusercontent.com/Spottedleaf/0131e7710ffd5d531e5fd246c3367380/raw/169ae1b2e240485f99bc7a6bd8e78d90e3af7397/chunks-2019-06-01_19.57.05.txt - -For references on certain keywords (ticket, status, etc), please see: - -https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528273&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528273 -https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528577&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528577 - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 8fd716bf2e1402694798b8be03fd85821153be44..53dd6c18de8e80378852bbb141016d9574d42162 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -6,13 +6,15 @@ import com.google.common.collect.ImmutableSet; - import com.google.common.collect.Iterables; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; --import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkHolder; - import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; - import net.minecraft.world.level.ChunkPos; -+import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import org.apache.commons.lang3.tuple.MutablePair; - import org.apache.commons.lang3.tuple.Pair; - import org.bukkit.Bukkit; -@@ -41,7 +43,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); - - public PaperCommand(String name) { - super(name); -@@ -69,6 +71,21 @@ public class PaperCommand extends Command { - if (args.length == 3) - return getListMatchingLast(sender, args, EntityType.getEntityNameList().stream().map(ResourceLocation::toString).sorted().toArray(String[]::new)); - break; -+ case "debug": -+ if (args.length == 2) { -+ return getListMatchingLast(sender, args, "help", "chunks"); -+ } -+ break; -+ case "chunkinfo": -+ List worldNames = new ArrayList<>(); -+ worldNames.add("*"); -+ for (org.bukkit.World world : Bukkit.getWorlds()) { -+ worldNames.add(world.getName()); -+ } -+ if (args.length == 2) { -+ return getListMatchingLast(sender, args, worldNames); -+ } -+ break; - } - return Collections.emptyList(); - } -@@ -135,6 +152,12 @@ public class PaperCommand extends Command { - case "reload": - doReload(sender); - break; -+ case "debug": -+ doDebug(sender, args); -+ break; -+ case "chunkinfo": -+ doChunkInfo(sender, args); -+ break; - case "ver": - if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) - case "version": -@@ -152,6 +175,114 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doChunkInfo(CommandSender sender, String[] args) { -+ List worlds; -+ if (args.length < 2 || args[1].equals("*")) { -+ worlds = Bukkit.getWorlds(); -+ } else { -+ worlds = new ArrayList<>(args.length - 1); -+ for (int i = 1; i < args.length; ++i) { -+ org.bukkit.World world = Bukkit.getWorld(args[i]); -+ if (world == null) { -+ sender.sendMessage(ChatColor.RED + "World '" + args[i] + "' is invalid"); -+ return; -+ } -+ worlds.add(world); -+ } -+ } -+ -+ int accumulatedTotal = 0; -+ int accumulatedInactive = 0; -+ int accumulatedBorder = 0; -+ int accumulatedTicking = 0; -+ int accumulatedEntityTicking = 0; -+ -+ for (org.bukkit.World bukkitWorld : worlds) { -+ ServerLevel world = ((CraftWorld)bukkitWorld).getHandle(); -+ -+ int total = 0; -+ int inactive = 0; -+ int border = 0; -+ int ticking = 0; -+ int entityTicking = 0; -+ -+ for (ChunkHolder chunk : world.getChunkSource().chunkMap.updatingChunkMap.values()) { -+ if (chunk.getFullChunkIfCached() == null) { -+ continue; -+ } -+ -+ ++total; -+ -+ ChunkHolder.FullChunkStatus state = ChunkHolder.getFullChunkStatus(chunk.getTicketLevel()); -+ -+ switch (state) { -+ case INACCESSIBLE: -+ ++inactive; -+ continue; -+ case BORDER: -+ ++border; -+ continue; -+ case TICKING: -+ ++ticking; -+ continue; -+ case ENTITY_TICKING: -+ ++entityTicking; -+ continue; -+ } -+ } -+ -+ accumulatedTotal += total; -+ accumulatedInactive += inactive; -+ accumulatedBorder += border; -+ accumulatedTicking += ticking; -+ accumulatedEntityTicking += entityTicking; -+ -+ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + bukkitWorld.getName() + ChatColor.DARK_AQUA + ":"); -+ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + total + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA -+ + inactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + border + ChatColor.BLUE + " Ticking: " -+ + ChatColor.DARK_AQUA + ticking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + entityTicking); -+ } -+ if (worlds.size() > 1) { -+ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + "all listed worlds" + ChatColor.DARK_AQUA + ":"); -+ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + accumulatedTotal + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA -+ + accumulatedInactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + accumulatedBorder + ChatColor.BLUE + " Ticking: " -+ + ChatColor.DARK_AQUA + accumulatedTicking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + accumulatedEntityTicking); -+ } -+ } -+ -+ private void doDebug(CommandSender sender, String[] args) { -+ if (args.length < 2) { -+ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); -+ return; -+ } -+ -+ String debugType = args[1].toLowerCase(Locale.ENGLISH); -+ switch (debugType) { -+ case "chunks": -+ if (args.length >= 3 && args[2].toLowerCase(Locale.ENGLISH).equals("help")) { -+ sender.sendMessage(ChatColor.RED + "Use /paper debug chunks to dump loaded chunk information to a file"); -+ break; -+ } -+ File file = new File(new File(new File("."), "debug"), -+ "chunks-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); -+ sender.sendMessage(ChatColor.GREEN + "Writing chunk information dump to " + file.toString()); -+ try { -+ MCUtil.dumpChunks(file); -+ sender.sendMessage(ChatColor.GREEN + "Successfully written chunk information!"); -+ } catch (Throwable thr) { -+ MinecraftServer.LOGGER.warn("Failed to dump chunk information to file " + file.toString(), thr); -+ sender.sendMessage(ChatColor.RED + "Failed to dump chunk information, see console"); -+ } -+ -+ break; -+ case "help": -+ // fall through to default -+ default: -+ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); -+ return; -+ } -+ } -+ - /* - * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 - */ -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 1fecc81b25109592907623741225a6222a8c5ccc..a16551c81a444685f6337a65b6d7862b8c0dc684 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -9,13 +9,27 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.chat.Component; -+import net.minecraft.server.level.ChunkHolder; -+import net.minecraft.server.level.ChunkMap; -+import net.minecraft.server.level.DistanceManager; -+import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.Ticket; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.ClipContext; - import net.minecraft.world.level.Level; -+import net.minecraft.world.level.chunk.ChunkAccess; -+import net.minecraft.world.level.chunk.ChunkStatus; - import org.apache.commons.lang.exception.ExceptionUtils; -+import com.google.gson.JsonArray; -+import com.google.gson.JsonObject; -+import com.google.gson.internal.Streams; -+import com.google.gson.stream.JsonWriter; - import com.mojang.authlib.GameProfile; -+import com.mojang.datafixers.util.Either; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; - import org.bukkit.Location; - import org.bukkit.block.BlockFace; - import org.bukkit.craftbukkit.CraftWorld; -@@ -24,8 +38,11 @@ import org.spigotmc.AsyncCatcher; - - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -+import java.io.*; -+import java.util.ArrayList; - import java.util.List; - import java.util.Queue; -+import java.util.Set; - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.ExecutionException; - import java.util.concurrent.LinkedBlockingQueue; -@@ -531,4 +548,170 @@ public final class MCUtil { - - return null; - } -+ -+ public static ChunkStatus getChunkStatus(ChunkHolder chunk) { -+ List statuses = ServerChunkCache.getPossibleChunkStatuses(); -+ for (int i = statuses.size() - 1; i >= 0; --i) { -+ ChunkStatus curr = statuses.get(i); -+ CompletableFuture> future = chunk.getFutureIfPresentUnchecked(curr); -+ if (future != ChunkHolder.UNLOADED_CHUNK_FUTURE) { -+ return curr; -+ } -+ } -+ return null; // unloaded -+ } -+ -+ public static void dumpChunks(File file) throws IOException { -+ file.getParentFile().mkdirs(); -+ file.createNewFile(); -+ /* -+ * Json format: -+ * -+ * Main data format: -+ * -server-version: -+ * -data-version: -+ * -worlds: -+ * -name: -+ * -view-distance: -+ * -keep-spawn-loaded: -+ * -keep-spawn-loaded-range: -+ * -visible-chunk-count: -+ * -loaded-chunk-count: -+ * -verified-fully-loaded-chunks: -+ * -players: -+ * -chunk-data: -+ * -+ * Player format: -+ * -name: -+ * -x: -+ * -y: -+ * -z: -+ * -+ * Chunk Format: -+ * -x: -+ * -z: -+ * -ticket-level: -+ * -state: -+ * -queued-for-unload: -+ * -status: -+ * -tickets: -+ * -+ * -+ * Ticket format: -+ * -ticket-type: -+ * -ticket-level: -+ * -add-tick: -+ * -object-reason: // This depends on the type of ticket. ie POST_TELEPORT -> entity id -+ */ -+ List worlds = org.bukkit.Bukkit.getWorlds(); -+ JsonObject data = new JsonObject(); -+ -+ data.addProperty("server-version", org.bukkit.Bukkit.getVersion()); -+ data.addProperty("data-version", 0); -+ -+ JsonArray worldsData = new JsonArray(); -+ -+ for (org.bukkit.World bukkitWorld : worlds) { -+ JsonObject worldData = new JsonObject(); -+ -+ ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); -+ ChunkMap chunkMap = world.getChunkSource().chunkMap; -+ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunkMap; -+ DistanceManager chunkMapDistance = chunkMap.distanceManager; -+ List allChunks = new ArrayList<>(visibleChunks.values()); -+ List players = world.players; -+ -+ int fullLoadedChunks = 0; -+ -+ for (ChunkHolder chunk : allChunks) { -+ if (chunk.getFullChunkIfCached() != null) { -+ ++fullLoadedChunks; -+ } -+ } -+ -+ // sorting by coordinate makes the log easier to read -+ allChunks.sort((ChunkHolder v1, ChunkHolder v2) -> { -+ if (v1.location.x != v2.location.x) { -+ return Integer.compare(v1.location.x, v2.location.x); -+ } -+ return Integer.compare(v1.location.z, v2.location.z); -+ }); -+ -+ worldData.addProperty("name", world.getWorld().getName()); -+ worldData.addProperty("view-distance", world.spigotConfig.viewDistance); -+ worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); -+ worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); -+ worldData.addProperty("visible-chunk-count", visibleChunks.size()); -+ worldData.addProperty("loaded-chunk-count", chunkMap.entitiesInLevel.size()); -+ worldData.addProperty("verified-fully-loaded-chunks", fullLoadedChunks); -+ -+ JsonArray playersData = new JsonArray(); -+ -+ for (ServerPlayer player : players) { -+ JsonObject playerData = new JsonObject(); -+ -+ playerData.addProperty("name", player.getScoreboardName()); -+ playerData.addProperty("x", player.getX()); -+ playerData.addProperty("y", player.getY()); -+ playerData.addProperty("z", player.getZ()); -+ -+ playersData.add(playerData); -+ -+ } -+ -+ worldData.add("players", playersData); -+ -+ JsonArray chunksData = new JsonArray(); -+ -+ for (ChunkHolder playerChunk : allChunks) { -+ JsonObject chunkData = new JsonObject(); -+ -+ Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.pair()); -+ ChunkStatus status = getChunkStatus(playerChunk); -+ -+ chunkData.addProperty("x", playerChunk.location.x); -+ chunkData.addProperty("z", playerChunk.location.z); -+ chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); -+ chunkData.addProperty("state", ChunkHolder.getFullChunkStatus(playerChunk.getTicketLevel()).toString()); -+ chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.pair())); -+ chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); -+ -+ JsonArray ticketsData = new JsonArray(); -+ -+ if (tickets != null) { -+ for (Ticket ticket : tickets) { -+ JsonObject ticketData = new JsonObject(); -+ -+ ticketData.addProperty("ticket-type", ticket.getType().toString()); -+ ticketData.addProperty("ticket-level", ticket.getTicketLevel()); -+ ticketData.addProperty("object-reason", String.valueOf(ticket.getObjectReason())); -+ ticketData.addProperty("add-tick", ticket.getCreationTick()); -+ -+ ticketsData.add(ticketData); -+ } -+ } -+ -+ chunkData.add("tickets", ticketsData); -+ chunksData.add(chunkData); -+ } -+ -+ -+ worldData.add("chunk-data", chunksData); -+ worldsData.add(worldData); -+ } -+ -+ data.add("worlds", worldsData); -+ -+ StringWriter stringWriter = new StringWriter(); -+ JsonWriter jsonWriter = new JsonWriter(stringWriter); -+ jsonWriter.setIndent(" "); -+ jsonWriter.setLenient(false); -+ Streams.write(data, jsonWriter); -+ -+ String fileData = stringWriter.toString(); -+ -+ try (PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) { -+ out.print(fileData); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 89e90806b78d94d5c1d781113da420dafa47930a..a89b9dab043ad4536014141d5a942670b4152a95 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -53,7 +53,7 @@ public class ChunkHolder { - public int oldTicketLevel; - private int ticketLevel; - private int queueLevel; -- private final ChunkPos pos; -+ final ChunkPos pos; // Paper - private -> package - private boolean hasChangedSections; - private final ShortSet[] changedBlocksPerSection; - private int blockChangedLightSectionFilter; -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 5d87a282042d7112415b7d7175031f734219f2c9..7585b6f87b72f53deccbcb8627a13503921fc682 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -104,7 +104,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); - public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; - private final Long2ObjectLinkedOpenHashMap pendingUnloads; -- private final LongSet entitiesInLevel; -+ public final LongSet entitiesInLevel; // Paper - private -> public - public final ServerLevel level; - private final ThreadedLevelLightEngine lightEngine; - private final BlockableEventLoop mainThreadExecutor; -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index a7122a0411f4a8656efd4facde3403c8093bc8a6..6d33c1ee44bc732b58d18a8f6b0fd4bbdcb2dcd6 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -46,7 +46,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper - - public class ServerChunkCache extends ChunkSource { - -- private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); -+ private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); public static final List getPossibleChunkStatuses() { return ServerChunkCache.CHUNK_STATUSES; } // Paper - OBFHELPER - private final DistanceManager distanceManager; - public final ChunkGenerator generator; - private final ServerLevel level; -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 0c118d482e304c567fe7fe778c6ff386f960bdde..c6b5f32153b63ac92df9c4b31b8de168481f79f2 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -6,8 +6,8 @@ public final class Ticket implements Comparable> { - - private final TicketType type; - private final int ticketLevel; -- public final T key; -- private long createdTick; -+ public final T key; public final T getObjectReason() { return this.key; } // Paper - OBFHELPER -+ private long createdTick; public final long getCreationTick() { return this.createdTick; } // Paper - OBFHELPER - - protected Ticket(TicketType type, int level, T argument) { - this.type = type; -@@ -51,6 +51,7 @@ public final class Ticket implements Comparable> { - return this.type; - } - -+ public final int getTicketLevel() { return this.getTicketLevel(); } // Paper - OBFHELPER - public int getTicketLevel() { - return this.ticketLevel; - } diff --git a/Remapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch b/Remapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch deleted file mode 100644 index 0a15b5e432..0000000000 --- a/Remapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 10 Jun 2019 09:36:40 +0100 -Subject: [PATCH] Catch exceptions from dispenser entity spawns - - -diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -index dccf689d17bb5a77abf97779663413d01e840c23..67a894a185a3d4a53b3c7f90174b2604dff18257 100644 ---- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -@@ -8,6 +8,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.BlockSource; - import net.minecraft.core.Direction; - import net.minecraft.core.Position; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvents; -@@ -235,7 +236,14 @@ public interface DispenseItemBehavior { - } - } - -+ try { // Paper - entitytypes.spawn(pointer.getLevel(), stack, (Player) null, pointer.getPos().relative(enumdirection), MobSpawnType.DISPENSER, enumdirection != Direction.UP, false); -+ // Paper start -+ } catch (Exception ex){ -+ MinecraftServer.LOGGER.warn("An exception occurred dispensing entity at {}[{}]", worldserver.getWorld().getName(), pointer.getPos(), ex); -+ } -+ // Paper end -+ - // itemstack.subtract(1); // Handled during event processing - // CraftBukkit end - return stack; diff --git a/Remapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch b/Remapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch deleted file mode 100644 index 6f00b2b7ac..0000000000 --- a/Remapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch +++ /dev/null @@ -1,390 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 15 Jun 2019 08:54:33 -0700 -Subject: [PATCH] Fix World#isChunkGenerated calls - -Optimize World#loadChunk() too -This patch also adds a chunk status cache on region files (note that -its only purpose is to cache the status on DISK) - -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index a89b9dab043ad4536014141d5a942670b4152a95..7010e0a970462d2b2e1b5696a1a49dba9ea60935 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -141,6 +141,19 @@ public class ChunkHolder { - Either either = (Either) statusFuture.getNow(null); - return either == null ? null : (LevelChunk) either.left().orElse(null); - } -+ -+ public ChunkAccess getAvailableChunkNow() { -+ // TODO can we just getStatusFuture(EMPTY)? -+ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) { -+ CompletableFuture> future = this.getFutureIfPresentUnchecked(curr); -+ Either either = future.getNow(null); -+ if (either == null || !either.left().isPresent()) { -+ continue; -+ } -+ return either.left().get(); -+ } -+ return null; -+ } - // Paper end - - public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 7585b6f87b72f53deccbcb8627a13503921fc682..0aac29de933c84c34cb24e204e8fcc7010060d8f 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -991,12 +991,61 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - @Nullable -- private CompoundTag readChunk(ChunkPos pos) throws IOException { -+ public CompoundTag readChunk(ChunkPos pos) throws IOException { // Paper - private -> public - CompoundTag nbttagcompound = this.read(pos); -+ // Paper start - Cache chunk status on disk -+ if (nbttagcompound == null) { -+ return null; -+ } -+ -+ nbttagcompound = this.getChunkData(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, pos, level); // CraftBukkit -+ if (nbttagcompound == null) { -+ return null; -+ } -+ -+ this.updateChunkStatusOnDisk(pos, nbttagcompound); -+ -+ return nbttagcompound; -+ // Paper end -+ } -+ -+ // Paper start - chunk status cache "api" -+ public ChunkStatus getChunkStatusOnDiskIfCached(ChunkPos chunkPos) { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); -+ -+ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } -+ -+ public ChunkStatus getChunkStatusOnDisk(ChunkPos chunkPos) throws IOException { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); -+ -+ if (regionFile == null || !regionFile.chunkExists(chunkPos)) { -+ return null; -+ } -+ -+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ -+ if (status != null) { -+ return status; -+ } -+ -+ this.readChunk(chunkPos); - -- return nbttagcompound == null ? null : this.getChunkData(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, pos, level); // CraftBukkit -+ return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); - } - -+ public void updateChunkStatusOnDisk(ChunkPos chunkPos, @Nullable CompoundTag compound) throws IOException { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ -+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); -+ } -+ -+ public ChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { -+ ChunkHolder chunkHolder = this.pendingUnloads.get(ChunkPos.asLong(chunkX, chunkZ)); -+ return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow(); -+ } -+ // Paper end -+ - boolean noPlayersCloseForSpawning(ChunkPos chunkcoordintpair) { - // Spigot start - return isOutsideOfRange(chunkcoordintpair, false); -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 6d33c1ee44bc732b58d18a8f6b0fd4bbdcb2dcd6..1e8ac0110badbf2d1c2336168c3e11991667c782 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -52,7 +52,7 @@ public class ServerChunkCache extends ChunkSource { - private final ServerLevel level; - public final Thread mainThread; // Paper - private -> public - private final ThreadedLevelLightEngine lightEngine; -- private final ServerChunkCache.MainThreadExecutor mainThreadProcessor; -+ public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; // Paper private -> public - public final ChunkMap chunkMap; - private final DimensionDataStorage dataStorage; - private long lastInhabitedUpdate; -@@ -317,6 +317,21 @@ public class ServerChunkCache extends ChunkSource { - - return ret; - } -+ -+ @Nullable -+ public ChunkAccess getChunkAtImmediately(int x, int z) { -+ long k = ChunkPos.asLong(x, z); -+ -+ // Note: Bypass cache to make this MT-Safe -+ -+ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(k); -+ if (playerChunk == null) { -+ return null; -+ } -+ -+ return playerChunk.getAvailableChunkNow(); -+ -+ } - // Paper end - - @Nullable -@@ -771,7 +786,7 @@ public class ServerChunkCache extends ChunkSource { - return this.lastSpawnState; - } - -- final class MainThreadExecutor extends BlockableEventLoop { -+ public final class MainThreadExecutor extends BlockableEventLoop { // Paper - package -> public - - private MainThreadExecutor(Level world) { - super("Chunk source main thread executor for " + world.dimension().location()); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -index ae84dc310c076e3212d3cdbca77a1ab06a11d479..46d5a24332c1fd3c164b760ec2a2d5bf859b1ab6 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -@@ -193,6 +193,7 @@ public class ChunkStatus { - return this.name; - } - -+ public ChunkStatus getPreviousStatus() { return this.getParent(); } // Paper - OBFHELPER - public ChunkStatus getParent() { - return this.parent; - } -@@ -213,6 +214,17 @@ public class ChunkStatus { - return this.chunkType; - } - -+ // Paper start -+ public static ChunkStatus getStatus(String name) { -+ try { -+ // We need this otherwise we return EMPTY for invalid names -+ ResourceLocation key = new ResourceLocation(name); -+ return Registry.CHUNK_STATUS.getOptional(key).orElse(null); -+ } catch (Exception ex) { -+ return null; // invalid name -+ } -+ } -+ // Paper end - public static ChunkStatus byName(String id) { - return (ChunkStatus) Registry.CHUNK_STATUS.get(ResourceLocation.tryParse(id)); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 542d6f322df5f44ad9f504c8e14c88e3fa540657..969130442b529eaac6f708107ff129f89cc0af90 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -462,6 +462,17 @@ public class ChunkSerializer { - } - // Paper end - -+ // Paper start -+ public static ChunkStatus getStatus(CompoundTag compound) { -+ if (compound == null) { -+ return null; -+ } -+ -+ // Note: Copied from below -+ return ChunkStatus.getStatus(compound.getCompound("Level").getString("Status")); -+ } -+ // Paper end -+ - public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag tag) { - if (tag != null) { - ChunkStatus chunkstatus = ChunkStatus.byName(tag.getCompound("Level").getString("Status")); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -index 637274532b01bb7b4cdb7d7b1b58181b98ac7e98..9cffef2098fbfba89ddd88a45bde33c07660497a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -@@ -21,7 +21,7 @@ import net.minecraft.world.level.storage.DimensionDataStorage; - - public class ChunkStorage implements AutoCloseable { - -- private final IOWorker worker; -+ private final IOWorker worker; public IOWorker getIOWorker() { return worker; } // Paper - OBFHELPER - protected final DataFixer fixerUpper; - @Nullable - private LegacyStructureDataHandler legacyStructureHandler; -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 424628c9588c02454558bc7e7c5bad3a3e75ec9f..4d96e5ed28c910387c0a4238c9036c7a12458f57 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -27,6 +27,7 @@ import net.minecraft.Util; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.NbtIo; - import net.minecraft.world.level.ChunkPos; -+import net.minecraft.world.level.chunk.ChunkStatus; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -44,6 +45,30 @@ public class RegionFile implements AutoCloseable { - protected final RegionBitmap usedSectors; - public final File file; // Paper - -+ // Paper start - Cache chunk status -+ private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; -+ -+ private boolean closed; -+ -+ // invoked on write/read -+ public void setStatus(int x, int z, ChunkStatus status) { -+ if (this.closed) { -+ // We've used an invalid region file. -+ throw new IllegalStateException("RegionFile is closed"); -+ } -+ this.statuses[getChunkLocation(x, z)] = status; -+ } -+ -+ public ChunkStatus getStatusIfCached(int x, int z) { -+ if (this.closed) { -+ // We've used an invalid region file. -+ throw new IllegalStateException("RegionFile is closed"); -+ } -+ final int location = getChunkLocation(x, z); -+ return this.statuses[location]; -+ } -+ // Paper end -+ - public RegionFile(File file, File directory, boolean dsync) throws IOException { - this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); - } -@@ -380,11 +405,13 @@ public class RegionFile implements AutoCloseable { - return this.getOffset(pos) != 0; - } - -+ private static int getChunkLocation(int x, int z) { return (x & 31) + (z & 31) * 32; } // Paper - OBFHELPER - sort of, mirror of logic below - private static int getOffsetIndex(ChunkPos pos) { - return pos.getRegionLocalX() + pos.getRegionLocalZ() * 32; - } - - public void close() throws IOException { -+ this.closed = true; // Paper - try { - this.padToFullSector(); - } finally { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 6d3e1bb20d1ab8ce5c9ea613322042d80550761a..6f1c96e4325caf6b4762700ad2286d9ea41515c9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -28,7 +28,14 @@ public final class RegionFileStorage implements AutoCloseable { - this.sync = dsync; - } - -- private RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit -+ -+ // Paper start -+ public RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { -+ return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); -+ } -+ -+ // Paper end -+ public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public - long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); - RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); - -@@ -175,6 +182,7 @@ public final class RegionFileStorage implements AutoCloseable { - - try { - NbtIo.write(tag, (DataOutput) dataoutputstream); -+ regionfile.setStatus(pos.x, pos.z, ChunkSerializer.getStatus(tag)); // Paper - cache status on disk - regionfile.setOversized(pos.x, pos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone - } catch (Throwable throwable1) { - throwable = throwable1; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0cb0021fac211996c5bdbb2cfc8f54addc3b49f6..a0615e4ba015cca4fe074de63b87d0bff84b1a14 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -19,6 +19,7 @@ import java.util.Objects; - import java.util.Random; - import java.util.Set; - import java.util.UUID; -+import java.util.concurrent.CompletableFuture; - import java.util.function.Predicate; - import java.util.stream.Collectors; - import net.minecraft.core.BlockPos; -@@ -401,8 +402,22 @@ public class CraftWorld implements World { - - @Override - public boolean isChunkGenerated(int x, int z) { -+ // Paper start - Fix this method -+ if (!Bukkit.isPrimaryThread()) { -+ return CompletableFuture.supplyAsync(() -> { -+ return CraftWorld.this.isChunkGenerated(x, z); -+ }, world.getChunkSource().mainThreadProcessor).join(); -+ } -+ ChunkAccess chunk = world.getChunkSource().getChunkAtImmediately(x, z); -+ if (chunk == null) { -+ chunk = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); -+ } -+ if (chunk != null) { -+ return chunk instanceof ImposterProtoChunk || chunk instanceof net.minecraft.world.level.chunk.LevelChunk; -+ } - try { -- return world.getChunkSource().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; // Paper (TODO check if the first part can be removed) -+ return world.getChunkSource().chunkMap.getChunkStatusOnDisk(new ChunkPos(x, z)) == ChunkStatus.FULL; -+ // Paper end - } catch (IOException ex) { - throw new RuntimeException(ex); - } -@@ -513,20 +528,48 @@ public class CraftWorld implements World { - @Override - public boolean loadChunk(int x, int z, boolean generate) { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -- ChunkAccess chunk = world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper -+ // Paper start - Optimize this method -+ ChunkPos chunkPos = new ChunkPos(x, z); - -- // If generate = false, but the chunk already exists, we will get this back. -- if (chunk instanceof ImposterProtoChunk) { -- // We then cycle through again to get the full chunk immediately, rather than after the ticket addition -- chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); -- } -+ if (!generate) { -+ ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z); -+ if (immediate == null) { -+ immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); -+ } -+ if (immediate != null) { -+ if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) { -+ return false; // not full status -+ } -+ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunk(x, z); // make sure we're at ticket level 32 or lower -+ return true; -+ } - -- if (chunk instanceof net.minecraft.world.level.chunk.LevelChunk) { -- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); -- return true; -+ net.minecraft.world.level.chunk.storage.RegionFile file; -+ try { -+ file = world.getChunkSource().chunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ ChunkStatus status = file.getStatusIfCached(x, z); -+ if (!file.hasChunk(chunkPos) || (status != null && status != ChunkStatus.FULL)) { -+ return false; -+ } -+ -+ ChunkAccess chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.EMPTY, true); -+ if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof net.minecraft.world.level.chunk.LevelChunk)) { -+ return false; -+ } -+ -+ // fall through to load -+ // we do this so we do not re-read the chunk data on disk - } - -- return false; -+ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); -+ return true; -+ // Paper end - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch b/Remapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch deleted file mode 100644 index 873d34715d..0000000000 --- a/Remapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 15 Jun 2019 10:28:25 -0700 -Subject: [PATCH] Show blockstate location if we failed to read it - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 730fda7f0bf02400d349959e9cc2aafaed000b21..66aee7635cd9260d97ae9dd2e9a2a0590fe3c433 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -19,6 +19,8 @@ public class CraftBlockEntityState extends CraftBlockStat - public CraftBlockEntityState(Block block, Class tileEntityClass) { - super(block); - -+ try {// Paper - show location on failure -+ - this.tileEntityClass = tileEntityClass; - - // get tile entity from block: -@@ -38,6 +40,14 @@ public class CraftBlockEntityState extends CraftBlockStat - this.load(this.snapshot); - } - // Paper end -+ // Paper start - show location on failure -+ } catch (Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ throw new RuntimeException("Failed to read BlockState at: world: " + block.getWorld().getName() + " location: (" + block.getX() + ", " + block.getY() + ", " + block.getZ() + ")", thr); -+ } -+ // Paper end - } - - public final boolean snapshotDisabled; // Paper diff --git a/Remapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch b/Remapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch deleted file mode 100644 index 9769725fb1..0000000000 --- a/Remapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 May 2020 20:29:02 -0400 -Subject: [PATCH] Synchronize DataPaletteBlock instead of ReentrantLock - -Mojang has flaws in their logic about chunks being concurrently -wrote to. So we constantly see crashes around multiple threads writing. - -Additionally, java has optimized synchronization so well that its -in many times faster than trying to manage read wrote locks for low -contention situations. - -And this is extremely a low contention situation. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index 6d3dcd19ce1abc9d502903b8008949b5174a13c3..917b0a64083ebbe24321089b784b91f3af4918b9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -8,7 +8,6 @@ import java.util.function.Function; - import java.util.function.Predicate; - import java.util.stream.Collectors; - import net.minecraft.CrashReport; --import net.minecraft.CrashReportCategory; - import net.minecraft.ReportedException; - import net.minecraft.core.IdMapper; - import net.minecraft.nbt.CompoundTag; -@@ -32,23 +31,23 @@ public class PalettedContainer implements PaletteResize { - private int bits; private int getBitsPerObject() { return this.bits; } // Paper - OBFHELPER - private final ReentrantLock lock = new ReentrantLock(); - -- public void acquire() { -- if (this.lock.isLocked() && !this.lock.isHeldByCurrentThread()) { -+ public void acquire() { /* // Paper start - disable this - use proper synchronization -+ if (this.j.isLocked() && !this.j.isHeldByCurrentThread()) { - String s = (String) Thread.getAllStackTraces().keySet().stream().filter(Objects::nonNull).map((thread) -> { - return thread.getName() + ": \n\tat " + (String) Arrays.stream(thread.getStackTrace()).map(Object::toString).collect(Collectors.joining("\n\tat ")); - }).collect(Collectors.joining("\n")); - CrashReport crashreport = new CrashReport("Writing into PalettedContainer from multiple threads", new IllegalStateException()); -- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Thread dumps"); -+ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Thread dumps"); - -- crashreportsystemdetails.setDetail("Thread dumps", (Object) s); -+ crashreportsystemdetails.a("Thread dumps", (Object) s); - throw new ReportedException(crashreport); - } else { -- this.lock.lock(); -- } -+ this.j.lock(); -+ } */ // Paper end - } - - public void release() { -- this.lock.unlock(); -+ //this.j.unlock(); // Paper - disable this - } - - public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { -@@ -84,7 +83,7 @@ public class PalettedContainer implements PaletteResize { - } - - @Override -- public int onResize(int newSize, T objectAdded) { -+ public synchronized int onResize(int newSize, T objectAdded) { // Paper - synchronize - this.acquire(); - BitStorage databits = this.storage; - Palette datapalette = this.palette; -@@ -107,18 +106,18 @@ public class PalettedContainer implements PaletteResize { - } - - public T getAndSet(int x, int y, int z, T value) { -- this.acquire(); -- T t1 = this.getAndSet(getIndex(x, y, z), value); -+ //this.a(); // Paper - remove to reduce ops - synchronize handled below -+ return this.getAndSet(getIndex(x, y, z), value); // Paper - -- this.release(); -- return t1; -+ //this.b(); // Paper -+ //return t1; // PAper - } - - public T getAndSetUnchecked(int x, int y, int z, T value) { - return this.getAndSet(getIndex(x, y, z), value); - } - -- protected T getAndSet(int index, T value) { -+ protected synchronized T getAndSet(int index, T value) { // Paper - synchronize - writes - int j = this.palette.idFor(value); - int k = this.storage.getAndSet(index, j); - T t1 = this.palette.valueFor(k); -@@ -143,7 +142,7 @@ public class PalettedContainer implements PaletteResize { - } - - public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER -- public void write(FriendlyByteBuf buf) { -+ public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize - this.acquire(); - buf.writeByte(this.bits); - this.palette.write(buf); -@@ -151,7 +150,7 @@ public class PalettedContainer implements PaletteResize { - this.release(); - } - -- public void read(ListTag paletteTag, long[] data) { -+ public synchronized void read(ListTag paletteTag, long[] data) { // Paper - synchronize - this.acquire(); - int i = Math.max(4, Mth.ceillog2(paletteTag.size())); - -@@ -184,7 +183,7 @@ public class PalettedContainer implements PaletteResize { - this.release(); - } - -- public void write(CompoundTag nbttagcompound, String s, String s1) { -+ public synchronized void write(CompoundTag nbttagcompound, String s, String s1) { // Paper - synchronize - this.acquire(); - HashMapPalette datapalettehash = new HashMapPalette<>(this.registry, this.bits, this.dummyPaletteResize, this.reader, this.writer); - T t0 = this.defaultValue; diff --git a/Remapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch b/Remapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch deleted file mode 100644 index 1600ad9506..0000000000 --- a/Remapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch +++ /dev/null @@ -1,317 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 9 Jun 2019 03:53:22 +0100 -Subject: [PATCH] incremental chunk saving - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index ffe9b1a63d78925e1d77b9e730aef42fed6d58fa..1278d09f70c1e97607ef20d87a178dc252c7f723 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -446,4 +446,19 @@ public class PaperWorldConfig { - keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); - log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); - } -+ -+ public int autoSavePeriod = -1; -+ private void autoSavePeriod() { -+ autoSavePeriod = getInt("auto-save-interval", -1); -+ if (autoSavePeriod > 0) { -+ log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)"); -+ } else if (autoSavePeriod < 0) { -+ autoSavePeriod = net.minecraft.server.MinecraftServer.getServer().autosavePeriod; -+ } -+ } -+ -+ public int maxAutoSaveChunksPerTick = 24; -+ private void maxAutoSaveChunksPerTick() { -+ maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0efe7024493f96bb54e7d8c1ea7b233a1b481a04..aab1a055c065d1f1a92461e4442ec2cdd8e0b347 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -261,6 +261,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; -+ public boolean serverAutoSave = false; // Paper - public Commands vanillaCommandDispatcher; - private boolean forceTicks; - // CraftBukkit end -@@ -1256,14 +1257,24 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % autosavePeriod == 0) { // CraftBukkit -- MinecraftServer.LOGGER.debug("Autosave started"); -+ //if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down -+ //MinecraftServer.LOGGER.debug("Autosave started"); // Paper -+ serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper - this.profiler.push("save"); -+ if (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0) { // Paper - this.playerList.saveAll(); -- this.saveAllChunks(true, false, false); -+ }// Paper -+ // Paper start -+ for (ServerLevel world : getAllLevels()) { -+ if (world.paperConfig.autoSavePeriod > 0) { -+ world.saveIncrementally(serverAutoSave); -+ } -+ } -+ // Paper end -+ - this.profiler.pop(); -- MinecraftServer.LOGGER.debug("Autosave finished"); -- } -+ //MinecraftServer.LOGGER.debug("Autosave finished"); // Paper -+ //} // Paper - - this.profiler.push("snooper"); - if (((DedicatedServer) this).getProperties().snooperEnabled && !this.snooper.isStarted() && this.tickCount > 100) { // Spigot -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 7010e0a970462d2b2e1b5696a1a49dba9ea60935..491a9e78fdcec8c211499e8f48cceb829f1e5c8b 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -66,6 +66,9 @@ public class ChunkHolder { - - private final ChunkMap chunkMap; // Paper - -+ long lastAutoSaveTime; // Paper - incremental autosave -+ long inactiveTimeStart; // Paper - incremental autosave -+ - public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { - this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); - this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; -@@ -421,7 +424,19 @@ public class ChunkHolder { - boolean flag2 = playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER); - boolean flag3 = playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER); - -+ boolean prevHasBeenLoaded = this.wasAccessibleSinceLastSave; // Paper - this.wasAccessibleSinceLastSave |= flag3; -+ // Paper start - incremental autosave -+ if (this.wasAccessibleSinceLastSave & !prevHasBeenLoaded) { -+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; -+ if (timeSinceAutoSave < 0) { -+ // safest bet is to assume autosave is needed here -+ timeSinceAutoSave = this.chunkMap.level.paperConfig.autoSavePeriod; -+ } -+ this.lastAutoSaveTime = this.chunkMap.level.getGameTime() - timeSinceAutoSave; -+ this.chunkMap.autoSaveQueue.add(this); -+ } -+ // Paper end - if (!flag2 && flag3) { - // Paper start - cache ticking ready status - int expectCreateCount = ++this.fullChunkCreateCount; -@@ -541,8 +556,32 @@ public class ChunkHolder { - } - - public void refreshAccessibility() { -+ boolean prev = this.wasAccessibleSinceLastSave; // Paper -+ this.wasAccessibleSinceLastSave = getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER); -+ // Paper start - incremental autosave -+ if (prev != this.wasAccessibleSinceLastSave) { -+ if (this.wasAccessibleSinceLastSave) { -+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; -+ if (timeSinceAutoSave < 0) { -+ // safest bet is to assume autosave is needed here -+ timeSinceAutoSave = this.chunkMap.level.paperConfig.autoSavePeriod; -+ } -+ this.lastAutoSaveTime = this.chunkMap.level.getGameTime() - timeSinceAutoSave; -+ this.chunkMap.autoSaveQueue.add(this); -+ } else { -+ this.inactiveTimeStart = this.chunkMap.level.getGameTime(); -+ this.chunkMap.autoSaveQueue.remove(this); -+ } -+ } -+ // Paper end -+ } -+ -+ // Paper start - incremental autosave -+ public boolean setHasBeenLoaded() { - this.wasAccessibleSinceLastSave = getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER); -+ return this.wasAccessibleSinceLastSave; - } -+ // Paper end - - public void replaceProtoChunk(ImposterProtoChunk protochunkextension) { - for (int i = 0; i < this.futures.length(); ++i) { -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 0aac29de933c84c34cb24e204e8fcc7010060d8f..cfec04e12dfaeb8852dc129a6a7e68c61dac54b6 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -91,6 +91,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana - import net.minecraft.world.level.storage.DimensionDataStorage; - import net.minecraft.world.level.storage.LevelStorageSource; - import net.minecraft.world.phys.Vec3; -+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper - import org.apache.commons.lang3.mutable.MutableBoolean; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -378,6 +379,64 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - } - -+ // Paper start - incremental autosave -+ final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((playerchunk1, playerchunk2) -> { -+ int timeCompare = Long.compare(playerchunk1.lastAutoSaveTime, playerchunk2.lastAutoSaveTime); -+ if (timeCompare != 0) { -+ return timeCompare; -+ } -+ -+ return Long.compare(MCUtil.getCoordinateKey(playerchunk1.pos), MCUtil.getCoordinateKey(playerchunk2.pos)); -+ }); -+ -+ protected void saveIncrementally() { -+ int savedThisTick = 0; -+ // optimized since we search far less chunks to hit ones that need to be saved -+ List reschedule = new java.util.ArrayList<>(this.level.paperConfig.maxAutoSaveChunksPerTick); -+ long currentTick = this.level.getGameTime(); -+ long maxSaveTime = currentTick - this.level.paperConfig.autoSavePeriod; -+ -+ for (Iterator iterator = this.autoSaveQueue.iterator(); iterator.hasNext();) { -+ ChunkHolder playerchunk = iterator.next(); -+ if (playerchunk.lastAutoSaveTime > maxSaveTime) { -+ break; -+ } -+ -+ iterator.remove(); -+ -+ ChunkAccess ichunkaccess = playerchunk.getChunkToSave().getNow(null); -+ if (ichunkaccess instanceof LevelChunk) { -+ boolean shouldSave = ((LevelChunk)ichunkaccess).lastSaveTime <= maxSaveTime; -+ -+ if (shouldSave && this.save(ichunkaccess)) { -+ ++savedThisTick; -+ -+ if (!playerchunk.setHasBeenLoaded()) { -+ // do not fall through to reschedule logic -+ playerchunk.inactiveTimeStart = currentTick; -+ if (savedThisTick >= this.level.paperConfig.maxAutoSaveChunksPerTick) { -+ break; -+ } -+ continue; -+ } -+ } -+ } -+ -+ reschedule.add(playerchunk); -+ -+ if (savedThisTick >= this.level.paperConfig.maxAutoSaveChunksPerTick) { -+ break; -+ } -+ } -+ -+ for (int i = 0, len = reschedule.size(); i < len; ++i) { -+ ChunkHolder playerchunk = reschedule.get(i); -+ playerchunk.lastAutoSaveTime = this.level.getGameTime(); -+ this.autoSaveQueue.add(playerchunk); -+ } -+ } -+ // Paper end -+ - protected void saveAllChunks(boolean flush) { - if (flush) { - List list = (List) this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); -@@ -488,6 +547,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - this.level.unload(chunk); - } -+ this.autoSaveQueue.remove(playerchunk); // Paper - - this.lightEngine.updateChunkStatus(ichunkaccess.getPos()); - this.lightEngine.tryScheduleUpdate(); -@@ -680,6 +740,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - playerchunk.replaceProtoChunk(new ImposterProtoChunk(chunk)); - } - -+ chunk.setLastSaveTime(this.level.getGameTime() - 1); // Paper - avoid autosaving newly generated/loaded chunks -+ - chunk.setFullStatus(() -> { - return ChunkHolder.getFullChunkStatus(playerchunk.getTicketLevel()); - }); -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 1e8ac0110badbf2d1c2336168c3e11991667c782..c1aa40c01a80a8870478193b8cd7354b0d71045c 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -558,6 +558,15 @@ public class ServerChunkCache extends ChunkSource { - } // Paper - Timings - } - -+ // Paper start - duplicate save, but call incremental -+ public void saveIncrementally() { -+ this.runDistanceManagerUpdates(); -+ try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings -+ this.chunkMap.saveIncrementally(); -+ } // Paper - Timings -+ } -+ // Paper end -+ - @Override - public void close() throws IOException { - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index b2ddf145ae9f581ec6820deb9cb6a98be87658d7..fd7ee4badb383ffb4347d62c00ea2dfa3d76fd12 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -882,6 +882,38 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos); - } - -+ // Paper start - derived from below -+ public void saveIncrementally(boolean doFull) { -+ ServerChunkCache chunkproviderserver = this.getChunkSource(); -+ -+ if (doFull) { -+ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); -+ } -+ -+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { -+ if (doFull) { -+ this.saveData(); -+ } -+ -+ timings.worldSaveChunks.startTiming(); // Paper -+ if (!this.noSave()) chunkproviderserver.saveIncrementally(); -+ timings.worldSaveChunks.stopTiming(); // Paper -+ -+ -+ // Copied from save() -+ // CraftBukkit start - moved from MinecraftServer.saveChunks -+ if (doFull) { // Paper -+ ServerLevel worldserver1 = this; -+ -+ worldDataServer.setWorldBorder(worldserver1.getWorldBorder().createSettings()); -+ worldDataServer.setCustomBossEvents(this.server.getCustomBossEvents().save()); -+ convertable.saveDataTag(this.server.registryHolder, this.worldDataServer, this.server.getPlayerList().getSingleplayerData()); -+ } -+ // CraftBukkit end -+ } -+ } -+ // Paper end -+ - public void save(@Nullable ProgressListener progressListener, boolean flush, boolean flag1) { - ServerChunkCache chunkproviderserver = this.getChunkSource(); - -@@ -912,6 +944,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - // CraftBukkit end - } - -+ private void saveData() { this.saveLevelData(); } // Paper - OBFHELPER - private void saveLevelData() { - if (this.dragonFight != null) { - this.worldDataServer.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 55872a17060a35b727a597bc414fecec3ada3515..419b4bf0549d798d52d73fbbd9de59313fc05eb1 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -80,7 +80,7 @@ public class LevelChunk implements ChunkAccess { - private TickList blockTicks; - private TickList liquidTicks; - private boolean lastSaveHadEntities; -- private long lastSaveTime; -+ public long lastSaveTime; // Paper - private volatile boolean unsaved; - private long inhabitedTime; - @Nullable diff --git a/Remapped-Spigot-Server-Patches/0362-Anti-Xray.patch b/Remapped-Spigot-Server-Patches/0362-Anti-Xray.patch deleted file mode 100644 index 95ed9fdc2a..0000000000 --- a/Remapped-Spigot-Server-Patches/0362-Anti-Xray.patch +++ /dev/null @@ -1,1624 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: stonar96 -Date: Mon, 20 Aug 2018 03:03:58 +0200 -Subject: [PATCH] Anti-Xray - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1278d09f70c1e97607ef20d87a178dc252c7f723..c45493e88bf7e8811be2759ff9ac19e3fe9d938a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -1,7 +1,9 @@ - package com.destroystokyo.paper; - -+import java.util.Arrays; - import java.util.List; - -+import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; - import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; -@@ -461,4 +463,38 @@ public class PaperWorldConfig { - private void maxAutoSaveChunksPerTick() { - maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); - } -+ -+ public boolean antiXray; -+ public EngineMode engineMode; -+ public int maxChunkSectionIndex; -+ public int updateRadius; -+ public boolean lavaObscures; -+ public boolean usePermission; -+ public List hiddenBlocks; -+ public List replacementBlocks; -+ private void antiXray() { -+ antiXray = getBoolean("anti-xray.enabled", false); -+ engineMode = EngineMode.getById(getInt("anti-xray.engine-mode", EngineMode.HIDE.getId())); -+ engineMode = engineMode == null ? EngineMode.HIDE : engineMode; -+ maxChunkSectionIndex = getInt("anti-xray.max-chunk-section-index", 3); -+ maxChunkSectionIndex = maxChunkSectionIndex > 15 ? 15 : maxChunkSectionIndex; -+ updateRadius = getInt("anti-xray.update-radius", 2); -+ lavaObscures = getBoolean("anti-xray.lava-obscures", false); -+ usePermission = getBoolean("anti-xray.use-permission", false); -+ hiddenBlocks = getList("anti-xray.hidden-blocks", Arrays.asList("gold_ore", "iron_ore", "coal_ore", "lapis_ore", "mossy_cobblestone", "obsidian", "chest", "diamond_ore", "redstone_ore", "clay", "emerald_ore", "ender_chest")); -+ replacementBlocks = getList("anti-xray.replacement-blocks", Arrays.asList("stone", "oak_planks")); -+ if (PaperConfig.version < 19) { -+ hiddenBlocks.remove("lit_redstone_ore"); -+ int index = replacementBlocks.indexOf("planks"); -+ if (index != -1) { -+ replacementBlocks.set(index, "oak_planks"); -+ } -+ set("anti-xray.hidden-blocks", hiddenBlocks); -+ set("anti-xray.replacement-blocks", replacementBlocks); -+ } -+ log("Anti-Xray: " + (antiXray ? "enabled" : "disabled") + " / Engine Mode: " + engineMode.getDescription() + " / Up to " + ((maxChunkSectionIndex + 1) * 16) + " blocks / Update Radius: " + updateRadius); -+ if (antiXray && usePermission) { -+ Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8fb63441fbf9afb6f11e1185a9f29528e1950546 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java -@@ -0,0 +1,45 @@ -+package com.destroystokyo.paper.antixray; -+ -+import net.minecraft.core.BlockPos; -+import net.minecraft.core.Direction; -+import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.ServerPlayerGameMode; -+import net.minecraft.world.level.Level; -+import net.minecraft.world.level.block.state.BlockState; -+import net.minecraft.world.level.chunk.ChunkAccess; -+import net.minecraft.world.level.chunk.LevelChunk; -+import net.minecraft.world.level.chunk.LevelChunkSection; -+ -+public class ChunkPacketBlockController { -+ -+ public static final ChunkPacketBlockController NO_OPERATION_INSTANCE = new ChunkPacketBlockController(); -+ -+ protected ChunkPacketBlockController() { -+ -+ } -+ -+ public BlockState[] getPredefinedBlockData(Level world, ChunkAccess chunk, LevelChunkSection chunkSection, boolean initializeBlocks) { -+ return null; -+ } -+ -+ public boolean shouldModify(ServerPlayer entityPlayer, LevelChunk chunk, int chunkSectionSelector) { -+ return false; -+ } -+ -+ public ChunkPacketInfo getChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector) { -+ return null; -+ } -+ -+ public void modifyBlocks(ClientboundLevelChunkPacket packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { -+ packetPlayOutMapChunk.setReady(true); -+ } -+ -+ public void onBlockChange(Level world, BlockPos blockPosition, BlockState newBlockData, BlockState oldBlockData, int flag) { -+ -+ } -+ -+ public void onPlayerLeftClickBlock(ServerPlayerGameMode playerInteractManager, BlockPos blockPosition, Direction enumDirection) { -+ -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6d41628444e880dea5c96ad5caf557f4c56dea46 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java -@@ -0,0 +1,649 @@ -+package com.destroystokyo.paper.antixray; -+ -+import java.util.ArrayList; -+import java.util.LinkedHashSet; -+import java.util.LinkedList; -+import java.util.List; -+import java.util.Set; -+import java.util.concurrent.Executor; -+import java.util.concurrent.ThreadLocalRandom; -+import java.util.function.IntSupplier; -+import net.minecraft.core.BlockPos; -+import net.minecraft.core.Direction; -+import net.minecraft.core.Registry; -+import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; -+import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.ServerPlayerGameMode; -+import net.minecraft.world.level.ChunkPos; -+import net.minecraft.world.level.Level; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.Blocks; -+import net.minecraft.world.level.block.state.BlockState; -+import net.minecraft.world.level.chunk.ChunkAccess; -+import net.minecraft.world.level.chunk.EmptyLevelChunk; -+import net.minecraft.world.level.chunk.LevelChunk; -+import net.minecraft.world.level.chunk.LevelChunkSection; -+import net.minecraft.world.level.chunk.Palette; -+import org.bukkit.Bukkit; -+import org.bukkit.World.Environment; -+ -+import com.destroystokyo.paper.PaperWorldConfig; -+ -+public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockController { -+ -+ private final Executor executor; -+ private final EngineMode engineMode; -+ private final int maxChunkSectionIndex; -+ private final int updateRadius; -+ private final boolean usePermission; -+ private final BlockState[] predefinedBlockData; -+ private final BlockState[] predefinedBlockDataFull; -+ private final BlockState[] predefinedBlockDataStone; -+ private final BlockState[] predefinedBlockDataNetherrack; -+ private final BlockState[] predefinedBlockDataEndStone; -+ private final int[] predefinedBlockDataBitsGlobal; -+ private final int[] predefinedBlockDataBitsStoneGlobal; -+ private final int[] predefinedBlockDataBitsNetherrackGlobal; -+ private final int[] predefinedBlockDataBitsEndStoneGlobal; -+ private final boolean[] solidGlobal = new boolean[Block.BLOCK_STATE_REGISTRY.size()]; -+ private final boolean[] obfuscateGlobal = new boolean[Block.BLOCK_STATE_REGISTRY.size()]; -+ private final LevelChunkSection[] emptyNearbyChunkSections = {LevelChunk.EMPTY_CHUNK_SECTION, LevelChunk.EMPTY_CHUNK_SECTION, LevelChunk.EMPTY_CHUNK_SECTION, LevelChunk.EMPTY_CHUNK_SECTION}; -+ private final int maxBlockYUpdatePosition; -+ -+ public ChunkPacketBlockControllerAntiXray(Level world, Executor executor) { -+ PaperWorldConfig paperWorldConfig = world.paperConfig; -+ engineMode = paperWorldConfig.engineMode; -+ maxChunkSectionIndex = paperWorldConfig.maxChunkSectionIndex; -+ updateRadius = paperWorldConfig.updateRadius; -+ usePermission = paperWorldConfig.usePermission; -+ -+ this.executor = executor; -+ -+ List toObfuscate; -+ -+ if (engineMode == EngineMode.HIDE) { -+ toObfuscate = paperWorldConfig.hiddenBlocks; -+ predefinedBlockData = null; -+ predefinedBlockDataFull = null; -+ predefinedBlockDataStone = new BlockState[] {Blocks.STONE.defaultBlockState()}; -+ predefinedBlockDataNetherrack = new BlockState[] {Blocks.NETHERRACK.defaultBlockState()}; -+ predefinedBlockDataEndStone = new BlockState[] {Blocks.END_STONE.defaultBlockState()}; -+ predefinedBlockDataBitsGlobal = null; -+ predefinedBlockDataBitsStoneGlobal = new int[] {LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(Blocks.STONE.defaultBlockState())}; -+ predefinedBlockDataBitsNetherrackGlobal = new int[] {LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(Blocks.NETHERRACK.defaultBlockState())}; -+ predefinedBlockDataBitsEndStoneGlobal = new int[] {LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(Blocks.END_STONE.defaultBlockState())}; -+ } else { -+ toObfuscate = new ArrayList<>(paperWorldConfig.replacementBlocks); -+ List predefinedBlockDataList = new LinkedList(); -+ -+ for (String id : paperWorldConfig.hiddenBlocks) { -+ Block block = Registry.BLOCK.getOptional(new ResourceLocation(id)).orElse(null); -+ -+ if (block != null && !block.isEntityBlock()) { -+ toObfuscate.add(id); -+ predefinedBlockDataList.add(block.defaultBlockState()); -+ } -+ } -+ -+ // The doc of the LinkedHashSet(Collection c) constructor doesn't specify that the insertion order is the predictable iteration order of the specified Collection, although it is in the implementation -+ Set predefinedBlockDataSet = new LinkedHashSet(); -+ // Therefore addAll(Collection c) is used, which guarantees this order in the doc -+ predefinedBlockDataSet.addAll(predefinedBlockDataList); -+ predefinedBlockData = predefinedBlockDataSet.size() == 0 ? new BlockState[] {Blocks.DIAMOND_ORE.defaultBlockState()} : predefinedBlockDataSet.toArray(new BlockState[0]); -+ predefinedBlockDataFull = predefinedBlockDataSet.size() == 0 ? new BlockState[] {Blocks.DIAMOND_ORE.defaultBlockState()} : predefinedBlockDataList.toArray(new BlockState[0]); -+ predefinedBlockDataStone = null; -+ predefinedBlockDataNetherrack = null; -+ predefinedBlockDataEndStone = null; -+ predefinedBlockDataBitsGlobal = new int[predefinedBlockDataFull.length]; -+ -+ for (int i = 0; i < predefinedBlockDataFull.length; i++) { -+ predefinedBlockDataBitsGlobal[i] = LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(predefinedBlockDataFull[i]); -+ } -+ -+ predefinedBlockDataBitsStoneGlobal = null; -+ predefinedBlockDataBitsNetherrackGlobal = null; -+ predefinedBlockDataBitsEndStoneGlobal = null; -+ } -+ -+ for (String id : toObfuscate) { -+ Block block = Registry.BLOCK.getOptional(new ResourceLocation(id)).orElse(null); -+ -+ // Don't obfuscate air because air causes unnecessary block updates and causes block updates to fail in the void -+ if (block != null && !block.defaultBlockState().isAir()) { -+ // Replace all block states of a specified block -+ // No OBFHELPER for nms.BlockStateList#a() due to too many decompile errors -+ // The OBFHELPER should be getBlockDataList() -+ for (BlockState blockData : block.getStateDefinition().getPossibleStates()) { -+ obfuscateGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(blockData)] = true; -+ } -+ } -+ } -+ -+ EmptyLevelChunk emptyChunk = new EmptyLevelChunk(world, new ChunkPos(0, 0)); -+ BlockPos zeroPos = new BlockPos(0, 0, 0); -+ -+ for (int i = 0; i < solidGlobal.length; i++) { -+ BlockState blockData = LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getObject(i); -+ -+ if (blockData != null) { -+ solidGlobal[i] = blockData.isRedstoneConductor(emptyChunk, zeroPos) -+ && blockData.getBlock() != Blocks.SPAWNER && blockData.getBlock() != Blocks.BARRIER && blockData.getBlock() != Blocks.SHULKER_BOX && blockData.getBlock() != Blocks.SLIME_BLOCK || paperWorldConfig.lavaObscures && blockData == Blocks.LAVA.defaultBlockState(); -+ // Comparing blockData == Blocks.LAVA.getBlockData() instead of blockData.getBlock() == Blocks.LAVA ensures that only "stationary lava" is used -+ // shulker box checks TE. -+ } -+ } -+ -+ this.maxBlockYUpdatePosition = (maxChunkSectionIndex + 1) * 16 + updateRadius - 1; -+ } -+ -+ private int getPredefinedBlockDataFullLength() { -+ return engineMode == EngineMode.HIDE ? 1 : predefinedBlockDataFull.length; -+ } -+ -+ @Override -+ public BlockState[] getPredefinedBlockData(Level world, ChunkAccess chunk, LevelChunkSection chunkSection, boolean initializeBlocks) { -+ // Return the block data which should be added to the data palettes so that they can be used for the obfuscation -+ if (chunkSection.bottomBlockY() >> 4 <= maxChunkSectionIndex) { -+ switch (engineMode) { -+ case HIDE: -+ switch (world.getWorld().getEnvironment()) { -+ case NETHER: -+ return predefinedBlockDataNetherrack; -+ case THE_END: -+ return predefinedBlockDataEndStone; -+ default: -+ return predefinedBlockDataStone; -+ } -+ default: -+ return predefinedBlockData; -+ } -+ } -+ -+ return null; -+ } -+ -+ @Override -+ public boolean shouldModify(ServerPlayer entityPlayer, LevelChunk chunk, int chunkSectionSelector) { -+ return !usePermission || !entityPlayer.getBukkitEntity().hasPermission("paper.antixray.bypass"); -+ } -+ -+ @Override -+ public ChunkPacketInfoAntiXray getChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector) { -+ // Return a new instance to collect data and objects in the right state while creating the chunk packet for thread safe access later -+ // Note: As of 1.14 this has to be moved later due to the chunk system. -+ ChunkPacketInfoAntiXray chunkPacketInfoAntiXray = new ChunkPacketInfoAntiXray(packetPlayOutMapChunk, chunk, chunkSectionSelector, this); -+ return chunkPacketInfoAntiXray; -+ } -+ -+ @Override -+ public void modifyBlocks(ClientboundLevelChunkPacket packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { -+ if (chunkPacketInfo == null) { -+ packetPlayOutMapChunk.setReady(true); -+ return; -+ } -+ -+ if (!Bukkit.isPrimaryThread()) { -+ // plugins? -+ MinecraftServer.getServer().scheduleOnMain(() -> { -+ this.modifyBlocks(packetPlayOutMapChunk, chunkPacketInfo); -+ }); -+ return; -+ } -+ -+ LevelChunk chunk = chunkPacketInfo.getChunk(); -+ int x = chunk.getPos().x; -+ int z = chunk.getPos().z; -+ ServerLevel world = (ServerLevel)chunk.world; -+ ((ChunkPacketInfoAntiXray) chunkPacketInfo).setNearbyChunks( -+ (LevelChunk) world.getChunkIfLoadedImmediately(x - 1, z), -+ (LevelChunk) world.getChunkIfLoadedImmediately(x + 1, z), -+ (LevelChunk) world.getChunkIfLoadedImmediately(x, z - 1), -+ (LevelChunk) world.getChunkIfLoadedImmediately(x, z + 1)); -+ -+ executor.execute((ChunkPacketInfoAntiXray) chunkPacketInfo); -+ } -+ -+ // Actually these fields should be variables inside the obfuscate method but in sync mode or with SingleThreadExecutor in async mode it's okay (even without ThreadLocal) -+ // If an ExecutorService with multiple threads is used, ThreadLocal must be used here -+ private final ThreadLocal predefinedBlockDataBits = ThreadLocal.withInitial(() -> new int[getPredefinedBlockDataFullLength()]); -+ private static final ThreadLocal solid = ThreadLocal.withInitial(() -> new boolean[Block.BLOCK_STATE_REGISTRY.size()]); -+ private static final ThreadLocal obfuscate = ThreadLocal.withInitial(() -> new boolean[Block.BLOCK_STATE_REGISTRY.size()]); -+ // These boolean arrays represent chunk layers, true means don't obfuscate, false means obfuscate -+ private static final ThreadLocal current = ThreadLocal.withInitial(() -> new boolean[16][16]); -+ private static final ThreadLocal next = ThreadLocal.withInitial(() -> new boolean[16][16]); -+ private static final ThreadLocal nextNext = ThreadLocal.withInitial(() -> new boolean[16][16]); -+ -+ public void obfuscate(ChunkPacketInfoAntiXray chunkPacketInfoAntiXray) { -+ int[] predefinedBlockDataBits = this.predefinedBlockDataBits.get(); -+ boolean[] solid = this.solid.get(); -+ boolean[] obfuscate = this.obfuscate.get(); -+ boolean[][] current = this.current.get(); -+ boolean[][] next = this.next.get(); -+ boolean[][] nextNext = this.nextNext.get(); -+ // dataBitsReader, dataBitsWriter and nearbyChunkSections could also be reused (with ThreadLocal if necessary) but it's not worth it -+ DataBitsReader dataBitsReader = new DataBitsReader(); -+ DataBitsWriter dataBitsWriter = new DataBitsWriter(); -+ LevelChunkSection[] nearbyChunkSections = new LevelChunkSection[4]; -+ boolean[] solidTemp = null; -+ boolean[] obfuscateTemp = null; -+ dataBitsReader.setDataBits(chunkPacketInfoAntiXray.getData()); -+ dataBitsWriter.setDataBits(chunkPacketInfoAntiXray.getData()); -+ int numberOfBlocks = predefinedBlockDataBits.length; -+ // Keep the lambda expressions as simple as possible. They are used very frequently. -+ IntSupplier random = numberOfBlocks == 1 ? (() -> 0) : new IntSupplier() { -+ private int state; -+ -+ { -+ while ((state = ThreadLocalRandom.current().nextInt()) == 0); -+ } -+ -+ @Override -+ public int getAsInt() { -+ // https://en.wikipedia.org/wiki/Xorshift -+ state ^= state << 13; -+ state ^= state >>> 17; -+ state ^= state << 5; -+ // https://www.pcg-random.org/posts/bounded-rands.html -+ return (int) ((Integer.toUnsignedLong(state) * numberOfBlocks) >>> 32); -+ } -+ }; -+ -+ for (int chunkSectionIndex = 0; chunkSectionIndex <= maxChunkSectionIndex; chunkSectionIndex++) { -+ if (chunkPacketInfoAntiXray.isWritten(chunkSectionIndex) && chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) != null) { -+ int[] predefinedBlockDataBitsTemp; -+ -+ if (chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex) == LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE) { -+ predefinedBlockDataBitsTemp = engineMode == EngineMode.HIDE ? chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.NETHER ? predefinedBlockDataBitsNetherrackGlobal : chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.THE_END ? predefinedBlockDataBitsEndStoneGlobal : predefinedBlockDataBitsStoneGlobal : predefinedBlockDataBitsGlobal; -+ } else { -+ // If it's this.predefinedBlockData, use this.predefinedBlockDataFull instead -+ BlockState[] predefinedBlockDataFull = chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) == predefinedBlockData ? this.predefinedBlockDataFull : chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex); -+ predefinedBlockDataBitsTemp = predefinedBlockDataBits; -+ -+ for (int i = 0; i < predefinedBlockDataBitsTemp.length; i++) { -+ predefinedBlockDataBitsTemp[i] = chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex).getOrCreateIdFor(predefinedBlockDataFull[i]); -+ } -+ } -+ -+ dataBitsWriter.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); -+ -+ // Check if the chunk section below was not obfuscated -+ if (chunkSectionIndex == 0 || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex - 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex - 1) == null) { -+ // If so, initialize some stuff -+ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); -+ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); -+ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), solid, solidGlobal); -+ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), obfuscate, obfuscateGlobal); -+ // Read the blocks of the upper layer of the chunk section below if it exists -+ LevelChunkSection belowChunkSection = null; -+ boolean skipFirstLayer = chunkSectionIndex == 0 || (belowChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex - 1]) == LevelChunk.EMPTY_CHUNK_SECTION; -+ -+ for (int z = 0; z < 16; z++) { -+ for (int x = 0; x < 16; x++) { -+ current[z][x] = true; -+ next[z][x] = skipFirstLayer || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(belowChunkSection.getBlockState(x, 15, z))]; -+ } -+ } -+ -+ // Abuse the obfuscateLayer method to read the blocks of the first layer of the current chunk section -+ dataBitsWriter.setBitsPerObject(0); -+ obfuscateLayer(-1, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, emptyNearbyChunkSections, random); -+ } -+ -+ dataBitsWriter.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); -+ nearbyChunkSections[0] = chunkPacketInfoAntiXray.getNearbyChunks()[0] == null ? LevelChunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[0].getSections()[chunkSectionIndex]; -+ nearbyChunkSections[1] = chunkPacketInfoAntiXray.getNearbyChunks()[1] == null ? LevelChunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[1].getSections()[chunkSectionIndex]; -+ nearbyChunkSections[2] = chunkPacketInfoAntiXray.getNearbyChunks()[2] == null ? LevelChunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[2].getSections()[chunkSectionIndex]; -+ nearbyChunkSections[3] = chunkPacketInfoAntiXray.getNearbyChunks()[3] == null ? LevelChunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[3].getSections()[chunkSectionIndex]; -+ -+ // Obfuscate all layers of the current chunk section except the upper one -+ for (int y = 0; y < 15; y++) { -+ boolean[][] temp = current; -+ current = next; -+ next = nextNext; -+ nextNext = temp; -+ obfuscateLayer(y, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); -+ } -+ -+ // Check if the chunk section above doesn't need obfuscation -+ if (chunkSectionIndex == maxChunkSectionIndex || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex + 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex + 1) == null) { -+ // If so, obfuscate the upper layer of the current chunk section by reading blocks of the first layer from the chunk section above if it exists -+ LevelChunkSection aboveChunkSection; -+ -+ if (chunkSectionIndex != 15 && (aboveChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex + 1]) != LevelChunk.EMPTY_CHUNK_SECTION) { -+ boolean[][] temp = current; -+ current = next; -+ next = nextNext; -+ nextNext = temp; -+ -+ for (int z = 0; z < 16; z++) { -+ for (int x = 0; x < 16; x++) { -+ if (!solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(aboveChunkSection.getBlockState(x, 0, z))]) { -+ current[z][x] = true; -+ } -+ } -+ } -+ -+ // There is nothing to read anymore -+ dataBitsReader.setBitsPerObject(0); -+ solid[0] = true; -+ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solid, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); -+ } -+ } else { -+ // If not, initialize the reader and other stuff for the chunk section above to obfuscate the upper layer of the current chunk section -+ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex + 1)); -+ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex + 1)); -+ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), solid, solidGlobal); -+ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), obfuscate, obfuscateGlobal); -+ boolean[][] temp = current; -+ current = next; -+ next = nextNext; -+ nextNext = temp; -+ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); -+ } -+ -+ dataBitsWriter.finish(); -+ } -+ } -+ -+ chunkPacketInfoAntiXray.getPacketPlayOutMapChunk().setReady(true); -+ } -+ -+ private void obfuscateLayer(int y, DataBitsReader dataBitsReader, DataBitsWriter dataBitsWriter, boolean[] solid, boolean[] obfuscate, int[] predefinedBlockDataBits, boolean[][] current, boolean[][] next, boolean[][] nextNext, LevelChunkSection[] nearbyChunkSections, IntSupplier random) { -+ // First block of first line -+ int dataBits = dataBitsReader.read(); -+ -+ if (nextNext[0][0] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[0][1] = true; -+ next[1][0] = true; -+ } else { -+ if (nearbyChunkSections[2] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getBlockState(0, y, 15))] || nearbyChunkSections[0] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getBlockState(15, y, 0))] || current[0][0]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[0][0] = true; -+ } -+ -+ // First line -+ for (int x = 1; x < 15; x++) { -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[0][x] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[0][x - 1] = true; -+ next[0][x + 1] = true; -+ next[1][x] = true; -+ } else { -+ if (nearbyChunkSections[2] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getBlockState(x, y, 15))] || current[0][x]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[0][x] = true; -+ } -+ } -+ -+ // Last block of first line -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[0][15] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[0][14] = true; -+ next[1][15] = true; -+ } else { -+ if (nearbyChunkSections[2] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getBlockState(15, y, 15))] || nearbyChunkSections[1] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getBlockState(0, y, 0))] || current[0][15]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[0][15] = true; -+ } -+ -+ // All inner lines -+ for (int z = 1; z < 15; z++) { -+ // First block -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[z][0] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[z][1] = true; -+ next[z - 1][0] = true; -+ next[z + 1][0] = true; -+ } else { -+ if (nearbyChunkSections[0] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getBlockState(15, y, z))] || current[z][0]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[z][0] = true; -+ } -+ -+ // All inner blocks -+ for (int x = 1; x < 15; x++) { -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[z][x] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[z][x - 1] = true; -+ next[z][x + 1] = true; -+ next[z - 1][x] = true; -+ next[z + 1][x] = true; -+ } else { -+ if (current[z][x]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[z][x] = true; -+ } -+ } -+ -+ // Last block -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[z][15] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[z][14] = true; -+ next[z - 1][15] = true; -+ next[z + 1][15] = true; -+ } else { -+ if (nearbyChunkSections[1] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getBlockState(0, y, z))] || current[z][15]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[z][15] = true; -+ } -+ } -+ -+ // First block of last line -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[15][0] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[15][1] = true; -+ next[14][0] = true; -+ } else { -+ if (nearbyChunkSections[3] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getBlockState(0, y, 0))] || nearbyChunkSections[0] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getBlockState(15, y, 15))] || current[15][0]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[15][0] = true; -+ } -+ -+ // Last line -+ for (int x = 1; x < 15; x++) { -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[15][x] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[15][x - 1] = true; -+ next[15][x + 1] = true; -+ next[14][x] = true; -+ } else { -+ if (nearbyChunkSections[3] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getBlockState(x, y, 0))] || current[15][x]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[15][x] = true; -+ } -+ } -+ -+ // Last block of last line -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[15][15] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[15][14] = true; -+ next[14][15] = true; -+ } else { -+ if (nearbyChunkSections[3] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getBlockState(15, y, 0))] || nearbyChunkSections[1] == LevelChunk.EMPTY_CHUNK_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getBlockState(0, y, 15))] || current[15][15]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[15][15] = true; -+ } -+ } -+ -+ private boolean[] readDataPalette(Palette dataPalette, boolean[] temp, boolean[] global) { -+ if (dataPalette == LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE) { -+ return global; -+ } -+ -+ BlockState blockData; -+ -+ for (int i = 0; (blockData = dataPalette.getObject(i)) != null; i++) { -+ temp[i] = global[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(blockData)]; -+ } -+ -+ return temp; -+ } -+ -+ @Override -+ public void onBlockChange(Level world, BlockPos blockPosition, BlockState newBlockData, BlockState oldBlockData, int flag) { -+ if (oldBlockData != null && solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(oldBlockData)] && !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(newBlockData)] && blockPosition.getY() <= maxBlockYUpdatePosition) { -+ updateNearbyBlocks(world, blockPosition); -+ } -+ } -+ -+ @Override -+ public void onPlayerLeftClickBlock(ServerPlayerGameMode playerInteractManager, BlockPos blockPosition, Direction enumDirection) { -+ if (blockPosition.getY() <= maxBlockYUpdatePosition) { -+ updateNearbyBlocks(playerInteractManager.level, blockPosition); -+ } -+ } -+ -+ private void updateNearbyBlocks(Level world, BlockPos blockPosition) { -+ if (updateRadius >= 2) { -+ BlockPos temp = blockPosition.west(); -+ updateBlock(world, temp); -+ updateBlock(world, temp.west()); -+ updateBlock(world, temp.below()); -+ updateBlock(world, temp.above()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.east()); -+ updateBlock(world, temp.east()); -+ updateBlock(world, temp.below()); -+ updateBlock(world, temp.above()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.below()); -+ updateBlock(world, temp.below()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.above()); -+ updateBlock(world, temp.above()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.north()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp = blockPosition.south()); -+ updateBlock(world, temp.south()); -+ } else if (updateRadius == 1) { -+ updateBlock(world, blockPosition.west()); -+ updateBlock(world, blockPosition.east()); -+ updateBlock(world, blockPosition.below()); -+ updateBlock(world, blockPosition.above()); -+ updateBlock(world, blockPosition.north()); -+ updateBlock(world, blockPosition.south()); -+ } else { -+ // Do nothing if updateRadius <= 0 (test mode) -+ } -+ } -+ -+ private void updateBlock(Level world, BlockPos blockPosition) { -+ BlockState blockData = world.getTypeIfLoaded(blockPosition); -+ -+ if (blockData != null && obfuscateGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.getOrCreateIdFor(blockData)]) { -+ // world.notify(blockPosition, blockData, blockData, 3); -+ ((ServerLevel)world).getChunkSource().blockChanged(blockPosition); // We only need to re-send to client -+ } -+ } -+ -+ public enum EngineMode { -+ -+ HIDE(1, "hide ores"), -+ OBFUSCATE(2, "obfuscate"); -+ -+ private final int id; -+ private final String description; -+ -+ EngineMode(int id, String description) { -+ this.id = id; -+ this.description = description; -+ } -+ -+ public static EngineMode getById(int id) { -+ for (EngineMode engineMode : values()) { -+ if (engineMode.id == id) { -+ return engineMode; -+ } -+ } -+ -+ return null; -+ } -+ -+ public int getId() { -+ return id; -+ } -+ -+ public String getDescription() { -+ return description; -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..dc04ffc76e11ab63cd98a84cf95c58dc5cd1efdb ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java -@@ -0,0 +1,81 @@ -+package com.destroystokyo.paper.antixray; -+ -+import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; -+import net.minecraft.world.level.chunk.LevelChunk; -+import net.minecraft.world.level.chunk.Palette; -+ -+public class ChunkPacketInfo { -+ -+ private final ClientboundLevelChunkPacket packetPlayOutMapChunk; -+ private final LevelChunk chunk; -+ private final int chunkSectionSelector; -+ private byte[] data; -+ private final int[] bitsPerObject = new int[16]; -+ private final Object[] dataPalettes = new Object[16]; -+ private final int[] dataBitsIndexes = new int[16]; -+ private final Object[][] predefinedObjects = new Object[16][]; -+ -+ public ChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector) { -+ this.packetPlayOutMapChunk = packetPlayOutMapChunk; -+ this.chunk = chunk; -+ this.chunkSectionSelector = chunkSectionSelector; -+ } -+ -+ public ClientboundLevelChunkPacket getPacketPlayOutMapChunk() { -+ return packetPlayOutMapChunk; -+ } -+ -+ public LevelChunk getChunk() { -+ return chunk; -+ } -+ -+ public int getChunkSectionSelector() { -+ return chunkSectionSelector; -+ } -+ -+ public byte[] getData() { -+ return data; -+ } -+ -+ public void setData(byte[] data) { -+ this.data = data; -+ } -+ -+ public int getBitsPerObject(int chunkSectionIndex) { -+ return bitsPerObject[chunkSectionIndex]; -+ } -+ -+ public void setBitsPerObject(int chunkSectionIndex, int bitsPerObject) { -+ this.bitsPerObject[chunkSectionIndex] = bitsPerObject; -+ } -+ -+ @SuppressWarnings("unchecked") -+ public Palette getDataPalette(int chunkSectionIndex) { -+ return (Palette) dataPalettes[chunkSectionIndex]; -+ } -+ -+ public void setDataPalette(int chunkSectionIndex, Palette dataPalette) { -+ dataPalettes[chunkSectionIndex] = dataPalette; -+ } -+ -+ public int getDataBitsIndex(int chunkSectionIndex) { -+ return dataBitsIndexes[chunkSectionIndex]; -+ } -+ -+ public void setDataBitsIndex(int chunkSectionIndex, int dataBitsIndex) { -+ dataBitsIndexes[chunkSectionIndex] = dataBitsIndex; -+ } -+ -+ @SuppressWarnings("unchecked") -+ public T[] getPredefinedObjects(int chunkSectionIndex) { -+ return (T[]) predefinedObjects[chunkSectionIndex]; -+ } -+ -+ public void setPredefinedObjects(int chunkSectionIndex, T[] predefinedObjects) { -+ this.predefinedObjects[chunkSectionIndex] = predefinedObjects; -+ } -+ -+ public boolean isWritten(int chunkSectionIndex) { -+ return bitsPerObject[chunkSectionIndex] != 0; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7345f1dc7c5c05f2e1ee09b94f4ebf56dd59bc55 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java -@@ -0,0 +1,30 @@ -+package com.destroystokyo.paper.antixray; -+ -+import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; -+import net.minecraft.world.level.block.state.BlockState; -+import net.minecraft.world.level.chunk.LevelChunk; -+ -+public final class ChunkPacketInfoAntiXray extends ChunkPacketInfo implements Runnable { -+ -+ private LevelChunk[] nearbyChunks; -+ private final ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray; -+ -+ public ChunkPacketInfoAntiXray(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector, -+ ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray) { -+ super(packetPlayOutMapChunk, chunk, chunkSectionSelector); -+ this.chunkPacketBlockControllerAntiXray = chunkPacketBlockControllerAntiXray; -+ } -+ -+ public LevelChunk[] getNearbyChunks() { -+ return nearbyChunks; -+ } -+ -+ public void setNearbyChunks(LevelChunk... nearbyChunks) { -+ this.nearbyChunks = nearbyChunks; -+ } -+ -+ @Override -+ public void run() { -+ chunkPacketBlockControllerAntiXray.obfuscate(this); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java -new file mode 100644 -index 0000000000000000000000000000000000000000..298ea423084dbcc1b61f991bcd82b8ae51bf0977 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java -@@ -0,0 +1,51 @@ -+package com.destroystokyo.paper.antixray; -+ -+public final class DataBitsReader { -+ -+ private byte[] dataBits; -+ private int bitsPerObject; -+ private int mask; -+ private int longInDataBitsIndex; -+ private int bitInLongIndex; -+ private long current; -+ -+ public void setDataBits(byte[] dataBits) { -+ this.dataBits = dataBits; -+ } -+ -+ public void setBitsPerObject(int bitsPerObject) { -+ this.bitsPerObject = bitsPerObject; -+ mask = (1 << bitsPerObject) - 1; -+ } -+ -+ public void setIndex(int index) { -+ this.longInDataBitsIndex = index; -+ bitInLongIndex = 0; -+ init(); -+ } -+ -+ private void init() { -+ if (dataBits.length > longInDataBitsIndex + 7) { -+ current = ((((long) dataBits[longInDataBitsIndex]) << 56) -+ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) -+ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) -+ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) -+ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) -+ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) -+ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) -+ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); -+ } -+ } -+ -+ public int read() { -+ if (bitInLongIndex + bitsPerObject > 64) { -+ bitInLongIndex = 0; -+ longInDataBitsIndex += 8; -+ init(); -+ } -+ -+ int value = (int) (current >>> bitInLongIndex) & mask; -+ bitInLongIndex += bitsPerObject; -+ return value; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..333763936897befda5bb6c077944d2667f922799 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java -@@ -0,0 +1,79 @@ -+package com.destroystokyo.paper.antixray; -+ -+public final class DataBitsWriter { -+ -+ private byte[] dataBits; -+ private int bitsPerObject; -+ private long mask; -+ private int longInDataBitsIndex; -+ private int bitInLongIndex; -+ private long current; -+ private boolean dirty; -+ -+ public void setDataBits(byte[] dataBits) { -+ this.dataBits = dataBits; -+ } -+ -+ public void setBitsPerObject(int bitsPerObject) { -+ this.bitsPerObject = bitsPerObject; -+ mask = (1 << bitsPerObject) - 1; -+ } -+ -+ public void setIndex(int index) { -+ this.longInDataBitsIndex = index; -+ bitInLongIndex = 0; -+ init(); -+ } -+ -+ private void init() { -+ if (dataBits.length > longInDataBitsIndex + 7) { -+ current = ((((long) dataBits[longInDataBitsIndex]) << 56) -+ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) -+ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) -+ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) -+ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) -+ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) -+ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) -+ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); -+ } -+ -+ dirty = false; -+ } -+ -+ public void finish() { -+ if (dirty && dataBits.length > longInDataBitsIndex + 7) { -+ dataBits[longInDataBitsIndex] = (byte) (current >> 56 & 0xff); -+ dataBits[longInDataBitsIndex + 1] = (byte) (current >> 48 & 0xff); -+ dataBits[longInDataBitsIndex + 2] = (byte) (current >> 40 & 0xff); -+ dataBits[longInDataBitsIndex + 3] = (byte) (current >> 32 & 0xff); -+ dataBits[longInDataBitsIndex + 4] = (byte) (current >> 24 & 0xff); -+ dataBits[longInDataBitsIndex + 5] = (byte) (current >> 16 & 0xff); -+ dataBits[longInDataBitsIndex + 6] = (byte) (current >> 8 & 0xff); -+ dataBits[longInDataBitsIndex + 7] = (byte) (current & 0xff); -+ } -+ } -+ -+ public void write(int value) { -+ if (bitInLongIndex + bitsPerObject > 64) { -+ finish(); -+ bitInLongIndex = 0; -+ longInDataBitsIndex += 8; -+ init(); -+ } -+ -+ current = current & ~(mask << bitInLongIndex) | (value & mask) << bitInLongIndex; -+ dirty = true; -+ bitInLongIndex += bitsPerObject; -+ } -+ -+ public void skip() { -+ bitInLongIndex += bitsPerObject; -+ -+ if (bitInLongIndex > 64) { -+ finish(); -+ bitInLongIndex = bitsPerObject; -+ longInDataBitsIndex += 8; -+ init(); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -index b587f774c8f88f2a1c3ea489f7e4fe0bbdeb5a41..10dd582b0fff4df27f1113e41c8ee3e274c6fb65 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -@@ -1,5 +1,6 @@ - package net.minecraft.network.protocol.game; - -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import com.google.common.collect.Lists; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.Unpooled; -@@ -16,6 +17,7 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.block.entity.BlockEntity; - import net.minecraft.world.level.block.entity.SkullBlockEntity; -+import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.level.chunk.ChunkBiomeContainer; - import net.minecraft.world.level.chunk.LevelChunk; - import net.minecraft.world.level.chunk.LevelChunkSection; -@@ -33,7 +35,13 @@ public class ClientboundLevelChunkPacket implements Packet blockEntitiesTags; - private boolean fullChunk; - -- public ClientboundLevelChunkPacket() {} -+ // Paper start - Async-Anti-Xray - Set the ready flag to true -+ private volatile boolean ready; // Paper - Async-Anti-Xray - Ready flag for the network manager -+ public ClientboundLevelChunkPacket() { -+ this.ready = true; -+ } -+ // Paper end -+ - // Paper start - private final java.util.List extraPackets = new java.util.ArrayList<>(); - private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); -@@ -43,12 +51,16 @@ public class ClientboundLevelChunkPacket implements Packet chunkPacketInfo = modifyBlocks ? chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i) : null; -+ // Paper end - ChunkPos chunkcoordintpair = chunk.getPos(); - - this.x = chunkcoordintpair.x; - this.z = chunkcoordintpair.z; -- this.fullChunk = includedSectionsMask == 65535; -+ this.fullChunk = i == 65535; - this.heightmaps = new CompoundTag(); - Iterator iterator = chunk.getHeightmaps().iterator(); - -@@ -65,8 +77,13 @@ public class ClientboundLevelChunkPacket implements Packet> 4; - -- if (this.isFullChunk() || (includedSectionsMask & 1 << j) != 0) { -+ if (this.isFullChunk() || (i & 1 << j) != 0) { - // Paper start - improve oversized chunk data packet handling - if (++totalTileEntities > TE_LIMIT) { - ClientboundBlockEntityDataPacket updatePacket = tileentity.getUpdatePacket(); -@@ -93,8 +110,19 @@ public class ClientboundLevelChunkPacket implements Packet chunkPacketInfo) { return this.a(packetDataSerializer, chunk, chunkSectionSelector, chunkPacketInfo); } // OBFHELPER -+ public int a(FriendlyByteBuf packetdataserializer, LevelChunk chunk, int i, ChunkPacketInfo chunkPacketInfo) { -+ // Paper end - int j = 0; - LevelChunkSection[] achunksection = chunk.getSections(); - int k = 0; -@@ -169,9 +201,9 @@ public class ClientboundLevelChunkPacket implements Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { - if (packets[0] == null) { -- packets[0] = new ClientboundLevelChunkPacket(chunk, 65535); -+ packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass - packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, true); - } - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index fd7ee4badb383ffb4347d62c00ea2dfa3d76fd12..7a09bc921827958f58290bd3d6f19984bb34a8f6 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -204,7 +204,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - - // Add env and gen to constructor, WorldData -> WorldDataServer - public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { -- super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env); -+ super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor - this.pvpMode = minecraftserver.isPvpAllowed(); - convertable = convertable_conversionsession; - uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile()); -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index d97607f2ded4977b253d3afa3bafcbe6d7f98837..af048ab682612233c01f7087d7b8afbf7e58945b 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -308,6 +308,8 @@ public class ServerPlayerGameMode { - } - - } -+ -+ this.level.chunkPacketBlockController.onPlayerLeftClickBlock(this, pos, direction); // Paper - Anti-Xray - } - - public void destroyAndAck(BlockPos pos, ServerboundPlayerActionPacket.Action action, String reason) { -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index eb88d830fb45a6b8c990e8bdc1943d80f63c8b93..1377465e3dc062f34be25cac10aa018776fb22e7 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -2,6 +2,8 @@ package net.minecraft.world.level; - - import co.aikar.timings.Timing; - import co.aikar.timings.Timings; -+import com.destroystokyo.paper.antixray.ChunkPacketBlockController; // Paper - Anti-Xray -+import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray; // Paper - Anti-Xray - import com.destroystokyo.paper.event.server.ServerExceptionEvent; - import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.base.MoreObjects; -@@ -144,6 +146,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - - public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper -+ public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray - - public final co.aikar.timings.WorldTimingsHandler timings; // Paper - public static BlockPos lastPhysicsProblem; // Spigot -@@ -165,9 +168,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return typeKey; - } - -- protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { -+ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot - this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper -+ this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray - this.generator = gen; - this.world = new CraftWorld((ServerLevel) this, gen, env); - this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns(); // CraftBukkit -@@ -433,6 +437,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - // CraftBukkit end - - BlockState iblockdata1 = chunk.setType(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag -+ this.chunkPacketBlockController.onBlockChange(this, pos, state, iblockdata1, flags); // Paper - Anti-Xray - - if (iblockdata1 == null) { - // CraftBukkit start - remove blockstate if failed (or the same) -diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java -index e369730ac6909ff5343468bd685c9ea2b6b3cfed..2c19d147710a3bbe2e980114161f1cdf81760947 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java -@@ -8,6 +8,7 @@ import net.minecraft.Util; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Registry; - import net.minecraft.data.worldgen.biome.Biomes; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkHolder; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkPos; -@@ -28,7 +29,7 @@ public class EmptyLevelChunk extends LevelChunk { - }); - - public EmptyLevelChunk(Level world, ChunkPos pos) { -- super(world, pos, new ChunkBiomeContainer(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), EmptyLevelChunk.BIOMES)); -+ super(world, pos, new ChunkBiomeContainer(MinecraftServer.getServer().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), EmptyLevelChunk.BIOMES)); // Paper - world isnt ready yet for anti xray use here, use server singleton for registry - } - - // Paper start -diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -index 17fa8b23d1000ae53f2b4f1a6e8817c1005c1c81..56ab660e29a0dc7d22eeaa41cc8f50e8a96717ef 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -@@ -27,7 +27,7 @@ public class ImposterProtoChunk extends ProtoChunk { - private final LevelChunk wrapped; - - public ImposterProtoChunk(LevelChunk wrapped) { -- super(wrapped.getPos(), UpgradeData.EMPTY); -+ super(wrapped.getPos(), UpgradeData.EMPTY, wrapped.world); // Paper - Anti-Xray - Add parameter - this.wrapped = wrapped; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 419b4bf0549d798d52d73fbbd9de59313fc05eb1..85861545ec4620a6cfd06876dad091637bd29b0b 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -464,7 +464,7 @@ public class LevelChunk implements ChunkAccess { - return null; - } - -- chunksection = new LevelChunkSection(j >> 4 << 4); -+ chunksection = new LevelChunkSection(j >> 4 << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters - this.sections[j >> 4] = chunksection; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index f5db97fb0dac78e1d9aa68d0417aa13f39914f52..38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -1,9 +1,11 @@ - package net.minecraft.world.level.chunk; - - import java.util.function.Predicate; -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import javax.annotation.Nullable; - import net.minecraft.nbt.NbtUtils; - import net.minecraft.network.FriendlyByteBuf; -+import net.minecraft.world.level.Level; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.BlockState; -@@ -18,16 +20,22 @@ public class LevelChunkSection { - private short tickingFluidCount; - final PalettedContainer states; // Paper - package-private - -- public LevelChunkSection(int yOffset) { -- this(yOffset, (short) 0, (short) 0, (short) 0); -+ // Paper start - Anti-Xray - Add parameters -+ @Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public LevelChunkSection(int i, ChunkAccess chunk, Level world, boolean initializeBlocks) { -+ this(i, (short) 0, (short) 0, (short) 0, chunk, world, initializeBlocks); -+ // Paper end - } - -- public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount) { -- this.bottomBlockY = yOffset; -- this.nonEmptyBlockCount = nonEmptyBlockCount; -- this.tickingBlockCount = randomTickableBlockCount; -- this.tickingFluidCount = nonEmptyFluidCount; -- this.states = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); -+ // Paper start - Anti-Xray - Add parameters -+ @Deprecated public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount) { this(yOffset, nonEmptyBlockCount, randomTickableBlockCount, nonEmptyFluidCount, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public LevelChunkSection(int i, short short0, short short1, short short2, ChunkAccess chunk, Level world, boolean initializeBlocks) { -+ // Paper end -+ this.bottomBlockY = i; -+ this.nonEmptyBlockCount = short0; -+ this.tickingBlockCount = short1; -+ this.tickingFluidCount = short2; -+ this.states = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState(), world == null ? null : world.chunkPacketBlockController.getPredefinedBlockData(world, chunk, this, initializeBlocks), initializeBlocks); // Paper - Anti-Xray - Add predefined block data - } - - public final BlockState getBlockState(int x, int y, int z) { // Paper -@@ -139,10 +147,14 @@ public class LevelChunkSection { - return this.states; - } - -- public void writeChunkSection(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER -- public void write(FriendlyByteBuf packetdataserializer) { -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public final void writeChunkSection(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public final void write(FriendlyByteBuf packetdataserializer) { this.writeChunkSection(packetdataserializer, null); } // Notice for updates: Please make sure this method isn't used anywhere -+ public final void writeChunkSection(FriendlyByteBuf packetDataSerializer, ChunkPacketInfo chunkPacketInfo) { this.b(packetDataSerializer, chunkPacketInfo); } // OBFHELPER -+ public void b(FriendlyByteBuf packetdataserializer, ChunkPacketInfo chunkPacketInfo) { -+ // Paper end - packetdataserializer.writeShort(this.nonEmptyBlockCount); -- this.states.write(packetdataserializer); -+ this.states.writeDataPaletteBlock(packetdataserializer, chunkPacketInfo, this.bottomBlockY >> 4); // Paper - Anti-Xray - Add chunk packet info - } - - public int getSerializedSize() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index 917b0a64083ebbe24321089b784b91f3af4918b9..dd252372e1e380674b1191e9ea265cbb10de437b 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -1,6 +1,7 @@ - package net.minecraft.world.level.chunk; - - import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import java.util.Arrays; - import java.util.Objects; - import java.util.concurrent.locks.ReentrantLock; -@@ -26,6 +27,7 @@ public class PalettedContainer implements PaletteResize { - private final Function reader; - private final Function writer; - private final T defaultValue; -+ private final T[] predefinedObjects; // Paper - Anti-Xray - Add predefined objects - protected BitStorage storage; public final BitStorage getDataBits() { return this.storage; } // Paper - OBFHELPER - private Palette palette; private Palette getDataPalette() { return this.palette; } // Paper - OBFHELPER - private int bits; private int getBitsPerObject() { return this.bits; } // Paper - OBFHELPER -@@ -50,14 +52,47 @@ public class PalettedContainer implements PaletteResize { - //this.j.unlock(); // Paper - disable this - } - -- public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { -- this.globalPalette = fallbackPalette; -- this.registry = idList; -- this.reader = elementDeserializer; -- this.writer = elementSerializer; -- this.defaultValue = defaultElement; -- this.setBits(4); -+ // Paper start - Anti-Xray - Add predefined objects -+ @Deprecated public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { this(fallbackPalette, idList, elementDeserializer, elementSerializer, defaultElement, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public PalettedContainer(Palette datapalette, IdMapper registryblockid, Function function, Function function1, T t0, T[] predefinedObjects, boolean initialize) { -+ // Paper end -+ this.globalPalette = datapalette; -+ this.registry = registryblockid; -+ this.reader = function; -+ this.writer = function1; -+ this.defaultValue = t0; -+ // Paper start - Anti-Xray - Add predefined objects -+ this.predefinedObjects = predefinedObjects; -+ -+ if (initialize) { -+ if (predefinedObjects == null) { -+ // Default -+ this.initialize(4); -+ } else { -+ // MathHelper.d() is trailingBits(roundCeilPow2(n)), alternatively; (int)ceil(log2(n)); however it's trash, use numberOfLeadingZeros instead -+ // Count the bits of the maximum array index to initialize a data palette with enough space from the beginning -+ // The length of the array is used because air is also added to the data palette from the beginning -+ // Start with at least 4 -+ int maxIndex = predefinedObjects.length >> 4; -+ int bitCount = (32 - Integer.numberOfLeadingZeros(Math.max(16, maxIndex) - 1)); -+ -+ // Initialize with at least 15 free indixes -+ this.initialize((1 << bitCount) - predefinedObjects.length < 16 ? bitCount + 1 : bitCount); -+ this.addPredefinedObjects(); -+ } -+ } -+ // Paper end -+ } -+ -+ // Paper start - Anti-Xray - Add predefined objects -+ private void addPredefinedObjects() { -+ if (this.predefinedObjects != null && this.getDataPalette() != this.getDataPaletteGlobal()) { -+ for (int i = 0; i < this.predefinedObjects.length; i++) { -+ this.getDataPalette().getOrCreateIdFor(this.predefinedObjects[i]); -+ } -+ } - } -+ // Paper end - - private static int getIndex(int x, int y, int z) { - return y << 8 | z << 4 | x; -@@ -92,6 +127,7 @@ public class PalettedContainer implements PaletteResize { - - int j; - -+ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects - for (j = 0; j < databits.getSize(); ++j) { - T t1 = datapalette.valueFor(databits.get(j)); - -@@ -141,24 +177,38 @@ public class PalettedContainer implements PaletteResize { - return t0 == null ? this.defaultValue : t0; - } - -- public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER -- public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public void write(FriendlyByteBuf buf) { this.writeDataPaletteBlock(buf, null, 0); } // Notice for updates: Please make sure this method isn't used anywhere -+ public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { this.b(packetDataSerializer, chunkPacketInfo, chunkSectionIndex); } // OBFHELPER -+ public synchronized void b(FriendlyByteBuf packetdataserializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { // Paper - synchronize -+ // Paper end - this.acquire(); -- buf.writeByte(this.bits); -- this.palette.write(buf); -- buf.writeLongArray(this.storage.getRaw()); -+ packetdataserializer.writeByte(this.bits); -+ this.palette.write(packetdataserializer); -+ // Paper start - Anti-Xray - Add chunk packet info -+ if (chunkPacketInfo != null) { -+ chunkPacketInfo.setBitsPerObject(chunkSectionIndex, this.getBitsPerObject()); -+ chunkPacketInfo.setDataPalette(chunkSectionIndex, this.getDataPalette()); -+ chunkPacketInfo.setDataBitsIndex(chunkSectionIndex, packetdataserializer.writerIndex() + FriendlyByteBuf.countBytes(this.getDataBits().getDataBits().length)); -+ chunkPacketInfo.setPredefinedObjects(chunkSectionIndex, this.predefinedObjects); -+ } -+ // Paper end -+ packetdataserializer.writeLongArray(this.storage.getRaw()); - this.release(); - } - - public synchronized void read(ListTag paletteTag, long[] data) { // Paper - synchronize - this.acquire(); -- int i = Math.max(4, Mth.ceillog2(paletteTag.size())); -+ // Paper - Anti-Xray - TODO: Should this.predefinedObjects.length just be added here (faster) or should the contents be compared to calculate the size (less RAM)? -+ int i = Math.max(4, Mth.ceillog2(paletteTag.size() + (this.predefinedObjects == null ? 0 : this.predefinedObjects.length))); // Paper - Anti-Xray - Calculate the size with predefined objects - -- if (i != this.bits) { -+ if (true || i != this.bits) { // Paper - Anti-Xray - Not initialized yet - this.setBits(i); - } - - this.palette.read(paletteTag); -+ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects - int j = data.length * 64 / 4096; - - if (this.palette == this.globalPalette) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index d8b7b210484079c9ca2c34831c84102cba6692f5..87fd585141ad9818fca0b697cb4c87248fe7ce11 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -64,16 +64,24 @@ public class ProtoChunk implements ChunkAccess { - private long inhabitedTime; - private final Map carvingMasks; - private volatile boolean isLightCorrect; -+ private final Level world; // Paper - Anti-Xray - Add world - -- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { -- this(pos, upgradeData, (LevelChunkSection[]) null, new ProtoTickList<>((block) -> { -+ // Paper start - Anti-Xray - Add world -+ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { this(pos, upgradeData, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ProtoChunk(ChunkPos chunkcoordintpair, UpgradeData chunkconverter, Level world) { -+ // Paper end -+ this(chunkcoordintpair, chunkconverter, (LevelChunkSection[]) null, new ProtoTickList<>((block) -> { - return block == null || block.defaultBlockState().isAir(); -- }, pos), new ProtoTickList<>((fluidtype) -> { -+ }, chunkcoordintpair), new ProtoTickList<>((fluidtype) -> { - return fluidtype == null || fluidtype == Fluids.EMPTY; -- }, pos)); -+ }, chunkcoordintpair), world); // Paper - Anti-Xray - Add world - } - -- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] sections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler) { -+ // Paper start - Anti-Xray - Add world -+ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] sections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler) { this(pos, upgradeData, sections, blockTickScheduler, fluidTickScheduler, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ProtoChunk(ChunkPos chunkcoordintpair, UpgradeData chunkconverter, @Nullable LevelChunkSection[] achunksection, ProtoTickList protochunkticklist, ProtoTickList protochunkticklist1, Level world) { -+ this.world = world; -+ // Paper end - this.heightmaps = Maps.newEnumMap(Heightmap.Types.class); - this.status = ChunkStatus.EMPTY; - this.blockEntities = Maps.newHashMap(); -@@ -85,15 +93,15 @@ public class ProtoChunk implements ChunkAccess { - this.structureStarts = Maps.newHashMap(); - this.structuresRefences = Maps.newHashMap(); - this.carvingMasks = new Object2ObjectArrayMap(); -- this.chunkPos = pos; -- this.upgradeData = upgradeData; -- this.blockTicks = blockTickScheduler; -- this.liquidTicks = fluidTickScheduler; -- if (sections != null) { -- if (this.sections.length == sections.length) { -- System.arraycopy(sections, 0, this.sections, 0, this.sections.length); -+ this.chunkPos = chunkcoordintpair; -+ this.upgradeData = chunkconverter; -+ this.blockTicks = protochunkticklist; -+ this.liquidTicks = protochunkticklist1; -+ if (achunksection != null) { -+ if (this.sections.length == achunksection.length) { -+ System.arraycopy(achunksection, 0, this.sections, 0, this.sections.length); - } else { -- ProtoChunk.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", sections.length, this.sections.length); -+ ProtoChunk.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", achunksection.length, this.sections.length); - } - } - -@@ -228,7 +236,7 @@ public class ProtoChunk implements ChunkAccess { - - public LevelChunkSection getOrCreateSection(int y) { - if (this.sections[y] == LevelChunk.EMPTY_SECTION) { -- this.sections[y] = new LevelChunkSection(y << 4); -+ this.sections[y] = new LevelChunkSection(y << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters - } - - return this.sections[y]; -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 969130442b529eaac6f708107ff129f89cc0af90..8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -101,7 +101,7 @@ public class ChunkSerializer { - byte b0 = nbttagcompound2.getByte("Y"); - - if (nbttagcompound2.contains("Palette", 9) && nbttagcompound2.contains("BlockStates", 12)) { -- LevelChunkSection chunksection = new LevelChunkSection(b0 << 4); -+ LevelChunkSection chunksection = new LevelChunkSection(b0 << 4, null, world, false); // Paper - Anti-Xray - Add parameters - - chunksection.getStates().read(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); - chunksection.recalcBlockCounts(); -@@ -165,7 +165,7 @@ public class ChunkSerializer { - // CraftBukkit end - }); - } else { -- ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1); -+ ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world); // Paper - Anti-Xray - Add parameter - - protochunk.setBiomes(biomestorage); - object = protochunk; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index 423594177fe78600755d913f169f28dd1bfa2b37..74bad15034d9d55fb70931f38868f812160c6305 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -43,7 +43,7 @@ public class CraftChunk implements Chunk { - private final ServerLevel worldServer; - private final int x; - private final int z; -- private static final PalettedContainer emptyBlockIDs = new LevelChunkSection(0).getStates(); -+ private static final PalettedContainer emptyBlockIDs = new LevelChunkSection(0, null, null, true).getStates(); // Paper - Anti-Xray - Add parameters - private static final byte[] emptyLight = new byte[2048]; - - public CraftChunk(net.minecraft.world.level.chunk.LevelChunk chunk) { -@@ -287,7 +287,7 @@ public class CraftChunk implements Chunk { - CompoundTag data = new CompoundTag(); - cs[i].getStates().write(data, "Palette", "BlockStates"); - -- PalettedContainer blockids = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, net.minecraft.world.level.block.Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); // TODO: snapshot whole ChunkSection -+ PalettedContainer blockids = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, net.minecraft.world.level.block.Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState(), null, false); // TODO: snapshot whole ChunkSection // Paper - Anti-Xray - Add no predefined block data and don't initialize because it's done in the line below internally - blockids.read(data.getList("Palette", CraftMagicNumbers.NBT.TAG_COMPOUND), data.getLongArray("BlockStates")); - - sectionBlockIDs[i] = blockids; -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index a94c65f4d63a06be099fd67b0b7756c5b45b84a0..8d72cd6a44cf462cfe3adac9bf99a16883a587df 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -21,9 +21,11 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - private final int maxHeight; - private final LevelChunkSection[] sections; - private Set tiles; -+ private World world; // Paper - Anti-Xray - Add world - - public CraftChunkData(World world) { - this(world.getMaxHeight()); -+ this.world = world; // Paper - Anti-Xray - Add world - } - - /* pp for tests */ CraftChunkData(int maxHeight) { -@@ -157,7 +159,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - private LevelChunkSection getChunkSection(int y, boolean create) { - LevelChunkSection section = sections[y >> 4]; - if (create && section == null) { -- sections[y >> 4] = section = new LevelChunkSection(y >> 4 << 4); -+ sections[y >> 4] = section = new LevelChunkSection(y >> 4 << 4, null, world instanceof org.bukkit.craftbukkit.CraftWorld ? ((org.bukkit.craftbukkit.CraftWorld) world).getHandle() : null, true); // Paper - Anti-Xray - Add parameters - } - return section; - } diff --git a/Remapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/Remapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch deleted file mode 100644 index 0d019759ff..0000000000 --- a/Remapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 01:01:32 -0400 -Subject: [PATCH] Only count Natural Spawned mobs towards natural spawn mob - limit - -This resolves the super common complaint about mobs not spawning. - -This was ultimately a flaw in the vanilla count algorithim that allows -spawners and other misc mobs to count against the mob limit, which are -not bounded, and can prevent the entire world from spawning new. - -I believe Bukkits changes around persistence may of actually made it -worse than vanilla. - -This should fully solve all of the issues around it so that only natural -influences natural spawns. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c45493e88bf7e8811be2759ff9ac19e3fe9d938a..384cb363eed794551bee6b0ec11ba1be92a3d7ac 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -464,6 +464,16 @@ public class PaperWorldConfig { - maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); - } - -+ public boolean countAllMobsForSpawning = false; -+ private void countAllMobsForSpawning() { -+ countAllMobsForSpawning = getBoolean("count-all-mobs-for-spawning", false); -+ if (countAllMobsForSpawning) { -+ log("Counting all mobs for spawning. Mob farms may reduce natural spawns elsewhere in world."); -+ } else { -+ log("Using improved mob spawn limits (Only Natural Spawns impact spawn limits for more natural spawns)"); -+ } -+ } -+ - public boolean antiXray; - public EngineMode engineMode; - public int maxChunkSectionIndex; -diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index e23875ae07c23fed1161ea070e63bbc3a30168a0..0fb69f9194078e5e05e36ed909eb48424b6465b4 100644 ---- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java -+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -79,6 +79,13 @@ public final class NaturalSpawner { - MobCategory enumcreaturetype = entity.getType().getCategory(); - - if (enumcreaturetype != MobCategory.MISC) { -+ // Paper start - Only count natural spawns -+ if (!entity.level.paperConfig.countAllMobsForSpawning && -+ !(entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL || -+ entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { -+ continue; -+ } -+ // Paper end - BlockPos blockposition = entity.blockPosition(); - long j = ChunkPos.asLong(blockposition.getX() >> 4, blockposition.getZ() >> 4); - diff --git a/Remapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch b/Remapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch deleted file mode 100644 index 111827bdd8..0000000000 --- a/Remapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lucavon -Date: Tue, 23 Jul 2019 20:29:20 -0500 -Subject: [PATCH] Configurable projectile relative velocity - -This patch adds an option "disable relative projectile velocity", which, when -nabled, will cause projectiles to ignore the shooter's current velocity, -like they did in Minecraft 1.8 and prior. -If a player is falling, for example, their shooting range will be drastically -reduced, as a downwards velocity is applied to the projectile. This prevents -players from saving themselves from falling off floating islands, for example, -as a thrown ender pearl will not make it back to the island, while it would -have in 1.8. - -While this could easily be done with plugins, too, there are multiple problems: -P1) If multiple plugins cancel the velocity by subtracting the shooter's velocity -from the projectile's velocity, the projectile's velocity would be different. -As there's no way to detect whether the projectile's velocity has already been -adjusted to ignore the player's velocity, plugins can't not do it if it's not -necessary. -P2) I've noticed some inconsistencies, e.g. weird velocity when shooting while -using an elytra. Checking for those inconsistencies is possible, but not as -efficient as just not applying the velocity in the first place. -P3) Solutions for 1) and especially 2) might not be future-proof, while this -server-internal fix makes this change future-proof. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 384cb363eed794551bee6b0ec11ba1be92a3d7ac..1ee2cced100626e48eb36ee14f84b9257c79a2f8 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -507,4 +507,9 @@ public class PaperWorldConfig { - Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); - } - } -+ -+ public boolean disableRelativeProjectileVelocity; -+ private void disableRelativeProjectileVelocity() { -+ disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index d385fb6eee5000951c350b6ced5669dc3dcce725..ca3d936433cd47caa4e0335e41246b1c4ce0eb99 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -129,7 +129,7 @@ public abstract class Projectile extends Entity { - this.shoot((double) f5, (double) f6, (double) f7, modifierZ, modifierXYZ); - Vec3 vec3d = user.getDeltaMovement(); - -- this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, user.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); -+ if (!user.level.paperConfig.disableRelativeProjectileVelocity) this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, user.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); // Paper - allow disabling relative velocity - } - - // CraftBukkit start - call projectile hit event diff --git a/Remapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch b/Remapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch deleted file mode 100644 index 17630cf486..0000000000 --- a/Remapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 28 Jul 2019 00:51:11 +0100 -Subject: [PATCH] Mark entities as being ticked when notifying navigation - - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 7a09bc921827958f58290bd3d6f19984bb34a8f6..a811ced17721b70bb51837f47e466c2261db2466 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1469,6 +1469,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - VoxelShape voxelshape1 = newState.getCollisionShape(this, pos); - - if (Shapes.joinIsNotEmpty(voxelshape, voxelshape1, BooleanOp.NOT_SAME)) { -+ boolean wasTicking = this.tickingEntities; this.tickingEntities = true; // Paper - Iterator iterator = this.navigations.iterator(); - - while (iterator.hasNext()) { -@@ -1490,6 +1491,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - } - -+ this.tickingEntities = wasTicking; // Paper - } - } - diff --git a/Remapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch b/Remapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch deleted file mode 100644 index 32966f397f..0000000000 --- a/Remapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Tue, 30 Jul 2019 03:17:16 +0500 -Subject: [PATCH] offset item frame ticking - - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java -index e0bf8c6c838b18a0c55b6f3317033e892b631f5c..3277a56bcf3831f8d3c9fa9168c608b369eed7e4 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java -@@ -35,7 +35,7 @@ public abstract class HangingEntity extends Entity { - protected static final Predicate HANGING_ENTITY = (entity) -> { - return entity instanceof HangingEntity; - }; -- private int checkInterval; -+ private int checkInterval; { this.checkInterval = this.getId() % this.level.spigotConfig.hangingTickFrequency; } // Paper - public BlockPos pos; - protected Direction direction; - diff --git a/Remapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch b/Remapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch deleted file mode 100644 index ee50904042..0000000000 --- a/Remapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CullanP -Date: Thu, 3 Mar 2016 02:13:38 -0600 -Subject: [PATCH] Avoid hopper searches if there are no items - -Hoppers searching for items and minecarts is the most expensive part of hopper ticking. -We keep track of the number of minecarts and items in a chunk. -If there are no items in the chunk, we skip searching for items. -If there are no minecarts in the chunk, we skip searching for them. - -Usually hoppers aren't near items, so we can skip most item searches. -And since minecart hoppers are used _very_ rarely near we can avoid alot of searching there. - -Combined, this adds up a lot. - -diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index d3640975c5a33b4911428760691215905b987385..e7facd849e3511c64b4ae44b34382f4a4985f2a4 100644 ---- a/src/main/java/net/minecraft/world/entity/EntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -16,6 +16,7 @@ public final class EntitySelector { - public static final Predicate ENTITY_NOT_BEING_RIDDEN = (entity) -> { - return entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); - }; -+ public static final Predicate isInventory() { return CONTAINER_ENTITY_SELECTOR; } // Paper - OBFHELPER - public static final Predicate CONTAINER_ENTITY_SELECTOR = (entity) -> { - return entity instanceof Container && entity.isAlive(); - }; -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 85861545ec4620a6cfd06876dad091637bd29b0b..4fef3abe4b416cbebe1b456468b5c3e162de18f1 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -31,10 +31,13 @@ import net.minecraft.server.level.ChunkHolder; - import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.Mth; -+import net.minecraft.world.Container; - import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntitySelector; - import net.minecraft.world.entity.EntityType; - import net.minecraft.world.entity.boss.EnderDragonPart; - import net.minecraft.world.entity.boss.enderdragon.EnderDragon; -+import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.ChunkTickList; - import net.minecraft.world.level.EmptyTickList; -@@ -122,6 +125,10 @@ public class LevelChunk implements ChunkAccess { - return removed; - } - } -+ // Track the number of minecarts and items -+ // Keep this synced with entitySlices.add() and entitySlices.remove() -+ private final int[] itemCounts = new int[16]; -+ private final int[] inventoryEntityCounts = new int[16]; - // Paper end - - public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes, UpgradeData upgradeData, TickList blockTickScheduler, TickList fluidTickScheduler, long inhabitedTime, @Nullable LevelChunkSection[] sections, @Nullable Consumer loadToWorldConsumer) { -@@ -581,6 +588,13 @@ public class LevelChunk implements ChunkAccess { - entity.zChunk = this.chunkPos.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ // Paper start -+ if (entity instanceof ItemEntity) { -+ itemCounts[k]++; -+ } else if (entity instanceof Container) { -+ inventoryEntityCounts[k]++; -+ } -+ // Paper end - entity.entitySlice = this.entitySlices[k]; // Paper - this.markUnsaved(); // Paper - } -@@ -614,6 +628,11 @@ public class LevelChunk implements ChunkAccess { - if (!this.entitySlices[section].remove(entity)) { - return; - } -+ if (entity instanceof ItemEntity) { -+ itemCounts[section]--; -+ } else if (entity instanceof Container) { -+ inventoryEntityCounts[section]--; -+ } - entityCounts.decrement(entity.getMinecraftKeyString()); - this.markUnsaved(); // Paper - // Paper end -@@ -899,6 +918,14 @@ public class LevelChunk implements ChunkAccess { - for (int k = i; k <= j; ++k) { - Iterator iterator = this.entitySlices[k].iterator(); // Spigot - -+ // Paper start - Don't search for inventories if we have none, and that is all we want -+ /* -+ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` -+ * -+ * Make sure the inventory selector stays in sync. -+ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -+ */ -+ if (predicate == EntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; - while (iterator.hasNext()) { - T entity = (T) iterator.next(); // CraftBukkit - decompile error - if (entity.shouldBeRemoved) continue; // Paper -@@ -919,9 +946,29 @@ public class LevelChunk implements ChunkAccess { - i = Mth.clamp(i, 0, this.entitySlices.length - 1); - j = Mth.clamp(j, 0, this.entitySlices.length - 1); - -+ // Paper start -+ int[] counts; -+ if (ItemEntity.class.isAssignableFrom(entityClass)) { -+ counts = itemCounts; -+ } else if (Container.class.isAssignableFrom(entityClass)) { -+ counts = inventoryEntityCounts; -+ } else { -+ counts = null; -+ } -+ // Paper end - for (int k = i; k <= j; ++k) { -+ if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for - Iterator iterator = this.entitySlices[k].iterator(); // Spigot - -+ // Paper start - Don't search for inventories if we have none, and that is all we want -+ /* -+ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` -+ * -+ * Make sure the inventory selector stays in sync. -+ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -+ */ -+ if (predicate == EntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; -+ // Paper end - while (iterator.hasNext()) { - T t0 = (T) iterator.next(); // CraftBukkit - decompile error - if (t0.shouldBeRemoved) continue; // Paper diff --git a/Remapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch b/Remapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch deleted file mode 100644 index c4fd709325..0000000000 --- a/Remapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch +++ /dev/null @@ -1,4410 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 13 Jul 2019 09:23:10 -0700 -Subject: [PATCH] Asynchronous chunk IO and loading - -This patch re-adds a file IO thread as well as shoving de-serializing -chunk NBT data onto worker threads. This patch also will shove -chunk data serialization onto the same worker threads when the chunk -is unloaded - this cannot be done for regular saves since that's unsafe. - -The file IO Thread - -Unlike 1.13 and below, the file IO thread is prioritized - IO tasks can -be reoredered, however they are "stuck" to a world & coordinate. - -Scheduling IO tasks works as follows, given a world & coordinate - location: - -The IO thread has been designed to ensure that reads and writes appear to -occur synchronously for a given location, however the implementation also -has the unfortunate side-effect of making every write appear as if -they occur without failure. - -The IO thread has also been designed to accomodate Mojang's decision to -store chunk data and POI data separately. It can independently schedule -tasks for each. - -However threads can wait for writes to complete and check if: - - The write was overwriten by another scheduler - - The write failed (however it does not indicate whether it was overwritten by another scheduler) - -Scheduling reads: - - - If a write task is in progress, the task is not scheduled and returns the in-progress write data - This means that readers cannot modify the NBTTagCompound returned and must clone if it they wish to write - - If a write task is not in progress but a read task is in progress, then the read task is simply chained - This means that again, readers cannot modify the NBTTagCompound returned - -Scheduling writes: - - - If a read task is in progress, ignore the read task and schedule the write - We cannot complete the read task since we assume it wants old data - not current - - If a write task is pending, overwrite the write data - The file IO thread does correctly handle cases where the data is overwritten when it - is writing data (before completing a task it will check if the data was overwritten and - will retry). - -When the file IO thread executes a task for a location, the it will -execute the read task first (if it exists), then it will execute the -write task. This ensures that, even when scheduling at different -priorities, that reads/writes for a location act synchronously. - -The downside of the file IO thread is that write failure can only be -indicated to the scheduling thread if: - -- No other thread decides to schedule another write for the location -concurrently -- The scheduling thread blocks on the write to complete (however the -current implementation can be modified to indicate success -asynchronously) - -The file io thread can be modified easily to provide indications -of write failure and write overwriting if needed. - -The upside of the file IO thread is that if a write failures, then -chunk data is not lost until server restart. This leaves more room -for spurious failure. - -Finally, the io thread will indicate to the console when reads -or writes fail - with relevant detail. - -Asynchronous chunk data serialization for unloading chunks - -When chunks unload they make a call to PlayerChunkMap#saveChunk(IChunkAccess). -Even if I make the IO asynchronous for this call, the data serialization -still hits pretty hard. And given that now the chunk system will -aggressively unload chunks more often (queued immediately at -ticket level 45 or higher), unloads occur more often, and -combined with our changes to the unload queue to make it -significantly more aggresive - chunk unloads can hit pretty hard. -Especially players running around with elytras and fireworks. - -For serializing chunk data off main, there are some tasks which cannot be -done asynchronously. Lighting data must be saved beforehand as well as -potentially some tick lists. These are completed before scheduling the -asynchronous save. - -However serializing chunk data off of the main thread is still risky. -Even though this patch schedules the save to occur after ALL references -of the chunk are removed from the world, plugins can still technically -access entities inside the chunks. For this, if the serialization task -fails for any reason, it will be re-scheduled to be serialized on the -main thread - with the hopes that the reason it failed was due to a plugin -and not an error with the save code itself. Like vanilla code - if the -serialization fails, the chunk data is lost. - -Asynchronous chunk io/loading - -Mojang's current implementation for loading chunk data off disk is -to return a CompletableFuture that will be completed by scheduling a -task to be executed on the world's chunk queue (which is only drained -on the main thread). This task will read the IO off disk and it will -apply data conversions & deserialization synchronously. Obviously -all 3 of these operations are expensive however all can be completed -asynchronously instead. - -The solution this patch uses is as follows: - -0. If an asynchronous chunk save is in progress (see above), wait -for that task to complete. It will use the serialized NBTTagCompound -created by the task. If the task fails to complete, then we would continue -with step 1. If it does not, we skip step 1. (Note: We actually load -POI data no matter what in this case). -1. Schedule an IO task to read chunk & poi data off disk. -2. The IO task will schedule a chunk load task. -3. The chunk load task executes on the async chunk loader threads -and will apply datafixers & de-serialize the chunk into a ProtoChunk -or ProtoChunkExtension. -4. The in progress chunk is then passed on to the world's chunk queue -to complete the ComletableFuture and execute any of the synchronous -tasks required to be executed by the chunk load task (i.e lighting -and some poi tasks). - -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -index 79ede25e4fe7a648b1d29c49d876482a2158f892..24eac9400fbf971742e89bbf47b0ba52b587c4eb 100644 ---- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -59,6 +59,17 @@ public class WorldTimingsHandler { - - public final Timing miscMobSpawning; - -+ public final Timing poiUnload; -+ public final Timing chunkUnload; -+ public final Timing poiSaveDataSerialization; -+ public final Timing chunkSave; -+ public final Timing chunkSaveOverwriteCheck; -+ public final Timing chunkSaveDataSerialization; -+ public final Timing chunkSaveIOWait; -+ public final Timing chunkUnloadPrepareSave; -+ public final Timing chunkUnloadPOISerialization; -+ public final Timing chunkUnloadDataSave; -+ - public WorldTimingsHandler(Level server) { - String name = ((PrimaryLevelData) server.getLevelData()).getLevelName() + " - "; - -@@ -112,6 +123,17 @@ public class WorldTimingsHandler { - - - miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ -+ poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); -+ chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); -+ poiSaveDataSerialization = Timings.ofSafe(name + "Chunk save - POI Data serialization"); -+ chunkSave = Timings.ofSafe(name + "Chunk save - Chunk"); -+ chunkSaveOverwriteCheck = Timings.ofSafe(name + "Chunk save - Chunk Overwrite Check"); -+ chunkSaveDataSerialization = Timings.ofSafe(name + "Chunk save - Chunk Data serialization"); -+ chunkSaveIOWait = Timings.ofSafe(name + "Chunk save - Chunk IO Wait"); -+ chunkUnloadPrepareSave = Timings.ofSafe(name + "Chunk unload - Async Save Prepare"); -+ chunkUnloadPOISerialization = Timings.ofSafe(name + "Chunk unload - POI Data Serialization"); -+ chunkUnloadDataSave = Timings.ofSafe(name + "Chunk unload - Data Serialization"); - } - - public static Timing getTickList(ServerLevel worldserver, String timingsType) { -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 53dd6c18de8e80378852bbb141016d9574d42162..62711d95db62221a2e4e6423c518afe13a6c7dbe 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper; - -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; - import com.google.common.base.Functions; - import com.google.common.base.Joiner; - import com.google.common.collect.ImmutableSet; -@@ -43,7 +44,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); - - public PaperCommand(String name) { - super(name); -@@ -155,6 +156,9 @@ public class PaperCommand extends Command { - case "debug": - doDebug(sender, args); - break; -+ case "dumpwaiting": -+ ChunkTaskManager.dumpAllChunkLoadInfo(); -+ break; - case "chunkinfo": - doChunkInfo(sender, args); - break; -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 469f78775b03cf363d88e35c69c0dc185c22547c..8bf4d2b8c38c02d6a5b2fea37113689a252f1571 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper; - -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; - import com.google.common.base.Strings; - import com.google.common.base.Throwables; - -@@ -352,4 +353,54 @@ public class PaperConfig { - maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); - maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); - } -+ -+ public static boolean asyncChunks = false; -+ private static void asyncChunks() { -+ ConfigurationSection section; -+ if (version < 15) { -+ section = config.createSection("settings.async-chunks"); -+ section.set("threads", -1); -+ } else { -+ section = config.getConfigurationSection("settings.async-chunks"); -+ if (section == null) { -+ section = config.createSection("settings.async-chunks"); -+ } -+ } -+ // Clean up old configs -+ if (section.contains("load-threads")) { -+ if (!section.contains("threads")) { -+ section.set("threads", section.get("load-threads")); -+ } -+ section.set("load-threads", null); -+ } -+ section.set("generation", null); -+ section.set("enabled", null); -+ section.set("thread-per-world-generation", null); -+ -+ int threads = getInt("settings.async-chunks.threads", -1); -+ int cpus = Runtime.getRuntime().availableProcessors(); -+ if (threads <= 0) { -+ threads = (int) Math.min(Integer.getInteger("paper.maxChunkThreads", 8), Math.max(1, cpus - 1)); -+ } -+ if (cpus == 1 && !Boolean.getBoolean("Paper.allowAsyncChunksSingleCore")) { -+ asyncChunks = false; -+ } else { -+ asyncChunks = true; -+ } -+ -+ // Let Shared Host set some limits -+ String sharedHostThreads = System.getenv("PAPER_ASYNC_CHUNKS_SHARED_HOST_THREADS"); -+ if (sharedHostThreads != null) { -+ try { -+ threads = Math.max(1, Math.min(threads, Integer.parseInt(sharedHostThreads))); -+ } catch (NumberFormatException ignored) {} -+ } -+ -+ if (!asyncChunks) { -+ log("Async Chunks: Disabled - Chunks will be managed synchronously, and will cause tremendous lag."); -+ } else { -+ ChunkTaskManager.initGlobalLoadThreads(threads); -+ log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/io/IOUtil.java b/src/main/java/com/destroystokyo/paper/io/IOUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5af0ac3d9e87c06053e65433060f15779c156c2a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/IOUtil.java -@@ -0,0 +1,62 @@ -+package com.destroystokyo.paper.io; -+ -+import org.bukkit.Bukkit; -+ -+public final class IOUtil { -+ -+ /* Copied from concrete or concurrentutil */ -+ -+ public static long getCoordinateKey(final int x, final int z) { -+ return ((long)z << 32) | (x & 0xFFFFFFFFL); -+ } -+ -+ public static int getCoordinateX(final long key) { -+ return (int)key; -+ } -+ -+ public static int getCoordinateZ(final long key) { -+ return (int)(key >>> 32); -+ } -+ -+ public static int getRegionCoordinate(final int chunkCoordinate) { -+ return chunkCoordinate >> 5; -+ } -+ -+ public static int getChunkInRegion(final int chunkCoordinate) { -+ return chunkCoordinate & 31; -+ } -+ -+ public static String genericToString(final Object object) { -+ return object == null ? "null" : object.getClass().getName() + ":" + object.toString(); -+ } -+ -+ public static T notNull(final T obj) { -+ if (obj == null) { -+ throw new NullPointerException(); -+ } -+ return obj; -+ } -+ -+ public static T notNull(final T obj, final String msgIfNull) { -+ if (obj == null) { -+ throw new NullPointerException(msgIfNull); -+ } -+ return obj; -+ } -+ -+ public static void arrayBounds(final int off, final int len, final int arrayLength, final String msgPrefix) { -+ if (off < 0 || len < 0 || (arrayLength - off) < len) { -+ throw new ArrayIndexOutOfBoundsException(msgPrefix + ": off: " + off + ", len: " + len + ", array length: " + arrayLength); -+ } -+ } -+ -+ public static int getPriorityForCurrentThread() { -+ return Bukkit.isPrimaryThread() ? PrioritizedTaskQueue.HIGHEST_PRIORITY : PrioritizedTaskQueue.NORMAL_PRIORITY; -+ } -+ -+ @SuppressWarnings("unchecked") -+ public static void rethrow(final Throwable throwable) throws T { -+ throw (T)throwable; -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a630a84b60b4517e3bc330d4983b914bd064efa4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java -@@ -0,0 +1,606 @@ -+package com.destroystokyo.paper.io; -+ -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.world.level.ChunkPos; -+import net.minecraft.world.level.chunk.storage.RegionFile; -+import org.apache.logging.log4j.Logger; -+ -+import java.io.IOException; -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.atomic.AtomicLong; -+import java.util.function.Consumer; -+import java.util.function.Function; -+ -+/** -+ * Prioritized singleton thread responsible for all chunk IO that occurs in a minecraft server. -+ * -+ *

    -+ * Singleton access: {@link Holder#INSTANCE} -+ *

    -+ * -+ *

    -+ * All functions provided are MT-Safe, however certain ordering constraints are (but not enforced): -+ *

  • -+ * Chunk saves may not occur for unloaded chunks. -+ *
  • -+ *
  • -+ * Tasks must be scheduled on the main thread. -+ *
  • -+ *

    -+ * -+ * @see Holder#INSTANCE -+ * @see #scheduleSave(ServerLevel, int, int, CompoundTag, CompoundTag, int) -+ * @see #loadChunkDataAsync(ServerLevel, int, int, int, Consumer, boolean, boolean, boolean) -+ */ -+public final class PaperFileIOThread extends QueueExecutorThread { -+ -+ public static final Logger LOGGER = MinecraftServer.LOGGER; -+ public static final CompoundTag FAILURE_VALUE = new CompoundTag(); -+ -+ public static final class Holder { -+ -+ public static final PaperFileIOThread INSTANCE = new PaperFileIOThread(); -+ -+ static { -+ INSTANCE.start(); -+ } -+ } -+ -+ private final AtomicLong writeCounter = new AtomicLong(); -+ -+ private PaperFileIOThread() { -+ super(new PrioritizedTaskQueue<>(), (int)(1.0e6)); // 1.0ms spinwait time -+ this.setName("Paper RegionFile IO Thread"); -+ this.setPriority(Thread.NORM_PRIORITY - 1); // we keep priority close to normal because threads can wait on us -+ this.setUncaughtExceptionHandler((final Thread unused, final Throwable thr) -> { -+ LOGGER.fatal("Uncaught exception thrown from IO thread, report this!", thr); -+ }); -+ } -+ -+ /* run() is implemented by superclass */ -+ -+ /* -+ * -+ * IO thread will perform reads before writes -+ * -+ * How reads/writes are scheduled: -+ * -+ * If read in progress while scheduling write, ignore read and schedule write -+ * If read in progress while scheduling read (no write in progress), chain the read task -+ * -+ * -+ * If write in progress while scheduling read, use the pending write data and ret immediately -+ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data -+ * -+ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however -+ * it fails to properly propagate write failures. When writes fail the data is kept so future reads will actually -+ * read the failed write data. This should hopefully act as a way to prevent data loss for spurious fails for writing data. -+ * -+ */ -+ -+ /** -+ * Attempts to bump the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority level to try to bump to -+ */ -+ public void bumpPriority(final ServerLevel world, final int chunkX, final int chunkZ, final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); -+ -+ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); -+ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); -+ -+ if (poiTask != null) { -+ poiTask.raisePriority(priority); -+ } -+ if (chunkTask != null) { -+ chunkTask.raisePriority(priority); -+ } -+ } -+ -+ public CompoundTag getPendingWrite(final ServerLevel world, final int chunkX, final int chunkZ, final boolean poiData) { -+ final ChunkDataController taskController = poiData ? world.poiDataController : world.chunkDataController; -+ -+ final ChunkDataTask dataTask = taskController.tasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); -+ -+ if (dataTask == null) { -+ return null; -+ } -+ -+ final ChunkDataController.InProgressWrite write = dataTask.inProgressWrite; -+ -+ if (write == null) { -+ return null; -+ } -+ -+ return write.data; -+ } -+ -+ /** -+ * Sets the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority level to set to -+ */ -+ public void setPriority(final ServerLevel world, final int chunkX, final int chunkZ, final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); -+ -+ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); -+ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); -+ -+ if (poiTask != null) { -+ poiTask.updatePriority(priority); -+ } -+ if (chunkTask != null) { -+ chunkTask.updatePriority(priority); -+ } -+ } -+ -+ /** -+ * Schedules the chunk data to be written asynchronously. -+ *

    -+ * Impl notes: -+ *

    -+ *
  • -+ * This function presumes a chunk load for the coordinates is not called during this function (anytime after is OK). This means -+ * saves must be scheduled before a chunk is unloaded. -+ *
  • -+ *
  • -+ * Writes may be called concurrently, although only the "later" write will go through. -+ *
  • -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param poiData Chunk point of interest data. If {@code null}, then no poi data is saved. -+ * @param chunkData Chunk data. If {@code null}, then no chunk data is saved. -+ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} -+ * @throws IllegalArgumentException If both {@code poiData} and {@code chunkData} are {@code null}. -+ * @throws IllegalStateException If the file io thread has shutdown. -+ */ -+ public void scheduleSave(final ServerLevel world, final int chunkX, final int chunkZ, -+ final CompoundTag poiData, final CompoundTag chunkData, -+ final int priority) throws IllegalArgumentException { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ final long writeCounter = this.writeCounter.getAndIncrement(); -+ -+ if (poiData != null) { -+ this.scheduleWrite(world.poiDataController, world, chunkX, chunkZ, poiData, priority, writeCounter); -+ } -+ if (chunkData != null) { -+ this.scheduleWrite(world.chunkDataController, world, chunkX, chunkZ, chunkData, priority, writeCounter); -+ } -+ } -+ -+ private void scheduleWrite(final ChunkDataController dataController, final ServerLevel world, -+ final int chunkX, final int chunkZ, final CompoundTag data, final int priority, final long writeCounter) { -+ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask taskRunning) -> { -+ if (taskRunning == null) { -+ // no task is scheduled -+ -+ // create task -+ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); -+ newTask.inProgressWrite = new ChunkDataController.InProgressWrite(); -+ newTask.inProgressWrite.writeCounter = writeCounter; -+ newTask.inProgressWrite.data = data; -+ -+ PaperFileIOThread.this.queueTask(newTask); // schedule -+ return newTask; -+ } -+ -+ taskRunning.raisePriority(priority); -+ -+ if (taskRunning.inProgressWrite == null) { -+ taskRunning.inProgressWrite = new ChunkDataController.InProgressWrite(); -+ } -+ -+ boolean reschedule = taskRunning.inProgressWrite.writeCounter == -1L; -+ -+ // synchronize for readers -+ //noinspection SynchronizationOnLocalVariableOrMethodParameter -+ synchronized (taskRunning) { -+ taskRunning.inProgressWrite.data = data; -+ taskRunning.inProgressWrite.writeCounter = writeCounter; -+ } -+ -+ if (reschedule) { -+ // We need to reschedule this task since the previous one is not currently scheduled since it failed -+ taskRunning.reschedule(priority); -+ } -+ -+ return taskRunning; -+ }); -+ } -+ -+ /** -+ * Same as {@link #loadChunkDataAsync(ServerLevel, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns -+ * a {@link CompletableFuture} which is potentially completed ASYNCHRONOUSLY ON THE FILE IO THREAD when the load task -+ * has completed. -+ *

    -+ * Note that if the chunk fails to load the returned future is completed with {@code null}. -+ *

    -+ */ -+ public CompletableFuture loadChunkDataAsyncFuture(final ServerLevel world, final int chunkX, final int chunkZ, -+ final int priority, final boolean readPoiData, final boolean readChunkData, -+ final boolean intendingToBlock) { -+ final CompletableFuture future = new CompletableFuture<>(); -+ this.loadChunkDataAsync(world, chunkX, chunkZ, priority, future::complete, readPoiData, readChunkData, intendingToBlock); -+ return future; -+ } -+ -+ /** -+ * Schedules a load to be executed asynchronously. -+ *

    -+ * Impl notes: -+ *

    -+ *
  • -+ * If a chunk fails to load, the {@code onComplete} parameter is completed with {@code null}. -+ *
  • -+ *
  • -+ * It is possible for the {@code onComplete} parameter to be given {@link ChunkData} containing data -+ * this call did not request. -+ *
  • -+ *
  • -+ * The {@code onComplete} parameter may be completed during the execution of this function synchronously or it may -+ * be completed asynchronously on this file io thread. Interacting with the file IO thread in the completion of -+ * data is undefined behaviour, and can cause deadlock. -+ *
  • -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} -+ * @param onComplete Consumer to execute once this task has completed -+ * @param readPoiData Whether to read point of interest data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. -+ * @param readChunkData Whether to read chunk data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. -+ * @return The {@link PrioritizedTaskQueue.PrioritizedTask} associated with this task. Note that this task does not support -+ * cancellation. -+ */ -+ public void loadChunkDataAsync(final ServerLevel world, final int chunkX, final int chunkZ, -+ final int priority, final Consumer onComplete, -+ final boolean readPoiData, final boolean readChunkData, -+ final boolean intendingToBlock) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ if (!(readPoiData | readChunkData)) { -+ throw new IllegalArgumentException("Must read chunk data or poi data"); -+ } -+ -+ final ChunkData complete = new ChunkData(); -+ final boolean[] requireCompletion = new boolean[] { readPoiData, readChunkData }; -+ -+ if (readPoiData) { -+ this.scheduleRead(world.poiDataController, world, chunkX, chunkZ, (final CompoundTag poiData) -> { -+ complete.poiData = poiData; -+ -+ final boolean finished; -+ -+ // avoid a race condition where the file io thread completes and we complete synchronously -+ // Note: Synchronization can be elided if both of the accesses are volatile -+ synchronized (requireCompletion) { -+ requireCompletion[0] = false; // 0 -> poi data -+ finished = !requireCompletion[1]; // 1 -> chunk data -+ } -+ -+ if (finished) { -+ onComplete.accept(complete); -+ } -+ }, priority, intendingToBlock); -+ } -+ -+ if (readChunkData) { -+ this.scheduleRead(world.chunkDataController, world, chunkX, chunkZ, (final CompoundTag chunkData) -> { -+ complete.chunkData = chunkData; -+ -+ final boolean finished; -+ -+ // avoid a race condition where the file io thread completes and we complete synchronously -+ // Note: Synchronization can be elided if both of the accesses are volatile -+ synchronized (requireCompletion) { -+ requireCompletion[1] = false; // 1 -> chunk data -+ finished = !requireCompletion[0]; // 0 -> poi data -+ } -+ -+ if (finished) { -+ onComplete.accept(complete); -+ } -+ }, priority, intendingToBlock); -+ } -+ -+ } -+ -+ // Note: the onComplete may be called asynchronously or synchronously here. -+ private void scheduleRead(final ChunkDataController dataController, final ServerLevel world, -+ final int chunkX, final int chunkZ, final Consumer onComplete, final int priority, -+ final boolean intendingToBlock) { -+ -+ Function tryLoadFunction = (final RegionFile file) -> { -+ if (file == null) { -+ return Boolean.TRUE; -+ } -+ return Boolean.valueOf(file.hasChunk(new ChunkPos(chunkX, chunkZ))); -+ }; -+ -+ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask running) -> { -+ if (running == null) { -+ // not scheduled -+ -+ final Boolean shouldSchedule = intendingToBlock ? dataController.computeForRegionFile(chunkX, chunkZ, tryLoadFunction) : -+ dataController.computeForRegionFileIfLoaded(chunkX, chunkZ, tryLoadFunction); -+ -+ if (shouldSchedule == Boolean.FALSE) { -+ // not on disk -+ onComplete.accept(null); -+ return null; -+ } -+ -+ // set up task -+ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); -+ newTask.inProgressRead = new ChunkDataController.InProgressRead(); -+ newTask.inProgressRead.readFuture.thenAccept(onComplete); -+ -+ PaperFileIOThread.this.queueTask(newTask); // schedule task -+ return newTask; -+ } -+ -+ running.raisePriority(priority); -+ -+ if (running.inProgressWrite == null) { -+ // chain to the read future -+ running.inProgressRead.readFuture.thenAccept(onComplete); -+ return running; -+ } -+ -+ // at this stage we have to use the in progress write's data to avoid an order issue -+ // we don't synchronize since all writes to data occur in the compute() call -+ onComplete.accept(running.inProgressWrite.data); -+ return running; -+ }); -+ } -+ -+ /** -+ * Same as {@link #loadChunkDataAsync(ServerLevel, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns -+ * the {@link ChunkData} associated with the specified chunk when the task is complete. -+ * @return The chunk data, or {@code null} if the chunk failed to load. -+ */ -+ public ChunkData loadChunkData(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, -+ final boolean readPoiData, final boolean readChunkData) { -+ return this.loadChunkDataAsyncFuture(world, chunkX, chunkZ, priority, readPoiData, readChunkData, true).join(); -+ } -+ -+ /** -+ * Schedules the given task at the specified priority to be executed on the IO thread. -+ *

    -+ * Internal api. Do not use. -+ *

    -+ */ -+ public void runTask(final int priority, final Runnable runnable) { -+ this.queueTask(new GeneralTask(priority, runnable)); -+ } -+ -+ static final class GeneralTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { -+ -+ private final Runnable run; -+ -+ public GeneralTask(final int priority, final Runnable run) { -+ super(priority); -+ this.run = IOUtil.notNull(run, "Task may not be null"); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ this.run.run(); -+ } catch (final Throwable throwable) { -+ if (throwable instanceof ThreadDeath) { -+ throw (ThreadDeath)throwable; -+ } -+ LOGGER.fatal("Failed to execute general task on IO thread " + IOUtil.genericToString(this.run), throwable); -+ } -+ } -+ } -+ -+ public static final class ChunkData { -+ -+ public CompoundTag poiData; -+ public CompoundTag chunkData; -+ -+ public ChunkData() {} -+ -+ public ChunkData(final CompoundTag poiData, final CompoundTag chunkData) { -+ this.poiData = poiData; -+ this.chunkData = chunkData; -+ } -+ } -+ -+ public static abstract class ChunkDataController { -+ -+ // ConcurrentHashMap synchronizes per chain, so reduce the chance of task's hashes colliding. -+ public final ConcurrentHashMap tasks = new ConcurrentHashMap<>(64, 0.5f); -+ -+ public abstract void writeData(final int x, final int z, final CompoundTag compound) throws IOException; -+ public abstract CompoundTag readData(final int x, final int z) throws IOException; -+ -+ public abstract T computeForRegionFile(final int chunkX, final int chunkZ, final Function function); -+ public abstract T computeForRegionFileIfLoaded(final int chunkX, final int chunkZ, final Function function); -+ -+ public static final class InProgressWrite { -+ public long writeCounter; -+ public CompoundTag data; -+ } -+ -+ public static final class InProgressRead { -+ public final CompletableFuture readFuture = new CompletableFuture<>(); -+ } -+ } -+ -+ public static final class ChunkDataTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { -+ -+ public ChunkDataController.InProgressWrite inProgressWrite; -+ public ChunkDataController.InProgressRead inProgressRead; -+ -+ private final ServerLevel world; -+ private final int x; -+ private final int z; -+ private final ChunkDataController taskController; -+ -+ public ChunkDataTask(final int priority, final ServerLevel world, final int x, final int z, final ChunkDataController taskController) { -+ super(priority); -+ this.world = world; -+ this.x = x; -+ this.z = z; -+ this.taskController = taskController; -+ } -+ -+ @Override -+ public String toString() { -+ return "Task for world: '" + this.world.getWorld().getName() + "' at " + this.x + "," + this.z + -+ " poi: " + (this.taskController == this.world.poiDataController) + ", hash: " + this.hashCode(); -+ } -+ -+ /* -+ * -+ * IO thread will perform reads before writes -+ * -+ * How reads/writes are scheduled: -+ * -+ * If read in progress while scheduling write, ignore read and schedule write -+ * If read in progress while scheduling read (no write in progress), chain the read task -+ * -+ * -+ * If write in progress while scheduling read, use the pending write data and ret immediately -+ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data -+ * -+ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however -+ * it fails to properly propagate write failures -+ * -+ */ -+ -+ void reschedule(final int priority) { -+ // priority is checked before this stage // TODO what -+ this.queue.lazySet(null); -+ this.priority.lazySet(priority); -+ PaperFileIOThread.Holder.INSTANCE.queueTask(this); -+ } -+ -+ @Override -+ public void run() { -+ ChunkDataController.InProgressRead read = this.inProgressRead; -+ if (read != null) { -+ CompoundTag compound = PaperFileIOThread.FAILURE_VALUE; -+ try { -+ compound = this.taskController.readData(this.x, this.z); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ LOGGER.fatal("Failed to read chunk data for task: " + this.toString(), thr); -+ // fall through to complete with null data -+ } -+ read.readFuture.complete(compound); -+ } -+ -+ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(this.x, this.z)); -+ -+ ChunkDataController.InProgressWrite write = this.inProgressWrite; -+ -+ if (write == null) { -+ // IntelliJ warns this is invalid, however it does not consider that writes to the task map & the inProgress field can occur concurrently. -+ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { -+ if (valueInMap == null) { -+ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); -+ } -+ if (valueInMap != ChunkDataTask.this) { -+ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); -+ } -+ return valueInMap.inProgressWrite == null ? null : valueInMap; -+ }); -+ -+ if (inMap == null) { -+ return; // set the task value to null, indicating we're done -+ } -+ -+ // not null, which means there was a concurrent write -+ write = this.inProgressWrite; -+ } -+ -+ // check if another process is writing -+ /*try { TODO: Can we restore this? -+ ((WorldServer)this.world).checkSession(); -+ } catch (final Exception ex) { -+ LOGGER.fatal("Couldn't save chunk; already in use by another instance of Minecraft?", ex); -+ // we don't need to set the write counter to -1 as we know at this stage there's no point in re-scheduling -+ // writes since they'll fail anyways. -+ return; -+ } -+*/ -+ for (;;) { -+ final long writeCounter; -+ final CompoundTag data; -+ -+ //noinspection SynchronizationOnLocalVariableOrMethodParameter -+ synchronized (write) { -+ writeCounter = write.writeCounter; -+ data = write.data; -+ } -+ -+ boolean failedWrite = false; -+ -+ try { -+ this.taskController.writeData(this.x, this.z, data); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ LOGGER.fatal("Failed to write chunk data for task: " + this.toString(), thr); -+ failedWrite = true; -+ } -+ -+ boolean finalFailWrite = failedWrite; -+ -+ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { -+ if (valueInMap == null) { -+ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); -+ } -+ if (valueInMap != ChunkDataTask.this) { -+ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); -+ } -+ if (valueInMap.inProgressWrite.writeCounter == writeCounter) { -+ if (finalFailWrite) { -+ valueInMap.inProgressWrite.writeCounter = -1L; -+ } -+ -+ return null; -+ } -+ return valueInMap; -+ // Hack end -+ }); -+ -+ if (inMap == null) { -+ // write counter matched, so we wrote the most up-to-date pending data, we're done here -+ // or we failed to write and successfully set the write counter to -1 -+ return; // we're done here -+ } -+ -+ // fetch & write new data -+ continue; -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java -new file mode 100644 -index 0000000000000000000000000000000000000000..97f2e433c483f1ebd7500ae142269e144ef5fda4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java -@@ -0,0 +1,277 @@ -+package com.destroystokyo.paper.io; -+ -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.concurrent.atomic.AtomicInteger; -+import java.util.concurrent.atomic.AtomicReference; -+ -+public class PrioritizedTaskQueue { -+ -+ // lower numbers are a higher priority (except < 0) -+ // higher priorities are always executed before lower priorities -+ -+ /** -+ * Priority value indicating the task has completed or is being completed. -+ */ -+ public static final int COMPLETING_PRIORITY = -1; -+ -+ /** -+ * Highest priority, should only be used for main thread tasks or tasks that are blocking the main thread. -+ */ -+ public static final int HIGHEST_PRIORITY = 0; -+ -+ /** -+ * Should be only used in an IO task so that chunk loads do not wait on other IO tasks. -+ * This only exists because IO tasks are scheduled before chunk load tasks to decrease IO waiting times. -+ */ -+ public static final int HIGHER_PRIORITY = 1; -+ -+ /** -+ * Should be used for scheduling chunk loads/generation that would increase response times to users. -+ */ -+ public static final int HIGH_PRIORITY = 2; -+ -+ /** -+ * Default priority. -+ */ -+ public static final int NORMAL_PRIORITY = 3; -+ -+ /** -+ * Use for tasks not at all critical and can potentially be delayed. -+ */ -+ public static final int LOW_PRIORITY = 4; -+ -+ /** -+ * Use for tasks that should "eventually" execute. -+ */ -+ public static final int LOWEST_PRIORITY = 5; -+ -+ private static final int TOTAL_PRIORITIES = 6; -+ -+ final ConcurrentLinkedQueue[] queues = (ConcurrentLinkedQueue[])new ConcurrentLinkedQueue[TOTAL_PRIORITIES]; -+ -+ private final AtomicBoolean shutdown = new AtomicBoolean(); -+ -+ { -+ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { -+ this.queues[i] = new ConcurrentLinkedQueue<>(); -+ } -+ } -+ -+ /** -+ * Returns whether the specified priority is valid -+ */ -+ public static boolean validPriority(final int priority) { -+ return priority >= 0 && priority < TOTAL_PRIORITIES; -+ } -+ -+ /** -+ * Queues a task. -+ * @throws IllegalStateException If the task has already been queued. Use {@link PrioritizedTask#raisePriority(int)} to -+ * raise a task's priority. -+ * This can also be thrown if the queue has shutdown. -+ */ -+ public void add(final T task) throws IllegalStateException { -+ int priority = task.getPriority(); -+ if (priority != COMPLETING_PRIORITY) { -+ task.setQueue(this); -+ this.queues[priority].add(task); -+ } -+ if (this.shutdown.get()) { -+ // note: we're not actually sure at this point if our task will go through -+ throw new IllegalStateException("Queue has shutdown, refusing to execute task " + IOUtil.genericToString(task)); -+ } -+ } -+ -+ /** -+ * Polls the highest priority task currently available. {@code null} if none. -+ */ -+ public T poll() { -+ T task; -+ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { -+ final ConcurrentLinkedQueue queue = this.queues[i]; -+ -+ while ((task = queue.poll()) != null) { -+ final int prevPriority = task.tryComplete(i); -+ if (prevPriority != COMPLETING_PRIORITY && prevPriority <= i) { -+ // if the prev priority was greater-than or equal to our current priority -+ return task; -+ } -+ } -+ } -+ -+ return null; -+ } -+ -+ /** -+ * Returns whether this queue may have tasks queued. -+ *

    -+ * This operation is not atomic, but is MT-Safe. -+ *

    -+ * @return {@code true} if tasks may be queued, {@code false} otherwise -+ */ -+ public boolean hasTasks() { -+ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { -+ final ConcurrentLinkedQueue queue = this.queues[i]; -+ -+ if (queue.peek() != null) { -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ /** -+ * Prevent further additions to this queue. Attempts to add after this call has completed (potentially during) will -+ * result in {@link IllegalStateException} being thrown. -+ *

    -+ * This operation is atomic with respect to other shutdown calls -+ *

    -+ *

    -+ * After this call has completed, regardless of return value, this queue will be shutdown. -+ *

    -+ * @return {@code true} if the queue was shutdown, {@code false} if it has shut down already -+ */ -+ public boolean shutdown() { -+ return this.shutdown.getAndSet(false); -+ } -+ -+ public abstract static class PrioritizedTask { -+ -+ protected final AtomicReference queue = new AtomicReference<>(); -+ -+ protected final AtomicInteger priority; -+ -+ protected PrioritizedTask() { -+ this(PrioritizedTaskQueue.NORMAL_PRIORITY); -+ } -+ -+ protected PrioritizedTask(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority " + priority); -+ } -+ this.priority = new AtomicInteger(priority); -+ } -+ -+ /** -+ * Returns the current priority. Note that {@link PrioritizedTaskQueue#COMPLETING_PRIORITY} will be returned -+ * if this task is completing or has completed. -+ */ -+ public final int getPriority() { -+ return this.priority.get(); -+ } -+ -+ /** -+ * Returns whether this task is scheduled to execute, or has been already executed. -+ */ -+ public boolean isScheduled() { -+ return this.queue.get() != null; -+ } -+ -+ final int tryComplete(final int minPriority) { -+ for (int curr = this.getPriorityVolatile();;) { -+ if (curr == COMPLETING_PRIORITY) { -+ return COMPLETING_PRIORITY; -+ } -+ if (curr > minPriority) { -+ // curr is lower priority -+ return curr; -+ } -+ -+ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, COMPLETING_PRIORITY))) { -+ return curr; -+ } -+ continue; -+ } -+ } -+ -+ /** -+ * Forces this task to be completed. -+ * @return {@code true} if the task was cancelled, {@code false} if the task has already completed or is being completed. -+ */ -+ public boolean cancel() { -+ return this.exchangePriorityVolatile(PrioritizedTaskQueue.COMPLETING_PRIORITY) != PrioritizedTaskQueue.COMPLETING_PRIORITY; -+ } -+ -+ /** -+ * Attempts to raise the priority to the priority level specified. -+ * @param priority Priority specified -+ * @return {@code true} if successful, {@code false} otherwise. -+ */ -+ public boolean raisePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority"); -+ } -+ -+ for (int curr = this.getPriorityVolatile();;) { -+ if (curr == COMPLETING_PRIORITY) { -+ return false; -+ } -+ if (priority >= curr) { -+ return true; -+ } -+ -+ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { -+ PrioritizedTaskQueue queue = this.queue.get(); -+ if (queue != null) { -+ //noinspection unchecked -+ queue.queues[priority].add(this); // silently fail on shutdown -+ } -+ return true; -+ } -+ continue; -+ } -+ } -+ -+ /** -+ * Attempts to set this task's priority level to the level specified. -+ * @param priority Specified priority level. -+ * @return {@code true} if successful, {@code false} if this task is completing or has completed. -+ */ -+ public boolean updatePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority"); -+ } -+ -+ for (int curr = this.getPriorityVolatile();;) { -+ if (curr == COMPLETING_PRIORITY) { -+ return false; -+ } -+ if (curr == priority) { -+ return true; -+ } -+ -+ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { -+ PrioritizedTaskQueue queue = this.queue.get(); -+ if (queue != null) { -+ //noinspection unchecked -+ queue.queues[priority].add(this); // silently fail on shutdown -+ } -+ return true; -+ } -+ continue; -+ } -+ } -+ -+ void setQueue(final PrioritizedTaskQueue queue) { -+ this.queue.set(queue); -+ } -+ -+ /* priority */ -+ -+ protected final int getPriorityVolatile() { -+ return this.priority.get(); -+ } -+ -+ protected final int compareAndExchangePriorityVolatile(final int expect, final int update) { -+ if (this.priority.compareAndSet(expect, update)) { -+ return expect; -+ } -+ return this.priority.get(); -+ } -+ -+ protected final int exchangePriorityVolatile(final int value) { -+ return this.priority.getAndSet(value); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ee906b594b306906c170180a29a8b61997d05168 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java -@@ -0,0 +1,241 @@ -+package com.destroystokyo.paper.io; -+ -+import net.minecraft.server.MinecraftServer; -+import org.apache.logging.log4j.Logger; -+ -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.concurrent.locks.LockSupport; -+ -+public class QueueExecutorThread extends Thread { -+ -+ private static final Logger LOGGER = MinecraftServer.LOGGER; -+ -+ protected final PrioritizedTaskQueue queue; -+ protected final long spinWaitTime; -+ -+ protected volatile boolean closed; -+ -+ protected final AtomicBoolean parked = new AtomicBoolean(); -+ -+ protected volatile ConcurrentLinkedQueue flushQueue = new ConcurrentLinkedQueue<>(); -+ protected volatile long flushCycles; -+ -+ public QueueExecutorThread(final PrioritizedTaskQueue queue) { -+ this(queue, (int)(1.e6)); // 1.0ms -+ } -+ -+ public QueueExecutorThread(final PrioritizedTaskQueue queue, final long spinWaitTime) { // in ms -+ this.queue = queue; -+ this.spinWaitTime = spinWaitTime; -+ } -+ -+ @Override -+ public void run() { -+ final long spinWaitTime = this.spinWaitTime; -+ main_loop: -+ for (;;) { -+ this.pollTasks(true); -+ -+ // spinwait -+ -+ final long start = System.nanoTime(); -+ -+ for (;;) { -+ // If we are interrpted for any reason, park() will always return immediately. Clear so that we don't needlessly use cpu in such an event. -+ Thread.interrupted(); -+ LockSupport.parkNanos("Spinwaiting on tasks", 1000L); // 1us -+ -+ if (this.pollTasks(true)) { -+ // restart loop, found tasks -+ continue main_loop; -+ } -+ -+ if (this.handleClose()) { -+ return; // we're done -+ } -+ -+ if ((System.nanoTime() - start) >= spinWaitTime) { -+ break; -+ } -+ } -+ -+ if (this.handleClose()) { -+ return; -+ } -+ -+ this.parked.set(true); -+ -+ // We need to parse here to avoid a race condition where a thread queues a task before we set parked to true -+ // (i.e it will not notify us) -+ if (this.pollTasks(true)) { -+ this.parked.set(false); -+ continue; -+ } -+ -+ if (this.handleClose()) { -+ return; -+ } -+ -+ // we don't need to check parked before sleeping, but we do need to check parked in a do-while loop -+ // LockSupport.park() can fail for any reason -+ do { -+ Thread.interrupted(); -+ LockSupport.park("Waiting on tasks"); -+ } while (this.parked.get()); -+ } -+ } -+ -+ protected boolean handleClose() { -+ if (this.closed) { -+ this.pollTasks(true); // this ensures we've emptied the queue -+ this.handleFlushThreads(true); -+ return true; -+ } -+ return false; -+ } -+ -+ protected boolean pollTasks(boolean flushTasks) { -+ Runnable task; -+ boolean ret = false; -+ -+ while ((task = this.queue.poll()) != null) { -+ ret = true; -+ try { -+ task.run(); -+ } catch (final Throwable throwable) { -+ if (throwable instanceof ThreadDeath) { -+ throw (ThreadDeath)throwable; -+ } -+ LOGGER.fatal("Exception thrown from prioritized runnable task in thread '" + this.getName() + "': " + IOUtil.genericToString(task), throwable); -+ } -+ } -+ -+ if (flushTasks) { -+ this.handleFlushThreads(false); -+ } -+ -+ return ret; -+ } -+ -+ protected void handleFlushThreads(final boolean shutdown) { -+ Thread parking; -+ ConcurrentLinkedQueue flushQueue = this.flushQueue; -+ do { -+ ++flushCycles; // may be plain read opaque write -+ while ((parking = flushQueue.poll()) != null) { -+ LockSupport.unpark(parking); -+ } -+ } while (this.pollTasks(false)); -+ -+ if (shutdown) { -+ this.flushQueue = null; -+ -+ // defend against a race condition where a flush thread double-checks right before we set to null -+ while ((parking = flushQueue.poll()) != null) { -+ LockSupport.unpark(parking); -+ } -+ } -+ } -+ -+ /** -+ * Notify's this thread that a task has been added to its queue -+ * @return {@code true} if this thread was waiting for tasks, {@code false} if it is executing tasks -+ */ -+ public boolean notifyTasks() { -+ if (this.parked.get() && this.parked.getAndSet(false)) { -+ LockSupport.unpark(this); -+ return true; -+ } -+ return false; -+ } -+ -+ protected void queueTask(final T task) { -+ this.queue.add(task); -+ this.notifyTasks(); -+ } -+ -+ /** -+ * Waits until this thread's queue is empty. -+ * -+ * @throws IllegalStateException If the current thread is {@code this} thread. -+ */ -+ public void flush() { -+ final Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread == this) { -+ // avoid deadlock -+ throw new IllegalStateException("Cannot flush the queue executor thread while on the queue executor thread"); -+ } -+ -+ // order is important -+ -+ int successes = 0; -+ long lastCycle = -1L; -+ -+ do { -+ final ConcurrentLinkedQueue flushQueue = this.flushQueue; -+ if (flushQueue == null) { -+ return; -+ } -+ -+ flushQueue.add(currentThread); -+ -+ // double check flush queue -+ if (this.flushQueue == null) { -+ return; -+ } -+ -+ final long currentCycle = this.flushCycles; // may be opaque read -+ -+ if (currentCycle == lastCycle) { -+ Thread.yield(); -+ continue; -+ } -+ -+ // force response -+ this.parked.set(false); -+ LockSupport.unpark(this); -+ -+ LockSupport.park("flushing queue executor thread"); -+ -+ // returns whether there are tasks queued, does not return whether there are tasks executing -+ // this is why we cycle twice twice through flush (we know a pollTask call is made after a flush cycle) -+ // we really only need to guarantee that the tasks this thread has queued has gone through, and can leave -+ // tasks queued concurrently that are unsychronized with this thread as undefined behavior -+ if (this.queue.hasTasks()) { -+ successes = 0; -+ } else { -+ ++successes; -+ } -+ -+ } while (successes != 2); -+ -+ } -+ -+ /** -+ * Closes this queue executor's queue and optionally waits for it to empty. -+ *

    -+ * If wait is {@code true}, then the queue will be empty by the time this call completes. -+ *

    -+ *

    -+ * This function is MT-Safe. -+ *

    -+ * @param wait If this call is to wait until the queue is empty -+ * @param killQueue Whether to shutdown this thread's queue -+ * @return whether this thread shut down the queue -+ */ -+ public boolean close(final boolean wait, final boolean killQueue) { -+ boolean ret = !killQueue ? false : this.queue.shutdown(); -+ this.closed = true; -+ -+ // force thread to respond to the shutdown -+ this.parked.set(false); -+ LockSupport.unpark(this); -+ -+ if (wait) { -+ this.flush(); -+ } -+ return ret; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java -new file mode 100644 -index 0000000000000000000000000000000000000000..26a5da48c87674f320aa9f7382217cde2c93e08c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java -@@ -0,0 +1,145 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import co.aikar.timings.Timing; -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.IOUtil; -+import java.util.ArrayDeque; -+import java.util.function.Consumer; -+import net.minecraft.server.level.ChunkMap; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.world.level.ChunkPos; -+import net.minecraft.world.level.chunk.storage.ChunkSerializer; -+ -+public final class ChunkLoadTask extends ChunkTask { -+ -+ public boolean cancelled; -+ -+ Consumer onComplete; -+ public PaperFileIOThread.ChunkData chunkData; -+ -+ private boolean hasCompleted; -+ -+ public ChunkLoadTask(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, -+ final ChunkTaskManager taskManager, -+ final Consumer onComplete) { -+ super(world, chunkX, chunkZ, priority, taskManager); -+ this.onComplete = onComplete; -+ } -+ -+ private static final ArrayDeque EMPTY_QUEUE = new ArrayDeque<>(); -+ -+ private static ChunkSerializer.InProgressChunkHolder createEmptyHolder() { -+ return new ChunkSerializer.InProgressChunkHolder(null, EMPTY_QUEUE); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ this.executeTask(); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.error("Failed to execute chunk load task: " + this.toString(), ex); -+ if (!this.hasCompleted) { -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ } -+ } -+ } -+ -+ private boolean checkCancelled() { -+ if (this.cancelled) { -+ // IntelliJ does not understand writes may occur to cancelled concurrently. -+ return this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != ChunkLoadTask.this) { -+ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); -+ } -+ -+ if (valueInMap.cancelled) { -+ return null; -+ } -+ return valueInMap; -+ }) == null; -+ } -+ return false; -+ } -+ -+ public void executeTask() { -+ if (this.checkCancelled()) { -+ return; -+ } -+ -+ // either executed synchronously or asynchronously -+ final PaperFileIOThread.ChunkData chunkData = this.chunkData; -+ -+ if (chunkData.poiData == PaperFileIOThread.FAILURE_VALUE || chunkData.chunkData == PaperFileIOThread.FAILURE_VALUE) { -+ PaperFileIOThread.LOGGER.error("Could not load chunk for task: " + this.toString() + ", file IO thread has dumped the relevant exception above"); -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ return; -+ } -+ -+ if (chunkData.chunkData == null) { -+ // not on disk -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ return; -+ } -+ -+ final ChunkPos chunkPos = new ChunkPos(this.chunkX, this.chunkZ); -+ -+ final ChunkMap chunkManager = this.world.getChunkSource().chunkMap; -+ -+ try (Timing ignored = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { -+ final ChunkSerializer.InProgressChunkHolder chunkHolder; -+ -+ // apply fixes -+ -+ try { -+ chunkData.chunkData = chunkManager.getChunkData(this.world.getTypeKey(), -+ chunkManager.getWorldPersistentDataSupplier(), chunkData.chunkData, chunkPos, this.world); // clone data for safety, file IO thread does not clone -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.error("Could not apply datafixers for chunk task: " + this.toString(), ex); -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ } -+ -+ if (this.checkCancelled()) { -+ return; -+ } -+ -+ try { -+ this.world.getChunkSource().chunkMap.updateChunkStatusOnDisk(chunkPos, chunkData.chunkData); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.warn("Failed to update chunk status cache for task: " + this.toString(), ex); -+ // non-fatal, continue -+ } -+ -+ try { -+ chunkHolder = ChunkSerializer.loadChunk(this.world, -+ chunkManager.structureManager, chunkManager.getVillagePlace(), chunkPos, -+ chunkData.chunkData, true); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.error("Could not de-serialize chunk data for task: " + this.toString(), ex); -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ return; -+ } -+ -+ this.complete(chunkHolder); -+ } -+ } -+ -+ private void complete(final ChunkSerializer.InProgressChunkHolder holder) { -+ this.hasCompleted = true; -+ holder.poiData = this.chunkData == null ? null : this.chunkData.poiData; -+ -+ this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != ChunkLoadTask.this) { -+ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); -+ } -+ if (valueInMap.cancelled) { -+ return null; -+ } -+ try { -+ ChunkLoadTask.this.onComplete.accept(holder); -+ } catch (final Throwable thr) { -+ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); -+ } -+ return null; -+ }); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java -new file mode 100644 -index 0000000000000000000000000000000000000000..69ebbfa171385c46a84d1a0d241d168a8c2af145 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java -@@ -0,0 +1,111 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import co.aikar.timings.Timing; -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.IOUtil; -+import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+ -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.atomic.AtomicInteger; -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.world.level.chunk.ChunkAccess; -+import net.minecraft.world.level.chunk.storage.ChunkSerializer; -+ -+public final class ChunkSaveTask extends ChunkTask { -+ -+ public final ChunkSerializer.AsyncSaveData asyncSaveData; -+ public final ChunkAccess chunk; -+ public final CompletableFuture onComplete = new CompletableFuture<>(); -+ -+ private final AtomicInteger attemptedPriority; -+ -+ public ChunkSaveTask(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, -+ final ChunkTaskManager taskManager, final ChunkSerializer.AsyncSaveData asyncSaveData, -+ final ChunkAccess chunk) { -+ super(world, chunkX, chunkZ, priority, taskManager); -+ this.chunk = chunk; -+ this.asyncSaveData = asyncSaveData; -+ this.attemptedPriority = new AtomicInteger(priority); -+ } -+ -+ @Override -+ public void run() { -+ // can be executed asynchronously or synchronously -+ final CompoundTag compound; -+ -+ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTimingIfSync()) { -+ compound = ChunkSerializer.saveChunk(this.world, this.chunk, this.asyncSaveData); -+ } catch (final Throwable ex) { -+ // has a plugin modified something it should not have and made us CME? -+ PaperFileIOThread.LOGGER.error("Failed to serialize unloading chunk data for task: " + this.toString() + ", falling back to a synchronous execution", ex); -+ -+ // Note: We add to the server thread queue here since this is what the server will drain tasks from -+ // when waiting for chunks -+ ChunkTaskManager.queueChunkWaitTask(() -> { -+ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTiming()) { -+ CompoundTag data = PaperFileIOThread.FAILURE_VALUE; -+ -+ try { -+ data = ChunkSerializer.saveChunk(this.world, this.chunk, this.asyncSaveData); -+ PaperFileIOThread.LOGGER.info("Successfully serialized chunk data for task: " + this.toString() + " synchronously"); -+ } catch (final Throwable ex1) { -+ PaperFileIOThread.LOGGER.fatal("Failed to synchronously serialize unloading chunk data for task: " + this.toString() + "! Chunk data will be lost", ex1); -+ } -+ -+ ChunkSaveTask.this.complete(data); -+ } -+ }); -+ -+ return; // the main thread will now complete the data -+ } -+ -+ this.complete(compound); -+ } -+ -+ @Override -+ public boolean raisePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalStateException("Invalid priority: " + priority); -+ } -+ -+ // we know priority is valid here -+ for (int curr = this.attemptedPriority.get();;) { -+ if (curr <= priority) { -+ break; // curr is higher/same priority -+ } -+ if (this.attemptedPriority.compareAndSet(curr, priority)) { -+ break; -+ } -+ curr = this.attemptedPriority.get(); -+ } -+ -+ return super.raisePriority(priority); -+ } -+ -+ @Override -+ public boolean updatePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalStateException("Invalid priority: " + priority); -+ } -+ this.attemptedPriority.set(priority); -+ return super.updatePriority(priority); -+ } -+ -+ private void complete(final CompoundTag compound) { -+ try { -+ this.onComplete.complete(compound); -+ } catch (final Throwable thr) { -+ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); -+ } -+ if (compound != PaperFileIOThread.FAILURE_VALUE) { -+ PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, this.chunkX, this.chunkZ, null, compound, this.attemptedPriority.get()); -+ } -+ this.taskManager.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { -+ if (valueInMap != ChunkSaveTask.this) { -+ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", this: " + ChunkSaveTask.this); -+ } -+ return null; -+ }); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java -new file mode 100644 -index 0000000000000000000000000000000000000000..058fb5a41565e6ce2acbd1f4d071a1b8be449f5d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java -@@ -0,0 +1,40 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+import net.minecraft.server.level.ServerLevel; -+ -+abstract class ChunkTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { -+ -+ public final ServerLevel world; -+ public final int chunkX; -+ public final int chunkZ; -+ public final ChunkTaskManager taskManager; -+ -+ public ChunkTask(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, -+ final ChunkTaskManager taskManager) { -+ super(priority); -+ this.world = world; -+ this.chunkX = chunkX; -+ this.chunkZ = chunkZ; -+ this.taskManager = taskManager; -+ } -+ -+ @Override -+ public String toString() { -+ return "Chunk task: class:" + this.getClass().getName() + ", for world '" + this.world.getWorld().getName() + -+ "', (" + this.chunkX + "," + this.chunkZ + "), hashcode:" + this.hashCode() + ", priority: " + this.getPriority(); -+ } -+ -+ @Override -+ public boolean raisePriority(final int priority) { -+ PaperFileIOThread.Holder.INSTANCE.bumpPriority(this.world, this.chunkX, this.chunkZ, priority); -+ return super.raisePriority(priority); -+ } -+ -+ @Override -+ public boolean updatePriority(final int priority) { -+ PaperFileIOThread.Holder.INSTANCE.setPriority(this.world, this.chunkX, this.chunkZ, priority); -+ return super.updatePriority(priority); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..499aff1f1e1ffc01ba8f9de43ca17899525a306f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -@@ -0,0 +1,513 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.IOUtil; -+import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+import com.destroystokyo.paper.io.QueueExecutorThread; -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkHolder; -+import net.minecraft.server.level.ServerChunkCache; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.util.thread.BlockableEventLoop; -+import net.minecraft.world.level.chunk.ChunkAccess; -+import net.minecraft.world.level.chunk.ChunkStatus; -+import net.minecraft.world.level.chunk.storage.ChunkSerializer; -+import org.apache.commons.lang.StringUtils; -+import org.apache.logging.log4j.Level; -+import org.bukkit.Bukkit; -+import org.spigotmc.AsyncCatcher; -+ -+import java.util.ArrayDeque; -+import java.util.HashSet; -+import java.util.Set; -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.function.Consumer; -+ -+public final class ChunkTaskManager { -+ -+ private final QueueExecutorThread[] workers; -+ private final ServerLevel world; -+ -+ private final PrioritizedTaskQueue queue; -+ private final boolean perWorldQueue; -+ -+ final ConcurrentHashMap chunkLoadTasks = new ConcurrentHashMap<>(64, 0.5f); -+ final ConcurrentHashMap chunkSaveTasks = new ConcurrentHashMap<>(64, 0.5f); -+ -+ private final PrioritizedTaskQueue chunkTasks = new PrioritizedTaskQueue<>(); // used if async chunks are disabled in config -+ -+ protected static QueueExecutorThread[] globalWorkers; -+ protected static QueueExecutorThread globalUrgentWorker; -+ protected static PrioritizedTaskQueue globalQueue; -+ protected static PrioritizedTaskQueue globalUrgentQueue; -+ -+ protected static final ConcurrentLinkedQueue CHUNK_WAIT_QUEUE = new ConcurrentLinkedQueue<>(); -+ -+ public static final ArrayDeque WAITING_CHUNKS = new ArrayDeque<>(); // stack -+ -+ private static final class ChunkInfo { -+ -+ public final int chunkX; -+ public final int chunkZ; -+ public final ServerLevel world; -+ -+ public ChunkInfo(final int chunkX, final int chunkZ, final ServerLevel world) { -+ this.chunkX = chunkX; -+ this.chunkZ = chunkZ; -+ this.world = world; -+ } -+ -+ @Override -+ public String toString() { -+ return "[( " + this.chunkX + "," + this.chunkZ + ") in '" + this.world.getWorld().getName() + "']"; -+ } -+ } -+ -+ public static void pushChunkWait(final ServerLevel world, final int chunkX, final int chunkZ) { -+ synchronized (WAITING_CHUNKS) { -+ WAITING_CHUNKS.push(new ChunkInfo(chunkX, chunkZ, world)); -+ } -+ } -+ -+ public static void popChunkWait() { -+ synchronized (WAITING_CHUNKS) { -+ WAITING_CHUNKS.pop(); -+ } -+ } -+ -+ private static ChunkInfo[] getChunkInfos() { -+ ChunkInfo[] chunks; -+ synchronized (WAITING_CHUNKS) { -+ chunks = WAITING_CHUNKS.toArray(new ChunkInfo[0]); -+ } -+ return chunks; -+ } -+ -+ public static void dumpAllChunkLoadInfo() { -+ ChunkInfo[] chunks = getChunkInfos(); -+ if (chunks.length > 0) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk wait task info below: "); -+ -+ for (final ChunkInfo chunkInfo : chunks) { -+ final long key = IOUtil.getCoordinateKey(chunkInfo.chunkX, chunkInfo.chunkZ); -+ final ChunkLoadTask loadTask = chunkInfo.world.asyncChunkTaskManager.chunkLoadTasks.get(key); -+ final ChunkSaveTask saveTask = chunkInfo.world.asyncChunkTaskManager.chunkSaveTasks.get(key); -+ -+ PaperFileIOThread.LOGGER.log(Level.ERROR, chunkInfo.chunkX + "," + chunkInfo.chunkZ + " in '" + chunkInfo.world.getWorld().getName() + ":"); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Load Task - " + (loadTask == null ? "none" : loadTask.toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Save Task - " + (saveTask == null ? "none" : saveTask.toString())); -+ // log current status of chunk to indicate whether we're waiting on generation or loading -+ ChunkHolder chunkHolder = chunkInfo.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(key); -+ -+ dumpChunkInfo(new HashSet<>(), chunkHolder, chunkInfo.chunkX, chunkInfo.chunkZ); -+ } -+ } -+ } -+ -+ static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z) { -+ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); -+ } -+ -+ static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z, int indent, int maxDepth) { -+ if (seenChunks.contains(chunkHolder)) { -+ return; -+ } -+ if (indent > maxDepth) { -+ return; -+ } -+ seenChunks.add(chunkHolder); -+ String indentStr = StringUtils.repeat(" ", indent); -+ if (chunkHolder == null) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - null for (" + x +"," + z +")"); -+ } else { -+ ChunkAccess chunk = chunkHolder.getAvailableChunkNow(); -+ ChunkStatus holderStatus = chunkHolder.getChunkHolderStatus(); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - non-null"); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); -+ } -+ } -+ -+ public static void initGlobalLoadThreads(int threads) { -+ if (threads <= 0 || globalWorkers != null) { -+ return; -+ } -+ -+ globalWorkers = new QueueExecutorThread[threads]; -+ globalQueue = new PrioritizedTaskQueue<>(); -+ globalUrgentQueue = new PrioritizedTaskQueue<>(); -+ -+ for (int i = 0; i < threads; ++i) { -+ globalWorkers[i] = new QueueExecutorThread<>(globalQueue, (long)0.10e6); //0.1ms -+ globalWorkers[i].setName("Paper Async Chunk Task Thread #" + i); -+ globalWorkers[i].setPriority(Thread.NORM_PRIORITY - 1); -+ globalWorkers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { -+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); -+ }); -+ -+ globalWorkers[i].start(); -+ } -+ -+ globalUrgentWorker = new QueueExecutorThread<>(globalUrgentQueue, (long)0.10e6); //0.1ms -+ globalUrgentWorker.setName("Paper Async Chunk Urgent Task Thread"); -+ globalUrgentWorker.setPriority(Thread.NORM_PRIORITY+1); -+ globalUrgentWorker.setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { -+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); -+ }); -+ -+ globalUrgentWorker.start(); -+ } -+ -+ /** -+ * Creates this chunk task manager to operate off the specified number of threads. If the specified number of threads is -+ * less-than or equal to 0, then this chunk task manager will operate off of the world's chunk task queue. -+ * @param world Specified world. -+ * @param threads Specified number of threads. -+ * @see ServerChunkCache#mainThreadProcessor -+ */ -+ public ChunkTaskManager(final ServerLevel world, final int threads) { -+ this.world = world; -+ this.workers = threads <= 0 ? null : new QueueExecutorThread[threads]; -+ this.queue = new PrioritizedTaskQueue<>(); -+ this.perWorldQueue = true; -+ -+ for (int i = 0; i < threads; ++i) { -+ this.workers[i] = new QueueExecutorThread<>(this.queue, (long)0.10e6); //0.1ms -+ this.workers[i].setName("Async chunk loader thread #" + i + " for world: " + world.getWorld().getName()); -+ this.workers[i].setPriority(Thread.NORM_PRIORITY - 1); -+ this.workers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { -+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); -+ }); -+ -+ this.workers[i].start(); -+ } -+ } -+ -+ /** -+ * Creates the chunk task manager to work from the global workers. When {@link #close(boolean)} is invoked, -+ * the global queue is not shutdown. If the global workers is configured to be disabled or use 0 threads, then -+ * this chunk task manager will operate off of the world's chunk task queue. -+ * @param world The world that this task manager is responsible for -+ * @see ServerChunkCache#mainThreadProcessor -+ */ -+ public ChunkTaskManager(final ServerLevel world) { -+ this.world = world; -+ this.workers = globalWorkers; -+ this.queue = globalQueue; -+ this.perWorldQueue = false; -+ } -+ -+ public boolean pollNextChunkTask() { -+ final ChunkTask task = this.chunkTasks.poll(); -+ -+ if (task != null) { -+ task.run(); -+ return true; -+ } -+ return false; -+ } -+ -+ /** -+ * Polls and runs the next available chunk wait queue task. This is to be used when the server is waiting on a chunk queue. -+ * (per-world can cause issues if all the worker threads are blocked waiting for a response from the main thread) -+ */ -+ public static boolean pollChunkWaitQueue() { -+ final Runnable run = CHUNK_WAIT_QUEUE.poll(); -+ if (run != null) { -+ run.run(); -+ return true; -+ } -+ return false; -+ } -+ -+ /** -+ * Queues a chunk wait task. Note that this will execute out of order with respect to tasks scheduled on a world's -+ * chunk task queue, since this is the global chunk wait queue. -+ */ -+ public static void queueChunkWaitTask(final Runnable runnable) { -+ CHUNK_WAIT_QUEUE.add(runnable); -+ } -+ -+ private static void drainChunkWaitQueue() { -+ Runnable run; -+ while ((run = CHUNK_WAIT_QUEUE.poll()) != null) { -+ run.run(); -+ } -+ } -+ -+ /** -+ * The exact same as {@link #scheduleChunkLoad(int, int, int, Consumer, boolean)}, except that the chunk data is provided as -+ * the {@code data} parameter. -+ */ -+ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, -+ final Consumer onComplete, -+ final boolean intendingToBlock, final CompletableFuture dataFuture) { -+ final ServerLevel world = this.world; -+ -+ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != null) { -+ if (!valueInMap.cancelled) { -+ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); -+ } -+ valueInMap.cancelled = false; -+ valueInMap.onComplete = onComplete; -+ return valueInMap; -+ } -+ -+ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); -+ -+ dataFuture.thenAccept((final CompoundTag data) -> { -+ final boolean failed = data == PaperFileIOThread.FAILURE_VALUE; -+ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { -+ ret.chunkData = chunkData; -+ if (!failed) { -+ chunkData.chunkData = data; -+ } -+ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here -+ }, true, failed, intendingToBlock); // read data off disk if the future fails -+ }); -+ -+ return ret; -+ }); -+ } -+ -+ public void cancelChunkLoad(final int chunkX, final int chunkZ) { -+ this.chunkLoadTasks.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap == null) { -+ return null; -+ } -+ -+ if (valueInMap.cancelled) { -+ PaperFileIOThread.LOGGER.warn("Task " + valueInMap.toString() + " is already cancelled!"); -+ } -+ valueInMap.cancelled = true; -+ if (valueInMap.cancel()) { -+ return null; -+ } -+ -+ return valueInMap; -+ }); -+ } -+ -+ /** -+ * Schedules an asynchronous chunk load for the specified coordinates. The onComplete parameter may be invoked asynchronously -+ * on a worker thread or on the world's chunk executor queue. As such the code that is executed for the parameter should be -+ * carefully chosen. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority for this task -+ * @param onComplete The consumer to invoke with the {@link ChunkSerializer.InProgressChunkHolder} object once this task is complete -+ * @param intendingToBlock Whether the caller is intending to block on this task completing (this is a performance tune, and has no adverse side-effects) -+ * @return The {@link ChunkLoadTask} associated with -+ */ -+ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, -+ final Consumer onComplete, -+ final boolean intendingToBlock) { -+ final ServerLevel world = this.world; -+ -+ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != null) { -+ if (!valueInMap.cancelled) { -+ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); -+ } -+ valueInMap.cancelled = false; -+ valueInMap.onComplete = onComplete; -+ return valueInMap; -+ } -+ -+ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); -+ -+ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { -+ ret.chunkData = chunkData; -+ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here -+ }, true, true, intendingToBlock); -+ -+ return ret; -+ }); -+ } -+ -+ /** -+ * Schedules an async save for the specified chunk. The chunk, at the beginning of this call, must be completely unloaded -+ * from the world. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority for this task -+ * @param asyncSaveData Async save data. See {@link ChunkSerializer#getAsyncSaveData(ServerLevel, ChunkAccess)} -+ * @param chunk Chunk to save -+ * @return The {@link ChunkSaveTask} associated with the save task. -+ */ -+ public ChunkSaveTask scheduleChunkSave(final int chunkX, final int chunkZ, final int priority, -+ final ChunkSerializer.AsyncSaveData asyncSaveData, -+ final ChunkAccess chunk) { -+ AsyncCatcher.catchOp("chunk save schedule"); -+ -+ final ServerLevel world = this.world; -+ -+ return this.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { -+ if (valueInMap != null) { -+ throw new IllegalStateException("Double scheduling chunk save for task: " + valueInMap.toString()); -+ } -+ -+ final ChunkSaveTask ret = new ChunkSaveTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, asyncSaveData, chunk); -+ -+ ChunkTaskManager.this.internalSchedule(ret); -+ -+ return ret; -+ }); -+ } -+ -+ /** -+ * Returns a completable future which will be completed with the un-copied chunk data for an in progress async save. -+ * Returns {@code null} if no save is in progress. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ */ -+ public CompletableFuture getChunkSaveFuture(final int chunkX, final int chunkZ) { -+ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); -+ if (chunkSaveTask == null) { -+ return null; -+ } -+ return chunkSaveTask.onComplete; -+ } -+ -+ /** -+ * Returns the chunk object being used to serialize data async for an unloaded chunk. Note that modifying this chunk -+ * is not safe to do as another thread is handling its save. The chunk is also not loaded into the world. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @return Chunk object for an in-progress async save, or {@code null} if no save is in progress -+ */ -+ public ChunkAccess getChunkInSaveProgress(final int chunkX, final int chunkZ) { -+ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); -+ if (chunkSaveTask == null) { -+ return null; -+ } -+ return chunkSaveTask.chunk; -+ } -+ -+ public void flush() { -+ // flush here since we schedule tasks on the IO thread that can schedule tasks here -+ drainChunkWaitQueue(); -+ PaperFileIOThread.Holder.INSTANCE.flush(); -+ drainChunkWaitQueue(); -+ -+ if (this.workers == null) { -+ if (Bukkit.isPrimaryThread() || MinecraftServer.getServer().hasStopped()) { -+ ((BlockableEventLoop)this.world.getChunkSource().mainThreadProcessor).runAllTasks(); -+ } else { -+ CompletableFuture wait = new CompletableFuture<>(); -+ MinecraftServer.getServer().scheduleOnMain(() -> { -+ ((BlockableEventLoop)this.world.getChunkSource().mainThreadProcessor).runAllTasks(); -+ }); -+ wait.join(); -+ } -+ } else { -+ for (final QueueExecutorThread worker : this.workers) { -+ worker.flush(); -+ } -+ } -+ if (globalUrgentWorker != null) globalUrgentWorker.flush(); -+ -+ // flush again since tasks we execute async saves -+ drainChunkWaitQueue(); -+ PaperFileIOThread.Holder.INSTANCE.flush(); -+ } -+ -+ public void close(final boolean wait) { -+ // flush here since we schedule tasks on the IO thread that can schedule tasks to this task manager -+ // we do this regardless of the wait param since after we invoke close no tasks can be queued -+ PaperFileIOThread.Holder.INSTANCE.flush(); -+ -+ if (this.workers == null) { -+ if (wait) { -+ this.flush(); -+ } -+ return; -+ } -+ -+ if (this.workers != globalWorkers) { -+ for (final QueueExecutorThread worker : this.workers) { -+ worker.close(false, this.perWorldQueue); -+ } -+ } -+ -+ if (wait) { -+ this.flush(); -+ } -+ } -+ -+ public void raisePriority(final int chunkX, final int chunkZ, final int priority) { -+ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); -+ -+ ChunkTask chunkSaveTask = this.chunkSaveTasks.get(chunkKey); -+ if (chunkSaveTask != null) { -+ // don't bump save into urgent queue -+ raiseTaskPriority(chunkSaveTask, priority != PrioritizedTaskQueue.HIGHEST_PRIORITY ? priority : PrioritizedTaskQueue.HIGH_PRIORITY); -+ } -+ -+ ChunkLoadTask chunkLoadTask = this.chunkLoadTasks.get(chunkKey); -+ if (chunkLoadTask != null) { -+ raiseTaskPriority(chunkLoadTask, priority); -+ } -+ } -+ -+ private void raiseTaskPriority(ChunkTask task, int priority) { -+ final boolean raised = task.raisePriority(priority); -+ if (task.isScheduled() && raised && this.workers != null) { -+ // only notify if we're in queue to be executed -+ if (priority == PrioritizedTaskQueue.HIGHEST_PRIORITY) { -+ // was in another queue but became urgent later, add to urgent queue and the previous -+ // queue will just have to ignore this task if it has already been started. -+ // Ultimately, we now have 2 potential queues that can pull it out whoever gets it first -+ // but the urgent queue has dedicated thread(s) so it's likely to win.... -+ globalUrgentQueue.add(task); -+ this.internalScheduleNotifyUrgent(); -+ } else { -+ this.internalScheduleNotify(); -+ } -+ } -+ } -+ -+ protected void internalSchedule(final ChunkTask task) { -+ if (this.workers == null) { -+ this.chunkTasks.add(task); -+ return; -+ } -+ -+ // It's important we order the task to be executed before notifying. Avoid a race condition where the worker thread -+ // wakes up and goes to sleep before we actually schedule (or it's just about to sleep) -+ if (task.getPriority() == PrioritizedTaskQueue.HIGHEST_PRIORITY) { -+ globalUrgentQueue.add(task); -+ this.internalScheduleNotifyUrgent(); -+ } else { -+ this.queue.add(task); -+ this.internalScheduleNotify(); -+ } -+ -+ } -+ -+ protected void internalScheduleNotify() { -+ if (this.workers == null) { -+ return; -+ } -+ for (final QueueExecutorThread worker : this.workers) { -+ if (worker.notifyTasks()) { -+ // break here since we only want to wake up one worker for scheduling one task -+ break; -+ } -+ } -+ } -+ -+ -+ protected void internalScheduleNotifyUrgent() { -+ if (globalUrgentWorker == null) { -+ return; -+ } -+ globalUrgentWorker.notifyTasks(); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java -index 354783f862986bf939639a86a9076ac0f5ed97e3..c171860bc117199ca00085bf37507f867d51fb62 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java -@@ -14,7 +14,7 @@ public class ServerboundCommandSuggestionPacket implements Packet { - DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataFixers.getDataFixer(), minecraftsessionservice, gameprofilerepository, usercache, LoggerChunkProgressListener::new); - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index aab1a055c065d1f1a92461e4442ec2cdd8e0b347..643d75b999c3da006eaaab11f4acd77e807683d4 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -920,7 +920,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> future = this.getFutureIfPresentUnchecked(curr); -+ Either either = future.getNow(null); -+ if (either == null || !either.left().isPresent()) { -+ continue; -+ } -+ return curr; -+ } -+ return null; -+ } - // Paper end - - public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { -@@ -375,7 +387,7 @@ public class ChunkHolder { - ChunkStatus chunkstatus = getStatus(this.oldTicketLevel); - ChunkStatus chunkstatus1 = getStatus(this.ticketLevel); - boolean flag = this.oldTicketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; -- boolean flag1 = this.ticketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; -+ boolean flag1 = this.ticketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; // Paper - diff on change: (flag1 = new ticket level is in loadable range) - ChunkHolder.FullChunkStatus playerchunk_state = getFullChunkStatus(this.oldTicketLevel); - ChunkHolder.FullChunkStatus playerchunk_state1 = getFullChunkStatus(this.ticketLevel); - // CraftBukkit start -@@ -411,6 +423,12 @@ public class ChunkHolder { - } - }); - -+ // Paper start -+ if (!flag1) { -+ chunkStorage.level.asyncChunkTaskManager.cancelChunkLoad(this.pos.x, this.pos.z); -+ } -+ // Paper end -+ - for (int i = flag1 ? chunkstatus1.getIndex() + 1 : 0; i <= chunkstatus.getIndex(); ++i) { - completablefuture = (CompletableFuture) this.futures.get(i); - if (completablefuture != null) { -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f327e2113 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -86,6 +86,7 @@ import net.minecraft.world.level.chunk.ProtoChunk; - import net.minecraft.world.level.chunk.UpgradeData; - import net.minecraft.world.level.chunk.storage.ChunkSerializer; - import net.minecraft.world.level.chunk.storage.ChunkStorage; -+import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; - import net.minecraft.world.level.storage.DimensionDataStorage; -@@ -110,7 +111,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private final ThreadedLevelLightEngine lightEngine; - private final BlockableEventLoop mainThreadExecutor; - public final ChunkGenerator generator; -- private final Supplier overworldDataStorage; -+ private final Supplier overworldDataStorage; public final Supplier getWorldPersistentDataSupplier() { return this.overworldDataStorage; } // Paper - OBFHELPER - private final PoiManager poiManager; - public final LongSet toDrop; - private boolean modified; -@@ -120,7 +121,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public final ChunkProgressListener progressListener; - public final ChunkMap.ChunkDistanceManager distanceManager; - private final AtomicInteger tickingGenerated; -- private final StructureManager structureManager; -+ public final StructureManager structureManager; // Paper - private -> public - private final File storageFolder; - private final PlayerMap playerMap; - public final Int2ObjectMap entityMap; -@@ -203,7 +204,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); - this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); - this.overworldDataStorage = supplier; -- this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag); -+ this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper - this.setViewDistance(i); - } - -@@ -245,12 +246,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - @Nullable -- protected ChunkHolder getUpdatingChunkIfPresent(long pos) { -+ public ChunkHolder getUpdatingChunkIfPresent(long pos) { // Paper - return (ChunkHolder) this.updatingChunkMap.get(pos); - } - - @Nullable -- protected ChunkHolder getVisibleChunkIfPresent(long pos) { -+ public ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public - return (ChunkHolder) this.visibleChunkMap.get(pos); - } - -@@ -372,6 +373,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public void close() throws IOException { - try { - this.queueSorter.close(); -+ this.level.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line - this.poiManager.close(); - } finally { - super.close(); -@@ -463,7 +465,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.processUnloads(() -> { - return true; - }); -- this.flushWorker(); -+ this.level.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour -+// this.i(); // Paper - nuke IOWorker - ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); - } else { - this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { -@@ -479,16 +482,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - } - -- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot -+ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more - - protected void tick(BooleanSupplier shouldKeepTicking) { - ProfilerFiller gameprofilerfiller = this.level.getProfiler(); - -+ try (Timing ignored = this.level.timings.poiUnload.startTiming()) { // Paper - gameprofilerfiller.push("poi"); - this.poiManager.tick(shouldKeepTicking); -+ } // Paper - gameprofilerfiller.popPush("chunk_unload"); - if (!this.level.noSave()) { -+ try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper - this.processUnloads(shouldKeepTicking); -+ }// Paper - } - - gameprofilerfiller.pop(); -@@ -509,12 +516,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - if (playerchunk != null) { - this.pendingUnloads.put(j, playerchunk); - this.modified = true; -+ this.scheduleUnload(j, playerchunk); // Paper - Move up - don't leak chunks - // Spigot start - if (!shouldKeepTicking.getAsBoolean() && this.toDrop.size() <= targetSize && activityAccountant.activityTimeIsExhausted()) { - break; - } - // Spigot end -- this.scheduleUnload(j, playerchunk); -+ //this.a(j, playerchunk); // Paper - move up because spigot did a dumb - } - } - activityAccountant.endActivity(); // Spigot -@@ -528,6 +536,60 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - } - -+ // Paper start - async chunk save for unload -+ // Note: This is very unsafe to call if the chunk is still in use. -+ // This is also modeled after PlayerChunkMap#saveChunk(IChunkAccess, boolean), with the intentional difference being -+ // serializing the chunk is left to a worker thread. -+ private void asyncSave(ChunkAccess chunk) { -+ ChunkPos chunkPos = chunk.getPos(); -+ CompoundTag poiData; -+ try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) { -+ poiData = this.getVillagePlace().getData(chunk.getPos()); -+ } -+ -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkPos.x, chunkPos.z, -+ poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); -+ -+ if (!chunk.isUnsaved()) { -+ return; -+ } -+ -+ ChunkStatus chunkstatus = chunk.getStatus(); -+ -+ // Copied from PlayerChunkMap#saveChunk(IChunkAccess, boolean) -+ if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { -+ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper -+ // Paper start - Optimize save by using status cache -+ try { -+ ChunkStatus statusOnDisk = this.getChunkStatusOnDisk(chunkPos); -+ if (statusOnDisk != null && statusOnDisk.getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { -+ // Paper end -+ return; -+ } -+ -+ if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::e)) { -+ return; -+ } -+ } catch (IOException ex) { -+ ex.printStackTrace(); -+ return; -+ } -+ } -+ } -+ -+ ChunkSerializer.AsyncSaveData asyncSaveData; -+ try (Timing ignored = this.level.timings.chunkUnloadPrepareSave.startTiming()) { -+ asyncSaveData = ChunkSerializer.getAsyncSaveData(this.level, chunk); -+ } -+ -+ this.level.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY, -+ asyncSaveData, chunk); -+ -+ chunk.setLastSaveTime(this.level.getGameTime()); -+ chunk.setUnsaved(false); -+ } -+ // Paper end -+ - private void scheduleUnload(long pos, ChunkHolder playerchunk) { - CompletableFuture completablefuture = playerchunk.getChunkToSave(); - Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error -@@ -541,7 +603,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - ((LevelChunk) ichunkaccess).setLoaded(false); - } - -- this.save(ichunkaccess); -+ //this.saveChunk(ichunkaccess);// Paper - delay - if (this.entitiesInLevel.remove(pos) && ichunkaccess instanceof LevelChunk) { - LevelChunk chunk = (LevelChunk) ichunkaccess; - -@@ -549,6 +611,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - this.autoSaveQueue.remove(playerchunk); // Paper - -+ try { -+ this.asyncSave(ichunkaccess); // Paper - async chunk saving -+ } catch (Throwable ex) { -+ LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex); -+ this.save(ichunkaccess); -+ } -+ - this.lightEngine.updateChunkStatus(ichunkaccess.getPos()); - this.lightEngine.tryScheduleUpdate(); - this.progressListener.onStatusChange(ichunkaccess.getPos(), (ChunkStatus) null); -@@ -619,19 +688,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - private CompletableFuture> scheduleChunkLoad(ChunkPos pos) { -- return CompletableFuture.supplyAsync(() -> { -+ // Paper start - Async chunk io -+ final java.util.function.BiFunction> syncLoadComplete = (chunkHolder, ioThrowable) -> { - try (Timing ignored = this.level.timings.chunkLoad.startTimingIfSync()) { // Paper - this.level.getProfiler().incrementCounter("chunkLoad"); -- CompoundTag nbttagcompound; // Paper -- try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings -- nbttagcompound = this.readChunk(pos); -- } // Paper end -+ // Paper start -+ if (ioThrowable != null) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable); -+ } -+ -+ this.getVillagePlace().loadInData(pos, chunkHolder.poiData); -+ chunkHolder.tasks.forEach(Runnable::run); -+ // Paper end - -- if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings -- boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8); -+ if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async - -- if (flag) { -- ProtoChunk protochunk = ChunkSerializer.read(this.level, this.structureManager, this.poiManager, pos, nbttagcompound); -+ if (true) { -+ ProtoChunk protochunk = chunkHolder.protoChunk; - - protochunk.setLastSaveTime(this.level.getGameTime()); - this.markPosition(pos, protochunk.getStatus().getChunkType()); -@@ -655,7 +728,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - this.markPositionReplaceable(pos); - return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level)); // Paper - Anti-Xray - Add parameter -- }, this.mainThreadExecutor); -+ // Paper start - Async chunk io -+ }; -+ CompletableFuture> ret = new CompletableFuture<>(); -+ -+ Consumer chunkHolderConsumer = (ChunkSerializer.InProgressChunkHolder holder) -> { -+ // Go into the chunk load queue and not server task queue so we can be popped out even faster. -+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.queueChunkWaitTask(() -> { -+ try { -+ ret.complete(syncLoadComplete.apply(holder, null)); -+ } catch (Exception e) { -+ ret.completeExceptionally(e); -+ } -+ }); -+ }; -+ -+ CompletableFuture chunkSaveFuture = this.level.asyncChunkTaskManager.getChunkSaveFuture(pos.x, pos.z); -+ if (chunkSaveFuture != null) { -+ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); -+ this.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); -+ } else { -+ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); -+ } -+ return ret; -+ // Paper end - } - - private void markPositionReplaceable(ChunkPos chunkcoordintpair) { -@@ -890,6 +988,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - public boolean save(ChunkAccess chunk) { -+ try (co.aikar.timings.Timing ignored = this.level.timings.chunkSave.startTiming()) { // Paper - this.poiManager.flush(chunk.getPos()); - if (!chunk.isUnsaved()) { - return false; -@@ -902,6 +1001,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - ChunkStatus chunkstatus = chunk.getStatus(); - - if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { -+ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper - if (this.isExistingChunkFull(chunkcoordintpair)) { - return false; - } -@@ -909,12 +1009,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::e)) { - return false; - } -+ } // Paper - } - - this.level.getProfiler().incrementCounter("chunkSave"); -- CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk); -+ CompoundTag nbttagcompound; -+ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper -+ nbttagcompound = ChunkSerializer.write(this.level, chunk); -+ } // Paper - -- this.write(chunkcoordintpair, nbttagcompound); -+ -+ // Paper start - async chunk io -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z, -+ null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); -+ // Paper end - async chunk io - this.markPosition(chunkcoordintpair, chunkstatus.getChunkType()); - return true; - } catch (Exception exception) { -@@ -923,6 +1031,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return false; - } - } -+ } // Paper - } - - private boolean isExistingChunkFull(ChunkPos chunkcoordintpair) { -@@ -1052,6 +1161,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - } - -+ // Paper start - Asynchronous chunk io -+ @Nullable -+ @Override -+ public CompoundTag read(ChunkPos chunkcoordintpair) throws IOException { -+ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .loadChunkDataAsyncFuture(this.level, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), -+ false, true, true).join().chunkData; -+ -+ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { -+ throw new IOException("See logs for further detail"); -+ } -+ return ret; -+ } -+ return super.read(chunkcoordintpair); -+ } -+ -+ @Override -+ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { -+ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( -+ this.level, chunkcoordintpair.x, chunkcoordintpair.z, null, nbttagcompound, -+ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); -+ return; -+ } -+ super.write(chunkcoordintpair, nbttagcompound); -+ } -+ // Paper end -+ - @Nullable - public CompoundTag readChunk(ChunkPos pos) throws IOException { // Paper - private -> public - CompoundTag nbttagcompound = this.read(pos); -@@ -1073,33 +1211,55 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - // Paper start - chunk status cache "api" - public ChunkStatus getChunkStatusOnDiskIfCached(ChunkPos chunkPos) { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); -+ synchronized (this) { // Paper -+ RegionFile regionFile = this.regionFileCache.getRegionFileIfLoaded(chunkPos); - - return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } // Paper - } - - public ChunkStatus getChunkStatusOnDisk(ChunkPos chunkPos) throws IOException { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); -+ // Paper start - async chunk save for unload -+ ChunkAccess unloadingChunk = this.level.asyncChunkTaskManager.getChunkInSaveProgress(chunkPos.x, chunkPos.z); -+ if (unloadingChunk != null) { -+ return unloadingChunk.getStatus(); -+ } -+ // Paper end -+ // Paper start - async io -+ CompoundTag inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .getPendingWrite(this.level, chunkPos.x, chunkPos.z, false); - -- if (regionFile == null || !regionFile.chunkExists(chunkPos)) { -- return null; -+ if (inProgressWrite != null) { -+ return ChunkSerializer.getStatus(inProgressWrite); - } -+ // Paper end -+ synchronized (this) { // Paper - async io -+ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, true); -+ -+ if (regionFile == null || !regionFile.hasChunk(chunkPos)) { -+ return null; -+ } - -- ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); - -- if (status != null) { -- return status; -+ if (status != null) { -+ return status; -+ } -+ // Paper start - async io - } - -- this.readChunk(chunkPos); -+ CompoundTag compound = this.readChunk(chunkPos); - -- return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ return ChunkSerializer.getStatus(compound); -+ // Paper end - } - - public void updateChunkStatusOnDisk(ChunkPos chunkPos, @Nullable CompoundTag compound) throws IOException { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ synchronized (this) { -+ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, false); - -- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); -+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); -+ } - } - - public ChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { -@@ -1108,6 +1268,39 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - // Paper end - -+ -+ // Paper start - async io -+ // this function will not load chunk data off disk to check for status -+ // ret null for unknown, empty for empty status on disk or absent from disk -+ public ChunkStatus getStatusOnDiskNoLoad(int x, int z) { -+ // Paper start - async chunk save for unload -+ ChunkAccess unloadingChunk = this.level.asyncChunkTaskManager.getChunkInSaveProgress(x, z); -+ if (unloadingChunk != null) { -+ return unloadingChunk.getStatus(); -+ } -+ // Paper end -+ // Paper start - async io -+ CompoundTag inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .getPendingWrite(this.level, x, z, false); -+ -+ if (inProgressWrite != null) { -+ return ChunkSerializer.getStatus(inProgressWrite); -+ } -+ // Paper end -+ // variant of PlayerChunkMap#getChunkStatusOnDisk that does not load data off disk, but loads the region file -+ ChunkPos chunkPos = new ChunkPos(x, z); -+ synchronized (level.getChunkSource().chunkMap) { -+ RegionFile file; -+ try { -+ file = level.getChunkSource().chunkMap.regionFileCache.getFile(chunkPos, false); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return !file.hasChunk(chunkPos) ? ChunkStatus.EMPTY : file.getStatusIfCached(x, z); -+ } -+ } -+ - boolean noPlayersCloseForSpawning(ChunkPos chunkcoordintpair) { - // Spigot start - return isOutsideOfRange(chunkcoordintpair, false); -@@ -1454,6 +1647,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - } - -+ public PoiManager getVillagePlace() { return this.getPoiManager(); } // Paper - OBFHELPER - protected PoiManager getPoiManager() { - return this.poiManager; - } -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index c1aa40c01a80a8870478193b8cd7354b0d71045c..120b604d91643248ab375969f95f62a74cbf6be7 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -37,6 +37,7 @@ import net.minecraft.world.level.chunk.ChunkAccess; - import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.chunk.ChunkSource; - import net.minecraft.world.level.chunk.ChunkStatus; -+import net.minecraft.world.level.chunk.ImposterProtoChunk; - import net.minecraft.world.level.chunk.LevelChunk; - import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; - import net.minecraft.world.level.storage.DimensionDataStorage; -@@ -332,11 +333,138 @@ public class ServerChunkCache extends ChunkSource { - return playerChunk.getAvailableChunkNow(); - - } -+ -+ private long asyncLoadSeqCounter; -+ -+ public CompletableFuture> getChunkAtAsynchronously(int x, int z, boolean gen, boolean isUrgent) { -+ if (Thread.currentThread() != this.mainThread) { -+ CompletableFuture> future = new CompletableFuture>(); -+ this.mainThreadProcessor.execute(() -> { -+ this.getChunkAtAsynchronously(x, z, gen, isUrgent).whenComplete((chunk, ex) -> { -+ if (ex != null) { -+ future.completeExceptionally(ex); -+ } else { -+ future.complete(chunk); -+ } -+ }); -+ }); -+ return future; -+ } -+ -+ if (!com.destroystokyo.paper.PaperConfig.asyncChunks) { -+ level.getWorld().loadChunk(x, z, gen); -+ LevelChunk chunk = getChunkAtIfLoadedMainThread(x, z); -+ return CompletableFuture.completedFuture(chunk != null ? Either.left(chunk) : ChunkHolder.UNLOADED_CHUNK); -+ } -+ -+ long k = ChunkPos.asLong(x, z); -+ ChunkPos chunkPos = new ChunkPos(x, z); -+ -+ ChunkAccess ichunkaccess; -+ -+ // try cache -+ for (int l = 0; l < 4; ++l) { -+ if (k == this.lastChunkPos[l] && ChunkStatus.FULL == this.lastChunkStatus[l]) { -+ ichunkaccess = this.lastChunk[l]; -+ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime -+ -+ // move to first in cache -+ -+ for (int i1 = 3; i1 > 0; --i1) { -+ this.lastChunkPos[i1] = this.lastChunkPos[i1 - 1]; -+ this.lastChunkStatus[i1] = this.lastChunkStatus[i1 - 1]; -+ this.lastChunk[i1] = this.lastChunk[i1 - 1]; -+ } -+ -+ this.lastChunkPos[0] = k; -+ this.lastChunkStatus[0] = ChunkStatus.FULL; -+ this.lastChunk[0] = ichunkaccess; -+ -+ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); -+ } -+ } -+ } -+ -+ if (gen) { -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ ChunkAccess current = this.getChunkAtImmediately(x, z); // we want to bypass ticket restrictions -+ if (current != null) { -+ if (!(current instanceof ImposterProtoChunk) && !(current instanceof LevelChunk)) { -+ return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); -+ } -+ // we know the chunk is at full status here (either in read-only mode or the real thing) -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ ChunkStatus status = level.getChunkSource().chunkMap.getStatusOnDiskNoLoad(x, z); -+ -+ if (status != null && status != ChunkStatus.FULL) { -+ // does not exist on disk -+ return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); -+ } -+ -+ if (status == ChunkStatus.FULL) { -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ // status is null here -+ -+ // here we don't know what status it is and we're not supposed to generate -+ // so we asynchronously load empty status -+ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.EMPTY, isUrgent).thenCompose((either) -> { -+ ChunkAccess chunk = either.left().orElse(null); -+ if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof LevelChunk)) { -+ // the chunk on disk was not a full status chunk -+ return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); -+ } -+ ; // bring to full status if required -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ }); -+ } -+ -+ private CompletableFuture> bringToFullStatusAsync(int x, int z, ChunkPos chunkPos, boolean isUrgent) { -+ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.FULL, isUrgent); -+ } -+ -+ private CompletableFuture> bringToStatusAsync(int x, int z, ChunkPos chunkPos, ChunkStatus status, boolean isUrgent) { -+ CompletableFuture> future = this.getChunkFutureMainThread(x, z, status, true, isUrgent); -+ Long identifier = Long.valueOf(this.asyncLoadSeqCounter++); -+ int ticketLevel = MCUtil.getTicketLevelFor(status); -+ this.addTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); -+ -+ return future.thenComposeAsync((Either either) -> { -+ // either left -> success -+ // either right -> failure -+ -+ this.removeTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); -+ this.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); // allow unloading -+ -+ Optional failure = either.right(); -+ -+ if (failure.isPresent()) { -+ // failure -+ throw new IllegalStateException("Chunk failed to load: " + failure.get().toString()); -+ } -+ -+ return CompletableFuture.completedFuture(either); -+ }, this.mainThreadProcessor); -+ } -+ -+ public void addTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { -+ this.distanceManager.addTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); -+ } -+ -+ public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { -+ this.distanceManager.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); -+ } - // Paper end - - @Nullable - @Override - public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) { -+ final int x1 = x; final int z1 = z; // Paper - conflict on variable change - if (Thread.currentThread() != this.mainThread) { - return (ChunkAccess) CompletableFuture.supplyAsync(() -> { - return this.getChunk(x, z, leastStatus, create); -@@ -359,11 +487,16 @@ public class ServerChunkCache extends ChunkSource { - } - - gameprofilerfiller.incrementCounter("getChunkCacheMiss"); -- CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); -+ CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper - - if (!completablefuture.isDone()) { // Paper -+ // Paper start - async chunk io/loading -+ this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); -+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); -+ // Paper end - this.level.timings.syncChunkLoad.startTiming(); // Paper - this.mainThreadProcessor.managedBlock(completablefuture::isDone); -+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug - this.level.timings.syncChunkLoad.stopTiming(); // Paper - } // Paper - ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { -@@ -429,9 +562,14 @@ public class ServerChunkCache extends ChunkSource { - } - - private CompletableFuture> getChunkFutureMainThread(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { -- ChunkPos chunkcoordintpair = new ChunkPos(chunkX, chunkZ); -+ // Paper start - add isUrgent - old sig left in place for dirty nms plugins -+ return getChunkFutureMainThread(chunkX, chunkZ, leastStatus, create, false); -+ } -+ private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag, boolean isUrgent) { -+ // Paper end -+ ChunkPos chunkcoordintpair = new ChunkPos(i, j); - long k = chunkcoordintpair.toLong(); -- int l = 33 + ChunkStatus.getDistance(leastStatus); -+ int l = 33 + ChunkStatus.getDistance(chunkstatus); - ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); - - // CraftBukkit start - don't add new ticket for currently unloading chunk -@@ -441,7 +579,7 @@ public class ServerChunkCache extends ChunkSource { - ChunkHolder.FullChunkStatus currentChunkState = ChunkHolder.getFullChunkStatus(playerchunk.getTicketLevel()); - currentlyUnloading = (oldChunkState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !currentChunkState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)); - } -- if (create && !currentlyUnloading) { -+ if (flag && !currentlyUnloading) { - // CraftBukkit end - this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); - if (this.chunkAbsent(playerchunk, l)) { -@@ -457,7 +595,7 @@ public class ServerChunkCache extends ChunkSource { - } - } - -- return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(leastStatus, this.chunkMap); -+ return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkstatus, this.chunkMap); - } - - private boolean chunkAbsent(@Nullable ChunkHolder holder, int maxLevel) { -@@ -831,11 +969,12 @@ public class ServerChunkCache extends ChunkSource { - protected boolean pollTask() { - // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task - try { -+ boolean execChunkTask = com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ServerChunkCache.this.level.asyncChunkTaskManager.pollNextChunkTask(); // Paper - if (ServerChunkCache.this.runDistanceManagerUpdates()) { - return true; - } else { - ServerChunkCache.this.lightEngine.tryScheduleUpdate(); -- return super.pollTask(); -+ return super.pollTask() || execChunkTask; // Paper - } - } finally { - chunkMap.callbackExecutor.run(); -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index a811ced17721b70bb51837f47e466c2261db2466..95eff4f6165024d21e5c4268a9ae1b7a4268de4b 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -51,6 +51,7 @@ import net.minecraft.core.RegistryAccess; - import net.minecraft.core.SectionPos; - import net.minecraft.core.Vec3i; - import net.minecraft.core.particles.ParticleOptions; -+import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.network.protocol.Packet; -@@ -122,6 +123,7 @@ import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.LevelChunk; - import net.minecraft.world.level.chunk.LevelChunkSection; -+import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.dimension.DimensionType; - import net.minecraft.world.level.dimension.end.EndDragonFight; - import net.minecraft.world.level.levelgen.Heightmap; -@@ -202,6 +204,79 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return this.chunkSource.getChunk(x, z, false); - } - -+ // Paper start - Asynchronous IO -+ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController poiDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { -+ @Override -+ public void writeData(int x, int z, CompoundTag compound) throws java.io.IOException { -+ ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().write(new ChunkPos(x, z), compound); -+ } -+ -+ @Override -+ public CompoundTag readData(int x, int z) throws java.io.IOException { -+ return ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().read(new ChunkPos(x, z)); -+ } -+ -+ @Override -+ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (ServerLevel.this.getChunkSource().chunkMap.getVillagePlace()) { -+ RegionFile file; -+ -+ try { -+ file = ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().getFile(new ChunkPos(chunkX, chunkZ), false); -+ } catch (java.io.IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return function.apply(file); -+ } -+ } -+ -+ @Override -+ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (ServerLevel.this.getChunkSource().chunkMap.getVillagePlace()) { -+ RegionFile file = ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().getRegionFileIfLoaded(new ChunkPos(chunkX, chunkZ)); -+ return function.apply(file); -+ } -+ } -+ }; -+ -+ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController chunkDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { -+ @Override -+ public void writeData(int x, int z, CompoundTag compound) throws java.io.IOException { -+ ServerLevel.this.getChunkSource().chunkMap.write(new ChunkPos(x, z), compound); -+ } -+ -+ @Override -+ public CompoundTag readData(int x, int z) throws java.io.IOException { -+ return ServerLevel.this.getChunkSource().chunkMap.read(new ChunkPos(x, z)); -+ } -+ -+ @Override -+ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (ServerLevel.this.getChunkSource().chunkMap) { -+ RegionFile file; -+ -+ try { -+ file = ServerLevel.this.getChunkSource().chunkMap.regionFileCache.getFile(new ChunkPos(chunkX, chunkZ), false); -+ } catch (java.io.IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return function.apply(file); -+ } -+ } -+ -+ @Override -+ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (ServerLevel.this.getChunkSource().chunkMap) { -+ RegionFile file = ServerLevel.this.getChunkSource().chunkMap.regionFileCache.getRegionFileIfLoaded(new ChunkPos(chunkX, chunkZ)); -+ return function.apply(file); -+ } -+ } -+ }; -+ public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; -+ // Paper end -+ - // Add env and gen to constructor, WorldData -> WorldDataServer - public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor -@@ -249,6 +324,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.dragonFight = null; - } - this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit -+ -+ this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper - } - - // CraftBukkit start -@@ -1737,7 +1814,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - MCUtil.getSpiralOutChunks(spawn, radiusInBlocks >> 4).forEach(pair -> { -- getChunkSource().getChunkAtMainThread(pair.x, pair.z); -+ getChunkSource().getChunkAtAsynchronously(pair.x, pair.z, true, false).exceptionally((ex) -> { -+ ex.printStackTrace(); -+ return null; -+ }); - }); - } - public void removeTicketsForSpawn(int radiusInBlocks, BlockPos spawn) { -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index cf3ced15c9a87e7a4dbccba17c57a7b32b77566c..d09e4857b6c40410d134fa81b48e95919a7373bd 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -26,6 +26,7 @@ public class TicketType { - public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit - public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit - public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper -+ public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper - - public static TicketType create(String name, Comparator comparator) { - return new TicketType<>(name, comparator, 0L); -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 4f99c3d06e3b994708c699395adf481a6828e097..5dd99709d6b0ed15bbcee184fe33a28bc1c19dac 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -728,6 +728,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper - return; - } -+ // Paper start -+ String str = packet.getCommand(); int index = -1; -+ if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { -+ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper -+ return; -+ } -+ // Paper end - // CraftBukkit end - StringReader stringreader = new StringReader(packet.getCommand()); - -diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -index e48fcfe2e4ff151258ae1d84cc0995d2cd54e9a6..a5ce61be7d6e85ac289730d9671e66a7190529f9 100644 ---- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -+++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -@@ -91,7 +91,7 @@ public abstract class BlockableEventLoop implements Processo - - } - -- protected void runAllTasks() { -+ public void runAllTasks() { // Paper - protected -> public - while (this.pollTask()) { - ; - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -index 33a8604fa6c6431ccc5f61e484c163e09f1625a0..d082af8cf4c0c7ca434598aa370712c62e05bb24 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -@@ -22,7 +22,9 @@ import java.util.stream.Stream; - import net.minecraft.Util; - import net.minecraft.core.BlockPos; - import net.minecraft.core.SectionPos; -+import net.minecraft.nbt.CompoundTag; - import net.minecraft.server.level.SectionTracker; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.LevelReader; -@@ -36,8 +38,16 @@ public class PoiManager extends SectionStorage { - private final PoiManager.DistanceTracker distanceTracker = new PoiManager.DistanceTracker(); - private final LongSet loadedChunks = new LongOpenHashSet(); - -+ private final ServerLevel world; // Paper -+ - public PoiManager(File directory, DataFixer datafixer, boolean flag) { -- super(directory, PoiSection::codec, PoiSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); -+ // Paper start - add world parameter -+ this(directory, datafixer, flag, null); -+ } -+ public PoiManager(File file, DataFixer datafixer, boolean flag, ServerLevel world) { -+ super(file, PoiSection::codec, PoiSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); -+ this.world = world; -+ // Paper end - add world parameter - } - - public void add(BlockPos pos, PoiType type) { -@@ -155,7 +165,23 @@ public class PoiManager extends SectionStorage { - - @Override - public void tick(BooleanSupplier shouldKeepTicking) { -- super.tick(shouldKeepTicking); -+ // Paper start - async chunk io -+ if (this.world == null) { -+ super.tick(shouldKeepTicking); -+ } else { -+ //super.a(booleansupplier); // re-implement below -+ while (!((SectionStorage)this).dirty.isEmpty() && shouldKeepTicking.getAsBoolean()) { -+ ChunkPos chunkcoordintpair = SectionPos.of(((SectionStorage)this).dirty.firstLong()).chunk(); -+ -+ CompoundTag data; -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) { -+ data = this.getData(chunkcoordintpair); -+ } -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, -+ chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); -+ } -+ } -+ // Paper end - this.distanceTracker.runAllUpdates(); - } - -@@ -255,6 +281,35 @@ public class PoiManager extends SectionStorage { - } - } - -+ // Paper start - Asynchronous chunk io -+ @javax.annotation.Nullable -+ @Override -+ public CompoundTag read(ChunkPos chunkcoordintpair) throws java.io.IOException { -+ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), -+ true, false, true).join().poiData; -+ -+ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { -+ throw new java.io.IOException("See logs for further detail"); -+ } -+ return ret; -+ } -+ return super.read(chunkcoordintpair); -+ } -+ -+ @Override -+ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws java.io.IOException { -+ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( -+ this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, -+ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); -+ return; -+ } -+ super.write(chunkcoordintpair, nbttagcompound); -+ } -+ // Paper end -+ - public static enum Occupancy { - - HAS_SPACE(PoiRecord::hasSpace), IS_OCCUPIED(PoiRecord::isOccupied), ANY((villageplacerecord) -> { -diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java -index d97e266b83bb331fcd4031046a5843d29ce53164..90833389022d7412bdda8868a356b84f62a00e03 100644 ---- a/src/main/java/net/minecraft/world/level/TickNextTickData.java -+++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java -@@ -5,7 +5,7 @@ import net.minecraft.core.BlockPos; - - public class TickNextTickData { - -- private static long counter; -+ private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading - private final T type; - public final BlockPos pos; - public final long triggerTick; -@@ -17,7 +17,7 @@ public class TickNextTickData { - } - - public TickNextTickData(BlockPos pos, T t, long time, TickPriority priority) { -- this.c = (long) (TickNextTickData.counter++); -+ this.c = (long) (TickNextTickData.COUNTER.getAndIncrement()); // Paper - async chunk loading - this.pos = pos.immutable(); - this.type = t; - this.triggerTick = time; -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -index 46d5a24332c1fd3c164b760ec2a2d5bf859b1ab6..3c85b0d39a3fc5c8ec073d92f48b360c0b0be245 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -@@ -170,6 +170,7 @@ public class ChunkStatus { - return ChunkStatus.STATUS_BY_RANGE.size(); - } - -+ public static int getTicketLevelOffset(ChunkStatus status) { return ChunkStatus.getDistance(status); } // Paper - OBFHELPER - public static int getDistance(ChunkStatus status) { - return ChunkStatus.RANGE_BY_STATUS.getInt(status.getIndex()); - } -@@ -185,6 +186,7 @@ public class ChunkStatus { - this.index = previous == null ? 0 : previous.getIndex() + 1; - } - -+ public final int getStatusIndex() { return getIndex(); } // Paper - OBFHELPER - public int getIndex() { - return this.index; - } -@@ -193,7 +195,7 @@ public class ChunkStatus { - return this.name; - } - -- public ChunkStatus getPreviousStatus() { return this.getParent(); } // Paper - OBFHELPER -+ public final ChunkStatus getPreviousStatus() { return this.getParent(); } // Paper - OBFHELPER - public ChunkStatus getParent() { - return this.parent; - } -@@ -206,6 +208,7 @@ public class ChunkStatus { - return this.loadingTask.doWork(this, world, structureManager, lightingProvider, function, chunk); - } - -+ public final int getNeighborRadius() { return this.getRange(); } // Paper - OBFHELPER - public int getRange() { - return this.range; - } -@@ -233,6 +236,7 @@ public class ChunkStatus { - return this.heightmapsAfter; - } - -+ public final boolean isAtLeastStatus(ChunkStatus chunkstatus) { return isOrAfter(chunkstatus); } // Paper - OBFHELPER - public boolean isOrAfter(ChunkStatus chunk) { - return this.getIndex() >= chunk.getIndex(); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java -index 808f69a10589a4a7d6c238c05f6d3e0f272681d3..2b798f4e556302f6f79d54182a309f4716a84f04 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java -@@ -73,6 +73,7 @@ public class DataLayer { - return this.data; - } - -+ public DataLayer copy() { return this.copy(); } // Paper - OBFHELPER - public DataLayer copy() { - return this.data == null ? new DataLayer() : new DataLayer((byte[]) this.data.clone()); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2..be67dc16bf70e4517efd213ca9002f116f60b57c 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet; - import it.unimi.dsi.fastutil.longs.LongSet; - import it.unimi.dsi.fastutil.shorts.ShortList; - import it.unimi.dsi.fastutil.shorts.ShortListIterator; -+import java.util.ArrayDeque; // Paper - import java.util.Arrays; - import java.util.BitSet; - import java.util.EnumSet; -@@ -66,34 +67,58 @@ public class ChunkSerializer { - - private static final Logger LOGGER = LogManager.getLogger(); - -+ // Paper start -+ public static final class InProgressChunkHolder { -+ -+ public final ProtoChunk protoChunk; -+ public final ArrayDeque tasks; -+ -+ public CompoundTag poiData; -+ -+ public InProgressChunkHolder(final ProtoChunk protoChunk, final ArrayDeque tasks) { -+ this.protoChunk = protoChunk; -+ this.tasks = tasks; -+ } -+ } -+ - public static ProtoChunk read(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag tag) { -- ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); -+ InProgressChunkHolder holder = loadChunk(world, structureManager, poiStorage, pos, tag, true); -+ holder.tasks.forEach(Runnable::run); -+ return holder.protoChunk; -+ } -+ -+ public static InProgressChunkHolder loadChunk(ServerLevel worldserver, StructureManager definedstructuremanager, PoiManager villageplace, ChunkPos chunkcoordintpair, CompoundTag nbttagcompound, boolean distinguish) { -+ ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); -+ // Paper end -+ ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); - BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); -- CompoundTag nbttagcompound1 = tag.getCompound("Level"); -+ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); - ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); - -- if (!Objects.equals(pos, chunkcoordintpair1)) { -- ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", pos, pos, chunkcoordintpair1); -+ if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { -+ ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); - } - -- ChunkBiomeContainer biomestorage = new ChunkBiomeContainer(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), pos, worldchunkmanager, nbttagcompound1.contains("Biomes", 11) ? nbttagcompound1.getIntArray("Biomes") : null); -+ ChunkBiomeContainer biomestorage = new ChunkBiomeContainer(worldserver.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunkcoordintpair, worldchunkmanager, nbttagcompound1.contains("Biomes", 11) ? nbttagcompound1.getIntArray("Biomes") : null); - UpgradeData chunkconverter = nbttagcompound1.contains("UpgradeData", 10) ? new UpgradeData(nbttagcompound1.getCompound("UpgradeData")) : UpgradeData.EMPTY; - ProtoTickList protochunkticklist = new ProtoTickList<>((block) -> { - return block == null || block.defaultBlockState().isAir(); -- }, pos, nbttagcompound1.getList("ToBeTicked", 9)); -+ }, chunkcoordintpair, nbttagcompound1.getList("ToBeTicked", 9)); - ProtoTickList protochunkticklist1 = new ProtoTickList<>((fluidtype) -> { - return fluidtype == null || fluidtype == Fluids.EMPTY; -- }, pos, nbttagcompound1.getList("LiquidsToBeTicked", 9)); -+ }, chunkcoordintpair, nbttagcompound1.getList("LiquidsToBeTicked", 9)); - boolean flag = nbttagcompound1.getBoolean("isLightOn"); - ListTag nbttaglist = nbttagcompound1.getList("Sections", 10); - boolean flag1 = true; - LevelChunkSection[] achunksection = new LevelChunkSection[16]; -- boolean flag2 = world.dimensionType().hasSkyLight(); -- ServerChunkCache chunkproviderserver = world.getChunkSource(); -+ boolean flag2 = worldserver.dimensionType().hasSkyLight(); -+ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); - LevelLightEngine lightengine = chunkproviderserver.getLightEngine(); - - if (flag) { -- lightengine.retainData(pos, true); -+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main -+ lightengine.retainData(chunkcoordintpair, true); -+ }); // Paper - delay this task since we're executing off-main - } - - for (int i = 0; i < nbttaglist.size(); ++i) { -@@ -101,7 +126,7 @@ public class ChunkSerializer { - byte b0 = nbttagcompound2.getByte("Y"); - - if (nbttagcompound2.contains("Palette", 9) && nbttagcompound2.contains("BlockStates", 12)) { -- LevelChunkSection chunksection = new LevelChunkSection(b0 << 4, null, world, false); // Paper - Anti-Xray - Add parameters -+ LevelChunkSection chunksection = new LevelChunkSection(b0 << 4, null, worldserver, false); // Paper - Anti-Xray - Add parameters - - chunksection.getStates().read(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); - chunksection.recalcBlockCounts(); -@@ -109,22 +134,34 @@ public class ChunkSerializer { - achunksection[b0] = chunksection; - } - -- poiStorage.checkConsistencyWithBlocks(pos, chunksection); -+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main -+ villageplace.checkConsistencyWithBlocks(chunkcoordintpair, chunksection); -+ }); // Paper - delay this task since we're executing off-main - } - - if (flag) { - if (nbttagcompound2.contains("BlockLight", 7)) { -- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("BlockLight")), true); -+ // Paper start - delay this task since we're executing off-main -+ DataLayer blockLight = new DataLayer(nbttagcompound2.getByteArray("BlockLight")); -+ tasksToExecuteOnMain.add(() -> { -+ lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair, b0), blockLight, true); -+ }); -+ // Paper end - delay this task since we're executing off-main - } - - if (flag2 && nbttagcompound2.contains("SkyLight", 7)) { -- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("SkyLight")), true); -+ // Paper start - delay this task since we're executing off-main -+ DataLayer skyLight = new DataLayer(nbttagcompound2.getByteArray("SkyLight")); -+ tasksToExecuteOnMain.add(() -> { -+ lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkcoordintpair, b0), skyLight, true); -+ }); -+ // Paper end - delay this task since we're executing off-main - } - } - } - - long j = nbttagcompound1.getLong("InhabitedTime"); -- ChunkStatus.ChunkType chunkstatus_type = getChunkTypeFromTag(tag); -+ ChunkStatus.ChunkType chunkstatus_type = getChunkTypeFromTag(nbttagcompound); - Object object; - - if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) { -@@ -155,7 +192,7 @@ public class ChunkSerializer { - object2 = protochunkticklist1; - } - -- object = new LevelChunk(world.getLevel(), pos, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { -+ object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { - postLoadChunk(nbttagcompound1, chunk); - // CraftBukkit start - load chunk persistent data from nbt - net.minecraft.nbt.Tag persistentBase = nbttagcompound1.get("ChunkBukkitValues"); -@@ -165,7 +202,7 @@ public class ChunkSerializer { - // CraftBukkit end - }); - } else { -- ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world); // Paper - Anti-Xray - Add parameter -+ ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter - - protochunk.setBiomes(biomestorage); - object = protochunk; -@@ -176,7 +213,7 @@ public class ChunkSerializer { - } - - if (!flag && protochunk.getStatus().isOrAfter(ChunkStatus.LIGHT)) { -- Iterator iterator = BlockPos.betweenClosed(pos.getMinBlockX(), 0, pos.getMinBlockZ(), pos.getMaxBlockX(), 255, pos.getMaxBlockZ()).iterator(); -+ Iterator iterator = BlockPos.betweenClosed(chunkcoordintpair.getMinBlockX(), 0, chunkcoordintpair.getMinBlockZ(), chunkcoordintpair.getMaxBlockX(), 255, chunkcoordintpair.getMaxBlockZ()).iterator(); - - while (iterator.hasNext()) { - BlockPos blockposition = (BlockPos) iterator.next(); -@@ -207,8 +244,8 @@ public class ChunkSerializer { - Heightmap.primeHeightmaps((ChunkAccess) object, enumset); - CompoundTag nbttagcompound4 = nbttagcompound1.getCompound("Structures"); - -- ((ChunkAccess) object).setAllStarts(unpackStructureStart(structureManager, nbttagcompound4, world.getSeed())); -- ((ChunkAccess) object).setAllReferences(unpackStructureReferences(pos, nbttagcompound4)); -+ ((ChunkAccess) object).setAllStarts(unpackStructureStart(definedstructuremanager, nbttagcompound4, worldserver.getSeed())); -+ ((ChunkAccess) object).setAllReferences(unpackStructureReferences(chunkcoordintpair, nbttagcompound4)); - if (nbttagcompound1.getBoolean("shouldSave")) { - ((ChunkAccess) object).setUnsaved(true); - } -@@ -227,7 +264,7 @@ public class ChunkSerializer { - } - - if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) { -- return new ImposterProtoChunk((LevelChunk) object); -+ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading - } else { - ProtoChunk protochunk1 = (ProtoChunk) object; - -@@ -266,12 +303,84 @@ public class ChunkSerializer { - protochunk1.setCarvingMask(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1))); - } - -- return protochunk1; -+ return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading - } - } - -+ // Paper start - async chunk save for unload -+ public static final class AsyncSaveData { -+ public final DataLayer[] blockLight; // null or size of 17 (for indices -1 through 15) -+ public final DataLayer[] skyLight; -+ -+ public final ListTag blockTickList; // non-null if we had to go to the server's tick list -+ public final ListTag fluidTickList; // non-null if we had to go to the server's tick list -+ -+ public final long worldTime; -+ -+ public AsyncSaveData(DataLayer[] blockLight, DataLayer[] skyLight, ListTag blockTickList, ListTag fluidTickList, -+ long worldTime) { -+ this.blockLight = blockLight; -+ this.skyLight = skyLight; -+ this.blockTickList = blockTickList; -+ this.fluidTickList = fluidTickList; -+ this.worldTime = worldTime; -+ } -+ } -+ -+ // must be called sync -+ public static AsyncSaveData getAsyncSaveData(ServerLevel world, ChunkAccess chunk) { -+ org.spigotmc.AsyncCatcher.catchOp("preparation of chunk data for async save"); -+ ChunkPos chunkPos = chunk.getPos(); -+ -+ ThreadedLevelLightEngine lightenginethreaded = world.getChunkSource().getLightEngine(); -+ -+ DataLayer[] blockLight = new DataLayer[17 - (-1)]; -+ DataLayer[] skyLight = new DataLayer[17 - (-1)]; -+ -+ for (int i = -1; i < 17; ++i) { -+ DataLayer blockArray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkPos, i)); -+ DataLayer skyArray = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkPos, i)); -+ -+ // copy data for safety -+ if (blockArray != null) { -+ blockArray = blockArray.copy(); -+ } -+ if (skyArray != null) { -+ skyArray = skyArray.copy(); -+ } -+ -+ // apply offset of 1 for -1 starting index -+ blockLight[i + 1] = blockArray; -+ skyLight[i + 1] = skyArray; -+ } -+ -+ TickList blockTickList = chunk.getBlockTicks(); -+ -+ ListTag blockTickListSerialized; -+ if (blockTickList instanceof ProtoTickList || blockTickList instanceof ChunkTickList) { -+ blockTickListSerialized = null; -+ } else { -+ blockTickListSerialized = world.getBlockTicks().save(chunkPos); -+ } -+ -+ TickList fluidTickList = chunk.getLiquidTicks(); -+ -+ ListTag fluidTickListSerialized; -+ if (fluidTickList instanceof ProtoTickList || fluidTickList instanceof ChunkTickList) { -+ fluidTickListSerialized = null; -+ } else { -+ fluidTickListSerialized = world.getLiquidTicks().save(chunkPos); -+ } -+ -+ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, world.getGameTime()); -+ } -+ - public static CompoundTag write(ServerLevel world, ChunkAccess chunk) { -- ChunkPos chunkcoordintpair = chunk.getPos(); -+ return saveChunk(world, chunk, null); -+ } -+ public static CompoundTag saveChunk(ServerLevel worldserver, ChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { -+ // Paper end -+ ChunkPos chunkcoordintpair = ichunkaccess.getPos(); - CompoundTag nbttagcompound = new CompoundTag(); - CompoundTag nbttagcompound1 = new CompoundTag(); - -@@ -279,30 +388,38 @@ public class ChunkSerializer { - nbttagcompound.put("Level", nbttagcompound1); - nbttagcompound1.putInt("xPos", chunkcoordintpair.x); - nbttagcompound1.putInt("zPos", chunkcoordintpair.z); -- nbttagcompound1.putLong("LastUpdate", world.getGameTime()); -- nbttagcompound1.putLong("InhabitedTime", chunk.getInhabitedTime()); -- nbttagcompound1.putString("Status", chunk.getStatus().getName()); -- UpgradeData chunkconverter = chunk.getUpgradeData(); -+ nbttagcompound1.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getGameTime()); // Paper - async chunk unloading -+ nbttagcompound1.putLong("InhabitedTime", ichunkaccess.getInhabitedTime()); -+ nbttagcompound1.putString("Status", ichunkaccess.getStatus().getName()); -+ UpgradeData chunkconverter = ichunkaccess.getUpgradeData(); - - if (!chunkconverter.isEmpty()) { - nbttagcompound1.put("UpgradeData", chunkconverter.write()); - } - -- LevelChunkSection[] achunksection = chunk.getSections(); -+ LevelChunkSection[] achunksection = ichunkaccess.getSections(); - ListTag nbttaglist = new ListTag(); -- ThreadedLevelLightEngine lightenginethreaded = world.getChunkSource().getLightEngine(); -- boolean flag = chunk.isLightCorrect(); -+ ThreadedLevelLightEngine lightenginethreaded = worldserver.getChunkSource().getLightEngine(); -+ boolean flag = ichunkaccess.isLightCorrect(); - - CompoundTag nbttagcompound2; - -- for (int i = -1; i < 17; ++i) { -+ for (int i = -1; i < 17; ++i) { // Paper - conflict on loop parameter change - int finalI = i; // CraftBukkit - decompile errors - LevelChunkSection chunksection = (LevelChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { - return chunksection1 != null && chunksection1.bottomBlockY() >> 4 == finalI; // CraftBukkit - decompile errors - }).findFirst().orElse(LevelChunk.EMPTY_SECTION); -- DataLayer nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); -- DataLayer nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); -- -+ // Paper start - async chunk save for unload -+ DataLayer nibblearray; // block light -+ DataLayer nibblearray1; // sky light -+ if (asyncsavedata == null) { -+ nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); /// Paper - diff on method change (see getAsyncSaveData) -+ nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); // Paper - diff on method change (see getAsyncSaveData) -+ } else { -+ nibblearray = asyncsavedata.blockLight[i + 1]; // +1 to offset the -1 starting index -+ nibblearray1 = asyncsavedata.skyLight[i + 1]; // +1 to offset the -1 starting index -+ } -+ // Paper end - if (chunksection != LevelChunk.EMPTY_SECTION || nibblearray != null || nibblearray1 != null) { - nbttagcompound2 = new CompoundTag(); - nbttagcompound2.putByte("Y", (byte) (i & 255)); -@@ -327,21 +444,21 @@ public class ChunkSerializer { - nbttagcompound1.putBoolean("isLightOn", true); - } - -- ChunkBiomeContainer biomestorage = chunk.getBiomes(); -+ ChunkBiomeContainer biomestorage = ichunkaccess.getBiomes(); - - if (biomestorage != null) { - nbttagcompound1.putIntArray("Biomes", biomestorage.writeBiomes()); - } - - ListTag nbttaglist1 = new ListTag(); -- Iterator iterator = chunk.getBlockEntitiesPos().iterator(); -+ Iterator iterator = ichunkaccess.getBlockEntitiesPos().iterator(); - - CompoundTag nbttagcompound3; - - while (iterator.hasNext()) { - BlockPos blockposition = (BlockPos) iterator.next(); - -- nbttagcompound3 = chunk.getBlockEntityNbtForSaving(blockposition); -+ nbttagcompound3 = ichunkaccess.getBlockEntityNbtForSaving(blockposition); - if (nbttagcompound3 != null) { - nbttaglist1.add(nbttagcompound3); - } -@@ -351,25 +468,25 @@ public class ChunkSerializer { - ListTag nbttaglist2 = new ListTag(); - - java.util.List toUpdate = new java.util.ArrayList<>(); // Paper -- if (chunk.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { -- LevelChunk chunk1 = (LevelChunk) chunk; -+ if (ichunkaccess.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { -+ LevelChunk chunk = (LevelChunk) ichunkaccess; - - // CraftBukkit start - store chunk persistent data in nbt -- if (!chunk1.persistentDataContainer.isEmpty()) { -- nbttagcompound1.put("ChunkBukkitValues", chunk1.persistentDataContainer.toTagCompound()); -+ if (!chunk.persistentDataContainer.isEmpty()) { -+ nbttagcompound1.put("ChunkBukkitValues", chunk.persistentDataContainer.toTagCompound()); - } - // CraftBukkit end - -- chunk1.setLastSaveHadEntities(false); -+ chunk.setLastSaveHadEntities(false); - -- for (int j = 0; j < chunk1.getEntitySlices().length; ++j) { -- Iterator iterator1 = chunk1.getEntitySlices()[j].iterator(); -+ for (int j = 0; j < chunk.getEntitySlices().length; ++j) { -+ Iterator iterator1 = chunk.getEntitySlices()[j].iterator(); - - while (iterator1.hasNext()) { - Entity entity = (Entity) iterator1.next(); - CompoundTag nbttagcompound4 = new CompoundTag(); - // Paper start -- if ((int) Math.floor(entity.getX()) >> 4 != chunk1.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk1.getPos().z) { -+ if (asyncsavedata == null && !entity.removed && (int) Math.floor(entity.getX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk.getPos().z) { - toUpdate.add(entity); - continue; - } -@@ -378,7 +495,7 @@ public class ChunkSerializer { - } - // Paper end - if (entity.save(nbttagcompound4)) { -- chunk1.setLastSaveHadEntities(true); -+ chunk.setLastSaveHadEntities(true); - nbttaglist2.add(nbttagcompound4); - } - } -@@ -386,12 +503,12 @@ public class ChunkSerializer { - - // Paper start - move entities to the correct chunk - for (Entity entity : toUpdate) { -- world.updateChunkPos(entity); -+ worldserver.updateChunkPos(entity); - } - // Paper end - - } else { -- ProtoChunk protochunk = (ProtoChunk) chunk; -+ ProtoChunk protochunk = (ProtoChunk) ichunkaccess; - - nbttaglist2.addAll(protochunk.getEntities()); - nbttagcompound1.put("Lights", packOffsets(protochunk.getPackedLights())); -@@ -412,40 +529,48 @@ public class ChunkSerializer { - } - - nbttagcompound1.put("Entities", nbttaglist2); -- TickList ticklist = chunk.getBlockTicks(); -+ TickList ticklist = ichunkaccess.getBlockTicks(); // Paper - diff on method change (see getAsyncSaveData) - - if (ticklist instanceof ProtoTickList) { - nbttagcompound1.put("ToBeTicked", ((ProtoTickList) ticklist).save()); - } else if (ticklist instanceof ChunkTickList) { - nbttagcompound1.put("TileTicks", ((ChunkTickList) ticklist).save()); -+ // Paper start - async chunk save for unload -+ } else if (asyncsavedata != null) { -+ nbttagcompound1.put("TileTicks", asyncsavedata.blockTickList); -+ // Paper end - } else { -- nbttagcompound1.put("TileTicks", world.getBlockTicks().save(chunkcoordintpair)); -+ nbttagcompound1.put("TileTicks", worldserver.getBlockTicks().save(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) - } - -- TickList ticklist1 = chunk.getLiquidTicks(); -+ TickList ticklist1 = ichunkaccess.getLiquidTicks(); // Paper - diff on method change (see getAsyncSaveData) - - if (ticklist1 instanceof ProtoTickList) { - nbttagcompound1.put("LiquidsToBeTicked", ((ProtoTickList) ticklist1).save()); - } else if (ticklist1 instanceof ChunkTickList) { - nbttagcompound1.put("LiquidTicks", ((ChunkTickList) ticklist1).save()); -+ // Paper start - async chunk save for unload -+ } else if (asyncsavedata != null) { -+ nbttagcompound1.put("LiquidTicks", asyncsavedata.fluidTickList); -+ // Paper end - } else { -- nbttagcompound1.put("LiquidTicks", world.getLiquidTicks().save(chunkcoordintpair)); -+ nbttagcompound1.put("LiquidTicks", worldserver.getLiquidTicks().save(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) - } - -- nbttagcompound1.put("PostProcessing", packOffsets(chunk.getPostProcessing())); -+ nbttagcompound1.put("PostProcessing", packOffsets(ichunkaccess.getPostProcessing())); - nbttagcompound2 = new CompoundTag(); -- Iterator iterator2 = chunk.getHeightmaps().iterator(); -+ Iterator iterator2 = ichunkaccess.getHeightmaps().iterator(); - - while (iterator2.hasNext()) { - Entry entry = (Entry) iterator2.next(); - -- if (chunk.getStatus().heightmapsAfter().contains(entry.getKey())) { -+ if (ichunkaccess.getStatus().heightmapsAfter().contains(entry.getKey())) { - nbttagcompound2.put(((Heightmap.Types) entry.getKey()).getSerializationKey(), new LongArrayTag(((Heightmap) entry.getValue()).getRawData())); - } - } - - nbttagcompound1.put("Heightmaps", nbttagcompound2); -- nbttagcompound1.put("Structures", packStructureData(chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences())); -+ nbttagcompound1.put("Structures", packStructureData(chunkcoordintpair, ichunkaccess.getAllStarts(), ichunkaccess.getAllReferences())); - return nbttagcompound; - } - // Paper start - this is saved with the player -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -index 9cffef2098fbfba89ddd88a45bde33c07660497a..684442b7175e30b6d4cafb2f7d2d4c10517cc33d 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -@@ -3,6 +3,10 @@ package net.minecraft.world.level.chunk.storage; - import com.mojang.datafixers.DataFixer; - import java.io.File; - import java.io.IOException; -+// Paper start -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.CompletionException; -+// Paper end - import java.util.function.Supplier; - import javax.annotation.Nullable; - import net.minecraft.SharedConstants; -@@ -21,32 +25,41 @@ import net.minecraft.world.level.storage.DimensionDataStorage; - - public class ChunkStorage implements AutoCloseable { - -- private final IOWorker worker; public IOWorker getIOWorker() { return worker; } // Paper - OBFHELPER -+ // Paper - OBFHELPER - nuke IOWorker - protected final DataFixer fixerUpper; - @Nullable -- private LegacyStructureDataHandler legacyStructureHandler; -+ private volatile LegacyStructureDataHandler legacyStructureHandler; // Paper - async chunk loading -+ -+ private final Object persistentDataLock = new Object(); // Paper -+ public final RegionFileStorage regionFileCache; - - public ChunkStorage(File file, DataFixer datafixer, boolean flag) { -+ this.regionFileCache = new RegionFileStorage(file, flag); // Paper - nuke IOWorker - this.fixerUpper = datafixer; -- this.worker = new IOWorker(file, flag, "chunk"); -+ // Paper - nuke IOWorker - } - - // CraftBukkit start - private boolean check(ServerChunkCache cps, int x, int z) throws IOException { - ChunkPos pos = new ChunkPos(x, z); - if (cps != null) { -- com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); -- if (cps.hasChunk(x, z)) { -+ //com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe -+ if (cps.getChunkAtIfCachedImmediately(x, z) != null) { // Paper - isLoaded is a ticket level check, not a chunk loaded check! - return true; - } - } - -- CompoundTag nbt = read(pos); -- if (nbt != null) { -- CompoundTag level = nbt.getCompound("Level"); -- if (level.getBoolean("TerrainPopulated")) { -- return true; -- } -+ -+ // Paper start - prioritize -+ CompoundTag nbt = cps == null ? read(pos) : -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.loadChunkData((ServerLevel)cps.getLevel(), x, z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHER_PRIORITY, false, true).chunkData; -+ // Paper end -+ if (nbt != null) { -+ CompoundTag level = nbt.getCompound("Level"); -+ if (level.getBoolean("TerrainPopulated")) { -+ return true; -+ } - - ChunkStatus status = ChunkStatus.byName(level.getString("Status")); - if (status != null && status.isOrAfter(ChunkStatus.FEATURES)) { -@@ -77,11 +90,13 @@ public class ChunkStorage implements AutoCloseable { - if (i < 1493) { - nbttagcompound = NbtUtils.update(this.fixerUpper, DataFixTypes.CHUNK, nbttagcompound, i, 1493); - if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { -+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading - if (this.legacyStructureHandler == null) { - this.legacyStructureHandler = LegacyStructureDataHandler.getLegacyStructureHandler(resourcekey, (DimensionDataStorage) supplier.get()); - } - - nbttagcompound = this.legacyStructureHandler.updateFromLegacy(nbttagcompound); -+ } // Paper - Async chunk loading - } - } - -@@ -99,22 +114,20 @@ public class ChunkStorage implements AutoCloseable { - - @Nullable - public CompoundTag read(ChunkPos chunkcoordintpair) throws IOException { -- return this.worker.load(chunkcoordintpair); -+ return this.regionFileCache.read(chunkcoordintpair); - } - -- public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) { -- this.worker.store(chunkcoordintpair, nbttagcompound); -+ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER -+ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) -+ this.regionFileCache.write(chunkcoordintpair, nbttagcompound); - if (this.legacyStructureHandler != null) { -+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading - this.legacyStructureHandler.removeIndex(chunkcoordintpair.toLong()); -+ } // Paper - Async chunk loading} - } -- -- } -- -- public void flushWorker() { -- this.worker.synchronize().join(); - } - - public void close() throws IOException { -- this.worker.close(); -+ this.regionFileCache.close(); - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 4d96e5ed28c910387c0a4238c9036c7a12458f57..7ecde2cb15fa0b1b5195fc560c559f2c367e336f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -45,6 +45,8 @@ public class RegionFile implements AutoCloseable { - protected final RegionBitmap usedSectors; - public final File file; // Paper - -+ public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper -+ - // Paper start - Cache chunk status - private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; - -@@ -251,7 +253,7 @@ public class RegionFile implements AutoCloseable { - return (byteCount + 4096 - 1) / 4096; - } - -- public boolean doesChunkExist(ChunkPos pos) { -+ public synchronized boolean doesChunkExist(ChunkPos pos) { // Paper - synchronized - int i = this.getOffset(pos); - - if (i == 0) { -@@ -411,6 +413,11 @@ public class RegionFile implements AutoCloseable { - } - - public void close() throws IOException { -+ // Paper start - Prevent regionfiles from being closed during use -+ this.fileLock.lock(); -+ synchronized (this) { -+ try { -+ // Paper end - this.closed = true; // Paper - try { - this.padToFullSector(); -@@ -421,6 +428,10 @@ public class RegionFile implements AutoCloseable { - this.file.close(); - } - } -+ } finally { // Paper start - Prevent regionfiles from being closed during use -+ this.fileLock.unlock(); -+ } -+ } // Paper end - - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 6f1c96e4325caf6b4762700ad2286d9ea41515c9..0498982ac14f20145d68dbf64a46bcaacf5516ef 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -17,7 +17,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionCollector; - import net.minecraft.world.level.ChunkPos; - --public final class RegionFileStorage implements AutoCloseable { -+public class RegionFileStorage implements AutoCloseable { // Paper - no final - - public final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap(); - private final File folder; -@@ -30,16 +30,27 @@ public final class RegionFileStorage implements AutoCloseable { - - - // Paper start -- public RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { -+ public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { // Paper - synchronize for async io - return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); - } - - // Paper end -- public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public -+ public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public, synchronize -+ // Paper start - add lock parameter -+ return this.getFile(chunkcoordintpair, existingOnly, false); -+ } -+ public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly, boolean lock) throws IOException { -+ // Paper end - long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); - RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); - - if (regionfile != null) { -+ // Paper start -+ if (lock) { -+ // must be in this synchronized block -+ regionfile.fileLock.lock(); -+ } -+ // Paper end - return regionfile; - } else { - if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable -@@ -55,6 +66,12 @@ public final class RegionFileStorage implements AutoCloseable { - RegionFile regionfile1 = new RegionFile(file, this.folder, this.sync); - - this.regionCache.putAndMoveToFirst(i, regionfile1); -+ // Paper start -+ if (lock) { -+ // must be in this synchronized block -+ regionfile1.fileLock.lock(); -+ } -+ // Paper end - return regionfile1; - } - } -@@ -130,11 +147,12 @@ public final class RegionFileStorage implements AutoCloseable { - @Nullable - public CompoundTag read(ChunkPos pos) throws IOException { - // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing -- RegionFile regionfile = this.getFile(pos, true); -+ RegionFile regionfile = this.getFile(pos, true, true); // Paper - if (regionfile == null) { - return null; - } - // CraftBukkit end -+ try { // Paper - DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); - // Paper start - if (regionfile.isOversized(pos.x, pos.z)) { -@@ -172,10 +190,14 @@ public final class RegionFileStorage implements AutoCloseable { - } - - return nbttagcompound; -+ } finally { // Paper start -+ regionfile.fileLock.unlock(); -+ } // Paper end - } - - protected void write(ChunkPos pos, CompoundTag tag) throws IOException { -- RegionFile regionfile = this.getFile(pos, false); // CraftBukkit -+ RegionFile regionfile = this.getFile(pos, false, true); // CraftBukkit // Paper -+ try { // Paper - int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper - DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(pos); - Throwable throwable = null; -@@ -214,9 +236,12 @@ public final class RegionFileStorage implements AutoCloseable { - MinecraftServer.LOGGER.error("Failed to save chunk", laste); - } - // Paper end -+ } finally { // Paper start -+ regionfile.fileLock.unlock(); -+ } // Paper end - } - -- public void close() throws IOException { -+ public synchronized void close() throws IOException { // Paper -> synchronized - ExceptionCollector exceptionsuppressor = new ExceptionCollector<>(); - ObjectIterator objectiterator = this.regionCache.values().iterator(); - -@@ -243,4 +268,12 @@ public final class RegionFileStorage implements AutoCloseable { - } - - } -+ -+ // CraftBukkit start -+ public synchronized boolean chunkExists(ChunkPos pos) throws IOException { // Paper - synchronize -+ RegionFile regionfile = getFile(pos, true); -+ -+ return regionfile != null ? regionfile.hasChunk(pos) : false; -+ } -+ // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java -index 059a658aa87d19025daa66d98f78112d5f5be4e3..bb30fb085a6c5edb717ad006c0ab481723ca1b6b 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java -@@ -30,28 +30,29 @@ import net.minecraft.world.level.Level; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - --public class SectionStorage implements AutoCloseable { -+public class SectionStorage extends RegionFileStorage implements AutoCloseable { // Paper - nuke IOWorker - - private static final Logger LOGGER = LogManager.getLogger(); -- private final IOWorker worker; -+ // Paper - nuke IOWorker - private final Long2ObjectMap> storage = new Long2ObjectOpenHashMap(); -- private final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet(); -+ public final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet(); // Paper - private -> public - private final Function> codec; - private final Function factory; - private final DataFixer fixerUpper; - private final DataFixTypes type; - - public SectionStorage(File directory, Function> codecFactory, Function factory, DataFixer datafixer, DataFixTypes datafixtypes, boolean flag) { -+ super(directory, flag); // Paper - nuke IOWorker - this.codec = codecFactory; - this.factory = factory; - this.fixerUpper = datafixer; - this.type = datafixtypes; -- this.worker = new IOWorker(directory, flag, directory.getName()); -+ //this.b = new IOWorker(file, flag, file.getName()); // Paper - nuke IOWorker - } - - protected void tick(BooleanSupplier shouldKeepTicking) { - while (!this.dirty.isEmpty() && shouldKeepTicking.getAsBoolean()) { -- ChunkPos chunkcoordintpair = SectionPos.of(this.dirty.firstLong()).chunk(); -+ ChunkPos chunkcoordintpair = SectionPos.of(this.dirty.firstLong()).chunk(); // Paper - conflict here to avoid obfhelpers - - this.writeColumn(chunkcoordintpair); - } -@@ -105,13 +106,18 @@ public class SectionStorage implements AutoCloseable { - } - - private void readColumn(ChunkPos chunkcoordintpair) { -- this.readColumn(chunkcoordintpair, NbtOps.INSTANCE, this.tryRead(chunkcoordintpair)); -+ // Paper start - load data in function -+ this.loadInData(chunkcoordintpair, this.tryRead(chunkcoordintpair)); -+ } -+ public void loadInData(ChunkPos chunkPos, CompoundTag compound) { -+ this.readColumn(chunkPos, NbtOps.INSTANCE, compound); -+ // Paper end - } - - @Nullable - private CompoundTag tryRead(ChunkPos pos) { - try { -- return this.worker.load(pos); -+ return this.read(pos); // Paper - nuke IOWorker - } catch (IOException ioexception) { - SectionStorage.LOGGER.error("Error reading chunk {} data from disk", pos, ioexception); - return null; -@@ -157,17 +163,31 @@ public class SectionStorage implements AutoCloseable { - } - - private void writeColumn(ChunkPos chunkcoordintpair) { -- Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); -+ Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); // Paper - conflict here to avoid adding obfhelpers :) - Tag nbtbase = (Tag) dynamic.getValue(); - - if (nbtbase instanceof CompoundTag) { -- this.worker.store(chunkcoordintpair, (CompoundTag) nbtbase); -+ try { this.write(chunkcoordintpair, (CompoundTag) nbtbase); } catch (IOException ioexception) { SectionStorage.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker // TODO make this write async - } else { - SectionStorage.LOGGER.error("Expected compound tag, got {}", nbtbase); - } - - } - -+ // Paper start - internal get data function, copied from above -+ private CompoundTag getDataInternal(ChunkPos chunkcoordintpair) { -+ Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); -+ Tag nbtbase = (Tag) dynamic.getValue(); -+ -+ if (nbtbase instanceof CompoundTag) { -+ return (CompoundTag)nbtbase; -+ } else { -+ SectionStorage.LOGGER.error("Expected compound tag, got {}", nbtbase); -+ } -+ return null; -+ } -+ // Paper end -+ - private Dynamic writeColumn(ChunkPos chunkcoordintpair, DynamicOps dynamicops) { - Map map = Maps.newHashMap(); - -@@ -213,9 +233,9 @@ public class SectionStorage implements AutoCloseable { - public void flush(ChunkPos chunkcoordintpair) { - if (!this.dirty.isEmpty()) { - for (int i = 0; i < 16; ++i) { -- long j = SectionPos.of(chunkcoordintpair, i).asLong(); -+ long j = SectionPos.of(chunkcoordintpair, i).asLong(); // Paper - conflict here to avoid obfhelpers - -- if (this.dirty.contains(j)) { -+ if (this.dirty.contains(j)) { // Paper - conflict here to avoid obfhelpers - this.writeColumn(chunkcoordintpair); - return; - } -@@ -224,7 +244,26 @@ public class SectionStorage implements AutoCloseable { - - } - -- public void close() throws IOException { -- this.worker.close(); -+// Paper start - nuke IOWorker -+// public void close() throws IOException { -+// this.b.close(); -+// } -+// Paper end -+ -+ // Paper start - get data function -+ public CompoundTag getData(ChunkPos chunkcoordintpair) { -+ // Note: Copied from above -+ // This is checking if the data exists, then it builds it later in getDataInternal(ChunkCoordIntPair) -+ if (!this.dirty.isEmpty()) { -+ for (int i = 0; i < 16; ++i) { -+ long j = SectionPos.of(chunkcoordintpair, i).asLong(); -+ -+ if (this.dirty.contains(j)) { -+ return this.getDataInternal(chunkcoordintpair); -+ } -+ } -+ } -+ return null; - } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index a0615e4ba015cca4fe074de63b87d0bff84b1a14..52444619a4bae80a12bf296fbe07fa811adf806e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -545,22 +545,23 @@ public class CraftWorld implements World { - return true; - } - -- net.minecraft.world.level.chunk.storage.RegionFile file; -- try { -- file = world.getChunkSource().chunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -- } catch (IOException ex) { -- throw new RuntimeException(ex); -- } -+ ChunkStatus status = world.getChunkSource().chunkMap.getStatusOnDiskNoLoad(x, z); // Paper - async io - move to own method - -- ChunkStatus status = file.getStatusIfCached(x, z); -- if (!file.hasChunk(chunkPos) || (status != null && status != ChunkStatus.FULL)) { -+ // Paper start - async io -+ if (status == ChunkStatus.EMPTY) { -+ // does not exist on disk - return false; - } - -+ if (status == null) { // at this stage we don't know what it is on disk - ChunkAccess chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.EMPTY, true); - if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof net.minecraft.world.level.chunk.LevelChunk)) { - return false; - } -+ } else if (status != ChunkStatus.FULL) { -+ return false; // not full status on disk -+ } -+ // Paper end - - // fall through to load - // we do this so we do not re-read the chunk data on disk -@@ -2483,6 +2484,34 @@ public class CraftWorld implements World { - public DragonBattle getEnderDragonBattle() { - return (getHandle().dragonFight() == null) ? null : new CraftDragonBattle(getHandle().dragonFight()); - } -+ // Paper start -+ @Override -+ public CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { -+ if (Bukkit.isPrimaryThread()) { -+ net.minecraft.world.level.chunk.LevelChunk immediate = this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); -+ if (immediate != null) { -+ return CompletableFuture.completedFuture(immediate.getBukkitChunk()); -+ } -+ } else { -+ CompletableFuture future = new CompletableFuture(); -+ world.getServer().execute(() -> { -+ getChunkAtAsync(x, z, gen, urgent).whenComplete((chunk, err) -> { -+ if (err != null) { -+ future.completeExceptionally(err); -+ } else { -+ future.complete(chunk); -+ } -+ }); -+ }); -+ return future; -+ } -+ -+ return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { -+ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); -+ return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); -+ }, net.minecraft.server.MinecraftServer.getServer()); -+ } -+ // Paper end - - // Spigot start - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 7ad4fb57af32cc1b8278688381e1b058ed8437db..76d652386806fd11961611486a1d0a12fe9616a4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -11,7 +11,9 @@ import net.minecraft.core.BlockPos; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.Tag; - import net.minecraft.network.chat.Component; -+import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.TicketType; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.AreaEffectCloud; - import net.minecraft.world.entity.Entity; -@@ -508,6 +510,28 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - entity.setYHeadRot(yaw); - } - -+ @Override// Paper start -+ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { -+ ChunkMap playerChunkMap = ((CraftWorld) loc.getWorld()).getHandle().getChunkSource().chunkMap; -+ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); -+ -+ loc.getWorld().getChunkAtAsyncUrgently(loc).thenCompose(chunk -> { -+ ChunkCoordIntPair pair = new ChunkCoordIntPair(chunk.getX(), chunk.getZ()); -+ ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().addTicketAtLevel(TicketType.POST_TELEPORT, pair, 31, 0); -+ PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pair.pair()); -+ if (updatingChunk != null) { -+ return updatingChunk.getEntityTickingFuture(); -+ } else { -+ return java.util.concurrent.CompletableFuture.completedFuture(com.mojang.datafixers.util.Either.left(((org.bukkit.craftbukkit.CraftChunk)chunk).getHandle())); -+ } -+ }).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { -+ future.completeExceptionally(ex); -+ return null; -+ }); -+ return future; -+ } -+ // Paper end -+ - @Override - public boolean teleport(Location location) { - return teleport(location, TeleportCause.PLUGIN); -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 16f6163bb53e73aa4ab6e22365342613b6b38118..33a66322d253c7562ae5acbdbc6cc87f7d72a9af 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -6,6 +6,7 @@ import java.lang.management.ThreadInfo; - import java.util.logging.Level; - import java.util.logging.Logger; - import com.destroystokyo.paper.PaperConfig; -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; // Paper - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; - -@@ -116,6 +117,7 @@ public class WatchdogThread extends Thread - // Paper end - Different message for short timeout - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper -+ ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // diff --git a/Remapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch b/Remapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch deleted file mode 100644 index 3becb4b6e9..0000000000 --- a/Remapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 8 Jul 2019 00:13:36 -0700 -Subject: [PATCH] Use getChunkIfLoadedImmediately in places - -This prevents us from hitting chunk loads for chunks at or less-than -ticket level 33 (yes getChunkIfLoaded will actually perform a chunk -load in that case). - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 95eff4f6165024d21e5c4268a9ae1b7a4268de4b..9d4c81a4964317a0726171dc6d490d12bd959cc4 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -201,7 +201,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI -- return this.chunkSource.getChunk(x, z, false); -+ return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - } - - // Paper start - Asynchronous IO -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 5dd99709d6b0ed15bbcee184fe33a28bc1c19dac..e45690b6197335ed1c07fa04c39b311b401724d7 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1242,7 +1242,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - speed = player.abilities.walkingSpeed * 10f; - } - // Paper start - Prevent moving into unloaded chunks -- if (player.level.paperConfig.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.hasChunk((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { -+ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && worldserver.getChunkIfLoadedImmediately((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4) == null) { // Paper - use getIfLoadedImmediately - this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.yRot, this.player.xRot, Collections.emptySet()); - return; - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -index d082af8cf4c0c7ca434598aa370712c62e05bb24..b9d32e3322c2cce1aca2a90df71b6175a6f8c548 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -@@ -284,10 +284,10 @@ public class PoiManager extends SectionStorage { - // Paper start - Asynchronous chunk io - @javax.annotation.Nullable - @Override -- public CompoundTag read(ChunkPos chunkcoordintpair) throws java.io.IOException { -+ public CompoundTag read(ChunkPos pos) throws java.io.IOException { - if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { - CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -- .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), -+ .loadChunkDataAsyncFuture(this.world, pos.x, pos.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), - true, false, true).join().poiData; - - if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { -@@ -295,18 +295,18 @@ public class PoiManager extends SectionStorage { - } - return ret; - } -- return super.read(chunkcoordintpair); -+ return super.read(pos); - } - - @Override -- public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws java.io.IOException { -+ public void write(ChunkPos pos, CompoundTag tag) throws java.io.IOException { - if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { - com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( -- this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, -+ this.world, pos.x, pos.z, tag, null, - com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); - return; - } -- super.write(chunkcoordintpair, nbttagcompound); -+ super.write(pos, tag); - } - // Paper end - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 1377465e3dc062f34be25cac10aa018776fb22e7..3a1b9f1ba19b28cebdafeb3b2476217d47213862 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -164,6 +164,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return (CraftServer) Bukkit.getServer(); - } - -+ // Paper start -+ @Override -+ public boolean hasChunk(int chunkX, int chunkZ) { -+ return ((ServerLevel)this).getChunkIfLoaded(chunkX, chunkZ) != null; -+ } -+ // Paper end -+ - public ResourceKey getTypeKey() { - return typeKey; - } -@@ -1190,7 +1197,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- LevelChunk chunk = ichunkprovider.getChunkNow(i1, j1); -+ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.getEntitiesOfClass(entityClass, box, list, predicate); -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 0a9bd85e0308e962df3b24a74bd5aac919744d6d..61f180a7c95d83bb88c7df4910c498d9bdf6785a 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -140,9 +140,10 @@ public class ActivationRange - { - for ( int j1 = k; j1 <= l; ++j1 ) - { -- if ( world.getWorld().isChunkLoaded( i1, j1 ) ) -+ LevelChunk chunk = (LevelChunk) world.getChunkIfLoadedImmediately( i1, j1 ); -+ if ( chunk != null ) - { -- activateChunkEntities( world.getChunk( i1, j1 ) ); -+ activateChunkEntities( chunk ); - } - } - } diff --git a/Remapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch b/Remapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch deleted file mode 100644 index 5349d43158..0000000000 --- a/Remapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch +++ /dev/null @@ -1,350 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 19 Jul 2019 03:29:14 -0700 -Subject: [PATCH] Reduce sync loads - -This reduces calls to getChunkAt which would load chunks. - -This patch also adds a tool to find calls which are doing this, however -it must be enabled by setting the startup flag -Dpaper.debug-sync-loads=true - -To get a debug log for sync loads, the command is /paper syncloadinfo - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 62711d95db62221a2e4e6423c518afe13a6c7dbe..ff718bc7f521575e6a670e17fcf59a2d30841705 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -1,12 +1,18 @@ - package com.destroystokyo.paper; - - import com.destroystokyo.paper.io.chunk.ChunkTaskManager; -+import com.destroystokyo.paper.io.SyncLoadFinder; - import com.google.common.base.Functions; - import com.google.common.base.Joiner; - import com.google.common.collect.ImmutableSet; - import com.google.common.collect.Iterables; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; -+import com.google.gson.JsonObject; -+import com.google.gson.internal.Streams; -+import com.google.gson.stream.JsonWriter; -+import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkHolder; - import net.minecraft.server.level.ServerChunkCache; -@@ -14,7 +20,6 @@ import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; - import net.minecraft.world.level.ChunkPos; --import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.MCUtil; - import org.apache.commons.lang3.tuple.MutablePair; - import org.apache.commons.lang3.tuple.Pair; -@@ -29,6 +34,9 @@ import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.entity.Player; - - import java.io.File; -+import java.io.FileOutputStream; -+import java.io.PrintStream; -+import java.io.StringWriter; - import java.time.LocalDateTime; - import java.time.format.DateTimeFormatter; - import java.util.ArrayList; -@@ -44,7 +52,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); - - public PaperCommand(String name) { - super(name); -@@ -162,6 +170,9 @@ public class PaperCommand extends Command { - case "chunkinfo": - doChunkInfo(sender, args); - break; -+ case "syncloadinfo": -+ this.doSyncLoadInfo(sender, args); -+ break; - case "ver": - if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) - case "version": -@@ -179,6 +190,40 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doSyncLoadInfo(CommandSender sender, String[] args) { -+ if (!SyncLoadFinder.ENABLED) { -+ sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); -+ return; -+ } -+ File file = new File(new File(new File("."), "debug"), -+ "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); -+ file.getParentFile().mkdirs(); -+ sender.sendMessage(ChatColor.GREEN + "Writing sync load info to " + file.toString()); -+ -+ -+ try { -+ final JsonObject data = SyncLoadFinder.serialize(); -+ -+ StringWriter stringWriter = new StringWriter(); -+ JsonWriter jsonWriter = new JsonWriter(stringWriter); -+ jsonWriter.setIndent(" "); -+ jsonWriter.setLenient(false); -+ Streams.write(data, jsonWriter); -+ -+ String fileData = stringWriter.toString(); -+ -+ try ( -+ PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8") -+ ) { -+ out.print(fileData); -+ } -+ sender.sendMessage(ChatColor.GREEN + "Successfully written sync load information!"); -+ } catch (Throwable thr) { -+ sender.sendMessage(ChatColor.RED + "Failed to write sync load information"); -+ thr.printStackTrace(); -+ } -+ } -+ - private void doChunkInfo(CommandSender sender, String[] args) { - List worlds; - if (args.length < 2 || args[1].equals("*")) { -diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..524f33371b9de1d4dd6972fe59ffbe1804d7c5f3 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -@@ -0,0 +1,171 @@ -+package com.destroystokyo.paper.io; -+ -+import com.google.gson.JsonArray; -+import com.google.gson.JsonObject; -+import com.mojang.datafixers.util.Pair; -+import it.unimi.dsi.fastutil.longs.Long2IntMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -+ -+import java.util.ArrayList; -+import java.util.List; -+import java.util.Map; -+import java.util.WeakHashMap; -+import net.minecraft.world.level.Level; -+ -+public class SyncLoadFinder { -+ -+ public static final boolean ENABLED = Boolean.getBoolean("paper.debug-sync-loads"); -+ -+ private static final WeakHashMap> SYNC_LOADS = new WeakHashMap<>(); -+ -+ private static final class SyncLoadInformation { -+ -+ public int times; -+ -+ public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); -+ } -+ -+ public static void logSyncLoad(final Level world, final int chunkX, final int chunkZ) { -+ if (!ENABLED) { -+ return; -+ } -+ -+ final ThrowableWithEquals stacktrace = new ThrowableWithEquals(Thread.currentThread().getStackTrace()); -+ -+ SYNC_LOADS.compute(world, (final Level keyInMap, Object2ObjectOpenHashMap map) -> { -+ if (map == null) { -+ map = new Object2ObjectOpenHashMap<>(); -+ } -+ -+ map.compute(stacktrace, (ThrowableWithEquals keyInMap0, SyncLoadInformation valueInMap) -> { -+ if (valueInMap == null) { -+ valueInMap = new SyncLoadInformation(); -+ } -+ -+ ++valueInMap.times; -+ -+ valueInMap.coordinateTimes.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (Long keyInMap1, Integer valueInMap1) -> { -+ return valueInMap1 == null ? Integer.valueOf(1) : Integer.valueOf(valueInMap1.intValue() + 1); -+ }); -+ -+ return valueInMap; -+ }); -+ -+ return map; -+ }); -+ } -+ -+ public static JsonObject serialize() { -+ final JsonObject ret = new JsonObject(); -+ -+ final JsonArray worldsData = new JsonArray(); -+ -+ for (final Map.Entry> entry : SYNC_LOADS.entrySet()) { -+ final Level world = entry.getKey(); -+ -+ final JsonObject worldData = new JsonObject(); -+ -+ worldData.addProperty("name", world.getWorld().getName()); -+ -+ final List> data = new ArrayList<>(); -+ -+ entry.getValue().forEach((ThrowableWithEquals stacktrace, SyncLoadInformation times) -> { -+ data.add(new Pair<>(stacktrace, times)); -+ }); -+ -+ data.sort((Pair pair1, Pair pair2) -> { -+ return Integer.compare(pair2.getSecond().times, pair1.getSecond().times); // reverse order -+ }); -+ -+ final JsonArray stacktraces = new JsonArray(); -+ -+ for (Pair pair : data) { -+ final JsonObject stacktrace = new JsonObject(); -+ -+ stacktrace.addProperty("times", pair.getSecond().times); -+ -+ final JsonArray traces = new JsonArray(); -+ -+ for (StackTraceElement element : pair.getFirst().stacktrace) { -+ traces.add(String.valueOf(element)); -+ } -+ -+ stacktrace.add("stacktrace", traces); -+ -+ final JsonArray coordinates = new JsonArray(); -+ -+ for (Long2IntMap.Entry coordinate : pair.getSecond().coordinateTimes.long2IntEntrySet()) { -+ final long key = coordinate.getLongKey(); -+ final int times = coordinate.getIntValue(); -+ coordinates.add("(" + IOUtil.getCoordinateX(key) + "," + IOUtil.getCoordinateZ(key) + "): " + times); -+ } -+ -+ stacktrace.add("coordinates", coordinates); -+ -+ stacktraces.add(stacktrace); -+ } -+ -+ -+ worldData.add("stacktraces", stacktraces); -+ worldsData.add(worldData); -+ } -+ -+ ret.add("worlds", worldsData); -+ -+ return ret; -+ } -+ -+ static final class ThrowableWithEquals { -+ -+ private final StackTraceElement[] stacktrace; -+ private final int hash; -+ -+ public ThrowableWithEquals(final StackTraceElement[] stacktrace) { -+ this.stacktrace = stacktrace; -+ this.hash = ThrowableWithEquals.hash(stacktrace); -+ } -+ -+ public static int hash(final StackTraceElement[] stacktrace) { -+ int hash = 0; -+ -+ for (int i = 0; i < stacktrace.length; ++i) { -+ hash *= 31; -+ hash += stacktrace[i].hashCode(); -+ } -+ -+ return hash; -+ } -+ -+ @Override -+ public int hashCode() { -+ return this.hash; -+ } -+ -+ @Override -+ public boolean equals(final Object obj) { -+ if (obj == null || obj.getClass() != this.getClass()) { -+ return false; -+ } -+ -+ final ThrowableWithEquals other = (ThrowableWithEquals)obj; -+ final StackTraceElement[] otherStackTrace = other.stacktrace; -+ -+ if (this.stacktrace.length != otherStackTrace.length || this.hash != other.hash) { -+ return false; -+ } -+ -+ if (this == obj) { -+ return true; -+ } -+ -+ for (int i = 0; i < this.stacktrace.length; ++i) { -+ if (!this.stacktrace[i].equals(otherStackTrace[i])) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 120b604d91643248ab375969f95f62a74cbf6be7..5e0d55c3821b1769d20514a8a6c5c74477019778 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -494,6 +494,7 @@ public class ServerChunkCache extends ChunkSource { - this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); - // Paper end -+ com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x1, z1); // Paper - sync load info - this.level.timings.syncChunkLoad.startTiming(); // Paper - this.mainThreadProcessor.managedBlock(completablefuture::isDone); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 9d4c81a4964317a0726171dc6d490d12bd959cc4..01f879a8dd0e1ffec380e02072567330152eaceb 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -276,6 +276,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - }; - public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; - // Paper end -+ // Paper start -+ @Override -+ public boolean hasChunk(int chunkX, int chunkZ) { -+ return this.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ) != null; -+ } -+ // Paper end - - // Add env and gen to constructor, WorldData -> WorldDataServer - public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 3a1b9f1ba19b28cebdafeb3b2476217d47213862..3e2cd6c7a34c1a792d7346019a8b039d1f4a7c04 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1130,7 +1130,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - for (int i1 = i; i1 <= j; ++i1) { - for (int j1 = k; j1 <= l; ++j1) { -- LevelChunk chunk = ichunkprovider.getChunk(i1, j1, false); -+ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.getEntities(except, box, list, predicate); -@@ -1151,7 +1151,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- LevelChunk chunk = this.getChunkSource().getChunk(i1, j1, false); -+ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.getEntities(type, box, list, predicate); -@@ -1174,7 +1174,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- LevelChunk chunk = ichunkprovider.getChunk(i1, j1, false); -+ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.getEntitiesOfClass(entityClass, box, list, predicate); diff --git a/Remapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch b/Remapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch deleted file mode 100644 index 21aa2f962b..0000000000 --- a/Remapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Mon, 3 Jun 2019 02:02:39 -0400 -Subject: [PATCH] Implement alternative item-despawn-rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1ee2cced100626e48eb36ee14f84b9257c79a2f8..b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -1,10 +1,15 @@ - package com.destroystokyo.paper; - - import java.util.Arrays; -+import java.util.EnumMap; -+import java.util.HashMap; - import java.util.List; -+import java.util.Map; - - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; - import org.bukkit.Bukkit; -+import org.bukkit.Material; -+import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -512,4 +517,52 @@ public class PaperWorldConfig { - private void disableRelativeProjectileVelocity() { - disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); - } -+ -+ public boolean altItemDespawnRateEnabled; -+ public Map altItemDespawnRateMap; -+ private void altItemDespawnRate() { -+ String path = "alt-item-despawn-rate"; -+ -+ altItemDespawnRateEnabled = getBoolean(path + ".enabled", false); -+ -+ Map altItemDespawnRateMapDefault = new EnumMap<>(Material.class); -+ altItemDespawnRateMapDefault.put(Material.COBBLESTONE, 300); -+ for (Material key : altItemDespawnRateMapDefault.keySet()) { -+ config.addDefault("world-settings.default." + path + ".items." + key, altItemDespawnRateMapDefault.get(key)); -+ } -+ -+ Map rawMap = new HashMap<>(); -+ try { -+ ConfigurationSection mapSection = config.getConfigurationSection("world-settings." + worldName + "." + path + ".items"); -+ if (mapSection == null) { -+ mapSection = config.getConfigurationSection("world-settings.default." + path + ".items"); -+ } -+ for (String key : mapSection.getKeys(false)) { -+ int val = mapSection.getInt(key); -+ rawMap.put(key, val); -+ } -+ } -+ catch (Exception e) { -+ logError("alt-item-despawn-rate was malformatted"); -+ altItemDespawnRateEnabled = false; -+ } -+ -+ altItemDespawnRateMap = new EnumMap<>(Material.class); -+ if (!altItemDespawnRateEnabled) { -+ return; -+ } -+ -+ for(String key : rawMap.keySet()) { -+ try { -+ altItemDespawnRateMap.put(Material.valueOf(key), rawMap.get(key)); -+ } catch (Exception e) { -+ logError("Could not add item " + key + " to altItemDespawnRateMap: " + e.getMessage()); -+ } -+ } -+ if(altItemDespawnRateEnabled) { -+ for(Material key : altItemDespawnRateMap.keySet()) { -+ log("Alternative item despawn rate of " + key + ": " + altItemDespawnRateMap.get(key)); -+ } -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 281f5646980afc70890bdafd358ff9b20d32420d..96b8102773cbee2c3fe2711008ba1487084d67b0 100644 ---- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -32,6 +32,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.stats.Stats; -+import org.bukkit.Material; // Paper - import org.bukkit.event.entity.EntityPickupItemEvent; - import org.bukkit.event.player.PlayerPickupItemEvent; - // CraftBukkit end -@@ -160,7 +161,7 @@ public class ItemEntity extends Entity { - } - } - -- if (!this.level.isClientSide && this.age >= level.spigotConfig.itemDespawnRate) { // Spigot -+ if (!this.level.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper - // CraftBukkit start - fire ItemDespawnEvent - if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { - this.age = 0; -@@ -184,7 +185,7 @@ public class ItemEntity extends Entity { - this.lastTick = MinecraftServer.currentTick; - // CraftBukkit end - -- if (!this.level.isClientSide && this.age >= level.spigotConfig.itemDespawnRate) { // Spigot -+ if (!this.level.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper - // CraftBukkit start - fire ItemDespawnEvent - if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { - this.age = 0; -@@ -534,9 +535,16 @@ public class ItemEntity extends Entity { - - public void makeFakeItem() { - this.setNeverPickUp(); -- this.age = level.spigotConfig.itemDespawnRate - 1; // Spigot -+ this.age = this.getDespawnRate() - 1; // Spigot // Paper - } - -+ // Paper start -+ public int getDespawnRate(){ -+ Material material = this.getItem().getBukkitStack().getType(); -+ return level.paperConfig.altItemDespawnRateMap.getOrDefault(material, level.spigotConfig.itemDespawnRate); -+ } -+ // Paper end -+ - @Override - public Packet getAddEntityPacket() { - return new ClientboundAddEntityPacket(this); diff --git a/Remapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/Remapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch deleted file mode 100644 index eab9bd3397..0000000000 --- a/Remapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Paul Sauve -Date: Sun, 14 Jul 2019 21:05:03 -0500 -Subject: [PATCH] Do less work if we have a custom Bukkit generator - -If the Bukkit generator already has a spawn, use it immediately instead -of spending time generating one that we won't use - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 643d75b999c3da006eaaab11f4acd77e807683d4..753e6f609189c589514739bea80007bace3c89d2 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -628,12 +628,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -- return biomebase.getMobSettings().playerSpawnFriendly(); -- }, random); -- ChunkPos chunkcoordintpair = blockposition == null ? new ChunkPos(0, 0) : new ChunkPos(blockposition); -+ // Paper start - moved down - // CraftBukkit start - if (world.generator != null) { - Random rand = new Random(world.getSeed()); -@@ -649,6 +644,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -+ return biomebase.getMobSettings().playerSpawnFriendly(); -+ }, random); -+ ChunkPos chunkcoordintpair = blockposition == null ? new ChunkPos(0, 0) : new ChunkPos(blockposition); -+ // Paper end - - if (blockposition == null) { - MinecraftServer.LOGGER.warn("Unable to find spawn biome"); diff --git a/Remapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch b/Remapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch deleted file mode 100644 index 585e674b4b..0000000000 --- a/Remapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 13 Aug 2019 06:35:17 -0700 -Subject: [PATCH] Fix MC-158900 - -The problem was we were checking isExpired() on the entry, but if it -was expired at that point, then it would be null. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7412765020854caabd32fb6f4fffcf7f4bf6dba7..e6eebb8f6f48cc55fc8fb114c959b8fbec4b8472 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -603,8 +603,10 @@ public abstract class PlayerList { - Player player = entity.getBukkitEntity(); - PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.connection.getRawAddress()).getAddress()); - -- if (getBans().isBanned(gameprofile) && !getBans().get(gameprofile).hasExpired()) { -- UserBanListEntry gameprofilebanentry = (UserBanListEntry) this.bans.get(gameprofile); -+ // Paper start - Fix MC-158900 -+ UserBanListEntry gameprofilebanentry; -+ if (getBans().isBanned(gameprofile) && (gameprofilebanentry = getBans().get(gameprofile)) != null) { -+ // Paper end - - chatmessage = new TranslatableComponent("multiplayer.disconnect.banned.reason", new Object[]{gameprofilebanentry.getReason()}); - if (gameprofilebanentry.getExpires() != null) { diff --git a/Remapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch b/Remapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch deleted file mode 100644 index 70bcd1b1bd..0000000000 --- a/Remapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch +++ /dev/null @@ -1,924 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Mon, 19 Aug 2019 01:27:58 +0500 -Subject: [PATCH] implement optional per player mob spawns - - -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -index 24eac9400fbf971742e89bbf47b0ba52b587c4eb..b818a7451d45d2ab7d4678f0065ada9017d8a631 100644 ---- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -58,6 +58,7 @@ public class WorldTimingsHandler { - - - public final Timing miscMobSpawning; -+ public final Timing playerMobDistanceMapUpdate; - - public final Timing poiUnload; - public final Timing chunkUnload; -@@ -123,6 +124,7 @@ public class WorldTimingsHandler { - - - miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ playerMobDistanceMapUpdate = Timings.ofSafe(name + "Per Player Mob Spawning - Distance Map Update"); - - poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); - chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920..6aec502eb529d4090306e12e837117cde7e114eb 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -565,4 +565,9 @@ public class PaperWorldConfig { - } - } - } -+ -+ public boolean perPlayerMobSpawns = false; -+ private void perPlayerMobSpawns() { -+ perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2a87599922d7075a9f888f48a2deb35ed3eb7c54 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java -@@ -0,0 +1,252 @@ -+package com.destroystokyo.paper.util; -+ -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; -+import java.util.List; -+import java.util.Map; -+import net.minecraft.core.SectionPos; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.world.level.ChunkPos; -+import org.spigotmc.AsyncCatcher; -+import java.util.HashMap; -+ -+/** @author Spottedleaf */ -+public final class PlayerMobDistanceMap { -+ -+ private static final PooledHashSets.PooledObjectLinkedOpenHashSet EMPTY_SET = new PooledHashSets.PooledObjectLinkedOpenHashSet<>(); -+ -+ private final Map players = new HashMap<>(); -+ // we use linked for better iteration. -+ private final Long2ObjectOpenHashMap> playerMap = new Long2ObjectOpenHashMap<>(32, 0.5f); -+ private int viewDistance; -+ -+ private final PooledHashSets pooledHashSets = new PooledHashSets<>(); -+ -+ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final ChunkPos chunkPos) { -+ return this.getPlayersInRange(chunkPos.x, chunkPos.z); -+ } -+ -+ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final int chunkX, final int chunkZ) { -+ return this.playerMap.getOrDefault(ChunkPos.asLong(chunkX, chunkZ), EMPTY_SET); -+ } -+ -+ public void update(final List currentPlayers, final int newViewDistance) { -+ AsyncCatcher.catchOp("Distance map update"); -+ final ObjectLinkedOpenHashSet gone = new ObjectLinkedOpenHashSet<>(this.players.keySet()); -+ -+ final int oldViewDistance = this.viewDistance; -+ this.viewDistance = newViewDistance; -+ -+ for (final ServerPlayer player : currentPlayers) { -+ if (player.isSpectator() || !player.affectsSpawning) { -+ continue; // will be left in 'gone' (or not added at all) -+ } -+ -+ gone.remove(player); -+ -+ final SectionPos newPosition = player.getPlayerMapSection(); -+ final SectionPos oldPosition = this.players.put(player, newPosition); -+ -+ if (oldPosition == null) { -+ this.addNewPlayer(player, newPosition, newViewDistance); -+ } else { -+ this.updatePlayer(player, oldPosition, newPosition, oldViewDistance, newViewDistance); -+ } -+ //this.validatePlayer(player, newViewDistance); // debug only -+ } -+ -+ for (final ServerPlayer player : gone) { -+ final SectionPos oldPosition = this.players.remove(player); -+ if (oldPosition != null) { -+ this.removePlayer(player, oldPosition, oldViewDistance); -+ } -+ } -+ } -+ -+ // expensive op, only for debug -+ private void validatePlayer(final ServerPlayer player, final int viewDistance) { -+ int entiesGot = 0; -+ int expectedEntries = (2 * viewDistance + 1); -+ expectedEntries *= expectedEntries; -+ -+ final SectionPos currPosition = player.getPlayerMapSection(); -+ -+ final int centerX = currPosition.getX(); -+ final int centerZ = currPosition.getZ(); -+ -+ for (final Long2ObjectLinkedOpenHashMap.Entry> entry : this.playerMap.long2ObjectEntrySet()) { -+ final long key = entry.getLongKey(); -+ final PooledHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); -+ -+ if (map.referenceCount == 0) { -+ throw new IllegalStateException("Invalid map"); -+ } -+ -+ if (map.set.contains(player)) { -+ ++entiesGot; -+ -+ final int chunkX = ChunkPos.getX(key); -+ final int chunkZ = ChunkPos.getZ(key); -+ -+ final int dist = Math.max(Math.abs(chunkX - centerX), Math.abs(chunkZ - centerZ)); -+ -+ if (dist > viewDistance) { -+ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); -+ } -+ } -+ } -+ -+ if (entiesGot != expectedEntries) { -+ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); -+ } -+ } -+ -+ private void addPlayerTo(final ServerPlayer player, final int chunkX, final int chunkZ) { -+ this.playerMap.compute(ChunkPos.asLong(chunkX, chunkZ), (final Long key, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { -+ if (players == null) { -+ return player.cachedSingleMobDistanceMap; -+ } else { -+ return PlayerMobDistanceMap.this.pooledHashSets.findMapWith(players, player); -+ } -+ }); -+ } -+ -+ private void removePlayerFrom(final ServerPlayer player, final int chunkX, final int chunkZ) { -+ this.playerMap.compute(ChunkPos.asLong(chunkX, chunkZ), (final Long keyInMap, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { -+ return PlayerMobDistanceMap.this.pooledHashSets.findMapWithout(players, player); // rets null instead of an empty map -+ }); -+ } -+ -+ private void updatePlayer(final ServerPlayer player, final SectionPos oldPosition, final SectionPos newPosition, final int oldViewDistance, final int newViewDistance) { -+ final int toX = newPosition.getX(); -+ final int toZ = newPosition.getZ(); -+ final int fromX = oldPosition.getX(); -+ final int fromZ = oldPosition.getZ(); -+ -+ final int dx = toX - fromX; -+ final int dz = toZ - fromZ; -+ -+ final int totalX = Math.abs(fromX - toX); -+ final int totalZ = Math.abs(fromZ - toZ); -+ -+ if (Math.max(totalX, totalZ) > (2 * oldViewDistance)) { -+ // teleported? -+ this.removePlayer(player, oldPosition, oldViewDistance); -+ this.addNewPlayer(player, newPosition, newViewDistance); -+ return; -+ } -+ -+ // x axis is width -+ // z axis is height -+ // right refers to the x axis of where we moved -+ // top refers to the z axis of where we moved -+ -+ if (oldViewDistance == newViewDistance) { -+ // same view distance -+ -+ // used for relative positioning -+ final int up = 1 | (dz >> (Integer.SIZE - 1)); // 1 if dz >= 0, -1 otherwise -+ final int right = 1 | (dx >> (Integer.SIZE - 1)); // 1 if dx >= 0, -1 otherwise -+ -+ // The area excluded by overlapping the two view distance squares creates four rectangles: -+ // Two on the left, and two on the right. The ones on the left we consider the "removed" section -+ // and on the right the "added" section. -+ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually -+ // exclusive to the regions they surround. -+ -+ // 4 points of the rectangle -+ int maxX; // exclusive -+ int minX; // inclusive -+ int maxZ; // exclusive -+ int minZ; // inclusive -+ -+ if (dx != 0) { -+ // handle right addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX + (oldViewDistance * right) + right; // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addPlayerTo(player, currX, currZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle up addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = toX - (oldViewDistance * right); // inclusive -+ maxZ = toZ + (oldViewDistance * up) + up; // exclusive -+ minZ = fromZ + (oldViewDistance * up) + up; // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addPlayerTo(player, currX, currZ); -+ } -+ } -+ } -+ -+ if (dx != 0) { -+ // handle left removal -+ -+ maxX = toX - (oldViewDistance * right); // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removePlayerFrom(player, currX, currZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle down removal -+ -+ maxX = fromX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = toZ - (oldViewDistance * up); // exclusive -+ minZ = fromZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removePlayerFrom(player, currX, currZ); -+ } -+ } -+ } -+ } else { -+ // different view distance -+ // for now :) -+ this.removePlayer(player, oldPosition, oldViewDistance); -+ this.addNewPlayer(player, newPosition, newViewDistance); -+ } -+ } -+ -+ private void removePlayer(final ServerPlayer player, final SectionPos position, final int viewDistance) { -+ final int x = position.getX(); -+ final int z = position.getZ(); -+ -+ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { -+ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { -+ this.removePlayerFrom(player, x + xoff, z + zoff); -+ } -+ } -+ } -+ -+ private void addNewPlayer(final ServerPlayer player, final SectionPos position, final int viewDistance) { -+ final int x = position.getX(); -+ final int z = position.getZ(); -+ -+ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { -+ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { -+ this.addPlayerTo(player, x + xoff, z + zoff); -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4f13d3ff8391793a99f067189f854078334499c6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java -@@ -0,0 +1,241 @@ -+package com.destroystokyo.paper.util; -+ -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; -+import java.lang.ref.WeakReference; -+import java.util.Iterator; -+ -+/** @author Spottedleaf */ -+public class PooledHashSets { -+ -+ // we really want to avoid that equals() check as much as possible... -+ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(64, 0.25f); -+ -+ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { -+ if (current.referenceCount == 0) { -+ throw new IllegalStateException("Cannot decrement reference count for " + current); -+ } -+ if (current.referenceCount == -1 || --current.referenceCount > 0) { -+ return; -+ } -+ -+ this.mapPool.remove(current); -+ return; -+ } -+ -+ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { -+ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); -+ -+ if (cached != null) { -+ if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ decrementReferenceCount(current); -+ -+ return cached; -+ } -+ -+ if (!current.add(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.remove(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.remove(object); -+ } -+ -+ current.updateAddCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ // rets null if current.size() == 1 -+ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { -+ if (current.set.size() == 1) { -+ decrementReferenceCount(current); -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); -+ -+ if (cached != null) { -+ if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ decrementReferenceCount(current); -+ -+ return cached; -+ } -+ -+ if (!current.remove(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.add(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.add(object); -+ } -+ -+ current.updateRemoveCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ public static final class PooledObjectLinkedOpenHashSet implements Iterable { -+ -+ private static final WeakReference NULL_REFERENCE = new WeakReference(null); -+ -+ final ObjectLinkedOpenHashSet set; -+ int referenceCount; // -1 if special -+ int hash; // optimize hashcode -+ -+ // add cache -+ WeakReference lastAddObject = NULL_REFERENCE; -+ WeakReference> lastAddMap = NULL_REFERENCE; -+ -+ // remove cache -+ WeakReference lastRemoveObject = NULL_REFERENCE; -+ WeakReference> lastRemoveMap = NULL_REFERENCE; -+ -+ public PooledObjectLinkedOpenHashSet() { -+ this.set = new ObjectLinkedOpenHashSet<>(2, 0.6f); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final E single) { -+ this(); -+ this.referenceCount = -1; -+ this.add(single); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { -+ this.set = other.set.clone(); -+ this.hash = other.hash; -+ } -+ -+ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java -+ // generated by https://github.com/skeeto/hash-prospector -+ static int hash0(int x) { -+ x *= 0x36935555; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ public PooledObjectLinkedOpenHashSet getAddCache(final E element) { -+ final E currentAdd = this.lastAddObject.get(); -+ -+ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet map = this.lastAddMap.get(); -+ if (map == null || map.referenceCount == 0) { -+ // we need to ret null if ref count is zero as calling code will assume the map is in use -+ return null; -+ } -+ -+ return map; -+ } -+ -+ public PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { -+ final E currentRemove = this.lastRemoveObject.get(); -+ -+ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet map = this.lastRemoveMap.get(); -+ if (map == null || map.referenceCount == 0) { -+ // we need to ret null if ref count is zero as calling code will assume the map is in use -+ return null; -+ } -+ -+ return map; -+ } -+ -+ public void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastAddObject = new WeakReference<>(element); -+ this.lastAddMap = new WeakReference<>(map); -+ } -+ -+ public void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastRemoveObject = new WeakReference<>(element); -+ this.lastRemoveMap = new WeakReference<>(map); -+ } -+ -+ boolean add(final E element) { -+ boolean added = this.set.add(element); -+ -+ if (added) { -+ this.hash += hash0(element.hashCode()); -+ } -+ -+ return added; -+ } -+ -+ boolean remove(Object element) { -+ boolean removed = this.set.remove(element); -+ -+ if (removed) { -+ this.hash -= hash0(element.hashCode()); -+ } -+ -+ return removed; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return this.set.iterator(); -+ } -+ -+ @Override -+ public int hashCode() { -+ return this.hash; -+ } -+ -+ @Override -+ public boolean equals(final Object other) { -+ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { -+ return false; -+ } -+ if (this.referenceCount == 0) { -+ return other == this; -+ } else { -+ if (other == this) { -+ // Unfortunately we are never equal to our own instance while in use! -+ return false; -+ } -+ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); -+ } -+ } -+ -+ @Override -+ public String toString() { -+ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + -+ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index c00f7c60ce7b497d697d1abdf230f91f327e2113..190ddd4d9ef3472c33d46c2ead72fa0dc918054a 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -71,6 +71,7 @@ import net.minecraft.util.thread.ProcessorMailbox; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; - import net.minecraft.world.entity.Mob; -+import net.minecraft.world.entity.MobCategory; - import net.minecraft.world.entity.ai.village.poi.PoiManager; - import net.minecraft.world.entity.boss.EnderDragonPart; - import net.minecraft.world.level.ChunkPos; -@@ -127,7 +128,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public final Int2ObjectMap entityMap; - private final Long2ByteMap chunkTypeCache; - private final Queue unloadQueue; private final Queue getUnloadQueueTasks() { return this.unloadQueue; } // Paper - OBFHELPER -- private int viewDistance; -+ int viewDistance; // Paper - private -> package private -+ public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper - - // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() - public final CallbackExecutor callbackExecutor = new CallbackExecutor(); -@@ -206,6 +208,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.overworldDataStorage = supplier; - this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper - this.setViewDistance(i); -+ this.playerMobDistanceMap = this.level.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper -+ } -+ -+ public void updatePlayerMobTypeMap(Entity entity) { -+ if (!this.level.paperConfig.perPlayerMobSpawns) { -+ return; -+ } -+ int chunkX = (int)Math.floor(entity.getX()) >> 4; -+ int chunkZ = (int)Math.floor(entity.getZ()) >> 4; -+ int index = entity.getType().getEnumCreatureType().ordinal(); -+ -+ for (ServerPlayer player : this.playerMobDistanceMap.getPlayersInRange(chunkX, chunkZ)) { -+ ++player.mobCounts[index]; -+ } -+ } -+ -+ public int getMobCountNear(ServerPlayer entityPlayer, MobCategory enumCreatureType) { -+ return entityPlayer.mobCounts[enumCreatureType.ordinal()]; - } - - private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 5e0d55c3821b1769d20514a8a6c5c74477019778..eac5e799c4d26e53286a27c54b56899ba0b9ffb2 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -768,7 +768,22 @@ public class ServerChunkCache extends ChunkSource { - this.level.getProfiler().push("naturalSpawnCount"); - this.level.timings.countNaturalMobs.startTiming(); // Paper - timings - int l = this.distanceManager.getNaturalSpawnChunkCount(); -- NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk); -+ // Paper start - per player mob spawning -+ NaturalSpawner.SpawnState spawnercreature_d; // moved down -+ if (this.chunkMap.playerMobDistanceMap != null) { -+ // update distance map -+ this.level.timings.playerMobDistanceMapUpdate.startTiming(); -+ this.chunkMap.playerMobDistanceMap.update(this.level.players, this.chunkMap.viewDistance); -+ this.level.timings.playerMobDistanceMapUpdate.stopTiming(); -+ // re-set mob counts -+ for (ServerPlayer player : this.level.players) { -+ Arrays.fill(player.mobCounts, 0); -+ } -+ spawnercreature_d = NaturalSpawner.countMobs(l, this.level.getAllEntities(), this::getFullChunk, true); -+ } else { -+ spawnercreature_d = NaturalSpawner.countMobs(l, this.level.getAllEntities(), this::getFullChunk, false); -+ } -+ // Paper end - this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings - - this.lastSpawnState = spawnercreature_d; -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index d6cfe68be1a944ff5d5780666467f5fd8e2794e3..b0eed4e18fc183856613c05f378576eb19985c46 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -93,6 +93,7 @@ import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.HumanoidArm; - import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.Mob; -+import net.minecraft.world.entity.MobCategory; - import net.minecraft.world.entity.NeutralMob; - import net.minecraft.world.entity.animal.horse.AbstractHorse; - import net.minecraft.world.entity.item.ItemEntity; -@@ -216,6 +217,11 @@ public class ServerPlayer extends Player implements ContainerListener { - public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; - // Paper end -+ // Paper start - mob spawning rework -+ public static final int ENUMCREATURETYPE_TOTAL_ENUMS = MobCategory.values().length; -+ public final int[] mobCounts = new int[ENUMCREATURETYPE_TOTAL_ENUMS]; // Paper -+ public final com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet cachedSingleMobDistanceMap; -+ // Paper end - - // CraftBukkit start - public String displayName; -@@ -254,6 +260,7 @@ public class ServerPlayer extends Player implements ContainerListener { - this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper - this.canPickUpLoot = true; - this.maxHealthCache = this.getMaxHealth(); -+ this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper - } - - // Yes, this doesn't match Vanilla, but it's the best we can do for now. -@@ -2058,6 +2065,7 @@ public class ServerPlayer extends Player implements ContainerListener { - - } - -+ public final SectionPos getPlayerMapSection() { return this.getLastSectionPos(); } // Paper - OBFHELPER - public SectionPos getLastSectionPos() { - return this.lastSectionPos; - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index e39d950783599b01271bdb7e67fe68b46af0c49c..ae50030df7512c56c552e800b74ef4c69ec6d6d2 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -426,6 +426,7 @@ public class EntityType { - return this.canSpawnFarFromPlayer; - } - -+ public final MobCategory getEnumCreatureType() { return this.getCategory(); } // Paper - OBFHELPER - public MobCategory getCategory() { - return this.category; - } -diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 0fb69f9194078e5e05e36ed909eb48424b6465b4..df271598f6036c8cab8a8811151a376dda46e44d 100644 ---- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java -+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -17,6 +17,7 @@ import net.minecraft.core.Registry; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.tags.BlockTags; - import net.minecraft.tags.FluidTags; - import net.minecraft.tags.Tag; -@@ -60,9 +61,14 @@ public final class NaturalSpawner { - }); - - public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkSource) { -+ // Paper start - add countMobs parameter -+ return countMobs(spawningChunkCount, entities, chunkSource, false); -+ } -+ public static NaturalSpawner.SpawnState countMobs(int i, Iterable iterable, NaturalSpawner.ChunkGetter spawnercreature_b, boolean countMobs) { -+ // Paper end - add countMobs parameter - PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator(); - Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); -- Iterator iterator = entities.iterator(); -+ Iterator iterator = iterable.iterator(); - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); -@@ -89,7 +95,7 @@ public final class NaturalSpawner { - BlockPos blockposition = entity.blockPosition(); - long j = ChunkPos.asLong(blockposition.getX() >> 4, blockposition.getZ() >> 4); - -- chunkSource.query(j, (chunk) -> { -+ spawnercreature_b.query(j, (chunk) -> { - MobSpawnSettings.MobSpawnCost biomesettingsmobs_b = getRoughBiome(blockposition, chunk).getMobSettings().getMobSpawnCost(entity.getType()); - - if (biomesettingsmobs_b != null) { -@@ -97,11 +103,16 @@ public final class NaturalSpawner { - } - - object2intopenhashmap.addTo(enumcreaturetype, 1); -+ // Paper start -+ if (countMobs) { -+ ((ServerLevel)chunk.world).getChunkSource().chunkMap.updatePlayerMobTypeMap(entity); -+ } -+ // Paper end - }); - } - } - -- return new NaturalSpawner.SpawnState(spawningChunkCount, object2intopenhashmap, spawnercreatureprobabilities); -+ return new NaturalSpawner.SpawnState(i, object2intopenhashmap, spawnercreatureprobabilities); - } - - private static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) { -@@ -155,13 +166,31 @@ public final class NaturalSpawner { - continue; - } - -- if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (shouldSpawnAnimals || !enumcreaturetype.isPersistent()) && info.a(enumcreaturetype, limit)) { -+ // Paper start - only allow spawns upto the limit per chunk and update count afterwards -+ int currEntityCount = info.getEntityCountsByType().getInt(enumcreaturetype); -+ int k1 = limit * info.getSpawnerChunks() / NaturalSpawner.MAGIC_NUMBER; -+ int difference = k1 - currEntityCount; -+ -+ if (world.paperConfig.perPlayerMobSpawns) { -+ int minDiff = Integer.MAX_VALUE; -+ for (ServerPlayer entityplayer : world.getChunkSource().chunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) { -+ minDiff = Math.min(limit - world.getChunkSource().chunkMap.getMobCountNear(entityplayer, enumcreaturetype), minDiff); -+ } -+ difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff; -+ } -+ // Paper end -+ -+ // Paper start - per player mob spawning -+ if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (shouldSpawnAnimals || !enumcreaturetype.isPersistent()) && difference > 0) { - // CraftBukkit end -- spawnCategoryForChunk(enumcreaturetype, world, chunk, (entitytypes, blockposition, ichunkaccess) -> { -+ int spawnCount = spawnMobs(enumcreaturetype, world, chunk, (entitytypes, blockposition, ichunkaccess) -> { - return info.canSpawn(entitytypes, blockposition, ichunkaccess); - }, (entityinsentient, ichunkaccess) -> { - info.afterSpawn(entityinsentient, ichunkaccess); -- }); -+ }, -+ difference, world.paperConfig.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null); -+ info.getEntityCountsByType().mergeInt(enumcreaturetype, spawnCount, Integer::sum); -+ // Paper end - per player mob spawning - } - } - -@@ -170,31 +199,43 @@ public final class NaturalSpawner { - } - - public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { -- BlockPos blockposition = getRandomPosWithin(world, chunk); -+ // Paper start - add parameters and int ret type -+ spawnMobs(group, world, chunk, checker, runner, Integer.MAX_VALUE, null); -+ } -+ public static int spawnMobs(MobCategory enumcreaturetype, ServerLevel worldserver, LevelChunk chunk, NaturalSpawner.SpawnPredicate spawnercreature_c, NaturalSpawner.AfterSpawnCallback spawnercreature_a, int maxSpawns, Consumer trackEntity) { -+ // Paper end - add parameters and int ret type -+ BlockPos blockposition = getRandomPosWithin(worldserver, chunk); - - if (blockposition.getY() >= 1) { -- spawnCategoryForPosition(group, world, (ChunkAccess) chunk, blockposition, checker, runner); -+ return spawnMobsInternal(enumcreaturetype, worldserver, (ChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a, maxSpawns, trackEntity); - } -+ return 0; // Paper - } - - public static void spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { -- StructureFeatureManager structuremanager = world.structureFeatureManager(); -- ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); -- int i = pos.getY(); -- BlockState iblockdata = world.getTypeIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn -- -- if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn -+ // Paper start - add maxSpawns parameter and return spawned mobs -+ spawnMobsInternal(group, world, chunk, pos, checker, runner, Integer.MAX_VALUE, null); -+ } -+ public static int spawnMobsInternal(MobCategory enumcreaturetype, ServerLevel worldserver, ChunkAccess ichunkaccess, BlockPos blockposition, NaturalSpawner.SpawnPredicate spawnercreature_c, NaturalSpawner.AfterSpawnCallback spawnercreature_a, int maxSpawns, Consumer trackEntity) { -+ // Paper end - add maxSpawns parameter and return spawned mobs -+ StructureFeatureManager structuremanager = worldserver.structureFeatureManager(); -+ ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); -+ int i = blockposition.getY(); -+ BlockState iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn -+ int j = 0; // Paper - moved up -+ -+ if (iblockdata != null && !iblockdata.isRedstoneConductor(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn - BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); -- int j = 0; -+ // Paper - moved up - int k = 0; - - while (k < 3) { -- int l = pos.getX(); -- int i1 = pos.getZ(); -+ int l = blockposition.getX(); -+ int i1 = blockposition.getZ(); - boolean flag = true; - MobSpawnSettings.SpawnerData biomesettingsmobs_c = null; - SpawnGroupData groupdataentity = null; -- int j1 = Mth.ceil(world.random.nextFloat() * 4.0F); -+ int j1 = Mth.ceil(worldserver.random.nextFloat() * 4.0F); - int k1 = 0; - int l1 = 0; - -@@ -202,53 +243,58 @@ public final class NaturalSpawner { - if (l1 < j1) { - label53: - { -- l += world.random.nextInt(6) - world.random.nextInt(6); -- i1 += world.random.nextInt(6) - world.random.nextInt(6); -+ l += worldserver.random.nextInt(6) - worldserver.random.nextInt(6); -+ i1 += worldserver.random.nextInt(6) - worldserver.random.nextInt(6); - blockposition_mutableblockposition.set(l, i, i1); - double d0 = (double) l + 0.5D; - double d1 = (double) i1 + 0.5D; -- Player entityhuman = world.getNearestPlayer(d0, (double) i, d1, -1.0D, false); -+ Player entityhuman = worldserver.getNearestPlayer(d0, (double) i, d1, -1.0D, false); - - if (entityhuman != null) { - double d2 = entityhuman.distanceToSqr(d0, (double) i, d1); - -- if (isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2) && world.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn -+ if (isRightDistanceToPlayerAndSpawnPoint(worldserver, ichunkaccess, blockposition_mutableblockposition, d2) && worldserver.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn - if (biomesettingsmobs_c == null) { -- biomesettingsmobs_c = getRandomSpawnMobAt(world, structuremanager, chunkgenerator, group, world.random, (BlockPos) blockposition_mutableblockposition); -+ biomesettingsmobs_c = getRandomSpawnMobAt(worldserver, structuremanager, chunkgenerator, enumcreaturetype, worldserver.random, (BlockPos) blockposition_mutableblockposition); - if (biomesettingsmobs_c == null) { - break label53; - } - -- j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); -+ j1 = biomesettingsmobs_c.minCount + worldserver.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); - } - - // Paper start -- Boolean doSpawning = a(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); -+ Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); - if (doSpawning == null) { -- return; -+ return j; // Paper - } -- if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { -+ if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, ichunkaccess)) { - // Paper end -- Mob entityinsentient = getMobForSpawn(world, biomesettingsmobs_c.type); -+ Mob entityinsentient = getMobForSpawn(worldserver, biomesettingsmobs_c.type); - - - if (entityinsentient == null) { -- return; -+ return j; // Paper - } - -- entityinsentient.moveTo(d0, (double) i, d1, world.random.nextFloat() * 360.0F, 0.0F); -- if (isValidPositionForMob(world, entityinsentient, d2)) { -- groupdataentity = entityinsentient.finalizeSpawn(world, world.getCurrentDifficultyAt(entityinsentient.blockPosition()), MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); -+ entityinsentient.moveTo(d0, (double) i, d1, worldserver.random.nextFloat() * 360.0F, 0.0F); -+ if (isValidPositionForMob(worldserver, entityinsentient, d2)) { -+ groupdataentity = entityinsentient.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(entityinsentient.blockPosition()), MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); - // CraftBukkit start -- world.addAllEntities(entityinsentient, SpawnReason.NATURAL); -+ worldserver.addAllEntities(entityinsentient, SpawnReason.NATURAL); - if (!entityinsentient.removed) { -- ++j; -+ ++j; // Paper - force diff on name change - we expect this to be the total amount spawned - ++k1; -- runner.run(entityinsentient, chunk); -+ spawnercreature_a.run(entityinsentient, ichunkaccess); -+ // Paper start -+ if (trackEntity != null) { -+ trackEntity.accept(entityinsentient); -+ } -+ // Paper end - } - // CraftBukkit end -- if (j >= entityinsentient.getMaxSpawnClusterSize()) { -- return; -+ if (j >= entityinsentient.getMaxSpawnClusterSize() || j >= maxSpawns) { // Paper -+ return j; // Paper - } - - if (entityinsentient.isMaxGroupSizeReached(k1)) { -@@ -270,6 +316,7 @@ public final class NaturalSpawner { - } - - } -+ return j; // Paper - } - - private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) { -@@ -510,8 +557,8 @@ public final class NaturalSpawner { - - public static class SpawnState { - -- private final int spawnableChunkCount; -- private final Object2IntOpenHashMap mobCategoryCounts; -+ private final int spawnableChunkCount; final int getSpawnerChunks() { return this.spawnableChunkCount; } // Paper - OBFHELPER -+ private final Object2IntOpenHashMap mobCategoryCounts; final Object2IntMap getEntityCountsByType() { return this.mobCategoryCounts; } // Paper - OBFHELPER - private final PotentialCalculator spawnPotential; - private final Object2IntMap unmodifiableMobCategoryCounts; - @Nullable -@@ -572,7 +619,7 @@ public final class NaturalSpawner { - - // CraftBukkit start - private boolean a(MobCategory enumcreaturetype, int limit) { -- int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; -+ int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; // Paper - diff on change, needed in the spawn method - // CraftBukkit end - - return this.mobCategoryCounts.getInt(enumcreaturetype) < i; diff --git a/Remapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch b/Remapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch deleted file mode 100644 index 32aa3ddc1d..0000000000 --- a/Remapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Mon, 19 Aug 2019 19:42:35 +0500 -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 046a05925739005080af35c4be984303b575bf68..f8917123547615dd624e3e428ec1bf6450c7b7d8 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3198,15 +3198,18 @@ public abstract class LivingEntity extends Entity { - this.entityData.set(LivingEntity.DATA_LIVING_ENTITY_FLAGS, (byte) j); - } - -- public void startUsingItem(InteractionHand hand) { -- ItemStack itemstack = this.getItemInHand(hand); -+ // Paper start -- OBFHELPER and forwarder to method with forceUpdate parameter -+ public void startUsingItem(InteractionHand hand) { this.updateActiveItem(hand, false); } -+ public void updateActiveItem(InteractionHand enumhand, boolean forceUpdate) { -+ // Paper end -+ ItemStack itemstack = this.getItemInHand(enumhand); - -- if (!itemstack.isEmpty() && !this.isUsingItem()) { -+ if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag - this.useItem = itemstack; - this.useItemRemaining = itemstack.getUseDuration(); - if (!this.level.isClientSide) { - this.setLivingEntityFlag(1, true); -- this.setLivingEntityFlag(2, hand == InteractionHand.OFF_HAND); -+ this.setLivingEntityFlag(2, enumhand == InteractionHand.OFF_HAND); - } - - } -@@ -3279,6 +3282,7 @@ public abstract class LivingEntity extends Entity { - this.releaseUsingItem(); - } else { - if (!this.useItem.isEmpty() && this.isUsingItem()) { -+ this.updateActiveItem(this.getUsedItemHand(), true); // Paper - this.triggerItemUseEffects(this.useItem, 16); - // CraftBukkit start - fire PlayerItemConsumeEvent - ItemStack itemstack; -@@ -3313,8 +3317,8 @@ public abstract class LivingEntity extends Entity { - } - - this.stopUsingItem(); -- // Paper start - if the replacement is anything but the default, update the client inventory -- if (this instanceof ServerPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { -+ // Paper start -+ if (this instanceof ServerPlayer) { - ((ServerPlayer) this).getBukkitEntity().updateInventory(); - } - // Paper end diff --git a/Remapped-Spigot-Server-Patches/0376-Generator-Settings.patch b/Remapped-Spigot-Server-Patches/0376-Generator-Settings.patch deleted file mode 100644 index fe0b780b55..0000000000 --- a/Remapped-Spigot-Server-Patches/0376-Generator-Settings.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 02:17:54 -0600 -Subject: [PATCH] Generator Settings - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6aec502eb529d4090306e12e837117cde7e114eb..290e49cf0077909ad7ab8127c01ef93cf7b70b51 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -570,4 +570,9 @@ public class PaperWorldConfig { - private void perPlayerMobSpawns() { - perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); - } -+ -+ public boolean generateFlatBedrock; -+ private void generatorSettings() { -+ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -index e6303cdb433ee2b6782e2a0bd6b03e4f6ecb18ba..36c7ab3919d8818af96d50170aeb431051c5aabf 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -@@ -25,6 +25,18 @@ import org.apache.logging.log4j.LogManager; - - public interface ChunkAccess extends BlockGetter, FeatureAccess { - -+ // Paper start -+ default boolean generateFlatBedrock() { -+ if (this instanceof ProtoChunk) { -+ return ((ProtoChunk)this).world.paperConfig.generateFlatBedrock; -+ } else if (this instanceof LevelChunk) { -+ return ((LevelChunk)this).world.paperConfig.generateFlatBedrock; -+ } else { -+ return false; -+ } -+ } -+ // Paper end -+ - BlockState getType(final int x, final int y, final int z); // Paper - @Nullable - BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 87fd585141ad9818fca0b697cb4c87248fe7ce11..5a94464b9628b74eefa1c1d8514cf267f4c8a11d 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -64,7 +64,7 @@ public class ProtoChunk implements ChunkAccess { - private long inhabitedTime; - private final Map carvingMasks; - private volatile boolean isLightCorrect; -- private final Level world; // Paper - Anti-Xray - Add world -+ final Level world; // Paper - Anti-Xray - Add world // Paper - private -> default - - // Paper start - Anti-Xray - Add world - @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { this(pos, upgradeData, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -index b38a9c87fc996bd3107c38f6446a687fd093c617..04adec255e4650ead8d80bee32a681c98686fb95 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -@@ -408,8 +408,8 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - int i = chunk.getPos().getMinBlockX(); - int j = chunk.getPos().getMinBlockZ(); - NoiseGeneratorSettings generatorsettingbase = (NoiseGeneratorSettings) this.settings.get(); -- int k = generatorsettingbase.getBedrockFloorPosition(); -- int l = this.height - 1 - generatorsettingbase.getBedrockRoofPosition(); -+ int k = generatorsettingbase.getBedrockFloorPosition(); final int floorHeight = k; // Paper -+ int l = this.height - 1 - generatorsettingbase.getBedrockRoofPosition(); final int roofHeight = l; // Paper - boolean flag = true; - boolean flag1 = l + 4 >= 0 && l < this.height; - boolean flag2 = k + 4 >= 0 && k < this.height; -@@ -423,7 +423,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - - if (flag1) { - for (i1 = 0; i1 < 5; ++i1) { -- if (i1 <= random.nextInt(5)) { -+ if (i1 <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof - chunk.setBlockState(blockposition_mutableblockposition.set(blockposition.getX(), l - i1, blockposition.getZ()), Blocks.BEDROCK.defaultBlockState(), false); - } - } -@@ -431,7 +431,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - - if (flag2) { - for (i1 = 4; i1 >= 0; --i1) { -- if (i1 <= random.nextInt(5)) { -+ if (i1 <= (chunk.generateFlatBedrock() ? floorHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor - chunk.setBlockState(blockposition_mutableblockposition.set(blockposition.getX(), k + i1, blockposition.getZ()), Blocks.BEDROCK.defaultBlockState(), false); - } - } diff --git a/Remapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch b/Remapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch deleted file mode 100644 index c50817dd4f..0000000000 --- a/Remapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 24 Sep 2019 16:03:00 -0700 -Subject: [PATCH] Fix MC-161754 - -Fixes https://github.com/PaperMC/Paper/issues/2580 - -We can use an entity valid check since this method is invoked for -each inventory iteraction (thanks to CB) and on player tick (vanilla). - -diff --git a/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java b/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java -index 7246b3a84415e303591adb08d81362201deebfce..e0237e821b2c31ba68168fddf1c1a4ebfcf10ca7 100644 ---- a/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java -@@ -85,7 +85,7 @@ public class HorseInventoryMenu extends AbstractContainerMenu { - - @Override - public boolean stillValid(Player player) { -- return this.horseContainer.stillValid(player) && this.horse.isAlive() && this.horse.distanceTo((Entity) player) < 8.0F; -+ return this.horseContainer.stillValid(player) && (this.horse.isAlive() && this.horse.valid) && this.horse.distanceTo((Entity) player) < 8.0F; // Paper - Fix MC-161754 - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch b/Remapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch deleted file mode 100644 index 439bca032a..0000000000 --- a/Remapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: wea_ondara -Date: Thu, 10 Oct 2019 11:29:42 +0200 -Subject: [PATCH] Performance improvement for Chunk.getEntities - -This patch aims to reduce performance cost used by collecting the -entities of a chunk. Previously the entitySlices were copied into an -extra array with List.toArray() with is a costly and unneccessary -operation. This patch will reduce the load of plugins which for example -implement custom moblimits and depend on Chunk.getEntities(). - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index 74bad15034d9d55fb70931f38868f812160c6305..0f45f4b2486e910d11fd94b260bcd68e49eae31e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -116,14 +116,14 @@ public class CraftChunk implements Chunk { - Entity[] entities = new Entity[count]; - - for (int i = 0; i < 16; i++) { -- -- for (Object obj : chunk.entitySlices[i].toArray()) { -- if (!(obj instanceof net.minecraft.world.entity.Entity)) { -+ // Paper start - speed up (was with chunk.entitySlices[i].toArray() and cast checks which costs a lot of performance if called often) -+ for (net.minecraft.world.entity.Entity entity : chunk.entitySlices[i]) { -+ if (entity == null) { - continue; - } -- -- entities[index++] = ((net.minecraft.world.entity.Entity) obj).getBukkitEntity(); -+ entities[index++] = entity.getBukkitEntity(); - } -+ // Paper end - } - - return entities; diff --git a/Remapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/Remapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch deleted file mode 100644 index 548deb2cdf..0000000000 --- a/Remapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterErwin -Date: Wed, 30 Oct 2019 16:57:54 +0100 -Subject: [PATCH] Fix spawning of hanging entities that are not ItemFrames and - can not face UP or DOWN - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 52444619a4bae80a12bf296fbe07fa811adf806e..fb74bdcf4c2935b56e92717cc5a1504fbc853d0a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1868,7 +1868,12 @@ public class CraftWorld implements World { - height = 9; - } - -- BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; -+ // Paper start - In addition to d65a2576e40e58c8e446b330febe6799d13a604f do not check UP/DOWN for non item frames -+ // BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; -+ BlockFace[] faces = (ItemFrame.class.isAssignableFrom(clazz)) -+ ? new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN} -+ : new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH}; -+ // Paper end - final BlockPos pos = new BlockPos(x, y, z); - for (BlockFace dir : faces) { - net.minecraft.world.level.block.state.BlockState nmsBlock = world.getBlockState(pos.relative(CraftBlock.blockFaceToNotch(dir))); diff --git a/Remapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch b/Remapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch deleted file mode 100644 index 9cf110529d..0000000000 --- a/Remapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 20 Apr 2019 19:47:34 -0500 -Subject: [PATCH] Expose the internal current tick - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 96a3a4d89df858d4e46a36f110dd9ad3a2061433..3c0ba80bbba19f3725013e118cecdbac5612deec 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2363,5 +2363,10 @@ public final class CraftServer implements Server { - } - return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); - } -+ -+ @Override -+ public int getCurrentTick() { -+ return net.minecraft.server.MinecraftServer.currentTick; -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/Remapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch deleted file mode 100644 index 169ff964a9..0000000000 --- a/Remapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 9 Oct 2019 21:51:43 -0500 -Subject: [PATCH] Fix stuck in sneak when changing worlds (MC-10657) - - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index b0eed4e18fc183856613c05f378576eb19985c46..2ef273e3b917803f3e2ac3c6a22d92a15b9eb71a 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1070,6 +1070,8 @@ public class ServerPlayer extends Player implements ContainerListener { - this.lastSentHealth = -1.0F; - this.lastSentFood = -1; - -+ setShiftKeyDown(false); // Paper - fix MC-10657 -+ - // CraftBukkit start - PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); - this.level.getCraftServer().getPluginManager().callEvent(changeEvent); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index e6eebb8f6f48cc55fc8fb114c959b8fbec4b8472..dfdde9722bc0d83916779014b7718eef2c01b3db 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -842,6 +842,8 @@ public abstract class PlayerList { - entityplayer.connection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobEffect)); - } - -+ entityplayer.setShiftKeyDown(false); // Paper - fix MC-10657 -+ - // Fire advancement trigger - entityplayer.triggerDimensionChangeTriggers(((CraftWorld) fromWorld).getHandle()); - diff --git a/Remapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch b/Remapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch deleted file mode 100644 index 2e772d88a3..0000000000 --- a/Remapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 9 Oct 2019 21:46:15 -0500 -Subject: [PATCH] Add option to disable pillager patrols - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 290e49cf0077909ad7ab8127c01ef93cf7b70b51..e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -575,4 +575,9 @@ public class PaperWorldConfig { - private void generatorSettings() { - generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); - } -+ -+ public boolean disablePillagerPatrols = false; -+ private void pillagerSettings() { -+ disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java -index caadd1a0fa6c4c446f84629088890a09e29622d9..48efe133d294bb1b17e8ac8b44eea8a29f15845f 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java -@@ -26,6 +26,7 @@ public class PatrolSpawner implements CustomSpawner { - - @Override - public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { -+ if (world.paperConfig.disablePillagerPatrols) return 0; // Paper - if (!spawnMonsters) { - return 0; - } else if (!world.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) { diff --git a/Remapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/Remapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch deleted file mode 100644 index 3d4d87429f..0000000000 --- a/Remapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lukasz Derlatka -Date: Mon, 11 Nov 2019 16:08:13 +0100 -Subject: [PATCH] Fix AssertionError when player hand set to empty type - -Fixes an AssertionError when setting the player's item in hand to null or a new ItemStack of Air in PlayerInteractEvent -Fixes GH-2718 - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index e45690b6197335ed1c07fa04c39b311b401724d7..2b79413bb8a592a7b7093e11d3a0cce895286c8f 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1706,6 +1706,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 - return; - } -+ // Paper start -+ itemstack = this.player.getItemInHand(enumhand); -+ if (itemstack.isEmpty()) return; -+ // Paper end - InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); - - if (enuminteractionresult.shouldSwing()) { -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index f8917123547615dd624e3e428ec1bf6450c7b7d8..b49d4772932a58852b3195f5f56ff93dbcabf766 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2153,6 +2153,7 @@ public abstract class LivingEntity extends Entity { - return predicate.test(this.getMainHandItem().getItem()) || predicate.test(this.getOffhandItem().getItem()); - } - -+ public final ItemStack getItemInHand(InteractionHand enumhand) { return this.getItemInHand(enumhand); } // Paper - OBFHELPER - public ItemStack getItemInHand(InteractionHand hand) { - if (hand == InteractionHand.MAIN_HAND) { - return this.getItemBySlot(EquipmentSlot.MAINHAND); diff --git a/Remapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch b/Remapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch deleted file mode 100644 index 886004a317..0000000000 --- a/Remapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch +++ /dev/null @@ -1,351 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 03:11:03 -0500 -Subject: [PATCH] PlayerLaunchProjectileEvent - - -diff --git a/src/main/java/net/minecraft/world/InteractionResultHolder.java b/src/main/java/net/minecraft/world/InteractionResultHolder.java -index 3bc22b977e00c1901a9025112e354e59fcc08a74..c12e2a65d30ca22db0c522e4b245009bcc38c4f4 100644 ---- a/src/main/java/net/minecraft/world/InteractionResultHolder.java -+++ b/src/main/java/net/minecraft/world/InteractionResultHolder.java -@@ -10,6 +10,7 @@ public class InteractionResultHolder { - this.object = value; - } - -+ public InteractionResult getResult() { return this.getResult(); } // Paper - OBFHELPER - public InteractionResult getResult() { - return this.result; - } -diff --git a/src/main/java/net/minecraft/world/item/EggItem.java b/src/main/java/net/minecraft/world/item/EggItem.java -index d2c4241104343a2d2283c358ab2247e333cf0dbf..5d03dcaf79a14946934a6732c94a195d3d65c56d 100644 ---- a/src/main/java/net/minecraft/world/item/EggItem.java -+++ b/src/main/java/net/minecraft/world/item/EggItem.java -@@ -25,21 +25,35 @@ public class EggItem extends Item { - - entityegg.setItem(itemstack); - entityegg.shootFromRotation(user, user.xRot, user.yRot, 0.0F, 1.5F, 1.0F); -- // CraftBukkit start -- if (!world.addFreshEntity(entityegg)) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityegg.getBukkitEntity()); -+ if (event.callEvent() && world.addFreshEntity(entityegg)) { -+ if (event.shouldConsume() && !user.abilities.instabuild) { -+ itemstack.shrink(1); -+ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { -+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ user.awardStat(Stats.ITEM_USED.get(this)); -+ } else { - if (user instanceof net.minecraft.server.level.ServerPlayer) { - ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); - } -- return InteractionResultHolder.fail(itemstack); -+ return new InteractionResultHolder(net.minecraft.world.InteractionResult.FAIL, itemstack); - } -- // CraftBukkit end -+ // Paper end -+ -+ - } - world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (EggItem.random.nextFloat() * 0.4F + 0.8F)); // CraftBukkit - from above - -- user.awardStat(Stats.ITEM_USED.get(this)); -- if (!user.abilities.instabuild) { -- itemstack.shrink(1); -+ /* // Paper start - moved up -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ if (!entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); - } -diff --git a/src/main/java/net/minecraft/world/item/EnderpearlItem.java b/src/main/java/net/minecraft/world/item/EnderpearlItem.java -index 347e95cc393e773de98b74e18cebbe05f612bdf6..a57c59b330766a2c784ddb7431719e9c1cc2fca8 100644 ---- a/src/main/java/net/minecraft/world/item/EnderpearlItem.java -+++ b/src/main/java/net/minecraft/world/item/EnderpearlItem.java -@@ -25,22 +25,37 @@ public class EnderpearlItem extends Item { - - entityenderpearl.setItem(itemstack); - entityenderpearl.shootFromRotation(user, user.xRot, user.yRot, 0.0F, 1.5F, 1.0F); -- if (!world.addFreshEntity(entityenderpearl)) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityenderpearl.getBukkitEntity()); -+ if (event.callEvent() && world.addFreshEntity(entityenderpearl)) { -+ if (event.shouldConsume() && !user.abilities.instabuild) { -+ itemstack.shrink(1); -+ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { -+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ user.awardStat(Stats.ITEM_USED.get(this)); -+ user.getCooldowns().addCooldown(this, 20); -+ } else { -+ // Paper end - if (user instanceof net.minecraft.server.level.ServerPlayer) { - ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); - } -- return InteractionResultHolder.fail(itemstack); -+ return new InteractionResultHolder(net.minecraft.world.InteractionResult.FAIL, itemstack); - } - } - -- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (EnderpearlItem.random.nextFloat() * 0.4F + 0.8F)); -- user.getCooldowns().addCooldown(this, 20); -- // CraftBukkit end -- -- user.awardStat(Stats.ITEM_USED.get(this)); -- if (!user.abilities.instabuild) { -- itemstack.shrink(1); -- } -+ // Paper start - moved up -+// world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F)); -+// entityhuman.getCooldownTracker().setCooldown(this, 20); -+// // CraftBukkit end -+// -+// entityhuman.b(StatisticList.ITEM_USED.b(this)); -+// if (!entityhuman.abilities.canInstantlyBuild) { -+// itemstack.subtract(1); -+// } -+ // Paper end - moved up - - return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); - } -diff --git a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java -index 032c476892c58a873242b00ca71fe084c719dcaa..0bd65165eacf6a54cdcc348991cf9adb44077bee 100644 ---- a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java -+++ b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java -@@ -1,10 +1,13 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.stats.Stats; - import net.minecraft.world.InteractionHand; -+import net.minecraft.world.InteractionResult; - import net.minecraft.world.InteractionResultHolder; -+import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.projectile.ThrownExperienceBottle; - import net.minecraft.world.level.Level; -@@ -24,19 +27,38 @@ public class ExperienceBottleItem extends Item { - public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { - ItemStack itemstack = user.getItemInHand(hand); - -- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (ExperienceBottleItem.random.nextFloat() * 0.4F + 0.8F)); -+ //world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); // Paper - moved down - if (!world.isClientSide) { - ThrownExperienceBottle entitythrownexpbottle = new ThrownExperienceBottle(world, user); - - entitythrownexpbottle.setItem(itemstack); - entitythrownexpbottle.shootFromRotation(user, user.xRot, user.yRot, -20.0F, 0.7F, 1.0F); -- world.addFreshEntity(entitythrownexpbottle); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitythrownexpbottle.getBukkitEntity()); -+ if (event.callEvent() && world.addFreshEntity(entitythrownexpbottle)) { -+ if (event.shouldConsume() && !user.abilities.instabuild) { -+ itemstack.shrink(1); -+ } else if (user instanceof ServerPlayer) { -+ ((ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ user.awardStat(Stats.ITEM_USED.get(this)); -+ } else { -+ if (user instanceof ServerPlayer) { -+ ((ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } -+ return new InteractionResultHolder(InteractionResult.FAIL, itemstack); -+ } -+ // Paper end - } - -- user.awardStat(Stats.ITEM_USED.get(this)); -- if (!user.abilities.instabuild) { -- itemstack.shrink(1); -+ /* // Paper start - moved up -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ if (!entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); - } -diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -index 28cffbe299acccc59c34d5dbd2cf458704be5ee5..4a70582bada607e1efcd826d58d725a0cc95e3c3 100644 ---- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -+++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -@@ -3,6 +3,7 @@ package net.minecraft.world.item; - import java.util.Arrays; - import java.util.Comparator; - import net.minecraft.core.Direction; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.InteractionHand; - import net.minecraft.world.InteractionResult; - import net.minecraft.world.InteractionResultHolder; -@@ -29,8 +30,12 @@ public class FireworkRocketItem extends Item { - FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, context.getPlayer(), vec3d.x + (double) enumdirection.getStepX() * 0.15D, vec3d.y + (double) enumdirection.getStepY() * 0.15D, vec3d.z + (double) enumdirection.getStepZ() * 0.15D, itemstack); - entityfireworks.spawningEntity = context.getPlayer().getUUID(); // Paper - -- world.addFreshEntity(entityfireworks); -- itemstack.shrink(1); -+ // Paper start - PlayerLaunchProjectileEvent -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) context.getPlayer().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); -+ if (!event.callEvent() || !world.addFreshEntity(entityfireworks)) return InteractionResult.PASS; -+ if (event.shouldConsume() && !context.getPlayer().abilities.instabuild) itemstack.shrink(1); -+ else if (context.getPlayer() instanceof ServerPlayer) ((ServerPlayer) context.getPlayer()).getBukkitEntity().updateInventory(); -+ // Paper end - } - - return InteractionResult.sidedSuccess(world.isClientSide); -@@ -50,9 +55,9 @@ public class FireworkRocketItem extends Item { - if (event.callEvent() && world.addFreshEntity(entityfireworks)) { - if (event.shouldConsume() && !user.abilities.instabuild) { - itemstack.shrink(1); -- } else ((EntityPlayer) user).getBukkitEntity().updateInventory(); -- } else if (user instanceof EntityPlayer) { -- ((EntityPlayer) user).getBukkitEntity().updateInventory(); -+ } else ((ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } else if (user instanceof ServerPlayer) { -+ ((ServerPlayer) user).getBukkitEntity().updateInventory(); - } - // Paper end - } -diff --git a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java -index 813a9c8464e253b9baa15af666111be104b4aa29..1957561f83645a57df5925b4b0b54153ebf4aeef 100644 ---- a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java -+++ b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java -@@ -3,6 +3,7 @@ package net.minecraft.world.item; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.world.InteractionHand; -+import net.minecraft.world.InteractionResult; - import net.minecraft.world.InteractionResultHolder; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.level.Level; -@@ -15,7 +16,12 @@ public class LingeringPotionItem extends ThrowablePotionItem { - - @Override - public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { -- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.LINGERING_POTION_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (LingeringPotionItem.random.nextFloat() * 0.4F + 0.8F)); -- return super.use(world, user, hand); -+ // Paper start -+ InteractionResultHolder wrapper = super.use(world, user, hand); -+ if (wrapper.getResult() != InteractionResult.FAIL) { -+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.LINGERING_POTION_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (LingeringPotionItem.random.nextFloat() * 0.4F + 0.8F)); -+ } -+ return wrapper; -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/item/SnowballItem.java b/src/main/java/net/minecraft/world/item/SnowballItem.java -index 50adbfc5d57b2b5f25c0efdc51da1701197c66e6..b053d105a1513a6b138972cdb9d28116fc6b8c81 100644 ---- a/src/main/java/net/minecraft/world/item/SnowballItem.java -+++ b/src/main/java/net/minecraft/world/item/SnowballItem.java -@@ -26,14 +26,20 @@ public class SnowballItem extends Item { - - entitysnowball.setItem(itemstack); - entitysnowball.shootFromRotation(user, user.xRot, user.yRot, 0.0F, 1.5F, 1.0F); -- if (world.addFreshEntity(entitysnowball)) { -- if (!user.abilities.instabuild) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity()); -+ if (event.callEvent() && world.addFreshEntity(entitysnowball)) { -+ if (event.shouldConsume() && !user.abilities.instabuild) { -+ // Paper end - itemstack.shrink(1); -+ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { // Paper -+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper - } - - world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (SnowballItem.random.nextFloat() * 0.4F + 0.8F)); -- } else if (user instanceof net.minecraft.server.level.ServerPlayer) { -- ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } else { // Paper -+ if (user instanceof net.minecraft.server.level.ServerPlayer) ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper -+ return new InteractionResultHolder(net.minecraft.world.InteractionResult.FAIL, itemstack); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/item/SplashPotionItem.java b/src/main/java/net/minecraft/world/item/SplashPotionItem.java -index 9c7547988fe90e9b87868636a1c1a7b4dff32622..6d3ab7fea3b5ebba4c304cdec5dd36dbea31f2c6 100644 ---- a/src/main/java/net/minecraft/world/item/SplashPotionItem.java -+++ b/src/main/java/net/minecraft/world/item/SplashPotionItem.java -@@ -3,6 +3,7 @@ package net.minecraft.world.item; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.world.InteractionHand; -+import net.minecraft.world.InteractionResult; - import net.minecraft.world.InteractionResultHolder; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.level.Level; -@@ -15,7 +16,12 @@ public class SplashPotionItem extends ThrowablePotionItem { - - @Override - public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { -+ // Paper start -+ InteractionResultHolder wrapper = super.use(world, user, hand); -+ if (wrapper.getResult() != InteractionResult.FAIL) { - world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SPLASH_POTION_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (SplashPotionItem.random.nextFloat() * 0.4F + 0.8F)); -- return super.use(world, user, hand); -+ } -+ return wrapper; -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java -index 3615bc9222db4489189537f7f5d7a7d338053d6d..e12c7ebc0a4ff4f132512dc1677db7f79db41b03 100644 ---- a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java -+++ b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java -@@ -1,7 +1,9 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.stats.Stats; - import net.minecraft.world.InteractionHand; -+import net.minecraft.world.InteractionResult; - import net.minecraft.world.InteractionResultHolder; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.projectile.ThrownPotion; -@@ -22,13 +24,31 @@ public class ThrowablePotionItem extends PotionItem { - - entitypotion.setItem(itemstack); - entitypotion.shootFromRotation(user, user.xRot, user.yRot, -20.0F, 0.5F, 1.0F); -- world.addFreshEntity(entitypotion); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitypotion.getBukkitEntity()); -+ if (event.callEvent() && world.addFreshEntity(entitypotion)) { -+ if (event.shouldConsume() && !user.abilities.instabuild) { -+ itemstack.shrink(1); -+ } else if (user instanceof ServerPlayer) { -+ ((ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } -+ -+ user.awardStat(Stats.ITEM_USED.get(this)); -+ } else { -+ if (user instanceof ServerPlayer) { -+ ((ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } -+ return new InteractionResultHolder(InteractionResult.FAIL, itemstack); -+ } -+ // Paper end - } - -- user.awardStat(Stats.ITEM_USED.get(this)); -- if (!user.abilities.instabuild) { -- itemstack.shrink(1); -+ /* // Paper start - moved up -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ if (!entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); - } diff --git a/Remapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch b/Remapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch deleted file mode 100644 index 509fc426f4..0000000000 --- a/Remapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BlackHole -Date: Sun, 15 Dec 2019 19:12:39 +0100 -Subject: [PATCH] Add CraftMagicNumbers.isSupportedApiVersion() - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 21052d0e88351b075733331d71e07b086354b820..86b319337fc41a09dd45df466df60cadaed1343f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -373,6 +373,11 @@ public final class CraftMagicNumbers implements UnsafeValues { - public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { - return new com.destroystokyo.paper.PaperVersionFetcher(); - } -+ -+ @Override -+ public boolean isSupportedApiVersion(String apiVersion) { -+ return apiVersion != null && SUPPORTED_API.contains(apiVersion); -+ } - // Paper end - - /** diff --git a/Remapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/Remapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch deleted file mode 100644 index 32b045db49..0000000000 --- a/Remapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Callahan -Date: Mon, 13 Jan 2020 23:47:28 -0600 -Subject: [PATCH] Prevent sync chunk loads when villagers try to find beds - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java -index 5151c794985a135d3bd794bbafdf524ab9f670de..9a582fb4b96b2d0406cc86e473e8bf8c4e488e37 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java -@@ -46,7 +46,8 @@ public class SleepInBed extends Behavior { - } - } - -- BlockState iblockdata = world.getBlockState(globalpos.getBlockPosition()); -+ BlockState iblockdata = world.getTypeIfLoaded(globalpos.getBlockPosition()); // Paper -+ if (iblockdata == null) { return false; } // Paper - - return globalpos.getBlockPosition().a((Position) entity.position(), 2.0D) && iblockdata.getBlock().is((Tag) BlockTags.BEDS) && !(Boolean) iblockdata.getValue(BedBlock.OCCUPIED); - } diff --git a/Remapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch b/Remapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch deleted file mode 100644 index 27d343fa11..0000000000 --- a/Remapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 18 Dec 2019 22:21:35 -0600 -Subject: [PATCH] MC-145656 Fix Follow Range Initial Target - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5..edda2121f8c1046478beaa77030ebb36d403b334 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -580,4 +580,9 @@ public class PaperWorldConfig { - private void pillagerSettings() { - disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); - } -+ -+ public boolean entitiesTargetWithFollowRange = false; -+ private void entitiesTargetWithFollowRange() { -+ entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java -index 7bba2ac71a3cd34a06ec865a3c1828b10decd644..93845edab0e1b0e2ad300cad051b0182cadd46e5 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java -@@ -32,6 +32,7 @@ public class NearestAttackableTargetGoal extends TargetG - this.randomInterval = reciprocalChance; - this.setFlags(EnumSet.of(Goal.Flag.TARGET)); - this.targetConditions = (new TargetingConditions()).range(this.getFollowDistance()).selector(targetPredicate); -+ if (mob.level.paperConfig.entitiesTargetWithFollowRange) this.targetConditions.useFollowRange(); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -index 1714507fa744b2767e8a66cdb5db7f43c21f5c56..e1a0104a3b52990a83e7732491029d8a20976dc3 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -@@ -4,6 +4,8 @@ import java.util.function.Predicate; - import javax.annotation.Nullable; - import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.Mob; -+import net.minecraft.world.entity.ai.attributes.AttributeInstance; -+import net.minecraft.world.entity.ai.attributes.Attributes; - - public class TargetingConditions { - -@@ -82,7 +84,7 @@ public class TargetingConditions { - - if (this.range > 0.0D) { - double d0 = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D; -- double d1 = Math.max(this.range * d0, 2.0D); -+ double d1 = Math.max((useFollowRange ? getFollowRange(baseEntity) : this.range) * d0, 2.0D); // Paper - double d2 = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); - - if (d2 > d1 * d1) { -@@ -98,4 +100,18 @@ public class TargetingConditions { - return true; - } - } -+ -+ // Paper start -+ private boolean useFollowRange = false; -+ -+ public TargetingConditions useFollowRange() { -+ this.useFollowRange = true; -+ return this; -+ } -+ -+ private double getFollowRange(LivingEntity entityliving) { -+ AttributeInstance attributeinstance = entityliving.getAttribute(Attributes.FOLLOW_RANGE); -+ return attributeinstance == null ? 16.0D : attributeinstance.getValue(); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch b/Remapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch deleted file mode 100644 index 5d342ad554..0000000000 --- a/Remapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch +++ /dev/null @@ -1,605 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Apr 2016 22:09:52 -0400 -Subject: [PATCH] Optimize Hoppers - -* Removes unnecessary extra calls to .update() that are very expensive -* Lots of itemstack cloning removed. Only clone if the item is actually moved -* Return true when a plugin cancels inventory move item event instead of false, as false causes pulls to cycle through all items. - However, pushes do not exhibit the same behavior, so this is not something plugins could of been relying on. -* Add option (Default on) to cooldown hoppers when they fail to move an item due to full inventory -* Skip subsequent InventoryMoveItemEvents if a plugin does not use the item after first event fire for an iteration -* Don't check for Entities with Inventories if the block above us is also occluding (not just Inventoried) -* Remove Streams from Item Suck In and restore restore 1.12 AABB checks which is simpler and no voxel allocations (was doing TWO Item Suck ins) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index edda2121f8c1046478beaa77030ebb36d403b334..7fbd501d70dccf869a4454e2789a5d68f2e15754 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -585,4 +585,13 @@ public class PaperWorldConfig { - private void entitiesTargetWithFollowRange() { - entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); - } -+ -+ public boolean cooldownHopperWhenFull = true; -+ public boolean disableHopperMoveEvents = false; -+ private void hopperOptimizations() { -+ cooldownHopperWhenFull = getBoolean("hopper.cooldown-when-full", cooldownHopperWhenFull); -+ log("Cooldown Hoppers when Full: " + (cooldownHopperWhenFull ? "enabled" : "disabled")); -+ disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); -+ log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 753e6f609189c589514739bea80007bace3c89d2..7038897b8fb4c18ca97b95a3b24c30b40b62b005 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -131,6 +131,7 @@ import net.minecraft.world.level.LevelSettings; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.biome.BiomeSource; - import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.HopperBlockEntity; - import net.minecraft.world.level.border.WorldBorder; - import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.dimension.DimensionType; -@@ -1360,6 +1361,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper -+ HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - - this.profiler.push(() -> { - return worldserver + " " + worldserver.dimension().location(); -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 02bfa4fb8055e60a84e878ffbf18303c0ee25b1d..ac996d581925c8f92832009945c766962e5b51c5 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -538,11 +538,12 @@ public final class ItemStack { - return this.getItem().interactLivingEntity(this, user, entity, hand); - } - -- public ItemStack copy() { -- if (this.isEmpty()) { -+ public ItemStack copy() { return cloneItemStack(false); } // Paper -+ public ItemStack cloneItemStack(boolean origItem) { // Paper -+ if (!origItem && this.isEmpty()) { // Paper - return ItemStack.EMPTY; - } else { -- ItemStack itemstack = new ItemStack(this.getItem(), this.count); -+ ItemStack itemstack = new ItemStack(origItem ? this.item : this.getItem(), this.count); // Paper - - itemstack.setPopTime(this.getPopTime()); - if (this.tag != null) { -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 3e2cd6c7a34c1a792d7346019a8b039d1f4a7c04..6b79f8cd9258af47afa6efa7b1f97c3780be58b0 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1162,8 +1162,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return list; - } - -- @Override -- public List getEntitiesOfClass(Class entityClass, AABB box, @Nullable Predicate predicate) { -+ public List getEntities(Class oclass, AABB axisalignedbb, @Nullable Predicate predicate) { return getEntitiesOfClass(oclass, axisalignedbb, predicate); } // Paper - OBFHELPER -+ @Override public List getEntitiesOfClass(Class entityClass, AABB box, @Nullable Predicate predicate) { - this.getProfiler().incrementCounter("getEntities"); - int i = Mth.floor((box.minX - 2.0D) / 16.0D); - int j = Mth.ceil((box.maxX + 2.0D) / 16.0D); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 84012c2d12817e657b046bc168cc8eddebcd3831..05fa76c02ce61e26891ad995fe89e925ea086557 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -77,6 +77,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - public void setCurrentChunk(LevelChunk chunk) { - this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; - } -+ static boolean IGNORE_TILE_UPDATES = false; - // Paper end - - @Nullable -@@ -155,6 +156,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - - public void setChanged() { - if (this.level != null) { -+ if (IGNORE_TILE_UPDATES) return; // Paper - this.blockState = this.level.getBlockState(this.worldPosition); - this.level.blockEntityChanged(this.worldPosition, this); - if (!this.blockState.isAir()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java -index f8e4a42bed265822666141683e36e6696694925b..fc8bb72f7d677f65db505016ad6a4cd6146de29f 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java -@@ -1,6 +1,7 @@ - package net.minecraft.world.level.block.entity; - - import javax.annotation.Nullable; -+import net.minecraft.core.BlockPos; - import net.minecraft.world.Container; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.block.Block; -@@ -17,12 +18,13 @@ public interface Hopper extends Container { - return Hopper.SUCK; - } - -- @Nullable -+ //@Nullable // Paper - it's annoying - Level getLevel(); -+ default BlockPos getBlockPosition() { return new BlockPos(getX(), getY(), getZ()); } // Paper - -- double getLevelX(); -+ double getLevelX(); default double getX() { return this.getLevelX(); } // Paper - OBFHELPER - -- double getLevelY(); -+ double getLevelY(); default double getY() { return this.getLevelY(); } // Paper - OBFHELPER - -- double getLevelZ(); -+ double getLevelZ(); default double getZ() { return this.getLevelZ(); } // Paper - OBFHELPER - } -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 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f7639dab54b 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 -@@ -193,6 +193,160 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - return false; - } - -+ // Paper start - Optimize Hoppers -+ private static boolean skipPullModeEventFire = false; -+ private static boolean skipPushModeEventFire = false; -+ public static boolean skipHopperEvents = false; -+ -+ private boolean hopperPush(Container iinventory, Direction enumdirection) { -+ skipPushModeEventFire = skipHopperEvents; -+ boolean foundItem = false; -+ for (int i = 0; i < this.getContainerSize(); ++i) { -+ ItemStack item = this.getItem(i); -+ if (!item.isEmpty()) { -+ foundItem = true; -+ ItemStack origItemStack = item; -+ ItemStack itemstack = origItemStack; -+ -+ final int origCount = origItemStack.getCount(); -+ final int moved = Math.min(level.spigotConfig.hopperAmount, origCount); -+ origItemStack.setCount(moved); -+ -+ // We only need to fire the event once to give protection plugins a chance to cancel this event -+ // Because nothing uses getItem, every event call should end up the same result. -+ if (!skipPushModeEventFire) { -+ itemstack = callPushMoveEvent(iinventory, itemstack); -+ if (itemstack == null) { // cancelled -+ origItemStack.setCount(origCount); -+ return false; -+ } -+ } -+ final ItemStack itemstack2 = addItem(this, iinventory, itemstack, enumdirection); -+ final int remaining = itemstack2.getCount(); -+ if (remaining != moved) { -+ origItemStack = origItemStack.cloneItemStack(true); -+ origItemStack.setCount(origCount); -+ if (!origItemStack.isEmpty()) { -+ origItemStack.setCount(origCount - moved + remaining); -+ } -+ this.setItem(i, origItemStack); -+ iinventory.setChanged(); -+ return true; -+ } -+ origItemStack.setCount(origCount); -+ } -+ } -+ if (foundItem && level.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown -+ this.setCooldown(level.spigotConfig.hopperTransfer); -+ } -+ return false; -+ } -+ -+ private static boolean hopperPull(Hopper ihopper, Container iinventory, ItemStack origItemStack, int i) { -+ ItemStack itemstack = origItemStack; -+ final int origCount = origItemStack.getCount(); -+ final Level world = ihopper.getLevel(); -+ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); -+ itemstack.setCount(moved); -+ -+ if (!skipPullModeEventFire) { -+ itemstack = callPullMoveEvent(ihopper, iinventory, itemstack); -+ if (itemstack == null) { // cancelled -+ origItemStack.setCount(origCount); -+ // Drastically improve performance by returning true. -+ // No plugin could of relied on the behavior of false as the other call -+ // site for IMIE did not exhibit the same behavior -+ return true; -+ } -+ } -+ -+ final ItemStack itemstack2 = addItem(iinventory, ihopper, itemstack, null); -+ final int remaining = itemstack2.getCount(); -+ if (remaining != moved) { -+ origItemStack = origItemStack.cloneItemStack(true); -+ origItemStack.setCount(origCount); -+ if (!origItemStack.isEmpty()) { -+ origItemStack.setCount(origCount - moved + remaining); -+ } -+ IGNORE_TILE_UPDATES = true; -+ iinventory.setItem(i, origItemStack); -+ IGNORE_TILE_UPDATES = false; -+ iinventory.setChanged(); -+ return true; -+ } -+ origItemStack.setCount(origCount); -+ -+ if (world.paperConfig.cooldownHopperWhenFull) { -+ cooldownHopper(ihopper); -+ } -+ -+ return false; -+ } -+ -+ private ItemStack callPushMoveEvent(Container iinventory, ItemStack itemstack) { -+ Inventory destinationInventory = getInventory(iinventory); -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner(false).getInventory(), -+ CraftItemStack.asCraftMirror(itemstack), destinationInventory, true); -+ boolean result = event.callEvent(); -+ if (!event.calledGetItem && !event.calledSetItem) { -+ skipPushModeEventFire = true; -+ } -+ if (!result) { -+ cooldownHopper(this); -+ return null; -+ } -+ -+ if (event.calledSetItem) { -+ return CraftItemStack.asNMSCopy(event.getItem()); -+ } else { -+ return itemstack; -+ } -+ } -+ -+ private static ItemStack callPullMoveEvent(Hopper hopper, Container iinventory, ItemStack itemstack) { -+ Inventory sourceInventory = getInventory(iinventory); -+ Inventory destination = getInventory(hopper); -+ -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, -+ // Mirror is safe as we no plugins ever use this item -+ CraftItemStack.asCraftMirror(itemstack), destination, false); -+ boolean result = event.callEvent(); -+ if (!event.calledGetItem && !event.calledSetItem) { -+ skipPullModeEventFire = true; -+ } -+ if (!result) { -+ cooldownHopper(hopper); -+ return null; -+ } -+ -+ if (event.calledSetItem) { -+ return CraftItemStack.asNMSCopy(event.getItem()); -+ } else { -+ return itemstack; -+ } -+ } -+ -+ private static Inventory getInventory(Container iinventory) { -+ Inventory sourceInventory;// Have to special case large chests as they work oddly -+ if (iinventory instanceof CompoundContainer) { -+ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); -+ } else if (iinventory instanceof BlockEntity) { -+ sourceInventory = ((BlockEntity) iinventory).getOwner(false).getInventory(); -+ } else { -+ sourceInventory = iinventory.getOwner().getInventory(); -+ } -+ return sourceInventory; -+ } -+ -+ private static void cooldownHopper(Hopper hopper) { -+ if (hopper instanceof HopperBlockEntity) { -+ ((HopperBlockEntity) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer); -+ } else if (hopper instanceof MinecartHopper) { -+ ((MinecartHopper) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer / 2); -+ } -+ } -+ // Paper end -+ - private boolean ejectItems() { - Container iinventory = this.getAttachedContainer(); - -@@ -204,27 +358,28 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - if (this.isFullContainer(iinventory, enumdirection)) { - return false; - } else { -- for (int i = 0; i < this.getContainerSize(); ++i) { -+ return hopperPush(iinventory, enumdirection); /* // Paper - disable rest -+ for (int i = 0; i < this.getSize(); ++i) { - if (!this.getItem(i).isEmpty()) { -- ItemStack itemstack = this.getItem(i).copy(); -+ ItemStack itemstack = this.getItem(i).cloneItemStack(); - // ItemStack itemstack1 = addItem(this, iinventory, this.splitStack(i, 1), enumdirection); - - // CraftBukkit start - Call event when pushing items into other inventories -- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.removeItem(i, level.spigotConfig.hopperAmount)); // Spigot -+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.splitStack(i, world.spigotConfig.hopperAmount)); // Spigot - - Inventory destinationInventory; - // Have to special case large chests as they work oddly -- if (iinventory instanceof CompoundContainer) { -- destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); -+ if (iinventory instanceof InventoryLargeChest) { -+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); - } else { - destinationInventory = iinventory.getOwner().getInventory(); - } - - InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); -- this.getLevel().getCraftServer().getPluginManager().callEvent(event); -+ this.getWorld().getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - this.setItem(i, itemstack); -- this.setCooldown(level.spigotConfig.hopperTransfer); // Spigot -+ this.setCooldown(world.spigotConfig.hopperTransfer); // Spigot - return false; - } - int origCount = event.getItem().getAmount(); // Spigot -@@ -232,16 +387,16 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - // CraftBukkit end - - if (itemstack1.isEmpty()) { -- iinventory.setChanged(); -+ iinventory.update(); - return true; - } - -- itemstack.shrink(origCount - itemstack1.getCount()); // Spigot -+ itemstack.subtract(origCount - itemstack1.getCount()); // Spigot - this.setItem(i, itemstack); - } - } - -- return false; -+ return false;*/ // Paper - end commenting out replaced block for Hopper Optimizations - } - } - } -@@ -250,18 +405,54 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - return inventory instanceof WorldlyContainer ? IntStream.of(((WorldlyContainer) inventory).getSlotsForFace(side)) : IntStream.range(0, inventory.getContainerSize()); - } - -- private boolean isFullContainer(Container inv, Direction enumdirection) { -- return getSlots(inv, enumdirection).allMatch((i) -> { -- ItemStack itemstack = inv.getItem(i); -+ private static boolean allMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate test) { -+ if (iinventory instanceof WorldlyContainer) { -+ for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) { -+ if (!test.test(iinventory.getItem(i), i)) { -+ return false; -+ } -+ } -+ } else { -+ int size = iinventory.getContainerSize(); -+ for (int i = 0; i < size; i++) { -+ if (!test.test(iinventory.getItem(i), i)) { -+ return false; -+ } -+ } -+ } -+ return true; -+ } - -- return itemstack.getCount() >= itemstack.getMaxStackSize(); -- }); -+ private static boolean anyMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate test) { -+ if (iinventory instanceof WorldlyContainer) { -+ for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) { -+ if (test.test(iinventory.getItem(i), i)) { -+ return true; -+ } -+ } -+ } else { -+ int size = iinventory.getContainerSize(); -+ for (int i = 0; i < size; i++) { -+ if (test.test(iinventory.getItem(i), i)) { -+ return true; -+ } -+ } -+ } -+ return true; -+ } -+ private static final java.util.function.BiPredicate STACK_SIZE_TEST = (itemstack, i) -> itemstack.getCount() >= itemstack.getMaxStackSize(); -+ private static final java.util.function.BiPredicate IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty(); -+ -+ // Paper end -+ -+ private boolean isFullContainer(Container inv, Direction enumdirection) { -+ // Paper start - no streams -+ return allMatch(inv, enumdirection, STACK_SIZE_TEST); -+ // Paper end - } - - private static boolean isEmptyContainer(Container inv, Direction facing) { -- return getSlots(inv, facing).allMatch((i) -> { -- return inv.getItem(i).isEmpty(); -- }); -+ return allMatch(inv, facing, IS_EMPTY_TEST); - } - - public static boolean suckInItems(Hopper hopper) { -@@ -270,9 +461,17 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - if (iinventory != null) { - Direction enumdirection = Direction.DOWN; - -- return isEmptyContainer(iinventory, enumdirection) ? false : getSlots(iinventory, enumdirection).anyMatch((i) -> { -- return tryTakeInItemFromSlot(hopper, iinventory, i, enumdirection); -+ // Paper start - optimize hoppers and remove streams -+ skipPullModeEventFire = skipHopperEvents; -+ return !isEmptyContainer(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { -+ // Logic copied from below to avoid extra getItem calls -+ if (!item.isEmpty() && canTakeItem(iinventory, item, i, enumdirection)) { -+ return hopperPull(hopper, iinventory, item, i); -+ } else { -+ return false; -+ } - }); -+ // Paper end - } else { - Iterator iterator = getItemsAtAndAbove(hopper).iterator(); - -@@ -290,47 +489,48 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - } - } - -- private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) { -+ private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) {// Paper - method unused as logic is inlined above - ItemStack itemstack = inventory.getItem(slot); - -- if (!itemstack.isEmpty() && canTakeItemFromContainer(inventory, itemstack, slot, side)) { -- ItemStack itemstack1 = itemstack.copy(); -+ if (!itemstack.isEmpty() && canTakeItemFromContainer(inventory, itemstack, slot, side)) { // If this logic changes, update above. this is left inused incase reflective plugins -+ return hopperPull(hopper, inventory, itemstack, slot); /* // Paper - disable rest -+ ItemStack itemstack1 = itemstack.cloneItemStack(); - // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null); - // CraftBukkit start - Call event on collection of items from inventories into the hopper -- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(inventory.removeItem(slot, hopper.getLevel().spigotConfig.hopperAmount)); // Spigot -+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.splitStack(i, ihopper.getWorld().spigotConfig.hopperAmount)); // Spigot - - Inventory sourceInventory; - // Have to special case large chests as they work oddly -- if (inventory instanceof CompoundContainer) { -- sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) inventory); -+ if (iinventory instanceof InventoryLargeChest) { -+ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); - } else { -- sourceInventory = inventory.getOwner().getInventory(); -+ sourceInventory = iinventory.getOwner().getInventory(); - } - -- InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), hopper.getOwner().getInventory(), false); -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), ihopper.getOwner().getInventory(), false); - -- hopper.getLevel().getCraftServer().getPluginManager().callEvent(event); -+ ihopper.getWorld().getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { -- inventory.setItem(slot, itemstack1); -+ iinventory.setItem(i, itemstack1); - -- if (hopper instanceof HopperBlockEntity) { -- ((HopperBlockEntity) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer); // Spigot -- } else if (hopper instanceof MinecartHopper) { -- ((MinecartHopper) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer / 2); // Spigot -+ if (ihopper instanceof TileEntityHopper) { -+ ((TileEntityHopper) ihopper).setCooldown(ihopper.getWorld().spigotConfig.hopperTransfer); // Spigot -+ } else if (ihopper instanceof EntityMinecartHopper) { -+ ((EntityMinecartHopper) ihopper).setCooldown(ihopper.getWorld().spigotConfig.hopperTransfer / 2); // Spigot - } - return false; - } - int origCount = event.getItem().getAmount(); // Spigot -- ItemStack itemstack2 = addItem(inventory, hopper, CraftItemStack.asNMSCopy(event.getItem()), null); -+ ItemStack itemstack2 = addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null); - // CraftBukkit end - - if (itemstack2.isEmpty()) { -- inventory.setChanged(); -+ iinventory.update(); - return true; - } - -- itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot -- inventory.setItem(slot, itemstack1); -+ itemstack1.subtract(origCount - itemstack2.getCount()); // Spigot -+ iinventory.setItem(i, itemstack1);*/ // Paper - end commenting out replaced block for Hopper Optimizations - } - - return false; -@@ -339,7 +539,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - public static boolean addItem(Container inventory, ItemEntity itemEntity) { - boolean flag = false; - // CraftBukkit start -- InventoryPickupItemEvent event = new InventoryPickupItemEvent(inventory.getOwner().getInventory(), (org.bukkit.entity.Item) itemEntity.getBukkitEntity()); -+ InventoryPickupItemEvent event = new InventoryPickupItemEvent(getInventory(inventory), (org.bukkit.entity.Item) itemEntity.getBukkitEntity()); // Paper - use getInventory() to avoid snapshot creation - itemEntity.level.getCraftServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return false; -@@ -381,6 +581,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - return !inventory.canPlaceItem(slot, stack) ? false : !(inventory instanceof WorldlyContainer) || ((WorldlyContainer) inventory).canPlaceItemThroughFace(slot, stack, side); - } - -+ private static boolean canTakeItem(Container iinventory, ItemStack itemstack, int i, Direction enumdirection) { return canTakeItemFromContainer(iinventory, itemstack, i, enumdirection); } // Paper - OBFHELPER - private static boolean canTakeItemFromContainer(Container inv, ItemStack stack, int slot, Direction facing) { - return !(inv instanceof WorldlyContainer) || ((WorldlyContainer) inv).canTakeItemThroughFace(slot, stack, facing); - } -@@ -393,7 +594,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - boolean flag1 = to.isEmpty(); - - if (itemstack1.isEmpty()) { -+ IGNORE_TILE_UPDATES = true; // Paper - to.setItem(slot, stack); -+ IGNORE_TILE_UPDATES = false; // Paper - stack = ItemStack.EMPTY; - flag = true; - } else if (canMergeItems(itemstack1, stack)) { -@@ -444,20 +647,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - } - - public static List getItemsAtAndAbove(Hopper ihopper) { -- return (List) ihopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> { -- return ihopper.getLevel().getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(ihopper.getLevelX() - 0.5D, ihopper.getLevelY() - 0.5D, ihopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream(); -- }).collect(Collectors.toList()); -+ // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?! -+ Level world = ihopper.getLevel(); -+ double d0 = ihopper.getX(); -+ double d1 = ihopper.getY(); -+ double d2 = ihopper.getZ(); -+ AABB bb = new AABB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); -+ return world.getEntities(ItemEntity.class, bb, Entity::isAlive); -+ // Paper end - } - - @Nullable - public static Container getContainerAt(Level world, BlockPos blockposition) { -- return getContainerAt(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); -+ return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, true); // Paper - } - - @Nullable -- public static Container getContainerAt(Level world, double x, double y, double z) { -+ public static Container getContainerAt(Level world, double x, double y, double z) { return a(world, x, y, z, false); } // Paper - overload to default false -+ public static Container a(Level world, double d0, double d1, double d2, boolean optimizeEntities) { // Paper - Object object = null; -- BlockPos blockposition = new BlockPos(x, y, z); -+ BlockPos blockposition = new BlockPos(d0, d1, d2); - if ( !world.hasChunkAt( blockposition ) ) return null; // Spigot - BlockState iblockdata = world.getBlockState(blockposition); - Block block = iblockdata.getBlock(); -@@ -475,8 +684,8 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - } - } - -- if (object == null) { -- List list = world.getEntities((Entity) null, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); -+ if (object == null && (!optimizeEntities || !org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(block).isOccluding())) { // Paper -+ List list = world.getEntities((Entity) null, new AABB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); - - if (!list.isEmpty()) { - object = (Container) list.get(world.random.nextInt(list.size())); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java -index 5ad419941ff1113ef29b9a4593f44d8f35ba8424..4525032232b5a89de13c6a46dc489a07428e3f21 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java -@@ -97,12 +97,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc - @Override - public boolean isEmpty() { - this.unpackLootTable((Player) null); -- return this.getItems().stream().allMatch(ItemStack::isEmpty); -+ // Paper start -+ for (ItemStack itemStack : this.getItems()) { -+ if (!itemStack.isEmpty()) { -+ return false; -+ } -+ } -+ // Paper end -+ return true; - } - - @Override - public ItemStack getItem(int slot) { -- this.unpackLootTable((Player) null); -+ if (slot == 0) this.unpackLootTable((Player) null); // Paper - return (ItemStack) this.getItems().get(slot); - } - diff --git a/Remapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch b/Remapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch deleted file mode 100644 index 4f453dc689..0000000000 --- a/Remapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 24 Dec 2019 00:35:42 +0000 -Subject: [PATCH] PlayerDeathEvent#shouldDropExperience - - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 2ef273e3b917803f3e2ac3c6a22d92a15b9eb71a..7f4e81ee3339e90b8525541dccf6dea187853cf7 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -819,7 +819,7 @@ public class ServerPlayer extends Player implements ContainerListener { - this.tellNeutralMobsThatIDied(); - } - // SPIGOT-5478 must be called manually now -- this.dropExperience(); -+ if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event - // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. - if (!event.getKeepInventory()) { - // Paper start - replace logic diff --git a/Remapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch b/Remapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch deleted file mode 100644 index 9a427d5aa2..0000000000 --- a/Remapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 5 Jan 2020 17:24:34 -0600 -Subject: [PATCH] Prevent bees loading chunks checking hive position - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index 32ee38142a3053091ab7b3fb3d608d268b07d4e3..edd6d63f715acef1a77eba0cf46ff8267228f4c6 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Bee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -442,6 +442,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - if (!this.hasHive()) { - return false; - } else { -+ if (level.getChunkIfLoadedImmediately(hivePos.getX() >> 4, hivePos.getZ() >> 4) == null) return true; // Paper - just assume the hive is still there, no need to load the chunk(s) - BlockEntity tileentity = this.level.getBlockEntity(this.hivePos); - - return tileentity != null && tileentity.getType() == BlockEntityType.BEEHIVE; diff --git a/Remapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/Remapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch deleted file mode 100644 index f6952f6250..0000000000 --- a/Remapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Nov 2016 20:28:12 -0400 -Subject: [PATCH] Don't load Chunks from Hoppers and other things - -Hoppers call this to I guess "get the primary side" of a double sided chest. - -If the double sided chest crosses chunk lines, it causes the chunk to load. -This will end up causing sync chunk loads, which will unload with Chunk GC, -only to be reloaded again the next tick. - -This of course is undesirable, so just return the loaded side as "primary" -and treat it as a single chest if the other sides are unloaded - -diff --git a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java -index a4f16b2093c867e9fd1c2e07b67c49c3c5ec7506..df20b3616929657d2e8061159ed97f500b33d192 100644 ---- a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java -+++ b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java -@@ -29,7 +29,12 @@ public class DoubleBlockCombiner { - return new DoubleBlockCombiner.NeighborCombineResult.Single<>(s0); - } else { - BlockPos blockposition1 = pos.relative((Direction) function1.apply(state)); -- BlockState iblockdata1 = world.getBlockState(blockposition1); -+ // Paper start -+ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); -+ if (iblockdata1 == null) { -+ return new DoubleBlockCombiner.NeighborCombineResult.Single<>(s0); -+ } -+ // Paper end - - if (iblockdata1.is(state.getBlock())) { - DoubleBlockCombiner.BlockType doubleblockfinder_blocktype1 = (DoubleBlockCombiner.BlockType) typeMapper.apply(iblockdata1); diff --git a/Remapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch b/Remapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch deleted file mode 100644 index 37dc33fc4a..0000000000 --- a/Remapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 27 Dec 2019 09:42:26 -0800 -Subject: [PATCH] Guard against serializing mismatching chunk coordinate - -Should help if something dumb happens - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index be67dc16bf70e4517efd213ca9002f116f60b57c..6c28a611b9b79c3322ab07883972c07b3bfc3073 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -67,6 +67,13 @@ public class ChunkSerializer { - - private static final Logger LOGGER = LogManager.getLogger(); - -+ // Paper start - guard against serializing mismatching coordinates -+ // TODO Note: This needs to be re-checked each update -+ public static ChunkPos getChunkCoordinate(CompoundTag chunkData) { -+ CompoundTag levelData = chunkData.getCompound("Level"); -+ return new ChunkPos(levelData.getInt("xPos"), levelData.getInt("zPos")); -+ } -+ // Paper end - // Paper start - public static final class InProgressChunkHolder { - -@@ -92,8 +99,8 @@ public class ChunkSerializer { - // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); - BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); -- CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); -- ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); -+ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate -+ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate - - if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { - ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -index 684442b7175e30b6d4cafb2f7d2d4c10517cc33d..1af804c5c6fb2b20ea3f020610763c1d7dcee110 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -@@ -13,6 +13,7 @@ import net.minecraft.SharedConstants; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.NbtUtils; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.datafix.DataFixTypes; -@@ -119,6 +120,13 @@ public class ChunkStorage implements AutoCloseable { - - public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER - public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) -+ // Paper start -+ if (!chunkcoordintpair.equals(ChunkSerializer.getChunkCoordinate(nbttagcompound))) { -+ String world = (this instanceof ChunkMap) ? ((ChunkMap)this).level.getWorld().getName() : null; -+ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkcoordintpair.toString() -+ + " but compound says coordinate is " + ChunkSerializer.getChunkCoordinate(nbttagcompound).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); -+ } -+ // Paper end - this.regionFileCache.write(chunkcoordintpair, nbttagcompound); - if (this.legacyStructureHandler != null) { - synchronized (this.persistentDataLock) { // Paper - Async chunk loading diff --git a/Remapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch b/Remapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch deleted file mode 100644 index e478c7d039..0000000000 --- a/Remapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 11 Jan 2020 21:50:56 -0800 -Subject: [PATCH] Optimise IEntityAccess#getPlayerByUUID - -Use the world entity map instead of iterating over all players - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 01f879a8dd0e1ffec380e02072567330152eaceb..40d7dbc4f1deda88d4a539b89d84b595217051b6 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -283,6 +283,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - // Paper end - -+ // Paper start - optimise getPlayerByUUID -+ @Nullable -+ @Override -+ public Player getPlayerByUUID(UUID uuid) { -+ Entity player = this.entitiesByUuid.get(uuid); -+ return (player instanceof Player) ? (Player)player : null; -+ } -+ // Paper end -+ - // Add env and gen to constructor, WorldData -> WorldDataServer - public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor -diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index 6a5430fe54a5c8ad119a0f3842961825a54d8d7a..b9606465ace8b320eafbbad3d60c01b87a859c44 100644 ---- a/src/main/java/net/minecraft/world/level/EntityGetter.java -+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -277,6 +277,12 @@ public interface EntityGetter { - - @Nullable - default Player getPlayerByUUID(UUID uuid) { -+ // Paper start - allow WorldServer to override -+ return this.getPlayerByUUID(uuid); -+ } -+ @Nullable -+ default Player getPlayerByUUID(UUID uuid) { -+ // Paper end - for (int i = 0; i < this.players().size(); ++i) { - Player entityhuman = (Player) this.players().get(i); - diff --git a/Remapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch b/Remapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch deleted file mode 100644 index f1ecdfe628..0000000000 --- a/Remapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AJMFactsheets -Date: Fri, 17 Jan 2020 17:17:54 -0600 -Subject: [PATCH] Fix items not falling correctly - -Since 1.14, Mojang has added an optimization which skips checking if -an item should fall every fourth tick. - -However, Spigot's entity activation range class also has an -optimization which skips ticking active entities every fourth tick. -This can result in a state where an item will never properly fall -due to its move method never being called. - -This patch resolves the conflict by offsetting checking an item's -move method from Spigot's entity activation range check. - -diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 96b8102773cbee2c3fe2711008ba1487084d67b0..9311f9f411d09d4460f0be8235957fab9e195b7a 100644 ---- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -115,7 +115,7 @@ public class ItemEntity extends Entity { - } - } - -- if (!this.onGround || getHorizontalDistanceSqr(this.getDeltaMovement()) > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) { -+ if (!this.onGround || getHorizontalDistanceSqr(this.getDeltaMovement()) > 9.999999747378752E-6D || this.tickCount % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check - this.move(MoverType.SELF, this.getDeltaMovement()); - float f1 = 0.98F; - diff --git a/Remapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch b/Remapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch deleted file mode 100644 index cc90ba9655..0000000000 --- a/Remapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 14 Jan 2020 15:28:28 -0800 -Subject: [PATCH] Lag compensate eating - -When the server is lagging, players will wait longer when eating. -Change to also use a time check instead if it passes. - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index b49d4772932a58852b3195f5f56ff93dbcabf766..016fcc4ae20e1e48728a848be28633e624ae49a7 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -211,7 +211,7 @@ public abstract class LivingEntity extends Entity { - private int noJumpDelay; - private float absorptionAmount; - public ItemStack useItem; // Paper - public -- protected int useItemRemaining; -+ protected int useItemRemaining; protected final int getEatTimeTicks() { return this.useItemRemaining; } protected final void setEatTimeTicks(int value) { this.useItemRemaining = value; } // Paper - OBFHELPER - protected int fallFlyTicks; - private BlockPos lastPos; - private Optional lastClimbablePos; -@@ -3148,6 +3148,11 @@ public abstract class LivingEntity extends Entity { - return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; - } - -+ // Paper start - lag compensate eating -+ protected long eatStartTime; -+ protected int totalEatTimeTicks; -+ // Paper end -+ - private void updatingUsingItem() { - if (this.isUsingItem()) { - if (ItemStack.isSameIgnoreDurability(this.getItemInHand(this.getUsedItemHand()), this.useItem)) { -@@ -3157,7 +3162,12 @@ public abstract class LivingEntity extends Entity { - this.triggerItemUseEffects(this.useItem, 5); - } - -- if (--this.useItemRemaining == 0 && !this.level.isClientSide && !this.useItem.useOnRelease()) { -+ // Paper start - lag compensate eating -+ // we add 1 to the expected time to avoid lag compensating when we should not -+ boolean shouldLagCompensate = this.useItem.getItem().isEdible() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); -+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level.isClientSide && !this.useItem.useOnRelease()) { -+ this.setEatTimeTicks(0); -+ // Paper end - this.completeUsingItem(); - } - } else { -@@ -3207,7 +3217,10 @@ public abstract class LivingEntity extends Entity { - - if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag - this.useItem = itemstack; -- this.useItemRemaining = itemstack.getUseDuration(); -+ // Paper start - lag compensate eating -+ this.useItemRemaining = this.totalEatTimeTicks = itemstack.getUseDuration(); -+ this.eatStartTime = System.nanoTime(); -+ // Paper end - if (!this.level.isClientSide) { - this.setLivingEntityFlag(1, true); - this.setLivingEntityFlag(2, enumhand == InteractionHand.OFF_HAND); -@@ -3231,7 +3244,10 @@ public abstract class LivingEntity extends Entity { - } - } else if (!this.isUsingItem() && !this.useItem.isEmpty()) { - this.useItem = ItemStack.EMPTY; -- this.useItemRemaining = 0; -+ // Paper start - lag compensate eating -+ this.useItemRemaining = this.totalEatTimeTicks = 0; -+ this.eatStartTime = -1L; -+ // Paper end - } - } - -@@ -3359,7 +3375,10 @@ public abstract class LivingEntity extends Entity { - } - - this.useItem = ItemStack.EMPTY; -- this.useItemRemaining = 0; -+ // Paper start - lag compensate eating -+ this.useItemRemaining = this.totalEatTimeTicks = 0; -+ this.eatStartTime = -1L; -+ // Paper end - } - - public boolean isBlocking() { diff --git a/Remapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch b/Remapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch deleted file mode 100644 index 9e3f2b3479..0000000000 --- a/Remapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BrodyBeckwith -Date: Tue, 14 Jan 2020 17:49:03 -0500 -Subject: [PATCH] Optimize call to getFluid for explosions - - -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 45a75f7be308678336e192828becf6cf5c9047bc..667a6d645034c67639c01b8221591877bcb87b35 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -151,7 +151,7 @@ public class Explosion { - for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { - BlockPos blockposition = new BlockPos(d4, d5, d6); - BlockState iblockdata = this.level.getBlockState(blockposition); -- FluidState fluid = this.level.getFluidState(blockposition); -+ FluidState fluid = iblockdata.getFluidState(); // Paper - Optional optional = this.damageCalculator.a(this, this.level, blockposition, iblockdata, fluid); - - if (optional.isPresent()) { diff --git a/Remapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch b/Remapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch deleted file mode 100644 index 63271d423f..0000000000 --- a/Remapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 17 Jan 2020 18:44:55 -0800 -Subject: [PATCH] Fix last firework in stack not having effects when dispensed - - #2871 - -CB used the resulting item in the dispenser rather than the item -dispensed. The resulting item would have size == 0 and therefore -be convertered to air, hence why the effects disappeared. - -diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -index 67a894a185a3d4a53b3c7f90174b2604dff18257..67d140dff483bfc654a0390e0cdcd13aa658a62d 100644 ---- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -@@ -425,7 +425,7 @@ public interface DispenseItemBehavior { - } - - itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); -- FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.getLevel(), stack, pointer.x(), pointer.y(), pointer.x(), true); -+ FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.getLevel(), itemstack1, pointer.x(), pointer.y(), pointer.x(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed - - DispenseItemBehavior.setEntityPokingOutOfBlock(pointer, entityfireworks, enumdirection); - entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F); diff --git a/Remapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch b/Remapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch deleted file mode 100644 index e51ec69f45..0000000000 --- a/Remapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jan 2020 12:25:07 -0600 -Subject: [PATCH] Add effect to block break naturally - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 5bff313dbbb3049105874846d995883e827fbc00..05f0833f762436bf8f5f5875c7e3cfed1da11e1c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -630,6 +630,13 @@ public class CraftBlock implements Block { - - @Override - public boolean breakNaturally(ItemStack item) { -+ // Paper start -+ return breakNaturally(item, false); -+ } -+ -+ @Override -+ public boolean breakNaturally(ItemStack item, boolean triggerEffect) { -+ // Paper end - // Order matters here, need to drop before setting to air so skulls can get their data - net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS(); - net.minecraft.world.level.block.Block block = iblockdata.getBlock(); -@@ -639,6 +646,7 @@ public class CraftBlock implements Block { - // Modelled off EntityHuman#hasBlock - if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) { - net.minecraft.world.level.block.Block.dropResources(iblockdata, world.getLevel(), position, world.getBlockEntity(position), null, nmsItem); -+ if (triggerEffect) world.levelEvent(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.world.level.block.Block.getId(block.defaultBlockState())); // Paper - result = true; - } - diff --git a/Remapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch b/Remapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch deleted file mode 100644 index ec1d0a178d..0000000000 --- a/Remapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Sat, 21 Dec 2019 15:22:09 -0500 -Subject: [PATCH] Tracking Range Improvements - -Sets tracking range of watermobs to animals instead of misc and simplifies code - -Also ignores Enderdragon, defaulting it to Mojang's setting - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 190ddd4d9ef3472c33d46c2ead72fa0dc918054a..6da406c8403797a1cd9276ac06577c3c080a8a22 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1795,6 +1795,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); - int j = entity.getType().clientTrackingRange() * 16; -+ j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper - - if (j > i) { - i = j; -diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java -index 8e3e36a8739a7dea1feb3785e96b7b9f19720446..b03fa9024c7f0238e1379f6ae4486db5300a70e9 100644 ---- a/src/main/java/org/spigotmc/TrackingRange.java -+++ b/src/main/java/org/spigotmc/TrackingRange.java -@@ -6,7 +6,6 @@ import net.minecraft.world.entity.ExperienceOrb; - import net.minecraft.world.entity.decoration.ItemFrame; - import net.minecraft.world.entity.decoration.Painting; - import net.minecraft.world.entity.item.ItemEntity; --import net.minecraft.world.entity.monster.Ghast; - - public class TrackingRange - { -@@ -25,26 +24,26 @@ public class TrackingRange - if ( entity instanceof ServerPlayer ) - { - return config.playerTrackingRange; -- } else if ( entity.activationType == ActivationRange.ActivationType.MONSTER || entity.activationType == ActivationRange.ActivationType.RAIDER ) -- { -- return config.monsterTrackingRange; -- } else if ( entity instanceof Ghast ) -- { -- if ( config.monsterTrackingRange > config.monsterActivationRange ) -- { -+ // Paper start - Simplify and set water mobs to animal tracking range -+ } -+ switch (entity.activationType) { -+ case RAIDER: -+ case MONSTER: -+ case FLYING_MONSTER: - return config.monsterTrackingRange; -- } else -- { -- return config.monsterActivationRange; -- } -- } else if ( entity.activationType == ActivationRange.ActivationType.ANIMAL ) -- { -- return config.animalTrackingRange; -- } else if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) -+ case WATER: -+ case VILLAGER: -+ case ANIMAL: -+ return config.animalTrackingRange; -+ case MISC: -+ } -+ if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) -+ // Paper end - { - return config.miscTrackingRange; - } else - { -+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt - return config.otherTrackingRange; - } - } diff --git a/Remapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch b/Remapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch deleted file mode 100644 index ad4d829921..0000000000 --- a/Remapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch +++ /dev/null @@ -1,908 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 13 May 2016 01:38:06 -0400 -Subject: [PATCH] Entity Activation Range 2.0 - -Optimizes performance of Activation Range - -Adds many new configurations and a new wake up inactive system - -Fixes and adds new Immunities to improve gameplay behavior - -Adds water Mobs to activation range config and nerfs fish -Adds flying monsters to control ghast and phantoms -Adds villagers as separate config - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 40d7dbc4f1deda88d4a539b89d84b595217051b6..bf1bb1530037ebcacc8d5a491789909bddb8b697 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -855,17 +855,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - ++TimingHistory.entityTicks; // Paper - timings - // Spigot start - co.aikar.timings.Timing timer; // Paper -- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { -- entity.tickCount++; -- timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings -+ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below -+ entity.ticksLived++; -+ timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings - entity.inactiveTick(); - } finally { timer.stopTiming(); } // Paper - return; -- } -+ }*/ // Paper - comment out EAR 2 - // Spigot end - // Paper start- timings -- TimingHistory.activatedEntityTicks++; -- timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); -+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); -+ timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper - try { - // Paper end - timings - entity.setPosAndOldPos(entity.getX(), entity.getY(), entity.getZ()); -@@ -879,12 +879,16 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return Registry.ENTITY_TYPE.getKey(entity.getType()).toString(); - }); - gameprofilerfiller.incrementCounter("tickNonPassenger"); -+ if (isActive) { // Paper - EAR 2 -+ TimingHistory.activatedEntityTicks++; // Paper - entity.tick(); - entity.postTick(); // CraftBukkit -+ } else { entity.inactiveTick(); } // Paper - EAR 2 - gameprofilerfiller.pop(); - } - - this.updateChunkPos(entity); -+ } finally { timer.stopTiming(); } // Paper - timings - if (entity.inChunk) { - Iterator iterator = entity.getPassengers().iterator(); - -@@ -894,7 +898,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.tickPassenger(entity, entity1); - } - } -- } finally { timer.stopTiming(); } // Paper - timings -+ //} finally { timer.stopTiming(); } // Paper - timings - move up - - } - } -@@ -902,6 +906,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - public void tickPassenger(Entity vehicle, Entity passenger) { - if (!passenger.removed && passenger.getVehicle() == vehicle) { - if (passenger instanceof Player || this.getChunkSource().isEntityTickingChunk(passenger)) { -+ // Paper - EAR 2 -+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); -+ co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper -+ try { -+ // Paper end - passenger.setPosAndOldPos(passenger.getX(), passenger.getY(), passenger.getZ()); - passenger.yRotO = passenger.yRot; - passenger.xRotO = passenger.xRot; -@@ -913,8 +922,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return Registry.ENTITY_TYPE.getKey(passenger.getType()).toString(); - }); - gameprofilerfiller.incrementCounter("tickPassenger"); -+ // Paper start - EAR 2 -+ if (isActive) { - passenger.rideTick(); - passenger.postTick(); // CraftBukkit -+ } else { -+ passenger.setDeltaMovement(Vec3.ZERO); -+ passenger.inactiveTick(); -+ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary -+ vehicle.syncPositionOf(passenger); -+ } -+ // Paper end - EAR 2 - gameprofilerfiller.pop(); - } - -@@ -927,7 +945,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - - this.tickPassenger(passenger, entity2); - } -- } -+ } } finally { timer.stopTiming(); } // Paper - EAR2 timings - - } - } else { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index af86c370c6f834514115a8e40659f5e1aaabec75..c6881a9a5da2caed77dea30e4906d2dd99a624c1 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -67,6 +67,7 @@ import net.minecraft.world.entity.animal.AbstractFish; - import net.minecraft.world.entity.animal.Animal; - import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.entity.player.Player; -+import net.minecraft.world.entity.vehicle.AbstractMinecart; - import net.minecraft.world.entity.vehicle.Boat; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.enchantment.EnchantmentHelper; -@@ -250,7 +251,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public boolean noCulling; - public boolean hasImpulse; - public int portalCooldown; -- protected boolean isInsidePortal; -+ public boolean isInsidePortal; // Paper - public - protected int portalTime; - protected BlockPos portalEntrancePos; - private boolean invulnerable; -@@ -274,6 +275,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; -+ public boolean isTemporarilyActive = false; // Paper - public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one - protected int numCollisions = 0; // Paper - public void inactiveTick() { } -@@ -664,6 +666,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.setLocationFromBoundingbox(); - } else { - if (type == MoverType.PISTON) { -+ this.activatedTick = MinecraftServer.currentTick + 20; // Paper - movement = this.limitPistonMovement(movement); - if (movement.equals(Vec3.ZERO)) { - return; -@@ -676,6 +679,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.stuckSpeedMultiplier = Vec3.ZERO; - this.setDeltaMovement(Vec3.ZERO); - } -+ // Paper start - ignore movement changes while inactive. -+ if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof AbstractMinecart) && movement == getDeltaMovement() && type == MoverType.SELF) { -+ setDeltaMovement(Vec3.ZERO); -+ this.level.getProfiler().pop(); -+ return; -+ } -+ // Paper end - - movement = this.maybeBackOffFromEdge(movement, type); - Vec3 vec3d1 = this.collide(movement); -@@ -2011,6 +2021,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - } - -+ public void syncPositionOf(Entity entity) { positionRider(entity); } // Paper - OBFHELPER - public void positionRider(Entity passenger) { - this.positionRider(passenger, Entity::setPos); - } -@@ -2821,6 +2832,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.stringUUID; - } - -+ public final boolean isPushedByWater() { return this.isPushedByFluid(); } // Paper - OBFHELPER - the below is not an obfhelper, don't use it! - public boolean isPushedByFluid() { - // Paper start - return this.pushedByWater(); -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 016fcc4ae20e1e48728a848be28633e624ae49a7..b84dab1043c56e2deb58aec8639226f98db165d1 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -189,7 +189,7 @@ public abstract class LivingEntity extends Entity { - protected float rotOffs; - protected int deathScore;protected int getKillCount() { return this.deathScore; } // Paper - OBFHELPER - public float lastHurt; -- protected boolean jumping; -+ public boolean jumping; // Paper protected -> public - public float xxa; - public float yya; - public float zza; -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 29a2eeee9f2011ed6fcc44f19041f616decfdb38..40ab66f888f30a5506e3aa96a4b32485452e8978 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -113,7 +113,7 @@ public abstract class Mob extends LivingEntity { - public ResourceLocation lootTable; - public long lootTableSeed; - @Nullable -- private Entity leashHolder; -+ public Entity leashHolder; // Paper - private -> public - private int delayedLeashHolderId; - @Nullable - private CompoundTag leashInfoTag; -@@ -194,6 +194,19 @@ public abstract class Mob extends LivingEntity { - return this.lookControl; - } - -+ // Paper start -+ @Override -+ public void inactiveTick() { -+ super.inactiveTick(); -+ if (this.goalSelector.inactiveTick()) { -+ this.goalSelector.tick(); -+ } -+ if (this.targetSelector.inactiveTick()) { -+ this.targetSelector.tick(); -+ } -+ } -+ // Paper end -+ - public MoveControl getMoveControl() { - if (this.isPassenger() && this.getVehicle() instanceof Mob) { - Mob entityinsentient = (Mob) this.getVehicle(); -diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java -index 920ae9af8985705a0ada7da5b7085a1ed8ca7f27..7c82d453388a27b69207d051dec316fc14715e2b 100644 ---- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java -+++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java -@@ -13,6 +13,7 @@ import org.bukkit.event.entity.EntityUnleashEvent; - public abstract class PathfinderMob extends Mob { - - public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper -+ public BlockPos movingTarget = null; public BlockPos getMovingTarget() { return movingTarget; } // Paper - - protected PathfinderMob(EntityType type, Level world) { - super(type, world); -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -index d44a5b7f6cf62d5e9acacad25d47cb0d44761cfa..558dd72c47930f6993952467f83b5a54ead95d92 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -@@ -20,7 +20,10 @@ public abstract class Goal { - - public void start() {} - -- public void stop() {} -+ public void stop() { -+ onTaskReset(); // Paper -+ } -+ public void onTaskReset() {} // Paper - - public void tick() {} - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -index 9066db5c9a76cfb9665bef77b36172f1ea6ba931..9bd2ee05a0de6678ad8933a8ffbe0ae66bd073b4 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -@@ -26,10 +26,11 @@ public class GoalSelector { - } - }; - private final Map lockedFlags = new EnumMap(Goal.Flag.class); -- private final Set availableGoals = Sets.newLinkedHashSet(); -+ private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER - private final Supplier profiler; - private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); -- private int newGoalRate = 3; -+ private int newGoalRate = 3;private int getTickRate() { return newGoalRate; } // Paper - OBFHELPER -+ private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO - - public GoalSelector(Supplier profiler) { - this.profiler = profiler; -@@ -39,6 +40,21 @@ public class GoalSelector { - this.availableGoals.add(new WrappedGoal(priority, goal)); - } - -+ // Paper start -+ public boolean inactiveTick() { -+ incRate(); -+ return getCurRate() % getTickRate() == 0; -+ } -+ public boolean hasTasks() { -+ for (WrappedGoal task : getTasks()) { -+ if (task.isRunning()) { -+ return true; -+ } -+ } -+ return false; -+ } -+ // Paper end -+ - public void removeGoal(Goal goal) { - this.availableGoals.stream().filter((pathfindergoalwrapped) -> { - return pathfindergoalwrapped.getGoal() == goal; -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -index c8680e795deeb68e0662eac7c760a103d1c767b4..e83cb412d8549b86d0348a2aa37c79201a5930be 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -@@ -9,12 +9,12 @@ import net.minecraft.world.level.LevelReader; - - public abstract class MoveToBlockGoal extends Goal { - -- protected final PathfinderMob mob; -+ protected final PathfinderMob mob;public PathfinderMob getEntity() { return mob; } // Paper - OBFHELPER - public final double speedModifier; - protected int nextStartTick; - protected int tryTicks; - private int maxStayTicks; -- protected BlockPos blockPos;public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER -+ protected BlockPos blockPos; public final BlockPos getTargetPosition() { return this.blockPos; } public void setTargetPosition(BlockPos pos) { this.blockPos = pos; getEntity().movingTarget = pos != BlockPos.ZERO ? pos : null; } // Paper - OBFHELPER - private boolean reachedTarget; - private final int searchRange; - private final int verticalSearchRange; -@@ -23,6 +23,13 @@ public abstract class MoveToBlockGoal extends Goal { - public MoveToBlockGoal(PathfinderMob mob, double speed, int range) { - this(mob, speed, range, 1); - } -+ // Paper start - activation range improvements -+ @Override -+ public void onTaskReset() { -+ super.onTaskReset(); -+ setTargetPosition(BlockPos.ZERO); -+ } -+ // Paper end - - public MoveToBlockGoal(PathfinderMob mob, double speed, int range, int maxYDifference) { - this.blockPos = BlockPos.ZERO; -@@ -111,6 +118,7 @@ public abstract class MoveToBlockGoal extends Goal { - blockposition_mutableblockposition.setWithOffset((Vec3i) blockposition, i1, k - 1, j1); - if (this.mob.isWithinRestriction((BlockPos) blockposition_mutableblockposition) && this.isValidTarget(this.mob.level, blockposition_mutableblockposition)) { - this.blockPos = blockposition_mutableblockposition; -+ setTargetPosition(blockposition_mutableblockposition.immutable()); // Paper - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -index 9921adf9292e0eff77515841d1b109a07b489367..81b4618a7979ee8dd25e1749c084de9262318ef4 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -@@ -64,6 +64,7 @@ public class WrappedGoal extends Goal { - return this.goal.getFlags(); - } - -+ public boolean isRunning() { return this.isRunning(); } // Paper - OBFHELPER - public boolean isRunning() { - return this.isRunning; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -index 5a7310bb48c1b8a72ad3c5d82c44fff8800995a2..a24af0600ad3e7d189581aa06a8e998f6a12e0fc 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -@@ -454,6 +454,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { - return this.caravanTail != null; - } - -+ public final boolean inCaravan() { return this.inCaravan(); } // Paper - OBFHELPER - public boolean inCaravan() { - return this.caravanHead != null; - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -index ae8f850baa14a4f4277da5b6fdb1e5ccb44c4f35..9eee68a5a84e121698d26bd54212a72c75e16251 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -70,10 +70,12 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan - return super.finalizeSpawn(world, difficulty, spawnReason, (SpawnGroupData) entityData, entityTag); - } - -+ public final int getUnhappy() { return getUnhappyCounter(); } // Paper - OBFHELPER - public int getUnhappyCounter() { - return (Integer) this.entityData.get(AbstractVillager.DATA_UNHAPPY_COUNTER); - } - -+ public final void setUnhappy(int i) { setUnhappyCounter(i); } // Paper - OBFHELPER - public void setUnhappyCounter(int ticks) { - this.entityData.set(AbstractVillager.DATA_UNHAPPY_COUNTER, ticks); - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index eed6265dc8275921a18fc5f4970ba131ba782132..4aa34320ef7d6c62ccb17734bfa61d406190b919 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/Villager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -212,17 +212,29 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - @Override - public void inactiveTick() { - // SPIGOT-3874, SPIGOT-3894, SPIGOT-3846, SPIGOT-5286 :( -- if (level.spigotConfig.tickInactiveVillagers && this.isEffectiveAi()) { -- this.customServerAiStep(); -+ // Paper start -+ if (this.getUnhappy() > 0) { -+ this.setUnhappy(this.getUnhappy() - 1); - } -+ if (this.isEffectiveAi()) { -+ if (level.spigotConfig.tickInactiveVillagers) { -+ this.customServerAiStep(); -+ } else { -+ this.mobTick(true); -+ } -+ } -+ doReputationTick(); -+ // Paper end -+ - super.inactiveTick(); - } - // Spigot End - - @Override -- protected void customServerAiStep() { -+ protected void customServerAiStep() { mobTick(false); } -+ protected void mobTick(boolean inactive) { - this.level.getProfiler().push("villagerBrain"); -- this.getBrain().tick((ServerLevel) this.level, this); // CraftBukkit - decompile error -+ if (!inactive) this.getBrain().tick((ServerLevel) this.level, this); // CraftBukkit - decompile error // Paper - this.level.getProfiler().pop(); - if (this.assignProfessionWhenSpawned) { - this.assignProfessionWhenSpawned = false; -@@ -246,7 +258,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - this.lastTradedPlayer = null; - } - -- if (!this.isNoAi() && this.random.nextInt(100) == 0) { -+ if (!inactive && !this.isNoAi() && this.random.nextInt(100) == 0) { // Paper - Raid raid = ((ServerLevel) this.level).getRaidAt(this.blockPosition()); - - if (raid != null && raid.isActive() && !raid.isOver()) { -@@ -257,6 +269,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.isTrading()) { - this.stopTrading(); - } -+ if (inactive) return; // Paper - - super.customServerAiStep(); - } -@@ -900,6 +913,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - } - } - -+ private void doReputationTick() { maybeDecayGossip(); } // Paper - OBFHELPER - private void maybeDecayGossip() { - long i = this.level.getGameTime(); - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 6b79f8cd9258af47afa6efa7b1f97c3780be58b0..1d536d77518a70bdc1a23924aea99df1042b3cd5 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -142,6 +142,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public long ticksPerWaterSpawns; - public long ticksPerWaterAmbientSpawns; - public long ticksPerAmbientSpawns; -+ // Paper start -+ public int wakeupInactiveRemainingAnimals; -+ public int wakeupInactiveRemainingFlying; -+ public int wakeupInactiveRemainingMonsters; -+ public int wakeupInactiveRemainingVillagers; -+ // Paper end - public boolean populating; - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3e4ac3eaf 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -1,41 +1,55 @@ - package org.spigotmc; - - import java.util.Collection; -+import net.minecraft.core.BlockPos; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.FlyingMob; - import net.minecraft.world.entity.LightningBolt; - import net.minecraft.world.entity.LivingEntity; -+import net.minecraft.world.entity.Mob; - import net.minecraft.world.entity.PathfinderMob; -+import net.minecraft.world.entity.ai.Brain; - import net.minecraft.world.entity.ambient.AmbientCreature; - import net.minecraft.world.entity.animal.Animal; -+import net.minecraft.world.entity.animal.Bee; - import net.minecraft.world.entity.animal.Sheep; -+import net.minecraft.world.entity.animal.WaterAnimal; -+import net.minecraft.world.entity.animal.horse.Llama; - import net.minecraft.world.entity.boss.EnderDragonPart; - import net.minecraft.world.entity.boss.enderdragon.EndCrystal; - import net.minecraft.world.entity.boss.enderdragon.EnderDragon; - import net.minecraft.world.entity.boss.wither.WitherBoss; -+import net.minecraft.world.entity.item.FallingBlockEntity; - import net.minecraft.world.entity.item.PrimedTnt; - import net.minecraft.world.entity.monster.Creeper; --import net.minecraft.world.entity.monster.Monster; --import net.minecraft.world.entity.monster.Slime; -+import net.minecraft.world.entity.monster.Enemy; -+import net.minecraft.world.entity.monster.Pillager; - import net.minecraft.world.entity.npc.Villager; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.projectile.AbstractArrow; - import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; -+import net.minecraft.world.entity.projectile.EyeOfEnder; - import net.minecraft.world.entity.projectile.FireworkRocketEntity; - import net.minecraft.world.entity.projectile.ThrowableProjectile; - import net.minecraft.world.entity.projectile.ThrownTrident; - import net.minecraft.world.entity.raid.Raider; -+import co.aikar.timings.MinecraftTimings; -+import net.minecraft.world.entity.schedule.Activity; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.chunk.LevelChunk; - import net.minecraft.world.phys.AABB; --import co.aikar.timings.MinecraftTimings; - - public class ActivationRange - { - - public enum ActivationType - { -+ WATER, // Paper -+ FLYING_MONSTER, // Paper -+ VILLAGER, // Paper - MONSTER, - ANIMAL, - RAIDER, -@@ -43,6 +57,43 @@ public class ActivationRange - - AABB boundingBox = new AABB( 0, 0, 0, 0, 0, 0 ); - } -+ // Paper start -+ -+ static Activity[] VILLAGER_PANIC_IMMUNITIES = { -+ Activity.HIDE, -+ Activity.PRE_RAID, -+ Activity.RAID, -+ Activity.PANIC -+ }; -+ -+ private static int checkInactiveWakeup(Entity entity) { -+ Level world = entity.level; -+ SpigotWorldConfig config = world.spigotConfig; -+ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; -+ if (entity.activationType == ActivationType.VILLAGER) { -+ if (inactiveFor > config.wakeUpInactiveVillagersEvery && world.wakeupInactiveRemainingVillagers > 0) { -+ world.wakeupInactiveRemainingVillagers--; -+ return config.wakeUpInactiveVillagersFor; -+ } -+ } else if (entity.activationType == ActivationType.ANIMAL) { -+ if (inactiveFor > config.wakeUpInactiveAnimalsEvery && world.wakeupInactiveRemainingAnimals > 0) { -+ world.wakeupInactiveRemainingAnimals--; -+ return config.wakeUpInactiveAnimalsFor; -+ } -+ } else if (entity.activationType == ActivationType.FLYING_MONSTER) { -+ if (inactiveFor > config.wakeUpInactiveFlyingEvery && world.wakeupInactiveRemainingFlying > 0) { -+ world.wakeupInactiveRemainingFlying--; -+ return config.wakeUpInactiveFlyingFor; -+ } -+ } else if (entity.activationType == ActivationType.MONSTER || entity.activationType == ActivationType.RAIDER) { -+ if (inactiveFor > config.wakeUpInactiveMonstersEvery && world.wakeupInactiveRemainingMonsters > 0) { -+ world.wakeupInactiveRemainingMonsters--; -+ return config.wakeUpInactiveMonstersFor; -+ } -+ } -+ return -1; -+ } -+ // Paper end - - static AABB maxBB = new AABB( 0, 0, 0, 0, 0, 0 ); - -@@ -55,10 +106,13 @@ public class ActivationRange - */ - public static ActivationType initializeEntityActivationType(Entity entity) - { -+ if (entity instanceof WaterAnimal) { return ActivationType.WATER; } // Paper -+ else if (entity instanceof Villager) { return ActivationType.VILLAGER; } // Paper -+ else if (entity instanceof FlyingMob && entity instanceof Enemy) { return ActivationType.FLYING_MONSTER; } // Paper - doing & Monster incase Flying no longer includes monster in future - if ( entity instanceof Raider ) - { - return ActivationType.RAIDER; -- } else if ( entity instanceof Monster || entity instanceof Slime ) -+ } else if ( entity instanceof Enemy ) // Paper - correct monster check - { - return ActivationType.MONSTER; - } else if ( entity instanceof PathfinderMob || entity instanceof AmbientCreature ) -@@ -79,10 +133,14 @@ public class ActivationRange - */ - public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) - { -- if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange == 0 ) -- || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange == 0 ) -- || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange == 0 ) -- || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange == 0 ) -+ if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.VILLAGER && config.villagerActivationRange <= 0 ) // Paper -+ || ( entity.activationType == ActivationType.WATER && config.waterActivationRange <= 0 ) // Paper -+ || ( entity.activationType == ActivationType.FLYING_MONSTER && config.flyingMonsterActivationRange <= 0 ) // Paper -+ || entity instanceof EyeOfEnder // Paper - || entity instanceof Player - || entity instanceof ThrowableProjectile - || entity instanceof EnderDragon -@@ -91,7 +149,7 @@ public class ActivationRange - || entity instanceof AbstractHurtingProjectile - || entity instanceof LightningBolt - || entity instanceof PrimedTnt -- || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks -+ || entity instanceof FallingBlockEntity // Paper - Always tick falling blocks - || entity instanceof EndCrystal - || entity instanceof FireworkRocketEntity - || entity instanceof ThrownTrident ) -@@ -115,10 +173,25 @@ public class ActivationRange - final int raiderActivationRange = world.spigotConfig.raiderActivationRange; - final int animalActivationRange = world.spigotConfig.animalActivationRange; - final int monsterActivationRange = world.spigotConfig.monsterActivationRange; -+ // Paper start -+ final int waterActivationRange = world.spigotConfig.waterActivationRange; -+ final int flyingActivationRange = world.spigotConfig.flyingMonsterActivationRange; -+ final int villagerActivationRange = world.spigotConfig.villagerActivationRange; -+ world.wakeupInactiveRemainingAnimals = Math.min(world.wakeupInactiveRemainingAnimals + 1, world.spigotConfig.wakeUpInactiveAnimals); -+ world.wakeupInactiveRemainingVillagers = Math.min(world.wakeupInactiveRemainingVillagers + 1, world.spigotConfig.wakeUpInactiveVillagers); -+ world.wakeupInactiveRemainingMonsters = Math.min(world.wakeupInactiveRemainingMonsters + 1, world.spigotConfig.wakeUpInactiveMonsters); -+ world.wakeupInactiveRemainingFlying = Math.min(world.wakeupInactiveRemainingFlying + 1, world.spigotConfig.wakeUpInactiveFlying); -+ final ServerChunkCache chunkProvider = (ServerChunkCache) world.getChunkSource(); -+ // Paper end - - int maxRange = Math.max( monsterActivationRange, animalActivationRange ); - maxRange = Math.max( maxRange, raiderActivationRange ); - maxRange = Math.max( maxRange, miscActivationRange ); -+ // Paper start -+ maxRange = Math.max( maxRange, flyingActivationRange ); -+ maxRange = Math.max( maxRange, waterActivationRange ); -+ maxRange = Math.max( maxRange, villagerActivationRange ); -+ // Paper end - maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); - - for ( Player player : world.players() ) -@@ -130,6 +203,11 @@ public class ActivationRange - ActivationType.RAIDER.boundingBox = player.getBoundingBox().inflate( raiderActivationRange, 256, raiderActivationRange ); - ActivationType.ANIMAL.boundingBox = player.getBoundingBox().inflate( animalActivationRange, 256, animalActivationRange ); - ActivationType.MONSTER.boundingBox = player.getBoundingBox().inflate( monsterActivationRange, 256, monsterActivationRange ); -+ // Paper start -+ ActivationType.WATER.boundingBox = player.getBoundingBox().inflate( waterActivationRange, 256, waterActivationRange ); -+ ActivationType.FLYING_MONSTER.boundingBox = player.getBoundingBox().inflate( flyingActivationRange, 256, flyingActivationRange ); -+ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().inflate( villagerActivationRange, 256, waterActivationRange ); -+ // Paper end - - int i = Mth.floor( maxBB.minX / 16.0D ); - int j = Mth.floor( maxBB.maxX / 16.0D ); -@@ -140,7 +218,7 @@ public class ActivationRange - { - for ( int j1 = k; j1 <= l; ++j1 ) - { -- LevelChunk chunk = (LevelChunk) world.getChunkIfLoadedImmediately( i1, j1 ); -+ LevelChunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper - if ( chunk != null ) - { - activateChunkEntities( chunk ); -@@ -158,19 +236,15 @@ public class ActivationRange - */ - private static void activateChunkEntities(LevelChunk chunk) - { -- for ( java.util.List slice : chunk.entitySlices ) -- { -- for ( Entity entity : (Collection) slice ) -+ // Paper start -+ Entity[] rawData = chunk.entities.getRawData(); -+ for (int i = 0; i < chunk.entities.size(); i++) { -+ Entity entity = rawData[i]; -+ //for ( Entity entity : (Collection) slice ) -+ // Paper end - { -- if ( MinecraftServer.currentTick > entity.activatedTick ) -- { -- if ( entity.defaultActivationState ) -- { -- entity.activatedTick = MinecraftServer.currentTick; -- continue; -- } -- if ( entity.activationType.boundingBox.intersects( entity.getBoundingBox() ) ) -- { -+ if (MinecraftServer.currentTick > entity.activatedTick) { -+ if (entity.defaultActivationState || entity.activationType.boundingBox.intersects(entity.getBoundingBox())) { // Paper - entity.activatedTick = MinecraftServer.currentTick; - } - } -@@ -185,56 +259,105 @@ public class ActivationRange - * @param entity - * @return - */ -- public static boolean checkEntityImmunities(Entity entity) -+ public static int checkEntityImmunities(Entity entity) // Paper - return # of ticks to get immunity - { -+ // Paper start -+ SpigotWorldConfig config = entity.level.spigotConfig; -+ int inactiveWakeUpImmunity = checkInactiveWakeup(entity); -+ if (inactiveWakeUpImmunity > -1) { -+ return inactiveWakeUpImmunity; -+ } -+ if (entity.remainingFireTicks > 0) { -+ return 2; -+ } -+ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; -+ // Paper end - // quick checks. -- if ( entity.wasTouchingWater || entity.remainingFireTicks > 0 ) -+ if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByWater()) ) // Paper - { -- return true; -+ return 100; // Paper - } - if ( !( entity instanceof AbstractArrow ) ) - { -- if ( !entity.isOnGround() || !entity.passengers.isEmpty() || entity.isPassenger() ) -+ if ( (!entity.isOnGround() && !(entity instanceof FlyingMob)) ) // Paper - remove passengers logic - { -- return true; -+ return 10; // Paper - } - } else if ( !( (AbstractArrow) entity ).inGround ) - { -- return true; -+ return 1; // Paper - } - // special cases. - if ( entity instanceof LivingEntity ) - { - LivingEntity living = (LivingEntity) entity; -- if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTime > 0 || living.activeEffects.size() > 0 ) -+ if ( living.onClimbable() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 ) // Paper - { -- return true; -+ return 1; // Paper - } -- if ( entity instanceof PathfinderMob && ( (PathfinderMob) entity ).getTarget() != null ) -+ if ( entity instanceof Mob && ((Mob) entity ).getTarget() != null) // Paper - { -- return true; -+ return 20; // Paper -+ } -+ // Paper start -+ if (entity instanceof Bee) { -+ Bee bee = (Bee)entity; -+ BlockPos movingTarget = bee.getMovingTarget(); -+ if (bee.isAngry() || -+ (bee.getHivePos() != null && bee.getHivePos().equals(movingTarget)) || -+ (bee.getSavedFlowerPos() != null && bee.getSavedFlowerPos().equals(movingTarget)) -+ ) { -+ return 20; -+ } -+ } -+ if ( entity instanceof Villager ) { -+ Brain behaviorController = ((Villager) entity).getBrain(); -+ -+ if (config.villagersActiveForPanic) { -+ for (Activity activity : VILLAGER_PANIC_IMMUNITIES) { -+ if (behaviorController.isActive(activity)) { -+ return 20*5; -+ } -+ } -+ } -+ -+ if (config.villagersWorkImmunityAfter > 0 && inactiveFor >= config.villagersWorkImmunityAfter) { -+ if (behaviorController.isActive(Activity.WORK)) { -+ return config.villagersWorkImmunityFor; -+ } -+ } - } -- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() ) -+ if ( entity instanceof Llama && ( (Llama) entity ).inCaravan() ) - { -- return true; -+ return 1; - } -+ // Paper end - if ( entity instanceof Animal ) - { - Animal animal = (Animal) entity; - if ( animal.isBaby() || animal.isInLove() ) - { -- return true; -+ return 5; // Paper - } - if ( entity instanceof Sheep && ( (Sheep) entity ).isSheared() ) - { -- return true; -+ return 1; // Paper - } - } - if (entity instanceof Creeper && ((Creeper) entity).isIgnited()) { // isExplosive -- return true; -+ return 20; // Paper - } -+ // Paper start -+ if (entity instanceof Mob && ((Mob) entity).targetSelector.hasTasks() ) { -+ return 0; -+ } -+ if (entity instanceof Pillager) { -+ Pillager pillager = (Pillager) entity; -+ // TODO:? -+ } -+ // Paper end - } -- return false; -+ return -1; // Paper - } - - /** -@@ -249,8 +372,19 @@ public class ActivationRange - if ( !entity.inChunk || entity instanceof FireworkRocketEntity ) { - return true; - } -+ // Paper start - special case always immunities -+ // immunize brand new entities, dead entities, and portal scenarios -+ if (entity.defaultActivationState || entity.tickCount < 20*10 || !entity.isAlive() || entity.isInsidePortal || entity.portalCooldown > 0) { -+ return true; -+ } -+ // immunize leashed entities -+ if (entity instanceof Mob && ((Mob)entity).leashHolder instanceof Player) { -+ return true; -+ } -+ // Paper end - -- boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; -+ boolean isActive = entity.activatedTick >= MinecraftServer.currentTick; -+ entity.isTemporarilyActive = false; // Paper - - // Should this entity tick? - if ( !isActive ) -@@ -258,15 +392,19 @@ public class ActivationRange - if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) - { - // Check immunities every 20 ticks. -- if ( checkEntityImmunities( entity ) ) -- { -- // Triggered some sort of immunity, give 20 full ticks before we check again. -- entity.activatedTick = MinecraftServer.currentTick + 20; -+ // Paper start -+ int immunity = checkEntityImmunities(entity); -+ if (immunity >= 0) { -+ entity.activatedTick = MinecraftServer.currentTick + immunity; -+ } else { -+ entity.isTemporarilyActive = true; - } -+ // Paper end - isActive = true; -+ - } - // Add a little performance juice to active entities. Skip 1/4 if not immune. -- } else if ( !entity.defaultActivationState && entity.tickCount % 4 == 0 && !checkEntityImmunities( entity ) ) -+ } else if (entity.tickCount % 4 == 0 && checkEntityImmunities( entity) < 0 ) // Paper - { - isActive = false; - } -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 34ee684901906fc2ef5f0d09680d2686b813e52b..6b015c1f26facb4e82d75b252164dec05731ca6c 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -180,13 +180,59 @@ public class SpigotWorldConfig - public int monsterActivationRange = 32; - public int raiderActivationRange = 48; - public int miscActivationRange = 16; -+ // Paper start -+ public int flyingMonsterActivationRange = 32; -+ public int waterActivationRange = 16; -+ public int villagerActivationRange = 32; -+ public int wakeUpInactiveAnimals = 4; -+ public int wakeUpInactiveAnimalsEvery = 60*20; -+ public int wakeUpInactiveAnimalsFor = 5*20; -+ public int wakeUpInactiveMonsters = 8; -+ public int wakeUpInactiveMonstersEvery = 20*20; -+ public int wakeUpInactiveMonstersFor = 5*20; -+ public int wakeUpInactiveVillagers = 4; -+ public int wakeUpInactiveVillagersEvery = 30*20; -+ public int wakeUpInactiveVillagersFor = 5*20; -+ public int wakeUpInactiveFlying = 8; -+ public int wakeUpInactiveFlyingEvery = 10*20; -+ public int wakeUpInactiveFlyingFor = 5*20; -+ public int villagersWorkImmunityAfter = 5*20; -+ public int villagersWorkImmunityFor = 20; -+ public boolean villagersActiveForPanic = true; -+ // Paper end - public boolean tickInactiveVillagers = true; - private void activationRange() - { -+ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", animalActivationRange) != animalActivationRange; // Paper - animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange ); - monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange ); - raiderActivationRange = getInt( "entity-activation-range.raiders", raiderActivationRange ); - miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange ); -+ // Paper start -+ waterActivationRange = getInt( "entity-activation-range.water", waterActivationRange ); -+ villagerActivationRange = getInt( "entity-activation-range.villagers", hasAnimalsConfig ? animalActivationRange : villagerActivationRange ); -+ flyingMonsterActivationRange = getInt( "entity-activation-range.flying-monsters", flyingMonsterActivationRange ); -+ -+ wakeUpInactiveAnimals = getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", wakeUpInactiveAnimals); -+ wakeUpInactiveAnimalsEvery = getInt("entity-activation-range.wake-up-inactive.animals-every", wakeUpInactiveAnimalsEvery); -+ wakeUpInactiveAnimalsFor = getInt("entity-activation-range.wake-up-inactive.animals-for", wakeUpInactiveAnimalsFor); -+ -+ wakeUpInactiveMonsters = getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", wakeUpInactiveMonsters); -+ wakeUpInactiveMonstersEvery = getInt("entity-activation-range.wake-up-inactive.monsters-every", wakeUpInactiveMonstersEvery); -+ wakeUpInactiveMonstersFor = getInt("entity-activation-range.wake-up-inactive.monsters-for", wakeUpInactiveMonstersFor); -+ -+ wakeUpInactiveVillagers = getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", wakeUpInactiveVillagers); -+ wakeUpInactiveVillagersEvery = getInt("entity-activation-range.wake-up-inactive.villagers-every", wakeUpInactiveVillagersEvery); -+ wakeUpInactiveVillagersFor = getInt("entity-activation-range.wake-up-inactive.villagers-for", wakeUpInactiveVillagersFor); -+ -+ wakeUpInactiveFlying = getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", wakeUpInactiveFlying); -+ wakeUpInactiveFlyingEvery = getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", wakeUpInactiveFlyingEvery); -+ wakeUpInactiveFlyingFor = getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", wakeUpInactiveFlyingFor); -+ -+ villagersWorkImmunityAfter = getInt( "entity-activation-range.villagers-work-immunity-after", villagersWorkImmunityAfter ); -+ villagersWorkImmunityFor = getInt( "entity-activation-range.villagers-work-immunity-for", villagersWorkImmunityFor ); -+ villagersActiveForPanic = getBoolean( "entity-activation-range.villagers-active-for-panic", villagersActiveForPanic ); -+ // Paper end - tickInactiveVillagers = getBoolean( "entity-activation-range.tick-inactive-villagers", tickInactiveVillagers ); - log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Ra " + raiderActivationRange + " / Mi " + miscActivationRange + " / Tiv " + tickInactiveVillagers ); - } diff --git a/Remapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch b/Remapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch deleted file mode 100644 index 283ad7000c..0000000000 --- a/Remapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AJMFactsheets -Date: Wed, 22 Jan 2020 19:52:28 -0600 -Subject: [PATCH] Fix items vanishing through end portal - -If the Paper configuration option "keep-spawn-loaded" is set to false, -items entering the overworld from the end will spawn at Y = 0. - -This is due to logic in the getHighestBlockYAt method in World.java -only searching the heightmap if the chunk is loaded. - -Quickly loading the exact world spawn chunk before searching the -heightmap resolves the issue without having to load all spawn chunks. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c6881a9a5da2caed77dea30e4906d2dd99a624c1..efc9cb6def2f4ee327329dc090d2918ff60d8e19 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2734,6 +2734,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - BlockPos blockposition1; - - if (flag1) { -+ // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate -+ this.level.getChunkAt(this.level.getSpawn()); -+ // Paper end - blockposition1 = ServerLevel.END_SPAWN_POINT; - } else { - blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSpawn()); diff --git a/Remapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/Remapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch deleted file mode 100644 index f19be75b52..0000000000 --- a/Remapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 26 Jan 2020 16:30:19 -0600 -Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java -index 2c9e3dd1b9dd7bb8825a2eb9fecc2b2be348d055..868e9cdeb3c7effb398cef6f6f9c1e4fffa2db8c 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java -@@ -16,7 +16,7 @@ public class FlyingMoveControl extends MoveControl { - } - - @Override -- public void tick() { -+ public void tick() { tick(); } public void tick() { // Paper - OBFHELPER - if (this.operation == MoveControl.Operation.MOVE_TO) { - this.operation = MoveControl.Operation.WAIT; - this.mob.setNoGravity(true); -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java -index ab65f0327766463a5e53fdd723e243464319fdbe..f4984d601d14c684e75f887f5f5d2f5a29326b15 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java -@@ -16,7 +16,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; - - public class MoveControl { - -- protected final Mob mob; -+ protected final Mob mob; public final Mob getEntity() { return mob; } // Paper - OBFHELPER - protected double wantedX; - protected double wantedY; - protected double wantedZ; -diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index edd6d63f715acef1a77eba0cf46ff8267228f4c6..9b68809b91910d2bbb82cafe23d1de5dfff4221c 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Bee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -111,7 +111,17 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - - public Bee(EntityType type, Level world) { - super(type, world); -- this.moveControl = new FlyingMoveControl(this, 20, true); -+ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 -+ this.moveControl = new FlyingMoveControl(this, 20, true) { -+ @Override -+ public void tick() { -+ if (getEntity().getY() <= 0) { -+ getEntity().setNoGravity(false); -+ } -+ super.tick(); -+ } -+ }; -+ // Paper end - this.lookControl = new Bee.BeeLookControl(this); - this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); - this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); diff --git a/Remapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/Remapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch deleted file mode 100644 index 009a0fad66..0000000000 --- a/Remapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 25 Jan 2020 17:04:35 -0800 -Subject: [PATCH] Optimise getChunkAt calls for loaded chunks - -bypass the need to get a player chunk, then get the either, -then unwrap it... - -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index eac5e799c4d26e53286a27c54b56899ba0b9ffb2..3aeb8426b0461ec572c1499116be80f968bb4104 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -470,6 +470,12 @@ public class ServerChunkCache extends ChunkSource { - return this.getChunk(x, z, leastStatus, create); - }, this.mainThreadProcessor).join(); - } else { -+ // Paper start - optimise for loaded chunks -+ LevelChunk ifLoaded = this.getChunkAtIfLoadedMainThread(x, z); -+ if (ifLoaded != null) { -+ return ifLoaded; -+ } -+ // Paper end - ProfilerFiller gameprofilerfiller = this.level.getProfiler(); - - gameprofilerfiller.incrementCounter("getChunk"); -@@ -520,39 +526,7 @@ public class ServerChunkCache extends ChunkSource { - if (Thread.currentThread() != this.mainThread) { - return null; - } else { -- this.level.getProfiler().incrementCounter("getChunkNow"); -- long k = ChunkPos.asLong(chunkX, chunkZ); -- -- for (int l = 0; l < 4; ++l) { -- if (k == this.lastChunkPos[l] && this.lastChunkStatus[l] == ChunkStatus.FULL) { -- ChunkAccess ichunkaccess = this.lastChunk[l]; -- -- return ichunkaccess instanceof LevelChunk ? (LevelChunk) ichunkaccess : null; -- } -- } -- -- ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); -- -- if (playerchunk == null) { -- return null; -- } else { -- Either either = (Either) playerchunk.getFutureIfPresent(ChunkStatus.FULL).getNow(null); // CraftBukkit - decompile error -- -- if (either == null) { -- return null; -- } else { -- ChunkAccess ichunkaccess1 = (ChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error -- -- if (ichunkaccess1 != null) { -- this.storeInCache(k, ichunkaccess1, ChunkStatus.FULL); -- if (ichunkaccess1 instanceof LevelChunk) { -- return (LevelChunk) ichunkaccess1; -- } -- } -- -- return null; -- } -- } -+ return this.getChunkAtIfLoadedMainThread(chunkX, chunkZ); // Paper - optimise for loaded chunks - } - } - diff --git a/Remapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch b/Remapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch deleted file mode 100644 index 04082e9a36..0000000000 --- a/Remapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 8 Feb 2020 18:02:24 -0600 -Subject: [PATCH] Allow overriding the java version check - --DPaper.IgnoreJavaVersion=true - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 808a7688ed81bdfef623ee0a151ff8f94df2a3d7..c519ceca6f7788ca7c5d74ad1001dbc09f62681c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -181,7 +181,7 @@ public class Main { - float javaVersion = Float.parseFloat(System.getProperty("java.class.version")); - if (javaVersion > 60.0) { - System.err.println("Unsupported Java detected (" + javaVersion + "). Only up to Java 16 is supported."); -- return; -+ if (!Boolean.getBoolean("Paper.IgnoreJavaVersion")) return; // Paper - } - - try { diff --git a/Remapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch b/Remapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch deleted file mode 100644 index 5bc9d2e683..0000000000 --- a/Remapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 9 Feb 2020 00:19:05 -0600 -Subject: [PATCH] Add ThrownEggHatchEvent - -Adds a new event similar to PlayerEggThrowEvent, but without the Player requirement -(dispensers can throw eggs to hatch them, too). - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java -index f3808a5e9155e1bf6c6219fc494864bb7dc61117..520eace73b569c2c77e76e0dfd18eb9c7188ec30 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java -@@ -63,6 +63,16 @@ public class ThrownEgg extends ThrowableItemProjectile { - hatchingType = event.getHatchingType(); - } - -+ // Paper start -+ com.destroystokyo.paper.event.entity.ThrownEggHatchEvent event = new com.destroystokyo.paper.event.entity.ThrownEggHatchEvent((org.bukkit.entity.Egg) getBukkitEntity(), hatching, b0, hatchingType); -+ event.callEvent(); -+ -+ b0 = event.getNumHatches(); -+ hatching = event.isHatching(); -+ hatchingType = event.getHatchingType(); -+ // Paper end -+ -+ - if (hatching) { - for (int i = 0; i < b0; ++i) { - Entity entity = level.getWorld().createEntity(new org.bukkit.Location(level.getWorld(), this.getX(), this.getY(), this.getZ(), this.yRot, 0.0F), hatchingType.getEntityClass()); diff --git a/Remapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch b/Remapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch deleted file mode 100644 index 881f7be3f4..0000000000 --- a/Remapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch +++ /dev/null @@ -1,407 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Jan 2020 21:28:00 -0800 -Subject: [PATCH] Optimise random block ticking - -Massive performance improvement for random block ticking. -The performance increase comes from the fact that the vast -majority of attempted block ticks (~95% in my testing) fail -because the randomly selected block is not tickable. - -Now only tickable blocks are targeted, however this means that -the maximum number of block ticks occurs per chunk. However, -not all chunks are going to be targeted. The percent chance -of a chunk being targeted is based on how many tickable blocks -are in the chunk. -This means that while block ticks are spread out less, the -total number of blocks ticked per world tick remains the same. -Therefore, the chance of a random tickable block being ticked -remains the same. - -diff --git a/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3edc8e52e06a62ce9f8cc734fd7458b37cfaad91 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java -@@ -0,0 +1,46 @@ -+package com.destroystokyo.paper.util.math; -+ -+import java.util.Random; -+ -+public final class ThreadUnsafeRandom extends Random { -+ -+ // See javadoc and internal comments for java.util.Random where these values come from, how they are used, and the author for them. -+ private static final long multiplier = 0x5DEECE66DL; -+ private static final long addend = 0xBL; -+ private static final long mask = (1L << 48) - 1; -+ -+ private static long initialScramble(long seed) { -+ return (seed ^ multiplier) & mask; -+ } -+ -+ private long seed; -+ -+ @Override -+ public void setSeed(long seed) { -+ // note: called by Random constructor -+ this.seed = initialScramble(seed); -+ } -+ -+ @Override -+ protected int next(int bits) { -+ // avoid the expensive CAS logic used by superclass -+ return (int) (((this.seed = this.seed * multiplier + addend) & mask) >>> (48 - bits)); -+ } -+ -+ // Taken from -+ // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ -+ // https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2016/06/25/fastrange.c -+ // Original license is public domain -+ public static int fastRandomBounded(final long randomInteger, final long limit) { -+ // randomInteger must be [0, pow(2, 32)) -+ // limit must be [0, pow(2, 32)) -+ return (int)((randomInteger * limit) >>> 32); -+ } -+ -+ @Override -+ public int nextInt(int bound) { -+ // yes this breaks random's spec -+ // however there's nothing that uses this class that relies on it -+ return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound); -+ } -+} -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index b13e5d05d862ea8c6031b8071f525f00bc48f7e7..3db77d9eda98eacb099135643aff5e94751f4c7c 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -468,6 +468,7 @@ public class BlockPos extends Vec3i { - return this.set(Mth.floor(x), Mth.floor(y), Mth.floor(z)); - } - -+ public final BlockPos.MutableBlockPos setValues(final Vec3i baseblockposition) { return this.set(baseblockposition); } // Paper - OBFHELPER - public BlockPos.MutableBlockPos set(Vec3i pos) { - return this.set(pos.getX(), pos.getY(), pos.getZ()); - } -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027ea23b400b 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -669,7 +669,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - }); - } - -- public void tickChunk(LevelChunk chunk, int randomTickSpeed) { -+ // Paper start - optimise random block ticking -+ private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos(); -+ private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom(); -+ // Paper end -+ -+ public void tickChunk(LevelChunk chunk, int randomTickSpeed) { final int randomTickSpeed1 = randomTickSpeed; // Paper - ChunkPos chunkcoordintpair = chunk.getPos(); - boolean flag = this.isRaining(); - int j = chunkcoordintpair.getMinBlockX(); -@@ -677,10 +682,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - ProfilerFiller gameprofilerfiller = this.getProfiler(); - - gameprofilerfiller.push("thunder"); -- BlockPos blockposition; -+ final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change - - if (!this.paperConfig.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder -- blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); -+ blockposition.setValues(this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper - if (this.isRainingAt(blockposition)) { - DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); - boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance; // Paper -@@ -703,59 +708,77 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - gameprofilerfiller.popPush("iceandsnow"); -- if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow -- blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.getBlockRandomPos(j, 0, k, 15)); -- BlockPos blockposition1 = blockposition.below(); -+ if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking -+ // Paper start - optimise chunk ticking -+ this.getRandomBlockPosition(j, 0, k, 15, blockposition); -+ int normalY = chunk.getHighestBlockY(Heightmap.Types.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15); -+ int downY = normalY - 1; -+ blockposition.setY(normalY); -+ // Paper end - Biome biomebase = this.getBiome(blockposition); - -- if (biomebase.shouldFreeze(this, blockposition1)) { -- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.defaultBlockState(), null); // CraftBukkit -+ // Paper start - optimise chunk ticking -+ blockposition.setY(downY); -+ if (biomebase.shouldFreeze(this, blockposition)) { -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.ICE.defaultBlockState(), null); // CraftBukkit -+ // Paper end - } - -+ blockposition.setY(normalY); // Paper - if (flag && biomebase.shouldSnow(this, blockposition)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit - } - -- if (flag && this.getBiome(blockposition1).getPrecipitation() == Biome.Precipitation.RAIN) { -- this.getBlockState(blockposition1).getBlock().handleRain((net.minecraft.world.level.Level) this, blockposition1); -+ // Paper start - optimise chunk ticking -+ blockposition.setY(downY); -+ if (flag && this.getBiome(blockposition).getPrecipitation() == Biome.Precipitation.RAIN) { -+ chunk.getBlockState(blockposition).getBlock().handleRain((net.minecraft.world.level.Level) this, blockposition); -+ // Paper end - } - } - -- gameprofilerfiller.popPush("tickBlocks"); -- timings.chunkTicksBlocks.startTiming(); // Paper -+ // Paper start - optimise random block ticking -+ gameprofilerfiller.pop(); - if (randomTickSpeed > 0) { -- LevelChunkSection[] achunksection = chunk.getSections(); -- int l = achunksection.length; -+ gameprofilerfiller.push("randomTick"); -+ timings.chunkTicksBlocks.startTiming(); // Paper - -- for (int i1 = 0; i1 < l; ++i1) { -- LevelChunkSection chunksection = achunksection[i1]; -+ LevelChunkSection[] sections = chunk.getSections(); - -- if (chunksection != LevelChunk.EMPTY_SECTION && chunksection.isRandomlyTicking()) { -- int j1 = chunksection.bottomBlockY(); -+ for (int sectionIndex = 0; sectionIndex < 16; ++sectionIndex) { -+ LevelChunkSection section = sections[sectionIndex]; -+ if (section == null || section.tickingList.size() == 0) { -+ continue; -+ } - -- for (int k1 = 0; k1 < randomTickSpeed; ++k1) { -- BlockPos blockposition2 = this.getBlockRandomPos(j, j1, k, 15); -+ int yPos = sectionIndex << 4; - -- gameprofilerfiller.push("randomTick"); -- BlockState iblockdata = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); -+ for (int a = 0; a < randomTickSpeed1; ++a) { -+ int tickingBlocks = section.tickingList.size(); -+ int index = this.randomTickRandom.nextInt(16 * 16 * 16); -+ if (index >= tickingBlocks) { -+ continue; -+ } - -- if (iblockdata.isRandomlyTicking()) { -- iblockdata.randomTick(this, blockposition2, this.random); -- } -+ long raw = section.tickingList.getRaw(index); -+ int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); -+ int randomX = location & 15; -+ int randomY = ((location >>> (4 + 4)) & 255) | yPos; -+ int randomZ = (location >>> 4) & 15; - -- FluidState fluid = iblockdata.getFluidState(); -+ BlockPos blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ); -+ BlockState iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); - -- if (fluid.isRandomlyTicking()) { -- fluid.randomTick(this, blockposition2, this.random); -- } -+ iblockdata.randomTick(this, blockposition2, this.randomTickRandom); - -- gameprofilerfiller.pop(); -- } -+ // We drop the fluid tick since LAVA is ALREADY TICKED by the above method. -+ // TODO CHECK ON UPDATE - } - } -+ gameprofilerfiller.pop(); -+ timings.chunkTicksBlocks.stopTiming(); // Paper -+ // Paper end - } -- timings.chunkTicksBlocks.stopTiming(); // Paper -- gameprofilerfiller.pop(); - } - - protected BlockPos findLightingTargetAround(BlockPos pos) { -diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java -index dd84984f28484cf7129c294222696784e128221a..9ea72751354e893cd3820befaa5df3e5e503de6e 100644 ---- a/src/main/java/net/minecraft/util/BitStorage.java -+++ b/src/main/java/net/minecraft/util/BitStorage.java -@@ -112,4 +112,32 @@ public class BitStorage { - } - - } -+ -+ // Paper start -+ public final void forEach(DataBitConsumer consumer) { -+ int i = 0; -+ long[] along = this.data; -+ int j = along.length; -+ -+ for (int k = 0; k < j; ++k) { -+ long l = along[k]; -+ -+ for (int i1 = 0; i1 < this.valuesPerLong; ++i1) { -+ consumer.accept(i, (int) (l & this.mask)); -+ l >>= this.bits; -+ ++i; -+ if (i >= this.size) { -+ return; -+ } -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface DataBitConsumer { -+ -+ void accept(int location, int data); -+ -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index 42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3..0e15ca2fb9cd1aeb4a075b8d50350dd7fd463c72 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -@@ -91,7 +91,7 @@ public class Turtle extends Animal { - } - - public void setHomePos(BlockPos pos) { -- this.entityData.set(Turtle.HOME_POS, pos); -+ this.entityData.set(Turtle.HOME_POS, pos.immutable()); // Paper - called with mutablepos... - } - - public BlockPos getHomePos() { // Paper - public -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 1d536d77518a70bdc1a23924aea99df1042b3cd5..632f32405053fbcff2fd26fa99f98c6add9f9dc7 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1472,10 +1472,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public abstract TagContainer getTagManager(); - - public BlockPos getBlockRandomPos(int x, int y, int z, int l) { -+ // Paper start - allow use of mutable pos -+ BlockPos.MutableBlockPos ret = new BlockPos.MutableBlockPos(); -+ this.getRandomBlockPosition(x, y, z, l, ret); -+ return ret.immutable(); -+ } -+ public final BlockPos.MutableBlockPos getRandomBlockPosition(int i, int j, int k, int l, BlockPos.MutableBlockPos out) { -+ // Paper end - this.randValue = this.randValue * 3 + 1013904223; - int i1 = this.randValue >> 2; - -- return new BlockPos(x + (i1 & 15), y + (i1 >> 16 & l), z + (i1 >> 8 & 15)); -+ out.setValues(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); // Paper - change to setValues call -+ return out; // Paper - } - - public boolean noSave() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 4fef3abe4b416cbebe1b456468b5c3e162de18f1..87d7a87a2925f2c062658e960bb5128738828d9f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -639,8 +639,8 @@ public class LevelChunk implements ChunkAccess { - this.entities.remove(entity); // Paper - } - -- @Override -- public int getHeight(Heightmap.Types type, int x, int z) { -+ public final int getHighestBlockY(Heightmap.Types heightmap_type, int i, int j) { return this.getHeight(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1 -+ @Override public int getHeight(Heightmap.Types type, int x, int z) { // Paper - return ((Heightmap) this.heightmaps.get(type)).getFirstAvailable(x & 15, z & 15) - 1; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a71ad031d9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -14,12 +14,14 @@ import net.minecraft.world.level.material.FluidState; - public class LevelChunkSection { - - public static final Palette GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState()); -- private final int bottomBlockY; -+ final int bottomBlockY; // Paper - private -> package-private - short nonEmptyBlockCount; // Paper - package-private -- private short tickingBlockCount; -+ short tickingBlockCount; // Paper - private -> package-private - private short tickingFluidCount; - final PalettedContainer states; // Paper - package-private - -+ public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper -+ - // Paper start - Anti-Xray - Add parameters - @Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere - public LevelChunkSection(int i, ChunkAccess chunk, Level world, boolean initializeBlocks) { -@@ -74,6 +76,9 @@ public class LevelChunkSection { - --this.nonEmptyBlockCount; - if (iblockdata1.isRandomlyTicking()) { - --this.tickingBlockCount; -+ // Paper start -+ this.tickingList.remove(x, y, z); -+ // Paper end - } - } - -@@ -85,6 +90,9 @@ public class LevelChunkSection { - ++this.nonEmptyBlockCount; - if (state.isRandomlyTicking()) { - ++this.tickingBlockCount; -+ // Paper start -+ this.tickingList.add(x, y, z, state); -+ // Paper end - } - } - -@@ -120,23 +128,29 @@ public class LevelChunkSection { - } - - public void recalcBlockCounts() { -+ // Paper start -+ this.tickingList.clear(); -+ // Paper end - this.nonEmptyBlockCount = 0; - this.tickingBlockCount = 0; - this.tickingFluidCount = 0; -- this.states.count((iblockdata, i) -> { -+ this.states.forEachLocation((iblockdata, location) -> { // Paper - FluidState fluid = iblockdata.getFluidState(); - - if (!iblockdata.isAir()) { -- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); - if (iblockdata.isRandomlyTicking()) { -- this.tickingBlockCount = (short) (this.tickingBlockCount + i); -+ this.tickingBlockCount = (short) (this.tickingBlockCount + 1); -+ // Paper start -+ this.tickingList.add(location, iblockdata); -+ // Paper end - } - } - - if (!fluid.isEmpty()) { -- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); - if (fluid.isRandomlyTicking()) { -- this.tickingFluidCount = (short) (this.tickingFluidCount + i); -+ this.tickingFluidCount = (short) (this.tickingFluidCount + 1); - } - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index dd252372e1e380674b1191e9ea265cbb10de437b..f93316b3ae5cd5fb960fa24f8c921b5b9276d9f3 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -285,6 +285,14 @@ public class PalettedContainer implements PaletteResize { - }); - } - -+ // Paper start -+ public void forEachLocation(PalettedContainer.CountConsumer datapaletteblock_a) { -+ this.getDataBits().forEach((int location, int data) -> { -+ datapaletteblock_a.accept(this.getDataPalette().getObject(data), location); -+ }); -+ } -+ // Paper end -+ - @FunctionalInterface - public interface CountConsumer { - diff --git a/Remapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch b/Remapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch deleted file mode 100644 index 15c22b27a5..0000000000 --- a/Remapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 8 Feb 2020 23:26:11 -0600 -Subject: [PATCH] Entity Jump API - - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index b84dab1043c56e2deb58aec8639226f98db165d1..43fbe7d220f61802ae0cb0620ad078c5df7b69bc 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2873,8 +2873,10 @@ public abstract class LivingEntity extends Entity { - } else if (this.isInLava() && (!this.onGround || d7 > d8)) { - this.jumpInLiquid((Tag) FluidTags.LAVA); - } else if ((this.onGround || flag && d7 <= d8) && this.noJumpDelay == 0) { -+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - this.jumpFromGround(); - this.noJumpDelay = 10; -+ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop - } - } else { - this.noJumpDelay = 0; -diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java -index 1621d8748e96c6e1abb33b699a1273bb698f67d2..423bdbe25b6f2261cb5092378b0564a82faeecb4 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Panda.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java -@@ -489,7 +489,9 @@ public class Panda extends Animal { - Panda entitypanda = (Panda) iterator.next(); - - if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.canPerformAction()) { -+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - entitypanda.jumpFromGround(); -+ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop - } - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index a01bd035846df0e2e28dc55e2ef2f5f35b83f905..5dac3bf5a117bfbf57798238f0614558deafcd1b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -792,5 +792,19 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public org.bukkit.inventory.EquipmentSlot getHandRaised() { - return getHandle().getUsedItemHand() == net.minecraft.world.InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; - } -+ -+ @Override -+ public boolean isJumping() { -+ return getHandle().jumping; -+ } -+ -+ @Override -+ public void setJumping(boolean jumping) { -+ getHandle().setJumping(jumping); -+ if (jumping && getHandle() instanceof Mob) { -+ // this is needed to actually make a mob jump -+ ((Mob) getHandle()).getJumpControl().jump(); -+ } -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch b/Remapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch deleted file mode 100644 index d66918d012..0000000000 --- a/Remapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 7 Feb 2020 14:36:56 -0600 -Subject: [PATCH] Add option to nerf pigmen from nether portals - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7fbd501d70dccf869a4454e2789a5d68f2e15754..9e4591ddc4b755f4ff5a6f1078b51cb13db80480 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -594,4 +594,9 @@ public class PaperWorldConfig { - disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); - log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); - } -+ -+ public boolean nerfNetherPortalPigmen = false; -+ private void nerfNetherPortalPigmen() { -+ nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index efc9cb6def2f4ee327329dc090d2918ff60d8e19..43f77d01fceab107d3502d282205aa579d64cc4b 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -277,6 +277,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public long activatedTick = Integer.MIN_VALUE; - public boolean isTemporarilyActive = false; // Paper - public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one -+ public boolean fromNetherPortal; // Paper - protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end -@@ -1693,6 +1694,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - if (spawnedViaMobSpawner) { - tag.putBoolean("Paper.FromMobSpawner", true); - } -+ if (fromNetherPortal) { -+ tag.putBoolean("Paper.FromNetherPortal", true); -+ } - // Paper end - return tag; - } catch (Throwable throwable) { -@@ -1827,6 +1831,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ fromNetherPortal = tag.getBoolean("Paper.FromNetherPortal"); - if (tag.contains("Paper.SpawnReason")) { - String spawnReasonName = tag.getString("Paper.SpawnReason"); - try { -diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -index 805d83a93bce20910d17c3f419bc085251b6cfc1..ae58929886921d0714bf811de92f99dc0dc120dc 100644 ---- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -@@ -8,6 +8,7 @@ import net.minecraft.network.chat.Component; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.entity.Mob; - import net.minecraft.world.entity.MobSpawnType; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.level.BlockGetter; -@@ -61,6 +62,8 @@ public class NetherPortalBlock extends Block { - - if (entity != null) { - entity.setPortalCooldown(); -+ entity.fromNetherPortal = true; // Paper -+ if (world.paperConfig.nerfNetherPortalPigmen) ((Mob) entity).aware = false; // Paper - } - } - } diff --git a/Remapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch b/Remapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch deleted file mode 100644 index c98d2918e6..0000000000 --- a/Remapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch +++ /dev/null @@ -1,439 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 2 Feb 2020 04:00:40 -0600 -Subject: [PATCH] Make the GUI graph fancier - - -diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphColor.java b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a4e641fdcccd3efcd1a2865dc6dc28d50671b995 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java -@@ -0,0 +1,44 @@ -+package com.destroystokyo.paper.gui; -+ -+import java.awt.Color; -+ -+public class GraphColor { -+ private static final Color[] colorLine = new Color[101]; -+ private static final Color[] colorFill = new Color[101]; -+ -+ static { -+ for (int i = 0; i < 101; i++) { -+ Color color = createColor(i); -+ colorLine[i] = new Color(color.getRed() / 2, color.getGreen() / 2, color.getBlue() / 2, 255); -+ colorFill[i] = new Color(colorLine[i].getRed(), colorLine[i].getGreen(), colorLine[i].getBlue(), 125); -+ } -+ } -+ -+ public static Color getLineColor(int percent) { -+ return colorLine[percent]; -+ } -+ -+ public static Color getFillColor(int percent) { -+ return colorFill[percent]; -+ } -+ -+ private static Color createColor(int percent) { -+ if (percent <= 50) { -+ return new Color(0X00FF00); -+ } -+ -+ int value = 510 - (int) (Math.min(Math.max(0, ((percent - 50) / 50F)), 1) * 510); -+ -+ int red, green; -+ if (value < 255) { -+ red = 255; -+ green = (int) (Math.sqrt(value) * 16); -+ } else { -+ green = 255; -+ value = value - 255; -+ red = 255 - (value * value / 255); -+ } -+ -+ return new Color(red, green, 0); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphData.java b/src/main/java/com/destroystokyo/paper/gui/GraphData.java -new file mode 100644 -index 0000000000000000000000000000000000000000..186fc722965e403f76b1480e1c2381fc34e29049 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/GraphData.java -@@ -0,0 +1,47 @@ -+package com.destroystokyo.paper.gui; -+ -+import java.awt.Color; -+ -+public class GraphData { -+ private long total; -+ private long free; -+ private long max; -+ private long usedMem; -+ private int usedPercent; -+ -+ public GraphData(long total, long free, long max) { -+ this.total = total; -+ this.free = free; -+ this.max = max; -+ this.usedMem = total - free; -+ this.usedPercent = usedMem == 0 ? 0 : (int) (usedMem * 100L / max); -+ } -+ -+ public long getTotal() { -+ return total; -+ } -+ -+ public long getFree() { -+ return free; -+ } -+ -+ public long getMax() { -+ return max; -+ } -+ -+ public long getUsedMem() { -+ return usedMem; -+ } -+ -+ public int getUsedPercent() { -+ return usedPercent; -+ } -+ -+ public Color getFillColor() { -+ return GraphColor.getFillColor(usedPercent); -+ } -+ -+ public Color getLineColor() { -+ return GraphColor.getLineColor(usedPercent); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0f29ad583e798c09b2fe3f568ed50cbc719e40e2 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.gui; -+ -+import net.minecraft.server.MinecraftServer; -+ -+import javax.swing.JPanel; -+import javax.swing.Timer; -+import java.awt.BorderLayout; -+import java.awt.Dimension; -+ -+public class GuiStatsComponent extends JPanel { -+ private final Timer timer; -+ private final RAMGraph ramGraph; -+ -+ public GuiStatsComponent(MinecraftServer server) { -+ super(new BorderLayout()); -+ -+ setOpaque(false); -+ -+ ramGraph = new RAMGraph(); -+ RAMDetails ramDetails = new RAMDetails(server); -+ -+ add(ramGraph, "North"); -+ add(ramDetails, "Center"); -+ -+ timer = new Timer(500, (event) -> { -+ ramGraph.update(); -+ ramDetails.update(); -+ }); -+ timer.start(); -+ } -+ -+ @Override -+ public Dimension getPreferredSize() { -+ return new Dimension(350, 200); -+ } -+ -+ public void stop() { a(); } public void a() { -+ timer.stop(); -+ ramGraph.stop(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c0923ec75ecced2e0a1c0d3ec2c046d69af3e9a9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -@@ -0,0 +1,73 @@ -+package com.destroystokyo.paper.gui; -+ -+import net.minecraft.Util; -+import net.minecraft.server.MinecraftServer; -+ -+import javax.swing.DefaultListCellRenderer; -+import javax.swing.DefaultListSelectionModel; -+import javax.swing.JList; -+import javax.swing.border.EmptyBorder; -+import java.awt.Dimension; -+import java.text.DecimalFormat; -+import java.text.DecimalFormatSymbols; -+import java.util.Locale; -+import java.util.Vector; -+ -+public class RAMDetails extends JList { -+ public static final DecimalFormat DECIMAL_FORMAT = Util.peek(new DecimalFormat("########0.000"), (format) -+ -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT))); -+ -+ private final MinecraftServer server; -+ -+ public RAMDetails(MinecraftServer server) { -+ this.server = server; -+ -+ setBorder(new EmptyBorder(0, 10, 0, 0)); -+ setFixedCellHeight(20); -+ setOpaque(false); -+ -+ DefaultListCellRenderer renderer = new DefaultListCellRenderer(); -+ renderer.setOpaque(false); -+ setCellRenderer(renderer); -+ -+ setSelectionModel(new DefaultListSelectionModel() { -+ @Override -+ public void setAnchorSelectionIndex(final int anchorIndex) { -+ } -+ -+ @Override -+ public void setLeadAnchorNotificationEnabled(final boolean flag) { -+ } -+ -+ @Override -+ public void setLeadSelectionIndex(final int leadIndex) { -+ } -+ -+ @Override -+ public void setSelectionInterval(final int index0, final int index1) { -+ } -+ }); -+ } -+ -+ @Override -+ public Dimension getPreferredSize() { -+ return new Dimension(350, 100); -+ } -+ -+ public void update() { -+ GraphData data = RAMGraph.DATA.peekLast(); -+ Vector vector = new Vector<>(); -+ vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); -+ vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); -+ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); -+ setListData(vector); -+ } -+ -+ public double getAverage(long[] tickTimes) { -+ long total = 0L; -+ for (long value : tickTimes) { -+ total += value; -+ } -+ return ((double) total / (double) tickTimes.length) * 1.0E-6D; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c3e54da4ab6440811aab2f9dd1e218802ac13285 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java -@@ -0,0 +1,144 @@ -+package com.destroystokyo.paper.gui; -+ -+import javax.swing.JComponent; -+import javax.swing.SwingUtilities; -+import javax.swing.Timer; -+import javax.swing.ToolTipManager; -+import java.awt.Color; -+import java.awt.Dimension; -+import java.awt.Graphics; -+import java.awt.MouseInfo; -+import java.awt.Point; -+import java.awt.PointerInfo; -+import java.awt.event.MouseAdapter; -+import java.awt.event.MouseEvent; -+import java.text.SimpleDateFormat; -+import java.util.Date; -+import java.util.LinkedList; -+import java.util.concurrent.TimeUnit; -+ -+public class RAMGraph extends JComponent { -+ public static final LinkedList DATA = new LinkedList() { -+ @Override -+ public boolean add(GraphData data) { -+ if (size() >= 348) { -+ remove(); -+ } -+ return super.add(data); -+ } -+ }; -+ -+ static { -+ GraphData empty = new GraphData(0, 0, 0); -+ for (int i = 0; i < 350; i++) { -+ DATA.add(empty); -+ } -+ } -+ -+ private final Timer timer; -+ private final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); -+ -+ private int currentTick; -+ -+ public RAMGraph() { -+ ToolTipManager.sharedInstance().setInitialDelay(0); -+ -+ addMouseListener(new MouseAdapter() { -+ final int defaultDismissTimeout = ToolTipManager.sharedInstance().getDismissDelay(); -+ final int dismissDelayMinutes = (int) TimeUnit.MINUTES.toMillis(10); -+ -+ @Override -+ public void mouseEntered(MouseEvent me) { -+ ToolTipManager.sharedInstance().setDismissDelay(dismissDelayMinutes); -+ } -+ -+ @Override -+ public void mouseExited(MouseEvent me) { -+ ToolTipManager.sharedInstance().setDismissDelay(defaultDismissTimeout); -+ } -+ }); -+ -+ timer = new Timer(50, (event) -> repaint()); -+ timer.start(); -+ } -+ -+ @Override -+ public Dimension getPreferredSize() { -+ return new Dimension(350, 110); -+ } -+ -+ public void update() { -+ Runtime jvm = Runtime.getRuntime(); -+ DATA.add(new GraphData(jvm.totalMemory(), jvm.freeMemory(), jvm.maxMemory())); -+ -+ PointerInfo pointerInfo = MouseInfo.getPointerInfo(); -+ if (pointerInfo != null) { -+ Point point = pointerInfo.getLocation(); -+ if (point != null) { -+ Point loc = new Point(point); -+ SwingUtilities.convertPointFromScreen(loc, this); -+ if (this.contains(loc)) { -+ ToolTipManager.sharedInstance().mouseMoved( -+ new MouseEvent(this, -1, System.currentTimeMillis(), 0, loc.x, loc.y, -+ point.x, point.y, 0, false, 0)); -+ } -+ } -+ } -+ -+ currentTick++; -+ } -+ -+ @Override -+ public void paint(Graphics graphics) { -+ graphics.setColor(new Color(0xFFFFFFFF)); -+ graphics.fillRect(0, 0, 350, 100); -+ -+ graphics.setColor(new Color(0x888888)); -+ graphics.drawLine(1, 25, 348, 25); -+ graphics.drawLine(1, 50, 348, 50); -+ graphics.drawLine(1, 75, 348, 75); -+ -+ int i = 0; -+ for (GraphData data : DATA) { -+ i++; -+ if ((i + currentTick) % 120 == 0) { -+ graphics.setColor(new Color(0x888888)); -+ graphics.drawLine(i, 1, i, 99); -+ } -+ int used = data.getUsedPercent(); -+ if (used > 0) { -+ Color color = data.getLineColor(); -+ graphics.setColor(data.getFillColor()); -+ graphics.fillRect(i, 100 - used, 1, used); -+ graphics.setColor(color); -+ graphics.fillRect(i, 100 - used, 1, 1); -+ } -+ } -+ -+ graphics.setColor(new Color(0xFF000000)); -+ graphics.drawRect(0, 0, 348, 100); -+ -+ Point m = getMousePosition(); -+ if (m != null && m.x > 0 && m.x < 348 && m.y > 0 && m.y < 100) { -+ GraphData data = DATA.get(m.x); -+ int used = data.getUsedPercent(); -+ graphics.setColor(new Color(0x000000)); -+ graphics.drawLine(m.x, 1, m.x, 99); -+ graphics.drawOval(m.x - 2, 100 - used - 2, 5, 5); -+ graphics.setColor(data.getLineColor()); -+ graphics.fillOval(m.x - 2, 100 - used - 2, 5, 5); -+ setToolTipText(String.format("Used: %s mb (%s%%)
    %s", -+ Math.round(data.getUsedMem() / 1024F / 1024F), -+ used, getTime(m.x))); -+ } -+ } -+ -+ public String getTime(int halfSeconds) { -+ int millis = (348 - halfSeconds) / 2 * 1000; -+ return TIME_FORMAT.format(new Date((System.currentTimeMillis() - millis))); -+ } -+ -+ public void stop() { -+ timer.stop(); -+ } -+} -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index cec5ad5052c8cf6059e9b117117846bdb217748f..c2f747226f10479c826849af898538610a2dd659 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -259,6 +259,7 @@ public class Util { - return factory.get(); - } - -+ public static T peek(T t0, Consumer consumer) { return make(t0, consumer); } // Paper - OBFHELPER - public static T make(T object, Consumer initializer) { - initializer.accept(object); - return object; -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 7038897b8fb4c18ca97b95a3b24c30b40b62b005..e33189dc8375a3034910087654607fb531061636 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -216,7 +216,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -+ private static final DecimalFormat DECIMAL_FORMAT = (DecimalFormat) Util.make(new DecimalFormat("########0.000"), (decimalformat) -> { // Paper - decompile error - decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); - }); - private final int[] values = new int[256]; diff --git a/Remapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch b/Remapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch deleted file mode 100644 index e93352bf03..0000000000 --- a/Remapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sun, 1 Mar 2020 22:43:24 +0100 -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 e696d2e52532df25d74a1f559e2c9ca0f3d5058d..7d9a3b65b2d6b294d3a11414289e64fac88665f0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -337,13 +337,18 @@ public class CraftEventFactory { - } - - org.bukkit.inventory.ItemStack item; -+ //Paper start - add hand to BlockMultiPlaceEvent -+ EquipmentSlot equipmentSlot; - if (hand == InteractionHand.MAIN_HAND) { - item = player.getInventory().getItemInMainHand(); -+ equipmentSlot = EquipmentSlot.HAND; - } else { - item = player.getInventory().getItemInOffHand(); -+ equipmentSlot = EquipmentSlot.OFF_HAND; - } - -- BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild); -+ BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild, equipmentSlot); -+ //Paper end - craftServer.getPluginManager().callEvent(event); - - return event; diff --git a/Remapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch b/Remapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch deleted file mode 100644 index ef6164bd27..0000000000 --- a/Remapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 3 Mar 2020 05:26:40 +0000 -Subject: [PATCH] Prevent teleporting dead entities - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 2b79413bb8a592a7b7093e11d3a0cce895286c8f..09a663cc53cdf8ae45352b280200c8170dbbcdfc 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1468,6 +1468,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } - - private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { -+ if (player.removed) { -+ LOGGER.info("Attempt to teleport dead player {} restricted", player.getScoreboardName()); -+ return; -+ } - // CraftBukkit start - if (Float.isNaN(f)) { - f = 0; diff --git a/Remapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch b/Remapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch deleted file mode 100644 index 8fbefb7aec..0000000000 --- a/Remapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 7 Mar 2020 00:07:51 +0000 -Subject: [PATCH] Validate tripwire hook placement before update - - -diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java -index f44d4809fe87c832e4d3bda429af2254e8c746d6..20428aff54527b664d988a6a0f54236b693fda89 100644 ---- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java -@@ -169,6 +169,7 @@ public class TripWireHookBlock extends Block { - - this.playSound(world, pos, flag4, flag5, flag2, flag3); - if (!beingRemoved) { -+ if (world.getBlockState(pos).getBlock() == Blocks.TRIPWIRE_HOOK) // Paper - validate - world.setBlock(pos, (BlockState) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection), 3); - if (flag1) { - this.notifyNeighbors(world, pos, enumdirection); diff --git a/Remapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/Remapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch deleted file mode 100644 index 163f5b9240..0000000000 --- a/Remapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 13 Apr 2019 16:50:58 -0500 -Subject: [PATCH] Add option to allow iron golems to spawn in air - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9e4591ddc4b755f4ff5a6f1078b51cb13db80480..fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -387,6 +387,11 @@ public class PaperWorldConfig { - scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); - } - -+ public boolean ironGolemsCanSpawnInAir = false; -+ private void ironGolemsCanSpawnInAir() { -+ ironGolemsCanSpawnInAir = getBoolean("iron-golems-can-spawn-in-air", ironGolemsCanSpawnInAir); -+ } -+ - public boolean armorStandEntityLookups = true; - private void armorStandEntityLookups() { - armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); -diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -index 9cedac83304847bdc92c2e97c4e6e119664c3bd0..59f0224b6a743408a03b642dd7cbe545f406c57e 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -+++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -@@ -297,7 +297,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { - BlockPos blockposition1 = blockposition.below(); - BlockState iblockdata = world.getBlockState(blockposition1); - -- if (!iblockdata.entityCanStandOn((BlockGetter) world, blockposition1, (Entity) this)) { -+ if (!iblockdata.entityCanStandOn((BlockGetter) world, blockposition1, (Entity) this) && !level.paperConfig.ironGolemsCanSpawnInAir) { // Paper - return false; - } else { - for (int i = 1; i < 3; ++i) { diff --git a/Remapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch b/Remapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch deleted file mode 100644 index 1bf93843e4..0000000000 --- a/Remapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zero -Date: Sat, 22 Feb 2020 16:10:31 -0500 -Subject: [PATCH] Configurable chance of villager zombie infection - -This allows you to solve an issue in vanilla behavior where: -* On easy difficulty your villagers will NEVER get infected, meaning they will always die. -* On normal difficulty they will have a 50% of getting infected or dying. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f..525d702d78a609af987ebd2c32169b873e5c05ed 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -604,4 +604,9 @@ public class PaperWorldConfig { - private void nerfNetherPortalPigmen() { - nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); - } -+ -+ public double zombieVillagerInfectionChance = -1.0; -+ private void zombieVillagerInfectionChance() { -+ zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 6fecf4188fc0247143edc688c03e645376960687..1e7c2c603b967c8c606efd94ce95a17c856f78d7 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -447,10 +447,14 @@ public class Zombie extends Monster { - @Override - public void killed(ServerLevel worldserver, LivingEntity entityliving) { - super.killed(worldserver, entityliving); -- if ((worldserver.getDifficulty() == Difficulty.NORMAL || worldserver.getDifficulty() == Difficulty.HARD) && entityliving instanceof Villager) { -- if (worldserver.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { -+ // Paper start -+ if (level.paperConfig.zombieVillagerInfectionChance != 0.0 && (level.paperConfig.zombieVillagerInfectionChance != -1.0 || worldserver.getDifficulty() == Difficulty.NORMAL || worldserver.getDifficulty() == Difficulty.HARD) && entityliving instanceof Villager) { -+ if (level.paperConfig.zombieVillagerInfectionChance == -1.0 && worldserver.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { - return; - } -+ if (level.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > level.paperConfig.zombieVillagerInfectionChance) { -+ return; -+ } // Paper end - - Villager entityvillager = (Villager) entityliving; - // CraftBukkit start diff --git a/Remapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch b/Remapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch deleted file mode 100644 index 2ba043c076..0000000000 --- a/Remapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 14 Jan 2020 14:59:08 -0800 -Subject: [PATCH] Optimise Chunk#getFluid - -Removing the try catch and generally reducing ops should make it -faster on its own, however removing the try catch makes it -easier to inline due to code size - -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 87d7a87a2925f2c062658e960bb5128738828d9f..8a14bdda4a408ec1e2b51efeb35467835f62b42c 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -430,25 +430,29 @@ public class LevelChunk implements ChunkAccess { - } - - public FluidState getFluidState(int x, int y, int z) { -- try { -- if (y >= 0 && y >> 4 < this.sections.length) { -- LevelChunkSection chunksection = this.sections[y >> 4]; -- -- if (!LevelChunkSection.isEmpty(chunksection)) { -- return chunksection.getFluidState(x & 15, y & 15, z & 15); -+ //try { // Paper - remove try catch -+ // Paper start - reduce the number of ops in this call -+ int index = y >> 4; -+ if (index >= 0 && index < this.sections.length) { -+ LevelChunkSection chunksection = this.sections[index]; -+ -+ if (chunksection != null) { -+ return chunksection.states.get((y & 15) << 8 | (z & 15) << 4 | x & 15).getFluidState(); - } -+ // Paper end - } - - return Fluids.EMPTY.defaultFluidState(); -- } catch (Throwable throwable) { -- CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state"); -- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got"); -+ /*} catch (Throwable throwable) { // Paper - remove try catch -+ CrashReport crashreport = CrashReport.a(throwable, "Getting fluid state"); -+ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being got"); - -- crashreportsystemdetails.setDetail("Location", () -> { -- return CrashReportCategory.formatLocation(x, y, z); -+ crashreportsystemdetails.a("Location", () -> { -+ return CrashReportSystemDetails.a(i, j, k); - }); - throw new ReportedException(crashreport); - } -+ */ // Paper - remove try catch - } - - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index c44d32f966c61497b4a8892eb51da3a71ad031d9..5e7f6000df129100ef306703f325af9f60da8ae6 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -45,7 +45,7 @@ public class LevelChunkSection { - } - - public FluidState getFluidState(int x, int y, int z) { -- return ((BlockState) this.states.get(x, y, z)).getFluidState(); -+ return ((BlockState) this.states.get(x, y, z)).getFluidState(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid. - } - - public void acquire() { diff --git a/Remapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch b/Remapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch deleted file mode 100644 index 6cf945010b..0000000000 --- a/Remapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch +++ /dev/null @@ -1,1301 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 14 Feb 2020 01:24:39 -0800 -Subject: [PATCH] Optimise TickListServer by rewriting it - -In my profiling TickListServer showed up as -~10% for saving chunks and ~5% for the scheduling -of items on a server with ~90 players at -view distance = 5. Most of the performance -loss is unneccessary. - -TickListServer has numerous performance issues: - 1. Handling scheduled items is O(nlogn) - 2. Getting scheduled items for a chunk is O(n), - with n being the the number of scheduled items - for all chunks (hits saving very hard) - 3. Checking if an item is scheduled for the current tick is O(n), - with n being the number of items scheduled for current tick - 4. Items not in ticking chunks are churned in the scheduler - -The biggest issues are 4 & 2. - -We solve 1 by splitting up scheduled items into short and long scheduled, -where we expect the vast majority of our entries to be in the short scheduled -set. Handling short scheduled items is O(n) due to how the comparison -process is reduced to mapping. See TickListServerInterval. However, -this isn't memory-efficient - which is why long scheduled exists. -Long scheduled is handled the same as TickListServer. - -2 is solved by mapping what entries are in what chunks. - -3 is solved by mapping what blocks have what scheduled for them. - -4 is solved by moving the items that are not in ticking chunks -into a map of entries for that chunk. Once the chunk is moved -to ticking, the items are re-scheduled. - -This patch has also added two flags to debug excessive tick delays: --Dpaper.ticklist-warn-on-excessive-delay=true (false by default) -and -Dpaper.ticklist-excessive-delay-threshold=ticks which -sets the excessive tick delay to the specified ticks (defaults to -60 * 20 ticks, aka 60 seconds) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 8bf4d2b8c38c02d6a5b2fea37113689a252f1571..da93d38fe63035e4ff198ada84a4431f52d97c01 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -354,6 +354,13 @@ public class PaperConfig { - maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); - } - -+ public static boolean useOptimizedTickList = true; -+ private static void useOptimizedTickList() { -+ if (config.contains("settings.use-optimized-ticklist")) { // don't add default, hopefully temporary config -+ useOptimizedTickList = config.getBoolean("settings.use-optimized-ticklist"); -+ } -+ } -+ - public static boolean asyncChunks = false; - private static void asyncChunks() { - ConfigurationSection section; -diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2d579909b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java -@@ -0,0 +1,628 @@ -+package com.destroystokyo.paper.server.ticklist; -+ -+import java.util.function.Function; -+import net.minecraft.CrashReport; -+import net.minecraft.CrashReportCategory; -+import net.minecraft.ReportedException; -+import net.minecraft.core.BlockPos; -+import net.minecraft.nbt.ListTag; -+import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ServerChunkCache; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.world.level.ChunkPos; -+import net.minecraft.world.level.ServerTickList; -+import net.minecraft.world.level.TickNextTickData; -+import net.minecraft.world.level.TickPriority; -+import net.minecraft.world.level.block.state.BlockState; -+import net.minecraft.world.level.levelgen.structure.BoundingBox; -+import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; -+import java.util.ArrayDeque; -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.Comparator; -+import java.util.Iterator; -+import java.util.List; -+import java.util.function.Consumer; -+import java.util.function.Predicate; -+ -+public final class PaperTickList extends ServerTickList { // extend to avoid breaking ABI -+ -+ // in the order the state is expected to change (mostly) -+ public static final int STATE_UNSCHEDULED = 1 << 0; -+ public static final int STATE_SCHEDULED = 1 << 1; // scheduled for some tick -+ public static final int STATE_PENDING_TICK = 1 << 2; // for this tick -+ public static final int STATE_TICKING = 1 << 3; -+ public static final int STATE_TICKED = 1 << 4; // after this, it gets thrown back to unscheduled -+ public static final int STATE_CANCELLED_TICK = 1 << 5; // still gets moved to unscheduled after tick -+ -+ private static final int SHORT_SCHEDULE_TICK_THRESHOLD = 20 * 20 + 1; // 20 seconds -+ -+ private final ServerLevel world; -+ private final Predicate excludeFromScheduling; -+ private final Function getMinecraftKeyFrom; -+ //private final Function getObjectFronMinecraftKey; -+ private final Consumer> tickFunction; -+ -+ private final co.aikar.timings.Timing timingCleanup; // Paper -+ private final co.aikar.timings.Timing timingTicking; // Paper -+ private final co.aikar.timings.Timing timingFinished; -+ -+ // note: remove ops / add ops suck on fastutil, a chained hashtable implementation would work better, but Long... -+ // try to alleviate with a very small load factor -+ private final Long2ObjectOpenHashMap>> entriesByBlock = new Long2ObjectOpenHashMap<>(1024, 0.25f); -+ private final Long2ObjectOpenHashMap>> entriesByChunk = new Long2ObjectOpenHashMap<>(1024, 0.25f); -+ private final Long2ObjectOpenHashMap>> pendingChunkTickLoad = new Long2ObjectOpenHashMap<>(1024, 0.5f); -+ -+ // fastutil has O(1) first/last while TreeMap/TreeSet are log(n) -+ private final ObjectRBTreeSet> longScheduled = new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); -+ -+ private final ArrayDeque> toTickThisTick = new ArrayDeque<>(); -+ -+ private final TickListServerInterval[] shortScheduled = new TickListServerInterval[SHORT_SCHEDULE_TICK_THRESHOLD]; -+ { -+ for (int i = 0, len = this.shortScheduled.length; i < len; ++i) { -+ this.shortScheduled[i] = new TickListServerInterval<>(); -+ } -+ } -+ private int shortScheduledIndex; -+ -+ private long currentTick; -+ -+ private static final boolean WARN_ON_EXCESSIVE_DELAY = Boolean.getBoolean("paper.ticklist-warn-on-excessive-delay"); -+ private static final long EXCESSIVE_DELAY_THRESHOLD = Long.getLong("paper.ticklist-excessive-delay-threshold", 60 * 20).longValue(); // 1 min dfl -+ -+ // assume index < length -+ private static int getWrappedIndex(final int start, final int length, final int index) { -+ final int next = start + index; -+ return next < length ? next : next - length; -+ } -+ -+ private static int getNextIndex(final int curr, final int length) { -+ final int next = curr + 1; -+ return next < length ? next : 0; -+ } -+ -+ public PaperTickList(final ServerLevel world, final Predicate excludeFromScheduling, final Function getMinecraftKeyFrom, -+ final Consumer> tickFunction, final String timingsType) { -+ super(world, excludeFromScheduling, getMinecraftKeyFrom, tickFunction, timingsType); -+ this.world = world; -+ this.excludeFromScheduling = excludeFromScheduling; -+ this.getMinecraftKeyFrom = getMinecraftKeyFrom; -+ this.tickFunction = tickFunction; -+ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Cleanup"); // Paper -+ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Ticking"); // Paper -+ this.timingFinished = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Finish"); -+ this.currentTick = this.world.getGameTime(); -+ } -+ -+ private void queueEntryForTick(final TickNextTickData entry, final ServerChunkCache chunkProvider) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ if (chunkProvider.isTickingReadyMainThread(entry.getPosition())) { -+ this.toTickThisTick.add(entry); -+ entry.tickState = STATE_PENDING_TICK; -+ } else { -+ // we dump them to a map to avoid constantly re-scheduling them -+ this.addToNotTickingReady(entry); -+ } -+ } -+ } -+ -+ private void addToNotTickingReady(final TickNextTickData entry) { -+ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (long keyInMap) -> { -+ return new ArrayList<>(); -+ }).add(entry); -+ } -+ -+ private void addToSchedule(final TickNextTickData entry) { -+ long delay = entry.getTargetTick() - (this.currentTick + 1); -+ if (delay < SHORT_SCHEDULE_TICK_THRESHOLD) { -+ if (delay < 0) { -+ // longScheduled orders by tick time, short scheduled does not -+ this.longScheduled.add(entry); -+ } else { -+ this.shortScheduled[getWrappedIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD, (int)delay)].addEntryLast(entry); -+ } -+ } else { -+ this.longScheduled.add(entry); -+ } -+ } -+ -+ private void removeEntry(final TickNextTickData entry) { -+ entry.tickState = STATE_CANCELLED_TICK; -+ // short/long scheduled will skip the entry -+ -+ final BlockPos pos = entry.getPosition(); -+ final long blockKey = MCUtil.getBlockKey(pos); -+ -+ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); -+ -+ if (currentEntries.size() == 1) { -+ // it should contain our entry -+ this.entriesByBlock.remove(blockKey); -+ } else { -+ // it's more likely that this entry is at the start of the list than the end -+ for (int i = 0, len = currentEntries.size(); i < len; ++i) { -+ final TickNextTickData currentEntry = currentEntries.get(i); -+ if (currentEntry == entry) { -+ currentEntries.remove(i); -+ break; -+ } -+ } -+ } -+ -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); -+ -+ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); -+ -+ set.remove(entry); -+ -+ if (set.isEmpty()) { -+ this.entriesByChunk.remove(chunkKey); -+ } -+ -+ ArrayList> pendingTickingLoad = this.pendingChunkTickLoad.get(chunkKey); -+ -+ if (pendingTickingLoad != null) { -+ for (int i = 0, len = pendingTickingLoad.size(); i < len; ++i) { -+ if (pendingTickingLoad.get(i) == entry) { -+ pendingTickingLoad.remove(i); -+ break; -+ } -+ } -+ -+ if (pendingTickingLoad.isEmpty()) { -+ this.pendingChunkTickLoad.remove(chunkKey); -+ } -+ } -+ -+ long delay = entry.getTargetTick() - (this.currentTick + 1); -+ if (delay >= SHORT_SCHEDULE_TICK_THRESHOLD) { -+ this.longScheduled.remove(entry); -+ } -+ } -+ -+ public void onChunkSetTicking(final int chunkX, final int chunkZ) { -+ final ArrayList> pending = this.pendingChunkTickLoad.remove(MCUtil.getCoordinateKey(chunkX, chunkZ)); -+ if (pending == null) { -+ return; -+ } -+ -+ for (int i = 0, size = pending.size(); i < size; ++i) { -+ final TickNextTickData entry = pending.get(i); -+ // already in all the relevant reference maps, just need to add to longScheduled or shortScheduled -+ this.addToSchedule(entry); -+ } -+ } -+ -+ private void prepare() { -+ final long currentTick = this.currentTick; -+ -+ final ServerChunkCache chunkProvider = this.world.getChunkSource(); -+ -+ // here we setup what's going to tick -+ -+ // we don't remove items from shortScheduled (but do from longScheduled) because they're cleared at the end of -+ // this tick -+ if (this.longScheduled.isEmpty() || this.longScheduled.first().getTargetTick() > currentTick) { -+ // nothing in longScheduled to worry about -+ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; -+ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { -+ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { -+ this.queueEntryForTick(iterator.next(), chunkProvider); -+ } -+ } -+ } else { -+ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; -+ -+ // combine interval and longScheduled, keeping order -+ final Comparator> comparator = (Comparator)TickListServerInterval.ENTRY_COMPARATOR; -+ final Iterator> longScheduledIterator = this.longScheduled.iterator(); -+ TickNextTickData longCurrent = longScheduledIterator.next(); -+ -+ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { -+ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { -+ final TickNextTickData shortCurrent = iterator.next(); -+ if (longCurrent != null) { -+ // drain longCurrent until we can add shortCurrent -+ while (comparator.compare(longCurrent, shortCurrent) <= 0) { -+ this.queueEntryForTick(longCurrent, chunkProvider); -+ longScheduledIterator.remove(); -+ if (longScheduledIterator.hasNext()) { -+ longCurrent = longScheduledIterator.next(); -+ if (longCurrent.getTargetTick() > currentTick) { -+ longCurrent = null; -+ break; -+ } -+ } else { -+ longCurrent = null; -+ break; -+ } -+ } -+ } -+ this.queueEntryForTick(shortCurrent, chunkProvider); -+ } -+ } -+ -+ // add remaining from long scheduled -+ for (;;) { -+ if (longCurrent == null || longCurrent.getTargetTick() > currentTick) { -+ break; -+ } -+ longScheduledIterator.remove(); -+ this.queueEntryForTick(longCurrent, chunkProvider); -+ -+ if (longScheduledIterator.hasNext()) { -+ longCurrent = longScheduledIterator.next(); -+ } else { -+ break; -+ } -+ } -+ } -+ } -+ -+ private boolean warnedAboutDesync; -+ -+ @Override -+ public void nextTick() { -+ ++this.currentTick; -+ if (this.currentTick != this.world.getGameTime()) { -+ if (!this.warnedAboutDesync) { -+ this.warnedAboutDesync = true; -+ MinecraftServer.LOGGER.error("World tick desync detected! Expected " + this.currentTick + " ticks, but got " + this.world.getGameTime() + " ticks for world '" + this.world.getWorld().getName() + "'", new Throwable()); -+ MinecraftServer.LOGGER.error("Preventing redstone from breaking by refusing to accept new tick time"); -+ } -+ } -+ } -+ -+ @Override -+ public void tick() { -+ final ServerChunkCache chunkProvider = this.world.getChunkSource(); -+ -+ this.world.getProfiler().push("cleaning"); -+ this.timingCleanup.startTiming(); -+ -+ this.prepare(); -+ -+ // this must be done here in case something schedules in the tick code -+ this.shortScheduled[this.shortScheduledIndex].clear(); -+ this.shortScheduledIndex = getNextIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD); -+ -+ this.timingCleanup.stopTiming(); -+ this.world.getProfiler().popPush("ticking"); -+ this.timingTicking.startTiming(); -+ -+ for (final TickNextTickData toTick : this.toTickThisTick) { -+ if (toTick.tickState != STATE_PENDING_TICK) { -+ // onTickEnd gets called at end of tick -+ continue; -+ } -+ try { -+ if (chunkProvider.isTickingReadyMainThread(toTick.getPosition())) { -+ toTick.tickState = STATE_TICKING; -+ this.tickFunction.accept(toTick); -+ if (toTick.tickState == STATE_TICKING) { -+ toTick.tickState = STATE_TICKED; -+ } // else it's STATE_CANCELLED_TICK -+ } else { -+ // re-schedule eventually -+ toTick.tickState = STATE_SCHEDULED; -+ this.addToNotTickingReady(toTick); -+ } -+ } catch (final Throwable thr) { -+ // start copy from TickListServer // TODO check on update -+ CrashReport crashreport = CrashReport.forThrowable(thr, "Exception while ticking"); -+ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being ticked"); -+ -+ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, toTick.getPosition(), (BlockState) null); -+ throw new ReportedException(crashreport); -+ // end copy from TickListServer -+ } -+ } -+ -+ this.timingTicking.stopTiming(); -+ this.world.getProfiler().pop(); -+ this.timingFinished.startTiming(); -+ -+ // finished ticking, actual cleanup time -+ for (int i = 0, len = this.toTickThisTick.size(); i < len; ++i) { -+ final TickNextTickData entry = this.toTickThisTick.poll(); -+ if (entry.tickState != STATE_SCHEDULED) { -+ // some entries get re-scheduled due to their chunk not being loaded/at correct status, so do not -+ // call onTickEnd for them -+ this.onTickEnd(entry); -+ } -+ } -+ -+ this.timingFinished.stopTiming(); -+ } -+ -+ private void onTickEnd(final TickNextTickData entry) { -+ if (entry.tickState == STATE_CANCELLED_TICK) { -+ return; -+ } -+ entry.tickState = STATE_UNSCHEDULED; -+ -+ final BlockPos pos = entry.getPosition(); -+ final long blockKey = MCUtil.getBlockKey(pos); -+ -+ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); -+ -+ if (currentEntries.size() == 1) { -+ // it should contain our entry -+ this.entriesByBlock.remove(blockKey); -+ } else { -+ // it's more likely that this entry is at the start of the list than the end -+ for (int i = 0, len = currentEntries.size(); i < len; ++i) { -+ final TickNextTickData currentEntry = currentEntries.get(i); -+ if (currentEntry == entry) { -+ currentEntries.remove(i); -+ break; -+ } -+ } -+ } -+ -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); -+ -+ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); -+ -+ set.remove(entry); -+ -+ if (set.isEmpty()) { -+ this.entriesByChunk.remove(chunkKey); -+ } -+ -+ // already removed from longScheduled or shortScheduled -+ } -+ -+ @Override -+ public boolean isPendingTickThisTick(final BlockPos blockposition, final T data) { -+ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); -+ -+ if (entries == null) { -+ return false; -+ } -+ -+ for (int i = 0, size = entries.size(); i < size; ++i) { -+ final TickNextTickData entry = entries.get(i); -+ if (entry.getData() == data && entry.tickState == STATE_PENDING_TICK) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ @Override -+ public boolean isScheduledForTick(final BlockPos blockposition, final T data) { -+ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); -+ -+ if (entries == null) { -+ return false; -+ } -+ -+ for (int i = 0, size = entries.size(); i < size; ++i) { -+ final TickNextTickData entry = entries.get(i); -+ if (entry.getData() == data && entry.tickState == STATE_SCHEDULED) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ @Override -+ public void schedule(BlockPos blockPosition, T t, int i, TickPriority tickListPriority) { -+ this.schedule(blockPosition, t, i + this.currentTick, tickListPriority); -+ } -+ -+ public void schedule(final TickNextTickData entry) { -+ this.schedule(entry.getPosition(), entry.getData(), entry.getTargetTick(), entry.getPriority()); -+ } -+ -+ public void schedule(final BlockPos pos, final T data, final long targetTick, final TickPriority priority) { -+ final TickNextTickData entry = new TickNextTickData<>(pos, data, targetTick, priority); -+ if (this.excludeFromScheduling.test(entry.getData())) { -+ return; -+ } -+ -+ if (WARN_ON_EXCESSIVE_DELAY) { -+ final long delay = entry.getTargetTick() - this.currentTick; -+ if (delay >= EXCESSIVE_DELAY_THRESHOLD) { -+ MinecraftServer.LOGGER.warn("Entry " + entry.toString() + " has been scheduled with an excessive delay of: " + delay, new Throwable()); -+ } -+ } -+ -+ final long blockKey = MCUtil.getBlockKey(pos); -+ -+ final ArrayList> currentEntries = this.entriesByBlock.computeIfAbsent(blockKey, (long keyInMap) -> new ArrayList<>(3)); -+ -+ if (currentEntries.isEmpty()) { -+ currentEntries.add(entry); -+ } else { -+ for (int i = 0, size = currentEntries.size(); i < size; ++i) { -+ final TickNextTickData currentEntry = currentEntries.get(i); -+ -+ // entries are only blocked from scheduling if currentEntry.equals(toSchedule) && currentEntry is scheduled to tick (NOT including pending) -+ if (currentEntry.getData() == entry.getData() && currentEntry.tickState == STATE_SCHEDULED) { -+ // can't add -+ return; -+ } -+ } -+ currentEntries.add(entry); -+ } -+ -+ entry.tickState = STATE_SCHEDULED; -+ -+ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (final long keyInMap) -> { -+ return new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); -+ }).add(entry); -+ -+ this.addToSchedule(entry); -+ } -+ -+ public void scheduleAll(final Iterator> iterator) { -+ while (iterator.hasNext()) { -+ this.schedule(iterator.next()); -+ } -+ } -+ -+ // this is not the standard interception calculation, but it's the one vanilla uses -+ // i.e the y value is ignored? the x, z calc isn't correct? -+ // however for the copy op they use the correct intersection, after using this one of course... -+ private static boolean isBlockInSortof(final BoundingBox boundingBox, final BlockPos pos) { -+ return pos.getX() >= boundingBox.getMinX() && pos.getX() < boundingBox.getMaxX() && pos.getZ() >= boundingBox.getMinZ() && pos.getZ() < boundingBox.getMaxZ(); -+ } -+ -+ @Override -+ public List> getEntriesInBoundingBox(final BoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { -+ if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) { -+ return Collections.emptyList(); // vanilla behaviour, check isBlockInSortof above -+ } -+ -+ final int lowerChunkX = structureboundingbox.getMinX() >> 4; -+ final int upperChunkX = (structureboundingbox.getMaxX() - 1) >> 4; // subtract 1 since maxX is exclusive -+ final int lowerChunkZ = structureboundingbox.getMinZ() >> 4; -+ final int upperChunkZ = (structureboundingbox.getMaxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive -+ -+ final int xChunksLength = (upperChunkX - lowerChunkX + 1); -+ final int zChunksLength = (upperChunkZ - lowerChunkZ + 1); -+ -+ final ObjectRBTreeSet>[] containingChunks = new ObjectRBTreeSet[xChunksLength * zChunksLength]; -+ -+ final int offset = (xChunksLength * -lowerChunkZ - lowerChunkX); -+ int totalEntries = 0; -+ for (int currChunkX = lowerChunkX; currChunkX <= upperChunkX; ++currChunkX) { -+ for (int currChunkZ = lowerChunkZ; currChunkZ <= upperChunkZ; ++currChunkZ) { -+ // todo optimize -+ //final int index = (currChunkX - lowerChunkX) + xChunksLength * (currChunkZ - lowerChunkZ); -+ final int index = offset + currChunkX + xChunksLength * currChunkZ; -+ final ObjectRBTreeSet> set = containingChunks[index] = this.entriesByChunk.get(MCUtil.getCoordinateKey(currChunkX, currChunkZ)); -+ if (set != null) { -+ totalEntries += set.size(); -+ } -+ } -+ } -+ -+ final List> ret = new ArrayList<>(totalEntries); -+ -+ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); -+ -+ MCUtil.mergeSortedSets((TickNextTickData entry) -> { -+ if (!isBlockInSortof(structureboundingbox, entry.getPosition())) { -+ return; -+ } -+ final int tickState = entry.tickState; -+ if ((tickState & matchOne) == 0) { -+ return; -+ } -+ -+ ret.add(entry); -+ return; -+ }, TickListServerInterval.ENTRY_COMPARATOR, containingChunks); -+ -+ if (removeReturned) { -+ for (TickNextTickData entry : ret) { -+ this.removeEntry(entry); -+ } -+ } -+ -+ return ret; -+ } -+ -+ @Override -+ public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { -+ // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInBoundingBox(structureboundingbox, false, false); -+ Iterator> iterator = list.iterator(); -+ -+ while (iterator.hasNext()) { -+ TickNextTickData nextticklistentry = iterator.next(); -+ -+ if (structureboundingbox.hasPoint( nextticklistentry.getPosition())) { -+ BlockPos blockposition1 = nextticklistentry.getPosition().add(blockposition); -+ T t0 = nextticklistentry.getData(); -+ -+ this.schedule(new TickNextTickData<>(blockposition1, t0, nextticklistentry.getTargetTick(), nextticklistentry.getPriority())); -+ } -+ } -+ // end copy from TickListServer -+ } -+ -+ @Override -+ public List> getEntriesInChunk(ChunkPos chunkPos, boolean removeReturned, boolean excludeTicked) { -+ // Vanilla DOES get the entries 2 blocks out of the chunk too, but that doesn't matter since we ignore chunks -+ // not at ticking status, and ticking status requires neighbours loaded -+ // so with this method we will reduce scheduler churning -+ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); -+ -+ final ObjectRBTreeSet> entries = this.entriesByChunk.get(MCUtil.getCoordinateKey(chunkPos)); -+ -+ if (entries == null) { -+ return Collections.emptyList(); -+ } -+ -+ final List> ret = new ArrayList<>(entries.size()); -+ -+ for (TickNextTickData entry : entries) { -+ if ((entry.tickState & matchOne) == 0) { -+ continue; -+ } -+ ret.add(entry); -+ } -+ -+ if (removeReturned) { -+ for (TickNextTickData entry : ret) { -+ this.removeEntry(entry); -+ } -+ } -+ -+ return ret; -+ } -+ -+ @Override -+ public ListTag serialize(ChunkPos chunkcoordintpair) { -+ // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInChunk(chunkcoordintpair, false, true); -+ -+ return ServerTickList.serialize(this.getMinecraftKeyFrom, list, this.currentTick); -+ // end copy from TickListServer -+ } -+ -+ @Override -+ public int getTotalScheduledEntries() { -+ // good thing this is only used in debug reports // TODO check on update -+ int ret = 0; -+ -+ for (TickNextTickData entry : this.longScheduled) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ ++ret; -+ } -+ } -+ -+ for (Iterator>>> iterator = this.pendingChunkTickLoad.long2ObjectEntrySet().iterator(); iterator.hasNext();) { -+ ArrayList> list = iterator.next().getValue(); -+ -+ for (TickNextTickData entry : list) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ ++ret; -+ } -+ } -+ } -+ -+ for (TickListServerInterval interval : this.shortScheduled) { -+ for (Iterable> set : interval.byPriority) { -+ for (TickNextTickData entry : set) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ ++ret; -+ } -+ } -+ } -+ } -+ -+ return ret; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d40a7aff6c27883f3ae8ba878a94c97242619f2c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.server.ticklist; -+ -+import com.destroystokyo.paper.util.set.LinkedSortedSet; -+import java.util.Comparator; -+import net.minecraft.world.level.TickNextTickData; -+import net.minecraft.world.level.TickPriority; -+ -+// represents a set of entries to tick at a specified time -+public final class TickListServerInterval { -+ -+ public static final int TOTAL_PRIORITIES = TickPriority.values().length; -+ public static final Comparator> ENTRY_COMPARATOR_BY_ID = (entry1, entry2) -> { -+ return Long.compare(entry1.getId(), entry2.getId()); -+ }; -+ public static final Comparator> ENTRY_COMPARATOR = (Comparator)TickNextTickData.comparator(); -+ -+ // we do not record the interval, this class is meant to be used on a ring buffer -+ -+ // inlined enum map for TickListPriority -+ public final LinkedSortedSet>[] byPriority = new LinkedSortedSet[TOTAL_PRIORITIES]; -+ -+ { -+ for (int i = 0, len = this.byPriority.length; i < len; ++i) { -+ this.byPriority[i] = new LinkedSortedSet<>(ENTRY_COMPARATOR_BY_ID); -+ } -+ } -+ -+ public void addEntryLast(final TickNextTickData entry) { -+ this.byPriority[entry.getPriority().ordinal()].addLast(entry); -+ } -+ -+ public void addEntryFirst(final TickNextTickData entry) { -+ this.byPriority[entry.getPriority().ordinal()].addFirst(entry); -+ } -+ -+ public void clear() { -+ for (int i = 0, len = this.byPriority.length; i < len; ++i) { -+ this.byPriority[i].clear(); // O(1) clear -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..118988c39e58f28e8a2851792b9c014f341f06fc ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java -@@ -0,0 +1,142 @@ -+package com.destroystokyo.paper.util.set; -+ -+import java.util.Comparator; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+ -+public final class LinkedSortedSet implements Iterable { -+ -+ public final Comparator comparator; -+ -+ protected Link head; -+ protected Link tail; -+ -+ public LinkedSortedSet() { -+ this((Comparator)Comparator.naturalOrder()); -+ } -+ -+ public LinkedSortedSet(final Comparator comparator) { -+ this.comparator = comparator; -+ } -+ -+ public void clear() { -+ this.head = this.tail = null; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator() { -+ -+ Link next = LinkedSortedSet.this.head; -+ -+ @Override -+ public boolean hasNext() { -+ return this.next != null; -+ } -+ -+ @Override -+ public E next() { -+ final Link next = this.next; -+ if (next == null) { -+ throw new NoSuchElementException(); -+ } -+ this.next = next.next; -+ return next.element; -+ } -+ }; -+ } -+ -+ public boolean addLast(final E element) { -+ final Comparator comparator = this.comparator; -+ -+ Link curr = this.tail; -+ if (curr != null) { -+ int compare; -+ -+ while ((compare = comparator.compare(element, curr.element)) < 0) { -+ Link prev = curr; -+ curr = curr.prev; -+ if (curr != null) { -+ continue; -+ } -+ this.head = prev.prev = new Link<>(element, null, prev); -+ return true; -+ } -+ -+ if (compare != 0) { -+ // insert after curr -+ final Link next = curr.next; -+ final Link insert = new Link<>(element, curr, next); -+ curr.next = insert; -+ -+ if (next == null) { -+ this.tail = insert; -+ } else { -+ next.prev = insert; -+ } -+ return true; -+ } -+ -+ return false; -+ } else { -+ this.head = this.tail = new Link<>(element); -+ return true; -+ } -+ } -+ -+ public boolean addFirst(final E element) { -+ final Comparator comparator = this.comparator; -+ -+ Link curr = this.head; -+ if (curr != null) { -+ int compare; -+ -+ while ((compare = comparator.compare(element, curr.element)) > 0) { -+ Link prev = curr; -+ curr = curr.next; -+ if (curr != null) { -+ continue; -+ } -+ this.tail = prev.next = new Link<>(element, prev, null); -+ return true; -+ } -+ -+ if (compare != 0) { -+ // insert before curr -+ final Link prev = curr.prev; -+ final Link insert = new Link<>(element, prev, curr); -+ curr.prev = insert; -+ -+ if (prev == null) { -+ this.head = insert; -+ } else { -+ prev.next = insert; -+ } -+ return true; -+ } -+ -+ return false; -+ } else { -+ this.head = this.tail = new Link<>(element); -+ return true; -+ } -+ } -+ -+ protected static final class Link { -+ public E element; -+ public Link prev; -+ public Link next; -+ -+ public Link() {} -+ -+ public Link(final E element) { -+ this.element = element; -+ } -+ -+ public Link(final E element, final Link prev, final Link next) { -+ this.element = element; -+ this.prev = prev; -+ this.next = next; -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 3db77d9eda98eacb099135643aff5e94751f4c7c..595abf528a7862478100770987906af1b13439fe 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -111,6 +111,7 @@ public class BlockPos extends Vec3i { - return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.getX() + x, this.getY() + y, this.getZ() + z); - } - -+ public final BlockPos add(Vec3i baseblockposition) { return this.offset(baseblockposition); } // Paper - OBFHELPER - public BlockPos offset(Vec3i pos) { - return this.offset(pos.getX(), pos.getY(), pos.getZ()); - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 77d3969200ac6f88f3af9add05def0b627ce6db3..d12d5459c847d3f0d655c85e31d81c27b7a2face 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -495,7 +495,9 @@ public class ChunkHolder { - ChunkHolder.this.isTickingReady = true; - - -- -+ // Paper start - rewrite ticklistserver -+ ChunkHolder.this.chunkMap.level.onChunkSetTicking(ChunkHolder.this.pos.x, ChunkHolder.this.pos.z); -+ // Paper end - rewrite ticklistserver - - } - }); -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 3aeb8426b0461ec572c1499116be80f968bb4104..e2b1541042bceac965411e3176d08c61f217c07f 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -21,6 +21,7 @@ import net.minecraft.Util; - import net.minecraft.core.BlockPos; - import net.minecraft.core.SectionPos; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.progress.ChunkProgressListener; - import net.minecraft.util.Mth; - import net.minecraft.util.profiling.ProfilerFiller; -@@ -217,6 +218,13 @@ public class ServerChunkCache extends ChunkSource { - } - // Paper end - -+ // Paper start - rewrite ticklistserver -+ public final boolean isTickingReadyMainThread(BlockPos pos) { -+ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(pos)); -+ return chunk != null && chunk.isTickingReady(); -+ } -+ // Paper end - rewrite ticklistserver -+ - public ServerChunkCache(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldloadlistener, Supplier supplier) { - this.level = worldserver; - this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(worldserver); -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 5d85895456b5d65954889cadf932027ea23b400b..9da0d98bc2ed7876a00a734690ed42f01b9a9a9b 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -292,6 +292,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - // Paper end - -+ // Paper start - rewrite ticklistserver -+ void onChunkSetTicking(int chunkX, int chunkZ) { -+ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { -+ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.blockTicks).onChunkSetTicking(chunkX, chunkZ); -+ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.liquidTicks).onChunkSetTicking(chunkX, chunkZ); -+ } -+ } -+ // Paper end - rewrite ticklistserver -+ - // Add env and gen to constructor, WorldData -> WorldDataServer - public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor -@@ -299,12 +308,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - convertable = convertable_conversionsession; - uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile()); - // CraftBukkit end -- this.blockTicks = new ServerTickList<>(this, (block) -> { -- return block == null || block.defaultBlockState().isAir(); -- }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings -- this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { -- return fluidtype == null || fluidtype == Fluids.EMPTY; -- }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings -+ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { -+ this.blockTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> { -+ return block == null || block.defaultBlockState().isAir(); -+ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings -+ this.liquidTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (fluidtype) -> { -+ return fluidtype == null || fluidtype == Fluids.EMPTY; -+ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings -+ } else { -+ this.blockTicks = new ServerTickList<>(this, (block) -> { -+ return block == null || block.defaultBlockState().isAir(); -+ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings -+ this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { -+ return fluidtype == null || fluidtype == Fluids.EMPTY; -+ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings -+ } - this.navigations = Sets.newHashSet(); - this.blockEvents = new ObjectLinkedOpenHashSet(); - this.tickTime = flag1; -@@ -639,7 +657,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - if (this.tickTime) { - long i = this.levelData.getGameTime() + 1L; - -- this.worldDataServer.setGameTime(i); -+ this.worldDataServer.setGameTime(i); // Paper - diff on change, we want the below to be ran right after this -+ this.blockTicks.nextTick(); // Paper -+ this.liquidTicks.nextTick(); // Paper - this.worldDataServer.getScheduledEvents().tick(this.server, i); - if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { - this.setDayTime(this.levelData.getDayTime() + 1L); -diff --git a/src/main/java/net/minecraft/world/level/ChunkTickList.java b/src/main/java/net/minecraft/world/level/ChunkTickList.java -index 16757eb9c03c0dab51a7a1b569daff81cf9654f3..3008e0c42efe908e45dba1a1437928d4d4378f24 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkTickList.java -+++ b/src/main/java/net/minecraft/world/level/ChunkTickList.java -@@ -9,6 +9,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MinecraftServer; - - public class ChunkTickList implements TickList { - -@@ -61,6 +62,8 @@ public class ChunkTickList implements TickList { - return nbttaglist; - } - -+ private static final int MAX_TICK_DELAY = Integer.getInteger("paper.ticklist-max-tick-delay", -1).intValue(); // Paper - clean up broken entries -+ - public static ChunkTickList create(ListTag ticks, Function function, Function function1) { - List> list = Lists.newArrayList(); - -@@ -71,7 +74,14 @@ public class ChunkTickList implements TickList { - if (t0 != null) { - BlockPos blockposition = new BlockPos(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); - -- list.add(new ChunkTickList.ScheduledTick<>(t0, blockposition, nbttagcompound.getInt("t"), TickPriority.byValue(nbttagcompound.getInt("p")))); -+ // Paper start - clean up broken entries -+ int delay = nbttagcompound.getInt("t"); -+ if (MAX_TICK_DELAY > 0 && delay > MAX_TICK_DELAY) { -+ MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockposition + ", tick delay " + delay); -+ continue; -+ } -+ list.add(new ChunkTickList.ScheduledTick<>(t0, blockposition, delay, TickPriority.byValue(nbttagcompound.getInt("p")))); -+ // Paper end - clean up broken entries - } - } - -diff --git a/src/main/java/net/minecraft/world/level/ServerTickList.java b/src/main/java/net/minecraft/world/level/ServerTickList.java -index 10ac1ba0a3d192486f22c2127d5bc30353f0edb6..65b3a16f40a295c2916be2a9fd019b452fb65e4f 100644 ---- a/src/main/java/net/minecraft/world/level/ServerTickList.java -+++ b/src/main/java/net/minecraft/world/level/ServerTickList.java -@@ -50,7 +50,16 @@ public class ServerTickList implements TickList { - private final co.aikar.timings.Timing timingTicking; // Paper - // Paper end - -+ // Paper start -+ public void nextTick() {} -+ // Paper end -+ -+ public void tick() { -+ // Paper start - allow overriding -+ this.tick(); -+ } - public void tick() { -+ // Paper end - int i = this.tickNextTickList.size(); - - if (false) { // CraftBukkit -@@ -118,28 +127,43 @@ public class ServerTickList implements TickList { - - @Override - public boolean willTickThisTick(BlockPos pos, T object) { -- return this.currentlyTicking.contains(new TickNextTickData<>(pos, object)); -+ // Paper start - allow overriding -+ return this.isPendingTickThisTick(pos, object); -+ } -+ public boolean isPendingTickThisTick(BlockPos blockposition, T t0) { -+ // Paper end -+ return this.currentlyTicking.contains(new TickNextTickData<>(blockposition, t0)); - } - - public List> fetchTicksInChunk(ChunkPos chunkcoordintpair, boolean updateState, boolean getStaleTicks) { -+ // Paper start - allow overriding -+ return this.getEntriesInChunk(chunkcoordintpair, updateState, getStaleTicks); -+ } -+ public List> getEntriesInChunk(ChunkPos chunkcoordintpair, boolean flag, boolean flag1) { -+ // Paper end - int i = (chunkcoordintpair.x << 4) - 2; - int j = i + 16 + 2; - int k = (chunkcoordintpair.z << 4) - 2; - int l = k + 16 + 2; - -- return this.fetchTicksInArea(new BoundingBox(i, 0, k, j, 256, l), updateState, getStaleTicks); -+ return this.fetchTicksInArea(new BoundingBox(i, 0, k, j, 256, l), flag, flag1); - } - - public List> fetchTicksInArea(BoundingBox bounds, boolean updateState, boolean getStaleTicks) { -- List> list = this.fetchTicksInArea((List) null, this.tickNextTickList, bounds, updateState); -+ // Paper start - allow overriding -+ return this.getEntriesInBoundingBox(bounds, updateState, getStaleTicks); -+ } -+ public List> getEntriesInBoundingBox(BoundingBox structureboundingbox, boolean flag, boolean flag1) { -+ // Paper end -+ List> list = this.fetchTicksInArea((List) null, this.tickNextTickList, structureboundingbox, flag); - -- if (updateState && list != null) { -+ if (flag && list != null) { - this.tickNextTickSet.removeAll(list); - } - -- list = this.fetchTicksInArea(list, this.currentlyTicking, bounds, updateState); -- if (!getStaleTicks) { -- list = this.fetchTicksInArea(list, this.alreadyTicked, bounds, updateState); -+ list = this.fetchTicksInArea(list, this.currentlyTicking, structureboundingbox, flag); -+ if (!flag1) { -+ list = this.fetchTicksInArea(list, this.alreadyTicked, structureboundingbox, flag); - } - - return list == null ? Collections.emptyList() : list; -@@ -170,14 +194,19 @@ public class ServerTickList implements TickList { - } - - public void copy(BoundingBox box, BlockPos offset) { -- List> list = this.fetchTicksInArea(box, false, false); -+ // Paper start - allow overriding -+ this.copy(box, offset); -+ } -+ public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { -+ // Paper end -+ List> list = this.fetchTicksInArea(structureboundingbox, false, false); - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) { - TickNextTickData nextticklistentry = (TickNextTickData) iterator.next(); - -- if (box.isInside((Vec3i) nextticklistentry.pos)) { -- BlockPos blockposition1 = nextticklistentry.pos.offset((Vec3i) offset); -+ if (structureboundingbox.isInside((Vec3i) nextticklistentry.pos)) { -+ BlockPos blockposition1 = nextticklistentry.pos.offset((Vec3i) blockposition); - T t0 = nextticklistentry.getType(); - - this.addTickData(new TickNextTickData<>(blockposition1, t0, nextticklistentry.triggerTick, nextticklistentry.priority)); -@@ -187,11 +216,17 @@ public class ServerTickList implements TickList { - } - - public ListTag save(ChunkPos chunkcoordintpair) { -+ // Paper start - allow overriding -+ return this.serialize(chunkcoordintpair); -+ } -+ public ListTag serialize(ChunkPos chunkcoordintpair) { -+ // Paper end - List> list = this.fetchTicksInChunk(chunkcoordintpair, false, true); - - return saveTickList(this.toId, list, this.level.getGameTime()); - } - -+ public static ListTag serialize(Function function, Iterable> iterable, long i) { return ServerTickList.saveTickList(function, iterable, i); } // Paper - OBFHELPER - private static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { - ListTag nbttaglist = new ListTag(); - Iterator iterator = scheduledTicks.iterator(); -@@ -214,13 +249,23 @@ public class ServerTickList implements TickList { - - @Override - public boolean hasScheduledTick(BlockPos pos, T object) { -- return this.tickNextTickSet.contains(new TickNextTickData<>(pos, object)); -+ // Paper start - allow overriding -+ return this.isScheduledForTick(pos, object); -+ } -+ public boolean isScheduledForTick(BlockPos blockposition, T t0) { -+ // Paper end -+ return this.tickNextTickSet.contains(new TickNextTickData<>(blockposition, t0)); - } - - @Override - public void scheduleTick(BlockPos pos, T object, int delay, TickPriority priority) { -- if (!this.ignore.test(object)) { -- this.addTickData(new TickNextTickData<>(pos, object, (long) delay + this.level.getGameTime(), priority)); -+ // Paper start - allow overriding -+ this.schedule(pos, object, delay, priority); -+ } -+ public void schedule(BlockPos blockposition, T t0, int i, TickPriority ticklistpriority) { -+ // Paper end -+ if (!this.ignore.test(t0)) { -+ this.addTickData(new TickNextTickData<>(blockposition, t0, (long) i + this.level.getGameTime(), ticklistpriority)); - } - - } -@@ -234,6 +279,11 @@ public class ServerTickList implements TickList { - } - - public int size() { -+ // Paper start - allow overriding -+ return this.getTotalScheduledEntries(); -+ } -+ public int getTotalScheduledEntries() { -+ // Paper end - return this.tickNextTickSet.size(); - } - } -diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java -index 90833389022d7412bdda8868a356b84f62a00e03..61cdaf45368dcc40f3311e8b7f8637a6c93a2d76 100644 ---- a/src/main/java/net/minecraft/world/level/TickNextTickData.java -+++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java -@@ -6,11 +6,13 @@ import net.minecraft.core.BlockPos; - public class TickNextTickData { - - private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading -- private final T type; -- public final BlockPos pos; -- public final long triggerTick; -- public final TickPriority priority; -- private final long c; -+ private final T type; public final T getData() { return this.type; } // Paper - OBFHELPER -+ public final BlockPos pos; public final BlockPos getPosition() { return this.pos; } // Paper - OBFHELPER -+ public final long triggerTick; public final long getTargetTick() { return this.triggerTick; } // Paper - OBFHELPER -+ public final TickPriority priority; public final TickPriority getPriority() { return this.priority; } // Paper - OBFHELPER -+ private final long c; public final long getId() { return this.c; } // Paper - OBFHELPER -+ private final int hash; // Paper -+ public int tickState; // Paper - - public TickNextTickData(BlockPos pos, T t) { - this(pos, t, 0L, TickPriority.NORMAL); -@@ -22,6 +24,7 @@ public class TickNextTickData { - this.type = t; - this.triggerTick = time; - this.priority = priority; -+ this.hash = this.computeHash(); // Paper - } - - public boolean equals(Object object) { -@@ -34,19 +37,31 @@ public class TickNextTickData { - } - } - -+ // Paper start - optimize hashcode -+ @Override - public int hashCode() { -+ return this.hash; -+ } -+ public final int computeHash() { -+ // Paper end - optimize hashcode - return this.pos.hashCode(); - } - -- public static Comparator createTimeComparator() { // Paper - decompile fix -- return Comparator.comparingLong((nextticklistentry) -> { -- return ((TickNextTickData) nextticklistentry).triggerTick; // Paper - decompile fix -- }).thenComparing((nextticklistentry) -> { -- return ((TickNextTickData) nextticklistentry).priority; // Paper - decompile fix -- }).thenComparingLong((nextticklistentry) -> { -- return ((TickNextTickData) nextticklistentry).c; // Paper - decompile fix -- }); -+ // Paper start - let's not use more functional code for no reason. -+ public static Comparator comparator() { return TickNextTickData.createTimeComparator(); } // Paper - OBFHELPER -+ public static Comparator createTimeComparator() { -+ return (Comparator)(Comparator)(TickNextTickData nextticklistentry, TickNextTickData nextticklistentry1) -> { -+ int i = Long.compare(nextticklistentry.getTargetTick(), nextticklistentry1.getTargetTick()); -+ -+ if (i != 0) { -+ return i; -+ } else { -+ i = nextticklistentry.getPriority().compareTo(nextticklistentry1.getPriority()); -+ return i != 0 ? i : Long.compare(nextticklistentry.getId(), nextticklistentry1.getId()); -+ } -+ }; - } -+ // Paper end - let's not use more functional code for no reason. - - public String toString() { - return this.type + ": " + this.pos + ", " + this.triggerTick + ", " + this.priority + ", " + this.c; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java b/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java -index 76bea58d35d352ee6f3d4bd0d10af3b6d615ae2c..4288fa253668196e6c32a876f18ec496fb3abad6 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java -@@ -8,12 +8,12 @@ import net.minecraft.nbt.IntArrayTag; - - public class BoundingBox { - -- public int x0; -- public int y0; -- public int z0; -- public int x1; -- public int y1; -- public int z1; -+ public int x0; public final int getMinX() { return this.x0; } // Paper - OBFHELPER -+ public int y0; public final int getMinY() { return this.y0; } // Paper - OBFHELPER -+ public int z0; public final int getMinZ() { return this.z0; } // Paper - OBFHELPER -+ public int x1; public final int getMaxX() { return this.x1; } // Paper - OBFHELPER -+ public int y1; public final int getMaxY() { return this.y1; } // Paper - OBFHELPER -+ public int z1; public final int getMaxZ() { return this.z1; } // Paper - OBFHELPER - - public BoundingBox() {} - -@@ -92,6 +92,7 @@ public class BoundingBox { - this.y1 = 512; - } - -+ public final boolean intersects(BoundingBox boundingBox) { return this.intersects(boundingBox); } // Paper - OBFHELPER - public boolean intersects(BoundingBox other) { - return this.x1 >= other.x0 && this.x0 <= other.x1 && this.z1 >= other.z0 && this.z0 <= other.z1 && this.y1 >= other.y0 && this.y0 <= other.y1; - } -@@ -126,6 +127,7 @@ public class BoundingBox { - this.move(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } - -+ public final boolean hasPoint(Vec3i baseblockposition) { return this.isInside(baseblockposition); } // Paper - OBFHELPER - public boolean isInside(Vec3i vec) { - return vec.getX() >= this.x0 && vec.getX() <= this.x1 && vec.getZ() >= this.z0 && vec.getZ() <= this.z1 && vec.getY() >= this.y0 && vec.getY() <= this.y1; - } diff --git a/Remapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch b/Remapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch deleted file mode 100644 index 6e0269c7f2..0000000000 --- a/Remapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sat, 1 Feb 2020 16:50:39 +0100 -Subject: [PATCH] Pillager patrol spawn settings and per player options - -This adds config options for defining the spawn chance, spawn delay and -spawn start day as well as toggles for handling the spawn delay and -start day per player. (Based on the time played statistic) -When not per player it will use the Vanilla mechanic of one delay per -world and the world age for the start day. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 525d702d78a609af987ebd2c32169b873e5c05ed..6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -582,10 +582,21 @@ public class PaperWorldConfig { - } - - public boolean disablePillagerPatrols = false; -+ public double patrolSpawnChance = 0.2; -+ public boolean patrolPerPlayerDelay = false; -+ public int patrolDelay = 12000; -+ public boolean patrolPerPlayerStart = false; -+ public int patrolStartDay = 5; - private void pillagerSettings() { - disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); -+ patrolSpawnChance = getDouble("game-mechanics.pillager-patrols.spawn-chance", patrolSpawnChance); -+ patrolPerPlayerDelay = getBoolean("game-mechanics.pillager-patrols.spawn-delay.per-player", patrolPerPlayerDelay); -+ patrolDelay = getInt("game-mechanics.pillager-patrols.spawn-delay.ticks", patrolDelay); -+ patrolPerPlayerStart = getBoolean("game-mechanics.pillager-patrols.start.per-player", patrolPerPlayerStart); -+ patrolStartDay = getInt("game-mechanics.pillager-patrols.start.day", patrolStartDay); - } - -+ - public boolean entitiesTargetWithFollowRange = false; - private void entitiesTargetWithFollowRange() { - entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 7f4e81ee3339e90b8525541dccf6dea187853cf7..a469016c43251f16913a365c4131b2448eaa4c48 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -213,6 +213,7 @@ public class ServerPlayer extends Player implements ContainerListener { - public boolean wonGame; - private int containerUpdateDelay; // Paper - public long loginTime; // Paper -+ public int patrolSpawnDelay; // Paper - per player patrol spawns - // Paper start - cancellable death event - public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; -diff --git a/src/main/java/net/minecraft/stats/StatType.java b/src/main/java/net/minecraft/stats/StatType.java -index ba48795a7b7cbf4622e64273ab488e26d7a862e2..b85987910cf80b1d1a04a7b772e19200f4ce4372 100644 ---- a/src/main/java/net/minecraft/stats/StatType.java -+++ b/src/main/java/net/minecraft/stats/StatType.java -@@ -28,6 +28,7 @@ public class StatType implements Iterable> { - return this.map.values().iterator(); - } - -+ public final Stat get(T t) { return this.get(t); }; // Paper - OBFHELPER - public Stat get(T key) { - return this.get(key, StatFormatter.DEFAULT); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java -index 48efe133d294bb1b17e8ac8b44eea8a29f15845f..dcbe74bdb1b6e07f7b8845182576ef544493d377 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java -@@ -4,11 +4,12 @@ import java.util.Random; - import net.minecraft.core.BlockPos; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.stats.Stats; - import net.minecraft.world.entity.EntityType; - import net.minecraft.world.entity.MobSpawnType; - import net.minecraft.world.entity.SpawnGroupData; - import net.minecraft.world.entity.monster.PatrollingMonster; --import net.minecraft.world.entity.player.Player; - import net.minecraft.world.level.BlockGetter; - import net.minecraft.world.level.CustomSpawner; - import net.minecraft.world.level.GameRules; -@@ -20,13 +21,13 @@ import net.minecraft.world.level.block.state.BlockState; - - public class PatrolSpawner implements CustomSpawner { - -- private int nextTick; -+ private int nextTick;private int getSpawnDelay() { return nextTick; } private void setSpawnDelay(int spawnDelay) { this.nextTick = spawnDelay; } // Paper - OBFHELPER - - public PatrolSpawner() {} - - @Override - public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { -- if (world.paperConfig.disablePillagerPatrols) return 0; // Paper -+ if (world.paperConfig.disablePillagerPatrols || world.paperConfig.patrolSpawnChance == 0) return 0; // Paper - if (!spawnMonsters) { - return 0; - } else if (!world.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) { -@@ -34,23 +35,51 @@ public class PatrolSpawner implements CustomSpawner { - } else { - Random random = world.random; - -- --this.nextTick; -- if (this.nextTick > 0) { -+ // Paper start - Patrol settings -+ // Random player selection moved up for per player spawning and configuration -+ int j = world.players().size(); -+ if (j < 1) { - return 0; -+ } -+ -+ ServerPlayer entityhuman = world.players().get(random.nextInt(j)); -+ if (entityhuman.isSpectator()) { -+ return 0; -+ } -+ -+ int patrolSpawnDelay; -+ if (world.paperConfig.patrolPerPlayerDelay) { -+ --entityhuman.patrolSpawnDelay; -+ patrolSpawnDelay = entityhuman.patrolSpawnDelay; - } else { -- this.nextTick += 12000 + random.nextInt(1200); -- long i = world.getDayTime() / 24000L; -+ setSpawnDelay(getSpawnDelay() - 1); -+ patrolSpawnDelay = getSpawnDelay(); -+ } -+ -+ if (patrolSpawnDelay > 0) { -+ return 0; -+ } else { -+ long days; -+ if (world.paperConfig.patrolPerPlayerStart) { -+ days = entityhuman.getStats().getValue(Stats.CUSTOM.get(Stats.PLAY_ONE_MINUTE)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang -+ } else { -+ days = world.getDayTime() / 24000L; -+ } -+ if (world.paperConfig.patrolPerPlayerDelay) { -+ entityhuman.patrolSpawnDelay += world.paperConfig.patrolDelay + random.nextInt(1200); -+ } else { -+ setSpawnDelay(getSpawnDelay() + world.paperConfig.patrolDelay + random.nextInt(1200)); -+ } - -- if (i >= 5L && world.isDay()) { -- if (random.nextInt(5) != 0) { -+ if (days >= world.paperConfig.patrolStartDay && world.isDay()) { -+ if (random.nextDouble() >= world.paperConfig.patrolSpawnChance) { -+ // Paper end - return 0; - } else { -- int j = world.players().size(); - - if (j < 1) { - return 0; - } else { -- Player entityhuman = (Player) world.players().get(random.nextInt(j)); - - if (entityhuman.isSpectator()) { - return 0; diff --git a/Remapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch b/Remapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch deleted file mode 100644 index 0c956bdb77..0000000000 --- a/Remapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 29 Mar 2020 18:26:14 -0400 -Subject: [PATCH] Ensure Entity is never double registered - -If something calls register twice, and the world is ticking, it could be -enqueued to add twice. - -Vs behavior of non ticking of just overwriting state. - -We will now simply log a warning when this happens instead of crashing the server. - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 9da0d98bc2ed7876a00a734690ed42f01b9a9a9b..9898d5c8fab63c576831bd416ccf1854ed077b0d 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -643,6 +643,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - Entity entity2; - - while ((entity2 = (Entity) this.toAddAfterTick.poll()) != null) { -+ if (!entity2.isQueuedForRegister) continue; // Paper - ignore cancelled registers - this.add(entity2); - } - -@@ -1400,6 +1401,19 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - - public void onEntityRemoved(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot -+ // Paper start - fix entity registration issues -+ if (entity instanceof EnderDragonPart) { -+ // Usually this is a no-op for complex parts, and ID's should be removed, but go ahead and remove it anyways -+ // Dragon parts are handled special in register. they don't receive a valid = true or register by UUID etc. -+ this.entitiesById.remove(entity.getId(), entity); -+ return; -+ } -+ if (!entity.valid) { -+ // Someone called remove before we ever got added, cancel the add. -+ entity.isQueuedForRegister = false; -+ return; -+ } -+ // Paper end - // Spigot start - if ( entity instanceof Player ) - { -@@ -1466,9 +1480,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - - private void add(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot -+ // Paper start - don't double enqueue entity registration -+ //noinspection ObjectEquality -+ if (this.entitiesById.get(entity.getId()) == entity) { -+ LOGGER.error(entity + " was already registered!"); -+ new Throwable().printStackTrace(); -+ return; -+ } -+ // Paper end - if (this.tickingEntities) { -- this.toAddAfterTick.add(entity); -+ if (!entity.isQueuedForRegister) { // Paper -+ this.toAddAfterTick.add(entity); -+ entity.isQueuedForRegister = true; // Paper -+ } - } else { -+ entity.isQueuedForRegister = false; // Paper - this.entitiesById.put(entity.getId(), entity); - if (entity instanceof EnderDragon) { - EnderDragonPart[] aentitycomplexpart = ((EnderDragon) entity).getSubEntities(); -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 43f77d01fceab107d3502d282205aa579d64cc4b..7e198b94f349d4c4d61502f5ad8c60686800d88f 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -147,6 +147,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - // Paper start -+ public boolean isQueuedForRegister = false; - public static Random SHARED_RANDOM = new Random() { - private boolean locked = false; - @Override diff --git a/Remapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch b/Remapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch deleted file mode 100644 index 110790b17f..0000000000 --- a/Remapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 Mar 2020 03:01:45 -0400 -Subject: [PATCH] Fix unregistering entities from unloading chunks - -CraftBukkit caused a regression here by making unloading chunks not -have a ticket added and returning unloaded future. - -This caused entities who were killed in same tick their chunk is unloading -to not be able to be removed from the chunk. - -This then results in dead entities lingering in the Chunk. - -Combine that with a buggy detail of the previous implementation of -the Dupe UUID patch, then this was the likely source of the "Ghost entities" - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 9898d5c8fab63c576831bd416ccf1854ed077b0d..c5dc41a3cf499038bd33451a189913cd3978b230 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1559,9 +1559,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - private void removeFromChunk(Entity entity) { -- ChunkAccess ichunkaccess = chunkSource.getChunkUnchecked(entity.xChunk, entity.zChunk); // CraftBukkit - SPIGOT-5228: getChunkAt won't find the entity's chunk if it has already been unloaded (i.e. if it switched to state INACCESSIBLE). -+ LevelChunk ichunkaccess = entity.getCurrentChunk(); // Paper - getChunkAt(x,z,full,false) is broken by CraftBukkit as it won't return an unloading chunk. Use our current chunk reference as this points to what chunk they need to be removed from anyways - -- if (ichunkaccess instanceof LevelChunk) { -+ if (ichunkaccess != null) { // Paper - ((LevelChunk) ichunkaccess).removeEntity(entity); - } - diff --git a/Remapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/Remapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch deleted file mode 100644 index a83d559354..0000000000 --- a/Remapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 Mar 2020 03:50:42 -0400 -Subject: [PATCH] Remote Connections shouldn't hold up shutdown - -Bugs in the connection logic appears to leave stale connections even, preventing shutdown - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 4862a9519d4ba5f05b634a0335837bea9812edee..f8ddc0aa98874c7879a51e76d1a629cbdaf58812 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -397,11 +397,11 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - } - - if (this.rconThread != null) { -- this.rconThread.stop(); -+ //this.remoteControlListener.b(); // Paper - don't wait for remote connections - } - - if (this.queryThreadGs4 != null) { -- this.queryThreadGs4.stop(); -+ //this.remoteStatusListener.b(); // Paper - don't wait for remote connections - } - - System.exit(0); // CraftBukkit diff --git a/Remapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/Remapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch deleted file mode 100644 index 044507e1b4..0000000000 --- a/Remapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Tue, 17 Mar 2020 14:18:50 -0500 -Subject: [PATCH] Do not allow bees to load chunks for beehives - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e99b45d887 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Bee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -358,6 +358,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - if (this.hivePos == null) { - return false; - } else { -+ if (!this.level.isLoadedAndInBounds(hivePos)) return false; // Paper - BlockEntity tileentity = this.level.getBlockEntity(this.hivePos); - - return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby(); -@@ -390,6 +391,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - } - - private boolean doesHiveHaveSpace(BlockPos pos) { -+ if (!this.level.isLoadedAndInBounds(pos)) return false; // Paper - BlockEntity tileentity = this.level.getBlockEntity(pos); - - return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false; -@@ -632,6 +634,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - @Override - public boolean canBeeUse() { - if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerThan((Position) Bee.this.position(), 2.0D)) { -+ if (!Bee.this.level.isLoadedAndInBounds(Bee.this.hivePos)) return false; // Paper - BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos); - - if (tileentity instanceof BeehiveBlockEntity) { -@@ -655,6 +658,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - - @Override - public void start() { -+ if (!Bee.this.level.isLoadedAndInBounds(Bee.this.hivePos)) return; // Paper - BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos); - - if (tileentity instanceof BeehiveBlockEntity) { diff --git a/Remapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/Remapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch deleted file mode 100644 index 720e9dcff9..0000000000 --- a/Remapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 01:42:39 -0400 -Subject: [PATCH] Prevent Double PlayerChunkMap adds crashing server - -Suspected case would be around the technique used in .stopRiding -Stack will identify any causer of this and warn instead of crashing. - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 6da406c8403797a1cd9276ac06577c3c080a8a22..e6eeca5834a164d87f5b0e564fe6237902edaa6a 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1501,6 +1501,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - protected void addEntity(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot -+ // Paper start - ignore and warn about illegal addEntity calls instead of crashing server -+ if (!entity.valid || entity.level != this.level || this.entityMap.containsKey(entity.getId())) { -+ new Throwable("[ERROR] Illegal PlayerChunkMap::addEntity for world " + this.level.getWorld().getName() -+ + ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : "")) -+ .printStackTrace(); -+ return; -+ } -+ // Paper end - if (!(entity instanceof EnderDragonPart)) { - EntityType entitytypes = entity.getType(); - int i = entitytypes.clientTrackingRange() * 16; -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index c5dc41a3cf499038bd33451a189913cd3978b230..5127bce423a83711cea94e387b3ae7866215ded5 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1525,7 +1525,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - } - -- this.getChunkSource().addEntity(entity); -+ // this.getChunkProvider().addEntity(entity); // Paper - moved down below valid=true - // CraftBukkit start - SPIGOT-5278 - if (entity instanceof Drowned) { - this.navigations.add(((Drowned) entity).waterNavigation); -@@ -1536,6 +1536,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.navigations.add(((Mob) entity).getNavigation()); - } - entity.valid = true; // CraftBukkit -+ this.getChunkSource().addEntity(entity); // Paper - from above to be below valid=true - // Paper start - Set origin location when the entity is being added to the world - if (entity.origin == null) { - entity.origin = entity.getBukkitEntity().getLocation(); diff --git a/Remapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch b/Remapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch deleted file mode 100644 index 58edb5460d..0000000000 --- a/Remapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 02:37:57 -0400 -Subject: [PATCH] Optimize Collision to not load chunks - -The collision code takes an AABB and generates a cuboid of checks rather -than a cylinder, so at high velocity this can generate a lot of chunk checks. - -Treat an unloaded chunk as a collision for entities, and also for players if -the "prevent moving into unloaded chunks" setting is enabled. - -If that serting is not enabled, collisions will be ignored for players, since -movement will load only the chunk the player enters anyways and avoids loading -massive amounts of surrounding chunks due to large AABB lookups. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index dfdde9722bc0d83916779014b7718eef2c01b3db..86c5549196a4e9011c5240e7918b466c299be4a3 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -59,12 +59,23 @@ import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.PlayerAdvancements; - import net.minecraft.server.ServerScoreboard; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.ServerPlayerGameMode; -+import net.minecraft.server.level.TicketType; -+import net.minecraft.server.network.ServerGamePacketListenerImpl; -+import net.minecraft.server.network.ServerLoginPacketListenerImpl; -+import net.minecraft.sounds.SoundEvents; -+import net.minecraft.sounds.SoundSource; -+import net.minecraft.stats.ServerStatsCounter; -+import net.minecraft.stats.Stats; - import net.minecraft.tags.BlockTags; - import net.minecraft.tags.Tag; - import net.minecraft.util.Mth; - import net.minecraft.world.effect.MobEffectInstance; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.GameType; - import net.minecraft.world.level.Level; -@@ -90,15 +101,6 @@ import io.papermc.paper.adventure.PaperAdventure; // Paper - import com.google.common.base.Predicate; - import com.google.common.collect.Iterables; - import net.minecraft.server.dedicated.DedicatedServer; --import net.minecraft.server.level.ServerLevel; --import net.minecraft.server.level.ServerPlayer; --import net.minecraft.server.level.ServerPlayerGameMode; --import net.minecraft.server.network.ServerGamePacketListenerImpl; --import net.minecraft.server.network.ServerLoginPacketListenerImpl; --import net.minecraft.sounds.SoundEvents; --import net.minecraft.sounds.SoundSource; --import net.minecraft.stats.ServerStatsCounter; --import net.minecraft.stats.Stats; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - -@@ -805,6 +807,7 @@ public abstract class PlayerList { - entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - // CraftBukkit end - -+ worldserver1.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, new ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper - while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < 256.0D) { - entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 7e198b94f349d4c4d61502f5ad8c60686800d88f..b8dcc91a191f25ca578e0858abf6c1b874fee15d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -168,6 +168,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - private CraftEntity bukkitEntity; - - ChunkMap.TrackedEntity tracker; // Paper -+ public boolean collisionLoadChunks = false; // Paper - public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { -diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java -index d9e69195ee0af4dfb90bf0e8f4cc65e63f7ecf5b..1b52f2a0ce9cb847d7d57b38f4b8b6bed8de2cd9 100644 ---- a/src/main/java/net/minecraft/world/level/CollisionGetter.java -+++ b/src/main/java/net/minecraft/world/level/CollisionGetter.java -@@ -54,7 +54,9 @@ public interface CollisionGetter extends BlockGetter { - } - - default boolean noCollision(@Nullable Entity entity, AABB axisalignedbb, Predicate predicate) { -+ try { if (entity != null) entity.collisionLoadChunks = true; // Paper - return this.getCollisions(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty); -+ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper - } - - Stream getEntityCollisions(@Nullable Entity entity, AABB axisalignedbb, Predicate predicate); -diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -index 7208c61da48ce5e735810b6268490584e1d5c260..feca9ff34936686c0665ae0dbc926869087df3a7 100644 ---- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -+++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -@@ -7,6 +7,9 @@ import java.util.function.Consumer; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Cursor3D; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.WorldGenRegion; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.block.Blocks; -@@ -21,13 +24,13 @@ import net.minecraft.world.phys.shapes.VoxelShape; - public class CollisionSpliterator extends AbstractSpliterator { - - @Nullable -- private final Entity source; -+ private final Entity source; final Entity getEntity() { return this.source; } // Paper - OBFHELPER - private final AABB box; - private final CollisionContext context; - private final Cursor3D cursor; -- private final BlockPos.MutableBlockPos pos; -+ private final BlockPos.MutableBlockPos pos; final BlockPos.MutableBlockPos getMutablePos() { return this.pos; } // Paper - OBFHELPER - private final VoxelShape entityShape; -- private final CollisionGetter collisionGetter; -+ private final CollisionGetter collisionGetter; final CollisionGetter getCollisionAccess() { return this.collisionGetter; } // Paper - OBFHELPER - private boolean needsBorderCheck; - private final BiPredicate predicate; - -@@ -64,23 +67,37 @@ public class CollisionSpliterator extends AbstractSpliterator { - boolean collisionCheck(Consumer consumer) { - while (true) { - if (this.cursor.advance()) { -- int i = this.cursor.nextX(); -- int j = this.cursor.nextY(); -- int k = this.cursor.nextZ(); -+ int i = this.cursor.nextX(); final int x = i; -+ int j = this.cursor.nextY(); final int y = j; -+ int k = this.cursor.nextZ(); final int z = k; - int l = this.cursor.getNextType(); - - if (l == 3) { - continue; - } - -- BlockGetter iblockaccess = this.getChunk(i, k); -- -- if (iblockaccess == null) { -+ // Paper start - ensure we don't load chunks -+ Entity entity = this.getEntity(); -+ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getMutablePos(); -+ boolean far = entity != null && MCUtil.distanceSq(entity.getX(), y, entity.getZ(), x, y, z) > 14; -+ blockposition_mutableblockposition.setValues(x, y, z); -+ -+ boolean isRegionLimited = this.getCollisionAccess() instanceof WorldGenRegion; -+ BlockState iblockdata = isRegionLimited ? Blocks.VOID_AIR.defaultBlockState() : ((!far && entity instanceof ServerPlayer) || (entity != null && entity.collisionLoadChunks) -+ ? this.getCollisionAccess().getBlockState(blockposition_mutableblockposition) -+ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition) -+ ); -+ -+ if (iblockdata == null) { -+ if (!(entity instanceof ServerPlayer) || entity.level.paperConfig.preventMovingIntoUnloadedChunks) { -+ VoxelShape voxelshape3 = Shapes.of(far ? entity.getBoundingBox() : new AABB(new BlockPos(x, y, z))); -+ consumer.accept(voxelshape3); -+ return true; -+ } - continue; - } -- -- this.pos.set(i, j, k); -- BlockState iblockdata = iblockaccess.getBlockState(this.pos); -+ // Paper - moved up -+ // Paper end - - if (!this.predicate.test(iblockdata, this.pos) || l == 1 && !iblockdata.hasLargeCollisionShape() || l == 2 && !iblockdata.is(Blocks.MOVING_PISTON)) { - continue; -diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -index fa2942d0b0424390daee2121f8959034c5352e0b..c14d5ebe16a693834ed218af8f737714065b2e17 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -@@ -249,7 +249,8 @@ public final class Shapes { - - if (k2 < 3) { - blockposition_mutableblockposition.set(enumaxiscycle1, i2, j2, l1); -- BlockState iblockdata = world.getBlockState(blockposition_mutableblockposition); -+ BlockState iblockdata = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper -+ if (iblockdata == null) return 0.0D; // Paper - - if ((k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { - initial = iblockdata.getCollisionShape((BlockGetter) world, blockposition_mutableblockposition, context).collide(enumdirection_enumaxis2, box.move((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), initial); diff --git a/Remapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch b/Remapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch deleted file mode 100644 index b748ace1a1..0000000000 --- a/Remapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 17:16:48 -0400 -Subject: [PATCH] Don't tick dead players - -Causes sync chunk loads and who knows what all else. -This is safe because Spectators are skipped in unloaded chunks too in vanilla. - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index a469016c43251f16913a365c4131b2448eaa4c48..286b75a27103a084a9f9d79a90716ebcad65d813 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -606,7 +606,7 @@ public class ServerPlayer extends Player implements ContainerListener { - - public void doTick() { - try { -- if (!this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { -+ if (valid && !this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) - super.tick(); - } - diff --git a/Remapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch b/Remapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch deleted file mode 100644 index 3e2b8e5352..0000000000 --- a/Remapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 19:31:16 -0400 -Subject: [PATCH] Dead Player's shouldn't be able to move - -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 0685920073a6a2b2c6a80018d0c9009b2ef860c4..32f1b180e82f41f3ce1b49ea7d67b7d55d2b9ca7 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1046,7 +1046,7 @@ public abstract class Player extends LivingEntity { - - @Override - protected boolean isImmobile() { -- return super.isImmobile() || this.isSleeping(); -+ return super.isImmobile() || this.isSleeping() || removed || !valid; // Paper - player's who are dead or not in a world shouldn't move... - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/Remapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch deleted file mode 100644 index a211d40a2c..0000000000 --- a/Remapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch +++ /dev/null @@ -1,294 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 8 Apr 2020 03:06:30 -0400 -Subject: [PATCH] Optimize PlayerChunkMap memory use for visibleChunks - -No longer clones visible chunks which is causing massive memory -allocation issues, likely the source of Humongous Objects on large servers. - -Instead we just synchronize, clear and rebuild, reusing the same object buffers -as before with only 2 small objects created (FastIterator/MapEntry) - -This should result in siginificant memory use reduction and improved GC behavior. - -diff --git a/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f6ff4d8132a95895680f5bc81f8f873e78f0bbdb ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java -@@ -0,0 +1,39 @@ -+package com.destroystokyo.paper.util.map; -+ -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+ -+public class Long2ObjectLinkedOpenHashMapFastCopy extends Long2ObjectLinkedOpenHashMap { -+ -+ public void copyFrom(Long2ObjectLinkedOpenHashMapFastCopy map) { -+ if (key.length != map.key.length) { -+ key = null; -+ key = new long[map.key.length]; -+ } -+ if (value.length != map.value.length) { -+ value = null; -+ //noinspection unchecked -+ value = (V[]) new Object[map.value.length]; -+ } -+ if (link.length != map.link.length) { -+ link = null; -+ link = new long[map.link.length]; -+ } -+ System.arraycopy(map.key, 0, this.key, 0, map.key.length); -+ System.arraycopy(map.value, 0, this.value, 0, map.value.length); -+ System.arraycopy(map.link, 0, this.link, 0, map.link.length); -+ this.size = map.size; -+ this.mask = map.mask; -+ this.first = map.first; -+ this.last = map.last; -+ this.n = map.n; -+ this.maxFill = map.maxFill; -+ this.containsNullKey = map.containsNullKey; -+ } -+ -+ @Override -+ public Long2ObjectLinkedOpenHashMapFastCopy clone() { -+ Long2ObjectLinkedOpenHashMapFastCopy clone = (Long2ObjectLinkedOpenHashMapFastCopy) super.clone(); -+ clone.copyFrom(this); -+ return clone; -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 99c3337eec552ba47d3b8b2d8feaaa80acf2a86f..9abef8550a89df5e15ac28de1a5549d064f29122 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -616,7 +616,7 @@ public final class MCUtil { - - ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); - ChunkMap chunkMap = world.getChunkSource().chunkMap; -- Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunkMap; -+ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.getVisibleChunks(); - DistanceManager chunkMapDistance = chunkMap.distanceManager; - List allChunks = new ArrayList<>(visibleChunks.values()); - List players = world.players; -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc08174003f4a 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -104,8 +104,33 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - private static final Logger LOGGER = LogManager.getLogger(); - public static final int MAX_CHUNK_DISTANCE = 33 + ChunkStatus.maxDistance(); -- public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); -- public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; -+ // Paper start - faster copying -+ public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<>(); // Paper - faster copying -+ public final Long2ObjectLinkedOpenHashMap visibleChunkMap = new ProtectedVisibleChunksMap(); // Paper - faster copying -+ -+ private class ProtectedVisibleChunksMap extends com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy { -+ @Override -+ public ChunkHolder put(long k, ChunkHolder playerChunk) { -+ throw new UnsupportedOperationException("Updating visible Chunks"); -+ } -+ -+ @Override -+ public ChunkHolder remove(long k) { -+ throw new UnsupportedOperationException("Removing visible Chunks"); -+ } -+ -+ @Override -+ public ChunkHolder get(long k) { -+ return ChunkMap.this.getVisibleChunkIfPresent(k); -+ } -+ -+ public ChunkHolder safeGet(long k) { -+ return super.get(k); -+ } -+ } -+ // Paper end -+ public final com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy pendingVisibleChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy(); // Paper - this is used if the visible chunks is updated while iterating only -+ public transient com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy visibleChunksClone; // Paper - used for async access of visible chunks, clone and cache only when needed - private final Long2ObjectLinkedOpenHashMap pendingUnloads; - public final LongSet entitiesInLevel; // Paper - private -> public - public final ServerLevel level; -@@ -178,7 +203,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag); -- this.visibleChunkMap = this.updatingChunkMap.clone(); -+ //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning - this.pendingUnloads = new Long2ObjectLinkedOpenHashMap(); - this.entitiesInLevel = new LongOpenHashSet(); - this.toDrop = new LongOpenHashSet(); -@@ -270,9 +295,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return (ChunkHolder) this.updatingChunkMap.get(pos); - } - -+ // Paper start - remove cloning of visible chunks unless accessed as a collection async -+ private static final boolean DEBUG_ASYNC_VISIBLE_CHUNKS = Boolean.getBoolean("paper.debug-async-visible-chunks"); -+ private boolean isIterating = false; -+ private boolean hasPendingVisibleUpdate = false; -+ public void forEachVisibleChunk(java.util.function.Consumer consumer) { -+ org.spigotmc.AsyncCatcher.catchOp("forEachVisibleChunk"); -+ boolean prev = isIterating; -+ isIterating = true; -+ try { -+ for (ChunkHolder value : this.visibleChunkMap.values()) { -+ consumer.accept(value); -+ } -+ } finally { -+ this.isIterating = prev; -+ if (!this.isIterating && this.hasPendingVisibleUpdate) { -+ ((ProtectedVisibleChunksMap)this.visibleChunkMap).copyFrom(this.pendingVisibleChunks); -+ this.pendingVisibleChunks.clear(); -+ this.hasPendingVisibleUpdate = false; -+ } -+ } -+ } -+ public Long2ObjectLinkedOpenHashMap getVisibleChunks() { -+ if (Thread.currentThread() == this.level.thread) { -+ return this.visibleChunkMap; -+ } else { -+ synchronized (this.visibleChunkMap) { -+ if (DEBUG_ASYNC_VISIBLE_CHUNKS) new Throwable("Async getVisibleChunks").printStackTrace(); -+ if (this.visibleChunksClone == null) { -+ this.visibleChunksClone = this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.clone() : ((ProtectedVisibleChunksMap)this.visibleChunkMap).clone(); -+ } -+ return this.visibleChunksClone; -+ } -+ } -+ } -+ // Paper end -+ - @Nullable - public ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public -- return (ChunkHolder) this.visibleChunkMap.get(pos); -+ // Paper start - mt safe get -+ if (Thread.currentThread() != this.level.thread) { -+ synchronized (this.visibleChunkMap) { -+ return (ChunkHolder) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(pos) : ((ProtectedVisibleChunksMap)this.visibleChunkMap).safeGet(pos)); -+ } -+ } -+ return (ChunkHolder) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(pos) : ((ProtectedVisibleChunksMap)this.visibleChunkMap).safeGet(pos)); -+ // Paper end - } - - protected IntSupplier getChunkQueueLevel(long pos) { -@@ -460,8 +528,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper end - - protected void saveAllChunks(boolean flush) { -+ Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) - if (flush) { -- List list = (List) this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); -+ List list = (List) visibleChunks.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); // Paper - remove cloning of visible chunks - MutableBoolean mutableboolean = new MutableBoolean(); - - do { -@@ -489,7 +558,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // this.i(); // Paper - nuke IOWorker - ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); - } else { -- this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { -+ visibleChunks.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { - ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error - - if (ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk) { -@@ -660,7 +729,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - if (!this.modified) { - return false; - } else { -- this.visibleChunkMap = this.updatingChunkMap.clone(); -+ // Paper start - stop cloning visibleChunks -+ synchronized (this.visibleChunkMap) { -+ if (isIterating) { -+ hasPendingVisibleUpdate = true; -+ this.pendingVisibleChunks.copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunkMap); -+ } else { -+ hasPendingVisibleUpdate = false; -+ this.pendingVisibleChunks.clear(); -+ ((ProtectedVisibleChunksMap)this.visibleChunkMap).copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunkMap); -+ this.visibleChunksClone = null; -+ } -+ } -+ // Paper end -+ - this.modified = false; - return true; - } -@@ -1139,12 +1221,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - protected Iterable getChunks() { -- return Iterables.unmodifiableIterable(this.visibleChunkMap.values()); -+ return Iterables.unmodifiableIterable(this.getVisibleChunks().values()); // Paper - } - - void dumpChunks(Writer writer) throws IOException { - CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("entity_count").addColumn("block_entity_count").build(writer); -- ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunkMap.long2ObjectEntrySet().iterator(); -+ ObjectBidirectionalIterator objectbidirectionaliterator = this.getVisibleChunks().long2ObjectEntrySet().iterator(); // Paper - - while (objectbidirectionaliterator.hasNext()) { - Entry entry = (Entry) objectbidirectionaliterator.next(); -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index e2b1541042bceac965411e3176d08c61f217c07f..f5de878020be9465739fba07fd7dea46b0a3ae34 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -782,7 +782,7 @@ public class ServerChunkCache extends ChunkSource { - }; - // Paper end - this.level.timings.chunkTicks.startTiming(); // Paper -- this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... -+ this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping - Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); - - if (optional.isPresent()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index fb74bdcf4c2935b56e92717cc5a1504fbc853d0a..1a839242e359fa32f32d0e571c6e918ac39642e9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -276,6 +276,7 @@ public class CraftWorld implements World { - return ret; - } - public int getTileEntityCount() { -+ return net.minecraft.server.MCUtil.ensureMain(() -> { - // We don't use the full world tile entity list, so we must iterate chunks - Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; - int size = 0; -@@ -287,11 +288,13 @@ public class CraftWorld implements World { - size += chunk.blockEntities.size(); - } - return size; -+ }); - } - public int getTickableTileEntityCount() { - return world.tickableBlockEntities.size(); - } - public int getChunkCount() { -+ return net.minecraft.server.MCUtil.ensureMain(() -> { - int ret = 0; - - for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { -@@ -300,7 +303,7 @@ public class CraftWorld implements World { - } - } - -- return ret; -+ return ret; }); - } - public int getPlayerCount() { - return world.players.size(); -@@ -425,6 +428,14 @@ public class CraftWorld implements World { - - @Override - public Chunk[] getLoadedChunks() { -+ // Paper start -+ if (Thread.currentThread() != world.getLevel().thread) { -+ synchronized (world.getChunkSource().chunkMap.visibleChunkMap) { -+ Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; -+ return chunks.values().stream().map(ChunkHolder::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new); -+ } -+ } -+ // Paper end - Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; - return chunks.values().stream().map(ChunkHolder::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new); - } diff --git a/Remapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch b/Remapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch deleted file mode 100644 index f5ba659507..0000000000 --- a/Remapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 8 Apr 2020 21:24:05 -0400 -Subject: [PATCH] Increase Light Queue Size - -Wiz mentioned that large WorldEdit operations cause light to run on -main thread. The queue was small, set to 5.. this bumps it to 20 -but makes it configurable per-world. - -The main risk of increasing this higher is during shutdown, some -queued light updates may be lost because mojang did not flush the -light engine on shutdown... - -The queue size only puts a cap on max loss, doesn't solve that problem. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1..cd248eb6be663e8be33f2c3c6b06b77b6d5753a4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -620,4 +620,9 @@ public class PaperWorldConfig { - private void zombieVillagerInfectionChance() { - zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); - } -+ -+ public int lightQueueSize = 20; -+ private void lightQueueSize() { -+ lightQueueSize = getInt("light-queue-size", lightQueueSize); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e33189dc8375a3034910087654607fb531061636..11c6e8ce10c53dcb639145fbda32c5426eb6b3d9 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -775,7 +775,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Thu, 9 Apr 2020 00:09:26 -0400 -Subject: [PATCH] Mid Tick Chunk Tasks - Speed up processing of chunk loads and - generation - -Credit to Spotted for the idea - -A lot of the new chunk system requires constant back and forth the main thread -to handle priority scheduling and ensuring conflicting tasks do not run at the -same time. - -The issue is, these queues are only checked at either: - -A) Sync Chunk Loads -B) End of Tick while sleeping - -This results in generating chunks sitting waiting for a full tick to -complete before it will even start the next unit of work to do. - -Additionally, this also delays loading of chunks until this same timing. - -We will now periodically poll the chunk task queues throughout the tick, -looking for work to do. -We do this in a fair method that considers all worlds, not just the one being -ticked, so that each world can get 1 task procesed each before the next pass. - -In a view distance of 15, chunk loading performance was visually faster on the client. - -Flying at high speed in spectator mode was able to keep up with chunk loading (as long as they are already generated) - -diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -index be3a62f543a5fec4739c14821fe5a443c1fa3f5b..6bff5317939635b925bb41eb7a67d1fd95715078 100644 ---- a/src/main/java/co/aikar/timings/MinecraftTimings.java -+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -17,6 +17,7 @@ import java.util.Map; - public final class MinecraftTimings { - - public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); -+ public static final Timing midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks"); - public static final Timing playerListTimer = Timings.ofSafe("Player List"); - public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); - public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index da93d38fe63035e4ff198ada84a4431f52d97c01..ddbc8cb712c50038922eded75dd6ca85fe851078 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -410,4 +410,9 @@ public class PaperConfig { - log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); - } - } -+ -+ public static int midTickChunkTasks = 1000; -+ private static void midTickChunkTasks() { -+ midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b174dee62 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1055,6 +1055,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -+ midTickLoadChunks(); // will only do loads since we are still considered !canSleepForTick - return !this.canOversleep(); - }); - isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -@@ -1318,13 +1337,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Paper - safe iterator incase chunk loads, also no wrapping -+ final int[] chunksTicked = {0}; this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping - Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); - - if (optional.isPresent()) { -@@ -806,6 +809,7 @@ public class ServerChunkCache extends ChunkSource { - //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper - this.level.tickChunk(chunk, k); - //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper -+ if (chunksTicked[0]++ % 10 == 0) this.level.getServer().midTickLoadChunks(); // Paper - } - } - } -@@ -963,6 +967,41 @@ public class ServerChunkCache extends ChunkSource { - super.doRunTask(task); - } - -+ // Paper start -+ private long lastMidTickChunkTask = 0; -+ public boolean pollChunkLoadTasks() { -+ if (com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ServerChunkCache.this.level.asyncChunkTaskManager.pollNextChunkTask()) { -+ try { -+ ServerChunkCache.this.runDistanceManagerUpdates(); -+ } finally { -+ // from below: process pending Chunk loadCallback() and unloadCallback() after each run task -+ chunkMap.callbackExecutor.run(); -+ } -+ return true; -+ } -+ return false; -+ } -+ public void midTickLoadChunks() { -+ MinecraftServer server = ServerChunkCache.this.level.getServer(); -+ // always try to load chunks, restrain generation/other updates only. don't count these towards tick count -+ //noinspection StatementWithEmptyBody -+ while (pollChunkLoadTasks()) {} -+ -+ if (System.nanoTime() - lastMidTickChunkTask < 200000) { -+ return; -+ } -+ -+ for (;server.midTickChunksTasksRan < com.destroystokyo.paper.PaperConfig.midTickChunkTasks && server.haveTime();) { -+ if (this.pollTask()) { -+ server.midTickChunksTasksRan++; -+ lastMidTickChunkTask = System.nanoTime(); -+ } else { -+ break; -+ } -+ } -+ } -+ // Paper end -+ - @Override - protected boolean pollTask() { - // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 5127bce423a83711cea94e387b3ae7866215ded5..4e75cc5e52a5295e32ccadb371702a405bb518bb 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -565,6 +565,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - timings.scheduledBlocks.stopTiming(); // Paper - -+ this.getServer().midTickLoadChunks(); // Paper - gameprofilerfiller.popPush("raid"); - this.timings.raids.startTiming(); // Paper - timings - this.raids.tick(); -@@ -573,6 +574,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - timings.doSounds.startTiming(); // Spigot - this.runBlockEvents(); - timings.doSounds.stopTiming(); // Spigot -+ this.getServer().midTickLoadChunks(); // Paper - this.handlingTick = false; - gameprofilerfiller.popPush("entities"); - boolean flag3 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players -@@ -639,6 +641,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - timings.entityTick.stopTiming(); // Spigot - - this.tickingEntities = false; -+ this.getServer().midTickLoadChunks(); // Paper - - Entity entity2; - -@@ -648,6 +651,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - timings.tickEntities.stopTiming(); // Spigot -+ this.getServer().midTickLoadChunks(); // Paper - this.tickBlockEntities(); - } - diff --git a/Remapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch b/Remapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch deleted file mode 100644 index 02f8b575b0..0000000000 --- a/Remapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 9 Apr 2020 21:20:33 -0400 -Subject: [PATCH] Don't move existing players to world spawn - -This can cause a nasty server lag the spawn chunks are not kept loaded -or they aren't finished loading yet, or if the world spawn radius is -larger than the keep loaded range. - -By skipping this, we avoid potential for a large spike on server start. - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 286b75a27103a084a9f9d79a90716ebcad65d813..162b1a8c6ab57aafa4f6deefc842755a8e14208e 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -251,7 +251,7 @@ public class ServerPlayer extends Player implements ContainerListener { - this.stats = server.getPlayerList().getStatisticManager(this); - this.advancements = server.getPlayerList().getPlayerAdvancements(this); - this.maxUpStep = 1.0F; -- this.fudgeSpawnLocation(world); -+ //this.c(worldserver); // Paper - don't move to spawn on login, only first join - this.textFilter = server.createTextFilterForPlayer(this); - - this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -@@ -303,6 +303,7 @@ public class ServerPlayer extends Player implements ContainerListener { - } - // CraftBukkit end - -+ public final void moveToSpawn(ServerLevel worldserver) { fudgeSpawnLocation(worldserver); } // Paper - OBFHELPER - private void fudgeSpawnLocation(ServerLevel world) { - BlockPos blockposition = world.getSpawn(); - -@@ -480,7 +481,7 @@ public class ServerPlayer extends Player implements ContainerListener { - position = Vec3.atCenterOf(((ServerLevel) world).getSpawn()); - } - this.level = world; -- this.setPos(position.x(), position.y(), position.z()); -+ this.setPosRaw(position.x(), position.y(), position.z()); // Paper - don't register to chunks yet - } - this.gameMode.setLevel((ServerLevel) world); - } -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 86c5549196a4e9011c5240e7918b466c299be4a3..30666fca36b683158ff60302684b5093f5536e24 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -204,6 +204,8 @@ public abstract class PlayerList { - worldserver1 = worldserver; - } - -+ if (nbttagcompound == null) player.moveToSpawn(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are.... -+ - player.setLevel(worldserver1); - player.gameMode.setLevel((ServerLevel) player.level); - String s1 = "local"; diff --git a/Remapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch b/Remapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch deleted file mode 100644 index 0f2cf4005e..0000000000 --- a/Remapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 5 Apr 2020 22:23:14 -0500 -Subject: [PATCH] Add tick times API and /mspt command - - -diff --git a/src/main/java/com/destroystokyo/paper/MSPTCommand.java b/src/main/java/com/destroystokyo/paper/MSPTCommand.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d0211d4f39f9d6af1d751ac66342b42cc6d7ba6d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/MSPTCommand.java -@@ -0,0 +1,64 @@ -+package com.destroystokyo.paper; -+ -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.ChatColor; -+import org.bukkit.Location; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+ -+import java.text.DecimalFormat; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collections; -+import java.util.List; -+ -+public class MSPTCommand extends Command { -+ private static final DecimalFormat DF = new DecimalFormat("########0.0"); -+ -+ public MSPTCommand(String name) { -+ super(name); -+ this.description = "View server tick times"; -+ this.usageMessage = "/mspt"; -+ this.setPermission("bukkit.command.mspt"); -+ } -+ -+ @Override -+ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { -+ return Collections.emptyList(); -+ } -+ -+ @Override -+ public boolean execute(CommandSender sender, String commandLabel, String[] args) { -+ if (!testPermission(sender)) return true; -+ -+ MinecraftServer server = MinecraftServer.getServer(); -+ -+ List times = new ArrayList<>(); -+ times.addAll(eval(server.tickTimes5s.getTimes())); -+ times.addAll(eval(server.tickTimes10s.getTimes())); -+ times.addAll(eval(server.tickTimes60s.getTimes())); -+ -+ sender.sendMessage("§6Server tick times §e(§7avg§e/§7min§e/§7max§e)§6 from last 5s§7,§6 10s§7,§6 1m§e:"); -+ sender.sendMessage(String.format("§6◴ %s§7/%s§7/%s§e, %s§7/%s§7/%s§e, %s§7/%s§7/%s", times.toArray())); -+ return true; -+ } -+ -+ private static List eval(long[] times) { -+ long min = Integer.MAX_VALUE; -+ long max = 0L; -+ long total = 0L; -+ for (long value : times) { -+ if (value > 0L && value < min) min = value; -+ if (value > max) max = value; -+ total += value; -+ } -+ double avgD = ((double) total / (double) times.length) * 1.0E-6D; -+ double minD = ((double) min) * 1.0E-6D; -+ double maxD = ((double) max) * 1.0E-6D; -+ return Arrays.asList(getColor(avgD), getColor(minD), getColor(maxD)); -+ } -+ -+ private static String getColor(double avg) { -+ return ChatColor.COLOR_CHAR + (avg >= 50 ? "c" : avg >= 40 ? "e" : "a") + DF.format(avg); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index ddbc8cb712c50038922eded75dd6ca85fe851078..78271b400c79578d043b20a5389a37b1bef9a70d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -69,6 +69,7 @@ public class PaperConfig { - - commands = new HashMap(); - commands.put("paper", new PaperCommand("paper")); -+ commands.put("mspt", new MSPTCommand("mspt")); - - version = getInt("config-version", 20); - set("config-version", 20); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 087f31ac0cc7816b1cbeffc45be6927b174dee62..99ee9de92264381a064066bc22bb66b4b2852a2e 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -217,6 +217,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Fri, 10 Apr 2020 21:24:12 -0400 -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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 4fa49b6bb26456d485f7f9193af560cb379e36f0..3f35e93b42efd03ff1002f09962fe3da51fb4c3f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2378,5 +2378,10 @@ public final class CraftServer implements Server { - public int getCurrentTick() { - return net.minecraft.server.MinecraftServer.currentTick; - } -+ -+ @Override -+ public boolean isStopping() { -+ return net.minecraft.server.MinecraftServer.getServer().hasStopped(); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch b/Remapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch deleted file mode 100644 index 4f867cd88c..0000000000 --- a/Remapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Thu, 30 Apr 2020 16:56:54 +0200 -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/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java -index b3838e709c1581c25da7738c9a03a827761845b1..05ace1d046e32a261e67bff5afc18c2d32e1a8aa 100644 ---- a/src/main/java/net/minecraft/nbt/NbtIo.java -+++ b/src/main/java/net/minecraft/nbt/NbtIo.java -@@ -51,6 +51,7 @@ public class NbtIo { - return nbttagcompound; - } - -+ public static CompoundTag readNBT(InputStream inputstream) throws IOException { return readCompressed(inputstream); } // Paper - OBFHELPER - public static CompoundTag readCompressed(InputStream stream) throws IOException { - DataInputStream datainputstream = new DataInputStream(new BufferedInputStream(new GZIPInputStream(stream))); - Throwable throwable = null; -@@ -106,6 +107,7 @@ public class NbtIo { - - } - -+ public static void writeNBT(CompoundTag nbttagcompound, OutputStream outputstream) throws IOException { writeCompressed(nbttagcompound, outputstream); } // Paper - OBFHELPER - public static void writeCompressed(CompoundTag tag, OutputStream stream) throws IOException { - DataOutputStream dataoutputstream = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(stream))); - Throwable throwable = null; -diff --git a/src/main/java/net/minecraft/util/datafix/DataFixers.java b/src/main/java/net/minecraft/util/datafix/DataFixers.java -index 950a4b67f9091af551ec1036ebeb943e3b335e91..dc4e2fc26e1bc2c545f955d30c052bb86e3ef614 100644 ---- a/src/main/java/net/minecraft/util/datafix/DataFixers.java -+++ b/src/main/java/net/minecraft/util/datafix/DataFixers.java -@@ -78,6 +78,7 @@ public class DataFixers { - return datafixerbuilder.build(Util.bootstrapExecutor()); - } - -+ public static DataFixer getDataFixer() { return getDataFixer(); } // Paper - OBFHELPER - public static DataFixer getDataFixer() { - return DataFixers.DATA_FIXER; - } -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index ac996d581925c8f92832009945c766962e5b51c5..458cdfbeac9d757c9721acd4557a548affa0ede1 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -196,6 +196,7 @@ public final class ItemStack { - this.updateEmptyCacheFlag(); - } - -+ public static ItemStack fromCompound(CompoundTag nbttagcompound) { return of(nbttagcompound); } // Paper - OBFHELPER - public static ItemStack of(CompoundTag tag) { - try { - return new ItemStack(tag); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 86b319337fc41a09dd45df466df60cadaed1343f..a5a5038a84434e69fda8f6b41d2f00b4989e25ae 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -378,6 +378,46 @@ public final class CraftMagicNumbers implements UnsafeValues { - public boolean isSupportedApiVersion(String apiVersion) { - return apiVersion != null && SUPPORTED_API.contains(apiVersion); - } -+ -+ @Override -+ public byte[] serializeItem(ItemStack item) { -+ Preconditions.checkNotNull(item, "null cannot be serialized"); -+ Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized"); -+ -+ java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); -+ CompoundTag compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).getHandle() : CraftItemStack.asNMSCopy(item)).save(new CompoundTag()); -+ compound.putInt("DataVersion", getDataVersion()); -+ try { -+ net.minecraft.nbt.NbtIo.writeNBT( -+ compound, -+ outputStream -+ ); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return outputStream.toByteArray(); -+ } -+ -+ @Override -+ public ItemStack deserializeItem(byte[] data) { -+ Preconditions.checkNotNull(data, "null cannot be deserialized"); -+ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing"); -+ -+ try { -+ CompoundTag compound = net.minecraft.nbt.NbtIo.readNBT( -+ new java.io.ByteArrayInputStream(data) -+ ); -+ int dataVersion = compound.getInt("DataVersion"); -+ -+ Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); -+ Dynamic converted = DataFixers.getDataFixer().update(References.ITEM_STACK, new Dynamic(NbtOps.INSTANCE, compound), dataVersion, getDataVersion()); -+ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.fromCompound((CompoundTag) converted.getValue())); -+ } catch (IOException ex) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ex); -+ throw new RuntimeException(); -+ } -+ } - // Paper end - - /** diff --git a/Remapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch b/Remapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch deleted file mode 100644 index 019eef698e..0000000000 --- a/Remapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 17:53:29 -0700 -Subject: [PATCH] Remove streams from Mob AI System - -The streams hurt performance and allocate tons of garbage, so -replace them with the standard iterator. - -Also optimise the stream.anyMatch statement to move to a bitset -where we can replace the call with a single bitwise operation. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -index 558dd72c47930f6993952467f83b5a54ead95d92..acc6306d659cd65a043d12cd42dcbaf55aaf5250 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -@@ -1,10 +1,12 @@ - package net.minecraft.world.entity.ai.goal; - -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector - import java.util.EnumSet; - - public abstract class Goal { - -- private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); -+ private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. -+ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector - - public Goal() {} - -@@ -28,16 +30,20 @@ public abstract class Goal { - public void tick() {} - - public void setFlags(EnumSet controls) { -- this.flags.clear(); -- this.flags.addAll(controls); -+ // Paper start - remove streams from pathfindergoalselector -+ this.goalTypes.clear(); -+ this.goalTypes.addAllUnchecked(controls); -+ // Paper end - remove streams from pathfindergoalselector - } - - public String toString() { - return this.getClass().getSimpleName(); - } - -- public EnumSet getFlags() { -- return this.flags; -+ // Paper start - remove streams from pathfindergoalselector -+ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { -+ return this.goalTypes; -+ // Paper end - remove streams from pathfindergoalselector - } - - public static enum Flag { -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -index 9bd2ee05a0de6678ad8933a8ffbe0ae66bd073b4..5da2d780c17522e07c733a5e23b17ec760c7b342 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -@@ -1,8 +1,10 @@ - package net.minecraft.world.entity.ai.goal; - -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector - import com.google.common.collect.Sets; - import java.util.EnumMap; - import java.util.EnumSet; -+import java.util.Iterator; // Paper - remove streams from pathfindergoalselector - import java.util.Map; - import java.util.Set; - import java.util.function.Supplier; -@@ -28,7 +30,8 @@ public class GoalSelector { - private final Map lockedFlags = new EnumMap(Goal.Flag.class); - private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER - private final Supplier profiler; -- private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); -+ private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. -+ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector - private int newGoalRate = 3;private int getTickRate() { return newGoalRate; } // Paper - OBFHELPER - private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO - -@@ -56,35 +59,38 @@ public class GoalSelector { - // Paper end - - public void removeGoal(Goal goal) { -- this.availableGoals.stream().filter((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.getGoal() == goal; -- }).filter(WrappedGoal::isRunning).forEach(WrappedGoal::stop); -- this.availableGoals.removeIf((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.getGoal() == goal; -- }); -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { -+ WrappedGoal goalWrapped = iterator.next(); -+ if (goalWrapped.getGoal() != goal) { -+ continue; -+ } -+ if (goalWrapped.isRunning()) { -+ goalWrapped.stop(); -+ } -+ iterator.remove(); -+ } -+ // Paper end - remove streams from pathfindergoalselector - } - -+ private static final Goal.Flag[] PATHFINDER_GOAL_TYPES = Goal.Flag.values(); // Paper - remove streams from pathfindergoalselector -+ - public void tick() { - ProfilerFiller gameprofilerfiller = (ProfilerFiller) this.profiler.get(); - - gameprofilerfiller.push("goalCleanup"); -- this.getRunningGoals().filter((pathfindergoalwrapped) -> { -- boolean flag; -- -- if (pathfindergoalwrapped.isRunning()) { -- Stream stream = pathfindergoalwrapped.getFlags().stream(); -- EnumSet enumset = this.disabledFlags; -- -- this.disabledFlags.getClass(); -- if (!stream.anyMatch(enumset::contains) && pathfindergoalwrapped.canContinueToUse()) { -- flag = false; -- return flag; -- } -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { -+ WrappedGoal wrappedGoal = iterator.next(); -+ if (!wrappedGoal.isRunning()) { -+ continue; - } -- -- flag = true; -- return flag; -- }).forEach(Goal::stop); -+ if (!this.goalTypes.hasCommonElements(wrappedGoal.getGoalTypes()) && wrappedGoal.canContinueToUse()) { -+ continue; -+ } -+ wrappedGoal.stop(); -+ } -+ // Paper end - remove streams from pathfindergoalselector - this.lockedFlags.forEach((pathfindergoal_type, pathfindergoalwrapped) -> { - if (!pathfindergoalwrapped.isRunning()) { - this.lockedFlags.remove(pathfindergoal_type); -@@ -93,30 +99,58 @@ public class GoalSelector { - }); - gameprofilerfiller.pop(); - gameprofilerfiller.push("goalUpdate"); -- this.availableGoals.stream().filter((pathfindergoalwrapped) -> { -- return !pathfindergoalwrapped.isRunning(); -- }).filter((pathfindergoalwrapped) -> { -- Stream stream = pathfindergoalwrapped.getFlags().stream(); -- EnumSet enumset = this.disabledFlags; -- -- this.disabledFlags.getClass(); -- return stream.noneMatch(enumset::contains); -- }).filter((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.getFlags().stream().allMatch((pathfindergoal_type) -> { -- return ((WrappedGoal) this.lockedFlags.getOrDefault(pathfindergoal_type, GoalSelector.NO_GOAL)).canBeReplacedBy(pathfindergoalwrapped); -- }); -- }).filter(WrappedGoal::canUse).forEach((pathfindergoalwrapped) -> { -- pathfindergoalwrapped.getFlags().forEach((pathfindergoal_type) -> { -- WrappedGoal pathfindergoalwrapped1 = (WrappedGoal) this.lockedFlags.getOrDefault(pathfindergoal_type, GoalSelector.NO_GOAL); -- -- pathfindergoalwrapped1.stop(); -- this.lockedFlags.put(pathfindergoal_type, pathfindergoalwrapped); -- }); -- pathfindergoalwrapped.start(); -- }); -+ // Paper start - remove streams from pathfindergoalselector -+ goal_update_loop: for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { -+ WrappedGoal wrappedGoal = iterator.next(); -+ if (wrappedGoal.isRunning()) { -+ continue; -+ } -+ -+ OptimizedSmallEnumSet wrappedGoalSet = wrappedGoal.getGoalTypes(); -+ -+ if (this.goalTypes.hasCommonElements(wrappedGoalSet)) { -+ continue; -+ } -+ -+ long iterator1 = wrappedGoalSet.getBackingSet(); -+ int wrappedGoalSize = wrappedGoalSet.size(); -+ for (int i = 0; i < wrappedGoalSize; ++i) { -+ Goal.Flag type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; -+ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); -+ WrappedGoal wrapped = this.lockedFlags.getOrDefault(type, GoalSelector.NO_GOAL); -+ if (!wrapped.canBeReplacedBy(wrappedGoal)) { -+ continue goal_update_loop; -+ } -+ } -+ -+ if (!wrappedGoal.canUse()) { -+ continue; -+ } -+ -+ iterator1 = wrappedGoalSet.getBackingSet(); -+ wrappedGoalSize = wrappedGoalSet.size(); -+ for (int i = 0; i < wrappedGoalSize; ++i) { -+ Goal.Flag type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; -+ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); -+ WrappedGoal wrapped = this.lockedFlags.getOrDefault(type, GoalSelector.NO_GOAL); -+ -+ wrapped.stop(); -+ this.lockedFlags.put(type, wrappedGoal); -+ } -+ -+ wrappedGoal.start(); -+ } -+ // Paper end - remove streams from pathfindergoalselector - gameprofilerfiller.pop(); - gameprofilerfiller.push("goalTick"); -- this.getRunningGoals().forEach(WrappedGoal::tick); -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { -+ WrappedGoal wrappedGoal = iterator.next(); -+ if (wrappedGoal.isRunning()) { -+ wrappedGoal.tick(); -+ } -+ } -+ // Paper end - remove streams from pathfindergoalselector - gameprofilerfiller.pop(); - } - -@@ -125,11 +159,11 @@ public class GoalSelector { - } - - public void disableControlFlag(Goal.Flag control) { -- this.disabledFlags.add(control); -+ this.goalTypes.addUnchecked(control); // Paper - remove streams from pathfindergoalselector - } - - public void enableControlFlag(Goal.Flag control) { -- this.disabledFlags.remove(control); -+ this.goalTypes.removeUnchecked(control); // Paper - remove streams from pathfindergoalselector - } - - public void setControlFlag(Goal.Flag control, boolean enabled) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -index 81b4618a7979ee8dd25e1749c084de9262318ef4..984146b2b6eb3e498433b1c4971397848166d9c9 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -@@ -59,9 +59,10 @@ public class WrappedGoal extends Goal { - this.goal.setFlags(controls); - } - -- @Override -- public EnumSet getFlags() { -- return this.goal.getFlags(); -+ // Paper start - remove streams from pathfindergoalselector -+ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { -+ return this.goal.getGoalTypes(); -+ // Paper end - remove streams from pathfindergoalselector - } - - public boolean isRunning() { return this.isRunning(); } // Paper - OBFHELPER diff --git a/Remapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch b/Remapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch deleted file mode 100644 index 9fb51d1e35..0000000000 --- a/Remapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Apr 2020 21:23:42 -0400 -Subject: [PATCH] Delay unsafe actions until after entity ticking is done - -This will help prevent many cases of unregistering entities during entity ticking - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 4e75cc5e52a5295e32ccadb371702a405bb518bb..b9978d296b83e73d3395b8254c0e8ccd9b36d0fa 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -172,6 +172,16 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - public final List players = Lists.newArrayList(); // Paper - private -> public - public final ServerChunkCache chunkSource; // Paper - public - boolean tickingEntities; -+ // Paper start -+ List afterEntityTickingTasks = Lists.newArrayList(); -+ public void doIfNotEntityTicking(java.lang.Runnable run) { -+ if (tickingEntities) { -+ afterEntityTickingTasks.add(run); -+ } else { -+ run.run(); -+ } -+ } -+ // Paper end - private final MinecraftServer server; - public final PrimaryLevelData worldDataServer; // CraftBukkit - type - public boolean noSave; -@@ -641,6 +651,16 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - timings.entityTick.stopTiming(); // Spigot - - this.tickingEntities = false; -+ // Paper start -+ for (java.lang.Runnable run : this.afterEntityTickingTasks) { -+ try { -+ run.run(); -+ } catch (Exception e) { -+ LOGGER.error("Error in After Entity Ticking Task", e); -+ } -+ } -+ this.afterEntityTickingTasks.clear(); -+ // Paper end - this.getServer().midTickLoadChunks(); // Paper - - Entity entity2; diff --git a/Remapped-Spigot-Server-Patches/0435-Async-command-map-building.patch b/Remapped-Spigot-Server-Patches/0435-Async-command-map-building.patch deleted file mode 100644 index 87f32eb782..0000000000 --- a/Remapped-Spigot-Server-Patches/0435-Async-command-map-building.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Callahan -Date: Wed, 8 Apr 2020 02:42:14 -0500 -Subject: [PATCH] Async command map building - - -diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java -index 44f2e8a3741afc0e3c3bca3b0864e37ecf83e5d4..8154d9327c5411bbfea3bfa4d99d57feab764664 100644 ---- a/src/main/java/net/minecraft/commands/Commands.java -+++ b/src/main/java/net/minecraft/commands/Commands.java -@@ -29,6 +29,7 @@ import net.minecraft.network.chat.MutableComponent; - import net.minecraft.network.chat.TextComponent; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.network.protocol.game.ClientboundCommandsPacket; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.commands.AdvancementCommands; - import net.minecraft.server.commands.AttributeCommand; - import net.minecraft.server.commands.BanIpCommands; -@@ -328,25 +329,40 @@ public class Commands { - if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot - // CraftBukkit start - // Register Vanilla commands into builtRoot as before -+ // Paper start - Async command map building -+ java.util.concurrent.ForkJoinPool.commonPool().execute(() -> { -+ sendAsync(player); -+ }); -+ } -+ -+ private void sendAsync(ServerPlayer entityplayer) { -+ // Paper end - Async command map building - Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues - RootCommandNode vanillaRoot = new RootCommandNode(); - -- RootCommandNode vanilla = player.server.vanillaCommandDispatcher.getDispatcher().getRoot(); -+ RootCommandNode vanilla = entityplayer.server.vanillaCommandDispatcher.getDispatcher().getRoot(); - map.put(vanilla, vanillaRoot); -- this.fillUsableCommands(vanilla, vanillaRoot, player.createCommandSourceStack(), (Map) map); -+ this.fillUsableCommands(vanilla, vanillaRoot, entityplayer.createCommandSourceStack(), (Map) map); - - // Now build the global commands in a second pass - RootCommandNode rootcommandnode = new RootCommandNode(); - - map.put(this.dispatcher.getRoot(), rootcommandnode); -- this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, player.createCommandSourceStack(), (Map) map); -+ this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, entityplayer.createCommandSourceStack(), (Map) map); - - Collection bukkit = new LinkedHashSet<>(); - for (CommandNode node : rootcommandnode.getChildren()) { - bukkit.add(node.getName()); - } -+ // Paper start - Async command map building -+ MinecraftServer.getServer().execute(() -> { -+ runSync(entityplayer, bukkit, rootcommandnode); -+ }); -+ } - -- PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit)); -+ private void runSync(ServerPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { -+ // Paper end - Async command map building -+ PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); - event.getPlayer().getServer().getPluginManager().callEvent(event); - - // Remove labels that were removed during the event -@@ -356,7 +372,7 @@ public class Commands { - } - } - // CraftBukkit end -- player.connection.send(new ClientboundCommandsPacket(rootcommandnode)); -+ entityplayer.connection.send(new ClientboundCommandsPacket(rootcommandnode)); - } - - private void fillUsableCommands(CommandNode tree, CommandNode result, CommandSourceStack source, Map, CommandNode> resultNodes) { diff --git a/Remapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch b/Remapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch deleted file mode 100644 index 928b62d524..0000000000 --- a/Remapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch +++ /dev/null @@ -1,608 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 12 Apr 2020 15:50:48 -0400 -Subject: [PATCH] Improved Watchdog Support - -Forced Watchdog Crash support and Improve Async Shutdown - -If the request to shut down the server is received while we are in -a watchdog hang, immediately treat it as a crash and begin the shutdown -process. Shutdown process is now improved to also shutdown cleanly when -not using restart scripts either. - -If a server is deadlocked, a server owner can send SIGUP (or any other signal -the JVM understands to shut down as it currently does) and the watchdog -will no longer need to wait until the full timeout, allowing you to trigger -a close process and try to shut the server down gracefully, saving player and -world data. - -Previously there was no way to trigger this outside of waiting for a full watchdog -timeout, which may be set to a really long time... - -Additionally, fix everything to do with shutting the server down asynchronously. - -Previously, nearly everything about the process was fragile and unsafe. Main might -not have actually been frozen, and might still be manipulating state. - -Or, some reuest might ask main to do something in the shutdown but main is dead. - -Or worse, other things might start closing down items such as the Console or Thread Pool -before we are fully shutdown. - -This change tries to resolve all of these issues by moving everything into the stop -method and guaranteeing only one thread is stopping the server. - -We then issue Thread Death to the main thread of another thread initiates the stop process. -We have to ensure Thread Death propagates correctly though to stop main completely. - -This is to ensure that if main isn't truely stuck, it's not manipulating state we are trying to save. - -This also moves all plugins who register "delayed init" tasks to occur just before "Done" so they -are properly accounted for and wont trip watchdog on init. - -diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index 0b9e689d57705965721b5c55bc45d36657f360e4..dee00aac05f1acf050f05d4db557a08dd0f301c8 100644 ---- a/src/main/java/com/destroystokyo/paper/Metrics.java -+++ b/src/main/java/com/destroystokyo/paper/Metrics.java -@@ -92,7 +92,12 @@ public class Metrics { - * Starts the Scheduler which submits our data every 30 minutes. - */ - private void startSubmitting() { -- final Runnable submitTask = this::submitData; -+ final Runnable submitTask = () -> { -+ if (MinecraftServer.getServer().hasStopped()) { -+ return; -+ } -+ submitData(); -+ }; - - // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the - // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. -diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java -index 4008fbe506e74f2c463dc7b12f5dd0f3b6fc342d..766ab2fe536a2acccaec28e922ccf8993b0790dc 100644 ---- a/src/main/java/net/minecraft/CrashReport.java -+++ b/src/main/java/net/minecraft/CrashReport.java -@@ -257,6 +257,7 @@ public class CrashReport { - } - - public static CrashReport forThrowable(Throwable cause, String title) { -+ if (cause instanceof ThreadDeath) com.destroystokyo.paper.util.SneakyThrow.sneaky(cause); // Paper - while (cause instanceof CompletionException && cause.getCause() != null) { - cause = cause.getCause(); - } -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index c2f747226f10479c826849af898538610a2dd659..83f9f97586f8c0e9d228923e4fec6f121a6702e2 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -129,6 +129,7 @@ public class Util { - return Util.IO_POOL; - } - -+ public static void shutdownServerThreadPool() { shutdownExecutors(); } // Paper - OBFHELPER - public static void shutdownExecutors() { - shutdownExecutor(Util.BACKGROUND_EXECUTOR); - shutdownExecutor(Util.IO_POOL); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 99ee9de92264381a064066bc22bb66b4b2852a2e..e5ad635a480d32e7a10ee92c65cfc18a98beafad 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -269,7 +269,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) { - AtomicReference atomicreference = new AtomicReference(); - Thread thread = new Thread(() -> { -@@ -851,6 +854,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -+ world.tickingEntities = false; -+ }); -+ } -+ // Paper end - // CraftBukkit end - MinecraftServer.LOGGER.info("Stopping server"); - MinecraftTimings.stopServer(); // Paper -@@ -930,7 +951,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop {}; -+ } -+ // Paper end - return new TickTask(this.tickCount, runnable); - } - -@@ -1421,6 +1478,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { - CompletableFuture completablefuture; -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index b9978d296b83e73d3395b8254c0e8ccd9b36d0fa..bf4e50cd1d561456c033cda2d5c5487c5e3fe1eb 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -171,7 +171,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - private final Queue toAddAfterTick = Queues.newArrayDeque(); - public final List players = Lists.newArrayList(); // Paper - private -> public - public final ServerChunkCache chunkSource; // Paper - public -- boolean tickingEntities; -+ public boolean tickingEntities; // Paper - expose for watchdog - // Paper start - List afterEntityTickingTasks = Lists.newArrayList(); - public void doIfNotEntityTicking(java.lang.Runnable run) { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 30666fca36b683158ff60302684b5093f5536e24..984ac19dcab446531c816e365c7c149e2c49d567 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -503,7 +503,7 @@ public abstract class PlayerList { - cserver.getPluginManager().callEvent(playerQuitEvent); - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - -- entityplayer.doTick(); // SPIGOT-924 -+ if (server.isSameThread()) entityplayer.doTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) - // CraftBukkit end - - // Paper start - Remove from collideRule team if needed -diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -index a5ce61be7d6e85ac289730d9671e66a7190529f9..add18ba4833686ff51fbb280b0a5759f142b3f91 100644 ---- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -+++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -@@ -135,6 +135,7 @@ public abstract class BlockableEventLoop implements Processo - try { - task.run(); - } catch (Exception exception) { -+ if (exception.getCause() instanceof ThreadDeath) throw exception; // Paper - BlockableEventLoop.LOGGER.fatal("Error executing task on {}", this.name(), exception); - } - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 632f32405053fbcff2fd26fa99f98c6add9f9dc7..5860e7866724abd35bde2a5710d9c92799e5de67 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -858,6 +858,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - gameprofilerfiller.pop(); - } catch (Throwable throwable) { -+ if (throwable instanceof ThreadDeath) throw throwable; // Paper - // Paper start - Prevent tile entity and entity crashes - String msg = "TileEntity threw exception at " + tileentity.getLevel().getWorld().getName() + ":" + tileentity.getBlockPos().getX() + "," + tileentity.getBlockPos().getY() + "," + tileentity.getBlockPos().getZ(); - System.err.println(msg); -@@ -932,6 +933,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - try { - tickConsumer.accept(entity); - } catch (Throwable throwable) { -+ if (throwable instanceof ThreadDeath) throw throwable; // Paper - // Paper start - Prevent tile entity and entity crashes - String msg = "Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ(); - System.err.println(msg); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 3f35e93b42efd03ff1002f09962fe3da51fb4c3f..43c37e660a8a7f9d326ad38e66f9aa7c53c7b87c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1839,7 +1839,7 @@ public final class CraftServer implements Server { - - @Override - public boolean isPrimaryThread() { -- return Thread.currentThread().equals(console.serverThread); // Paper - Fix issues with detecting main thread properly -+ return Thread.currentThread().equals(console.serverThread) || Thread.currentThread().equals(net.minecraft.server.MinecraftServer.getServer().shutdownThread); // Paper - Fix issues with detecting main thread properly, the only time Watchdog will be used is during a crash shutdown which is a "try our best" scenario - } - - // Paper start -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index c519ceca6f7788ca7c5d74ad1001dbc09f62681c..c288b89bf5a22269823ba1d18af217032d7c6a36 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -12,6 +12,8 @@ import java.util.logging.Level; - import java.util.logging.Logger; - import joptsimple.OptionParser; - import joptsimple.OptionSet; -+import net.minecraft.util.ExceptionCollector; -+import net.minecraft.world.level.lighting.LayerLightEventListener; - import net.minecrell.terminalconsole.TerminalConsoleAppender; // Paper - - public class Main { -@@ -156,6 +158,36 @@ public class Main { - - OptionSet options = null; - -+ // Paper start - preload logger classes to avoid plugins mixing versions -+ tryPreloadClass("com.destroystokyo.paper.log.LogFullPolicy"); -+ tryPreloadClass("org.apache.logging.log4j.core.Core"); -+ tryPreloadClass("org.apache.logging.log4j.core.Appender"); -+ tryPreloadClass("org.apache.logging.log4j.core.ContextDataInjector"); -+ tryPreloadClass("org.apache.logging.log4j.core.Filter"); -+ tryPreloadClass("org.apache.logging.log4j.core.ErrorHandler"); -+ tryPreloadClass("org.apache.logging.log4j.core.LogEvent"); -+ tryPreloadClass("org.apache.logging.log4j.core.Logger"); -+ tryPreloadClass("org.apache.logging.log4j.core.LoggerContext"); -+ tryPreloadClass("org.apache.logging.log4j.core.LogEventListener"); -+ tryPreloadClass("org.apache.logging.log4j.core.AbstractLogEvent"); -+ tryPreloadClass("org.apache.logging.log4j.message.AsynchronouslyFormattable"); -+ tryPreloadClass("org.apache.logging.log4j.message.FormattedMessage"); -+ tryPreloadClass("org.apache.logging.log4j.message.ParameterizedMessage"); -+ tryPreloadClass("org.apache.logging.log4j.message.Message"); -+ tryPreloadClass("org.apache.logging.log4j.message.MessageFactory"); -+ tryPreloadClass("org.apache.logging.log4j.message.TimestampMessage"); -+ tryPreloadClass("org.apache.logging.log4j.message.SimpleMessage"); -+ tryPreloadClass("org.apache.logging.log4j.core.async.AsyncLogger"); -+ tryPreloadClass("org.apache.logging.log4j.core.async.AsyncLoggerContext"); -+ tryPreloadClass("org.apache.logging.log4j.core.async.AsyncQueueFullPolicy"); -+ tryPreloadClass("org.apache.logging.log4j.core.async.AsyncLoggerDisruptor"); -+ tryPreloadClass("org.apache.logging.log4j.core.async.RingBufferLogEvent"); -+ tryPreloadClass("org.apache.logging.log4j.core.async.DisruptorUtil"); -+ tryPreloadClass("org.apache.logging.log4j.core.async.RingBufferLogEventHandler"); -+ tryPreloadClass("org.apache.logging.log4j.core.impl.ThrowableProxy"); -+ tryPreloadClass("org.apache.logging.log4j.core.impl.ExtendedClassInfo"); -+ tryPreloadClass("org.apache.logging.log4j.core.impl.ExtendedStackTraceElement"); -+ // Paper end - try { - options = parser.parse(args); - } catch (joptsimple.OptionException ex) { -@@ -251,8 +283,64 @@ public class Main { - } catch (Throwable t) { - t.printStackTrace(); - } -+ // Paper start -+ // load some required classes to avoid errors during shutdown if jar is replaced -+ // also to guarantee our version loads over plugins -+ tryPreloadClass("com.destroystokyo.paper.util.SneakyThrow"); -+ tryPreloadClass("com.google.common.collect.Iterators$PeekingImpl"); -+ tryPreloadClass("com.google.common.collect.MapMakerInternalMap$Values"); -+ tryPreloadClass("com.google.common.collect.MapMakerInternalMap$ValueIterator"); -+ tryPreloadClass("com.google.common.collect.MapMakerInternalMap$WriteThroughEntry"); -+ tryPreloadClass("com.google.common.collect.Iterables"); -+ for (int i = 1; i <= 15; i++) { -+ tryPreloadClass("com.google.common.collect.Iterables$" + i, false); -+ } -+ tryPreloadClass("org.apache.commons.lang3.mutable.MutableBoolean"); -+ tryPreloadClass("org.apache.commons.lang3.mutable.MutableInt"); -+ tryPreloadClass("org.jline.terminal.impl.MouseSupport"); -+ tryPreloadClass("org.jline.terminal.impl.MouseSupport$1"); -+ tryPreloadClass("org.jline.terminal.Terminal$MouseTracking"); -+ tryPreloadClass("co.aikar.timings.TimingHistory"); -+ tryPreloadClass("co.aikar.timings.TimingHistory$MinuteReport"); -+ tryPreloadClass("io.netty.channel.AbstractChannelHandlerContext"); -+ tryPreloadClass("io.netty.channel.AbstractChannelHandlerContext$11"); -+ tryPreloadClass("io.netty.channel.AbstractChannelHandlerContext$12"); -+ tryPreloadClass("io.netty.channel.AbstractChannel$AbstractUnsafe$8"); -+ tryPreloadClass("io.netty.util.concurrent.DefaultPromise"); -+ tryPreloadClass("io.netty.util.concurrent.DefaultPromise$1"); -+ tryPreloadClass("io.netty.util.internal.PromiseNotificationUtil"); -+ tryPreloadClass("io.netty.util.internal.SystemPropertyUtil"); -+ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler"); -+ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler$1"); -+ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler$2"); -+ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler$3"); -+ tryPreloadClass("org.bukkit.craftbukkit.scheduler.CraftScheduler$4"); -+ tryPreloadClass("org.slf4j.helpers.MessageFormatter"); -+ tryPreloadClass("org.slf4j.helpers.FormattingTuple"); -+ tryPreloadClass("org.slf4j.helpers.BasicMarker"); -+ tryPreloadClass("org.slf4j.helpers.Util"); -+ tryPreloadClass("com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent"); -+ tryPreloadClass("com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent"); -+ // Minecraft, seen during saving -+ tryPreloadClass(LayerLightEventListener.DummyLightLayerEventListener.class.getName()); -+ tryPreloadClass(LayerLightEventListener.class.getName()); -+ tryPreloadClass(ExceptionCollector.class.getName()); -+ // Paper end -+ } -+ } -+ -+ // Paper start -+ private static void tryPreloadClass(String className) { -+ tryPreloadClass(className, true); -+ } -+ private static void tryPreloadClass(String className, boolean printError) { -+ try { -+ Class.forName(className); -+ } catch (ClassNotFoundException e) { -+ if (printError) System.err.println("An expected class " + className + " was not found for preloading: " + e.getMessage()); - } - } -+ // Paper end - - private static List asList(String... params) { - return Arrays.asList(params); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index 449e99d1b673870ed6892f6ab2c715a2db35c35d..c7ed6e0f8a989cec97700df2b15198c9c481c549 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -12,12 +12,27 @@ public class ServerShutdownThread extends Thread { - @Override - public void run() { - try { -+ // Paper start - try to shutdown on main -+ server.safeShutdown(false, false); -+ for (int i = 1000; i > 0 && !server.hasStopped(); i -= 100) { -+ Thread.sleep(100); -+ } -+ if (server.hasStopped()) { -+ while (!server.hasFullyShutdown) Thread.sleep(1000); -+ return; -+ } -+ // Looks stalled, close async - org.spigotmc.AsyncCatcher.enabled = false; // Spigot - org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper -+ server.forceTicks = true; - server.close(); -+ while (!server.hasFullyShutdown) Thread.sleep(1000); -+ } catch (InterruptedException e) { -+ e.printStackTrace(); -+ // Paper end - } finally { - try { -- net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender -+ //net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Move into stop - } catch (Exception e) { - } - } -diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index 6dab105cd7cc4340c031c395c0346d4731355d79..6498dc4c6630bfef1a52edf74d8574e5e4876720 100644 ---- a/src/main/java/org/spigotmc/RestartCommand.java -+++ b/src/main/java/org/spigotmc/RestartCommand.java -@@ -139,7 +139,7 @@ public class RestartCommand extends Command - // Paper end - - // Paper start - copied from above and modified to return if the hook registered -- private static boolean addShutdownHook(String restartScript) -+ public static boolean addShutdownHook(String restartScript) - { - String[] split = restartScript.split( " " ); - if ( split.length > 0 && new File( split[0] ).isFile() ) -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 33a66322d253c7562ae5acbdbc6cc87f7d72a9af..26c9adf7af4328ce2d8e08568019c5b438e28b05 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -13,6 +13,7 @@ import org.bukkit.Bukkit; - public class WatchdogThread extends Thread - { - -+ public static final boolean DISABLE_WATCHDOG = Boolean.getBoolean("disable.watchdog"); // Paper - private static WatchdogThread instance; - private long timeoutTime; - private boolean restart; -@@ -41,6 +42,7 @@ public class WatchdogThread extends Thread - { - if ( instance == null ) - { -+ if (timeoutTime <= 0) timeoutTime = 300; // Paper - instance = new WatchdogThread( timeoutTime * 1000L, restart ); - instance.start(); - } else -@@ -71,12 +73,13 @@ public class WatchdogThread extends Thread - // Paper start - Logger log = Bukkit.getServer().getLogger(); - long currentTime = monotonicMillis(); -- if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) -+ MinecraftServer server = MinecraftServer.getServer(); -+ if (lastTick != 0 && timeoutTime > 0 && hasStarted && (!server.isRunning() || (currentTime > lastTick + earlyWarningEvery && !DISABLE_WATCHDOG) )) - { -- boolean isLongTimeout = currentTime > lastTick + timeoutTime; -+ boolean isLongTimeout = currentTime > lastTick + timeoutTime || (!server.isRunning() && !server.hasStopped() && currentTime > lastTick + 1000); - // Don't spam early warning dumps - if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; -- if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... -+ if ( !isLongTimeout && server.hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... - lastEarlyWarning = currentTime; - if (isLongTimeout) { - // Paper end -@@ -118,7 +121,7 @@ public class WatchdogThread extends Thread - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper -- dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); -+ dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // - // Paper start - Only print full dump on long timeouts -@@ -139,9 +142,25 @@ public class WatchdogThread extends Thread - - if ( isLongTimeout ) - { -- if ( restart && !MinecraftServer.getServer().hasStopped() ) -+ if ( !server.hasStopped() ) - { -- RestartCommand.restart(); -+ AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us -+ AsyncCatcher.shuttingDown = true; -+ server.forceTicks = true; -+ if (restart) { -+ RestartCommand.addShutdownHook( SpigotConfig.restartScript ); -+ } -+ // try one last chance to safe shutdown on main incase it 'comes back' -+ server.abnormalExit = true; -+ server.safeShutdown(false, restart); -+ try { -+ Thread.sleep(1000); -+ } catch (InterruptedException e) { -+ e.printStackTrace(); -+ } -+ if (!server.hasStopped()) { -+ server.close(); -+ } - } - break; - } // Paper end -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 476f4a5cbe664ddd05474cb88553018bd334a5b8..8af159abd3d0cc94cf155fec5b384c42f69551bf 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -1,5 +1,5 @@ - -- -+ - - - diff --git a/Remapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch b/Remapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch deleted file mode 100644 index 9f2777798e..0000000000 --- a/Remapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 02:02:07 -0600 -Subject: [PATCH] Optimize Pathfinding - -Prevents pathfinding from spamming failures for things such as -arrow attacks. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index a362506f38e8d30543b6cd6d215db561290dac76..c501e42b6fef4af065807182dc5b4c444e74e310 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -11,6 +11,7 @@ import net.minecraft.core.Position; - import net.minecraft.core.Vec3i; - import net.minecraft.network.protocol.game.DebugPackets; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.Mob; -@@ -32,7 +33,7 @@ public abstract class PathNavigation { - protected final Mob mob; public Entity getEntity() { return mob; } // Paper - OBFHELPER - protected final Level level; - @Nullable -- protected Path path; -+ protected Path path; protected final Path getCurrentPath() { return this.path; } // Paper - OBFHELPER - protected double speedModifier; - protected int tick; - protected int lastStuckCheck; -@@ -184,10 +185,30 @@ public abstract class PathNavigation { - return this.moveTo(this.createPath(x, y, z, 1), speed); - } - -+ // Paper start - optimise pathfinding -+ private int lastFailure = 0; -+ private int pathfindFailures = 0; -+ // Paper end -+ - public boolean moveTo(Entity entity, double speed) { -+ // Paper start - Pathfinding optimizations -+ if (this.pathfindFailures > 10 && this.getCurrentPath() == null && MinecraftServer.currentTick < this.lastFailure + 40) { -+ return false; -+ } -+ // Paper end - Path pathentity = this.createPath(entity, 1); - -- return pathentity != null && this.moveTo(pathentity, speed); -+ // Paper start - Pathfinding optimizations -+ if (pathentity != null && this.moveTo(pathentity, speed)) { -+ this.lastFailure = 0; -+ this.pathfindFailures = 0; -+ return true; -+ } else { -+ this.pathfindFailures++; -+ this.lastFailure = MinecraftServer.currentTick; -+ return false; -+ } -+ // Paper end - } - - public boolean setDestination(@Nullable Path pathentity, double speed) { return moveTo(pathentity, speed); } // Paper - OBFHELPER diff --git a/Remapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch b/Remapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch deleted file mode 100644 index 991b0f903b..0000000000 --- a/Remapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 18:35:09 -0700 -Subject: [PATCH] Reduce Either Optional allocation - -In order to get chunk values, we shouldn't need to create -an optional each time. - -diff --git a/src/main/java/com/mojang/datafixers/util/Either.java b/src/main/java/com/mojang/datafixers/util/Either.java -index fc8dbdf43833d76d8dc5f4e92575ca2965afa93a..ab71cdb3a8c2bec036ece630a0e0f088653e928f 100644 ---- a/src/main/java/com/mojang/datafixers/util/Either.java -+++ b/src/main/java/com/mojang/datafixers/util/Either.java -@@ -22,7 +22,7 @@ public abstract class Either implements App, L> { - } - - private static final class Left extends Either { -- private final L value; -+ private final L value; private Optional valueOptional; // Paper - reduce the optional allocation... - - public Left(final L value) { - this.value = value; -@@ -51,7 +51,7 @@ public abstract class Either implements App, L> { - - @Override - public Optional left() { -- return Optional.of(value); -+ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... - } - - @Override -@@ -83,7 +83,7 @@ public abstract class Either implements App, L> { - } - - private static final class Right extends Either { -- private final R value; -+ private final R value; private Optional valueOptional; // Paper - reduce the optional allocation... - - public Right(final R value) { - this.value = value; -@@ -117,7 +117,7 @@ public abstract class Either implements App, L> { - - @Override - public Optional right() { -- return Optional.of(value); -+ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch b/Remapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch deleted file mode 100644 index 935abedc0d..0000000000 --- a/Remapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 18:10:43 -0700 -Subject: [PATCH] Remove streams from PairedQueue - -We shouldn't be doing stream calls just to see if the queue is -empty. This creates loads of garbage thanks to how often it's called. - -diff --git a/src/main/java/net/minecraft/util/thread/StrictQueue.java b/src/main/java/net/minecraft/util/thread/StrictQueue.java -index cdc572b0261034248960fa13b8412e874fd20db5..07938519b699a31a280f3f419b34fb7cf6cf6883 100644 ---- a/src/main/java/net/minecraft/util/thread/StrictQueue.java -+++ b/src/main/java/net/minecraft/util/thread/StrictQueue.java -@@ -20,32 +20,30 @@ public interface StrictQueue { - - public static final class FixedPriorityQueue implements StrictQueue { - -- private final List> queueList; -+ private final List> queueList; private final List> getQueues() { return this.queueList; } // Paper - OBFHELPER - - public FixedPriorityQueue(int priorityCount) { -- this.queueList = (List) IntStream.range(0, priorityCount).mapToObj((j) -> { -- return Queues.newConcurrentLinkedQueue(); -- }).collect(Collectors.toList()); -+ // Paper start - remove streams -+ this.queueList = new java.util.ArrayList<>(priorityCount); // queues -+ for (int j = 0; j < priorityCount; ++j) { -+ this.getQueues().add(Queues.newConcurrentLinkedQueue()); -+ } -+ // Paper end - remove streams - } - - @Nullable - @Override - public Runnable pop() { -- Iterator iterator = this.queueList.iterator(); -- -- Runnable runnable; -- -- do { -- if (!iterator.hasNext()) { -- return null; -+ // Paper start - remove iterator creation -+ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { -+ Queue queue = this.getQueues().get(i); -+ Runnable ret = queue.poll(); -+ if (ret != null) { -+ return ret; - } -- -- Queue queue = (Queue) iterator.next(); -- -- runnable = (Runnable) queue.poll(); -- } while (runnable == null); -- -- return runnable; -+ } -+ return null; -+ // Paper end - remove iterator creation - } - - public boolean push(StrictQueue.IntRunnable message) { -@@ -57,7 +55,16 @@ public interface StrictQueue { - - @Override - public boolean isEmpty() { -- return this.queueList.stream().allMatch(Collection::isEmpty); -+ // Paper start - remove streams -+ // why are we doing streams every time we might want to execute a task? -+ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { -+ Queue queue = this.getQueues().get(i); -+ if (!queue.isEmpty()) { -+ return false; -+ } -+ } -+ return true; -+ // Paper end - remove streams - } - } - diff --git a/Remapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch b/Remapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch deleted file mode 100644 index dcba632a31..0000000000 --- a/Remapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 17:39:25 -0700 -Subject: [PATCH] Reduce memory footprint of NBTTagCompound - -Fastutil maps are going to have a lower memory footprint - which -is important because we clone chunk data after reading it for safety. -So, reduce the impact of the clone on GC. - -diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java -index a91bf94ed9f2f353a685194fc91c4b101ccc1232..c856ca720a9329a94bb07eaa3060c034f95718b3 100644 ---- a/src/main/java/net/minecraft/nbt/CompoundTag.java -+++ b/src/main/java/net/minecraft/nbt/CompoundTag.java -@@ -26,6 +26,7 @@ import net.minecraft.ReportedException; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.MutableComponent; - import net.minecraft.network.chat.TextComponent; -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -47,7 +48,7 @@ public class CompoundTag implements Tag { - if (i > 512) { - throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512"); - } else { -- HashMap hashmap = Maps.newHashMap(); -+ Object2ObjectOpenHashMap hashmap = new Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound - - byte b0; - -@@ -83,7 +84,7 @@ public class CompoundTag implements Tag { - } - - public CompoundTag() { -- this(Maps.newHashMap()); -+ this(new Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - reduce memory footprint of NBTTagCompound - } - - @Override -@@ -417,9 +418,17 @@ public class CompoundTag implements Tag { - - @Override - public CompoundTag copy() { -- Map map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy)); -+ // Paper start - reduce memory footprint of NBTTagCompound -+ Object2ObjectOpenHashMap ret = new Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f); - -- return new CompoundTag(map); -+ Iterator> iterator = (this.tags instanceof Object2ObjectOpenHashMap) ? ((Object2ObjectOpenHashMap)this.tags).object2ObjectEntrySet().fastIterator() : this.tags.entrySet().iterator(); -+ while (iterator.hasNext()) { -+ Map.Entry entry = iterator.next(); -+ ret.put(entry.getKey(), entry.getValue().copy()); -+ } -+ -+ return new CompoundTag(ret); -+ // Paper end - reduce memory footprint of NBTTagCompound - } - - public boolean equals(Object object) { diff --git a/Remapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch b/Remapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch deleted file mode 100644 index 7b2a22a56b..0000000000 --- a/Remapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 13 Apr 2020 07:31:44 +0100 -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 162b1a8c6ab57aafa4f6deefc842755a8e14208e..efacfcaab444270b985f3a7fe0ef97e33c18a9de 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -557,7 +557,7 @@ public class ServerPlayer extends Player implements ContainerListener { - containerUpdateDelay = level.paperConfig.containerUpdateTickRate; - } - // Paper end -- if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { -+ if (!this.level.isClientSide && this.containerMenu != this.inventoryMenu && (isImmobile() || !this.containerMenu.stillValid(this))) { // Paper - auto close while frozen - this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.containerMenu = this.inventoryMenu; - } -@@ -1404,7 +1404,7 @@ public class ServerPlayer extends Player implements ContainerListener { - } else { - // CraftBukkit start - this.containerMenu = container; -- this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); -+ if (!isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper - // CraftBukkit end - container.addSlotListener(this); - return OptionalInt.of(this.containerCounter); -@@ -2206,7 +2206,7 @@ public class ServerPlayer extends Player implements ContainerListener { - } - - @Override -- protected boolean isImmobile() { -+ public boolean isImmobile() { // Paper - protected > public - return super.isImmobile() || (this.connection != null && this.connection.isDisconnected()); // Paper - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index a73c6ddd6bf66cc21ae5b25daacdece8cbfeeeac..ae6faa331fcbefd99ee1cd92c88926d767fc50ee 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -323,7 +323,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper - - //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment -- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper -+ if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - getHandle().containerMenu = container; - getHandle().containerMenu.addSlotListener(player); - } -@@ -397,7 +397,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper - if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper - //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment -- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper -+ if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - player.containerMenu = container; - player.containerMenu.addSlotListener(player); - } diff --git a/Remapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch b/Remapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch deleted file mode 100644 index dad03aa170..0000000000 --- a/Remapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Apr 2020 18:23:28 -0700 -Subject: [PATCH] Optimise ArraySetSorted#removeIf - -Remove iterator allocation and ensure the call is always O(n) - -diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java -index 93813a508be1e1e600a8211f9822f2087328de70..8f03847eeb95ccdb69ad181b38b8724c9c72a76b 100644 ---- a/src/main/java/net/minecraft/util/SortedArraySet.java -+++ b/src/main/java/net/minecraft/util/SortedArraySet.java -@@ -10,8 +10,8 @@ import java.util.NoSuchElementException; - public class SortedArraySet extends AbstractSet { - - private final Comparator comparator; -- private T[] contents; -- private int size; -+ private T[] contents; private final T[] getBackingArray() { return this.contents; } // Paper - OBFHELPER -+ private int size; private final int getSize() { return this.size; } private final void setSize(int value) { this.size = value; } // Paper - OBFHELPER - - private SortedArraySet(int initialCapacity, Comparator comparator) { - this.comparator = comparator; -@@ -22,6 +22,42 @@ public class SortedArraySet extends AbstractSet { - } - } - -+ // Paper start - optimise removeIf -+ @Override -+ public boolean removeIf(java.util.function.Predicate filter) { -+ // prev. impl used an iterator, which could be n^2 and creates garbage -+ int i = 0, len = this.getSize(); -+ T[] backingArray = this.getBackingArray(); -+ -+ for (;;) { -+ if (i >= len) { -+ return false; -+ } -+ if (!filter.test(backingArray[i])) { -+ ++i; -+ continue; -+ } -+ break; -+ } -+ -+ // we only want to write back to backingArray if we really need to -+ -+ int lastIndex = i; // this is where new elements are shifted to -+ -+ for (; i < len; ++i) { -+ T curr = backingArray[i]; -+ if (!filter.test(curr)) { // if test throws we're screwed -+ backingArray[lastIndex++] = curr; -+ } -+ } -+ -+ // cleanup end -+ Arrays.fill(backingArray, lastIndex, len, null); -+ this.setSize(lastIndex); -+ return true; -+ } -+ // Paper end - optimise removeIf -+ - public static > SortedArraySet create(int initialCapacity) { - return new SortedArraySet<>(initialCapacity, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix - } diff --git a/Remapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch b/Remapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch deleted file mode 100644 index 474688a9b3..0000000000 --- a/Remapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Apr 2020 17:56:07 -0700 -Subject: [PATCH] Don't run entity collision code if not needed - -Will not run if max entity craming is disabled and -the max collisions per entity is less than or equal to 0 - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 43fbe7d220f61802ae0cb0620ad078c5df7b69bc..46b962183e2e27ed93054ad9fb6d8ecbf70bc5f9 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2941,10 +2941,16 @@ public abstract class LivingEntity extends Entity { - protected void serverAiStep() {} - - protected void pushEntities() { -+ // Paper - start don't run getEntities if we're not going to use its result -+ int i = this.level.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); -+ if (i <= 0 && level.paperConfig.maxCollisionsPerEntity <= 0) { -+ return; -+ } -+ // Paper - end don't run getEntities if we're not going to use its result - List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); - - if (!list.isEmpty()) { -- int i = this.level.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); -+ // Paper - move up - int j; - - if (i > 0 && list.size() > i - 1 && this.random.nextInt(4) == 0) { diff --git a/Remapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch b/Remapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch deleted file mode 100644 index e6f6255656..0000000000 --- a/Remapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 16 Apr 2020 16:13:59 -0700 -Subject: [PATCH] Optimize ChunkProviderServer's chunk level checking helper - methods - -These can be hot functions (i.e entity ticking and block ticking), -so inline where possible, and avoid the abstraction of the -Either class. - -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 3744cce8611ac01b1b6c76cd3c4890795c1f06a2..531fe1259a1d60ff69321c3fefbf97f7141e6475 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -24,7 +24,6 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.progress.ChunkProgressListener; --import net.minecraft.util.Mth; - import net.minecraft.util.profiling.ProfilerFiller; - import net.minecraft.util.thread.BlockableEventLoop; - import net.minecraft.world.entity.Entity; -@@ -644,21 +643,29 @@ public class ServerChunkCache extends ChunkSource { - - public final boolean isInEntityTickingChunk(Entity entity) { return this.isEntityTickingChunk(entity); } // Paper - OBFHELPER - @Override public boolean isEntityTickingChunk(Entity entity) { -- long i = ChunkPos.asLong(Mth.floor(entity.getX()) >> 4, Mth.floor(entity.getZ()) >> 4); -- -- return this.checkChunkFuture(i, (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error -+ // Paper start - optimize is ticking ready type functions -+ // entity ticking -+ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(MCUtil.getCoordinateKey(entity)); -+ return playerChunk != null && playerChunk.isEntityTickingReady(); -+ // Paper end - optimize is ticking ready type functions - } - - public final boolean isEntityTickingChunk(ChunkPos chunkcoordintpair) { return this.isEntityTickingChunk(chunkcoordintpair); } // Paper - OBFHELPER - @Override public boolean isEntityTickingChunk(ChunkPos pos) { -- return this.checkChunkFuture(pos.toLong(), (Function>>) ChunkHolder::getEntityTickingChunkFuture); // CraftBukkit - decompile error -+ // Paper start - optimize is ticking ready type functions -+ // is entity ticking ready -+ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(MCUtil.getCoordinateKey(pos)); -+ return playerChunk != null && playerChunk.isEntityTickingReady(); -+ // Paper end - optimize is ticking ready type functions - } - - @Override - public boolean isTickingChunk(BlockPos pos) { -- long i = ChunkPos.asLong(pos.getX() >> 4, pos.getZ() >> 4); -- -- return this.checkChunkFuture(i, (Function>>) ChunkHolder::getTickingChunkFuture); // CraftBukkit - decompile error -+ // Paper start - optimize is ticking ready type functions -+ // is ticking ready -+ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(MCUtil.getCoordinateKey(pos)); -+ return playerChunk != null && playerChunk.isTickingReady(); -+ // Paper end - optimize is ticking ready type functions - } - - private boolean checkChunkFuture(long pos, Function>> futureFunction) { diff --git a/Remapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch b/Remapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch deleted file mode 100644 index bc23f71417..0000000000 --- a/Remapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 16 Apr 2020 20:07:29 -0500 -Subject: [PATCH] Restrict vanilla teleport command to valid locations - -Fixes GH-3165, GH-3575 - -diff --git a/src/main/java/net/minecraft/server/commands/TeleportCommand.java b/src/main/java/net/minecraft/server/commands/TeleportCommand.java -index 774180d9e450199309fee65b1d10e1592f84548a..d04ce9a323b079b4556b8c341fb11186e8d3e05d 100644 ---- a/src/main/java/net/minecraft/server/commands/TeleportCommand.java -+++ b/src/main/java/net/minecraft/server/commands/TeleportCommand.java -@@ -141,6 +141,12 @@ public class TeleportCommand { - - private static void performTeleport(CommandSourceStack source, Entity target, ServerLevel world, double x, double y, double z, Set movementFlags, float yaw, float pitch, @Nullable TeleportCommand.LookAt facingLocation) throws CommandSyntaxException { - BlockPos blockposition = new BlockPos(x, y, z); -+ // Paper start - Don't allow teleport command to invalid locations -+ if (x <= -30000000 || z <= -30000000 || x > 30000000 || z > 30000000 || y > 30000000 || y <= -30000000) { // Copy/pasta from BaseBlockPosition#isValidLocation -+ org.bukkit.Bukkit.getLogger().warning("Refused to teleport " + target.getScoreboardName() + " to " + x + ", " + y + ", " + z); -+ return; -+ } -+ // Paper end - - if (!Level.isInSpawnableBounds(blockposition)) { - throw TeleportCommand.INVALID_POSITION.create(); diff --git a/Remapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch b/Remapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch deleted file mode 100644 index dcdbea5496..0000000000 --- a/Remapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch +++ /dev/null @@ -1,188 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Mon, 20 Jan 2020 21:38:15 +0100 -Subject: [PATCH] Implement Player Client Options API - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperSkinParts.java b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabba57885e1 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java -@@ -0,0 +1,74 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Objects; -+ -+import java.util.StringJoiner; -+ -+public class PaperSkinParts implements SkinParts { -+ -+ private final int raw; -+ -+ public PaperSkinParts(int raw) { -+ this.raw = raw; -+ } -+ -+ public boolean hasCapeEnabled() { -+ return (raw & 1) == 1; -+ } -+ -+ public boolean hasJacketEnabled() { -+ return (raw >> 1 & 1) == 1; -+ } -+ -+ public boolean hasLeftSleeveEnabled() { -+ return (raw >> 2 & 1) == 1; -+ } -+ -+ public boolean hasRightSleeveEnabled() { -+ return (raw >> 3 & 1) == 1; -+ } -+ -+ public boolean hasLeftPantsEnabled() { -+ return (raw >> 4 & 1) == 1; -+ } -+ -+ public boolean hasRightPantsEnabled() { -+ return (raw >> 5 & 1) == 1; -+ } -+ -+ public boolean hasHatsEnabled() { -+ return (raw >> 6 & 1) == 1; -+ } -+ -+ @Override -+ public int getRaw() { -+ return raw; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ PaperSkinParts that = (PaperSkinParts) o; -+ return raw == that.raw; -+ } -+ -+ @Override -+ public int hashCode() { -+ return Objects.hashCode(raw); -+ } -+ -+ @Override -+ public String toString() { -+ return new StringJoiner(", ", PaperSkinParts.class.getSimpleName() + "[", "]") -+ .add("raw=" + raw) -+ .add("cape=" + hasCapeEnabled()) -+ .add("jacket=" + hasJacketEnabled()) -+ .add("leftSleeve=" + hasLeftSleeveEnabled()) -+ .add("rightSleeve=" + hasRightSleeveEnabled()) -+ .add("leftPants=" + hasLeftPantsEnabled()) -+ .add("rightPants=" + hasRightPantsEnabled()) -+ .add("hats=" + hasHatsEnabled()) -+ .toString(); -+ } -+} -diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java -index 1f486cfd77b49568540398b1b3fa6127b17ba6aa..4b43740f9ff4feab4f1cd2f8e91d55be3cf8eb50 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java -@@ -41,14 +41,17 @@ public class ServerboundClientInformationPacket implements Packet POSES = ImmutableMap.builder().put(Pose.STANDING, Player.STANDING_DIMENSIONS).put(Pose.SLEEPING, Player.SLEEPING_DIMENSIONS).put(Pose.FALL_FLYING, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.SWIMMING, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.SPIN_ATTACK, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.CROUCHING, EntityDimensions.scalable(0.6F, 1.5F)).put(Pose.DYING, EntityDimensions.fixed(0.2F, 0.2F)).build(); - private static final EntityDataAccessor DATA_PLAYER_ABSORPTION_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.FLOAT); - private static final EntityDataAccessor DATA_SCORE_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.INT); -- protected static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); -+ protected static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); public static EntityDataAccessor getSkinPartsWatcher() { return DATA_PLAYER_MODE_CUSTOMISATION; } // Paper - OBFHELPER - protected static final EntityDataAccessor DATA_PLAYER_MAIN_HAND = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); - protected static final EntityDataAccessor DATA_SHOULDER_LEFT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); - protected static final EntityDataAccessor DATA_SHOULDER_RIGHT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 20de8e358789d05bb5ac15e4cdd7dda85b61b7f8..eb366396820c9b6731469df4198e0884a431a77c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1,5 +1,8 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.ClientOption.ChatVisibility; -+import com.destroystokyo.paper.PaperSkinParts; -+import com.destroystokyo.paper.ClientOption; - import com.destroystokyo.paper.Title; - import com.google.common.base.Preconditions; - import com.google.common.collect.ImmutableSet; -@@ -2250,6 +2253,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public void setViewDistance(int viewDistance) { - throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO - } -+ -+ @Override -+ public T getClientOption(ClientOption type) { -+ if(ClientOption.SKIN_PARTS.equals(type)) { -+ return type.getType().cast(new PaperSkinParts(getHandle().getEntityData().get(net.minecraft.world.entity.player.Player.getSkinPartsWatcher()))); -+ } else if(ClientOption.CHAT_COLORS_ENABLED.equals(type)) { -+ return type.getType().cast(getHandle().hasChatColorsEnabled()); -+ } else if(ClientOption.CHAT_VISIBILITY.equals(type)) { -+ return type.getType().cast(getHandle().getChatVisibility() == null ? ChatVisibility.UNKNOWN : ChatVisibility.valueOf(getHandle().getChatVisibility().name())); -+ } else if(ClientOption.LOCALE.equals(type)) { -+ return type.getType().cast(getLocale()); -+ } else if(ClientOption.MAIN_HAND.equals(type)) { -+ return type.getType().cast(getMainHand()); -+ } else if(ClientOption.VIEW_DISTANCE.equals(type)) { -+ return type.getType().cast(getClientViewDistance()); -+ } -+ throw new RuntimeException("Unknown settings type"); -+ } - // Paper end - - // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch b/Remapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch deleted file mode 100644 index 1d32694a1d..0000000000 --- a/Remapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Apr 2020 04:36:11 -0400 -Subject: [PATCH] Fix Chunk Post Processing deadlock risk - -See: https://gist.github.com/aikar/dd22bbd2a3d78a2fd3d92e95e9f28dc6 - -as part of post processing a chunk, we can call ChunkConverter. - -ChunkConverter then kicks off major physics updates, and when blocks -that have connections across chunk boundries occur, a recursive risk -can occur where A updates a block that triggers a physics request. - -That physics request may trigger a chunk request, that then enqueues -a task into the Mailbox ChunkTaskQueueSorter. - -If anything requests that same chunk that is in the middle of conversion, -it's mailbox queue is going to be held up, so the subsequent chunk request -will be unable to proceed. - -We delay post processing of Chunk.A() 1 "pass" by re stuffing it back into -the executor so that the mailbox ChunkQueue is now considered empty. - -This successfully fixed a reoccurring and highly reproduceable crash -for heightmaps. - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 49728aab7512ea8486d277d34e80d3c6a4727aac..dbe60f5d24fb39be52c3cb8f933371b1626951df 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -181,6 +181,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - }; - // CraftBukkit end - -+ final CallbackExecutor chunkLoadConversionCallbackExecutor = new CallbackExecutor(); // Paper -+ - // Paper start - distance maps - private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); - -@@ -1054,7 +1056,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return Either.left(chunk); - }); - }, (runnable) -> { -- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); -+ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, () -> ChunkMap.this.chunkLoadConversionCallbackExecutor.execute(runnable))); // Paper - delay running Chunk post processing until outside of the sorter to prevent a deadlock scenario when post processing causes another chunk request. - }); - - completablefuture1.thenAcceptAsync((either) -> { -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 531fe1259a1d60ff69321c3fefbf97f7141e6475..b45fe750c8ca838e1beebff4077e5819eec2836c 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -1021,6 +1021,7 @@ public class ServerChunkCache extends ChunkSource { - return super.pollTask() || execChunkTask; // Paper - } - } finally { -+ chunkMap.chunkLoadConversionCallbackExecutor.run(); // Paper - Add chunk load conversion callback executor to prevent deadlock due to recursion in the chunk task queue sorter - chunkMap.callbackExecutor.run(); - } - // CraftBukkit end diff --git a/Remapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/Remapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch deleted file mode 100644 index 1469edc105..0000000000 --- a/Remapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Apr 2020 15:59:41 -0400 -Subject: [PATCH] Don't crash if player is attempted to be removed from - untracked chunk. - -I suspect it deals with teleporting as it uses players current x/y/z - -diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index 71a51cc99e26579e765f88340588e23956888929..90429d3f5c5b725098cfb001d54c70608f3df7bb 100644 ---- a/src/main/java/net/minecraft/server/level/DistanceManager.java -+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -245,8 +245,8 @@ public abstract class DistanceManager { - ObjectSet objectset = (ObjectSet) this.playersPerChunk.get(i); - if (objectset == null) return; // CraftBukkit - SPIGOT-6208 - -- objectset.remove(player); -- if (objectset.isEmpty()) { -+ if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully. -+ if (objectset == null || objectset.isEmpty()) { // Paper - this.playersPerChunk.remove(i); - this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); - this.playerTicketManager.update(i, Integer.MAX_VALUE, false); diff --git a/Remapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch b/Remapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch deleted file mode 100644 index de365413d4..0000000000 --- a/Remapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AvrooVulcan -Date: Fri, 17 Apr 2020 00:15:23 +0100 -Subject: [PATCH] Broadcast join message to console - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 984ac19dcab446531c816e365c7c149e2c49d567..e043722436492140162940770c22be47690fb47f 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -284,7 +284,9 @@ public abstract class PlayerList { - - if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure - joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure -- server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure -+ // Paper start - Removed sendAll for loop and broadcasted to console also -+ server.getPlayerList().sendMessage(joinMessage); // Paper - Adventure -+ // Paper end - } - // CraftBukkit end - diff --git a/Remapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/Remapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch deleted file mode 100644 index e4ac02eb91..0000000000 --- a/Remapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 00:05:46 -0400 -Subject: [PATCH] Fix Longstanding Broken behavior of PlayerJoinEvent - -For years, plugin developers have had to delay many things they do -inside of the PlayerJoinEvent by 1 tick to make it actually work. - -This all boiled down to 1 reason why: The event fired before the -player was fully ready and joined to the world! - -Additionally, if that player logged out on a vehicle, the event -fired before the vehicle was even loaded, so that plugins had no -access to the vehicle during this event either. - -This change finally fixes this issue, fully preparing the player -into the world as a fully ready entity, vehicle included. - -There should be no plugins that break because of this change, but might -improve consistency with other plugins instead. - -For example, if 2 plugins listens to this event, and the first one -teleported the player in the event, then the 2nd plugin actually -would be getting a valid player! - -This was very non deterministic. This change will ensure every plugin -receives a deterministic result, and should no longer require 1 tick -delays anymore. - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index dbe60f5d24fb39be52c3cb8f933371b1626951df..b3ca4300b280a24f3ed2acaffdd6ae2cdffd140d 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1584,7 +1584,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - }); - } - -- protected void addEntity(Entity entity) { -+ public void addEntity(Entity entity) { // Paper - protected -> public - org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot - // Paper start - ignore and warn about illegal addEntity calls instead of crashing server - if (!entity.valid || entity.level != this.level || this.entityMap.containsKey(entity.getId())) { -@@ -1593,6 +1593,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - .printStackTrace(); - return; - } -+ if (entity instanceof ServerPlayer && ((ServerPlayer) entity).supressTrackerForLogin) return; // Delay adding to tracker until after list packets - // Paper end - if (!(entity instanceof EnderDragonPart)) { - EntityType entitytypes = entity.getType(); -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index aa979d17c264840ebd528708df3d6118e69fec68..75a095e0c2177dc1b46b080597ff8f12f1480acc 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -237,6 +237,7 @@ public class ServerPlayer extends Player implements ContainerListener { - public double maxHealthCache; - public boolean joining = true; - public boolean sentListPacket = false; -+ public boolean supressTrackerForLogin = false; // Paper - public Integer clientViewDistance; - // CraftBukkit end - public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index e043722436492140162940770c22be47690fb47f..454d60566743e02e7e55868c7bb45e30583dfa8f 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -272,6 +272,12 @@ public abstract class PlayerList { - this.playersByUUID.put(player.getUUID(), player); - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below - -+ // Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks -+ player.supressTrackerForLogin = true; -+ worldserver1.addNewPlayer(player); -+ this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below worldserver.addPlayerJoin(entityplayer); -+ mountSavedVehicle(player, worldserver1, nbttagcompound); -+ // Paper end - // CraftBukkit start - PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - cserver.getPluginManager().callEvent(playerJoinEvent); -@@ -307,6 +313,8 @@ public abstract class PlayerList { - player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); - } - player.sentListPacket = true; -+ player.supressTrackerForLogin = false; // Paper -+ ((ServerLevel)player.level).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now - // CraftBukkit end - - player.connection.send(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn -@@ -332,6 +340,11 @@ public abstract class PlayerList { - playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect)); - } - -+ // Paper start - move vehicle into method so it can be called above - short circuit around that code -+ onPlayerJoinFinish(player, worldserver1, s1); -+ } -+ private void mountSavedVehicle(ServerPlayer entityplayer, ServerLevel worldserver1, CompoundTag nbttagcompound) { -+ // Paper end - if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) { - CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); - // CraftBukkit start -@@ -354,20 +367,20 @@ public abstract class PlayerList { - Entity entity1; - - if (entity.getUUID().equals(uuid)) { -- player.startRiding(entity, true); -+ entityplayer.startRiding(entity, true); - } else { - iterator1 = entity.getIndirectPassengers().iterator(); - - while (iterator1.hasNext()) { - entity1 = (Entity) iterator1.next(); - if (entity1.getUUID().equals(uuid)) { -- player.startRiding(entity1, true); -+ entityplayer.startRiding(entity1, true); - break; - } - } - } - -- if (!player.isPassenger()) { -+ if (!entityplayer.isPassenger()) { - PlayerList.LOGGER.warn("Couldn't reattach entity to player"); - worldserver1.despawn(entity); - iterator1 = entity.getIndirectPassengers().iterator(); -@@ -380,16 +393,20 @@ public abstract class PlayerList { - } - } - -- player.initMenu(); -+ // Paper start -+ } -+ public void onPlayerJoinFinish(ServerPlayer entityplayer, ServerLevel worldserver1, String s1) { -+ // Paper end -+ entityplayer.initMenu(); - // Paper start - Add to collideRule team if needed - final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); - final PlayerTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName); -- if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) { -- scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); -+ if (this.collideRuleTeamName != null && collideRuleTeam != null && entityplayer.getTeam() == null) { -+ scoreboard.addPlayerToTeam(entityplayer.getScoreboardName(), collideRuleTeam); - } - // Paper end - // CraftBukkit - Moved from above, added world -- PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.worldDataServer.getLevelName(), player.getX(), player.getY(), player.getZ()); -+ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getName().getString(), s1, entityplayer.getId(), worldserver1.worldDataServer.getLevelName(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()); - } - - public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) { diff --git a/Remapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch b/Remapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch deleted file mode 100644 index f02494b2a2..0000000000 --- a/Remapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch +++ /dev/null @@ -1,416 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 04:28:29 -0400 -Subject: [PATCH] Load Chunks for Login Asynchronously - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index b3ca4300b280a24f3ed2acaffdd6ae2cdffd140d..97a582614ad28f9fa864ae9be4860658e5979214 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -145,7 +145,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private final ProcessorHandle> worldgenMailbox; - private final ProcessorHandle> mainThreadMailbox; - public final ChunkProgressListener progressListener; -- public final ChunkMap.ChunkDistanceManager distanceManager; -+ public final ChunkMap.ChunkDistanceManager distanceManager; public final DistanceManager getChunkDistanceManager() { return this.distanceManager; } // Paper - OBFHELPER - private final AtomicInteger tickingGenerated; - public final StructureManager structureManager; // Paper - private -> public - private final File storageFolder; -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index b45fe750c8ca838e1beebff4077e5819eec2836c..79fb63c40dd0543a6f629e78f390f23f34992ba1 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -629,7 +629,7 @@ public class ServerChunkCache extends ChunkSource { - return this.mainThreadProcessor.pollTask(); - } - -- private boolean runDistanceManagerUpdates() { -+ public boolean runDistanceManagerUpdates() { // Paper - private -> public - boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); - boolean flag1 = this.chunkMap.promoteChunkMap(); - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 75a095e0c2177dc1b46b080597ff8f12f1480acc..24c508ade61a6ad90b0ef73cdc995f531ef18263 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -32,6 +32,7 @@ import net.minecraft.core.Vec3i; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.NbtOps; - import net.minecraft.nbt.Tag; -+import net.minecraft.network.Connection; - import net.minecraft.network.chat.ChatType; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.HoverEvent; -@@ -172,6 +173,7 @@ public class ServerPlayer extends Player implements ContainerListener { - - private static final Logger LOGGER = LogManager.getLogger(); - public ServerGamePacketListenerImpl connection; -+ public Connection networkManager; // Paper - public final MinecraftServer server; - public final ServerPlayerGameMode gameMode; - public final Deque removeQueue = new ArrayDeque<>(); // Paper -@@ -238,6 +240,7 @@ public class ServerPlayer extends Player implements ContainerListener { - public boolean joining = true; - public boolean sentListPacket = false; - public boolean supressTrackerForLogin = false; // Paper -+ public boolean didPlayerJoinEvent = false; // Paper - public Integer clientViewDistance; - // CraftBukkit end - public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index d09e4857b6c40410d134fa81b48e95919a7373bd..583587457790df826a8a3239a4bd1d0f1dcab1da 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -21,6 +21,7 @@ public class TicketType { - public static final TicketType FORCED = create("forced", Comparator.comparingLong(ChunkPos::toLong)); - public static final TicketType LIGHT = create("light", Comparator.comparingLong(ChunkPos::toLong)); - public static final TicketType PORTAL = create("portal", Vec3i::compareTo, 300); -+ public static final TicketType LOGIN = create("login", Long::compareTo, 100); // Paper - public static final TicketType POST_TELEPORT = create("post_teleport", Integer::compareTo, 5); - public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); - public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 09a663cc53cdf8ae45352b280200c8170dbbcdfc..1bed6e69bf3cc1ab9b0c1259de4f643bf58371aa 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -220,6 +220,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - private static final Logger LOGGER = LogManager.getLogger(); - public final Connection connection; - private final MinecraftServer server; -+ public Runnable playerJoinReady; // Paper - public ServerPlayer player; - private int tickCount; - private long keepAliveTime = Util.getMillis(); private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER -@@ -298,6 +299,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // CraftBukkit end - - public void tick() { -+ // Paper start - login async -+ Runnable playerJoinReady = this.playerJoinReady; -+ if (playerJoinReady != null) { -+ this.playerJoinReady = null; -+ playerJoinReady.run(); -+ } -+ // Don't tick if not valid (dead), otherwise we load chunks below -+ if (this.player.valid) { -+ // Paper end - this.resetPosition(); - this.player.xo = this.player.getX(); - this.player.yo = this.player.getY(); -@@ -339,7 +349,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - this.lastVehicle = null; - this.clientVehicleIsFloating = false; - this.aboveGroundVehicleTickCount = 0; -- } -+ }} // Paper - end if (valid) - - this.server.getProfiler().push("keepAlive"); - // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 9631fa93b821c7f6bc6dc707c2c82cce2ae8291e..e229c7735ba88be3d8721440104958408a2a075e 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -86,7 +86,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - } - // Paper end - } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { -- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); -+ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper - - if (entityplayer == null) { - this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT; -@@ -186,7 +186,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - } - - this.connection.send(new ClientboundGameProfilePacket(this.gameProfile)); -- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); -+ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper - - if (entityplayer != null) { - this.state = ServerLoginPacketListenerImpl.State.DELAY_ACCEPT; -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 454d60566743e02e7e55868c7bb45e30583dfa8f..ffc8c9ee8b1768dd809189858ee45658fb9bf1c5 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -36,6 +36,7 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; - import net.minecraft.network.protocol.game.ClientboundChatPacket; - import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; -+import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; - import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; - import net.minecraft.network.protocol.game.ClientboundGameEventPacket; - import net.minecraft.network.protocol.game.ClientboundLoginPacket; -@@ -59,6 +60,8 @@ import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.PlayerAdvancements; - import net.minecraft.server.ServerScoreboard; -+import net.minecraft.server.level.ChunkHolder; -+import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.level.ServerPlayerGameMode; -@@ -124,11 +127,12 @@ public abstract class PlayerList { - private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); - private final MinecraftServer server; - public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety -- private final Map playersByUUID = Maps.newHashMap(); -+ private final Map playersByUUID = Maps.newHashMap();Map getUUIDMap() { return playersByUUID; } // Paper - OBFHELPER - private final UserBanList bans; - private final IpBanList ipBans; - private final ServerOpList ops; - private final UserWhiteList whitelist; -+ private final Map pendingPlayers = Maps.newHashMap(); // Paper - // CraftBukkit start - // private final Map o; - // private final Map p; -@@ -167,6 +171,11 @@ public abstract class PlayerList { - } - - public void placeNewPlayer(Connection connection, ServerPlayer player) { -+ ServerPlayer prev = pendingPlayers.put(player.getUUID(), player);// Paper -+ if (prev != null) { -+ disconnectPendingPlayer(prev); -+ } -+ player.networkManager = connection; // Paper - player.loginTime = System.currentTimeMillis(); // Paper - GameProfile gameprofile = player.getGameProfile(); - GameProfileCache usercache = this.server.getProfileCache(); -@@ -180,7 +189,7 @@ public abstract class PlayerList { - if (nbttagcompound != null && nbttagcompound.contains("bukkit")) { - CompoundTag bukkit = nbttagcompound.getCompound("bukkit"); - s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; -- } -+ }String lastKnownName = s; // Paper - // CraftBukkit end - - if (nbttagcompound != null) { -@@ -255,34 +264,79 @@ public abstract class PlayerList { - player.getRecipeBook().sendInitialRecipeBook(player); - this.updateEntireScoreboard(worldserver1.getScoreboard(), player); - this.server.invalidateStatus(); -+ // Paper start - async load spawn in chunk -+ ServerLevel finalWorldserver = worldserver1; -+ int chunkX = loc.getBlockX() >> 4; -+ int chunkZ = loc.getBlockZ() >> 4; -+ final ChunkPos pos = new ChunkPos(chunkX, chunkZ); -+ ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; -+ playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.toLong()); -+ worldserver1.getChunkSource().runDistanceManagerUpdates(); -+ worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { -+ ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); -+ if (updatingChunk != null) { -+ return updatingChunk.getEntityTickingFuture(); -+ } else { -+ return java.util.concurrent.CompletableFuture.completedFuture(chunk); -+ } -+ }).thenAccept(chunk -> { -+ playerconnection.playerJoinReady = () -> { -+ postChunkLoadJoin( -+ player, finalWorldserver, connection, playerconnection, -+ nbttagcompound, connection.getRemoteAddress().toString(), lastKnownName -+ ); -+ }; -+ }); -+ } -+ -+ public ServerPlayer getActivePlayer(UUID uuid) { -+ ServerPlayer player = this.getUUIDMap().get(uuid); -+ return player != null ? player : pendingPlayers.get(uuid); -+ } -+ -+ void disconnectPendingPlayer(ServerPlayer entityplayer) { -+ TranslatableComponent msg = new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0]); -+ entityplayer.networkManager.send(new ClientboundDisconnectPacket(msg), (future) -> { -+ entityplayer.networkManager.disconnect(msg); -+ entityplayer.networkManager = null; -+ }); -+ } -+ -+ private void postChunkLoadJoin(ServerPlayer entityplayer, ServerLevel worldserver1, Connection networkmanager, ServerGamePacketListenerImpl playerconnection, CompoundTag nbttagcompound, String s1, String s) { -+ pendingPlayers.remove(entityplayer.getUUID(), entityplayer); -+ if (!networkmanager.isConnected()) { -+ return; -+ } -+ entityplayer.didPlayerJoinEvent = true; -+ // Paper end - TranslatableComponent chatmessage; - -- if (player.getGameProfile().getName().equalsIgnoreCase(s)) { -- chatmessage = new TranslatableComponent("multiplayer.player.joined", new Object[]{player.getDisplayName()}); -+ if (entityplayer.getGameProfile().getName().equalsIgnoreCase(s)) { -+ chatmessage = new TranslatableComponent("multiplayer.player.joined", new Object[]{entityplayer.getDisplayName()}); - } else { -- chatmessage = new TranslatableComponent("multiplayer.player.joined.renamed", new Object[]{player.getDisplayName(), s}); -+ chatmessage = new TranslatableComponent("multiplayer.player.joined.renamed", new Object[]{entityplayer.getDisplayName(), s}); - } - // CraftBukkit start - chatmessage.withStyle(ChatFormatting.YELLOW); - Component joinMessage = chatmessage; // Paper - Adventure - -- playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.yRot, player.xRot); -- this.players.add(player); -- this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot -- this.playersByUUID.put(player.getUUID(), player); -+ playerconnection.teleport(entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), entityplayer.yRot, entityplayer.xRot); -+ this.players.add(entityplayer); -+ this.playersByName.put(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT), entityplayer); // Spigot -+ this.playersByUUID.put(entityplayer.getUUID(), entityplayer); - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below - - // Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks -- player.supressTrackerForLogin = true; -- worldserver1.addNewPlayer(player); -- this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below worldserver.addPlayerJoin(entityplayer); -- mountSavedVehicle(player, worldserver1, nbttagcompound); -+ entityplayer.supressTrackerForLogin = true; -+ worldserver1.addNewPlayer(entityplayer); -+ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); // see commented out section below worldserver.addPlayerJoin(entityplayer); -+ mountSavedVehicle(entityplayer, worldserver1, nbttagcompound); - // Paper end - // CraftBukkit start -- PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure -+ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - cserver.getPluginManager().callEvent(playerJoinEvent); - -- if (!player.connection.connection.isConnected()) { -+ if (!entityplayer.connection.connection.isConnected()) { - return; - } - -@@ -297,51 +351,51 @@ public abstract class PlayerList { - // CraftBukkit end - - // CraftBukkit start - sendAll above replaced with this loop -- ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, player); -+ ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, entityplayer); - - for (int i = 0; i < this.players.size(); ++i) { - ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i); - -- if (entityplayer1.getBukkitEntity().canSee(player.getBukkitEntity())) { -+ if (entityplayer1.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { - entityplayer1.connection.send(packet); - } - -- if (!player.getBukkitEntity().canSee(entityplayer1.getBukkitEntity())) { -+ if (!entityplayer.getBukkitEntity().canSee(entityplayer1.getBukkitEntity())) { - continue; - } - -- player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); -+ entityplayer.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); - } -- player.sentListPacket = true; -- player.supressTrackerForLogin = false; // Paper -- ((ServerLevel)player.level).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now -+ entityplayer.sentListPacket = true; -+ entityplayer.supressTrackerForLogin = false; // Paper -+ ((ServerLevel)entityplayer.level).getChunkSource().chunkMap.addEntity(entityplayer); // Paper - track entity now - // CraftBukkit end - -- player.connection.send(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn -+ entityplayer.connection.send(new ClientboundSetEntityDataPacket(entityplayer.getId(), entityplayer.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn - - // CraftBukkit start - Only add if the player wasn't moved in the event -- if (player.level == worldserver1 && !worldserver1.players().contains(player)) { -- worldserver1.addNewPlayer(player); -- this.server.getCustomBossEvents().onPlayerConnect(player); -+ if (entityplayer.level == worldserver1 && !worldserver1.players().contains(entityplayer)) { -+ worldserver1.addNewPlayer(entityplayer); -+ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); - } - -- worldserver1 = player.getLevel(); // CraftBukkit - Update in case join event changed it -+ worldserver1 = entityplayer.getLevel(); // CraftBukkit - Update in case join event changed it - // CraftBukkit end -- this.sendLevelInfo(player, worldserver1); -+ this.sendLevelInfo(entityplayer, worldserver1); - if (!this.server.getResourcePack().isEmpty()) { -- player.sendTexturePack(this.server.getResourcePack(), this.server.getResourcePackHash()); -+ entityplayer.sendTexturePack(this.server.getResourcePack(), this.server.getResourcePackHash()); - } - -- Iterator iterator = player.getActiveEffects().iterator(); -+ Iterator iterator = entityplayer.getActiveEffects().iterator(); - - while (iterator.hasNext()) { - MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); - -- playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect)); -+ playerconnection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobeffect)); - } - - // Paper start - move vehicle into method so it can be called above - short circuit around that code -- onPlayerJoinFinish(player, worldserver1, s1); -+ onPlayerJoinFinish(entityplayer, worldserver1, s1); - } - private void mountSavedVehicle(ServerPlayer entityplayer, ServerLevel worldserver1, CompoundTag nbttagcompound) { - // Paper end -@@ -492,6 +546,7 @@ public abstract class PlayerList { - - protected void save(ServerPlayer player) { - if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit -+ if (!player.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) - this.playerIo.save(player); - ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit - -@@ -519,7 +574,7 @@ public abstract class PlayerList { - } - - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); -- cserver.getPluginManager().callEvent(playerQuitEvent); -+ if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - - if (server.isSameThread()) entityplayer.doTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) -@@ -572,6 +627,13 @@ public abstract class PlayerList { - // this.p.remove(uuid); - // CraftBukkit end - } -+ // Paper start -+ entityplayer1 = pendingPlayers.get(uuid); -+ if (entityplayer1 == entityplayer) { -+ pendingPlayers.remove(uuid); -+ } -+ entityplayer.networkManager = null; -+ // Paper end - - // CraftBukkit start - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[]{entityplayer})); -@@ -589,7 +651,7 @@ public abstract class PlayerList { - cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); - // CraftBukkit end - -- return playerQuitEvent.quitMessage(); // Paper - Adventure -+ return entityplayer.didPlayerJoinEvent ? playerQuitEvent.quitMessage() : null; // CraftBukkit // Paper - Adventure // Paper - don't print quit if we never printed join - } - - // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer -@@ -608,6 +670,13 @@ public abstract class PlayerList { - list.add(entityplayer); - } - } -+ // Paper start - check pending players too -+ entityplayer = pendingPlayers.get(uuid); -+ if (entityplayer != null) { -+ this.pendingPlayers.remove(uuid); -+ disconnectPendingPlayer(entityplayer); -+ } -+ // Paper end - - Iterator iterator = list.iterator(); - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b8dcc91a191f25ca578e0858abf6c1b874fee15d..9f0371282f5829d26dc9618c3d466bccaa4cd3af 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1371,7 +1371,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.yo = y; - this.zo = d4; - this.setPos(d3, y, d4); -- level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit -+ if (valid) level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit // Paper - } - - public void moveTo(Vec3 vec3d) { diff --git a/Remapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/Remapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch deleted file mode 100644 index eeaa3a49f4..0000000000 --- a/Remapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: 2277 <38501234+2277@users.noreply.github.com> -Date: Tue, 31 Mar 2020 10:33:55 +0100 -Subject: [PATCH] Move player to spawn point if spawn in unloaded world - -The code following this has better support for null worlds to move -them back to the world spawn. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 9f0371282f5829d26dc9618c3d466bccaa4cd3af..34226102c50a4353c42e68917d41c44d251e602f 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1808,9 +1808,11 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - bworld = server.getWorld(worldName); - } - -- if (bworld == null) { -- bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getLevel(Level.OVERWORLD).getWorld(); -- } -+ // Paper start - Move player to spawn point if spawn in unloaded world -+// if (bworld == null) { -+// bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld(); -+// } -+ // Paper end - Move player to spawn point if spawn in unloaded world - - setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle()); - } diff --git a/Remapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch b/Remapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch deleted file mode 100644 index f1eab97e33..0000000000 --- a/Remapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: nossr50 -Date: Thu, 26 Mar 2020 19:44:50 -0700 -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 46b962183e2e27ed93054ad9fb6d8ecbf70bc5f9..cec1e6105b8c2ac3d1482c00482d53d6be0d38d1 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1928,7 +1928,16 @@ public abstract class LivingEntity extends Entity { - - 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 -+ 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()) { -+ player.resetAttackStrengthTicker(); -+ } -+ } else { -+ ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); -+ } -+ // Paper end - } - if (event.isCancelled()) { - return false; diff --git a/Remapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/Remapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch deleted file mode 100644 index 025b5a9d8e..0000000000 --- a/Remapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 21 Apr 2020 03:51:53 -0400 -Subject: [PATCH] Allow multiple callbacks to schedule for Callback Executor - -ChunkMapDistance polls multiple entries for pendingChunkUpdates - -Each of these have the potential to move a chunk in and out of -"Loaded" state, which will result in multiple callbacks being -needed within a single tick of ChunkMapDistance - -Use an ArrayDeque to store this Queue - -We make sure to also implement a pattern that is recursion safe too. - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 97a582614ad28f9fa864ae9be4860658e5979214..6c7af93cead523830d32b007cc69b313e59abef1 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -160,24 +160,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public final CallbackExecutor callbackExecutor = new CallbackExecutor(); - public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { - -- private Runnable queued; -+ // Paper start - replace impl with recursive safe multi entry queue -+ // it's possible to schedule multiple tasks currently, so it's vital we change this impl -+ // If we recurse into the executor again, we will append to another queue, ensuring task order consistency -+ private java.util.ArrayDeque queued = new java.util.ArrayDeque<>(); - - @Override - public void execute(Runnable runnable) { -- if (queued != null) { -- throw new IllegalStateException("Already queued"); -+ if (queued == null) { -+ queued = new java.util.ArrayDeque<>(); - } -- queued = runnable; -+ queued.add(runnable); - } - - @Override - public void run() { -- Runnable task = queued; -+ if (queued == null) { -+ return; -+ } -+ java.util.ArrayDeque queue = queued; - queued = null; -- if (task != null) { -+ Runnable task; -+ while ((task = queue.pollFirst()) != null) { - task.run(); - } - } -+ // Paper end - }; - // CraftBukkit end - diff --git a/Remapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch b/Remapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch deleted file mode 100644 index 8997a0897d..0000000000 --- a/Remapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 23 Apr 2020 01:36:39 -0400 -Subject: [PATCH] Don't fire BlockFade on worldgen threads - -Caused a deadlock - -diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java -index 31b6c1333c7d0af28385e804e94348cef398748b..ac63c5bef5b35b158e57835d765bbdd15fc60664 100644 ---- a/src/main/java/net/minecraft/world/level/block/FireBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java -@@ -93,6 +93,7 @@ public class FireBlock extends BaseFireBlock { - @Override - public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { - // CraftBukkit start -+ if (!(world instanceof ServerLevel)) return this.canSurvive(state, world, pos) ? (BlockState) this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)) : Blocks.AIR.defaultBlockState(); // Paper - don't fire events in world generation - if (!this.canSurvive(state, world, pos)) { - // Suppress during worldgen - if (!(world instanceof Level)) { -@@ -108,7 +109,7 @@ public class FireBlock extends BaseFireBlock { - return blockState.getHandle(); - } - } -- return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)); -+ return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)); // Paper - diff on change, see "don't fire events in world generation" - // CraftBukkit end - } - diff --git a/Remapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch b/Remapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch deleted file mode 100644 index 9a052de409..0000000000 --- a/Remapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 25 Apr 2020 15:13:41 -0500 -Subject: [PATCH] Add phantom creative and insomniac controls - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index cd248eb6be663e8be33f2c3c6b06b77b6d5753a4..46ac6d91422423f1e03b86d3efa3241f2599000d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -625,4 +625,11 @@ public class PaperWorldConfig { - private void lightQueueSize() { - lightQueueSize = getInt("light-queue-size", lightQueueSize); - } -+ -+ public boolean phantomIgnoreCreative = true; -+ public boolean phantomOnlyAttackInsomniacs = true; -+ private void phantomSettings() { -+ phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); -+ phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index e7facd849e3511c64b4ae44b34382f4a4985f2a4..8ce62148ebaeac9988e7c9d4b2f7ee57f58d883e 100644 ---- a/src/main/java/net/minecraft/world/entity/EntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -3,6 +3,9 @@ package net.minecraft.world.entity; - import com.google.common.base.Predicates; - import java.util.function.Predicate; - import javax.annotation.Nullable; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.stats.Stats; -+import net.minecraft.util.Mth; - import net.minecraft.world.Container; - import net.minecraft.world.Difficulty; - import net.minecraft.world.entity.player.Player; -@@ -31,10 +34,11 @@ public final class EntitySelector { - public static final Predicate NO_SPECTATORS = (entity) -> { - return !entity.isSpectator(); - }; -+ public static Predicate isInsomniac = (player) -> Mth.clamp(((ServerPlayer) player).getStats().getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper - - // Paper start - public static final Predicate affectsSpawning = (entity) -> { -- return !entity.isSpectator() && entity.isAlive() && (entity instanceof EntityPlayer) && ((EntityPlayer) entity).affectsSpawning; -+ return !entity.isSpectator() && entity.isAlive() && (entity instanceof ServerPlayer) && ((ServerPlayer) entity).affectsSpawning; - }; - // Paper end - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index e37137a2890330b92e05d6f76c46ffc99a527803..a40c23e824652cff59633b7c314e27ec9a515c07 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -@@ -262,6 +262,7 @@ public class Phantom extends FlyingMob implements Enemy { - Player entityhuman = (Player) iterator.next(); - - if (Phantom.this.canAttack((LivingEntity) entityhuman, TargetingConditions.DEFAULT)) { -+ if (!level.paperConfig.phantomOnlyAttackInsomniacs || EntitySelector.isInsomniac.test(entityhuman)) // Paper - Phantom.this.setGoalTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason - return true; - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java -index 42effcbd3ca7c38a4e8b1aa835543ad243112a33..79504dc3448402e73b09c4232b1fd0488872cf68 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java -@@ -53,7 +53,7 @@ public class PhantomSpawner implements CustomSpawner { - while (iterator.hasNext()) { - Player entityhuman = (Player) iterator.next(); - -- if (!entityhuman.isSpectator()) { -+ if (!entityhuman.isSpectator() && (!world.paperConfig.phantomIgnoreCreative || !entityhuman.isCreative())) { // Paper - BlockPos blockposition = entityhuman.blockPosition(); - - if (!world.dimensionType().hasSkyLight() || blockposition.getY() >= world.getSeaLevel() && world.canSeeSky(blockposition)) { diff --git a/Remapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/Remapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch deleted file mode 100644 index 9e378d1d32..0000000000 --- a/Remapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 25 Apr 2020 06:46:35 -0400 -Subject: [PATCH] Fix numerous item duplication issues and teleport issues - -This notably fixes the newest "Donkey Dupe", but also fixes a lot -of dupe bugs in general around nether portals and entity world transfer - -We also fix item duplication generically by anytime we clone an item -to drop it on the ground, destroy the source item. - -This avoid an itemstack ever existing twice in the world state pre -clean up stage. - -So even if something NEW comes up, it would be impossible to drop the -same item twice because the source was destroyed. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 34226102c50a4353c42e68917d41c44d251e602f..2b48c4a2b512c42bed2c767db90a28898c74286a 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1973,11 +1973,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } else { - // CraftBukkit start - Capture drops for death event - if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) { -- ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(stack)); -+ ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack)); // Paper - mirror so we can destroy it later - return null; - } - // CraftBukkit end -- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY() + (double) yOffset, this.getZ(), stack); -+ ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY() + (double) yOffset, this.getZ(), stack.copy()); // Paper - clone so we can destroy original -+ stack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe - - entityitem.setDefaultPickUpDelay(); - // CraftBukkit start -@@ -2625,6 +2626,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - @Nullable - public Entity teleportTo(ServerLevel worldserver, BlockPos location) { - // CraftBukkit end -+ // Paper start - fix bad state entities causing dupes -+ if (!isAlive() || !valid) { -+ LOGGER.warn("Illegal Entity Teleport " + this + " to " + worldserver + ":" + location, new Throwable()); -+ return null; -+ } -+ // Paper end - if (this.level instanceof ServerLevel && !this.removed) { - this.level.getProfiler().push("changeDimension"); - // CraftBukkit start -@@ -2645,6 +2652,11 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - // CraftBukkit end - - this.level.getProfiler().popPush("reloading"); -+ // Paper start - Change lead drop timing to prevent dupe -+ if (this instanceof Mob) { -+ ((Mob) this).dropLeash(true, true); // Paper drop lead -+ } -+ // Paper end - Entity entity = this.getType().create((Level) worldserver); - - if (entity != null) { -@@ -2658,10 +2670,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - // CraftBukkit start - Forward the CraftEntity to the new entity - this.getBukkitEntity().setHandle(entity); - entity.bukkitEntity = this.getBukkitEntity(); -- -- if (this instanceof Mob) { -- ((Mob) this).dropLeash(true, false); // Unleash to prevent duping of leads. -- } - // CraftBukkit end - } - -@@ -2786,7 +2794,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public boolean canChangeDimensions() { -- return true; -+ return isAlive() && valid; // Paper - } - - 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/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 33d51852ed6fe3f5adcdecf8f405a23689f4265a..5714aa450ac09788bcf1c2790d4f1581c9a7c28b 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -598,7 +598,7 @@ public class ArmorStand extends LivingEntity { - for (i = 0; i < this.handItems.size(); ++i) { - itemstack = (ItemStack) this.handItems.get(i); - if (!itemstack.isEmpty()) { -- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops -+ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe - this.handItems.set(i, ItemStack.EMPTY); - } - } -@@ -606,7 +606,7 @@ public class ArmorStand extends LivingEntity { - for (i = 0; i < this.armorItems.size(); ++i) { - itemstack = (ItemStack) this.armorItems.get(i); - if (!itemstack.isEmpty()) { -- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops -+ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe - this.armorItems.set(i, ItemStack.EMPTY); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 7d9a3b65b2d6b294d3a11414289e64fac88665f0..87fe7f4f5ed70bf1b3dc1e2a392ba42a1f8f568b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -815,7 +815,8 @@ public class CraftEventFactory { - for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { - if (stack == null || stack.getType() == Material.AIR || stack.getAmount() == 0) continue; - -- world.dropItem(entity.getLocation(), stack); -+ world.dropItem(entity.getLocation(), stack); // Paper - note: dropItem already clones due to this being bukkit -> NMS -+ if (stack instanceof CraftItemStack) stack.setAmount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe, but don't nuke bukkit stacks of manually added items - } - - return event; diff --git a/Remapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch b/Remapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch deleted file mode 100644 index 5504aee900..0000000000 --- a/Remapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 18:15:29 -0400 -Subject: [PATCH] Implement Brigadier Mojang API - -Adds AsyncPlayerSendCommandsEvent - - Allows modifying on a per command basis what command data they see. - -Adds CommandRegisteredEvent - - Allows manipulating the CommandNode to add more children/metadata for the client - -diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java -index f74765f31bc7272724ee7fac0cc5a8c852550006..e1f4ffaa36bfffb7741c74b7a094e26a03a9a1e6 100644 ---- a/src/main/java/net/minecraft/commands/CommandSourceStack.java -+++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java -@@ -37,7 +37,7 @@ import net.minecraft.world.phys.Vec2; - import net.minecraft.world.phys.Vec3; - import com.mojang.brigadier.tree.CommandNode; // CraftBukkit - --public class CommandSourceStack implements SharedSuggestionProvider { -+public class CommandSourceStack implements SharedSuggestionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource { // Paper - - public static final SimpleCommandExceptionType ERROR_NOT_PLAYER = new SimpleCommandExceptionType(new TranslatableComponent("permissions.requires.player")); - public static final SimpleCommandExceptionType ERROR_NOT_ENTITY = new SimpleCommandExceptionType(new TranslatableComponent("permissions.requires.entity")); -@@ -149,6 +149,25 @@ public class CommandSourceStack implements SharedSuggestionProvider { - return this.textName; - } - -+ // Paper start -+ @Override -+ public org.bukkit.entity.Entity getBukkitEntity() { -+ return getEntity() != null ? getEntity().getBukkitEntity() : null; -+ } -+ -+ @Override -+ public org.bukkit.World getBukkitWorld() { -+ return getLevel() != null ? getLevel().getWorld() : null; -+ } -+ -+ @Override -+ public org.bukkit.Location getBukkitLocation() { -+ Vec3 pos = getPosition(); -+ org.bukkit.World world = getBukkitWorld(); -+ return world != null && pos != null ? new org.bukkit.Location(world, pos.x, pos.y, pos.z) : null; -+ } -+ // Paper end -+ - @Override - public boolean hasPermission(int level) { - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java -index 8154d9327c5411bbfea3bfa4d99d57feab764664..c63033e3eb50423a7c32acfc0e705623cc4bec68 100644 ---- a/src/main/java/net/minecraft/commands/Commands.java -+++ b/src/main/java/net/minecraft/commands/Commands.java -@@ -355,6 +355,7 @@ public class Commands { - bukkit.add(node.getName()); - } - // Paper start - Async command map building -+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper - MinecraftServer.getServer().execute(() -> { - runSync(entityplayer, bukkit, rootcommandnode); - }); -@@ -362,6 +363,7 @@ public class Commands { - - private void runSync(ServerPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { - // Paper end - Async command map building -+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper - PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); - event.getPlayer().getServer().getPluginManager().callEvent(event); - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 1bed6e69bf3cc1ab9b0c1259de4f643bf58371aa..5f12987b93f1578624626c4e911d1757dee3d45f 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -768,8 +768,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); - - this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -- this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); -+ // Paper start -+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); -+ suggestEvent.setCancelled(suggestions.isEmpty()); -+ if (!suggestEvent.callEvent()) return; -+ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), (com.mojang.brigadier.suggestion.Suggestions) suggestEvent.getSuggestions())); // CraftBukkit - decompile error // Paper -+ // Paper end - }); - }); - } -@@ -778,7 +782,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); - completions.forEach(builder::suggest); -- player.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), builder.buildFuture().join())); -+ com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); -+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); -+ suggestEvent.setCancelled(suggestions.isEmpty()); -+ if (!suggestEvent.callEvent()) return; -+ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestEvent.getSuggestions())); - } - // Paper end - async tab completion - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -index f9a245503c8982d1756503a6179f3715d919d910..b17002abdb43e74da4eb61e65e45c5e0e1dc0f95 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -@@ -17,7 +17,7 @@ import net.minecraft.commands.CommandSourceStack; - import org.bukkit.command.Command; - import org.bukkit.craftbukkit.CraftServer; - --public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider { -+public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommand { // Paper - - private final CraftServer server; - private final Command command; -@@ -28,10 +28,19 @@ public class BukkitCommandWrapper implements com.mojang.brigadier.Command register(CommandDispatcher dispatcher, String label) { -- return dispatcher.register( -- LiteralArgumentBuilder.literal(label).requires(this).executes(this) -- .then(RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this)) -- ); -+ // Paper start - Expose Brigadier to Paper-MojangAPI -+ com.mojang.brigadier.tree.RootCommandNode root = dispatcher.getRoot(); -+ LiteralCommandNode literal = LiteralArgumentBuilder.literal(label).requires(this).executes(this).build(); -+ com.mojang.brigadier.tree.ArgumentCommandNode defaultArgs = RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this).build(); -+ literal.addChild(defaultArgs); -+ com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent event = new com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent<>(label, this, this.command, root, literal, defaultArgs); -+ if (!event.callEvent()) { -+ return null; -+ } -+ literal = event.getLiteral(); -+ root.addChild(literal); -+ return literal; -+ // Paper end - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch b/Remapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch deleted file mode 100644 index 49b6ff50fa..0000000000 --- a/Remapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: zbk -Date: Sun, 26 Apr 2020 23:49:01 -0400 -Subject: [PATCH] Villager Restocks API - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 4aa34320ef7d6c62ccb17734bfa61d406190b919..a83a7d37f3d769535161fda46fca6f71dcc4d515 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/Villager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -112,7 +112,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - private long lastGossipDecayTime; - private int villagerXp; - private long lastRestockGameTime; -- private int numberOfRestocksToday; -+ private int numberOfRestocksToday; public int getRestocksToday(){ return this.numberOfRestocksToday; } public void setRestocksToday(int restocksToday){ this.numberOfRestocksToday = restocksToday; } // Paper OBFHELPER - private long lastRestockCheckDayTime; - private boolean assignProfessionWhenSpawned; - private static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.MOBS, MemoryModuleType.VISIBLE_MOBS, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.WALK_TARGET, new MemoryModuleType[]{MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index 5a21e9447c3e0225b07144eec83c277dd101bfd5..d0b933cfd02b237bfe85011831dab6e8e966496e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -@@ -83,6 +83,18 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { - getHandle().setVillagerXp(experience); - } - -+ // Paper start -+ @Override -+ public int getRestocksToday() { -+ return getHandle().getRestocksToday(); -+ } -+ -+ @Override -+ public void setRestocksToday(int restocksToday) { -+ getHandle().setRestocksToday(restocksToday); -+ } -+ // Paper end -+ - @Override - public boolean sleep(Location location) { - Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/Remapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch b/Remapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch deleted file mode 100644 index 34909e54c5..0000000000 --- a/Remapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 2 May 2020 03:09:46 -0400 -Subject: [PATCH] Validate PickItem Packet and kick for invalid - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 5f12987b93f1578624626c4e911d1757dee3d45f..3f416479e23c60ec5b4b779cce9ab62c74865ac8 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -881,7 +881,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - @Override - public void handlePickItem(ServerboundPickItemPacket packet) { - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); -- this.player.inventory.pickSlot(packet.getSlot()); -+ // Paper start - validate pick item position -+ if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.inventory.items.size())) { -+ ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); -+ this.disconnect("Invalid hotbar selection (Hacking?)"); -+ return; -+ } -+ this.player.inventory.pickSlot(packet.getSlot()); // Paper - Diff above if changed -+ // Paper end - this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, this.player.inventory.selected, this.player.inventory.getItem(this.player.inventory.selected))); - this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, packet.getSlot(), this.player.inventory.getItem(packet.getSlot()))); - this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.inventory.selected)); diff --git a/Remapped-Spigot-Server-Patches/0461-Expose-game-version.patch b/Remapped-Spigot-Server-Patches/0461-Expose-game-version.patch deleted file mode 100644 index 9e0cf63bd9..0000000000 --- a/Remapped-Spigot-Server-Patches/0461-Expose-game-version.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Fri, 1 May 2020 17:39:26 +0300 -Subject: [PATCH] Expose game version - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 43c37e660a8a7f9d326ad38e66f9aa7c53c7b87c..1bfe96443877e460d22513d59ebc3b5988e8eb43 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -514,6 +514,13 @@ public final class CraftServer implements Server { - return bukkitVersion; - } - -+ // Paper start - expose game version -+ @Override -+ public String getMinecraftVersion() { -+ return console.getServerVersion(); -+ } -+ // Paper end -+ - @Override - public List getOnlinePlayers() { - return this.playerView; diff --git a/Remapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch b/Remapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch deleted file mode 100644 index 935b12df1e..0000000000 --- a/Remapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch +++ /dev/null @@ -1,175 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 May 2020 22:35:09 -0400 -Subject: [PATCH] Optimize Voxel Shape Merging - -This method shows up as super hot in profiler, and also a high "self" time. - -Upon analyzing, it appears most usages of this method fall down to the final -else statement of the nasty ternary. - -Upon even further analyzation, it appears then the majority of those have a -consistent list 1.... One with Infinity head and Tails. - -First optimization is to detect these infinite states and immediately return that -VoxelShapeMergerList so we can avoid testing the rest for most cases. - -Break the method into 2 to help the JVM promote inlining of this fast path. - -Then it was also noticed that VoxelShapeMergerList constructor is also a hotspot -with a high self time... - -Well, knowing that in most cases our list 1 is actualy the same value, it allows -us to know that with an infinite list1, the result on the merger is essentially -list2 as the final values. - -This let us analyze the 2 potential states (Infinite with 2 sources or 4 sources) -and compute a deterministic result for the MergerList values. - -Additionally, this lets us avoid even allocating new objects for this too, further -reducing memory usage. - -diff --git a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java -index f0e74daa5bb9e88c028225e7c71deb04c481a7ac..abbe05b07831423eccf8779e854251dec5fbc2ae 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java -@@ -6,10 +6,16 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; - - public final class IndirectMerger implements IndexMerger { - -- private final DoubleArrayList result; -+ private final DoubleList a; // Paper - private final IntArrayList firstIndices; - private final IntArrayList secondIndices; - -+ // Paper start -+ private static final IntArrayList INFINITE_B_1 = new IntArrayList(new int[]{1, 1}); -+ private static final IntArrayList INFINITE_B_0 = new IntArrayList(new int[]{0, 0}); -+ private static final IntArrayList INFINITE_C = new IntArrayList(new int[]{0, 1}); -+ // Paper end -+ - protected IndirectMerger(DoubleList first, DoubleList second, boolean includeFirstOnly, boolean includeSecondOnly) { - int i = 0; - int j = 0; -@@ -18,7 +24,23 @@ public final class IndirectMerger implements IndexMerger { - int l = second.size(); - int i1 = k + l; - -- this.result = new DoubleArrayList(i1); -+ // Paper start - optimize common path of infinity doublelist -+ int size = first.size(); -+ double tail = first.getDouble(size - 1); -+ double head = first.getDouble(0); -+ if (head == Double.NEGATIVE_INFINITY && tail == Double.POSITIVE_INFINITY && !includeFirstOnly && !includeSecondOnly && (size == 2 || size == 4)) { -+ this.a = second; -+ if (size == 2) { -+ this.firstIndices = INFINITE_B_0; -+ } else { -+ this.firstIndices = INFINITE_B_1; -+ } -+ this.secondIndices = INFINITE_C; -+ return; -+ } -+ // Paper end -+ -+ this.a = new DoubleArrayList(i1); - this.firstIndices = new IntArrayList(i1); - this.secondIndices = new IntArrayList(i1); - -@@ -27,8 +49,8 @@ public final class IndirectMerger implements IndexMerger { - boolean flag3 = j < l; - - if (!flag2 && !flag3) { -- if (this.result.isEmpty()) { -- this.result.add(Math.min(first.getDouble(k - 1), second.getDouble(l - 1))); -+ if (this.a.isEmpty()) { -+ this.a.add(Math.min(first.getDouble(k - 1), second.getDouble(l - 1))); - } - - return; -@@ -41,9 +63,9 @@ public final class IndirectMerger implements IndexMerger { - if (!(d0 >= d1 - 1.0E-7D)) { // Paper - decompile error - welcome to hell - this.firstIndices.add(i - 1); - this.secondIndices.add(j - 1); -- this.result.add(d1); -+ this.a.add(d1); - d0 = d1; -- } else if (!this.result.isEmpty()) { -+ } else if (!this.a.isEmpty()) { - this.firstIndices.set(this.firstIndices.size() - 1, i - 1); - this.secondIndices.set(this.secondIndices.size() - 1, j - 1); - } -@@ -53,7 +75,7 @@ public final class IndirectMerger implements IndexMerger { - - @Override - public boolean forMergedIndexes(IndexMerger.IndexConsumer predicate) { -- for (int i = 0; i < this.result.size() - 1; ++i) { -+ for (int i = 0; i < this.a.size() - 1; ++i) { - if (!predicate.merge(this.firstIndices.getInt(i), this.secondIndices.getInt(i), i)) { - return false; - } -@@ -64,6 +86,6 @@ public final class IndirectMerger implements IndexMerger { - - @Override - public DoubleList getList() { -- return this.result; -+ return this.a; - } - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -index c14d5ebe16a693834ed218af8f737714065b2e17..1603eb3f7d90a4b3a028b20776566db77d09c123 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -@@ -329,19 +329,46 @@ public final class Shapes { - } - - @VisibleForTesting -- protected static IndexMerger createIndexMerger(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { -- int j = first.size() - 1; -- int k = second.size() - 1; -+ private static IndexMerger createIndexMerger(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { // Paper - private -+ // Paper start - fast track the most common scenario -+ // doublelist is usually a DoubleArrayList with Infinite head/tails that falls to the final else clause -+ // This is actually the most common path, so jump to it straight away -+ if (first.getDouble(0) == Double.NEGATIVE_INFINITY && first.getDouble(first.size() - 1) == Double.POSITIVE_INFINITY) { -+ return new IndirectMerger(first, second, includeFirst, includeSecond); -+ } -+ // Split out rest to hopefully inline the above -+ return lessCommonMerge(size, first, second, includeFirst, includeSecond); -+ } -+ -+ private static IndexMerger lessCommonMerge(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { -+ int j = doublelist.size() - 1; -+ int k = doublelist1.size() - 1; -+ // Paper note - Rewrite below as optimized order if instead of nasty ternary - -- if (first instanceof CubePointRange && second instanceof CubePointRange) { -+ if (doublelist instanceof CubePointRange && doublelist1 instanceof CubePointRange) { - long l = lcm(j, k); - -- if ((long) size * l <= 256L) { -+ if ((long) i * l <= 256L) { - return new DiscreteCubeMerger(j, k); - } - } - -- return (IndexMerger) (first.getDouble(j) < second.getDouble(0) - 1.0E-7D ? new NonOverlappingMerger(first, second, false) : (second.getDouble(k) < first.getDouble(0) - 1.0E-7D ? new NonOverlappingMerger(second, first, true) : (j == k && Objects.equals(first, second) ? (first instanceof IdenticalMerger ? (IndexMerger) first : (second instanceof IdenticalMerger ? (IndexMerger) second : new IdenticalMerger(first))) : new IndirectMerger(first, second, includeFirst, includeSecond)))); -+ // Identical happens more often than Disjoint -+ if (j == k && Objects.equals(doublelist, doublelist1)) { -+ if (doublelist instanceof IdenticalMerger) { -+ return (IndexMerger) doublelist; -+ } else if (doublelist1 instanceof IdenticalMerger) { -+ return (IndexMerger) doublelist1; -+ } -+ return new IdenticalMerger(doublelist); -+ } else if (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-07) { -+ return new NonOverlappingMerger(doublelist, doublelist1, false); -+ } else if (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-07) { -+ return new NonOverlappingMerger(doublelist1, doublelist, true); -+ } else { -+ return new IndirectMerger(doublelist, doublelist1, flag, flag1); -+ } -+ // Paper end - } - - public interface DoubleLineConsumer { diff --git a/Remapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/Remapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch deleted file mode 100644 index d35e663567..0000000000 --- a/Remapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 4 May 2020 01:08:56 -0400 -Subject: [PATCH] Set cap on JDK per-thread native byte buffer cache - -See: https://www.evanjones.ca/java-bytebuffer-leak.html - -This is potentially a source of lots of native memory usage. - -We are clearly seeing native usage upwards to 1-4GB which doesn't make sense. - -Region File usage fixed in previous patch should of tecnically only been somewhat -temporary until GC finally gets it some time later, but between all the various -plugins doing IO on various threads, this hidden detail of the JDK could be -keeping long lived large direct buffers in cache. - -Set system properly at server startup if not set already to help protect from this. - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index c288b89bf5a22269823ba1d18af217032d7c6a36..bd10345cb90f98b8af1519afd603a5244f3a5ca2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -28,6 +28,7 @@ public class Main { - } - // Paper end - // Todo: Installation script -+ if (System.getProperty("jdk.nio.maxCachedBufferSize") == null) System.setProperty("jdk.nio.maxCachedBufferSize", "262144"); // Paper - cap per-thread NIO cache size - OptionParser parser = new OptionParser() { - { - acceptsAll(asList("?", "help"), "Show the help"); diff --git a/Remapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch b/Remapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch deleted file mode 100644 index 0aaed21f24..0000000000 --- a/Remapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch +++ /dev/null @@ -1,1104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Fri, 3 Jan 2020 16:26:19 +0100 -Subject: [PATCH] Implement Mob Goal API - - -diff --git a/pom.xml b/pom.xml -index 4c8a057e790c96b0ab5123549d0566371acacb46..1a9204c869dd36e80932b1366352db15ebd70723 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -176,6 +176,13 @@ - 1.3 - test - -+ -+ -+ io.github.classgraph -+ classgraph -+ 4.8.47 -+ test -+ - - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6ddb198f86ccf3bc2471752d5fb2f59d9a7ab4df ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -@@ -0,0 +1,462 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import GoalKey; -+import GoalType; -+import com.destroystokyo.paper.entity.RangedEntity; -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; -+import com.google.common.collect.BiMap; -+import com.google.common.collect.HashBiMap; -+import java.lang.reflect.Constructor; -+import java.util.EnumSet; -+import java.util.HashMap; -+import java.util.HashSet; -+import java.util.Map; -+import java.util.Set; -+import net.minecraft.world.entity.AgableMob; -+import net.minecraft.world.entity.FlyingMob; -+import net.minecraft.world.entity.PathfinderMob; -+import net.minecraft.world.entity.TamableAnimal; -+import net.minecraft.world.entity.ai.goal.Goal; -+import net.minecraft.world.entity.ambient.AmbientCreature; -+import net.minecraft.world.entity.animal.AbstractFish; -+import net.minecraft.world.entity.animal.AbstractGolem; -+import net.minecraft.world.entity.animal.AbstractSchoolingFish; -+import net.minecraft.world.entity.animal.Animal; -+import net.minecraft.world.entity.animal.Pufferfish; -+import net.minecraft.world.entity.animal.ShoulderRidingEntity; -+import net.minecraft.world.entity.animal.SnowGolem; -+import net.minecraft.world.entity.animal.WaterAnimal; -+import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; -+import net.minecraft.world.entity.boss.wither.WitherBoss; -+import net.minecraft.world.entity.monster.AbstractIllager; -+import net.minecraft.world.entity.monster.AbstractSkeleton; -+import net.minecraft.world.entity.monster.EnderMan; -+import net.minecraft.world.entity.monster.PatrollingMonster; -+import net.minecraft.world.entity.monster.RangedAttackMob; -+import net.minecraft.world.entity.monster.SpellcasterIllager; -+import net.minecraft.world.entity.monster.ZombifiedPiglin; -+import net.minecraft.world.entity.monster.piglin.AbstractPiglin; -+import org.bukkit.NamespacedKey; -+import org.bukkit.entity.AbstractHorse; -+import org.bukkit.entity.AbstractVillager; -+import org.bukkit.entity.Ageable; -+import org.bukkit.entity.Ambient; -+import org.bukkit.entity.Animals; -+import org.bukkit.entity.Bat; -+import org.bukkit.entity.Bee; -+import org.bukkit.entity.Blaze; -+import org.bukkit.entity.Cat; -+import org.bukkit.entity.CaveSpider; -+import org.bukkit.entity.ChestedHorse; -+import org.bukkit.entity.Chicken; -+import org.bukkit.entity.Cod; -+import org.bukkit.entity.Cow; -+import org.bukkit.entity.Creature; -+import org.bukkit.entity.Creeper; -+import org.bukkit.entity.Dolphin; -+import org.bukkit.entity.Donkey; -+import org.bukkit.entity.Drowned; -+import org.bukkit.entity.ElderGuardian; -+import org.bukkit.entity.EnderDragon; -+import org.bukkit.entity.Enderman; -+import org.bukkit.entity.Endermite; -+import org.bukkit.entity.Evoker; -+import org.bukkit.entity.Fish; -+import org.bukkit.entity.Flying; -+import org.bukkit.entity.Fox; -+import org.bukkit.entity.Ghast; -+import org.bukkit.entity.Giant; -+import org.bukkit.entity.Golem; -+import org.bukkit.entity.Guardian; -+import org.bukkit.entity.Hoglin; -+import org.bukkit.entity.Horse; -+import org.bukkit.entity.Husk; -+import org.bukkit.entity.Illager; -+import org.bukkit.entity.Illusioner; -+import org.bukkit.entity.IronGolem; -+import org.bukkit.entity.Llama; -+import org.bukkit.entity.MagmaCube; -+import org.bukkit.entity.Mob; -+import org.bukkit.entity.Monster; -+import org.bukkit.entity.Mule; -+import org.bukkit.entity.MushroomCow; -+import org.bukkit.entity.Ocelot; -+import org.bukkit.entity.Panda; -+import org.bukkit.entity.Parrot; -+import org.bukkit.entity.Phantom; -+import org.bukkit.entity.Pig; -+import org.bukkit.entity.PigZombie; -+import org.bukkit.entity.Piglin; -+import org.bukkit.entity.PiglinAbstract; -+import org.bukkit.entity.PiglinBrute; -+import org.bukkit.entity.Pillager; -+import org.bukkit.entity.PolarBear; -+import org.bukkit.entity.PufferFish; -+import org.bukkit.entity.Rabbit; -+import org.bukkit.entity.Raider; -+import org.bukkit.entity.Ravager; -+import org.bukkit.entity.Salmon; -+import org.bukkit.entity.Sheep; -+import org.bukkit.entity.Shulker; -+import org.bukkit.entity.Silverfish; -+import org.bukkit.entity.Skeleton; -+import org.bukkit.entity.SkeletonHorse; -+import org.bukkit.entity.Slime; -+import org.bukkit.entity.Snowman; -+import org.bukkit.entity.Spellcaster; -+import org.bukkit.entity.Spider; -+import org.bukkit.entity.Squid; -+import org.bukkit.entity.Stray; -+import org.bukkit.entity.Strider; -+import org.bukkit.entity.Tameable; -+import org.bukkit.entity.TraderLlama; -+import org.bukkit.entity.TropicalFish; -+import org.bukkit.entity.Turtle; -+import org.bukkit.entity.Vex; -+import org.bukkit.entity.Villager; -+import org.bukkit.entity.Vindicator; -+import org.bukkit.entity.WanderingTrader; -+import org.bukkit.entity.WaterMob; -+import org.bukkit.entity.Witch; -+import org.bukkit.entity.Wither; -+import org.bukkit.entity.WitherSkeleton; -+import org.bukkit.entity.Wolf; -+import org.bukkit.entity.Zoglin; -+import org.bukkit.entity.Zombie; -+import org.bukkit.entity.ZombieHorse; -+import org.bukkit.entity.ZombieVillager; -+ -+public class MobGoalHelper { -+ -+ private static final BiMap deobfuscationMap = HashBiMap.create(); -+ private static final Map, Class> entityClassCache = new HashMap<>(); -+ private static final Map, Class> bukkitMap = new HashMap<>(); -+ -+ static final Set ignored = new HashSet<>(); -+ -+ static { -+ // TODO these kinda should be checked on each release, in case obfuscation changes -+ deobfuscationMap.put("bee_b", "bee_attack"); -+ deobfuscationMap.put("bee_c", "bee_become_angry"); -+ deobfuscationMap.put("bee_d", "bee_enter_hive"); -+ deobfuscationMap.put("bee_e", "bee_go_to_hive"); -+ deobfuscationMap.put("bee_f", "bee_go_to_known_flower"); -+ deobfuscationMap.put("bee_g", "bee_grow_crop"); -+ deobfuscationMap.put("bee_h", "bee_hurt_by_other"); -+ deobfuscationMap.put("bee_i", "bee_locate_hive"); -+ deobfuscationMap.put("bee_k", "bee_pollinate"); -+ deobfuscationMap.put("bee_l", "bee_wander"); -+ deobfuscationMap.put("cat_a", "cat_avoid_entity"); -+ deobfuscationMap.put("cat_b", "cat_relax_on_owner"); -+ deobfuscationMap.put("dolphin_b", "dolphin_swim_to_treasure"); -+ deobfuscationMap.put("dolphin_c", "dolphin_swim_with_player"); -+ deobfuscationMap.put("dolphin_d", "dolphin_play_with_items"); -+ deobfuscationMap.put("drowned_a", "drowned_attack"); -+ deobfuscationMap.put("drowned_b", "drowned_goto_beach"); -+ deobfuscationMap.put("drowned_c", "drowned_goto_water"); -+ deobfuscationMap.put("drowned_e", "drowned_swim_up"); -+ deobfuscationMap.put("drowned_f", "drowned_trident_attack"); -+ deobfuscationMap.put("enderman_a", "enderman_freeze_when_looked_at"); -+ deobfuscationMap.put("evoker_a", "evoker_attack_spell"); -+ deobfuscationMap.put("evoker_b", "evoker_cast_spell"); -+ deobfuscationMap.put("evoker_c", "evoker_summon_spell"); -+ deobfuscationMap.put("evoker_d", "evoker_wololo_spell"); -+ deobfuscationMap.put("fish_b", "fish_swim"); -+ deobfuscationMap.put("fox_a", "fox_defend_trusted"); -+ deobfuscationMap.put("fox_b", "fox_faceplant"); -+ deobfuscationMap.put("fox_e", "fox_breed"); -+ deobfuscationMap.put("fox_f", "fox_eat_berries"); -+ deobfuscationMap.put("fox_g", "fox_float"); -+ deobfuscationMap.put("fox_h", "fox_follow_parent"); -+ deobfuscationMap.put("fox_j", "fox_look_at_player"); -+ deobfuscationMap.put("fox_l", "fox_melee_attack"); -+ deobfuscationMap.put("fox_n", "fox_panic"); -+ deobfuscationMap.put("fox_o", "fox_pounce"); -+ deobfuscationMap.put("fox_p", "fox_search_for_items"); -+ deobfuscationMap.put("fox_q", "fox_stroll_through_village"); -+ deobfuscationMap.put("fox_r", "fox_perch_and_search"); -+ deobfuscationMap.put("fox_s", "fox_seek_shelter"); -+ deobfuscationMap.put("fox_t", "fox_sleep"); -+ deobfuscationMap.put("fox_u", "fox_stalk_prey"); -+ deobfuscationMap.put("illager_abstract_b", "raider_open_door"); -+ deobfuscationMap.put("illager_illusioner_a", "illusioner_blindness_spell"); -+ deobfuscationMap.put("illager_illusioner_b", "illusioner_mirror_spell"); -+ deobfuscationMap.put("illager_wizard_b", "spellcaster_cast_spell"); -+ deobfuscationMap.put("llama_a", "llama_attack_wolf"); -+ deobfuscationMap.put("llama_c", "llama_hurt_by"); -+ deobfuscationMap.put("llama_trader_a", "llamatrader_defended_wandering_trader"); -+ deobfuscationMap.put("monster_patrolling_a", "long_distance_patrol"); -+ deobfuscationMap.put("ocelot_a", "ocelot_avoid_entity"); -+ deobfuscationMap.put("ocelot_b", "ocelot_tempt"); -+ deobfuscationMap.put("panda_b", "panda_attack"); -+ deobfuscationMap.put("panda_c", "panda_avoid"); -+ deobfuscationMap.put("panda_d", "panda_breed"); -+ deobfuscationMap.put("panda_e", "panda_hurt_by_target"); -+ deobfuscationMap.put("panda_f", "panda_lie_on_back"); -+ deobfuscationMap.put("panda_g", "panda_look_at_player"); -+ deobfuscationMap.put("panda_i", "panda_panic"); -+ deobfuscationMap.put("panda_j", "panda_roll"); -+ deobfuscationMap.put("panda_k", "panda_sit"); -+ deobfuscationMap.put("panda_l", "panda_sneeze"); -+ deobfuscationMap.put("phantom_b", "phantom_attack_player"); -+ deobfuscationMap.put("phantom_c", "phantom_attack_strategy"); -+ deobfuscationMap.put("phantom_e", "phantom_circle_around_anchor"); -+ deobfuscationMap.put("phantom_i", "phantom_sweep_attack"); -+ deobfuscationMap.put("polar_bear_a", "polarbear_attack_players"); -+ deobfuscationMap.put("polar_bear_b", "polarbear_hurt_by"); -+ deobfuscationMap.put("polar_bear_c", "polarbear_melee"); -+ deobfuscationMap.put("polar_bear_d", "polarbear_panic"); -+ deobfuscationMap.put("puffer_fish_a", "pufferfish_puff"); -+ deobfuscationMap.put("raider_a", "raider_hold_ground"); -+ deobfuscationMap.put("raider_b", "raider_obtain_banner"); -+ deobfuscationMap.put("raider_c", "raider_celebration"); -+ deobfuscationMap.put("raider_d", "raider_move_through_village"); -+ deobfuscationMap.put("ravager_a", "ravager_melee_attack"); -+ deobfuscationMap.put("shulker_a", "shulker_attack"); -+ deobfuscationMap.put("shulker_c", "shulker_defense"); -+ deobfuscationMap.put("shulker_d", "shulker_nearest"); -+ deobfuscationMap.put("shulker_e", "shulker_peek"); -+ deobfuscationMap.put("squid_a", "squid_flee"); -+ deobfuscationMap.put("skeleton_abstract_1", "skeleton_melee"); -+ deobfuscationMap.put("strider_a", "strider_go_to_lava"); -+ deobfuscationMap.put("turtle_a", "turtle_breed"); -+ deobfuscationMap.put("turtle_b", "turtle_go_home"); -+ deobfuscationMap.put("turtle_c", "turtle_goto_water"); -+ deobfuscationMap.put("turtle_d", "turtle_lay_egg"); -+ deobfuscationMap.put("turtle_f", "turtle_panic"); -+ deobfuscationMap.put("turtle_h", "turtle_random_stroll"); -+ deobfuscationMap.put("turtle_i", "turtle_tempt"); -+ deobfuscationMap.put("turtle_j", "turtle_travel"); -+ deobfuscationMap.put("vex_a", "vex_charge_attack"); -+ deobfuscationMap.put("vex_b", "vex_copy_target_of_owner"); -+ deobfuscationMap.put("vex_d", "vex_random_move"); -+ deobfuscationMap.put("villager_trader_a", "villagertrader_wander_to_position"); -+ deobfuscationMap.put("vindicator_a", "vindicator_break_door"); -+ deobfuscationMap.put("vindicator_b", "vindicator_johnny_attack"); -+ deobfuscationMap.put("vindicator_c", "vindicator_melee_attack"); -+ deobfuscationMap.put("wither_a", "wither_do_nothing"); -+ deobfuscationMap.put("wolf_a", "wolf_avoid_entity"); -+ deobfuscationMap.put("zombie_a", "zombie_attack_turtle_egg"); -+ -+ ignored.add("selector_1"); -+ ignored.add("selector_2"); -+ ignored.add("wrapped"); -+ -+ bukkitMap.put(net.minecraft.world.entity.Mob.class, Mob.class); -+ bukkitMap.put(AgableMob.class, Ageable.class); -+ bukkitMap.put(AmbientCreature.class, Ambient.class); -+ bukkitMap.put(Animal.class, Animals.class); -+ bukkitMap.put(net.minecraft.world.entity.ambient.Bat.class, Bat.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Bee.class, Bee.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Blaze.class, Blaze.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Cat.class, Cat.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.CaveSpider.class, CaveSpider.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Chicken.class, Chicken.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Cod.class, Cod.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Cow.class, Cow.class); -+ bukkitMap.put(PathfinderMob.class, Creature.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Creeper.class, Creeper.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Dolphin.class, Dolphin.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Drowned.class, Drowned.class); -+ bukkitMap.put(net.minecraft.world.entity.boss.enderdragon.EnderDragon.class, EnderDragon.class); -+ bukkitMap.put(EnderMan.class, Enderman.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Endermite.class, Endermite.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Evoker.class, Evoker.class); -+ bukkitMap.put(AbstractFish.class, Fish.class); -+ bukkitMap.put(AbstractSchoolingFish.class, Fish.class); // close enough -+ bukkitMap.put(FlyingMob.class, Flying.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Fox.class, Fox.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Ghast.class, Ghast.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Giant.class, Giant.class); -+ bukkitMap.put(AbstractGolem.class, Golem.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Guardian.class, Guardian.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.ElderGuardian.class, ElderGuardian.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.horse.Horse.class, Horse.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.horse.AbstractHorse.class, AbstractHorse.class); -+ bukkitMap.put(AbstractChestedHorse.class, ChestedHorse.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.horse.Donkey.class, Donkey.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.horse.Mule.class, Mule.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.horse.SkeletonHorse.class, SkeletonHorse.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.horse.ZombieHorse.class, ZombieHorse.class); -+ bukkitMap.put(AbstractIllager.class, Illager.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Illusioner.class, Illusioner.class); -+ bukkitMap.put(SpellcasterIllager.class, Spellcaster.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.IronGolem.class, IronGolem.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.horse.Llama.class, Llama.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.horse.TraderLlama.class, TraderLlama.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.MagmaCube.class, MagmaCube.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Monster.class, Monster.class); -+ bukkitMap.put(PatrollingMonster.class, Monster.class); // close enough -+ bukkitMap.put(net.minecraft.world.entity.animal.MushroomCow.class, MushroomCow.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Ocelot.class, Ocelot.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Panda.class, Panda.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Parrot.class, Parrot.class); -+ bukkitMap.put(ShoulderRidingEntity.class, Parrot.class); // close enough -+ bukkitMap.put(net.minecraft.world.entity.monster.Phantom.class, Phantom.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Pig.class, Pig.class); -+ bukkitMap.put(ZombifiedPiglin.class, PigZombie.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Pillager.class, Pillager.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.PolarBear.class, PolarBear.class); -+ bukkitMap.put(Pufferfish.class, PufferFish.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Rabbit.class, Rabbit.class); -+ bukkitMap.put(net.minecraft.world.entity.raid.Raider.class, Raider.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Ravager.class, Ravager.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Salmon.class, Salmon.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Sheep.class, Sheep.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Shulker.class, Shulker.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Silverfish.class, Silverfish.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Skeleton.class, Skeleton.class); -+ bukkitMap.put(AbstractSkeleton.class, Skeleton.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Stray.class, Stray.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.WitherSkeleton.class, WitherSkeleton.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Slime.class, Slime.class); -+ bukkitMap.put(SnowGolem.class, Snowman.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Spider.class, Spider.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Squid.class, Squid.class); -+ bukkitMap.put(TamableAnimal.class, Tameable.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.TropicalFish.class, TropicalFish.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Turtle.class, Turtle.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Vex.class, Vex.class); -+ bukkitMap.put(net.minecraft.world.entity.npc.Villager.class, Villager.class); -+ bukkitMap.put(net.minecraft.world.entity.npc.AbstractVillager.class, AbstractVillager.class); -+ bukkitMap.put(net.minecraft.world.entity.npc.WanderingTrader.class, WanderingTrader.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Vindicator.class, Vindicator.class); -+ bukkitMap.put(WaterAnimal.class, WaterMob.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Witch.class, Witch.class); -+ bukkitMap.put(WitherBoss.class, Wither.class); -+ bukkitMap.put(net.minecraft.world.entity.animal.Wolf.class, Wolf.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Zombie.class, Zombie.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Husk.class, Husk.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.ZombieVillager.class, ZombieVillager.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.hoglin.Hoglin.class, Hoglin.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.piglin.Piglin.class, Piglin.class); -+ bukkitMap.put(AbstractPiglin.class, PiglinAbstract.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.piglin.PiglinBrute.class, PiglinBrute.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Strider.class, Strider.class); -+ bukkitMap.put(net.minecraft.world.entity.monster.Zoglin.class, Zoglin.class); -+ } -+ -+ public static String getUsableName(Class clazz) { -+ String name = clazz.getName(); -+ name = name.substring(name.lastIndexOf(".") + 1); -+ boolean flag = false; -+ // inner classes -+ if (name.contains("$")) { -+ String cut = name.substring(name.indexOf("$") + 1); -+ if (cut.length() <= 2) { -+ name = name.replace("Entity", ""); -+ name = name.replace("$", "_"); -+ flag = true; -+ } else { -+ // mapped, wooo -+ name = cut; -+ } -+ } -+ name = name.replace("PathfinderGoal", ""); -+ StringBuilder sb = new StringBuilder(); -+ for (char c : name.toCharArray()) { -+ if (c >= 'A' && c <= 'Z') { -+ sb.append("_"); -+ sb.append(Character.toLowerCase(c)); -+ } else { -+ sb.append(c); -+ } -+ } -+ name = sb.toString(); -+ name = name.replaceFirst("_", ""); -+ -+ if (flag && !deobfuscationMap.containsKey(name.toLowerCase()) && !ignored.contains(name)) { -+ System.out.println("need to map " + clazz.getName() + " (" + name.toLowerCase() + ")"); -+ } -+ -+ // did we rename this key? -+ return deobfuscationMap.getOrDefault(name, name); -+ } -+ -+ public static EnumSet vanillaToPaper(OptimizedSmallEnumSet types) { -+ EnumSet goals = EnumSet.noneOf(GoalType.class); -+ for (GoalType type : GoalType.values()) { -+ if (types.hasElement(paperToVanilla(type))) { -+ goals.add(type); -+ } -+ } -+ return goals; -+ } -+ -+ public static GoalType vanillaToPaper(Goal.Flag type) { -+ switch (type) { -+ case MOVE: -+ return GoalType.MOVE; -+ case LOOK: -+ return GoalType.LOOK; -+ case JUMP: -+ return GoalType.JUMP; -+ case UNKNOWN_BEHAVIOR: -+ return GoalType.UNKNOWN_BEHAVIOR; -+ case TARGET: -+ return GoalType.TARGET; -+ default: -+ throw new IllegalArgumentException("Unknown vanilla mob goal type " + type.name()); -+ } -+ } -+ -+ public static EnumSet paperToVanilla(EnumSet types) { -+ EnumSet goals = EnumSet.noneOf(Goal.Flag.class); -+ for (GoalType type : types) { -+ goals.add(paperToVanilla(type)); -+ } -+ return goals; -+ } -+ -+ public static Goal.Flag paperToVanilla(GoalType type) { -+ switch (type) { -+ case MOVE: -+ return Goal.Flag.MOVE; -+ case LOOK: -+ return Goal.Flag.LOOK; -+ case JUMP: -+ return Goal.Flag.JUMP; -+ case UNKNOWN_BEHAVIOR: -+ return Goal.Flag.UNKNOWN_BEHAVIOR; -+ case TARGET: -+ return Goal.Flag.TARGET; -+ default: -+ throw new IllegalArgumentException("Unknown paper mob goal type " + type.name()); -+ } -+ } -+ -+ public static GoalKey getKey(Class goalClass) { -+ String name = getUsableName(goalClass); -+ if (ignored.contains(name)) { -+ //noinspection unchecked -+ return (GoalKey) GoalKey.of(Mob.class, NamespacedKey.minecraft(name)); -+ } -+ return GoalKey.of(getEntity(goalClass), NamespacedKey.minecraft(name)); -+ } -+ -+ public static Class getEntity(Class goalClass) { -+ //noinspection unchecked -+ return (Class) entityClassCache.computeIfAbsent(goalClass, key -> { -+ for (Constructor ctor : key.getDeclaredConstructors()) { -+ for (int i = 0; i < ctor.getParameterCount(); i++) { -+ Class param = ctor.getParameterTypes()[i]; -+ if (net.minecraft.world.entity.Mob.class.isAssignableFrom(param)) { -+ //noinspection unchecked -+ return toBukkitClass((Class) param); -+ } else if (RangedAttackMob.class.isAssignableFrom(param)) { -+ return RangedEntity.class; -+ } -+ } -+ } -+ throw new RuntimeException("Can't figure out applicable entity for mob goal " + goalClass); // maybe just return EntityInsentient? -+ }); -+ } -+ -+ public static Class toBukkitClass(Class nmsClass) { -+ Class bukkitClass = bukkitMap.get(nmsClass); -+ if (bukkitClass == null) { -+ throw new RuntimeException("Can't figure out applicable bukkit entity for nms entity " + nmsClass); // maybe just return Mob? -+ } -+ return bukkitClass; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java -new file mode 100644 -index 0000000000000000000000000000000000000000..14ddf844be10c04522aa3ec125fa7a0f540b10c2 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java -@@ -0,0 +1,55 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import GoalKey; -+import net.minecraft.world.entity.ai.goal.Goal; -+import org.bukkit.entity.Mob; -+ -+/** -+ * Wraps api in vanilla -+ */ -+public class PaperCustomGoal extends Goal { -+ -+ private final Goal handle; -+ -+ public PaperCustomGoal(Goal handle) { -+ this.handle = handle; -+ -+ this.setTypes(MobGoalHelper.paperToVanilla(handle.getTypes())); -+ if (this.getGoalTypes().size() == 0) { -+ this.getGoalTypes().addUnchecked(Flag.UNKNOWN_BEHAVIOR); -+ } -+ } -+ -+ @Override -+ public boolean shouldActivate() { -+ return handle.shouldActivate(); -+ } -+ -+ @Override -+ public boolean shouldStayActive() { -+ return handle.shouldStayActive(); -+ } -+ -+ @Override -+ public void start() { -+ handle.start(); -+ } -+ -+ @Override -+ public void onTaskReset() { -+ handle.stop(); -+ } -+ -+ @Override -+ public void tick() { -+ handle.tick(); -+ } -+ -+ public Goal getHandle() { -+ return handle; -+ } -+ -+ public GoalKey getKey() { -+ return handle.getKey(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java -new file mode 100644 -index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959e82e4ab1 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java -@@ -0,0 +1,222 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import java.util.Collection; -+import java.util.EnumSet; -+import java.util.HashMap; -+import java.util.HashSet; -+import java.util.LinkedList; -+import java.util.List; -+import java.util.Map; -+import java.util.Set; -+import net.minecraft.world.entity.ai.goal.Goal; -+import net.minecraft.world.entity.ai.goal.GoalSelector; -+import net.minecraft.world.entity.ai.goal.WrappedGoal; -+import org.bukkit.craftbukkit.entity.CraftMob; -+import org.bukkit.entity.Mob; -+ -+public class PaperMobGoals implements MobGoals { -+ -+ private final Map> instanceCache = new HashMap<>(); -+ -+ @Override -+ public void addGoal(T mob, int priority, Goal goal) { -+ CraftMob craftMob = (CraftMob) mob; -+ getHandle(craftMob, goal.getTypes()).addGoal(priority, new PaperCustomGoal<>(goal)); -+ } -+ -+ @Override -+ public void removeGoal(T mob, Goal goal) { -+ CraftMob craftMob = (CraftMob) mob; -+ if (goal instanceof PaperCustomGoal) { -+ getHandle(craftMob, goal.getTypes()).removeGoal((Goal) goal); -+ } else if (goal instanceof PaperVanillaGoal) { -+ getHandle(craftMob, goal.getTypes()).removeGoal(((PaperVanillaGoal) goal).getHandle()); -+ } else { -+ List toRemove = new LinkedList<>(); -+ for (WrappedGoal item : getHandle(craftMob, goal.getTypes()).getTasks()) { -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ if (((PaperCustomGoal) item.getGoal()).getHandle() == goal) { -+ toRemove.add(item.getGoal()); -+ } -+ } -+ } -+ -+ for (Goal g : toRemove) { -+ getHandle(craftMob, goal.getTypes()).removeGoal(g); -+ } -+ } -+ } -+ -+ @Override -+ public void removeAllGoals(T mob) { -+ for (GoalType type : GoalType.values()) { -+ removeAllGoals(mob, type); -+ } -+ } -+ -+ @Override -+ public void removeAllGoals(T mob, GoalType type) { -+ for (Goal goal : getAllGoals(mob, type)) { -+ removeGoal(mob, goal); -+ } -+ } -+ -+ @Override -+ public void removeGoal(T mob, GoalKey key) { -+ for (Goal goal : getGoals(mob, key)) { -+ removeGoal(mob, goal); -+ } -+ } -+ -+ @Override -+ public boolean hasGoal(T mob, GoalKey key) { -+ for (Goal g : getAllGoals(mob)) { -+ if (g.getKey().equals(key)) { -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ @Override -+ public Goal getGoal(T mob, GoalKey key) { -+ for (Goal g : getAllGoals(mob)) { -+ if (g.getKey().equals(key)) { -+ return g; -+ } -+ } -+ return null; -+ } -+ -+ @Override -+ public Collection> getGoals(T mob, GoalKey key) { -+ Set> goals = new HashSet<>(); -+ for (Goal g : getAllGoals(mob)) { -+ if (g.getKey().equals(key)) { -+ goals.add(g); -+ } -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getAllGoals(T mob) { -+ Set> goals = new HashSet<>(); -+ for (GoalType type : GoalType.values()) { -+ goals.addAll(getAllGoals(mob, type)); -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getAllGoals(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ for (WrappedGoal item : getHandle(craftMob, type).getTasks()) { -+ if (!item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { -+ continue; -+ } -+ -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getAllGoalsWithout(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ for (GoalType internalType : GoalType.values()) { -+ if (internalType == type) { -+ continue; -+ } -+ for (WrappedGoal item : getHandle(craftMob, internalType).getTasks()) { -+ if (item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { -+ continue; -+ } -+ -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ } -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getRunningGoals(T mob) { -+ Set> goals = new HashSet<>(); -+ for (GoalType type : GoalType.values()) { -+ goals.addAll(getRunningGoals(mob, type)); -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getRunningGoals(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ getHandle(craftMob, type).getExecutingGoals() -+ .filter(item -> item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) -+ .forEach(item -> { -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ }); -+ return goals; -+ } -+ -+ @Override -+ public Collection> getRunningGoalsWithout(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ for (GoalType internalType : GoalType.values()) { -+ if (internalType == type) { -+ continue; -+ } -+ getHandle(craftMob, internalType).getExecutingGoals() -+ .filter(item -> !item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) -+ .forEach(item -> { -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ }); -+ } -+ return goals; -+ } -+ -+ private GoalSelector getHandle(CraftMob mob, EnumSet types) { -+ if (types.contains(GoalType.TARGET)) { -+ return mob.getHandle().targetSelector; -+ } else { -+ return mob.getHandle().goalSelector; -+ } -+ } -+ -+ private GoalSelector getHandle(CraftMob mob, GoalType type) { -+ if (type == GoalType.TARGET) { -+ return mob.getHandle().targetSelector; -+ } else { -+ return mob.getHandle().goalSelector; -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d4fe9d517a05f99c715ab73d5baf1deb6a732068 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java -@@ -0,0 +1,62 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import GoalKey; -+import java.util.EnumSet; -+import net.minecraft.world.entity.ai.goal.Goal; -+import org.bukkit.entity.Mob; -+ -+/** -+ * Wraps vanilla in api -+ */ -+public class PaperVanillaGoal implements VanillaGoal { -+ -+ private final Goal handle; -+ private final GoalKey key; -+ -+ private final EnumSet types; -+ -+ public PaperVanillaGoal(Goal handle) { -+ this.handle = handle; -+ this.key = MobGoalHelper.getKey(handle.getClass()); -+ this.types = MobGoalHelper.vanillaToPaper(handle.getGoalTypes()); -+ } -+ -+ public Goal getHandle() { -+ return handle; -+ } -+ -+ @Override -+ public boolean shouldActivate() { -+ return handle.shouldActivate2(); -+ } -+ -+ @Override -+ public boolean shouldStayActive() { -+ return handle.shouldStayActive2(); -+ } -+ -+ @Override -+ public void start() { -+ handle.start(); -+ } -+ -+ @Override -+ public void stop() { -+ handle.onTaskReset(); -+ } -+ -+ @Override -+ public void tick() { -+ handle.tick(); -+ } -+ -+ @Override -+ public GoalKey getKey() { -+ return key; -+ } -+ -+ @Override -+ public EnumSet getTypes() { -+ return types; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -index 9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f..b3329c6fcd6758a781a51f5ba8f5052ac1c77b49 100644 ---- a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -+++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -@@ -64,4 +64,8 @@ public final class OptimizedSmallEnumSet> { - public boolean hasCommonElements(final OptimizedSmallEnumSet other) { - return (other.backingSet & this.backingSet) != 0; - } -+ -+ public boolean hasElement(final E element) { -+ return (this.backingSet & (1L << element.ordinal())) != 0; -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -index acc6306d659cd65a043d12cd42dcbaf55aaf5250..f85dfd8b57cf81ad7c6b12753fdd42e93f772f9e 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -@@ -8,11 +8,17 @@ public abstract class Goal { - private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. - private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector - -- public Goal() {} -+ // Paper start make sure goaltypes is never empty -+ public Goal() { -+ if (this.goalTypes.size() == 0) { -+ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR); -+ } -+ } -+ // paper end - -- public abstract boolean canUse(); -+ public boolean canUse() { return this.shouldActivate(); } public boolean shouldActivate() { return false;} public boolean shouldActivate2() { return canUse(); } // Paper - OBFHELPER, for both directions... - -- public boolean canContinueToUse() { -+ public boolean canContinueToUse() { return this.shouldStayActive(); } public boolean shouldStayActive2() { return canContinueToUse(); } public boolean shouldStayActive() { // Paper - OBFHELPER, for both directions... - return this.canUse(); - } - -@@ -20,19 +26,23 @@ public abstract class Goal { - return true; - } - -- public void start() {} -+ public void start() { this.start(); } public void start() {} // Paper - OBFHELPER - - public void stop() { - onTaskReset(); // Paper - } - public void onTaskReset() {} // Paper - -- public void tick() {} -+ public void tick() { this.tick(); } public void tick() {} // Paper OBFHELPER - -- public void setFlags(EnumSet controls) { -+ public void setFlags(EnumSet controls) { this.setTypes(controls); } public void setTypes(EnumSet enumset) { // Paper - OBFHELPER - // Paper start - remove streams from pathfindergoalselector - this.goalTypes.clear(); -- this.goalTypes.addAllUnchecked(controls); -+ this.goalTypes.addAllUnchecked(enumset); -+ // make sure its never empty -+ if (this.goalTypes.size() == 0) { -+ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR); -+ } - // Paper end - remove streams from pathfindergoalselector - } - -@@ -48,7 +58,7 @@ public abstract class Goal { - - public static enum Flag { - -- MOVE, LOOK, JUMP, TARGET; -+ MOVE, LOOK, JUMP, TARGET, UNKNOWN_BEHAVIOR; // Paper - add unknown - - private Flag() {} - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -index 5da2d780c17522e07c733a5e23b17ec760c7b342..a03f72f67948efab3b000dfa1d48061abf7cc02f 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -@@ -28,7 +28,7 @@ public class GoalSelector { - } - }; - private final Map lockedFlags = new EnumMap(Goal.Flag.class); -- private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER -+ private final Set availableGoals = Sets.newLinkedHashSet(); public final Set getTasks() { return availableGoals; }// Paper - OBFHELPER // Paper - private -> public - private final Supplier profiler; - private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. - private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector -@@ -39,7 +39,7 @@ public class GoalSelector { - this.profiler = profiler; - } - -- public void addGoal(int priority, Goal goal) { -+ public void addGoal(int priority, Goal goal) {addGoal(priority, goal);} public void addGoal(int priority, Goal goal) { // Paper - OBFHELPER - this.availableGoals.add(new WrappedGoal(priority, goal)); - } - -@@ -58,7 +58,7 @@ public class GoalSelector { - } - // Paper end - -- public void removeGoal(Goal goal) { -+ public void removeGoal(Goal goal) {removeGoal(goal);} public void removeGoal(Goal goal) { // Paper - OBFHELPER - // Paper start - remove streams from pathfindergoalselector - for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { - WrappedGoal goalWrapped = iterator.next(); -@@ -154,6 +154,7 @@ public class GoalSelector { - gameprofilerfiller.pop(); - } - -+ public final Stream getExecutingGoals() { return getRunningGoals(); } // Paper - OBFHELPER - public Stream getRunningGoals() { - return this.availableGoals.stream().filter(WrappedGoal::isRunning); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -index 984146b2b6eb3e498433b1c4971397848166d9c9..06fe2248a52c180ffabe0a6fe0cf155b78d4752d 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -@@ -5,8 +5,8 @@ import javax.annotation.Nullable; - - public class WrappedGoal extends Goal { - -- private final Goal goal; -- private final int priority; -+ private final Goal goal; public Goal getGoal() {return goal;} // Paper - OBFHELPER -+ private final int priority; public int getPriority() {return priority;} // Paper - OBFHELPER - private boolean isRunning; - - public WrappedGoal(int priority, Goal goal) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 1bfe96443877e460d22513d59ebc3b5988e8eb43..c6dc314a1735bf849ee1572e01335909bed9b455 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2390,5 +2390,11 @@ public final class CraftServer implements Server { - public boolean isStopping() { - return net.minecraft.server.MinecraftServer.getServer().hasStopped(); - } -+ -+ private com.destroystokyo.paper.entity.ai.MobGoals mobGoals = new com.destroystokyo.paper.entity.ai.PaperMobGoals(); -+ @Override -+ public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { -+ return mobGoals; -+ } - // Paper end - } -diff --git a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c0525216a8469613c3e0d4b5774a82f69e70fb16 ---- /dev/null -+++ b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java -@@ -0,0 +1,104 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import org.junit.Assert; -+import org.junit.Test; -+ -+import java.lang.reflect.Field; -+import java.lang.reflect.Modifier; -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+import java.util.stream.Collectors; -+ -+import org.bukkit.entity.Mob; -+ -+import io.github.classgraph.ClassGraph; -+import io.github.classgraph.ScanResult; -+ -+public class VanillaMobGoalTest { -+ -+ @Test -+ public void testKeys() { -+ List> deprecated = new ArrayList<>(); -+ List> keys = new ArrayList<>(); -+ for (Field field : VanillaGoal.class.getFields()) { -+ if (field.getType().equals(GoalKey.class)) { -+ try { -+ GoalKey goalKey = (GoalKey) field.get(null); -+ if (field.getAnnotation(Deprecated.class) != null) { -+ deprecated.add(goalKey); -+ } else { -+ keys.add(goalKey); -+ } -+ } catch (IllegalAccessException e) { -+ System.out.println("Skipping " + field.getName() + ": " + e.getMessage()); -+ } -+ } -+ } -+ -+ List> classes; -+ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) { -+ classes = scanResult.getSubclasses(PathfinderGoal.class.getName()).loadClasses(); -+ } -+ -+ List> vanillaNames = classes.stream() -+ .filter(VanillaMobGoalTest::hasNoEnclosingClass) -+ .filter(clazz -> !Modifier.isAbstract(clazz.getModifiers())) -+ .map(goalClass -> MobGoalHelper.getKey((Class) goalClass)) -+ .collect(Collectors.toList()); -+ -+ List> missingFromAPI = new ArrayList<>(vanillaNames); -+ missingFromAPI.removeAll(keys); -+ missingFromAPI.removeIf(k -> MobGoalHelper.ignored.contains(k.getNamespacedKey().getKey())); -+ List> missingFromVanilla = new ArrayList<>(keys); -+ missingFromVanilla.removeAll(vanillaNames); -+ -+ boolean shouldFail = false; -+ if (missingFromAPI.size() != 0) { -+ System.out.println("Missing from API: "); -+ for (GoalKey key : missingFromAPI) { -+ System.out.println("GoalKey<" + key.getEntityClass().getSimpleName() + "> " + key.getNamespacedKey().getKey().toUpperCase() + -+ " = GoalKey.of(" + key.getEntityClass().getSimpleName() + ".class, NamespacedKey.minecraft(\"" + key.getNamespacedKey().getKey() + "\"));"); -+ } -+ shouldFail = true; -+ } -+ if (missingFromVanilla.size() != 0) { -+ System.out.println("Missing from vanilla: "); -+ missingFromVanilla.forEach(System.out::println); -+ shouldFail = true; -+ } -+ -+ if (deprecated.size() != 0) { -+ System.out.println("Deprecated (might want to remove them at some point): "); -+ deprecated.forEach(System.out::println); -+ } -+ -+ if (shouldFail) Assert.fail("See above"); -+ } -+ -+ private static boolean hasNoEnclosingClass(Class clazz) { -+ return clazz.getEnclosingClass() == null || hasNoEnclosingClass(clazz.getSuperclass()); -+ } -+ -+ @Test -+ public void testBukkitMap() { -+ List> classes; -+ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft.world.entity").scan()) { -+ classes = scanResult.getSubclasses("net.minecraft.world.entity.EntityInsentient").loadClasses(); -+ } -+ Assert.assertNotEquals("There are supposed to be more than 0 entity types!", Collections.emptyList(), classes); -+ -+ boolean shouldFail = false; -+ for (Class nmsClass : classes) { -+ Class bukkitClass = MobGoalHelper.toBukkitClass((Class) nmsClass); -+ if (bukkitClass == null) { -+ shouldFail = true; -+ System.out.println("Missing bukkitMap.put(" + nmsClass.getSimpleName() + ".class, " + nmsClass.getSimpleName().replace("Entity", "") + ".class);"); -+ } -+ } -+ -+ if (shouldFail) Assert.fail("See above"); -+ } -+} diff --git a/Remapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch b/Remapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch deleted file mode 100644 index 16a647e328..0000000000 --- a/Remapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch +++ /dev/null @@ -1,413 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 20:18:05 -0700 -Subject: [PATCH] Use distance map to optimise entity tracker - -Use the distance map to find candidate players for tracking. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e5ad635a480d32e7a10ee92c65cfc18a98beafad..74f393ffa2ae2d0e25b3f0b674cef7a987e985d3 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1652,6 +1652,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); -+ // Paper start - use distance map to optimise tracker -+ public static boolean isLegacyTrackingEntity(Entity entity) { -+ return entity.isLegacyTrackingEntity; -+ } -+ -+ // inlined EnumMap, TrackingRange.TrackingRangeType -+ static final org.spigotmc.TrackingRange.TrackingRangeType[] TRACKING_RANGE_TYPES = org.spigotmc.TrackingRange.TrackingRangeType.values(); -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap[] playerEntityTrackerTrackMaps; -+ final int[] entityTrackerTrackRanges; -+ -+ private int convertSpigotRangeToVanilla(final int vanilla) { -+ return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); -+ } -+ // Paper end - use distance map to optimise tracker - - void addPlayerToDistanceMaps(ServerPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.getX()); - int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); - // Note: players need to be explicitly added to distance maps before they can be updated -+ // Paper start - use distance map to optimise entity tracker -+ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -+ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; -+ int trackRange = this.entityTrackerTrackRanges[i]; -+ -+ trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); -+ } -+ // Paper end - use distance map to optimise entity tracker - } - - void removePlayerFromDistanceMaps(ServerPlayer player) { -- -+ // Paper start - use distance map to optimise tracker -+ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -+ this.playerEntityTrackerTrackMaps[i].remove(player); -+ } -+ // Paper end - use distance map to optimise tracker - } - - void updateMaps(ServerPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.getX()); - int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); - // Note: players need to be explicitly added to distance maps before they can be updated -+ // Paper start - use distance map to optimise entity tracker -+ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -+ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; -+ int trackRange = this.entityTrackerTrackRanges[i]; -+ -+ trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); -+ } -+ // Paper end - use distance map to optimise entity tracker - } - // Paper end - -@@ -244,6 +279,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper - this.setViewDistance(i); - this.playerMobDistanceMap = this.level.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper -+ // Paper start - use distance map to optimise entity tracker -+ this.playerEntityTrackerTrackMaps = new com.destroystokyo.paper.util.misc.PlayerAreaMap[TRACKING_RANGE_TYPES.length]; -+ this.entityTrackerTrackRanges = new int[TRACKING_RANGE_TYPES.length]; -+ -+ org.spigotmc.SpigotWorldConfig spigotWorldConfig = this.level.spigotConfig; -+ -+ for (int ordinal = 0, len = TRACKING_RANGE_TYPES.length; ordinal < len; ++ordinal) { -+ org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = TRACKING_RANGE_TYPES[ordinal]; -+ int configuredSpigotValue; -+ switch (trackingRangeType) { -+ case PLAYER: -+ configuredSpigotValue = spigotWorldConfig.playerTrackingRange; -+ break; -+ case ANIMAL: -+ configuredSpigotValue = spigotWorldConfig.animalTrackingRange; -+ break; -+ case MONSTER: -+ configuredSpigotValue = spigotWorldConfig.monsterTrackingRange; -+ break; -+ case MISC: -+ configuredSpigotValue = spigotWorldConfig.miscTrackingRange; -+ break; -+ case OTHER: -+ configuredSpigotValue = spigotWorldConfig.otherTrackingRange; -+ break; -+ case ENDERDRAGON: -+ configuredSpigotValue = EntityType.ENDER_DRAGON.clientTrackingRange() * 16; -+ break; -+ default: -+ throw new IllegalStateException("Missing case for enum " + trackingRangeType); -+ } -+ configuredSpigotValue = convertSpigotRangeToVanilla(configuredSpigotValue); -+ -+ int trackRange = (configuredSpigotValue >>> 4) + ((configuredSpigotValue & 15) != 0 ? 1 : 0); -+ this.entityTrackerTrackRanges[ordinal] = trackRange; -+ -+ this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); -+ } -+ // Paper end - use distance map to optimise entity tracker - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -1490,17 +1564,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - public void move(ServerPlayer player) { -- ObjectIterator objectiterator = this.entityMap.values().iterator(); -- -- while (objectiterator.hasNext()) { -- ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); -- -- if (playerchunkmap_entitytracker.entity == player) { -- playerchunkmap_entitytracker.updatePlayers(this.level.players()); -- } else { -- playerchunkmap_entitytracker.updatePlayer(player); -- } -- } -+ // Paper - delay this logic for the entity tracker tick, no need to duplicate it - - int i = Mth.floor(player.getX()) >> 4; - int j = Mth.floor(player.getZ()) >> 4; -@@ -1616,7 +1680,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker - this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); -- playerchunkmap_entitytracker.updatePlayers(this.level.players()); -+ playerchunkmap_entitytracker.updatePlayers(entity.getPlayersInTrackRange()); // Paper - don't search all players - if (entity instanceof ServerPlayer) { - ServerPlayer entityplayer = (ServerPlayer) entity; - -@@ -1659,7 +1723,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - entity.tracker = null; // Paper - We're no longer tracked - } - -+ // Paper start - optimised tracker -+ private final void processTrackQueue() { -+ this.level.timings.tracker1.startTiming(); -+ try { -+ for (TrackedEntity tracker : this.entityMap.values()) { -+ // update tracker entry -+ tracker.updatePlayers(tracker.entity.getPlayersInTrackRange()); -+ } -+ } finally { -+ this.level.timings.tracker1.stopTiming(); -+ } -+ -+ -+ this.level.timings.tracker2.startTiming(); -+ try { -+ for (TrackedEntity tracker : this.entityMap.values()) { -+ tracker.serverEntity.tick(); -+ } -+ } finally { -+ this.level.timings.tracker2.stopTiming(); -+ } -+ } -+ // Paper end - optimised tracker -+ - protected void tick() { -+ // Paper start - optimized tracker -+ if (true) { -+ this.processTrackQueue(); -+ return; -+ } -+ // Paper end - optimized tracker - List list = Lists.newArrayList(); - List list1 = this.level.players(); - -@@ -1728,23 +1822,31 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos()); - List list = Lists.newArrayList(); - List list1 = Lists.newArrayList(); -- ObjectIterator objectiterator = this.entityMap.values().iterator(); -+ // Paper start - optimise entity tracker -+ // use the chunk entity list, not the whole trackedEntities map... -+ Entity[] entities = chunk.entities.getRawData(); -+ for (int i = 0, size = chunk.entities.size(); i < size; ++i) { -+ Entity entity = entities[i]; -+ if (entity == player) { -+ continue; -+ } -+ ChunkMap.TrackedEntity tracker = this.entityMap.get(entity.getId()); -+ if (tracker != null) { // dumb plugins... move on... -+ tracker.updatePlayer(player); -+ } - -- while (objectiterator.hasNext()) { -- ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); -- Entity entity = playerchunkmap_entitytracker.entity; -+ // keep the vanilla logic here - this is REQUIRED or else passengers and their vehicles disappear! -+ // (and god knows what the leash thing is) - -- if (entity != player && entity.xChunk == chunk.getPos().x && entity.zChunk == chunk.getPos().z) { -- playerchunkmap_entitytracker.updatePlayer(player); -- if (entity instanceof Mob && ((Mob) entity).getLeashHolder() != null) { -- list.add(entity); -- } -+ if (entity instanceof Mob && ((Mob)entity).getLeashHolder() != null) { -+ list.add(entity); -+ } - -- if (!entity.getPassengers().isEmpty()) { -- list1.add(entity); -- } -+ if (!entity.getPassengers().isEmpty()) { -+ list1.add(entity); - } - } -+ // Paper end - optimise entity tracker - - Iterator iterator; - Entity entity1; -@@ -1782,7 +1884,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - public class TrackedEntity { - -- private final ServerEntity serverEntity; -+ final ServerEntity serverEntity; // Paper - private -> package private - private final Entity entity; - private final int range; - private SectionPos lastSectionPos; -@@ -1799,6 +1901,42 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.lastSectionPos = SectionPos.of(entity); - } - -+ // Paper start - use distance map to optimise tracker -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet lastTrackerCandidates; -+ -+ final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet oldTrackerCandidates = this.lastTrackerCandidates; -+ this.lastTrackerCandidates = newTrackerCandidates; -+ -+ if (newTrackerCandidates != null) { -+ Object[] rawData = newTrackerCandidates.getBackingSet(); -+ for (int i = 0, len = rawData.length; i < len; ++i) { -+ Object raw = rawData[i]; -+ if (!(raw instanceof ServerPlayer)) { -+ continue; -+ } -+ ServerPlayer player = (ServerPlayer)raw; -+ this.updatePlayer(player); -+ } -+ } -+ -+ if (oldTrackerCandidates == newTrackerCandidates) { -+ // this is likely the case. -+ // means there has been no range changes, so we can just use the above for tracking. -+ return; -+ } -+ -+ // stuff could have been removed, so we need to check the trackedPlayers set -+ // for players that were removed -+ -+ for (ServerPlayer player : this.seenBy.toArray(new ServerPlayer[0])) { // avoid CME -+ if (newTrackerCandidates == null || !newTrackerCandidates.contains(player)) { -+ this.updatePlayer(player); -+ } -+ } -+ } -+ // Paper end - use distance map to optimise tracker -+ - public boolean equals(Object object) { - return object instanceof ChunkMap.TrackedEntity ? ((ChunkMap.TrackedEntity) object).entity.getId() == this.entity.getId() : false; - } -@@ -1899,7 +2037,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - int j = entity.getType().clientTrackingRange() * 16; - j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper - -- if (j > i) { -+ if (j < i) { // Paper - we need the lowest range thanks to the fact that our tracker doesn't account for passenger logic - i = j; - } - } -diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index 1609ab94c86e964421f996d4d46aef30f8b8e696..d797873db52ba265ac4478f9f3c6344badd4739e 100644 ---- a/src/main/java/net/minecraft/server/level/ServerEntity.java -+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -100,6 +100,7 @@ public class ServerEntity { - this.wasOnGround = entity.isOnGround(); - } - -+ public final void tick() { this.sendChanges(); } // Paper - OBFHELPER - public void sendChanges() { - List list = this.entity.getPassengers(); - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 2b48c4a2b512c42bed2c767db90a28898c74286a..d9bb00752ac81b2171d3ad25fd84904467a18e3b 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -46,6 +46,7 @@ import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; - import net.minecraft.resources.ResourceKey; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.ServerLevel; -@@ -294,6 +295,21 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - // CraftBukkit end - -+ // Paper start - optimise entity tracking -+ final org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = org.spigotmc.TrackingRange.getTrackingRangeType(this); -+ -+ public boolean isLegacyTrackingEntity = false; -+ -+ public final void setLegacyTrackingEntity(final boolean isLegacyTrackingEntity) { -+ this.isLegacyTrackingEntity = isLegacyTrackingEntity; -+ } -+ -+ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayersInTrackRange() { -+ return ((ServerLevel)this.level).getChunkSource().chunkMap.playerEntityTrackerTrackMaps[this.trackingRangeType.ordinal()] -+ .getObjectsInRange(MCUtil.getCoordinateKey(this)); -+ } -+ // Paper end - optimise entity tracking -+ - public Entity(EntityType type, Level world) { - this.id = Entity.ENTITY_COUNTER.incrementAndGet(); - this.passengers = Lists.newArrayList(); -diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java -index b03fa9024c7f0238e1379f6ae4486db5300a70e9..7b6011be849ecffdd791d439f70ae5dffc96f264 100644 ---- a/src/main/java/org/spigotmc/TrackingRange.java -+++ b/src/main/java/org/spigotmc/TrackingRange.java -@@ -20,6 +20,7 @@ public class TrackingRange - */ - public static int getEntityTrackingRange(Entity entity, int defaultRange) - { -+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return defaultRange; // Paper - enderdragon is exempt - SpigotWorldConfig config = entity.level.spigotConfig; - if ( entity instanceof ServerPlayer ) - { -@@ -43,8 +44,48 @@ public class TrackingRange - return config.miscTrackingRange; - } else - { -- if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt - return config.otherTrackingRange; - } - } -+ -+ // Paper start - optimise entity tracking -+ // copied from above, TODO check on update -+ public static TrackingRangeType getTrackingRangeType(Entity entity) -+ { -+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return TrackingRangeType.ENDERDRAGON; // Paper - enderdragon is exempt -+ if ( entity instanceof ServerPlayer ) -+ { -+ return TrackingRangeType.PLAYER; -+ // Paper start - Simplify and set water mobs to animal tracking range -+ } -+ switch (entity.activationType) { -+ case RAIDER: -+ case MONSTER: -+ case FLYING_MONSTER: -+ return TrackingRangeType.MONSTER; -+ case WATER: -+ case VILLAGER: -+ case ANIMAL: -+ return TrackingRangeType.ANIMAL; -+ case MISC: -+ } -+ if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) -+ // Paper end -+ { -+ return TrackingRangeType.MISC; -+ } else -+ { -+ return TrackingRangeType.OTHER; -+ } -+ } -+ -+ public static enum TrackingRangeType { -+ PLAYER, -+ ANIMAL, -+ MONSTER, -+ MISC, -+ OTHER, -+ ENDERDRAGON; -+ } -+ // Paper end - optimise entity tracking - } diff --git a/Remapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch b/Remapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch deleted file mode 100644 index adc6c14065..0000000000 --- a/Remapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch +++ /dev/null @@ -1,384 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 20:40:53 -0700 -Subject: [PATCH] Optimize isOutsideRange to use distance maps - -Use a distance map to find the players in range quickly - -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index d12d5459c847d3f0d655c85e31d81c27b7a2face..0147798c0285f64b8d767dfb2709d92f66ac72ef 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -69,6 +69,18 @@ public class ChunkHolder { - long lastAutoSaveTime; // Paper - incremental autosave - long inactiveTimeStart; // Paper - incremental autosave - -+ // Paper start - optimise isOutsideOfRange -+ // cached here to avoid a map lookup -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInMobSpawnRange; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInChunkTickRange; -+ -+ void updateRanges() { -+ long key = net.minecraft.server.MCUtil.getCoordinateKey(this.pos); -+ this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key); -+ this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); -+ } -+ // Paper end - optimise isOutsideOfRange -+ - public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { - this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); - this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; -@@ -85,6 +97,7 @@ public class ChunkHolder { - this.queueLevel = this.oldTicketLevel; - this.setTicketLevel(level); - this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper -+ this.updateRanges(); // Paper - optimise isOutsideOfRange - } - - // Paper start -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c756a5be9 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -208,6 +208,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); - } - // Paper end - use distance map to optimise tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ // A note about the naming used here: -+ // Previously, mojang used a "spawn range" of 8 for controlling both ticking and -+ // mob spawn range. However, spigot makes the spawn range configurable by -+ // checking if the chunk is in the tick range (8) and the spawn range -+ // obviously this means a spawn range > 8 cannot be implemented -+ -+ // these maps are named after spigot's uses -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - - void addPlayerToDistanceMaps(ServerPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.getX()); -@@ -221,6 +232,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); - } - // Paper end - use distance map to optimise entity tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - void removePlayerFromDistanceMaps(ServerPlayer player) { -@@ -229,6 +243,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.playerEntityTrackerTrackMaps[i].remove(player); - } - // Paper end - use distance map to optimise tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerMobSpawnMap.remove(player); -+ this.playerChunkTickRangeMap.remove(player); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - void updateMaps(ServerPlayer player) { -@@ -243,6 +261,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); - } - // Paper end - use distance map to optimise entity tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - // Paper end - -@@ -274,7 +295,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); - this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); - this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); -- this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); -+ this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper - this.overworldDataStorage = supplier; - this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper - this.setViewDistance(i); -@@ -318,6 +339,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); - } - // Paper end - use distance map to optimise entity tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerChunkTickRangeMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInChunkTickRange = newState; -+ } -+ }, -+ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInChunkTickRange = newState; -+ } -+ }); -+ this.playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInMobSpawnRange = newState; -+ } -+ }, -+ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInMobSpawnRange = newState; -+ } -+ }); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -337,6 +390,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return entityPlayer.mobCounts[enumCreatureType.ordinal()]; - } - -+ private static double getDistanceSquaredFromChunk(ChunkPos chunkPos, Entity entity) { return euclideanDistanceSquared(chunkPos, entity); } // Paper - OBFHELPER - private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { - double d0 = (double) (pos.x * 16 + 8); - double d1 = (double) (pos.z * 16 + 8); -@@ -515,6 +569,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } else { - if (holder != null) { - holder.setTicketLevel(level); -+ holder.updateRanges(); // Paper - optimise isOutsideOfRange - } - - if (holder != null) { -@@ -1493,30 +1548,53 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return isOutsideOfRange(chunkcoordintpair, false); - } - -- boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) { -- int chunkRange = level.spigotConfig.mobSpawnRange; -- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; -- chunkRange = (chunkRange > 8) ? 8 : chunkRange; -+ // Paper start - optimise isOutsideOfRange -+ final boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) { -+ return this.isOutsideOfRange(this.getUpdatingChunkIfPresent(chunkcoordintpair.toLong()), chunkcoordintpair, reducedRange); -+ } - -- final int finalChunkRange = chunkRange; // Paper for lambda below -- //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event -- // Spigot end -- long i = chunkcoordintpair.toLong(); -+ final boolean isOutsideOfRange(ChunkHolder playerchunk, ChunkPos chunkcoordintpair, boolean reducedRange) { -+ // this function is so hot that removing the map lookup call can have an order of magnitude impact on its performance -+ // tested and confirmed via System.nanoTime() -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInRange = reducedRange ? playerchunk.playersInMobSpawnRange : playerchunk.playersInChunkTickRange; - -- return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { -- // Paper start - -- com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; -- double blockRange = 16384.0D; -- if (reducedRange) { -- event = entityplayer.playerNaturallySpawnedEvent; -- if (event == null || event.isCancelled()) return false; -- blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); -- } -+ if (playersInRange == null) { -+ return true; -+ } - -- return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot -- // Paper end -- }); -+ Object[] backingSet = playersInRange.getBackingSet(); -+ -+ if (reducedRange) { -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object raw = backingSet[i]; -+ if (!(raw instanceof ServerPlayer)) { -+ continue; -+ } -+ ServerPlayer player = (ServerPlayer) raw; -+ // don't check spectator and whatnot, already handled by mob spawn map update -+ if (player.lastEntitySpawnRadiusSquared > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { -+ return false; // in range -+ } -+ } -+ } else { -+ final double range = (DistanceManager.MOB_SPAWN_RANGE * 16) * (DistanceManager.MOB_SPAWN_RANGE * 16); -+ // before spigot, mob spawn range was actually mob spawn range + tick range, but it was split -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object raw = backingSet[i]; -+ if (!(raw instanceof ServerPlayer)) { -+ continue; -+ } -+ ServerPlayer player = (ServerPlayer) raw; -+ // don't check spectator and whatnot, already handled by mob spawn map update -+ if (range > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { -+ return false; // in range -+ } -+ } -+ } -+ // no players in range -+ return true; - } -+ // Paper end - optimise isOutsideOfRange - - private boolean skipPlayer(ServerPlayer player) { - return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); -diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5980d3467 100644 ---- a/src/main/java/net/minecraft/server/level/DistanceManager.java -+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -37,7 +37,7 @@ public abstract class DistanceManager { - private final Long2ObjectMap> playersPerChunk = new Long2ObjectOpenHashMap(); - public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); - private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); -- private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); -+ public static final int MOB_SPAWN_RANGE = 8; // private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used - private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); - // Paper start use a queue, but still keep unique requirement - public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { -@@ -56,6 +56,8 @@ public abstract class DistanceManager { - private final Executor mainThreadExecutor; - private long ticketTickCounter; - -+ ChunkMap chunkMap; // Paper -+ - protected DistanceManager(Executor workerExecutor, Executor mainThreadExecutor) { - mainThreadExecutor.getClass(); - ProcessorHandle mailbox = ProcessorHandle.of("player ticket throttler", mainThreadExecutor::execute); -@@ -100,7 +102,7 @@ public abstract class DistanceManager { - protected abstract ChunkHolder updateChunkScheduling(long pos, int level, @Nullable ChunkHolder holder, int k); - - public boolean runAllUpdates(ChunkMap chunkStorage) { -- this.naturalSpawnChunkCounter.runAllUpdates(); -+ //this.f.a(); // Paper - no longer used - this.playerTicketManager.runAllUpdates(); - int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE); - boolean flag = i != 0; -@@ -236,7 +238,7 @@ public abstract class DistanceManager { - ((ObjectSet) this.playersPerChunk.computeIfAbsent(i, (j) -> { - return new ObjectOpenHashSet(); - })).add(player); -- this.naturalSpawnChunkCounter.update(i, 0, true); -+ //this.f.update(i, 0, true); // Paper - no longer used - this.playerTicketManager.update(i, 0, true); - } - -@@ -248,7 +250,7 @@ public abstract class DistanceManager { - if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully. - if (objectset == null || objectset.isEmpty()) { // Paper - this.playersPerChunk.remove(i); -- this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); -+ //this.f.update(i, Integer.MAX_VALUE, false); // Paper - no longer used - this.playerTicketManager.update(i, Integer.MAX_VALUE, false); - } - -@@ -272,13 +274,17 @@ public abstract class DistanceManager { - } - - public int getNaturalSpawnChunkCount() { -- this.naturalSpawnChunkCounter.runAllUpdates(); -- return this.naturalSpawnChunkCounter.chunks.size(); -+ // Paper start - use distance map to implement -+ // note: this is the spawn chunk count -+ return this.chunkMap.playerChunkTickRangeMap.size(); -+ // Paper end - use distance map to implement - } - - public boolean hasPlayersNearby(long i) { -- this.naturalSpawnChunkCounter.runAllUpdates(); -- return this.naturalSpawnChunkCounter.chunks.containsKey(i); -+ // Paper start - use distance map to implement -+ // note: this is the is spawn chunk method -+ return this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(i) != null; -+ // Paper end - use distance map to implement - } - - public String getDebugStatus() { -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 79fb63c40dd0543a6f629e78f390f23f34992ba1..52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -753,6 +753,37 @@ public class ServerChunkCache extends ChunkSource { - boolean flag1 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !level.players().isEmpty(); // CraftBukkit - - if (!flag) { -+ // Paper start - optimize isOutisdeRange -+ ChunkMap playerChunkMap = this.chunkMap; -+ for (ServerPlayer player : this.level.players) { -+ if (!player.affectsSpawning || player.isSpectator()) { -+ playerChunkMap.playerMobSpawnMap.remove(player); -+ continue; -+ } -+ -+ int viewDistance = this.chunkMap.getEffectiveViewDistance(); -+ -+ // copied and modified from isOutisdeRange -+ int chunkRange = level.spigotConfig.mobSpawnRange; -+ chunkRange = (chunkRange > viewDistance) ? (byte)viewDistance : chunkRange; -+ chunkRange = (chunkRange > DistanceManager.MOB_SPAWN_RANGE) ? DistanceManager.MOB_SPAWN_RANGE : chunkRange; -+ -+ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(player.getBukkitEntity(), (byte)chunkRange); -+ event.callEvent(); -+ if (event.isCancelled() || event.getSpawnRadius() < 0 || playerChunkMap.playerChunkTickRangeMap.getLastViewDistance(player) == -1) { -+ playerChunkMap.playerMobSpawnMap.remove(player); -+ continue; -+ } -+ -+ int range = Math.min(event.getSpawnRadius(), 32); // limit to max view distance -+ int chunkX = net.minecraft.server.MCUtil.getChunkCoordinate(player.getX()); -+ int chunkZ = net.minecraft.server.MCUtil.getChunkCoordinate(player.getZ()); -+ -+ playerChunkMap.playerMobSpawnMap.addOrUpdate(player, chunkX, chunkZ, range); -+ player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in isOutsideRange -+ player.playerNaturallySpawnedEvent = event; -+ } -+ // Paper end - optimize isOutisdeRange - this.level.getProfiler().push("pollingChunks"); - int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); - boolean flag2 = level.ticksPerAnimalSpawns != 0L && worlddata.getGameTime() % level.ticksPerAnimalSpawns == 0L; // CraftBukkit -@@ -782,15 +813,7 @@ public class ServerChunkCache extends ChunkSource { - this.level.getProfiler().pop(); - //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper - //Collections.shuffle(list); // Paper -- //Paper start - call player naturally spawn event -- int chunkRange = level.spigotConfig.mobSpawnRange; -- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; -- chunkRange = Math.min(chunkRange, 8); -- for (ServerPlayer entityPlayer : this.level.players()) { -- entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); -- entityPlayer.playerNaturallySpawnedEvent.callEvent(); -- }; -- // Paper end -+ // Paper - moved up - this.level.timings.chunkTicks.startTiming(); // Paper - final int[] chunksTicked = {0}; this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping - Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); -@@ -807,9 +830,9 @@ public class ServerChunkCache extends ChunkSource { - LevelChunk chunk = (LevelChunk) optional1.get(); - ChunkPos chunkcoordintpair = playerchunk.getPos(); - -- if (!this.chunkMap.noPlayersCloseForSpawning(chunkcoordintpair)) { -+ if (!this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange - chunk.setInhabitedTime(chunk.getInhabitedTime() + j); -- if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot -+ if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange - NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); - } - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 24c508ade61a6ad90b0ef73cdc995f531ef18263..95f1f4727a8e2000931e6f36b862e3ad28334a69 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -247,6 +247,8 @@ public class ServerPlayer extends Player implements ContainerListener { - - public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper - -+ double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks -+ - public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { - super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); - this.respawnDimension = Level.OVERWORLD; diff --git a/Remapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch b/Remapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch deleted file mode 100644 index e9e6a043fc..0000000000 --- a/Remapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch +++ /dev/null @@ -1,320 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Apr 2020 04:05:38 -0700 -Subject: [PATCH] Stop copy-on-write operations for updating light data - -Causes huge memory allocations + gc issues - -diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java -index 9f33fa8f84d10f8f4089030074ad6c0d81269ce8..a1ad4d73ddaf6afe97a1f1ff7e0622b52fac8761 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java -@@ -10,7 +10,7 @@ import net.minecraft.world.level.chunk.LightChunkGetter; - public class BlockLightSectionStorage extends LayerLightSectionStorage { - - protected BlockLightSectionStorage(LightChunkGetter chunkProvider) { -- super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new Long2ObjectOpenHashMap())); -+ super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data - } - - @Override -@@ -23,13 +23,13 @@ public class BlockLightSectionStorage extends LayerLightSectionStorage { - -- public BlockDataLayerStorageMap(Long2ObjectOpenHashMap arrays) { -- super(arrays); -+ public BlockDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data -+ super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data - } - - @Override - public BlockLightSectionStorage.BlockDataLayerStorageMap copy() { -- return new BlockLightSectionStorage.BlockDataLayerStorageMap(this.map.clone()); -+ return new BlockDataLayerStorageMap(this.data, true); // Paper - avoid copying light data - } - } - } -diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -index 01ae1c811862f56317a90e3811fe2ef4b593695f..4c9041f1c1cb4b3ec114fbd0c5d4db50a6f2526d 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -+++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -@@ -9,10 +9,23 @@ public abstract class DataLayerStorageMap> { - private final long[] lastSectionKeys = new long[2]; - private final DataLayer[] lastSections = new DataLayer[2]; - private boolean cacheEnabled; -- protected final Long2ObjectOpenHashMap map; -- -- protected DataLayerStorageMap(Long2ObjectOpenHashMap arrays) { -- this.map = arrays; -+ protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data -+ protected final boolean isVisible; // Paper - avoid copying light data -+ java.util.function.Function lookup; // Paper - faster branchless lookup -+ -+ // Paper start - avoid copying light data -+ protected DataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { -+ if (isVisible) { -+ data.performUpdatesLockMap(); -+ } -+ this.data = data; -+ this.isVisible = isVisible; -+ if (isVisible) { -+ lookup = data::getVisibleAsync; -+ } else { -+ lookup = data::getUpdating; -+ } -+ // Paper end - avoid copying light data - this.clearCache(); - this.cacheEnabled = true; - } -@@ -20,16 +33,17 @@ public abstract class DataLayerStorageMap> { - public abstract M copy(); - - public void copyDataLayer(long pos) { -- this.map.put(pos, ((DataLayer) this.map.get(pos)).copy()); -+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data -+ this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data - this.clearCache(); - } - - public boolean hasLayer(long chunkPos) { -- return this.map.containsKey(chunkPos); -+ return lookup.apply(chunkPos) != null; // Paper - avoid copying light data - } - - @Nullable -- public DataLayer getLayer(long chunkPos) { -+ public final DataLayer getLayer(long chunkPos) { // Paper - final - if (this.cacheEnabled) { - for (int j = 0; j < 2; ++j) { - if (chunkPos == this.lastSectionKeys[j]) { -@@ -38,7 +52,7 @@ public abstract class DataLayerStorageMap> { - } - } - -- DataLayer nibblearray = (DataLayer) this.map.get(chunkPos); -+ DataLayer nibblearray = lookup.apply(chunkPos); // Paper - avoid copying light data - - if (nibblearray == null) { - return null; -@@ -59,11 +73,13 @@ public abstract class DataLayerStorageMap> { - - @Nullable - public DataLayer removeLayer(long chunkPos) { -- return (DataLayer) this.map.remove(chunkPos); -+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data -+ return (DataLayer) this.data.queueRemove(chunkPos); // Paper - avoid copying light data - } - - public void setLayer(long pos, DataLayer data) { -- this.map.put(pos, data); -+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data -+ this.data.queueUpdate(pos, data); // Paper - avoid copying light data - } - - public void clearCache() { -@@ -71,7 +87,6 @@ public abstract class DataLayerStorageMap> { - this.lastSectionKeys[i] = Long.MAX_VALUE; - this.lastSections[i] = null; - } -- - } - - public void disableCache() { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -index 45be10a0d7c26e4b6e5738ba994ce343265210f5..177dae992d13674bb285a60b8427df9ea843dc99 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -@@ -26,8 +26,8 @@ public abstract class LayerLightSectionStorage> - protected final LongSet dataSectionSet = new LongOpenHashSet(); - protected final LongSet toMarkNoData = new LongOpenHashSet(); - protected final LongSet toMarkData = new LongOpenHashSet(); -- protected volatile M visibleSectionData; -- protected final M updatingSectionData; -+ protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change -+ protected final M updatingSectionData; // Paper - diff on change, should be "updating" - protected final LongSet changedSections = new LongOpenHashSet(); - protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet(); - protected final Long2ObjectMap queuedSections = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); -@@ -41,8 +41,8 @@ public abstract class LayerLightSectionStorage> - this.layer = lightType; - this.chunkSource = chunkProvider; - this.updatingSectionData = lightData; -- this.visibleSectionData = lightData.copy(); -- this.visibleSectionData.disableCache(); -+ this.e_visible = lightData.copy(); // Paper - avoid copying light data -+ this.e_visible.disableCache(); // Paper - avoid copying light data - } - - protected boolean storingLightForSection(long sectionPos) { -@@ -51,7 +51,15 @@ public abstract class LayerLightSectionStorage> - - @Nullable - protected DataLayer getDataLayer(long sectionPos, boolean cached) { -- return this.getDataLayer(cached ? this.updatingSectionData : this.visibleSectionData, sectionPos); -+ // Paper start - avoid copying light data -+ if (cached) { -+ return this.getDataLayer(this.updatingSectionData, sectionPos); -+ } else { -+ synchronized (this.visibleUpdateLock) { -+ return this.getDataLayer(this.e_visible, sectionPos); -+ } -+ } -+ // Paper end - avoid copying light data - } - - @Nullable -@@ -364,10 +372,12 @@ public abstract class LayerLightSectionStorage> - - protected void swapSectionMap() { - if (!this.changedSections.isEmpty()) { -+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data - M m0 = this.updatingSectionData.copy(); - - m0.disableCache(); -- this.visibleSectionData = m0; -+ this.e_visible = m0; // Paper - avoid copying light data -+ } // Paper - avoid copying light data - this.changedSections.clear(); - } - -diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -index c304637ae8f80c65b58e8ba8a27609b532bb1184..410fcfa8c01b7e3d3e3829ebdb92a11badff16ea 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -@@ -23,15 +23,16 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data - } - - @Override - protected int getLightValue(long blockPos) { - long j = SectionPos.blockToSection(blockPos); - int k = SectionPos.y(j); -- SkyLightSectionStorage.SkyDataLayerStorageMap lightenginestoragesky_a = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.visibleSectionData; -- int l = lightenginestoragesky_a.topSections.get(SectionPos.getZeroNode(j)); -+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data -+ SkyLightSectionStorage.SkyDataLayerStorageMap lightenginestoragesky_a = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.e_visible; // Paper - avoid copying light data - must be after lock acquire -+ int l = lightenginestoragesky_a.otherData.getVisibleAsync(SectionPos.getZeroNode(j)); // Paper - avoid copying light data - - if (l != lightenginestoragesky_a.currentLowestY && k < l) { - DataLayer nibblearray = this.getDataLayer(lightenginestoragesky_a, j); // Paper - decompile fix -@@ -52,6 +53,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage j) { - ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY = j; -- ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.defaultReturnValue(((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY); -+ ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.queueDefaultReturnValue(((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY); // Paper - avoid copying light data - } - - long k = SectionPos.getZeroNode(sectionPos); -- int l = ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.get(k); -+ int l = ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.getUpdating(k); // Paper - avoid copying light data - - if (l < j + 1) { -- ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.put(k, j + 1); -+ ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.queueUpdate(k, j + 1); // Paper - avoid copying light data - if (this.columnsWithSkySources.contains(k)) { - this.queueAddSource(sectionPos); - if (l > ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY) { -@@ -107,7 +109,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage= k; - } -@@ -327,18 +329,21 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage { - - private int currentLowestY; -- private final Long2IntOpenHashMap topSections; -- -- public SkyDataLayerStorageMap(Long2ObjectOpenHashMap arrays, Long2IntOpenHashMap columnToTopSection, int minSectionY) { -- super(arrays); -- this.topSections = columnToTopSection; -- columnToTopSection.defaultReturnValue(minSectionY); -- this.currentLowestY = minSectionY; -+ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data -+ -+ // Paper start - avoid copying light data -+ public SkyDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData, int i, boolean isVisible) { -+ super(data, isVisible); -+ this.otherData = otherData; -+ otherData.queueDefaultReturnValue(i); -+ // Paper end - avoid copying light data -+ this.currentLowestY = i; - } - - @Override - public SkyLightSectionStorage.SkyDataLayerStorageMap copy() { -- return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.map.clone(), this.topSections.clone(), this.currentLowestY); -+ this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data -+ return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.data, this.otherData, this.currentLowestY, true); // Paper - avoid copying light data - } - } - } diff --git a/Remapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch b/Remapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch deleted file mode 100644 index 9fee42c2d0..0000000000 --- a/Remapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch +++ /dev/null @@ -1,819 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 21:23:34 -0700 -Subject: [PATCH] No-Tick view distance implementation - -Implements world view distance getters/setters - -Per-Player is absent due to difficulty of maintaining -the diff required to make it happen. - -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index 5bcf9cefc29eb20e2cfbfb49e2b2662ec394a87e..a696474b4bd0e32a26dadfbc1257580ee596f0c0 100644 ---- a/src/main/java/co/aikar/timings/TimingsExport.java -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -156,7 +156,8 @@ public class TimingsExport extends Thread { - pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { - return pair(rule, world.getWorld().getGameRuleValue(rule)); - })), -- pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) -+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()), -+ pair("notick-viewdistance", world.getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance()) - )); - })); - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 46ac6d91422423f1e03b86d3efa3241f2599000d..6463d3e4837d032a35654a035f42b8a805e0e286 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -632,4 +632,9 @@ public class PaperWorldConfig { - phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); - phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); - } -+ -+ public int noTickViewDistance; -+ private void viewDistance() { -+ this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 9abef8550a89df5e15ac28de1a5549d064f29122..d18497a33dc53f6b465e659967bf8c98731c46c0 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -638,7 +638,8 @@ public final class MCUtil { - }); - - worldData.addProperty("name", world.getWorld().getName()); -- worldData.addProperty("view-distance", world.spigotConfig.viewDistance); -+ worldData.addProperty("view-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance()); -+ worldData.addProperty("no-view-distance", world.getChunkSource().chunkMap.getRawNoTickViewDistance()); - worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); - worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); - worldData.addProperty("visible-chunk-count", visibleChunks.size()); -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 0147798c0285f64b8d767dfb2709d92f66ac72ef..9ebcfca10071cc42d4f1df02c25de5042c065f38 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -81,6 +81,18 @@ public class ChunkHolder { - } - // Paper end - optimise isOutsideOfRange - -+ // Paper start - no-tick view distance -+ public final LevelChunk getSendingChunk() { -+ // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used -+ // in Chunk's neighbour callback -+ LevelChunk ret = this.chunkMap.level.getChunkSource().getChunkAtIfLoadedImmediately(this.pos.x, this.pos.z); -+ if (ret != null && ret.areNeighboursLoaded(1)) { -+ return ret; -+ } -+ return null; -+ } -+ // Paper end - no-tick view distance -+ - public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { - this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); - this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; -@@ -240,7 +252,7 @@ public class ChunkHolder { - } - - public void blockChanged(BlockPos blockposition) { -- LevelChunk chunk = this.getTickingChunk(); -+ LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { - byte b0 = (byte) SectionPos.blockToSectionCoord(blockposition.getY()); -@@ -256,7 +268,7 @@ public class ChunkHolder { - } - - public void sectionLightChanged(LightLayer type, int y) { -- LevelChunk chunk = this.getTickingChunk(); -+ LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { - chunk.setUnsaved(true); -@@ -338,9 +350,48 @@ public class ChunkHolder { - } - - private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { -- this.playerProvider.getPlayers(this.pos, onlyOnWatchDistanceEdge).forEach((entityplayer) -> { -- entityplayer.connection.send(packet); -- }); -+ // Paper start - per player view distance -+ // there can be potential desync with player's last mapped section and the view distance map, so use the -+ // view distance map here. -+ com.destroystokyo.paper.util.misc.PlayerAreaMap viewDistanceMap = this.chunkMap.playerViewDistanceBroadcastMap; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = viewDistanceMap.getObjectsInRange(this.pos); -+ if (players == null) { -+ return; -+ } -+ -+ if (onlyOnWatchDistanceEdge) { // flag -> border only -+ Object[] backingSet = players.getBackingSet(); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof ServerPlayer)) { -+ continue; -+ } -+ ServerPlayer player = (ServerPlayer)temp; -+ -+ int viewDistance = viewDistanceMap.getLastViewDistance(player); -+ long lastPosition = viewDistanceMap.getLastCoordinate(player); -+ -+ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - this.pos.x); -+ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - this.pos.z); -+ -+ if (Math.max(distX, distZ) == viewDistance) { -+ player.connection.send(packet); -+ } -+ } -+ } else { -+ Object[] backingSet = players.getBackingSet(); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof ServerPlayer)) { -+ continue; -+ } -+ ServerPlayer player = (ServerPlayer)temp; -+ player.connection.send(packet); -+ } -+ } -+ -+ return; -+ // Paper end - per player view distance - } - - public CompletableFuture> getOrScheduleFuture(ChunkStatus targetStatus, ChunkMap chunkStorage) { -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d3956c5f2efb 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -57,12 +57,14 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; - import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; - import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; -+import net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket; - import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; - import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; - import net.minecraft.network.protocol.game.DebugPackets; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.progress.ChunkProgressListener; -+import net.minecraft.server.network.ServerGamePacketListenerImpl; - import net.minecraft.util.CsvOutput; - import net.minecraft.util.Mth; - import net.minecraft.util.profiling.ProfilerFiller; -@@ -144,7 +146,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private boolean modified; - private final ChunkTaskPriorityQueueSorter queueSorter; - private final ProcessorHandle> worldgenMailbox; -- private final ProcessorHandle> mainThreadMailbox; -+ public final ProcessorHandle> mainThreadMailbox; // Paper - private -> public -+ // Paper start -+ final ProcessorHandle> mailboxLight; -+ public void addLightTask(ChunkHolder playerchunk, Runnable run) { -+ this.mailboxLight.tell(ChunkTaskPriorityQueueSorter.message(playerchunk, run)); -+ } -+ // Paper end - public final ChunkProgressListener progressListener; - public final ChunkMap.ChunkDistanceManager distanceManager; public final DistanceManager getChunkDistanceManager() { return this.distanceManager; } // Paper - OBFHELPER - private final AtomicInteger tickingGenerated; -@@ -219,6 +227,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick - public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ int noTickViewDistance; -+ public final int getRawNoTickViewDistance() { -+ return this.noTickViewDistance; -+ } -+ public final int getEffectiveNoTickViewDistance() { -+ return this.noTickViewDistance == -1 ? this.getEffectiveViewDistance() : this.noTickViewDistance; -+ } -+ public final int getLoadViewDistance() { -+ return Math.max(this.getEffectiveViewDistance(), this.getEffectiveNoTickViewDistance()); -+ } -+ -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceBroadcastMap; -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap; -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap; -+ // Paper end - no-tick view distance - - void addPlayerToDistanceMaps(ServerPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.getX()); -@@ -235,6 +259,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper start - optimise PlayerChunkMap#isOutsideRange - this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ int effectiveTickViewDistance = this.getEffectiveViewDistance(); -+ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); -+ -+ if (!this.cannotLoadChunks(player)) { -+ this.playerViewDistanceTickMap.add(player, chunkX, chunkZ, effectiveTickViewDistance); -+ this.playerViewDistanceNoTickMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) -+ } -+ -+ player.needsChunkCenterUpdate = true; -+ this.playerViewDistanceBroadcastMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured -+ player.needsChunkCenterUpdate = false; -+ // Paper end - no-tick view distance - } - - void removePlayerFromDistanceMaps(ServerPlayer player) { -@@ -247,6 +284,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.playerMobSpawnMap.remove(player); - this.playerChunkTickRangeMap.remove(player); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ this.playerViewDistanceBroadcastMap.remove(player); -+ this.playerViewDistanceTickMap.remove(player); -+ this.playerViewDistanceNoTickMap.remove(player); -+ // Paper end - no-tick view distance - } - - void updateMaps(ServerPlayer player) { -@@ -264,6 +306,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper start - optimise PlayerChunkMap#isOutsideRange - this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ int effectiveTickViewDistance = this.getEffectiveViewDistance(); -+ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); -+ -+ if (!this.cannotLoadChunks(player)) { -+ this.playerViewDistanceTickMap.update(player, chunkX, chunkZ, effectiveTickViewDistance); -+ this.playerViewDistanceNoTickMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) -+ } -+ -+ player.needsChunkCenterUpdate = true; -+ this.playerViewDistanceBroadcastMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured -+ player.needsChunkCenterUpdate = false; -+ // Paper end - no-tick view distance - } - // Paper end - -@@ -371,6 +426,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - }); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); -+ this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (newState.size() != 1) { -+ return; -+ } -+ LevelChunk chunk = ChunkMap.this.level.getChunkSource().getChunkAtIfLoadedMainThreadNoCache(rangeX, rangeZ); -+ if (chunk == null || !chunk.areNeighboursLoaded(2)) { -+ return; -+ } -+ -+ ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); -+ ChunkMap.this.level.getChunkSource().addTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update -+ }, -+ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (newState != null) { -+ return; -+ } -+ ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); -+ ChunkMap.this.level.getChunkSource().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update -+ }); -+ this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); -+ this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (player.needsChunkCenterUpdate) { -+ player.needsChunkCenterUpdate = false; -+ player.connection.send(new ClientboundSetChunkCacheCenterPacket(currPosX, currPosZ)); -+ } -+ ChunkMap.this.updateChunkTracking(player, new ChunkPos(rangeX, rangeZ), new Packet[2], false, true); // unloaded, loaded -+ }, -+ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ ChunkMap.this.updateChunkTracking(player, new ChunkPos(rangeX, rangeZ), null, true, false); // unloaded, loaded -+ }); -+ // Paper end - no-tick view distance - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -1199,15 +1293,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - completablefuture1.thenAcceptAsync((either) -> { - either.mapLeft((chunk) -> { - this.tickingGenerated.getAndIncrement(); -- Packet[] apacket = new Packet[2]; -- -- this.getPlayers(chunkcoordintpair, false).forEach((entityplayer) -> { -- this.playerLoadedChunk(entityplayer, apacket, chunk); -- }); -+ // Paper - no-tick view distance - moved to Chunk neighbour update - return Either.left(chunk); - }); - }, (runnable) -> { -- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); -+ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); // Paper - diff on change, this is the scheduling method copied in Chunk used to schedule chunk broadcasts (on change it needs to be copied again) - }); - return completablefuture1; - } -@@ -1302,32 +1392,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - } - -- protected void setViewDistance(int watchDistance) { -- int j = Mth.clamp(watchDistance + 1, 3, 33); -+ public void setViewDistance(int watchDistance) { // Paper - public -+ int j = Mth.clamp(watchDistance + 1, 3, 33); // Paper - diff on change, these make the lower view distance limit 2 and the upper 32 - - if (j != this.viewDistance) { - int k = this.viewDistance; - - this.viewDistance = j; -- this.distanceManager.updatePlayerTickets(this.viewDistance); -- ObjectIterator objectiterator = this.updatingChunkMap.values().iterator(); -+ this.setNoTickViewDistance(this.getRawNoTickViewDistance()); //Paper - no-tick view distance - propagate changes to no-tick, which does the actual chunk loading/sending -+ } - -- while (objectiterator.hasNext()) { -- ChunkHolder playerchunk = (ChunkHolder) objectiterator.next(); -- ChunkPos chunkcoordintpair = playerchunk.getPos(); -- Packet[] apacket = new Packet[2]; -+ } - -- this.getPlayers(chunkcoordintpair, false).forEach((entityplayer) -> { -- int l = checkerboardDistance(chunkcoordintpair, entityplayer, true); -- boolean flag = l <= k; -- boolean flag1 = l <= this.viewDistance; -+ // Paper start - no-tick view distance -+ public final void setNoTickViewDistance(int viewDistance) { -+ viewDistance = viewDistance == -1 ? -1 : Mth.clamp(viewDistance, 2, 32); - -- this.updateChunkTracking(entityplayer, chunkcoordintpair, apacket, flag, flag1); -- }); -+ this.noTickViewDistance = viewDistance; -+ int loadViewDistance = this.getLoadViewDistance(); -+ this.distanceManager.setNoTickViewDistance(loadViewDistance + 2 + 2); // add 2 to account for the change to 31 -> 33 tickets // see notes in the distance map updating for the other + 2 -+ -+ if (this.level != null && this.level.players != null) { // this can be called from constructor, where these aren't set -+ for (ServerPlayer player : this.level.players) { -+ ServerGamePacketListenerImpl connection = player.connection; -+ if (connection != null) { -+ // moved in from PlayerList -+ connection.send(new ClientboundSetChunkCacheRadiusPacket(loadViewDistance)); -+ } -+ this.updateMaps(player); - } - } -- - } -+ // Paper end - no-tick view distance - - protected void updateChunkTracking(ServerPlayer player, ChunkPos pos, Packet[] packets, boolean withinMaxWatchDistance, boolean withinViewDistance) { - if (player.level == this.level) { -@@ -1335,7 +1431,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.toLong()); - - if (playerchunk != null) { -- LevelChunk chunk = playerchunk.getTickingChunk(); -+ LevelChunk chunk = playerchunk.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { - this.playerLoadedChunk(player, packets, chunk); -@@ -1596,6 +1692,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - // Paper end - optimise isOutsideOfRange - -+ private boolean cannotLoadChunks(ServerPlayer entityplayer) { return this.skipPlayer(entityplayer); } // Paper - OBFHELPER - private boolean skipPlayer(ServerPlayer player) { - return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); - } -@@ -1623,13 +1720,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.removePlayerFromDistanceMaps(player); // Paper - distance maps - } - -- for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { -- for (int l = j - this.viewDistance; l <= j + this.viewDistance; ++l) { -- ChunkPos chunkcoordintpair = new ChunkPos(k, l); -- -- this.updateChunkTracking(player, chunkcoordintpair, new Packet[2], !added, added); -- } -- } -+ // Paper - broadcast view distance map handles this (see remove/add calls above) - - } - -@@ -1637,7 +1728,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - SectionPos sectionposition = SectionPos.of((Entity) entityplayer); - - entityplayer.setLastSectionPos(sectionposition); -- entityplayer.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); -+ // Paper - distance map handles this now - return sectionposition; - } - -@@ -1682,6 +1773,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - int k1; - int l1; - -+ /* // Paper start - replaced by distance map - if (Math.abs(i1 - i) <= this.viewDistance * 2 && Math.abs(j1 - j) <= this.viewDistance * 2) { - k1 = Math.min(i, i1) - this.viewDistance; - l1 = Math.min(j, j1) - this.viewDistance; -@@ -1690,36 +1782,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - for (int k2 = k1; k2 <= i2; ++k2) { - for (int l2 = l1; l2 <= j2; ++l2) { -- ChunkPos chunkcoordintpair = new ChunkPos(k2, l2); -- boolean flag3 = checkerboardDistance(chunkcoordintpair, i1, j1) <= this.viewDistance; -- boolean flag4 = checkerboardDistance(chunkcoordintpair, i, j) <= this.viewDistance; -+ ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k2, l2); -+ boolean flag3 = a(chunkcoordintpair, i1, j1) <= this.viewDistance; -+ boolean flag4 = a(chunkcoordintpair, i, j) <= this.viewDistance; - -- this.updateChunkTracking(player, chunkcoordintpair, new Packet[2], flag3, flag4); -+ this.sendChunk(entityplayer, chunkcoordintpair, new Packet[2], flag3, flag4); - } - } - } else { -- ChunkPos chunkcoordintpair1; -+ ChunkCoordIntPair chunkcoordintpair1; - boolean flag5; - boolean flag6; - - for (k1 = i1 - this.viewDistance; k1 <= i1 + this.viewDistance; ++k1) { - for (l1 = j1 - this.viewDistance; l1 <= j1 + this.viewDistance; ++l1) { -- chunkcoordintpair1 = new ChunkPos(k1, l1); -+ chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1); - flag5 = true; - flag6 = false; -- this.updateChunkTracking(player, chunkcoordintpair1, new Packet[2], true, false); -+ this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], true, false); - } - } - - for (k1 = i - this.viewDistance; k1 <= i + this.viewDistance; ++k1) { - for (l1 = j - this.viewDistance; l1 <= j + this.viewDistance; ++l1) { -- chunkcoordintpair1 = new ChunkPos(k1, l1); -+ chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1); - flag5 = false; - flag6 = true; -- this.updateChunkTracking(player, chunkcoordintpair1, new Packet[2], false, true); -+ this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], false, true); - } - } -- } -+ }*/ // Paper end - replaced by distance map - - this.updateMaps(player); // Paper - distance maps - -@@ -1727,11 +1819,46 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - @Override - public Stream getPlayers(ChunkPos chunkPos, boolean onlyOnWatchDistanceEdge) { -- return this.playerMap.a(chunkPos.toLong()).filter((entityplayer) -> { -- int i = b(chunkcoordintpair, entityplayer, true); -+ // Paper start - per player view distance -+ // there can be potential desync with player's last mapped section and the view distance map, so use the -+ // view distance map here. -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = this.playerViewDistanceBroadcastMap.getObjectsInRange(chunkPos); - -- return i > this.viewDistance ? false : !flag || i == this.viewDistance; -- }); -+ if (inRange == null) { -+ return Stream.empty(); -+ } -+ // all current cases are inlined so we wont hit this code, it's just in case plugins or future updates use it -+ List players = new java.util.ArrayList<>(); -+ Object[] backingSet = inRange.getBackingSet(); -+ -+ if (onlyOnWatchDistanceEdge) { // flag -> border only -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof ServerPlayer)) { -+ continue; -+ } -+ ServerPlayer player = (ServerPlayer)temp; -+ int viewDistance = this.playerViewDistanceBroadcastMap.getLastViewDistance(player); -+ long lastPosition = this.playerViewDistanceBroadcastMap.getLastCoordinate(player); -+ -+ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - chunkPos.x); -+ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - chunkPos.z); -+ if (Math.max(distX, distZ) == viewDistance) { -+ players.add(player); -+ } -+ } -+ } else { -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof ServerPlayer)) { -+ continue; -+ } -+ ServerPlayer player = (ServerPlayer)temp; -+ players.add(player); -+ } -+ } -+ return players.stream(); -+ // Paper end - per player view distance - } - - public void addEntity(Entity entity) { // Paper - protected -> public -@@ -1889,7 +2016,48 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - } - -- private final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER -+ // Paper start -+ private static int getLightMask(final LevelChunk chunk) { -+ final ChunkSection[] chunkSections = chunk.getSections(); -+ int mask = 0; -+ -+ for (int i = 0; i < chunkSections.length; ++i) { -+ /* -+ -+ -+Lightmasks have 18 bits, from the -1 (void) section until the 17th (air) section. -+Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. -+ -+ */ -+ mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; -+ } -+ -+ return mask; -+ } -+ -+ private static int getCeilingLightMask(final LevelChunk chunk) { -+ int mask = getLightMask(chunk); -+ -+ /* -+ It is similar to get highest bit, it would turn an 001010 into an 001111 so basically the highest bit and all below. -+ We then invert this, so we'd have 110000 and compare that to the "main" chunk. -+ This is because the bug only appears when the current chunks lightmaps are higher than those of the neighbors, thus we can omit sending neighbors which are lower than the current chunks lights. -+ -+ so TLDR is that getCeilingLightMask returns a light mask with all bits set below the highest affected section. We could also count the number of leading zeros and invert them, somehow. -+ @TODO: Implement Leafs suggestion -+ either use Integer#numberOfLeadingZeros or document what this bithack is supposed to be doing then -+ */ -+ mask |= mask >> 1; -+ mask |= mask >> 2; -+ mask |= mask >> 4; -+ mask |= mask >> 8; -+ mask |= mask >> 16; -+ -+ return mask; -+ } -+ // Paper end -+ -+ public final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { - if (packets[0] == null) { - packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass -@@ -2075,7 +2243,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - ChunkPos chunkcoordintpair = new ChunkPos(this.entity.xChunk, this.entity.zChunk); - ChunkHolder playerchunk = ChunkMap.this.getVisibleChunkIfPresent(chunkcoordintpair.toLong()); - -- if (playerchunk != null && playerchunk.getTickingChunk() != null) { -+ if (playerchunk != null && playerchunk.getSendingChunk() != null) { // Paper - no-tick view distance - flag1 = ChunkMap.checkerboardDistance(chunkcoordintpair, player, false) <= ChunkMap.this.viewDistance; - } - } -diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index 91c672531087430c47365657a3219ab5980d3467..c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e 100644 ---- a/src/main/java/net/minecraft/server/level/DistanceManager.java -+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -269,8 +269,8 @@ public abstract class DistanceManager { - return s; - } - -- protected void updatePlayerTickets(int viewDistance) { -- this.playerTicketManager.updateViewDistance(viewDistance); -+ protected void setNoTickViewDistance(int i) { // Paper - force abi breakage on usage change -+ this.playerTicketManager.updateViewDistance(i); - } - - public int getNaturalSpawnChunkCount() { -@@ -388,7 +388,7 @@ public abstract class DistanceManager { - - private void onLevelChange(long pos, int distance, boolean oldWithinViewDistance, boolean withinViewDistance) { - if (oldWithinViewDistance != withinViewDistance) { -- Ticket ticket = new Ticket<>(TicketType.PLAYER, DistanceManager.PLAYER_TICKET_LEVEL, new ChunkPos(pos)); -+ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkPos(pos)); // Paper - no-tick view distance - - if (withinViewDistance) { - DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 95f1f4727a8e2000931e6f36b862e3ad28334a69..8e4cef60b760be385df81a74834d026f856a78c5 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -249,6 +249,8 @@ public class ServerPlayer extends Player implements ContainerListener { - - double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks - -+ boolean needsChunkCenterUpdate; // Paper - no-tick view distance -+ - public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { - super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); - this.respawnDimension = Level.OVERWORLD; -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index ffc8c9ee8b1768dd809189858ee45658fb9bf1c5..8e00747c1a717836d12a43aa48d667bf801167b0 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -250,7 +250,7 @@ public abstract class PlayerList { - boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); - - // Spigot - view distance -- playerconnection.send(new ClientboundLoginPacket(player.getId(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), worlddata.isHardcore(), this.server.levelKeys(), this.registryHolder, worldserver1.dimensionType(), worldserver1.dimension(), this.getMaxPlayers(), worldserver1.spigotConfig.viewDistance, flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat())); -+ playerconnection.send(new ClientboundLoginPacket(player.getId(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), worlddata.isHardcore(), this.server.levelKeys(), this.registryHolder, worldserver1.dimensionType(), worldserver1.dimension(), this.getMaxPlayers(), worldserver1.getChunkSource().chunkMap.getLoadViewDistance(), flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat())); // Paper - no-tick view distance - player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit - playerconnection.send(new ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.BRAND, (new FriendlyByteBuf(Unpooled.buffer())).writeUtf(this.getServer().getServerModName()))); - playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); -@@ -904,7 +904,7 @@ public abstract class PlayerList { - // CraftBukkit start - LevelData worlddata = worldserver1.getLevelData(); - entityplayer1.connection.send(new ClientboundRespawnPacket(worldserver1.dimensionType(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), entityplayer1.gameMode.getGameModeForPlayer(), entityplayer1.gameMode.getPreviousGameModeForPlayer(), worldserver1.isDebug(), worldserver1.isFlat(), flag)); -- entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.spigotConfig.viewDistance)); // Spigot -+ entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.getChunkSource().chunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance - entityplayer1.setLevel(worldserver1); - entityplayer1.removed = false; - entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.yRot, entityplayer1.xRot)); -@@ -1372,7 +1372,7 @@ public abstract class PlayerList { - - public void setViewDistance(int viewDistance) { - this.viewDistance = viewDistance; -- this.broadcastAll(new ClientboundSetChunkCacheRadiusPacket(viewDistance)); -+ //this.sendAll(new PacketPlayOutViewDistance(i)); // Paper - move into setViewDistance - Iterator iterator = this.server.getAllLevels().iterator(); - - while (iterator.hasNext()) { -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 5860e7866724abd35bde2a5710d9c92799e5de67..67ab681a9c9157a420de5fd872bde1fc0de24561 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -525,8 +525,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); - } - -- if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement -+ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement // Paper - diff on change, see below - this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i); -+ // Paper start - per player view distance - allow block updates for non-ticking chunks in player view distance -+ // if copied from above -+ } else if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || ((ServerLevel)this).getChunkSource().chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.getCoordinateKey(blockposition)) != null)) { -+ ((ServerLevel)this).getChunkSource().blockChanged(blockposition); -+ // Paper end - per player view distance - } - - if ((i & 1) != 0) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 8a14bdda4a408ec1e2b51efeb35467835f62b42c..dbea2a4370ccf24a5084cdabeecbc81f206e910a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -27,9 +27,14 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Registry; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.network.protocol.Packet; - import net.minecraft.server.level.ChunkHolder; -+import net.minecraft.server.level.ChunkMap; -+import net.minecraft.server.level.ChunkTaskPriorityQueueSorter; - import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.TicketType; - import net.minecraft.util.Mth; - import net.minecraft.world.Container; - import net.minecraft.world.entity.Entity; -@@ -242,7 +247,51 @@ public class LevelChunk implements ChunkAccess { - } - - protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { -+ // Paper start - no-tick view distance -+ ServerChunkCache chunkProviderServer = ((ServerLevel)this.world).getChunkSource(); -+ ChunkMap chunkMap = chunkProviderServer.chunkMap; -+ // this code handles the addition of ticking tickets - the distance map handles the removal -+ if (!areNeighboursLoaded(bitsetBefore, 2) && areNeighboursLoaded(bitsetAfter, 2)) { -+ if (chunkMap.playerViewDistanceTickMap.getObjectsInRange(this.coordinateKey) != null) { -+ // now we're ready for entity ticking -+ chunkProviderServer.mainThreadProcessor.execute(() -> { -+ // double check that this condition still holds. -+ if (LevelChunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(LevelChunk.this.coordinateKey) != null) { -+ chunkProviderServer.addTicketAtLevel(TicketType.PLAYER, LevelChunk.this.chunkPos, 31, LevelChunk.this.chunkPos); // 31 -> entity ticking, TODO check on update -+ } -+ }); -+ } -+ } - -+ // this code handles the chunk sending -+ if (!areNeighboursLoaded(bitsetBefore, 1) && areNeighboursLoaded(bitsetAfter, 1)) { -+ if (chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(this.coordinateKey) != null) { -+ // now we're ready to send -+ chunkMap.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(chunkMap.getUpdatingChunkIfPresent(this.coordinateKey), (() -> { // Copied frm PlayerChunkMap -+ // double check that this condition still holds. -+ if (!LevelChunk.this.areNeighboursLoaded(1)) { -+ return; -+ } -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(LevelChunk.this.coordinateKey); -+ if (inRange == null) { -+ return; -+ } -+ -+ // broadcast -+ Object[] backingSet = inRange.getBackingSet(); -+ Packet[] chunkPackets = new Packet[2]; -+ for (int index = 0, len = backingSet.length; index < len; ++index) { -+ Object temp = backingSet[index]; -+ if (!(temp instanceof ServerPlayer)) { -+ continue; -+ } -+ ServerPlayer player = (ServerPlayer)temp; -+ chunkMap.sendChunk(player, chunkPackets, LevelChunk.this); -+ } -+ }))); -+ } -+ } -+ // Paper end - no-tick view distance - } - - public final boolean isAnyNeighborsLoaded() { -@@ -1131,7 +1180,7 @@ public class LevelChunk implements ChunkAccess { - BlockState iblockdata = this.getBlockState(blockposition); - BlockState iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, (LevelAccessor) this.world, blockposition); - -- this.world.setBlock(blockposition, iblockdata1, 20); -+ this.world.setBlock(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here - } - - this.postProcessing[i].clear(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 1a839242e359fa32f32d0e571c6e918ac39642e9..4fc44390f432ef13c9952aa22bbb29bc8bf47975 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -31,6 +31,7 @@ import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; - import net.minecraft.network.protocol.game.ClientboundSetTimePacket; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.level.ChunkHolder; -+import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.DistanceManager; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.Ticket; -@@ -2532,10 +2533,39 @@ public class CraftWorld implements World { - // Spigot start - @Override - public int getViewDistance() { -- return world.spigotConfig.viewDistance; -+ return getHandle().getChunkSource().chunkMap.getEffectiveViewDistance(); // Paper - no-tick view distance - } - // Spigot end - -+ // Paper start - per player view distance -+ @Override -+ public void setViewDistance(int viewDistance) { -+ if (viewDistance < 2 || viewDistance > 32) { -+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); -+ } -+ ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; -+ if (viewDistance != chunkMap.getEffectiveViewDistance()) { -+ chunkMap.setViewDistance(viewDistance); -+ } -+ } -+ -+ @Override -+ public int getNoTickViewDistance() { -+ return getHandle().getChunkSource().chunkMap.getEffectiveNoTickViewDistance(); -+ } -+ -+ @Override -+ public void setNoTickViewDistance(int viewDistance) { -+ if ((viewDistance < 2 || viewDistance > 32) && viewDistance != -1) { -+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); -+ } -+ ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; -+ if (viewDistance != chunkMap.getRawNoTickViewDistance()) { -+ chunkMap.setNoTickViewDistance(viewDistance); -+ } -+ } -+ // Paper end - per player view distance -+ - // Spigot start - private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot() - { -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 8cbafad53d20366a36493f22160c4fa3e4ac3eaf..20d5da61fc0594e86c68ea8fb5ebe5517f27f126 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -4,6 +4,7 @@ import java.util.Collection; - import net.minecraft.core.BlockPos; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerChunkCache; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.FlyingMob; -@@ -192,7 +193,7 @@ public class ActivationRange - maxRange = Math.max( maxRange, waterActivationRange ); - maxRange = Math.max( maxRange, villagerActivationRange ); - // Paper end -- maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); -+ maxRange = Math.min( ( ((ServerLevel)world).getChunkSource().chunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance - - for ( Player player : world.players() ) - { diff --git a/Remapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch b/Remapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch deleted file mode 100644 index 771a37b8cf..0000000000 --- a/Remapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 22 Apr 2020 23:29:20 +0200 -Subject: [PATCH] Add villager reputation API - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c6072615e95bf51c83b2f728fc3288a7043a89af ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java -@@ -0,0 +1,11 @@ -+package com.destroystokyo.paper.entity.villager; -+// Must have own package due to package-level constructor. -+ -+import Reputation; -+ -+public final class ReputationConstructor { -+ // Abuse the package-level constructor. -+ public static Reputation construct(int[] values) { -+ return new Reputation(values); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -index c4ece3ac4863067b12c10772debd1b1454bec5b4..0204f05d989d45c0848f810d1953adf0992ce3c2 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -@@ -27,7 +27,7 @@ import net.minecraft.core.SerializableUUID; - - public class GossipContainer { - -- private final Map gossips = Maps.newHashMap(); -+ private final Map gossips = Maps.newHashMap(); public Map getReputations() { return this.gossips; } // Paper - add getter for reputations - - public GossipContainer() {} - -@@ -142,11 +142,11 @@ public class GossipContainer { - return k > type.max ? Math.max(type.max, left) : k; - } - -- static class EntityGossips { -+ public static class EntityGossips { // Paper - make public - - private final Object2IntMap entries; - -- private EntityGossips() { -+ public EntityGossips() { // Paper - make public - update CraftVillager setReputation on change - this.entries = new Object2IntOpenHashMap(); - } - -@@ -200,6 +200,28 @@ public class GossipContainer { - public void remove(GossipType gossipType) { - this.entries.removeInt(gossipType); - } -+ -+ // Paper start - Add villager reputation API -+ private static final com.destroystokyo.paper.entity.villager.ReputationType[] REPUTATION_TYPES = com.destroystokyo.paper.entity.villager.ReputationType.values(); -+ public com.destroystokyo.paper.entity.villager.Reputation getPaperReputation() { -+ int[] reputation = new int[REPUTATION_TYPES.length]; -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE.ordinal()] = entries.getOrDefault(GossipType.MAJOR_NEGATIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE.ordinal()] = entries.getOrDefault(GossipType.MAJOR_POSITIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE.ordinal()] = entries.getOrDefault(GossipType.MINOR_NEGATIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE.ordinal()] = entries.getOrDefault(GossipType.MINOR_POSITIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.TRADING.ordinal()] = entries.getOrDefault(GossipType.TRADING, 0); -+ return com.destroystokyo.paper.entity.villager.ReputationConstructor.construct(reputation); -+ } -+ -+ public void assignFromPaperReputation(com.destroystokyo.paper.entity.villager.Reputation rep) { -+ int val; -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE)) != 0) this.entries.put(GossipType.MAJOR_NEGATIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE)) != 0) this.entries.put(GossipType.MAJOR_POSITIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE)) != 0) this.entries.put(GossipType.MINOR_NEGATIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE)) != 0) this.entries.put(GossipType.MINOR_POSITIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.TRADING)) != 0) this.entries.put(GossipType.TRADING, val); -+ } -+ // Paper end - } - - static class GossipEntry { -diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index a83a7d37f3d769535161fda46fca6f71dcc4d515..e9912551e6a19d6ad3b20fad1b716577b9d28f99 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/Villager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -1037,6 +1037,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - this.numberOfRestocksToday = 0; - } - -+ public GossipContainer getReputation() { return this.getGossips(); } // Paper - OBFHELPER - public GossipContainer getGossips() { - return this.gossips; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index d0b933cfd02b237bfe85011831dab6e8e966496e..e3d4214ef6360b4a9949a73ba3d665ad08733b43 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -@@ -16,6 +16,13 @@ import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; - import org.bukkit.entity.Villager.Type; - -+// Paper start -+import com.destroystokyo.paper.entity.villager.Reputation; -+import com.google.common.collect.Maps; -+import java.util.Map; -+import java.util.UUID; -+// Paper end -+ - public class CraftVillager extends CraftAbstractVillager implements Villager { - - public CraftVillager(CraftServer server, net.minecraft.world.entity.npc.Villager entity) { -@@ -125,4 +132,45 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { - public static VillagerProfession bukkitToNmsProfession(Profession bukkit) { - return Registry.VILLAGER_PROFESSION.get(CraftNamespacedKey.toMinecraft(bukkit.getKey())); - } -+ -+ // Paper start - Add villager reputation API -+ @Override -+ public Reputation getReputation(UUID uniqueId) { -+ net.minecraft.world.entity.ai.gossip.GossipContainer.EntityGossips rep = getHandle().getReputation().getReputations().get(uniqueId); -+ if (rep == null) { -+ return new Reputation(Maps.newHashMap()); -+ } -+ -+ return rep.getPaperReputation(); -+ } -+ -+ @Override -+ public Map getReputations() { -+ return getHandle().getReputation().getReputations().entrySet() -+ .stream() -+ .collect(java.util.stream.Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getPaperReputation())); -+ } -+ -+ @Override -+ public void setReputation(UUID uniqueId, Reputation reputation) { -+ net.minecraft.world.entity.ai.gossip.GossipContainer.EntityGossips nmsReputation = -+ getHandle().getReputation().getReputations().computeIfAbsent( -+ uniqueId, -+ key -> new net.minecraft.world.entity.ai.gossip.GossipContainer.EntityGossips() -+ ); -+ nmsReputation.assignFromPaperReputation(reputation); -+ } -+ -+ @Override -+ public void setReputations(Map reputations) { -+ for (Map.Entry entry : reputations.entrySet()) { -+ setReputation(entry.getKey(), entry.getValue()); -+ } -+ } -+ -+ @Override -+ public void clearReputations() { -+ getHandle().getReputation().getReputations().clear(); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch b/Remapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch deleted file mode 100644 index 382b91a80f..0000000000 --- a/Remapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch +++ /dev/null @@ -1,182 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 7 May 2020 19:17:36 -0400 -Subject: [PATCH] Fix Light Command - -This lets you run /paper fixlight (max 5) to automatically -fix all light data in the chunks. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index ff718bc7f521575e6a670e17fcf59a2d30841705..528c860fc0c04431e0ebb2ae6bc96bf9c2d04789 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -11,16 +11,20 @@ import com.google.common.collect.Maps; - import com.google.gson.JsonObject; - import com.google.gson.internal.Streams; - import com.google.gson.stream.JsonWriter; -+import net.minecraft.core.BlockPos; -+import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkHolder; - import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.ThreadedLevelLightEngine; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; - import net.minecraft.world.level.ChunkPos; --import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.chunk.LevelChunk; - import org.apache.commons.lang3.tuple.MutablePair; - import org.apache.commons.lang3.tuple.Pair; - import org.bukkit.Bukkit; -@@ -31,6 +35,7 @@ import org.bukkit.command.Command; - import org.bukkit.command.CommandSender; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.entity.Player; - - import java.io.File; -@@ -39,10 +44,12 @@ import java.io.PrintStream; - import java.io.StringWriter; - import java.time.LocalDateTime; - import java.time.format.DateTimeFormatter; -+import java.util.ArrayDeque; - import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; - import java.util.Collections; -+import java.util.Deque; - import java.util.Iterator; - import java.util.List; - import java.util.Locale; -@@ -52,7 +59,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); - - public PaperCommand(String name) { - super(name); -@@ -173,6 +180,9 @@ public class PaperCommand extends Command { - case "syncloadinfo": - this.doSyncLoadInfo(sender, args); - break; -+ case "fixlight": -+ this.doFixLight(sender, args); -+ break; - case "ver": - if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) - case "version": -@@ -190,6 +200,77 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doFixLight(CommandSender sender, String[] args) { -+ if (!(sender instanceof Player)) { -+ sender.sendMessage("Only players can use this command"); -+ return; -+ } -+ int radius = 2; -+ if (args.length > 1) { -+ try { -+ radius = Math.min(5, Integer.parseInt(args[1])); -+ } catch (Exception e) { -+ sender.sendMessage("Not a number"); -+ return; -+ } -+ -+ } -+ -+ CraftPlayer player = (CraftPlayer) sender; -+ ServerPlayer handle = player.getHandle(); -+ ServerLevel world = (ServerLevel) handle.level; -+ ThreadedLevelLightEngine lightengine = world.getChunkSource().getLightEngine(); -+ -+ BlockPos center = MCUtil.toBlockPosition(player.getLocation()); -+ Deque queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius)); -+ updateLight(sender, world, lightengine, queue); -+ } -+ -+ private void updateLight(CommandSender sender, ServerLevel world, ThreadedLevelLightEngine lightengine, Deque queue) { -+ ChunkPos coord = queue.poll(); -+ if (coord == null) { -+ sender.sendMessage("All Chunks Light updated"); -+ return; -+ } -+ world.getChunkSource().getChunkAtAsynchronously(coord.x, coord.z, false, false).whenCompleteAsync((either, ex) -> { -+ if (ex != null) { -+ sender.sendMessage("Error loading chunk " + coord); -+ updateLight(sender, world, lightengine, queue); -+ return; -+ } -+ LevelChunk chunk = (LevelChunk) either.left().orElse(null); -+ if (chunk == null) { -+ updateLight(sender, world, lightengine, queue); -+ return; -+ } -+ lightengine.setTaskPerBatch(world.paperConfig.lightQueueSize + 16 * 256); // ensure full chunk can fit into queue -+ sender.sendMessage("Updating Light " + coord); -+ int cx = chunk.getPos().x << 4; -+ int cz = chunk.getPos().z << 4; -+ for (int y = 0; y < world.getHeight(); y++) { -+ for (int x = 0; x < 16; x++) { -+ for (int z = 0; z < 16; z++) { -+ BlockPos pos = new BlockPos(cx + x, y, cz + z); -+ lightengine.checkBlock(pos); -+ } -+ } -+ } -+ lightengine.tryScheduleUpdate(); -+ ChunkHolder visibleChunk = world.getChunkSource().chunkMap.getVisibleChunkIfPresent(chunk.coordinateKey); -+ if (visibleChunk != null) { -+ world.getChunkSource().chunkMap.addLightTask(visibleChunk, () -> { -+ MinecraftServer.getServer().processQueue.add(() -> { -+ visibleChunk.sendPacketToTrackedPlayers(new ClientboundLightUpdatePacket(chunk.getPos(), lightengine, true), false); -+ updateLight(sender, world, lightengine, queue); -+ }); -+ }); -+ } else { -+ updateLight(sender, world, lightengine, queue); -+ } -+ lightengine.setTaskPerBatch(world.paperConfig.lightQueueSize); -+ }, MinecraftServer.getServer()); -+ } -+ - private void doSyncLoadInfo(CommandSender sender, String[] args) { - if (!SyncLoadFinder.ENABLED) { - sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 9ebcfca10071cc42d4f1df02c25de5042c065f38..d907872d80f840b343419f49a6708082da6f921b 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -349,6 +349,7 @@ public class ChunkHolder { - - } - -+ public void sendPacketToTrackedPlayers(Packet packet, boolean flag) { broadcast(packet, flag); } // Paper - OBFHELPER - private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { - // Paper start - per player view distance - // there can be potential desync with player's last mapped section and the view distance map, so use the -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 6b51a082cf42bc3ffc550614e385d3956c5f2efb..67f748d5955453ba4873b0c9bb741b5bfe52d655 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -344,11 +344,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - ProcessorHandle mailbox = ProcessorHandle.of("main", mainThreadExecutor::tell); - - this.progressListener = worldGenerationProgressListener; -- ProcessorMailbox threadedmailbox1 = ProcessorMailbox.create(workerExecutor, "light"); -+ ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(workerExecutor, "light"); // Paper - - this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), workerExecutor, Integer.MAX_VALUE); - this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); - this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); -+ this.mailboxLight = this.queueSorter.getProcessor(lightthreaded, false);// Paper - this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); - this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper - this.overworldDataStorage = supplier; diff --git a/Remapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch b/Remapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch deleted file mode 100644 index 5968f9b0c8..0000000000 --- a/Remapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Fri, 8 May 2020 00:49:18 -0400 -Subject: [PATCH] Fix PotionEffect ignores icon flag - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 5dac3bf5a117bfbf57798238f0614558deafcd1b..067eaf1e05ced344eb168431403f3fe786eafddf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -408,7 +408,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - - @Override - public boolean addPotionEffect(PotionEffect effect, boolean force) { -- getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN); -+ getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon - return true; - } - diff --git a/Remapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch b/Remapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch deleted file mode 100644 index d213e040be..0000000000 --- a/Remapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: virustotalop -Date: Thu, 16 Apr 2020 20:51:32 -0700 -Subject: [PATCH] Optimize brigadier child sorting performance - - -diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -index 120234605433165d1c78986b5f0f130e64c5a20a..5c35cef42af4053332c02b4960c227fe95d4c197 100644 ---- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java -+++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -@@ -26,7 +26,7 @@ import java.util.stream.Collectors; - import net.minecraft.commands.CommandSourceStack; - - public abstract class CommandNode implements Comparable> { -- private Map> children = Maps.newLinkedHashMap(); -+ private Map> children = Maps.newTreeMap(); //Paper - Switch to tree map for automatic sorting - private Map> literals = Maps.newLinkedHashMap(); - private Map> arguments = Maps.newLinkedHashMap(); - private final Predicate requirement; -@@ -106,8 +106,7 @@ public abstract class CommandNode implements Comparable> { - arguments.put(node.getName(), (ArgumentCommandNode) node); - } - } -- -- children = children.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); -+ //Paper - Remove manual sorting, it is no longer needed - } - - public void findAmbiguities(final AmbiguityConsumer consumer) { diff --git a/Remapped-Spigot-Server-Patches/0473-Potential-bed-API.patch b/Remapped-Spigot-Server-Patches/0473-Potential-bed-API.patch deleted file mode 100644 index efd1703506..0000000000 --- a/Remapped-Spigot-Server-Patches/0473-Potential-bed-API.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Sun, 10 May 2020 23:06:30 -0400 -Subject: [PATCH] Potential bed API - -Adds a new method to fetch the location of a player's bed without generating any sync loads. - -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/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index ae6faa331fcbefd99ee1cd92c88926d767fc50ee..878a62e04962aafeaf192075fbe08e319298a800 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -12,6 +12,7 @@ import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; - import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.MenuProvider; - import net.minecraft.world.entity.Entity; -@@ -126,6 +127,22 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - return getHandle().sleepCounter; - } - -+ // Paper start - Potential bed api -+ @Override -+ public Location getPotentialBedLocation() { -+ ServerPlayer handle = (ServerPlayer) getHandle(); -+ BlockPos bed = handle.getRespawnPosition(); -+ if (bed == null) { -+ return null; -+ } -+ -+ ServerLevel worldServer = handle.server.getLevel(handle.getRespawnDimension()); -+ if (worldServer == null) { -+ return null; -+ } -+ return new Location(worldServer.getWorld(), bed.getX(), bed.getY(), bed.getZ()); -+ } -+ // Paper end - @Override - public boolean sleep(Location location, boolean force) { - Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/Remapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch b/Remapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch deleted file mode 100644 index dea3aa2ef9..0000000000 --- a/Remapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 May 2020 22:16:17 -0400 -Subject: [PATCH] Wait for Async Tasks during shutdown - -Server.reload() had this logic to give time for tasks to shutdown, -however shutdown did not... - -Adds a 5 second grace period for any async tasks to finish and warns -if any are still running after that delay just as reload does. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 74f393ffa2ae2d0e25b3f0b674cef7a987e985d3..f530c739b6aee3718eb5d0e0e6a09d882d817c68 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -892,6 +892,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { -+ try { -+ Thread.sleep(100); -+ } catch (InterruptedException e) {} -+ pollCount++; -+ } -+ -+ List overdueWorkers = getScheduler().getActiveWorkers(); -+ for (BukkitWorker worker : overdueWorkers) { -+ Plugin plugin = worker.getOwner(); -+ String author = ""; -+ if (plugin.getDescription().getAuthors().size() > 0) { -+ author = plugin.getDescription().getAuthors().get(0); -+ } -+ getLogger().log(Level.SEVERE, String.format( -+ "Nag author: '%s' of '%s' about the following: %s", -+ author, -+ plugin.getDescription().getName(), -+ "This plugin is not properly shutting down its async tasks when it is being shut down. This task may throw errors during the final shutdown logs and might not complete before process dies." -+ )); -+ } -+ } -+ // Paper end -+ - @Override - public void reloadData() { - ReloadCommand.reload(console); diff --git a/Remapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/Remapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch deleted file mode 100644 index 99d8f1263a..0000000000 --- a/Remapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Sat, 9 May 2020 02:01:48 -0400 -Subject: [PATCH] Ensure EntityRaider respects game and entity rules for - picking up items - - -diff --git a/src/main/java/net/minecraft/world/entity/raid/Raider.java b/src/main/java/net/minecraft/world/entity/raid/Raider.java -index 6406b0a03b67ea61083b704cd24b9b25a0f33c87..5502615be430d9eba0c1c68e3f10826d75b08672 100644 ---- a/src/main/java/net/minecraft/world/entity/raid/Raider.java -+++ b/src/main/java/net/minecraft/world/entity/raid/Raider.java -@@ -523,7 +523,7 @@ public abstract class Raider extends PatrollingMonster { - - public class ObtainRaidLeaderBannerGoal extends Goal { - -- private final T mob; -+ private final T mob; private T getRaider() { return mob; } // Paper - obfhelper - - public ObtainRaidLeaderBannerGoal(T entityraider) { // CraftBukkit - decompile error - this.mob = entityraider; -@@ -532,6 +532,7 @@ public abstract class Raider extends PatrollingMonster { - - @Override - public boolean canUse() { -+ if (!getRaider().level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || !getRaider().canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items - Raid raid = this.mob.getCurrentRaid(); - - if (this.mob.hasActiveRaid() && !this.mob.getCurrentRaid().isOver() && this.mob.canBeLeader() && !ItemStack.matches(this.mob.getItemBySlot(EquipmentSlot.HEAD), Raid.getLeaderBannerInstance())) { diff --git a/Remapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/Remapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch deleted file mode 100644 index 99a5355669..0000000000 --- a/Remapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 May 2020 23:01:26 -0400 -Subject: [PATCH] Protect Bedrock and End Portal/Frames from being destroyed - -This fixes exploits that let players destroy bedrock by Pistons, explosions -and Mushrooom/Tree generation. - -These blocks are designed to not be broken except by creative players/commands. -So protect them from a multitude of methods of destroying them. - -A config is provided if you rather let players use these exploits, and let -them destroy the worlds End Portals and get on top of the nether easy. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 78271b400c79578d043b20a5389a37b1bef9a70d..5f3b0d95cc7e6a0434d78ea7305a70689c41c71c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -416,4 +416,17 @@ public class PaperConfig { - private static void midTickChunkTasks() { - midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); - } -+ -+ public static boolean allowBlockPermanentBreakingExploits = false; -+ private static void allowBlockPermanentBreakingExploits() { -+ if (config.contains("allow-perm-block-break-exploits")) { -+ allowBlockPermanentBreakingExploits = config.getBoolean("allow-perm-block-break-exploits", false); -+ config.set("allow-perm-block-break-exploits", null); -+ } -+ -+ config.set("settings.unsupported-settings.allow-permanent-block-break-exploits-readme", "This setting controls if players should be able to break bedrock, end portals and other intended to be permanent blocks."); -+ allowBlockPermanentBreakingExploits = getBoolean("settings.unsupported-settings.allow-permanent-block-break-exploits", allowBlockPermanentBreakingExploits); -+ -+ } -+ - } -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 667a6d645034c67639c01b8221591877bcb87b35..0f0a5fa2be5a7c69291b593a04cad83e069ba5b1 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -151,6 +151,7 @@ public class Explosion { - for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { - BlockPos blockposition = new BlockPos(d4, d5, d6); - BlockState iblockdata = this.level.getBlockState(blockposition); -+ if (!iblockdata.isDestroyable()) continue; // Paper - FluidState fluid = iblockdata.getFluidState(); // Paper - Optional optional = this.damageCalculator.a(this, this.level, blockposition, iblockdata, fluid); - -@@ -304,7 +305,7 @@ public class Explosion { - BlockState iblockdata = this.level.getBlockState(blockposition); - Block block = iblockdata.getBlock(); - -- if (!iblockdata.isAir()) { -+ if (!iblockdata.isAir() && iblockdata.isDestroyable()) { // Paper - BlockPos blockposition1 = blockposition.immutable(); - - this.level.getProfiler().push("explosion_blocks"); -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 67ab681a9c9157a420de5fd872bde1fc0de24561..9b50b8030174338c04b60d441b980131e1d593e4 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -422,6 +422,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { - // CraftBukkit start - tree generation - if (this.captureTreeGeneration) { -+ // Paper start -+ BlockState type = getBlockState(pos); -+ if (!type.isDestroyable()) return false; -+ // Paper end - CraftBlockState blockstate = capturedBlockStates.get(pos); - if (blockstate == null) { - blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index fca5d175cbef24fb0ee2d0bbedc8d1c0af3eb528..5b84ee4091e354c4b6500f58a31931f2a6827ffc 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -62,6 +62,19 @@ public class Block extends BlockBehaviour implements ItemLike { - protected final StateDefinition stateDefinition; - private BlockState defaultBlockState; - // Paper start -+ public final boolean isDestroyable() { -+ return com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || -+ this != Blocks.BEDROCK && -+ this != Blocks.END_PORTAL_FRAME && -+ this != Blocks.END_PORTAL && -+ this != Blocks.END_GATEWAY && -+ this != Blocks.COMMAND_BLOCK && -+ this != Blocks.REPEATING_COMMAND_BLOCK && -+ this != Blocks.CHAIN_COMMAND_BLOCK && -+ this != Blocks.BARRIER && -+ this != Blocks.STRUCTURE_BLOCK && -+ this != Blocks.JIGSAW; -+ } - public co.aikar.timings.Timing timing; - public co.aikar.timings.Timing getTiming() { - if (timing == null) { -diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -index dc9584a30c18d964afd9cc118c81c24a80beba63..40a18302dd682e5ade4ec77ac7f316b6c0f8c112 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -@@ -193,6 +193,12 @@ public class PistonBaseBlock extends DirectionalBlock { - @Override - public boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) { - Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING); -+ // Paper start - prevent retracting when we're facing the wrong way (we were replaced before retraction could occur) -+ Direction directionQueuedAs = Direction.from3DDataValue(data & 7); // Paper - copied from below -+ if (!com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits && enumdirection != directionQueuedAs) { -+ return false; -+ } -+ // Paper end - prevent retracting when we're facing the wrong way - - if (!world.isClientSide) { - boolean flag = this.getNeighborSignal(world, pos, enumdirection); -@@ -224,7 +230,7 @@ public class PistonBaseBlock extends DirectionalBlock { - BlockState iblockdata1 = (BlockState) ((BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, enumdirection)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); - - world.setBlock(pos, iblockdata1, 20); -- world.setBlockEntity(pos, MovingPistonBlock.newMovingBlockEntity((BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); -+ world.setBlockEntity(pos, MovingPistonBlock.newMovingBlockEntity((BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - diff on change, j is facing direction - copy this above - world.blockUpdated(pos, iblockdata1.getBlock()); - iblockdata1.updateNeighbourShapes(world, pos, 2); - if (this.isSticky) { -@@ -253,7 +259,14 @@ public class PistonBaseBlock extends DirectionalBlock { - } - } - } else { -- world.removeBlock(pos.relative(enumdirection), false); -+ // Paper start - fix headless pistons breaking blocks -+ BlockPos headPos = pos.relative(enumdirection); -+ if (com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || world.getBlockState(headPos) == Blocks.PISTON_HEAD.defaultBlockState().setValue(FACING, enumdirection)) { // double check to make sure we're not a headless piston. -+ world.setAir(headPos, false); -+ } else { -+ ((ServerLevel)world).getChunkSource().blockChanged(headPos); // ... fix client desync -+ } -+ // Paper end - fix headless pistons breaking blocks - } - - world.playSound((Player) null, pos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F); -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index 57eedaeedaa24bd274fb55c6e4521f1305382645..df2836b071158729728411f5b228cc38dddd4d4e 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -189,7 +189,7 @@ public abstract class BlockBehaviour { - - @Deprecated - public boolean canBeReplaced(BlockState state, BlockPlaceContext context) { -- return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || context.getItemInHand().getItem() != this.asItem()); -+ return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || context.getItemInHand().getItem() != this.asItem()) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().abilities.instabuild)); // Paper - } - - @Deprecated -@@ -393,7 +393,11 @@ public abstract class BlockBehaviour { - public Block getBlock() { - return (Block) this.owner; - } -- -+ // Paper start -+ public final boolean isDestroyable() { -+ return getBlock().isDestroyable(); -+ } -+ // Paper end - public Material getMaterial() { - return this.material; - } -@@ -483,7 +487,7 @@ public abstract class BlockBehaviour { - } - - public PushReaction getPistonPushReaction() { -- return this.getBlock().getPistonPushReaction(this.asState()); -+ return !isDestroyable() ? PushReaction.BLOCK : this.getBlock().getPistonPushReaction(this.asState()); // Paper - } - - public boolean isSolidRender(BlockGetter world, BlockPos pos) { diff --git a/Remapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch b/Remapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch deleted file mode 100644 index 9cdcec0403..0000000000 --- a/Remapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch +++ /dev/null @@ -1,394 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 23:30:30 -0400 -Subject: [PATCH] Optimize NibbleArray to use pooled buffers - -Massively reduces memory allocation of 2048 byte buffers by using -an object pool for these. - -Uses lots of advanced new capabilities of the Paper codebase :) - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java -index bc1b4cc2e0a4181bde5ac05ce0a20a651cb0c4c3..902f14e2e5ac5aa11b545a68ac69e9b0282df7f4 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java -@@ -1,12 +1,16 @@ - package net.minecraft.network.protocol.game; - - import com.google.common.collect.Lists; -+import io.netty.channel.ChannelFuture; // Paper -+ - import java.io.IOException; - import java.util.Iterator; - import java.util.List; - import net.minecraft.core.SectionPos; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.LightLayer; - import net.minecraft.world.level.chunk.DataLayer; -@@ -24,14 +28,43 @@ public class ClientboundLightUpdatePacket implements Packet blockUpdates; - private boolean trustEdges; - -+ // Paper start -+ java.lang.Runnable cleaner1; -+ java.lang.Runnable cleaner2; -+ java.util.concurrent.atomic.AtomicInteger remainingSends = new java.util.concurrent.atomic.AtomicInteger(0); -+ -+ @Override -+ public void onPacketDispatch(ServerPlayer player) { -+ remainingSends.incrementAndGet(); -+ } -+ -+ @Override -+ public void onPacketDispatchFinish(ServerPlayer player, ChannelFuture future) { -+ if (remainingSends.decrementAndGet() <= 0) { -+ // incase of any race conditions, schedule this delayed -+ MCUtil.scheduleTask(5, () -> { -+ if (remainingSends.get() == 0) { -+ cleaner1.run(); -+ cleaner2.run(); -+ } -+ }, "Light Packet Release"); -+ } -+ } -+ -+ @Override -+ public boolean hasFinishListener() { -+ return true; -+ } -+ -+ // Paper end - public ClientboundLightUpdatePacket() {} - - public ClientboundLightUpdatePacket(ChunkPos chunkcoordintpair, LevelLightEngine lightengine, boolean flag) { - this.x = chunkcoordintpair.x; - this.z = chunkcoordintpair.z; - this.trustEdges = flag; -- this.skyUpdates = Lists.newArrayList(); -- this.blockUpdates = Lists.newArrayList(); -+ this.skyUpdates = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.skyUpdates, DataLayer::releaseBytes); // Paper -+ this.blockUpdates = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.blockUpdates, DataLayer::releaseBytes); // Paper - - for (int i = 0; i < 18; ++i) { - DataLayer nibblearray = lightengine.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, -1 + i)); -@@ -42,7 +75,7 @@ public class ClientboundLightUpdatePacket implements Packet BYTE_2048 = new PooledObjects<>(() -> new byte[2048], maxPoolSize); -+ public static void releaseBytes(byte[] bytes) { -+ if (bytes != null && bytes != EMPTY_NIBBLE && bytes.length == 2048) { -+ System.arraycopy(EMPTY_NIBBLE, 0, bytes, 0, 2048); -+ BYTE_2048.release(bytes); -+ } -+ } -+ -+ public DataLayer markPoolSafe(byte[] bytes) { -+ if (bytes != EMPTY_NIBBLE) this.data = bytes; -+ return markPoolSafe(); -+ } -+ public DataLayer markPoolSafe() { -+ poolSafe = true; -+ return this; -+ } -+ public byte[] getIfSet() { -+ return this.data != null ? this.data : EMPTY_NIBBLE; -+ } -+ public byte[] getCloneIfSet() { -+ if (data == null) { -+ return EMPTY_NIBBLE; -+ } -+ byte[] ret = BYTE_2048.acquire(); -+ System.arraycopy(getIfSet(), 0, ret, 0, 2048); -+ return ret; -+ } -+ -+ public DataLayer cloneAndSet(byte[] bytes) { -+ if (bytes != null && bytes != EMPTY_NIBBLE) { -+ this.data = BYTE_2048.acquire(); -+ System.arraycopy(bytes, 0, this.data, 0, 2048); -+ } -+ return this; -+ } -+ boolean poolSafe = false; -+ public java.lang.Runnable cleaner; -+ private void registerCleaner() { -+ if (!poolSafe) { -+ cleaner = MCUtil.registerCleaner(this, this.data, DataLayer::releaseBytes); -+ } else { -+ cleaner = MCUtil.once(() -> DataLayer.releaseBytes(this.data)); -+ } -+ } -+ // Paper end -+ @Nullable protected byte[] data; -+ - - public DataLayer() {} - - public DataLayer(byte[] abyte) { -+ // Paper start -+ this(abyte, false); -+ } -+ public DataLayer(byte[] abyte, boolean isSafe) { - this.data = abyte; -+ if (!isSafe) this.data = getCloneIfSet(); // Paper - clone for safety -+ registerCleaner(); -+ // Paper end - if (abyte.length != 2048) { - throw (IllegalArgumentException) Util.pauseInIde((Throwable) (new IllegalArgumentException("ChunkNibbleArrays should be 2048 bytes not: " + abyte.length))); - } -@@ -46,7 +106,8 @@ public class DataLayer { - - public void set(int index, int value) { // PAIL: private -> public - if (this.data == null) { -- this.data = new byte[2048]; -+ this.data = BYTE_2048.acquire(); // Paper -+ registerCleaner();// Paper - } - - int k = this.getPosition(index); -@@ -68,14 +129,36 @@ public class DataLayer { - public byte[] getData() { - if (this.data == null) { - this.data = new byte[2048]; -+ } else { // Paper start -+ // Accessor may need this object past garbage collection so need to clone it and return pooled value -+ // If we know its safe for pre GC access, use asBytesPoolSafe(). If you just need read, use getIfSet() -+ Runnable cleaner = this.cleaner; -+ if (cleaner != null) { -+ this.data = this.data.clone(); -+ cleaner.run(); // release the previously pooled value -+ this.cleaner = null; -+ } -+ } -+ // Paper end -+ -+ return this.data; -+ } -+ -+ @Nonnull -+ public byte[] asBytesPoolSafe() { -+ if (this.data == null) { -+ this.data = BYTE_2048.acquire(); // Paper -+ registerCleaner(); // Paper - } - -+ //noinspection ConstantConditions - return this.data; - } -+ // Paper end - - public DataLayer copy() { return this.copy(); } // Paper - OBFHELPER - public DataLayer copy() { -- return this.data == null ? new DataLayer() : new DataLayer((byte[]) this.data.clone()); -+ return this.data == null ? new DataLayer() : new DataLayer(this.data); // Paper - clone in ctor - } - - public String toString() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 6c28a611b9b79c3322ab07883972c07b3bfc3073..1e58958c3d7b10da5a5f22fc9591d9183e53e3cc 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -435,11 +435,11 @@ public class ChunkSerializer { - } - - if (nibblearray != null && !nibblearray.isEmpty()) { -- nbttagcompound2.putByteArray("BlockLight", nibblearray.getData()); -+ nbttagcompound2.putByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper - } - - if (nibblearray1 != null && !nibblearray1.isEmpty()) { -- nbttagcompound2.putByteArray("SkyLight", nibblearray1.getData()); -+ nbttagcompound2.putByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper - } - - nbttaglist.add(nbttagcompound2); -diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -index 4c9041f1c1cb4b3ec114fbd0c5d4db50a6f2526d..54cca3b376e5ce02936edc8b9c17e67e17f07147 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -+++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.lighting; - - import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; - import javax.annotation.Nullable; -+import net.minecraft.server.MCUtil; - import net.minecraft.world.level.chunk.DataLayer; - - public abstract class DataLayerStorageMap> { -@@ -34,7 +35,9 @@ public abstract class DataLayerStorageMap> { - - public void copyDataLayer(long pos) { - if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data -- this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data -+ DataLayer updating = this.data.getUpdating(pos); // Paper - pool nibbles -+ this.data.queueUpdate(pos, new DataLayer().markPoolSafe(updating.getCloneIfSet())); // Paper - avoid copying light data - pool safe clone -+ if (updating.cleaner != null) MCUtil.scheduleTask(2, updating.cleaner, "Light Engine Release"); // Paper - delay clean incase anything holding ref was still using it - this.clearCache(); - } - -diff --git a/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java b/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java -index 9b95ae0ff193d7f52650f406c70e76e3f7e07e1c..c0d356ac4d54b952fe9ddaf5125b07177ac44d1f 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java -+++ b/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java -@@ -10,7 +10,7 @@ public class FlatDataLayer extends DataLayer { - - public FlatDataLayer(DataLayer nibblearray, int i) { - super(128); -- System.arraycopy(nibblearray.getData(), i * 128, this.data, 0, 128); -+ System.arraycopy(nibblearray.getIfSet(), i * 128, this.data, 0, 128); // Paper - } - - @Override -@@ -20,7 +20,7 @@ public class FlatDataLayer extends DataLayer { - - @Override - public byte[] getData() { -- byte[] abyte = new byte[2048]; -+ byte[] abyte = BYTE_2048.acquire(); // Paper - - for (int i = 0; i < 16; ++i) { - System.arraycopy(this.data, 0, abyte, i * 128, 128); -diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -index 177dae992d13674bb285a60b8427df9ea843dc99..5757bcfded35f112d52a7c81586850ba50e0d8dd 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -@@ -156,7 +156,7 @@ public abstract class LayerLightSectionStorage> - protected DataLayer createDataLayer(long sectionPos) { - DataLayer nibblearray = (DataLayer) this.queuedSections.get(sectionPos); - -- return nibblearray != null ? nibblearray : new DataLayer(); -+ return nibblearray != null ? nibblearray : new DataLayer().markPoolSafe(); // Paper - } - - protected void clearQueuedSectionBlocks(LayerLightEngine storage, long sectionPos) { -@@ -338,12 +338,12 @@ public abstract class LayerLightSectionStorage> - - protected void queueSectionData(long sectionPos, @Nullable DataLayer array, boolean flag) { - if (array != null) { -- this.queuedSections.put(sectionPos, array); -+ DataLayer remove = this.queuedSections.put(sectionPos, array); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed - if (!flag) { - this.untrustedSections.add(sectionPos); - } - } else { -- this.queuedSections.remove(sectionPos); -+ DataLayer remove = this.queuedSections.remove(sectionPos); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed - } - - } -diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -index 410fcfa8c01b7e3d3e3829ebdb92a11badff16ea..88f168f9d4c29cfc93500227bf8a60de4b6e4d8a 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -@@ -172,9 +172,9 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage -Date: Mon, 27 Apr 2020 02:48:06 -0700 -Subject: [PATCH] Reduce MutableInt allocations from light engine - -We can abuse the fact light is single threaded and share an instance -per light engine instance - -diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java -index 8979101a52537f4ec03a5f43030264b8e72fcea4..709fc42057f8a0282c3c942067e63abb874d9042 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java -+++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java -@@ -16,6 +16,7 @@ public final class BlockLightEngine extends LayerLightEngine= 15) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java -index d99890121bdf1e499e364bdc953e628c04d69b95..ff1fbc46776b26ca56c3293e40ed55028230ec46 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java -+++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java -@@ -15,6 +15,7 @@ public final class SkyLightEngine extends LayerLightEngine= 15) { - return level; - } else { -- MutableInt mutableint = new MutableInt(); -+ //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded - BlockState iblockdata = this.getStateAndOpacity(targetId, mutableint); - - if (mutableint.getValue() >= 15) { diff --git a/Remapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/Remapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch deleted file mode 100644 index 6751467281..0000000000 --- a/Remapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Apr 2020 00:04:16 -0700 -Subject: [PATCH] Reduce allocation of Vec3D by entity tracker - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 67f748d5955453ba4873b0c9bb741b5bfe52d655..738f1183ce663db7c67d2f0289823390a7f06a0e 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -95,7 +95,6 @@ import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; - import net.minecraft.world.level.storage.DimensionDataStorage; - import net.minecraft.world.level.storage.LevelStorageSource; --import net.minecraft.world.phys.Vec3; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper - import org.apache.commons.lang3.mutable.MutableBoolean; - import org.apache.logging.log4j.LogManager; -@@ -2233,9 +2232,14 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - public void updatePlayer(ServerPlayer player) { - org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot - if (player != this.entity) { -- Vec3 vec3d = player.position().subtract(this.entity.position()); // MC-155077, SPIGOT-5113 -+ // Paper start - remove allocation of Vec3D here -+ //Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 -+ double vec3d_dx = player.getX() - this.entity.getX(); -+ double vec3d_dy = player.getY() - this.entity.getY(); -+ double vec3d_dz = player.getZ() - this.entity.getZ(); -+ // Paper end - remove allocation of Vec3D here - int i = Math.min(this.getEffectiveRange(), (ChunkMap.this.viewDistance - 1) * 16); -- boolean flag = vec3d.x >= (double) (-i) && vec3d.x <= (double) i && vec3d.z >= (double) (-i) && vec3d.z <= (double) i && this.entity.broadcastToPlayer(player); -+ boolean flag = vec3d_dx >= (double) (-i) && vec3d_dx <= (double) i && vec3d_dz >= (double) (-i) && vec3d_dz <= (double) i && this.entity.broadcastToPlayer(player); // Paper - remove allocation of Vec3D here - - if (flag) { - boolean flag1 = this.entity.forcedLoading; -diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index d797873db52ba265ac4478f9f3c6344badd4739e..75e2274578c2c28de3d786372df0b4102337a2cc 100644 ---- a/src/main/java/net/minecraft/server/level/ServerEntity.java -+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -154,8 +154,12 @@ public class ServerEntity { - ++this.teleportDelay; - i = Mth.floor(this.entity.yRot * 256.0F / 360.0F); - j = Mth.floor(this.entity.xRot * 256.0F / 360.0F); -- Vec3 vec3d = this.entity.position().subtract(ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp)); -- boolean flag1 = vec3d.lengthSqr() >= 7.62939453125E-6D; -+ // Paper start - reduce allocation of Vec3D here -+ double vec3d_dx = this.entity.getX() - 2.44140625E-4D*(this.xp); -+ double vec3d_dy = this.entity.getY() - 2.44140625E-4D*(this.yp); -+ double vec3d_dz = this.entity.getZ() - 2.44140625E-4D*(this.zp); -+ boolean flag1 = (vec3d_dx * vec3d_dx + vec3d_dy * vec3d_dy + vec3d_dz * vec3d_dz) >= 7.62939453125E-6D; -+ // Paper end - reduce allocation of Vec3D here - Packet packet1 = null; - boolean flag2 = flag1 || this.tickCount % 60 == 0; - boolean flag3 = Math.abs(i - this.yRotp) >= 1 || Math.abs(j - this.xRotp) >= 1; -@@ -172,9 +176,11 @@ public class ServerEntity { - // CraftBukkit end - - if (this.tickCount > 0 || this.entity instanceof AbstractArrow) { -- long k = ClientboundMoveEntityPacket.entityToPacket(vec3d.x); -- long l = ClientboundMoveEntityPacket.entityToPacket(vec3d.y); -- long i1 = ClientboundMoveEntityPacket.entityToPacket(vec3d.z); -+ // Paper start - remove allocation of Vec3D here -+ long k = ClientboundMoveEntityPacket.entityToPacket(vec3d_dx); -+ long l = ClientboundMoveEntityPacket.entityToPacket(vec3d_dy); -+ long i1 = ClientboundMoveEntityPacket.entityToPacket(vec3d_dz); -+ // Paper end - remove allocation of Vec3D here - boolean flag4 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L; - - if (!flag4 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.isOnGround()) { diff --git a/Remapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch b/Remapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch deleted file mode 100644 index 3ca91f50a5..0000000000 --- a/Remapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Fri, 15 May 2020 01:10:03 -0400 -Subject: [PATCH] Ensure safe gateway teleport - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -index b70e0633435a272ae1e9fbd12d7f18862de0b951..3491956cb09b825bbfc99667b058d67cef127332 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -@@ -86,9 +86,14 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements - } else if (!this.level.isClientSide) { - List list = this.level.getEntitiesOfClass(Entity.class, new AABB(this.getBlockPos()), TheEndGatewayBlockEntity::canEntityTeleport); - -- if (!list.isEmpty()) { -- this.teleportEntity((Entity) list.get(this.level.random.nextInt(list.size()))); -+ // Paper start -+ for (Entity entity : list) { -+ if (entity.canChangeDimensions()) { -+ this.teleportEntity(entity); -+ break; -+ } - } -+ // Paper end - - if (this.age % 2400L == 0L) { - this.triggerCooldown(); diff --git a/Remapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch b/Remapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch deleted file mode 100644 index 61d650c223..0000000000 --- a/Remapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 16 May 2020 10:12:15 +0200 -Subject: [PATCH] Add option for console having all permissions - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 5f3b0d95cc7e6a0434d78ea7305a70689c41c71c..7f140333c2e62012fa572c1a061d84432426997f 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -429,4 +429,9 @@ public class PaperConfig { - - } - -+ public static boolean consoleHasAllPermissions = false; -+ private static void consoleHasAllPermissions() { -+ consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); -+ } -+ - } -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 525cd44411b344bc4b5d43c087094fea88fa41a6..4817b8ab259d348b48bc325d34ba9351ffe951df 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1886,7 +1886,7 @@ public abstract class Player extends LivingEntity { - } - } - -- protected void removeEntitiesOnShoulder() { -+ public void removeEntitiesOnShoulder() { // Paper - protected -> public - if (this.timeEntitySatOnShoulder + 20L < this.level.getGameTime()) { - // CraftBukkit start - if (this.spawnEntityFromShoulder(this.getShoulderEntityLeft())) { -diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -index af986adfdb547cb61fbd52f0f89858f1a9e52cc3..80a67deaeaae3b3f0ceb9a298de5bb38b8ee707b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -@@ -86,5 +86,15 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co - public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { - this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); - } -+ -+ @Override -+ public boolean hasPermission(String name) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); -+ } -+ -+ @Override -+ public boolean hasPermission(org.bukkit.permissions.Permission perm) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -index d0757d116ee689041c0e64e622d2c36e0b0bcaf1..7b53b5a0857fc0ce0463db319f86a1f79833ab93 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -@@ -39,4 +39,16 @@ public class CraftRemoteConsoleCommandSender extends ServerCommandSender impleme - public void setOp(boolean value) { - throw new UnsupportedOperationException("Cannot change operator status of remote controller."); - } -+ -+ // Paper start -+ @Override -+ public boolean hasPermission(String name) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); -+ } -+ -+ @Override -+ public boolean hasPermission(org.bukkit.permissions.Permission perm) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/Remapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch deleted file mode 100644 index 1346418468..0000000000 --- a/Remapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 23 May 2020 01:31:06 -0400 -Subject: [PATCH] Fix Non Full Status Chunk NBT Memory Leak - -Any full status chunk that was requested for any status less than full -would hold onto their entire nbt tree and every variable in that function. - -This was due to use of a lambda that persists on the Chunk object -until that chunk reaches FULL status. - -With introduction of no tick, we greatly increased the number of non -full chunks so this was really starting to hurt. - -We further improve it by making a copy of the nbt tag with only the memory -it needs, so that we dont have to hold a copy to the entire compound. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 1e58958c3d7b10da5a5f22fc9591d9183e53e3cc..0adf14af9841cd3a20a8b2c0c320eb06794ef261 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -26,6 +26,7 @@ import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.nbt.LongArrayTag; - import net.minecraft.nbt.ShortTag; -+import net.minecraft.nbt.Tag; - import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; -@@ -199,15 +200,9 @@ public class ChunkSerializer { - object2 = protochunkticklist1; - } - -- object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { -- postLoadChunk(nbttagcompound1, chunk); -- // CraftBukkit start - load chunk persistent data from nbt -- net.minecraft.nbt.Tag persistentBase = nbttagcompound1.get("ChunkBukkitValues"); -- if (persistentBase instanceof CompoundTag) { -- chunk.persistentDataContainer.putAll((CompoundTag) persistentBase); -- } -- // CraftBukkit end -- }); -+ object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. -+ createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities", "ChunkBukkitValues")) // Paper - move CB Chunk PDC into here -+ );// Paper end - } else { - ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter - -@@ -313,6 +308,50 @@ public class ChunkSerializer { - return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading - } - } -+ // Paper start -+ -+ /** -+ * This wrapper will error out if any key is accessed that wasn't copied so we can catch it easy on an update -+ */ -+ private static class SafeNBTCopy extends CompoundTag { -+ private final java.util.Set keys = new java.util.HashSet(); -+ public SafeNBTCopy(CompoundTag base, String... keys) { -+ for (String key : keys) { -+ this.keys.add(key); -+ final Tag nbtBase = base.get(key); -+ if (nbtBase != null) { -+ this.put(key, nbtBase); -+ } -+ } -+ } -+ -+ @Override -+ public boolean contains(String key) { -+ if (super.contains(key)) { -+ return true; -+ } else if (keys.contains(key)) { -+ return false; -+ } -+ throw new IllegalStateException("Missing Key " + key + " in SafeNBTCopy"); -+ } -+ -+ @Override -+ public boolean contains(String key, int type) { -+ return contains(key) && super.contains(key, type); -+ } -+ } -+ private static java.util.function.Consumer createLoadEntitiesConsumer(CompoundTag nbt) { -+ return (chunk) -> { -+ postLoadChunk(nbt, chunk); -+ // CraftBukkit start - load chunk persistent data from nbt -+ Tag persistentBase = nbt.get("ChunkBukkitValues"); -+ if (persistentBase instanceof CompoundTag) { -+ chunk.persistentDataContainer.putAll((CompoundTag) persistentBase); -+ } -+ // CraftBukkit end -+ }; -+ } -+ // Paper end - - // Paper start - async chunk save for unload - public static final class AsyncSaveData { diff --git a/Remapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch b/Remapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch deleted file mode 100644 index 7918002d5e..0000000000 --- a/Remapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 12 May 2020 23:02:43 +0200 -Subject: [PATCH] Workaround for Client Lag Spikes (MC-162253) - -When crossing certain chunk boundaries, the client needlessly -calculates light maps for chunk neighbours. In some specific map -configurations, these calculations cause a 500ms+ freeze on the Client. - -This patch basically serves as a workaround by sending light maps -to the client, so that it doesn't attempt to calculate them. -This mitigates the frametime impact to a minimum (but it's still there). - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 738f1183ce663db7c67d2f0289823390a7f06a0e..8070acde38c47c364c1d26ec3b7d65da037554a5 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -85,6 +85,7 @@ import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.ImposterProtoChunk; - import net.minecraft.world.level.chunk.LevelChunk; -+import net.minecraft.world.level.chunk.LevelChunkSection; - import net.minecraft.world.level.chunk.LightChunkGetter; - import net.minecraft.world.level.chunk.ProtoChunk; - import net.minecraft.world.level.chunk.UpgradeData; -@@ -2018,7 +2019,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - // Paper start - private static int getLightMask(final LevelChunk chunk) { -- final ChunkSection[] chunkSections = chunk.getSections(); -+ final LevelChunkSection[] chunkSections = chunk.getSections(); - int mask = 0; - - for (int i = 0; i < chunkSections.length; ++i) { -@@ -2029,7 +2030,7 @@ Lightmasks have 18 bits, from the -1 (void) section until the 17th (air) section - Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. - - */ -- mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; -+ mask |= (LevelChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; - } - - return mask; -@@ -2060,9 +2061,68 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - public final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { - if (packets[0] == null) { -+ // Paper start - add 8 for light fix workaround -+ if (packets.length != 10) { // in case Plugins call sendChunk, resize -+ packets = new Packet[10]; -+ } -+ // Paper end - packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass - packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, true); -+ -+ // Paper start - Fix MC-162253 -+ final int lightMask = getLightMask(chunk); -+ int i = 1; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) { -+ continue; -+ } -+ -+ ++i; -+ -+ if (!chunk.isNeighbourLoaded(x, z)) { -+ continue; -+ } -+ -+ final LevelChunk neighbor = chunk.getRelativeNeighbourIfLoaded(x, z); -+ final int updateLightMask = lightMask & ~getCeilingLightMask(neighbor); -+ -+ if (updateLightMask == 0) { -+ continue; -+ } -+ -+ packets[i] = new ClientboundLightUpdatePacket(new ChunkPos(chunk.getPos().x + x, chunk.getPos().z + z), lightEngine, updateLightMask, 0, true); -+ } -+ } -+ } -+ -+ final int viewDistance = playerViewDistanceBroadcastMap.getLastViewDistance(player); -+ final long lastPosition = playerViewDistanceBroadcastMap.getLastCoordinate(player); -+ -+ int j = 1; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) { -+ continue; -+ } -+ -+ ++j; -+ -+ Packet packet = packets[j]; -+ if (packet == null) { -+ continue; -+ } -+ -+ final int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - (chunk.getPos().x + x)); -+ final int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - (chunk.getPos().z + z)); -+ -+ if (Math.max(distX, distZ) > viewDistance) { -+ continue; -+ } -+ player.connection.send(packet); -+ } - } -+ // Paper end - Fix MC-162253 - - player.trackChunk(chunk.getPos(), packets[0], packets[1]); - DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos()); -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index dbea2a4370ccf24a5084cdabeecbc81f206e910a..9b76dc15417eef420804e5184a6d684e1137a746 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -279,7 +279,7 @@ public class LevelChunk implements ChunkAccess { - - // broadcast - Object[] backingSet = inRange.getBackingSet(); -- Packet[] chunkPackets = new Packet[2]; -+ Packet[] chunkPackets = new Packet[10]; - for (int index = 0, len = backingSet.length; index < len; ++index) { - Object temp = backingSet[index]; - if (!(temp instanceof ServerPlayer)) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index 5e7f6000df129100ef306703f325af9f60da8ae6..cc7d930c1fcd7157efc181d766e1639669f6eab9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -107,6 +107,7 @@ public class LevelChunkSection { - return this.nonEmptyBlockCount == 0; - } - -+ public static boolean isEmpty(@Nullable LevelChunkSection chunksection) { return isEmpty(chunksection) ; } // Paper - OBFHELPER - public static boolean isEmpty(@Nullable LevelChunkSection section) { - return section == LevelChunk.EMPTY_SECTION || section.isEmpty(); - } diff --git a/Remapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/Remapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch deleted file mode 100644 index c64155c42a..0000000000 --- a/Remapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch +++ /dev/null @@ -1,1352 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Apr 2020 03:56:07 -0400 -Subject: [PATCH] Implement Chunk Priority / Urgency System for Chunks - -Mark chunks that are blocking main thread for world generation as urgent - -Implements a general priority system so that chunks that are sorted in -the generator queues can prioritize certain chunks over another. - -Urgent chunks will jump to the front of the line, ensuring that a -sync chunk load on an ungenerated chunk does not lag the server for -a long period of time if the servers generator queues are filled with -lots of chunks already. - -This massively reduces the lag spikes from sync chunk gens. - -Then we further prioritize loading order so nearby chunks have higher -priority than distant chunks, reducing the pressure a high no tick -view distance holds on you. - -Chunks in front of the player have higher priority, to help with -fast traveling players keep up with their movement. - -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -index 499aff1f1e1ffc01ba8f9de43ca17899525a306f..97b85587525ddb62af9bfc8785b48727a6135599 100644 ---- a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -@@ -108,7 +108,7 @@ public final class ChunkTaskManager { - } - - static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z) { -- dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); -+ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 4); - } - - static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z, int indent, int maxDepth) { -@@ -129,6 +129,30 @@ public final class ChunkTaskManager { - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Priority - " + chunkHolder.getCurrentPriority()); -+ -+ if (!chunkHolder.neighbors.isEmpty()) { -+ if (indent >= maxDepth) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: (Can't show, too deeply nested)"); -+ return; -+ } -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: "); -+ for (ChunkHolder neighbor : chunkHolder.neighbors.keySet()) { -+ ChunkStatus status = neighbor.getChunkHolderStatus(); -+ if (status != null && status.isAtLeastStatus(ChunkHolder.getStatus(neighbor.getTicketLevel()))) { -+ continue; -+ } -+ int nx = neighbor.pos.x; -+ int nz = neighbor.pos.z; -+ if (seenChunks.contains(neighbor)) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + " (CIRCULAR)"); -+ continue; -+ } -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + ":"); -+ dumpChunkInfo(seenChunks, neighbor, nx, nz, indent + 1, maxDepth); -+ } -+ } -+ - } - } - -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index d18497a33dc53f6b465e659967bf8c98731c46c0..9a5737caf250dd2cc7f244248226f69117b27bad 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -631,10 +631,10 @@ public final class MCUtil { - - // sorting by coordinate makes the log easier to read - allChunks.sort((ChunkHolder v1, ChunkHolder v2) -> { -- if (v1.location.x != v2.location.x) { -- return Integer.compare(v1.location.x, v2.location.x); -+ if (v1.pos.x != v2.pos.x) { -+ return Integer.compare(v1.pos.x, v2.pos.x); - } -- return Integer.compare(v1.location.z, v2.location.z); -+ return Integer.compare(v1.pos.z, v2.pos.z); - }); - - worldData.addProperty("name", world.getWorld().getName()); -@@ -667,14 +667,15 @@ public final class MCUtil { - for (ChunkHolder playerChunk : allChunks) { - JsonObject chunkData = new JsonObject(); - -- Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.pair()); -+ Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.toLong()); - ChunkStatus status = getChunkStatus(playerChunk); - -- chunkData.addProperty("x", playerChunk.location.x); -- chunkData.addProperty("z", playerChunk.location.z); -+ chunkData.addProperty("x", playerChunk.pos.x); -+ chunkData.addProperty("z", playerChunk.pos.z); - chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); -+ chunkData.addProperty("priority", playerChunk.getCurrentPriority()); - chunkData.addProperty("state", ChunkHolder.getFullChunkStatus(playerChunk.getTicketLevel()).toString()); -- chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.pair())); -+ chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.toLong())); - chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); - - JsonArray ticketsData = new JsonArray(); -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index d907872d80f840b343419f49a6708082da6f921b..ce320672d7602c94dd75ad857435dca6ac3bab56 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -1,6 +1,7 @@ - package net.minecraft.server.level; - - import com.mojang.datafixers.util.Either; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper - import it.unimi.dsi.fastutil.shorts.ShortArraySet; - import it.unimi.dsi.fastutil.shorts.ShortSet; - import java.util.List; -@@ -19,6 +20,7 @@ import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; - import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; - import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; - import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; -+import net.minecraft.server.MCUtil; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.LightLayer; -@@ -52,8 +54,8 @@ public class ChunkHolder { - private CompletableFuture chunkToSave; - public int oldTicketLevel; - private int ticketLevel; -- private int queueLevel; -- final ChunkPos pos; // Paper - private -> package -+ volatile int queueLevel; public final int getCurrentPriority() { return queueLevel; } // Paper - OBFHELPER - make volatile since this is concurrently accessed -+ public final ChunkPos pos; // Paper - private -> public - private boolean hasChangedSections; - private final ShortSet[] changedBlocksPerSection; - private int blockChangedLightSectionFilter; -@@ -65,6 +67,7 @@ public class ChunkHolder { - private boolean resendLight; - - private final ChunkMap chunkMap; // Paper -+ public ServerLevel getWorld() { return chunkMap.level; } // Paper - - long lastAutoSaveTime; // Paper - incremental autosave - long inactiveTimeStart; // Paper - incremental autosave -@@ -92,6 +95,120 @@ public class ChunkHolder { - return null; - } - // Paper end - no-tick view distance -+ // Paper start - Chunk gen/load priority system -+ volatile int neighborPriority = -1; -+ volatile int priorityBoost = 0; -+ public final java.util.concurrent.ConcurrentHashMap neighbors = new java.util.concurrent.ConcurrentHashMap<>(); -+ public final Long2ObjectOpenHashMap neighborPriorities = new Long2ObjectOpenHashMap<>(); -+ -+ private int getDemandedPriority() { -+ int priority = neighborPriority; // if we have a neighbor priority, use it -+ int myPriority = getMyPriority(); -+ -+ if (priority == -1 || (ticketLevel <= 33 && priority > myPriority)) { -+ priority = myPriority; -+ } -+ -+ return Math.max(1, Math.min(Math.max(ticketLevel, ChunkMap.MAX_CHUNK_DISTANCE), priority)); -+ } -+ -+ private int getMyPriority() { -+ if (priorityBoost == DistanceManager.URGENT_PRIORITY) { -+ return 2; // Urgent - ticket level isn't always 31 so 33-30 = 3, but allow 1 more tasks to go below this for dependents -+ } -+ return ticketLevel - priorityBoost; -+ } -+ -+ private int getNeighborsPriority() { -+ return (neighborPriorities.isEmpty() ? getMyPriority() : getDemandedPriority()) + 1; -+ } -+ -+ public void onNeighborRequest(ChunkHolder neighbor, ChunkStatus status) { -+ neighbor.setNeighborPriority(this, getNeighborsPriority()); -+ this.neighbors.compute(neighbor, (playerChunk, currentWantedStatus) -> { -+ if (currentWantedStatus == null || !currentWantedStatus.isAtLeastStatus(status)) { -+ //System.out.println(this + " request " + neighbor + " at " + status + " currently " + currentWantedStatus); -+ return status; -+ } else { -+ //System.out.println(this + " requested " + neighbor + " at " + status + " but thats lower than other wanted status " + currentWantedStatus); -+ return currentWantedStatus; -+ } -+ }); -+ -+ } -+ -+ public void onNeighborDone(ChunkHolder neighbor, ChunkStatus chunkstatus, ChunkAccess chunk) { -+ this.neighbors.compute(neighbor, (playerChunk, wantedStatus) -> { -+ if (wantedStatus != null && chunkstatus.isAtLeastStatus(wantedStatus)) { -+ //System.out.println(this + " neighbor done at " + neighbor + " for status " + chunkstatus + " wanted " + wantedStatus); -+ neighbor.removeNeighborPriority(this); -+ return null; -+ } else { -+ //System.out.println(this + " neighbor finished our previous request at " + neighbor + " for status " + chunkstatus + " but we now want instead " + wantedStatus); -+ return wantedStatus; -+ } -+ }); -+ } -+ -+ private void removeNeighborPriority(ChunkHolder requester) { -+ synchronized (neighborPriorities) { -+ neighborPriorities.remove(requester.pos.toLong()); -+ recalcNeighborPriority(); -+ } -+ checkPriority(); -+ } -+ -+ -+ private void setNeighborPriority(ChunkHolder requester, int priority) { -+ synchronized (neighborPriorities) { -+ neighborPriorities.put(requester.pos.toLong(), Integer.valueOf(priority)); -+ recalcNeighborPriority(); -+ } -+ checkPriority(); -+ } -+ -+ private void recalcNeighborPriority() { -+ neighborPriority = -1; -+ if (!neighborPriorities.isEmpty()) { -+ synchronized (neighborPriorities) { -+ for (Integer neighbor : neighborPriorities.values()) { -+ if (neighbor < neighborPriority || neighborPriority == -1) { -+ neighborPriority = neighbor; -+ } -+ } -+ } -+ } -+ } -+ private void checkPriority() { -+ if (getCurrentPriority() != getDemandedPriority()) this.chunkMap.queueHolderUpdate(this); -+ } -+ -+ public final double getDistance(ServerPlayer player) { -+ return getDistance(player.getX(), player.getZ()); -+ } -+ public final double getDistance(double blockX, double blockZ) { -+ int cx = MCUtil.fastFloor(blockX) >> 4; -+ int cz = MCUtil.fastFloor(blockZ) >> 4; -+ final double x = pos.x - cx; -+ final double z = pos.z - cz; -+ return (x * x) + (z * z); -+ } -+ -+ public final double getDistanceFrom(BlockPos pos) { -+ return getDistance(pos.getX(), pos.getZ()); -+ } -+ -+ @Override -+ public String toString() { -+ return "PlayerChunk{" + -+ "location=" + pos + -+ ", ticketLevel=" + ticketLevel + "/" + getStatus(this.ticketLevel) + -+ ", chunkHolderStatus=" + getChunkHolderStatus() + -+ ", neighborPriority=" + getNeighborsPriority() + -+ ", priority=(" + ticketLevel + " - " + priorityBoost +" vs N " + neighborPriority + ") = " + getDemandedPriority() + " A " + getCurrentPriority() + -+ '}'; -+ } -+ // Paper end - - public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { - this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); -@@ -194,6 +311,18 @@ public class ChunkHolder { - } - return null; - } -+ public static ChunkStatus getNextStatus(ChunkStatus status) { -+ if (status == ChunkStatus.FULL) { -+ return status; -+ } -+ return CHUNK_STATUSES.get(status.getStatusIndex() + 1); -+ } -+ public CompletableFuture> getStatusFutureUncheckedMain(ChunkStatus chunkstatus) { -+ return ensureMain(getFutureIfPresentUnchecked(chunkstatus)); -+ } -+ public CompletableFuture ensureMain(CompletableFuture future) { -+ return future.thenApplyAsync(r -> r, chunkMap.mainInvokingExecutor); -+ } - // Paper end - - public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { -@@ -440,6 +569,7 @@ public class ChunkHolder { - return this.queueLevel; - } - -+ private void setPriority(int i) { setQueueLevel(i); } // Paper - OBFHELPER - private void setQueueLevel(int level) { - this.queueLevel = level; - } -@@ -458,7 +588,7 @@ public class ChunkHolder { - // CraftBukkit start - // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. - if (playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { -- this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { -+ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main - LevelChunk chunk = (LevelChunk)either.left().orElse(null); - if (chunk != null) { - chunkStorage.callbackExecutor.execute(() -> { -@@ -523,12 +653,13 @@ public class ChunkHolder { - if (!flag2 && flag3) { - // Paper start - cache ticking ready status - int expectCreateCount = ++this.fullChunkCreateCount; -- this.fullChunkFuture = chunkStorage.unpackTicks(this); this.fullChunkFuture.thenAccept((either) -> { -+ this.fullChunkFuture = chunkStorage.unpackTicks(this); ensureMain(this.fullChunkFuture).thenAccept((either) -> { // Paper - ensure main - if (either.left().isPresent() && ChunkHolder.this.fullChunkCreateCount == expectCreateCount) { - // note: Here is a very good place to add callbacks to logic waiting on this. - LevelChunk fullChunk = either.left().get(); - ChunkHolder.this.isFullChunkReady = true; - fullChunk.playerChunk = ChunkHolder.this; -+ this.chunkMap.distanceManager.clearPriorityTickets(pos); - - - } -@@ -553,7 +684,7 @@ public class ChunkHolder { - - if (!flag4 && flag5) { - // Paper start - cache ticking ready status -- this.tickingChunkFuture = chunkStorage.postProcess(this); this.tickingChunkFuture.thenAccept((either) -> { -+ this.tickingChunkFuture = chunkStorage.postProcess(this); ensureMain(this.tickingChunkFuture).thenAccept((either) -> { // Paper - ensure main - if (either.left().isPresent()) { - // note: Here is a very good place to add callbacks to logic waiting on this. - LevelChunk tickingChunk = either.left().get(); -@@ -584,7 +715,7 @@ public class ChunkHolder { - } - - // Paper start - cache ticking ready status -- this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); this.entityTickingChunkFuture.thenAccept((either) -> { -+ this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); ensureMain(this.entityTickingChunkFuture).thenAccept((either) -> { // Paper ensureMain - if (either.left().isPresent()) { - // note: Here is a very good place to add callbacks to logic waiting on this. - LevelChunk entityTickingChunk = either.left().get(); -@@ -604,12 +735,29 @@ public class ChunkHolder { - this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; - } - -- this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); -+ // Paper start - raise IO/load priority if priority changes, use our preferred priority -+ priorityBoost = chunkMap.distanceManager.getChunkPriority(pos); -+ int priority = getDemandedPriority(); -+ if (getCurrentPriority() > priority) { -+ int ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; -+ if (priority <= 10) { -+ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; -+ } else if (priority <= 20) { -+ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; -+ } -+ chunkMap.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, ioPriority); -+ } -+ if (getCurrentPriority() != priority) { -+ this.onLevelChange.onLevelChange(this.pos, this::getCurrentPriority, priority, this::setPriority); // use preferred priority -+ int neighborsPriority = getNeighborsPriority(); -+ this.neighbors.forEach((neighbor, neighborDesired) -> neighbor.setNeighborPriority(this, neighborsPriority)); -+ } -+ // Paper end - this.oldTicketLevel = this.ticketLevel; - // CraftBukkit start - // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. - if (!playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { -- this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { -+ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main - LevelChunk chunk = (LevelChunk)either.left().orElse(null); - if (chunk != null) { - chunkStorage.callbackExecutor.execute(() -> { -@@ -691,6 +839,7 @@ public class ChunkHolder { - - public interface LevelChangeListener { - -+ default void changePriority(ChunkPos chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer) { onLevelChange(chunkcoordintpair, intsupplier, i, intconsumer); } // Paper - OBFHELPER - void onLevelChange(ChunkPos pos, IntSupplier levelGetter, int targetLevel, IntConsumer levelSetter); - } - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c06720820 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -14,6 +14,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; - import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - import it.unimi.dsi.fastutil.longs.Long2ByteMap; - import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; // Paper - import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; - import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; - import it.unimi.dsi.fastutil.longs.LongIterator; -@@ -51,6 +52,7 @@ import net.minecraft.CrashReport; - import net.minecraft.CrashReportCategory; - import net.minecraft.ReportedException; - import net.minecraft.Util; -+import net.minecraft.core.BlockPos; - import net.minecraft.core.SectionPos; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.protocol.Packet; -@@ -102,6 +104,7 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - import org.bukkit.entity.Player; // CraftBukkit -+import org.spigotmc.AsyncCatcher; - - public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider { - -@@ -139,6 +142,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public final ServerLevel level; - private final ThreadedLevelLightEngine lightEngine; - private final BlockableEventLoop mainThreadExecutor; -+ final java.util.concurrent.Executor mainInvokingExecutor; // Paper - public final ChunkGenerator generator; - private final Supplier overworldDataStorage; public final Supplier getWorldPersistentDataSupplier() { return this.overworldDataStorage; } // Paper - OBFHELPER - private final PoiManager poiManager; -@@ -176,6 +180,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - @Override - public void execute(Runnable runnable) { -+ AsyncCatcher.catchOp("Callback Executor execute"); - if (queued == null) { - queued = new java.util.ArrayDeque<>(); - } -@@ -184,6 +189,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - @Override - public void run() { -+ AsyncCatcher.catchOp("Callback Executor run"); - if (queued == null) { - return; - } -@@ -338,6 +344,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.level = worldserver; - this.generator = chunkGenerator; - this.mainThreadExecutor = mainThreadExecutor; -+ // Paper start -+ this.mainInvokingExecutor = (run) -> { -+ if (MCUtil.isMainThread()) { -+ run.run(); -+ } else { -+ mainThreadExecutor.execute(run); -+ } -+ }; -+ // Paper end - ProcessorMailbox threadedmailbox = ProcessorMailbox.create(workerExecutor, "worldgen"); - - mainThreadExecutor.getClass(); -@@ -432,6 +447,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, - (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, - com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ checkHighPriorityChunks(player); - if (newState.size() != 1) { - return; - } -@@ -450,7 +466,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); - ChunkMap.this.level.getChunkSource().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update -- }); -+ ChunkMap.this.level.getChunkSource().clearPriorityTickets(chunkPos); -+ }, (player, prevPos, newPos) -> { -+ player.lastHighPriorityChecked = -1; // reset and recheck -+ checkHighPriorityChunks(player); -+ }); - this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); - this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, - (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -@@ -467,6 +487,115 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - }); - // Paper end - no-tick view distance - } -+ // Paper start - Chunk Prioritization -+ public void queueHolderUpdate(ChunkHolder playerchunk) { -+ Runnable runnable = () -> { -+ if (isUnloading(playerchunk)) { -+ return; // unloaded -+ } -+ distanceManager.pendingChunkUpdates.add(playerchunk); -+ if (!distanceManager.pollingPendingChunkUpdates) { -+ level.getChunkSource().runDistanceManagerUpdates(); -+ } -+ }; -+ if (MCUtil.isMainThread()) { -+ // We can't use executor here because it will not execute tasks if its currently in the middle of executing tasks... -+ runnable.run(); -+ } else { -+ mainThreadExecutor.execute(runnable); -+ } -+ } -+ -+ private boolean isUnloading(ChunkHolder playerchunk) { -+ return playerchunk == null || toDrop.contains(playerchunk.pos.toLong()); -+ } -+ -+ private void updateChunkPriorityMap(Long2IntOpenHashMap map, long chunk, int level) { -+ int prev = map.getOrDefault(chunk, -1); -+ if (level > prev) { -+ map.put(chunk, level); -+ } -+ } -+ -+ public void checkHighPriorityChunks(ServerPlayer player) { -+ int currentTick = MinecraftServer.currentTick; -+ if (currentTick - player.lastHighPriorityChecked < 20 || !player.isRealPlayer) { // weed out fake players -+ return; -+ } -+ player.lastHighPriorityChecked = currentTick; -+ Long2IntOpenHashMap priorities = new Long2IntOpenHashMap(); -+ -+ int viewDistance = getEffectiveNoTickViewDistance(); -+ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); -+ -+ // Prioritize circular near -+ double playerChunkX = Mth.floor(player.getX()) >> 4; -+ double playerChunkZ = Mth.floor(player.getZ()) >> 4; -+ pos.setValues(player.getX(), 0, player.getZ()); -+ double twoThirdModifier = 2D / 3D; -+ MCUtil.getSpiralOutChunks(pos, Math.min(6, viewDistance)).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) return; -+ -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ // Prioritize immediate -+ if (dist <= 4) { -+ updateChunkPriorityMap(priorities, coord.toLong(), (int) (27 - dist)); -+ return; -+ } -+ -+ // Prioritize nearby chunks -+ updateChunkPriorityMap(priorities, coord.toLong(), (int) (20 - dist * twoThirdModifier)); -+ }); -+ -+ // Prioritize Frustum near 3 -+ ChunkPos front3 = player.getChunkInFront(3); -+ pos.setValues(front3.x << 4, 0, front3.z << 4); -+ MCUtil.getSpiralOutChunks(pos, Math.min(5, viewDistance)).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) return; -+ -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ updateChunkPriorityMap(priorities, coord.toLong(), (int) (25 - dist * twoThirdModifier)); -+ }); -+ -+ // Prioritize Frustum near 5 -+ if (viewDistance > 4) { -+ ChunkPos front5 = player.getChunkInFront(5); -+ pos.setValues(front5.x << 4, 0, front5.z << 4); -+ MCUtil.getSpiralOutChunks(pos, 4).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) return; -+ -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ updateChunkPriorityMap(priorities, coord.toLong(), (int) (25 - dist * twoThirdModifier)); -+ }); -+ } -+ -+ // Prioritize Frustum far 7 -+ if (viewDistance > 6) { -+ ChunkPos front7 = player.getChunkInFront(7); -+ pos.setValues(front7.x << 4, 0, front7.z << 4); -+ MCUtil.getSpiralOutChunks(pos, 3).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) { -+ return; -+ } -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ updateChunkPriorityMap(priorities, coord.toLong(), (int) (25 - dist * twoThirdModifier)); -+ }); -+ } -+ -+ if (priorities.isEmpty()) return; -+ distanceManager.delayDistanceManagerTick = true; -+ priorities.long2IntEntrySet().fastForEach(entry -> distanceManager.markHighPriority(new ChunkPos(entry.getLongKey()), entry.getIntValue())); -+ distanceManager.delayDistanceManagerTick = false; -+ level.getChunkSource().runDistanceManagerUpdates(); -+ -+ } -+ -+ private boolean shouldSkipPrioritization(ChunkPos coord) { -+ if (playerViewDistanceNoTickMap.getObjectsInRange(coord.toLong()) == null) return true; -+ ChunkHolder chunk = getUpdatingChunkIfPresent(coord.toLong()); -+ return chunk != null && (chunk.isFullChunkReady()); -+ } -+ // Paper end - - public void updatePlayerMobTypeMap(Entity entity) { - if (!this.level.paperConfig.perPlayerMobSpawns) { -@@ -596,6 +725,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - List>> list = Lists.newArrayList(); - int j = centerChunk.x; - int k = centerChunk.z; -+ ChunkHolder requestingNeighbor = getUpdatingChunkIfPresent(centerChunk.toLong()); // Paper - - for (int l = -margin; l <= margin; ++l) { - for (int i1 = -margin; i1 <= margin; ++i1) { -@@ -614,6 +744,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - ChunkStatus chunkstatus = (ChunkStatus) distanceToStatus.apply(j1); - CompletableFuture> completablefuture = playerchunk.getOrScheduleFuture(chunkstatus, this); -+ // Paper start -+ if (requestingNeighbor != null && requestingNeighbor != playerchunk && !completablefuture.isDone()) { -+ requestingNeighbor.onNeighborRequest(playerchunk, chunkstatus); -+ completablefuture.thenAccept(either -> { -+ requestingNeighbor.onNeighborDone(playerchunk, chunkstatus, either.left().orElse(null)); -+ }); -+ } -+ // Paper end - - list.add(completablefuture); - } -@@ -1081,14 +1219,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - }; - - CompletableFuture chunkSaveFuture = this.level.asyncChunkTaskManager.getChunkSaveFuture(pos.x, pos.z); -+ ChunkHolder playerChunk = getUpdatingChunkIfPresent(pos.toLong()); -+ int chunkPriority = playerChunk != null ? playerChunk.getCurrentPriority() : 33; -+ int priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; -+ -+ if (chunkPriority <= 10) { -+ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; -+ } else if (chunkPriority <= 20) { -+ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; -+ } -+ boolean isHighestPriority = priority == com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; - if (chunkSaveFuture != null) { -- this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, -- com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); -- this.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); -+ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, priority, chunkHolderConsumer, isHighestPriority, chunkSaveFuture); - } else { -- this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, -- com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); -+ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, priority, chunkHolderConsumer, isHighestPriority); - } -+ this.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, priority); - return ret; - // Paper end - } -@@ -1233,7 +1379,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - long i = playerchunk.getPos().toLong(); - - playerchunk.getClass(); -- mailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, playerchunk::getTicketLevel)); -+ mailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, () -> 1)); // Paper - final loads are always urgent! - }); - } - -diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a906f07e97 100644 ---- a/src/main/java/net/minecraft/server/level/DistanceManager.java -+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -21,7 +21,10 @@ import java.util.Set; - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.Executor; - import javax.annotation.Nullable; -+import net.minecraft.core.BlockPos; - import net.minecraft.core.SectionPos; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.SortedArraySet; - import net.minecraft.util.thread.ProcessorHandle; - import net.minecraft.world.level.ChunkPos; -@@ -29,6 +32,7 @@ import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.LevelChunk; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import org.spigotmc.AsyncCatcher; // Paper - - public abstract class DistanceManager { - -@@ -52,7 +56,7 @@ public abstract class DistanceManager { - private final ChunkTaskPriorityQueueSorter ticketThrottler; - private final ProcessorHandle> ticketThrottlerInput; - private final ProcessorHandle ticketThrottlerReleaser; -- private final LongSet ticketsToRelease = new LongOpenHashSet(); -+ private final LongSet ticketsToRelease = new LongOpenHashSet(); public final LongSet getOnPlayerTicketAddQueue() { return ticketsToRelease; } // Paper - OBFHELPER - private final Executor mainThreadExecutor; - private long ticketTickCounter; - -@@ -90,6 +94,7 @@ public abstract class DistanceManager { - } - - private static int getTicketLevelAt(SortedArraySet> arraysetsorted) { -+ AsyncCatcher.catchOp("ChunkMapDistance::getLowestTicketLevel"); // Paper - return !arraysetsorted.isEmpty() ? ((Ticket) arraysetsorted.first()).getTicketLevel() : ChunkMap.MAX_CHUNK_DISTANCE + 1; - } - -@@ -103,6 +108,7 @@ public abstract class DistanceManager { - - public boolean runAllUpdates(ChunkMap chunkStorage) { - //this.f.a(); // Paper - no longer used -+ AsyncCatcher.catchOp("DistanceManagerTick"); // Paper - this.playerTicketManager.runAllUpdates(); - int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE); - boolean flag = i != 0; -@@ -113,11 +119,13 @@ public abstract class DistanceManager { - - // Paper start - if (!this.pendingChunkUpdates.isEmpty()) { -+ this.pollingPendingChunkUpdates = true; try { - while(!this.pendingChunkUpdates.isEmpty()) { - ChunkHolder remove = this.pendingChunkUpdates.remove(); - remove.isUpdateQueued = false; - remove.updateFutures(chunkStorage); - } -+ } finally { this.pollingPendingChunkUpdates = false; } - // Paper end - return true; - } else { -@@ -153,8 +161,10 @@ public abstract class DistanceManager { - return flag; - } - } -+ boolean pollingPendingChunkUpdates = false; // Paper - - private boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean -+ AsyncCatcher.catchOp("ChunkMapDistance::addTicket"); // Paper - SortedArraySet> arraysetsorted = this.getTickets(i); - int j = getTicketLevelAt(arraysetsorted); - Ticket ticket1 = (Ticket) arraysetsorted.addOrGet(ticket); // CraftBukkit - decompile error -@@ -168,7 +178,9 @@ public abstract class DistanceManager { - } - - private boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean -+ AsyncCatcher.catchOp("ChunkMapDistance::removeTicket"); // Paper - SortedArraySet> arraysetsorted = this.getTickets(i); -+ int oldLevel = getTicketLevelAt(arraysetsorted); // Paper - - boolean removed = false; // CraftBukkit - if (arraysetsorted.remove(ticket)) { -@@ -179,7 +191,8 @@ public abstract class DistanceManager { - this.tickets.remove(i); - } - -- this.ticketTracker.update(i, getTicketLevelAt(arraysetsorted), false); -+ int newLevel = getTicketLevelAt(arraysetsorted); // Paper -+ if (newLevel > oldLevel) this.ticketTracker.update(i, newLevel, false); // Paper - return removed; // CraftBukkit - } - -@@ -188,6 +201,135 @@ public abstract class DistanceManager { - this.addTicketAtLevel(type, pos, level, argument); - } - -+ // Paper start -+ public static final int PRIORITY_TICKET_LEVEL = ChunkMap.MAX_CHUNK_DISTANCE; -+ public static final int URGENT_PRIORITY = 29; -+ public boolean delayDistanceManagerTick = false; -+ public boolean markUrgent(ChunkPos coords) { -+ return addPriorityTicket(coords, TicketType.URGENT, URGENT_PRIORITY); -+ } -+ public boolean markHighPriority(ChunkPos coords, int priority) { -+ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); -+ return addPriorityTicket(coords, TicketType.PRIORITY, priority); -+ } -+ -+ public void markAreaHighPriority(ChunkPos center, int priority, int radius) { -+ delayDistanceManagerTick = true; -+ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); -+ int finalPriority = priority; -+ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { -+ addPriorityTicket(coords, TicketType.PRIORITY, finalPriority); -+ }); -+ delayDistanceManagerTick = false; -+ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); -+ } -+ -+ public void clearAreaPriorityTickets(ChunkPos center, int radius) { -+ delayDistanceManagerTick = true; -+ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { -+ this.removeTicket(coords.toLong(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); -+ }); -+ delayDistanceManagerTick = false; -+ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); -+ } -+ -+ private boolean hasPlayerTicket(ChunkPos coords, int level) { -+ SortedArraySet> tickets = this.tickets.get(coords.toLong()); -+ if (tickets == null || tickets.isEmpty()) { -+ return false; -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getType() == TicketType.PLAYER && ticket.getTicketLevel() == level) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ private boolean addPriorityTicket(ChunkPos coords, TicketType ticketType, int priority) { -+ AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket"); -+ long pair = coords.toLong(); -+ ChunkHolder chunk = chunkMap.getUpdatingChunkIfPresent(pair); -+ boolean needsTicket = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(pair) != null && !hasPlayerTicket(coords, 33); -+ -+ if (needsTicket) { -+ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); -+ getOnPlayerTicketAddQueue().add(pair); -+ addTicket(pair, ticket); -+ } -+ if ((chunk != null && chunk.isFullChunkReady())) { -+ if (needsTicket) { -+ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); -+ } -+ return needsTicket; -+ } -+ -+ boolean success; -+ if (!(success = updatePriorityTicket(coords, ticketType, priority))) { -+ Ticket ticket = new Ticket(ticketType, PRIORITY_TICKET_LEVEL, coords); -+ ticket.priority = priority; -+ success = this.addTicket(pair, ticket); -+ } else { -+ if (chunk == null) { -+ chunk = chunkMap.getUpdatingChunkIfPresent(pair); -+ } -+ chunkMap.queueHolderUpdate(chunk); -+ } -+ -+ //chunkMap.world.getWorld().spawnParticle(priority <= 15 ? org.bukkit.Particle.EXPLOSION_HUGE : org.bukkit.Particle.EXPLOSION_NORMAL, chunkMap.world.getWorld().getPlayers(), null, coords.x << 4, 70, coords.z << 4, 2, 0, 0, 0, 1, null, true); -+ -+ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); -+ -+ return success; -+ } -+ -+ private boolean updatePriorityTicket(ChunkPos coords, TicketType type, int priority) { -+ SortedArraySet> tickets = this.tickets.get(coords.toLong()); -+ if (tickets == null) { -+ return false; -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getType() == type) { -+ // We only support increasing, not decreasing, too complicated -+ ticket.setCurrentTick(this.ticketTickCounter); -+ ticket.priority = Math.max(ticket.priority, priority); -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ public int getChunkPriority(ChunkPos coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::getChunkPriority"); -+ SortedArraySet> tickets = this.tickets.get(coords.toLong()); -+ if (tickets == null) { -+ return 0; -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getType() == TicketType.URGENT) { -+ return URGENT_PRIORITY; -+ } -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getType() == TicketType.PRIORITY && ticket.priority > 0) { -+ return ticket.priority; -+ } -+ } -+ return 0; -+ } -+ -+ public void clearPriorityTickets(ChunkPos coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::clearPriority"); -+ this.removeTicket(coords.toLong(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); -+ } -+ -+ public void clearUrgent(ChunkPos coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::clearUrgent"); -+ this.removeTicket(coords.toLong(), new Ticket(TicketType.URGENT, PRIORITY_TICKET_LEVEL, coords)); -+ } -+ // Paper end - public boolean addTicketAtLevel(TicketType ticketType, ChunkPos chunkcoordintpair, int level, T identifier) { - return this.addTicket(chunkcoordintpair.toLong(), new Ticket<>(ticketType, level, identifier)); - // CraftBukkit end -@@ -358,7 +500,7 @@ public abstract class DistanceManager { - - class PlayerTicketTracker extends DistanceManager.FixedPlayerDistanceChunkTracker { - -- private int viewDistance = 0; -+ private int viewDistance = 0; private int getViewDistance() { return viewDistance; } private void setViewDistance(int value) { this.viewDistance = value; } // Paper - OBFHELPER - private final Long2IntMap queueLevels = Long2IntMaps.synchronize(new Long2IntOpenHashMap()); - private final LongSet toUpdate = new LongOpenHashSet(); - -@@ -374,41 +516,68 @@ public abstract class DistanceManager { - - public void updateViewDistance(int watchDistance) { - ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); -+ // Paper start - set the view distance before scheduling chunk loads/unloads -+ int lastViewDistance = getViewDistance(); -+ setViewDistance(watchDistance); -+ // Paper end - - while (objectiterator.hasNext()) { - Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix - byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); - long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); - -- this.onLevelChange(j, b0, this.haveTicketFor(b0), b0 <= watchDistance - 2); -+ this.onLevelChange(j, b0, b0 <= lastViewDistance - 2, this.haveTicketFor(b0)); // Paper - } - -- this.viewDistance = watchDistance; -+ //this.e = i; // Paper - view distance is now set further up - } - - private void onLevelChange(long pos, int distance, boolean oldWithinViewDistance, boolean withinViewDistance) { - if (oldWithinViewDistance != withinViewDistance) { -- Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkPos(pos)); // Paper - no-tick view distance -+ ChunkPos coords = new ChunkPos(pos); // Paper -+ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); // Paper - no-tick view distance - - if (withinViewDistance) { -- DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { -+ scheduleChunkLoad(pos, MinecraftServer.currentTick, distance, (priority) -> { // Paper - smarter ticket delay based on frustum and distance -+ // Paper start - recheck its still valid if not cancel -+ if (!isChunkInRange(pos)) { -+ DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { -+ DistanceManager.this.mainThreadExecutor.execute(() -> { -+ DistanceManager.this.removeTicket(pos, ticket); -+ DistanceManager.this.clearPriorityTickets(coords); -+ }); -+ }, pos, false)); -+ return; -+ } -+ // abort early if we got a ticket already -+ if (hasPlayerTicket(coords, 33)) return; -+ // skip player ticket throttle for near chunks -+ if (priority <= 3) { -+ DistanceManager.this.addTicket(pos, ticket); -+ DistanceManager.this.ticketsToRelease.add(pos); -+ return; -+ } -+ // Paper end -+ DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { // CraftBukkit - decompile error - DistanceManager.this.mainThreadExecutor.execute(() -> { -- if (this.haveTicketFor(this.getLevel(pos))) { -+ if (isChunkInRange(pos)) { if (!hasPlayerTicket(coords, 33)) { // Paper - high priority might of already added it - DistanceManager.this.addTicket(pos, ticket); - DistanceManager.this.ticketsToRelease.add(pos); -- } else { -- DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { -+ }} else { // Paper -+ DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { // CraftBukkit - decompile error - }, pos, false)); - } - - }); - }, pos, () -> { -- return distance; -+ return Math.min(ChunkMap.MAX_CHUNK_DISTANCE, priority); // Paper - })); -+ }); // Paper - } else { - DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { - DistanceManager.this.mainThreadExecutor.execute(() -> { - DistanceManager.this.removeTicket(pos, ticket); -+ DistanceManager.this.clearPriorityTickets(coords); // Paper - }); - }, pos, true)); - } -@@ -416,6 +585,101 @@ public abstract class DistanceManager { - - } - -+ // Paper start - smart scheduling of player tickets -+ private boolean isChunkInRange(long i) { -+ return this.isLoadedChunkLevel(this.getChunkLevel(i)); -+ } -+ public void scheduleChunkLoad(long i, long startTick, int initialDistance, java.util.function.Consumer task) { -+ long elapsed = MinecraftServer.currentTick - startTick; -+ ChunkPos chunkPos = new ChunkPos(i); -+ ChunkHolder updatingChunk = chunkMap.getUpdatingChunkIfPresent(i); -+ if ((updatingChunk != null && updatingChunk.isFullChunkReady()) || !isChunkInRange(i) || getChunkPriority(chunkPos) > 0) { // Copied from above -+ // no longer needed -+ task.accept(1); -+ return; -+ } -+ -+ int desireDelay = 0; -+ double minDist = Double.MAX_VALUE; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(i); -+ if (elapsed == 0 && initialDistance <= 4) { -+ // Aim for no delay on initial 6 chunk radius tickets save on performance of the below code to only > 6 -+ minDist = initialDistance; -+ } else if (players != null) { -+ Object[] backingSet = players.getBackingSet(); -+ -+ BlockPos blockPos = chunkPos.asPosition(); -+ -+ boolean isFront = false; -+ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); -+ for (int index = 0, len = backingSet.length; index < len; ++index) { -+ if (!(backingSet[index] instanceof ServerPlayer)) { -+ continue; -+ } -+ ServerPlayer player = (ServerPlayer) backingSet[index]; -+ -+ ChunkPos pointInFront = player.getChunkInFront(5); -+ pos.setValues(pointInFront.x << 4, 0, pointInFront.z << 4); -+ double frontDist = MCUtil.distanceSq(pos, blockPos); -+ -+ pos.setValues(player.getX(), 0, player.getZ()); -+ double center = MCUtil.distanceSq(pos, blockPos); -+ -+ double dist = Math.min(frontDist, center); -+ if (!isFront) { -+ ChunkPos pointInBack = player.getChunkInFront(-7); -+ pos.setValues(pointInBack.x << 4, 0, pointInBack.z << 4); -+ double backDist = MCUtil.distanceSq(pos, blockPos); -+ if (frontDist < backDist) { -+ isFront = true; -+ } -+ } -+ if (dist < minDist) { -+ minDist = dist; -+ } -+ } -+ if (minDist == Double.MAX_VALUE) { -+ minDist = 15; -+ } else { -+ minDist = Math.sqrt(minDist) / 16; -+ } -+ if (minDist > 4) { -+ int desiredTimeDelayMax = isFront ? -+ (minDist < 10 ? 7 : 15) : // Front -+ (minDist < 10 ? 15 : 45); // Back -+ desireDelay += (desiredTimeDelayMax * 20) * (minDist / 32); -+ } -+ } else { -+ minDist = initialDistance; -+ desireDelay = 1; -+ } -+ long delay = desireDelay - elapsed; -+ if (delay <= 0 && minDist > 4 && minDist < Double.MAX_VALUE) { -+ boolean hasAnyNeighbor = false; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) continue; -+ long pair = ChunkPos.asLong(chunkPos.x + x, chunkPos.z + z); -+ ChunkHolder neighbor = chunkMap.getUpdatingChunkIfPresent(pair); -+ ChunkStatus current = neighbor != null ? neighbor.getChunkHolderStatus() : null; -+ if (current != null && current.isAtLeastStatus(ChunkStatus.LIGHT)) { -+ hasAnyNeighbor = true; -+ } -+ } -+ } -+ if (!hasAnyNeighbor) { -+ delay += 20; -+ } -+ } -+ if (delay <= 0) { -+ task.accept((int) minDist); -+ } else { -+ int taskDelay = (int) Math.min(delay, minDist >= 10 ? 40 : (minDist < 6 ? 5 : 20)); -+ MCUtil.scheduleTask(taskDelay, () -> scheduleChunkLoad(i, startTick, initialDistance, task), "Player Ticket Delayer"); -+ } -+ } -+ // Paper end -+ - @Override - public void runAllUpdates() { - super.runAllUpdates(); -@@ -447,6 +711,7 @@ public abstract class DistanceManager { - - } - -+ private boolean isLoadedChunkLevel(int i) { return haveTicketFor(i); } // Paper - OBFHELPER - private boolean haveTicketFor(int distance) { - return distance <= this.viewDistance - 2; - } -@@ -463,6 +728,7 @@ public abstract class DistanceManager { - this.chunks.defaultReturnValue((byte) (i + 2)); - } - -+ protected final int getChunkLevel(long i) { return getLevel(i); } // Paper - OBFHELPER - @Override - protected int getLevel(long id) { - return this.chunks.get(id); -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd..f36badcafbad7fb4537ffdf54d9e266ae3d72459 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -467,6 +467,26 @@ public class ServerChunkCache extends ChunkSource { - public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { - this.distanceManager.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); - } -+ -+ public boolean markUrgent(ChunkPos coords) { -+ return this.distanceManager.markUrgent(coords); -+ } -+ -+ public boolean markHighPriority(ChunkPos coords, int priority) { -+ return this.distanceManager.markHighPriority(coords, priority); -+ } -+ -+ public void markAreaHighPriority(ChunkPos center, int priority, int radius) { -+ this.distanceManager.markAreaHighPriority(center, priority, radius); -+ } -+ -+ public void clearAreaPriorityTickets(ChunkPos center, int radius) { -+ this.distanceManager.clearAreaPriorityTickets(center, radius); -+ } -+ -+ public void clearPriorityTickets(ChunkPos coords) { -+ this.distanceManager.clearPriorityTickets(coords); -+ } - // Paper end - - @Nullable -@@ -505,6 +525,8 @@ public class ServerChunkCache extends ChunkSource { - - if (!completablefuture.isDone()) { // Paper - // Paper start - async chunk io/loading -+ ChunkPos pair = new ChunkPos(x1, z1); -+ this.distanceManager.markUrgent(pair); - this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); - // Paper end -@@ -513,6 +535,8 @@ public class ServerChunkCache extends ChunkSource { - this.mainThreadProcessor.managedBlock(completablefuture::isDone); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug - this.level.timings.syncChunkLoad.stopTiming(); // Paper -+ this.distanceManager.clearPriorityTickets(pair); // Paper -+ this.distanceManager.clearUrgent(pair); // Paper - } // Paper - ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { - return ichunkaccess1; -@@ -565,10 +589,12 @@ public class ServerChunkCache extends ChunkSource { - if (flag && !currentlyUnloading) { - // CraftBukkit end - this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); -+ if (isUrgent) this.distanceManager.markUrgent(chunkcoordintpair); // Paper - if (this.chunkAbsent(playerchunk, l)) { - ProfilerFiller gameprofilerfiller = this.level.getProfiler(); - - gameprofilerfiller.push("chunkLoad"); -+ distanceManager.delayDistanceManagerTick = false; // Paper - ensure this is never false - this.runDistanceManagerUpdates(); - playerchunk = this.getVisibleChunkIfPresent(k); - gameprofilerfiller.pop(); -@@ -577,8 +603,13 @@ public class ServerChunkCache extends ChunkSource { - } - } - } -- -- return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkstatus, this.chunkMap); -+ // Paper start -+ CompletableFuture> future = this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkstatus, this.chunkMap); -+ if (isUrgent) { -+ future.thenAccept(either -> this.distanceManager.clearUrgent(chunkcoordintpair)); -+ } -+ return future; -+ // Paper end - } - - private boolean chunkAbsent(@Nullable ChunkHolder holder, int maxLevel) { -@@ -630,6 +661,7 @@ public class ServerChunkCache extends ChunkSource { - } - - public boolean runDistanceManagerUpdates() { // Paper - private -> public -+ if (distanceManager.delayDistanceManagerTick) return false; // Paper - boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); - boolean flag1 = this.chunkMap.promoteChunkMap(); - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 8e4cef60b760be385df81a74834d026f856a78c5..c5717f45a0110492aad41f21cc06fb8cbeb1f791 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -73,6 +73,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; - import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; - import net.minecraft.resources.ResourceKey; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.PlayerAdvancements; - import net.minecraft.server.network.ServerGamePacketListenerImpl; -@@ -185,6 +186,12 @@ public class ServerPlayer extends Player implements ContainerListener { - private int lastRecordedArmor = Integer.MIN_VALUE; - private int lastRecordedLevel = Integer.MIN_VALUE; - private int lastRecordedExperience = Integer.MIN_VALUE; -+ public long lastHighPriorityChecked; // Paper -+ public void forceCheckHighPriority() { -+ lastHighPriorityChecked = -1; -+ getLevel().getChunkSource().chunkMap.checkHighPriorityChunks(this); -+ } -+ public boolean isRealPlayer; // Paper - private float lastSentHealth = -1.0E8F; - private int lastSentFood = -99999999; - private boolean lastFoodSaturationZero = true; -@@ -272,6 +279,21 @@ public class ServerPlayer extends Player implements ContainerListener { - this.maxHealthCache = this.getMaxHealth(); - this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper - } -+ // Paper start -+ public BlockPos getPointInFront(double inFront) { -+ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yRot+90)); // MC rotates yaw 90 for some odd reason -+ final double x = getX() + inFront * Math.cos(rads); -+ final double z = getZ() + inFront * Math.sin(rads); -+ return new BlockPos(x, getY(), z); -+ } -+ -+ public ChunkPos getChunkInFront(double inFront) { -+ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yRot+90)); // MC rotates yaw 90 for some odd reason -+ final double x = getX() + (inFront * 16) * Math.cos(rads); -+ final double z = getZ() + (inFront * 16) * Math.sin(rads); -+ return new ChunkPos(Mth.floor(x) >> 4, Mth.floor(z) >> 4); -+ } -+ // Paper end - - // Yes, this doesn't match Vanilla, but it's the best we can do for now. - // If this is an issue, PRs are welcome -@@ -619,6 +641,7 @@ public class ServerPlayer extends Player implements ContainerListener { - if (valid && !this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) - super.tick(); - } -+ if (valid && isAlive() && connection != null) ((ServerLevel)level).getChunkSource().chunkMap.checkHighPriorityChunks(this); // Paper - - for (int i = 0; i < this.inventory.getContainerSize(); ++i) { - ItemStack itemstack = this.inventory.getItem(i); -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index c6b5f32153b63ac92df9c4b31b8de168481f79f2..c0bfe136ccb9ad4fc0f8ccdd703254205213ec8e 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -8,6 +8,7 @@ public final class Ticket implements Comparable> { - private final int ticketLevel; - public final T key; public final T getObjectReason() { return this.key; } // Paper - OBFHELPER - private long createdTick; public final long getCreationTick() { return this.createdTick; } // Paper - OBFHELPER -+ public int priority = 0; // Paper - - protected Ticket(TicketType type, int level, T argument) { - this.type = type; -@@ -56,6 +57,7 @@ public final class Ticket implements Comparable> { - return this.ticketLevel; - } - -+ public final void setCurrentTick(long i) { this.setCreatedTick(i); } // Paper - OBFHELPER - protected void setCreatedTick(long tickCreated) { - this.createdTick = tickCreated; - } -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 583587457790df826a8a3239a4bd1d0f1dcab1da..2444f6f676db543509b14e8c882491dc3f41b264 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -28,6 +28,8 @@ public class TicketType { - public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit - public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper - public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper -+ public static final TicketType PRIORITY = create("priority", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper -+ public static final TicketType URGENT = create("urgent", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper - - public static TicketType create(String name, Comparator comparator) { - return new TicketType<>(name, comparator, 0L); -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 3f416479e23c60ec5b4b779cce9ab62c74865ac8..0625bc7ffd07b66b27176fe62ae3061aa7c67df2 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1528,6 +1528,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - this.awaitingTeleportTime = this.tickCount; - this.player.absMoveTo(d0, d1, d2, f, f1); -+ this.player.forceCheckHighPriority(); // Paper - this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); - } - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8e00747c1a717836d12a43aa48d667bf801167b0..168895dab31a0d5356eb96f2642399a1c99fccab 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -271,8 +271,8 @@ public abstract class PlayerList { - final ChunkPos pos = new ChunkPos(chunkX, chunkZ); - ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; - playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.toLong()); -- worldserver1.getChunkSource().runDistanceManagerUpdates(); -- worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { -+ worldserver1.getChunkSource().markAreaHighPriority(pos, 28, 3); -+ worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, false).thenApply(chunk -> { - ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); - if (updatingChunk != null) { - return updatingChunk.getEntityTickingFuture(); -@@ -692,6 +692,7 @@ public abstract class PlayerList { - SocketAddress socketaddress = loginlistener.connection.getRemoteAddress(); - - ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameprofile, new ServerPlayerGameMode(this.server.getLevel(Level.OVERWORLD))); -+ entity.isRealPlayer = true; // Paper - Player player = entity.getBukkitEntity(); - PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.connection.getRawAddress()).getAddress()); - -@@ -898,6 +899,7 @@ public abstract class PlayerList { - // CraftBukkit end - - worldserver1.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, new ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper -+ entityplayer1.forceCheckHighPriority(); // Player - while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < 256.0D) { - entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); - } -diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java -index 7ccf830146c252cff8e22553d293e02d4b53dad8..4a5f318adf5bc2ca1c3fab5d173a99cddd77ab85 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkPos.java -+++ b/src/main/java/net/minecraft/world/level/ChunkPos.java -@@ -104,6 +104,7 @@ public class ChunkPos { - return "[" + this.x + ", " + this.z + "]"; - } - -+ public final BlockPos asPosition() { return getWorldPosition(); } // Paper - OBFHELPER - public BlockPos getWorldPosition() { - return new BlockPos(this.getMinBlockX(), 0, this.getMinBlockZ()); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 4fc44390f432ef13c9952aa22bbb29bc8bf47975..7261e22a71d219efe0949a08c5d3f10747759469 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2523,6 +2523,10 @@ public class CraftWorld implements World { - return future; - } - -+ if (!urgent) { -+ // if not urgent, at least use a slightly boosted priority -+ world.getChunkSource().markHighPriority(new ChunkPos(x, z), 1); -+ } - return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { - net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index eb366396820c9b6731469df4198e0884a431a77c..610eabd2e93f9efccee810c3b5a314bc3cc649d8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -60,6 +60,7 @@ import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.network.ServerGamePacketListenerImpl; - import net.minecraft.server.players.UserWhiteListEntry; -+import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.ExperienceOrb; - import net.minecraft.world.entity.LivingEntity; -@@ -69,6 +70,7 @@ import net.minecraft.world.entity.ai.attributes.Attributes; - import net.minecraft.world.inventory.AbstractContainerMenu; - import net.minecraft.world.item.enchantment.EnchantmentHelper; - import net.minecraft.world.item.enchantment.Enchantments; -+import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.GameType; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.entity.SignBlockEntity; -@@ -848,6 +850,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - throw new UnsupportedOperationException("Cannot set rotation of players. Consider teleporting instead."); - } - -+ // Paper start -+ @Override -+ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull PlayerTeleportEvent.TeleportCause cause) { -+ ((CraftWorld)loc.getWorld()).getHandle().getChunkSource().markAreaHighPriority(new ChunkPos(Mth.floor(loc.getX()) >> 4, Mth.floor(loc.getZ()) >> 4), 28, 3); // Paper - load area high priority -+ return super.teleportAsync(loc, cause); -+ } -+ // Paper end -+ - @Override - public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) { - Preconditions.checkArgument(location != null, "location"); diff --git a/Remapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/Remapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch deleted file mode 100644 index e8add9864d..0000000000 --- a/Remapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 23 May 2020 17:03:41 -0400 -Subject: [PATCH] Optimize sending packets to nearby locations (sounds/effects) - -Instead of using the entire world or player list, use the distance -maps to only iterate players who are even seeing the chunk the packet -is originating from. - -This will drastically cut down on packet sending cost for worlds with -lots of players in them. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 168895dab31a0d5356eb96f2642399a1c99fccab..713cc88dd067c0d918f253b1845f42c0d9eb920f 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1149,16 +1149,40 @@ public abstract class PlayerList { - } - - public void broadcast(@Nullable net.minecraft.world.entity.player.Player player, double x, double y, double z, double distance, ResourceKey worldKey, Packet packet) { -- for (int i = 0; i < this.players.size(); ++i) { -- ServerPlayer entityplayer = (ServerPlayer) this.players.get(i); -+ ServerLevel world = null; -+ if (player != null && player.level instanceof ServerLevel) { -+ world = (ServerLevel) player.level; -+ } - -- // CraftBukkit start - Test if player receiving packet can see the source of the packet -- if (player != null && player instanceof ServerPlayer && !entityplayer.getBukkitEntity().canSee(((ServerPlayer) player).getBukkitEntity())) { -- continue; -+ // Paper start -+ if (world == null) { -+ world = server.getLevel(worldKey); -+ } -+ ChunkMap chunkMap = world != null ? world.getChunkSource().chunkMap : null; -+ Object[] backingSet; -+ if (chunkMap == null) { -+ // Really shouldn't happen... -+ backingSet = world != null ? world.players.toArray() : players.toArray(); -+ } else { -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.fastFloor(x) >> 4, MCUtil.fastFloor(z) >> 4); -+ if (nearbyPlayers == null) { -+ return; - } -+ backingSet = nearbyPlayers.getBackingSet(); -+ } -+ -+ for (Object object : backingSet) { -+ if (!(object instanceof ServerPlayer)) continue; -+ ServerPlayer entityplayer = (ServerPlayer) object; -+ // Paper end -+ -+ // CraftBukkit start - Test if player receiving packet can see the source of the packet -+ //if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { // Paper -+ //continue; // Paper -+ //} // Paper - // CraftBukkit end - -- if (entityplayer != player && entityplayer.level.dimension() == worldKey) { -+ if (entityplayer != player && entityplayer.level.dimension() == worldKey && (!(player instanceof ServerPlayer) || entityplayer.getBukkitEntity().canSee(((ServerPlayer) player).getBukkitEntity()))) { // Paper - double d4 = x - entityplayer.getX(); - double d5 = y - entityplayer.getY(); - double d6 = z - entityplayer.getZ(); diff --git a/Remapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch b/Remapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch deleted file mode 100644 index 38e09f9701..0000000000 --- a/Remapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 May 2020 23:32:14 -0400 -Subject: [PATCH] Improve Chunk Status Transition Speed - -When a chunk is loaded from disk that has already been generated, -the server has to promote the chunk through the system to reach -it's current desired status level. - -This results in every single status transition going from the main thread -to the world gen threads, only to discover it has no work it actually -needs to do.... and then it returns back to main. - -This back and forth costs a lot of time and can really delay chunk loads -when the server is under high TPS due to their being a lot of time in -between chunk load times, as well as hogs up the chunk threads from doing -actual generation and light work. - -Additionally, the whole task system uses a lot of CPU on the server threads anyways. - -So by optimizing status transitions for status's that are already complete, -we can run them to the desired level while on main thread (where it has -to happen anyways) instead of ever jumping to world gen thread. - -This will improve chunk loading effeciency to be reduced down to the following -scenario / path: - -1) MAIN: Chunk Requested, Load Request sent to ChunkTaskManager / IO Queue -2) IO: Once position in queue comes, submit read IO data and schedule to chunk task thread -3) CHUNK: Once IO is loaded and position in queue comes, deserialize the chunk data, process conversions, submit to main queue -4) MAIN: next Chunk Task process (Mid Tick or End Of Tick), load chunk data into world (POI, main thread tasks) -5) MAIN: process status transitions all the way to LIGHT, light schedules Threaded task -6) SERVER: Light tasks register light enablement for chunk and any lighting needing to be done -7) MAIN: Task returns to main, finish processing to FULL/TICKING status - -Previously would have hopped to SERVER around 12+ times there extra. - -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index ce320672d7602c94dd75ad857435dca6ac3bab56..8260636da673ef095728c208db2d6237bab2db19 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -83,6 +83,13 @@ public class ChunkHolder { - this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); - } - // Paper end - optimise isOutsideOfRange -+ // Paper start - optimize chunk status progression without jumping through thread pool -+ public boolean canAdvanceStatus() { -+ ChunkStatus status = getChunkHolderStatus(); -+ ChunkAccess chunk = getAvailableChunkNow(); -+ return chunk != null && (status == null || chunk.getStatus().isAtLeastStatus(getNextStatus(status))); -+ } -+ // Paper end - - // Paper start - no-tick view distance - public final LevelChunk getSendingChunk() { -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 7a1f6d1807757a43a7aa471db651404c06720820..acc566d14926dcf9e88f3e0837884e4c823d777c 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -792,7 +792,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return either.mapLeft((list) -> { - return (LevelChunk) list.get(list.size() / 2); - }); -- }, this.mainThreadExecutor); -+ }, this.mainInvokingExecutor); // Paper - } - - @Nullable -@@ -1142,7 +1142,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - ChunkAccess ichunkaccess = (ChunkAccess) optional.get(); - - if (ichunkaccess.getStatus().isOrAfter(requiredStatus)) { -- CompletableFuture completablefuture1; -+ CompletableFuture> completablefuture1; // Paper - - if (requiredStatus == ChunkStatus.LIGHT) { - completablefuture1 = this.scheduleChunkGeneration(holder, requiredStatus); -@@ -1158,7 +1158,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return this.scheduleChunkGeneration(holder, requiredStatus); - } - } -- }, this.mainThreadExecutor); -+ }, this.mainInvokingExecutor).thenComposeAsync(CompletableFuture::completedFuture, this.mainInvokingExecutor); // Paper - optimize chunk status progression without jumping through thread pool - ensure main - } - } - -@@ -1279,6 +1279,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return CompletableFuture.completedFuture(Either.right(playerchunk_failure)); - }); - }, (runnable) -> { -+ // Paper start - optimize chunk status progression without jumping through thread pool -+ if (holder.canAdvanceStatus()) { -+ this.mainInvokingExecutor.execute(runnable); -+ return; -+ } -+ // Paper end - this.worldgenMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); - }); - } diff --git a/Remapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch b/Remapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch deleted file mode 100644 index 65b79cf458..0000000000 --- a/Remapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Fri, 5 Jun 2020 20:02:04 -0500 -Subject: [PATCH] Fix villager trading demand - MC-163962 - -Prevent demand from going negative and tending to negative infinity - -diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java -index 9ce1c1092970618a204f87c673144152afbade99..fa74813e0fe76612023830b2fc41d41aa0b4f10e 100644 ---- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java -+++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java -@@ -109,7 +109,7 @@ public class MerchantOffer { - } - - public void updateDemand() { -- this.demand = this.demand + this.uses - (this.maxUses - this.uses); -+ this.demand = Math.max(0, this.demand + this.uses - (this.maxUses - this.uses)); // Paper - } - - public ItemStack assemble() { diff --git a/Remapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch b/Remapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch deleted file mode 100644 index 186fc75fa9..0000000000 --- a/Remapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sun, 7 Jun 2020 21:43:42 +0100 -Subject: [PATCH] Maps shouldn't load chunks - -Previously maps would load all chunks in a certain radius depending on - their scale when trying to update their content. This would result in - main thread chunk loads when they weren't really necessary, especially - on low view distances or "slow" async chunk loads after teleports or - other prioritisation. - - This changes it to only try to render already loaded chunks based on - the assumption that the chunks around the player will get loaded - eventually anyways and that maps will get checked for update every - five ticks that movement occur in anyways. - -diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java -index 1736d2eb33e5f2221210a0a4f3ceb8905555a162..05759dc6edaa790a5e3f2ca2e0ae27e53cfa4397 100644 ---- a/src/main/java/net/minecraft/world/item/MapItem.java -+++ b/src/main/java/net/minecraft/world/item/MapItem.java -@@ -119,9 +119,9 @@ public class MapItem extends ComplexItem { - int k2 = (j / i + k1 - 64) * i; - int l2 = (k / i + l1 - 64) * i; - Multiset multiset = LinkedHashMultiset.create(); -- LevelChunk chunk = world.getChunkAt(new BlockPos(k2, 0, l2)); -+ LevelChunk chunk = world.getChunkIfLoaded(new BlockPos(k2, 0, l2)); // Paper - Maps shouldn't load chunks - -- if (!chunk.isEmpty()) { -+ if (chunk != null && !chunk.isEmpty()) { // Paper - Maps shouldn't load chunks - ChunkPos chunkcoordintpair = chunk.getPos(); - int i3 = k2 & 15; - int j3 = l2 & 15; diff --git a/Remapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/Remapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch deleted file mode 100644 index 356dcc464b..0000000000 --- a/Remapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 7 Jun 2020 19:25:13 -0400 -Subject: [PATCH] Use seed based lookup for Treasure Maps - Fixes lag from - carto/sunken maps - - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index bf4e50cd1d561456c033cda2d5c5487c5e3fe1eb..61aee2c109614a014149ae5a15ad2a28c796cb9d 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -415,8 +415,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.worldDataServer.setThundering(thundering); - } - -- @Override -- public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { -+ public Biome getBiomeBySeed(int i, int j, int k) { return getUncachedNoiseBiome(i, j, k); } // Paper - OBFHELPER -+ @Override public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { - return this.getChunkSource().getGenerator().getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ); - } - -diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java -index 05759dc6edaa790a5e3f2ca2e0ae27e53cfa4397..550892bc769a58991583b16295a72a162ceea788 100644 ---- a/src/main/java/net/minecraft/world/item/MapItem.java -+++ b/src/main/java/net/minecraft/world/item/MapItem.java -@@ -252,7 +252,7 @@ public class MapItem extends ComplexItem { - - for (l = 0; l < 128 * i; ++l) { - for (i1 = 0; i1 < 128 * i; ++i1) { -- abiomebase[l * 128 * i + i1] = worldserver.getBiome(new BlockPos((j / i - 64) * i + i1, 0, (k / i - 64) * i + l)); -+ abiomebase[l * 128 * i + i1] = worldserver.getBiomeBySeed((j / i - 64) * i + i1, 0, (k / i - 64) * i + l); // Paper - } - } - diff --git a/Remapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch b/Remapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch deleted file mode 100644 index f1615b3c0b..0000000000 --- a/Remapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 4 Jun 2020 02:24:49 -0400 -Subject: [PATCH] Optimize Bit Operations by inlining - -Inline bit operations and reduce instruction count to make these hot -operations faster - -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 595abf528a7862478100770987906af1b13439fe..727af6ac84075db87615ebac51a024e6376fa3cb 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -31,14 +31,16 @@ public class BlockPos extends Vec3i { - }).stable(); - private static final Logger LOGGER = LogManager.getLogger(); - public static final BlockPos ZERO = new BlockPos(0, 0, 0); -- private static final int PACKED_X_LENGTH = 1 + Mth.log2(Mth.smallestEncompassingPowerOfTwo(30000000)); -- private static final int PACKED_Z_LENGTH = BlockPos.PACKED_X_LENGTH; -- private static final int PACKED_Y_LENGTH = 64 - BlockPos.PACKED_X_LENGTH - BlockPos.PACKED_Z_LENGTH; -- private static final long PACKED_X_MASK = (1L << BlockPos.PACKED_X_LENGTH) - 1L; -- private static final long PACKED_Y_MASK = (1L << BlockPos.PACKED_Y_LENGTH) - 1L; -- private static final long PACKED_Z_MASK = (1L << BlockPos.PACKED_Z_LENGTH) - 1L; -- private static final int Z_OFFSET = BlockPos.PACKED_Y_LENGTH; -- private static final int X_OFFSET = BlockPos.PACKED_Y_LENGTH + BlockPos.PACKED_Z_LENGTH; -+ // Paper start - static constants -+ private static final int PACKED_X_LENGTH = 26; -+ private static final int PACKED_Z_LENGTH = 26; -+ private static final int PACKED_Y_LENGTH = 12; -+ private static final long PACKED_X_MASK = 67108863; -+ private static final long PACKED_Y_MASK = 4095; -+ private static final long PACKED_Z_MASK = 67108863; -+ private static final int Z_OFFSET = 12; -+ private static final int X_OFFSET = 38; -+ // Paper end - - public BlockPos(int x, int y, int z) { - super(x, y, z); -@@ -60,28 +62,29 @@ public class BlockPos extends Vec3i { - this(pos.getX(), pos.getY(), pos.getZ()); - } - -+ public static long getAdjacent(int baseX, int baseY, int baseZ, Direction enumdirection) { return asLong(baseX + enumdirection.getStepX(), baseY + enumdirection.getStepY(), baseZ + enumdirection.getStepZ()); } // Paper - public static long offset(long value, Direction direction) { - return offset(value, direction.getStepX(), direction.getStepY(), direction.getStepZ()); - } - - public static long offset(long value, int x, int y, int z) { -- return asLong(getX(value) + x, getY(value) + y, getZ(value) + z); -+ return asLong((int) (value >> 38) + x, (int) ((value << 52) >> 52) + y, (int) ((value << 26) >> 38) + z); // Paper - simplify/inline - } - - public static int getX(long packedPos) { -- return (int) (packedPos << 64 - BlockPos.X_OFFSET - BlockPos.PACKED_X_LENGTH >> 64 - BlockPos.PACKED_X_LENGTH); -+ return (int) (packedPos >> 38); // Paper - simplify/inline - } - - public static int getY(long packedPos) { -- return (int) (packedPos << 64 - BlockPos.PACKED_Y_LENGTH >> 64 - BlockPos.PACKED_Y_LENGTH); -+ return (int) ((packedPos << 52) >> 52); // Paper - simplify/inline - } - - public static int getZ(long packedPos) { -- return (int) (packedPos << 64 - BlockPos.Z_OFFSET - BlockPos.PACKED_Z_LENGTH >> 64 - BlockPos.PACKED_Z_LENGTH); -+ return (int) ((packedPos << 26) >> 38); // Paper - simplify/inline - } - - public static BlockPos of(long packedPos) { -- return new BlockPos(getX(packedPos), getY(packedPos), getZ(packedPos)); -+ return new BlockPos((int) (packedPos >> 38), (int) ((packedPos << 52) >> 52), (int) ((packedPos << 26) >> 38)); // Paper - simplify/inline - } - - public long asLong() { -@@ -90,12 +93,7 @@ public class BlockPos extends Vec3i { - - public static long asLong(int x, int y, int z) { return asLong(x, y, z); } // Paper - OBFHELPER - public static long asLong(int x, int y, int z) { -- long l = 0L; -- -- l |= ((long) x & BlockPos.PACKED_X_MASK) << BlockPos.X_OFFSET; -- l |= ((long) y & BlockPos.PACKED_Y_MASK) << 0; -- l |= ((long) z & BlockPos.PACKED_Z_MASK) << BlockPos.Z_OFFSET; -- return l; -+ return (((long) x & (long) 67108863) << 38) | (((long) y & (long) 4095)) | (((long) z & (long) 67108863) << 12); // Paper - inline constants and simplify - } - - public static long getFlatIndex(long y) { -diff --git a/src/main/java/net/minecraft/core/SectionPos.java b/src/main/java/net/minecraft/core/SectionPos.java -index 700e0d7b132242bd65d13ec61c1f7036905b2767..c4bf1bc383fbdfb8ec997883aececde38206c7dd 100644 ---- a/src/main/java/net/minecraft/core/SectionPos.java -+++ b/src/main/java/net/minecraft/core/SectionPos.java -@@ -19,7 +19,7 @@ public class SectionPos extends Vec3i { - } - - public static SectionPos of(BlockPos pos) { -- return new SectionPos(blockToSectionCoord(pos.getX()), blockToSectionCoord(pos.getY()), blockToSectionCoord(pos.getZ())); -+ return new SectionPos(pos.getX() >> 4, pos.getY() >> 4, pos.getZ() >> 4); // Paper - } - - public static SectionPos of(ChunkPos chunkPos, int y) { -@@ -31,15 +31,23 @@ public class SectionPos extends Vec3i { - } - - public static SectionPos of(long packed) { -- return new SectionPos(x(packed), y(packed), z(packed)); -+ return new SectionPos((int) (packed >> 42), (int) (packed << 44 >> 44), (int) (packed << 22 >> 42)); // Paper - } - - public static long offset(long packed, Direction direction) { - return offset(packed, direction.getStepX(), direction.getStepY(), direction.getStepZ()); - } - -+ // Paper start -+ public static long getAdjacentFromBlockPos(int x, int y, int z, Direction enumdirection) { -+ return (((long) ((x >> 4) + enumdirection.getStepX()) & 4194303L) << 42) | (((long) ((y >> 4) + enumdirection.getStepY()) & 1048575L)) | (((long) ((z >> 4) + enumdirection.getStepZ()) & 4194303L) << 20); -+ } -+ public static long getAdjacentFromSectionPos(int x, int y, int z, Direction enumdirection) { -+ return (((long) (x + enumdirection.getStepX()) & 4194303L) << 42) | (((long) ((y) + enumdirection.getStepY()) & 1048575L)) | (((long) (z + enumdirection.getStepZ()) & 4194303L) << 20); -+ } -+ // Paper end - public static long offset(long packed, int x, int y, int z) { -- return asLong(x(packed) + x, y(packed) + y, z(packed) + z); -+ return (((long) ((int) (packed >> 42) + x) & 4194303L) << 42) | (((long) ((int) (packed << 44 >> 44) + y) & 1048575L)) | (((long) ((int) (packed << 22 >> 42) + z) & 4194303L) << 20); // Simplify to reduce instruction count - } - - public static int blockToSectionCoord(int coord) { -@@ -51,11 +59,7 @@ public class SectionPos extends Vec3i { - } - - public static short sectionRelativePos(BlockPos pos) { -- int i = sectionRelative(pos.getX()); -- int j = sectionRelative(pos.getY()); -- int k = sectionRelative(pos.getZ()); -- -- return (short) (i << 8 | k << 4 | j << 0); -+ return (short) ((pos.getX() & 15) << 8 | (pos.getZ() & 15) << 4 | pos.getY() & 15); // Paper - simplify/inline - } - - public static int sectionRelativeX(short packedLocalPos) { -@@ -114,16 +118,16 @@ public class SectionPos extends Vec3i { - return this.getZ(); - } - -- public int minBlockX() { -- return this.x() << 4; -+ public final int minBlockX() { // Paper -+ return this.getX() << 4; // Paper - } - -- public int minBlockY() { -- return this.y() << 4; -+ public final int minBlockY() { // Paper -+ return this.getY() << 4; // Paper - } - -- public int minBlockZ() { -- return this.z() << 4; -+ public final int minBlockZ() { // Paper -+ return this.getZ() << 4; // Paper - } - - public int maxBlockX() { -@@ -138,8 +142,10 @@ public class SectionPos extends Vec3i { - return (this.z() << 4) + 15; - } - -+ public static long blockToSection(long i) { return blockToSection(i); } // Paper - OBFHELPER - public static long blockToSection(long blockPos) { -- return asLong(blockToSectionCoord(BlockPos.getX(blockPos)), blockToSectionCoord(BlockPos.getY(blockPos)), blockToSectionCoord(BlockPos.getZ(blockPos))); -+ // b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); -+ return (((long) (int) (blockPos >> 42) & 4194303L) << 42) | (((long) (int) ((blockPos << 52) >> 56) & 1048575L)) | (((long) (int) ((blockPos << 26) >> 42) & 4194303L) << 20); // Simplify to reduce instruction count - } - - public static long getZeroNode(long pos) { -@@ -160,17 +166,18 @@ public class SectionPos extends Vec3i { - return new ChunkPos(this.x(), this.z()); - } - -+ // Paper start -+ public static long blockPosAsSectionLong(int i, int j, int k) { -+ return (((long) (i >> 4) & 4194303L) << 42) | (((long) (j >> 4) & 1048575L)) | (((long) (k >> 4) & 4194303L) << 20); -+ } -+ // Paper end -+ public static long asLong(int i, int j, int k) { return asLong(i, j, k); } // Paper - OBFHELPER - public static long asLong(int x, int y, int z) { -- long l = 0L; -- -- l |= ((long) x & 4194303L) << 42; -- l |= ((long) y & 1048575L) << 0; -- l |= ((long) z & 4194303L) << 20; -- return l; -+ return (((long) x & 4194303L) << 42) | (((long) y & 1048575L)) | (((long) z & 4194303L) << 20); // Paper - Simplify to reduce instruction count - } - - public long asLong() { -- return asLong(this.x(), this.y(), this.z()); -+ return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count - } - - public Stream blocksInside() { -@@ -178,18 +185,11 @@ public class SectionPos extends Vec3i { - } - - public static Stream cube(SectionPos center, int radius) { -- int j = center.x(); -- int k = center.y(); -- int l = center.z(); -- -- return betweenClosedStream(j - radius, k - radius, l - radius, j + radius, k + radius, l + radius); -+ return betweenClosedStream(center.getX() - radius, center.getY() - radius, center.getZ() - radius, center.getX() + radius, center.getY() + radius, center.getZ() + radius); // Paper - simplify/inline - } - - public static Stream aroundChunk(ChunkPos center, int radius) { -- int j = center.x; -- int k = center.z; -- -- return betweenClosedStream(j - radius, 0, k - radius, j + radius, 15, k + radius); -+ return betweenClosedStream(center.x - radius, 0, center.z - radius, center.x + radius, 15, center.z + radius); // Paper - simplify/inline - } - - public static Stream betweenClosedStream(final int minX, final int minY, final int minZ, final int maxX, final int maxY, final int maxZ) { diff --git a/Remapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch b/Remapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch deleted file mode 100644 index 53f26fe554..0000000000 --- a/Remapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch +++ /dev/null @@ -1,1464 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 4 Jun 2020 22:43:29 -0400 -Subject: [PATCH] Optimize Light Engine - -Massive update to light to improve performance and chunk loading/generation. - -1) Massive bit packing/unpacking optimizations and inlining. - A lot of performance has to do with constant packing and unpacking of bits. - We now inline a most bit operations, and re-use base x/y/z bits in many places. - This helps with cpu level processing to just do all the math at once instead - of having to jump in and out of function calls. - - This much logic also is likely over the JVM Inline limit for JIT too. -2) Applied a few of JellySquid's Phosphor mod optimizations such as - - ensuring we don't notify neighbor chunks when neighbor chunk doesn't need to be notified - - reduce hasLight checks in initializing light, and prob some more, they are tagged JellySquid where phosphor influence was used. -3) Optimize hot path accesses to getting updating chunk to have less branching -4) Optimize getBlock accesses to have less branching, and less unpacking -5) Have a separate urgent bucket for chunk light tasks. These tasks will always cut in line over non blocking light tasks. -6) Retain chunk priority while light tasks are enqueued. So if a task comes in at high priority but the queue is full - of tasks already at a lower priority, before the task was simply added to the end. Now it can cut in line to the front. - this applies for both urgent and non urgent tasks. -7) Buffer non urgent tasks even if queueUpdate is called multiple times to improve efficiency. -8) Fix NPE risk that crashes server in getting nibble data - -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 8260636da673ef095728c208db2d6237bab2db19..9e3629884709126574a52ad44fe7523f01dbcce9 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -753,6 +753,7 @@ public class ChunkHolder { - ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; - } - chunkMap.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, ioPriority); -+ chunkMap.level.getChunkSource().getLightEngine().queue.changePriority(pos.toLong(), getCurrentPriority(), priority); - } - if (getCurrentPriority() != priority) { - this.onLevelChange.onLevelChange(this.pos, this::getCurrentPriority, priority, this::setPriority); // use preferred priority -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index acc566d14926dcf9e88f3e0837884e4c823d777c..f4dd30c8b3326db72d3b3068ee2291de6f15de7c 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -98,6 +98,7 @@ import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; - import net.minecraft.world.level.storage.DimensionDataStorage; - import net.minecraft.world.level.storage.LevelStorageSource; -+import net.minecraft.world.level.storage.PrimaryLevelData; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper - import org.apache.commons.lang3.mutable.MutableBoolean; - import org.apache.logging.log4j.LogManager; -@@ -328,6 +329,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - // Paper end - -+ private final java.util.concurrent.ExecutorService lightThread; - public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag); - //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning -@@ -359,7 +361,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - ProcessorHandle mailbox = ProcessorHandle.of("main", mainThreadExecutor::tell); - - this.progressListener = worldGenerationProgressListener; -- ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(workerExecutor, "light"); // Paper -+ // Paper start - use light thread -+ ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(lightThread = java.util.concurrent.Executors.newSingleThreadExecutor(r -> { -+ Thread thread = new Thread(r); -+ thread.setName(((PrimaryLevelData)level.getLevelData()).getLevelName() + " - Light"); -+ thread.setDaemon(true); -+ thread.setPriority(Thread.NORM_PRIORITY+1); -+ return thread; -+ }), "light"); -+ // Paper end - - this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), workerExecutor, Integer.MAX_VALUE); - this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); -@@ -705,6 +715,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper end - } - -+ protected final IntSupplier getPrioritySupplier(long i) { return getChunkQueueLevel(i); } // Paper - OBFHELPER - protected IntSupplier getChunkQueueLevel(long pos) { - return () -> { - ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos); -@@ -832,6 +843,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - @Override - public void close() throws IOException { - try { -+ this.lightThread.shutdown(); // Paper - this.queueSorter.close(); - this.level.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line - this.poiManager.close(); -diff --git a/src/main/java/net/minecraft/server/level/SectionTracker.java b/src/main/java/net/minecraft/server/level/SectionTracker.java -index 125ae965bb539ae24c60cb992eb7cfc35fd65b25..9fa6c290373b0e0cc0e7ed84c0c2363c8ad14dd3 100644 ---- a/src/main/java/net/minecraft/server/level/SectionTracker.java -+++ b/src/main/java/net/minecraft/server/level/SectionTracker.java -@@ -1,6 +1,5 @@ - package net.minecraft.server.level; - --import net.minecraft.core.SectionPos; - import net.minecraft.world.level.lighting.DynamicGraphMinFixedPoint; - - public abstract class SectionTracker extends DynamicGraphMinFixedPoint { -@@ -16,14 +15,20 @@ public abstract class SectionTracker extends DynamicGraphMinFixedPoint { - - @Override - protected void checkNeighborsAfterUpdate(long id, int level, boolean decrease) { -+ // Paper start -+ int x = (int) (id >> 42); -+ int y = (int) (id << 44 >> 44); -+ int z = (int) (id << 22 >> 42); -+ // Paper end - for (int k = -1; k <= 1; ++k) { - for (int l = -1; l <= 1; ++l) { - for (int i1 = -1; i1 <= 1; ++i1) { -- long j1 = SectionPos.offset(id, k, l, i1); -+ if (k == 0 && l == 0 && i1 == 0) continue; // Paper -+ long j1 = (((long) (x + k) & 4194303L) << 42) | (((long) (y + l) & 1048575L)) | (((long) (z + i1) & 4194303L) << 20); // Paper - -- if (j1 != id) { -+ //if (j1 != i) { // Paper - checked above - this.checkNeighbor(id, j1, level, decrease); -- } -+ //} // Paper - } - } - } -@@ -34,10 +39,15 @@ public abstract class SectionTracker extends DynamicGraphMinFixedPoint { - protected int getComputedLevel(long id, long excludedId, int maxLevel) { - int l = maxLevel; - -+ // Paper start -+ int x = (int) (id >> 42); -+ int y = (int) (id << 44 >> 44); -+ int z = (int) (id << 22 >> 42); -+ // Paper end - for (int i1 = -1; i1 <= 1; ++i1) { - for (int j1 = -1; j1 <= 1; ++j1) { - for (int k1 = -1; k1 <= 1; ++k1) { -- long l1 = SectionPos.offset(id, i1, j1, k1); -+ long l1 = (((long) (x + i1) & 4194303L) << 42) | (((long) (y + j1) & 1048575L)) | (((long) (z + k1) & 4194303L) << 20); // Paper - - if (l1 == id) { - l1 = Long.MAX_VALUE; -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index f36badcafbad7fb4537ffdf54d9e266ae3d72459..7a615a18f1f297adfe7e046407a019d8933e9ed9 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -1072,7 +1072,7 @@ public class ServerChunkCache extends ChunkSource { - if (ServerChunkCache.this.runDistanceManagerUpdates()) { - return true; - } else { -- ServerChunkCache.this.lightEngine.tryScheduleUpdate(); -+ ServerChunkCache.this.lightEngine.tryScheduleUpdate(); // Paper - not needed - return super.pollTask() || execChunkTask; // Paper - } - } finally { -diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java -index cc4190b3a8904d1eaae0f542a3b3090583f5ff82..14835bfab300d305faee2db705d7386dc16427f5 100644 ---- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java -+++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java -@@ -1,6 +1,7 @@ - package net.minecraft.server.level; - - import com.mojang.datafixers.util.Pair; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; // Paper - import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import it.unimi.dsi.fastutil.objects.ObjectList; - import it.unimi.dsi.fastutil.objects.ObjectListIterator; -@@ -16,6 +17,7 @@ import net.minecraft.util.thread.ProcessorMailbox; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.LightLayer; - import net.minecraft.world.level.chunk.ChunkAccess; -+import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.DataLayer; - import net.minecraft.world.level.chunk.LevelChunkSection; - import net.minecraft.world.level.chunk.LightChunkGetter; -@@ -27,15 +29,149 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl - - private static final Logger LOGGER = LogManager.getLogger(); - private final ProcessorMailbox taskMailbox; -- private final ObjectList> lightTasks = new ObjectArrayList(); -- private final ChunkMap chunkMap; -+ // Paper start -+ private static final int MAX_PRIORITIES = ChunkMap.MAX_CHUNK_DISTANCE + 2; -+ -+ private boolean isChunkLightStatus(long pair) { -+ ChunkHolder playerChunk = playerChunkMap.getVisibleChunkIfPresent(pair); -+ if (playerChunk == null) { -+ return false; -+ } -+ ChunkStatus status = ChunkHolder.getStatus(playerChunk.getTicketLevel()); -+ return status != null && status.isAtLeastStatus(ChunkStatus.LIGHT); -+ } -+ -+ static class ChunkLightQueue { -+ public boolean shouldFastUpdate; -+ java.util.ArrayDeque pre = new java.util.ArrayDeque(); -+ java.util.ArrayDeque post = new java.util.ArrayDeque(); -+ -+ ChunkLightQueue(long chunk) {} -+ } -+ -+ static class PendingLightTask { -+ long chunkId; -+ IntSupplier priority; -+ Runnable pre; -+ Runnable post; -+ boolean fastUpdate; -+ -+ public PendingLightTask(long chunkId, IntSupplier priority, Runnable pre, Runnable post, boolean fastUpdate) { -+ this.chunkId = chunkId; -+ this.priority = priority; -+ this.pre = pre; -+ this.post = post; -+ this.fastUpdate = fastUpdate; -+ } -+ } -+ -+ -+ // Retain the chunks priority level for queued light tasks -+ class LightQueue { -+ private int size = 0; -+ private final Long2ObjectLinkedOpenHashMap[] buckets = new Long2ObjectLinkedOpenHashMap[MAX_PRIORITIES]; -+ private final java.util.concurrent.ConcurrentLinkedQueue pendingTasks = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private final java.util.concurrent.ConcurrentLinkedQueue priorityChanges = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ -+ private LightQueue() { -+ for (int i = 0; i < buckets.length; i++) { -+ buckets[i] = new Long2ObjectLinkedOpenHashMap<>(); -+ } -+ } -+ -+ public void changePriority(long pair, int currentPriority, int priority) { -+ this.priorityChanges.add(() -> { -+ ChunkLightQueue remove = this.buckets[currentPriority].remove(pair); -+ if (remove != null) { -+ ChunkLightQueue existing = this.buckets[Math.max(1, priority)].put(pair, remove); -+ if (existing != null) { -+ remove.pre.addAll(existing.pre); -+ remove.post.addAll(existing.post); -+ } -+ } -+ }); -+ } -+ -+ public final void addChunk(long chunkId, IntSupplier priority, Runnable pre, Runnable post) { -+ pendingTasks.add(new PendingLightTask(chunkId, priority, pre, post, true)); -+ tryScheduleUpdate(); -+ } -+ -+ public final void add(long chunkId, IntSupplier priority, ThreadedLevelLightEngine.TaskType type, Runnable run) { -+ pendingTasks.add(new PendingLightTask(chunkId, priority, type == TaskType.PRE_UPDATE ? run : null, type == TaskType.POST_UPDATE ? run : null, false)); -+ } -+ public final void add(PendingLightTask update) { -+ int priority = update.priority.getAsInt(); -+ ChunkLightQueue lightQueue = this.buckets[priority].computeIfAbsent(update.chunkId, ChunkLightQueue::new); -+ -+ if (update.pre != null) { -+ this.size++; -+ lightQueue.pre.add(update.pre); -+ } -+ if (update.post != null) { -+ this.size++; -+ lightQueue.post.add(update.post); -+ } -+ if (update.fastUpdate) { -+ lightQueue.shouldFastUpdate = true; -+ } -+ } -+ -+ public final boolean isEmpty() { -+ return this.size == 0 && this.pendingTasks.isEmpty(); -+ } -+ -+ public final int size() { -+ return this.size; -+ } -+ -+ public boolean poll(java.util.List pre, java.util.List post) { -+ PendingLightTask pending; -+ while ((pending = pendingTasks.poll()) != null) { -+ add(pending); -+ } -+ Runnable run; -+ while ((run = priorityChanges.poll()) != null) { -+ run.run(); -+ } -+ boolean hasWork = false; -+ Long2ObjectLinkedOpenHashMap[] buckets = this.buckets; -+ int priority = 0; -+ while (priority < MAX_PRIORITIES && !isEmpty()) { -+ Long2ObjectLinkedOpenHashMap bucket = buckets[priority]; -+ if (bucket.isEmpty()) { -+ priority++; -+ if (hasWork) { -+ return true; -+ } else { -+ continue; -+ } -+ } -+ ChunkLightQueue queue = bucket.removeFirst(); -+ this.size -= queue.pre.size() + queue.post.size(); -+ pre.addAll(queue.pre); -+ post.addAll(queue.post); -+ queue.pre.clear(); -+ queue.post.clear(); -+ hasWork = true; -+ if (queue.shouldFastUpdate) { -+ return true; -+ } -+ } -+ return hasWork; -+ } -+ } -+ -+ final LightQueue queue = new LightQueue(); -+ // Paper end -+ private final ChunkMap chunkMap; private final ChunkMap playerChunkMap; // Paper - private final ProcessorHandle> sorterMailbox; - private volatile int taskPerBatch = 5; - private final AtomicBoolean scheduled = new AtomicBoolean(); - - public ThreadedLevelLightEngine(LightChunkGetter chunkProvider, ChunkMap chunkStorage, boolean hasBlockLight, ProcessorMailbox processor, ProcessorHandle> executor) { - super(chunkProvider, true, hasBlockLight); -- this.chunkMap = chunkStorage; -+ this.chunkMap = chunkStorage; this.playerChunkMap = chunkMap; // Paper - this.sorterMailbox = executor; - this.taskMailbox = processor; - } -@@ -122,13 +258,9 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl - } - - private void addTask(int x, int z, IntSupplier completedLevelSupplier, ThreadedLevelLightEngine.TaskType stage, Runnable task) { -- this.sorterMailbox.tell(ChunkTaskPriorityQueueSorter.message(() -> { -- this.lightTasks.add(Pair.of(stage, task)); -- if (this.lightTasks.size() >= this.taskPerBatch) { -- this.runUpdate(); -- } -- -- }, ChunkPos.asLong(x, z), completedLevelSupplier)); -+ // Paper start - replace method -+ this.queue.add(ChunkPos.asLong(x, z), completedLevelSupplier, stage, task); -+ // Paper end - } - - @Override -@@ -145,8 +277,19 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl - public CompletableFuture lightChunk(ChunkAccess chunk, boolean excludeBlocks) { - ChunkPos chunkcoordintpair = chunk.getPos(); - -- chunk.setLightCorrect(false); -- this.addTask(chunkcoordintpair.x, chunkcoordintpair.z, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> { -+ // Paper start -+ //ichunkaccess.b(false); // Don't need to disable this -+ long pair = chunkcoordintpair.toLong(); -+ CompletableFuture future = new CompletableFuture<>(); -+ IntSupplier prioritySupplier = playerChunkMap.getPrioritySupplier(pair); -+ boolean[] skippedPre = {false}; -+ this.queue.addChunk(pair, prioritySupplier, Util.name(() -> { -+ if (!isChunkLightStatus(pair)) { -+ future.complete(chunk); -+ skippedPre[0] = true; -+ return; -+ } -+ // Paper end - LevelChunkSection[] achunksection = chunk.getSections(); - - for (int i = 0; i < 16; ++i) { -@@ -164,55 +307,48 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl - }); - } - -- this.chunkMap.releaseLightTicket(chunkcoordintpair); -+ // this.d.c(chunkcoordintpair); // Paper - move into post task below - }, () -> { - return "lightChunk " + chunkcoordintpair + " " + excludeBlocks; -- })); -- return CompletableFuture.supplyAsync(() -> { -+ // Paper start - merge the 2 together -+ }), () -> { -+ this.chunkMap.releaseLightTicket(chunkcoordintpair); // Paper - release light tickets as post task to ensure they stay loaded until fully done -+ if (skippedPre[0]) return; // Paper - future's already complete - chunk.setLightCorrect(true); - super.retainData(chunkcoordintpair, false); -- return chunk; -- }, (runnable) -> { -- this.addTask(chunkcoordintpair.x, chunkcoordintpair.z, ThreadedLevelLightEngine.TaskType.POST_UPDATE, runnable); -+ // Paper start -+ future.complete(chunk); - }); -+ return future; -+ // Paper end - } - - public void tryScheduleUpdate() { -- if ((!this.lightTasks.isEmpty() || super.hasLightWork()) && this.scheduled.compareAndSet(false, true)) { -+ if ((!this.queue.isEmpty() || super.hasLightWork()) && this.scheduled.compareAndSet(false, true)) { // Paper - this.taskMailbox.tell((() -> { // Paper - decompile error - this.runUpdate(); - this.scheduled.set(false); -+ tryScheduleUpdate(); // Paper - if we still have work to do, do it! - })); - } - - } - -+ // Paper start - replace impl -+ private final java.util.List pre = new java.util.ArrayList<>(); -+ private final java.util.List post = new java.util.ArrayList<>(); - private void runUpdate() { -- int i = Math.min(this.lightTasks.size(), this.taskPerBatch); -- ObjectListIterator> objectlistiterator = this.lightTasks.iterator(); -- -- Pair pair; -- int j; -- -- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { -- pair = (Pair) objectlistiterator.next(); -- if (pair.getFirst() == ThreadedLevelLightEngine.TaskType.PRE_UPDATE) { -- ((Runnable) pair.getSecond()).run(); -- } -+ if (queue.poll(pre, post)) { -+ pre.forEach(Runnable::run); -+ pre.clear(); -+ super.runUpdates(Integer.MAX_VALUE, true, true); -+ post.forEach(Runnable::run); -+ post.clear(); -+ } else { -+ // might have level updates to go still -+ super.runUpdates(Integer.MAX_VALUE, true, true); - } -- -- objectlistiterator.back(j); -- super.runUpdates(Integer.MAX_VALUE, true, true); -- -- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { -- pair = (Pair) objectlistiterator.next(); -- if (pair.getFirst() == ThreadedLevelLightEngine.TaskType.POST_UPDATE) { -- ((Runnable) pair.getSecond()).run(); -- } -- -- objectlistiterator.remove(); -- } -- -+ // Paper end - } - - public void setTaskPerBatch(int taskBatchSize) { -diff --git a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java -index c763aa0c0cf49dd844af94a820103258b49021ae..195535835bdc63f7cfdebeaa957dde590262ea42 100644 ---- a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java -+++ b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java -@@ -110,7 +110,8 @@ public class ProcessorMailbox implements ProcessorHandle, AutoCloseable, R - - } - -- @Override -+ -+ public final void queue(T t0) { tell(t0); } @Override // Paper - OBFHELPER - public void tell(T message) { - this.queue.push(message); - this.registerForExecution(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java -index 83e9d8bff9a31fe13a0e22445cd6eecb7abe8561..1e8ce9894fd0a121da83020c6064b7833af1c5f2 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java -@@ -11,6 +11,13 @@ import net.minecraft.server.MCUtil; - public class DataLayer { - - // Paper start -+ public static final DataLayer EMPTY_NIBBLE_ARRAY = new DataLayer() { -+ @Override -+ public byte[] getData() { -+ throw new IllegalStateException(); -+ } -+ }; -+ public long lightCacheKey = Long.MIN_VALUE; - public static byte[] EMPTY_NIBBLE = new byte[2048]; - private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072); - private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8)); -diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java -index 709fc42057f8a0282c3c942067e63abb874d9042..eaaaecb67966e5e366cf59f92674c82d1d87552e 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java -+++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java -@@ -23,9 +23,11 @@ public final class BlockLightEngine extends LayerLightEngine> 38); -+ int k = (int) ((blockPos << 52) >> 52); -+ int l = (int) ((blockPos << 26) >> 38); -+ // Paper end - BlockGetter iblockaccess = this.chunkSource.getChunkForLighting(j >> 4, l >> 4); - - return iblockaccess != null ? iblockaccess.getLightEmission(this.pos.set(j, k, l)) : 0; -@@ -40,25 +42,33 @@ public final class BlockLightEngine extends LayerLightEngine= 15) { - return level; - } else { -- int l = Integer.signum(BlockPos.getX(targetId) - BlockPos.getX(sourceId)); -- int i1 = Integer.signum(BlockPos.getY(targetId) - BlockPos.getY(sourceId)); -- int j1 = Integer.signum(BlockPos.getZ(targetId) - BlockPos.getZ(sourceId)); -+ // Paper start - reuse math - credit to JellySquid for idea -+ int jx = (int) (targetId >> 38); -+ int jy = (int) ((targetId << 52) >> 52); -+ int jz = (int) ((targetId << 26) >> 38); -+ int ix = (int) (sourceId >> 38); -+ int iy = (int) ((sourceId << 52) >> 52); -+ int iz = (int) ((sourceId << 26) >> 38); -+ int l = Integer.signum(jx - ix); -+ int i1 = Integer.signum(jy - iy); -+ int j1 = Integer.signum(jz - iz); -+ // Paper end - Direction enumdirection = Direction.fromNormal(l, i1, j1); - - if (enumdirection == null) { - return 15; - } else { - //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded -- BlockState iblockdata = this.getStateAndOpacity(targetId, mutableint); -- -- if (mutableint.getValue() >= 15) { -+ BlockState iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); // Paper -+ int blockedLight = mutableint.getValue(); // Paper -+ if (blockedLight >= 15) { // Paper - return 15; - } else { -- BlockState iblockdata1 = this.getStateAndOpacity(sourceId, (MutableInt) null); -+ BlockState iblockdata1 = this.getBlockOptimized(ix, iy, iz); // Paper - VoxelShape voxelshape = this.getShape(iblockdata1, sourceId, enumdirection); - VoxelShape voxelshape1 = this.getShape(iblockdata, targetId, enumdirection.getOpposite()); - -- return Shapes.faceShapeOccludes(voxelshape, voxelshape1) ? 15 : level + Math.max(1, mutableint.getValue()); -+ return Shapes.faceShapeOccludes(voxelshape, voxelshape1) ? 15 : level + Math.max(1, blockedLight); // Paper - } - } - } -@@ -66,14 +76,19 @@ public final class BlockLightEngine extends LayerLightEngine> 38); -+ int y = (int) ((id << 52) >> 52); -+ int z = (int) ((id << 26) >> 38); -+ long k = SectionPos.blockPosAsSectionLong(x, y, z); -+ // Paper end - Direction[] aenumdirection = BlockLightEngine.DIRECTIONS; - int l = aenumdirection.length; - - for (int i1 = 0; i1 < l; ++i1) { - Direction enumdirection = aenumdirection[i1]; -- long j1 = BlockPos.offset(id, enumdirection); -- long k1 = SectionPos.blockToSection(j1); -+ long j1 = BlockPos.getAdjacent(x, y, z, enumdirection); // Paper -+ long k1 = SectionPos.blockToSection(j1); // Paper - - if (k == k1 || ((BlockLightSectionStorage) this.storage).storingLightForSection(k1)) { - this.checkNeighbor(id, j1, level, decrease); -@@ -98,27 +113,37 @@ public final class BlockLightEngine extends LayerLightEngine> 38); -+ int baseY = (int) ((id << 52) >> 52); -+ int baseZ = (int) ((id << 26) >> 38); -+ long j1 = SectionPos.blockPosAsSectionLong(baseX, baseY, baseZ); -+ DataLayer nibblearray = this.storage.updating.getUpdatingOptimized(j1); -+ // Paper end - Direction[] aenumdirection = BlockLightEngine.DIRECTIONS; - int k1 = aenumdirection.length; - - for (int l1 = 0; l1 < k1; ++l1) { - Direction enumdirection = aenumdirection[l1]; -- long i2 = BlockPos.offset(id, enumdirection); -+ // Paper start -+ int newX = baseX + enumdirection.getStepX(); -+ int newY = baseY + enumdirection.getStepY(); -+ int newZ = baseZ + enumdirection.getStepZ(); -+ long i2 = BlockPos.asLong(newX, newY, newZ); - - if (i2 != excludedId) { -- long j2 = SectionPos.blockToSection(i2); -+ long j2 = SectionPos.blockPosAsSectionLong(newX, newY, newZ); -+ // Paper end - DataLayer nibblearray1; - - if (j1 == j2) { - nibblearray1 = nibblearray; - } else { -- nibblearray1 = ((BlockLightSectionStorage) this.storage).getDataLayer(j2, true); -+ nibblearray1 = ((BlockLightSectionStorage) this.storage).updating.getUpdatingOptimized(j2); // Paper - } - - if (nibblearray1 != null) { -- int k2 = this.computeLevelFromNeighbor(i2, id, this.getLevel(nibblearray1, i2)); -+ int k2 = this.computeLevelFromNeighbor(i2, id, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper - - if (l > k2) { - l = k2; -diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java -index a1ad4d73ddaf6afe97a1f1ff7e0622b52fac8761..f771ef8d841567b421b6c0529af3f0713c79eb7c 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java -@@ -1,8 +1,6 @@ - package net.minecraft.world.level.lighting; - - import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; --import net.minecraft.core.BlockPos; --import net.minecraft.core.SectionPos; - import net.minecraft.world.level.LightLayer; - import net.minecraft.world.level.chunk.DataLayer; - import net.minecraft.world.level.chunk.LightChunkGetter; -@@ -15,10 +13,14 @@ public class BlockLightSectionStorage extends LayerLightSectionStorage> 38); -+ int baseY = (int) ((blockPos << 52) >> 52); -+ int baseZ = (int) ((blockPos << 26) >> 38); -+ long j = (((long) (baseX >> 4) & 4194303L) << 42) | (((long) (baseY >> 4) & 1048575L)) | (((long) (baseZ >> 4) & 4194303L) << 20); -+ DataLayer nibblearray = this.e_visible.lookup.apply(j); -+ return nibblearray == null ? 0 : nibblearray.get(baseX & 15, baseY & 15, baseZ & 15); -+ // Paper end - } - - public static final class BlockDataLayerStorageMap extends DataLayerStorageMap { -diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -index 54cca3b376e5ce02936edc8b9c17e67e17f07147..ed2ed6194670016086be580dc4514d5d3d1b235b 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -+++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -@@ -7,13 +7,18 @@ import net.minecraft.world.level.chunk.DataLayer; - - public abstract class DataLayerStorageMap> { - -- private final long[] lastSectionKeys = new long[2]; -- private final DataLayer[] lastSections = new DataLayer[2]; -+ // private final long[] b = new long[2]; // Paper - unused -+ private final DataLayer[] lastSections = new DataLayer[]{DataLayer.EMPTY_NIBBLE_ARRAY, DataLayer.EMPTY_NIBBLE_ARRAY}; private final DataLayer[] cache = lastSections; // Paper - OBFHELPER - private boolean cacheEnabled; - protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data - protected final boolean isVisible; // Paper - avoid copying light data -- java.util.function.Function lookup; // Paper - faster branchless lookup - -+ // Paper start - faster lookups with less branching, use interface to avoid boxing instead of Function -+ public final NibbleArrayAccess lookup; -+ public interface NibbleArrayAccess { -+ DataLayer apply(long id); -+ } -+ // Paper end - // Paper start - avoid copying light data - protected DataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { - if (isVisible) { -@@ -21,12 +26,14 @@ public abstract class DataLayerStorageMap> { - } - this.data = data; - this.isVisible = isVisible; -+ // Paper end - avoid copying light data -+ // Paper start - faster lookups with less branching - if (isVisible) { - lookup = data::getVisibleAsync; - } else { -- lookup = data::getUpdating; -+ lookup = data.getUpdatingMap()::get; // jump straight the sub map - } -- // Paper end - avoid copying light data -+ // Paper end - this.clearCache(); - this.cacheEnabled = true; - } -@@ -36,7 +43,9 @@ public abstract class DataLayerStorageMap> { - public void copyDataLayer(long pos) { - if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data - DataLayer updating = this.data.getUpdating(pos); // Paper - pool nibbles -- this.data.queueUpdate(pos, new DataLayer().markPoolSafe(updating.getCloneIfSet())); // Paper - avoid copying light data - pool safe clone -+ DataLayer nibblearray = new DataLayer().markPoolSafe(updating.getCloneIfSet()); // Paper -+ nibblearray.lightCacheKey = pos; // Paper -+ this.data.queueUpdate(pos, nibblearray); // Paper - avoid copying light data - pool safe clone - if (updating.cleaner != null) MCUtil.scheduleTask(2, updating.cleaner, "Light Engine Release"); // Paper - delay clean incase anything holding ref was still using it - this.clearCache(); - } -@@ -45,34 +54,34 @@ public abstract class DataLayerStorageMap> { - return lookup.apply(chunkPos) != null; // Paper - avoid copying light data - } - -- @Nullable -- public final DataLayer getLayer(long chunkPos) { // Paper - final -- if (this.cacheEnabled) { -- for (int j = 0; j < 2; ++j) { -- if (chunkPos == this.lastSectionKeys[j]) { -- return this.lastSections[j]; -- } -- } -- } -- -- DataLayer nibblearray = lookup.apply(chunkPos); // Paper - avoid copying light data -+ // Paper start - less branching as we know we are using cache and updating -+ public final DataLayer getUpdatingOptimized(final long i) { // Paper - final -+ final DataLayer[] cache = this.cache; -+ if (cache[0].lightCacheKey == i) return cache[0]; -+ if (cache[1].lightCacheKey == i) return cache[1]; - -+ final DataLayer nibblearray = this.lookup.apply(i); // Paper - avoid copying light data - if (nibblearray == null) { - return null; - } else { -- if (this.cacheEnabled) { -- for (int k = 1; k > 0; --k) { -- this.lastSectionKeys[k] = this.lastSectionKeys[k - 1]; -- this.lastSections[k] = this.lastSections[k - 1]; -- } -- -- this.lastSectionKeys[0] = chunkPos; -- this.lastSections[0] = nibblearray; -- } -- -+ cache[1] = cache[0]; -+ cache[0] = nibblearray; - return nibblearray; - } - } -+ // Paper end -+ -+ @Nullable -+ public final DataLayer getLayer(final long chunkPos) { // Paper - final -+ // Paper start - optimize visible case or missed updating cases -+ if (this.cacheEnabled) { -+ // short circuit to optimized -+ return getUpdatingOptimized(chunkPos); -+ } -+ -+ return this.lookup.apply(chunkPos); -+ // Paper end -+ } - - @Nullable - public DataLayer removeLayer(long chunkPos) { -@@ -82,13 +91,14 @@ public abstract class DataLayerStorageMap> { - - public void setLayer(long pos, DataLayer data) { - if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data -+ data.lightCacheKey = pos; // Paper - this.data.queueUpdate(pos, data); // Paper - avoid copying light data - } - - public void clearCache() { - for (int i = 0; i < 2; ++i) { -- this.lastSectionKeys[i] = Long.MAX_VALUE; -- this.lastSections[i] = null; -+ // this.b[i] = Long.MAX_VALUE; // Paper - Unused -+ this.lastSections[i] = DataLayer.EMPTY_NIBBLE_ARRAY; // Paper - } - } - -diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightEngine.java -index 53f38fa95f4ffad12c73d94ab1d7ecf7ee78af09..088ea8a14f1bb264b59fcec626b1a28d7f6d7c47 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LayerLightEngine.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightEngine.java -@@ -10,6 +10,7 @@ import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.LightLayer; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.BlockState; -+import net.minecraft.world.level.chunk.ChunkAccess; - import net.minecraft.world.level.chunk.DataLayer; - import net.minecraft.world.level.chunk.LightChunkGetter; - import net.minecraft.world.phys.shapes.Shapes; -@@ -23,10 +24,37 @@ public abstract class LayerLightEngine, S exten - protected final LightLayer layer; - protected final S storage; - private boolean runningLightUpdates; -- protected final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); -+ protected final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); protected final BlockPos.MutableBlockPos pos = pos; // Paper - private final long[] lastChunkPos = new long[2]; -- private final BlockGetter[] lastChunk = new BlockGetter[2]; -+ private final ChunkAccess[] h = new ChunkAccess[2]; // Paper - -+ // Paper start - see fully commented out method below (look for Bedrock) -+ // optimized method with less branching for when scenarios arent needed. -+ // avoid using mutable version if can -+ protected final BlockState getBlockOptimized(int x, int y, int z, MutableInt mutableint) { -+ ChunkAccess iblockaccess = this.a(x >> 4, z >> 4); -+ -+ if (iblockaccess == null) { -+ mutableint.setValue(16); -+ return Blocks.BEDROCK.defaultBlockState(); -+ } else { -+ this.pos.setValues(x, y, z); -+ BlockState iblockdata = iblockaccess.getType(x, y, z); -+ mutableint.setValue(iblockdata.getLightBlock(this.chunkSource.getLevel(), this.pos)); -+ return iblockdata.canOcclude() && iblockdata.useShapeForLightOcclusion() ? iblockdata : Blocks.AIR.defaultBlockState(); -+ } -+ } -+ protected final BlockState getBlockOptimized(int x, int y, int z) { -+ ChunkAccess iblockaccess = this.a(x >> 4, z >> 4); -+ -+ if (iblockaccess == null) { -+ return Blocks.BEDROCK.defaultBlockState(); -+ } else { -+ BlockState iblockdata = iblockaccess.getType(x, y, z); -+ return iblockdata.canOcclude() && iblockdata.useShapeForLightOcclusion() ? iblockdata : Blocks.AIR.defaultBlockState(); -+ } -+ } -+ // Paper end - public LayerLightEngine(LightChunkGetter chunkProvider, LightLayer type, S lightStorage) { - super(16, 256, 8192); - this.chunkSource = chunkProvider; -@@ -45,63 +73,65 @@ public abstract class LayerLightEngine, S exten - } - - @Nullable -- private BlockGetter getChunk(int chunkX, int chunkZ) { -- long k = ChunkPos.asLong(chunkX, chunkZ); -+ private ChunkAccess a(int i, int j) { // Paper -+ long k = ChunkPos.asLong(i, j); - - for (int l = 0; l < 2; ++l) { - if (k == this.lastChunkPos[l]) { -- return this.lastChunk[l]; -+ return this.h[l]; - } - } - -- BlockGetter iblockaccess = this.chunkSource.getChunkForLighting(chunkX, chunkZ); -+ ChunkAccess iblockaccess = (ChunkAccess) this.chunkSource.getChunkForLighting(i, j); // Paper - - for (int i1 = 1; i1 > 0; --i1) { - this.lastChunkPos[i1] = this.lastChunkPos[i1 - 1]; -- this.lastChunk[i1] = this.lastChunk[i1 - 1]; -+ this.h[i1] = this.h[i1 - 1]; - } - - this.lastChunkPos[0] = k; -- this.lastChunk[0] = iblockaccess; -+ this.h[0] = iblockaccess; - return iblockaccess; - } - - private void clearCache() { - Arrays.fill(this.lastChunkPos, ChunkPos.INVALID_CHUNK_POS); -- Arrays.fill(this.lastChunk, (Object) null); -+ Arrays.fill(this.h, (Object) null); - } - -- protected BlockState getStateAndOpacity(long pos, @Nullable MutableInt mutableint) { -- if (pos == Long.MAX_VALUE) { -- if (mutableint != null) { -- mutableint.setValue(0); -- } -- -- return Blocks.AIR.defaultBlockState(); -- } else { -- int j = SectionPos.blockToSectionCoord(BlockPos.getX(pos)); -- int k = SectionPos.blockToSectionCoord(BlockPos.getZ(pos)); -- BlockGetter iblockaccess = this.getChunk(j, k); -- -- if (iblockaccess == null) { -- if (mutableint != null) { -- mutableint.setValue(16); -- } -- -- return Blocks.BEDROCK.defaultBlockState(); -- } else { -- this.pos.set(pos); -- BlockState iblockdata = iblockaccess.getBlockState(this.pos); -- boolean flag = iblockdata.canOcclude() && iblockdata.useShapeForLightOcclusion(); -- -- if (mutableint != null) { -- mutableint.setValue(iblockdata.getLightBlock(this.chunkSource.getLevel(), (BlockPos) this.pos)); -- } -- -- return flag ? iblockdata : Blocks.AIR.defaultBlockState(); -- } -- } -- } -+ // Paper start - comment out, see getBlockOptimized -+// protected IBlockData a(long i, @Nullable MutableInt mutableint) { -+// if (i == Long.MAX_VALUE) { -+// if (mutableint != null) { -+// mutableint.setValue(0); -+// } -+// -+// return Blocks.AIR.getBlockData(); -+// } else { -+// int j = SectionPosition.a(BlockPosition.b(i)); -+// int k = SectionPosition.a(BlockPosition.d(i)); -+// IBlockAccess iblockaccess = this.a(j, k); -+// -+// if (iblockaccess == null) { -+// if (mutableint != null) { -+// mutableint.setValue(16); -+// } -+// -+// return Blocks.BEDROCK.getBlockData(); -+// } else { -+// this.d.g(i); -+// IBlockData iblockdata = iblockaccess.getType(this.d); -+// boolean flag = iblockdata.l() && iblockdata.e(); -+// -+// if (mutableint != null) { -+// mutableint.setValue(iblockdata.b(this.a.getWorld(), (BlockPosition) this.d)); -+// } -+// -+// return flag ? iblockdata : Blocks.AIR.getBlockData(); -+// } -+// } -+// } -+ // Paper end - - protected VoxelShape getShape(BlockState world, long pos, Direction facing) { - return world.canOcclude() ? world.getFaceOcclusionShape(this.chunkSource.getLevel(), this.pos.set(pos), facing) : Shapes.empty(); -@@ -136,8 +166,9 @@ public abstract class LayerLightEngine, S exten - return id == Long.MAX_VALUE ? 0 : 15 - this.storage.getStoredLevel(id); - } - -+ protected int getNibbleLightInverse(DataLayer nibblearray, int x, int y, int z) { return 15 - nibblearray.get(x & 15, y & 15, z & 15); } // Paper - x/y/z version of below - protected int getLevel(DataLayer section, long blockPos) { -- return 15 - section.get(SectionPos.sectionRelative(BlockPos.getX(blockPos)), SectionPos.sectionRelative(BlockPos.getY(blockPos)), SectionPos.sectionRelative(BlockPos.getZ(blockPos))); -+ return 15 - section.get((int) (blockPos >> 38) & 15, (int) ((blockPos << 52) >> 52) & 15, (int) ((blockPos << 26) >> 38) & 15); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -index 5757bcfded35f112d52a7c81586850ba50e0d8dd..17a6610b352af5d3e2cbcdf9b4d9b0d4d356b5cf 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -@@ -27,9 +27,9 @@ public abstract class LayerLightSectionStorage> - protected final LongSet toMarkNoData = new LongOpenHashSet(); - protected final LongSet toMarkData = new LongOpenHashSet(); - protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change -- protected final M updatingSectionData; // Paper - diff on change, should be "updating" -+ protected final M updatingSectionData; protected final M updating; // Paper - diff on change, should be "updating" - protected final LongSet changedSections = new LongOpenHashSet(); -- protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet(); -+ protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet(); LongSet dirty = sectionsAffectedByLightUpdates; // Paper - OBFHELPER - protected final Long2ObjectMap queuedSections = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); - private final LongSet untrustedSections = new LongOpenHashSet(); - private final LongSet columnsToRetainQueuedDataFor = new LongOpenHashSet(); -@@ -37,33 +37,33 @@ public abstract class LayerLightSectionStorage> - protected volatile boolean hasToRemove; - - protected LayerLightSectionStorage(LightLayer lightType, LightChunkGetter chunkProvider, M lightData) { -- super(3, 16, 256); -+ super(3, 256, 256); // Paper - bump expected size of level sets to improve collisions and reduce rehashing (seen a lot of it) - this.layer = lightType; - this.chunkSource = chunkProvider; -- this.updatingSectionData = lightData; -+ this.updatingSectionData = lightData; updating = lightData; // Paper - this.e_visible = lightData.copy(); // Paper - avoid copying light data - this.e_visible.disableCache(); // Paper - avoid copying light data - } - -- protected boolean storingLightForSection(long sectionPos) { -- return this.getDataLayer(sectionPos, true) != null; -+ protected final boolean storingLightForSection(long sectionPos) { // Paper - final to help inlining -+ return this.updating.getUpdatingOptimized(sectionPos) != null; // Paper - inline to avoid branching - } - - @Nullable - protected DataLayer getDataLayer(long sectionPos, boolean cached) { - // Paper start - avoid copying light data - if (cached) { -- return this.getDataLayer(this.updatingSectionData, sectionPos); -+ return this.updating.getUpdatingOptimized(sectionPos); - } else { - synchronized (this.visibleUpdateLock) { -- return this.getDataLayer(this.e_visible, sectionPos); -+ return this.e_visible.lookup.apply(sectionPos); - } - } - // Paper end - avoid copying light data - } - - @Nullable -- protected DataLayer getDataLayer(M storage, long sectionPos) { -+ protected final DataLayer getDataLayer(M storage, long sectionPos) { // Paper - return storage.getLayer(sectionPos); - } - -@@ -77,27 +77,57 @@ public abstract class LayerLightSectionStorage> - protected abstract int getLightValue(long blockPos); - - protected int getStoredLevel(long blockPos) { -- long j = SectionPos.blockToSection(blockPos); -- DataLayer nibblearray = this.getDataLayer(j, true); -+ // Paper start - reuse and inline math, use Optimized Updating path -+ final int x = (int) (blockPos >> 38); -+ final int y = (int) ((blockPos << 52) >> 52); -+ final int z = (int) ((blockPos << 26) >> 38); -+ long j = SectionPos.blockPosAsSectionLong(x, y, z); -+ DataLayer nibblearray = this.updating.getUpdatingOptimized(j); -+ // BUG: Sometimes returns null and crashes, try to recover, but to prevent crash just return no light. -+ if (nibblearray == null) { -+ nibblearray = this.e_visible.lookup.apply(j); -+ } -+ if (nibblearray == null) { -+ System.err.println("Null nibble, preventing crash " + BlockPos.of(blockPos)); -+ return 0; -+ } - -- return nibblearray.get(SectionPos.sectionRelative(BlockPos.getX(blockPos)), SectionPos.sectionRelative(BlockPos.getY(blockPos)), SectionPos.sectionRelative(BlockPos.getZ(blockPos))); -+ return nibblearray.get(x & 15, y & 15, z & 15); // Paper - inline operations -+ // Paper end - } - - protected void setStoredLevel(long blockPos, int value) { -- long k = SectionPos.blockToSection(blockPos); -+ // Paper start - cache part of the math done in loop below -+ int x = (int) (blockPos >> 38); -+ int y = (int) ((blockPos << 52) >> 52); -+ int z = (int) ((blockPos << 26) >> 38); -+ long k = SectionPos.blockPosAsSectionLong(x, y, z); -+ // Paper end - - if (this.changedSections.add(k)) { - this.updatingSectionData.copyDataLayer(k); - } - - DataLayer nibblearray = this.getDataLayer(k, true); -- -- nibblearray.set(SectionPos.sectionRelative(BlockPos.getX(blockPos)), SectionPos.sectionRelative(BlockPos.getY(blockPos)), SectionPos.sectionRelative(BlockPos.getZ(blockPos)), value); -- -- for (int l = -1; l <= 1; ++l) { -- for (int i1 = -1; i1 <= 1; ++i1) { -- for (int j1 = -1; j1 <= 1; ++j1) { -- this.sectionsAffectedByLightUpdates.add(SectionPos.blockToSection(BlockPos.offset(blockPos, i1, j1, l))); -+ nibblearray.set(x & 15, y & 15, z & 15, value); // Paper - use already calculated x/y/z -+ -+ // Paper start - credit to JellySquid for a major optimization here: -+ /* -+ * An extremely important optimization is made here in regards to adding items to the pending notification set. The -+ * original implementation attempts to add the coordinate of every chunk which contains a neighboring block position -+ * even though a huge number of loop iterations will simply map to block positions within the same updating chunk. -+ * -+ * Our implementation here avoids this by pre-calculating the min/max chunk coordinates so we can iterate over only -+ * the relevant chunk positions once. This reduces what would always be 27 iterations to just 1-8 iterations. -+ * -+ * @reason Use faster implementation -+ * @author JellySquid -+ */ -+ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { -+ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { -+ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { -+ this.dirty.add(SectionPos.asLong(x2, y2, z2)); -+ // Paper end - } - } - } -@@ -129,17 +159,23 @@ public abstract class LayerLightSectionStorage> - } - - if (k >= 2 && level != 2) { -- if (this.toRemove.contains(id)) { -- this.toRemove.remove(id); -- } else { -+ if (!this.toRemove.remove(id)) { // Paper - remove useless contains - credit to JellySquid -+ //this.p.remove(i); // Paper -+ //} else { // Paper - this.updatingSectionData.setLayer(id, this.createDataLayer(id)); - this.changedSections.add(id); - this.onNodeAdded(id); - -- for (int l = -1; l <= 1; ++l) { -- for (int i1 = -1; i1 <= 1; ++i1) { -- for (int j1 = -1; j1 <= 1; ++j1) { -- this.sectionsAffectedByLightUpdates.add(SectionPos.blockToSection(BlockPos.offset(id, i1, j1, l))); -+ // Paper start - reuse x/y/z and only notify valid chunks - Credit to JellySquid (See above method for notes) -+ int x = (int) (id >> 38); -+ int y = (int) ((id << 52) >> 52); -+ int z = (int) ((id << 26) >> 38); -+ -+ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { -+ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { -+ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { -+ this.dirty.add(SectionPos.asLong(x2, y2, z2)); -+ // Paper end - } - } - } -@@ -165,9 +201,9 @@ public abstract class LayerLightSectionStorage> - return SectionPos.blockToSection(j) == sectionPos; - }); - } else { -- int j = SectionPos.sectionToBlockCoord(SectionPos.x(sectionPos)); -- int k = SectionPos.sectionToBlockCoord(SectionPos.y(sectionPos)); -- int l = SectionPos.sectionToBlockCoord(SectionPos.z(sectionPos)); -+ int j = (int) (sectionPos >> 42) << 4; // Paper - inline -+ int k = (int) (sectionPos << 44 >> 44) << 4; // Paper - inline -+ int l = (int) (sectionPos << 22 >> 42) << 4; // Paper - inline - - for (int i1 = 0; i1 < 16; ++i1) { - for (int j1 = 0; j1 < 16; ++j1) { -@@ -194,7 +230,7 @@ public abstract class LayerLightSectionStorage> - DataLayer nibblearray; - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.clearQueuedSectionBlocks(lightProvider, i); - DataLayer nibblearray1 = (DataLayer) this.queuedSections.remove(i); - -@@ -212,7 +248,7 @@ public abstract class LayerLightSectionStorage> - longiterator = this.toRemove.iterator(); - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.onNodeRemoved(i); - } - -@@ -223,12 +259,13 @@ public abstract class LayerLightSectionStorage> - Entry entry; - long j; - -+ DataLayer test = null; // Paper - while (objectiterator.hasNext()) { - entry = (Entry) objectiterator.next(); - j = entry.getLongKey(); -- if (this.storingLightForSection(j)) { -+ if ((test = this.updating.getUpdatingOptimized(j)) != null) { // Paper - dont look up nibble twice - nibblearray = (DataLayer) entry.getValue(); -- if (this.updatingSectionData.getLayer(j) != nibblearray) { -+ if (test != nibblearray) { // Paper - this.clearQueuedSectionBlocks(lightProvider, j); - this.updatingSectionData.setLayer(j, nibblearray); - this.changedSections.add(j); -@@ -241,14 +278,14 @@ public abstract class LayerLightSectionStorage> - longiterator = this.queuedSections.keySet().iterator(); - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.checkEdgesForSection(lightProvider, i); - } - } else { - longiterator = this.untrustedSections.iterator(); - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.checkEdgesForSection(lightProvider, i); - } - } -@@ -269,15 +306,20 @@ public abstract class LayerLightSectionStorage> - - private void checkEdgesForSection(LayerLightEngine lightProvider, long sectionPos) { - if (this.storingLightForSection(sectionPos)) { -- int j = SectionPos.sectionToBlockCoord(SectionPos.x(sectionPos)); -- int k = SectionPos.sectionToBlockCoord(SectionPos.y(sectionPos)); -- int l = SectionPos.sectionToBlockCoord(SectionPos.z(sectionPos)); -+ // Paper start -+ int secX = (int) (sectionPos >> 42); -+ int secY = (int) (sectionPos << 44 >> 44); -+ int secZ = (int) (sectionPos << 22 >> 42); -+ int j = secX << 4; // baseX -+ int k = secY << 4; // baseY -+ int l = secZ << 4; // baseZ -+ // Paper end - Direction[] aenumdirection = LayerLightSectionStorage.DIRECTIONS; - int i1 = aenumdirection.length; - - for (int j1 = 0; j1 < i1; ++j1) { - Direction enumdirection = aenumdirection[j1]; -- long k1 = SectionPos.offset(sectionPos, enumdirection); -+ long k1 = SectionPos.getAdjacentFromSectionPos(secX, secY, secZ, enumdirection); // Paper - avoid extra unpacking - - if (!this.queuedSections.containsKey(k1) && this.storingLightForSection(k1)) { - for (int l1 = 0; l1 < 16; ++l1) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java -index ff1fbc46776b26ca56c3293e40ed55028230ec46..da4003aebc8d5ffce695071af9a27139568d773f 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java -+++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java -@@ -4,6 +4,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; - import net.minecraft.core.SectionPos; - import net.minecraft.world.level.LightLayer; -+import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.level.chunk.DataLayer; - import net.minecraft.world.level.chunk.LightChunkGetter; -@@ -38,21 +39,25 @@ public final class SkyLightEngine extends LayerLightEngine= 15) { -+ // Paper start - use x/y/z and optimized block lookup -+ int jx = (int) (targetId >> 38); -+ int jy = (int) ((targetId << 52) >> 52); -+ int jz = (int) ((targetId << 26) >> 38); -+ BlockState iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); -+ int blockedLight = mutableint.getValue(); -+ if (blockedLight >= 15) { -+ // Paper end - return 15; - } else { -- int l = BlockPos.getX(sourceId); -- int i1 = BlockPos.getY(sourceId); -- int j1 = BlockPos.getZ(sourceId); -- int k1 = BlockPos.getX(targetId); -- int l1 = BlockPos.getY(targetId); -- int i2 = BlockPos.getZ(targetId); -- boolean flag = l == k1 && j1 == i2; -- int j2 = Integer.signum(k1 - l); -- int k2 = Integer.signum(l1 - i1); -- int l2 = Integer.signum(i2 - j1); -+ // Paper start - inline math -+ int ix = (int) (sourceId >> 38); -+ int iy = (int) ((sourceId << 52) >> 52); -+ int iz = (int) ((sourceId << 26) >> 38); -+ boolean flag = ix == jx && iz == jz; -+ int j2 = Integer.signum(jx - ix); -+ int k2 = Integer.signum(jy - iy); -+ int l2 = Integer.signum(jz - iz); -+ // Paper end - Direction enumdirection; - - if (sourceId == Long.MAX_VALUE) { -@@ -61,7 +66,7 @@ public final class SkyLightEngine extends LayerLightEngine l1; -+ boolean flag1 = sourceId == Long.MAX_VALUE || flag && iy > jy; // Paper rename vars to iy > jy - -- return flag1 && level == 0 && mutableint.getValue() == 0 ? 0 : level + Math.max(1, mutableint.getValue()); -+ return flag1 && level == 0 && blockedLight == 0 ? 0 : level + Math.max(1, blockedLight); // Paper - } - } - } -@@ -101,10 +106,14 @@ public final class SkyLightEngine extends LayerLightEngine> 38); -+ int baseY = (int) ((id << 52) >> 52); -+ int baseZ = (int) ((id << 26) >> 38); -+ long k = SectionPos.blockPosAsSectionLong(baseX, baseY, baseZ); -+ int i1 = baseY & 15; -+ int j1 = baseY >> 4; -+ // Paper end - int k1; - - if (i1 != 0) { -@@ -119,15 +128,16 @@ public final class SkyLightEngine extends LayerLightEngine> 38); -+ int baseY = (int) ((id << 52) >> 52); -+ int baseZ = (int) ((id << 26) >> 38); -+ long j1 = SectionPos.blockPosAsSectionLong(baseX, baseY, baseZ); -+ DataLayer nibblearray = this.storage.updating.getUpdatingOptimized(j1); -+ // Paper end - Direction[] aenumdirection = SkyLightEngine.DIRECTIONS; - int k1 = aenumdirection.length; - - for (int l1 = 0; l1 < k1; ++l1) { - Direction enumdirection = aenumdirection[l1]; -- long i2 = BlockPos.offset(id, enumdirection); -- long j2 = SectionPos.blockToSection(i2); -+ // Paper start -+ int newX = baseX + enumdirection.getStepX(); -+ int newY = baseY + enumdirection.getStepY(); -+ int newZ = baseZ + enumdirection.getStepZ(); -+ long i2 = BlockPos.asLong(newX, newY, newZ); -+ long j2 = SectionPos.blockPosAsSectionLong(newX, newY, newZ); -+ // Paper end - DataLayer nibblearray1; - - if (j1 == j2) { - nibblearray1 = nibblearray; - } else { -- nibblearray1 = ((SkyLightSectionStorage) this.storage).getDataLayer(j2, true); -+ nibblearray1 = ((SkyLightSectionStorage) this.storage).updating.getUpdatingOptimized(j2); // Paper - } - - if (nibblearray1 != null) { - if (i2 != excludedId) { -- int k2 = this.computeLevelFromNeighbor(i2, id, this.getLevel(nibblearray1, i2)); -+ int k2 = this.computeLevelFromNeighbor(i2, id, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper - - if (l > k2) { - l = k2; -@@ -215,7 +235,7 @@ public final class SkyLightEngine extends LayerLightEngine> 38); -+ int baseY = (int) ((blockPos << 52) >> 52); -+ int baseZ = (int) ((blockPos << 26) >> 38); -+ long j = SectionPos.blockPosAsSectionLong(baseX, baseY, baseZ); -+ // Paper end - int k = SectionPos.y(j); - synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data - SkyLightSectionStorage.SkyDataLayerStorageMap lightenginestoragesky_a = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.e_visible; // Paper - avoid copying light data - must be after lock acquire -@@ -49,7 +54,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage> 52) & 15, (int) baseZ & 15); // Paper - y changed above - } else { - return 15; - } -@@ -168,7 +173,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage> 42) << 4; // Paper -+ int baseY = (int) (i << 44 >> 44) << 4; // Paper -+ int baseZ = (int) (i << 22 >> 42) << 4; // Paper - j = this.getLevel(i); - if (j != 2 && !this.sectionsToRemoveSourcesFrom.contains(i) && this.sectionsWithSources.add(i)) { - int l; -@@ -203,10 +211,10 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage> 42) << 4; // Paper -+ int baseY = (int) (i << 44 >> 44) << 4; // Paper -+ int baseZ = (int) (i << 22 >> 42) << 4; // Paper - if (this.sectionsWithSources.remove(i) && this.storingLightForSection(i)) { - for (j = 0; j < 16; ++j) { - for (k = 0; k < 16; ++k) { -- long l3 = BlockPos.asLong(SectionPos.sectionToBlockCoord(SectionPos.x(i)) + j, SectionPos.sectionToBlockCoord(SectionPos.y(i)) + 16 - 1, SectionPos.sectionToBlockCoord(SectionPos.z(i)) + k); -+ long l3 = BlockPos.asLong(baseX + j, baseY + 16 - 1, baseZ + k); // Paper - - lightProvider.checkEdge(Long.MAX_VALUE, l3, 15, false); - } diff --git a/Remapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/Remapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch deleted file mode 100644 index a8c890b13a..0000000000 --- a/Remapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Jun 2016 23:22:12 -0400 -Subject: [PATCH] Delay Chunk Unloads based on Player Movement - -When players are moving in the world, doing things such as building or exploring, -they will commonly go back and forth in a small area. This causes a ton of chunk load -and unload activity on the edge chunks of their view distance. - -A simple back and forth movement in 6 blocks could spam a chunk to thrash a -loading and unload cycle over and over again. - -This is very wasteful. This system introduces a delay of inactivity on a chunk -before it actually unloads, which will be handled by the ticket expiry process. - -This allows servers with smaller worlds who do less long distance exploring to stop -wasting cpu cycles on saving/unloading/reloading chunks repeatedly. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6463d3e4837d032a35654a035f42b8a805e0e286..1655bca0502e7b871de4addaa163536d86547a02 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -637,4 +637,13 @@ public class PaperWorldConfig { - private void viewDistance() { - this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); - } -+ -+ public long delayChunkUnloadsBy; -+ private void delayChunkUnloadsBy() { -+ delayChunkUnloadsBy = PaperConfig.getSeconds(getString("delay-chunk-unloads-by", "10s")); -+ if (delayChunkUnloadsBy > 0) { -+ log("Delaying chunk unloads by " + delayChunkUnloadsBy + " seconds"); -+ delayChunkUnloadsBy *= 20; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index e41f388e8350010a471410436adf15a906f07e97..e0241b9d60cd2b72f8fb774f1ab4753dfd615184 100644 ---- a/src/main/java/net/minecraft/server/level/DistanceManager.java -+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -185,6 +185,27 @@ public abstract class DistanceManager { - boolean removed = false; // CraftBukkit - if (arraysetsorted.remove(ticket)) { - removed = true; // CraftBukkit -+ // Paper start - delay chunk unloads for player tickets -+ long delayChunkUnloadsBy = chunkMap.level.paperConfig.delayChunkUnloadsBy; -+ if (ticket.getType() == TicketType.PLAYER && delayChunkUnloadsBy > 0) { -+ boolean hasPlayer = false; -+ for (Ticket ticket1 : arraysetsorted) { -+ if (ticket1.getType() == TicketType.PLAYER) { -+ hasPlayer = true; -+ break; -+ } -+ } -+ ChunkHolder playerChunk = chunkMap.getUpdatingChunkIfPresent(i); -+ if (!hasPlayer && playerChunk != null && playerChunk.isFullChunkReady()) { -+ Ticket delayUnload = new Ticket(TicketType.DELAY_UNLOAD, 33, i); -+ delayUnload.delayUnloadBy = delayChunkUnloadsBy; -+ delayUnload.setCurrentTick(this.ticketTickCounter); -+ arraysetsorted.remove(delayUnload); -+ // refresh ticket -+ arraysetsorted.add(delayUnload); -+ } -+ } -+ // Paper end - } - - if (arraysetsorted.isEmpty()) { -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index c0bfe136ccb9ad4fc0f8ccdd703254205213ec8e..f7898bd7806684d2c068898cecbf835d834df461 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -9,11 +9,13 @@ public final class Ticket implements Comparable> { - public final T key; public final T getObjectReason() { return this.key; } // Paper - OBFHELPER - private long createdTick; public final long getCreationTick() { return this.createdTick; } // Paper - OBFHELPER - public int priority = 0; // Paper -+ public long delayUnloadBy; // Paper - - protected Ticket(TicketType type, int level, T argument) { - this.type = type; - this.ticketLevel = level; - this.key = argument; -+ this.delayUnloadBy = type.timeout; // Paper - } - - public int compareTo(Ticket ticket) { -@@ -63,7 +65,7 @@ public final class Ticket implements Comparable> { - } - - protected boolean timedOut(long currentTick) { -- long j = this.type.timeout(); -+ long j = delayUnloadBy; // Paper - - return j != 0L && currentTick - this.createdTick > j; - } -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 2444f6f676db543509b14e8c882491dc3f41b264..531ebf1bafec2b295af9f6dfec8f4b6466688287 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -30,6 +30,7 @@ public class TicketType { - public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper - public static final TicketType PRIORITY = create("priority", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper - public static final TicketType URGENT = create("urgent", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper -+ public static final TicketType DELAY_UNLOAD = create("delay_unload", Long::compareTo, 300); // Paper - - public static TicketType create(String name, Comparator comparator) { - return new TicketType<>(name, comparator, 0L); diff --git a/Remapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/Remapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch deleted file mode 100644 index 2d4cc183be..0000000000 --- a/Remapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 9 Jun 2020 03:33:03 -0400 -Subject: [PATCH] Add Plugin Tickets to API Chunk Methods - -Like previous versions, plugins loading chunks kept them loaded until -they garbage collected to avoid constant spamming of chunk loads - -This adds tickets to a few more places so that they can be unloaded. - -Additionally, this drops their ticket level to BORDER so they wont be ticking -so they will just sit inactive instead. - -Using .loadChunk to keep a chunk ticking was a horrible idea for upstream -when we have TWO methods that are able to do that already in the API. - -Also reduce their collection count down to a maximum of 1 second. Barely -anyone knows what chunk-gc is in bukkit.yml as its less relevant now, and -since this wasn't spigot behavior, this is safe to mostly ignore (unless someone -wants it to collect even faster, they can restore that setting back to 1 instead of 20+) - -Not adding it to .getType() though to keep behavior consistent with vanilla for performance reasons. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 92f1a6d32a96fee682342e86c3ffd3c65292150b..2ec41cb87cec97780f1fa8abfbb756fca4dba1bf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -342,7 +342,7 @@ public final class CraftServer implements Server { - ambientSpawn = configuration.getInt("spawn-limits.ambient"); - console.autosavePeriod = configuration.getInt("ticks-per.autosave"); - warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); -- TicketType.PLUGIN.timeout = configuration.getInt("chunk-gc.period-in-ticks"); -+ TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - loadIcon(); - } -@@ -832,7 +832,7 @@ public final class CraftServer implements Server { - waterAmbientSpawn = configuration.getInt("spawn-limits.water-ambient"); - ambientSpawn = configuration.getInt("spawn-limits.ambient"); - warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); -- TicketType.PLUGIN.timeout = configuration.getInt("chunk-gc.period-in-ticks"); -+ TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - printSaveWarning = false; - console.autosavePeriod = configuration.getInt("ticks-per.autosave"); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 7261e22a71d219efe0949a08c5d3f10747759469..4436b3d23dc8f33925da1ec539ea16307e0785b9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.ClientboundCustomSoundPacket; - import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; - import net.minecraft.network.protocol.game.ClientboundSetTimePacket; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ChunkHolder; - import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.DistanceManager; -@@ -389,8 +390,21 @@ public class CraftWorld implements World { - - @Override - public Chunk getChunkAt(int x, int z) { -- return this.world.getChunkSource().getChunk(x, z, true).bukkitChunk; -+ // Paper start - add ticket to hold chunk for a little while longer if plugin accesses it -+ net.minecraft.world.level.chunk.LevelChunk chunk = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); -+ if (chunk == null) { -+ addTicket(x, z); -+ chunk = this.world.getChunkSource().getChunk(x, z, true); -+ } -+ return chunk.bukkitChunk; -+ // Paper end -+ } -+ -+ // Paper start -+ private void addTicket(int x, int z) { -+ MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE)); // Paper - } -+ // Paper end - - @Override - public Chunk getChunkAt(Block block) { -@@ -465,7 +479,7 @@ public class CraftWorld implements World { - public boolean unloadChunkRequest(int x, int z) { - org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot - if (isChunkLoaded(x, z)) { -- world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); -+ world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE); // Paper - } - - return true; -@@ -542,9 +556,12 @@ public class CraftWorld implements World { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot - // Paper start - Optimize this method - ChunkPos chunkPos = new ChunkPos(x, z); -+ ChunkAccess immediate = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); // Paper -+ if (immediate != null) return true; // Paper - - if (!generate) { -- ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z); -+ -+ //IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); // Paper - if (immediate == null) { - immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); - } -@@ -552,7 +569,7 @@ public class CraftWorld implements World { - if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) { - return false; // not full status - } -- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper - world.getChunk(x, z); // make sure we're at ticket level 32 or lower - return true; - } -@@ -579,7 +596,7 @@ public class CraftWorld implements World { - // we do this so we do not re-read the chunk data on disk - } - -- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper - world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); - return true; - // Paper end -@@ -2529,6 +2546,7 @@ public class CraftWorld implements World { - } - return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { - net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); -+ if (chunk != null) addTicket(x, z); // Paper - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); - }, net.minecraft.server.MinecraftServer.getServer()); - } diff --git a/Remapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch b/Remapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch deleted file mode 100644 index f86c4c1c6b..0000000000 --- a/Remapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: David Slovikosky -Date: Tue, 9 Jun 2020 00:10:03 -0700 -Subject: [PATCH] Fix missing chunks due to integer overflow - -This patch fixes a bug in the WorldChunkManagerTheEnd class where the distance -from 0,0 squared overflows the maximum size of an integer. The overflow leads -to hard chunk borders around 370,000 blocks from 0,0. After this cutoff there -is a few hundred thousand block gap before end land resuming to generate at -530,000 blocks from spawn. This is due to the integer flipping back and forth. - -The fix for the issue is quite simple, casting chunk coordinates to longs -allows the distance calculation to avoid overflow and work as intended. - -diff --git a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java -index af006c2e45e0a14367a0bc850c319024c6b82024..063369d3a64b4afc9cc6e1d20360900595e1a05f 100644 ---- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java -+++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java -@@ -75,7 +75,9 @@ public class TheEndBiomeSource extends BiomeSource { - int l = j / 2; - int i1 = i % 2; - int j1 = j % 2; -- float f = 100.0F - Mth.sqrt((float) (i * i + j * j)) * 8.0F; -+ // Paper start - cast ints to long to avoid integer overflow -+ float f = 100.0F - Mth.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; -+ // Paper end - - f = Mth.clamp(f, -100.0F, 80.0F); - diff --git a/Remapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/Remapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch deleted file mode 100644 index 423af0ebf9..0000000000 --- a/Remapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ossi -Date: Fri, 12 Jun 2020 01:38:06 +0300 -Subject: [PATCH] Fix CraftScheduler#runTaskTimerAsynchronously(Plugin, - Consumer, long, long) scheduling a non-repeating task instead of - a repeating one. - - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index ca90237a53c9a026919d28adaedf483ca3c7c2a8..13e461ffb2ee2e7d0440c0f60809ea99629b843c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -184,7 +184,7 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public void runTaskTimerAsynchronously(Plugin plugin, Consumer task, long delay, long period) throws IllegalArgumentException { -- runTaskTimerAsynchronously(plugin, (Object) task, delay, CraftTask.NO_REPEATING); -+ runTaskTimerAsynchronously(plugin, (Object) task, delay, period); - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch b/Remapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch deleted file mode 100644 index 1d54c7bad6..0000000000 --- a/Remapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 11 Jun 2020 17:29:42 -0700 -Subject: [PATCH] Fix piston physics inconsistency - MC-188840 - -Pistons invoke physics when they move blocks. The physics can cause -tnt blocks to ignite. However, pistons (when storing the blocks they "moved") -don't actually go back to the world state sometimes to check if something -like that happened. As a result they end up moving the tnt like it was -never ignited. This resulted in the ability to create machines -that can duplicate tnt, called "world eaters". -This patch makes the piston logic retrieve the block state from the world -prevent this from occuring. - -This patch also sets the moved pos to air immediately after creating -the moving piston TE. This prevents the block from being updated from -other physics calls by the piston. - -Tested against the following tnt duper design: -https://www.youtube.com/watch?v=mS7xxNGhjxs - -This patch also affects every type of machine that utilises -this mechanic. For example, dead coral is removed by a physics -update when being moved while it is attached to slimeblocks. - -Standard piston machines that don't destroy or modify the -blocks they move by physics updates should be entirely -unaffected. - -This patch fixes https://bugs.mojang.com/browse/MC-188840 - -This patch also fixes rail duping and carpet duping. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 7f140333c2e62012fa572c1a061d84432426997f..b67ba8f75e4a3358d7c2462918b85b0bf9b5a922 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -434,4 +434,10 @@ public class PaperConfig { - consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); - } - -+ public static boolean allowPistonDuplication; -+ private static void allowPistonDuplication() { -+ config.set("settings.unsupported-settings.allow-piston-duplication-readme", "This setting controls if player should be able to use TNT duplication, but this also allows duplicating carpet, rails and potentially other items"); -+ allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); -+ set("settings.unsupported-settings.allow-tnt-duplication", null); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -index 40a18302dd682e5ade4ec77ac7f316b6c0f8c112..44876557515eaa6bbe33344b3d3ba03aee58409f 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -@@ -398,12 +398,24 @@ public class PistonBaseBlock extends DirectionalBlock { - } - - for (k = list.size() - 1; k >= 0; --k) { -- blockposition3 = (BlockPos) list.get(k); -- iblockdata1 = world.getBlockState(blockposition3); -+ // Paper start - fix a variety of piston desync dupes -+ boolean allowDesync = com.destroystokyo.paper.PaperConfig.allowPistonDuplication; -+ BlockPos oldPos = blockposition3 = (BlockPos) list.get(k); -+ iblockdata1 = allowDesync ? world.getBlockState(oldPos) : null; -+ // Paper end - fix a variety of piston desync dupes - blockposition3 = blockposition3.relative(enumdirection1); - map.remove(blockposition3); - world.setBlock(blockposition3, (BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, dir), 68); -- world.setBlockEntity(blockposition3, MovingPistonBlock.newMovingBlockEntity((BlockState) list1.get(k), dir, retract, false)); -+ // Paper start - fix a variety of piston desync dupes -+ if (!allowDesync) { -+ iblockdata1 = world.getBlockState(oldPos); -+ map.replace(oldPos, iblockdata1); -+ } -+ world.setBlockEntity(blockposition3, MovingPistonBlock.newMovingBlockEntity(allowDesync ? list1.get(k) : iblockdata1, dir, retract, false)); -+ if (!allowDesync) { -+ world.setBlock(oldPos, Blocks.AIR.defaultBlockState(), 2 | 4 | 16 | 1024); // set air to prevent later physics updates from seeing this block -+ } -+ // Paper end - fix a variety of piston desync dupes - aiblockdata[j++] = iblockdata1; - } - -diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -index 73888713746e7ddd72ba9ac9d33d8e616eb3bd25..001e90da8b09e16b6df4849a5bac4f4821000c94 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -@@ -279,7 +279,7 @@ public class PistonMovingBlockEntity extends BlockEntity implements TickableBloc - BlockState iblockdata = Block.updateFromNeighbourShapes(this.movedState, (LevelAccessor) this.level, this.worldPosition); - - if (iblockdata.isAir()) { -- this.level.setBlock(this.worldPosition, this.movedState, 84); -+ this.level.setBlock(this.worldPosition, this.movedState, com.destroystokyo.paper.PaperConfig.allowPistonDuplication ? 84 : (84 | 2)); // Paper - force notify (flag 2), it's possible the set type by the piston block (which doesn't notify) set this block to air - Block.updateOrDestroy(this.movedState, iblockdata, this.level, this.worldPosition, 3); - } else { - if (iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) iblockdata.getValue(BlockStateProperties.WATERLOGGED)) { diff --git a/Remapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch b/Remapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch deleted file mode 100644 index d06a661655..0000000000 --- a/Remapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 12 Jun 2020 13:33:19 -0700 -Subject: [PATCH] Fix sand duping - -If the falling block dies during teleportation (entity#move), then we need -to detect that by placing a check after the move. - -diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -index ff8f7e4569a889ead1512b7c9908f9c5cad9eed5..2ba81e7179c7f9e2e1add1ad6bd6b96ee12c5da1 100644 ---- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -101,6 +101,11 @@ public class FallingBlockEntity extends Entity { - - @Override - public void tick() { -+ // Paper start - fix sand duping -+ if (this.removed) { -+ return; -+ } -+ // Paper end - fix sand duping - if (this.blockState.isAir()) { - this.remove(); - } else { -@@ -123,6 +128,12 @@ public class FallingBlockEntity extends Entity { - - this.move(MoverType.SELF, this.getDeltaMovement()); - -+ // Paper start - fix sand duping -+ if (this.removed) { -+ return; -+ } -+ // Paper end - fix sand duping -+ - // Paper start - Configurable EntityFallingBlock height nerf - if (this.level.paperConfig.fallingBlockHeightNerf != 0 && this.getY() > this.level.paperConfig.fallingBlockHeightNerf) { - if (this.dropItem && this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { diff --git a/Remapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch b/Remapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch deleted file mode 100644 index 9994f830fa..0000000000 --- a/Remapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 12 Jun 2020 16:51:39 -0700 -Subject: [PATCH] Prevent position desync in playerconnection causing tp - exploit - -Caused the server to revert to the player's overworld coordinates -after teleporting into the end. - -Sidenote: The underlying issue is that the move call can teleport -entities and do other things like kill the entity. In the future, -to fix all exploits derieved from this usually unexpected -behaviour, we need to move all of this dangerous logic outside -of the move call and into an appropriate place in the tick method. - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 0625bc7ffd07b66b27176fe62ae3061aa7c67df2..fbafb89cc63744d942933546026e272122bd9fba 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1324,6 +1324,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9)); - this.player.setOnGround(packet.isOnGround()); // CraftBukkit - SPIGOT-5810, SPIGOT-5835: reset by this.player.move -+ // Paper start - prevent position desync -+ if (this.awaitingPositionFromClient != null) { -+ return; // ... thanks Mojang for letting move calls teleport across dimensions. -+ } -+ // Paper end - prevent position desync - double d12 = d8; - - d7 = d4 - this.player.getX(); diff --git a/Remapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch b/Remapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch deleted file mode 100644 index 38690afc49..0000000000 --- a/Remapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 12 Jun 2020 22:25:11 -0700 -Subject: [PATCH] Fix enderdragon exp dupe - -Properly track death stage when unloading/loading in the -dragon - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index ec9436005a3a6fdfb4783d1092bb361224eb6414..b224a630f8adb1fa357c838e6b32c784aed0b15b 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -879,6 +879,7 @@ public class EnderDragon extends Mob implements Enemy { - public void addAdditionalSaveData(CompoundTag tag) { - super.addAdditionalSaveData(tag); - tag.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId()); -+ tag.putInt("Paper.DeathTick", this.dragonDeathTime); // Paper - } - - @Override -@@ -887,6 +888,7 @@ public class EnderDragon extends Mob implements Enemy { - if (tag.contains("DragonPhase")) { - this.phaseManager.setPhase(EnderDragonPhase.getById(tag.getInt("DragonPhase"))); - } -+ this.dragonDeathTime = tag.getInt("Paper.DeathTick"); // Paper - - } - diff --git a/Remapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch b/Remapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch deleted file mode 100644 index d25c9ffc5a..0000000000 --- a/Remapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Wed, 10 Jun 2020 23:55:15 +0100 -Subject: [PATCH] Inventory getHolder method without block snapshot - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index ef2d18d19a86b3701855aa1ac126462e663f8fcd..7ccc085228f373e6eba55d809bed480d43d5c211 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -10,6 +10,7 @@ import net.minecraft.world.inventory.PlayerEnderChestContainer; - import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; - import net.minecraft.world.level.block.entity.BarrelBlockEntity; - import net.minecraft.world.level.block.entity.BlastFurnaceBlockEntity; -+import net.minecraft.world.level.block.entity.BlockEntity; - import net.minecraft.world.level.block.entity.BrewingStandBlockEntity; - import net.minecraft.world.level.block.entity.DispenserBlockEntity; - import net.minecraft.world.level.block.entity.DropperBlockEntity; -@@ -525,6 +526,13 @@ public class CraftInventory implements Inventory { - return inventory.getOwner(); - } - -+ // Paper start - getHolder without snapshot -+ @Override -+ public InventoryHolder getHolder(boolean useSnapshot) { -+ return inventory instanceof BlockEntity ? ((BlockEntity) inventory).getOwner(useSnapshot) : getHolder(); -+ } -+ // Paper end -+ - @Override - public int getMaxStackSize() { - return inventory.getMaxStackSize(); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -index 3245dfa94410d319e53543c862c990e80ed3c72d..23dcf6e9332bd2b42ebb851497483e41948355d8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -@@ -64,6 +64,13 @@ public class CraftInventoryDoubleChest extends CraftInventory implements DoubleC - return new DoubleChest(this); - } - -+ // Paper start - getHolder without snapshot -+ @Override -+ public DoubleChest getHolder(boolean useSnapshot) { -+ return getHolder(); -+ } -+ // Paper end -+ - @Override - public Location getLocation() { - return getLeftSide().getLocation().add(getRightSide().getLocation()).multiply(0.5); diff --git a/Remapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch b/Remapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch deleted file mode 100644 index cafd641bc1..0000000000 --- a/Remapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nesaak <52047222+Nesaak@users.noreply.github.com> -Date: Sat, 23 May 2020 10:31:11 -0400 -Subject: [PATCH] Expose Arrow getItemStack - - -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 3ce431c1fdf1f5bd62b49f26cca188e939e98efa..6225f390b51733217a809910182f58acea1055e2 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -556,6 +556,7 @@ public abstract class AbstractArrow extends Projectile { - } - } - -+ public final ItemStack getOriginalItemStack() { return getPickupItem(); } // Paper - OBFHELPER - exists purely due to overrides all as protected and dont want to change them all - protected abstract ItemStack getPickupItem(); - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -index 5b898118a46007a85254931c7b5bd18d7cda99be..91d32aff07e81608a2f8ecb1301ef3c08533494b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -@@ -102,6 +102,13 @@ public class CraftArrow extends AbstractProjectile implements AbstractArrow { - getHandle().pickup = net.minecraft.world.entity.projectile.AbstractArrow.Pickup.byOrdinal(status.ordinal()); - } - -+ // Paper start -+ @Override -+ public org.bukkit.craftbukkit.inventory.CraftItemStack getItemStack() { -+ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(getHandle().getOriginalItemStack()); -+ } -+ //Paper end -+ - @Override - public void setTicksLived(int value) { - super.setTicksLived(value); diff --git a/Remapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch b/Remapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch deleted file mode 100644 index 412fc1c8ad..0000000000 --- a/Remapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Fri, 5 Jun 2020 18:24:06 -0400 -Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index fbafb89cc63744d942933546026e272122bd9fba..a0b2fc3fe59d97b9282a9451f35542b39df774e7 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2770,9 +2770,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); - this.player.resetLastActionTime(); - if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu.isSynched(this.player) && this.player.containerMenu instanceof RecipeBookMenu) { -- this.server.getRecipeManager().byKey(packet.getRecipe()).ifPresent((irecipe) -> { -- ((RecipeBookMenu) this.player.containerMenu).handlePlacement(packet.isShiftDown(), irecipe, this.player); -- }); -+ // Paper start - fire event for clicking recipes in the recipe book -+ com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent event = new com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent( -+ player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(packet.getRecipe()), packet.isShiftDown()); -+ if (event.callEvent()) { -+ this.server.getRecipeManager().byKey(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getRecipe())).ifPresent((irecipe) -> { -+ ((ContainerRecipeBook) this.player.activeContainer).a(event.isMakeAll(), irecipe, this.player); -+ }); -+ } -+ // Paper end - } - } - diff --git a/Remapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch b/Remapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch deleted file mode 100644 index 43a0839a47..0000000000 --- a/Remapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 26 Jun 2020 22:35:08 -0700 -Subject: [PATCH] Hide sync chunk writes behind flag - -Syncing writes on each write call has terrible performance -on harddrives. - --DPaper.enable-sync-chunk-writes=true to enable - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index 545096d9ba403396b6aaa7bb6d912f2de08a967e..3450a58fc02a472eb710aa1a31f6fecefc982b6f 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -@@ -108,7 +108,7 @@ public class DedicatedServerProperties extends Settings { - return Mth.clamp(integer, 1, 29999984); - }, 29999984); -- this.syncChunkWrites = this.get("sync-chunk-writes", true); -+ this.syncChunkWrites = this.get("sync-chunk-writes", true) && Boolean.getBoolean("Paper.enable-sync-chunk-writes"); // Paper - hide behind flag - this.enableJmxMonitoring = this.get("enable-jmx-monitoring", false); - this.enableStatus = this.get("enable-status", true); - this.entityBroadcastRangePercentage = this.get("entity-broadcast-range-percentage", (integer) -> { diff --git a/Remapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch b/Remapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch deleted file mode 100644 index 1f74c2ced9..0000000000 --- a/Remapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Fri, 14 Sep 2018 17:42:08 +0200 -Subject: [PATCH] Limit lightning strike effect distance - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1655bca0502e7b871de4addaa163536d86547a02..978062774c1db286bfb9b0ffdef19d880b1f249b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -646,4 +646,26 @@ public class PaperWorldConfig { - delayChunkUnloadsBy *= 20; - } - } -+ -+ public double sqrMaxThunderDistance; -+ public double sqrMaxLightningImpactSoundDistance; -+ public double maxLightningFlashDistance; -+ private void lightningStrikeDistanceLimit() { -+ sqrMaxThunderDistance = getInt("lightning-strike-distance-limit.sound", -1); -+ if (sqrMaxThunderDistance > 0) { -+ sqrMaxThunderDistance *= sqrMaxThunderDistance; -+ } -+ -+ sqrMaxLightningImpactSoundDistance = getInt("lightning-strike-distance-limit.impact-sound", -1); -+ if (sqrMaxLightningImpactSoundDistance < 0) { -+ sqrMaxLightningImpactSoundDistance = 32 * 32; //Vanilla value -+ } else { -+ sqrMaxLightningImpactSoundDistance *= sqrMaxLightningImpactSoundDistance; -+ } -+ -+ maxLightningFlashDistance = getInt("lightning-strike-distance-limit.flash", -1); -+ if (maxLightningFlashDistance < 0) { -+ maxLightningFlashDistance = 512; // Vanilla value -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java -index e030e7f3d8bd9fe6578df0b560a237d494ec8a01..4b0dbeded2b8a475d32f518957909d3495a4b6fc 100644 ---- a/src/main/java/net/minecraft/world/entity/LightningBolt.java -+++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java -@@ -15,7 +15,6 @@ import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.world.Difficulty; --import net.minecraft.world.entity.player.Player; - import net.minecraft.world.level.BlockGetter; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.Level; -@@ -74,6 +73,17 @@ public class LightningBolt extends Entity { - double deltaX = this.getX() - player.getX(); - double deltaZ = this.getZ() - player.getZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -+ // Paper start - Limit lightning strike effect distance -+ if (distanceSquared <= this.level.paperConfig.sqrMaxLightningImpactSoundDistance) { -+ player.connection.send(new ClientboundSoundPacket(SoundEvents.LIGHTNING_BOLT_IMPACT, -+ SoundSource.WEATHER, this.getX(), this.getY(), this.getZ(), 2.0f, 0.5F + this.random.nextFloat() * 0.2F)); -+ } -+ -+ if (level.paperConfig.sqrMaxThunderDistance != -1 && distanceSquared >= level.paperConfig.sqrMaxThunderDistance) { -+ continue; -+ } -+ -+ // Paper end - if (distanceSquared > viewDistance * viewDistance) { - double deltaLength = Math.sqrt(distanceSquared); - double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance; -@@ -84,7 +94,7 @@ public class LightningBolt extends Entity { - } - } - // CraftBukkit end -- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_IMPACT, SoundSource.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); -+// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); // Paper - Limit lightning strike effect distance (the packet is now sent from inside the loop) - } - - --this.life; diff --git a/Remapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch b/Remapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch deleted file mode 100644 index 9e0fdeee13..0000000000 --- a/Remapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 16 May 2020 10:05:30 +0200 -Subject: [PATCH] Add permission for command blocks - - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index af048ab682612233c01f7087d7b8afbf7e58945b..79f3e4176145c42debb9adc1e68175cf063c1f22 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -386,7 +386,7 @@ public class ServerPlayerGameMode { - BlockEntity tileentity = this.level.getBlockEntity(pos); - Block block = iblockdata.getBlock(); - -- if ((block instanceof CommandBlock || block instanceof StructureBlock || block instanceof JigsawBlock) && !this.player.canUseGameMasterBlocks()) { -+ if ((block instanceof CommandBlock || block instanceof StructureBlock || block instanceof JigsawBlock) && !this.player.canUseGameMasterBlocks() && !(block instanceof CommandBlock && (this.player.isCreative() && this.player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission - this.level.sendBlockUpdated(pos, iblockdata, iblockdata, 3); - return false; - } else if (this.player.blockActionRestricted((Level) this.level, pos, this.gameModeForPlayer)) { -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index a0b2fc3fe59d97b9282a9451f35542b39df774e7..471370a9aafa3eda83beb4097c6233650bd155ee 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -796,7 +796,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); - if (!this.server.isCommandBlockEnabled()) { - this.player.sendMessage(new TranslatableComponent("advMode.notEnabled"), Util.NIL_UUID); -- } else if (!this.player.canUseGameMasterBlocks()) { -+ } else if (!this.player.canUseGameMasterBlocks() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission - this.player.sendMessage(new TranslatableComponent("advMode.notAllowed"), Util.NIL_UUID); - } else { - BaseCommandBlock commandblocklistenerabstract = null; -@@ -859,7 +859,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); - if (!this.server.isCommandBlockEnabled()) { - this.player.sendMessage(new TranslatableComponent("advMode.notEnabled"), Util.NIL_UUID); -- } else if (!this.player.canUseGameMasterBlocks()) { -+ } else if (!this.player.canUseGameMasterBlocks() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission - this.player.sendMessage(new TranslatableComponent("advMode.notAllowed"), Util.NIL_UUID); - } else { - BaseCommandBlock commandblocklistenerabstract = packet.getCommandBlock(this.player.level); -diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java -index 00dc4cd436023b946d7005f17a7ba983a4bbdfb6..23500428abf5e7daec19f8fb3c24e6c5361f0819 100644 ---- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java -+++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java -@@ -192,7 +192,7 @@ public abstract class BaseCommandBlock implements CommandSource { - } - - public InteractionResult usedBy(Player player) { -- if (!player.canUseGameMasterBlocks()) { -+ if (!player.canUseGameMasterBlocks() && !player.isCreative() && !player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission - return InteractionResult.PASS; - } else { - if (player.getCommandSenderWorld().isClientSide) { -diff --git a/src/main/java/net/minecraft/world/level/block/CommandBlock.java b/src/main/java/net/minecraft/world/level/block/CommandBlock.java -index 088d78905732cacf69beb7a4b713dac4bec82220..c5e81e7d67504b1bc2a87c0b577bb93be4a57e9c 100644 ---- a/src/main/java/net/minecraft/world/level/block/CommandBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/CommandBlock.java -@@ -128,7 +128,7 @@ public class CommandBlock extends BaseEntityBlock { - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - BlockEntity tileentity = world.getBlockEntity(pos); - -- if (tileentity instanceof CommandBlockEntity && player.canUseGameMasterBlocks()) { -+ if (tileentity instanceof CommandBlockEntity && (player.canUseGameMasterBlocks() || (player.isCreative() && player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission - player.openCommandBlock((CommandBlockEntity) tileentity); - return InteractionResult.sidedSuccess(world.isClientSide); - } else { -diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java -index 525ebf961e5da0687183a5e2ead23ed92cbd9d79..a4a809f302c5ff9c76cde5fc0add2ceec1bdf9b5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java -@@ -16,6 +16,7 @@ public final class CraftDefaultPermissions { - DefaultPermissions.registerPermission(ROOT + ".nbt.copy", "Gives the user the ability to copy NBT in creative", org.bukkit.permissions.PermissionDefault.TRUE, parent); - DefaultPermissions.registerPermission(ROOT + ".debugstick", "Gives the user the ability to use the debug stick in creative", org.bukkit.permissions.PermissionDefault.OP, parent); - DefaultPermissions.registerPermission(ROOT + ".debugstick.always", "Gives the user the ability to use the debug stick in all game modes", org.bukkit.permissions.PermissionDefault.FALSE, parent); -+ DefaultPermissions.registerPermission(ROOT + ".commandblock", "Gives the user the ability to use command blocks.", org.bukkit.permissions.PermissionDefault.OP, parent); // Paper - // Spigot end - parent.recalculatePermissibles(); - } diff --git a/Remapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch b/Remapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch deleted file mode 100644 index f77fef5ea0..0000000000 --- a/Remapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 May 2020 22:12:46 -0400 -Subject: [PATCH] Ensure Entity AABB's are never invalid - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d9bb00752ac81b2171d3ad25fd84904467a18e3b..728379292728cf58f5512feae3cdc74392980f68 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -66,6 +66,7 @@ import net.minecraft.world.Nameable; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.animal.AbstractFish; - import net.minecraft.world.entity.animal.Animal; -+import net.minecraft.world.entity.decoration.HangingEntity; - import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.vehicle.AbstractMinecart; -@@ -478,7 +479,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - - public void setPos(double x, double y, double z) { - this.setPosRaw(x, y, z); -- this.setBoundingBox(this.dimensions.makeBoundingBox(x, y, z)); -+ //this.a(this.size.a(d0, d1, d2)); // Paper - move into setPositionRaw - if (valid) ((ServerLevel) level).updateChunkPos(this); // CraftBukkit - } - -@@ -2998,6 +2999,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return new AABB(vec3d, vec3d1); - } - -+ public final void setBoundingBox(AABB axisalignedbb) { setBoundingBox(axisalignedbb); } // Paper - OBFHELPER - public void setBoundingBox(AABB boundingBox) { - // CraftBukkit start - block invalid bounding boxes - double minX = boundingBox.minX, -@@ -3436,6 +3438,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public void setPosRaw(double x, double y, double z) { -+ // Paper start - never allow AABB to become desynced from position -+ // hanging has its own special logic -+ if (!(this instanceof HangingEntity) && (this.position.x != x || this.position.y != y || this.position.z != z)) { -+ this.setBoundingBox(this.dimensions.makeBoundingBox(x, y, z)); -+ } -+ // Paper end - if (this.position.x != x || this.position.y != y || this.position.z != z) { - this.position = new Vec3(x, y, z); - int i = Mth.floor(x); diff --git a/Remapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch b/Remapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch deleted file mode 100644 index bc82f5847c..0000000000 --- a/Remapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 10 May 2020 22:49:05 -0400 -Subject: [PATCH] Optimize WorldBorder collision checks and air - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 728379292728cf58f5512feae3cdc74392980f68..e9a658b11e2b6683831dc3f5bd20be9a7840ed69 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -102,7 +102,6 @@ import net.minecraft.world.phys.AABB; - import net.minecraft.world.phys.HitResult; - import net.minecraft.world.phys.Vec2; - import net.minecraft.world.phys.Vec3; --import net.minecraft.world.phys.shapes.BooleanOp; - import net.minecraft.world.phys.shapes.CollisionContext; - import net.minecraft.world.phys.shapes.Shapes; - import net.minecraft.world.phys.shapes.VoxelShape; -@@ -908,7 +907,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - AABB axisalignedbb = this.getBoundingBox(); - CollisionContext voxelshapecollision = CollisionContext.of(this); - VoxelShape voxelshape = this.level.getWorldBorder().getCollisionShape(); -- Stream stream = Shapes.joinIsNotEmpty(voxelshape, Shapes.create(axisalignedbb.deflate(1.0E-7D)), BooleanOp.AND) ? Stream.empty() : Stream.of(voxelshape); -+ Stream stream = !this.level.getWorldBorder().isInBounds(axisalignedbb) ? Stream.empty() : Stream.of(voxelshape); // Paper - Stream stream1 = this.level.getEntityCollisions(this, axisalignedbb.expandTowards(movement), (entity) -> { - return true; - }); -diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -index feca9ff34936686c0665ae0dbc926869087df3a7..60f8585a736af5b654b8aaed89a39a8bf5e91301 100644 ---- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -+++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -@@ -143,10 +143,10 @@ public class CollisionSpliterator extends AbstractSpliterator { - AABB axisalignedbb = this.source.getBoundingBox(); - - if (!isBoxFullyWithinWorldBorder(worldborder, axisalignedbb)) { -- VoxelShape voxelshape = worldborder.getCollisionShape(); -- -- if (!isOutsideBorder(voxelshape, axisalignedbb) && isCloseToBorder(voxelshape, axisalignedbb)) { -- consumer.accept(voxelshape); -+ // Paper start -+ if (worldborder.isInBounds(axisalignedbb.deflate(1.0E-7D)) && !worldborder.isInBounds(axisalignedbb.grow(1.0E-7D))) { -+ consumer.accept(worldborder.asVoxelShape()); -+ // Paper end - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 7a728ca96ee2eaf776c391ba8351196a526e18ec..aaa6251838483de5c46913534413151b5cb1d3fe 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -52,6 +52,7 @@ public class WorldBorder { - return (double) pos.getMaxBlockX() > this.getMinX() && (double) pos.getMinBlockX() < this.getMaxX() && (double) pos.getMaxBlockZ() > this.getMinZ() && (double) pos.getMinBlockZ() < this.getMaxZ(); - } - -+ public final boolean isInBounds(AABB aabb) { return this.isWithinBounds(aabb); } // Paper - OBFHELPER - public boolean isWithinBounds(AABB box) { - return box.maxX > this.getMinX() && box.minX < this.getMaxX() && box.maxZ > this.getMinZ() && box.minZ < this.getMaxZ(); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -index 1603eb3f7d90a4b3a028b20776566db77d09c123..f28d2126bc29fad3971a32cf85a7a7c4803b36ab 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -@@ -252,7 +252,7 @@ public final class Shapes { - BlockState iblockdata = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper - if (iblockdata == null) return 0.0D; // Paper - -- if ((k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { -+ if (!iblockdata.isAir() && (k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { // Paper - initial = iblockdata.getCollisionShape((BlockGetter) world, blockposition_mutableblockposition, context).collide(enumdirection_enumaxis2, box.move((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), initial); - if (Math.abs(initial) < 1.0E-7D) { - return 0.0D; diff --git a/Remapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/Remapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch deleted file mode 100644 index 568d1c34e6..0000000000 --- a/Remapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 03:59:10 -0400 -Subject: [PATCH] Fix Per World Difficulty / Remembering Difficulty - -Fixes per world difficulty with /difficulty command and also -makes it so that the server keeps the last difficulty used instead -of restoring the server.properties every single load. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f530c739b6aee3718eb5d0e0e6a09d882d817c68..19544b794b5a46c129016172798ff7294fcfed33 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1645,11 +1645,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Sun, 28 Jun 2020 19:27:20 -0400 -Subject: [PATCH] Paper dumpitem command - -Let's you quickly view the item in your hands NBT data - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 528c860fc0c04431e0ebb2ae6bc96bf9c2d04789..6fad9329213e4e8a3ef9ce7fb568ad22484a11f3 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -12,6 +12,7 @@ import com.google.gson.JsonObject; - import com.google.gson.internal.Streams; - import com.google.gson.stream.JsonWriter; - import net.minecraft.core.BlockPos; -+import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.MCUtil; -@@ -36,7 +37,9 @@ import org.bukkit.command.CommandSender; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.entity.CraftPlayer; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; - import org.bukkit.entity.Player; -+import org.bukkit.inventory.ItemStack; - - import java.io.File; - import java.io.FileOutputStream; -@@ -59,7 +62,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight", "dumpitem").build(); - - public PaperCommand(String name) { - super(name); -@@ -168,6 +171,9 @@ public class PaperCommand extends Command { - case "reload": - doReload(sender); - break; -+ case "dumpitem": -+ doDumpItem(sender); -+ break; - case "debug": - doDebug(sender, args); - break; -@@ -200,6 +206,19 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doDumpItem(CommandSender sender) { -+ ItemStack itemInHand = ((CraftPlayer) sender).getItemInHand(); -+ net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(itemInHand); -+ CompoundTag tag = itemStack.getTag(); -+ if (tag != null) { -+ String nbt = org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(tag.getNbtPrettyComponent()); -+ Bukkit.getConsoleSender().sendMessage(nbt); -+ sender.sendMessage(nbt); -+ } else { -+ sender.sendMessage("Item does not have NBT"); -+ } -+ } -+ - private void doFixLight(CommandSender sender, String[] args) { - if (!(sender instanceof Player)) { - sender.sendMessage("Only players can use this command"); -diff --git a/src/main/java/net/minecraft/nbt/Tag.java b/src/main/java/net/minecraft/nbt/Tag.java -index 85e9c5f4620fcf48cb3655fbb2db58b3fb31aa74..ba204cf135be333d4ac1c06ee6c2e961faadf8cb 100644 ---- a/src/main/java/net/minecraft/nbt/Tag.java -+++ b/src/main/java/net/minecraft/nbt/Tag.java -@@ -26,6 +26,7 @@ public interface Tag { - return this.toString(); - } - -+ default Component getNbtPrettyComponent() { return this.getPrettyDisplay(); } // Paper - OBFHELPER - default Component getPrettyDisplay() { - return this.getPrettyDisplay("", 0); - } diff --git a/Remapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch b/Remapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch deleted file mode 100644 index dfc52a21c5..0000000000 --- a/Remapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 19:36:55 -0400 -Subject: [PATCH] Don't allow null UUID's for chat - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -index 002a6c7933f64405707d7d34d3e5c17584539623..a983785bf3bc43f65bd0809870c14a9fd30a3fc1 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -@@ -3,6 +3,7 @@ package net.minecraft.network.protocol.game; - - import java.io.IOException; - import java.util.UUID; -+import net.minecraft.Util; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.chat.ChatType; - import net.minecraft.network.chat.Component; -@@ -21,7 +22,7 @@ public class ClientboundChatPacket implements Packet { - public ClientboundChatPacket(Component message, ChatType location, UUID senderUuid) { - this.message = message; - this.type = location; -- this.sender = senderUuid; -+ this.sender = senderUuid != null ? senderUuid : Util.getNullUUID(); // Paper - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch b/Remapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch deleted file mode 100644 index 2f031e9064..0000000000 --- a/Remapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 19:08:41 -0400 -Subject: [PATCH] Improve Legacy Component serialization size - -Don't constantly send format: false for all formatting options when parent already -has it false - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -index b27af66795d902a2e95d692fa0ff18eccbef8a75..b89660244ffad484e3fbf69ccb9cdc1bc178d2ad 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -@@ -46,6 +46,7 @@ public final class CraftChatMessage { - // Separate pattern with no group 3, new lines are part of previous string - private static final Pattern INCREMENTAL_PATTERN_KEEP_NEWLINES = Pattern.compile("(" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + "[0-9a-fk-orx])|((?:(?:https?):\\/\\/)?(?:[-\\w_\\.]{2,}\\.[a-z]{2,4}.*?(?=[\\.\\?!,;:]?(?:[" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + " ]|$))))", Pattern.CASE_INSENSITIVE); - // ChatColor.b does not explicitly reset, its more of empty -+ private static final Style EMPTY = Style.EMPTY.withItalic(false); // Paper - OBFHELPER - private static final Style RESET = Style.EMPTY.withBold(false).withItalic(false).setUnderline(false).setStrikethrough(false).setRandom(false); - - private final List list = new ArrayList(); -@@ -67,6 +68,7 @@ public final class CraftChatMessage { - Matcher matcher = (keepNewlines ? INCREMENTAL_PATTERN_KEEP_NEWLINES : INCREMENTAL_PATTERN).matcher(message); - String match = null; - boolean needsAdd = false; -+ boolean hasReset = false; // Paper - while (matcher.find()) { - int groupId = 0; - while ((match = matcher.group(++groupId)) == null) { -@@ -112,7 +114,26 @@ public final class CraftChatMessage { - throw new AssertionError("Unexpected message format"); - } - } else { // Color resets formatting -- modifier = RESET.withColor(format); -+ // Paper start - improve legacy formatting -+ Style previous = modifier; -+ modifier = (!hasReset ? RESET : EMPTY).withColor(format); -+ hasReset = true; -+ if (previous.isBold()) { -+ modifier = modifier.withBold(false); -+ } -+ if (previous.isItalic()) { -+ modifier = modifier.withItalic(false); -+ } -+ if (previous.isObfuscated()) { -+ modifier = modifier.setRandom(false); -+ } -+ if (previous.isStrikethrough()) { -+ modifier = modifier.setStrikethrough(false); -+ } -+ if (previous.isUnderlined()) { -+ modifier = modifier.setUnderline(false); -+ } -+ // Paper end - } - needsAdd = true; - break; diff --git a/Remapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch b/Remapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch deleted file mode 100644 index ffba727ac3..0000000000 --- a/Remapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Jun 2020 03:26:17 -0400 -Subject: [PATCH] Support old UUID format for NBT - -We have stored UUID in plenty of places that did not get DFU'd - -So just look for old format and load it if it exists. - -diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java -index c856ca720a9329a94bb07eaa3060c034f95718b3..0b739b5f040697049893d311c99456dbc5470e93 100644 ---- a/src/main/java/net/minecraft/nbt/CompoundTag.java -+++ b/src/main/java/net/minecraft/nbt/CompoundTag.java -@@ -142,6 +142,12 @@ public class CompoundTag implements Tag { - - public void setUUID(String prefix, UUID uuid) { putUUID(prefix, uuid); } // Paper - OBFHELPER - public void putUUID(String key, UUID value) { -+ // Paper start - support old format -+ if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { -+ this.tags.remove(key + "Most"); -+ this.tags.remove(key + "Least"); -+ } -+ // Paper end - this.tags.put(key, NbtUtils.createUUID(value)); - } - -@@ -151,11 +157,21 @@ public class CompoundTag implements Tag { - */ - public UUID getUUID(String prefix) { return getUUID(prefix); } // Paper - OBFHELPER - public UUID getUUID(String key) { -+ // Paper start - support old format -+ if (!contains(key, 11) && this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { -+ return new UUID(this.getLong(key + "Most"), this.getLong(key + "Least")); -+ } -+ // Paper end - return NbtUtils.loadUUID(this.get(key)); - } - - public final boolean hasUUID(String s) { return this.hasUUID(s); } // Paper - OBFHELPER - public boolean hasUUID(String key) { -+ // Paper start - support old format -+ if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { -+ return true; -+ } -+ // Paper end - Tag nbtbase = this.get(key); - - return nbtbase != null && nbtbase.getType() == IntArrayTag.TYPE && ((IntArrayTag) nbtbase).getAsIntArray().length == 4; -diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java -index bf0da04ec9db3ec8313bddb06c278c13073819d1..f57c5e441045a81072a2edfed0f199d90e6d7fde 100644 ---- a/src/main/java/net/minecraft/nbt/NbtUtils.java -+++ b/src/main/java/net/minecraft/nbt/NbtUtils.java -@@ -40,6 +40,11 @@ public final class NbtUtils { - s = tag.getString("Name"); - } - -+ // Paper start - support string UUID's -+ if (tag.contains("Id", 8)) { -+ uuid = UUID.fromString(tag.getString("Id")); -+ } -+ // Paper end - if (tag.hasUUID("Id")) { - uuid = tag.getUUID("Id"); - } diff --git a/Remapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch b/Remapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch deleted file mode 100644 index 40c9060216..0000000000 --- a/Remapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 1 Jul 2020 03:12:06 -0400 -Subject: [PATCH] Clean up duplicated GameProfile Properties - -We had a bug where we accidently cloned properties resulting in skulls -growing to large sizes and preventing login. - -This now automatically cleans up the extra properties. - -diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java -index f57c5e441045a81072a2edfed0f199d90e6d7fde..3abfd21ea84c54aec6256008b3b9e6bbc7ae694c 100644 ---- a/src/main/java/net/minecraft/nbt/NbtUtils.java -+++ b/src/main/java/net/minecraft/nbt/NbtUtils.java -@@ -59,8 +59,8 @@ public final class NbtUtils { - while (iterator.hasNext()) { - String s1 = (String) iterator.next(); - ListTag nbttaglist = nbttagcompound1.getList(s1, 10); -- -- for (int i = 0; i < nbttaglist.size(); ++i) { -+ if (nbttaglist.size() == 0) continue; // Paper - remove duplicate properties -+ for (int i = nbttaglist.size() - 1; i < nbttaglist.size(); ++i) { // Paper - remove duplicate properties - CompoundTag nbttagcompound2 = nbttaglist.getCompound(i); - String s2 = nbttagcompound2.getString("Value"); - -@@ -246,7 +246,7 @@ public final class NbtUtils { - Optional optional = property.getValue(propertiesTag.getString(key)); - - if (optional.isPresent()) { -- return (StateHolder) state.setValue(property, (Comparable) optional.get()); -+ return state.setValue(property, optional.get()); // Paper - decompile error - } else { - NbtUtils.LOGGER.warn("Unable to read property: {} with value: {} for blockstate: {}", key, propertiesTag.getString(key), mainTag.toString()); - return state; -@@ -276,8 +276,8 @@ public final class NbtUtils { - return nbttagcompound; - } - -- private static > String getName(net.minecraft.world.level.block.state.properties.Property property, Comparable value) { -- return property.value(value); -+ private static > String getName(net.minecraft.world.level.block.state.properties.Property property, Comparable value) {// Paper - decompile error -+ return property.getName((T) value);// Paper - decompile error - } - - public static CompoundTag update(DataFixer fixer, DataFixTypes fixTypes, CompoundTag tag, int oldVersion) { -diff --git a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java -index 1cb67832a849db96f1cce95c32b41574e990e5b7..d97be7a1dfa7ad413afb8ff7668189fd37baf264 100644 ---- a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java -+++ b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java -@@ -59,6 +59,18 @@ public class PlayerHeadItem extends StandingAndWallBlockItem { - return true; - } else { - // CraftBukkit start -+ // Paper start - clean up old duplicated properties -+ CompoundTag properties = tag.getCompound("SkullOwner").getCompound("Properties"); -+ for (String key : properties.getAllKeys()) { -+ net.minecraft.nbt.ListTag values = properties.getList(key, 10); -+ if (values.size() > 1) { -+ net.minecraft.nbt.Tag texture = values.get(values.size() - 1); -+ values = new net.minecraft.nbt.ListTag(); -+ values.add(texture); -+ properties.put(key, values); -+ } -+ } -+ // Paper end - net.minecraft.nbt.ListTag textures = tag.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts - for (int i = 0; i < textures.size(); i++) { - if (textures.get(i) instanceof CompoundTag && !((CompoundTag) textures.get(i)).contains("Signature", 8) && ((CompoundTag) textures.get(i)).getString("Value").trim().isEmpty()) { diff --git a/Remapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch b/Remapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch deleted file mode 100644 index 9306e47d2d..0000000000 --- a/Remapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 1 Jul 2020 04:50:22 -0400 -Subject: [PATCH] Convert legacy attributes in Item Meta - - -diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -index 2d547810125f00680ef7e60dd791d0bddd9ebd3e..320fd6780af2fa99e4e4f4193cbc9338d492dc6d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -@@ -11,6 +11,20 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; - public class CraftAttributeMap implements Attributable { - - private final AttributeMap handle; -+ // Paper start - convert legacy attributes -+ private static final com.google.common.collect.ImmutableMap legacyNMS = com.google.common.collect.ImmutableMap.builder().put("generic.maxHealth", "generic.max_health").put("Max Health", "generic.max_health").put("zombie.spawnReinforcements", "zombie.spawn_reinforcements").put("Spawn Reinforcements Chance", "zombie.spawn_reinforcements").put("horse.jumpStrength", "horse.jump_strength").put("Jump Strength", "horse.jump_strength").put("generic.followRange", "generic.follow_range").put("Follow Range", "generic.follow_range").put("generic.knockbackResistance", "generic.knockback_resistance").put("Knockback Resistance", "generic.knockback_resistance").put("generic.movementSpeed", "generic.movement_speed").put("Movement Speed", "generic.movement_speed").put("generic.flyingSpeed", "generic.flying_speed").put("Flying Speed", "generic.flying_speed").put("generic.attackDamage", "generic.attack_damage").put("generic.attackKnockback", "generic.attack_knockback").put("generic.attackSpeed", "generic.attack_speed").put("generic.armorToughness", "generic.armor_toughness").build(); -+ -+ public static String convertIfNeeded(String nms) { -+ if (nms == null) { -+ return null; -+ } -+ nms = legacyNMS.getOrDefault(nms, nms); -+ if (!nms.toLowerCase().equals(nms) || nms.indexOf(' ') != -1) { -+ return null; -+ } -+ return nms; -+ } -+ // Paper end - - public CraftAttributeMap(AttributeMap handle) { - this.handle = handle; -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 45abfebf3f947dcbd2e7b1d95be8ba918f044e51..cb66998dbaa9d93e92ef4045b83efbb0fd486234 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -480,7 +480,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - - AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); - -- String attributeName = entry.getString(ATTRIBUTES_IDENTIFIER.NBT); -+ String attributeName = CraftAttributeMap.convertIfNeeded(entry.getString(ATTRIBUTES_IDENTIFIER.NBT)); // Paper - if (attributeName == null || attributeName.isEmpty()) { - continue; - } diff --git a/Remapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch b/Remapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch deleted file mode 100644 index 26f90fc29a..0000000000 --- a/Remapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Mon, 29 Jun 2020 17:03:06 -0400 -Subject: [PATCH] Remove some streams from structures - -This showed up a lot in the spark profiler, should have a low-medium performance improvement. - -diff --git a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java -index e842dbc586234799a05b6df213b686e17b8ed1ac..2f88e015708cadb43a348ba2b144c3dd92bb95a5 100644 ---- a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java -+++ b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java -@@ -2,21 +2,22 @@ - package net.minecraft.world.level; - - import com.mojang.datafixers.DataFixUtils; -+import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper - import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; - import net.minecraft.core.SectionPos; --import net.minecraft.core.Vec3i; - import net.minecraft.server.level.WorldGenRegion; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.FeatureAccess; - import net.minecraft.world.level.levelgen.WorldGenSettings; - import net.minecraft.world.level.levelgen.feature.StructureFeature; -+import net.minecraft.world.level.levelgen.structure.StructurePiece; - import net.minecraft.world.level.levelgen.structure.StructureStart; - - public class StructureFeatureManager { - -- private final LevelAccessor level; -+ private final LevelAccessor level; public LevelAccessor getLevel() { return level; } // Paper - OBFHELPER - private final WorldGenSettings worldGenSettings; - - public StructureFeatureManager(LevelAccessor world, WorldGenSettings options) { -@@ -42,6 +43,20 @@ public class StructureFeatureManager { - }); - } - -+ // Paper start - remove structure streams -+ public java.util.List> getFeatureStarts(SectionPos sectionPosition, StructureFeature structureGenerator) { -+ java.util.List> list = new ObjectArrayList<>(); -+ for (Long curLong: getLevel().getChunk(sectionPosition.x(), sectionPosition.z(), ChunkStatus.STRUCTURE_REFERENCES).getReferencesForFeature(structureGenerator)) { -+ SectionPos sectionPosition1 = SectionPos.of(new ChunkPos(curLong), 0); -+ StructureStart structurestart = getStartForFeature(sectionPosition1, structureGenerator, getLevel().getChunk(sectionPosition1.x(), sectionPosition1.z(), ChunkStatus.STRUCTURE_STARTS)); -+ if (structurestart != null && structurestart.e()) { -+ list.add(structurestart); -+ } -+ } -+ return list; -+ } -+ // Paper end -+ - @Nullable - public StructureStart getStartForFeature(SectionPos pos, StructureFeature feature, FeatureAccess holder) { - return holder.getStartForFeature(feature); -@@ -60,13 +75,21 @@ public class StructureFeatureManager { - } - - public StructureStart getStructureAt(BlockPos pos, boolean matchChildren, StructureFeature feature) { -- return (StructureStart) DataFixUtils.orElse(this.startsForFeature(SectionPos.of(pos), feature).filter((structurestart) -> { -- return structurestart.c().b((Vec3i) pos); -- }).filter((structurestart) -> { -- return !matchChildren || structurestart.d().stream().anyMatch((structurepiece) -> { -- return structurepiece.g().b((BaseBlockPosition) blockposition); -- }); -- }).findFirst(), StructureStart.a); -+ // Paper start - remove structure streams -+ for (StructureStart structurestart : getFeatureStarts(SectionPos.of(pos), feature)) { -+ if (structurestart.c().b(pos)) { -+ if (!matchChildren) { -+ return structurestart; -+ } -+ for (StructurePiece structurepiece : structurestart.d()) { -+ if (structurepiece.g().b(pos)) { -+ return structurestart; -+ } -+ } -+ } -+ } -+ return StructureStart.a; -+ // Paper end - } - - // Spigot start -diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java -index ed83335175bb882741dfaef251ab30ce1590f74c..2422dbb8691b8c45401a68602a33d4d7f1718dfb 100644 ---- a/src/main/java/net/minecraft/world/level/biome/Biome.java -+++ b/src/main/java/net/minecraft/world/level/biome/Biome.java -@@ -39,6 +39,7 @@ import net.minecraft.world.level.levelgen.WorldgenRandom; - import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; - import net.minecraft.world.level.levelgen.feature.StructureFeature; - import net.minecraft.world.level.levelgen.structure.BoundingBox; -+import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder; - import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise; - import net.minecraft.world.level.material.FluidState; -@@ -238,9 +239,11 @@ public final class Biome { - int l1 = j1 << 4; - - try { -- structureAccessor.startsForFeature(SectionPos.of(pos), structuregenerator).forEach((structurestart) -> { -- structurestart.a(region, structureAccessor, chunkGenerator, random, new BoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkPos(i1, j1)); -- }); -+ // Paper start - remove structure streams -+ for (StructureStart structureStart : structureAccessor.getFeatureStarts(SectionPos.of(pos), structuregenerator)) { -+ structureStart.a(region, structureAccessor, chunkGenerator, random, new BoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkPos(i1, j1)); -+ } -+ // Paper end - } catch (Exception exception) { - CrashReport crashreport = CrashReport.forThrowable(exception, "Feature placement"); - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -index 04adec255e4650ead8d80bee32a681c98686fb95..20f3899b7e39033ebc0f833e75fbdba29777a168 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -@@ -41,6 +41,7 @@ import net.minecraft.world.level.levelgen.feature.structures.StructureTemplatePo - import net.minecraft.world.level.levelgen.structure.BoundingBox; - import net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece; - import net.minecraft.world.level.levelgen.structure.StructurePiece; -+import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.synth.ImprovedNoise; - import net.minecraft.world.level.levelgen.synth.PerlinNoise; - import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise; -@@ -455,7 +456,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - while (iterator.hasNext()) { - StructureFeature structuregenerator = (StructureFeature) iterator.next(); - -- accessor.startsForFeature(SectionPos.of(chunkcoordintpair, 0), structuregenerator).forEach((structurestart) -> { -+ for (StructureStart structurestart : accessor.getFeatureStarts(SectionPos.of(chunkcoordintpair, 0), structuregenerator)) { // Paper - remove structure streams - Iterator iterator1 = structurestart.d().iterator(); - - while (iterator1.hasNext()) { -@@ -487,7 +488,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - } - } - -- }); -+ } // Paper - remove structure streams - } - - double[][][] adouble = new double[2][this.chunkCountZ + 1][this.chunkCountY + 1]; diff --git a/Remapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch b/Remapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch deleted file mode 100644 index a3582192b3..0000000000 --- a/Remapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 1 Jul 2020 18:01:49 -0400 -Subject: [PATCH] Remove streams from classes related villager gossip - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -index 0204f05d989d45c0848f810d1953adf0992ce3c2..57832c392910d22aa81ac2b4816d043dd7ac867a 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -@@ -9,6 +9,7 @@ import com.mojang.serialization.DynamicOps; - import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper - import it.unimi.dsi.fastutil.objects.ObjectIterator; - import java.util.Arrays; - import java.util.Collection; -@@ -51,8 +52,21 @@ public class GossipContainer { - }); - } - -+ // Paper start - Remove streams from reputation -+ private List decompress() { -+ List list = new ObjectArrayList<>(); -+ for (Map.Entry entry : getReputations().entrySet()) { -+ for (GossipContainer.GossipEntry cur : entry.getValue().decompress(entry.getKey())) { -+ if (cur.weightedValue() != 0) -+ list.add(cur); -+ } -+ } -+ return list; -+ } -+ // Paper end -+ - private Collection selectGossipsForTransfer(Random random, int count) { -- List list = (List) this.unpack().collect(Collectors.toList()); -+ List list = decompress(); // Paper - Remove streams from reputation - - if (list.isEmpty()) { - return Collections.emptyList(); -@@ -119,7 +133,7 @@ public class GossipContainer { - } - - public Dynamic store(DynamicOps dynamicops) { -- return new Dynamic(dynamicops, dynamicops.createList(this.unpack().map((reputation_b) -> { -+ return new Dynamic(dynamicops, dynamicops.createList(this.decompress().stream().map((reputation_b) -> { - return reputation_b.store(dynamicops); - }).map(Dynamic::getValue))); - } -@@ -144,18 +158,30 @@ public class GossipContainer { - - public static class EntityGossips { // Paper - make public - -- private final Object2IntMap entries; -+ private final Object2IntMap entries; private Object2IntMap getEntries() { return entries; } // Paper - OBFHELPER - - public EntityGossips() { // Paper - make public - update CraftVillager setReputation on change - this.entries = new Object2IntOpenHashMap(); - } - - public int weightedValue(Predicate gossipTypeFilter) { -- return this.entries.object2IntEntrySet().stream().filter((entry) -> { -- return gossipTypeFilter.test(entry.getKey()); -- }).mapToInt((entry) -> { -- return entry.getIntValue() * ((GossipType) entry.getKey()).weight; -- }).sum(); -+ // Paper start - Remove streams from reputation -+ int weight = 0; -+ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { -+ if (gossipTypeFilter.test(entry.getKey())) { -+ weight += entry.getIntValue() * entry.getKey().getWeight(); -+ } -+ } -+ return weight; -+ } -+ -+ public List decompress(UUID uuid) { -+ List list = new ObjectArrayList<>(); -+ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { -+ list.add(new GossipContainer.GossipEntry(uuid, entry.getKey(), entry.getIntValue())); -+ } -+ return list; -+ // Paper - end - } - - public Stream unpack(UUID target) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java -index 808eaaae5d534427d197c90c8e53494f4c3bfd82..c775d0df2a8f8a0fd32a8ffc26d6ea6978cbb595 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java -@@ -11,7 +11,7 @@ public enum GossipType { - MAJOR_NEGATIVE("major_negative", -5, 100, 10, 10), MINOR_NEGATIVE("minor_negative", -1, 200, 20, 20), MINOR_POSITIVE("minor_positive", 1, 200, 1, 5), MAJOR_POSITIVE("major_positive", 5, 100, 0, 100), TRADING("trading", 1, 25, 2, 20); - - public final String id; -- public final int weight; -+ public final int weight; public int getWeight() { return weight; } // Paper - OBFHELPER - public final int max; - public final int decayPerDay; - public final int decayPerTransfer; diff --git a/Remapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch b/Remapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch deleted file mode 100644 index 66bda208cc..0000000000 --- a/Remapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Sat, 6 Jun 2020 18:13:42 +0200 -Subject: [PATCH] Support components in ItemMeta - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index cb66998dbaa9d93e92ef4045b83efbb0fd486234..20e008277d1188fc7b31bfb2522ef9f6429cc3fb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -874,11 +874,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return CraftChatMessage.fromJSONComponent(displayName); - } - -+ // 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(displayName); -+ } -+ // Paper end - @Override - public final void setDisplayName(String name) { - this.displayName = CraftChatMessage.fromStringOrNullToJSON(name); - } - -+ // Paper start -+ @Override -+ public void setDisplayNameComponent(net.md_5.bungee.api.chat.BaseComponent[] component) { -+ this.displayName = net.md_5.bungee.chat.ComponentSerializer.toString(component); -+ } -+ // Paper end - @Override - public boolean hasDisplayName() { - return displayName != null; -@@ -1021,6 +1033,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return this.lore == null ? null : new ArrayList(Lists.transform(this.lore, CraftChatMessage::fromJSONComponent)); - } - -+ // 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(entry) -+ ).collect(java.util.stream.Collectors.toList())); -+ } -+ // Paper end - @Override - public void setLore(List lore) { - if (lore == null || lore.isEmpty()) { -@@ -1035,6 +1055,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -+ // 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 customModelData != null; -@@ -1496,6 +1531,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - - for (Object object : addFrom) { -+ // Paper start - support components -+ if(object instanceof net.md_5.bungee.api.chat.BaseComponent[]) { -+ addTo.add(net.md_5.bungee.chat.ComponentSerializer.toString((net.md_5.bungee.api.chat.BaseComponent[]) object)); -+ } else -+ // Paper end - if (!(object instanceof String)) { - if (object != null) { - throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName()); diff --git a/Remapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/Remapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch deleted file mode 100644 index 52cd27053f..0000000000 --- a/Remapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 3 Jul 2020 15:03:33 -0700 -Subject: [PATCH] Improve EntityTargetLivingEntityEvent for 1.16 mobs - -CraftBukkit has a bug in their implementation and is incorrectly handling forget -Also adds more target reasons for why it forgot target. - -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 738162a55eb186f66df4d31e017c9b9a7cc604c2..1b6f34c2a185368aac973e8a5316a03950e4314b 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 -@@ -33,15 +33,15 @@ public class StopAttackingIfTargetInvalid extends Behavior { - - protected void start(ServerLevel world, E entity, long time) { - if (isTiredOfTryingToReachTarget((LivingEntity) entity)) { -- this.clearAttackTarget(entity); -+ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // Paper - } else if (this.isCurrentTargetDeadOrRemoved(entity)) { -- this.clearAttackTarget(entity); -+ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_DIED); // Paper - } else if (this.isCurrentTargetInDifferentLevel(entity)) { -- this.clearAttackTarget(entity); -+ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_OTHER_LEVEL); // Paper - } else if (!EntitySelector.ATTACK_ALLOWED.test(this.getAttackTarget(entity))) { -- this.clearAttackTarget(entity); -+ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper - } else if (this.stopAttackingWhen.test(this.getAttackTarget(entity))) { -- this.clearAttackTarget(entity); -+ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper - } - } - -@@ -65,18 +65,21 @@ public class StopAttackingIfTargetInvalid extends Behavior { - return optional.isPresent() && !((LivingEntity) optional.get()).isAlive(); - } - -- private void clearAttackTarget(E entity) { -+ private void d(E e0, EntityTargetEvent.TargetReason reason) { - // CraftBukkit start -- LivingEntity old = entity.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); -- EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); -+ // Paper start - fix this event -+ //EntityLiving old = e0.getBehaviorController().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); -+ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(e0, null, reason); - if (event.isCancelled()) { - return; - } -- if (event.getTarget() != null) { -- entity.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); -+ // comment out, bad logic - bad -+ /*if (event.getTarget() != null) { -+ e0.getBehaviorController().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); - return; -- } -+ }*/ -+ // Paper end - // CraftBukkit end -- entity.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); -+ e0.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); - } - } diff --git a/Remapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch b/Remapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch deleted file mode 100644 index 87da8f1dcb..0000000000 --- a/Remapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jul 2020 18:11:43 -0500 -Subject: [PATCH] Add entity liquid API - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index e9a658b11e2b6683831dc3f5bd20be9a7840ed69..aea2457510c75214bbb925307155611e981f115f 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1164,12 +1164,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.wasTouchingWater; - } - -- private boolean isInRain() { -+ public boolean isInRain() { // Paper - private -> public - BlockPos blockposition = this.blockPosition(); - - return this.level.isRainingAt(blockposition) || this.level.isRainingAt(new BlockPos((double) blockposition.getX(), this.getBoundingBox().maxY, (double) blockposition.getZ())); - } - -+ public final boolean isInBubbleColumn() { return isInBubbleColumn(); } // Paper - OBFHELPER - private boolean isInBubbleColumn() { - return this.level.getBlockState(this.blockPosition()).is(Blocks.BUBBLE_COLUMN); - } -@@ -1183,6 +1184,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.isInWater() || this.isInRain() || this.isInBubbleColumn(); - } - -+ public final boolean isInWaterOrBubbleColumn() { return isInWaterOrBubble(); } // Paper - OBFHELPER - public boolean isInWaterOrBubble() { - return this.isInWater() || this.isInBubbleColumn(); - } -@@ -1325,6 +1327,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.fluidOnEyes == tag; - } - -+ public final boolean isInLava() { return isInLava(); } // Paper - OBFHELPER - public boolean isInLava() { - return !this.firstTick && this.fluidHeight.getDouble(FluidTags.LAVA) > 0.0D; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 76d652386806fd11961611486a1d0a12fe9616a4..deeae62e9926f9435907c68e7d35e7420f5e79dd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1135,5 +1135,29 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { - return getHandle().spawnReason; - } -+ -+ public boolean isInRain() { -+ return getHandle().isInRain(); -+ } -+ -+ public boolean isInBubbleColumn() { -+ return getHandle().isInBubbleColumn(); -+ } -+ -+ public boolean isInWaterOrRain() { -+ return getHandle().isInWaterOrRain(); -+ } -+ -+ public boolean isInWaterOrBubbleColumn() { -+ return getHandle().isInWaterOrBubbleColumn(); -+ } -+ -+ public boolean isInWaterOrRainOrBubbleColumn() { -+ return getHandle().isInWaterOrRainOrBubble(); -+ } -+ -+ public boolean isInLava() { -+ return getHandle().isInLava(); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch b/Remapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch deleted file mode 100644 index 1b999bcc30..0000000000 --- a/Remapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 1 Jul 2020 11:57:40 -0500 -Subject: [PATCH] Update itemstack legacy name and lore - - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 458cdfbeac9d757c9721acd4557a548affa0ede1..04b717326524f400da3562655c25db59e72814ec 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -49,6 +49,7 @@ import net.minecraft.core.Registry; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.nbt.NbtOps; -+import net.minecraft.nbt.StringTag; - import net.minecraft.nbt.Tag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.ComponentUtils; -@@ -135,6 +136,44 @@ public final class ItemStack { - list.sort((Comparator) enchantSorter); // Paper - } catch (Exception ignored) {} - } -+ -+ private void processText() { -+ CompoundTag display = getSubTag("display"); -+ if (display != null) { -+ if (display.contains("Name", 8)) { -+ String json = display.getString("Name"); -+ if (json != null && json.contains("\u00A7")) { -+ try { -+ display.put("Name", convert(json)); -+ } catch (JsonParseException jsonparseexception) { -+ display.remove("Name"); -+ } -+ } -+ } -+ if (display.contains("Lore", 9)) { -+ ListTag list = display.getList("Lore", 8); -+ for (int index = 0; index < list.size(); index++) { -+ String json = list.getString(index); -+ if (json != null && json.contains("\u00A7")) { // Only try if it has legacy in the unparsed json -+ try { -+ list.set(index, convert(json)); -+ } catch (JsonParseException e) { -+ list.set(index, StringTag.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(new TextComponent("")))); -+ } -+ } -+ } -+ } -+ } -+ } -+ -+ private StringTag convert(String json) { -+ Component component = Component.Serializer.jsonToComponent(json); -+ if (component instanceof TextComponent && component.getContents().contains("\u00A7") && component.getSiblings().isEmpty()) { -+ // Only convert if the root component is a single comp with legacy in it, don't convert already normal components -+ component = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(component.getContents())[0]; -+ } -+ return StringTag.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(component)); -+ } - // Paper end - - public ItemStack(ItemLike item) { -@@ -180,6 +219,7 @@ public final class ItemStack { - // CraftBukkit start - make defensive copy as this data may be coming from the save thread - this.tag = (CompoundTag) nbttagcompound.getCompound("tag").copy(); - processEnchantOrder(this.tag); // Paper -+ processText(); // Paper - this.getItem().verifyTagAfterLoad(this.tag); - // CraftBukkit end - } -@@ -663,6 +703,7 @@ public final class ItemStack { - } - } - -+ @Nullable public CompoundTag getSubTag(String s) { return getTagElement(s); } // Paper - OBFHELPER - @Nullable - public CompoundTag getTagElement(String key) { - return this.tag != null && this.tag.contains(key, 10) ? this.tag.getCompound(key) : null; diff --git a/Remapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch b/Remapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch deleted file mode 100644 index 5ec61b9dae..0000000000 --- a/Remapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Wyatt Childers -Date: Fri, 3 Jul 2020 14:57:05 -0400 -Subject: [PATCH] Spawn player in correct world on login - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 713cc88dd067c0d918f253b1845f42c0d9eb920f..f36c92e42300c2056075610caf63f8bef0e7edda 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -192,7 +192,18 @@ public abstract class PlayerList { - }String lastKnownName = s; // Paper - // CraftBukkit end - -- if (nbttagcompound != null) { -+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID. -+ if (nbttagcompound != null && nbttagcompound.contains("WorldUUIDMost") && nbttagcompound.contains("WorldUUIDLeast")) { -+ UUID uid = new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast")); -+ org.bukkit.World bWorld = org.bukkit.Bukkit.getServer().getWorld(uid); -+ if (bWorld != null) { -+ resourcekey = ((CraftWorld) bWorld).getHandle().dimension(); -+ } else { -+ resourcekey = Level.OVERWORLD; -+ } -+ } else if (nbttagcompound != null) { -+ // Vanilla migration support -+ // Paper end - DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension"))); - Logger logger = PlayerList.LOGGER; - diff --git a/Remapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch b/Remapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch deleted file mode 100644 index be0c76ca05..0000000000 --- a/Remapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 3 Jul 2020 11:58:56 -0500 -Subject: [PATCH] Add PrepareResultEvent - -Adds a new event for all crafting stations that generate a result slot item - -Anvil, Grindstone and Smithing now extend this event - -diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -index 72b0cfcc5aab03e14e63440c734436e9c1432111..bc39e7464646d712b085251dc0277a5b1ec0a393 100644 ---- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -141,6 +141,7 @@ public abstract class AbstractContainerMenu { - return nonnulllist; - } - -+ public final void notifyListeners() { this.broadcastChanges(); } // Paper - OBFHELPER - public void broadcastChanges() { - int i; - -diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java -index 3d53edae7e3d5bb00913384ad0eb67551a65750e..492a42ad5dc460717de8179d522d042cee11db60 100644 ---- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java -@@ -307,6 +307,7 @@ public class AnvilMenu extends ItemCombinerMenu { - } - - this.createResult(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java -index 6183e33237a231be388a8ace0ca3b56720db13ee..464f27d3f0cc694257a550cf873a0ee4534e2189 100644 ---- a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java -@@ -146,6 +146,7 @@ public class CartographyTableMenu extends AbstractContainerMenu { - this.setupResultSlot(itemstack, itemstack1, itemstack2); - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - private void setupResultSlot(ItemStack map, ItemStack item, ItemStack oldResult) { -diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -index e9e830117fe3e4e02a51eef8671a3d3b48c2858e..329a6d70d53c13cd554c64996f2ddc489bdc1e94 100644 ---- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -@@ -156,6 +156,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { - super.slotsChanged(inventory); - if (inventory == this.repairSlots) { - this.createResult(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java -index d944cbcdf4d886d3b8b171edd8e2ac8a54dc19b9..8704c4dbead1ff661d84b751479babac5ebc5839 100644 ---- a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java -@@ -71,6 +71,7 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu { - super.slotsChanged(inventory); - if (inventory == this.inputSlots) { - this.createResult(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java -index b33daf92752841e46f2fd9fa20dc1cfa79aa423a..3460fb2bb1451b8456a7fe42449ec4dbce641f40 100644 ---- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java -@@ -188,7 +188,8 @@ public class LoomMenu extends AbstractContainerMenu { - } - - this.setupResultSlot(); -- this.broadcastChanges(); -+ //this.c(); // Paper - done below -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 3); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/inventory/SmithingMenu.java b/src/main/java/net/minecraft/world/inventory/SmithingMenu.java -index befb2e6294c3d0a16ae4766c3804d04fd4e1bba5..44aa1f4f91ae9f84fc7ed38cc6b3c11f07d55ba1 100644 ---- a/src/main/java/net/minecraft/world/inventory/SmithingMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/SmithingMenu.java -@@ -78,6 +78,7 @@ public class SmithingMenu extends ItemCombinerMenu { - // CraftBukkit end - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java -index febf7fa112c470888af171e585ab6a052abb46ca..072bac443e7c54ac2b92e1d93b757bdacf230fbb 100644 ---- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java -@@ -155,6 +155,7 @@ public class StonecutterMenu extends AbstractContainerMenu { - this.setupRecipeList(inventory, itemstack); - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 1); // Paper - } - - private void setupRecipeList(Container input, ItemStack stack) { -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 87fe7f4f5ed70bf1b3dc1e2a392ba42a1f8f568b..64cfa14aa4e32430a6970fd4f3654a56146ba807 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1522,19 +1522,44 @@ public class CraftEventFactory { - return event; - } - -- public static PrepareAnvilEvent callPrepareAnvilEvent(InventoryView view, ItemStack item) { -- PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item).clone()); -- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); -+ // Paper start - disable this method, handled below -+ public static void callPrepareAnvilEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult -+ PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone -+ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // disable event - event.getInventory().setItem(2, event.getResult()); -- return event; -+ //return event; // Paper - } -+ // Paper end - -- public static PrepareSmithingEvent callPrepareSmithingEvent(InventoryView view, ItemStack item) { -- PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item).clone()); -- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); -+ // Paper start - disable this method, handled in callPrepareResultEvent -+ public static void callPrepareSmithingEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult -+ PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone -+ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // Paper - disable event - event.getInventory().setItem(2, event.getResult()); -- return event; -+ //return event; // Paper - } -+ // Paper end -+ -+ // Paper start - support specific overrides for prepare result -+ public static void callPrepareResultEvent(AbstractContainerMenu container, int resultSlot) { -+ com.destroystokyo.paper.event.inventory.PrepareResultEvent event; -+ InventoryView view = container.getBukkitView(); -+ org.bukkit.inventory.ItemStack origItem = view.getTopInventory().getItem(resultSlot); -+ CraftItemStack result = origItem != null ? CraftItemStack.asCraftCopy(origItem) : null; -+ if (view.getTopInventory() instanceof org.bukkit.inventory.AnvilInventory) { -+ event = new PrepareAnvilEvent(view, result); -+ } else if (view.getTopInventory() instanceof org.bukkit.inventory.GrindstoneInventory) { -+ event = new com.destroystokyo.paper.event.inventory.PrepareGrindstoneEvent(view, result); -+ } else if (view.getTopInventory() instanceof org.bukkit.inventory.SmithingInventory) { -+ event = new PrepareSmithingEvent(view, result); -+ } else { -+ event = new com.destroystokyo.paper.event.inventory.PrepareResultEvent(view, result); -+ } -+ event.callEvent(); -+ event.getInventory().setItem(resultSlot, event.getResult()); -+ container.notifyListeners(); -+ } -+ // Paper end - - /** - * Mob spawner event. diff --git a/Remapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch b/Remapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch deleted file mode 100644 index 183e23a96c..0000000000 --- a/Remapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Wed, 29 Apr 2020 02:10:32 +0200 -Subject: [PATCH] Allow delegation to vanilla chunk gen - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java -index aaa8d78b131c4095b36c6db6078f57f927c15374..54e560348836498f16dde017c6e7e3fcc263eeea 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java -+++ b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java -@@ -36,7 +36,7 @@ import org.apache.logging.log4j.Logger; - public class UpgradeData { - - private static final Logger LOGGER = LogManager.getLogger(); -- public static final UpgradeData EMPTY = new UpgradeData(); -+ public static final UpgradeData EMPTY = new UpgradeData(); public static UpgradeData getEmptyConverter() { return EMPTY; } // Paper - obfhelper - private static final Direction8[] DIRECTIONS = Direction8.values(); - private final EnumSet sides; - private final int[][] index; -@@ -322,7 +322,7 @@ public class UpgradeData { - if ((Integer) iblockdata.getValue(BlockStateProperties.DISTANCE) >= j) { - world.setBlock(blockposition, (BlockState) iblockdata.setValue(BlockStateProperties.DISTANCE, j), 18); - if (i != 7) { -- Direction[] aenumdirection = null.f; -+ Direction[] aenumdirection = DIRECTIONS; // Paper - decomp fix - int k = aenumdirection.length; - - for (int l = 0; l < k; ++l) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 2ec41cb87cec97780f1fa8abfbb756fca4dba1bf..e301aee53b19fc3f93a36d0ed03a649741123bfa 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2032,6 +2032,32 @@ public final class CraftServer implements Server { - return new CraftChunkData(world); - } - -+ // Paper start -+ @Override -+ public ChunkGenerator.ChunkData createVanillaChunkData(World world, int x, int z) { -+ // get empty object -+ CraftChunkData data = (CraftChunkData) createChunkData(world); -+ // do bunch of vanilla shit -+ net.minecraft.server.level.ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); -+ net.minecraft.world.level.chunk.ProtoChunk protoChunk = new net.minecraft.world.level.chunk.ProtoChunk(new net.minecraft.world.level.ChunkPos(x, z), net.minecraft.world.level.chunk.UpgradeData.getEmptyConverter(), nmsWorld); -+ List list = new ArrayList<>(); -+ list.add(protoChunk); -+ net.minecraft.server.level.WorldGenRegion genRegion = new net.minecraft.server.level.WorldGenRegion(nmsWorld, list); -+ // call vanilla generator, one feature after another. Order here is important! -+ net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator = nmsWorld.getChunkSource().generator; -+ if (chunkGenerator instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator) { -+ chunkGenerator = ((org.bukkit.craftbukkit.generator.CustomChunkGenerator) chunkGenerator).delegate; -+ } -+ chunkGenerator.createBiomes(nmsWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), protoChunk); -+ chunkGenerator.fillFromNoise(genRegion, nmsWorld.structureFeatureManager(), protoChunk); -+ chunkGenerator.buildSurfaceAndBedrock(genRegion, protoChunk); -+ // copy over generated sections -+ data.setRawChunkData(protoChunk.getSections()); -+ // hooray! -+ return data; -+ } -+ // Paper end -+ - @Override - public BossBar createBossBar(String title, BarColor color, BarStyle style, BarFlag... flags) { - return new CraftBossBar(title, color, style, flags); -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index 8d72cd6a44cf462cfe3adac9bf99a16883a587df..fd2cb2a584fea360fcf8180338708f35c4e3dc1f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -19,7 +19,7 @@ import org.bukkit.material.MaterialData; - */ - public final class CraftChunkData implements ChunkGenerator.ChunkData { - private final int maxHeight; -- private final LevelChunkSection[] sections; -+ private LevelChunkSection[] sections; // Paper - remove final - private Set tiles; - private World world; // Paper - Anti-Xray - Add world - -@@ -168,6 +168,12 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - return sections; - } - -+ // Paper start -+ public void setRawChunkData(LevelChunkSection[] sections) { -+ this.sections = sections; -+ } -+ // Paper end -+ - Set getTiles() { - return tiles; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -index eba3a6a2467116d93945ab2d5dc0a6f41d76f547..e25dc1c87752fcf73181cb02ddaf84b258ac4e9d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -@@ -32,7 +32,7 @@ import org.bukkit.generator.ChunkGenerator.ChunkData; - - public class CustomChunkGenerator extends InternalChunkGenerator { - -- private final net.minecraft.world.level.chunk.ChunkGenerator delegate; -+ public final net.minecraft.world.level.chunk.ChunkGenerator delegate; // Paper - public - private final ChunkGenerator generator; - private final ServerLevel world; - private final Random random = new Random(); diff --git a/Remapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/Remapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch deleted file mode 100644 index 253148a7ee..0000000000 --- a/Remapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 5 Jul 2020 14:59:31 -0400 -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 cec1e6105b8c2ac3d1482c00482d53d6be0d38d1..9724d4222311345a44aa101ec47523a1909fbe8f 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3038,7 +3038,7 @@ public abstract class LivingEntity extends Entity { - Entity entity = this.getVehicle(); - - super.stopRiding(suppressCancellation); // Paper - suppress -- if (entity != null && entity != this.getVehicle() && !this.level.isClientSide) { -+ if (entity != null && entity != this.getVehicle() && !this.level.isClientSide && entity.valid) { // Paper - don't process on world gen - this.dismountVehicle(entity); - } - diff --git a/Remapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch b/Remapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch deleted file mode 100644 index dc51ae715d..0000000000 --- a/Remapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Sun, 5 Jul 2020 22:38:18 -0400 -Subject: [PATCH] Optimize NetworkManager Exception Handling - - -diff --git a/src/main/java/net/minecraft/network/ConnectionProtocol.java b/src/main/java/net/minecraft/network/ConnectionProtocol.java -index fca778d131aa10e88d5f7ed8d57eda6803318184..47a5ee9db64184f173af5984765e9b6d1a8ec367 100644 ---- a/src/main/java/net/minecraft/network/ConnectionProtocol.java -+++ b/src/main/java/net/minecraft/network/ConnectionProtocol.java -@@ -151,6 +151,7 @@ public enum ConnectionProtocol { - - @Nullable - public Packet createPacket(int id) { -+ if (id < 0 || id >= this.idToConstructor.size()) return null; // Paper - Supplier> supplier = (Supplier) this.idToConstructor.get(id); - - return supplier != null ? (Packet) supplier.get() : null; -diff --git a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java -index 8363b63f8dbd16948eeba3f912dc43605ad8db6a..fbebef6525a0872fecc081c7f63f27c1a04e11dc 100644 ---- a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java -+++ b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java -@@ -9,11 +9,21 @@ import java.util.List; - - public class Varint21FrameDecoder extends ByteToMessageDecoder { - -+ private final byte[] lenBuf = new byte[3]; // Paper - public Varint21FrameDecoder() {} - - protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { -+ // Paper start - if channel is not active just discard the packet -+ if (!channelhandlercontext.channel().isActive()) { -+ bytebuf.skipBytes(bytebuf.readableBytes()); -+ return; -+ } -+ // Paper end - bytebuf.markReaderIndex(); -- byte[] abyte = new byte[3]; -+ // Paper start - reuse temporary length buffer -+ byte[] abyte = lenBuf; -+ java.util.Arrays.fill(abyte, (byte) 0); -+ // Paper end - - for (int i = 0; i < abyte.length; ++i) { - if (!bytebuf.isReadable()) { -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index 22db5d0d2cc33498ca40162c66aa3b5fbf2f569f..3163502cb9bbbb5a00e7f06cf0032b1ad93c354d 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -2,8 +2,10 @@ package net.minecraft.network.protocol; - - import io.netty.channel.ChannelFuture; // Paper - import java.io.IOException; -+import net.minecraft.network.Connection; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.PacketListener; -+import net.minecraft.server.level.ServerPlayer; - - public interface Packet { - -@@ -18,17 +20,17 @@ public interface Packet { - /** - * @param player Null if not at PLAY stage yet - */ -- default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} -+ default void onPacketDispatch(@javax.annotation.Nullable ServerPlayer player) {} - - /** - * @param player Null if not at PLAY stage yet - * @param future Can be null if packet was cancelled - */ -- default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} -+ default void onPacketDispatchFinish(@javax.annotation.Nullable ServerPlayer player, @javax.annotation.Nullable ChannelFuture future) {} - default boolean hasFinishListener() { return false; } - default boolean isReady() { return true; } - default java.util.List getExtraPackets() { return null; } -- default boolean packetTooLarge(NetworkManager manager) { -+ default boolean packetTooLarge(Connection manager) { - return false; - } - // Paper end -diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -index 4ae8201d7dcffeb3298a4e593f978e15ffc5ac15..5812e518222e419da141ab0f70d1e7a3939a0df0 100644 ---- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java -+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -@@ -1,6 +1,9 @@ - package net.minecraft.network.protocol; - -+import net.minecraft.network.Connection; - import net.minecraft.network.PacketListener; -+import net.minecraft.network.chat.TextComponent; -+import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - import co.aikar.timings.MinecraftTimings; // Paper -@@ -30,6 +33,21 @@ public class PacketUtils { - try (Timing ignored = timing.startTiming()) { // Paper - timings - packet.handle(listener); - } // Paper - timings -+ // Paper start -+ catch (Exception e) { -+ Connection networkmanager = listener.a(); -+ if (networkmanager.getPlayer() != null) { -+ LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), networkmanager.getRemoteAddress(), e); -+ } else { -+ LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getRemoteAddress(), e); -+ } -+ TextComponent error = new TextComponent("Packet processing error"); -+ networkmanager.send(new ClientboundDisconnectPacket(error), (future) -> { -+ networkmanager.disconnect(error); -+ }); -+ networkmanager.setReadOnly(); -+ } -+ // Paper end - } else { - PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); - } diff --git a/Remapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch b/Remapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch deleted file mode 100644 index 7c0af04ac0..0000000000 --- a/Remapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 6 Jul 2020 18:36:41 -0400 -Subject: [PATCH] Fix Concurrency issue in WeightedList - -if multiple threads from worldgen sort at same time, it will crash. -So make a copy of the list for sorting purposes. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java -index 0a65e442ddc31c06f3bb0ff5aa152daee7a210af..a81ad258b39b7472312ab1bedeeacaf26ffae4f7 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java -@@ -17,7 +17,7 @@ public class GateBehavior extends Behavior { - private final Set> exitErasedMemories; - private final GateBehavior.OrderPolicy orderPolicy; - private final GateBehavior.RunningPolicy runningPolicy; -- private final WeightedList> behaviors = new WeightedList<>(); -+ private final WeightedList> behaviors = new WeightedList<>(false); // Paper - don't use a clone - - public GateBehavior(Map, MemoryStatus> requiredMemoryState, Set> memoriesToForgetWhenStopped, GateBehavior.OrderPolicy order, GateBehavior.RunningPolicy runMode, List, Integer>> tasks) { - super(requiredMemoryState); -@@ -65,10 +65,9 @@ public class GateBehavior extends Behavior { - }).forEach((behavior) -> { - behavior.g(world, entity, time); - }); -- Set set = this.exitErasedMemories; - Brain behaviorcontroller = entity.getBrain(); - -- set.forEach(behaviorcontroller::removeMemory); -+ this.exitErasedMemories.forEach(behaviorcontroller::eraseMemory); // Paper - decomp fix - } - - @Override -@@ -111,11 +110,11 @@ public class GateBehavior extends Behavior { - static enum OrderPolicy { - - ORDERED((weightedlist) -> { -- }), SHUFFLED(WeightedList::a); -+ }), SHUFFLED(WeightedList::shuffle); - - private final Consumer> consumer; - -- private OrderPolicy(Consumer consumer) { -+ private OrderPolicy(Consumer> consumer) { // Paper - decomp fix - this.consumer = consumer; - } - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java -index e4c1c58e9a9c744c7ebb9948a27766b84a081b9e..85df30ef7c03c2f8ae741a8cac8bf601490d2539 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java -@@ -6,7 +6,7 @@ import com.mojang.serialization.Codec; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import com.mojang.serialization.DynamicOps; --import com.mojang.serialization.OptionalDynamic; -+ - import java.util.Comparator; - import java.util.List; - import java.util.Random; -@@ -14,26 +14,32 @@ import java.util.stream.Stream; - - public class WeightedList { - -- protected final List> entries; -+ protected final List> list; // Paper - decompile conflict - private final Random random; -+ private final boolean isUnsafe; // Paper - -- public WeightedList() { -- this(Lists.newArrayList()); -+ // Paper start - add useClone option -+ public WeightedList() { this(true); } -+ public WeightedList(boolean isUnsafe) { -+ this(Lists.newArrayList(), isUnsafe); - } - -- private WeightedList(List> entries) { -+ private WeightedList(List> entries) { this(entries, true); } -+ private WeightedList(List> list, boolean isUnsafe) { -+ this.isUnsafe = isUnsafe; -+ // Paper end - this.random = new Random(); -- this.entries = Lists.newArrayList(entries); -+ this.list = Lists.newArrayList(list); // Paper - decompile conflict - } - - public static Codec> codec(Codec codec) { -- return WeightedList.entries.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { -- return weightedlist.a; -+ return WeightedList.WeightedEntry.codec(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { // Paper - decompile conflict -+ return weightedlist.list; // Paper - decompile conflict - }); - } - - public WeightedList add(U item, int weight) { -- this.entries.add(new WeightedList.WeightedEntry<>(item, weight)); -+ this.list.add(new WeightedList.WeightedEntry<>(item, weight)); // Paper - decompile conflict - return this; - } - -@@ -42,21 +48,20 @@ public class WeightedList { - } - - public WeightedList shuffle(Random random) { -- this.entries.forEach((weightedlist_a) -> { -- weightedlist_a.setRandom(random.nextFloat()); -- }); -- this.entries.sort(Comparator.comparingDouble((object) -> { -- return ((WeightedList.WeightedEntry) object).getRandWeight(); -- })); -- return this; -+ // Paper start - make concurrent safe, work off a clone of the list -+ List> list = isUnsafe ? new java.util.ArrayList>(this.list) : this.list; -+ list.forEach((weightedlist_a) -> weightedlist_a.setRandom(random.nextFloat())); -+ list.sort(Comparator.comparingDouble(WeightedEntry::getRandWeight)); -+ return isUnsafe ? new WeightedList<>(list, isUnsafe) : this; -+ // Paper end - } - - public boolean isEmpty() { -- return this.entries.isEmpty(); -+ return this.list.isEmpty(); // Paper - decompile conflict - } - - public Stream stream() { -- return this.entries.stream().map(WeightedList.entries::a); -+ return this.list.stream().map(WeightedList.WeightedEntry::getData); // Paper - decompile conflict - } - - public U getOne(Random random) { -@@ -64,7 +69,7 @@ public class WeightedList { - } - - public String toString() { -- return "WeightedList[" + this.entries + "]"; -+ return "WeightedList[" + this.list + "]"; // Paper - decompile conflict - } - - public static class WeightedEntry { -@@ -98,11 +103,7 @@ public class WeightedList { - return new Codec>() { - public DataResult, T>> decode(DynamicOps dynamicops, T t0) { - Dynamic dynamic = new Dynamic(dynamicops, t0); -- OptionalDynamic optionaldynamic = dynamic.get("data"); -- Codec codec1 = codec; -- -- codec.getClass(); -- return optionaldynamic.flatMap(codec1::parse).map((object) -> { -+ return dynamic.get("data").flatMap(codec::parse).map((object) -> { // Paper - decompile error - return new WeightedList.WeightedEntry<>(object, dynamic.get("weight").asInt(1)); - }).map((weightedlist_a) -> { - return Pair.of(weightedlist_a, dynamicops.empty()); diff --git a/Remapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch b/Remapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch deleted file mode 100644 index a23f3a28c9..0000000000 --- a/Remapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Wyatt Childers -Date: Sat, 4 Jul 2020 23:07:43 -0400 -Subject: [PATCH] Optimize the advancement data player iteration to be O(N) - rather than O(N^2) - - -diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java -index 5ab62fc74085bbbb0c81b2f4d16a35c9345cd1f1..af8553f1b22e24fbeb732937fbbffc95cb9dfe90 100644 ---- a/src/main/java/net/minecraft/server/PlayerAdvancements.java -+++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java -@@ -457,6 +457,16 @@ public class PlayerAdvancements { - } - - private void ensureVisibility(Advancement advancement) { -+ // Paper start -+ e(advancement, IterationEntryPoint.ROOT); -+ } -+ private enum IterationEntryPoint { -+ ROOT, -+ ITERATOR, -+ PARENT_OF_ITERATOR -+ } -+ private void e(Advancement advancement, IterationEntryPoint entryPoint) { -+ // Paper end - boolean flag = this.shouldBeVisible(advancement); - boolean flag1 = this.visible.contains(advancement); - -@@ -472,15 +482,23 @@ public class PlayerAdvancements { - } - - if (flag != flag1 && advancement.getParent() != null) { -- this.ensureVisibility(advancement.getParent()); -+ // Paper start - If we're not coming from an iterator consider this to be a root entry, otherwise -+ // market that we're entering from the parent of an iterator. -+ this.e(advancement.getParent(), entryPoint == IterationEntryPoint.ITERATOR ? IterationEntryPoint.PARENT_OF_ITERATOR : IterationEntryPoint.ROOT); - } - -+ // If this is true, we've went through a child iteration, entered the parent, processed the parent -+ // and are about to reprocess the children. Stop processing here to prevent O(N^2) processing. -+ if (entryPoint == IterationEntryPoint.PARENT_OF_ITERATOR) { -+ return; -+ } // Paper end -+ - Iterator iterator = advancement.getChildren().iterator(); - - while (iterator.hasNext()) { - Advancement advancement1 = (Advancement) iterator.next(); - -- this.ensureVisibility(advancement1); -+ this.e(advancement1, IterationEntryPoint.ITERATOR); // Paper - Mark this call as being from iteration - } - - } diff --git a/Remapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch b/Remapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch deleted file mode 100644 index 677615b010..0000000000 --- a/Remapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 8 Jul 2020 11:24:30 -0500 -Subject: [PATCH] Fix arrows never despawning MC-125757 - -This forces the despawn counter to start ticking regardless of -state after the arrow has been alive for 200 ticks (10 seconds) -instead of getting stuck in a never despawn state (bubble columns, -etc). - -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 6225f390b51733217a809910182f58acea1055e2..73df844610530bbfb133bd59d00015117b59b215 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -169,6 +169,7 @@ public abstract class AbstractArrow extends Projectile { - - ++this.inGroundTime; - } else { -+ if (tickCount > 200) this.tickDespawnCounter(); // Paper - tick despawnCounter regardless after 10 seconds - this.inGroundTime = 0; - Vec3 vec3d2 = this.position(); - -@@ -290,6 +291,7 @@ public abstract class AbstractArrow extends Projectile { - - } - -+ protected final void tickDespawnCounter() { this.tickDespawn(); } // Paper - OBFHELPER - protected void tickDespawn() { - ++this.life; - if (this.life >= (pickup == Pickup.CREATIVE_ONLY ? level.paperConfig.creativeArrowDespawnRate : (pickup == Pickup.DISALLOWED ? level.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? diff --git a/Remapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch b/Remapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch deleted file mode 100644 index 41cf790265..0000000000 --- a/Remapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Jul 2020 03:54:28 -0400 -Subject: [PATCH] Thread Safe Vanilla Command permission checking - -Datapacks check this on load and are built concurrently. This was breaking them badly due -to race conditions. - -Plus, .canUse we want to be safe for async anyways. - -diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -index 5c35cef42af4053332c02b4960c227fe95d4c197..757ed7a0887f4bdb187ca7c757db5c188362f1a0 100644 ---- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java -+++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -@@ -74,10 +74,10 @@ public abstract class CommandNode implements Comparable> { - public synchronized boolean canUse(final S source) { - if (source instanceof CommandSourceStack) { - try { -- ((CommandSourceStack) source).currentCommand = this; -+ ((CommandSourceStack) source).currentCommand.set(this); // Paper - return requirement.test(source); - } finally { -- ((CommandSourceStack) source).currentCommand = null; -+ ((CommandSourceStack) source).currentCommand.set(null); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java -index e1f4ffaa36bfffb7741c74b7a094e26a03a9a1e6..2c024f8f8b949dc8cebd29a10415eeac6d50902e 100644 ---- a/src/main/java/net/minecraft/commands/CommandSourceStack.java -+++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java -@@ -54,7 +54,7 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy - private final ResultConsumer consumer; - private final EntityAnchorArgument.Anchor anchor; - private final Vec2 rotation; -- public volatile CommandNode currentCommand; // CraftBukkit -+ public ThreadLocal currentCommand = new ThreadLocal<>(); // CraftBukkit // Paper - - public CommandSourceStack(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String simpleName, Component name, MinecraftServer server, @Nullable Entity entity) { - this(output, pos, rot, world, level, simpleName, name, server, entity, false, (commandcontext, flag, j) -> { -@@ -171,9 +171,11 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy - @Override - public boolean hasPermission(int level) { - // CraftBukkit start -- CommandNode currentCommand = this.currentCommand; -+ // Paper start - fix concurrency issue -+ CommandNode currentCommand = this.currentCommand.get(); - if (currentCommand != null) { - return hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); -+ // Paper end - } - // CraftBukkit end - diff --git a/Remapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch b/Remapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch deleted file mode 100644 index 7fba765097..0000000000 --- a/Remapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Jul 2020 19:34:11 -0700 -Subject: [PATCH] Move range check for block placing up - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 773f2589c14e16d2f5b01a6dbd48e09d17d19c7e..d264fca2737f83a0860394f7bb6b269ffe669594 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1661,15 +1661,19 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - BlockPos blockposition = movingobjectpositionblock.getBlockPos(); - Direction enumdirection = movingobjectpositionblock.getDirection(); - -+ // Paper start - move check up -+ Location eyeLoc = this.getPlayer().getEyeLocation(); -+ double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); -+ if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { -+ return; -+ } -+ // Paper end - move check up -+ - this.player.resetLastActionTime(); - if (blockposition.getY() < this.server.getMaxBuildHeight()) { - if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition)) { - // CraftBukkit start - Check if we can actually do something over this large a distance -- Location eyeLoc = this.getPlayer().getEyeLocation(); -- double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); -- if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { -- return; -- } -+ // Paper - move check up - this.player.stopUsingItem(); // SPIGOT-4706 - // CraftBukkit end - InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); diff --git a/Remapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch b/Remapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch deleted file mode 100644 index 84a6a9da90..0000000000 --- a/Remapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 15 Jul 2020 21:42:52 -0400 -Subject: [PATCH] Fix SPIGOT-5989 - -Before this fix, if a player was respawning to a respawn anchor and -the respawn location was modified away from the anchor with the -PlayerRespawnEvent, the anchor would still lose some charge. -This fixes that by checking if the modified spawn location is -still at a respawn anchor. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index f36c92e42300c2056075610caf63f8bef0e7edda..882cd25c9610f0b995c27291aa62846922ab531f 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -84,6 +84,7 @@ import net.minecraft.world.level.GameType; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.Blocks; -+import net.minecraft.world.level.block.RespawnAnchorBlock; - import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.level.border.BorderChangeListener; - import net.minecraft.world.level.border.WorldBorder; -@@ -846,6 +847,7 @@ public abstract class PlayerList { - // Paper start - boolean isBedSpawn = false; - boolean isRespawn = false; -+ boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 - // Paper end - - // CraftBukkit start - fire PlayerRespawnEvent -@@ -856,7 +858,7 @@ public abstract class PlayerList { - Optional optional; - - if (blockposition != null) { -- optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, flag); -+ optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, true); // Paper - Fix SPIGOT-5989 - } else { - optional = Optional.empty(); - } -@@ -899,7 +901,12 @@ public abstract class PlayerList { - } - // Spigot End - -- location = respawnEvent.getRespawnLocation(); -+ // Paper start - Fix SPIGOT-5989 -+ if (!location.equals(respawnEvent.getRespawnLocation()) ) { -+ location = respawnEvent.getRespawnLocation(); -+ isLocAltered = true; -+ } -+ // Paper end - if (!flag) entityplayer.reset(); // SPIGOT-4785 - isRespawn = true; // Paper - } else { -@@ -937,8 +944,12 @@ public abstract class PlayerList { - } - // entityplayer1.syncInventory(); - entityplayer1.setHealth(entityplayer1.getHealth()); -- if (flag2) { -- entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 1.0F, 1.0F)); -+ // Paper start - Fix SPIGOT-5989 -+ if (flag2 && !isLocAltered) { -+ BlockState data = worldserver1.getBlockState(blockposition); -+ worldserver1.setBlock(blockposition, data.setValue(RespawnAnchorBlock.CHARGE, data.getValue(RespawnAnchorBlock.CHARGE) - 1), 3); -+ entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) location.getX(), (double) location.getY(), (double) location.getZ(), 1.0F, 1.0F)); -+ // Paper end - } - // Added from changeDimension - sendAllPlayerInfo(entityplayer); // Update health, etc... diff --git a/Remapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/Remapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch deleted file mode 100644 index 52bb1345ae..0000000000 --- a/Remapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 10 Jul 2020 13:12:33 -0500 -Subject: [PATCH] Fix SPIGOT-5824 Bukkit world-container is not used - - -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 855b3b4c90d84d4efa8395a76010b4b194591cbc..4e353432281a6dbbb49eaa4a6cb4eb051d1a08c5 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -124,11 +124,20 @@ public class Main { - return; - } - -- File file = (File) optionset.valueOf("universe"); // CraftBukkit -+ // Paper start - fix SPIGOT-5824 -+ File file; -+ File userCacheFile = new File("usercache.json"); -+ if (optionset.has("universe")) { -+ file = (File) optionset.valueOf("universe"); // CraftBukkit -+ userCacheFile = new File(file, "usercache.json"); -+ } else { -+ file = new File(bukkitConfiguration.getString("settings.world-container", ".")); -+ } -+ // Paper end - fix SPIGOT-5824 - YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper - MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); - GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); -- GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName())); -+ GameProfileCache usercache = new GameProfileCache(gameprofilerepository, userCacheFile); // Paper - only move usercache.json into folder if --universe is used, not world-container - // CraftBukkit start - String s = (String) Optional.ofNullable(optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); - LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath()); diff --git a/Remapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/Remapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch deleted file mode 100644 index fb2e14a9d3..0000000000 --- a/Remapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 10 Jul 2020 12:38:12 -0500 -Subject: [PATCH] Fix SPIGOT-5885 Unable to disable advancements - - -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 4e353432281a6dbbb49eaa4a6cb4eb051d1a08c5..9dc9a5e6ad7f23c8bf3553c765ceeecd67a49ac1 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -124,6 +124,7 @@ public class Main { - return; - } - -+ org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init - // Paper start - fix SPIGOT-5824 - File file; - File userCacheFile = new File("usercache.json"); diff --git a/Remapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/Remapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch deleted file mode 100644 index 8ec38751cb..0000000000 --- a/Remapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 13 Jul 2020 06:22:54 -0700 -Subject: [PATCH] Fix AdvancementDataPlayer leak due from quitting early in - login - -Move the criterion storage to the AdvancementDataPlayer object -itself, so the criterion object stores no references - and thus -needs no cleanup. - -diff --git a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java -index 31650e41b37e322d2e8a4d4a3deec95851e72675..a645c79af856d2484a4ce7aa2885a32358b9a480 100644 ---- a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java -+++ b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java -@@ -16,25 +16,25 @@ import net.minecraft.world.level.storage.loot.LootContext; - - public abstract class SimpleCriterionTrigger implements CriterionTrigger { - -- private final Map>> a = Maps.newIdentityHashMap(); -+ //private final Map>> a = Maps.newIdentityHashMap(); // Paper - moved into AdvancementDataPlayer to fix memory leak - - public SimpleCriterionTrigger() {} - - @Override - public final void a(PlayerAdvancements advancementdataplayer, CriterionTrigger.Listener criteriontrigger_a) { -- ((Set) this.a.computeIfAbsent(advancementdataplayer, (advancementdataplayer1) -> { -+ (advancementdataplayer.criterionData.computeIfAbsent(this, (advancementdataplayer1) -> { // Paper - fix AdvancementDataPlayer leak - return Sets.newHashSet(); - })).add(criteriontrigger_a); - } - - @Override - public final void b(PlayerAdvancements advancementdataplayer, CriterionTrigger.Listener criteriontrigger_a) { -- Set> set = (Set) this.a.get(advancementdataplayer); -+ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak - - if (set != null) { - set.remove(criteriontrigger_a); - if (set.isEmpty()) { -- this.a.remove(advancementdataplayer); -+ advancementdataplayer.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak - } - } - -@@ -42,7 +42,7 @@ public abstract class SimpleCriterionTrigger tester) { - PlayerAdvancements advancementdataplayer = player.getAdvancements(); -- Set> set = (Set) this.a.get(advancementdataplayer); -+ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak - - if (set != null && !set.isEmpty()) { - LootContext loottableinfo = EntityPredicate.createContext(player, player); -@@ -67,7 +67,7 @@ public abstract class SimpleCriterionTrigger> criterionData = Maps.newIdentityHashMap(); -+ // Paper end - fix advancement data player leakage -+ - public PlayerAdvancements(DataFixer datafixer, PlayerList playerlist, ServerAdvancementManager advancementdataworld, File file, ServerPlayer entityplayer) { - this.dataFixer = datafixer; - this.playerList = playerlist; diff --git a/Remapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/Remapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch deleted file mode 100644 index 468888ab9b..0000000000 --- a/Remapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 26 Jul 2020 12:11:39 +0100 -Subject: [PATCH] Add missing strikeLighting call to - World#spigot()#strikeLightningEffect - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 4436b3d23dc8f33925da1ec539ea16307e0785b9..793b1309528671ce822d5a484ff9e40d6eba4e9d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2609,6 +2609,7 @@ public class CraftWorld implements World { - lightning.moveTo( loc.getX(), loc.getY(), loc.getZ() ); - lightning.visualOnly = true; - lightning.isSilent = isSilent; -+ world.strikeLightning( lightning ); - return (LightningStrike) lightning.getBukkitEntity(); - } - }; diff --git a/Remapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch b/Remapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch deleted file mode 100644 index a1593c3e27..0000000000 --- a/Remapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 24 Jul 2020 15:56:05 -0700 -Subject: [PATCH] Fix some rails connecting improperly - - -diff --git a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java -index 1a44c8b41928a83a22b53d1b6f45ce39b4caf2b2..7cef6d1fc2045c62d4e96a0fd0a311d089cb1406 100644 ---- a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java -@@ -62,6 +62,7 @@ public abstract class BaseRailBlock extends Block { - state = this.updateDir(world, pos, state, true); - if (this.isStraight) { - state.neighborChanged(world, pos, this, pos, notify); -+ state = world.getBlockState(pos); // Paper - don't desync, update again - } - - return state; -diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java -index 0ab1e15d8575c3e90a10b80b94030e15a01faac9..1854809e045300e84a713dc7c3a8264f53ec6c0f 100644 ---- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java -@@ -70,6 +70,7 @@ public class DetectorRailBlock extends BaseRailBlock { - - private void checkPressed(Level world, BlockPos pos, BlockState state) { - if (this.canSurvive(state, world, pos)) { -+ if (state.getBlock() != this) { return; } // Paper - not our block, don't do anything - boolean flag = (Boolean) state.getValue(DetectorRailBlock.POWERED); - boolean flag1 = false; - List list = this.getInteractingMinecartOfType(world, pos, AbstractMinecart.class, (Predicate) null); -diff --git a/src/main/java/net/minecraft/world/level/block/RailState.java b/src/main/java/net/minecraft/world/level/block/RailState.java -index 0d824ab98dcdd6ea9dac025c37970fb4ec464131..4c17bec369fb19f47760e30b391b2128cee6b276 100644 ---- a/src/main/java/net/minecraft/world/level/block/RailState.java -+++ b/src/main/java/net/minecraft/world/level/block/RailState.java -@@ -12,13 +12,19 @@ import net.minecraft.world.level.block.state.properties.RailShape; - - public class RailState { - -- private final Level level; -- private final BlockPos pos; -+ private final Level level; public final Level getWorld() { return this.level; } // Paper - OBFHELPER -+ private final BlockPos pos; public final BlockPos getPos() { return this.pos; } // Paper - OBFHELPER - private final BaseRailBlock block; -- private BlockState state; -+ private BlockState state; public final BlockState getRailState() { return this.state; } // Paper - OBFHELPER - private final boolean isStraight; - private final List connections = Lists.newArrayList(); - -+ // Paper start - prevent desync -+ public boolean isValid() { -+ return this.getWorld().getBlockState(this.getPos()).getBlock() == this.getRailState().getBlock(); -+ } -+ // Paper end - prevent desync -+ - public RailState(Level world, BlockPos pos, BlockState state) { - this.level = world; - this.pos = pos; -@@ -153,6 +159,11 @@ public class RailState { - } - - private void connectTo(RailState placementHelper) { -+ // Paper start - prevent desync -+ if (!this.isValid() || !placementHelper.isValid()) { -+ return; -+ } -+ // Paper end - prevent desync - this.connections.add(placementHelper.pos); - BlockPos blockposition = this.pos.north(); - BlockPos blockposition1 = this.pos.south(); -@@ -347,11 +358,16 @@ public class RailState { - this.state = (BlockState) this.state.setValue(this.block.getShapeProperty(), blockpropertytrackposition1); - if (forceUpdate || this.level.getBlockState(this.pos) != this.state) { - this.level.setBlock(this.pos, this.state, 3); -+ // Paper start - prevent desync -+ if (!this.isValid()) { -+ return this; -+ } -+ // Paper end - prevent desync - - for (int i = 0; i < this.connections.size(); ++i) { - RailState minecarttracklogic = this.getRail((BlockPos) this.connections.get(i)); - -- if (minecarttracklogic != null) { -+ if (minecarttracklogic != null && minecarttracklogic.isValid()) { // Paper - prevent desync - minecarttracklogic.removeSoftConnections(); - if (minecarttracklogic.canConnectTo(this)) { - minecarttracklogic.connectTo(this); -@@ -364,6 +380,6 @@ public class RailState { - } - - public BlockState getState() { -- return this.state; -+ return this.getWorld().getBlockState(this.getPos()); // Paper - prevent desync - } - } diff --git a/Remapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/Remapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch deleted file mode 100644 index 7f15a77054..0000000000 --- a/Remapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 4 Aug 2020 22:24:15 +0200 -Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections - -I utilized the IDE to convert streams to non streams code, so shouldn't -be any risk of behavior change. Only did minor optimization of the -generated code set to remove unnecessary things. - -I expect us to just drop this patch on next major update and re-apply -it with the IDE again and re-apply the collections optimization. - -Optimize collection by creating a list instead of a set of the key and value. - -This lets us get faster foreach iteration, as well as avoids map lookups on -the values when needed. - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -index ba8ee93032aabe7ec4ecf52d452e1a580d6ebc20..2ef0e04af771e14f8d71aef4ccb81d3b81db7df5 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -@@ -33,28 +33,31 @@ public class PathFinder { - this.openSet.a(); - this.nodeEvaluator.prepare(world, mob); - Node pathpoint = this.nodeEvaluator.getStart(); -- Map map = (Map) positions.stream().collect(Collectors.toMap((blockposition) -> { -- return this.nodeEvaluator.getGoal((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); -- }, Function.identity())); -- Path pathentity = this.findPath(pathpoint, map, followRange, distance, rangeMultiplier); -+ // Paper start - remove streams - and optimize collection -+ List> map = Lists.newArrayList(); -+ for (BlockPos blockposition : positions) { -+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal((double) blockposition.getX(), blockposition.getY(), blockposition.getZ()), blockposition)); -+ } -+ // Paper end -+ Path pathentity = this.a(pathpoint, map, followRange, distance, rangeMultiplier); - - this.nodeEvaluator.done(); - return pathentity; - } - - @Nullable -- private Path findPath(Node startNode, Map positions, float followRange, int distance, float rangeMultiplier) { -- Set set = positions.keySet(); -+ private Path a(Node pathpoint, List> list, float f, int i, float f1) { // Paper - optimize collection -+ //Set set = map.keySet(); // Paper - -- startNode.g = 0.0F; -- startNode.h = this.getBestH(startNode, set); -- startNode.f = startNode.h; -+ pathpoint.g = 0.0F; -+ pathpoint.h = this.a(pathpoint, list); // Paper - optimize collection -+ pathpoint.f = pathpoint.h; - this.openSet.a(); -- this.openSet.a(startNode); -+ this.openSet.a(pathpoint); - Set set1 = ImmutableSet.of(); - int j = 0; -- Set set2 = Sets.newHashSetWithExpectedSize(set.size()); -- int k = (int) ((float) this.maxVisitedNodes * rangeMultiplier); -+ List> set2 = Lists.newArrayListWithExpectedSize(list.size()); // Paper - optimize collection -+ int k = (int) ((float) this.maxVisitedNodes * f1); - - while (!this.openSet.e()) { - ++j; -@@ -65,14 +68,15 @@ public class PathFinder { - Node pathpoint1 = this.openSet.c(); - - pathpoint1.closed = true; -- Iterator iterator = set.iterator(); -- -- while (iterator.hasNext()) { -- Target pathdestination = (Target) iterator.next(); -+ // Paper start - optimize collection -+ for (int i1 = 0; i1 < list.size(); i1++) { -+ Map.Entry entry = list.get(i1); -+ Target pathdestination = entry.getKey(); - -- if (pathpoint1.distanceManhattan((Node) pathdestination) <= (float) distance) { -+ if (pathpoint1.distanceManhattan((Node) pathdestination) <= (float) i) { - pathdestination.setReached(); -- set2.add(pathdestination); -+ set2.add(entry); -+ // Paper end - } - } - -@@ -80,7 +84,7 @@ public class PathFinder { - break; - } - -- if (pathpoint1.distanceTo(startNode) < followRange) { -+ if (pathpoint1.distanceTo(pathpoint) < f) { - int l = this.nodeEvaluator.getNeighbors(this.neighbors, pathpoint1); - - for (int i1 = 0; i1 < l; ++i1) { -@@ -90,10 +94,10 @@ public class PathFinder { - pathpoint2.walkedDistance = pathpoint1.walkedDistance + f2; - float f3 = pathpoint1.g + f2 + pathpoint2.costMalus; - -- if (pathpoint2.walkedDistance < followRange && (!pathpoint2.inOpenSet() || f3 < pathpoint2.g)) { -+ if (pathpoint2.walkedDistance < f && (!pathpoint2.inOpenSet() || f3 < pathpoint2.g)) { - pathpoint2.cameFrom = pathpoint1; - pathpoint2.g = f3; -- pathpoint2.h = this.getBestH(pathpoint2, set) * 1.5F; -+ pathpoint2.h = this.a(pathpoint2, list) * 1.5F; // Paper - list instead of set - if (pathpoint2.inOpenSet()) { - this.openSet.a(pathpoint2, pathpoint2.g + pathpoint2.h); - } else { -@@ -105,31 +109,32 @@ public class PathFinder { - } - } - -- Optional optional = !set2.isEmpty() ? set2.stream().map((pathdestination1) -> { -- return this.reconstructPath(pathdestination1.getBestNode(), (BlockPos) positions.get(pathdestination1), true); -- }).min(Comparator.comparingInt(Path::getNodeCount)) : set.stream().map((pathdestination1) -> { -- return this.reconstructPath(pathdestination1.getBestNode(), (BlockPos) positions.get(pathdestination1), false); -- }).min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount)); -- -- if (!optional.isPresent()) { -- return null; -- } else { -- Path pathentity = (Path) optional.get(); -- -- return pathentity; -+ // Paper start - remove streams - and optimize collection -+ Path best = null; -+ boolean useSet1 = set2.isEmpty(); -+ Comparator comparator = useSet1 ? Comparator.comparingInt(Path::getNodeCount) -+ : Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount); -+ for (Map.Entry entry : useSet1 ? list : set2) { -+ Path pathEntity = this.reconstructPath(entry.getKey().getBestNode(), entry.getValue(), !useSet1); -+ if (best == null || comparator.compare(pathEntity, best) < 0) -+ best = pathEntity; - } -+ return best; -+ // Paper end - } - -- private float getBestH(Node node, Set targets) { -+ private float a(Node pathpoint, List> list) { // Paper - optimize collection - float f = Float.MAX_VALUE; - - float f1; - -- for (Iterator iterator = targets.iterator(); iterator.hasNext(); f = Math.min(f1, f)) { -- Target pathdestination = (Target) iterator.next(); -+ // Paper start - optimize collection -+ for (int i = 0, listSize = list.size(); i < listSize; f = Math.min(f1, f), i++) { // Paper -+ Target pathdestination = list.get(i).getKey(); // Paper -+ // Paper end - -- f1 = node.distanceTo(pathdestination); -- pathdestination.updateBest(f1, node); -+ f1 = pathpoint.distanceTo(pathdestination); -+ pathdestination.updateBest(f1, pathpoint); - } - - return f; diff --git a/Remapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch b/Remapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch deleted file mode 100644 index cd7713a510..0000000000 --- a/Remapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 9 Aug 2020 08:59:25 +0300 -Subject: [PATCH] Incremental player saving - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index b67ba8f75e4a3358d7c2462918b85b0bf9b5a922..fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -440,4 +440,15 @@ public class PaperConfig { - allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); - set("settings.unsupported-settings.allow-tnt-duplication", null); - } -+ -+ public static int playerAutoSaveRate = -1; -+ public static int maxPlayerAutoSavePerTick = 10; -+ private static void playerAutoSaveRate() { -+ playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1); -+ maxPlayerAutoSavePerTick = getInt("settings.max-player-auto-save-per-tick", -1); -+ if (maxPlayerAutoSavePerTick == -1) { // -1 Automatic / "Recommended" -+ // 10 should be safe for everyone unless you mass spamming player auto save -+ maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 19544b794b5a46c129016172798ff7294fcfed33..735c3c983e96e4e6f36de0975909fc48cb042081 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1347,9 +1347,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down - //MinecraftServer.LOGGER.debug("Autosave started"); // Paper - serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper -+ // Paper start -+ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate; -+ if (playerSaveInterval < 0) { -+ playerSaveInterval = autosavePeriod; -+ } -+ // Paper end - this.profiler.push("save"); -- if (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0) { // Paper -- this.playerList.saveAll(); -+ if (playerSaveInterval > 0) { // Paper -+ this.playerList.savePlayers(playerSaveInterval); // Paper - }// Paper - // Paper start - for (ServerLevel world : getAllLevels()) { -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index c5717f45a0110492aad41f21cc06fb8cbeb1f791..bd4d4ace35e966e819aa461d3962fe06ff402be7 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -173,6 +173,7 @@ import org.bukkit.inventory.MainHand; - public class ServerPlayer extends Player implements ContainerListener { - - private static final Logger LOGGER = LogManager.getLogger(); -+ public long lastSave = MinecraftServer.currentTick; // Paper - public ServerGamePacketListenerImpl connection; - public Connection networkManager; // Paper - public final MinecraftServer server; -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 882cd25c9610f0b995c27291aa62846922ab531f..b76735531ef96f9d4c870a5107feea01524a7670 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -559,6 +559,7 @@ public abstract class PlayerList { - protected void save(ServerPlayer player) { - if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit - if (!player.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) -+ player.lastSave = MinecraftServer.currentTick; // Paper - this.playerIo.save(player); - ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit - -@@ -1218,10 +1219,21 @@ public abstract class PlayerList { - } - - public void saveAll() { -+ // Paper start - incremental player saving -+ savePlayers(null); -+ } -+ public void savePlayers(Integer interval) { - MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper -+ int numSaved = 0; -+ long now = MinecraftServer.currentTick; - for (int i = 0; i < this.players.size(); ++i) { -- this.save((ServerPlayer) this.players.get(i)); -+ ServerPlayer entityplayer = this.players.get(i); -+ if (interval == null || now - entityplayer.lastSave >= interval) { -+ this.save(entityplayer); -+ if (interval != null && ++numSaved <= com.destroystokyo.paper.PaperConfig.maxPlayerAutoSavePerTick) { break; } -+ } -+ // Paper end - } - MinecraftTimings.savePlayers.stopTiming(); // Paper - return null; }); // Paper - ensure main diff --git a/Remapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch b/Remapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch deleted file mode 100644 index 706c8236e3..0000000000 --- a/Remapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 12 Aug 2020 11:33:04 +0200 -Subject: [PATCH] Import fastutil classes - - -diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java -index 95e166aa63f42c675df645a56e313bdffc2e8663..05f7d4a3835536f26f741d54a0884bd43fc82967 100644 ---- a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java -+++ b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java -@@ -16,6 +16,7 @@ import net.minecraft.CrashReport; - import net.minecraft.ReportedException; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.world.entity.Entity; -+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; // Paper - import org.apache.commons.lang3.ObjectUtils; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -25,7 +26,7 @@ public class SynchedEntityData { - private static final Logger LOGGER = LogManager.getLogger(); - private static final Map, Integer> ENTITY_ID_POOL = Maps.newHashMap(); - private final Entity entity; -- private final it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap> entries = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL -+ private final Int2ObjectOpenHashMap> entries = new Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL - // private final ReadWriteLock lock = new ReentrantReadWriteLock(); // Spigot - not required - private boolean isEmpty = true; - private boolean isDirty; diff --git a/Remapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch b/Remapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch deleted file mode 100644 index 3a19fd93b1..0000000000 --- a/Remapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Fri, 14 Aug 2020 23:41:19 +0200 -Subject: [PATCH] Don't mark null chunk sections for block updates - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 9e3629884709126574a52ad44fe7523f01dbcce9..82205ad13ef0e987bd83979d06331545efe0a60a 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -449,6 +449,7 @@ public class ChunkHolder { - this.broadcastBlockEntityIfNeeded(world, blockposition, iblockdata); - } else { - LevelChunkSection chunksection = chunk.getSections()[sectionposition.getY()]; -+ if (chunksection == null) chunksection = new LevelChunkSection(sectionposition.getY(), chunk, world, true); // Paper - make a new chunk section if none was found - ClientboundSectionBlocksUpdatePacket packetplayoutmultiblockchange = new ClientboundSectionBlocksUpdatePacket(sectionposition, shortset, chunksection, this.resendLight); - - this.broadcast(packetplayoutmultiblockchange, false); diff --git a/Remapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch b/Remapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch deleted file mode 100644 index 8e11c05922..0000000000 --- a/Remapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Fri, 14 Aug 2020 23:59:26 +0200 -Subject: [PATCH] Remove armour stand double add to world - - -diff --git a/src/main/java/net/minecraft/world/item/ArmorStandItem.java b/src/main/java/net/minecraft/world/item/ArmorStandItem.java -index a2dfcaac8a2a4a69e703de43be76d4fe369fd647..bed063497bb593683ea384605ae1a71a68f4fc1b 100644 ---- a/src/main/java/net/minecraft/world/item/ArmorStandItem.java -+++ b/src/main/java/net/minecraft/world/item/ArmorStandItem.java -@@ -53,7 +53,7 @@ public class ArmorStandItem extends Item { - return InteractionResult.FAIL; - } - -- worldserver.addFreshEntityWithPassengers(entityarmorstand); -+ // Paper - moved down - float f = (float) Mth.floor((Mth.wrapDegrees(context.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F; - - entityarmorstand.moveTo(entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), f, 0.0F); -@@ -63,7 +63,7 @@ public class ArmorStandItem extends Item { - return InteractionResult.FAIL; - } - // CraftBukkit end -- world.addFreshEntity(entityarmorstand); -+ worldserver.addFreshEntityWithPassengers(entityarmorstand); // Paper - moved down - world.playSound((Player) null, entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F); - } - diff --git a/Remapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch b/Remapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch deleted file mode 100644 index 1e2cd52d5b..0000000000 --- a/Remapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 15 Aug 2020 08:04:49 -0500 -Subject: [PATCH] Fix MC-187716 Use configured height - - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java -index 3f297ef7bde4159c77681574966446a0eba03f25..ff17c76f341028dd6d17f4c1f13f442c2e404532 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java -@@ -44,7 +44,7 @@ public abstract class NetherCappedSurfaceBuilder extends SurfaceBuilder= 0; --k2) { -+ for (int k2 = height; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.set(k1, k2, l1); - BlockState iblockdata5 = chunk.getBlockState(blockposition_mutableblockposition); - int l2; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java -index 4d6c03048022442dea467e1d9d018f150adc62c7..f64671b7359fb71e8af578d48d0a3c211e315057 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java -@@ -34,7 +34,7 @@ public class NetherForestSurfaceBuilder extends SurfaceBuilder= 0; --k2) { -+ for (int k2 = height; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.set(k1, k2, l1); - BlockState iblockdata3 = surfaceBlocks.getTopMaterial(); - BlockState iblockdata4 = chunk.getBlockState(blockposition_mutableblockposition); -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java -index c1e0fd7813786bf1cc03b08b204007711575f144..b222890e7bdff2c1470841677a99d4423f9c9d7f 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java -@@ -36,7 +36,7 @@ public class NetherSurfaceBuilder extends SurfaceBuilder= 0; --k2) { -+ for (int k2 = height; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.set(k1, k2, l1); - BlockState iblockdata4 = chunk.getBlockState(blockposition_mutableblockposition); - diff --git a/Remapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/Remapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch deleted file mode 100644 index c7a761474b..0000000000 --- a/Remapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mbax -Date: Mon, 17 Aug 2020 12:17:37 -0400 -Subject: [PATCH] Fix regex mistake in CB NBT int deserialization - -The existing regex is too open and allows for the absence of any actual -number data, detecting an NBT entry of just the letter "i" in upper or -lower case. This causes a single-character NBT entry to be processed as -an integer ending in "i", passing an empty String to to Integer.parseInt, -triggering an exception in loading the item. - -This commit forces numbers to be present prior to the ending "i" -letter. - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -index 94d46bc56b3bc4c4750fcfb1732eea0e49a04195..8ec09ff3b5aae4267b753bd715f0a9d4ef0381bd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -@@ -19,7 +19,7 @@ import net.minecraft.nbt.TagParser; - public class CraftNBTTagConfigSerializer { - - private static final Pattern ARRAY = Pattern.compile("^\\[.*]"); -- private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)?i", Pattern.CASE_INSENSITIVE); -+ private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)i", Pattern.CASE_INSENSITIVE); // Paper - fix regex - private static final Pattern DOUBLE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", Pattern.CASE_INSENSITIVE); - private static final TagParser MOJANGSON_PARSER = new TagParser(new StringReader("")); - diff --git a/Remapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch b/Remapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch deleted file mode 100644 index d47ebc8c6e..0000000000 --- a/Remapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 23 Jul 2019 20:44:47 -0500 -Subject: [PATCH] Do not let the server load chunks from newer versions - -If the server attempts to load a chunk generated by a newer version of -the game, immediately stop the server to prevent data corruption. - -You can override this functionality at your own peril. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 0adf14af9841cd3a20a8b2c0c320eb06794ef261..f6a814f9305813eaafa56baa0327e0111cd4e38c 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -95,10 +95,24 @@ public class ChunkSerializer { - return holder.protoChunk; - } - -+ // Paper start -+ private static final int CURRENT_DATA_VERSION = SharedConstants.getCurrentVersion().getWorldVersion(); -+ private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion"); -+ // Paper end -+ - public static InProgressChunkHolder loadChunk(ServerLevel worldserver, StructureManager definedstructuremanager, PoiManager villageplace, ChunkPos chunkcoordintpair, CompoundTag nbttagcompound, boolean distinguish) { - ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); - // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); -+ // Paper start - Do NOT attempt to load chunks saved with newer versions -+ if (nbttagcompound.contains("DataVersion", 99)) { -+ int dataVersion = nbttagcompound.getInt("DataVersion"); -+ if (!JUST_CORRUPT_IT && dataVersion > CURRENT_DATA_VERSION) { -+ new RuntimeException("Server attempted to load chunk saved with newer version of minecraft! " + dataVersion + " > " + CURRENT_DATA_VERSION).printStackTrace(); -+ System.exit(1); -+ } -+ } -+ // Paper end - BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); - CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate - ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate diff --git a/Remapped-Spigot-Server-Patches/0545-Brand-support.patch b/Remapped-Spigot-Server-Patches/0545-Brand-support.patch deleted file mode 100644 index e134b27182..0000000000 --- a/Remapped-Spigot-Server-Patches/0545-Brand-support.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DigitalRegent -Date: Sat, 11 Apr 2020 13:10:58 +0200 -Subject: [PATCH] Brand support - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index d264fca2737f83a0860394f7bb6b269ffe669594..ab6494f5a872bba5398bef0367b4d9257786f61e 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -5,6 +5,7 @@ import com.google.common.primitives.Doubles; - import com.google.common.primitives.Floats; - import com.mojang.brigadier.ParseResults; - import com.mojang.brigadier.StringReader; -+import io.netty.buffer.Unpooled; - import io.netty.util.concurrent.Future; - import io.netty.util.concurrent.GenericFutureListener; - import it.unimi.dsi.fastutil.ints.Int2ShortMap; -@@ -37,6 +38,7 @@ import net.minecraft.nbt.ListTag; - import net.minecraft.nbt.StringTag; - import net.minecraft.nbt.Tag; - import net.minecraft.network.Connection; -+import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.chat.ChatType; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.MutableComponent; -@@ -258,6 +260,8 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); - private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - -+ private String clientBrandName = null; // Paper - Brand name -+ - public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { - this.server = server; - this.connection = connection; -@@ -2998,6 +3002,8 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register"); - private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister"); - -+ private static final ResourceLocation MINECRAFT_BRAND = new ResourceLocation("brand"); // Paper - Brand support -+ - @Override - public void handleCustomPayload(ServerboundCustomPayloadPacket packet) { - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); -@@ -3025,6 +3031,16 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - try { - byte[] data = new byte[packet.data.readableBytes()]; - packet.data.readBytes(data); -+ -+ // Paper start - Brand support -+ if (packet.identifier.equals(MINECRAFT_BRAND)) { -+ try { -+ this.clientBrandName = new FriendlyByteBuf(Unpooled.copiedBuffer(data)).readUTF(256); -+ } catch (StringIndexOutOfBoundsException ex) { -+ this.clientBrandName = "illegal"; -+ } -+ } -+ // Paper end - craftServer.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packet.identifier.toString(), data); - } catch (Exception ex) { - ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); -@@ -3034,6 +3050,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - } - -+ // Paper start - brand support -+ public String getClientBrandName() { -+ return clientBrandName; -+ } -+ // Paper end -+ - public final boolean isDisconnected() { - return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 610eabd2e93f9efccee810c3b5a314bc3cc649d8..7aae63d22167dc1b3ec7e8bc8672855c2038007e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2385,6 +2385,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - // Paper end - }; - -+ // Paper start - brand support -+ @Override -+ public String getClientBrandName() { -+ return getHandle().connection != null ? getHandle().connection.getClientBrandName() : null; -+ } -+ // Paper end -+ - public Player.Spigot spigot() - { - return spigot; diff --git a/Remapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch b/Remapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch deleted file mode 100644 index d3257fe8be..0000000000 --- a/Remapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Thu, 20 Aug 2020 19:24:13 -0700 -Subject: [PATCH] Fix MC-99259 Wither Boss Bar doesn't update until - invulnerability period is over - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index edd231568b75330d0cffbecb03a7e9dbc55d5f94..1f330d852eb9b3a36570542e10a88ae065798714 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -391,8 +391,9 @@ public class WitherBoss extends Monster implements RangedAttackMob { - this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit - } - -- this.bossEvent.setPercent(this.getHealth() / this.getMaxHealth()); -+ //this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Moved down - } -+ this.bossEvent.setPercent(this.getHealth() / this.getMaxHealth()); // Paper - Fix MC-99259 (Boss bar does not update until Wither invulnerability period ends) - } - - public static boolean canDestroy(BlockState block) { diff --git a/Remapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch b/Remapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch deleted file mode 100644 index 14ad3b04d2..0000000000 --- a/Remapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ishland -Date: Sun, 23 Aug 2020 10:57:44 +0200 -Subject: [PATCH] Fix MC-197271 - -This patch only fixes an issue for servers running OpenJ9. - -diff --git a/src/main/java/net/minecraft/data/BuiltinRegistries.java b/src/main/java/net/minecraft/data/BuiltinRegistries.java -index d64cebb4431664762a14670c7d9d782dd7894ed5..0c403ea85f7ea20f2f978e06313f8675abf204b6 100644 ---- a/src/main/java/net/minecraft/data/BuiltinRegistries.java -+++ b/src/main/java/net/minecraft/data/BuiltinRegistries.java -@@ -48,11 +48,11 @@ public class BuiltinRegistries { - public static final Registry PROCESSOR_LIST = registerSimple(Registry.PROCESSOR_LIST_REGISTRY, () -> { - return ProcessorLists.b; - }); -- public static final Registry TEMPLATE_POOL = registerSimple(Registry.TEMPLATE_POOL_REGISTRY, Pools::bootstrap); -+ public static final Registry TEMPLATE_POOL = registerSimple(Registry.TEMPLATE_POOL_REGISTRY, () -> Pools.bootstrap()); // Paper - MC-197271 - public static final Registry BIOME = registerSimple(Registry.BIOME_REGISTRY, () -> { - return Biomes.PLAINS; - }); -- public static final Registry NOISE_GENERATOR_SETTINGS = registerSimple(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY, NoiseGeneratorSettings::bootstrap); -+ public static final Registry NOISE_GENERATOR_SETTINGS = registerSimple(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY, () -> NoiseGeneratorSettings.bootstrap()); // Paper - MC-197271 - - private static Registry registerSimple(ResourceKey> registryRef, Supplier defaultValueSupplier) { - return registerSimple(registryRef, Lifecycle.stable(), defaultValueSupplier); -@@ -66,9 +66,9 @@ public class BuiltinRegistries { - ResourceLocation minecraftkey = registryRef.location(); - - BuiltinRegistries.LOADERS.put(minecraftkey, defaultValueSupplier); -- WritableRegistry iregistrywritable = BuiltinRegistries.WRITABLE_REGISTRY; -+ WritableRegistry iregistrywritable = (WritableRegistry) BuiltinRegistries.WRITABLE_REGISTRY; // Paper - decompile fix - -- return (WritableRegistry) iregistrywritable.register(registryRef, (Object) registry, lifecycle); -+ return (R) iregistrywritable.register((ResourceKey) registryRef, registry, lifecycle); // Paper - decompile fix - } - - public static T register(Registry registry, String id, T object) { -@@ -76,11 +76,11 @@ public class BuiltinRegistries { - } - - public static T register(Registry registry, ResourceLocation id, T object) { -- return ((WritableRegistry) registry).register(ResourceKey.create(registry.key(), id), object, Lifecycle.stable()); -+ return (T) ((WritableRegistry) registry).register(ResourceKey.create(registry.key(), id), object, Lifecycle.stable()); // Paper - decompile fix - } - - public static T registerMapping(Registry iregistry, int rawId, ResourceKey resourcekey, T object) { -- return ((WritableRegistry) iregistry).registerMapping(rawId, resourcekey, object, Lifecycle.stable()); -+ return (T) ((WritableRegistry) iregistry).registerMapping(rawId, resourcekey, object, Lifecycle.stable()); // Paper - decompile fix - } - - public static void bootstrap() {} diff --git a/Remapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch b/Remapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch deleted file mode 100644 index fd35ea34e4..0000000000 --- a/Remapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 21 Aug 2020 21:05:28 -0400 -Subject: [PATCH] MC-197883: Bandaid decode issue - -Mojang has a mix of type and name in the data sets, but you can only -use one. - -This will retry as name if type is asked for and not found. - -diff --git a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java -index de7d1e5e0319c65775d932144c268c2d55bb7dc7..bd6a0e1b5454e880a4f2a16be7dc8da64b73e11d 100644 ---- a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java -+++ b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java -@@ -48,7 +48,12 @@ public class KeyDispatchCodec extends MapCodec { - - @Override - public DataResult decode(final DynamicOps ops, final MapLike input) { -- final T elementName = input.get(typeKey); -+ // Paper start - bandaid MC-197883 -+ T elementName = input.get(typeKey); -+ if (elementName == null && "type".equals(typeKey)) { -+ elementName = input.get("name"); -+ } -+ // Paper end - if (elementName == null) { - return DataResult.error("Input does not contain a key [" + typeKey + "]: " + input); - } diff --git a/Remapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch b/Remapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch deleted file mode 100644 index bfd99ce60a..0000000000 --- a/Remapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 22 Aug 2020 23:59:30 +0200 -Subject: [PATCH] Add #setMaxPlayers API - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index b76735531ef96f9d4c870a5107feea01524a7670..7e44c911f4abc5c7d0e89513bf2cfc3516f13492 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -141,7 +141,7 @@ public abstract class PlayerList { - public final PlayerDataStorage playerIo; - private boolean doWhiteList; - private final RegistryAccess.RegistryHolder registryHolder; -- protected final int maxPlayers; -+ protected int maxPlayers; public final void setMaxPlayers(int maxPlayers) { this.maxPlayers = maxPlayers; } // Paper - remove final and add setter - private int viewDistance; - private GameType overrideGameMode; - private boolean allowCheatsForAllPlayers; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e301aee53b19fc3f93a36d0ed03a649741123bfa..e599be15af17e5e45d2b694c30140cc4a787a7f5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -613,6 +613,13 @@ public final class CraftServer implements Server { - return playerList.getMaxPlayers(); - } - -+ // Paper start -+ @Override -+ public void setMaxPlayers(int maxPlayers) { -+ this.playerList.setMaxPlayers(maxPlayers); -+ } -+ // Paper end -+ - // NOTE: These are dependent on the corresponding call in MinecraftServer - // so if that changes this will need to as well - @Override diff --git a/Remapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch b/Remapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch deleted file mode 100644 index e3089f12ce..0000000000 --- a/Remapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 23 Aug 2020 19:36:22 +0200 -Subject: [PATCH] Add playPickupItemAnimation to LivingEntity - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 067eaf1e05ced344eb168431403f3fe786eafddf..eb136af0f99f5d7520ceabb98cefd5a01122872c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -806,5 +806,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - ((Mob) getHandle()).getJumpControl().jump(); - } - } -+ -+ @Override -+ public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { -+ getHandle().take(((CraftItem) item).getHandle(), quantity); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch b/Remapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch deleted file mode 100644 index 5ecdef5062..0000000000 --- a/Remapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sun, 23 Aug 2020 19:01:04 +0200 -Subject: [PATCH] Don't require FACING data - - -diff --git a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -index f7e60cdfa0b3f5970a897b5d52aaa72210f2fa57..ab8e69f9fc38012844ce01bd0cc5be8de2fcf4ab 100644 ---- a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -+++ b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -@@ -14,20 +14,22 @@ import org.bukkit.event.block.BlockDispenseEvent; - // CraftBukkit end - - public class DefaultDispenseItemBehavior implements DispenseItemBehavior { -+ private Direction enumdirection; // Paper - - public DefaultDispenseItemBehavior() {} - - @Override - public final ItemStack dispense(BlockSource pointer, ItemStack stack) { -+ enumdirection = pointer.getBlockState().getValue(DispenserBlock.FACING); // Paper - cache facing direction - ItemStack itemstack1 = this.execute(pointer, stack); - - this.playSound(pointer); -- this.playAnimation(pointer, (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING)); -+ this.playAnimation(pointer, enumdirection); // Paper - cache facing direction - return itemstack1; - } - - protected ItemStack execute(BlockSource pointer, ItemStack stack) { -- Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING); -+ // Paper - cached enum direction - Position iposition = DispenserBlock.getDispensePosition(pointer); - ItemStack itemstack1 = stack.split(1); - diff --git a/Remapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/Remapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch deleted file mode 100644 index 7947c73149..0000000000 --- a/Remapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 22 Aug 2020 23:36:21 +0200 -Subject: [PATCH] Fix SpawnChangeEvent not firing for all use-cases - - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 61aee2c109614a014149ae5a15ad2a28c796cb9d..22266fda4de9b5fbace3b8e55ce390b8d7e75a65 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1981,12 +1981,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - // Paper end - -+ public final void setSpawn(BlockPos blockposition, float f) { this.setDefaultSpawnPos(blockposition, f); } // Paper - OBFHELPER - public void setDefaultSpawnPos(BlockPos pos, float angle) { - // Paper - configurable spawn radius - BlockPos prevSpawn = this.getSpawn(); - //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); - - this.levelData.setSpawn(pos, angle); -+ new org.bukkit.event.world.SpawnChangeEvent(getWorld(), MCUtil.toLocation(this, prevSpawn)).callEvent(); // Paper - if (this.keepSpawnInMemory) { - // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add - this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 793b1309528671ce822d5a484ff9e40d6eba4e9d..37513a1774f5a6611338c1b90018b974238ddbf6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -371,11 +371,13 @@ public class CraftWorld implements World { - public boolean setSpawnLocation(int x, int y, int z, float angle) { - try { - Location previousLocation = getSpawnLocation(); -- world.levelData.setSpawn(new BlockPos(x, y, z), angle); -+ world.setSpawn(new BlockPos(x, y, z), angle); // Paper - use WorldServer#setSpawn - -+ // Paper start - move to nms.World - // Notify anyone who's listening. -- SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); -- server.getPluginManager().callEvent(event); -+ // SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); -+ // server.getPluginManager().callEvent(event); -+ // Paper end - - return true; - } catch (Exception e) { diff --git a/Remapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch b/Remapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch deleted file mode 100644 index bd3ee0c1e2..0000000000 --- a/Remapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 16:32:11 +0200 -Subject: [PATCH] Add moon phase API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 37513a1774f5a6611338c1b90018b974238ddbf6..28bf53bc9fca21f57cd4851adf508d833ecdd33b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -310,6 +310,11 @@ public class CraftWorld implements World { - public int getPlayerCount() { - return world.players.size(); - } -+ -+ @Override -+ public io.papermc.paper.world.MoonPhase getMoonPhase() { -+ return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); -+ } - // Paper end - - private static final Random rand = new Random(); diff --git a/Remapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch b/Remapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch deleted file mode 100644 index 15edeb8af6..0000000000 --- a/Remapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: commandblockguy -Date: Fri, 14 Aug 2020 14:44:14 -0500 -Subject: [PATCH] Prevent headless pistons from being created - -Prevent headless pistons from being created by explosions or tree/mushroom growth. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb..faa1b775e45563b93ac1d5b904938b1f5ad8d80c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -441,6 +441,12 @@ public class PaperConfig { - set("settings.unsupported-settings.allow-tnt-duplication", null); - } - -+ public static boolean allowHeadlessPistons; -+ private static void allowHeadlessPistons() { -+ config.set("settings.unsupported-settings.allow-headless-pistons-readme", "This setting controls if players should be able to create headless pistons."); -+ allowHeadlessPistons = getBoolean("settings.unsupported-settings.allow-headless-pistons", false); -+ } -+ - public static int playerAutoSaveRate = -1; - public static int maxPlayerAutoSavePerTick = 10; - private static void playerAutoSaveRate() { -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 0f0a5fa2be5a7c69291b593a04cad83e069ba5b1..f7ca5294fe571770e3b0036e92563c5a099f76b1 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -15,6 +15,7 @@ import java.util.Random; - import java.util.Set; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; -+import net.minecraft.core.Direction; - import net.minecraft.core.Vec3i; - import net.minecraft.core.particles.ParticleTypes; - import net.minecraft.server.level.ServerLevel; -@@ -35,6 +36,8 @@ import net.minecraft.world.level.block.BaseFireBlock; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.BlockEntity; -+import net.minecraft.world.level.block.piston.PistonHeadBlock; -+import net.minecraft.world.level.block.piston.PistonMovingBlockEntity; - import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.level.material.FluidState; - import net.minecraft.world.level.storage.loot.LootContext; -@@ -161,6 +164,15 @@ public class Explosion { - - if (f > 0.0F && this.damageCalculator.a(this, this.level, blockposition, iblockdata, f) && blockposition.getY() < 256 && blockposition.getY() >= 0) { // CraftBukkit - don't wrap explosions - set.add(blockposition); -+ // Paper start - prevent headless pistons from forming -+ if (!com.destroystokyo.paper.PaperConfig.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) { -+ BlockEntity extension = this.level.getBlockEntity(blockposition); -+ if (extension instanceof PistonMovingBlockEntity && ((PistonMovingBlockEntity) extension).isHead()) { -+ Direction direction = iblockdata.getValue(PistonHeadBlock.FACING); -+ set.add(blockposition.relative(direction.getOpposite())); -+ } -+ } -+ // Paper end - } - - d4 += d0 * 0.30000001192092896D; -diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -index 001e90da8b09e16b6df4849a5bac4f4821000c94..81f3c6fb7bab9de364537d3f3b2ea0f32795e5f1 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -@@ -65,6 +65,8 @@ public class PistonMovingBlockEntity extends BlockEntity implements TickableBloc - return this.direction; - } - -+ public final boolean isHead() { return this.isSourcePiston(); } // Paper - OBFHELPER -+ - public boolean isSourcePiston() { - return this.isSourcePiston; - } diff --git a/Remapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch b/Remapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch deleted file mode 100644 index 05dfb6c0bb..0000000000 --- a/Remapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Eearslya Sleiarion -Date: Sun, 23 Aug 2020 13:04:02 +0200 -Subject: [PATCH] Add BellRingEvent - -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/net/minecraft/world/level/block/BellBlock.java b/src/main/java/net/minecraft/world/level/block/BellBlock.java -index affae471e50354bfa9594e188e6dcea183b9b5c9..dc5dc9e533c71908b7a9a3cc9e614bd4a0dcde98 100644 ---- a/src/main/java/net/minecraft/world/level/block/BellBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/BellBlock.java -@@ -1,8 +1,11 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.BellRingEvent; -+ - import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.stats.Stats; -@@ -89,7 +92,7 @@ public class BellBlock extends BaseEntityBlock { - boolean flag1 = !flag || this.isProperHit(state, enumdirection, movingobjectpositionblock.getLocation().y - (double) blockposition.getY()); - - if (flag1) { -- boolean flag2 = this.attemptToRing(world, blockposition, enumdirection); -+ boolean flag2 = this.handleBellRing(world, blockposition, enumdirection, entityhuman); // Paper - - if (flag2 && entityhuman != null) { - entityhuman.awardStat(Stats.BELL_RING); -@@ -123,15 +126,21 @@ public class BellBlock extends BaseEntityBlock { - } - - public boolean attemptToRing(Level world, BlockPos pos, @Nullable Direction enumdirection) { -- BlockEntity tileentity = world.getBlockEntity(pos); -+ // Paper start - add ringer param -+ return this.handleBellRing(world, pos, enumdirection, null); -+ } -+ public boolean handleBellRing(Level world, BlockPos blockposition, @Nullable Direction enumdirection, @Nullable Entity ringer) { -+ // Paper end -+ BlockEntity tileentity = world.getBlockEntity(blockposition); - - if (!world.isClientSide && tileentity instanceof BellBlockEntity) { - if (enumdirection == null) { -- enumdirection = (Direction) world.getBlockState(pos).getValue(BellBlock.FACING); -+ enumdirection = (Direction) world.getBlockState(blockposition).getValue(BellBlock.FACING); - } - -+ if (!new BellRingEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, blockposition)), ringer == null ? null : ringer.getBukkitEntity()).callEvent()) return false; // Paper - BellRingEvent - ((BellBlockEntity) tileentity).onHit(enumdirection); -- world.playSound((Player) null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); -+ world.playSound((Player) null, blockposition, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); - return true; - } else { - return false; diff --git a/Remapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch b/Remapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch deleted file mode 100644 index d46a54fd32..0000000000 --- a/Remapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 15:47:34 +0200 -Subject: [PATCH] Add zombie targets turtle egg config - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 978062774c1db286bfb9b0ffdef19d880b1f249b..36ecdfce84141ac731b827e469ac842f5c666259 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -668,4 +668,9 @@ public class PaperWorldConfig { - maxLightningFlashDistance = 512; // Vanilla value - } - } -+ -+ public boolean zombiesTargetTurtleEggs = true; -+ private void zombiesTargetTurtleEggs() { -+ zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 1e7c2c603b967c8c606efd94ce95a17c856f78d7..4105c1763d25824aac35d305a793823c1604eee8 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -104,7 +104,7 @@ public class Zombie extends Monster { - - @Override - protected void registerGoals() { -- this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); -+ if (level.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); // Paper - this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); - this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); - this.addBehaviourGoals(); diff --git a/Remapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch b/Remapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch deleted file mode 100644 index b9f930aa4e..0000000000 --- a/Remapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Wed, 19 Aug 2020 05:05:54 +0100 -Subject: [PATCH] Buffer joins to world - -This patch buffers the number of logins which will attempt to join -the world per tick, this attempts to reduce the impact that join floods -has on the server - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index faa1b775e45563b93ac1d5b904938b1f5ad8d80c..545948f20efd6c8dd42140b565af94cd6b52b661 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -457,4 +457,9 @@ public class PaperConfig { - maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; - } - } -+ -+ public static int maxJoinsPerTick; -+ private static void maxJoinsPerTick() { -+ maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); -+ } - } -diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index fc63df21aecd4721efdb45d4744666ed0b562c1b..6f7cbce5a049d87d4a0ed7cc4517cb4e8694efb5 100644 ---- a/src/main/java/net/minecraft/network/Connection.java -+++ b/src/main/java/net/minecraft/network/Connection.java -@@ -32,6 +32,7 @@ import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; - import net.minecraft.network.protocol.game.ClientboundKeepAlivePacket; - import net.minecraft.network.protocol.game.ClientboundSetTitlesPacket; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.RunningOnDifferentThreadException; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.network.ServerGamePacketListenerImpl; -@@ -382,10 +383,22 @@ public class Connection extends SimpleChannelInboundHandler> { - } - // Paper end - -+ private static final int MAX_PER_TICK = com.destroystokyo.paper.PaperConfig.maxJoinsPerTick; // Paper -+ private static int joinAttemptsThisTick; // Paper -+ private static int currTick; // Paper - public void tick() { - this.p(); -+ // Paper start -+ if (currTick != MinecraftServer.currentTick) { -+ currTick = MinecraftServer.currentTick; -+ joinAttemptsThisTick = 0; -+ } -+ // Paper end - if (this.packetListener instanceof ServerLoginPacketListenerImpl) { -+ if ( ((ServerLoginPacketListenerImpl) this.packetListener).getLoginState() != ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT // Paper -+ || (joinAttemptsThisTick++ < MAX_PER_TICK)) { // Paper - limit the number of joins which can be processed each tick - ((ServerLoginPacketListenerImpl) this.packetListener).tick(); -+ } // Paper - } - - if (this.packetListener instanceof ServerGamePacketListenerImpl) { -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index e229c7735ba88be3d8721440104958408a2a075e..659bf14cf3c949b896d0333f893a3d5e16ab9c92 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -420,7 +420,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - return new GameProfile(uuid, profile.getName()); - } - -- static enum State { -+ public enum State { // Paper - package private -> public - - HELLO, KEY, AUTHENTICATING, NEGOTIATING, READY_TO_ACCEPT, DELAY_ACCEPT, ACCEPTED; - diff --git a/Remapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch b/Remapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch deleted file mode 100644 index 002eed1eeb..0000000000 --- a/Remapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch +++ /dev/null @@ -1,1157 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: theosib -Date: Thu, 27 Sep 2018 01:43:35 -0600 -Subject: [PATCH] Optimize redstone algorithm - -Author: theosib -Co-authored-by: egg82 - -Original license: MIT - -This patch implements theosib's redstone algorithms to completely overhaul the way redstone works. -The new algorithms should be many times faster than current vanilla ones. -From the original author's comments, it looks like it shouldn't interfere with any redstone save for very extreme edge-cases. - -Surprisingly, not a lot was touched aside from a few obfuscation helpers and BlockRedstoneWire. -A lot of this code is self-contained in a helper class. - -Aside from making the obvious class/function renames and obfhelpers I didn't need to modify much. -Just added Bukkit's event system and took a few liberties with dead code and comment misspellings. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 36ecdfce84141ac731b827e469ac842f5c666259..02bb85364560784adea47c877c13291c3d016b86 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -673,4 +673,14 @@ public class PaperWorldConfig { - private void zombiesTargetTurtleEggs() { - zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); - } -+ -+ public boolean useEigencraftRedstone = false; -+ private void useEigencraftRedstone() { -+ useEigencraftRedstone = this.getBoolean("use-faster-eigencraft-redstone", false); -+ if (useEigencraftRedstone) { -+ log("Using Eigencraft redstone algorithm by theosib."); -+ } else { -+ log("Using vanilla redstone algorithm."); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..19604f4d2d0cdf65cb9f164258c4435a5a3450bc ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java -@@ -0,0 +1,913 @@ -+package com.destroystokyo.paper.util; -+ -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.ThreadLocalRandom; -+import net.minecraft.core.BlockPos; -+import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.item.Items; -+import net.minecraft.world.level.Level; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.RedStoneWireBlock; -+import net.minecraft.world.level.block.state.BlockState; -+import org.bukkit.event.block.BlockRedstoneEvent; -+ -+import com.google.common.collect.Lists; -+import com.google.common.collect.Maps; -+ -+/** -+ * Used for the faster redstone algorithm. -+ * Original author: theosib -+ * Original license: MIT -+ * -+ * Ported to Paper and updated to 1.13 by egg82 -+ */ -+public class RedstoneWireTurbo { -+ /* -+ * This is Helper class for BlockRedstoneWire. It implements a minimally-invasive -+ * bolt-on accelerator that performs a breadth-first search through redstone wire blocks -+ * in order to more efficiently and deterministically compute new redstone wire power levels -+ * and determine the order in which other blocks should be updated. -+ * -+ * Features: -+ * - Changes to BlockRedstoneWire are very limited, no other classes are affected, and the -+ * choice between old and new redstone wire update algorithms is switchable on-line. -+ * - The vanilla implementation relied on World.notifyNeighborsOfStateChange for redstone -+ * wire blocks to communicate power level changes to each other, generating 36 block -+ * updates per call. This improved implementation propagates power level changes directly -+ * between redstone wire blocks. Redstone wire power levels are therefore computed more quickly, -+ * and block updates are sent only to non-redstone blocks, many of which may perform an -+ * action when informed of a change in redstone power level. (Note: Block updates are not -+ * the same as state changes to redstone wire. Wire block states are updated as soon -+ * as they are computed.) -+ * - Of the 36 block updates generated by a call to World.notifyNeighborsOfStateChange, -+ * 12 of them are obviously redundant (e.g. the west neighbor of the east neighbor). -+ * These are eliminated. -+ * - Updates to redstone wire and other connected blocks are propagated in a breath-first -+ * manner, radiating out from the initial trigger (a block update to a redstone wire -+ * from something other than redstone wire). -+ * - Updates are scheduled both deterministically and in an intuitive order, addressing bug -+ * MC-11193. -+ * - All redstone behavior that used to be locational now works the same in all locations. -+ * - All behaviors of redstone wire that used to be orientational now work the same in all -+ * orientations, as long as orientation can be determined; random otherwise. Some other -+ * redstone components still update directionally (e.g. switches), and this code can't -+ * compensate for that. -+ * - Information that is otherwise computed over and over again or which is expensive to -+ * to compute is cached for faster lookup. This includes coordinates of block position -+ * neighbors and block states that won't change behind our backs during the execution of -+ * this search algorithm. -+ * - Redundant block updates (both to redstone wire and to other blocks) are heavily -+ * consolidated. For worst-case scenarios (depowering of redstone wire) this results -+ * in a reduction of block updates by as much as 95% (factor of 1/21). Due to overheads, -+ * empirical testing shows a speedup better than 10x. This addresses bug MC-81098. -+ * -+ * Extensive testing has been performed to ensure that existing redstone contraptions still -+ * behave as expected. Results of early testing that identified undesirable behavior changes -+ * were addressed. Additionally, real-time performance testing revealed compute inefficiencies -+ * With earlier implementations of this accelerator. Some compatibility adjustments and -+ * performance optimizations resulted in harmless increases in block updates above the -+ * theoretical minimum. -+ * -+ * Only a single redstone machine was found to break: An instant dropper line hack that -+ * relies on powered rails and quasi-connectivity but doesn't work in all directions. The -+ * replacement is to lay redstone wire directly on top of the dropper line, which now works -+ * reliably in any direction. -+ * -+ * There are numerous other optimization that can be made, but those will be provided later in -+ * separate updates. This version is designed to be minimalistic. -+ * -+ * Many thanks to the following individuals for their help in testing this functionality: -+ * - pokechu22, _MethodZz_, WARBEN, NarcolepticFrog, CommandHelper (nessie), ilmango, -+ * OreoLamp, Xcom6000, tryashtar, RedCMD, Smokey95Dog, EDDxample, Rays Works, -+ * Nodnam, BlockyPlays, Grumm, NeunEinser, HelVince. -+ */ -+ -+ /* Reference to BlockRedstoneWire object, which uses this accelerator */ -+ private final RedStoneWireBlock wire; -+ -+ /* -+ * Implementation: -+ * -+ * RedstoneWire Blocks are updated in concentric rings or "layers" radiating out from the -+ * initial block update that came from a call to BlockRedstoneWire.neighborChanged(). -+ * All nodes put in Layer N are those with Manhattan distance N from the trigger -+ * position, reachable through connected redstone wire blocks. -+ * -+ * Layer 0 represents the trigger block position that was input to neighborChanged. -+ * Layer 1 contains the immediate neighbors of that position. -+ * Layer N contains the neighbors of blocks in layer N-1, not including -+ * those in previous layers. -+ * -+ * Layers enforce an update order that is a function of Manhattan distance -+ * from the initial coordinates input to neighborChanged. The same -+ * coordinates may appear in multiple layers, but redundant updates are minimized. -+ * Block updates are sent layer-by-layer. If multiple of a block's neighbors experience -+ * redstone wire changes before its layer is processed, then those updates will be merged. -+ * If a block's update has been sent, but its neighboring redstone changes -+ * after that, then another update will be sent. This preserves compatibility with -+ * machines that rely on zero-tick behavior, except that the new functionality is non- -+ * locational. -+ * -+ * Within each layer, updates are ordered left-to-right relative to the direction of -+ * information flow. This makes the implementation non-orientational. Only when -+ * this direction is ambiguous is randomness applied (intentionally). -+ */ -+ private List updateQueue0 = Lists.newArrayList(); -+ private List updateQueue1 = Lists.newArrayList(); -+ private List updateQueue2 = Lists.newArrayList(); -+ -+ public RedstoneWireTurbo(RedStoneWireBlock wire) { -+ this.wire = wire; -+ } -+ -+ /* -+ * Compute neighbors of a block. When a redstone wire value changes, previously it called -+ * World.notifyNeighborsOfStateChange. That lists immediately neighboring blocks in -+ * west, east, down, up, north, south order. For each of those neighbors, their own -+ * neighbors are updated in the same order. This generates 36 updates, but 12 of them are -+ * redundant; for instance the west neighbor of a block's east neighbor. -+ * -+ * Note that this ordering is only used to create the initial list of neighbors. Once -+ * the direction of signal flow is identified, the ordering of updates is completely -+ * reorganized. -+ */ -+ public static BlockPos[] computeAllNeighbors(final BlockPos pos) { -+ final int x = pos.getX(); -+ final int y = pos.getY(); -+ final int z = pos.getZ(); -+ final BlockPos[] n = new BlockPos[24]; -+ -+ // Immediate neighbors, in the same order as -+ // World.notifyNeighborsOfStateChange, etc.: -+ // west, east, down, up, north, south -+ n[0] = new BlockPos(x - 1, y, z); -+ n[1] = new BlockPos(x + 1, y, z); -+ n[2] = new BlockPos(x, y - 1, z); -+ n[3] = new BlockPos(x, y + 1, z); -+ n[4] = new BlockPos(x, y, z - 1); -+ n[5] = new BlockPos(x, y, z + 1); -+ -+ // Neighbors of neighbors, in the same order, -+ // except that duplicates are not included -+ n[6] = new BlockPos(x - 2, y, z); -+ n[7] = new BlockPos(x - 1, y - 1, z); -+ n[8] = new BlockPos(x - 1, y + 1, z); -+ n[9] = new BlockPos(x - 1, y, z - 1); -+ n[10] = new BlockPos(x - 1, y, z + 1); -+ n[11] = new BlockPos(x + 2, y, z); -+ n[12] = new BlockPos(x + 1, y - 1, z); -+ n[13] = new BlockPos(x + 1, y + 1, z); -+ n[14] = new BlockPos(x + 1, y, z - 1); -+ n[15] = new BlockPos(x + 1, y, z + 1); -+ n[16] = new BlockPos(x, y - 2, z); -+ n[17] = new BlockPos(x, y - 1, z - 1); -+ n[18] = new BlockPos(x, y - 1, z + 1); -+ n[19] = new BlockPos(x, y + 2, z); -+ n[20] = new BlockPos(x, y + 1, z - 1); -+ n[21] = new BlockPos(x, y + 1, z + 1); -+ n[22] = new BlockPos(x, y, z - 2); -+ n[23] = new BlockPos(x, y, z + 2); -+ return n; -+ } -+ -+ /* -+ * We only want redstone wires to update redstone wires that are -+ * immediately adjacent. Some more distant updates can result -+ * in cross-talk that (a) wastes time and (b) can make the update -+ * order unintuitive. Therefore (relative to the neighbor order -+ * computed by computeAllNeighbors), updates are not scheduled -+ * for redstone wire in those non-connecting positions. On the -+ * other hand, updates will always be sent to *other* types of blocks -+ * in any of the 24 neighboring positions. -+ */ -+ private static final boolean[] update_redstone = { -+ true, true, false, false, true, true, // 0 to 5 -+ false, true, true, false, false, false, // 6 to 11 -+ true, true, false, false, false, true, // 12 to 17 -+ true, false, true, true, false, false // 18 to 23 -+ }; -+ -+ // Internal numbering for cardinal directions -+ private static final int North = 0; -+ private static final int East = 1; -+ private static final int South = 2; -+ private static final int West = 3; -+ -+ /* -+ * These lookup tables completely remap neighbor positions into a left-to-right -+ * ordering, based on the cardinal direction that is determined to be forward. -+ * See below for more explanation. -+ */ -+ private static final int[] forward_is_north = {2, 3, 16, 19, 0, 4, 1, 5, 7, 8, 17, 20, 12, 13, 18, 21, 6, 9, 22, 14, 11, 10, 23, 15}; -+ private static final int[] forward_is_east = {2, 3, 16, 19, 4, 1, 5, 0, 17, 20, 12, 13, 18, 21, 7, 8, 22, 14, 11, 15, 23, 9, 6, 10}; -+ private static final int[] forward_is_south = {2, 3, 16, 19, 1, 5, 0, 4, 12, 13, 18, 21, 7, 8, 17, 20, 11, 15, 23, 10, 6, 14, 22, 9}; -+ private static final int[] forward_is_west = {2, 3, 16, 19, 5, 0, 4, 1, 18, 21, 7, 8, 17, 20, 12, 13, 23, 10, 6, 9, 22, 15, 11, 14}; -+ -+ /* For any orientation, we end up with the update order defined below. This order is relative to any redstone wire block -+ * that is itself having an update computed, and this center position is marked with C. -+ * - The update position marked 0 is computed first, and the one marked 23 is last. -+ * - Forward is determined by the local direction of information flow into position C from prior updates. -+ * - The first updates are scheduled for the four positions below and above C. -+ * - Then updates are scheduled for the four horizontal neighbors of C, followed by the positions below and above those neighbors. -+ * - Finally, updates are scheduled for the remaining positions with Manhattan distance 2 from C (at the same Y coordinate). -+ * - For a given horizontal distance from C, updates are scheduled starting from directly left and stepping clockwise to directly -+ * right. The remaining positions behind C are scheduled counterclockwise so as to maintain the left-to-right ordering. -+ * - If C is in layer N of the update schedule, then all 24 positions may be scheduled for layer N+1. For redstone wire, no -+ * updates are scheduled for positions that cannot directly connect. Additionally, the four positions above and below C -+ * are ALSO scheduled for layer N+2. -+ * - This update order was selected after experimenting with a number of alternative schedules, based on its compatibility -+ * with existing redstone designs and behaviors that were considered to be intuitive by various testers. WARBEN in particular -+ * made some of the most challenging test cases, but the 3-tick clocks (made by RedCMD) were also challenging to fix, -+ * along with the rail-based instant dropper line built by ilmango. Numerous others made test cases as well, including -+ * NarcolepticFrog, nessie, and Pokechu22. -+ * -+ * - The forward direction is determined locally. So when there are branches in the redstone wire, the left one will get updated -+ * before the right one. Each branch can have its own relative forward direction, resulting in the left side of a left branch -+ * having priority over the right branch of a left branch, which has priority over the left branch of a right branch, followed -+ * by the right branch of a right branch. And so forth. Since redstone power reduces to zero after a path distance of 15, -+ * that imposes a practical limit on the branching. Note that the branching is not tracked explicitly -- relative forward -+ * directions dictate relative sort order, which maintains the proper global ordering. This also makes it unnecessary to be -+ * concerned about branches meeting up with each other. -+ * -+ * ^ -+ * | -+ * Forward -+ * <-- Left Right --> -+ * -+ * 18 -+ * 10 17 5 19 11 -+ * 2 8 0 12 16 4 C 6 20 9 1 13 3 -+ * 14 21 7 23 15 -+ * Further 22 Further -+ * Down Down Up Up -+ * -+ * Backward -+ * | -+ * V -+ */ -+ -+ // This allows the above remapping tables to be looked up by cardial direction index -+ private static final int[][] reordering = { forward_is_north, forward_is_east, forward_is_south, forward_is_west }; -+ -+ /* -+ * Input: Array of UpdateNode objects in an order corresponding to the positions -+ * computed by computeAllNeighbors above. -+ * Output: Array of UpdateNode objects oriented using the above remapping tables -+ * corresponding to the identified heading (direction of information flow). -+ */ -+ private static void orientNeighbors(final UpdateNode[] src, final UpdateNode[] dst, final int heading) { -+ final int[] re = reordering[heading]; -+ for (int i = 0; i < 24; i++) { -+ dst[i] = src[re[i]]; -+ } -+ } -+ -+ /* -+ * Structure to keep track of redstone wire blocks and -+ * neighbors that will receive updates. -+ */ -+ private static class UpdateNode { -+ public static enum Type { -+ UNKNOWN, REDSTONE, OTHER -+ } -+ -+ BlockState currentState; // Keep track of redstone wire value -+ UpdateNode[] neighbor_nodes; // References to neighbors (directed graph edges) -+ BlockPos self; // UpdateNode's own position -+ BlockPos parent; // Which block pos spawned/updated this node -+ Type type = Type.UNKNOWN; // unknown, redstone wire, other type of block -+ int layer; // Highest layer this node is scheduled in -+ boolean visited; // To keep track of information flow direction, visited restone wire is marked -+ int xbias, zbias; // Remembers directionality of ancestor nodes; helps eliminate directional ambiguities. -+ } -+ -+ /* -+ * Keep track of all block positions discovered during search and their current states. -+ * We want to remember one entry for each position. -+ */ -+ private final Map nodeCache = Maps.newHashMap(); -+ -+ /* -+ * For a newly created UpdateNode object, determine what type of block it is. -+ */ -+ private void identifyNode(final Level worldIn, final UpdateNode upd1) { -+ final BlockPos pos = upd1.self; -+ final BlockState oldState = worldIn.getBlockState(pos); -+ upd1.currentState = oldState; -+ -+ // Some neighbors of redstone wire are other kinds of blocks. -+ // These need to receive block updates to inform them that -+ // redstone wire values have changed. -+ final Block block = oldState.getBlock(); -+ if (block != wire) { -+ // Mark this block as not redstone wire and therefore -+ // requiring updates -+ upd1.type = UpdateNode.Type.OTHER; -+ -+ // Non-redstone blocks may propagate updates, but those updates -+ // are not handled by this accelerator. Therefore, we do not -+ // expand this position's neighbors. -+ return; -+ } -+ -+ // One job of BlockRedstoneWire.neighborChanged is to convert -+ // redstone wires to items if the block beneath was removed. -+ // With this accelerator, BlockRedstoneWire.neighborChanged -+ // is only typically called for a single wire block, while -+ // others are processed internally by the breadth first search -+ // algorithm. To preserve this game behavior, this check must -+ // be replicated here. -+ if (!wire.canSurvive(null, worldIn, pos)) { -+ // Pop off the redstone dust -+ Block.popResource(worldIn, pos, new ItemStack(Items.REDSTONE)); // TODO -+ worldIn.setAir(pos); -+ -+ // Mark this position as not being redstone wire -+ upd1.type = UpdateNode.Type.OTHER; -+ -+ // Note: Sending updates to air blocks leads to an empty method. -+ // Testing shows this to be faster than explicitly avoiding updates to -+ // air blocks. -+ return; -+ } -+ -+ // If the above conditions fail, then this is a redstone wire block. -+ upd1.type = UpdateNode.Type.REDSTONE; -+ } -+ -+ /* -+ * Given which redstone wire blocks have been visited and not visited -+ * around the position currently being updated, compute the cardinal -+ * direction that is "forward." -+ * -+ * rx is the forward direction along the West/East axis -+ * rz is the forward direction along the North/South axis -+ */ -+ static private int computeHeading(final int rx, final int rz) { -+ // rx and rz can only take on values -1, 0, and 1, so we can -+ // compute a code number that allows us to use a single switch -+ // to determine the heading. -+ final int code = (rx + 1) + 3 * (rz + 1); -+ switch (code) { -+ case 0: { -+ // Both rx and rz are -1 (northwest) -+ // Randomly choose one to be forward. -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? North : West; -+ } -+ case 1: { -+ // rx=0, rz=-1 -+ // Definitively North -+ return North; -+ } -+ case 2: { -+ // rx=1, rz=-1 (northeast) -+ // Choose randomly between north and east -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? North : East; -+ } -+ case 3: { -+ // rx=-1, rz=0 -+ // Definitively West -+ return West; -+ } -+ case 4: { -+ // rx=0, rz=0 -+ // Heading is completely ambiguous. Choose -+ // randomly among the four cardinal directions. -+ return ThreadLocalRandom.current().nextInt(0, 4); -+ } -+ case 5: { -+ // rx=1, rz=0 -+ // Definitively East -+ return East; -+ } -+ case 6: { -+ // rx=-1, rz=1 (southwest) -+ // Choose randomly between south and west -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? South : West; -+ } -+ case 7: { -+ // rx=0, rz=1 -+ // Definitively South -+ return South; -+ } -+ case 8: { -+ // rx=1, rz=1 (southeast) -+ // Choose randomly between south and east -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? South : East; -+ } -+ } -+ -+ // We should never get here -+ return ThreadLocalRandom.current().nextInt(0, 4); -+ } -+ -+ // Select whether to use updateSurroundingRedstone from BlockRedstoneWire (old) -+ // or this helper class (new) -+ private static final boolean old_current_change = false; -+ -+ /* -+ * Process a node whose neighboring redstone wire has experienced value changes. -+ */ -+ private void updateNode(final Level worldIn, final UpdateNode upd1, final int layer) { -+ final BlockPos pos = upd1.self; -+ -+ // Mark this redstone wire as having been visited so that it can be used -+ // to calculate direction of information flow. -+ upd1.visited = true; -+ -+ // Look up the last known state. -+ // Due to the way other redstone components are updated, we do not -+ // have to worry about a state changing behind our backs. The rare -+ // exception is handled by scheduleReentrantNeighborChanged. -+ final BlockState oldState = upd1.currentState; -+ -+ // Ask the wire block to compute its power level from its neighbors. -+ // This will also update the wire's power level and return a new -+ // state if it has changed. When a wire power level is changed, -+ // calculateCurrentChanges will immediately update the block state in the world -+ // and return the same value here to be cached in the corresponding -+ // UpdateNode object. -+ BlockState newState; -+ if (old_current_change) { -+ newState = wire.calculateCurrentChanges(worldIn, pos, pos, oldState); -+ } else { -+ // Looking up block state is slow. This accelerator includes a version of -+ // calculateCurrentChanges that uses cahed wire values for a -+ // significant performance boost. -+ newState = this.calculateCurrentChanges(worldIn, upd1); -+ } -+ -+ // Only inform neighbors if the state has changed -+ if (newState != oldState) { -+ // Store the new state -+ upd1.currentState = newState; -+ -+ // Inform neighbors of the change -+ propagateChanges(worldIn, upd1, layer); -+ } -+ } -+ -+ /* -+ * This identifies the neighboring positions of a new UpdateNode object, -+ * determines their types, and links those to into the graph. Then based on -+ * what nodes in the redstone wire graph have been visited, the neighbors -+ * are reordered left-to-right relative to the direction of information flow. -+ */ -+ private void findNeighbors(final Level worldIn, final UpdateNode upd1) { -+ final BlockPos pos = upd1.self; -+ -+ // Get the list of neighbor coordinates -+ final BlockPos[] neighbors = computeAllNeighbors(pos); -+ -+ // Temporary array of neighbors in cardinal ordering -+ final UpdateNode[] neighbor_nodes = new UpdateNode[24]; -+ -+ // Target array of neighbors sorted left-to-right -+ upd1.neighbor_nodes = new UpdateNode[24]; -+ -+ for (int i=0; i<24; i++) { -+ // Look up each neighbor in the node cache -+ final BlockPos pos2 = neighbors[i]; -+ UpdateNode upd2 = nodeCache.get(pos2); -+ if (upd2 == null) { -+ // If this is a previously unreached position, create -+ // a new update node, add it to the cache, and identify what it is. -+ upd2 = new UpdateNode(); -+ upd2.self = pos2; -+ upd2.parent = pos; -+ nodeCache.put(pos2, upd2); -+ identifyNode(worldIn, upd2); -+ } -+ -+ // For non-redstone blocks, any of the 24 neighboring positions -+ // should receive a block update. However, some block coordinates -+ // may contain a redstone wire that does not directly connect to the -+ // one being expanded. To avoid redundant calculations and confusing -+ // cross-talk, those neighboring positions are not included. -+ if (update_redstone[i] || upd2.type != UpdateNode.Type.REDSTONE) { -+ neighbor_nodes[i] = upd2; -+ } -+ } -+ -+ // Determine the directions from which the redstone signal may have come from. This -+ // checks for redstone wire at the same Y level and also Y+1 and Y-1, relative to the -+ // block being expanded. -+ final boolean fromWest = (neighbor_nodes[0].visited || neighbor_nodes[7].visited || neighbor_nodes[8].visited); -+ final boolean fromEast = (neighbor_nodes[1].visited || neighbor_nodes[12].visited || neighbor_nodes[13].visited); -+ final boolean fromNorth = (neighbor_nodes[4].visited || neighbor_nodes[17].visited || neighbor_nodes[20].visited); -+ final boolean fromSouth = (neighbor_nodes[5].visited || neighbor_nodes[18].visited || neighbor_nodes[21].visited); -+ -+ int cx = 0, cz = 0; -+ if (fromWest) cx += 1; -+ if (fromEast) cx -= 1; -+ if (fromNorth) cz += 1; -+ if (fromSouth) cz -= 1; -+ -+ int heading; -+ if (cx==0 && cz==0) { -+ // If there is no clear direction, try to inherit the heading from ancestor nodes. -+ heading = computeHeading(upd1.xbias, upd1.zbias); -+ -+ // Propagate that heading to descendant nodes. -+ for (int i=0; i<24; i++) { -+ final UpdateNode nn = neighbor_nodes[i]; -+ if (nn != null) { -+ nn.xbias = upd1.xbias; -+ nn.zbias = upd1.zbias; -+ } -+ } -+ } else { -+ if (cx != 0 && cz != 0) { -+ // If the heading is somewhat ambiguous, try to disambiguate based on -+ // ancestor nodes. -+ if (upd1.xbias != 0) cz = 0; -+ if (upd1.zbias != 0) cx = 0; -+ } -+ heading = computeHeading(cx, cz); -+ -+ // Propagate that heading to descendant nodes. -+ for (int i=0; i<24; i++) { -+ final UpdateNode nn = neighbor_nodes[i]; -+ if (nn != null) { -+ nn.xbias = cx; -+ nn.zbias = cz; -+ } -+ } -+ } -+ -+ // Reorder neighboring UpdateNode objects according to the forward direction -+ // determined above. -+ orientNeighbors(neighbor_nodes, upd1.neighbor_nodes, heading); -+ } -+ -+ /* -+ * For any redstone wire block in layer N, inform neighbors to recompute their states -+ * in layers N+1 and N+2; -+ */ -+ private void propagateChanges(final Level worldIn, final UpdateNode upd1, final int layer) { -+ if (upd1.neighbor_nodes == null) { -+ // If this node has not been expanded yet, find its neighbors -+ findNeighbors(worldIn, upd1); -+ } -+ -+ final BlockPos pos = upd1.self; -+ -+ // All neighbors may be scheduled for layer N+1 -+ final int layer1 = layer + 1; -+ -+ // If the node being updated (upd1) has already been expanded, then merely -+ // schedule updates to its neighbors. -+ for (int i = 0; i < 24; i++) { -+ final UpdateNode upd2 = upd1.neighbor_nodes[i]; -+ -+ // This test ensures that an UpdateNode is never scheduled to the same layer -+ // more than once. Also, skip non-connecting redstone wire blocks -+ if (upd2 != null && layer1 > upd2.layer) { -+ upd2.layer = layer1; -+ updateQueue1.add(upd2); -+ -+ // Keep track of which block updated this neighbor -+ upd2.parent = pos; -+ } -+ } -+ -+ // Nodes above and below are scheduled ALSO for layer N+2 -+ final int layer2 = layer + 2; -+ -+ // Repeat of the loop above, but only for the first four (above and below) neighbors -+ // and for layer N+2; -+ for (int i = 0; i < 4; i++) { -+ final UpdateNode upd2 = upd1.neighbor_nodes[i]; -+ if (upd2 != null && layer2 > upd2.layer) { -+ upd2.layer = layer2; -+ updateQueue2.add(upd2); -+ upd2.parent = pos; -+ } -+ } -+ } -+ -+ // The breadth-first search below will send block updates to blocks -+ // that are not redstone wire. If one of those updates results in -+ // a distant redstone wire getting an update, then this.neighborChanged -+ // will get called. This would be a reentrant call, and -+ // it is necessary to properly integrate those updates into the -+ // on-going search through redstone wire. Thus, we make the layer -+ // currently being processed visible at the object level. -+ -+ // The current layer being processed by the breadth-first search -+ private int currentWalkLayer = 0; -+ -+ private void shiftQueue() { -+ final List t = updateQueue0; -+ t.clear(); -+ updateQueue0 = updateQueue1; -+ updateQueue1 = updateQueue2; -+ updateQueue2 = t; -+ } -+ -+ /* -+ * Perform a breadth-first (layer by layer) traversal through redstone -+ * wire blocks, propagating value changes to neighbors in an order -+ * that is a function of distance from the initial call to -+ * this.neighborChanged. -+ */ -+ private void breadthFirstWalk(final Level worldIn) { -+ shiftQueue(); -+ currentWalkLayer = 1; -+ -+ // Loop over all layers -+ while (updateQueue0.size()>0 || updateQueue1.size()>0) { -+ // Get the set of blocks in this layer -+ final List thisLayer = updateQueue0; -+ -+ // Loop over all blocks in the layer. Recall that -+ // this is a List, preserving the insertion order of -+ // left-to-right based on direction of information flow. -+ for (UpdateNode upd : thisLayer) { -+ if (upd.type == UpdateNode.Type.REDSTONE) { -+ // If the node is is redstone wire, -+ // schedule updates to neighbors if its value -+ // has changed. -+ updateNode(worldIn, upd, currentWalkLayer); -+ } else { -+ // If this block is not redstone wire, send a block update. -+ // Redstone wire blocks get state updates, but they don't -+ // need block updates. Only non-redstone neighbors need updates. -+ -+ // World.neighborChanged is called from -+ // World.notifyNeighborsOfStateChange, and -+ // notifyNeighborsOfStateExcept. We don't use -+ // World.notifyNeighborsOfStateChange here, since we are -+ // already keeping track of all of the neighbor positions -+ // that need to be updated. All on its own, handling neighbors -+ // this way reduces block updates by 1/3 (24 instead of 36). -+ worldIn.neighborChanged(upd.self, wire, upd.parent); -+ } -+ } -+ -+ // Move on to the next layer -+ shiftQueue(); -+ currentWalkLayer++; -+ } -+ -+ currentWalkLayer = 0; -+ } -+ -+ /* -+ * Normally, when Minecraft is computing redstone wire power changes, and a wire power level -+ * change sends a block update to a neighboring functional component (e.g. piston, repeater, etc.), -+ * those updates are queued. Only once all redstone wire updates are complete will any component -+ * action generate any further block updates to redstone wire. Instant repeater lines, for instance, -+ * will process all wire updates for one redstone line, after which the pistons will zero-tick, -+ * after which the next redstone line performs all of its updates. Thus, each wire is processed in its -+ * own discrete wave. -+ * -+ * However, there are some corner cases where this pattern breaks, with a proof of concept discovered -+ * by Rays Works, which works the same in vanilla. The scenario is as follows: -+ * (1) A redstone wire is conducting a signal. -+ * (2) Part-way through that wave of updates, a neighbor is updated that causes an update to a completely -+ * separate redstone wire. -+ * (3) This results in a call to BlockRedstoneWire.neighborChanged for that other wire, in the middle of -+ * an already on-going propagation through the first wire. -+ * -+ * The vanilla code, being depth-first, would end up fully processing the second wire before going back -+ * to finish processing the first one. (Although technically, vanilla has no special concept of "being -+ * in the middle" of processing updates to a wire.) For the breadth-first algorithm, we give this -+ * situation special handling, where the updates for the second wire are incorporated into the schedule -+ * for the first wire, and then the callstack is allowed to unwind back to the on-going search loop in -+ * order to continue processing both the first and second wire in the order of distance from the initial -+ * trigger. -+ */ -+ private BlockState scheduleReentrantNeighborChanged(final Level worldIn, final BlockPos pos, final BlockState newState, final BlockPos source) { -+ if (source != null) { -+ // If the cause of the redstone wire update is known, we can use that to help determine -+ // direction of information flow. -+ UpdateNode src = nodeCache.get(source); -+ if (src == null) { -+ src = new UpdateNode(); -+ src.self = source; -+ src.parent = source; -+ src.visited = true; -+ identifyNode(worldIn, src); -+ nodeCache.put(source, src); -+ } -+ } -+ -+ // Find or generate a node for the redstone block position receiving the update -+ UpdateNode upd = nodeCache.get(pos); -+ if (upd == null) { -+ upd = new UpdateNode(); -+ upd.self = pos; -+ upd.parent = pos; -+ upd.visited = true; -+ identifyNode(worldIn, upd); -+ nodeCache.put(pos, upd); -+ } -+ upd.currentState = newState; -+ -+ // Receiving this block update may mean something in the world changed. -+ // Therefore we clear the cached block info about all neighbors of -+ // the position receiving the update and then re-identify what they are. -+ if (upd.neighbor_nodes != null) { -+ for (int i=0; i<24; i++) { -+ final UpdateNode upd2 = upd.neighbor_nodes[i]; -+ if (upd2 == null) continue; -+ upd2.type = UpdateNode.Type.UNKNOWN; -+ upd2.currentState = null; -+ identifyNode(worldIn, upd2); -+ } -+ } -+ -+ // The block at 'pos' is a redstone wire and has been updated already by calling -+ // wire.calculateCurrentChanges, so we don't schedule that. However, we do need -+ // to schedule its neighbors. By passing the current value of 'currentWalkLayer' to -+ // propagateChanges, the neighbors of 'pos' are scheduled for layers currentWalkLayer+1 -+ // and currentWalkLayer+2. -+ propagateChanges(worldIn, upd, currentWalkLayer); -+ -+ // Return here. The call stack will unwind back to the first call to -+ // updateSurroundingRedstone, whereupon the new updates just scheduled will -+ // be propagated. This also facilitates elimination of superfluous and -+ // redundant block updates. -+ return newState; -+ } -+ -+ /* -+ * New version of pre-existing updateSurroundingRedstone, which is called from -+ * wire.updateSurroundingRedstone, which is called from wire.neighborChanged and a -+ * few other methods in BlockRedstoneWire. This sets off the breadth-first -+ * walk through all redstone dust connected to the initial position triggered. -+ */ -+ public BlockState updateSurroundingRedstone(final Level worldIn, final BlockPos pos, final BlockState state, final BlockPos source) { -+ // Check this block's neighbors and see if its power level needs to change -+ // Use the calculateCurrentChanges method in BlockRedstoneWire since we have no -+ // cached block states at this point. -+ final BlockState newState = wire.calculateCurrentChanges(worldIn, pos, pos, state); -+ -+ // If no change, exit -+ if (newState == state) { -+ return state; -+ } -+ -+ // Check to see if this update was received during an on-going breadth first search -+ if (currentWalkLayer > 0 || nodeCache.size() > 0) { -+ // As breadthFirstWalk progresses, it sends block updates to neighbors. Some of those -+ // neighbors may affect the world so as to cause yet another redstone wire block to receive -+ // an update. If that happens, we need to integrate those redstone wire updates into the -+ // already on-going graph walk being performed by breadthFirstWalk. -+ return scheduleReentrantNeighborChanged(worldIn, pos, newState, source); -+ } -+ // If there are no on-going walks through redstone wire, then start a new walk. -+ -+ // If the source of the block update to the redstone wire at 'pos' is known, we can use -+ // that to help determine the direction of information flow. -+ if (source != null) { -+ final UpdateNode src = new UpdateNode(); -+ src.self = source; -+ src.parent = source; -+ src.visited = true; -+ nodeCache.put(source, src); -+ identifyNode(worldIn, src); -+ } -+ -+ // Create a node representing the block at 'pos', and then propagate updates -+ // to its neighbors. As stated above, the call to wire.calculateCurrentChanges -+ // already performs the update to the block at 'pos', so it is not added to the schedule. -+ final UpdateNode upd = new UpdateNode(); -+ upd.self = pos; -+ upd.parent = source!=null ? source : pos; -+ upd.currentState = newState; -+ upd.type = UpdateNode.Type.REDSTONE; -+ upd.visited = true; -+ nodeCache.put(pos, upd); -+ propagateChanges(worldIn, upd, 0); -+ -+ // Perform the walk over all directly reachable redstone wire blocks, propagating wire value -+ // updates in a breadth first order out from the initial update received for the block at 'pos'. -+ breadthFirstWalk(worldIn); -+ -+ // With the whole search completed, clear the list of all known blocks. -+ // We do not want to keep around state information that may be changed by other code. -+ // In theory, we could cache the neighbor block positions, but that is a separate -+ // optimization. -+ nodeCache.clear(); -+ -+ return newState; -+ } -+ -+ // For any array of neighbors in an UpdateNode object, these are always -+ // the indices of the four immediate neighbors at the same Y coordinate. -+ private static final int[] rs_neighbors = {4, 5, 6, 7}; -+ private static final int[] rs_neighbors_up = {9, 11, 13, 15}; -+ private static final int[] rs_neighbors_dn = {8, 10, 12, 14}; -+ -+ /* -+ * Updated calculateCurrentChanges that is optimized for speed and uses -+ * the UpdateNode's neighbor array to find the redstone states of neighbors -+ * that might power it. -+ */ -+ private BlockState calculateCurrentChanges(final Level worldIn, final UpdateNode upd) { -+ BlockState state = upd.currentState; -+ final int i = state.getValue(RedStoneWireBlock.POWER).intValue(); -+ int j = 0; -+ j = getMaxCurrentStrength(upd, j); -+ int l = 0; -+ -+ wire.setCanProvidePower(false); -+ // Unfortunately, World.isBlockIndirectlyGettingPowered is complicated, -+ // and I'm not ready to try to replicate even more functionality from -+ // elsewhere in Minecraft into this accelerator. So sadly, we must -+ // suffer the performance hit of this very expensive call. If there -+ // is consistency to what this call returns, we may be able to cache it. -+ final int k = worldIn.isBlockIndirectlyGettingPowered(upd.self); -+ wire.setCanProvidePower(true); -+ -+ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. -+ // If 'k' has the highest level of all neighbors, then the power level of this -+ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the -+ // following loop can affect the power level of the wire. Therefore, the loop is -+ // skipped if k is already 15. -+ if (k < 15) { -+ if (upd.neighbor_nodes == null) { -+ // If this node's neighbors are not known, expand the node -+ findNeighbors(worldIn, upd); -+ } -+ -+ // These remain constant, so pull them out of the loop. -+ // Regardless of which direction is forward, the UpdateNode for the -+ // position directly above the node being calculated is always -+ // at index 1. -+ UpdateNode center_up = upd.neighbor_nodes[1]; -+ boolean center_up_is_cube = center_up.currentState.isRedstoneConductor(worldIn, center_up.self); // TODO -+ -+ for (int m = 0; m < 4; m++) { -+ // Get the neighbor array index of each of the four cardinal -+ // neighbors. -+ int n = rs_neighbors[m]; -+ -+ // Get the max redstone power level of each of the cardinal -+ // neighbors -+ UpdateNode neighbor = upd.neighbor_nodes[n]; -+ l = getMaxCurrentStrength(neighbor, l); -+ -+ // Also check the positions above and below the cardinal -+ // neighbors -+ boolean neighbor_is_cube = neighbor.currentState.isRedstoneConductor(worldIn, neighbor.self); // TODO -+ if (!neighbor_is_cube) { -+ UpdateNode neighbor_down = upd.neighbor_nodes[rs_neighbors_dn[m]]; -+ l = getMaxCurrentStrength(neighbor_down, l); -+ } else -+ if (!center_up_is_cube) { -+ UpdateNode neighbor_up = upd.neighbor_nodes[rs_neighbors_up[m]]; -+ l = getMaxCurrentStrength(neighbor_up, l); -+ } -+ } -+ } -+ -+ // The new code sets this RedstoneWire block's power level to the highest neighbor -+ // minus 1. This usually results in wire power levels dropping by 2 at a time. -+ // This optimization alone has no impact on update order, only the number of updates. -+ j = l - 1; -+ -+ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will -+ // always be in the range of 0 to 15, the following if will correct that. -+ if (k > j) j = k; -+ -+ // egg82's amendment -+ // Adding Bukkit's BlockRedstoneEvent - er.. event. -+ if (i != j) { -+ BlockRedstoneEvent event = new BlockRedstoneEvent(worldIn.getWorld().getBlockAt(upd.self.getX(), upd.self.getY(), upd.self.getZ()), i, j); -+ worldIn.getCraftServer().getPluginManager().callEvent(event); -+ j = event.getNewCurrent(); -+ } -+ -+ if (i != j) { -+ // If the power level has changed from its previous value, compute a new state -+ // and set it in the world. -+ // Possible optimization: Don't commit state changes to the world until they -+ // need to be known by some nearby non-redstone-wire block. -+ BlockPos pos = new BlockPos(upd.self.getX(), upd.self.getY(), upd.self.getZ()); -+ if (wire.canSurvive(null, worldIn, pos)) { -+ state = state.setValue(RedStoneWireBlock.POWER, Integer.valueOf(j)); -+ worldIn.setBlock(upd.self, state, 2); -+ } -+ } -+ -+ return state; -+ } -+ -+ /* -+ * Optimized function to compute a redstone wire's power level based on cached -+ * state. -+ */ -+ private static int getMaxCurrentStrength(final UpdateNode upd, final int strength) { -+ if (upd.type != UpdateNode.Type.REDSTONE) return strength; -+ final int i = upd.currentState.getValue(RedStoneWireBlock.POWER).intValue(); -+ return i > strength ? i : strength; -+ } -+} -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 9b50b8030174338c04b60d441b980131e1d593e4..ebb92f88e0402681c47834bcf45e6b236748289a 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -659,6 +659,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - } - -+ public void neighborChanged(BlockPos pos, Block blockIn, BlockPos fromPos) { neighborChanged(pos, blockIn, fromPos); } // Paper - OBFHELPER - public void neighborChanged(BlockPos sourcePos, Block sourceBlock, BlockPos neighborPos) { - if (!this.isClientSide) { - BlockState iblockdata = this.getBlockState(sourcePos); -@@ -1287,6 +1288,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return this.getSignal(pos.below(), Direction.DOWN) > 0 ? true : (this.getSignal(pos.above(), Direction.UP) > 0 ? true : (this.getSignal(pos.north(), Direction.NORTH) > 0 ? true : (this.getSignal(pos.south(), Direction.SOUTH) > 0 ? true : (this.getSignal(pos.west(), Direction.WEST) > 0 ? true : this.getSignal(pos.east(), Direction.EAST) > 0)))); - } - -+ public int isBlockIndirectlyGettingPowered(BlockPos pos) { return this.getBestNeighborSignal(pos); } // Paper - OBFHELPER - public int getBestNeighborSignal(BlockPos pos) { - int i = 0; - Direction[] aenumdirection = Level.DIRECTIONS; -diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java -index 7318536fe89cddda305007a9ab115970bf18f65d..e5558b73c6159e4c1901d286535a7875924434e9 100644 ---- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java -@@ -1,5 +1,7 @@ - package net.minecraft.world.level.block; - -+import com.destroystokyo.paper.PaperConfig; -+import com.destroystokyo.paper.util.RedstoneWireTurbo; - import com.google.common.collect.ImmutableMap; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -49,7 +51,7 @@ public class RedStoneWireBlock extends Block { - private final Map SHAPES_CACHE = Maps.newHashMap(); - private static final Vector3f[] COLORS = new Vector3f[16]; - private final BlockState crossState; -- private boolean shouldSignal = true; -+ private boolean shouldSignal = true; public final boolean canProvidePower() { return this.shouldSignal; } public final void setCanProvidePower(boolean value) { this.shouldSignal = value; } // Paper - OBFHELPER - - public RedStoneWireBlock(BlockBehaviour.Properties settings) { - super(settings); -@@ -236,6 +238,121 @@ public class RedStoneWireBlock extends Block { - return floor.isFaceSturdy(world, pos, Direction.UP) || floor.is(Blocks.HOPPER); - } - -+ // Paper start - Optimize redstone -+ // The bulk of the new functionality is found in RedstoneWireTurbo.java -+ RedstoneWireTurbo turbo = new RedstoneWireTurbo(this); -+ -+ /* -+ * Modified version of pre-existing updateSurroundingRedstone, which is called from -+ * this.neighborChanged and a few other methods in this class. -+ * Note: Added 'source' argument so as to help determine direction of information flow -+ */ -+ private void updateSurroundingRedstone(Level worldIn, BlockPos pos, BlockState state, BlockPos source) { -+ if (worldIn.paperConfig.useEigencraftRedstone) { -+ turbo.updateSurroundingRedstone(worldIn, pos, state, source); -+ return; -+ } -+ updatePowerStrength(worldIn, pos, state); -+ } -+ -+ /* -+ * Slightly modified method to compute redstone wire power levels from neighboring blocks. -+ * Modifications cut the number of power level changes by about 45% from vanilla, and this -+ * optimization synergizes well with the breadth-first search implemented in -+ * RedstoneWireTurbo. -+ * Note: RedstoneWireTurbo contains a faster version of this code. -+ * Note: Made this public so that RedstoneWireTurbo can access it. -+ */ -+ public BlockState calculateCurrentChanges(Level worldIn, BlockPos pos1, BlockPos pos2, BlockState state) { -+ BlockState iblockstate = state; -+ int i = state.getValue(POWER); -+ int j = 0; -+ j = this.getPower(j, worldIn.getBlockState(pos2)); -+ this.setCanProvidePower(false); -+ int k = worldIn.isBlockIndirectlyGettingPowered(pos1); -+ this.setCanProvidePower(true); -+ -+ if (!worldIn.paperConfig.useEigencraftRedstone) { -+ // This code is totally redundant to if statements just below the loop. -+ if (k > 0 && k > j - 1) { -+ j = k; -+ } -+ } -+ -+ int l = 0; -+ -+ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. -+ // If 'k' has the highest level of all neighbors, then the power level of this -+ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the -+ // following loop can affect the power level of the wire. Therefore, the loop is -+ // skipped if k is already 15. -+ if (!worldIn.paperConfig.useEigencraftRedstone || k < 15) { -+ for (Direction enumfacing : Direction.Plane.HORIZONTAL) { -+ BlockPos blockpos = pos1.relative(enumfacing); -+ boolean flag = blockpos.getX() != pos2.getX() || blockpos.getZ() != pos2.getZ(); -+ -+ if (flag) { -+ l = this.getPower(l, worldIn.getBlockState(blockpos)); -+ } -+ -+ if (worldIn.getBlockState(blockpos).isRedstoneConductor(worldIn, blockpos) && !worldIn.getBlockState(pos1.above()).isRedstoneConductor(worldIn, pos1)) { -+ if (flag && pos1.getY() >= pos2.getY()) { -+ l = this.getPower(l, worldIn.getBlockState(blockpos.above())); -+ } -+ } else if (!worldIn.getBlockState(blockpos).isRedstoneConductor(worldIn, blockpos) && flag && pos1.getY() <= pos2.getY()) { -+ l = this.getPower(l, worldIn.getBlockState(blockpos.below())); -+ } -+ } -+ } -+ -+ if (!worldIn.paperConfig.useEigencraftRedstone) { -+ // The old code would decrement the wire value only by 1 at a time. -+ if (l > j) { -+ j = l - 1; -+ } else if (j > 0) { -+ --j; -+ } else { -+ j = 0; -+ } -+ -+ if (k > j - 1) { -+ j = k; -+ } -+ } else { -+ // The new code sets this RedstoneWire block's power level to the highest neighbor -+ // minus 1. This usually results in wire power levels dropping by 2 at a time. -+ // This optimization alone has no impact on update order, only the number of updates. -+ j = l - 1; -+ -+ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will -+ // always be in the range of 0 to 15, the following if will correct that. -+ if (k > j) j = k; -+ } -+ -+ if (i != j) { -+ state = state.setValue(POWER, j); -+ -+ if (worldIn.getBlockState(pos1) == iblockstate) { -+ worldIn.setBlock(pos1, state, 2); -+ } -+ -+ // 1.16(.1?) dropped the need for blocks needing updates. -+ // Whether this is necessary after all is to be seen. -+// if (!worldIn.paperConfig.useEigencraftRedstone) { -+// // The new search algorithm keeps track of blocks needing updates in its own data structures, -+// // so only add anything to blocksNeedingUpdate if we're using the vanilla update algorithm. -+// this.getBlocksNeedingUpdate().add(pos1); -+// -+// for (EnumDirection enumfacing1 : EnumDirection.values()) { -+// this.getBlocksNeedingUpdate().add(pos1.shift(enumfacing1)); -+// } -+// } -+ } -+ -+ return state; -+ } -+ // Paper end -+ - private void updatePowerStrength(Level world, BlockPos pos, BlockState state) { - int i = this.calculateTargetStrength(world, pos); - -@@ -305,6 +422,8 @@ public class RedStoneWireBlock extends Block { - return Math.max(i, j - 1); - } - -+ private int getPower(int min, BlockState iblockdata) { return Math.max(min, getPower(iblockdata)); } // Paper - Optimize redstone -+ private int getPower(BlockState iblockdata) { return this.getWireSignal(iblockdata); } // Paper - OBFHELPER - private int getWireSignal(BlockState state) { - return state.is((Block) this) ? (Integer) state.getValue(RedStoneWireBlock.POWER) : 0; - } -@@ -327,7 +446,7 @@ public class RedStoneWireBlock extends Block { - @Override - public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { - if (!oldState.is(state.getBlock()) && !world.isClientSide) { -- this.updatePowerStrength(world, pos, state); -+ this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone - Iterator iterator = Direction.Plane.VERTICAL.iterator(); - - while (iterator.hasNext()) { -@@ -354,7 +473,7 @@ public class RedStoneWireBlock extends Block { - world.updateNeighborsAt(pos.relative(enumdirection), this); - } - -- this.updatePowerStrength(world, pos, state); -+ this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone - this.updateNeighborsOfNeighboringWires(world, pos); - } - } -@@ -389,7 +508,7 @@ public class RedStoneWireBlock extends Block { - public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { - if (!world.isClientSide) { - if (state.canSurvive(world, pos)) { -- this.updatePowerStrength(world, pos, state); -+ this.updateSurroundingRedstone(world, pos, state, fromPos); // Paper - Optimize redstone - } else { - dropResources(state, world, pos); - world.removeBlock(pos, false); diff --git a/Remapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch b/Remapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch deleted file mode 100644 index dfda54388f..0000000000 --- a/Remapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Thu, 27 Aug 2020 16:57:25 -0400 -Subject: [PATCH] Fix hex colors not working in some kick messages - - -diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -index 6f98be2b9b00f71dd041e7511c70166fdecf0749..c648b73a4c478f9d8020274205d6684f7c7c416f 100644 ---- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -@@ -50,7 +50,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - synchronized (throttleTracker) { - if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { - throttleTracker.put(address, currentTime); -- TranslatableComponent chatmessage = new TranslatableComponent(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message -+ Component chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage, true)[0]; // Paper - Configurable connection throttle kick message // Paper - Fix hex colors not working in some kick messages - this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); - this.connection.disconnect(chatmessage); - return; -@@ -76,12 +76,12 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - } - // CraftBukkit end - if (packet.getProtocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { -- TranslatableComponent chatmessage; -+ Component chatmessage; // Paper - Fix hex colors not working in some kick messages - - if (packet.getProtocolVersion() < 754) { -- chatmessage = new TranslatableComponent( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) ); // Spigot -+ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages - } else { -- chatmessage = new TranslatableComponent( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) ); // Spigot -+ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages - } - - this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); -@@ -99,7 +99,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - if (event.callEvent()) { - // If we've failed somehow, let the client know so and go no further. - if (event.isFailed()) { -- chatmessage = new TranslatableComponent(event.getFailMessage()); -+ Component chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(event.getFailMessage(), true)[0]; // Paper - Fix hex colors not working in some kick messages - this.getNetworkManager().send(new ClientboundLoginDisconnectPacket(chatmessage)); - this.getNetworkManager().disconnect(chatmessage); - return; -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 659bf14cf3c949b896d0333f893a3d5e16ab9c92..573963a09f15046cfcaab83aef906801ce70d75a 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -104,14 +104,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - // CraftBukkit start - @Deprecated - public void disconnect(String s) { -- try { -- Component ichatbasecomponent = new TextComponent(s); -- ServerLoginPacketListenerImpl.LOGGER.info("Disconnecting {}: {}", this.getUserName(), s); -- this.connection.send(new ClientboundLoginDisconnectPacket(ichatbasecomponent)); -- this.connection.disconnect(ichatbasecomponent); -- } catch (Exception exception) { -- ServerLoginPacketListenerImpl.LOGGER.error("Error whilst disconnecting player", exception); -- } -+ disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s, true)[0]); // Paper - Fix hex colors not working in some kick messages - } - // CraftBukkit end - diff --git a/Remapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch b/Remapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch deleted file mode 100644 index 0287c9ed0f..0000000000 --- a/Remapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Fri, 21 Aug 2020 20:57:54 +0200 -Subject: [PATCH] PortalCreateEvent needs to know its entity - - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 04b717326524f400da3562655c25db59e72814ec..a9256fc4a0bc3cd277cb372a9c090028e03482f5 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -366,7 +366,7 @@ public final class ItemStack { - net.minecraft.world.level.block.state.BlockState block = world.getBlockState(newblockposition); - - if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically -- block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); -+ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true, itemactioncontext); // Paper - pass itemactioncontext - } - - world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point -diff --git a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java -index cd005f7dbfcaf3cebae3a92da36e0d40c93dbf79..ad37261e716b15d62fc2083d137cdac818308cdd 100644 ---- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java -@@ -7,6 +7,7 @@ import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.context.BlockPlaceContext; -+import net.minecraft.world.item.context.UseOnContext; - import net.minecraft.world.level.BlockGetter; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.LevelAccessor; -@@ -66,20 +67,23 @@ public abstract class BaseFireBlock extends Block { - super.entityInside(state, world, pos, entity); - } - -+ // Paper start - ItemActionContext param -+ @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { this.onPlace(state, world, pos, oldState, notify, null); } - @Override -- public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { -- if (!oldState.is(state.getBlock())) { -+ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { -+ // Paper end -+ if (!iblockdata1.is(iblockdata.getBlock())) { - if (inPortalDimension(world)) { -- Optional optional = PortalShape.findEmptyPortalShape((LevelAccessor) world, pos, Direction.Axis.X); -+ Optional optional = PortalShape.findEmptyPortalShape((LevelAccessor) world, blockposition, Direction.Axis.X); - - if (optional.isPresent()) { -- ((PortalShape) optional.get()).createPortal(); -+ ((PortalShape) optional.get()).createPortal(itemActionContext); // Paper - pass ItemActionContext param - return; - } - } - -- if (!state.canSurvive(world, pos)) { -- fireExtinguished(world, pos); // CraftBukkit - fuel block broke -+ if (!iblockdata.canSurvive(world, blockposition)) { -+ fireExtinguished(world, blockposition); // CraftBukkit - fuel block broke - } - - } -diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java -index ac63c5bef5b35b158e57835d765bbdd15fc60664..e690e7c366fc087d3b28d61323dcc78bb7154aed 100644 ---- a/src/main/java/net/minecraft/world/level/block/FireBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java -@@ -15,6 +15,7 @@ import net.minecraft.core.Vec3i; - import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.item.context.BlockPlaceContext; -+import net.minecraft.world.item.context.UseOnContext; - import net.minecraft.world.level.BlockGetter; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.Level; -@@ -363,9 +364,11 @@ public class FireBlock extends BaseFireBlock { - } - - @Override -- public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { -- super.onPlace(state, world, pos, oldState, notify); -- world.getBlockTicks().a(pos, this, getFireTickDelay(world.random)); -+ // Paper start - ItemActionContext param -+ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { -+ super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext); -+ // Paper end -+ world.getBlockTicks().a(blockposition, this, getFireTickDelay(world.random)); - } - - private static int getFireTickDelay(Random random) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index df2836b071158729728411f5b228cc38dddd4d4e..f2fefdad26057c722085e60ba837fe2c117f55f7 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -32,6 +32,7 @@ import net.minecraft.world.item.DyeColor; - import net.minecraft.world.item.Item; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.context.BlockPlaceContext; -+import net.minecraft.world.item.context.UseOnContext; - import net.minecraft.world.level.BlockGetter; - import net.minecraft.world.level.EmptyBlockGetter; - import net.minecraft.world.level.Level; -@@ -119,6 +120,12 @@ public abstract class BlockBehaviour { - DebugPackets.sendNeighborsUpdatePacket(world, pos); - } - -+ // Paper start - add ItemActionContext param -+ @Deprecated -+ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { -+ this.onPlace(iblockdata, world, blockposition, iblockdata1, flag); -+ } -+ // Paper end - @Deprecated - public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { - org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot -diff --git a/src/main/java/net/minecraft/world/level/portal/PortalShape.java b/src/main/java/net/minecraft/world/level/portal/PortalShape.java -index 7a99adbe39ca2566d42ed67dc9d6f609005f3d6f..500744b6383390266efed9e35a000511210cb5b9 100644 ---- a/src/main/java/net/minecraft/world/level/portal/PortalShape.java -+++ b/src/main/java/net/minecraft/world/level/portal/PortalShape.java -@@ -11,6 +11,7 @@ import net.minecraft.tags.BlockTags; - import net.minecraft.tags.Tag; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.EntityDimensions; -+import net.minecraft.world.item.context.UseOnContext; - import net.minecraft.world.level.LevelAccessor; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.NetherPortalBlock; -@@ -181,7 +182,10 @@ public class PortalShape { - } - - // CraftBukkit start - return boolean -- public boolean createPortal() { -+ // Paper start - ItemActionContext param -+ @Deprecated public boolean createPortal() { return this.createPortal(null); } -+ public boolean createPortal(UseOnContext itemActionContext) { -+ // Paper end - org.bukkit.World bworld = this.level.getLevel().getWorld(); - - // Copy below for loop -@@ -190,8 +194,7 @@ public class PortalShape { - BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { - blocks.setBlock(blockposition, iblockdata, 18); - }); -- -- PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); -+ PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, itemActionContext == null || itemActionContext.getPlayer() == null ? null : itemActionContext.getPlayer().getBukkitEntity(), PortalCreateEvent.CreateReason.FIRE); // Paper - pass entity param - this.level.getLevel().getServer().server.getPluginManager().callEvent(event); - - if (event.isCancelled()) { diff --git a/Remapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch b/Remapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch deleted file mode 100644 index d30a891285..0000000000 --- a/Remapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: foss-mc <69294560+foss-mc@users.noreply.github.com> -Date: Sun, 30 Aug 2020 15:30:29 +0800 -Subject: [PATCH] Fix CraftTeam null check - - -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -index 7ebcba4ada42f5599d56cfdeb75dbf62f2a09b78..222e3d4e379fd5ca50c122f70e90ed11b2f5e1f7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -@@ -253,7 +253,7 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { - - @Override - public boolean hasEntry(String entry) throws IllegalArgumentException, IllegalStateException { -- Validate.notNull("Entry cannot be null"); -+ Validate.notNull(entry, "Entry cannot be null"); // Paper - - CraftScoreboard scoreboard = checkState(); - diff --git a/Remapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch b/Remapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch deleted file mode 100644 index af8a4c5513..0000000000 --- a/Remapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 15:28:35 +0200 -Subject: [PATCH] Add more Evoker API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Evoker.java b/src/main/java/net/minecraft/world/entity/monster/Evoker.java -index c0a5b0074480aad717177c92b28fa27b8a1d707d..617075955506500dc2d9c734398c48b8fc10b69d 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Evoker.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Evoker.java -@@ -40,7 +40,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; - - public class Evoker extends SpellcasterIllager { - -- private Sheep wololoTarget; -+ private Sheep wololoTarget; public final Sheep getWololoTarget() { return this.wololoTarget; } public final void setWololoTarget(Sheep sheep) { this.wololoTarget = sheep; } // Paper - OBFHELPER - - public Evoker(EntityType type, Level world) { - super(type, world); -@@ -59,7 +59,7 @@ public class Evoker extends SpellcasterIllager { - this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); - this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); - this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); -- this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).canUse()); -+ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers(new Class[0])); // Paper - decompile fix - this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); - this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, false)); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -index 29fec87c938c4252cf5c9473ce9e5c1908ea9063..950e35f67f88138cc2ce923be1ea7976bd317d1f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import net.minecraft.world.entity.animal.Sheep; - import net.minecraft.world.entity.monster.SpellcasterIllager; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; -@@ -35,4 +36,17 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { - public void setCurrentSpell(Evoker.Spell spell) { - getHandle().setIsCastingSpell(spell == null ? SpellcasterIllager.IllagerSpell.NONE : SpellcasterIllager.IllagerSpell.byId(spell.ordinal())); - } -+ -+ // Paper start -+ @Override -+ public org.bukkit.entity.Sheep getWololoTarget() { -+ Sheep sheep = getHandle().getWololoTarget(); -+ return sheep == null ? null : (org.bukkit.entity.Sheep) sheep.getBukkitEntity(); -+ } -+ -+ @Override -+ public void setWololoTarget(org.bukkit.entity.Sheep sheep) { -+ getHandle().setWololoTarget(sheep == null ? null : ((org.bukkit.craftbukkit.entity.CraftSheep) sheep).getHandle()); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/Remapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch deleted file mode 100644 index 163eac24a0..0000000000 --- a/Remapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 11 Aug 2020 19:16:09 +0200 -Subject: [PATCH] Add a way to get translation keys for blocks, entities and - materials - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index ae50030df7512c56c552e800b74ef4c69ec6d6d2..d38828485d6deb08036e11d8bf16b3d63a60fbae 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -278,6 +278,7 @@ public class EntityType { - return Registry.ENTITY_TYPE.getKey(type); - } - -+ public static Optional> getByName(String name) { return byString(name); } // Paper - OBFHELPER - public static Optional> byString(String id) { - return Registry.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(id)); - } -@@ -431,6 +432,7 @@ public class EntityType { - return this.category; - } - -+ public String getDescriptionId() { return getDescriptionId(); } // Paper - OBFHELPER - public String getDescriptionId() { - if (this.descriptionId == null) { - this.descriptionId = Util.makeDescriptionId("entity", Registry.ENTITY_TYPE.getKey(this)); -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 6fce16e89c5492654c891d5754714360a7649bca..58400e84830c93675b0a1fe632be5e217c19a932 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -56,7 +56,7 @@ public class Item implements ItemLike { - private final FoodProperties foodProperties; - - public static int getId(Item item) { -- return item == null ? 0 : Registry.ITEM.getId((Object) item); -+ return item == null ? 0 : Registry.ITEM.getId(item); // Paper - Fix Decompiler Issue - } - - public static Item byId(int id) { -@@ -152,6 +152,7 @@ public class Item implements ItemLike { - return Registry.ITEM.getKey(this).getPath(); - } - -+ public String getOrCreateDescriptionId() { return getOrCreateDescriptionId(); } // Paper - OBFHELPER - protected String getOrCreateDescriptionId() { - if (this.descriptionId == null) { - this.descriptionId = Util.makeDescriptionId("item", Registry.ITEM.getKey(this)); -@@ -164,6 +165,7 @@ public class Item implements ItemLike { - return this.getOrCreateDescriptionId(); - } - -+ public String getDescriptionId(ItemStack itemStack) { return getDescriptionId(itemStack); } // Paper - OBFHELPER - public String getDescriptionId(ItemStack stack) { - return this.getDescriptionId(); - } -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 5b84ee4091e354c4b6500f58a31931f2a6827ffc..baa587e73a71d6324bb7817fa4702a7c3a2db726 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -318,6 +318,7 @@ public class Block extends BlockBehaviour implements ItemLike { - return !this.material.isBuildable() && !this.material.isLiquid(); - } - -+ public String getOrCreateDescriptionId() { return getDescriptionId(); } // Paper - OBFHELPER - public String getDescriptionId() { - if (this.descriptionId == null) { - this.descriptionId = Util.makeDescriptionId("block", Registry.BLOCK.getKey(this)); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 05f0833f762436bf8f5f5875c7e3cfed1da11e1c..e09f65f0b06c8fb9a965b921c2c8e68ae2ac1e55 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -761,5 +761,10 @@ public class CraftBlock implements Block { - public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { - return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().defaultBlockState().getSoundType()); - } -+ -+ @Override -+ public String getTranslationKey() { -+ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); -+ } - // 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 a5a5038a84434e69fda8f6b41d2f00b4989e25ae..de5d02a1345f9886200f0540ac08be0df5878708 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -43,6 +43,7 @@ import org.bukkit.Registry; - import org.bukkit.UnsafeValues; - import org.bukkit.advancement.Advancement; - import org.bukkit.block.data.BlockData; -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.block.data.CraftBlockData; - import org.bukkit.craftbukkit.inventory.CraftItemStack; - import org.bukkit.craftbukkit.legacy.CraftLegacy; -@@ -418,6 +419,30 @@ public final class CraftMagicNumbers implements UnsafeValues { - throw new RuntimeException(); - } - } -+ -+ @Override -+ public String getTranslationKey(Material mat) { -+ if (mat.isBlock()) { -+ return getBlock(mat).getOrCreateDescriptionId(); -+ } -+ return getItem(mat).getDescriptionId(); -+ } -+ -+ @Override -+ public String getTranslationKey(org.bukkit.block.Block block) { -+ return ((org.bukkit.craftbukkit.block.CraftBlock)block).getNMS().getBlock().getOrCreateDescriptionId(); -+ } -+ -+ @Override -+ public String getTranslationKey(org.bukkit.entity.EntityType type) { -+ return net.minecraft.world.entity.EntityType.getByName(type.getName()).map(net.minecraft.world.entity.EntityType::getDescriptionId).orElse(null); -+ } -+ -+ @Override -+ public String getTranslationKey(org.bukkit.inventory.ItemStack itemStack) { -+ net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); -+ return nmsItemStack.getItem().getDescriptionId(nmsItemStack); -+ } - // Paper end - - /** diff --git a/Remapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch b/Remapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch deleted file mode 100644 index a7252fed8a..0000000000 --- a/Remapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 6 Jul 2020 22:18:04 +0200 -Subject: [PATCH] Create HoverEvent from ItemStack Entity - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 746755f76ae177b2eeccf66f8cd95e6ffd5acad9..2e0be9771ca3511f5d9364c57235556b70f07ec6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -365,5 +365,40 @@ public final class CraftItemFactory implements ItemFactory { - - return nms != null ? net.minecraft.locale.Language.getInstance().translateKey(nms.getItem().getDescriptionId()) : null; - } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(ItemStack itemStack) { -+ net.md_5.bungee.api.chat.ItemTag itemTag = net.md_5.bungee.api.chat.ItemTag.ofNbt(CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString()); -+ return new net.md_5.bungee.api.chat.hover.content.Item( -+ itemStack.getType().getKey().toString(), -+ itemStack.getAmount(), -+ itemTag); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity) { -+ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(entity.getCustomName()) ? null : new net.md_5.bungee.api.chat.TextComponent(entity.getCustomName())); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, String customName) { -+ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(customName) ? null : new net.md_5.bungee.api.chat.TextComponent(customName)); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent customName) { -+ return new net.md_5.bungee.api.chat.hover.content.Entity( -+ entity.getType().getKey().toString(), -+ entity.getUniqueId().toString(), -+ customName); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent[] customName) { -+ return new net.md_5.bungee.api.chat.hover.content.Entity( -+ entity.getType().getKey().toString(), -+ entity.getUniqueId().toString(), -+ new net.md_5.bungee.api.chat.TextComponent(customName)); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch b/Remapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch deleted file mode 100644 index b4924166cc..0000000000 --- a/Remapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Thu, 6 Dec 2018 19:52:50 -0500 -Subject: [PATCH] Cache block data strings - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 735c3c983e96e4e6f36de0975909fc48cb042081..5c5903867432894b47bc62d89989f78c36a84ca1 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1953,6 +1953,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop%s", nms, bukkit); - } - -+ // Paper start - cache block data strings -+ private static Map stringDataCache = new HashMap<>(); -+ -+ static { -+ // cache all of the default states at startup, will not cache ones with the custom states inside of the -+ // brackets in a different order, though -+ reloadCache(); -+ } -+ -+ public static void reloadCache() { -+ stringDataCache.clear(); -+ Block.BLOCK_STATE_REGISTRY.forEach(blockData -> stringDataCache.put(blockData.toString(), blockData.createCraftBlockData())); -+ } -+ // Paper end -+ - public static CraftBlockData newData(Material material, String data) { - Preconditions.checkArgument(material == null || material.isBlock(), "Cannot get data for not block %s", material); - -+ // Paper start - cache block data strings -+ if (material != null) { -+ Block block = CraftMagicNumbers.getBlock(material); -+ if (block != null) { -+ ResourceLocation key = Registry.BLOCK.getKey(block); -+ data = data == null ? key.toString() : key + data; -+ } -+ } -+ -+ CraftBlockData cached = stringDataCache.computeIfAbsent(data, s -> createNewData(null, s)); -+ return (CraftBlockData) cached.clone(); -+ } -+ -+ private static CraftBlockData createNewData(Material material, String data) { -+ // Paper end - cache block data strings - BlockState blockData; - Block block = CraftMagicNumbers.getBlock(material); - Map, Comparable> parsed = null; diff --git a/Remapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/Remapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch deleted file mode 100644 index 1e30590a64..0000000000 --- a/Remapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 25 Aug 2020 20:45:36 -0400 -Subject: [PATCH] Fix Entity Teleportation and cancel velocity if teleported - -Uses correct setPositionRotation for Entity teleporting instead of setLocation -as this is how Vanilla teleports entities. - -Cancel any pending motion when teleported. - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ab6494f5a872bba5398bef0367b4d9257786f61e..ab45497e8f7720c9d60626b32e9c95779af676b0 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -691,7 +691,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - public void handleAcceptTeleportPacket(ServerboundAcceptTeleportationPacket packet) { - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); - if (packet.getId() == this.awaitingTeleport && this.awaitingPositionFromClient != null) { // CraftBukkit -- this.player.absMoveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.yRot, this.player.xRot); -+ this.player.moveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.yRot, this.player.xRot); // Paper - use proper setPositionRotation for teleportation - this.lastGoodX = this.awaitingPositionFromClient.x; - this.lastGoodY = this.awaitingPositionFromClient.y; - this.lastGoodZ = this.awaitingPositionFromClient.z; -@@ -1536,7 +1536,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // CraftBukkit end - - this.awaitingTeleportTime = this.tickCount; -- this.player.absMoveTo(d0, d1, d2, f, f1); -+ this.player.moveTo(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation - this.player.forceCheckHighPriority(); // Paper - this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index aea2457510c75214bbb925307155611e981f115f..d69981a1b5a40418c7d17de5f3bece30592ae586 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -143,6 +143,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - - // CraftBukkit start - private static final int CURRENT_LEVEL = 2; -+ public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation - static boolean isLevelAtLeast(CompoundTag tag, int level) { - return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; - } -@@ -1406,6 +1407,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public void moveTo(double x, double y, double z, float yaw, float pitch) { -+ // Paper - cancel entity velocity if teleported -+ if (!preserveMotion) { -+ this.deltaMovement = Vec3.ZERO; -+ } else { -+ this.preserveMotion = false; -+ } -+ // Paper end - this.setPosAndOldPos(x, y, z); - this.yRot = yaw; - this.xRot = pitch; -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 6ca378ec7868b855d46c749910c656f82ddb009f..091e72474ac199c38fff979a5faf524e011d8d0a 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -165,6 +165,7 @@ public abstract class BaseSpawner { - return; - } - -+ entity.preserveMotion = true; // Paper - preserve entity motion from tag - entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), world.random.nextFloat() * 360.0F, 0.0F); - if (entity instanceof Mob) { - Mob entityinsentient = (Mob) entity; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index deeae62e9926f9435907c68e7d35e7420f5e79dd..1275768762884416fa3c68dab3a6671b24949976 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -556,7 +556,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - } - - // entity.setLocation() throws no event, and so cannot be cancelled -- entity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); -+ entity.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); // Paper - use proper setPosition, as per vanilla teleporting - // SPIGOT-619: Force sync head rotation also - entity.setYHeadRot(location.getYaw()); - ((net.minecraft.server.level.ServerLevel) entity.level).updateChunkPos(entity); // Spigot - register to new chunk diff --git a/Remapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch b/Remapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch deleted file mode 100644 index 4f031f39de..0000000000 --- a/Remapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 26 Aug 2020 02:12:31 -0400 -Subject: [PATCH] Add additional open container api 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 878a62e04962aafeaf192075fbe08e319298a800..aceb57c93c91730345f49f78838780c41ce2dcef 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -459,6 +459,70 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - return this.getHandle().containerMenu.getBukkitView(); - } - -+ // Paper start - Add additional containers -+ @Override -+ public InventoryView openAnvil(Location location, boolean force) { -+ return openInventory(location, force, Material.ANVIL); -+ } -+ -+ @Override -+ public InventoryView openCartographyTable(Location location, boolean force) { -+ return openInventory(location, force, Material.CARTOGRAPHY_TABLE); -+ } -+ -+ @Override -+ public InventoryView openGrindstone(Location location, boolean force) { -+ return openInventory(location, force, Material.GRINDSTONE); -+ } -+ -+ @Override -+ public InventoryView openLoom(Location location, boolean force) { -+ return openInventory(location, force, Material.LOOM); -+ } -+ -+ @Override -+ public InventoryView openSmithingTable(Location location, boolean force) { -+ return openInventory(location, force, Material.SMITHING_TABLE); -+ } -+ -+ @Override -+ public InventoryView openStonecutter(Location location, boolean force) { -+ return openInventory(location, force, Material.STONECUTTER); -+ } -+ -+ private InventoryView openInventory(Location location, boolean force, Material material) { -+ org.spigotmc.AsyncCatcher.catchOp("open" + material); -+ if (location == null) { -+ location = getLocation(); -+ } -+ if (!force) { -+ Block block = location.getBlock(); -+ if (block.getType() != material) { -+ return null; -+ } -+ } -+ net.minecraft.world.level.block.Block block; -+ if (material == Material.ANVIL) { -+ block = Blocks.ANVIL; -+ } else if (material == Material.CARTOGRAPHY_TABLE) { -+ block = Blocks.CARTOGRAPHY_TABLE; -+ } else if (material == Material.GRINDSTONE) { -+ block = Blocks.GRINDSTONE; -+ } else if (material == Material.LOOM) { -+ block = Blocks.LOOM; -+ } else if (material == Material.SMITHING_TABLE) { -+ block = Blocks.SMITHING_TABLE; -+ } else if (material == Material.STONECUTTER) { -+ block = Blocks.STONECUTTER; -+ } else { -+ throw new IllegalArgumentException("Unsupported inventory type: " + material); -+ } -+ getHandle().openMenu(block.getMenuProvider(null, getHandle().level, new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()))); -+ getHandle().containerMenu.checkReachable = !force; -+ return getHandle().containerMenu.getBukkitView(); -+ } -+ // Paper end -+ - @Override - public void closeInventory() { - // Paper start diff --git a/Remapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/Remapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch deleted file mode 100644 index a02addc375..0000000000 --- a/Remapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 12 Sep 2020 17:21:38 -0400 -Subject: [PATCH] Cache DataFixerUpper Rewrite Rules on demand - -Mojang precaches every single potential rewrite rule that could ever -exist on server startup. This includes rules from all the way back to versions from 6+ years ago. - -This is the source of why the server hogs every CPU core at 100% every start. - -For anyone who hard resets for updates or has force upgraded their entire world, this -results in completely wasted cpu cycles. - -This massive CPU usage also delays server startup time. - -We improve this by making "min version to precache" that defaults to a future version -so that no rewrite rules are precached. - -someone who expects to be converting a lot chunks could theoretically set --DPaper.minPrecachedDatafixVersion= as a startup -parameter and only build from that point on. - -However this will likely never be needed as the server will still run -the same cache logic on demand when it's actually needed. The only -cost would be some delay on the FIRST chunk conversion, but paper already -runs chunk conversions on another thread so this will likely never be -a concern for TPS. - -This patch will significantly reduce CPU use on startup, reduce memory usage, -and improve server startup time. - -diff --git a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java -index edb77982d273e9492ab1a669ca1ad89da2ec3c3e..abc265b00044b14abb55c2628d454ee01fef467b 100644 ---- a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java -+++ b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java -@@ -26,8 +26,10 @@ public class DataFixerBuilder { - private final Int2ObjectSortedMap schemas = new Int2ObjectAVLTreeMap<>(); - private final List globalList = Lists.newArrayList(); - private final IntSortedSet fixerVersions = new IntAVLTreeSet(); -+ private final int minDataFixPrecacheVersion; // Paper - - public DataFixerBuilder(final int dataVersion) { -+ minDataFixPrecacheVersion = Integer.getInteger("Paper.minPrecachedDatafixVersion", dataVersion+1) * 10; // Paper - default to precache nothing - mojang stores versions * 10 to allow for 'sub versions' - this.dataVersion = dataVersion; - } - -@@ -65,6 +67,7 @@ public class DataFixerBuilder { - final IntBidirectionalIterator iterator = fixerUpper.fixerVersions().iterator(); - while (iterator.hasNext()) { - final int versionKey = iterator.nextInt(); -+ if (versionKey < minDataFixPrecacheVersion) continue; // Paper - final Schema schema = schemas.get(versionKey); - for (final String typeName : schema.types()) { - CompletableFuture.runAsync(() -> { diff --git a/Remapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch b/Remapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch deleted file mode 100644 index 21f6d53f47..0000000000 --- a/Remapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 17 Sep 2020 00:36:05 +0100 -Subject: [PATCH] Extend block drop capture to capture all items added to the - world - - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 22266fda4de9b5fbace3b8e55ce390b8d7e75a65..fe7b71fbb3963beafe93a5d86bebdd629c7ec8f2 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -95,6 +95,7 @@ import net.minecraft.world.entity.ai.village.poi.PoiType; - import net.minecraft.world.entity.animal.horse.SkeletonHorse; - import net.minecraft.world.entity.boss.EnderDragonPart; - import net.minecraft.world.entity.boss.enderdragon.EnderDragon; -+import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.entity.monster.Drowned; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.raid.Raid; -@@ -1284,6 +1285,13 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } else if (this.isUUIDUsed(entity)) { - return false; - } else { -+ // Paper start - capture all item additions to the world -+ if (captureDrops != null && entity instanceof ItemEntity) { -+ captureDrops.add((ItemEntity) entity); -+ return true; -+ } -+ // Paper end -+ - if (!CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { - return false; - } -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index 79f3e4176145c42debb9adc1e68175cf063c1f22..6269e37f2859417a80e6de16045f1c2325f9746f 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -6,6 +6,7 @@ import net.minecraft.world.InteractionResult; - import net.minecraft.world.InteractionResultHolder; - import net.minecraft.world.MenuProvider; - import net.minecraft.world.entity.EquipmentSlot; -+import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.DoubleHighBlockItem; - import net.minecraft.world.item.ItemStack; -@@ -418,10 +419,12 @@ public class ServerPlayerGameMode { - // return true; // CraftBukkit - } - // CraftBukkit start -+ java.util.List itemsToDrop = level.captureDrops; // Paper - store current list -+ level.captureDrops = null; // Paper - Remove this earlier so that we can actually drop stuff - if (event.isDropItems()) { -- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, level.captureDrops); -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - use stored ref - } -- level.captureDrops = null; -+ //world.captureDrops = null; // Paper - move up - - // Drop event experience - if (flag && event != null) { diff --git a/Remapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/Remapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch deleted file mode 100644 index 07195903cb..0000000000 --- a/Remapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sun, 27 Sep 2020 16:25:24 +0200 -Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086) - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 82205ad13ef0e987bd83979d06331545efe0a60a..50dc47e8c03ce274d558bc0dfa73ba3ab5fbae5c 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -388,6 +388,7 @@ public class ChunkHolder { - } - - public void blockChanged(BlockPos blockposition) { -+ if (!blockposition.isValidLocation()) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks - LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { diff --git a/Remapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/Remapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch deleted file mode 100644 index 6eb1a44bc0..0000000000 --- a/Remapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Fri, 28 Aug 2020 01:41:26 +0200 -Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and - non-conflicting Entity Ids - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d69981a1b5a40418c7d17de5f3bece30592ae586..fa22c0d7f676c96d34bf56d80181d6b047f2ff0b 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -3476,4 +3476,10 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - - void accept(Entity entity, double x, double y, double z); - } -+ -+ // Paper start -+ public static int nextEntityId() { -+ return ENTITY_COUNTER.incrementAndGet(); -+ } -+ // 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 de5d02a1345f9886200f0540ac08be0df5878708..9a16882deee21faf78ea46e08b2f2ad3fbb6021b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -443,6 +443,10 @@ public final class CraftMagicNumbers implements UnsafeValues { - net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); - return nmsItemStack.getItem().getDescriptionId(nmsItemStack); - } -+ -+ public int nextEntityId() { -+ return net.minecraft.world.entity.Entity.nextEntityId(); -+ } - // Paper end - - /** diff --git a/Remapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch b/Remapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch deleted file mode 100644 index e06db589aa..0000000000 --- a/Remapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Sat, 3 Oct 2020 04:15:09 -0400 -Subject: [PATCH] Lazily track plugin scoreboards by default - -On servers with plugins that constantly churn through scoreboards, there is a risk of -degraded GC performance due to the number of scoreboards held on by weak references. -Most plugins don't even need the (vanilla) functionality that requires all plugin -scoreboards to be tracked by the server. Instead, only track scoreboards when an -objective is added with a non-dummy criteria. - -This is a breaking change, however the change is a much more sensible default. In case -this breaks your workflow you can always force all scoreboards to be tracked with -settings.track-plugin-scoreboards in paper.yml. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 545948f20efd6c8dd42140b565af94cd6b52b661..7d50aded88f5b7dfebaea1aebc86231f7b5c4e25 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -462,4 +462,9 @@ public class PaperConfig { - private static void maxJoinsPerTick() { - maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); - } -+ -+ public static boolean trackPluginScoreboards; -+ private static void trackPluginScoreboards() { -+ trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -index 4c93be31fd95d731327479519ecb34a08785c1ca..57537b8871dd5c54d97f3effe1802a3396644e46 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -@@ -18,6 +18,7 @@ import org.bukkit.scoreboard.Team; - - public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - final Scoreboard board; -+ boolean registeredGlobally = false; // Paper - - CraftScoreboard(Scoreboard board) { - this.board = board; -@@ -44,6 +45,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); - Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); - CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ // Paper start - the block comment from the old registerNewObjective didnt cause a conflict when rebasing, so this block wasn't added to the adventure registerNewObjective -+ if (craftCriteria.criteria != net.minecraft.world.scores.criteria.ObjectiveCriteria.DUMMY && !registeredGlobally) { -+ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); -+ registeredGlobally = true; -+ } -+ // Paper end - net.minecraft.world.scores.Objective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); - return new CraftObjective(this, objective); - } -@@ -65,6 +72,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); - - CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ // Paper start -+ if (craftCriteria.criteria != net.minecraft.server.IScoreboardCriteria.DUMMY && !registeredGlobally) { -+ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); -+ registeredGlobally = true; -+ } -+ // Paper end - ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); - return new CraftObjective(this, objective);*/ // Paper - return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -index 30b0d4986a7edcf324d94d9304d66d0567098855..8217e35f5a3093e63a165ee8c8b30bf3f28f3bd3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -@@ -30,6 +30,7 @@ public final class CraftScoreboardManager implements ScoreboardManager { - - public CraftScoreboardManager(MinecraftServer minecraftserver, net.minecraft.world.scores.Scoreboard scoreboardServer) { - mainScoreboard = new CraftScoreboard(scoreboardServer); -+ mainScoreboard.registeredGlobally = true; // Paper - server = minecraftserver; - scoreboards.add(mainScoreboard); - } -@@ -43,10 +44,22 @@ public final class CraftScoreboardManager implements ScoreboardManager { - public CraftScoreboard getNewScoreboard() { - org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot - CraftScoreboard scoreboard = new CraftScoreboard(new ServerScoreboard(server)); -+ // Paper start -+ if (com.destroystokyo.paper.PaperConfig.trackPluginScoreboards) { -+ scoreboard.registeredGlobally = true; - scoreboards.add(scoreboard); -+ } -+ // Paper end - return scoreboard; - } - -+ // Paper start -+ public void registerScoreboardForVanilla(CraftScoreboard scoreboard) { -+ org.spigotmc.AsyncCatcher.catchOp("scoreboard registration"); -+ scoreboards.add(scoreboard); -+ } -+ // Paper end -+ - // CraftBukkit method - public CraftScoreboard getPlayerBoard(CraftPlayer player) { - CraftScoreboard board = playerBoards.get(player); diff --git a/Remapped-Spigot-Server-Patches/0573-Entity-isTicking.patch b/Remapped-Spigot-Server-Patches/0573-Entity-isTicking.patch deleted file mode 100644 index 22d5c7950d..0000000000 --- a/Remapped-Spigot-Server-Patches/0573-Entity-isTicking.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 21:39:16 -0500 -Subject: [PATCH] Entity#isTicking - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index fa22c0d7f676c96d34bf56d80181d6b047f2ff0b..a623c22cd03ad92657e661851fddc76a30986755 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -49,6 +49,7 @@ import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkMap; -+import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.level.TicketType; -@@ -3481,5 +3482,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public static int nextEntityId() { - return ENTITY_COUNTER.incrementAndGet(); - } -+ -+ public boolean isTicking() { -+ return ((ServerChunkCache) level.getChunkSource()).isInEntityTickingChunk(this); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 1275768762884416fa3c68dab3a6671b24949976..502773ae60290125057fb342a3358ff55927d196 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1159,5 +1159,9 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public boolean isInLava() { - return getHandle().isInLava(); - } -+ -+ public boolean isTicking() { -+ return getHandle().isTicking(); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/Remapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch deleted file mode 100644 index 2d6ec97910..0000000000 --- a/Remapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 22:00:27 -0500 -Subject: [PATCH] Fix deop kicking non-whitelisted player when white list is - not enabled - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 5c5903867432894b47bc62d89989f78c36a84ca1..954dce690852da87a37e7797c6f9f549242e511a 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2018,6 +2018,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop list = Lists.newArrayList(playerlist.getPlayers()); - Iterator iterator = list.iterator(); - diff --git a/Remapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch b/Remapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch deleted file mode 100644 index 5b9dbf362f..0000000000 --- a/Remapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 8 Oct 2020 00:00:25 -0400 -Subject: [PATCH] Fix "Not a string" Map Conversion spam - -The maps did convert successfully, but had noisy logs due to Spigot -implementing this logic incorrectly. - -This stops the spam by converting the old format to new before -requesting the world. - -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -index 7582c7cd4235d212a0cf66a4c59ce0cedaa360ad..e7b178127228dea5a17ba0fbd6bae148d70e8eb5 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -@@ -12,6 +12,8 @@ import net.minecraft.core.BlockPos; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.nbt.NbtOps; -+import net.minecraft.nbt.NumericTag; -+import net.minecraft.nbt.StringTag; - import net.minecraft.nbt.Tag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.protocol.Packet; -@@ -94,7 +96,26 @@ public class MapItemSavedData extends SavedData { - - @Override - public void load(CompoundTag tag) { -- DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, tag.get("dimension"))); // CraftBukkit - decompile error -+ // Paper start - fix "Not a string" spam -+ Tag dimension = tag.get("dimension"); -+ if (dimension instanceof NumericTag && ((NumericTag) dimension).getAsInt() >= CraftWorld.CUSTOM_DIMENSION_OFFSET) { -+ long least = tag.getLong("UUIDLeast"); -+ long most = tag.getLong("UUIDMost"); -+ -+ if (least != 0L && most != 0L) { -+ this.uniqueId = new UUID(most, least); -+ CraftWorld world = (CraftWorld) server.getWorld(this.uniqueId); -+ if (world != null) { -+ dimension = StringTag.create("minecraft:" + world.getName().toLowerCase(java.util.Locale.ENGLISH)); -+ } else { -+ dimension = StringTag.create("bukkit:_invalidworld_"); -+ } -+ } else { -+ dimension = StringTag.create("bukkit:_invalidworld_"); -+ } -+ } -+ DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, dimension)); // CraftBukkit - decompile error -+ // Paper end - fix "Not a string" spam - Logger logger = MapItemSavedData.LOGGER; - - logger.getClass(); diff --git a/Remapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/Remapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch deleted file mode 100644 index d952b410f0..0000000000 --- a/Remapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Sun, 4 Oct 2020 19:55:25 -0700 -Subject: [PATCH] Fix CME on adding a passenger in CreatureSpawnEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a623c22cd03ad92657e661851fddc76a30986755..90e9797cc1f3a4aa0a2bee28dca364e6f6dd0c0b 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -3180,7 +3180,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public Stream getSelfAndPassengers() { -- return Stream.concat(Stream.of(this), this.passengers.stream().flatMap(Entity::getSelfAndPassengers)); -+ return Stream.concat(Stream.of(this), com.google.common.collect.ImmutableList.copyOf(this.passengers).stream().flatMap(Entity::getSelfAndPassengers)); // Paper - } - - public boolean hasOnePlayerPassenger() { diff --git a/Remapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch b/Remapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch deleted file mode 100644 index 02442096a4..0000000000 --- a/Remapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Wed, 18 Mar 2020 00:07:46 -0500 -Subject: [PATCH] MC-147729: Drop items that are extra from a crafting recipe - - -diff --git a/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java b/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java -index a18aa176850bef45afcaf5742e9afbfa39281e22..c6ba6aabf94c26cccbd14689ea32373c17bbccc4 100644 ---- a/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java -+++ b/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java -@@ -71,7 +71,12 @@ public class ServerPlaceRecipe implements PlaceRecipe -Date: Wed, 1 Jun 2016 23:29:17 -0400 -Subject: [PATCH] Reset Ender Crystals on Dragon Spawn - -Crystals can end up in a bad state in certain conditions which causes -an exception on the expected number of crystals going negative. - -This ensures the crystals/pillars are in expected state when the dragon spawns. - -See #3522 - -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 4b18931225ef60dbcffd7fcc20d0e9ce62348a07..590df3b93b897613cad74f9920aec62b33a2f7f7 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -441,6 +441,7 @@ public class EndDragonFight { - entityenderdragon.moveTo(0.0D, 128.0D, 0.0D, this.level.random.nextFloat() * 360.0F, 0.0F); - this.level.addFreshEntity(entityenderdragon); - this.dragonUUID = entityenderdragon.getUUID(); -+ this.resetSpikeCrystals(); // Paper - return entityenderdragon; - } - diff --git a/Remapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch b/Remapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch deleted file mode 100644 index 42d90f77ee..0000000000 --- a/Remapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 17 May 2020 23:47:33 -0700 -Subject: [PATCH] Fix for large move vectors crashing server - -Check movement distance also based on current position. - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ab45497e8f7720c9d60626b32e9c95779af676b0..3a114bec14fcc6c1e1045e2b99178a6adb25f387 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -516,19 +516,24 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) { - ServerLevel worldserver = this.player.getLevel(); -- double d0 = entity.getX(); -- double d1 = entity.getY(); -- double d2 = entity.getZ(); -- double d3 = packet.getX(); -- double d4 = packet.getY(); -- double d5 = packet.getZ(); -+ double d0 = entity.getX();double fromX = d0; // Paper - OBFHELPER -+ double d1 = entity.getY();double fromY = d1; // Paper - OBFHELPER -+ double d2 = entity.getZ();double fromZ = d2; // Paper - OBFHELPER -+ double d3 = packet.getX();double toX = d3; // Paper - OBFHELPER -+ double d4 = packet.getY();double toY = d4; // Paper - OBFHELPER -+ double d5 = packet.getZ();double toZ = d5; // Paper - OBFHELPER - float f = packet.getYRot(); - float f1 = packet.getXRot(); - double d6 = d3 - this.vehicleFirstGoodX; - double d7 = d4 - this.vehicleFirstGoodY; - double d8 = d5 - this.vehicleFirstGoodZ; - double d9 = entity.getDeltaMovement().lengthSqr(); -- double d10 = d6 * d6 + d7 * d7 + d8 * d8; -+ // Paper start - fix large move vectors killing the server -+ double currDeltaX = toX - fromX; -+ double currDeltaY = toY - fromY; -+ double currDeltaZ = toZ - fromZ; -+ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); -+ // Paper end - fix large move vectors killing the server - - - // CraftBukkit start - handle custom speeds and skipped ticks -@@ -1230,7 +1235,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - double d2 = this.player.getZ(); - double d3 = this.player.getY(); - double d4 = packet.getX(this.player.getX());double toX = d4; // Paper - OBFHELPER -- double d5 = packet.getY(this.player.getY()); -+ double d5 = packet.getY(this.player.getY());double toY = d5; // Paper - OBFHELPER - double d6 = packet.getZ(this.player.getZ());double toZ = d6; // Paper - OBFHELPER - float f = packet.getYRot(this.player.yRot); - float f1 = packet.getXRot(this.player.xRot); -@@ -1238,7 +1243,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - double d8 = d5 - this.firstGoodY; - double d9 = d6 - this.firstGoodZ; - double d10 = this.player.getDeltaMovement().lengthSqr(); -- double d11 = d7 * d7 + d8 * d8 + d9 * d9; -+ // Paper start - fix large move vectors killing the server -+ double currDeltaX = toX - prevX; -+ double currDeltaY = toY - prevY; -+ double currDeltaZ = toZ - prevZ; -+ double d11 = Math.max(d7 * d7 + d8 * d8 + d9 * d9, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); -+ // Paper end - fix large move vectors killing the server - - if (this.player.isSleeping()) { - if (d11 > 1.0D) { diff --git a/Remapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch b/Remapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch deleted file mode 100644 index f1103a3993..0000000000 --- a/Remapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 3 Jun 2020 11:37:13 -0700 -Subject: [PATCH] Optimise getType calls - -Remove the map lookup for converting from Block->Bukkit Material - -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockState.java b/src/main/java/net/minecraft/world/level/block/state/BlockState.java -index 9958cdf55cef2177fafd0cdae48da9db064af9f1..4263ac345d57e36e010e3dd009130c02799b249c 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockState.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockState.java -@@ -11,6 +11,19 @@ public class BlockState extends BlockBehaviour.BlockStateBase { - - public static final Codec CODEC = codec((Codec) Registry.BLOCK, Block::defaultBlockState).stable(); - -+ -+ // Paper start - optimise getType calls -+ org.bukkit.Material cachedMaterial; -+ -+ public final org.bukkit.Material getBukkitMaterial() { -+ if (this.cachedMaterial == null) { -+ this.cachedMaterial = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(this.getBlock()); -+ } -+ -+ return this.cachedMaterial; -+ } -+ // Paper end - optimise getType calls -+ - public BlockState(Block block, ImmutableMap, Comparable> propertyMap, MapCodec mapcodec) { - super(block, propertyMap, mapcodec); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -index fe00c8fdacc28a68c732aac0b887ea107d87e979..227974a85a81c623311301e28e83e85424b05f3d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -@@ -78,7 +78,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot { - public Material getBlockType(int x, int y, int z) { - CraftChunk.validateChunkCoordinates(x, y, z); - -- return CraftMagicNumbers.getMaterial(blockids[y >> 4].get(x, y & 0xF, z).getBlock()); -+ return blockids[y >> 4].get(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index e09f65f0b06c8fb9a965b921c2c8e68ae2ac1e55..37eceaef1212e2ee13aa763a5ede24ec170e5391 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -211,7 +211,7 @@ public class CraftBlock implements Block { - - @Override - public Material getType() { -- return CraftMagicNumbers.getMaterial(world.getBlockState(position).getBlock()); -+ return world.getBlockState(position).getBukkitMaterial(); // Paper - optimise getType calls - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -index 754559c9e47032845fdc94eedad0cece0e0ae4c7..7e4c522605cf04a38a7a0f54e7ac6ea0e372c98d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -@@ -134,7 +134,7 @@ public class CraftBlockState implements BlockState { - - @Override - public Material getType() { -- return CraftMagicNumbers.getMaterial(data.getBlock()); -+ return data.getBukkitMaterial(); // Paper - optimise getType calls - } - - public void setFlag(int flag) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -index 03e065bf92cafd376ad0f878584cdac6fd196245..d93f2373f3127462aa2f9b69f7cc808b58d47b61 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -@@ -45,7 +45,7 @@ public class CraftBlockData implements BlockData { - - @Override - public Material getMaterial() { -- return CraftMagicNumbers.getMaterial(state.getBlock()); -+ return state.getBukkitMaterial(); // Paper - optimise getType calls - } - - public BlockState getState() { -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index fd2cb2a584fea360fcf8180338708f35c4e3dc1f..a463b89888460e5a894098c20eb4c4a78c04642c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -73,7 +73,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - - @Override - public Material getType(int x, int y, int z) { -- return CraftMagicNumbers.getMaterial(getTypeId(x, y, z).getBlock()); -+ return getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch b/Remapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch deleted file mode 100644 index 2d03e1410f..0000000000 --- a/Remapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Mon, 7 Oct 2019 00:15:37 -0500 -Subject: [PATCH] Villager#resetOffers - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -index 9eee68a5a84e121698d26bd54212a72c75e16251..407a68edf6408400f1a6c5bb1a6cbbfae08ac2cd 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -111,6 +111,13 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan - return this.tradingPlayer != null; - } - -+ // Paper start -+ public void resetOffers() { -+ this.offers = new MerchantOffers(); -+ this.updateTrades(); -+ } -+ // Paper end -+ - @Override - public MerchantOffers getOffers() { - if (this.offers == null) { -@@ -232,6 +239,7 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan - return this.level; - } - -+ protected final void updateTrades() { updateTrades(); } // Paper - OBFHELPER - protected abstract void updateTrades(); - - protected void addOffersFromItemListings(MerchantOffers recipeList, VillagerTrades.ItemListing[] pool, int count) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -index 8ffdfe3e8229b556838eab18dcb6bfb0c05a6063..7f887e883a87f2df7ae428ffddb072724d602d62 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -@@ -70,4 +70,11 @@ public class CraftAbstractVillager extends CraftAgeable implements AbstractVilla - public HumanEntity getTrader() { - return getMerchant().getTrader(); - } -+ -+ // Paper start -+ @Override -+ public void resetOffers() { -+ getHandle().resetOffers(); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/Remapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch deleted file mode 100644 index fc2f46516c..0000000000 --- a/Remapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Jul 2020 20:46:50 -0700 -Subject: [PATCH] Improve inlinig for some hot IBlockData methods - - -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index f2fefdad26057c722085e60ba837fe2c117f55f7..17baae6b11f191f4738a107c7e62ea5bdac17a3c 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -390,7 +390,14 @@ public abstract class BlockBehaviour { - } - // Paper end - -+ // Paper start -+ protected boolean isTicking; -+ protected FluidState fluid; -+ // Paper end -+ - public void initCache() { -+ this.fluid = this.getBlock().getFluidState(this.asState()); // Paper - moved from getFluid() -+ this.isTicking = this.getBlock().isRandomlyTicking(this.asState()); // Paper - moved from isTicking() - if (!this.getBlock().hasDynamicShape()) { - this.cache = new BlockBehaviour.BlockStateBase.Cache(this.asState()); - } -@@ -429,19 +436,19 @@ public abstract class BlockBehaviour { - return this.getBlock().getOcclusionShape(this.asState(), world, pos); - } - -- public boolean hasLargeCollisionShape() { -+ public final boolean hasLargeCollisionShape() { // Paper - return this.cache == null || this.cache.largeCollisionShape; - } - -- public boolean useShapeForLightOcclusion() { -+ public final boolean useShapeForLightOcclusion() { // Paper - return this.useShapeForLightOcclusion; - } - -- public int getLightEmission() { -+ public final int getLightEmission() { // Paper - return this.lightEmission; - } - -- public boolean isAir() { -+ public final boolean isAir() { // Paper - return this.isAir; - } - -@@ -507,7 +514,7 @@ public abstract class BlockBehaviour { - } - } - -- public boolean canOcclude() { -+ public final boolean canOcclude() { // Paper - return this.canOcclude; - } - -@@ -679,12 +686,12 @@ public abstract class BlockBehaviour { - return this.getBlock().is(block); - } - -- public FluidState getFluidState() { -- return this.getBlock().getFluidState(this.asState()); -+ public final FluidState getFluidState() { // Paper -+ return this.fluid; // Paper - moved into init - } - -- public boolean isRandomlyTicking() { -- return this.getBlock().isRandomlyTicking(this.asState()); -+ public final boolean isRandomlyTicking() { // Paper -+ return this.isTicking; // Paper - moved into init - } - - public SoundType getSoundType() { -diff --git a/src/main/java/net/minecraft/world/level/material/FluidState.java b/src/main/java/net/minecraft/world/level/material/FluidState.java -index c077e4a7ce6a484956206eaab9dfde057b7e429a..69cf9e149c207336c537a00f08251a2252752df6 100644 ---- a/src/main/java/net/minecraft/world/level/material/FluidState.java -+++ b/src/main/java/net/minecraft/world/level/material/FluidState.java -@@ -20,8 +20,12 @@ public final class FluidState extends StateHolder { - - public static final Codec CODEC = codec((Codec) Registry.FLUID, Fluid::defaultFluidState).stable(); - -+ // Paper start -+ protected final boolean isEmpty; -+ // Paper end - public FluidState(Fluid fluid, ImmutableMap, Comparable> propertiesMap, MapCodec mapcodec) { - super(fluid, propertiesMap, mapcodec); -+ this.isEmpty = fluid.isEmpty(); // Paper - moved from isEmpty() - } - - public Fluid getType() { -@@ -33,7 +37,7 @@ public final class FluidState extends StateHolder { - } - - public boolean isEmpty() { -- return this.getType().isEmpty(); -+ return this.isEmpty; // Paper - moved into constructor - } - - public float getHeight(BlockGetter world, BlockPos pos) { diff --git a/Remapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch b/Remapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch deleted file mode 100644 index 1d1bff4b34..0000000000 --- a/Remapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 7 Aug 2020 04:27:56 -0700 -Subject: [PATCH] Retain block place order when capturing blockstates - -Fixes twisted vines not connecting properly when grown via -bonemeal by a player. - -In general, look at making this logic more robust (i.e properly handling -cases where a captured entry is overriden) - but for now this will do. - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index ebb92f88e0402681c47834bcf45e6b236748289a..2ad8a4558aa812885adebee8c05dab45f2bf5f90 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -135,7 +135,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; - public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper -- public Map capturedTileEntities = new HashMap<>(); -+ public Map capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - public List captureDrops; - public long ticksPerAnimalSpawns; - public long ticksPerMonsterSpawns; diff --git a/Remapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch b/Remapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch deleted file mode 100644 index 9371d97aec..0000000000 --- a/Remapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 25 Apr 2020 17:10:55 -0700 -Subject: [PATCH] Reduce blockpos allocation from pathfinding - - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java -index 7ae24381b91c282745b7fe5f6897865e74bc0acf..3c460682611969a5db136aa41ca0d230c6228d56 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java -@@ -498,7 +498,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { - return BlockPathTypes.DANGER_FIRE; - } - -- if (iblockaccess.getFluidState(blockposition_mutableblockposition).is((Tag) FluidTags.WATER)) { -+ if (iblockdata.getFluidState().is((Tag) FluidTags.WATER)) { // Paper - remove another getType call - return BlockPathTypes.WATER_BORDER; - } - } // Paper -@@ -528,7 +528,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { - } else if (iblockdata.is(Blocks.COCOA)) { - return BlockPathTypes.COCOA; - } else { -- FluidState fluid = iblockaccess.getFluidState(blockposition); -+ FluidState fluid = iblockdata.getFluidState(); // Paper - remove another get type call - - return fluid.is((Tag) FluidTags.WATER) ? BlockPathTypes.WATER : (fluid.is((Tag) FluidTags.LAVA) ? BlockPathTypes.LAVA : (isBurningBlock(iblockdata) ? BlockPathTypes.DAMAGE_FIRE : (DoorBlock.isWoodenDoor(iblockdata) && !(Boolean) iblockdata.getValue(DoorBlock.OPEN) ? BlockPathTypes.DOOR_WOOD_CLOSED : (block instanceof DoorBlock && material == Material.ORE && !(Boolean) iblockdata.getValue(DoorBlock.OPEN) ? BlockPathTypes.DOOR_IRON_CLOSED : (block instanceof DoorBlock && (Boolean) iblockdata.getValue(DoorBlock.OPEN) ? BlockPathTypes.DOOR_OPEN : (block instanceof BaseRailBlock ? BlockPathTypes.RAIL : (block instanceof LeavesBlock ? BlockPathTypes.LEAVES : (!block.is((Tag) BlockTags.FENCES) && !block.is((Tag) BlockTags.WALLS) && (!(block instanceof FenceGateBlock) || (Boolean) iblockdata.getValue(FenceGateBlock.OPEN)) ? (!iblockdata.isPathfindable(iblockaccess, blockposition, PathComputationType.LAND) ? BlockPathTypes.BLOCKED : BlockPathTypes.OPEN) : BlockPathTypes.FENCE)))))))); - } diff --git a/Remapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch b/Remapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch deleted file mode 100644 index 535e3ffd30..0000000000 --- a/Remapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 20:32:25 -0500 -Subject: [PATCH] Fix item locations dropped from campfires - -Fixes #4259 by not flooring the blockposition among other weirdness - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -index 0c90b1b13611843ba4402c8ccf0b15781b85e773..6c38361d744eae763b6c131ad314485f5a88fcfc 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -@@ -14,6 +14,7 @@ import net.minecraft.world.Clearable; - import net.minecraft.world.ContainerHelper; - import net.minecraft.world.Containers; - import net.minecraft.world.SimpleContainer; -+import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.crafting.CampfireCookingRecipe; - import net.minecraft.world.item.crafting.RecipeType; -@@ -91,7 +92,11 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable, Ticka - result = blockCookEvent.getResult(); - itemstack1 = CraftItemStack.asNMSCopy(result); - // CraftBukkit end -- Containers.dropItemStack(this.level, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack1); -+ // Paper start -+ ItemEntity droppedItem = new ItemEntity(this.level, blockposition.getX() + 0.5D, blockposition.getY() + 0.5D, blockposition.getZ() + 0.5D, itemstack1.split(this.level.random.nextInt(21) + 10)); -+ droppedItem.setDeltaMovement(this.level.random.nextGaussian() * 0.05D, this.level.random.nextGaussian() * 0.05D + 0.2D, this.level.random.nextGaussian() * 0.05D); -+ this.level.addFreshEntity(droppedItem); -+ // Paper end - this.items.set(i, ItemStack.EMPTY); - this.markUpdated(); - } diff --git a/Remapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch b/Remapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch deleted file mode 100644 index 92e087e79f..0000000000 --- a/Remapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Tue, 14 Apr 2020 12:05:22 +0200 -Subject: [PATCH] Player elytra boost API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 7aae63d22167dc1b3ec7e8bc8672855c2038007e..94240b70e245bdc3dda60420f5787f8d5dcc1958 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -67,6 +67,7 @@ import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.ai.attributes.AttributeInstance; - import net.minecraft.world.entity.ai.attributes.AttributeMap; - import net.minecraft.world.entity.ai.attributes.Attributes; -+import net.minecraft.world.entity.projectile.FireworkRocketEntity; - import net.minecraft.world.inventory.AbstractContainerMenu; - import net.minecraft.world.item.enchantment.EnchantmentHelper; - import net.minecraft.world.item.enchantment.Enchantments; -@@ -2281,6 +2282,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - throw new RuntimeException("Unknown settings type"); - } -+ -+ @Override -+ public org.bukkit.entity.Firework boostElytra(ItemStack firework) { -+ Validate.isTrue(isGliding(), "Player must be gliding"); -+ Validate.isTrue(firework != null, "firework == null"); -+ Validate.isTrue(firework.getType() == Material.FIREWORK_ROCKET, "Firework must be Material.FIREWORK_ROCKET"); -+ -+ net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(firework); -+ net.minecraft.world.level.Level world = ((CraftWorld) getWorld()).getHandle(); -+ FireworkRocketEntity entity = new FireworkRocketEntity(world, item, getHandle()); -+ return world.addFreshEntity(entity) -+ ? (org.bukkit.entity.Firework) entity.getBukkitEntity() -+ : null; -+ } - // Paper end - - // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch b/Remapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch deleted file mode 100644 index de814154fd..0000000000 --- a/Remapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: giacomo <32515303+giacomozama@users.noreply.github.com> -Date: Sat, 10 Oct 2020 12:15:33 +0200 -Subject: [PATCH] Fixed TileEntityBell memory leak - -TileEntityBell has a list of entities (entitiesAtRing) that was not being cleared at the right time, causing leaks whenever a bell would be rung near a crowd of entities. - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java -index aa45a142aa11acc9fd08b4877891741f3cbd936d..3f9179a7678091875161a34d13b6ec0e78025c4c 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java -@@ -27,8 +27,8 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity - public int ticks; - public boolean shaking; - public Direction clickDirection; -- private List nearbyEntities; -- private boolean resonating; -+ private List nearbyEntities; private List getEntitiesAtRing() { return this.nearbyEntities; } // Paper - OBFHELPER -+ private boolean resonating; private boolean getShouldReveal() { return this.resonating; } // Paper - OBFHELPER - private int resonationTicks; - - public BellBlockEntity() { -@@ -57,6 +57,11 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity - - if (this.ticks >= 50) { - this.shaking = false; -+ // Paper start -+ if (!this.getShouldReveal()) { -+ this.getEntitiesAtRing().clear(); -+ } -+ // Paper end - this.ticks = 0; - } - -@@ -71,6 +76,7 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity - } else { - this.makeRaidersGlow(this.level); - this.showBellParticles(this.level); -+ this.getEntitiesAtRing().clear(); // Paper - this.resonating = false; - } - } -@@ -111,11 +117,12 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity - LivingEntity entityliving = (LivingEntity) iterator.next(); - - if (entityliving.isAlive() && !entityliving.removed && blockposition.closerThan((Position) entityliving.position(), 32.0D)) { -- entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, (Object) this.level.getGameTime()); -+ entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.level.getGameTime()); // Paper - decompile fix - } - } - } - -+ this.getEntitiesAtRing().removeIf(e -> !e.isAlive()); // Paper - } - - private boolean areRaidersNearby() { diff --git a/Remapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/Remapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch deleted file mode 100644 index 6072b2edd8..0000000000 --- a/Remapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Toon Schoenmakers -Date: Fri, 23 Oct 2020 15:01:44 +0200 -Subject: [PATCH] Avoid error bubbling up when item stack is empty in fishing - loot - -This can realistically only happen if there's custom loot active on fishing -which can return 0 items. This would disconnect the player who's fishing. - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -index 7bff012f3cd4458673ee02e5f5f830fc0ef983a3..ef71cca9922ed134ec82fb2982d375bf16f47b17 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -@@ -481,9 +481,15 @@ public class FishingHook extends Projectile { - - while (iterator.hasNext()) { - ItemStack itemstack1 = (ItemStack) iterator.next(); -- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), itemstack1); -+ // Paper start, new EntityItem would throw if for whatever reason (mostly shitty datapacks) the itemstack1 turns out to be empty -+ // if the item stack is empty we instead just have our entityitem as null -+ ItemEntity entityitem = null; -+ if (!itemstack1.isEmpty()) { -+ entityitem = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), itemstack1); -+ } -+ // Paper end - // CraftBukkit start -- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); -+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null - playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); - this.level.getCraftServer().getPluginManager().callEvent(playerFishEvent); - -@@ -496,8 +502,12 @@ public class FishingHook extends Projectile { - double d2 = entityhuman.getZ() - this.getZ(); - double d3 = 0.1D; - -- entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); -- this.level.addFreshEntity(entityitem); -+ // Paper start, entity item can be null, so we need to check against this -+ if (entityitem != null) { -+ entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); -+ this.level.addFreshEntity(entityitem); -+ } -+ // Paper end - // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() - if (playerFishEvent.getExpToDrop() > 0) { - entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper diff --git a/Remapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch b/Remapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch deleted file mode 100644 index b581372702..0000000000 --- a/Remapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: oxygencraft <21054297+oxygencraft@users.noreply.github.com> -Date: Sun, 25 Oct 2020 18:34:50 +1100 -Subject: [PATCH] Add getOfflinePlayerIfCached(String) - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e599be15af17e5e45d2b694c30140cc4a787a7f5..046fbc646d2818bb2c7e08ff22093523e8246523 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1612,6 +1612,28 @@ public final class CraftServer implements Server { - return result; - } - -+ // Paper start -+ @Override -+ @Nullable -+ public OfflinePlayer getOfflinePlayerIfCached(String name) { -+ Validate.notNull(name, "Name cannot be null"); -+ Validate.notEmpty(name, "Name cannot be empty"); -+ -+ OfflinePlayer result = getPlayerExact(name); -+ if (result == null) { -+ GameProfile profile = console.getProfileCache().getProfileIfCached(name); -+ -+ if (profile != null) { -+ result = getOfflinePlayer(profile); -+ } -+ } else { -+ offlinePlayers.remove(result.getUniqueId()); -+ } -+ -+ return result; -+ } -+ // Paper end -+ - @Override - public OfflinePlayer getOfflinePlayer(UUID id) { - Validate.notNull(id, "UUID cannot be null"); diff --git a/Remapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch b/Remapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch deleted file mode 100644 index e20018337f..0000000000 --- a/Remapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Mon, 9 Nov 2020 20:44:51 +0100 -Subject: [PATCH] Add ignore discounts API - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index e9912551e6a19d6ad3b20fad1b716577b9d28f99..415fa3591add1f1ab22dd5866e110dbfccd0ec93 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/Villager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -459,6 +459,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - - while (iterator.hasNext()) { - MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); -+ if (merchantrecipe.ignoreDiscounts) continue; // Paper - - // CraftBukkit start - int bonus = -Mth.floor((float) i * merchantrecipe.getPriceMultiplier()); -@@ -478,6 +479,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - - while (iterator1.hasNext()) { - MerchantOffer merchantrecipe1 = (MerchantOffer) iterator1.next(); -+ if (merchantrecipe1.ignoreDiscounts) continue; // Paper - double d0 = 0.3D + 0.0625D * (double) j; - int k = (int) Math.floor(d0 * (double) merchantrecipe1.getBaseCostA().getCount()); - -diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java -index fa74813e0fe76612023830b2fc41d41aa0b4f10e..25a0f180967911d5916eb71334a94baec84eafbf 100644 ---- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java -+++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java -@@ -19,6 +19,7 @@ public class MerchantOffer { - private int demand; - public float priceMultiplier; - public int xp; -+ public boolean ignoreDiscounts; // Paper - // CraftBukkit start - private CraftMerchantRecipe bukkitHandle; - -@@ -27,7 +28,12 @@ public class MerchantOffer { - } - - public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { -- this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier); -+ // Paper start - add ignoreDiscounts param -+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, false, bukkit); -+ } -+ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) { -+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, ignoreDiscounts); -+ // Paper end - this.bukkitHandle = bukkit; - } - // CraftBukkit end -@@ -59,6 +65,7 @@ public class MerchantOffer { - - this.specialPriceDiff = nbttagcompound.getInt("specialPrice"); - this.demand = nbttagcompound.getInt("demand"); -+ this.ignoreDiscounts = nbttagcompound.getBoolean("Paper.IgnoreDiscounts"); // Paper - } - - public MerchantOffer(ItemStack buyItem, ItemStack sellItem, int maxUses, int rewardedExp, float priceMultiplier) { -@@ -70,10 +77,19 @@ public class MerchantOffer { - } - - public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int rewardedExp, float priceMultiplier) { -- this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, rewardedExp, priceMultiplier, 0); -+ // Paper start - add ignoreDiscounts param -+ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, rewardedExp, priceMultiplier, false); -+ } -+ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, boolean ignoreDiscounts) { -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, 0, ignoreDiscounts); - } - - public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l) { -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, l, false); -+ } -+ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l, boolean ignoreDiscounts) { -+ this.ignoreDiscounts = ignoreDiscounts; -+ // Paper end - this.rewardExp = true; - this.xp = 1; - this.baseCostA = itemstack; -@@ -189,6 +205,7 @@ public class MerchantOffer { - nbttagcompound.putFloat("priceMultiplier", this.priceMultiplier); - nbttagcompound.putInt("specialPrice", this.specialPriceDiff); - nbttagcompound.putInt("demand", this.demand); -+ nbttagcompound.putBoolean("Paper.IgnoreDiscounts", this.ignoreDiscounts); // Paper - return nbttagcompound; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -index 212f9c7f3e73ffedf27b94abeac957b7d866a086..a6c8588f10c4c109833aea6a8b02c9048b6d9ea4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -@@ -17,7 +17,12 @@ public class CraftMerchantRecipe extends MerchantRecipe { - } - - public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier) { -- super(result, uses, maxUses, experienceReward, experience, priceMultiplier); -+ // Paper start - add ignoreDiscounts param -+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, false); -+ } -+ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, boolean ignoreDiscounts) { -+ super(result, uses, maxUses, experienceReward, experience, priceMultiplier, ignoreDiscounts); -+ // Paper end - this.handle = new net.minecraft.world.item.trading.MerchantOffer( - net.minecraft.world.item.ItemStack.EMPTY, - net.minecraft.world.item.ItemStack.EMPTY, -@@ -26,6 +31,7 @@ public class CraftMerchantRecipe extends MerchantRecipe { - maxUses, - experience, - priceMultiplier, -+ ignoreDiscounts, // Paper - add ignoreDiscounts param - this - ); - this.setExperienceReward(experienceReward); -@@ -81,6 +87,18 @@ public class CraftMerchantRecipe extends MerchantRecipe { - handle.priceMultiplier = priceMultiplier; - } - -+ // Paper start -+ @Override -+ public boolean shouldIgnoreDiscounts() { -+ return this.handle.ignoreDiscounts; -+ } -+ -+ @Override -+ public void setIgnoreDiscounts(boolean ignoreDiscounts) { -+ this.handle.ignoreDiscounts = ignoreDiscounts; -+ } -+ // Paper end -+ - public net.minecraft.world.item.trading.MerchantOffer toMinecraft() { - List ingredients = getIngredients(); - Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients"); -@@ -95,7 +113,7 @@ public class CraftMerchantRecipe extends MerchantRecipe { - if (recipe instanceof CraftMerchantRecipe) { - return (CraftMerchantRecipe) recipe; - } else { -- CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier()); -+ CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.shouldIgnoreDiscounts()); // Paper - shouldIgnoreDiscounts - craft.setIngredients(recipe.getIngredients()); - - return craft; diff --git a/Remapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch b/Remapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch deleted file mode 100644 index 184345a27e..0000000000 --- a/Remapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 30 Sep 2020 22:49:14 +0200 -Subject: [PATCH] Toggle for removing existing dragon - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 02bb85364560784adea47c877c13291c3d016b86..424754a0183b071d20c86f0420cec784a8992e2b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -683,4 +683,12 @@ public class PaperWorldConfig { - log("Using vanilla redstone algorithm."); - } - } -+ -+ public boolean shouldRemoveDragon = false; -+ private void shouldRemoveDragon() { -+ shouldRemoveDragon = getBoolean("should-remove-dragon", shouldRemoveDragon); -+ if (shouldRemoveDragon) { -+ log("The Ender Dragon will be removed if she already exists without a portal."); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 590df3b93b897613cad74f9920aec62b33a2f7f7..84447e9845edad2d228b94184b35b4afb453a14b 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -210,7 +210,7 @@ public class EndDragonFight { - this.dragonUUID = entityenderdragon.getUUID(); - EndDragonFight.LOGGER.info("Found that there's a dragon still alive ({})", entityenderdragon); - this.dragonKilled = false; -- if (!flag) { -+ if (!flag && this.level.paperConfig.shouldRemoveDragon) { // Paper - EndDragonFight.LOGGER.info("But we didn't have a portal, let's remove it."); - entityenderdragon.remove(); - this.dragonUUID = null; diff --git a/Remapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch b/Remapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch deleted file mode 100644 index 2affffb90a..0000000000 --- a/Remapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Sat, 31 Oct 2020 11:49:01 -0700 -Subject: [PATCH] Fix client lag on advancement loading - -When new advancements are added via the UnsafeValues#loadAdvancement -API, it triggers a full datapack reload when this is not necessary. The -advancement is already loaded directly into the advancement registry, -and the point of saving the advancement to the Bukkit datapack seems to -be for persistence. By removing the call to reload datapacks when an -advancement is loaded, the client no longer completely freezes up when -adding a new advancement. -To ensure the client still receives the updated advancement data, we -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/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java -index acb41cc3965154c5b515cd8e808bf2cf5dc850e4..b8d3f2c59199e245e2035d6205dd1a042aa93f77 100644 ---- a/src/main/java/net/minecraft/server/PlayerAdvancements.java -+++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java -@@ -97,6 +97,7 @@ public class PlayerAdvancements { - - } - -+ public final void reload(ServerAdvancementManager advancementDataWorld) { this.reload(advancementDataWorld); } // Paper - OBFHELPER - public void reload(ServerAdvancementManager advancementLoader) { - this.stopListening(); - this.advancements.clear(); -@@ -393,6 +394,7 @@ public class PlayerAdvancements { - - } - -+ public final void sendUpdateIfNeeded(ServerPlayer entityPlayer) { this.flushDirty(entityPlayer); } // Paper - OBFHELPER - public void flushDirty(ServerPlayer player) { - if (this.isFirstPacket || !this.visibilityChanged.isEmpty() || !this.progressChanged.isEmpty()) { - Map map = Maps.newHashMap(); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 9a16882deee21faf78ea46e08b2f2ad3fbb6021b..ac94fd569bd4c79e30adef148e09e395ba8c1812 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -307,7 +307,13 @@ public final class CraftMagicNumbers implements UnsafeValues { - Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex); - } - -- MinecraftServer.getServer().getPlayerList().reloadResources(); -+ // Paper start -+ //MinecraftServer.getServer().getPlayerList().reload(); -+ MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> { -+ player.getAdvancements().reload(MinecraftServer.getServer().getAdvancements()); -+ player.getAdvancements().sendUpdateIfNeeded(player); -+ }); -+ // Paper end - - return bukkit; - } diff --git a/Remapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch b/Remapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch deleted file mode 100644 index 0c17d7553d..0000000000 --- a/Remapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Smith -Date: Sat, 7 Nov 2020 01:20:33 +0000 -Subject: [PATCH] Item no age & no player pickup - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -index 9a410f557988d737c3b930a79ef2ccb2b5c8b406..aff17bb3bd22de492b9736d27b7f3e4bdb37134c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -@@ -10,6 +10,12 @@ import org.bukkit.entity.Item; - import org.bukkit.inventory.ItemStack; - - public class CraftItem extends CraftEntity implements Item { -+ -+ // Paper start -+ private final static int NO_AGE_TIME = (int) Short.MIN_VALUE; -+ private final static int NO_PICKUP_TIME = (int) Short.MAX_VALUE; -+ // Paper end -+ - private final ItemEntity item; - - public CraftItem(CraftServer server, Entity entity, ItemEntity item) { -@@ -57,6 +63,26 @@ public class CraftItem extends CraftEntity implements Item { - public void setCanMobPickup(boolean canMobPickup) { - item.canMobPickup = canMobPickup; - } -+ -+ @Override -+ public boolean canPlayerPickup() { -+ return item.pickupDelay != NO_PICKUP_TIME; -+ } -+ -+ @Override -+ public void setCanPlayerPickup(boolean canPlayerPickup) { -+ item.pickupDelay = canPlayerPickup ? 0 : NO_PICKUP_TIME; -+ } -+ -+ @Override -+ public boolean willAge() { -+ return item.age != NO_AGE_TIME; -+ } -+ -+ @Override -+ public void setWillAge(boolean willAge) { -+ item.age = willAge ? 0 : NO_AGE_TIME; -+ } - // Paper End - - @Override diff --git a/Remapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch b/Remapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch deleted file mode 100644 index 78d729cb3e..0000000000 --- a/Remapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 12:39:08 -0600 -Subject: [PATCH] Beacon API - custom effect ranges - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -index 5f75c6d653a31f65fcf9c0e280d796e15d059c00..fed29e5707e2a7f64159d284c52647dd91e1948e 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -@@ -71,6 +71,26 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - return (hasSecondaryEffect()) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, getLevelCb(), getAmplification(), true, true)) : null; - } - // CraftBukkit end -+ // Paper start - add field/methods for custom range -+ private final String PAPER_RANGE_TAG = "Paper.Range"; -+ private double effectRange = -1; -+ -+ public double getEffectRange() { -+ if (this.effectRange < 0) { -+ return this.levels * 10 + 10; -+ } else { -+ return effectRange; -+ } -+ } -+ -+ public void setEffectRange(double range) { -+ this.effectRange = range; -+ } -+ -+ public void resetEffectRange() { -+ this.effectRange = -1; -+ } -+ // Paper end - - public BeaconBlockEntity() { - super(BlockEntityType.BEACON); -@@ -261,7 +281,8 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - - public List getHumansInRange() { - { -- double d0 = (double) (this.levels * 10 + 10); -+ // Paper - custom beacon ranges -+ double d0 = this.getEffectRange(); - - AABB axisalignedbb = (new AABB(this.worldPosition)).inflate(d0).expandTowards(0.0D, (double) this.level.getMaxBuildHeight(), 0.0D); - List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.player.Player.class, axisalignedbb); -@@ -361,6 +382,9 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - this.secondaryPower = MobEffect.byId(tag.getInt("Secondary")); - this.levels = tag.getInt("Levels"); // SPIGOT-5053, use where available - // CraftBukkit end -+ // Paper -+ this.effectRange = tag.contains(PAPER_RANGE_TAG, 6) ? tag.getDouble(PAPER_RANGE_TAG) : -1; -+ - if (tag.contains("CustomName", 8)) { - this.name = Component.Serializer.fromJson(tag.getString("CustomName")); - } -@@ -377,6 +401,8 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - if (this.name != null) { - tag.putString("CustomName", Component.Serializer.toJson(this.name)); - } -+ // Paper -+ tag.putDouble(PAPER_RANGE_TAG, this.effectRange); - - this.lockKey.addToTag(tag); - return tag; -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -index 940fef58f14e06213c7f305f67dcb8918976c03d..2a10a9352fdb52f5cb27eae2b6d3baa9ff95e486 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -@@ -108,4 +108,19 @@ public class CraftBeacon extends CraftBlockEntityState implem - public void setLock(String key) { - this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key); - } -+ -+ @Override -+ public double getEffectRange() { -+ return this.getSnapshot().getEffectRange(); -+ } -+ -+ @Override -+ public void setEffectRange(double range) { -+ this.getSnapshot().setEffectRange(range); -+ } -+ -+ @Override -+ public void resetEffectRange() { -+ this.getSnapshot().resetEffectRange(); -+ } - } diff --git a/Remapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch b/Remapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch deleted file mode 100644 index 988b77b058..0000000000 --- a/Remapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 14 Nov 2020 16:19:52 +0100 -Subject: [PATCH] Add API for quit reason - - -diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 6f7cbce5a049d87d4a0ed7cc4517cb4e8694efb5..3ba9c38fc44a8edba9b504112a383249052a0035 100644 ---- a/src/main/java/net/minecraft/network/Connection.java -+++ b/src/main/java/net/minecraft/network/Connection.java -@@ -137,12 +137,15 @@ public class Connection extends SimpleChannelInboundHandler> { - - this.handlingFault = true; - if (this.channel.isOpen()) { -+ ServerPlayer player = this.getPlayer(); // Paper - if (throwable instanceof TimeoutException) { - Connection.LOGGER.debug("Timeout", throwable); -+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper - this.disconnect(new TranslatableComponent("disconnect.timeout")); - } else { - TranslatableComponent chatmessage = new TranslatableComponent("disconnect.genericReason", new Object[]{"Internal Exception: " + throwable}); - -+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper - if (flag) { - Connection.LOGGER.debug("Failed to sent packet", throwable); - this.send(new ClientboundDisconnectPacket(chatmessage), (future) -> { -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index bd4d4ace35e966e819aa461d3962fe06ff402be7..1b5f24920c46cd238a79f5a2857d26fa1c12b983 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -258,6 +258,7 @@ public class ServerPlayer extends Player implements ContainerListener { - double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks - - boolean needsChunkCenterUpdate; // Paper - no-tick view distance -+ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event - - public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { - super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 3a114bec14fcc6c1e1045e2b99178a6adb25f387..ccfe5a1ec1e9895f7462b7c676fee80903502a88 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -447,6 +447,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - final Component ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure - // CraftBukkit end - -+ this.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper - this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> { - this.connection.disconnect(ichatbasecomponent); - }); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7e44c911f4abc5c7d0e89513bf2cfc3516f13492..cda21726f4929b03191e912550d4e4b1232b3b0b 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -586,7 +586,7 @@ public abstract class PlayerList { - entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - } - -- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); -+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName())), entityplayer.quitReason); // Paper - quit reason - if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - diff --git a/Remapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch b/Remapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch deleted file mode 100644 index 40529ba82f..0000000000 --- a/Remapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Mon, 13 Jan 2020 15:40:32 +0100 -Subject: [PATCH] Seed based feature search - -This tries to work around the issue where the server will load -surrounding chunks up to a radius of 100 chunks in order to search for -features e.g. when running the /locate command or for treasure maps -(issue #2312). -This is done by backporting Mojang's change in 1.17 which makes it so -that the biome (generated by the seed) is checked first if the feature -can be generated before actually to load the chunk. - -Additionally to that the center location of the target chunk is simply -returned if the chunk is not loaded to avoid the sync chunk load. -As this can lead to less precise locations a toggle is provided to -enable the sync loading of the target chunk again. - -The main downside of this is that it breaks once the seed or generator -changes but this should usually not happen. A config option to disable -this completely is added though in case that should ever be necessary. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 424754a0183b071d20c86f0420cec784a8992e2b..97870622e41cca36d9c7493bfad796f35f3831f4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -337,6 +337,14 @@ public class PaperWorldConfig { - } - } - -+ public boolean seedBasedFeatureSearch = true; -+ public boolean seedBasedFeatureSearchLoadsChunks = false; -+ private void seedBasedFeatureSearch() { -+ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch); -+ seedBasedFeatureSearchLoadsChunks = getBoolean("seed-based-feature-search-loads-chunks", seedBasedFeatureSearchLoadsChunks); -+ log("Feature search is based on seed: " + seedBasedFeatureSearch + ", loads chunks:" + seedBasedFeatureSearchLoadsChunks); -+ } -+ - public int maxCollisionsPerEntity; - private void maxEntityCollision() { - maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); -diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java -index 4a5f318adf5bc2ca1c3fab5d173a99cddd77ab85..f61a3eda40328922b95f166be4dc604500e000be 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkPos.java -+++ b/src/main/java/net/minecraft/world/level/ChunkPos.java -@@ -68,10 +68,12 @@ public class ChunkPos { - } - } - -+ public int getBlockX() { return getMinBlockX(); } // Paper - OBFHELPER - public int getMinBlockX() { - return this.x << 4; - } - -+ public int getBlockZ() { return getMinBlockZ(); } // Paper - OBFHELPER - public int getMinBlockZ() { - return this.z << 4; - } -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 2ad8a4558aa812885adebee8c05dab45f2bf5f90..066d5f7ee93351bff67c0d39ee9d940ac51515d8 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1511,8 +1511,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return this.profiler; - } - -- @Override -- public BiomeManager getBiomeManager() { -+ public BiomeManager getBiomeManager() { return getBiomeManager(); } // Paper - OBFHELPER -+ @Override public BiomeManager getBiomeManager() { - return this.biomeManager; - } - -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -index d22ac114440d807a6cf5f286961bc63935fa7823..3a1909c0b198d89539f4351d70a39d16cfd84987 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -@@ -23,6 +23,7 @@ public class BiomeManager { - return new BiomeManager(source, this.biomeZoomSeed, this.zoomer); - } - -+ public Biome getBiome(BlockPos blockposition) { return getBiome(blockposition); } // Paper - OBFHELPER - public Biome getBiome(BlockPos pos) { - return this.zoomer.getBiome(this.biomeZoomSeed, pos.getX(), pos.getY(), pos.getZ(), this.noiseBiomeSource); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -index 0624b8270bc28c83c5479cd51fa4633ed5c36f44..6b24590a1ac460a7fd4bbc2c70d4a4981378e79c 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -@@ -176,7 +176,24 @@ public abstract class StructureFeature { - int j2 = i1 + k * l1; - ChunkPos chunkcoordintpair = this.getPotentialFeatureChunk(config, worldSeed, seededrandom, i2, j2); - if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper -- ChunkAccess ichunkaccess = world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); -+ // Paper start - seed based feature search -+ ChunkAccess ichunkaccess = null; -+ if (structureAccessor.getWorld().paperConfig.seedBasedFeatureSearch) { -+ Biome biomeBase = structureAccessor.getWorld().getBiomeManager().getBiome(new BlockPos(chunkcoordintpair.getBlockX() + 9, 0, chunkcoordintpair.getBlockZ() + 9)); -+ if (!biomeBase.getGenerationSettings().isValidStart(this)) { -+ continue; -+ } -+ if (!structureAccessor.getWorld().paperConfig.seedBasedFeatureSearchLoadsChunks) { -+ ichunkaccess = structureAccessor.getWorld().getChunkIfLoaded(chunkcoordintpair.x, chunkcoordintpair.z); -+ if (ichunkaccess == null) { -+ return chunkcoordintpair.asPosition().add(8, searchStartPos.getY(), 8); -+ } -+ } -+ } -+ if (ichunkaccess == null) { -+ ichunkaccess = world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); -+ } -+ // Paper end - StructureStart structurestart = structureAccessor.getStartForFeature(SectionPos.of(ichunkaccess.getPos(), 0), this, ichunkaccess); - - if (structurestart != null && structurestart.e()) { diff --git a/Remapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch b/Remapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch deleted file mode 100644 index 2dbaff374a..0000000000 --- a/Remapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Thu, 20 Aug 2020 11:20:12 -0700 -Subject: [PATCH] Add Wandering Trader spawn rate config options - -Adds config options for modifying the spawn rates of Wandering Traders. -These values are all easy to understand and configure after a quick read of this -page on the Minecraft wiki: https://minecraft.gamepedia.com/Wandering_Trader#Spawning -Usages of the vanilla WanderingTraderSpawnDelay and WanderingTraderSpawnChance values -in IWorldServerData are removed as they were only used in certain places, with hardcoded -values used in other places. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 97870622e41cca36d9c7493bfad796f35f3831f4..5a451cc855de57f79a57670ba38e3af2343cb510 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -699,4 +699,17 @@ public class PaperWorldConfig { - log("The Ender Dragon will be removed if she already exists without a portal."); - } - } -+ -+ public int wanderingTraderSpawnMinuteTicks = 1200; -+ public int wanderingTraderSpawnDayTicks = 24000; -+ public int wanderingTraderSpawnChanceFailureIncrement = 25; -+ public int wanderingTraderSpawnChanceMin = 25; -+ public int wanderingTraderSpawnChanceMax = 75; -+ private void wanderingTraderSettings() { -+ wanderingTraderSpawnMinuteTicks = getInt("wandering-trader.spawn-minute-length", wanderingTraderSpawnMinuteTicks); -+ wanderingTraderSpawnDayTicks = getInt("wandering-trader.spawn-day-length", wanderingTraderSpawnDayTicks); -+ wanderingTraderSpawnChanceFailureIncrement = getInt("wandering-trader.spawn-chance-failure-increment", wanderingTraderSpawnChanceFailureIncrement); -+ wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); -+ wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -index c297051bc48ff20a6764496cbf11eef601761d13..9074d57e1576db2da3e4c76add4f7e07e5567879 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -@@ -30,49 +30,59 @@ public class WanderingTraderSpawner implements CustomSpawner { - - private final Random random = new Random(); - private final ServerLevelData serverLevelData; -- private int tickDelay; -- private int spawnDelay; -- private int spawnChance; -+ private int tickDelay; public final int getMinuteTimer() { return this.tickDelay; } public final void setMinuteTimer(int x) { this.tickDelay = x; } // Paper - OBFHELPER -+ private int spawnDelay; public final int getDayTimer() { return this.spawnDelay; } public final void setDayTimer(int x) { this.spawnDelay = x; } // Paper - OBFHELPER -+ private int spawnChance; public final int getSpawnChance() { return this.spawnChance; } public final void setSpawnChance(int x) { this.spawnChance = x; } // Paper - OBFHELPER - - public WanderingTraderSpawner(ServerLevelData properties) { - this.serverLevelData = properties; -- this.tickDelay = 1200; -- this.spawnDelay = properties.getWanderingTraderSpawnDelay(); -- this.spawnChance = properties.getWanderingTraderSpawnChance(); -- if (this.spawnDelay == 0 && this.spawnChance == 0) { -- this.spawnDelay = 24000; -- properties.setWanderingTraderSpawnDelay(this.spawnDelay); -- this.spawnChance = 25; -- properties.setWanderingTraderSpawnChance(this.spawnChance); -- } -+ // Paper start -+ this.setMinuteTimer(Integer.MIN_VALUE); -+ //this.d = iworlddataserver.v(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value -+ //this.e = iworlddataserver.w(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value -+ //if (this.d == 0 && this.e == 0) { -+ // this.d = 24000; -+ // iworlddataserver.g(this.d); -+ // this.e = 25; -+ // iworlddataserver.h(this.e); -+ //} -+ // Paper end - - } - - @Override - public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { -+ // Paper start -+ if (this.getMinuteTimer() == Integer.MIN_VALUE) { -+ this.setMinuteTimer(world.paperConfig.wanderingTraderSpawnMinuteTicks); -+ this.setDayTimer(world.paperConfig.wanderingTraderSpawnDayTicks); -+ this.setSpawnChance(world.paperConfig.wanderingTraderSpawnChanceMin); -+ } - if (!world.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) { - return 0; -- } else if (--this.tickDelay > 0) { -+ } else if (this.getMinuteTimer() - 1 > 0) { -+ this.setMinuteTimer(this.getMinuteTimer() - 1); - return 0; - } else { -- this.tickDelay = 1200; -- this.spawnDelay -= 1200; -- this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay); -- if (this.spawnDelay > 0) { -+ this.setMinuteTimer(world.paperConfig.wanderingTraderSpawnMinuteTicks); -+ this.setDayTimer(getDayTimer() - world.paperConfig.wanderingTraderSpawnMinuteTicks); -+ //this.b.g(this.d); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways -+ if (this.getDayTimer() > 0) { - return 0; - } else { -- this.spawnDelay = 24000; -+ this.setDayTimer(world.paperConfig.wanderingTraderSpawnDayTicks); - if (!world.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { - return 0; - } else { -- int i = this.spawnChance; -+ int i = this.getSpawnChance(); - -- this.spawnChance = Mth.clamp(this.spawnChance + 25, 25, 75); -- this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); -+ this.setSpawnChance(Mth.clamp(i + world.paperConfig.wanderingTraderSpawnChanceFailureIncrement, world.paperConfig.wanderingTraderSpawnChanceMin, world.paperConfig.wanderingTraderSpawnChanceMax)); -+ //this.b.h(this.e); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways - if (this.random.nextInt(100) > i) { - return 0; - } else if (this.spawn(world)) { -- this.spawnChance = 25; -+ this.setSpawnChance(world.paperConfig.wanderingTraderSpawnChanceMin); -+ // Paper end - return 1; - } else { - return 0; diff --git a/Remapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch b/Remapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch deleted file mode 100644 index 22a13c79b6..0000000000 --- a/Remapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com> -Date: Tue, 3 Nov 2020 23:48:05 -0600 -Subject: [PATCH] Significantly improve performance of the end generation - -This patch implements a noise cache for the end which significantly reduces the computation time of generation. This results in about a 3x improvement. - -Original code by SuperCoder7979 and Gegy in Lithium, licensed under LGPL-3.0 (Source: https://github.com/jellysquid3/lithium-fabric) - -Co-authored-by: Gegy -Co-authored-by: Dylan Xaldin -Co-authored-by: pop4959 - -diff --git a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java -index 063369d3a64b4afc9cc6e1d20360900595e1a05f..f01d1b01ebc31f0967a73871f278aac9e414fb67 100644 ---- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java -+++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java -@@ -3,10 +3,12 @@ package net.minecraft.world.level.biome; - import com.google.common.collect.ImmutableList; - import com.mojang.serialization.Codec; - import com.mojang.serialization.codecs.RecordCodecBuilder; -+import it.unimi.dsi.fastutil.HashCommon; // Paper - import java.util.List; - import net.minecraft.core.Registry; - import net.minecraft.resources.RegistryLookupCodec; - import net.minecraft.util.Mth; -+import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.levelgen.WorldgenRandom; - import net.minecraft.world.level.levelgen.synth.SimplexNoise; - -@@ -27,6 +29,16 @@ public class TheEndBiomeSource extends BiomeSource { - private final Biome midlands; - private final Biome islands; - private final Biome barrens; -+ // Paper start -+ private static final class NoiseCache { -+ public long[] keys = new long[8192]; -+ public float[] values = new float[8192]; -+ public NoiseCache() { -+ java.util.Arrays.fill(keys, Long.MIN_VALUE); -+ } -+ } -+ private static final ThreadLocal> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new); -+ // Paper end - - public TheEndBiomeSource(Registry biomeRegistry, long seed) { - this(biomeRegistry, seed, (Biome) biomeRegistry.lifecycle(Biomes.THE_END), (Biome) biomeRegistry.lifecycle(Biomes.END_HIGHLANDS), (Biome) biomeRegistry.lifecycle(Biomes.END_MIDLANDS), (Biome) biomeRegistry.lifecycle(Biomes.SMALL_END_ISLANDS), (Biome) biomeRegistry.lifecycle(Biomes.END_BARRENS)); -@@ -81,13 +93,27 @@ public class TheEndBiomeSource extends BiomeSource { - - f = Mth.clamp(f, -100.0F, 80.0F); - -+ NoiseCache cache = noiseCache.get().computeIfAbsent(noisegenerator3handler, m -> new NoiseCache()); // Paper - for (int k1 = -12; k1 <= 12; ++k1) { - for (int l1 = -12; l1 <= 12; ++l1) { - long i2 = (long) (k + k1); - long j2 = (long) (l + l1); - -- if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.getValue((double) i2, (double) j2) < -0.8999999761581421D) { -- float f1 = (Mth.abs((float) i2) * 3439.0F + Mth.abs((float) j2) * 147.0F) % 13.0F + 9.0F; -+ // Paper start - Significantly improve end generation performance by using a noise cache -+ long key = ChunkPos.asLong((int) i2, (int) j2); -+ int index = (int) HashCommon.mix(key) & 8191; -+ float f1 = Float.MIN_VALUE; -+ if (cache.keys[index] == key) { -+ f1 = cache.values[index]; -+ } else { -+ if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.getValue((double) i2, (double) j2) < -0.8999999761581421D) { -+ f1 = (Mth.abs((float) i2) * 3439.0F + Mth.abs((float) j2) * 147.0F) % 13.0F + 9.0F; -+ } -+ cache.keys[index] = key; -+ cache.values[index] = f1; -+ } -+ if (f1 != Float.MIN_VALUE) { -+ // Paper end - float f2 = (float) (i1 - k1 * 2); - float f3 = (float) (j1 - l1 * 2); - float f4 = 100.0F - Mth.sqrt(f2 * f2 + f3 * f3) * f1; diff --git a/Remapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch b/Remapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch deleted file mode 100644 index 0086ded8da..0000000000 --- a/Remapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Tue, 17 Nov 2020 19:13:09 +0200 -Subject: [PATCH] Expose world spawn angle - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index cda21726f4929b03191e912550d4e4b1232b3b0b..7e07fd0c8dec9f9cdeda65dfa0ccf42b4dde010e 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -890,7 +890,7 @@ public abstract class PlayerList { - if (location == null) { - worldserver1 = this.server.getLevel(Level.OVERWORLD); - blockposition = entityplayer1.getSpawnPoint(worldserver1); -- location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F)); -+ location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F), worldserver1.levelData.getSpawnAngle(), 0.0F); // Paper - use world spawn angle - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); -diff --git a/src/main/java/net/minecraft/world/level/storage/LevelData.java b/src/main/java/net/minecraft/world/level/storage/LevelData.java -index 12a2371b15588ae84824d7a2d36a6d4c37e77013..078cee770a77b77d9b4a777754599d7b0b31f54b 100644 ---- a/src/main/java/net/minecraft/world/level/storage/LevelData.java -+++ b/src/main/java/net/minecraft/world/level/storage/LevelData.java -@@ -12,6 +12,7 @@ public interface LevelData { - - int getZSpawn(); - -+ default float getSpawnAngle() { return getSpawnAngle(); } // Paper - OBFHELPER - float getSpawnAngle(); - - long getGameTime(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 28bf53bc9fca21f57cd4851adf508d833ecdd33b..aaf97c13babce3b0ffc639ef950d59d1eba1398a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -362,7 +362,7 @@ public class CraftWorld implements World { - @Override - public Location getSpawnLocation() { - BlockPos spawn = world.getSpawn(); -- return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); -+ return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ(), world.levelData.getSpawnAngle(), 0.0F); // Paper - expose world spawn angle - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch b/Remapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch deleted file mode 100644 index 53910619a5..0000000000 --- a/Remapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ineusia -Date: Mon, 26 Oct 2020 11:48:06 -0500 -Subject: [PATCH] Add Destroy Speed API - -Co-authored-by: Jake Potrebic - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 37eceaef1212e2ee13aa763a5ede24ec170e5391..9defb202761296a825d035e27ddc51e17a311647 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -766,5 +766,23 @@ public class CraftBlock implements Block { - public String getTranslationKey() { - return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); - } -+ -+ @Override -+ public float getDestroySpeed(ItemStack itemStack, boolean considerEnchants) { -+ net.minecraft.world.item.ItemStack nmsItemStack; -+ if (itemStack instanceof CraftItemStack) { -+ nmsItemStack = ((CraftItemStack) itemStack).getHandle(); -+ } else { -+ nmsItemStack = CraftItemStack.asNMSCopy(itemStack); -+ } -+ float speed = nmsItemStack.getItem().getDestroySpeed(nmsItemStack, this.getNMSBlock().defaultBlockState()); -+ if (speed > 1.0F && considerEnchants) { -+ int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.BLOCK_EFFICIENCY, nmsItemStack); -+ if (enchantLevel > 0) { -+ speed += enchantLevel * enchantLevel + 1; -+ } -+ } -+ return speed; -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/Remapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch deleted file mode 100644 index 95a480a03b..0000000000 --- a/Remapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Esophose -Date: Sat, 3 Oct 2020 18:57:47 -0600 -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 94240b70e245bdc3dda60420f5787f8d5dcc1958..40380fff222cc1f3340cf6a6c4afbe60aaa5d3a6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2008,7 +2008,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (data != null && !particle.getDataType().isInstance(data)) { - throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); - } -- ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.toNMS(particle, data), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); -+ ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.toNMS(particle, data), true, x, y, z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); // Paper - Fix x/y/z coordinate precision loss - getHandle().connection.send(packetplayoutworldparticles); - - } diff --git a/Remapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch b/Remapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch deleted file mode 100644 index 308d4591ab..0000000000 --- a/Remapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Anrza -Date: Wed, 15 Jul 2020 12:08:49 +0200 -Subject: [PATCH] Add LivingEntity#clearActiveItem - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index eb136af0f99f5d7520ceabb98cefd5a01122872c..170bb1124ee396a85dd64baed8110e39823ad849 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -773,6 +773,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().useItem.asBukkitMirror(); - } - -+ // Paper start -+ @Override -+ public void clearActiveItem() { -+ getHandle().stopUsingItem(); -+ } -+ // Paper end -+ - @Override - public int getItemUseRemainingTime() { - return getHandle().getItemUseRemainingTime(); diff --git a/Remapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch b/Remapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch deleted file mode 100644 index 4d8772cbb5..0000000000 --- a/Remapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Tue, 25 Aug 2020 13:48:33 +0200 -Subject: [PATCH] Add PlayerItemCooldownEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java -index 93161583c215e1832570b39e72f7e7cfb94a700c..1983cdcefed60795e8c88737ae3459d5821cdcfa 100644 ---- a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java -+++ b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java -@@ -1,16 +1,27 @@ - package net.minecraft.world.item; - -+import io.papermc.paper.event.player.PlayerItemCooldownEvent; // Paper - import net.minecraft.network.protocol.game.ClientboundCooldownPacket; - import net.minecraft.server.level.ServerPlayer; - - public class ServerItemCooldowns extends ItemCooldowns { - -- private final ServerPlayer player; -+ private final ServerPlayer player; public ServerPlayer getEntityPlayer() { return player; } // Paper - OBFHELPER - - public ServerItemCooldowns(ServerPlayer player) { - this.player = player; - } - -+ // Paper start -+ @Override -+ public void addCooldown(Item item, int duration) { -+ PlayerItemCooldownEvent event = new PlayerItemCooldownEvent(getEntityPlayer().getBukkitEntity(), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(item), duration); -+ if (event.callEvent()) { -+ super.addCooldown(item, event.getCooldown()); -+ } -+ } -+ // Paper end -+ - @Override - protected void onCooldownStarted(Item item, int duration) { - super.onCooldownStarted(item, duration); diff --git a/Remapped-Spigot-Server-Patches/0604-More-lightning-API.patch b/Remapped-Spigot-Server-Patches/0604-More-lightning-API.patch deleted file mode 100644 index 6c4c8bac10..0000000000 --- a/Remapped-Spigot-Server-Patches/0604-More-lightning-API.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Sun, 26 Jul 2020 14:44:09 +0200 -Subject: [PATCH] More lightning API - - -diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java -index 4b0dbeded2b8a475d32f518957909d3495a4b6fc..3fdef4511e21e453b89e42a8f41e587fe300ba6b 100644 ---- a/src/main/java/net/minecraft/world/entity/LightningBolt.java -+++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java -@@ -28,7 +28,7 @@ public class LightningBolt extends Entity { - - private int life; - public long seed; -- private int flashes; -+ private int flashes; public int getFlashCount() { return flashes; } public void setFlashCount(int flashes) { this.flashes = flashes; } // Paper - OBFHELPER - public boolean visualOnly; - @Nullable - private ServerPlayer cause; -@@ -46,6 +46,16 @@ public class LightningBolt extends Entity { - this.visualOnly = cosmetic; - } - -+ // Paper start -+ public int getLifeTicks() { -+ return life; -+ } -+ -+ public void setLifeTicks(int lifeTicks) { -+ this.life = lifeTicks; -+ } -+ // Paper end -+ - @Override - public SoundSource getSoundSource() { - return SoundSource.WEATHER; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -index 26506c22592b58b208487fb244985361d70988a8..c1593bb345b38deb4d8b28a73d8dc6246c17b873 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -@@ -45,4 +45,27 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike - return spigot; - } - // Spigot end -+ -+ // Paper start -+ @Override -+ public int getFlashCount() { -+ return getHandle().getFlashCount(); -+ } -+ -+ @Override -+ public void setFlashCount(int flashes) { -+ com.google.common.base.Preconditions.checkArgument(flashes >= 0, "Flashes has to be a positive number!"); -+ getHandle().setFlashCount(flashes); -+ } -+ -+ @Override -+ public int getLifeTicks() { -+ return getHandle().getLifeTicks(); -+ } -+ -+ @Override -+ public void setLifeTicks(int lifeTicks) { -+ getHandle().setLifeTicks(lifeTicks); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch b/Remapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch deleted file mode 100644 index c25768004e..0000000000 --- a/Remapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch +++ /dev/null @@ -1,179 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 23 Aug 2020 20:59:00 +0200 -Subject: [PATCH] Climbing should not bypass cramming gamerule - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5a451cc855de57f79a57670ba38e3af2343cb510..7d3207a9af8360ddad228281d6aa65e1a0d24157 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -712,4 +712,9 @@ public class PaperWorldConfig { - wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); - wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); - } -+ -+ public boolean fixClimbingBypassingCrammingRule = false; -+ private void fixClimbingBypassingCrammingRule() { -+ fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 90e9797cc1f3a4aa0a2bee28dca364e6f6dd0c0b..ec98f5f59ca2b4cb58eb00ed8cdfa364f8bacd88 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1573,6 +1573,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public boolean isPushable() { -+ // Paper start -+ return isCollidable(false); -+ } -+ -+ public boolean isCollidable(boolean ignoreClimbing) { -+ // Paper end - return false; - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index 8ce62148ebaeac9988e7c9d4b2f7ee57f58d883e..8d1e24c2fa844971908ae7ac918a8950026b40a6 100644 ---- a/src/main/java/net/minecraft/world/entity/EntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -51,11 +51,17 @@ public final class EntitySelector { - } - - public static Predicate pushableBy(Entity entity) { -+ // Paper start - ignoreClimbing param -+ return pushable(entity, false); -+ } -+ -+ public static Predicate pushable(Entity entity, boolean ignoreClimbing) { -+ // Paper end - Team scoreboardteambase = entity.getTeam(); - Team.CollisionRule scoreboardteambase_enumteampush = scoreboardteambase == null ? Team.CollisionRule.ALWAYS : scoreboardteambase.getCollisionRule(); - - return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> { -- if (!entity1.canCollideWithCb(entity) || !entity.canCollideWithCb(entity1)) { // CraftBukkit - collidable API -+ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWithCb(entity) || !entity.canCollideWithCb(entity1)) { // CraftBukkit - collidable API // Paper - isCollidable - return false; - } 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 9724d4222311345a44aa101ec47523a1909fbe8f..57b933afdbb2136ed48170da6945eb2b92edb4db 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -134,7 +134,6 @@ import org.bukkit.event.entity.EntityTeleportEvent; - import org.bukkit.event.player.PlayerItemConsumeEvent; - // CraftBukkit end - --import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class LivingEntity extends Entity { - -@@ -2956,7 +2955,7 @@ public abstract class LivingEntity extends Entity { - return; - } - // Paper - end don't run getEntities if we're not going to use its result -- List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); -+ List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushable(this, level.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule - - if (!list.isEmpty()) { - // Paper - move up -@@ -3094,9 +3093,16 @@ public abstract class LivingEntity extends Entity { - return !this.removed && this.collides; // CraftBukkit - } - -+ // Paper start - @Override - public boolean isPushable() { -- return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit -+ return this.isCollidable(level.paperConfig.fixClimbingBypassingCrammingRule); -+ } -+ -+ @Override -+ public boolean isCollidable(boolean ignoreClimbing) { -+ return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.onClimbable()) && this.collides; // CraftBukkit -+ // Paper end - } - - // CraftBukkit start - collidable API -diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java -index e56c575d744e1efe9a7512f337b781dc3715f6be..8e02e3a4464ab4096637fc69c03d083988bb426e 100644 ---- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java -+++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java -@@ -75,7 +75,7 @@ public class Bat extends AmbientCreature { - } - - @Override -- public boolean isPushable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return false; - } - -diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java -index 918628c0ed8fb32d44c034fddf045f08659c10f8..d6a9d0e94d80f1924cedef913829d15762456537 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java -@@ -368,8 +368,8 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { - } - - @Override -- public boolean isPushable() { -- return super.isPushable(); // CraftBukkit - collidable API -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper -+ return super.isCollidable(ignoreClimbing); // CraftBukkit - collidable API // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index d9bfc754d7544a54ff214b41b4f6c0a6bc66df28..b298bcfb665b1036cd21445cec1518069eb08f06 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -@@ -226,7 +226,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, - } - - @Override -- public boolean isPushable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return !this.isVehicle(); - } - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 5714aa450ac09788bcf1c2790d4f1581c9a7c28b..a89573670f7dccfd8f0c81fcd95673b6faf3fc10 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -358,7 +358,7 @@ public class ArmorStand extends LivingEntity { - } - - @Override -- public boolean isPushable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return false; - } - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -index 1257a740a4ab79870fe89057782e8ffc6c658c14..9cbde70787d8044f0edeb3d459231dd7fbb79584 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -@@ -144,7 +144,7 @@ public abstract class AbstractMinecart extends Entity { - } - - @Override -- public boolean isPushable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return true; - } - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -index bddc51c656f04f25744ec29cabab31d465cf8bce..4f82c6797fe9bbb1a29420ea15277be50e44808c 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -@@ -149,7 +149,7 @@ public class Boat extends Entity { - } - - @Override -- public boolean isPushable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return true; - } - diff --git a/Remapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch b/Remapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch deleted file mode 100644 index 25843d00d1..0000000000 --- a/Remapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 16 Nov 2020 12:01:52 -0800 -Subject: [PATCH] Added missing default perms for commands - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -index d5f4ece060b61de9ca5292d1f2411c709de5ece2..f0a57d225b81a505ff12425155ba838d8fad990c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -@@ -31,6 +31,59 @@ public final class CommandPermissions { - DefaultPermissions.registerPermission(PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands); -+ // Paper start -+ DefaultPermissions.registerPermission(PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "ban", "Allows the user to add players to banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "ban-ip", "Allows the user to add ip address to banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "banlist", "Allows the user to display banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "pardon", "Allows the user to remove entries from the banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "replaceitem", "Allows the user to replace items in inventories", PermissionDefault.OP, commands); // Remove in 1.17 (replaced by /item) -+ DefaultPermissions.registerPermission(PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands); -+ DefaultPermissions.registerPermission(PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands); -+ // Paper end - - DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands); - diff --git a/Remapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch b/Remapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch deleted file mode 100644 index c9ae36d161..0000000000 --- a/Remapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Thu, 27 Aug 2020 15:02:48 -0400 -Subject: [PATCH] Add PlayerShearBlockEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java -index 1a01937f5250f3a529932dc2fdd9e1ebd9ae896a..125e646b39ef4a59be3989df16b5625c5504aac1 100644 ---- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java -@@ -1,5 +1,7 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts -+ - import java.util.Iterator; - import java.util.List; - import java.util.Random; -@@ -10,6 +12,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.Tag; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; -@@ -116,8 +119,19 @@ public class BeehiveBlock extends BaseEntityBlock { - - if (i >= 5) { - if (itemstack.getItem() == Items.SHEARS) { -+ // Paper start - Add PlayerShearBlockEvent -+ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); -+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3))); -+ if (!event.callEvent()) { -+ return InteractionResult.PASS; -+ } -+ // Paper end - world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.NEUTRAL, 1.0F, 1.0F); -- dropHoneycomb(world, pos); -+ // Paper start - Add PlayerShearBlockEvent -+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { -+ dropItem(world, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); -+ } -+ // Paper end - itemstack.hurtAndBreak(1, player, (entityhuman1) -> { - entityhuman1.broadcastBreakEvent(hand); - }); -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index baa587e73a71d6324bb7817fa4702a7c3a2db726..5f1853c3f22661809437bdb49f002482da7195f2 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -262,13 +262,13 @@ public class Block extends BlockBehaviour implements ItemLike { - - } - -- public static void popResource(Level world, BlockPos pos, ItemStack stack) { -- if (!world.isClientSide && !stack.isEmpty() && world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { -+ public static void popResource(Level world, BlockPos pos, ItemStack stack) { dropItem(world, pos, stack); } public static void dropItem(Level world, BlockPos blockposition, ItemStack itemstack) { // Paper - OBFHELPER -+ if (!world.isClientSide && !itemstack.isEmpty() && world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { - float f = 0.5F; - double d0 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; - double d1 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; - double d2 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; -- ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + d0, (double) pos.getY() + d1, (double) pos.getZ() + d2, stack); -+ ItemEntity entityitem = new ItemEntity(world, (double) blockposition.getX() + d0, (double) blockposition.getY() + d1, (double) blockposition.getZ() + d2, itemstack); - - entityitem.setDefaultPickUpDelay(); - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java -index fe528f7dee693982285ce035abd9929cb4e0cbdf..7cac13ad06ee7acfc3bdcbf79318dbfbd2a31e02 100644 ---- a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; - - import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.world.InteractionHand; -@@ -14,6 +15,7 @@ import net.minecraft.world.level.Level; - import net.minecraft.world.level.block.state.BlockBehaviour; - import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.phys.BlockHitResult; -+import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts - - public class PumpkinBlock extends StemGrownBlock { - -@@ -27,15 +29,26 @@ public class PumpkinBlock extends StemGrownBlock { - - if (itemstack.getItem() == Items.SHEARS) { - if (!world.isClientSide) { -+ // Paper start - Add PlayerShearBlockEvent -+ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); -+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4))); -+ if (!event.callEvent()) { -+ return InteractionResult.PASS; -+ } -+ // Paper end - Direction enumdirection = hit.getDirection(); - Direction enumdirection1 = enumdirection.getAxis() == Direction.Axis.Y ? player.getDirection().getOpposite() : enumdirection; - - world.playSound((Player) null, pos, SoundEvents.PUMPKIN_CARVE, SoundSource.BLOCKS, 1.0F, 1.0F); - world.setBlock(pos, (BlockState) Blocks.CARVED_PUMPKIN.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, enumdirection1), 11); -- ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) enumdirection1.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) enumdirection1.getStepZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4)); -+ // Paper start - Add PlayerShearBlockEvent -+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { -+ ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) enumdirection1.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) enumdirection1.getStepZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); -+ // Paper end - - entityitem.setDeltaMovement(0.05D * (double) enumdirection1.getStepX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double) enumdirection1.getStepZ() + world.random.nextDouble() * 0.02D); - world.addFreshEntity(entityitem); -+ } // Paper - Add PlayerShearBlockEvent - itemstack.hurtAndBreak(1, player, (entityhuman1) -> { - entityhuman1.broadcastBreakEvent(hand); - }); diff --git a/Remapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch b/Remapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch deleted file mode 100644 index ce4786d7fc..0000000000 --- a/Remapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Wed, 2 Dec 2020 21:58:45 -0800 -Subject: [PATCH] Add warning for servers not running on Java 16 - - -diff --git a/src/main/java/io/papermc/paper/util/PaperJvmChecker.java b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fdf3ff8894e5e202229d1be52fe3c92ea039ef15 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java -@@ -0,0 +1,48 @@ -+package io.papermc.paper.util; -+ -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; -+ -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+public class PaperJvmChecker { -+ -+ private static int getJvmVersion() { -+ String javaVersion = System.getProperty("java.version"); -+ final Matcher matcher = Pattern.compile("(?:1\\.)?(\\d+)").matcher(javaVersion); -+ if (!matcher.find()) { -+ LogManager.getLogger().warn("Failed to determine Java version; Could not parse: {}", javaVersion); -+ return -1; -+ } -+ -+ final String version = matcher.group(1); -+ try { -+ return Integer.parseInt(version); -+ } catch (final NumberFormatException e) { -+ LogManager.getLogger().warn("Failed to determine Java version; Could not parse {} from {}", version, javaVersion, e); -+ return -1; -+ } -+ } -+ -+ public static void checkJvm() { -+ if (getJvmVersion() < 16) { -+ final Logger logger = LogManager.getLogger(); -+ logger.warn("************************************************************"); -+ logger.warn("* WARNING - YOU ARE RUNNING AN OUTDATED VERSION OF JAVA."); -+ logger.warn("* PAPER WILL STOP BEING COMPATIBLE WITH THIS VERSION OF"); -+ logger.warn("* JAVA WHEN MINECRAFT 1.17 IS RELEASED."); -+ logger.warn("*"); -+ logger.warn("* Please update the version of Java you use to run Paper"); -+ logger.warn("* to at least Java 16. When Paper for Minecraft 1.17 is"); -+ logger.warn("* released support for versions of Java before 16 will"); -+ logger.warn("* be dropped."); -+ logger.warn("*"); -+ logger.warn("* Current Java version: {}", System.getProperty("java.version")); -+ logger.warn("*"); -+ logger.warn("* Check this forum post for more information: "); -+ logger.warn("* https://papermc.io/java16"); -+ logger.warn("************************************************************"); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 954dce690852da87a37e7797c6f9f549242e511a..c83f2636ae93d92381e019d5b13ac82c5a1d30bf 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -180,6 +180,7 @@ import org.bukkit.event.server.ServerLoadEvent; - - import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot -+import io.papermc.paper.util.PaperJvmChecker; // Paper - - public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { - -@@ -1075,6 +1076,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Wed, 2 Dec 2020 20:17:54 -0800 -Subject: [PATCH] Set spigots verbose world setting to false by def - - -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 6b015c1f26facb4e82d75b252164dec05731ca6c..094a934c168d232b0550c3efe722f2ebfbdf8e24 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -20,7 +20,7 @@ public class SpigotWorldConfig - - public void init() - { -- this.verbose = getBoolean( "verbose", true ); -+ this.verbose = getBoolean( "verbose", false ); // Paper - - log( "-------- World Settings For [" + worldName + "] --------" ); - SpigotConfig.readConfig( SpigotWorldConfig.class, this ); diff --git a/Remapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch b/Remapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch deleted file mode 100644 index 852cffc989..0000000000 --- a/Remapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 8 Dec 2020 20:14:20 -0600 -Subject: [PATCH] Fix curing zombie villager discount exploit - -This fixes the exploit used to gain absurd trading discounts with infecting -and curing a villager on repeat by simply resetting the relevant part of -the reputation when it is cured. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7d3207a9af8360ddad228281d6aa65e1a0d24157..a3b3e3e04b7a5e3a351992e06870cc91fbd8adc8 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -717,4 +717,9 @@ public class PaperWorldConfig { - private void fixClimbingBypassingCrammingRule() { - fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); - } -+ -+ public boolean fixCuringZombieVillagerDiscountExploit = true; -+ private void fixCuringExploit() { -+ fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -index 57832c392910d22aa81ac2b4816d043dd7ac867a..9a68201bab4fcbad69c85e2469a103634b65d7b3 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -@@ -223,6 +223,7 @@ public class GossipContainer { - - } - -+ public final void removeReputationForType(GossipType reputationType) { this.remove(reputationType); } // Paper - OBFHELPER - public void remove(GossipType gossipType) { - this.entries.removeInt(gossipType); - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 415fa3591add1f1ab22dd5866e110dbfccd0ec93..7817071b1964b962c8f4017d5bb39d74ca0ca3e4 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/Villager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -1013,6 +1013,15 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - @Override - public void onReputationEventFrom(ReputationEventType interaction, Entity entity) { - if (interaction == ReputationEventType.ZOMBIE_VILLAGER_CURED) { -+ // Paper start - fix MC-181190 -+ if (level.paperConfig.fixCuringZombieVillagerDiscountExploit) { -+ final GossipContainer.EntityGossips playerReputation = this.getReputation().getReputations().get(entity.getUUID()); -+ if (playerReputation != null) { -+ playerReputation.removeReputationForType(GossipType.MAJOR_POSITIVE); -+ playerReputation.removeReputationForType(GossipType.MINOR_POSITIVE); -+ } -+ } -+ // Paper end - this.gossips.add(entity.getUUID(), GossipType.MAJOR_POSITIVE, 20); - this.gossips.add(entity.getUUID(), GossipType.MINOR_POSITIVE, 25); - } else if (interaction == ReputationEventType.TRADE) { diff --git a/Remapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch b/Remapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch deleted file mode 100644 index dc1bd95672..0000000000 --- a/Remapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 12 Dec 2020 23:45:28 +0000 -Subject: [PATCH] Limit recipe packets - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 7d50aded88f5b7dfebaea1aebc86231f7b5c4e25..652d87fc5d566dba8018c81676329f0e0bca471b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -334,6 +334,13 @@ public class PaperConfig { - tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); - } - -+ public static int autoRecipeIncrement = 1; -+ public static int autoRecipeLimit = 20; -+ private static void autoRecipieLimiters() { -+ autoRecipeIncrement = getInt("settings.spam-limiter.recipe-spam-increment", autoRecipeIncrement); -+ autoRecipeLimit = getInt("settings.spam-limiter.recipe-spam-limit", autoRecipeLimit); -+ } -+ - public static boolean velocitySupport; - public static boolean velocityOnlineMode; - public static byte[] velocitySecretKey; -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ccfe5a1ec1e9895f7462b7c676fee80903502a88..e50e42cce60c725cdd981d8927e379c5760d9200 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.network; - -+import com.destroystokyo.paper.PaperConfig; - import com.google.common.collect.Lists; - import com.google.common.primitives.Doubles; - import com.google.common.primitives.Floats; -@@ -174,6 +175,7 @@ import io.papermc.paper.adventure.ChatProcessor; // Paper - import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.util.concurrent.ExecutionException; - import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -+import org.bukkit.Bukkit; // Paper - import org.bukkit.Location; - import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.craftbukkit.event.CraftEventFactory; -@@ -232,6 +234,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - private volatile int chatSpamTickCount; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(ServerGamePacketListenerImpl.class, "chatThrottle"); - private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits -+ private final java.util.concurrent.atomic.AtomicInteger recipeSpamPackets = new java.util.concurrent.atomic.AtomicInteger(); // Paper - auto recipe limit - // CraftBukkit end - private int dropSpamTickCount; - private final Int2ShortMap expectedAcks = new Int2ShortOpenHashMap(); -@@ -380,6 +383,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // CraftBukkit start - for (int spam; (spam = this.chatSpamTickCount) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; - if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable -+ if (recipeSpamPackets.get() > 0) recipeSpamPackets.getAndDecrement(); // Paper - /* Use thread-safe field access instead - if (this.chatThrottle > 0) { - --this.chatThrottle; -@@ -2786,6 +2790,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - @Override - public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) { -+ // Paper start -+ if (!Bukkit.isPrimaryThread()) { -+ if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { -+ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper -+ return; -+ } -+ } -+ // Paper end - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); - this.player.resetLastActionTime(); - if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu.isSynched(this.player) && this.player.containerMenu instanceof RecipeBookMenu) { diff --git a/Remapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch b/Remapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch deleted file mode 100644 index 60e8ef1e6b..0000000000 --- a/Remapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Thu, 17 Dec 2020 15:25:49 -0600 -Subject: [PATCH] Fix CraftSound backwards compatibility - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java -index 266563e72b563fd9db85f17bca710bbe45e8a22d..b2667c5f0794d521766203fea3299f12e21f5c76 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java -@@ -26,4 +26,10 @@ public class CraftSound { - public static Sound getBukkit(SoundEvent soundEffect) { - return Registry.SOUNDS.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.Registry.SOUND_EVENT.getKey(soundEffect))); - } -+ -+ // Paper start -+ public static String getSound(Sound sound) { -+ return sound.getKey().getKey(); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch b/Remapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch deleted file mode 100644 index 3d3624adc8..0000000000 --- a/Remapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 8 Dec 2020 20:24:52 -0600 -Subject: [PATCH] MC-4: Fix item position desync - -This fixes item position desync (MC-4) by running the item coordinates -through the encode/decode methods of the packet that causes the precision -loss, which forces the server to lose the same precision as the client -keeping them in sync. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 652d87fc5d566dba8018c81676329f0e0bca471b..c56e7fb18f9a56c8025eb70a524f028b5942da37 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -474,4 +474,9 @@ public class PaperConfig { - private static void trackPluginScoreboards() { - trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); - } -+ -+ public static boolean fixEntityPositionDesync = true; -+ private static void fixEntityPositionDesync() { -+ fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); -+ } - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java -index cb10c87728b5f9062c4bdd1fe5e4b2c7a558f323..6b97d60d923e772c7284e674bc3f2e9a5a0ddead 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java -@@ -19,11 +19,11 @@ public class ClientboundMoveEntityPacket implements Packet { -+ private static final float[] SIN = (float[]) Util.make((new float[65536]), (afloat) -> { // Paper - decompile error - for (int i = 0; i < afloat.length; ++i) { - afloat[i] = (float) Math.sin((double) i * 3.141592653589793D * 2.0D / 65536.0D); - } -@@ -49,6 +49,7 @@ public class Mth { - return d0 < (double) i ? i - 1 : i; - } - -+ public static long floorLong(double d0) { return lfloor(d0); } // Paper - OBFHELPER - public static long lfloor(double d0) { - long i = (long) d0; - -diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 9311f9f411d09d4460f0be8235957fab9e195b7a..7476ae301fb4ee503944d39022cb25ccb19f1232 100644 ---- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -549,4 +549,16 @@ public class ItemEntity extends Entity { - public Packet getAddEntityPacket() { - return new ClientboundAddEntityPacket(this); - } -+ -+ // Paper start - fix MC-4 -+ public void setPosRaw(double x, double y, double z) { -+ if (com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) { -+ // encode/decode from PacketPlayOutEntity -+ x = Mth.floorLong(x * 4096.0D) * (1 / 4096.0D); -+ y = Mth.floorLong(y * 4096.0D) * (1 / 4096.0D); -+ z = Mth.floorLong(z * 4096.0D) * (1 / 4096.0D); -+ } -+ super.setPosRaw(x, y, z); -+ } -+ // Paper end - fix MC-4 - } diff --git a/Remapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch b/Remapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch deleted file mode 100644 index d7abc567f0..0000000000 --- a/Remapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 5 Oct 2020 21:25:16 +0200 -Subject: [PATCH] Player Chunk Load/Unload Events - - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 1b5f24920c46cd238a79f5a2857d26fa1c12b983..ff831ca0cbc0cabbf78178c609ccf70d78da7980 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -136,6 +136,8 @@ import net.minecraft.world.level.dimension.DimensionType; - import net.minecraft.world.level.portal.PortalInfo; - import net.minecraft.world.phys.AABB; - import net.minecraft.world.phys.Vec3; -+import io.papermc.paper.event.packet.PlayerChunkLoadEvent; // Paper -+import io.papermc.paper.event.packet.PlayerChunkUnloadEvent; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - import net.minecraft.world.Container; -@@ -2095,11 +2097,21 @@ public class ServerPlayer extends Player implements ContainerListener { - public void trackChunk(ChunkPos chunkcoordintpair, Packet packet, Packet packet1) { - this.connection.send(packet1); - this.connection.send(packet); -+ // Paper start -+ if(PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0){ -+ new PlayerChunkLoadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); -+ } -+ // Paper end - } - - public void untrackChunk(ChunkPos chunkcoordintpair) { - if (this.isAlive()) { - this.connection.send(new ClientboundForgetLevelChunkPacket(chunkcoordintpair.x, chunkcoordintpair.z)); -+ // Paper start -+ if(PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0){ -+ new PlayerChunkUnloadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); -+ } -+ // Paper end - } - - } diff --git a/Remapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch b/Remapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch deleted file mode 100644 index 5a4efe035c..0000000000 --- a/Remapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 21 Dec 2020 11:01:42 -0500 -Subject: [PATCH] Optimize Dynamic#get Missing Keys - -get was calling toString() on every NBT object that was ever asked for an optional -key from the object to build a string for the error text. - -When done on large NBT objects, this was using a ton of computation time building the -JSON representation of the NBT object. - -Now we will just skip the value when 99.9999% of the time the text is never even printed. - -diff --git a/src/main/java/com/mojang/serialization/Dynamic.java b/src/main/java/com/mojang/serialization/Dynamic.java -index a75d3db046dc985a03b4b870c91f41de1bd66bad..044facc9de9e8e582d7953d681c0c051578979c3 100644 ---- a/src/main/java/com/mojang/serialization/Dynamic.java -+++ b/src/main/java/com/mojang/serialization/Dynamic.java -@@ -17,6 +17,7 @@ import java.util.stream.Stream; - - @SuppressWarnings("unused") - public class Dynamic extends DynamicLike { -+ private static final boolean DEBUG_MISSING_KEYS = Boolean.getBoolean("Paper.debugDynamicMissingKeys"); // Paper - private final T value; - - public Dynamic(final DynamicOps ops) { -@@ -113,7 +114,7 @@ public class Dynamic extends DynamicLike { - return new OptionalDynamic<>(ops, ops.getMap(value).flatMap(m -> { - final T value = m.get(key); - if (value == null) { -- return DataResult.error("key missing: " + key + " in " + this.value); -+ return DataResult.error(DEBUG_MISSING_KEYS ? "key missing: " + key + " in " + this.value : "key missing: " + key); // Paper - } - return DataResult.success(new Dynamic<>(ops, value)); - })); diff --git a/Remapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch b/Remapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch deleted file mode 100644 index d179506896..0000000000 --- a/Remapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 13 Dec 2020 05:32:05 +0200 -Subject: [PATCH] Expose LivingEntity hurt direction - - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 57b933afdbb2136ed48170da6945eb2b92edb4db..02ddb84c563b3149c4f1b0e24899ce8a21ad61bb 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -160,7 +160,7 @@ public abstract class LivingEntity extends Entity { - public int removeStingerTime; - public int hurtTime; - public int hurtDuration; -- public float hurtDir; -+ public float hurtDir; public final float getHurtDirection() { return hurtDir; } public final void setHurtDirection(float hurtDirection) { this.hurtDir = hurtDirection; } // Paper - OBFHELPER - public int deathTime; - public float oAttackAnim; - public float attackAnim; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 170bb1124ee396a85dd64baed8110e39823ad849..a8d21382d5859edfd12e01a48924ce780790b4b7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -818,5 +818,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { - getHandle().take(((CraftItem) item).getHandle(), quantity); - } -+ -+ @Override -+ public float getHurtDirection() { -+ return getHandle().getHurtDirection(); -+ } -+ -+ @Override -+ public void setHurtDirection(float hurtDirection) { -+ getHandle().setHurtDirection(hurtDirection); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/Remapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch deleted file mode 100644 index d2162d0415..0000000000 --- a/Remapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 24 Dec 2020 12:43:39 -0800 -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 64cfa14aa4e32430a6970fd4f3654a56146ba807..34c7b1213b3f83ff1a1f2d606a9c25e57fea8ef3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -259,6 +259,10 @@ public class CraftEventFactory { - return BedEnterResult.TOO_FAR_AWAY; - case NOT_SAFE: - return BedEnterResult.NOT_SAFE; -+ // Paper start -+ case OBSTRUCTED: -+ return BedEnterResult.OBSTRUCTED; -+ // Paper end - default: - return BedEnterResult.OTHER_PROBLEM; - } diff --git a/Remapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/Remapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch deleted file mode 100644 index f57f5ee833..0000000000 --- a/Remapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 27 Dec 2020 11:31:06 +0000 -Subject: [PATCH] Do not crash from invalid ingredient lists in - VillagerAcquireTradeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -index 407a68edf6408400f1a6c5bb1a6cbbfae08ac2cd..335000713279b7964c5172937483678c671bfed1 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -270,7 +270,11 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan - Bukkit.getPluginManager().callEvent(event); - } - if (!event.isCancelled()) { -- recipeList.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); -+ // Paper start -+ final CraftMerchantRecipe craftMerchantRecipe = CraftMerchantRecipe.fromBukkit(event.getRecipe()); -+ if (craftMerchantRecipe.getIngredients().isEmpty()) return; -+ recipeList.add(craftMerchantRecipe.toMinecraft()); -+ // Paper end - } - // CraftBukkit end - } diff --git a/Remapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch b/Remapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch deleted file mode 100644 index 3589365354..0000000000 --- a/Remapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 2 Jul 2020 16:12:10 -0700 -Subject: [PATCH] added PlayerTradeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 40ab66f888f30a5506e3aa96a4b32485452e8978..87dd6c012bf1ca6a1e8df44dc0957c4c67d02adc 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -91,7 +91,7 @@ import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; - public abstract class Mob extends LivingEntity { - - private static final EntityDataAccessor DATA_MOB_FLAGS_ID = SynchedEntityData.defineId(Mob.class, EntityDataSerializers.BYTE); -- public int ambientSoundTime; -+ public int ambientSoundTime;public void setAmbientSoundTime(int time) { this.ambientSoundTime = time; } // Paper - OBFHELPER - protected int xpReward; - protected LookControl lookControl; - protected MoveControl moveControl; -@@ -293,6 +293,7 @@ public abstract class Mob extends LivingEntity { - this.entityData.define(Mob.DATA_MOB_FLAGS_ID, (byte) 0); - } - -+ public int getAmbientSoundInterval() { return getAmbientSoundInterval(); } // Paper - OBFHELPER - public int getAmbientSoundInterval() { - return 80; - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -index 335000713279b7964c5172937483678c671bfed1..d31b773f8aff09c9f214662aa3aa0c904119e12c 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -37,6 +37,9 @@ import org.bukkit.craftbukkit.inventory.CraftMerchant; - import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; - import org.bukkit.event.entity.VillagerAcquireTradeEvent; - // CraftBukkit end -+// Paper start -+import io.papermc.paper.event.player.PlayerTradeEvent; -+// Paper end - - public abstract class AbstractVillager extends AgableMob implements Npc, Merchant { - -@@ -133,16 +136,27 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan - - @Override - public void notifyTrade(MerchantOffer offer) { -- offer.increaseUses(); -- this.ambientSoundTime = -this.getAmbientSoundInterval(); -- this.rewardTradeXp(offer); -+ // Paper - moved down -+ // Paper start - if (this.tradingPlayer instanceof ServerPlayer) { -- CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, offer.getResult()); -+ PlayerTradeEvent event = new PlayerTradeEvent(((ServerPlayer) this.tradingPlayer).getBukkitEntity(), (org.bukkit.entity.AbstractVillager) this.getBukkitEntity(), offer.asBukkit(), true, true); -+ event.callEvent(); -+ if (!event.isCancelled()) { -+ MerchantOffer recipe = CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft(); -+ if (event.willIncreaseTradeUses()) recipe.increaseUses(); -+ this.setAmbientSoundTime(-getAmbientSoundInterval()); -+ if (event.isRewardingExp()) this.rewardTradeXp(recipe); -+ CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, recipe.getResult()); -+ } -+ } else { -+ offer.increaseUses(); -+ this.setAmbientSoundTime(-getAmbientSoundInterval()); -+ this.rewardTradeXp(offer); - } -- -+ // Paper end - } - -- protected abstract void rewardTradeXp(MerchantOffer offer); -+ protected abstract void rewardTradeXp(MerchantOffer offer); public void rewardTradeXp(MerchantOffer merchantrecipe) { this.rewardTradeXp(merchantrecipe); } // Paper - OBFHELPER - - @Override - public boolean showProgressBar() { diff --git a/Remapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch b/Remapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch deleted file mode 100644 index bc8c6c48be..0000000000 --- a/Remapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Wed, 25 Nov 2020 23:20:44 -0800 -Subject: [PATCH] Implement TargetHitEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/TargetBlock.java b/src/main/java/net/minecraft/world/level/block/TargetBlock.java -index bbaf90b30b07c97321541b8fe15d47975a34161d..a7215c9b9f0f191bbfe95cb1185c99a8d21ff785 100644 ---- a/src/main/java/net/minecraft/world/level/block/TargetBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/TargetBlock.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.TargetHitEvent; // Paper - Need to import because 'io' class exists in nms - import java.util.Random; - import net.minecraft.advancements.CriteriaTriggers; - import net.minecraft.core.BlockPos; -@@ -34,13 +35,17 @@ public class TargetBlock extends Block { - @Override - public void onProjectileHit(Level world, BlockState state, BlockHitResult hit, Projectile projectile) { - int i = updateRedstoneOutput((LevelAccessor) world, state, hit, (Entity) projectile); -- Entity entity = projectile.getOwner(); -+ // Paper start -+ } -+ private static void awardTargetHitCriteria(Projectile iprojectile, BlockHitResult movingobjectpositionblock, int i) { -+ // Paper end -+ Entity entity = iprojectile.getOwner(); - - if (entity instanceof ServerPlayer) { - ServerPlayer entityplayer = (ServerPlayer) entity; - - entityplayer.awardStat(Stats.TARGET_HIT); -- CriteriaTriggers.TARGET_BLOCK_HIT.trigger(entityplayer, projectile, hit.getLocation(), i); -+ CriteriaTriggers.TARGET_BLOCK_HIT.trigger(entityplayer, iprojectile, movingobjectpositionblock.getLocation(), i); - } - - } -@@ -49,6 +54,20 @@ public class TargetBlock extends Block { - int i = getRedstoneStrength(movingobjectpositionblock, movingobjectpositionblock.getLocation()); - int j = entity instanceof AbstractArrow ? 20 : 8; - -+ // Paper start -+ if (entity instanceof Projectile) { -+ final Projectile projectile = (Projectile) entity; -+ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, movingobjectpositionblock.getBlockPos()); -+ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(movingobjectpositionblock.getDirection()); -+ final TargetHitEvent targetHitEvent = new TargetHitEvent((org.bukkit.entity.Projectile) projectile.getBukkitEntity(), craftBlock, blockFace, i); -+ if (targetHitEvent.callEvent()) { -+ i = targetHitEvent.getSignalStrength(); -+ awardTargetHitCriteria(projectile, movingobjectpositionblock, i); -+ } else { -+ return i; -+ } -+ } -+ // Paper end - if (!world.getBlockTicks().a(movingobjectpositionblock.getBlockPos(), state.getBlock())) { - setOutputPower(world, state, i, movingobjectpositionblock.getBlockPos(), j); - } diff --git a/Remapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch b/Remapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch deleted file mode 100644 index 6aa789f4d3..0000000000 --- a/Remapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 30 Dec 2020 19:43:01 -0500 -Subject: [PATCH] Additional Block Material API's - -Faster version for isSolid() that utilizes NMS's state for isSolid instead of the slower -process to do this in the Bukkit API - -Adds API for buildable, replaceable, burnable too. - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 9defb202761296a825d035e27ddc51e17a311647..376b0497c28a35d7ea615397c87b2558b95c596a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -618,6 +618,25 @@ public class CraftBlock implements Block { - return getNMS().getMaterial().isLiquid(); - } - -+ // Paper start -+ @Override -+ public boolean isBuildable() { -+ return getNMS().getMaterial().isBuildable(); -+ } -+ @Override -+ public boolean isBurnable() { -+ return getNMS().getMaterial().isBurnable(); -+ } -+ @Override -+ public boolean isReplaceable() { -+ return getNMS().getMaterial().isReplaceable(); -+ } -+ @Override -+ public boolean isSolid() { -+ return getNMS().getMaterial().blocksMotion(); -+ } -+ // Paper end -+ - @Override - public PistonMoveReaction getPistonMoveReaction() { - return PistonMoveReaction.getById(getNMS().getPistonPushReaction().ordinal()); diff --git a/Remapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch b/Remapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch deleted file mode 100644 index e5c11d28d2..0000000000 --- a/Remapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> -Date: Thu, 23 Jul 2020 14:25:07 -0700 -Subject: [PATCH] Fix harming potion dupe - -EntityLiving#applyInstantEffect() immediately kills the player and drops their inventory. -Before this patch, instant effects would be applied before the potion ItemStack is removed and replaced with a glass bottle. This caused the potion ItemStack to be dropped before it was supposed to be removed from the inventory. It also caused the glass bottle to be put into a dead player's inventory. -This patch makes it so that instant effects are applied after the potion ItemStack is removed, and the glass bottle is only put into the player's inventory if the player is not dead. Otherwise, the glass bottle is dropped on the ground. - -diff --git a/src/main/java/net/minecraft/world/item/PotionItem.java b/src/main/java/net/minecraft/world/item/PotionItem.java -index 36ccec8ad2f605d5bceae476e26c2fbfbdae39d8..ba2bc044b259b0a5ba590d4ae6fd36e5c415ddff 100644 ---- a/src/main/java/net/minecraft/world/item/PotionItem.java -+++ b/src/main/java/net/minecraft/world/item/PotionItem.java -@@ -15,6 +15,7 @@ import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.alchemy.Potion; - import net.minecraft.world.item.alchemy.PotionUtils; - import net.minecraft.world.item.alchemy.Potions; -+import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.Level; - - public class PotionItem extends Item { -@@ -36,6 +37,7 @@ public class PotionItem extends Item { - CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) entityhuman, stack); - } - -+ List instantLater = new java.util.ArrayList<>(); // Paper - Fix harming potion dupe - if (!world.isClientSide) { - List list = PotionUtils.getMobEffects(stack); - Iterator iterator = list.iterator(); -@@ -44,7 +46,7 @@ public class PotionItem extends Item { - MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); - - if (mobeffect.getMobEffect().isInstant()) { -- mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D); -+ instantLater.add(mobeffect); // Paper - Fix harming potion dupe - } else { - user.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit - } -@@ -58,7 +60,20 @@ public class PotionItem extends Item { - } - } - -+ // Paper start - Fix harming potion dupe -+ for (MobEffectInstance mobeffect : instantLater) { -+ mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D); -+ } -+ // Paper end -+ - if (entityhuman == null || !entityhuman.abilities.instabuild) { -+ // Paper start - Fix harming potion dupe -+ if (user.getHealth() <= 0 && !user.level.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY)) { -+ user.dropItem(new ItemStack(Items.GLASS_BOTTLE), 0); -+ return ItemStack.NULL_ITEM; -+ } -+ // Paper end -+ - if (stack.isEmpty()) { - return new ItemStack(Items.GLASS_BOTTLE); - } diff --git a/Remapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/Remapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch deleted file mode 100644 index f956ace9fd..0000000000 --- a/Remapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Thu, 31 Dec 2020 12:48:19 +1000 -Subject: [PATCH] Implement API to get Material from Boats and Minecarts - - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -index 4f82c6797fe9bbb1a29420ea15277be50e44808c..6a9c18540886979b2212bf7917a21753c9a9db3c 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -@@ -259,6 +259,7 @@ public class Boat extends Entity { - - } - -+ public final Item getBoatItem() { return this.getDropItem(); } // Paper - OBFHELPER - public Item getDropItem() { - switch (this.getBoatType()) { - case OAK: -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -index de8e9e8d18fb9cc6f49d98ab0c57faffec61e5b5..5928ab97b91062963e5cca0a8ec50f2bc3a7ff96 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -@@ -1,7 +1,9 @@ - package org.bukkit.craftbukkit.entity; - -+import org.bukkit.Material; // Paper - import org.bukkit.TreeSpecies; - import org.bukkit.craftbukkit.CraftServer; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper - import org.bukkit.entity.Boat; - import org.bukkit.entity.EntityType; - -@@ -65,6 +67,13 @@ public class CraftBoat extends CraftVehicle implements Boat { - getHandle().landBoats = workOnLand; - } - -+ // Paper start -+ @Override -+ public Material getBoatMaterial() { -+ return CraftMagicNumbers.getMaterial(getHandle().getBoatItem()); -+ } -+ // Paper end -+ - @Override - public net.minecraft.world.entity.vehicle.Boat getHandle() { - return (net.minecraft.world.entity.vehicle.Boat) entity; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -index 55df92a4661e13a9085f325db0572a265a89948c..fb26b6125ad4090d87b2326add94ffaded82c8ef 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -@@ -1,8 +1,10 @@ - package org.bukkit.craftbukkit.entity; - - import net.minecraft.world.entity.vehicle.AbstractMinecart; -+import net.minecraft.world.item.Items; // Paper - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.BlockState; -+import org.bukkit.Material; // Paper - import org.bukkit.block.data.BlockData; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.block.data.CraftBlockData; -@@ -68,6 +70,38 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart { - getHandle().setDerailedVelocityMod(derailed); - } - -+ // Paper start -+ @Override -+ public Material getMinecartMaterial() { -+ net.minecraft.world.item.Item minecartItem; -+ switch (getHandle().getMinecartType()) { -+ case CHEST: -+ minecartItem = Items.CHEST_MINECART; -+ break; -+ case FURNACE: -+ minecartItem = Items.FURNACE_MINECART; -+ break; -+ case TNT: -+ minecartItem = Items.TNT_MINECART; -+ break; -+ case HOPPER: -+ minecartItem = Items.HOPPER_MINECART; -+ break; -+ case COMMAND_BLOCK: -+ minecartItem = Items.COMMAND_BLOCK_MINECART; -+ break; -+ case RIDEABLE: -+ case SPAWNER: -+ minecartItem = Items.MINECART; -+ break; -+ default: -+ throw new IllegalStateException("Unexpected value: " + getHandle().getMinecartType()); -+ } -+ -+ return CraftMagicNumbers.getMaterial(minecartItem); -+ } -+ // Paper end -+ - @Override - public AbstractMinecart getHandle() { - return (AbstractMinecart) entity; diff --git a/Remapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch b/Remapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch deleted file mode 100644 index 3dd32bb45a..0000000000 --- a/Remapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas -Date: Sun, 27 Dec 2020 17:19:51 +0100 -Subject: [PATCH] Optimized tick ready check - - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 066d5f7ee93351bff67c0d39ee9d940ac51515d8..b89cefc8890774dbc64fd6bddeb038d2ee36d485 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -854,13 +854,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - if (!tileentity.isRemoved() && tileentity.hasLevel()) { - BlockPos blockposition = tileentity.getBlockPos(); - -- if (this.getChunkSource().isTickingChunk(blockposition) && this.getWorldBorder().isWithinBounds(blockposition)) { -+ LevelChunk chunk; ChunkHolder playerChunk; if ((chunk = tileentity.getCurrentChunk()) != null && (playerChunk = chunk.playerChunk) != null && playerChunk.isTickingReady() && this.getWorldBorder().isInBounds(blockposition)) { // Paper - optimized tick ready check by inlining ChunkProviderServer.a(BlockPosition). Chunk lookup is no longer required and we can use the PlayerChunk directly available through the tile entity - try { - gameprofilerfiller.push(() -> { - return String.valueOf(BlockEntityType.getKey(tileentity.getType())); - }); - tileentity.tickTimer.startTiming(); // Spigot -- if (tileentity.getType().isValid(this.getBlockState(blockposition).getBlock())) { -+ if (tileentity.getType().isValid(chunk.getBlockState(blockposition).getBlock())) { // Paper - reuse the chunk from above, do not look it up again - ((TickableBlockEntity) tileentity).tick(); - } else { - tileentity.logInvalidState(); -@@ -893,9 +893,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - this.tickableBlockEntities.remove(tileTickPosition--); - // Spigot end - //this.tileEntityList.remove(tileentity); // Paper - remove unused list -- if (this.hasChunkAt(tileentity.getBlockPos())) { -- this.getChunkAt(tileentity.getBlockPos()).removeBlockEntity(tileentity.getBlockPos()); -+ // Paper - prevent double chunk lookups -+ LevelChunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getBlockPos())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again -+ chunk.removeBlockEntity(tileentity.getBlockPos()); - } -+ // Paper end - } - } - -@@ -914,8 +916,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - // CraftBukkit end */ - -- if (this.hasChunkAt(tileentity1.getBlockPos())) { -- LevelChunk chunk = this.getChunkAt(tileentity1.getBlockPos()); -+ LevelChunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity1.getBlockPos())) != null) { // Paper - inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again -+ // Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); // Paper - already computed above - BlockState iblockdata = chunk.getBlockState(tileentity1.getBlockPos()); - - chunk.setBlockEntity(tileentity1.getBlockPos(), tileentity1); diff --git a/Remapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch b/Remapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch deleted file mode 100644 index 4163e2cc84..0000000000 --- a/Remapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas -Date: Sun, 27 Dec 2020 16:47:00 +0100 -Subject: [PATCH] Cache burn durations - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 4126a36dbc7750108a883f0be14dcb0d2e6d7ae8..f47b46cebd43faa509b8139d2a51cc8f87615893 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.block.entity; - -+import com.google.common.collect.ImmutableMap; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; -@@ -111,7 +112,15 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - this.recipeType = recipeType; - } - -+ private static Map cachedBurnDurations = null; // Paper - cache burn durations -+ -+ public static Map getBurnDurations() { return getFuel(); } // Paper - OBFHELPER - public static Map getFuel() { -+ // Paper start - cache burn durations -+ if(cachedBurnDurations != null) { -+ return cachedBurnDurations; -+ } -+ // Paper end - Map map = Maps.newLinkedHashMap(); - - add(map, (ItemLike) Items.LAVA_BUCKET, 20000); -@@ -174,7 +183,10 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - add(map, (ItemLike) Blocks.FLETCHING_TABLE, 300); - add(map, (ItemLike) Blocks.SMITHING_TABLE, 300); - add(map, (ItemLike) Blocks.COMPOSTER, 300); -- return map; -+ // Paper start - cache burn durations -+ cachedBurnDurations = ImmutableMap.copyOf(map); -+ return cachedBurnDurations; -+ // Paper end - } - - // CraftBukkit start - add fields and methods -@@ -428,7 +440,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - } else { - Item item = fuel.getItem(); - -- return (Integer) getFuel().getOrDefault(item, 0); -+ return getBurnDurations().getOrDefault(item, 0); // Paper - cache burn durations - } - } - -@@ -441,7 +453,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - // Paper end - - public static boolean isFuel(ItemStack stack) { -- return getFuel().containsKey(stack.getItem()); -+ return getBurnDurations().containsKey(stack.getItem()); // Paper - cache burn durations - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/Remapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch deleted file mode 100644 index efb245db2f..0000000000 --- a/Remapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BrodyBeckwith -Date: Fri, 9 Oct 2020 20:30:12 -0400 -Subject: [PATCH] Allow disabling mob spawner spawn egg transformation - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a3b3e3e04b7a5e3a351992e06870cc91fbd8adc8..b48067c71f9de18ba40e970e2832f6245984a218 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -722,4 +722,9 @@ public class PaperWorldConfig { - private void fixCuringExploit() { - fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); - } -+ -+ public boolean disableMobSpawnerSpawnEggTransformation = false; -+ private void disableMobSpawnerSpawnEggTransformation() { -+ disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); -+ } - } -diff --git a/src/main/java/net/minecraft/world/item/SpawnEggItem.java b/src/main/java/net/minecraft/world/item/SpawnEggItem.java -index 9aae1435a271bb17d6355e4c75ccbce78cb9d449..7904a2176253eaf48b47e06dd2e19758a673873c 100644 ---- a/src/main/java/net/minecraft/world/item/SpawnEggItem.java -+++ b/src/main/java/net/minecraft/world/item/SpawnEggItem.java -@@ -60,7 +60,7 @@ public class SpawnEggItem extends Item { - Direction enumdirection = context.getClickedFace(); - BlockState iblockdata = world.getBlockState(blockposition); - -- if (iblockdata.is(Blocks.SPAWNER)) { -+ if (!world.paperConfig.disableMobSpawnerSpawnEggTransformation && iblockdata.is(Blocks.SPAWNER)) { // Paper - BlockEntity tileentity = world.getBlockEntity(blockposition); - - if (tileentity instanceof SpawnerBlockEntity) { diff --git a/Remapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch b/Remapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch deleted file mode 100644 index 2c81edd9ad..0000000000 --- a/Remapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterVector -Date: Tue, 13 Aug 2019 19:45:06 -0700 -Subject: [PATCH] Implement PlayerFlowerPotManipulateEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java b/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java -index ae74e70457f8f46ee71bf0902ade3468da272e81..a1d1f3416df8e313688fedad47dd264444d7c465 100644 ---- a/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java -@@ -20,6 +20,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType; - import net.minecraft.world.phys.BlockHitResult; - import net.minecraft.world.phys.shapes.CollisionContext; - import net.minecraft.world.phys.shapes.VoxelShape; -+import io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent; // Paper - - public class FlowerPotBlock extends Block { - -@@ -52,6 +53,27 @@ public class FlowerPotBlock extends Block { - boolean flag1 = this.content == Blocks.AIR; - - if (flag != flag1) { -+ // Paper start -+ org.bukkit.entity.Player player1 = (org.bukkit.entity.Player) player.getBukkitEntity(); -+ boolean placing = flag1; -+ org.bukkit.block.Block bukkitblock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos); -+ org.bukkit.inventory.ItemStack bukkititemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack); -+ org.bukkit.Material mat = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(content); -+ org.bukkit.inventory.ItemStack bukkititemstack1 = new org.bukkit.inventory.ItemStack(mat, 1); -+ org.bukkit.inventory.ItemStack whichitem = placing ? bukkititemstack : bukkititemstack1; -+ -+ PlayerFlowerPotManipulateEvent event = new PlayerFlowerPotManipulateEvent(player1, bukkitblock, whichitem, placing); -+ player1.getServer().getPluginManager().callEvent(event); -+ -+ if (event.isCancelled()) { -+ // Update client -+ player1.sendBlockChange(bukkitblock.getLocation(), bukkitblock.getBlockData()); -+ player1.updateInventory(); -+ -+ return InteractionResult.PASS; -+ } -+ // Paper end -+ - if (flag1) { - world.setBlock(pos, block.defaultBlockState(), 3); - player.awardStat(Stats.POT_FLOWER); diff --git a/Remapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch b/Remapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch deleted file mode 100644 index 5e69fe3a87..0000000000 --- a/Remapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheMolkaPL -Date: Sun, 21 Jun 2020 17:21:46 +0200 -Subject: [PATCH] Fix interact event not being called in adventure - -Call PlayerInteractEvent when left-clicking on a block in adventure mode - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index e50e42cce60c725cdd981d8927e379c5760d9200..cb6568b622abeb939a1195f4656accc8a1c3f1fc 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1701,7 +1701,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - MutableComponent ichatmutablecomponent = (new TranslatableComponent("build.tooHigh", new Object[]{this.server.getMaxBuildHeight()})).withStyle(ChatFormatting.RED); - - this.player.connection.send(new ClientboundChatPacket(ichatmutablecomponent, ChatType.GAME_INFO, Util.NIL_UUID)); -- } else if (enuminteractionresult.shouldSwing()) { -+ } else if (enuminteractionresult.shouldSwing() && !this.player.gameMode.interactResult) { - this.player.swing(enumhand, true); - } - } -@@ -2202,7 +2202,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - Vec3 vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); - HitResult movingobjectposition = this.player.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)); - -- if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK) { -+ if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK || this.player.gameMode.getGameModeForPlayer() == GameType.ADVENTURE) { // Paper - call PlayerInteractEvent when left-clicking on a block in adventure mode - CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.inventory.getSelected(), InteractionHand.MAIN_HAND); - } - diff --git a/Remapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch b/Remapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch deleted file mode 100644 index 63b6f1e733..0000000000 --- a/Remapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 18 Nov 2020 11:32:46 -0800 -Subject: [PATCH] Zombie API - breaking doors - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 4105c1763d25824aac35d305a793823c1604eee8..77634a1e8e7539000f7db0b96f4548137af1a819 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -137,10 +137,12 @@ public class Zombie extends Monster { - return (Boolean) this.getEntityData().get(Zombie.DATA_DROWNED_CONVERSION_ID); - } - -+ public boolean canBreakDoors() { return this.canBreakDoors(); } // Paper - OBFHELPER - public boolean canBreakDoors() { - return this.canBreakDoors; - } - -+ public void setCanBreakDoors(boolean canBreakDoors) { this.setCanBreakDoors(canBreakDoors); } // Paper - OBFHELPER - public void setCanBreakDoors(boolean canBreakDoors) { - if (this.supportsBreakDoorGoal() && GoalUtils.hasGroundPathNavigation(this)) { - if (this.canBreakDoors != canBreakDoors) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 86f65c07806a118c49e900c59be86c2bd2eb124c..44f21b3b1c2f2fbc1f3f53931349b9a9426e97f8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -@@ -128,6 +128,16 @@ public class CraftZombie extends CraftMonster implements Zombie { - public void setShouldBurnInDay(boolean shouldBurnInDay) { - getHandle().setShouldBurnInDay(shouldBurnInDay); - } -+ -+ @Override -+ public boolean canBreakDoors() { -+ return getHandle().canBreakDoors(); -+ } -+ -+ @Override -+ public void setCanBreakDoors(boolean canBreakDoors) { -+ getHandle().setCanBreakDoors(canBreakDoors); -+ } - // Paper end - - @Override diff --git a/Remapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch b/Remapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch deleted file mode 100644 index 85d8576628..0000000000 --- a/Remapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 24 Aug 2020 08:39:06 -0700 -Subject: [PATCH] Fix nerfed slime when splitting - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java -index 120ceb28ee3aee8a09cf67b45ac95d3d6613c133..2f04543c1c0a197f22fb26b2a38c7c79e6b4a63a 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Slime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java -@@ -242,6 +242,7 @@ public class Slime extends Mob implements Enemy { - entityslime.setPersistenceRequired(); - } - -+ entityslime.aware = this.aware; // Paper - entityslime.setCustomName(ichatbasecomponent); - entityslime.setNoAi(flag); - entityslime.setInvulnerable(this.isInvulnerable()); diff --git a/Remapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch b/Remapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch deleted file mode 100644 index 6eea724442..0000000000 --- a/Remapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 7 Oct 2020 12:04:01 -0400 -Subject: [PATCH] Add EntityLoadCrossbowEvent - - -diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java -index e1e58b7035e6dbafdad0a04cc5333464fc4febb8..32e927375daeaf16f4ea763bc9f7c4a244797bba 100644 ---- a/src/main/java/net/minecraft/world/item/CrossbowItem.java -+++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java -@@ -3,6 +3,8 @@ package net.minecraft.world.item; - import com.google.common.collect.Lists; - import com.mojang.math.Quaternion; - import com.mojang.math.Vector3f; -+import org.bukkit.inventory.EquipmentSlot; // Paper -+import io.papermc.paper.event.entity.EntityLoadCrossbowEvent; // Paper - EntityLoadCrossbowEvent namespace conflicts - import java.util.List; - import java.util.Random; - import java.util.function.Predicate; -@@ -73,7 +75,11 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { - int j = this.getUseDuration(stack) - remainingUseTicks; - float f = getPowerForTime(j, stack); - -- if (f >= 1.0F && !isCharged(stack) && tryLoadProjectiles(user, stack)) { -+ // Paper start - EntityLoadCrossbowEvent -+ if (f >= 1.0F && !isCharged(stack) /*&& a(entityliving, itemstack)*/) { -+ final EntityLoadCrossbowEvent event = new EntityLoadCrossbowEvent(user.getBukkitLivingEntity(), stack.asBukkitMirror(), user.getUsedItemHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND); -+ if (!event.callEvent() || !attemptProjectileLoad(user, stack, event.shouldConsumeItem())) return; -+ // Paper end - setCharged(stack, true); - SoundSource soundcategory = user instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE; - -@@ -82,11 +88,14 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { - - } - -- private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack projectile) { -- int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, projectile); -+ private static boolean attemptProjectileLoad(LivingEntity ent, ItemStack bow) { return tryLoadProjectiles(ent, bow); } // Paper - EntityLoadCrossbowEvent - OBFHELPER -+ private static boolean attemptProjectileLoad(LivingEntity ent, ItemStack bow, boolean consume) { return a(ent, bow, consume); } // Paper - EntityLoadCrossbowEvent - OBFHELPER -+ private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack projectile) { return a(shooter, projectile, true); };// Paper - add consume -+ private static boolean a(LivingEntity entityliving, ItemStack itemstack, boolean consume) { // Paper - add consume -+ int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, itemstack); - int j = i == 0 ? 1 : 3; -- boolean flag = shooter instanceof Player && ((Player) shooter).abilities.instabuild; -- ItemStack itemstack1 = shooter.getProjectile(projectile); -+ boolean flag = !consume || entityliving instanceof Player && ((Player) entityliving).abilities.instabuild; // Paper - add consme -+ ItemStack itemstack1 = entityliving.getProjectile(itemstack); - ItemStack itemstack2 = itemstack1.copy(); - - for (int k = 0; k < j; ++k) { -@@ -103,7 +112,7 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { - // CraftBukkit end - } - -- if (!loadProjectile(shooter, projectile, itemstack1, k > 0, flag)) { -+ if (!loadProjectile(entityliving, itemstack, itemstack1, k > 0, flag)) { - return false; - } - } diff --git a/Remapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch b/Remapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch deleted file mode 100644 index c16b905697..0000000000 --- a/Remapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabscap -Date: Sat, 19 Mar 2016 22:25:11 +0100 -Subject: [PATCH] Guardian beam workaround - -This patch is a workaround for MC-165595 - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java -index a02f492c279f4e859b44d52e150a2990cbe8275a..4f177e7396db00db56f2106068fc02b9c2618407 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java -@@ -6,7 +6,7 @@ import net.minecraft.network.protocol.Packet; - - public class ClientboundSetTimePacket implements Packet { - -- private long gameTime; -+ private long gameTime; private final void setWorldAge(final long age) { this.gameTime = age; } private final long getWorldAge() { return this.gameTime; } // Paper - OBFHELPER - private long dayTime; - - public ClientboundSetTimePacket() {} -@@ -21,6 +21,9 @@ public class ClientboundSetTimePacket implements Packet -Date: Sun, 20 Dec 2020 16:41:44 -0800 -Subject: [PATCH] Added WorldGameRuleChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java -index 87b968019fa10647522121c7b29094ed3e0dcf6d..7f124784dd7876cdb26f16e83deddf07dd9a198e 100644 ---- a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java -+++ b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java -@@ -31,7 +31,7 @@ public class GameRuleCommand { - CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); - T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(key); // CraftBukkit - -- t0.setFromArgument(context, "value"); -+ t0.setValue(context, "value", key); // Paper - commandlistenerwrapper.sendSuccess(new TranslatableComponent("commands.gamerule.set", new Object[]{key.getId(), t0.toString()}), true); - return t0.getCommandResult(); - } -diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java -index 6c996d34ef34879db1d65c39adf99ce2d64e5499..1e6f299571a25729dbf8c5b0cd115c1e842a8a3c 100644 ---- a/src/main/java/net/minecraft/world/level/GameRules.java -+++ b/src/main/java/net/minecraft/world/level/GameRules.java -@@ -25,6 +25,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerPlayer; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.event.world.WorldGameRuleChangeEvent; // Paper - - public class GameRules { - -@@ -177,8 +178,11 @@ public class GameRules { - } - - @Override -- protected void updateFromArgument(CommandContext context, String name) { -- this.value = BoolArgumentType.getBool(context, name); -+ protected void a(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { // Paper start -+ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(commandcontext, s))); -+ if (!event.callEvent()) return; -+ this.value = Boolean.parseBoolean(event.getValue()); -+ // Paper end - } - - public boolean get() { -@@ -237,8 +241,11 @@ public class GameRules { - } - - @Override -- protected void updateFromArgument(CommandContext context, String name) { -- this.value = IntegerArgumentType.getInteger(context, name); -+ protected void a(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { // Paper start -+ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(commandcontext, s))); -+ if (!event.callEvent()) return; -+ this.value = Integer.parseInt(event.getValue()); -+ // Paper end - } - - public int get() { -@@ -291,11 +298,13 @@ public class GameRules { - this.type = type; - } - -- protected abstract void updateFromArgument(CommandContext context, String name); -+ protected void updateValue(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { this.a(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER -+ protected abstract void a(CommandContext commandcontext, String s, GameRules.Key gameRuleKey); // Paper - -- public void setFromArgument(CommandContext context, String name) { -- this.updateFromArgument(context, name); -- this.onChanged(((CommandSourceStack) context.getSource()).getServer()); -+ public void setValue(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { this.b(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER -+ public void b(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { // Paper -+ this.updateValue(commandcontext, s, gameRuleKey); // Paper -+ this.onChanged(((CommandSourceStack) commandcontext.getSource()).getServer()); - } - - public void onChanged(@Nullable MinecraftServer server) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index aaf97c13babce3b0ffc639ef950d59d1eba1398a..f497b9e11a075a84ff0a2117eb79d0532e4a326f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2345,8 +2345,13 @@ public class CraftWorld implements World { - - if (!isGameRule(rule)) return false; - -+ // Paper start -+ GameRule gameRule = GameRule.getByName(rule); -+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, gameRule, value); -+ if (!event.callEvent()) return false; -+ // Paper end - GameRules.Value handle = getHandle().getGameRules().getRule(getGameRulesNMS().get(rule)); -- handle.deserialize(value); -+ handle.deserialize(event.getValue().toString()); // Paper - handle.onChanged(getHandle().getServer()); - return true; - } -@@ -2381,8 +2386,12 @@ public class CraftWorld implements World { - - if (!isGameRule(rule.getName())) return false; - -+ // Paper start -+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, rule, String.valueOf(newValue)); -+ if (!event.callEvent()) return false; -+ // Paper end - GameRules.Value handle = getHandle().getGameRules().getRule(getGameRulesNMS().get(rule.getName())); -- handle.deserialize(newValue.toString()); -+ handle.deserialize(event.getValue().toString()); // Paper - handle.onChanged(getHandle().getServer()); - return true; - } diff --git a/Remapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch b/Remapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch deleted file mode 100644 index 02aef6be64..0000000000 --- a/Remapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Dec 2020 20:04:01 -0800 -Subject: [PATCH] Added ServerResourcesReloadedEvent - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index c83f2636ae93d92381e019d5b13ac82c5a1d30bf..892ca65d258b0745be95d7ef4886c49899b24d92 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2,9 +2,6 @@ package net.minecraft.server; - - import com.google.common.base.Splitter; - import com.google.common.collect.ImmutableList; --import co.aikar.timings.Timings; --import com.destroystokyo.paper.event.server.PaperServerListPingEvent; --import com.google.common.base.Stopwatch; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -181,6 +178,7 @@ import org.bukkit.event.server.ServerLoadEvent; - import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot - import io.papermc.paper.util.PaperJvmChecker; // Paper -+import io.papermc.paper.event.server.ServerResourcesReloadedEvent; // Paper - - public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { - -@@ -1934,9 +1932,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop reloadResources(Collection datapacks) { -+ return this.reloadServerResources(datapacks, ServerResourcesReloadedEvent.Cause.PLUGIN); -+ } -+ public CompletableFuture reloadServerResources(Collection collection, ServerResourcesReloadedEvent.Cause cause) { -+ // Paper end - CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { -- Stream stream = datapacks.stream(); // CraftBukkit - decompile error -+ Stream stream = collection.stream(); // CraftBukkit - decompile error - PackRepository resourcepackrepository = this.packRepository; - - this.packRepository.getClass(); -@@ -1947,9 +1951,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop collection, CommandSourceStack commandlistenerwrapper) { -- commandlistenerwrapper.getServer().reloadResources(collection).exceptionally((throwable) -> { -- ReloadCommand.LOGGER.warn("Failed to execute reload", throwable); -- commandlistenerwrapper.sendFailure(new TranslatableComponent("commands.reload.failure")); -+ commandlistenerwrapper.getServer().reloadServerResources(collection, ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally((throwable) -> { // Paper -+ CommandReload.LOGGER.warn("Failed to execute reload", throwable); -+ commandlistenerwrapper.sendFailureMessage(new ChatMessage("commands.reload.failure")); - return null; - }); - } -@@ -48,7 +49,7 @@ public class ReloadCommand { - WorldData savedata = minecraftserver.getWorldData(); - Collection collection = resourcepackrepository.getSelectedIds(); - Collection collection1 = discoverNewPacks(resourcepackrepository, savedata, collection); -- minecraftserver.reloadResources(collection1); -+ minecraftserver.reloadServerResources(collection1, ServerResourcesReloadedEvent.Cause.PLUGIN); // Paper - } - // CraftBukkit end - diff --git a/Remapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch b/Remapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch deleted file mode 100644 index ead34bbc60..0000000000 --- a/Remapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 28 Nov 2020 18:43:52 -0800 -Subject: [PATCH] Added world settings for mobs picking up loot - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b48067c71f9de18ba40e970e2832f6245984a218..23a23e2ea133ce81d3dedc4ffd17435a995497ef 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -363,6 +363,14 @@ public class PaperWorldConfig { - log("Creeper lingering effect: " + disableCreeperLingeringEffect); - } - -+ public boolean zombiesAlwaysCanPickUpLoot; -+ public boolean skeletonsAlwaysCanPickUpLoot; -+ private void setMobsAlwaysCanPickUpLoot() { -+ zombiesAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.zombies", false); -+ skeletonsAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.skeletons", false); -+ log("Zombies can always pick up loot: " + zombiesAlwaysCanPickUpLoot + ". Skeletons can always pick up loot: " + skeletonsAlwaysCanPickUpLoot + "."); -+ } -+ - public int expMergeMaxValue; - private void expMergeMaxValue() { - expMergeMaxValue = getInt("experience-merge-max-value", -1); -diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -index 76027a7c9615495af64102744e264d7ba7c9b87e..68e52e3a31e70569d1a92602aff4b7b81c594757 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -+++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -@@ -149,7 +149,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo - this.populateDefaultEquipmentSlots(difficulty); - this.populateDefaultEquipmentEnchantments(difficulty); - this.reassessWeaponGoal(); -- this.setCanPickUpLoot(this.random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); -+ this.setCanPickUpLoot(this.level.paperConfig.skeletonsAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper - if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { - LocalDate localdate = LocalDate.now(); - int i = localdate.get(ChronoField.DAY_OF_MONTH); -diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 77634a1e8e7539000f7db0b96f4548137af1a819..74fd175c4dc2d0d9832ee41efaf065b75a43f4b8 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -494,7 +494,7 @@ public class Zombie extends Monster { - Object object = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag); - float f = difficulty.getSpecialMultiplier(); - -- this.setCanPickUpLoot(this.random.nextFloat() < 0.55F * f); -+ this.setCanPickUpLoot(this.level.paperConfig.zombiesAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * f); // Paper - if (object == null) { - object = new Zombie.ZombieGroupData(getSpawnAsBabyOdds(world.getRandom()), true); - } diff --git a/Remapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch b/Remapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch deleted file mode 100644 index a7a4e49910..0000000000 --- a/Remapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheViperShow <29604693+TheViperShow@users.noreply.github.com> -Date: Wed, 22 Apr 2020 09:40:38 +0200 -Subject: [PATCH] Implemented BlockFailedDispenseEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -index bfb2e21ccbcc67d6c9b4b329db1949d7d938bd2e..2a4cb76bdfcf55ba222b4976359c1b8efb165009 100644 ---- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -@@ -81,6 +81,7 @@ public class DispenserBlock extends BaseEntityBlock { - int i = tileentitydispenser.getRandomSlot(); - - if (i < 0) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, pos)) // Paper - BlockFailedDispenseEvent is called here - worldserver.levelEvent(1001, pos, 0); - } else { - ItemStack itemstack = tileentitydispenser.getItem(i); -diff --git a/src/main/java/net/minecraft/world/level/block/DropperBlock.java b/src/main/java/net/minecraft/world/level/block/DropperBlock.java -index 154ec671e9d741e536464b794783da859e8447c1..492b19b94e2e2439f72ed9478d75641b0f50451a 100644 ---- a/src/main/java/net/minecraft/world/level/block/DropperBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/DropperBlock.java -@@ -45,6 +45,7 @@ public class DropperBlock extends DispenserBlock { - int i = tileentitydispenser.getRandomSlot(); - - if (i < 0) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, pos)) // Paper - BlockFailedDispenseEvent is called here - worldserver.levelEvent(1001, pos, 0); - } 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 34c7b1213b3f83ff1a1f2d606a9c25e57fea8ef3..8829ef03d0be16d8317aaf05bcd286b74f20656a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -4,6 +4,7 @@ import com.google.common.base.Function; - import com.google.common.base.Functions; - import com.google.common.collect.Lists; - import com.mojang.datafixers.util.Either; -+import io.papermc.paper.event.block.BlockFailedDispenseEvent; - import java.net.InetAddress; - import java.util.ArrayList; - import java.util.Collections; -@@ -111,7 +112,6 @@ import org.bukkit.entity.ThrownPotion; - import org.bukkit.entity.Vehicle; - import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; --import org.bukkit.entity.ExperienceOrb; // Paper - import org.bukkit.event.Cancellable; - import org.bukkit.event.Event; - import org.bukkit.event.Event.Result; -@@ -1784,4 +1784,12 @@ public class CraftEventFactory { - Bukkit.getPluginManager().callEvent(event); - return event; - } -+ -+ // Paper start -+ public static boolean handleBlockFailedDispenseEvent(ServerLevel worldserver, BlockPos blockposition) { -+ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); -+ return event.callEvent(); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch b/Remapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch deleted file mode 100644 index b4eacbfa37..0000000000 --- a/Remapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 23 Nov 2020 12:58:51 -0800 -Subject: [PATCH] Added PlayerLecternPageChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -index bc39e7464646d712b085251dc0277a5b1ec0a393..b5d79635cd8b0eb6b17962450b347010aeb52654 100644 ---- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -561,6 +561,7 @@ public abstract class AbstractContainerMenu { - this.getSlot(slot).set(stack); - } - -+ public void setData(int index, int value) { this.setData(index, value); } // Paper - OBFHELPER - public void setData(int id, int value) { - ((DataSlot) this.dataSlots.get(id)).set(value); - } -diff --git a/src/main/java/net/minecraft/world/inventory/LecternMenu.java b/src/main/java/net/minecraft/world/inventory/LecternMenu.java -index 29e8dbc6be57faf50a8ca68eed6bf2e203b7e87a..a7be91a9336065899c409526a890e55f37b98751 100644 ---- a/src/main/java/net/minecraft/world/inventory/LecternMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/LecternMenu.java -@@ -11,6 +11,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - import org.bukkit.event.player.PlayerTakeLecternBookEvent; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerLecternPageChangeEvent; // Paper - - public class LecternMenu extends AbstractContainerMenu { - -@@ -58,6 +59,7 @@ public class LecternMenu extends AbstractContainerMenu { - @Override - public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { - int j; -+ PlayerLecternPageChangeEvent playerLecternPageChangeEvent; CraftInventoryLectern bukkitView; // Paper - - if (id >= 100) { - j = id - 100; -@@ -67,11 +69,25 @@ public class LecternMenu extends AbstractContainerMenu { - switch (id) { - case 1: - j = this.lecternData.get(0); -- this.setData(0, j - 1); -+ // Paper start -+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); -+ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, j, j - 1); -+ if (!playerLecternPageChangeEvent.callEvent()) { -+ return false; -+ } -+ this.setData(0, playerLecternPageChangeEvent.getNewPage()); -+ // Paper end - return true; - case 2: - j = this.lecternData.get(0); -- this.setData(0, j + 1); -+ // Paper start -+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); -+ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, j, j + 1); -+ if (!playerLecternPageChangeEvent.callEvent()) { -+ return false; -+ } -+ this.setData(0, playerLecternPageChangeEvent.getNewPage()); -+ // Paper end - return true; - case 3: - if (!player.mayBuild()) { diff --git a/Remapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch b/Remapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch deleted file mode 100644 index a893ed5f5c..0000000000 --- a/Remapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch +++ /dev/null @@ -1,265 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 17 Mar 2019 21:46:56 +0200 -Subject: [PATCH] Fire event on GS4 query - - -diff --git a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java -index d10de580430d754204b36de809376538a14591e6..f6f0539a8e6edbeb1c412cee753a282b24a38046 100644 ---- a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java -+++ b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java -@@ -18,15 +18,27 @@ public class NetworkDataOutputStream { - this.dataOutputStream.write(abyte, 0, abyte.length); - } - -+ public void writeString(String string) throws IOException { this.writeString(string); } // Paper - OBFHELPER - public void writeString(String s) throws IOException { - this.dataOutputStream.writeBytes(s); - this.dataOutputStream.write(0); - } -+ // Paper start - unchecked exception variant to use in Stream API -+ public void writeStringUnchecked(String string) { -+ try { -+ writeString(string); -+ } catch (IOException e) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(e); -+ } -+ } -+ // Paper end - -+ public void writeInt(int i) throws IOException { this.write(i); } // Paper - OBFHELPER - public void write(int i) throws IOException { - this.dataOutputStream.write(i); - } - -+ public void writeShort(short i) throws IOException { this.writeShort(i); } // Paper - OBFHELPER - public void writeShort(short short0) throws IOException { - this.dataOutputStream.writeShort(Short.reverseBytes(short0)); - } -diff --git a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java -index 170d047463154bd6851199f06fe343ccb1896213..5562a3caff328bb08857b4f06a79b1e52f390fdd 100644 ---- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java -+++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java -@@ -16,6 +16,7 @@ import java.util.Random; - import javax.annotation.Nullable; - import net.minecraft.Util; - import net.minecraft.server.ServerInterface; -+import net.minecraft.server.dedicated.DedicatedServer; - import net.minecraft.server.rcon.NetworkDataOutputStream; - import net.minecraft.server.rcon.PktUtils; - import org.apache.logging.log4j.LogManager; -@@ -26,18 +27,18 @@ public class QueryThreadGs4 extends GenericThread { - private static final Logger LOGGER = LogManager.getLogger(); - private long lastChallengeCheck; - private final int port; -- private final int serverPort; -- private final int maxPlayers; -- private final String serverName; -- private final String worldName; -+ private final int serverPort; private final int getServerPort() { return this.serverPort; } // Paper - OBFHELPER -+ private final int maxPlayers; private final int getMaxPlayers() { return this.maxPlayers; } // Paper - OBFHELPER -+ private final String serverName; private final String getMotd() { return this.serverName; } // Paper - OBFHELPER -+ private final String worldName; private final String getWorldName() { return this.worldName; } // Paper - OBFHELPER - private DatagramSocket socket; - private final byte[] buffer = new byte[1460]; -- private String hostIp; -+ private String hostIp; public final String getServerHost() { return this.hostIp; } // Paper - OBFHELPER - private String serverIp; - private final Map validChallenges; -- private final NetworkDataOutputStream rulesResponse; -+ private final NetworkDataOutputStream rulesResponse; private final NetworkDataOutputStream getCachedFullResponse() { return this.rulesResponse; } // Paper - OBFHELPER - private long lastRulesResponse; -- private final ServerInterface serverInterface; -+ private final ServerInterface serverInterface; private final ServerInterface getServer() { return this.serverInterface; } // Paper - OBFHELPER - - private QueryThreadGs4(ServerInterface server, int queryPort) { - super("Query Listener"); -@@ -107,13 +108,39 @@ public class QueryThreadGs4 extends GenericThread { - - remotestatusreply.write((int) 0); - remotestatusreply.writeBytes(this.getIdentBytes(packet.getSocketAddress())); -- remotestatusreply.writeString(this.serverName); -+ /* Paper start - GS4 Query event -+ remotestatusreply.a(this.i); -+ remotestatusreply.a("SMP"); -+ remotestatusreply.a(this.j); -+ remotestatusreply.a(Integer.toString(this.r.getPlayerCount())); -+ remotestatusreply.a(Integer.toString(this.h)); -+ remotestatusreply.a((short) this.g); -+ remotestatusreply.a(this.m); -+ */ -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.BASIC; -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() -+ .motd(this.getMotd()) -+ .map(this.getWorldName()) -+ .currentPlayers(this.getServer().getPlayerCount()) -+ .maxPlayers(this.getMaxPlayers()) -+ .port(this.getServerPort()) -+ .hostname(this.getServerHost()) -+ .gameVersion(this.getServer().getServerVersion()) -+ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) -+ .build(); -+ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = -+ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, packet.getAddress(), queryResponse); -+ queryEvent.callEvent(); -+ queryResponse = queryEvent.getResponse(); -+ remotestatusreply.writeString(queryResponse.getMotd()); - remotestatusreply.writeString("SMP"); -- remotestatusreply.writeString(this.worldName); -- remotestatusreply.writeString(Integer.toString(this.serverInterface.getPlayerCount())); -- remotestatusreply.writeString(Integer.toString(this.maxPlayers)); -- remotestatusreply.writeShort((short) this.serverPort); -- remotestatusreply.writeString(this.hostIp); -+ remotestatusreply.writeString(queryResponse.getMap()); -+ remotestatusreply.writeString(Integer.toString(queryResponse.getCurrentPlayers())); -+ remotestatusreply.writeString(Integer.toString(queryResponse.getMaxPlayers())); -+ remotestatusreply.writeShort((short) queryResponse.getPort()); -+ remotestatusreply.writeString(queryResponse.getHostname()); -+ // Paper end - this.sendTo(remotestatusreply.toByteArray(), packet); - QueryThreadGs4.LOGGER.debug("Status [{}]", socketaddress); - } -@@ -150,41 +177,115 @@ public class QueryThreadGs4 extends GenericThread { - this.rulesResponse.writeString("splitnum"); - this.rulesResponse.write((int) 128); - this.rulesResponse.write((int) 0); -- this.rulesResponse.writeString("hostname"); -- this.rulesResponse.writeString(this.serverName); -- this.rulesResponse.writeString("gametype"); -- this.rulesResponse.writeString("SMP"); -- this.rulesResponse.writeString("game_id"); -- this.rulesResponse.writeString("MINECRAFT"); -- this.rulesResponse.writeString("version"); -- this.rulesResponse.writeString(this.serverInterface.getServerVersion()); -- this.rulesResponse.writeString("plugins"); -- this.rulesResponse.writeString(this.serverInterface.getPluginNames()); -- this.rulesResponse.writeString("map"); -- this.rulesResponse.writeString(this.worldName); -- this.rulesResponse.writeString("numplayers"); -- this.rulesResponse.writeString("" + this.serverInterface.getPlayerCount()); -- this.rulesResponse.writeString("maxplayers"); -- this.rulesResponse.writeString("" + this.maxPlayers); -- this.rulesResponse.writeString("hostport"); -- this.rulesResponse.writeString("" + this.serverPort); -- this.rulesResponse.writeString("hostip"); -- this.rulesResponse.writeString(this.hostIp); -- this.rulesResponse.write((int) 0); -- this.rulesResponse.write((int) 1); -- this.rulesResponse.writeString("player_"); -- this.rulesResponse.write((int) 0); -- String[] astring = this.serverInterface.getPlayerNames(); -+ /* Paper start - GS4 Query event -+ this.p.a("hostname"); -+ this.p.a(this.i); -+ this.p.a("gametype"); -+ this.p.a("SMP"); -+ this.p.a("game_id"); -+ this.p.a("MINECRAFT"); -+ this.p.a("version"); -+ this.p.a(this.r.getVersion()); -+ this.p.a("plugins"); -+ this.p.a(this.r.getPlugins()); -+ this.p.a("map"); -+ this.p.a(this.j); -+ this.p.a("numplayers"); -+ this.p.a("" + this.r.getPlayerCount()); -+ this.p.a("maxplayers"); -+ this.p.a("" + this.h); -+ this.p.a("hostport"); -+ this.p.a("" + this.g); -+ this.p.a("hostip"); -+ this.p.a(this.m); -+ this.p.a((int) 0); -+ this.p.a((int) 1); -+ this.p.a("player_"); -+ this.p.a((int) 0); -+ String[] astring = this.r.getPlayers(); - String[] astring1 = astring; - int j = astring.length; - - for (int k = 0; k < j; ++k) { - String s = astring1[k]; - -- this.rulesResponse.writeString(s); -+ this.p.a(s); - } - -- this.rulesResponse.write((int) 0); -+ this.p.a((int) 0); -+ */ -+ // Pack plugins -+ java.util.List plugins = java.util.Collections.emptyList(); -+ org.bukkit.plugin.Plugin[] bukkitPlugins; -+ if (((DedicatedServer) this.getServer()).server.getQueryPlugins() && (bukkitPlugins = org.bukkit.Bukkit.getPluginManager().getPlugins()).length > 0) { -+ plugins = java.util.stream.Stream.of(bukkitPlugins) -+ .map(plugin -> com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation.of(plugin.getName(), plugin.getDescription().getVersion())) -+ .collect(java.util.stream.Collectors.toList()); -+ } -+ -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() -+ .motd(this.getMotd()) -+ .map(this.getWorldName()) -+ .currentPlayers(this.getServer().getPlayerCount()) -+ .maxPlayers(this.getMaxPlayers()) -+ .port(this.getServerPort()) -+ .hostname(this.getServerHost()) -+ .plugins(plugins) -+ .players(this.getServer().getPlayerNames()) -+ .gameVersion(this.getServer().getServerVersion()) -+ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) -+ .build(); -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.FULL; -+ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = -+ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, packet.getAddress(), queryResponse); -+ queryEvent.callEvent(); -+ queryResponse = queryEvent.getResponse(); -+ this.getCachedFullResponse().writeString("hostname"); -+ this.getCachedFullResponse().writeString(queryResponse.getMotd()); -+ this.getCachedFullResponse().writeString("gametype"); -+ this.getCachedFullResponse().writeString("SMP"); -+ this.getCachedFullResponse().writeString("game_id"); -+ this.getCachedFullResponse().writeString("MINECRAFT"); -+ this.getCachedFullResponse().writeString("version"); -+ this.getCachedFullResponse().writeString(queryResponse.getGameVersion()); -+ this.getCachedFullResponse().writeString("plugins"); -+ java.lang.StringBuilder pluginsString = new java.lang.StringBuilder(); -+ pluginsString.append(queryResponse.getServerVersion()); -+ if (!queryResponse.getPlugins().isEmpty()) { -+ pluginsString.append(": "); -+ java.util.Iterator iter = queryResponse.getPlugins().iterator(); -+ while (iter.hasNext()) { -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation info = iter.next(); -+ pluginsString.append(info.getName()); -+ if (info.getVersion() != null) { -+ pluginsString.append(' ').append(info.getVersion().replace(";", ",")); -+ } -+ if (iter.hasNext()) { -+ pluginsString.append(';').append(' '); -+ } -+ } -+ } -+ this.getCachedFullResponse().writeString(pluginsString.toString()); -+ this.getCachedFullResponse().writeString("map"); -+ this.getCachedFullResponse().writeString(queryResponse.getMap()); -+ this.getCachedFullResponse().writeString("numplayers"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getCurrentPlayers())); -+ this.getCachedFullResponse().writeString("maxplayers"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getMaxPlayers())); -+ this.getCachedFullResponse().writeString("hostport"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getPort())); -+ this.getCachedFullResponse().writeString("hostip"); -+ this.getCachedFullResponse().writeString(queryResponse.getHostname()); -+ // The "meaningless data" start, copied from above -+ this.getCachedFullResponse().writeInt(0); -+ this.getCachedFullResponse().writeInt(1); -+ this.getCachedFullResponse().writeString("player_"); -+ this.getCachedFullResponse().writeInt(0); -+ // "Meaningless data" end -+ queryResponse.getPlayers().forEach(this.getCachedFullResponse()::writeStringUnchecked); -+ this.getCachedFullResponse().writeInt(0); -+ // Paper end - return this.rulesResponse.toByteArray(); - } - } diff --git a/Remapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch b/Remapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch deleted file mode 100644 index 3c2cf5afe6..0000000000 --- a/Remapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 25 Nov 2020 16:33:27 -0800 -Subject: [PATCH] Added PlayerLoomPatternSelectEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java -index 3460fb2bb1451b8456a7fe42449ec4dbce641f40..0dc1b0b7181c0f93dcf6213c63baffcd4694d70c 100644 ---- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java -@@ -20,6 +20,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerLoomPatternSelectEvent; // Paper - - public class LoomMenu extends AbstractContainerMenu { - -@@ -39,7 +40,7 @@ public class LoomMenu extends AbstractContainerMenu { - } - // CraftBukkit end - private final ContainerLevelAccess access; -- private final DataSlot selectedBannerPatternIndex; -+ private final DataSlot selectedBannerPatternIndex; public final DataSlot getSelectedBannerPattern() { return this.selectedBannerPatternIndex; }; // Paper - OBFHELPER - private Runnable slotUpdateListener; - private final Slot bannerSlot; - private final Slot dyeSlot; -@@ -158,7 +159,22 @@ public class LoomMenu extends AbstractContainerMenu { - @Override - public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { - if (id > 0 && id <= BannerPattern.AVAILABLE_PATTERNS) { -- this.selectedBannerPatternIndex.set(id); -+ // Paper start -+ int enumBannerPatternTypeOrdinal = id; -+ PlayerLoomPatternSelectEvent event = new PlayerLoomPatternSelectEvent((Player) player.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.block.banner.PatternType.getByIdentifier(BannerPattern.values()[id].getIdentifier())); -+ if (!event.callEvent()) { -+ ((Player) player.getBukkitEntity()).updateInventory(); -+ return false; -+ } -+ for (BannerPattern nms : BannerPattern.values()) { -+ if (event.getPatternType().getIdentifier().equals(nms.getIdentifier())) { -+ enumBannerPatternTypeOrdinal = nms.ordinal(); -+ break; -+ } -+ } -+ ((Player) player.getBukkitEntity()).updateInventory(); -+ this.getSelectedBannerPattern().set(enumBannerPatternTypeOrdinal); -+ // Paper end - this.setupResultSlot(); - return true; - } else { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java b/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java -index 9ea01d5888a21b0dedb555d118a4dc07af2b50fd..9ee3f8bb2294fc552735a64efbddf661d39602c7 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java -@@ -33,6 +33,7 @@ public enum BannerPattern { - this.hasPatternItem = flag; - } - -+ public String getIdentifier() { return this.getHashname(); } // Paper - OBFHELPER - public String getHashname() { - return this.hashname; - } diff --git a/Remapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch b/Remapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch deleted file mode 100644 index c1c84edf4d..0000000000 --- a/Remapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 22:27:43 -0800 -Subject: [PATCH] Configurable door breaking difficulty - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 23a23e2ea133ce81d3dedc4ffd17435a995497ef..7ebc85264a2cbfb601dfe5472b561cac1a7cf8bf 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -5,7 +5,10 @@ import java.util.EnumMap; - import java.util.HashMap; - import java.util.List; - import java.util.Map; -- -+import java.util.stream.Collectors; -+import net.minecraft.world.Difficulty; -+import net.minecraft.world.entity.monster.Vindicator; -+import net.minecraft.world.entity.monster.Zombie; - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; - import org.bukkit.Bukkit; - import org.bukkit.Material; -@@ -73,6 +76,11 @@ public class PaperWorldConfig { - return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); - } - -+ private > List getEnumList(String path, List def, Class type) { -+ config.addDefault("world-settings.default." + path, def.stream().map(Enum::name).collect(Collectors.toList())); -+ return ((List) (config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)))).stream().map(s -> Enum.valueOf(type, s)).collect(Collectors.toList()); -+ } -+ - public int cactusMaxHeight; - public int reedMaxHeight; - public int bambooMaxHeight; -@@ -735,4 +743,23 @@ public class PaperWorldConfig { - private void disableMobSpawnerSpawnEggTransformation() { - disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); - } -+ -+ public List zombieBreakDoors; -+ public List vindicatorBreakDoors; -+ private void setupEntityBreakingDoors() { -+ zombieBreakDoors = getEnumList( -+ "door-breaking-difficulty.zombie", -+ Arrays.stream(Difficulty.values()) -+ .filter(Zombie.getDoorBreakingPredicate()) -+ .collect(Collectors.toList()), -+ Difficulty.class -+ ); -+ vindicatorBreakDoors = getEnumList( -+ "door-breaking-difficulty.vindicator", -+ Arrays.stream(Difficulty.values()) -+ .filter(Vindicator.getDoorBreakingPredicate()) -+ .collect(Collectors.toList()), -+ Difficulty.class -+ ); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -index 623de661f3b56062792e3a7dbc508637aa58aca5..48700094da6e97610ccc652593a9e229ba7b1003 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -@@ -48,6 +48,7 @@ import net.minecraft.world.level.ServerLevelAccessor; - - public class Vindicator extends AbstractIllager { - -+ public static final Predicate getDoorBreakingPredicate() { return DOOR_BREAKING_PREDICATE; } // Paper - OBFHELPER - private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { - return enumdifficulty == Difficulty.NORMAL || enumdifficulty == Difficulty.HARD; - }; -@@ -204,7 +205,7 @@ public class Vindicator extends AbstractIllager { - static class VindicatorBreakDoorGoal extends BreakDoorGoal { - - public VindicatorBreakDoorGoal(Mob mob) { -- super(mob, 6, Vindicator.DOOR_BREAKING_PREDICATE); -+ super(mob, 6, com.google.common.base.Predicates.in(mob.level.paperConfig.vindicatorBreakDoors)); // Paper - this.setFlags(EnumSet.of(Goal.Flag.MOVE)); - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 74fd175c4dc2d0d9832ee41efaf065b75a43f4b8..caa99a2737598bd74ede54f1c35ce4b99ce1e6d3 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -83,6 +83,7 @@ public class Zombie extends Monster { - private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); - private static final EntityDataAccessor DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT); - public static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); -+ public static final Predicate getDoorBreakingPredicate() { return DOOR_BREAKING_PREDICATE; } // Paper - OBFHELPER - private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { - return enumdifficulty == Difficulty.HARD; - }; -@@ -95,7 +96,7 @@ public class Zombie extends Monster { - - public Zombie(EntityType type, Level world) { - super(type, world); -- this.breakDoorGoal = new BreakDoorGoal(this, Zombie.DOOR_BREAKING_PREDICATE); -+ this.breakDoorGoal = new BreakDoorGoal(this, com.google.common.base.Predicates.in(world.paperConfig.zombieBreakDoors)); // Paper - } - - public Zombie(Level world) { diff --git a/Remapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch b/Remapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch deleted file mode 100644 index a9abc78c3f..0000000000 --- a/Remapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 6 Jan 2021 23:38:43 +0100 -Subject: [PATCH] Empty commands shall not be dispatched - - -diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java -index c63033e3eb50423a7c32acfc0e705623cc4bec68..5ed78383ce247ceb24cda0335dbeae293958055c 100644 ---- a/src/main/java/net/minecraft/commands/Commands.java -+++ b/src/main/java/net/minecraft/commands/Commands.java -@@ -223,6 +223,7 @@ public class Commands { - command = event.getCommand(); - - String[] args = command.split(" "); -+ if (args.length == 0) return 0; // Paper - empty commands shall not be dispatched - - String cmd = args[0]; - if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); diff --git a/Remapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch b/Remapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch deleted file mode 100644 index 4f115620e4..0000000000 --- a/Remapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Mon, 4 Jan 2021 16:40:27 +1000 -Subject: [PATCH] Implement API to expose exact interaction point - - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index 6269e37f2859417a80e6de16045f1c2325f9746f..37761176861027d0ee06f50d60584687fdac669b 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -495,7 +495,7 @@ public class ServerPlayerGameMode { - cancelledBlock = true; - } - -- PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand); -+ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand, hitResult.getLocation()); // Paper - firedInteract = true; - interactResult = event.useItemInHand() == Event.Result.DENY; - 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 8829ef03d0be16d8317aaf05bcd286b74f20656a..586d21eed8189adf696ca6d3642afebbe752d1b5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -58,7 +58,9 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams; - import net.minecraft.world.phys.BlockHitResult; - import net.minecraft.world.phys.EntityHitResult; - import net.minecraft.world.phys.HitResult; -+import net.minecraft.world.phys.Vec3; - import org.bukkit.Bukkit; -+import org.bukkit.Location; // Paper - import org.bukkit.Material; - import org.bukkit.NamespacedKey; - import org.bukkit.Server; -@@ -475,7 +477,13 @@ public class CraftEventFactory { - return callPlayerInteractEvent(who, action, position, direction, itemstack, false, hand); - } - -+ // Paper start - Add interactionPoint - public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, InteractionHand hand) { -+ return callPlayerInteractEvent(who, action, position, direction, itemstack, cancelledBlock, hand, null); -+ } -+ -+ public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, InteractionHand hand, Vec3 hitVec) { -+ // Paper end - Player player = (who == null) ? null : (Player) who.getBukkitEntity(); - CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack); - -@@ -501,7 +509,10 @@ public class CraftEventFactory { - itemInHand = null; - } - -- PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); -+ // Paper start -+ Location interactionPoint = hitVec == null ? null : new Location(craftWorld, hitVec.x, hitVec.y, hitVec.z); -+ PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND), interactionPoint); -+ // Paper end - if (cancelledBlock) { - event.setUseInteractedBlock(Event.Result.DENY); - } diff --git a/Remapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch b/Remapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch deleted file mode 100644 index 561ae57f81..0000000000 --- a/Remapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 9 Jan 2021 14:17:07 +0100 -Subject: [PATCH] Remove stale POIs - - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index fe7b71fbb3963beafe93a5d86bebdd629c7ec8f2..9f1838d12b13d64f10871eb672ed2aec78d9936e 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -2071,6 +2071,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - }); - optional1.ifPresent((villageplacetype) -> { - this.getServer().execute(() -> { -+ // Paper start -+ if (!optional.isPresent() && this.getPoiStorage().test(blockposition1, com.google.common.base.Predicates.alwaysTrue())) { -+ this.getPoiStorage().remove(blockposition1); -+ } -+ // Paper end - this.getPoiManager().add(blockposition1, villageplacetype); - DebugPackets.sendPoiAddedPacket(this, blockposition1); - }); -@@ -2078,6 +2083,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - } - -+ public final PoiManager getPoiStorage() { return this.getPoiManager(); } // Paper - OBFHELPER - public PoiManager getPoiManager() { - return this.getChunkSource().getPoiManager(); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -index b9d32e3322c2cce1aca2a90df71b6175a6f8c548..25b26a78a55f98687ed22e986b54d5e9d47a16ea 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -@@ -54,6 +54,7 @@ public class PoiManager extends SectionStorage { - ((PoiSection) this.getOrCreate(SectionPos.of(pos).asLong())).add(pos, type); - } - -+ public void remove(BlockPos blockposition) { this.remove(blockposition); } // Paper - OBFHELPER - public void remove(BlockPos pos) { - ((PoiSection) this.getOrCreate(SectionPos.of(pos).asLong())).remove(pos); - } -@@ -138,6 +139,7 @@ public class PoiManager extends SectionStorage { - return ((PoiSection) this.getOrCreate(SectionPos.of(pos).asLong())).release(pos); - } - -+ public final boolean test(BlockPos blockposition, Predicate predicate) { return this.exists(blockposition, predicate); } // Paper - OBFHELPER - public boolean exists(BlockPos pos, Predicate predicate) { - return (Boolean) this.getOrLoad(SectionPos.of(pos).asLong()).map((villageplacesection) -> { - return villageplacesection.exists(pos, predicate); diff --git a/Remapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch b/Remapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch deleted file mode 100644 index bc4c9d15d6..0000000000 --- a/Remapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Mon, 11 Jan 2021 12:43:51 -0800 -Subject: [PATCH] Fix villager boat exploit - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7e07fd0c8dec9f9cdeda65dfa0ccf42b4dde010e..9d1116f601b79dabf7a0d9e5ecf5c2a0306f9aa4 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -78,6 +78,7 @@ import net.minecraft.util.Mth; - import net.minecraft.world.effect.MobEffectInstance; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.entity.npc.AbstractVillager; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.GameType; -@@ -617,6 +618,15 @@ public abstract class PlayerList { - - for (Iterator iterator = entity.getIndirectPassengers().iterator(); iterator.hasNext(); entity1.removed = true) { - entity1 = (Entity) iterator.next(); -+ // Paper start -+ if (entity1 instanceof AbstractVillager) { -+ final AbstractVillager villager = (AbstractVillager) entity1; -+ final net.minecraft.world.entity.player.Player human = villager.getTradingPlayer(); -+ if (human != null) { -+ villager.setTradingPlayer(null); -+ } -+ } -+ // Paper end - worldserver.despawn(entity1); - } - diff --git a/Remapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch b/Remapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch deleted file mode 100644 index a9cb53ca69..0000000000 --- a/Remapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Wed, 18 Nov 2020 20:52:25 -0800 -Subject: [PATCH] Entity load/save limit per chunk - -Adds a config option to limit the number of entities saved and loaded -to a chunk. The default values of -1 disable the limit. Although -defaults are only included for certain entites, this allows setting -limits for any entity type. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7ebc85264a2cbfb601dfe5472b561cac1a7cf8bf..486e5438254348db68017228af131cba7defd637 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -7,6 +7,7 @@ import java.util.List; - import java.util.Map; - import java.util.stream.Collectors; - import net.minecraft.world.Difficulty; -+import net.minecraft.world.entity.EntityType; - import net.minecraft.world.entity.monster.Vindicator; - import net.minecraft.world.entity.monster.Zombie; - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; -@@ -762,4 +763,18 @@ public class PaperWorldConfig { - Difficulty.class - ); - } -+ -+ public Map, Integer> entityPerChunkSaveLimits = new HashMap<>(); -+ private void entityPerChunkSaveLimits() { -+ getInt("entity-per-chunk-save-limit.experience_orb", -1); -+ getInt("entity-per-chunk-save-limit.snowball", -1); -+ getInt("entity-per-chunk-save-limit.ender_pearl", -1); -+ getInt("entity-per-chunk-save-limit.arrow", -1); -+ EntityType.getEntityNameList().forEach(name -> { -+ final EntityType type = EntityType.getByName(name.getPath()).orElseThrow(() -> new IllegalStateException("Unknown Entity Type: " + name.toString())); -+ final String path = ".entity-per-chunk-save-limit." + name.getPath(); -+ final int value = config.getInt("world-settings." + worldName + path, config.getInt("world-settings.default" + path, -1)); // get without setting defaults -+ if (value != -1) entityPerChunkSaveLimits.put(type, value); -+ }); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index f6a814f9305813eaafa56baa0327e0111cd4e38c..30f80f8549c3236d6bfe594e323e4ca6e702005d 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -539,11 +539,22 @@ public class ChunkSerializer { - - chunk.setLastSaveHadEntities(false); - -+ // Paper start -+ final Map, Integer> savedEntityCounts = Maps.newHashMap(); - for (int j = 0; j < chunk.getEntitySlices().length; ++j) { - Iterator iterator1 = chunk.getEntitySlices()[j].iterator(); - - while (iterator1.hasNext()) { - Entity entity = (Entity) iterator1.next(); -+ final EntityType entityType = entity.getType(); -+ final int saveLimit = worldserver.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); -+ if (saveLimit > -1) { -+ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { -+ continue; -+ } -+ savedEntityCounts.merge(entityType, 1, Integer::sum); -+ } -+ // Paper end - CompoundTag nbttagcompound4 = new CompoundTag(); - // Paper start - if (asyncsavedata == null && !entity.removed && (int) Math.floor(entity.getX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk.getPos().z) { -@@ -674,10 +685,21 @@ public class ChunkSerializer { - ListTag nbttaglist = tag.getList("Entities", 10); - Level world = chunk.getLevel(); - -+ // Paper start -+ final Map, Integer> loadedEntityCounts = Maps.newHashMap(); - for (int i = 0; i < nbttaglist.size(); ++i) { - CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); - - EntityType.loadEntityRecursive(nbttagcompound1, world, (entity) -> { -+ final EntityType entityType = entity.getType(); -+ final int saveLimit = world.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); -+ if (saveLimit > -1) { -+ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { -+ return null; -+ } -+ loadedEntityCounts.merge(entityType, 1, Integer::sum); -+ } -+ // Paper end - chunk.addEntity(entity); - return entity; - }); diff --git a/Remapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch b/Remapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch deleted file mode 100644 index 82ff3e57c1..0000000000 --- a/Remapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Tue, 29 Dec 2020 15:03:03 +0100 -Subject: [PATCH] Add sendOpLevel API - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 9d1116f601b79dabf7a0d9e5ecf5c2a0306f9aa4..c962b6fc0c65dc5e2ea636220727bca63bf4b740 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1134,22 +1134,29 @@ public abstract class PlayerList { - } - - private void sendPlayerPermissionLevel(ServerPlayer player, int permissionLevel) { -- if (player.connection != null) { -+ // Paper start - add recalculatePermissions parameter -+ this.sendPlayerOperatorStatus(player, permissionLevel, true); -+ } -+ public void sendPlayerOperatorStatus(ServerPlayer entityplayer, int i, boolean recalculatePermissions) { -+ // Paper end -+ if (entityplayer.connection != null) { - byte b0; - -- if (permissionLevel <= 0) { -+ if (i <= 0) { - b0 = 24; -- } else if (permissionLevel >= 4) { -+ } else if (i >= 4) { - b0 = 28; - } else { -- b0 = (byte) (24 + permissionLevel); -+ b0 = (byte) (24 + i); - } - -- player.connection.send(new ClientboundEntityEventPacket(player, b0)); -+ entityplayer.connection.send(new ClientboundEntityEventPacket(entityplayer, b0)); - } - -- player.getBukkitEntity().recalculatePermissions(); // CraftBukkit -- this.server.getCommands().sendCommands(player); -+ if (recalculatePermissions) { // Paper -+ entityplayer.getBukkitEntity().recalculatePermissions(); // CraftBukkit -+ this.server.getCommands().sendCommands(entityplayer); -+ } // Paper - } - - // Paper start -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 40380fff222cc1f3340cf6a6c4afbe60aaa5d3a6..d2d179cdef8129653983b01d94928ba83f64f644 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2296,6 +2296,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - ? (org.bukkit.entity.Firework) entity.getBukkitEntity() - : null; - } -+ -+ @Override -+ public void sendOpLevel(byte level) { -+ Preconditions.checkArgument(level >= 0 && level <= 4, "Level must be within [0, 4]"); -+ -+ this.getHandle().getServer().getPlayerList().sendPlayerOperatorStatus(this.getHandle(), level, false); -+ } - // Paper end - - // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch b/Remapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch deleted file mode 100644 index 6aaa2cdea9..0000000000 --- a/Remapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: dfsek -Date: Wed, 16 Sep 2020 01:12:29 -0700 -Subject: [PATCH] Add StructureLocateEvent - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -index 860af116dbc7dd9d691ff27d28a2d10dbec83df4..29310d96eb562ead1e568a97b6f3019e43ca0a88 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.chunk; - - import com.google.common.collect.Lists; - import com.mojang.serialization.Codec; -+import io.papermc.paper.event.world.StructureLocateEvent; // Paper - Add import due to naming conflict. - import java.util.BitSet; - import java.util.Iterator; - import java.util.List; -@@ -160,6 +161,22 @@ public abstract class ChunkGenerator { - - @Nullable - public BlockPos findNearestMapFeature(ServerLevel world, StructureFeature feature, BlockPos center, int radius, boolean skipExistingChunks) { -+ // Paper start -+ org.bukkit.World world1 = world.getWorld(); -+ org.bukkit.Location originLocation = new org.bukkit.Location(world1, center.getX(), center.getY(), center.getZ()); -+ StructureLocateEvent event = new StructureLocateEvent(world1, originLocation, org.bukkit.StructureType.getStructureTypes().get(feature.getFeatureName()), radius, skipExistingChunks); -+ if(!event.callEvent()) return null; -+ // If event call set a final location, skip structure finding and just return set result. -+ if(event.getResult() != null) return new BlockPos(event.getResult().getBlockX(), event.getResult().getBlockY(), event.getResult().getBlockZ()); -+ // Get origin location (re)defined by event call. -+ center = new BlockPos(event.getOrigin().getBlockX(), event.getOrigin().getBlockY(), event.getOrigin().getBlockZ()); -+ // Get world (re)defined by event call. -+ world = ((org.bukkit.craftbukkit.CraftWorld) event.getOrigin().getWorld()).getHandle(); -+ // Get radius and whether to find unexplored structures (re)defined by event call. -+ radius = event.getRadius(); -+ skipExistingChunks = event.shouldFindUnexplored(); -+ feature = StructureFeature.STRUCTURES_REGISTRY.get(event.getType().getName()); -+ // Paper end - if (!this.biomeSource.canGenerateStructure(feature)) { - return null; - } else if (feature == StructureFeature.STRONGHOLD) { diff --git a/Remapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch b/Remapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch deleted file mode 100644 index 33e77f9b2e..0000000000 --- a/Remapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 14 Nov 2020 16:48:37 +0100 -Subject: [PATCH] Collision option for requiring a player participant - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 486e5438254348db68017228af131cba7defd637..3dd228ae8071a747f2cd7b2b46a2215183f72cd0 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -717,6 +717,18 @@ public class PaperWorldConfig { - } - } - -+ public boolean onlyPlayersCollide = false; -+ public boolean allowVehicleCollisions = true; -+ private void onlyPlayersCollide() { -+ onlyPlayersCollide = getBoolean("only-players-collide", onlyPlayersCollide); -+ allowVehicleCollisions = getBoolean("allow-vehicle-collisions", allowVehicleCollisions); -+ if (onlyPlayersCollide && !allowVehicleCollisions) { -+ log("Collisions will only work if a player is one of the two entities colliding."); -+ } else if (onlyPlayersCollide) { -+ log("Collisions will only work if a player OR a vehicle is one of the two entities colliding."); -+ } -+ } -+ - public int wanderingTraderSpawnMinuteTicks = 1200; - public int wanderingTraderSpawnDayTicks = 24000; - public int wanderingTraderSpawnChanceFailureIncrement = 25; -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index ec98f5f59ca2b4cb58eb00ed8cdfa364f8bacd88..87c719caf796f54296ff7e412548062e02af270e 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1465,6 +1465,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public void push(Entity entity) { - if (!this.isPassengerOfSameVehicle(entity)) { - if (!entity.noPhysics && !this.noPhysics) { -+ if (this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer || this instanceof ServerPlayer)) return; // Paper - double d0 = entity.getX() - this.getX(); - double d1 = entity.getZ() - this.getZ(); - double d2 = Mth.absMax(d0, d1); -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -index 9cbde70787d8044f0edeb3d459231dd7fbb79584..25df3ef6b96bec39847a732394af8eccdb4d5d45 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -@@ -21,6 +21,7 @@ import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; - import net.minecraft.network.syncher.EntityDataAccessor; - import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.tags.BlockTags; - import net.minecraft.tags.Tag; - import net.minecraft.util.Mth; -@@ -766,6 +767,7 @@ public abstract class AbstractMinecart extends Entity { - public void push(Entity entity) { - if (!this.level.isClientSide) { - if (!entity.noPhysics && !this.noPhysics) { -+ if (!this.level.paperConfig.allowVehicleCollisions && this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer)) return; // Paper - if (!this.hasPassenger(entity)) { - // CraftBukkit start - VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -index 6a9c18540886979b2212bf7917a21753c9a9db3c..e7ac3bff190c899397d6576fabbf4966878ea7e5 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -@@ -14,6 +14,7 @@ import net.minecraft.network.protocol.game.ServerboundPaddleBoatPacket; - import net.minecraft.network.syncher.EntityDataAccessor; - import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvent; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.tags.FluidTags; -@@ -229,6 +230,7 @@ public class Boat extends Entity { - - @Override - public void push(Entity entity) { -+ if (!this.level.paperConfig.allowVehicleCollisions && this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer)) return; // Paper - if (entity instanceof Boat) { - if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { - // CraftBukkit start diff --git a/Remapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/Remapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch deleted file mode 100644 index ed43990f0e..0000000000 --- a/Remapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 16 Jan 2021 14:30:12 -0500 -Subject: [PATCH] Remove ProjectileHitEvent call when fireballs dead - -The duplicate ProjectileHitEvent in EntityFireball was removed. The -event was always called before the duplicate call. - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -index 872ff430547276e2a41a48aa07ae63b87ab39e5d..cba1b361162456cf297d88439f76586a2f61fc45 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -@@ -86,7 +86,7 @@ public abstract class AbstractHurtingProjectile extends Projectile { - - // CraftBukkit start - Fire ProjectileHitEvent - if (this.removed) { -- CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); -+ // CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); // Paper - this is an undesired duplicate event - } - // CraftBukkit end - } diff --git a/Remapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch b/Remapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch deleted file mode 100644 index 8f0e61039a..0000000000 --- a/Remapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CDFN -Date: Tue, 7 Jul 2020 17:53:23 +0200 -Subject: [PATCH] Return chat component with empty text instead of throwing - exception - - -diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -index b5d79635cd8b0eb6b17962450b347010aeb52654..d2f762371f82d54bcec8b1a0a02d0866e55fd174 100644 ---- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -12,6 +12,7 @@ import net.minecraft.ReportedException; - import net.minecraft.core.NonNullList; - import net.minecraft.core.Registry; - import net.minecraft.network.chat.Component; -+import net.minecraft.network.chat.TextComponent; - import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.util.Mth; -@@ -60,7 +61,12 @@ public abstract class AbstractContainerMenu { - } - private Component title; - public final Component getTitle() { -- Preconditions.checkState(this.title != null, "Title not set"); -+ // Paper start - return chat component with empty text instead of throwing error -+ // Preconditions.checkState(this.title != null, "Title not set"); -+ if(this.title == null){ -+ return new TextComponent(""); -+ } -+ // Paper end - return this.title; - } - public final void setTitle(Component title) { diff --git a/Remapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch b/Remapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch deleted file mode 100644 index 24fcb77734..0000000000 --- a/Remapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 19:52:44 -0800 -Subject: [PATCH] Make schedule command per-world - - -diff --git a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java -index 122a790285734ecd95fe6817043a84cf1752dbe8..173ab97b01b2191d9d731a28f2690eb4f539880b 100644 ---- a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java -+++ b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java -@@ -32,7 +32,7 @@ public class ScheduleCommand { - return new TranslatableComponent("commands.schedule.cleared.failure", new Object[]{object}); - }); - private static final SuggestionProvider SUGGEST_SCHEDULE = (commandcontext, suggestionsbuilder) -> { -- return SharedSuggestionProvider.suggest((Iterable) ((CommandSourceStack) commandcontext.getSource()).getServer().getWorldData().overworldData().getScheduledEvents().getEventsIds(), suggestionsbuilder); -+ return SharedSuggestionProvider.suggest((Iterable) ((CommandSourceStack) commandcontext.getSource()).getLevel().worldDataServer.overworldData().getScheduledEvents().getEventsIds(), suggestionsbuilder); // Paper - }; - - public static void register(CommandDispatcher dispatcher) { -@@ -55,7 +55,7 @@ public class ScheduleCommand { - } else { - long j = source.getLevel().getGameTime() + (long) i; - ResourceLocation minecraftkey = (ResourceLocation) pair.getFirst(); -- TimerQueue customfunctioncallbacktimerqueue = source.getServer().getWorldData().overworldData().getScheduledEvents(); -+ TimerQueue customfunctioncallbacktimerqueue = source.getLevel().worldDataServer.overworldData().getScheduledEvents(); // Paper - - ((Either) pair.getSecond()).ifLeft((customfunction) -> { - String s = minecraftkey.toString(); -@@ -81,7 +81,7 @@ public class ScheduleCommand { - } - - private static int remove(CommandSourceStack commandlistenerwrapper, String s) throws CommandSyntaxException { -- int i = commandlistenerwrapper.getServer().getWorldData().overworldData().getScheduledEvents().remove(s); -+ int i = commandlistenerwrapper.getLevel().worldDataServer.overworldData().getScheduledEvents().remove(s); // Paper - - if (i == 0) { - throw ScheduleCommand.ERROR_CANT_REMOVE.create(s); diff --git a/Remapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch b/Remapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch deleted file mode 100644 index 42d46d7655..0000000000 --- a/Remapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 21:04:03 -0800 -Subject: [PATCH] Configurable max leash distance - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3dd228ae8071a747f2cd7b2b46a2215183f72cd0..c4ca7ed5b251a2a3d64297351ef32541a4243c35 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -166,6 +166,12 @@ public class PaperWorldConfig { - } - } - -+ public float maxLeashDistance = 10f; -+ private void maxLeashDistance() { -+ maxLeashDistance = getFloat("max-leash-distance", maxLeashDistance); -+ log("Max leash distance: " + maxLeashDistance); -+ } -+ - public boolean disableEndCredits; - private void disableEndCredits() { - disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); -diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java -index 7c82d453388a27b69207d051dec316fc14715e2b..a884940cc576704951d42c6b0d00f5a319297c29 100644 ---- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java -+++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java -@@ -46,7 +46,7 @@ public abstract class PathfinderMob extends Mob { - float f = this.distanceTo(entity); - - if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) { -- if (f > 10.0F) { -+ if (f > entity.level.paperConfig.maxLeashDistance) { // Paper - this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit - this.dropLeash(true, true); - } -@@ -55,7 +55,7 @@ public abstract class PathfinderMob extends Mob { - } - - this.onLeashDistance(f); -- if (f > 10.0F) { -+ if (f > entity.level.paperConfig.maxLeashDistance) { // Paper - this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit - this.dropLeash(true, true); - this.goalSelector.disableControlFlag(Goal.Flag.MOVE); diff --git a/Remapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch b/Remapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch deleted file mode 100644 index fea75084e5..0000000000 --- a/Remapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Sun, 17 Jan 2021 13:16:09 +1000 -Subject: [PATCH] Implement BlockPreDispenseEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -index 2a4cb76bdfcf55ba222b4976359c1b8efb165009..08ce586f8d024b57a20031868ca2a3058bc500ee 100644 ---- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -@@ -88,6 +88,7 @@ public class DispenserBlock extends BaseEntityBlock { - DispenseItemBehavior idispensebehavior = this.getDispenseMethod(itemstack); - - if (idispensebehavior != DispenseItemBehavior.NOOP) { -+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(worldserver, pos, itemstack, i)) return; // Paper - BlockPreDispenseEvent is called here - eventFired = false; // CraftBukkit - reset event status - tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 586d21eed8189adf696ca6d3642afebbe752d1b5..34c0216baa69206aca51821aec421484b18cb04c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -59,6 +59,7 @@ import net.minecraft.world.phys.BlockHitResult; - import net.minecraft.world.phys.EntityHitResult; - import net.minecraft.world.phys.HitResult; - import net.minecraft.world.phys.Vec3; -+import io.papermc.paper.event.block.BlockPreDispenseEvent; // Paper - import org.bukkit.Bukkit; - import org.bukkit.Location; // Paper - import org.bukkit.Material; -@@ -1802,5 +1803,11 @@ public class CraftEventFactory { - BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); - return event.callEvent(); - } -+ -+ public static boolean handleBlockPreDispenseEvent(ServerLevel worldserver, BlockPos blockposition, ItemStack itemStack, int slot) { -+ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ BlockPreDispenseEvent event = new BlockPreDispenseEvent(block, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), slot); -+ return event.callEvent(); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch b/Remapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch deleted file mode 100644 index fcf1ba26d8..0000000000 --- a/Remapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 20:03:35 -0800 -Subject: [PATCH] Added Vanilla Entity Tags - - -diff --git a/src/main/java/io/papermc/paper/CraftEntityTag.java b/src/main/java/io/papermc/paper/CraftEntityTag.java -new file mode 100644 -index 0000000000000000000000000000000000000000..687edf189871fc989174248dbf070bcba161f1a8 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/CraftEntityTag.java -@@ -0,0 +1,28 @@ -+package io.papermc.paper; -+ -+import org.bukkit.craftbukkit.tag.CraftTag; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.entity.EntityType; -+ -+import java.util.Collections; -+import java.util.Set; -+import java.util.stream.Collectors; -+import net.minecraft.resources.ResourceLocation; -+import net.minecraft.tags.TagCollection; -+ -+public class CraftEntityTag extends CraftTag, EntityType> { -+ -+ public CraftEntityTag(TagCollection> registry, ResourceLocation tag) { -+ super(registry, tag); -+ } -+ -+ @Override -+ public boolean isTagged(EntityType item) { -+ return getHandle().isTagged(CraftMagicNumbers.getEntityTypes(item)); -+ } -+ -+ @Override -+ public Set getValues() { -+ return Collections.unmodifiableSet(getHandle().getTagged().stream().map(CraftMagicNumbers::getEntityType).collect(Collectors.toSet())); -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 046fbc646d2818bb2c7e08ff22093523e8246523..3d7cc98710bb925743e6fe8de1f154096334d46c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2221,6 +2221,11 @@ public final class CraftServer implements Server { - Preconditions.checkArgument(clazz == org.bukkit.Fluid.class, "Fluid namespace must have fluid type"); - - return (org.bukkit.Tag) new CraftFluidTag(console.getTags().getFluids(), key); -+ // Paper start -+ case org.bukkit.Tag.REGISTRY_ENTITIES: -+ Preconditions.checkArgument(clazz == org.bukkit.entity.EntityType.class, "Entity namespace must have entitytype type"); -+ return (org.bukkit.Tag) new io.papermc.paper.CraftEntityTag(console.getTags().getEntityTypes(), key); -+ // Paper end - default: - throw new IllegalArgumentException(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index ac94fd569bd4c79e30adef148e09e395ba8c1812..25a29d997f163ce2b11330d66a691601f514a9cb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -116,8 +116,17 @@ public final class CraftMagicNumbers implements UnsafeValues { - private static final Map MATERIAL_ITEM = new HashMap<>(); - private static final Map MATERIAL_BLOCK = new HashMap<>(); - private static final Map MATERIAL_FLUID = new HashMap<>(); -+ // Paper start -+ private static final Map> ENTITY_TYPE_ENTITY_TYPES = new HashMap<>(); -+ private static final Map, org.bukkit.entity.EntityType> ENTITY_TYPES_ENTITY_TYPE = new HashMap<>(); - - static { -+ for (org.bukkit.entity.EntityType type : org.bukkit.entity.EntityType.values()) { -+ if (type == org.bukkit.entity.EntityType.UNKNOWN) continue; -+ ENTITY_TYPE_ENTITY_TYPES.put(type, net.minecraft.core.Registry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey()))); -+ ENTITY_TYPES_ENTITY_TYPE.put(net.minecraft.core.Registry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey())), type); -+ } -+ // Paper end - for (Block block : net.minecraft.core.Registry.BLOCK) { - BLOCK_MATERIAL.put(block, Material.getMaterial(net.minecraft.core.Registry.BLOCK.getKey(block).getPath().toUpperCase(Locale.ROOT))); - } -@@ -183,6 +192,14 @@ public final class CraftMagicNumbers implements UnsafeValues { - public static ResourceLocation key(Material mat) { - return CraftNamespacedKey.toMinecraft(mat.getKey()); - } -+ // Paper start -+ public static net.minecraft.world.entity.EntityType getEntityTypes(org.bukkit.entity.EntityType type) { -+ return ENTITY_TYPE_ENTITY_TYPES.get(type); -+ } -+ public static org.bukkit.entity.EntityType getEntityType(net.minecraft.world.entity.EntityType entityTypes) { -+ return ENTITY_TYPES_ENTITY_TYPE.get(entityTypes); -+ } -+ // Paper end - // ======================================================================== - // Paper start - @Override diff --git a/Remapped-Spigot-Server-Patches/0655-added-Wither-API.patch b/Remapped-Spigot-Server-Patches/0655-added-Wither-API.patch deleted file mode 100644 index 175023cea0..0000000000 --- a/Remapped-Spigot-Server-Patches/0655-added-Wither-API.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 5 Jul 2020 15:39:19 -0700 -Subject: [PATCH] added Wither API - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 1f330d852eb9b3a36570542e10a88ae065798714..fd91c80cd6337b5fa41d6060ecdb44b8fa68a16a 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -80,6 +80,11 @@ public class WitherBoss extends Monster implements RangedAttackMob { - return entityliving.getMobType() != MobType.UNDEAD && entityliving.attackable(); - }; - private static final TargetingConditions TARGETING_CONDITIONS = (new TargetingConditions()).range(20.0D).selector(WitherBoss.LIVING_ENTITY_SELECTOR); -+ // Paper start -+ private boolean canPortal = false; -+ -+ public void setCanTravelThroughPortals(boolean canPortal) { this.canPortal = canPortal; } -+ // Paper end - - public WitherBoss(EntityType type, Level world) { - super(type, world); -@@ -578,6 +583,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { - this.entityData.set((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(headIndex), id); - } - -+ public final boolean isPowered() { return this.isPowered(); } // Paper - OBFHELPER - public boolean isPowered() { - return this.getHealth() <= this.getMaxHealth() / 2.0F; - } -@@ -594,7 +600,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { - - @Override - public boolean canChangeDimensions() { -- return false; -+ return super.canChangeDimensions() && canPortal; // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -index fdcd680b972da54f9cdb41dff5563e42bd12d8e3..a09f46c586416b77dda40067fe1639a9250af3f0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -@@ -38,4 +38,31 @@ public class CraftWither extends CraftMonster implements Wither, com.destroystok - public BossBar getBossBar() { - return bossBar; - } -+ -+ // Paper start -+ @Override -+ public boolean isCharged() { -+ return getHandle().isPowered(); -+ } -+ -+ @Override -+ public int getInvulnerableTicks() { -+ return getHandle().getInvulnerableTicks(); -+ } -+ -+ @Override -+ public void setInvulnerableTicks(int ticks) { -+ getHandle().setInvulnerableTicks(ticks); -+ } -+ -+ @Override -+ public boolean canTravelThroughPortals() { -+ return getHandle().canChangeDimensions(); -+ } -+ -+ @Override -+ public void setCanTravelThroughPortals(boolean value) { -+ getHandle().setCanTravelThroughPortals(value); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/Remapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch deleted file mode 100644 index e2d21ff095..0000000000 --- a/Remapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 15:14:51 -0600 -Subject: [PATCH] Added firing of PlayerChangeBeaconEffectEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java -index 1371bfe4a4b5bb065de4d2118b2b32f4ee0b78d9..20069eeece4e03827ed4b3b4e2b713c43b23a366 100644 ---- a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java -@@ -11,6 +11,10 @@ import net.minecraft.world.level.block.Blocks; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - // CraftBukkit end - -+// Paper start -+import io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent; -+// Paper end -+ - public class BeaconMenu extends AbstractContainerMenu { - - private final Container beacon; -@@ -137,9 +141,15 @@ public class BeaconMenu extends AbstractContainerMenu { - - public void updateEffects(int primaryEffectId, int secondaryEffectId) { - if (this.paymentSlot.hasItem()) { -- this.beaconData.set(1, primaryEffectId); -- this.beaconData.set(2, secondaryEffectId); -+ // Paper start -+ PlayerChangeBeaconEffectEvent event = new PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), org.bukkit.potion.PotionEffectType.getById(primaryEffectId), org.bukkit.potion.PotionEffectType.getById(secondaryEffectId), this.access.getLocation().getBlock()); -+ if (event.callEvent()) { -+ this.beaconData.set(1, event.getPrimary() == null ? 0 : event.getPrimary().getId()); -+ this.beaconData.set(2, event.getSecondary() == null ? 0 : event.getSecondary().getId()); -+ if (!event.willConsumeItem()) return; - this.paymentSlot.a(1); -+ } -+ // Paper end - } - - } diff --git a/Remapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch b/Remapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch deleted file mode 100644 index 239c089fb6..0000000000 --- a/Remapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Thu, 19 Nov 2020 02:07:10 +0000 -Subject: [PATCH] Fix console spam when removing chests in water - - -diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java -index 6b95cd2e2af66eef324dfcc8f7642da2f9e39d4e..d061548b5490f441b91a2dd90e7668a05f7f2112 100644 ---- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java -@@ -239,7 +239,7 @@ public class ChestBlock extends AbstractChestBlock implements - @Override - public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) { - if (!state.is(newState.getBlock())) { -- BlockEntity tileentity = world.getBlockEntity(pos); -+ BlockEntity tileentity = world.getTileEntity(pos, false); // Paper - Don't validate TE - Fix console spam when removing chests in water - - if (tileentity instanceof Container) { - Containers.dropContents(world, pos, (Container) tileentity); diff --git a/Remapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch b/Remapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch deleted file mode 100644 index 2dafd06172..0000000000 --- a/Remapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 26 Nov 2020 11:47:24 +0000 -Subject: [PATCH] Add toggle for always placing the dragon egg - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c4ca7ed5b251a2a3d64297351ef32541a4243c35..40939de88b1a8169dbfc7a0cd288c2fe9b706426 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -795,4 +795,9 @@ public class PaperWorldConfig { - if (value != -1) entityPerChunkSaveLimits.put(type, value); - }); - } -+ -+ public boolean enderDragonsDeathAlwaysPlacesDragonEgg = false; -+ private void enderDragonsDeathAlwaysPlacesDragonEgg() { -+ enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 84447e9845edad2d228b94184b35b4afb453a14b..e2f784b771b12bd646d519938c33b1c86cc2686d 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -396,7 +396,7 @@ public class EndDragonFight { - this.dragonEvent.setVisible(false); - this.spawnExitPortal(true); - this.spawnNewGateway(); -- if (!this.previouslyKilled) { -+ if (this.level.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg - this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.END_PODIUM_LOCATION), Blocks.DRAGON_EGG.defaultBlockState()); - } - diff --git a/Remapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch b/Remapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch deleted file mode 100644 index aab6a1ebc8..0000000000 --- a/Remapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 27 Nov 2020 17:14:27 -0800 -Subject: [PATCH] Added PlayerStonecutterRecipeSelectEvent - -Co-Authored-By: MiniDigger - -diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -index d2f762371f82d54bcec8b1a0a02d0866e55fd174..b5eeb2749237d589eafdfbea073bfe90e609600b 100644 ---- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -117,7 +117,7 @@ public abstract class AbstractContainerMenu { - return slot; - } - -- protected DataSlot addDataSlot(DataSlot containerproperty) { -+ protected DataSlot addDataSlot(DataSlot containerproperty) { return addDataSlot(containerproperty); } protected DataSlot addDataSlot(DataSlot containerproperty) { // Paper - OBFHELPER - this.dataSlots.add(containerproperty); - return containerproperty; - } -diff --git a/src/main/java/net/minecraft/world/inventory/DataSlot.java b/src/main/java/net/minecraft/world/inventory/DataSlot.java -index 56d99e39f8cfe46a780bd17a0f99c3cbbe01c719..e851d6c8e5ad58091a58d489a48cd3ec379ce0da 100644 ---- a/src/main/java/net/minecraft/world/inventory/DataSlot.java -+++ b/src/main/java/net/minecraft/world/inventory/DataSlot.java -@@ -20,7 +20,7 @@ public abstract class DataSlot { - }; - } - -- public static DataSlot shared(final int[] array, final int index) { -+ public static DataSlot shared(final int[] aint, final int i) { return shared(aint, i); } public static DataSlot shared(final int[] array, final int index) { // Paper - OBFHELPER - return new DataSlot() { - @Override - public int get() { -@@ -54,7 +54,7 @@ public abstract class DataSlot { - - public abstract void set(int value); - -- public boolean checkAndClearUpdateFlag() { -+ public boolean checkAndClearUpdateFlag() { return checkAndClearUpdateFlag(); } public boolean checkAndClearUpdateFlag() { // Paper - OBFHELPER - int i = this.get(); - boolean flag = i != this.prevValue; - -diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java -index 072bac443e7c54ac2b92e1d93b757bdacf230fbb..beb02f953719170d1668ada1c09d073d84bb7baf 100644 ---- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java -@@ -21,13 +21,14 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent; // Paper - - public class StonecutterMenu extends AbstractContainerMenu { - - private final ContainerLevelAccess access; - private final DataSlot selectedRecipeIndex; - private final Level level; -- private List recipes; -+ private List recipes; public final List getRecipes() { return this.recipes; } // Paper - OBFHELPER - private ItemStack input; - private long lastSoundTime; - final Slot inputSlot; -@@ -57,7 +58,7 @@ public class StonecutterMenu extends AbstractContainerMenu { - - public StonecutterMenu(int syncId, Inventory playerInventory, final ContainerLevelAccess context) { - super(MenuType.STONECUTTER, syncId); -- this.selectedRecipeIndex = DataSlot.standalone(); -+ this.selectedRecipeIndex = addDataSlot(DataSlot.shared(new int[1], 0)); // Paper - allow replication - this.recipes = Lists.newArrayList(); - this.input = ItemStack.EMPTY; - this.slotUpdateListener = () -> { -@@ -135,13 +136,36 @@ public class StonecutterMenu extends AbstractContainerMenu { - @Override - public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { - if (this.isValidRecipeIndex(id)) { -- this.selectedRecipeIndex.set(id); -+ // Paper start -+ int recipeIndex = id; -+ this.selectedRecipeIndex.set(recipeIndex); -+ this.selectedRecipeIndex.checkAndClearUpdateFlag(); // mark as changed -+ if (this.isValidRecipeIndex(id)) { -+ PlayerStonecutterRecipeSelectEvent event = new PlayerStonecutterRecipeSelectEvent((Player) player.getBukkitEntity(), (org.bukkit.inventory.StonecutterInventory) getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) this.getRecipes().get(id).toBukkitRecipe()); -+ if (!event.callEvent()) { -+ ((Player) player.getBukkitEntity()).updateInventory(); -+ return false; -+ } -+ int newRecipeIndex; -+ if (!this.getRecipes().get(recipeIndex).getId().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { // If the recipe did NOT stay the same -+ for (newRecipeIndex = 0; newRecipeIndex < this.getRecipes().size(); newRecipeIndex++) { -+ if (this.getRecipes().get(newRecipeIndex).getId().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { -+ recipeIndex = newRecipeIndex; -+ break; -+ } -+ } -+ } -+ } -+ ((Player) player.getBukkitEntity()).updateInventory(); -+ this.selectedRecipeIndex.set(recipeIndex); // set new index, so that listeners can read it -+ // Paper end - this.setupResultSlot(); - } - - return true; - } - -+ private boolean isValidRecipeIndex(int index) { return this.isValidRecipeIndex(index); } // Paper - OBFHELPER - private boolean isValidRecipeIndex(int i) { - return i >= 0 && i < this.recipes.size(); - } diff --git a/Remapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/Remapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch deleted file mode 100644 index 33a094ba1f..0000000000 --- a/Remapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch +++ /dev/null @@ -1,156 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Fri, 29 Jan 2021 15:13:11 +0100 -Subject: [PATCH] Add dropLeash variable to EntityUnleashEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 87dd6c012bf1ca6a1e8df44dc0957c4c67d02adc..ea34306858116e5626383af408529091836c2752 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -86,6 +86,7 @@ import org.bukkit.event.entity.EntityTargetEvent; - import org.bukkit.event.entity.EntityTransformEvent; - import org.bukkit.event.entity.EntityUnleashEvent; - import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; -+import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper - // CraftBukkit end - - public abstract class Mob extends LivingEntity { -@@ -1205,12 +1206,15 @@ public abstract class Mob extends LivingEntity { - return InteractionResult.PASS; - } else if (this.getLeashHolder() == player) { - // CraftBukkit start - fire PlayerUnleashEntityEvent -- if (CraftEventFactory.callPlayerUnleashEntityEvent(this, player).isCancelled()) { -+ // Paper start - drop leash variable -+ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, player, !player.abilities.instabuild); -+ if (event.isCancelled()) { -+ // Paper end - ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); - return InteractionResult.PASS; - } - // CraftBukkit end -- this.dropLeash(true, !player.abilities.instabuild); -+ this.dropLeash(true, event.isDropLeash()); // Paper - drop leash variable - return InteractionResult.sidedSuccess(this.level.isClientSide); - } else { - InteractionResult enuminteractionresult = this.checkAndHandleImportantInteractions(player, hand); -@@ -1364,8 +1368,11 @@ public abstract class Mob extends LivingEntity { - - if (this.leashHolder != null) { - if (!this.isAlive() || !this.leashHolder.isAlive()) { -- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit -- this.dropLeash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE, true); -+ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.dropLeash(true, event.isDropLeash()); -+ // Paper end - } - - } -@@ -1433,8 +1440,11 @@ public abstract class Mob extends LivingEntity { - boolean flag1 = super.startRiding(entity, force); - - if (flag1 && this.isLeashed()) { -- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit -- this.dropLeash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, true); -+ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.dropLeash(true, event.isDropLeash()); -+ // Paper end - } - - return flag1; -@@ -1636,7 +1646,10 @@ public abstract class Mob extends LivingEntity { - @Override - protected void removeAfterChangingDimensions() { - super.removeAfterChangingDimensions(); -- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit -- this.dropLeash(true, false); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, false); -+ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.dropLeash(true, event.isDropLeash()); -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java -index a884940cc576704951d42c6b0d00f5a319297c29..d16a7bab5495d58ea9e6811d4b507667cfa3d264 100644 ---- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java -+++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java -@@ -47,8 +47,11 @@ public abstract class PathfinderMob extends Mob { - - if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) { - if (f > entity.level.paperConfig.maxLeashDistance) { // Paper -- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit -- this.dropLeash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); -+ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.dropLeash(true, event.isDropLeash()); -+ // Paper end - } - - return; -@@ -56,8 +59,11 @@ public abstract class PathfinderMob extends Mob { - - this.onLeashDistance(f); - if (f > entity.level.paperConfig.maxLeashDistance) { // Paper -- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit -- this.dropLeash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); -+ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.dropLeash(true, event.isDropLeash()); -+ // Paper end - this.goalSelector.disableControlFlag(Goal.Flag.MOVE); - } else if (f > 6.0F) { - double d0 = (entity.getX() - this.getX()) / (double) f; -diff --git a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java -index 465548de7e32028a2aed4b6e9543e1bd9b73700b..1f54c020cc2b1928b2e7edda9ddf7b9d61e6424b 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java -@@ -28,6 +28,8 @@ import net.minecraft.world.phys.AABB; - import org.bukkit.craftbukkit.event.CraftEventFactory; - // CraftBukkit end - -+import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper -+ - public class LeashFenceKnotEntity extends HangingEntity { - - public LeashFenceKnotEntity(EntityType type, Level world) { -@@ -123,11 +125,14 @@ public class LeashFenceKnotEntity extends HangingEntity { - entityinsentient = (Mob) iterator.next(); - if (entityinsentient.isLeashed() && entityinsentient.getLeashHolder() == this) { - // CraftBukkit start -- if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, player).isCancelled()) { -+ // Paper start - drop leash variable -+ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, player, !player.abilities.instabuild); -+ if (event.isCancelled()) { -+ // Paper end - die = false; - continue; - } -- entityinsentient.dropLeash(true, !player.abilities.instabuild); // false -> survival mode boolean -+ entityinsentient.dropLeash(true, event.isDropLeash()); // false -> survival mode boolean // Paper - drop leash variable - // CraftBukkit end - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 34c0216baa69206aca51821aec421484b18cb04c..ea7c30ef17fc66c1fb55d5909f94651c98b181be 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1460,8 +1460,10 @@ public class CraftEventFactory { - return itemInHand; - } - -- public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(Mob entity, net.minecraft.world.entity.player.Player player) { -- PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity()); -+ // Paper start - drop leash variable -+ public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(Mob entity, net.minecraft.world.entity.player.Player player, boolean dropLeash) { -+ PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), dropLeash); -+ // Paper end - entity.level.getCraftServer().getPluginManager().callEvent(event); - return event; - } diff --git a/Remapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch b/Remapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch deleted file mode 100644 index fac284074d..0000000000 --- a/Remapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Beech Horn -Date: Fri, 14 Feb 2020 19:39:59 +0000 -Subject: [PATCH] Skip distance map update when spawning disabled. - - -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 7a615a18f1f297adfe7e046407a019d8933e9ed9..8e27559a12ada05e0530c7fe5b0bfbc4422ccbd6 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -825,7 +825,7 @@ public class ServerChunkCache extends ChunkSource { - int l = this.distanceManager.getNaturalSpawnChunkCount(); - // Paper start - per player mob spawning - NaturalSpawner.SpawnState spawnercreature_d; // moved down -- if (this.chunkMap.playerMobDistanceMap != null) { -+ if ((this.spawnFriendlies || this.spawnEnemies) && this.chunkMap.playerMobDistanceMap != null) { // don't update when animals and monsters are disabled - // update distance map - this.level.timings.playerMobDistanceMapUpdate.startTiming(); - this.chunkMap.playerMobDistanceMap.update(this.level.players, this.chunkMap.viewDistance); diff --git a/Remapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch b/Remapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch deleted file mode 100644 index 4349f8f4d8..0000000000 --- a/Remapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yive -Date: Sun, 24 Jan 2021 08:55:19 -0800 -Subject: [PATCH] Reset shield blocking on dimension change - - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index ff831ca0cbc0cabbf78178c609ccf70d78da7980..314f168c9d17ab3654c9dda07e48839570f0d332 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1115,6 +1115,11 @@ public class ServerPlayer extends Player implements ContainerListener { - this.level.getCraftServer().getPluginManager().callEvent(changeEvent); - // CraftBukkit end - } -+ // Paper start -+ if (this.isBlocking()) { -+ this.stopUsingItem(); -+ } -+ // Paper end - - return this; - } diff --git a/Remapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch b/Remapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch deleted file mode 100644 index 17cbf7f9ae..0000000000 --- a/Remapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Mon, 25 Jan 2021 14:53:57 +0100 -Subject: [PATCH] add DragonEggFormEvent - - -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index e2f784b771b12bd646d519938c33b1c86cc2686d..f32e2c71929a73258e4eb521c160c247690744d2 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -57,6 +57,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfigur - import net.minecraft.world.phys.AABB; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.event.block.DragonEggFormEvent; // Paper - DragonEggFormEvent - - public class EndDragonFight { - -@@ -396,9 +397,24 @@ public class EndDragonFight { - this.dragonEvent.setVisible(false); - this.spawnExitPortal(true); - this.spawnNewGateway(); -+ // Paper start - DragonEggFormEvent -+ BlockPos eggPosition = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getPosition()); -+ org.bukkit.craftbukkit.block.CraftBlock eggBlock = org.bukkit.craftbukkit.block.CraftBlock.at(this.level, eggPosition); -+ org.bukkit.craftbukkit.block.CraftBlockState eggState = new org.bukkit.craftbukkit.block.CraftBlockState(eggBlock); -+ eggState.setData(Blocks.DRAGON_EGG.defaultBlockState()); -+ DragonEggFormEvent eggEvent = new DragonEggFormEvent(eggBlock, eggState, -+ new org.bukkit.craftbukkit.boss.CraftDragonBattle(this)); -+ // Paper end - DragonEggFormEvent - if (this.level.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg -- this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.END_PODIUM_LOCATION), Blocks.DRAGON_EGG.defaultBlockState()); -+ // Paper start - DragonEggFormEvent -+ //this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); -+ } else { -+ eggEvent.setCancelled(true); -+ } -+ if (eggEvent.callEvent()) { -+ eggEvent.getNewState().update(true); - } -+ // Paper end - DragonEggFormEvent - - this.previouslyKilled = true; - this.dragonKilled = true; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java -index cd24e9db1e9a490117716d4883376bb6b59c7c67..e085607f4033476e80b7dcd7b026449c12a47cf6 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java -@@ -14,7 +14,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConf - - public class EndPodiumFeature extends Feature { - -- public static final BlockPos END_PODIUM_LOCATION = BlockPos.ZERO; -+ public static final BlockPos END_PODIUM_LOCATION = BlockPos.ZERO; public static BlockPos getPosition() { return END_PODIUM_LOCATION; } // Paper - OBFHELPER - private final boolean active; - - public EndPodiumFeature(boolean open) { -@@ -22,43 +22,43 @@ public class EndPodiumFeature extends Feature { - this.active = open; - } - -- public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, NoneFeatureConfiguration config) { -- Iterator iterator = BlockPos.betweenClosed(new BlockPos(pos.getX() - 4, pos.getY() - 1, pos.getZ() - 4), new BlockPos(pos.getX() + 4, pos.getY() + 32, pos.getZ() + 4)).iterator(); -+ public boolean generate(WorldGenLevel generatoraccessseed, ChunkGenerator chunkgenerator, Random random, BlockPos blockposition, NoneFeatureConfiguration worldgenfeatureemptyconfiguration) { // Paper - decompile fix -+ Iterator iterator = BlockPos.betweenClosed(new BlockPos(blockposition.getX() - 4, blockposition.getY() - 1, blockposition.getZ() - 4), new BlockPos(blockposition.getX() + 4, blockposition.getY() + 32, blockposition.getZ() + 4)).iterator(); - - while (iterator.hasNext()) { - BlockPos blockposition1 = (BlockPos) iterator.next(); -- boolean flag = blockposition1.closerThan((Vec3i) pos, 2.5D); -+ boolean flag = blockposition1.closerThan((Vec3i) blockposition, 2.5D); - -- if (flag || blockposition1.closerThan((Vec3i) pos, 3.5D)) { -- if (blockposition1.getY() < pos.getY()) { -+ if (flag || blockposition1.closerThan((Vec3i) blockposition, 3.5D)) { -+ if (blockposition1.getY() < blockposition.getY()) { - if (flag) { -- this.setBlock(world, blockposition1, Blocks.BEDROCK.defaultBlockState()); -- } else if (blockposition1.getY() < pos.getY()) { -- this.setBlock(world, blockposition1, Blocks.END_STONE.defaultBlockState()); -+ this.setBlock(generatoraccessseed, blockposition1, Blocks.BEDROCK.defaultBlockState()); -+ } else if (blockposition1.getY() < blockposition.getY()) { -+ this.setBlock(generatoraccessseed, blockposition1, Blocks.END_STONE.defaultBlockState()); - } -- } else if (blockposition1.getY() > pos.getY()) { -- this.setBlock(world, blockposition1, Blocks.AIR.defaultBlockState()); -+ } else if (blockposition1.getY() > blockposition.getY()) { -+ this.setBlock(generatoraccessseed, blockposition1, Blocks.AIR.defaultBlockState()); - } else if (!flag) { -- this.setBlock(world, blockposition1, Blocks.BEDROCK.defaultBlockState()); -+ this.setBlock(generatoraccessseed, blockposition1, Blocks.BEDROCK.defaultBlockState()); - } else if (this.active) { -- this.setBlock(world, new BlockPos(blockposition1), Blocks.END_PORTAL.defaultBlockState()); -+ this.setBlock(generatoraccessseed, new BlockPos(blockposition1), Blocks.END_PORTAL.defaultBlockState()); - } else { -- this.setBlock(world, new BlockPos(blockposition1), Blocks.AIR.defaultBlockState()); -+ this.setBlock(generatoraccessseed, new BlockPos(blockposition1), Blocks.AIR.defaultBlockState()); - } - } - } - - for (int i = 0; i < 4; ++i) { -- this.setBlock(world, pos.above(i), Blocks.BEDROCK.defaultBlockState()); -+ this.setBlock(generatoraccessseed, blockposition.above(i), Blocks.BEDROCK.defaultBlockState()); - } - -- BlockPos blockposition2 = pos.above(2); -+ BlockPos blockposition2 = blockposition.above(2); - Iterator iterator1 = Direction.Plane.HORIZONTAL.iterator(); - - while (iterator1.hasNext()) { - Direction enumdirection = (Direction) iterator1.next(); - -- this.setBlock(world, blockposition2.relative(enumdirection), (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, enumdirection)); -+ this.setBlock(generatoraccessseed, blockposition2.relative(enumdirection), (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, enumdirection)); - } - - return true; diff --git a/Remapped-Spigot-Server-Patches/0664-EntityMoveEvent.patch b/Remapped-Spigot-Server-Patches/0664-EntityMoveEvent.patch deleted file mode 100644 index eec865bf53..0000000000 --- a/Remapped-Spigot-Server-Patches/0664-EntityMoveEvent.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Tue, 11 Feb 2020 21:56:48 -0600 -Subject: [PATCH] EntityMoveEvent - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 892ca65d258b0745be95d7ef4886c49899b24d92..bc44811f26076871848ba8f5c582ab26b1fd7170 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -13,6 +13,7 @@ import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; - import io.papermc.paper.adventure.PaperAdventure; // Paper -+import io.papermc.paper.event.entity.EntityMoveEvent; - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -1458,6 +1459,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper -+ worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - - this.profiler.push(() -> { -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 9f1838d12b13d64f10871eb672ed2aec78d9936e..338b4c382fb8ea349ce81f2009e96de1df7ac5e2 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -207,6 +207,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - public final LevelStorageSource.LevelStorageAccess convertable; - public final UUID uuid; - public boolean hasPhysicsEvent = true; // Paper -+ public boolean hasEntityMoveEvent = false; // Paper - private static Throwable getAddToWorldStackTrace(Entity entity) { - return new Throwable(entity + " Added to world at " + new java.util.Date()); - } -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 02ddb84c563b3149c4f1b0e24899ce8a21ad61bb..8bc74878919ab7cf6a50d425da61f1b8a8b0ee44 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -10,6 +10,7 @@ import com.mojang.datafixers.util.Pair; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import com.mojang.serialization.DynamicOps; -+import io.papermc.paper.event.entity.EntityMoveEvent; - import java.util.Collection; - import java.util.ConcurrentModificationException; - import java.util.Iterator; -@@ -2909,6 +2910,20 @@ public abstract class LivingEntity extends Entity { - - this.pushEntities(); - this.level.getProfiler().pop(); -+ // Paper start -+ if (((ServerLevel) level).hasEntityMoveEvent) { -+ if (xo != getX() || yo != getY() || zo != getZ() || yRotO != yRot || xRotO != xRot) { -+ Location from = new Location(level.getWorld(), xo, yo, zo, yRotO, xRotO); -+ Location to = new Location (level.getWorld(), getX(), getY(), getZ(), yRot, xRot); -+ EntityMoveEvent event = new EntityMoveEvent(getBukkitLivingEntity(), from, to.clone()); -+ if (!event.callEvent()) { -+ absMoveTo(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); -+ } else if (!to.equals(event.getTo())) { -+ absMoveTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); -+ } -+ } -+ } -+ // Paper end - if (!this.level.isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { - this.hurt(DamageSource.DROWN, 1.0F); - } diff --git a/Remapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch b/Remapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch deleted file mode 100644 index ca84c216d2..0000000000 --- a/Remapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas81298 -Date: Mon, 25 Jan 2021 14:37:57 +0100 -Subject: [PATCH] added option to disable pathfinding updates on block changes - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 40939de88b1a8169dbfc7a0cd288c2fe9b706426..bbb1d0ed9e76f414dc7d73b4f7786891425f55cd 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -800,4 +800,9 @@ public class PaperWorldConfig { - private void enderDragonsDeathAlwaysPlacesDragonEgg() { - enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); - } -+ -+ public boolean updatePathfindingOnBlockUpdate = true; -+ private void setUpdatePathfindingOnBlockUpdate() { -+ updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 338b4c382fb8ea349ce81f2009e96de1df7ac5e2..a7553a856b9c99bee8f75d514b97cfab952bfd33 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1678,6 +1678,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - @Override - public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) { - this.getChunkSource().blockChanged(pos); -+ if(this.paperConfig.updatePathfindingOnBlockUpdate) { // Paper - option to disable pathfinding updates - VoxelShape voxelshape = oldState.getCollisionShape(this, pos); - VoxelShape voxelshape1 = newState.getCollisionShape(this, pos); - -@@ -1706,6 +1707,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - - this.tickingEntities = wasTicking; // Paper - } -+ } // Paper - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch b/Remapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch deleted file mode 100644 index bf3e677ed6..0000000000 --- a/Remapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Mon, 18 Jan 2021 20:45:25 -0500 -Subject: [PATCH] Inline shift direction fields - -Removes a layer of indirection for EnumDirection.getAdjacent(X|Y|Z)(), which is in the -critical section for much of the server, including the lighting engine. - -diff --git a/src/main/java/net/minecraft/core/Direction.java b/src/main/java/net/minecraft/core/Direction.java -index 3ebc62fe93a0cd0048e07b0343fc724f2c056010..51217f7e5288162b8e76c8717506b393cd262537 100644 ---- a/src/main/java/net/minecraft/core/Direction.java -+++ b/src/main/java/net/minecraft/core/Direction.java -@@ -53,6 +53,11 @@ public enum Direction implements StringRepresentable { - }, (enumdirection, enumdirection1) -> { - throw new IllegalArgumentException("Duplicate keys"); - }, Long2ObjectOpenHashMap::new)); -+ // Paper start -+ private final int adjX; -+ private final int adjY; -+ private final int adjZ; -+ // Paper end - - private Direction(int i, int j, int k, String s, Direction.AxisDirection enumdirection_enumaxisdirection, Direction.Axis enumdirection_enumaxis, Vec3i baseblockposition) { - this.data3d = i; -@@ -62,6 +67,11 @@ public enum Direction implements StringRepresentable { - this.axis = enumdirection_enumaxis; - this.axisDirection = enumdirection_enumaxisdirection; - this.normal = baseblockposition; -+ // Paper start -+ this.adjX = baseblockposition.getX(); -+ this.adjY = baseblockposition.getY(); -+ this.adjZ = baseblockposition.getZ(); -+ // Paper end - } - - public static Direction[] orderedByNearest(Entity entity) { -@@ -137,15 +147,15 @@ public enum Direction implements StringRepresentable { - } - - public int getStepX() { -- return this.normal.getX(); -+ return this.adjX; // Paper - } - - public int getStepY() { -- return this.normal.getY(); -+ return this.adjY; // Paper - } - - public int getStepZ() { -- return this.normal.getZ(); -+ return this.adjZ; // Paper - } - - public String getName() { diff --git a/Remapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch b/Remapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch deleted file mode 100644 index 973fb6de6c..0000000000 --- a/Remapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Wed, 20 Jan 2021 14:23:37 -0600 -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 ea7c30ef17fc66c1fb55d5909f94651c98b181be..5145968c9c6ccabfb15b91102f82e8a3a2d3cf82 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -389,13 +389,30 @@ public class CraftEventFactory { - } - - public static void handleBlockDropItemEvent(Block block, BlockState state, ServerPlayer player, List items) { -- BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), Lists.transform(items, (item) -> (org.bukkit.entity.Item) item.getBukkitEntity())); -+ // Paper start -+ List list = new ArrayList<>(); -+ for (ItemEntity item : items) { -+ list.add((Item) item.getBukkitEntity()); -+ } -+ BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), list); -+ // Paper end - Bukkit.getPluginManager().callEvent(event); - - if (!event.isCancelled()) { -- for (ItemEntity item : items) { -- item.level.addFreshEntity(item); -+ // Paper start -+ for (Item bukkit : list) { -+ if (!bukkit.isValid()) { -+ Entity item = ((org.bukkit.craftbukkit.entity.CraftItem) bukkit).getHandle(); -+ item.level.addFreshEntity(item); -+ } -+ } -+ } else { -+ for (Item bukkit : list) { -+ if (bukkit.isValid()) { -+ bukkit.remove(); -+ } - } -+ // Paper end - } - } - diff --git a/Remapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/Remapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch deleted file mode 100644 index f2acd9e212..0000000000 --- a/Remapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aleksander Jagiello -Date: Sun, 24 Jan 2021 22:17:54 +0100 -Subject: [PATCH] Add getMainThreadExecutor to BukkitScheduler - - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 13e461ffb2ee2e7d0440c0f60809ea99629b843c..0be39dac4b9dd69d7d73d86d64cf1e33e4086e81 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -635,4 +635,15 @@ public class CraftScheduler implements BukkitScheduler { - public BukkitTask runTaskTimerAsynchronously(Plugin plugin, BukkitRunnable task, long delay, long period) throws IllegalArgumentException { - throw new UnsupportedOperationException("Use BukkitRunnable#runTaskTimerAsynchronously(Plugin, long, long)"); - } -+ -+ // Paper start - add getMainThreadExecutor -+ @Override -+ public Executor getMainThreadExecutor(Plugin plugin) { -+ Validate.notNull(plugin, "Plugin cannot be null"); -+ return command -> { -+ Validate.notNull(command, "Command cannot be null"); -+ this.runTask(plugin, command); -+ }; -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch b/Remapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch deleted file mode 100644 index 78a2270873..0000000000 --- a/Remapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Sat, 24 Oct 2020 16:37:44 +0200 -Subject: [PATCH] living entity allow attribute registration - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java -index a501f334ce0bcc606dd2bb186cf7195102cd6c09..8acd102c0778e4e546e5191b6098eacbd15bd9f9 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java -+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java -@@ -21,7 +21,7 @@ import org.apache.logging.log4j.Logger; - public class AttributeMap { - - private static final Logger LOGGER = LogManager.getLogger(); -- private final Map attributes = Maps.newHashMap(); -+ private final Map attributes = Maps.newHashMap(); private final Map attributeMap = attributes; // Paper - OBFHELPER - private final Set dirtyAttributes = Sets.newHashSet(); - private final AttributeSupplier supplier; - -@@ -135,4 +135,12 @@ public class AttributeMap { - } - - } -+ -+ // Paper - start -+ public void registerAttribute(Attribute attributeBase) { -+ AttributeInstance attributeModifiable = new AttributeInstance(attributeBase, AttributeInstance::getAttribute); -+ attributeMap.put(attributeBase, attributeModifiable); -+ } -+ // Paper - end -+ - } -diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -index 320fd6780af2fa99e4e4f4193cbc9338d492dc6d..a57b16679889f5b20c74712651f94d6796b8c661 100644 ---- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -@@ -38,6 +38,14 @@ public class CraftAttributeMap implements Attributable { - return (nms == null) ? null : new CraftAttributeInstance(nms, attribute); - } - -+ // Paper start -+ @Override -+ public void registerAttribute(Attribute attribute) { -+ Preconditions.checkArgument(attribute != null, "attribute"); -+ handle.registerAttribute(CraftAttributeMap.toMinecraft(attribute)); -+ } -+ // Paper end -+ - public static net.minecraft.world.entity.ai.attributes.Attribute toMinecraft(Attribute attribute) { - return net.minecraft.core.Registry.ATTRIBUTE.get(CraftNamespacedKey.toMinecraft(attribute.getKey())); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index a8d21382d5859edfd12e01a48924ce780790b4b7..eefb6bd580ea176c3a242695ab4af46e7c61b492 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -663,6 +663,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().craftAttributes.getAttribute(attribute); - } - -+ // Paper start -+ @Override -+ public void registerAttribute(Attribute attribute) { -+ getHandle().craftAttributes.registerAttribute(attribute); -+ } -+ // Paper end -+ - @Override - public void setAI(boolean ai) { - if (this.getHandle() instanceof Mob) { diff --git a/Remapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch b/Remapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch deleted file mode 100644 index 72df11355c..0000000000 --- a/Remapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Fri, 5 Feb 2021 22:12:13 +0100 -Subject: [PATCH] fix dead slime setSize invincibility - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -index 340036135588d06e43cbd229dd3a6613b04bb9ab..d1bb7e1f7f7837774512e0af0c8b855d34d5a85b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -@@ -17,7 +17,7 @@ public class CraftSlime extends CraftMob implements Slime { - - @Override - public void setSize(int size) { -- getHandle().setSize(size, true); -+ getHandle().setSize(size, /* true */ getHandle().isAlive()); // Paper - fix dead slime setSize invincibility - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch b/Remapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch deleted file mode 100644 index c4baf4a043..0000000000 --- a/Remapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Wed, 10 Feb 2021 14:53:36 -0800 -Subject: [PATCH] Merchant#getRecipes should return an immutable list - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -index 3437ec2c7c1a84debb7d7b7c90283d7e25208604..b4bcbd6329c67ea3deeeb1bf38233ebd15e922b7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -@@ -24,7 +24,7 @@ public class CraftMerchant implements Merchant { - - @Override - public List getRecipes() { -- return Collections.unmodifiableList(Lists.transform(merchant.getOffers(), new Function() { -+ return com.google.common.collect.ImmutableList.copyOf(Lists.transform(merchant.getOffers(), new Function() { // Paper - javadoc says 'an immutable list of trades' - not 'an unmodifiable view of a list of trades'. fixes issue with setRecipes(getRecipes()) - @Override - public MerchantRecipe apply(net.minecraft.world.item.trading.MerchantOffer recipe) { - return recipe.asBukkit(); diff --git a/Remapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch b/Remapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch deleted file mode 100644 index f56af1f8b5..0000000000 --- a/Remapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 18 Feb 2021 20:23:28 +0000 -Subject: [PATCH] misc debugging dumps - - -diff --git a/src/main/java/io/papermc/paper/util/TraceUtil.java b/src/main/java/io/papermc/paper/util/TraceUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2d5494d2813b773e60ddba6790b750a9a08f21f8 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/util/TraceUtil.java -@@ -0,0 +1,18 @@ -+package io.papermc.paper.util; -+ -+import org.bukkit.Bukkit; -+ -+public final class TraceUtil { -+ -+ public static void dumpTraceForThread(Thread thread, String reason) { -+ Bukkit.getLogger().warning(thread.getName() + ": " + reason); -+ StackTraceElement[] trace = thread.getStackTrace(); -+ for (StackTraceElement traceElement : trace) { -+ Bukkit.getLogger().warning("\tat " + traceElement); -+ } -+ } -+ -+ public static void dumpTraceForThread(String reason) { -+ new Throwable(reason).printStackTrace(); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index bc44811f26076871848ba8f5c582ab26b1fd7170..9b654fed2a00740cef84cf72258abfc7aeafc0c2 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -14,6 +14,7 @@ import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; - import io.papermc.paper.adventure.PaperAdventure; // Paper - import io.papermc.paper.event.entity.EntityMoveEvent; -+import io.papermc.paper.util.TraceUtil; - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -855,6 +856,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Sat, 20 Feb 2021 13:09:59 -0500 -Subject: [PATCH] Add support for hex color codes in console - -Converts upstream's hex color code legacy format into actual hex color codes in the console. - -diff --git a/src/main/java/io/papermc/paper/console/HexFormattingConverter.java b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a4315961b7a465fb4872a4d67e7c26d4b4ed1fb9 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java -@@ -0,0 +1,178 @@ -+package io.papermc.paper.console; -+ -+import net.minecrell.terminalconsole.TerminalConsoleAppender; -+import org.apache.logging.log4j.core.LogEvent; -+import org.apache.logging.log4j.core.config.Configuration; -+import org.apache.logging.log4j.core.config.plugins.Plugin; -+import org.apache.logging.log4j.core.layout.PatternLayout; -+import org.apache.logging.log4j.core.pattern.*; -+import org.apache.logging.log4j.util.PerformanceSensitive; -+import org.apache.logging.log4j.util.PropertiesUtil; -+ -+import java.util.List; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+import static net.minecrell.terminalconsole.MinecraftFormattingConverter.KEEP_FORMATTING_PROPERTY; -+ -+/** -+ * Modified version of -+ * TerminalConsoleAppender's MinecraftFormattingConverter to support hex color codes using the md_5 &x&r&r&g&g&b&b format. -+ */ -+@Plugin(name = "paperMinecraftFormatting", category = PatternConverter.CATEGORY) -+@ConverterKeys({ "paperMinecraftFormatting" }) -+@PerformanceSensitive("allocation") -+public final class HexFormattingConverter extends LogEventPatternConverter { -+ -+ private static final boolean KEEP_FORMATTING = PropertiesUtil.getProperties().getBooleanProperty(KEEP_FORMATTING_PROPERTY); -+ -+ private static final String ANSI_RESET = "\u001B[m"; -+ -+ private static final char COLOR_CHAR = '§'; -+ private static final String LOOKUP = "0123456789abcdefklmnor"; -+ -+ private static final String RGB_ANSI = "\u001B[38;2;%d;%d;%dm"; -+ private static final Pattern NAMED_PATTERN = Pattern.compile(COLOR_CHAR + "[0-9a-fk-orA-FK-OR]"); -+ private static final Pattern RGB_PATTERN = Pattern.compile(COLOR_CHAR + "x(" + COLOR_CHAR + "[0-9a-fA-F]){6}"); -+ -+ private static final String[] ansiCodes = new String[] { -+ "\u001B[0;30m", // Black §0 -+ "\u001B[0;34m", // Dark Blue §1 -+ "\u001B[0;32m", // Dark Green §2 -+ "\u001B[0;36m", // Dark Aqua §3 -+ "\u001B[0;31m", // Dark Red §4 -+ "\u001B[0;35m", // Dark Purple §5 -+ "\u001B[0;33m", // Gold §6 -+ "\u001B[0;37m", // Gray §7 -+ "\u001B[0;30;1m", // Dark Gray §8 -+ "\u001B[0;34;1m", // Blue §9 -+ "\u001B[0;32;1m", // Green §a -+ "\u001B[0;36;1m", // Aqua §b -+ "\u001B[0;31;1m", // Red §c -+ "\u001B[0;35;1m", // Light Purple §d -+ "\u001B[0;33;1m", // Yellow §e -+ "\u001B[0;37;1m", // White §f -+ "\u001B[5m", // Obfuscated §k -+ "\u001B[21m", // Bold §l -+ "\u001B[9m", // Strikethrough §m -+ "\u001B[4m", // Underline §n -+ "\u001B[3m", // Italic §o -+ ANSI_RESET, // Reset §r -+ }; -+ -+ private final boolean ansi; -+ private final List formatters; -+ -+ /** -+ * Construct the converter. -+ * -+ * @param formatters The pattern formatters to generate the text to manipulate -+ * @param strip If true, the converter will strip all formatting codes -+ */ -+ protected HexFormattingConverter(List formatters, boolean strip) { -+ super("paperMinecraftFormatting", null); -+ this.formatters = formatters; -+ this.ansi = !strip; -+ } -+ -+ @Override -+ public void format(LogEvent event, StringBuilder toAppendTo) { -+ int start = toAppendTo.length(); -+ //noinspection ForLoopReplaceableByForEach -+ for (int i = 0, size = formatters.size(); i < size; i++) { -+ formatters.get(i).format(event, toAppendTo); -+ } -+ -+ if (KEEP_FORMATTING || toAppendTo.length() == start) { -+ // Skip replacement if disabled or if the content is empty -+ return; -+ } -+ -+ boolean useAnsi = ansi && TerminalConsoleAppender.isAnsiSupported(); -+ String content = toAppendTo.substring(start); -+ content = useAnsi ? convertRGBColors(content) : stripRGBColors(content); -+ format(content, toAppendTo, start, useAnsi); -+ } -+ -+ private static String convertRGBColors(String input) { -+ Matcher matcher = RGB_PATTERN.matcher(input); -+ StringBuffer buffer = new StringBuffer(); -+ while (matcher.find()) { -+ String s = matcher.group().replace(String.valueOf(COLOR_CHAR), "").replace('x', '#'); -+ int hex = Integer.decode(s); -+ int red = (hex >> 16) & 0xFF; -+ int green = (hex >> 8) & 0xFF; -+ int blue = hex & 0xFF; -+ String replacement = String.format(RGB_ANSI, red, green, blue); -+ matcher.appendReplacement(buffer, replacement); -+ } -+ matcher.appendTail(buffer); -+ return buffer.toString(); -+ } -+ -+ private static String stripRGBColors(String input) { -+ Matcher matcher = RGB_PATTERN.matcher(input); -+ StringBuffer buffer = new StringBuffer(); -+ while (matcher.find()) { -+ matcher.appendReplacement(buffer, ""); -+ } -+ matcher.appendTail(buffer); -+ return buffer.toString(); -+ } -+ -+ static void format(String content, StringBuilder result, int start, boolean ansi) { -+ int next = content.indexOf(COLOR_CHAR); -+ int last = content.length() - 1; -+ if (next == -1 || next == last) { -+ result.setLength(start); -+ result.append(content); -+ if (ansi) { -+ result.append(ANSI_RESET); -+ } -+ return; -+ } -+ -+ Matcher matcher = NAMED_PATTERN.matcher(content); -+ StringBuffer buffer = new StringBuffer(); -+ while (matcher.find()) { -+ int format = LOOKUP.indexOf(Character.toLowerCase(matcher.group().charAt(1))); -+ if (format != -1) { -+ matcher.appendReplacement(buffer, ansi ? ansiCodes[format] : ""); -+ } -+ } -+ matcher.appendTail(buffer); -+ -+ result.setLength(start); -+ result.append(buffer.toString()); -+ if (ansi) { -+ result.append(ANSI_RESET); -+ } -+ } -+ -+ /** -+ * Gets a new instance of the {@link HexFormattingConverter} with the -+ * specified options. -+ * -+ * @param config The current configuration -+ * @param options The pattern options -+ * @return The new instance -+ * -+ * @see HexFormattingConverter -+ */ -+ public static HexFormattingConverter newInstance(Configuration config, String[] options) { -+ if (options.length < 1 || options.length > 2) { -+ LOGGER.error("Incorrect number of options on paperMinecraftFormatting. Expected at least 1, max 2 received " + options.length); -+ return null; -+ } -+ if (options[0] == null) { -+ LOGGER.error("No pattern supplied on paperMinecraftFormatting"); -+ return null; -+ } -+ -+ PatternParser parser = PatternLayout.createPatternParser(config); -+ List formatters = parser.parse(options[0]); -+ boolean strip = options.length > 1 && "strip".equals(options[1]); -+ return new HexFormattingConverter(formatters, strip); -+ } -+ -+} -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 8af159abd3d0cc94cf155fec5b384c42f69551bf..67da1aa7a21622fb231d19dede3775a282a4a12e 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -6,21 +6,21 @@ - - - -- -+ - - - -+ pattern="%highlightError{[%d{HH:mm:ss} %level]: %paperMinecraftFormatting{%msg}%n%xEx{full}}" /> - - - - - -- -+ - - - -+ pattern="[%d{HH:mm:ss}] [%t/%level]: %paperMinecraftFormatting{%msg}{strip}%n%xEx{full}" /> - - - diff --git a/Remapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch b/Remapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch deleted file mode 100644 index 08d7212876..0000000000 --- a/Remapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tom -Date: Fri, 26 Feb 2021 16:10:53 -0600 -Subject: [PATCH] Clear SyncLoadInfo - -This patch merely adds the extra argument "clear" after /paper syncloadinfo to clear currently stored syncload info. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 6fad9329213e4e8a3ef9ce7fb568ad22484a11f3..a6b2b69a5a79fb8cea81e55018ee7f57c8820e56 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -295,6 +295,13 @@ public class PaperCommand extends Command { - sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); - return; - } -+ -+ if (args.length > 1 && args[1].equals("clear")) { -+ SyncLoadFinder.clear(); -+ sender.sendMessage(ChatColor.GRAY + "Sync load data cleared."); -+ return; -+ } -+ - File file = new File(new File(new File("."), "debug"), - "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); - file.getParentFile().mkdirs(); -diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -index 524f33371b9de1d4dd6972fe59ffbe1804d7c5f3..0bb4aaa546939b67a5d22865190f30478a9337c1 100644 ---- a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -+++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -@@ -26,6 +26,10 @@ public class SyncLoadFinder { - public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); - } - -+ public static void clear() { -+ SYNC_LOADS.clear(); -+ } -+ - public static void logSyncLoad(final Level world, final int chunkX, final int chunkZ) { - if (!ENABLED) { - return; diff --git a/Remapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch b/Remapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch deleted file mode 100644 index 7997af8fee..0000000000 --- a/Remapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tom -Date: Fri, 26 Feb 2021 16:24:25 -0600 -Subject: [PATCH] Expose Tracked Players - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 87c719caf796f54296ff7e412548062e02af270e..ec30f886585d407fbd122e05107ebca44895c585 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -170,7 +170,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - -- ChunkMap.TrackedEntity tracker; // Paper -+ public ChunkMap.TrackedEntity tracker; // Paper package private -> public - public boolean collisionLoadChunks = false; // Paper - public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index d2d179cdef8129653983b01d94928ba83f64f644..ec8c7499662c0a810f1337ebc0fa24d2f3ca79e7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -16,6 +16,7 @@ import java.net.InetSocketAddress; - import java.net.SocketAddress; - import java.util.ArrayList; - import java.util.Collection; -+import java.util.Collections; // Paper - import java.util.HashMap; - import java.util.HashSet; - import java.util.LinkedHashMap; -@@ -2305,6 +2306,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - // Paper end - -+ // Paper start -+ @Override -+ public Set getTrackedPlayers() { -+ if (entity.tracker == null) { -+ return Collections.emptySet(); -+ } -+ -+ Set set = new HashSet<>(entity.tracker.seenBy.size()); -+ for (ServerPlayer entityPlayer : entity.tracker.seenBy) { -+ set.add(entityPlayer.getBukkitEntity().getPlayer()); -+ } -+ return set; -+ } -+ // Paper end -+ - // Spigot start - private final Player.Spigot spigot = new Player.Spigot() - { diff --git a/Remapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch b/Remapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch deleted file mode 100644 index f305e85937..0000000000 --- a/Remapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Bjarne Koll -Date: Wed, 3 Mar 2021 12:48:48 +0100 -Subject: [PATCH] Remove streams from SensorNearest - -The behavioural nearby sensors are validated every tick on the entities -that registered the respective sensors and are therefore a good subject -to performance improvements. - -More specifically this commit replaces the Stream#filter usage with -ArrayList#removeIf as the removeIf method on an array list is heavily -optimized towards a single internal array re-allocation without any -further overhead on the removeIf call. - -The only negative of this change is the rather agressive diff these -patches introduce as the methods are basically being reimplemented -compared to the previous stream-based implementation. - -See: https://nipafx.dev/java-stream-performance/ - -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -index 91295b8501b1e9d60bf9a7e954ea7fbce9cdea7f..0cd5a19beeb6103dec454b9071cc2e40adf2d006 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -@@ -27,18 +27,16 @@ public class NearestItemSensor extends Sensor { - List list = world.getEntitiesOfClass(ItemEntity.class, entity.getBoundingBox().inflate(8.0D, 4.0D, 8.0D), (entityitem) -> { - return true; - }); -- -- entity.getClass(); -+ // Paper start - remove streams in favour of lists - list.sort(Comparator.comparingDouble(entity::distanceToSqr)); -- Stream stream = list.stream().filter((entityitem) -> { -- return entity.wantsToPickUp(entityitem.getItem()); -- }).filter((entityitem) -> { -- return entityitem.closerThan((Entity) entity, 9.0D); -- }); -- -- entity.getClass(); -- Optional optional = stream.filter(entity::hasLineOfSight).findFirst(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); -+ ItemEntity nearest = null; -+ for (ItemEntity entityItem : list) { -+ if (entity.wantsToPickUp(entityItem.getItem()) && entityItem.closerThan(entity, 9.0D) && entity.canSee(entityItem)) { -+ nearest = entityItem; -+ break; -+ } -+ } -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java -index bf38e8b465ae0f50e34b94e0d7830dfdc1be1d59..fa827377ef0ef7cb280d1d54e156e45579899e6c 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java -@@ -26,10 +26,12 @@ public class NearestLivingEntitySensor extends Sensor { - list.sort(Comparator.comparingDouble(entity::distanceToSqr)); - Brain behaviorcontroller = entity.getBrain(); - -- behaviorcontroller.setMemory(MemoryModuleType.MOBS, (Object) list); -- behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, list.stream().filter((entityliving1) -> { -- return doTick(entity, entityliving1); -- }).collect(Collectors.toList())); -+ behaviorcontroller.setMemory(MemoryModuleType.MOBS, list); // Paper - decompile error -+ // Paper start - remove streams in favour of lists -+ List visibleMobs = new java.util.ArrayList<>(list); -+ visibleMobs.removeIf(otherEntityLiving -> !Sensor.a(entity, otherEntityLiving)); -+ behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, visibleMobs); -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -index 41a9db2cc4af26baa7072b3c4cebc5357ff43301..fe7414293f144656a938de42524841592c9f40d4 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -@@ -26,22 +26,26 @@ public class PlayerSensor extends Sensor { - - @Override - protected void doTick(ServerLevel world, LivingEntity entity) { -- Stream stream = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((entityplayer) -> { -- return entity.closerThan((Entity) entityplayer, 16.0D); -- }); -+ // Paper start - remove streams in favour of lists -+ List players = new java.util.ArrayList<>(world.players()); -+ players.removeIf(player -> !EntitySelector.notSpectator().test(player) || !entity.closerThan(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator -+ players.sort(Comparator.comparingDouble(entity::distanceToSqr)); - -- entity.getClass(); -- List list = (List) stream.sorted(Comparator.comparingDouble(entity::h)).collect(Collectors.toList()); - Brain behaviorcontroller = entity.getBrain(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, (Object) list); -- List list1 = (List) list.stream().filter((entityhuman) -> { -- return doTick(entity, (LivingEntity) entityhuman); -- }).collect(Collectors.toList()); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, (Object) (list1.isEmpty() ? null : (Player) list1.get(0))); -- Optional optional = list1.stream().filter(EntitySelector.ATTACK_ALLOWED).findFirst(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, optional); -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); -+ -+ Player nearest = null, nearestTargetable = null; -+ for (Player player : players) { -+ if (Sensor.a(entity, player)) { -+ if (nearest == null) nearest = player; -+ if (EntitySelector.canAITarget().test(player)) { -+ nearestTargetable = player; -+ break; // Both variables are assigned, no reason to loop further -+ } -+ } -+ } -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, nearestTargetable); -+ // Paper end - } - } diff --git a/Remapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch b/Remapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch deleted file mode 100644 index e8d0daacfc..0000000000 --- a/Remapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch +++ /dev/null @@ -1,239 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas81298 -Date: Sun, 13 Dec 2020 13:42:55 +0100 -Subject: [PATCH] do not create unnecessary copies of passenger list - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java -index a6ecb82d14ccab5d8229689a2a6cb67c579b1f71..cded79352dff0978e0d633eae9d9020b4dec1d4b 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java -@@ -15,7 +15,7 @@ public class ClientboundSetPassengersPacket implements Packet list = entity.getPassengers(); -+ List list = entity.passengers; // Paper - do not create a copy of the list - - this.passengers = new int[list.size()]; - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index f4dd30c8b3326db72d3b3068ee2291de6f15de7c..c17e827a976f509c8294df65335f12139cd36a9f 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -2312,7 +2312,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - list.add(entity); - } - -- if (!entity.getPassengers().isEmpty()) { -+ if (!entity.passengers.isEmpty()) { // Paper - do not copy list - list1.add(entity); - } - } -diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index 75e2274578c2c28de3d786372df0b4102337a2cc..e703233db7879c73378b3a06b2e89f7fcea97979 100644 ---- a/src/main/java/net/minecraft/server/level/ServerEntity.java -+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -102,10 +102,10 @@ public class ServerEntity { - - public final void tick() { this.sendChanges(); } // Paper - OBFHELPER - public void sendChanges() { -- List list = this.entity.getPassengers(); -+ List list = this.entity.passengers; // Paper - do not copy list - - if (!list.equals(this.lastPassengers)) { -- this.lastPassengers = list; -+ this.lastPassengers = com.google.common.collect.ImmutableList.copyOf(list); // Paper - only copy list if something has changed - this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit - } - -@@ -375,7 +375,7 @@ public class ServerEntity { - } - } - -- if (!this.entity.getPassengers().isEmpty()) { -+ if (!this.entity.passengers.isEmpty()) { // Paper - do not create copy of list - consumer.accept(new ClientboundSetPassengersPacket(this.entity)); - } - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index ec30f886585d407fbd122e05107ebca44895c585..d055b362459e5b4658aa220e16118ee6174c0de4 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2233,7 +2233,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - protected boolean canAddPassenger(Entity passenger) { -- return this.getPassengers().size() < 1; -+ return this.passengers.size() < 1; // Paper - do not copy list - } - - public final float getCollisionBorderSize() { return getPickRadius(); } // Paper - OBFHELPER -@@ -2329,7 +2329,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public boolean isVehicle() { -- return !this.getPassengers().isEmpty(); -+ return !this.passengers.isEmpty(); // Paper - do not copy list - } - - public boolean rideableUnderWater() { -@@ -3141,7 +3141,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public boolean hasPassenger(Entity passenger) { -- Iterator iterator = this.getPassengers().iterator(); -+ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list - - Entity entity1; - -@@ -3157,7 +3157,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public boolean hasPassenger(Class clazz) { -- Iterator iterator = this.getPassengers().iterator(); -+ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list - - Entity entity; - -@@ -3174,7 +3174,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - - public Collection getIndirectPassengers() { - Set set = Sets.newHashSet(); -- Iterator iterator = this.getPassengers().iterator(); -+ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); -@@ -3200,7 +3200,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - private void fillIndirectPassengers(boolean playersOnly, Set output) { - Entity entity; - -- for (Iterator iterator = this.getPassengers().iterator(); iterator.hasNext(); entity.fillIndirectPassengers(playersOnly, output)) { -+ for (Iterator iterator = this.passengers.iterator(); iterator.hasNext(); entity.fillIndirectPassengers(playersOnly, output)) { // Paper - do not copy list - entity = (Entity) iterator.next(); - if (!playersOnly || ServerPlayer.class.isAssignableFrom(entity.getClass())) { - output.add(entity); -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java -index 3d919e878908e19d598d70011c44cf980676f4f8..debf53a8bf6f062a237160a7b7e0a251a9756ef6 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java -@@ -52,7 +52,7 @@ public class RunAroundLikeCrazyGoal extends Goal { - @Override - public void tick() { - if (!this.horse.isTamed() && this.horse.getRandom().nextInt(50) == 0) { -- Entity entity = (Entity) this.horse.getPassengers().get(0); -+ Entity entity = this.horse.passengers.isEmpty() ? null : this.horse.passengers.get(0); // Paper - do not copy list, fixed array out of bounds exception as well - - if (entity == null) { - return; -diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.java -index e512a38ccbba93266f0234e3b2fcf7f62693039b..7a60c0b2c301e8cb768c39ad20f273a5921428cb 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Pig.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java -@@ -85,7 +85,7 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { - @Nullable - @Override - public Entity getControllingPassenger() { -- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index b298bcfb665b1036cd21445cec1518069eb08f06..5901e92a749af50166c517bda575d541554756f5 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -@@ -971,7 +971,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, - @Nullable - @Override - public Entity getControllingPassenger() { -- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - } - - @Nullable -diff --git a/src/main/java/net/minecraft/world/entity/monster/Ravager.java b/src/main/java/net/minecraft/world/entity/monster/Ravager.java -index e50d72c98f2ee3cd3349d2df9a0cdc47b733f7cd..ccc9d941b28ee090436a5958e1b48589d48d9d6f 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java -@@ -134,7 +134,7 @@ public class Ravager extends Raider { - @Nullable - @Override - public Entity getControllingPassenger() { -- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -index 25df3ef6b96bec39847a732394af8eccdb4d5d45..23421c4964c67a963a55ce08595c8de112a2ba6e 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -@@ -560,7 +560,7 @@ public abstract class AbstractMinecart extends Entity { - - vec3d1 = new Vec3(d8 * d4 / d6, vec3d1.y, d8 * d5 / d6); - this.setDeltaMovement(vec3d1); -- Entity entity = this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ Entity entity = this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - - if (entity instanceof Player) { - Vec3 vec3d2 = entity.getDeltaMovement(); -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -index e7ac3bff190c899397d6576fabbf4966878ea7e5..37f0e359ec858eebfa15d01f23a9ce0103816c8b 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -@@ -316,7 +316,7 @@ public class Boat extends Entity { - super.tick(); - this.tickLerp(); - if (this.isControlledByLocalInstance()) { -- if (this.getPassengers().isEmpty() || !(this.getPassengers().get(0) instanceof Player)) { -+ if (this.passengers.isEmpty() || !(this.passengers.get(0) instanceof Player)) { // Paper - do not copy list - this.setPaddleState(false, false); - } - -@@ -379,7 +379,7 @@ public class Boat extends Entity { - Entity entity = (Entity) list.get(j); - - if (!entity.hasPassenger(this)) { -- if (flag && this.getPassengers().size() < 2 && !entity.isPassenger() && entity.getBbWidth() < this.getBbWidth() && entity instanceof LivingEntity && !(entity instanceof WaterAnimal) && !(entity instanceof Player)) { -+ if (flag && this.passengers.size() < 2 && !entity.isPassenger() && entity.getBbWidth() < this.getBbWidth() && entity instanceof LivingEntity && !(entity instanceof WaterAnimal) && !(entity instanceof Player)) { // Paper - do not copy passenger list - entity.startRiding(this); - } else { - this.push(entity); -@@ -726,8 +726,8 @@ public class Boat extends Entity { - float f = 0.0F; - float f1 = (float) ((this.removed ? 0.009999999776482582D : this.getPassengersRidingOffset()) + passenger.getMyRidingOffset()); - -- if (this.getPassengers().size() > 1) { -- int i = this.getPassengers().indexOf(passenger); -+ if (this.passengers.size() > 1) { // Paper - do not copy list -+ int i = this.passengers.indexOf(passenger); // Paper - do not copy list - - if (i == 0) { - f = 0.2F; -@@ -746,7 +746,7 @@ public class Boat extends Entity { - passenger.yRot += this.deltaRotation; - passenger.setYHeadRot(passenger.getYHeadRot() + this.deltaRotation); - this.clampRotation(passenger); -- if (passenger instanceof Animal && this.getPassengers().size() > 1) { -+ if (passenger instanceof Animal && this.passengers.size() > 1) { // Paper - do not copy list - int j = passenger.getId() % 2 == 0 ? 90 : 270; - - passenger.setYBodyRot(((Animal) passenger).yBodyRot + (float) j); -@@ -906,13 +906,13 @@ public class Boat extends Entity { - - @Override - protected boolean canAddPassenger(Entity passenger) { -- return this.getPassengers().size() < 2 && !this.isEyeInFluid((Tag) FluidTags.WATER); -+ return this.passengers.size() < 2 && !this.isEyeInFluid((Tag) FluidTags.WATER); // Paper - do not copy list - } - - @Nullable - @Override - public Entity getControllingPassenger() { -- List list = this.getPassengers(); -+ List list = this.passengers; // Paper - do not copy list - - return list.isEmpty() ? null : (Entity) list.get(0); - } diff --git a/Remapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch b/Remapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch deleted file mode 100644 index ec43d966cb..0000000000 --- a/Remapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheShermanTanker -Date: Thu, 1 Oct 2020 01:11:03 +0800 -Subject: [PATCH] MC-29274: Fix Wither hostility towards players - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index bbb1d0ed9e76f414dc7d73b4f7786891425f55cd..eb367b8feda8219a97a547c3ef6ab82d278d2f25 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -805,4 +805,10 @@ public class PaperWorldConfig { - private void setUpdatePathfindingOnBlockUpdate() { - updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); - } -+ -+ public boolean fixWitherTargetingBug = false; -+ private void witherSettings() { -+ fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); -+ log("Withers properly target players: " + fixWitherTargetingBug); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index fd91c80cd6337b5fa41d6060ecdb44b8fa68a16a..b364b442d4cb1f3351850140b85c62c30c888bed 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -102,6 +102,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { - this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); - this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); - this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); -+ if(this.level.paperConfig.fixWitherTargetingBug) this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 0, false, false, null)); // Paper - Fix MC-29274 - this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Mob.class, 0, false, false, WitherBoss.LIVING_ENTITY_SELECTOR)); - } - diff --git a/Remapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch b/Remapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch deleted file mode 100644 index cdc493b6d3..0000000000 --- a/Remapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sun, 1 Nov 2020 16:43:11 +0100 -Subject: [PATCH] Throw proper exception on empty JsonList file - - -diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java -index e2982a8ac5448110378bc92247952332bdffe12c..71de59cadcbd214b9e3a91a6051f918d9b421b16 100644 ---- a/src/main/java/net/minecraft/server/players/StoredUserList.java -+++ b/src/main/java/net/minecraft/server/players/StoredUserList.java -@@ -189,6 +189,7 @@ public abstract class StoredUserList> { - - try { - JsonArray jsonarray = (JsonArray) StoredUserList.GSON.fromJson(bufferedreader, JsonArray.class); -+ com.google.common.base.Preconditions.checkState(jsonarray != null, "The file \"" + this.file.getName() + "\" is either empty or corrupt"); // Paper - - this.map.clear(); - Iterator iterator = jsonarray.iterator(); diff --git a/Remapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch b/Remapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch deleted file mode 100644 index 46ebed8c68..0000000000 --- a/Remapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch +++ /dev/null @@ -1,400 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com> -Date: Sat, 3 Oct 2020 08:27:40 +0200 -Subject: [PATCH] Improve ServerGUI - -- Added logo to server frame -- Show tps in the server stats - -diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -index c0923ec75ecced2e0a1c0d3ec2c046d69af3e9a9..a3e17c1cb54938908d72d3e86e43f4655f1db194 100644 ---- a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -+++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -@@ -57,9 +57,18 @@ public class RAMDetails extends JList { - public void update() { - GraphData data = RAMGraph.DATA.peekLast(); - Vector vector = new Vector<>(); -+ -+ double[] tps = new double[] {server.tps1.getAverage(), server.tps5.getAverage(), server.tps15.getAverage()}; -+ String[] tpsAvg = new String[tps.length]; -+ -+ for ( int g = 0; g < tps.length; g++) { -+ tpsAvg[g] = format( tps[g] ); -+ } - vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); - vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); - vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); -+ vector.add("TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg)); -+ - setListData(vector); - } - -@@ -70,4 +79,9 @@ public class RAMDetails extends JList { - } - return ((double) total / (double) tickTimes.length) * 1.0E-6D; - } -+ -+ private static String format(double tps) -+ { -+ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); -+ } - } -diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java -index 2567c588a1dcf732800e6cf87352b020c7bb84d6..ad912fae191777256dd88f6c863ec92f8b6a9c13 100644 ---- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java -+++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java -@@ -31,6 +31,11 @@ import net.minecraft.DefaultUncaughtExceptionHandler; - import net.minecraft.server.dedicated.DedicatedServer; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+// Paper start -+import java.io.IOException; -+import java.util.Objects; -+import javax.imageio.ImageIO; -+// Paper end - - public class MinecraftServerGui extends JComponent { - -@@ -56,6 +61,15 @@ public class MinecraftServerGui extends JComponent { - jframe.pack(); - jframe.setLocationRelativeTo((Component) null); - jframe.setVisible(true); -+ jframe.setName("Minecraft server"); // Paper -+ -+ // Paper start - Add logo as frame image -+ try { -+ jframe.setIconImage(ImageIO.read(Objects.requireNonNull(MinecraftServerGui.class.getClassLoader().getResourceAsStream("logo.png")))); -+ } catch (IOException ignore) { -+ } -+ // Paper end -+ - jframe.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent windowevent) { - if (!servergui.isClosing.getAndSet(true)) { -diff --git a/src/main/java/net/minecraft/server/gui/StatsComponent.java b/src/main/java/net/minecraft/server/gui/StatsComponent.java -index 09414d04208a843f8d337569b53f61b34e64ed92..d2583c762fe655dd1d7bed1061e41cd08ac0c092 100644 ---- a/src/main/java/net/minecraft/server/gui/StatsComponent.java -+++ b/src/main/java/net/minecraft/server/gui/StatsComponent.java -@@ -18,7 +18,7 @@ public class StatsComponent extends JComponent { - }); - private final int[] values = new int[256]; - private int vp; -- private final String[] msgs = new String[11]; -+ private final String[] msgs = new String[12]; public String[] getStatEntries() { return this.msgs; } // Paper - change size, OBFHELPER - private final MinecraftServer server; - private final Timer timer; - -@@ -37,8 +37,18 @@ public class StatsComponent extends JComponent { - private void tick() { - long i = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - -+ // Paper start - Add tps entry -+ double[] tps = org.bukkit.Bukkit.getTPS(); -+ String[] tpsAvg = new String[tps.length]; -+ -+ for ( int g = 0; g < tps.length; g++) { -+ tpsAvg[g] = format( tps[g] ); -+ } - this.msgs[0] = "Memory use: " + i / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)"; - this.msgs[1] = "Avg tick: " + StatsComponent.DECIMAL_FORMAT.format(this.getAverage(this.server.tickTimes) * 1.0E-6D) + " ms"; -+ getStatEntries()[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg); -+ // Paper end -+ - this.values[this.vp++ & 255] = (int) (i * 100L / Runtime.getRuntime().maxMemory()); - this.repaint(); - } -@@ -85,4 +95,10 @@ public class StatsComponent extends JComponent { - public void close() { - this.timer.stop(); - } -+ -+ // Paper - start Add tps entry -+ private static String format(double tps) { -+ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise -+ } -+ // Paper end - } -diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png -new file mode 100644 -index 0000000000000000000000000000000000000000..a7d785f60c884ee4ee487cc364402d66c3dc2ecc -GIT binary patch -literal 14310 -zcmXY21yoy2uugDycPmm{N^yd_Q`}vP7YOd|PH`>8wLo!q*HRn`6f5rV?*HD)IX5{c -zxpy-=`|Zxo_svGBD$Agwkf4A-AaprdNp;|J21vifLD%hMrT$lZeEex|7Xe0mqFAZArC{!qp)zJmbab@utqA`6 -z61Z~|e!k$IbXNT?PvGuuzT7G514$8e!}lsR>%nURMm+~pde``@(!O=ISt0%B93;Ez -za-qRi4n0Q>zQ2#2^_y08QOl3jT*!Ir5@<8VrFx(6f9sP|H8ttjftN;wrX>jP4BcG1;MfU5x^L`zc09u!bDBt#+ll=7@ -zB;}A$BKgu}V?#qfHvm`~pt%wG2y{MOc%B!8I`p|pc -zO#?sq!Zd&j8UPmvY4RQnfo>!6{a}GFV!}g@qu<3Wu$07X(O`vikNW$~q!ngF23Ls2 -z53p8js<-B_Qd?xX6rtq43Mdz(jOg2QXx#Wng_9^1^^~KqFNq{Kvb@Ap9}bf&xFA-C -z5+#cQ`#v$A=kd0O=agATcleBaxXf_(dnqbQz|cL9R&&Ni1omTs+6~YApmk)MCghxj -z1}mq&IU>1nEiF=q=PI`%jQbyRd=hVI83Sm{E-4uTc#w;NNwEW)C(C`xvWzY_%`_MmO -zD&g-sEaE)}6(&g)y-N&rNy;5@+{M`}!{60Y8wMgF5;HmO#B~hG`W$;7xLG*yF((rq -zxP6I#r#o`B3FppK{v(q1!C+YLFSfySDcHyoW!}EfzuCB1B|C5+oP}dtocnwkcNy1EZ6#5JX4=ePl&cu~0tMnt&79+I4%PaK>VqFx;r!QdNmnxlEqdU-QR%Nmu{aWP -zJxwXvt5fFTCOVgB)Zq -z%H0U=9q7Y0lu&1kc4zYT3*lHA@XJfoK>3WFM&WWf2u6^+wCm8##D$x@Gkw+t^HoO( -z4pxDRqg;$5S=t^k22H5^V3V0Qfy%Ogl8I%LD$52=7)J>Ki9Ej1HyEi_ujELlz8$-+?cdD1Zxi02kW0 -zaY=caFq4~s^R?zxcc3Z0X|az}Aww<{P$>6rk+5Di5J7$kWor0{Q&>+DWSBH^Gf`SP -zT{4}IOFh-hB7xwBdewq%de)q6QvxorV(()2>@j8i!kj)=^hN -zl_N{$9xTHHA;V&Zx#tX&1pOO;v^NiOP#_UK@J;;lp+OOhOOO2mlMdxM;Qv-mWG+^vzox|8t`w| -z=gPlM3)y6G*hfV1WwuMe>bO-vP9g`h5BqgO9x{ROBD;aPl>XDmvt(3PUxt|4RFRpK -z5OEtRz{(Oa_W_!Z4XHf#h;Z-~71XM7wlF*L!-#h_Uy2tGuy-rAZ)4{qE~feNkp}qf -zgvBtLkFPI~I7%C=OHZfPZz$j>L9)rb;l -z@J^dxncy52;wmHg=wC3|Xn6jPYCR7xc}~D0wNjoYxmoRh_zh=6@8coM1UQIa_z*1)cZPw4v40qoZQp-uy#DLv=oP -zX9b3vzFA2r8}|_AO8W1(OMG__0{1AUD&Z%&7-(>s+Z-X6Sv}G5QguIbZ3mYa--?09 -z;wNw?n=yAag4%m#w$$-YZ{(ZJUcwHfzu&!gykNjG)e}!=q8xy2_KS=ULsQwv45NK! -zVqqD8#S{vRjg4(Q6HM_F&tihNIQns<%DVjE$cv33ET>Dvc^#{z&#u&&9RgXO?ZLuebczKv#;! -zCS|2lIa37Bp#3RWj0$V3=I2>o40{(J^LD|EUH?!2;Z&HS*>7*V%{v1)wHaUP85mcX -z%q!K}Ntr*IzJD%++btJ;VQO*OjJL1t{GvR3cy@OC-~pe^bV?N`z0QKCr?Tom)4u%A -z3mi2k&eIgh0^rGI#Di+&3lrsy-r+}zwBkDQtswtPbkj!Y^l`{f!# -zLseC0M;DiifDa!({-G4{W$Wxsgv*(NX%HMyXhArVwY105dUHg?+=@6Sy8n@slS76x -zU7%PI8ToKm#qahfR;7kn#|t@9y(0EkooWBDqA1(mpO)>BBz))giBi8xVHlj#dR9U8 -zRo%`iBdlj8%_tRn^qa%T>{nsLLwTNld&WHLyfbPzv2W62m6q=Nsdxnk -z#{P==5!Lidx3bcr_qlUl%BX!xjywA?jv>FU^mJDa0zQT9Kw8RRHq>7B -zb~DXw0(oqBrOQunsm2ghWV2i1VmN{F?)U;0%*j{FEUxazAJ3)KSWomuhklkDi?5h*MTLDS5ma_Nk1sNZYzZ#$maGRyiXBzjG@(G__fuyBl(^A>s&{jF+J%5| -zv#7nD1XK806#_U_4#N2ANAxznk%;U$Y$z#{K*O07mADqx6LjACqwP<`HFV#C6Q*wx -z8JVP_qGF}V7B?^8)f*2F5AON7v$L~Kr?2}oPai_kG!_6MI(U`LS~+Mo*CSyrw>pPE -zllqxy -z^&rnDn4XA@AUY7~`1lwTCrm8KlVRqX&!kZFH&;i9@=R}UDxNSh*)Iq2U+#9}@ag1t -z%KUOEw0DXT)>hQoLTprY^z=BC=8NAyi3pZWT7A`?;rI<3%65Nqb93%pJ=!+dNtB>W -z7f3O-e-S7ZBgBntcyt~wOG_p$AU2zlGH8=%TEm+z8kLYReEMTkIo#2YiA=iKWrH); -zS%uT3xAyyY=!U)0Evpgx{{38MPR2nN<3913M<0O#YCO=TSt^4IzV3^D%2zC>t_OO} -z_h~AVOk+IIi$Ov;-g93a4j@WaekCC#HFm2_Vu9s)8-GbYtr{LgrxnSIN^PW9)!jYX -z?%-yssA~&R3F)C)wj5i|@!atCx?Qy%P1QEGSZm;iUNai`-F(8a%y+_a>CMzx$XEKx -z>sW|JbN36s+Y{4SZsrspH%UH=+Q6J`c&_-JLGL&5|$XUA1vFOC+rgoc&xT{dFT&pMaEBKwyD;plX0>2nla;jTlQ{!fn2M=Ak*=K*g% -zBm0-$ly1~}CT-5gv){jex9)7&b8u!a+vYHXU>=NF2>g3+_rN{(LUMGwRWKk49sS$v -zazyX8zZ1hwZ|U*5{fK@i@hRl*U%Q2cg+!iIfb)6W%S5F{91qinEZE%~4Gl>rBw9S< -zMP5$exl1jESyt}d~jo?hf`z^32b!}UGtJH+w9(0UrI#~Ei*ii&6z(AVE?(}k_A -zE9Z@mj7HF-ch46I0ipe3gapRj{=zk_J1E^b_JwdrhKi4ytBuwP)m>e$@9v`A{1N{h -zwUN6H=_W+h(a?rGaQ%%LP5C4)XiZ*`1uUwgqWvk`LyDD!Ps#Q5oI($KDJ%8n5kBi- -zghsLx`~mf<>WT)6-cJBbp|htk1NfkZ@e#B4@l?UH7!MDMpO?1NETGk_Eg{z!N3!D< -zWg8gtgS%b(0Bg7dw9u35xq)1vNdnM8iu7Eje*u?#sZ~%^q*HDaZC?5z4ZzhSA%ndS -z4&$M&7(|(9nWY%QShCnuN0 -z`n9&UeypypUgx;R+x;XM#8uDM{p`9~j<49)^dotHJVO*A@HL&g7F={FP#trj@{dzm -zeQUiqRWJ&pkKkA1O-|vOf8O1UQ$$0lIExffio|}F@ROV#MXcPH$ -z?$$kxAF@B#KT}u;R@SVyIO>1sw1!i?C(_013w9@?8$bKaLQi34zC$g*^}F&(%NEO6 -zQzD-^6}HQMnGJ{h$J*)HjSxjblWegsW&rLC8Ov_r_20jLjUS$Ptnm|p9fK%r0j+4; -z57^mjL&lISh8>DC;eB$B69$h4XxE3qU4T&zUpDeV@4g>or%D-x@qhie>6mqD959ck74(h?S0BA0}YQ18d?hr6}%}y{%ZNJ^-(?=Op~; -z#2-UNh)jH9>RXmvPJ(Y!8(uhyW|sFpyvv)AaNeljHj^Fx+RC -z!`@c->W1C^FUKHmG2w_atkdsMnzY+l!CV8havQ8-Gu)<8t{#V*2Pwp4h?ayXsi5Z> -zo!guta>TA~iv#iJpQkN>#)QF%As@2WgU&V_Y^qm#E*O}M_ijJfFWq}ts)-l4>D)kCqJJ@MG2$69ph0jzwI8ry1u8D@CyinC$oT?7S*Z}Eg -zYs}PWLqr4u@)w}#!{cMx;KxO6W2H6~3k$laJjAt+C{0mmCRnfs=OJYbh}HMh&e`#> -zj;jrpjqKCh41OK{FOS`@_sPP$iCm46G^EMNk8(l-1f>!gEV+4vMVRZ#8infUenP+k -zL^tBOHF^=)k&U-Tw{gfijqQ&^ -z-RHHII5yp}2|o8pTsf6x7$teW9Em!~iy2DN?D@|U)g%I6VG%JBO$|~;c~1Q^3|x`1 -z6HRbq1#~Ke)wWpALcc&@P;m+*sGavR0{aOx3=IwUE3YPWAwV45pzD$~02inxi7(6X -z$zk683M=_r#M*+6fQ)&FK0y|lm7JLwS)K=t&ZJk!U_-y%_o@fhr{s37MUEQOF*M)3 -zB$;4>Zx;Xk*(hwFjb>1iJ1f*D#nyWL{=>{2|9*^vCNN!%bF8Oe<`xz#s;jFz?;I}4M3lL;!fy_;J-E96Of+;sG%K=fZdR)99pJ}fM( -zq%(s8UrsEL{NrdF`!#RY+VjFyPpE_vtqPMM!MQ+QnE)+_g9Z^{4^;k&Sa^=w*yuxB_*Z!U%!3{_9Qr)Jfz4IeS#io4oj_Kqhq`HCUub|Ke!v$1-$v=kc+O#rlCej?%dhY -zxxKUTsFPG1nfoFp3%7@gh9S?vM0N27#*fpJyaX;Vy{!pt*}!9_mX9uC#J5RyjknW2Dm3dCvZYU -zSW?0kvI9!o2un}*%`AYhr^CQT1aZF=-Nt^atn@Kt%b2!hT(pK!|MclbBv3-<+6{>_ -z8toMfWc9rpOk(8|KW>Z-k>Fr(xc_+q9ocf`8!_n}XYUrW?Ax|*_|=5m*4F0V+46wJ -z1IGS^Z5t=0Zj86J2MfJc -zUq#WKCfhoB<;P2&&`*_G4^_0uqDR20m!>T8ay_rxSzA&9_v5##g6tzXTkx+KRfz32 -z9vvpp?+YxHTxDthCBu7)&Q052y4s9*$M4_2w-OdPyK?F-EBoUuSsIk@@(!gA*A_!0 -z2eu1y;-Q$Ut(M>8FCOtw?vZR-%*ly^x)<95vK@P0tJoZws@+M*NGhg_NU`!}DZnWBHQz%*@6))$BWN;EM0xAF+B4Mph#S??J?K+&viwPmes*n^HGDL9iBf -zCk|mDu46wwughN!isu&G((DO>Ws`(VLY?^#w=RONxUgFGby--Y=5NJ|(>qXOS`;lZhmXyMEyBdVM@jJh71E-})~`?t4w8^Kwy) -z<+KACjs!F^TS-;FT24_iWF+=l(nR}j7U#;Vd -z)IT3=b&}A}1PUKFa6DKfgHkJci!~7u?a%k9h7Rri^{y`|;;xNDoQbV}+oJ=LdApL}|77o@C= -z;~aed)XpbrMtt1x3gHPWxbliQH4nKBCew{9 -z*-_PTyn~`1VrwKcc4ZrhI^!MsZ{D0O0%O2!SHHi^Dfyr9*x*DGFKwc()b;q6nM*M7 -zvA$x_?$BMJJHN5HIn9Ps{_7-sn79~BZegaa5V;s(BA<5BnU?^AeJHXtd)cIj_UCjA -zW|N@MjV~vrJz{sE0Dzv}tXxUDQAXm)1(kX7C_ZVFX%!TlZ850i(P1A0BxaJu)#LcH -zoxMFRzxoxw$bM=B6gpuMD#vcsa^00?%=D+T9-dQqV*=zD|)W!3BLun2&^n)~$ -z2_^{i9~sGXOAsF_S=k&4mWJ@`mD+G%MiPTlhuomboeFNwHb(< -zVpVR!mwf;JmpO3JL|B%L-!;@7TG}+`HZA;-{VIlQGY|T=f|!9!S=!c?sq5|KeEQ*~ -zm!1xeZcJPbSsfjU9e>K|=Ni<+YgrIG!|5@|Z>4bjx+`1j^O-{QK8XARf -zUG$nLRiTEtt;)9F30rvw>nj)@vCF{$d7>o2n>}~Y2^^C79l@s`uXRZOcuy>^%2@t- -zRGv={pKlDXFUgvG_^DWGR==il1rIzn{$p4r(FVOQxZi!_*Ksfl2hR{Aj>01RbFAM= -zpr0wzMwlOwlkt4|JLK)$>VL+{4nv>^`yMa)T;(9f*B(9;{T+)_=M4dN>M&&hS-#(G -z)-sW(WxVkHR)`x#g)25Lu7qnN;~Q-bvKDZ=;^fyLy@okDpvt&ZU{!U)WVtmnp -zAN-CzM{jPFWep9NAKDDq@=kynkGi_GQ@Z2y_Wn)xc_q3-&+9`qdGy_{PF-2c^$)%x -zd0sonEJhtG*2|P*Q-f_3`Akk96HzBz2 -z!5tnJaCcA2hGQrSw*{F)epvfYX?7toP=O0dN -zizY2w`>O@4Vqff!dBhQ^><#TjMP}loM9ProiD-Og@$V=*zQ|Avg0D!+96lr^u(1fl -z3J52PHoJYDdvdiIW?q?JIC*r?88VruLx#bp0lys39v$(c6uC*j}2IFFh -zViOX|K+DH18cd9%Rgjs$*sXuoW<>p^Fv-7CV|zpgTUnj812pyyX-nhA4TZ^UyYY9; -z?}BOarTT1q;0xSTjV_DPWE11?Y2+wSA*ybzebDoy8JwhznKa6SvYxE$WswX7Z6pG$ -zsA2GgHFFL3^zA@XTYK{a+6$Q8di%@1-|q9U15y+~R-L7Kwx8*xr(FP{g*JDPa`e((jSl#~?Rx=3ne(nLfeP9k0grubJK -zU4euzZqt~$Cl%k^{-!e6YQZi|D3#+MUS}VsYZ)0S>y@)kyqRI?A_esvAu-{`1Uq@! -zC+b`wnMK&<_mitl+k@e*$*{&S>vayX*>D>Q5sw2FZ?l(8ff%(8lo<^mBMrwQXOXe+ -z*7sZdWzBTIwZO$y^F)qZL1XbOMY<@M_a56y{({Vg@YN<_y}toq41V%~w=+4ZQvg)X -zVw~l$z-sId^nKU%dlk7W(mG}eS&KV2BdYqNJnX-p=YrG&&`_m0fzA_|iKD${5?oL* -zdS$heR@%Q+(3!!T&k;tIN|v2j=UI))rgkvyC7MTTrKP3g>Fma@_R0`GE5(tL%sS$7 -zG41ag%(Y(xZ5cjlk=R~(3XC+$25r*Fo=G5OhGgR}i!nDoG?^sult?Eo*x$x6CH-3L@LtZ0dfq!Bbbw-S}RwlN%lpH8c=4l2qH -z1wRszHSPh~=esnWvXD8B{D4<}?}6cA+@Ob1760Is6`g!zl@WL(L&={LA}SxAt0>Tw -z%b7i^&yNKM;(vGcNwuxAK{g|S3Y1&pH_6U1G -z3M4zx5FU=O;=l_?VzQ-~bx~xN1axPgYI0am3d25BjYmfSTX7Q}==Vcryl6@Se0(Jv -zxKW_o%H`jdnC7QXlkFbCsACHN1Dx=0gf<~@PW-&<=`1Hd)@#ypH7%OpalDj-P=ts+3^~yWs~TV}BD20HjkW6zc1L -z0#HzMkn3JV%7N-18_@tgE82*YnmEzxirriDSx#_|<|q1vL{k}7>^mRzO(ueTSN2~H -zG}kxp)Qn!&)><3|e>62+GXSpQKcemfqU!&BHZ5Ca;DT<63bBM&uV1BDS?MM$M;x8w>gShAPMxJM^BbMZn}Unm{OC9^4x3%% -zlmX8!km-u$N4fQXQ>jRe`7)3+RFGjhz -z18zf(Fo2<>YV^7LJO^UTZ2Ivd#mpN}o?7pBV&q=f%ID>haV7M8R3jsF*@a%iwIy>| -zsZ!-y{!%&j7`B?W8TcF4NH-RHH1xZ{;7BsA<#APu!;cND)te)FhoXz$BIU}2&^7WP -zT}TX>ZO58$VNPuh6JV7~s(W$vAj`^%AtUamex3YdVl3~4+pqk?G)qUibNMrj0*M25 -zY>5Ac|Dnv6xBQmV#$3JA?&HTN(lYl~J}@$l{*TY^kORrCB)3dDO}^^v!dcLf^CHty -zanjllIQeSLmpuG+h&ae`r*v!C*0A&W^a&q>93?BAXzG7n -z2*3TGPIcN`-_hY9&oaiv#fiv~>}7`T`4=pInEqWX*3e8+yPm^9h-tr&ts55$l+388 -zW)~F}2JH!}VLbQ>?6~H@&k`MnSsTeVj0TRVP4jGbP*!!CwM6`Z11c)yI2w$+R0zxo -zT|obYS1&&`{>>Z9(jnVU&=yI*%PGe*f78ie*_9oap?sd7fx7{r^WT>=XHF -zl`f{=UJEn2?tRw`Fem?eRE6#*nOes(ebRcmaK3~a3{a3EyE1zXSF0p7I_iDJ&%;3V -zU;AS}e?*mH#Yh2P9E3QBigIqu2iXf=@t)2+I~f*_E^JtEP1@IR{CBfTj%T}E3e#n% -zUa{@vU?D$l4DEANwkkK@ruP4ta)E*e^KLGg%$PizyPmHvKNMWtuJQ6sPXY=(1m#>W -z7V?9E!Vj}>a|KfQx5ESpH+q6$@gAp-P#~lbz`aj1_?xinN>3o8b2-Z3w>UZ3QZ}W0 -zWg-!>p>AADDcU^4;0*L4UFgB0QLlXd^y1E&4>txV!T|!`RwjZGl`;-4ZgFf>luHIy -zZ8d8Rh{I3r!g-ht6mAZxMB6VxRqnA0UY`h|mJZy2 -z17BazT$jMKFL3J6Ue_HL1^)4s%$Jj~Qx~1HG#tS@kwL(KP_ZI3dWz0SH(sqj#-*TNGsIWqPj>cj?!GyWvfdEiNOu4$>MIqL=F&Cc0{g*~L5 -zA1wt)=_zMFUkCT5$l!G{1-Y9QtGQ#qm5E(3fYPms_EP*sSVI)bfXN|uNO`BqVuCvd -zv)z8IGRgtM1<_trndVhQ^xA)wn~*W~#d*X@E=W)jcQWI8+?kdzHe;DZ`%+JE%gE}m -z6H=FO8rJxM{N90S=Gi!Mel)TyanxPa;E}C?hJl@e9UWad->;S|v;axgFjrY$z3(rV{MiJ}3M)t;Q?P5wZy0e3G{dcDO7n}3slDXLMrB$;#*W@Qv)D$=?Xs$F(8eTcyGIQ~IWgD%Gn&E>F9y#o>cR-7spE;Rur<_E~Pu)e0I -z#&y1|@8D~8c55<|KMf;&x;hg!A%VOZ38_+uk`jH4#=b9M&xcpxV-7cMN{jXVRnKSe -zlKJJ%=VBV{$DNeI1QkiA;DfdVT?$;O#22z6v6bTK9)fjrfIh!Hq__l~KzuNqT{&kA -zKs@YV6^1ZLGjTgR%(=NHS-DvWnnP)NM#qbHINqmQdCE5??co$3nuikqgm=s7*#Kd*+j_weKrZjMeLeHEoiJm>zuDRU` -zh~ggr^knneWU!Nn}AQt=0Id6Hk; -z4bJqse|V$H`stT?NS0yreYvaZ9YF!fw+N}{3#yXRU!C7?exl35BDC%+!jDMGT^DN# -zN9FGd#5t#;$h}5UgQ?q-Gr15>C6=nLUszle9<+_!!oi_m@_L^-R>_Qty7_g|C%m|5 -z-7^5X5V_ARi?h9_LW%2vByD3X_IvUktqBv{%SYXO1&;e&O#Ll_cfC`Wv1u+l_#RI< -zQ5Kly0;P`%TXaQN(heOg~>V&L{d+ZDA%eq-UKo#1)$rkjSm=nzAE2r -z5--RyKhxfXoGVU3^ab{5XGlyL1+26foG)4HZvN -zG@&I3h0fnK5lIjcrg*XxPy1(gK3_TN`&VYnxP;C|j$~0rT$0f|*#=OzM^NbE-1T5D -z%Csnt)n!sx3N#b(8G&+G3W~Q_B#StA6jZZ=p#wuu`DrAMXm{T@#S;ku4Dme@{Njmk -zCtrh3z6O>o)~o{&Htx+6kn*)$NNBH-biu^aYtWUq -z(G>4rCEKr#tO>!x8A@%W@6g)Xs%2Hq!y#Mbb@9R2@GDWi&!{jhZvzQ1D9nMuPoOS+ -z+cj{9nx5X{jJOIavbFf)Kz5Jnbe5Bu#(XE-z$j&iaP%c9W59OoT0~|N#D*(N2kz={ -zs(|)nH!_+_g1)#ZH2xk>ZTG#6WN#qa3BxZM{NWxq`*#$H255k6Ky?hw*hSA6`c_fl -zT@Ua%E5Ez3;~`kQFmrC#$Nlvc_Uy3#yzhd-6UYuuIwgIBZZC-`dwOBJbfurL(FfhH -z{YkjE+9OrOveY`{t{sGw&51YO1@{iO4)Ki=!Z5#q=m_Hi)_j0`>?;t2j);vv%BUif -z;wpTZdLQLsGvZ()DCdxYudn^Pt;BZ}Rin$4F8h{R`HxT2z`uc&aMXIQOvwgA5%{&) -zFW52MiN!$!EXgx}Px~e1!EMp;#&kY65oDho95j~!qD%YJr`+aK4jCJ4UJ^;q>w@Lf -zvDfg|M`S^@DGxu+7aR3Cx#;%?advj&1~L-m -zJqCP9&TW3migV*`Z$#)Qa>3>Jf)g9D6Ki28P@iX(uso)hic8Dp1F< -zeF;(n8Po8A*~^T{De(J)Z2nqLl@Vv3yoSlGwq0aeOg4ymI(KIkTeur-=J-yp9z?qe)it6gq-wl@I -z0D-_I{|T<5kwD9uH3yf1GWXp5*8eOgJf*q0IRoK|+r{}Fug&0WpNDKMTC@(Xc)9K8 -zy`lByMn!1fnY)1KYP(0Je1)c~WilUuh<&Q8^OE?L9Q^xK*Y@M$`6D6TDCZ^@l8{|} -zxmmNw)mng$hYBii+&ZqedxWT0dnV#LG4zC%+kzcK+-??vEHT>Q-T8zu|s_1IbA#OV)^+1pg1OmmZn` - -literal 0 -HcmV?d00001 - diff --git a/Remapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/Remapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch deleted file mode 100644 index 1099f41d55..0000000000 --- a/Remapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Tue, 2 Feb 2021 09:17:59 +0100 -Subject: [PATCH] stop firing pressure plate EntityInteractEvent for ignored - entities - - -diff --git a/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java b/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java -index f12bf33aa8cc8043052aa1048087f61d9a6d4d52..ae5b052b80665bfba126f5ca5dcd78608cb27d48 100644 ---- a/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java -@@ -81,6 +81,7 @@ public class PressurePlateBlock extends BasePressurePlateBlock { - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); -+ if (entity.isIgnoringBlockTriggers()) continue; // Paper - don't call event for ignored entities - - // CraftBukkit start - Call interact event when turning on a pressure plate - if (this.getSignalForState(world.getBlockState(pos)) == 0) { diff --git a/Remapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch b/Remapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch deleted file mode 100644 index 950227fe76..0000000000 --- a/Remapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 19:49:15 -0800 -Subject: [PATCH] fix converting txt to json file - - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -index 603b4f841bcc276997d130f1545c4cf550dcac2d..2eafb7e27d06a975cee48cc18c7596d610483d16 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -@@ -18,6 +18,11 @@ public class DedicatedPlayerList extends PlayerList { - - this.setViewDistance(dedicatedserverproperties.viewDistance); - super.setUsingWhiteList((Boolean) dedicatedserverproperties.whiteList.get()); -+ // Paper start - moved from constructor -+ } -+ @Override -+ public void loadAndSaveFiles() { -+ // Paper end - this.loadUserBanList(); - this.saveUserBanList(); - this.loadIpBanList(); -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 95f9863bbccaa23d08c409792314df4f2397a317..c2947313cc0eda3247fb4b20ddd1d0b86c37c50a 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -195,6 +195,12 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); - org.spigotmc.SpigotConfig.registerCommands(); - // Spigot end -+ // Paper start - moved up to right after PlayerList creation but before file load/save -+ if (this.convertOldUsers()) { -+ this.getProfileCache().save(false); // Paper -+ } -+ this.getPlayerList().loadAndSaveFiles(); // Must be after convertNames -+ // Paper end - // Paper start - try { - com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); -@@ -257,10 +263,6 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - DedicatedServer.LOGGER.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file."); - } - -- if (this.convertOldUsers()) { -- this.getProfileCache().b(false); // Paper -- } -- - if (!OldUsersConverter.serverReadyAfterUserconversion(this)) { - return false; - } else { -diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index 941b7e356c377fd8ad4e27409cd74c0046878396..f23ca6bebf2c0b7e02dc6aa51e384cee4e3d12c3 100644 ---- a/src/main/java/net/minecraft/server/players/GameProfileCache.java -+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java -@@ -243,6 +243,7 @@ public class GameProfileCache { - return arraylist; - } - -+ public void save(boolean asyncSave) { b(asyncSave); } // Paper - OBFHELPER - public void b(boolean asyncSave) { // Paper - JsonArray jsonarray = new JsonArray(); - DateFormat dateformat = createDateFormat(); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index c962b6fc0c65dc5e2ea636220727bca63bf4b740..dd121ec8f779b3786eeb7fe85519cf9e472f5adf 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -171,6 +171,7 @@ public abstract class PlayerList { - this.maxPlayers = maxPlayers; - this.playerIo = saveHandler; - } -+ abstract public void loadAndSaveFiles(); // Paper - moved from DedicatedPlayerList constructor - - public void placeNewPlayer(Connection connection, ServerPlayer player) { - ServerPlayer prev = pendingPlayers.put(player.getUUID(), player);// Paper diff --git a/Remapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch b/Remapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch deleted file mode 100644 index 33286aca0e..0000000000 --- a/Remapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 22:40:34 -0800 -Subject: [PATCH] Add worldborder events - - -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index aaa6251838483de5c46913534413151b5cb1d3fe..4ad686f4fcd3a23c4230faa03946db1f338bc904 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -14,6 +14,9 @@ import net.minecraft.world.phys.AABB; - import net.minecraft.world.phys.shapes.BooleanOp; - import net.minecraft.world.phys.shapes.Shapes; - import net.minecraft.world.phys.shapes.VoxelShape; -+import io.papermc.paper.event.world.border.WorldBorderBoundsChangeFinishEvent; // Paper -+import io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent; // Paper -+import io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent; // Paper - - public class WorldBorder { - -@@ -102,15 +105,19 @@ public class WorldBorder { - } - - public void setCenter(double x, double z) { -- this.centerX = x; -- this.centerZ = z; -+ // Paper start -+ WorldBorderCenterChangeEvent event = new WorldBorderCenterChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), new org.bukkit.Location(world.getWorld(), this.getCenterX(), 0, this.getCenterZ()), new org.bukkit.Location(world.getWorld(), x, 0, z)); -+ if (!event.callEvent()) return; -+ this.centerX = event.getNewCenter().getX(); -+ this.centerZ = event.getNewCenter().getZ(); -+ // Paper end - this.extent.onCenterChange(); - Iterator iterator = this.getListeners().iterator(); - - while (iterator.hasNext()) { - BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); - -- iworldborderlistener.onBorderCenterSet(this, x, z); -+ iworldborderlistener.onBorderCenterSet(this, event.getNewCenter().getX(), event.getNewCenter().getZ()); // Paper - } - - } -@@ -128,25 +135,43 @@ public class WorldBorder { - } - - public void setSize(double size) { -- this.extent = new WorldBorder.StaticBorderExtent(size); -+ // Paper start -+ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE, getSize(), size, 0); -+ if (!event.callEvent()) return; -+ if (event.getType() == WorldBorderBoundsChangeEvent.Type.STARTED_MOVE && event.getDuration() > 0) { // If changed to a timed transition -+ lerpSizeBetween(event.getOldSize(), event.getNewSize(), event.getDuration()); -+ return; -+ } -+ this.extent = new WorldBorder.StaticBorderExtent(event.getNewSize()); -+ // Paper end - Iterator iterator = this.getListeners().iterator(); - - while (iterator.hasNext()) { - BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); - -- iworldborderlistener.onBorderSizeSet(this, size); -+ iworldborderlistener.onBorderSizeSet(this, event.getNewSize()); // Paper - } - - } - - public void lerpSizeBetween(double fromSize, double toSize, long time) { -- this.extent = (WorldBorder.BorderExtent) (fromSize == toSize ? new WorldBorder.StaticBorderExtent(toSize) : new WorldBorder.MovingBorderExtent(fromSize, toSize, time)); -+ // Paper start -+ WorldBorderBoundsChangeEvent.Type type; -+ if (fromSize == toSize) { // new size = old size -+ type = WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE; // Use INSTANT_MOVE because below it creates a Static border if they are equal. -+ } else { -+ type = WorldBorderBoundsChangeEvent.Type.STARTED_MOVE; -+ } -+ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), type, fromSize, toSize, time); -+ if (!event.callEvent()) return; -+ this.extent = (WorldBorder.BorderExtent) (fromSize == event.getNewSize() ? new WorldBorder.StaticBorderExtent(event.getNewSize()) : new WorldBorder.MovingBorderExtent(fromSize, event.getNewSize(), event.getDuration())); -+ // Paper end - Iterator iterator = this.getListeners().iterator(); - - while (iterator.hasNext()) { - BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); - -- iworldborderlistener.onBorderSizeLerping(this, fromSize, toSize, time); -+ iworldborderlistener.onBorderSizeLerping(this, fromSize, event.getNewSize(), event.getDuration()); // Paper - } - - } -@@ -434,11 +459,11 @@ public class WorldBorder { - - class MovingBorderExtent implements WorldBorder.BorderExtent { - -- private final double from; -- private final double to; -+ private final double from; public final double getOldSize() { return this.from; } // Paper - OBFHELPER -+ private final double to; public final double getNewSize() { return this.to; } // Paper - OBFHELPER - private final long lerpEnd; - private final long lerpBegin; -- private final double lerpDuration; -+ private final double lerpDuration; public final double getDuration() { return this.lerpDuration; } // Paper - OBFHELPER - - private MovingBorderExtent(double d0, double d1, long i) { - this.from = d0; -@@ -493,6 +518,7 @@ public class WorldBorder { - - @Override - public WorldBorder.BorderExtent update() { -+ if (this.getLerpTimeRemaining() <= 0L) new WorldBorderBoundsChangeFinishEvent(world.getWorld(), world.getWorld().getWorldBorder(), getOldSize(), getNewSize(), getDuration()).callEvent(); // Paper - return (WorldBorder.BorderExtent) (this.getLerpRemainingTime() <= 0L ? WorldBorder.this.new StaticBorderExtent(this.to) : this); - } - -@@ -514,6 +540,7 @@ public class WorldBorder { - - double getSize(); - -+ default long getLerpTimeRemaining() { return getLerpRemainingTime(); } // Paper - OBFHELPER - long getLerpRemainingTime(); - - double getLerpTarget(); diff --git a/Remapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch b/Remapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch deleted file mode 100644 index 64f85dbc14..0000000000 --- a/Remapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 5 Jul 2020 00:33:54 -0700 -Subject: [PATCH] added PlayerNameEntityEvent - - -diff --git a/src/main/java/net/minecraft/world/item/NameTagItem.java b/src/main/java/net/minecraft/world/item/NameTagItem.java -index 5e38077c3de0a40f3cfd856bf2e48f7061e39a9d..5c575798c20f15d28350f767ecf15bfc042ebc8c 100644 ---- a/src/main/java/net/minecraft/world/item/NameTagItem.java -+++ b/src/main/java/net/minecraft/world/item/NameTagItem.java -@@ -1,5 +1,10 @@ - package net.minecraft.world.item; - -+// Paper start -+import io.papermc.paper.adventure.PaperAdventure; -+import io.papermc.paper.event.player.PlayerNameEntityEvent; -+// Paper end -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.InteractionHand; - import net.minecraft.world.InteractionResult; - import net.minecraft.world.entity.LivingEntity; -@@ -16,11 +21,15 @@ public class NameTagItem extends Item { - public InteractionResult interactLivingEntity(ItemStack stack, Player user, LivingEntity entity, InteractionHand hand) { - if (stack.hasCustomHoverName() && !(entity instanceof Player)) { - if (!user.level.isClientSide && entity.isAlive()) { -- entity.setCustomName(stack.getHoverName()); -- if (entity instanceof Mob) { -- ((Mob) entity).setPersistenceRequired(); -+ // Paper start -+ PlayerNameEntityEvent event = new PlayerNameEntityEvent(((ServerPlayer) user).getBukkitEntity(), entity.getBukkitLivingEntity(), PaperAdventure.asAdventure(stack.getHoverName()), true); -+ if (!event.callEvent()) return InteractionResult.PASS; -+ LivingEntity newEntityLiving = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle(); -+ newEntityLiving.setCustomName(event.getName() != null ? PaperAdventure.asVanilla(event.getName()) : null); -+ if (event.isPersistent() && newEntityLiving instanceof Mob) { -+ ((Mob) newEntityLiving).setPersistenceRequired(); - } -- -+ // Paper end - stack.shrink(1); - } - diff --git a/Remapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch b/Remapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch deleted file mode 100644 index 9f050a4e9b..0000000000 --- a/Remapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Tue, 16 Feb 2021 21:37:51 -0600 -Subject: [PATCH] Prevent grindstones from overstacking items - - -diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -index 329a6d70d53c13cd554c64996f2ddc489bdc1e94..445d408963538fbc01d61902805b2e35c861e4ce 100644 ---- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -@@ -195,13 +195,13 @@ public class GrindstoneMenu extends AbstractContainerMenu { - i = Math.max(item.getMaxDamage() - l, 0); - itemstack2 = this.mergeEnchants(itemstack, itemstack1); - if (!itemstack2.isDamageableItem()) { -- if (!ItemStack.matches(itemstack, itemstack1)) { -+ if (!ItemStack.matches(itemstack, itemstack1) || itemstack2.getMaxStackSize() == 1) { // Paper - add max stack size check - this.resultSlots.setItem(0, ItemStack.EMPTY); - this.broadcastChanges(); - return; - } - -- b0 = 2; -+ b0 = 2; // Paper - the problem line for above change, causing over-stacking - } - } else { - boolean flag3 = !itemstack.isEmpty(); diff --git a/Remapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch b/Remapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch deleted file mode 100644 index e43e7804ac..0000000000 --- a/Remapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> -Date: Wed, 6 Jan 2021 12:04:03 -0800 -Subject: [PATCH] Add recipe to cook events - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index f47b46cebd43faa509b8139d2a51cc8f87615893..2dcabfc765cbf6341546a7e2c48156fd921fcc82 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -393,7 +393,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); - -- FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()), source, result); -+ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()), source, result, (org.bukkit.inventory.CookingRecipe) recipe.toBukkitRecipe()); // Paper - this.level.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent); - - if (furnaceSmeltEvent.isCancelled()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -index 6c38361d744eae763b6c131ad314485f5a88fcfc..39b4782df965c785be7946d6964e0b7a4381ff74 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -@@ -73,7 +73,10 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable, Ticka - - if (this.cookingProgress[i] >= this.cookingTime[i]) { - SimpleContainer inventorysubcontainer = new SimpleContainer(new ItemStack[]{itemstack}); -- ItemStack itemstack1 = (ItemStack) this.level.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, inventorysubcontainer, this.level).map((recipecampfire) -> { -+ // Paper start -+ Optional recipe = this.level.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, inventorysubcontainer, this.level); -+ ItemStack itemstack1 = (ItemStack) recipe.map((recipecampfire) -> { -+ // Paper end - return recipecampfire.assemble(inventorysubcontainer); - }).orElse(itemstack); - BlockPos blockposition = this.getBlockPos(); -@@ -82,7 +85,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable, Ticka - CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); - -- BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.level, this.worldPosition), source, result); -+ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.level, this.worldPosition), source, result, (org.bukkit.inventory.CookingRecipe) recipe.map(CampfireCookingRecipe::toBukkitRecipe).orElse(null)); // Paper - this.level.getCraftServer().getPluginManager().callEvent(blockCookEvent); - - if (blockCookEvent.isCancelled()) { diff --git a/Remapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch b/Remapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch deleted file mode 100644 index a9fe23e278..0000000000 --- a/Remapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 6 Jul 2020 12:44:31 -0700 -Subject: [PATCH] Add Block#isValidTool - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 376b0497c28a35d7ea615397c87b2558b95c596a..def19e23996b85e1e540cd5edc6821ae0ae37f91 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -803,5 +803,9 @@ public class CraftBlock implements Block { - } - return speed; - } -+ -+ public boolean isValidTool(ItemStack itemStack) { -+ return getDrops(itemStack).size() != 0; -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch b/Remapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch deleted file mode 100644 index fa0bc9f104..0000000000 --- a/Remapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Anton Lindroth -Date: Wed, 15 Apr 2020 01:54:02 +0200 -Subject: [PATCH] Allow using signs inside spawn protection - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index eb367b8feda8219a97a547c3ef6ab82d278d2f25..108a005c296c4ed370de4af636163088971bed13 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -811,4 +811,9 @@ public class PaperWorldConfig { - fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); - log("Withers properly target players: " + fixWitherTargetingBug); - } -+ -+ public boolean allowUsingSignsInsideSpawnProtection = false; -+ private void allowUsingSignsInsideSpawnProtection() { -+ allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index cb6568b622abeb939a1195f4656accc8a1c3f1fc..1add53082ab9382cb2e90dc8305b8c71ef1c6a46 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -152,6 +152,7 @@ import net.minecraft.world.level.Level; - import net.minecraft.world.level.LevelReader; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.CommandBlock; -+import net.minecraft.world.level.block.SignBlock; - import net.minecraft.world.level.block.entity.BlockEntity; - import net.minecraft.world.level.block.entity.CommandBlockEntity; - import net.minecraft.world.level.block.entity.JigsawBlockEntity; -@@ -1690,7 +1691,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - this.player.resetLastActionTime(); - if (blockposition.getY() < this.server.getMaxBuildHeight()) { -- if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition)) { -+ if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && (worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition) || (worldserver.paperConfig.allowUsingSignsInsideSpawnProtection && worldserver.getBlockState(blockposition).getBlock() instanceof SignBlock))) { // Paper - // CraftBukkit start - Check if we can actually do something over this large a distance - // Paper - move check up - this.player.stopUsingItem(); // SPIGOT-4706 diff --git a/Remapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch b/Remapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch deleted file mode 100644 index 94fd5a3703..0000000000 --- a/Remapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 6 Jan 2021 00:34:04 -0800 -Subject: [PATCH] Implement Keyed on World - - -diff --git a/src/main/java/net/minecraft/core/Registry.java b/src/main/java/net/minecraft/core/Registry.java -index 5a98bc1522c2035487ce0a048c236903dbfa816e..4924d8cd3004a6e1ce76cd5cf7520556c23fe20a 100644 ---- a/src/main/java/net/minecraft/core/Registry.java -+++ b/src/main/java/net/minecraft/core/Registry.java -@@ -130,7 +130,7 @@ public abstract class Registry implements Codec, Keyable, IdMap { - public static final ResourceKey> LOOT_FUNCTION_REGISTRY = createRegistryKey("loot_function_type"); - public static final ResourceKey> LOOT_ITEM_REGISTRY = createRegistryKey("loot_condition_type"); - public static final ResourceKey> DIMENSION_TYPE_REGISTRY = createRegistryKey("dimension_type"); -- public static final ResourceKey> DIMENSION_REGISTRY = createRegistryKey("dimension"); -+ public static final ResourceKey> DIMENSION_REGISTRY = createRegistryKey("dimension"); public static final ResourceKey> getWorldRegistry() { return DIMENSION_REGISTRY; } // Paper - OBFHELPER - public static final ResourceKey> LEVEL_STEM_REGISTRY = createRegistryKey("dimension"); - public static final Registry SOUND_EVENT = registerSimple(Registry.SOUND_EVENT_REGISTRY, () -> { - return SoundEvents.ITEM_PICKUP; -@@ -339,9 +339,9 @@ public abstract class Registry implements Codec, Keyable, IdMap { - ResourceLocation minecraftkey = resourcekey.location(); - - Registry.LOADERS.put(minecraftkey, defaultEntry); -- WritableRegistry iregistrywritable = Registry.WRITABLE_REGISTRY; -+ WritableRegistry iregistrywritable = Registry.WRITABLE_REGISTRY; // Paper - decompile fix - -- return (WritableRegistry) iregistrywritable.register(resourcekey, (Object) registry, lifecycle); -+ return (R) iregistrywritable.register(resourcekey, (Object) registry, lifecycle); // Paper - decompile fix - } - - protected Registry(ResourceKey> key, Lifecycle lifecycle) { -@@ -428,11 +428,11 @@ public abstract class Registry implements Codec, Keyable, IdMap { - } - - public static T register(Registry registry, ResourceLocation id, T entry) { -- return ((WritableRegistry) registry).register(ResourceKey.create(registry.key, id), entry, Lifecycle.stable()); -+ return ((WritableRegistry) registry).register(ResourceKey.create(registry.key, id), entry, Lifecycle.stable()); // Paper - decompile fix - } - - public static T registerMapping(Registry registry, int rawId, String id, T entry) { -- return ((WritableRegistry) registry).registerMapping(rawId, ResourceKey.create(registry.key, new ResourceLocation(id)), entry, Lifecycle.stable()); -+ return ((WritableRegistry) registry).registerMapping(rawId, ResourceKey.create(registry.key, new ResourceLocation(id)), entry, Lifecycle.stable()); // Paper - decompile fix - } - - static { -diff --git a/src/main/java/net/minecraft/resources/ResourceKey.java b/src/main/java/net/minecraft/resources/ResourceKey.java -index 2f39438ee9b23706efb2fd877fe223777b6968c7..3085ec1f20f4c945242697b809188a8c828cfb75 100644 ---- a/src/main/java/net/minecraft/resources/ResourceKey.java -+++ b/src/main/java/net/minecraft/resources/ResourceKey.java -@@ -12,6 +12,7 @@ public class ResourceKey { - private final ResourceLocation registryName; - private final ResourceLocation location; - -+ public static ResourceKey newResourceKey(ResourceKey> registryKey, ResourceLocation minecraftKey) { return create(registryKey, minecraftKey); } // Paper - OBFHELPER - public static ResourceKey create(ResourceKey> registry, ResourceLocation value) { - return create(registry.location, value); - } -@@ -41,6 +42,7 @@ public class ResourceKey { - return this.registryName.equals(registry.location()); - } - -+ public ResourceLocation getLocation() { return location(); } // Paper - OBFHELPER - public ResourceLocation location() { - return this.location; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 794b894ed24636aec60de9a28ba7613d7a917324..6905256147d9bd79e5f52bf86bdb21c89b8411a7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1156,7 +1156,7 @@ public final class CraftServer implements Server { - } else if (name.equals(levelName + "_the_end")) { - worldKey = net.minecraft.world.level.Level.END; - } else { -- worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(name.toLowerCase(java.util.Locale.ENGLISH))); -+ worldKey = ResourceKey.newResourceKey(Registry.getWorldRegistry(), new net.minecraft.resources.ResourceLocation(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper - } - - ServerLevel internal = (ServerLevel) new ServerLevel(console, console.executor, worldSession, worlddata, worldKey, dimensionmanager, getServer().progressListenerFactory.create(11), -@@ -1246,6 +1246,15 @@ public final class CraftServer implements Server { - return null; - } - -+ // Paper start -+ @Override -+ public World getWorld(NamespacedKey worldKey) { -+ ServerLevel worldServer = console.getLevel(ResourceKey.newResourceKey(Registry.getWorldRegistry(), CraftNamespacedKey.toMinecraft(worldKey))); -+ if (worldServer == null) return null; -+ return worldServer.getWorld(); -+ } -+ // Paper end -+ - public void addWorld(World world) { - // Check if a World already exists with the UID. - if (getWorld(world.getUID()) != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index f497b9e11a075a84ff0a2117eb79d0532e4a326f..b0212b2043ee5fd77c8876ef0b51ef91488712f0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2566,6 +2566,11 @@ public class CraftWorld implements World { - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); - }, net.minecraft.server.MinecraftServer.getServer()); - } -+ -+ @Override -+ public org.bukkit.NamespacedKey getKey() { -+ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(world.dimension().getLocation()); -+ } - // Paper end - - // Spigot start diff --git a/Remapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch b/Remapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch deleted file mode 100644 index b395761137..0000000000 --- a/Remapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Irmo van den Berge -Date: Wed, 10 Mar 2021 21:26:31 +0100 -Subject: [PATCH] Add fast alternative constructor for Vector3f - -Signed-off-by: Irmo van den Berge - -diff --git a/src/main/java/net/minecraft/core/Rotations.java b/src/main/java/net/minecraft/core/Rotations.java -index e3c2affb5dfaf2d78139e98c9e8a40b37c92bf2f..4782cbd9d86d8246954db76993741a8a749a7fe0 100644 ---- a/src/main/java/net/minecraft/core/Rotations.java -+++ b/src/main/java/net/minecraft/core/Rotations.java -@@ -19,6 +19,18 @@ public class Rotations { - this(serialized.getFloat(0), serialized.getFloat(1), serialized.getFloat(2)); - } - -+ // Paper start - faster alternative constructor -+ private Rotations(float x, float y, float z, Void dummy_var) { -+ this.x = x; -+ this.y = y; -+ this.z = z; -+ } -+ -+ public static Rotations createWithoutValidityChecks(float x, float y, float z) { -+ return new Rotations(x, y, z, null); -+ } -+ // Paper end -+ - public ListTag save() { - ListTag nbttaglist = new ListTag(); - diff --git a/Remapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch b/Remapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch deleted file mode 100644 index 51a841f551..0000000000 --- a/Remapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 12 Mar 2021 17:09:42 -0800 -Subject: [PATCH] Item Rarity API - - -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 58400e84830c93675b0a1fe632be5e217c19a932..cb079bfd5339b96ad372b0a3b483d02cd0636bfd 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -45,7 +45,7 @@ public class Item implements ItemLike { - protected static final UUID BASE_ATTACK_SPEED_UUID = UUID.fromString("FA233E1C-4180-4865-B01B-BCCE9785ACA3"); - protected static final Random random = new Random(); - protected final CreativeModeTab category; -- private final Rarity rarity; -+ private final Rarity rarity; public final Rarity getItemRarity() { return rarity; } // Paper - OBFHELPER - private final int maxStackSize; - private final int maxDamage; - private final boolean isFireResistant; -@@ -209,6 +209,7 @@ public class Item implements ItemLike { - return stack.isEnchanted(); - } - -+ public Rarity getItemStackRarity(ItemStack itemStack) { return getRarity(itemStack); } // Paper - OBFHELPER - public Rarity getRarity(ItemStack stack) { - if (!stack.isEnchanted()) { - return this.rarity; -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 25a29d997f163ce2b11330d66a691601f514a9cb..472b0615dcdc3c0c52bd377fd69752716f354262 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -470,6 +470,20 @@ public final class CraftMagicNumbers implements UnsafeValues { - public int nextEntityId() { - return net.minecraft.world.entity.Entity.nextEntityId(); - } -+ -+ @Override -+ public io.papermc.paper.inventory.ItemRarity getItemRarity(org.bukkit.Material material) { -+ Item item = getItem(material); -+ if (item == null) { -+ throw new IllegalArgumentException(material + " is not an item, and rarity does not apply to blocks"); -+ } -+ return io.papermc.paper.inventory.ItemRarity.values()[item.getItemRarity().ordinal()]; -+ } -+ -+ @Override -+ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { -+ return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; -+ } - // Paper end - - /** diff --git a/Remapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/Remapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch deleted file mode 100644 index c076df0076..0000000000 --- a/Remapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Fri, 19 Mar 2021 16:07:21 -0700 -Subject: [PATCH] Only set despawnTimer for Wandering Traders spawned by - MobSpawnerTrader - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index d38828485d6deb08036e11d8bf16b3d63a60fbae..f6d2aca2fe3ee9b69a0b200c8b2ea35f222fb521 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -319,6 +319,12 @@ public class EntityType { - - @Nullable - public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ // Paper start - add consumer to modify entity before spawn -+ return this.spawnCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1, spawnReason, null); -+ } -+ @Nullable -+ public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason, @Nullable java.util.function.Consumer op) { -+ // Paper end - // Paper start - Call PreCreatureSpawnEvent - org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath()); - if (type != null) { -@@ -334,6 +340,7 @@ public class EntityType { - } - // Paper end - T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); -+ if (t0 != null && op != null) op.accept(t0); // Paper - - if (t0 != null) { - worldserver.addAllEntities(t0, spawnReason); -diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -index 69d92590d265abe8a04d8bf48bbe9a6ae606ae50..04c4cca4be8886feb59f180915977b77f9c7dde8 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -@@ -61,7 +61,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill - public WanderingTrader(EntityType type, Level world) { - super(type, world); - this.forcedLoading = true; -- this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader -+ //this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set. - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -index 9074d57e1576db2da3e4c76add4f7e07e5567879..f861d83affbb0b5eaf7440a909ca3b5f7a604da7 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -@@ -114,7 +114,7 @@ public class WanderingTraderSpawner implements CustomSpawner { - return false; - } - -- WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawnCreature(worldserver, (CompoundTag) null, (Component) null, (Player) null, blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit -+ WanderingTrader entityvillagertrader = EntityType.WANDERING_TRADER.spawnCreature(worldserver, null, null, null, blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, trader -> trader.setDespawnDelay(48000)); // CraftBukkit // Paper - set despawnTimer before spawn events called - - if (entityvillagertrader != null) { - for (int i = 0; i < 2; ++i) { diff --git a/Remapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch b/Remapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch deleted file mode 100644 index 862aed64d3..0000000000 --- a/Remapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 23 Mar 2021 06:43:30 +0000 -Subject: [PATCH] copy TESign#isEditable from snapshots - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -index 65e8a349c80a700f63dd27b11bb2099f65cbc069..eb0739c0927e821a5080d14e762225fd4936b82d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -@@ -109,6 +109,7 @@ public class CraftSign extends CraftBlockEntityState implements - } - // Paper end - } -+ sign.isEditable = getSnapshot().isEditable; // Paper - copy manually - } - - // Paper start diff --git a/Remapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch b/Remapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch deleted file mode 100644 index 4e8128fd64..0000000000 --- a/Remapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dmitry Sidorov -Date: Thu, 4 Feb 2021 20:32:01 +0300 -Subject: [PATCH] Drop carried item when player has disconnected - -Fixes disappearance of held items, when a player gets disconnected and PlayerDropItemEvent is cancelled. -Closes #5036 - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index dd121ec8f779b3786eeb7fe85519cf9e472f5adf..23cfaf5c432221f2d1afe37ba657f723d6d21a73 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -79,6 +79,7 @@ import net.minecraft.world.effect.MobEffectInstance; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; - import net.minecraft.world.entity.npc.AbstractVillager; -+import net.minecraft.world.item.ItemStack; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.GameType; -@@ -605,6 +606,14 @@ public abstract class PlayerList { - } - // Paper end - -+ // Paper - Drop carried item when player has disconnected -+ if (!entityplayer.inventory.getCarried().isEmpty()) { -+ ItemStack carried = entityplayer.inventory.getCarried(); -+ entityplayer.inventory.setCarried(ItemStack.NULL_ITEM); -+ entityplayer.drop(carried, false); -+ } -+ // Paper end -+ - this.save(entityplayer); - if (entityplayer.isPassenger()) { - Entity entity = entityplayer.getRootVehicle(); diff --git a/Remapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch b/Remapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch deleted file mode 100644 index 4b433dc16c..0000000000 --- a/Remapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sat, 27 Mar 2021 09:24:23 +0100 -Subject: [PATCH] forced whitelist: use configurable kick message - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 9b654fed2a00740cef84cf72258abfc7aeafc0c2..fd76d776c7003585c9efef44c6d7da0f6c3f574e 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -73,7 +73,6 @@ import net.minecraft.nbt.NbtOps; - import net.minecraft.nbt.Tag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TextComponent; --import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; - import net.minecraft.network.protocol.game.ClientboundSetTimePacket; -@@ -2040,7 +2039,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Mon, 29 Mar 2021 09:07:25 +0200 -Subject: [PATCH] Make sure to remove correct TE during TE tick - -This looks like it can cause premature TE removal. - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index b89cefc8890774dbc64fd6bddeb038d2ee36d485..4523bc1f49e7be248a47eeb599fa7b6550dbb08d 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -895,7 +895,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - //this.tileEntityList.remove(tileentity); // Paper - remove unused list - // Paper - prevent double chunk lookups - LevelChunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getBlockPos())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again -- chunk.removeBlockEntity(tileentity.getBlockPos()); -+ chunk.removeTileEntity(tileentity.getBlockPos(), tileentity); // Paper - remove correct TE - } - // Paper end - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 9b76dc15417eef420804e5184a6d684e1137a746..a15c08be3e1bd0e7934175db6ae0684bbb05e249 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -818,10 +818,18 @@ public class LevelChunk implements ChunkAccess { - - @Override - public void removeBlockEntity(BlockPos pos) { -+ // Paper start - remove correct TE -+ removeTileEntity(pos, null); -+ } -+ public void removeTileEntity(BlockPos blockposition, BlockEntity match) { -+ // Paper end - if (this.loaded || this.world.isClientSide()) { -- BlockEntity tileentity = (BlockEntity) this.blockEntities.remove(pos); -+ // Paper start -+ BlockEntity tileentity = (BlockEntity) this.blockEntities.get(blockposition); - -- if (tileentity != null) { -+ if (tileentity != null && (match == null || match == tileentity)) { -+ this.blockEntities.remove(blockposition); -+ // Paper end - tileentity.setRemoved(); - } - } diff --git a/Remapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/Remapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch deleted file mode 100644 index 930a7a71e6..0000000000 --- a/Remapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Mon, 5 Apr 2021 18:35:15 -0700 -Subject: [PATCH] Don't ignore result of PlayerEditBookEvent - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 1add53082ab9382cb2e90dc8305b8c71ef1c6a46..65afc23f4791aca19bff78ed86b3b0d31fa81977 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1144,7 +1144,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - list.stream().map(StringTag::valueOf).forEach(nbttaglist::add); - ItemStack old = itemstack.copy(); // CraftBukkit - itemstack.addTagElement("pages", (Tag) nbttaglist); -- CraftEventFactory.handleEditBookEvent(player, i, old, itemstack); // CraftBukkit -+ this.player.inventory.setItem(i, CraftEventFactory.handleEditBookEvent(player, i, old, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) - } - } - diff --git a/Remapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch b/Remapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch deleted file mode 100644 index 00cd7e5d6c..0000000000 --- a/Remapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sat, 27 Mar 2021 11:13:30 +0100 -Subject: [PATCH] fix cancelling block falling causing client desync - - -diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -index 2ba81e7179c7f9e2e1add1ad6bd6b96ee12c5da1..718e20f83a9b510c095d7e12241616cdce33d2d6 100644 ---- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -13,6 +13,7 @@ import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; - import net.minecraft.network.syncher.EntityDataAccessor; - import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.tags.BlockTags; - import net.minecraft.tags.FluidTags; - import net.minecraft.tags.Tag; -@@ -41,6 +42,7 @@ import net.minecraft.world.level.material.Fluids; - import net.minecraft.world.phys.BlockHitResult; - import net.minecraft.world.phys.HitResult; - import net.minecraft.world.phys.Vec3; -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit - - public class FallingBlockEntity extends Entity { -@@ -114,8 +116,18 @@ public class FallingBlockEntity extends Entity { - - if (this.time++ == 0) { - blockposition = this.blockPosition(); -- if (this.level.getBlockState(blockposition).is(block) && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { -- this.level.removeBlock(blockposition, false); -+ // Paper start - fix cancelling block falling causing client desync -+ if (this.level.getBlockState(blockposition).isSameInstance(block)) { -+ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { -+ if (this.level.getBlockState(blockposition).isSameInstance(block)) { //if listener didn't update the block -+ ((ServerLevel) level).getChunkSource().blockChanged(blockposition); -+ } -+ this.remove(); -+ return; -+ } else { -+ this.level.setAir(blockposition, false); -+ } -+ // Paper end - fix cancelling block falling causing client desync - } else if (!this.level.isClientSide) { - this.remove(); - return; -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index 17baae6b11f191f4738a107c7e62ea5bdac17a3c..32cda8c2e14cf8b218cb006a9b25330f0dab849a 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -682,6 +682,7 @@ public abstract class BlockBehaviour { - return this.getBlock().is(tag) && predicate.test(this); - } - -+ public final boolean isSameInstance(Block block) { return is(block); } // Paper - OBFHELPER - public boolean is(Block block) { - return this.getBlock().is(block); - } diff --git a/Remapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch b/Remapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch deleted file mode 100644 index 0e4392f5f9..0000000000 --- a/Remapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Fri, 26 Mar 2021 11:23:17 +0100 -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 472b0615dcdc3c0c52bd377fd69752716f354262..402e5a98290a1701dd67d27c484c97e0a6067c4f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -484,6 +484,11 @@ public final class CraftMagicNumbers implements UnsafeValues { - public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { - return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; - } -+ -+ @Override -+ public int getProtocolVersion() { -+ return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion(); -+ } - // Paper end - - /** diff --git a/Remapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/Remapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch deleted file mode 100644 index 036bfe3e5a..0000000000 --- a/Remapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Thu, 1 Apr 2021 00:34:02 -0700 -Subject: [PATCH] Allow for Component suggestion tooltips in - AsyncTabCompleteEvent - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 65afc23f4791aca19bff78ed86b3b0d31fa81977..67defaf71752ed29fde483e8232aa358ffa53675 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -769,12 +769,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - // Paper start - async tab completion - com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -- java.util.List completions = new java.util.ArrayList<>(); - String buffer = packet.getCommand(); -- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), - buffer, true, null); - event.callEvent(); -- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ java.util.List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); - // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server - if (!event.isHandled()) { - if (!event.isCancelled()) { -@@ -793,10 +792,16 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - }); - } - } else if (!completions.isEmpty()) { -- com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); -+ com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); - -- builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); -- completions.forEach(builder::suggest); -+ final com.mojang.brigadier.suggestion.SuggestionsBuilder builder = builder0.createOffset(builder0.getInput().lastIndexOf(' ') + 1); -+ completions.forEach(completion -> { -+ if (completion.tooltip() == null) { -+ builder.suggest(completion.suggestion()); -+ } else { -+ builder.suggest(completion.suggestion(), PaperAdventure.asVanilla(completion.tooltip())); -+ } -+ }); - com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); - com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); - suggestEvent.setCancelled(suggestions.isEmpty()); -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index c5e00bd9e2790992202aadf8eec2002fc88c78f1..dd8e87ad192c19743577bb95253a127072ea196c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -29,34 +29,56 @@ public class ConsoleCommandCompleter implements Completer { - final CraftServer server = this.server.server; - final String buffer = line.line(); - // Async Tab Complete -- com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -- java.util.List completions = new java.util.ArrayList<>(); -- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, -- buffer, true, null); -+ final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event = -+ new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), buffer, true, null); - event.callEvent(); -- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ final List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); - - if (event.isCancelled() || event.isHandled()) { - // Still fire sync event with the provided completions, if someone is listening - if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { -- List finalCompletions = completions; -+ List finalCompletions = new java.util.ArrayList<>(completions); - Waitable> syncCompletions = new Waitable>() { - @Override - protected List evaluate() { -- org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); -+ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, -+ finalCompletions.stream() -+ .map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::suggestion) -+ .collect(java.util.stream.Collectors.toList())); - return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); - } - }; - server.getServer().processQueue.add(syncCompletions); - try { -- completions = syncCompletions.get(); -+ final List legacyCompletions = syncCompletions.get(); -+ completions.removeIf(it -> !legacyCompletions.contains(it.suggestion())); // remove any suggestions that were removed -+ // add any new suggestions -+ for (final String completion : legacyCompletions) { -+ if (notNewSuggestion(completions, completion)) { -+ continue; -+ } -+ completions.add(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion(completion)); -+ } - } catch (InterruptedException | ExecutionException e1) { - e1.printStackTrace(); - } - } - - if (!completions.isEmpty()) { -- candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); -+ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { -+ if (completion.suggestion().isEmpty()) { -+ continue; -+ } -+ candidates.add(new Candidate( -+ completion.suggestion(), -+ completion.suggestion(), -+ null, -+ io.papermc.paper.adventure.PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null), -+ null, -+ null, -+ false -+ )); -+ } - } - return; - } -@@ -106,4 +128,15 @@ public class ConsoleCommandCompleter implements Completer { - Thread.currentThread().interrupt(); - } - } -+ -+ // Paper start -+ private boolean notNewSuggestion(final List completions, final String completion) { -+ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion it : completions) { -+ if (it.suggestion().equals(completion)) { -+ return true; -+ } -+ } -+ return false; -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch b/Remapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch deleted file mode 100644 index f6416177a9..0000000000 --- a/Remapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch +++ /dev/null @@ -1,316 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Tue, 30 Mar 2021 16:06:08 -0700 -Subject: [PATCH] Enhance console tab completions for brigadier commands - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index c56e7fb18f9a56c8025eb70a524f028b5942da37..efc1e42d606e1c9feb1a4871c0714933ae92a1b2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -479,4 +479,11 @@ public class PaperConfig { - private static void fixEntityPositionDesync() { - fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); - } -+ -+ public static boolean enableBrigadierConsoleHighlighting = true; -+ public static boolean enableBrigadierConsoleCompletions = true; -+ private static void consoleSettings() { -+ enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); -+ enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -index a4070b59e261f0f1ac4beec47b11492f4724bf27..372a459bd08f79f10ffd1391ec492e37f1e8bb50 100644 ---- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -+++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -@@ -1,5 +1,7 @@ - package com.destroystokyo.paper.console; - -+import com.destroystokyo.paper.PaperConfig; -+import io.papermc.paper.console.BrigadierCommandHighlighter; - import net.minecraft.server.dedicated.DedicatedServer; - import net.minecrell.terminalconsole.SimpleTerminalConsole; - import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; -@@ -16,11 +18,15 @@ public final class PaperConsole extends SimpleTerminalConsole { - - @Override - protected LineReader buildReader(LineReaderBuilder builder) { -- return super.buildReader(builder -+ builder - .appName("Paper") - .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) - .completer(new ConsoleCommandCompleter(this.server)) -- ); -+ .option(LineReader.Option.COMPLETE_IN_WORD, true); -+ if (PaperConfig.enableBrigadierConsoleHighlighting) { -+ builder.highlighter(new BrigadierCommandHighlighter(this.server, this.server.createCommandSourceStack())); -+ } -+ return super.buildReader(builder); - } - - @Override -diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2768028750fb9a95b3f3b409d047be14bb0083d5 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java -@@ -0,0 +1,95 @@ -+package io.papermc.paper.console; -+ -+import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion; -+import com.mojang.brigadier.CommandDispatcher; -+import com.mojang.brigadier.ParseResults; -+import com.mojang.brigadier.StringReader; -+import com.mojang.brigadier.suggestion.Suggestion; -+import io.papermc.paper.adventure.PaperAdventure; -+import net.minecraft.commands.CommandSourceStack; -+import net.minecraft.network.chat.ComponentUtils; -+import net.minecraft.server.dedicated.DedicatedServer; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.jline.reader.Candidate; -+import org.jline.reader.LineReader; -+import org.jline.reader.ParsedLine; -+ -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+ -+import static com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion; -+ -+public final class BrigadierCommandCompleter { -+ private final CommandSourceStack commandSourceStack; -+ private final DedicatedServer server; -+ -+ public BrigadierCommandCompleter(final @NonNull DedicatedServer server, final @NonNull CommandSourceStack commandSourceStack) { -+ this.server = server; -+ this.commandSourceStack = commandSourceStack; -+ } -+ -+ public void complete(final @NonNull LineReader reader, final @NonNull ParsedLine line, final @NonNull List candidates, final @NonNull List existing) { -+ if (!com.destroystokyo.paper.PaperConfig.enableBrigadierConsoleCompletions) { -+ this.addCandidates(candidates, Collections.emptyList(), existing); -+ return; -+ } -+ final CommandDispatcher dispatcher = this.server.getCommands().dispatcher(); -+ final ParseResults results = dispatcher.parse(prepareStringReader(line.line()), this.commandSourceStack); -+ this.addCandidates( -+ candidates, -+ dispatcher.getCompletionSuggestions(results, line.cursor()).join().getList(), -+ existing -+ ); -+ } -+ -+ private void addCandidates( -+ final @NonNull List candidates, -+ final @NonNull List brigSuggestions, -+ final @NonNull List existing -+ ) { -+ final List completions = new ArrayList<>(); -+ brigSuggestions.forEach(it -> completions.add(toCompletion(it))); -+ for (final Completion completion : existing) { -+ if (completion.suggestion().isEmpty() || brigSuggestions.stream().anyMatch(it -> it.getText().equals(completion.suggestion()))) { -+ continue; -+ } -+ completions.add(completion); -+ } -+ for (final Completion completion : completions) { -+ if (completion.suggestion().isEmpty()) { -+ continue; -+ } -+ candidates.add(toCandidate(completion)); -+ } -+ } -+ -+ private static @NonNull Candidate toCandidate(final @NonNull Completion completion) { -+ final String suggestionText = completion.suggestion(); -+ final String suggestionTooltip = PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null); -+ return new Candidate( -+ suggestionText, -+ suggestionText, -+ null, -+ suggestionTooltip, -+ null, -+ null, -+ false -+ ); -+ } -+ -+ private static @NonNull Completion toCompletion(final @NonNull Suggestion suggestion) { -+ if (suggestion.getTooltip() == null) { -+ return completion(suggestion.getText()); -+ } -+ return completion(suggestion.getText(), PaperAdventure.asAdventure(ComponentUtils.fromMessage(suggestion.getTooltip()))); -+ } -+ -+ static @NonNull StringReader prepareStringReader(final @NonNull String line) { -+ final StringReader stringReader = new StringReader(line); -+ if (stringReader.canRead() && stringReader.peek() == '/') { -+ stringReader.skip(); -+ } -+ return stringReader; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..812027fb84e1b7825f2dd0fb6fa33831367c2dc0 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java -@@ -0,0 +1,57 @@ -+package io.papermc.paper.console; -+ -+import com.mojang.brigadier.ParseResults; -+import com.mojang.brigadier.context.ParsedCommandNode; -+import com.mojang.brigadier.tree.LiteralCommandNode; -+import net.minecraft.commands.CommandSourceStack; -+import net.minecraft.server.dedicated.DedicatedServer; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.jline.reader.Highlighter; -+import org.jline.reader.LineReader; -+import org.jline.utils.AttributedString; -+import org.jline.utils.AttributedStringBuilder; -+import org.jline.utils.AttributedStyle; -+ -+public final class BrigadierCommandHighlighter implements Highlighter { -+ private static final int[] COLORS = {AttributedStyle.CYAN, AttributedStyle.YELLOW, AttributedStyle.GREEN, AttributedStyle.MAGENTA, /* Client uses GOLD here, not BLUE, however there is no GOLD AttributedStyle. */ AttributedStyle.BLUE}; -+ private final CommandSourceStack commandSourceStack; -+ private final DedicatedServer server; -+ -+ public BrigadierCommandHighlighter(final @NonNull DedicatedServer server, final @NonNull CommandSourceStack commandSourceStack) { -+ this.server = server; -+ this.commandSourceStack = commandSourceStack; -+ } -+ -+ @Override -+ public AttributedString highlight(final @NonNull LineReader reader, final @NonNull String buffer) { -+ final AttributedStringBuilder builder = new AttributedStringBuilder(); -+ final ParseResults results = this.server.getCommands().dispatcher().parse(BrigadierCommandCompleter.prepareStringReader(buffer), this.commandSourceStack); -+ int pos = 0; -+ if (buffer.startsWith("/")) { -+ builder.append("/", AttributedStyle.DEFAULT); -+ pos = 1; -+ } -+ int component = -1; -+ for (final ParsedCommandNode node : results.getContext().getLastChild().getNodes()) { -+ if (node.getRange().getStart() >= buffer.length()) { -+ break; -+ } -+ final int start = node.getRange().getStart(); -+ final int end = Math.min(node.getRange().getEnd(), buffer.length()); -+ builder.append(buffer.substring(pos, start), AttributedStyle.DEFAULT); -+ if (node.getNode() instanceof LiteralCommandNode) { -+ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT); -+ } else { -+ if (++component >= COLORS.length) { -+ component = 0; -+ } -+ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT.foreground(COLORS[component])); -+ } -+ pos = end; -+ } -+ if (pos < buffer.length()) { -+ builder.append((buffer.substring(pos)), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)); -+ } -+ return builder.toAttributedString(); -+ } -+} -diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java -index 5ed78383ce247ceb24cda0335dbeae293958055c..e2f18b5bf1e091fe5fd868520a6d1bcc2669c24c 100644 ---- a/src/main/java/net/minecraft/commands/Commands.java -+++ b/src/main/java/net/minecraft/commands/Commands.java -@@ -440,7 +440,7 @@ public class Commands { - }; - } - -- public com.mojang.brigadier.CommandDispatcher getDispatcher() { -+ public com.mojang.brigadier.CommandDispatcher getDispatcher() { return this.dispatcher(); } public com.mojang.brigadier.CommandDispatcher dispatcher() { // Paper - OBFHELPER - return this.dispatcher; - } - -diff --git a/src/main/java/net/minecraft/network/chat/ComponentUtils.java b/src/main/java/net/minecraft/network/chat/ComponentUtils.java -index b5a59aed5d5cfbe0f75a8209b058b368b1f2b595..ed90c4348ca030d678251b0f9891d00153992f89 100644 ---- a/src/main/java/net/minecraft/network/chat/ComponentUtils.java -+++ b/src/main/java/net/minecraft/network/chat/ComponentUtils.java -@@ -90,7 +90,7 @@ public class ComponentUtils { - TextComponent chatcomponenttext = new TextComponent(""); - boolean flag = true; - -- for (Iterator iterator = elements.iterator(); iterator.hasNext(); flag = false) { -+ for (Iterator iterator = elements.iterator(); iterator.hasNext(); flag = false) { // Paper - decompile fix - T t0 = iterator.next(); - - if (!flag) { -@@ -108,7 +108,7 @@ public class ComponentUtils { - return new TranslatableComponent("chat.square_brackets", new Object[]{text}); - } - -- public static Component fromMessage(Message message) { -+ public static Component fromMessage(Message message) { return fromMessage(message); } public static Component fromMessage(final @org.checkerframework.checker.nullness.qual.NonNull Message message) { // Paper - OBFHELPER - return (Component) (message instanceof Component ? (Component) message : new TextComponent(message.getString())); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index dd8e87ad192c19743577bb95253a127072ea196c..eaad328d0d15ef450bb5a305828ce413d1eab53b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -18,9 +18,11 @@ import org.bukkit.event.server.TabCompleteEvent; - - public class ConsoleCommandCompleter implements Completer { - private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer -+ private final io.papermc.paper.console.BrigadierCommandCompleter brigadierCompleter; // Paper - - public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer - this.server = server; -+ this.brigadierCompleter = new io.papermc.paper.console.BrigadierCommandCompleter(this.server, this.server.createCommandSourceStack()); // Paper - } - - // Paper start - Change method signature for JLine update -@@ -64,7 +66,7 @@ public class ConsoleCommandCompleter implements Completer { - } - } - -- if (!completions.isEmpty()) { -+ if (false && !completions.isEmpty()) { - for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { - if (completion.suggestion().isEmpty()) { - continue; -@@ -80,6 +82,7 @@ public class ConsoleCommandCompleter implements Completer { - )); - } - } -+ this.addCompletions(reader, line, candidates, completions); - return; - } - -@@ -99,10 +102,12 @@ public class ConsoleCommandCompleter implements Completer { - try { - List offers = waitable.get(); - if (offers == null) { -+ this.addCompletions(reader, line, candidates, Collections.emptyList()); // Paper - return; // Paper - Method returns void - } - - // Paper start - JLine update -+ /* - for (String completion : offers) { - if (completion.isEmpty()) { - continue; -@@ -110,6 +115,8 @@ public class ConsoleCommandCompleter implements Completer { - - candidates.add(new Candidate(completion)); - } -+ */ -+ this.addCompletions(reader, line, candidates, offers.stream().map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::completion).collect(java.util.stream.Collectors.toList())); - // Paper end - - // Paper start - JLine handles cursor now -@@ -138,5 +145,9 @@ public class ConsoleCommandCompleter implements Completer { - } - return false; - } -+ -+ private void addCompletions(final LineReader reader, final ParsedLine line, final List candidates, final List existing) { -+ this.brigadierCompleter.complete(reader, line, candidates, existing); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/Remapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch deleted file mode 100644 index a86a2c1b40..0000000000 --- a/Remapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Fri, 19 Mar 2021 00:33:15 -0500 -Subject: [PATCH] Fix PlayerItemConsumeEvent cancelling properly - -When the active item is not cleared, the item is still readied -for use and will repeatedly trigger the PlayerItemConsumeEvent -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 8bc74878919ab7cf6a50d425da61f1b8a8b0ee44..37787a725725d22b0870dcab0f3bec8b94cfd130 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3348,6 +3348,7 @@ public abstract class LivingEntity extends Entity { - level.getCraftServer().getPluginManager().callEvent(event); - - if (event.isCancelled()) { -+ this.stopUsingItem(); // Paper - event is using an item, clear active item to reset its use - // Update client - ((ServerPlayer) this).getBukkitEntity().updateInventory(); - ((ServerPlayer) this).getBukkitEntity().updateScaledHealth(); diff --git a/Remapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch b/Remapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch deleted file mode 100644 index 88f6d3d8dc..0000000000 --- a/Remapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 18 Apr 2021 21:27:01 +0100 -Subject: [PATCH] Add bypass host check - -Paper.bypassHostCheck - -Seriously, fix your firewalls. -.- - -diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -index c648b73a4c478f9d8020274205d6684f7c7c416f..4e055a41de3ee410682cc05a3b883ac8babeb290 100644 ---- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -@@ -30,6 +30,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - private static final Component IGNORE_STATUS_REASON = new TextComponent("Ignoring status request"); - private final MinecraftServer server; - private final Connection connection; final Connection getNetworkManager() { return this.connection; } // Paper - OBFHELPER -+ private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper - - public ServerHandshakePacketListenerImpl(MinecraftServer server, Connection connection) { - this.server = server; -@@ -118,7 +119,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - // Spigot Start - //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! - String[] split = packet.hostName.split("\00"); -- if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { -+ if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper - packet.hostName = split[0]; - connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort()); - connection.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); diff --git a/Remapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch b/Remapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch deleted file mode 100644 index 487cbc3ff9..0000000000 --- a/Remapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 20 Apr 2021 01:15:04 +0100 -Subject: [PATCH] don't throw when loading invalid TEs - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 05fa76c02ce61e26891ad995fe89e925ea086557..b7ebb213efd759253f0042f77e11f2a8102ea6ca 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.block.entity; - - import javax.annotation.Nullable; - import net.minecraft.CrashReportCategory; -+import net.minecraft.ResourceLocationException; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Registry; - import net.minecraft.nbt.CompoundTag; -@@ -133,7 +134,13 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - public static BlockEntity loadStatic(BlockState state, CompoundTag tag) { - String s = tag.getString("id"); - -- return (BlockEntity) Registry.BLOCK_ENTITY_TYPE.getOptional(new ResourceLocation(s)).map((tileentitytypes) -> { -+ // Paper -+ ResourceLocation minecraftKey = null; -+ try { -+ minecraftKey = new ResourceLocation(s); -+ } catch (ResourceLocationException ex) {} -+ // Paper end -+ return (BlockEntity) Registry.BLOCK_ENTITY_TYPE.getOptional(minecraftKey).map((tileentitytypes) -> { - try { - return tileentitytypes.create(); - } catch (Throwable throwable) { diff --git a/Remapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch b/Remapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch deleted file mode 100644 index f907ad7a6b..0000000000 --- a/Remapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Mon, 5 Apr 2021 16:58:20 -0400 -Subject: [PATCH] Set area affect cloud rotation - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index b0212b2043ee5fd77c8876ef0b51ef91488712f0..b44e83d93bba579e439b93e5093350675137b070 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1959,6 +1959,7 @@ public class CraftWorld implements World { - entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(world); - } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { - entity = new net.minecraft.world.entity.AreaEffectCloud(world, x, y, z); -+ entity.moveTo(x, y, z, yaw, pitch); // Paper - Set area effect cloud Rotation - } else if (EvokerFangs.class.isAssignableFrom(clazz)) { - entity = new net.minecraft.world.entity.projectile.EvokerFangs(world, x, y, z, (float) Math.toRadians(yaw), 0, null); - } diff --git a/Remapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch b/Remapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch deleted file mode 100644 index 75f3e9118b..0000000000 --- a/Remapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 8 Apr 2021 17:36:10 -0700 -Subject: [PATCH] add isDeeplySleeping 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 aceb57c93c91730345f49f78838780c41ce2dcef..0559f2cfab817e989c02ce2d13bcdabb8ad3b82b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -122,6 +122,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - } - } - -+ // Paper start -+ @Override -+ public boolean isDeeplySleeping() { -+ return getHandle().isSleepingLongEnough(); -+ } -+ // Paper end -+ - @Override - public int getSleepTicks() { - return getHandle().sleepCounter; diff --git a/Remapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch b/Remapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch deleted file mode 100644 index 0672393254..0000000000 --- a/Remapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alphaesia -Date: Fri, 23 Apr 2021 09:57:56 +1200 -Subject: [PATCH] Fix duplicating /give items on item drop cancel - -Fixes SPIGOT-2942 (Give command fires PlayerDropItemEvent, cancelling it causes item duplication). - -For every stack of items to give, /give puts the item stack straight -into the player's inventory. However, it also summons a "fake item" -at the player's location. When the PlayerDropItemEvent for this fake -item is cancelled, the server attempts to put the item back into the -player's inventory. The result is that the fake item, which is never -meant to be obtained, is combined with the real items injected directly -into the player's inventory. This means more items than the amount -specified in /give are given to the player - one for every stack of -items given. (e.g. /give @s dirt 1 gives you 2 dirt). - -While this isn't a big issue for general building usage, it can affect -e.g. adventure maps where the number of items the player receives is -important (and you want to restrict the player from throwing items). - -If there are any overflow items that didn't make it into the inventory -(insufficient space), those items are dropped as a real item instead -of a fake one. While cancelling this drop would also result in the -server attempting to put those items into the inventory, since it is -full this has no effect. - -Just ignoring cancellation of the PlayerDropItemEvent seems like the -cleanest and least intrusive way to fix it. - -diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java -index a6259e9160f291cf527a4ea5533a2e5530471874..3b8a7b9bdd2445afa93e4f2dc971a1d252c1463a 100644 ---- a/src/main/java/net/minecraft/server/commands/GiveCommand.java -+++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java -@@ -49,7 +49,7 @@ public class GiveCommand { - - if (flag && itemstack.isEmpty()) { - itemstack.setCount(1); -- entityitem = entityplayer.drop(itemstack, false); -+ entityitem = entityplayer.drop(itemstack, false, false, true); // Paper - Fix duplicating /give items on item drop cancel - if (entityitem != null) { - entityitem.makeFakeItem(); - } -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 4817b8ab259d348b48bc325d34ba9351ffe951df..cfb9bd6b9863a0f6f0f50181b7553adce90cfebe 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -639,7 +639,14 @@ public abstract class Player extends LivingEntity { - - @Nullable - public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership) { -- if (stack.isEmpty()) { -+ // Paper start - Fix duplicating /give items on item drop cancel -+ return this.drop(stack, throwRandomly, retainOwnership, false); -+ } -+ -+ @Nullable -+ public ItemEntity drop(ItemStack itemstack, boolean flag, boolean flag1, boolean alwaysSucceed) { -+ // Paper end -+ if (itemstack.isEmpty()) { - return null; - } else { - if (this.level.isClientSide) { -@@ -647,17 +654,17 @@ public abstract class Player extends LivingEntity { - } - - double d0 = this.getEyeY() - 0.30000001192092896D; -- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), d0, this.getZ(), stack); -+ ItemEntity entityitem = new ItemEntity(this.level, this.getX(), d0, this.getZ(), itemstack); - - entityitem.setPickUpDelay(40); -- if (retainOwnership) { -+ if (flag1) { - entityitem.setThrower(this.getUUID()); - } - - float f; - float f1; - -- if (throwRandomly) { -+ if (flag) { - f = this.random.nextFloat() * 0.5F; - f1 = this.random.nextFloat() * 6.2831855F; - entityitem.setDeltaMovement((double) (-Mth.sin(f1) * f), 0.20000000298023224D, (double) (Mth.cos(f1) * f)); -@@ -680,12 +687,12 @@ public abstract class Player extends LivingEntity { - PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); - this.level.getCraftServer().getPluginManager().callEvent(event); - -- if (event.isCancelled()) { -+ if (event.isCancelled() && !alwaysSucceed) { // Paper - Fix duplicating /give items on item drop cancel - org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); -- if (retainOwnership && (cur == null || cur.getAmount() == 0)) { -+ if (flag1 && (cur == null || cur.getAmount() == 0)) { - // The complete stack was dropped - player.getInventory().setItemInHand(drop.getItemStack()); -- } else if (retainOwnership && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { -+ } else if (flag1 && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { - // Only one item is dropped - cur.setAmount(cur.getAmount() + 1); - player.getInventory().setItemInHand(cur); -@@ -697,9 +704,9 @@ public abstract class Player extends LivingEntity { - } - // CraftBukkit end - // Paper start - remove player from map on drop -- if (stack.getItem() == Items.FILLED_MAP) { -- MapItemSavedData worldmap = MapItem.getOrCreateSavedData(stack, this.level); -- worldmap.updateSeenPlayers(this, stack); -+ if (itemstack.getItem() == Items.FILLED_MAP) { -+ MapItemSavedData worldmap = MapItem.getOrCreateSavedData(itemstack, this.level); -+ worldmap.updateSeenPlayers(this, itemstack); - } - // Paper end - diff --git a/Remapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch b/Remapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch deleted file mode 100644 index f9cc308842..0000000000 --- a/Remapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 16:45:28 -0700 -Subject: [PATCH] add consumeFuel to FurnaceBurnEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 2dcabfc765cbf6341546a7e2c48156fd921fcc82..6e4feb2280021c26dbbfb92feb08c95165e126fe 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -329,7 +329,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - if (this.isLit() && furnaceBurnEvent.isBurning()) { - // CraftBukkit end - flag1 = true; -- if (!itemstack.isEmpty()) { -+ if (!itemstack.isEmpty() && furnaceBurnEvent.willConsumeFuel()) { // Paper - Item item = itemstack.getItem(); - - itemstack.shrink(1); diff --git a/Remapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch b/Remapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch deleted file mode 100644 index c18ac532d5..0000000000 --- a/Remapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 00:28:11 -0700 -Subject: [PATCH] add get-set drop chance to EntityEquipment - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -index e8d6e1abf29a5c50e1cafa01c602f36596d42ecf..9841b4ed648b95272feee45e6f1e8fd9399c322e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -@@ -244,6 +244,17 @@ public class CraftEntityEquipment implements EntityEquipment { - public void setBootsDropChance(float chance) { - setDropChance(net.minecraft.world.entity.EquipmentSlot.FEET, chance); - } -+ // Paper start -+ @Override -+ public float getDropChance(EquipmentSlot slot) { -+ return getDropChance(CraftEquipmentSlot.getNMS(slot)); -+ } -+ -+ @Override -+ public void setDropChance(EquipmentSlot slot, float chance) { -+ setDropChance(CraftEquipmentSlot.getNMS(slot), chance); -+ } -+ // Paper end - - private void setDropChance(net.minecraft.world.entity.EquipmentSlot slot, float chance) { - if (slot == net.minecraft.world.entity.EquipmentSlot.MAINHAND || slot == net.minecraft.world.entity.EquipmentSlot.OFFHAND) { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -index 7a8181f559cc3c92c3b3aa2ff8eda515719eba08..c326a75728fffbab301654afd94b6839c009fe93 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -@@ -354,4 +354,15 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i - public void setBootsDropChance(float chance) { - throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); - } -+ // Paper start -+ @Override -+ public float getDropChance(EquipmentSlot slot) { -+ return 1; -+ } -+ -+ @Override -+ public void setDropChance(EquipmentSlot slot, float chance) { -+ throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch b/Remapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch deleted file mode 100644 index 5d4feaac2c..0000000000 --- a/Remapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Thu, 18 Mar 2021 21:38:01 +0100 -Subject: [PATCH] fix PigZombieAngerEvent cancellation - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -index f85dfd8b57cf81ad7c6b12753fdd42e93f772f9e..16f4dbfd21a287bad3e10c174fa77a1cac771afa 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -@@ -28,6 +28,7 @@ public abstract class Goal { - - public void start() { this.start(); } public void start() {} // Paper - OBFHELPER - -+ public final void onTaskResetObfHelper() { stop(); } // Paper - OBFHELPER - public void stop() { - onTaskReset(); // Paper - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java -index d1cbbfbf9d3c5e65785aad00c2292245a5de1422..d67a50740b1c6d4ecd49a5541d24d1e4bacb8887 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java -+++ b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java -@@ -49,6 +49,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { - private UUID persistentAngerTarget; - private static final IntRange ALERT_INTERVAL = TimeUtil.rangeOfSeconds(4, 6); - private int ticksUntilNextAlert; -+ private HurtByTargetGoal pathfinderGoalHurtByTarget; // Paper - - public ZombifiedPiglin(EntityType type, Level world) { - super(type, world); -@@ -69,7 +70,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { - protected void addBehaviourGoals() { - this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0D, false)); - this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); -- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers(new Class[0])); // CraftBukkit - decompile error -+ this.targetSelector.addGoal(1, pathfinderGoalHurtByTarget = new HurtByTargetGoal(this).setAlertOthers(new Class[0])); // CraftBukkit - decompile error // Paper - assign field - this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); - this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true)); - } -@@ -172,6 +173,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { - this.level.getCraftServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - this.setPersistentAngerTarget(null); -+ pathfinderGoalHurtByTarget.onTaskResetObfHelper(); // Paper - clear goalTargets to fix cancellation - return; - } - this.setRemainingPersistentAngerTime(event.getNewAnger()); diff --git a/Remapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch b/Remapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch deleted file mode 100644 index 38d7d768a3..0000000000 --- a/Remapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Sun, 4 Apr 2021 14:25:04 -0400 -Subject: [PATCH] Fix checkReach check for Shulker boxes - - -diff --git a/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java b/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java -index c40518b0e4ad2b043a9acc858413648d6419f3a3..4b7814a31deeef31e877cee96f0d51b348e7a281 100644 ---- a/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java -@@ -65,6 +65,7 @@ public class ShulkerBoxMenu extends AbstractContainerMenu { - - @Override - public boolean stillValid(Player player) { -+ if (!this.checkReachable) return true; // Paper - Add reachable override for ContainerShulkerBox - return this.container.stillValid(player); - } - diff --git a/Remapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch b/Remapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch deleted file mode 100644 index 094351a8ff..0000000000 --- a/Remapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Thu, 22 Apr 2021 19:02:07 -0700 -Subject: [PATCH] fix PlayerItemHeldEvent firing twice - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java -index 68026536cfc26f07ca99ee9e76fd74b4ed4a995c..848fb02988b0fb319655f790112274ac2a437d25 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java -@@ -24,6 +24,7 @@ public class ServerboundSetCarriedItemPacket implements Packet= 0 && packet.getSlot() < Inventory.getSelectionSize()) { -+ if (packet.getItemInHandIndex() == this.player.inventory.selected) { return; } // Paper - don't fire itemheldevent when there wasn't a slot change - PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.selected, packet.getSlot()); - this.craftServer.getPluginManager().callEvent(event); - if (event.isCancelled()) { diff --git a/Remapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch b/Remapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch deleted file mode 100644 index 14d231bf04..0000000000 --- a/Remapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 21 Apr 2021 15:58:19 -0700 -Subject: [PATCH] Added 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 cfb9bd6b9863a0f6f0f50181b7553adce90cfebe..c0d2ca1daca0c0c6f21334bc4d9d039440efc453 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -232,6 +232,11 @@ public abstract class Player extends LivingEntity { - - if (this.isSleeping()) { - ++this.sleepCounter; -+ // Paper start -+ if (this.sleepCounter == 100) { -+ if (!new io.papermc.paper.event.player.PlayerDeepSleepEvent((org.bukkit.entity.Player) getBukkitEntity()).callEvent()) { this.sleepCounter = Integer.MIN_VALUE; } -+ } -+ // Paper end - if (this.sleepCounter > 100) { - this.sleepCounter = 100; - } diff --git a/Remapped-Spigot-Server-Patches/0714-More-World-API.patch b/Remapped-Spigot-Server-Patches/0714-More-World-API.patch deleted file mode 100644 index 37cb7379d4..0000000000 --- a/Remapped-Spigot-Server-Patches/0714-More-World-API.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 7 Jul 2020 10:52:34 -0700 -Subject: [PATCH] More World API - - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index a7553a856b9c99bee8f75d514b97cfab952bfd33..511e6a941d441c55a4b38660f0f7f8c47fa689dd 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1863,6 +1863,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return !this.worldDataServer.worldGenSettings().generateFeatures() ? null : this.getChunkSource().getGenerator().findNearestMapFeature(this, feature, pos, radius, skipExistingChunks); // CraftBukkit - } - -+ public BlockPos getNearestBiome(Biome biomeBase, BlockPos blockPosition, int radius, int step) { return this.findNearestBiome(biomeBase, blockPosition, radius, step); } // Paper - OBFHELPER - @Nullable - public BlockPos findNearestBiome(Biome biome, BlockPos pos, int radius, int j) { - return this.getChunkSource().getGenerator().getBiomeSource().findBiomeHorizontal(pos.getX(), pos.getY(), pos.getZ(), radius, j, (biomebase1) -> { -@@ -1885,6 +1886,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return this.noSave; - } - -+ public RegistryAccess getWorldCustomRegistry() { return registryAccess(); } // Paper - OBFHELPER - @Override - public RegistryAccess registryAccess() { - return this.server.registryAccess(); -diff --git a/src/main/java/net/minecraft/world/level/dimension/DimensionType.java b/src/main/java/net/minecraft/world/level/dimension/DimensionType.java -index 7dead90a0d77e936816c2a54fe70c87d92dc8e5b..fb2bdfbeb44de6ce967af2deb4738972b44dcf44 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/DimensionType.java -+++ b/src/main/java/net/minecraft/world/level/dimension/DimensionType.java -@@ -142,10 +142,10 @@ public class DimensionType { - public static RegistryAccess.RegistryHolder registerBuiltin(RegistryAccess.RegistryHolder registryManager) { - WritableRegistry iregistrywritable = registryManager.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); - -- iregistrywritable.register(DimensionType.OVERWORLD_LOCATION, (Object) DimensionType.DEFAULT_OVERWORLD, Lifecycle.stable()); -- iregistrywritable.register(DimensionType.OVERWORLD_CAVES_LOCATION, (Object) DimensionType.DEFAULT_OVERWORLD_CAVES, Lifecycle.stable()); -- iregistrywritable.register(DimensionType.NETHER_LOCATION, (Object) DimensionType.DEFAULT_NETHER, Lifecycle.stable()); -- iregistrywritable.register(DimensionType.END_LOCATION, (Object) DimensionType.DEFAULT_END, Lifecycle.stable()); -+ iregistrywritable.register(DimensionType.OVERWORLD_LOCATION, DimensionType.DEFAULT_OVERWORLD, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.register(DimensionType.OVERWORLD_CAVES_LOCATION, DimensionType.DEFAULT_OVERWORLD_CAVES, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.register(DimensionType.NETHER_LOCATION, DimensionType.DEFAULT_NETHER, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.register(DimensionType.END_LOCATION, DimensionType.DEFAULT_END, Lifecycle.stable()); // Paper - decompile fix - return registryManager; - } - -@@ -164,10 +164,10 @@ public class DimensionType { - public static MappedRegistry defaultDimensions(Registry dimensionRegistry, Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed) { - MappedRegistry registrymaterials = new MappedRegistry<>(Registry.LEVEL_STEM_REGISTRY, Lifecycle.experimental()); - -- registrymaterials.register(LevelStem.NETHER, (Object) (new LevelStem(() -> { -+ registrymaterials.register(LevelStem.NETHER, (new LevelStem(() -> { // Paper - decompile fix - return (DimensionType) dimensionRegistry.getOrThrow(DimensionType.NETHER_LOCATION); - }, defaultNetherGenerator(biomeRegistry, chunkGeneratorSettingsRegistry, seed))), Lifecycle.stable()); -- registrymaterials.register(LevelStem.END, (Object) (new LevelStem(() -> { -+ registrymaterials.register(LevelStem.END, (new LevelStem(() -> { // Paper - decompile fix - return (DimensionType) dimensionRegistry.getOrThrow(DimensionType.END_LOCATION); - }, defaultEndGenerator(biomeRegistry, chunkGeneratorSettingsRegistry, seed))), Lifecycle.stable()); - return registrymaterials; -@@ -256,6 +256,7 @@ public class DimensionType { - return this.brightnessRamp[i]; - } - -+ public Tag getInfiniburnTag() { return infiniburn(); } // Paper - OBFHELPER - public Tag infiniburn() { - Tag tag = BlockTags.getAllTags().getTag(this.infiniburn); - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index b44e83d93bba579e439b93e5093350675137b070..a1fa2d5e00bd125abd38a00e0bc3936f2fb8186f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2515,6 +2515,75 @@ public class CraftWorld implements World { - return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); - } - -+ // Paper start -+ @Override -+ public Location locateNearestBiome(Location origin, Biome biome, int radius) { -+ return this.locateNearestBiome(origin, biome, radius, 8); -+ } -+ -+ @Override -+ public Location locateNearestBiome(Location origin, Biome biome, int radius, int step) { -+ BlockPos originPos = new BlockPos(origin.getX(), origin.getY(), origin.getZ()); -+ BlockPos nearest = getHandle().getNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().getWorldCustomRegistry().registryOrThrow(Registry.BIOME_REGISTRY), biome), originPos, radius, step); -+ return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); -+ } -+ -+ @Override -+ public boolean isUltrawarm() { -+ return getHandle().dimensionType().ultraWarm(); -+ } -+ -+ @Override -+ public boolean isNatural() { -+ return getHandle().dimensionType().natural(); -+ } -+ -+ @Override -+ public double getCoordinateScale() { -+ return getHandle().dimensionType().coordinateScale(); -+ } -+ -+ @Override -+ public boolean hasSkylight() { -+ return getHandle().dimensionType().hasSkyLight(); -+ } -+ -+ @Override -+ public boolean hasBedrockCeiling() { -+ return getHandle().dimensionType().hasSkyLight(); -+ } -+ -+ @Override -+ public boolean isPiglinSafe() { -+ return getHandle().dimensionType().piglinSafe(); -+ } -+ -+ @Override -+ public boolean doesBedWork() { -+ return getHandle().dimensionType().bedWorks(); -+ } -+ -+ @Override -+ public boolean doesRespawnAnchorWork() { -+ return getHandle().dimensionType().respawnAnchorWorks(); -+ } -+ -+ @Override -+ public boolean hasRaids() { -+ return getHandle().dimensionType().hasRaids(); -+ } -+ -+ @Override -+ public boolean isFixedTime() { -+ return getHandle().dimensionType().hasFixedTime(); -+ } -+ -+ @Override -+ public Collection getInfiniburn() { -+ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().dimensionType().getInfiniburnTag().getTagged().iterator(), CraftMagicNumbers::getMaterial)); -+ } -+ // Paper end -+ - @Override - public Raid locateNearestRaid(Location location, int radius) { - Validate.notNull(location, "Location cannot be null"); diff --git a/Remapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch b/Remapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch deleted file mode 100644 index 87c355341c..0000000000 --- a/Remapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 24 Dec 2020 12:27:41 -0800 -Subject: [PATCH] Added PlayerBedFailEnterEvent - - -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 c0d2ca1daca0c0c6f21334bc4d9d039440efc453..007d9476943f5a9c75554927df941bda0f7dd6d5 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -2230,6 +2230,7 @@ public abstract class Player extends LivingEntity { - this.message = ichatbasecomponent; - } - -+ public @Nullable Component getChatComponent() { return this.getMessage(); }; // Paper - OBFHELPER - @Nullable - public Component getMessage() { - return this.message; -diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java -index 9dcbc0f741f5980305ae031daac70c7933bc6862..9dcf145b6d1a93785150d268828bca4bb31984c8 100644 ---- a/src/main/java/net/minecraft/world/level/block/BedBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java -@@ -43,6 +43,8 @@ import net.minecraft.world.phys.shapes.CollisionContext; - import net.minecraft.world.phys.shapes.Shapes; - import net.minecraft.world.phys.shapes.VoxelShape; - import org.apache.commons.lang3.ArrayUtils; -+import io.papermc.paper.event.player.PlayerBedFailEnterEvent; // Paper -+import io.papermc.paper.adventure.PaperAdventure; // Paper - - public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock { - -@@ -101,14 +103,23 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock - BlockPos finalblockposition = pos; - // CraftBukkit end - player.startSleepInBed(pos).ifLeft((entityhuman_enumbedresult) -> { -+ // Paper start - PlayerBedFailEnterEvent -+ if (entityhuman_enumbedresult != null) { -+ PlayerBedFailEnterEvent event = new PlayerBedFailEnterEvent((org.bukkit.entity.Player) player.getBukkitEntity(), PlayerBedFailEnterEvent.FailReason.VALUES[entityhuman_enumbedresult.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(world, finalblockposition), entityhuman_enumbedresult == Player.BedSleepingProblem.NOT_POSSIBLE_HERE, PaperAdventure.asAdventure(entityhuman_enumbedresult.getChatComponent())); -+ if (!event.callEvent()) { -+ return; -+ } -+ // Paper end - // CraftBukkit start - handling bed explosion from below here -- if (entityhuman_enumbedresult == Player.BedSleepingProblem.NOT_POSSIBLE_HERE) { -+ if (event.getWillExplode()) { // Paper - this.explodeBed(finaliblockdata, world, finalblockposition); - } else - // CraftBukkit end - if (entityhuman_enumbedresult != null) { -- player.displayClientMessage(entityhuman_enumbedresult.getMessage(), true); -+ final net.kyori.adventure.text.Component message = event.getMessage(); // Paper -+ if(message != null) player.displayClientMessage(PaperAdventure.asVanilla(message), true); // Paper - } -+ } // Paper - - }); - return InteractionResult.SUCCESS; diff --git a/Remapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch b/Remapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch deleted file mode 100644 index e796b62074..0000000000 --- a/Remapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Sat, 24 Apr 2021 02:09:32 -0700 -Subject: [PATCH] Implement methods to convert between Component and - Brigadier's Message - - -diff --git a/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..dd6012b6a097575b2d1471be5069eccee4537c0a ---- /dev/null -+++ b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java -@@ -0,0 +1,30 @@ -+package io.papermc.paper.brigadier; -+ -+import com.mojang.brigadier.Message; -+import io.papermc.paper.adventure.PaperAdventure; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.ComponentLike; -+import net.minecraft.network.chat.ComponentUtils; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+import static java.util.Objects.requireNonNull; -+ -+public enum PaperBrigadierProviderImpl implements PaperBrigadierProvider { -+ INSTANCE; -+ -+ PaperBrigadierProviderImpl() { -+ PaperBrigadierProvider.initialize(this); -+ } -+ -+ @Override -+ public @NonNull Message message(final @NonNull ComponentLike componentLike) { -+ requireNonNull(componentLike, "componentLike"); -+ return PaperAdventure.asVanilla(componentLike.asComponent()); -+ } -+ -+ @Override -+ public @NonNull Component componentFromMessage(final @NonNull Message message) { -+ requireNonNull(message, "message"); -+ return PaperAdventure.asAdventure(ComponentUtils.fromMessage(message)); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index c2947313cc0eda3247fb4b20ddd1d0b86c37c50a..0198268bc614b190cd84f625a62f6c55247a01c8 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -210,6 +210,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - } - com.destroystokyo.paper.PaperConfig.registerCommands(); - com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now -+ io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider - // Paper end - - this.setPvpAllowed(dedicatedserverproperties.pvp); diff --git a/Remapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/Remapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch deleted file mode 100644 index cf90fd18e8..0000000000 --- a/Remapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Fri, 23 Apr 2021 22:42:42 +0100 -Subject: [PATCH] Fix anchor respawn acting as a bed respawn from the end - portal - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 23cfaf5c432221f2d1afe37ba657f723d6d21a73..a4e897171ce05736bcead319b7fda74d2b02fd2e 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -867,6 +867,7 @@ public abstract class PlayerList { - - // Paper start - boolean isBedSpawn = false; -+ boolean isAnchorSpawn = false; - boolean isRespawn = false; - boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 - // Paper end -@@ -887,6 +888,7 @@ public abstract class PlayerList { - if (optional.isPresent()) { - BlockState iblockdata = worldserver1.getBlockState(blockposition); - boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); -+ isAnchorSpawn = flag3; // Paper - Fix anchor respawn acting as a bed respawn from the end portal - Vec3 vec3d = (Vec3) optional.get(); - float f1; - -@@ -914,7 +916,7 @@ public abstract class PlayerList { - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); -- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag2, flag2); -+ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal - cserver.getPluginManager().callEvent(respawnEvent); - // Spigot Start - if (entityplayer.connection.isDisconnected()) { diff --git a/Remapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch b/Remapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch deleted file mode 100644 index b0c5ab3263..0000000000 --- a/Remapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 17:17:47 -0700 -Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 5b0eb8744dba5df6f16bafd6d907cd1efd508fe6..a0e69cac7699ddc318057c8016e329850d3baa26 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2440,7 +2440,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - case PERFORM_RESPAWN: - if (this.player.wonGame) { - this.player.wonGame = false; -- this.player = this.server.getPlayerList().respawn(this.player, true); -+ this.player = this.server.getPlayerList().moveToWorld(this.player, this.server.getLevel(this.player.getRespawnDimension()), true, null, true, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); // Paper - add isEndCreditsRespawn argument - CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD); - } else { - if (this.player.getHealth() > 0.0F) { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index a4e897171ce05736bcead319b7fda74d2b02fd2e..6011b43ae8a858f88b8fcf6dc0bf147024a4742c 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -816,7 +816,13 @@ public abstract class PlayerList { - return this.moveToWorld(player, this.server.getLevel(player.getRespawnDimension()), alive, null, true); - } - -+ // Paper start - public ServerPlayer moveToWorld(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation) { -+ return moveToWorld(entityplayer, worldserver, flag, location, avoidSuffocation, new org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag[0]); -+ } -+ -+ public ServerPlayer moveToWorld(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag...respawnFlags) { -+ // Paper end - entityplayer.stopRiding(); // CraftBukkit - this.players.remove(entityplayer); - this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -916,7 +922,7 @@ public abstract class PlayerList { - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); -- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal -+ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn, com.google.common.collect.ImmutableSet.builder().add(respawnFlags)); // Paper - Fix anchor respawn acting as a bed respawn from the end portal - cserver.getPluginManager().callEvent(respawnEvent); - // Spigot Start - if (entityplayer.connection.isDisconnected()) { diff --git a/Remapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch b/Remapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch deleted file mode 100644 index 57b84d6df6..0000000000 --- a/Remapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spyridon Pagkalos -Date: Thu, 25 Mar 2021 20:28:04 +0200 -Subject: [PATCH] Introduce beacon activation/deactivation events - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -index fed29e5707e2a7f64159d284c52647dd91e1948e..7025a27c25f8640df06a3c65c2086059769870b5 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -@@ -199,6 +199,15 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - this.playSound(SoundEvents.BEACON_AMBIENT); - } - } -+ // Paper start - beacon activation/deactivation events -+ if (!(i1 > 0) && this.levels > 0) { -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); -+ new io.papermc.paper.event.block.BeaconActivatedEvent(block).callEvent(); -+ } else if (i1 > 0 && !(this.levels > 0)) { -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); -+ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); -+ } -+ // Paper end - - if (this.lastCheckY >= l) { - this.lastCheckY = -1; -@@ -255,6 +264,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - - @Override - public void setRemoved() { -+ // Paper start - BeaconDeactivatedEvent -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); -+ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); -+ // Paper end - this.playSound(SoundEvents.BEACON_DEACTIVATE); - super.setRemoved(); - } diff --git a/Remapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch b/Remapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch deleted file mode 100644 index 72cbb09b5a..0000000000 --- a/Remapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Thu, 29 Apr 2021 21:19:33 +0200 -Subject: [PATCH] Add Channel initialization listeners - - -diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..88099df34c2d74daba9645aadf65b446ca795a91 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java -@@ -0,0 +1,15 @@ -+package io.papermc.paper.network; -+ -+import io.netty.channel.Channel; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+/** -+ * Internal API to register channel initialization listeners. -+ *

    -+ * This is not officially supported API and we make no guarantees to the existence or state of this interface. -+ */ -+@FunctionalInterface -+public interface ChannelInitializeListener { -+ -+ void afterInitChannel(@NonNull Channel channel); -+} -diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..30e62719e0a83525daa33cf41cb61df360c0e046 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java -@@ -0,0 +1,74 @@ -+package io.papermc.paper.network; -+ -+import io.netty.channel.Channel; -+import net.kyori.adventure.key.Key; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+ -+import java.util.Collections; -+import java.util.HashMap; -+import java.util.Map; -+ -+/** -+ * Internal API to register channel initialization listeners. -+ *

    -+ * This is not officially supported API and we make no guarantees to the existence or state of this class. -+ */ -+public final class ChannelInitializeListenerHolder { -+ -+ private static final Map LISTENERS = new HashMap<>(); -+ private static final Map IMMUTABLE_VIEW = Collections.unmodifiableMap(LISTENERS); -+ -+ private ChannelInitializeListenerHolder() { -+ } -+ -+ /** -+ * Registers whether an initialization listener is registered under the given key. -+ * -+ * @param key key -+ * @return whether an initialization listener is registered under the given key -+ */ -+ public static boolean hasListener(@NonNull Key key) { -+ return LISTENERS.containsKey(key); -+ } -+ -+ /** -+ * Registers a channel initialization listener called after ServerConnection is initialized. -+ * -+ * @param key key -+ * @param listener initialization listeners -+ */ -+ public static void addListener(@NonNull Key key, @NonNull ChannelInitializeListener listener) { -+ LISTENERS.put(key, listener); -+ } -+ -+ /** -+ * Removes and returns an initialization listener registered by the given key if present. -+ * -+ * @param key key -+ * @return removed initialization listener if present -+ */ -+ public static @Nullable ChannelInitializeListener removeListener(@NonNull Key key) { -+ return LISTENERS.remove(key); -+ } -+ -+ /** -+ * Returns an immutable map of registered initialization listeners. -+ * -+ * @return immutable map of registered initialization listeners -+ */ -+ public static @NonNull Map getListeners() { -+ return IMMUTABLE_VIEW; -+ } -+ -+ /** -+ * Calls the registered listeners with the given channel. -+ * -+ * @param channel channel -+ */ -+ public static void callListeners(@NonNull Channel channel) { -+ for (ChannelInitializeListener listener : LISTENERS.values()) { -+ listener.afterInitChannel(channel); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -index d46910cfdc0aef046a0c79731a85d381953c328a..bcc19d0a4b6c5f683dc416e27a13705b57213d21 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -@@ -104,6 +104,7 @@ public class ServerConnectionListener { - pending.add((Connection) object); // Paper - channel.pipeline().addLast("packet_handler", (ChannelHandler) object); - ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); -+ io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper - } - }).group((EventLoopGroup) lazyinitvar.get()).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit - } diff --git a/Remapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch b/Remapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch deleted file mode 100644 index de0a65c719..0000000000 --- a/Remapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 26 Apr 2021 01:27:08 +0100 -Subject: [PATCH] Send empty commands if tab completion is disabled - - -diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java -index e2f18b5bf1e091fe5fd868520a6d1bcc2669c24c..1d880a80348527d036b6f8b04f7dd1c4a479fcfd 100644 ---- a/src/main/java/net/minecraft/commands/Commands.java -+++ b/src/main/java/net/minecraft/commands/Commands.java -@@ -327,7 +327,12 @@ public class Commands { - } - - public void sendCommands(ServerPlayer player) { -- if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot -+ // Paper start - Send empty commands if tab completion is disabled -+ if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) { //return; // Spigot -+ player.connection.send(new ClientboundCommandsPacket(new RootCommandNode<>())); -+ return; -+ } -+ // Paper end - // CraftBukkit start - // Register Vanilla commands into builtRoot as before - // Paper start - Async command map building diff --git a/Remapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch b/Remapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch deleted file mode 100644 index b99c0c4512..0000000000 --- a/Remapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Thu, 6 May 2021 14:56:43 +0100 -Subject: [PATCH] Add more WanderingTrader API - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -index 04c4cca4be8886feb59f180915977b77f9c7dde8..22a695ee3f6c60d484285f1b441b809da61f2436 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -@@ -57,6 +57,10 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill - @Nullable - private BlockPos wanderTarget; - private int despawnDelay; -+ // Paper start - Add more WanderingTrader API -+ public boolean canDrinkPotion = true; -+ public boolean canDrinkMilk = true; -+ // Paper end - - public WanderingTrader(EntityType type, Level world) { - super(type, world); -@@ -68,10 +72,10 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill - protected void registerGoals() { - this.goalSelector.addGoal(0, new FloatGoal(this)); - this.goalSelector.addGoal(0, new UseItemGoal<>(this, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEvents.WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { -- return this.world.isNight() && !entityvillagertrader.isInvisible(); -+ return canDrinkPotion && this.world.isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API - })); - this.goalSelector.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { -- return this.level.isDay() && entityvillagertrader.isInvisible(); -+ return canDrinkMilk && this.level.isDay() && entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API - })); - this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this)); - this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zombie.class, 8.0F, 0.5D, 0.5D)); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -index a00b1ee5d80d3918ece2260dc1360aa90de16c8a..de58fc26bd811e87cd393bdecee796faf72e65e1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -@@ -34,4 +34,26 @@ public class CraftWanderingTrader extends CraftAbstractVillager implements Wande - public void setDespawnDelay(int despawnDelay) { - getHandle().setDespawnDelay(despawnDelay); - } -+ -+ // Paper start - Add more WanderingTrader API -+ @Override -+ public void setCanDrinkPotion(boolean bool) { -+ getHandle().canDrinkPotion = bool; -+ } -+ -+ @Override -+ public boolean canDrinkPotion() { -+ return getHandle().canDrinkPotion; -+ } -+ -+ @Override -+ public void setCanDrinkMilk(boolean bool) { -+ getHandle().canDrinkMilk = bool; -+ } -+ -+ @Override -+ public boolean canDrinkMilk() { -+ return getHandle().canDrinkMilk; -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch b/Remapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch deleted file mode 100644 index 530ee44dcf..0000000000 --- a/Remapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Mon, 5 Apr 2021 18:12:29 -0400 -Subject: [PATCH] Add EntityBlockStorage#clearEntities() - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -index cbd0587eeecf14b1914bdb33f7a4584bd6b5c8d0..83e5367ee1126afe31e9f704a0daedd310339d15 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -@@ -120,6 +120,11 @@ public class BeehiveBlockEntity extends BlockEntity implements TickableBlockEnti - return this.stored.size(); - } - -+ // Paper start - Add EntityBlockStorage clearEntities -+ public void clearBees() { -+ this.stored.clear(); -+ } -+ // Paper end - public static int getHoneyLevel(BlockState state) { - return (Integer) state.getValue(BeehiveBlock.HONEY_LEVEL); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java -index e61ea9c7fb711e8335a5d0fd5a8bc0152a225038..3346a1962a992566fe840fd0a75cfa06f694833a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java -@@ -83,4 +83,10 @@ public class CraftBeehive extends CraftBlockEntityState impl - - getSnapshot().addOccupant(((CraftBee) entity).getHandle(), false); - } -+ // Paper start - Add EntityBlockStorage clearEntities -+ @Override -+ public void clearEntities() { -+ getSnapshot().clearBees(); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/Remapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch deleted file mode 100644 index 9006bd8edb..0000000000 --- a/Remapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alvinn8 <42838560+Alvinn8@users.noreply.github.com> -Date: Fri, 8 Jan 2021 20:31:13 +0100 -Subject: [PATCH] Add Adventure message to PlayerAdvancementDoneEvent - - -diff --git a/src/main/java/net/minecraft/advancements/Advancement.java b/src/main/java/net/minecraft/advancements/Advancement.java -index 9d27b658d32297337fb367bae628a1cc3a78712a..4abbe45237667c08753c040ef1281af1b2f34f88 100644 ---- a/src/main/java/net/minecraft/advancements/Advancement.java -+++ b/src/main/java/net/minecraft/advancements/Advancement.java -@@ -76,6 +76,7 @@ public class Advancement { - return this.parent; - } - -+ public final @Nullable DisplayInfo getAdvancementDisplay() { return this.getDisplay(); } // Paper - OBFHELPER - @Nullable - public DisplayInfo getDisplay() { - return this.display; -@@ -125,6 +126,7 @@ public class Advancement { - return this.requirements; - } - -+ public final Component getChatComponent() { return this.getChatComponent(); } // Paper - OBFHELPER - public Component getChatComponent() { - return this.chatComponent; - } -diff --git a/src/main/java/net/minecraft/advancements/DisplayInfo.java b/src/main/java/net/minecraft/advancements/DisplayInfo.java -index 2bcf14826ec1c6a1654246844d03184ceae55d79..1b41578fed1da6d15a806a7200e53954f608b625 100644 ---- a/src/main/java/net/minecraft/advancements/DisplayInfo.java -+++ b/src/main/java/net/minecraft/advancements/DisplayInfo.java -@@ -54,10 +54,12 @@ public class DisplayInfo { - return this.description; - } - -+ public final FrameType getFrameType() { return this.getFrame(); } // Paper - OBFHELPER - public FrameType getFrame() { - return this.frame; - } - -+ public final boolean shouldAnnounceToChat() { return this.shouldAnnounceChat(); } // Paper - OBFHELPER - public boolean shouldAnnounceChat() { - return this.announceChat; - } -diff --git a/src/main/java/net/minecraft/advancements/FrameType.java b/src/main/java/net/minecraft/advancements/FrameType.java -index 0ccac480a760259412b525e66c43de3a209543f5..f6d4b876bdd25942763780f17c8bb69ac3d56031 100644 ---- a/src/main/java/net/minecraft/advancements/FrameType.java -+++ b/src/main/java/net/minecraft/advancements/FrameType.java -@@ -20,6 +20,7 @@ public enum FrameType { - this.displayName = new TranslatableComponent("advancements.toast." + s); - } - -+ public final String getId() { return this.getName(); } // Paper - OBFHELPER - public String getName() { - return this.name; - } -diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java -index b8d3f2c59199e245e2035d6205dd1a042aa93f77..fcb59f6538e66fa43d11d4998e6eeac2e33b0393 100644 ---- a/src/main/java/net/minecraft/server/PlayerAdvancements.java -+++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java -@@ -51,6 +51,7 @@ import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.GameRules; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - - public class PlayerAdvancements { - -@@ -313,10 +314,18 @@ public class PlayerAdvancements { - this.progressChanged.add(advancement); - flag = true; - if (!flag1 && advancementprogress.isDone()) { -- this.player.level.getCraftServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit)); // CraftBukkit -+ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent -+ boolean announceToChat = advancement.getAdvancementDisplay() != null && advancement.getAdvancementDisplay().shouldAnnounceToChat(); -+ net.kyori.adventure.text.Component message = announceToChat ? PaperAdventure.asAdventure(new TranslatableComponent("chat.type.advancement." + advancement.getAdvancementDisplay().getFrameType().getId(), this.player.getDisplayName(), advancement.getChatComponent())) : null; -+ org.bukkit.event.player.PlayerAdvancementDoneEvent event = new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit, message); -+ this.player.level.getCraftServer().getPluginManager().callEvent(event); -+ message = event.message(); -+ // Paper end - advancement.getRewards().a(this.player); -- if (advancement.getDisplay() != null && advancement.getDisplay().shouldAnnounceChat() && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { -- this.playerList.broadcastMessage(new TranslatableComponent("chat.type.advancement." + advancement.getDisplay().getFrame().getName(), new Object[]{this.player.getDisplayName(), advancement.getChatComponent()}), ChatType.SYSTEM, Util.NIL_UUID); -+ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent -+ if (message != null && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { -+ this.playerList.broadcastMessage(PaperAdventure.asVanilla(message), ChatType.SYSTEM, Util.getNullUUID()); -+ // Paper end - } - } - } diff --git a/Remapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/Remapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch deleted file mode 100644 index a376cbbc19..0000000000 --- a/Remapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Wed, 12 May 2021 08:09:19 +0100 -Subject: [PATCH] Add raw address to AsyncPlayerPreLoginEvent - - -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 573963a09f15046cfcaab83aef906801ce70d75a..99275a8bc2e7bf242ff3c5b5c29924af5328327a 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -325,12 +325,13 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - // Paper end - String playerName = gameProfile.getName(); - java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); -+ java.net.InetAddress rawAddress = ((java.net.InetSocketAddress) connection.getRawAddress()).getAddress(); // Paper - java.util.UUID uniqueId = gameProfile.getId(); - final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; - - // Paper start - PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); -- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); -+ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile); - server.getPluginManager().callEvent(asyncEvent); - profile = asyncEvent.getPlayerProfile(); - profile.complete(true); diff --git a/Remapped-Spigot-Server-Patches/0726-Inventory-close.patch b/Remapped-Spigot-Server-Patches/0726-Inventory-close.patch deleted file mode 100644 index f206ea0fbd..0000000000 --- a/Remapped-Spigot-Server-Patches/0726-Inventory-close.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 11 May 2021 14:54:56 -0700 -Subject: [PATCH] Inventory#close - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index 7ccc085228f373e6eba55d809bed480d43d5c211..16d34f44e92e26d13188417942f444952f98dfa1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -448,6 +448,14 @@ public class CraftInventory implements Inventory { - clear(i); - } - } -+ // Paper start -+ @Override -+ public int close() { -+ int count = this.inventory.getViewers().size(); -+ com.google.common.collect.Lists.newArrayList(this.inventory.getViewers()).forEach(HumanEntity::closeInventory); -+ return count; -+ } -+ // Paper end - - @Override - public ListIterator iterator() { diff --git a/Remapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch b/Remapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch deleted file mode 100644 index 4776fc7a79..0000000000 --- a/Remapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 12 May 2021 03:21:22 -0700 -Subject: [PATCH] call PortalCreateEvent players and end platform - - -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 727af6ac84075db87615ebac51a024e6376fa3cb..6e2a272075ead399004dabfb7d4f0ea5fd32ffc2 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -496,6 +496,7 @@ public class BlockPos extends Vec3i { - return this.set(this.getX() + direction.getStepX() * distance, this.getY() + direction.getStepY() * distance, this.getZ() + direction.getStepZ() * distance); - } - -+ public BlockPos.MutableBlockPos withOffset(int x, int y, int z) { return move(x, y, z); } // Paper - OBFHELPER - public BlockPos.MutableBlockPos move(int dx, int dy, int dz) { - return this.set(this.getX() + dx, this.getY() + dy, this.getZ() + dz); - } -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 314f168c9d17ab3654c9dda07e48839570f0d332..5d710a1f4e0c61d4be6efe8cebd9b80789868338 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1142,15 +1142,21 @@ public class ServerPlayer extends Player implements ContainerListener { - private void createEndPlatform(ServerLevel world, BlockPos centerPos) { - BlockPos.MutableBlockPos blockposition_mutableblockposition = centerPos.mutable(); - -+ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(world); // Paper - for (int i = -2; i <= 2; ++i) { - for (int j = -2; j <= 2; ++j) { - for (int k = -1; k < 3; ++k) { - BlockState iblockdata = k == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); - -- world.setBlockAndUpdate(blockposition_mutableblockposition.set(centerPos).move(j, k, i), iblockdata); -+ blockList.setBlock(blockposition_mutableblockposition.setValues(centerPos).withOffset(j, k, i), iblockdata, 3); // Paper - } - } - } -+ // Paper start -+ if (new org.bukkit.event.world.PortalCreateEvent((List< org.bukkit.block.BlockState>) (List) blockList.getList(), world.getWorld(), this.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM).callEvent()) { -+ blockList.updateList(); -+ } -+ // Paper end - - } - diff --git a/Remapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/Remapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch deleted file mode 100644 index fb4c1ca38d..0000000000 --- a/Remapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 11 May 2021 00:48:33 +0200 -Subject: [PATCH] Add a "should burn in sunlight" API for Phantoms and - Skeletons - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -index 68e52e3a31e70569d1a92602aff4b7b81c594757..a8a0dba43453b7ac73e8e0faf7728445d9bcc2cd 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -+++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -@@ -98,9 +98,15 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo - return MobType.UNDEAD; - } - -+ // Paper start -+ private boolean shouldBurnInDay = true; -+ public boolean shouldBurnInDay() { return shouldBurnInDay; } -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } -+ // Paper end -+ - @Override - public void aiStep() { -- boolean flag = this.isSunBurnTick(); -+ boolean flag = shouldBurnInDay && this.isSunBurnTick(); // Paper - Configurable Burning - - if (flag) { - ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); -@@ -224,7 +230,16 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo - public void readAdditionalSaveData(CompoundTag tag) { - super.readAdditionalSaveData(tag); - this.reassessWeaponGoal(); -+ this.shouldBurnInDay = tag.getBoolean("Paper.ShouldBurnInDay"); // Paper -+ } -+ -+ // Paper start -+ @Override -+ public void addAdditionalSaveData(CompoundTag tag) { -+ super.addAdditionalSaveData(tag); -+ tag.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); - } -+ // Paper end - - @Override - public void setItemSlot(EquipmentSlot slot, ItemStack stack) { -diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index a40c23e824652cff59633b7c314e27ec9a515c07..8f4dd4540330966689e71568e9e9ef77f82a786a 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -@@ -134,7 +134,7 @@ public class Phantom extends FlyingMob implements Enemy { - - @Override - public void aiStep() { -- if (this.isAlive() && this.isSunBurnTick()) { -+ if (this.isAlive() && shouldBurnInDay && this.isSunBurnTick()) { // Paper - Configurable Burning - this.setSecondsOnFire(8); - } - -@@ -165,6 +165,7 @@ public class Phantom extends FlyingMob implements Enemy { - if (tag.hasUUID("Paper.SpawningEntity")) { - this.spawningEntity = tag.getUUID("Paper.SpawningEntity"); - } -+ this.shouldBurnInDay = tag.getBoolean("Paper.ShouldBurnInDay"); - // Paper end - } - -@@ -179,6 +180,7 @@ public class Phantom extends FlyingMob implements Enemy { - if (this.spawningEntity != null) { - tag.setUUID("Paper.SpawningEntity", this.spawningEntity); - } -+ tag.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); - // Paper end - } - -@@ -233,6 +235,10 @@ public class Phantom extends FlyingMob implements Enemy { - return spawningEntity; - } - public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } -+ -+ private boolean shouldBurnInDay = true; -+ public boolean shouldBurnInDay() { return shouldBurnInDay; } -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } - // Paper end - - class PhantomAttackPlayerTargetGoal extends Goal { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -index 92162fa22f5e98b7837bde5830bd47c31b8b52d8..011ad2224a3a3a2d255b2498e406fbb047359240 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -@@ -39,5 +39,15 @@ public class CraftPhantom extends CraftFlying implements Phantom { - public java.util.UUID getSpawningEntity() { - return getHandle().getSpawningEntity(); - } -+ -+ @Override -+ public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); -+ } -+ -+ @Override -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ getHandle().setShouldBurnInDay(shouldBurnInDay); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -index b2d3244cca4d9d108159f3537d8a9aace3f8e77f..28dda8beb1793fad47b2c9db815c0b6cf6ed781a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -@@ -36,4 +36,16 @@ public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroy - public void setSkeletonType(SkeletonType type) { - throw new UnsupportedOperationException("Not supported."); - } -+ -+ // Paper start -+ @Override -+ public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); -+ } -+ -+ @Override -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ getHandle().setShouldBurnInDay(shouldBurnInDay); -+ } -+ // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch b/Remapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch deleted file mode 100644 index 140b30b682..0000000000 --- a/Remapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sceri -Date: Fri, 14 May 2021 19:06:51 +0500 -Subject: [PATCH] Fix CraftPotionBrewer cache - - -diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -index e20d96ec67dcbe935357b4de7e0e9a6984dc3303..eb28a055ba60bb1da3412cf0dbbe5ce76a779f38 100644 ---- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -@@ -15,12 +15,18 @@ import org.bukkit.potion.PotionEffectType; - import org.bukkit.potion.PotionType; - - public class CraftPotionBrewer implements PotionBrewer { -- private static final Map> cache = Maps.newHashMap(); -+ private static final Map> cache = Maps.newHashMap(); // Paper - - @Override - public Collection getEffects(PotionType damage, boolean upgraded, boolean extended) { -- if (cache.containsKey(damage)) -- return cache.get(damage); -+ // Paper start -+ int key = damage.ordinal() << 2; -+ key |= (upgraded ? 1 : 0) << 1; -+ key |= extended ? 1 : 0; -+ -+ if (cache.containsKey(key)) -+ return cache.get(key); -+ // Paper end - - List mcEffects = Potion.byName(CraftPotionUtil.fromBukkit(new PotionData(damage, extended, upgraded))).getEffects(); - -@@ -29,9 +35,9 @@ public class CraftPotionBrewer implements PotionBrewer { - builder.add(CraftPotionUtil.toBukkit(effect)); - } - -- cache.put(damage, builder.build()); -+ cache.put(key, builder.build()); // Paper - -- return cache.get(damage); -+ return cache.get(key); // Paper - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch b/Remapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch deleted file mode 100644 index 547e7cb557..0000000000 --- a/Remapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Sun, 16 May 2021 15:07:34 +0100 -Subject: [PATCH] Add basic Datapack API - - -diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java -new file mode 100644 -index 0000000000000000000000000000000000000000..66debefcd474e4dcc2a8889a82af6c1809c93f46 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java -@@ -0,0 +1,51 @@ -+package io.papermc.paper.datapack; -+ -+import Compatibility; -+import io.papermc.paper.event.server.ServerResourcesReloadedEvent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.packs.repository.Pack; -+import java.util.List; -+import java.util.stream.Collectors; -+ -+public class PaperDatapack implements Datapack { -+ private final String name; -+ private final Compatibility compatibility; -+ private final boolean enabled; -+ -+ PaperDatapack(Pack loader, boolean enabled) { -+ this.name = loader.getName(); -+ this.compatibility = Compatibility.valueOf(loader.getVersion().name()); -+ this.enabled = enabled; -+ } -+ -+ @Override -+ public String getName() { -+ return name; -+ } -+ -+ @Override -+ public Compatibility getCompatibility() { -+ return compatibility; -+ } -+ -+ @Override -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @Override -+ public void setEnabled(boolean enabled) { -+ if (enabled == this.enabled) { -+ return; -+ } -+ -+ MinecraftServer server = MinecraftServer.getServer(); -+ List enabledKeys = server.getPackRepository().getEnabledPacks().stream().map(Pack::getName).collect(Collectors.toList()); -+ if (enabled) { -+ enabledKeys.add(this.name); -+ } else { -+ enabledKeys.remove(this.name); -+ } -+ server.reloadServerResources(enabledKeys, ServerResourcesReloadedEvent.Cause.PLUGIN); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ec221183bef1065bda0a37e1025958df0d1f6318 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java -@@ -0,0 +1,25 @@ -+package io.papermc.paper.datapack; -+ -+import java.util.Collection; -+import java.util.stream.Collectors; -+import net.minecraft.server.packs.repository.Pack; -+import net.minecraft.server.packs.repository.PackRepository; -+ -+public class PaperDatapackManager implements DatapackManager { -+ private final PackRepository repository; -+ -+ public PaperDatapackManager(PackRepository repository) { -+ this.repository = repository; -+ } -+ -+ @Override -+ public Collection getPacks() { -+ Collection enabledPacks = repository.getEnabledPacks(); -+ return repository.getPacks().stream().map(loader -> new PaperDatapack(loader, enabledPacks.contains(loader))).collect(Collectors.toList()); -+ } -+ -+ @Override -+ public Collection getEnabledPacks() { -+ return repository.getEnabledPacks().stream().map(loader -> new PaperDatapack(loader, true)).collect(Collectors.toList()); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/packs/repository/Pack.java b/src/main/java/net/minecraft/server/packs/repository/Pack.java -index df5d258b80e37077fa236e4190ad934853c88619..4120326e0d047347e5d7ab9521babe7bb6b6a7db 100644 ---- a/src/main/java/net/minecraft/server/packs/repository/Pack.java -+++ b/src/main/java/net/minecraft/server/packs/repository/Pack.java -@@ -101,6 +101,7 @@ public class Pack implements AutoCloseable { - }); - } - -+ public final PackCompatibility getVersion() { return this.getCompatibility(); } // Paper - OBFHELPER - public PackCompatibility getCompatibility() { - return this.compatibility; - } -@@ -109,6 +110,7 @@ public class Pack implements AutoCloseable { - return (PackResources) this.supplier.get(); - } - -+ public final String getName() { return this.getId(); } // Paper - OBFHELPER - public String getId() { - return this.id; - } -diff --git a/src/main/java/net/minecraft/server/packs/repository/PackRepository.java b/src/main/java/net/minecraft/server/packs/repository/PackRepository.java -index bce2fd67048bd1fd53865eef81bac262dbda2865..8d0ef3bdf9fa283f54628800768717181df28aa5 100644 ---- a/src/main/java/net/minecraft/server/packs/repository/PackRepository.java -+++ b/src/main/java/net/minecraft/server/packs/repository/PackRepository.java -@@ -88,6 +88,7 @@ public class PackRepository implements AutoCloseable { - return this.available.keySet(); - } - -+ public final Collection getPacks() { return this.getAvailablePacks(); } // Paper - OBFHELPER - public Collection getAvailablePacks() { - return this.available.values(); - } -@@ -96,6 +97,7 @@ public class PackRepository implements AutoCloseable { - return (Collection) this.selected.stream().map(Pack::getId).collect(ImmutableSet.toImmutableSet()); - } - -+ public final Collection getEnabledPacks() { return this.getSelectedPacks(); } // Paper - OBFHELPER - public Collection getSelectedPacks() { - return this.selected; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6905256147d9bd79e5f52bf86bdb21c89b8411a7..63639923f7875d76f569b8c6e958782c6462d906 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -18,6 +18,7 @@ import com.mojang.serialization.Lifecycle; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.datapack.PaperDatapackManager; // Paper - import io.papermc.paper.util.TraceUtil; - import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; - import java.awt.image.BufferedImage; -@@ -264,6 +265,7 @@ public final class CraftServer implements Server { - public boolean ignoreVanillaPermissions = false; - private final List playerView; - public int reloadCount; -+ private final PaperDatapackManager datapackManager; // Paper - public static Exception excessiveVelEx; // Paper - Velocity warnings - - static { -@@ -346,6 +348,7 @@ public final class CraftServer implements Server { - TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - loadIcon(); -+ datapackManager = new PaperDatapackManager(console.getPackRepository()); // Paper - } - - public boolean getCommandBlockOverride(String command) { -@@ -2496,5 +2499,11 @@ public final class CraftServer implements Server { - public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { - return mobGoals; - } -+ -+ @Override -+ public PaperDatapackManager getDatapackManager() { -+ return datapackManager; -+ } -+ - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch b/Remapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch deleted file mode 100644 index a1f57cca90..0000000000 --- a/Remapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Mon, 17 May 2021 00:34:55 -0700 -Subject: [PATCH] Add environment variable to disable server gui - - -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 9dc9a5e6ad7f23c8bf3553c765ceeecd67a49ac1..ba6c17da4875c3a342da99e354c9f07cc7f17326 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -225,6 +225,7 @@ public class Main { - */ - boolean flag1 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui"); - -+ if(!Boolean.parseBoolean(System.getenv().getOrDefault("PAPER_DISABLE_SERVER_GUI", String.valueOf(false)))) // Paper - if (flag1 && !GraphicsEnvironment.isHeadless()) { - dedicatedserver1.showGui(); - } diff --git a/Remapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch b/Remapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch deleted file mode 100644 index 31a8669378..0000000000 --- a/Remapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 10:04:43 -0700 -Subject: [PATCH] additions to PlayerGameModeChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java -index c0098a8f8a9fa2671ff66cbcf50ac74b057d1446..ebbd6f2b0e7236b33d136ab2218c8eca4c5df03e 100644 ---- a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java -+++ b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java -@@ -43,7 +43,13 @@ public class DefaultGameModeCommands { - ServerPlayer entityplayer = (ServerPlayer) iterator.next(); - - if (entityplayer.gameMode.getGameModeForPlayer() != defaultGameMode) { -- entityplayer.setGameMode(defaultGameMode); -+ // Paper start - handle event cancelling the change -+ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(defaultGameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getScoreboardName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); -+ if (event != null && event.isCancelled()) { -+ source.sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); -+ continue; -+ } -+ // Paper end - ++i; - } - } -diff --git a/src/main/java/net/minecraft/server/commands/GameModeCommand.java b/src/main/java/net/minecraft/server/commands/GameModeCommand.java -index 3e999090fb3b03b996a9790c53e5b4618c8891f7..3b17c81167f8e011e7f9c09bf42eb632f5a3c2f2 100644 ---- a/src/main/java/net/minecraft/server/commands/GameModeCommand.java -+++ b/src/main/java/net/minecraft/server/commands/GameModeCommand.java -@@ -62,13 +62,13 @@ public class GameModeCommand { - ServerPlayer entityplayer = (ServerPlayer) iterator.next(); - - if (entityplayer.gameMode.getGameModeForPlayer() != gameMode) { -- entityplayer.setGameMode(gameMode); -- // CraftBukkit start - handle event cancelling the change -- if (entityplayer.gameMode.getGameModeForPlayer() != gameMode) { -- context.getSource().sendFailure(new net.minecraft.network.chat.TextComponent("Failed to set the gamemode of '" + entityplayer.getScoreboardName() + "'")); -+ // Paper start - handle event cancelling the change -+ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getScoreboardName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); -+ if (event != null && event.isCancelled()) { -+ context.getSource().sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); - continue; - } -- // CraftBukkit end -+ // Paper end - logGamemodeChange((CommandSourceStack) context.getSource(), entityplayer, gameMode); - ++i; - } -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 5d710a1f4e0c61d4be6efe8cebd9b80789868338..779b926921fd435620cbbc69ed6f9931a422b652 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -393,7 +393,16 @@ public class ServerPlayer extends Player implements ContainerListener { - if (this.getY() > 300) this.setPosRaw(getX(), 257, getZ()); // Paper - bring down to a saner Y level if out of world - if (tag.contains("playerGameType", 99)) { - if (this.getServer().getForceGameType()) { -+ // Paper start - call PlayerGameModeChangeEvent on join for players that do not have the correct gamemode -+ if (this.getServer().getDefaultGameType() != GameType.byId(tag.getInt("playerGameType"))) { -+ if (new org.bukkit.event.player.PlayerGameModeChangeEvent(this.getBukkitEntity(), GameMode.getByValue(this.getServer().getDefaultGameType().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) { - this.gameMode.setGameModeForPlayer(this.getServer().getDefaultGameType(), GameType.NOT_SET); -+ } else { -+ this.gameMode.setGameModeForPlayer(GameType.byId(tag.getInt("playerGameType")), tag.contains("previousPlayerGameType", 3) ? GameType.byId(tag.getInt("previousPlayerGameType")) : GameType.NOT_SET); // copied from below; if cancelled, set gamemode normally -+ } -+ } else { -+ this.gameMode.setGameModeForPlayer(GameType.byId(tag.getInt("playerGameType")), tag.contains("previousPlayerGameType", 3) ? GameType.byId(tag.getInt("previousPlayerGameType")) : GameType.NOT_SET); // copied from below; if no change needed, set gamemode normally -+ } // Paper end - } else { - this.gameMode.setGameModeForPlayer(GameType.byId(tag.getInt("playerGameType")), tag.contains("previousPlayerGameType", 3) ? GameType.byId(tag.getInt("previousPlayerGameType")) : GameType.NOT_SET); - } -@@ -1789,21 +1798,27 @@ public class ServerPlayer extends Player implements ContainerListener { - - @Override - public void setGameMode(GameType gameMode) { -+ // Paper start - Add cause and nullable message to event -+ setGamemode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null); -+ } -+ -+ public PlayerGameModeChangeEvent setGamemode(GameType enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component message) { -+ // Paper end - // CraftBukkit start -- if (gameMode == this.gameMode.getGameModeForPlayer()) { -- return; -+ if (enumgamemode == this.gameMode.getGameModeForPlayer()) { -+ return null; // Paper - } - -- PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(gameMode.getId())); -+ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(enumgamemode.getId()), cause, message); // Paper - level.getCraftServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { -- return; -+ return event; // Paper - } - // CraftBukkit end - -- this.gameMode.setGameModeForPlayer(gameMode); -- this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) gameMode.getId())); -- if (gameMode == GameType.SPECTATOR) { -+ this.gameMode.setGameModeForPlayer(enumgamemode); -+ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) enumgamemode.getId())); -+ if (enumgamemode == GameType.SPECTATOR) { - this.removeEntitiesOnShoulder(); - this.stopRiding(); - } else { -@@ -1812,6 +1827,7 @@ public class ServerPlayer extends Player implements ContainerListener { - - this.onUpdateAbilities(); - this.updateEffectVisibility(); -+ return event; // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index a0e69cac7699ddc318057c8016e329850d3baa26..c454908f23a436f66f8e64fc346186f113b6eefb 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2449,7 +2449,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - this.player = this.server.getPlayerList().respawn(this.player, false); - if (this.server.isHardcore()) { -- this.player.setGameMode(GameType.SPECTATOR); -+ this.player.setGamemode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper - ((GameRules.BooleanValue) this.player.getLevel().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, this.server); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ec8c7499662c0a810f1337ebc0fa24d2f3ca79e7..3dbe94d9b9647f5cc1e27335b36042e50c652cea 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1189,7 +1189,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - throw new IllegalArgumentException("Mode cannot be null"); - } - -- getHandle().setGameMode(GameType.byId(mode.getValue())); -+ getHandle().setGamemode(GameType.byId(mode.getValue()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.PLUGIN, null); // Paper - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch b/Remapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch deleted file mode 100644 index 74dbd3c778..0000000000 --- a/Remapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 22:11:11 -0700 -Subject: [PATCH] ItemStack repair check API - - -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index cb079bfd5339b96ad372b0a3b483d02cd0636bfd..42085d3f4ae5c6ceecaffde79fb3187712a2af00 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -269,6 +269,7 @@ public class Item implements ItemLike { - return this.category; - } - -+ public boolean canRepair(ItemStack toBeRepaired, ItemStack repairMaterial) { return isValidRepairItem(toBeRepaired, repairMaterial); } // Paper - OBFHELPER - public boolean isValidRepairItem(ItemStack stack, ItemStack ingredient) { - return false; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 402e5a98290a1701dd67d27c484c97e0a6067c4f..34eed57c7ed884e0d634ca403e38d25c95b6a038 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -485,6 +485,14 @@ public final class CraftMagicNumbers implements UnsafeValues { - return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; - } - -+ @Override -+ public boolean isValidRepairItemStack(org.bukkit.inventory.ItemStack itemToBeRepaired, org.bukkit.inventory.ItemStack repairMaterial) { -+ if (!itemToBeRepaired.getType().isItem() || !repairMaterial.getType().isItem()) { -+ return false; -+ } -+ return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); -+ } -+ - @Override - public int getProtocolVersion() { - return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion(); -diff --git a/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8d9c9b3bd53d407391d4fcb7fc773153d1a7b402 ---- /dev/null -+++ b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java -@@ -0,0 +1,48 @@ -+package io.papermc.paper.util; -+ -+import org.bukkit.Material; -+import org.bukkit.inventory.ItemStack; -+import org.bukkit.support.AbstractTestingBase; -+import org.junit.Test; -+ -+import static org.junit.Assert.assertFalse; -+import static org.junit.Assert.assertThrows; -+import static org.junit.Assert.assertTrue; -+ -+public class ItemStackRepairCheckTest extends AbstractTestingBase { -+ -+ @Test -+ public void testIsRepariableBy() { -+ ItemStack diamondPick = new ItemStack(Material.DIAMOND_PICKAXE); -+ -+ assertTrue("diamond pick isn't repairable by a diamond", diamondPick.isRepairableBy(new ItemStack(Material.DIAMOND))); -+ } -+ -+ @Test -+ public void testCanRepair() { -+ ItemStack diamond = new ItemStack(Material.DIAMOND); -+ -+ assertTrue("diamond can't repair a diamond axe", diamond.canRepair(new ItemStack(Material.DIAMOND_AXE))); -+ } -+ -+ @Test -+ public void testIsNotRepairableBy() { -+ ItemStack notDiamondPick = new ItemStack(Material.ACACIA_SAPLING); -+ -+ assertFalse("acacia sapling is repairable by a diamond", notDiamondPick.isRepairableBy(new ItemStack(Material.DIAMOND))); -+ } -+ -+ @Test -+ public void testCanNotRepair() { -+ ItemStack diamond = new ItemStack(Material.DIAMOND); -+ -+ assertFalse("diamond can repair oak button", diamond.canRepair(new ItemStack(Material.OAK_BUTTON))); -+ } -+ -+ @Test -+ public void testInvalidItem() { -+ ItemStack badItemStack = new ItemStack(Material.ACACIA_WALL_SIGN); -+ -+ assertFalse("acacia wall sign is repairable by diamond", badItemStack.isRepairableBy(new ItemStack(Material.DIAMOND))); -+ } -+} diff --git a/Remapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch b/Remapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch deleted file mode 100644 index 4bf44e22d8..0000000000 --- a/Remapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch +++ /dev/null @@ -1,211 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 6 May 2021 19:57:58 -0700 -Subject: [PATCH] More Enchantment API - - -diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -index c23ec1b31950471905c65e46273ae105de853d9b..b994a7aca0ce01b5c0d44b9b126295ffcd2f795d 100644 ---- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -+++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -@@ -17,7 +17,7 @@ import net.minecraft.world.item.ItemStack; - - public abstract class Enchantment { - -- private final EquipmentSlot[] slots; -+ private final EquipmentSlot[] slots; public final EquipmentSlot[] getSlots() { return this.slots; } // Paper - OBFHELPER - private final Enchantment.Rarity rarity; - public final EnchantmentCategory category; - @Nullable -@@ -46,6 +46,7 @@ public abstract class Enchantment { - return map; - } - -+ public Enchantment.Rarity getRarity() { return getRarity(); } // Paper - OBFHELPER - public Enchantment.Rarity getRarity() { - return this.rarity; - } -@@ -70,6 +71,7 @@ public abstract class Enchantment { - return 0; - } - -+ public float getDamageIncrease(int level, MobType enumMonsterType) { return getDamageBonus(level, enumMonsterType); } // Paper - OBFHELPER - public float getDamageBonus(int level, MobType group) { - return 0.0F; - } -@@ -123,14 +125,17 @@ public abstract class Enchantment { - return false; - } - -+ public boolean isCursed() { return isCurse(); } // Paper - OBFHELPER - public boolean isCurse() { - return false; - } - -+ public boolean isTradeable() { return isTradeable(); } // Paper - OBFHELPER - public boolean isTradeable() { - return true; - } - -+ public boolean isDiscoverable() { return isDiscoverable(); } // Paper - OBFHELPER - public boolean isDiscoverable() { - return true; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -index b1ffe6c7a5915f00a476e88f3a38349b740b4910..20858bb8463ff86c96b5fcdeca455c20c696870f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -+++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -@@ -1,8 +1,6 @@ - package org.bukkit.craftbukkit.enchantments; - - import net.minecraft.core.Registry; --import net.minecraft.world.item.enchantment.BindingCurseEnchantment; --import net.minecraft.world.item.enchantment.VanishingCurseEnchantment; - import org.bukkit.craftbukkit.inventory.CraftItemStack; - import org.bukkit.craftbukkit.util.CraftNamespacedKey; - import org.bukkit.enchantments.Enchantment; -@@ -71,7 +69,7 @@ public class CraftEnchantment extends Enchantment { - - @Override - public boolean isCursed() { -- return target instanceof BindingCurseEnchantment || target instanceof VanishingCurseEnchantment; -+ return target.isCursed(); // Paper - } - - @Override -@@ -192,6 +190,45 @@ public class CraftEnchantment extends Enchantment { - public net.kyori.adventure.text.Component displayName(int level) { - return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); - } -+ -+ @Override -+ public boolean isTradeable() { -+ return target.isTradeable(); -+ } -+ -+ @Override -+ public boolean isDiscoverable() { -+ return target.isDiscoverable(); -+ } -+ -+ @Override -+ public io.papermc.paper.enchantments.EnchantmentRarity getRarity() { -+ return fromNMSRarity(target.getRarity()); -+ } -+ -+ @Override -+ public float getDamageIncrease(int level, org.bukkit.entity.EntityCategory entityCategory) { -+ return target.getDamageIncrease(level, org.bukkit.craftbukkit.entity.CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); -+ } -+ -+ @Override -+ public java.util.Set getActiveSlots() { -+ return java.util.stream.Stream.of(target.getSlots()).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet()); -+ } -+ -+ public static io.papermc.paper.enchantments.EnchantmentRarity fromNMSRarity(net.minecraft.world.item.enchantment.Enchantment.Rarity nmsRarity) { -+ if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.COMMON) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.COMMON; -+ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.UNCOMMON) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.UNCOMMON; -+ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.RARE) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.RARE; -+ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.VERY_RARE) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.VERY_RARE; -+ } -+ -+ throw new IllegalArgumentException(String.format("Unable to convert %s to a enum value of %s.", nmsRarity, io.papermc.paper.enchantments.EnchantmentRarity.class)); -+ } - // Paper end - - public net.minecraft.world.item.enchantment.Enchantment getHandle() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index eefb6bd580ea176c3a242695ab4af46e7c61b492..25ba7a26c951fc5e4638bdb0db36e94d3e08fb2e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -835,5 +835,21 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setHurtDirection(float hurtDirection) { - getHandle().setHurtDirection(hurtDirection); - } -+ -+ public static MobType fromBukkitEntityCategory(EntityCategory entityCategory) { -+ switch (entityCategory) { -+ case NONE: -+ return MobType.UNDEFINED; -+ case UNDEAD: -+ return MobType.UNDEAD; -+ case ARTHROPOD: -+ return MobType.ARTHROPOD; -+ case ILLAGER: -+ return MobType.ILLAGER; -+ case WATER: -+ return MobType.WATER; -+ } -+ throw new IllegalArgumentException(entityCategory + " is an unrecognized entity category"); -+ } - // Paper end - } -diff --git a/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..62b56b5b43696b03fc72cac59f986d006edc3f76 ---- /dev/null -+++ b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java -@@ -0,0 +1,18 @@ -+package io.papermc.paper.enchantments; -+ -+import net.minecraft.world.item.enchantment.Enchantment.Rarity; -+import org.bukkit.craftbukkit.enchantments.CraftEnchantment; -+import org.junit.Test; -+ -+import static org.junit.Assert.assertNotNull; -+ -+public class EnchantmentRarityTest { -+ -+ @Test -+ public void test() { -+ for (Rarity nmsRarity : Rarity.values()) { -+ // Will throw exception if a bukkit counterpart is not found -+ CraftEnchantment.fromNMSRarity(nmsRarity); -+ } -+ } -+} -diff --git a/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..adb0e5b4268fa115b814143cf29d9a3688e4bc17 ---- /dev/null -+++ b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java -@@ -0,0 +1,34 @@ -+package io.papermc.paper.entity; -+ -+import com.google.common.base.Joiner; -+import com.google.common.collect.Maps; -+import com.google.common.collect.Sets; -+import net.minecraft.world.entity.EnumMonsterType; -+import org.bukkit.craftbukkit.entity.CraftLivingEntity; -+import org.bukkit.entity.EntityCategory; -+import org.junit.Test; -+ -+import java.lang.reflect.Field; -+import java.util.Map; -+import java.util.Set; -+ -+import static org.junit.Assert.assertTrue; -+ -+public class EntityCategoryTest { -+ -+ @Test -+ public void test() throws IllegalAccessException { -+ -+ Map enumMonsterTypeFieldMap = Maps.newHashMap(); -+ for (Field field : EnumMonsterType.class.getDeclaredFields()) { -+ if (field.getType() == EnumMonsterType.class) { -+ enumMonsterTypeFieldMap.put( (EnumMonsterType) field.get(null), field.getName()); -+ } -+ } -+ -+ for (EntityCategory entityCategory : EntityCategory.values()) { -+ enumMonsterTypeFieldMap.remove(CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); -+ } -+ assertTrue(EnumMonsterType.class.getName() + " instance(s): " + Joiner.on(", ").join(enumMonsterTypeFieldMap.values()) + " do not have bukkit equivalents", enumMonsterTypeFieldMap.size() == 0); -+ } -+} diff --git a/Remapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/Remapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch deleted file mode 100644 index 6c752cc24c..0000000000 --- a/Remapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Tue, 18 May 2021 14:39:44 -0700 -Subject: [PATCH] Add command line option to load extra plugin jars not in the - plugins folder - -ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 63639923f7875d76f569b8c6e958782c6462d906..f1e6d0050092ad51bf233c80b6a51a121e961b07 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -384,8 +384,13 @@ public final class CraftServer implements Server { - - File pluginFolder = (File) console.options.valueOf("plugins"); - -- if (pluginFolder.exists()) { -- Plugin[] plugins = pluginManager.loadPlugins(pluginFolder); -+ // Paper start -+ if (true || pluginFolder.exists()) { -+ if (!pluginFolder.exists()) { -+ pluginFolder.mkdirs(); -+ } -+ Plugin[] plugins = pluginManager.loadPlugins(pluginFolder, this.extraPluginJars()); -+ // Paper end - for (Plugin plugin : plugins) { - try { - String message = String.format("Loading %s", plugin.getDescription().getFullName()); -@@ -400,6 +405,18 @@ public final class CraftServer implements Server { - } - } - -+ // Paper start -+ private List extraPluginJars() { -+ @SuppressWarnings("unchecked") -+ final List jars = (List) this.console.options.valuesOf("add-plugin"); -+ return jars.stream() -+ .filter(File::exists) -+ .filter(File::isFile) -+ .filter(file -> file.getName().endsWith(".jar")) -+ .collect(java.util.stream.Collectors.toList()); -+ } -+ // Paper end -+ - public void enablePlugins(PluginLoadOrder type) { - if (type == PluginLoadOrder.STARTUP) { - helpMap.clear(); -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index bd10345cb90f98b8af1519afd603a5244f3a5ca2..521542999b25b1da448fadb3fe6531e083f93e67 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -153,6 +153,12 @@ public class Main { - .ofType(String.class) - .defaultsTo("Unknown Server") - .describedAs("Name"); -+ -+ acceptsAll(asList("add-plugin", "add-extra-plugin-jar")) -+ .withRequiredArg() -+ .ofType(File.class) -+ .defaultsTo(new File[] {}) -+ .describedAs("Specify paths to extra plugin jars to be loaded in addition to those in the plugins folder. This argument can be specified multiple times, once for each extra plugin jar path."); - // Paper end - } - }; diff --git a/Remapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/Remapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch deleted file mode 100644 index 7f7be61f7b..0000000000 --- a/Remapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 10 May 2021 15:46:57 -0700 -Subject: [PATCH] Fix incorrect status dataconverter for pre 1.13 chunks - -Vanilla was setting non-populated OR non-lit chunks to empty, but -really this is just completely wrong. It should be set to "carved" -at minmum, because pre 1.13 chunks went through 3 distinct stages -of generation: carving, population, and lighting - in this order. -There is no "empty" status, because a chunk was simply carved -or it didn't exist. So mapping any chunk data to empty is simply -invalid. - -If the chunk is terrain populated, then obviously it must be at -minmum "decorated." If the chunk is lit and populated, then it is marked -"mobs_spawned" (which is what Vanilla is doing, and this is the last -stage before moving to full so it looks correct). - -So now here is a table representing the new status conversion: - -Chunk is lit Chunk is populated Vanilla - F F empty - T F empty - F T empty - T T mobs_spawned - -Chunk is lit Chunk is populated Paper - F F carved - T F carved - F T decorated - T T mobs_spawned - -This should fix some problems converting old data, as the -changes here are going to prevent the chunk from being regenerated -incorrectly. - -diff --git a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java -index 16f6aa39385e2d278d4883a32c11ddd119d0d85d..3d262dcf6db0e395d2fa457f7197f24013037ac1 100644 ---- a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java -+++ b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java -@@ -43,13 +43,21 @@ public class ChunkToProtochunkFix extends DataFix { - return dynamic.asStreamOpt().result(); - }); - Dynamic dynamic = (Dynamic) typed1.get(DSL.remainderFinder()); -- boolean flag = dynamic.get("TerrainPopulated").asBoolean(false) && (!dynamic.get("LightPopulated").asNumber().result().isPresent() || dynamic.get("LightPopulated").asBoolean(false)); -- -- dynamic = dynamic.set("Status", dynamic.createString(flag ? "mobs_spawned" : "empty")); -+ // Paper start - fix incorrect status conversion -+ // Vanilla is setting chunks to incorrect status here, they should be using at minimum carved. -+ // for populated chunks, it should be at minimum decorated -+ // and for lit and populated, mobs_spawned is correct (technically mobs_spawned should be for populated, -+ // but if it's not lit then it can't be set above lit) -+ final boolean terrainPopulated = dynamic.get("TerrainPopulated").asBoolean(false); -+ final boolean lightPopulated = dynamic.get("LightPopulated").asBoolean(false) || dynamic.get("LightPopulated").asNumber().result().isPresent(); -+ final String newStatus = !terrainPopulated ? "carved" : (lightPopulated ? "mobs_spawned" : "decorated"); -+ -+ dynamic = dynamic.set("Status", dynamic.createString(newStatus)); - dynamic = dynamic.set("hasLegacyStructureData", dynamic.createBoolean(true)); -- Dynamic dynamic1; -+ // Paper end - fix incorrect status conversion -+ Dynamic dynamic1; // Paper - decompile fix - -- if (flag) { -+ if (true) { // Paper - fix incorrect status conversion - Optional optional1 = dynamic.get("Biomes").asByteBufferOpt().result(); - - if (optional1.isPresent()) { -@@ -70,7 +78,7 @@ public class ChunkToProtochunkFix extends DataFix { - }).collect(Collectors.toList()); - - if (optional.isPresent()) { -- ((Stream) optional.get()).forEach((dynamic2) -> { -+ optional.get().forEach((dynamic2) -> { // Paper - decompile fix - int j = dynamic2.get("x").asInt(0); - int k = dynamic2.get("y").asInt(0); - int l = dynamic2.get("z").asInt(0); -@@ -78,11 +86,11 @@ public class ChunkToProtochunkFix extends DataFix { - - ((ShortList) list.get(k >> 4)).add(short0); - }); -+ Dynamic finalDynamic = dynamic; // Paper - decompile fix - dynamic = dynamic.set("ToBeTicked", dynamic.createList(list.stream().map((shortlist) -> { -- Stream stream = shortlist.stream(); -+ Stream stream = shortlist.stream(); // Paper - decompile fix - -- dynamic.getClass(); -- return dynamic.createList(stream.map(dynamic::createShort)); -+ return finalDynamic.createList(stream.map(finalDynamic::createShort)); - }))); - } - diff --git a/Remapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch b/Remapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch deleted file mode 100644 index 885e2d6ca3..0000000000 --- a/Remapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: SamB440 -Date: Fri, 21 May 2021 00:22:09 +0100 -Subject: [PATCH] Fix MC-148809: Increase structure block data length to 128 - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java -index 4c797dd82bb1989861e350a7e628eb847b58bbd8..4792aafd8d992cd64d05f8bbef5cbf30988949ed 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java -@@ -43,7 +43,7 @@ public class ServerboundSetStructureBlockPacket implements Packet -Date: Thu, 20 May 2021 07:02:22 -0700 -Subject: [PATCH] Fix and optimise world force upgrading - -The WorldUpgrader class was incorrectly modified by -CB. It will store an IChunkLoader instance for all -dimension types in the world, but obviously with how -CB shifts around worlds only one dimension type exists -per world. But this would be OK if CB did this -change correctly. All IChunkLoader instances -will point to the same regionfiles. And all -IChunkLoader instances are going to be read from. - -This problem hasn't really been reported because -it relies on the persistent legacy data to be converted -as well to cause corruption. Why? Because the legacy -data is also shared, it will result in different -outputs from conversion (as once conversion for legacy -persistent data takes place, it is REMOVED - so the next -convert will _not_ have the data). Which means different -sizes on disk. Which means different regionfile sector -allocations. Which means there are 3 different possible -regionfile sector allocations in memory, and none of them -are going to be correct. - -I've fixed this by writing a world upgrader suited to -CB's changes to world folder format. It was brain dead -easy to add threading, so I did. - -diff --git a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f476f21bcfd64d4eb2b690c9100275093c49c9d6 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java -@@ -0,0 +1,200 @@ -+package io.papermc.paper.world; -+ -+import com.mojang.datafixers.DataFixer; -+import net.minecraft.SharedConstants; -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.resources.ResourceKey; -+import net.minecraft.util.worldupdate.WorldUpgrader; -+import net.minecraft.world.level.ChunkPos; -+import net.minecraft.world.level.chunk.storage.ChunkStorage; -+import net.minecraft.world.level.chunk.storage.RegionFileStorage; -+import net.minecraft.world.level.dimension.DimensionType; -+import net.minecraft.world.level.dimension.LevelStem; -+import net.minecraft.world.level.storage.DimensionDataStorage; -+import net.minecraft.world.level.storage.LevelStorageSource; -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; -+import java.io.File; -+import java.io.IOException; -+import java.text.DecimalFormat; -+import java.util.concurrent.ExecutorService; -+import java.util.concurrent.Executors; -+import java.util.concurrent.ThreadFactory; -+import java.util.concurrent.atomic.AtomicInteger; -+import java.util.concurrent.atomic.AtomicLong; -+import java.util.function.Supplier; -+ -+public class ThreadedWorldUpgrader { -+ -+ private static final Logger LOGGER = LogManager.getLogger(); -+ -+ private final ResourceKey dimensionType; -+ private final ResourceKey worldKey; -+ private final String worldName; -+ private final ExecutorService threadPool; -+ private final DataFixer dataFixer; -+ private final boolean removeCaches; -+ -+ public ThreadedWorldUpgrader(final ResourceKey dimensionType, final ResourceKey worldKey, final String worldName, final int threads, -+ final DataFixer dataFixer, final boolean removeCaches) { -+ this.dimensionType = dimensionType; -+ this.worldKey = worldKey; -+ this.worldName = worldName; -+ this.threadPool = Executors.newFixedThreadPool(Math.max(1, threads), new ThreadFactory() { -+ private final AtomicInteger threadCounter = new AtomicInteger(); -+ -+ @Override -+ public Thread newThread(final Runnable run) { -+ final Thread ret = new Thread(run); -+ -+ ret.setName("World upgrader thread for world " + ThreadedWorldUpgrader.this.worldName + " #" + this.threadCounter.getAndIncrement()); -+ ret.setUncaughtExceptionHandler((thread, throwable) -> { -+ LOGGER.fatal("Error upgrading world", throwable); -+ }); -+ -+ return ret; -+ } -+ }); -+ this.dataFixer = dataFixer; -+ this.removeCaches = removeCaches; -+ } -+ -+ public void convert() { -+ final File worldFolder = LevelStorageSource.getFolder(new File(this.worldName), this.dimensionType); -+ final DimensionDataStorage worldPersistentData = new DimensionDataStorage(new File(worldFolder, "data"), this.dataFixer); -+ -+ final File regionFolder = new File(worldFolder, "region"); -+ -+ LOGGER.info("Force upgrading " + this.worldName); -+ LOGGER.info("Counting regionfiles for " + this.worldName); -+ final File[] regionFiles = regionFolder.listFiles((final File dir, final String name) -> { -+ return WorldUpgrader.getRegionfileRegex().matcher(name).matches(); -+ }); -+ if (regionFiles == null) { -+ LOGGER.info("Found no regionfiles to convert for world " + this.worldName); -+ return; -+ } -+ LOGGER.info("Found " + regionFiles.length + " regionfiles to convert"); -+ LOGGER.info("Starting conversion now for world " + this.worldName); -+ -+ final WorldInfo info = new WorldInfo(() -> worldPersistentData, -+ new ChunkStorage(regionFolder, this.dataFixer, false), this.removeCaches, this.worldKey); -+ -+ long expectedChunks = (long)regionFiles.length * (32L * 32L); -+ -+ for (final File regionFile : regionFiles) { -+ final ChunkPos regionPos = RegionFileStorage.getRegionFileCoordinates(regionFile); -+ if (regionPos == null) { -+ expectedChunks -= (32L * 32L); -+ continue; -+ } -+ -+ this.threadPool.execute(new ConvertTask(info, regionPos.x >> 5, regionPos.z >> 5)); -+ } -+ this.threadPool.shutdown(); -+ -+ final DecimalFormat format = new DecimalFormat("#0.00"); -+ -+ final long start = System.nanoTime(); -+ -+ while (!this.threadPool.isTerminated()) { -+ final long current = info.convertedChunks.get(); -+ -+ LOGGER.info("{}% completed ({} / {} chunks)...", format.format((double)current / (double)expectedChunks * 100.0), current, expectedChunks); -+ -+ try { -+ Thread.sleep(1000L); -+ } catch (final InterruptedException ignore) {} -+ } -+ -+ final long end = System.nanoTime(); -+ -+ try { -+ info.loader.close(); -+ } catch (final IOException ex) { -+ LOGGER.fatal("Failed to close chunk loader", ex); -+ } -+ LOGGER.info("Completed conversion. Took {}s, {} out of {} chunks needed to be converted/modified ({}%)", -+ (int)Math.ceil((end - start) * 1.0e-9), info.modifiedChunks.get(), expectedChunks, format.format((double)info.modifiedChunks.get() / (double)expectedChunks * 100.0)); -+ } -+ -+ private static final class WorldInfo { -+ -+ public final Supplier persistentDataSupplier; -+ public final ChunkStorage loader; -+ public final boolean removeCaches; -+ public final ResourceKey worldKey; -+ public final AtomicLong convertedChunks = new AtomicLong(); -+ public final AtomicLong modifiedChunks = new AtomicLong(); -+ -+ private WorldInfo(final Supplier persistentDataSupplier, final ChunkStorage loader, final boolean removeCaches, -+ final ResourceKey worldKey) { -+ this.persistentDataSupplier = persistentDataSupplier; -+ this.loader = loader; -+ this.removeCaches = removeCaches; -+ this.worldKey = worldKey; -+ } -+ } -+ -+ private static final class ConvertTask implements Runnable { -+ -+ private final WorldInfo worldInfo; -+ private final int regionX; -+ private final int regionZ; -+ -+ public ConvertTask(final WorldInfo worldInfo, final int regionX, final int regionZ) { -+ this.worldInfo = worldInfo; -+ this.regionX = regionX; -+ this.regionZ = regionZ; -+ } -+ -+ @Override -+ public void run() { -+ final int regionCX = this.regionX << 5; -+ final int regionCZ = this.regionZ << 5; -+ -+ final Supplier persistentDataSupplier = this.worldInfo.persistentDataSupplier; -+ final ChunkStorage loader = this.worldInfo.loader; -+ final boolean removeCaches = this.worldInfo.removeCaches; -+ final ResourceKey worldKey = this.worldInfo.worldKey; -+ -+ for (int cz = regionCZ; cz < (regionCZ + 32); ++cz) { -+ for (int cx = regionCX; cx < (regionCX + 32); ++cx) { -+ final ChunkPos chunkPos = new ChunkPos(cx, cz); -+ try { -+ // no need to check the coordinate of the chunk, the regionfilecache does that for us -+ -+ CompoundTag chunkNBT = loader.read(chunkPos); -+ -+ if (chunkNBT == null) { -+ continue; -+ } -+ -+ final int versionBefore = ChunkStorage.getVersion(chunkNBT); -+ -+ chunkNBT = loader.getChunkData(worldKey, persistentDataSupplier, chunkNBT, chunkPos, null); -+ -+ boolean modified = versionBefore < SharedConstants.getCurrentVersion().getWorldVersion(); -+ -+ if (removeCaches) { -+ final CompoundTag level = chunkNBT.getCompound("Level"); -+ modified |= level.contains("Heightmaps"); -+ level.remove("Heightmaps"); -+ modified |= level.contains("isLightOn"); -+ level.remove("isLightOn"); -+ } -+ -+ if (modified) { -+ this.worldInfo.modifiedChunks.getAndIncrement(); -+ loader.write(chunkPos, chunkNBT); -+ } -+ } catch (final Exception ex) { -+ LOGGER.error("Error upgrading chunk {}", chunkPos, ex); -+ } finally { -+ this.worldInfo.convertedChunks.getAndIncrement(); -+ } -+ } -+ } -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index ba6c17da4875c3a342da99e354c9f07cc7f17326..d0105061c714af4403b3e14e96e54e17a82c172b 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -15,6 +15,7 @@ import java.nio.file.Paths; - import java.util.Optional; - import java.util.concurrent.CompletableFuture; - import java.util.function.BooleanSupplier; -+import io.papermc.paper.world.ThreadedWorldUpgrader; - import joptsimple.NonOptionArgumentSpec; - import joptsimple.OptionParser; - import joptsimple.OptionSet; -@@ -269,6 +270,15 @@ public class Main { - } - // Paper end - -+ // Paper start - fix and optimise world upgrading -+ public static void convertWorldButItWorks(ResourceKey dimensionType, ResourceKey worldKey, String worldName, -+ DataFixer dataFixer, boolean removeCaches) { -+ int threads = Runtime.getRuntime().availableProcessors() * 3 / 8; -+ final ThreadedWorldUpgrader worldUpgrader = new ThreadedWorldUpgrader(dimensionType, worldKey, worldName, threads, dataFixer, removeCaches); -+ worldUpgrader.convert(); -+ } -+ // Paper end - fix and optimise world upgrading -+ - public static void forceUpgrade(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, boolean eraseCache, BooleanSupplier booleansupplier, ImmutableSet> worlds) { // CraftBukkit - Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit - WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, worlds, eraseCache); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index fd76d776c7003585c9efef44c6d7da0f6c3f574e..9d7cebd703bd0171ca3e95d2985c1a52fdb59712 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -512,13 +512,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -- return true; -- }, worlddata.worldGenSettings().dimensions().entrySet().stream().map((entry1) -> { -- return ResourceKey.create(Registry.DIMENSION_TYPE_REGISTRY, ((ResourceKey) entry1.getKey()).location()); -- }).collect(ImmutableSet.toImmutableSet())); -- } -+ // Paper - move down - - ServerLevelData iworlddataserver = worlddata; - WorldGenSettings generatorsettings = worlddata.worldGenSettings(); -@@ -538,6 +532,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, dimensionKey.location()); - - if (dimensionKey == LevelStem.OVERWORLD) { -diff --git a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java -index 79491c5081dbc0cc479d6bc0329ff9b374559c9b..29c0fe698e91e232bcebfafdd853d222c83d5af8 100644 ---- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java -+++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java -@@ -52,7 +52,7 @@ public class WorldUpgrader { - private volatile int skipped; - private final Object2FloatMap> progressMap = Object2FloatMaps.synchronize(new Object2FloatOpenCustomHashMap(Util.identityStrategy())); // CraftBukkit - private volatile Component status = new TranslatableComponent("optimizeWorld.stage.counting"); -- private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); -+ private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); public static final Pattern getRegionfileRegex() { return REGEX; } // Paper - OBFHELPER - private final DimensionDataStorage overworldDataStorage; - - public WorldUpgrader(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, ImmutableSet> worlds, boolean eraseCache) { // CraftBukkit -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 4523bc1f49e7be248a47eeb599fa7b6550dbb08d..d155d00abf8f423e64e6e6d80ddadbc1cfb58a64 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -181,6 +181,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return typeKey; - } - -+ // Paper start - fix and optimise world upgrading -+ // copied from below -+ public static ResourceKey getDimensionKey(DimensionType manager) { -+ return ((org.bukkit.craftbukkit.CraftServer)org.bukkit.Bukkit.getServer()).getHandle().getServer().registryHolder.dimensionTypes().getResourceKey(manager).orElseThrow(() -> { -+ return new IllegalStateException("Unregistered dimension type: " + manager); -+ }); -+ } -+ // Paper end - fix and optimise world upgrading -+ - protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot - this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -index 1af804c5c6fb2b20ea3f020610763c1d7dcee110..0e38f2f31d167c417b707f00aa68cacaef3d9f6c 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -@@ -109,6 +109,7 @@ public class ChunkStorage implements AutoCloseable { - return nbttagcompound; - } - -+ public static int getVersion(CompoundTag nbttagcompound) { return getVersion(nbttagcompound); } // Paper - OBFHELPER - public static int getVersion(CompoundTag tag) { - return tag.contains("DataVersion", 99) ? tag.getInt("DataVersion") : -1; - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 0498982ac14f20145d68dbf64a46bcaacf5516ef..7a01f2fbe459e36cee5416455a049b25963e257a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -30,6 +30,28 @@ public class RegionFileStorage implements AutoCloseable { // Paper - no final - - - // Paper start -+ public static ChunkPos getRegionFileCoordinates(File file) { -+ String fileName = file.getName(); -+ if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) { -+ return null; -+ } -+ -+ String[] split = fileName.split("\\."); -+ -+ if (split.length != 4) { -+ return null; -+ } -+ -+ try { -+ int x = Integer.parseInt(split[1]); -+ int z = Integer.parseInt(split[2]); -+ -+ return new ChunkPos(x << 5, z << 5); -+ } catch (NumberFormatException ex) { -+ return null; -+ } -+ } -+ - public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { // Paper - synchronize for async io - return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f1e6d0050092ad51bf233c80b6a51a121e961b07..831f187cde88e815c9a859e52ab45fbbe054f83e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1145,14 +1145,7 @@ public final class CraftServer implements Server { - } - worlddata.checkName(name); - worlddata.setModdedInfo(console.getServerModName(), console.getModdedStatus().isPresent()); -- -- if (console.options.has("forceUpgrade")) { -- net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), console.options.has("eraseCache"), () -> { -- return true; -- }, worlddata.worldGenSettings().dimensions().entrySet().stream().map((entry) -> { -- return ResourceKey.create(Registry.DIMENSION_TYPE_REGISTRY, ((ResourceKey) entry.getKey()).location()); -- }).collect(ImmutableSet.toImmutableSet())); -- } -+ // Paper - move down - - long j = BiomeManager.obfuscateSeed(creator.seed()); - List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata)); -@@ -1169,6 +1162,14 @@ public final class CraftServer implements Server { - chunkgenerator = worlddimension.generator(); - } - -+ // Paper start - fix and optimise world upgrading -+ if (console.options.has("forceUpgrade")) { -+ net.minecraft.server.Main.convertWorldButItWorks( -+ actualDimension, net.minecraft.world.level.Level.getDimensionKey(dimensionmanager), worldSession.getLevelId(), DataFixers.getDataFixer(), console.options.has("eraseCache") -+ ); -+ } -+ // Paper end - fix and optimise world upgrading -+ - ResourceKey worldKey; - String levelName = this.getServer().getProperties().levelName; - if (name.equals(levelName + "_nether")) { diff --git a/Remapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch b/Remapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch deleted file mode 100644 index ce42177784..0000000000 --- a/Remapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 14 May 2021 13:42:17 -0500 -Subject: [PATCH] Add Mob#lookAt API - - -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index ea34306858116e5626383af408529091836c2752..5692b497875ba2ee455859bc8a88d7888afd86fc 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -850,14 +850,17 @@ public abstract class Mob extends LivingEntity { - - protected void customServerAiStep() {} - -+ public int getMaxHeadXRot() { return getMaxHeadXRot(); } // Paper - OBFHELPER - public int getMaxHeadXRot() { - return 40; - } - -+ public int getMaxHeadYRot() { return getMaxHeadYRot(); } // Paper - OBFHELPER - public int getMaxHeadYRot() { - return 75; - } - -+ public int getHeadRotSpeed() { return getHeadRotSpeed(); } // Paper - OBFHELPER - public int getHeadRotSpeed() { - return 10; - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java b/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java -index faba4a95883bb0fcfd4f65c3f62bd6f476ded249..3fe159c4bdc3ad3e95354e18e2921305af121725 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java -@@ -20,18 +20,28 @@ public class LookControl { - this.mob = entity; - } - -+ public void lookAt(Vec3 vec3d) { setLookAt(vec3d); } // Paper - OBFHELPER - public void setLookAt(Vec3 direction) { - this.setLookAt(direction.x, direction.y, direction.z); - } - -+ // Paper start -+ public void lookAt(Entity entity) { -+ this.lookAt(entity.getX(), getWantedY(entity), entity.getZ()); -+ } -+ // Paper end -+ -+ public void lookAt(Entity entity, float f, float f1) { setLookAt(entity, f, f1); } // Paper - OBFHELPER - public void setLookAt(Entity entity, float yawSpeed, float pitchSpeed) { - this.setLookAt(entity.getX(), getWantedY(entity), entity.getZ(), yawSpeed, pitchSpeed); - } - -+ public void lookAt(double d0, double d1, double d2) { setLookAt(d0, d1, d2); } // Paper - OBFHELPER - public void setLookAt(double x, double y, double z) { - this.setLookAt(x, y, z, (float) this.mob.getHeadRotSpeed(), (float) this.mob.getMaxHeadXRot()); - } - -+ public void lookAt(double d0, double d1, double d2, float f, float f1) { setLookAt(d0, d1, d2, f, f1); } // Paper - OBFHELPER - public void setLookAt(double x, double y, double z, float yawSpeed, float pitchSpeed) { - this.wantedX = x; - this.wantedY = y; -@@ -103,6 +113,7 @@ public class LookControl { - return from + f4; - } - -+ public static double getWantedY(Entity entity) { return getWantedY(entity); } // Paper - OBFHELPER - private static double getWantedY(Entity entity) { - return entity instanceof LivingEntity ? entity.getEyeY() : (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0D; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index 1e3a0851c75d8067d2699f00bb3f6621d1d739d8..f597cf70779fde265cc45868aba3ae9db898fb6e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -83,5 +83,53 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { - public boolean isInDaylight() { - return getHandle().isInDaylight(); - } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location) { -+ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); -+ getHandle().getLookControl().lookAt(location.getX(), location.getY(), location.getZ()); -+ } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location, float headRotationSpeed, float maxHeadPitch) { -+ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); -+ getHandle().getLookControl().lookAt(location.getX(), location.getY(), location.getZ(), headRotationSpeed, maxHeadPitch); -+ } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity) { -+ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); -+ getHandle().getLookControl().lookAt(((CraftEntity) entity).getHandle()); -+ } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity, float headRotationSpeed, float maxHeadPitch) { -+ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); -+ getHandle().getLookControl().lookAt(((CraftEntity) entity).getHandle(), headRotationSpeed, maxHeadPitch); -+ } -+ -+ @Override -+ public void lookAt(double x, double y, double z) { -+ getHandle().getLookControl().lookAt(x, y, z); -+ } -+ -+ @Override -+ public void lookAt(double x, double y, double z, float headRotationSpeed, float maxHeadPitch) { -+ getHandle().getLookControl().lookAt(x, y, z, headRotationSpeed, maxHeadPitch); -+ } -+ -+ @Override -+ public int getHeadRotationSpeed() { -+ return getHandle().getHeadRotSpeed(); -+ } -+ -+ @Override -+ public int getMaxHeadPitch() { -+ return getHandle().getMaxHeadXRot(); -+ } - // Paper end - } diff --git a/Remapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch b/Remapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch deleted file mode 100644 index 83c74f604e..0000000000 --- a/Remapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Tue, 11 May 2021 17:39:22 -0400 -Subject: [PATCH] Add Unix domain socket support - -For Windows and ARM support, JEP-380 is required: -https://inside.java/2021/02/03/jep380-unix-domain-sockets-channels/ -This will be possible as of the Minecraft 1.17 Java version bump. - -Tested-by: Mariell Hoversholm -Reviewed-by: Mariell Hoversholm - -diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 3ba9c38fc44a8edba9b504112a383249052a0035..cc823a1337bea3ad552687add46706128311f26d 100644 ---- a/src/main/java/net/minecraft/network/Connection.java -+++ b/src/main/java/net/minecraft/network/Connection.java -@@ -564,6 +564,11 @@ public class Connection extends SimpleChannelInboundHandler> { - // Spigot Start - public SocketAddress getRawAddress() - { -+ // Paper start - this can be nullable in the case of a Unix domain socket, so if it is, fake something -+ if (this.channel.remoteAddress() == null) { -+ return new java.net.InetSocketAddress(java.net.InetAddress.getLoopbackAddress(), 0); -+ } -+ // Paper end - return this.channel.remoteAddress(); - } - // Spigot End -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 0198268bc614b190cd84f625a62f6c55247a01c8..2821fa9505d6b5adc8e776219df024713fc1a486 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -222,6 +222,20 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist); - // this.saveData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading - DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode); -+ // Paper start - Unix domain socket support -+ java.net.SocketAddress bindAddress; -+ if (this.getLocalIp().startsWith("unix:")) { -+ if (!io.netty.channel.epoll.Epoll.isAvailable()) { -+ DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!"); -+ DedicatedServer.LOGGER.fatal("You are trying to use a Unix domain socket but you're not on a supported OS."); -+ return false; -+ } else if (!com.destroystokyo.paper.PaperConfig.velocitySupport && !org.spigotmc.SpigotConfig.bungee) { -+ DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!"); -+ DedicatedServer.LOGGER.fatal("Unix domain sockets require IPs to be forwarded from a proxy."); -+ return false; -+ } -+ bindAddress = new io.netty.channel.unix.DomainSocketAddress(this.getLocalIp().substring("unix:".length())); -+ } else { - InetAddress inetaddress = null; - - if (!this.getLocalIp().isEmpty()) { -@@ -231,12 +245,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - if (this.getPort() < 0) { - this.setPort(dedicatedserverproperties.serverPort); - } -+ bindAddress = new java.net.InetSocketAddress(inetaddress, this.getPort()); -+ } -+ // Paper end - - this.initializeKeyPair(); - DedicatedServer.LOGGER.info("Starting Minecraft server on {}:{}", this.getLocalIp().isEmpty() ? "*" : this.getLocalIp(), this.getPort()); - - try { -- this.getConnection().startTcpServerListener(inetaddress, this.getPort()); -+ this.getConnection().bind(bindAddress); // Paper - Unix domain socket support - } catch (IOException ioexception) { - DedicatedServer.LOGGER.warn("**** FAILED TO BIND TO PORT!"); - DedicatedServer.LOGGER.warn("The exception was: {}", ioexception.toString()); -diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -index bcc19d0a4b6c5f683dc416e27a13705b57213d21..67a17ced9460bc83a6f564b38fdb43b1a7f1b8a0 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -@@ -70,7 +70,12 @@ public class ServerConnectionListener { - this.running = true; - } - -+ // Paper start - public void startTcpServerListener(@Nullable InetAddress address, int port) throws IOException { -+ bind(new java.net.InetSocketAddress(address, port)); -+ } -+ public void bind(java.net.SocketAddress address) throws IOException { -+ // Paper end - List list = this.channels; - - synchronized (this.channels) { -@@ -78,7 +83,11 @@ public class ServerConnectionListener { - LazyLoadedValue lazyinitvar; - - if (Epoll.isAvailable() && this.server.isEpollEnabled()) { -+ if (address instanceof io.netty.channel.unix.DomainSocketAddress) { -+ oclass = io.netty.channel.epoll.EpollServerDomainSocketChannel.class; -+ } else { - oclass = EpollServerSocketChannel.class; -+ } - lazyinitvar = ServerConnectionListener.SERVER_EPOLL_EVENT_GROUP; - ServerConnectionListener.LOGGER.info("Using epoll channel type"); - } else { -@@ -106,7 +115,7 @@ public class ServerConnectionListener { - ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); - io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper - } -- }).group((EventLoopGroup) lazyinitvar.get()).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit -+ }).group((EventLoopGroup) lazyinitvar.get()).localAddress(address)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit // Paper - } - } - -diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -index 4e055a41de3ee410682cc05a3b883ac8babeb290..e1fbb207d6921516c7423e9a3cded8efb5676d49 100644 ---- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -@@ -44,6 +44,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - this.connection.setProtocol(ConnectionProtocol.LOGIN); - // CraftBukkit start - Connection throttle - try { -+ if (!(this.connection.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress)) { // Paper - the connection throttle is useless when you have a Unix domain socket - long currentTime = System.currentTimeMillis(); - long connectionThrottle = this.server.server.getConnectionThrottle(); - InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress(); -@@ -72,6 +73,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - } - } - } -+ } // Paper - add closing bracket for if check above - } catch (Throwable t) { - org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); - } -@@ -120,8 +122,11 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! - String[] split = packet.hostName.split("\00"); - if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper -+ // Paper start - Unix domain socket support -+ java.net.SocketAddress socketAddress = connection.getRemoteAddress(); - packet.hostName = split[0]; -- connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort()); -+ connection.address = new java.net.InetSocketAddress(split[1], socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); -+ // Paper end - connection.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); - } else - { diff --git a/Remapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch b/Remapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch deleted file mode 100644 index 6380d78daa..0000000000 --- a/Remapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 8 May 2021 18:02:36 -0700 -Subject: [PATCH] Add EntityInsideBlockEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java -index ad37261e716b15d62fc2083d137cdac818308cdd..58519e224a5005bf6468b99196acb7209b2e1398 100644 ---- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java -@@ -48,6 +48,7 @@ public abstract class BaseFireBlock extends Block { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (!entity.fireImmune()) { - entity.setRemainingFireTicks(entity.getRemainingFireTicks() + 1); - if (entity.getRemainingFireTicks() == 0) { -diff --git a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java -index 6acb24f96591d555e550d399d2ed38036a0220fe..8d8fd646c9527852bfe9a2d3cd0a6bf1bfa9e4a2 100644 ---- a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java -@@ -65,6 +65,7 @@ public abstract class BasePressurePlateBlock extends Block { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (!world.isClientSide) { - int i = this.getSignalForState(state); - -diff --git a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java -index f741980d0e1759e3fefe322b654760dab35200d6..faa1070aaf3fcc40bf7e36a0dda8ec7879c89dd6 100644 ---- a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java -@@ -33,6 +33,7 @@ public class BubbleColumnBlock extends Block implements BucketPickup { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - BlockState iblockdata1 = world.getBlockState(pos.above()); - - if (iblockdata1.isAir()) { -diff --git a/src/main/java/net/minecraft/world/level/block/ButtonBlock.java b/src/main/java/net/minecraft/world/level/block/ButtonBlock.java -index 52ca5dad75674b81b997f8a1cf3f5d52bf4313c1..2c4c5fc6d45225cc9f7f1c2038bd4d0ae20c9daa 100644 ---- a/src/main/java/net/minecraft/world/level/block/ButtonBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/ButtonBlock.java -@@ -179,6 +179,7 @@ public abstract class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (!world.isClientSide && this.sensitive && !(Boolean) state.getValue(ButtonBlock.POWERED)) { - this.checkPressed(state, world, pos); - } -diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java -index de61393e3f702554817d81ff10693ec3fb63d492..28b083a8220856723b6169b5b13677b965a4dab6 100644 ---- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java -@@ -115,6 +115,7 @@ public class CactusBlock extends Block { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - CraftEventFactory.blockDamage = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit - entity.hurt(DamageSource.CACTUS, 1.0F); - CraftEventFactory.blockDamage = null; // CraftBukkit -diff --git a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java -index 87f106ad9139157af69a0ae1602c32ed372a04be..b0c6ac74daea347f4acb5da95e6b0cb013827509 100644 ---- a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java -@@ -88,6 +88,7 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (!entity.fireImmune() && (Boolean) state.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { - entity.hurt(DamageSource.IN_FIRE, (float) this.fireDamage); - } -diff --git a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java -index 941061b50f7909278e962fb2aa080bb630862aa1..7d23adaa833c9c45708705294969fe268153b927 100644 ---- a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java -@@ -58,6 +58,7 @@ public class CauldronBlock extends Block { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - int i = (Integer) state.getValue(CauldronBlock.LEVEL); - float f = (float) pos.getY() + (6.0F + (float) (3 * i)) / 16.0F; - -diff --git a/src/main/java/net/minecraft/world/level/block/CropBlock.java b/src/main/java/net/minecraft/world/level/block/CropBlock.java -index 4cd6f18e0a2ee8d0495b3c822b227e212a13b11f..8368a5911690a9abb26c0f381bda7a0633197548 100644 ---- a/src/main/java/net/minecraft/world/level/block/CropBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/CropBlock.java -@@ -159,6 +159,7 @@ public class CropBlock extends BushBlock implements BonemealableBlock { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (entity instanceof Ravager && !CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)).isCancelled()) { // CraftBukkit - world.destroyBlock(pos, true, entity); - } -diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java -index 1854809e045300e84a713dc7c3a8264f53ec6c0f..d970fe7137f7dd37221b54e4025b98d15b950489 100644 ---- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java -@@ -44,6 +44,7 @@ public class DetectorRailBlock extends BaseRailBlock { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (!world.isClientSide) { - if (!(Boolean) state.getValue(DetectorRailBlock.POWERED)) { - this.checkPressed(world, pos, state); -diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -index a6d793478be8e2aab1f72b68a6a96c86642ad1fc..2231680140d0e3c4c10b6722fd13fe0ee55ce294 100644 ---- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -@@ -41,6 +41,7 @@ public class EndPortalBlock extends BaseEntityBlock { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (world instanceof ServerLevel && !entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-pos.getX()), (double) (-pos.getY()), (double) (-pos.getZ()))), state.getShape(world, pos), BooleanOp.AND)) { - ResourceKey resourcekey = world.getTypeKey() == DimensionType.END_LOCATION ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends - ServerLevel worldserver = ((ServerLevel) world).getServer().getLevel(resourcekey); -diff --git a/src/main/java/net/minecraft/world/level/block/HoneyBlock.java b/src/main/java/net/minecraft/world/level/block/HoneyBlock.java -index 7d0206dc5ac46220970adad51863028840b4a9ad..ef74852a1677a4ec80149aa7eafca910fac5ee91 100644 ---- a/src/main/java/net/minecraft/world/level/block/HoneyBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/HoneyBlock.java -@@ -49,6 +49,7 @@ public class HoneyBlock extends HalfTransparentBlock { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (this.isSlidingDown(pos, entity)) { - this.maybeDoSlideAchievement(entity, pos); - this.doSlideMovement(entity); -diff --git a/src/main/java/net/minecraft/world/level/block/HopperBlock.java b/src/main/java/net/minecraft/world/level/block/HopperBlock.java -index 1f50c2b4bebeb6a224eb0ac552d6ea693f7831a6..40b1bba69ae96e4cd652261e3f97850e2e7c51a3 100644 ---- a/src/main/java/net/minecraft/world/level/block/HopperBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/HopperBlock.java -@@ -197,6 +197,7 @@ public class HopperBlock extends BaseEntityBlock { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - BlockEntity tileentity = world.getBlockEntity(pos); - - if (tileentity instanceof HopperBlockEntity) { -diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -index ae58929886921d0714bf811de92f99dc0dc120dc..53e7570cc2538e73f1cfe3d28ffc491f61cac372 100644 ---- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -@@ -81,6 +81,7 @@ public class NetherPortalBlock extends Block { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (!entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions()) { - // CraftBukkit start - Entity in portal - EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); -diff --git a/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java b/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java -index 09122e2031e9ddfae4544911f8c25b937b03933f..6b5e8654ddd2c268627d0244b01dadeaeb4a7de4 100644 ---- a/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java -@@ -66,6 +66,7 @@ public class SweetBerryBushBlock extends BushBlock implements BonemealableBlock - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (entity instanceof LivingEntity && entity.getType() != EntityType.FOX && entity.getType() != EntityType.BEE) { - entity.makeStuckInBlock(state, new Vec3(0.800000011920929D, 0.75D, 0.800000011920929D)); - if (!world.isClientSide && (Integer) state.getValue(SweetBerryBushBlock.AGE) > 0 && (entity.xOld != entity.getX() || entity.zOld != entity.getZ())) { -diff --git a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java -index eaee409bc8fbf8c5541afd10d24975535556a7f6..a488a2a589126df617564d9278eb0496915b6f88 100644 ---- a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java -@@ -118,6 +118,7 @@ public class TripWireBlock extends Block { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (!world.isClientSide) { - if (!(Boolean) state.getValue(TripWireBlock.POWERED)) { - this.checkPressed(world, pos); -diff --git a/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java b/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java -index 2b2a28d0383ccc8c0e7debd90331570b02b5e65f..bd4295f8d24ca9fd8c3af31abcd13da24db1c5d5 100644 ---- a/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java -@@ -25,6 +25,7 @@ public class WaterlilyBlock extends BushBlock { - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { - super.entityInside(state, world, pos, entity); -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (world instanceof ServerLevel && entity instanceof Boat && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { // CraftBukkit - world.destroyBlock(new BlockPos(pos), true, entity); - } -diff --git a/src/main/java/net/minecraft/world/level/block/WebBlock.java b/src/main/java/net/minecraft/world/level/block/WebBlock.java -index c368531420d464414de3661e1624e2a284976ab6..fc1c2e057e8b63048c919b5cbcc0a0e897f1dd01 100644 ---- a/src/main/java/net/minecraft/world/level/block/WebBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/WebBlock.java -@@ -15,6 +15,7 @@ public class WebBlock extends Block { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - entity.makeStuckInBlock(state, new Vec3(0.25D, 0.05000000074505806D, 0.25D)); - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java b/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java -index c1648c28c761cdf31089d434f9cb896ddef41521..5cb4e1ec7ce3087163d2ecf26d043894310768d1 100644 ---- a/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java -@@ -26,6 +26,7 @@ public class WitherRoseBlock extends FlowerBlock { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if (!world.isClientSide && world.getDifficulty() != Difficulty.PEACEFUL) { - if (entity instanceof LivingEntity) { - LivingEntity entityliving = (LivingEntity) entity; diff --git a/Remapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch b/Remapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch deleted file mode 100644 index ce7b672b14..0000000000 --- a/Remapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 8 May 2021 15:01:54 -0700 -Subject: [PATCH] Attributes API for item defaults - - -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 42085d3f4ae5c6ceecaffde79fb3187712a2af00..3043378c3addf959e0ccf323c1cde8b300b5f237 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -274,6 +274,7 @@ public class Item implements ItemLike { - return false; - } - -+ public Multimap getAttributesForSlot(EquipmentSlot enumItemSlot) { return getDefaultAttributeModifiers(enumItemSlot); } // Paper - OBFHELPER - public Multimap getDefaultAttributeModifiers(EquipmentSlot slot) { - return ImmutableMultimap.of(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 34eed57c7ed884e0d634ca403e38d25c95b6a038..824111fc74bade75ce06b1f0b57498006d0a66cd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -493,6 +493,19 @@ public final class CraftMagicNumbers implements UnsafeValues { - return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); - } - -+ @Override -+ public com.google.common.collect.Multimap getItemAttributes(org.bukkit.Material material, org.bukkit.inventory.EquipmentSlot equipmentSlot) { -+ Item item = this.getItem(material); -+ if (item == null) { -+ throw new IllegalArgumentException(material + " is not an item and therefore does not have attributes"); -+ } -+ com.google.common.collect.ImmutableMultimap.Builder attributeMapBuilder = com.google.common.collect.ImmutableMultimap.builder(); -+ item.getAttributesForSlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(equipmentSlot)).forEach((attributeBase, attributeModifier) -> { -+ attributeMapBuilder.put(org.bukkit.Registry.ATTRIBUTE.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.Registry.ATTRIBUTE.getKey(attributeBase))), org.bukkit.craftbukkit.attribute.CraftAttributeInstance.convert(attributeModifier)); -+ }); -+ return attributeMapBuilder.build(); -+ } -+ - @Override - public int getProtocolVersion() { - return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion(); diff --git a/Remapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/Remapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch deleted file mode 100644 index 339837dc3e..0000000000 --- a/Remapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alexander -Date: Thu, 6 May 2021 13:01:25 +0100 -Subject: [PATCH] Have CraftMerchantCustom emit PlayerPurchaseEvent - - -diff --git a/src/main/java/net/minecraft/world/item/trading/Merchant.java b/src/main/java/net/minecraft/world/item/trading/Merchant.java -index 8298e667aa3a17d987bbc4cc2b63600af48beabc..334df355470bff98db63396b33c8db6a0abcc61a 100644 ---- a/src/main/java/net/minecraft/world/item/trading/Merchant.java -+++ b/src/main/java/net/minecraft/world/item/trading/Merchant.java -@@ -19,7 +19,7 @@ public interface Merchant { - - MerchantOffers getOffers(); - -- void notifyTrade(MerchantOffer offer); -+ void notifyTrade(MerchantOffer offer); default void handlePurchase(MerchantOffer merchantRecipe) { notifyTrade(merchantRecipe); } // Paper - OBFHELPER - - void notifyTradeUpdated(ItemStack stack); - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -index 306c6483708ae1b41bd16f122d36beec1916a776..d52192545c39734be3c97c7978652a54d7b9f029 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -@@ -81,6 +81,35 @@ public class CraftMerchantCustom extends CraftMerchant { - - @Override - public void notifyTrade(MerchantOffer offer) { -+ // Paper start -+ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerAbstract#b(MerchantRecipe)} */ -+ if (getTradingPlayer() instanceof net.minecraft.server.level.ServerPlayer) { -+ final net.minecraft.server.level.ServerPlayer trader = (net.minecraft.server.level.ServerPlayer) getTradingPlayer(); -+ final io.papermc.paper.event.player.PlayerPurchaseEvent event = new io.papermc.paper.event.player.PlayerPurchaseEvent( -+ trader.getBukkitEntity(), -+ offer.asBukkit(), -+ false, // reward xp? -+ true); // should increase uses? -+ event.callEvent(); -+ if (event.isCancelled()) { -+ return; -+ } -+ final org.bukkit.inventory.MerchantRecipe eventTrade = event.getTrade(); -+ if (event.willIncreaseTradeUses()) { -+ eventTrade.setUses(eventTrade.getUses() + 1); -+ } -+ if (event.isRewardingExp() && eventTrade.hasExperienceReward()) { -+ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerTrader#b(MerchantRecipe)} */ -+ final int xp = 3 + net.minecraft.world.entity.Entity.SHARED_RANDOM.nextInt(4); -+ final Level world = trader.getCommandSenderWorld(); -+ world.addFreshEntity(new net.minecraft.world.entity.ExperienceOrb( -+ world, trader.getX(), trader.getY() + 0.5d, trader.getZ(), xp, -+ org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, trader, null)); -+ } -+ return; -+ } -+ // Paper end -+ - // increase recipe's uses - offer.increaseUses(); - } diff --git a/Remapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch b/Remapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch deleted file mode 100644 index fb889a4693..0000000000 --- a/Remapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Dec 2020 18:23:26 -0800 -Subject: [PATCH] Add cause to Weather/ThunderChangeEvents - - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 511e6a941d441c55a4b38660f0f7f8c47fa689dd..85e62e3c52950a517c4dbae739d21d879cb467a4 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -413,8 +413,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.worldDataServer.setClearWeatherTime(clearDuration); - this.worldDataServer.setRainTime(rainDuration); - this.worldDataServer.setThunderTime(rainDuration); -- this.worldDataServer.setRaining(raining); -- this.worldDataServer.setThundering(thundering); -+ this.worldDataServer.setRaining(raining, org.bukkit.event.weather.WeatherChangeEvent.Cause.COMMAND); // Paper -+ this.worldDataServer.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.COMMAND); // Paper - } - - public Biome getBiomeBySeed(int i, int j, int k) { return getUncachedNoiseBiome(i, j, k); } // Paper - OBFHELPER -@@ -476,8 +476,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.worldDataServer.setThunderTime(j); - this.worldDataServer.setRainTime(k); - this.worldDataServer.setClearWeatherTime(i); -- this.worldDataServer.setThundering(flag1); -- this.worldDataServer.setRaining(flag2); -+ this.worldDataServer.setThundering(flag1, org.bukkit.event.weather.ThunderChangeEvent.Cause.NATURAL); // Paper -+ this.worldDataServer.setRaining(flag2, org.bukkit.event.weather.WeatherChangeEvent.Cause.NATURAL); // Paper - } - - this.oThunderLevel = this.thunderLevel; -@@ -879,14 +879,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - - private void stopWeather() { - // CraftBukkit start -- this.worldDataServer.setRaining(false); -+ this.worldDataServer.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - when passing the night - // If we stop due to everyone sleeping we should reset the weather duration to some other random value. - // Not that everyone ever manages to get the whole server to sleep at the same time.... - if (!this.worldDataServer.isRaining()) { - this.worldDataServer.setRainTime(0); - } - // CraftBukkit end -- this.worldDataServer.setThundering(false); -+ this.worldDataServer.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - when passing the night - // CraftBukkit start - // If we stop due to everyone sleeping we should reset the weather duration to some other random value. - // Not that everyone ever manages to get the whole server to sleep at the same time.... -diff --git a/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java b/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java -index 83f2fdfa1ac2435f5199b5c33bfc409d2e94f4ed..e902534fd64f72e46feefa04f526e0dacd612627 100644 ---- a/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java -+++ b/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java -@@ -325,21 +325,26 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { - - @Override - public void setThundering(boolean thundering) { -+ // Paper start -+ this.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.UNKNOWN); -+ } -+ public void setThundering(boolean flag, org.bukkit.event.weather.ThunderChangeEvent.Cause cause) { -+ // Paper end - // CraftBukkit start -- if (this.thundering == thundering) { -+ if (this.thundering == flag) { - return; - } - - org.bukkit.World world = Bukkit.getWorld(getLevelName()); - if (world != null) { -- ThunderChangeEvent thunder = new ThunderChangeEvent(world, thundering); -+ ThunderChangeEvent thunder = new ThunderChangeEvent(world, flag, cause); // Paper - Bukkit.getServer().getPluginManager().callEvent(thunder); - if (thunder.isCancelled()) { - return; - } - } - // CraftBukkit end -- this.thundering = thundering; -+ this.thundering = flag; - } - - @Override -@@ -359,21 +364,27 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { - - @Override - public void setRaining(boolean raining) { -+ // Paper start -+ this.setRaining(raining, org.bukkit.event.weather.WeatherChangeEvent.Cause.UNKNOWN); -+ } -+ -+ public void setStorm(boolean flag, org.bukkit.event.weather.WeatherChangeEvent.Cause cause) { -+ // Paper end - // CraftBukkit start -- if (this.raining == raining) { -+ if (this.raining == flag) { - return; - } - - org.bukkit.World world = Bukkit.getWorld(getLevelName()); - if (world != null) { -- WeatherChangeEvent weather = new WeatherChangeEvent(world, raining); -+ WeatherChangeEvent weather = new WeatherChangeEvent(world, flag, cause); // Paper - Bukkit.getServer().getPluginManager().callEvent(weather); - if (weather.isCancelled()) { - return; - } - } - // CraftBukkit end -- this.raining = raining; -+ this.raining = flag; - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index a1fa2d5e00bd125abd38a00e0bc3936f2fb8186f..1c9321cef1a05c5e8a22dd52bc63a5103eaf7311 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1452,7 +1452,7 @@ public class CraftWorld implements World { - - @Override - public void setStorm(boolean hasStorm) { -- world.levelData.setRaining(hasStorm); -+ world.worldDataServer.setRaining(hasStorm, org.bukkit.event.weather.WeatherChangeEvent.Cause.PLUGIN); // Paper - setWeatherDuration(0); // Reset weather duration (legacy behaviour) - setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) - } -@@ -1474,7 +1474,7 @@ public class CraftWorld implements World { - - @Override - public void setThundering(boolean thundering) { -- world.worldDataServer.setThundering(thundering); -+ world.worldDataServer.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.PLUGIN); // Paper - setThunderDuration(0); // Reset weather duration (legacy behaviour) - setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) - } diff --git a/Remapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch b/Remapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch deleted file mode 100644 index 5a3dcda899..0000000000 --- a/Remapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: LemonCaramel -Date: Sun, 23 May 2021 17:49:51 +0900 -Subject: [PATCH] More Lidded Block API - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java -index 8f0477d9620ef71e10855bbca07f9b6984d5d794..70ca456fad052ca6eeaf8c4242c78d15d81084a5 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java -@@ -10,8 +10,9 @@ public class EnderChestBlockEntity extends BlockEntity { // Paper - Remove ITick - - public float openness; - public float oOpenness; -- public int openCount; -+ public int openCount; public int getViewerCount() { return openCount; } // Paper - OBFHELPER - private int tickInterval; -+ public boolean opened; // Paper - More Lidded Block API - - public EnderChestBlockEntity() { - super(BlockEntityType.ENDER_CHEST); -@@ -106,12 +107,14 @@ public class EnderChestBlockEntity extends BlockEntity { // Paper - Remove ITick - - public void startOpen() { - ++this.openCount; -+ if (opened) return; // Paper - More Lidded Block API - this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); - doOpenLogic(); // Paper - } - - public void stopOpen() { - --this.openCount; -+ if (opened) return; // Paper - More Lidded Block API - this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); - doCloseLogic(); // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java -index a0eadcbcb2575eb18f7b4951ae9eadfbc2e8af6f..fc4397a48425a23d64e0a679ace9e58fbf9b770b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java -@@ -59,4 +59,11 @@ public class CraftBarrel extends CraftLootable implements Bar - } - getTileEntity().opened = false; - } -+ -+ // Paper start - More Lidded Block API -+ @Override -+ public boolean isOpen() { -+ return getTileEntity().opened; -+ } -+ // Paper end - More Lidded Block API - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -index a821df3e13e2ddc479dc5f55540671f43563cdac..9d7af8717085ba5c170a998aa863686d72840a40 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -@@ -78,4 +78,11 @@ public class CraftChest extends CraftLootable implements Chest - } - getTileEntity().opened = false; - } -+ -+ // Paper start - More Lidded Block API -+ @Override -+ public boolean isOpen() { -+ return getTileEntity().opened; -+ } -+ // Paper end - More Lidded Block API - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java -index 25add8bee6ea35beeb205dd828759304346e4f48..fabcb2b8dc950fd074d65fed95d6b371dcfbf842 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java -@@ -14,4 +14,33 @@ public class CraftEnderChest extends CraftBlockEntityState implem - if (getTileEntity().opened) { - Level world = getTileEntity().getLevel(); - world.blockEvent(getPosition(), getTileEntity().getBlockState().getBlock(), 1, 0); -- world.playSound(null, getPosition(), SoundEvents.SHULKER_BOX_OPEN, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); -+ world.playSound(null, getPosition(), SoundEvents.SHULKER_BOX_CLOSE, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); // Paper - More Lidded Block API (Wrong sound) - } - getTileEntity().opened = false; - } -+ -+ // Paper start - More Lidded Block API -+ @Override -+ public boolean isOpen() { -+ return getTileEntity().opened; -+ } -+ // Paper end - More Lidded Block API - } diff --git a/Remapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch b/Remapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch deleted file mode 100644 index 82c7b23bb7..0000000000 --- a/Remapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch +++ /dev/null @@ -1,393 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 20:30:45 -0700 -Subject: [PATCH] Add PlayerKickEvent causes - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 9d7cebd703bd0171ca3e95d2985c1a52fdb59712..9e3b8c7478d97bf65a875807a268d1c98389c1f8 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2041,7 +2041,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 80) { - ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); -- this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_PLAYER); // Paper - use configurable kick message & kick event cause - return; - } - } else { -@@ -346,7 +346,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) { - if (++this.aboveGroundVehicleTickCount > 80) { - ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); -- this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_VEHICLE); // Paper - use configurable kick message & kick event cause - return; - } - } else { -@@ -368,7 +368,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - if (this.isPendingPing()) { - if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected - ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info -- this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0])); -+ this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause - } - } else { - if (elapsedTime >= 15000L) { // 15 seconds -@@ -398,7 +398,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) (this.server.getPlayerIdleTimeout() * 1000 * 60)) { - this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 -- this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling")); -+ this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause - } - - } -@@ -423,14 +423,22 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - public void disconnect(String s) { - // Paper start -- this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); -+ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); -+ } -+ -+ public void disconnect(String s, PlayerKickEvent.Cause cause) { -+ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s), cause); - } - - public void disconnect(final Component reason) { -- this.disconnect(PaperAdventure.asAdventure(reason)); -+ this.disconnect(PaperAdventure.asAdventure(reason), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); -+ } -+ -+ public void disconnect(final Component reason, PlayerKickEvent.Cause cause) { -+ this.disconnect(PaperAdventure.asAdventure(reason), cause); - } - -- public void disconnect(net.kyori.adventure.text.Component reason) { -+ public void disconnect(net.kyori.adventure.text.Component reason, org.bukkit.event.player.PlayerKickEvent.Cause cause) { - // Paper end - // CraftBukkit start - fire PlayerKickEvent - if (this.processedDisconnect) { -@@ -438,7 +446,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } - net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure - -- PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure -+ PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), reason, leaveMessage, cause); // Paper - Adventure & kick event reason - - if (this.craftServer.getServer().isRunning()) { - this.craftServer.getPluginManager().callEvent(event); -@@ -516,7 +524,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - public void handleMoveVehicle(ServerboundMoveVehiclePacket packet) { - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); - if (containsInvalidValues(packet)) { -- this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_vehicle_movement")); -+ this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_vehicle_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_VEHICLE_MOVEMENT); // Paper - kick event cause - } else { - Entity entity = this.player.getRootVehicle(); - -@@ -750,13 +758,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async - // CraftBukkit start - if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable -- server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper -+ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause - return; - } - // Paper start - String str = packet.getCommand(); int index = -1; - if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { -- server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper -+ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause - return; - } - // Paper end -@@ -904,7 +912,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // Paper start - validate pick item position - if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.inventory.items.size())) { - ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); -- this.disconnect("Invalid hotbar selection (Hacking?)"); -+ this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause - return; - } - this.player.inventory.pickSlot(packet.getSlot()); // Paper - Diff above if changed -@@ -1058,7 +1066,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - ListTag pageList = testStack.getTag().getList("pages", 8); - if (pageList.size() > 100) { - ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with too many pages"); -- server.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause - return; - } - long byteTotal = 0; -@@ -1070,7 +1078,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; - if (byteLength > 256 * 4) { - ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!"); -- server.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause - return; - } - byteTotal += byteLength; -@@ -1093,14 +1101,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - if (byteTotal > byteAllowed) { - ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); -- server.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause - return; - } - } - // Paper end - // CraftBukkit start - if (this.lastBookTick + 20 > MinecraftServer.currentTick) { -- this.disconnect("Book edited too quickly!"); -+ this.disconnect("Book edited too quickly!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause - return; - } - this.lastBookTick = MinecraftServer.currentTick; -@@ -1212,7 +1220,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - public void handleMovePlayer(ServerboundMovePlayerPacket packet) { - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); - if (containsInvalidValues(packet)) { -- this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement")); -+ this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause - } else { - ServerLevel worldserver = this.player.getLevel(); - -@@ -1611,7 +1619,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - this.dropCount++; - if (this.dropCount >= 20) { - LOGGER.warn(this.player.getScoreboardName() + " dropped their items too quickly!"); -- this.disconnect("You dropped your items too quickly (Hacking?)"); -+ this.disconnect("You dropped your items too quickly (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause - return; - } - } -@@ -1924,7 +1932,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - this.player.resetLastActionTime(); - } else { - ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); -- this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit -+ this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // CraftBukkit // Paper - kick event cause - } - } - -@@ -1961,7 +1969,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - Waitable waitable = new Waitable() { - @Override - protected Object evaluate() { -- ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters")); -+ ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause - return null; - } - }; -@@ -1976,7 +1984,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - throw new RuntimeException(e); - } - } else { -- this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters")); -+ this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause - } - // CraftBukkit end - return; -@@ -2030,7 +2038,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - Waitable waitable = new Waitable() { - @Override - protected Object evaluate() { -- ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("disconnect.spam")); -+ ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause - return null; - } - }; -@@ -2045,7 +2053,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - throw new RuntimeException(e); - } - } else { -- this.disconnect(new TranslatableComponent("disconnect.spam")); -+ this.disconnect(new TranslatableComponent("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause - } - // CraftBukkit end - } -@@ -2318,7 +2326,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // Spigot Start - if ( entity == player && !player.isSpectator() ) - { -- disconnect( "Cannot interact with self!" ); -+ disconnect( "Cannot interact with self!", org.bukkit.event.player.PlayerKickEvent.Cause.SELF_INTERACTION ); // Paper - kick event cause - return; - } - // Spigot End -@@ -2395,7 +2403,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // CraftBukkit end - } else if (packet.getAction() == ServerboundInteractPacket.Action.ATTACK) { - if (entity instanceof ItemEntity || entity instanceof ExperienceOrb || entity instanceof AbstractArrow || (entity == this.player && !player.isSpectator())) { // CraftBukkit -- this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked")); -+ this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_ENTITY_ATTACKED); // Paper - kick event cause - ServerGamePacketListenerImpl.LOGGER.warn("Player {} tried to attack an invalid entity", this.player.getName().getString()); - return; - } -@@ -2800,7 +2808,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // Paper start - if (!Bukkit.isPrimaryThread()) { - if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { -- server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper -+ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause - return; - } - } -@@ -2999,7 +3007,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } else if (!this.isSingleplayerOwner()) { - // Paper start - This needs to be handled on the main thread for plugins - server.scheduleOnMain(() -> { -- this.disconnect(new TranslatableComponent("disconnect.timeout")); -+ this.disconnect(new TranslatableComponent("disconnect.timeout"), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause - }); - // Paper end - } -@@ -3045,7 +3053,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } - } catch (Exception ex) { - ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex); -- this.disconnect("Invalid payload REGISTER!"); -+ this.disconnect("Invalid payload REGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause - } - } else if (packet.identifier.equals(CUSTOM_UNREGISTER)) { - try { -@@ -3055,7 +3063,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } - } catch (Exception ex) { - ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t unregister custom payload", ex); -- this.disconnect("Invalid payload UNREGISTER!"); -+ this.disconnect("Invalid payload UNREGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause - } - } else { - try { -@@ -3074,7 +3082,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - craftServer.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packet.identifier.toString(), data); - } catch (Exception ex) { - ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); -- this.disconnect("Invalid custom payload!"); -+ this.disconnect("Invalid custom payload!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause - } - } - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 6011b43ae8a858f88b8fcf6dc0bf147024a4742c..9e138bf9f9ee4efee462271d1a69a2126aa94946 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -716,7 +716,7 @@ public abstract class PlayerList { - while (iterator.hasNext()) { - entityplayer = (ServerPlayer) iterator.next(); - save(entityplayer); // CraftBukkit - Force the player's inventory to be saved -- entityplayer.connection.disconnect(new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0])); -+ entityplayer.connection.disconnect(new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause - } - - // Instead of kicking then returning, we need to store the kick reason -@@ -1385,8 +1385,8 @@ public abstract class PlayerList { - public void shutdown(boolean isRestarting) { - // CraftBukkit start - disconnect safely - for (ServerPlayer player : this.players) { -- if (isRestarting) player.connection.disconnect(org.spigotmc.SpigotConfig.restartMessage); else // Paper -- player.connection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure -+ if (isRestarting) player.connection.disconnect(org.spigotmc.SpigotConfig.restartMessage, org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); else // Paper - kick event cause (cause is never used here) -+ player.connection.disconnect(this.server.server.shutdownMessage(), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); // CraftBukkit - add custom shutdown message // Paper - Adventure & KickEventCause (cause is never used here) - } - // CraftBukkit end - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 3dbe94d9b9647f5cc1e27335b36042e50c652cea..97aec6370a8a24a13ae04443d03f250f8938b2e0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -495,16 +495,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - org.spigotmc.AsyncCatcher.catchOp("player kick"); // Spigot - if (getHandle().connection == null) return; - -- getHandle().connection.disconnect(message == null ? "" : message); -+ getHandle().connection.disconnect(message == null ? "" : message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause - } - - // Paper start - @Override - public void kick(final net.kyori.adventure.text.Component message) { -+ kick(message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); -+ } -+ -+ @Override -+ public void kick(net.kyori.adventure.text.Component message, org.bukkit.event.player.PlayerKickEvent.Cause cause) { - org.spigotmc.AsyncCatcher.catchOp("player kick"); - final ServerGamePacketListenerImpl connection = this.getHandle().connection; - if (connection != null) { -- connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); -+ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message, cause); - } - } - // Paper end -diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index 6498dc4c6630bfef1a52edf74d8574e5e4876720..ea1f088ac94616978af5e01a59c558cd2db4b619 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(SpigotConfig.restartMessage); -+ p.connection.disconnect(SpigotConfig.restartMessage, 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/Remapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch b/Remapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch deleted file mode 100644 index 276c9629f2..0000000000 --- a/Remapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yive -Date: Wed, 26 May 2021 15:09:33 -0700 -Subject: [PATCH] Limit item frame cursors on maps - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 108a005c296c4ed370de4af636163088971bed13..9287dfcf29ce6f89a937f4e10b70be8faab9ab9e 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -816,4 +816,9 @@ public class PaperWorldConfig { - private void allowUsingSignsInsideSpawnProtection() { - allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); - } -+ -+ public int mapItemFrameCursorLimit = 128; -+ private void mapItemFrameCursorLimit() { -+ mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -index e7b178127228dea5a17ba0fbd6bae148d70e8eb5..e2f550c833030d8ad12b80d3d379f4731ddeb2ec 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -@@ -279,8 +279,12 @@ public class MapItemSavedData extends SavedData { - - MapFrame worldmapframe1 = new MapFrame(blockposition, entityitemframe.getDirection().get2DDataValue() * 90, entityitemframe.getId()); - -+ // Paper start -+ if (this.decorations.size() < player.level.paperConfig.mapItemFrameCursorLimit) { - this.addDecoration(MapDecoration.Type.FRAME, player.level, "frame-" + entityitemframe.getId(), (double) blockposition.getX(), (double) blockposition.getZ(), (double) (entityitemframe.getDirection().get2DDataValue() * 90), (Component) null); - this.frameMarkers.put(worldmapframe1.getId(), worldmapframe1); -+ } -+ // Paper end - } - - CompoundTag nbttagcompound = stack.getTag(); diff --git a/Remapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch b/Remapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch deleted file mode 100644 index 58dca35d6b..0000000000 --- a/Remapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Mon, 10 May 2021 16:59:05 +0100 -Subject: [PATCH] Add PufferFishStateChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java -index eb80bde66fbb03dad845e36f1bd1a8eaf8592fbf..44b7b62622d65326aa3926764bb1bb1ed8694511 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java -@@ -89,25 +89,39 @@ public class Pufferfish extends AbstractFish { - public void tick() { - if (!this.level.isClientSide && this.isAlive() && this.isEffectiveAi()) { - if (this.inflateCounter > 0) { -+ boolean increase = true; // Paper - Add PufferFishStateChangeEvent - if (this.getPuffState() == 0) { -+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent - this.playSound(SoundEvents.PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.getVoicePitch()); - this.setPuffState(1); -+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } else if (this.inflateCounter > 40 && this.getPuffState() == 1) { -+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 2).callEvent()) { // Paper - Add PufferFishStateChangeEvent - this.playSound(SoundEvents.PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.getVoicePitch()); - this.setPuffState(2); -+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } - -+ if (increase) { // Paper - Add PufferFishStateChangeEvent - ++this.inflateCounter; -+ } // Paper - Add PufferFishStateChangeEvent - } else if (this.getPuffState() != 0) { -+ boolean increase = true; // Paper - Add PufferFishStateChangeEvent - if (this.deflateTimer > 60 && this.getPuffState() == 2) { -+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent - this.playSound(SoundEvents.PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.getVoicePitch()); - this.setPuffState(1); -+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } else if (this.deflateTimer > 100 && this.getPuffState() == 1) { -+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 0).callEvent()) { // Paper - Add PufferFishStateChangeEvent - this.playSound(SoundEvents.PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.getVoicePitch()); - this.setPuffState(0); -+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } - -+ if (increase) { // Paper - Add PufferFishStateChangeEvent - ++this.deflateTimer; -+ } // Paper - Add PufferFishStateChangeEvent - } - } - diff --git a/Remapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/Remapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch deleted file mode 100644 index 85fe9b3b12..0000000000 --- a/Remapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 20 May 2021 22:16:37 -0700 -Subject: [PATCH] Fix PlayerBucketEmptyEvent result itemstack - -Fixes SPIGOT-2560: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-2560 - -diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java -index d0e847e58483695d2af1c1410826bb25231cd6f6..08c00a084b2972420eae020e13480489b29aec64 100644 ---- a/src/main/java/net/minecraft/world/item/BucketItem.java -+++ b/src/main/java/net/minecraft/world/item/BucketItem.java -@@ -116,6 +116,13 @@ public class BucketItem extends Item { - } - - protected ItemStack getEmptySuccessItem(ItemStack stack, Player player) { -+ // Paper -+ if (itemLeftInHandAfterPlayerBucketEmptyEvent != null) { -+ ItemStack itemInHand = itemLeftInHandAfterPlayerBucketEmptyEvent; -+ itemLeftInHandAfterPlayerBucketEmptyEvent = null; -+ return itemInHand; -+ } -+ // Paper - return !player.abilities.instabuild ? new ItemStack(Items.BUCKET) : stack; - } - -@@ -126,6 +133,7 @@ public class BucketItem extends Item { - return a(player, world, pos, movingobjectpositionblock, null, null, null, null); - } - -+ private ItemStack itemLeftInHandAfterPlayerBucketEmptyEvent = null; // Paper - public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, InteractionHand enumhand) { - // Paper end - // CraftBukkit end -@@ -146,6 +154,9 @@ public class BucketItem extends Item { - ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 - return false; - } -+ // Paper start -+ itemLeftInHandAfterPlayerBucketEmptyEvent = event.getItemStack().equals(CraftItemStack.asNewCraftStack(net.minecraft.world.item.Items.BUCKET)) ? null : CraftItemStack.asNMSCopy(event.getItemStack()); -+ // Paper end - } - // CraftBukkit end - if (!flag1) { diff --git a/Remapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch b/Remapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch deleted file mode 100644 index 3cd329efc6..0000000000 --- a/Remapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: GioSDA -Date: Wed, 10 Mar 2021 10:06:45 -0800 -Subject: [PATCH] Add option to fix items merging through walls - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9287dfcf29ce6f89a937f4e10b70be8faab9ab9e..74f2413773fbe30597314e02a5284172e0fc40b2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -821,4 +821,9 @@ public class PaperWorldConfig { - private void mapItemFrameCursorLimit() { - mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); - } -+ -+ public boolean fixItemsMergingThroughWalls; -+ private void fixItemsMergingThroughWalls() { -+ fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 7476ae301fb4ee503944d39022cb25ccb19f1232..d937a74d2e822c8542286fb5bcdfcec7895d845c 100644 ---- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -227,6 +227,14 @@ public class ItemEntity extends Entity { - ItemEntity entityitem = (ItemEntity) iterator.next(); - - if (entityitem.isMergable()) { -+ // Paper Start - Fix items merging through walls -+ if (this.level.paperConfig.fixItemsMergingThroughWalls) { -+ net.minecraft.world.level.ClipContext rayTrace = new net.minecraft.world.level.ClipContext(this.position(), entityitem.position(), -+ net.minecraft.world.level.ClipContext.Block.COLLIDER, net.minecraft.world.level.ClipContext.Fluid.NONE, this); -+ net.minecraft.world.phys.BlockHitResult rayTraceResult = level.clip(rayTrace); -+ if (rayTraceResult.getType() == net.minecraft.world.phys.HitResult.Type.BLOCK) continue; -+ } -+ // Paper End - this.tryToMerge(entityitem); - if (this.removed) { - break; diff --git a/Remapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch b/Remapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch deleted file mode 100644 index 78020871e6..0000000000 --- a/Remapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Wed, 26 May 2021 17:09:07 -0400 -Subject: [PATCH] Add BellRevealRaiderEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java -index 3f9179a7678091875161a34d13b6ec0e78025c4c..03c2831a7c4f310936dad1ee72f402ed38f3c9e7 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java -@@ -6,6 +6,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; - import net.minecraft.core.Position; - import net.minecraft.core.particles.ParticleTypes; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.tags.EntityTypeTags; -@@ -181,6 +182,7 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity - } - - private void glow(LivingEntity entity) { -+ if (!new io.papermc.paper.event.block.BellRevealRaiderEvent(level.getWorld().getBlockAt(MCUtil.toLocation(level, worldPosition)), entity.getBukkitEntity()).callEvent()) return; // Paper - BellRevealRaiderEvent - entity.addEffect(new MobEffectInstance(MobEffects.GLOWING, 60)); - } - } diff --git a/Remapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch b/Remapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch deleted file mode 100644 index d830a00fa4..0000000000 --- a/Remapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Max Lee -Date: Thu, 27 May 2021 14:52:30 -0700 -Subject: [PATCH] Fix invulnerable end crystals - -MC-108513 - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 74f2413773fbe30597314e02a5284172e0fc40b2..dc5ebbb44238cb5928f385d2962c9057388575f8 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -826,4 +826,9 @@ public class PaperWorldConfig { - private void fixItemsMergingThroughWalls() { - fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); - } -+ -+ public boolean fixInvulnerableEndCrystalExploit = true; -+ private void fixInvulnerableEndCrystalExploit() { -+ fixInvulnerableEndCrystalExploit = getBoolean("unsupported-settings.fix-invulnerable-end-crystal-exploit", fixInvulnerableEndCrystalExploit); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java -index 6292d04464950ac52fcd6d69345db5125d3127eb..8583209750e4bb70e86d7243a47c525f1726ee42 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java -@@ -29,6 +29,7 @@ public class EndCrystal extends Entity { - private static final EntityDataAccessor> DATA_BEAM_TARGET = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.OPTIONAL_BLOCK_POS); - private static final EntityDataAccessor DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN); - public int time; -+ public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals - - public EndCrystal(EntityType type, Level world) { - super(type, world); -@@ -65,6 +66,17 @@ public class EndCrystal extends Entity { - } - // CraftBukkit end - } -+ // Paper start - Fix invulnerable end crystals -+ if (this.level.paperConfig.fixInvulnerableEndCrystalExploit && this.generatedByDragonFight && this.isInvulnerable()) { -+ if ((this.origin.getWorld() != null && !((ServerLevel) this.level).uuid.equals(this.origin.getWorld().getUID())) -+ || ((ServerLevel) this.level).dragonFight() == null -+ || ((ServerLevel) this.level).dragonFight().respawnStage == null -+ || ((ServerLevel) this.level).dragonFight().respawnStage.ordinal() > net.minecraft.world.level.dimension.end.DragonRespawnAnimation.SUMMONING_DRAGON.ordinal()) { -+ this.setInvulnerable(false); -+ this.setBeamTarget(null); -+ } -+ } -+ // Paper end - } - - } -@@ -76,6 +88,7 @@ public class EndCrystal extends Entity { - } - - tag.putBoolean("ShowBottom", this.showsBottom()); -+ if (this.generatedByDragonFight) tag.putBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals - } - - @Override -@@ -87,6 +100,7 @@ public class EndCrystal extends Entity { - if (tag.contains("ShowBottom", 1)) { - this.setShowBottom(tag.getBoolean("ShowBottom")); - } -+ if (tag.contains("Paper.GeneratedByDragonFight", 1)) this.generatedByDragonFight = tag.getBoolean("Paper.GeneratedByDragonFight"); // Paper - Fix invulnerable end crystals - - } - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java -index b99576b524a65cc1a0de88c49324d929503d655f..d51d2fb6d24bfee63b04f32f2cb157fec9d8ee6c 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java -@@ -42,11 +42,11 @@ public class SpikeFeature extends Feature { - return (List) SpikeFeature.SPIKE_CACHE.getUnchecked(i); - } - -- public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, SpikeConfiguration config) { -- List list = config.getSpikes(); -+ public boolean generate(WorldGenLevel generatoraccessseed, ChunkGenerator chunkgenerator, Random random, BlockPos blockposition, SpikeConfiguration worldgenfeatureendspikeconfiguration) { // Paper - decompile fix -+ List list = worldgenfeatureendspikeconfiguration.getSpikes(); - - if (list.isEmpty()) { -- list = getSpikesForLevel(world); -+ list = getSpikesForLevel(generatoraccessseed); - } - - Iterator iterator = list.iterator(); -@@ -54,8 +54,8 @@ public class SpikeFeature extends Feature { - while (iterator.hasNext()) { - SpikeFeature.EndSpike worldgenender_spike = (SpikeFeature.EndSpike) iterator.next(); - -- if (worldgenender_spike.isCenterWithinChunk(pos)) { -- this.placeSpike(world, random, config, worldgenender_spike); -+ if (worldgenender_spike.isCenterWithinChunk(blockposition)) { -+ this.placeSpike(generatoraccessseed, random, worldgenfeatureendspikeconfiguration, worldgenender_spike); - } - } - -@@ -106,6 +106,7 @@ public class SpikeFeature extends Feature { - entityendercrystal.setBeamTarget(config.getCrystalBeamTarget()); - entityendercrystal.setInvulnerable(config.isCrystalInvulnerable()); - entityendercrystal.moveTo((double) spike.getCenterX() + 0.5D, (double) (spike.getHeight() + 1), (double) spike.getCenterZ() + 0.5D, random.nextFloat() * 360.0F, 0.0F); -+ entityendercrystal.generatedByDragonFight = true; - world.addFreshEntity(entityendercrystal); - this.setBlock(world, new BlockPos(spike.getCenterX(), spike.getHeight(), spike.getCenterZ()), Blocks.BEDROCK.defaultBlockState()); - } diff --git a/Remapped-Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch b/Remapped-Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch deleted file mode 100644 index 2e0af7d211..0000000000 --- a/Remapped-Spigot-Server-Patches/0753-Add-ElderGuardianAppearanceEvent.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Fri, 19 Mar 2021 23:39:09 -0400 -Subject: [PATCH] Add ElderGuardianAppearanceEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java -index b6a842f9a24634ff84f2f4f94c0f2838f10cddb0..0cf6a06f8bddac0a2a1a00f3a4b266116f7ae594 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java -+++ b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java -@@ -77,10 +77,12 @@ public class ElderGuardian extends Guardian { - while (iterator.hasNext()) { - ServerPlayer entityplayer = (ServerPlayer) iterator.next(); - -+ if (new io.papermc.paper.event.entity.ElderGuardianAppearanceEvent(getBukkitEntity(), entityplayer.getBukkitEntity()).callEvent()) { // Paper - Add Guardian Appearance Event - if (!entityplayer.hasEffect(mobeffectlist) || entityplayer.getEffect(mobeffectlist).getAmplifier() < 2 || entityplayer.getEffect(mobeffectlist).getDuration() < 1200) { - entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)); - entityplayer.addEffect(new MobEffectInstance(mobeffectlist, 6000, 2), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit - } -+ } // Paper - Add Guardian Appearance Event - } - } - diff --git a/Remapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch b/Remapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch deleted file mode 100644 index a6ef1d69fa..0000000000 --- a/Remapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 1 Jun 2021 22:05:08 -0500 -Subject: [PATCH] Reset villager inventory on cancelled pickup event - - -diff --git a/src/main/java/net/minecraft/world/SimpleContainer.java b/src/main/java/net/minecraft/world/SimpleContainer.java -index d6bb1d540e6dcbbad5e5bdf54803c495a4f3e771..3e639f5af83bea6760669696425dffd2d741cc16 100644 ---- a/src/main/java/net/minecraft/world/SimpleContainer.java -+++ b/src/main/java/net/minecraft/world/SimpleContainer.java -@@ -34,6 +34,16 @@ public class SimpleContainer implements Container, StackedContentsCompatible { - return this.items; - } - -+ // Paper start -+ public void setContents(List items) { -+ this.items.clear(); -+ for(int i = 0; i < items.size(); i++) { -+ this.items.set(i, items.get(i)); -+ } -+ this.setChanged(); -+ } -+ // Paper end -+ - public void onOpen(CraftHumanEntity who) { - transaction.add(who); - } -@@ -148,6 +158,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible { - return itemstack; - } - -+ public ItemStack addItem(ItemStack itemstack) { return addItem(itemstack); } // Paper - OBFHELPER - public ItemStack addItem(ItemStack stack) { - ItemStack itemstack1 = stack.copy(); - -diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 7817071b1964b962c8f4017d5bb39d74ca0ca3e4..1fbb7a2db5c362a5fc9e3f81382f729c962e377b 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/Villager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -844,15 +844,19 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - } - - // CraftBukkit start -- ItemStack remaining = new SimpleContainer(inventorysubcontainer).addItem(itemstack); -- if (CraftEventFactory.callEntityPickupItemEvent(this, item, remaining.getCount(), false).isCancelled()) { -+ // Paper start -+ List contentsSnapshot = new java.util.ArrayList<>(inventorysubcontainer.getContents()); -+ ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); -+ if (CraftEventFactory.callEntityPickupItemEvent(this, item, itemstack1.getCount(), false).isCancelled()) { -+ inventorysubcontainer.setContents(contentsSnapshot); -+ // Paper end - return; - } - // CraftBukkit end - - this.onItemPickup(item); - this.take(item, itemstack.getCount()); -- ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); -+ // ItemStack itemstack1 = inventorysubcontainer.a(itemstack); // Paper - moved up - - if (itemstack1.isEmpty()) { - item.remove(); diff --git a/Remapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch b/Remapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch deleted file mode 100644 index a1fbfe0408..0000000000 --- a/Remapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 4 Jun 2021 17:06:52 -0400 -Subject: [PATCH] Fix dangerous end portal logic - -End portals could teleport entities during move calls. Stupid -logic given the caller will never expect that kind of thing, -and will result in all kinds of dupes. - -Move the tick logic into the post tick, where portaling was -designed to happen in the first place. - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 779b926921fd435620cbbc69ed6f9931a422b652..25711ab723386db0f448c54e18ef069bfcd0dd99 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1020,6 +1020,7 @@ public class ServerPlayer extends Player implements ContainerListener { - return b(destination, TeleportCause.UNKNOWN); - } - -+ @Nullable public final Entity changeDimension(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { return this.b(worldserver, cause); } // Paper - OBFHELPER - @Nullable - public Entity b(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d055b362459e5b4658aa220e16118ee6174c0de4..2462a78d976937cf4737f1ce0bfde2b2b7d5b1f7 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -312,6 +312,37 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - // Paper end - optimise entity tracking - -+ // Paper start - make end portalling safe -+ public BlockPos portalBlock; -+ public ServerLevel portalWorld; -+ public void tickEndPortal() { -+ BlockPos pos = this.portalBlock; -+ ServerLevel world = this.portalWorld; -+ this.portalBlock = null; -+ this.portalWorld = null; -+ -+ if (pos == null || world == null || world != this.level) { -+ return; -+ } -+ -+ if (this.isPassenger() || this.isVehicle() || !this.canChangeDimensions() || this.removed || !this.valid || !this.isAlive()) { -+ return; -+ } -+ -+ ResourceKey resourcekey = world.getTypeKey() == DimensionType.END_LOCATION ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends -+ ServerLevel worldserver = world.getServer().getLevel(resourcekey); -+ -+ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(this.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); -+ event.callEvent(); -+ -+ if (this instanceof ServerPlayer) { -+ ((ServerPlayer)this).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); -+ return; -+ } -+ this.teleportTo(worldserver, null); -+ } -+ // Paper end - make end portalling safe -+ - public Entity(EntityType type, Level world) { - this.id = Entity.ENTITY_COUNTER.incrementAndGet(); - this.passengers = Lists.newArrayList(); -@@ -2297,6 +2328,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - this.processPortalCooldown(); -+ this.tickEndPortal(); // Paper - make end portalling safe - } - } - -diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -index 2231680140d0e3c4c10b6722fd13fe0ee55ce294..52884b87b25bef8abfa824f40d02efe3f947f330 100644 ---- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -@@ -3,7 +3,6 @@ package net.minecraft.world.level.block; - import net.minecraft.core.BlockPos; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.level.ServerLevel; --import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.BlockGetter; - import net.minecraft.world.level.Level; -@@ -50,16 +49,10 @@ public class EndPortalBlock extends BaseEntityBlock { - // return; // CraftBukkit - always fire event in case plugins wish to change it - } - -- // CraftBukkit start - Entity in portal -- EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); -- world.getCraftServer().getPluginManager().callEvent(event); -- -- if (entity instanceof ServerPlayer) { -- ((ServerPlayer) entity).b(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); -- return; -- } -- // CraftBukkit end -- entity.changeDimension(worldserver); -+ // Paper start - move all of this logic into portal tick -+ entity.portalWorld = ((ServerLevel)world); -+ entity.portalBlock = pos.immutable(); -+ // Paper end - move all of this logic into portal tick - } - - } diff --git a/Remapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch b/Remapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch deleted file mode 100644 index 964f15ad4b..0000000000 --- a/Remapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 4 Jun 2021 12:12:35 -0700 -Subject: [PATCH] Make item validations configurable - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index efc1e42d606e1c9feb1a4871c0714933ae92a1b2..7acf077bc131af718c7548cc29deef558c04e463 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -486,4 +486,19 @@ public class PaperConfig { - enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); - enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); - } -+ -+ public static int itemValidationDisplayNameLength = 8192; -+ public static int itemValidationLocNameLength = 8192; -+ public static int itemValidationLoreLineLength = 8192; -+ public static int itemValidationBookTitleLength = 8192; -+ public static int itemValidationBookAuthorLength = 8192; -+ public static int itemValidationBookPageLength = 16384; -+ private static void itemValidationSettings() { -+ itemValidationDisplayNameLength = getInt("settings.item-validation.display-name", itemValidationDisplayNameLength); -+ itemValidationLocNameLength = getInt("settings.item-validation.loc-name", itemValidationLocNameLength); -+ itemValidationLoreLineLength = getInt("settings.item-validation.lore-line", itemValidationLoreLineLength); -+ itemValidationBookTitleLength = getInt("settings.item-validation.book.title", itemValidationBookTitleLength); -+ itemValidationBookAuthorLength = getInt("settings.item-validation.book.author", itemValidationBookAuthorLength); -+ itemValidationBookPageLength = getInt("settings.item-validation.book.page", itemValidationBookPageLength); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index 80397e223990f11c9aa413f3f4ebd7c1b8ce1cff..2ff1619e6898add074481c7ca43bfbf9a8d163ca 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -94,11 +94,11 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - super(tag); - - if (tag.contains(BOOK_TITLE.NBT)) { -- this.title = limit( tag.getString(BOOK_TITLE.NBT), 8192 ); // Spigot -+ this.title = limit( tag.getString(BOOK_TITLE.NBT), com.destroystokyo.paper.PaperConfig.itemValidationBookTitleLength); // Spigot // Paper - make configurable - } - - if (tag.contains(BOOK_AUTHOR.NBT)) { -- this.author = limit( tag.getString(BOOK_AUTHOR.NBT), 8192 ); // Spigot -+ this.author = limit( tag.getString(BOOK_AUTHOR.NBT), com.destroystokyo.paper.PaperConfig.itemValidationBookAuthorLength ); // Spigot // Paper - make configurable - } - - if (tag.contains(RESOLVED.NBT)) { -@@ -126,7 +126,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - } else { - page = validatePage(page); - } -- this.pages.add( limit( page, 16384 ) ); // Spigot -+ this.pages.add( limit( page, com.destroystokyo.paper.PaperConfig.itemValidationBookPageLength ) ); // Spigot // Paper - make configurable - } - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 20e008277d1188fc7b31bfb2522ef9f6429cc3fb..99e18748b3cc4168b1d15c030f992a128b666d84 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -357,18 +357,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - CompoundTag display = tag.getCompound(DISPLAY.NBT); - - if (display.contains(NAME.NBT)) { -- displayName = limit( display.getString(NAME.NBT), 8192 ); // Spigot -+ displayName = limit( display.getString(NAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationDisplayNameLength); // Spigot // Paper - make configurable - } - - if (display.contains(LOCNAME.NBT)) { -- locName = limit( display.getString(LOCNAME.NBT), 8192 ); // Spigot -+ locName = limit( display.getString(LOCNAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationLocNameLength ); // Spigot // Paper - make configurable - } - - if (display.contains(LORE.NBT)) { - ListTag list = display.getList(LORE.NBT, CraftMagicNumbers.NBT.TAG_STRING); - lore = new ArrayList(list.size()); - for (int index = 0; index < list.size(); index++) { -- String line = limit( list.getString(index), 8192 ); // Spigot -+ String line = limit( list.getString(index), com.destroystokyo.paper.PaperConfig.itemValidationLoreLineLength ); // Spigot // Paper - make configurable - lore.add(line); - } - } diff --git a/Remapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch b/Remapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch deleted file mode 100644 index 2961b16b07..0000000000 --- a/Remapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TwoLeggedCat <80929284+TwoLeggedCat@users.noreply.github.com> -Date: Sat, 29 May 2021 14:33:25 -0500 -Subject: [PATCH] Add more line of sight methods - - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 37787a725725d22b0870dcab0f3bec8b94cfd130..79b43b1b0f8e223f256c2aaec1925426931a9a54 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3091,6 +3091,7 @@ public abstract class LivingEntity extends Entity { - Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); - Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); - -+ // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists - return this.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 1c9321cef1a05c5e8a22dd52bc63a5103eaf7311..312ed9c693cc5108d51ad90e15d6be4bb21904e1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -315,6 +315,17 @@ public class CraftWorld implements World { - public io.papermc.paper.world.MoonPhase getMoonPhase() { - return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); - } -+ -+ @Override -+ public boolean lineOfSightExists(Location from, Location to) { -+ Validate.notNull(from, "from parameter in lineOfSightExists cannot be null"); -+ Validate.notNull(to, "to parameter in lineOfSightExists cannot be null"); -+ if (from.getWorld() != to.getWorld()) return false; -+ Vec3 vec3d = new Vec3(from.getX(), from.getY(), from.getZ()); -+ Vec3 vec3d1 = new Vec3(to.getX(), to.getY(), to.getZ()); -+ -+ return this.getHandle().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, null)).getType() == HitResult.Type.MISS; -+ } - // Paper end - - private static final Random rand = new Random(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 25ba7a26c951fc5e4638bdb0db36e94d3e08fb2e..cd42edd8f36cea3acad76974c39eb0cd1585f73d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -549,6 +549,17 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().canSee(((CraftEntity) other).getHandle()); - } - -+ // Paper start -+ @Override -+ public boolean hasLineOfSight(Location loc) { -+ if (this.getHandle().level != ((CraftWorld) loc.getWorld()).getHandle()) return false; -+ Vec3 vec3d = new Vec3(this.getHandle().getX(), this.getHandle().getEyeY(), this.getHandle().getZ()); -+ Vec3 vec3d1 = new Vec3(loc.getX(), loc.getY(), loc.getZ()); -+ -+ return this.getHandle().level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this.getHandle())).getType() == HitResult.Type.MISS; -+ } -+ // Paper end -+ - @Override - public boolean getRemoveWhenFarAway() { - return getHandle() instanceof Mob && !((Mob) getHandle()).persistenceRequired; diff --git a/Remapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch b/Remapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch deleted file mode 100644 index b4f5cd5335..0000000000 --- a/Remapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chase -Date: Wed, 2 Dec 2020 22:43:39 -0800 -Subject: [PATCH] add per world spawn limits - -Taken from #2982. Credit to Chasewhip8 - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index dc5ebbb44238cb5928f385d2962c9057388575f8..f80186f663ff654ab6b69189941cd26815f65f09 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -652,6 +652,19 @@ public class PaperWorldConfig { - zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); - } - -+ public int spawnLimitMonsters = -1; -+ public int spawnLimitAnimals = -1; -+ public int spawnLimitWaterAnimals = -1; -+ public int spawnLimitWaterAmbient = -1; -+ public int spawnLimitAmbient = -1; -+ private void perWorldSpawnLimits() { -+ spawnLimitMonsters = getInt("spawn-limits.monsters", spawnLimitMonsters); -+ spawnLimitAnimals = getInt("spawn-limits.animals", spawnLimitAnimals); -+ spawnLimitWaterAnimals = getInt("spawn-limits.water-animals", spawnLimitWaterAnimals); -+ spawnLimitWaterAmbient = getInt("spawn-limits.water-ambient", spawnLimitWaterAmbient); -+ spawnLimitAmbient = getInt("spawn-limits.ambient", spawnLimitAmbient); -+ } -+ - public int lightQueueSize = 20; - private void lightQueueSize() { - lightQueueSize = getInt("light-queue-size", lightQueueSize); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 312ed9c693cc5108d51ad90e15d6be4bb21904e1..89aac4214084bd72a83eaaf043b7d47cc0b748f5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -335,6 +335,13 @@ public class CraftWorld implements World { - this.generator = gen; - - environment = env; -+ // Paper start - per world spawn limits -+ this.monsterSpawn = this.world.paperConfig.spawnLimitMonsters; -+ this.animalSpawn = this.world.paperConfig.spawnLimitAnimals; -+ this.waterAnimalSpawn = this.world.paperConfig.spawnLimitWaterAnimals; -+ this.waterAmbientSpawn = this.world.paperConfig.spawnLimitWaterAmbient; -+ this.ambientSpawn = this.world.paperConfig.spawnLimitAmbient; -+ // Paper end - } - - @Override diff --git a/Remapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch b/Remapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch deleted file mode 100644 index f351ce4533..0000000000 --- a/Remapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 20 May 2021 20:40:53 -0700 -Subject: [PATCH] Fix PotionSplashEvent for water splash potions - -Fixes SPIGOT-6221: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-6221 - -diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -index ed81d2a306d28561370745bb3389c49012f677a7..fbdfab50af195d219f9745324c8924fc777f76ec 100644 ---- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java -+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -@@ -99,6 +99,7 @@ public class DamageSource { - return (new IndirectEntityDamageSource("thrown", projectile, attacker)).setProjectile(); - } - -+ public static DamageSource indirectMagic(Entity target, Entity cause) { return indirectMagic(target, cause); } // Paper - OBFHELPER - public static DamageSource indirectMagic(Entity magic, @Nullable Entity attacker) { - return (new IndirectEntityDamageSource("indirectMagic", magic, attacker)).bypassArmor().setMagic(); - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java -index 2ff7e8dfc0a520fb330177c140a1ae5c729f14c0..8bf095bce9dfec6479185b6e60c2e9d76e3363eb 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java -@@ -122,6 +122,7 @@ public class ThrownPotion extends ThrowableItemProjectile { - private void applyWater() { - AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); - List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb, ThrownPotion.WATER_SENSITIVE); -+ Map affected = new HashMap<>(); // Paper - - if (!list.isEmpty()) { - Iterator iterator = list.iterator(); -@@ -131,11 +132,22 @@ public class ThrownPotion extends ThrowableItemProjectile { - double d0 = this.distanceToSqr(entityliving); - - if (d0 < 16.0D && entityliving.isSensitiveToWater()) { -- entityliving.hurt(DamageSource.indirectMagic(entityliving, this.getOwner()), 1.0F); -+ // Paper start -+ double intensity = 1.0D - Math.sqrt(d0) / 4.0D; -+ affected.put(entityliving.getBukkitLivingEntity(), intensity); -+ // entityliving.damageEntity(DamageSource.c(entityliving, this.getShooter()), 1.0F); // Paper - moved down - } - } - } - -+ org.bukkit.event.entity.PotionSplashEvent event = CraftEventFactory.callPotionSplashEvent(this, affected); -+ if (!event.isCancelled()) { -+ for (LivingEntity affectedEntity : event.getAffectedEntities()) { -+ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) affectedEntity).getHandle(); -+ entityliving.hurt(DamageSource.indirectMagic(entityliving, this.getOwner()), 1.0F); -+ } -+ } -+ // Paper end - } - - private void applySplash(List statusEffects, @Nullable Entity entity) { -@@ -153,6 +165,7 @@ public class ThrownPotion extends ThrowableItemProjectile { - double d0 = this.distanceToSqr(entityliving); - - if (d0 < 16.0D) { -+ // Paper - diff on change, used when calling the splash event for water splash potions - double d1 = 1.0D - Math.sqrt(d0) / 4.0D; - - if (entityliving == entity) { diff --git a/Spigot-API-Patches/0001-Convert-project-to-Gradle.patch b/Spigot-API-Patches/0001-Convert-project-to-Gradle.patch deleted file mode 100644 index d34ab3ef3c..0000000000 --- a/Spigot-API-Patches/0001-Convert-project-to-Gradle.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Thu, 10 Dec 2020 20:50:33 -0800 -Subject: [PATCH] Convert project to Gradle - - -diff --git a/.gitignore b/.gitignore -index e431e3435737e28394d81b56568a08b3c3148b9b..c484aff2c192bf42059b5689327909e4af654401 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -1,3 +1,5 @@ -+.gradle/ -+ - # Eclipse stuff - /.classpath - /.project -diff --git a/build.gradle.kts b/build.gradle.kts -new file mode 100644 -index 0000000000000000000000000000000000000000..a0f1c1d1ac63fdcce942922ffe68a8d44c712513 ---- /dev/null -+++ b/build.gradle.kts -@@ -0,0 +1,54 @@ -+plugins { -+ `java-library` -+ checkstyle -+} -+ -+java { -+ withSourcesJar() -+ withJavadocJar() -+} -+ -+dependencies { -+ // api dependencies are listed transitively to API consumers -+ api("commons-lang:commons-lang:2.6") -+ api("com.google.guava:guava:21.0") -+ api("com.google.code.gson:gson:2.8.0") -+ api("net.md-5:bungeecord-chat:1.16-R0.4") -+ api("org.yaml:snakeyaml:1.29") -+ -+ compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") -+ compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") -+ compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") -+ -+ val annotations = "org.jetbrains:annotations-java5:21.0.1" -+ compileOnly(annotations) -+ testCompileOnly(annotations) -+ -+ testImplementation("junit:junit:4.13.1") -+ testImplementation("org.hamcrest:hamcrest-library:1.3") -+ testImplementation("org.ow2.asm:asm-tree:9.1") -+ -+ checkstyle("com.puppycrawl.tools:checkstyle:8.39") -+} -+ -+tasks.jar { -+ manifest { -+ attributes += mapOf( -+ "Automatic-Module-Name" to "org.bukkit" -+ ) -+ } -+} -+ -+tasks.withType().configureEach { -+ (options as StandardJavadocDocletOptions).links( -+ "https://guava.dev/releases/21.0/api/docs/", -+ "https://javadoc.io/doc/org.yaml/snakeyaml/1.27/", -+ "https://javadoc.io/doc/org.jetbrains/annotations-java5/20.1.0/", -+ "https://javadoc.io/doc/net.md-5/bungeecord-chat/1.16-R0.4/" -+ ) -+} -+ -+checkstyle { -+ configFile = file("checkstyle.xml") -+ sourceSets = listOf(project.sourceSets.main.get(), project.sourceSets.test.get()) -+} diff --git a/Spigot-Server-Patches/0001-Setup-Gradle-project.patch b/Spigot-Server-Patches/0001-Setup-Gradle-project.patch deleted file mode 100644 index 9e12bf0e6d..0000000000 --- a/Spigot-Server-Patches/0001-Setup-Gradle-project.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Thu, 10 Dec 2020 20:54:19 -0800 -Subject: [PATCH] Setup Gradle project - - -diff --git a/.gitignore b/.gitignore -index 67fb370cad6924895a6b27052dbd5c1767e3f0c9..3e05459f27c4c5697ae65da504d67a6a2f617b57 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -1,3 +1,6 @@ -+.gradle/ -+build/ -+ - # Eclipse stuff - /.classpath - /.project -diff --git a/build.gradle.kts b/build.gradle.kts -new file mode 100644 -index 0000000000000000000000000000000000000000..fddf2f440356425d948f40dcf9d9853a374ddc8e ---- /dev/null -+++ b/build.gradle.kts -@@ -0,0 +1,72 @@ -+import com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer -+import java.time.Instant -+ -+plugins { -+ java -+ id("com.github.johnrengelman.shadow") -+} -+ -+val packageVersion = providers.gradleProperty("packageVersion").forUseAtConfigurationTime().get() -+ -+repositories { -+ maven("https://libraries.minecraft.net/") -+} -+ -+dependencies { -+ implementation(project(":Paper-API")) -+ implementation("jline:jline:2.12.1") -+ implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") { -+ exclude(group = "org.apache.logging.log4j", module = "log4j-api") -+ } -+ implementation("org.ow2.asm:asm:9.1") -+ implementation("com.googlecode.json-simple:json-simple:1.1.1") { -+ // This includes junit transitively for whatever reason -+ isTransitive = false -+ } -+ runtimeOnly("org.xerial:sqlite-jdbc:3.34.0") -+ runtimeOnly("mysql:mysql-connector-java:5.1.49") -+ -+ runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.1") -+ runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") -+ runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") -+ -+ testImplementation("junit:junit:4.13.1") -+ testImplementation("org.hamcrest:hamcrest-library:1.3") -+} -+ -+tasks.jar { -+ manifest { -+ attributes(mapOf( -+ "Main-Class" to "org.bukkit.craftbukkit.Main", -+ "Implementation-Title" to "CraftBukkit", -+ "Implementation-Vendor" to Instant.now().epochSecond, -+ "Specification-Title" to "Bukkit", -+ "Specification-Version" to project.version, -+ "Specification-Vendor" to "Bukkit Team" -+ )) -+ for (tld in listOf("net", "com", "org")) { -+ attributes(mapOf( -+ "Sealed" to "true" -+ ), "$tld/bukkit") -+ } -+ } -+} -+ -+tasks.shadowJar { -+ listOf( -+ "jline", "it.unimi", "org.apache.commons.codec", "org.apache.commons.io", -+ "org.apache.commons.lang3", "org.objectweb.asm" -+ ).forEach { pack -> -+ relocate(pack, "org.bukkit.craftbukkit.libs.$pack") -+ } -+ relocate("org.bukkit.craftbukkit", "org.bukkit.craftbukkit.v$packageVersion") { -+ exclude("org.bukkit.craftbukkit.Main*") -+ } -+ transform(AppendingTransformer::class.java) { -+ resource = "META-INF/services/java.sql.Driver" -+ } -+} -+ -+tasks.test { -+ exclude("org/bukkit/craftbukkit/inventory/ItemStack*Test.class") -+} diff --git a/Spigot-Server-Patches/0002-Decompile-fixes.patch b/Spigot-Server-Patches/0002-Decompile-fixes.patch deleted file mode 100644 index ce714be18b..0000000000 --- a/Spigot-Server-Patches/0002-Decompile-fixes.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Fri, 11 Jun 2021 05:25:03 -0500 -Subject: [PATCH] Decompile fixes - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 3aecce56bdac0a316742a55e340c522bea737321..6b4d84faba50d9f3f87e48251cf1294479d4a3a0 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1138,7 +1138,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -- entity1.moveTo(pos.x, pos.y, pos.z, entity1.getYRot(), entity1.getXRot()); -- return entity1; -+ Entity entity1 = EntityType.loadEntityRecursive(nbttagcompound1, worldserver, (loadedEntity) -> { // Paper - decomp fix -+ loadedEntity.moveTo(pos.x, pos.y, pos.z, loadedEntity.getYRot(), loadedEntity.getXRot()); // Paper - decomp fix -+ return loadedEntity; // Paper - decomp fix - }); - - if (entity1 == null) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java -index 88a8c2bc4aa30f478122a05fd119486a0107db82..5f00e3f4c86196db47bf1007973445d40866afdd 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java -@@ -169,8 +169,8 @@ public class BehaviorUtils { - - return optional.map((uuid) -> { - return ((ServerLevel) entity.level).getEntity(uuid); -- }).map((entity) -> { -- return entity instanceof LivingEntity ? (LivingEntity) entity : null; -+ }).map((entity2) -> { // Paper - decomp fix -+ return entity2 instanceof LivingEntity ? (LivingEntity) entity2 : null; // Paper - decomp fix - }); - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index c88dc823ca0c2f83bc10886208d498ea77523d68..dcfd0b107ac7bd1633f3b681cd5f5e26ce87bd63 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -@@ -522,7 +522,7 @@ public class Phantom extends FlyingMob implements Enemy { - List list = Phantom.this.level.getNearbyPlayers(this.attackTargeting, (LivingEntity) Phantom.this, Phantom.this.getBoundingBox().inflate(16.0D, 64.0D, 16.0D)); - - if (!list.isEmpty()) { -- list.sort(Comparator.comparing(Entity::getY).reversed()); -+ list.sort(Comparator.comparing(Entity::getY).reversed()); // Paper - decomp fix - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) { -diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java -index b4a5709b03e400d00504f33a9b34019d2b7bf115..2d79d4014770081fcd58a929e5fe0a26ac1b8023 100644 ---- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java -+++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java -@@ -172,7 +172,7 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { - Map, Object2ObjectLinkedOpenHashMap>> map = Maps.newHashMap(); // CraftBukkit - - recipes.forEach((irecipe) -> { -- Map> map1 = (Map) map.computeIfAbsent(irecipe.getType(), (recipes) -> { -+ Map> map1 = (Map) map.computeIfAbsent(irecipe.getType(), (recipes_) -> { // Paper - decomp fix - return new Object2ObjectLinkedOpenHashMap<>(); // CraftBukkit - }); - Recipe irecipe1 = (Recipe) map1.put(irecipe.getId(), irecipe); diff --git a/Unmapped-Spigot-API-Patches/0001-POM-changes.patch b/Unmapped-Spigot-API-Patches/0001-POM-changes.patch deleted file mode 100644 index b6c98e0a08..0000000000 --- a/Unmapped-Spigot-API-Patches/0001-POM-changes.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 00:16:08 +0100 -Subject: [PATCH] POM changes - - -diff --git a/pom.xml b/pom.xml -index debe5bd7adb1f41e8a6878a8545de4bfcad1a590..d7cf64f05d0a2f5b186ca13b2b88e390abe84226 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -2,33 +2,34 @@ - - 4.0.0 -+ -+ com.destroystokyo.paper -+ paper-parent -+ dev-SNAPSHOT -+ - -- org.spigotmc -- spigot-api -+ com.destroystokyo.paper -+ paper-api - 1.17-R0.1-SNAPSHOT - jar - -- Spigot-API -- https://www.spigotmc.org/ -+ Paper-API -+ https://github.com/PaperMC/Paper - An enhanced plugin API for Minecraft servers. - - -- true -+ - 1.8 - 1.8 - UTF-8 - - -- -+ - -- spigotmc-releases -- https://hub.spigotmc.org/nexus/content/repositories/releases/ -+ sonatype -+ https://oss.sonatype.org/content/groups/public/ - -- -- spigotmc-snapshots -- https://hub.spigotmc.org/nexus/content/repositories/snapshots/ -- -- -+ - - - -@@ -37,6 +38,20 @@ - 2.6 - compile - -+ -+ -+ com.google.code.findbugs -+ jsr305 -+ 1.3.9 -+ compile -+ -+ -+ -+ com.googlecode.json-simple -+ json-simple -+ 1.1.1 -+ compile -+ - - - com.google.guava -@@ -112,6 +127,7 @@ - - - -+ clean install - - - net.md-5 -@@ -130,10 +146,6 @@ - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 -- -- -- eclipse -- - - - org.codehaus.plexus -@@ -183,6 +195,7 @@ - - - -+ ${project.build.directory}/dependency-reduced-pom.xml - - true - diff --git a/Unmapped-Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch b/Unmapped-Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch deleted file mode 100644 index a5e6eda88d..0000000000 --- a/Unmapped-Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 1 Apr 2016 00:02:47 -0400 -Subject: [PATCH] Add FastUtil to Bukkit - -Doesn't expose to plugins, just allows Paper-API to use it for optimization - -diff --git a/pom.xml b/pom.xml -index 61b8ee4e3e122dd2671f50ea3b432e4abd4600a2..12306d830c6889c2c9b12699abebe0411262aef6 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -32,6 +32,12 @@ - - - -+ -+ it.unimi.dsi -+ fastutil -+ 8.2.2 -+ provided -+ - - commons-lang - commons-lang diff --git a/Unmapped-Spigot-API-Patches/0003-Paper-Utils.patch b/Unmapped-Spigot-API-Patches/0003-Paper-Utils.patch deleted file mode 100644 index a647b698ad..0000000000 --- a/Unmapped-Spigot-API-Patches/0003-Paper-Utils.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 23 Feb 2019 11:26:21 -0500 -Subject: [PATCH] Paper Utils - - -diff --git a/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java b/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9db0056ab94145819628b3ad8d8d26130d117fcf ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java -@@ -0,0 +1,16 @@ -+package com.destroystokyo.paper.util; -+ -+import org.jetbrains.annotations.NotNull; -+ -+public class SneakyThrow { -+ -+ public static void sneaky(@NotNull Throwable exception) { -+ SneakyThrow.throwSneaky(exception); -+ } -+ -+ @SuppressWarnings("unchecked") -+ private static void throwSneaky(@NotNull Throwable exception) throws T { -+ throw (T) exception; -+ } -+ -+} diff --git a/Unmapped-Spigot-API-Patches/0004-Timings-v2.patch b/Unmapped-Spigot-API-Patches/0004-Timings-v2.patch deleted file mode 100644 index 9cfffce81e..0000000000 --- a/Unmapped-Spigot-API-Patches/0004-Timings-v2.patch +++ /dev/null @@ -1,3759 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Feb 2016 18:48:17 -0600 -Subject: [PATCH] Timings v2 - - -diff --git a/src/main/java/co/aikar/timings/FullServerTickHandler.java b/src/main/java/co/aikar/timings/FullServerTickHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..dfaa266ff53e43ad48dc5a5a5657fe70600f539a ---- /dev/null -+++ b/src/main/java/co/aikar/timings/FullServerTickHandler.java -@@ -0,0 +1,85 @@ -+package co.aikar.timings; -+ -+import static co.aikar.timings.TimingsManager.*; -+ -+import org.bukkit.Bukkit; -+import org.jetbrains.annotations.NotNull; -+ -+public class FullServerTickHandler extends TimingHandler { -+ private static final TimingIdentifier IDENTITY = new TimingIdentifier("Minecraft", "Full Server Tick", null); -+ final TimingData minuteData; -+ double avgFreeMemory = -1D; -+ double avgUsedMemory = -1D; -+ FullServerTickHandler() { -+ super(IDENTITY); -+ minuteData = new TimingData(id); -+ -+ TIMING_MAP.put(IDENTITY, this); -+ } -+ -+ @NotNull -+ @Override -+ public Timing startTiming() { -+ if (TimingsManager.needsFullReset) { -+ TimingsManager.resetTimings(); -+ } else if (TimingsManager.needsRecheckEnabled) { -+ TimingsManager.recheckEnabled(); -+ } -+ return super.startTiming(); -+ } -+ -+ @Override -+ public void stopTiming() { -+ super.stopTiming(); -+ if (!isEnabled() || Bukkit.isStopping()) { -+ return; -+ } -+ if (TimingHistory.timedTicks % 20 == 0) { -+ final Runtime runtime = Runtime.getRuntime(); -+ double usedMemory = runtime.totalMemory() - runtime.freeMemory(); -+ double freeMemory = runtime.maxMemory() - usedMemory; -+ if (this.avgFreeMemory == -1) { -+ this.avgFreeMemory = freeMemory; -+ } else { -+ this.avgFreeMemory = (this.avgFreeMemory * (59 / 60D)) + (freeMemory * (1 / 60D)); -+ } -+ -+ if (this.avgUsedMemory == -1) { -+ this.avgUsedMemory = usedMemory; -+ } else { -+ this.avgUsedMemory = (this.avgUsedMemory * (59 / 60D)) + (usedMemory * (1 / 60D)); -+ } -+ } -+ -+ long start = System.nanoTime(); -+ TimingsManager.tick(); -+ long diff = System.nanoTime() - start; -+ TIMINGS_TICK.addDiff(diff, null); -+ // addDiff for TIMINGS_TICK incremented this, bring it back down to 1 per tick. -+ record.setCurTickCount(record.getCurTickCount()-1); -+ -+ minuteData.setCurTickTotal(record.getCurTickTotal()); -+ minuteData.setCurTickCount(1); -+ -+ boolean violated = isViolated(); -+ minuteData.processTick(violated); -+ TIMINGS_TICK.processTick(violated); -+ processTick(violated); -+ -+ -+ if (TimingHistory.timedTicks % 1200 == 0) { -+ MINUTE_REPORTS.add(new TimingHistory.MinuteReport()); -+ TimingHistory.resetTicks(false); -+ minuteData.reset(); -+ } -+ if (TimingHistory.timedTicks % Timings.getHistoryInterval() == 0) { -+ TimingsManager.HISTORY.add(new TimingHistory()); -+ TimingsManager.resetTimings(); -+ } -+ Bukkit.getUnsafe().reportTimings(); -+ } -+ -+ boolean isViolated() { -+ return record.getCurTickTotal() > 50000000; -+ } -+} -diff --git a/src/main/java/co/aikar/timings/NullTimingHandler.java b/src/main/java/co/aikar/timings/NullTimingHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9b45ce887b9172f30302b83fe24b99b76b16dac3 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/NullTimingHandler.java -@@ -0,0 +1,68 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public final class NullTimingHandler implements Timing { -+ public static final Timing NULL = new NullTimingHandler(); -+ @NotNull -+ @Override -+ public Timing startTiming() { -+ return this; -+ } -+ -+ @Override -+ public void stopTiming() { -+ -+ } -+ -+ @NotNull -+ @Override -+ public Timing startTimingIfSync() { -+ return this; -+ } -+ -+ @Override -+ public void stopTimingIfSync() { -+ -+ } -+ -+ @Override -+ public void abort() { -+ -+ } -+ -+ @Nullable -+ @Override -+ public TimingHandler getTimingHandler() { -+ return null; -+ } -+ -+ @Override -+ public void close() { -+ -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimedEventExecutor.java b/src/main/java/co/aikar/timings/TimedEventExecutor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4e6e1b8e8aeb07e34536941d2cbfc25e5cfa6c27 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimedEventExecutor.java -@@ -0,0 +1,83 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.event.Event; -+import org.bukkit.event.EventException; -+import org.bukkit.event.Listener; -+import org.bukkit.plugin.EventExecutor; -+import org.bukkit.plugin.Plugin; -+ -+import java.lang.reflect.Method; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class TimedEventExecutor implements EventExecutor { -+ -+ private final EventExecutor executor; -+ private final Timing timings; -+ -+ /** -+ * Wraps an event executor and associates a timing handler to it. -+ * -+ * @param executor Executor to wrap -+ * @param plugin Owning plugin -+ * @param method EventHandler method -+ * @param eventClass Owning class -+ */ -+ public TimedEventExecutor(@NotNull EventExecutor executor, @NotNull Plugin plugin, @Nullable Method method, @NotNull Class eventClass) { -+ this.executor = executor; -+ String id; -+ -+ if (method == null) { -+ if (executor.getClass().getEnclosingClass() != null) { // Oh Skript, how we love you -+ method = executor.getClass().getEnclosingMethod(); -+ } -+ } -+ -+ if (method != null) { -+ id = method.getDeclaringClass().getName(); -+ } else { -+ id = executor.getClass().getName(); -+ } -+ -+ -+ final String eventName = eventClass.getSimpleName(); -+ boolean verbose = "BlockPhysicsEvent".equals(eventName); -+ this.timings = Timings.ofSafe(plugin, (verbose ? "## " : "") + -+ "Event: " + id + " (" + eventName + ")"); -+ } -+ -+ @Override -+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { -+ if (event.isAsynchronous() || !Timings.timingsEnabled || !Bukkit.isPrimaryThread()) { -+ executor.execute(listener, event); -+ return; -+ } -+ try (Timing ignored = timings.startTiming()){ -+ executor.execute(listener, event); -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/Timing.java b/src/main/java/co/aikar/timings/Timing.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a21e5ead5024fd0058c5e3302d8201dd249d32bc ---- /dev/null -+++ b/src/main/java/co/aikar/timings/Timing.java -@@ -0,0 +1,83 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Provides an ability to time sections of code within the Minecraft Server -+ */ -+public interface Timing extends AutoCloseable { -+ /** -+ * Starts timing the execution until {@link #stopTiming()} is called. -+ * -+ * @return Timing -+ */ -+ @NotNull -+ Timing startTiming(); -+ -+ /** -+ *

    Stops timing and records the data. Propagates the data up to group handlers.

    -+ * -+ * Will automatically be called when this Timing is used with try-with-resources -+ */ -+ void stopTiming(); -+ -+ /** -+ * Starts timing the execution until {@link #stopTiming()} is called. -+ * -+ * But only if we are on the primary thread. -+ * -+ * @return Timing -+ */ -+ @NotNull -+ Timing startTimingIfSync(); -+ -+ /** -+ *

    Stops timing and records the data. Propagates the data up to group handlers.

    -+ * -+ *

    Will automatically be called when this Timing is used with try-with-resources

    -+ * -+ * But only if we are on the primary thread. -+ */ -+ void stopTimingIfSync(); -+ -+ /** -+ * @deprecated Doesn't do anything - Removed -+ */ -+ @Deprecated -+ void abort(); -+ -+ /** -+ * Used internally to get the actual backing Handler in the case of delegated Handlers -+ * -+ * @return TimingHandler -+ */ -+ @Nullable -+ TimingHandler getTimingHandler(); -+ -+ @Override -+ void close(); -+} -diff --git a/src/main/java/co/aikar/timings/TimingData.java b/src/main/java/co/aikar/timings/TimingData.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a5d13a1e44edb861f45c83a9b4309fbf799d407d ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingData.java -@@ -0,0 +1,122 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import java.util.List; -+import org.jetbrains.annotations.NotNull; -+ -+import static co.aikar.util.JSONUtil.toArray; -+ -+/** -+ *

    Lightweight object for tracking timing data

    -+ * -+ * This is broken out to reduce memory usage -+ */ -+class TimingData { -+ private final int id; -+ private int count = 0; -+ private int lagCount = 0; -+ private long totalTime = 0; -+ private long lagTotalTime = 0; -+ private int curTickCount = 0; -+ private long curTickTotal = 0; -+ -+ TimingData(int id) { -+ this.id = id; -+ } -+ -+ private TimingData(TimingData data) { -+ this.id = data.id; -+ this.totalTime = data.totalTime; -+ this.lagTotalTime = data.lagTotalTime; -+ this.count = data.count; -+ this.lagCount = data.lagCount; -+ } -+ -+ void add(long diff) { -+ ++curTickCount; -+ curTickTotal += diff; -+ } -+ -+ void processTick(boolean violated) { -+ totalTime += curTickTotal; -+ count += curTickCount; -+ if (violated) { -+ lagTotalTime += curTickTotal; -+ lagCount += curTickCount; -+ } -+ curTickTotal = 0; -+ curTickCount = 0; -+ } -+ -+ void reset() { -+ count = 0; -+ lagCount = 0; -+ curTickTotal = 0; -+ curTickCount = 0; -+ totalTime = 0; -+ lagTotalTime = 0; -+ } -+ -+ protected TimingData clone() { -+ return new TimingData(this); -+ } -+ -+ @NotNull -+ List export() { -+ List list = toArray( -+ id, -+ count, -+ totalTime); -+ if (lagCount > 0) { -+ list.add(lagCount); -+ list.add(lagTotalTime); -+ } -+ return list; -+ } -+ -+ boolean hasData() { -+ return count > 0; -+ } -+ -+ long getTotalTime() { -+ return totalTime; -+ } -+ -+ int getCurTickCount() { -+ return curTickCount; -+ } -+ -+ void setCurTickCount(int curTickCount) { -+ this.curTickCount = curTickCount; -+ } -+ -+ long getCurTickTotal() { -+ return curTickTotal; -+ } -+ -+ void setCurTickTotal(long curTickTotal) { -+ this.curTickTotal = curTickTotal; -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingHandler.java b/src/main/java/co/aikar/timings/TimingHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..199789d56d22fcb1b77ebd56805cc28aa5a5ab0a ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingHandler.java -@@ -0,0 +1,226 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import co.aikar.util.LoadingIntMap; -+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -+ -+import java.util.ArrayDeque; -+import java.util.Deque; -+import java.util.concurrent.atomic.AtomicInteger; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+ -+import org.bukkit.Bukkit; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+class TimingHandler implements Timing { -+ -+ private static AtomicInteger idPool = new AtomicInteger(1); -+ private static Deque TIMING_STACK = new ArrayDeque<>(); -+ final int id = idPool.getAndIncrement(); -+ -+ final TimingIdentifier identifier; -+ private final boolean verbose; -+ -+ private final Int2ObjectOpenHashMap children = new LoadingIntMap<>(TimingData::new); -+ -+ final TimingData record; -+ private TimingHandler startParent; -+ private final TimingHandler groupHandler; -+ -+ private long start = 0; -+ private int timingDepth = 0; -+ private boolean added; -+ private boolean timed; -+ private boolean enabled; -+ -+ TimingHandler(@NotNull TimingIdentifier id) { -+ this.identifier = id; -+ this.verbose = id.name.startsWith("##"); -+ this.record = new TimingData(this.id); -+ this.groupHandler = id.groupHandler; -+ -+ TimingIdentifier.getGroup(id.group).handlers.add(this); -+ checkEnabled(); -+ } -+ -+ final void checkEnabled() { -+ enabled = Timings.timingsEnabled && (!verbose || Timings.verboseEnabled); -+ } -+ -+ void processTick(boolean violated) { -+ if (timingDepth != 0 || record.getCurTickCount() == 0) { -+ timingDepth = 0; -+ start = 0; -+ return; -+ } -+ -+ record.processTick(violated); -+ for (TimingData handler : children.values()) { -+ handler.processTick(violated); -+ } -+ } -+ -+ @NotNull -+ @Override -+ public Timing startTimingIfSync() { -+ startTiming(); -+ return this; -+ } -+ -+ @Override -+ public void stopTimingIfSync() { -+ stopTiming(); -+ } -+ -+ @NotNull -+ public Timing startTiming() { -+ if (!enabled || !Bukkit.isPrimaryThread()) { -+ return this; -+ } -+ if (++timingDepth == 1) { -+ startParent = TIMING_STACK.peekLast(); -+ start = System.nanoTime(); -+ } -+ TIMING_STACK.addLast(this); -+ return this; -+ } -+ -+ public void stopTiming() { -+ if (!enabled || timingDepth <= 0 || start == 0 || !Bukkit.isPrimaryThread()) { -+ return; -+ } -+ -+ popTimingStack(); -+ if (--timingDepth == 0) { -+ addDiff(System.nanoTime() - start, startParent); -+ startParent = null; -+ start = 0; -+ } -+ } -+ -+ private void popTimingStack() { -+ TimingHandler last; -+ while ((last = TIMING_STACK.removeLast()) != this) { -+ last.timingDepth = 0; -+ if ("Minecraft".equalsIgnoreCase(last.identifier.group)) { -+ Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Look above this for any errors and report this to Paper unless it has a plugin in the stack trace (" + last.identifier + " did not stopTiming)"); -+ } else { -+ Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Report this to the plugin " + last.identifier.group + " (Look for errors above this in the logs) (" + last.identifier + " did not stopTiming)", new Throwable()); -+ } -+ -+ boolean found = TIMING_STACK.contains(this); -+ if (!found) { -+ // We aren't even in the stack... Don't pop everything -+ TIMING_STACK.addLast(last); -+ break; -+ } -+ } -+ } -+ -+ @Override -+ public final void abort() { -+ -+ } -+ -+ void addDiff(long diff, @Nullable TimingHandler parent) { -+ if (parent != null) { -+ parent.children.get(id).add(diff); -+ } -+ -+ record.add(diff); -+ if (!added) { -+ added = true; -+ timed = true; -+ TimingsManager.HANDLERS.add(this); -+ } -+ if (groupHandler != null) { -+ groupHandler.addDiff(diff, parent); -+ groupHandler.children.get(id).add(diff); -+ } -+ } -+ -+ /** -+ * Reset this timer, setting all values to zero. -+ */ -+ void reset(boolean full) { -+ record.reset(); -+ if (full) { -+ timed = false; -+ } -+ start = 0; -+ timingDepth = 0; -+ added = false; -+ children.clear(); -+ checkEnabled(); -+ } -+ -+ @NotNull -+ @Override -+ public TimingHandler getTimingHandler() { -+ return this; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ return (this == o); -+ } -+ -+ @Override -+ public int hashCode() { -+ return id; -+ } -+ -+ /** -+ * This is simply for the Closeable interface so it can be used with try-with-resources () -+ */ -+ @Override -+ public void close() { -+ stopTimingIfSync(); -+ } -+ -+ public boolean isSpecial() { -+ return this == TimingsManager.FULL_SERVER_TICK || this == TimingsManager.TIMINGS_TICK; -+ } -+ -+ boolean isTimed() { -+ return timed; -+ } -+ -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @NotNull -+ TimingData[] cloneChildren() { -+ final TimingData[] clonedChildren = new TimingData[children.size()]; -+ int i = 0; -+ for (TimingData child : children.values()) { -+ clonedChildren[i++] = child.clone(); -+ } -+ return clonedChildren; -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingHistory.java b/src/main/java/co/aikar/timings/TimingHistory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ddaed81275fcc12d1671b668697acf318e96888b ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingHistory.java -@@ -0,0 +1,354 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import co.aikar.timings.TimingHistory.RegionData.RegionId; -+import com.google.common.base.Function; -+import com.google.common.collect.Sets; -+import org.bukkit.Bukkit; -+import org.bukkit.Chunk; -+import org.bukkit.Material; -+import org.bukkit.World; -+import org.bukkit.block.BlockState; -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.EntityType; -+import org.bukkit.entity.Player; -+import co.aikar.util.LoadingMap; -+import co.aikar.util.MRUMapCache; -+ -+import java.lang.management.ManagementFactory; -+import java.util.Collection; -+import java.util.EnumMap; -+import java.util.List; -+import java.util.Map; -+import java.util.Set; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import static co.aikar.timings.TimingsManager.FULL_SERVER_TICK; -+import static co.aikar.timings.TimingsManager.MINUTE_REPORTS; -+import static co.aikar.util.JSONUtil.*; -+ -+@SuppressWarnings({"deprecation", "SuppressionAnnotation", "Convert2Lambda", "Anonymous2MethodRef"}) -+public class TimingHistory { -+ public static long lastMinuteTime; -+ public static long timedTicks; -+ public static long playerTicks; -+ public static long entityTicks; -+ public static long tileEntityTicks; -+ public static long activatedEntityTicks; -+ private static int worldIdPool = 1; -+ static Map worldMap = LoadingMap.newHashMap(new Function() { -+ @NotNull -+ @Override -+ public Integer apply(@Nullable String input) { -+ return worldIdPool++; -+ } -+ }); -+ private final long endTime; -+ private final long startTime; -+ private final long totalTicks; -+ private final long totalTime; // Represents all time spent running the server this history -+ private final MinuteReport[] minuteReports; -+ -+ private final TimingHistoryEntry[] entries; -+ final Set tileEntityTypeSet = Sets.newHashSet(); -+ final Set entityTypeSet = Sets.newHashSet(); -+ private final Map worlds; -+ -+ TimingHistory() { -+ this.endTime = System.currentTimeMillis() / 1000; -+ this.startTime = TimingsManager.historyStart / 1000; -+ if (timedTicks % 1200 != 0 || MINUTE_REPORTS.isEmpty()) { -+ this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size() + 1]); -+ this.minuteReports[this.minuteReports.length - 1] = new MinuteReport(); -+ } else { -+ this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size()]); -+ } -+ long ticks = 0; -+ for (MinuteReport mp : this.minuteReports) { -+ ticks += mp.ticksRecord.timed; -+ } -+ this.totalTicks = ticks; -+ this.totalTime = FULL_SERVER_TICK.record.getTotalTime(); -+ this.entries = new TimingHistoryEntry[TimingsManager.HANDLERS.size()]; -+ -+ int i = 0; -+ for (TimingHandler handler : TimingsManager.HANDLERS) { -+ entries[i++] = new TimingHistoryEntry(handler); -+ } -+ -+ // Information about all loaded chunks/entities -+ //noinspection unchecked -+ this.worlds = toObjectMapper(Bukkit.getWorlds(), new Function() { -+ @NotNull -+ @Override -+ public JSONPair apply(World world) { -+ Map regions = LoadingMap.newHashMap(RegionData.LOADER); -+ -+ for (Chunk chunk : world.getLoadedChunks()) { -+ RegionData data = regions.get(new RegionId(chunk.getX(), chunk.getZ())); -+ -+ for (Entity entity : chunk.getEntities()) { -+ if (entity == null) { -+ Bukkit.getLogger().warning("Null entity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ()); -+ continue; -+ } -+ -+ data.entityCounts.get(entity.getType()).increment(); -+ } -+ -+ for (BlockState tileEntity : chunk.getTileEntities()) { -+ if (tileEntity == null) { -+ Bukkit.getLogger().warning("Null tileentity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ()); -+ continue; -+ } -+ -+ data.tileEntityCounts.get(tileEntity.getBlock().getType()).increment(); -+ } -+ } -+ return pair( -+ worldMap.get(world.getName()), -+ toArrayMapper(regions.values(),new Function() { -+ @NotNull -+ @Override -+ public Object apply(RegionData input) { -+ return toArray( -+ input.regionId.x, -+ input.regionId.z, -+ toObjectMapper(input.entityCounts.entrySet(), -+ new Function, JSONPair>() { -+ @NotNull -+ @Override -+ public JSONPair apply(Map.Entry entry) { -+ entityTypeSet.add(entry.getKey()); -+ return pair( -+ String.valueOf(entry.getKey().ordinal()), -+ entry.getValue().count() -+ ); -+ } -+ } -+ ), -+ toObjectMapper(input.tileEntityCounts.entrySet(), -+ new Function, JSONPair>() { -+ @NotNull -+ @Override -+ public JSONPair apply(Map.Entry entry) { -+ tileEntityTypeSet.add(entry.getKey()); -+ return pair( -+ String.valueOf(entry.getKey().ordinal()), -+ entry.getValue().count() -+ ); -+ } -+ } -+ ) -+ ); -+ } -+ }) -+ ); -+ } -+ }); -+ } -+ static class RegionData { -+ final RegionId regionId; -+ @SuppressWarnings("Guava") -+ static Function LOADER = new Function() { -+ @NotNull -+ @Override -+ public RegionData apply(@NotNull RegionId id) { -+ return new RegionData(id); -+ } -+ }; -+ RegionData(@NotNull RegionId id) { -+ this.regionId = id; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) { -+ return true; -+ } -+ if (o == null || getClass() != o.getClass()) { -+ return false; -+ } -+ -+ RegionData that = (RegionData) o; -+ -+ return regionId.equals(that.regionId); -+ -+ } -+ -+ @Override -+ public int hashCode() { -+ return regionId.hashCode(); -+ } -+ -+ @SuppressWarnings("unchecked") -+ final Map entityCounts = MRUMapCache.of(LoadingMap.of( -+ new EnumMap(EntityType.class), k -> new Counter() -+ )); -+ @SuppressWarnings("unchecked") -+ final Map tileEntityCounts = MRUMapCache.of(LoadingMap.of( -+ new EnumMap(Material.class), k -> new Counter() -+ )); -+ -+ static class RegionId { -+ final int x, z; -+ final long regionId; -+ RegionId(int x, int z) { -+ this.x = x >> 5 << 5; -+ this.z = z >> 5 << 5; -+ this.regionId = ((long) (this.x) << 32) + (this.z >> 5 << 5) - Integer.MIN_VALUE; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ -+ RegionId regionId1 = (RegionId) o; -+ -+ return regionId == regionId1.regionId; -+ -+ } -+ -+ @Override -+ public int hashCode() { -+ return (int) (regionId ^ (regionId >>> 32)); -+ } -+ } -+ } -+ static void resetTicks(boolean fullReset) { -+ if (fullReset) { -+ // Non full is simply for 1 minute reports -+ timedTicks = 0; -+ } -+ lastMinuteTime = System.nanoTime(); -+ playerTicks = 0; -+ tileEntityTicks = 0; -+ entityTicks = 0; -+ activatedEntityTicks = 0; -+ } -+ -+ @NotNull -+ Object export() { -+ return createObject( -+ pair("s", startTime), -+ pair("e", endTime), -+ pair("tk", totalTicks), -+ pair("tm", totalTime), -+ pair("w", worlds), -+ pair("h", toArrayMapper(entries, new Function() { -+ @Nullable -+ @Override -+ public Object apply(TimingHistoryEntry entry) { -+ TimingData record = entry.data; -+ if (!record.hasData()) { -+ return null; -+ } -+ return entry.export(); -+ } -+ })), -+ pair("mp", toArrayMapper(minuteReports, new Function() { -+ @NotNull -+ @Override -+ public Object apply(MinuteReport input) { -+ return input.export(); -+ } -+ })) -+ ); -+ } -+ -+ static class MinuteReport { -+ final long time = System.currentTimeMillis() / 1000; -+ -+ final TicksRecord ticksRecord = new TicksRecord(); -+ final PingRecord pingRecord = new PingRecord(); -+ final TimingData fst = TimingsManager.FULL_SERVER_TICK.minuteData.clone(); -+ final double tps = 1E9 / ( System.nanoTime() - lastMinuteTime ) * ticksRecord.timed; -+ final double usedMemory = TimingsManager.FULL_SERVER_TICK.avgUsedMemory; -+ final double freeMemory = TimingsManager.FULL_SERVER_TICK.avgFreeMemory; -+ final double loadAvg = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage(); -+ -+ @NotNull -+ List export() { -+ return toArray( -+ time, -+ Math.round(tps * 100D) / 100D, -+ Math.round(pingRecord.avg * 100D) / 100D, -+ fst.export(), -+ toArray(ticksRecord.timed, -+ ticksRecord.player, -+ ticksRecord.entity, -+ ticksRecord.activatedEntity, -+ ticksRecord.tileEntity -+ ), -+ usedMemory, -+ freeMemory, -+ loadAvg -+ ); -+ } -+ } -+ -+ private static class TicksRecord { -+ final long timed; -+ final long player; -+ final long entity; -+ final long tileEntity; -+ final long activatedEntity; -+ -+ TicksRecord() { -+ timed = timedTicks - (TimingsManager.MINUTE_REPORTS.size() * 1200); -+ player = playerTicks; -+ entity = entityTicks; -+ tileEntity = tileEntityTicks; -+ activatedEntity = activatedEntityTicks; -+ } -+ -+ } -+ -+ private static class PingRecord { -+ final double avg; -+ -+ PingRecord() { -+ final Collection onlinePlayers = Bukkit.getOnlinePlayers(); -+ int totalPing = 0; -+ for (Player player : onlinePlayers) { -+ totalPing += player.spigot().getPing(); -+ } -+ avg = onlinePlayers.isEmpty() ? 0 : totalPing / onlinePlayers.size(); -+ } -+ } -+ -+ -+ private static class Counter { -+ private int count = 0; -+ public int increment() { -+ return ++count; -+ } -+ public int count() { -+ return count; -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingHistoryEntry.java b/src/main/java/co/aikar/timings/TimingHistoryEntry.java -new file mode 100644 -index 0000000000000000000000000000000000000000..86d5ac6bd0d7d0003688761aceb3f3343575319f ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingHistoryEntry.java -@@ -0,0 +1,58 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import com.google.common.base.Function; -+ -+import java.util.List; -+import org.jetbrains.annotations.NotNull; -+ -+import static co.aikar.util.JSONUtil.toArrayMapper; -+ -+class TimingHistoryEntry { -+ final TimingData data; -+ private final TimingData[] children; -+ -+ TimingHistoryEntry(@NotNull TimingHandler handler) { -+ this.data = handler.record.clone(); -+ children = handler.cloneChildren(); -+ } -+ -+ @NotNull -+ List export() { -+ List result = data.export(); -+ if (children.length > 0) { -+ result.add( -+ toArrayMapper(children, new Function() { -+ @NotNull -+ @Override -+ public Object apply(TimingData child) { -+ return child.export(); -+ } -+ }) -+ ); -+ } -+ return result; -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingIdentifier.java b/src/main/java/co/aikar/timings/TimingIdentifier.java -new file mode 100644 -index 0000000000000000000000000000000000000000..df142a89b8c43acb81eb383eac0ef048a1f49a6e ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingIdentifier.java -@@ -0,0 +1,116 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import co.aikar.util.LoadingMap; -+ -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+import java.util.Map; -+import java.util.Objects; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.atomic.AtomicInteger; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ *

    Used as a basis for fast HashMap key comparisons for the Timing Map.

    -+ * -+ * This class uses interned strings giving us the ability to do an identity check instead of equals() on the strings -+ */ -+final class TimingIdentifier { -+ /** -+ * Holds all groups. Autoloads on request for a group by name. -+ */ -+ static final Map GROUP_MAP = LoadingMap.of(new ConcurrentHashMap<>(64, .5F), TimingGroup::new); -+ private static final TimingGroup DEFAULT_GROUP = getGroup("Minecraft"); -+ final String group; -+ final String name; -+ final TimingHandler groupHandler; -+ private final int hashCode; -+ -+ TimingIdentifier(@Nullable String group, @NotNull String name, @Nullable Timing groupHandler) { -+ this.group = group != null ? group: DEFAULT_GROUP.name; -+ this.name = name; -+ this.groupHandler = groupHandler != null ? groupHandler.getTimingHandler() : null; -+ this.hashCode = (31 * this.group.hashCode()) + this.name.hashCode(); -+ } -+ -+ @NotNull -+ static TimingGroup getGroup(@Nullable String groupName) { -+ if (groupName == null) { -+ //noinspection ConstantConditions -+ return DEFAULT_GROUP; -+ } -+ -+ return GROUP_MAP.get(groupName); -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (o == null) { -+ return false; -+ } -+ -+ TimingIdentifier that = (TimingIdentifier) o; -+ return Objects.equals(group, that.group) && Objects.equals(name, that.name); -+ } -+ -+ @Override -+ public int hashCode() { -+ return hashCode; -+ } -+ -+ @Override -+ public String toString() { -+ return "TimingIdentifier{id=" + group + ":" + name +'}'; -+ } -+ -+ static class TimingGroup { -+ -+ private static AtomicInteger idPool = new AtomicInteger(1); -+ final int id = idPool.getAndIncrement(); -+ -+ final String name; -+ final List handlers = Collections.synchronizedList(new ArrayList<>(64)); -+ -+ private TimingGroup(String name) { -+ this.name = name; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ TimingGroup that = (TimingGroup) o; -+ return id == that.id; -+ } -+ -+ @Override -+ public int hashCode() { -+ return id; -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/Timings.java b/src/main/java/co/aikar/timings/Timings.java -new file mode 100644 -index 0000000000000000000000000000000000000000..da76e1aaee1dee794e38ddd4e0a28e0071e90bbf ---- /dev/null -+++ b/src/main/java/co/aikar/timings/Timings.java -@@ -0,0 +1,296 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import com.google.common.base.Preconditions; -+import com.google.common.collect.EvictingQueue; -+import com.google.common.collect.Lists; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Bukkit; -+import org.bukkit.command.CommandSender; -+import org.bukkit.plugin.Plugin; -+ -+import java.util.List; -+import java.util.Queue; -+import java.util.logging.Level; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+@SuppressWarnings({"UnusedDeclaration", "WeakerAccess", "SameParameterValue"}) -+public final class Timings { -+ -+ final static List requestingReport = Lists.newArrayList(); -+ private static final int MAX_HISTORY_FRAMES = 12; -+ public static final Timing NULL_HANDLER = new NullTimingHandler(); -+ static boolean timingsEnabled = false; -+ static boolean verboseEnabled = false; -+ private static int historyInterval = -1; -+ private static int historyLength = -1; -+ -+ private Timings() {} -+ -+ /** -+ * Returns a Timing for a plugin corresponding to a name. -+ * -+ * @param plugin Plugin to own the Timing -+ * @param name Name of Timing -+ * @return Handler -+ */ -+ @NotNull -+ public static Timing of(@NotNull Plugin plugin, @NotNull String name) { -+ Timing pluginHandler = null; -+ if (plugin != null) { -+ pluginHandler = ofSafe(plugin.getName(), "Combined Total", TimingsManager.PLUGIN_GROUP_HANDLER); -+ } -+ return of(plugin, name, pluginHandler); -+ } -+ -+ /** -+ *

    Returns a handler that has a groupHandler timer handler. Parent timers should not have their -+ * start/stop methods called directly, as the children will call it for you.

    -+ * -+ * Parent Timers are used to group multiple subsections together and get a summary of them combined -+ * Parent Handler can not be changed after first call -+ * -+ * @param plugin Plugin to own the Timing -+ * @param name Name of Timing -+ * @param groupHandler Parent handler to mirror .start/stop calls to -+ * @return Timing Handler -+ */ -+ @NotNull -+ public static Timing of(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) { -+ Preconditions.checkNotNull(plugin, "Plugin can not be null"); -+ return TimingsManager.getHandler(plugin.getName(), name, groupHandler); -+ } -+ -+ /** -+ * Returns a Timing object after starting it, useful for Java7 try-with-resources. -+ * -+ * try (Timing ignored = Timings.ofStart(plugin, someName)) { -+ * // timed section -+ * } -+ * -+ * @param plugin Plugin to own the Timing -+ * @param name Name of Timing -+ * @return Timing Handler -+ */ -+ @NotNull -+ public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name) { -+ return ofStart(plugin, name, null); -+ } -+ -+ /** -+ * Returns a Timing object after starting it, useful for Java7 try-with-resources. -+ * -+ * try (Timing ignored = Timings.ofStart(plugin, someName, groupHandler)) { -+ * // timed section -+ * } -+ * -+ * @param plugin Plugin to own the Timing -+ * @param name Name of Timing -+ * @param groupHandler Parent handler to mirror .start/stop calls to -+ * @return Timing Handler -+ */ -+ @NotNull -+ public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) { -+ Timing timing = of(plugin, name, groupHandler); -+ timing.startTiming(); -+ return timing; -+ } -+ -+ /** -+ * Gets whether or not the Spigot Timings system is enabled -+ * -+ * @return Enabled or not -+ */ -+ public static boolean isTimingsEnabled() { -+ return timingsEnabled; -+ } -+ -+ /** -+ *

    Sets whether or not the Spigot Timings system should be enabled

    -+ * -+ * Calling this will reset timing data. -+ * -+ * @param enabled Should timings be reported -+ */ -+ public static void setTimingsEnabled(boolean enabled) { -+ timingsEnabled = enabled; -+ reset(); -+ } -+ -+ /** -+ *

    Sets whether or not the Timings should monitor at Verbose level.

    -+ * -+ *

    When Verbose is disabled, high-frequency timings will not be available.

    -+ * -+ * @return Enabled or not -+ */ -+ public static boolean isVerboseTimingsEnabled() { -+ return verboseEnabled; -+ } -+ -+ /** -+ *

    Sets whether or not the Timings should monitor at Verbose level.

    -+ * -+ * When Verbose is disabled, high-frequency timings will not be available. -+ * Calling this will reset timing data. -+ * -+ * @param enabled Should high-frequency timings be reported -+ */ -+ public static void setVerboseTimingsEnabled(boolean enabled) { -+ verboseEnabled = enabled; -+ TimingsManager.needsRecheckEnabled = true; -+ } -+ -+ /** -+ *

    Gets the interval between Timing History report generation.

    -+ * -+ * Defaults to 5 minutes (6000 ticks) -+ * -+ * @return Interval in ticks -+ */ -+ public static int getHistoryInterval() { -+ return historyInterval; -+ } -+ -+ /** -+ *

    Sets the interval between Timing History report generations.

    -+ * -+ *

    Defaults to 5 minutes (6000 ticks)

    -+ * -+ * This will recheck your history length, so lowering this value will lower your -+ * history length if you need more than 60 history windows. -+ * -+ * @param interval Interval in ticks -+ */ -+ public static void setHistoryInterval(int interval) { -+ historyInterval = Math.max(20*60, interval); -+ // Recheck the history length with the new Interval -+ if (historyLength != -1) { -+ setHistoryLength(historyLength); -+ } -+ } -+ -+ /** -+ * Gets how long in ticks Timings history is kept for the server. -+ * -+ * Defaults to 1 hour (72000 ticks) -+ * -+ * @return Duration in Ticks -+ */ -+ public static int getHistoryLength() { -+ return historyLength; -+ } -+ -+ /** -+ * Sets how long Timing History reports are kept for the server. -+ * -+ * Defaults to 1 hours(72000 ticks) -+ * -+ * This value is capped at a maximum of getHistoryInterval() * MAX_HISTORY_FRAMES (12) -+ * -+ * Will not reset Timing Data but may truncate old history if the new length is less than old length. -+ * -+ * @param length Duration in ticks -+ */ -+ public static void setHistoryLength(int length) { -+ // Cap at 12 History Frames, 1 hour at 5 minute frames. -+ int maxLength = historyInterval * MAX_HISTORY_FRAMES; -+ // For special cases of servers with special permission to bypass the max. -+ // This max helps keep data file sizes reasonable for processing on Aikar's Timing parser side. -+ // Setting this will not help you bypass the max unless Aikar has added an exception on the API side. -+ if (System.getProperty("timings.bypassMax") != null) { -+ maxLength = Integer.MAX_VALUE; -+ } -+ historyLength = Math.max(Math.min(maxLength, length), historyInterval); -+ Queue oldQueue = TimingsManager.HISTORY; -+ int frames = (getHistoryLength() / getHistoryInterval()); -+ if (length > maxLength) { -+ Bukkit.getLogger().log(Level.WARNING, "Timings Length too high. Requested " + length + ", max is " + maxLength + ". To get longer history, you must increase your interval. Set Interval to " + Math.ceil(length / MAX_HISTORY_FRAMES) + " to achieve this length."); -+ } -+ TimingsManager.HISTORY = EvictingQueue.create(frames); -+ TimingsManager.HISTORY.addAll(oldQueue); -+ } -+ -+ /** -+ * Resets all Timing Data -+ */ -+ public static void reset() { -+ TimingsManager.reset(); -+ } -+ -+ /** -+ * Generates a report and sends it to the specified command sender. -+ * -+ * If sender is null, ConsoleCommandSender will be used. -+ * @param sender The sender to send to, or null to use the ConsoleCommandSender -+ */ -+ public static void generateReport(@Nullable CommandSender sender) { -+ if (sender == null) { -+ sender = Bukkit.getConsoleSender(); -+ } -+ requestingReport.add(sender); -+ } -+ -+ /** -+ * Generates a report and sends it to the specified listener. -+ * Use with {@link org.bukkit.command.BufferedCommandSender} to get full response when done! -+ * @param sender The listener to send responses too. -+ */ -+ public static void generateReport(@NotNull TimingsReportListener sender) { -+ Validate.notNull(sender); -+ requestingReport.add(sender); -+ } -+ -+ /* -+ ================= -+ Protected API: These are for internal use only in Bukkit/CraftBukkit -+ These do not have isPrimaryThread() checks in the startTiming/stopTiming -+ ================= -+ */ -+ @NotNull -+ static TimingHandler ofSafe(@NotNull String name) { -+ return ofSafe(null, name, null); -+ } -+ -+ @NotNull -+ static Timing ofSafe(@Nullable Plugin plugin, @NotNull String name) { -+ Timing pluginHandler = null; -+ if (plugin != null) { -+ pluginHandler = ofSafe(plugin.getName(), "Combined Total", TimingsManager.PLUGIN_GROUP_HANDLER); -+ } -+ return ofSafe(plugin != null ? plugin.getName() : "Minecraft - Invalid Plugin", name, pluginHandler); -+ } -+ -+ @NotNull -+ static TimingHandler ofSafe(@NotNull String name, @Nullable Timing groupHandler) { -+ return ofSafe(null, name, groupHandler); -+ } -+ -+ @NotNull -+ static TimingHandler ofSafe(@Nullable String groupName, @NotNull String name, @Nullable Timing groupHandler) { -+ return TimingsManager.getHandler(groupName, name, groupHandler); -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingsCommand.java b/src/main/java/co/aikar/timings/TimingsCommand.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f7c2245a310a084367ff25db539b3c967d5cb141 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingsCommand.java -@@ -0,0 +1,119 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import com.google.common.collect.ImmutableList; -+import org.apache.commons.lang.Validate; -+import org.bukkit.ChatColor; -+import org.bukkit.command.CommandSender; -+import org.bukkit.command.defaults.BukkitCommand; -+import org.bukkit.util.StringUtil; -+ -+import java.util.ArrayList; -+import java.util.List; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+ -+public class TimingsCommand extends BukkitCommand { -+ private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste", "verbon", "verboff"); -+ private long lastResetAttempt = 0; -+ -+ public TimingsCommand(@NotNull String name) { -+ super(name); -+ this.description = "Manages Spigot Timings data to see performance of the server."; -+ this.usageMessage = "/timings "; -+ this.setPermission("bukkit.command.timings"); -+ } -+ -+ @Override -+ public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { -+ if (!testPermission(sender)) { -+ return true; -+ } -+ if (args.length < 1) { -+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -+ return true; -+ } -+ final String arg = args[0]; -+ if ("on".equalsIgnoreCase(arg)) { -+ Timings.setTimingsEnabled(true); -+ sender.sendMessage("Enabled Timings & Reset"); -+ return true; -+ } else if ("off".equalsIgnoreCase(arg)) { -+ Timings.setTimingsEnabled(false); -+ sender.sendMessage("Disabled Timings"); -+ return true; -+ } -+ -+ if (!Timings.isTimingsEnabled()) { -+ sender.sendMessage("Please enable timings by typing /timings on"); -+ return true; -+ } -+ -+ long now = System.currentTimeMillis(); -+ if ("verbon".equalsIgnoreCase(arg)) { -+ Timings.setVerboseTimingsEnabled(true); -+ sender.sendMessage("Enabled Verbose Timings"); -+ return true; -+ } else if ("verboff".equalsIgnoreCase(arg)) { -+ Timings.setVerboseTimingsEnabled(false); -+ sender.sendMessage("Disabled Verbose Timings"); -+ return true; -+ } else if ("reset".equalsIgnoreCase(arg)) { -+ if (now - lastResetAttempt < 30000) { -+ TimingsManager.reset(); -+ sender.sendMessage(ChatColor.RED + "Timings reset. Please wait 5-10 minutes before using /timings report."); -+ } else { -+ lastResetAttempt = now; -+ sender.sendMessage(ChatColor.RED + "WARNING: Timings v2 should not be reset. If you are encountering lag, please wait 3 minutes and then issue a report. The best timings will include 10+ minutes, with data before and after your lag period. If you really want to reset, run this command again within 30 seconds."); -+ } -+ } else if ( -+ "paste".equalsIgnoreCase(arg) || -+ "report".equalsIgnoreCase(arg) || -+ "get".equalsIgnoreCase(arg) || -+ "merged".equalsIgnoreCase(arg) || -+ "separate".equalsIgnoreCase(arg) -+ ) { -+ Timings.generateReport(sender); -+ } else { -+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -+ } -+ return true; -+ } -+ -+ @NotNull -+ @Override -+ public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { -+ Validate.notNull(sender, "Sender cannot be null"); -+ Validate.notNull(args, "Arguments cannot be null"); -+ Validate.notNull(alias, "Alias cannot be null"); -+ -+ if (args.length == 1) { -+ return StringUtil.copyPartialMatches(args[0], TIMINGS_SUBCOMMANDS, -+ new ArrayList(TIMINGS_SUBCOMMANDS.size())); -+ } -+ return ImmutableList.of(); -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingsManager.java b/src/main/java/co/aikar/timings/TimingsManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ef824d701c97cad8b31e76ad98c94fc4367a7eda ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingsManager.java -@@ -0,0 +1,188 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import co.aikar.util.LoadingMap; -+import com.google.common.collect.EvictingQueue; -+import org.bukkit.Bukkit; -+import org.bukkit.Server; -+import org.bukkit.command.Command; -+import org.bukkit.plugin.Plugin; -+import org.bukkit.plugin.java.PluginClassLoader; -+ -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.logging.Level; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public final class TimingsManager { -+ static final Map TIMING_MAP = LoadingMap.of( -+ new ConcurrentHashMap<>(4096, .5F), TimingHandler::new -+ ); -+ public static final FullServerTickHandler FULL_SERVER_TICK = new FullServerTickHandler(); -+ public static final TimingHandler TIMINGS_TICK = Timings.ofSafe("Timings Tick", FULL_SERVER_TICK); -+ public static final Timing PLUGIN_GROUP_HANDLER = Timings.ofSafe("Plugins"); -+ public static List hiddenConfigs = new ArrayList(); -+ public static boolean privacy = false; -+ -+ static final List HANDLERS = new ArrayList<>(1024); -+ static final List MINUTE_REPORTS = new ArrayList<>(64); -+ -+ static EvictingQueue HISTORY = EvictingQueue.create(12); -+ static long timingStart = 0; -+ static long historyStart = 0; -+ static boolean needsFullReset = false; -+ static boolean needsRecheckEnabled = false; -+ -+ private TimingsManager() {} -+ -+ /** -+ * Resets all timing data on the next tick -+ */ -+ static void reset() { -+ needsFullReset = true; -+ } -+ -+ /** -+ * Ticked every tick by CraftBukkit to count the number of times a timer -+ * caused TPS loss. -+ */ -+ static void tick() { -+ if (Timings.timingsEnabled) { -+ boolean violated = FULL_SERVER_TICK.isViolated(); -+ -+ for (TimingHandler handler : HANDLERS) { -+ if (handler.isSpecial()) { -+ // We manually call this -+ continue; -+ } -+ handler.processTick(violated); -+ } -+ -+ TimingHistory.playerTicks += Bukkit.getOnlinePlayers().size(); -+ TimingHistory.timedTicks++; -+ // Generate TPS/Ping/Tick reports every minute -+ } -+ } -+ static void stopServer() { -+ Timings.timingsEnabled = false; -+ recheckEnabled(); -+ } -+ static void recheckEnabled() { -+ synchronized (TIMING_MAP) { -+ for (TimingHandler timings : TIMING_MAP.values()) { -+ timings.checkEnabled(); -+ } -+ } -+ needsRecheckEnabled = false; -+ } -+ static void resetTimings() { -+ if (needsFullReset) { -+ // Full resets need to re-check every handlers enabled state -+ // Timing map can be modified from async so we must sync on it. -+ synchronized (TIMING_MAP) { -+ for (TimingHandler timings : TIMING_MAP.values()) { -+ timings.reset(true); -+ } -+ } -+ Bukkit.getLogger().log(Level.INFO, "Timings Reset"); -+ HISTORY.clear(); -+ needsFullReset = false; -+ needsRecheckEnabled = false; -+ timingStart = System.currentTimeMillis(); -+ } else { -+ // Soft resets only need to act on timings that have done something -+ // Handlers can only be modified on main thread. -+ for (TimingHandler timings : HANDLERS) { -+ timings.reset(false); -+ } -+ } -+ -+ HANDLERS.clear(); -+ MINUTE_REPORTS.clear(); -+ -+ TimingHistory.resetTicks(true); -+ historyStart = System.currentTimeMillis(); -+ } -+ -+ @NotNull -+ static TimingHandler getHandler(@Nullable String group, @NotNull String name, @Nullable Timing parent) { -+ return TIMING_MAP.get(new TimingIdentifier(group, name, parent)); -+ } -+ -+ -+ /** -+ *

    Due to access restrictions, we need a helper method to get a Command TimingHandler with String group

    -+ * -+ * Plugins should never call this -+ * -+ * @param pluginName Plugin this command is associated with -+ * @param command Command to get timings for -+ * @return TimingHandler -+ */ -+ @NotNull -+ public static Timing getCommandTiming(@Nullable String pluginName, @NotNull Command command) { -+ Plugin plugin = null; -+ final Server server = Bukkit.getServer(); -+ if (!( server == null || pluginName == null || -+ "minecraft".equals(pluginName) || "bukkit".equals(pluginName) || -+ "spigot".equalsIgnoreCase(pluginName) || "paper".equals(pluginName) -+ )) { -+ plugin = server.getPluginManager().getPlugin(pluginName); -+ } -+ if (plugin == null) { -+ // Plugin is passing custom fallback prefix, try to look up by class loader -+ plugin = getPluginByClassloader(command.getClass()); -+ } -+ if (plugin == null) { -+ return Timings.ofSafe("Command: " + pluginName + ":" + command.getTimingName()); -+ } -+ -+ return Timings.ofSafe(plugin, "Command: " + pluginName + ":" + command.getTimingName()); -+ } -+ -+ /** -+ * Looks up the class loader for the specified class, and if it is a PluginClassLoader, return the -+ * Plugin that created this class. -+ * -+ * @param clazz Class to check -+ * @return Plugin if created by a plugin -+ */ -+ @Nullable -+ public static Plugin getPluginByClassloader(@Nullable Class clazz) { -+ if (clazz == null) { -+ return null; -+ } -+ final ClassLoader classLoader = clazz.getClassLoader(); -+ if (classLoader instanceof PluginClassLoader) { -+ PluginClassLoader pluginClassLoader = (PluginClassLoader) classLoader; -+ return pluginClassLoader.getPlugin(); -+ } -+ return null; -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingsReportListener.java b/src/main/java/co/aikar/timings/TimingsReportListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ef58a6c00f444bd498a2d8fc4e457236f393954f ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingsReportListener.java -@@ -0,0 +1,77 @@ -+package co.aikar.timings; -+ -+import com.google.common.collect.Lists; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Bukkit; -+import org.bukkit.command.CommandSender; -+import org.bukkit.command.ConsoleCommandSender; -+import org.bukkit.command.MessageCommandSender; -+import org.bukkit.command.RemoteConsoleCommandSender; -+ -+import java.util.List; -+import java.util.UUID; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+@SuppressWarnings("WeakerAccess") -+public class TimingsReportListener implements MessageCommandSender { -+ private final List senders; -+ private final Runnable onDone; -+ private String timingsURL; -+ -+ public TimingsReportListener(@NotNull CommandSender senders) { -+ this(senders, null); -+ } -+ public TimingsReportListener(@NotNull CommandSender sender, @Nullable Runnable onDone) { -+ this(Lists.newArrayList(sender), onDone); -+ } -+ public TimingsReportListener(@NotNull List senders) { -+ this(senders, null); -+ } -+ public TimingsReportListener(@NotNull List senders, @Nullable Runnable onDone) { -+ Validate.notNull(senders); -+ Validate.notEmpty(senders); -+ -+ this.senders = Lists.newArrayList(senders); -+ this.onDone = onDone; -+ } -+ -+ @Nullable -+ public String getTimingsURL() { -+ return timingsURL; -+ } -+ -+ public void done() { -+ done(null); -+ } -+ -+ public void done(@Nullable String url) { -+ this.timingsURL = url; -+ if (onDone != null) { -+ onDone.run(); -+ } -+ for (CommandSender sender : senders) { -+ if (sender instanceof TimingsReportListener) { -+ ((TimingsReportListener) sender).done(); -+ } -+ } -+ } -+ -+ @Override -+ public void sendMessage(@NotNull String message) { -+ senders.forEach((sender) -> sender.sendMessage(message)); -+ } -+ -+ public void addConsoleIfNeeded() { -+ boolean hasConsole = false; -+ for (CommandSender sender : this.senders) { -+ if (sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender) { -+ hasConsole = true; -+ } -+ } -+ if (!hasConsole) { -+ this.senders.add(Bukkit.getConsoleSender()); -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/UnsafeTimingHandler.java b/src/main/java/co/aikar/timings/UnsafeTimingHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..632c4961515f5052551f841cfa840e60bba7a257 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/UnsafeTimingHandler.java -@@ -0,0 +1,53 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import org.bukkit.Bukkit; -+import org.jetbrains.annotations.NotNull; -+ -+class UnsafeTimingHandler extends TimingHandler { -+ -+ UnsafeTimingHandler(@NotNull TimingIdentifier id) { -+ super(id); -+ } -+ -+ private static void checkThread() { -+ if (!Bukkit.isPrimaryThread()) { -+ throw new IllegalStateException("Calling Timings from Async Operation"); -+ } -+ } -+ -+ @NotNull -+ @Override -+ public Timing startTiming() { -+ checkThread(); -+ return super.startTiming(); -+ } -+ -+ @Override -+ public void stopTiming() { -+ checkThread(); -+ super.stopTiming(); -+ } -+} -diff --git a/src/main/java/co/aikar/util/Counter.java b/src/main/java/co/aikar/util/Counter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..eff63c371c39e21a5a9cb5af8c2dcf78a60dd52b ---- /dev/null -+++ b/src/main/java/co/aikar/util/Counter.java -@@ -0,0 +1,38 @@ -+package co.aikar.util; -+ -+import com.google.common.collect.ForwardingMap; -+ -+import java.util.HashMap; -+import java.util.Map; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class Counter extends ForwardingMap { -+ private final Map counts = new HashMap<>(); -+ -+ public long decrement(@Nullable T key) { -+ return increment(key, -1); -+ } -+ public long increment(@Nullable T key) { -+ return increment(key, 1); -+ } -+ public long decrement(@Nullable T key, long amount) { -+ return increment(key, -amount); -+ } -+ public long increment(@Nullable T key, long amount) { -+ Long count = this.getCount(key); -+ count += amount; -+ this.counts.put(key, count); -+ return count; -+ } -+ -+ public long getCount(@Nullable T key) { -+ return this.counts.getOrDefault(key, 0L); -+ } -+ -+ @NotNull -+ @Override -+ protected Map delegate() { -+ return this.counts; -+ } -+} -diff --git a/src/main/java/co/aikar/util/JSONUtil.java b/src/main/java/co/aikar/util/JSONUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..190bf0598442c89c2a1c93ad7c8c1a29797304ae ---- /dev/null -+++ b/src/main/java/co/aikar/util/JSONUtil.java -@@ -0,0 +1,140 @@ -+package co.aikar.util; -+ -+import com.google.common.base.Function; -+import com.google.common.collect.Lists; -+import com.google.common.collect.Maps; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+import org.json.simple.JSONArray; -+import org.json.simple.JSONObject; -+ -+import java.util.ArrayList; -+import java.util.LinkedHashMap; -+import java.util.List; -+import java.util.Map; -+ -+/** -+ * Provides Utility methods that assist with generating JSON Objects -+ */ -+@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) -+public final class JSONUtil { -+ private JSONUtil() {} -+ -+ /** -+ * Creates a key/value "JSONPair" object -+ * -+ * @param key Key to use -+ * @param obj Value to use -+ * @return JSONPair -+ */ -+ @NotNull -+ public static JSONPair pair(@NotNull String key, @Nullable Object obj) { -+ return new JSONPair(key, obj); -+ } -+ -+ @NotNull -+ public static JSONPair pair(long key, @Nullable Object obj) { -+ return new JSONPair(String.valueOf(key), obj); -+ } -+ -+ /** -+ * Creates a new JSON object from multiple JSONPair key/value pairs -+ * -+ * @param data JSONPairs -+ * @return Map -+ */ -+ @NotNull -+ public static Map createObject(@NotNull JSONPair... data) { -+ return appendObjectData(new LinkedHashMap(), data); -+ } -+ -+ /** -+ * This appends multiple key/value Obj pairs into a JSON Object -+ * -+ * @param parent Map to be appended to -+ * @param data Data to append -+ * @return Map -+ */ -+ @NotNull -+ public static Map appendObjectData(@NotNull Map parent, @NotNull JSONPair... data) { -+ for (JSONPair JSONPair : data) { -+ parent.put(JSONPair.key, JSONPair.val); -+ } -+ return parent; -+ } -+ -+ /** -+ * This builds a JSON array from a set of data -+ * -+ * @param data Data to build JSON array from -+ * @return List -+ */ -+ @NotNull -+ public static List toArray(@NotNull Object... data) { -+ return Lists.newArrayList(data); -+ } -+ -+ /** -+ * These help build a single JSON array using a mapper function -+ * -+ * @param collection Collection to apply to -+ * @param mapper Mapper to apply -+ * @param Element Type -+ * @return List -+ */ -+ @NotNull -+ public static List toArrayMapper(@NotNull E[] collection, @NotNull Function mapper) { -+ return toArrayMapper(Lists.newArrayList(collection), mapper); -+ } -+ -+ @NotNull -+ public static List toArrayMapper(@NotNull Iterable collection, @NotNull Function mapper) { -+ List array = Lists.newArrayList(); -+ for (E e : collection) { -+ Object object = mapper.apply(e); -+ if (object != null) { -+ array.add(object); -+ } -+ } -+ return array; -+ } -+ -+ /** -+ * These help build a single JSON Object from a collection, using a mapper function -+ * -+ * @param collection Collection to apply to -+ * @param mapper Mapper to apply -+ * @param Element Type -+ * @return Map -+ */ -+ @NotNull -+ public static Map toObjectMapper(@NotNull E[] collection, @NotNull Function mapper) { -+ return toObjectMapper(Lists.newArrayList(collection), mapper); -+ } -+ -+ @NotNull -+ public static Map toObjectMapper(@NotNull Iterable collection, @NotNull Function mapper) { -+ Map object = Maps.newLinkedHashMap(); -+ for (E e : collection) { -+ JSONPair JSONPair = mapper.apply(e); -+ if (JSONPair != null) { -+ object.put(JSONPair.key, JSONPair.val); -+ } -+ } -+ return object; -+ } -+ -+ /** -+ * Simply stores a key and a value, used internally by many methods below. -+ */ -+ @SuppressWarnings("PublicInnerClass") -+ public static class JSONPair { -+ final String key; -+ final Object val; -+ -+ JSONPair(@NotNull String key, @NotNull Object val) { -+ this.key = key; -+ this.val = val; -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/util/LoadingIntMap.java b/src/main/java/co/aikar/util/LoadingIntMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..63a899c7dbdb69daa4876a2ce2a7dfb734b5af9d ---- /dev/null -+++ b/src/main/java/co/aikar/util/LoadingIntMap.java -@@ -0,0 +1,76 @@ -+/* -+ * Copyright (c) 2015. Starlis LLC / dba Empire Minecraft -+ * -+ * This source code is proprietary software and must not be redistributed without Starlis LLC's approval -+ * -+ */ -+package co.aikar.util; -+ -+ -+import com.google.common.base.Function; -+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Allows you to pass a Loader function that when a key is accessed that doesn't exist, -+ * automatically loads the entry into the map by calling the loader Function. -+ * -+ * .get() Will only return null if the Loader can return null. -+ * -+ * You may pass any backing Map to use. -+ * -+ * This class is not thread safe and should be wrapped with Collections.synchronizedMap on the OUTSIDE of the LoadingMap if needed. -+ * -+ * Do not wrap the backing map with Collections.synchronizedMap. -+ * -+ * @param Value -+ */ -+public class LoadingIntMap extends Int2ObjectOpenHashMap { -+ private final Function loader; -+ -+ public LoadingIntMap(@NotNull Function loader) { -+ super(); -+ this.loader = loader; -+ } -+ -+ public LoadingIntMap(int expectedSize, @NotNull Function loader) { -+ super(expectedSize); -+ this.loader = loader; -+ } -+ -+ public LoadingIntMap(int expectedSize, float loadFactor, @NotNull Function loader) { -+ super(expectedSize, loadFactor); -+ this.loader = loader; -+ } -+ -+ -+ @Nullable -+ @Override -+ public V get(int key) { -+ V res = super.get(key); -+ if (res == null) { -+ res = loader.apply(key); -+ if (res != null) { -+ put(key, res); -+ } -+ } -+ return res; -+ } -+ -+ /** -+ * Due to java stuff, you will need to cast it to (Function) for some cases -+ * -+ * @param Type -+ */ -+ public abstract static class Feeder implements Function { -+ @Nullable -+ @Override -+ public T apply(@Nullable Object input) { -+ return apply(); -+ } -+ -+ @Nullable -+ public abstract T apply(); -+ } -+} -diff --git a/src/main/java/co/aikar/util/LoadingMap.java b/src/main/java/co/aikar/util/LoadingMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..aedbb03321886cb267879d7994653e447b485f6a ---- /dev/null -+++ b/src/main/java/co/aikar/util/LoadingMap.java -@@ -0,0 +1,368 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.util; -+ -+import com.google.common.base.Preconditions; -+import java.lang.reflect.Constructor; -+import java.util.AbstractMap; -+import java.util.Collection; -+import java.util.HashMap; -+import java.util.IdentityHashMap; -+import java.util.Map; -+import java.util.Set; -+import java.util.function.Function; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Allows you to pass a Loader function that when a key is accessed that doesn't exists, -+ * automatically loads the entry into the map by calling the loader Function. -+ * -+ * .get() Will only return null if the Loader can return null. -+ * -+ * You may pass any backing Map to use. -+ * -+ * This class is not thread safe and should be wrapped with Collections.synchronizedMap on the OUTSIDE of the LoadingMap if needed. -+ * -+ * Do not wrap the backing map with Collections.synchronizedMap. -+ * -+ * @param Key -+ * @param Value -+ */ -+public class LoadingMap extends AbstractMap { -+ private final Map backingMap; -+ private final java.util.function.Function loader; -+ -+ /** -+ * Initializes an auto loading map using specified loader and backing map -+ * @param backingMap Map to wrap -+ * @param loader Loader -+ */ -+ public LoadingMap(@NotNull Map backingMap, @NotNull java.util.function.Function loader) { -+ this.backingMap = backingMap; -+ this.loader = loader; -+ } -+ -+ /** -+ * Creates a new LoadingMap with the specified map and loader -+ * -+ * @param backingMap Actual map being used. -+ * @param loader Loader to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map of(@NotNull Map backingMap, @NotNull Function loader) { -+ return new LoadingMap<>(backingMap, loader); -+ } -+ -+ /** -+ * Creates a LoadingMap with an auto instantiating loader. -+ * -+ * Will auto construct class of of Value when not found -+ * -+ * Since this uses Reflection, It is more effecient to define your own static loader -+ * than using this helper, but if performance is not critical, this is easier. -+ * -+ * @param backingMap Actual map being used. -+ * @param keyClass Class used for the K generic -+ * @param valueClass Class used for the V generic -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map that auto instantiates on .get() -+ */ -+ @NotNull -+ public static Map newAutoMap(@NotNull Map backingMap, @Nullable final Class keyClass, -+ @NotNull final Class valueClass) { -+ return new LoadingMap<>(backingMap, new AutoInstantiatingLoader<>(keyClass, valueClass)); -+ } -+ /** -+ * Creates a LoadingMap with an auto instantiating loader. -+ * -+ * Will auto construct class of of Value when not found -+ * -+ * Since this uses Reflection, It is more effecient to define your own static loader -+ * than using this helper, but if performance is not critical, this is easier. -+ * -+ * @param backingMap Actual map being used. -+ * @param valueClass Class used for the V generic -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map that auto instantiates on .get() -+ */ -+ @NotNull -+ public static Map newAutoMap(@NotNull Map backingMap, -+ @NotNull final Class valueClass) { -+ return newAutoMap(backingMap, null, valueClass); -+ } -+ -+ /** -+ * @see #newAutoMap -+ * -+ * new Auto initializing map using a HashMap. -+ * -+ * @param keyClass Class used for the K generic -+ * @param valueClass Class used for the V generic -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map that auto instantiates on .get() -+ */ -+ @NotNull -+ public static Map newHashAutoMap(@Nullable final Class keyClass, @NotNull final Class valueClass) { -+ return newAutoMap(new HashMap<>(), keyClass, valueClass); -+ } -+ -+ /** -+ * @see #newAutoMap -+ * -+ * new Auto initializing map using a HashMap. -+ * -+ * @param valueClass Class used for the V generic -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map that auto instantiates on .get() -+ */ -+ @NotNull -+ public static Map newHashAutoMap(@NotNull final Class valueClass) { -+ return newHashAutoMap(null, valueClass); -+ } -+ -+ /** -+ * @see #newAutoMap -+ * -+ * new Auto initializing map using a HashMap. -+ * -+ * @param keyClass Class used for the K generic -+ * @param valueClass Class used for the V generic -+ * @param initialCapacity Initial capacity to use -+ * @param loadFactor Load factor to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map that auto instantiates on .get() -+ */ -+ @NotNull -+ public static Map newHashAutoMap(@Nullable final Class keyClass, @NotNull final Class valueClass, int initialCapacity, float loadFactor) { -+ return newAutoMap(new HashMap<>(initialCapacity, loadFactor), keyClass, valueClass); -+ } -+ -+ /** -+ * @see #newAutoMap -+ * -+ * new Auto initializing map using a HashMap. -+ * -+ * @param valueClass Class used for the V generic -+ * @param initialCapacity Initial capacity to use -+ * @param loadFactor Load factor to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map that auto instantiates on .get() -+ */ -+ @NotNull -+ public static Map newHashAutoMap(@NotNull final Class valueClass, int initialCapacity, float loadFactor) { -+ return newHashAutoMap(null, valueClass, initialCapacity, loadFactor); -+ } -+ -+ /** -+ * Initializes an auto loading map using a HashMap -+ * -+ * @param loader Loader to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map newHashMap(@NotNull Function loader) { -+ return new LoadingMap<>(new HashMap<>(), loader); -+ } -+ -+ /** -+ * Initializes an auto loading map using a HashMap -+ * -+ * @param loader Loader to use -+ * @param initialCapacity Initial capacity to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map newHashMap(@NotNull Function loader, int initialCapacity) { -+ return new LoadingMap<>(new HashMap<>(initialCapacity), loader); -+ } -+ /** -+ * Initializes an auto loading map using a HashMap -+ * -+ * @param loader Loader to use -+ * @param initialCapacity Initial capacity to use -+ * @param loadFactor Load factor to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map newHashMap(@NotNull Function loader, int initialCapacity, float loadFactor) { -+ return new LoadingMap<>(new HashMap<>(initialCapacity, loadFactor), loader); -+ } -+ -+ /** -+ * Initializes an auto loading map using an Identity HashMap -+ * -+ * @param loader Loader to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map newIdentityHashMap(@NotNull Function loader) { -+ return new LoadingMap<>(new IdentityHashMap<>(), loader); -+ } -+ -+ /** -+ * Initializes an auto loading map using an Identity HashMap -+ * -+ * @param loader Loader to use -+ * @param initialCapacity Initial capacity to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map newIdentityHashMap(@NotNull Function loader, int initialCapacity) { -+ return new LoadingMap<>(new IdentityHashMap<>(initialCapacity), loader); -+ } -+ -+ @Override -+ public int size() {return backingMap.size();} -+ -+ @Override -+ public boolean isEmpty() {return backingMap.isEmpty();} -+ -+ @Override -+ public boolean containsKey(@Nullable Object key) {return backingMap.containsKey(key);} -+ -+ @Override -+ public boolean containsValue(@Nullable Object value) {return backingMap.containsValue(value);} -+ -+ @Nullable -+ @Override -+ public V get(@Nullable Object key) { -+ V v = backingMap.get(key); -+ if (v != null) { -+ return v; -+ } -+ return backingMap.computeIfAbsent((K) key, loader); -+ } -+ -+ @Nullable -+ public V put(@Nullable K key, @Nullable V value) {return backingMap.put(key, value);} -+ -+ @Nullable -+ @Override -+ public V remove(@Nullable Object key) {return backingMap.remove(key);} -+ -+ public void putAll(@NotNull Map m) {backingMap.putAll(m);} -+ -+ @Override -+ public void clear() {backingMap.clear();} -+ -+ @NotNull -+ @Override -+ public Set keySet() {return backingMap.keySet();} -+ -+ @NotNull -+ @Override -+ public Collection values() {return backingMap.values();} -+ -+ @Override -+ public boolean equals(@Nullable Object o) {return backingMap.equals(o);} -+ -+ @Override -+ public int hashCode() {return backingMap.hashCode();} -+ -+ @NotNull -+ @Override -+ public Set> entrySet() { -+ return backingMap.entrySet(); -+ } -+ -+ @NotNull -+ public LoadingMap clone() { -+ return new LoadingMap<>(backingMap, loader); -+ } -+ -+ private static class AutoInstantiatingLoader implements Function { -+ final Constructor constructor; -+ private final Class valueClass; -+ -+ AutoInstantiatingLoader(@Nullable Class keyClass, @NotNull Class valueClass) { -+ try { -+ this.valueClass = valueClass; -+ if (keyClass != null) { -+ constructor = valueClass.getConstructor(keyClass); -+ } else { -+ constructor = null; -+ } -+ } catch (NoSuchMethodException e) { -+ throw new IllegalStateException( -+ valueClass.getName() + " does not have a constructor for " + (keyClass != null ? keyClass.getName() : null)); -+ } -+ } -+ -+ @NotNull -+ @Override -+ public V apply(@Nullable K input) { -+ try { -+ return (constructor != null ? constructor.newInstance(input) : valueClass.newInstance()); -+ } catch (Exception e) { -+ throw new ExceptionInInitializerError(e); -+ } -+ } -+ -+ @Override -+ public int hashCode() { -+ return super.hashCode(); -+ } -+ -+ @Override -+ public boolean equals(Object object) { -+ return false; -+ } -+ } -+ -+ /** -+ * Due to java stuff, you will need to cast it to (Function) for some cases -+ * -+ * @param Type -+ */ -+ public abstract static class Feeder implements Function { -+ @Nullable -+ @Override -+ public T apply(@Nullable Object input) { -+ return apply(); -+ } -+ -+ @Nullable -+ public abstract T apply(); -+ } -+} -diff --git a/src/main/java/co/aikar/util/MRUMapCache.java b/src/main/java/co/aikar/util/MRUMapCache.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5989ee21297935651b0edd44b8239e655eaef1d9 ---- /dev/null -+++ b/src/main/java/co/aikar/util/MRUMapCache.java -@@ -0,0 +1,111 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.util; -+ -+import java.util.AbstractMap; -+import java.util.Collection; -+import java.util.Map; -+import java.util.Set; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Implements a Most Recently Used cache in front of a backing map, to quickly access the last accessed result. -+ * -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ */ -+public class MRUMapCache extends AbstractMap { -+ final Map backingMap; -+ Object cacheKey; -+ V cacheValue; -+ public MRUMapCache(@NotNull final Map backingMap) { -+ this.backingMap = backingMap; -+ } -+ -+ public int size() {return backingMap.size();} -+ -+ public boolean isEmpty() {return backingMap.isEmpty();} -+ -+ public boolean containsKey(@Nullable Object key) { -+ return key != null && key.equals(cacheKey) || backingMap.containsKey(key); -+ } -+ -+ public boolean containsValue(@Nullable Object value) { -+ return value != null && value == cacheValue || backingMap.containsValue(value); -+ } -+ -+ @Nullable -+ public V get(@Nullable Object key) { -+ if (cacheKey != null && cacheKey.equals(key)) { -+ return cacheValue; -+ } -+ cacheKey = key; -+ return cacheValue = backingMap.get(key); -+ } -+ -+ @Nullable -+ public V put(@Nullable K key, @Nullable V value) { -+ cacheKey = key; -+ return cacheValue = backingMap.put(key, value); -+ } -+ -+ @Nullable -+ public V remove(@Nullable Object key) { -+ if (key != null && key.equals(cacheKey)) { -+ cacheKey = null; -+ } -+ return backingMap.remove(key); -+ } -+ -+ public void putAll(@NotNull Map m) {backingMap.putAll(m);} -+ -+ public void clear() { -+ cacheKey = null; -+ cacheValue = null; -+ backingMap.clear(); -+ } -+ -+ @NotNull -+ public Set keySet() {return backingMap.keySet();} -+ -+ @NotNull -+ public Collection values() {return backingMap.values();} -+ -+ @NotNull -+ public Set> entrySet() {return backingMap.entrySet();} -+ -+ /** -+ * Wraps the specified map with a most recently used cache -+ * -+ * @param map Map to be wrapped -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map of(@NotNull Map map) { -+ return new MRUMapCache(map); -+ } -+} -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 7168dd083ee30a47b104ab32cabb3215815f7470..7c715fdc11ab7837552b1fe3ffd08b31cec0a63b 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -649,7 +649,6 @@ public final class Bukkit { - */ - public static void reload() { - server.reload(); -- org.spigotmc.CustomTimingsHandler.reload(); // Spigot - } - - /** -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 4ba8572f1beb3b9ad46620946eb4ee89ac91818e..a6b9e4f158583e5932bf8ca210d531857e9f5360 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1344,6 +1344,26 @@ public interface Server extends PluginMessageRecipient { - throw new UnsupportedOperationException("Not supported yet."); - } - -+ // Paper start -+ @NotNull -+ public org.bukkit.configuration.file.YamlConfiguration getBukkitConfig() -+ { -+ throw new UnsupportedOperationException( "Not supported yet." ); -+ } -+ -+ @NotNull -+ public org.bukkit.configuration.file.YamlConfiguration getSpigotConfig() -+ { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } -+ -+ @NotNull -+ public org.bukkit.configuration.file.YamlConfiguration getPaperConfig() -+ { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } -+ // Paper end -+ - /** - * 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 247d194f86c00db11acbc58e7d163b2606db4f07..945b8b030d1b2a13afc0c4efad76997eb7bf00ba 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -18,6 +18,7 @@ import org.bukkit.plugin.PluginDescriptionFile; - @Deprecated - public interface UnsafeValues { - -+ void reportTimings(); // Paper - Material toLegacy(Material material); - - Material fromLegacy(Material material); -@@ -69,4 +70,12 @@ public interface UnsafeValues { - * @return true if a file matching this key was found and deleted - */ - boolean removeAdvancement(NamespacedKey key); -+ -+ // Paper start -+ /** -+ * Server name to report to timings v2 -+ * @return name -+ */ -+ String getTimingsServerName(); -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/command/BufferedCommandSender.java b/src/main/java/org/bukkit/command/BufferedCommandSender.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f9a00aecca5ec41b460bf41dfe1c69694768cf98 ---- /dev/null -+++ b/src/main/java/org/bukkit/command/BufferedCommandSender.java -@@ -0,0 +1,21 @@ -+package org.bukkit.command; -+ -+import org.jetbrains.annotations.NotNull; -+ -+public class BufferedCommandSender implements MessageCommandSender { -+ private final StringBuffer buffer = new StringBuffer(); -+ @Override -+ public void sendMessage(@NotNull String message) { -+ buffer.append(message); -+ buffer.append("\n"); -+ } -+ -+ @NotNull -+ public String getBuffer() { -+ return buffer.toString(); -+ } -+ -+ public void reset() { -+ this.buffer.setLength(0); -+ } -+} -diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java -index 4bfc214685164a38ba4261b2bae7faa8a3bd297e..03bdc1622791e1206406c87065978688d602e39e 100644 ---- a/src/main/java/org/bukkit/command/Command.java -+++ b/src/main/java/org/bukkit/command/Command.java -@@ -33,7 +33,8 @@ public abstract class Command { - protected String usageMessage; - private String permission; - private String permissionMessage; -- public org.spigotmc.CustomTimingsHandler timings; // Spigot -+ public co.aikar.timings.Timing timings; // Paper -+ @NotNull public String getTimingName() {return getName();} // Paper - - protected Command(@NotNull String name) { - this(name, "", "/" + name, new ArrayList()); -@@ -47,7 +48,6 @@ public abstract class Command { - this.usageMessage = (usageMessage == null) ? "/" + name : usageMessage; - this.aliases = aliases; - this.activeAliases = new ArrayList(aliases); -- this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot - } - - /** -@@ -245,7 +245,6 @@ public abstract class Command { - } - this.nextLabel = name; - if (!isRegistered()) { -- this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot - this.label = name; - return true; - } -diff --git a/src/main/java/org/bukkit/command/FormattedCommandAlias.java b/src/main/java/org/bukkit/command/FormattedCommandAlias.java -index d6c8938b1e13b63116b7b0e074ea8ef5997f8dc3..a6ad94ef98a1df1d2842635d850bc990b0137849 100644 ---- a/src/main/java/org/bukkit/command/FormattedCommandAlias.java -+++ b/src/main/java/org/bukkit/command/FormattedCommandAlias.java -@@ -9,6 +9,7 @@ public class FormattedCommandAlias extends Command { - - public FormattedCommandAlias(@NotNull String alias, @NotNull String[] formatStrings) { - super(alias); -+ timings = co.aikar.timings.TimingsManager.getCommandTiming("minecraft", this); // Spigot - this.formatStrings = formatStrings; - } - -@@ -113,6 +114,10 @@ public class FormattedCommandAlias extends Command { - return formatString; - } - -+ @NotNull -+ @Override // Paper -+ public String getTimingName() {return "Command Forwarder - " + super.getTimingName();} // Paper -+ - private static boolean inRange(int i, int j, int k) { - return i >= j && i <= k; - } -diff --git a/src/main/java/org/bukkit/command/MessageCommandSender.java b/src/main/java/org/bukkit/command/MessageCommandSender.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a7ef1f51c2b96617a32e6e7b1723e8770ba8a6a8 ---- /dev/null -+++ b/src/main/java/org/bukkit/command/MessageCommandSender.java -@@ -0,0 +1,129 @@ -+package org.bukkit.command; -+ -+import org.apache.commons.lang.NotImplementedException; -+import org.bukkit.Bukkit; -+import org.bukkit.Server; -+import org.bukkit.permissions.Permission; -+import org.bukkit.permissions.PermissionAttachment; -+import org.bukkit.permissions.PermissionAttachmentInfo; -+import org.bukkit.plugin.Plugin; -+ -+import java.util.Set; -+import java.util.UUID; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * For when all you care about is just messaging -+ */ -+public interface MessageCommandSender extends CommandSender { -+ -+ @Override -+ default void sendMessage(@NotNull String[] messages) { -+ for (String message : messages) { -+ sendMessage(message); -+ } -+ } -+ -+ @Override -+ default void sendMessage(@Nullable UUID sender, @NotNull String message) { -+ sendMessage(message); -+ } -+ -+ @Override -+ default void sendMessage(@Nullable UUID sender, @NotNull String[] messages) { -+ for (String message : messages) { -+ sendMessage(message); -+ } -+ } -+ -+ @NotNull -+ @Override -+ default Server getServer() { -+ return Bukkit.getServer(); -+ } -+ -+ @NotNull -+ @Override -+ default String getName() { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default boolean isOp() { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default void setOp(boolean value) { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default boolean isPermissionSet(@NotNull String name) { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default boolean isPermissionSet(@NotNull Permission perm) { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default boolean hasPermission(@NotNull String name) { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default boolean hasPermission(@NotNull Permission perm) { -+ throw new NotImplementedException(); -+ } -+ -+ @NotNull -+ @Override -+ default PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value) { -+ throw new NotImplementedException(); -+ } -+ -+ @NotNull -+ @Override -+ default PermissionAttachment addAttachment(@NotNull Plugin plugin) { -+ throw new NotImplementedException(); -+ } -+ -+ @NotNull -+ @Override -+ default PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks) { -+ throw new NotImplementedException(); -+ } -+ -+ @NotNull -+ @Override -+ default PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks) { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default void removeAttachment(@NotNull PermissionAttachment attachment) { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default void recalculatePermissions() { -+ throw new NotImplementedException(); -+ } -+ -+ @NotNull -+ @Override -+ default Set getEffectivePermissions() { -+ throw new NotImplementedException(); -+ } -+ -+ @NotNull -+ @Override -+ default Spigot spigot() { -+ throw new NotImplementedException(); -+ } -+ -+} -diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java -index 81e4fa57337f5a40c4b673136dd5eb595cce4629..f020cb04eba27a2e70fc7cf799ebbfb434b9d974 100644 ---- a/src/main/java/org/bukkit/command/SimpleCommandMap.java -+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java -@@ -15,7 +15,6 @@ import org.bukkit.command.defaults.BukkitCommand; - import org.bukkit.command.defaults.HelpCommand; - import org.bukkit.command.defaults.PluginsCommand; - import org.bukkit.command.defaults.ReloadCommand; --import org.bukkit.command.defaults.TimingsCommand; - import org.bukkit.command.defaults.VersionCommand; - import org.bukkit.entity.Player; - import org.bukkit.util.StringUtil; -@@ -35,7 +34,7 @@ public class SimpleCommandMap implements CommandMap { - register("bukkit", new VersionCommand("version")); - register("bukkit", new ReloadCommand("reload")); - register("bukkit", new PluginsCommand("plugins")); -- register("bukkit", new TimingsCommand("timings")); -+ register("bukkit", new co.aikar.timings.TimingsCommand("timings")); // Paper - } - - public void setFallbackCommands() { -@@ -67,6 +66,7 @@ public class SimpleCommandMap implements CommandMap { - */ - @Override - public boolean register(@NotNull String label, @NotNull String fallbackPrefix, @NotNull Command command) { -+ command.timings = co.aikar.timings.TimingsManager.getCommandTiming(fallbackPrefix, command); // Paper - label = label.toLowerCase(java.util.Locale.ENGLISH).trim(); - fallbackPrefix = fallbackPrefix.toLowerCase(java.util.Locale.ENGLISH).trim(); - boolean registered = register(label, command, false, fallbackPrefix); -@@ -143,16 +143,22 @@ public class SimpleCommandMap implements CommandMap { - return false; - } - -+ // Paper start - Plugins do weird things to workaround normal registration -+ if (target.timings == null) { -+ target.timings = co.aikar.timings.TimingsManager.getCommandTiming(null, target); -+ } -+ // Paper end -+ - try { -- target.timings.startTiming(); // Spigot -+ try (co.aikar.timings.Timing ignored = target.timings.startTiming()) { // Paper - use try with resources - // Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false) - target.execute(sender, sentCommandLabel, Arrays.copyOfRange(args, 1, args.length)); -- target.timings.stopTiming(); // Spigot -+ } // target.timings.stopTiming(); // Spigot // Paper - } catch (CommandException ex) { -- target.timings.stopTiming(); // Spigot -+ //target.timings.stopTiming(); // Spigot // Paper - throw ex; - } catch (Throwable ex) { -- target.timings.stopTiming(); // Spigot -+ //target.timings.stopTiming(); // Spigot // Paper - throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex); - } - -diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java -deleted file mode 100644 -index 2a145d851ce30360aa39549745bd87590c034584..0000000000000000000000000000000000000000 ---- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java -+++ /dev/null -@@ -1,250 +0,0 @@ --package org.bukkit.command.defaults; -- --import com.google.common.collect.ImmutableList; --import java.io.File; --import java.io.IOException; --import java.io.PrintStream; --import java.util.ArrayList; --import java.util.List; --import org.apache.commons.lang.Validate; --import org.bukkit.Bukkit; --import org.bukkit.ChatColor; --import org.bukkit.command.CommandSender; --import org.bukkit.event.Event; --import org.bukkit.event.HandlerList; --import org.bukkit.plugin.Plugin; --import org.bukkit.plugin.RegisteredListener; --import org.bukkit.plugin.TimedRegisteredListener; --import org.bukkit.util.StringUtil; --import org.jetbrains.annotations.NotNull; -- --// Spigot start --// CHECKSTYLE:OFF --import java.io.ByteArrayOutputStream; --import java.io.OutputStream; --import java.net.HttpURLConnection; --import java.net.URL; --import java.util.logging.Level; --import org.bukkit.command.RemoteConsoleCommandSender; --import org.bukkit.plugin.SimplePluginManager; --import org.spigotmc.CustomTimingsHandler; --// CHECKSTYLE:ON --// Spigot end -- --public class TimingsCommand extends BukkitCommand { -- private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste"); // Spigot -- public static long timingStart = 0; // Spigot -- -- public TimingsCommand(@NotNull String name) { -- super(name); -- this.description = "Manages Spigot Timings data to see performance of the server."; // Spigot -- this.usageMessage = "/timings "; // Spigot -- this.setPermission("bukkit.command.timings"); -- } -- -- // Spigot start - redesigned Timings Command -- public void executeSpigotTimings(@NotNull CommandSender sender, @NotNull String[] args) { -- if ("on".equals(args[0])) { -- ((SimplePluginManager) Bukkit.getPluginManager()).useTimings(true); -- CustomTimingsHandler.reload(); -- sender.sendMessage("Enabled Timings & Reset"); -- return; -- } else if ("off".equals(args[0])) { -- ((SimplePluginManager) Bukkit.getPluginManager()).useTimings(false); -- sender.sendMessage("Disabled Timings"); -- return; -- } -- -- if (!Bukkit.getPluginManager().useTimings()) { -- sender.sendMessage("Please enable timings by typing /timings on"); -- return; -- } -- -- boolean paste = "paste".equals(args[0]); -- if ("reset".equals(args[0])) { -- CustomTimingsHandler.reload(); -- sender.sendMessage("Timings reset"); -- } else if ("merged".equals(args[0]) || "report".equals(args[0]) || paste) { -- long sampleTime = System.nanoTime() - timingStart; -- int index = 0; -- File timingFolder = new File("timings"); -- timingFolder.mkdirs(); -- File timings = new File(timingFolder, "timings.txt"); -- ByteArrayOutputStream bout = (paste) ? new ByteArrayOutputStream() : null; -- while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt"); -- PrintStream fileTimings = null; -- try { -- fileTimings = (paste) ? new PrintStream(bout) : new PrintStream(timings); -- -- CustomTimingsHandler.printTimings(fileTimings); -- fileTimings.println("Sample time " + sampleTime + " (" + sampleTime / 1E9 + "s)"); -- -- fileTimings.println(""); -- fileTimings.println(Bukkit.spigot().getConfig().saveToString()); -- fileTimings.println(""); -- -- if (paste) { -- new PasteThread(sender, bout).start(); -- return; -- } -- -- sender.sendMessage("Timings written to " + timings.getPath()); -- sender.sendMessage("Paste contents of file into form at http://www.spigotmc.org/go/timings to read results."); -- -- } catch (IOException e) { -- } finally { -- if (fileTimings != null) { -- fileTimings.close(); -- } -- } -- } -- } -- // Spigot end -- -- @Override -- public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { -- if (!testPermission(sender)) return true; -- if (args.length < 1) { // Spigot -- sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -- return false; -- } -- // Spigot start -- if (true) { -- executeSpigotTimings(sender, args); -- return true; -- } -- // Spigot end -- if (!sender.getServer().getPluginManager().useTimings()) { -- sender.sendMessage("Please enable timings by setting \"settings.plugin-profiling\" to true in bukkit.yml"); -- return true; -- } -- -- boolean separate = "separate".equalsIgnoreCase(args[0]); -- if ("reset".equalsIgnoreCase(args[0])) { -- for (HandlerList handlerList : HandlerList.getHandlerLists()) { -- for (RegisteredListener listener : handlerList.getRegisteredListeners()) { -- if (listener instanceof TimedRegisteredListener) { -- ((TimedRegisteredListener) listener).reset(); -- } -- } -- } -- sender.sendMessage("Timings reset"); -- } else if ("merged".equalsIgnoreCase(args[0]) || separate) { -- -- int index = 0; -- int pluginIdx = 0; -- File timingFolder = new File("timings"); -- timingFolder.mkdirs(); -- File timings = new File(timingFolder, "timings.txt"); -- File names = null; -- while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt"); -- PrintStream fileTimings = null; -- PrintStream fileNames = null; -- try { -- fileTimings = new PrintStream(timings); -- if (separate) { -- names = new File(timingFolder, "names" + index + ".txt"); -- fileNames = new PrintStream(names); -- } -- for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { -- pluginIdx++; -- long totalTime = 0; -- if (separate) { -- fileNames.println(pluginIdx + " " + plugin.getDescription().getFullName()); -- fileTimings.println("Plugin " + pluginIdx); -- } else { -- fileTimings.println(plugin.getDescription().getFullName()); -- } -- for (RegisteredListener listener : HandlerList.getRegisteredListeners(plugin)) { -- if (listener instanceof TimedRegisteredListener) { -- TimedRegisteredListener trl = (TimedRegisteredListener) listener; -- long time = trl.getTotalTime(); -- int count = trl.getCount(); -- if (count == 0) continue; -- long avg = time / count; -- totalTime += time; -- Class eventClass = trl.getEventClass(); -- if (count > 0 && eventClass != null) { -- fileTimings.println(" " + eventClass.getSimpleName() + (trl.hasMultiple() ? " (and sub-classes)" : "") + " Time: " + time + " Count: " + count + " Avg: " + avg); -- } -- } -- } -- fileTimings.println(" Total time " + totalTime + " (" + totalTime / 1000000000 + "s)"); -- } -- sender.sendMessage("Timings written to " + timings.getPath()); -- if (separate) sender.sendMessage("Names written to " + names.getPath()); -- } catch (IOException e) { -- } finally { -- if (fileTimings != null) { -- fileTimings.close(); -- } -- if (fileNames != null) { -- fileNames.close(); -- } -- } -- } else { -- sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -- return false; -- } -- return true; -- } -- -- @NotNull -- @Override -- public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { -- Validate.notNull(sender, "Sender cannot be null"); -- Validate.notNull(args, "Arguments cannot be null"); -- Validate.notNull(alias, "Alias cannot be null"); -- -- if (args.length == 1) { -- return StringUtil.copyPartialMatches(args[0], TIMINGS_SUBCOMMANDS, new ArrayList(TIMINGS_SUBCOMMANDS.size())); -- } -- return ImmutableList.of(); -- } -- -- // Spigot start -- private static class PasteThread extends Thread { -- -- private final CommandSender sender; -- private final ByteArrayOutputStream bout; -- -- public PasteThread(@NotNull CommandSender sender, @NotNull ByteArrayOutputStream bout) { -- super("Timings paste thread"); -- this.sender = sender; -- this.bout = bout; -- } -- -- @Override -- public synchronized void start() { -- if (sender instanceof RemoteConsoleCommandSender) { -- run(); -- } else { -- super.start(); -- } -- } -- -- @Override -- public void run() { -- try { -- HttpURLConnection con = (HttpURLConnection) new URL("https://timings.spigotmc.org/paste").openConnection(); -- con.setDoOutput(true); -- con.setRequestMethod("POST"); -- con.setInstanceFollowRedirects(false); -- -- OutputStream out = con.getOutputStream(); -- out.write(bout.toByteArray()); -- out.close(); -- -- com.google.gson.JsonObject location = new com.google.gson.Gson().fromJson(new java.io.InputStreamReader(con.getInputStream()), com.google.gson.JsonObject.class); -- con.getInputStream().close(); -- -- String pasteID = location.get("key").getAsString(); -- sender.sendMessage(ChatColor.GREEN + "Timings results can be viewed at https://www.spigotmc.org/go/timings?url=" + pasteID); -- } catch (IOException ex) { -- sender.sendMessage(ChatColor.RED + "Error pasting timings, check your console for more information"); -- Bukkit.getServer().getLogger().log(Level.WARNING, "Could not paste timings", ex); -- } -- } -- } -- // Spigot end --} -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index da1b5b5253c0ac0abe1019096166e6c76a50e699..586fd9ebd02039ebd2c071cbbbf60f24879f96b9 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1368,7 +1368,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); -+ -+ } -+ -+ // Paper start -+ public int getPing() { -+ throw new UnsupportedOperationException( "Not supported yet." ); - } -+ // Paper end - } - - @NotNull -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 77dcfe35e6a765c8ccb38bc5d900989dc0456b13..7548e40af8043c1b5716f2d7d0122833466854c4 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -358,7 +358,6 @@ public final class SimplePluginManager implements PluginManager { - } - } - -- org.bukkit.command.defaults.TimingsCommand.timingStart = System.nanoTime(); // Spigot - return result.toArray(new Plugin[result.size()]); - } - -@@ -397,9 +396,9 @@ public final class SimplePluginManager implements PluginManager { - - if (result != null) { - plugins.add(result); -- lookupNames.put(result.getDescription().getName(), result); -+ lookupNames.put(result.getDescription().getName().toLowerCase(java.util.Locale.ENGLISH), result); // Paper - for (String provided : result.getDescription().getProvides()) { -- lookupNames.putIfAbsent(provided, result); -+ lookupNames.putIfAbsent(provided.toLowerCase(java.util.Locale.ENGLISH), result); // Paper - } - } - -@@ -428,7 +427,7 @@ public final class SimplePluginManager implements PluginManager { - @Override - @Nullable - public synchronized Plugin getPlugin(@NotNull String name) { -- return lookupNames.get(name.replace(' ', '_')); -+ return lookupNames.get(name.replace(' ', '_').toLowerCase(java.util.Locale.ENGLISH)); // Paper - } - - @Override -@@ -646,7 +645,8 @@ public final class SimplePluginManager implements PluginManager { - throw new IllegalPluginAccessException("Plugin attempted to register " + event + " while not enabled"); - } - -- if (useTimings) { -+ executor = new co.aikar.timings.TimedEventExecutor(executor, plugin, null, event); // Paper -+ if (false) { // Spigot - RL handles useTimings check now // Paper - getEventListeners(event).register(new TimedRegisteredListener(listener, executor, priority, plugin, ignoreCancelled)); - } else { - getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin, ignoreCancelled)); -@@ -861,7 +861,7 @@ public final class SimplePluginManager implements PluginManager { - - @Override - public boolean useTimings() { -- return useTimings; -+ return co.aikar.timings.Timings.isTimingsEnabled(); // Spigot - } - - /** -@@ -870,6 +870,6 @@ public final class SimplePluginManager implements PluginManager { - * @param use True if per event timing code should be used - */ - public void useTimings(boolean use) { -- useTimings = use; -+ co.aikar.timings.Timings.setTimingsEnabled(use); // Paper - } - } -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index a09c3f71ca563b6f40a118ce1344d0eb273bed40..cf2f517765d8f2a23cc4a17d9ee2dcd81f841b1b 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -54,7 +54,6 @@ public final class JavaPluginLoader implements PluginLoader { - private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; - private final List loaders = new CopyOnWriteArrayList(); - private final LibraryLoader libraryLoader; -- public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot - - /** - * This class was not meant to be constructed explicitly -@@ -292,27 +291,21 @@ public final class JavaPluginLoader implements PluginLoader { - } - } - -- final CustomTimingsHandler timings = new CustomTimingsHandler("Plugin: " + plugin.getDescription().getFullName() + " Event: " + listener.getClass().getName() + "::" + method.getName() + "(" + eventClass.getSimpleName() + ")", pluginParentTimer); // Spigot -- EventExecutor executor = new EventExecutor() { -+ EventExecutor executor = new co.aikar.timings.TimedEventExecutor(new EventExecutor() { // Paper - @Override -- public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { -+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { // Paper - try { - if (!eventClass.isAssignableFrom(event.getClass())) { - return; - } -- // Spigot start -- boolean isAsync = event.isAsynchronous(); -- if (!isAsync) timings.startTiming(); - method.invoke(listener, event); -- if (!isAsync) timings.stopTiming(); -- // Spigot end - } catch (InvocationTargetException ex) { - throw new EventException(ex.getCause()); - } catch (Throwable t) { - throw new EventException(t); - } - } -- }; -+ }, plugin, method, eventClass); // Paper - if (false) { // Spigot - RL handles useTimings check now - eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); - } else { -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 6843e32438492f380e2e72bb40dd49d45fe675cb..5ffa98bb9c76d802a9d0ea6c572a704a2732c67c 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -29,7 +29,8 @@ import org.jetbrains.annotations.Nullable; - /** - * A ClassLoader for plugins, to allow shared classes across multiple plugins - */ --final class PluginClassLoader extends URLClassLoader { -+public final class PluginClassLoader extends URLClassLoader { // Spigot -+ public JavaPlugin getPlugin() { return plugin; } // Spigot - private final JavaPluginLoader loader; - private final Map> classes = new ConcurrentHashMap>(); - private final PluginDescriptionFile description; -diff --git a/src/main/java/org/bukkit/util/CachedServerIcon.java b/src/main/java/org/bukkit/util/CachedServerIcon.java -index 5ca863b3692b2e1b58e7fb4d82f554a92cc4f01e..612958a331575d1da2715531ebdf6b1168f2e860 100644 ---- a/src/main/java/org/bukkit/util/CachedServerIcon.java -+++ b/src/main/java/org/bukkit/util/CachedServerIcon.java -@@ -2,6 +2,7 @@ package org.bukkit.util; - - import org.bukkit.Server; - import org.bukkit.event.server.ServerListPingEvent; -+import org.jetbrains.annotations.Nullable; - - /** - * This is a cached version of a server-icon. It's internal representation -@@ -12,4 +13,9 @@ import org.bukkit.event.server.ServerListPingEvent; - * @see Server#loadServerIcon(java.io.File) - * @see ServerListPingEvent#setServerIcon(CachedServerIcon) - */ --public interface CachedServerIcon {} -+public interface CachedServerIcon { -+ -+ @Nullable -+ public String getData(); // Paper -+ -+} -diff --git a/src/main/java/org/spigotmc/CustomTimingsHandler.java b/src/main/java/org/spigotmc/CustomTimingsHandler.java -index 44badfedcc3fdc26bdc293b85d8c781d6f659faa..3cbe5c2bb55dead7968a6f165ef267e3e2931061 100644 ---- a/src/main/java/org/spigotmc/CustomTimingsHandler.java -+++ b/src/main/java/org/spigotmc/CustomTimingsHandler.java -@@ -1,3 +1,26 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ - package org.spigotmc; - - import java.io.PrintStream; -@@ -5,133 +28,84 @@ import java.util.Queue; - import java.util.concurrent.ConcurrentLinkedQueue; - import org.bukkit.Bukkit; - import org.bukkit.World; --import org.bukkit.command.defaults.TimingsCommand; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; -+import org.bukkit.plugin.AuthorNagException; -+import org.bukkit.plugin.Plugin; -+import co.aikar.timings.Timing; -+import co.aikar.timings.Timings; -+import co.aikar.timings.TimingsManager; -+ -+import java.lang.reflect.InvocationTargetException; -+import java.lang.reflect.Method; -+import java.util.logging.Level; - - /** -- * Provides custom timing sections for /timings merged. -+ * This is here for legacy purposes incase any plugin used it. -+ * -+ * If you use this, migrate ASAP as this will be removed in the future! -+ * -+ * @deprecated -+ * @see co.aikar.timings.Timings#of - */ --public class CustomTimingsHandler { -- -- private static Queue HANDLERS = new ConcurrentLinkedQueue(); -- /*========================================================================*/ -- private final String name; -- private final CustomTimingsHandler parent; -- private long count = 0; -- private long start = 0; -- private long timingDepth = 0; -- private long totalTime = 0; -- private long curTickTotal = 0; -- private long violations = 0; -+@Deprecated -+public final class CustomTimingsHandler { -+ private final Timing handler; -+ private static Boolean sunReflectAvailable; -+ private static Method getCallerClass; - - public CustomTimingsHandler(@NotNull String name) { -- this(name, null); -- } -+ if (sunReflectAvailable == null) { -+ String javaVer = System.getProperty("java.version"); -+ String[] elements = javaVer.split("\\."); - -- public CustomTimingsHandler(@NotNull String name, @Nullable CustomTimingsHandler parent) { -- this.name = name; -- this.parent = parent; -- HANDLERS.add(this); -- } -+ int major = Integer.parseInt(elements.length >= 2 ? elements[1] : javaVer); -+ if (major <= 8) { -+ sunReflectAvailable = true; - -- /** -- * Prints the timings and extra data to the given stream. -- * -- * @param printStream output stream -- */ -- public static void printTimings(@NotNull PrintStream printStream) { -- printStream.println("Minecraft"); -- for (CustomTimingsHandler timings : HANDLERS) { -- long time = timings.totalTime; -- long count = timings.count; -- if (count == 0) { -- continue; -+ try { -+ Class reflection = Class.forName("sun.reflect.Reflection"); -+ getCallerClass = reflection.getMethod("getCallerClass", int.class); -+ } catch (ClassNotFoundException | NoSuchMethodException ignored) { -+ } -+ } else { -+ sunReflectAvailable = false; - } -- long avg = time / count; -- -- printStream.println(" " + timings.name + " Time: " + time + " Count: " + count + " Avg: " + avg + " Violations: " + timings.violations); -- } -- printStream.println("# Version " + Bukkit.getVersion()); -- int entities = 0; -- int livingEntities = 0; -- for (World world : Bukkit.getWorlds()) { -- entities += world.getEntities().size(); -- livingEntities += world.getLivingEntities().size(); - } -- printStream.println("# Entities " + entities); -- printStream.println("# LivingEntities " + livingEntities); -- } - -- /** -- * Resets all timings. -- */ -- public static void reload() { -- if (Bukkit.getPluginManager().useTimings()) { -- for (CustomTimingsHandler timings : HANDLERS) { -- timings.reset(); -+ Class calling = null; -+ if (sunReflectAvailable) { -+ try { -+ calling = (Class) getCallerClass.invoke(null, 2); -+ } catch (IllegalAccessException | InvocationTargetException ignored) { - } - } -- TimingsCommand.timingStart = System.nanoTime(); -- } - -- /** -- * Ticked every tick by CraftBukkit to count the number of times a timer -- * caused TPS loss. -- */ -- public static void tick() { -- if (Bukkit.getPluginManager().useTimings()) { -- for (CustomTimingsHandler timings : HANDLERS) { -- if (timings.curTickTotal > 50000000) { -- timings.violations += Math.ceil(timings.curTickTotal / 50000000); -- } -- timings.curTickTotal = 0; -- timings.timingDepth = 0; // incase reset messes this up -- } -- } -- } -+ Timing timing; - -- /** -- * Starts timing to track a section of code. -- */ -- public void startTiming() { -- // If second condtion fails we are already timing -- if (Bukkit.getPluginManager().useTimings() && ++timingDepth == 1) { -- start = System.nanoTime(); -- if (parent != null && ++parent.timingDepth == 1) { -- parent.start = start; -- } -- } -- } -+ Plugin plugin = null; -+ try { -+ plugin = TimingsManager.getPluginByClassloader(calling); -+ } catch (Exception ignored) {} - -- /** -- * Stops timing a section of code. -- */ -- public void stopTiming() { -- if (Bukkit.getPluginManager().useTimings()) { -- if (--timingDepth != 0 || start == 0) { -- return; -- } -- long diff = System.nanoTime() - start; -- totalTime += diff; -- curTickTotal += diff; -- count++; -- start = 0; -- if (parent != null) { -- parent.stopTiming(); -+ new AuthorNagException("Deprecated use of CustomTimingsHandler. Please Switch to Timings.of ASAP").printStackTrace(); -+ if (plugin != null) { -+ timing = Timings.of(plugin, "(Deprecated API) " + name); -+ } else { -+ try { -+ final Method ofSafe = TimingsManager.class.getDeclaredMethod("getHandler", String.class, String.class, Timing.class); -+ ofSafe.setAccessible(true); -+ timing = (Timing) ofSafe.invoke(null,"Minecraft", "(Deprecated API) " + name, null); -+ } catch (Exception e) { -+ e.printStackTrace(); -+ Bukkit.getLogger().log(Level.SEVERE, "This handler could not be registered"); -+ timing = Timings.NULL_HANDLER; - } - } -+ handler = timing; - } - -- /** -- * Reset this timer, setting all values to zero. -- */ -- public void reset() { -- count = 0; -- violations = 0; -- curTickTotal = 0; -- totalTime = 0; -- start = 0; -- timingDepth = 0; -- } -+ public void startTiming() { handler.startTiming(); } -+ public void stopTiming() { handler.stopTiming(); } -+ - } diff --git a/Unmapped-Spigot-API-Patches/0005-Adventure.patch b/Unmapped-Spigot-API-Patches/0005-Adventure.patch deleted file mode 100644 index bbfafdf464..0000000000 --- a/Unmapped-Spigot-API-Patches/0005-Adventure.patch +++ /dev/null @@ -1,4124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Fri, 29 Jan 2021 17:21:55 +0100 -Subject: [PATCH] Adventure - -Co-authored-by: zml -Co-authored-by: Jake Potrebic - -diff --git a/pom.xml b/pom.xml -index 1ebc4c096638128194cea9c2a4131f901e7d6896..cae43ce5c1287a4cd117fd069d34ebc1b64b7fdb 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -22,6 +22,7 @@ - 1.8 - 1.8 - UTF-8 -+ 4.7.0 - - - -@@ -31,7 +32,39 @@ - - - -+ -+ -+ -+ -+ net.kyori -+ adventure-bom -+ ${adventure.version} -+ pom -+ import -+ -+ -+ -+ -+ - -+ -+ -+ net.kyori -+ adventure-api -+ -+ -+ net.kyori -+ adventure-text-serializer-gson -+ -+ -+ net.kyori -+ adventure-text-serializer-legacy -+ -+ -+ net.kyori -+ adventure-text-serializer-plain -+ -+ - - it.unimi.dsi - fastutil -@@ -216,6 +249,12 @@ - https://javadoc.io/doc/org.yaml/snakeyaml/1.27/ - https://javadoc.io/doc/org.jetbrains/annotations-java5/20.1.0/ - https://javadoc.io/doc/net.md-5/bungeecord-chat/1.16-R0.4/ -+ -+ https://jd.adventure.kyori.net/api/${adventure.version}/ -+ https://jd.adventure.kyori.net/text-serializer-gson/${adventure.version}/ -+ https://jd.adventure.kyori.net/text-serializer-legacy/${adventure.version}/ -+ https://jd.adventure.kyori.net/text-serializer-plain/${adventure.version}/ -+ - - - -diff --git a/src/main/java/co/aikar/timings/TimingsReportListener.java b/src/main/java/co/aikar/timings/TimingsReportListener.java -index ef58a6c00f444bd498a2d8fc4e457236f393954f..ecd149157d4fb80444f34bf5633d74bcdb63dec5 100644 ---- a/src/main/java/co/aikar/timings/TimingsReportListener.java -+++ b/src/main/java/co/aikar/timings/TimingsReportListener.java -@@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - - @SuppressWarnings("WeakerAccess") --public class TimingsReportListener implements MessageCommandSender { -+public class TimingsReportListener implements net.kyori.adventure.audience.ForwardingAudience, MessageCommandSender { // Paper - private final List senders; - private final Runnable onDone; - private String timingsURL; -@@ -74,4 +74,17 @@ public class TimingsReportListener implements MessageCommandSender { - this.senders.add(Bukkit.getConsoleSender()); - } - } -+ -+ // Paper start -+ @Override -+ public void sendMessage(final @NotNull net.kyori.adventure.identity.Identity source, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { -+ net.kyori.adventure.audience.ForwardingAudience.super.sendMessage(source, message, type); -+ } -+ -+ @NotNull -+ @Override -+ public Iterable audiences() { -+ return this.senders; -+ } -+ // Paper end - } -diff --git a/src/main/java/io/papermc/paper/chat/ChatComposer.java b/src/main/java/io/papermc/paper/chat/ChatComposer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7d2fb50210246bb42d166f7e6d1c0cdfad0bdb3d ---- /dev/null -+++ b/src/main/java/io/papermc/paper/chat/ChatComposer.java -@@ -0,0 +1,29 @@ -+package io.papermc.paper.chat; -+ -+import net.kyori.adventure.text.Component; -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * A chat composer is responsible for composing chat messages sent by {@link Player}s to the server. -+ * -+ * @deprecated for removal with 1.17, in favor of {@link ChatRenderer} -+ */ -+@Deprecated -+@FunctionalInterface -+public interface ChatComposer { -+ ChatComposer DEFAULT = (player, displayName, message) -> Component.translatable("chat.type.text", displayName, message); -+ -+ /** -+ * Composes a chat message. -+ * -+ * @param source the message source -+ * @param displayName the display name of the {@link Player} sending the message -+ * @param message the chat message -+ * @return a composed chat message -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ @NotNull -+ Component composeChat(final @NotNull Player source, final @NotNull Component displayName, final @NotNull Component message); -+} -diff --git a/src/main/java/io/papermc/paper/chat/ChatFormatter.java b/src/main/java/io/papermc/paper/chat/ChatFormatter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ba784ab037adfd37b01b222ea33abea00161ecae ---- /dev/null -+++ b/src/main/java/io/papermc/paper/chat/ChatFormatter.java -@@ -0,0 +1,29 @@ -+package io.papermc.paper.chat; -+ -+import net.kyori.adventure.text.Component; -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * A chat formatter is responsible for the formatting of chat messages sent by {@link Player}s to the server. -+ * -+ * @deprecated for removal with 1.17, in favour of {@link ChatRenderer} -+ */ -+@Deprecated -+@FunctionalInterface -+public interface ChatFormatter { -+ @Deprecated -+ ChatFormatter DEFAULT = (displayName, message) -> Component.translatable("chat.type.text", displayName, message); -+ -+ /** -+ * Formats a chat message. -+ * -+ * @param displayName the display name of the {@link Player} sending the message -+ * @param message the chat message -+ * @return a formatted chat message -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ @NotNull -+ Component chat(final @NotNull Component displayName, final @NotNull Component message); -+} -diff --git a/src/main/java/io/papermc/paper/chat/ChatRenderer.java b/src/main/java/io/papermc/paper/chat/ChatRenderer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..85fd5d6777b53bab09cc54c360bb75141635bdd3 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/chat/ChatRenderer.java -@@ -0,0 +1,75 @@ -+package io.papermc.paper.chat; -+ -+import net.kyori.adventure.audience.Audience; -+import net.kyori.adventure.text.Component; -+import org.bukkit.entity.Player; -+import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * A chat renderer is responsible for rendering chat messages sent by {@link Player}s to the server. -+ */ -+@FunctionalInterface -+public interface ChatRenderer { -+ /** -+ * Renders a chat message. This will be called once for each receiving {@link Audience}. -+ * -+ * @param source the message source -+ * @param sourceDisplayName the display name of the source player -+ * @param message the chat message -+ * @param viewer the receiving {@link Audience} -+ * @return a rendered chat message -+ */ -+ @NotNull -+ Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message, @NotNull Audience viewer); -+ -+ /** -+ * Create a new instance of the default {@link ChatRenderer}. -+ * -+ * @return a new {@link ChatRenderer} -+ */ -+ @NotNull -+ static ChatRenderer defaultRenderer() { -+ return viewerUnaware((source, sourceDisplayName, message) -> Component.translatable("chat.type.text", sourceDisplayName, message)); -+ } -+ -+ /** -+ * Creates a new viewer-unaware {@link ChatRenderer}, which will render the chat message a single time, -+ * displaying the same rendered message to every viewing {@link Audience}. -+ * -+ * @param renderer the viewer unaware renderer -+ * @return a new {@link ChatRenderer} -+ */ -+ @NotNull -+ static ChatRenderer viewerUnaware(final @NotNull ViewerUnaware renderer) { -+ return new ChatRenderer() { -+ private @MonotonicNonNull Component message; -+ -+ @Override -+ public @NotNull Component render(final @NotNull Player source, final @NotNull Component sourceDisplayName, final @NotNull Component message, final @NotNull Audience viewer) { -+ if (this.message == null) { -+ this.message = renderer.render(source, sourceDisplayName, message); -+ } -+ return this.message; -+ } -+ }; -+ } -+ -+ /** -+ * Similar to {@link ChatRenderer}, but without knowledge of the message viewer. -+ * -+ * @see ChatRenderer#viewerUnaware(ViewerUnaware) -+ */ -+ interface ViewerUnaware { -+ /** -+ * Renders a chat message. -+ * -+ * @param source the message source -+ * @param sourceDisplayName the display name of the source player -+ * @param message the chat message -+ * @return a rendered chat message -+ */ -+ @NotNull -+ Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java b/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..718b860ace4077affad715a4e43961e10a83e9d9 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java -@@ -0,0 +1,299 @@ -+package io.papermc.paper.event.player; -+ -+import io.papermc.paper.chat.ChatComposer; -+import io.papermc.paper.chat.ChatFormatter; -+import java.util.HashSet; -+import java.util.Set; -+import io.papermc.paper.chat.ChatRenderer; -+import net.kyori.adventure.audience.Audience; -+import net.kyori.adventure.audience.ForwardingAudience; -+import net.kyori.adventure.text.Component; -+import org.bukkit.Bukkit; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.player.PlayerEvent; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+import org.jetbrains.annotations.NotNull; -+ -+import static java.util.Objects.requireNonNull; -+ -+/** -+ * An abstract implementation of a chat event, handling shared logic. -+ */ -+public abstract class AbstractChatEvent extends PlayerEvent implements Cancellable { -+ private final Set viewers; -+ @Deprecated private final Set recipients; -+ private boolean cancelled = false; -+ private ChatRenderer renderer; -+ @Deprecated private @Nullable ChatComposer composer; -+ @Deprecated private @Nullable ChatFormatter formatter; -+ private final Component originalMessage; -+ private Component message; -+ -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { -+ super(player, async); -+ this.viewers = viewers; -+ this.recipients = new HashSet<>(Bukkit.getOnlinePlayers()); -+ this.renderer = renderer; -+ this.message = message; -+ this.originalMessage = originalMessage; -+ } -+ -+ /** -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { -+ super(player, async); -+ this.viewers = viewers; -+ this.recipients = new HashSet<>(Bukkit.getOnlinePlayers()); -+ this.renderer = renderer; -+ this.message = message; -+ this.originalMessage = message; -+ } -+ -+ /** -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { -+ super(player, async); -+ this.recipients = recipients; -+ this.viewers = viewers; -+ this.renderer = renderer; -+ this.message = message; -+ this.originalMessage = originalMessage; -+ } -+ -+ /** -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { -+ super(player, async); -+ this.recipients = recipients; -+ this.viewers = viewers; -+ this.renderer = renderer; -+ this.message = message; -+ this.originalMessage = message; -+ } -+ -+ /** -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatComposer composer, final @NotNull Component message) { -+ super(player, async); -+ this.recipients = recipients; -+ final Set audiences = new HashSet<>(recipients); -+ audiences.add(Bukkit.getConsoleSender()); -+ this.viewers = audiences; -+ this.composer = composer; -+ this.message = message; -+ this.originalMessage = message; -+ } -+ -+ /** -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) { -+ super(player, async); -+ this.recipients = recipients; -+ final Set audiences = new HashSet<>(recipients); -+ audiences.add(Bukkit.getConsoleSender()); -+ this.viewers = audiences; -+ this.formatter = formatter; -+ this.message = message; -+ this.originalMessage = message; -+ } -+ -+ /** -+ * Gets a set of {@link Audience audiences} that this chat message will be displayed to. -+ * -+ *

    The set returned is not guaranteed to be mutable and may auto-populate -+ * on access. Any listener accessing the returned set should be aware that -+ * it may reduce performance for a lazy set implementation.

    -+ * -+ *

    Listeners should be aware that modifying the list may throw {@link -+ * UnsupportedOperationException} if the event caller provides an -+ * unmodifiable set.

    -+ * -+ * @return a set of {@link Audience audiences} who will receive the chat message -+ */ -+ @NotNull -+ public final Set viewers() { -+ return this.viewers; -+ } -+ -+ /** -+ * Gets a set of recipients that this chat message will be displayed to. -+ * -+ *

    The set returned is not guaranteed to be mutable and may auto-populate -+ * on access. Any listener accessing the returned set should be aware that -+ * it may reduce performance for a lazy set implementation.

    -+ * -+ *

    Listeners should be aware that modifying the list may throw {@link -+ * UnsupportedOperationException} if the event caller provides an -+ * unmodifiable set.

    -+ * -+ * @return a set of players who will receive the chat message -+ * @deprecated for removal with 1.17, in favor of {@link #viewers()} -+ */ -+ @Deprecated -+ @NotNull -+ public final Set recipients() { -+ return this.recipients; -+ } -+ -+ /** -+ * Sets the chat renderer. -+ * -+ * @param renderer the chat renderer -+ * @throws NullPointerException if {@code renderer} is {@code null} -+ */ -+ public final void renderer(final @NotNull ChatRenderer renderer) { -+ this.renderer = requireNonNull(renderer, "renderer"); -+ this.formatter = null; -+ this.composer = null; -+ } -+ -+ /** -+ * Gets the chat renderer. -+ * -+ * @return the chat renderer -+ */ -+ @NotNull -+ public final ChatRenderer renderer() { -+ if(this.renderer == null) { -+ if(this.composer != null) { -+ this.renderer = ChatRenderer.viewerUnaware((source, displayName, message) -> this.composer.composeChat(source, source.displayName(), message)); -+ } else { -+ requireNonNull(this.formatter, "renderer, composer, and formatter"); -+ this.renderer = ChatRenderer.viewerUnaware((source, displayName, message) -> this.formatter.chat(source.displayName(), message)); -+ } -+ } -+ return this.renderer; -+ } -+ -+ /** -+ * Gets the chat composer. -+ * -+ * @return the chat composer -+ * @deprecated for removal with 1.17, in favour of {@link #renderer()} -+ */ -+ @Deprecated -+ @NotNull -+ public final ChatComposer composer() { -+ if(this.composer == null) { -+ if(this.renderer != null) { -+ this.composer = (source, displayName, message) -> this.renderer.render(source, displayName, message, this.legacyForwardingAudience()); -+ } else { -+ requireNonNull(this.formatter, "renderer, composer, and formatter"); -+ this.composer = (source, displayName, message) -> this.formatter.chat(displayName, message); -+ } -+ } -+ return this.composer; -+ } -+ -+ /** -+ * Sets the chat composer. -+ * -+ * @param composer the chat composer -+ * @throws NullPointerException if {@code composer} is {@code null} -+ * @deprecated for removal with 1.17, in favour of {@link #renderer(ChatRenderer)} -+ */ -+ @Deprecated -+ public final void composer(final @NotNull ChatComposer composer) { -+ this.composer = requireNonNull(composer, "composer"); -+ this.formatter = null; -+ this.renderer = null; -+ } -+ -+ /** -+ * Gets the chat formatter. -+ * -+ * @return the chat formatter -+ * @deprecated for removal with 1.17, in favour of {@link #renderer()} -+ */ -+ @Deprecated -+ @NotNull -+ public final ChatFormatter formatter() { -+ if(this.formatter == null) { -+ if(this.renderer != null) { -+ this.formatter = (displayName, message) -> this.renderer.render(this.player, displayName, message, this.legacyForwardingAudience()); -+ } else { -+ requireNonNull(this.composer, "renderer, composer, and formatter"); -+ this.formatter = (displayName, message) -> this.composer.composeChat(this.player, displayName, message); -+ } -+ } -+ return this.formatter; -+ } -+ -+ /** -+ * Sets the chat formatter. -+ * -+ * @param formatter the chat formatter -+ * @throws NullPointerException if {@code formatter} is {@code null} -+ * @deprecated for removal with 1.17, in favour of {@link #renderer(ChatRenderer)} -+ */ -+ @Deprecated -+ public final void formatter(final @NotNull ChatFormatter formatter) { -+ this.formatter = requireNonNull(formatter, "formatter"); -+ this.composer = null; -+ this.renderer = null; -+ } -+ -+ /** -+ * Gets the user-supplied message. -+ * The return value will reflect changes made using {@link #message(Component)}. -+ * -+ * @return the user-supplied message -+ */ -+ @NotNull -+ public final Component message() { -+ return this.message; -+ } -+ -+ /** -+ * Sets the user-supplied message. -+ * -+ * @param message the user-supplied message -+ * @throws NullPointerException if {@code message} is {@code null} -+ */ -+ public final void message(final @NotNull Component message) { -+ this.message = requireNonNull(message, "message"); -+ } -+ -+ /** -+ * Gets the original and unmodified user-supplied message. -+ * The return value will not reflect changes made using -+ * {@link #message(Component)}. -+ * -+ * @return the original user-supplied message -+ */ -+ @NotNull -+ public final Component originalMessage() { -+ return this.originalMessage; -+ } -+ -+ @Override -+ public final boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ @Override -+ public final void setCancelled(final boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ private @NotNull Audience legacyForwardingAudience() { -+ return new ForwardingAudience() { -+ @Override -+ public @NonNull Iterable audiences() { -+ return AbstractChatEvent.this.viewers; -+ } -+ }; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ee7ec316a2f814ec759e0a3e5dfe5efbee782b22 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java -@@ -0,0 +1,73 @@ -+package io.papermc.paper.event.player; -+ -+import io.papermc.paper.chat.ChatComposer; -+import io.papermc.paper.chat.ChatFormatter; -+import java.util.Set; -+import io.papermc.paper.chat.ChatRenderer; -+import net.kyori.adventure.audience.Audience; -+import net.kyori.adventure.text.Component; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * An event fired when a {@link Player} sends a chat message to the server. -+ */ -+public final class AsyncChatEvent extends AbstractChatEvent { -+ private static final HandlerList HANDLERS = new HandlerList(); -+ -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { -+ super(async, player, viewers, renderer, message, originalMessage); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { -+ super(async, player, viewers, renderer, message); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { -+ super(async, player, recipients, viewers, renderer, message, originalMessage); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { -+ super(async, player, recipients, viewers, renderer, message); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatComposer composer, final @NotNull Component message) { -+ super(async, player, recipients, composer, message); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) { -+ super(async, player, recipients, formatter, message); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLERS; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLERS; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/player/ChatEvent.java b/src/main/java/io/papermc/paper/event/player/ChatEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c6bcf0dc3f77c631aa7eeb9b1e88b5bbfe445fc6 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/ChatEvent.java -@@ -0,0 +1,70 @@ -+package io.papermc.paper.event.player; -+ -+import io.papermc.paper.chat.ChatComposer; -+import io.papermc.paper.chat.ChatFormatter; -+import java.util.Set; -+import io.papermc.paper.chat.ChatRenderer; -+import net.kyori.adventure.audience.Audience; -+import net.kyori.adventure.text.Component; -+import org.bukkit.Warning; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * An event fired when a {@link Player} sends a chat message to the server. -+ * -+ * @deprecated Listening to this event forces chat to wait for the main thread, delaying chat messages. It is recommended to use {@link AsyncChatEvent} instead, wherever possible. -+ */ -+@Deprecated -+@Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.") -+public final class ChatEvent extends AbstractChatEvent { -+ private static final HandlerList HANDLERS = new HandlerList(); -+ -+ public ChatEvent(final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { -+ super(false, player, viewers, renderer, message, originalMessage); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #ChatEvent(Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public ChatEvent(final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { -+ super(false, player, viewers, renderer, message); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #ChatEvent(Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public ChatEvent(final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { -+ super(false, player, recipients, viewers, renderer, message, originalMessage); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #ChatEvent(Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public ChatEvent(final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatComposer composer, final @NotNull Component message) { -+ super(false, player, recipients, composer, message); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #ChatEvent(Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public ChatEvent(final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) { -+ super(false, player, recipients, formatter, message); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLERS; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLERS; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/text/PaperComponents.java b/src/main/java/io/papermc/paper/text/PaperComponents.java -new file mode 100644 -index 0000000000000000000000000000000000000000..77db592d05b754f879f8d1790642e9d9bbd30a4e ---- /dev/null -+++ b/src/main/java/io/papermc/paper/text/PaperComponents.java -@@ -0,0 +1,88 @@ -+package io.papermc.paper.text; -+ -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.flattener.ComponentFlattener; -+import net.kyori.adventure.text.format.NamedTextColor; -+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; -+import org.bukkit.Bukkit; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+/** -+ * Paper API-specific methods for working with {@link Component}s and related. -+ */ -+public final class PaperComponents { -+ private PaperComponents() { -+ throw new RuntimeException("PaperComponents is not to be instantiated!"); -+ } -+ -+ /** -+ * Return a component flattener that can use game data to resolve extra information about components. -+ * -+ * @return a component flattener -+ */ -+ public static @NonNull ComponentFlattener flattener() { -+ return Bukkit.getUnsafe().componentFlattener(); -+ } -+ -+ /** -+ * Get a serializer for {@link Component}s that will convert components to -+ * a plain-text string. -+ * -+ *

    Implementations may provide a serializer capable of processing any -+ * information that requires access to implementation details.

    -+ * -+ * @return a serializer to plain text -+ */ -+ public static @NonNull PlainComponentSerializer plainSerializer() { -+ return Bukkit.getUnsafe().plainComponentSerializer(); -+ } -+ -+ /** -+ * Get a serializer for {@link Component}s that will convert to and from the -+ * standard JSON serialization format using Gson. -+ * -+ *

    Implementations may provide a serializer capable of processing any -+ * information that requires implementation details, such as legacy -+ * (pre-1.16) hover events.

    -+ * -+ * @return a json component serializer -+ */ -+ public static @NonNull GsonComponentSerializer gsonSerializer() { -+ return Bukkit.getUnsafe().gsonComponentSerializer(); -+ } -+ -+ /** -+ * Get a serializer for {@link Component}s that will convert to and from the -+ * standard JSON serialization format using Gson, downsampling any RGB colors -+ * to their nearest {@link NamedTextColor} counterpart. -+ * -+ *

    Implementations may provide a serializer capable of processing any -+ * information that requires implementation details, such as legacy -+ * (pre-1.16) hover events.

    -+ * -+ * @return a json component serializer -+ */ -+ public static @NonNull GsonComponentSerializer colorDownsamplingGsonSerializer() { -+ return Bukkit.getUnsafe().colorDownsamplingGsonComponentSerializer(); -+ } -+ -+ /** -+ * Get a serializer for {@link Component}s that will convert to and from the -+ * legacy component format used by Bukkit. This serializer uses the -+ * {@link LegacyComponentSerializer.Builder#useUnusualXRepeatedCharacterHexFormat()} -+ * option to match upstream behavior. -+ * -+ *

    This legacy serializer uses the standard section symbol to mark -+ * formatting characters.

    -+ * -+ *

    Implementations may provide a serializer capable of processing any -+ * information that requires access to implementation details.

    -+ * -+ * @return a section serializer -+ */ -+ public static @NonNull LegacyComponentSerializer legacySectionSerializer() { -+ return Bukkit.getUnsafe().legacyComponentSerializer(); -+ } -+} -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 7c715fdc11ab7837552b1fe3ffd08b31cec0a63b..f3b07f0f1b3be14c8ecd059e1f3594cc90f84442 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -278,7 +278,9 @@ public final class Bukkit { - * - * @param message the message - * @return the number of players -+ * @deprecated in favour of {@link Server#broadcast(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public static int broadcastMessage(@NotNull String message) { - return server.broadcastMessage(message); - } -@@ -836,6 +838,19 @@ public final class Bukkit { - server.shutdown(); - } - -+ // Paper start -+ /** -+ * Broadcast a message to all players. -+ *

    -+ * This is the same as calling {@link #broadcast(net.kyori.adventure.text.Component, -+ * java.lang.String)} with the {@link Server#BROADCAST_CHANNEL_USERS} permission. -+ * -+ * @param message the message -+ * @return the number of players -+ */ -+ public static int broadcast(@NotNull net.kyori.adventure.text.Component message) { -+ return server.broadcast(message); -+ } - /** - * Broadcasts the specified message to every user with the given - * permission name. -@@ -845,6 +860,21 @@ public final class Bukkit { - * permissibles} must have to receive the broadcast - * @return number of message recipients - */ -+ public static int broadcast(@NotNull net.kyori.adventure.text.Component message, @NotNull String permission) { -+ return server.broadcast(message, permission); -+ } -+ // Paper end -+ /** -+ * Broadcasts the specified message to every user with the given -+ * permission name. -+ * -+ * @param message message to broadcast -+ * @param permission the required permission {@link Permissible -+ * permissibles} must have to receive the broadcast -+ * @return number of message recipients -+ * @deprecated in favour of {@link #broadcast(net.kyori.adventure.text.Component, String)} -+ */ -+ @Deprecated // Paper - public static int broadcast(@NotNull String message, @NotNull String permission) { - return server.broadcast(message, permission); - } -@@ -1044,6 +1074,7 @@ public final class Bukkit { - return server.createInventory(owner, type); - } - -+ // Paper start - /** - * 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; -@@ -1069,6 +1100,38 @@ public final class Bukkit { - * @see InventoryType#isCreatable() - */ - @NotNull -+ public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull net.kyori.adventure.text.Component title) { -+ return server.createInventory(owner, type, title); -+ } -+ // Paper end -+ -+ /** -+ * 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; -+ * otherwise the new inventory has the normal size for its type.
    -+ * It should be noted that some inventory types do not support titles and -+ * may not render with said titles on the Minecraft client. -+ *
    -+ * {@link InventoryType#WORKBENCH} will not process crafting recipes if -+ * created with this method. Use -+ * {@link Player#openWorkbench(Location, boolean)} instead. -+ *
    -+ * {@link InventoryType#ENCHANTING} will not process {@link ItemStack}s -+ * for possible enchanting results. Use -+ * {@link Player#openEnchanting(Location, boolean)} instead. -+ * -+ * @param owner The holder of the inventory; can be null if there's no holder. -+ * @param type The type of inventory to create. -+ * @param title The title of the inventory, to be displayed when it is viewed. -+ * @return The new inventory. -+ * @throws IllegalArgumentException if the {@link InventoryType} cannot be -+ * viewed. -+ * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} -+ * -+ * @see InventoryType#isCreatable() -+ */ -+ @Deprecated // Paper -+ @NotNull - public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title) { - return server.createInventory(owner, type, title); - } -@@ -1087,6 +1150,7 @@ public final class Bukkit { - return server.createInventory(owner, size); - } - -+ // Paper start - /** - * Creates an empty inventory of type {@link InventoryType#CHEST} with the - * specified size and title. -@@ -1099,10 +1163,30 @@ public final class Bukkit { - * @throws IllegalArgumentException if the size is not a multiple of 9 - */ - @NotNull -+ public static Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull net.kyori.adventure.text.Component title) throws IllegalArgumentException { -+ return server.createInventory(owner, size, title); -+ } -+ // Paper end -+ -+ /** -+ * Creates an empty inventory of type {@link InventoryType#CHEST} with the -+ * specified size and title. -+ * -+ * @param owner the holder of the inventory, or null to indicate no holder -+ * @param size a multiple of 9 as the size of inventory to create -+ * @param title the title of the inventory, displayed when inventory is -+ * viewed -+ * @return a new inventory -+ * @throws IllegalArgumentException if the size is not a multiple of 9 -+ * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} -+ */ -+ @Deprecated // Paper -+ @NotNull - public static Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException { - return server.createInventory(owner, size, title); - } - -+ // Paper start - /** - * Creates an empty merchant. - * -@@ -1110,7 +1194,20 @@ public final class Bukkit { - * when the merchant inventory is viewed - * @return a new merchant - */ -+ public static @NotNull Merchant createMerchant(@Nullable net.kyori.adventure.text.Component title) { -+ return server.createMerchant(title); -+ } -+ // Paper start -+ /** -+ * Creates an empty merchant. -+ * -+ * @param title the title of the corresponding merchant inventory, displayed -+ * when the merchant inventory is viewed -+ * @return a new merchant -+ * @deprecated in favour of {@link #createMerchant(net.kyori.adventure.text.Component)} -+ */ - @NotNull -+ @Deprecated // Paper - public static Merchant createMerchant(@Nullable String title) { - return server.createMerchant(title); - } -@@ -1181,22 +1278,47 @@ public final class Bukkit { - return server.isPrimaryThread(); - } - -+ // Paper start -+ /** -+ * Gets the message that is displayed on the server list. -+ * -+ * @return the server's MOTD -+ */ -+ @NotNull public static net.kyori.adventure.text.Component motd() { -+ return server.motd(); -+ } -+ // Paper end -+ - /** - * Gets the message that is displayed on the server list. - * - * @return the servers MOTD -+ * @deprecated in favour of {@link #motd()} - */ - @NotNull -+ @Deprecated // Paper - public static String getMotd() { - return server.getMotd(); - } - -+ // Paper start -+ /** -+ * Gets the default message that is displayed when the server is stopped. -+ * -+ * @return the shutdown message -+ */ -+ public static @Nullable net.kyori.adventure.text.Component shutdownMessage() { -+ return server.shutdownMessage(); -+ } -+ // Paper end - /** - * Gets the default message that is displayed when the server is stopped. - * - * @return the shutdown message -+ * @deprecated in favour of {@link #shutdownMessage()} - */ - @Nullable -+ @Deprecated // Paper - public static String getShutdownMessage() { - return server.getShutdownMessage(); - } -diff --git a/src/main/java/org/bukkit/Nameable.java b/src/main/java/org/bukkit/Nameable.java -index fee814e01a653d2b53c56e8b566383ca44aa5346..2acdf2a6d3955923c721222b9da784f3278f6418 100644 ---- a/src/main/java/org/bukkit/Nameable.java -+++ b/src/main/java/org/bukkit/Nameable.java -@@ -4,6 +4,30 @@ import org.jetbrains.annotations.Nullable; - - public interface Nameable { - -+ // Paper start -+ /** -+ * Gets the custom name. -+ * -+ *

    This value has no effect on players, they will always use their real name.

    -+ * -+ * @return the custom name -+ */ -+ @Nullable net.kyori.adventure.text.Component customName(); -+ -+ /** -+ * Sets the custom name. -+ * -+ *

    This name will be used in death messages and can be sent to the client as a nameplate over the mob.

    -+ * -+ *

    Setting the name to {@code null} will clear it.

    -+ * -+ *

    This value has no effect on players, they will always use their real name.

    -+ * -+ * @param customName the custom name to set -+ */ -+ void customName(final @Nullable net.kyori.adventure.text.Component customName); -+ // Paper end -+ - /** - * Gets the custom name on a mob or block. If there is no name this method - * will return null. -diff --git a/src/main/java/org/bukkit/NamespacedKey.java b/src/main/java/org/bukkit/NamespacedKey.java -index 803fa0019869127ee8c7e4fb1777a59c43e66f8a..c65f0d6569c130b4920a9e71ad24af6427f1f030 100644 ---- a/src/main/java/org/bukkit/NamespacedKey.java -+++ b/src/main/java/org/bukkit/NamespacedKey.java -@@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable; - * underscores, hyphens, and forward slashes. - * - */ --public final class NamespacedKey { -+public final class NamespacedKey implements net.kyori.adventure.key.Key { // Paper - implement Key - - /** - * The namespace representing all inbuilt keys. -@@ -212,4 +212,24 @@ public final class NamespacedKey { - public static NamespacedKey fromString(@NotNull String key) { - return fromString(key, null); - } -+ -+ // Paper start -+ @NotNull -+ @Override -+ public String namespace() { -+ return this.getNamespace(); -+ } -+ -+ @NotNull -+ @Override -+ public String value() { -+ return this.getKey(); -+ } -+ -+ @NotNull -+ @Override -+ public String asString() { -+ return this.namespace + ':' + this.key; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index a6b9e4f158583e5932bf8ca210d531857e9f5360..7abdbf43e2f52e8e9e0f7bd7c7a58baf347e3929 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -55,13 +55,13 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a server implementation. - */ --public interface Server extends PluginMessageRecipient { -+public interface Server extends PluginMessageRecipient, net.kyori.adventure.audience.ForwardingAudience { // Paper - - /** - * Used for all administrative messages, such as an operator using a - * command. - *

    -- * For use in {@link #broadcast(java.lang.String, java.lang.String)}. -+ * For use in {@link #broadcast(net.kyori.adventure.text.Component, java.lang.String)}. - */ - public static final String BROADCAST_CHANNEL_ADMINISTRATIVE = "bukkit.broadcast.admin"; - -@@ -69,7 +69,7 @@ public interface Server extends PluginMessageRecipient { - * Used for all announcement messages, such as informing users that a - * player has joined. - *

    -- * For use in {@link #broadcast(java.lang.String, java.lang.String)}. -+ * For use in {@link #broadcast(net.kyori.adventure.text.Component, java.lang.String)}. - */ - public static final String BROADCAST_CHANNEL_USERS = "bukkit.broadcast.user"; - -@@ -229,7 +229,9 @@ public interface Server extends PluginMessageRecipient { - * - * @param message the message - * @return the number of players -+ * @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public int broadcastMessage(@NotNull String message); - - /** -@@ -703,8 +705,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 -+ * @deprecated in favour of {@link #broadcast(net.kyori.adventure.text.Component, String)} - */ -+ @Deprecated // Paper - public int broadcast(@NotNull String message, @NotNull String permission); -+ // Paper start -+ /** -+ * Broadcast a message to all players. -+ *

    -+ * This is the same as calling {@link #broadcast(net.kyori.adventure.text.Component, -+ * java.lang.String)} with the {@link #BROADCAST_CHANNEL_USERS} permission. -+ * -+ * @param message the message -+ * @return the number of players -+ */ -+ int broadcast(@NotNull net.kyori.adventure.text.Component message); -+ -+ /** -+ * Broadcasts the specified message to every user with the given -+ * permission name. -+ * -+ * @param message message to broadcast -+ * @param permission the required permission {@link Permissible -+ * permissibles} must have to receive the broadcast -+ * @return number of message recipients -+ */ -+ int broadcast(@NotNull net.kyori.adventure.text.Component message, @NotNull String permission); -+ // Paper end - - /** - * Gets the player by the given name, regardless if they are offline or -@@ -869,6 +896,7 @@ public interface Server extends PluginMessageRecipient { - @NotNull - Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type); - -+ // Paper start - /** - * 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; -@@ -894,6 +922,36 @@ public interface Server extends PluginMessageRecipient { - * @see InventoryType#isCreatable() - */ - @NotNull -+ Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull net.kyori.adventure.text.Component title); -+ // Paper end -+ -+ /** -+ * 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; -+ * otherwise the new inventory has the normal size for its type.
    -+ * It should be noted that some inventory types do not support titles and -+ * may not render with said titles on the Minecraft client. -+ *
    -+ * {@link InventoryType#WORKBENCH} will not process crafting recipes if -+ * created with this method. Use -+ * {@link Player#openWorkbench(Location, boolean)} instead. -+ *
    -+ * {@link InventoryType#ENCHANTING} will not process {@link ItemStack}s -+ * for possible enchanting results. Use -+ * {@link Player#openEnchanting(Location, boolean)} instead. -+ * -+ * @param owner The holder of the inventory; can be null if there's no holder. -+ * @param type The type of inventory to create. -+ * @param title The title of the inventory, to be displayed when it is viewed. -+ * @return The new inventory. -+ * @throws IllegalArgumentException if the {@link InventoryType} cannot be -+ * viewed. -+ * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} -+ * -+ * @see InventoryType#isCreatable() -+ */ -+ @Deprecated // Paper -+ @NotNull - Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title); - - /** -@@ -908,6 +966,22 @@ public interface Server extends PluginMessageRecipient { - @NotNull - Inventory createInventory(@Nullable InventoryHolder owner, int size) throws IllegalArgumentException; - -+ // Paper start -+ /** -+ * Creates an empty inventory of type {@link InventoryType#CHEST} with the -+ * specified size and title. -+ * -+ * @param owner the holder of the inventory, or null to indicate no holder -+ * @param size a multiple of 9 as the size of inventory to create -+ * @param title the title of the inventory, displayed when inventory is -+ * viewed -+ * @return a new inventory -+ * @throws IllegalArgumentException if the size is not a multiple of 9 -+ */ -+ @NotNull -+ Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull net.kyori.adventure.text.Component title) throws IllegalArgumentException; -+ // Paper end -+ - /** - * Creates an empty inventory of type {@link InventoryType#CHEST} with the - * specified size and title. -@@ -918,10 +992,13 @@ public interface Server extends PluginMessageRecipient { - * viewed - * @return a new inventory - * @throws IllegalArgumentException if the size is not a multiple of 9 -+ * @deprecated in favour of {@link #createInventory(InventoryHolder, int, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - @NotNull - Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException; - -+ // Paper start - /** - * Creates an empty merchant. - * -@@ -929,7 +1006,18 @@ public interface Server extends PluginMessageRecipient { - * when the merchant inventory is viewed - * @return a new merchant - */ -+ @NotNull Merchant createMerchant(@Nullable net.kyori.adventure.text.Component title); -+ // Paper start -+ /** -+ * Creates an empty merchant. -+ * -+ * @param title the title of the corresponding merchant inventory, displayed -+ * when the merchant inventory is viewed -+ * @return a new merchant -+ * @deprecated in favour of {@link #createMerchant(net.kyori.adventure.text.Component)} -+ */ - @NotNull -+ @Deprecated // Paper - Merchant createMerchant(@Nullable String title); - - /** -@@ -986,20 +1074,41 @@ public interface Server extends PluginMessageRecipient { - */ - boolean isPrimaryThread(); - -+ // Paper start -+ /** -+ * Gets the message that is displayed on the server list. -+ * -+ * @return the server's MOTD -+ */ -+ @NotNull net.kyori.adventure.text.Component motd(); -+ // Paper end -+ - /** - * Gets the message that is displayed on the server list. - * - * @return the servers MOTD -+ * @deprecated in favour of {@link #motd()} - */ - @NotNull -+ @Deprecated // Paper - String getMotd(); - -+ // Paper start -+ /** -+ * Gets the default message that is displayed when the server is stopped. -+ * -+ * @return the shutdown message -+ */ -+ @Nullable net.kyori.adventure.text.Component shutdownMessage(); -+ // Paper end - /** - * Gets the default message that is displayed when the server is stopped. - * - * @return the shutdown message -+ * @deprecated in favour of {@link #shutdownMessage()} - */ - @Nullable -+ @Deprecated // Paper - String getShutdownMessage(); - - /** -@@ -1368,7 +1477,9 @@ public interface Server extends PluginMessageRecipient { - * Sends the component to the player - * - * @param component the components to send -+ * @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -1377,7 +1488,9 @@ public interface Server extends PluginMessageRecipient { - * Sends an array of components as a single message to the player - * - * @param components the components to send -+ * @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); - } -diff --git a/src/main/java/org/bukkit/Sound.java b/src/main/java/org/bukkit/Sound.java -index 2c8cc0c2af4741df9ae594ab9c436dea5347167c..445b6bf18e6ee26fe6cafca8cf5f1775bcd72d1e 100644 ---- a/src/main/java/org/bukkit/Sound.java -+++ b/src/main/java/org/bukkit/Sound.java -@@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; - * guarantee values will not be removed from this Enum. As such, you should not - * depend on the ordinal values of this class. - */ --public enum Sound implements Keyed { -+public enum Sound implements Keyed, net.kyori.adventure.sound.Sound.Type { // Paper - implement Sound.Type - - AMBIENT_BASALT_DELTAS_ADDITIONS("ambient.basalt_deltas.additions"), - AMBIENT_BASALT_DELTAS_LOOP("ambient.basalt_deltas.loop"), -@@ -1214,4 +1214,12 @@ public enum Sound implements Keyed { - public NamespacedKey getKey() { - return key; - } -+ -+ // Paper start -+ @NotNull -+ @Override -+ public net.kyori.adventure.key.@org.checkerframework.checker.nullness.qual.NonNull Key key() { -+ return this.key; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 945b8b030d1b2a13afc0c4efad76997eb7bf00ba..207c656c0a11a3a630bc70491efcf433b2681e18 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -17,6 +17,13 @@ import org.bukkit.plugin.PluginDescriptionFile; - */ - @Deprecated - public interface UnsafeValues { -+ // Paper start -+ net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener(); -+ net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer(); -+ net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer(); -+ net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer(); -+ net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer(); -+ // Paper end - - void reportTimings(); // Paper - Material toLegacy(Material material); -diff --git a/src/main/java/org/bukkit/Warning.java b/src/main/java/org/bukkit/Warning.java -index efb97712cc9dc7c1e12a59f5b94e4f2ad7c6b7d8..3024468af4c073324e536c1cb26beffb1e09f3f4 100644 ---- a/src/main/java/org/bukkit/Warning.java -+++ b/src/main/java/org/bukkit/Warning.java -@@ -67,6 +67,7 @@ public @interface Warning { - * - */ - public boolean printFor(@Nullable Warning warning) { -+ if (Boolean.getBoolean("paper.alwaysPrintWarningState")) return true; // Paper - if (this == DEFAULT) { - return warning == null || warning.value(); - } -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index bc4417d8ffa92a78f690bfa5705d3e42cdc11fd2..d3519fa5b99e2888a194c6382415537785fbeef0 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -38,7 +38,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a world, which may contain entities, chunks and blocks - */ --public interface World extends PluginMessageRecipient, Metadatable { -+public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience { // Paper - - /** - * Gets the {@link Block} at the given coordinates -@@ -640,6 +640,14 @@ public interface World extends PluginMessageRecipient, Metadatable { - @NotNull - public List getPlayers(); - -+ // Paper start -+ @NotNull -+ @Override -+ default Iterable audiences() { -+ return this.getPlayers(); -+ } -+ // Paper end -+ - /** - * Returns a list of entities within a bounding box centered around a - * Location. -diff --git a/src/main/java/org/bukkit/block/Sign.java b/src/main/java/org/bukkit/block/Sign.java -index a52dff9ef1c1cd7d3705e66510dfa2c91119539c..cdcf02ff9e80f5908a8fa22e82701445d5e2d298 100644 ---- a/src/main/java/org/bukkit/block/Sign.java -+++ b/src/main/java/org/bukkit/block/Sign.java -@@ -7,13 +7,48 @@ import org.jetbrains.annotations.NotNull; - * Represents a captured state of either a SignPost or a WallSign. - */ - public interface Sign extends TileState, Colorable { -+ // Paper start -+ /** -+ * Gets all the lines of text currently on this sign. -+ * -+ * @return Array of Strings containing each line of text -+ */ -+ @NotNull -+ public java.util.List lines(); -+ -+ /** -+ * Gets the line of text at the specified index. -+ *

    -+ * For example, getLine(0) will return the first line of text. -+ * -+ * @param index Line number to get the text from, starting at 0 -+ * @throws IndexOutOfBoundsException Thrown when the line does not exist -+ * @return Text on the given line -+ */ -+ @NotNull -+ public net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException; -+ -+ /** -+ * Sets the line of text at the specified index. -+ *

    -+ * For example, setLine(0, "Line One") will set the first line of text to -+ * "Line One". -+ * -+ * @param index Line number to set the text at, starting from 0 -+ * @param line New text to set at the specified index -+ * @throws IndexOutOfBoundsException If the index is out of the range 0..3 -+ */ -+ public void line(int index, @NotNull net.kyori.adventure.text.Component line) throws IndexOutOfBoundsException; -+ // Paper end - - /** - * Gets all the lines of text currently on this sign. - * - * @return Array of Strings containing each line of text -+ * @deprecated in favour of {@link #lines()} - */ - @NotNull -+ @Deprecated // Paper - public String[] getLines(); - - /** -@@ -24,8 +59,10 @@ public interface Sign extends TileState, Colorable { - * @param index Line number to get the text from, starting at 0 - * @throws IndexOutOfBoundsException Thrown when the line does not exist - * @return Text on the given line -+ * @deprecated in favour of {@link #line(int)} - */ - @NotNull -+ @Deprecated // Paper - public String getLine(int index) throws IndexOutOfBoundsException; - - /** -@@ -37,7 +74,9 @@ public interface Sign extends TileState, Colorable { - * @param index Line number to set the text at, starting from 0 - * @param line New text to set at the specified index - * @throws IndexOutOfBoundsException If the index is out of the range 0..3 -+ * @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException; - - /** -diff --git a/src/main/java/org/bukkit/command/CommandSender.java b/src/main/java/org/bukkit/command/CommandSender.java -index ac772bf349e0ffe9cab1df165d9460b387f2fe69..c88418c7aa19b4fecdfa9af3d18ff202a5dc5763 100644 ---- a/src/main/java/org/bukkit/command/CommandSender.java -+++ b/src/main/java/org/bukkit/command/CommandSender.java -@@ -6,12 +6,13 @@ import org.bukkit.permissions.Permissible; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - --public interface CommandSender extends Permissible { -+public interface CommandSender extends net.kyori.adventure.audience.Audience, Permissible { // Paper - - /** - * Sends this sender a message - * - * @param message Message to be displayed -+ * @see #sendMessage(net.kyori.adventure.text.Component) - */ - public void sendMessage(@NotNull String message); - -@@ -19,6 +20,7 @@ public interface CommandSender extends Permissible { - * Sends this sender multiple messages - * - * @param messages An array of messages to be displayed -+ * @see #sendMessage(net.kyori.adventure.text.Component) - */ - public void sendMessage(@NotNull String[] messages); - -@@ -27,6 +29,7 @@ public interface CommandSender extends Permissible { - * - * @param message Message to be displayed - * @param sender The sender of this message -+ * @see #sendMessage(net.kyori.adventure.identity.Identified, net.kyori.adventure.text.Component) - */ - public void sendMessage(@Nullable UUID sender, @NotNull String message); - -@@ -35,6 +38,7 @@ public interface CommandSender extends Permissible { - * - * @param messages An array of messages to be displayed - * @param sender The sender of this message -+ * @see #sendMessage(net.kyori.adventure.identity.Identified, net.kyori.adventure.text.Component) - */ - public void sendMessage(@Nullable UUID sender, @NotNull String[] messages); - -@@ -61,7 +65,9 @@ public interface CommandSender extends Permissible { - * Sends this sender a chat component. - * - * @param component the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -70,7 +76,9 @@ public interface CommandSender extends Permissible { - * Sends an array of components as a single message to the sender. - * - * @param components the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -80,7 +88,9 @@ public interface CommandSender extends Permissible { - * - * @param component the components to send - * @param sender the sender of the message -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -90,7 +100,9 @@ public interface CommandSender extends Permissible { - * - * @param components the components to send - * @param sender the sender of the message -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -99,4 +111,11 @@ public interface CommandSender extends Permissible { - @NotNull - Spigot spigot(); - // Spigot end -+ -+ // Paper start -+ @Override -+ default void sendMessage(final @NotNull net.kyori.adventure.identity.Identity identity, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { -+ this.sendMessage(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(message)); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/command/ProxiedCommandSender.java b/src/main/java/org/bukkit/command/ProxiedCommandSender.java -index fcc34b640265f4dccb46b9f09466ab8e1d96043e..74599b4ee0518481c0e3a5f6ab2f5302837f1ae3 100644 ---- a/src/main/java/org/bukkit/command/ProxiedCommandSender.java -+++ b/src/main/java/org/bukkit/command/ProxiedCommandSender.java -@@ -3,7 +3,7 @@ package org.bukkit.command; - - import org.jetbrains.annotations.NotNull; - --public interface ProxiedCommandSender extends CommandSender { -+public interface ProxiedCommandSender extends CommandSender, net.kyori.adventure.audience.ForwardingAudience.Single { // Paper - - /** - * Returns the CommandSender which triggered this proxied command -@@ -21,4 +21,16 @@ public interface ProxiedCommandSender extends CommandSender { - @NotNull - CommandSender getCallee(); - -+ // Paper start -+ @Override -+ default void sendMessage(final @NotNull net.kyori.adventure.identity.Identity source, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { -+ net.kyori.adventure.audience.ForwardingAudience.Single.super.sendMessage(source, message, type); -+ } -+ -+ @NotNull -+ @Override -+ default net.kyori.adventure.audience.Audience audience() { -+ return this.getCaller(); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java -index b833ef63fbe01271ceb2bd83a9eb4a84c9912761..8eb0497c81744874809ebc4bc2e28b128e66a926 100644 ---- a/src/main/java/org/bukkit/enchantments/Enchantment.java -+++ b/src/main/java/org/bukkit/enchantments/Enchantment.java -@@ -294,6 +294,19 @@ public abstract class Enchantment implements Keyed { - * @return True if the enchantment may be applied, otherwise False - */ - public abstract boolean canEnchantItem(@NotNull ItemStack item); -+ // Paper start -+ /** -+ * Get the name of the enchantment with its applied level. -+ *

    -+ * If the given {@code level} is either less than the {@link #getStartLevel()} or greater than the {@link #getMaxLevel()}, -+ * the level may not be shown in the numeral format one may otherwise expect. -+ *

    -+ * -+ * @param level the level of the enchantment to show -+ * @return the name of the enchantment with {@code level} applied -+ */ -+ public abstract @NotNull net.kyori.adventure.text.Component displayName(int level); -+ // Paper end - - @Override - public boolean equals(Object obj) { -diff --git a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java -index 9566e4306ada5e82dede0f002aa06da12c44996b..4d5f0837bd0e02a30c943d8969fb6b13452322e0 100644 ---- a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java -+++ b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java -@@ -63,4 +63,11 @@ public class EnchantmentWrapper extends Enchantment { - public boolean conflictsWith(@NotNull Enchantment other) { - return getEnchantment().conflictsWith(other); - } -+ // Paper start -+ @NotNull -+ @Override -+ public net.kyori.adventure.text.Component displayName(int level) { -+ return getEnchantment().displayName(level); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 0831f2519a32cf1c5c7d5b72864bcb1c22c52eda..03e12de470f983e89a473c4e42c21941085b1d37 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a base entity in the world - */ --public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder { -+public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource { // Paper - - /** - * Gets the entity's current position -@@ -648,4 +648,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - @Override - Spigot spigot(); - // Spigot end -+ -+ // Paper start -+ @NotNull -+ @Override -+ default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { -+ return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.customName()))); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5a2f8469c 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -30,7 +30,28 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a player, connected or not - */ --public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient { -+public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified { // Paper -+ -+ // Paper start -+ @Override -+ default @NotNull net.kyori.adventure.identity.Identity identity() { -+ return net.kyori.adventure.identity.Identity.identity(this.getUniqueId()); -+ } -+ -+ /** -+ * Gets the "friendly" name to display of this player. -+ * -+ * @return the display name -+ */ -+ @NotNull net.kyori.adventure.text.Component displayName(); -+ -+ /** -+ * Sets the "friendly" name to display of this player. -+ * -+ * @param displayName the display name to set -+ */ -+ void displayName(final @Nullable net.kyori.adventure.text.Component displayName); -+ // Paper end - - /** - * Gets the "friendly" name to display of this player. This may include -@@ -40,7 +61,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * places defined by plugins. - * - * @return the friendly name -+ * @deprecated in favour of {@link #displayName()} - */ -+ @Deprecated // Paper - @NotNull - public String getDisplayName(); - -@@ -52,15 +75,50 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * places defined by plugins. - * - * @param name The new display name. -+ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setDisplayName(@Nullable String name); - -+ // Paper start -+ /** -+ * Sets the name that is shown on the in-game player list. -+ *

    -+ * If the value is null, the name will be identical to {@link #getName()}. -+ * -+ * @param name new player list name -+ */ -+ void playerListName(@Nullable net.kyori.adventure.text.Component name); -+ -+ /** -+ * Gets the name that is shown on the in-game player list. -+ * -+ * @return the player list name -+ */ -+ @Nullable net.kyori.adventure.text.Component playerListName(); -+ -+ /** -+ * Gets the currently displayed player list header for this player. -+ * -+ * @return player list header or null -+ */ -+ @Nullable net.kyori.adventure.text.Component playerListHeader(); -+ -+ /** -+ * Gets the currently displayed player list footer for this player. -+ * -+ * @return player list footer or null -+ */ -+ @Nullable net.kyori.adventure.text.Component playerListFooter(); -+ // Paper end - /** - * Gets the name that is shown on the player list. - * - * @return the player list name -+ * @deprecated in favour of {@link #playerListName()} - */ - @NotNull -+ @Deprecated // Paper - public String getPlayerListName(); - - /** -@@ -69,14 +127,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * If the value is null, the name will be identical to {@link #getName()}. - * - * @param name new player list name -+ * @deprecated in favour of {@link #playerListName(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setPlayerListName(@Nullable String name); - - /** - * Gets the currently displayed player list header for this player. - * - * @return player list header or null -+ * @deprecated in favour of {@link #playerListHeader()} - */ -+ @Deprecated // Paper - @Nullable - public String getPlayerListHeader(); - -@@ -84,7 +146,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * Gets the currently displayed player list footer for this player. - * - * @return player list header or null -+ * @deprecated in favour of {@link #playerListFooter()} - */ -+ @Deprecated // Paper - @Nullable - public String getPlayerListFooter(); - -@@ -92,14 +156,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * Sets the currently displayed player list header for this player. - * - * @param header player list header, null for empty -+ * @deprecated in favour of {@link #sendPlayerListHeader(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setPlayerListHeader(@Nullable String header); - - /** - * Sets the currently displayed player list footer for this player. - * - * @param footer player list footer, null for empty -+ * @deprecated in favour of {@link #sendPlayerListFooter(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setPlayerListFooter(@Nullable String footer); - - /** -@@ -108,7 +176,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * - * @param header player list header, null for empty - * @param footer player list footer, null for empty -+ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setPlayerListHeaderFooter(@Nullable String header, @Nullable String footer); - - /** -@@ -146,9 +216,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * Kicks player with custom kick message. - * - * @param message kick message -+ * @deprecated in favour of {@link #kick(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void kickPlayer(@Nullable String message); - -+ // Paper start -+ /** -+ * Kicks player with custom kick message. -+ * -+ * @param message kick message -+ */ -+ void kick(final @Nullable net.kyori.adventure.text.Component message); -+ // Paper end -+ - /** - * Says a message (or runs a command). - * -@@ -448,6 +529,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - @Deprecated - public boolean sendChunkChange(@NotNull Location loc, int sx, int sy, int sz, @NotNull byte[] data); - -+ // Paper start - /** - * Send a sign change. This fakes a sign change packet for a user at - * a certain location. This will not actually change the world in any way. -@@ -463,6 +545,43 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @throws IllegalArgumentException if location is null - * @throws IllegalArgumentException if lines is non-null and has a length less than 4 - */ -+ void sendSignChange(@NotNull Location loc, @Nullable java.util.List lines) throws IllegalArgumentException; -+ /** -+ * Send a sign change. This fakes a sign change packet for a user at -+ * a certain location. This will not actually change the world in any way. -+ * This method will use a sign at the location's block or a faked sign -+ * sent via -+ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. -+ *

    -+ * If the client does not have a sign at the given location it will -+ * display an error message to the user. -+ * -+ * @param loc the location of the sign -+ * @param lines the new text on the sign or null to clear it -+ * @param dyeColor the color of the sign -+ * @throws IllegalArgumentException if location is null -+ * @throws IllegalArgumentException if dyeColor is null -+ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 -+ */ -+ void sendSignChange(@NotNull Location loc, @Nullable java.util.List lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException; -+ // Paper end -+ /** -+ * Send a sign change. This fakes a sign change packet for a user at -+ * a certain location. This will not actually change the world in any way. -+ * This method will use a sign at the location's block or a faked sign -+ * sent via -+ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. -+ *

    -+ * If the client does not have a sign at the given location it will -+ * display an error message to the user. -+ * -+ * @param loc the location of the sign -+ * @param lines the new text on the sign or null to clear it -+ * @throws IllegalArgumentException if location is null -+ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 -+ * @deprecated in favour of {@link #sendSignChange(org.bukkit.Location, java.util.List)} -+ */ -+ @Deprecated // Paper - public void sendSignChange(@NotNull Location loc, @Nullable String[] lines) throws IllegalArgumentException; - - -@@ -482,7 +601,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @throws IllegalArgumentException if location is null - * @throws IllegalArgumentException if dyeColor is null - * @throws IllegalArgumentException if lines is non-null and has a length less than 4 -+ * @deprecated in favour of {@link #sendSignChange(org.bukkit.Location, java.util.List, org.bukkit.DyeColor)} - */ -+ @Deprecated // Paper - public void sendSignChange(@NotNull Location loc, @Nullable String[] lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException; - - /** -@@ -1220,6 +1341,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - public int getClientViewDistance(); - -+ // Paper start -+ /** -+ * Gets the player's current locale. -+ * -+ * @return the player's locale -+ */ -+ @NotNull java.util.Locale locale(); -+ // Paper end - /** - * Gets the player's estimated ping in milliseconds. - * -@@ -1245,8 +1374,10 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * they wish. - * - * @return the player's locale -+ * @deprecated in favour of {@link #locale()} - */ - @NotNull -+ @Deprecated // Paper - public String getLocale(); - - /** -@@ -1264,6 +1395,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - public void openBook(@NotNull ItemStack book); - -+ // Paper start -+ @NotNull -+ @Override -+ default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { -+ return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.displayName()))); -+ } -+ // Paper end -+ - // Spigot start - public class Spigot extends Entity.Spigot { - -@@ -1318,11 +1457,13 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - throw new UnsupportedOperationException("Not supported yet."); - } - -+ @Deprecated // Paper - @Override - public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { - throw new UnsupportedOperationException("Not supported yet."); - } - -+ @Deprecated // Paper - @Override - public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); -@@ -1333,7 +1474,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * - * @param position the screen position - * @param component the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -1343,7 +1486,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * - * @param position the screen position - * @param components the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -1354,7 +1499,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param position the screen position - * @param sender the sender of the message - * @param component the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -1365,7 +1512,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param position the screen position - * @param sender the sender of the message - * @param components the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); - -diff --git a/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java b/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java -index 63c80b4ee1f7adc8a9efc3b607993104b1991f90..91cab8b13d5bba34007f124838b32a1df58c5ac7 100644 ---- a/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java -+++ b/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java -@@ -32,7 +32,9 @@ public interface CommandMinecart extends Minecart { - * same as setting it to "@". - * - * @param name New name for this CommandMinecart. -+ * @deprecated in favour of {@link #customName(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setName(@Nullable String name); - - } -diff --git a/src/main/java/org/bukkit/event/block/SignChangeEvent.java b/src/main/java/org/bukkit/event/block/SignChangeEvent.java -index 7190db11eff7d48df8a99f405a9dbaefdfa76e3d..1f79f704abf339150df08900b8ea7da4cefef258 100644 ---- a/src/main/java/org/bukkit/event/block/SignChangeEvent.java -+++ b/src/main/java/org/bukkit/event/block/SignChangeEvent.java -@@ -16,12 +16,25 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean cancel = false; - private final Player player; -- private final String[] lines; -+ // Paper start -+ private final java.util.List adventure$lines; - -+ public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player player, @NotNull final java.util.List adventure$lines) { -+ super(theBlock); -+ this.player = player; -+ this.adventure$lines = adventure$lines; -+ } -+ -+ @Deprecated // Paper end - public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player thePlayer, @NotNull final String[] theLines) { - super(theBlock); - this.player = thePlayer; -- this.lines = theLines; -+ // Paper start -+ this.adventure$lines = new java.util.ArrayList<>(); -+ for (String theLine : theLines) { -+ this.adventure$lines.add(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(theLine)); -+ } -+ // Paper end - } - - /** -@@ -34,14 +47,52 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - return player; - } - -+ // Paper start -+ /** -+ * Gets all of the lines of text from the sign involved in this event. -+ * -+ * @return the String array for the sign's lines new text -+ */ -+ public @NotNull java.util.List lines() { -+ return this.adventure$lines; -+ } -+ -+ /** -+ * Gets a single line of text from the sign involved in this event. -+ * -+ * @param index index of the line to get -+ * @return the String containing the line of text associated with the -+ * provided index -+ * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 -+ * or < 0} -+ */ -+ public @Nullable net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException { -+ return this.adventure$lines.get(index); -+ } -+ -+ /** -+ * Sets a single line for the sign involved in this event -+ * -+ * @param index index of the line to set -+ * @param line text to set -+ * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 -+ * or < 0} -+ */ -+ public void line(int index, @Nullable net.kyori.adventure.text.Component line) throws IndexOutOfBoundsException { -+ this.adventure$lines.set(index, line); -+ } -+ // Paper end -+ - /** - * Gets all of the lines of text from the sign involved in this event. - * - * @return the String array for the sign's lines new text -+ * @deprecated in favour of {@link #lines()} - */ - @NotNull -+ @Deprecated // Paper - public String[] getLines() { -- return lines; -+ return adventure$lines.stream().map(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer()::serialize).toArray(String[]::new); // Paper - } - - /** -@@ -52,10 +103,12 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - * provided index - * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 - * or < 0} -+ * @deprecated in favour of {@link #line(int)} - */ - @Nullable -+ @Deprecated // Paper - public String getLine(int index) throws IndexOutOfBoundsException { -- return lines[index]; -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.adventure$lines.get(index)); // Paper - } - - /** -@@ -65,9 +118,11 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - * @param line text to set - * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 - * or < 0} -+ * @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setLine(int index, @Nullable String line) throws IndexOutOfBoundsException { -- lines[index] = line; -+ adventure$lines.set(index, line != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(line) : null); // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -index 3c2ea8fec3a748cab7f5ad9100d12bd8213ec6c9..a01d4c21bedc7f1a54f5a330bb4c2909ce3a18e4 100644 ---- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -+++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -@@ -12,25 +12,48 @@ import org.jetbrains.annotations.Nullable; - public class PlayerDeathEvent extends EntityDeathEvent { - private int newExp = 0; - private String deathMessage = ""; -+ private net.kyori.adventure.text.Component adventure$deathMessage; // Paper - private int newLevel = 0; - private int newTotalExp = 0; - private boolean keepLevel = false; - private boolean keepInventory = false; -+ // Paper start -+ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage) { -+ this(player, drops, droppedExp, 0, adventure$deathMessage, null); -+ } -+ -+ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage) { -+ this(player, drops, droppedExp, newExp, 0, 0, adventure$deathMessage, deathMessage); -+ } - -+ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage) { -+ super(player, drops, droppedExp); -+ this.newExp = newExp; -+ this.newTotalExp = newTotalExp; -+ this.newLevel = newLevel; -+ this.deathMessage = deathMessage; -+ this.adventure$deathMessage = adventure$deathMessage; -+ } -+ // Paper end -+ -+ @Deprecated // Paper - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final String deathMessage) { - this(player, drops, droppedExp, 0, deathMessage); - } - -+ @Deprecated // Paper - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, @Nullable final String deathMessage) { - this(player, drops, droppedExp, newExp, 0, 0, deathMessage); - } - -+ @Deprecated // Paper - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final String deathMessage) { - super(player, drops, droppedExp); - this.newExp = newExp; - this.newTotalExp = newTotalExp; - this.newLevel = newLevel; - this.deathMessage = deathMessage; -+ this.adventure$deathMessage = deathMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(deathMessage) : net.kyori.adventure.text.Component.empty(); // Paper - } - - @NotNull -@@ -39,25 +62,55 @@ public class PlayerDeathEvent extends EntityDeathEvent { - return (Player) entity; - } - -+ // Paper start -+ /** -+ * Set the death message that will appear to everyone on the server. -+ * -+ * @param deathMessage Message to appear to other players on the server. -+ */ -+ public void deathMessage(@Nullable net.kyori.adventure.text.Component deathMessage) { -+ this.deathMessage = null; -+ this.adventure$deathMessage = deathMessage; -+ } -+ -+ /** -+ * Get the death message that will appear to everyone on the server. -+ * -+ * @return Message to appear to other players on the server. -+ */ -+ public @Nullable net.kyori.adventure.text.Component deathMessage() { -+ return this.adventure$deathMessage; -+ } -+ // Paper end -+ - /** - * Set the death message that will appear to everyone on the server. - * - * @param deathMessage Message to appear to other players on the server. -+ * @deprecated in favour of {@link #deathMessage(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setDeathMessage(@Nullable String deathMessage) { - this.deathMessage = deathMessage; -+ this.adventure$deathMessage = deathMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(deathMessage) : net.kyori.adventure.text.Component.empty(); // Paper - } - - /** - * Get the death message that will appear to everyone on the server. - * - * @return Message to appear to other players on the server. -+ * @deprecated in favour of {@link #deathMessage()} - */ - @Nullable -+ @Deprecated // Paper - public String getDeathMessage() { -- return deathMessage; -+ return this.deathMessage != null ? this.deathMessage : (this.adventure$deathMessage != null ? getDeathMessageString(this.adventure$deathMessage) : null); // Paper - } -- -+ // Paper start //TODO: add translation API to drop String deathMessage in favor of just Adventure -+ private static String getDeathMessageString(net.kyori.adventure.text.Component component) { -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(component); -+ } -+ // Paper end - /** - * Gets how much EXP the Player should have at respawn. - *

    -diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java -index f1e9bc9bc797b7216336d3470e3c696a06f2b21a..090d22bd30f7947103771aaaf09a2398970ac337 100644 ---- a/src/main/java/org/bukkit/event/inventory/InventoryType.java -+++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java -@@ -136,6 +136,18 @@ public enum InventoryType { - private final String title; - private final boolean isCreatable; - -+ // Paper start -+ private final net.kyori.adventure.text.Component defaultTitleComponent; -+ -+ /** -+ * Gets the inventory's default title. -+ * -+ * @return the inventory's default title -+ */ -+ public @NotNull net.kyori.adventure.text.Component defaultTitle() { -+ return defaultTitleComponent; -+ } -+ // Paper end - private InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle) { - this(defaultSize, defaultTitle, true); - } -@@ -144,6 +156,7 @@ public enum InventoryType { - size = defaultSize; - title = defaultTitle; - this.isCreatable = isCreatable; -+ this.defaultTitleComponent = net.kyori.adventure.text.Component.text(defaultTitle); // Paper - Adventure - } - - public int getDefaultSize() { -@@ -151,6 +164,7 @@ public enum InventoryType { - } - - @NotNull -+ @Deprecated // Paper - public String getDefaultTitle() { - return title; - } -diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java -index 9c68c3f2d61500479f48b80264f625aaae2f3204..399afcd19fcb6acd24857ed6ab48cf0d105a01a3 100644 ---- a/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java -+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java -@@ -22,7 +22,11 @@ import org.jetbrains.annotations.NotNull; - *

    - * Care should be taken to check {@link #isAsynchronous()} and treat the event - * appropriately. -+ * -+ * @deprecated use {@link io.papermc.paper.event.player.AsyncChatEvent} instead - */ -+@Deprecated // Paper -+@org.bukkit.Warning(value = false, reason = "Don't nag on old event yet") // Paper - public class AsyncPlayerChatEvent extends PlayerEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean cancel = false; -diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -index c8384da69af61e1970f254a3a9c206ee81d7a989..d3b4219a57fff4519ef8d803c333c854fafa7859 100644 ---- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -@@ -14,7 +14,7 @@ import org.jetbrains.annotations.NotNull; - public class AsyncPlayerPreLoginEvent extends Event { - private static final HandlerList handlers = new HandlerList(); - private Result result; -- private String message; -+ private net.kyori.adventure.text.Component message; // Paper - private final String name; - private final InetAddress ipAddress; - private final UUID uniqueId; -@@ -27,7 +27,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId) { - super(true); - this.result = Result.ALLOWED; -- this.message = ""; -+ this.message = net.kyori.adventure.text.Component.empty(); // Paper - this.name = name; - this.ipAddress = ipAddress; - this.uniqueId = uniqueId; -@@ -79,6 +79,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - this.result = result == null ? null : Result.valueOf(result.name()); - } - -+ // Paper start - /** - * Gets the current kick message that will be used if getResult() != - * Result.ALLOWED -@@ -86,7 +87,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - * @return Current kick message - */ - @NotNull -- public String getKickMessage() { -+ public net.kyori.adventure.text.Component kickMessage() { - return message; - } - -@@ -95,16 +96,66 @@ public class AsyncPlayerPreLoginEvent extends Event { - * - * @param message New kick message - */ -- public void setKickMessage(@NotNull final String message) { -+ public void kickMessage(@NotNull final net.kyori.adventure.text.Component message) { -+ this.message = message; -+ } -+ -+ /** -+ * Disallows the player from logging in, with the given reason -+ * -+ * @param result New result for disallowing the player -+ * @param message Kick message to display to the user -+ */ -+ public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { -+ this.result = result; - this.message = message; - } - -+ /** -+ * Disallows the player from logging in, with the given reason -+ * -+ * @param result New result for disallowing the player -+ * @param message Kick message to display to the user -+ * @deprecated This method uses a deprecated enum from {@link -+ * PlayerPreLoginEvent} -+ * @see #disallow(Result, String) -+ */ -+ @Deprecated -+ public void disallow(@NotNull final PlayerPreLoginEvent.Result result, @NotNull final net.kyori.adventure.text.Component message) { -+ this.result = result == null ? null : Result.valueOf(result.name()); -+ this.message = message; -+ } -+ // Paper end -+ /** -+ * Gets the current kick message that will be used if getResult() != -+ * Result.ALLOWED -+ * -+ * @return Current kick message -+ * @deprecated in favour of {@link #kickMessage()} -+ */ -+ @NotNull -+ @Deprecated // Paper -+ public String getKickMessage() { -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); // Paper -+ } -+ -+ /** -+ * Sets the kick message to display if getResult() != Result.ALLOWED -+ * -+ * @param message New kick message -+ * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} -+ */ -+ @Deprecated // Paper -+ public void setKickMessage(@NotNull final String message) { -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper -+ } -+ - /** - * Allows the player to log in - */ - public void allow() { - result = Result.ALLOWED; -- message = ""; -+ message = net.kyori.adventure.text.Component.empty(); // Paper - } - - /** -@@ -112,10 +163,12 @@ public class AsyncPlayerPreLoginEvent extends Event { - * - * @param result New result for disallowing the player - * @param message Kick message to display to the user -+ * @deprecated in favour of {@link #disallow(org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void disallow(@NotNull final Result result, @NotNull final String message) { - this.result = result; -- this.message = message; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper - } - - /** -@@ -130,7 +183,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - @Deprecated - public void disallow(@NotNull final PlayerPreLoginEvent.Result result, @NotNull final String message) { - this.result = result == null ? null : Result.valueOf(result.name()); -- this.message = message; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper - } - - /** -diff --git a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java -index 8ea56aac752544f798728b429e7152afbee497e4..213837794c603cb9f152f917941b912326a08030 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java -@@ -18,6 +18,7 @@ import org.jetbrains.annotations.NotNull; - * Listening to this event forces chat to wait for the main thread which - * causes delays for chat. {@link AsyncPlayerChatEvent} is the encouraged - * alternative for thread safe implementations. -+ * @deprecated use {@link io.papermc.paper.event.player.ChatEvent} instead - */ - @Deprecated - @Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.") -diff --git a/src/main/java/org/bukkit/event/player/PlayerEvent.java b/src/main/java/org/bukkit/event/player/PlayerEvent.java -index 793b661b6d2d05de3d7f4fc26a4c018a2af58e62..f6d3b817de3001f04ea4554c7c39a1290af3fd6d 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerEvent.java -@@ -14,7 +14,7 @@ public abstract class PlayerEvent extends Event { - player = who; - } - -- PlayerEvent(@NotNull final Player who, boolean async) { -+ public PlayerEvent(@NotNull final Player who, boolean async) { // Paper - public - super(async); - player = who; - -diff --git a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java -index d06684aba7688ce06777dbd837a46856a9d7767f..851a189d42e271679abc78f95049d8badf7a2b64 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java -@@ -10,30 +10,60 @@ import org.jetbrains.annotations.Nullable; - */ - public class PlayerJoinEvent extends PlayerEvent { - private static final HandlerList handlers = new HandlerList(); -- private String joinMessage; -+ // Paper start -+ private net.kyori.adventure.text.Component joinMessage; -+ public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final net.kyori.adventure.text.Component joinMessage) { -+ super(playerJoined); -+ this.joinMessage = joinMessage; -+ } - -+ @Deprecated // Paper end - public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final String joinMessage) { - super(playerJoined); -+ this.joinMessage = joinMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(joinMessage) : null; // Paper end -+ } -+ -+ // Paper start -+ /** -+ * Gets the join message to send to all online players -+ * -+ * @return string join message. Can be null -+ */ -+ public @Nullable net.kyori.adventure.text.Component joinMessage() { -+ return this.joinMessage; -+ } -+ -+ /** -+ * Sets the join message to send to all online players -+ * -+ * @param joinMessage join message. If null, no message will be sent -+ */ -+ public void joinMessage(@Nullable net.kyori.adventure.text.Component joinMessage) { - this.joinMessage = joinMessage; - } -+ // Paper end - - /** - * Gets the join message to send to all online players - * - * @return string join message. Can be null -+ * @deprecated in favour of {@link #joinMessage()} - */ - @Nullable -+ @Deprecated // Paper - public String getJoinMessage() { -- return joinMessage; -+ return this.joinMessage == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.joinMessage); // Paper - } - - /** - * Sets the join message to send to all online players - * - * @param joinMessage join message. If null, no message will be sent -+ * @deprecated in favour of {@link #joinMessage(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setJoinMessage(@Nullable String joinMessage) { -- this.joinMessage = joinMessage; -+ this.joinMessage = joinMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(joinMessage) : null; // Paper - } - - @NotNull -diff --git a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -index 14c337f15fc804f52e52cb0a185aad38d89303a8..5c0efe74237dbe6803ce023fde99682ff70d1a92 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -@@ -10,35 +10,84 @@ import org.jetbrains.annotations.NotNull; - */ - public class PlayerKickEvent extends PlayerEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); -- private String leaveMessage; -- private String kickReason; -+ private net.kyori.adventure.text.Component leaveMessage; // Paper -+ private net.kyori.adventure.text.Component kickReason; // Paper - private Boolean cancel; - -+ @Deprecated // Paper - public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final String kickReason, @NotNull final String leaveMessage) { -+ super(playerKicked); -+ this.kickReason = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickReason); // Paper -+ this.leaveMessage = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(leaveMessage); // Paper -+ this.cancel = false; -+ } -+ // Paper start -+ public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final net.kyori.adventure.text.Component kickReason, @NotNull final net.kyori.adventure.text.Component leaveMessage) { - super(playerKicked); - this.kickReason = kickReason; - this.leaveMessage = leaveMessage; - this.cancel = false; - } - -+ /** -+ * Gets the leave message send to all online players -+ * -+ * @return string kick reason -+ */ -+ public @NotNull net.kyori.adventure.text.Component leaveMessage() { -+ return this.leaveMessage; -+ } -+ -+ /** -+ * Sets the leave message send to all online players -+ * -+ * @param leaveMessage leave message -+ */ -+ public void leaveMessage(@NotNull net.kyori.adventure.text.Component leaveMessage) { -+ this.leaveMessage = leaveMessage; -+ } -+ - /** - * Gets the reason why the player is getting kicked - * - * @return string kick reason - */ -+ public @NotNull net.kyori.adventure.text.Component reason() { -+ return this.kickReason; -+ } -+ -+ /** -+ * Sets the reason why the player is getting kicked -+ * -+ * @param kickReason kick reason -+ */ -+ public void reason(@NotNull net.kyori.adventure.text.Component kickReason) { -+ this.kickReason = kickReason; -+ } -+ // Paper end -+ -+ /** -+ * Gets the reason why the player is getting kicked -+ * -+ * @return string kick reason -+ * @deprecated in favour of {@link #reason()} -+ */ - @NotNull -+ @Deprecated // Paper - public String getReason() { -- return kickReason; -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.kickReason); // Paper - } - - /** - * Gets the leave message send to all online players - * - * @return string kick reason -+ * @deprecated in favour of {@link #leaveMessage()} - */ - @NotNull -+ @Deprecated // Paper - public String getLeaveMessage() { -- return leaveMessage; -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.leaveMessage); // Paper - } - - @Override -@@ -55,18 +104,22 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { - * Sets the reason why the player is getting kicked - * - * @param kickReason kick reason -+ * @deprecated in favour of {@link #reason(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setReason(@NotNull String kickReason) { -- this.kickReason = kickReason; -+ this.kickReason = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickReason); // Paper - } - - /** - * Sets the leave message send to all online players - * - * @param leaveMessage leave message -+ * @deprecated in favour of {@link #leaveMessage(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setLeaveMessage(@NotNull String leaveMessage) { -- this.leaveMessage = leaveMessage; -+ this.leaveMessage = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(leaveMessage); // Paper - } - - @NotNull -diff --git a/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java b/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java -index 1db386bb701cb6974daedc6bb5b93a3afbc42100..84521186404b8e43c81a2f9513dce2be40d27840 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java -@@ -12,18 +12,32 @@ public class PlayerLocaleChangeEvent extends PlayerEvent { - private static final HandlerList handlers = new HandlerList(); - // - private final String locale; -+ // Paper start -+ private final java.util.Locale adventure$locale; -+ /** -+ * @see Player#getLocale() -+ * -+ * @return the player's new locale -+ */ -+ public @NotNull java.util.Locale locale() { -+ return this.adventure$locale; -+ } -+ // Paper end - - public PlayerLocaleChangeEvent(@NotNull Player who, @NotNull String locale) { - super(who); - this.locale = locale; -+ this.adventure$locale = net.kyori.adventure.translation.Translator.parseLocale(locale); // Paper - } - - /** - * @see Player#getLocale() - * - * @return the player's new locale -+ * @deprecated in favour of {@link #locale()} - */ - @NotNull -+ @Deprecated // Paper - public String getLocale() { - return locale; - } -diff --git a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java -index 084ca8cfcb7381bfa4fa6280748cf9b81210a9c1..75cc54739ef841cd90568d74927d6002d4cfa7e0 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java -@@ -17,7 +17,7 @@ public class PlayerLoginEvent extends PlayerEvent { - private final InetAddress address; - private final String hostname; - private Result result = Result.ALLOWED; -- private String message = ""; -+ private net.kyori.adventure.text.Component message = net.kyori.adventure.text.Component.empty(); - private final InetAddress realAddress; // Spigot - - /** -@@ -53,12 +53,52 @@ public class PlayerLoginEvent extends PlayerEvent { - * @param result The result status for this event - * @param message The message to be displayed if result denies login - * @param realAddress the actual, unspoofed connecting address -+ * @deprecated in favour of {@link #PlayerLoginEvent(Player, String, InetAddress, Result, net.kyori.adventure.text.Component, InetAddress)} - */ -+ @Deprecated // Paper - public PlayerLoginEvent(@NotNull final Player player, @NotNull String hostname, @NotNull final InetAddress address, @NotNull final Result result, @NotNull final String message, @NotNull final InetAddress realAddress) { // Spigot - this(player, hostname, address, realAddress); // Spigot - this.result = result; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper -+ } -+ -+ // Paper start -+ /** -+ * This constructor pre-configures the event with a result and message -+ * -+ * @param player The {@link Player} for this event -+ * @param hostname The hostname that was used to connect to the server -+ * @param address The address the player used to connect, provided for -+ * timing issues -+ * @param result The result status for this event -+ * @param message The message to be displayed if result denies login -+ * @param realAddress the actual, unspoofed connecting address -+ */ -+ public PlayerLoginEvent(@NotNull final Player player, @NotNull String hostname, @NotNull final InetAddress address, @NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message, @NotNull final InetAddress realAddress) { // Spigot -+ this(player, hostname, address, realAddress); // Spigot -+ this.result = result; -+ this.message = message; -+ } -+ -+ /** -+ * Gets the current kick message that will be used if getResult() != -+ * Result.ALLOWED -+ * -+ * @return Current kick message -+ */ -+ public @NotNull net.kyori.adventure.text.Component kickMessage() { -+ return this.message; -+ } -+ -+ /** -+ * Sets the kick message to display if getResult() != Result.ALLOWED -+ * -+ * @param message New kick message -+ */ -+ public void kickMessage(@NotNull net.kyori.adventure.text.Component message) { - this.message = message; - } -+ // Paper end - - // Spigot start - /** -@@ -96,19 +136,23 @@ public class PlayerLoginEvent extends PlayerEvent { - * Result.ALLOWED - * - * @return Current kick message -+ * @deprecated in favour of {@link #kickMessage()} - */ - @NotNull -+ @Deprecated // Paper - public String getKickMessage() { -- return message; -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); // Paper - } - - /** - * Sets the kick message to display if getResult() != Result.ALLOWED - * - * @param message New kick message -+ * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setKickMessage(@NotNull final String message) { -- this.message = message; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper - } - - /** -@@ -127,7 +171,7 @@ public class PlayerLoginEvent extends PlayerEvent { - */ - public void allow() { - result = Result.ALLOWED; -- message = ""; -+ message = net.kyori.adventure.text.Component.empty(); // Paper - } - - /** -@@ -135,8 +179,21 @@ public class PlayerLoginEvent extends PlayerEvent { - * - * @param result New result for disallowing the player - * @param message Kick message to display to the user -+ * @deprecated in favour of {@link #disallow(Result, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper start - public void disallow(@NotNull final Result result, @NotNull final String message) { -+ this.result = result; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); -+ } -+ /** -+ * Disallows the player from logging in, with the given reason -+ * -+ * @param result New result for disallowing the player -+ * @param message Kick message to display to the user -+ */ -+ public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { -+ // Paper end - this.result = result; - this.message = message; - } -diff --git a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java -index fb066251f793ec3b41bfc075b9478901b15ee549..123979ed64939d615b061f91c19c630e1e1db8c7 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java -@@ -19,7 +19,7 @@ import org.jetbrains.annotations.NotNull; - public class PlayerPreLoginEvent extends Event { - private static final HandlerList handlers = new HandlerList(); - private Result result; -- private String message; -+ private net.kyori.adventure.text.Component message; // Paper - private final String name; - private final InetAddress ipAddress; - private final UUID uniqueId; -@@ -31,7 +31,7 @@ public class PlayerPreLoginEvent extends Event { - - public PlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId) { - this.result = Result.ALLOWED; -- this.message = ""; -+ this.message = net.kyori.adventure.text.Component.empty(); // Paper - this.name = name; - this.ipAddress = ipAddress; - this.uniqueId = uniqueId; -@@ -56,6 +56,7 @@ public class PlayerPreLoginEvent extends Event { - this.result = result; - } - -+ // Paper start - /** - * Gets the current kick message that will be used if getResult() != - * Result.ALLOWED -@@ -63,7 +64,7 @@ public class PlayerPreLoginEvent extends Event { - * @return Current kick message - */ - @NotNull -- public String getKickMessage() { -+ public net.kyori.adventure.text.Component kickMessage() { - return message; - } - -@@ -72,16 +73,51 @@ public class PlayerPreLoginEvent extends Event { - * - * @param message New kick message - */ -- public void setKickMessage(@NotNull final String message) { -+ public void kickMessage(@NotNull final net.kyori.adventure.text.Component message) { - this.message = message; - } - -+ /** -+ * Disallows the player from logging in, with the given reason -+ * -+ * @param result New result for disallowing the player -+ * @param message Kick message to display to the user -+ */ -+ public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { -+ this.result = result; -+ this.message = message; -+ } -+ // Paper end -+ /** -+ * Gets the current kick message that will be used if getResult() != -+ * Result.ALLOWED -+ * -+ * @return Current kick message -+ * @deprecated in favour of {@link #kickMessage()} -+ */ -+ @Deprecated // Paper -+ @NotNull -+ public String getKickMessage() { -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); // Paper -+ } -+ -+ /** -+ * Sets the kick message to display if getResult() != Result.ALLOWED -+ * -+ * @param message New kick message -+ * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} -+ */ -+ @Deprecated // Paper -+ public void setKickMessage(@NotNull final String message) { -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper -+ } -+ - /** - * Allows the player to log in - */ - public void allow() { - result = Result.ALLOWED; -- message = ""; -+ message = net.kyori.adventure.text.Component.empty(); // Paper - } - - /** -@@ -89,10 +125,12 @@ public class PlayerPreLoginEvent extends Event { - * - * @param result New result for disallowing the player - * @param message Kick message to display to the user -+ * @deprecated in favour of {@link #disallow(org.bukkit.event.player.PlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void disallow(@NotNull final Result result, @NotNull final String message) { - this.result = result; -- this.message = message; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper - } - - /** -diff --git a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -index d70c25f404e994766a9ebce89a917c8d0719777c..849e8f10dd77e9fb46aab17752b8f1ff79e9d42e 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -@@ -10,30 +10,59 @@ import org.jetbrains.annotations.Nullable; - */ - public class PlayerQuitEvent extends PlayerEvent { - private static final HandlerList handlers = new HandlerList(); -- private String quitMessage; -+ private net.kyori.adventure.text.Component quitMessage; // Paper - -+ @Deprecated // Paper - public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage) { - super(who); -+ this.quitMessage = quitMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(quitMessage) : null; // Paper -+ } -+ // Paper start -+ public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage) { -+ super(who); -+ this.quitMessage = quitMessage; -+ } -+ -+ /** -+ * Gets the quit message to send to all online players -+ * -+ * @return string quit message -+ */ -+ public @Nullable net.kyori.adventure.text.Component quitMessage() { -+ return quitMessage; -+ } -+ -+ /** -+ * Sets the quit message to send to all online players -+ * -+ * @param quitMessage quit message -+ */ -+ public void quitMessage(@Nullable net.kyori.adventure.text.Component quitMessage) { - this.quitMessage = quitMessage; - } -+ // Paper end - - /** - * Gets the quit message to send to all online players - * - * @return string quit message -+ * @deprecated in favour of {@link #quitMessage()} - */ - @Nullable -+ @Deprecated // Paper - public String getQuitMessage() { -- return quitMessage; -+ return this.quitMessage == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.quitMessage); // Paper - } - - /** - * Sets the quit message to send to all online players - * - * @param quitMessage quit message -+ * @deprecated in favour of {@link #quitMessage(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setQuitMessage(@Nullable String quitMessage) { -- this.quitMessage = quitMessage; -+ this.quitMessage = quitMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(quitMessage) : null; // Paper - } - - @NotNull -diff --git a/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java b/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java -index 03bfca9d368bbe4b7c1353d52c883e756bf69bda..4f8c85222c7bd33217c7db0ff5f47bf397f8f3e5 100644 ---- a/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java -+++ b/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java -@@ -18,7 +18,7 @@ import org.jetbrains.annotations.NotNull; - public class BroadcastMessageEvent extends ServerEvent implements Cancellable { - - private static final HandlerList handlers = new HandlerList(); -- private String message; -+ private net.kyori.adventure.text.Component message; // Paper - private final Set recipients; - private boolean cancelled = false; - -@@ -27,29 +27,66 @@ public class BroadcastMessageEvent extends ServerEvent implements Cancellable { - this(false, message, recipients); - } - -+ @Deprecated // Paper - public BroadcastMessageEvent(boolean isAsync, @NotNull String message, @NotNull Set recipients) { -+ // Paper start -+ super(isAsync); -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); -+ this.recipients = recipients; -+ } -+ -+ @Deprecated -+ public BroadcastMessageEvent(@NotNull net.kyori.adventure.text.Component message, @NotNull Set recipients) { -+ this(false, message, recipients); -+ } -+ -+ public BroadcastMessageEvent(boolean isAsync, @NotNull net.kyori.adventure.text.Component message, @NotNull Set recipients) { -+ // Paper end - super(isAsync); - this.message = message; - this.recipients = recipients; - } -+ // Paper start -+ /** -+ * Get the broadcast message. -+ * -+ * @return Message to broadcast -+ */ -+ public @NotNull net.kyori.adventure.text.Component message() { -+ return this.message; -+ } -+ -+ /** -+ * Set the broadcast message. -+ * -+ * @param message New message to broadcast -+ */ -+ public void message(@NotNull net.kyori.adventure.text.Component message) { -+ this.message = message; -+ } -+ // Paper end - - /** - * Get the message to broadcast. - * - * @return Message to broadcast -+ * @deprecated in favour of {@link #message()} - */ - @NotNull -+ @Deprecated // Paper - public String getMessage() { -- return message; -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); // Paper - } - - /** - * Set the message to broadcast. - * - * @param message New message to broadcast -+ * @deprecated in favour of {@link #message(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setMessage(@NotNull String message) { -- this.message = message; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper - } - - /** -diff --git a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java -index 7a2a58bac8e721c3f0c64f69f77be07a51f76d58..ede5a41bc071a9c9cea369b227b37a50222f295d 100644 ---- a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java -+++ b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java -@@ -17,15 +17,16 @@ public class ServerListPingEvent extends ServerEvent implements Iterable - private static final int MAGIC_PLAYER_COUNT = Integer.MIN_VALUE; - private static final HandlerList handlers = new HandlerList(); - private final InetAddress address; -- private String motd; -+ private net.kyori.adventure.text.Component motd; // Paper - private final int numPlayers; - private int maxPlayers; - -+ @Deprecated // Paper - public ServerListPingEvent(@NotNull final InetAddress address, @NotNull final String motd, final int numPlayers, final int maxPlayers) { - super(true); - Validate.isTrue(numPlayers >= 0, "Cannot have negative number of players online", numPlayers); - this.address = address; -- this.motd = motd; -+ this.motd = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(motd); // Paper - this.numPlayers = numPlayers; - this.maxPlayers = maxPlayers; - } -@@ -38,14 +39,58 @@ public class ServerListPingEvent extends ServerEvent implements Iterable - * @param address the address of the pinger - * @param motd the message of the day - * @param maxPlayers the max number of players -+ * @deprecated in favour of {@link #ServerListPingEvent(java.net.InetAddress, net.kyori.adventure.text.Component, int)} - */ -+ @Deprecated // Paper - protected ServerListPingEvent(@NotNull final InetAddress address, @NotNull final String motd, final int maxPlayers) { -+ super(true); -+ this.numPlayers = MAGIC_PLAYER_COUNT; -+ this.address = address; -+ this.motd = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(motd); // Paper -+ this.maxPlayers = maxPlayers; -+ } -+ // Paper start -+ public ServerListPingEvent(@NotNull final InetAddress address, @NotNull final net.kyori.adventure.text.Component motd, final int numPlayers, final int maxPlayers) { -+ super(true); -+ Validate.isTrue(numPlayers >= 0, "Cannot have negative number of players online", numPlayers); -+ this.address = address; -+ this.motd = motd; -+ this.numPlayers = numPlayers; -+ this.maxPlayers = maxPlayers; -+ } -+ /** -+ * This constructor is intended for implementations that provide the -+ * {@link #iterator()} method, thus provided the {@link #getNumPlayers()} -+ * count. -+ * -+ * @param address the address of the pinger -+ * @param motd the message of the day -+ * @param maxPlayers the max number of players -+ */ -+ protected ServerListPingEvent(@NotNull final InetAddress address, @NotNull final net.kyori.adventure.text.Component motd, final int maxPlayers) { - super(true); - this.numPlayers = MAGIC_PLAYER_COUNT; - this.address = address; - this.motd = motd; - this.maxPlayers = maxPlayers; - } -+ /** -+ * Get the message of the day message. -+ * -+ * @return the message of the day -+ */ -+ public @NotNull net.kyori.adventure.text.Component motd() { -+ return motd; -+ } -+ /** -+ * Change the message of the day message. -+ * -+ * @param motd the message of the day -+ */ -+ public void motd(@NotNull net.kyori.adventure.text.Component motd) { -+ this.motd = motd; -+ } -+ // Paper end - - /** - * Get the address the ping is coming from. -@@ -61,19 +106,23 @@ public class ServerListPingEvent extends ServerEvent implements Iterable - * Get the message of the day message. - * - * @return the message of the day -+ * @deprecated in favour of {@link #motd()} - */ - @NotNull -+ @Deprecated // Paper - public String getMotd() { -- return motd; -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.motd); // Paper - } - - /** - * Change the message of the day message. - * - * @param motd the message of the day -+ * @deprecated in favour of {@link #motd(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setMotd(@NotNull String motd) { -- this.motd = motd; -+ this.motd = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(motd); // Paper - } - - /** -diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java -index 14346d83bc99581b18e53d19af03708c0bf22cf7..664de64b020cf9090a2fbee0afe2bfaf150adc3c 100644 ---- a/src/main/java/org/bukkit/inventory/InventoryView.java -+++ b/src/main/java/org/bukkit/inventory/InventoryView.java -@@ -446,11 +446,25 @@ public abstract class InventoryView { - return getPlayer().setWindowProperty(prop, value); - } - -+ // Paper start - /** - * Get the title of this inventory window. - * - * @return The title. - */ - @NotNull -+ public /*abstract*/ net.kyori.adventure.text.Component title() { -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(this.getTitle()); -+ } -+ // Paper end -+ -+ /** -+ * Get the title of this inventory window. -+ * -+ * @return The title. -+ * @deprecated in favour of {@link #title()} -+ */ -+ @Deprecated // Paper -+ @NotNull - public abstract String getTitle(); - } -diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index 4ff149fd98895dd8ba45939a37c223b1f8d7281f..6cc4bad2ecd19f44a680ff03cbfb99d48ea5c337 100644 ---- a/src/main/java/org/bukkit/inventory/ItemFactory.java -+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java -@@ -141,4 +141,24 @@ public interface ItemFactory { - @Deprecated - @NotNull - Material updateMaterial(@NotNull final ItemMeta meta, @NotNull final Material material) throws IllegalArgumentException; -+ -+ // Paper start -+ /** -+ * Creates a hover event for the given item. -+ * -+ * @param item The item -+ * @return A hover event -+ */ -+ @NotNull -+ net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull ItemStack item, final @NotNull java.util.function.UnaryOperator op); -+ -+ /** -+ * Get the formatted display name of the {@link ItemStack}. -+ * -+ * @param itemStack the {@link ItemStack} -+ * @return display name of the {@link ItemStack} -+ */ -+ @NotNull -+ net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index f70a6a22b85ff0da76e67e9b223ad4e0b020b5c4..a15abec467bac70116a6fc21a300d4930b909f15 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -22,7 +22,7 @@ import org.jetbrains.annotations.Nullable; - * use this class to encapsulate Materials for which {@link Material#isItem()} - * returns false. - */ --public class ItemStack implements Cloneable, ConfigurationSerializable { -+public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyori.adventure.text.event.HoverEventSource { // Paper - private Material type = Material.AIR; - private int amount = 0; - private MaterialData data = null; -@@ -595,4 +595,21 @@ public class ItemStack implements Cloneable, ConfigurationSerializable { - - return true; - } -+ -+ // Paper start -+ @NotNull -+ @Override -+ public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { -+ return org.bukkit.Bukkit.getServer().getItemFactory().asHoverEvent(this, op); -+ } -+ -+ /** -+ * Get the formatted display name of the {@link ItemStack}. -+ * -+ * @return display name of the {@link ItemStack} -+ */ -+ public @NotNull net.kyori.adventure.text.Component displayName() { -+ return Bukkit.getServer().getItemFactory().displayName(this); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/meta/BookMeta.java b/src/main/java/org/bukkit/inventory/meta/BookMeta.java -index 94852d50e88d0594b84b581cd627174043629995..4947251f347d83fa326a67735293401c10d87ba4 100644 ---- a/src/main/java/org/bukkit/inventory/meta/BookMeta.java -+++ b/src/main/java/org/bukkit/inventory/meta/BookMeta.java -@@ -1,8 +1,12 @@ - package org.bukkit.inventory.meta; - - import java.util.List; -+ -+import net.kyori.adventure.inventory.Book; - import net.md_5.bungee.api.chat.BaseComponent; - import org.bukkit.Material; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.common.returnsreceiver.qual.This; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - -@@ -10,7 +14,7 @@ import org.jetbrains.annotations.Nullable; - * Represents a book ({@link Material#WRITABLE_BOOK} or {@link - * Material#WRITTEN_BOOK}) that can have a title, an author, and pages. - */ --public interface BookMeta extends ItemMeta { -+public interface BookMeta extends ItemMeta, net.kyori.adventure.inventory.Book { // Paper - - /** - * Represents the generation (or level of copying) of a written book -@@ -119,6 +123,117 @@ public interface BookMeta extends ItemMeta { - */ - boolean hasPages(); - -+ // Paper start -+ /** -+ * Gets the title of the book. -+ *

    -+ * Plugins should check that hasTitle() returns true before calling this -+ * method. -+ * -+ * @return the title of the book -+ */ -+ @Nullable -+ @Override -+ net.kyori.adventure.text.Component title(); -+ -+ /** -+ * Sets the title of the book. -+ *

    -+ * Limited to 32 characters. Removes title when given null. -+ * -+ * @param title the title to set -+ * @return the same {@link BookMeta} instance -+ */ -+ @NotNull -+ @Override -+ @This BookMeta title(@Nullable net.kyori.adventure.text.Component title); -+ -+ /** -+ * Gets the author of the book. -+ *

    -+ * Plugins should check that hasAuthor() returns true before calling this -+ * method. -+ * -+ * @return the author of the book -+ */ -+ @Nullable -+ @Override -+ net.kyori.adventure.text.Component author(); -+ -+ /** -+ * Sets the author of the book. Removes author when given null. -+ * -+ * @param author the author to set -+ * @return the same {@link BookMeta} instance -+ */ -+ @NotNull -+ @Override -+ @This BookMeta author(@Nullable net.kyori.adventure.text.Component author); -+ /** -+ * Gets the specified page in the book. The page must exist. -+ *

    -+ * Pages are 1-indexed. -+ * -+ * @param page the page number to get, in range [1, getPageCount()] -+ * @return the page from the book -+ */ -+ @NotNull net.kyori.adventure.text.Component page(int page); -+ -+ /** -+ * Sets the specified page in the book. Pages of the book must be -+ * contiguous. -+ *

    -+ * The data can be up to 256 characters in length, additional characters -+ * are truncated. -+ *

    -+ * Pages are 1-indexed. -+ * -+ * @param page the page number to set, in range [1, getPageCount()] -+ * @param data the data to set for that page -+ */ -+ void page(int page, @NotNull net.kyori.adventure.text.Component data); -+ -+ /** -+ * Adds new pages to the end of the book. Up to a maximum of 50 pages with -+ * 256 characters per page. -+ * -+ * @param pages A list of strings, each being a page -+ */ -+ void addPages(@NotNull net.kyori.adventure.text.Component... pages); -+ -+ interface BookMetaBuilder extends Builder { -+ -+ @NotNull -+ @Override -+ BookMetaBuilder title(@Nullable net.kyori.adventure.text.Component title); -+ -+ @NotNull -+ @Override -+ BookMetaBuilder author(@Nullable net.kyori.adventure.text.Component author); -+ -+ @NotNull -+ @Override -+ BookMetaBuilder addPage(@NotNull net.kyori.adventure.text.Component page); -+ -+ @NotNull -+ @Override -+ BookMetaBuilder pages(@NotNull net.kyori.adventure.text.Component... pages); -+ -+ @NotNull -+ @Override -+ BookMetaBuilder pages(@NotNull java.util.Collection pages); -+ -+ @NotNull -+ @Override -+ BookMeta build(); -+ } -+ -+ @Override -+ @NonNull -+ BookMetaBuilder toBuilder(); -+ -+ // Paper end -+ - /** - * Gets the specified page in the book. The given page must exist. - *

    -@@ -126,8 +241,10 @@ public interface BookMeta extends ItemMeta { - * - * @param page the page number to get, in range [1, getPageCount()] - * @return the page from the book -+ * @deprecated in favour of {@link #page(int)} - */ - @NotNull -+ @Deprecated // Paper - String getPage(int page); - - /** -@@ -141,15 +258,19 @@ public interface BookMeta extends ItemMeta { - * - * @param page the page number to set, in range [1, getPageCount()] - * @param data the data to set for that page -+ * @deprecated in favour of {@link #page(int, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setPage(int page, @NotNull String data); - - /** - * Gets all the pages in the book. - * - * @return list of all the pages in the book -+ * @deprecated in favour of {@link #pages()} - */ - @NotNull -+ @Deprecated // Paper - List getPages(); - - /** -@@ -157,7 +278,9 @@ public interface BookMeta extends ItemMeta { - * pages. Maximum 100 pages with 256 characters per page. - * - * @param pages A list of pages to set the book to use -+ * @deprecated in favour of {@link #pages(List)} - */ -+ @Deprecated // Paper - void setPages(@NotNull List pages); - - /** -@@ -165,7 +288,9 @@ public interface BookMeta extends ItemMeta { - * pages. Maximum 50 pages with 256 characters per page. - * - * @param pages A list of strings, each being a page -+ * @deprecated in favour of {@link #pages(net.kyori.adventure.text.Component...)} - */ -+ @Deprecated // Paper - void setPages(@NotNull String... pages); - - /** -@@ -173,7 +298,9 @@ public interface BookMeta extends ItemMeta { - * 256 characters per page. - * - * @param pages A list of strings, each being a page -+ * @deprecated in favour of {@link #addPages(net.kyori.adventure.text.Component...)} - */ -+ @Deprecated // Paper - void addPage(@NotNull String... pages); - - /** -@@ -195,8 +322,10 @@ public interface BookMeta extends ItemMeta { - * - * @param page the page number to get - * @return the page from the book -+ * @deprecated in favour of {@link #page(int)} - */ - @NotNull -+ @Deprecated // Paper - public BaseComponent[] getPage(int page) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -210,7 +339,9 @@ public interface BookMeta extends ItemMeta { - * - * @param page the page number to set - * @param data the data to set for that page -+ * @deprecated in favour of {@link #page(int, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setPage(int page, @Nullable BaseComponent... data) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -219,8 +350,10 @@ public interface BookMeta extends ItemMeta { - * Gets all the pages in the book. - * - * @return list of all the pages in the book -+ * @deprecated in favour of {@link #pages()} - */ - @NotNull -+ @Deprecated // Paper - public List getPages() { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -230,7 +363,9 @@ public interface BookMeta extends ItemMeta { - * pages. Maximum 50 pages with 256 characters per page. - * - * @param pages A list of pages to set the book to use -+ * @deprecated in favour of {@link #pages(java.util.List)} - */ -+ @Deprecated // Paper - public void setPages(@NotNull List pages) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -240,7 +375,9 @@ public interface BookMeta extends ItemMeta { - * pages. Maximum 50 pages with 256 characters per page. - * - * @param pages A list of component arrays, each being a page -+ * @deprecated in favour of {@link #pages(net.kyori.adventure.text.Component...)} - */ -+ @Deprecated // Paper - public void setPages(@NotNull BaseComponent[]... pages) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -250,7 +387,9 @@ public interface BookMeta extends ItemMeta { - * with 256 characters per page. - * - * @param pages A list of component arrays, each being a page -+ * @deprecated in favour of {@link #addPages(net.kyori.adventure.text.Component...)} - */ -+ @Deprecated // Paper - public void addPage(@NotNull BaseComponent[]... pages) { - throw new UnsupportedOperationException("Not supported yet."); - } -diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -index f2e9f2753ec92aa4a3e3f06ca6053bd70b9091d7..1c362636c56db0e6c118171ba367c43c4f7cff33 100644 ---- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -+++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -@@ -31,6 +31,24 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - */ - boolean hasDisplayName(); - -+ // Paper start -+ /** -+ * Gets the display name. -+ * -+ *

    Plugins should check that {@link #hasDisplayName()} returns true before calling this method.

    -+ * -+ * @return the display name -+ */ -+ @Nullable net.kyori.adventure.text.Component displayName(); -+ -+ /** -+ * Sets the display name. -+ * -+ * @param displayName the display name to set -+ */ -+ void displayName(final @Nullable net.kyori.adventure.text.Component displayName); -+ // Paper end -+ - /** - * Gets the display name that is set. - *

    -@@ -38,7 +56,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - * before calling this method. - * - * @return the display name that is set -+ * @deprecated in favour of {@link #displayName()} - */ -+ @Deprecated // Paper - @NotNull - String getDisplayName(); - -@@ -46,7 +66,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - * Sets the display name. - * - * @param name the name to set -+ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setDisplayName(@Nullable String name); - - /** -@@ -81,6 +103,24 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - */ - boolean hasLore(); - -+ // Paper start -+ /** -+ * Gets the lore. -+ * -+ *

    Plugins should check that {@link #hasLore()} returns true before calling this method.

    -+ * -+ * @return the display name -+ */ -+ @Nullable List lore(); -+ -+ /** -+ * Sets the lore. -+ * -+ * @param lore the lore to set -+ */ -+ void lore(final @Nullable List lore); -+ // Paper end -+ - /** - * Gets the lore that is set. - *

    -@@ -88,7 +128,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - * calling this method. - * - * @return a list of lore that is set -+ * @deprecated in favour of {@link #lore()} - */ -+ @Deprecated // Paper - @Nullable - List getLore(); - -@@ -97,7 +139,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - * Removes lore when given null. - * - * @param lore the lore that will be set -+ * @deprecated in favour of {@link #lore(List)} - */ -+ @Deprecated // Paper - void setLore(@Nullable List lore); - - /** -diff --git a/src/main/java/org/bukkit/map/MapCursor.java b/src/main/java/org/bukkit/map/MapCursor.java -index 83354b2a38b6261b172b91c1008dcf3313cc4a8f..ed0bc2024a0bb85837e25f75ae89d1fe257b2e60 100644 ---- a/src/main/java/org/bukkit/map/MapCursor.java -+++ b/src/main/java/org/bukkit/map/MapCursor.java -@@ -10,7 +10,7 @@ public final class MapCursor { - private byte x, y; - private byte direction, type; - private boolean visible; -- private String caption; -+ private net.kyori.adventure.text.Component caption; // Paper - - /** - * Initialize the map cursor. -@@ -24,7 +24,7 @@ public final class MapCursor { - */ - @Deprecated - public MapCursor(byte x, byte y, byte direction, byte type, boolean visible) { -- this(x, y, direction, type, visible, null); -+ this(x, y, direction, type, visible, (String) null); // Paper - } - - /** -@@ -37,7 +37,7 @@ public final class MapCursor { - * @param visible Whether the cursor is visible by default. - */ - public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible) { -- this(x, y, direction, type, visible, null); -+ this(x, y, direction, type, visible, (String) null); // Paper - } - - /** -@@ -49,7 +49,7 @@ public final class MapCursor { - * @param type The type (color/style) of the map cursor. - * @param visible Whether the cursor is visible by default. - * @param caption cursor caption -- * @deprecated Magic value -+ * @deprecated Magic value. Use {@link #MapCursor(byte, byte, byte, byte, boolean, net.kyori.adventure.text.Component)} - */ - @Deprecated - public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, @Nullable String caption) { -@@ -58,8 +58,42 @@ public final class MapCursor { - setDirection(direction); - setRawType(type); - this.visible = visible; -- this.caption = caption; -+ this.caption = caption == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(caption); // Paper - } -+ // Paper start -+ /** -+ * Initialize the map cursor. -+ * -+ * @param x The x coordinate, from -128 to 127. -+ * @param y The y coordinate, from -128 to 127. -+ * @param direction The facing of the cursor, from 0 to 15. -+ * @param type The type (color/style) of the map cursor. -+ * @param visible Whether the cursor is visible by default. -+ * @param caption cursor caption -+ * @deprecated Magic value -+ */ -+ @Deprecated -+ public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, @Nullable net.kyori.adventure.text.Component caption) { -+ this.x = x; this.y = y; this.visible = visible; this.caption = caption; -+ setDirection(direction); -+ setRawType(type); -+ } -+ /** -+ * Initialize the map cursor. -+ * -+ * @param x The x coordinate, from -128 to 127. -+ * @param y The y coordinate, from -128 to 127. -+ * @param direction The facing of the cursor, from 0 to 15. -+ * @param type The type (color/style) of the map cursor. -+ * @param visible Whether the cursor is visible by default. -+ * @param caption cursor caption -+ */ -+ public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible, @Nullable net.kyori.adventure.text.Component caption) { -+ this.x = x; this.y = y; this.visible = visible; this.caption = caption; -+ setDirection(direction); -+ setType(type); -+ } -+ // Paper end - - /** - * Initialize the map cursor. -@@ -77,7 +111,7 @@ public final class MapCursor { - setDirection(direction); - setType(type); - this.visible = visible; -- this.caption = caption; -+ this.caption = caption == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(caption); // Paper - } - - /** -@@ -200,23 +234,45 @@ public final class MapCursor { - this.visible = visible; - } - -+ // Paper start -+ /** -+ * Gets the caption on this cursor. -+ * -+ * @return caption -+ */ -+ public @Nullable net.kyori.adventure.text.Component caption() { -+ return this.caption; -+ } -+ /** -+ * Sets the caption on this cursor. -+ * -+ * @param caption new caption -+ */ -+ public void caption(@Nullable net.kyori.adventure.text.Component caption) { -+ this.caption = caption; -+ } -+ // Paper end - /** - * Gets the caption on this cursor. - * - * @return caption -+ * @deprecated in favour of {@link #caption()} - */ - @Nullable -+ @Deprecated // Paper - public String getCaption() { -- return caption; -+ return this.caption == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.caption); // Paper - } - - /** - * Sets the caption on this cursor. - * - * @param caption new caption -+ * @deprecated in favour of {@link #caption(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setCaption(@Nullable String caption) { -- this.caption = caption; -+ this.caption = caption == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(caption); // Paper - } - - /** -diff --git a/src/main/java/org/bukkit/map/MapCursorCollection.java b/src/main/java/org/bukkit/map/MapCursorCollection.java -index 4dba721aefe4fc6699b3b4bfa7ecb0b19c2a2a1a..01dec2c877df58c9dc22445e8b1f9ce2e53066da 100644 ---- a/src/main/java/org/bukkit/map/MapCursorCollection.java -+++ b/src/main/java/org/bukkit/map/MapCursorCollection.java -@@ -117,4 +117,22 @@ public final class MapCursorCollection { - public MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible, @Nullable String caption) { - return addCursor(new MapCursor((byte) x, (byte) y, direction, type, visible, caption)); - } -+ // Paper start -+ /** -+ * Add a cursor to the collection. -+ * -+ * @param x The x coordinate, from -128 to 127. -+ * @param y The y coordinate, from -128 to 127. -+ * @param direction The facing of the cursor, from 0 to 15. -+ * @param type The type (color/style) of the map cursor. -+ * @param visible Whether the cursor is visible. -+ * @param caption banner caption -+ * @return The newly added MapCursor. -+ * @deprecated Magic value -+ */ -+ @Deprecated -+ public @NotNull MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible, @Nullable net.kyori.adventure.text.Component caption) { -+ return addCursor(new MapCursor((byte) x, (byte) y, direction, type, visible, caption)); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/scoreboard/Objective.java b/src/main/java/org/bukkit/scoreboard/Objective.java -index f5cbf6df32ef169cf0f2266f7c6e9c4f771ccb7d..58bddb11fd534e7c33a4ffd7b72b055ba92c767a 100644 ---- a/src/main/java/org/bukkit/scoreboard/Objective.java -+++ b/src/main/java/org/bukkit/scoreboard/Objective.java -@@ -19,14 +19,35 @@ public interface Objective { - */ - @NotNull - String getName() throws IllegalStateException; -+ // Paper start -+ /** -+ * Gets the name displayed to players for this objective -+ * -+ * @return this objective's display name -+ * @throws IllegalStateException if this objective has been unregistered -+ */ -+ @NotNull net.kyori.adventure.text.Component displayName() throws IllegalStateException; -+ /** -+ * Sets the name displayed to players for this objective. -+ * -+ * @param displayName Display name to set -+ * @throws IllegalStateException if this objective has been unregistered -+ * @throws IllegalArgumentException if displayName is null -+ * @throws IllegalArgumentException if displayName is longer than 128 -+ * characters. -+ */ -+ void displayName(@Nullable net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException; -+ // Paper end - - /** - * Gets the name displayed to players for this objective - * - * @return this objective's display name - * @throws IllegalStateException if this objective has been unregistered -+ * @deprecated in favour of {@link #displayName()} - */ - @NotNull -+ @Deprecated // Paper - String getDisplayName() throws IllegalStateException; - - /** -@@ -37,7 +58,9 @@ public interface Objective { - * @throws IllegalArgumentException if displayName is null - * @throws IllegalArgumentException if displayName is longer than 128 - * characters. -+ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setDisplayName(@NotNull String displayName) throws IllegalStateException, IllegalArgumentException; - - /** -diff --git a/src/main/java/org/bukkit/scoreboard/Scoreboard.java b/src/main/java/org/bukkit/scoreboard/Scoreboard.java -index 4bfaaea78c9b6aa5d392629aa943d26dbe6a7d4a..f09ff32cc3ffc16af379a378b1948991435393e8 100644 ---- a/src/main/java/org/bukkit/scoreboard/Scoreboard.java -+++ b/src/main/java/org/bukkit/scoreboard/Scoreboard.java -@@ -27,6 +27,48 @@ public interface Scoreboard { - @Deprecated - @NotNull - Objective registerNewObjective(@NotNull String name, @NotNull String criteria) throws IllegalArgumentException; -+ // Paper start -+ /** -+ * Registers an Objective on this Scoreboard -+ * -+ * @param name Name of the Objective -+ * @param criteria Criteria for the Objective -+ * @param displayName Name displayed to players for the Objective. -+ * @return The registered Objective -+ * @throws IllegalArgumentException if name is null -+ * @throws IllegalArgumentException if name is longer than 16 -+ * characters. -+ * @throws IllegalArgumentException if criteria is null -+ * @throws IllegalArgumentException if displayName is null -+ * @throws IllegalArgumentException if displayName is longer than 128 -+ * characters. -+ * @throws IllegalArgumentException if an objective by that name already -+ * exists -+ */ -+ @NotNull -+ Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @Nullable net.kyori.adventure.text.Component displayName) throws IllegalArgumentException; -+ /** -+ * Registers an Objective on this Scoreboard -+ * -+ * @param name Name of the Objective -+ * @param criteria Criteria for the Objective -+ * @param displayName Name displayed to players for the Objective. -+ * @param renderType Manner of rendering the Objective -+ * @return The registered Objective -+ * @throws IllegalArgumentException if name is null -+ * @throws IllegalArgumentException if name is longer than 16 -+ * characters. -+ * @throws IllegalArgumentException if criteria is null -+ * @throws IllegalArgumentException if displayName is null -+ * @throws IllegalArgumentException if displayName is longer than 128 -+ * characters. -+ * @throws IllegalArgumentException if renderType is null -+ * @throws IllegalArgumentException if an objective by that name already -+ * exists -+ */ -+ @NotNull -+ Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @Nullable net.kyori.adventure.text.Component displayName, @NotNull RenderType renderType) throws IllegalArgumentException; -+ // Paper end - - /** - * Registers an Objective on this Scoreboard -@@ -44,8 +86,10 @@ public interface Scoreboard { - * characters. - * @throws IllegalArgumentException if an objective by that name already - * exists -+ * @deprecated in favour of {@link #registerNewObjective(String, String, net.kyori.adventure.text.Component)} - */ - @NotNull -+ @Deprecated // Paper - Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @NotNull String displayName) throws IllegalArgumentException; - - /** -@@ -66,8 +110,10 @@ public interface Scoreboard { - * @throws IllegalArgumentException if renderType is null - * @throws IllegalArgumentException if an objective by that name already - * exists -+ * @deprecated in favour of {@link #registerNewObjective(String, String, net.kyori.adventure.text.Component, RenderType)} - */ - @NotNull -+ @Deprecated // Paper - Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @NotNull String displayName, @NotNull RenderType renderType) throws IllegalArgumentException; - - /** -diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java -index da01d2926cc8a2485a3349ac1ebb32cad20e287c..f0af10a5b9ad048be197ed5ec6c8ed2672eb3dd5 100644 ---- a/src/main/java/org/bukkit/scoreboard/Team.java -+++ b/src/main/java/org/bukkit/scoreboard/Team.java -@@ -22,14 +22,95 @@ public interface Team { - */ - @NotNull - String getName() throws IllegalStateException; -+ // Paper start -+ /** -+ * Gets the name displayed to entries for this team -+ * -+ * @return Team display name -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ @NotNull net.kyori.adventure.text.Component displayName() throws IllegalStateException; -+ -+ /** -+ * Sets the name displayed to entries for this team -+ * -+ * @param displayName New display name -+ * @throws IllegalArgumentException if displayName is longer than 128 -+ * characters. -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ void displayName(@Nullable net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException; -+ -+ /** -+ * Gets the prefix prepended to the display of entries on this team. -+ * -+ * @return Team prefix -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ @NotNull net.kyori.adventure.text.Component prefix() throws IllegalStateException; -+ -+ /** -+ * Sets the prefix prepended to the display of entries on this team. -+ * -+ * @param prefix New prefix -+ * @throws IllegalArgumentException if prefix is null -+ * @throws IllegalArgumentException if prefix is longer than 64 -+ * characters -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ void prefix(@Nullable net.kyori.adventure.text.Component prefix) throws IllegalStateException, IllegalArgumentException; -+ -+ /** -+ * Gets the suffix appended to the display of entries on this team. -+ * -+ * @return the team's current suffix -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ @NotNull net.kyori.adventure.text.Component suffix() throws IllegalStateException; -+ -+ /** -+ * Sets the suffix appended to the display of entries on this team. -+ * -+ * @param suffix the new suffix for this team. -+ * @throws IllegalArgumentException if suffix is null -+ * @throws IllegalArgumentException if suffix is longer than 64 -+ * characters -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ void suffix(@Nullable net.kyori.adventure.text.Component suffix) throws IllegalStateException, IllegalArgumentException; -+ -+ /** -+ * Gets the color of the team. -+ *
    -+ * This only sets the team outline, other occurrences of colors such as in -+ * names are handled by prefixes / suffixes. -+ * -+ * @return team color, defaults to {@link ChatColor#RESET} -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ @NotNull net.kyori.adventure.text.format.TextColor color() throws IllegalStateException; -+ -+ /** -+ * Sets the color of the team. -+ *
    -+ * This only sets the team outline, other occurrences of colors such as in -+ * names are handled by prefixes / suffixes. -+ * -+ * @param color new color, must be non-null. Use {@link ChatColor#RESET} for -+ * no color -+ */ -+ void color(@Nullable net.kyori.adventure.text.format.NamedTextColor color); -+ // Paper end - - /** - * Gets the name displayed to entries for this team - * - * @return Team display name - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #displayName()} - */ - @NotNull -+ @Deprecated // Paper - String getDisplayName() throws IllegalStateException; - - /** -@@ -39,7 +120,9 @@ public interface Team { - * @throws IllegalArgumentException if displayName is longer than 128 - * characters. - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setDisplayName(@NotNull String displayName) throws IllegalStateException, IllegalArgumentException; - - /** -@@ -47,8 +130,10 @@ public interface Team { - * - * @return Team prefix - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #prefix()} - */ - @NotNull -+ @Deprecated // Paper - String getPrefix() throws IllegalStateException; - - /** -@@ -59,7 +144,9 @@ public interface Team { - * @throws IllegalArgumentException if prefix is longer than 64 - * characters - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #prefix(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setPrefix(@NotNull String prefix) throws IllegalStateException, IllegalArgumentException; - - /** -@@ -67,8 +154,10 @@ public interface Team { - * - * @return the team's current suffix - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #suffix()} - */ - @NotNull -+ @Deprecated // Paper - String getSuffix() throws IllegalStateException; - - /** -@@ -79,7 +168,9 @@ public interface Team { - * @throws IllegalArgumentException if suffix is longer than 64 - * characters - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #suffix(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setSuffix(@NotNull String suffix) throws IllegalStateException, IllegalArgumentException; - - /** -@@ -90,8 +181,10 @@ public interface Team { - * - * @return team color, defaults to {@link ChatColor#RESET} - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #color()} - */ - @NotNull -+ @Deprecated // Paper - ChatColor getColor() throws IllegalStateException; - - /** -@@ -102,7 +195,9 @@ public interface Team { - * - * @param color new color, must be non-null. Use {@link ChatColor#RESET} for - * no color -+ * @deprecated in favour of {@link #color(net.kyori.adventure.text.format.NamedTextColor)} - */ -+ @Deprecated // Paper - void setColor(@NotNull ChatColor color); - - /** -diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 0c7377247ad9251c9e498039511e7220370aba2d..c62919f18f318fec15a6c364d8b6d562c2b04762 100644 ---- a/src/test/java/org/bukkit/AnnotationTest.java -+++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -26,6 +26,12 @@ import org.objectweb.asm.tree.ParameterNode; - public class AnnotationTest { - - private static final String[] ACCEPTED_ANNOTATIONS = { -+ // Paper start -+ "Lorg/checkerframework/checker/nullness/qual/Nullable;", -+ "Lorg/checkerframework/checker/nullness/qual/NonNull;", -+ "Lorg/checkerframework/checker/nullness/qual/PolyNull;", -+ "Lorg/checkerframework/checker/nullness/qual/MonotonicNonNull;", -+ // Paper end - "Lorg/jetbrains/annotations/Nullable;", - "Lorg/jetbrains/annotations/NotNull;", - "Lorg/jetbrains/annotations/Contract;", -@@ -66,7 +72,7 @@ public class AnnotationTest { - continue; - } - -- if (mustBeAnnotated(Type.getReturnType(method.desc)) && !isWellAnnotated(method.invisibleAnnotations)) { -+ if (mustBeAnnotated(Type.getReturnType(method.desc)) && !isWellAnnotated(method.invisibleAnnotations) && !isWellAnnotated(method.visibleTypeAnnotations)) { // Paper - also check visible type annotations - warn(errors, clazz, method, "return value"); - } - -@@ -174,7 +180,7 @@ public class AnnotationTest { - return true; - } - -- private static boolean isWellAnnotated(@Nullable List annotations) { -+ private static boolean isWellAnnotated(@Nullable List annotations) { // Paper - allow children of AnnotationNode - if (annotations == null) { - return false; - } diff --git a/Unmapped-Spigot-API-Patches/0006-Player-affects-spawning-API.patch b/Unmapped-Spigot-API-Patches/0006-Player-affects-spawning-API.patch deleted file mode 100644 index f923a3d19b..0000000000 --- a/Unmapped-Spigot-API-Patches/0006-Player-affects-spawning-API.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Mon, 29 Feb 2016 17:22:34 -0600 -Subject: [PATCH] Player affects spawning API - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 171e2663301f654258dbd772a57688b5a2f8469c..76ac0b20842002ce1b593e338bea98483e7080ac 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1380,6 +1380,22 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - @Deprecated // Paper - public String getLocale(); - -+ // Paper start -+ /** -+ * Get whether the player can affect mob spawning -+ * -+ * @return if the player can affect mob spawning -+ */ -+ public boolean getAffectsSpawning(); -+ -+ /** -+ * Set whether the player can affect mob spawning -+ * -+ * @param affects Whether the player can affect mob spawning -+ */ -+ public void setAffectsSpawning(boolean affects); -+ // Paper end -+ - /** - * Update the list of commands sent to the client. - *
    diff --git a/Unmapped-Spigot-API-Patches/0007-Add-getTPS-method.patch b/Unmapped-Spigot-API-Patches/0007-Add-getTPS-method.patch deleted file mode 100644 index 22aef5d962..0000000000 --- a/Unmapped-Spigot-API-Patches/0007-Add-getTPS-method.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Feb 2016 17:24:57 -0600 -Subject: [PATCH] Add getTPS method - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index ab4d5aca6251b620ef5d654fa4ea3fc31783c2f2..0636edd8d9121eabfa60957c8c224261d228a16b 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1543,6 +1543,17 @@ public final class Bukkit { - return server.getEntity(uuid); - } - -+ // Paper start -+ /** -+ * Gets the current server TPS -+ * @return current server TPS (1m, 5m, 15m in Paper-Server) -+ */ -+ @NotNull -+ public static double[] getTPS() { -+ return server.getTPS(); -+ } -+ // Paper end -+ - /** - * 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 b862f22d5f31934eb46b50ecf04f8c1bf23c5044..5c638e0d45e8896382bdbf9b9c10474b05a97df5 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1301,6 +1301,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @Nullable - Entity getEntity(@NotNull UUID uuid); - -+ // Paper start -+ /** -+ * Gets the current server TPS -+ * -+ * @return current server TPS (1m, 5m, 15m in Paper-Server) -+ */ -+ @NotNull -+ public double[] getTPS(); -+ // Paper end -+ - /** - * Get the advancement specified by this key. - * diff --git a/Unmapped-Spigot-API-Patches/0008-Entity-Origin-API.patch b/Unmapped-Spigot-API-Patches/0008-Entity-Origin-API.patch deleted file mode 100644 index 626916f4f7..0000000000 --- a/Unmapped-Spigot-API-Patches/0008-Entity-Origin-API.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Mon, 29 Feb 2016 17:50:31 -0600 -Subject: [PATCH] Entity Origin API - - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 03e12de470f983e89a473c4e42c21941085b1d37..fdce246aecac775c3ff4a028c307b09762505258 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -655,5 +655,15 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { - return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.customName()))); - } -+ -+ /** -+ * Gets the location where this entity originates from. -+ *

    -+ * This value can be null if the entity hasn't yet been added to the world. -+ * -+ * @return Location where entity originates or null if not yet added -+ */ -+ @Nullable -+ Location getOrigin(); - // Paper end - } -diff --git a/src/main/java/org/bukkit/entity/FallingBlock.java b/src/main/java/org/bukkit/entity/FallingBlock.java -index 64f9d3fd870d65afd2ee9a85625b149163eee144..14cb0d770561151570ab4399ca5facff43076819 100644 ---- a/src/main/java/org/bukkit/entity/FallingBlock.java -+++ b/src/main/java/org/bukkit/entity/FallingBlock.java -@@ -54,4 +54,15 @@ public interface FallingBlock extends Entity { - * @param hurtEntities whether entities will be damaged by this block. - */ - void setHurtEntities(boolean hurtEntities); -+ -+ /** -+ * Gets the source block location of the FallingBlock -+ * -+ * @return the source block location the FallingBlock was spawned from -+ * @deprecated replaced by {@link Entity#getOrigin()} -+ */ -+ @Deprecated -+ default org.bukkit.Location getSourceLoc() { -+ return this.getOrigin(); -+ } - } -diff --git a/src/main/java/org/bukkit/entity/TNTPrimed.java b/src/main/java/org/bukkit/entity/TNTPrimed.java -index a23cfdf66877f0a61eae700de084c76e6ee7b431..0813bd913c8fdb2001963ce3e82c07c2af105418 100644 ---- a/src/main/java/org/bukkit/entity/TNTPrimed.java -+++ b/src/main/java/org/bukkit/entity/TNTPrimed.java -@@ -53,4 +53,15 @@ public interface TNTPrimed extends Explosive { - * @param source the source of this primed TNT - */ - public void setSource(@Nullable Entity source); -+ -+ /** -+ * Gets the source block location of the TNTPrimed -+ * -+ * @return the source block location the TNTPrimed was spawned from -+ * @deprecated replaced by {@link Entity#getOrigin()} -+ */ -+ @Deprecated -+ default org.bukkit.Location getSourceLoc() { -+ return this.getOrigin(); -+ } - } diff --git a/Unmapped-Spigot-API-Patches/0009-Version-Command-2.0.patch b/Unmapped-Spigot-API-Patches/0009-Version-Command-2.0.patch deleted file mode 100644 index c7cc974e1a..0000000000 --- a/Unmapped-Spigot-API-Patches/0009-Version-Command-2.0.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 27 May 2019 01:10:06 -0500 -Subject: [PATCH] Version Command 2.0 - - -diff --git a/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a736d7bcdc5861a01b66ba36158db1c716339346 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java -@@ -0,0 +1,45 @@ -+package com.destroystokyo.paper.util; -+ -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.format.NamedTextColor; -+import org.bukkit.Bukkit; -+import org.jetbrains.annotations.NotNull; -+ -+public interface VersionFetcher { -+ /** -+ * Amount of time to cache results for in milliseconds -+ *

    -+ * Negative values will never cache. -+ * -+ * @return cache time -+ */ -+ long getCacheTime(); -+ -+ /** -+ * Gets the version message to cache and show to command senders. -+ * -+ *

    NOTE: This is run in a new thread separate from that of the command processing thread

    -+ * -+ * @param serverVersion the current version of the server (will match {@link Bukkit#getVersion()}) -+ * @return the message to show when requesting a version -+ */ -+ @NotNull -+ Component getVersionMessage(@NotNull String serverVersion); -+ -+ class DummyVersionFetcher implements VersionFetcher { -+ -+ @Override -+ public long getCacheTime() { -+ return -1; -+ } -+ -+ @NotNull -+ @Override -+ public Component getVersionMessage(@NotNull String serverVersion) { -+ Bukkit.getLogger().warning("Version provider has not been set, cannot check for updates!"); -+ Bukkit.getLogger().info("Override the default implementation of org.bukkit.UnsafeValues#getVersionFetcher()"); -+ new Throwable().printStackTrace(); -+ return Component.text("Unable to check for updates. No version provider set.", NamedTextColor.RED); -+ } -+ } -+} -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 207c656c0a11a3a630bc70491efcf433b2681e18..195b6bb328de92c4d17d1cd14e13578226b1ac3c 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -84,5 +84,12 @@ public interface UnsafeValues { - * @return name - */ - String getTimingsServerName(); -+ -+ /** -+ * Called once by the version command on first use, then cached. -+ */ -+ default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { -+ return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher(); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/command/defaults/VersionCommand.java b/src/main/java/org/bukkit/command/defaults/VersionCommand.java -index 2305eb40832a82159cd89162934870cf57e1aa0e..4c2ddc722a9dc4011906ad9530b13fa9be1d3ff9 100644 ---- a/src/main/java/org/bukkit/command/defaults/VersionCommand.java -+++ b/src/main/java/org/bukkit/command/defaults/VersionCommand.java -@@ -1,5 +1,6 @@ - package org.bukkit.command.defaults; - -+import com.destroystokyo.paper.util.VersionFetcher; // Paper - version supplier - import com.google.common.base.Charsets; - import com.google.common.collect.ImmutableList; - import com.google.common.io.Resources; -@@ -16,6 +17,7 @@ import java.util.HashSet; - import java.util.List; - import java.util.Set; - import java.util.concurrent.locks.ReentrantLock; -+import net.kyori.adventure.text.Component; // Paper - import org.apache.commons.lang.Validate; - import org.bukkit.Bukkit; - import org.bukkit.ChatColor; -@@ -26,6 +28,15 @@ import org.bukkit.util.StringUtil; - import org.jetbrains.annotations.NotNull; - - public class VersionCommand extends BukkitCommand { -+ private VersionFetcher versionFetcher; -+ private VersionFetcher getVersionFetcher() { // lazy load because unsafe isn't available at command registration -+ if (versionFetcher == null) { -+ versionFetcher = Bukkit.getUnsafe().getVersionFetcher(); -+ } -+ -+ return versionFetcher; -+ } -+ - public VersionCommand(@NotNull String name) { - super(name); - -@@ -40,7 +51,7 @@ public class VersionCommand extends BukkitCommand { - if (!testPermission(sender)) return true; - - if (args.length == 0) { -- sender.sendMessage("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")"); -+ //sender.sendMessage("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")"); // Paper - moved to setVersionMessage - sendVersion(sender); - } else { - StringBuilder name = new StringBuilder(); -@@ -146,14 +157,14 @@ public class VersionCommand extends BukkitCommand { - - private final ReentrantLock versionLock = new ReentrantLock(); - private boolean hasVersion = false; -- private String versionMessage = null; -+ private Component versionMessage = null; // Paper - private final Set versionWaiters = new HashSet(); - private boolean versionTaskStarted = false; - private long lastCheck = 0; - - private void sendVersion(@NotNull CommandSender sender) { - if (hasVersion) { -- if (System.currentTimeMillis() - lastCheck > 21600000) { -+ if (System.currentTimeMillis() - lastCheck > getVersionFetcher().getCacheTime()) { // Paper - use version supplier - lastCheck = System.currentTimeMillis(); - hasVersion = false; - } else { -@@ -168,7 +179,7 @@ public class VersionCommand extends BukkitCommand { - return; - } - versionWaiters.add(sender); -- sender.sendMessage("Checking version, please wait..."); -+ sender.sendMessage(Component.text("Checking version, please wait...", net.kyori.adventure.text.format.NamedTextColor.WHITE, net.kyori.adventure.text.format.TextDecoration.ITALIC)); // Paper - if (!versionTaskStarted) { - versionTaskStarted = true; - new Thread(new Runnable() { -@@ -186,6 +197,13 @@ public class VersionCommand extends BukkitCommand { - - private void obtainVersion() { - String version = Bukkit.getVersion(); -+ // Paper start -+ if (version.startsWith("null")) { // running from ide? -+ setVersionMessage(Component.text("Unknown version, custom build?", net.kyori.adventure.text.format.NamedTextColor.YELLOW)); -+ return; -+ } -+ setVersionMessage(getVersionFetcher().getVersionMessage(version)); -+ /* - if (version == null) version = "Custom"; - String[] parts = version.substring(0, version.indexOf(' ')).split("-"); - if (parts.length == 4) { -@@ -215,11 +233,24 @@ public class VersionCommand extends BukkitCommand { - } else { - setVersionMessage("Unknown version, custom build?"); - } -+ */ -+ // Paper end - } - -- private void setVersionMessage(@NotNull String msg) { -+ // Paper start -+ private void setVersionMessage(final @NotNull Component msg) { - lastCheck = System.currentTimeMillis(); -- versionMessage = msg; -+ final Component message = net.kyori.adventure.text.TextComponent.ofChildren( -+ Component.text("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")", net.kyori.adventure.text.format.NamedTextColor.WHITE), -+ Component.newline(), -+ msg -+ ); -+ this.versionMessage = Component.text() -+ .append(message) -+ .hoverEvent(Component.text("Click to copy to clipboard", net.kyori.adventure.text.format.NamedTextColor.WHITE)) -+ .clickEvent(net.kyori.adventure.text.event.ClickEvent.copyToClipboard(net.kyori.adventure.text.serializer.plain.PlainComponentSerializer.plain().serialize(message))) -+ .build(); -+ // Paper end - versionLock.lock(); - try { - hasVersion = true; diff --git a/Unmapped-Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch b/Unmapped-Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch deleted file mode 100644 index 10593168ec..0000000000 --- a/Unmapped-Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Isaac Moore -Date: Mon, 29 Feb 2016 18:02:25 -0600 -Subject: [PATCH] Add PlayerLocaleChangeEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..29dd763a99ce7c6ecb176b9fb346a400369d48a0 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java -@@ -0,0 +1,50 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+ -+/** -+ * Called when the locale of the player is changed. -+ * -+ * @deprecated Replaced by {@link org.bukkit.event.player.PlayerLocaleChangeEvent} upstream -+ */ -+@Deprecated -+public class PlayerLocaleChangeEvent extends PlayerEvent { -+ private static final HandlerList handlers = new HandlerList(); -+ private final String oldLocale; -+ private final String newLocale; -+ -+ public PlayerLocaleChangeEvent(final Player player, final String oldLocale, final String newLocale) { -+ super(player); -+ this.oldLocale = oldLocale; -+ this.newLocale = newLocale; -+ } -+ -+ /** -+ * Gets the locale the player switched from. -+ * -+ * @return player's old locale -+ */ -+ public String getOldLocale() { -+ return oldLocale; -+ } -+ -+ /** -+ * Gets the locale the player is changed to. -+ * -+ * @return player's new locale -+ */ -+ public String getNewLocale() { -+ return newLocale; -+ } -+ -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0011-Add-player-view-distance-API.patch b/Unmapped-Spigot-API-Patches/0011-Add-player-view-distance-API.patch deleted file mode 100644 index 8b5561ac14..0000000000 --- a/Unmapped-Spigot-API-Patches/0011-Add-player-view-distance-API.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Mon, 29 Feb 2016 18:05:37 -0600 -Subject: [PATCH] Add player view distance API - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 76ac0b20842002ce1b593e338bea98483e7080ac..f34601480a3b3069c30c52d258a35a2a79c981fb 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1394,6 +1394,28 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param affects Whether the player can affect mob spawning - */ - public void setAffectsSpawning(boolean affects); -+ -+ /** -+ * Gets the view distance for this player -+ * -+ * @return the player's view distance -+ * @deprecated This is unimplemented and will throw an exception at runtime. The {@link org.bukkit.World World}-based methods still work. -+ * @see org.bukkit.World#getViewDistance() -+ * @see org.bukkit.World#getNoTickViewDistance() -+ */ -+ @Deprecated -+ public int getViewDistance(); -+ -+ /** -+ * Sets the view distance for this player -+ * -+ * @param viewDistance the player's view distance -+ * @deprecated This is unimplemented and will throw an exception at runtime. The {@link org.bukkit.World World}-based methods still work. -+ * @see org.bukkit.World#setViewDistance(int) -+ * @see org.bukkit.World#setNoTickViewDistance(int) -+ */ -+ @Deprecated -+ public void setViewDistance(int viewDistance); - // Paper end - - /** diff --git a/Unmapped-Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch b/Unmapped-Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch deleted file mode 100644 index 43af3c3828..0000000000 --- a/Unmapped-Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Mon, 29 Feb 2016 18:09:40 -0600 -Subject: [PATCH] Add BeaconEffectEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..978813b94a5eae0afccbd3b38b463091a46b56ac ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java -@@ -0,0 +1,86 @@ -+package com.destroystokyo.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.bukkit.potion.PotionEffect; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a beacon effect is being applied to a player. -+ */ -+public class BeaconEffectEvent extends BlockEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ private PotionEffect effect; -+ private Player player; -+ private boolean primary; -+ -+ public BeaconEffectEvent(@NotNull Block block, @NotNull PotionEffect effect, @NotNull Player player, boolean primary) { -+ super(block); -+ this.effect = effect; -+ this.player = player; -+ this.primary = primary; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ /** -+ * Gets the potion effect being applied. -+ * -+ * @return Potion effect -+ */ -+ @NotNull -+ public PotionEffect getEffect() { -+ return effect; -+ } -+ -+ /** -+ * Sets the potion effect that will be applied. -+ * -+ * @param effect Potion effect -+ */ -+ public void setEffect(@NotNull PotionEffect effect) { -+ this.effect = effect; -+ } -+ -+ /** -+ * Gets the player who the potion effect is being applied to. -+ * -+ * @return Affected player -+ */ -+ @NotNull -+ public Player getPlayer() { -+ return player; -+ } -+ -+ /** -+ * Gets whether the effect is a primary beacon effect. -+ * -+ * @return true if this event represents a primary effect -+ */ -+ public boolean isPrimary() { -+ return primary; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch b/Unmapped-Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch deleted file mode 100644 index c113777bf5..0000000000 --- a/Unmapped-Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Steve Anton -Date: Mon, 29 Feb 2016 18:13:58 -0600 -Subject: [PATCH] Add PlayerInitialSpawnEvent - -For modifying a player's initial spawn location as they join the server - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8b1fdb9d2869d4c1862d557c91bf8a1d8c537507 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java -@@ -0,0 +1,16 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+import org.spigotmc.event.player.PlayerSpawnLocationEvent; -+ -+/** -+ * @deprecated Use {@link PlayerSpawnLocationEvent}, Duplicate API -+ */ -+public class PlayerInitialSpawnEvent extends PlayerSpawnLocationEvent { -+ -+ public PlayerInitialSpawnEvent(@NotNull Player who, @NotNull Location spawnLocation) { -+ super(who, spawnLocation); -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch b/Unmapped-Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch deleted file mode 100644 index 55aeb559ba..0000000000 --- a/Unmapped-Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Feb 2016 19:45:21 -0600 -Subject: [PATCH] Automatically disable plugins that fail to load - - -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index cf2f517765d8f2a23cc4a17d9ee2dcd81f841b1b..2e306c7b984a02e12a74fac14589bf29ab6488bf 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -335,6 +335,10 @@ public final class JavaPluginLoader implements PluginLoader { - jPlugin.setEnabled(true); - } catch (Throwable ex) { - server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ // Paper start - Disable plugins that fail to load -+ disablePlugin(jPlugin); -+ return; -+ // Paper end - } - - // Perhaps abort here, rather than continue going, but as it stands, diff --git a/Unmapped-Spigot-API-Patches/0015-Expose-server-CommandMap.patch b/Unmapped-Spigot-API-Patches/0015-Expose-server-CommandMap.patch deleted file mode 100644 index 6d7e3f1431..0000000000 --- a/Unmapped-Spigot-API-Patches/0015-Expose-server-CommandMap.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Mon, 29 Feb 2016 19:48:59 -0600 -Subject: [PATCH] Expose server CommandMap - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 0636edd8d9121eabfa60957c8c224261d228a16b..8d707e117035d5bc0d8c9a5fd386ee8355359259 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1717,6 +1717,19 @@ public final class Bukkit { - return server.getUnsafe(); - } - -+ -+ // Paper start -+ /** -+ * Gets the active {@link org.bukkit.command.CommandMap} -+ * -+ * @return the active command map -+ */ -+ @NotNull -+ public static org.bukkit.command.CommandMap getCommandMap() { -+ return server.getCommandMap(); -+ } -+ // Paper end -+ - @NotNull - 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 5c638e0d45e8896382bdbf9b9c10474b05a97df5..24bcc63afbda5f27aad385dc707f262d1a3a3399 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1311,6 +1311,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - public double[] getTPS(); - // Paper end - -+ // Paper start -+ /** -+ * Gets the active {@link org.bukkit.command.CommandMap} -+ * -+ * @return the active command map -+ */ -+ @NotNull -+ org.bukkit.command.CommandMap getCommandMap(); -+ - /** - * Get the advancement specified by this key. - * diff --git a/Unmapped-Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch b/Unmapped-Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch deleted file mode 100644 index 28128cfb69..0000000000 --- a/Unmapped-Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 29 Feb 2016 19:54:32 -0600 -Subject: [PATCH] Graduate bungeecord chat API from spigot subclasses - -Change Javadoc to be accurate - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 10274053320f1ec690a65d3794abb44b58658059..22b83b142de97dcba28fa9a49730de7880d0b5d2 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -285,6 +285,30 @@ public final class Bukkit { - return server.broadcastMessage(message); - } - -+ // Paper start -+ /** -+ * Sends the component to all online players. -+ * -+ * @param component the component to send -+ * @deprecated use {@code sendMessage} methods on {@link #getServer()} that accept {@link net.kyori.adventure.text.Component} -+ */ -+ @Deprecated -+ public static void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { -+ server.broadcast(component); -+ } -+ -+ /** -+ * Sends an array of components as a single message to all online players. -+ * -+ * @param components the components to send -+ * @deprecated use {@code sendMessage} methods on {@link #getServer()} that accept {@link net.kyori.adventure.text.Component} -+ */ -+ @Deprecated -+ public static void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { -+ server.broadcast(components); -+ } -+ // Paper end -+ - /** - * Gets the name of the update folder. The update folder is used to safely - * update plugins at the right moment on a plugin load. -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 7e4a728ceb943b6a32b9ba9b84bada34e71c0980..9ce9b4ce2da6c57c62607502ae2042e30fc26d88 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -234,6 +234,30 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @Deprecated // Paper - public int broadcastMessage(@NotNull String message); - -+ // Paper start -+ /** -+ * Sends the component to all online players. -+ * -+ * @param component the component to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} -+ */ -+ @Deprecated -+ public default void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { -+ spigot().broadcast(component); -+ } -+ -+ /** -+ * Sends an array of components as a single message to all online players. -+ * -+ * @param components the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} -+ */ -+ @Deprecated -+ public default void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { -+ spigot().broadcast(components); -+ } -+ // Paper end -+ - /** - * Gets the name of the update folder. The update folder is used to safely - * update plugins at the right moment on a plugin load. -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 68795a48cb15d322906ce0569b7701231c1f94c2..88853cc165c67fd60a0a8f87e4ce356e4ca045f9 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -614,6 +614,42 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - public void sendMap(@NotNull MapView map); - -+ // Paper start -+ /** -+ * Sends the component to the player -+ * -+ * @param component the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} -+ */ -+ @Override -+ @Deprecated -+ public default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { -+ spigot().sendMessage(component); -+ } -+ -+ /** -+ * Sends an array of components as a single message to the player -+ * -+ * @param components the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} -+ */ -+ @Override -+ @Deprecated -+ public default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { -+ spigot().sendMessage(components); -+ } -+ -+ /** -+ * Sends an array of components as a single message to the specified screen position of this player -+ * -+ * @param position the screen position -+ * @param components the components to send -+ */ -+ public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { -+ spigot().sendMessage(position, components); -+ } -+ // Paper end -+ - /** - * Forces an update of the player's entire inventory. - * diff --git a/Unmapped-Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch b/Unmapped-Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch deleted file mode 100644 index 90316cae1d..0000000000 --- a/Unmapped-Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch +++ /dev/null @@ -1,577 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Mon, 29 Feb 2016 20:02:40 -0600 -Subject: [PATCH] Player Tab List and Title APIs - -Co-authored-by: Fruxz - -diff --git a/src/main/java/com/destroystokyo/paper/Title.java b/src/main/java/com/destroystokyo/paper/Title.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9e90c3df567a65b48a0b9341f784eb902cb35d8c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/Title.java -@@ -0,0 +1,420 @@ -+package com.destroystokyo.paper; -+ -+import net.md_5.bungee.api.chat.BaseComponent; -+import net.md_5.bungee.api.chat.TextComponent; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collection; -+import java.util.List; -+ -+import static com.google.common.base.Preconditions.checkArgument; -+import static com.google.common.base.Preconditions.checkNotNull; -+import static com.google.common.base.Preconditions.checkState; -+ -+/** -+ * Represents a title to may be sent to a {@link Player}. -+ * -+ *

    A title can be sent without subtitle text.

    -+ * -+ * @deprecated use {@link net.kyori.adventure.title.Title} -+ */ -+@Deprecated -+public final class Title { -+ -+ /** -+ * The default number of ticks for the title to fade in. -+ */ -+ public static final int DEFAULT_FADE_IN = 20; -+ /** -+ * The default number of ticks for the title to stay. -+ */ -+ public static final int DEFAULT_STAY = 200; -+ /** -+ * The default number of ticks for the title to fade out. -+ */ -+ public static final int DEFAULT_FADE_OUT = 20; -+ -+ private final BaseComponent[] title; -+ private final BaseComponent[] subtitle; -+ private final int fadeIn; -+ private final int stay; -+ private final int fadeOut; -+ -+ /** -+ * Create a title with the default time values and no subtitle. -+ * -+ *

    Times use default values.

    -+ * -+ * @param title the main text of the title -+ * @throws NullPointerException if the title is null -+ */ -+ public Title(@NotNull BaseComponent title) { -+ this(title, null); -+ } -+ -+ /** -+ * Create a title with the default time values and no subtitle. -+ * -+ *

    Times use default values.

    -+ * -+ * @param title the main text of the title -+ * @throws NullPointerException if the title is null -+ */ -+ public Title(@NotNull BaseComponent[] title) { -+ this(title, null); -+ } -+ -+ /** -+ * Create a title with the default time values and no subtitle. -+ * -+ *

    Times use default values.

    -+ * -+ * @param title the main text of the title -+ * @throws NullPointerException if the title is null -+ */ -+ public Title(@NotNull String title) { -+ this(title, null); -+ } -+ -+ /** -+ * Create a title with the default time values. -+ * -+ *

    Times use default values.

    -+ * -+ * @param title the main text of the title -+ * @param subtitle the secondary text of the title -+ */ -+ public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle) { -+ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT); -+ } -+ -+ /** -+ * Create a title with the default time values. -+ * -+ *

    Times use default values.

    -+ * -+ * @param title the main text of the title -+ * @param subtitle the secondary text of the title -+ */ -+ public Title(@NotNull BaseComponent[] title, @Nullable BaseComponent[] subtitle) { -+ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT); -+ } -+ -+ /** -+ * Create a title with the default time values. -+ * -+ *

    Times use default values.

    -+ * -+ * @param title the main text of the title -+ * @param subtitle the secondary text of the title -+ */ -+ public Title(@NotNull String title, @Nullable String subtitle) { -+ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT); -+ } -+ -+ /** -+ * Creates a new title. -+ * -+ * @param title the main text of the title -+ * @param subtitle the secondary text of the title -+ * @param fadeIn the number of ticks for the title to fade in -+ * @param stay the number of ticks for the title to stay on screen -+ * @param fadeOut the number of ticks for the title to fade out -+ * @throws IllegalArgumentException if any of the times are negative -+ */ -+ public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle, int fadeIn, int stay, int fadeOut) { -+ this( -+ new BaseComponent[]{checkNotNull(title, "title")}, -+ subtitle == null ? null : new BaseComponent[]{subtitle}, -+ fadeIn, -+ stay, -+ fadeOut -+ ); -+ } -+ -+ /** -+ * Creates a new title. -+ * -+ * @param title the main text of the title -+ * @param subtitle the secondary text of the title -+ * @param fadeIn the number of ticks for the title to fade in -+ * @param stay the number of ticks for the title to stay on screen -+ * @param fadeOut the number of ticks for the title to fade out -+ * @throws IllegalArgumentException if any of the times are negative -+ */ -+ public Title(@Nullable BaseComponent[] title, @NotNull BaseComponent[] subtitle, int fadeIn, int stay, int fadeOut) { -+ checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn); -+ checkArgument(stay >= 0, "Negative stay: %s", stay); -+ checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut); -+ this.title = checkNotNull(title, "title"); -+ this.subtitle = subtitle; -+ this.fadeIn = fadeIn; -+ this.stay = stay; -+ this.fadeOut = fadeOut; -+ } -+ -+ /** -+ * Creates a new title. -+ * -+ *

    It is recommended to the {@link BaseComponent} constrctors.

    -+ * -+ * @param title the main text of the title -+ * @param subtitle the secondary text of the title -+ * @param fadeIn the number of ticks for the title to fade in -+ * @param stay the number of ticks for the title to stay on screen -+ * @param fadeOut the number of ticks for the title to fade out -+ */ -+ public Title(@NotNull String title, @Nullable String subtitle, int fadeIn, int stay, int fadeOut) { -+ this( -+ TextComponent.fromLegacyText(checkNotNull(title, "title")), -+ subtitle == null ? null : TextComponent.fromLegacyText(subtitle), -+ fadeIn, -+ stay, -+ fadeOut -+ ); -+ } -+ -+ /** -+ * Gets the text of this title -+ * -+ * @return the text -+ */ -+ @NotNull -+ public BaseComponent[] getTitle() { -+ return this.title; -+ } -+ -+ /** -+ * Gets the text of this title's subtitle -+ * -+ * @return the text -+ */ -+ @Nullable -+ public BaseComponent[] getSubtitle() { -+ return this.subtitle; -+ } -+ -+ /** -+ * Gets the number of ticks to fade in. -+ * -+ *

    The returned value is never negative.

    -+ * -+ * @return the number of ticks to fade in -+ */ -+ public int getFadeIn() { -+ return this.fadeIn; -+ } -+ -+ /** -+ * Gets the number of ticks to stay. -+ * -+ *

    The returned value is never negative.

    -+ * -+ * @return the number of ticks to stay -+ */ -+ public int getStay() { -+ return this.stay; -+ } -+ -+ /** -+ * Gets the number of ticks to fade out. -+ * -+ *

    The returned value is never negative.

    -+ * -+ * @return the number of ticks to fade out -+ */ -+ public int getFadeOut() { -+ return this.fadeOut; -+ } -+ -+ /** -+ * Sends the title directly to an player -+ * -+ * @param player the receiver of the title -+ */ -+ public void send(@NotNull Player player) { -+ player.sendTitle(this); -+ } -+ -+ /** -+ * Sends the title directly to the defined players -+ * -+ * @param players the receivers of the title -+ */ -+ public void send(@NotNull Collection players) { -+ for (Player player : players) { -+ player.sendTitle(this); -+ } -+ } -+ -+ /** -+ * Sends the title directly to the defined players -+ * -+ * @param players the receivers of the title -+ */ -+ public void send(@NotNull Player[] players) { -+ for (Player player : players) { -+ player.sendTitle(this); -+ } -+ } -+ -+ /** -+ * Sends the title directly to all online players -+ */ -+ public void broadcast() { -+ send(Bukkit.getOnlinePlayers()); -+ } -+ -+ @NotNull -+ public static Builder builder() { -+ return new Builder(); -+ } -+ -+ /** -+ * A builder for creating titles -+ */ -+ public static final class Builder { -+ -+ private BaseComponent[] title; -+ private BaseComponent[] subtitle; -+ private int fadeIn = DEFAULT_FADE_IN; -+ private int stay = DEFAULT_STAY; -+ private int fadeOut = DEFAULT_FADE_OUT; -+ -+ /** -+ * Sets the title to the given text. -+ * -+ * @param title the title text -+ * @return this builder instance -+ * @throws NullPointerException if the title is null -+ */ -+ @NotNull -+ public Builder title(@NotNull BaseComponent title) { -+ return this.title(new BaseComponent[]{checkNotNull(title, "title")}); -+ } -+ -+ /** -+ * Sets the title to the given text. -+ * -+ * @param title the title text -+ * @return this builder instance -+ * @throws NullPointerException if the title is null -+ */ -+ @NotNull -+ public Builder title(@NotNull BaseComponent[] title) { -+ this.title = checkNotNull(title, "title"); -+ return this; -+ } -+ -+ /** -+ * Sets the title to the given text. -+ * -+ *

    It is recommended to the {@link BaseComponent} methods.

    -+ * -+ * @param title the title text -+ * @return this builder instance -+ * @throws NullPointerException if the title is null -+ */ -+ @NotNull -+ public Builder title(@NotNull String title) { -+ return this.title(TextComponent.fromLegacyText(checkNotNull(title, "title"))); -+ } -+ -+ /** -+ * Sets the subtitle to the given text. -+ * -+ * @param subtitle the title text -+ * @return this builder instance -+ */ -+ @NotNull -+ public Builder subtitle(@Nullable BaseComponent subtitle) { -+ return this.subtitle(subtitle == null ? null : new BaseComponent[]{subtitle}); -+ } -+ -+ /** -+ * Sets the subtitle to the given text. -+ * -+ * @param subtitle the title text -+ * @return this builder instance -+ */ -+ @NotNull -+ public Builder subtitle(@Nullable BaseComponent[] subtitle) { -+ this.subtitle = subtitle; -+ return this; -+ } -+ -+ /** -+ * Sets the subtitle to the given text. -+ * -+ *

    It is recommended to the {@link BaseComponent} methods.

    -+ * -+ * @param subtitle the title text -+ * @return this builder instance -+ */ -+ @NotNull -+ public Builder subtitle(@Nullable String subtitle) { -+ return this.subtitle(subtitle == null ? null : TextComponent.fromLegacyText(subtitle)); -+ } -+ -+ /** -+ * Sets the number of ticks for the title to fade in -+ * -+ * @param fadeIn the number of ticks to fade in -+ * @return this builder instance -+ * @throws IllegalArgumentException if it is negative -+ */ -+ @NotNull -+ public Builder fadeIn(int fadeIn) { -+ checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn); -+ this.fadeIn = fadeIn; -+ return this; -+ } -+ -+ -+ /** -+ * Sets the number of ticks for the title to stay. -+ * -+ * @param stay the number of ticks to stay -+ * @return this builder instance -+ * @throws IllegalArgumentException if it is negative -+ */ -+ @NotNull -+ public Builder stay(int stay) { -+ checkArgument(stay >= 0, "Negative stay: %s", stay); -+ this.stay = stay; -+ return this; -+ } -+ -+ /** -+ * Sets the number of ticks for the title to fade out. -+ * -+ * @param fadeOut the number of ticks to fade out -+ * @return this builder instance -+ * @throws IllegalArgumentException if it is negative -+ */ -+ @NotNull -+ public Builder fadeOut(int fadeOut) { -+ checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut); -+ this.fadeOut = fadeOut; -+ return this; -+ } -+ -+ /** -+ * Create a title based on the values in the builder. -+ * -+ * @return a title from the values in this builder -+ * @throws IllegalStateException if title isn't specified -+ */ -+ @NotNull -+ public Title build() { -+ checkState(title != null, "Title not specified"); -+ return new Title(this.title, this.subtitle, this.fadeIn, this.stay, this.fadeOut); -+ } -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 88853cc165c67fd60a0a8f87e4ce356e4ca045f9..c9e4cb2d153fc0c6853fe520263a0073e7504e38 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -2,6 +2,7 @@ package org.bukkit.entity; - - import java.net.InetSocketAddress; - import java.util.UUID; -+import com.destroystokyo.paper.Title; // Paper - import org.bukkit.DyeColor; - import org.bukkit.Effect; - import org.bukkit.GameMode; -@@ -648,6 +649,131 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { - spigot().sendMessage(position, components); - } -+ -+ /** -+ * Set the text displayed in the player list header and footer for this player -+ * -+ * @param header content for the top of the player list -+ * @param footer content for the bottom of the player list -+ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} -+ */ -+ @Deprecated -+ public void setPlayerListHeaderFooter(@Nullable net.md_5.bungee.api.chat.BaseComponent[] header, @Nullable net.md_5.bungee.api.chat.BaseComponent[] footer); -+ -+ /** -+ * Set the text displayed in the player list header and footer for this player -+ * -+ * @param header content for the top of the player list -+ * @param footer content for the bottom of the player list -+ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} -+ */ -+ @Deprecated -+ public void setPlayerListHeaderFooter(@Nullable net.md_5.bungee.api.chat.BaseComponent header, @Nullable net.md_5.bungee.api.chat.BaseComponent footer); -+ -+ /** -+ * Update the times for titles displayed to the player -+ * -+ * @param fadeInTicks ticks to fade-in -+ * @param stayTicks ticks to stay visible -+ * @param fadeOutTicks ticks to fade-out -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void setTitleTimes(int fadeInTicks, int stayTicks, int fadeOutTicks); -+ -+ /** -+ * Update the subtitle of titles displayed to the player -+ * -+ * @param subtitle Subtitle to set -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent[] subtitle); -+ -+ /** -+ * Update the subtitle of titles displayed to the player -+ * -+ * @param subtitle Subtitle to set -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent subtitle); -+ -+ /** -+ * Show the given title to the player, along with the last subtitle set, using the last set times -+ * -+ * @param title Title to set -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent[] title); -+ -+ /** -+ * Show the given title to the player, along with the last subtitle set, using the last set times -+ * -+ * @param title Title to set -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent title); -+ -+ /** -+ * Show the given title and subtitle to the player using the given times -+ * -+ * @param title big text -+ * @param subtitle little text under it -+ * @param fadeInTicks ticks to fade-in -+ * @param stayTicks ticks to stay visible -+ * @param fadeOutTicks ticks to fade-out -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent[] title, @Nullable net.md_5.bungee.api.chat.BaseComponent[] subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks); -+ -+ /** -+ * Show the given title and subtitle to the player using the given times -+ * -+ * @param title big text -+ * @param subtitle little text under it -+ * @param fadeInTicks ticks to fade-in -+ * @param stayTicks ticks to stay visible -+ * @param fadeOutTicks ticks to fade-out -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent title, @Nullable net.md_5.bungee.api.chat.BaseComponent subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks); -+ -+ /** -+ * Show the title to the player, overriding any previously displayed title. -+ * -+ *

    This method overrides any previous title, use {@link #updateTitle(Title)} to change the existing one.

    -+ * -+ * @param title the title to send -+ * @throws NullPointerException if the title is null -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ void sendTitle(@NotNull Title title); -+ -+ /** -+ * Show the title to the player, overriding any previously displayed title. -+ * -+ *

    This method doesn't override previous titles, but changes their values.

    -+ * -+ * @param title the title to send -+ * @throws NullPointerException if title is null -+ * @deprecated use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ void updateTitle(@NotNull Title title); -+ -+ /** -+ * Hide any title that is currently visible to the player -+ * -+ * @deprecated use {@link #clearTitle()} -+ */ -+ @Deprecated -+ public void hideTitle(); - // Paper end - - /** diff --git a/Unmapped-Spigot-API-Patches/0018-Add-exception-reporting-event.patch b/Unmapped-Spigot-API-Patches/0018-Add-exception-reporting-event.patch deleted file mode 100644 index b295b466fc..0000000000 --- a/Unmapped-Spigot-API-Patches/0018-Add-exception-reporting-event.patch +++ /dev/null @@ -1,604 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 29 Feb 2016 20:24:35 -0600 -Subject: [PATCH] Add exception reporting event - - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2f573299a9a817a98372817a1de8bf641aaca956 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java -@@ -0,0 +1,43 @@ -+package com.destroystokyo.paper.event.server; -+ -+import com.google.common.base.Preconditions; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Bukkit; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import com.destroystokyo.paper.exception.ServerException; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called whenever an exception is thrown in a recoverable section of the server. -+ */ -+public class ServerExceptionEvent extends Event { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private ServerException exception; -+ -+ public ServerExceptionEvent(@NotNull ServerException exception) { -+ super(!Bukkit.isPrimaryThread()); -+ this.exception = Preconditions.checkNotNull(exception, "exception"); -+ } -+ -+ /** -+ * Gets the wrapped exception that was thrown. -+ * -+ * @return Exception thrown -+ */ -+ @NotNull -+ public ServerException getException() { -+ return exception; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java b/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6fb39af0479a818f7f1465bcdfe505ab4ff7da1a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java -@@ -0,0 +1,64 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+ -+import static com.google.common.base.Preconditions.checkNotNull; -+ -+/** -+ * Thrown when a command throws an exception -+ */ -+public class ServerCommandException extends ServerException { -+ -+ private final Command command; -+ private final CommandSender commandSender; -+ private final String[] arguments; -+ -+ public ServerCommandException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) { -+ super(message, cause); -+ this.commandSender = checkNotNull(commandSender, "commandSender"); -+ this.arguments = checkNotNull(arguments, "arguments"); -+ this.command = checkNotNull(command, "command"); -+ } -+ -+ public ServerCommandException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) { -+ super(cause); -+ this.commandSender = checkNotNull(commandSender, "commandSender"); -+ this.arguments = checkNotNull(arguments, "arguments"); -+ this.command = checkNotNull(command, "command"); -+ } -+ -+ protected ServerCommandException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) { -+ super(message, cause, enableSuppression, writableStackTrace); -+ this.commandSender = checkNotNull(commandSender, "commandSender"); -+ this.arguments = checkNotNull(arguments, "arguments"); -+ this.command = checkNotNull(command, "command"); -+ } -+ -+ /** -+ * Gets the command which threw the exception -+ * -+ * @return exception throwing command -+ */ -+ public Command getCommand() { -+ return command; -+ } -+ -+ /** -+ * Gets the command sender which executed the command request -+ * -+ * @return command sender of exception thrown command request -+ */ -+ public CommandSender getCommandSender() { -+ return commandSender; -+ } -+ -+ /** -+ * Gets the arguments which threw the exception for the command -+ * -+ * @return arguments of exception thrown command request -+ */ -+ public String[] getArguments() { -+ return arguments; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java b/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..410b24139535cd5d8439ad581c43c61b5757fbf6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java -@@ -0,0 +1,52 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.event.Event; -+import org.bukkit.event.Listener; -+import org.bukkit.plugin.Plugin; -+ -+import static com.google.common.base.Preconditions.*; -+ -+/** -+ * Exception thrown when a server event listener throws an exception -+ */ -+public class ServerEventException extends ServerPluginException { -+ -+ private final Listener listener; -+ private final Event event; -+ -+ public ServerEventException(String message, Throwable cause, Plugin responsiblePlugin, Listener listener, Event event) { -+ super(message, cause, responsiblePlugin); -+ this.listener = checkNotNull(listener, "listener"); -+ this.event = checkNotNull(event, "event"); -+ } -+ -+ public ServerEventException(Throwable cause, Plugin responsiblePlugin, Listener listener, Event event) { -+ super(cause, responsiblePlugin); -+ this.listener = checkNotNull(listener, "listener"); -+ this.event = checkNotNull(event, "event"); -+ } -+ -+ protected ServerEventException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, Listener listener, Event event) { -+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin); -+ this.listener = checkNotNull(listener, "listener"); -+ this.event = checkNotNull(event, "event"); -+ } -+ -+ /** -+ * Gets the listener which threw the exception -+ * -+ * @return event listener -+ */ -+ public Listener getListener() { -+ return listener; -+ } -+ -+ /** -+ * Gets the event which caused the exception -+ * -+ * @return event -+ */ -+ public Event getEvent() { -+ return event; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerException.java b/src/main/java/com/destroystokyo/paper/exception/ServerException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c06ea3942447d4824b83ff839cb449fb818dede1 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerException.java -@@ -0,0 +1,23 @@ -+package com.destroystokyo.paper.exception; -+ -+/** -+ * Wrapper exception for all exceptions that are thrown by the server. -+ */ -+public class ServerException extends Exception { -+ -+ public ServerException(String message) { -+ super(message); -+ } -+ -+ public ServerException(String message, Throwable cause) { -+ super(message, cause); -+ } -+ -+ public ServerException(Throwable cause) { -+ super(cause); -+ } -+ -+ protected ServerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { -+ super(message, cause, enableSuppression, writableStackTrace); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java b/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e762ed0dbad51625e65fef2e1898679108459a36 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java -@@ -0,0 +1,35 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.Bukkit; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+ -+/** -+ * Thrown when the internal server throws a recoverable exception. -+ */ -+public class ServerInternalException extends ServerException { -+ -+ public ServerInternalException(String message) { -+ super(message); -+ } -+ -+ public ServerInternalException(String message, Throwable cause) { -+ super(message, cause); -+ } -+ -+ public ServerInternalException(Throwable cause) { -+ super(cause); -+ } -+ -+ protected ServerInternalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { -+ super(message, cause, enableSuppression, writableStackTrace); -+ } -+ -+ public static void reportInternalException(Throwable cause) { -+ try { -+ Bukkit.getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(cause))); -+ ; -+ } catch (Throwable t) { -+ t.printStackTrace(); // Don't want to rethrow! -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f016ba3b1b62e554a9bacbb9635f2dbe441b3c4e ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java -@@ -0,0 +1,20 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.plugin.Plugin; -+ -+/** -+ * Thrown whenever there is an exception with any enabling or disabling of plugins. -+ */ -+public class ServerPluginEnableDisableException extends ServerPluginException { -+ public ServerPluginEnableDisableException(String message, Throwable cause, Plugin responsiblePlugin) { -+ super(message, cause, responsiblePlugin); -+ } -+ -+ public ServerPluginEnableDisableException(Throwable cause, Plugin responsiblePlugin) { -+ super(cause, responsiblePlugin); -+ } -+ -+ protected ServerPluginEnableDisableException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) { -+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin); -+ } -+} -\ No newline at end of file -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6defac287d0214fdf99418d979144050cc1e53bc ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java -@@ -0,0 +1,38 @@ -+package com.destroystokyo.paper.exception; -+ -+import com.google.common.base.Preconditions; -+import org.apache.commons.lang.Validate; -+import org.bukkit.plugin.Plugin; -+ -+import static com.google.common.base.Preconditions.*; -+ -+/** -+ * Wrapper exception for all cases to which a plugin can be immediately blamed for -+ */ -+public class ServerPluginException extends ServerException { -+ public ServerPluginException(String message, Throwable cause, Plugin responsiblePlugin) { -+ super(message, cause); -+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin"); -+ } -+ -+ public ServerPluginException(Throwable cause, Plugin responsiblePlugin) { -+ super(cause); -+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin"); -+ } -+ -+ protected ServerPluginException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) { -+ super(message, cause, enableSuppression, writableStackTrace); -+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin"); -+ } -+ -+ private final Plugin responsiblePlugin; -+ -+ /** -+ * Gets the plugin which is directly responsible for the exception being thrown -+ * -+ * @return plugin which is responsible for the exception throw -+ */ -+ public Plugin getResponsiblePlugin() { -+ return responsiblePlugin; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..89e132525cfae0ce979e37b3e2793df781e47227 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java -@@ -0,0 +1,64 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.plugin.Plugin; -+ -+import static com.google.common.base.Preconditions.*; -+ -+/** -+ * Thrown when an incoming plugin message channel throws an exception -+ */ -+public class ServerPluginMessageException extends ServerPluginException { -+ -+ private final Player player; -+ private final String channel; -+ private final byte[] data; -+ -+ public ServerPluginMessageException(String message, Throwable cause, Plugin responsiblePlugin, Player player, String channel, byte[] data) { -+ super(message, cause, responsiblePlugin); -+ this.player = checkNotNull(player, "player"); -+ this.channel = checkNotNull(channel, "channel"); -+ this.data = checkNotNull(data, "data"); -+ } -+ -+ public ServerPluginMessageException(Throwable cause, Plugin responsiblePlugin, Player player, String channel, byte[] data) { -+ super(cause, responsiblePlugin); -+ this.player = checkNotNull(player, "player"); -+ this.channel = checkNotNull(channel, "channel"); -+ this.data = checkNotNull(data, "data"); -+ } -+ -+ protected ServerPluginMessageException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, Player player, String channel, byte[] data) { -+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin); -+ this.player = checkNotNull(player, "player"); -+ this.channel = checkNotNull(channel, "channel"); -+ this.data = checkNotNull(data, "data"); -+ } -+ -+ /** -+ * Gets the channel to which the error occurred from recieving data from -+ * -+ * @return exception channel -+ */ -+ public String getChannel() { -+ return channel; -+ } -+ -+ /** -+ * Gets the data to which the error occurred from -+ * -+ * @return exception data -+ */ -+ public byte[] getData() { -+ return data; -+ } -+ -+ /** -+ * Gets the player which the plugin message causing the exception originated from -+ * -+ * @return exception player -+ */ -+ public Player getPlayer() { -+ return player; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java b/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2d0b2d4a9b3e5bdeec0e4ea7ab69858d86aa3715 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java -@@ -0,0 +1,37 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.scheduler.BukkitTask; -+ -+import static com.google.common.base.Preconditions.checkNotNull; -+ -+/** -+ * Thrown when a plugin's scheduler fails with an exception -+ */ -+public class ServerSchedulerException extends ServerPluginException { -+ -+ private final BukkitTask task; -+ -+ public ServerSchedulerException(String message, Throwable cause, BukkitTask task) { -+ super(message, cause, task.getOwner()); -+ this.task = checkNotNull(task, "task"); -+ } -+ -+ public ServerSchedulerException(Throwable cause, BukkitTask task) { -+ super(cause, task.getOwner()); -+ this.task = checkNotNull(task, "task"); -+ } -+ -+ protected ServerSchedulerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, BukkitTask task) { -+ super(message, cause, enableSuppression, writableStackTrace, task.getOwner()); -+ this.task = checkNotNull(task, "task"); -+ } -+ -+ /** -+ * Gets the task which threw the exception -+ * -+ * @return exception throwing task -+ */ -+ public BukkitTask getTask() { -+ return task; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java b/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5582999fe94c7a3dac655044ccc6d078cd9521a1 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java -@@ -0,0 +1,22 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+ -+/** -+ * Called when a tab-complete request throws an exception -+ */ -+public class ServerTabCompleteException extends ServerCommandException { -+ -+ public ServerTabCompleteException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) { -+ super(message, cause, command, commandSender, arguments); -+ } -+ -+ public ServerTabCompleteException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) { -+ super(cause, command, commandSender, arguments); -+ } -+ -+ protected ServerTabCompleteException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) { -+ super(message, cause, enableSuppression, writableStackTrace, command, commandSender, arguments); -+ } -+} -diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java -index f020cb04eba27a2e70fc7cf799ebbfb434b9d974..adfc7aae2c0f49bbcdd358e83b04a0cf078a7d52 100644 ---- a/src/main/java/org/bukkit/command/SimpleCommandMap.java -+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java -@@ -8,6 +8,10 @@ import java.util.HashMap; - import java.util.Iterator; - import java.util.List; - import java.util.Map; -+ -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerCommandException; -+import com.destroystokyo.paper.exception.ServerTabCompleteException; - import org.apache.commons.lang.Validate; - import org.bukkit.Location; - import org.bukkit.Server; -@@ -155,11 +159,14 @@ public class SimpleCommandMap implements CommandMap { - target.execute(sender, sentCommandLabel, Arrays.copyOfRange(args, 1, args.length)); - } // target.timings.stopTiming(); // Spigot // Paper - } catch (CommandException ex) { -+ server.getPluginManager().callEvent(new ServerExceptionEvent(new ServerCommandException(ex, target, sender, args))); // Paper - //target.timings.stopTiming(); // Spigot // Paper - throw ex; - } catch (Throwable ex) { - //target.timings.stopTiming(); // Spigot // Paper -- throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex); -+ String msg = "Unhandled exception executing '" + commandLine + "' in " + target; -+ server.getPluginManager().callEvent(new ServerExceptionEvent(new ServerCommandException(ex, target, sender, args))); // Paper -+ throw new CommandException(msg, ex); - } - - // return true as command was handled -@@ -238,7 +245,9 @@ public class SimpleCommandMap implements CommandMap { - } catch (CommandException ex) { - throw ex; - } catch (Throwable ex) { -- throw new CommandException("Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target, ex); -+ String msg = "Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target; -+ server.getPluginManager().callEvent(new ServerExceptionEvent(new ServerTabCompleteException(msg, ex, target, sender, args))); // Paper -+ throw new CommandException(msg, ex); - } - } - -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 745eaa8f2f2ff83536301db8ca47a8af30df7a73..d0fec44d2546290091649879450761ce08514fcb 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -23,6 +23,10 @@ import java.util.WeakHashMap; - import java.util.logging.Level; - import java.util.regex.Matcher; - import java.util.regex.Pattern; -+ -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerEventException; -+import com.destroystokyo.paper.exception.ServerPluginEnableDisableException; - import org.apache.commons.lang.Validate; - import org.bukkit.Server; - import org.bukkit.World; -@@ -478,7 +482,8 @@ public final class SimplePluginManager implements PluginManager { - try { - plugin.getPluginLoader().enablePlugin(plugin); - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ handlePluginException("Error occurred (in the plugin loader) while enabling " -+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); - } - - HandlerList.bakeAll(); -@@ -499,32 +504,37 @@ public final class SimplePluginManager implements PluginManager { - try { - plugin.getPluginLoader().disablePlugin(plugin); - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ handlePluginException("Error occurred (in the plugin loader) while disabling " -+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper - } - - try { - server.getScheduler().cancelTasks(plugin); - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while cancelling tasks for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ handlePluginException("Error occurred (in the plugin loader) while cancelling tasks for " -+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper - } - - try { - server.getServicesManager().unregisterAll(plugin); - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering services for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ handlePluginException("Error occurred (in the plugin loader) while unregistering services for " -+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper - } - - try { - HandlerList.unregisterAll(plugin); - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering events for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ handlePluginException("Error occurred (in the plugin loader) while unregistering events for " -+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper - } - - try { - server.getMessenger().unregisterIncomingPluginChannel(plugin); - server.getMessenger().unregisterOutgoingPluginChannel(plugin); - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering plugin channels for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ handlePluginException("Error occurred (in the plugin loader) while unregistering plugin channels for " -+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper - } - - try { -@@ -537,6 +547,13 @@ public final class SimplePluginManager implements PluginManager { - } - } - -+ // Paper start -+ private void handlePluginException(String msg, Throwable ex, Plugin plugin) { -+ server.getLogger().log(Level.SEVERE, msg, ex); -+ callEvent(new ServerExceptionEvent(new ServerPluginEnableDisableException(msg, ex, plugin))); -+ } -+ // Paper end -+ - @Override - public void clearPlugins() { - synchronized (this) { -@@ -600,7 +617,13 @@ public final class SimplePluginManager implements PluginManager { - )); - } - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(), ex); -+ // Paper start - error reporting -+ String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(); -+ server.getLogger().log(Level.SEVERE, msg, ex); -+ if (!(event instanceof ServerExceptionEvent)) { // We don't want to cause an endless event loop -+ callEvent(new ServerExceptionEvent(new ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event))); -+ } -+ // Paper end - } - } - } diff --git a/Unmapped-Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch b/Unmapped-Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch deleted file mode 100644 index 87d3369578..0000000000 --- a/Unmapped-Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Feb 2016 20:26:39 -0600 -Subject: [PATCH] Fix ServerListPingEvent flagging as Async - -This event can sometimes fire Async, set the proper boolean - -diff --git a/src/main/java/org/bukkit/event/server/ServerEvent.java b/src/main/java/org/bukkit/event/server/ServerEvent.java -index 46b119017a1e3dfcd9ae5fb91b4fe8c20b0d6b86..05167fb34e4c42edc67af6e6700a2a3cc0f92769 100644 ---- a/src/main/java/org/bukkit/event/server/ServerEvent.java -+++ b/src/main/java/org/bukkit/event/server/ServerEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.server; - -+import org.bukkit.Bukkit; - import org.bukkit.event.Event; - - /** -@@ -8,7 +9,7 @@ import org.bukkit.event.Event; - public abstract class ServerEvent extends Event { - - public ServerEvent() { -- super(); -+ super(!Bukkit.isPrimaryThread()); // Paper - } - - public ServerEvent(boolean isAsync) { diff --git a/Unmapped-Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch b/Unmapped-Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch deleted file mode 100644 index b8376a9108..0000000000 --- a/Unmapped-Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Tue, 8 Mar 2016 13:05:59 -0800 -Subject: [PATCH] Add BaseComponent sendMessage methods to CommandSender - - -diff --git a/src/main/java/org/bukkit/command/CommandSender.java b/src/main/java/org/bukkit/command/CommandSender.java -index c88418c7aa19b4fecdfa9af3d18ff202a5dc5763..fb0e608fa92dae99b9eee8fc1cbdf4b91a33e620 100644 ---- a/src/main/java/org/bukkit/command/CommandSender.java -+++ b/src/main/java/org/bukkit/command/CommandSender.java -@@ -1,6 +1,9 @@ - package org.bukkit.command; - - import java.util.UUID; -+import net.kyori.adventure.audience.MessageType; -+import net.kyori.adventure.identity.Identity; -+import net.kyori.adventure.text.Component; - import org.bukkit.Server; - import org.bukkit.permissions.Permissible; - import org.jetbrains.annotations.NotNull; -@@ -117,5 +120,33 @@ public interface CommandSender extends net.kyori.adventure.audience.Audience, Pe - default void sendMessage(final @NotNull net.kyori.adventure.identity.Identity identity, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { - this.sendMessage(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(message)); - } -+ -+ /** -+ * Sends the component to the sender -+ * -+ *

    If this sender does not support sending full components then -+ * the component will be sent as legacy text.

    -+ * -+ * @param component the component to send -+ * @deprecated use {@link #sendMessage(Identity, Component, MessageType)} instead -+ */ -+ @Deprecated -+ default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { -+ this.sendMessage(component.toLegacyText()); -+ } -+ -+ /** -+ * Sends an array of components as a single message to the sender -+ * -+ *

    If this sender does not support sending full components then -+ * the components will be sent as legacy text.

    -+ * -+ * @param components the components to send -+ * @deprecated use {@link #sendMessage(Identity, Component, MessageType)} instead -+ */ -+ @Deprecated -+ default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { -+ this.sendMessage(new net.md_5.bungee.api.chat.TextComponent(components).toLegacyText()); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Unmapped-Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch deleted file mode 100644 index 515b56ff03..0000000000 --- a/Unmapped-Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mrapple -Date: Sun, 25 Nov 2012 13:47:27 -0600 -Subject: [PATCH] Add methods for working with arrows stuck in living entities - - -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 24c858182f25496cc7254f7cf9e996b3bea1f9ec..45e9f585c3e522ecf94a6bc42cdc190e1a191a5c 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -605,4 +605,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - * @return Whether the entity is invisible - */ - public boolean isInvisible(); -+ -+ // Paper start -+ /** -+ * Get the number of arrows stuck in this entity -+ * @return Number of arrows stuck -+ */ -+ int getArrowsStuck(); -+ -+ /** -+ * Set the number of arrows stuck in this entity -+ * -+ * @param arrows Number of arrows to stick in this entity -+ */ -+ void setArrowsStuck(int arrows); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0022-Complete-resource-pack-API.patch b/Unmapped-Spigot-API-Patches/0022-Complete-resource-pack-API.patch deleted file mode 100644 index ff78c17d14..0000000000 --- a/Unmapped-Spigot-API-Patches/0022-Complete-resource-pack-API.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 4 Apr 2015 22:59:54 -0400 -Subject: [PATCH] Complete resource pack API - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 769ad98fd7a6a866b320e1ccffd7962228d564cf..ddbe5734ac0f905b0c388e30f17a281530b82262 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1124,7 +1124,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @throws IllegalArgumentException Thrown if the URL is null. - * @throws IllegalArgumentException Thrown if the URL is too long. The - * length restriction is an implementation specific arbitrary value. -+ * @deprecated use {@link #setResourcePack(String, String)} - */ -+ @Deprecated // Paper - public void setResourcePack(@NotNull String url); - - /** -@@ -1601,6 +1603,60 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { - return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.displayName()))); - } -+ -+ /** -+ * Request that the player's client download and switch resource packs. -+ *

    -+ * The player's client will download the new resource pack asynchronously -+ * in the background, and will automatically switch to it once the -+ * download is complete. If the client has downloaded and cached the same -+ * resource pack in the past, it will perform a quick timestamp check -+ * over the network to determine if the resource pack has changed and -+ * needs to be downloaded again. When this request is sent for the very -+ * first time from a given server, the client will first display a -+ * confirmation GUI to the player before proceeding with the download. -+ *

    -+ * Notes: -+ *

      -+ *
    • Players can disable server resources on their client, in which -+ * case this method will have no affect on them. -+ *
    • There is no concept of resetting resource packs back to default -+ * within Minecraft, so players will have to relog to do so. -+ *
    -+ * -+ * @param url The URL from which the client will download the resource -+ * pack. The string must contain only US-ASCII characters and should -+ * be encoded as per RFC 1738. -+ * @param hash A 40 character hexadecimal and lowercase SHA-1 digest of -+ * the resource pack file. -+ * @throws IllegalArgumentException Thrown if the URL is null. -+ * @throws IllegalArgumentException Thrown if the URL is too long. The -+ * length restriction is an implementation specific arbitrary value. -+ */ -+ void setResourcePack(@NotNull String url, @NotNull String hash); -+ -+ /** -+ * @return the most recent resource pack status received from the player, -+ * or null if no status has ever been received from this player. -+ */ -+ @Nullable -+ org.bukkit.event.player.PlayerResourcePackStatusEvent.Status getResourcePackStatus(); -+ -+ /** -+ * @return the most recent resource pack hash received from the player, -+ * or null if no hash has ever been received from this player. -+ * -+ * @deprecated This is no longer sent from the client and will always be null -+ */ -+ @Nullable -+ @Deprecated -+ String getResourcePackHash(); -+ -+ /** -+ * @return true if the last resource pack status received from this player -+ * was {@link org.bukkit.event.player.PlayerResourcePackStatusEvent.Status#SUCCESSFULLY_LOADED} -+ */ -+ boolean hasResourcePack(); - // Paper end - - // Spigot start -diff --git a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java -index b98195650d49d78ec35970ca0376b6289b861e4b..4c2102a11c3d682d98f0db4ccafa35231e66bcdd 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java -@@ -11,13 +11,32 @@ import org.jetbrains.annotations.NotNull; - public class PlayerResourcePackStatusEvent extends PlayerEvent { - - private static final HandlerList handlers = new HandlerList(); -+ @Deprecated -+ private final String hash; // Paper - private final Status status; - - public PlayerResourcePackStatusEvent(@NotNull final Player who, @NotNull Status resourcePackStatus) { - super(who); -+ this.hash = null; // Paper - this.status = resourcePackStatus; - } - -+ @Deprecated // Paper -+ public PlayerResourcePackStatusEvent(final Player who, Status resourcePackStatus, String hash) { -+ super(who); -+ this.hash = hash; // Paper -+ this.status = resourcePackStatus; -+ } -+ -+ @Deprecated -+ /** -+ * @deprecated Hash does not seem to ever be set -+ */ -+ public String getHash() { -+ return this.hash; -+ } -+ // Paper end -+ - /** - * Gets the status of this pack. - * diff --git a/Unmapped-Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch b/Unmapped-Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch deleted file mode 100644 index bcbe8ec071..0000000000 --- a/Unmapped-Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch +++ /dev/null @@ -1,398 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Thu, 3 Mar 2016 13:20:33 -0700 -Subject: [PATCH] Use ASM for event executors. - -Uses method handles for private or static methods. - -diff --git a/pom.xml b/pom.xml -index 1ced7a212684cee8faf07fa9a083adcd47be7fcb..7ec7e6047193a6b390d24f6d2722e35d1d36830d 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -163,6 +163,17 @@ - 9.1 - test -
    -+ -+ -+ org.ow2.asm -+ asm -+ 9.0 -+ -+ -+ org.ow2.asm -+ asm-commons -+ 9.0 -+ -
    - - -diff --git a/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5b28e9b1daba7834af67dbc193dd656bedd9a994 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java -@@ -0,0 +1,42 @@ -+package com.destroystokyo.paper.event.executor; -+ -+import java.lang.invoke.MethodHandle; -+import java.lang.invoke.MethodHandles; -+import java.lang.reflect.Method; -+ -+import com.destroystokyo.paper.util.SneakyThrow; -+import org.bukkit.event.Event; -+import org.bukkit.event.EventException; -+import org.bukkit.event.Listener; -+import org.bukkit.plugin.EventExecutor; -+import org.jetbrains.annotations.NotNull; -+ -+public class MethodHandleEventExecutor implements EventExecutor { -+ private final Class eventClass; -+ private final MethodHandle handle; -+ -+ public MethodHandleEventExecutor(@NotNull Class eventClass, @NotNull MethodHandle handle) { -+ this.eventClass = eventClass; -+ this.handle = handle; -+ } -+ -+ public MethodHandleEventExecutor(@NotNull Class eventClass, @NotNull Method m) { -+ this.eventClass = eventClass; -+ try { -+ m.setAccessible(true); -+ this.handle = MethodHandles.lookup().unreflect(m); -+ } catch (IllegalAccessException e) { -+ throw new AssertionError("Unable to set accessible", e); -+ } -+ } -+ -+ @Override -+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { -+ if (!eventClass.isInstance(event)) return; -+ try { -+ handle.invoke(listener, event); -+ } catch (Throwable t) { -+ SneakyThrow.sneaky(t); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c83672427324bd068ed52916f700b68446a226f6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java -@@ -0,0 +1,43 @@ -+package com.destroystokyo.paper.event.executor; -+ -+import java.lang.invoke.MethodHandle; -+import java.lang.invoke.MethodHandles; -+import java.lang.reflect.Method; -+import java.lang.reflect.Modifier; -+ -+import com.destroystokyo.paper.util.SneakyThrow; -+import com.google.common.base.Preconditions; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.event.Event; -+import org.bukkit.event.EventException; -+import org.bukkit.event.Listener; -+import org.bukkit.plugin.EventExecutor; -+import org.jetbrains.annotations.NotNull; -+ -+public class StaticMethodHandleEventExecutor implements EventExecutor { -+ private final Class eventClass; -+ private final MethodHandle handle; -+ -+ public StaticMethodHandleEventExecutor(@NotNull Class eventClass, @NotNull Method m) { -+ Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m); -+ Preconditions.checkArgument(eventClass != null, "eventClass is null"); -+ this.eventClass = eventClass; -+ try { -+ m.setAccessible(true); -+ this.handle = MethodHandles.lookup().unreflect(m); -+ } catch (IllegalAccessException e) { -+ throw new AssertionError("Unable to set accessible", e); -+ } -+ } -+ -+ @Override -+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { -+ if (!eventClass.isInstance(event)) return; -+ try { -+ handle.invoke(event); -+ } catch (Throwable throwable) { -+ SneakyThrow.sneaky(throwable); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b6e7d8ee8d903ebf975d60bec0e08603d9a49fdb ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java -@@ -0,0 +1,47 @@ -+package com.destroystokyo.paper.event.executor.asm; -+ -+import java.lang.reflect.Method; -+import java.util.concurrent.atomic.AtomicInteger; -+ -+import org.bukkit.plugin.EventExecutor; -+import org.jetbrains.annotations.NotNull; -+import org.objectweb.asm.ClassWriter; -+import org.objectweb.asm.Type; -+import org.objectweb.asm.commons.GeneratorAdapter; -+ -+import static org.objectweb.asm.Opcodes.*; -+ -+public class ASMEventExecutorGenerator { -+ @NotNull -+ public static byte[] generateEventExecutor(@NotNull Method m, @NotNull String name) { -+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); -+ writer.visit(V1_8, ACC_PUBLIC, name.replace('.', '/'), null, Type.getInternalName(Object.class), new String[] {Type.getInternalName(EventExecutor.class)}); -+ // Generate constructor -+ GeneratorAdapter methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "", "()V", null, null), ACC_PUBLIC, "", "()V"); -+ methodGenerator.loadThis(); -+ methodGenerator.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "", "()V", false); // Invoke the super class (Object) constructor -+ methodGenerator.returnValue(); -+ methodGenerator.endMethod(); -+ // Generate the execute method -+ methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "execute", "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Event;)V", null, null), ACC_PUBLIC, "execute", "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Listener;)V");; -+ methodGenerator.loadArg(0); -+ methodGenerator.checkCast(Type.getType(m.getDeclaringClass())); -+ methodGenerator.loadArg(1); -+ methodGenerator.checkCast(Type.getType(m.getParameterTypes()[0])); -+ methodGenerator.visitMethodInsn(m.getDeclaringClass().isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, Type.getInternalName(m.getDeclaringClass()), m.getName(), Type.getMethodDescriptor(m), m.getDeclaringClass().isInterface()); -+ if (m.getReturnType() != void.class) { -+ methodGenerator.pop(); -+ } -+ methodGenerator.returnValue(); -+ methodGenerator.endMethod(); -+ writer.visitEnd(); -+ return writer.toByteArray(); -+ } -+ -+ public static AtomicInteger NEXT_ID = new AtomicInteger(1); -+ @NotNull -+ public static String generateName() { -+ int id = NEXT_ID.getAndIncrement(); -+ return "com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor" + id; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f79685b48bb581277a6891927988b6f7a4389dc4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java -@@ -0,0 +1,34 @@ -+package com.destroystokyo.paper.event.executor.asm; -+ -+import org.jetbrains.annotations.NotNull; -+ -+public interface ClassDefiner { -+ -+ /** -+ * Returns if the defined classes can bypass access checks -+ * -+ * @return if classes bypass access checks -+ */ -+ public default boolean isBypassAccessChecks() { -+ return false; -+ } -+ -+ /** -+ * Define a class -+ * -+ * @param parentLoader the parent classloader -+ * @param name the name of the class -+ * @param data the class data to load -+ * @return the defined class -+ * @throws ClassFormatError if the class data is invalid -+ * @throws NullPointerException if any of the arguments are null -+ */ -+ @NotNull -+ public Class defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data); -+ -+ @NotNull -+ public static ClassDefiner getInstance() { -+ return SafeClassDefiner.INSTANCE; -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ac99477e9f2c08041aeff31abc1d1edee58d0a67 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java -@@ -0,0 +1,66 @@ -+package com.destroystokyo.paper.event.executor.asm; -+ -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.ConcurrentMap; -+ -+import com.google.common.base.Preconditions; -+ -+import com.google.common.collect.MapMaker; -+import org.jetbrains.annotations.NotNull; -+import org.objectweb.asm.Type; -+ -+public class SafeClassDefiner implements ClassDefiner { -+ /* default */ static final SafeClassDefiner INSTANCE = new SafeClassDefiner(); -+ -+ private SafeClassDefiner() {} -+ -+ private final ConcurrentMap loaders = new MapMaker().weakKeys().makeMap(); -+ -+ @NotNull -+ @Override -+ public Class defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data) { -+ GeneratedClassLoader loader = loaders.computeIfAbsent(parentLoader, GeneratedClassLoader::new); -+ synchronized (loader.getClassLoadingLock(name)) { -+ Preconditions.checkState(!loader.hasClass(name), "%s already defined", name); -+ Class c = loader.define(name, data); -+ assert c.getName().equals(name); -+ return c; -+ } -+ } -+ -+ private static class GeneratedClassLoader extends ClassLoader { -+ static { -+ ClassLoader.registerAsParallelCapable(); -+ } -+ -+ protected GeneratedClassLoader(@NotNull ClassLoader parent) { -+ super(parent); -+ } -+ -+ private Class define(@NotNull String name, byte[] data) { -+ synchronized (getClassLoadingLock(name)) { -+ assert !hasClass(name); -+ Class c = defineClass(name, data, 0, data.length); -+ resolveClass(c); -+ return c; -+ } -+ } -+ -+ @Override -+ @NotNull -+ public Object getClassLoadingLock(@NotNull String name) { -+ return super.getClassLoadingLock(name); -+ } -+ -+ public boolean hasClass(@NotNull String name) { -+ synchronized (getClassLoadingLock(name)) { -+ try { -+ Class.forName(name); -+ return true; -+ } catch (ClassNotFoundException e) { -+ return false; -+ } -+ } -+ } -+ } -+} -diff --git a/src/main/java/org/bukkit/plugin/EventExecutor.java b/src/main/java/org/bukkit/plugin/EventExecutor.java -index a850f0780de05463fc0d3f9e15ff7f19d88b2aed..9026e108ccd3a88aee1267ee275137befa646455 100644 ---- a/src/main/java/org/bukkit/plugin/EventExecutor.java -+++ b/src/main/java/org/bukkit/plugin/EventExecutor.java -@@ -5,9 +5,75 @@ import org.bukkit.event.EventException; - import org.bukkit.event.Listener; - import org.jetbrains.annotations.NotNull; - -+// Paper start -+import java.lang.reflect.Method; -+import java.lang.reflect.Modifier; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.ConcurrentMap; -+import java.util.function.Function; -+ -+import com.destroystokyo.paper.event.executor.MethodHandleEventExecutor; -+import com.destroystokyo.paper.event.executor.StaticMethodHandleEventExecutor; -+import com.destroystokyo.paper.event.executor.asm.ASMEventExecutorGenerator; -+import com.destroystokyo.paper.event.executor.asm.ClassDefiner; -+import com.google.common.base.Preconditions; -+// Paper end -+ - /** - * Interface which defines the class for event call backs to plugins - */ - public interface EventExecutor { - public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException; -+ -+ // Paper start -+ ConcurrentMap> eventExecutorMap = new ConcurrentHashMap>() { -+ @NotNull -+ @Override -+ public Class computeIfAbsent(@NotNull Method key, @NotNull Function> mappingFunction) { -+ Class executorClass = get(key); -+ if (executorClass != null) -+ return executorClass; -+ -+ //noinspection SynchronizationOnLocalVariableOrMethodParameter -+ synchronized (key) { -+ executorClass = get(key); -+ if (executorClass != null) -+ return executorClass; -+ -+ return super.computeIfAbsent(key, mappingFunction); -+ } -+ } -+ }; -+ -+ @NotNull -+ public static EventExecutor create(@NotNull Method m, @NotNull Class eventClass) { -+ Preconditions.checkNotNull(m, "Null method"); -+ Preconditions.checkArgument(m.getParameterCount() != 0, "Incorrect number of arguments %s", m.getParameterCount()); -+ Preconditions.checkArgument(m.getParameterTypes()[0] == eventClass, "First parameter %s doesn't match event class %s", m.getParameterTypes()[0], eventClass); -+ ClassDefiner definer = ClassDefiner.getInstance(); -+ if (Modifier.isStatic(m.getModifiers())) { -+ return new StaticMethodHandleEventExecutor(eventClass, m); -+ } else if (definer.isBypassAccessChecks() || Modifier.isPublic(m.getDeclaringClass().getModifiers()) && Modifier.isPublic(m.getModifiers())) { -+ // get the existing generated EventExecutor class for the Method or generate one -+ Class executorClass = eventExecutorMap.computeIfAbsent(m, (__) -> { -+ String name = ASMEventExecutorGenerator.generateName(); -+ byte[] classData = ASMEventExecutorGenerator.generateEventExecutor(m, name); -+ return definer.defineClass(m.getDeclaringClass().getClassLoader(), name, classData).asSubclass(EventExecutor.class); -+ }); -+ -+ try { -+ EventExecutor asmExecutor = executorClass.newInstance(); -+ // Define a wrapper to conform to bukkit stupidity (passing in events that don't match and wrapper exception) -+ return (listener, event) -> { -+ if (!eventClass.isInstance(event)) return; -+ asmExecutor.execute(listener, event); -+ }; -+ } catch (InstantiationException | IllegalAccessException e) { -+ throw new AssertionError("Unable to initialize generated event executor", e); -+ } -+ } else { -+ return new MethodHandleEventExecutor(eventClass, m); -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 2e306c7b984a02e12a74fac14589bf29ab6488bf..79ac529017aac059d13fe342f279e9c8faeba599 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -291,21 +291,7 @@ public final class JavaPluginLoader implements PluginLoader { - } - } - -- EventExecutor executor = new co.aikar.timings.TimedEventExecutor(new EventExecutor() { // Paper -- @Override -- public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { // Paper -- try { -- if (!eventClass.isAssignableFrom(event.getClass())) { -- return; -- } -- method.invoke(listener, event); -- } catch (InvocationTargetException ex) { -- throw new EventException(ex.getCause()); -- } catch (Throwable t) { -- throw new EventException(t); -- } -- } -- }, plugin, method, eventClass); // Paper -+ EventExecutor executor = new co.aikar.timings.TimedEventExecutor(EventExecutor.create(method, eventClass), plugin, method, eventClass); // Paper // Paper (Yes.) - Use factory method `EventExecutor.create()` - if (false) { // Spigot - RL handles useTimings check now - eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); - } else { diff --git a/Unmapped-Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch b/Unmapped-Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch deleted file mode 100644 index 4b287bfa56..0000000000 --- a/Unmapped-Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 May 2013 20:36:58 -0400 -Subject: [PATCH] Add a call helper to Event - -Reduces diff in Server patches - -diff --git a/src/main/java/org/bukkit/event/Event.java b/src/main/java/org/bukkit/event/Event.java -index 18d0636b749913bfdcea8eebc7d0840d192fb071..8ec56cd6b8e0f5c5dd8c7c88b4671e18dcf109d0 100644 ---- a/src/main/java/org/bukkit/event/Event.java -+++ b/src/main/java/org/bukkit/event/Event.java -@@ -35,6 +35,22 @@ public abstract class Event { - this.async = isAsync; - } - -+ // Paper start -+ /** -+ * Calls the event and tests if cancelled. -+ * -+ * @return false if event was cancelled, if cancellable. otherwise true. -+ */ -+ public boolean callEvent() { -+ org.bukkit.Bukkit.getPluginManager().callEvent(this); -+ if (this instanceof Cancellable) { -+ return !((Cancellable) this).isCancelled(); -+ } else { -+ return true; -+ } -+ } -+ // Paper end -+ - /** - * Convenience method for providing a user-friendly identifier. By - * default, it is the event's class's {@linkplain Class#getSimpleName() diff --git a/Unmapped-Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch b/Unmapped-Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch deleted file mode 100644 index 7122fed4a2..0000000000 --- a/Unmapped-Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 22 Jul 2015 18:50:41 -0400 -Subject: [PATCH] Add sender name to commands.yml replacement - -This allows you to use $sender in commands.yml definitions to make -commands that auto target self. - -diff --git a/src/main/java/org/bukkit/command/FormattedCommandAlias.java b/src/main/java/org/bukkit/command/FormattedCommandAlias.java -index a6ad94ef98a1df1d2842635d850bc990b0137849..9d4f553c04784cca63901a56a7aea62a5cae1d72 100644 ---- a/src/main/java/org/bukkit/command/FormattedCommandAlias.java -+++ b/src/main/java/org/bukkit/command/FormattedCommandAlias.java -@@ -1,6 +1,9 @@ - package org.bukkit.command; - - import java.util.ArrayList; -+import java.util.regex.Matcher; // Paper -+import java.util.regex.Pattern; // Paper -+ - import org.bukkit.Bukkit; - import org.jetbrains.annotations.NotNull; - -@@ -19,7 +22,7 @@ public class FormattedCommandAlias extends Command { - ArrayList commands = new ArrayList(); - for (String formatString : formatStrings) { - try { -- commands.add(buildCommand(formatString, args)); -+ commands.add(buildCommand(sender, formatString, args)); // Paper - } catch (Throwable throwable) { - if (throwable instanceof IllegalArgumentException) { - sender.sendMessage(throwable.getMessage()); -@@ -37,7 +40,10 @@ public class FormattedCommandAlias extends Command { - return result; - } - -- private String buildCommand(@NotNull String formatString, @NotNull String[] args) { -+ private String buildCommand(@NotNull CommandSender sender, @NotNull String formatString, @NotNull String[] args) { // Paper -+ if (formatString.contains("$sender")) { // Paper -+ formatString = formatString.replaceAll(Pattern.quote("$sender"), Matcher.quoteReplacement(sender.getName())); // Paper -+ } // Paper - int index = formatString.indexOf('$'); - while (index != -1) { - int start = index; diff --git a/Unmapped-Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch b/Unmapped-Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch deleted file mode 100644 index d7a1bb7514..0000000000 --- a/Unmapped-Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William -Date: Fri, 18 Mar 2016 03:28:07 -0400 -Subject: [PATCH] Add command to reload permissions.yml and require confirm to - reload - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 8646fc0987a8833996c5d977c36fe0d01bf72992..72375883b07ede041a7ea5f7b6785f71aef702c0 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1752,6 +1752,13 @@ public final class Bukkit { - public static org.bukkit.command.CommandMap getCommandMap() { - return server.getCommandMap(); - } -+ -+ /** -+ * Reload the Permissions in permissions.yml -+ */ -+ public static void reloadPermissions() { -+ server.reloadPermissions(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 599347ef656acad9a40be15fc5030e5d0f1630df..a2940eafa61814aae7f766262309495e991533d6 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1549,4 +1549,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @NotNull - Spigot spigot(); - // Spigot end -+ -+ void reloadPermissions(); // Paper - } -diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -index 50cc311be7904cc8fc6070a21c8e4de3a489fd20..c62da4131b17e66892678e8b618fb9ba3de93b56 100644 ---- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -+++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -@@ -13,15 +13,35 @@ public class ReloadCommand extends BukkitCommand { - public ReloadCommand(@NotNull String name) { - super(name); - this.description = "Reloads the server configuration and plugins"; -- this.usageMessage = "/reload"; -+ this.usageMessage = "/reload [permissions]"; // Paper - this.setPermission("bukkit.command.reload"); - this.setAliases(Arrays.asList("rl")); - } - - @Override -- public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { -+ public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { // Paper - if (!testPermission(sender)) return true; - -+ // Paper start - Reload permissions.yml & require confirm -+ boolean confirmed = System.getProperty("LetMeReload") != null; -+ if (args.length == 1) { -+ if (args[0].equalsIgnoreCase("permissions")) { -+ Bukkit.getServer().reloadPermissions(); -+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Permissions successfully reloaded."); -+ return true; -+ } else if ("confirm".equalsIgnoreCase(args[0])) { -+ confirmed = true; -+ } else { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Usage: " + usageMessage); -+ return true; -+ } -+ } -+ if (!confirmed) { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Are you sure you wish to reload your server? Doing so may cause bugs and memory leaks. It is recommended to restart instead of using /reload. To confirm, please type " + ChatColor.YELLOW + "/reload confirm"); -+ return true; -+ } -+ // Paper end -+ - Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues when using some plugins."); - Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); - Bukkit.reload(); -@@ -33,6 +53,6 @@ public class ReloadCommand extends BukkitCommand { - @NotNull - @Override - public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException { -- return Collections.emptyList(); -+ return java.util.Collections.singletonList("permissions"); // Paper - } - } -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index c2c49ee9b5531bc4761d2da54cd707c57fc647bf..2d27dfb859c312d46a14d0356c7c3f227e965a67 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -895,4 +895,13 @@ public final class SimplePluginManager implements PluginManager { - public void useTimings(boolean use) { - co.aikar.timings.Timings.setTimingsEnabled(use); // Paper - } -+ -+ // Paper start -+ public void clearPermissions() { -+ permissions.clear(); -+ defaultPerms.get(true).clear(); -+ defaultPerms.get(false).clear(); -+ } -+ // Paper end -+ - } diff --git a/Unmapped-Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch b/Unmapped-Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch deleted file mode 100644 index 94ff9d88e2..0000000000 --- a/Unmapped-Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sun, 21 Jun 2015 15:05:21 -0400 -Subject: [PATCH] Custom replacement for eaten items - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java b/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java -index c2793f3ef01c1246c130971c17e1c2bf8f551435..373f4b5b5185aa81ff728da89c9cc4e0ccf87889 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java -@@ -22,6 +22,7 @@ public class PlayerItemConsumeEvent extends PlayerEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean isCancelled = false; - private ItemStack item; -+ @Nullable private ItemStack replacement; // Paper - - /** - * @param player the player consuming -@@ -58,6 +59,29 @@ public class PlayerItemConsumeEvent extends PlayerEvent implements Cancellable { - } - } - -+ // Paper start -+ /** -+ * Return the custom item stack that will replace the consumed item, or null if no -+ * custom replacement has been set (which means the default replacement will be used). -+ * -+ * @return The custom item stack that will replace the consumed item or null -+ */ -+ @Nullable -+ public ItemStack getReplacement() { -+ return this.replacement; -+ } -+ -+ /** -+ * Set a custom item stack to replace the consumed item. Pass null to clear any custom -+ * stack that has been set and use the default replacement. -+ * -+ * @param replacement Replacement item to set, null to clear any custom stack and use default -+ */ -+ public void setReplacement(@Nullable ItemStack replacement) { -+ this.replacement = replacement; -+ } -+ // Paper end -+ - @Override - public boolean isCancelled() { - return this.isCancelled; diff --git a/Unmapped-Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch b/Unmapped-Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch deleted file mode 100644 index 5dc11c88f8..0000000000 --- a/Unmapped-Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:26:34 -0400 -Subject: [PATCH] Entity AddTo/RemoveFrom World Events - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..07660202e41ee86f1b66bad3335cf6fe126e7f9c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java -@@ -0,0 +1,32 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired any time an entity is being added to the world for any reason. -+ * -+ * Not to be confused with {@link org.bukkit.event.entity.CreatureSpawnEvent} -+ * This will fire anytime a chunk is reloaded too. -+ */ -+public class EntityAddToWorldEvent extends EntityEvent { -+ -+ public EntityAddToWorldEvent(@NotNull Entity entity) { -+ super(entity); -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e5dbbd660409bae0d3b96e83390511d3a423a52e ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java -@@ -0,0 +1,29 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired any time an entity is being removed from a world for any reason -+ */ -+public class EntityRemoveFromWorldEvent extends EntityEvent { -+ -+ public EntityRemoveFromWorldEvent(@NotNull Entity entity) { -+ super(entity); -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0029-EntityPathfindEvent.patch b/Unmapped-Spigot-API-Patches/0029-EntityPathfindEvent.patch deleted file mode 100644 index 697b76661a..0000000000 --- a/Unmapped-Spigot-API-Patches/0029-EntityPathfindEvent.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 21:15:34 -0400 -Subject: [PATCH] EntityPathfindEvent - -Fires when an Entity decides to start moving to a location. - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..63e46b2fb1b12b36fcb1e98b178cf29dd2e3d1b5 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java -@@ -0,0 +1,82 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Fired when an Entity decides to start moving towards a location. -+ * -+ * This event does not fire for the entities actual movement. Only when it -+ * is choosing to start moving to a location. -+ */ -+public class EntityPathfindEvent extends EntityEvent implements Cancellable { -+ @Nullable private final Entity targetEntity; -+ @NotNull private final Location loc; -+ -+ public EntityPathfindEvent(@NotNull Entity entity, @NotNull Location loc, @Nullable Entity targetEntity) { -+ super(entity); -+ this.targetEntity = targetEntity; -+ this.loc = loc; -+ } -+ -+ /** -+ * The Entity that is pathfinding. -+ * @return The Entity that is pathfinding. -+ */ -+ @NotNull -+ public Entity getEntity() { -+ return entity; -+ } -+ -+ /** -+ * If the Entity is trying to pathfind to an entity, this is the entity in relation. -+ * -+ * Otherwise this will return null. -+ * -+ * @return The entity target or null -+ */ -+ @Nullable -+ public Entity getTargetEntity() { -+ return targetEntity; -+ } -+ -+ /** -+ * The Location of where the entity is about to move to. -+ * -+ * Note that if the target happened to of been an entity -+ * @return Location of where the entity is trying to pathfind to. -+ */ -+ @NotNull -+ public Location getLoc() { -+ return loc; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch b/Unmapped-Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch deleted file mode 100644 index d4674ca2f4..0000000000 --- a/Unmapped-Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: crast -Date: Sat, 1 Jun 2013 13:52:30 -0600 -Subject: [PATCH] Reduce thread synchronization in MetadataStoreBase - -Use ConcurrentHashMap to allow thread-safe access methods and very -limited synchronized portions to allow much higher concurrency in -MetadataStore as well as far less locking, especially on reads - -diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java -index baf850226aed8545a5794deba6dff9603953b4b2..d363d517c05b3335101d829ce4ec22d049059c24 100644 ---- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java -+++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java -@@ -12,7 +12,7 @@ import org.bukkit.plugin.Plugin; - import org.jetbrains.annotations.NotNull; - - public abstract class MetadataStoreBase { -- private Map> metadataMap = new HashMap>(); -+ private Map> metadataMap = new java.util.concurrent.ConcurrentHashMap>(); // Paper - - /** - * Adds a metadata value to an object. Each metadata value is owned by a -@@ -46,7 +46,9 @@ public abstract class MetadataStoreBase { - entry = new WeakHashMap(1); - metadataMap.put(key, entry); - } -- entry.put(owningPlugin, newMetadataValue); -+ synchronized (entry) { -+ entry.put(owningPlugin, newMetadataValue); -+ } - } - - /** -@@ -60,10 +62,11 @@ public abstract class MetadataStoreBase { - * @see MetadataStore#getMetadata(Object, String) - */ - @NotNull -- public synchronized List getMetadata(@NotNull T subject, @NotNull String metadataKey) { -+ public List getMetadata(@NotNull T subject, @NotNull String metadataKey) { // Paper - String key = disambiguate(subject, metadataKey); -- if (metadataMap.containsKey(key)) { -- Collection values = metadataMap.get(key).values(); -+ Map entry = metadataMap.get(key); -+ if (entry != null) { -+ Collection values = entry.values(); - return Collections.unmodifiableList(new ArrayList(values)); - } else { - return Collections.emptyList(); -@@ -78,7 +81,7 @@ public abstract class MetadataStoreBase { - * @param metadataKey the unique metadata key being queried. - * @return the existence of the metadataKey within subject. - */ -- public synchronized boolean hasMetadata(@NotNull T subject, @NotNull String metadataKey) { -+ public boolean hasMetadata(@NotNull T subject, @NotNull String metadataKey) { // Paper - String key = disambiguate(subject, metadataKey); - return metadataMap.containsKey(key); - } -@@ -94,17 +97,18 @@ public abstract class MetadataStoreBase { - * @see MetadataStore#removeMetadata(Object, String, - * org.bukkit.plugin.Plugin) - */ -- public synchronized void removeMetadata(@NotNull T subject, @NotNull String metadataKey, @NotNull Plugin owningPlugin) { -+ public void removeMetadata(@NotNull T subject, @NotNull String metadataKey, @NotNull Plugin owningPlugin) { // Paper - Validate.notNull(owningPlugin, "Plugin cannot be null"); - String key = disambiguate(subject, metadataKey); - Map entry = metadataMap.get(key); - if (entry == null) { - return; - } -- -- entry.remove(owningPlugin); -- if (entry.isEmpty()) { -- metadataMap.remove(key); -+ synchronized (entry) { -+ entry.remove(owningPlugin); -+ if (entry.isEmpty()) { -+ metadataMap.remove(key); -+ } - } - } - -@@ -117,7 +121,7 @@ public abstract class MetadataStoreBase { - * @throws IllegalArgumentException If plugin is null - * @see MetadataStore#invalidateAll(org.bukkit.plugin.Plugin) - */ -- public synchronized void invalidateAll(@NotNull Plugin owningPlugin) { -+ public void invalidateAll(@NotNull Plugin owningPlugin) { // Paper - Validate.notNull(owningPlugin, "Plugin cannot be null"); - for (Map values : metadataMap.values()) { - if (values.containsKey(owningPlugin)) { diff --git a/Unmapped-Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch b/Unmapped-Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch deleted file mode 100644 index d15d19b316..0000000000 --- a/Unmapped-Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 16 Jul 2013 21:26:50 -0400 -Subject: [PATCH] Add MetadataStoreBase.removeAll(Plugin) - -So that on reload, metadata will be cleared - -diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java -index d363d517c05b3335101d829ce4ec22d049059c24..abbe545af572687a0399c2387434863cd2b70f68 100644 ---- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java -+++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java -@@ -4,6 +4,7 @@ import java.util.ArrayList; - import java.util.Collection; - import java.util.Collections; - import java.util.HashMap; -+import java.util.Iterator; // Paper - import java.util.List; - import java.util.Map; - import java.util.WeakHashMap; -@@ -130,6 +131,26 @@ public abstract class MetadataStoreBase { - } - } - -+ /** -+ * Removes all metadata in the metadata store that originates from the -+ * given plugin. -+ * -+ * @param owningPlugin the plugin requesting the invalidation. -+ * @throws IllegalArgumentException If plugin is null -+ */ -+ public void removeAll(@NotNull Plugin owningPlugin) { -+ Validate.notNull(owningPlugin, "Plugin cannot be null"); -+ for (Iterator> iterator = metadataMap.values().iterator(); iterator.hasNext(); ) { -+ Map values = iterator.next(); -+ if (values.containsKey(owningPlugin)) { -+ values.remove(owningPlugin); -+ } -+ if (values.isEmpty()) { -+ iterator.remove(); -+ } -+ } -+ } -+ - /** - * Creates a unique name for the object receiving metadata by combining - * unique data from the subject with a metadataKey. diff --git a/Unmapped-Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch b/Unmapped-Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch deleted file mode 100644 index 8fa59475c2..0000000000 --- a/Unmapped-Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 2 Apr 2016 05:08:36 -0400 -Subject: [PATCH] Add PlayerUseUnknownEntityEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..09cfdf48ead8f03f3497646537292174241b0868 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java -@@ -0,0 +1,46 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.EquipmentSlot; -+import org.jetbrains.annotations.NotNull; -+ -+public class PlayerUseUnknownEntityEvent extends PlayerEvent { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private final int entityId; -+ private final boolean attack; -+ @NotNull private final EquipmentSlot hand; -+ -+ public PlayerUseUnknownEntityEvent(@NotNull Player who, int entityId, boolean attack, @NotNull EquipmentSlot hand) { -+ super(who); -+ this.entityId = entityId; -+ this.attack = attack; -+ this.hand = hand; -+ } -+ -+ public int getEntityId() { -+ return this.entityId; -+ } -+ -+ public boolean isAttack() { -+ return this.attack; -+ } -+ -+ @NotNull -+ public EquipmentSlot getHand() { -+ return this.hand; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Unmapped-Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch deleted file mode 100644 index eb1703e485..0000000000 --- a/Unmapped-Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch +++ /dev/null @@ -1,290 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 13 Apr 2016 20:20:18 -0700 -Subject: [PATCH] Add handshake event to allow plugins to handle client - handshaking logic themselves - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a077962fa786a3291849abfa823c7f0ec4664fce ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java -@@ -0,0 +1,277 @@ -+package com.destroystokyo.paper.event.player; -+ -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.format.NamedTextColor; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Bukkit; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import java.util.UUID; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * This event is fired during a player handshake. -+ * -+ *

    If there are no listeners listening to this event, the logic default -+ * to your server platform will be ran.

    -+ * -+ *

    WARNING: TAMPERING WITH THIS EVENT CAN BE DANGEROUS

    -+ */ -+public class PlayerHandshakeEvent extends Event implements Cancellable { -+ -+ private static final HandlerList HANDLERS = new HandlerList(); -+ @NotNull private final String originalHandshake; -+ @NotNull private final String originalSocketAddressHostname; -+ private boolean cancelled; -+ @Nullable private String serverHostname; -+ @Nullable private String socketAddressHostname; -+ @Nullable private UUID uniqueId; -+ @Nullable private String propertiesJson; -+ private boolean failed; -+ private Component failMessage = Component.text("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!", NamedTextColor.YELLOW); -+ -+ /** -+ * Creates a new {@link PlayerHandshakeEvent}. -+ * -+ * @param originalHandshake the original handshake string -+ * @param cancelled if this event is enabled -+ * -+ * @deprecated in favour of {@link PlayerHandshakeEvent(String, String, boolean)} -+ */ -+ @Deprecated -+ public PlayerHandshakeEvent(@NotNull String originalHandshake, boolean cancelled) { -+ this(originalHandshake, "127.0.0.1", cancelled); -+ } -+ -+ /** -+ * Creates a new {@link PlayerHandshakeEvent}. -+ * -+ * @param originalHandshake the original handshake string -+ * @param originalSocketAddressHostname the original socket address hostname -+ * @param cancelled if this event is enabled -+ */ -+ public PlayerHandshakeEvent(@NotNull String originalHandshake, @NotNull String originalSocketAddressHostname, boolean cancelled) { -+ super(true); -+ this.originalHandshake = originalHandshake; -+ this.originalSocketAddressHostname = originalSocketAddressHostname; -+ this.cancelled = cancelled; -+ } -+ -+ /** -+ * Determines if this event is cancelled. -+ * -+ *

    When this event is cancelled, custom handshake logic will not -+ * be processed.

    -+ * -+ * @return {@code true} if this event is cancelled, {@code false} otherwise -+ */ -+ @Override -+ public boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ /** -+ * Sets if this event is cancelled. -+ * -+ *

    When this event is cancelled, custom handshake logic will not -+ * be processed.

    -+ * -+ * @param cancelled {@code true} if this event is cancelled, {@code false} otherwise -+ */ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ /** -+ * Gets the original handshake string. -+ * -+ * @return the original handshake string -+ */ -+ @NotNull -+ public String getOriginalHandshake() { -+ return this.originalHandshake; -+ } -+ -+ /** -+ * Gets the original socket address hostname. -+ * -+ *

    This does not include the port.

    -+ *

    In cases where this event is manually fired and the plugin wasn't updated yet, the default is {@code "127.0.0.1"}.

    -+ * -+ * @return the original socket address hostname -+ */ -+ @NotNull -+ public String getOriginalSocketAddressHostname() { -+ return this.originalSocketAddressHostname; -+ } -+ -+ /** -+ * Gets the server hostname string. -+ * -+ *

    This should not include the port.

    -+ * -+ * @return the server hostname string -+ */ -+ @Nullable -+ public String getServerHostname() { -+ return this.serverHostname; -+ } -+ -+ /** -+ * Sets the server hostname string. -+ * -+ *

    This should not include the port.

    -+ * -+ * @param serverHostname the server hostname string -+ */ -+ public void setServerHostname(@NotNull String serverHostname) { -+ this.serverHostname = serverHostname; -+ } -+ -+ /** -+ * Gets the socket address hostname string. -+ * -+ *

    This should not include the port.

    -+ * -+ * @return the socket address hostname string -+ */ -+ @Nullable -+ public String getSocketAddressHostname() { -+ return this.socketAddressHostname; -+ } -+ -+ /** -+ * Sets the socket address hostname string. -+ * -+ *

    This should not include the port.

    -+ * -+ * @param socketAddressHostname the socket address hostname string -+ */ -+ public void setSocketAddressHostname(@NotNull String socketAddressHostname) { -+ this.socketAddressHostname = socketAddressHostname; -+ } -+ -+ /** -+ * Gets the unique id. -+ * -+ * @return the unique id -+ */ -+ @Nullable -+ public UUID getUniqueId() { -+ return this.uniqueId; -+ } -+ -+ /** -+ * Sets the unique id. -+ * -+ * @param uniqueId the unique id -+ */ -+ public void setUniqueId(@NotNull UUID uniqueId) { -+ this.uniqueId = uniqueId; -+ } -+ -+ /** -+ * Gets the profile properties. -+ * -+ *

    This should be a valid JSON string.

    -+ * -+ * @return the profile properties, as JSON -+ */ -+ @Nullable -+ public String getPropertiesJson() { -+ return this.propertiesJson; -+ } -+ -+ /** -+ * Determines if authentication failed. -+ * -+ *

    When {@code true}, the client connecting will be disconnected -+ * with the {@link #getFailMessage() fail message}.

    -+ * -+ * @return {@code true} if authentication failed, {@code false} otherwise -+ */ -+ public boolean isFailed() { -+ return this.failed; -+ } -+ -+ /** -+ * Sets if authentication failed and the client should be disconnected. -+ * -+ *

    When {@code true}, the client connecting will be disconnected -+ * with the {@link #getFailMessage() fail message}.

    -+ * -+ * @param failed {@code true} if authentication failed, {@code false} otherwise -+ */ -+ public void setFailed(boolean failed) { -+ this.failed = failed; -+ } -+ -+ /** -+ * Sets the profile properties. -+ * -+ *

    This should be a valid JSON string.

    -+ * -+ * @param propertiesJson the profile properties, as JSON -+ */ -+ public void setPropertiesJson(@NotNull String propertiesJson) { -+ this.propertiesJson = propertiesJson; -+ } -+ -+ /** -+ * Gets the message to display to the client when authentication fails. -+ * -+ * @return the message to display to the client -+ */ -+ @NotNull -+ public Component failMessage() { -+ return this.failMessage; -+ } -+ -+ /** -+ * Sets the message to display to the client when authentication fails. -+ * -+ * @param failMessage the message to display to the client -+ */ -+ public void failMessage(@NotNull Component failMessage) { -+ this.failMessage = failMessage; -+ } -+ -+ /** -+ * Gets the message to display to the client when authentication fails. -+ * -+ * @return the message to display to the client -+ * @deprecated use {@link #failMessage()} -+ */ -+ @NotNull -+ @Deprecated -+ public String getFailMessage() { -+ return Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.failMessage()); -+ } -+ -+ /** -+ * Sets the message to display to the client when authentication fails. -+ * -+ * @param failMessage the message to display to the client -+ * @deprecated use {@link #failMessage(Component)} -+ */ -+ @Deprecated -+ public void setFailMessage(@NotNull String failMessage) { -+ Validate.notEmpty(failMessage, "fail message cannot be null or empty"); -+ this.failMessage(Bukkit.getUnsafe().legacyComponentSerializer().deserialize(failMessage)); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLERS; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLERS; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch b/Unmapped-Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch deleted file mode 100644 index fb3753f0e1..0000000000 --- a/Unmapped-Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Fri, 4 Mar 2016 03:13:18 -0500 -Subject: [PATCH] Arrow pickup rule API - - -diff --git a/src/main/java/org/bukkit/entity/AbstractArrow.java b/src/main/java/org/bukkit/entity/AbstractArrow.java -index 5b50a4e10e8ace8cc53ad3c8d7c3185f88d5c8db..e8e56e89e32d84af0639fe2e9b0eeabd747b6007 100644 ---- a/src/main/java/org/bukkit/entity/AbstractArrow.java -+++ b/src/main/java/org/bukkit/entity/AbstractArrow.java -@@ -141,4 +141,38 @@ public interface AbstractArrow extends Projectile { - */ - CREATIVE_ONLY - } -+ -+ // Paper start -+ /** -+ * Gets the {@link PickupRule} for this arrow. -+ * -+ *

    This is generally {@link PickupRule#ALLOWED} only if the arrow was -+ * not fired from a bow with the infinity enchantment.

    -+ * -+ * @return The pickup rule -+ * @deprecated Use {@link Arrow#getPickupStatus()} as an upstream compatible replacement for this function -+ */ -+ @Deprecated -+ default PickupRule getPickupRule() { -+ return PickupRule.valueOf(this.getPickupStatus().name()); -+ } -+ -+ /** -+ * Set the rule for which players can pickup this arrow as an item. -+ * -+ * @param rule The pickup rule -+ * @deprecated Use {@link Arrow#setPickupStatus(PickupStatus)} with {@link PickupStatus} as an upstream compatible replacement for this function -+ */ -+ @Deprecated -+ default void setPickupRule(PickupRule rule) { -+ this.setPickupStatus(PickupStatus.valueOf(rule.name())); -+ } -+ -+ @Deprecated -+ enum PickupRule { -+ DISALLOWED, -+ ALLOWED, -+ CREATIVE_ONLY; -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0035-EntityRegainHealthEvent-isFastRegen-API.patch b/Unmapped-Spigot-API-Patches/0035-EntityRegainHealthEvent-isFastRegen-API.patch deleted file mode 100644 index f06ee13d15..0000000000 --- a/Unmapped-Spigot-API-Patches/0035-EntityRegainHealthEvent-isFastRegen-API.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 22 Apr 2016 01:43:11 -0500 -Subject: [PATCH] EntityRegainHealthEvent isFastRegen API - - -diff --git a/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java b/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java -index 8feb6698f9630f099be99e52d1149cd6bc615197..d51d2ec1d04d9ea8a25a70d0d856f2355ebfcb4a 100644 ---- a/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java -+++ b/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java -@@ -13,12 +13,31 @@ public class EntityRegainHealthEvent extends EntityEvent implements Cancellable - private boolean cancelled; - private double amount; - private final RegainReason regainReason; -+ private final boolean isFastRegen; // Paper - - public EntityRegainHealthEvent(@NotNull final Entity entity, final double amount, @NotNull final RegainReason regainReason) { -+ // Paper start - Forward -+ this(entity, amount, regainReason, false); -+ } -+ -+ public EntityRegainHealthEvent(@NotNull final Entity entity, final double amount, @NotNull final RegainReason regainReason, boolean isFastRegen) { -+ // Paper end - super(entity); - this.amount = amount; - this.regainReason = regainReason; -+ this.isFastRegen = isFastRegen; // Paper -+ } -+ -+ // Paper start - Add getter for isFastRegen -+ /** -+ * Is this event a result of the fast regeneration mechanic -+ * -+ * @return Whether the event is the result of a fast regeneration mechanic -+ */ -+ public boolean isFastRegen() { -+ return isFastRegen; - } -+ // Paper end - - /** - * Gets the amount of regained health diff --git a/Unmapped-Spigot-API-Patches/0036-LootTable-API.patch b/Unmapped-Spigot-API-Patches/0036-LootTable-API.patch deleted file mode 100644 index ed6e56042d..0000000000 --- a/Unmapped-Spigot-API-Patches/0036-LootTable-API.patch +++ /dev/null @@ -1,402 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 1 May 2016 15:19:49 -0400 -Subject: [PATCH] LootTable API - -Provides API to control what Loot Table an object uses. - -Also provides an Event to control if a lootable inventory should -auto replenish for a player. - -Provides methods to determine players looted state for an object - -diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..92d7b853a2ccaae5afa8ac141bead840942944ef ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.loottable; -+ -+import org.bukkit.block.Block; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents an Inventory that can generate loot, such as Chests inside of Fortresses and Mineshafts -+ */ -+public interface LootableBlockInventory extends LootableInventory { -+ -+ /** -+ * Gets the block that is lootable -+ * @return The Block -+ */ -+ @NotNull -+ Block getBlock(); -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b387894fe8001edb41ad2ad2b70ebabe065b682e ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.loottable; -+ -+import org.bukkit.entity.Entity; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents an Inventory that can generate loot, such as Minecarts inside of Mineshafts -+ */ -+public interface LootableEntityInventory extends LootableInventory { -+ -+ /** -+ * Gets the entity that is lootable -+ * @return The Entity -+ */ -+ @NotNull -+ Entity getEntity(); -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..97815eeb231cf0706b34fa47a4f7d1bb786305b4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java -@@ -0,0 +1,116 @@ -+package com.destroystokyo.paper.loottable; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.loot.Lootable; -+ -+import java.util.UUID; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Represents an Inventory that contains a Loot Table associated to it that will -+ * automatically fill on first open. -+ * -+ * A new feature and API is provided to support automatically refreshing the contents -+ * of the inventory based on that Loot Table after a configurable amount of time has passed. -+ * -+ * The behavior of how the Inventory is filled based on the loot table may vary based -+ * on Minecraft versions and the Loot Table feature. -+ */ -+public interface LootableInventory extends Lootable { -+ -+ /** -+ * Server owners have to enable whether or not an object in a world should refill -+ * -+ * @return If the world this inventory is currently in has Replenishable Lootables enabled -+ */ -+ boolean isRefillEnabled(); -+ -+ /** -+ * Whether or not this object has ever been filled -+ * @return Has ever been filled -+ */ -+ boolean hasBeenFilled(); -+ -+ /** -+ * Has this player ever looted this block -+ * @param player The player to check -+ * @return Whether or not this player has looted this block -+ */ -+ default boolean hasPlayerLooted(@NotNull Player player) { -+ return hasPlayerLooted(player.getUniqueId()); -+ } -+ -+ /** -+ * Has this player ever looted this block -+ * @param player The player to check -+ * @return Whether or not this player has looted this block -+ */ -+ boolean hasPlayerLooted(@NotNull UUID player); -+ -+ /** -+ * Gets the timestamp, in milliseconds, of when the player last looted this object -+ * -+ * @param player The player to check -+ * @return Timestamp last looted, or null if player has not looted this object -+ */ -+ @Nullable -+ default Long getLastLooted(@NotNull Player player) { -+ return getLastLooted(player.getUniqueId()); -+ } -+ -+ /** -+ * Gets the timestamp, in milliseconds, of when the player last looted this object -+ * -+ * @param player The player to check -+ * @return Timestamp last looted, or null if player has not looted this object -+ */ -+ @Nullable -+ Long getLastLooted(@NotNull UUID player); -+ -+ /** -+ * Change the state of whether or not a player has looted this block -+ * @param player The player to change state for -+ * @param looted true to add player to looted list, false to remove -+ * @return The previous state of whether the player had looted this or not -+ */ -+ default boolean setHasPlayerLooted(@NotNull Player player, boolean looted) { -+ return setHasPlayerLooted(player.getUniqueId(), looted); -+ } -+ -+ /** -+ * Change the state of whether or not a player has looted this block -+ * @param player The player to change state for -+ * @param looted true to add player to looted list, false to remove -+ * @return The previous state of whether the player had looted this or not -+ */ -+ boolean setHasPlayerLooted(@NotNull UUID player, boolean looted); -+ -+ /** -+ * Returns Whether or not this object has been filled and now has a pending refill -+ * @return Has pending refill -+ */ -+ boolean hasPendingRefill(); -+ -+ /** -+ * Gets the timestamp in milliseconds that the Lootable object was last refilled -+ * -+ * @return -1 if it was never refilled, or timestamp in milliseconds -+ */ -+ long getLastFilled(); -+ -+ /** -+ * Gets the timestamp in milliseconds that the Lootable object will refill -+ * -+ * @return -1 if it is not scheduled for refill, or timestamp in milliseconds -+ */ -+ long getNextRefill(); -+ -+ /** -+ * Sets the timestamp in milliseconds of the next refill for this object -+ * -+ * @param refillAt timestamp in milliseconds. -1 to clear next refill -+ * @return The previous scheduled time to refill, or -1 if was not scheduled -+ */ -+ long setNextRefill(long refillAt); -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fd184f13f5e8ee5cf829fff4f44696e1f760430b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java -@@ -0,0 +1,45 @@ -+package com.destroystokyo.paper.loottable; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+public class LootableInventoryReplenishEvent extends PlayerEvent implements Cancellable { -+ @NotNull private final LootableInventory inventory; -+ -+ public LootableInventoryReplenishEvent(@NotNull Player player, @NotNull LootableInventory inventory) { -+ super(player); -+ this.inventory = inventory; -+ } -+ -+ @NotNull -+ public LootableInventory getInventory() { -+ return inventory; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} -diff --git a/src/main/java/org/bukkit/block/Chest.java b/src/main/java/org/bukkit/block/Chest.java -index b451191312e4fb19f2131c2d0a0c0337953f6c7c..db6affbc78106b2d93b41953b624a0bca0ca1d72 100644 ---- a/src/main/java/org/bukkit/block/Chest.java -+++ b/src/main/java/org/bukkit/block/Chest.java -@@ -1,5 +1,7 @@ - package org.bukkit.block; - -+import com.destroystokyo.paper.loottable.LootableBlockInventory; // Paper -+import org.bukkit.Nameable; // Paper - import org.bukkit.inventory.Inventory; - import org.bukkit.loot.Lootable; - import org.jetbrains.annotations.NotNull; -@@ -7,7 +9,7 @@ import org.jetbrains.annotations.NotNull; - /** - * Represents a captured state of a chest. - */ --public interface Chest extends Container, Lootable, Lidded { -+public interface Chest extends Container, LootableBlockInventory, Lidded { // Paper - - /** - * Gets the inventory of the chest block represented by this block state. -diff --git a/src/main/java/org/bukkit/block/Dispenser.java b/src/main/java/org/bukkit/block/Dispenser.java -index 74cd194c9a98245dc52e7e352d7d6c046e1e5cf3..07af1a3f011d4b96275f919d302ac367198e923e 100644 ---- a/src/main/java/org/bukkit/block/Dispenser.java -+++ b/src/main/java/org/bukkit/block/Dispenser.java -@@ -1,5 +1,6 @@ - package org.bukkit.block; - -+import com.destroystokyo.paper.loottable.LootableBlockInventory; - import org.bukkit.Nameable; - import org.bukkit.loot.Lootable; - import org.bukkit.projectiles.BlockProjectileSource; -@@ -8,7 +9,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a captured state of a dispenser. - */ --public interface Dispenser extends Container, Nameable, Lootable { -+public interface Dispenser extends Container, Nameable, LootableBlockInventory { // Paper - - /** - * Gets the BlockProjectileSource object for the dispenser. -diff --git a/src/main/java/org/bukkit/block/Dropper.java b/src/main/java/org/bukkit/block/Dropper.java -index 424392fb5ed4628199b0e73689522aa3c90740cb..c76202321e29ad67597ca3017eb8d9baf6787383 100644 ---- a/src/main/java/org/bukkit/block/Dropper.java -+++ b/src/main/java/org/bukkit/block/Dropper.java -@@ -1,11 +1,12 @@ - package org.bukkit.block; - -+import com.destroystokyo.paper.loottable.LootableBlockInventory; - import org.bukkit.loot.Lootable; - - /** - * Represents a captured state of a dropper. - */ --public interface Dropper extends Container, Lootable { -+public interface Dropper extends Container, LootableBlockInventory { // Paper - - /** - * Tries to drop a randomly selected item from the dropper's inventory, -diff --git a/src/main/java/org/bukkit/block/Hopper.java b/src/main/java/org/bukkit/block/Hopper.java -index 58e493099810fb8d4705ecd49b4a5e1e1949b87b..7ade312f180b7e30871d3a3240c76325cc369c26 100644 ---- a/src/main/java/org/bukkit/block/Hopper.java -+++ b/src/main/java/org/bukkit/block/Hopper.java -@@ -1,8 +1,9 @@ - package org.bukkit.block; - -+import com.destroystokyo.paper.loottable.LootableBlockInventory; - import org.bukkit.loot.Lootable; - - /** - * Represents a captured state of a hopper. - */ --public interface Hopper extends Container, Lootable { } -+public interface Hopper extends Container, LootableBlockInventory { } // Paper -diff --git a/src/main/java/org/bukkit/block/ShulkerBox.java b/src/main/java/org/bukkit/block/ShulkerBox.java -index 387b2892886e1ccb2bd928e5111fb9bd41d777ab..5dc5318b0a451937228a8a059dfec1cd9de389a6 100644 ---- a/src/main/java/org/bukkit/block/ShulkerBox.java -+++ b/src/main/java/org/bukkit/block/ShulkerBox.java -@@ -1,5 +1,6 @@ - package org.bukkit.block; - -+import com.destroystokyo.paper.loottable.LootableBlockInventory; - import org.bukkit.DyeColor; - import org.bukkit.loot.Lootable; - import org.jetbrains.annotations.Nullable; -@@ -7,7 +8,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a captured state of a ShulkerBox. - */ --public interface ShulkerBox extends Container, Lootable, Lidded { -+public interface ShulkerBox extends Container, LootableBlockInventory, Lidded { // Paper - - /** - * Get the {@link DyeColor} corresponding to this ShulkerBox -diff --git a/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java b/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java -index 937b99f8734d71b2ad33af142afbc251b81d9745..db69687a7ad4b18d17ab1677cae5d8dd4dcd3678 100644 ---- a/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java -+++ b/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java -@@ -1,5 +1,6 @@ - package org.bukkit.entity.minecart; - -+import com.destroystokyo.paper.loottable.LootableEntityInventory; - import org.bukkit.entity.Minecart; - import org.bukkit.inventory.InventoryHolder; - import org.bukkit.loot.Lootable; -@@ -7,7 +8,7 @@ import org.bukkit.loot.Lootable; - /** - * Represents a Minecart with a Hopper inside it - */ --public interface HopperMinecart extends Minecart, InventoryHolder, Lootable { -+public interface HopperMinecart extends Minecart, InventoryHolder, LootableEntityInventory { - - /** - * Checks whether or not this Minecart will pick up -diff --git a/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java b/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java -index 9ea403e6fd8e960d017660e0aec118abeda2c42b..238d118f7788b13cd86b7e9ea3a0fc38e2e09715 100644 ---- a/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java -+++ b/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java -@@ -1,5 +1,6 @@ - package org.bukkit.entity.minecart; - -+import com.destroystokyo.paper.loottable.LootableEntityInventory; - import org.bukkit.entity.Minecart; - import org.bukkit.inventory.InventoryHolder; - import org.bukkit.loot.Lootable; -@@ -9,5 +10,5 @@ import org.bukkit.loot.Lootable; - * minecarts} have their own inventory that can be accessed using methods - * from the {@link InventoryHolder} interface. - */ --public interface StorageMinecart extends Minecart, InventoryHolder, Lootable { -+public interface StorageMinecart extends Minecart, InventoryHolder, LootableEntityInventory { // Paper - } -diff --git a/src/main/java/org/bukkit/loot/Lootable.java b/src/main/java/org/bukkit/loot/Lootable.java -index 24a3d989db3bc67e7afe8459a3d4bb132f448ea7..901db852498e0658c79a57582508dab29bf0a798 100644 ---- a/src/main/java/org/bukkit/loot/Lootable.java -+++ b/src/main/java/org/bukkit/loot/Lootable.java -@@ -36,6 +36,34 @@ public interface Lootable { - @Nullable - LootTable getLootTable(); - -+ // Paper start -+ /** -+ * Set the loot table and seed for a container or entity at the same time. -+ * -+ * @param table the Loot Table this {@link org.bukkit.block.Container} or {@link org.bukkit.entity.Mob} will have. -+ * @param seed the seed to used to generate loot. Default is 0. -+ */ -+ default void setLootTable(@Nullable LootTable table, long seed) { -+ setLootTable(table); -+ setSeed(seed); -+ } -+ -+ /** -+ * Returns whether or not this object has a Loot Table -+ * @return Has a loot table -+ */ -+ default boolean hasLootTable() { -+ return getLootTable() != null; -+ } -+ -+ /** -+ * Clears the associated Loot Table to this object -+ */ -+ default void clearLootTable() { -+ setLootTable(null); -+ } -+ // Paper end -+ - /** - * Set the seed used when this Loot Table generates loot. - * diff --git a/Unmapped-Spigot-API-Patches/0037-Add-EntityZapEvent.patch b/Unmapped-Spigot-API-Patches/0037-Add-EntityZapEvent.patch deleted file mode 100644 index 41d603f073..0000000000 --- a/Unmapped-Spigot-API-Patches/0037-Add-EntityZapEvent.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlphaBlend -Date: Sun, 16 Oct 2016 23:19:34 -0700 -Subject: [PATCH] Add EntityZapEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3b725a489008d333630af166d2be5fc48168a6b9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java -@@ -0,0 +1,65 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.apache.commons.lang.Validate; -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.LightningStrike; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.event.entity.EntityTransformEvent; -+ -+import java.util.Collections; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when lightning strikes an entity -+ */ -+public class EntityZapEvent extends EntityTransformEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ @NotNull private final LightningStrike bolt; -+ -+ public EntityZapEvent(@NotNull final Entity entity, @NotNull final LightningStrike bolt, @NotNull final Entity replacementEntity) { -+ super(entity, Collections.singletonList(replacementEntity), TransformReason.LIGHTNING); -+ Validate.notNull(bolt); -+ Validate.notNull(replacementEntity); -+ this.bolt = bolt; -+ } -+ -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ /** -+ * Gets the lightning bolt that is striking the entity. -+ * @return The lightning bolt responsible for this event -+ */ -+ @NotNull -+ public LightningStrike getBolt() { -+ return bolt; -+ } -+ -+ /** -+ * Gets the entity that will replace the struck entity. -+ * @return The entity that will replace the struck entity -+ */ -+ @NotNull -+ public Entity getReplacementEntity() { -+ return getTransformedEntity(); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/event/entity/PigZapEvent.java b/src/main/java/org/bukkit/event/entity/PigZapEvent.java -index 0e0ed93b568fd2c0d8f6e359c31dc29cb0fa71c2..d3949edfc736b3d67a627ef378748b374769e183 100644 ---- a/src/main/java/org/bukkit/event/entity/PigZapEvent.java -+++ b/src/main/java/org/bukkit/event/entity/PigZapEvent.java -@@ -2,6 +2,7 @@ package org.bukkit.event.entity; - - import java.util.Collections; - import org.bukkit.entity.Entity; -+import com.destroystokyo.paper.event.entity.EntityZapEvent; - import org.bukkit.entity.LightningStrike; - import org.bukkit.entity.Pig; - import org.bukkit.entity.PigZombie; -@@ -12,14 +13,14 @@ import org.jetbrains.annotations.NotNull; - /** - * Stores data for pigs being zapped - */ --public class PigZapEvent extends EntityTransformEvent implements Cancellable { -- private static final HandlerList handlers = new HandlerList(); -+public class PigZapEvent extends EntityZapEvent implements Cancellable { -+ //private static final HandlerList handlers = new HandlerList(); - private boolean canceled; - private final PigZombie pigzombie; - private final LightningStrike bolt; - - public PigZapEvent(@NotNull final Pig pig, @NotNull final LightningStrike bolt, @NotNull final PigZombie pigzombie) { -- super(pig, Collections.singletonList((Entity) pigzombie), TransformReason.LIGHTNING); -+ super(pig, bolt, pigzombie); - this.bolt = bolt; - this.pigzombie = pigzombie; - } -@@ -63,6 +64,8 @@ public class PigZapEvent extends EntityTransformEvent implements Cancellable { - return pigzombie; - } - -+ // Paper start -+ /* - @NotNull - @Override - public HandlerList getHandlers() { -@@ -73,4 +76,6 @@ public class PigZapEvent extends EntityTransformEvent implements Cancellable { - public static HandlerList getHandlerList() { - return handlers; - } -+ */ -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0038-Misc-Utils.patch b/Unmapped-Spigot-API-Patches/0038-Misc-Utils.patch deleted file mode 100644 index fac858b16c..0000000000 --- a/Unmapped-Spigot-API-Patches/0038-Misc-Utils.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: vemacs -Date: Wed, 23 Nov 2016 12:53:43 -0500 -Subject: [PATCH] Misc Utils - - -diff --git a/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java b/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5bb677ce585b856b3d3e589e29786a29619c56a7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java -@@ -0,0 +1,34 @@ -+package com.destroystokyo.paper.utils; -+ -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.concurrent.atomic.LongAdder; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class CachedSizeConcurrentLinkedQueue extends ConcurrentLinkedQueue { -+ private final LongAdder cachedSize = new LongAdder(); -+ -+ @Override -+ public boolean add(@NotNull E e) { -+ boolean result = super.add(e); -+ if (result) { -+ cachedSize.increment(); -+ } -+ return result; -+ } -+ -+ @Nullable -+ @Override -+ public E poll() { -+ E result = super.poll(); -+ if (result != null) { -+ cachedSize.decrement(); -+ } -+ return result; -+ } -+ -+ @Override -+ public int size() { -+ return cachedSize.intValue(); -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch b/Unmapped-Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch deleted file mode 100644 index dcad4e696d..0000000000 --- a/Unmapped-Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: willies952002 -Date: Mon, 28 Nov 2016 10:16:39 -0500 -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 1380a26f34a9d2b162e88fbea14b17118945643c..7b3a0c958b4b4bffb6c19a0e4d3bf4824f8db237 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1759,6 +1759,15 @@ public final class Bukkit { - public static void reloadPermissions() { - server.reloadPermissions(); - } -+ -+ /** -+ * Reload the Command Aliases in commands.yml -+ * -+ * @return Whether the reload was successful -+ */ -+ public static boolean reloadCommandAliases() { -+ return server.reloadCommandAliases(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 4c201097ef98f545acb604fa72d56413553e4d4f..6f4817af249e258905c97f4dac3d2f33804bdfc5 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1551,4 +1551,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - // Spigot end - - void reloadPermissions(); // Paper -+ -+ boolean reloadCommandAliases(); // Paper - } -diff --git a/src/main/java/org/bukkit/command/CommandMap.java b/src/main/java/org/bukkit/command/CommandMap.java -index bd2c7a6964722412148fae39e1b4951fc0002b9b..864c263bbd4dd6dd7c37a74b39b1a40a884d0731 100644 ---- a/src/main/java/org/bukkit/command/CommandMap.java -+++ b/src/main/java/org/bukkit/command/CommandMap.java -@@ -128,4 +128,14 @@ public interface CommandMap { - */ - @Nullable - public List tabComplete(@NotNull CommandSender sender, @NotNull String cmdLine, @Nullable Location location) throws IllegalArgumentException; -+ -+ // Paper start - Expose Known Commands -+ /** -+ * Return a Map of known commands -+ * -+ * @return known commands -+ */ -+ @NotNull -+ public java.util.Map getKnownCommands(); -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java -index adfc7aae2c0f49bbcdd358e83b04a0cf078a7d52..460fda05a62b12db2edcfb7ea8b2a5dd8e4b110d 100644 ---- a/src/main/java/org/bukkit/command/SimpleCommandMap.java -+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java -@@ -297,4 +297,11 @@ public class SimpleCommandMap implements CommandMap { - } - } - } -+ -+ // Paper start - Expose Known Commands -+ @NotNull -+ public Map getKnownCommands() { -+ return knownCommands; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -index c62da4131b17e66892678e8b618fb9ba3de93b56..0c7ba0718de2b93d013968ca0fec34ffd423990f 100644 ---- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -+++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -@@ -13,7 +13,7 @@ public class ReloadCommand extends BukkitCommand { - public ReloadCommand(@NotNull String name) { - super(name); - this.description = "Reloads the server configuration and plugins"; -- this.usageMessage = "/reload [permissions]"; // Paper -+ this.usageMessage = "/reload [permissions|commands|confirm]"; // Paper - this.setPermission("bukkit.command.reload"); - this.setAliases(Arrays.asList("rl")); - } -@@ -29,6 +29,13 @@ public class ReloadCommand extends BukkitCommand { - Bukkit.getServer().reloadPermissions(); - Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Permissions successfully reloaded."); - return true; -+ } else if ("commands".equalsIgnoreCase(args[0])) { -+ if (Bukkit.getServer().reloadCommandAliases()) { -+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Command aliases successfully reloaded."); -+ } else { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "An error occurred while trying to reload command aliases."); -+ } -+ return true; - } else if ("confirm".equalsIgnoreCase(args[0])) { - confirmed = true; - } else { -@@ -53,6 +60,6 @@ public class ReloadCommand extends BukkitCommand { - @NotNull - @Override - public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException { -- return java.util.Collections.singletonList("permissions"); // Paper -+ return com.google.common.collect.Lists.newArrayList("permissions", "commands"); // Paper - } - } diff --git a/Unmapped-Spigot-API-Patches/0040-Add-source-to-PlayerExpChangeEvent.patch b/Unmapped-Spigot-API-Patches/0040-Add-source-to-PlayerExpChangeEvent.patch deleted file mode 100644 index 675b2be839..0000000000 --- a/Unmapped-Spigot-API-Patches/0040-Add-source-to-PlayerExpChangeEvent.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlphaBlend -Date: Thu, 8 Sep 2016 08:47:08 -0700 -Subject: [PATCH] Add source to PlayerExpChangeEvent - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerExpChangeEvent.java b/src/main/java/org/bukkit/event/player/PlayerExpChangeEvent.java -index c99c9281e98e4b510dddb711b8785bcd56b3b92f..7c340f539c31a431d7d9204a8135e0bfc31863a8 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerExpChangeEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerExpChangeEvent.java -@@ -1,21 +1,43 @@ - package org.bukkit.event.player; - -+import org.bukkit.entity.Entity; // Paper - import org.bukkit.entity.Player; - import org.bukkit.event.HandlerList; - import org.jetbrains.annotations.NotNull; - -+import org.jetbrains.annotations.Nullable; // Paper -+ - /** - * Called when a players experience changes naturally - */ - public class PlayerExpChangeEvent extends PlayerEvent { - private static final HandlerList handlers = new HandlerList(); -+ // Paper start -+ @Nullable -+ private final Entity source; - private int exp; - - public PlayerExpChangeEvent(@NotNull final Player player, final int expAmount) { -+ this(player, null, expAmount); -+ } -+ -+ public PlayerExpChangeEvent(@NotNull final Player player, @Nullable final Entity sourceEntity, final int expAmount) { - super(player); -+ source = sourceEntity; - exp = expAmount; - } - -+ /** -+ * Get the source that provided the experience. -+ * -+ * @return The source of the experience -+ */ -+ @Nullable -+ public Entity getSource() { -+ return source; -+ } -+ // Paper end -+ - /** - * Get the amount of experience the player will receive - * diff --git a/Unmapped-Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch b/Unmapped-Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch deleted file mode 100644 index a5c9df18df..0000000000 --- a/Unmapped-Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Fri, 16 Dec 2016 21:25:39 -0600 -Subject: [PATCH] Add ProjectileCollideEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..453663893021768ae21d4980ce17ffba55d9e129 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java -@@ -0,0 +1,67 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.Projectile; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when an projectile collides with an entity -+ *

    -+ * This event is called before {@link org.bukkit.event.entity.EntityDamageByEntityEvent}, and cancelling it will allow the projectile to continue flying -+ */ -+public class ProjectileCollideEvent extends EntityEvent implements Cancellable { -+ @NotNull private final Entity collidedWith; -+ -+ /** -+ * Get the entity the projectile collided with -+ * -+ * @return the entity collided with -+ */ -+ @NotNull -+ public Entity getCollidedWith() { -+ return collidedWith; -+ } -+ -+ public ProjectileCollideEvent(@NotNull Projectile what, @NotNull Entity collidedWith) { -+ super(what); -+ this.collidedWith = collidedWith; -+ } -+ -+ /** -+ * Get the projectile that collided -+ * -+ * @return the projectile that collided -+ */ -+ @NotNull -+ public Projectile getEntity() { -+ return (Projectile) super.getEntity(); -+ } -+ -+ private static final HandlerList handlerList = new HandlerList(); -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlerList; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlerList; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch b/Unmapped-Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch deleted file mode 100644 index ae3f76e08c..0000000000 --- a/Unmapped-Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 20 Dec 2016 15:55:55 -0500 -Subject: [PATCH] Add String based Action Bar API - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index ddbe5734ac0f905b0c388e30f17a281530b82262..6bb0bb8052c12c5a215abf4bd9602fbefc769523 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -3,6 +3,7 @@ package org.bukkit.entity; - import java.net.InetSocketAddress; - import java.util.UUID; - import com.destroystokyo.paper.Title; // Paper -+import net.kyori.adventure.text.Component; - import org.bukkit.DyeColor; - import org.bukkit.Effect; - import org.bukkit.GameMode; -@@ -616,6 +617,39 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - public void sendMap(@NotNull MapView map); - - // Paper start -+ -+ /** -+ * Sends an Action Bar message to the client. -+ * -+ * Use Section symbols for legacy color codes to send formatting. -+ * -+ * @param message The message to send -+ * @deprecated use {@link #sendActionBar(Component)} -+ */ -+ @Deprecated -+ public void sendActionBar(@NotNull String message); -+ -+ /** -+ * Sends an Action Bar message to the client. -+ * -+ * Use supplied alternative character to the section symbol to represent legacy color codes. -+ * -+ * @param alternateChar Alternate symbol such as '&' -+ * @param message The message to send -+ * @deprecated use {@link #sendActionBar(Component)} -+ */ -+ @Deprecated -+ public void sendActionBar(char alternateChar, @NotNull String message); -+ -+ /** -+ * Sends an Action Bar message to the client. -+ * -+ * @param message The components to send -+ * @deprecated use {@link #sendActionBar(Component)} -+ */ -+ @Deprecated -+ public void sendActionBar(@NotNull net.md_5.bungee.api.chat.BaseComponent... message); -+ - /** - * Sends the component to the player - * -@@ -643,9 +677,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - /** - * Sends an array of components as a single message to the specified screen position of this player - * -+ * @deprecated This is unlikely the API you want to use. See {@link #sendActionBar(String)} for a more proper Action Bar API. This deprecated API may send unsafe items to the client. - * @param position the screen position - * @param components the components to send - */ -+ @Deprecated - public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { - spigot().sendMessage(position, components); - } -@@ -1728,6 +1764,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - /** - * Sends the component to the specified screen position of this player - * -+ * @deprecated This is unlikely the API you want to use. See {@link #sendActionBar(String)} for a more proper Action Bar API. This deprecated API may send unsafe items to the client. - * @param position the screen position - * @param component the components to send - * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} -@@ -1740,6 +1777,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - /** - * Sends an array of components as a single message to the specified screen position of this player - * -+ * @deprecated This is unlikely the API you want to use. See {@link #sendActionBar(String)} for a more proper Action Bar API. This deprecated API may send unsafe items to the client. - * @param position the screen position - * @param components the components to send - * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} diff --git a/Unmapped-Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch b/Unmapped-Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch deleted file mode 100644 index 3f2a539353..0000000000 --- a/Unmapped-Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 21 Dec 2016 11:47:25 -0600 -Subject: [PATCH] Add API methods to control if armour stands can move - - -diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java -index e94ec567fbda93f4f5783f84b4b5136b309d0eab..fddc063798edc8084ca695578a47485204a7f3cd 100644 ---- a/src/main/java/org/bukkit/entity/ArmorStand.java -+++ b/src/main/java/org/bukkit/entity/ArmorStand.java -@@ -344,4 +344,21 @@ public interface ArmorStand extends LivingEntity { - */ - ADDING; - } -+ // Paper start -+ /** -+ * Tests if this armor stand can move. -+ * -+ *

    The default value is {@code true}.

    -+ * -+ * @return {@code true} if this armour stand can move, {@code false} otherwise -+ */ -+ boolean canMove(); -+ -+ /** -+ * Sets if this armor stand can move. -+ * -+ * @param move {@code true} if this armour stand can move, {@code false} otherwise -+ */ -+ void setCanMove(boolean move); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0044-IllegalPacketEvent.patch b/Unmapped-Spigot-API-Patches/0044-IllegalPacketEvent.patch deleted file mode 100644 index 7eb8d61aaa..0000000000 --- a/Unmapped-Spigot-API-Patches/0044-IllegalPacketEvent.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 4 Dec 2016 01:19:14 -0500 -Subject: [PATCH] IllegalPacketEvent - -Fire an event when an illegal packet is received to let plugins handle it - -Lets plugins change the kick message and if it should kick or not. - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java b/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8d8e9b16f2a6707d2af7567c7682dfc5db51a737 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java -@@ -0,0 +1,74 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * @deprecated Not used -+ */ -+@Deprecated -+public class IllegalPacketEvent extends PlayerEvent { -+ @Nullable private final String type; -+ @Nullable private final String ex; -+ @Nullable private String kickMessage; -+ private boolean shouldKick = true; -+ -+ public IllegalPacketEvent(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception e) { -+ super(player); -+ this.type = type; -+ this.kickMessage = kickMessage; -+ this.ex = e.getMessage(); -+ } -+ -+ public boolean isShouldKick() { -+ return shouldKick; -+ } -+ -+ public void setShouldKick(boolean shouldKick) { -+ this.shouldKick = shouldKick; -+ } -+ -+ @Nullable -+ public String getKickMessage() { -+ return kickMessage; -+ } -+ -+ public void setKickMessage(@Nullable String kickMessage) { -+ this.kickMessage = kickMessage; -+ } -+ -+ @Nullable -+ public String getType() { -+ return type; -+ } -+ -+ @Nullable -+ public String getExceptionMessage() { -+ return ex; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ public static void process(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception exception) { -+ IllegalPacketEvent event = new IllegalPacketEvent(player, type, kickMessage, exception); -+ event.callEvent(); -+ if (event.shouldKick) { -+ player.kickPlayer(kickMessage); -+ } -+ Bukkit.getLogger().severe(player.getName() + "/" + type + ": " + exception.getMessage()); -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0045-Fireworks-API-s.patch b/Unmapped-Spigot-API-Patches/0045-Fireworks-API-s.patch deleted file mode 100644 index a0ed753ac6..0000000000 --- a/Unmapped-Spigot-API-Patches/0045-Fireworks-API-s.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 28 Dec 2016 01:18:55 -0500 -Subject: [PATCH] Fireworks API's - -Get the Entity being boosted -Get the firework launcher - -diff --git a/src/main/java/org/bukkit/entity/Firework.java b/src/main/java/org/bukkit/entity/Firework.java -index 05e86cb9d826cdf14490fa649348d46c51adbfdb..d616d5941b3c7b85e350e845901da798601b9a3c 100644 ---- a/src/main/java/org/bukkit/entity/Firework.java -+++ b/src/main/java/org/bukkit/entity/Firework.java -@@ -43,4 +43,15 @@ public interface Firework extends Projectile { - * @param shotAtAngle the new shotAtAngle - */ - void setShotAtAngle(boolean shotAtAngle); -+ -+ // Paper start -+ @org.jetbrains.annotations.Nullable -+ public java.util.UUID getSpawningEntity(); -+ /** -+ * If this firework is boosting an entity, return it -+ * @return The entity being boosted -+ */ -+ @org.jetbrains.annotations.Nullable -+ public LivingEntity getBoostedEntity(); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch b/Unmapped-Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch deleted file mode 100644 index 664edd24cd..0000000000 --- a/Unmapped-Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 31 Dec 2016 20:29:33 -0500 -Subject: [PATCH] PlayerTeleportEndGatewayEvent - -Allows you to access the Gateway being used in a teleport event - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b64ab6eecd8bc4ca9c109b9d83c82861d6260793 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java -@@ -0,0 +1,29 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.Location; -+import org.bukkit.block.EndGateway; -+import org.bukkit.entity.Player; -+import org.bukkit.event.player.PlayerTeleportEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a teleport is triggered for an End Gateway -+ */ -+public class PlayerTeleportEndGatewayEvent extends PlayerTeleportEvent { -+ @NotNull private final EndGateway gateway; -+ -+ public PlayerTeleportEndGatewayEvent(@NotNull Player player, @NotNull Location from, @NotNull Location to, @NotNull EndGateway gateway) { -+ super(player, from, to, PlayerTeleportEvent.TeleportCause.END_GATEWAY); -+ this.gateway = gateway; -+ } -+ -+ /** -+ * The gateway triggering the teleport -+ * -+ * @return EndGateway used -+ */ -+ @NotNull -+ public EndGateway getGateway() { -+ return gateway; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch b/Unmapped-Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch deleted file mode 100644 index fc838a6f02..0000000000 --- a/Unmapped-Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 15:23:03 -0500 -Subject: [PATCH] Provide E/TE/Chunk count stat methods - -Provides counts without the ineffeciency of using .getEntities().size() -which creates copy of the collections. - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 6b5dbe4ea711807a1944cfe2aae2ce415d4f2638..789e070f6aee83e4b6426def784e05df98e1bc65 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -40,6 +40,33 @@ import org.jetbrains.annotations.Nullable; - */ - public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience { // Paper - -+ // Paper start -+ /** -+ * @return The amount of Entities in this world -+ */ -+ int getEntityCount(); -+ -+ /** -+ * @return The amount of Tile Entities in this world -+ */ -+ int getTileEntityCount(); -+ -+ /** -+ * @return The amount of Tickable Tile Entities in this world -+ */ -+ int getTickableTileEntityCount(); -+ -+ /** -+ * @return The amount of Chunks in this world -+ */ -+ int getChunkCount(); -+ -+ /** -+ * @return The amount of Players in this world -+ */ -+ int getPlayerCount(); -+ // Paper end -+ - /** - * Gets the {@link Block} at the given coordinates - * diff --git a/Unmapped-Spigot-API-Patches/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/Unmapped-Spigot-API-Patches/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch deleted file mode 100644 index 5dadaf640f..0000000000 --- a/Unmapped-Spigot-API-Patches/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 16:28:32 -0500 -Subject: [PATCH] ExperienceOrbs API for Reason/Source/Triggering player - -Adds lots of information about why this orb exists. - -Replaces isFromBottle() with logic that persists entity reloads too. - -diff --git a/src/main/java/org/bukkit/entity/ExperienceOrb.java b/src/main/java/org/bukkit/entity/ExperienceOrb.java -index c286edfd827e185a76e44c44faace19a80325d7a..dec70bbfaf73a9d525b2c45682b804c684e1645b 100644 ---- a/src/main/java/org/bukkit/entity/ExperienceOrb.java -+++ b/src/main/java/org/bukkit/entity/ExperienceOrb.java -@@ -1,5 +1,8 @@ - package org.bukkit.entity; - -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; // Paper -+ - /** - * Represents an Experience Orb. - */ -@@ -18,4 +21,99 @@ public interface ExperienceOrb extends Entity { - * @param value Amount of experience - */ - public void setExperience(int value); -+ -+ // Paper start -+ /** -+ * Check if this orb was spawned from a {@link ThrownExpBottle} -+ * -+ * @return if orb was spawned from a bottle -+ * @deprecated Use getSpawnReason() == EXP_BOTTLE -+ */ -+ @Deprecated -+ default boolean isFromBottle() { -+ return getSpawnReason() == SpawnReason.EXP_BOTTLE; -+ } -+ -+ /** -+ * Reasons for why this Experience Orb was spawned -+ */ -+ enum SpawnReason { -+ /** -+ * Spawned by a player dying -+ */ -+ PLAYER_DEATH, -+ /** -+ * Spawned by an entity dying after being damaged by a player -+ */ -+ ENTITY_DEATH, -+ /** -+ * Spawned by player using a furnace -+ */ -+ FURNACE, -+ /** -+ * Spawned by player breeding animals -+ */ -+ BREED, -+ /** -+ * Spawned by player trading with a villager -+ */ -+ VILLAGER_TRADE, -+ /** -+ * Spawned by player fishing -+ */ -+ FISHING, -+ /** -+ * Spawned by player breaking a block that gives experience points such as Diamond Ore -+ */ -+ BLOCK_BREAK, -+ /** -+ * Spawned by Bukkit API -+ */ -+ CUSTOM, -+ /** -+ * Spawned by a player throwing an experience points bottle -+ */ -+ EXP_BOTTLE, -+ /** -+ * Spawned by a player using a grindstone -+ */ -+ GRINDSTONE, -+ /** -+ * We do not know why it was spawned -+ */ -+ UNKNOWN -+ } -+ -+ /** -+ * If this experience orb was triggered to be spawned by -+ * an entity such as a player, due to events such as killing entity, -+ * breaking blocks, smelting in a furnace, etc, this will return the UUID -+ * of the entity that triggered this orb to drop. -+ * -+ * In the case of an entity being killed, this will be the killers UUID. -+ * -+ * @return UUID of the player that triggered this orb to drop, or null if unknown/no triggering entity -+ */ -+ @Nullable java.util.UUID getTriggerEntityId(); -+ -+ /** -+ * If this experience orb was spawned in relation to another -+ * entity, such as a player or other living entity death, or breeding, -+ * return the source entity UUID. -+ * -+ * In the case of breeding, this will be the new baby entities UUID. -+ * In the case of an entity being killed, this will be the dead entities UUID. -+ * -+ * @return The UUID of the entity that sourced this experience orb -+ */ -+ @Nullable java.util.UUID getSourceEntityId(); -+ -+ /** -+ * Gets the reason that this experience orb was spawned. For any case that we -+ * do not know, such as orbs spawned before this API was added, UNKNOWN is returned. -+ * @return The reason for this orb being spawned. -+ */ -+ @NotNull -+ SpawnReason getSpawnReason(); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch b/Unmapped-Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch deleted file mode 100644 index f700226be3..0000000000 --- a/Unmapped-Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 21 Jan 2017 17:03:10 -0600 -Subject: [PATCH] Expose WorldBorder#isInBounds(Location) check - - -diff --git a/src/main/java/org/bukkit/WorldBorder.java b/src/main/java/org/bukkit/WorldBorder.java -index 7e8f5649ce0eb0090899514b1e228601eb644613..afb7b136b461202026290624836446cff9f9e45d 100644 ---- a/src/main/java/org/bukkit/WorldBorder.java -+++ b/src/main/java/org/bukkit/WorldBorder.java -@@ -117,4 +117,18 @@ public interface WorldBorder { - * @return if this location is inside the border or not - */ - public boolean isInside(@NotNull Location location); -+ -+ // Paper start -+ /** -+ * Checks if the location is within the boundaries of this border. -+ * -+ * @param location specific location to check -+ * @return true if the location is within the bounds of this border, false otherwise. -+ * @deprecated use {@link #isInside(Location)} for an upstream compatible replacement -+ */ -+ @Deprecated -+ public default boolean isInBounds(@NotNull Location location) { -+ return this.isInside(location); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch b/Unmapped-Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch deleted file mode 100644 index 195a5c5c39..0000000000 --- a/Unmapped-Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Fri, 9 Jun 2017 07:24:24 -0700 -Subject: [PATCH] Add configuration option to prevent player names from being - suggested - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 7b3a0c958b4b4bffb6c19a0e4d3bf4824f8db237..e2052baa65ed3525a89b26c065b3e2a58916ab99 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1768,6 +1768,16 @@ public final class Bukkit { - public static boolean reloadCommandAliases() { - return server.reloadCommandAliases(); - } -+ -+ /** -+ * Checks if player names should be suggested when a command returns {@code null} as -+ * their tab completion result. -+ * -+ * @return true if player names should be suggested -+ */ -+ public static boolean suggestPlayerNamesWhenNullTabCompletions() { -+ return server.suggestPlayerNamesWhenNullTabCompletions(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 6f4817af249e258905c97f4dac3d2f33804bdfc5..8fd026e4ffcdf009365ae04b87f7559bed32c7d3 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1553,4 +1553,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - void reloadPermissions(); // Paper - - boolean reloadCommandAliases(); // Paper -+ -+ // Paper start - allow preventing player name suggestions by default -+ /** -+ * Checks if player names should be suggested when a command returns {@code null} as -+ * their tab completion result. -+ * -+ * @return true if player names should be suggested -+ */ -+ boolean suggestPlayerNamesWhenNullTabCompletions(); -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java -index 03bdc1622791e1206406c87065978688d602e39e..7c80dc54776d0d66f7816b77136f6dbd9b801704 100644 ---- a/src/main/java/org/bukkit/command/Command.java -+++ b/src/main/java/org/bukkit/command/Command.java -@@ -99,7 +99,7 @@ public abstract class Command { - Validate.notNull(args, "Arguments cannot be null"); - Validate.notNull(alias, "Alias cannot be null"); - -- if (args.length == 0) { -+ if (args.length == 0 || !sender.getServer().suggestPlayerNamesWhenNullTabCompletions()) { // Paper - allow preventing player name suggestions by default) { - return ImmutableList.of(); - } - diff --git a/Unmapped-Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch b/Unmapped-Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch deleted file mode 100644 index 083596bdd2..0000000000 --- a/Unmapped-Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 10 Jun 2017 16:59:40 -0500 -Subject: [PATCH] Fix upstream javadoc warnings and errors - -Upstream still refuses to use Java 8 with the API so they are likely unaware these are even issues. - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 3f68baef538098d9ce66b91195b6fa17f26f0d78..e71b048e53ee2db4e768eea2ddf19b00a14d2484 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -634,7 +634,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * - * Use supplied alternative character to the section symbol to represent legacy color codes. - * -- * @param alternateChar Alternate symbol such as '&' -+ * @param alternateChar Alternate symbol such as '&' - * @param message The message to send - * @deprecated use {@link #sendActionBar(Component)} - */ -diff --git a/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java b/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java -index 1b2267f4e8ebded198773ec80e2bff2c861c7084..1a58734d919fae247eeb85dd785fd59990856505 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java -@@ -78,7 +78,7 @@ public class PlayerMoveEvent extends PlayerEvent implements Cancellable { - * - * @return Location the player moved to - */ -- @Nullable -+ @NotNull // Paper - public Location getTo() { - return to; - } -diff --git a/src/main/java/org/bukkit/inventory/PlayerInventory.java b/src/main/java/org/bukkit/inventory/PlayerInventory.java -index 91afd844dafec4ed9ab9e2e16b220ffbd35e7495..1e45c9078ffffe9d3c25538fdd433780ae751270 100644 ---- a/src/main/java/org/bukkit/inventory/PlayerInventory.java -+++ b/src/main/java/org/bukkit/inventory/PlayerInventory.java -@@ -106,7 +106,7 @@ public interface PlayerInventory extends Inventory { - * - * @return the ItemStack in the given slot - */ -- @NotNull -+ @Nullable - public ItemStack getItem(@NotNull EquipmentSlot slot); - - /** diff --git a/Unmapped-Spigot-API-Patches/0052-Item-canEntityPickup.patch b/Unmapped-Spigot-API-Patches/0052-Item-canEntityPickup.patch deleted file mode 100644 index 27894bda93..0000000000 --- a/Unmapped-Spigot-API-Patches/0052-Item-canEntityPickup.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 5 May 2017 03:57:08 -0500 -Subject: [PATCH] Item#canEntityPickup - - -diff --git a/src/main/java/org/bukkit/entity/Item.java b/src/main/java/org/bukkit/entity/Item.java -index 3f2736fbddd8661e764bc2f8d0499bd13ca91df5..c404a5b8efea7c780db5ddae19456753808abb3d 100644 ---- a/src/main/java/org/bukkit/entity/Item.java -+++ b/src/main/java/org/bukkit/entity/Item.java -@@ -75,4 +75,20 @@ public interface Item extends Entity { - */ - @Nullable - public UUID getThrower(); -+ -+ // Paper Start -+ /** -+ * Gets if non-player entities can pick this Item up -+ * -+ * @return True if non-player entities can pickup -+ */ -+ public boolean canMobPickup(); -+ -+ /** -+ * Sets if non-player entities can pick this Item up -+ * -+ * @param canMobPickup True to allow non-player entity pickup -+ */ -+ public void setCanMobPickup(boolean canMobPickup); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch b/Unmapped-Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch deleted file mode 100644 index 353d395911..0000000000 --- a/Unmapped-Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 May 2017 06:26:01 -0500 -Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java b/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java -index 951ea2cc763973655beedcba3c75332d3f297313..18d82c111f30e0279c10a174a51bac018185cd38 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java -@@ -17,6 +17,7 @@ import org.jetbrains.annotations.NotNull; - public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private final Item item; -+ private boolean flyAtPlayer = true; // Paper - private boolean cancel = false; - private final int remaining; - -@@ -45,6 +46,27 @@ public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable { - return remaining; - } - -+ // Paper Start -+ /** -+ * Set if the item will fly at the player -+ *

    Cancelling the event will set this value to false.

    -+ * -+ * @param flyAtPlayer True for item to fly at player -+ */ -+ public void setFlyAtPlayer(boolean flyAtPlayer) { -+ this.flyAtPlayer = flyAtPlayer; -+ } -+ -+ /** -+ * Gets if the item will fly at the player -+ * -+ * @return True if the item will fly at the player -+ */ -+ public boolean getFlyAtPlayer() { -+ return flyAtPlayer; -+ } -+ // Paper End -+ - @Override - public boolean isCancelled() { - return cancel; -@@ -53,6 +75,7 @@ public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable { - @Override - public void setCancelled(boolean cancel) { - this.cancel = cancel; -+ this.flyAtPlayer = !cancel; // Paper - } - - @NotNull diff --git a/Unmapped-Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch b/Unmapped-Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch deleted file mode 100644 index 6b504ae688..0000000000 --- a/Unmapped-Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 11 Jun 2017 16:30:37 -0500 -Subject: [PATCH] PlayerAttemptPickupItemEvent - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java b/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0788153a9641e75da565d2e6eee37eeee1cbc61e ---- /dev/null -+++ b/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java -@@ -0,0 +1,90 @@ -+package org.bukkit.event.player; -+ -+import org.bukkit.entity.Item; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Thrown when a player attempts to pick an item up from the ground -+ */ -+public class PlayerAttemptPickupItemEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private final Item item; -+ private final int remaining; -+ private boolean flyAtPlayer = true; -+ private boolean isCancelled = false; -+ -+ @Deprecated // Remove in 1.13 // Remove in 1.14? -+ public PlayerAttemptPickupItemEvent(@NotNull final Player player, @NotNull final Item item) { -+ this(player, item, 0); -+ } -+ -+ public PlayerAttemptPickupItemEvent(@NotNull final Player player, @NotNull final Item item, final int remaining) { -+ super(player); -+ this.item = item; -+ this.remaining = remaining; -+ } -+ -+ /** -+ * Gets the Item attempted by the player. -+ * -+ * @return Item -+ */ -+ @NotNull -+ public Item getItem() { -+ return item; -+ } -+ -+ /** -+ * Gets the amount that will remain on the ground, if any -+ * -+ * @return amount that will remain on the ground -+ */ -+ public int getRemaining() { -+ return remaining; -+ } -+ -+ /** -+ * Set if the item will fly at the player -+ *

    Cancelling the event will set this value to false.

    -+ * -+ * @param flyAtPlayer True for item to fly at player -+ */ -+ public void setFlyAtPlayer(boolean flyAtPlayer) { -+ this.flyAtPlayer = flyAtPlayer; -+ } -+ -+ /** -+ * Gets if the item will fly at the player -+ * -+ * @return True if the item will fly at the player -+ */ -+ public boolean getFlyAtPlayer() { -+ return this.flyAtPlayer; -+ } -+ -+ -+ @Override -+ public boolean isCancelled() { -+ return this.isCancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.isCancelled = cancel; -+ this.flyAtPlayer = !cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch b/Unmapped-Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch deleted file mode 100644 index 9e3d997b0d..0000000000 --- a/Unmapped-Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sweepyoface -Date: Sat, 17 Jun 2017 18:48:06 -0400 -Subject: [PATCH] Add UnknownCommandEvent - - -diff --git a/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java b/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d5632d352590dec6982a372b285a8d4a332fa589 ---- /dev/null -+++ b/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java -@@ -0,0 +1,114 @@ -+package org.bukkit.event.command; -+ -+import net.kyori.adventure.text.Component; -+import org.bukkit.Bukkit; -+import org.bukkit.command.CommandSender; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.Event; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Thrown when a player executes a command that is not defined -+ */ -+public class UnknownCommandEvent extends Event { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private CommandSender sender; -+ @NotNull private String commandLine; -+ @Nullable private Component message; -+ -+ @Deprecated -+ public UnknownCommandEvent(@NotNull final CommandSender sender, @NotNull final String commandLine, @Nullable final String message) { -+ this(sender, commandLine, message == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message)); -+ } -+ -+ public UnknownCommandEvent(@NotNull final CommandSender sender, @NotNull final String commandLine, @Nullable final Component message) { -+ super(false); -+ this.sender = sender; -+ this.commandLine = commandLine; -+ this.message = message; -+ } -+ -+ /** -+ * Gets the CommandSender or ConsoleCommandSender -+ *

    -+ * -+ * @return Sender of the command -+ */ -+ @NotNull -+ public CommandSender getSender() { -+ return sender; -+ } -+ -+ /** -+ * Gets the command that was send -+ *

    -+ * -+ * @return Command sent -+ */ -+ @NotNull -+ public String getCommandLine() { -+ return commandLine; -+ } -+ -+ /** -+ * Gets message that will be returned -+ *

    -+ * -+ * @return Unknown command message -+ * @deprecated use {@link #message()} -+ */ -+ @Nullable -+ @Deprecated -+ public String getMessage() { -+ return this.message == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); -+ } -+ -+ /** -+ * Sets message that will be returned -+ *

    -+ * Set to null to avoid any message being sent -+ * -+ * @param message the message to be returned, or null -+ * @deprecated use {@link #message(Component)} -+ */ -+ @Deprecated -+ public void setMessage(@Nullable String message) { -+ this.message(message == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message)); -+ } -+ -+ /** -+ * Gets message that will be returned -+ *

    -+ * -+ * @return Unknown command message -+ */ -+ @Nullable -+ public Component message() { -+ return this.message; -+ } -+ -+ /** -+ * Sets message that will be returned -+ *

    -+ * Set to null to avoid any message being sent -+ * -+ * @param message the message to be returned, or null -+ */ -+ public void message(@Nullable Component message) { -+ this.message = message; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -+ diff --git a/Unmapped-Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch b/Unmapped-Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch deleted file mode 100644 index 1c7a3ce8f5..0000000000 --- a/Unmapped-Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch +++ /dev/null @@ -1,351 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 15 Jan 2018 21:46:46 -0500 -Subject: [PATCH] Basic PlayerProfile API - -Provides basic elements of a PlayerProfile to be used by future API/events - -diff --git a/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2ef9a7bd55e2c9cf8cb20d5f77282676ae11181f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java -@@ -0,0 +1,177 @@ -+package com.destroystokyo.paper.profile; -+ -+import java.util.Collection; -+import java.util.Set; -+import java.util.UUID; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Represents a players profile for the game, such as UUID, Name, and textures. -+ */ -+public interface PlayerProfile { -+ -+ /** -+ * @return The players name, if set -+ */ -+ @Nullable -+ String getName(); -+ -+ /** -+ * Sets this profiles Name -+ * -+ * @param name The new Name -+ * @return The previous Name -+ */ -+ @NotNull -+ String setName(@Nullable String name); -+ -+ /** -+ * @return The players unique identifier, if set -+ */ -+ @Nullable UUID getId(); -+ -+ /** -+ * Sets this profiles UUID -+ * -+ * @param uuid The new UUID -+ * @return The previous UUID -+ */ -+ @Nullable -+ UUID setId(@Nullable UUID uuid); -+ -+ /** -+ * @return A Mutable set of this players properties, such as textures. -+ * Values specified here are subject to implementation details. -+ */ -+ @NotNull Set getProperties(); -+ -+ /** -+ * Check if the Profile has the specified property -+ * @param property Property name to check -+ * @return If the property is set -+ */ -+ boolean hasProperty(@Nullable String property); -+ -+ /** -+ * Sets a property. If the property already exists, the previous one will be replaced -+ * @param property Property to set. -+ */ -+ void setProperty(@NotNull ProfileProperty property); -+ -+ /** -+ * Sets multiple properties. If any of the set properties already exist, it will be replaced -+ * @param properties The properties to set -+ */ -+ void setProperties(@NotNull Collection properties); -+ -+ /** -+ * Removes a specific property from this profile -+ * @param property The property to remove -+ * @return If a property was removed -+ */ -+ boolean removeProperty(@Nullable String property); -+ -+ /** -+ * Removes a specific property from this profile -+ * @param property The property to remove -+ * @return If a property was removed -+ */ -+ default boolean removeProperty(@NotNull ProfileProperty property) { -+ return removeProperty(property.getName()); -+ } -+ -+ /** -+ * Removes all properties in the collection -+ * @param properties The properties to remove -+ * @return If any property was removed -+ */ -+ default boolean removeProperties(@NotNull Collection properties) { -+ boolean removed = false; -+ for (ProfileProperty property : properties) { -+ if (removeProperty(property)) { -+ removed = true; -+ } -+ } -+ return removed; -+ } -+ -+ /** -+ * Clears all properties on this profile -+ */ -+ void clearProperties(); -+ -+ /** -+ * @return If the profile is now complete (has UUID and Name) -+ */ -+ boolean isComplete(); -+ -+ /** -+ * Like {@link #complete(boolean)} but will try only from cache, and not make network calls -+ * Does not account for textures. -+ * -+ * @return If the profile is now complete (has UUID and Name) -+ */ -+ boolean completeFromCache(); -+ -+ /** -+ * Like {@link #complete(boolean)} but will try only from cache, and not make network calls -+ * Does not account for textures. -+ * -+ * @param onlineMode Treat this as online mode or not -+ * @return If the profile is now complete (has UUID and Name) -+ */ -+ boolean completeFromCache(boolean onlineMode); -+ -+ /** -+ * Like {@link #complete(boolean)} but will try only from cache, and not make network calls -+ * Does not account for textures. -+ * -+ * @param lookupUUID If only name is supplied, should we do a UUID lookup -+ * @param onlineMode Treat this as online mode or not -+ * @return If the profile is now complete (has UUID and Name) -+ */ -+ boolean completeFromCache(boolean lookupUUID, boolean onlineMode); -+ -+ /** -+ * If this profile is not complete, then make the API call to complete it. -+ * This is a blocking operation and should be done asynchronously. -+ * -+ * This will also complete textures. If you do not want to load textures, use {{@link #complete(boolean)}} -+ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail) -+ */ -+ default boolean complete() { -+ return complete(true); -+ } -+ -+ /** -+ * If this profile is not complete, then make the API call to complete it. -+ * This is a blocking operation and should be done asynchronously. -+ * -+ * Optionally will also fill textures. -+ * -+ * Online mode will be automatically determined -+ * @param textures controls if we should fill the profile with texture properties -+ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail) -+ */ -+ boolean complete(boolean textures); -+ -+ /** -+ * If this profile is not complete, then make the API call to complete it. -+ * This is a blocking operation and should be done asynchronously. -+ * -+ * Optionally will also fill textures. -+ * @param textures controls if we should fill the profile with texture properties -+ * @param onlineMode Treat this server as online mode or not -+ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail) -+ */ -+ boolean complete(boolean textures, boolean onlineMode); -+ -+ /** -+ * Whether or not this Profile has textures associated to it -+ * @return If has a textures property -+ */ -+ default boolean hasTextures() { -+ return hasProperty("textures"); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java b/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7b3b6ef533d32169fbeca389bd61cfc6b0e0faee ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java -@@ -0,0 +1,72 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.google.common.base.Preconditions; -+ -+import java.util.Objects; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Represents a property on a {@link PlayerProfile} -+ */ -+public class ProfileProperty { -+ private final String name; -+ private final String value; -+ private final String signature; -+ -+ public ProfileProperty(@NotNull String name, @NotNull String value) { -+ this(name, value, null); -+ } -+ -+ public ProfileProperty(@NotNull String name, @NotNull String value, @Nullable String signature) { -+ this.name = Preconditions.checkNotNull(name, "ProfileProperty name can not be null"); -+ this.value = Preconditions.checkNotNull(value, "ProfileProperty value can not be null"); -+ this.signature = signature; -+ } -+ -+ /** -+ * @return The property name, ie "textures" -+ */ -+ @NotNull -+ public String getName() { -+ return name; -+ } -+ -+ /** -+ * @return The property value, likely to be base64 encoded -+ */ -+ @NotNull -+ public String getValue() { -+ return value; -+ } -+ -+ /** -+ * @return A signature from Mojang for signed properties -+ */ -+ @Nullable -+ public String getSignature() { -+ return signature; -+ } -+ -+ /** -+ * @return If this property has a signature or not -+ */ -+ public boolean isSigned() { -+ return this.signature != null; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ ProfileProperty that = (ProfileProperty) o; -+ return Objects.equals(name, that.name) && -+ Objects.equals(value, that.value) && -+ Objects.equals(signature, that.signature); -+ } -+ -+ @Override -+ public int hashCode() { -+ return Objects.hash(name); -+ } -+} -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index e2052baa65ed3525a89b26c065b3e2a58916ab99..39942b4c5683f2dcc40be5a23af36a3bb32badb1 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1778,6 +1778,40 @@ public final class Bukkit { - public static boolean suggestPlayerNamesWhenNullTabCompletions() { - return server.suggestPlayerNamesWhenNullTabCompletions(); - } -+ -+ /** -+ * Creates a PlayerProfile for the specified uuid, with name as null -+ * @param uuid UUID to create profile for -+ * @return A PlayerProfile object -+ */ -+ @NotNull -+ public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull UUID uuid) { -+ return server.createProfile(uuid); -+ } -+ -+ /** -+ * Creates a PlayerProfile for the specified name, with UUID as null -+ * @param name Name to create profile for -+ * @return A PlayerProfile object -+ */ -+ @NotNull -+ public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull String name) { -+ return server.createProfile(name); -+ } -+ -+ /** -+ * Creates a PlayerProfile for the specified name/uuid -+ * -+ * Both UUID and Name can not be null at same time. One must be supplied. -+ * -+ * @param uuid UUID to create profile for -+ * @param name Name to create profile for -+ * @return A PlayerProfile object -+ */ -+ @NotNull -+ public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { -+ return server.createProfile(uuid, name); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 8fd026e4ffcdf009365ae04b87f7559bed32c7d3..0c1fbaee08cb614dfdd1de0200dfa7fa351fc52d 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1562,5 +1562,33 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @return true if player names should be suggested - */ - boolean suggestPlayerNamesWhenNullTabCompletions(); -+ -+ /** -+ * Creates a PlayerProfile for the specified uuid, with name as null -+ * @param uuid UUID to create profile for -+ * @return A PlayerProfile object -+ */ -+ @NotNull -+ com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull UUID uuid); -+ -+ /** -+ * Creates a PlayerProfile for the specified name, with UUID as null -+ * @param name Name to create profile for -+ * @return A PlayerProfile object -+ */ -+ @NotNull -+ com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull String name); -+ -+ /** -+ * Creates a PlayerProfile for the specified name/uuid -+ * -+ * Both UUID and Name can not be null at same time. One must be supplied. -+ * -+ * @param uuid UUID to create profile for -+ * @param name Name to create profile for -+ * @return A PlayerProfile object -+ */ -+ @NotNull -+ com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch b/Unmapped-Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch deleted file mode 100644 index 249e81f7ad..0000000000 --- a/Unmapped-Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 17 Jun 2017 15:04:51 -0400 -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 72178c3036f567ceaf15016978a9737eb9c4afc4..d212d5123b6294f7873d72f125505a006c290b05 100644 ---- a/src/main/java/org/bukkit/entity/HumanEntity.java -+++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -300,6 +300,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder - */ - public int getExpToLevel(); - -+ // Paper start -+ /** -+ * If there is an Entity on this entities left shoulder, it will be released to the world and returned. -+ * If no Entity is released, null will be returned. -+ * -+ * @return The released entity, or null -+ */ -+ @Nullable -+ public Entity releaseLeftShoulderEntity(); -+ -+ /** -+ * If there is an Entity on this entities left shoulder, it will be released to the world and returned. -+ * If no Entity is released, null will be returned. -+ * -+ * @return The released entity, or null -+ */ -+ @Nullable -+ public Entity releaseRightShoulderEntity(); -+ // Paper end -+ - /** - * Gets the current cooldown for a player's attack. - * diff --git a/Unmapped-Spigot-API-Patches/0058-Profile-Lookup-Events.patch b/Unmapped-Spigot-API-Patches/0058-Profile-Lookup-Events.patch deleted file mode 100644 index 1cdb35476d..0000000000 --- a/Unmapped-Spigot-API-Patches/0058-Profile-Lookup-Events.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 17 Jun 2017 16:30:44 -0400 -Subject: [PATCH] Profile Lookup Events - -Adds a Pre Lookup Event and a Post Lookup Event so that plugins may prefill in profile data, and cache the responses from -profiles that had to be looked up. - -diff --git a/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8df37c07cd55ddf110d1dd68183d7b697f7a6756 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java -@@ -0,0 +1,46 @@ -+package com.destroystokyo.paper.event.profile; -+ -+import com.destroystokyo.paper.profile.PlayerProfile; -+import org.bukkit.Bukkit; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Allows a plugin to be notified anytime AFTER a Profile has been looked up from the Mojang API -+ * This is an opportunity to view the response and potentially cache things. -+ * -+ * No guarantees are made about thread execution context for this event. If you need to know, check -+ * event.isAsync() -+ */ -+public class LookupProfileEvent extends Event { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull private final PlayerProfile profile; -+ -+ public LookupProfileEvent(@NotNull PlayerProfile profile) { -+ super(!Bukkit.isPrimaryThread()); -+ this.profile = profile; -+ } -+ -+ /** -+ * @return The profile that was recently looked up. This profile can be mutated -+ */ -+ @NotNull -+ public PlayerProfile getPlayerProfile() { -+ return profile; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4dcf6242c9acc62d030a94f67b78729ed29f8c85 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java -@@ -0,0 +1,108 @@ -+package com.destroystokyo.paper.event.profile; -+ -+import com.destroystokyo.paper.profile.PlayerProfile; -+import com.destroystokyo.paper.profile.ProfileProperty; -+import com.google.common.collect.ArrayListMultimap; -+import org.bukkit.Bukkit; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import java.util.HashSet; -+import java.util.Set; -+import java.util.UUID; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Allows a plugin to intercept a Profile Lookup for a Profile by name -+ * -+ * At the point of event fire, the UUID and properties are unset. -+ * -+ * If a plugin sets the UUID, and optionally the properties, the API call to look up the profile may be skipped. -+ * -+ * No guarantees are made about thread execution context for this event. If you need to know, check -+ * event.isAsync() -+ */ -+public class PreLookupProfileEvent extends Event { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private final String name; -+ private UUID uuid; -+ @NotNull private Set properties = new HashSet<>(); -+ -+ public PreLookupProfileEvent(@NotNull String name) { -+ super(!Bukkit.isPrimaryThread()); -+ this.name = name; -+ } -+ -+ /** -+ * @return Name of the profile -+ */ -+ @NotNull -+ public String getName() { -+ return name; -+ } -+ -+ /** -+ * If this value is left null by the completion of the event call, then the server will -+ * trigger a call to the Mojang API to look up the UUID (Network Request), and subsequently, fire a -+ * {@link LookupProfileEvent} -+ * -+ * @return The UUID of the profile if it has already been provided by a plugin -+ */ -+ @Nullable -+ public UUID getUUID() { -+ return uuid; -+ } -+ -+ /** -+ * Sets the UUID for this player name. This will skip the initial API call to find the players UUID. -+ * -+ * However, if Profile Properties are needed by the server, you must also set them or else an API call might still be made. -+ * -+ * @param uuid the UUID to set for the profile or null to reset -+ */ -+ public void setUUID(@Nullable UUID uuid) { -+ this.uuid = uuid; -+ } -+ -+ /** -+ * @return The currently pending prepopulated properties. -+ * Any property in this Set will be automatically prefilled on this Profile -+ */ -+ @NotNull -+ public Set getProfileProperties() { -+ return this.properties; -+ } -+ -+ /** -+ * Clears any existing prepopulated properties and uses the supplied properties -+ * Any property in this Set will be automatically prefilled on this Profile -+ * @param properties The properties to add -+ */ -+ public void setProfileProperties(@NotNull Set properties) { -+ this.properties = new HashSet<>(); -+ this.properties.addAll(properties); -+ } -+ -+ /** -+ * Adds any properties currently missing to the prepopulated properties set, replacing any that already were set. -+ * Any property in this Set will be automatically prefilled on this Profile -+ * @param properties The properties to add -+ */ -+ public void addProfileProperties(@NotNull Set properties) { -+ this.properties.addAll(properties); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+} diff --git a/Unmapped-Spigot-API-Patches/0059-Entity-fromMobSpawner.patch b/Unmapped-Spigot-API-Patches/0059-Entity-fromMobSpawner.patch deleted file mode 100644 index 73b4016c92..0000000000 --- a/Unmapped-Spigot-API-Patches/0059-Entity-fromMobSpawner.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 18 Jun 2017 18:17:05 -0500 -Subject: [PATCH] Entity#fromMobSpawner() - - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index fdce246aecac775c3ff4a028c307b09762505258..fdc95c87a6020bdcaee5b0b8ab5a996c0e241b33 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -665,5 +665,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - */ - @Nullable - Location getOrigin(); -+ -+ /** -+ * Returns whether this entity was spawned from a mob spawner. -+ * -+ * @return True if entity spawned from a mob spawner -+ */ -+ boolean fromMobSpawner(); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch b/Unmapped-Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch deleted file mode 100644 index 85814456bf..0000000000 --- a/Unmapped-Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 10 Dec 2016 16:12:48 -0500 -Subject: [PATCH] Improve the Saddle API for Horses - -Not all horses with Saddles have armor. This lets us break up the horses with saddles -and access their saddle state separately from an interface shared with Armor. - -diff --git a/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java b/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..163ffe8ff76ded6265d865901d5110fb6a56950d ---- /dev/null -+++ b/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java -@@ -0,0 +1,21 @@ -+package org.bukkit.inventory; -+ -+import org.jetbrains.annotations.Nullable; -+ -+public interface ArmoredHorseInventory extends AbstractHorseInventory { -+ -+ /** -+ * Gets the item in the horse's armor slot. -+ * -+ * @return the armor item -+ */ -+ @Nullable -+ ItemStack getArmor(); -+ -+ /** -+ * Sets the item in the horse's armor slot. -+ * -+ * @param stack the new item -+ */ -+ void setArmor(@Nullable ItemStack stack); -+} -diff --git a/src/main/java/org/bukkit/inventory/HorseInventory.java b/src/main/java/org/bukkit/inventory/HorseInventory.java -index 608e99c4207405bf9dd88d44ad8e82eefa19e45c..53498debe4cfb80592ef3025270bc8e5df4a5fec 100644 ---- a/src/main/java/org/bukkit/inventory/HorseInventory.java -+++ b/src/main/java/org/bukkit/inventory/HorseInventory.java -@@ -5,20 +5,4 @@ import org.jetbrains.annotations.Nullable; - /** - * An interface to the inventory of a Horse. - */ --public interface HorseInventory extends AbstractHorseInventory { -- -- /** -- * Gets the item in the horse's armor slot. -- * -- * @return the armor item -- */ -- @Nullable -- ItemStack getArmor(); -- -- /** -- * Sets the item in the horse's armor slot. -- * -- * @param stack the new item -- */ -- void setArmor(@Nullable ItemStack stack); --} -+public interface HorseInventory extends AbstractHorseInventory, ArmoredHorseInventory {} -diff --git a/src/main/java/org/bukkit/inventory/LlamaInventory.java b/src/main/java/org/bukkit/inventory/LlamaInventory.java -index 2fa2c9d07ecbafaf2396d913af90f1f4d432b238..5ac1afb8a213fa0fe344db4730ecbc5de6eed445 100644 ---- a/src/main/java/org/bukkit/inventory/LlamaInventory.java -+++ b/src/main/java/org/bukkit/inventory/LlamaInventory.java -@@ -6,7 +6,7 @@ import org.jetbrains.annotations.Nullable; - /** - * An interface to the inventory of a {@link Llama}. - */ --public interface LlamaInventory extends AbstractHorseInventory { -+public interface LlamaInventory extends SaddledHorseInventory { - - /** - * Gets the item in the llama's decor slot. -diff --git a/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java b/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7944f26a3e2a92601c3be0e55c00c39cc16cf177 ---- /dev/null -+++ b/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java -@@ -0,0 +1,3 @@ -+package org.bukkit.inventory; -+ -+public interface SaddledHorseInventory extends AbstractHorseInventory {} diff --git a/Unmapped-Spigot-API-Patches/0061-ensureServerConversions-API.patch b/Unmapped-Spigot-API-Patches/0061-ensureServerConversions-API.patch deleted file mode 100644 index ed64978a06..0000000000 --- a/Unmapped-Spigot-API-Patches/0061-ensureServerConversions-API.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 May 2016 23:55:48 -0400 -Subject: [PATCH] ensureServerConversions API - -This will take a Bukkit ItemStack and run it through any conversions a server process would perform on it, -to ensure it meets latest minecraft expectations. - -diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index 6cc4bad2ecd19f44a680ff03cbfb99d48ea5c337..42551f8aa6666a6144815b619327c6d8f3c3776b 100644 ---- a/src/main/java/org/bukkit/inventory/ItemFactory.java -+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java -@@ -160,5 +160,17 @@ public interface ItemFactory { - */ - @NotNull - net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); -+ -+ /** -+ * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks. -+ * -+ * Use this method to to ensure any desired data conversions are processed. -+ * The input itemstack will not be the same as the returned itemstack. -+ * -+ * @param item The item to process conversions on -+ * @return A potentially Data Converted ItemStack -+ */ -+ @NotNull -+ ItemStack ensureServerConversions(@NotNull ItemStack item); - // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index a15abec467bac70116a6fc21a300d4930b909f15..f9d226962f16821d07ac80f1bf69cb01a5de2654 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -536,7 +536,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - } - } - -- return result; -+ return result.ensureServerConversions(); // Paper - } - - /** -@@ -611,5 +611,18 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public @NotNull net.kyori.adventure.text.Component displayName() { - return Bukkit.getServer().getItemFactory().displayName(this); - } -+ -+ /** -+ * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks. -+ * -+ * Use this method to to ensure any desired data conversions are processed. -+ * The input itemstack will not be the same as the returned itemstack. -+ * -+ * @return A potentially Data Converted ItemStack -+ */ -+ @NotNull -+ public ItemStack ensureServerConversions() { -+ return Bukkit.getServer().getItemFactory().ensureServerConversions(this); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch b/Unmapped-Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch deleted file mode 100644 index e4dde4f260..0000000000 --- a/Unmapped-Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 May 2016 23:55:48 -0400 -Subject: [PATCH] Add getI18NDisplayName API - -Gets the Display name as seen in the Client. -Currently the server only supports the English language. To override this, -You must replace the language file embedded in the server jar. - -diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index 44a858490f4db37f979fd487ed7a5b2b8b7f1a3f..3fd56a95de7d4cbeaf5d8554fbc7127a627cb977 100644 ---- a/src/main/java/org/bukkit/inventory/ItemFactory.java -+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java -@@ -172,5 +172,16 @@ public interface ItemFactory { - */ - @NotNull - ItemStack ensureServerConversions(@NotNull ItemStack item); -+ -+ /** -+ * Gets the Display name as seen in the Client. -+ * Currently the server only supports the English language. To override this, -+ * You must replace the language file embedded in the server jar. -+ * -+ * @param item Item to return Display name of -+ * @return Display name of Item -+ */ -+ @Nullable -+ String getI18NDisplayName(@Nullable ItemStack item); - // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 47d8611221967d32b654ddac0fbf0e405ef62352..82bd3e6701dbd7df9f0f8c3801c5ae1baba4eec5 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -624,5 +624,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public ItemStack ensureServerConversions() { - return Bukkit.getServer().getItemFactory().ensureServerConversions(this); - } -+ -+ /** -+ * Gets the Display name as seen in the Client. -+ * Currently the server only supports the English language. To override this, -+ * You must replace the language file embedded in the server jar. -+ * -+ * @return Display name of Item -+ */ -+ @Nullable -+ public String getI18NDisplayName() { -+ return Bukkit.getServer().getItemFactory().getI18NDisplayName(this); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch b/Unmapped-Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch deleted file mode 100644 index ff996377f4..0000000000 --- a/Unmapped-Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 3 Jul 2017 18:11:34 -0500 -Subject: [PATCH] ProfileWhitelistVerifyEvent - -Fires when the server is validating if a player is whitelisted. - -Allows you to do dynamic whitelisting and change of kick message - -diff --git a/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8a259ab49ea79673b6da9e4e2aaecec67469994e ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java -@@ -0,0 +1,142 @@ -+/* -+ * Copyright (c) 2017 - Daniel Ennis (Aikar) - MIT License -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+package com.destroystokyo.paper.event.profile; -+ -+import com.destroystokyo.paper.profile.PlayerProfile; -+import net.kyori.adventure.text.Component; -+import org.bukkit.Bukkit; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Fires when the server needs to verify if a player is whitelisted. -+ * -+ * Plugins may override/control the servers whitelist with this event, -+ * and dynamically change the kick message. -+ */ -+public class ProfileWhitelistVerifyEvent extends Event { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private final PlayerProfile profile; -+ private final boolean whitelistEnabled; -+ private boolean whitelisted; -+ private final boolean isOp; -+ @Nullable private Component kickMessage; -+ -+ @Deprecated -+ public ProfileWhitelistVerifyEvent(@NotNull final PlayerProfile profile, boolean whitelistEnabled, boolean whitelisted, boolean isOp, @Nullable String kickMessage) { -+ this(profile, whitelistEnabled, whitelisted, isOp, kickMessage == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickMessage)); -+ } -+ -+ public ProfileWhitelistVerifyEvent(@NotNull final PlayerProfile profile, boolean whitelistEnabled, boolean whitelisted, boolean isOp, @Nullable Component kickMessage) { -+ this.profile = profile; -+ this.whitelistEnabled = whitelistEnabled; -+ this.whitelisted = whitelisted; -+ this.isOp = isOp; -+ this.kickMessage = kickMessage; -+ } -+ -+ /** -+ * @return the currently planned message to send to the user if they are not whitelisted -+ * @deprecated use {@link #kickMessage()} -+ */ -+ @Deprecated -+ @Nullable -+ public String getKickMessage() { -+ return this.kickMessage == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().serialize(kickMessage); -+ } -+ -+ /** -+ * @param kickMessage The message to send to the player on kick if not whitelisted. May set to null to use the server configured default -+ * @deprecated Use {@link #kickMessage(Component)} -+ */ -+ @Deprecated -+ public void setKickMessage(@Nullable String kickMessage) { -+ this.kickMessage(kickMessage == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickMessage)); -+ } -+ -+ /** -+ * @return the currently planned message to send to the user if they are not whitelisted -+ */ -+ @Nullable -+ public Component kickMessage() { -+ return this.kickMessage; -+ } -+ -+ /** -+ * @param kickMessage The message to send to the player on kick if not whitelisted. May set to null to use the server configured default -+ */ -+ public void kickMessage(@Nullable Component kickMessage) { -+ this.kickMessage = kickMessage; -+ } -+ -+ /** -+ * @return The profile of the player trying to connect -+ */ -+ @NotNull -+ public PlayerProfile getPlayerProfile() { -+ return profile; -+ } -+ -+ /** -+ * @return Whether the player is whitelisted to play on this server (whitelist may be off is why its true) -+ */ -+ public boolean isWhitelisted() { -+ return whitelisted; -+ } -+ -+ /** -+ * Changes the players whitelisted state. false will deny the login -+ * @param whitelisted The new whitelisted state -+ */ -+ public void setWhitelisted(boolean whitelisted) { -+ this.whitelisted = whitelisted; -+ } -+ -+ /** -+ * @return if the player obtained whitelist status by having op -+ */ -+ public boolean isOp() { -+ return isOp; -+ } -+ -+ /** -+ * @return if the server even has whitelist on -+ */ -+ public boolean isWhitelistEnabled() { -+ return whitelistEnabled; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch b/Unmapped-Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch deleted file mode 100644 index ec1fc9814a..0000000000 --- a/Unmapped-Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 02:08:55 -0500 -Subject: [PATCH] Make /plugins list alphabetical - - -diff --git a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java -index bcb576a4271b1ec7b1cfe6f83cf161b7d89ed2e5..4de959bbd1270d7d6ea8e5e69521bcca6abe2138 100644 ---- a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java -+++ b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java -@@ -3,6 +3,9 @@ package org.bukkit.command.defaults; - import java.util.Arrays; - import java.util.Collections; - import java.util.List; -+import java.util.Map; -+import java.util.TreeMap; -+ - import org.bukkit.Bukkit; - import org.bukkit.ChatColor; - import org.bukkit.command.CommandSender; -@@ -34,15 +37,22 @@ public class PluginsCommand extends BukkitCommand { - - @NotNull - private String getPluginList() { -- StringBuilder pluginList = new StringBuilder(); -- Plugin[] plugins = Bukkit.getPluginManager().getPlugins(); -+ // Paper start -+ TreeMap plugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); -+ -+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { -+ plugins.put(plugin.getDescription().getName(), plugin); -+ } - -- for (Plugin plugin : plugins) { -+ StringBuilder pluginList = new StringBuilder(); -+ for (Map.Entry entry : plugins.entrySet()) { - if (pluginList.length() > 0) { - pluginList.append(ChatColor.WHITE); - pluginList.append(", "); - } - -+ Plugin plugin = entry.getValue(); -+ - pluginList.append(plugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED); - pluginList.append(plugin.getDescription().getName()); - -@@ -51,6 +61,8 @@ public class PluginsCommand extends BukkitCommand { - } - } - -- return "(" + plugins.length + "): " + pluginList.toString(); -+ return "(" + plugins.size() + "): " + pluginList.toString(); -+ // Paper end - } -+ - } diff --git a/Unmapped-Spigot-API-Patches/0065-LivingEntity-setKiller.patch b/Unmapped-Spigot-API-Patches/0065-LivingEntity-setKiller.patch deleted file mode 100644 index b7b93870eb..0000000000 --- a/Unmapped-Spigot-API-Patches/0065-LivingEntity-setKiller.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:49:43 -0500 -Subject: [PATCH] LivingEntity#setKiller - - -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 45e9f585c3e522ecf94a6bc42cdc190e1a191a5c..33fffda7c8b05cde3c95623937e7eb6c8b628ec6 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -279,6 +279,15 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - @Nullable - public Player getKiller(); - -+ // Paper start -+ /** -+ * Sets the player identified as the killer of the living entity. -+ * -+ * @param killer player -+ */ -+ public void setKiller(@Nullable Player killer); -+ // Paper end -+ - /** - * Adds the given {@link PotionEffect} to the living entity. - * diff --git a/Unmapped-Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch b/Unmapped-Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch deleted file mode 100644 index a1273c87c6..0000000000 --- a/Unmapped-Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Thu, 21 Sep 2017 16:14:13 +0200 -Subject: [PATCH] Handle plugin prefixes in implementation logging - configuration - -Currently, plugin prefixes are prepended to the log message in -the PluginLogger before passing the message to the underlying -logging framework. This is bad design because they need to be -stripped manually when using custom appenders to log messages -in a different format. - -Additionally, it makes integration of alternative logging APIs hard -because all logging must go through the PluginLogger. Avoid using -PluginLogger and create a regular logger using the plugin name. -The implementation should handle plugin prefixes by displaying -logger names when appropriate. - -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -index 2231900549607a0917dd04e8b433c027b846cef9..bb2e55e97bf887a28cac7d4f9a0a23960d22cf56 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -@@ -42,7 +42,7 @@ public abstract class JavaPlugin extends PluginBase { - private boolean naggable = true; - private FileConfiguration newConfig = null; - private File configFile = null; -- private PluginLogger logger = null; -+ private Logger logger = null; // Paper - PluginLogger -> Logger - - public JavaPlugin() { - final ClassLoader classLoader = this.getClass().getClassLoader(); -@@ -276,7 +276,8 @@ public abstract class JavaPlugin extends PluginBase { - this.dataFolder = dataFolder; - this.classLoader = classLoader; - this.configFile = new File(dataFolder, "config.yml"); -- this.logger = new PluginLogger(this); -+ // Paper - Handle plugin prefix in implementation -+ this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); - } - - /** diff --git a/Unmapped-Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch b/Unmapped-Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch deleted file mode 100644 index 58225ea7be..0000000000 --- a/Unmapped-Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Thu, 21 Sep 2017 16:33:12 +0200 -Subject: [PATCH] Allow plugins to use SLF4J for logging - -SLF4J is a commonly used abstraction for various logging frameworks -such as java.util.logging (JUL) or Log4j. Currently, plugins are -required to do all their logging using the provided JUL logger. -This is annoying for plugins that target multiple platforms or when -using libraries that log messages using SLF4J. - -Expose SLF4J as optional logging API for plugins, so they can use -it without having to shade it in the plugin and going through -several layers of logging abstraction. - -diff --git a/pom.xml b/pom.xml -index 2c757ffb2253748c6a81f9b373290108209b6ff2..8cf6e1f78d4c1ae388bb478700d5dceaab65c4e7 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -144,6 +144,13 @@ - 21.0.1 - provided - -+ -+ -+ org.slf4j -+ slf4j-api -+ 1.7.25 -+ compile -+ - - - junit -diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java -index febfec6efafd76bb59b4b43aa223af16f73339b4..79890c68f1ad31f951dfdbd9a16dac500ec58c40 100644 ---- a/src/main/java/org/bukkit/plugin/Plugin.java -+++ b/src/main/java/org/bukkit/plugin/Plugin.java -@@ -166,6 +166,13 @@ public interface Plugin extends TabExecutor { - @NotNull - public Logger getLogger(); - -+ // Paper start - Add SLF4J logger -+ @NotNull -+ default org.slf4j.Logger getSLF4JLogger() { -+ return org.slf4j.LoggerFactory.getLogger(getLogger().getName()); -+ } -+ // Paper end -+ - /** - * Returns the name of the plugin. - *

    diff --git a/Unmapped-Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/Unmapped-Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch deleted file mode 100644 index 47b6099ab7..0000000000 --- a/Unmapped-Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Thu, 21 Sep 2017 19:41:20 +0200 -Subject: [PATCH] Add workaround for plugins modifying the parent of the plugin - logger - -Essentials uses a custom logger name ("Essentials") instead of the -plugin logger. Log messages are redirected to the plugin logger by -setting the parent of the "Essentials" logger to the plugin logger. - -With our changes, the plugin logger is now also called "Essentials", -resulting in an infinite loop. Make sure plugins can't change the -parent of the plugin logger to avoid this. - -diff --git a/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java -new file mode 100644 -index 0000000000000000000000000000000000000000..76f2cb9cd99cad2a9484eab2becd8c36f1dd91b3 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.utils; -+ -+import org.bukkit.plugin.PluginDescriptionFile; -+ -+import java.util.logging.Level; -+import java.util.logging.LogManager; -+import java.util.logging.Logger; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Prevents plugins (e.g. Essentials) from changing the parent of the plugin logger. -+ */ -+public class PaperPluginLogger extends Logger { -+ -+ @NotNull -+ public static Logger getLogger(@NotNull PluginDescriptionFile description) { -+ Logger logger = new PaperPluginLogger(description); -+ if (!LogManager.getLogManager().addLogger(logger)) { -+ // Disable this if it's going to happen across reloads anyways... -+ //logger.log(Level.WARNING, "Could not insert plugin logger - one was already found: {}", LogManager.getLogManager().getLogger(this.getName())); -+ logger = LogManager.getLogManager().getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); -+ } -+ -+ return logger; -+ } -+ -+ private PaperPluginLogger(@NotNull PluginDescriptionFile description) { -+ super(description.getPrefix() != null ? description.getPrefix() : description.getName(), null); -+ } -+ -+ @Override -+ public void setParent(@NotNull Logger parent) { -+ if (getParent() != null) { -+ warning("Ignoring attempt to change parent of plugin logger"); -+ } else { -+ this.log(Level.FINE, "Setting plugin logger parent to {0}", parent); -+ super.setParent(parent); -+ } -+ } -+ -+} -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -index bb2e55e97bf887a28cac7d4f9a0a23960d22cf56..04fa3991f6ce4e9dad804f28fc6c947695857089 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -@@ -42,7 +42,7 @@ public abstract class JavaPlugin extends PluginBase { - private boolean naggable = true; - private FileConfiguration newConfig = null; - private File configFile = null; -- private Logger logger = null; // Paper - PluginLogger -> Logger -+ Logger logger = null; // Paper - PluginLogger -> Logger, package-private - - public JavaPlugin() { - final ClassLoader classLoader = this.getClass().getClassLoader(); -@@ -276,8 +276,11 @@ public abstract class JavaPlugin extends PluginBase { - this.dataFolder = dataFolder; - this.classLoader = classLoader; - this.configFile = new File(dataFolder, "config.yml"); -- // Paper - Handle plugin prefix in implementation -- this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); -+ // Paper start -+ if (this.logger == null) { -+ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(this.description); -+ } -+ // Paper end - } - - /** -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 13100c688bfccb826b3072aaa92901f8634cf9ab..b9766b9b47547c400ed075f1635bb1461cb5e860 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -44,6 +44,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - private JavaPlugin pluginInit; - private IllegalStateException pluginState; - private final Set seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>()); -+ private java.util.logging.Logger logger; // Paper - add field - - static { - ClassLoader.registerAsParallelCapable(); -@@ -62,6 +63,8 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - this.url = file.toURI().toURL(); - this.libraryLoader = libraryLoader; - -+ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(description); // Paper - Register logger early -+ - try { - Class jarClass; - try { -@@ -222,6 +225,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - pluginState = new IllegalStateException("Initial initialization"); - this.pluginInit = javaPlugin; - -+ javaPlugin.logger = this.logger; // Paper - set logger - javaPlugin.init(loader, loader.server, description, dataFolder, file, this); - } - } diff --git a/Unmapped-Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch b/Unmapped-Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch deleted file mode 100644 index 18f2c35b4d..0000000000 --- a/Unmapped-Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 28 Sep 2017 17:21:32 -0400 -Subject: [PATCH] Add PlayerJumpEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..289a0d784a3c74caf8a7231b4dd166096b1849a1 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java -@@ -0,0 +1,106 @@ -+package com.destroystokyo.paper.event.player; -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.Location; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when the server detects the player is jumping. -+ *

    -+ * Added to avoid the overhead and special case logic that many plugins use -+ * when checking for jumps via PlayerMoveEvent, this event is fired whenever -+ * the server detects that the player is jumping. -+ */ -+public class PlayerJumpEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancel = false; -+ @NotNull private Location from; -+ @NotNull private Location to; -+ -+ public PlayerJumpEvent(@NotNull final Player player, @NotNull final Location from, @NotNull final Location to) { -+ super(player); -+ this.from = from; -+ this.to = to; -+ } -+ -+ /** -+ * Gets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ *

    -+ * If a jump event is cancelled, the player will be moved or -+ * teleported back to the Location as defined by getFrom(). This will not -+ * fire an event -+ * -+ * @return true if this event is cancelled -+ */ -+ public boolean isCancelled() { -+ return cancel; -+ } -+ -+ /** -+ * Sets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ *

    -+ * If a jump event is cancelled, the player will be moved or -+ * teleported back to the Location as defined by getFrom(). This will not -+ * fire an event -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ public void setCancelled(boolean cancel) { -+ this.cancel = cancel; -+ } -+ -+ /** -+ * Gets the location this player jumped from -+ * -+ * @return Location the player jumped from -+ */ -+ @NotNull -+ public Location getFrom() { -+ return from; -+ } -+ -+ /** -+ * Sets the location to mark as where the player jumped from -+ * -+ * @param from New location to mark as the players previous location -+ */ -+ public void setFrom(@NotNull Location from) { -+ validateLocation(from); -+ this.from = from; -+ } -+ -+ /** -+ * Gets the location this player jumped to -+ * -+ * This information is based on what the client sends, it typically -+ * has little relation to the arc of the jump at any given point. -+ * -+ * @return Location the player jumped to -+ */ -+ @NotNull -+ public Location getTo() { -+ return to; -+ } -+ -+ private void validateLocation(Location loc) { -+ Preconditions.checkArgument(loc != null, "Cannot use null location!"); -+ Preconditions.checkArgument(loc.getWorld() != null, "Cannot use location with null world!"); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch b/Unmapped-Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch deleted file mode 100644 index ff8f83ac14..0000000000 --- a/Unmapped-Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Tue, 10 Oct 2017 18:44:42 +0200 -Subject: [PATCH] Expose client protocol version and virtual host - -Add a NetworkClient interface that provides access to: - - The socket address - - The protocol version - - The virtual host (the hostname/port the client used to connect - to the server) - -diff --git a/src/main/java/com/destroystokyo/paper/network/NetworkClient.java b/src/main/java/com/destroystokyo/paper/network/NetworkClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7b2af1bd72dfbcf4e962a982940fc49b851aa04f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/NetworkClient.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.network; -+ -+import java.net.InetSocketAddress; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Represents a client connected to the server. -+ */ -+public interface NetworkClient { -+ -+ /** -+ * Returns the socket address of the client. -+ * -+ * @return The client's socket address -+ */ -+ @NotNull -+ InetSocketAddress getAddress(); -+ -+ /** -+ * Returns the protocol version of the client. -+ * -+ * @return The client's protocol version, or {@code -1} if unknown -+ * @see List of protocol -+ * version numbers -+ */ -+ int getProtocolVersion(); -+ -+ /** -+ * Returns the virtual host the client is connected to. -+ * -+ *

    The virtual host refers to the hostname/port the client used to -+ * connect to the server.

    -+ * -+ * @return The client's virtual host, or {@code null} if unknown -+ */ -+ @Nullable -+ InetSocketAddress getVirtualHost(); -+ -+} -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 9cf7adf244335ac7dccbdf11f605a8c6910f7414..04f1a6513711dde8576c9b5c2b04619c56b48d8a 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a player, connected or not - */ --public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified { // Paper -+public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, com.destroystokyo.paper.network.NetworkClient { // Paper - - // Paper start - @Override diff --git a/Unmapped-Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch b/Unmapped-Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch deleted file mode 100644 index 4e9d795db3..0000000000 --- a/Unmapped-Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: pkt77 -Date: Fri, 10 Nov 2017 23:45:59 -0500 -Subject: [PATCH] Add PlayerArmorChangeEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e406ce639a2e88b78f82f25e71678a669d0a958b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java -@@ -0,0 +1,137 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.Material; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.ItemStack; -+ -+import java.util.Arrays; -+import java.util.Collections; -+import java.util.HashSet; -+import java.util.Set; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import static org.bukkit.Material.*; -+ -+/** -+ * Called when the player themselves change their armor items -+ *

    -+ * Not currently called for environmental factors though it MAY BE IN THE FUTURE -+ */ -+public class PlayerArmorChangeEvent extends PlayerEvent { -+ private static final HandlerList HANDLERS = new HandlerList(); -+ -+ @NotNull private final SlotType slotType; -+ @Nullable private final ItemStack oldItem; -+ @Nullable private final ItemStack newItem; -+ -+ public PlayerArmorChangeEvent(@NotNull Player player, @NotNull SlotType slotType, @Nullable ItemStack oldItem, @Nullable ItemStack newItem) { -+ super(player); -+ this.slotType = slotType; -+ this.oldItem = oldItem; -+ this.newItem = newItem; -+ } -+ -+ /** -+ * Gets the type of slot being altered. -+ * -+ * @return type of slot being altered -+ */ -+ @NotNull -+ public SlotType getSlotType() { -+ return this.slotType; -+ } -+ -+ /** -+ * Gets the existing item that's being replaced -+ * -+ * @return old item -+ */ -+ @Nullable -+ public ItemStack getOldItem() { -+ return this.oldItem; -+ } -+ -+ /** -+ * Gets the new item that's replacing the old -+ * -+ * @return new item -+ */ -+ @Nullable -+ public ItemStack getNewItem() { -+ return this.newItem; -+ } -+ -+ @Override -+ public String toString() { -+ return "ArmorChangeEvent{" + "player=" + player + ", slotType=" + slotType + ", oldItem=" + oldItem + ", newItem=" + newItem + '}'; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLERS; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLERS; -+ } -+ -+ public enum SlotType { -+ HEAD(NETHERITE_HELMET, DIAMOND_HELMET, GOLDEN_HELMET, IRON_HELMET, CHAINMAIL_HELMET, LEATHER_HELMET, CARVED_PUMPKIN, PLAYER_HEAD, SKELETON_SKULL, ZOMBIE_HEAD, CREEPER_HEAD, WITHER_SKELETON_SKULL, TURTLE_HELMET), -+ CHEST(NETHERITE_CHESTPLATE, DIAMOND_CHESTPLATE, GOLDEN_CHESTPLATE, IRON_CHESTPLATE, CHAINMAIL_CHESTPLATE, LEATHER_CHESTPLATE, ELYTRA), -+ LEGS(NETHERITE_LEGGINGS, DIAMOND_LEGGINGS, GOLDEN_LEGGINGS, IRON_LEGGINGS, CHAINMAIL_LEGGINGS, LEATHER_LEGGINGS), -+ FEET(NETHERITE_BOOTS, DIAMOND_BOOTS, GOLDEN_BOOTS, IRON_BOOTS, CHAINMAIL_BOOTS, LEATHER_BOOTS); -+ -+ private final Set mutableTypes = new HashSet<>(); -+ private Set immutableTypes; -+ -+ SlotType(Material... types) { -+ this.mutableTypes.addAll(Arrays.asList(types)); -+ } -+ -+ /** -+ * Gets an immutable set of all allowed material types that can be placed in an -+ * armor slot. -+ * -+ * @return immutable set of material types -+ */ -+ @NotNull -+ public Set getTypes() { -+ if (immutableTypes == null) { -+ immutableTypes = Collections.unmodifiableSet(mutableTypes); -+ } -+ -+ return immutableTypes; -+ } -+ -+ /** -+ * Gets the type of slot via the specified material -+ * -+ * @param material material to get slot by -+ * @return slot type the material will go in, or null if it won't -+ */ -+ @Nullable -+ public static SlotType getByMaterial(@NotNull Material material) { -+ for (SlotType slotType : values()) { -+ if (slotType.getTypes().contains(material)) { -+ return slotType; -+ } -+ } -+ return null; -+ } -+ -+ /** -+ * Gets whether or not this material can be equipped to a slot -+ * -+ * @param material material to check -+ * @return whether or not this material can be equipped -+ */ -+ public static boolean isEquipable(@NotNull Material material) { -+ return getByMaterial(material) != null; -+ } -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch b/Unmapped-Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch deleted file mode 100644 index 9d4f264793..0000000000 --- a/Unmapped-Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 6 Nov 2017 21:10:01 -0500 -Subject: [PATCH] API to get a BlockState without a snapshot - -This allows you to get a BlockState without creating a snapshot, operating -on the real tile entity. - -This is useful for where performance is needed - -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 0cfad6f84eda6f7bfa1fae041341ccb1021b157d..e89c8079625525667f496c06207da655fe43d749 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -269,6 +269,16 @@ public interface Block extends Metadatable { - @NotNull - BlockState getState(); - -+ // Paper start -+ /** -+ * @see #getState() optionally disables use of snapshot, to operate on real block data -+ * @param useSnapshot if this block is a TE, should we create a fully copy of the TileEntity -+ * @return BlockState with the current state of this block -+ */ -+ @NotNull -+ BlockState getState(boolean useSnapshot); -+ // Paper end -+ - /** - * Returns the biome that this block resides in - * diff --git a/Unmapped-Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch b/Unmapped-Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch deleted file mode 100644 index e86dd9b401..0000000000 --- a/Unmapped-Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch +++ /dev/null @@ -1,266 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 26 Nov 2017 13:17:09 -0500 -Subject: [PATCH] AsyncTabCompleteEvent - -Let plugins be able to control tab completion of commands and chat async. - -This will be useful for frameworks like ACF so we can define async safe completion handlers, -and avoid going to main for tab completions. - -Especially useful if you need to query a database in order to obtain the results for tab -completion, such as offline players. - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..619ed37169c126a8c75d02699a04728bac49d10d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java -@@ -0,0 +1,177 @@ -+/* -+ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+package com.destroystokyo.paper.event.server; -+ -+import com.google.common.collect.ImmutableList; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Location; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import java.util.ArrayList; -+import java.util.List; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Allows plugins to compute tab completion results asynchronously. If this event provides completions, then the standard synchronous process will not be fired to populate the results. However, the synchronous TabCompleteEvent will fire with the Async results. -+ * -+ * Only 1 process will be allowed to provide completions, the Async Event, or the standard process. -+ */ -+public class AsyncTabCompleteEvent extends Event implements Cancellable { -+ @NotNull private final CommandSender sender; -+ @NotNull private final String buffer; -+ private final boolean isCommand; -+ @Nullable -+ private final Location loc; -+ @NotNull private List completions; -+ private boolean cancelled; -+ private boolean handled = false; -+ private boolean fireSyncHandler = true; -+ -+ public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull List completions, @NotNull String buffer, boolean isCommand, @Nullable Location loc) { -+ super(true); -+ this.sender = sender; -+ this.completions = completions; -+ this.buffer = buffer; -+ this.isCommand = isCommand; -+ this.loc = loc; -+ } -+ -+ /** -+ * Get the sender completing this command. -+ * -+ * @return the {@link CommandSender} instance -+ */ -+ @NotNull -+ public CommandSender getSender() { -+ return sender; -+ } -+ -+ /** -+ * The list of completions which will be offered to the sender, in order. -+ * This list is mutable and reflects what will be offered. -+ * -+ * If this collection is not empty after the event is fired, then -+ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} -+ * or current player names will not be called. -+ * -+ * @return a list of offered completions -+ */ -+ @NotNull -+ public List getCompletions() { -+ return completions; -+ } -+ -+ /** -+ * Set the completions offered, overriding any already set. -+ * If this collection is not empty after the event is fired, then -+ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} -+ * or current player names will not be called. -+ * -+ * The passed collection will be cloned to a new List. You must call {{@link #getCompletions()}} to mutate from here -+ * -+ * @param completions the new completions -+ */ -+ public void setCompletions(@NotNull List completions) { -+ Validate.notNull(completions); -+ this.completions = new ArrayList<>(completions); -+ } -+ -+ /** -+ * Return the entire buffer which formed the basis of this completion. -+ * -+ * @return command buffer, as entered -+ */ -+ @NotNull -+ public String getBuffer() { -+ return buffer; -+ } -+ -+ /** -+ * @return True if it is a command being tab completed, false if it is a chat message. -+ */ -+ public boolean isCommand() { -+ return isCommand; -+ } -+ -+ /** -+ * @return The position looked at by the sender, or null if none -+ */ -+ @Nullable -+ public Location getLocation() { -+ return loc; -+ } -+ -+ /** -+ * If true, the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} -+ * or current player names will not be called. -+ * -+ * @return Is completions considered handled. Always true if completions is not empty. -+ */ -+ public boolean isHandled() { -+ return !completions.isEmpty() || handled; -+ } -+ -+ /** -+ * Sets whether or not to consider the completion request handled. -+ * If true, the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} -+ * or current player names will not be called. -+ * -+ * @param handled if this completion should be marked as being handled -+ */ -+ public void setHandled(boolean handled) { -+ this.handled = handled; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Will provide no completions, and will not fire the synchronous process -+ * @param cancelled true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java -index d1a9956a1573dab54c5ff2e5d67ca86cfe1dc01a..f96c4ba53ab41ea66d4f9a4d54eeabb63f992b58 100644 ---- a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java -+++ b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.server; - -+import java.util.ArrayList; - import java.util.List; - import org.apache.commons.lang.Validate; - import org.bukkit.command.CommandSender; -@@ -8,6 +9,7 @@ import org.bukkit.event.Event; - import org.bukkit.event.HandlerList; - import org.bukkit.event.player.PlayerCommandSendEvent; - import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; - - /** - * Called when a {@link CommandSender} of any description (ie: player or -@@ -29,6 +31,13 @@ public class TabCompleteEvent extends Event implements Cancellable { - private boolean cancelled; - - public TabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, @NotNull List completions) { -+ // Paper start -+ this(sender, buffer, completions, sender instanceof org.bukkit.command.ConsoleCommandSender || buffer.startsWith("/"), null); -+ } -+ public TabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, @NotNull List completions, boolean isCommand, @Nullable org.bukkit.Location location) { -+ this.isCommand = isCommand; -+ this.loc = location; -+ // Paper end - Validate.notNull(sender, "sender"); - Validate.notNull(buffer, "buffer"); - Validate.notNull(completions, "completions"); -@@ -69,14 +78,35 @@ public class TabCompleteEvent extends Event implements Cancellable { - return completions; - } - -+ // Paper start -+ private final boolean isCommand; -+ private final org.bukkit.Location loc; -+ /** -+ * @return True if it is a command being tab completed, false if it is a chat message. -+ */ -+ public boolean isCommand() { -+ return isCommand; -+ } -+ -+ /** -+ * @return The position looked at by the sender, or null if none -+ */ -+ @Nullable -+ public org.bukkit.Location getLocation() { -+ return loc; -+ } -+ // Paper end -+ - /** - * Set the completions offered, overriding any already set. - * -+ * The passed collection will be cloned to a new List. You must call {{@link #getCompletions()}} to mutate from here -+ * - * @param completions the new completions - */ - public void setCompletions(@NotNull List completions) { - Validate.notNull(completions); -- this.completions = completions; -+ this.completions = new ArrayList<>(completions); // Paper - } - - @Override diff --git a/Unmapped-Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch b/Unmapped-Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch deleted file mode 100644 index 2b6c78a2c4..0000000000 --- a/Unmapped-Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 9 Dec 2017 12:40:25 -0500 -Subject: [PATCH] Display warning on deprecated recipe API - -Any plugin still using this API will result in the server saving an inconsistent UUID to player data files, -which then triggers warnings such as "Tried to load unrecognized recipe: bukkit:9e5b92f5-e549-4f47-b0a8-9f89390ed77b removed now." -on the players login. - -Plugin authors need to define a key to keep it consistent between server restarts. - -diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -index d74b3114f535e1e5e36ae007f1fe0522916a0362..d742c4058ba9aed4fbe1591fd755a06608b06e98 100644 ---- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java -+++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -@@ -25,6 +25,7 @@ public class ShapedRecipe implements Recipe, Keyed { - public ShapedRecipe(@NotNull ItemStack result) { - Preconditions.checkArgument(result.getType() != Material.AIR, "Recipe must have non-AIR result."); - this.key = NamespacedKey.randomKey(); -+ new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace(); - this.output = new ItemStack(result); - } - -diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java -index 68447fb8c12356e779b96ec98c54119045046751..84062dd719cb8a6142dc8c806777cb208c6b42b2 100644 ---- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java -+++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java -@@ -26,6 +26,7 @@ public class ShapelessRecipe implements Recipe, Keyed { - public ShapelessRecipe(@NotNull ItemStack result) { - Preconditions.checkArgument(result.getType() != Material.AIR, "Recipe must have non-AIR result."); - this.key = NamespacedKey.randomKey(); -+ new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace(); - this.output = new ItemStack(result); - } - diff --git a/Unmapped-Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch b/Unmapped-Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch deleted file mode 100644 index 906a8ec7c3..0000000000 --- a/Unmapped-Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:00:41 -0500 -Subject: [PATCH] PlayerPickupExperienceEvent - -Allows plugins to cancel a player picking up an experience orb - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f7beb22d5105157940b39efe594ace9d4cb153f5 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.ExperienceOrb; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a player is attempting to pick up an experience orb -+ */ -+public class PlayerPickupExperienceEvent extends PlayerEvent implements Cancellable { -+ @NotNull private final ExperienceOrb experienceOrb; -+ -+ public PlayerPickupExperienceEvent(@NotNull Player player, @NotNull ExperienceOrb experienceOrb) { -+ super(player); -+ this.experienceOrb = experienceOrb; -+ } -+ -+ /** -+ * @return Returns the Orb that the player is picking up -+ */ -+ @NotNull -+ public ExperienceOrb getExperienceOrb() { -+ return experienceOrb; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * If true, Cancels picking up the experience orb, leaving it in the world -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch b/Unmapped-Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch deleted file mode 100644 index 3a4722a776..0000000000 --- a/Unmapped-Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:56:24 -0500 -Subject: [PATCH] ExperienceOrbMergeEvent - -Fired when the server is about to merge 2 experience orbs -Plugins can cancel this if they want to ensure experience orbs do not lose important -metadata such as spawn reason, or conditionally move data from source to target. - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0ce3e397716c28c30ed05e153babd0bfb9dd354a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java -@@ -0,0 +1,87 @@ -+/* -+ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.ExperienceOrb; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired anytime the server is about to merge 2 experience orbs into one -+ */ -+public class ExperienceOrbMergeEvent extends EntityEvent implements Cancellable { -+ @NotNull private final ExperienceOrb mergeTarget; -+ @NotNull private final ExperienceOrb mergeSource; -+ -+ public ExperienceOrbMergeEvent(@NotNull ExperienceOrb mergeTarget, @NotNull ExperienceOrb mergeSource) { -+ super(mergeTarget); -+ this.mergeTarget = mergeTarget; -+ this.mergeSource = mergeSource; -+ } -+ -+ /** -+ * @return The orb that will absorb the other experience orb -+ */ -+ @NotNull -+ public ExperienceOrb getMergeTarget() { -+ return mergeTarget; -+ } -+ -+ /** -+ * @return The orb that is subject to being removed and merged into the target orb -+ */ -+ @NotNull -+ public ExperienceOrb getMergeSource() { -+ return mergeSource; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * @param cancel true if you wish to cancel this event, and prevent the orbs from merging -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch b/Unmapped-Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch deleted file mode 100644 index a225f3dedc..0000000000 --- a/Unmapped-Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 20 Dec 2017 17:38:07 -0500 -Subject: [PATCH] Ability to apply mending to XP API - -This allows plugins that give players the ability to apply the experience -points to the Item Mending formula, which will repair an item instead -of giving the player experience points. - -Both an API To standalone mend, and apply mending logic to .giveExp has been added. - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 21bed0d8075335538374fadfdf1cb868e4eebe80..9d1ad67b7d220ab425ac9bf6b1c8d8fb8d5f416c 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -892,12 +892,33 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - public void resetPlayerWeather(); - -+ // Paper start -+ /** -+ * Gives the player the amount of experience specified. -+ * -+ * @param amount Exp amount to give -+ */ -+ public default void giveExp(int amount) { -+ giveExp(amount, false); -+ } - /** - * Gives the player the amount of experience specified. - * - * @param amount Exp amount to give -+ * @param applyMending Mend players items with mending, with same behavior as picking up orbs. calls {@link #applyMending(int)} - */ -- public void giveExp(int amount); -+ public void giveExp(int amount, boolean applyMending); -+ -+ /** -+ * Applies the mending effect to any items just as picking up an orb would. -+ * -+ * Can also be called with {@link #giveExp(int, boolean)} by passing true to applyMending -+ * -+ * @param amount Exp to apply -+ * @return the remaining experience -+ */ -+ public int applyMending(int amount); -+ // Paper end - - /** - * Gives the player the amount of experience levels specified. Levels can diff --git a/Unmapped-Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch b/Unmapped-Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch deleted file mode 100644 index 0090330de9..0000000000 --- a/Unmapped-Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 16:59:43 -0500 -Subject: [PATCH] PreCreatureSpawnEvent - -Adds an event to fire before an Entity is created, so that plugins that need to cancel -CreatureSpawnEvent can do so from this event instead. - -Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste -as it's done after the Entity object has been fully created. - -Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event -instead and save a lot of server resources. - -See: https://github.com/PaperMC/Paper/issues/917 - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3ad231aa3206c8cfd5ec995249584cebab5d11f3 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java -@@ -0,0 +1,105 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.Location; -+import org.bukkit.entity.EntityType; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.CreatureSpawnEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * WARNING: This event only fires for a limited number of cases, and not for every case that CreatureSpawnEvent does. -+ * -+ * You should still listen to CreatureSpawnEvent as a backup, and only use this event as an "enhancement". -+ * The intent of this event is to improve server performance, so it fires even if the spawning might fail later, for -+ * example when the entity would be unable to spawn due to limited space or lighting. -+ * -+ * Currently: NATURAL and SPAWNER based reasons. Please submit a Pull Request for future additions. -+ * Also, Plugins that replace Entity Registrations with their own custom entities might not fire this event. -+ */ -+public class PreCreatureSpawnEvent extends Event implements Cancellable { -+ @NotNull private final Location location; -+ @NotNull private final EntityType type; -+ @NotNull private final CreatureSpawnEvent.SpawnReason reason; -+ private boolean shouldAbortSpawn; -+ -+ public PreCreatureSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason) { -+ this.location = Preconditions.checkNotNull(location, "Location may not be null").clone(); -+ this.type = Preconditions.checkNotNull(type, "Type may not be null"); -+ this.reason = Preconditions.checkNotNull(reason, "Reason may not be null"); -+ } -+ -+ /** -+ * @return The location this creature is being spawned at -+ */ -+ @NotNull -+ public Location getSpawnLocation() { -+ return location; -+ } -+ -+ /** -+ * @return The type of creature being spawned -+ */ -+ @NotNull -+ public EntityType getType() { -+ return type; -+ } -+ -+ /** -+ * @return Reason this creature is spawning (ie, NATURAL vs SPAWNER) -+ */ -+ @NotNull -+ public CreatureSpawnEvent.SpawnReason getReason() { -+ return reason; -+ } -+ -+ /** -+ * @return If the spawn process should be aborted vs trying more attempts -+ */ -+ public boolean shouldAbortSpawn() { -+ return shouldAbortSpawn; -+ } -+ -+ /** -+ * Set this if you are more blanket blocking all types of these spawns, and wish to abort the spawn process from -+ * trying more attempts after this cancellation. -+ * -+ * @param shouldAbortSpawn Set if the spawn process should be aborted vs trying more attempts -+ */ -+ public void setShouldAbortSpawn(boolean shouldAbortSpawn) { -+ this.shouldAbortSpawn = shouldAbortSpawn; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ /** -+ * @return If the spawn of this creature is cancelled or not -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Cancelling this event is more effecient than cancelling CreatureSpawnEvent -+ * @param cancel true if you wish to cancel this event, and abort the spawn of this creature -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch b/Unmapped-Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch deleted file mode 100644 index a6fa8a9b72..0000000000 --- a/Unmapped-Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 17:31:37 -0500 -Subject: [PATCH] PlayerNaturallySpawnCreaturesEvent - -This event can be used for when you want to exclude a certain player -from triggering monster spawns on a server. - -Also a highly more effecient way to blanket block spawns in a world - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..112a0dbf522b8e74ce882678434923814e6b187f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java -@@ -0,0 +1,64 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when the server is calculating what chunks to try to spawn monsters in every Monster Spawn Tick event -+ */ -+public class PlayerNaturallySpawnCreaturesEvent extends PlayerEvent implements Cancellable { -+ private byte radius; -+ -+ public PlayerNaturallySpawnCreaturesEvent(@NotNull Player player, byte radius) { -+ super(player); -+ this.radius = radius; -+ } -+ -+ /** -+ * @return The radius of chunks around this player to be included in natural spawn selection -+ */ -+ public byte getSpawnRadius() { -+ return radius; -+ } -+ -+ /** -+ * @param radius The radius of chunks around this player to be included in natural spawn selection -+ */ -+ public void setSpawnRadius(byte radius) { -+ this.radius = radius; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ /** -+ * @return If this players chunks will be excluded from natural spawns -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * @param cancel true if you wish to cancel this event, and not include this players chunks for natural spawning -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch b/Unmapped-Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch deleted file mode 100644 index 42ffd3f948..0000000000 --- a/Unmapped-Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 19 Jan 2018 00:29:28 -0500 -Subject: [PATCH] Add setPlayerProfile API for Skulls - -This allows you to create already filled textures on Skulls to avoid texture lookups -which commonly cause rate limit issues with Mojang API - -diff --git a/src/main/java/org/bukkit/block/Skull.java b/src/main/java/org/bukkit/block/Skull.java -index 943d751fb3e48212fbe258845beba03c25fa22d9..a6914f01e01e9103702185f92b0209b3c84c152a 100644 ---- a/src/main/java/org/bukkit/block/Skull.java -+++ b/src/main/java/org/bukkit/block/Skull.java -@@ -7,6 +7,7 @@ import org.bukkit.block.data.BlockData; - import org.jetbrains.annotations.Contract; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; -+import com.destroystokyo.paper.profile.PlayerProfile; // Paper - - /** - * Represents a captured state of a skull block. -@@ -61,6 +62,20 @@ public interface Skull extends TileState { - */ - public void setOwningPlayer(@NotNull OfflinePlayer player); - -+ // Paper start -+ /** -+ * Sets this skull to use the supplied Player Profile, which can include textures already prefilled. -+ * @param profile The profile to set this Skull to use, may not be null -+ */ -+ void setPlayerProfile(@NotNull PlayerProfile profile); -+ -+ /** -+ * If the skull has an owner, per {@link #hasOwner()}, return the owners {@link PlayerProfile} -+ * @return The profile of the owner, if set -+ */ -+ @Nullable PlayerProfile getPlayerProfile(); -+ // Paper end -+ - /** - * Gets the rotation of the skull in the world (or facing direction if this - * is a wall mounted skull). -diff --git a/src/main/java/org/bukkit/inventory/meta/SkullMeta.java b/src/main/java/org/bukkit/inventory/meta/SkullMeta.java -index 496254f959345d74167a9b44d160ea1bb428c5a1..88d1c889c09adb91abb09a8e43a30c871b217da2 100644 ---- a/src/main/java/org/bukkit/inventory/meta/SkullMeta.java -+++ b/src/main/java/org/bukkit/inventory/meta/SkullMeta.java -@@ -1,9 +1,11 @@ - package org.bukkit.inventory.meta; - -+import com.destroystokyo.paper.profile.PlayerProfile; - import org.bukkit.OfflinePlayer; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - -+ - /** - * Represents a skull that can have an owner. - */ -@@ -36,6 +38,20 @@ public interface SkullMeta extends ItemMeta { - @Deprecated - boolean setOwner(@Nullable String owner); - -+ // Paper start -+ /** -+ * Sets this skull to use the supplied Player Profile, which can include textures already prefilled. -+ * @param profile The profile to set this Skull to use, or null to clear owner -+ */ -+ void setPlayerProfile(@Nullable PlayerProfile profile); -+ -+ /** -+ * If the skull has an owner, per {@link #hasOwner()}, return the owners {@link PlayerProfile} -+ * @return The profile of the owner, if set -+ */ -+ @Nullable PlayerProfile getPlayerProfile(); -+ // Paper end -+ - /** - * Gets the owner of the skull. - * diff --git a/Unmapped-Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch b/Unmapped-Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch deleted file mode 100644 index 5511f6449a..0000000000 --- a/Unmapped-Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch +++ /dev/null @@ -1,176 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 2 Jan 2018 00:31:08 -0500 -Subject: [PATCH] Fill Profile Property Events - -Allows plugins to populate profile properties from local sources to avoid calls out to Mojang API -to fill in textures for example. - -If Mojang API does need to be hit, event fire so you can get the results. - -This is useful for implementing a ProfileCache for Player Skulls - -diff --git a/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..71f36e9cae209ec6861835a5e76e018de959040a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java -@@ -0,0 +1,75 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+package com.destroystokyo.paper.event.profile; -+ -+import com.destroystokyo.paper.profile.PlayerProfile; -+import com.destroystokyo.paper.profile.ProfileProperty; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import java.util.Set; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired once a profiles additional properties (such as textures) has been filled -+ */ -+public class FillProfileEvent extends Event { -+ @NotNull private final PlayerProfile profile; -+ -+ public FillProfileEvent(@NotNull PlayerProfile profile) { -+ super(!org.bukkit.Bukkit.isPrimaryThread()); -+ this.profile = profile; -+ } -+ -+ /** -+ * @return The Profile that had properties filled -+ */ -+ @NotNull -+ public PlayerProfile getPlayerProfile() { -+ return profile; -+ } -+ -+ /** -+ * Same as .getPlayerProfile().getProperties() -+ * -+ * @see PlayerProfile#getProperties() -+ * @return The new properties on the profile. -+ */ -+ @NotNull -+ public Set getProperties() { -+ return profile.getProperties(); -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..021bc86310a06f84b39459e0eb8927802726399c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java -@@ -0,0 +1,77 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+package com.destroystokyo.paper.event.profile; -+ -+import com.destroystokyo.paper.profile.PlayerProfile; -+import com.destroystokyo.paper.profile.ProfileProperty; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import java.util.Collection; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when the server is requesting to fill in properties of an incomplete profile, such as textures. -+ * -+ * Allows plugins to pre populate cached properties and avoid a call to the Mojang API -+ */ -+public class PreFillProfileEvent extends Event { -+ @NotNull private final PlayerProfile profile; -+ -+ public PreFillProfileEvent(@NotNull PlayerProfile profile) { -+ super(!org.bukkit.Bukkit.isPrimaryThread()); -+ this.profile = profile; -+ } -+ -+ /** -+ * @return The profile that needs its properties filled -+ */ -+ @NotNull -+ public PlayerProfile getPlayerProfile() { -+ return profile; -+ } -+ -+ /** -+ * Sets the properties on the profile, avoiding the call to the Mojang API -+ * Same as .getPlayerProfile().setProperties(properties); -+ * -+ * @see PlayerProfile#setProperties(Collection) -+ * @param properties The properties to set/append -+ */ -+ public void setProperties(@NotNull Collection properties) { -+ profile.setProperties(properties); -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch b/Unmapped-Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch deleted file mode 100644 index 5e8eaca58a..0000000000 --- a/Unmapped-Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 19 Jan 2018 08:15:14 -0600 -Subject: [PATCH] PlayerAdvancementCriterionGrantEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..bb8d7c959cdea4b66455a49e74804ea4b126620d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java -@@ -0,0 +1,63 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.advancement.Advancement; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player is granted a criteria in an advancement. -+ */ -+public class PlayerAdvancementCriterionGrantEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private final Advancement advancement; -+ @NotNull private final String criterion; -+ private boolean cancel = false; -+ -+ public PlayerAdvancementCriterionGrantEvent(@NotNull Player who, @NotNull Advancement advancement, @NotNull String criterion) { -+ super(who); -+ this.advancement = advancement; -+ this.criterion = criterion; -+ } -+ -+ /** -+ * Get the advancement which has been affected. -+ * -+ * @return affected advancement -+ */ -+ @NotNull -+ public Advancement getAdvancement() { -+ return advancement; -+ } -+ -+ /** -+ * Get the criterion which has been granted. -+ * -+ * @return granted criterion -+ */ -+ @NotNull -+ public String getCriterion() { -+ return criterion; -+ } -+ -+ public boolean isCancelled() { -+ return cancel; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ this.cancel = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch b/Unmapped-Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch deleted file mode 100644 index 6287ef49e7..0000000000 --- a/Unmapped-Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 27 Jan 2018 17:06:24 -0500 -Subject: [PATCH] Add ArmorStand Item Meta - -This is adds basic item meta for armor stands. It does not add all -possible metadata however. - -There are armor, hand, and equipment types, as well as position data -that can also be added here. This initial addition should serve a -starting point for future additions in this area. - -diff --git a/src/main/java/com/destroystokyo/paper/inventory/meta/ArmorStandMeta.java b/src/main/java/com/destroystokyo/paper/inventory/meta/ArmorStandMeta.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7e4acfff16db80a75e1ff2fee1972b16955b0918 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/inventory/meta/ArmorStandMeta.java -@@ -0,0 +1,78 @@ -+package com.destroystokyo.paper.inventory.meta; -+ -+import org.bukkit.inventory.meta.ItemMeta; -+ -+public interface ArmorStandMeta extends ItemMeta { -+ -+ /** -+ * Gets whether the ArmorStand should be invisible when spawned -+ * -+ * @return true if this should be invisible -+ */ -+ boolean isInvisible(); -+ -+ /** -+ * Gets whether this ArmorStand should have no base plate when spawned -+ * -+ * @return true if it will not have a base plate -+ */ -+ boolean hasNoBasePlate(); -+ -+ /** -+ * Gets whether this ArmorStand should show arms when spawned -+ * -+ * @return true if it will show arms -+ */ -+ boolean shouldShowArms(); -+ -+ /** -+ * Gets whether this ArmorStand will be small when spawned -+ * -+ * @return true if it will be small -+ */ -+ boolean isSmall(); -+ -+ /** -+ * Gets whether this ArmorStand will be a marker when spawned -+ * The exact details of this flag are an implementation detail -+ * -+ * @return true if it will be a marker -+ */ -+ boolean isMarker(); -+ -+ /** -+ * Sets that this ArmorStand should be invisible when spawned -+ * -+ * @param invisible true if set invisible -+ */ -+ void setInvisible(boolean invisible); -+ -+ /** -+ * Sets that this ArmorStand should have no base plate when spawned -+ * -+ * @param noBasePlate true if no base plate -+ */ -+ void setNoBasePlate(boolean noBasePlate); -+ -+ /** -+ * Sets that this ArmorStand should show arms when spawned -+ * -+ * @param showArms true if show arms -+ */ -+ void setShowArms(boolean showArms); -+ -+ /** -+ * Sets that this ArmorStand should be small when spawned -+ * -+ * @param small true if small -+ */ -+ void setSmall(boolean small); -+ -+ /** -+ * Sets that this ArmorStand should be a marker when spawned -+ * The exact details of this flag are an implementation detail -+ * -+ * @param marker true if a marker -+ */ -+ void setMarker(boolean marker); -+} diff --git a/Unmapped-Spigot-API-Patches/0084-Optimize-Hoppers.patch b/Unmapped-Spigot-API-Patches/0084-Optimize-Hoppers.patch deleted file mode 100644 index 79c141af55..0000000000 --- a/Unmapped-Spigot-API-Patches/0084-Optimize-Hoppers.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 18 Jan 2018 01:00:27 -0500 -Subject: [PATCH] Optimize Hoppers - -Adds data about what Item related methods were used in InventoryMoveItem event -so that the server can improve the performance of this event. - -diff --git a/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java -index a8c48f5a416326e96c431e5fa22edee04825530e..04d4a83bfc4f86341f9d72128458154d08c8ec43 100644 ---- a/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java -@@ -31,6 +31,8 @@ public class InventoryMoveItemEvent extends Event implements Cancellable { - private final Inventory destinationInventory; - private ItemStack itemStack; - private final boolean didSourceInitiate; -+ public boolean calledGetItem; // Paper -+ public boolean calledSetItem; // Paper - - public InventoryMoveItemEvent(@NotNull final Inventory sourceInventory, @NotNull final ItemStack itemStack, @NotNull final Inventory destinationInventory, final boolean didSourceInitiate) { - Validate.notNull(itemStack, "ItemStack cannot be null"); -@@ -58,7 +60,8 @@ public class InventoryMoveItemEvent extends Event implements Cancellable { - */ - @NotNull - public ItemStack getItem() { -- return itemStack.clone(); -+ calledGetItem = true; // Paper - record this method was used for auto detection of mode -+ return itemStack; // Paper - Removed clone, handled better in Server - } - - /** -@@ -70,6 +73,7 @@ public class InventoryMoveItemEvent extends Event implements Cancellable { - */ - public void setItem(@NotNull ItemStack itemStack) { - Validate.notNull(itemStack, "ItemStack cannot be null. Cancel the event if you want nothing to be transferred."); -+ calledSetItem = true; // Paper - record this method was used for auto detection of mode - this.itemStack = itemStack.clone(); - } - diff --git a/Unmapped-Spigot-API-Patches/0085-Tameable-getOwnerUniqueId-API.patch b/Unmapped-Spigot-API-Patches/0085-Tameable-getOwnerUniqueId-API.patch deleted file mode 100644 index b911542a60..0000000000 --- a/Unmapped-Spigot-API-Patches/0085-Tameable-getOwnerUniqueId-API.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 24 Feb 2018 00:55:52 -0500 -Subject: [PATCH] Tameable#getOwnerUniqueId API - -This is faster if all you need is the UUID, as .getOwner() will cause -an OfflinePlayer to be loaded from disk. - -diff --git a/src/main/java/org/bukkit/entity/Tameable.java b/src/main/java/org/bukkit/entity/Tameable.java -index 26c996cd41acc88490ac0135a9239cffc03e8efb..65e68da98ab66ed781bce2f0dbe0913be48d2990 100644 ---- a/src/main/java/org/bukkit/entity/Tameable.java -+++ b/src/main/java/org/bukkit/entity/Tameable.java -@@ -1,5 +1,6 @@ - package org.bukkit.entity; - -+import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - - public interface Tameable extends Animals { -@@ -25,9 +26,22 @@ public interface Tameable extends Animals { - */ - public void setTamed(boolean tame); - -+ // Paper start -+ /** -+ * Gets the owners UUID -+ * -+ * @return the owners UUID, or null if not owned -+ */ -+ @Nullable -+ public java.util.UUID getOwnerUniqueId(); -+ // Paper end -+ - /** - * Gets the current owning AnimalTamer - * -+ * @see #getOwnerUniqueId() Recommended to use UUID version instead of this for performance. -+ * This method will cause OfflinePlayer to be loaded from disk if the owner is not online. -+ * - * @return the owning AnimalTamer, or null if not owned - */ - @Nullable diff --git a/Unmapped-Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/Unmapped-Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch deleted file mode 100644 index a2a9f5270f..0000000000 --- a/Unmapped-Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 18 Mar 2018 11:43:30 -0400 -Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent - -This will allow you to change the players name or skin on login. - -diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -index 992d1025ca02020e87a9ab5db83d249427f41d69..a40b57edb1aeff71fc0b9767d410950da5c06283 100644 ---- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -@@ -2,6 +2,9 @@ package org.bukkit.event.player; - - import java.net.InetAddress; - import java.util.UUID; -+ -+import com.destroystokyo.paper.profile.PlayerProfile; -+import org.bukkit.Bukkit; - import org.bukkit.event.Event; - import org.bukkit.event.HandlerList; - import org.jetbrains.annotations.NotNull; -@@ -15,9 +18,9 @@ public class AsyncPlayerPreLoginEvent extends Event { - private static final HandlerList handlers = new HandlerList(); - private Result result; - private net.kyori.adventure.text.Component message; // Paper -- private final String name; -+ //private String name; // Paper - Not used anymore - private final InetAddress ipAddress; -- private final UUID uniqueId; -+ //private UUID uniqueId; // Paper - Not used anymore - - @Deprecated - public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress) { -@@ -25,12 +28,37 @@ public class AsyncPlayerPreLoginEvent extends Event { - } - - public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId) { -+ // Paper start -+ this(name, ipAddress, uniqueId, Bukkit.createProfile(uniqueId, name)); -+ } -+ private PlayerProfile profile; -+ -+ /** -+ * Gets the PlayerProfile of the player logging in -+ * @return The Profile -+ */ -+ @NotNull -+ public PlayerProfile getPlayerProfile() { -+ return profile; -+ } -+ -+ /** -+ * Changes the PlayerProfile the player will login as -+ * @param profile The profile to use -+ */ -+ public void setPlayerProfile(@NotNull PlayerProfile profile) { -+ this.profile = profile; -+ } -+ -+ public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId, @NotNull PlayerProfile profile) { - super(true); -+ this.profile = profile; -+ // Paper end - this.result = Result.ALLOWED; - this.message = net.kyori.adventure.text.Component.empty(); // Paper -- this.name = name; -+ //this.name = name; // Paper - Not used anymore - this.ipAddress = ipAddress; -- this.uniqueId = uniqueId; -+ //this.uniqueId = uniqueId; // Paper - Not used anymore - } - - /** -@@ -193,7 +221,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - */ - @NotNull - public String getName() { -- return name; -+ return profile.getName(); // Paper - } - - /** -@@ -213,7 +241,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - */ - @NotNull - public UUID getUniqueId() { -- return uniqueId; -+ return profile.getId(); // Paper - } - - @NotNull diff --git a/Unmapped-Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch b/Unmapped-Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch deleted file mode 100644 index f35ae4323f..0000000000 --- a/Unmapped-Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch +++ /dev/null @@ -1,381 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 15:55:38 +0200 -Subject: [PATCH] Add extended PaperServerListPingEvent - -Add a new event that extends the original ServerListPingEvent -and allows full control of the response sent to the client. - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java b/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..baac2e4f090a490372ef4aed92c8a5771955e921 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java -@@ -0,0 +1,334 @@ -+package com.destroystokyo.paper.event.server; -+ -+import static java.util.Objects.requireNonNull; -+ -+import com.destroystokyo.paper.network.StatusClient; -+import com.destroystokyo.paper.profile.PlayerProfile; -+import org.bukkit.Bukkit; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.server.ServerListPingEvent; -+import org.bukkit.util.CachedServerIcon; -+ -+import java.util.ArrayList; -+import java.util.Iterator; -+import java.util.List; -+import java.util.NoSuchElementException; -+import java.util.UUID; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Extended version of {@link ServerListPingEvent} that allows full control -+ * of the response sent to the client. -+ */ -+public class PaperServerListPingEvent extends ServerListPingEvent implements Cancellable { -+ -+ @NotNull private final StatusClient client; -+ -+ private int numPlayers; -+ private boolean hidePlayers; -+ @NotNull private final List playerSample = new ArrayList<>(); -+ -+ @NotNull private String version; -+ private int protocolVersion; -+ -+ @Nullable private CachedServerIcon favicon; -+ -+ private boolean cancelled; -+ -+ private boolean originalPlayerCount = true; -+ private Object[] players; -+ -+ @Deprecated -+ public PaperServerListPingEvent(@NotNull StatusClient client, @NotNull String motd, int numPlayers, int maxPlayers, -+ @NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon) { -+ super(client.getAddress().getAddress(), motd, numPlayers, maxPlayers); -+ this.client = client; -+ this.numPlayers = numPlayers; -+ this.version = version; -+ this.protocolVersion = protocolVersion; -+ setServerIcon(favicon); -+ } -+ -+ public PaperServerListPingEvent(@NotNull StatusClient client, @NotNull net.kyori.adventure.text.Component motd, int numPlayers, int maxPlayers, -+ @NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon) { -+ super(client.getAddress().getAddress(), motd, numPlayers, maxPlayers); -+ this.client = client; -+ this.numPlayers = numPlayers; -+ this.version = version; -+ this.protocolVersion = protocolVersion; -+ setServerIcon(favicon); -+ } -+ -+ /** -+ * Returns the {@link StatusClient} pinging the server. -+ * -+ * @return The client -+ */ -+ @NotNull -+ public StatusClient getClient() { -+ return this.client; -+ } -+ -+ /** -+ * {@inheritDoc} -+ * -+ *

    Returns {@code -1} if players are hidden using -+ * {@link #shouldHidePlayers()}.

    -+ */ -+ @Override -+ public int getNumPlayers() { -+ if (this.hidePlayers) { -+ return -1; -+ } -+ -+ return this.numPlayers; -+ } -+ -+ /** -+ * Sets the number of players displayed in the server list. -+ * -+ *

    Note that this won't have any effect if {@link #shouldHidePlayers()} -+ * is enabled.

    -+ * -+ * @param numPlayers The number of online players -+ */ -+ public void setNumPlayers(int numPlayers) { -+ if (this.numPlayers != numPlayers) { -+ this.numPlayers = numPlayers; -+ this.originalPlayerCount = false; -+ } -+ } -+ -+ /** -+ * {@inheritDoc} -+ * -+ *

    Returns {@code -1} if players are hidden using -+ * {@link #shouldHidePlayers()}.

    -+ */ -+ @Override -+ public int getMaxPlayers() { -+ if (this.hidePlayers) { -+ return -1; -+ } -+ -+ return super.getMaxPlayers(); -+ } -+ -+ /** -+ * Returns whether all player related information is hidden in the server -+ * list. This will cause {@link #getNumPlayers()}, {@link #getMaxPlayers()} -+ * and {@link #getPlayerSample()} to be skipped in the response. -+ * -+ *

    The Vanilla Minecraft client will display the player count as {@code ???} -+ * when this option is enabled.

    -+ * -+ * @return {@code true} if the player count is hidden -+ */ -+ public boolean shouldHidePlayers() { -+ return hidePlayers; -+ } -+ -+ /** -+ * Sets whether all player related information is hidden in the server -+ * list. This will cause {@link #getNumPlayers()}, {@link #getMaxPlayers()} -+ * and {@link #getPlayerSample()} to be skipped in the response. -+ * -+ *

    The Vanilla Minecraft client will display the player count as {@code ???} -+ * when this option is enabled.

    -+ * -+ * @param hidePlayers {@code true} if the player count should be hidden -+ */ -+ public void setHidePlayers(boolean hidePlayers) { -+ this.hidePlayers = hidePlayers; -+ } -+ -+ /** -+ * Returns a mutable list of {@link PlayerProfile} that will be displayed -+ * as online players on the client. -+ * -+ *

    The Vanilla Minecraft client will display them when hovering the -+ * player count with the mouse.

    -+ * -+ * @return The mutable player sample list -+ */ -+ @NotNull -+ public List getPlayerSample() { -+ return this.playerSample; -+ } -+ -+ /** -+ * Returns the version that will be sent as server version on the client. -+ * -+ * @return The server version -+ */ -+ @NotNull -+ public String getVersion() { -+ return version; -+ } -+ -+ /** -+ * Sets the version that will be sent as server version to the client. -+ * -+ * @param version The server version -+ */ -+ public void setVersion(@NotNull String version) { -+ this.version = requireNonNull(version, "version"); -+ } -+ -+ /** -+ * Returns the protocol version that will be sent as the protocol version -+ * of the server to the client. -+ * -+ * @return The protocol version of the server, or {@code -1} if the server -+ * has not finished initialization yet -+ */ -+ public int getProtocolVersion() { -+ return protocolVersion; -+ } -+ -+ /** -+ * Sets the protocol version that will be sent as the protocol version -+ * of the server to the client. -+ * -+ * @param protocolVersion The protocol version of the server -+ */ -+ public void setProtocolVersion(int protocolVersion) { -+ this.protocolVersion = protocolVersion; -+ } -+ -+ /** -+ * Gets the server icon sent to the client. -+ * -+ * @return The icon to send to the client, or {@code null} for none -+ */ -+ @Nullable -+ public CachedServerIcon getServerIcon() { -+ return this.favicon; -+ } -+ -+ /** -+ * Sets the server icon sent to the client. -+ * -+ * @param icon The icon to send to the client, or {@code null} for none -+ */ -+ @Override -+ public void setServerIcon(@Nullable CachedServerIcon icon) { -+ if (icon != null && icon.isEmpty()) { -+ // Represent empty icons as null -+ icon = null; -+ } -+ -+ this.favicon = icon; -+ } -+ -+ /** -+ * {@inheritDoc} -+ * -+ *

    Cancelling this event will cause the connection to be closed immediately, -+ * without sending a response to the client.

    -+ */ -+ @Override -+ public boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ /** -+ * {@inheritDoc} -+ * -+ *

    Cancelling this event will cause the connection to be closed immediately, -+ * without sending a response to the client.

    -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ /** -+ * {@inheritDoc} -+ * -+ *

    Note: For compatibility reasons, this method will return all -+ * online players, not just the ones referenced in {@link #getPlayerSample()}. -+ * Removing a player will:

    -+ * -+ *
      -+ *
    • Decrement the online player count (if and only if) the player -+ * count wasn't changed by another plugin before.
    • -+ *
    • Remove all entries from {@link #getPlayerSample()} that refer to -+ * the removed player (based on their {@link UUID}).
    • -+ *
    -+ */ -+ @NotNull -+ @Override -+ public Iterator iterator() { -+ if (this.players == null) { -+ this.players = getOnlinePlayers(); -+ } -+ -+ return new PlayerIterator(); -+ } -+ -+ @NotNull -+ protected Object[] getOnlinePlayers() { -+ return Bukkit.getOnlinePlayers().toArray(); -+ } -+ -+ @NotNull -+ protected Player getBukkitPlayer(@NotNull Object player) { -+ return (Player) player; -+ } -+ -+ private final class PlayerIterator implements Iterator { -+ -+ private int next; -+ private int current; -+ @Nullable private Player player; -+ -+ @Override -+ public boolean hasNext() { -+ for (; this.next < players.length; this.next++) { -+ if (players[this.next] != null) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ @NotNull -+ @Override -+ public Player next() { -+ if (!hasNext()) { -+ this.player = null; -+ throw new NoSuchElementException(); -+ } -+ -+ this.current = this.next++; -+ return this.player = getBukkitPlayer(players[this.current]); -+ } -+ -+ @Override -+ public void remove() { -+ if (this.player == null) { -+ throw new IllegalStateException(); -+ } -+ -+ UUID uniqueId = this.player.getUniqueId(); -+ this.player = null; -+ -+ // Remove player from iterator -+ players[this.current] = null; -+ -+ // Remove player from sample -+ getPlayerSample().removeIf(p -> uniqueId.equals(p.getId())); -+ -+ // Decrement player count -+ if (originalPlayerCount) { -+ numPlayers--; -+ } -+ } -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/network/StatusClient.java b/src/main/java/com/destroystokyo/paper/network/StatusClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..517d15238ed117f38bbd39f570874014cecf7bb5 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/StatusClient.java -@@ -0,0 +1,13 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+ -+/** -+ * Represents a client requesting the current status from the server (e.g. from -+ * the server list). -+ * -+ * @see PaperServerListPingEvent -+ */ -+public interface StatusClient extends NetworkClient { -+ -+} -diff --git a/src/main/java/org/bukkit/util/CachedServerIcon.java b/src/main/java/org/bukkit/util/CachedServerIcon.java -index 612958a331575d1da2715531ebdf6b1168f2e860..bb4f7702ced0baf0670a7a21d48ad528b7249361 100644 ---- a/src/main/java/org/bukkit/util/CachedServerIcon.java -+++ b/src/main/java/org/bukkit/util/CachedServerIcon.java -@@ -18,4 +18,9 @@ public interface CachedServerIcon { - @Nullable - public String getData(); // Paper - -+ // Paper start -+ default boolean isEmpty() { -+ return getData() == null; -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch b/Unmapped-Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch deleted file mode 100644 index 5a914436ae..0000000000 --- a/Unmapped-Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 18 Mar 2018 12:28:55 -0400 -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/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 9a262d412b2762a33a60b1e8762a7d9c9c3f933d..3ae4d670059f80bd057870a37f4025261e397dfa 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -4,6 +4,7 @@ import java.net.InetSocketAddress; - import java.util.UUID; - import com.destroystokyo.paper.Title; // Paper - import net.kyori.adventure.text.Component; -+import com.destroystokyo.paper.profile.PlayerProfile; // Paper - import org.bukkit.DyeColor; - import org.bukkit.Effect; - import org.bukkit.GameMode; -@@ -1714,6 +1715,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * was {@link org.bukkit.event.player.PlayerResourcePackStatusEvent.Status#SUCCESSFULLY_LOADED} - */ - boolean hasResourcePack(); -+ -+ /** -+ * Gets a copy of this players profile -+ * @return The players profile object -+ */ -+ @NotNull -+ PlayerProfile getPlayerProfile(); -+ -+ /** -+ * Changes the PlayerProfile for this player. This will cause this player -+ * to be reregistered to all clients that can currently see this player -+ * @param profile The new profile to use -+ */ -+ void setPlayerProfile(@NotNull PlayerProfile profile); - // Paper end - - // Spigot start diff --git a/Unmapped-Spigot-API-Patches/0089-getPlayerUniqueId-API.patch b/Unmapped-Spigot-API-Patches/0089-getPlayerUniqueId-API.patch deleted file mode 100644 index 6586351ea9..0000000000 --- a/Unmapped-Spigot-API-Patches/0089-getPlayerUniqueId-API.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 22 Mar 2018 01:39:28 -0400 -Subject: [PATCH] getPlayerUniqueId API - -Gets the unique ID of the player currently known as the specified player name -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 f5d3a7370390871d1b6075f32846d1a942b05b7f..2d7f8e128e23934a8fe26baf19198b7ffc8447bb 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -504,6 +504,20 @@ public final class Bukkit { - return server.getPlayer(id); - } - -+ // Paper start -+ /** -+ * Gets the unique ID of the player currently known as the specified player name -+ * In Offline Mode, will return an Offline UUID -+ * -+ * @param playerName the player name to look up the unique ID for -+ * @return A UUID, or null if that player name is not registered with Minecraft and the server is in online mode -+ */ -+ @Nullable -+ public static UUID getPlayerUniqueId(@NotNull String playerName) { -+ return server.getPlayerUniqueId(playerName); -+ } -+ // Paper end -+ - /** - * 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 38d138b217734e598581ed14065ff2015135ee9a..01657abaff86cf7bb3ffb857024c5032781b8660 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -429,6 +429,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @Nullable - public Player getPlayer(@NotNull UUID id); - -+ // Paper start -+ /** -+ * Gets the unique ID of the player currently known as the specified player name -+ * In Offline Mode, will return an Offline UUID -+ * -+ * @param playerName the player name to look up the unique ID for -+ * @return A UUID, or null if that player name is not registered with Minecraft and the server is in online mode -+ */ -+ @Nullable -+ public UUID getPlayerUniqueId(@NotNull String playerName); -+ // Paper end -+ - /** - * Gets the plugin manager for interfacing with plugins. - * diff --git a/Unmapped-Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch b/Unmapped-Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch deleted file mode 100644 index f21c766148..0000000000 --- a/Unmapped-Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 19:30:20 +0200 -Subject: [PATCH] Add legacy ping support to PaperServerListPingEvent - -Add a new method to StatusClient check if the client is a legacy -client that does not support all of the features provided in the -event. - -diff --git a/src/main/java/com/destroystokyo/paper/network/StatusClient.java b/src/main/java/com/destroystokyo/paper/network/StatusClient.java -index 517d15238ed117f38bbd39f570874014cecf7bb5..ffda9f6a8b094942009aa78b331d22d9dcca2802 100644 ---- a/src/main/java/com/destroystokyo/paper/network/StatusClient.java -+++ b/src/main/java/com/destroystokyo/paper/network/StatusClient.java -@@ -10,4 +10,16 @@ import com.destroystokyo.paper.event.server.PaperServerListPingEvent; - */ - public interface StatusClient extends NetworkClient { - -+ /** -+ * Returns whether the client is using an older version that doesn't -+ * support all of the features in {@link PaperServerListPingEvent}. -+ * -+ *

    For Vanilla, this returns {@code true} for all clients older than 1.7.

    -+ * -+ * @return {@code true} if the client is using legacy ping -+ */ -+ default boolean isLegacy() { -+ return false; -+ } -+ - } diff --git a/Unmapped-Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch b/Unmapped-Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch deleted file mode 100644 index c75d281c23..0000000000 --- a/Unmapped-Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 1 Apr 2018 02:28:43 +0300 -Subject: [PATCH] Add method to open already placed sign - - -diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index d212d5123b6294f7873d72f125505a006c290b05..7430bc85301d0fcb34c6035fbe08ae245c76e043 100644 ---- a/src/main/java/org/bukkit/entity/HumanEntity.java -+++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -461,6 +461,14 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder - */ - @Deprecated - public void setShoulderEntityRight(@Nullable Entity entity); -+ // Paper start - Add method to open already placed sign -+ /** -+ * Opens an editor window for the specified sign -+ * -+ * @param sign The sign to open -+ */ -+ void openSign(@NotNull org.bukkit.block.Sign sign); -+ // Paper end - - /** - * Make the entity drop the item in their hand. diff --git a/Unmapped-Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch b/Unmapped-Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch deleted file mode 100644 index 540eeb4d36..0000000000 --- a/Unmapped-Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 28 Apr 2018 10:28:50 -0400 -Subject: [PATCH] Add Ban Methods to Player Objects - -Allows a more logical API for banning players. - -player.banPlayer("Breaking the rules"); - -diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java -index 58313929f81509030216a0e5e3869da63e11108e..6cf05fed701c67a2c797a4e0839c795802a238a1 100644 ---- a/src/main/java/org/bukkit/OfflinePlayer.java -+++ b/src/main/java/org/bukkit/OfflinePlayer.java -@@ -45,6 +45,61 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio - * @return true if banned, otherwise false - */ - public boolean isBanned(); -+ // Paper start -+ -+ /** -+ * Permanently Bans this player from the server -+ * -+ * @param reason Reason for Ban -+ * @return Ban Entry -+ */ -+ @NotNull -+ public default BanEntry banPlayer(@Nullable String reason) { -+ return banPlayer(reason, null, null); -+ } -+ -+ /** -+ * Permanently Bans this player from the server -+ * @param reason Reason for Ban -+ * @param source Source of the ban, or null for default -+ * @return Ban Entry -+ */ -+ @NotNull -+ public default BanEntry banPlayer(@Nullable String reason, @Nullable String source) { -+ return banPlayer(reason, null, source); -+ } -+ -+ /** -+ * Bans this player from the server -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @return Ban Entry -+ */ -+ @NotNull -+ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.Date expires) { -+ return banPlayer(reason, expires, null); -+ } -+ -+ /** -+ * Bans this player from the server -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @param source Source of the ban or null for default -+ * @return Ban Entry -+ */ -+ @NotNull -+ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.Date expires, @Nullable String source) { -+ return banPlayer(reason, expires, source, true); -+ } -+ @NotNull -+ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.Date expires, @Nullable String source, boolean kickIfOnline) { -+ BanEntry banEntry = Bukkit.getServer().getBanList(BanList.Type.NAME).addBan(getName(), reason, expires, source); -+ if (kickIfOnline && isOnline()) { -+ getPlayer().kickPlayer(reason); -+ } -+ return banEntry; -+ } -+ // Paper end - - /** - * Checks if this player is whitelisted or not -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 6769330f336afcd5f26c0f7286defa00bead543c..88fd4cdeaad4d27f414c6b268022cdedf73492e7 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -5,6 +5,10 @@ import java.util.UUID; - import com.destroystokyo.paper.Title; // Paper - import net.kyori.adventure.text.Component; - import com.destroystokyo.paper.profile.PlayerProfile; // Paper -+import java.util.Date; // Paper -+import org.bukkit.BanEntry; // Paper -+import org.bukkit.BanList; // Paper -+import org.bukkit.Bukkit; // Paper - import org.bukkit.DyeColor; - import org.bukkit.Effect; - import org.bukkit.GameMode; -@@ -618,6 +622,162 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - public void sendMap(@NotNull MapView map); - - // Paper start -+ /** -+ * Permanently Bans the Profile and IP address currently used by the player. -+ * -+ * @param reason Reason for ban -+ * @return Ban Entry -+ */ -+ // For reference, Bukkit defines this as nullable, while they impl isn't, we'll follow API. -+ @Nullable -+ public default BanEntry banPlayerFull(@Nullable String reason) { -+ return banPlayerFull(reason, null, null); -+ } -+ -+ /** -+ * Permanently Bans the Profile and IP address currently used by the player. -+ * -+ * @param reason Reason for ban -+ * @param source Source of ban, or null for default -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerFull(@Nullable String reason, @Nullable String source) { -+ return banPlayerFull(reason, null, source); -+ } -+ -+ /** -+ * Bans the Profile and IP address currently used by the player. -+ * -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerFull(@Nullable String reason, @Nullable Date expires) { -+ return banPlayerFull(reason, expires, null); -+ } -+ -+ /** -+ * Bans the Profile and IP address currently used by the player. -+ * -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @param source Source of the ban, or null for default -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerFull(@Nullable String reason, @Nullable Date expires, @Nullable String source) { -+ banPlayer(reason, expires, source); -+ return banPlayerIP(reason, expires, source, true); -+ } -+ -+ /** -+ * Permanently Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * -+ * @param reason Reason for ban -+ * @param kickPlayer Whether or not to kick the player afterwards -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, boolean kickPlayer) { -+ return banPlayerIP(reason, null, null, kickPlayer); -+ } -+ -+ /** -+ * Permanently Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * @param reason Reason for ban -+ * @param source Source of ban, or null for default -+ * @param kickPlayer Whether or not to kick the player afterwards -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable String source, boolean kickPlayer) { -+ return banPlayerIP(reason, null, source, kickPlayer); -+ } -+ -+ /** -+ * Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @param kickPlayer Whether or not to kick the player afterwards -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable Date expires, boolean kickPlayer) { -+ return banPlayerIP(reason, expires, null, kickPlayer); -+ } -+ -+ /** -+ * Permanently Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * -+ * @param reason Reason for ban -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason) { -+ return banPlayerIP(reason, null, null); -+ } -+ -+ /** -+ * Permanently Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * @param reason Reason for ban -+ * @param source Source of ban, or null for default -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable String source) { -+ return banPlayerIP(reason, null, source); -+ } -+ -+ /** -+ * Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable Date expires) { -+ return banPlayerIP(reason, expires, null); -+ } -+ -+ /** -+ * Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @param source Source of the banm or null for default -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable Date expires, @Nullable String source) { -+ return banPlayerIP(reason, expires, source, true); -+ } -+ -+ /** -+ * Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @param source Source of the banm or null for default -+ * @param kickPlayer if the targeted player should be kicked -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable Date expires, @Nullable String source, boolean kickPlayer) { -+ BanEntry banEntry = Bukkit.getServer().getBanList(BanList.Type.IP).addBan(getAddress().getAddress().getHostAddress(), reason, expires, source); -+ if (kickPlayer && isOnline()) { -+ getPlayer().kickPlayer(reason); -+ } -+ -+ return banEntry; -+ } - - /** - * Sends an Action Bar message to the client. diff --git a/Unmapped-Spigot-API-Patches/0093-EndermanEscapeEvent.patch b/Unmapped-Spigot-API-Patches/0093-EndermanEscapeEvent.patch deleted file mode 100644 index 82d22fd0ea..0000000000 --- a/Unmapped-Spigot-API-Patches/0093-EndermanEscapeEvent.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 13:14:30 -0400 -Subject: [PATCH] EndermanEscapeEvent - -Fires an event anytime an enderman intends to teleport away from the player - -You may cancel this, enabling ranged attacks to damage the enderman for example. - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..806112a8b5a7ce31166675f5b074ceaf42e364b6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java -@@ -0,0 +1,87 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Enderman; -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+public class EndermanEscapeEvent extends EntityEvent implements Cancellable { -+ @NotNull private final Reason reason; -+ -+ public EndermanEscapeEvent(@NotNull Enderman entity, @NotNull Reason reason) { -+ super(entity); -+ this.reason = reason; -+ } -+ -+ @NotNull -+ @Override -+ public Enderman getEntity() { -+ return (Enderman) super.getEntity(); -+ } -+ -+ /** -+ * @return The reason the enderman is trying to escape -+ */ -+ @NotNull -+ public Reason getReason() { -+ return reason; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Cancels the escape. -+ * -+ * If this escape normally would of resulted in damage avoidance such as indirect, -+ * the enderman will now take damage. -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ public enum Reason { -+ /** -+ * The enderman has stopped attacking and ran away -+ */ -+ RUNAWAY, -+ /** -+ * The enderman has teleported away due to indirect damage (ranged) -+ */ -+ INDIRECT, -+ /** -+ * The enderman has teleported away due to a critical hit -+ */ -+ CRITICAL_HIT, -+ /** -+ * The enderman has teleported away due to the player staring at it during combat -+ */ -+ STARE, -+ /** -+ * Specific case for CRITICAL_HIT where the enderman is taking rain damage -+ */ -+ DROWN -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0094-Enderman.teleportRandomly.patch b/Unmapped-Spigot-API-Patches/0094-Enderman.teleportRandomly.patch deleted file mode 100644 index 9c226d009c..0000000000 --- a/Unmapped-Spigot-API-Patches/0094-Enderman.teleportRandomly.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 13:29:15 -0400 -Subject: [PATCH] Enderman.teleportRandomly() - -Ability to trigger the vanilla "teleport randomly" mechanic of an enderman. - -diff --git a/src/main/java/org/bukkit/entity/Enderman.java b/src/main/java/org/bukkit/entity/Enderman.java -index bb325d9c802e33431530bbccdcf5de5839e5fe68..821c690f8a32918bdb284ffec4af98f411f76ccc 100644 ---- a/src/main/java/org/bukkit/entity/Enderman.java -+++ b/src/main/java/org/bukkit/entity/Enderman.java -@@ -10,6 +10,17 @@ import org.jetbrains.annotations.Nullable; - */ - public interface Enderman extends Monster { - -+ // Paper start -+ /** -+ * Try to teleport the enderman to a random nearby location. -+ * -+ * May conditionally fail if the random location was not valid -+ * @return If the enderman teleported successfully or not -+ */ -+ -+ public boolean teleportRandomly(); -+ // Paper end -+ - /** - * Gets the id and data of the block that the Enderman is carrying. - * diff --git a/Unmapped-Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch b/Unmapped-Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch deleted file mode 100644 index cde5bb2148..0000000000 --- a/Unmapped-Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch +++ /dev/null @@ -1,292 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 17:55:28 -0400 -Subject: [PATCH] Additional world.getNearbyEntities API's - -Provides more methods to get nearby entities, and filter by types and predicates - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 0f86a9c67797fd662cbbfdb808789bcab95caba4..cae848ce698337d0b254bd48938abfc1e68ad561 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -1,6 +1,9 @@ - package org.bukkit; - - import java.io.File; -+import org.bukkit.generator.ChunkGenerator; -+ -+import java.util.ArrayList; - import java.util.Collection; - import java.util.HashMap; - import java.util.List; -@@ -659,6 +662,256 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @NotNull - public Collection getEntitiesByClasses(@NotNull Class... classes); - -+ // Paper start -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param radius Radius -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyLivingEntities(@NotNull Location loc, double radius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, radius, radius, radius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyLivingEntities(@NotNull Location loc, double xzRadius, double yRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, xzRadius, yRadius, xzRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z radius -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyLivingEntities(@NotNull Location loc, double xRadius, double yRadius, double zRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, xRadius, yRadius, zRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param radius X Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of living entities near location. This will always be a non-null collection -+ */ -+ @NotNull -+ public default Collection getNearbyLivingEntities(@NotNull Location loc, double radius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, radius, radius, radius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of living entities near location. This will always be a non-null collection -+ */ -+ @NotNull -+ public default Collection getNearbyLivingEntities(@NotNull Location loc, double xzRadius, double yRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, xzRadius, yRadius, xzRadius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyLivingEntities(@NotNull Location loc, double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, xRadius, yRadius, zRadius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param radius X/Y/Z Radius -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyPlayers(@NotNull Location loc, double radius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, radius, radius, radius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyPlayers(@NotNull Location loc, double xzRadius, double yRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, xzRadius, yRadius, xzRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyPlayers(@NotNull Location loc, double xRadius, double yRadius, double zRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, xRadius, yRadius, zRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param radius X/Y/Z Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyPlayers(@NotNull Location loc, double radius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, radius, radius, radius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyPlayers(@NotNull Location loc, double xzRadius, double yRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, xzRadius, yRadius, xzRadius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyPlayers(@NotNull Location loc, double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, xRadius, yRadius, zRadius, predicate); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param loc Center location -+ * @param radius X/Y/Z radius to search within -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double radius) { -+ return getNearbyEntitiesByType(clazz, loc, radius, radius, radius, null); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box) -+ * @param clazz Type to filter by -+ * @param loc Center location -+ * @param xzRadius X/Z radius to search within -+ * @param yRadius Y radius to search within -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double xzRadius, double yRadius) { -+ return getNearbyEntitiesByType(clazz, loc, xzRadius, yRadius, xzRadius, null); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param loc Center location -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double xRadius, double yRadius, double zRadius) { -+ return getNearbyEntitiesByType(clazz, loc, xRadius, yRadius, zRadius, null); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param loc Center location -+ * @param radius X/Y/Z radius to search within -+ * @param predicate a predicate used to filter results -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double radius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(clazz, loc, radius, radius, radius, predicate); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box) -+ * @param clazz Type to filter by -+ * @param loc Center location -+ * @param xzRadius X/Z radius to search within -+ * @param yRadius Y radius to search within -+ * @param predicate a predicate used to filter results -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double xzRadius, double yRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(clazz, loc, xzRadius, yRadius, xzRadius, predicate); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param loc Center location -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @param predicate a predicate used to filter results -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { -+ if (clazz == null) { -+ clazz = Entity.class; -+ } -+ List nearby = new ArrayList<>(); -+ for (Entity bukkitEntity : getNearbyEntities(loc, xRadius, yRadius, zRadius)) { -+ //noinspection unchecked -+ if (clazz.isAssignableFrom(bukkitEntity.getClass()) && (predicate == null || predicate.test((T) bukkitEntity))) { -+ //noinspection unchecked -+ nearby.add((T) bukkitEntity); -+ } -+ } -+ return nearby; -+ } -+ // Paper end -+ - /** - * Get a list of all players in this World - * -diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -index a40b57edb1aeff71fc0b9767d410950da5c06283..184d9462ebbc500d8b81aaf14fe138d247bf2470 100644 ---- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -@@ -42,8 +42,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - return profile; - } - -- /** -- * Changes the PlayerProfile the player will login as -+ /* * Changes the PlayerProfile the player will login as - * @param profile The profile to use - */ - public void setPlayerProfile(@NotNull PlayerProfile profile) { diff --git a/Unmapped-Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch b/Unmapped-Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch deleted file mode 100644 index 1670d20348..0000000000 --- a/Unmapped-Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 19:27:31 -0400 -Subject: [PATCH] Location.isChunkLoaded() API - - -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index 0939a8070f9cc4f66f1679fef74862debb7d32ae..6c8b8eddcdb81f7151202eb12541308040790d45 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -533,6 +533,7 @@ public class Location implements Cloneable, ConfigurationSerializable { - return this; - } - -+ public boolean isChunkLoaded() { return this.getWorld().isChunkLoaded(locToBlock(x) >> 4, locToBlock(z) >> 4); } // Paper - @Override - public boolean equals(Object obj) { - if (obj == null) { diff --git a/Unmapped-Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch b/Unmapped-Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch deleted file mode 100644 index da01d6d5c3..0000000000 --- a/Unmapped-Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch +++ /dev/null @@ -1,579 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 29 Aug 2017 23:58:48 -0400 -Subject: [PATCH] Expand World.spawnParticle API and add Builder - -Adds ability to control who receives it and who is the source/sender (vanish API) -the standard API is to send the packet to everyone in the world, which is ineffecient. - -This adds a new Builder API which is much friendlier to use. - -diff --git a/src/main/java/com/destroystokyo/paper/ParticleBuilder.java b/src/main/java/com/destroystokyo/paper/ParticleBuilder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..06f1602f5b327705f726d0a99dd6b95e1554d382 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/ParticleBuilder.java -@@ -0,0 +1,478 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.collect.Lists; -+import org.bukkit.Color; -+import org.bukkit.Location; -+import org.bukkit.Particle; -+import org.bukkit.World; -+import org.bukkit.entity.Player; -+import org.bukkit.util.NumberConversions; -+ -+import java.util.Collection; -+import java.util.List; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Helps prepare a particle to be sent to players. -+ * -+ * Usage of the builder is preferred over the super long {@link World#spawnParticle(Particle, Location, int, double, double, double, double, Object)} API -+ */ -+public class ParticleBuilder { -+ -+ private Particle particle; -+ private List receivers; -+ private Player source; -+ private Location location; -+ private int count = 1; -+ private double offsetX = 0, offsetY = 0, offsetZ = 0; -+ private double extra = 1; -+ private Object data; -+ private boolean force = true; -+ -+ public ParticleBuilder(@NotNull Particle particle) { -+ this.particle = particle; -+ } -+ -+ /** -+ * Sends the particle to all receiving players (or all). This method is safe to use -+ * Asynchronously -+ * -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder spawn() { -+ if (this.location == null) { -+ throw new IllegalStateException("Please specify location for this particle"); -+ } -+ location.getWorld().spawnParticle(particle, receivers, source, -+ location.getX(), location.getY(), location.getZ(), -+ count, offsetX, offsetY, offsetZ, extra, data, force -+ ); -+ return this; -+ } -+ -+ /** -+ * @return The particle going to be sent -+ */ -+ @NotNull -+ public Particle particle() { -+ return particle; -+ } -+ -+ /** -+ * Changes what particle will be sent -+ * -+ * @param particle The particle -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder particle(@NotNull Particle particle) { -+ this.particle = particle; -+ return this; -+ } -+ -+ /** -+ * @return List of players who will receive the particle, or null for all in world -+ */ -+ @Nullable -+ public List receivers() { -+ return receivers; -+ } -+ -+ /** -+ * Example use: -+ * -+ * builder.receivers(16); if (builder.hasReceivers()) { sendParticleAsync(builder); } -+ * -+ * @return If this particle is going to be sent to someone -+ */ -+ public boolean hasReceivers() { -+ return (receivers == null && !location.getWorld().getPlayers().isEmpty()) || ( -+ receivers != null && !receivers.isEmpty()); -+ } -+ -+ /** -+ * Sends this particle to all players in the world. This is rather silly and you should likely not -+ * be doing this. -+ * -+ * Just be a logical person and use receivers by radius or collection. -+ * -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder allPlayers() { -+ this.receivers = null; -+ return this; -+ } -+ -+ /** -+ * @param receivers List of players to receive this particle, or null for all players in the -+ * world -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(@Nullable List receivers) { -+ // Had to keep this as we first made API List<> and not Collection, but removing this may break plugins compiled on older jars -+ // TODO: deprecate? -+ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null; -+ return this; -+ } -+ -+ /** -+ * @param receivers List of players to receive this particle, or null for all players in the -+ * world -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(@Nullable Collection receivers) { -+ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null; -+ return this; -+ } -+ -+ /** -+ * @param receivers List of players to be receive this particle, or null for all players in the -+ * world -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(@Nullable Player... receivers) { -+ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null; -+ return this; -+ } -+ -+ /** -+ * Selects all players within a cuboid selection around the particle location, within the -+ * specified bounding box. If you want a more spherical check, see {@link #receivers(int, -+ * boolean)} -+ * -+ * @param radius amount to add on all axis -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(int radius) { -+ return receivers(radius, radius); -+ } -+ -+ /** -+ * Selects all players within the specified radius around the particle location. If byDistance is -+ * false, behavior uses cuboid selection the same as {@link #receivers(int, int)} If byDistance is -+ * true, radius is tested by distance in a spherical shape -+ * -+ * @param radius amount to add on each axis -+ * @param byDistance true to use a spherical radius, false to use a cuboid -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(int radius, boolean byDistance) { -+ if (!byDistance) { -+ return receivers(radius, radius, radius); -+ } else { -+ this.receivers = Lists.newArrayList(); -+ for (Player nearbyPlayer : location.getWorld() -+ .getNearbyPlayers(location, radius, radius, radius)) { -+ Location loc = nearbyPlayer.getLocation(); -+ double x = NumberConversions.square(location.getX() - loc.getX()); -+ double y = NumberConversions.square(location.getY() - loc.getY()); -+ double z = NumberConversions.square(location.getZ() - loc.getZ()); -+ if (Math.sqrt(x + y + z) > radius) { -+ continue; -+ } -+ this.receivers.add(nearbyPlayer); -+ } -+ return this; -+ } -+ } -+ -+ /** -+ * Selects all players within a cuboid selection around the particle location, within the -+ * specified bounding box. Allows specifying a different Y size than X and Z If you want a more -+ * cylinder check, see {@link #receivers(int, int, boolean)} If you want a more spherical check, -+ * see {@link #receivers(int, boolean)} -+ * -+ * @param xzRadius amount to add on the x/z axis -+ * @param yRadius amount to add on the y axis -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(int xzRadius, int yRadius) { -+ return receivers(xzRadius, yRadius, xzRadius); -+ } -+ -+ /** -+ * Selects all players within the specified radius around the particle location. If byDistance is -+ * false, behavior uses cuboid selection the same as {@link #receivers(int, int)} If byDistance is -+ * true, radius is tested by distance on the y plane and on the x/z plane, in a cylinder shape. -+ * -+ * @param xzRadius amount to add on the x/z axis -+ * @param yRadius amount to add on the y axis -+ * @param byDistance true to use a cylinder shape, false to use cuboid -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(int xzRadius, int yRadius, boolean byDistance) { -+ if (!byDistance) { -+ return receivers(xzRadius, yRadius, xzRadius); -+ } else { -+ this.receivers = Lists.newArrayList(); -+ for (Player nearbyPlayer : location.getWorld() -+ .getNearbyPlayers(location, xzRadius, yRadius, xzRadius)) { -+ Location loc = nearbyPlayer.getLocation(); -+ if (Math.abs(loc.getY() - this.location.getY()) > yRadius) { -+ continue; -+ } -+ double x = NumberConversions.square(location.getX() - loc.getX()); -+ double z = NumberConversions.square(location.getZ() - loc.getZ()); -+ if (x + z > NumberConversions.square(xzRadius)) { -+ continue; -+ } -+ this.receivers.add(nearbyPlayer); -+ } -+ return this; -+ } -+ } -+ -+ /** -+ * Selects all players within a cuboid selection around the particle location, within the -+ * specified bounding box. If you want a more cylinder check, see {@link #receivers(int, int, -+ * boolean)} If you want a more spherical check, see {@link #receivers(int, boolean)} -+ * -+ * @param xRadius amount to add on the x axis -+ * @param yRadius amount to add on the y axis -+ * @param zRadius amount to add on the z axis -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(int xRadius, int yRadius, int zRadius) { -+ if (location == null) { -+ throw new IllegalStateException("Please set location first"); -+ } -+ return receivers(location.getWorld().getNearbyPlayers(location, xRadius, yRadius, zRadius)); -+ } -+ -+ /** -+ * @return The player considered the source of this particle (for Visibility concerns), or null -+ */ -+ @Nullable -+ public Player source() { -+ return source; -+ } -+ -+ /** -+ * Sets the source of this particle for visibility concerns (Vanish API) -+ * -+ * @param source The player who is considered the source -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder source(@Nullable Player source) { -+ this.source = source; -+ return this; -+ } -+ -+ /** -+ * @return Location of where the particle will spawn -+ */ -+ @Nullable -+ public Location location() { -+ return location; -+ } -+ -+ /** -+ * Sets the location of where to spawn the particle -+ * -+ * @param location The location of the particle -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder location(@NotNull Location location) { -+ this.location = location.clone(); -+ return this; -+ } -+ -+ /** -+ * Sets the location of where to spawn the particle -+ * -+ * @param world World to spawn particle in -+ * @param x X location -+ * @param y Y location -+ * @param z Z location -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder location(@NotNull World world, double x, double y, double z) { -+ this.location = new Location(world, x, y, z); -+ return this; -+ } -+ -+ /** -+ * @return Number of particles to spawn -+ */ -+ public int count() { -+ return count; -+ } -+ -+ /** -+ * Sets the number of particles to spawn -+ * -+ * @param count Number of particles -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder count(int count) { -+ this.count = count; -+ return this; -+ } -+ -+ /** -+ * Particle offset X. Varies by particle on how this is used -+ * -+ * @return Particle offset X. -+ */ -+ public double offsetX() { -+ return offsetX; -+ } -+ -+ /** -+ * Particle offset Y. Varies by particle on how this is used -+ * -+ * @return Particle offset Y. -+ */ -+ public double offsetY() { -+ return offsetY; -+ } -+ -+ /** -+ * Particle offset Z. Varies by particle on how this is used -+ * -+ * @return Particle offset Z. -+ */ -+ public double offsetZ() { -+ return offsetZ; -+ } -+ -+ /** -+ * Sets the particle offset. Varies by particle on how this is used -+ * -+ * @param offsetX Particle offset X -+ * @param offsetY Particle offset Y -+ * @param offsetZ Particle offset Z -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder offset(double offsetX, double offsetY, double offsetZ) { -+ this.offsetX = offsetX; -+ this.offsetY = offsetY; -+ this.offsetZ = offsetZ; -+ return this; -+ } -+ -+ /** -+ * Gets the Particle extra data. Varies by particle on how this is used -+ * -+ * @return the extra particle data -+ */ -+ public double extra() { -+ return extra; -+ } -+ -+ /** -+ * Sets the particle extra data. Varies by particle on how this is used -+ * -+ * @param extra the extra particle data -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder extra(double extra) { -+ this.extra = extra; -+ return this; -+ } -+ -+ /** -+ * Gets the particle custom data. Varies by particle on how this is used -+ * -+ * @param The Particle data type -+ * @return the ParticleData for this particle -+ */ -+ @Nullable -+ public T data() { -+ //noinspection unchecked -+ return (T) data; -+ } -+ -+ /** -+ * Sets the particle custom data. Varies by particle on how this is used -+ * -+ * @param data The new particle data -+ * @param The Particle data type -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder data(@Nullable T data) { -+ this.data = data; -+ return this; -+ } -+ -+ /** -+ * Sets whether the particle is forcefully shown to the player. If forced, the particle will show -+ * faraway, as far as the player's view distance allows. If false, the particle will show -+ * according to the client's particle settings. -+ * -+ * @param force true to force, false for normal -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder force(boolean force) { -+ this.force = force; -+ return this; -+ } -+ -+ /** -+ * Sets the particle Color. Only valid for REDSTONE. -+ * -+ * @param color the new particle color -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder color(@Nullable Color color) { -+ return color(color, 1); -+ } -+ -+ /** -+ * Sets the particle Color and size. Only valid for REDSTONE. -+ * -+ * @param color the new particle color -+ * @param size the size of the particle -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder color(@Nullable Color color, float size) { -+ if (particle != Particle.REDSTONE && color != null) { -+ throw new IllegalStateException("Color may only be set on REDSTONE"); -+ } -+ -+ // We don't officially support reusing these objects, but here we go -+ if (color == null) { -+ if (data instanceof Particle.DustOptions) { -+ return data(null); -+ } else { -+ return this; -+ } -+ } -+ -+ return data(new Particle.DustOptions(color, size)); -+ } -+ -+ /** -+ * Sets the particle Color. -+ * Only valid for REDSTONE. -+ * @param r red color component -+ * @param g green color component -+ * @param b blue color component -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder color(int r, int g, int b) { -+ return color(Color.fromRGB(r, g, b)); -+ } -+} -diff --git a/src/main/java/org/bukkit/Particle.java b/src/main/java/org/bukkit/Particle.java -index c5315ee1ed435c39a3ae298e248b67c5dc291497..687a62707c8021f87e03d6bc358b3b4e6da331e7 100644 ---- a/src/main/java/org/bukkit/Particle.java -+++ b/src/main/java/org/bukkit/Particle.java -@@ -123,6 +123,17 @@ public enum Particle { - return dataType; - } - -+ // Paper start - Particle API expansion -+ /** -+ * Creates a {@link com.destroystokyo.paper.ParticleBuilder} -+ * -+ * @return a {@link com.destroystokyo.paper.ParticleBuilder} for the particle -+ */ -+ @NotNull -+ public com.destroystokyo.paper.ParticleBuilder builder() { -+ return new com.destroystokyo.paper.ParticleBuilder(this); -+ } -+ // Paper end - /** - * Options which can be applied to redstone dust particles - a particle - * color and size. -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 6cc9c7fc913f229c4869a976e73253acb74fcda3..ca2b1cbff153c53ec9182e44a1979350bacd695b 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -2592,7 +2592,57 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - * @param data the data to use for the particle or null, - * the type of this depends on {@link Particle#getDataType()} - */ -- public void spawnParticle(@NotNull Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data); -+ public default void spawnParticle(@NotNull Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data) { spawnParticle(particle, null, null, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, true); }// Paper start - Expand Particle API -+ /** -+ * Spawns the particle (the number of times specified by count) -+ * at the target location. The position of each particle will be -+ * randomized positively and negatively by the offset parameters -+ * on each axis. -+ * -+ * @param particle the particle to spawn -+ * @param receivers List of players to receive the particles, or null for all in world -+ * @param source Source of the particles to be used in visibility checks, or null if no player source -+ * @param x the position on the x axis to spawn at -+ * @param y the position on the y axis to spawn at -+ * @param z the position on the z axis to spawn at -+ * @param count the number of particles -+ * @param offsetX the maximum random offset on the X axis -+ * @param offsetY the maximum random offset on the Y axis -+ * @param offsetZ the maximum random offset on the Z axis -+ * @param extra the extra data for this particle, depends on the -+ * particle used (normally speed) -+ * @param data the data to use for the particle or null, -+ * the type of this depends on {@link Particle#getDataType()} -+ * @param Type -+ */ -+ public default void spawnParticle(@NotNull Particle particle, @Nullable List receivers, @NotNull Player source, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data) { spawnParticle(particle, receivers, source, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, true); } -+ /** -+ * Spawns the particle (the number of times specified by count) -+ * at the target location. The position of each particle will be -+ * randomized positively and negatively by the offset parameters -+ * on each axis. -+ * -+ * @param particle the particle to spawn -+ * @param receivers List of players to receive the particles, or null for all in world -+ * @param source Source of the particles to be used in visibility checks, or null if no player source -+ * @param x the position on the x axis to spawn at -+ * @param y the position on the y axis to spawn at -+ * @param z the position on the z axis to spawn at -+ * @param count the number of particles -+ * @param offsetX the maximum random offset on the X axis -+ * @param offsetY the maximum random offset on the Y axis -+ * @param offsetZ the maximum random offset on the Z axis -+ * @param extra the extra data for this particle, depends on the -+ * particle used (normally speed) -+ * @param data the data to use for the particle or null, -+ * the type of this depends on {@link Particle#getDataType()} -+ * @param Type -+ * @param force allows the particle to be seen further away from the player -+ * and shows to players using any vanilla client particle settings -+ */ -+ public void spawnParticle(@NotNull Particle particle, @Nullable List receivers, @Nullable Player source, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data, boolean force); -+ // Paper end -+ - - /** - * Spawns the particle (the number of times specified by count) diff --git a/Unmapped-Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch b/Unmapped-Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch deleted file mode 100644 index 9f3e105c9d..0000000000 --- a/Unmapped-Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 May 2018 20:17:44 -0400 -Subject: [PATCH] EndermanAttackPlayerEvent - -Allow control over whether or not an enderman aggros a player. - -This allows you to override/extend the pumpkin/stare logic. - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f530a3d9314e17d1da896cac633f6a422258d9a9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java -@@ -0,0 +1,101 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Enderman; -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when an Enderman determines if it should attack a player or not. -+ * Starts off cancelled if the player is wearing a pumpkin head or is not looking -+ * at the Enderman, according to Vanilla rules. -+ * -+ */ -+public class EndermanAttackPlayerEvent extends EntityEvent implements Cancellable { -+ @NotNull private final Player player; -+ -+ public EndermanAttackPlayerEvent(@NotNull Enderman entity, @NotNull Player player) { -+ super(entity); -+ this.player = player; -+ } -+ -+ /** -+ * The enderman considering attacking -+ * -+ * @return The enderman considering attacking -+ */ -+ @NotNull -+ @Override -+ public Enderman getEntity() { -+ return (Enderman) super.getEntity(); -+ } -+ -+ /** -+ * The player the Enderman is considering attacking -+ * -+ * @return The player the Enderman is considering attacking -+ */ -+ @NotNull -+ public Player getPlayer() { -+ return player; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ /** -+ * -+ * @return If cancelled, the enderman will not attack -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Cancels if the Enderman will attack this player -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch b/Unmapped-Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch deleted file mode 100644 index 6580fe3c76..0000000000 --- a/Unmapped-Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 May 2018 21:33:35 -0400 -Subject: [PATCH] Close Plugin Class Loaders on Disable - -This should close more memory leaks from /reload and disabling plugins, -by closing the class loader and the jar file. - -diff --git a/src/main/java/org/bukkit/plugin/PluginLoader.java b/src/main/java/org/bukkit/plugin/PluginLoader.java -index a88733f1cd1ddb5d85ab1b0e6af4fd5b80bbc1c6..6ab9cd8213cbe35943748dcf42948d5fc048c84c 100644 ---- a/src/main/java/org/bukkit/plugin/PluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/PluginLoader.java -@@ -77,4 +77,18 @@ public interface PluginLoader { - * @param plugin Plugin to disable - */ - public void disablePlugin(@NotNull Plugin plugin); -+ // Paper start - close Classloader on disable -+ /** -+ * Disables the specified plugin -+ *

    -+ * Attempting to disable a plugin that is not enabled will have no effect -+ * -+ * @param plugin Plugin to disable -+ * @param closeClassloader if the classloader for the Plugin should be closed -+ */ -+ // provide default to allow other PluginLoader implementations to work -+ default public void disablePlugin(@NotNull Plugin plugin, boolean closeClassloader) { -+ disablePlugin(plugin); -+ } -+ // Paper end - close Classloader on disable - } -diff --git a/src/main/java/org/bukkit/plugin/PluginManager.java b/src/main/java/org/bukkit/plugin/PluginManager.java -index 41e26451fe12d8e6e0ef73c85731b24b4e3f200c..86cc5025ad98f7a752c51713b7cd6a39d5136ecc 100644 ---- a/src/main/java/org/bukkit/plugin/PluginManager.java -+++ b/src/main/java/org/bukkit/plugin/PluginManager.java -@@ -161,6 +161,18 @@ public interface PluginManager { - */ - public void disablePlugin(@NotNull Plugin plugin); - -+ // Paper start - close Classloader on disable -+ /** -+ * Disables the specified plugin -+ *

    -+ * Attempting to disable a plugin that is not enabled will have no effect -+ * -+ * @param plugin Plugin to disable -+ * @param closeClassloader if the classloader for the Plugin should be closed -+ */ -+ public void disablePlugin(@NotNull Plugin plugin, boolean closeClassloader); -+ // Paper end - close Classloader on disable -+ - /** - * Gets a {@link Permission} from its fully qualified name - * -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 8b33d914d29897c0276f9e2e7ce83bd2c316d5e2..a7393d2830b95d7167121b02066a3f357cee6085 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -492,17 +492,28 @@ public final class SimplePluginManager implements PluginManager { - - @Override - public void disablePlugins() { -+ disablePlugins(false); -+ } -+ -+ public void disablePlugins(boolean closeClassloaders) { -+ // Paper end - close Classloader on disable - Plugin[] plugins = getPlugins(); - for (int i = plugins.length - 1; i >= 0; i--) { -- disablePlugin(plugins[i]); -+ disablePlugin(plugins[i], closeClassloaders); // Paper - close Classloader on disable - } - } - - @Override - public void disablePlugin(@NotNull final Plugin plugin) { -+ disablePlugin(plugin, false); -+ } -+ -+ @Override -+ public void disablePlugin(@NotNull final Plugin plugin, boolean closeClassloader) { -+ // Paper end - close Classloader on disable - if (plugin.isEnabled()) { - try { -- plugin.getPluginLoader().disablePlugin(plugin); -+ plugin.getPluginLoader().disablePlugin(plugin, closeClassloader); // Paper - close Classloader on disable - } catch (Throwable ex) { - handlePluginException("Error occurred (in the plugin loader) while disabling " - + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper -@@ -557,7 +568,7 @@ public final class SimplePluginManager implements PluginManager { - @Override - public void clearPlugins() { - synchronized (this) { -- disablePlugins(); -+ disablePlugins(true); // Paper - close Classloader on disable - plugins.clear(); - lookupNames.clear(); - dependencyGraph = GraphBuilder.directed().build(); -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 79ac529017aac059d13fe342f279e9c8faeba599..816c2b1797447ab315ceb6eda89d25f27d2bce98 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -322,7 +322,7 @@ public final class JavaPluginLoader implements PluginLoader { - } catch (Throwable ex) { - server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); - // Paper start - Disable plugins that fail to load -- disablePlugin(jPlugin); -+ server.getPluginManager().disablePlugin(jPlugin, true); // Paper - close Classloader on disable - She's dead jim - return; - // Paper end - } -@@ -335,6 +335,12 @@ public final class JavaPluginLoader implements PluginLoader { - - @Override - public void disablePlugin(@NotNull Plugin plugin) { -+ // Paper start - close Classloader on disable -+ disablePlugin(plugin, false); // Retain old behavior unless requested -+ } -+ -+ public void disablePlugin(@NotNull Plugin plugin, boolean closeClassloader) { -+ // Paper end - close Class Loader on disable - Validate.isTrue(plugin instanceof JavaPlugin, "Plugin is not associated with this PluginLoader"); - - if (plugin.isEnabled()) { -@@ -367,6 +373,16 @@ public final class JavaPluginLoader implements PluginLoader { - } catch (IOException ex) { - // - } -+ // Paper start - close Class Loader on disable -+ try { -+ if (closeClassloader) { -+ loader.close(); -+ } -+ } catch (IOException e) { -+ server.getLogger().log(Level.WARNING, "Error closing the Plugin Class Loader for " + plugin.getDescription().getFullName()); -+ e.printStackTrace(); -+ } -+ // Paper end - } - } - } diff --git a/Unmapped-Spigot-API-Patches/0100-WitchConsumePotionEvent.patch b/Unmapped-Spigot-API-Patches/0100-WitchConsumePotionEvent.patch deleted file mode 100644 index fab6106411..0000000000 --- a/Unmapped-Spigot-API-Patches/0100-WitchConsumePotionEvent.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 16 May 2018 20:26:16 -0400 -Subject: [PATCH] WitchConsumePotionEvent - -Fires when a witch consumes the potion in their hand - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchConsumePotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchConsumePotionEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fbbace36d69373046a7f3618ed5c1c1318b489b9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchConsumePotionEvent.java -@@ -0,0 +1,70 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Witch; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Fired when a witch consumes the potion in their hand to buff themselves. -+ */ -+public class WitchConsumePotionEvent extends EntityEvent implements Cancellable { -+ @Nullable private ItemStack potion; -+ -+ public WitchConsumePotionEvent(@NotNull Witch witch, @Nullable ItemStack potion) { -+ super(witch); -+ this.potion = potion; -+ } -+ -+ @NotNull -+ @Override -+ public Witch getEntity() { -+ return (Witch) super.getEntity(); -+ } -+ -+ /** -+ * @return the potion the witch will consume and have the effects applied. -+ */ -+ @Nullable -+ public ItemStack getPotion() { -+ return potion; -+ } -+ -+ /** -+ * Sets the potion to be consumed and applied to the witch. -+ * @param potion The potion -+ */ -+ public void setPotion(@Nullable ItemStack potion) { -+ this.potion = potion != null ? potion.clone() : null; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ /** -+ * @return Event was cancelled or potion was null -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled || potion == null; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6ef6367b67261c2b653a97322b9703a9409b3499 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java -@@ -0,0 +1,33 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+public class WitchThrowPotionEvent extends Event implements Cancellable { -+ public WitchThrowPotionEvent() { -+ } -+ -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0101-WitchThrowPotionEvent.patch b/Unmapped-Spigot-API-Patches/0101-WitchThrowPotionEvent.patch deleted file mode 100644 index a5dfe42f35..0000000000 --- a/Unmapped-Spigot-API-Patches/0101-WitchThrowPotionEvent.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 16 May 2018 20:39:09 -0400 -Subject: [PATCH] WitchThrowPotionEvent - -Fired when a witch throws a potion at a player - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java -index 6ef6367b67261c2b653a97322b9703a9409b3499..688a596aa2b925651a92bf092e1ef4d77a47258c 100644 ---- a/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java -+++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java -@@ -1,29 +1,77 @@ - package com.destroystokyo.paper.event.entity; - -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Witch; - import org.bukkit.event.Cancellable; --import org.bukkit.event.Event; - import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; - --public class WitchThrowPotionEvent extends Event implements Cancellable { -- public WitchThrowPotionEvent() { -+/** -+ * Fired when a witch throws a potion at a player -+ */ -+public class WitchThrowPotionEvent extends EntityEvent implements Cancellable { -+ @NotNull private final LivingEntity target; -+ @Nullable private ItemStack potion; -+ -+ public WitchThrowPotionEvent(@NotNull Witch witch, @NotNull LivingEntity target, @Nullable ItemStack potion) { -+ super(witch); -+ this.target = target; -+ this.potion = potion; - } - -+ @NotNull -+ @Override -+ public Witch getEntity() { -+ return (Witch) super.getEntity(); -+ } -+ -+ /** -+ * @return The target of the potion -+ */ -+ @NotNull -+ public LivingEntity getTarget() { -+ return target; -+ } -+ -+ /** -+ * @return The potion the witch will throw at a player -+ */ -+ @Nullable -+ public ItemStack getPotion() { -+ return potion; -+ } -+ -+ /** -+ * Sets the potion to be thrown at a player -+ * @param potion The potion -+ */ -+ public void setPotion(@Nullable ItemStack potion) { -+ this.potion = potion != null ? potion.clone() : null; -+ } - - private static final HandlerList handlers = new HandlerList(); - -+ @NotNull - public HandlerList getHandlers() { - return handlers; - } - -+ @NotNull - public static HandlerList getHandlerList() { - return handlers; - } - - private boolean cancelled = false; - -+ /** -+ * @return Event was cancelled or potion was null -+ */ - @Override - public boolean isCancelled() { -- return cancelled; -+ return cancelled || potion == null; - } - - @Override diff --git a/Unmapped-Spigot-API-Patches/0102-Location.toBlockLocation-toCenterLocation.patch b/Unmapped-Spigot-API-Patches/0102-Location.toBlockLocation-toCenterLocation.patch deleted file mode 100644 index 1f3ad622a7..0000000000 --- a/Unmapped-Spigot-API-Patches/0102-Location.toBlockLocation-toCenterLocation.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 24 May 2018 21:01:13 -0400 -Subject: [PATCH] Location.toBlockLocation/toCenterLocation() - -Convert location objects to their block coordinates, or the center of the block - -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index 6c8b8eddcdb81f7151202eb12541308040790d45..f61bf28afe99f83cdac6490bcc114509698d0aad 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -534,6 +534,31 @@ public class Location implements Cloneable, ConfigurationSerializable { - } - - public boolean isChunkLoaded() { return this.getWorld().isChunkLoaded(locToBlock(x) >> 4, locToBlock(z) >> 4); } // Paper -+ -+ // Paper start -+ /** -+ * @return A new location where X/Y/Z are on the Block location (integer value of X/Y/Z) -+ */ -+ @NotNull -+ public Location toBlockLocation() { -+ Location blockLoc = clone(); -+ blockLoc.setX(getBlockX()); -+ blockLoc.setY(getBlockY()); -+ blockLoc.setZ(getBlockZ()); -+ return blockLoc; -+ } -+ /** -+ * @return A new location where X/Y/Z are the center of the block -+ */ -+ @NotNull -+ public Location toCenterLocation() { -+ Location centerLoc = clone(); -+ centerLoc.setX(getBlockX() + 0.5); -+ centerLoc.setY(getBlockY() + 0.5); -+ centerLoc.setZ(getBlockZ() + 0.5); -+ return centerLoc; -+ } -+ // Paper end - @Override - public boolean equals(Object obj) { - if (obj == null) { diff --git a/Unmapped-Spigot-API-Patches/0103-PotionEffect-clone-methods.patch b/Unmapped-Spigot-API-Patches/0103-PotionEffect-clone-methods.patch deleted file mode 100644 index 7f4e064a78..0000000000 --- a/Unmapped-Spigot-API-Patches/0103-PotionEffect-clone-methods.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 Jun 2018 04:10:13 -0400 -Subject: [PATCH] PotionEffect clone methods - - -diff --git a/src/main/java/org/bukkit/potion/PotionEffect.java b/src/main/java/org/bukkit/potion/PotionEffect.java -index 60716c627d315b08c3fe03b1a945af60c350711f..74767751199bce03d63f2a9524712656193f850c 100644 ---- a/src/main/java/org/bukkit/potion/PotionEffect.java -+++ b/src/main/java/org/bukkit/potion/PotionEffect.java -@@ -101,6 +101,33 @@ public class PotionEffect implements ConfigurationSerializable { - this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT, false), getBool(map, PARTICLES, true), getBool(map, ICON, getBool(map, PARTICLES, true))); - } - -+ // Paper start -+ @NotNull -+ public PotionEffect withType(@NotNull PotionEffectType type) { -+ return new PotionEffect(type, duration, amplifier, ambient, particles, icon); -+ } -+ @NotNull -+ public PotionEffect withDuration(int duration) { -+ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); -+ } -+ @NotNull -+ public PotionEffect withAmplifier(int amplifier) { -+ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); -+ } -+ @NotNull -+ public PotionEffect withAmbient(boolean ambient) { -+ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); -+ } -+ @NotNull -+ public PotionEffect withParticles(boolean particles) { -+ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); -+ } -+ @NotNull -+ public PotionEffect withIcon(boolean icon) { -+ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); -+ } -+ // Paper end -+ - @NotNull - private static PotionEffectType getEffectType(@NotNull Map map) { - int type = getInt(map, TYPE); diff --git a/Unmapped-Spigot-API-Patches/0104-WitchReadyPotionEvent.patch b/Unmapped-Spigot-API-Patches/0104-WitchReadyPotionEvent.patch deleted file mode 100644 index 5722426049..0000000000 --- a/Unmapped-Spigot-API-Patches/0104-WitchReadyPotionEvent.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 22:47:08 -0400 -Subject: [PATCH] WitchReadyPotionEvent - -Control what potion the witch readies to use - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchReadyPotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchReadyPotionEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5351b523defa054ba56ae3fb591029283ca7510d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchReadyPotionEvent.java -@@ -0,0 +1,80 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.Material; -+import org.bukkit.entity.Witch; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class WitchReadyPotionEvent extends EntityEvent implements Cancellable { -+ private ItemStack potion; -+ -+ public WitchReadyPotionEvent(@NotNull Witch witch, @Nullable ItemStack potion) { -+ super(witch); -+ this.potion = potion; -+ } -+ -+ /** -+ * Fires thee event, returning the desired potion, or air of cancelled -+ * @param witch the witch whom is readying to use a potion -+ * @param potion the potion to be used -+ * @return The ItemStack to be used -+ */ -+ @Nullable -+ public static ItemStack process(@NotNull Witch witch, @Nullable ItemStack potion) { -+ WitchReadyPotionEvent event = new WitchReadyPotionEvent(witch, potion); -+ if (!event.callEvent() || event.getPotion() == null) { -+ return new ItemStack(Material.AIR); -+ } -+ return event.getPotion(); -+ } -+ -+ @NotNull -+ @Override -+ public Witch getEntity() { -+ return (Witch) super.getEntity(); -+ } -+ -+ /** -+ * @return the potion the witch is readying to use -+ */ -+ @Nullable -+ public ItemStack getPotion() { -+ return potion; -+ } -+ -+ /** -+ * Sets the potion the which is going to hold and use -+ * @param potion The potion -+ */ -+ public void setPotion(@Nullable ItemStack potion) { -+ this.potion = potion != null ? potion.clone() : null; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch b/Unmapped-Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch deleted file mode 100644 index b00193d717..0000000000 --- a/Unmapped-Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 22:59:50 -0400 -Subject: [PATCH] ItemStack#getMaxItemUseDuration - -Allows you to determine how long it takes to use a usable/consumable item - -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 82bd3e6701dbd7df9f0f8c3801c5ae1baba4eec5..f41701e6374ca23eca4bdb092e385053a12eb718 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -636,5 +636,13 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public String getI18NDisplayName() { - return Bukkit.getServer().getItemFactory().getI18NDisplayName(this); - } -+ -+ public int getMaxItemUseDuration() { -+ if (type == null || type == Material.AIR || !type.isItem()) { -+ return 0; -+ } -+ // Requires access to NMS -+ return ensureServerConversions().getMaxItemUseDuration(); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch b/Unmapped-Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch deleted file mode 100644 index 0422ec9858..0000000000 --- a/Unmapped-Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 9 Jun 2018 13:08:21 +0100 -Subject: [PATCH] Add EntityTeleportEndGatewayEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityTeleportEndGatewayEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityTeleportEndGatewayEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..bfc69a43c291fbed91b9d0387e4ef18b0ed1b9de ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityTeleportEndGatewayEvent.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.Location; -+import org.bukkit.block.EndGateway; -+import org.bukkit.entity.Entity; -+import org.bukkit.event.entity.EntityTeleportEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired any time an entity attempts to teleport in an end gateway -+ */ -+public class EntityTeleportEndGatewayEvent extends EntityTeleportEvent { -+ -+ @NotNull private final EndGateway gateway; -+ -+ public EntityTeleportEndGatewayEvent(@NotNull Entity what, @NotNull Location from, @NotNull Location to, @NotNull EndGateway gateway) { -+ super(what, from, to); -+ this.gateway = gateway; -+ } -+ -+ /** -+ * The gateway triggering the teleport -+ * -+ * @return EndGateway used -+ */ -+ @NotNull -+ public EndGateway getGateway() { -+ return gateway; -+ } -+ -+} diff --git a/Unmapped-Spigot-API-Patches/0107-Make-shield-blocking-delay-configurable.patch b/Unmapped-Spigot-API-Patches/0107-Make-shield-blocking-delay-configurable.patch deleted file mode 100644 index cec33b7a78..0000000000 --- a/Unmapped-Spigot-API-Patches/0107-Make-shield-blocking-delay-configurable.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 16 Jun 2018 01:17:39 -0500 -Subject: [PATCH] Make shield blocking delay configurable - - -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 33fffda7c8b05cde3c95623937e7eb6c8b628ec6..879dec59f202ee95043bd7317a672cd59ab3bbbe 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -628,5 +628,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - * @param arrows Number of arrows to stick in this entity - */ - void setArrowsStuck(int arrows); -+ -+ /** -+ * Get the delay (in ticks) before blocking is effective for this entity -+ * -+ * @return Delay in ticks -+ */ -+ int getShieldBlockingDelay(); -+ -+ /** -+ * Set the delay (in ticks) before blocking is effective for this entity -+ * -+ * @param delay Delay in ticks -+ */ -+ void setShieldBlockingDelay(int delay); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch b/Unmapped-Spigot-API-Patches/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch deleted file mode 100644 index 71a82a8eae..0000000000 --- a/Unmapped-Spigot-API-Patches/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 15 Jun 2013 19:52:04 -0400 -Subject: [PATCH] EntityShootBowEvent consumeArrow and getArrowItem API - -Adds ability to get what arrow was shot, and control if it should be consumed. - -diff --git a/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java b/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java -index d4d7ad9c3c953680342c121f39ddaef476549047..719d0d878320c1903b44076053989ba99fa0e92a 100644 ---- a/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java -+++ b/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java -@@ -22,7 +22,32 @@ public class EntityShootBowEvent extends EntityEvent implements Cancellable { - private final float force; - private boolean consumeItem; - private boolean cancelled; -+ // Paper start -+ @Deprecated -+ public void setConsumeArrow(boolean consumeArrow) { -+ this.setConsumeItem(consumeArrow); -+ } -+ -+ @Deprecated -+ public boolean getConsumeArrow() { -+ return this.shouldConsumeItem(); -+ } -+ -+ @NotNull @Deprecated -+ public ItemStack getArrowItem() { -+ return this.getConsumable(); -+ } -+ -+ @Deprecated -+ public EntityShootBowEvent(@NotNull final LivingEntity shooter, @Nullable final ItemStack bow, @NotNull final Entity projectile, final float force) { -+ this(shooter, bow, new ItemStack(org.bukkit.Material.AIR), projectile, force); -+ } - -+ @Deprecated -+ public EntityShootBowEvent(@NotNull final LivingEntity shooter, @Nullable final ItemStack bow, @NotNull ItemStack arrowItem, @NotNull final Entity projectile, final float force) { -+ this(shooter, bow, arrowItem, projectile, EquipmentSlot.HAND, force, true); -+ } -+ // Paper end - public EntityShootBowEvent(@NotNull final LivingEntity shooter, @Nullable final ItemStack bow, @Nullable final ItemStack consumable, @NotNull final Entity projectile, @NotNull final EquipmentSlot hand, final float force, final boolean consumeItem) { - super(shooter); - this.bow = bow; diff --git a/Unmapped-Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch b/Unmapped-Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch deleted file mode 100644 index a362af6260..0000000000 --- a/Unmapped-Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch +++ /dev/null @@ -1,275 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 18 Jun 2018 00:41:46 -0500 -Subject: [PATCH] Add "getNearbyXXX" methods to Location - - -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index f61bf28afe99f83cdac6490bcc114509698d0aad..4cf22afc3c1f1cc19b6e5350043431215908a612 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -12,6 +12,15 @@ import org.bukkit.util.Vector; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - -+// Paper start -+import java.util.Collection; -+import java.util.Collections; -+import java.util.function.Predicate; -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Player; -+// Paper end -+ - /** - * Represents a 3-dimensional position in a world. - *
    -@@ -558,6 +567,248 @@ public class Location implements Cloneable, ConfigurationSerializable { - centerLoc.setZ(getBlockZ() + 0.5); - return centerLoc; - } -+ -+ /** -+ * Returns a list of entities within a bounding box centered around a Location. -+ * -+ * Some implementations may impose artificial restrictions on the size of the search bounding box. -+ * -+ * @param x 1/2 the size of the box along x axis -+ * @param y 1/2 the size of the box along y axis -+ * @param z 1/2 the size of the box along z axis -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntities(double x, double y, double z) { -+ World world = this.getWorld(); -+ if (world == null) { -+ throw new IllegalArgumentException("Location has no world"); -+ } -+ return world.getNearbyEntities(this, x, y, z); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param radius X Radius -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyLivingEntities(double radius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, radius, radius, radius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyLivingEntities(double xzRadius, double yRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, xzRadius, yRadius, xzRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z radius -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyLivingEntities(double xRadius, double yRadius, double zRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, xRadius, yRadius, zRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param radius Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyLivingEntities(double radius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, radius, radius, radius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyLivingEntities(double xzRadius, double yRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, xzRadius, yRadius, xzRadius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyLivingEntities(double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, xRadius, yRadius, zRadius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param radius X/Y/Z Radius -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyPlayers(double radius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, radius, radius, radius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyPlayers(double xzRadius, double yRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, xzRadius, yRadius, xzRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyPlayers(double xRadius, double yRadius, double zRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, xRadius, yRadius, zRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param radius X/Y/Z Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyPlayers(double radius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, radius, radius, radius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyPlayers(double xzRadius, double yRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, xzRadius, yRadius, xzRadius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyPlayers(double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, xRadius, yRadius, zRadius, predicate); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param radius X/Y/Z radius to search within -+ * @param the entity type -+ * @return the collection of entities of type clazz near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double radius) { -+ return getNearbyEntitiesByType(clazz, radius, radius, radius, null); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box) -+ * @param clazz Type to filter by -+ * @param xzRadius X/Z radius to search within -+ * @param yRadius Y radius to search within -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double xzRadius, double yRadius) { -+ return getNearbyEntitiesByType(clazz, xzRadius, yRadius, xzRadius, null); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double xRadius, double yRadius, double zRadius) { -+ return getNearbyEntitiesByType(clazz, xRadius, yRadius, zRadius, null); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param radius X/Y/Z radius to search within -+ * @param predicate a predicate used to filter results -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double radius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(clazz, radius, radius, radius, predicate); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box) -+ * @param clazz Type to filter by -+ * @param xzRadius X/Z radius to search within -+ * @param yRadius Y radius to search within -+ * @param predicate a predicate used to filter results -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double xzRadius, double yRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(clazz, xzRadius, yRadius, xzRadius, predicate); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @param predicate a predicate used to filter results -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { -+ World world = this.getWorld(); -+ if (world == null) { -+ throw new IllegalArgumentException("Location has no world"); -+ } -+ return world.getNearbyEntitiesByType(clazz, this, xRadius, yRadius, zRadius, predicate); -+ } - // Paper end - @Override - public boolean equals(Object obj) { diff --git a/Unmapped-Spigot-API-Patches/0110-PlayerReadyArrowEvent.patch b/Unmapped-Spigot-API-Patches/0110-PlayerReadyArrowEvent.patch deleted file mode 100644 index 7ea1740581..0000000000 --- a/Unmapped-Spigot-API-Patches/0110-PlayerReadyArrowEvent.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 18 Jun 2018 01:09:27 -0400 -Subject: [PATCH] PlayerReadyArrowEvent - -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/com/destroystokyo/paper/event/player/PlayerReadyArrowEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerReadyArrowEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5d04a22fd6964d8d44a2aa069c9629722893b1f4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerReadyArrowEvent.java -@@ -0,0 +1,93 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player is firing a bow and the server is choosing an arrow to use. -+ */ -+public class PlayerReadyArrowEvent extends PlayerEvent implements Cancellable { -+ @NotNull private final ItemStack bow; -+ @NotNull private final ItemStack arrow; -+ -+ public PlayerReadyArrowEvent(@NotNull Player player, @NotNull ItemStack bow, @NotNull ItemStack arrow) { -+ super(player); -+ this.bow = bow; -+ this.arrow = arrow; -+ } -+ -+ /** -+ * @return the player is using to fire the arrow -+ */ -+ @NotNull -+ public ItemStack getBow() { -+ return bow; -+ } -+ -+ /** -+ * @return the arrow that is attempting to be used -+ */ -+ @NotNull -+ public ItemStack getArrow() { -+ return arrow; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ /** -+ * Whether or not use of this arrow is cancelled. On cancel, the server will try the next arrow available and fire another event. -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Cancel use of this arrow. On cancel, the server will try the next arrow available and fire another event. -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch b/Unmapped-Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch deleted file mode 100644 index 1620ab68a6..0000000000 --- a/Unmapped-Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Mon, 18 Jun 2018 15:40:39 +0200 -Subject: [PATCH] Add EntityKnockbackByEntityEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityKnockbackByEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityKnockbackByEntityEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9efecabab813f575bb447a356e5e7e952d110f30 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityKnockbackByEntityEvent.java -@@ -0,0 +1,82 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.util.Vector; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when an Entity is knocked back by the hit of another Entity. The acceleration -+ * vector can be modified. If this event is cancelled, the entity is not knocked back. -+ * -+ */ -+public class EntityKnockbackByEntityEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull private final Entity hitBy; -+ private final float knockbackStrength; -+ @NotNull private final Vector acceleration; -+ private boolean cancelled = false; -+ -+ public EntityKnockbackByEntityEvent(@NotNull LivingEntity entity, @NotNull Entity hitBy, float knockbackStrength, @NotNull Vector acceleration) { -+ super(entity); -+ this.hitBy = hitBy; -+ this.knockbackStrength = knockbackStrength; -+ this.acceleration = acceleration; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ /** -+ * @return the entity which was knocked back -+ */ -+ @NotNull -+ @Override -+ public LivingEntity getEntity() { -+ return (LivingEntity) super.getEntity(); -+ } -+ -+ /** -+ * @return the original knockback strength. -+ */ -+ public float getKnockbackStrength() { -+ return knockbackStrength; -+ } -+ -+ /** -+ * @return the Entity which hit -+ */ -+ @NotNull -+ public Entity getHitBy() { -+ return hitBy; -+ } -+ -+ /** -+ * @return the acceleration that will be applied -+ */ -+ @NotNull -+ public Vector getAcceleration() { -+ return acceleration; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0112-Expand-Explosions-API.patch b/Unmapped-Spigot-API-Patches/0112-Expand-Explosions-API.patch deleted file mode 100644 index 389fec9570..0000000000 --- a/Unmapped-Spigot-API-Patches/0112-Expand-Explosions-API.patch +++ /dev/null @@ -1,200 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 16:24:42 -0500 -Subject: [PATCH] Expand Explosions API - -Add Entity as a Source capability, and add more API choices, and on Location. - -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index 4cf22afc3c1f1cc19b6e5350043431215908a612..af2ee43f2c5133668c18710f526a107d94a5d898 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -7,6 +7,7 @@ import java.util.HashMap; - import java.util.Map; - import org.bukkit.block.Block; - import org.bukkit.configuration.serialization.ConfigurationSerializable; -+import org.bukkit.entity.Entity; // Paper - import org.bukkit.util.NumberConversions; - import org.bukkit.util.Vector; - import org.jetbrains.annotations.NotNull; -@@ -568,6 +569,87 @@ public class Location implements Cloneable, ConfigurationSerializable { - return centerLoc; - } - -+ /** -+ * Creates explosion at this location with given power -+ * -+ * Will break blocks and ignite blocks on fire. -+ * -+ * @param power The power of explosion, where 4F is TNT -+ * @return false if explosion was canceled, otherwise true -+ */ -+ public boolean createExplosion(float power) { -+ return this.getWorld().createExplosion(this, power); -+ } -+ -+ /** -+ * Creates explosion at this location with given power and optionally -+ * setting blocks on fire. -+ * -+ * Will break blocks. -+ * -+ * @param power The power of explosion, where 4F is TNT -+ * @param setFire Whether or not to set blocks on fire -+ * @return false if explosion was canceled, otherwise true -+ */ -+ public boolean createExplosion(float power, boolean setFire) { -+ return this.getWorld().createExplosion(this, power, setFire); -+ } -+ -+ /** -+ * Creates explosion at this location with given power and optionally -+ * setting blocks on fire. -+ * -+ * @param power The power of explosion, where 4F is TNT -+ * @param setFire Whether or not to set blocks on fire -+ * @param breakBlocks Whether or not to have blocks be destroyed -+ * @return false if explosion was canceled, otherwise true -+ */ -+ public boolean createExplosion(float power, boolean setFire, boolean breakBlocks) { -+ return this.getWorld().createExplosion(this, power, setFire, breakBlocks); -+ } -+ -+ /** -+ * Creates explosion at this location with given power, with the specified entity as the source. -+ * -+ * Will break blocks and ignite blocks on fire. -+ * -+ * @param source The source entity of the explosion -+ * @param power The power of explosion, where 4F is TNT -+ * @return false if explosion was canceled, otherwise true -+ */ -+ public boolean createExplosion(@Nullable Entity source, float power) { -+ return this.getWorld().createExplosion(source, this, power, true, true); -+ } -+ -+ /** -+ * Creates explosion at this location with given power and optionally -+ * setting blocks on fire, with the specified entity as the source. -+ * -+ * Will break blocks. -+ * -+ * @param source The source entity of the explosion -+ * @param power The power of explosion, where 4F is TNT -+ * @param setFire Whether or not to set blocks on fire -+ * @return false if explosion was canceled, otherwise true -+ */ -+ public boolean createExplosion(@Nullable Entity source, float power, boolean setFire) { -+ return this.getWorld().createExplosion(source, this, power, setFire, true); -+ } -+ -+ /** -+ * Creates explosion at this location with given power and optionally -+ * setting blocks on fire, with the specified entity as the source. -+ * -+ * @param source The source entity of the explosion -+ * @param power The power of explosion, where 4F is TNT -+ * @param setFire Whether or not to set blocks on fire -+ * @param breakBlocks Whether or not to have blocks be destroyed -+ * @return false if explosion was canceled, otherwise true -+ */ -+ public boolean createExplosion(@NotNull Entity source, float power, boolean setFire, boolean breakBlocks) { -+ return this.getWorld().createExplosion(source, this, power, setFire, breakBlocks); -+ } -+ - /** - * Returns a list of entities within a bounding box centered around a Location. - * -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 05643d0f2bf2cb2dedb0a2ad693b2121565d3f1f..c7cdbc36f96a8ee9eaac2a2145afbfc76bc38cc9 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -1442,6 +1442,88 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - */ - public boolean createExplosion(@NotNull Location loc, float power, boolean setFire); - -+ // Paper start -+ /** -+ * Creates explosion at given location with given power and optionally -+ * setting blocks on fire, with the specified entity as the source. -+ * -+ * @param source The source entity of the explosion -+ * @param loc Location to blow up -+ * @param power The power of explosion, where 4F is TNT -+ * @param setFire Whether or not to set blocks on fire -+ * @param breakBlocks Whether or not to have blocks be destroyed -+ * @return false if explosion was canceled, otherwise true -+ */ -+ public boolean createExplosion(@Nullable Entity source, @NotNull Location loc, float power, boolean setFire, boolean breakBlocks); -+ -+ /** -+ * Creates explosion at given location with given power and optionally -+ * setting blocks on fire, with the specified entity as the source. -+ * -+ * Will destroy other blocks -+ * -+ * @param source The source entity of the explosion -+ * @param loc Location to blow up -+ * @param power The power of explosion, where 4F is TNT -+ * @param setFire Whether or not to set blocks on fire -+ * @return false if explosion was canceled, otherwise true -+ */ -+ public default boolean createExplosion(@Nullable Entity source, @NotNull Location loc, float power, boolean setFire) { -+ return createExplosion(source, loc, power, setFire, true); -+ } -+ /** -+ * Creates explosion at given location with given power, with the specified entity as the source. -+ * Will set blocks on fire and destroy blocks. -+ * -+ * @param source The source entity of the explosion -+ * @param loc Location to blow up -+ * @param power The power of explosion, where 4F is TNT -+ * @return false if explosion was canceled, otherwise true -+ */ -+ public default boolean createExplosion(@Nullable Entity source, @NotNull Location loc, float power) { -+ return createExplosion(source, loc, power, true, true); -+ } -+ /** -+ * Creates explosion at given entities location with given power and optionally -+ * setting blocks on fire, with the specified entity as the source. -+ * -+ * @param source The source entity of the explosion -+ * @param power The power of explosion, where 4F is TNT -+ * @param setFire Whether or not to set blocks on fire -+ * @param breakBlocks Whether or not to have blocks be destroyed -+ * @return false if explosion was canceled, otherwise true -+ */ -+ public default boolean createExplosion(@NotNull Entity source, float power, boolean setFire, boolean breakBlocks) { -+ return createExplosion(source, source.getLocation(), power, setFire, breakBlocks); -+ } -+ /** -+ * Creates explosion at given entities location with given power and optionally -+ * setting blocks on fire, with the specified entity as the source. -+ * -+ * Will destroy blocks. -+ * -+ * @param source The source entity of the explosion -+ * @param power The power of explosion, where 4F is TNT -+ * @param setFire Whether or not to set blocks on fire -+ * @return false if explosion was canceled, otherwise true -+ */ -+ public default boolean createExplosion(@NotNull Entity source, float power, boolean setFire) { -+ return createExplosion(source, source.getLocation(), power, setFire, true); -+ } -+ -+ /** -+ * Creates explosion at given entities location with given power and optionally -+ * setting blocks on fire, with the specified entity as the source. -+ * -+ * @param source The source entity of the explosion -+ * @param power The power of explosion, where 4F is TNT -+ * @return false if explosion was canceled, otherwise true -+ */ -+ public default boolean createExplosion(@NotNull Entity source, float power) { -+ return createExplosion(source, source.getLocation(), power, true, true); -+ } -+ // Paper end -+ - /** - * Creates explosion at given coordinates with given power and optionally - * setting blocks on fire or breaking blocks. diff --git a/Unmapped-Spigot-API-Patches/0113-ItemStack-API-additions-for-quantity-flags-lore.patch b/Unmapped-Spigot-API-Patches/0113-ItemStack-API-additions-for-quantity-flags-lore.patch deleted file mode 100644 index d5b56b9832..0000000000 --- a/Unmapped-Spigot-API-Patches/0113-ItemStack-API-additions-for-quantity-flags-lore.patch +++ /dev/null @@ -1,206 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 22 Jun 2018 22:59:18 -0400 -Subject: [PATCH] ItemStack API additions for quantity/flags/lore - - -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index f41701e6374ca23eca4bdb092e385053a12eb718..07fd8a495828ff79239359c736c425c4902543a4 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -2,7 +2,9 @@ package org.bukkit.inventory; - - import com.google.common.collect.ImmutableMap; - import java.util.LinkedHashMap; -+import java.util.List; // Paper - import java.util.Map; -+import java.util.Set; // Paper - import org.apache.commons.lang.Validate; - import org.bukkit.Bukkit; - import org.bukkit.Material; -@@ -644,5 +646,185 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - // Requires access to NMS - return ensureServerConversions().getMaxItemUseDuration(); - } -+ -+ /** -+ * Clones the itemstack and returns it a single quantity. -+ * @return The new itemstack with 1 quantity -+ */ -+ @NotNull -+ public ItemStack asOne() { -+ return asQuantity(1); -+ } -+ -+ /** -+ * Clones the itemstack and returns it as the specified quantity -+ * @param qty The quantity of the cloned item -+ * @return The new itemstack with specified quantity -+ */ -+ @NotNull -+ public ItemStack asQuantity(int qty) { -+ ItemStack clone = clone(); -+ clone.setAmount(qty); -+ return clone; -+ } -+ -+ /** -+ * Adds 1 to this itemstack. Will not go over the items max stack size. -+ * @return The same item (not a clone) -+ */ -+ @NotNull -+ public ItemStack add() { -+ return add(1); -+ } -+ -+ /** -+ * Adds quantity to this itemstack. Will not go over the items max stack size. -+ * -+ * @param qty The amount to add -+ * @return The same item (not a clone) -+ */ -+ @NotNull -+ public ItemStack add(int qty) { -+ setAmount(Math.min(getMaxStackSize(), getAmount() + qty)); -+ return this; -+ } -+ -+ /** -+ * Subtracts 1 to this itemstack. Going to 0 or less will invalidate the item. -+ * @return The same item (not a clone) -+ */ -+ @NotNull -+ public ItemStack subtract() { -+ return subtract(1); -+ } -+ -+ /** -+ * Subtracts quantity to this itemstack. Going to 0 or less will invalidate the item. -+ * -+ * @param qty The amount to add -+ * @return The same item (not a clone) -+ */ -+ @NotNull -+ public ItemStack subtract(int qty) { -+ setAmount(Math.max(0, getAmount() - qty)); -+ return this; -+ } -+ -+ /** -+ * If the item has lore, returns it, else it will return null -+ * @return The lore, or null -+ * @deprecated in favor of {@link #lore()} -+ */ -+ @Deprecated -+ public @Nullable List getLore() { -+ if (!hasItemMeta()) { -+ return null; -+ } -+ ItemMeta itemMeta = getItemMeta(); -+ if (!itemMeta.hasLore()) { -+ return null; -+ } -+ return itemMeta.getLore(); -+ } -+ -+ /** -+ * If the item has lore, returns it, else it will return null -+ * @return The lore, or null -+ */ -+ public @Nullable List lore() { -+ if (!this.hasItemMeta()) { -+ return null; -+ } -+ final ItemMeta itemMeta = getItemMeta(); -+ if (!itemMeta.hasLore()) { -+ return null; -+ } -+ return itemMeta.lore(); -+ } -+ -+ /** -+ * Sets the lore for this item. -+ * Removes lore when given null. -+ * -+ * @param lore the lore that will be set -+ * @deprecated in favour of {@link #lore(List)} -+ */ -+ @Deprecated -+ public void setLore(@Nullable List lore) { -+ ItemMeta itemMeta = getItemMeta(); -+ if (itemMeta == null) { -+ throw new IllegalStateException("Cannot set lore on " + getType()); -+ } -+ itemMeta.setLore(lore); -+ setItemMeta(itemMeta); -+ } -+ -+ /** -+ * Sets the lore for this item. -+ * Removes lore when given null. -+ * -+ * @param lore the lore that will be set -+ */ -+ public void lore(@Nullable List lore) { -+ ItemMeta itemMeta = getItemMeta(); -+ if (itemMeta == null) { -+ throw new IllegalStateException("Cannot set lore on " + getType()); -+ } -+ itemMeta.lore(lore); -+ this.setItemMeta(itemMeta); -+ } -+ -+ /** -+ * Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. -+ * -+ * @param itemFlags The hideflags which shouldn't be rendered -+ */ -+ public void addItemFlags(@NotNull ItemFlag... itemFlags) { -+ ItemMeta itemMeta = getItemMeta(); -+ if (itemMeta == null) { -+ throw new IllegalStateException("Cannot add flags on " + getType()); -+ } -+ itemMeta.addItemFlags(itemFlags); -+ setItemMeta(itemMeta); -+ } -+ -+ /** -+ * Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. -+ * -+ * @param itemFlags Hideflags which should be removed -+ */ -+ public void removeItemFlags(@NotNull ItemFlag... itemFlags) { -+ ItemMeta itemMeta = getItemMeta(); -+ if (itemMeta == null) { -+ throw new IllegalStateException("Cannot remove flags on " + getType()); -+ } -+ itemMeta.removeItemFlags(itemFlags); -+ setItemMeta(itemMeta); -+ } -+ -+ /** -+ * Get current set itemFlags. The collection returned is unmodifiable. -+ * -+ * @return A set of all itemFlags set -+ */ -+ @NotNull -+ public Set getItemFlags() { -+ ItemMeta itemMeta = getItemMeta(); -+ if (itemMeta == null) { -+ return java.util.Collections.emptySet(); -+ } -+ return itemMeta.getItemFlags(); -+ } -+ -+ /** -+ * Check if the specified flag is present on this item. -+ * -+ * @param flag the flag to check -+ * @return if it is present -+ */ -+ public boolean hasItemFlag(@NotNull ItemFlag flag) { -+ ItemMeta itemMeta = getItemMeta(); -+ return itemMeta != null && itemMeta.hasItemFlag(flag); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch b/Unmapped-Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch deleted file mode 100644 index 62fef67f7a..0000000000 --- a/Unmapped-Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 Jun 2018 00:19:19 -0400 -Subject: [PATCH] LivingEntity Hand Raised/Item Use API - -How long an entity has raised hands to charge an attack or use an item - -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 879dec59f202ee95043bd7317a672cd59ab3bbbe..4f62a49e7b0538f0ce9cecd2c1b645f40ce17b3d 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -12,6 +12,7 @@ import org.bukkit.attribute.Attributable; - import org.bukkit.block.Block; - import org.bukkit.entity.memory.MemoryKey; - import org.bukkit.inventory.EntityEquipment; -+import org.bukkit.inventory.ItemStack; - import org.bukkit.potion.PotionEffect; - import org.bukkit.potion.PotionEffectType; - import org.bukkit.projectiles.ProjectileSource; -@@ -642,5 +643,42 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - * @param delay Delay in ticks - */ - void setShieldBlockingDelay(int delay); -+ -+ /** -+ * Get's the item being actively "used" or consumed. -+ * @return The item. Will be null if no active item. -+ */ -+ @Nullable -+ ItemStack getActiveItem(); -+ -+ /** -+ * Get's remaining time a player needs to keep hands raised with an item to finish using it. -+ * @return Remaining ticks to use the item -+ */ -+ int getItemUseRemainingTime(); -+ -+ /** -+ * Get how long the players hands have been raised (Charging Bow attack, using a potion, etc) -+ * -+ * @return Get how long the players hands have been raised (Charging Bow attack, using a potion, etc) -+ */ -+ int getHandRaisedTime(); -+ -+ /** -+ * Whether or not this entity is using or charging an attack (Bow pulled back, drinking potion, eating food) -+ * -+ * @return Whether or not this entity is using or charging an attack (Bow pulled back, drinking potion, eating food) -+ */ -+ boolean isHandRaised(); -+ -+ /** -+ * Gets the hand raised by this living entity. Will be either -+ * {@link org.bukkit.inventory.EquipmentSlot#HAND} or -+ * {@link org.bukkit.inventory.EquipmentSlot#OFF_HAND}. -+ * -+ * @return the hand raised -+ */ -+ @NotNull -+ org.bukkit.inventory.EquipmentSlot getHandRaised(); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0115-RangedEntity-API.patch b/Unmapped-Spigot-API-Patches/0115-RangedEntity-API.patch deleted file mode 100644 index f609bc2f0e..0000000000 --- a/Unmapped-Spigot-API-Patches/0115-RangedEntity-API.patch +++ /dev/null @@ -1,188 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 26 Jun 2018 21:34:40 -0400 -Subject: [PATCH] RangedEntity API - -Allows you to determine if an entity is capable of ranged attacks, -and to perform an attack. - -diff --git a/src/main/java/com/destroystokyo/paper/entity/RangedEntity.java b/src/main/java/com/destroystokyo/paper/entity/RangedEntity.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f2e3233a3d1744e32fb76d3731b9858ef0067e30 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/RangedEntity.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.entity; -+ -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Mob; -+import org.jetbrains.annotations.NotNull; -+ -+public interface RangedEntity extends Mob { -+ /** -+ * Attack the specified entity using a ranged attack. -+ * -+ * @param target the entity to target -+ * @param charge How "charged" the attack is (how far back the bow was pulled for Bow attacks). -+ * This should be a value between 0 and 1, represented as targetDistance/maxDistance. -+ */ -+ void rangedAttack(@NotNull LivingEntity target, float charge); -+ -+ /** -+ * Sets that the Entity is "charging" up an attack, by raising its hands -+ * -+ * @param raiseHands Whether the entities hands are raised to charge attack -+ */ -+ void setChargingAttack(boolean raiseHands); -+ -+ /** -+ * Alias to {@link LivingEntity#isHandRaised()}, if the entity is charging an attack -+ * @return If entities hands are raised -+ */ -+ default boolean isChargingAttack() { -+ return isHandRaised(); -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Drowned.java b/src/main/java/org/bukkit/entity/Drowned.java -index 1dee177ae6e21da000607dc8dd8fd76857f323b9..8d1ad9ef757cb1e8d72b145262df73612a76c746 100644 ---- a/src/main/java/org/bukkit/entity/Drowned.java -+++ b/src/main/java/org/bukkit/entity/Drowned.java -@@ -1,6 +1,8 @@ - package org.bukkit.entity; - -+import com.destroystokyo.paper.entity.RangedEntity; -+ - /** - * Drowned zombie. - */ --public interface Drowned extends Zombie { } -+public interface Drowned extends Zombie, RangedEntity { } // Paper -diff --git a/src/main/java/org/bukkit/entity/Illusioner.java b/src/main/java/org/bukkit/entity/Illusioner.java -index 7c92c431b32754dca12b4d584bd6fa93ff73badf..14e6c5ee06ece3d1bbc1239afa67c847a479948f 100644 ---- a/src/main/java/org/bukkit/entity/Illusioner.java -+++ b/src/main/java/org/bukkit/entity/Illusioner.java -@@ -1,6 +1,10 @@ - package org.bukkit.entity; - -+import com.destroystokyo.paper.entity.RangedEntity; -+ - /** - * Represents an Illusioner "Illager". - */ --public interface Illusioner extends Spellcaster { } -+public interface Illusioner extends Spellcaster, RangedEntity { // Paper -+ -+} -diff --git a/src/main/java/org/bukkit/entity/Llama.java b/src/main/java/org/bukkit/entity/Llama.java -index c43854298548391679c1d280bd42edbeed7759b9..d23226ccb0f6c25028f000ce31346cd0a8898e6a 100644 ---- a/src/main/java/org/bukkit/entity/Llama.java -+++ b/src/main/java/org/bukkit/entity/Llama.java -@@ -1,12 +1,13 @@ - package org.bukkit.entity; - -+import com.destroystokyo.paper.entity.RangedEntity; - import org.bukkit.inventory.LlamaInventory; - import org.jetbrains.annotations.NotNull; - - /** - * Represents a Llama. - */ --public interface Llama extends ChestedHorse { -+public interface Llama extends ChestedHorse, RangedEntity { // Paper - - /** - * Represents the base color that the llama has. -diff --git a/src/main/java/org/bukkit/entity/Piglin.java b/src/main/java/org/bukkit/entity/Piglin.java -index b96e57552245e2c6d452755d4227c572266fcec7..6fdc0e0bb62189dbf3cf9ce7a87b7fbb995956a3 100644 ---- a/src/main/java/org/bukkit/entity/Piglin.java -+++ b/src/main/java/org/bukkit/entity/Piglin.java -@@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; - /** - * Represents a Piglin. - */ --public interface Piglin extends PiglinAbstract, InventoryHolder { -+public interface Piglin extends PiglinAbstract, InventoryHolder, com.destroystokyo.paper.entity.RangedEntity { // Paper - - /** - * Get whether the piglin is able to hunt hoglins. -diff --git a/src/main/java/org/bukkit/entity/Pillager.java b/src/main/java/org/bukkit/entity/Pillager.java -index 9a2252fef56be1ed3ae2169aea46cb567e965c6c..11f38187fca830d974be01fea2966a31936184cb 100644 ---- a/src/main/java/org/bukkit/entity/Pillager.java -+++ b/src/main/java/org/bukkit/entity/Pillager.java -@@ -1,8 +1,10 @@ - package org.bukkit.entity; - -+import com.destroystokyo.paper.entity.RangedEntity; // Paper -+ - import org.bukkit.inventory.InventoryHolder; - - /** - * Illager entity. - */ --public interface Pillager extends Illager, InventoryHolder { } -+public interface Pillager extends Illager, InventoryHolder, RangedEntity { } // Paper -diff --git a/src/main/java/org/bukkit/entity/Skeleton.java b/src/main/java/org/bukkit/entity/Skeleton.java -index 16b1293887cee2bc5267f3da771fb5a6ece1b4e9..1c367f78eadf24850061a84ce63b950b79d3c435 100644 ---- a/src/main/java/org/bukkit/entity/Skeleton.java -+++ b/src/main/java/org/bukkit/entity/Skeleton.java -@@ -2,11 +2,12 @@ package org.bukkit.entity; - - import org.jetbrains.annotations.Contract; - import org.jetbrains.annotations.NotNull; -+import com.destroystokyo.paper.entity.RangedEntity; - - /** - * Represents a Skeleton. - */ --public interface Skeleton extends Monster { -+public interface Skeleton extends Monster, RangedEntity { // Paper - - /** - * Gets the current type of this skeleton. -diff --git a/src/main/java/org/bukkit/entity/Snowman.java b/src/main/java/org/bukkit/entity/Snowman.java -index 818efe2a4d1ac0c4d8dca6c757850d99cdc2cb4b..10f8f6d45ae9280651c3ebddd1f90acbd7d6ff29 100644 ---- a/src/main/java/org/bukkit/entity/Snowman.java -+++ b/src/main/java/org/bukkit/entity/Snowman.java -@@ -1,9 +1,11 @@ - package org.bukkit.entity; - -+import com.destroystokyo.paper.entity.RangedEntity; -+ - /** - * Represents a snowman entity - */ --public interface Snowman extends Golem { -+public interface Snowman extends Golem, RangedEntity { // Paper - - /** - * Gets whether this snowman is in "derp mode", meaning it is not wearing a -diff --git a/src/main/java/org/bukkit/entity/Witch.java b/src/main/java/org/bukkit/entity/Witch.java -index b4343903b66a7fb5250c1da2e09c9e5863c20daf..aa88aede6c4e66a608a63d07bc66d60357b0bee9 100644 ---- a/src/main/java/org/bukkit/entity/Witch.java -+++ b/src/main/java/org/bukkit/entity/Witch.java -@@ -1,7 +1,9 @@ - package org.bukkit.entity; - -+import com.destroystokyo.paper.entity.RangedEntity; -+ - /** - * Represents a Witch - */ --public interface Witch extends Raider { -+public interface Witch extends Raider, RangedEntity { // Paper - } -diff --git a/src/main/java/org/bukkit/entity/Wither.java b/src/main/java/org/bukkit/entity/Wither.java -index 3bc332ee7f7d428bef6e2566ddded8b941858e2e..426d3693317cd303d35d8203026b528d87e401d5 100644 ---- a/src/main/java/org/bukkit/entity/Wither.java -+++ b/src/main/java/org/bukkit/entity/Wither.java -@@ -1,7 +1,9 @@ - package org.bukkit.entity; - -+import com.destroystokyo.paper.entity.RangedEntity; -+ - /** - * Represents a Wither boss - */ --public interface Wither extends Monster, Boss { -+public interface Wither extends Monster, Boss, RangedEntity { // Paper - } diff --git a/Unmapped-Spigot-API-Patches/0116-Add-World.getEntity-UUID-API.patch b/Unmapped-Spigot-API-Patches/0116-Add-World.getEntity-UUID-API.patch deleted file mode 100644 index bb7e7eafdf..0000000000 --- a/Unmapped-Spigot-API-Patches/0116-Add-World.getEntity-UUID-API.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 3 Jul 2018 16:07:16 +0200 -Subject: [PATCH] Add World.getEntity(UUID) API - - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index c7cdbc36f96a8ee9eaac2a2145afbfc76bc38cc9..edf136ef50c9cdd8ccea2e35508e4464c3de99bd 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -946,6 +946,17 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @NotNull - public Collection getNearbyEntities(@NotNull Location location, double x, double y, double z); - -+ // Paper start - getEntity by UUID API -+ /** -+ * Gets an entity in this world by its UUID -+ * -+ * @param uuid the UUID of the entity -+ * @return the entity with the given UUID, or null if it isn't found -+ */ -+ @Nullable -+ public Entity getEntity(@NotNull UUID uuid); -+ // Paper end -+ - /** - * Returns a list of entities within a bounding box centered around a - * Location. diff --git a/Unmapped-Spigot-API-Patches/0117-InventoryCloseEvent-Reason-API.patch b/Unmapped-Spigot-API-Patches/0117-InventoryCloseEvent-Reason-API.patch deleted file mode 100644 index c03581bf2f..0000000000 --- a/Unmapped-Spigot-API-Patches/0117-InventoryCloseEvent-Reason-API.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 3 Jul 2018 21:52:52 -0400 -Subject: [PATCH] InventoryCloseEvent Reason API - -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 7430bc85301d0fcb34c6035fbe08ae245c76e043..3418133d07250a7fd50caad8d97924b86fb30bad 100644 ---- a/src/main/java/org/bukkit/entity/HumanEntity.java -+++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -153,6 +153,15 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder - */ - public void closeInventory(); - -+ // Paper start -+ /** -+ * Force-closes the currently open inventory view for this player, if any. -+ * -+ * @param reason why the inventory is closing -+ */ -+ public void closeInventory(@NotNull org.bukkit.event.inventory.InventoryCloseEvent.Reason reason); -+ // Paper end -+ - /** - * Returns the ItemStack currently in your hand, can be empty. - * -diff --git a/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java -index 5861247c1b8ee4fe2736fd5098e05a2ca9ab78ea..21ad8888c0e403bfc63518502577d651c02dda05 100644 ---- a/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java -@@ -11,9 +11,60 @@ import org.jetbrains.annotations.NotNull; - */ - public class InventoryCloseEvent extends InventoryEvent { - private static final HandlerList handlers = new HandlerList(); -+ // Paper start -+ private final Reason reason; -+ @NotNull -+ public Reason getReason() { -+ return reason; -+ } -+ -+ public enum Reason { -+ /** -+ * Unknown reason -+ */ -+ UNKNOWN, -+ /** -+ * Player is teleporting -+ */ -+ TELEPORT, -+ /** -+ * Player is no longer permitted to use this inventory -+ */ -+ CANT_USE, -+ /** -+ * The chunk the inventory was in was unloaded -+ */ -+ UNLOADED, -+ /** -+ * Opening new inventory instead -+ */ -+ OPEN_NEW, -+ /** -+ * Closed -+ */ -+ PLAYER, -+ /** -+ * Closed due to disconnect -+ */ -+ DISCONNECT, -+ /** -+ * The player died -+ */ -+ DEATH, -+ /** -+ * Closed by Bukkit API -+ */ -+ PLUGIN, -+ } - - public InventoryCloseEvent(@NotNull InventoryView transaction) { -+ this(transaction, Reason.UNKNOWN); -+ } -+ -+ public InventoryCloseEvent(@NotNull InventoryView transaction, @NotNull Reason reason) { - super(transaction); -+ this.reason = reason; -+ // Paper end - } - - /** diff --git a/Unmapped-Spigot-API-Patches/0118-Entity-getChunk-API.patch b/Unmapped-Spigot-API-Patches/0118-Entity-getChunk-API.patch deleted file mode 100644 index 1a598ac537..0000000000 --- a/Unmapped-Spigot-API-Patches/0118-Entity-getChunk-API.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 02:25:48 -0400 -Subject: [PATCH] Entity#getChunk API - -Get the chunk the entity is currently registered to - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index fdc95c87a6020bdcaee5b0b8ab5a996c0e241b33..76c20d84fee011af4f1850d0cab8ac00a69f2b34 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -3,6 +3,7 @@ package org.bukkit.entity; - import java.util.List; - import java.util.Set; - import java.util.UUID; -+import org.bukkit.Chunk; // Paper - import org.bukkit.EntityEffect; - import org.bukkit.Location; - import org.bukkit.Nameable; -@@ -672,5 +673,13 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - * @return True if entity spawned from a mob spawner - */ - boolean fromMobSpawner(); -+ -+ /** -+ * Gets the latest chunk an entity is currently or was in. -+ * -+ * @return The current, or most recent chunk if the entity is invalid (which may load the chunk) -+ */ -+ @NotNull -+ Chunk getChunk(); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch b/Unmapped-Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch deleted file mode 100644 index d768a18607..0000000000 --- a/Unmapped-Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 1 Dec 2020 14:57:02 +0100 -Subject: [PATCH] Add an asterisk to legacy API plugins - -Not here to name and shame, only so server admins can be aware of which -plugins have and haven't been updated. - -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 195b6bb328de92c4d17d1cd14e13578226b1ac3c..d6897f43a0692e031bed8a212d9a637ef548cc60 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -91,5 +91,11 @@ public interface UnsafeValues { - default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { - return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher(); - } -+ -+ boolean isSupportedApiVersion(String apiVersion); -+ -+ static boolean isLegacyPlugin(org.bukkit.plugin.Plugin plugin) { -+ return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java -index 4de959bbd1270d7d6ea8e5e69521bcca6abe2138..1aa58c59e1e8738bbdc77752885ff3b18b29de42 100644 ---- a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java -+++ b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java -@@ -52,9 +52,15 @@ public class PluginsCommand extends BukkitCommand { - } - - Plugin plugin = entry.getValue(); -- -+ - pluginList.append(plugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED); -- pluginList.append(plugin.getDescription().getName()); -+ // Paper start - Add an asterisk to legacy plugins (so admins are aware) -+ String pluginName = plugin.getDescription().getName(); -+ if (org.bukkit.UnsafeValues.isLegacyPlugin(plugin)) { -+ pluginName += "*"; -+ } -+ pluginList.append(pluginName); -+ // Paper end - - if (plugin.getDescription().getProvides().size() > 0) { - pluginList.append(" (").append(String.join(", ", plugin.getDescription().getProvides())).append(")"); -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 816c2b1797447ab315ceb6eda89d25f27d2bce98..f26303315c9c93356f0b04440136855dd54d32b7 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -306,7 +306,14 @@ public final class JavaPluginLoader implements PluginLoader { - Validate.isTrue(plugin instanceof JavaPlugin, "Plugin is not associated with this PluginLoader"); - - if (!plugin.isEnabled()) { -- plugin.getLogger().info("Enabling " + plugin.getDescription().getFullName()); -+ // Paper start - Add an asterisk to legacy plugins (so admins are aware) -+ String enableMsg = "Enabling " + plugin.getDescription().getFullName(); -+ if (org.bukkit.UnsafeValues.isLegacyPlugin(plugin)) { -+ enableMsg += "*"; -+ } -+ -+ plugin.getLogger().info(enableMsg); -+ // Paper end - - JavaPlugin jPlugin = (JavaPlugin) plugin; - diff --git a/Unmapped-Spigot-API-Patches/0120-EnderDragon-Events.patch b/Unmapped-Spigot-API-Patches/0120-EnderDragon-Events.patch deleted file mode 100644 index 68ed791382..0000000000 --- a/Unmapped-Spigot-API-Patches/0120-EnderDragon-Events.patch +++ /dev/null @@ -1,225 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:51:05 -0500 -Subject: [PATCH] EnderDragon Events - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFireballHitEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFireballHitEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..118c7b6772a52c250649af2a9286f483f43da385 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFireballHitEvent.java -@@ -0,0 +1,79 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.AreaEffectCloud; -+import org.bukkit.entity.DragonFireball; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+ -+import java.util.Collection; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Fired when a DragonFireball collides with a block/entity and spawns an AreaEffectCloud -+ */ -+public class EnderDragonFireballHitEvent extends EntityEvent implements Cancellable { -+ @Nullable private final Collection targets; -+ @NotNull private final AreaEffectCloud areaEffectCloud; -+ -+ public EnderDragonFireballHitEvent(@NotNull DragonFireball fireball, @Nullable Collection targets, @NotNull AreaEffectCloud areaEffectCloud) { -+ super(fireball); -+ this.targets = targets; -+ this.areaEffectCloud = areaEffectCloud; -+ } -+ -+ /** -+ * The fireball involved in this event -+ */ -+ @NotNull -+ @Override -+ public DragonFireball getEntity() { -+ return (DragonFireball) super.getEntity(); -+ } -+ -+ /** -+ * The living entities hit by fireball -+ * -+ * May be null if no entities were hit -+ * -+ * @return the targets -+ */ -+ @Nullable -+ public Collection getTargets() { -+ return targets; -+ } -+ -+ /** -+ * @return The area effect cloud spawned in this collision -+ */ -+ @NotNull -+ public AreaEffectCloud getAreaEffectCloud() { -+ return areaEffectCloud; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFlameEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFlameEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..1915177f4b8f8013656fbdb41240f6c5c88f95d7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFlameEvent.java -@@ -0,0 +1,61 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.AreaEffectCloud; -+import org.bukkit.entity.EnderDragon; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when an EnderDragon spawns an AreaEffectCloud by shooting flames -+ */ -+public class EnderDragonFlameEvent extends EntityEvent implements Cancellable { -+ @NotNull private final AreaEffectCloud areaEffectCloud; -+ -+ public EnderDragonFlameEvent(@NotNull EnderDragon enderDragon, @NotNull AreaEffectCloud areaEffectCloud) { -+ super(enderDragon); -+ this.areaEffectCloud = areaEffectCloud; -+ } -+ -+ /** -+ * The enderdragon involved in this event -+ */ -+ @NotNull -+ @Override -+ public EnderDragon getEntity() { -+ return (EnderDragon) super.getEntity(); -+ } -+ -+ /** -+ * @return The area effect cloud spawned in this collision -+ */ -+ @NotNull -+ public AreaEffectCloud getAreaEffectCloud() { -+ return areaEffectCloud; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonShootFireballEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonShootFireballEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8414bd805ec68d7b305fbf645c59f8d5b762c9ce ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonShootFireballEvent.java -@@ -0,0 +1,61 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.DragonFireball; -+import org.bukkit.entity.EnderDragon; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when an EnderDragon shoots a fireball -+ */ -+public class EnderDragonShootFireballEvent extends EntityEvent implements Cancellable { -+ @NotNull private final DragonFireball fireball; -+ -+ public EnderDragonShootFireballEvent(@NotNull EnderDragon entity, @NotNull DragonFireball fireball) { -+ super(entity); -+ this.fireball = fireball; -+ } -+ -+ /** -+ * The enderdragon shooting the fireball -+ */ -+ @NotNull -+ @Override -+ public EnderDragon getEntity() { -+ return (EnderDragon) super.getEntity(); -+ } -+ -+ /** -+ * @return The fireball being shot -+ */ -+ @NotNull -+ public DragonFireball getFireball() { -+ return fireball; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch b/Unmapped-Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch deleted file mode 100644 index 7524daea92..0000000000 --- a/Unmapped-Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 03:10:50 -0500 -Subject: [PATCH] PlayerLaunchProjectileEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerLaunchProjectileEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerLaunchProjectileEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9074b2ede01f76c0560e5318246382163cc91591 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerLaunchProjectileEvent.java -@@ -0,0 +1,83 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.entity.Projectile; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player shoots a projectile -+ */ -+public class PlayerLaunchProjectileEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private final Projectile projectile; -+ @NotNull private final ItemStack itemStack; -+ private boolean consumeItem = true; -+ private boolean cancelled; -+ -+ public PlayerLaunchProjectileEvent(@NotNull Player shooter, @NotNull ItemStack itemStack, @NotNull Projectile projectile) { -+ super(shooter); -+ this.itemStack = itemStack; -+ this.projectile = projectile; -+ } -+ -+ /** -+ * Gets the projectile which will be launched by this event -+ * -+ * @return the launched projectile -+ */ -+ @NotNull -+ public Projectile getProjectile() { -+ return projectile; -+ } -+ -+ /** -+ * Get the ItemStack used to fire the projectile -+ * -+ * @return The ItemStack used -+ */ -+ @NotNull -+ public ItemStack getItemStack() { -+ return itemStack; -+ } -+ -+ /** -+ * Get whether to consume the ItemStack or not -+ * -+ * @return True to consume -+ */ -+ public boolean shouldConsume() { -+ return consumeItem; -+ } -+ -+ /** -+ * Set whether to consume the ItemStack or not -+ * -+ * @param consumeItem True to consume -+ */ -+ public void setShouldConsume(boolean consumeItem) { -+ this.consumeItem = consumeItem; -+ } -+ -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch b/Unmapped-Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch deleted file mode 100644 index c5d8e5ddf3..0000000000 --- a/Unmapped-Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:59:53 -0500 -Subject: [PATCH] PlayerElytraBoostEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerElytraBoostEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerElytraBoostEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e9a76a25fa5445905a09dbc2fd5b35bff56d80b3 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerElytraBoostEvent.java -@@ -0,0 +1,85 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Firework; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a player boosts elytra flight with a firework -+ */ -+public class PlayerElytraBoostEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled = false; -+ @NotNull private final ItemStack itemStack; -+ @NotNull private Firework firework; -+ private boolean consume = true; -+ -+ public PlayerElytraBoostEvent(@NotNull Player player, @NotNull ItemStack itemStack, @NotNull Firework firework) { -+ super(player); -+ this.itemStack = itemStack; -+ this.firework = firework; -+ } -+ -+ /** -+ * Get the firework itemstack used -+ * -+ * @return ItemStack of firework -+ */ -+ @NotNull -+ public ItemStack getItemStack() { -+ return itemStack; -+ } -+ -+ /** -+ * Get the firework entity that was spawned -+ * -+ * @return Firework entity -+ */ -+ @NotNull -+ public Firework getFirework() { -+ return firework; -+ } -+ -+ /** -+ * Get whether to consume the firework or not -+ * -+ * @return True to consume -+ */ -+ public boolean shouldConsume() { -+ return consume; -+ } -+ -+ /** -+ * Set whether to consume the firework or not -+ * -+ * @param consume True to consume -+ */ -+ public void setShouldConsume(boolean consume) { -+ this.consume = consume; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0123-EntityTransformedEvent.patch b/Unmapped-Spigot-API-Patches/0123-EntityTransformedEvent.patch deleted file mode 100644 index c77c4a8ba6..0000000000 --- a/Unmapped-Spigot-API-Patches/0123-EntityTransformedEvent.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Anthony MacAllister -Date: Thu, 26 Jul 2018 15:28:53 -0400 -Subject: [PATCH] EntityTransformedEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityTransformedEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityTransformedEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..12194f1fc7f03ca6785904b6187b3dfd03b16461 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityTransformedEvent.java -@@ -0,0 +1,92 @@ -+package com.destroystokyo.paper.event.entity; -+ -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.event.entity.EntityTransformEvent; -+ -+/** -+ * Fired when an entity transforms into another entity -+ *

    -+ * If the event is cancelled, the entity will not transform -+ * @deprecated Bukkit has added {@link EntityTransformEvent}, you should start using that -+ */ -+@Deprecated -+public class EntityTransformedEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ private final Entity transformed; -+ private final TransformedReason reason; -+ -+ public EntityTransformedEvent(Entity entity, Entity transformed, TransformedReason reason) { -+ super(entity); -+ this.transformed = transformed; -+ this.reason = reason; -+ } -+ -+ /** -+ * The entity after it has transformed -+ * -+ * @return Transformed entity -+ * @deprecated see {@link EntityTransformEvent#getTransformedEntity()} -+ */ -+ @Deprecated -+ public Entity getTransformed() { -+ return transformed; -+ } -+ -+ /** -+ * @return The reason for the transformation -+ * @deprecated see {@link EntityTransformEvent#getTransformReason()} -+ */ -+ @Deprecated -+ public TransformedReason getReason() { -+ return reason; -+ } -+ -+ -+ @Override -+ public HandlerList getHandlers(){ -+ return handlers; -+ } -+ -+ public static HandlerList getHandlerList(){ -+ return handlers; -+ } -+ -+ @Override -+ public boolean isCancelled(){ -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel){ -+ cancelled = cancel; -+ } -+ -+ public enum TransformedReason { -+ /** -+ * When a zombie drowns -+ */ -+ DROWNED, -+ /** -+ * When a zombie villager is cured -+ */ -+ CURED, -+ /** -+ * When a villager turns to a zombie villager -+ */ -+ INFECTED, -+ /** -+ * When a mooshroom turns to a cow -+ */ -+ SHEARED, -+ /** -+ * When a pig turns to a zombiepigman -+ */ -+ LIGHTNING -+ -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch b/Unmapped-Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch deleted file mode 100644 index 30f0bf5227..0000000000 --- a/Unmapped-Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 15 Aug 2018 01:26:03 -0700 -Subject: [PATCH] Allow disabling armour stand ticking - - -diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java -index fddc063798edc8084ca695578a47485204a7f3cd..365d3a3c5fc4a47efe56225ef1eb87b5046034f4 100644 ---- a/src/main/java/org/bukkit/entity/ArmorStand.java -+++ b/src/main/java/org/bukkit/entity/ArmorStand.java -@@ -360,5 +360,21 @@ public interface ArmorStand extends LivingEntity { - * @param move {@code true} if this armour stand can move, {@code false} otherwise - */ - void setCanMove(boolean move); -+ -+ /** -+ * Tests if this armor stand can tick. -+ * -+ *

    The default value is defined in {@code paper.yml}.

    -+ * -+ * @return {@code true} if this armour stand can tick, {@code false} otherwise -+ */ -+ boolean canTick(); -+ -+ /** -+ * Sets if this armor stand can tick. -+ * -+ * @param tick {@code true} if this armour stand can tick, {@code false} otherwise -+ */ -+ void setCanTick(final boolean tick); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0125-SkeletonHorse-Additions.patch b/Unmapped-Spigot-API-Patches/0125-SkeletonHorse-Additions.patch deleted file mode 100644 index 8d4dd478ab..0000000000 --- a/Unmapped-Spigot-API-Patches/0125-SkeletonHorse-Additions.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 27 Jul 2018 22:36:17 -0500 -Subject: [PATCH] SkeletonHorse Additions - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9ce2948dfaa56d0adf53fe9b6117a90d7773b771 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java -@@ -0,0 +1,62 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import com.google.common.collect.ImmutableList; -+import org.bukkit.entity.HumanEntity; -+import org.bukkit.entity.SkeletonHorse; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.List; -+ -+/** -+ * Event called when a player gets close to a skeleton horse and triggers the lightning trap -+ */ -+public class SkeletonHorseTrapEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ private final List eligibleHumans; -+ -+ public SkeletonHorseTrapEvent(@NotNull SkeletonHorse horse) { -+ this(horse, ImmutableList.of()); -+ } -+ -+ public SkeletonHorseTrapEvent(@NotNull SkeletonHorse horse, @NotNull List eligibleHumans) { -+ super(horse); -+ this.eligibleHumans = eligibleHumans; -+ } -+ -+ @NotNull -+ @Override -+ public SkeletonHorse getEntity() { -+ return (SkeletonHorse) super.getEntity(); -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ public List getEligibleHumans() { -+ return eligibleHumans; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -+ -diff --git a/src/main/java/org/bukkit/entity/SkeletonHorse.java b/src/main/java/org/bukkit/entity/SkeletonHorse.java -index b2c6b6a8689f6bd6ce784bbe6f571f756dd700c1..ba9983463263f77db3d3487bc12f01db4508a32b 100644 ---- a/src/main/java/org/bukkit/entity/SkeletonHorse.java -+++ b/src/main/java/org/bukkit/entity/SkeletonHorse.java -@@ -3,4 +3,12 @@ package org.bukkit.entity; - /** - * Represents a SkeletonHorse - variant of {@link AbstractHorse}. - */ --public interface SkeletonHorse extends AbstractHorse { } -+public interface SkeletonHorse extends AbstractHorse { -+ // Paper start -+ int getTrapTime(); -+ -+ boolean isTrap(); -+ -+ void setTrap(boolean trap); -+ // Paper end -+} diff --git a/Unmapped-Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch b/Unmapped-Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch deleted file mode 100644 index 271041f256..0000000000 --- a/Unmapped-Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 25 Jul 2018 01:36:07 -0400 -Subject: [PATCH] Expand Location Manipulation API - -Adds set(x, y, z), add(base, x, y, z), subtract(base, x, y, z); - -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index af2ee43f2c5133668c18710f526a107d94a5d898..369ce9ff6c8bb97a64a8e229115564412e6e7654 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -546,6 +546,54 @@ public class Location implements Cloneable, ConfigurationSerializable { - public boolean isChunkLoaded() { return this.getWorld().isChunkLoaded(locToBlock(x) >> 4, locToBlock(z) >> 4); } // Paper - - // Paper start -+ -+ /** -+ * Sets the position of this Location and returns itself -+ * -+ * This mutates this object, clone first. -+ * @param x X coordinate -+ * @param y Y coordinate -+ * @param z Z coordinate -+ * @return self (not cloned) -+ */ -+ @NotNull -+ public Location set(double x, double y, double z) { -+ this.x = x; -+ this.y = y; -+ this.z = z; -+ return this; -+ } -+ -+ /** -+ * Takes the x/y/z from base and adds the specified x/y/z to it and returns self -+ * -+ * This mutates this object, clone first. -+ * @param base The base coordinate to modify -+ * @param x X coordinate to add to base -+ * @param y Y coordinate to add to base -+ * @param z Z coordinate to add to base -+ * @return self (not cloned) -+ */ -+ @NotNull -+ public Location add(@NotNull Location base, double x, double y, double z) { -+ return this.set(base.x + x, base.y + y, base.z + z); -+ } -+ -+ /** -+ * Takes the x/y/z from base and subtracts the specified x/y/z to it and returns self -+ * -+ * This mutates this object, clone first. -+ * @param base The base coordinate to modify -+ * @param x X coordinate to subtract from base -+ * @param y Y coordinate to subtract from base -+ * @param z Z coordinate to subtract from base -+ * @return self (not cloned) -+ */ -+ @NotNull -+ public Location subtract(@NotNull Location base, double x, double y, double z) { -+ return this.set(base.x - x, base.y - y, base.z - z); -+ } -+ - /** - * @return A new location where X/Y/Z are on the Block location (integer value of X/Y/Z) - */ diff --git a/Unmapped-Spigot-API-Patches/0127-Expand-ArmorStand-API.patch b/Unmapped-Spigot-API-Patches/0127-Expand-ArmorStand-API.patch deleted file mode 100644 index 036951f69d..0000000000 --- a/Unmapped-Spigot-API-Patches/0127-Expand-ArmorStand-API.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: willies952002 -Date: Thu, 26 Jul 2018 02:22:44 -0400 -Subject: [PATCH] Expand ArmorStand API - -Add the following: -- Add proper methods for getting and setting items in both hands. Deprecates old methods -- Enable/Disable slot interactions - -diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java -index 365d3a3c5fc4a47efe56225ef1eb87b5046034f4..8ca6c9eba926f436203af211c6e274a59ddb15e8 100644 ---- a/src/main/java/org/bukkit/entity/ArmorStand.java -+++ b/src/main/java/org/bukkit/entity/ArmorStand.java -@@ -13,7 +13,7 @@ public interface ArmorStand extends LivingEntity { - * Returns the item the armor stand is currently holding. - * - * @return the held item -- * @deprecated prefer {@link EntityEquipment#getItemInHand()} -+ * @deprecated prefer {@link ArmorStand#getItem(EquipmentSlot)} // Paper - * @see #getEquipment() - */ - @NotNull -@@ -25,7 +25,7 @@ public interface ArmorStand extends LivingEntity { - * - * @param item the item to hold - * @deprecated prefer -- * {@link EntityEquipment#setItemInHand(org.bukkit.inventory.ItemStack)} -+ * {@link ArmorStand#setItem(EquipmentSlot, ItemStack)} // Paper - * @see #getEquipment() - */ - @Deprecated -@@ -376,5 +376,71 @@ public interface ArmorStand extends LivingEntity { - * @param tick {@code true} if this armour stand can tick, {@code false} otherwise - */ - void setCanTick(final boolean tick); -+ -+ /** -+ * Returns the item the armor stand has -+ * equip in the given equipment slot -+ * -+ * @param slot the equipment slot to get -+ * @return the ItemStack in the equipment slot -+ */ -+ @NotNull -+ ItemStack getItem(@NotNull final org.bukkit.inventory.EquipmentSlot slot); -+ -+ /** -+ * Sets the item the armor stand has -+ * equip in the given equipment slot -+ * -+ * @param slot the equipment slot to set -+ * @param item the item to hold -+ */ -+ void setItem(@NotNull final org.bukkit.inventory.EquipmentSlot slot, @Nullable final ItemStack item); -+ -+ /** -+ * Get the list of disabled slots -+ * -+ * @return list of disabled slots -+ */ -+ @NotNull -+ java.util.Set getDisabledSlots(); -+ -+ /** -+ * Set the disabled slots -+ * -+ * This makes it so a player is unable to interact with the Armor Stand to place, remove, or replace an item in the given slot(s) -+ * Note: Once a slot is disabled, the only way to get an item back it to break the armor stand. -+ * -+ * @param slots var-arg array of slots to lock -+ */ -+ void setDisabledSlots(@NotNull org.bukkit.inventory.EquipmentSlot... slots); -+ -+ /** -+ * Disable specific slots, adding them -+ * to the currently disabled slots -+ * -+ * This makes it so a player is unable to interact with the Armor Stand to place, remove, or replace an item in the given slot(s) -+ * Note: Once a slot is disabled, the only way to get an item back it to break the armor stand. -+ * -+ * @param slots var-arg array of slots to lock -+ */ -+ void addDisabledSlots(@NotNull final org.bukkit.inventory.EquipmentSlot... slots); -+ -+ /** -+ * Remove the given slots from the disabled -+ * slots list, enabling them. -+ * -+ * This makes it so a player is able to interact with the Armor Stand to place, remove, or replace an item in the given slot(s) -+ * -+ * @param slots var-arg array of slots to unlock -+ */ -+ void removeDisabledSlots(@NotNull final org.bukkit.inventory.EquipmentSlot... slots); -+ -+ /** -+ * Check if a specific slot is disabled -+ * -+ * @param slot The slot to check -+ * @return {@code true} if the slot is disabled, else {@code false}. -+ */ -+ boolean isSlotDisabled(@NotNull org.bukkit.inventory.EquipmentSlot slot); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0128-AnvilDamageEvent.patch b/Unmapped-Spigot-API-Patches/0128-AnvilDamageEvent.patch deleted file mode 100644 index 7561b6a9db..0000000000 --- a/Unmapped-Spigot-API-Patches/0128-AnvilDamageEvent.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 20 Jul 2018 23:36:55 -0500 -Subject: [PATCH] AnvilDamageEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/block/AnvilDamagedEvent.java b/src/main/java/com/destroystokyo/paper/event/block/AnvilDamagedEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a83c286c1c11af25fc4d16af7a42b95ce90b9dee ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/block/AnvilDamagedEvent.java -@@ -0,0 +1,148 @@ -+package com.destroystokyo.paper.event.block; -+ -+import org.bukkit.Material; -+import org.bukkit.block.data.BlockData; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.inventory.InventoryEvent; -+import org.bukkit.inventory.AnvilInventory; -+import org.bukkit.inventory.InventoryView; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when an anvil is damaged from being used -+ */ -+public class AnvilDamagedEvent extends InventoryEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancel; -+ private DamageState damageState; -+ -+ public AnvilDamagedEvent(@NotNull InventoryView inventory, @NotNull BlockData blockData) { -+ super(inventory); -+ this.damageState = DamageState.getState(blockData); -+ } -+ -+ @NotNull -+ @Override -+ public AnvilInventory getInventory() { -+ return (AnvilInventory) super.getInventory(); -+ } -+ -+ /** -+ * Gets the new state of damage on the anvil -+ * -+ * @return Damage state -+ */ -+ @NotNull -+ public DamageState getDamageState() { -+ return damageState; -+ } -+ -+ /** -+ * Sets the new state of damage on the anvil -+ * -+ * @param damageState Damage state -+ */ -+ public void setDamageState(@NotNull DamageState damageState) { -+ this.damageState = damageState; -+ } -+ -+ /** -+ * Gets if anvil is breaking on this use -+ * -+ * @return True if breaking -+ */ -+ public boolean isBreaking() { -+ return damageState == DamageState.BROKEN; -+ } -+ -+ /** -+ * Sets if anvil is breaking on this use -+ * -+ * @param breaking True if breaking -+ */ -+ public void setBreaking(boolean breaking) { -+ if (breaking) { -+ damageState = DamageState.BROKEN; -+ } else if (damageState == DamageState.BROKEN) { -+ damageState = DamageState.DAMAGED; -+ } -+ } -+ -+ public boolean isCancelled() { -+ return cancel; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ this.cancel = cancel; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ /** -+ * Represents the amount of damage on an anvil block -+ */ -+ public enum DamageState { -+ FULL(Material.ANVIL), -+ CHIPPED(Material.CHIPPED_ANVIL), -+ DAMAGED(Material.DAMAGED_ANVIL), -+ BROKEN(Material.AIR); -+ -+ private Material material; -+ -+ DamageState(@NotNull Material material) { -+ this.material = material; -+ } -+ -+ /** -+ * Get block material of this state -+ * -+ * @return Material -+ */ -+ @NotNull -+ public Material getMaterial() { -+ return material; -+ } -+ -+ /** -+ * Get damaged state by block data -+ * -+ * @param blockData Block data -+ * @return DamageState -+ * @throws IllegalArgumentException If non anvil block data is given -+ */ -+ @NotNull -+ public static DamageState getState(@Nullable BlockData blockData) { -+ return blockData == null ? BROKEN : getState(blockData.getMaterial()); -+ } -+ -+ /** -+ * Get damaged state by block material -+ * -+ * @param material Block material -+ * @return DamageState -+ * @throws IllegalArgumentException If non anvil material is given -+ */ -+ @NotNull -+ public static DamageState getState(@Nullable Material material) { -+ if (material == null) { -+ return BROKEN; -+ } -+ for (DamageState state : values()) { -+ if (state.material == material) { -+ return state; -+ } -+ } -+ throw new IllegalArgumentException("Material not an anvil"); -+ } -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch b/Unmapped-Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch deleted file mode 100644 index 2725c79f2e..0000000000 --- a/Unmapped-Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 9 Sep 2018 00:32:05 -0400 -Subject: [PATCH] Remove deadlock risk in firing async events - -The PluginManager incorrectly used synchronization on firing any event -that was marked as synchronous. - -This synchronized did not even protect any concurrency risk as -handlers were already thread safe in terms of mutations during event -dispatch. - -The way it was used, has commonly led to deadlocks on the server, -which results in a hard crash. - -This change removes the synchronize and adds some protection around enable/disable - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 9b8823279524d1c1566176c589aa5794eb8aafbc..707638c327077a74c777a603b9f2392f46b51c0c 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable; - */ - public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource { // Paper - -- /** -+ /* - * Gets the entity's current position - * - * @return a new copy of Location containing the position of this entity -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index a7393d2830b95d7167121b02066a3f357cee6085..a1a805004941d67abb0b9aa1721e0370c45b5289 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -462,7 +462,7 @@ public final class SimplePluginManager implements PluginManager { - * @return true if the plugin is enabled, otherwise false - */ - @Override -- public boolean isPluginEnabled(@Nullable Plugin plugin) { -+ public synchronized boolean isPluginEnabled(@Nullable Plugin plugin) { // Paper - synchronize - if ((plugin != null) && (plugins.contains(plugin))) { - return plugin.isEnabled(); - } else { -@@ -471,7 +471,7 @@ public final class SimplePluginManager implements PluginManager { - } - - @Override -- public void enablePlugin(@NotNull final Plugin plugin) { -+ public synchronized void enablePlugin(@NotNull final Plugin plugin) { // Paper - synchronize - if (!plugin.isEnabled()) { - List pluginCommands = PluginCommandYamlParser.parse(plugin); - -@@ -509,7 +509,7 @@ public final class SimplePluginManager implements PluginManager { - } - - @Override -- public void disablePlugin(@NotNull final Plugin plugin, boolean closeClassloader) { -+ public synchronized void disablePlugin(@NotNull final Plugin plugin, boolean closeClassloader) { // Paper - synchronize - // Paper end - close Classloader on disable - if (plugin.isEnabled()) { - try { -@@ -579,6 +579,7 @@ public final class SimplePluginManager implements PluginManager { - defaultPerms.get(false).clear(); - } - } -+ private void fireEvent(Event event) { callEvent(event); } // Paper - support old method incase plugin uses reflection - - /** - * Calls an event with the given details. -@@ -587,23 +588,13 @@ public final class SimplePluginManager implements PluginManager { - */ - @Override - public void callEvent(@NotNull Event event) { -- if (event.isAsynchronous()) { -- if (Thread.holdsLock(this)) { -- throw new IllegalStateException(event.getEventName() + " cannot be triggered asynchronously from inside synchronized code."); -- } -- if (server.isPrimaryThread()) { -- throw new IllegalStateException(event.getEventName() + " cannot be triggered asynchronously from primary server thread."); -- } -- } else { -- if (!server.isPrimaryThread()) { -- throw new IllegalStateException(event.getEventName() + " cannot be triggered asynchronously from another thread."); -- } -+ // Paper - replace callEvent by merging to below method -+ if (event.isAsynchronous() && server.isPrimaryThread()) { -+ throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously."); -+ } else if (!event.isAsynchronous() && !server.isPrimaryThread()) { -+ throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously."); - } - -- fireEvent(event); -- } -- -- private void fireEvent(@NotNull Event event) { - HandlerList handlers = event.getHandlers(); - RegisteredListener[] listeners = handlers.getRegisteredListeners(); - -diff --git a/src/test/java/org/bukkit/plugin/PluginManagerTest.java b/src/test/java/org/bukkit/plugin/PluginManagerTest.java -index f188cd4f3b07027c30d41f1162db77a506b7b6bb..1941c9f49e9514c1236c5f4ea9f7af47f7be85c5 100644 ---- a/src/test/java/org/bukkit/plugin/PluginManagerTest.java -+++ b/src/test/java/org/bukkit/plugin/PluginManagerTest.java -@@ -17,7 +17,7 @@ public class PluginManagerTest { - private static final PluginManager pm = TestServer.getInstance().getPluginManager(); - - private final MutableObject store = new MutableObject(); -- -+/* // Paper start - remove unneeded test - @Test - public void testAsyncSameThread() { - final Event event = new TestEvent(true); -@@ -28,14 +28,14 @@ public class PluginManagerTest { - return; - } - throw new IllegalStateException("No exception thrown"); -- } -+ }*/ // Paper end - - @Test - public void testSyncSameThread() { - final Event event = new TestEvent(false); - pm.callEvent(event); - } -- -+/* // Paper start - remove unneeded test - @Test - public void testAsyncLocked() throws InterruptedException { - final Event event = new TestEvent(true); -@@ -129,7 +129,7 @@ public class PluginManagerTest { - if (store.value == null) { - throw new IllegalStateException("No exception thrown"); - } -- } -+ } */ // Paper - - @Test - public void testRemovePermissionByNameLower() { diff --git a/Unmapped-Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch b/Unmapped-Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch deleted file mode 100644 index 85c5c370f3..0000000000 --- a/Unmapped-Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Thu, 2 Aug 2018 08:44:20 -0500 -Subject: [PATCH] Add hand to bucket events - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java b/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java -index 7f225baa9fd3ff6f4f950ae70f9500141c674f66..25bd8153ef2ab7ab1052cf756bb599f1095732e7 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java -@@ -5,6 +5,7 @@ import org.bukkit.block.Block; - import org.bukkit.block.BlockFace; - import org.bukkit.entity.Player; - import org.bukkit.event.HandlerList; -+import org.bukkit.inventory.EquipmentSlot; - import org.bukkit.inventory.ItemStack; - import org.jetbrains.annotations.NotNull; - -@@ -22,6 +23,16 @@ public class PlayerBucketEmptyEvent extends PlayerBucketEvent { - public PlayerBucketEmptyEvent(@NotNull final Player who, @NotNull final Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand) { - super(who, block, blockClicked, blockFace, bucket, itemInHand); - } -+ // Paper start - add EquipmentSlot -+ @Deprecated -+ public PlayerBucketEmptyEvent(@NotNull final Player who, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @org.jetbrains.annotations.Nullable final EquipmentSlot hand) { -+ super(who, blockClicked, blockFace, bucket, itemInHand, hand); -+ } -+ -+ public PlayerBucketEmptyEvent(@NotNull final Player who, @NotNull final Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @org.jetbrains.annotations.Nullable final EquipmentSlot hand) { -+ super(who, block, blockClicked, blockFace, bucket, itemInHand, hand); -+ } -+ // Paper end - - @NotNull - @Override -diff --git a/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java b/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java -index 0e4fa04ea73baaf2f9ad86725d379b569d7d6381..1e0f7ee7d198c08ce421ce105be42c4d01dc924f 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java -@@ -5,6 +5,7 @@ import org.bukkit.block.Block; - import org.bukkit.block.BlockFace; - import org.bukkit.entity.Player; - import org.bukkit.event.Cancellable; -+import org.bukkit.inventory.EquipmentSlot; - import org.bukkit.inventory.ItemStack; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; -@@ -19,6 +20,7 @@ public abstract class PlayerBucketEvent extends PlayerEvent implements Cancellab - private final Block blockClicked; - private final BlockFace blockFace; - private final Material bucket; -+ private final EquipmentSlot hand; // Paper - add EquipmentSlot - - @Deprecated - public PlayerBucketEvent(@NotNull final Player who, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand) { -@@ -26,12 +28,24 @@ public abstract class PlayerBucketEvent extends PlayerEvent implements Cancellab - } - - public PlayerBucketEvent(@NotNull final Player who, @NotNull final Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand) { -+ // Paper start - add EquipmentSlot -+ this(who, block, blockClicked, blockFace, bucket, itemInHand, null); -+ } -+ -+ @Deprecated -+ public PlayerBucketEvent(@NotNull final Player who,@NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @Nullable final EquipmentSlot hand) { -+ this(who, null, blockClicked, blockFace, bucket, itemInHand, hand); -+ } -+ -+ public PlayerBucketEvent(@NotNull final Player who, @NotNull final Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @Nullable final EquipmentSlot hand) { -+ // Paper end - super(who); - this.block = block; - this.blockClicked = blockClicked; - this.blockFace = blockFace; - this.itemStack = itemInHand; - this.bucket = bucket; -+ this.hand = hand == null ? player.getInventory().getItemInMainHand().equals(itemInHand) ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND : hand; // Paper - add EquipmentSlot - } - - /** -@@ -93,6 +107,18 @@ public abstract class PlayerBucketEvent extends PlayerEvent implements Cancellab - return blockFace; - } - -+ // Paper start -+ /** -+ * The hand used to perform this action. -+ * -+ * @return the hand used -+ */ -+ @NotNull -+ public EquipmentSlot getHand() { -+ return hand; -+ } -+ // Paper end -+ - @Override - public boolean isCancelled() { - return cancelled; -diff --git a/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java b/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java -index 77c3a6e5c89ffde564d63b98b2d9e36c356d79fd..56f1cc2d773d2c58207ee291bac596692980a731 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java -@@ -5,6 +5,7 @@ import org.bukkit.block.Block; - import org.bukkit.block.BlockFace; - import org.bukkit.entity.Player; - import org.bukkit.event.HandlerList; -+import org.bukkit.inventory.EquipmentSlot; - import org.bukkit.inventory.ItemStack; - import org.jetbrains.annotations.NotNull; - -@@ -23,6 +24,18 @@ public class PlayerBucketFillEvent extends PlayerBucketEvent { - super(who, block, blockClicked, blockFace, bucket, itemInHand); - } - -+ // Paper start - add EquipmentSlot -+ @Deprecated -+ public PlayerBucketFillEvent(@NotNull final Player who, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @org.jetbrains.annotations.Nullable final EquipmentSlot hand) { -+ super(who, blockClicked, blockFace, bucket, itemInHand, hand); -+ } -+ -+ // Paper start - add EquipmentSlot -+ public PlayerBucketFillEvent(@NotNull final Player who, @NotNull Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @org.jetbrains.annotations.Nullable final EquipmentSlot hand) { -+ super(who, block, blockClicked, blockFace, bucket, itemInHand, hand); -+ } -+ // Paper end -+ - @NotNull - @Override - public HandlerList getHandlers() { diff --git a/Unmapped-Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch b/Unmapped-Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch deleted file mode 100644 index 2bddc56f13..0000000000 --- a/Unmapped-Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 15 Jul 2018 22:17:55 +0300 -Subject: [PATCH] Add TNTPrimeEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/block/TNTPrimeEvent.java b/src/main/java/com/destroystokyo/paper/event/block/TNTPrimeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..73dabb82c7fbea3f0cccade0a2944b11a80ede06 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/block/TNTPrimeEvent.java -@@ -0,0 +1,114 @@ -+package com.destroystokyo.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when TNT block is about to turn into {@link org.bukkit.entity.TNTPrimed} -+ *

    -+ * Cancelling it won't turn TNT into {@link org.bukkit.entity.TNTPrimed} and leaves -+ * the TNT block as-is -+ * -+ * @author Mark Vainomaa -+ */ -+public class TNTPrimeEvent extends BlockEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ @NotNull private PrimeReason reason; -+ @Nullable private Entity primerEntity; -+ -+ public TNTPrimeEvent(@NotNull Block theBlock, @NotNull PrimeReason reason, @Nullable Entity primerEntity) { -+ super(theBlock); -+ this.reason = reason; -+ this.primerEntity = primerEntity; -+ } -+ -+ /** -+ * Gets the TNT prime reason -+ * -+ * @return Prime reason -+ */ -+ @NotNull -+ public PrimeReason getReason() { -+ return this.reason; -+ } -+ -+ /** -+ * Gets the TNT primer {@link Entity}. -+ * -+ * It's null if {@link #getReason()} is {@link PrimeReason#REDSTONE} or {@link PrimeReason#FIRE}. -+ * It's not null if {@link #getReason()} is {@link PrimeReason#ITEM} or {@link PrimeReason#PROJECTILE} -+ * It might be null if {@link #getReason()} is {@link PrimeReason#EXPLOSION} -+ * -+ * @return The {@link Entity} who primed the TNT -+ */ -+ @Nullable -+ public Entity getPrimerEntity() { -+ return this.primerEntity; -+ } -+ -+ /** -+ * Gets whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not -+ * -+ * @return Whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not -+ */ -+ @Override -+ public boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ /** -+ * Sets whether to cancel spawning {@link org.bukkit.entity.TNTPrimed} or not -+ * -+ * @param cancel whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @Nullable -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @Nullable -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ public enum PrimeReason { -+ /** -+ * When TNT prime was caused by other explosion (chain reaction) -+ */ -+ EXPLOSION, -+ -+ /** -+ * When TNT prime was caused by fire -+ */ -+ FIRE, -+ -+ /** -+ * When {@link org.bukkit.entity.Player} used {@link org.bukkit.Material#FLINT_AND_STEEL} or -+ * {@link org.bukkit.Material#FIRE_CHARGE} on given TNT block -+ */ -+ ITEM, -+ -+ /** -+ * When TNT prime was caused by an {@link Entity} shooting TNT -+ * using a bow with {@link org.bukkit.enchantments.Enchantment#ARROW_FIRE} enchantment -+ */ -+ PROJECTILE, -+ -+ /** -+ * When redstone power triggered the TNT prime -+ */ -+ REDSTONE -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch b/Unmapped-Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch deleted file mode 100644 index 3616f82f03..0000000000 --- a/Unmapped-Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 4 Aug 2018 19:37:35 -0400 -Subject: [PATCH] Provide Chunk Coordinates as a Long API - -Allows you to easily access the chunks X/z as a long, and a method -to look up by the long key too. - -diff --git a/src/main/java/org/bukkit/Chunk.java b/src/main/java/org/bukkit/Chunk.java -index beac1439c71fb28f1a3baecf56157237e12ccfd5..fa576096e908f8fbdbef53e1bd91215ac9e73ed6 100644 ---- a/src/main/java/org/bukkit/Chunk.java -+++ b/src/main/java/org/bukkit/Chunk.java -@@ -28,6 +28,32 @@ public interface Chunk extends PersistentDataHolder { - */ - int getZ(); - -+ // Paper start -+ /** -+ * @return The Chunks X and Z coordinates packed into a long -+ */ -+ default long getChunkKey() { -+ return getChunkKey(getX(), getZ()); -+ } -+ -+ /** -+ * @param loc Location to get chunk key -+ * @return Location's chunk coordinates packed into a long -+ */ -+ static long getChunkKey(@NotNull Location loc) { -+ return getChunkKey((int) Math.floor(loc.getX()) >> 4, (int) Math.floor(loc.getZ()) >> 4); -+ } -+ -+ /** -+ * @param x X Coordinate -+ * @param z Z Coordinate -+ * @return Chunk coordinates packed into a long -+ */ -+ static long getChunkKey(int x, int z) { -+ return (long) x & 0xffffffffL | ((long) z & 0xffffffffL) << 32; -+ } -+ // Paper end -+ - /** - * Gets the world containing this chunk - * -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 9c4f2d9e1a4011e3a9860d913e1a718030696bed..e372b3d43960ac7df58985609ef729c68fca0533 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -207,6 +207,22 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @NotNull - public Chunk getChunkAt(@NotNull Block block); - -+ // Paper start -+ /** -+ * Gets the chunk at the specified chunk key, which is the X and Z packed into a long. -+ * -+ * See {@link Chunk#getChunkKey()} for easy access to the key, or you may calculate it as: -+ * long chunkKey = (long) chunkX & 0xffffffffL | ((long) chunkZ & 0xffffffffL) >> 32; -+ * -+ * @param chunkKey The Chunk Key to look up the chunk by -+ * @return The chunk at the specified key -+ */ -+ @NotNull -+ public default Chunk getChunkAt(long chunkKey) { -+ return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); -+ } -+ // Paper end -+ - /** - * Checks if the specified {@link Chunk} is loaded - * diff --git a/Unmapped-Spigot-API-Patches/0133-Async-Chunks-API.patch b/Unmapped-Spigot-API-Patches/0133-Async-Chunks-API.patch deleted file mode 100644 index 992af6f95b..0000000000 --- a/Unmapped-Spigot-API-Patches/0133-Async-Chunks-API.patch +++ /dev/null @@ -1,534 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Feb 2016 17:43:33 -0600 -Subject: [PATCH] Async Chunks API - -Adds API's to load or generate chunks asynchronously. - -Also adds utility methods to Entity to teleport asynchronously. - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index e372b3d43960ac7df58985609ef729c68fca0533..3f231c28842f02f80fd3136c36fe99b41726137f 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -221,6 +221,482 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - public default Chunk getChunkAt(long chunkKey) { - return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); - } -+ -+ /** -+ * This is the Legacy API before Java 8 was supported. Java 8 Consumer is provided, -+ * as well as future support -+ * -+ * Used by {@link World#getChunkAtAsync(Location,ChunkLoadCallback)} methods -+ * to request a {@link Chunk} to be loaded, with this callback receiving -+ * the chunk when it is finished. -+ * -+ * This callback will be executed on synchronously on the main thread. -+ * -+ * Timing and order this callback is fired is intentionally not defined and -+ * and subject to change. -+ * -+ * @deprecated Use either the Future or the Consumer based methods -+ */ -+ @Deprecated -+ public static interface ChunkLoadCallback extends java.util.function.Consumer { -+ public void onLoad(@NotNull Chunk chunk); -+ -+ // backwards compat to old api -+ @Override -+ default void accept(@NotNull Chunk chunk) { -+ onLoad(chunk); -+ } -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link ChunkLoadCallback} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @deprecated Use either the Future or the Consumer based methods -+ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16) -+ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16) -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ @Deprecated -+ public default void getChunkAtAsync(int x, int z, @NotNull ChunkLoadCallback cb) { -+ getChunkAtAsync(x, z, true).thenAccept(cb::onLoad).exceptionally((ex) -> { -+ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); -+ return null; -+ }); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given {@link Location} -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link ChunkLoadCallback} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @deprecated Use either the Future or the Consumer based methods -+ * @param loc Location of the chunk -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ @Deprecated -+ public default void getChunkAtAsync(@NotNull Location loc, @NotNull ChunkLoadCallback cb) { -+ getChunkAtAsync(loc, true).thenAccept(cb::onLoad).exceptionally((ex) -> { -+ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); -+ return null; -+ }); -+ } -+ -+ /** -+ * Requests {@link Chunk} to be loaded that contains the given {@link Block} -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link ChunkLoadCallback} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @deprecated Use either the Future or the Consumer based methods -+ * @param block Block to get the containing chunk from -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ @Deprecated -+ public default void getChunkAtAsync(@NotNull Block block, @NotNull ChunkLoadCallback cb) { -+ getChunkAtAsync(block, true).thenAccept(cb::onLoad).exceptionally((ex) -> { -+ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); -+ return null; -+ }); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link java.util.function.Consumer} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16) -+ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16) -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ public default void getChunkAtAsync(int x, int z, @NotNull java.util.function.Consumer cb) { -+ getChunkAtAsync(x, z, true).thenAccept(cb).exceptionally((ex) -> { -+ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); -+ return null; -+ }); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link java.util.function.Consumer} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16) -+ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16) -+ * @param gen Should we generate a chunk if it doesn't exists or not -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ public default void getChunkAtAsync(int x, int z, boolean gen, @NotNull java.util.function.Consumer cb) { -+ getChunkAtAsync(x, z, gen).thenAccept(cb).exceptionally((ex) -> { -+ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); -+ return null; -+ }); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given {@link Location} -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link java.util.function.Consumer} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param loc Location of the chunk -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ public default void getChunkAtAsync(@NotNull Location loc, @NotNull java.util.function.Consumer cb) { -+ getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, true, cb); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given {@link Location} -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link java.util.function.Consumer} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param loc Location of the chunk -+ * @param gen Should the chunk generate -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ public default void getChunkAtAsync(@NotNull Location loc, boolean gen, @NotNull java.util.function.Consumer cb) { -+ getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, gen, cb); -+ } -+ -+ /** -+ * Requests {@link Chunk} to be loaded that contains the given {@link Block} -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link java.util.function.Consumer} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param block Block to get the containing chunk from -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ public default void getChunkAtAsync(@NotNull Block block, @NotNull java.util.function.Consumer cb) { -+ getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, true, cb); -+ } -+ -+ /** -+ * Requests {@link Chunk} to be loaded that contains the given {@link Block} -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link java.util.function.Consumer} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param block Block to get the containing chunk from -+ * @param gen Should the chunk generate -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ public default void getChunkAtAsync(@NotNull Block block, boolean gen, @NotNull java.util.function.Consumer cb) { -+ getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, gen, cb); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param loc Location to load the corresponding chunk from -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsync(@NotNull Location loc) { -+ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param loc Location to load the corresponding chunk from -+ * @param gen Should the chunk generate -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsync(@NotNull Location loc, boolean gen) { -+ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, gen); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param block Block to load the corresponding chunk from -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsync(@NotNull Block block) { -+ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param block Block to load the corresponding chunk from -+ * @param gen Should the chunk generate -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsync(@NotNull Block block, boolean gen) { -+ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, gen); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param x X Coord -+ * @param z Z Coord -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z) { -+ return getChunkAtAsync(x, z, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16) -+ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16) -+ * @param gen Should we generate a chunk if it doesn't exists or not -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen) { -+ return getChunkAtAsync(x, z, gen, false); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param loc Location to load the corresponding chunk from -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(@NotNull Location loc) { -+ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, true, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param loc Location to load the corresponding chunk from -+ * @param gen Should the chunk generate -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(@NotNull Location loc, boolean gen) { -+ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, gen, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param block Block to load the corresponding chunk from -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(@NotNull Block block) { -+ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, true, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param block Block to load the corresponding chunk from -+ * @param gen Should the chunk generate -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(@NotNull Block block, boolean gen) { -+ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, gen, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param x X Coord -+ * @param z Z Coord -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(int x, int z) { -+ return getChunkAtAsync(x, z, true, true); -+ } -+ -+ @NotNull -+ java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent); - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 707638c327077a74c777a603b9f2392f46b51c0c..c137199ed0537874010f1abf311a9cbee56831ac 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -163,6 +163,33 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - */ - public boolean teleport(@NotNull Entity destination, @NotNull TeleportCause cause); - -+ // Paper start -+ /** -+ * Loads/Generates(in 1.13+) the Chunk asynchronously, and then teleports the entity when the chunk is ready. -+ * @param loc Location to teleport to -+ * @return A future that will be completed with the result of the teleport -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture teleportAsync(@NotNull Location loc) { -+ return teleportAsync(loc, TeleportCause.PLUGIN); -+ } -+ /** -+ * Loads/Generates(in 1.13+) the Chunk asynchronously, and then teleports the entity when the chunk is ready. -+ * @param loc Location to teleport to -+ * @param cause Reason for teleport -+ * @return A future that will be completed with the result of the teleport -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture teleportAsync(@NotNull Location loc, @NotNull TeleportCause cause) { -+ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); -+ loc.getWorld().getChunkAtAsyncUrgently(loc).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { -+ future.completeExceptionally(ex); -+ return null; -+ }); -+ return future; -+ } -+ // Paper end -+ - /** - * Returns a list of entities within a bounding box centered around this - * entity diff --git a/Unmapped-Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch b/Unmapped-Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch deleted file mode 100644 index 6779d66171..0000000000 --- a/Unmapped-Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 10 Aug 2018 22:08:34 -0400 -Subject: [PATCH] Make EnderDragon extend Mob - - -diff --git a/src/main/java/org/bukkit/entity/EnderDragon.java b/src/main/java/org/bukkit/entity/EnderDragon.java -index c14278d2c99deedddfd9c8afdc900760b0331546..92da609fb2bdf7c6396ba868410a40725fda05f0 100644 ---- a/src/main/java/org/bukkit/entity/EnderDragon.java -+++ b/src/main/java/org/bukkit/entity/EnderDragon.java -@@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents an Ender Dragon - */ --public interface EnderDragon extends ComplexLivingEntity, Boss { -+public interface EnderDragon extends ComplexLivingEntity, Boss, org.bukkit.entity.Mob { // Paper - add Mob - - /** - * Represents a phase or action that an Ender Dragon can perform. diff --git a/Unmapped-Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/Unmapped-Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch deleted file mode 100644 index cbe8cd6f69..0000000000 --- a/Unmapped-Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 15 Aug 2018 01:04:58 -0400 -Subject: [PATCH] Ability to get Tile Entities from a chunk without snapshots - - -diff --git a/src/main/java/org/bukkit/Chunk.java b/src/main/java/org/bukkit/Chunk.java -index fa576096e908f8fbdbef53e1bd91215ac9e73ed6..98263d896f316983609432c45b85401a2692432d 100644 ---- a/src/main/java/org/bukkit/Chunk.java -+++ b/src/main/java/org/bukkit/Chunk.java -@@ -1,6 +1,8 @@ - package org.bukkit; - - import java.util.Collection; -+import java.util.function.Predicate; -+ - import org.bukkit.block.Block; - import org.bukkit.block.BlockState; - import org.bukkit.block.data.BlockData; -@@ -103,13 +105,36 @@ public interface Chunk extends PersistentDataHolder { - @NotNull - Entity[] getEntities(); - -+ // Paper start - /** - * Get a list of all tile entities in the chunk. - * - * @return The tile entities. - */ - @NotNull -- BlockState[] getTileEntities(); -+ default BlockState[] getTileEntities() { -+ return getTileEntities(true); -+ } -+ -+ /** -+ * Get a list of all tile entities in the chunk. -+ * -+ * @param useSnapshot Take snapshots or direct references -+ * @return The tile entities. -+ */ -+ @NotNull -+ BlockState[] getTileEntities(boolean useSnapshot); -+ -+ /** -+ * Get a list of all tile entities that match a given predicate in the chunk. -+ * -+ * @param blockPredicate The predicate of blocks to return tile entities for -+ * @param useSnapshot Take snapshots or direct references -+ * @return The tile entities. -+ */ -+ @NotNull -+ Collection getTileEntities(@NotNull Predicate blockPredicate, boolean useSnapshot); -+ // Paper end - - /** - * Checks if the chunk is loaded. diff --git a/Unmapped-Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch b/Unmapped-Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch deleted file mode 100644 index 536fdc2d06..0000000000 --- a/Unmapped-Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 15 Aug 2018 01:19:37 -0400 -Subject: [PATCH] Don't use snapshots for Timings Tile Entity reports - - -diff --git a/src/main/java/co/aikar/timings/TimingHistory.java b/src/main/java/co/aikar/timings/TimingHistory.java -index ddaed81275fcc12d1671b668697acf318e96888b..203cda0f9a4dea4f28a21ea9ee8db7a7369842e3 100644 ---- a/src/main/java/co/aikar/timings/TimingHistory.java -+++ b/src/main/java/co/aikar/timings/TimingHistory.java -@@ -119,7 +119,7 @@ public class TimingHistory { - data.entityCounts.get(entity.getType()).increment(); - } - -- for (BlockState tileEntity : chunk.getTileEntities()) { -+ for (BlockState tileEntity : chunk.getTileEntities(false)) { - if (tileEntity == null) { - Bukkit.getLogger().warning("Null tileentity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ()); - continue; diff --git a/Unmapped-Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch b/Unmapped-Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch deleted file mode 100644 index 568d6bcd6e..0000000000 --- a/Unmapped-Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 14 Aug 2018 21:42:10 -0700 -Subject: [PATCH] Allow Blocks to be accessed via a long key - -The key can be retrieved via methods Location#toBlockKey() and -Block#getBlockKey() - -World provides lookup for blocks by long key via method World#getBlockAtKey(long) - -The formatting for the key is as follows: - -10 bit y|27 bit z|27 bit x - -The y value is considered unsigned while z and x are considered two's complement - -Y range: [0, 1023] -X, Z range: [-67 108 864, 67 108 863] - -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index 369ce9ff6c8bb97a64a8e229115564412e6e7654..e700875beb76dadd55b585aca748338def286908 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -15,7 +15,6 @@ import org.jetbrains.annotations.Nullable; - - // Paper start - import java.util.Collection; --import java.util.Collections; - import java.util.function.Predicate; - import org.bukkit.entity.Entity; - import org.bukkit.entity.LivingEntity; -@@ -605,6 +604,17 @@ public class Location implements Cloneable, ConfigurationSerializable { - blockLoc.setZ(getBlockZ()); - return blockLoc; - } -+ -+ // Paper Start -+ /** -+ * @return The block key for this location's block location. -+ * @see Block#getBlockKey(int, int, int) -+ */ -+ public long toBlockKey() { -+ return Block.getBlockKey(getBlockX(), getBlockY(), getBlockZ()); -+ } -+ // Paper End -+ - /** - * @return A new location where X/Y/Z are the center of the block - */ -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 3f231c28842f02f80fd3136c36fe99b41726137f..d8674c773d61517f79d0fe77276392e47fd3e1e1 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -90,6 +90,38 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @NotNull - public Block getBlockAt(@NotNull Location location); - -+ // Paper start -+ /** -+ * Gets the {@link Block} at the given block key -+ * -+ * @param key The block key. See {@link Block#getBlockKey()} -+ * @return Block at the key -+ * @see Block#getBlockKey(int, int, int) -+ */ -+ @NotNull -+ public default Block getBlockAtKey(long key) { -+ int x = Block.getBlockKeyX(key); -+ int y = Block.getBlockKeyY(key); -+ int z = Block.getBlockKeyZ(key); -+ return getBlockAt(x, y, z); -+ } -+ -+ /** -+ * Gets the {@link Location} at the given block key -+ * -+ * @param key The block key. See {@link Location#toBlockKey()} -+ * @return Location at the key -+ * @see Block#getBlockKey(int, int, int) -+ */ -+ @NotNull -+ public default Location getLocationAtKey(long key) { -+ int x = Block.getBlockKeyX(key); -+ int y = Block.getBlockKeyY(key); -+ int z = Block.getBlockKeyZ(key); -+ return new Location(this, x, y, z); -+ } -+ // Paper end -+ - /** - * Gets the highest non-empty (impassable) coordinate at the given - * coordinates. -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index e89c8079625525667f496c06207da655fe43d749..d6f74dbcfeb153d4b17be2827e2989f2d8160d21 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -153,6 +153,72 @@ public interface Block extends Metadatable { - */ - int getZ(); - -+ // Paper Start -+ /** -+ * Returns this block's coordinates packed into a long value. -+ * Computed via: {@code Block.getBlockKey(this.getX(), this.getY(), this.getZ())} -+ * @see Block#getBlockKey(int, int, int) -+ * @return This block's x, y, and z coordinates packed into a long value -+ */ -+ public default long getBlockKey() { -+ return Block.getBlockKey(this.getX(), this.getY(), this.getZ()); -+ } -+ -+ /** -+ * Returns the specified block coordinates packed into a long value -+ *

    -+ * The return value can be computed as follows: -+ *
    -+ * {@code long value = ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54);} -+ *

    -+ * -+ *

    -+ * And may be unpacked as follows: -+ *
    -+ * {@code int x = (int) ((packed << 37) >> 37);} -+ *
    -+ * {@code int y = (int) (packed >>> 54);} -+ *
    -+ * {@code int z = (int) ((packed << 10) >> 37);} -+ *

    -+ * -+ * @return This block's x, y, and z coordinates packed into a long value -+ */ -+ public static long getBlockKey(int x, int y, int z) { -+ return ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54); -+ } -+ -+ /** -+ * Returns the x component from the packed value. -+ * @param packed The packed value, as computed by {@link Block#getBlockKey(int, int, int)} -+ * @see Block#getBlockKey(int, int, int) -+ * @return The x component from the packed value. -+ */ -+ public static int getBlockKeyX(long packed) { -+ return (int) ((packed << 37) >> 37); -+ } -+ -+ /** -+ * Returns the y component from the packed value. -+ * @param packed The packed value, as computed by {@link Block#getBlockKey(int, int, int)} -+ * @see Block#getBlockKey(int, int, int) -+ * @return The y component from the packed value. -+ */ -+ public static int getBlockKeyY(long packed) { -+ return (int) (packed >>> 54); -+ } -+ -+ /** -+ * Returns the z component from the packed value. -+ * @param packed The packed value, as computed by {@link Block#getBlockKey(int, int, int)} -+ * @see Block#getBlockKey(int, int, int) -+ * @return The z component from the packed value. -+ */ -+ public static int getBlockKeyZ(long packed) { -+ return (int) ((packed << 10) >> 37); -+ } -+ // Paper End -+ - /** - * Gets the Location of the block - * diff --git a/Unmapped-Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch b/Unmapped-Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch deleted file mode 100644 index 8d27bd1b14..0000000000 --- a/Unmapped-Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch +++ /dev/null @@ -1,217 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 08:18:27 -0500 -Subject: [PATCH] Slime Pathfinder Events - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimeChangeDirectionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimeChangeDirectionEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2638bbd3e1392b3d8640be58163f6eb2789dee4a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimeChangeDirectionEvent.java -@@ -0,0 +1,38 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Slime; -+import org.bukkit.event.Cancellable; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Slime decides to change it's facing direction. -+ *

    -+ * This event does not fire for the entity's actual movement. Only when it -+ * is choosing to change direction. -+ */ -+public class SlimeChangeDirectionEvent extends SlimePathfindEvent implements Cancellable { -+ private float yaw; -+ -+ public SlimeChangeDirectionEvent(@NotNull Slime slime, float yaw) { -+ super(slime); -+ this.yaw = yaw; -+ } -+ -+ /** -+ * Get the new chosen yaw -+ * -+ * @return Chosen yaw -+ */ -+ public float getNewYaw() { -+ return yaw; -+ } -+ -+ /** -+ * Set the new chosen yaw -+ * -+ * @param yaw Chosen yaw -+ */ -+ public void setNewYaw(float yaw) { -+ this.yaw = yaw; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimePathfindEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimePathfindEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..14b67da109321ae6521eab2ac6f6945f05d02db5 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimePathfindEvent.java -@@ -0,0 +1,53 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Slime; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Slime decides to start pathfinding. -+ *

    -+ * This event does not fire for the entity's actual movement. Only when it -+ * is choosing to start moving. -+ */ -+public class SlimePathfindEvent extends EntityEvent implements Cancellable { -+ public SlimePathfindEvent(@NotNull Slime slime) { -+ super(slime); -+ } -+ -+ /** -+ * The Slime that is pathfinding. -+ * -+ * @return The Slime that is pathfinding. -+ */ -+ @NotNull -+ public Slime getEntity() { -+ return (Slime) entity; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimeSwimEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimeSwimEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c8dd49d11da5a90a1bac965a75f2b65fd825f3f7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimeSwimEvent.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Slime; -+import org.bukkit.event.Cancellable; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Slime decides to start jumping while swimming in water/lava. -+ *

    -+ * This event does not fire for the entity's actual movement. Only when it -+ * is choosing to start jumping. -+ */ -+public class SlimeSwimEvent extends SlimeWanderEvent implements Cancellable { -+ public SlimeSwimEvent(@NotNull Slime slime) { -+ super(slime); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimeTargetLivingEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimeTargetLivingEntityEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e9ba32799ed838779e49cd4c5011b7515b3363cb ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimeTargetLivingEntityEvent.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Slime; -+import org.bukkit.event.Cancellable; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Slime decides to change direction to target a LivingEntity. -+ *

    -+ * This event does not fire for the entity's actual movement. Only when it -+ * is choosing to start moving. -+ */ -+public class SlimeTargetLivingEntityEvent extends SlimePathfindEvent implements Cancellable { -+ @NotNull private final LivingEntity target; -+ -+ public SlimeTargetLivingEntityEvent(@NotNull Slime slime, @NotNull LivingEntity target) { -+ super(slime); -+ this.target = target; -+ } -+ -+ /** -+ * Get the targeted entity -+ * -+ * @return Targeted entity -+ */ -+ @NotNull -+ public LivingEntity getTarget() { -+ return target; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimeWanderEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimeWanderEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4683a7237d2ed527fc85b9b4e5b2eaaf5ae3d797 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimeWanderEvent.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Slime; -+import org.bukkit.event.Cancellable; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Slime decides to start wandering. -+ *

    -+ * This event does not fire for the entity's actual movement. Only when it -+ * is choosing to start moving. -+ */ -+public class SlimeWanderEvent extends SlimePathfindEvent implements Cancellable { -+ public SlimeWanderEvent(@NotNull Slime slime) { -+ super(slime); -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Slime.java b/src/main/java/org/bukkit/entity/Slime.java -index 1119e26e270bb45f517955b19d95a9ec3d113634..c4791f95d788d3a9e013dc89d8e64103ad8480a1 100644 ---- a/src/main/java/org/bukkit/entity/Slime.java -+++ b/src/main/java/org/bukkit/entity/Slime.java -@@ -14,4 +14,20 @@ public interface Slime extends Mob { - * @param sz The new size of the slime. - */ - public void setSize(int sz); -+ -+ // Paper start -+ /** -+ * Get whether this slime can randomly wander/jump around on its own -+ * -+ * @return true if can wander -+ */ -+ public boolean canWander(); -+ -+ /** -+ * Set whether this slime can randomly wander/jump around on its own -+ * -+ * @param canWander true if can wander -+ */ -+ public void setWander(boolean canWander); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0139-isChunkGenerated-API.patch b/Unmapped-Spigot-API-Patches/0139-isChunkGenerated-API.patch deleted file mode 100644 index a26301e9c3..0000000000 --- a/Unmapped-Spigot-API-Patches/0139-isChunkGenerated-API.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: cswhite2000 <18whitechristop@gmail.com> -Date: Tue, 21 Aug 2018 19:39:46 -0700 -Subject: [PATCH] isChunkGenerated API - - -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index e700875beb76dadd55b585aca748338def286908..9c91c49ed7302c12fcb1d8e9bc58712efc199954 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -3,6 +3,7 @@ package org.bukkit; - import com.google.common.base.Preconditions; - import java.lang.ref.Reference; - import java.lang.ref.WeakReference; -+import com.google.common.base.Preconditions; // Paper - import java.util.HashMap; - import java.util.Map; - import org.bukkit.block.Block; -@@ -545,6 +546,16 @@ public class Location implements Cloneable, ConfigurationSerializable { - public boolean isChunkLoaded() { return this.getWorld().isChunkLoaded(locToBlock(x) >> 4, locToBlock(z) >> 4); } // Paper - - // Paper start -+ /** -+ * Checks if a {@link Chunk} has been generated at this location. -+ * -+ * @return true if a chunk has been generated at this location -+ */ -+ public boolean isGenerated() { -+ World world = this.getWorld(); -+ Preconditions.checkNotNull(world, "Location has no world!"); -+ return world.isChunkGenerated(locToBlock(x) >> 4, locToBlock(z) >> 4); -+ } - - /** - * Sets the position of this Location and returns itself -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index d8674c773d61517f79d0fe77276392e47fd3e1e1..cf831f96efa302f789cf26a384a091df51215a76 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -254,6 +254,17 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); - } - -+ /** -+ * Checks if a {@link Chunk} has been generated at the specified chunk key, -+ * which is the X and Z packed into a long. -+ * -+ * @param chunkKey The Chunk Key to look up the chunk by -+ * @return true if the chunk has been generated, otherwise false -+ */ -+ public default boolean isChunkGenerated(long chunkKey) { -+ return isChunkGenerated((int) chunkKey, (int) (chunkKey >> 32)); -+ } -+ - /** - * This is the Legacy API before Java 8 was supported. Java 8 Consumer is provided, - * as well as future support diff --git a/Unmapped-Spigot-API-Patches/0140-Add-More-Creeper-API.patch b/Unmapped-Spigot-API-Patches/0140-Add-More-Creeper-API.patch deleted file mode 100644 index b45e2fbeba..0000000000 --- a/Unmapped-Spigot-API-Patches/0140-Add-More-Creeper-API.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 11:50:16 -0500 -Subject: [PATCH] Add More Creeper API - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/CreeperIgniteEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/CreeperIgniteEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ff10251b6ded533b08048ec533525176eff03707 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/CreeperIgniteEvent.java -@@ -0,0 +1,54 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Creeper; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a Creeper is ignite flag is changed (armed/disarmed to explode). -+ */ -+public class CreeperIgniteEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean canceled; -+ private boolean ignited; -+ -+ public CreeperIgniteEvent(@NotNull Creeper creeper, boolean ignited) { -+ super(creeper); -+ this.ignited = ignited; -+ } -+ -+ @NotNull -+ @Override -+ public Creeper getEntity() { -+ return (Creeper) entity; -+ } -+ -+ public boolean isIgnited() { -+ return ignited; -+ } -+ -+ public void setIgnited(boolean ignited) { -+ this.ignited = ignited; -+ } -+ -+ public boolean isCancelled() { -+ return canceled; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ canceled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Creeper.java b/src/main/java/org/bukkit/entity/Creeper.java -index 5793193d93d76a062fd0431475c269c4978ec993..e144f618702122bf28ebedc5cb8ce0f6ef27c107 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. - */ - public void ignite(); -+ // Paper start -+ -+ /** -+ * Set whether creeper is ignited or not (armed to explode) -+ * -+ * @param ignited New ignited state -+ */ -+ public void setIgnited(boolean ignited); -+ -+ /** -+ * Check if creeper is ignited or not (armed to explode) -+ * -+ * @return Ignited state -+ */ -+ public boolean isIgnited(); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch b/Unmapped-Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch deleted file mode 100644 index 5ffdc818cb..0000000000 --- a/Unmapped-Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 25 Aug 2018 19:56:42 -0500 -Subject: [PATCH] Add PhantomPreSpawnEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PhantomPreSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PhantomPreSpawnEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9022f697ab244df43074e48c9150f39d44217531 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/PhantomPreSpawnEvent.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.EntityType; -+import org.bukkit.event.entity.CreatureSpawnEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+ -+/** -+ * Called when a phantom is spawned for an exhausted player -+ */ -+public class PhantomPreSpawnEvent extends PreCreatureSpawnEvent { -+ @NotNull private final Entity entity; -+ -+ public PhantomPreSpawnEvent(@NotNull Location location, @NotNull Entity entity, @NotNull CreatureSpawnEvent.SpawnReason reason) { -+ super(location, EntityType.PHANTOM, reason); -+ this.entity = entity; -+ } -+ -+ /** -+ * Get the entity this phantom is spawning for -+ * -+ * @return Entity -+ */ -+ @Nullable -+ public Entity getSpawningEntity() { -+ return entity; -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Phantom.java b/src/main/java/org/bukkit/entity/Phantom.java -index 1a1044edc57078f96c4a95c994d0865da382c152..ed4d417c2deefb78807cb61b01df5afcd334d754 100644 ---- a/src/main/java/org/bukkit/entity/Phantom.java -+++ b/src/main/java/org/bukkit/entity/Phantom.java -@@ -1,5 +1,8 @@ - package org.bukkit.entity; - -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ - /** - * Represents a phantom. - */ -@@ -14,4 +17,14 @@ public interface Phantom extends Flying { - * @param sz The new size of the phantom. - */ - public void setSize(int sz); -+ -+ // Paper start -+ /** -+ * Get the UUID of the entity that caused this phantom to spawn -+ * -+ * @return UUID -+ */ -+ @Nullable -+ public java.util.UUID getSpawningEntity(); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch b/Unmapped-Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch deleted file mode 100644 index 965de7c24a..0000000000 --- a/Unmapped-Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sotr -Date: Thu, 23 Aug 2018 16:14:25 +0800 -Subject: [PATCH] Add source block to BlockPhysicsEvent - - -diff --git a/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java b/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java -index e3a5f5824ed882058f5bac5003f66ce79733a868..c382f9fc2b8c5b959df7071007110dab737e400e 100644 ---- a/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java -@@ -32,6 +32,13 @@ public class BlockPhysicsEvent extends BlockEvent implements Cancellable { - private final Block sourceBlock; - private boolean cancel = false; - -+ // Paper start - Legacy constructor, use #BlockPhysicsEvent(Block, BlockData, Block) -+ @Deprecated -+ public BlockPhysicsEvent(final Block block, final BlockData changed, final int sourceX, final int sourceY, final int sourceZ) { -+ this(block, changed, block.getWorld().getBlockAt(sourceX, sourceY, sourceZ)); -+ } -+ // Paper end -+ - public BlockPhysicsEvent(@NotNull final Block block, @NotNull final BlockData changed) { - this(block, changed, block); - } diff --git a/Unmapped-Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch b/Unmapped-Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch deleted file mode 100644 index 4d6f2e9e57..0000000000 --- a/Unmapped-Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 28 Aug 2018 23:04:06 -0400 -Subject: [PATCH] Inventory#removeItemAnySlot - - -diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java -index 5576a6a8df8c95164bf2dde45d756ce8b7ec957a..9c6a5bdac8c3ab682bbfae04ff24b76a62bc2883 100644 ---- a/src/main/java/org/bukkit/inventory/Inventory.java -+++ b/src/main/java/org/bukkit/inventory/Inventory.java -@@ -125,6 +125,34 @@ public interface Inventory extends Iterable { - @NotNull - public HashMap removeItem(@NotNull ItemStack... items) throws IllegalArgumentException; - -+ // Paper start -+ /** -+ * Searches all possible inventory slots in order to remove the given ItemStacks. -+ *

    -+ * Similar to {@link Inventory#removeItem(ItemStack...)} in behavior, except this -+ * method will check all possible slots in the inventory, rather than just the main -+ * storage contents. -+ *

    -+ * It will try to remove 'as much as possible' from the types and amounts -+ * you give as arguments. -+ *

    -+ * The returned HashMap contains what it couldn't remove, where the key is -+ * the index of the parameter, and the value is the ItemStack at that -+ * index of the varargs parameter. If all the given ItemStacks are -+ * removed, it will return an empty HashMap. -+ *

    -+ * It is known that in some implementations this method will also set the -+ * inputted argument amount to the number of that item not removed from -+ * slots. -+ * -+ * @param items The ItemStacks to remove -+ * @return A HashMap containing items that couldn't be removed. -+ * @throws IllegalArgumentException if items is null -+ */ -+ @NotNull -+ public HashMap removeItemAnySlot(@NotNull ItemStack... items) throws IllegalArgumentException; -+ // Paper end -+ - /** - * Returns all ItemStacks from the inventory - * diff --git a/Unmapped-Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch b/Unmapped-Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch deleted file mode 100644 index 96c37c9d46..0000000000 --- a/Unmapped-Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 3 Sep 2018 18:13:53 -0500 -Subject: [PATCH] Add ray tracing methods to LivingEntity - - -diff --git a/src/main/java/com/destroystokyo/paper/block/TargetBlockInfo.java b/src/main/java/com/destroystokyo/paper/block/TargetBlockInfo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..18a96dbb01d3b34476652264b2d6be3782a154ec ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/block/TargetBlockInfo.java -@@ -0,0 +1,54 @@ -+package com.destroystokyo.paper.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.block.BlockFace; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents information about a targeted block -+ */ -+public class TargetBlockInfo { -+ private final Block block; -+ private final BlockFace blockFace; -+ -+ public TargetBlockInfo(@NotNull Block block, @NotNull BlockFace blockFace) { -+ this.block = block; -+ this.blockFace = blockFace; -+ } -+ -+ /** -+ * Get the block that is targeted -+ * -+ * @return Targeted block -+ */ -+ @NotNull -+ public Block getBlock() { -+ return block; -+ } -+ -+ /** -+ * Get the targeted BlockFace -+ * -+ * @return Targeted blockface -+ */ -+ @NotNull -+ public BlockFace getBlockFace() { -+ return blockFace; -+ } -+ -+ /** -+ * Get the relative Block to the targeted block on the side it is targeted at -+ * -+ * @return Block relative to targeted block -+ */ -+ @NotNull -+ public Block getRelativeBlock() { -+ return block.getRelative(blockFace); -+ } -+ -+ public enum FluidMode { -+ NEVER, -+ SOURCE_ONLY, -+ ALWAYS -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 8b89c0701dd557bcab0c05c1593354ee704b9fe4..8fe7ccf12339355554835542cc1068d9f6c3a435 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -82,6 +82,77 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - @NotNull - public Block getTargetBlock(@Nullable Set transparent, int maxDistance); - -+ // Paper start -+ /** -+ * Gets the block that the living entity has targeted, ignoring fluids -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @return block that the living entity has targeted, -+ * or null if no block is within maxDistance -+ */ -+ @Nullable -+ public default Block getTargetBlock(int maxDistance) { -+ return getTargetBlock(maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode.NEVER); -+ } -+ -+ /** -+ * Gets the block that the living entity has targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @param fluidMode whether to check fluids or not -+ * @return block that the living entity has targeted, -+ * or null if no block is within maxDistance -+ */ -+ @Nullable -+ public Block getTargetBlock(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode); -+ -+ /** -+ * Gets the blockface of that block that the living entity has targeted, ignoring fluids -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @return blockface of the block that the living entity has targeted, -+ * or null if no block is targeted -+ */ -+ @Nullable -+ public default org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance) { -+ return getTargetBlockFace(maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode.NEVER); -+ } -+ -+ /** -+ * Gets the blockface of that block that the living entity has targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @param fluidMode whether to check fluids or not -+ * @return blockface of the block that the living entity has targeted, -+ * or null if no block is targeted -+ */ -+ @Nullable -+ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode); -+ -+ /** -+ * Gets information about the block the living entity has targeted, ignoring fluids -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @return TargetBlockInfo about the block the living entity has targeted, -+ * or null if no block is targeted -+ */ -+ @Nullable -+ public default com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance) { -+ return getTargetBlockInfo(maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode.NEVER); -+ } -+ -+ /** -+ * Gets information about the block the living entity has targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @param fluidMode whether to check fluids or not -+ * @return TargetBlockInfo about the block the living entity has targeted, -+ * or null if no block is targeted -+ */ -+ @Nullable -+ public com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode); -+ // Paper end -+ - /** - * Gets the last two blocks along the living entity's line of sight. - *

    diff --git a/Unmapped-Spigot-API-Patches/0145-Improve-death-events.patch b/Unmapped-Spigot-API-Patches/0145-Improve-death-events.patch deleted file mode 100644 index f42921460c..0000000000 --- a/Unmapped-Spigot-API-Patches/0145-Improve-death-events.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 21 Aug 2018 01:32:28 +0100 -Subject: [PATCH] Improve death events - -This adds the ability to cancel the death events and to modify the sound -an entity makes when dying. (In cases were no sound should it will be -called with shouldPlaySound set to false allowing unsilencing of silent -entities) - -It makes handling of entity deaths a lot nicer as you no longer need -to listen on the damage event and calculate if the entity dies yourself -to cancel the death which has the benefit of also receiving the dropped -items and experience which is otherwise only properly possible by using -internal code. - -diff --git a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java -index a5984ab06cce95d30e70511e125f69339b574c04..e19a3df9aa2204b44c0b029bda141ae6306f60a1 100644 ---- a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java -+++ b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java -@@ -5,14 +5,24 @@ import org.bukkit.entity.LivingEntity; - import org.bukkit.event.HandlerList; - import org.bukkit.inventory.ItemStack; - import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; - - /** - * Thrown whenever a LivingEntity dies - */ --public class EntityDeathEvent extends EntityEvent { -+public class EntityDeathEvent extends EntityEvent implements org.bukkit.event.Cancellable { // Paper - make cancellable - private static final HandlerList handlers = new HandlerList(); - private final List drops; - private int dropExp = 0; -+ // Paper start - make cancellable -+ private boolean cancelled; -+ private double reviveHealth = 0; -+ private boolean shouldPlayDeathSound; -+ @Nullable private org.bukkit.Sound deathSound; -+ @Nullable private org.bukkit.SoundCategory deathSoundCategory; -+ private float deathSoundVolume; -+ private float deathSoundPitch; -+ // Paper end - - public EntityDeathEvent(@NotNull final LivingEntity entity, @NotNull final List drops) { - this(entity, drops, 0); -@@ -74,4 +84,134 @@ public class EntityDeathEvent extends EntityEvent { - public static HandlerList getHandlerList() { - return handlers; - } -+ -+ // Paper start - make cancellable -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ /** -+ * Get the amount of health that the entity should revive with after cancelling the event. -+ * Set to the entity's max health by default. -+ * -+ * @return The amount of health -+ */ -+ public double getReviveHealth() { -+ return reviveHealth; -+ } -+ -+ /** -+ * Set the amount of health that the entity should revive with after cancelling the event. -+ * Revive health value must be between 0 (exclusive) and the entity's max health (inclusive). -+ * -+ * @param reviveHealth The amount of health -+ * @throws IllegalArgumentException Thrown if the health is {@literal <= 0 or >} max health -+ */ -+ public void setReviveHealth(double reviveHealth) throws IllegalArgumentException { -+ double maxHealth = ((LivingEntity) entity).getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue(); -+ if ((maxHealth != 0 && reviveHealth <= 0) || (reviveHealth > maxHealth)) { -+ throw new IllegalArgumentException("Health must be between 0 (exclusive) and " + maxHealth + " (inclusive), but was " + reviveHealth); -+ } -+ this.reviveHealth = reviveHealth; -+ } -+ -+ -+ /** -+ * Whether or not the death sound should play when the entity dies. If the event is cancelled it does not play! -+ * -+ * @return Whether or not the death sound should play. Event is called with this set to false if the entity is silent. -+ */ -+ public boolean shouldPlayDeathSound() { -+ return shouldPlayDeathSound; -+ } -+ -+ /** -+ * Set whether or not the death sound should play when the entity dies. If the event is cancelled it does not play! -+ * -+ * @param playDeathSound Enable or disable the death sound -+ */ -+ public void setShouldPlayDeathSound(boolean playDeathSound) { -+ this.shouldPlayDeathSound = playDeathSound; -+ } -+ -+ /** -+ * Get the sound that the entity makes when dying -+ * -+ * @return The sound that the entity makes -+ */ -+ @Nullable -+ public org.bukkit.Sound getDeathSound() { -+ return deathSound; -+ } -+ -+ /** -+ * Set the sound that the entity makes when dying -+ * -+ * @param sound The sound that the entity should make when dying -+ */ -+ public void setDeathSound(@Nullable org.bukkit.Sound sound) { -+ deathSound = sound; -+ } -+ -+ /** -+ * Get the sound category that the death sound should play in -+ * -+ * @return The sound category -+ */ -+ @Nullable -+ public org.bukkit.SoundCategory getDeathSoundCategory() { -+ return deathSoundCategory; -+ } -+ -+ /** -+ * Set the sound category that the death sound should play in. -+ * -+ * @param soundCategory The sound category -+ */ -+ public void setDeathSoundCategory(@Nullable org.bukkit.SoundCategory soundCategory) { -+ this.deathSoundCategory = soundCategory; -+ } -+ -+ /** -+ * Get the volume that the death sound will play at. -+ * -+ * @return The volume the death sound will play at -+ */ -+ public float getDeathSoundVolume() { -+ return deathSoundVolume; -+ } -+ -+ /** -+ * Set the volume the death sound should play at. If the event is cancelled this will not play the sound! -+ * -+ * @param volume The volume the death sound should play at -+ */ -+ public void setDeathSoundVolume(float volume) { -+ this.deathSoundVolume = volume; -+ } -+ -+ /** -+ * Get the pitch that the death sound will play with. -+ * -+ * @return The pitch the death sound will play with -+ */ -+ public float getDeathSoundPitch() { -+ return deathSoundPitch; -+ } -+ -+ /** -+ * GSetet the pitch that the death sound should play with. -+ * -+ * @param pitch The pitch the death sound should play with -+ */ -+ public void setDeathSoundPitch(float pitch) { -+ this.deathSoundPitch = pitch; -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0146-Mob-Pathfinding-API.patch b/Unmapped-Spigot-API-Patches/0146-Mob-Pathfinding-API.patch deleted file mode 100644 index 8408100069..0000000000 --- a/Unmapped-Spigot-API-Patches/0146-Mob-Pathfinding-API.patch +++ /dev/null @@ -1,259 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 9 Sep 2018 12:39:06 -0400 -Subject: [PATCH] Mob Pathfinding API - -Adds an API to allow plugins to instruct a Mob to Pathfind to a Location or Entity - -This does not do anything to stop other AI rules from changing the location, so -it is still up to the plugin to control that or override after another goal changed -the location. - -You can use EntityPathfindEvent to cancel new pathfinds from overriding your current. - -diff --git a/src/main/java/com/destroystokyo/paper/entity/Pathfinder.java b/src/main/java/com/destroystokyo/paper/entity/Pathfinder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e2a6f9c3881ff9d7373ac30e60009200432555aa ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/Pathfinder.java -@@ -0,0 +1,212 @@ -+package com.destroystokyo.paper.entity; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Mob; -+ -+import java.util.List; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Handles pathfinding operations for an Entity -+ */ -+public interface Pathfinder { -+ -+ /** -+ * -+ * @return The entity that is controlled by this pathfinder -+ */ -+ @NotNull -+ Mob getEntity(); -+ -+ /** -+ * Instructs the Entity to stop trying to navigate to its current desired location -+ */ -+ void stopPathfinding(); -+ -+ /** -+ * If the entity is currently trying to navigate to a destination, this will return true -+ * @return true if the entity is navigating to a destination -+ */ -+ boolean hasPath(); -+ -+ /** -+ * @return The location the entity is trying to navigate to, or null if there is no destination -+ */ -+ @Nullable -+ PathResult getCurrentPath(); -+ -+ /** -+ * Calculates a destination for the Entity to navigate to, but does not set it -+ * as the current target. Useful for calculating what would happen before setting it. -+ * @param loc Location to navigate to -+ * @return The closest Location the Entity can get to for this navigation, or null if no path could be calculated -+ */ -+ @Nullable PathResult findPath(@NotNull Location loc); -+ -+ /** -+ * Calculates a destination for the Entity to navigate to to reach the target entity, -+ * but does not set it as the current target. -+ * Useful for calculating what would happen before setting it. -+ * -+ * The behavior of this PathResult is subject to the games pathfinding rules, and may -+ * result in the pathfinding automatically updating to follow the target Entity. -+ * -+ * However, this behavior is not guaranteed, and is subject to the games behavior. -+ * -+ * @param target the Entity to navigate to -+ * @return The closest Location the Entity can get to for this navigation, or null if no path could be calculated -+ */ -+ @Nullable PathResult findPath(@NotNull LivingEntity target); -+ -+ /** -+ * Calculates a destination for the Entity to navigate to, and sets it with default speed -+ * as the current target. -+ * @param loc Location to navigate to -+ * @return If the pathfinding was successfully started -+ */ -+ default boolean moveTo(@NotNull Location loc) { -+ return moveTo(loc, 1); -+ } -+ -+ /** -+ * Calculates a destination for the Entity to navigate to, with desired speed -+ * as the current target. -+ * @param loc Location to navigate to -+ * @param speed Speed multiplier to navigate at, where 1 is 'normal' -+ * @return If the pathfinding was successfully started -+ */ -+ default boolean moveTo(@NotNull Location loc, double speed) { -+ PathResult path = findPath(loc); -+ return path != null && moveTo(path, speed); -+ } -+ -+ /** -+ * Calculates a destination for the Entity to navigate to to reach the target entity, -+ * and sets it with default speed. -+ * -+ * The behavior of this PathResult is subject to the games pathfinding rules, and may -+ * result in the pathfinding automatically updating to follow the target Entity. -+ * -+ * However, this behavior is not guaranteed, and is subject to the games behavior. -+ * -+ * @param target the Entity to navigate to -+ * @return If the pathfinding was successfully started -+ */ -+ default boolean moveTo(@NotNull LivingEntity target) { -+ return moveTo(target, 1); -+ } -+ -+ /** -+ * Calculates a destination for the Entity to navigate to to reach the target entity, -+ * and sets it with specified speed. -+ * -+ * The behavior of this PathResult is subject to the games pathfinding rules, and may -+ * result in the pathfinding automatically updating to follow the target Entity. -+ * -+ * However, this behavior is not guaranteed, and is subject to the games behavior. -+ * -+ * @param target the Entity to navigate to -+ * @param speed Speed multiplier to navigate at, where 1 is 'normal' -+ * @return If the pathfinding was successfully started -+ */ -+ default boolean moveTo(@NotNull LivingEntity target, double speed) { -+ PathResult path = findPath(target); -+ return path != null && moveTo(path, speed); -+ } -+ -+ /** -+ * Takes the result of a previous pathfinding calculation and sets it -+ * as the active pathfinding with default speed. -+ * -+ * @param path The Path to start following -+ * @return If the pathfinding was successfully started -+ */ -+ default boolean moveTo(@NotNull PathResult path) { -+ return moveTo(path, 1); -+ } -+ -+ /** -+ * Takes the result of a previous pathfinding calculation and sets it -+ * as the active pathfinding, -+ * -+ * @param path The Path to start following -+ * @param speed Speed multiplier to navigate at, where 1 is 'normal' -+ * @return If the pathfinding was successfully started -+ */ -+ boolean moveTo(@NotNull PathResult path, double speed); -+ -+ /** -+ * Checks if this pathfinder allows passing through closed doors. -+ * -+ * @return if this pathfinder allows passing through closed doors -+ */ -+ boolean canOpenDoors(); -+ -+ /** -+ * Allows this pathfinder to pass through closed doors, or not -+ * -+ * @param canOpenDoors if the mob can pass through closed doors, or not -+ */ -+ void setCanOpenDoors(boolean canOpenDoors); -+ -+ /** -+ * Checks if this pathfinder allows passing through open doors. -+ * -+ * @return if this pathfinder allows passing through open doors -+ */ -+ boolean canPassDoors(); -+ -+ /** -+ * Allows this pathfinder to pass through open doors, or not -+ * -+ * @param canPassDoors if the mob can pass through open doors, or not -+ */ -+ void setCanPassDoors(boolean canPassDoors); -+ -+ /** -+ * Checks if this pathfinder assumes that the mob can float -+ * -+ * @return if this pathfinder assumes that the mob can float -+ */ -+ boolean canFloat(); -+ -+ /** -+ * Makes this pathfinder assume that the mob can float, or not -+ * -+ * @param canFloat if the mob can float, or not -+ */ -+ void setCanFloat(boolean canFloat); -+ -+ /** -+ * Represents the result of a pathfinding calculation -+ */ -+ interface PathResult { -+ -+ /** -+ * All currently calculated points to follow along the path to reach the destination location -+ * -+ * Will return points the entity has already moved past, see {@link #getNextPointIndex()} -+ * @return List of points -+ */ -+ @NotNull -+ List getPoints(); -+ -+ /** -+ * @return Returns the index of the current point along the points returned in {@link #getPoints()} the entity -+ * is trying to reach, or null if we are done with this pathfinding. -+ */ -+ int getNextPointIndex(); -+ -+ /** -+ * @return The next location in the path points the entity is trying to reach, or null if there is no next point -+ */ -+ @Nullable Location getNextPoint(); -+ -+ /** -+ * @return The closest point the path can get to the target location -+ */ -+ @Nullable Location getFinalPoint(); -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java -index be9334a8b5fba9181ad63c211697e798be63da25..b132287817d35579ca5128a1ed5c242bf229771a 100644 ---- a/src/main/java/org/bukkit/entity/Mob.java -+++ b/src/main/java/org/bukkit/entity/Mob.java -@@ -1,6 +1,7 @@ - package org.bukkit.entity; - - import org.bukkit.loot.Lootable; -+import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - - /** -@@ -8,6 +9,15 @@ import org.jetbrains.annotations.Nullable; - */ - public interface Mob extends LivingEntity, Lootable { - -+ // Paper start -+ /** -+ * Enables access to control the pathing of an Entity -+ * @return Pathfinding Manager for this entity -+ */ -+ @NotNull -+ com.destroystokyo.paper.entity.Pathfinder getPathfinder(); -+ // Paper end -+ - /** - * Instructs this Mob to set the specified LivingEntity as its target. - *

    diff --git a/Unmapped-Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch b/Unmapped-Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch deleted file mode 100644 index e67693668d..0000000000 --- a/Unmapped-Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 4 Sep 2018 15:01:54 -0500 -Subject: [PATCH] Expose attack cooldown methods for Player - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 257bf4a75393d1e25839bcae0ca5551ee832c627..ec87c78d0f9379511467b6d13b9cdfa4c19d15ca 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1889,6 +1889,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param profile The new profile to use - */ - void setPlayerProfile(@NotNull PlayerProfile profile); -+ -+ /** -+ * Returns the amount of ticks the current cooldown lasts -+ * -+ * @return Amount of ticks cooldown will last -+ */ -+ float getCooldownPeriod(); -+ -+ /** -+ * Returns the percentage of attack power available based on the cooldown (zero to one). -+ * -+ * @param adjustTicks Amount of ticks to add to cooldown counter for this calculation -+ * @return Percentage of attack power available -+ */ -+ float getCooledAttackStrength(float adjustTicks); -+ -+ /** -+ * Reset the cooldown counter to 0, effectively starting the cooldown period. -+ */ -+ void resetCooldown(); - // Paper end - - // Spigot start diff --git a/Unmapped-Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/Unmapped-Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch deleted file mode 100644 index c5b4ce2e41..0000000000 --- a/Unmapped-Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch +++ /dev/null @@ -1,319 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Wed, 12 Sep 2018 18:53:35 +0300 -Subject: [PATCH] Add an API for CanPlaceOn and CanDestroy NBT values - - -diff --git a/src/main/java/com/destroystokyo/paper/Namespaced.java b/src/main/java/com/destroystokyo/paper/Namespaced.java -new file mode 100644 -index 0000000000000000000000000000000000000000..cd1a34b82870684e09e18c47169bd472ecbbb91f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/Namespaced.java -@@ -0,0 +1,40 @@ -+package com.destroystokyo.paper; -+ -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents a namespaced resource, see {@link org.bukkit.NamespacedKey} for single elements -+ * or {@link com.destroystokyo.paper.NamespacedTag} for a collection of elements -+ * -+ * Namespaces may only contain lowercase alphanumeric characters, periods, -+ * underscores, and hyphens. -+ *

    -+ * Keys may only contain lowercase alphanumeric characters, periods, -+ * underscores, hyphens, and forward slashes. -+ *

    -+ * You should not be implementing this interface yourself, use {@link org.bukkit.NamespacedKey} -+ * or {@link com.destroystokyo.paper.NamespacedTag} as needed instead. -+ */ -+public interface Namespaced { -+ /** -+ * Gets the namespace this resource is a part of -+ *

    -+ * This is contractually obligated to only contain lowercase alphanumeric characters, -+ * periods, underscores, and hyphens. -+ * -+ * @return resource namespace -+ */ -+ @NotNull -+ String getNamespace(); -+ -+ /** -+ * Gets the key corresponding to this resource -+ *

    -+ * This is contractually obligated to only contain lowercase alphanumeric characters, -+ * periods, underscores, hyphens, and forward slashes. -+ * -+ * @return resource key -+ */ -+ @NotNull -+ String getKey(); -+} -diff --git a/src/main/java/com/destroystokyo/paper/NamespacedTag.java b/src/main/java/com/destroystokyo/paper/NamespacedTag.java -new file mode 100644 -index 0000000000000000000000000000000000000000..28f3fda950999a9c964a3608042ca60567ae1d6a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/NamespacedTag.java -@@ -0,0 +1,142 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Preconditions; -+import java.util.Locale; -+import java.util.UUID; -+import java.util.regex.Pattern; -+import org.bukkit.plugin.Plugin; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents a String based key pertaining to a tagged entry. Consists of two components - a namespace -+ * and a key. -+ *

    -+ * Namespaces may only contain lowercase alphanumeric characters, periods, -+ * underscores, and hyphens. -+ *

    -+ * Keys may only contain lowercase alphanumeric characters, periods, -+ * underscores, hyphens, and forward slashes. -+ * -+ */ -+// Paper - entire class, based on org.bukkit.NamespacedKey -+public final class NamespacedTag implements com.destroystokyo.paper.Namespaced { -+ -+ /** -+ * The namespace representing all inbuilt keys. -+ */ -+ public static final String MINECRAFT = "minecraft"; -+ /** -+ * The namespace representing all keys generated by Bukkit for backwards -+ * compatibility measures. -+ */ -+ public static final String BUKKIT = "bukkit"; -+ // -+ private static final Pattern VALID_NAMESPACE = Pattern.compile("[a-z0-9._-]+"); -+ private static final Pattern VALID_KEY = Pattern.compile("[a-z0-9/._-]+"); -+ // -+ private final String namespace; -+ private final String key; -+ -+ /** -+ * Create a key in a specific namespace. -+ * -+ * @param namespace String representing a grouping of keys -+ * @param key Name for this specific key -+ * @deprecated should never be used by plugins, for internal use only!! -+ */ -+ @Deprecated -+ public NamespacedTag(@NotNull String namespace, @NotNull String key) { -+ Preconditions.checkArgument(namespace != null && VALID_NAMESPACE.matcher(namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", namespace); -+ Preconditions.checkArgument(key != null && VALID_KEY.matcher(key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", key); -+ -+ this.namespace = namespace; -+ this.key = key; -+ -+ String string = toString(); -+ Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters", string); -+ } -+ -+ /** -+ * Create a key in the plugin's namespace. -+ *

    -+ * Namespaces may only contain lowercase alphanumeric characters, periods, -+ * underscores, and hyphens. -+ *

    -+ * Keys may only contain lowercase alphanumeric characters, periods, -+ * underscores, hyphens, and forward slashes. -+ * -+ * @param plugin the plugin to use for the namespace -+ * @param key the key to create -+ */ -+ public NamespacedTag(@NotNull Plugin plugin, @NotNull String key) { -+ Preconditions.checkArgument(plugin != null, "Plugin cannot be null"); -+ Preconditions.checkArgument(key != null, "Key cannot be null"); -+ -+ this.namespace = plugin.getName().toLowerCase(Locale.ROOT); -+ this.key = key.toLowerCase().toLowerCase(Locale.ROOT); -+ -+ // Check validity after normalization -+ Preconditions.checkArgument(VALID_NAMESPACE.matcher(this.namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", this.namespace); -+ Preconditions.checkArgument(VALID_KEY.matcher(this.key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", this.key); -+ -+ String string = toString(); -+ Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters (%s)", string); -+ } -+ -+ @NotNull -+ public String getNamespace() { -+ return namespace; -+ } -+ -+ @NotNull -+ public String getKey() { -+ return key; -+ } -+ -+ @Override -+ public int hashCode() { -+ int hash = 7; -+ hash = 47 * hash + this.namespace.hashCode(); -+ hash = 47 * hash + this.key.hashCode(); -+ return hash; -+ } -+ -+ @Override -+ public boolean equals(Object obj) { -+ if (obj == null) { -+ return false; -+ } -+ if (getClass() != obj.getClass()) { -+ return false; -+ } -+ final NamespacedTag other = (NamespacedTag) obj; -+ return this.namespace.equals(other.namespace) && this.key.equals(other.key); -+ } -+ -+ @Override -+ public String toString() { -+ return "#" + this.namespace + ":" + this.key; -+ } -+ -+ /** -+ * Return a new random key in the {@link #BUKKIT} namespace. -+ * -+ * @return new key -+ * @deprecated should never be used by plugins, for internal use only!! -+ */ -+ @Deprecated -+ public static NamespacedTag randomKey() { -+ return new NamespacedTag(BUKKIT, UUID.randomUUID().toString()); -+ } -+ -+ /** -+ * Get a key in the Minecraft namespace. -+ * -+ * @param key the key to use -+ * @return new key in the Minecraft namespace -+ */ -+ @NotNull -+ public static NamespacedTag minecraft(@NotNull String key) { -+ return new NamespacedTag(MINECRAFT, key); -+ } -+} -diff --git a/src/main/java/org/bukkit/NamespacedKey.java b/src/main/java/org/bukkit/NamespacedKey.java -index c65f0d6569c130b4920a9e71ad24af6427f1f030..01bcb3a1bdb5accdf844d0178cec3d25746b3eaa 100644 ---- a/src/main/java/org/bukkit/NamespacedKey.java -+++ b/src/main/java/org/bukkit/NamespacedKey.java -@@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable; - * underscores, hyphens, and forward slashes. - * - */ --public final class NamespacedKey implements net.kyori.adventure.key.Key { // Paper - implement Key -+public final class NamespacedKey implements net.kyori.adventure.key.Key, com.destroystokyo.paper.Namespaced { // Paper - implement Key and Namespaced - - /** - * The namespace representing all inbuilt keys. -@@ -84,11 +84,13 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key { // Pap - } - - @NotNull -+ @Override // Paper - public String getNamespace() { - return namespace; - } - - @NotNull -+ @Override // Paper - public String getKey() { - return key; - } -diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -index 1c362636c56db0e6c118171ba367c43c4f7cff33..01b462fccce71cef3398dd43944046f322b8e57e 100644 ---- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -+++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -@@ -432,4 +432,87 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - @SuppressWarnings("javadoc") - @NotNull - ItemMeta clone(); -+ -+ // Paper start - Add an API for CanPlaceOn and CanDestroy NBT values -+ /** -+ * Gets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @return Set of materials -+ * @deprecated Minecraft does not limit this to the material enum, Use {@link #getDestroyableKeys()} as a replacement -+ */ -+ @Deprecated -+ Set getCanDestroy(); -+ -+ /** -+ * Sets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @param canDestroy Set of materials -+ * @deprecated Minecraft does not limit this to the material enum, Use {@link #setDestroyableKeys(Collection)} as a replacement -+ */ -+ @Deprecated -+ void setCanDestroy(Set canDestroy); -+ -+ /** -+ * Gets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @return Set of materials -+ * @deprecated Minecraft does not limit this to the material enum, Use {@link #getPlaceableKeys()} as a replacement -+ */ -+ @Deprecated -+ Set getCanPlaceOn(); -+ -+ /** -+ * Sets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @param canPlaceOn Set of materials -+ * @deprecated Minecraft does not limit this to the material enum, Use {@link #setPlaceableKeys(Collection)} as a replacement -+ */ -+ @Deprecated -+ void setCanPlaceOn(Set canPlaceOn); -+ -+ /** -+ * Gets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @return Set of {@link com.destroystokyo.paper.Namespaced} -+ */ -+ @NotNull -+ Set getDestroyableKeys(); -+ -+ /** -+ * Sets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @param canDestroy Collection of {@link com.destroystokyo.paper.Namespaced} -+ */ -+ void setDestroyableKeys(@NotNull Collection canDestroy); -+ -+ /** -+ * Gets the collection of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @return Set of {@link com.destroystokyo.paper.Namespaced} -+ */ -+ @NotNull -+ Set getPlaceableKeys(); -+ -+ /** -+ * Sets the set of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @param canPlaceOn Collection of {@link com.destroystokyo.paper.Namespaced} -+ */ -+ @NotNull -+ void setPlaceableKeys(@NotNull Collection canPlaceOn); -+ -+ /** -+ * Checks for the existence of any keys that the item can be placed on -+ * -+ * @return true if this item has placeable keys -+ */ -+ boolean hasPlaceableKeys(); -+ -+ /** -+ * Checks for the existence of any keys that the item can destroy -+ * -+ * @return true if this item has destroyable keys -+ */ -+ boolean hasDestroyableKeys(); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch b/Unmapped-Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch deleted file mode 100644 index 4d64579e4a..0000000000 --- a/Unmapped-Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 13 Sep 2018 20:51:50 -0400 -Subject: [PATCH] Performance & Concurrency Improvements to Permissions - -Modifying of permissions was only half protected, enabling concurrency -issues to occur if permissions were modified async. - -While no plugin really should be doing that, modifying operations -are not heavily called, so they are safe to add synchronization to. - -Now, all modification API's will be synchronized ensuring safety. - -Additionally, hasPermission was victim to a common java newbie mistake -of calling if (containsKey(k)) return get(k), resulting in 2 map lookups. - -Optimized it to simply be a single get call cutting permission map -lookups in half. - -diff --git a/src/main/java/org/bukkit/permissions/PermissibleBase.java b/src/main/java/org/bukkit/permissions/PermissibleBase.java -index 497775f7f8fa2eae34555ca0f0c6ba72d6cfab3f..c94e4cdb5785d5dfcb704c4adabda0b19a20ec7d 100644 ---- a/src/main/java/org/bukkit/permissions/PermissibleBase.java -+++ b/src/main/java/org/bukkit/permissions/PermissibleBase.java -@@ -75,8 +75,11 @@ public class PermissibleBase implements Permissible { - - String name = inName.toLowerCase(java.util.Locale.ENGLISH); - -- if (isPermissionSet(name)) { -- return permissions.get(name).getValue(); -+ // Paper start -+ PermissionAttachmentInfo info = permissions.get(name); -+ if (info != null) { -+ return info.getValue(); -+ // Paper end - } else { - Permission perm = Bukkit.getServer().getPluginManager().getPermission(name); - -@@ -96,15 +99,18 @@ public class PermissibleBase implements Permissible { - - String name = perm.getName().toLowerCase(java.util.Locale.ENGLISH); - -- if (isPermissionSet(name)) { -- return permissions.get(name).getValue(); -+ // Paper start -+ PermissionAttachmentInfo info = permissions.get(name); -+ if (info != null) { -+ return info.getValue(); - } -+ // Paper end - return perm.getDefault().getValue(isOp()); - } - - @Override - @NotNull -- public PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value) { -+ public synchronized PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value) { // Paper - synchronized - if (name == null) { - throw new IllegalArgumentException("Permission name cannot be null"); - } else if (plugin == null) { -@@ -123,7 +129,7 @@ public class PermissibleBase implements Permissible { - - @Override - @NotNull -- public PermissionAttachment addAttachment(@NotNull Plugin plugin) { -+ public synchronized PermissionAttachment addAttachment(@NotNull Plugin plugin) { // Paper - synchronized - if (plugin == null) { - throw new IllegalArgumentException("Plugin cannot be null"); - } else if (!plugin.isEnabled()) { -@@ -139,7 +145,7 @@ public class PermissibleBase implements Permissible { - } - - @Override -- public void removeAttachment(@NotNull PermissionAttachment attachment) { -+ public synchronized void removeAttachment(@NotNull PermissionAttachment attachment) { // Paper - synchronized - if (attachment == null) { - throw new IllegalArgumentException("Attachment cannot be null"); - } -@@ -159,7 +165,7 @@ public class PermissibleBase implements Permissible { - } - - @Override -- public void recalculatePermissions() { -+ public synchronized void recalculatePermissions() { // Paper - synchronized - clearPermissions(); - Set defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(isOp()); - Bukkit.getServer().getPluginManager().subscribeToDefaultPerms(isOp(), parent); -@@ -208,7 +214,7 @@ public class PermissibleBase implements Permissible { - - @Override - @Nullable -- public PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks) { -+ public synchronized PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks) { // Paper - if (name == null) { - throw new IllegalArgumentException("Permission name cannot be null"); - } else if (plugin == null) { -@@ -228,7 +234,7 @@ public class PermissibleBase implements Permissible { - - @Override - @Nullable -- public PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks) { -+ public synchronized PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks) { // Paper - synchronized - if (plugin == null) { - throw new IllegalArgumentException("Plugin cannot be null"); - } else if (!plugin.isEnabled()) { -@@ -248,7 +254,7 @@ public class PermissibleBase implements Permissible { - - @Override - @NotNull -- public Set getEffectivePermissions() { -+ public synchronized Set getEffectivePermissions() { // Paper - synchronized - return new HashSet(permissions.values()); - } - diff --git a/Unmapped-Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch b/Unmapped-Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch deleted file mode 100644 index 1a4eca8cc0..0000000000 --- a/Unmapped-Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 13 Sep 2018 21:39:26 -0400 -Subject: [PATCH] Add ItemStackRecipeChoice Draft API - -This is based on Spigots Draft API. This is subject to change - -Allows creating recipes that must match isSimilar to full item stack. - -diff --git a/src/main/java/com/destroystokyo/paper/inventory/ItemStackRecipeChoice.java b/src/main/java/com/destroystokyo/paper/inventory/ItemStackRecipeChoice.java -new file mode 100644 -index 0000000000000000000000000000000000000000..43e6576b1d1bb811f9feb22de0024d9c823cb21a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/inventory/ItemStackRecipeChoice.java -@@ -0,0 +1,51 @@ -+package com.destroystokyo.paper.inventory; -+ -+import org.bukkit.inventory.ItemStack; -+import org.bukkit.inventory.RecipeChoice; -+ -+import java.util.ArrayList; -+import java.util.List; -+ -+/** -+ * Allows crafting Items that require full matching itemstacks to complete the recipe for custom items -+ * @deprecated Draft API -+ */ -+@Deprecated -+public class ItemStackRecipeChoice implements RecipeChoice { -+ -+ protected final List choices = new ArrayList<>(); -+ -+ public ItemStackRecipeChoice(ItemStack choices) { -+ this.choices.add(choices); -+ } -+ -+ public ItemStackRecipeChoice(List choices) { -+ this.choices.addAll(choices); -+ } -+ -+ @Override -+ public ItemStack getItemStack() { -+ return choices.isEmpty() ? null : choices.get(0); -+ } -+ -+ @Override -+ public RecipeChoice clone() { -+ try { -+ ItemStackRecipeChoice clone = (ItemStackRecipeChoice) super.clone(); -+ clone.choices.addAll(this.choices); -+ return clone; -+ } catch (CloneNotSupportedException ex) { -+ throw new AssertionError(ex); -+ } -+ } -+ -+ @Override -+ public boolean test(ItemStack itemStack) { -+ for (ItemStack stack : choices) { -+ if (stack.isSimilar(itemStack)) { -+ return true; -+ } -+ } -+ return false; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch b/Unmapped-Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch deleted file mode 100644 index cb4250b87c..0000000000 --- a/Unmapped-Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tassu -Date: Thu, 13 Sep 2018 08:45:01 +0300 -Subject: [PATCH] Implement furnace cook speed multiplier API - -Signed-off-by: Tassu - -diff --git a/src/main/java/org/bukkit/block/Furnace.java b/src/main/java/org/bukkit/block/Furnace.java -index c5a8c96fa2204d6b4d2409b1bfc97697d39d964e..9063cf370a0fe66c2a27086e125f9111b77366ae 100644 ---- a/src/main/java/org/bukkit/block/Furnace.java -+++ b/src/main/java/org/bukkit/block/Furnace.java -@@ -61,6 +61,26 @@ public interface Furnace extends Container { - */ - public void setCookTimeTotal(int cookTimeTotal); - -+ // Paper start -+ /** -+ * Gets the cook speed multiplier that this {@link Furnace} will cook -+ * compared to vanilla. -+ * -+ * @return the multiplier, a value between 0 and 200 -+ */ -+ public double getCookSpeedMultiplier(); -+ -+ /** -+ * Sets the speed multiplier that this {@link Furnace} will cook -+ * compared to vanilla. -+ * -+ * @param multiplier the multiplier to set, a value between 0 and 200 -+ * @throws IllegalArgumentException if value is less than 0 -+ * @throws IllegalArgumentException if value is more than 200 -+ */ -+ public void setCookSpeedMultiplier(double multiplier); -+ // Paper end -+ - @NotNull - @Override - public FurnaceInventory getInventory(); diff --git a/Unmapped-Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch b/Unmapped-Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch deleted file mode 100644 index 70ec0d47bd..0000000000 --- a/Unmapped-Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 18 Sep 2018 23:50:10 +0100 -Subject: [PATCH] PreSpawnerSpawnEvent - -This adds a separate event before an entity is spawned by a spawner -which contains the location of the spawner too similarly to how the -SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for -spawners. - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..48cff063594840a07aeaf35513780e28ea019a76 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java -@@ -0,0 +1,29 @@ -+package com.destroystokyo.paper.event.entity; -+ -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.Location; -+import org.bukkit.entity.EntityType; -+import org.bukkit.event.entity.CreatureSpawnEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called before an entity is spawned into a world by a spawner. -+ * -+ * This only includes the spawner's location and not the full BlockState snapshot for performance reasons. -+ * If you really need it you have to get the spawner yourself. -+ */ -+ -+public class PreSpawnerSpawnEvent extends PreCreatureSpawnEvent { -+ @NotNull private final Location spawnerLocation; -+ -+ public PreSpawnerSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull Location spawnerLocation) { -+ super(location, type, CreatureSpawnEvent.SpawnReason.SPAWNER); -+ this.spawnerLocation = Preconditions.checkNotNull(spawnerLocation, "Spawner location may not be null"); -+ } -+ -+ @NotNull -+ public Location getSpawnerLocation() { -+ return spawnerLocation; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0153-Material-API-additions.patch b/Unmapped-Spigot-API-Patches/0153-Material-API-additions.patch deleted file mode 100644 index 629bed4425..0000000000 --- a/Unmapped-Spigot-API-Patches/0153-Material-API-additions.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 6 Oct 2018 21:14:29 -0400 -Subject: [PATCH] Material API additions - - -diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index a9769ae0bad61d200c70331eba0b655da4ba03b2..9c28351c7c3f60c6a3b4020329344f91efeedae1 100644 ---- a/src/main/java/org/bukkit/Material.java -+++ b/src/main/java/org/bukkit/Material.java -@@ -98,6 +98,7 @@ import org.jetbrains.annotations.Nullable; - /** - * An enum of all material IDs accepted by the official server and client - */ -+@SuppressWarnings({"DeprecatedIsStillUsed", "deprecation"}) // Paper - public enum Material implements Keyed { - // - AIR(9648, 0), -@@ -3976,6 +3977,22 @@ public enum Material implements Keyed { - } - } - -+ // Paper start -+ -+ /** -+ * @return If the type is either AIR, CAVE_AIR or VOID_AIR -+ */ -+ public boolean isEmpty() { -+ switch (this) { -+ case AIR: -+ case CAVE_AIR: -+ case VOID_AIR: -+ return true; -+ } -+ return false; -+ } -+ // Paper end -+ - /** - * Do not use for any reason. - * diff --git a/Unmapped-Spigot-API-Patches/0154-Add-Material-Tags.patch b/Unmapped-Spigot-API-Patches/0154-Add-Material-Tags.patch deleted file mode 100644 index 7fa999bf70..0000000000 --- a/Unmapped-Spigot-API-Patches/0154-Add-Material-Tags.patch +++ /dev/null @@ -1,1044 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 17 Jul 2018 01:27:15 -0400 -Subject: [PATCH] Add Material Tags - -This adds a bunch of useful and missing Tags to be able to identify items that -are related to each other by a trait. - -Co-authored-by: Jake Potrebic - -diff --git a/src/main/java/com/destroystokyo/paper/MaterialSetTag.java b/src/main/java/com/destroystokyo/paper/MaterialSetTag.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a02a02aa0c87e0f0ed9e509e4dcab01565b3d92a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/MaterialSetTag.java -@@ -0,0 +1,97 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ */ -+ -+package com.destroystokyo.paper; -+ -+import com.google.common.collect.Lists; -+import io.papermc.paper.tag.BaseTag; -+import org.bukkit.Material; -+import org.bukkit.NamespacedKey; -+import org.bukkit.block.Block; -+import org.bukkit.block.BlockState; -+import org.bukkit.block.data.BlockData; -+import org.bukkit.inventory.ItemStack; -+ -+import java.util.Collection; -+import java.util.Set; -+import java.util.function.Predicate; -+import java.util.stream.Collectors; -+import java.util.stream.Stream; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class MaterialSetTag extends BaseTag { -+ -+ /** -+ * @deprecated Use NamespacedKey version of constructor -+ */ -+ @Deprecated -+ public MaterialSetTag(@NotNull Predicate filter) { -+ this(null, Stream.of(Material.values()).filter(filter).collect(Collectors.toList())); -+ } -+ -+ /** -+ * @deprecated Use NamespacedKey version of constructor -+ */ -+ @Deprecated -+ public MaterialSetTag(@NotNull Collection materials) { -+ this(null, materials); -+ } -+ -+ /** -+ * @deprecated Use NamespacedKey version of constructor -+ */ -+ @Deprecated -+ public MaterialSetTag(@NotNull Material... materials) { -+ this(null, materials); -+ } -+ -+ public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Predicate filter) { -+ this(key, Stream.of(Material.values()).filter(filter).collect(Collectors.toList())); -+ } -+ -+ public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Material... materials) { -+ this(key, Lists.newArrayList(materials)); -+ } -+ -+ public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Collection materials) { -+ this(key != null ? key : NamespacedKey.randomKey(), materials, ((Predicate) Material::isLegacy).negate()); -+ } -+ -+ public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Collection materials, @NotNull Predicate...globalPredicates) { -+ super(Material.class, key != null ? key : NamespacedKey.randomKey(), materials, globalPredicates); -+ } -+ -+ @NotNull -+ @Override -+ protected Set getAllPossibleValues() { -+ return Stream.of(Material.values()).collect(Collectors.toSet()); -+ } -+ -+ @Override -+ @NotNull -+ protected String getName(@NotNull Material value) { -+ return value.name(); -+ } -+ -+ public boolean isTagged(@NotNull BlockData block) { -+ return isTagged(block.getMaterial()); -+ } -+ -+ public boolean isTagged(@NotNull BlockState block) { -+ return isTagged(block.getType()); -+ } -+ -+ public boolean isTagged(@NotNull Block block) { -+ return isTagged(block.getType()); -+ } -+ -+ public boolean isTagged(@NotNull ItemStack item) { -+ return isTagged(item.getType()); -+ } -+ -+ public boolean isTagged(@NotNull Material material) { -+ return this.tagged.contains(material); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/MaterialTags.java b/src/main/java/com/destroystokyo/paper/MaterialTags.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2b5a61a8afa8f73006676cdcb8a34640b43de1c3 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/MaterialTags.java -@@ -0,0 +1,558 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+package com.destroystokyo.paper; -+ -+import org.bukkit.Material; -+import org.bukkit.NamespacedKey; -+import org.bukkit.Tag; -+ -+/** -+ * Represents a collection tags to identify materials that share common properties. -+ * Will map to minecraft for missing tags, as well as custom ones that may be useful. -+ */ -+@SuppressWarnings({"NonFinalUtilityClass", "unused", "WeakerAccess"}) -+public class MaterialTags { -+ -+ private static NamespacedKey keyFor(String key) { -+ //noinspection deprecation -+ return new NamespacedKey("paper", key + "_settag"); -+ } -+ public static final MaterialSetTag ARROWS = new MaterialSetTag(keyFor("arrows")) -+ .endsWith("ARROW") -+ .ensureSize("ARROWS", 3); -+ -+ /** -+ * Covers all colors of beds. -+ */ -+ public static final MaterialSetTag BEDS = new MaterialSetTag(keyFor("beds")) -+ .endsWith("_BED") -+ .ensureSize("BEDS", 16); -+ -+ /** -+ * Covers all bucket items. -+ */ -+ public static final MaterialSetTag BUCKETS = new MaterialSetTag(keyFor("buckets")) -+ .endsWith("BUCKET") -+ .ensureSize("BUCKETS", 8); -+ -+ /** -+ * Covers coal and charcoal. -+ */ -+ public static final MaterialSetTag COALS = new MaterialSetTag(keyFor("coals")) -+ .add(Material.COAL, Material.CHARCOAL); -+ -+ /** -+ * Covers both cobblestone wall variants. -+ */ -+ public static final MaterialSetTag COBBLESTONE_WALLS = new MaterialSetTag(keyFor("cobblestone_walls")) -+ .endsWith("COBBLESTONE_WALL") -+ .ensureSize("COBBLESTONE_WALLS", 2); -+ -+ /** -+ * Covers both cobblestone and mossy Cobblestone. -+ */ -+ public static final MaterialSetTag COBBLESTONES = new MaterialSetTag(keyFor("cobblestones")) -+ .add(Material.COBBLESTONE, Material.MOSSY_COBBLESTONE); -+ -+ /** -+ * Covers all colors of concrete. -+ */ -+ public static final MaterialSetTag CONCRETES = new MaterialSetTag(keyFor("concretes")) -+ .endsWith("_CONCRETE") -+ .ensureSize("CONCRETES", 16); -+ -+ /** -+ * Covers all colors of concrete powder. -+ */ -+ public static final MaterialSetTag CONCRETE_POWDER = new MaterialSetTag(keyFor("concrete_powder")) -+ .endsWith("_CONCRETE_POWDER") -+ .ensureSize("CONCRETE_POWDER", 16); -+ -+ /** -+ * Covers the two types of cooked fish. -+ */ -+ public static final MaterialSetTag COOKED_FISH = new MaterialSetTag(keyFor("cooked_fish")) -+ .add(Material.COOKED_COD, Material.COOKED_SALMON); -+ -+ /** -+ * Covers all variants of doors. -+ */ -+ public static final MaterialSetTag DOORS = new MaterialSetTag(keyFor("doors")) -+ .endsWith("_DOOR") -+ .ensureSize("DOORS", 9); -+ -+ /** -+ * Covers all dyes. -+ */ -+ public static final MaterialSetTag DYES = new MaterialSetTag(keyFor("dyes")) -+ .endsWith("_DYE") -+ .ensureSize("DYES", 16); -+ -+ /** -+ * Covers all variants of gates. -+ */ -+ public static final MaterialSetTag FENCE_GATES = new MaterialSetTag(keyFor("fence_gates")) -+ .endsWith("_GATE") -+ .ensureSize("FENCE_GATES", 8); -+ -+ /** -+ * Covers all variants of fences. -+ */ -+ public static final MaterialSetTag FENCES = new MaterialSetTag(keyFor("fences")) -+ .endsWith("_FENCE") -+ .ensureSize("FENCES", 9); -+ -+ /** -+ * Covers all variants of fish buckets. -+ */ -+ public static final MaterialSetTag FISH_BUCKETS = new MaterialSetTag(keyFor("fish_buckets")) -+ .add(Material.COD_BUCKET, Material.PUFFERFISH_BUCKET, Material.SALMON_BUCKET, Material.TROPICAL_FISH_BUCKET); -+ -+ /** -+ * Covers the non-colored glass and 16 stained glass (not panes). -+ */ -+ public static final MaterialSetTag GLASS = new MaterialSetTag(keyFor("glass")) -+ .endsWith("_GLASS") -+ .add(Material.GLASS) -+ .ensureSize("GLASS", 17); -+ -+ /** -+ * Covers the non-colored glass panes and stained glass panes (panes only). -+ */ -+ public static final MaterialSetTag GLASS_PANES = new MaterialSetTag(keyFor("glass_panes")) -+ .endsWith("GLASS_PANE") -+ .ensureSize("GLASS_PANES", 17); -+ -+ /** -+ * Covers all glazed terracotta blocks. -+ */ -+ public static final MaterialSetTag GLAZED_TERRACOTTA = new MaterialSetTag(keyFor("glazed_terracotta")) -+ .endsWith("GLAZED_TERRACOTTA") -+ .ensureSize("GLAZED_TERRACOTTA", 16); -+ -+ /** -+ * Covers the colors of stained terracotta. -+ */ -+ public static final MaterialSetTag STAINED_TERRACOTTA = new MaterialSetTag(keyFor("stained_terracotta")) -+ .endsWith("TERRACOTTA") -+ .not(Material.TERRACOTTA) -+ .notEndsWith("GLAZED_TERRACOTTA") -+ .ensureSize("STAINED_TERRACOTTA", 16); -+ -+ /** -+ * Covers terracotta along with the stained variants. -+ */ -+ public static final MaterialSetTag TERRACOTTA = new MaterialSetTag(keyFor("terracotta")) -+ .endsWith("TERRACOTTA") -+ .ensureSize("TERRACOTTA", 33); -+ -+ /** -+ * Covers both golden apples. -+ */ -+ public static final MaterialSetTag GOLDEN_APPLES = new MaterialSetTag(keyFor("golden_apples")) -+ .endsWith("GOLDEN_APPLE") -+ .ensureSize("GOLDEN_APPLES", 2); -+ -+ /** -+ * Covers the variants of horse armor. -+ */ -+ public static final MaterialSetTag HORSE_ARMORS = new MaterialSetTag(keyFor("horse_armors")) -+ .endsWith("_HORSE_ARMOR") -+ .ensureSize("HORSE_ARMORS", 4); -+ -+ /** -+ * Covers the variants of infested blocks. -+ */ -+ public static final MaterialSetTag INFESTED_BLOCKS = new MaterialSetTag(keyFor("infested_blocks")) -+ .startsWith("INFESTED_") -+ .ensureSize("INFESTED_BLOCKS", 6); -+ -+ /** -+ * Covers the variants of mushroom blocks. -+ */ -+ public static final MaterialSetTag MUSHROOM_BLOCKS = new MaterialSetTag(keyFor("mushroom_blocks")) -+ .endsWith("MUSHROOM_BLOCK") -+ .add(Material.MUSHROOM_STEM) -+ .ensureSize("MUSHROOM_BLOCKS", 3); -+ -+ /** -+ * Covers all mushrooms. -+ */ -+ public static final MaterialSetTag MUSHROOMS = new MaterialSetTag(keyFor("mushrooms")) -+ .add(Material.BROWN_MUSHROOM, Material.RED_MUSHROOM); -+ -+ /** -+ * Covers all music disc items. -+ */ -+ public static final MaterialSetTag MUSIC_DISCS = new MaterialSetTag(keyFor("music_discs")) -+ .startsWith("MUSIC_DISC_"); -+ -+ /** -+ * Covers all ores. -+ */ -+ public static final MaterialSetTag ORES = new MaterialSetTag(keyFor("ores")) -+ .add(Material.ANCIENT_DEBRIS) -+ .endsWith("_ORE") -+ .ensureSize("ORES", 10); -+ -+ /** -+ * Covers all piston typed items and blocks including the piston head and moving piston. -+ */ -+ public static final MaterialSetTag PISTONS = new MaterialSetTag(keyFor("pistons")) -+ .contains("PISTON") -+ .ensureSize("PISTONS", 4); -+ -+ /** -+ * Covers all potato items. -+ */ -+ public static final MaterialSetTag POTATOES = new MaterialSetTag(keyFor("potatoes")) -+ .endsWith("POTATO") -+ .ensureSize("POTATOES", 3); -+ -+ /** -+ * Covers all wooden pressure plates and the weighted pressure plates and the stone pressure plate. -+ */ -+ public static final MaterialSetTag PRESSURE_PLATES = new MaterialSetTag(keyFor("pressure_plates")) -+ .endsWith("_PRESSURE_PLATE") -+ .ensureSize("PRESSURE_PLATES", 12); -+ -+ /** -+ * Covers the variants of prismarine blocks. -+ */ -+ public static final MaterialSetTag PRISMARINE = new MaterialSetTag(keyFor("prismarine")) -+ .add(Material.PRISMARINE, Material.PRISMARINE_BRICKS, Material.DARK_PRISMARINE); -+ -+ /** -+ * Covers the variants of prismarine slabs. -+ */ -+ public static final MaterialSetTag PRISMARINE_SLABS = new MaterialSetTag(keyFor("prismarine_slabs")) -+ .add(Material.PRISMARINE_SLAB, Material.PRISMARINE_BRICK_SLAB, Material.DARK_PRISMARINE_SLAB); -+ -+ /** -+ * Covers the variants of prismarine stairs. -+ */ -+ public static final MaterialSetTag PRISMARINE_STAIRS = new MaterialSetTag(keyFor("prismarine_stairs")) -+ .add(Material.PRISMARINE_STAIRS, Material.PRISMARINE_BRICK_STAIRS, Material.DARK_PRISMARINE_STAIRS); -+ -+ /** -+ * Covers the variants of pumpkins. -+ */ -+ public static final MaterialSetTag PUMPKINS = new MaterialSetTag(keyFor("pumpkins")) -+ .add(Material.CARVED_PUMPKIN, Material.JACK_O_LANTERN, Material.PUMPKIN); -+ -+ /** -+ * Covers the variants of quartz blocks. -+ */ -+ public static final MaterialSetTag QUARTZ_BLOCKS = new MaterialSetTag(keyFor("quartz_blocks")) -+ .add(Material.QUARTZ_BLOCK, Material.QUARTZ_PILLAR, Material.CHISELED_QUARTZ_BLOCK, Material.SMOOTH_QUARTZ); -+ -+ /** -+ * Covers all uncooked fish items. -+ */ -+ public static final MaterialSetTag RAW_FISH = new MaterialSetTag(keyFor("raw_fish")) -+ .add(Material.COD, Material.PUFFERFISH, Material.SALMON, Material.TROPICAL_FISH); -+ -+ /** -+ * Covers the variants of red sandstone blocks. -+ */ -+ public static final MaterialSetTag RED_SANDSTONES = new MaterialSetTag(keyFor("red_sandstones")) -+ .endsWith("RED_SANDSTONE") -+ .ensureSize("RED_SANDSTONES", 4); -+ -+ /** -+ * Covers the variants of sandstone blocks. -+ */ -+ public static final MaterialSetTag SANDSTONES = new MaterialSetTag(keyFor("sandstones")) -+ .add(Material.SANDSTONE, Material.CHISELED_SANDSTONE, Material.CUT_SANDSTONE, Material.SMOOTH_SANDSTONE); -+ -+ /** -+ * Covers sponge and wet sponge. -+ */ -+ public static final MaterialSetTag SPONGES = new MaterialSetTag(keyFor("sponges")) -+ .endsWith("SPONGE") -+ .ensureSize("SPONGES", 2); -+ -+ /** -+ * Covers the non-colored and colored shulker boxes. -+ */ -+ public static final MaterialSetTag SHULKER_BOXES = new MaterialSetTag(keyFor("shulker_boxes")) -+ .endsWith("SHULKER_BOX") -+ .ensureSize("SHULKER_BOXES", 17); -+ -+ /** -+ * Covers zombie, creeper, skeleton, dragon, and player heads. -+ */ -+ public static final MaterialSetTag SKULLS = new MaterialSetTag(keyFor("skulls")) -+ .endsWith("_HEAD") -+ .endsWith("_SKULL") -+ .not(Material.PISTON_HEAD) -+ .ensureSize("SKULLS", 12); -+ -+ /** -+ * Covers all spawn egg items. -+ */ -+ public static final MaterialSetTag SPAWN_EGGS = new MaterialSetTag(keyFor("spawn_eggs")) -+ .endsWith("_SPAWN_EGG") -+ .ensureSize("SPAWN_EGGS", 64); -+ -+ /** -+ * Covers all colors of stained glass. -+ */ -+ public static final MaterialSetTag STAINED_GLASS = new MaterialSetTag(keyFor("stained_glass")) -+ .endsWith("_STAINED_GLASS") -+ .ensureSize("STAINED_GLASS", 16); -+ -+ /** -+ * Covers all colors of stained glass panes. -+ */ -+ public static final MaterialSetTag STAINED_GLASS_PANES = new MaterialSetTag(keyFor("stained_glass_panes")) -+ .endsWith("STAINED_GLASS_PANE") -+ .ensureSize("STAINED_GLASS_PANES", 16); -+ -+ /** -+ * Covers all variants of trapdoors. -+ */ -+ public static final MaterialSetTag TRAPDOORS = new MaterialSetTag(keyFor("trapdoors")) -+ .endsWith("_TRAPDOOR") -+ .ensureSize("TRAPDOORS", 9); -+ -+ /** -+ * Covers all wood variants of doors. -+ */ -+ public static final MaterialSetTag WOODEN_DOORS = new MaterialSetTag(keyFor("wooden_doors")) -+ .endsWith("_DOOR") -+ .not(Material.IRON_DOOR) -+ .ensureSize("WOODEN_DOORS", 8); -+ -+ /** -+ * Covers all wood variants of fences. -+ */ -+ public static final MaterialSetTag WOODEN_FENCES = new MaterialSetTag(keyFor("wooden_fences")) -+ .endsWith("_FENCE") -+ .not(Material.NETHER_BRICK_FENCE) -+ .ensureSize("WOODEN_FENCES", 8); -+ -+ /** -+ * Covers all wood variants of trapdoors. -+ */ -+ public static final MaterialSetTag WOODEN_TRAPDOORS = new MaterialSetTag(keyFor("wooden_trapdoors")) -+ .endsWith("_TRAPDOOR") -+ .not(Material.IRON_TRAPDOOR) -+ .ensureSize("WOODEN_TRAPDOORS", 8); -+ -+ /** -+ * Covers the wood variants of gates. -+ */ -+ public static final MaterialSetTag WOODEN_GATES = new MaterialSetTag(keyFor("wooden_gates")) -+ .endsWith("_GATE") -+ .ensureSize("WOODEN_GATES", 8); -+ -+ /** -+ * Covers the variants of purpur. -+ */ -+ public static final MaterialSetTag PURPUR = new MaterialSetTag(keyFor("purpur")) -+ .startsWith("PURPUR_") -+ .ensureSize("PURPUR", 4); -+ -+ /** -+ * Covers the variants of signs. -+ */ -+ public static final MaterialSetTag SIGNS = new MaterialSetTag(keyFor("signs")) -+ .endsWith("_SIGN") -+ .ensureSize("SIGNS", 16); -+ -+ /** -+ * Covers the variants of a regular torch. -+ */ -+ public static final MaterialSetTag TORCH = new MaterialSetTag(keyFor("torch")) -+ .add(Material.TORCH, Material.WALL_TORCH) -+ .ensureSize("TORCH", 2); -+ -+ /** -+ * Covers the variants of a redstone torch. -+ */ -+ public static final MaterialSetTag REDSTONE_TORCH = new MaterialSetTag(keyFor("restone_torch")) -+ .add(Material.REDSTONE_TORCH, Material.REDSTONE_WALL_TORCH) -+ .ensureSize("REDSTONE_TORCH", 2); -+ -+ /** -+ * Covers the variants of a soul torch. -+ */ -+ public static final MaterialSetTag SOUL_TORCH = new MaterialSetTag(keyFor("soul_torch")) -+ .add(Material.SOUL_TORCH, Material.SOUL_WALL_TORCH) -+ .ensureSize("SOUL_TORCH", 2); -+ -+ /** -+ * Covers the variants of torches. -+ */ -+ public static final MaterialSetTag TORCHES = new MaterialSetTag(keyFor("torches")) -+ .add(TORCH, REDSTONE_TORCH, SOUL_TORCH) -+ .ensureSize("TORCHES", 6); -+ -+ /** -+ * Covers the variants of lanterns. -+ */ -+ public static final MaterialSetTag LANTERNS = new MaterialSetTag(keyFor("lanterns")) -+ .add(Material.LANTERN, Material.SOUL_LANTERN) -+ .ensureSize("LANTERNS", 2); -+ -+ /** -+ * Covers the variants of rails. -+ */ -+ public static final MaterialSetTag RAILS = new MaterialSetTag(keyFor("rails")) -+ .endsWith("RAIL") -+ .ensureSize("RAILS", 4); -+ -+ /** -+ * Covers the variants of swords. -+ */ -+ public static final MaterialSetTag SWORDS = new MaterialSetTag(keyFor("swords")) -+ .endsWith("_SWORD") -+ .ensureSize("SWORDS", 6); -+ -+ /** -+ * Covers the variants of shovels. -+ */ -+ public static final MaterialSetTag SHOVELS = new MaterialSetTag(keyFor("shovels")) -+ .endsWith("_SHOVEL") -+ .ensureSize("SHOVELS", 6); -+ -+ /** -+ * Covers the variants of pickaxes. -+ */ -+ public static final MaterialSetTag PICKAXES = new MaterialSetTag(keyFor("pickaxes")) -+ .endsWith("_PICKAXE") -+ .ensureSize("PICKAXES", 6); -+ -+ /** -+ * Covers the variants of axes. -+ */ -+ public static final MaterialSetTag AXES = new MaterialSetTag(keyFor("axes")) -+ .endsWith("_AXE") -+ .ensureSize("AXES", 6); -+ -+ /** -+ * Covers the variants of hoes. -+ */ -+ public static final MaterialSetTag HOES = new MaterialSetTag(keyFor("hoes")) -+ .endsWith("_HOE") -+ .ensureSize("HOES", 6); -+ -+ /** -+ * Covers the variants of helmets. -+ */ -+ public static final MaterialSetTag HELMETS = new MaterialSetTag(keyFor("helmets")) -+ .endsWith("_HELMET") -+ .ensureSize("HELMETS", 7); -+ -+ /** -+ * Covers the variants of items that can be equipped in the helmet slot. -+ */ -+ public static final MaterialSetTag HEAD_EQUIPPABLE = new MaterialSetTag(keyFor("head_equippable")) -+ .endsWith("_HELMET") -+ .add(SKULLS) -+ .add(Material.CARVED_PUMPKIN) -+ .ensureSize("HEAD_EQUIPPABLE", 20); -+ -+ /** -+ * Covers the variants of chestplate. -+ */ -+ public static final MaterialSetTag CHESTPLATES = new MaterialSetTag(keyFor("chestplates")) -+ .endsWith("_CHESTPLATE") -+ .ensureSize("CHESTPLATES", 6); -+ -+ /** -+ * Covers the variants of items that can be equipped in the chest slot. -+ */ -+ public static final MaterialSetTag CHEST_EQUIPPABLE = new MaterialSetTag(keyFor("chest_equippable")) -+ .endsWith("_CHESTPLATE") -+ .add(Material.ELYTRA) -+ .ensureSize("CHEST_EQUIPPABLE", 7); -+ -+ /** -+ * Covers the variants of leggings. -+ */ -+ public static final MaterialSetTag LEGGINGS = new MaterialSetTag(keyFor("leggings")) -+ .endsWith("_LEGGINGS") -+ .ensureSize("LEGGINGS", 6); -+ -+ /** -+ * Covers the variants of boots. -+ */ -+ public static final MaterialSetTag BOOTS = new MaterialSetTag(keyFor("boots")) -+ .endsWith("_BOOTS") -+ .ensureSize("BOOTS", 6); -+ -+ /** -+ * Covers the variants of bows. -+ */ -+ public static final MaterialSetTag BOWS = new MaterialSetTag(keyFor("bows")) -+ .add(Material.BOW) -+ .add(Material.CROSSBOW) -+ .ensureSize("BOWS", 2); -+ -+ /** -+ * Covers the variants of player-throwable projectiles (not requiring a bow or any other "assistance"). -+ */ -+ public static final MaterialSetTag THROWABLE_PROJECTILES = new MaterialSetTag(keyFor("throwable_projectiles")) -+ .add(Material.EGG, Material.SNOWBALL, Material.SPLASH_POTION, Material.TRIDENT, Material.ENDER_PEARL, Material.EXPERIENCE_BOTTLE, Material.FIREWORK_ROCKET); -+ -+ /** -+ * Covers materials that can be colored, such as wool, shulker boxes, stained glass etc. -+ */ -+ @SuppressWarnings("unchecked") -+ public static final MaterialSetTag COLORABLE = new MaterialSetTag(keyFor("colorable")) -+ .add(Tag.WOOL, Tag.CARPETS).add(SHULKER_BOXES, STAINED_GLASS, STAINED_GLASS_PANES, CONCRETES, BEDS); -+ //.ensureSize("COLORABLE", 81); unit test don't have the vanilla item tags, so counts don't line up for real -+ -+ /** -+ * Covers the variants of coral. -+ */ -+ public static final MaterialSetTag CORAL = new MaterialSetTag(keyFor("coral")) -+ .endsWith("_CORAL") -+ .ensureSize("CORAL", 10); -+ -+ /** -+ * Covers the variants of coral fans. -+ */ -+ public static final MaterialSetTag CORAL_FANS = new MaterialSetTag(keyFor("coral_fans")) -+ .endsWith("_CORAL_FAN") -+ .endsWith("_CORAL_WALL_FAN") -+ .ensureSize("CORAL_FANS", 20); -+ -+ /** -+ * Covers the variants of coral blocks. -+ */ -+ public static final MaterialSetTag CORAL_BLOCKS = new MaterialSetTag(keyFor("coral_blocks")) -+ .endsWith("_CORAL_BLOCK") -+ .ensureSize("CORAL_BLOCKS", 10); -+ -+ /** -+ * Covers all items that can be enchanted from the enchantment table or anvil. -+ */ -+ public static final MaterialSetTag ENCHANTABLE = new MaterialSetTag(keyFor("enchantable")) -+ .add(PICKAXES, SWORDS, SHOVELS, AXES, HOES, HELMETS, CHEST_EQUIPPABLE, LEGGINGS, BOOTS, BOWS) -+ .add(Material.TRIDENT, Material.SHIELD, Material.FISHING_ROD, Material.SHEARS, Material.FLINT_AND_STEEL, Material.CARROT_ON_A_STICK, Material.WARPED_FUNGUS_ON_A_STICK) -+ .ensureSize("ENCHANTABLE", 65); -+} -diff --git a/src/main/java/io/papermc/paper/tag/BaseTag.java b/src/main/java/io/papermc/paper/tag/BaseTag.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4b8552e4e4c07b197fa9431fa911535b0222561e ---- /dev/null -+++ b/src/main/java/io/papermc/paper/tag/BaseTag.java -@@ -0,0 +1,160 @@ -+package io.papermc.paper.tag; -+ -+import com.google.common.collect.Lists; -+import org.bukkit.Keyed; -+import org.bukkit.NamespacedKey; -+import org.bukkit.Tag; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Collection; -+import java.util.EnumSet; -+import java.util.HashSet; -+import java.util.List; -+import java.util.Set; -+import java.util.function.Predicate; -+import java.util.stream.Collectors; -+ -+public abstract class BaseTag> implements Tag { -+ -+ protected final NamespacedKey key; -+ protected final Set tagged; -+ private final List> globalPredicates; -+ -+ public BaseTag(@NotNull Class clazz, @NotNull NamespacedKey key, @NotNull Predicate filter) { -+ this(clazz, key); -+ add(filter); -+ } -+ -+ public BaseTag(@NotNull Class clazz, @NotNull NamespacedKey key, @NotNull T...values) { -+ this(clazz, key, Lists.newArrayList(values)); -+ } -+ -+ public BaseTag(@NotNull Class clazz, @NotNull NamespacedKey key, @NotNull Collection values) { -+ this(clazz, key, values, o -> true); -+ } -+ -+ public BaseTag(@NotNull Class clazz, @NotNull NamespacedKey key, @NotNull Collection values, @NotNull Predicate... globalPredicates) { -+ this.key = key != null ? key : NamespacedKey.randomKey(); -+ this.tagged = clazz.isEnum() ? createEnumSet(clazz) : new HashSet<>(); -+ this.tagged.addAll(values); -+ this.globalPredicates = Lists.newArrayList(globalPredicates); -+ } -+ -+ private Set createEnumSet(Class enumClass) { -+ assert enumClass.isEnum(); -+ return (Set) EnumSet.noneOf((Class) enumClass); -+ } -+ -+ @NotNull -+ @Override -+ public NamespacedKey getKey() { -+ return key; -+ } -+ -+ @NotNull -+ @Override -+ public Set getValues() { -+ return tagged; -+ } -+ -+ @Override -+ public boolean isTagged(@NotNull T item) { -+ return tagged.contains(item); -+ } -+ -+ @NotNull -+ public C add(@NotNull Tag...tags) { -+ for (Tag tag : tags) { -+ add(tag.getValues()); -+ } -+ return (C) this; -+ } -+ -+ @NotNull -+ public C add(@NotNull T...values) { -+ this.tagged.addAll(Lists.newArrayList(values)); -+ return (C) this; -+ } -+ -+ @NotNull -+ public C add(@NotNull Collection collection) { -+ this.tagged.addAll(collection); -+ return (C) this; -+ } -+ -+ @NotNull -+ public C add(@NotNull Predicate filter) { -+ return add(getAllPossibleValues().stream().filter(globalPredicates.stream().reduce(Predicate::or).orElse(t -> true)).filter(filter).collect(Collectors.toSet())); -+ } -+ -+ @NotNull -+ public C contains(@NotNull String with) { -+ return add(value -> getName(value).contains(with)); -+ } -+ -+ @NotNull -+ public C endsWith(@NotNull String with) { -+ return add(value -> getName(value).endsWith(with)); -+ } -+ -+ @NotNull -+ public C startsWith(@NotNull String with) { -+ return add(value -> getName(value).startsWith(with)); -+ } -+ -+ @NotNull -+ public C not(@NotNull Tag...tags) { -+ for (Tag tag : tags) { -+ not(tag.getValues()); -+ } -+ return (C) this; -+ } -+ -+ @NotNull -+ public C not(@NotNull T...values) { -+ this.tagged.removeAll(Lists.newArrayList(values)); -+ return (C) this; -+ } -+ -+ @NotNull -+ public C not(@NotNull Collection values) { -+ this.tagged.removeAll(values); -+ return (C) this; -+ } -+ -+ @NotNull -+ public C not(@NotNull Predicate filter) { -+ not(getAllPossibleValues().stream().filter(globalPredicates.stream().reduce(Predicate::or).orElse(t -> true)).filter(filter).collect(Collectors.toSet())); -+ return (C) this; -+ } -+ -+ @NotNull -+ public C notContains(@NotNull String with) { -+ return not(value -> getName(value).contains(with)); -+ } -+ -+ @NotNull -+ public C notEndsWith(@NotNull String with) { -+ return not(value -> getName(value).endsWith(with)); -+ } -+ -+ @NotNull -+ public C notStartsWith(@NotNull String with) { -+ return not(value -> getName(value).startsWith(with)); -+ } -+ -+ @NotNull -+ public C ensureSize(@NotNull String label, int size) { -+ long actual = this.tagged.stream().filter(globalPredicates.stream().reduce(Predicate::or).orElse(t -> true)).count(); -+ if (size != actual) { -+ throw new IllegalStateException(key.toString() + ": " + label + " - Expected " + size + " values, got " + actual); -+ } -+ return (C) this; -+ } -+ -+ @NotNull -+ protected abstract Set getAllPossibleValues(); -+ -+ @NotNull -+ protected abstract String getName(@NotNull T value); -+} -diff --git a/src/main/java/io/papermc/paper/tag/EntitySetTag.java b/src/main/java/io/papermc/paper/tag/EntitySetTag.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c89c4619aaf388197834d98eb95af2f1e93db871 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/tag/EntitySetTag.java -@@ -0,0 +1,42 @@ -+package io.papermc.paper.tag; -+ -+import org.bukkit.NamespacedKey; -+import org.bukkit.entity.EntityType; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Collection; -+import java.util.Set; -+import java.util.function.Predicate; -+import java.util.stream.Collectors; -+import java.util.stream.Stream; -+ -+public class EntitySetTag extends BaseTag { -+ -+ public EntitySetTag(@NotNull NamespacedKey key, @NotNull Predicate filter) { -+ super(EntityType.class, key, filter); -+ } -+ -+ public EntitySetTag(@NotNull NamespacedKey key, @NotNull EntityType... values) { -+ super(EntityType.class, key, values); -+ } -+ -+ public EntitySetTag(@NotNull NamespacedKey key, @NotNull Collection values) { -+ super(EntityType.class, key, values); -+ } -+ -+ public EntitySetTag(@NotNull NamespacedKey key, @NotNull Collection values, @NotNull Predicate... globalPredicates) { -+ super(EntityType.class, key, values, globalPredicates); -+ } -+ -+ @NotNull -+ @Override -+ protected Set getAllPossibleValues() { -+ return Stream.of(EntityType.values()).collect(Collectors.toSet()); -+ } -+ -+ @NotNull -+ @Override -+ protected String getName(@NotNull EntityType value) { -+ return value.name(); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/tag/EntityTags.java b/src/main/java/io/papermc/paper/tag/EntityTags.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9266c9d77e2eef7cd717dc729834a190f1fc7c1d ---- /dev/null -+++ b/src/main/java/io/papermc/paper/tag/EntityTags.java -@@ -0,0 +1,50 @@ -+package io.papermc.paper.tag; -+ -+import org.bukkit.NamespacedKey; -+ -+import static org.bukkit.entity.EntityType.*; -+ -+public class EntityTags { -+ -+ private static NamespacedKey keyFor(String key) { -+ //noinspection deprecation -+ return new NamespacedKey("paper", key + "_settag"); -+ } -+ -+ /** -+ * Covers undead mobs -+ * @see https://minecraft.gamepedia.com/Mob#Undead_mobs -+ */ -+ public static final EntitySetTag UNDEADS = new EntitySetTag(keyFor("undeads")) -+ .add(DROWNED, HUSK, PHANTOM, SKELETON, SKELETON_HORSE, STRAY, WITHER, WITHER_SKELETON, ZOGLIN, ZOMBIE, ZOMBIE_HORSE, ZOMBIE_VILLAGER, ZOMBIFIED_PIGLIN) -+ .ensureSize("UNDEADS", 13); -+ -+ /** -+ * Covers all horses -+ */ -+ public static final EntitySetTag HORSES = new EntitySetTag(keyFor("horses")) -+ .contains("HORSE") -+ .ensureSize("HORSES", 3); -+ -+ /** -+ * Covers all minecarts -+ */ -+ public static final EntitySetTag MINECARTS = new EntitySetTag(keyFor("minecarts")) -+ .contains("MINECART") -+ .ensureSize("MINECARTS", 7); -+ -+ /** -+ * Covers mobs that split into smaller mobs -+ */ -+ public static final EntitySetTag SPLITTING_MOBS = new EntitySetTag(keyFor("splitting_mobs")) -+ .add(SLIME, MAGMA_CUBE) -+ .ensureSize("SLIMES", 2); -+ -+ /** -+ * Covers all water based mobs -+ * @see https://minecraft.gamepedia.com/Mob#Water-based_mobs -+ */ -+ public static final EntitySetTag WATER_BASED = new EntitySetTag(keyFor("water_based")) -+ .add(DOLPHIN, SQUID, GUARDIAN, ELDER_GUARDIAN, TURTLE, COD, SALMON, PUFFERFISH, TROPICAL_FISH) -+ .ensureSize("WATER_BASED", 9); -+} -diff --git a/src/main/java/org/bukkit/Tag.java b/src/main/java/org/bukkit/Tag.java -index aacbfadc91f580cc667603c8165eacbadee38cca..3c2a6a2167eab43097f5d6ccf1550e12795fc0b6 100644 ---- a/src/main/java/org/bukkit/Tag.java -+++ b/src/main/java/org/bukkit/Tag.java -@@ -10,6 +10,10 @@ import org.jetbrains.annotations.NotNull; - * Note that whilst all tags defined within this interface must be present in - * implementations, their existence is not guaranteed across future versions. - * -+ *

    Custom tags defined by Paper are not present (as constants) in this class. -+ * To access them please refer to {@link com.destroystokyo.paper.MaterialTags} -+ * and {@link io.papermc.paper.tag.EntityTags}.

    -+ * - * @param the type of things grouped by this tag - */ - public interface Tag extends Keyed { -diff --git a/src/test/java/com/destroystokyo/paper/MaterialTagsTest.java b/src/test/java/com/destroystokyo/paper/MaterialTagsTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..328c51471dc12e81c1a1b643455337b3fef4d14a ---- /dev/null -+++ b/src/test/java/com/destroystokyo/paper/MaterialTagsTest.java -@@ -0,0 +1,25 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ */ -+ -+package com.destroystokyo.paper; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.TestServer; -+import org.junit.Test; -+ -+import java.util.logging.Level; -+ -+public class MaterialTagsTest { -+ @Test -+ public void testInitialize() { -+ try { -+ TestServer.getInstance(); -+ MaterialTags.SHULKER_BOXES.getValues(); -+ assert true; -+ } catch (Throwable e) { -+ Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e); -+ assert false; -+ } -+ } -+} -diff --git a/src/test/java/io/papermc/paper/EntityTagsTest.java b/src/test/java/io/papermc/paper/EntityTagsTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..06bb9d1180361d3d00c699796bbacbce5bef2177 ---- /dev/null -+++ b/src/test/java/io/papermc/paper/EntityTagsTest.java -@@ -0,0 +1,24 @@ -+package io.papermc.paper; -+ -+import com.destroystokyo.paper.MaterialTags; -+import io.papermc.paper.tag.EntityTags; -+import org.bukkit.Bukkit; -+import org.bukkit.TestServer; -+import org.junit.Test; -+ -+import java.util.logging.Level; -+ -+public class EntityTagsTest { -+ -+ @Test -+ public void testInitialize() { -+ try { -+ TestServer.getInstance(); -+ EntityTags.HORSES.getValues(); -+ assert true; -+ } catch (Throwable e) { -+ Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e); -+ assert false; -+ } -+ } -+} -diff --git a/src/test/java/org/bukkit/TestServer.java b/src/test/java/org/bukkit/TestServer.java -index 61993528e6975c38d82213e9b5caf996fe777328..5f9d348241210689eaf41a39ace5948e7a237b12 100644 ---- a/src/test/java/org/bukkit/TestServer.java -+++ b/src/test/java/org/bukkit/TestServer.java -@@ -29,6 +29,16 @@ public final class TestServer implements InvocationHandler { - } - } - ); -+ // Paper start -+ methodMap.put( -+ Server.class.getMethod("getTag", String.class, NamespacedKey.class, Class.class), -+ new MethodHandler() { -+ public Object handle(TestServer server, Object[] args) { -+ return new com.destroystokyo.paper.MaterialSetTag(); -+ } -+ } -+ ); -+ // Paper end - methodMap.put( - Server.class.getMethod("getPluginManager"), - new MethodHandler() { diff --git a/Unmapped-Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch b/Unmapped-Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch deleted file mode 100644 index 68b33503be..0000000000 --- a/Unmapped-Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 6 Oct 2018 21:47:09 -0500 -Subject: [PATCH] Allow setting the vex's summoner - - -diff --git a/src/main/java/org/bukkit/entity/Vex.java b/src/main/java/org/bukkit/entity/Vex.java -index 6b61c4ab773c731fe5ae9577fd13e44707be9787..c34a3ea7b4d16817b4bee25d5c69787e22ec44d8 100644 ---- a/src/main/java/org/bukkit/entity/Vex.java -+++ b/src/main/java/org/bukkit/entity/Vex.java -@@ -1,5 +1,7 @@ - package org.bukkit.entity; - -+import org.jetbrains.annotations.Nullable; -+ - /** - * Represents a Vex. - */ -@@ -22,4 +24,21 @@ public interface Vex extends Monster { - * @param charging new state - */ - void setCharging(boolean charging); -+ -+ // Paper start -+ /** -+ * Get the Mob that summoned this vex -+ * -+ * @return Mob that summoned this vex -+ */ -+ @Nullable -+ Mob getSummoner(); -+ -+ /** -+ * Set the summoner of this vex -+ * -+ * @param summoner New summoner -+ */ -+ void setSummoner(@Nullable Mob summoner); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch b/Unmapped-Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch deleted file mode 100644 index cc02ae973f..0000000000 --- a/Unmapped-Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 22 Sep 2018 00:32:53 -0500 -Subject: [PATCH] Add LivingEntity#getTargetEntity - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/TargetEntityInfo.java b/src/main/java/com/destroystokyo/paper/entity/TargetEntityInfo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f52644fab1522bdf83ff4f489e9805b274421094 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/TargetEntityInfo.java -@@ -0,0 +1,38 @@ -+package com.destroystokyo.paper.entity; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.util.Vector; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents information about a targeted entity -+ */ -+public class TargetEntityInfo { -+ private final Entity entity; -+ private final Vector hitVec; -+ -+ public TargetEntityInfo(@NotNull Entity entity, @NotNull Vector hitVec) { -+ this.entity = entity; -+ this.hitVec = hitVec; -+ } -+ -+ /** -+ * Get the entity that is targeted -+ * -+ * @return Targeted entity -+ */ -+ @NotNull -+ public Entity getEntity() { -+ return entity; -+ } -+ -+ /** -+ * Get the position the entity is targeted at -+ * -+ * @return Targeted position -+ */ -+ @NotNull -+ public Vector getHitVector() { -+ return hitVec; -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 8fe7ccf12339355554835542cc1068d9f6c3a435..561db9d594633e3909fd6d69dad1dc2976928d58 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -151,6 +151,50 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - */ - @Nullable - public com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode); -+ -+ /** -+ * Gets information about the entity being targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @return entity being targeted, or null if no entity is targeted -+ */ -+ @Nullable -+ public default Entity getTargetEntity(int maxDistance) { -+ return getTargetEntity(maxDistance, false); -+ } -+ -+ /** -+ * Gets information about the entity being targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @param ignoreBlocks true to scan through blocks -+ * @return entity being targeted, or null if no entity is targeted -+ */ -+ @Nullable -+ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks); -+ -+ /** -+ * Gets information about the entity being targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @return TargetEntityInfo about the entity being targeted, -+ * or null if no entity is targeted -+ */ -+ @Nullable -+ public default com.destroystokyo.paper.entity.TargetEntityInfo getTargetEntityInfo(int maxDistance) { -+ return getTargetEntityInfo(maxDistance, false); -+ } -+ -+ /** -+ * Gets information about the entity being targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @param ignoreBlocks true to scan through blocks -+ * @return TargetEntityInfo about the entity being targeted, -+ * or null if no entity is targeted -+ */ -+ @Nullable -+ public com.destroystokyo.paper.entity.TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks); - // Paper end - - /** diff --git a/Unmapped-Spigot-API-Patches/0157-Add-sun-related-API.patch b/Unmapped-Spigot-API-Patches/0157-Add-sun-related-API.patch deleted file mode 100644 index 85efb56e43..0000000000 --- a/Unmapped-Spigot-API-Patches/0157-Add-sun-related-API.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 Oct 2018 00:54:15 -0500 -Subject: [PATCH] Add sun related API - - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index ec8e3a949a869545a8e0cb8c2f59f1a6dd8f5485..ce1a3de1d03e10b18c0098ee2778361cc9a4cb01 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -1812,6 +1812,16 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - */ - public void setFullTime(long time); - -+ // Paper start -+ -+ /** -+ * Check if it is currently daytime in this world -+ * -+ * @return True if it is daytime -+ */ -+ public boolean isDayTime(); -+ // Paper end -+ - /** - * Gets the full in-game time on this world since the world generation - * -diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java -index b132287817d35579ca5128a1ed5c242bf229771a..d726453c041a980576312b6bee96a07837f37974 100644 ---- a/src/main/java/org/bukkit/entity/Mob.java -+++ b/src/main/java/org/bukkit/entity/Mob.java -@@ -16,6 +16,13 @@ public interface Mob extends LivingEntity, Lootable { - */ - @NotNull - com.destroystokyo.paper.entity.Pathfinder getPathfinder(); -+ -+ /** -+ * Check if this mob is exposed to daylight -+ * -+ * @return True if mob is exposed to daylight -+ */ -+ boolean isInDaylight(); - // Paper end - - /** diff --git a/Unmapped-Spigot-API-Patches/0158-Here-s-Johnny.patch b/Unmapped-Spigot-API-Patches/0158-Here-s-Johnny.patch deleted file mode 100644 index faaadfb5db..0000000000 --- a/Unmapped-Spigot-API-Patches/0158-Here-s-Johnny.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 12 Oct 2018 01:37:16 -0500 -Subject: [PATCH] Here's Johnny! - - -diff --git a/src/main/java/org/bukkit/entity/Vindicator.java b/src/main/java/org/bukkit/entity/Vindicator.java -index b8ea68a8f420c1ba99c0621a15e654d3ee48c8d6..c5d9e76a6a4125eb0409967a57e3836b8f2d24a0 100644 ---- a/src/main/java/org/bukkit/entity/Vindicator.java -+++ b/src/main/java/org/bukkit/entity/Vindicator.java -@@ -3,4 +3,30 @@ package org.bukkit.entity; - /** - * Represents a Vindicator. - */ --public interface Vindicator extends Illager { } -+public interface Vindicator extends Illager { -+ // Paper start -+ /** -+ * Check if this Vindicator is set to Johnny mode. -+ *

    -+ * When in Johnny mode the Vindicator will be hostile to any kind of mob, except -+ * for evokers, ghasts, illusioners and other vindicators. It will even be hostile -+ * to vexes. All mobs, except for endermites, phantoms, guardians, slimes and -+ * magma cubes, will try to attack the vindicator in return. -+ * -+ * @return True if in Johnny mode -+ */ -+ boolean isJohnny(); -+ -+ /** -+ * Set this Vindicator's Johnny mode. -+ *

    -+ * When in Johnny mode the Vindicator will be hostile to any kind of mob, except -+ * for evokers, ghasts, illusioners and other vindicators. It will even be hostile -+ * to vexes. All mobs, except for endermites, phantoms, guardians, slimes and -+ * magma cubes, will try to attack the vindicator in return. -+ * -+ * @param johnny True to enable Johnny mode -+ */ -+ void setJohnny(boolean johnny); -+ // Paper end -+} diff --git a/Unmapped-Spigot-API-Patches/0159-Turtle-API.patch b/Unmapped-Spigot-API-Patches/0159-Turtle-API.patch deleted file mode 100644 index 06abb703f4..0000000000 --- a/Unmapped-Spigot-API-Patches/0159-Turtle-API.patch +++ /dev/null @@ -1,283 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 28 Sep 2018 17:08:09 -0500 -Subject: [PATCH] Turtle API - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/TurtleGoHomeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/TurtleGoHomeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..021356d151ed638068e3e89b8cc77b3795883233 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/TurtleGoHomeEvent.java -@@ -0,0 +1,49 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Turtle; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Turtle decides to go home -+ */ -+public class TurtleGoHomeEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled = false; -+ -+ public TurtleGoHomeEvent(@NotNull Turtle turtle) { -+ super(turtle); -+ } -+ -+ /** -+ * The turtle going home -+ * -+ * @return The turtle -+ */ -+ @NotNull -+ public Turtle getEntity() { -+ return (Turtle) entity; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a315c5185cd465dcf63c0ababef195da76dfc786 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java -@@ -0,0 +1,87 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.Turtle; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Turtle lays eggs -+ */ -+public class TurtleLayEggEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled = false; -+ @NotNull -+ private final Location location; -+ private int eggCount; -+ -+ public TurtleLayEggEvent(@NotNull Turtle turtle, @NotNull Location location, int eggCount) { -+ super(turtle); -+ this.location = location; -+ this.eggCount = eggCount; -+ } -+ -+ /** -+ * The turtle laying the eggs -+ * -+ * @return The turtle -+ */ -+ @NotNull -+ public Turtle getEntity() { -+ return (Turtle) entity; -+ } -+ -+ /** -+ * Get the location where the eggs are being laid -+ * -+ * @return Location of eggs -+ */ -+ @NotNull -+ public Location getLocation() { -+ return location; -+ } -+ -+ /** -+ * Get the number of eggs being laid -+ * -+ * @return Number of eggs -+ */ -+ public int getEggCount() { -+ return eggCount; -+ } -+ -+ /** -+ * Set the number of eggs being laid -+ * -+ * @param eggCount Number of eggs -+ */ -+ public void setEggCount(int eggCount) { -+ if (eggCount < 1) { -+ cancelled = true; -+ return; -+ } -+ eggCount = Math.min(eggCount, 4); -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..abeb24fccda2acfdb0dfdadacb8fe688bd97cf78 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java -@@ -0,0 +1,62 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.Turtle; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Turtle starts digging to lay eggs -+ */ -+public class TurtleStartDiggingEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled = false; -+ @NotNull private final Location location; -+ -+ public TurtleStartDiggingEvent(@NotNull Turtle turtle, @NotNull Location location) { -+ super(turtle); -+ this.location = location; -+ } -+ -+ /** -+ * The turtle digging -+ * -+ * @return The turtle -+ */ -+ @NotNull -+ public Turtle getEntity() { -+ return (Turtle) entity; -+ } -+ -+ /** -+ * Get the location where the turtle is digging -+ * -+ * @return Location where digging -+ */ -+ @NotNull -+ public Location getLocation() { -+ return location; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Turtle.java b/src/main/java/org/bukkit/entity/Turtle.java -index 0a4cd29930c2f1c28f5a3e6884c7dec45b5cac11..5375ea14097f4f10b2294488b92924a35a72d4d7 100644 ---- a/src/main/java/org/bukkit/entity/Turtle.java -+++ b/src/main/java/org/bukkit/entity/Turtle.java -@@ -1,6 +1,55 @@ - package org.bukkit.entity; - -+import org.bukkit.Location; -+import org.jetbrains.annotations.NotNull; -+ - /** - * Represents a turtle. - */ --public interface Turtle extends Animals { } -+public interface Turtle extends Animals { -+ // Paper start -+ -+ /** -+ * Get the turtle's home location -+ * -+ * @return Home location -+ */ -+ @NotNull -+ Location getHome(); -+ -+ /** -+ * Set the turtle's home location -+ * -+ * @param location Home location -+ */ -+ void setHome(@NotNull Location location); -+ -+ /** -+ * Check if turtle is currently pathfinding to it's home -+ * -+ * @return True if going home -+ */ -+ boolean isGoingHome(); -+ -+ /** -+ * Get if turtle is digging to lay eggs -+ * -+ * @return True if digging -+ */ -+ boolean isDigging(); -+ -+ /** -+ * Get if turtle is carrying egg -+ * -+ * @return True if carrying egg -+ */ -+ boolean hasEgg(); -+ -+ /** -+ * Set if turtle is carrying egg -+ * -+ * @param hasEgg True if carrying egg -+ */ -+ void setHasEgg(boolean hasEgg); -+ // Paper end -+} diff --git a/Unmapped-Spigot-API-Patches/0160-Add-spectator-target-events.patch b/Unmapped-Spigot-API-Patches/0160-Add-spectator-target-events.patch deleted file mode 100644 index c5d4b7c4db..0000000000 --- a/Unmapped-Spigot-API-Patches/0160-Add-spectator-target-events.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Caleb Bassham -Date: Fri, 28 Sep 2018 02:30:56 -0500 -Subject: [PATCH] Add spectator target events - -- PlayerStartSpectatingEntityEvent -- PlayerStopSpectatingEntityEvent - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerStartSpectatingEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerStartSpectatingEntityEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b8ec7ef2d4ef0683cc0d6ca86885dd9a01f47e16 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerStartSpectatingEntityEvent.java -@@ -0,0 +1,67 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Triggered when a player starts spectating an entity in spectator mode. -+ */ -+public class PlayerStartSpectatingEntityEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ @NotNull private final Entity currentSpectatorTarget; -+ @NotNull private final Entity newSpectatorTarget; -+ -+ public PlayerStartSpectatingEntityEvent(@NotNull Player player, @NotNull Entity currentSpectatorTarget, @NotNull Entity newSpectatorTarget) { -+ super(player); -+ this.currentSpectatorTarget = currentSpectatorTarget; -+ this.newSpectatorTarget = newSpectatorTarget; -+ } -+ -+ /** -+ * Gets the entity that the player is currently spectating or themselves if they weren't spectating anything -+ * -+ * @return The entity the player is currently spectating (before they start spectating the new target). -+ */ -+ @NotNull -+ public Entity getCurrentSpectatorTarget() { -+ return currentSpectatorTarget; -+ } -+ -+ /** -+ * Gets the new entity that the player will now be spectating -+ * -+ * @return The entity the player is now going to be spectating. -+ */ -+ @NotNull -+ public Entity getNewSpectatorTarget() { -+ return newSpectatorTarget; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -+ -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerStopSpectatingEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerStopSpectatingEntityEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..693d119ab920a1bd0d1b5a0feb092631715ec0ad ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerStopSpectatingEntityEvent.java -@@ -0,0 +1,54 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Triggered when a player stops spectating an entity in spectator mode. -+ */ -+public class PlayerStopSpectatingEntityEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ @NotNull private final Entity spectatorTarget; -+ -+ public PlayerStopSpectatingEntityEvent(@NotNull Player player, @NotNull Entity spectatorTarget) { -+ super(player); -+ this.spectatorTarget = spectatorTarget; -+ } -+ -+ /** -+ * Gets the entity that the player is spectating -+ * -+ * @return The entity the player is currently spectating (before they will stop). -+ */ -+ @NotNull -+ public Entity getSpectatorTarget() { -+ return spectatorTarget; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0161-Add-more-Witch-API.patch b/Unmapped-Spigot-API-Patches/0161-Add-more-Witch-API.patch deleted file mode 100644 index 8fa1dd1e47..0000000000 --- a/Unmapped-Spigot-API-Patches/0161-Add-more-Witch-API.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 12 Oct 2018 03:47:26 -0500 -Subject: [PATCH] Add more Witch API - - -diff --git a/src/main/java/org/bukkit/entity/Witch.java b/src/main/java/org/bukkit/entity/Witch.java -index aa88aede6c4e66a608a63d07bc66d60357b0bee9..b7f9db08fb2e4633e1dfad5c752451f6ac23d437 100644 ---- a/src/main/java/org/bukkit/entity/Witch.java -+++ b/src/main/java/org/bukkit/entity/Witch.java -@@ -2,8 +2,53 @@ package org.bukkit.entity; - - import com.destroystokyo.paper.entity.RangedEntity; - -+// Paper start -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.Nullable; -+// Paper end -+ - /** - * Represents a Witch - */ - public interface Witch extends Raider, RangedEntity { // Paper -+ // Paper start -+ /** -+ * Check if Witch is drinking a potion -+ * -+ * @return True if drinking a potion -+ */ -+ boolean isDrinkingPotion(); -+ -+ /** -+ * Get time remaining (in ticks) the Witch is drinking a potion -+ * -+ * @return Time remaining (in ticks) -+ */ -+ int getPotionUseTimeLeft(); -+ -+ /** -+ * Set time remaining (in ticks) that the Witch is drinking a potion. -+ *

    -+ * This only has an effect while the Witch is drinking a potion. -+ * -+ * @param ticks Time in ticks remaining -+ * @see #isDrinkingPotion -+ */ -+ void setPotionUseTimeLeft(int ticks); -+ -+ /** -+ * Get the potion the Witch is drinking -+ * -+ * @return The potion the witch is drinking -+ */ -+ @Nullable -+ ItemStack getDrinkingPotion(); -+ -+ /** -+ * Set the potion the Witch should drink -+ * -+ * @param potion Potion to drink -+ */ -+ void setDrinkingPotion(@Nullable ItemStack potion); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch b/Unmapped-Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch deleted file mode 100644 index 06ba70ae7d..0000000000 --- a/Unmapped-Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 18 Nov 2018 19:44:54 +0000 -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 6b619b85fee86ccc599cb46d789e39b81af3201c..dcaefdaf5a0de8486f59115c8c4d4c211b7d64cd 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1793,6 +1793,15 @@ public final class Bukkit { - return server.suggestPlayerNamesWhenNullTabCompletions(); - } - -+ /** -+ * -+ * @return the default no permission message used on the server -+ */ -+ @NotNull -+ public static String getPermissionMessage() { -+ return server.getPermissionMessage(); -+ } -+ - /** - * Creates a PlayerProfile for the specified uuid, with name as null - * @param uuid UUID to create profile for -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index c642fe9cfae6407404f5cf17264f42ef83a01280..9b8e6b7bbbed44e2659379c8046acaa35aaa8910 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1575,6 +1575,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - */ - boolean suggestPlayerNamesWhenNullTabCompletions(); - -+ /** -+ * -+ * @return the default no permission message used on the server -+ */ -+ @NotNull -+ String getPermissionMessage(); -+ - /** - * Creates a PlayerProfile for the specified uuid, with name as null - * @param uuid UUID to create profile for -diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java -index 7c80dc54776d0d66f7816b77136f6dbd9b801704..c10fc8d2386301bc2caddcdb1cd18566bcaa8689 100644 ---- a/src/main/java/org/bukkit/command/Command.java -+++ b/src/main/java/org/bukkit/command/Command.java -@@ -185,7 +185,7 @@ public abstract class Command { - } - - if (permissionMessage == null) { -- target.sendMessage(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is a mistake."); -+ target.sendMessage(Bukkit.getPermissionMessage()); // Paper - } else if (permissionMessage.length() != 0) { - for (String line : permissionMessage.replace("", permission).split("\n")) { - target.sendMessage(line); diff --git a/Unmapped-Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch b/Unmapped-Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch deleted file mode 100644 index a36772974a..0000000000 --- a/Unmapped-Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 18 Nov 2018 15:53:43 +0000 -Subject: [PATCH] Support cancellation supression of EntityDismount/VehicleExit - events" - -Entities must be dismounted before teleportation in order to avoid -multiple issues in the server with regards to teleportation, shamefully, -too many plugins rely on the events firing, which means that not firing -these events caues more issues than it solves; - -In order to counteract this, Entity dismount/exit vehicle events have -been modified to supress cancellation (and has a method to allow plugins -to check if this has been set), noting that cancellation will be silently -surpressed given that plugins are not expecting this event to not be cancellable. - -This is a far from ideal scenario, however: given the current state of this -event and other alternatives causing issues elsewhere, I believe that -this is going to be the best soultion all around. - -Improvements/suggestions welcome! - -diff --git a/src/main/java/org/bukkit/event/vehicle/VehicleExitEvent.java b/src/main/java/org/bukkit/event/vehicle/VehicleExitEvent.java -index 963b9ead4ca0426b2e95c5641b0e89317c48853d..a976c32de6ad5e90b0a96a0f387136ab0f5eb52e 100644 ---- a/src/main/java/org/bukkit/event/vehicle/VehicleExitEvent.java -+++ b/src/main/java/org/bukkit/event/vehicle/VehicleExitEvent.java -@@ -13,10 +13,18 @@ public class VehicleExitEvent extends VehicleEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled; - private final LivingEntity exited; -+ private final boolean isCancellable; // Paper - -- public VehicleExitEvent(@NotNull final Vehicle vehicle, @NotNull final LivingEntity exited) { -+ public VehicleExitEvent(@NotNull final Vehicle vehicle, @NotNull final LivingEntity exited, boolean isCancellable) { // Paper - super(vehicle); - this.exited = exited; -+ // Paper start -+ this.isCancellable = isCancellable; -+ } -+ -+ public VehicleExitEvent(@NotNull final Vehicle vehicle, @NotNull final LivingEntity exited) { -+ this(vehicle, exited, true); -+ // Paper end - } - - /** -@@ -36,9 +44,18 @@ public class VehicleExitEvent extends VehicleEvent implements Cancellable { - - @Override - public void setCancelled(boolean cancel) { -+ // Paper start -+ if (cancel && !isCancellable) { -+ return; -+ } - this.cancelled = cancel; - } - -+ public boolean isCancellable() { -+ return isCancellable; -+ // paper end -+ } -+ - @NotNull - @Override - public HandlerList getHandlers() { -diff --git a/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java b/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java -index 00d8ec81b4ae6ca5e438161ec9135e3c1edea6f4..a7632c8f5cb1bce4be0e456ec34f4a69c5ce80f3 100644 ---- a/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java -+++ b/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java -@@ -14,10 +14,19 @@ public class EntityDismountEvent extends EntityEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled; - private final Entity dismounted; -+ private final boolean isCancellable; // Paper - - public EntityDismountEvent(@NotNull Entity what, @NotNull Entity dismounted) { -- super(what); -+ // Paper start -+ this(what, dismounted, true); -+ } -+ -+ -+ public EntityDismountEvent(@NotNull Entity what, @NotNull Entity dismounted, boolean isCancellable) { -+ // Paper end -+ super( what ); - this.dismounted = dismounted; -+ this.isCancellable = isCancellable; // Paper - } - - @NotNull -@@ -32,9 +41,18 @@ public class EntityDismountEvent extends EntityEvent implements Cancellable { - - @Override - public void setCancelled(boolean cancel) { -+ // Paper start -+ if (cancel && !isCancellable) { -+ return; -+ } - this.cancelled = cancel; - } - -+ public boolean isCancellable() { -+ return isCancellable; -+ // Paper end -+ } -+ - @NotNull - @Override - public HandlerList getHandlers() { diff --git a/Unmapped-Spigot-API-Patches/0164-Add-more-Zombie-API.patch b/Unmapped-Spigot-API-Patches/0164-Add-more-Zombie-API.patch deleted file mode 100644 index ec2c93dc46..0000000000 --- a/Unmapped-Spigot-API-Patches/0164-Add-more-Zombie-API.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 Oct 2018 04:29:51 -0500 -Subject: [PATCH] Add more Zombie API - - -diff --git a/src/main/java/org/bukkit/entity/Zombie.java b/src/main/java/org/bukkit/entity/Zombie.java -index a5b20b0454af5ea78e2bb7f16a56c38670c84efb..1217576e6f08abf0175ab800cfca058d5deda116 100644 ---- a/src/main/java/org/bukkit/entity/Zombie.java -+++ b/src/main/java/org/bukkit/entity/Zombie.java -@@ -90,4 +90,55 @@ public interface Zombie extends Monster, Ageable { - * @param time new conversion time - */ - void setConversionTime(int time); -+ // Paper start -+ /** -+ * Check if zombie is drowning -+ * -+ * @return True if zombie conversion process has begun -+ */ -+ boolean isDrowning(); -+ -+ /** -+ * Make zombie start drowning -+ * -+ * @param drownedConversionTime Amount of time until zombie converts from drowning -+ * -+ * @deprecated See {@link #setConversionTime(int)} -+ */ -+ @Deprecated -+ void startDrowning(int drownedConversionTime); -+ -+ /** -+ * Stop a zombie from starting the drowning conversion process -+ */ -+ void stopDrowning(); -+ -+ /** -+ * Set if zombie has its arms raised -+ * -+ * @param raised True to raise arms -+ */ -+ void setArmsRaised(boolean raised); -+ -+ /** -+ * Check if zombie has arms raised -+ * -+ * @return True if arms are raised -+ */ -+ boolean isArmsRaised(); -+ -+ /** -+ * Check if this zombie will burn in the sunlight -+ * -+ * @return True if zombie will burn in sunlight -+ */ -+ boolean shouldBurnInDay(); -+ -+ /** -+ * Set if this zombie should burn in the sunlight -+ * -+ * @param shouldBurnInDay True to burn in sunlight -+ */ -+ void setShouldBurnInDay(boolean shouldBurnInDay); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch b/Unmapped-Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch deleted file mode 100644 index fa3de62864..0000000000 --- a/Unmapped-Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DoNotSpamPls <7570108+DoNotSpamPls@users.noreply.github.com> -Date: Tue, 23 Oct 2018 19:32:55 +0300 -Subject: [PATCH] Change the reserved channel check to be sensible - - -diff --git a/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java b/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java -index 1d061412cdafa28c6940c7433747ab1dabe23de1..6fda7f3aa68e76af64362e9afed70fc6a5e92986 100644 ---- a/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java -+++ b/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java -@@ -172,7 +172,7 @@ public class StandardMessenger implements Messenger { - public boolean isReservedChannel(@NotNull String channel) { - channel = validateAndCorrectChannel(channel); - -- return channel.contains("minecraft") && !channel.equals("minecraft:brand"); -+ return channel.equals("minecraft:register") || channel.equals("minecraft:unregister"); // Paper - } - - @Override -diff --git a/src/test/java/org/bukkit/plugin/messaging/StandardMessengerTest.java b/src/test/java/org/bukkit/plugin/messaging/StandardMessengerTest.java -index dce3d619a6f1791197e44277c2dee9eaf19ff56f..7e2335ed8acc692af1e70eddcf97ee7a56e30f68 100644 ---- a/src/test/java/org/bukkit/plugin/messaging/StandardMessengerTest.java -+++ b/src/test/java/org/bukkit/plugin/messaging/StandardMessengerTest.java -@@ -25,8 +25,8 @@ public class StandardMessengerTest { - assertTrue(messenger.isReservedChannel("minecraft:register")); - assertFalse(messenger.isReservedChannel("test:register")); - assertTrue(messenger.isReservedChannel("minecraft:unregister")); -- assertFalse(messenger.isReservedChannel("test:nregister")); -- assertTrue(messenger.isReservedChannel("minecraft:something")); -+ assertFalse(messenger.isReservedChannel("test:unregister")); // Paper - fix typo -+ assertFalse(messenger.isReservedChannel("minecraft:something")); // Paper - now less strict - assertFalse(messenger.isReservedChannel("minecraft:brand")); - } - diff --git a/Unmapped-Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch b/Unmapped-Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch deleted file mode 100644 index f1a017f4fb..0000000000 --- a/Unmapped-Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 7 Oct 2018 12:05:06 -0700 -Subject: [PATCH] Add PlayerConnectionCloseEvent - -This event is invoked when a player has disconnected. It is guaranteed that, -if the server is in online-mode, that the provided uuid and username have been -validated. - -The event is invoked for players who have not yet logged into the world, whereas -PlayerQuitEvent is only invoked on players who have logged into the world. - -The event is invoked for players who have already logged into the world, -although whether or not the player exists in the world at the time of -firing is undefined. (That is, whether the plugin can retrieve a Player object -using the event parameters is undefined). However, it is guaranteed that this -event is invoked AFTER PlayerQuitEvent, if the player has already logged into -the world. - -This event is guaranteed to never fire unless AsyncPlayerPreLoginEvent has -been called beforehand, and this event may not be called in parallel with -AsyncPlayerPreLoginEvent for the same connection. - -Cancelling the AsyncPlayerPreLoginEvent guarantees the corresponding -PlayerConnectionCloseEvent is never called. - -The event may be invoked asynchronously or synchronously. As it stands, -it is never invoked asynchronously. However, plugins should check -Event#isAsynchronous to be future-proof. - -On purpose, the deprecated PlayerPreLoginEvent event is left out of the -API spec for this event. Plugins should not be using that event, and -how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent -is undefined. - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..12c1c6fe9dc8dc5f5faf6dcf99f6857219ef22b8 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java -@@ -0,0 +1,95 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import java.net.InetAddress; -+import java.util.UUID; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ *

    -+ * This event is invoked when a player has disconnected. It is guaranteed that, -+ * if the server is in online-mode, that the provided uuid and username have been -+ * validated. -+ *

    -+ * -+ *

    -+ * The event is invoked for players who have not yet logged into the world, whereas -+ * {@link org.bukkit.event.player.PlayerQuitEvent} is only invoked on players who have logged into the world. -+ *

    -+ * -+ *

    -+ * The event is invoked for players who have already logged into the world, -+ * although whether or not the player exists in the world at the time of -+ * firing is undefined. (That is, whether the plugin can retrieve a Player object -+ * using the event parameters is undefined). However, it is guaranteed that this -+ * event is invoked AFTER {@link org.bukkit.event.player.PlayerQuitEvent}, if the player has already logged into the world. -+ *

    -+ * -+ *

    -+ * This event is guaranteed to never fire unless {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} has -+ * been fired beforehand, and this event may not be called in parallel with -+ * {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} for the same connection. -+ *

    -+ * -+ *

    -+ * Cancelling the {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} guarantees the corresponding -+ * {@code PlayerConnectionCloseEvent} is never called. -+ *

    -+ * -+ *

    -+ * The event may be invoked asynchronously or synchronously. Plugins should check -+ * {@link Event#isAsynchronous()} and handle accordingly. -+ *

    -+ */ -+public class PlayerConnectionCloseEvent extends Event { -+ -+ private static final HandlerList HANDLERS = new HandlerList(); -+ -+ @NotNull private final UUID playerUniqueId; -+ @NotNull private final String playerName; -+ @NotNull private final InetAddress ipAddress; -+ -+ public PlayerConnectionCloseEvent(@NotNull final UUID playerUniqueId, @NotNull final String playerName, @NotNull final InetAddress ipAddress, final boolean async) { -+ super(async); -+ this.playerUniqueId = playerUniqueId; -+ this.playerName = playerName; -+ this.ipAddress = ipAddress; -+ } -+ -+ /** -+ * Returns the {@code UUID} of the player disconnecting. -+ */ -+ @NotNull -+ public UUID getPlayerUniqueId() { -+ return this.playerUniqueId; -+ } -+ -+ /** -+ * Returns the name of the player disconnecting. -+ */ -+ @NotNull -+ public String getPlayerName() { -+ return this.playerName; -+ } -+ -+ /** -+ * Returns the player's IP address. -+ */ -+ @NotNull -+ public InetAddress getIpAddress() { -+ return this.ipAddress; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLERS; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLERS; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/Unmapped-Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch deleted file mode 100644 index ec2b79af2d..0000000000 --- a/Unmapped-Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Jan 2019 00:31:12 -0600 -Subject: [PATCH] Add APIs to replace OfflinePlayer#getLastPlayed - -Currently OfflinePlayer#getLastPlayed could more accurately be described -as "OfflinePlayer#getLastTimeTheirDataWasSaved". - -The API doc says it should return the last time the server "witnessed" -the player, whilst also saying it should return the last time they -logged in. The current implementation does neither. - -Given this interesting contradiction in the API documentation and the -current defacto implementation, I've elected to deprecate (with no -intent to remove) and replace it with two new methods, clearly named and -documented as to their purpose. - -diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java -index 6cf05fed701c67a2c797a4e0839c795802a238a1..3afd5f5c0208a4ee93b5dbfc2aab2b9d2e8a7544 100644 ---- a/src/main/java/org/bukkit/OfflinePlayer.java -+++ b/src/main/java/org/bukkit/OfflinePlayer.java -@@ -147,7 +147,9 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio - * UTC. - * - * @return Date of last log-in for this player, or 0 -+ * @deprecated The API contract is ambiguous and the implementation may or may not return the correct value given this API ambiguity. It is instead recommended use {@link #getLastLogin()} or {@link #getLastSeen()} depending on your needs. - */ -+ @Deprecated - public long getLastPlayed(); - - /** -@@ -165,6 +167,30 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio - */ - @Nullable - public Location getBedSpawnLocation(); -+ // Paper start -+ /** -+ * Gets the last date and time that this player logged into the server. -+ *

    -+ * If the player has never played before, this will return 0. Otherwise, -+ * it will be the amount of milliseconds since midnight, January 1, 1970 -+ * UTC. -+ * -+ * @return last login time -+ */ -+ public long getLastLogin(); -+ -+ /** -+ * Gets the last date and time that this player was seen on the server. -+ *

    -+ * If the player has never played before, this will return 0. If the -+ * player is currently online, this will return the current time. -+ * Otherwise it will be the amount of milliseconds since midnight, -+ * January 1, 1970 UTC. -+ * -+ * @return last seen time -+ */ -+ public long getLastSeen(); -+ // Paper end - - /** - * Increments the given statistic for this player. diff --git a/Unmapped-Spigot-API-Patches/0168-BlockDestroyEvent.patch b/Unmapped-Spigot-API-Patches/0168-BlockDestroyEvent.patch deleted file mode 100644 index 4ad73d8ef1..0000000000 --- a/Unmapped-Spigot-API-Patches/0168-BlockDestroyEvent.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 Feb 2019 00:19:33 -0500 -Subject: [PATCH] BlockDestroyEvent - -Adds an event for when the server is going to destroy a current block, -potentially causing it to drop. This event can be cancelled to avoid -the block destruction, such as preventing signs from popping when -floating in the air. - -This can replace many uses of BlockPhysicsEvent - -diff --git a/src/main/java/com/destroystokyo/paper/event/block/BlockDestroyEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BlockDestroyEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..28255dc39eab5faf324d1fe556ab12daed527ff6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/block/BlockDestroyEvent.java -@@ -0,0 +1,92 @@ -+package com.destroystokyo.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.block.data.BlockData; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired anytime the server intends to 'destroy' a block through some triggering reason. -+ * This does not fire anytime a block is set to air, but only with more direct triggers such -+ * as physics updates, pistons, Entities changing blocks, commands set to "Destroy". -+ * -+ * This event is associated with the game playing a sound effect at the block in question, when -+ * something can be described as "intend to destroy what is there", -+ * -+ * Events such as leaves decaying, pistons retracting (where the block is moving), does NOT fire this event. -+ * -+ */ -+public class BlockDestroyEvent extends BlockEvent implements Cancellable { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull private final BlockData newState; -+ private final boolean willDrop; -+ private boolean playEffect = true; -+ -+ private boolean cancelled = false; -+ -+ public BlockDestroyEvent(@NotNull Block block, @NotNull BlockData newState, boolean willDrop) { -+ super(block); -+ this.newState = newState; -+ this.willDrop = willDrop; -+ } -+ -+ /** -+ * @return The new state of this block (Air, or a Fluid type) -+ */ -+ @NotNull -+ public BlockData getNewState() { -+ return newState; -+ } -+ -+ /** -+ * @return If the server is going to drop the block in question with this destroy event -+ */ -+ public boolean willDrop() { -+ return this.willDrop; -+ } -+ -+ /** -+ * @return If the server is going to play the sound effect for this destruction -+ */ -+ public boolean playEffect() { -+ return this.playEffect; -+ } -+ -+ /** -+ * @param playEffect If the server should play the sound effect for this destruction -+ */ -+ public void setPlayEffect(boolean playEffect) { -+ this.playEffect = playEffect; -+ } -+ -+ /** -+ * @return If the event is cancelled, meaning the block will not be destroyed -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * If the event is cancelled, the block will remain in its previous state. -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch b/Unmapped-Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch deleted file mode 100644 index 9b2dfc0c72..0000000000 --- a/Unmapped-Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 28 Jan 2014 19:13:57 -0500 -Subject: [PATCH] Add ItemStack Recipe API helper methods - -Allows using ExactChoice Recipes with easier methodss - -diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -index d742c4058ba9aed4fbe1591fd755a06608b06e98..222a12baa8e93ad686ab59426653f066d5876e38 100644 ---- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java -+++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -@@ -145,6 +145,13 @@ public class ShapedRecipe implements Recipe, Keyed { - return this; - } - -+ // Paper start -+ @NotNull -+ public ShapedRecipe setIngredient(char key, @NotNull ItemStack item) { -+ return setIngredient(key, new RecipeChoice.ExactChoice(item)); -+ } -+ // Paper end -+ - /** - * Get a copy of the ingredients map. - * -diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java -index 84062dd719cb8a6142dc8c806777cb208c6b42b2..7f6d3c71c5b3a9aa54c84a4c3b7c3614a0d477ce 100644 ---- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java -+++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java -@@ -143,6 +143,40 @@ public class ShapelessRecipe implements Recipe, Keyed { - return this; - } - -+ // Paper start -+ @NotNull -+ public ShapelessRecipe addIngredient(@NotNull ItemStack item) { -+ return addIngredient(item.getAmount(), item); -+ } -+ -+ @NotNull -+ public ShapelessRecipe addIngredient(int count, @NotNull ItemStack item) { -+ Validate.isTrue(ingredients.size() + count <= 9, "Shapeless recipes cannot have more than 9 ingredients"); -+ while (count-- > 0) { -+ ingredients.add(new RecipeChoice.ExactChoice(item)); -+ } -+ return this; -+ } -+ -+ @NotNull -+ public ShapelessRecipe removeIngredient(@NotNull ItemStack item) { -+ return removeIngredient(1, item); -+ } -+ -+ @NotNull -+ public ShapelessRecipe removeIngredient(int count, @NotNull ItemStack item) { -+ Iterator iterator = ingredients.iterator(); -+ while (count > 0 && iterator.hasNext()) { -+ ItemStack stack = iterator.next().getItemStack(); -+ if (stack.equals(item)) { -+ iterator.remove(); -+ count--; -+ } -+ } -+ return this; -+ } -+ // Paper end -+ - /** - * Removes an ingredient from the list. - * diff --git a/Unmapped-Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch b/Unmapped-Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch deleted file mode 100644 index 4bb54b5c92..0000000000 --- a/Unmapped-Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Wed, 13 Mar 2019 20:04:43 +0200 -Subject: [PATCH] Add WhitelistToggleEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/WhitelistToggleEvent.java b/src/main/java/com/destroystokyo/paper/event/server/WhitelistToggleEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fdd5eedb2b7401439912a3a4343a920f32edc860 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/WhitelistToggleEvent.java -@@ -0,0 +1,40 @@ -+package com.destroystokyo.paper.event.server; -+ -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * This event is fired when whitelist is toggled -+ * -+ * @author Mark Vainomaa -+ */ -+public class WhitelistToggleEvent extends Event { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ private boolean enabled; -+ -+ public WhitelistToggleEvent(boolean enabled) { -+ this.enabled = enabled; -+ } -+ -+ /** -+ * Gets whether whitelist is going to be enabled or not -+ * -+ * @return Whether whitelist is going to be enabled or not -+ */ -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0171-Annotation-Test-changes.patch b/Unmapped-Spigot-API-Patches/0171-Annotation-Test-changes.patch deleted file mode 100644 index 380b55d775..0000000000 --- a/Unmapped-Spigot-API-Patches/0171-Annotation-Test-changes.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 17 Mar 2019 23:04:30 +0000 -Subject: [PATCH] Annotation Test changes - - -diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index c62919f18f318fec15a6c364d8b6d562c2b04762..2bb75e967d4250476a151599b68de80011d222b2 100644 ---- a/src/test/java/org/bukkit/AnnotationTest.java -+++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -46,7 +46,17 @@ public class AnnotationTest { - "org/bukkit/util/io/Wrapper", - "org/bukkit/plugin/java/PluginClassLoader", - // Generic functional interface -- "org/bukkit/util/Consumer" -+ "org/bukkit/util/Consumer", -+ // Paper start -+ // Timings history is broken in terms of nullability due to guavas Function defining that the param is NonNull -+ "co/aikar/timings/TimingHistory$2", -+ "co/aikar/timings/TimingHistory$2$1", -+ "co/aikar/timings/TimingHistory$2$1$1", -+ "co/aikar/timings/TimingHistory$2$1$2", -+ "co/aikar/timings/TimingHistory$3", -+ "co/aikar/timings/TimingHistory$4", -+ "co/aikar/timings/TimingHistoryEntry$1" -+ // Paper end - }; - - @Test diff --git a/Unmapped-Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch b/Unmapped-Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch deleted file mode 100644 index 080a5c3186..0000000000 --- a/Unmapped-Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 00:21:23 -0400 -Subject: [PATCH] Entity#getEntitySpawnReason - -Allows you to return the SpawnReason for why an Entity Spawned - -Pre existing entities will return NATURAL if it was a non -persistenting Living Entity, SPAWNER for spawners, -or DEFAULT since data was not stored. - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 4b1f9b0ad5dc9ad6f33fddafc376b6f983a556ef..5b382091b1466b25ad42325d5808785a8e948552 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -708,5 +708,11 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - */ - @NotNull - Chunk getChunk(); -+ -+ /** -+ * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity. -+ */ -+ @NotNull -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason(); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0173-Add-GS4-Query-event.patch b/Unmapped-Spigot-API-Patches/0173-Add-GS4-Query-event.patch deleted file mode 100644 index ffab49a92a..0000000000 --- a/Unmapped-Spigot-API-Patches/0173-Add-GS4-Query-event.patch +++ /dev/null @@ -1,424 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 17 Mar 2019 21:46:27 +0200 -Subject: [PATCH] Add GS4 Query event - - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java b/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..77a19995f6792a182c5a43d6714e7bda0f42df5b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java -@@ -0,0 +1,412 @@ -+package com.destroystokyo.paper.event.server; -+ -+import com.google.common.base.Preconditions; -+import com.google.common.collect.ImmutableList; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+import java.net.InetAddress; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collection; -+import java.util.List; -+ -+/** -+ * This event is fired if server is getting queried over GS4 Query protocol -+ * -+ * Adapted from Velocity's ProxyQueryEvent -+ * -+ * @author Mark Vainomaa -+ */ -+public final class GS4QueryEvent extends Event { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ private final QueryType queryType; -+ private final InetAddress querierAddress; -+ private QueryResponse response; -+ -+ public GS4QueryEvent(@NotNull QueryType queryType, @NotNull InetAddress querierAddress, @NotNull QueryResponse response) { -+ super(true); // should always be called async -+ this.queryType = Preconditions.checkNotNull(queryType, "queryType"); -+ this.querierAddress = Preconditions.checkNotNull(querierAddress, "querierAddress"); -+ this.response = Preconditions.checkNotNull(response, "response"); -+ } -+ -+ /** -+ * Get query type -+ * @return query type -+ */ -+ @NotNull -+ public QueryType getQueryType() { -+ return queryType; -+ } -+ -+ /** -+ * Get querier address -+ * @return querier address -+ */ -+ @NotNull -+ public InetAddress getQuerierAddress() { -+ return querierAddress; -+ } -+ -+ /** -+ * Get query response -+ * @return query response -+ */ -+ @NotNull -+ public QueryResponse getResponse() { -+ return response; -+ } -+ -+ /** -+ * Set query response -+ * @param response query response -+ */ -+ public void setResponse(@NotNull QueryResponse response) { -+ this.response = Preconditions.checkNotNull(response, "response"); -+ } -+ -+ @Override -+ public String toString() { -+ return "GS4QueryEvent{" + -+ "queryType=" + queryType + -+ ", querierAddress=" + querierAddress + -+ ", response=" + response + -+ '}'; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ /** -+ * The type of query -+ */ -+ public enum QueryType { -+ /** -+ * Basic query asks only a subset of information, such as motd, game type (hardcoded to

    MINECRAFT
    ), map, -+ * current players, max players, server port and server motd -+ */ -+ BASIC, -+ -+ /** -+ * Full query asks pretty much everything present on this event (only hardcoded values cannot be modified here). -+ */ -+ FULL -+ ; -+ } -+ -+ public final static class QueryResponse { -+ private final String motd; -+ private final String gameVersion; -+ private final String map; -+ private final int currentPlayers; -+ private final int maxPlayers; -+ private final String hostname; -+ private final int port; -+ private final Collection players; -+ private final String serverVersion; -+ private final Collection plugins; -+ -+ private QueryResponse(String motd, String gameVersion, String map, int currentPlayers, int maxPlayers, String hostname, int port, Collection players, String serverVersion, Collection plugins) { -+ this.motd = motd; -+ this.gameVersion = gameVersion; -+ this.map = map; -+ this.currentPlayers = currentPlayers; -+ this.maxPlayers = maxPlayers; -+ this.hostname = hostname; -+ this.port = port; -+ this.players = players; -+ this.serverVersion = serverVersion; -+ this.plugins = plugins; -+ } -+ -+ /** -+ * Get motd which will be used to reply to the query. By default it is {@link org.bukkit.Server#getMotd()}. -+ * @return motd -+ */ -+ @NotNull -+ public String getMotd() { -+ return motd; -+ } -+ -+ /** -+ * Get game version which will be used to reply to the query. By default supported Minecraft versions range is sent. -+ * @return game version -+ */ -+ @NotNull -+ public String getGameVersion() { -+ return gameVersion; -+ } -+ -+ /** -+ * Get map name which will be used to reply to the query. By default {@code world} is sent. -+ * @return map name -+ */ -+ @NotNull -+ public String getMap() { -+ return map; -+ } -+ -+ /** -+ * Get current online player count which will be used to reply to the query. -+ * @return online player count -+ */ -+ public int getCurrentPlayers() { -+ return currentPlayers; -+ } -+ -+ /** -+ * Get max player count which will be used to reply to the query. -+ * @return max player count -+ */ -+ public int getMaxPlayers() { -+ return maxPlayers; -+ } -+ -+ /** -+ * Get server (public facing) hostname -+ * @return server hostname -+ */ -+ @NotNull -+ public String getHostname() { -+ return hostname; -+ } -+ -+ /** -+ * Get server (public facing) port -+ * @return server port -+ */ -+ public int getPort() { -+ return port; -+ } -+ -+ /** -+ * Get collection of players which will be used to reply to the query. -+ * @return collection of players -+ */ -+ @NotNull -+ public Collection getPlayers() { -+ return players; -+ } -+ -+ /** -+ * Get server software (name and version) which will be used to reply to the query. -+ * @return server software -+ */ -+ @NotNull -+ public String getServerVersion() { -+ return serverVersion; -+ } -+ -+ /** -+ * Get list of plugins which will be used to reply to the query. -+ * @return collection of plugins -+ */ -+ @NotNull -+ public Collection getPlugins() { -+ return plugins; -+ } -+ -+ -+ /** -+ * Creates a new {@link Builder} instance from data represented by this response -+ * @return {@link QueryResponse} builder -+ */ -+ @NotNull -+ public Builder toBuilder() { -+ return QueryResponse.builder() -+ .motd(getMotd()) -+ .gameVersion(getGameVersion()) -+ .map(getMap()) -+ .currentPlayers(getCurrentPlayers()) -+ .maxPlayers(getMaxPlayers()) -+ .hostname(getHostname()) -+ .port(getPort()) -+ .players(getPlayers()) -+ .serverVersion(getServerVersion()) -+ .plugins(getPlugins()); -+ } -+ -+ /** -+ * Creates a new {@link Builder} instance -+ * @return {@link QueryResponse} builder -+ */ -+ @NotNull -+ public static Builder builder() { -+ return new Builder(); -+ } -+ -+ /** -+ * A builder for {@link QueryResponse} objects. -+ */ -+ public static final class Builder { -+ private String motd; -+ private String gameVersion; -+ private String map; -+ private String hostname; -+ private String serverVersion; -+ -+ private int currentPlayers; -+ private int maxPlayers; -+ private int port; -+ -+ private List players = new ArrayList<>(); -+ private List plugins = new ArrayList<>(); -+ -+ private Builder() {} -+ -+ @NotNull -+ public Builder motd(@NotNull String motd) { -+ this.motd = Preconditions.checkNotNull(motd, "motd"); -+ return this; -+ } -+ -+ @NotNull -+ public Builder gameVersion(@NotNull String gameVersion) { -+ this.gameVersion = Preconditions.checkNotNull(gameVersion, "gameVersion"); -+ return this; -+ } -+ -+ @NotNull -+ public Builder map(@NotNull String map) { -+ this.map = Preconditions.checkNotNull(map, "map"); -+ return this; -+ } -+ -+ @NotNull -+ public Builder currentPlayers(int currentPlayers) { -+ Preconditions.checkArgument(currentPlayers >= 0, "currentPlayers cannot be negative"); -+ this.currentPlayers = currentPlayers; -+ return this; -+ } -+ -+ @NotNull -+ public Builder maxPlayers(int maxPlayers) { -+ Preconditions.checkArgument(maxPlayers >= 0, "maxPlayers cannot be negative"); -+ this.maxPlayers = maxPlayers; -+ return this; -+ } -+ -+ @NotNull -+ public Builder hostname(@NotNull String hostname) { -+ this.hostname = Preconditions.checkNotNull(hostname, "hostname"); -+ return this; -+ } -+ -+ @NotNull -+ public Builder port(int port) { -+ Preconditions.checkArgument(port >= 1 && port <= 65535, "port must be between 1-65535"); -+ this.port = port; -+ return this; -+ } -+ -+ @NotNull -+ public Builder players(@NotNull Collection players) { -+ this.players.addAll(Preconditions.checkNotNull(players, "players")); -+ return this; -+ } -+ -+ @NotNull -+ public Builder players(@NotNull String... players) { -+ this.players.addAll(Arrays.asList(Preconditions.checkNotNull(players, "players"))); -+ return this; -+ } -+ -+ @NotNull -+ public Builder clearPlayers() { -+ this.players.clear(); -+ return this; -+ } -+ -+ @NotNull -+ public Builder serverVersion(@NotNull String serverVersion) { -+ this.serverVersion = Preconditions.checkNotNull(serverVersion, "serverVersion"); -+ return this; -+ } -+ -+ @NotNull -+ public Builder plugins(@NotNull Collection plugins) { -+ this.plugins.addAll(Preconditions.checkNotNull(plugins, "plugins")); -+ return this; -+ } -+ -+ @NotNull -+ public Builder plugins(@NotNull PluginInformation... plugins) { -+ this.plugins.addAll(Arrays.asList(Preconditions.checkNotNull(plugins, "plugins"))); -+ return this; -+ } -+ -+ @NotNull -+ public Builder clearPlugins() { -+ this.plugins.clear(); -+ return this; -+ } -+ -+ /** -+ * Builds new {@link QueryResponse} with supplied data -+ * @return response -+ */ -+ @NotNull -+ public QueryResponse build() { -+ return new QueryResponse( -+ Preconditions.checkNotNull(motd, "motd"), -+ Preconditions.checkNotNull(gameVersion, "gameVersion"), -+ Preconditions.checkNotNull(map, "map"), -+ currentPlayers, -+ maxPlayers, -+ Preconditions.checkNotNull(hostname, "hostname"), -+ port, -+ ImmutableList.copyOf(players), -+ Preconditions.checkNotNull(serverVersion, "serverVersion"), -+ ImmutableList.copyOf(plugins) -+ ); -+ } -+ } -+ -+ /** -+ * Plugin information -+ */ -+ public static class PluginInformation { -+ private String name; -+ private String version; -+ -+ public PluginInformation(@NotNull String name, @NotNull String version) { -+ this.name = Preconditions.checkNotNull(name, "name"); -+ this.version = Preconditions.checkNotNull(version, "version"); -+ } -+ -+ @NotNull -+ public String getName() { -+ return name; -+ } -+ -+ public void setName(@NotNull String name) { -+ this.name = name; -+ } -+ -+ public void setVersion(@NotNull String version) { -+ this.version = version; -+ } -+ -+ @NotNull -+ public String getVersion() { -+ return version; -+ } -+ -+ @NotNull -+ public static PluginInformation of(@NotNull String name, @NotNull String version) { -+ return new PluginInformation(name, version); -+ } -+ } -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch b/Unmapped-Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch deleted file mode 100644 index 2eb0647eac..0000000000 --- a/Unmapped-Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterVector -Date: Fri, 26 Oct 2018 21:33:13 -0700 -Subject: [PATCH] Add PlayerPostRespawnEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..31f34b54801f6699ce43355fa2a0a51f1ad0c997 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java -@@ -0,0 +1,52 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired after a player has respawned -+ */ -+public class PlayerPostRespawnEvent extends PlayerEvent { -+ private final static HandlerList handlers = new HandlerList(); -+ private final Location respawnedLocation; -+ private final boolean isBedSpawn; -+ -+ public PlayerPostRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnedLocation, final boolean isBedSpawn) { -+ super(respawnPlayer); -+ this.respawnedLocation = respawnedLocation; -+ this.isBedSpawn = isBedSpawn; -+ } -+ -+ /** -+ * Returns the location of the respawned player -+ * -+ * @return location of the respawned player -+ */ -+ @NotNull -+ public Location getRespawnedLocation() { -+ return respawnedLocation.clone(); -+ } -+ -+ /** -+ * Checks if the player respawned to their bed -+ * -+ * @return whether the player respawned to their bed -+ */ -+ public boolean isBedSpawn() { -+ return isBedSpawn; -+ } -+ -+ @Override -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch b/Unmapped-Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch deleted file mode 100644 index 28d9857af0..0000000000 --- a/Unmapped-Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 18:44:26 -0400 -Subject: [PATCH] Ignore package-private methods for nullability annotations - -This isn't API - -diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 2bb75e967d4250476a151599b68de80011d222b2..03229d5f4ec36a82197beb391356d791ff67fb2f 100644 ---- a/src/test/java/org/bukkit/AnnotationTest.java -+++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -168,7 +168,7 @@ public class AnnotationTest { - - private static boolean isMethodIncluded(@NotNull ClassNode clazz, @NotNull MethodNode method, @NotNull Map allClasses) { - // Exclude private, synthetic and deprecated methods -- if ((method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED)) != 0) { -+ if ((method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED)) != 0 || (method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) == 0) { // Paper - ignore package-private - return false; - } - diff --git a/Unmapped-Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch b/Unmapped-Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch deleted file mode 100644 index 44f9bcdbe3..0000000000 --- a/Unmapped-Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 18:39:01 -0400 -Subject: [PATCH] Flip some Spigot API null annotations - -while some of these may of been true, they are extreme cases and cause -a ton of noise to plugin developers. - -These do not help plugin developers if they bring moise noise than value. - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index dcaefdaf5a0de8486f59115c8c4d4c211b7d64cd..e3304fcc8c4fd176abd3fb7d4b47e5ccb7bdd37f 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1389,7 +1389,7 @@ public final class Bukkit { - * - * @return the scoreboard manager or null if no worlds are loaded. - */ -- @Nullable -+ @NotNull // Paper - public static ScoreboardManager getScoreboardManager() { - return server.getScoreboardManager(); - } -@@ -1686,7 +1686,7 @@ public final class Bukkit { - * @param clazz the class of the tag entries - * @return the tag or null - */ -- @Nullable -+ @UndefinedNullability // Paper - public static Tag getTag(@NotNull String registry, @NotNull NamespacedKey tag, @NotNull Class clazz) { - return server.getTag(registry, tag, clazz); - } -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index 9c91c49ed7302c12fcb1d8e9bc58712efc199954..d5d67b3d84cd88ed0f858497e68535ec0162c700 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -46,7 +46,7 @@ public class Location implements Cloneable, ConfigurationSerializable { - * @param y The y-coordinate of this new location - * @param z The z-coordinate of this new location - */ -- public Location(@Nullable final World world, final double x, final double y, final double z) { -+ public Location(@UndefinedNullability final World world, final double x, final double y, final double z) { // Paper - this(world, x, y, z, 0, 0); - } - -@@ -60,7 +60,7 @@ public class Location implements Cloneable, ConfigurationSerializable { - * @param yaw The absolute rotation on the x-plane, in degrees - * @param pitch The absolute rotation on the y-plane, in degrees - */ -- public Location(@Nullable final World world, final double x, final double y, final double z, final float yaw, final float pitch) { -+ public Location(@UndefinedNullability final World world, final double x, final double y, final double z, final float yaw, final float pitch) { - if (world != null) { - this.world = new WeakReference<>(world); - } -@@ -102,7 +102,7 @@ public class Location implements Cloneable, ConfigurationSerializable { - * @throws IllegalArgumentException when world is unloaded - * @see #isWorldLoaded() - */ -- @Nullable -+ @UndefinedNullability - public World getWorld() { - if (this.world == null) { - return null; -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 9b8e6b7bbbed44e2659379c8046acaa35aaa8910..989a732e5ef2053deede245d65fbf99cdf117c5e 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1171,7 +1171,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * - * @return the scoreboard manager or null if no worlds are loaded. - */ -- @Nullable -+ @NotNull // Paper - ScoreboardManager getScoreboardManager(); - - /** -@@ -1441,7 +1441,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @param clazz the class of the tag entries - * @return the tag or null - */ -- @Nullable -+ @UndefinedNullability - Tag getTag(@NotNull String registry, @NotNull NamespacedKey tag, @NotNull Class clazz); - - /** -diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index 591e095dabd4cb72881abf206b1d7f0c8818cef3..ecf509a970ed4f0052d5d2c756406bf96052a680 100644 ---- a/src/main/java/org/bukkit/inventory/ItemFactory.java -+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java -@@ -3,6 +3,7 @@ package org.bukkit.inventory; - import org.bukkit.Color; - import org.bukkit.Material; - import org.bukkit.Server; -+import org.bukkit.UndefinedNullability; - import org.bukkit.inventory.meta.BookMeta; - import org.bukkit.inventory.meta.ItemMeta; - import org.bukkit.inventory.meta.SkullMeta; -@@ -25,7 +26,7 @@ public interface ItemFactory { - * @return a new ItemMeta that could be applied to an item stack of the - * specified material - */ -- @Nullable -+ @UndefinedNullability // Paper - ItemMeta getItemMeta(@NotNull final Material material); - - /** -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 686e2a0b9fe061816b41435ef2337870dbdca8e5..290c3f0fd6e8c3407d421b697e0ee01584f4cebd 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -8,6 +8,7 @@ import java.util.Set; // Paper - import org.apache.commons.lang.Validate; - import org.bukkit.Bukkit; - import org.bukkit.Material; -+import org.bukkit.UndefinedNullability; - import org.bukkit.Utility; - import org.bukkit.configuration.serialization.ConfigurationSerializable; - import org.bukkit.enchantments.Enchantment; -@@ -546,7 +547,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - * - * @return a copy of the current ItemStack's ItemData - */ -- @Nullable -+ @UndefinedNullability // Paper - public ItemMeta getItemMeta() { - return this.meta == null ? Bukkit.getItemFactory().getItemMeta(this.type) : this.meta.clone(); - } diff --git a/Unmapped-Spigot-API-Patches/0177-Server-Tick-Events.patch b/Unmapped-Spigot-API-Patches/0177-Server-Tick-Events.patch deleted file mode 100644 index 9cb8b9a4c0..0000000000 --- a/Unmapped-Spigot-API-Patches/0177-Server-Tick-Events.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Mar 2019 21:58:55 -0400 -Subject: [PATCH] Server Tick Events - -Fires event at start and end of a server tick - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerTickEndEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerTickEndEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9fd28e03649f66f71fb7f0536a137557ec32cd25 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/ServerTickEndEvent.java -@@ -0,0 +1,59 @@ -+package com.destroystokyo.paper.event.server; -+ -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when the server has finished ticking the main loop -+ */ -+public class ServerTickEndEvent extends Event { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private final int tickNumber; -+ private final double tickDuration; -+ private final long timeEnd; -+ -+ public ServerTickEndEvent(int tickNumber, double tickDuration, long timeRemaining) { -+ this.tickNumber = tickNumber; -+ this.tickDuration = tickDuration; -+ this.timeEnd = System.nanoTime() + timeRemaining; -+ } -+ -+ /** -+ * @return What tick this was since start (first tick = 1) -+ */ -+ public int getTickNumber() { -+ return tickNumber; -+ } -+ -+ /** -+ * @return Time in milliseconds of how long this tick took -+ */ -+ public double getTickDuration() { -+ return tickDuration; -+ } -+ -+ /** -+ * Amount of nanoseconds remaining before the next tick should start. -+ * -+ * If this value is negative, then that means the server has exceeded the tick time limit and TPS has been lost. -+ * -+ * Method will continously return the updated time remaining value. (return value is not static) -+ * -+ * @return Amount of nanoseconds remaining before the next tick should start -+ */ -+ public long getTimeRemaining() { -+ return this.timeEnd - System.nanoTime(); -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerTickStartEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerTickStartEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..eac85f1f49088bb71afb01eff4d5f53887306461 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/ServerTickStartEvent.java -@@ -0,0 +1,32 @@ -+package com.destroystokyo.paper.event.server; -+ -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+public class ServerTickStartEvent extends Event { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private final int tickNumber; -+ -+ public ServerTickStartEvent(int tickNumber) { -+ this.tickNumber = tickNumber; -+ } -+ -+ /** -+ * @return What tick this is going be since start (first tick = 1) -+ */ -+ public int getTickNumber() { -+ return tickNumber; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch b/Unmapped-Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch deleted file mode 100644 index e41136bc7f..0000000000 --- a/Unmapped-Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 11 Mar 2013 20:04:34 -0400 -Subject: [PATCH] PlayerDeathEvent#getItemsToKeep - -Exposes a mutable array on items a player should keep on death - -Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4 - -diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -index a01d4c21bedc7f1a54f5a330bb4c2909ce3a18e4..8c46eaebf004823c1c31eb2c7304181487cb1332 100644 ---- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -+++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -@@ -36,7 +36,6 @@ public class PlayerDeathEvent extends EntityDeathEvent { - } - // Paper end - -- @Deprecated // Paper - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final String deathMessage) { - this(player, drops, droppedExp, 0, deathMessage); - } -@@ -56,6 +55,41 @@ public class PlayerDeathEvent extends EntityDeathEvent { - this.adventure$deathMessage = deathMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(deathMessage) : net.kyori.adventure.text.Component.empty(); // Paper - } - -+ @Deprecated // Paper -+ // Paper start -+ private List itemsToKeep = new java.util.ArrayList<>(); -+ -+ /** -+ * A mutable collection to add items that the player should retain in their inventory on death (Similar to KeepInventory game rule) -+ * -+ * You MUST remove the item from the .getDrops() collection too or it will duplicate! -+ *
    {@code
    -+     *    {@literal @EventHandler(ignoreCancelled = true)}
    -+     *     public void onPlayerDeath(PlayerDeathEvent event) {
    -+     *         for (Iterator iterator = event.getDrops().iterator(); iterator.hasNext(); ) {
    -+     *             ItemStack drop = iterator.next();
    -+     *             List lore = drop.getLore();
    -+     *             if (lore != null && !lore.isEmpty()) {
    -+     *                 if (lore.get(0).contains("(SOULBOUND)")) {
    -+     *                     iterator.remove();
    -+     *                     event.getItemsToKeep().add(drop);
    -+     *                 }
    -+     *             }
    -+     *         }
    -+     *     }
    -+     * }
    -+ * -+ * Adding an item to this list that the player did not previously have will give them the item on death. -+ * An example case could be a "Note" that "You died at X/Y/Z coordinates" -+ * -+ * @return The list to hold items to keep -+ */ -+ @NotNull -+ public List getItemsToKeep() { -+ return itemsToKeep; -+ } -+ // Paper end -+ - @NotNull - @Override - public Player getEntity() { diff --git a/Unmapped-Spigot-API-Patches/0179-Add-Heightmap-API.patch b/Unmapped-Spigot-API-Patches/0179-Add-Heightmap-API.patch deleted file mode 100644 index 73e1e8d46f..0000000000 --- a/Unmapped-Spigot-API-Patches/0179-Add-Heightmap-API.patch +++ /dev/null @@ -1,196 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 1 Dec 2018 19:00:36 -0800 -Subject: [PATCH] Add Heightmap API - -Changed to use upstream's heightmap API - Machine_Maker - -diff --git a/src/main/java/com/destroystokyo/paper/HeightmapType.java b/src/main/java/com/destroystokyo/paper/HeightmapType.java -new file mode 100644 -index 0000000000000000000000000000000000000000..709e44ea1b14ab6917501c928e689cc6cbdf4bb4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/HeightmapType.java -@@ -0,0 +1,39 @@ -+package com.destroystokyo.paper; -+ -+import org.bukkit.*; -+ -+/** -+ * Enumeration of different heightmap types maintained by the server. Generally using these maps is much faster -+ * than using an iterative search for a block in a given x, z coordinate. -+ * -+ * @deprecated Upstream has added their own API for using the game heightmaps. See {@link org.bukkit.HeightMap} and the -+ * non-deprecated getHighestBlock methods on World such as {@link org.bukkit.World#getHighestBlockAt(Location, HeightMap)}. -+ */ -+@Deprecated -+public enum HeightmapType { -+ -+ /** -+ * The highest block used for lighting in the world. Also the block returned by {@link World#getHighestBlockYAt(int, int)}} -+ */ -+ LIGHT_BLOCKING, -+ -+ /** -+ * References the highest block in the world. -+ */ -+ ANY, -+ -+ /** -+ * References the highest solid block in a world. -+ */ -+ SOLID, -+ -+ /** -+ * References the highest solid or liquid block in a world. -+ */ -+ SOLID_OR_LIQUID, -+ -+ /** -+ * References the highest solid or liquid block in a world, excluding leaves. -+ */ -+ SOLID_OR_LIQUID_NO_LEAVES; -+} -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index d5d67b3d84cd88ed0f858497e68535ec0162c700..432d5711b7ec34eafeb27df82d367612dfe1fe54 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -638,6 +638,47 @@ public class Location implements Cloneable, ConfigurationSerializable { - return centerLoc; - } - -+ // Paper start - Add heightmap api -+ -+ /** -+ * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ()) -+ * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ()) -+ * @throws NullPointerException if {{@link #getWorld()}} is {@code null} -+ */ -+ @NotNull -+ public Location toHighestLocation() { -+ return this.toHighestLocation(HeightMap.WORLD_SURFACE); -+ } -+ -+ /** -+ * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightmap) -+ * @param heightmap The heightmap to use for finding the highest y location. -+ * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightmap) -+ * @throws NullPointerException if {{@link #getWorld()}} is {@code null} -+ * @throws UnsupportedOperationException if {@link World#getHighestBlockYAt(int, int, com.destroystokyo.paper.HeightmapType)} does not support the specified heightmap -+ * @deprecated Use {@link org.bukkit.Location#toHighestLocation(HeightMap)} -+ */ -+ @NotNull -+ @Deprecated -+ public Location toHighestLocation(@NotNull final com.destroystokyo.paper.HeightmapType heightmap) { -+ final Location ret = this.clone(); -+ ret.setY(this.getWorld().getHighestBlockYAt(this, heightmap)); -+ return ret; -+ } -+ -+ /** -+ * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightMap) -+ * @param heightMap The heightmap to use for finding the highest y location. -+ * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightMap) -+ */ -+ @NotNull -+ public Location toHighestLocation(@NotNull final HeightMap heightMap) { -+ final Location ret = this.clone(); -+ ret.setY(this.getWorld().getHighestBlockYAt(this, heightMap)); -+ return ret; -+ } -+ // Paper end -+ - /** - * Creates explosion at this location with given power - * -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 19060c7d9c74b9b2808103f3d5627444aece6ccb..f8e104d5e61e52c5fe658d7cda373f62424c7bea 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -160,6 +160,87 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @NotNull - public Block getHighestBlockAt(@NotNull Location location); - -+ // Paper start - Add heightmap API -+ /** -+ * Returns the highest block's y-coordinate at the specified block coordinates that match the specified heightmap's conditions. -+ *

    -+ * implNote: Implementations are recommended to use an iterative search as a fallback before resorting to -+ * throwing an {@code UnsupportedOperationException}. -+ *

    -+ * -+ * @param x The block's x-coordinate. -+ * @param z The block's z-coordinate. -+ * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType} -+ * @return The highest block's y-coordinate at (x, z) that matches the specified heightmap's conditions. -+ * @throws UnsupportedOperationException If the heightmap type is not supported. -+ * @deprecated Upstream has added support for this, use {@link World#getHighestBlockYAt(int, int, HeightMap)} -+ * -+ * @see com.destroystokyo.paper.HeightmapType -+ */ -+ @Deprecated -+ public int getHighestBlockYAt(int x, int z, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException; -+ -+ /** -+ * Returns the highest block's y-coordinate at the specified block coordinates that match the specified heightmap's conditions. -+ * Note that the y-coordinate of the specified location is ignored. -+ *

    -+ * implNote: Implementations are recommended to use an iterative search as a fallback before resorting to -+ * throwing an {@code UnsupportedOperationException}. -+ *

    -+ * -+ * @param location The specified block coordinates. -+ * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType} -+ * @return The highest block's y-coordinate at {@code location} that matches the specified heightmap's conditions. -+ * @throws UnsupportedOperationException If the heightmap type is not supported. -+ * @deprecated Upstream has added support for this, use {@link World#getHighestBlockYAt(Location, HeightMap)} -+ * @see com.destroystokyo.paper.HeightmapType -+ */ -+ @Deprecated -+ default int getHighestBlockYAt(@NotNull Location location, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { -+ return this.getHighestBlockYAt(location.getBlockX(), location.getBlockZ(), heightmap); -+ } -+ -+ /** -+ * Returns the highest {@link Block} at the specified block coordinates that match the specified heightmap's conditions. -+ *

    -+ * implNote: Implementations are recommended to use an iterative search as a fallback before resorting to -+ * throwing an {@code UnsupportedOperationException}. -+ *

    -+ * @param x The block's x-coordinate. -+ * @param z The block's z-coordinate. -+ * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType} -+ * @return The highest {@link Block} at (x, z) that matches the specified heightmap's conditions. -+ * @throws UnsupportedOperationException If the heightmap type is not supported. -+ * @deprecated Upstream has added support for this, use {@link World#getHighestBlockAt(int, int, HeightMap)} -+ * @see com.destroystokyo.paper.HeightmapType -+ */ -+ @Deprecated -+ @NotNull -+ default Block getHighestBlockAt(int x, int z, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { -+ return this.getBlockAt(x, this.getHighestBlockYAt(x, z, heightmap), z); -+ } -+ -+ /** -+ * Returns the highest {@link Block} at the specified block coordinates that match the specified heightmap's conditions. -+ * Note that the y-coordinate of the specified location is ignored. -+ *

    -+ * implNote: Implementations are recommended to use an iterative search as a fallback before resorting to -+ * throwing an {@code UnsupportedOperationException}. -+ *

    -+ * @param location The specified block coordinates. -+ * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType} -+ * @return The highest {@link Block} at {@code location} that matches the specified heightmap's conditions. -+ * @throws UnsupportedOperationException If the heightmap type is not supported. -+ * @deprecated Upstream has added support for this, use {@link World#getHighestBlockAt(Location, HeightMap)} -+ * @see com.destroystokyo.paper.HeightmapType -+ */ -+ @Deprecated -+ @NotNull -+ default Block getHighestBlockAt(@NotNull Location location, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { -+ return this.getHighestBlockAt(location.getBlockX(), location.getBlockZ(), heightmap); -+ } -+ // Paper end -+ - /** - * Gets the highest coordinate corresponding to the {@link HeightMap} at the - * given coordinates. diff --git a/Unmapped-Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch b/Unmapped-Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch deleted file mode 100644 index 2bbe92cbe9..0000000000 --- a/Unmapped-Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -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 cb447a4ad5a9dce7c98999a5d7fcd6111fc9b10e..5bbae759ce39d42886994e500fd9454ec328f804 100644 ---- a/src/main/java/org/bukkit/block/CreatureSpawner.java -+++ b/src/main/java/org/bukkit/block/CreatureSpawner.java -@@ -199,4 +199,30 @@ public interface CreatureSpawner extends TileState { - * @see #getSpawnRange() - */ - public void setSpawnRange(int spawnRange); -+ -+ // Paper start -+ /** -+ * Check if spawner is activated (a player is close enough) -+ * -+ * @return True if a player is close enough to activate it -+ */ -+ public boolean isActivated(); -+ -+ /** -+ * Resets the spawn delay timer within the min/max range -+ */ -+ public void resetTimer(); -+ -+ /** -+ * Sets the {@link EntityType} to {@link EntityType#DROPPED_ITEM} and sets the data to the given -+ * {@link org.bukkit.inventory.ItemStack ItemStack}. -+ *

    -+ * {@link #setSpawnCount(int)} does not dictate the amount of items in the stack spawned, but rather how many -+ * stacks should be spawned. -+ * -+ * @param itemStack The item to spawn. Must not {@link org.bukkit.Material#isAir be air}. -+ * @see #setSpawnedType(EntityType) -+ */ -+ void setSpawnedItem(@NotNull org.bukkit.inventory.ItemStack itemStack); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch b/Unmapped-Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch deleted file mode 100644 index 428810f1d8..0000000000 --- a/Unmapped-Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: simpleauthority -Date: Tue, 28 May 2019 03:41:28 -0700 -Subject: [PATCH] Add BlockSoundGroup interface - -This PR adds the getSoundGroup() method in Block which returns a BlockSoundGroup - -diff --git a/src/main/java/com/destroystokyo/paper/block/BlockSoundGroup.java b/src/main/java/com/destroystokyo/paper/block/BlockSoundGroup.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8cf87d228a7006658d52ce0da16c2d74f4706545 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/block/BlockSoundGroup.java -@@ -0,0 +1,52 @@ -+package com.destroystokyo.paper.block; -+ -+import org.bukkit.Sound; -+import org.bukkit.block.Block; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents the sounds that a {@link Block} makes in certain situations -+ *

    -+ * The sound group includes break, step, place, hit, and fall sounds. -+ */ -+public interface BlockSoundGroup { -+ /** -+ * Gets the sound that plays when breaking this block -+ * -+ * @return The break sound -+ */ -+ @NotNull -+ Sound getBreakSound(); -+ -+ /** -+ * Gets the sound that plays when stepping on this block -+ * -+ * @return The step sound -+ */ -+ @NotNull -+ Sound getStepSound(); -+ -+ /** -+ * Gets the sound that plays when placing this block -+ * -+ * @return The place sound -+ */ -+ @NotNull -+ Sound getPlaceSound(); -+ -+ /** -+ * Gets the sound that plays when hitting this block -+ * -+ * @return The hit sound -+ */ -+ @NotNull -+ Sound getHitSound(); -+ -+ /** -+ * Gets the sound that plays when this block falls -+ * -+ * @return The fall sound -+ */ -+ @NotNull -+ Sound getFallSound(); -+} -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index b090938f883c486e703cb7c036c47925f3016704..5e2aa4fb8cf8130df21d3172dd94e857317f7653 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -1,6 +1,7 @@ - package org.bukkit.block; - - import java.util.Collection; -+ - import org.bukkit.Chunk; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -560,4 +561,16 @@ public interface Block extends Metadatable { - */ - @NotNull - BoundingBox getBoundingBox(); -+ -+ // Paper start -+ /** -+ * Gets the {@link com.destroystokyo.paper.block.BlockSoundGroup} for this block. -+ *

    -+ * This object contains the block, step, place, hit, and fall sounds. -+ * -+ * @return the sound group for this block -+ */ -+ @NotNull -+ com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup(); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch b/Unmapped-Spigot-API-Patches/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch deleted file mode 100644 index b5148c5574..0000000000 --- a/Unmapped-Spigot-API-Patches/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: simpleauthority -Date: Thu, 11 Jul 2019 10:35:56 -0700 -Subject: [PATCH] Amend PlayerInteractAtEntityEvent javadoc for ArmorStands - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerInteractAtEntityEvent.java b/src/main/java/org/bukkit/event/player/PlayerInteractAtEntityEvent.java -index 1075dbb8135d2fd2fd69d1e821dd1ba7f90824d5..3f24d302e28170f7f6e5885b5b9abb22cbbb7d66 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerInteractAtEntityEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerInteractAtEntityEvent.java -@@ -13,6 +13,9 @@ import org.jetbrains.annotations.NotNull; - *
    - * Note that the client may sometimes spuriously send this packet in addition to {@link PlayerInteractEntityEvent}. - * Users are advised to listen to this (parent) class unless specifically required. -+ *
    -+ * Note that interacting with Armor Stands fires this event only and not its parent and as such users are expressly required -+ * to listen to this event for that scenario. - */ - public class PlayerInteractAtEntityEvent extends PlayerInteractEntityEvent { - private static final HandlerList handlers = new HandlerList(); diff --git a/Unmapped-Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch b/Unmapped-Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch deleted file mode 100644 index 24aacd2b29..0000000000 --- a/Unmapped-Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Fri, 18 Oct 2019 17:39:05 +0100 -Subject: [PATCH] Increase custom payload channel message size - -Doubles the custom payload size limit imposed by bukkit, also creates a system -property to allow customizing the size `paper.maxCustomChannelName` - -diff --git a/src/main/java/org/bukkit/plugin/messaging/Messenger.java b/src/main/java/org/bukkit/plugin/messaging/Messenger.java -index 9d2c68c826f3b867d407e7f13c6394a899cc8ee8..682c77188436d696d4dafbc70cf131d5c921e94d 100644 ---- a/src/main/java/org/bukkit/plugin/messaging/Messenger.java -+++ b/src/main/java/org/bukkit/plugin/messaging/Messenger.java -@@ -24,7 +24,7 @@ public interface Messenger { - /** - * Represents the largest size that a Plugin Channel may be. - */ -- public static final int MAX_CHANNEL_SIZE = 64; -+ public static final int MAX_CHANNEL_SIZE = Integer.getInteger("paper.maxCustomChannelName", 64); // Paper - - /** - * Checks if the specified channel is a reserved name. diff --git a/Unmapped-Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch b/Unmapped-Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch deleted file mode 100644 index b127872bfe..0000000000 --- a/Unmapped-Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 20 Apr 2019 19:47:29 -0500 -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 e3304fcc8c4fd176abd3fb7d4b47e5ccb7bdd37f..49bf621a2c0e5e9641b334a42b2769944c991d5d 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1835,6 +1835,10 @@ public final class Bukkit { - public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { - return server.createProfile(uuid, name); - } -+ -+ public static int getCurrentTick() { -+ return server.getCurrentTick(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 989a732e5ef2053deede245d65fbf99cdf117c5e..e448ae78304974f7664b7ef18568a547833ece9f 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1609,5 +1609,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - */ - @NotNull - com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name); -+ -+ /** -+ * Get the current internal server tick -+ * -+ * @return Current tick -+ */ -+ int getCurrentTick(); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch b/Unmapped-Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch deleted file mode 100644 index f19bdcd569..0000000000 --- a/Unmapped-Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 24 Dec 2019 00:35:31 +0000 -Subject: [PATCH] PlayerDeathEvent#shouldDropExperience - - -diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -index 7b78afe9281681cb9262fa044c1069a6121358eb..46917615ac4734bf5fa4ddea497132466eb5cc35 100644 ---- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -+++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -@@ -1,6 +1,8 @@ - package org.bukkit.event.entity; - - import java.util.List; -+ -+import org.bukkit.GameMode; - import org.bukkit.entity.Player; - import org.bukkit.inventory.ItemStack; - import org.jetbrains.annotations.NotNull; -@@ -18,6 +20,8 @@ public class PlayerDeathEvent extends EntityDeathEvent { - private boolean keepLevel = false; - private boolean keepInventory = false; - // Paper start -+ private boolean doExpDrop; -+ - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage) { - this(player, drops, droppedExp, 0, adventure$deathMessage, null); - } -@@ -27,12 +31,17 @@ public class PlayerDeathEvent extends EntityDeathEvent { - } - - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage) { -+ this(player, drops, droppedExp, newExp, newTotalExp, newLevel, adventure$deathMessage, deathMessage, true); -+ } -+ -+ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage, boolean doExpDrop) { - super(player, drops, droppedExp); - this.newExp = newExp; - this.newTotalExp = newTotalExp; - this.newLevel = newLevel; - this.deathMessage = deathMessage; - this.adventure$deathMessage = adventure$deathMessage; -+ this.doExpDrop = doExpDrop; - } - // Paper end - -@@ -47,6 +56,11 @@ public class PlayerDeathEvent extends EntityDeathEvent { - - @Deprecated // Paper - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final String deathMessage) { -+ this(player, drops, droppedExp, newExp, newTotalExp, newLevel, deathMessage, true); -+ } -+ -+ @Deprecated // Paper -+ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final String deathMessage, boolean doExpDrop) { - super(player, drops, droppedExp); - this.newExp = newExp; - this.newTotalExp = newTotalExp; -@@ -88,6 +102,20 @@ public class PlayerDeathEvent extends EntityDeathEvent { - public List getItemsToKeep() { - return itemsToKeep; - } -+ -+ /** -+ * @return should experience be dropped from this death -+ */ -+ public boolean shouldDropExperience() { -+ return doExpDrop; -+ } -+ -+ /** -+ * @param doExpDrop sets if experience should be dropped from this death -+ */ -+ public void setShouldDropExperience(boolean doExpDrop) { -+ this.doExpDrop = doExpDrop; -+ } - // Paper end - - @NotNull diff --git a/Unmapped-Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch b/Unmapped-Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch deleted file mode 100644 index 7c52aaa446..0000000000 --- a/Unmapped-Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jan 2020 12:25:16 -0600 -Subject: [PATCH] Add effect to block break naturally - - -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index d4ba9c2b858204825d47fd6e91dab8c003df085a..f8c599718143fe638de422fd4625f353ee6c54ae 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -469,6 +469,18 @@ public interface Block extends Metadatable { - */ - boolean breakNaturally(@Nullable ItemStack tool); - -+ // Paper start -+ /** -+ * Breaks the block and spawns items as if a player had digged it with a -+ * specific tool -+ * -+ * @param tool The tool or item in hand used for digging -+ * @param triggerEffect Play the block break particle effect and sound -+ * @return true if the block was destroyed -+ */ -+ boolean breakNaturally(@NotNull ItemStack tool, boolean triggerEffect); -+ // Paper end -+ - /** - * Simulate bone meal application to this block (if possible). - * diff --git a/Unmapped-Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch b/Unmapped-Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch deleted file mode 100644 index f605a2a11b..0000000000 --- a/Unmapped-Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 9 Feb 2020 00:19:08 -0600 -Subject: [PATCH] Add ThrownEggHatchEvent - -Adds a new event similar to PlayerEggThrowEvent, but without the Player requirement -(dispensers can throw eggs to hatch them, too). - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ThrownEggHatchEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ThrownEggHatchEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..085d77dde83d6ed13eb83f23cf3e51d380187c9c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/ThrownEggHatchEvent.java -@@ -0,0 +1,115 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Egg; -+import org.bukkit.entity.EntityType; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a thrown egg might hatch. -+ *

    -+ * This event fires for all thrown eggs that may hatch, players, dispensers, etc. -+ */ -+public class ThrownEggHatchEvent extends Event { -+ private static final HandlerList handlers = new HandlerList(); -+ private final Egg egg; -+ private boolean hatching; -+ private EntityType hatchType; -+ private byte numHatches; -+ -+ public ThrownEggHatchEvent(@NotNull final Egg egg, final boolean hatching, final byte numHatches, @NotNull final EntityType hatchingType) { -+ this.egg = egg; -+ this.hatching = hatching; -+ this.numHatches = numHatches; -+ this.hatchType = hatchingType; -+ } -+ -+ /** -+ * Gets the egg involved in this event. -+ * -+ * @return the egg involved in this event -+ */ -+ @NotNull -+ public Egg getEgg() { -+ return egg; -+ } -+ -+ /** -+ * Gets whether the egg is hatching or not. Will be what the server -+ * would've done without interaction. -+ * -+ * @return boolean Whether the egg is going to hatch or not -+ */ -+ public boolean isHatching() { -+ return hatching; -+ } -+ -+ /** -+ * Sets whether the egg will hatch or not. -+ * -+ * @param hatching true if you want the egg to hatch, false if you want it -+ * not to -+ */ -+ public void setHatching(boolean hatching) { -+ this.hatching = hatching; -+ } -+ -+ /** -+ * Get the type of the mob being hatched (EntityType.CHICKEN by default) -+ * -+ * @return The type of the mob being hatched by the egg -+ */ -+ @NotNull -+ public EntityType getHatchingType() { -+ return hatchType; -+ } -+ -+ /** -+ * Change the type of mob being hatched by the egg -+ * -+ * @param hatchType The type of the mob being hatched by the egg -+ */ -+ public void setHatchingType(@NotNull EntityType hatchType) { -+ if (!hatchType.isSpawnable()) throw new IllegalArgumentException("Can't spawn that entity type from an egg!"); -+ this.hatchType = hatchType; -+ } -+ -+ /** -+ * Get the number of mob hatches from the egg. By default the number will -+ * be the number the server would've done -+ *

      -+ *
    • 7/8 chance of being 0 -+ *
    • 31/256 ~= 1/8 chance to be 1 -+ *
    • 1/256 chance to be 4 -+ *
    -+ * -+ * @return The number of mobs going to be hatched by the egg -+ */ -+ public byte getNumHatches() { -+ return numHatches; -+ } -+ -+ /** -+ * Change the number of mobs coming out of the hatched egg -+ *

    -+ * The boolean hatching will override this number. Ie. If hatching = -+ * false, this number will not matter -+ * -+ * @param numHatches The number of mobs coming out of the egg -+ */ -+ public void setNumHatches(byte numHatches) { -+ this.numHatches = numHatches; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0188-Entity-Jump-API.patch b/Unmapped-Spigot-API-Patches/0188-Entity-Jump-API.patch deleted file mode 100644 index dd4991158c..0000000000 --- a/Unmapped-Spigot-API-Patches/0188-Entity-Jump-API.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 8 Feb 2020 23:26:18 -0600 -Subject: [PATCH] Entity Jump API - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityJumpEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityJumpEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f0067c2e953d18e1a33536980071ba3f0152ecb4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityJumpEvent.java -@@ -0,0 +1,46 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when an entity jumps -+ *

    -+ * Cancelling the event will stop the entity from jumping -+ */ -+public class EntityJumpEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean canceled; -+ -+ public EntityJumpEvent(@NotNull LivingEntity entity) { -+ super(entity); -+ } -+ -+ @NotNull -+ @Override -+ public LivingEntity getEntity() { -+ return (LivingEntity) entity; -+ } -+ -+ public boolean isCancelled() { -+ return canceled; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ canceled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index ac6921093457cee6d01fd27690c8bb6034b4af53..a46379b3a777a9071b0b13357bbd6af40dbfb569 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -795,5 +795,25 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - */ - @NotNull - org.bukkit.inventory.EquipmentSlot getHandRaised(); -+ -+ /** -+ * Get entity jump state. -+ *

    -+ * Jump state will be true when the entity has been marked to jump. -+ * -+ * @return entity jump state. -+ */ -+ boolean isJumping(); -+ -+ /** -+ * Set entity jump state -+ *

    -+ * Setting to true will mark the entity to jump. -+ *

    -+ * Setting to false will unmark the entity to jump but will not stop a jump already in-progress. -+ * -+ * @param jumping entity jump state -+ */ -+ void setJumping(boolean jumping); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch b/Unmapped-Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch deleted file mode 100644 index f61bddb960..0000000000 --- a/Unmapped-Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sun, 1 Mar 2020 22:43:34 +0100 -Subject: [PATCH] add hand to BlockMultiPlaceEvent - - -diff --git a/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java b/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java -index fe2ec79dd6084509cb8cbb8155a356f4162466fd..8460aa4f5e211fb0a6ab11f7487d38dba927e1da 100644 ---- a/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java -@@ -18,9 +18,17 @@ import org.jetbrains.annotations.NotNull; - public class BlockMultiPlaceEvent extends BlockPlaceEvent { - private final List states; - -+ @Deprecated // Paper - public BlockMultiPlaceEvent(@NotNull List states, @NotNull Block clicked, @NotNull ItemStack itemInHand, @NotNull Player thePlayer, boolean canBuild) { -- super(states.get(0).getBlock(), states.get(0), clicked, itemInHand, thePlayer, canBuild); -+ //Paper start - add hand to BlockMultiPlaceEvent -+ this(states, clicked, itemInHand, thePlayer, canBuild, org.bukkit.inventory.EquipmentSlot.HAND); -+ } -+ -+ -+ public BlockMultiPlaceEvent(@NotNull List states, @NotNull Block clicked, @NotNull ItemStack itemInHand, @NotNull Player thePlayer, boolean canBuild, @NotNull org.bukkit.inventory.EquipmentSlot hand) { -+ super(states.get(0).getBlock(), states.get(0), clicked, itemInHand, thePlayer, canBuild, hand); - this.states = ImmutableList.copyOf(states); -+ //Paper end - } - - /** diff --git a/Unmapped-Spigot-API-Patches/0190-Add-tick-times-API.patch b/Unmapped-Spigot-API-Patches/0190-Add-tick-times-API.patch deleted file mode 100644 index a4ae8d485c..0000000000 --- a/Unmapped-Spigot-API-Patches/0190-Add-tick-times-API.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 5 Apr 2020 22:22:58 -0500 -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 49bf621a2c0e5e9641b334a42b2769944c991d5d..4bae8a4387b86c868149f06b490ef6dfced2ff41 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1590,6 +1590,25 @@ public final class Bukkit { - public static double[] getTPS() { - return server.getTPS(); - } -+ -+ /** -+ * Get a sample of the servers last tick times (in nanos) -+ * -+ * @return A sample of the servers last tick times (in nanos) -+ */ -+ @NotNull -+ public static long[] getTickTimes() { -+ return server.getTickTimes(); -+ } -+ -+ /** -+ * Get the average tick time (in millis) -+ * -+ * @return Average tick time (in millis) -+ */ -+ public static double getAverageTickTime() { -+ return server == null ? 0D : server.getAverageTickTime(); -+ } - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index e448ae78304974f7664b7ef18568a547833ece9f..bea7ffdb00e6de1391e9143901c62f0aceaaf727 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1345,6 +1345,21 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - */ - @NotNull - public double[] getTPS(); -+ -+ /** -+ * Get a sample of the servers last tick times (in nanos) -+ * -+ * @return A sample of the servers last tick times (in nanos) -+ */ -+ @NotNull -+ long[] getTickTimes(); -+ -+ /** -+ * Get the average tick time (in millis) -+ * -+ * @return Average tick time (in millis) -+ */ -+ double getAverageTickTime(); - // Paper end - - // Paper start diff --git a/Unmapped-Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch b/Unmapped-Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch deleted file mode 100644 index 33f2570121..0000000000 --- a/Unmapped-Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Fri, 10 Apr 2020 21:24:35 -0400 -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 4bae8a4387b86c868149f06b490ef6dfced2ff41..4dadea432c8d79b15fa126b4f0c810e9a72b4029 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1858,6 +1858,15 @@ public final class Bukkit { - public static int getCurrentTick() { - return server.getCurrentTick(); - } -+ -+ /** -+ * Checks if the server is in the process of being shutdown. -+ * -+ * @return true if server is in the process of being shutdown -+ */ -+ public static boolean isStopping() { -+ return server.isStopping(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index bea7ffdb00e6de1391e9143901c62f0aceaaf727..b92261e09790e89788560bf7c9784c8399504810 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1631,5 +1631,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @return Current tick - */ - int getCurrentTick(); -+ -+ /** -+ * Checks if the server is in the process of being shutdown. -+ * -+ * @return true if server is in the process of being shutdown -+ */ -+ boolean isStopping(); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch b/Unmapped-Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch deleted file mode 100644 index 5ca0264ed8..0000000000 --- a/Unmapped-Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Apr 2020 21:38:59 -0400 -Subject: [PATCH] Disable Sync Events firing Async errors during shutdown - -This is how it use to behave on Paper, and this is totally destroying -the ability to try to shut the server down gracefully during the -shutdown process as events firing on the watchdog thread are throwing -errors. - -This isn't an issue on Spigot - -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index a1a805004941d67abb0b9aa1721e0370c45b5289..26685f59b235ea5b4c4fb7ae21acb5149edaa2b3 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -591,7 +591,7 @@ public final class SimplePluginManager implements PluginManager { - // Paper - replace callEvent by merging to below method - if (event.isAsynchronous() && server.isPrimaryThread()) { - throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously."); -- } else if (!event.isAsynchronous() && !server.isPrimaryThread()) { -+ } else if (!event.isAsynchronous() && !server.isPrimaryThread() && !server.isStopping() ) { - throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously."); - } - diff --git a/Unmapped-Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch b/Unmapped-Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch deleted file mode 100644 index be66a6a695..0000000000 --- a/Unmapped-Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Wed, 15 Apr 2020 01:24:55 -0400 -Subject: [PATCH] Make JavaPluginLoader thread-safe - - -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index f26303315c9c93356f0b04440136855dd54d32b7..ce751577623eaad0f31e2eb7bf0842d1ab73e845 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -52,6 +52,8 @@ import org.yaml.snakeyaml.error.YAMLException; - public final class JavaPluginLoader implements PluginLoader { - final Server server; - private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; -+ private final Map classLoadLock = new java.util.HashMap(); // Paper -+ private final Map classLoadLockCount = new java.util.HashMap(); // Paper - private final List loaders = new CopyOnWriteArrayList(); - private final LibraryLoader libraryLoader; - -@@ -201,12 +203,33 @@ public final class JavaPluginLoader implements PluginLoader { - - @Nullable - Class getClassByName(final String name, boolean resolve, PluginDescriptionFile description) { -+ // Paper start - make MT safe -+ java.util.concurrent.locks.ReentrantReadWriteLock lock; -+ synchronized (classLoadLock) { -+ lock = classLoadLock.computeIfAbsent(name, (x) -> new java.util.concurrent.locks.ReentrantReadWriteLock()); -+ classLoadLockCount.compute(name, (x, prev) -> prev != null ? prev + 1 : 1); -+ } -+ lock.writeLock().lock();try { -+ // Paper end - for (PluginClassLoader loader : loaders) { - try { - return loader.loadClass0(name, resolve, false, ((SimplePluginManager) server.getPluginManager()).isTransitiveDepend(description, loader.plugin.getDescription())); - } catch (ClassNotFoundException cnfe) { - } - } -+ // Paper start - make MT safe -+ } finally { -+ synchronized (classLoadLock) { -+ lock.writeLock().unlock(); -+ if (classLoadLockCount.get(name) == 1) { -+ classLoadLock.remove(name); -+ classLoadLockCount.remove(name); -+ } else { -+ classLoadLockCount.compute(name, (x, prev) -> prev - 1); -+ } -+ } -+ } -+ // Paper end - return null; - } - diff --git a/Unmapped-Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch b/Unmapped-Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch deleted file mode 100644 index c156119b15..0000000000 --- a/Unmapped-Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch +++ /dev/null @@ -1,202 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Mon, 20 Jan 2020 21:38:34 +0100 -Subject: [PATCH] Add Player Client Options API - - -diff --git a/src/main/java/com/destroystokyo/paper/ClientOption.java b/src/main/java/com/destroystokyo/paper/ClientOption.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9dad814cf51bc59ec5dfbf14474fea6557de38aa ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/ClientOption.java -@@ -0,0 +1,33 @@ -+package com.destroystokyo.paper; -+ -+import org.jetbrains.annotations.NotNull; -+ -+import org.bukkit.inventory.MainHand; -+ -+public final class ClientOption { -+ -+ public static final ClientOption SKIN_PARTS = new ClientOption<>(SkinParts.class); -+ public static final ClientOption CHAT_COLORS_ENABLED = new ClientOption<>(Boolean.class); -+ public static final ClientOption CHAT_VISIBILITY = new ClientOption<>(ChatVisibility.class); -+ public static final ClientOption LOCALE = new ClientOption<>(String.class); -+ public static final ClientOption MAIN_HAND = new ClientOption<>(MainHand.class); -+ public static final ClientOption VIEW_DISTANCE = new ClientOption<>(Integer.class); -+ -+ private final Class type; -+ -+ private ClientOption(@NotNull Class type) { -+ this.type = type; -+ } -+ -+ @NotNull -+ public Class getType() { -+ return type; -+ } -+ -+ public enum ChatVisibility { -+ FULL, -+ SYSTEM, -+ HIDDEN, -+ UNKNOWN -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/SkinParts.java b/src/main/java/com/destroystokyo/paper/SkinParts.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4a0c39405d4fbed457787e3c6ded4cc6591bc8c2 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/SkinParts.java -@@ -0,0 +1,20 @@ -+package com.destroystokyo.paper; -+ -+public interface SkinParts { -+ -+ boolean hasCapeEnabled(); -+ -+ boolean hasJacketEnabled(); -+ -+ boolean hasLeftSleeveEnabled(); -+ -+ boolean hasRightSleeveEnabled(); -+ -+ boolean hasLeftPantsEnabled(); -+ -+ boolean hasRightPantsEnabled(); -+ -+ boolean hasHatsEnabled(); -+ -+ int getRaw(); -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerClientOptionsChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerClientOptionsChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f7f171c4ee0b8339b2f8fbe82442d65f17202f28 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerClientOptionsChangeEvent.java -@@ -0,0 +1,100 @@ -+package com.destroystokyo.paper.event.player; -+ -+import com.destroystokyo.paper.ClientOption; -+import com.destroystokyo.paper.ClientOption.ChatVisibility; -+import com.destroystokyo.paper.SkinParts; -+ -+import org.jetbrains.annotations.NotNull; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.MainHand; -+ -+/** -+ * Called when the player changes his client settings -+ */ -+public class PlayerClientOptionsChangeEvent extends PlayerEvent { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ private final String locale; -+ private final int viewDistance; -+ private final ChatVisibility chatVisibility; -+ private final boolean chatColors; -+ private final SkinParts skinparts; -+ private final MainHand mainHand; -+ -+ public PlayerClientOptionsChangeEvent(@NotNull Player player, @NotNull String locale, int viewDistance, @NotNull ChatVisibility chatVisibility, boolean chatColors, @NotNull SkinParts skinParts, @NotNull MainHand mainHand) { -+ super(player); -+ this.locale = locale; -+ this.viewDistance = viewDistance; -+ this.chatVisibility = chatVisibility; -+ this.chatColors = chatColors; -+ this.skinparts = skinParts; -+ this.mainHand = mainHand; -+ } -+ -+ @NotNull -+ public String getLocale() { -+ return locale; -+ } -+ -+ public boolean hasLocaleChanged() { -+ return !locale.equals(player.getClientOption(ClientOption.LOCALE)); -+ } -+ -+ public int getViewDistance() { -+ return viewDistance; -+ } -+ -+ public boolean hasViewDistanceChanged() { -+ return viewDistance != player.getClientOption(ClientOption.VIEW_DISTANCE); -+ } -+ -+ @NotNull -+ public ChatVisibility getChatVisibility() { -+ return chatVisibility; -+ } -+ -+ public boolean hasChatVisibilityChanged() { -+ return chatVisibility != player.getClientOption(ClientOption.CHAT_VISIBILITY); -+ } -+ -+ public boolean hasChatColorsEnabled() { -+ return chatColors; -+ } -+ -+ public boolean hasChatColorsEnabledChanged() { -+ return chatColors != player.getClientOption(ClientOption.CHAT_COLORS_ENABLED); -+ } -+ -+ @NotNull -+ public SkinParts getSkinParts() { -+ return skinparts; -+ } -+ -+ public boolean hasSkinPartsChanged() { -+ return skinparts.getRaw() != player.getClientOption(ClientOption.SKIN_PARTS).getRaw(); -+ } -+ -+ @NotNull -+ public MainHand getMainHand() { -+ return mainHand; -+ } -+ -+ public boolean hasMainHandChanged() { -+ return mainHand != player.getClientOption(ClientOption.MAIN_HAND); -+ } -+ -+ @Override -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index ec87c78d0f9379511467b6d13b9cdfa4c19d15ca..2530c811f52f51d6338900221b4681c952c1c752 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -2,6 +2,7 @@ package org.bukkit.entity; - - import java.net.InetSocketAddress; - import java.util.UUID; -+import com.destroystokyo.paper.ClientOption; // Paper - import com.destroystokyo.paper.Title; // Paper - import net.kyori.adventure.text.Component; - import com.destroystokyo.paper.profile.PlayerProfile; // Paper -@@ -1909,6 +1910,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * Reset the cooldown counter to 0, effectively starting the cooldown period. - */ - void resetCooldown(); -+ -+ /** -+ * @return the client option value of the player -+ */ -+ @NotNull -+ T getClientOption(@NotNull ClientOption option); - // Paper end - - // Spigot start diff --git a/Unmapped-Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch b/Unmapped-Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch deleted file mode 100644 index 15fa2db392..0000000000 --- a/Unmapped-Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: nossr50 -Date: Thu, 26 Mar 2020 19:30:58 -0700 -Subject: [PATCH] Add PlayerAttackEntityCooldownResetEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerAttackEntityCooldownResetEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerAttackEntityCooldownResetEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ebdebe7b6ec6ed5aadc7ee925ba0147e61e6bc84 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerAttackEntityCooldownResetEvent.java -@@ -0,0 +1,76 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when processing a player's attack on an entity when the player's attack strength cooldown is reset -+ */ -+public class PlayerAttackEntityCooldownResetEvent extends PlayerEvent implements Cancellable { -+ -+ private final float cooledAttackStrength; -+ private boolean cancel = false; -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private final Entity attackedEntity; -+ -+ public PlayerAttackEntityCooldownResetEvent(@NotNull Player who, @NotNull Entity attackedEntity, float cooledAttackStrength) { -+ super(who); -+ this.attackedEntity = attackedEntity; -+ this.cooledAttackStrength = cooledAttackStrength; -+ } -+ -+ @Override -+ public @NotNull HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ public static @NotNull HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ /** -+ * Gets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ *

    -+ * If an attack cooldown event is cancelled, the players attack strength will remain at the same value instead of being reset. -+ * -+ * @return true if this event is cancelled -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancel; -+ } -+ -+ /** -+ * Cancelling this event will prevent the target player from having their cooldown reset from attacking this entity -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancel = cancel; -+ } -+ -+ /** -+ * Get the value of the players cooldown attack strength when they initiated the attack -+ * -+ * @return returns the original player cooldown value -+ */ -+ public float getCooledAttackStrength() { -+ return cooledAttackStrength; -+ } -+ -+ /** -+ * Returns the entity attacked by the player -+ * -+ * @return the entity attacked by the player -+ */ -+ @NotNull -+ public Entity getAttackedEntity() { -+ return attackedEntity; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch b/Unmapped-Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch deleted file mode 100644 index 800d5364e2..0000000000 --- a/Unmapped-Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Wesley Smith -Date: Fri, 24 Apr 2020 18:30:26 -0400 -Subject: [PATCH] Fix Potion#toItemStack swapping the extended and upgraded - constructor values. - -While the Potion class is deprecated, it is still used in some plugins for cross-version potion handling. This issue has existed for a long time, and has caused many heaches along the way. - -diff --git a/src/main/java/org/bukkit/potion/Potion.java b/src/main/java/org/bukkit/potion/Potion.java -index b9dbbfd07dea643d7ac749822548571968adaa94..ac02ae4fc179483b4ac3d1adc41684a8426197eb 100644 ---- a/src/main/java/org/bukkit/potion/Potion.java -+++ b/src/main/java/org/bukkit/potion/Potion.java -@@ -267,7 +267,7 @@ public class Potion { - } - ItemStack itemStack = new ItemStack(material, amount); - PotionMeta meta = (PotionMeta) itemStack.getItemMeta(); -- meta.setBasePotionData(new PotionData(type, level == 2, extended)); -+ meta.setBasePotionData(new PotionData(type, extended, level == 2)); // Paper - fix swapped values - itemStack.setItemMeta(meta); - return itemStack; - } diff --git a/Unmapped-Spigot-API-Patches/0197-Villager-Restocks-API.patch b/Unmapped-Spigot-API-Patches/0197-Villager-Restocks-API.patch deleted file mode 100644 index e2dcfc3144..0000000000 --- a/Unmapped-Spigot-API-Patches/0197-Villager-Restocks-API.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: zbk -Date: Sun, 26 Apr 2020 23:49:03 -0400 -Subject: [PATCH] Villager Restocks API - - -diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java -index ef48ad9b28750ab7b33071f6b8e354e922731909..d1579153092c1b80350155110f1b9926b1a1ef57 100644 ---- a/src/main/java/org/bukkit/entity/Villager.java -+++ b/src/main/java/org/bukkit/entity/Villager.java -@@ -77,6 +77,20 @@ public interface Villager extends AbstractVillager { - */ - public void setVillagerExperience(int experience); - -+ // Paper start -+ /** -+ * Gets the amount of times a villager has restocked their trades today -+ * @return The amount of trade restocks. -+ */ -+ public int getRestocksToday(); -+ -+ /** -+ * Sets the amount of times a villager has restocked their trades today -+ * @param restocksToday new restock count -+ */ -+ public void setRestocksToday(int restocksToday); -+ // Paper end -+ - /** - * Attempts to make this villager sleep at the given location. - *
    diff --git a/Unmapped-Spigot-API-Patches/0198-Expose-game-version.patch b/Unmapped-Spigot-API-Patches/0198-Expose-game-version.patch deleted file mode 100644 index 560d2370a1..0000000000 --- a/Unmapped-Spigot-API-Patches/0198-Expose-game-version.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Fri, 1 May 2020 17:39:02 +0300 -Subject: [PATCH] Expose game version - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 86ac6702b3aeab1126b2b2879b87ef3883793d44..12214ce2af7363d40cf44652e46f05c5c1f2fe5a 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -118,6 +118,18 @@ public final class Bukkit { - return server.getBukkitVersion(); - } - -+ // Paper start - expose game version -+ /** -+ * Gets the version of game this server implements -+ * -+ * @return version of game -+ */ -+ @NotNull -+ public static String getMinecraftVersion() { -+ return server.getMinecraftVersion(); -+ } -+ // Paper end -+ - /** - * 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 16a74b834c4d4b907f9b11ccf9ef9804514df224..360decea2eb6de4c567fa4cceea8f19bceff6823 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -97,6 +97,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @NotNull - public String getBukkitVersion(); - -+ // Paper start - expose game version -+ /** -+ * Gets the version of game this server implements -+ * -+ * @return version of game -+ */ -+ @NotNull -+ String getMinecraftVersion(); -+ // Paper end -+ - /** - * Gets a view of all currently logged in players. This {@linkplain - * Collections#unmodifiableCollection(Collection) view} is a reused diff --git a/Unmapped-Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch b/Unmapped-Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch deleted file mode 100644 index 3b3612713f..0000000000 --- a/Unmapped-Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch +++ /dev/null @@ -1,283 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Sat, 25 Apr 2020 23:31:28 +0200 -Subject: [PATCH] Add item slot convenience methods - - -diff --git a/src/main/java/org/bukkit/inventory/AnvilInventory.java b/src/main/java/org/bukkit/inventory/AnvilInventory.java -index 4af562426aa38faeb6822abb0c878a3ac346b383..b95e563b5454306a9188ae3295309ee86a756477 100644 ---- a/src/main/java/org/bukkit/inventory/AnvilInventory.java -+++ b/src/main/java/org/bukkit/inventory/AnvilInventory.java -@@ -49,4 +49,64 @@ public interface AnvilInventory extends Inventory { - * @param levels the maximum experience cost - */ - void setMaximumRepairCost(int levels); -+ -+ // Paper start -+ /** -+ * Gets the item in the left input slot. -+ * -+ * @return item in the first slot -+ */ -+ @Nullable -+ default ItemStack getFirstItem() { -+ return getItem(0); -+ } -+ -+ /** -+ * Sets the item in the left input slot. -+ * -+ * @param firstItem item to set -+ */ -+ default void setFirstItem(@Nullable ItemStack firstItem) { -+ setItem(0, firstItem); -+ } -+ -+ /** -+ * Gets the item in the right input slot. -+ * -+ * @return item in the second slot -+ */ -+ @Nullable -+ default ItemStack getSecondItem() { -+ return getItem(1); -+ } -+ -+ /** -+ * Sets the item in the right input slot. -+ * -+ * @param secondItem item to set -+ */ -+ default void setSecondItem(@Nullable ItemStack secondItem) { -+ setItem(1, secondItem); -+ } -+ -+ /** -+ * Gets the item in the result slot. -+ * -+ * @return item in the result slot -+ */ -+ @Nullable -+ default ItemStack getResult() { -+ return getItem(2); -+ } -+ -+ /** -+ * Sets the item in the result slot. -+ * Note that the client might not be able to take out the item if it does not match the input items. -+ * -+ * @param result item to set -+ */ -+ default void setResult(@Nullable ItemStack result) { -+ setItem(2, result); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/GrindstoneInventory.java b/src/main/java/org/bukkit/inventory/GrindstoneInventory.java -index 9048892c8768c6b4d6cea03da73339f13bfbe82e..1c750108f55a0a31ad23433b333e0ea486a63ff2 100644 ---- a/src/main/java/org/bukkit/inventory/GrindstoneInventory.java -+++ b/src/main/java/org/bukkit/inventory/GrindstoneInventory.java -@@ -1,6 +1,68 @@ - package org.bukkit.inventory; - -+import org.jetbrains.annotations.Nullable; // Paper -+ - /** - * Interface to the inventory of a Grindstone. - */ --public interface GrindstoneInventory extends Inventory { } -+public interface GrindstoneInventory extends Inventory { -+ -+ // Paper start -+ /** -+ * Gets the upper input item. -+ * -+ * @return upper input item -+ */ -+ @Nullable -+ default ItemStack getUpperItem() { -+ return getItem(0); -+ } -+ -+ /** -+ * Sets the upper input item. -+ * -+ * @param upperItem item to set -+ */ -+ default void setUpperItem(@Nullable ItemStack upperItem) { -+ setItem(0, upperItem); -+ } -+ -+ /** -+ * Gets the lower input item. -+ * -+ * @return lower input item -+ */ -+ @Nullable -+ default ItemStack getLowerItem() { -+ return getItem(1); -+ } -+ -+ /** -+ * Sets the lower input item. -+ * -+ * @param lowerItem item to set -+ */ -+ default void setLowerItem(@Nullable ItemStack lowerItem) { -+ setItem(1, lowerItem); -+ } -+ -+ /** -+ * Gets the result. -+ * -+ * @return result -+ */ -+ @Nullable -+ default ItemStack getResult() { -+ return getItem(2); -+ } -+ -+ /** -+ * Sets the result. -+ * -+ * @param result item to set -+ */ -+ default void setResult(@Nullable ItemStack result) { -+ setItem(2, result); -+ } -+ // Paper end -+} -diff --git a/src/main/java/org/bukkit/inventory/LecternInventory.java b/src/main/java/org/bukkit/inventory/LecternInventory.java -index 4a0c43acc2714e095973eb78536041bb1a179ddc..acf2244f77133df53eb5f862c8e713c85192f13d 100644 ---- a/src/main/java/org/bukkit/inventory/LecternInventory.java -+++ b/src/main/java/org/bukkit/inventory/LecternInventory.java -@@ -11,4 +11,25 @@ public interface LecternInventory extends Inventory { - @Nullable - @Override - public Lectern getHolder(); -+ -+ // Paper start -+ /** -+ * Gets the lectern's held book. -+ * -+ * @return book set in the lectern -+ */ -+ @Nullable -+ default ItemStack getBook() { -+ return getItem(0); -+ } -+ -+ /** -+ * Sets the lectern's held book. -+ * -+ * @param book the new book -+ */ -+ default void setBook(@Nullable ItemStack book) { -+ setItem(0, book); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/SmithingInventory.java b/src/main/java/org/bukkit/inventory/SmithingInventory.java -index 96d526b7b153e56c9a97de42ce3270b6638510e4..a41ca6bd2672db2810dd70c4925b84a4f081af05 100644 ---- a/src/main/java/org/bukkit/inventory/SmithingInventory.java -+++ b/src/main/java/org/bukkit/inventory/SmithingInventory.java -@@ -30,4 +30,44 @@ public interface SmithingInventory extends Inventory { - */ - @Nullable - Recipe getRecipe(); -+ -+ // Paper start -+ /** -+ * Gets the input equipment (first slot). -+ * -+ * @return input equipment item -+ */ -+ @Nullable -+ default ItemStack getInputEquipment() { -+ return getItem(0); -+ } -+ -+ /** -+ * Sets the input equipment (first slot). -+ * -+ * @param itemStack item to set -+ */ -+ default void setInputEquipment(@Nullable ItemStack itemStack) { -+ setItem(0, itemStack); -+ } -+ -+ /** -+ * Gets the input mineral (second slot). -+ * -+ * @return input mineral item -+ */ -+ @Nullable -+ default ItemStack getInputMineral() { -+ return getItem(1); -+ } -+ -+ /** -+ * Sets the input mineral (second slot). -+ * -+ * @param itemStack item to set -+ */ -+ default void setInputMineral(@Nullable ItemStack itemStack) { -+ setItem(1, itemStack); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/StonecutterInventory.java b/src/main/java/org/bukkit/inventory/StonecutterInventory.java -index dbb034fae3b8bfaf40e6341460e274c21e321a3b..e7a8e7188bf8b9840de56dc80c2b79d64a9389cb 100644 ---- a/src/main/java/org/bukkit/inventory/StonecutterInventory.java -+++ b/src/main/java/org/bukkit/inventory/StonecutterInventory.java -@@ -1,6 +1,49 @@ - package org.bukkit.inventory; - -+import org.jetbrains.annotations.Nullable; // Paper -+ - /** - * Interface to the inventory of a Stonecutter. - */ --public interface StonecutterInventory extends Inventory { } -+public interface StonecutterInventory extends Inventory { -+ -+ // Paper start -+ /** -+ * Gets the input item. -+ * -+ * @return input item -+ */ -+ @Nullable -+ default ItemStack getInputItem() { -+ return getItem(0); -+ } -+ -+ /** -+ * Sets the input item. -+ * -+ * @param itemStack item to set -+ */ -+ default void setInputItem(@Nullable ItemStack itemStack) { -+ setItem(0, itemStack); -+ } -+ -+ /** -+ * Gets the result item. -+ * -+ * @return result -+ */ -+ @Nullable -+ default ItemStack getResult() { -+ return getItem(1); -+ } -+ -+ /** -+ * Sets the result item. -+ * -+ * @param itemStack item to set -+ */ -+ default void setResult(@Nullable ItemStack itemStack) { -+ setItem(1, itemStack); -+ } -+ // Paper end -+} diff --git a/Unmapped-Spigot-API-Patches/0200-Add-Mob-Goal-API.patch b/Unmapped-Spigot-API-Patches/0200-Add-Mob-Goal-API.patch deleted file mode 100644 index 24855e7426..0000000000 --- a/Unmapped-Spigot-API-Patches/0200-Add-Mob-Goal-API.patch +++ /dev/null @@ -1,481 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Fri, 3 Jan 2020 16:24:46 +0100 -Subject: [PATCH] Add Mob Goal API - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/Goal.java b/src/main/java/com/destroystokyo/paper/entity/ai/Goal.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c57c5416c88e2070a082403ab0dda9d7f08d2a57 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/Goal.java -@@ -0,0 +1,66 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.EnumSet; -+ -+import org.bukkit.entity.Mob; -+ -+/** -+ * Represents an AI goal of an entity -+ */ -+public interface Goal { -+ -+ /** -+ * Checks if this goal should be activated -+ * -+ * @return if this goal should be activated -+ */ -+ boolean shouldActivate(); -+ -+ /** -+ * Checks if this goal should stay active, defaults to {@link Goal#shouldActivate()} -+ * -+ * @return if this goal should stay active -+ */ -+ default boolean shouldStayActive() { -+ return shouldActivate(); -+ } -+ -+ /** -+ * Called when this goal gets activated -+ */ -+ default void start() { -+ } -+ -+ /** -+ * Called when this goal gets stopped -+ */ -+ default void stop() { -+ } -+ -+ /** -+ * Called each tick the goal is activated -+ */ -+ default void tick() { -+ } -+ -+ /** -+ * A unique key that identifies this type of goal. Plugins should use their own namespace, not the minecraft -+ * namespace. Additionally, this key also specifies to what mobs this goal can be applied to -+ * -+ * @return the goal key -+ */ -+ @NotNull -+ GoalKey getKey(); -+ -+ /** -+ * Returns a list of all applicable flags for this goal.
    -+ * -+ * This method is only called on construction. -+ * -+ * @return the subtypes. -+ */ -+ @NotNull -+ EnumSet getTypes(); -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/GoalKey.java b/src/main/java/com/destroystokyo/paper/entity/ai/GoalKey.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9cd98c6fcfa3eb439d9013ef76ef4661175a0e5a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/GoalKey.java -@@ -0,0 +1,64 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import com.google.common.base.Objects; -+ -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.StringJoiner; -+ -+import org.bukkit.NamespacedKey; -+import org.bukkit.entity.Mob; -+ -+/** -+ * -+ * Used to identify a Goal. Consists of a {@link NamespacedKey} and the type of mob the goal can be applied to -+ * -+ * @param the type of mob the goal can be applied to -+ */ -+public class GoalKey { -+ -+ private final Class entityClass; -+ private final NamespacedKey namespacedKey; -+ -+ private GoalKey(@NotNull Class entityClass, @NotNull NamespacedKey namespacedKey) { -+ this.entityClass = entityClass; -+ this.namespacedKey = namespacedKey; -+ } -+ -+ @NotNull -+ public Class getEntityClass() { -+ return entityClass; -+ } -+ -+ @NotNull -+ public NamespacedKey getNamespacedKey() { -+ return namespacedKey; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ GoalKey goalKey = (GoalKey) o; -+ return Objects.equal(entityClass, goalKey.entityClass) && -+ Objects.equal(namespacedKey, goalKey.namespacedKey); -+ } -+ -+ @Override -+ public int hashCode() { -+ return Objects.hashCode(entityClass, namespacedKey); -+ } -+ -+ @Override -+ public String toString() { -+ return new StringJoiner(", ", GoalKey.class.getSimpleName() + "[", "]") -+ .add("entityClass=" + entityClass) -+ .add("namespacedKey=" + namespacedKey) -+ .toString(); -+ } -+ -+ @NotNull -+ public static GoalKey of(@NotNull Class entityClass, @NotNull NamespacedKey namespacedKey) { -+ return new GoalKey<>(entityClass, namespacedKey); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/GoalType.java b/src/main/java/com/destroystokyo/paper/entity/ai/GoalType.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7024c8f484d2460abf3abfe65a29771d814105ec ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/GoalType.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+/** -+ * Represents the subtype of a goal. Used by minecraft to disable certain types of goals if needed. -+ */ -+public enum GoalType { -+ -+ MOVE, -+ LOOK, -+ JUMP, -+ TARGET, -+ /** -+ * Used to map vanilla goals, that are a behavior goal but don't have a type set... -+ */ -+ UNKNOWN_BEHAVIOR, -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoals.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e21f7574763dd4f13794f91bbef192ef66a8f5e9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoals.java -@@ -0,0 +1,50 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import java.util.Collection; -+ -+import org.bukkit.entity.Mob; -+ -+/** -+ * Represents a part of the "brain" of a mob. It tracks all tasks (running or not), allows adding and removing goals -+ */ -+public interface MobGoals { -+ -+ void addGoal(@NotNull T mob, int priority, @NotNull Goal goal); -+ -+ void removeGoal(@NotNull T mob, @NotNull Goal goal); -+ -+ void removeAllGoals(@NotNull T mob); -+ -+ void removeAllGoals(@NotNull T mob, @NotNull GoalType type); -+ -+ void removeGoal(@NotNull T mob, @NotNull GoalKey key); -+ -+ boolean hasGoal(@NotNull T mob, @NotNull GoalKey key); -+ -+ @Nullable -+ Goal getGoal(@NotNull T mob, @NotNull GoalKey key); -+ -+ @NotNull -+ Collection> getGoals(@NotNull T mob, @NotNull GoalKey key); -+ -+ @NotNull -+ Collection> getAllGoals(@NotNull T mob); -+ -+ @NotNull -+ Collection> getAllGoals(@NotNull T mob, @NotNull GoalType type); -+ -+ @NotNull -+ Collection> getAllGoalsWithout(@NotNull T mob, @NotNull GoalType type); -+ -+ @NotNull -+ Collection> getRunningGoals(@NotNull T mob); -+ -+ @NotNull -+ Collection> getRunningGoals(@NotNull T mob, @NotNull GoalType type); -+ -+ @NotNull -+ Collection> getRunningGoalsWithout(@NotNull T mob, @NotNull GoalType type); -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b42091752981a1f309ab350e9a394092cb334824 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java -@@ -0,0 +1,209 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import com.destroystokyo.paper.entity.RangedEntity; -+ -+import org.bukkit.NamespacedKey; -+import org.bukkit.entity.*; -+ -+/** -+ * Represents a vanilla goal. Plugins should never implement this.
    -+ * Generated by VanillaPathfinderTest in paper-server -+ */ -+public interface VanillaGoal extends Goal { -+ -+ GoalKey BEE_ATTACK = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_attack")); -+ GoalKey BEE_BECOME_ANGRY = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_become_angry")); -+ GoalKey BEE_ENTER_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_enter_hive")); -+ GoalKey BEE_GO_TO_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_go_to_hive")); -+ GoalKey BEE_GO_TO_KNOWN_FLOWER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_go_to_known_flower")); -+ GoalKey BEE_GROW_CROP = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_grow_crop")); -+ GoalKey BEE_HURT_BY_OTHER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_hurt_by_other")); -+ GoalKey BEE_LOCATE_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_locate_hive")); -+ GoalKey BEE_POLLINATE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_pollinate")); -+ GoalKey BEE_WANDER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_wander")); -+ GoalKey BLAZE_FIREBALL = GoalKey.of(Blaze.class, NamespacedKey.minecraft("blaze_fireball")); -+ GoalKey TEMPT_CHANCE = GoalKey.of(Cat.class, NamespacedKey.minecraft("tempt_chance")); -+ GoalKey CAT_AVOID_ENTITY = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_avoid_entity")); -+ GoalKey CAT_RELAX_ON_OWNER = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_relax_on_owner")); -+ GoalKey DOLPHIN_SWIM_TO_TREASURE = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_swim_to_treasure")); -+ GoalKey DOLPHIN_SWIM_WITH_PLAYER = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_swim_with_player")); -+ GoalKey DOLPHIN_PLAY_WITH_ITEMS = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_play_with_items")); -+ GoalKey DROWNED_ATTACK = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack")); -+ GoalKey DROWNED_GOTO_BEACH = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_goto_beach")); -+ GoalKey DROWNED_GOTO_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("drowned_goto_water")); -+ GoalKey DROWNED_SWIM_UP = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_swim_up")); -+ GoalKey DROWNED_TRIDENT_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("drowned_trident_attack")); -+ GoalKey ENDERMAN_PICKUP_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_pickup_block")); -+ GoalKey ENDERMAN_PLACE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_place_block")); -+ GoalKey PLAYER_WHO_LOOKED_AT_TARGET = GoalKey.of(Enderman.class, NamespacedKey.minecraft("player_who_looked_at_target")); -+ GoalKey ENDERMAN_FREEZE_WHEN_LOOKED_AT = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_freeze_when_looked_at")); -+ GoalKey EVOKER_ATTACK_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_attack_spell")); -+ GoalKey EVOKER_CAST_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_cast_spell")); -+ GoalKey EVOKER_SUMMON_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_summon_spell")); -+ GoalKey EVOKER_WOLOLO_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_wololo_spell")); -+ GoalKey FISH_SWIM = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_swim")); -+ GoalKey FOX_DEFEND_TRUSTED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_defend_trusted")); -+ GoalKey FOX_FACEPLANT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_faceplant")); -+ GoalKey FOX_BREED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_breed")); -+ GoalKey FOX_EAT_BERRIES = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_eat_berries")); -+ GoalKey FOX_FLOAT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_float")); -+ GoalKey FOX_FOLLOW_PARENT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_follow_parent")); -+ GoalKey FOX_LOOK_AT_PLAYER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_look_at_player")); -+ GoalKey FOX_MELEE_ATTACK = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_melee_attack")); -+ GoalKey FOX_PANIC = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_panic")); -+ GoalKey FOX_PERCH_AND_SEARCH = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_perch_and_search")); -+ GoalKey FOX_POUNCE = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_pounce")); -+ GoalKey FOX_SEARCH_FOR_ITEMS = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_search_for_items")); -+ GoalKey FOX_SLEEP = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_sleep")); -+ GoalKey FOX_STROLL_THROUGH_VILLAGE = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stroll_through_village")); -+ GoalKey FOX_SEEK_SHELTER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_seek_shelter")); -+ GoalKey FOX_STALK_PREY = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stalk_prey")); -+ GoalKey GHAST_ATTACK_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_attack_target")); -+ GoalKey GHAST_IDLE_MOVE = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_idle_move")); -+ GoalKey GHAST_MOVE_TOWARDS_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_move_towards_target")); -+ GoalKey GUARDIAN_ATTACK = GoalKey.of(Guardian.class, NamespacedKey.minecraft("guardian_attack")); -+ GoalKey RAIDER_OPEN_DOOR = GoalKey.of(Illager.class, NamespacedKey.minecraft("raider_open_door")); -+ GoalKey ILLUSIONER_BLINDNESS_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_blindness_spell")); -+ GoalKey ILLUSIONER_MIRROR_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_mirror_spell")); -+ GoalKey SPELLCASTER_CAST_SPELL = GoalKey.of(Spellcaster.class, NamespacedKey.minecraft("spellcaster_cast_spell")); -+ GoalKey LLAMA_ATTACK_WOLF = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_attack_wolf")); -+ GoalKey LLAMA_HURT_BY = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_hurt_by")); -+ GoalKey LLAMATRADER_DEFENDED_WANDERING_TRADER = GoalKey.of(TraderLlama.class, NamespacedKey.minecraft("llamatrader_defended_wandering_trader")); -+ GoalKey LONG_DISTANCE_PATROL = GoalKey.of(Monster.class, NamespacedKey.minecraft("long_distance_patrol")); -+ GoalKey OCELOT_AVOID_ENTITY = GoalKey.of(Ocelot.class, NamespacedKey.minecraft("ocelot_avoid_entity")); -+ GoalKey OCELOT_TEMPT = GoalKey.of(Ocelot.class, NamespacedKey.minecraft("ocelot_tempt")); -+ GoalKey PANDA_ATTACK = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_attack")); -+ GoalKey PANDA_AVOID = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_avoid")); -+ GoalKey PANDA_BREED = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_breed")); -+ GoalKey PANDA_HURT_BY_TARGET = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_hurt_by_target")); -+ GoalKey PANDA_LIE_ON_BACK = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_lie_on_back")); -+ GoalKey PANDA_LOOK_AT_PLAYER = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_look_at_player")); -+ GoalKey PANDA_PANIC = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_panic")); -+ GoalKey PANDA_ROLL = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_roll")); -+ GoalKey PANDA_SIT = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_sit")); -+ GoalKey PANDA_SNEEZE = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_sneeze")); -+ GoalKey PHANTOM_ATTACK_PLAYER = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_player")); -+ GoalKey PHANTOM_ATTACK_STRATEGY = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_strategy")); -+ GoalKey PHANTOM_CIRCLE_AROUND_ANCHOR = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_circle_around_anchor")); -+ GoalKey PHANTOM_SWEEP_ATTACK = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_sweep_attack")); -+ /** -+ * @deprecated removed in 1.16 -+ */ -+ @Deprecated -+ GoalKey ANGER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger")); -+ /** -+ * @deprecated removed in 1.16 -+ */ -+ @Deprecated -+ GoalKey ANGER_OTHER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger_other")); -+ GoalKey POLARBEAR_ATTACK_PLAYERS = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_attack_players")); -+ GoalKey POLARBEAR_HURT_BY = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_hurt_by")); -+ GoalKey POLARBEAR_MELEE = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_melee")); -+ GoalKey POLARBEAR_PANIC = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_panic")); -+ GoalKey PUFFERFISH_PUFF = GoalKey.of(PufferFish.class, NamespacedKey.minecraft("pufferfish_puff")); -+ GoalKey EAT_CARROTS = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("eat_carrots")); -+ GoalKey KILLER_RABBIT_MELEE_ATTACK = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("killer_rabbit_melee_attack")); -+ GoalKey RABBIT_AVOID_TARGET = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_avoid_target")); -+ GoalKey RABBIT_PANIC = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_panic")); -+ GoalKey RAIDER_HOLD_GROUND = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_hold_ground")); -+ GoalKey RAIDER_OBTAIN_BANNER = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_obtain_banner")); -+ GoalKey RAIDER_CELEBRATION = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_celebration")); -+ GoalKey RAIDER_MOVE_THROUGH_VILLAGE = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_move_through_village")); -+ GoalKey RAVAGER_MELEE_ATTACK = GoalKey.of(Ravager.class, NamespacedKey.minecraft("ravager_melee_attack")); -+ GoalKey SHULKER_ATTACK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_attack")); -+ GoalKey SHULKER_DEFENSE = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_defense")); -+ GoalKey SHULKER_NEAREST = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_nearest")); -+ GoalKey SHULKER_PEEK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_peek")); -+ GoalKey SILVERFISH_HIDE_IN_BLOCK = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_hide_in_block")); -+ GoalKey SILVERFISH_WAKE_OTHERS = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_wake_others")); -+ GoalKey SKELETON_MELEE = GoalKey.of(Skeleton.class, NamespacedKey.minecraft("skeleton_melee")); -+ GoalKey SLIME_IDLE = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_idle")); -+ GoalKey SLIME_NEAREST_PLAYER = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_nearest_player")); -+ GoalKey SLIME_RANDOM_DIRECTION = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_direction")); -+ GoalKey SLIME_RANDOM_JUMP = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_jump")); -+ GoalKey SPIDER_MELEE_ATTACK = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_melee_attack")); -+ GoalKey SPIDER_NEAREST_ATTACKABLE_TARGET = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_nearest_attackable_target")); -+ GoalKey STRIDER_GO_TO_LAVA = GoalKey.of(Strider.class, NamespacedKey.minecraft("strider_go_to_lava")); -+ GoalKey SQUID = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid")); -+ GoalKey SQUID_FLEE = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid_flee")); -+ GoalKey TURTLE_BREED = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_breed")); -+ GoalKey TURTLE_GO_HOME = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_go_home")); -+ GoalKey TURTLE_GOTO_WATER = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_goto_water")); -+ GoalKey TURTLE_LAY_EGG = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_lay_egg")); -+ GoalKey TURTLE_PANIC = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_panic")); -+ GoalKey TURTLE_RANDOM_STROLL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_random_stroll")); -+ GoalKey TURTLE_TEMPT = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_tempt")); -+ GoalKey TURTLE_TRAVEL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_travel")); -+ GoalKey VEX_CHARGE_ATTACK = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_charge_attack")); -+ GoalKey VEX_COPY_TARGET_OF_OWNER = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_copy_target_of_owner")); -+ GoalKey VEX_RANDOM_MOVE = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_random_move")); -+ GoalKey VILLAGERTRADER_WANDER_TO_POSITION = GoalKey.of(WanderingTrader.class, NamespacedKey.minecraft("villagertrader_wander_to_position")); -+ GoalKey VINDICATOR_BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("vindicator_break_door")); -+ GoalKey VINDICATOR_JOHNNY_ATTACK = GoalKey.of(Vindicator.class, NamespacedKey.minecraft("vindicator_johnny_attack")); -+ GoalKey VINDICATOR_MELEE_ATTACK = GoalKey.of(Vindicator.class, NamespacedKey.minecraft("vindicator_melee_attack")); -+ GoalKey WITHER_DO_NOTHING = GoalKey.of(Wither.class, NamespacedKey.minecraft("wither_do_nothing")); -+ GoalKey WOLF_AVOID_ENTITY = GoalKey.of(Wolf.class, NamespacedKey.minecraft("wolf_avoid_entity")); -+ GoalKey ZOMBIE_ATTACK_TURTLE_EGG = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack_turtle_egg")); -+ GoalKey ARROW_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("arrow_attack")); -+ GoalKey AVOID_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("avoid_target")); -+ GoalKey BEG = GoalKey.of(Wolf.class, NamespacedKey.minecraft("beg")); -+ GoalKey BOW_SHOOT = GoalKey.of(Monster.class, NamespacedKey.minecraft("bow_shoot")); -+ GoalKey BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("break_door")); -+ GoalKey BREATH = GoalKey.of(Creature.class, NamespacedKey.minecraft("breath")); -+ GoalKey BREED = GoalKey.of(Animals.class, NamespacedKey.minecraft("breed")); -+ GoalKey CAT_SIT_ON_BED = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_sit_on_bed")); -+ GoalKey CROSSBOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("crossbow_attack")); -+ GoalKey DEFEND_VILLAGE = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("defend_village")); -+ GoalKey DOOR_OPEN = GoalKey.of(Mob.class, NamespacedKey.minecraft("door_open")); -+ GoalKey EAT_TILE = GoalKey.of(Mob.class, NamespacedKey.minecraft("eat_tile")); -+ GoalKey FISH_SCHOOL = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_school")); -+ GoalKey FLEE_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("flee_sun")); -+ GoalKey FLOAT = GoalKey.of(Mob.class, NamespacedKey.minecraft("float")); -+ GoalKey FOLLOW_BOAT = GoalKey.of(Creature.class, NamespacedKey.minecraft("follow_boat")); -+ GoalKey FOLLOW_ENTITY = GoalKey.of(Mob.class, NamespacedKey.minecraft("follow_entity")); -+ GoalKey FOLLOW_OWNER = GoalKey.of(Tameable.class, NamespacedKey.minecraft("follow_owner")); -+ GoalKey FOLLOW_PARENT = GoalKey.of(Animals.class, NamespacedKey.minecraft("follow_parent")); -+ GoalKey HORSE_TRAP = GoalKey.of(SkeletonHorse.class, NamespacedKey.minecraft("horse_trap")); -+ GoalKey HURT_BY_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("hurt_by_target")); -+ GoalKey INTERACT = GoalKey.of(Mob.class, NamespacedKey.minecraft("interact")); -+ GoalKey JUMP_ON_BLOCK = GoalKey.of(Cat.class, NamespacedKey.minecraft("jump_on_block")); -+ GoalKey LEAP_AT_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("leap_at_target")); -+ GoalKey LLAMA_FOLLOW = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_follow")); -+ GoalKey LOOK_AT_PLAYER = GoalKey.of(Mob.class, NamespacedKey.minecraft("look_at_player")); -+ GoalKey LOOK_AT_TRADING_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("look_at_trading_player")); -+ GoalKey MELEE_ATTACK = GoalKey.of(Creature.class, NamespacedKey.minecraft("melee_attack")); -+ GoalKey MOVE_THROUGH_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_through_village")); -+ GoalKey MOVE_TOWARDS_RESTRICTION = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_restriction")); -+ GoalKey MOVE_TOWARDS_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_target")); -+ GoalKey NEAREST_ATTACKABLE_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("nearest_attackable_target")); -+ GoalKey NEAREST_ATTACKABLE_TARGET_WITCH = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_attackable_target_witch")); -+ GoalKey NEAREST_HEALABLE_RAIDER = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_healable_raider")); -+ GoalKey NEAREST_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("nearest_village")); -+ GoalKey OCELOT_ATTACK = GoalKey.of(Mob.class, NamespacedKey.minecraft("ocelot_attack")); -+ GoalKey OFFER_FLOWER = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("offer_flower")); -+ GoalKey OWNER_HURT_BY_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_by_target")); -+ GoalKey OWNER_HURT_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_target")); -+ GoalKey PANIC = GoalKey.of(Creature.class, NamespacedKey.minecraft("panic")); -+ GoalKey PERCH = GoalKey.of(Parrot.class, NamespacedKey.minecraft("perch")); -+ GoalKey RAID = GoalKey.of(Raider.class, NamespacedKey.minecraft("raid")); -+ GoalKey RANDOM_FLY = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_fly")); -+ GoalKey RANDOM_LOOKAROUND = GoalKey.of(Mob.class, NamespacedKey.minecraft("random_lookaround")); -+ GoalKey RANDOM_STROLL = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll")); -+ GoalKey RANDOM_STROLL_LAND = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll_land")); -+ GoalKey RANDOM_SWIM = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_swim")); -+ GoalKey RANDOM_TARGET_NON_TAMED = GoalKey.of(Tameable.class, NamespacedKey.minecraft("random_target_non_tamed")); -+ GoalKey REMOVE_BLOCK = GoalKey.of(Creature.class, NamespacedKey.minecraft("remove_block")); -+ GoalKey RESTRICT_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("restrict_sun")); -+ GoalKey SIT = GoalKey.of(Tameable.class, NamespacedKey.minecraft("sit")); -+ GoalKey STROLL_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village")); -+ GoalKey SWELL = GoalKey.of(Creeper.class, NamespacedKey.minecraft("swell")); -+ GoalKey TAME = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("tame")); -+ GoalKey TEMPT = GoalKey.of(Creature.class, NamespacedKey.minecraft("tempt")); -+ GoalKey TRADE_WITH_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("trade_with_player")); -+ GoalKey USE_ITEM = GoalKey.of(Mob.class, NamespacedKey.minecraft("use_item")); -+ GoalKey WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("water")); -+ GoalKey WATER_JUMP = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("water_jump")); -+ GoalKey ZOMBIE_ATTACK = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack")); -+ GoalKey STROLL_VILLAGE_GOLEM = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village_golem")); -+ GoalKey UNIVERSAL_ANGER_RESET = GoalKey.of(Mob.class, NamespacedKey.minecraft("universal_anger_reset")); -+} -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index bbf15311a48ba96e14ffa2ab9d59613e79f06618..4cffbc4f665e267371e99094e8b7de975fffc223 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1879,6 +1879,16 @@ public final class Bukkit { - public static boolean isStopping() { - return server.isStopping(); - } -+ -+ /** -+ * Returns the {@link com.destroystokyo.paper.entity.ai.MobGoals} manager -+ * -+ * @return the mob goals manager -+ */ -+ @NotNull -+ public static com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { -+ return server.getMobGoals(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 21ebe1e70a4b9df54a5c730cee6d024cc1358b88..969cba46ba2790dde32724111ad77332c5872e0b 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1648,5 +1648,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @return true if server is in the process of being shutdown - */ - boolean isStopping(); -+ -+ /** -+ * Returns the {@link com.destroystokyo.paper.entity.ai.MobGoals} manager -+ * -+ * @return the mob goals manager -+ */ -+ @NotNull -+ com.destroystokyo.paper.entity.ai.MobGoals getMobGoals(); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0201-World-view-distance-api.patch b/Unmapped-Spigot-API-Patches/0201-World-view-distance-api.patch deleted file mode 100644 index 17a9a94f12..0000000000 --- a/Unmapped-Spigot-API-Patches/0201-World-view-distance-api.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 21:28:01 -0700 -Subject: [PATCH] World view distance api - - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 7bf85151efddcbd561afb0fb2d423aa97ac176c1..61dfb057d94d89477d11b9e8d4be7c16032e25a9 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -3447,6 +3447,34 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - int getViewDistance(); - // Spigot end - -+ // Paper start - view distance api -+ /** -+ * Sets the view distance for this world. -+ * @param viewDistance view distance in [2, 32] -+ */ -+ void setViewDistance(int viewDistance); -+ -+ /** -+ * Returns the no-tick view distance for this world. -+ *

    -+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not -+ * be set to tick. -+ *

    -+ * @return The no-tick view distance for this world. -+ */ -+ int getNoTickViewDistance(); -+ -+ /** -+ * Sets the no-tick view distance for this world. -+ *

    -+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not -+ * be set to tick. -+ *

    -+ * @param viewDistance view distance in [2, 32] -+ */ -+ void setNoTickViewDistance(int viewDistance); -+ // Paper end - view distance api -+ - // Spigot start - public class Spigot { - diff --git a/Unmapped-Spigot-API-Patches/0202-Add-villager-reputation-API.patch b/Unmapped-Spigot-API-Patches/0202-Add-villager-reputation-API.patch deleted file mode 100644 index cef4ea6027..0000000000 --- a/Unmapped-Spigot-API-Patches/0202-Add-villager-reputation-API.patch +++ /dev/null @@ -1,177 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 22 Apr 2020 23:13:49 +0200 -Subject: [PATCH] Add villager reputation API - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/Reputation.java b/src/main/java/com/destroystokyo/paper/entity/villager/Reputation.java -new file mode 100644 -index 0000000000000000000000000000000000000000..1cc9ef255df888cb7dd7f7f2c5014e818d1be613 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/villager/Reputation.java -@@ -0,0 +1,54 @@ -+package com.destroystokyo.paper.entity.villager; -+ -+import com.google.common.base.Preconditions; -+import java.util.Map; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * A reputation score for a player on a villager. -+ */ -+public final class Reputation { -+ private static final ReputationType[] REPUTATION_TYPES = ReputationType.values(); // Avoid allocation -+ @NotNull -+ private final int[] reputation; -+ -+ public Reputation() { -+ this(new int[REPUTATION_TYPES.length]); -+ } -+ -+ // Package level to avoid plugins creating reputations with "magic values". -+ Reputation(@NotNull int[] reputation) { -+ this.reputation = reputation; -+ } -+ -+ public Reputation(@NotNull final Map reputation) { -+ this(); -+ Preconditions.checkNotNull(reputation, "reputation cannot be null"); -+ -+ for (Map.Entry entry : reputation.entrySet()) { -+ setReputation(entry.getKey(), entry.getValue()); -+ } -+ } -+ -+ /** -+ * Gets the reputation value for a specific {@link ReputationType}. -+ * -+ * @param type The {@link ReputationType type} of reputation to get. -+ * @return The value of the {@link ReputationType type}. -+ */ -+ public int getReputation(@NotNull ReputationType type) { -+ Preconditions.checkNotNull(type, "the reputation type cannot be null"); -+ return reputation[type.ordinal()]; -+ } -+ -+ /** -+ * Sets the reputation value for a specific {@link ReputationType}. -+ * -+ * @param type The {@link ReputationType type} of reputation to set. -+ * @param value The value of the {@link ReputationType type}. -+ */ -+ public void setReputation(@NotNull ReputationType type, int value) { -+ Preconditions.checkNotNull(type, "the reputation type cannot be null"); -+ reputation[type.ordinal()] = value; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/ReputationType.java b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationType.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5600fcdc9795a9f49091db48d73bbd4964b8b737 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationType.java -@@ -0,0 +1,36 @@ -+package com.destroystokyo.paper.entity.villager; -+ -+/** -+ * A type of reputation gained with a {@link org.bukkit.entity.Villager Villager}. -+ *

    -+ * All types but {@link #MAJOR_POSITIVE} are shared to other villagers. -+ */ -+public enum ReputationType { -+ /** -+ * A gossip with a majorly negative effect. This is only gained through killing a nearby -+ * villager. -+ */ -+ MAJOR_NEGATIVE, -+ -+ /** -+ * A gossip with a minor negative effect. This is only gained through damaging a villager. -+ */ -+ MINOR_NEGATIVE, -+ -+ /** -+ * A gossip with a minor positive effect. This is only gained through curing a zombie -+ * villager. -+ */ -+ MINOR_POSITIVE, -+ -+ /** -+ * A gossip with a major positive effect. This is only gained through curing a zombie -+ * villager. -+ */ -+ MAJOR_POSITIVE, -+ -+ /** -+ * A gossip with a minor positive effect. This is only gained through trading with a villager. -+ */ -+ TRADING, -+} -diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java -index d1579153092c1b80350155110f1b9926b1a1ef57..c8777a476e38ef5e72b6709761990a339eb43d2b 100644 ---- a/src/main/java/org/bukkit/entity/Villager.java -+++ b/src/main/java/org/bukkit/entity/Villager.java -@@ -1,10 +1,13 @@ - package org.bukkit.entity; - - import java.util.Locale; -+import java.util.Map; // Paper -+import java.util.UUID; // Paper - import org.bukkit.Keyed; - import org.bukkit.Location; - import org.bukkit.NamespacedKey; - import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; // Paper - - /** - * Represents a villager NPC -@@ -224,4 +227,50 @@ public interface Villager extends AbstractVillager { - return key; - } - } -+ -+ // Paper start - Add villager reputation API -+ /** -+ * Get the {@link com.destroystokyo.paper.entity.villager.Reputation reputation} -+ * for a specific player by {@link UUID}. -+ * -+ * @param uniqueId The {@link UUID} of the player to get the reputation of. -+ * @return The player's copied reputation with this villager. -+ */ -+ @Nullable -+ public com.destroystokyo.paper.entity.villager.Reputation getReputation(@NotNull UUID uniqueId); -+ -+ /** -+ * Get all {@link com.destroystokyo.paper.entity.villager.Reputation reputations} -+ * for all players mapped by their {@link UUID unique IDs}. -+ * -+ * @return All {@link com.destroystokyo.paper.entity.villager.Reputation reputations} for all players -+ * in a copied map. -+ */ -+ @NotNull -+ public Map getReputations(); -+ -+ /** -+ * Set the {@link com.destroystokyo.paper.entity.villager.Reputation reputation} -+ * for a specific player by {@link UUID}. -+ * -+ * @param uniqueId The {@link UUID} of the player to set the reputation of. -+ * @param reputation The {@link com.destroystokyo.paper.entity.villager.Reputation reputation} to set. -+ */ -+ public void setReputation(@NotNull UUID uniqueId, @NotNull com.destroystokyo.paper.entity.villager.Reputation reputation); -+ -+ /** -+ * Set all {@link com.destroystokyo.paper.entity.villager.Reputation reputations} -+ * for all players mapped by their {@link UUID unique IDs}. -+ * -+ * @param reputations All {@link com.destroystokyo.paper.entity.villager.Reputation reputations} -+ * for all players mapped by their {@link UUID unique IDs}. -+ */ -+ public void setReputations(@NotNull Map reputations); -+ -+ /** -+ * Clear all reputations from this villager. This removes every single -+ * reputation regardless of its impact and the player associated. -+ */ -+ public void clearReputations(); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0203-Spawn-Reason-API.patch b/Unmapped-Spigot-API-Patches/0203-Spawn-Reason-API.patch deleted file mode 100644 index 0ee08ee996..0000000000 --- a/Unmapped-Spigot-API-Patches/0203-Spawn-Reason-API.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 10 Apr 2014 23:18:28 -0400 -Subject: [PATCH] Spawn Reason API - - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 476184db904d8a2e1347e1219e8ba196bf4da5cb..c1010e314144a65e12eaf5514d639a87f45891a9 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -1,6 +1,8 @@ - package org.bukkit; - - import java.io.File; -+ -+import org.bukkit.event.entity.CreatureSpawnEvent; - import org.bukkit.generator.ChunkGenerator; - - import java.util.ArrayList; -@@ -2249,6 +2251,12 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @NotNull - public T spawn(@NotNull Location location, @NotNull Class clazz) throws IllegalArgumentException; - -+ // Paper start -+ @NotNull -+ public default T spawn(@NotNull Location location, @NotNull Class clazz, @NotNull CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException { -+ return spawn(location, clazz, reason, null); -+ } -+ - /** - * Spawn an entity of a specific class at the given {@link Location}, with - * the supplied function run before the entity is added to the world. -@@ -2266,7 +2274,28 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - * {@link Entity} requested cannot be spawned - */ - @NotNull -- public T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function) throws IllegalArgumentException; -+ public default T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function) throws IllegalArgumentException { -+ return spawn(location, clazz, CreatureSpawnEvent.SpawnReason.CUSTOM, function); -+ } -+ -+ @NotNull -+ public default T spawn(@NotNull Location location, @NotNull Class clazz, @NotNull CreatureSpawnEvent.SpawnReason reason, @Nullable Consumer function) throws IllegalArgumentException { -+ return spawn(location, clazz, function, reason); -+ } -+ -+ @NotNull -+ public default Entity spawnEntity(@NotNull Location loc, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason) { -+ return spawn(loc, (Class) type.getEntityClass(), reason, null); -+ } -+ -+ @NotNull -+ public default Entity spawnEntity(@NotNull Location loc, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason, @Nullable Consumer function) { -+ return spawn(loc, (Class) type.getEntityClass(), reason, function); -+ } -+ -+ @NotNull -+ public T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function, @NotNull CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException; -+ // Paper end - - /** - * Spawn a {@link FallingBlock} entity at the given {@link Location} of diff --git a/Unmapped-Spigot-API-Patches/0204-Potential-bed-API.patch b/Unmapped-Spigot-API-Patches/0204-Potential-bed-API.patch deleted file mode 100644 index b8b1e2519a..0000000000 --- a/Unmapped-Spigot-API-Patches/0204-Potential-bed-API.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Sun, 10 May 2020 23:06:41 -0400 -Subject: [PATCH] Potential bed API - -Adds a new method to fetch the location of a player's bed without generating any sync loads. - -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 3418133d07250a7fd50caad8d97924b86fb30bad..b09d12390d5f77330ac84452e0fee63a169bd01f 100644 ---- a/src/main/java/org/bukkit/entity/HumanEntity.java -+++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -240,6 +240,19 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder - */ - public int getSleepTicks(); - -+ -+ // Paper start - Potential bed api -+ /** -+ * Gets the Location of the player's bed, null if they have not slept -+ * in one. This method will not attempt to validate if the current bed -+ * is still valid. -+ * -+ * @return Bed Location if has slept in one, otherwise null. -+ */ -+ @Nullable -+ public Location getPotentialBedLocation(); -+ // Paper end -+ - /** - * Attempts to make the entity sleep at the given location. - *
    diff --git a/Unmapped-Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch b/Unmapped-Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch deleted file mode 100644 index be1c895ad7..0000000000 --- a/Unmapped-Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Mon, 27 Apr 2020 12:31:59 +0200 -Subject: [PATCH] Prioritise own classes where possible - -This adds the server property `Paper.DisableClassPrioritization` to disable -prioritization of own classes for plugins' classloaders. - -This value is by default not present, and this will therefore break any -plugins which abuse behaviour related to not using their own classes -while still loading their own. This is often an issue with failing to -relocate or shade properly, such as when shading plugin APIs like Vault. - -A plugin's classloader will first look in the same jar as it is loading -in for a requested class, then load it. It does not re-use other -plugins' classes if it has the chance to avoid doing so. - -If a class is not found in the same jar as it is loading for and it does -find it elsewhere, it will still choose the class elsewhere. This is -intended behaviour, as it will only prioritise classes it has in its own -jar, no other plugins' classes will be prioritised in any other order -than the one they were registered in. - -The patch in general terms just loads the class in the plugin's jar -before it starts looking elsewhere for it. - -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index ce751577623eaad0f31e2eb7bf0842d1ab73e845..31793f46e5623729dfb4048e901f274082f57826 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -51,6 +51,7 @@ import org.yaml.snakeyaml.error.YAMLException; - */ - public final class JavaPluginLoader implements PluginLoader { - final Server server; -+ private static final boolean DISABLE_CLASS_PRIORITIZATION = Boolean.getBoolean("Paper.DisableClassPrioritization"); // Paper - private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; - private final Map classLoadLock = new java.util.HashMap(); // Paper - private final Map classLoadLockCount = new java.util.HashMap(); // Paper -@@ -203,6 +204,11 @@ public final class JavaPluginLoader implements PluginLoader { - - @Nullable - Class getClassByName(final String name, boolean resolve, PluginDescriptionFile description) { -+ // Paper start - prioritize self -+ return getClassByName(name, resolve, description, null); -+ } -+ Class getClassByName(final String name, boolean resolve, PluginDescriptionFile description, PluginClassLoader requester) { -+ // Paper end - // Paper start - make MT safe - java.util.concurrent.locks.ReentrantReadWriteLock lock; - synchronized (classLoadLock) { -@@ -210,6 +216,13 @@ public final class JavaPluginLoader implements PluginLoader { - classLoadLockCount.compute(name, (x, prev) -> prev != null ? prev + 1 : 1); - } - lock.writeLock().lock();try { -+ // Paper start - prioritize self -+ if (!DISABLE_CLASS_PRIORITIZATION && requester != null) { -+ try { -+ return requester.loadClass0(name, false, false, ((SimplePluginManager) server.getPluginManager()).isTransitiveDepend(description, requester.getDescription())); -+ } catch (ClassNotFoundException cnfe) {} -+ } -+ // Paper end - // Paper end - for (PluginClassLoader loader : loaders) { - try { -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index b9766b9b47547c400ed075f1635bb1461cb5e860..87016d01640d8ea86b93cf2f7ead4c88b6d9d778 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -33,7 +33,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - public JavaPlugin getPlugin() { return plugin; } // Spigot - private final JavaPluginLoader loader; - private final Map> classes = new ConcurrentHashMap>(); -- private final PluginDescriptionFile description; -+ private final PluginDescriptionFile description; PluginDescriptionFile getDescription() { return description; } // Paper - private final File dataFolder; - private final File file; - private final JarFile jar; -@@ -118,7 +118,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - - if (checkGlobal) { - // This ignores the libraries of other plugins, unless they are transitive dependencies. -- Class result = loader.getClassByName(name, resolve, description); -+ Class result = loader.getClassByName(name, resolve, description, this); // Paper - prioritize self - - // If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check. - if (result != null && result.getClassLoader() instanceof PluginClassLoader) { diff --git a/Unmapped-Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch b/Unmapped-Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch deleted file mode 100644 index 8ffb283fa6..0000000000 --- a/Unmapped-Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Thu, 30 Apr 2020 16:56:31 +0200 -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 d6897f43a0692e031bed8a212d9a637ef548cc60..e348034288c74ab80360086d71f0b7f61551df24 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -97,5 +97,9 @@ public interface UnsafeValues { - static boolean isLegacyPlugin(org.bukkit.plugin.Plugin plugin) { - return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); - } -+ -+ byte[] serializeItem(ItemStack item); -+ -+ ItemStack deserializeItem(byte[] data); - // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index bf39989dbe08c93120d75bed6281ae75c460afca..15b48ad1ba5bcf7394fb3f52ce2cc6baa6632f66 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -628,6 +628,30 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - return Bukkit.getServer().getItemFactory().ensureServerConversions(this); - } - -+ /** -+ * Deserializes this itemstack from raw NBT bytes. NBT is safer for data migrations as it will -+ * use the built in data converter instead of bukkits dangerous serialization system. -+ * -+ * This expects that the DataVersion was stored on the root of the Compound, as saved from -+ * the {@link #serializeAsBytes()} API returned. -+ * @param bytes bytes representing an item in NBT -+ * @return ItemStack migrated to this version of Minecraft if needed. -+ */ -+ @NotNull -+ public static ItemStack deserializeBytes(@NotNull byte[] bytes) { -+ return org.bukkit.Bukkit.getUnsafe().deserializeItem(bytes); -+ } -+ -+ /** -+ * Serializes this itemstack to raw bytes in NBT. NBT is safer for data migrations as it will -+ * use the built in data converter instead of bukkits dangerous serialization system. -+ * @return bytes representing this item in NBT. -+ */ -+ @NotNull -+ public byte[] serializeAsBytes() { -+ return org.bukkit.Bukkit.getUnsafe().serializeItem(this); -+ } -+ - /** - * Gets the Display name as seen in the Client. - * Currently the server only supports the English language. To override this, diff --git a/Unmapped-Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch b/Unmapped-Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch deleted file mode 100644 index f993bdc2b7..0000000000 --- a/Unmapped-Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 31 May 2020 15:26:17 +0100 -Subject: [PATCH] Provide a useful PluginClassLoader#toString - -There are several cases where the plugin classloader may be dumped to the logs, -however, this provides no indication of the owner of the classloader, making -these messages effectively useless, this patch rectifies this - -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 87016d01640d8ea86b93cf2f7ead4c88b6d9d778..cb62666d14a8eeb6338ecef75d57a1946cfa99a4 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -228,4 +228,16 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - javaPlugin.logger = this.logger; // Paper - set logger - javaPlugin.init(loader, loader.server, description, dataFolder, file, this); - } -+ -+ // Paper start -+ @Override -+ public String toString() { -+ JavaPlugin currPlugin = plugin != null ? plugin : pluginInit; -+ return "PluginClassLoader{" + -+ "plugin=" + currPlugin + -+ ", pluginEnabled=" + (currPlugin == null ? "uninitialized" : currPlugin.isEnabled()) + -+ ", url=" + file + -+ '}'; -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch b/Unmapped-Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch deleted file mode 100644 index 5b633e50af..0000000000 --- a/Unmapped-Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Wed, 10 Jun 2020 23:55:16 +0100 -Subject: [PATCH] Inventory getHolder method without block snapshot - - -diff --git a/src/main/java/org/bukkit/block/DoubleChest.java b/src/main/java/org/bukkit/block/DoubleChest.java -index 83a4642119c3f33749e04c774cf2b39839f797e2..a39d2f1acbbd84ae0e2cf29f85594e09e55e9355 100644 ---- a/src/main/java/org/bukkit/block/DoubleChest.java -+++ b/src/main/java/org/bukkit/block/DoubleChest.java -@@ -34,6 +34,18 @@ public class DoubleChest implements InventoryHolder { - return inventory.getRightSide().getHolder(); - } - -+ // Paper start - getHolder without snapshot -+ @Nullable -+ public InventoryHolder getLeftSide(boolean useSnapshot) { -+ return inventory.getLeftSide().getHolder(useSnapshot); -+ } -+ -+ @Nullable -+ public InventoryHolder getRightSide(boolean useSnapshot) { -+ return inventory.getRightSide().getHolder(useSnapshot); -+ } -+ // Paper end -+ - @NotNull - public Location getLocation() { - return getInventory().getLocation(); -diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java -index 9c6a5bdac8c3ab682bbfae04ff24b76a62bc2883..6386206188e820206bb1a9f516b5e194fdc9d952 100644 ---- a/src/main/java/org/bukkit/inventory/Inventory.java -+++ b/src/main/java/org/bukkit/inventory/Inventory.java -@@ -384,6 +384,17 @@ public interface Inventory extends Iterable { - @Nullable - public InventoryHolder getHolder(); - -+ // Paper start - getHolder without snapshot -+ /** -+ * Gets the block or entity belonging to the open inventory -+ * -+ * @param useSnapshot Create a snapshot if the holder is a tile entity -+ * @return The holder of the inventory; null if it has no holder. -+ */ -+ @Nullable -+ public InventoryHolder getHolder(boolean useSnapshot); -+ // Paper end -+ - @NotNull - @Override - public ListIterator iterator(); diff --git a/Unmapped-Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch b/Unmapped-Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch deleted file mode 100644 index e718e0e598..0000000000 --- a/Unmapped-Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nesaak <52047222+Nesaak@users.noreply.github.com> -Date: Fri, 22 May 2020 13:35:21 -0400 -Subject: [PATCH] Expose Arrow getItemStack - - -diff --git a/src/main/java/org/bukkit/entity/AbstractArrow.java b/src/main/java/org/bukkit/entity/AbstractArrow.java -index e8e56e89e32d84af0639fe2e9b0eeabd747b6007..b1d8007eed489aa061c1a6813bcdafc101231e56 100644 ---- a/src/main/java/org/bukkit/entity/AbstractArrow.java -+++ b/src/main/java/org/bukkit/entity/AbstractArrow.java -@@ -143,6 +143,14 @@ public interface AbstractArrow extends Projectile { - } - - // Paper start -+ /** -+ * Gets the ItemStack for this arrow. -+ * -+ * @return The ItemStack, as if a player picked up the arrow -+ */ -+ @NotNull -+ org.bukkit.inventory.ItemStack getItemStack(); -+ - /** - * Gets the {@link PickupRule} for this arrow. - * diff --git a/Unmapped-Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch b/Unmapped-Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch deleted file mode 100644 index 93bd233b85..0000000000 --- a/Unmapped-Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: LordKorea -Date: Mon, 11 May 2020 22:38:10 -0400 -Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerRecipeBookClickEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerRecipeBookClickEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7fa937d339ee98ad308deebb523fead6522eb262 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerRecipeBookClickEvent.java -@@ -0,0 +1,84 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.NamespacedKey; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player clicks a recipe in the recipe book -+ */ -+public class PlayerRecipeBookClickEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancel = false; -+ @NotNull private NamespacedKey recipe; -+ private boolean makeAll; -+ -+ public PlayerRecipeBookClickEvent(@NotNull Player player, @NotNull NamespacedKey recipe, boolean makeAll) { -+ super(player); -+ this.recipe = recipe; -+ this.makeAll = makeAll; -+ } -+ -+ /** -+ * Gets the namespaced key of the recipe that was clicked by the player -+ * -+ * @return The namespaced key of the recipe -+ */ -+ @NotNull -+ public NamespacedKey getRecipe() { -+ return recipe; -+ } -+ -+ /** -+ * Changes what recipe is requested. This sets the requested recipe to the recipe with the given key -+ * -+ * @param recipe The key of the recipe that should be requested -+ */ -+ public void setRecipe(@NotNull NamespacedKey recipe) { -+ this.recipe = recipe; -+ } -+ -+ /** -+ * Gets a boolean which indicates whether or not the player requested to make the maximum amount of results. This is -+ * true if shift is pressed while the recipe is clicked in the recipe book -+ * -+ * @return {@code true} if shift is pressed while the recipe is clicked -+ */ -+ public boolean isMakeAll() { -+ return makeAll; -+ } -+ -+ /** -+ * Sets whether or not the maximum amount of results should be made. If this is true, the request is handled as if -+ * the player had pressed shift while clicking on the recipe -+ * -+ * @param makeAll {@code true} if the request should attempt to make the maximum amount of results -+ */ -+ public void setMakeAll(boolean makeAll) { -+ this.makeAll = makeAll; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancel; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancel = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch b/Unmapped-Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch deleted file mode 100644 index 1b51f21c69..0000000000 --- a/Unmapped-Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Sat, 6 Jun 2020 18:13:16 +0200 -Subject: [PATCH] Support components in ItemMeta - - -diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -index 01b462fccce71cef3398dd43944046f322b8e57e..f093f991f1fedd20fcef041b093398250b7fb286 100644 ---- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -+++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -@@ -5,6 +5,7 @@ import java.util.Collection; - import java.util.List; - import java.util.Map; - import java.util.Set; -+import net.kyori.adventure.text.Component; - import org.bukkit.attribute.Attribute; - import org.bukkit.attribute.AttributeModifier; - import org.bukkit.configuration.serialization.ConfigurationSerializable; -@@ -62,6 +63,20 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - @NotNull - String getDisplayName(); - -+ // Paper start -+ /** -+ * Gets the display name that is set. -+ *

    -+ * Plugins should check that hasDisplayName() returns true -+ * before calling this method. -+ * -+ * @return the display name that is set -+ * @deprecated use {@link #displayName()} -+ */ -+ @NotNull -+ @Deprecated -+ net.md_5.bungee.api.chat.BaseComponent[] getDisplayNameComponent(); -+ // Paper end - /** - * Sets the display name. - * -@@ -71,6 +86,16 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - @Deprecated // Paper - void setDisplayName(@Nullable String name); - -+ // Paper start -+ /** -+ * Sets the display name. -+ * -+ * @param component the name component to set -+ * @deprecated use {@link #displayName(Component)} -+ */ -+ @Deprecated -+ void setDisplayNameComponent(@Nullable net.md_5.bungee.api.chat.BaseComponent[] component); -+ // Paper end - /** - * Checks for existence of a localized name. - * -@@ -134,6 +159,19 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - @Nullable - List getLore(); - -+ /** -+ * Gets the lore that is set. -+ *

    -+ * Plugins should check if hasLore() returns true before -+ * calling this method. -+ * -+ * @return a list of lore that is set -+ * @deprecated use {@link #lore()} -+ */ -+ @Nullable -+ @Deprecated -+ List getLoreComponents(); -+ - /** - * Sets the lore for this item. - * Removes lore when given null. -@@ -144,6 +182,16 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - @Deprecated // Paper - void setLore(@Nullable List lore); - -+ /** -+ * Sets the lore for this item. -+ * Removes lore when given null. -+ * -+ * @param lore the lore that will be set -+ * @deprecated use {@link #lore(List)} -+ */ -+ @Deprecated -+ void setLoreComponents(@Nullable List lore); -+ - /** - * Checks for existence of custom model data. - *

    diff --git a/Unmapped-Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch b/Unmapped-Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch deleted file mode 100644 index 747470a546..0000000000 --- a/Unmapped-Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 3 Jul 2020 15:05:54 -0700 -Subject: [PATCH] added 2 new TargetReasons for 1.16 mob behavior - - -diff --git a/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java b/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java -index dee186e99463a56394bbc2039d1e763d109125b9..601904150156d475c18286b485f3409307a75950 100644 ---- a/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java -+++ b/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java -@@ -159,6 +159,14 @@ public class EntityTargetEvent extends EntityEvent implements Cancellable { - * as wheat in it's hand. - */ - TEMPT, -+ /** -+ * When the target is in a different dimension -+ */ -+ TARGET_OTHER_LEVEL, // Paper -+ /** -+ * When the target is in creative or spectator mode, or the gamemode is peaceful, or other reasons -+ */ -+ TARGET_INVALID, // Paper - /** - * A currently unknown reason for the entity changing target. - */ diff --git a/Unmapped-Spigot-API-Patches/0213-Add-entity-liquid-API.patch b/Unmapped-Spigot-API-Patches/0213-Add-entity-liquid-API.patch deleted file mode 100644 index c38113b716..0000000000 --- a/Unmapped-Spigot-API-Patches/0213-Add-entity-liquid-API.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jul 2020 18:11:33 -0500 -Subject: [PATCH] Add entity liquid API - - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 5b382091b1466b25ad42325d5808785a8e948552..ecb5595332ab493224d06a75904e142ab541aad9 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -714,5 +714,35 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - */ - @NotNull - org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason(); -+ -+ /** -+ * Check if entity is in rain -+ */ -+ public boolean isInRain(); -+ -+ /** -+ * Check if entity is in bubble column -+ */ -+ public boolean isInBubbleColumn(); -+ -+ /** -+ * Check if entity is in water or rain -+ */ -+ public boolean isInWaterOrRain(); -+ -+ /** -+ * Check if entity is in water or bubble column -+ */ -+ public boolean isInWaterOrBubbleColumn(); -+ -+ /** -+ * Check if entity is in water or rain or bubble column -+ */ -+ public boolean isInWaterOrRainOrBubbleColumn(); -+ -+ /** -+ * Check if entity is in lava -+ */ -+ public boolean isInLava(); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch b/Unmapped-Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch deleted file mode 100644 index 5dc61d601d..0000000000 --- a/Unmapped-Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch +++ /dev/null @@ -1,211 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 3 Jul 2020 11:58:56 -0500 -Subject: [PATCH] Add PrepareResultEvent / PrepareGrindstoneEvent - -Adds a new event for all crafting stations that generate a result slot item - -Anvil, Grindstone and Smithing now extend this event - -Grindstone is a backwards compat from a previous PrepareGrindstoneEvent - -diff --git a/src/main/java/com/destroystokyo/paper/event/inventory/PrepareGrindstoneEvent.java b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareGrindstoneEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..449e8c06f8434b59d49a76481fa60c5c49e80579 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareGrindstoneEvent.java -@@ -0,0 +1,28 @@ -+package com.destroystokyo.paper.event.inventory; -+ -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.inventory.InventoryEvent; -+import org.bukkit.inventory.GrindstoneInventory; -+import org.bukkit.inventory.InventoryView; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when an item is put in a slot for grinding in a Grindstone -+ * @see com.destroystokyo.paper.event.inventory.PrepareResultEvent -+ */ -+@Deprecated -+public class PrepareGrindstoneEvent extends PrepareResultEvent { -+ -+ public PrepareGrindstoneEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) { -+ super(inventory, result); -+ } -+ -+ @NotNull -+ @Override -+ public GrindstoneInventory getInventory() { -+ return (GrindstoneInventory) super.getInventory(); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/inventory/PrepareResultEvent.java b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareResultEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..045ce9ec3c9134aced5f5235b760ac85599d16c6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareResultEvent.java -@@ -0,0 +1,48 @@ -+package com.destroystokyo.paper.event.inventory; -+ -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.inventory.InventoryEvent; -+import org.bukkit.event.inventory.InventoryType; -+import org.bukkit.inventory.InventoryView; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when an item is put in an inventory containing a result slot -+ */ -+public class PrepareResultEvent extends InventoryEvent { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private ItemStack result; -+ -+ public PrepareResultEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) { -+ super(inventory); -+ this.result = result; -+ } -+ -+ /** -+ * Get result item, may be null. -+ * -+ * @return result item -+ */ -+ @Nullable -+ public ItemStack getResult() { -+ return result; -+ } -+ -+ public void setResult(@Nullable ItemStack result) { -+ this.result = result; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java b/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java -index 77109a07f07aa6985106dc1a9ad5218f6c7f360f..f1f6f4ab4f81a3f21e757fef4a30b00e94371f8d 100644 ---- a/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.inventory; - -+import com.destroystokyo.paper.event.inventory.PrepareResultEvent; - import org.bukkit.event.HandlerList; - import org.bukkit.inventory.AnvilInventory; - import org.bukkit.inventory.InventoryView; -@@ -10,14 +11,16 @@ import org.jetbrains.annotations.Nullable; - /** - * Called when an item is put in a slot for repair by an anvil. - */ --public class PrepareAnvilEvent extends InventoryEvent { -+// Paper start - extend PrepareResultEvent -+public class PrepareAnvilEvent extends PrepareResultEvent { - -- private static final HandlerList handlers = new HandlerList(); -- private ItemStack result; -+ //private static final HandlerList handlers = new HandlerList(); -+ //private ItemStack result; - - public PrepareAnvilEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) { -- super(inventory); -- this.result = result; -+ super(inventory, result); -+ //this.result = result; -+ // Paper end - } - - @NotNull -@@ -33,13 +36,14 @@ public class PrepareAnvilEvent extends InventoryEvent { - */ - @Nullable - public ItemStack getResult() { -- return result; -+ return super.getResult(); // Paper - } - - public void setResult(@Nullable ItemStack result) { -- this.result = result; -+ super.setResult(result); // Paper - } - -+ /* // Paper - comment out - @NotNull - @Override - public HandlerList getHandlers() { -@@ -50,4 +54,5 @@ public class PrepareAnvilEvent extends InventoryEvent { - public static HandlerList getHandlerList() { - return handlers; - } -+ */ // Paper - } -diff --git a/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java b/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java -index 99af1540324c4d68c5890ac40b591c5cbdd2e870..0bc0ca4f96c800e9c46c61710f44446691d8b93f 100644 ---- a/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.inventory; - -+import com.destroystokyo.paper.event.inventory.PrepareResultEvent; - import org.bukkit.event.HandlerList; - import org.bukkit.inventory.InventoryView; - import org.bukkit.inventory.ItemStack; -@@ -10,14 +11,16 @@ import org.jetbrains.annotations.Nullable; - /** - * Called when an item is put in a slot for upgrade by a Smithing Table. - */ --public class PrepareSmithingEvent extends InventoryEvent { -+// Paper start - extend PrepareResultEvent -+public class PrepareSmithingEvent extends PrepareResultEvent { - -- private static final HandlerList handlers = new HandlerList(); -- private ItemStack result; -+ //private static final HandlerList handlers = new HandlerList(); -+ //private ItemStack result; - - public PrepareSmithingEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) { -- super(inventory); -- this.result = result; -+ super(inventory, result); -+ //this.result = result; -+ // Paper end - } - - @NotNull -@@ -33,13 +36,14 @@ public class PrepareSmithingEvent extends InventoryEvent { - */ - @Nullable - public ItemStack getResult() { -- return result; -+ return super.getResult(); // Paper - } - - public void setResult(@Nullable ItemStack result) { -- this.result = result; -+ super.setResult(result); // Paper - } - -+ /* // Paper - comment out - @NotNull - @Override - public HandlerList getHandlers() { -@@ -50,4 +54,5 @@ public class PrepareSmithingEvent extends InventoryEvent { - public static HandlerList getHandlerList() { - return handlers; - } -+ */ // Paper - } diff --git a/Unmapped-Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch b/Unmapped-Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch deleted file mode 100644 index c270243b46..0000000000 --- a/Unmapped-Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Wed, 29 Apr 2020 02:09:17 +0200 -Subject: [PATCH] Allow delegation to vanilla chunk gen - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 4cffbc4f665e267371e99094e8b7de975fffc223..a1e211653e05f3c9bc2ddf5aa1b69dea1c4bb61b 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1490,6 +1490,22 @@ public final class Bukkit { - return server.createChunkData(world); - } - -+ // Paper start -+ /** -+ * Create a ChunkData for use in a generator, that is populated by the vanilla generator for that world -+ * -+ * @param world the world to create the ChunkData for -+ * @param x the x coordinate of the chunk -+ * @param z the z coordinate of the chunk -+ * @return a new ChunkData for the world -+ * -+ */ -+ @NotNull -+ public static ChunkGenerator.ChunkData createVanillaChunkData(@NotNull World world, int x, int z) { -+ return server.createVanillaChunkData(world, x, z); -+ } -+ // Paper stop -+ - /** - * Creates a boss bar instance to display to players. The progress - * defaults to 1.0 -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 969cba46ba2790dde32724111ad77332c5872e0b..71538dfce294776b8f98046cbddde21dc9ae89e7 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1256,6 +1256,20 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @NotNull - public ChunkGenerator.ChunkData createChunkData(@NotNull World world); - -+ // Paper start -+ /** -+ * Create a ChunkData for use in a generator, that is populated by the vanilla generator for that world -+ * -+ * @param world the world to create the ChunkData for -+ * @param x the x coordinate of the chunk -+ * @param z the z coordinate of the chunk -+ * @return a new ChunkData for the world -+ * -+ */ -+ @NotNull -+ ChunkGenerator.ChunkData createVanillaChunkData(@NotNull World world, int x, int z); -+ // Paper end -+ - /** - * Creates a boss bar instance to display to players. The progress - * defaults to 1.0 -diff --git a/src/main/java/org/bukkit/generator/ChunkGenerator.java b/src/main/java/org/bukkit/generator/ChunkGenerator.java -index 7caef27682f22a77de283dd6f391ec8bc0b0312b..5ba77d40a38e5e592ee265e4fbd510043a0b4345 100644 ---- a/src/main/java/org/bukkit/generator/ChunkGenerator.java -+++ b/src/main/java/org/bukkit/generator/ChunkGenerator.java -@@ -227,6 +227,22 @@ public abstract class ChunkGenerator { - return false; - } - -+ // Paper start -+ /** -+ * Create a ChunkData for use in a generator, that is populated by the vanilla generator for that world -+ * -+ * @param world the world to create the ChunkData for -+ * @param x the x coordinate of the chunk -+ * @param z the z coordinate of the chunk -+ * @return a new ChunkData for the world -+ * -+ */ -+ @NotNull -+ public ChunkData createVanillaChunkData(@NotNull World world, int x, int z) { -+ return Bukkit.getServer().createVanillaChunkData(world, x, z); -+ } -+ // Paper end -+ - /** - * Data for a Chunk. - */ diff --git a/Unmapped-Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch b/Unmapped-Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch deleted file mode 100644 index a3117a4377..0000000000 --- a/Unmapped-Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gerrygames -Date: Thu, 16 Jul 2020 10:40:10 +0200 -Subject: [PATCH] Support hex colors in getLastColors - - -diff --git a/src/main/java/org/bukkit/ChatColor.java b/src/main/java/org/bukkit/ChatColor.java -index 44d597d7a6f66a18b8037e971170ff7cea5e825f..4594701d77c5d0f744bece871b98d9f6f73eb5a7 100644 ---- a/src/main/java/org/bukkit/ChatColor.java -+++ b/src/main/java/org/bukkit/ChatColor.java -@@ -363,6 +363,7 @@ public enum ChatColor { - return new String(b); - } - -+ private static final Pattern HEX_COLOR_PATTERN = Pattern.compile(COLOR_CHAR + "x(?>" + COLOR_CHAR + "[0-9a-f]){6}", Pattern.CASE_INSENSITIVE); // Paper - Support hex colors in getLastColors - /** - * Gets the ChatColors used at the end of the given input string. - * -@@ -380,6 +381,15 @@ public enum ChatColor { - for (int index = length - 1; index > -1; index--) { - char section = input.charAt(index); - if (section == COLOR_CHAR && index < length - 1) { -+ // Paper start - Support hex colors -+ if (index > 11 && input.charAt(index - 12) == COLOR_CHAR && (input.charAt(index - 11) == 'x' || input.charAt(index - 11) == 'X')) { -+ String color = input.substring(index - 12, index + 2); -+ if (HEX_COLOR_PATTERN.matcher(color).matches()) { -+ result = color + result; -+ break; -+ } -+ } -+ // Paper end - char c = input.charAt(index + 1); - ChatColor color = getByChar(c); - diff --git a/Unmapped-Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch b/Unmapped-Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch deleted file mode 100644 index 17b9d923f2..0000000000 --- a/Unmapped-Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 22 Aug 2020 23:59:25 +0200 -Subject: [PATCH] Add #setMaxPlayers API - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 1eaf6aae1e13c48a7f911e523015cb9b8cca8638..6228d7eca85fba52296c8d63d32804f32af1b421 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -171,6 +171,17 @@ public final class Bukkit { - return server.getMaxPlayers(); - } - -+ // Paper start -+ /** -+ * Set the maximum amount of players which can login to this server. -+ * -+ * @param maxPlayers the amount of players this server allows -+ */ -+ public static void setMaxPlayers(int maxPlayers) { -+ server.setMaxPlayers(maxPlayers); -+ } -+ // Paper end -+ - /** - * Get the game port that the server runs on. - * -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 8ee02c3d6cc8751704e5993fecd05293714e492f..6237578b373002c009efde4fb4c1864f0bf4f19e 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -144,6 +144,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - */ - public int getMaxPlayers(); - -+ // Paper start -+ /** -+ * Set the maximum amount of players which can login to this server. -+ * -+ * @param maxPlayers the amount of players this server allows -+ */ -+ public void setMaxPlayers(int maxPlayers); -+ // Paper end -+ - /** - * Get the game port that the server runs on. - * diff --git a/Unmapped-Spigot-API-Patches/0218-Add-moon-phase-API.patch b/Unmapped-Spigot-API-Patches/0218-Add-moon-phase-API.patch deleted file mode 100644 index c9e9827954..0000000000 --- a/Unmapped-Spigot-API-Patches/0218-Add-moon-phase-API.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 16:32:03 +0200 -Subject: [PATCH] Add moon phase API - - -diff --git a/src/main/java/io/papermc/paper/world/MoonPhase.java b/src/main/java/io/papermc/paper/world/MoonPhase.java -new file mode 100644 -index 0000000000000000000000000000000000000000..df05153397b42930cd53d37b30824c7e5f008f7e ---- /dev/null -+++ b/src/main/java/io/papermc/paper/world/MoonPhase.java -@@ -0,0 +1,36 @@ -+package io.papermc.paper.world; -+ -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.HashMap; -+import java.util.Map; -+ -+public enum MoonPhase { -+ FULL_MOON(0L), -+ WANING_GIBBOUS(1L), -+ LAST_QUARTER(2L), -+ WANING_CRESCENT(3L), -+ NEW_MOON(4L), -+ WAXING_CRESCENT(5L), -+ FIRST_QUARTER(6L), -+ WAXING_GIBBOUS(7L); -+ -+ private final long day; -+ -+ MoonPhase(long day) { -+ this.day = day; -+ } -+ -+ private static final Map BY_DAY = new HashMap<>(); -+ -+ static { -+ for (MoonPhase phase : values()) { -+ BY_DAY.put(phase.day, phase); -+ } -+ } -+ -+ @NotNull -+ public static MoonPhase getPhase(long day) { -+ return BY_DAY.get(day % 8L); -+ } -+} -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 6441d4e45e5d5f008f95233cdc34048b8be38592..e20d863d1308b470a294cb7ab022aac4b9a91f71 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -70,6 +70,12 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - * @return The amount of Players in this world - */ - int getPlayerCount(); -+ -+ /** -+ * @return the current moon phase at the current time in the world -+ */ -+ @NotNull -+ io.papermc.paper.world.MoonPhase getMoonPhase(); - // Paper end - - /** diff --git a/Unmapped-Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch b/Unmapped-Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch deleted file mode 100644 index 561ec4779e..0000000000 --- a/Unmapped-Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 23 Aug 2020 19:36:08 +0200 -Subject: [PATCH] Add playPickupItemAnimation to LivingEntity - - -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index a46379b3a777a9071b0b13357bbd6af40dbfb569..c4fe44dce3bcb3502b26af7c76ec6b36c2a2bebe 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -815,5 +815,28 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - * @param jumping entity jump state - */ - void setJumping(boolean jumping); -+ -+ /** -+ * Plays pickup item animation towards this entity. -+ *

    -+ * This will remove the item on the client. -+ *

    -+ * Quantity is inferred to be that of the {@link Item}. -+ * -+ * @param item item to pickup -+ */ -+ default void playPickupItemAnimation(@NotNull Item item) { -+ playPickupItemAnimation(item, item.getItemStack().getAmount()); -+ } -+ -+ /** -+ * Plays pickup item animation towards this entity. -+ *

    -+ * This will remove the item on the client. -+ * -+ * @param item item to pickup -+ * @param quantity quantity of item -+ */ -+ void playPickupItemAnimation(@NotNull Item item, int quantity); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0220-Add-BellRingEvent.patch b/Unmapped-Spigot-API-Patches/0220-Add-BellRingEvent.patch deleted file mode 100644 index 7862ad8c88..0000000000 --- a/Unmapped-Spigot-API-Patches/0220-Add-BellRingEvent.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Eearslya Sleiarion -Date: Mon, 24 Jun 2019 21:27:39 -0700 -Subject: [PATCH] Add BellRingEvent - -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/io/papermc/paper/event/block/BellRingEvent.java b/src/main/java/io/papermc/paper/event/block/BellRingEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..881e545df51409e6101b4bb49f699655a744f13f ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/BellRingEvent.java -@@ -0,0 +1,55 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.bukkit.potion.PotionEffect; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when a bell is rung. -+ */ -+public class BellRingEvent extends BlockEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ private final Entity entity; -+ -+ public BellRingEvent(@NotNull Block block, @Nullable Entity entity) { -+ super(block); -+ this.entity = entity; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ /** -+ * Gets the entity that rang the bell. -+ * -+ * @return the ringer or null if none -+ */ -+ @Nullable -+ public Entity getEntity() { -+ return entity; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0221-Brand-support.patch b/Unmapped-Spigot-API-Patches/0221-Brand-support.patch deleted file mode 100644 index 2c6d0a6ab9..0000000000 --- a/Unmapped-Spigot-API-Patches/0221-Brand-support.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DigitalRegent -Date: Mon, 6 Apr 2020 20:30:09 +0200 -Subject: [PATCH] Brand support - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 2530c811f52f51d6338900221b4681c952c1c752..828b2b0538d4f936bee57d9fca55774723e13970 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -2044,6 +2044,16 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - // Paper end - } - -+ // Paper start - brand support -+ /** -+ * Returns player's client brand name. If the client didn't send this information, the brand name will be null.
    -+ * For the Notchian client this name defaults to vanilla. Some modified clients report other names such as forge.
    -+ * @return client brand name -+ */ -+ @Nullable -+ String getClientBrandName(); -+ // Paper end -+ - @NotNull - @Override - Spigot spigot(); diff --git a/Unmapped-Spigot-API-Patches/0222-Add-more-Evoker-API.patch b/Unmapped-Spigot-API-Patches/0222-Add-more-Evoker-API.patch deleted file mode 100644 index 0d6f0f7328..0000000000 --- a/Unmapped-Spigot-API-Patches/0222-Add-more-Evoker-API.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 15:22:44 +0200 -Subject: [PATCH] Add more Evoker API - - -diff --git a/src/main/java/org/bukkit/entity/Evoker.java b/src/main/java/org/bukkit/entity/Evoker.java -index f8d173adc09197418883dc7bc66dd8bfff8c5c72..76f81cd124090337876c9e5e469862a1c8da4ec8 100644 ---- a/src/main/java/org/bukkit/entity/Evoker.java -+++ b/src/main/java/org/bukkit/entity/Evoker.java -@@ -64,4 +64,19 @@ public interface Evoker extends Spellcaster { - */ - @Deprecated - void setCurrentSpell(@Nullable Spell spell); -+ -+ // Paper start -+ /** -+ * @return the sheep being targeted by the {@link Spell#WOLOLO wololo spell}, or {@code null} if none -+ */ -+ @Nullable -+ Sheep getWololoTarget(); -+ -+ /** -+ * Set the sheep to be the target of the {@link Spell#WOLOLO wololo spell}, or {@code null} to clear. -+ * -+ * @param sheep new wololo target -+ */ -+ void setWololoTarget(@Nullable Sheep sheep); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/Unmapped-Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch deleted file mode 100644 index bfa151e84b..0000000000 --- a/Unmapped-Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 11 Aug 2020 19:17:46 +0200 -Subject: [PATCH] Add a way to get translation keys for blocks, entities and - materials - - -diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 9c28351c7c3f60c6a3b4020329344f91efeedae1..69c85c3a1f45476f7de0a9399852d82eeb4f9c86 100644 ---- a/src/main/java/org/bukkit/Material.java -+++ b/src/main/java/org/bukkit/Material.java -@@ -3991,6 +3991,16 @@ public enum Material implements Keyed { - } - return false; - } -+ -+ /** -+ * Return the translation key for the Material, so the client can translate it into the active -+ * locale when using a TranslatableComponent. -+ * @return the translation key -+ */ -+ @NotNull -+ public String getTranslationKey() { -+ return Bukkit.getUnsafe().getTranslationKey(this); -+ } - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index e348034288c74ab80360086d71f0b7f61551df24..2d9264ffe0fee863f1b814952ef063daa7962d76 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -101,5 +101,34 @@ public interface UnsafeValues { - byte[] serializeItem(ItemStack item); - - ItemStack deserializeItem(byte[] data); -+ -+ /** -+ * Return the translation key for the Material, so the client can translate it into the active -+ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}. -+ * @return the translation key -+ */ -+ String getTranslationKey(Material mat); -+ -+ /** -+ * Return the translation key for the Block, so the client can translate it into the active -+ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}. -+ * @return the translation key -+ */ -+ String getTranslationKey(org.bukkit.block.Block block); -+ -+ /** -+ * Return the translation key for the EntityType, so the client can translate it into the active -+ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.
    -+ * This is null, when the EntityType isn't known to NMS (custom entities) -+ * @return the translation key -+ */ -+ String getTranslationKey(org.bukkit.entity.EntityType type); -+ -+ /** -+ * Return the translation key for the ItemStack, so the client can translate it into the active -+ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.
    -+ * @return the translation key -+ */ -+ String getTranslationKey(ItemStack itemStack); - // Paper end - } -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index e1cc36fbe808973227c0e8ca7166453235c90279..e6647c45f65bae916759cd899256f8130790d242 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -584,5 +584,13 @@ public interface Block extends Metadatable { - */ - @NotNull - com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup(); -+ -+ /** -+ * Return the translation key for the Block, so the client can translate it into the active -+ * locale when using a TranslatableComponent. -+ * @return the translation key -+ */ -+ @NotNull -+ String getTranslationKey(); - // Paper end - } -diff --git a/src/main/java/org/bukkit/entity/EntityType.java b/src/main/java/org/bukkit/entity/EntityType.java -index 9be5371c7f398d0ec8241403661415ff40661067..f415b61b0d4b57e1557aaf240a0f2ad5915035fc 100644 ---- a/src/main/java/org/bukkit/entity/EntityType.java -+++ b/src/main/java/org/bukkit/entity/EntityType.java -@@ -419,4 +419,15 @@ public enum EntityType implements Keyed { - public boolean isAlive() { - return living; - } -+ -+ /** -+ * Return the translation key for the EntityType, so the client can translate it into the active -+ * locale when using a TranslatableComponent.
    -+ * This is null, when the EntityType isn't known to NMS (custom entities) -+ * @return the translation key -+ */ -+ @Nullable -+ String getTranslationKey() { -+ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); -+ } - } -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 9a878e4fde31c015e2f3fdf365d5d16c30198685..bd96c06aca1fc18807e65c34f399ce2ebe891816 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -851,5 +851,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - ItemMeta itemMeta = getItemMeta(); - return itemMeta != null && itemMeta.hasItemFlag(flag); - } -+ -+ /** -+ * Gets the translation key for this itemstack. -+ * This is not the same as getting the translation key -+ * for the material of this itemstack. -+ * -+ * @return the translation key -+ */ -+ @NotNull -+ public String getTranslationKey() { -+ return Bukkit.getUnsafe().getTranslationKey(this); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch b/Unmapped-Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch deleted file mode 100644 index 9a15253cfd..0000000000 --- a/Unmapped-Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 6 Jul 2020 22:17:37 +0200 -Subject: [PATCH] Create HoverEvent from ItemStack Entity - - -diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index e2bcc96ad067e2abfe9108b3a2235fe5da7ab3eb..3cbe5afc3548d4b7d0c6e625d9029506133676ff 100644 ---- a/src/main/java/org/bukkit/inventory/ItemFactory.java -+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java -@@ -184,5 +184,62 @@ public interface ItemFactory { - */ - @Nullable - String getI18NDisplayName(@Nullable ItemStack item); -+ -+ /** -+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that ItemStack for displaying. -+ * -+ * @param itemStack -+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that ItemStack -+ */ -+ @NotNull -+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull ItemStack itemStack); -+ -+ /** -+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying. -+ * Uses the display name of the entity, if present. -+ * -+ * @param entity Entity to create the HoverEvent for -+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} -+ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent()} -+ */ -+ @NotNull -+ @Deprecated -+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity); -+ -+ /** -+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying. -+ * -+ * @param entity Entity to create the HoverEvent for -+ * @param customName a custom name that should be displayed, if not passed entity name will be displayed -+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} -+ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent(java.util.function.UnaryOperator)} -+ */ -+ @NotNull -+ @Deprecated -+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @Nullable String customName); -+ -+ /** -+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying. -+ * -+ * @param entity Entity to create the HoverEvent for -+ * @param customName a custom name that should be displayed, if not passed entity name will be displayed -+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} -+ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent(java.util.function.UnaryOperator)} -+ */ -+ @NotNull -+ @Deprecated -+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @Nullable net.md_5.bungee.api.chat.BaseComponent customName); -+ -+ /** -+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying. -+ * -+ * @param entity Entity to create the HoverEvent for -+ * @param customName a custom name that should be displayed, if not passed entity name will be displayed -+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} -+ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent(java.util.function.UnaryOperator)} -+ */ -+ @NotNull -+ @Deprecated -+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @NotNull net.md_5.bungee.api.chat.BaseComponent[] customName); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch b/Unmapped-Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch deleted file mode 100644 index 53584ff633..0000000000 --- a/Unmapped-Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 26 Aug 2020 02:11:58 -0400 -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 b09d12390d5f77330ac84452e0fee63a169bd01f..77bff8fb6bfdf739e413084e13677a83e723c71e 100644 ---- a/src/main/java/org/bukkit/entity/HumanEntity.java -+++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -148,6 +148,92 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder - @Nullable - public InventoryView openMerchant(@NotNull Merchant merchant, boolean force); - -+ // Paper start - Add additional containers -+ /** -+ * Opens an empty anvil inventory window with the player's inventory -+ * on the bottom. -+ * -+ * @param location The location to attach it to. If null, the player's -+ * location is used. -+ * @param force If false, and there is no anvil block at the location, -+ * no inventory will be opened and null will be returned. -+ * @return The newly opened inventory view, or null if it could not be -+ * opened. -+ */ -+ @Nullable -+ public InventoryView openAnvil(@Nullable Location location, boolean force); -+ -+ /** -+ * Opens an empty cartography table inventory window with the player's inventory -+ * on the bottom. -+ * -+ * @param location The location to attach it to. If null, the player's -+ * location is used. -+ * @param force If false, and there is no cartography table block at the location, -+ * no inventory will be opened and null will be returned. -+ * @return The newly opened inventory view, or null if it could not be -+ * opened. -+ */ -+ @Nullable -+ public InventoryView openCartographyTable(@Nullable Location location, boolean force); -+ -+ /** -+ * Opens an empty grindstone inventory window with the player's inventory -+ * on the bottom. -+ * -+ * @param location The location to attach it to. If null, the player's -+ * location is used. -+ * @param force If false, and there is no grindstone block at the location, -+ * no inventory will be opened and null will be returned. -+ * @return The newly opened inventory view, or null if it could not be -+ * opened. -+ */ -+ @Nullable -+ public InventoryView openGrindstone(@Nullable Location location, boolean force); -+ -+ /** -+ * Opens an empty loom inventory window with the player's inventory -+ * on the bottom. -+ * -+ * @param location The location to attach it to. If null, the player's -+ * location is used. -+ * @param force If false, and there is no loom block at the location, -+ * no inventory will be opened and null will be returned. -+ * @return The newly opened inventory view, or null if it could not be -+ * opened. -+ */ -+ @Nullable -+ public InventoryView openLoom(@Nullable Location location, boolean force); -+ -+ /** -+ * Opens an empty smithing table inventory window with the player's inventory -+ * on the bottom. -+ * -+ * @param location The location to attach it to. If null, the player's -+ * location is used. -+ * @param force If false, and there is no smithing table block at the location, -+ * no inventory will be opened and null will be returned. -+ * @return The newly opened inventory view, or null if it could not be -+ * opened. -+ */ -+ @Nullable -+ public InventoryView openSmithingTable(@Nullable Location location, boolean force); -+ -+ /** -+ * Opens an empty stonecutter inventory window with the player's inventory -+ * on the bottom. -+ * -+ * @param location The location to attach it to. If null, the player's -+ * location is used. -+ * @param force If false, and there is no stonecutter block at the location, -+ * no inventory will be opened and null will be returned. -+ * @return The newly opened inventory view, or null if it could not be -+ * opened. -+ */ -+ @Nullable -+ public InventoryView openStonecutter(@Nullable Location location, boolean force); -+ // Paper end -+ - /** - * Force-closes the currently open inventory view for this player, if any. - */ diff --git a/Unmapped-Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/Unmapped-Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch deleted file mode 100644 index a92a435f5a..0000000000 --- a/Unmapped-Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Fri, 28 Aug 2020 01:41:31 +0200 -Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and - non-conflicting Entity Ids - - -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 2d9264ffe0fee863f1b814952ef063daa7962d76..84eda68281c6c6968d95b1313a33696c3a9980d4 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -130,5 +130,12 @@ public interface UnsafeValues { - * @return the translation key - */ - String getTranslationKey(ItemStack itemStack); -+ -+ /** -+ * Creates and returns the next EntityId available. -+ *

    -+ * Use this when sending custom packets, so that there are no collisions on the client or server. -+ */ -+ public int nextEntityId(); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0227-Entity-isTicking.patch b/Unmapped-Spigot-API-Patches/0227-Entity-isTicking.patch deleted file mode 100644 index 315c89bf3b..0000000000 --- a/Unmapped-Spigot-API-Patches/0227-Entity-isTicking.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 21:39:07 -0500 -Subject: [PATCH] Entity#isTicking - - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index ecb5595332ab493224d06a75904e142ab541aad9..4ed8c74f874dbd1017764d7592acfdafbc5d5fe1 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -744,5 +744,10 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - * Check if entity is in lava - */ - public boolean isInLava(); -+ -+ /** -+ * Check if entity is inside a ticking chunk -+ */ -+ public boolean isTicking(); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch b/Unmapped-Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch deleted file mode 100644 index 2947f78299..0000000000 --- a/Unmapped-Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aurora -Date: Sat, 3 Oct 2020 16:28:41 +0200 -Subject: [PATCH] Clarify the Javadocs for Entity.getEntitySpawnReason() - - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 4ed8c74f874dbd1017764d7592acfdafbc5d5fe1..14470b23f7b4102cf2dca777bc832ebcbcd5edc6 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -710,7 +710,7 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - Chunk getChunk(); - - /** -- * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity. -+ * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that initially spawned this entity. - */ - @NotNull - org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason(); diff --git a/Unmapped-Spigot-API-Patches/0229-Villager-resetOffers.patch b/Unmapped-Spigot-API-Patches/0229-Villager-resetOffers.patch deleted file mode 100644 index 60fedfba0f..0000000000 --- a/Unmapped-Spigot-API-Patches/0229-Villager-resetOffers.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Mon, 7 Oct 2019 00:15:28 -0500 -Subject: [PATCH] Villager#resetOffers - - -diff --git a/src/main/java/org/bukkit/entity/AbstractVillager.java b/src/main/java/org/bukkit/entity/AbstractVillager.java -index d2b0c08554dba4d34b37b440f1d77ae0e64cb99e..7fbe31c4fd69d4fca7ef96c0a56b0e0204d60cf4 100644 ---- a/src/main/java/org/bukkit/entity/AbstractVillager.java -+++ b/src/main/java/org/bukkit/entity/AbstractVillager.java -@@ -21,4 +21,11 @@ public interface AbstractVillager extends Breedable, NPC, InventoryHolder, Merch - @NotNull - @Override - Inventory getInventory(); -+ -+ // Paper start -+ /** -+ * Reset this villager's trade offers -+ */ -+ public void resetOffers(); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0230-Player-elytra-boost-API.patch b/Unmapped-Spigot-API-Patches/0230-Player-elytra-boost-API.patch deleted file mode 100644 index 1f9e683db7..0000000000 --- a/Unmapped-Spigot-API-Patches/0230-Player-elytra-boost-API.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Tue, 14 Apr 2020 12:06:14 +0200 -Subject: [PATCH] Player elytra boost API - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 828b2b0538d4f936bee57d9fca55774723e13970..7aa9fb852dce23c53fee80e97e0dcdb278ae82ba 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1916,6 +1916,19 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - @NotNull - T getClientOption(@NotNull ClientOption option); -+ -+ /** -+ * Boost a Player that's {@link #isGliding()} using a {@link Firework}. -+ * If the creation of the entity is cancelled, no boosting is done. -+ * This method does not fire {@link com.destroystokyo.paper.event.player.PlayerElytraBoostEvent}. -+ * -+ * @param firework The {@link Material#FIREWORK_ROCKET} to boost the player with -+ * @return The {@link Firework} boosting the Player or null if the spawning of the entity was cancelled -+ * @throws IllegalArgumentException if {@link #isGliding()} is false -+ * or if the {@code firework} isn't a {@link Material#FIREWORK_ROCKET} -+ */ -+ @Nullable -+ Firework boostElytra(@NotNull ItemStack firework); - // Paper end - - // Spigot start diff --git a/Unmapped-Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch b/Unmapped-Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch deleted file mode 100644 index f39340e7f4..0000000000 --- a/Unmapped-Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: oxygencraft <21054297+oxygencraft@users.noreply.github.com> -Date: Sun, 25 Oct 2020 18:35:58 +1100 -Subject: [PATCH] Add getOfflinePlayerIfCached(String) - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 3a930ee1b1dce3639d590a8646f68b4ab92207fb..a498c5267458767e1f7802ab3d3b7a22f987d985 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -962,6 +962,27 @@ public final class Bukkit { - return server.getOfflinePlayer(name); - } - -+ // Paper start -+ /** -+ * Gets the player by the given name, regardless if they are offline or -+ * online. -+ *

    -+ * This will not make a web request to get the UUID for the given name, -+ * thus this method will not block. However this method will return -+ * {@code null} if the player is not cached. -+ *

    -+ * -+ * @param name the name of the player to retrieve -+ * @return an offline player if cached, {@code null} otherwise -+ * @see #getOfflinePlayer(String) -+ * @see #getOfflinePlayer(java.util.UUID) -+ */ -+ @Nullable -+ public static OfflinePlayer getOfflinePlayerIfCached(@NotNull String name) { -+ return server.getOfflinePlayerIfCached(name); -+ } -+ // Paper end -+ - /** - * 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 9d8886526ae0cd31ec5771462f3cd57692b1cb53..bbc7a1a35da6c8c66c18779ba4fb1aca1a567e6f 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -808,6 +808,25 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @NotNull - public OfflinePlayer getOfflinePlayer(@NotNull String name); - -+ // Paper start -+ /** -+ * Gets the player by the given name, regardless if they are offline or -+ * online. -+ *

    -+ * This will not make a web request to get the UUID for the given name, -+ * thus this method will not block. However this method will return -+ * {@code null} if the player is not cached. -+ *

    -+ * -+ * @param name the name of the player to retrieve -+ * @return an offline player if cached, {@code null} otherwise -+ * @see #getOfflinePlayer(String) -+ * @see #getOfflinePlayer(java.util.UUID) -+ */ -+ @Nullable -+ public OfflinePlayer getOfflinePlayerIfCached(@NotNull String name); -+ // Paper end -+ - /** - * Gets the player by the given UUID, regardless if they are offline or - * online. diff --git a/Unmapped-Spigot-API-Patches/0232-Add-ignore-discounts-API.patch b/Unmapped-Spigot-API-Patches/0232-Add-ignore-discounts-API.patch deleted file mode 100644 index 492c998c91..0000000000 --- a/Unmapped-Spigot-API-Patches/0232-Add-ignore-discounts-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Mon, 9 Nov 2020 20:33:38 +0100 -Subject: [PATCH] Add ignore discounts API - - -diff --git a/src/main/java/org/bukkit/inventory/MerchantRecipe.java b/src/main/java/org/bukkit/inventory/MerchantRecipe.java -index 1fb4a1c53791776f9c5a952a592f15fc35cb2703..2be2f3fe655c417bfc8f8e840f9e9415d168f37e 100644 ---- a/src/main/java/org/bukkit/inventory/MerchantRecipe.java -+++ b/src/main/java/org/bukkit/inventory/MerchantRecipe.java -@@ -28,6 +28,7 @@ public class MerchantRecipe implements Recipe { - private boolean experienceReward; - private int villagerExperience; - private float priceMultiplier; -+ private boolean ignoreDiscounts; // Paper - - public MerchantRecipe(@NotNull ItemStack result, int maxUses) { - this(result, 0, maxUses, false); -@@ -38,6 +39,12 @@ public class MerchantRecipe implements Recipe { - } - - public MerchantRecipe(@NotNull ItemStack result, int uses, int maxUses, boolean experienceReward, int villagerExperience, float priceMultiplier) { -+ // Paper start - add ignoreDiscounts param -+ this(result, uses, maxUses, experienceReward, villagerExperience, priceMultiplier, false); -+ } -+ public MerchantRecipe(@NotNull ItemStack result, int uses, int maxUses, boolean experienceReward, int villagerExperience, float priceMultiplier, boolean ignoreDiscounts) { -+ this.ignoreDiscounts = ignoreDiscounts; -+ // Paper end - this.result = result; - this.uses = uses; - this.maxUses = maxUses; -@@ -172,4 +179,20 @@ public class MerchantRecipe implements Recipe { - public void setPriceMultiplier(float priceMultiplier) { - this.priceMultiplier = priceMultiplier; - } -+ -+ // Paper start -+ /** -+ * @return Whether all discounts on this trade should be ignored. -+ */ -+ public boolean shouldIgnoreDiscounts() { -+ return ignoreDiscounts; -+ } -+ -+ /** -+ * @param ignoreDiscounts Whether all discounts on this trade should be ignored. -+ */ -+ public void setIgnoreDiscounts(boolean ignoreDiscounts) { -+ this.ignoreDiscounts = ignoreDiscounts; -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch b/Unmapped-Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch deleted file mode 100644 index 142a8b5202..0000000000 --- a/Unmapped-Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Smith -Date: Sat, 7 Nov 2020 01:20:27 +0000 -Subject: [PATCH] Item no age & no player pickup - - -diff --git a/src/main/java/org/bukkit/entity/Item.java b/src/main/java/org/bukkit/entity/Item.java -index c404a5b8efea7c780db5ddae19456753808abb3d..0ee072645ecf1bf5feb74de6960947ef76db366e 100644 ---- a/src/main/java/org/bukkit/entity/Item.java -+++ b/src/main/java/org/bukkit/entity/Item.java -@@ -90,5 +90,34 @@ public interface Item extends Entity { - * @param canMobPickup True to allow non-player entity pickup - */ - public void setCanMobPickup(boolean canMobPickup); -+ -+ /** -+ * Gets whether the player can pickup the item or not -+ * -+ * @return True if a player can pickup the item -+ */ -+ public boolean canPlayerPickup(); -+ -+ /** -+ * Sets whether the item can be picked up or not. Modifies the pickup delay value to do so. -+ * -+ * @param canPlayerPickup True if the player can pickup the item -+ */ -+ public void setCanPlayerPickup(boolean canPlayerPickup); -+ -+ /** -+ * Gets whether the item will age and despawn from being on the ground too long -+ * -+ * @return True if the item will age -+ */ -+ public boolean willAge(); -+ -+ /** -+ * Sets whether the item will age or not. If the item is not ageing, it will not despawn -+ * by being on the ground for too long. -+ * -+ * @param willAge True if the item should age -+ */ -+ public void setWillAge(boolean willAge); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch b/Unmapped-Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch deleted file mode 100644 index ff56b99ebf..0000000000 --- a/Unmapped-Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 12:38:15 -0600 -Subject: [PATCH] Beacon API - custom effect ranges - - -diff --git a/src/main/java/org/bukkit/block/Beacon.java b/src/main/java/org/bukkit/block/Beacon.java -index 6349fa9da3f96df3553fb9552c1cab95338cecb0..78475fc6faff0f295828d7b53792001d51aa2889 100644 ---- a/src/main/java/org/bukkit/block/Beacon.java -+++ b/src/main/java/org/bukkit/block/Beacon.java -@@ -64,4 +64,26 @@ public interface Beacon extends TileState, Lockable, Nameable { - * @param effect desired secondary effect - */ - void setSecondaryEffect(@Nullable PotionEffectType effect); -+ -+ // Paper start - Custom effect ranges -+ /** -+ * Gets the effect range of this beacon. -+ * A negative range value means the beacon is using its default range based on tier. -+ * @return Either the custom range set with {@link #setEffectRange(double)} or the range based on the beacon tier. -+ */ -+ double getEffectRange(); -+ -+ /** -+ * Sets the effect range of the beacon -+ * A negative range value means the beacon is using its default range based on tier. -+ * @param range Radius of effect range. -+ */ -+ void setEffectRange(double range); -+ -+ /** -+ * Resets the custom range from this beacon and falls back to the range based on the the beacon tier. -+ * Shortcut for setting the effect range to a negative number. -+ */ -+ void resetEffectRange(); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0235-Add-API-for-quit-reason.patch b/Unmapped-Spigot-API-Patches/0235-Add-API-for-quit-reason.patch deleted file mode 100644 index 63d864224b..0000000000 --- a/Unmapped-Spigot-API-Patches/0235-Add-API-for-quit-reason.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 14 Nov 2020 16:19:58 +0100 -Subject: [PATCH] Add API for quit reason - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -index 849e8f10dd77e9fb46aab17752b8f1ff79e9d42e..b6016aa1e91863efc252eecab69ade6f54c89f27 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -@@ -11,16 +11,28 @@ import org.jetbrains.annotations.Nullable; - public class PlayerQuitEvent extends PlayerEvent { - private static final HandlerList handlers = new HandlerList(); - private net.kyori.adventure.text.Component quitMessage; // Paper -+ private final QuitReason reason; // Paper - - @Deprecated // Paper - public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage) { -+ // Paper start -+ this(who, quitMessage, null); -+ } -+ @Deprecated // Paper -+ public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage, @Nullable QuitReason quitReason) { - super(who); - this.quitMessage = quitMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(quitMessage) : null; // Paper -+ this.reason = quitReason == null ? QuitReason.DISCONNECTED : quitReason; - } - // Paper start -+ @Deprecated - public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage) { -+ this(who, quitMessage, null); -+ } -+ public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage, @Nullable QuitReason quitReason) { - super(who); - this.quitMessage = quitMessage; -+ this.reason = quitReason == null ? QuitReason.DISCONNECTED : quitReason; - } - - /** -@@ -75,4 +87,39 @@ public class PlayerQuitEvent extends PlayerEvent { - public static HandlerList getHandlerList() { - return handlers; - } -+ -+ // Paper start -+ @NotNull -+ public QuitReason getReason() { -+ return this.reason; -+ } -+ -+ public enum QuitReason { -+ /** -+ * The player left on their own behalf. -+ *

    -+ * This does not mean they pressed the disconnect button in their client, but rather that the client severed the -+ * connection themselves. This may occur if no keep-alive packet is received on their side, among other things. -+ */ -+ DISCONNECTED, -+ -+ /** -+ * The player was kicked from the server. -+ */ -+ KICKED, -+ -+ /** -+ * The player has timed out. -+ */ -+ TIMED_OUT, -+ -+ /** -+ * The player's connection has entered an erroneous state. -+ *

    -+ * Reasons for this may include invalid packets, invalid data, and uncaught exceptions in the packet handler, -+ * among others. -+ */ -+ ERRONEOUS_STATE, -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch b/Unmapped-Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch deleted file mode 100644 index bdf3dd2bbe..0000000000 --- a/Unmapped-Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ineusia -Date: Mon, 26 Oct 2020 11:37:48 -0500 -Subject: [PATCH] Add Destroy Speed API - -Co-authored-by: Jake Potrebic - -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index e6647c45f65bae916759cd899256f8130790d242..e4e3be0ee9c557e04d9ed1ab6f1569bd36a0e846 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -592,5 +592,29 @@ public interface Block extends Metadatable { - */ - @NotNull - String getTranslationKey(); -+ -+ /** -+ * Gets the speed at which this block will be destroyed by a given {@link ItemStack} -+ * -+ *

    Default value is 1.0

    -+ * -+ * @param itemStack {@link ItemStack} used to mine this Block -+ * @return the speed that this Block will be mined by the given {@link ItemStack} -+ */ -+ @NotNull -+ public default float getDestroySpeed(@NotNull ItemStack itemStack) { -+ return getDestroySpeed(itemStack, false); -+ } -+ -+ /** -+ * Gets the speed at which this blook will be destroyed by a given {@link org.bukkit.inventory.ItemStack} -+ *

    -+ * Default value is 1.0 -+ * @param itemStack {@link org.bukkit.inventory.ItemStack} used to mine this Block -+ * @param considerEnchants true to look at enchants on the itemstack -+ * @return the speed that this Block will be mined by the given {@link org.bukkit.inventory.ItemStack} -+ */ -+ @NotNull -+ float getDestroySpeed(@NotNull ItemStack itemStack, boolean considerEnchants); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch b/Unmapped-Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch deleted file mode 100644 index bb5b5e0b5e..0000000000 --- a/Unmapped-Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Anrza -Date: Wed, 15 Jul 2020 12:07:58 +0200 -Subject: [PATCH] Add LivingEntity#clearActiveItem - - -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 9bf525b795ff1d88d2596b1f2bc787ce0df047bb..e535750d01a6c1bf4b1fe94df518166213da9b08 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -766,6 +766,13 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - @Nullable - ItemStack getActiveItem(); - -+ // Paper start -+ /** -+ * Interrupts any ongoing active "usage" or consumption or an item. -+ */ -+ void clearActiveItem(); -+ // Paper end -+ - /** - * Get's remaining time a player needs to keep hands raised with an item to finish using it. - * @return Remaining ticks to use the item diff --git a/Unmapped-Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch b/Unmapped-Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch deleted file mode 100644 index 3bf6084e14..0000000000 --- a/Unmapped-Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Tue, 25 Aug 2020 13:45:15 +0200 -Subject: [PATCH] Add PlayerItemCooldownEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerItemCooldownEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerItemCooldownEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..58d18f05af13d836ddc62fcd30befcb06f07c57c ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerItemCooldownEvent.java -@@ -0,0 +1,77 @@ -+package io.papermc.paper.event.player; -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.Material; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a player receives an item cooldown. -+ */ -+public class PlayerItemCooldownEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull -+ private final Material type; -+ private boolean cancelled; -+ private int cooldown; -+ -+ public PlayerItemCooldownEvent(@NotNull Player player, @NotNull Material type, int cooldown) { -+ super(player); -+ this.type = type; -+ this.cooldown = cooldown; -+ } -+ -+ /** -+ * Get the material affected by the cooldown. -+ * -+ * @return material affected by the cooldown -+ */ -+ @NotNull -+ public Material getType() { -+ return type; -+ } -+ -+ /** -+ * Gets the cooldown in ticks. -+ * -+ * @return cooldown in ticks -+ */ -+ public int getCooldown() { -+ return cooldown; -+ } -+ -+ /** -+ * Sets the cooldown of the material in ticks. -+ * Setting the cooldown to 0 results in removing an already existing cooldown for the material. -+ * -+ * @param cooldown cooldown in ticks, has to be a positive number -+ */ -+ public void setCooldown(int cooldown) { -+ Preconditions.checkArgument(cooldown >= 0, "The cooldown has to be equal to or greater than 0!"); -+ this.cooldown = cooldown; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0239-More-lightning-API.patch b/Unmapped-Spigot-API-Patches/0239-More-lightning-API.patch deleted file mode 100644 index 1b6f512299..0000000000 --- a/Unmapped-Spigot-API-Patches/0239-More-lightning-API.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Sun, 26 Jul 2020 14:44:16 +0200 -Subject: [PATCH] More lightning API - - -diff --git a/src/main/java/org/bukkit/entity/LightningStrike.java b/src/main/java/org/bukkit/entity/LightningStrike.java -index be347c3d0291f44036bae29a4e7e4645d6a4cdf6..2c81a3f685588431a3c7675c84b35a28975232af 100644 ---- a/src/main/java/org/bukkit/entity/LightningStrike.java -+++ b/src/main/java/org/bukkit/entity/LightningStrike.java -@@ -31,4 +31,38 @@ public interface LightningStrike extends Entity { - @Override - Spigot spigot(); - // Spigot end -+ -+ // Paper start -+ /** -+ * Returns the amount of flash iterations that will be done before the lightning dies. -+ * -+ * @see #getLifeTicks() for how long the current flash will last -+ * @return amount of flashes that will be shown before the lightning dies -+ */ -+ int getFlashCount(); -+ -+ /** -+ * Sets the amount of life iterations that will be done before the lightning dies. -+ * Default number of flashes on creation is between 1-3. -+ * -+ * @param flashes amount of iterations that will be done before the lightning dies, must to be a positive number -+ */ -+ void setFlashCount(int flashes); -+ -+ /** -+ * Returns the amount of ticks the current flash will do damage for. -+ * Starts with 2 by default, will damage while it is equal to or above 0, with the next flash beginning somewhere between 0 and -9. -+ * -+ * @return ticks the current flash will do damage for -+ */ -+ int getLifeTicks(); -+ -+ /** -+ * Sets the amount of ticks the current flash will do damage/fire for. -+ * Default is 2 for each flash, on which the sound and effect will also be played. -+ * -+ * @param lifeTicks ticks the current flash will do damage for -+ */ -+ void setLifeTicks(int lifeTicks); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch b/Unmapped-Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch deleted file mode 100644 index 051544b4a9..0000000000 --- a/Unmapped-Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Thu, 27 Aug 2020 12:32:35 -0400 -Subject: [PATCH] Add PlayerShearBlockEvent - - -diff --git a/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java b/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..aa7d440b797eac9e62678d03cc87f42838758bfd ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java -@@ -0,0 +1,108 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.EquipmentSlot; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.List; -+ -+/** -+ * Called when a player uses sheers on a block. -+ *

    -+ * This event is not called when breaking blocks with shears but instead only when a -+ * player uses the sheer item on a block to garner drops from said block and/or change its state. -+ *

    -+ * Examples include shearing a pumpkin to turn it into a carved pumpkin or shearing a beehive to get honeycomb. -+ */ -+public class PlayerShearBlockEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled = false; -+ private final Block block; -+ private final ItemStack item; -+ private final EquipmentSlot hand; -+ private final List drops; -+ -+ public PlayerShearBlockEvent(@NotNull Player who, @NotNull Block block, @NotNull ItemStack item, @NotNull EquipmentSlot hand, @NotNull List drops) { -+ super(who); -+ this.block = block; -+ this.item = item; -+ this.hand = hand; -+ this.drops = drops; -+ } -+ -+ /** -+ * Gets the block being sheared in this event. -+ * -+ * @return The {@link Block} which block is being sheared in this event. -+ */ -+ @NotNull -+ public Block getBlock() { -+ return block; -+ } -+ -+ /** -+ * Gets the item used to shear the block. -+ * -+ * @return The {@link ItemStack} of the shears. -+ */ -+ @NotNull -+ public ItemStack getItem() { -+ return item; -+ } -+ -+ /** -+ * Gets the hand used to shear the block. -+ * -+ * @return Either {@link EquipmentSlot#HAND} OR {@link EquipmentSlot#OFF_HAND}. -+ */ -+ @NotNull -+ public EquipmentSlot getHand() { -+ return hand; -+ } -+ -+ /** -+ * Gets the resulting drops of this event. -+ * -+ * @return A {@link List list} of {@link ItemStack items} that will be dropped as result of this event. -+ */ -+ @NotNull -+ public List getDrops() { -+ return drops; -+ } -+ -+ /** -+ * Gets whether the shearing of the block should be cancelled or not. -+ * -+ * @return Whether the shearing of the block should be cancelled or not. -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Sets whether the shearing of the block should be cancelled or not. -+ * -+ * @param cancel whether the shearing of the block should be cancelled or not. -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch b/Unmapped-Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch deleted file mode 100644 index 9f71d1c074..0000000000 --- a/Unmapped-Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Fri, 4 Dec 2020 15:53:19 -0800 -Subject: [PATCH] Enable multi-release plugin jars - - -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 11e5618ff66385574ba04db0942a75227cf8eb0f..c833cee9fddd12afdfe6bde1435559819b9ad656 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -58,7 +58,18 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - this.description = description; - this.dataFolder = dataFolder; - this.file = file; -- this.jar = new JarFile(file); -+ // Paper - enable multi-release jars for Java 9+ -+ JarFile jarFile; -+ try { -+ final java.lang.reflect.Method runtimeVersionMethod = JarFile.class.getMethod("runtimeVersion"); -+ final Object runtimeVersion = runtimeVersionMethod.invoke(null); -+ @SuppressWarnings("JavaReflectionMemberAccess") final java.lang.reflect.Constructor constructor = JarFile.class.getConstructor(File.class, boolean.class, int.class, runtimeVersion.getClass()); -+ jarFile = constructor.newInstance(file, true, java.util.zip.ZipFile.OPEN_READ, runtimeVersion); -+ } catch (Exception ignored) { -+ jarFile = new JarFile(file); -+ } -+ this.jar = jarFile; -+ // Paper end - this.manifest = jar.getManifest(); - this.url = file.toURI().toURL(); - this.libraryLoader = libraryLoader; diff --git a/Unmapped-Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch b/Unmapped-Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch deleted file mode 100644 index e2ce87ec9d..0000000000 --- a/Unmapped-Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 5 Oct 2020 21:24:45 +0200 -Subject: [PATCH] Player Chunk Load/Unload Events - - -diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2c1cda1126e577a88f19071e958eddb5a38785af ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java -@@ -0,0 +1,42 @@ -+package io.papermc.paper.event.packet; -+ -+import org.bukkit.Chunk; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.world.ChunkEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Is called when a {@link org.bukkit.entity.Player} receives a {@link org.bukkit.Chunk} -+ *

    -+ * Can for example be used for spawning a fake entity when the player receives a chunk. -+ * -+ * Should only be used for packet/clientside related stuff. -+ * Not intended for modifying server side state. -+ */ -+public class PlayerChunkLoadEvent extends ChunkEvent { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private final Player player; -+ -+ public PlayerChunkLoadEvent(@NotNull Chunk chunk, @NotNull Player player) { -+ super(chunk); -+ this.player = player; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public Player getPlayer() { -+ return player; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..12163a7b0591a7d022dc7eb9ee6608a1b6c39d9b ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java -@@ -0,0 +1,40 @@ -+package io.papermc.paper.event.packet; -+ -+import org.bukkit.Chunk; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.world.ChunkEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Is called when a {@link Player} receives a chunk unload packet. -+ * -+ * Should only be used for packet/clientside related stuff. -+ * Not intended for modifying server side. -+ */ -+public class PlayerChunkUnloadEvent extends ChunkEvent { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private final Player player; -+ -+ public PlayerChunkUnloadEvent(@NotNull Chunk chunk, @NotNull Player player) { -+ super(chunk); -+ this.player = player; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public Player getPlayer() { -+ return player; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch b/Unmapped-Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch deleted file mode 100644 index 95b46eabc4..0000000000 --- a/Unmapped-Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 13 Dec 2020 05:32:12 +0200 -Subject: [PATCH] Expose LivingEntity hurt direction - - -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index b96b5f4f2fc754298e2223b2f449a0755469278c..b6de41e3e718fa5d1b82c6f68b153e60a81265e7 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -845,5 +845,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - * @param quantity quantity of item - */ - void playPickupItemAnimation(@NotNull Item item, int quantity); -+ -+ /** -+ * Gets player hurt direction -+ * -+ * @return hurt direction -+ */ -+ float getHurtDirection(); -+ -+ /** -+ * Sets player hurt direction -+ * -+ * @param hurtDirection hurt direction -+ */ -+ void setHurtDirection(float hurtDirection); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0244-Added-PlayerTradeEvent.patch b/Unmapped-Spigot-API-Patches/0244-Added-PlayerTradeEvent.patch deleted file mode 100644 index e09b088160..0000000000 --- a/Unmapped-Spigot-API-Patches/0244-Added-PlayerTradeEvent.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 2 Jul 2020 16:10:10 -0700 -Subject: [PATCH] Added PlayerTradeEvent - -[Amendment: Alexander ] -PlayerTradeEvent is used for player purchases from villagers and wandering -traders, but not custom merchants created via Bukkit.createMerchant(). During -discussions in Discord it was decided that it'd be better to add a new event -that PlayerTradeEvent inherits from than change getVillager()'s annotation to -@Nullable, especially since that'd also infringe on the implication of the -event being about villager trades. - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerPurchaseEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerPurchaseEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c5648055c5e815474bf1e564a5c192ff5c0624fb ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerPurchaseEvent.java -@@ -0,0 +1,112 @@ -+package io.papermc.paper.event.player; -+ -+import java.util.Objects; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.MerchantRecipe; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player trades with a standalone merchant GUI. -+ */ -+public class PlayerPurchaseEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ -+ private boolean increaseTradeUses; -+ private boolean rewardExp; -+ private MerchantRecipe trade; -+ -+ public PlayerPurchaseEvent(@NotNull Player player, -+ @NotNull MerchantRecipe trade, -+ boolean rewardExp, -+ boolean increaseTradeUses) { -+ super(Objects.requireNonNull(player, "Player cannot be null!")); -+ setTrade(trade); -+ this.rewardExp = rewardExp; -+ this.increaseTradeUses = increaseTradeUses; -+ } -+ -+ /** -+ * Gets the associated trade with this event -+ * @return the trade -+ */ -+ @NotNull -+ public MerchantRecipe getTrade() { -+ return this.trade; -+ } -+ -+ /** -+ * Sets the trade. This is then used to determine the next prices -+ * @param trade the trade to use -+ */ -+ public void setTrade(@NotNull MerchantRecipe trade) { -+ this.trade = Objects.requireNonNull(trade, "Trade cannot be null!"); -+ } -+ -+ /** -+ * @return will trade try to reward exp -+ */ -+ public boolean isRewardingExp() { -+ return this.rewardExp; -+ } -+ -+ /** -+ * Sets whether the trade will try to reward exp -+ * @param rewardExp try to reward exp -+ */ -+ public void setRewardExp(boolean rewardExp) { -+ this.rewardExp = rewardExp; -+ } -+ -+ /** -+ * @return whether or not the trade will count as a use of the trade -+ */ -+ public boolean willIncreaseTradeUses() { -+ return this.increaseTradeUses; -+ } -+ -+ /** -+ * Sets whether or not the trade will count as a use -+ * @param increaseTradeUses true to count/false to not count -+ */ -+ public void setIncreaseTradeUses(boolean increaseTradeUses) { -+ this.increaseTradeUses = increaseTradeUses; -+ } -+ -+ /** -+ * Gets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ * -+ * @return true if this event is cancelled -+ */ -+ @Override -+ public boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ /** -+ * Sets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins. -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+} -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java -new file mode 100755 -index 0000000000000000000000000000000000000000..a41fc186746b87f76347dfcc1f80d0969398322b ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java -@@ -0,0 +1,29 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.entity.AbstractVillager; -+import org.bukkit.entity.Player; -+import org.bukkit.inventory.MerchantRecipe; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player trades with a villager or wandering trader -+ */ -+public class PlayerTradeEvent extends PlayerPurchaseEvent { -+ -+ private final AbstractVillager villager; -+ -+ public PlayerTradeEvent(@NotNull Player player, @NotNull AbstractVillager villager, @NotNull MerchantRecipe trade, boolean rewardExp, boolean increaseTradeUses) { -+ super(player, trade, rewardExp, increaseTradeUses); -+ this.villager = villager; -+ } -+ -+ /** -+ * Gets the Villager or Wandering trader associated with this event -+ * @return the villager or wandering trader -+ */ -+ @NotNull -+ public AbstractVillager getVillager() { -+ return this.villager; -+ } -+ -+} diff --git a/Unmapped-Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/Unmapped-Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch deleted file mode 100644 index eed087f1f6..0000000000 --- a/Unmapped-Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 24 Dec 2020 12:43:30 -0800 -Subject: [PATCH] Add OBSTRUCTED reason to BedEnterResult - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java b/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java -index c7d57e286c11eaa578ff6fd457b02a9ff829aa71..24b371b11347abf31fda4dadde8e0a7af60b181b 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java -@@ -37,6 +37,12 @@ public class PlayerBedEnterEvent extends PlayerEvent implements Cancellable { - * Entering the bed is prevented due to the player being too far away. - */ - TOO_FAR_AWAY, -+ // Paper start -+ /** -+ * Bed was obstructed. -+ */ -+ OBSTRUCTED, -+ // Paper end - /** - * Entering the bed is prevented due to there being monsters nearby. - */ diff --git a/Unmapped-Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch b/Unmapped-Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch deleted file mode 100644 index ddc1efeb9e..0000000000 --- a/Unmapped-Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Wed, 25 Nov 2020 23:21:32 -0800 -Subject: [PATCH] Add TargetHitEvent API - - -diff --git a/src/main/java/io/papermc/paper/event/block/TargetHitEvent.java b/src/main/java/io/papermc/paper/event/block/TargetHitEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..cc067ae118af9957b1b9f5c8d45f63f9154f4942 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/TargetHitEvent.java -@@ -0,0 +1,69 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.block.BlockFace; -+import org.bukkit.entity.Projectile; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.ProjectileHitEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a Target Block is hit by a projectile. -+ *

    -+ * Cancelling this event will stop the Target from emitting a redstone signal, -+ * and in the case that the shooter is a player, will stop them from receiving -+ * advancement criteria. -+ */ -+public class TargetHitEvent extends ProjectileHitEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ private int signalStrength; -+ -+ public TargetHitEvent(@NotNull Projectile projectile, @NotNull Block block, @NotNull BlockFace blockFace, int signalStrength) { -+ super(projectile, null, block, blockFace); -+ this.signalStrength = signalStrength; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ /** -+ * Gets the strength of the redstone signal to be emitted by the Target block -+ * -+ * @return the strength of the redstone signal to be emitted -+ */ -+ public int getSignalStrength() { -+ return signalStrength; -+ } -+ -+ /** -+ * Sets the strength of the redstone signal to be emitted by the Target block -+ * -+ * @param signalStrength the strength of the redstone signal to be emitted -+ */ -+ public void setSignalStrength(int signalStrength) { -+ if (signalStrength < 0 || signalStrength > 15) { -+ throw new IllegalArgumentException("Signal strength out of range (" + signalStrength + "), must be in range [0,15]"); -+ } -+ this.signalStrength = signalStrength; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch b/Unmapped-Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch deleted file mode 100644 index 87283b0984..0000000000 --- a/Unmapped-Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 30 Dec 2020 17:27:27 -0500 -Subject: [PATCH] Additional Block Material API's - -Faster version for isSolid() that utilizes NMS's state for isSolid instead of the slower -process to do this in the Bukkit API - -Adds API for buildable, replaceable, burnable too. - -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 6933fd6ad353a2d008c4a64c52a64bf36bd8035c..0c72d00ad238ab69d7ae0941e3ecb6c86e71624d 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -427,6 +427,42 @@ public interface Block extends Metadatable { - */ - boolean isLiquid(); - -+ // Paper start -+ /** -+ * Check if this block is solid -+ *

    -+ * Determined by Minecraft, typically a block a player can use to place a new block to build things. -+ * An example of a non buildable block would be liquids, flowers, or fire -+ * -+ * @return true if block is buildable -+ */ -+ boolean isBuildable(); -+ /** -+ * Check if this block is burnable -+ *

    -+ * Determined by Minecraft, typically a block that fire can destroy (Wool, Wood) -+ * -+ * @return true if block is burnable -+ */ -+ boolean isBurnable(); -+ /** -+ * Check if this block is replaceable -+ *

    -+ * Determined by Minecraft, representing a block that is not AIR that you can still place a new block at, such as flowers. -+ * @return true if block is replaceable -+ */ -+ boolean isReplaceable(); -+ /** -+ * Check if this block is solid -+ *

    -+ * Determined by Minecraft, typically a block a player can stand on and can't be passed through. -+ * -+ * This API is faster than accessing Material#isSolid as it avoids a material lookup and switch statement. -+ * @return true if block is solid -+ */ -+ boolean isSolid(); -+ // Paper end -+ - /** - * Gets the temperature of this block. - *

    diff --git a/Unmapped-Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch b/Unmapped-Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch deleted file mode 100644 index d6cdb8862b..0000000000 --- a/Unmapped-Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Thu, 31 Dec 2020 12:48:38 +1000 -Subject: [PATCH] Add API to get Material from Boats and Minecarts - - -diff --git a/src/main/java/org/bukkit/entity/Boat.java b/src/main/java/org/bukkit/entity/Boat.java -index 24751b5c4e3bc24bdfa85af8f6fcba37413aa002..e0d0537606d4f9a3fe588ebf7d02f314c0359335 100644 ---- a/src/main/java/org/bukkit/entity/Boat.java -+++ b/src/main/java/org/bukkit/entity/Boat.java -@@ -1,5 +1,6 @@ - package org.bukkit.entity; - -+import org.bukkit.Material; - import org.bukkit.TreeSpecies; - import org.jetbrains.annotations.NotNull; - -@@ -103,4 +104,14 @@ public interface Boat extends Vehicle { - */ - @Deprecated - public void setWorkOnLand(boolean workOnLand); -+ -+ // Paper start -+ /** -+ * Gets the {@link Material} that represents this Boat type. -+ * -+ * @return the boat material. -+ */ -+ @NotNull -+ public Material getBoatMaterial(); -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/entity/Minecart.java b/src/main/java/org/bukkit/entity/Minecart.java -index 95c79c5fa0c4e30201f887da6467ce5f81c8a255..53b042f8ebbbf6ee77435b93d4e89371375cc515 100644 ---- a/src/main/java/org/bukkit/entity/Minecart.java -+++ b/src/main/java/org/bukkit/entity/Minecart.java -@@ -1,5 +1,6 @@ - package org.bukkit.entity; - -+import org.bukkit.Material; - import org.bukkit.block.data.BlockData; - import org.bukkit.material.MaterialData; - import org.bukkit.util.Vector; -@@ -143,4 +144,14 @@ public interface Minecart extends Vehicle { - * @return the current block offset for this minecart. - */ - public int getDisplayBlockOffset(); -+ -+ // Paper start -+ /** -+ * Gets the {@link Material} that represents this Minecart type. -+ * -+ * @return the minecart material. -+ */ -+ @NotNull -+ public Material getMinecartMaterial(); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch b/Unmapped-Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch deleted file mode 100644 index d9cd5a9f01..0000000000 --- a/Unmapped-Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterVector -Date: Tue, 13 Aug 2019 19:44:19 -0700 -Subject: [PATCH] Add PlayerFlowerPotManipulateEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerFlowerPotManipulateEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerFlowerPotManipulateEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4c141f3d8f668cdf9c75865a8e3ecbd012d9e521 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerFlowerPotManipulateEvent.java -@@ -0,0 +1,82 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player places an item in or takes an item out of a flowerpot. -+ */ -+public class PlayerFlowerPotManipulateEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ private final Block flowerpot; -+ @NotNull -+ private final ItemStack item; -+ private final boolean placing; -+ -+ private boolean cancel = false; -+ -+ public PlayerFlowerPotManipulateEvent(@NotNull final Player player, @NotNull final Block flowerpot, @NotNull final ItemStack item, final boolean placing) { -+ super(player); -+ this.flowerpot = flowerpot; -+ this.item = item; -+ this.placing = placing; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancel; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancel = cancel; -+ } -+ -+ /** -+ * Gets the flowerpot that is involved in this event. -+ * -+ * @return the flowerpot that is involved with this event -+ */ -+ @NotNull -+ public Block getFlowerpot() { -+ return flowerpot; -+ } -+ -+ /** -+ * Gets the item being placed, or taken from, the flower pot. -+ * Check if placing with {@link #isPlacing()}. -+ * -+ * @return the item placed, or taken from, the flowerpot -+ */ -+ @NotNull -+ public ItemStack getItem() { -+ return item; -+ } -+ -+ /** -+ * Gets if the item is being placed into the flowerpot. -+ * -+ * @return if the item is being placed into the flowerpot -+ */ -+ public boolean isPlacing() { -+ return placing; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch b/Unmapped-Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch deleted file mode 100644 index e2a1a8350e..0000000000 --- a/Unmapped-Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 18 Nov 2020 11:32:15 -0800 -Subject: [PATCH] Zombie API - breaking doors - - -diff --git a/src/main/java/org/bukkit/entity/Zombie.java b/src/main/java/org/bukkit/entity/Zombie.java -index 1217576e6f08abf0175ab800cfca058d5deda116..a39fbc9fa0903be8ed8e89f3ef39f93c02dfc90b 100644 ---- a/src/main/java/org/bukkit/entity/Zombie.java -+++ b/src/main/java/org/bukkit/entity/Zombie.java -@@ -140,5 +140,19 @@ public interface Zombie extends Monster, Ageable { - * @param shouldBurnInDay True to burn in sunlight - */ - void setShouldBurnInDay(boolean shouldBurnInDay); -+ -+ /** -+ * Check if this zombie can break doors -+ * -+ * @return True if zombie can break doors -+ */ -+ boolean canBreakDoors(); -+ -+ /** -+ * Sets if this zombie can break doors -+ * -+ * @param canBreakDoors True if zombie can break doors -+ */ -+ void setCanBreakDoors(boolean canBreakDoors); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch b/Unmapped-Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch deleted file mode 100644 index f484d40cca..0000000000 --- a/Unmapped-Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 7 Oct 2020 12:04:17 -0400 -Subject: [PATCH] Add EntityLoadCrossbowEvent - - -diff --git a/src/main/java/io/papermc/paper/event/entity/EntityLoadCrossbowEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityLoadCrossbowEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..287f487b266d5c12fcf6f028452735e314d55636 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/entity/EntityLoadCrossbowEvent.java -@@ -0,0 +1,101 @@ -+package io.papermc.paper.event.entity; -+ -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.inventory.EquipmentSlot; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when a LivingEntity loads a crossbow with a projectile. -+ */ -+public class EntityLoadCrossbowEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private final ItemStack crossbow; -+ private final EquipmentSlot hand; -+ private boolean cancelled; -+ private boolean consumeItem = true; -+ -+ public EntityLoadCrossbowEvent(@NotNull LivingEntity entity, @Nullable ItemStack crossbow, @NotNull EquipmentSlot hand) { -+ super(entity); -+ this.crossbow = crossbow; -+ this.hand = hand; -+ } -+ -+ @NotNull -+ @Override -+ public LivingEntity getEntity() { -+ return (LivingEntity) entity; -+ } -+ -+ /** -+ * Gets the crossbow {@link ItemStack} being loaded. -+ * -+ * @return the crossbow involved in this event -+ */ -+ @Nullable -+ public ItemStack getCrossbow() { -+ return crossbow; -+ } -+ -+ /** -+ * Gets the hand from which the crossbow was loaded. -+ * -+ * @return the hand -+ */ -+ @NotNull -+ public EquipmentSlot getHand() { -+ return hand; -+ } -+ -+ /** -+ * -+ * @return should the itemstack be consumed -+ */ -+ public boolean shouldConsumeItem() { -+ return consumeItem; -+ } -+ -+ /** -+ * -+ * @param consume should the item be consumed -+ */ -+ public void setConsumeItem(boolean consume) { -+ this.consumeItem = consume; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Set whether or not to cancel the crossbow being loaded. If canceled, the -+ * projectile that would be loaded into the crossbow will not be consumed. -+ * -+ * If set to false, and this event is pertaining to a player entity, -+ * it's recommended that a call to {@link Player#updateInventory()} is made -+ * as the client may think the server still loaded an item into the crossbow. -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch b/Unmapped-Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch deleted file mode 100644 index 8ef5f7efcd..0000000000 --- a/Unmapped-Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 20 Dec 2020 16:41:44 -0800 -Subject: [PATCH] Added WorldGameRuleChangeEvent - - -diff --git a/src/main/java/io/papermc/paper/event/world/WorldGameRuleChangeEvent.java b/src/main/java/io/papermc/paper/event/world/WorldGameRuleChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..20c25a0f9d65188402e8bb3981348bc6462904bf ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/world/WorldGameRuleChangeEvent.java -@@ -0,0 +1,91 @@ -+package io.papermc.paper.event.world; -+ -+import org.bukkit.GameRule; -+import org.bukkit.World; -+import org.bukkit.command.CommandSender; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.world.WorldEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when a world's gamerule is changed, either by command or by api. -+ */ -+public class WorldGameRuleChangeEvent extends WorldEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private final CommandSender commandSender; -+ private final GameRule gameRule; -+ private String value; -+ private boolean cancelled; -+ -+ public WorldGameRuleChangeEvent(@NotNull World world, @Nullable CommandSender commandSender, @NotNull GameRule gameRule, @NotNull String value) { -+ super(world); -+ this.commandSender = commandSender; -+ this.gameRule = gameRule; -+ this.value = value; -+ } -+ -+ /** -+ * Gets the command sender associated with this event. -+ * -+ * @return {@code null} if the gamerule was changed via api, otherwise the {@link CommandSender}. -+ */ -+ @Nullable -+ public CommandSender getCommandSender() { -+ return commandSender; -+ } -+ -+ /** -+ * Gets the game rule associated with this event. -+ * -+ * @return the gamerule being changed. -+ */ -+ @NotNull -+ public GameRule getGameRule() { -+ return gameRule; -+ } -+ -+ /** -+ * Gets the new value of the gamerule. -+ * -+ * @return the new value of the gamerule. -+ */ -+ @NotNull -+ public String getValue() { -+ return value; -+ } -+ -+ /** -+ * Sets the new value of this gamerule. -+ * -+ * @param value the new value of the gamerule. -+ */ -+ public void setValue(@NotNull String value) { -+ this.value = value; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch b/Unmapped-Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch deleted file mode 100644 index de081bbae7..0000000000 --- a/Unmapped-Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Dec 2020 20:04:16 -0800 -Subject: [PATCH] Added ServerResourcesReloadedEvent - - -diff --git a/src/main/java/io/papermc/paper/event/server/ServerResourcesReloadedEvent.java b/src/main/java/io/papermc/paper/event/server/ServerResourcesReloadedEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7a8d6815c17a107039399298f7ac9f0612faee02 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/server/ServerResourcesReloadedEvent.java -@@ -0,0 +1,48 @@ -+package io.papermc.paper.event.server; -+ -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.server.ServerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when resources such as datapacks are reloaded (e.g. /minecraft:reload) -+ *

    -+ * Intended for use to re-register custom recipes, advancements that may be lost during a reload like this. -+ *

    -+ */ -+public class ServerResourcesReloadedEvent extends ServerEvent { -+ -+ public static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private final Cause cause; -+ -+ public ServerResourcesReloadedEvent(@NotNull Cause cause) { -+ this.cause = cause; -+ } -+ -+ /** -+ * Gets the cause of the resource reload. -+ * -+ * @return the reload cause -+ */ -+ @NotNull -+ public Cause getCause() { -+ return cause; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ public enum Cause { -+ COMMAND, -+ PLUGIN, -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch b/Unmapped-Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch deleted file mode 100644 index 126714b965..0000000000 --- a/Unmapped-Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheViperShow <29604693+TheViperShow@users.noreply.github.com> -Date: Wed, 22 Apr 2020 09:40:23 +0200 -Subject: [PATCH] Add BlockFailedDispenseEvent - - -diff --git a/src/main/java/io/papermc/paper/event/block/BlockFailedDispenseEvent.java b/src/main/java/io/papermc/paper/event/block/BlockFailedDispenseEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..dab794341170ed10d5a05c1b4c180d164e0f70e2 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/BlockFailedDispenseEvent.java -@@ -0,0 +1,57 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a block tries to dispense an item, but its inventory is empty. -+ */ -+public class BlockFailedDispenseEvent extends BlockEvent { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ private boolean shouldPlayEffect = true; -+ -+ public BlockFailedDispenseEvent(@NotNull Block theBlock) { -+ super(theBlock); -+ } -+ -+ /** -+ * @return if the effect should be played -+ */ -+ public boolean shouldPlayEffect() { -+ return this.shouldPlayEffect; -+ } -+ -+ /** -+ * Sets if the effect for empty dispensers should be played -+ * -+ * @param playEffect if the effect should be played -+ */ -+ public void shouldPlayEffect(boolean playEffect) { -+ this.shouldPlayEffect = playEffect; -+ } -+ -+ /** -+ * {@inheritDoc} -+ * -+ * @return {@link #shouldPlayEffect()} -+ */ -+ @Override -+ public boolean callEvent() { -+ super.callEvent(); -+ return this.shouldPlayEffect(); -+ } -+ -+ @Override -+ public @NotNull -+ HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ public static @NotNull -+ HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch b/Unmapped-Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch deleted file mode 100644 index 2b65c3a245..0000000000 --- a/Unmapped-Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 23 Nov 2020 12:58:16 -0800 -Subject: [PATCH] Added PlayerLecternPageChangeEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerLecternPageChangeEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerLecternPageChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..26370e46e4a12e3470e9bb747fac5786a7305810 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerLecternPageChangeEvent.java -@@ -0,0 +1,115 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.block.Lectern; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class PlayerLecternPageChangeEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private boolean cancelled; -+ private final Lectern lectern; -+ private final ItemStack book; -+ private final PageChangeDirection pageChangeDirection; -+ private final int oldPage; -+ private int newPage; -+ -+ public PlayerLecternPageChangeEvent(@NotNull Player player, @NotNull Lectern lectern, @NotNull ItemStack book, @NotNull PageChangeDirection pageChangeDirection, int oldPage, int newPage) { -+ super(player); -+ this.lectern = lectern; -+ this.book = book; -+ this.pageChangeDirection = pageChangeDirection; -+ this.oldPage = oldPage; -+ this.newPage = newPage; -+ } -+ -+ /** -+ * Gets the lectern involved. -+ * -+ * @return the Lectern -+ */ -+ @NotNull -+ public Lectern getLectern() { -+ return lectern; -+ } -+ -+ /** -+ * Gets the current ItemStack on the lectern. -+ * -+ * @return the ItemStack on the Lectern -+ */ -+ @NotNull -+ public ItemStack getBook() { -+ return this.book; -+ } -+ -+ /** -+ * Gets the page change direction. This is essentially returns which button the player clicked, left or right. -+ * -+ * @return the page change direction -+ */ -+ @NotNull -+ public PageChangeDirection getPageChangeDirection() { -+ return pageChangeDirection; -+ } -+ -+ /** -+ * Gets the page changed from. Pages are 0-indexed. -+ * -+ * @return the page changed from -+ */ -+ public int getOldPage() { -+ return oldPage; -+ } -+ -+ /** -+ * Gets the page changed to. Pages are 0-indexed. -+ * -+ * @return the page changed to -+ */ -+ public int getNewPage() { -+ return newPage; -+ } -+ -+ /** -+ * Sets the page changed to. Pages are 0-indexed. -+ * Page indices that are greater than the number of pages will show the last page. -+ * -+ * @param newPage the new paged changed to -+ */ -+ public void setNewPage(int newPage) { -+ this.newPage = newPage; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+ -+ public enum PageChangeDirection { -+ LEFT, -+ RIGHT, -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch b/Unmapped-Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch deleted file mode 100644 index 5677026956..0000000000 --- a/Unmapped-Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 25 Nov 2020 16:33:42 -0800 -Subject: [PATCH] Added PlayerLoomPatternSelectEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerLoomPatternSelectEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerLoomPatternSelectEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8cb05709f7cb5dee993ff6fea1626c41b90a7d8b ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerLoomPatternSelectEvent.java -@@ -0,0 +1,77 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.block.banner.PatternType; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.LoomInventory; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player selects a banner patten in a loom inventory. -+ */ -+public class PlayerLoomPatternSelectEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private boolean cancelled; -+ private final LoomInventory loomInventory; -+ private PatternType patternType; -+ -+ public PlayerLoomPatternSelectEvent(@NotNull Player player, @NotNull LoomInventory loomInventory, @NotNull PatternType patternType) { -+ super(player); -+ this.loomInventory = loomInventory; -+ this.patternType = patternType; -+ } -+ -+ /** -+ * Gets the loom inventory involved. -+ * -+ * @return the loom inventory -+ */ -+ @NotNull -+ public LoomInventory getLoomInventory() { -+ return loomInventory; -+ } -+ -+ /** -+ * Gets the pattern type selected. -+ * -+ * @return the pattern type -+ */ -+ @NotNull -+ public PatternType getPatternType() { -+ return patternType; -+ } -+ -+ /** -+ * Sets the pattern type selected. -+ * -+ * @param patternType the pattern type -+ */ -+ public void setPatternType(@NotNull PatternType patternType) { -+ this.patternType = patternType; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch b/Unmapped-Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch deleted file mode 100644 index 2a40d2b44f..0000000000 --- a/Unmapped-Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 3 Dec 2020 14:04:57 -0800 -Subject: [PATCH] Better AnnotationTest printout - - -diff --git a/pom.xml b/pom.xml -index 6b71d9a397dd5b72320402a47b8e7197d24e061c..73fbd5d5a591871a3a386fb5c455cd96a3992e7a 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -257,6 +257,19 @@ - true - - -+ -+ org.apache.maven.plugins -+ maven-surefire-plugin -+ 2.22.2 -+ -+ -+ -+ listener -+ io.papermc.paper.JunitEventListener -+ -+ -+ -+ - - org.apache.maven.plugins - maven-javadoc-plugin -diff --git a/src/test/java/io/papermc/paper/JunitEventListener.java b/src/test/java/io/papermc/paper/JunitEventListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..072ac1a96394b8d494f42fca8dfe08115eaed3fe ---- /dev/null -+++ b/src/test/java/io/papermc/paper/JunitEventListener.java -@@ -0,0 +1,6 @@ -+package io.papermc.paper; -+ -+import org.junit.runner.notification.RunListener; -+ -+public class JunitEventListener extends RunListener { -+} -diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 03229d5f4ec36a82197beb391356d791ff67fb2f..19271057cf24329757c9419fa6c97848e008a96c 100644 ---- a/src/test/java/org/bukkit/AnnotationTest.java -+++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -107,13 +107,18 @@ public class AnnotationTest { - - Collections.sort(errors); - -- System.out.println(errors.size() + " missing annotation(s):"); -+ StringBuilder builder = new StringBuilder() -+ .append("There ") -+ .append(errors.size() != 1 ? "are " : "is ") -+ .append(errors.size()) -+ .append(" missing annotation") -+ .append(errors.size() != 1 ? "s:\n" : ":\n"); -+ - for (String message : errors) { -- System.out.print("\t"); -- System.out.println(message); -+ builder.append("\t").append(message).append("\n"); - } - -- Assert.fail("There " + errors.size() + " are missing annotation(s)"); -+ Assert.fail(builder.toString()); - } - - private static void collectClasses(@NotNull File from, @NotNull Map to) throws IOException { diff --git a/Unmapped-Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch b/Unmapped-Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch deleted file mode 100644 index 197d00ca14..0000000000 --- a/Unmapped-Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Mon, 4 Jan 2021 16:40:55 +1000 -Subject: [PATCH] Add API to get exact interaction point in PlayerInteractEvent - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java b/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java -index 1208e1f8c2163d83c5b12bbb9b7ac044c72380e0..a01f86e6aba8b66ecc713da0787cd861e2930a2a 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.player; - -+import org.bukkit.Location; - import org.bukkit.Material; - import org.bukkit.block.Block; - import org.bukkit.block.BlockFace; -@@ -34,22 +35,30 @@ public class PlayerInteractEvent extends PlayerEvent implements Cancellable { - private Result useClickedBlock; - private Result useItemInHand; - private EquipmentSlot hand; -+ private Location interactionPoint; // Paper - - public PlayerInteractEvent(@NotNull final Player who, @NotNull final Action action, @Nullable final ItemStack item, @Nullable final Block clickedBlock, @NotNull final BlockFace clickedFace) { - this(who, action, item, clickedBlock, clickedFace, EquipmentSlot.HAND); - } - - public PlayerInteractEvent(@NotNull final Player who, @NotNull final Action action, @Nullable final ItemStack item, @Nullable final Block clickedBlock, @NotNull final BlockFace clickedFace, @Nullable final EquipmentSlot hand) { -+ // Paper start - Add interactionPoint -+ this(who, action, item, clickedBlock, clickedFace, hand, null); -+ } -+ -+ public PlayerInteractEvent(@NotNull final Player who, @NotNull final Action action, @Nullable final ItemStack item, @Nullable final Block clickedBlock, @NotNull final BlockFace clickedFace, @Nullable final EquipmentSlot hand, @Nullable final Location interactionPoint) { - super(who); - this.action = action; - this.item = item; - this.blockClicked = clickedBlock; - this.blockFace = clickedFace; - this.hand = hand; -+ this.interactionPoint = interactionPoint; - - useItemInHand = Result.DEFAULT; - useClickedBlock = clickedBlock == null ? Result.DENY : Result.ALLOW; - } -+ // Paper end - - /** - * Returns the action type -@@ -221,6 +230,18 @@ public class PlayerInteractEvent extends PlayerEvent implements Cancellable { - return hand; - } - -+ // Paper start -+ /** -+ * The exact point at which the interaction occurred. May be null. -+ * -+ * @return the exact interaction point. May be null. -+ */ -+ @Nullable -+ public Location getInteractionPoint() { -+ return interactionPoint; -+ } -+ // Paper end -+ - @NotNull - @Override - public HandlerList getHandlers() { diff --git a/Unmapped-Spigot-API-Patches/0259-Add-sendOpLevel-API.patch b/Unmapped-Spigot-API-Patches/0259-Add-sendOpLevel-API.patch deleted file mode 100644 index d1a8696b2d..0000000000 --- a/Unmapped-Spigot-API-Patches/0259-Add-sendOpLevel-API.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Tue, 29 Dec 2020 15:02:57 +0100 -Subject: [PATCH] Add sendOpLevel API - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 7aa9fb852dce23c53fee80e97e0dcdb278ae82ba..68a03821a5f06308a9c51fdf107d3924c44886c8 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1929,6 +1929,17 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - @Nullable - Firework boostElytra(@NotNull ItemStack firework); -+ -+ /** -+ * Send a packet to the player indicating its operator status level. -+ *

    -+ * Note: This will not persist across more than the current connection, and setting the player's operator -+ * status as a later point will override the effects of this. -+ * -+ * @param level The level to send to the player. Must be in {@code [0, 4]}. -+ * @throws IllegalArgumentException If the level is negative or greater than {@code 4} (i.e. not within {@code [0, 4]}). -+ */ -+ void sendOpLevel(byte level); - // Paper end - - // Spigot start diff --git a/Unmapped-Spigot-API-Patches/0260-Add-StructureLocateEvent.patch b/Unmapped-Spigot-API-Patches/0260-Add-StructureLocateEvent.patch deleted file mode 100644 index 88c14d8ea6..0000000000 --- a/Unmapped-Spigot-API-Patches/0260-Add-StructureLocateEvent.patch +++ /dev/null @@ -1,167 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: dfsek -Date: Tue, 15 Sep 2020 21:59:16 -0700 -Subject: [PATCH] Add StructureLocateEvent - - -diff --git a/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java b/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..45b6694fc5741831e2df638b1f760a3ca28a4907 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java -@@ -0,0 +1,155 @@ -+package io.papermc.paper.event.world; -+ -+import org.bukkit.Location; -+import org.bukkit.StructureType; -+import org.bukkit.World; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.world.WorldEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called before a structure/feature is located. -+ * This happens when: -+ *

      -+ *
    • The /locate command is used.
    • -+ *
    • An Eye of Ender is used.
    • -+ *
    • An Explorer/Treasure Map is activated.
    • -+ *
    • {@link World#locateNearestStructure(Location, StructureType, int, boolean)} is invoked.
    • -+ *
    -+ */ -+public class StructureLocateEvent extends WorldEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private final Location origin; -+ private Location result = null; -+ private StructureType type; -+ private int radius; -+ private boolean findUnexplored; -+ private boolean cancelled = false; -+ -+ public StructureLocateEvent(@NotNull World world, @NotNull Location origin, @NotNull StructureType structureType, int radius, boolean findUnexplored) { -+ super(world); -+ this.origin = origin; -+ this.type = structureType; -+ this.radius = radius; -+ this.findUnexplored = findUnexplored; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ /** -+ * Gets the location set as the structure location, if it was defined. -+ *

    -+ * Returns {@code null} if it has not been set by {@link StructureLocateEvent#setResult(Location)}. -+ * Since this event fires before the search is done, the actual location is unknown at this point. -+ * -+ * @return The result location, if it has been set. null if it has not. -+ * @see World#locateNearestStructure(Location, StructureType, int, boolean) -+ */ -+ @Nullable -+ public Location getResult() { -+ return result; -+ } -+ -+ /** -+ * Sets the result {@link Location}. This causes the search to be skipped, and the location passed here to be used as the result. -+ * -+ * @param result the {@link Location} of the structure. -+ */ -+ public void setResult(@Nullable Location result) { -+ this.result = result; -+ } -+ -+ /** -+ * Gets the {@link StructureType} that is to be located. -+ * -+ * @return the structure type. -+ */ -+ @NotNull -+ public StructureType getType() { -+ return type; -+ } -+ -+ /** -+ * Sets the {@link StructureType} that is to be located. -+ * -+ * @param type the structure type. -+ */ -+ public void setType(@NotNull StructureType type) { -+ this.type = type; -+ } -+ -+ /** -+ * Gets the {@link Location} from which the search is to be conducted. -+ * -+ * @return {@link Location} where search begins -+ */ -+ @NotNull -+ public Location getOrigin() { -+ return origin; -+ } -+ -+ /** -+ * Gets the search radius in which to attempt locating the structure. -+ *

    -+ * This radius may not always be obeyed during the structure search! -+ * -+ * @return the search radius. -+ */ -+ public int getRadius() { -+ return radius; -+ } -+ -+ /** -+ * Sets the search radius in which to attempt locating the structure. -+ *

    -+ * This radius may not always be obeyed during the structure search! -+ * -+ * @param radius the search radius. -+ */ -+ public void setRadius(int radius) { -+ this.radius = radius; -+ } -+ -+ /** -+ * Gets whether to search exclusively for unexplored structures. -+ *

    -+ * As with the search radius, this value is not always obeyed. -+ * -+ * @return Whether to search for only unexplored structures. -+ */ -+ public boolean shouldFindUnexplored() { -+ return findUnexplored; -+ } -+ -+ /** -+ * Sets whether to search exclusively for unexplored structures. -+ *

    -+ * As with the search radius, this value is not always obeyed. -+ * -+ * @param findUnexplored Whether to search for only unexplored structures. -+ */ -+ public void setFindUnexplored(boolean findUnexplored) { -+ this.findUnexplored = findUnexplored; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch b/Unmapped-Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch deleted file mode 100644 index e7986f5bb1..0000000000 --- a/Unmapped-Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CDFN -Date: Tue, 7 Jul 2020 17:53:23 +0200 -Subject: [PATCH] Return chat component with empty text instead of throwing - exception - - -diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java -index 664de64b020cf9090a2fbee0afe2bfaf150adc3c..b06995aa57aa9cba0bb59f1d26d81015619a08e6 100644 ---- a/src/main/java/org/bukkit/inventory/InventoryView.java -+++ b/src/main/java/org/bukkit/inventory/InventoryView.java -@@ -450,7 +450,7 @@ public abstract class InventoryView { - /** - * Get the title of this inventory window. - * -- * @return The title. -+ * @return The title or empty string when title is {@code null}. - */ - @NotNull - public /*abstract*/ net.kyori.adventure.text.Component title() { diff --git a/Unmapped-Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch b/Unmapped-Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch deleted file mode 100644 index 5850391175..0000000000 --- a/Unmapped-Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Sun, 17 Jan 2021 13:15:54 +1000 -Subject: [PATCH] Add BlockPreDispenseEvent - - -diff --git a/src/main/java/io/papermc/paper/event/block/BlockPreDispenseEvent.java b/src/main/java/io/papermc/paper/event/block/BlockPreDispenseEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..07aad3f4ff60a6a6de69634b0d31926e9c00e77b ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/BlockPreDispenseEvent.java -@@ -0,0 +1,60 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+ -+public class BlockPreDispenseEvent extends BlockEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled = false; -+ private final ItemStack itemStack; -+ private final int slot; -+ -+ public BlockPreDispenseEvent(@NotNull Block block, @NotNull ItemStack itemStack, int slot) { -+ super(block); -+ this.itemStack = itemStack; -+ this.slot = slot; -+ } -+ -+ /** -+ * Gets the {@link ItemStack} to be dispensed. -+ * -+ * @return The item to be dispensed -+ */ -+ @NotNull -+ public ItemStack getItemStack() { -+ return itemStack; -+ } -+ -+ /** -+ * Gets the inventory slot of the dispenser to dispense from. -+ * -+ * @return The inventory slot -+ */ -+ public int getSlot() { -+ return slot; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch b/Unmapped-Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch deleted file mode 100644 index 53c933017b..0000000000 --- a/Unmapped-Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 20:03:40 -0800 -Subject: [PATCH] Added Vanilla Entity Tags - - -diff --git a/src/main/java/org/bukkit/Tag.java b/src/main/java/org/bukkit/Tag.java -index 88ea8b6c5c2c4d2116f646341de62590718bc28c..a2da2cbef6c09b9defbdf97e79cfb3efd742d439 100644 ---- a/src/main/java/org/bukkit/Tag.java -+++ b/src/main/java/org/bukkit/Tag.java -@@ -589,6 +589,32 @@ public interface Tag extends Keyed { - * Vanilla fluid tag representing water and flowing water. - */ - Tag FLUIDS_WATER = Bukkit.getTag(REGISTRY_FLUIDS, NamespacedKey.minecraft("water"), Fluid.class); -+ // Paper start -+ /** -+ * Key for the build in entity registry -+ */ -+ String REGISTRY_ENTITIES = "entities"; -+ /** -+ * Vanilla entity tag representing arrow entities. -+ */ -+ Tag ARROWS = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("arrows"), org.bukkit.entity.EntityType.class); -+ /** -+ * Vanilla entity tag representing entities that live in beehives -+ */ -+ Tag BEEHIVE_INHABITORS = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("beehive_inhabitors"), org.bukkit.entity.EntityType.class); -+ /** -+ * Vanilla entity tag representing projectiles that impact -+ */ -+ Tag IMPACT_PROJECTILES = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("impact_projectiles"), org.bukkit.entity.EntityType.class); -+ /** -+ * Vanilla entity tag for village raiders -+ */ -+ Tag RAIDERS = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("raiders"), org.bukkit.entity.EntityType.class); -+ /** -+ * Vanilla entity tag for skeleton types -+ */ -+ Tag SKELETONS = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("skeletons"), org.bukkit.entity.EntityType.class); -+ // Paper end - - /** - * Returns whether or not this tag has an entry for the specified item. diff --git a/Unmapped-Spigot-API-Patches/0264-added-Wither-API.patch b/Unmapped-Spigot-API-Patches/0264-added-Wither-API.patch deleted file mode 100644 index dbfc15a42c..0000000000 --- a/Unmapped-Spigot-API-Patches/0264-added-Wither-API.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 5 Jul 2020 15:39:40 -0700 -Subject: [PATCH] added Wither API - - -diff --git a/src/main/java/org/bukkit/entity/Wither.java b/src/main/java/org/bukkit/entity/Wither.java -index 426d3693317cd303d35d8203026b528d87e401d5..8c95cd6933f11076de936854f379e6fc8600b525 100644 ---- a/src/main/java/org/bukkit/entity/Wither.java -+++ b/src/main/java/org/bukkit/entity/Wither.java -@@ -6,4 +6,34 @@ import com.destroystokyo.paper.entity.RangedEntity; - * Represents a Wither boss - */ - public interface Wither extends Monster, Boss, RangedEntity { // Paper -+ // Paper start -+ /** -+ * @return whether the wither is charged -+ */ -+ boolean isCharged(); -+ -+ /** -+ * @return ticks the wither is invulnerable for -+ */ -+ int getInvulnerableTicks(); -+ -+ /** -+ * Sets for how long in the future, the wither should be invulnerable. -+ * -+ * @param ticks ticks the wither is invulnerable for -+ */ -+ void setInvulnerableTicks(int ticks); -+ -+ /** -+ * @return whether the wither can travel through portals -+ */ -+ boolean canTravelThroughPortals(); -+ -+ /** -+ * Sets whether the wither can travel through portals. -+ * -+ * @param value whether the wither can travel through portals -+ */ -+ void setCanTravelThroughPortals(boolean value); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch b/Unmapped-Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch deleted file mode 100644 index 4331e880bb..0000000000 --- a/Unmapped-Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 15:12:18 -0600 -Subject: [PATCH] Added PlayerChangeBeaconEffectEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerChangeBeaconEffectEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerChangeBeaconEffectEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c80183a79713b1e73549911e474a8c585cfdeb52 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerChangeBeaconEffectEvent.java -@@ -0,0 +1,141 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.potion.PotionEffectType; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when a player sets the effect for a beacon -+ */ -+public class PlayerChangeBeaconEffectEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ private PotionEffectType primary; -+ private PotionEffectType secondary; -+ private final Block beacon; -+ private boolean consumeItem = true; -+ -+ private boolean isCancelled; -+ -+ public PlayerChangeBeaconEffectEvent(@NotNull Player player, @Nullable PotionEffectType primary, @Nullable PotionEffectType secondary, @Nullable Block beacon) { -+ super(player); -+ this.primary = primary; -+ this.secondary = secondary; -+ this.isCancelled = false; -+ this.beacon = beacon; -+ } -+ -+ /** -+ * @return the primary effect -+ */ -+ @Nullable public PotionEffectType getPrimary() { -+ return primary; -+ } -+ -+ /** -+ * Sets the primary effect -+ *

    -+ * NOTE: The primary effect still has to be one of the valid effects for a beacon. -+ * -+ * @param primary the primary effect -+ */ -+ public void setPrimary(@Nullable PotionEffectType primary) { -+ this.primary = primary; -+ } -+ -+ /** -+ * @return the secondary effect -+ */ -+ @Nullable public PotionEffectType getSecondary() { -+ return secondary; -+ } -+ -+ /** -+ * Sets the secondary effect -+ *

    -+ * This only has an effect when the beacon is able to accept a secondary effect. -+ * NOTE: The secondary effect still has to be a valid effect for a beacon. -+ * -+ * @param secondary the secondary effect -+ */ -+ public void setSecondary(@Nullable PotionEffectType secondary) { -+ this.secondary = secondary; -+ } -+ -+ /** -+ * @return the beacon block associated with this event, or null if not found -+ */ -+ @Nullable -+ public Block getBeacon() { -+ return beacon; -+ } -+ -+ /** -+ * Gets if the item used to change the beacon will be consume. -+ *

    -+ * Independant of {@link #isCancelled()}. If the event is cancelled -+ * the item will NOT be consumed. -+ * -+ * @return true if item will be consumed -+ */ -+ public boolean willConsumeItem() { -+ return consumeItem; -+ } -+ -+ /** -+ * Sets if the item used to change the beacon should be consumed. -+ *

    -+ * Independant of {@link #isCancelled()}. If the event is cancelled -+ * the item will NOT be consumed. -+ * -+ * @param consumeItem true if item should be consumed -+ */ -+ public void setConsumeItem(boolean consumeItem) { -+ this.consumeItem = consumeItem; -+ } -+ -+ /** -+ * Gets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ *

    -+ * If a {@link PlayerChangeBeaconEffectEvent} is cancelled, the changes will -+ * not take effect -+ * -+ * @return true if this event is cancelled -+ */ -+ @Override -+ public boolean isCancelled() { -+ return this.isCancelled; -+ } -+ -+ /** -+ * Sets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ *

    -+ * If cancelled, the item will NOT be consumed regardless of what {@link #willConsumeItem()} says -+ *

    -+ * If a {@link PlayerChangeBeaconEffectEvent} is cancelled, the changes will not be applied -+ * or saved. -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.isCancelled = cancel; -+ } -+ -+ @Override -+ public @NotNull HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/Unmapped-Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch deleted file mode 100644 index 1a81930699..0000000000 --- a/Unmapped-Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Fri, 29 Jan 2021 15:13:04 +0100 -Subject: [PATCH] Add dropLeash variable to EntityUnleashEvent - - -diff --git a/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java b/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java -index a33986a0c437a673435206fc337031a7eebdab3b..e0e068799a1868c8e561869015f41f553ef4fbdb 100644 ---- a/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java -+++ b/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java -@@ -10,10 +10,19 @@ import org.jetbrains.annotations.NotNull; - public class EntityUnleashEvent extends EntityEvent { - private static final HandlerList handlers = new HandlerList(); - private final UnleashReason reason; -+ private boolean dropLeash; // Paper - -+ // Paper start - drop leash variable -+ @Deprecated - public EntityUnleashEvent(@NotNull Entity entity, @NotNull UnleashReason reason) { -+ this(entity, reason, false); -+ } -+ -+ public EntityUnleashEvent(@NotNull Entity entity, @NotNull UnleashReason reason, boolean dropLeash) { - super(entity); -+ // Paper end - this.reason = reason; -+ this.dropLeash = dropLeash; // Paper - } - - /** -@@ -26,6 +35,26 @@ public class EntityUnleashEvent extends EntityEvent { - return reason; - } - -+ // Paper start -+ /** -+ * Returns whether a leash item will be dropped. -+ * -+ * @return Whether the leash item will be dropped -+ */ -+ public boolean isDropLeash() { -+ return dropLeash; -+ } -+ -+ /** -+ * Sets whether a leash item should be dropped. -+ * -+ * @param dropLeash Whether the leash item should be dropped -+ */ -+ public void setDropLeash(boolean dropLeash) { -+ this.dropLeash = dropLeash; -+ } -+ // Paper end -+ - @NotNull - @Override - public HandlerList getHandlers() { -diff --git a/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java b/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java -index cf78950b56d4977f6c4d9d98d183bfc5ba3bacc0..68eab1563caba1ee4f52b308f390e4e172667fc5 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java -@@ -13,8 +13,15 @@ public class PlayerUnleashEntityEvent extends EntityUnleashEvent implements Canc - private final Player player; - private boolean cancelled = false; - -+ // Paper start - drop leash variable -+ @Deprecated - public PlayerUnleashEntityEvent(@NotNull Entity entity, @NotNull Player player) { -- super(entity, UnleashReason.PLAYER_UNLEASH); -+ this(entity, player, false); -+ } -+ -+ public PlayerUnleashEntityEvent(@NotNull Entity entity, @NotNull Player player, boolean dropLeash) { -+ super(entity, UnleashReason.PLAYER_UNLEASH, dropLeash); -+ // Paper end - this.player = player; - } - diff --git a/Unmapped-Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch b/Unmapped-Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch deleted file mode 100644 index ce446c46fe..0000000000 --- a/Unmapped-Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 27 Nov 2020 17:13:59 -0800 -Subject: [PATCH] Added PlayerStonecutterRecipeSelectEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerStonecutterRecipeSelectEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerStonecutterRecipeSelectEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fb1bca3a9d12096c9a2b2663f466a8ff5f2b4319 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerStonecutterRecipeSelectEvent.java -@@ -0,0 +1,59 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.StonecutterInventory; -+import org.bukkit.inventory.StonecuttingRecipe; -+import org.jetbrains.annotations.NotNull; -+ -+public class PlayerStonecutterRecipeSelectEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private boolean cancelled; -+ private final StonecutterInventory stonecutterInventory; -+ private StonecuttingRecipe stonecuttingRecipe; -+ -+ public PlayerStonecutterRecipeSelectEvent(@NotNull Player player, @NotNull StonecutterInventory stonecutterInventory, @NotNull StonecuttingRecipe stonecuttingRecipe) { -+ super(player); -+ this.stonecutterInventory = stonecutterInventory; -+ this.stonecuttingRecipe = stonecuttingRecipe; -+ } -+ -+ @NotNull -+ public StonecutterInventory getStonecutterInventory() { -+ return stonecutterInventory; -+ } -+ -+ @NotNull -+ public StonecuttingRecipe getStonecuttingRecipe() { -+ return stonecuttingRecipe; -+ } -+ -+ public void setStonecuttingRecipe(@NotNull StonecuttingRecipe stonecuttingRecipe) { -+ this.stonecuttingRecipe = stonecuttingRecipe; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0268-EntityMoveEvent.patch b/Unmapped-Spigot-API-Patches/0268-EntityMoveEvent.patch deleted file mode 100644 index 0f5a4c5a81..0000000000 --- a/Unmapped-Spigot-API-Patches/0268-EntityMoveEvent.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Tue, 11 Feb 2020 21:56:38 -0600 -Subject: [PATCH] EntityMoveEvent - - -diff --git a/src/main/java/io/papermc/paper/event/entity/EntityMoveEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityMoveEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fae0b1daf733e85d8f691f5ef934b8c0b51db194 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/entity/EntityMoveEvent.java -@@ -0,0 +1,140 @@ -+package io.papermc.paper.event.entity; -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.Location; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Holds information for living entity movement events -+ */ -+public class EntityMoveEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean canceled; -+ private Location from; -+ private Location to; -+ -+ public EntityMoveEvent(@NotNull LivingEntity entity, @NotNull Location from, @NotNull Location to) { -+ super(entity); -+ this.from = from; -+ this.to = to; -+ } -+ -+ @Override -+ @NotNull -+ public LivingEntity getEntity() { -+ return (LivingEntity) entity; -+ } -+ -+ public boolean isCancelled() { -+ return canceled; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ canceled = cancel; -+ } -+ -+ /** -+ * Gets the location this entity moved from -+ * -+ * @return Location the entity moved from -+ */ -+ @NotNull -+ public Location getFrom() { -+ return from; -+ } -+ -+ /** -+ * Sets the location to mark as where the entity moved from -+ * -+ * @param from New location to mark as the entity's previous location -+ */ -+ public void setFrom(@NotNull Location from) { -+ validateLocation(from); -+ this.from = from; -+ } -+ -+ /** -+ * Gets the location this entity moved to -+ * -+ * @return Location the entity moved to -+ */ -+ @NotNull -+ public Location getTo() { -+ return to; -+ } -+ -+ /** -+ * Sets the location that this entity will move to -+ * -+ * @param to New Location this entity will move to -+ */ -+ public void setTo(@NotNull Location to) { -+ validateLocation(to); -+ this.to = to; -+ } -+ -+ /** -+ * Check if the entity has changed position (even within the same block) in the event -+ * -+ * @return whether the entity has changed position or not -+ */ -+ public boolean hasChangedPosition() { -+ return hasExplicitlyChangedPosition() || !from.getWorld().equals(to.getWorld()); -+ } -+ -+ /** -+ * Check if the entity has changed position (even within the same block) in the event, disregarding a possible world change -+ * -+ * @return whether the entity has changed position or not -+ */ -+ public boolean hasExplicitlyChangedPosition() { -+ return from.getX() != to.getX() || from.getY() != to.getY() || from.getZ() != to.getZ(); -+ } -+ -+ /** -+ * Check if the entity has moved to a new block in the event -+ * -+ * @return whether the entity has moved to a new block or not -+ */ -+ public boolean hasChangedBlock() { -+ return hasExplicitlyChangedBlock() || !from.getWorld().equals(to.getWorld()); -+ } -+ -+ /** -+ * Check if the entity has moved to a new block in the event, disregarding a possible world change -+ * -+ * @return whether the entity has moved to a new block or not -+ */ -+ public boolean hasExplicitlyChangedBlock() { -+ return from.getBlockX() != to.getBlockX() || from.getBlockY() != to.getBlockY() || from.getBlockZ() != to.getBlockZ(); -+ } -+ -+ /** -+ * Check if the entity has changed orientation in the event -+ * -+ * @return whether the entity has changed orientation or not -+ */ -+ public boolean hasChangedOrientation() { -+ return from.getPitch() != to.getPitch() || from.getYaw() != to.getYaw(); -+ } -+ -+ private void validateLocation(@NotNull Location loc) { -+ Preconditions.checkArgument(loc != null, "Cannot use null location!"); -+ Preconditions.checkArgument(loc.getWorld() != null, "Cannot use null location with null world!"); -+ } -+ -+ @Override -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0269-add-DragonEggFormEvent.patch b/Unmapped-Spigot-API-Patches/0269-add-DragonEggFormEvent.patch deleted file mode 100644 index c465295e88..0000000000 --- a/Unmapped-Spigot-API-Patches/0269-add-DragonEggFormEvent.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Mon, 25 Jan 2021 14:53:49 +0100 -Subject: [PATCH] add DragonEggFormEvent - - -diff --git a/src/main/java/io/papermc/paper/event/block/DragonEggFormEvent.java b/src/main/java/io/papermc/paper/event/block/DragonEggFormEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5495b87330518363498e1ac5d8f0a832be35fefb ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/DragonEggFormEvent.java -@@ -0,0 +1,63 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.Material; -+import org.bukkit.block.Block; -+import org.bukkit.block.BlockState; -+import org.bukkit.boss.DragonBattle; -+import org.bukkit.entity.EnderDragon; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockFormEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when the {@link EnderDragon} is defeated (killed) in a {@link DragonBattle}, -+ * causing a {@link Material#DRAGON_EGG} (more formally: {@link #getNewState()}) -+ * to possibly appear depending on {@link #isCancelled()}. -+ * This event might be cancelled by default depending on -+ * eg. {@link DragonBattle#hasBeenPreviouslyKilled()} and server configuration. -+ */ -+public class DragonEggFormEvent extends BlockFormEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private final DragonBattle dragonBattle; -+ private boolean cancelled; -+ -+ public DragonEggFormEvent(@NotNull Block block, @NotNull BlockState newState, -+ @NotNull DragonBattle dragonBattle) { -+ super(block, newState); -+ this.dragonBattle = dragonBattle; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ /** -+ * Gets the {@link DragonBattle} associated with this event. -+ * Keep in mind that the {@link EnderDragon} is already dead -+ * when this event is called. -+ * -+ * @return the dragon battle -+ */ -+ @NotNull -+ public DragonBattle getDragonBattle() { -+ return dragonBattle; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch b/Unmapped-Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch deleted file mode 100644 index 984da00f52..0000000000 --- a/Unmapped-Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Wed, 20 Jan 2021 14:25:26 -0600 -Subject: [PATCH] Allow adding items to BlockDropItemEvent - - -diff --git a/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java b/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java -index a0f6f1af304190b4c5db4b284d460f625eeb7801..3dd4bd38e72c04e74e5787fb38ca9abd10bad06b 100644 ---- a/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java -@@ -64,7 +64,7 @@ public class BlockDropItemEvent extends BlockEvent implements Cancellable { - * Gets list of the Item drops caused by the block break. - * - * This list is mutable - removing an item from it will cause it to not -- * drop. It is not legal however to add new items to the list. -+ * drop. Adding to the list is allowed. - * - * @return The Item the block caused to drop - */ diff --git a/Unmapped-Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/Unmapped-Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch deleted file mode 100644 index 6de1a3b396..0000000000 --- a/Unmapped-Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aleksander Jagiello -Date: Sun, 24 Jan 2021 22:17:29 +0100 -Subject: [PATCH] Add getMainThreadExecutor to BukkitScheduler - - -diff --git a/src/main/java/org/bukkit/scheduler/BukkitScheduler.java b/src/main/java/org/bukkit/scheduler/BukkitScheduler.java -index ac140fc2c638e22e06b2920db3e376ab9e8c3733..f5e3bfd22d4d38182065b5215e5f78d9bb13381e 100644 ---- a/src/main/java/org/bukkit/scheduler/BukkitScheduler.java -+++ b/src/main/java/org/bukkit/scheduler/BukkitScheduler.java -@@ -458,4 +458,15 @@ public interface BukkitScheduler { - @Deprecated - @NotNull - public BukkitTask runTaskTimerAsynchronously(@NotNull Plugin plugin, @NotNull BukkitRunnable task, long delay, long period) throws IllegalArgumentException; -+ -+ // Paper start - add getMainThreadExecutor -+ /** -+ * Returns an executor that will run tasks on the next server tick. -+ * -+ * @param plugin the reference to the plugin scheduling tasks -+ * @return an executor associated with the given plugin -+ */ -+ @NotNull -+ public java.util.concurrent.Executor getMainThreadExecutor(@NotNull Plugin plugin); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0272-living-entity-allow-attribute-registration.patch b/Unmapped-Spigot-API-Patches/0272-living-entity-allow-attribute-registration.patch deleted file mode 100644 index e7ded6dabb..0000000000 --- a/Unmapped-Spigot-API-Patches/0272-living-entity-allow-attribute-registration.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Sat, 24 Oct 2020 16:37:21 +0200 -Subject: [PATCH] living entity allow attribute registration - - -diff --git a/src/main/java/org/bukkit/attribute/Attributable.java b/src/main/java/org/bukkit/attribute/Attributable.java -index 0ed96b5af0e6e93590882e0ad8239221bcc3f688..474ed1df364a5ca18661d0fbc29901760e39cb07 100644 ---- a/src/main/java/org/bukkit/attribute/Attributable.java -+++ b/src/main/java/org/bukkit/attribute/Attributable.java -@@ -17,4 +17,14 @@ public interface Attributable { - */ - @Nullable - AttributeInstance getAttribute(@NotNull Attribute attribute); -+ -+ // Paper start -+ /** -+ * Registers a generic attribute to that attributable instance. -+ * Allows it to add attributes not registered by default to that entity. -+ * -+ * @param attribute the generic attribute to register -+ */ -+ void registerAttribute(@NotNull Attribute attribute); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0273-Add-missing-effects.patch b/Unmapped-Spigot-API-Patches/0273-Add-missing-effects.patch deleted file mode 100644 index 57086bea9c..0000000000 --- a/Unmapped-Spigot-API-Patches/0273-Add-missing-effects.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ivan Pekov -Date: Tue, 5 Jan 2021 10:19:11 +0200 -Subject: [PATCH] Add missing effects - - -diff --git a/src/main/java/org/bukkit/Effect.java b/src/main/java/org/bukkit/Effect.java -index d0c812c72967469122f7f276ced31cfb0e9482dc..0f598fa0560d14b44dcc65205364870c0bbfa0d8 100644 ---- a/src/main/java/org/bukkit/Effect.java -+++ b/src/main/java/org/bukkit/Effect.java -@@ -201,6 +201,65 @@ public enum Effect { - * The sound of an enderdragon growling - */ - ENDERDRAGON_GROWL(3001, Type.SOUND), -+ // Paper start - add missing effects -+ /** -+ * The sound of a wither spawning -+ */ -+ WITHER_SPAWNED(1023, Type.SOUND), -+ /** -+ * The sound of an ender dragon dying -+ */ -+ ENDER_DRAGON_DEATH(1028, Type.SOUND), -+ /** -+ * The sound of an ender portal being created in the overworld -+ */ -+ END_PORTAL_CREATED_IN_OVERWORLD(1038, Type.SOUND), -+ /** -+ * The sound of phantom's bites -+ */ -+ PHANTOM_BITES(1039, Type.SOUND), -+ /** -+ * The sound of zombie converting to drowned zombie -+ */ -+ ZOMBIE_CONVERTS_TO_DROWNED(1040, Type.SOUND), -+ /** -+ * The sound of a husk converting to zombie by drowning -+ */ -+ HUSK_CONVERTS_TO_ZOMBIE(1041, Type.SOUND), -+ /** -+ * The sound of a grindstone being used -+ */ -+ GRINDSTONE_USED(1042, Type.SOUND), -+ /** -+ * The sound of a book page being turned -+ */ -+ BOOK_PAGE_TURNED(1043, Type.SOUND), -+ /** -+ * Particles displayed when a composter composts -+ */ -+ COMPOSTER_COMPOSTS(1500, Type.VISUAL), -+ /** -+ * Particles displayed when lava converts a block (either water to stone, or -+ * removing existing blocks such as torches) -+ */ -+ LAVA_CONVERTS_BLOCK(1501, Type.VISUAL), -+ /** -+ * Particles displayd when a redstone torch burns out -+ */ -+ REDSTONE_TORCH_BURNS_OUT(1502, Type.VISUAL), -+ /** -+ * Particles displayed when an ender eye is placed -+ */ -+ ENDER_EYE_PLACED(1503, Type.VISUAL), -+ /** -+ * Particles displayed when an ender dragon destroys block -+ */ -+ ENDER_DRAGON_DESTROYS_BLOCK(2008, Type.VISUAL), -+ /** -+ * Particles displayed when a wet sponge vaporizes in nether. -+ */ -+ WET_SPONGE_VAPORIZES_IN_NETHER(2009, Type.VISUAL) -+ // Paper end - ; - - private final int id; diff --git a/Unmapped-Spigot-API-Patches/0274-Expose-Tracked-Players.patch b/Unmapped-Spigot-API-Patches/0274-Expose-Tracked-Players.patch deleted file mode 100644 index 1c4214897c..0000000000 --- a/Unmapped-Spigot-API-Patches/0274-Expose-Tracked-Players.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tom -Date: Fri, 26 Feb 2021 16:24:25 -0600 -Subject: [PATCH] Expose Tracked Players - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 68a03821a5f06308a9c51fdf107d3924c44886c8..34b51466ffb281b05f531b3f7deda245ae7fd96a 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1,6 +1,7 @@ - package org.bukkit.entity; - - import java.net.InetSocketAddress; -+import java.util.Set; // Paper - import java.util.UUID; - import com.destroystokyo.paper.ClientOption; // Paper - import com.destroystokyo.paper.Title; // Paper -@@ -1942,6 +1943,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - void sendOpLevel(byte level); - // Paper end - -+ // Paper start -+ /** -+ * @return Returns a set of Players within this player's tracking range (that the player's client can "see") -+ */ -+ @NotNull -+ Set getTrackedPlayers(); -+ // Paper end -+ - // Spigot start - public class Spigot extends Entity.Spigot { - diff --git a/Unmapped-Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch b/Unmapped-Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch deleted file mode 100644 index 7eca03bdf5..0000000000 --- a/Unmapped-Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Tue, 2 Mar 2021 15:24:58 -0800 -Subject: [PATCH] Cache the result of Material#isBlock - - -diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 69c85c3a1f45476f7de0a9399852d82eeb4f9c86..0f081835c0484e15fca4fadaa27e90cadd394276 100644 ---- a/src/main/java/org/bukkit/Material.java -+++ b/src/main/java/org/bukkit/Material.java -@@ -3935,6 +3935,7 @@ public enum Material implements Keyed { - public final Class data; - private final boolean legacy; - private final NamespacedKey key; -+ private boolean isBlock; // Paper - - private Material(final int id) { - this(id, 64); -@@ -4132,6 +4133,11 @@ public enum Material implements Keyed { - * @return true if this material is a block - */ - public boolean isBlock() { -+ // Paper start - cache isBlock -+ return this.isBlock; -+ } -+ private boolean isBlock0() { -+ // Paper end - switch (this) { - // - case ACACIA_BUTTON: -@@ -5213,6 +5219,7 @@ public enum Material implements Keyed { - static { - for (Material material : values()) { - BY_NAME.put(material.name(), material); -+ material.isBlock = material.isBlock0(); // Paper - } - } - diff --git a/Unmapped-Spigot-API-Patches/0276-Add-worldborder-events.patch b/Unmapped-Spigot-API-Patches/0276-Add-worldborder-events.patch deleted file mode 100644 index 09c3770e16..0000000000 --- a/Unmapped-Spigot-API-Patches/0276-Add-worldborder-events.patch +++ /dev/null @@ -1,308 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 22:40:26 -0800 -Subject: [PATCH] Add worldborder events - - -diff --git a/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeEvent.java b/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..126fe50b519a8d7cd158f799058cb235f9c4cbdb ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeEvent.java -@@ -0,0 +1,114 @@ -+package io.papermc.paper.event.world.border; -+ -+import org.bukkit.World; -+import org.bukkit.WorldBorder; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a world border changes its bounds, either over time, or instantly. -+ */ -+public class WorldBorderBoundsChangeEvent extends WorldBorderEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private Type type; -+ private final double oldSize; -+ private double newSize; -+ private long duration; -+ private boolean cancelled; -+ -+ public WorldBorderBoundsChangeEvent(@NotNull World world, @NotNull WorldBorder worldBorder, @NotNull Type type, double oldSize, double newSize, long duration) { -+ super(world, worldBorder); -+ this.type = type; -+ this.oldSize = oldSize; -+ this.newSize = newSize; -+ this.duration = duration; -+ } -+ -+ /** -+ * Gets if this change is an instant change or over-time change. -+ * -+ * @return the change type -+ */ -+ @NotNull -+ public Type getType() { -+ return type; -+ } -+ -+ /** -+ * Gets the old size or the world border. -+ * -+ * @return the old size -+ */ -+ public double getOldSize() { -+ return oldSize; -+ } -+ -+ /** -+ * Gets the new size of the world border. -+ * -+ * @return the new size -+ */ -+ public double getNewSize() { -+ return newSize; -+ } -+ -+ /** -+ * Sets the new size of the world border. -+ * -+ * @param newSize the new size -+ */ -+ public void setNewSize(double newSize) { -+ // PAIL: TODO: Magic Values -+ this.newSize = Math.min(6.0E7D, Math.max(1.0D, newSize)); -+ } -+ -+ /** -+ * Gets the time in milliseconds for the change. Will be 0 if instant. -+ * -+ * @return the time in milliseconds for the change -+ */ -+ public long getDuration() { -+ return duration; -+ } -+ -+ /** -+ * Sets the time in milliseconds for the change. Will change {@link #getType()} to return -+ * {@link Type#STARTED_MOVE}. -+ * -+ * @param duration the time in milliseconds for the change -+ */ -+ public void setDuration(long duration) { -+ // PAIL: TODO: Magic Values -+ this.duration = Math.min(9223372036854775L, Math.max(0L, duration)); -+ if (duration >= 0 && type == Type.INSTANT_MOVE) type = Type.STARTED_MOVE; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+ -+ public enum Type { -+ STARTED_MOVE, -+ INSTANT_MOVE -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeFinishEvent.java b/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeFinishEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c3d578ae2c5615b0ebace99d9bacf100b086c971 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeFinishEvent.java -@@ -0,0 +1,65 @@ -+package io.papermc.paper.event.world.border; -+ -+import org.bukkit.World; -+import org.bukkit.WorldBorder; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a moving world border has finished it's move. -+ */ -+public class WorldBorderBoundsChangeFinishEvent extends WorldBorderEvent { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private final double oldSize; -+ private final double newSize; -+ private final double duration; -+ -+ public WorldBorderBoundsChangeFinishEvent(@NotNull World world, @NotNull WorldBorder worldBorder, double oldSize, double newSize, double duration) { -+ super(world, worldBorder); -+ this.oldSize = oldSize; -+ this.newSize = newSize; -+ this.duration = duration; -+ } -+ -+ /** -+ * Gets the old size of the worldborder. -+ * -+ * @return the old size -+ */ -+ public double getOldSize() { -+ return oldSize; -+ } -+ -+ /** -+ * Gets the new size of the worldborder. -+ * -+ * @return the new size -+ */ -+ public double getNewSize() { -+ return newSize; -+ } -+ -+ /** -+ * Gets the duration this worldborder took to make the change. -+ *

    -+ * Can be 0 if handlers for {@link io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent} set the duration to 0. -+ * -+ * @return the duration of the transition -+ */ -+ public double getDuration() { -+ return duration; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/world/border/WorldBorderCenterChangeEvent.java b/src/main/java/io/papermc/paper/event/world/border/WorldBorderCenterChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4a10c773a8d05a596066e63306dead74c1363fd7 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/world/border/WorldBorderCenterChangeEvent.java -@@ -0,0 +1,77 @@ -+package io.papermc.paper.event.world.border; -+ -+import org.bukkit.Location; -+import org.bukkit.World; -+import org.bukkit.WorldBorder; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.world.WorldEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a world border's center is changed. -+ */ -+public class WorldBorderCenterChangeEvent extends WorldBorderEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private final Location oldCenter; -+ private Location newCenter; -+ private boolean cancelled; -+ -+ public WorldBorderCenterChangeEvent(@NotNull World world, @NotNull WorldBorder worldBorder, @NotNull Location oldCenter, @NotNull Location newCenter) { -+ super(world, worldBorder); -+ this.oldCenter = oldCenter; -+ this.newCenter = newCenter; -+ } -+ -+ /** -+ * Gets the original center location of the world border. -+ * -+ * @return the old center -+ */ -+ @NotNull -+ public Location getOldCenter() { -+ return oldCenter; -+ } -+ -+ /** -+ * Gets the new center location for the world border. -+ * -+ * @return the new center -+ */ -+ @NotNull -+ public Location getNewCenter() { -+ return newCenter; -+ } -+ -+ /** -+ * Sets the new center location for the world border. Y coordinate is ignored. -+ * -+ * @param newCenter the new center -+ */ -+ public void setNewCenter(@NotNull Location newCenter) { -+ this.newCenter = newCenter; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/world/border/WorldBorderEvent.java b/src/main/java/io/papermc/paper/event/world/border/WorldBorderEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..67bd469d3680c9554ce6c1d5493826a252682835 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/world/border/WorldBorderEvent.java -@@ -0,0 +1,22 @@ -+package io.papermc.paper.event.world.border; -+ -+import org.bukkit.World; -+import org.bukkit.WorldBorder; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.world.WorldEvent; -+import org.jetbrains.annotations.NotNull; -+ -+public abstract class WorldBorderEvent extends WorldEvent { -+ -+ private final WorldBorder worldBorder; -+ -+ public WorldBorderEvent(@NotNull World world, @NotNull WorldBorder worldBorder) { -+ super(world); -+ this.worldBorder = worldBorder; -+ } -+ -+ @NotNull -+ public WorldBorder getWorldBorder() { -+ return worldBorder; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch b/Unmapped-Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch deleted file mode 100644 index a38082f8e8..0000000000 --- a/Unmapped-Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 5 Jul 2020 00:34:24 -0700 -Subject: [PATCH] added PlayerNameEntityEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerNameEntityEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerNameEntityEvent.java -new file mode 100755 -index 0000000000000000000000000000000000000000..ef9e53a73eff469bbaa8fb20c634297acb9d1986 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerNameEntityEvent.java -@@ -0,0 +1,118 @@ -+package io.papermc.paper.event.player; -+ -+import net.kyori.adventure.text.Component; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when the player is attempting to rename a mob -+ */ -+public class PlayerNameEntityEvent extends PlayerEvent implements Cancellable { -+ -+ private LivingEntity entity; -+ private Component name; -+ private boolean persistent; -+ private boolean cancelled; -+ -+ public PlayerNameEntityEvent(@NotNull Player player, @NotNull LivingEntity entity, @NotNull Component name, boolean persistent) { -+ super(player); -+ this.entity = entity; -+ this.name = name; -+ this.persistent = persistent; -+ } -+ -+ /** -+ * Gets the name to be given to the entity. -+ * @return the name -+ */ -+ @Nullable -+ public Component getName() { -+ return name; -+ } -+ -+ /** -+ * Sets the name to be given to the entity. -+ * -+ * @param name the name -+ */ -+ public void setName(@Nullable Component name) { -+ this.name = name; -+ } -+ -+ /** -+ * Gets the entity involved in this event. -+ * -+ * @return the entity -+ */ -+ @NotNull -+ public LivingEntity getEntity() { -+ return entity; -+ } -+ -+ /** -+ * Sets the entity involved in this event. -+ * -+ * @param entity the entity -+ */ -+ public void setEntity(@NotNull LivingEntity entity) { -+ this.entity = entity; -+ } -+ -+ /** -+ * Gets whether this will set the mob to be persistent. -+ * -+ * @return persistent -+ */ -+ public boolean isPersistent() { -+ return persistent; -+ } -+ -+ /** -+ * Sets whether this will set the mob to be persistent. -+ * -+ * @param persistent persistent -+ */ -+ public void setPersistent(boolean persistent) { -+ this.persistent = persistent; -+ } -+ -+ /** -+ * Gets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ * -+ * @return true if this event is cancelled -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Sets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins. -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch b/Unmapped-Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch deleted file mode 100644 index b0b34773c0..0000000000 --- a/Unmapped-Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> -Date: Wed, 6 Jan 2021 12:05:29 -0800 -Subject: [PATCH] Add recipe to cook events - - -diff --git a/src/main/java/org/bukkit/event/block/BlockCookEvent.java b/src/main/java/org/bukkit/event/block/BlockCookEvent.java -index be7af5440bf9923f0c9c84efa4d70a89337a2f96..a3f1c9cb36c9069ed622985a525bfc2a7a27ab91 100644 ---- a/src/main/java/org/bukkit/event/block/BlockCookEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockCookEvent.java -@@ -14,12 +14,21 @@ public class BlockCookEvent extends BlockEvent implements Cancellable { - private final ItemStack source; - private ItemStack result; - private boolean cancelled; -+ private final org.bukkit.inventory.CookingRecipe recipe; // Paper - -+ @Deprecated // Paper - public BlockCookEvent(@NotNull final Block block, @NotNull final ItemStack source, @NotNull final ItemStack result) { -+ // Paper start -+ this(block, source, result, null); -+ } -+ -+ public BlockCookEvent(@NotNull final Block block, @NotNull final ItemStack source, @NotNull final ItemStack result, @org.jetbrains.annotations.Nullable org.bukkit.inventory.CookingRecipe recipe) { -+ // Paper end - super(block); - this.source = source; - this.result = result; - this.cancelled = false; -+ this.recipe = recipe; // Paper - } - - /** -@@ -61,6 +70,18 @@ public class BlockCookEvent extends BlockEvent implements Cancellable { - this.cancelled = cancel; - } - -+ // Paper start -+ /** -+ * Gets the cooking recipe associated with this event. -+ * -+ * @return the recipe -+ */ -+ @org.jetbrains.annotations.Nullable -+ public org.bukkit.inventory.CookingRecipe getRecipe() { -+ return recipe; -+ } -+ // Paper end -+ - @NotNull - @Override - public HandlerList getHandlers() { -diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java -index 066e7dd9a34d35c8b643a5efcf95d6a5ef47c7ee..16b3ab8f525c4e863f804cc8460a330407d85478 100644 ---- a/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java -@@ -10,7 +10,13 @@ import org.jetbrains.annotations.NotNull; - */ - public class FurnaceSmeltEvent extends BlockCookEvent { - -+ @Deprecated // Paper - public FurnaceSmeltEvent(@NotNull final Block furnace, @NotNull final ItemStack source, @NotNull final ItemStack result) { - super(furnace, source, result); - } -+ // Paper start -+ public FurnaceSmeltEvent(@NotNull final Block furnace, @NotNull final ItemStack source, @NotNull final ItemStack result, @org.jetbrains.annotations.Nullable org.bukkit.inventory.CookingRecipe recipe) { -+ super(furnace, source, result, recipe); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0279-Add-Block-isValidTool.patch b/Unmapped-Spigot-API-Patches/0279-Add-Block-isValidTool.patch deleted file mode 100644 index f037cf8c32..0000000000 --- a/Unmapped-Spigot-API-Patches/0279-Add-Block-isValidTool.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 6 Jul 2020 12:44:23 -0700 -Subject: [PATCH] Add Block#isValidTool - - -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 181658c679d306ffc4ad45259494571ee224ef47..08e6f1741685f54506c8a4ff29bbd30f62cf8e45 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -218,6 +218,15 @@ public interface Block extends Metadatable { - public static int getBlockKeyZ(long packed) { - return (int) ((packed << 10) >> 37); - } -+ -+ /** -+ * Checks if the itemstack is a valid tool to -+ * break the block with -+ * -+ * @param itemStack The (tool) itemstack -+ * @return whether the block will drop items -+ */ -+ boolean isValidTool(@NotNull ItemStack itemStack); - // Paper End - - /** diff --git a/Unmapped-Spigot-API-Patches/0280-Implement-Keyed-on-World.patch b/Unmapped-Spigot-API-Patches/0280-Implement-Keyed-on-World.patch deleted file mode 100644 index 75f66d5848..0000000000 --- a/Unmapped-Spigot-API-Patches/0280-Implement-Keyed-on-World.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 6 Jan 2021 00:34:10 -0800 -Subject: [PATCH] Implement Keyed on World - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 68101a322ffab8ec28843386b79b8079576fa720..5f7208196684d9c8373df28b7cfb5f9e21baa41e 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -639,6 +639,18 @@ public final class Bukkit { - public static World getWorld(@NotNull UUID uid) { - return server.getWorld(uid); - } -+ // Paper start -+ /** -+ * Gets the world from the given NamespacedKey -+ * -+ * @param worldKey the NamespacedKey of the world to retrieve -+ * @return a world with the given NamespacedKey, or null if none exists -+ */ -+ @Nullable -+ public static World getWorld(@NotNull NamespacedKey worldKey) { -+ return server.getWorld(worldKey); -+ } -+ // Paper end - - /** - * Gets the map from the given item ID. -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index a79fa08b9e6fb924b2da933eb6e4b365d14d938d..f3e27d2d02a9407bb1b091b8c1125ad5abf99e55 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -541,6 +541,17 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @Nullable - public World getWorld(@NotNull UUID uid); - -+ // Paper start -+ /** -+ * Gets the world from the given NamespacedKey -+ * -+ * @param worldKey the NamespacedKey of the world to retrieve -+ * @return a world with the given NamespacedKey, or null if none exists -+ */ -+ @Nullable -+ public World getWorld(@NotNull NamespacedKey worldKey); -+ // Paper end -+ - /** - * Gets the map from the given item ID. - * -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index ced33fc6de6bfa2767123131d532e7ae9ef3a5be..98512bddbb0c8bd6a3f487c60b1ec77b274b991e 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -43,7 +43,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a world, which may contain entities, chunks and blocks - */ --public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience { // Paper -+public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience, Keyed { // Paper - - // Paper start - /** -@@ -829,6 +829,15 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - - @NotNull - java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent); -+ -+ /** -+ * Get the world's key -+ * -+ * @return the world's key -+ */ -+ @NotNull -+ @Override -+ NamespacedKey getKey(); - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/WorldCreator.java b/src/main/java/org/bukkit/WorldCreator.java -index 6e6945dd4c770be04ec09da3958fae751717527a..e6a83252f42da31ad38f8dc1beccc7aa2c3f54b8 100644 ---- a/src/main/java/org/bukkit/WorldCreator.java -+++ b/src/main/java/org/bukkit/WorldCreator.java -@@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; - * Represents various types of options that may be used to create a world. - */ - public class WorldCreator { -+ private final NamespacedKey key; // Paper - private final String name; - private long seed; - private World.Environment environment = World.Environment.NORMAL; -@@ -26,13 +27,67 @@ public class WorldCreator { - * @param name Name of the world that will be created - */ - public WorldCreator(@NotNull String name) { -- if (name == null) { -- throw new IllegalArgumentException("World name cannot be null"); -- } -+ // Paper start -+ this(name, NamespacedKey.minecraft(name.toLowerCase(java.util.Locale.ENGLISH).replace(" ", "_"))); -+ } - -- this.name = name; -+ /** -+ * Creates an empty WorldCreator for the given world name and key -+ * -+ * @param levelName LevelName of the world that will be created -+ * @param worldKey NamespacedKey of the world that will be created -+ */ -+ public WorldCreator(@NotNull String levelName, @NotNull NamespacedKey worldKey) { -+ if (levelName == null || worldKey == null) { -+ throw new IllegalArgumentException("World name and key cannot be null"); -+ } -+ this.name = levelName; - this.seed = (new Random()).nextLong(); -+ this.key = worldKey; -+ } -+ -+ /** -+ * Creates an empty WorldCreator for the given key. -+ * LevelName will be the Key part of the NamespacedKey. -+ * -+ * @param worldKey NamespacedKey of the world that will be created -+ */ -+ public WorldCreator(@NotNull NamespacedKey worldKey) { -+ this(worldKey.getKey(), worldKey); -+ } -+ -+ /** -+ * Gets the key for this WorldCreator -+ * -+ * @return the key -+ */ -+ @NotNull -+ public NamespacedKey key() { -+ return key; -+ } -+ -+ /** -+ * Creates an empty WorldCreator for the given world name and key -+ * -+ * @param levelName LevelName of the world that will be created -+ * @param worldKey NamespacedKey of the world that will be created -+ */ -+ @NotNull -+ public static WorldCreator ofNameAndKey(@NotNull String levelName, @NotNull NamespacedKey worldKey) { -+ return new WorldCreator(levelName, worldKey); -+ } -+ -+ /** -+ * Creates an empty WorldCreator for the given key. -+ * LevelName will be the Key part of the NamespacedKey. -+ * -+ * @param worldKey NamespacedKey of the world that will be created -+ */ -+ @NotNull -+ public static WorldCreator ofKey(@NotNull NamespacedKey worldKey) { -+ return new WorldCreator(worldKey); - } -+ // Paper end - - /** - * Copies the options from the specified world diff --git a/Unmapped-Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch b/Unmapped-Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch deleted file mode 100644 index 4d216020ec..0000000000 --- a/Unmapped-Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CDFN -Date: Fri, 12 Mar 2021 18:31:31 +0100 -Subject: [PATCH] fix Inventory#getContents null annotations - - -diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java -index 6386206188e820206bb1a9f516b5e194fdc9d952..7956aebcb390379677dccf7c9561866cf94c024c 100644 ---- a/src/main/java/org/bukkit/inventory/Inventory.java -+++ b/src/main/java/org/bukkit/inventory/Inventory.java -@@ -158,9 +158,8 @@ public interface Inventory extends Iterable { - * - * @return An array of ItemStacks from the inventory. Individual items may be null. - */ -- @NotNull -- public ItemStack[] getContents(); -- -+ public @org.checkerframework.checker.nullness.qual.Nullable ItemStack @org.checkerframework.checker.nullness.qual.NonNull [] getContents(); // Paper - make array elements nullable instead array -+ - /** - * Completely replaces the inventory's contents. Removes all existing - * contents and replaces it with the ItemStacks given in the array. diff --git a/Unmapped-Spigot-API-Patches/0282-Item-Rarity-API.patch b/Unmapped-Spigot-API-Patches/0282-Item-Rarity-API.patch deleted file mode 100644 index 8f0f4fc977..0000000000 --- a/Unmapped-Spigot-API-Patches/0282-Item-Rarity-API.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 12 Mar 2021 17:09:40 -0800 -Subject: [PATCH] Item Rarity API - - -diff --git a/src/main/java/io/papermc/paper/inventory/ItemRarity.java b/src/main/java/io/papermc/paper/inventory/ItemRarity.java -new file mode 100644 -index 0000000000000000000000000000000000000000..74ef8395cc040ce488c2acaa416db20272cc2734 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/inventory/ItemRarity.java -@@ -0,0 +1,28 @@ -+package io.papermc.paper.inventory; -+ -+import net.kyori.adventure.text.format.NamedTextColor; -+import net.kyori.adventure.text.format.TextColor; -+import org.jetbrains.annotations.NotNull; -+ -+public enum ItemRarity { -+ -+ COMMON(NamedTextColor.WHITE), -+ UNCOMMON(NamedTextColor.YELLOW), -+ RARE(NamedTextColor.AQUA), -+ EPIC(NamedTextColor.LIGHT_PURPLE); -+ -+ TextColor color; -+ -+ ItemRarity(TextColor color) { -+ this.color = color; -+ } -+ -+ /** -+ * Gets the color formatting associated with the rarity. -+ * @return -+ */ -+ @NotNull -+ public TextColor getColor() { -+ return color; -+ } -+} -diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 0f081835c0484e15fca4fadaa27e90cadd394276..07b8b913434bb575df8670230d693b2d4cec2571 100644 ---- a/src/main/java/org/bukkit/Material.java -+++ b/src/main/java/org/bukkit/Material.java -@@ -4002,6 +4002,17 @@ public enum Material implements Keyed { - public String getTranslationKey() { - return Bukkit.getUnsafe().getTranslationKey(this); - } -+ -+ /** -+ * Returns the item rarity for the item. The Material MUST be an Item not a block. -+ * Use {@link #isItem()} before this. -+ * -+ * @return the item rarity -+ */ -+ @NotNull -+ public io.papermc.paper.inventory.ItemRarity getItemRarity() { -+ return Bukkit.getUnsafe().getItemRarity(this); -+ } - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 84eda68281c6c6968d95b1313a33696c3a9980d4..bcd10b2c9255d778b678310febf1937301d01a50 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -137,5 +137,22 @@ public interface UnsafeValues { - * Use this when sending custom packets, so that there are no collisions on the client or server. - */ - public int nextEntityId(); -+ -+ /** -+ * Gets the item rarity of a material. The material MUST be an item. -+ * Use {@link Material#isItem()} before this. -+ * -+ * @param material the material to get the rarity of -+ * @return the item rarity -+ */ -+ public io.papermc.paper.inventory.ItemRarity getItemRarity(Material material); -+ -+ /** -+ * Gets the item rarity of the itemstack. The rarity can change based on enchantements. -+ * -+ * @param itemStack the itemstack to get the rarity of -+ * @return the itemstack rarity -+ */ -+ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(ItemStack itemStack); - // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index bd96c06aca1fc18807e65c34f399ce2ebe891816..f72d3d62d61755bbaf1950ebcb228ce95d1faf58 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -863,5 +863,15 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public String getTranslationKey() { - return Bukkit.getUnsafe().getTranslationKey(this); - } -+ -+ /** -+ * Gets the item rarity of the itemstack. The rarity can change based on enchantements. -+ * -+ * @return the itemstack rarity -+ */ -+ @NotNull -+ public io.papermc.paper.inventory.ItemRarity getRarity() { -+ return Bukkit.getUnsafe().getItemStackRarity(this); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0283-Expose-protocol-version.patch b/Unmapped-Spigot-API-Patches/0283-Expose-protocol-version.patch deleted file mode 100644 index f5e20e22d7..0000000000 --- a/Unmapped-Spigot-API-Patches/0283-Expose-protocol-version.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Fri, 26 Mar 2021 11:23:27 +0100 -Subject: [PATCH] Expose protocol version - - -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index bcd10b2c9255d778b678310febf1937301d01a50..6dbd520182b1e7713a68baad09b7f613424ef619 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -154,5 +154,12 @@ public interface UnsafeValues { - * @return the itemstack rarity - */ - public io.papermc.paper.inventory.ItemRarity getItemStackRarity(ItemStack itemStack); -+ -+ /** -+ * Returns the server's protocol version. -+ * -+ * @return the server's protocol version -+ */ -+ int getProtocolVersion(); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch b/Unmapped-Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch deleted file mode 100644 index b0f198f0e1..0000000000 --- a/Unmapped-Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 8 Apr 2021 17:36:15 -0700 -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 f0e0710fef5a3e0b722ece7ccf89c3d0f88f8f0f..2ce774c81a93260a1464183d435b4c418ed61648 100644 ---- a/src/main/java/org/bukkit/entity/HumanEntity.java -+++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -319,6 +319,15 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder - */ - public void setCooldown(@NotNull Material material, int ticks); - -+ // Paper start -+ /** -+ * If the player has slept enough to count towards passing the night. -+ * -+ * @return true if the player has slept enough -+ */ -+ public boolean isDeeplySleeping(); -+ // Paper end -+ - /** - * Get the sleep ticks of the player. This value may be capped. - * diff --git a/Unmapped-Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch b/Unmapped-Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch deleted file mode 100644 index 6c8b681cd9..0000000000 --- a/Unmapped-Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 16:45:15 -0700 -Subject: [PATCH] add consumeFuel to FurnaceBurnEvent - - -diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java -index bc71bc2d3ace0d19d730c09f05f9e0655bcee8f5..caef53d0f6546516fa7aabb2cb3abed70808b3ba 100644 ---- a/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java -@@ -16,6 +16,7 @@ public class FurnaceBurnEvent extends BlockEvent implements Cancellable { - private int burnTime; - private boolean cancelled; - private boolean burning; -+ private boolean consumeFuel = true; // Paper - - public FurnaceBurnEvent(@NotNull final Block furnace, @NotNull final ItemStack fuel, final int burnTime) { - super(furnace); -@@ -70,6 +71,25 @@ public class FurnaceBurnEvent extends BlockEvent implements Cancellable { - public void setBurning(boolean burning) { - this.burning = burning; - } -+ // Paper start -+ /** -+ * Gets whether the furnace's fuel will be consumed or not. -+ * -+ * @return whether the furnace's fuel will be consumed -+ */ -+ public boolean willConsumeFuel() { -+ return consumeFuel; -+ } -+ -+ /** -+ * Sets whether the furnace's fuel will be consumed or not. -+ * -+ * @param consumeFuel true to consume the fuel -+ */ -+ public void setConsumeFuel(boolean consumeFuel) { -+ this.consumeFuel = consumeFuel; -+ } -+ // Paper end - - @Override - public boolean isCancelled() { diff --git a/Unmapped-Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch b/Unmapped-Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch deleted file mode 100644 index 447a45db06..0000000000 --- a/Unmapped-Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 00:28:20 -0700 -Subject: [PATCH] add get-set drop chance to EntityEquipment - - -diff --git a/src/main/java/org/bukkit/inventory/EntityEquipment.java b/src/main/java/org/bukkit/inventory/EntityEquipment.java -index f905bf7a28a42d8bd2aecd42030d2b2092696fc3..58cfd450973f56bfbdd20f9dca8c1e7455260a55 100644 ---- a/src/main/java/org/bukkit/inventory/EntityEquipment.java -+++ b/src/main/java/org/bukkit/inventory/EntityEquipment.java -@@ -405,4 +405,32 @@ public interface EntityEquipment { - */ - @Nullable - Entity getHolder(); -+ // Paper start -+ /** -+ * Gets the drop chance of specified slot. -+ * -+ *

      -+ *
    • A drop chance of 0.0F will never drop -+ *
    • A drop chance of 1.0F will always drop -+ *
    -+ * -+ * @param slot the slot to get the drop chance of -+ * @return the drop chance for the slot -+ */ -+ float getDropChance(@NotNull EquipmentSlot slot); -+ -+ /** -+ * Sets the drop chance of the specified slot. -+ * -+ *
      -+ *
    • A drop chance of 0.0F will never drop -+ *
    • A drop chance of 1.0F will always drop -+ *
    -+ * -+ * @param slot the slot to set the drop chance of -+ * @param chance the drop chance for the slot -+ * @throws UnsupportedOperationException when called on players -+ */ -+ void setDropChance(@NotNull EquipmentSlot slot, float chance); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch b/Unmapped-Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch deleted file mode 100644 index d8dccca755..0000000000 --- a/Unmapped-Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 21 Apr 2021 15:58:25 -0700 -Subject: [PATCH] Added PlayerDeepSleepEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerDeepSleepEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerDeepSleepEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e3ee540bb0a5bc578b148fbcf8b5e39ab9c8575c ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerDeepSleepEvent.java -@@ -0,0 +1,46 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player has slept long enough -+ * to count as passing the night/storm. -+ *

    -+ * Cancelling this event will prevent the player from being counted as deeply sleeping -+ * unless they exit and re-enter the bed. -+ */ -+public class PlayerDeepSleepEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private boolean cancelled; -+ -+ public PlayerDeepSleepEvent(@NotNull Player player) { -+ super(player); -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0288-More-World-API.patch b/Unmapped-Spigot-API-Patches/0288-More-World-API.patch deleted file mode 100644 index 1a3c73561c..0000000000 --- a/Unmapped-Spigot-API-Patches/0288-More-World-API.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 7 Jul 2020 10:53:22 -0700 -Subject: [PATCH] More World API - - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 98512bddbb0c8bd6a3f487c60b1ec77b274b991e..a1496fe00a2d5ba6c1af054d4327f868b2cd7344 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -3482,6 +3482,120 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @Nullable - public Location locateNearestStructure(@NotNull Location origin, @NotNull StructureType structureType, int radius, boolean findUnexplored); - -+ // Paper start -+ /** -+ * Locates the nearest biome based on an origin, biome type, and radius to search. -+ * Step defaults to {@code 8}. -+ * -+ * @param origin Origin location -+ * @param biome Biome to find -+ * @param radius radius to search -+ * @return Location of biome or null if not found in specified radius -+ */ -+ @Nullable -+ Location locateNearestBiome(@NotNull Location origin, @NotNull Biome biome, int radius); -+ -+ /** -+ * Locates the nearest biome based on an origin, biome type, and radius to search -+ * and step -+ * -+ * @param origin Origin location -+ * @param biome Biome to find -+ * @param radius radius to search -+ * @param step Search step 1 would mean checking every block, 8 would be every 8th block -+ * @return Location of biome or null if not found in specified radius -+ */ -+ @Nullable -+ Location locateNearestBiome(@NotNull Location origin, @NotNull Biome biome, int radius, int step); -+ -+ /** -+ * Checks if the world: -+ *

      -+ *
    • evaporates water
    • -+ *
    • dries sponges
    • -+ *
    • has lava spread faster and further
    • -+ *
    -+ * -+ * @return true if ultrawarm, false if not -+ */ -+ boolean isUltrawarm(); -+ -+ /** -+ * Checks if the world is natural. -+ *

    -+ * If {@code false}, compasses will spin randomly in the world. -+ * If {@code true}, nether portals will spawn zombified piglins. -+ *

    -+ * -+ * @return true or false -+ */ -+ boolean isNatural(); -+ -+ /** -+ * Gets the coordinate scaling of this world. -+ * -+ * @return the coordinate scale -+ */ -+ double getCoordinateScale(); -+ -+ /** -+ * Checks if the world has skylight access -+ * -+ * @return whether there is skylight -+ */ -+ boolean hasSkylight(); -+ -+ /** -+ * Checks if the world has a bedrock ceiling -+ * -+ * @return whether the world has a bedrock ceiling -+ */ -+ boolean hasBedrockCeiling(); -+ -+ /** -+ * Checks if piglins will turn into Zombified Piglins in this world -+ * -+ * @return whether Piglins will not transform -+ */ -+ boolean isPiglinSafe(); -+ -+ /** -+ * Checks if beds work -+ * -+ * @return whether beds work -+ */ -+ boolean doesBedWork(); -+ -+ /** -+ * Checks if respawn anchors work -+ * -+ * @return whether respawn anchors work -+ */ -+ boolean doesRespawnAnchorWork(); -+ -+ /** -+ * Checks if this world supports raids -+ * -+ * @return whether this world supports raids -+ */ -+ boolean hasRaids(); -+ -+ /** -+ * Checks if this world has a fixed time -+ * -+ * @return whether this world has fixed time -+ */ -+ boolean isFixedTime(); -+ -+ /** -+ * Gets the collection of materials that burn infinitely in this world. -+ * -+ * @return the materials that will forever stay lit by fire -+ */ -+ @NotNull -+ Collection getInfiniburn(); -+ // Paper end -+ - // Spigot start - /** - * Returns the view distance used for this world. diff --git a/Unmapped-Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch b/Unmapped-Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch deleted file mode 100644 index a622f2b98f..0000000000 --- a/Unmapped-Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 24 Dec 2020 12:27:49 -0800 -Subject: [PATCH] Added PlayerBedFailEnterEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerBedFailEnterEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerBedFailEnterEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e0028733615ddc9e34359f673ca1c3cadb133948 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerBedFailEnterEvent.java -@@ -0,0 +1,119 @@ -+package io.papermc.paper.event.player; -+ -+import net.kyori.adventure.text.Component; -+import org.bukkit.block.Block; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class PlayerBedFailEnterEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private final FailReason failReason; -+ private final Block bed; -+ private boolean willExplode; -+ private Component message; -+ private boolean cancelled; -+ -+ public PlayerBedFailEnterEvent(@NotNull Player player, @NotNull FailReason failReason, @NotNull Block bed, boolean willExplode, @Nullable Component message) { -+ super(player); -+ this.failReason = failReason; -+ this.bed = bed; -+ this.willExplode = willExplode; -+ this.message = message; -+ } -+ -+ @NotNull -+ public FailReason getFailReason() { -+ return failReason; -+ } -+ -+ @NotNull -+ public Block getBed() { -+ return bed; -+ } -+ -+ public boolean getWillExplode() { -+ return willExplode; -+ } -+ -+ public void setWillExplode(boolean willExplode) { -+ this.willExplode = willExplode; -+ } -+ -+ @Nullable -+ public Component getMessage() { -+ return message; -+ } -+ -+ public void setMessage(@Nullable Component message) { -+ this.message = message; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Cancel this event. -+ *

    -+ * NOTE: This does not cancel the player getting in the bed, but any messages/explosions -+ * that may occur because of the interaction. -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+ -+ public static enum FailReason { -+ /** -+ * The world doesn't allow sleeping (ex. Nether or The End). Entering -+ * the bed is prevented and the bed explodes. -+ */ -+ NOT_POSSIBLE_HERE, -+ /** -+ * Entering the bed is prevented due to it not being night nor -+ * thundering currently. -+ *

    -+ * If the event is forcefully allowed during daytime, the player will -+ * enter the bed (and set its bed location), but might get immediately -+ * thrown out again. -+ */ -+ NOT_POSSIBLE_NOW, -+ /** -+ * Entering the bed is prevented due to the player being too far away. -+ */ -+ TOO_FAR_AWAY, -+ /** -+ * Bed is obstructed. -+ */ -+ OBSTRUCTED, -+ /** -+ * Entering the bed is prevented due to there being some other problem. -+ */ -+ OTHER_PROBLEM, -+ /** -+ * Entering the bed is prevented due to there being monsters nearby. -+ */ -+ NOT_SAFE; -+ -+ public static final FailReason[] VALUES = values(); -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch b/Unmapped-Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch deleted file mode 100644 index c2f0577191..0000000000 --- a/Unmapped-Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spyridon Pagkalos -Date: Thu, 25 Mar 2021 20:25:47 +0200 -Subject: [PATCH] Introduce beacon activation/deactivation events - - -diff --git a/src/main/java/io/papermc/paper/event/block/BeaconActivatedEvent.java b/src/main/java/io/papermc/paper/event/block/BeaconActivatedEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7575ca7dd84dee89528ec2e5e5f99f97d8a10f58 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/BeaconActivatedEvent.java -@@ -0,0 +1,40 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Beacon; -+import org.bukkit.block.Block; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a beacon is activated. -+ * Activation occurs when the beacon beam becomes visible. -+ */ -+public class BeaconActivatedEvent extends BlockEvent { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ public BeaconActivatedEvent(@NotNull Block block) { -+ super(block); -+ } -+ -+ /** -+ * Returns the beacon that was activated. -+ * -+ * @return the beacon that was activated. -+ */ -+ @NotNull -+ public Beacon getBeacon() { -+ return (Beacon) block.getState(); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/block/BeaconDeactivatedEvent.java b/src/main/java/io/papermc/paper/event/block/BeaconDeactivatedEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..34f18468b4cfc08717cc3442778c9e85124e5a22 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/BeaconDeactivatedEvent.java -@@ -0,0 +1,43 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.Material; -+import org.bukkit.block.Beacon; -+import org.bukkit.block.Block; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when a beacon is deactivated, either because its base block(s) or itself were destroyed. -+ */ -+public class BeaconDeactivatedEvent extends BlockEvent { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ public BeaconDeactivatedEvent(@NotNull Block block) { -+ super(block); -+ } -+ -+ /** -+ * Returns the beacon that was deactivated. -+ * This will return null if the beacon does not exist. -+ * (which can occur after the deactivation of a now broken beacon) -+ * -+ * @return The beacon that got deactivated, or null if it does not exist. -+ */ -+ @Nullable -+ public Beacon getBeacon() { -+ return block.getType() == Material.BEACON ? (Beacon) block.getState() : null; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0291-PlayerMoveEvent-Improvements.patch b/Unmapped-Spigot-API-Patches/0291-PlayerMoveEvent-Improvements.patch deleted file mode 100644 index 33cf16e54b..0000000000 --- a/Unmapped-Spigot-API-Patches/0291-PlayerMoveEvent-Improvements.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Thu, 29 Apr 2021 10:31:44 +0100 -Subject: [PATCH] PlayerMoveEvent Improvements - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java b/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java -index 1a58734d919fae247eeb85dd785fd59990856505..b484abf3b06b1fb3577b43d50d64498dcd7652c9 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java -@@ -93,6 +93,53 @@ public class PlayerMoveEvent extends PlayerEvent implements Cancellable { - this.to = to; - } - -+ // Paper start - PlayerMoveEvent improvements -+ /** -+ * Check if the player has changed position (even within the same block) in the event -+ * -+ * @return whether the player has changed position or not -+ */ -+ public boolean hasChangedPosition() { -+ return hasExplicitlyChangedPosition() || !from.getWorld().equals(to.getWorld()); -+ } -+ -+ /** -+ * Check if the player has changed position (even within the same block) in the event, disregarding a possible world change -+ * -+ * @return whether the player has changed position or not -+ */ -+ public boolean hasExplicitlyChangedPosition() { -+ return from.getX() != to.getX() || from.getY() != to.getY() || from.getZ() != to.getZ(); -+ } -+ -+ /** -+ * Check if the player has moved to a new block in the event -+ * -+ * @return whether the player has moved to a new block or not -+ */ -+ public boolean hasChangedBlock() { -+ return hasExplicitlyChangedBlock() || !from.getWorld().equals(to.getWorld()); -+ } -+ -+ /** -+ * Check if the player has moved to a new block in the event, disregarding a possible world change -+ * -+ * @return whether the player has moved to a new block or not -+ */ -+ public boolean hasExplicitlyChangedBlock() { -+ return from.getBlockX() != to.getBlockX() || from.getBlockY() != to.getBlockY() || from.getBlockZ() != to.getBlockZ(); -+ } -+ -+ /** -+ * Check if the player has changed orientation in the event -+ * -+ * @return whether the player has changed orientation or not -+ */ -+ public boolean hasChangedOrientation() { -+ return from.getPitch() != to.getPitch() || from.getYaw() != to.getYaw(); -+ } -+ // Paper end -+ - private void validateLocation(@NotNull Location loc) { - Preconditions.checkArgument(loc != null, "Cannot use null location!"); - Preconditions.checkArgument(loc.getWorld() != null, "Cannot use null location with null world!"); diff --git a/Unmapped-Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch b/Unmapped-Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch deleted file mode 100644 index 41342d0d34..0000000000 --- a/Unmapped-Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 17:17:54 -0700 -Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java b/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java -index d2be2ad2e3665728e614a89dd62ef9237f1d3ce6..359e385bd6854a4b146cd0a54badb9c3d31ca12d 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java -@@ -14,17 +14,30 @@ public class PlayerRespawnEvent extends PlayerEvent { - private Location respawnLocation; - private final boolean isBedSpawn; - private final boolean isAnchorSpawn; -+ private final java.util.Set respawnFlags; // Paper - - @Deprecated - public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn) { - this(respawnPlayer, respawnLocation, isBedSpawn, false); - } - -+ @Deprecated // Paper - public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn) { -+ // Paper start -+ this(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, com.google.common.collect.ImmutableSet.builder()); -+ } -+ -+ public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn, @NotNull final com.google.common.collect.ImmutableSet.Builder respawnFlags) { -+ // Paper end - super(respawnPlayer); - this.respawnLocation = respawnLocation; - this.isBedSpawn = isBedSpawn; - this.isAnchorSpawn = isAnchorSpawn; -+ // Paper start -+ if (this.isBedSpawn) { respawnFlags.add(RespawnFlag.BED_SPAWN); } -+ if (this.isAnchorSpawn) { respawnFlags.add(RespawnFlag.ANCHOR_SPAWN); } -+ this.respawnFlags = respawnFlags.build(); -+ // Paper end - } - - /** -@@ -77,4 +90,31 @@ public class PlayerRespawnEvent extends PlayerEvent { - public static HandlerList getHandlerList() { - return handlers; - } -+ -+ // Paper start -+ /** -+ * Get the set of flags that apply to this respawn. -+ * -+ * @return an immutable set of the flags that apply to this respawn -+ */ -+ @NotNull -+ public java.util.Set getRespawnFlags() { -+ return respawnFlags; -+ } -+ -+ public enum RespawnFlag { -+ /** -+ * Will use the bed spawn location -+ */ -+ BED_SPAWN, -+ /** -+ * Will use the respawn anchor location -+ */ -+ ANCHOR_SPAWN, -+ /** -+ * Is caused by going to the end portal in the end. -+ */ -+ END_PORTAL, -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0293-Add-more-WanderingTrader-API.patch b/Unmapped-Spigot-API-Patches/0293-Add-more-WanderingTrader-API.patch deleted file mode 100644 index 99045d4949..0000000000 --- a/Unmapped-Spigot-API-Patches/0293-Add-more-WanderingTrader-API.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Thu, 6 May 2021 14:56:26 +0100 -Subject: [PATCH] Add more WanderingTrader API - - -diff --git a/src/main/java/org/bukkit/entity/WanderingTrader.java b/src/main/java/org/bukkit/entity/WanderingTrader.java -index 55394ed5c68cb0bf4333fc918e3b4c8c4e3db0c6..da76e1ed5406322073dd8c7a89ca55aa68620ac4 100644 ---- a/src/main/java/org/bukkit/entity/WanderingTrader.java -+++ b/src/main/java/org/bukkit/entity/WanderingTrader.java -@@ -28,4 +28,30 @@ public interface WanderingTrader extends AbstractVillager { - * {@link WanderingTrader} is forcibly despawned - */ - public void setDespawnDelay(int despawnDelay); -+ -+ // Paper start - Add more WanderingTrader API -+ /** -+ * Set if the Wandering Trader can and will drink an invisibility potion. -+ * @param bool whether the mob will drink -+ */ -+ public void setCanDrinkPotion(boolean bool); -+ -+ /** -+ * Get if the Wandering Trader can and will drink an invisibility potion. -+ * @return whether the mob will drink -+ */ -+ public boolean canDrinkPotion(); -+ -+ /** -+ * Set if the Wandering Trader can and will drink milk. -+ * @param bool whether the mob will drink -+ */ -+ public void setCanDrinkMilk(boolean bool); -+ -+ /** -+ * Get if the Wandering Trader can and will drink milk. -+ * @return whether the mob will drink -+ */ -+ public boolean canDrinkMilk(); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/Unmapped-Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch deleted file mode 100644 index b2fb9bb339..0000000000 --- a/Unmapped-Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch +++ /dev/null @@ -1,407 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Thu, 1 Apr 2021 00:34:41 -0700 -Subject: [PATCH] Allow for Component suggestion tooltips in - AsyncTabCompleteEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java -index 619ed37169c126a8c75d02699a04728bac49d10d..4cd97cb102e1ec53b3fe1a451b65b4b640fde099 100644 ---- a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java -+++ b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java -@@ -24,6 +24,11 @@ - package com.destroystokyo.paper.event.server; - - import com.google.common.collect.ImmutableList; -+import io.papermc.paper.util.TransformingRandomAccessList; -+import net.kyori.adventure.text.Component; -+import net.kyori.examination.Examinable; -+import net.kyori.examination.ExaminableProperty; -+import net.kyori.examination.string.StringExaminer; - import org.apache.commons.lang.Validate; - import org.bukkit.Location; - import org.bukkit.command.Command; -@@ -34,6 +39,7 @@ import org.bukkit.event.HandlerList; - - import java.util.ArrayList; - import java.util.List; -+import java.util.stream.Stream; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - -@@ -48,15 +54,29 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { - private final boolean isCommand; - @Nullable - private final Location loc; -- @NotNull private List completions; -+ private final List completions = new ArrayList<>(); -+ private final List stringCompletions = new TransformingRandomAccessList<>( -+ this.completions, -+ Completion::suggestion, -+ Completion::completion -+ ); - private boolean cancelled; - private boolean handled = false; - private boolean fireSyncHandler = true; - -+ public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, boolean isCommand, @Nullable Location loc) { -+ super(true); -+ this.sender = sender; -+ this.buffer = buffer; -+ this.isCommand = isCommand; -+ this.loc = loc; -+ } -+ -+ @Deprecated - public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull List completions, @NotNull String buffer, boolean isCommand, @Nullable Location loc) { - super(true); - this.sender = sender; -- this.completions = completions; -+ this.completions.addAll(fromStrings(completions)); - this.buffer = buffer; - this.isCommand = isCommand; - this.loc = loc; -@@ -84,7 +104,7 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { - */ - @NotNull - public List getCompletions() { -- return completions; -+ return this.stringCompletions; - } - - /** -@@ -98,8 +118,42 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { - * @param completions the new completions - */ - public void setCompletions(@NotNull List completions) { -+ if (completions == this.stringCompletions) { -+ return; -+ } - Validate.notNull(completions); -- this.completions = new ArrayList<>(completions); -+ this.completions.clear(); -+ this.completions.addAll(fromStrings(completions)); -+ } -+ -+ /** -+ * The list of {@link Completion completions} which will be offered to the sender, in order. -+ * This list is mutable and reflects what will be offered. -+ *

    -+ * If this collection is not empty after the event is fired, then -+ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} -+ * or current player names will not be called. -+ * -+ * @return a list of offered completions -+ */ -+ public @NotNull List completions() { -+ return this.completions; -+ } -+ -+ /** -+ * Set the {@link Completion completions} offered, overriding any already set. -+ * If this collection is not empty after the event is fired, then -+ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} -+ * or current player names will not be called. -+ *

    -+ * The passed collection will be cloned to a new List. You must call {{@link #completions()}} to mutate from here -+ * -+ * @param newCompletions the new completions -+ */ -+ public void completions(final @NotNull List newCompletions) { -+ Validate.notNull(newCompletions, "new completions"); -+ this.completions.clear(); -+ this.completions.addAll(newCompletions); - } - - /** -@@ -174,4 +228,102 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { - public static HandlerList getHandlerList() { - return handlers; - } -+ -+ private static @NotNull List fromStrings(final @NotNull List strings) { -+ final List list = new ArrayList<>(); -+ for (final String it : strings) { -+ list.add(new CompletionImpl(it, null)); -+ } -+ return list; -+ } -+ -+ /** -+ * A rich tab completion, consisting of a string suggestion, and a nullable {@link Component} tooltip. -+ */ -+ public interface Completion extends Examinable { -+ /** -+ * Get the suggestion string for this {@link Completion}. -+ * -+ * @return suggestion string -+ */ -+ @NotNull String suggestion(); -+ -+ /** -+ * Get the suggestion tooltip for this {@link Completion}. -+ * -+ * @return tooltip component -+ */ -+ @Nullable Component tooltip(); -+ -+ @Override -+ default @NotNull Stream examinableProperties() { -+ return Stream.of(ExaminableProperty.of("suggestion", this.suggestion()), ExaminableProperty.of("tooltip", this.tooltip())); -+ } -+ -+ /** -+ * Create a new {@link Completion} from a suggestion string. -+ * -+ * @param suggestion suggestion string -+ * @return new completion instance -+ */ -+ static @NotNull Completion completion(final @NotNull String suggestion) { -+ return new CompletionImpl(suggestion, null); -+ } -+ -+ /** -+ * Create a new {@link Completion} from a suggestion string and a tooltip {@link Component}. -+ * -+ *

    If the provided component is null, the suggestion will not have a tooltip.

    -+ * -+ * @param suggestion suggestion string -+ * @param tooltip tooltip component, or null -+ * @return new completion instance -+ */ -+ static @NotNull Completion completion(final @NotNull String suggestion, final @Nullable Component tooltip) { -+ return new CompletionImpl(suggestion, tooltip); -+ } -+ } -+ -+ static final class CompletionImpl implements Completion { -+ private final String suggestion; -+ private final Component tooltip; -+ -+ CompletionImpl(final @NotNull String suggestion, final @Nullable Component tooltip) { -+ this.suggestion = suggestion; -+ this.tooltip = tooltip; -+ } -+ -+ @Override -+ public @NotNull String suggestion() { -+ return this.suggestion; -+ } -+ -+ @Override -+ public @Nullable Component tooltip() { -+ return this.tooltip; -+ } -+ -+ @Override -+ public boolean equals(final @Nullable Object o) { -+ if (this == o) { -+ return true; -+ } -+ if (o == null || this.getClass() != o.getClass()) { -+ return false; -+ } -+ final CompletionImpl that = (CompletionImpl) o; -+ return this.suggestion.equals(that.suggestion) -+ && java.util.Objects.equals(this.tooltip, that.tooltip); -+ } -+ -+ @Override -+ public int hashCode() { -+ return java.util.Objects.hash(this.suggestion, this.tooltip); -+ } -+ -+ @Override -+ public @NotNull String toString() { -+ return StringExaminer.simpleEscaping().examine(this); -+ } -+ } - } -diff --git a/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java b/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276118c1c7b ---- /dev/null -+++ b/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java -@@ -0,0 +1,169 @@ -+package io.papermc.paper.util; -+ -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.AbstractList; -+import java.util.Iterator; -+import java.util.List; -+import java.util.ListIterator; -+import java.util.RandomAccess; -+import java.util.function.Function; -+import java.util.function.Predicate; -+ -+import static com.google.common.base.Preconditions.checkNotNull; -+ -+/** -+ * Modified version of the Guava class with the same name to support add operations. -+ * -+ * @param backing list element type -+ * @param transformed list element type -+ */ -+public final class TransformingRandomAccessList extends AbstractList implements RandomAccess { -+ final List fromList; -+ final Function toFunction; -+ final Function fromFunction; -+ -+ /** -+ * Create a new {@link TransformingRandomAccessList}. -+ * -+ * @param fromList backing list -+ * @param toFunction function mapping backing list element type to transformed list element type -+ * @param fromFunction function mapping transformed list element type to backing list element type -+ */ -+ public TransformingRandomAccessList( -+ final @NonNull List fromList, -+ final @NonNull Function toFunction, -+ final @NonNull Function fromFunction -+ ) { -+ this.fromList = checkNotNull(fromList); -+ this.toFunction = checkNotNull(toFunction); -+ this.fromFunction = checkNotNull(fromFunction); -+ } -+ -+ @Override -+ public void clear() { -+ this.fromList.clear(); -+ } -+ -+ @Override -+ public T get(int index) { -+ return this.toFunction.apply(this.fromList.get(index)); -+ } -+ -+ @Override -+ public @NotNull Iterator iterator() { -+ return this.listIterator(); -+ } -+ -+ @Override -+ public @NotNull ListIterator listIterator(int index) { -+ return new TransformedListIterator(this.fromList.listIterator(index)) { -+ @Override -+ T transform(F from) { -+ return TransformingRandomAccessList.this.toFunction.apply(from); -+ } -+ -+ @Override -+ F transformBack(T from) { -+ return TransformingRandomAccessList.this.fromFunction.apply(from); -+ } -+ }; -+ } -+ -+ @Override -+ public boolean isEmpty() { -+ return this.fromList.isEmpty(); -+ } -+ -+ @Override -+ public boolean removeIf(Predicate filter) { -+ checkNotNull(filter); -+ return this.fromList.removeIf(element -> filter.test(this.toFunction.apply(element))); -+ } -+ -+ @Override -+ public T remove(int index) { -+ return this.toFunction.apply(this.fromList.remove(index)); -+ } -+ -+ @Override -+ public int size() { -+ return this.fromList.size(); -+ } -+ -+ @Override -+ public T set(int i, T t) { -+ return this.toFunction.apply(this.fromList.set(i, this.fromFunction.apply(t))); -+ } -+ -+ @Override -+ public void add(int i, T t) { -+ this.fromList.add(i, this.fromFunction.apply(t)); -+ } -+ -+ static abstract class TransformedListIterator implements ListIterator, Iterator { -+ final Iterator backingIterator; -+ -+ TransformedListIterator(ListIterator backingIterator) { -+ this.backingIterator = checkNotNull((Iterator) backingIterator); -+ } -+ -+ private ListIterator backingIterator() { -+ return cast(this.backingIterator); -+ } -+ -+ static
    ListIterator cast(Iterator iterator) { -+ return (ListIterator) iterator; -+ } -+ -+ @Override -+ public final boolean hasPrevious() { -+ return this.backingIterator().hasPrevious(); -+ } -+ -+ @Override -+ public final T previous() { -+ return this.transform(this.backingIterator().previous()); -+ } -+ -+ @Override -+ public final int nextIndex() { -+ return this.backingIterator().nextIndex(); -+ } -+ -+ @Override -+ public final int previousIndex() { -+ return this.backingIterator().previousIndex(); -+ } -+ -+ @Override -+ public void set(T element) { -+ this.backingIterator().set(this.transformBack(element)); -+ } -+ -+ @Override -+ public void add(T element) { -+ this.backingIterator().add(this.transformBack(element)); -+ } -+ -+ abstract T transform(F from); -+ -+ abstract F transformBack(T to); -+ -+ @Override -+ public final boolean hasNext() { -+ return this.backingIterator.hasNext(); -+ } -+ -+ @Override -+ public final T next() { -+ return this.transform(this.backingIterator.next()); -+ } -+ -+ @Override -+ public final void remove() { -+ this.backingIterator.remove(); -+ } -+ } -+} -diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 19271057cf24329757c9419fa6c97848e008a96c..82b2783497947f336b0dd95db61f31f8f77f446c 100644 ---- a/src/test/java/org/bukkit/AnnotationTest.java -+++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -48,6 +48,8 @@ public class AnnotationTest { - // Generic functional interface - "org/bukkit/util/Consumer", - // Paper start -+ "io/papermc/paper/util/TransformingRandomAccessList", -+ "io/papermc/paper/util/TransformingRandomAccessList$TransformedListIterator", - // Timings history is broken in terms of nullability due to guavas Function defining that the param is NonNull - "co/aikar/timings/TimingHistory$2", - "co/aikar/timings/TimingHistory$2$1", diff --git a/Unmapped-Spigot-API-Patches/0295-Add-EntityBlockStorage-clearEntities.patch b/Unmapped-Spigot-API-Patches/0295-Add-EntityBlockStorage-clearEntities.patch deleted file mode 100644 index 7032ba6155..0000000000 --- a/Unmapped-Spigot-API-Patches/0295-Add-EntityBlockStorage-clearEntities.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Mon, 5 Apr 2021 18:12:06 -0400 -Subject: [PATCH] Add EntityBlockStorage#clearEntities() - - -diff --git a/src/main/java/org/bukkit/block/EntityBlockStorage.java b/src/main/java/org/bukkit/block/EntityBlockStorage.java -index f3f8d765d5d487aa14edf0b88c32608fb804c331..739911cda33b373f99df627a3a378b37d7d461aa 100644 ---- a/src/main/java/org/bukkit/block/EntityBlockStorage.java -+++ b/src/main/java/org/bukkit/block/EntityBlockStorage.java -@@ -53,4 +53,11 @@ public interface EntityBlockStorage extends TileState { - * @param entity Entity to add to the block - */ - void addEntity(@NotNull T entity); -+ -+ // Paper start - Add EntityBlockStorage clearEntities -+ /** -+ * Clear all currently stored entities in the block. -+ */ -+ void clearEntities(); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/Unmapped-Spigot-API-Patches/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch deleted file mode 100644 index 16af3a7728..0000000000 --- a/Unmapped-Spigot-API-Patches/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alvinn8 <42838560+Alvinn8@users.noreply.github.com> -Date: Fri, 8 Jan 2021 20:29:58 +0100 -Subject: [PATCH] Add Adventure message to PlayerAdvancementDoneEvent - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerAdvancementDoneEvent.java b/src/main/java/org/bukkit/event/player/PlayerAdvancementDoneEvent.java -index 21ff095afb434d15babcdbe85fa0b94cbb7e75a7..6f618bb140a901c5c1cd08210978a6a651677ba4 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerAdvancementDoneEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerAdvancementDoneEvent.java -@@ -4,6 +4,10 @@ import org.bukkit.advancement.Advancement; - import org.bukkit.entity.Player; - import org.bukkit.event.HandlerList; - import org.jetbrains.annotations.NotNull; -+// Paper start -+import org.jetbrains.annotations.Nullable; -+import net.kyori.adventure.text.Component; -+// Paper end - - /** - * Called when a player has completed all criteria in an advancement. -@@ -13,10 +17,17 @@ public class PlayerAdvancementDoneEvent extends PlayerEvent { - private static final HandlerList handlers = new HandlerList(); - // - private final Advancement advancement; -+ private Component message; // Paper - Add Adventure message - - public PlayerAdvancementDoneEvent(@NotNull Player who, @NotNull Advancement advancement) { -+ // Paper start - Add Adventure message -+ this(who, advancement, null); -+ } -+ public PlayerAdvancementDoneEvent(@NotNull Player who, @NotNull Advancement advancement, @Nullable Component message) { -+ // Paper end - super(who); - this.advancement = advancement; -+ this.message = message; // Paper - Add Adventure message - } - - /** -@@ -29,6 +40,31 @@ public class PlayerAdvancementDoneEvent extends PlayerEvent { - return advancement; - } - -+ // Paper start - Add Adventure message -+ /** -+ * Gets the message to send to all online players. -+ *

    -+ * Will be null if the advancement does not announce to chat, for example if -+ * it is a recipe unlock or a root advancement. -+ * -+ * @return The announcement message, or null -+ */ -+ @Nullable -+ public Component message() { -+ return this.message; -+ } -+ -+ /** -+ * Sets the message to send to all online players. -+ *

    -+ * If set to null the message will not be sent. -+ * -+ * @param message The new message -+ */ -+ public void message(@Nullable Component message) { -+ this.message = message; -+ } -+ // Paper end - @NotNull - @Override - public HandlerList getHandlers() { diff --git a/Unmapped-Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/Unmapped-Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch deleted file mode 100644 index 58db0a8a2b..0000000000 --- a/Unmapped-Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Wed, 12 May 2021 08:09:19 +0100 -Subject: [PATCH] Add raw address to AsyncPlayerPreLoginEvent - - -diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -index c9af02b0f62b3d18da1e91d1ea02ce0864fc60b9..77aefda5aac4602bf5bf71c29600e7450defdd4e 100644 ---- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -@@ -20,6 +20,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - private net.kyori.adventure.text.Component message; // Paper - //private String name; // Paper - Not used anymore - private final InetAddress ipAddress; -+ private final InetAddress rawAddress; // Paper - //private UUID uniqueId; // Paper - Not used anymore - - @Deprecated -@@ -49,7 +50,23 @@ public class AsyncPlayerPreLoginEvent extends Event { - this.profile = profile; - } - -+ // Paper Start -+ /** -+ * Gets the raw address of the player logging in -+ * @return The address -+ */ -+ @NotNull -+ public InetAddress getRawAddress() { -+ return rawAddress; -+ } -+ // Paper end -+ -+ @Deprecated - public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId, @NotNull PlayerProfile profile) { -+ this(name, ipAddress, ipAddress, uniqueId, profile); -+ } -+ -+ public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final InetAddress rawAddress, @NotNull final UUID uniqueId, @NotNull PlayerProfile profile) { - super(true); - this.profile = profile; - // Paper end -@@ -57,6 +74,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - this.message = net.kyori.adventure.text.Component.empty(); // Paper - //this.name = name; // Paper - Not used anymore - this.ipAddress = ipAddress; -+ this.rawAddress = rawAddress; // Paper - //this.uniqueId = uniqueId; // Paper - Not used anymore - } - diff --git a/Unmapped-Spigot-API-Patches/0298-Inventory-close.patch b/Unmapped-Spigot-API-Patches/0298-Inventory-close.patch deleted file mode 100644 index 550e287fa6..0000000000 --- a/Unmapped-Spigot-API-Patches/0298-Inventory-close.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 11 May 2021 14:54:20 -0700 -Subject: [PATCH] Inventory#close - - -diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java -index 7956aebcb390379677dccf7c9561866cf94c024c..8f00cb2e3bc9963e9657c1b2493e8b015a6664d0 100644 ---- a/src/main/java/org/bukkit/inventory/Inventory.java -+++ b/src/main/java/org/bukkit/inventory/Inventory.java -@@ -353,6 +353,15 @@ public interface Inventory extends Iterable { - */ - public void clear(); - -+ // Paper start -+ /** -+ * Closes the inventory for all viewers. -+ * -+ * @return the number if viewers the inventory was closed for -+ */ -+ public int close(); -+ // Paper end -+ - /** - * Gets a list of players viewing the inventory. Note that a player is - * considered to be viewing their own inventory and internal crafting diff --git a/Unmapped-Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/Unmapped-Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch deleted file mode 100644 index 9b01b30676..0000000000 --- a/Unmapped-Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 11 May 2021 00:48:51 +0200 -Subject: [PATCH] Add a "should burn in sunlight" API for Phantoms and - Skeletons - - -diff --git a/src/main/java/org/bukkit/entity/Phantom.java b/src/main/java/org/bukkit/entity/Phantom.java -index ed4d417c2deefb78807cb61b01df5afcd334d754..a40b045f08b85e22e75459b547e7e7c0b95103ed 100644 ---- a/src/main/java/org/bukkit/entity/Phantom.java -+++ b/src/main/java/org/bukkit/entity/Phantom.java -@@ -26,5 +26,19 @@ public interface Phantom extends Flying { - */ - @Nullable - public java.util.UUID getSpawningEntity(); -+ -+ /** -+ * Check if this phantom will burn in the sunlight -+ * -+ * @return True if phantom will burn in sunlight -+ */ -+ public boolean shouldBurnInDay(); -+ -+ /** -+ * Set if this phantom should burn in the sunlight -+ * -+ * @param shouldBurnInDay True to burn in sunlight -+ */ -+ public void setShouldBurnInDay(boolean shouldBurnInDay); - // Paper end - } -diff --git a/src/main/java/org/bukkit/entity/Skeleton.java b/src/main/java/org/bukkit/entity/Skeleton.java -index 1c367f78eadf24850061a84ce63b950b79d3c435..684477b894e52ff33f9fce2edf76e58c292dd75e 100644 ---- a/src/main/java/org/bukkit/entity/Skeleton.java -+++ b/src/main/java/org/bukkit/entity/Skeleton.java -@@ -46,4 +46,19 @@ public interface Skeleton extends Monster, RangedEntity { // Paper - */ - STRAY; - } -+ // Paper start -+ /** -+ * Check if this skeleton will burn in the sunlight -+ * -+ * @return True if skeleton will burn in sunlight -+ */ -+ boolean shouldBurnInDay(); -+ -+ /** -+ * Set if this skeleton should burn in the sunlight -+ * -+ * @param shouldBurnInDay True to burn in sunlight -+ */ -+ void setShouldBurnInDay(boolean shouldBurnInDay); -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0300-Add-basic-Datapack-API.patch b/Unmapped-Spigot-API-Patches/0300-Add-basic-Datapack-API.patch deleted file mode 100644 index ae9149d2f3..0000000000 --- a/Unmapped-Spigot-API-Patches/0300-Add-basic-Datapack-API.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Sun, 16 May 2021 15:07:34 +0100 -Subject: [PATCH] Add basic Datapack API - - -diff --git a/src/main/java/io/papermc/paper/datapack/Datapack.java b/src/main/java/io/papermc/paper/datapack/Datapack.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7b2ab0be10a21e0496ad1d485ff8cb2c0b92a2cb ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/Datapack.java -@@ -0,0 +1,32 @@ -+package io.papermc.paper.datapack; -+ -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+public interface Datapack { -+ -+ /** -+ * @return the name of the pack -+ */ -+ @NonNull -+ String getName(); -+ -+ /** -+ * @return the compatibility of the pack -+ */ -+ @NonNull -+ Compatibility getCompatibility(); -+ -+ /** -+ * @return whether or not the pack is currently enabled -+ */ -+ boolean isEnabled(); -+ -+ void setEnabled(boolean enabled); -+ -+ enum Compatibility { -+ TOO_OLD, -+ TOO_NEW, -+ COMPATIBLE, -+ } -+ -+} -diff --git a/src/main/java/io/papermc/paper/datapack/DatapackManager.java b/src/main/java/io/papermc/paper/datapack/DatapackManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..58f78d5e91beacaf710f62461cf869f70d08b2a2 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/DatapackManager.java -@@ -0,0 +1,21 @@ -+package io.papermc.paper.datapack; -+ -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+import java.util.Collection; -+ -+public interface DatapackManager { -+ -+ /** -+ * @return all the packs known to the server -+ */ -+ @NonNull -+ Collection getPacks(); -+ -+ /** -+ * @return all the packs which are currently enabled -+ */ -+ @NonNull -+ Collection getEnabledPacks(); -+ -+} -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 050ee6a6fd0b74d9bfdd9dfe88cd4cd3d17da868..a8b6cc350e85d4f1a31f30dee42feafd0edb6009 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1949,6 +1949,14 @@ public final class Bukkit { - public static com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { - return server.getMobGoals(); - } -+ -+ /** -+ * @return the datapack manager -+ */ -+ @NotNull -+ public static io.papermc.paper.datapack.DatapackManager getDatapackManager() { -+ return server.getDatapackManager(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index eb7f604600839618eaf27e0e5444b4830716eb07..2b400079559abd6b847782ae8480f2ae1948e22a 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1709,5 +1709,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - */ - @NotNull - com.destroystokyo.paper.entity.ai.MobGoals getMobGoals(); -+ -+ /** -+ * @return the datapack manager -+ */ -+ @NotNull -+ io.papermc.paper.datapack.DatapackManager getDatapackManager(); - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0301-additions-to-PlayerGameModeChangeEvent.patch b/Unmapped-Spigot-API-Patches/0301-additions-to-PlayerGameModeChangeEvent.patch deleted file mode 100644 index 07c662e585..0000000000 --- a/Unmapped-Spigot-API-Patches/0301-additions-to-PlayerGameModeChangeEvent.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 10:04:50 -0700 -Subject: [PATCH] additions to PlayerGameModeChangeEvent - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerGameModeChangeEvent.java b/src/main/java/org/bukkit/event/player/PlayerGameModeChangeEvent.java -index 4b96e0573c7ce32ad8c41124ee9ecab8359318a5..b71f37dc8ac00175efd9275e9d8988bb5f2d9c47 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerGameModeChangeEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerGameModeChangeEvent.java -@@ -13,10 +13,22 @@ public class PlayerGameModeChangeEvent extends PlayerEvent implements Cancellabl - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled; - private final GameMode newGameMode; -+ // Paper start -+ private final Cause cause; -+ private net.kyori.adventure.text.Component cancelMessage; - -+ @Deprecated // Paper end - public PlayerGameModeChangeEvent(@NotNull final Player player, @NotNull final GameMode newGameMode) { -+ // Paper start -+ this(player, newGameMode, Cause.UNKNOWN, null); -+ } -+ -+ public PlayerGameModeChangeEvent(@NotNull final Player player, @NotNull final GameMode newGameMode, @NotNull Cause cause, @org.jetbrains.annotations.Nullable net.kyori.adventure.text.Component cancelMessage) { -+ // Paper end - super(player); - this.newGameMode = newGameMode; -+ this.cause = cause; // Paper -+ this.cancelMessage = cancelMessage; // Paper - } - - @Override -@@ -49,4 +61,77 @@ public class PlayerGameModeChangeEvent extends PlayerEvent implements Cancellabl - public static HandlerList getHandlerList() { - return handlers; - } -+ // Paper start -+ /** -+ * Gets the cause of this gamemode change. -+ * -+ * @return the cause -+ */ -+ @NotNull -+ public Cause getCause() { -+ return cause; -+ } -+ -+ /** -+ * Only valid if the cause of the gamemode change was directly due to a command.. -+ * Gets the message shown to the command user if the event is cancelled -+ * as a notification that a player's gamemode was not changed. -+ *

    -+ * This returns {@code null} if the gamemode change was due to a plugin, or a -+ * player joining the game with a gamemode not equal to the server default gamemode -+ * and {@code force-gamemode} is set to true. -+ * -+ * @return the error message shown to the command user, null if not directly caused by a command -+ */ -+ @org.jetbrains.annotations.Nullable -+ public net.kyori.adventure.text.Component cancelMessage() { -+ return cancelMessage; -+ } -+ -+ /** -+ * Sets the message shown to the command user if the event was cancelled. -+ * The message is only shown to cancelled events that are directly called by a command -+ * not by a plugin or a player joining with the wrong gamemode. -+ * -+ * @param message the error message shown to the command user, null to show no message. -+ */ -+ public void cancelMessage(@org.jetbrains.annotations.Nullable net.kyori.adventure.text.Component message) { -+ this.cancelMessage = message; -+ } -+ -+ public enum Cause { -+ -+ /** -+ * A plugin changed the player's gamemode with -+ * {@link Player#setGameMode(GameMode)}. -+ */ -+ PLUGIN, -+ -+ /** -+ * The {@code /gamemode} command was used. -+ */ -+ COMMAND, -+ -+ /** -+ * A player had their gamemode changed as a result of -+ * the {@code /defaultgamemode} command, or they joined -+ * with a gamemode that was not the default gamemode and -+ * {@code force-gamemode} in {@code server.properties} is set to true. -+ */ -+ DEFAULT_GAMEMODE, -+ -+ /** -+ * When the player dies in a hardcore world and has their gamemode -+ * changed to {@link GameMode#SPECTATOR}. -+ */ -+ HARDCORE_DEATH, -+ -+ /** -+ * This cause is only used if a plugin fired their own -+ * {@link PlayerGameModeChangeEvent} and did not include a -+ * cause. Can usually be ignored. -+ */ -+ UNKNOWN, -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0302-ItemStack-repair-check-API.patch b/Unmapped-Spigot-API-Patches/0302-ItemStack-repair-check-API.patch deleted file mode 100644 index 2281b38541..0000000000 --- a/Unmapped-Spigot-API-Patches/0302-ItemStack-repair-check-API.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 22:10:50 -0700 -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 6dbd520182b1e7713a68baad09b7f613424ef619..e504567cf755557be8511f2c93c171572b78e722 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -155,6 +155,16 @@ public interface UnsafeValues { - */ - public io.papermc.paper.inventory.ItemRarity getItemStackRarity(ItemStack itemStack); - -+ /** -+ * Checks if an itemstack can be repaired with another itemstack. -+ * Returns false if either argument's type is not an item ({@link Material#isItem()}). -+ * -+ * @param itemToBeRepaired the itemstack to be repaired -+ * @param repairMaterial the repair material -+ * @return true if valid repair, false if not -+ */ -+ public boolean isValidRepairItemStack(@org.jetbrains.annotations.NotNull ItemStack itemToBeRepaired, @org.jetbrains.annotations.NotNull ItemStack repairMaterial); -+ - /** - * Returns the server's protocol version. - * -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index fccfae41f53a175e1a6a670c793e464456de6b60..0f8c593ae9bca46081f0b22c2d763a2699175398 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -873,5 +873,27 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public io.papermc.paper.inventory.ItemRarity getRarity() { - return Bukkit.getUnsafe().getItemStackRarity(this); - } -+ -+ /** -+ * Checks if an itemstack can repair this itemstack. -+ * Returns false if {@code this} or {@code repairMaterial}'s type is not an item ({@link Material#isItem()}). -+ * -+ * @param repairMaterial the repair material -+ * @return true if it is repairable by, false if not -+ */ -+ public boolean isRepairableBy(@NotNull ItemStack repairMaterial) { -+ return Bukkit.getUnsafe().isValidRepairItemStack(this, repairMaterial); -+ } -+ -+ /** -+ * Checks if this itemstack can repair another. -+ * Returns false if {@code this} or {@code toBeRepaired}'s type is not an item ({@link Material#isItem()}). -+ * -+ * @param toBeRepaired the itemstack to be repaired -+ * @return true if it can repair, false if not -+ */ -+ public boolean canRepair(@NotNull ItemStack toBeRepaired) { -+ return Bukkit.getUnsafe().isValidRepairItemStack(toBeRepaired, this); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0303-More-Enchantment-API.patch b/Unmapped-Spigot-API-Patches/0303-More-Enchantment-API.patch deleted file mode 100644 index dda68575ca..0000000000 --- a/Unmapped-Spigot-API-Patches/0303-More-Enchantment-API.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 6 May 2021 19:58:03 -0700 -Subject: [PATCH] More Enchantment API - - -diff --git a/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java b/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e6a40c1fcea761bd66743b50e3da3d14797d05b0 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java -@@ -0,0 +1,24 @@ -+package io.papermc.paper.enchantments; -+ -+public enum EnchantmentRarity { -+ -+ COMMON(10), -+ UNCOMMON(5), -+ RARE(2), -+ VERY_RARE(1); -+ -+ private final int weight; -+ -+ EnchantmentRarity(int weight) { -+ this.weight = weight; -+ } -+ -+ /** -+ * Gets the weight for the rarity. -+ * -+ * @return the weight -+ */ -+ public int getWeight() { -+ return weight; -+ } -+} -diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java -index 8eb0497c81744874809ebc4bc2e28b128e66a926..799813410f40589ba1d7d530a47d87f609764705 100644 ---- a/src/main/java/org/bukkit/enchantments/Enchantment.java -+++ b/src/main/java/org/bukkit/enchantments/Enchantment.java -@@ -306,6 +306,46 @@ public abstract class Enchantment implements Keyed { - * @return the name of the enchantment with {@code level} applied - */ - public abstract @NotNull net.kyori.adventure.text.Component displayName(int level); -+ -+ /** -+ * Checks if this enchantment can be found in villager trades. -+ * -+ * @return true if the enchantment can be found in trades -+ */ -+ public abstract boolean isTradeable(); -+ -+ /** -+ * Checks if this enchantment can be found in an enchanting table -+ * or use to enchant items generated by loot tables. -+ * -+ * @return true if the enchantment can be found in a table or by loot tables -+ */ -+ public abstract boolean isDiscoverable(); -+ -+ /** -+ * Gets the rarity of this enchantment. -+ * -+ * @return the rarity -+ */ -+ @NotNull -+ public abstract io.papermc.paper.enchantments.EnchantmentRarity getRarity(); -+ -+ /** -+ * Gets the damage increase as a result of the level and entity category specified -+ * -+ * @param level the level of enchantment -+ * @param entityCategory the category of entity -+ * @return the damage increase -+ */ -+ public abstract float getDamageIncrease(int level, @NotNull org.bukkit.entity.EntityCategory entityCategory); -+ -+ /** -+ * Gets the equipment slots where this enchantment is considered "active". -+ * -+ * @return the equipment slots -+ */ -+ @NotNull -+ public abstract java.util.Set getActiveSlots(); - // Paper end - - @Override -diff --git a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java -index 4d5f0837bd0e02a30c943d8969fb6b13452322e0..ca097db904db96e81c0ea4b06b445a13e9333cfe 100644 ---- a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java -+++ b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java -@@ -69,5 +69,32 @@ public class EnchantmentWrapper extends Enchantment { - public net.kyori.adventure.text.Component displayName(int level) { - return getEnchantment().displayName(level); - } -+ -+ @Override -+ public boolean isTradeable() { -+ return getEnchantment().isTradeable(); -+ } -+ -+ @Override -+ public boolean isDiscoverable() { -+ return getEnchantment().isDiscoverable(); -+ } -+ -+ @NotNull -+ @Override -+ public io.papermc.paper.enchantments.EnchantmentRarity getRarity() { -+ return getEnchantment().getRarity(); -+ } -+ -+ @Override -+ public float getDamageIncrease(int level, @NotNull org.bukkit.entity.EntityCategory entityCategory) { -+ return getEnchantment().getDamageIncrease(level, entityCategory); -+ } -+ -+ @NotNull -+ @Override -+ public java.util.Set getActiveSlots() { -+ return getEnchantment().getActiveSlots(); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/Unmapped-Spigot-API-Patches/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch deleted file mode 100644 index c4cd74cdbe..0000000000 --- a/Unmapped-Spigot-API-Patches/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Tue, 18 May 2021 14:42:26 -0700 -Subject: [PATCH] Add command line option to load extra plugin jars not in the - plugins folder - -ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar - -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 26685f59b235ea5b4c4fb7ae21acb5149edaa2b3..ca866876f2f35a1c41eb009064412423fa09e441 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -60,6 +60,7 @@ public final class SimplePluginManager implements PluginManager { - private final Map> permSubs = new HashMap>(); - private final Map> defSubs = new HashMap>(); - private boolean useTimings = false; -+ private File pluginsDirectory; public @Nullable File pluginsDirectory() { return this.pluginsDirectory; } // Paper - - public SimplePluginManager(@NotNull Server instance, @NotNull SimpleCommandMap commandMap) { - server = instance; -@@ -115,6 +116,13 @@ public final class SimplePluginManager implements PluginManager { - @Override - @NotNull - public Plugin[] loadPlugins(@NotNull File directory) { -+ // Paper start - extra jars -+ return this.loadPlugins(directory, java.util.Collections.emptyList()); -+ } -+ @NotNull -+ public Plugin[] loadPlugins(final @NotNull File directory, final @NotNull List extraPluginJars) { -+ this.pluginsDirectory = directory; -+ // Paper end - Validate.notNull(directory, "Directory cannot be null"); - Validate.isTrue(directory.isDirectory(), "Directory must be a directory"); - -@@ -132,7 +140,11 @@ public final class SimplePluginManager implements PluginManager { - Map> softDependencies = new HashMap>(); - - // This is where it figures out all possible plugins -- for (File file : directory.listFiles()) { -+ // Paper start - extra jars -+ final List pluginJars = new ArrayList<>(java.util.Arrays.asList(directory.listFiles())); -+ pluginJars.addAll(extraPluginJars); -+ for (File file : pluginJars) { -+ // Paper end - PluginLoader loader = null; - for (Pattern filter : filters) { - Matcher match = filter.matcher(file.getName()); -@@ -148,14 +160,14 @@ public final class SimplePluginManager implements PluginManager { - description = loader.getPluginDescription(file); - String name = description.getName(); - if (name.equalsIgnoreCase("bukkit") || name.equalsIgnoreCase("minecraft") || name.equalsIgnoreCase("mojang")) { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "': Restricted Name"); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "': Restricted Name"); // Paper - continue; - } else if (description.rawName.indexOf(' ') != -1) { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "': uses the space-character (0x20) in its name"); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "': uses the space-character (0x20) in its name"); // Paper - continue; - } - } catch (InvalidDescriptionException ex) { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", ex); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'", ex); // Paper - continue; - } - -@@ -166,7 +178,7 @@ public final class SimplePluginManager implements PluginManager { - description.getName(), - file.getPath(), - replacedFile.getPath(), -- directory.getPath() -+ file.getParentFile().getPath() // Paper - )); - } - -@@ -187,7 +199,7 @@ public final class SimplePluginManager implements PluginManager { - file.getPath(), - provided, - pluginFile.getPath(), -- directory.getPath() -+ file.getParentFile().getPath() // Paper - )); - } else { - String replacedPlugin = pluginsProvided.put(provided, description.getName()); -@@ -269,7 +281,7 @@ public final class SimplePluginManager implements PluginManager { - - server.getLogger().log( - Level.SEVERE, -- "Could not load '" + entry.getValue().getPath() + "' in folder '" + directory.getPath() + "'", -+ "Could not load '" + entry.getValue().getPath() + "' in folder '" + entry.getValue().getParentFile().getPath() + "'", // Paper - new UnknownDependencyException("Unknown dependency " + dependency + ". Please download and install " + dependency + " to run this plugin.")); - break; - } -@@ -308,11 +320,11 @@ public final class SimplePluginManager implements PluginManager { - loadedPlugins.add(loadedPlugin.getName()); - loadedPlugins.addAll(loadedPlugin.getDescription().getProvides()); - } else { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'"); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'"); // Paper - } - continue; - } catch (InvalidPluginException ex) { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", ex); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'", ex); // Paper - } - } - } -@@ -339,11 +351,11 @@ public final class SimplePluginManager implements PluginManager { - loadedPlugins.add(loadedPlugin.getName()); - loadedPlugins.addAll(loadedPlugin.getDescription().getProvides()); - } else { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'"); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'"); // Paper - } - break; - } catch (InvalidPluginException ex) { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", ex); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'", ex); // Paper - } - } - } -@@ -356,7 +368,7 @@ public final class SimplePluginManager implements PluginManager { - while (failedPluginIterator.hasNext()) { - File file = failedPluginIterator.next(); - failedPluginIterator.remove(); -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "': circular dependency detected"); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "': circular dependency detected"); // Paper - } - } - } -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 31793f46e5623729dfb4048e901f274082f57826..d3812d8cd195017841ee08ffbc53a5748fcc74ec 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -94,7 +94,7 @@ public final class JavaPluginLoader implements PluginLoader { - throw new InvalidPluginException(ex); - } - -- final File parentFile = file.getParentFile(); -+ final File parentFile = ((SimplePluginManager) this.server.getPluginManager()).pluginsDirectory(); // Paper - final File dataFolder = new File(parentFile, description.getName()); - @SuppressWarnings("deprecation") - final File oldDataFolder = new File(parentFile, description.getRawName()); diff --git a/Unmapped-Spigot-API-Patches/0305-List-all-missing-hard-depends-not-just-first.patch b/Unmapped-Spigot-API-Patches/0305-List-all-missing-hard-depends-not-just-first.patch deleted file mode 100644 index bbbab43d60..0000000000 --- a/Unmapped-Spigot-API-Patches/0305-List-all-missing-hard-depends-not-just-first.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 18 May 2021 10:38:10 -0700 -Subject: [PATCH] List all missing hard depends not just first - - -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index ca866876f2f35a1c41eb009064412423fa09e441..d1c35e4cf778070f8d18bbe0af8d423334c6dfbf 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -264,6 +264,7 @@ public final class SimplePluginManager implements PluginManager { - - if (dependencies.containsKey(plugin)) { - Iterator dependencyIterator = dependencies.get(plugin).iterator(); -+ final Set missingHardDependencies = new HashSet<>(dependencies.get(plugin).size()); // Paper - list all missing hard depends - - while (dependencyIterator.hasNext()) { - String dependency = dependencyIterator.next(); -@@ -274,6 +275,12 @@ public final class SimplePluginManager implements PluginManager { - - // We have a dependency not found - } else if (!plugins.containsKey(dependency) && !pluginsProvided.containsKey(dependency)) { -+ // Paper start -+ missingHardDependencies.add(dependency); -+ } -+ } -+ if (!missingHardDependencies.isEmpty()) { -+ // Paper end - missingDependency = false; - pluginIterator.remove(); - softDependencies.remove(plugin); -@@ -282,9 +289,7 @@ public final class SimplePluginManager implements PluginManager { - server.getLogger().log( - Level.SEVERE, - "Could not load '" + entry.getValue().getPath() + "' in folder '" + entry.getValue().getParentFile().getPath() + "'", // Paper -- new UnknownDependencyException("Unknown dependency " + dependency + ". Please download and install " + dependency + " to run this plugin.")); -- break; -- } -+ new UnknownDependencyException(missingHardDependencies, plugin)); // Paper - } - - if (dependencies.containsKey(plugin) && dependencies.get(plugin).isEmpty()) { -diff --git a/src/main/java/org/bukkit/plugin/UnknownDependencyException.java b/src/main/java/org/bukkit/plugin/UnknownDependencyException.java -index a80251eff75430863b37db1c131e22593f3fcd5e..7b2e607a21f1173d98ee84581881411176380625 100644 ---- a/src/main/java/org/bukkit/plugin/UnknownDependencyException.java -+++ b/src/main/java/org/bukkit/plugin/UnknownDependencyException.java -@@ -26,6 +26,19 @@ public class UnknownDependencyException extends RuntimeException { - super(message); - } - -+ // Paper start -+ /** -+ * Create a new {@link UnknownDependencyException} with a message informing -+ * about which dependencies are missing for what plugin. -+ * -+ * @param missingDependencies missing dependencies -+ * @param pluginName plugin which is missing said dependencies -+ */ -+ public UnknownDependencyException(final @org.jetbrains.annotations.NotNull java.util.Collection missingDependencies, final @org.jetbrains.annotations.NotNull String pluginName) { -+ this("Unknown/missing dependency plugins: [" + String.join(", ", missingDependencies) + "]. Please download and install these plugins to run '" + pluginName + "'."); -+ } -+ // Paper end -+ - /** - * Constructs a new UnknownDependencyException based on the given - * Exception -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index d3812d8cd195017841ee08ffbc53a5748fcc74ec..b622cedeeee017f042bcf92485d81832030a8030 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -132,13 +132,19 @@ public final class JavaPluginLoader implements PluginLoader { - )); - } - -+ Set missingHardDependencies = new HashSet<>(description.getDepend().size()); // Paper - list all missing hard depends - for (final String pluginName : description.getDepend()) { - Plugin current = server.getPluginManager().getPlugin(pluginName); - - if (current == null) { -- throw new UnknownDependencyException("Unknown dependency " + pluginName + ". Please download and install " + pluginName + " to run this plugin."); -+ missingHardDependencies.add(pluginName); // Paper - list all missing hard depends - } - } -+ // Paper start - list all missing hard depends -+ if (!missingHardDependencies.isEmpty()) { -+ throw new UnknownDependencyException(missingHardDependencies, description.getFullName()); -+ } -+ // Paper end - - server.getUnsafe().checkSupported(description); - diff --git a/Unmapped-Spigot-API-Patches/0306-Add-Mob-lookAt-API.patch b/Unmapped-Spigot-API-Patches/0306-Add-Mob-lookAt-API.patch deleted file mode 100644 index b1a75288cb..0000000000 --- a/Unmapped-Spigot-API-Patches/0306-Add-Mob-lookAt-API.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 14 May 2021 13:42:06 -0500 -Subject: [PATCH] Add Mob#lookAt API - - -diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java -index d726453c041a980576312b6bee96a07837f37974..7d4ce660adb21e579e564796568945ee20f0ca59 100644 ---- a/src/main/java/org/bukkit/entity/Mob.java -+++ b/src/main/java/org/bukkit/entity/Mob.java -@@ -23,6 +23,88 @@ public interface Mob extends LivingEntity, Lootable { - * @return True if mob is exposed to daylight - */ - boolean isInDaylight(); -+ -+ /** -+ * Instruct this Mob to look at a specific Location -+ *

    -+ * Useful when implementing custom mob goals -+ * -+ * @param location location to look at -+ */ -+ void lookAt(@NotNull org.bukkit.Location location); -+ -+ /** -+ * Instruct this Mob to look at a specific Location -+ *

    -+ * Useful when implementing custom mob goals -+ * -+ * @param location location to look at -+ * @param headRotationSpeed head rotation speed -+ * @param maxHeadPitch max head pitch rotation -+ */ -+ void lookAt(@NotNull org.bukkit.Location location, float headRotationSpeed, float maxHeadPitch); -+ -+ /** -+ * Instruct this Mob to look at a specific Entity -+ *

    -+ * If a LivingEntity, look at eye location -+ *

    -+ * Useful when implementing custom mob goals -+ * -+ * @param entity entity to look at -+ */ -+ void lookAt(@NotNull Entity entity); -+ -+ /** -+ * Instruct this Mob to look at a specific Entity -+ *

    -+ * If a LivingEntity, look at eye location -+ *

    -+ * Useful when implementing custom mob goals -+ * -+ * @param entity entity to look at -+ * @param headRotationSpeed head rotation speed -+ * @param maxHeadPitch max head pitch rotation -+ */ -+ void lookAt(@NotNull Entity entity, float headRotationSpeed, float maxHeadPitch); -+ -+ /** -+ * Instruct this Mob to look at a specific position -+ *

    -+ * Useful when implementing custom mob goals -+ * -+ * @param x x coordinate -+ * @param y y coordinate -+ * @param z z coordinate -+ */ -+ void lookAt(double x, double y, double z); -+ -+ /** -+ * Instruct this Mob to look at a specific position -+ *

    -+ * Useful when implementing custom mob goals -+ * -+ * @param x x coordinate -+ * @param y y coordinate -+ * @param z z coordinate -+ * @param headRotationSpeed head rotation speed -+ * @param maxHeadPitch max head pitch rotation -+ */ -+ void lookAt(double x, double y, double z, float headRotationSpeed, float maxHeadPitch); -+ -+ /** -+ * Gets the head rotation speed -+ * -+ * @return the head rotation speed -+ */ -+ int getHeadRotationSpeed(); -+ -+ /** -+ * Gets the max head pitch rotation -+ * -+ * @return the max head pitch rotation -+ */ -+ int getMaxHeadPitch(); - // Paper end - - /** diff --git a/Unmapped-Spigot-API-Patches/0307-ItemStack-editMeta.patch b/Unmapped-Spigot-API-Patches/0307-ItemStack-editMeta.patch deleted file mode 100644 index d9b90f5c32..0000000000 --- a/Unmapped-Spigot-API-Patches/0307-ItemStack-editMeta.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Sun, 23 May 2021 05:04:28 -0700 -Subject: [PATCH] ItemStack#editMeta - - -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 1bd9f7582bb907ff178fd110fdc92834885d1d78..a7909406e9d54c1ab4789b984ed6b1da50837fce 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -542,6 +542,31 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - return result.ensureServerConversions(); // Paper - } - -+ // Paper start -+ /** -+ * Edits the {@link ItemMeta} of this stack. -+ *

    -+ * The {@link java.util.function.Consumer} must only interact -+ * with this stack's {@link ItemMeta} through the provided {@link ItemMeta} instance. -+ * Calling this method or any other meta-related method of the {@link ItemStack} class -+ * (such as {@link #getItemMeta()}, {@link #addItemFlags(ItemFlag...)}, {@link #lore()}, etc.) -+ * from inside the consumer is disallowed and will produce undefined results or exceptions. -+ *

    -+ * -+ * @param consumer the meta consumer -+ * @return {@code true} if the edit was successful, {@code false} otherwise -+ */ -+ public boolean editMeta(final @NotNull java.util.function.Consumer consumer) { -+ final ItemMeta meta = this.getItemMeta(); -+ if (meta != null) { -+ consumer.accept(meta); -+ this.setItemMeta(meta); -+ return true; -+ } -+ return false; -+ } -+ // Paper end -+ - /** - * Get a copy of this ItemStack's {@link ItemMeta}. - * diff --git a/Unmapped-Spigot-API-Patches/0308-Add-EntityInsideBlockEvent.patch b/Unmapped-Spigot-API-Patches/0308-Add-EntityInsideBlockEvent.patch deleted file mode 100644 index 26c188e7a0..0000000000 --- a/Unmapped-Spigot-API-Patches/0308-Add-EntityInsideBlockEvent.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 8 May 2021 18:02:06 -0700 -Subject: [PATCH] Add EntityInsideBlockEvent - - -diff --git a/src/main/java/io/papermc/paper/event/entity/EntityInsideBlockEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityInsideBlockEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..94e8b6f6501c92711bd0bc9ee0f67e28f85a605f ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/entity/EntityInsideBlockEvent.java -@@ -0,0 +1,80 @@ -+package io.papermc.paper.event.entity; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when an entity enters the hitbox of a block. -+ * Only called for blocks that react when an entity is inside. -+ * If cancelled, any action that would have resulted from that entity -+ * being in the block will not happen (such as extinguishing an entity in a cauldron). -+ *

    -+ * Blocks this is currently called for: -+ *

      -+ *
    • Bubble column
    • -+ *
    • Buttons
    • -+ *
    • Cactus
    • -+ *
    • Campfire
    • -+ *
    • Cauldron
    • -+ *
    • Crops
    • -+ *
    • Ender Portal
    • -+ *
    • Fires
    • -+ *
    • Honey
    • -+ *
    • Hopper
    • -+ *
    • Detector rails
    • -+ *
    • Nether portals
    • -+ *
    • Pressure plates
    • -+ *
    • Sweet berry bush
    • -+ *
    • Tripwire
    • -+ *
    • Waterlily
    • -+ *
    • Web
    • -+ *
    • Wither rose
    • -+ *
    -+ */ -+public class EntityInsideBlockEvent extends EntityEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private final Block block; -+ private boolean cancelled; -+ -+ public EntityInsideBlockEvent(@NotNull Entity entity, @NotNull Block block) { -+ super(entity); -+ this.block = block; -+ } -+ -+ /** -+ * Gets the block. -+ * -+ * @return the block -+ */ -+ @NotNull -+ public Block getBlock() { -+ return block; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch b/Unmapped-Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch deleted file mode 100644 index fa1b8ce93a..0000000000 --- a/Unmapped-Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 8 May 2021 15:02:00 -0700 -Subject: [PATCH] Attributes API for item defaults - - -diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 07b8b913434bb575df8670230d693b2d4cec2571..397591da25fbb0e4d3012431df70d661d9bc9188 100644 ---- a/src/main/java/org/bukkit/Material.java -+++ b/src/main/java/org/bukkit/Material.java -@@ -4013,6 +4013,19 @@ public enum Material implements Keyed { - public io.papermc.paper.inventory.ItemRarity getItemRarity() { - return Bukkit.getUnsafe().getItemRarity(this); - } -+ -+ /** -+ * Returns an immutable multimap of attributes for the slot. -+ * {@link #isItem()} must be true for this material. -+ * -+ * @param equipmentSlot the slot to get the attributes for -+ * @throws IllegalArgumentException if {@link #isItem()} is false -+ * @return an immutable multimap of attributes -+ */ -+ @NotNull -+ public com.google.common.collect.Multimap getItemAttributes(@NotNull EquipmentSlot equipmentSlot) { -+ return Bukkit.getUnsafe().getItemAttributes(this, equipmentSlot); -+ } - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index e504567cf755557be8511f2c93c171572b78e722..379acee1b5f2d06e6a96f3444783f4a29ca24095 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -165,6 +165,18 @@ public interface UnsafeValues { - */ - public boolean isValidRepairItemStack(@org.jetbrains.annotations.NotNull ItemStack itemToBeRepaired, @org.jetbrains.annotations.NotNull ItemStack repairMaterial); - -+ /** -+ * Returns an immutable multimap of attributes for the material and slot. -+ * {@link Material#isItem()} must be true for this material. -+ * -+ * @param material the material -+ * @param equipmentSlot the slot to get the attributes for -+ * @throws IllegalArgumentException if {@link Material#isItem()} is false -+ * @return an immutable multimap of attributes -+ */ -+ @org.jetbrains.annotations.NotNull -+ public com.google.common.collect.Multimap getItemAttributes(@org.jetbrains.annotations.NotNull Material material, @org.jetbrains.annotations.NotNull org.bukkit.inventory.EquipmentSlot equipmentSlot); -+ - /** - * Returns the server's protocol version. - * diff --git a/Unmapped-Spigot-API-Patches/0310-Add-cause-to-Weather-ThunderChangeEvents.patch b/Unmapped-Spigot-API-Patches/0310-Add-cause-to-Weather-ThunderChangeEvents.patch deleted file mode 100644 index 8e5d45d87b..0000000000 --- a/Unmapped-Spigot-API-Patches/0310-Add-cause-to-Weather-ThunderChangeEvents.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Dec 2020 18:25:31 -0800 -Subject: [PATCH] Add cause to Weather/ThunderChangeEvents - - -diff --git a/src/main/java/org/bukkit/event/weather/ThunderChangeEvent.java b/src/main/java/org/bukkit/event/weather/ThunderChangeEvent.java -index 6cdf83476b4e366bed79960e3706bea5ebe56788..032395c7114b6d757acf1918ce2b014870e85fcd 100644 ---- a/src/main/java/org/bukkit/event/weather/ThunderChangeEvent.java -+++ b/src/main/java/org/bukkit/event/weather/ThunderChangeEvent.java -@@ -12,10 +12,20 @@ public class ThunderChangeEvent extends WeatherEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean canceled; - private final boolean to; -+ // Paper start -+ private final Cause cause; - -+ public ThunderChangeEvent(@NotNull final World world, final boolean to, @NotNull final Cause cause) { -+ super(world); -+ this.to = to; -+ this.cause = cause; -+ } -+ -+ @Deprecated // Paper end - public ThunderChangeEvent(@NotNull final World world, final boolean to) { - super(world); - this.to = to; -+ this.cause = Cause.UNKNOWN; // Paper - } - - @Override -@@ -47,4 +57,23 @@ public class ThunderChangeEvent extends WeatherEvent implements Cancellable { - public static HandlerList getHandlerList() { - return handlers; - } -+ // Paper start -+ /** -+ * Gets the cause of the weather change. -+ * -+ * @return the weather change cause -+ */ -+ @NotNull -+ public Cause getCause() { -+ return this.cause; -+ } -+ -+ public enum Cause { -+ COMMAND, -+ NATURAL, -+ SLEEP, -+ PLUGIN, -+ UNKNOWN -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/event/weather/WeatherChangeEvent.java b/src/main/java/org/bukkit/event/weather/WeatherChangeEvent.java -index d562d87e7418641e52f4dae44f573eaa31add44a..dabd390b84354c14c269c03cbed2006014d004b2 100644 ---- a/src/main/java/org/bukkit/event/weather/WeatherChangeEvent.java -+++ b/src/main/java/org/bukkit/event/weather/WeatherChangeEvent.java -@@ -12,10 +12,20 @@ public class WeatherChangeEvent extends WeatherEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean canceled; - private final boolean to; -+ // Paper start -+ private final Cause cause; - -+ public WeatherChangeEvent(@NotNull final World world, final boolean to, @NotNull Cause cause) { -+ super(world); -+ this.to = to; -+ this.cause = cause; -+ } -+ -+ @Deprecated // Paper end - public WeatherChangeEvent(@NotNull final World world, final boolean to) { - super(world); - this.to = to; -+ this.cause = Cause.UNKNOWN; // Paper - } - - @Override -@@ -47,4 +57,23 @@ public class WeatherChangeEvent extends WeatherEvent implements Cancellable { - public static HandlerList getHandlerList() { - return handlers; - } -+ // Paper start -+ /** -+ * Gets the cause of the weather change. -+ * -+ * @return the weather change cause -+ */ -+ @NotNull -+ public Cause getCause() { -+ return cause; -+ } -+ -+ public enum Cause { -+ COMMAND, -+ NATURAL, -+ SLEEP, -+ PLUGIN, -+ UNKNOWN -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0311-More-Lidded-Block-API.patch b/Unmapped-Spigot-API-Patches/0311-More-Lidded-Block-API.patch deleted file mode 100644 index ca6b5ed744..0000000000 --- a/Unmapped-Spigot-API-Patches/0311-More-Lidded-Block-API.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: LemonCaramel -Date: Sun, 23 May 2021 17:49:31 +0900 -Subject: [PATCH] More Lidded Block API - - -diff --git a/src/main/java/org/bukkit/block/EnderChest.java b/src/main/java/org/bukkit/block/EnderChest.java -index 17843e338f2cbccfa9342b420c62d0e4d6eec31d..ebae4e660244df15bf93a78d41f8c0c5c7083b27 100644 ---- a/src/main/java/org/bukkit/block/EnderChest.java -+++ b/src/main/java/org/bukkit/block/EnderChest.java -@@ -3,4 +3,4 @@ package org.bukkit.block; - /** - * Represents a captured state of an ender chest. - */ --public interface EnderChest extends TileState { } -+public interface EnderChest extends TileState, Lidded { } // Paper - More Lidded Block API -diff --git a/src/main/java/org/bukkit/block/Lidded.java b/src/main/java/org/bukkit/block/Lidded.java -index 9da2566e02e63be1a0188deaa27b841fa61688ea..30c7df0021df44a411e50636d906d4a1d30fd927 100644 ---- a/src/main/java/org/bukkit/block/Lidded.java -+++ b/src/main/java/org/bukkit/block/Lidded.java -@@ -13,4 +13,13 @@ public interface Lidded { - * viewing this block. - */ - void close(); -+ -+ // Paper start - More Lidded Block API -+ /** -+ * Checks if the block's animation state. -+ * -+ * @return true if the block's animation state is set to open. -+ */ -+ boolean isOpen(); -+ // Paper end - More Lidded Block API - } diff --git a/Unmapped-Spigot-API-Patches/0312-Add-PlayerKickEvent-causes.patch b/Unmapped-Spigot-API-Patches/0312-Add-PlayerKickEvent-causes.patch deleted file mode 100644 index b3cfb136d3..0000000000 --- a/Unmapped-Spigot-API-Patches/0312-Add-PlayerKickEvent-causes.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 20:30:34 -0700 -Subject: [PATCH] Add PlayerKickEvent causes - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 34b51466ffb281b05f531b3f7deda245ae7fd96a..a4b236d75e77176a163094edd31f81725bbf4eca 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -237,6 +237,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param message kick message - */ - void kick(final @Nullable net.kyori.adventure.text.Component message); -+ -+ /** -+ * Kicks player with custom kick message and cause. -+ * -+ * @param message kick message -+ * @param cause kick cause -+ */ -+ void kick(final @Nullable Component message, @NotNull org.bukkit.event.player.PlayerKickEvent.Cause cause); - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -index 5c0efe74237dbe6803ce023fde99682ff70d1a92..02914c0743852e9e4fd2c085fd4b735e74d8875b 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -@@ -12,6 +12,7 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private net.kyori.adventure.text.Component leaveMessage; // Paper - private net.kyori.adventure.text.Component kickReason; // Paper -+ private final Cause cause; // Paper - private Boolean cancel; - - @Deprecated // Paper -@@ -19,14 +20,25 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { - super(playerKicked); - this.kickReason = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickReason); // Paper - this.leaveMessage = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(leaveMessage); // Paper -+ this.cause = Cause.UNKNOWN; // Paper - this.cancel = false; - } - // Paper start -+ @Deprecated - public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final net.kyori.adventure.text.Component kickReason, @NotNull final net.kyori.adventure.text.Component leaveMessage) { - super(playerKicked); - this.kickReason = kickReason; - this.leaveMessage = leaveMessage; - this.cancel = false; -+ this.cause = Cause.UNKNOWN; -+ } -+ -+ public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final net.kyori.adventure.text.Component kickReason, @NotNull final net.kyori.adventure.text.Component leaveMessage, @NotNull final Cause cause) { -+ super(playerKicked); -+ this.kickReason = kickReason; -+ this.leaveMessage = leaveMessage; -+ this.cancel = false; -+ this.cause = cause; - } - - /** -@@ -132,4 +144,63 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { - public static HandlerList getHandlerList() { - return handlers; - } -+ // Paper start -+ /** -+ * Gets the cause of this kick -+ * -+ * @return -+ */ -+ @NotNull -+ public org.bukkit.event.player.PlayerKickEvent.Cause getCause() { -+ return cause; -+ } -+ -+ public enum Cause { -+ -+ PLUGIN, -+ -+ WHITELIST, -+ -+ BANNED, -+ -+ IP_BANNED, -+ -+ KICK_COMMAND, -+ -+ FLYING_PLAYER, -+ -+ FLYING_VEHICLE, -+ -+ TIMEOUT, -+ -+ IDLING, -+ -+ INVALID_VEHICLE_MOVEMENT, -+ -+ INVALID_PLAYER_MOVEMENT, -+ -+ INVALID_ENTITY_ATTACKED, -+ -+ INVALID_PAYLOAD, -+ -+ SPAM, -+ -+ ILLEGAL_ACTION, -+ -+ ILLEGAL_CHARACTERS, -+ -+ SELF_INTERACTION, -+ -+ DUPLICATE_LOGIN, -+ -+ /** -+ * Spigot's restart command -+ */ -+ RESTART_COMMAND, -+ /** -+ * Fallback cause -+ */ -+ UNKNOWN, -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-API-Patches/0313-Add-PufferFishStateChangeEvent.patch b/Unmapped-Spigot-API-Patches/0313-Add-PufferFishStateChangeEvent.patch deleted file mode 100644 index c3014534d3..0000000000 --- a/Unmapped-Spigot-API-Patches/0313-Add-PufferFishStateChangeEvent.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Mon, 10 May 2021 16:58:38 +0100 -Subject: [PATCH] Add PufferFishStateChangeEvent - - -diff --git a/src/main/java/io/papermc/paper/event/entity/PufferFishStateChangeEvent.java b/src/main/java/io/papermc/paper/event/entity/PufferFishStateChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3585457b21aca2a2f1779868a0fa91f8011ad3c9 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/entity/PufferFishStateChangeEvent.java -@@ -0,0 +1,80 @@ -+package io.papermc.paper.event.entity; -+ -+import org.bukkit.entity.PufferFish; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called just before a {@link PufferFish} inflates or deflates. -+ */ -+public class PufferFishStateChangeEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ private int newPuffState; -+ -+ public PufferFishStateChangeEvent(@NotNull PufferFish entity, int newPuffState) { -+ super(entity); -+ this.newPuffState = newPuffState; -+ } -+ -+ @NotNull -+ @Override -+ public PufferFish getEntity() { -+ return (PufferFish) entity; -+ } -+ -+ /** -+ * Get the new puff state of the {@link PufferFish}. -+ *

    -+ * This is what the {@link PufferFish}'s new puff state will be after this event if it isn't cancelled.
    -+ * Refer to {@link PufferFish#getPuffState()} to get the current puff state. -+ * @return The new puff state, 0 being not inflated, 1 being slightly inflated and 2 being fully inflated -+ */ -+ public int getNewPuffState() { -+ return this.newPuffState; -+ } -+ -+ /** -+ * Get if the {@link PufferFish} is going to inflate. -+ * @return If its going to inflate -+ */ -+ public boolean isInflating() { -+ return getNewPuffState() > getEntity().getPuffState(); -+ } -+ -+ /** -+ * Get if the {@link PufferFish} is going to deflate. -+ * @return If its going to deflate -+ */ -+ public boolean isDeflating() { -+ return getNewPuffState() < getEntity().getPuffState(); -+ } -+ -+ /** -+ * Set whether or not to cancel the {@link PufferFish} (in/de)flating. -+ * -+ * @param cancel true if you wish to cancel the (in/de)flation -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0314-Add-BellRevealRaiderEvent.patch b/Unmapped-Spigot-API-Patches/0314-Add-BellRevealRaiderEvent.patch deleted file mode 100644 index 8b0ee3e5b4..0000000000 --- a/Unmapped-Spigot-API-Patches/0314-Add-BellRevealRaiderEvent.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Wed, 26 May 2021 17:08:57 -0400 -Subject: [PATCH] Add BellRevealRaiderEvent - - -diff --git a/src/main/java/io/papermc/paper/event/block/BellRevealRaiderEvent.java b/src/main/java/io/papermc/paper/event/block/BellRevealRaiderEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..03dae5be7dba8ab550d03f365c05af4ba73e4224 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/BellRevealRaiderEvent.java -@@ -0,0 +1,58 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.Raider; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a {@link org.bukkit.entity.Raider} is revealed by a bell. -+ */ -+public class BellRevealRaiderEvent extends BlockEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ private boolean cancelled = false; -+ private final Raider raider; -+ -+ public BellRevealRaiderEvent(@NotNull Block theBlock, @NotNull Entity raider) { -+ super(theBlock); -+ this.raider = (Raider) raider; -+ } -+ -+ /** -+ * Gets the raider that the bell revealed. -+ * -+ * @return The raider -+ */ -+ @NotNull -+ public Raider getEntity() { -+ return raider; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * {@inheritDoc} -+ *

    -+ * This does not cancel the particle effects shown on the bell, only the entity. -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @Override -+ public @NotNull HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ public static @NotNull HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0315-Add-ElderGuardianAppearanceEvent.patch b/Unmapped-Spigot-API-Patches/0315-Add-ElderGuardianAppearanceEvent.patch deleted file mode 100644 index 8d925d10ac..0000000000 --- a/Unmapped-Spigot-API-Patches/0315-Add-ElderGuardianAppearanceEvent.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Fri, 19 Mar 2021 23:39:21 -0400 -Subject: [PATCH] Add ElderGuardianAppearanceEvent - - -diff --git a/src/main/java/io/papermc/paper/event/entity/ElderGuardianAppearanceEvent.java b/src/main/java/io/papermc/paper/event/entity/ElderGuardianAppearanceEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4cd551c8311ff8f7321ed2dc6a4efc87162dadfe ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/entity/ElderGuardianAppearanceEvent.java -@@ -0,0 +1,69 @@ -+package io.papermc.paper.event.entity; -+ -+import org.bukkit.entity.ElderGuardian; -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Collections; -+import java.util.List; -+ -+/** -+ * Is called when an {@link org.bukkit.entity.ElderGuardian} appears in front of a {@link org.bukkit.entity.Player}. -+ */ -+public class ElderGuardianAppearanceEvent extends EntityEvent implements Cancellable { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ private boolean cancelled; -+ private final Player affectedPlayer; -+ -+ public ElderGuardianAppearanceEvent(@NotNull Entity what, @NotNull Player affectedPlayer) { -+ super(what); -+ this.affectedPlayer = affectedPlayer; -+ } -+ -+ /** -+ * Get the player affected by the guardian appearance. -+ * -+ * @return Player affected by the appearance -+ */ -+ @NotNull -+ public Player getAffectedPlayer() { -+ return affectedPlayer; -+ } -+ -+ /** -+ * The elder guardian playing the effect. -+ * -+ * @return The elder guardian -+ */ -+ @NotNull -+ public ElderGuardian getEntity() { -+ return (ElderGuardian) entity; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Unmapped-Spigot-API-Patches/0316-Add-more-line-of-sight-methods.patch b/Unmapped-Spigot-API-Patches/0316-Add-more-line-of-sight-methods.patch deleted file mode 100644 index be49c1cc25..0000000000 --- a/Unmapped-Spigot-API-Patches/0316-Add-more-line-of-sight-methods.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TwoLeggedCat <80929284+TwoLeggedCat@users.noreply.github.com> -Date: Sat, 29 May 2021 14:33:18 -0500 -Subject: [PATCH] Add more line of sight methods - - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index a1496fe00a2d5ba6c1af054d4327f868b2cd7344..f66ec2dfdc64871f8b752bf44086954300804f08 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -76,6 +76,14 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - */ - @NotNull - io.papermc.paper.world.MoonPhase getMoonPhase(); -+ -+ /** -+ * Tell whether a line of sight exists between the given locations -+ * @param from Location to start at -+ * @param to target Location -+ * @return whether a line of sight exists between {@code from} and {@code to} -+ */ -+ public boolean lineOfSightExists(@NotNull Location from, @NotNull Location to); - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index b6de41e3e718fa5d1b82c6f68b153e60a81265e7..ccb81ceee74fff50ec3ed88ae0a41f790c40ae87 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -483,6 +483,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - */ - public boolean hasLineOfSight(@NotNull Entity other); - -+ // Paper start -+ /** -+ * Checks whether the living entity has block line of sight to the given block. -+ *

    -+ * This uses the same algorithm that hostile mobs use to find the closest -+ * player. -+ * -+ * @param location the location to determine line of sight to -+ * @return true if there is a line of sight, false if not -+ */ -+ public boolean hasLineOfSight(@NotNull Location location); -+ // Paper end -+ - /** - * Returns if the living entity despawns when away from players or not. - *

    diff --git a/Unmapped-Spigot-Server-Patches/0001-POM-Changes.patch b/Unmapped-Spigot-Server-Patches/0001-POM-Changes.patch deleted file mode 100644 index 8d0da0d549..0000000000 --- a/Unmapped-Spigot-Server-Patches/0001-POM-Changes.patch +++ /dev/null @@ -1,291 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 29 Feb 2016 20:40:33 -0600 -Subject: [PATCH] POM Changes - - -diff --git a/pom.xml b/pom.xml -index 3fc047371e8f8a626e69697fad549d689c5dce89..a5d87d22cb1588d15e08da3b37e51c5e261c7799 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -1,15 +1,14 @@ - - 4.0.0 -- org.spigotmc -- spigot -+ paper - jar - 1.16.5-R0.1-SNAPSHOT -- Spigot -- https://www.spigotmc.org/ -+ Paper -+ https://papermc.io - - -- true -+ - UTF-8 - unknown - git -@@ -20,21 +19,39 @@ - - - -- org.spigotmc -- spigot-parent -+ com.destroystokyo.paper -+ paper-parent - dev-SNAPSHOT - ../pom.xml - - -+ -+ -+ -+ org.apache.logging.log4j -+ log4j-bom -+ 2.11.2 -+ pom -+ import -+ -+ -+ -+ - - -- org.spigotmc -- spigot-api -+ com.destroystokyo.paper -+ paper-api -+ ${project.version} -+ compile -+ -+ -+ com.destroystokyo.paper -+ paper-mojangapi - ${project.version} - compile - - -- org.spigotmc -+ io.papermc - minecraft-server - ${minecraft.version}-SNAPSHOT - compile -@@ -45,18 +62,15 @@ - 2.12.1 - compile - -+ -+ org.apache.logging.log4j -+ log4j-api -+ compile -+ - - org.apache.logging.log4j - log4j-iostreams -- 2.8.1 - compile -- -- -- -- org.apache.logging.log4j -- log4j-api -- -- - - - org.ow2.asm -@@ -64,12 +78,23 @@ - 9.1 - compile - -+ -+ -+ co.aikar -+ cleaner -+ 1.0-SNAPSHOT -+ -+ -+ io.netty -+ netty-all -+ 4.1.50.Final -+ - - - com.googlecode.json-simple - json-simple - 1.1.1 -- runtime -+ compile - - - org.xerial -@@ -80,7 +105,7 @@ - - mysql - mysql-connector-java -- 5.1.49 -+ 8.0.23 - runtime - - -@@ -105,7 +130,7 @@ - - org.apache.logging.log4j - log4j-slf4j-impl -- 2.8.1 -+ - runtime - - -@@ -132,34 +157,22 @@ - - - -+ paper-${minecraft.version} -+ clean install - - -- net.md-5 -- scriptus -- 0.4.1 -+ com.lukegb.mojo -+ gitdescribe-maven-plugin -+ 1.3 -+ -+ git-Paper- -+ .. -+ - - -- ex-spigot -- -- ${bt.name}-Spigot-%s -- ../ -- spigot.desc -- -- initialize -- -- describe -- -- -- -- ex-craftbukkit -- -- -%s -- ../../CraftBukkit -- craftbukkit.desc -- -- initialize -+ compile - -- describe -+ gitdescribe - - - -@@ -169,6 +182,7 @@ - maven-jar-plugin - 3.2.0 - -+ true - - - false -@@ -176,11 +190,13 @@ - - org.bukkit.craftbukkit.Main - CraftBukkit -- ${spigot.desc}${craftbukkit.desc} -- ${project.build.outputTimestamp} -+ -+ ${describe} -+ ${maven.build.timestamp} - Bukkit - ${api.version} - Bukkit Team -+ true - - - -@@ -216,14 +232,24 @@ - shade - - -+ ${project.build.directory}/dependency-reduced-pom.xml - ${shadeSourcesJar} - - -- org.spigotmc:minecraft-server -+ io.papermc:minecraft-server - - com/google/common/** - com/google/gson/** - com/google/thirdparty/** -+ -+ io/netty/** -+ META-INF/native/libnetty* -+ com/mojang/brigadier/** -+ META-INF/MANIFEST.MF -+ com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.class -+ com/mojang/datafixers/util/Either* -+ org/apache/logging/log4j/** -+ META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat - - - -@@ -245,10 +271,11 @@ - jline - org.bukkit.craftbukkit.libs.jline - -- -- it.unimi -- org.bukkit.craftbukkit.libs.it.unimi -- -+ -+ -+ -+ -+ - - org.apache.commons.codec - org.bukkit.craftbukkit.libs.org.apache.commons.codec -@@ -316,10 +343,6 @@ - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 -- -- -- eclipse -- - - - org.codehaus.plexus -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 4452427d0a8298d119ca29ef397b7a94f19eec28..46a16e31775b28c44f95a8ac5545ebcb656c74b6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -186,7 +186,7 @@ public class Main { - } - - if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { -- Date buildDate = new Date(Integer.parseInt(Main.class.getPackage().getImplementationVendor()) * 1000L); -+ Date buildDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(Main.class.getPackage().getImplementationVendor()); // Paper - - Calendar deadline = Calendar.getInstance(); - deadline.add(Calendar.DAY_OF_YEAR, -28); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 93046379d0cefd5d3236fc59e698809acdc18f80..674096cab190d62622f9947853b056f57d43a2a5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -@@ -11,7 +11,7 @@ public final class Versioning { - public static String getBukkitVersion() { - String result = "Unknown-Version"; - -- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties"); -+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.destroystokyo.paper/paper-api/pom.properties"); - Properties properties = new Properties(); - - if (stream != null) { diff --git a/Unmapped-Spigot-Server-Patches/0002-Paper-config-files.patch b/Unmapped-Spigot-Server-Patches/0002-Paper-config-files.patch deleted file mode 100644 index 59424f2288..0000000000 --- a/Unmapped-Spigot-Server-Patches/0002-Paper-config-files.patch +++ /dev/null @@ -1,820 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 29 Feb 2016 21:02:09 -0600 -Subject: [PATCH] Paper config files - -Loads each yml file for early init too so it can be used for early options - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -new file mode 100644 -index 0000000000000000000000000000000000000000..68cd4134cb6a00c1768100462f8e9e94f3fa6279 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +1,286 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Functions; -+import com.google.common.base.Joiner; -+import com.google.common.collect.ImmutableSet; -+import com.google.common.collect.Iterables; -+import com.google.common.collect.Lists; -+import com.google.common.collect.Maps; -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import org.apache.commons.lang3.tuple.MutablePair; -+import org.apache.commons.lang3.tuple.Pair; -+import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; -+import org.bukkit.Location; -+import org.bukkit.World; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+import org.bukkit.craftbukkit.CraftServer; -+import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.entity.Player; -+ -+import java.io.File; -+import java.time.LocalDateTime; -+import java.time.format.DateTimeFormatter; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collection; -+import java.util.Collections; -+import java.util.Iterator; -+import java.util.List; -+import java.util.Locale; -+import java.util.Map; -+import java.util.Set; -+import java.util.stream.Collectors; -+ -+public class PaperCommand extends Command { -+ private static final String BASE_PERM = "bukkit.command.paper."; -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); -+ -+ public PaperCommand(String name) { -+ super(name); -+ this.description = "Paper related commands"; -+ this.usageMessage = "/paper [" + Joiner.on(" | ").join(SUBCOMMANDS) + "]"; -+ this.setPermission("bukkit.command.paper;" + Joiner.on(';').join(SUBCOMMANDS.stream().map(s -> BASE_PERM + s).collect(Collectors.toSet()))); -+ } -+ -+ private static boolean testPermission(CommandSender commandSender, String permission) { -+ if (commandSender.hasPermission(BASE_PERM + permission) || commandSender.hasPermission("bukkit.command.paper")) return true; -+ commandSender.sendMessage(Bukkit.getPermissionMessage()); -+ return false; -+ } -+ -+ @Override -+ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { -+ if (args.length <= 1) -+ return getListMatchingLast(sender, args, SUBCOMMANDS); -+ -+ switch (args[0].toLowerCase(Locale.ENGLISH)) -+ { -+ case "entity": -+ if (args.length == 2) -+ return getListMatchingLast(sender, args, "help", "list"); -+ if (args.length == 3) -+ return getListMatchingLast(sender, args, EntityTypes.getEntityNameList().stream().map(MinecraftKey::toString).sorted().toArray(String[]::new)); -+ break; -+ } -+ return Collections.emptyList(); -+ } -+ -+ // Code from Mojang - copyright them -+ public static List getListMatchingLast(CommandSender sender, String[] args, String... matches) { -+ return getListMatchingLast(sender, args, (Collection) Arrays.asList(matches)); -+ } -+ -+ public static boolean matches(String s, String s1) { -+ return s1.regionMatches(true, 0, s, 0, s.length()); -+ } -+ -+ public static List getListMatchingLast(CommandSender sender, String[] strings, Collection collection) { -+ String last = strings[strings.length - 1]; -+ ArrayList results = Lists.newArrayList(); -+ -+ if (!collection.isEmpty()) { -+ Iterator iterator = Iterables.transform(collection, Functions.toStringFunction()).iterator(); -+ -+ while (iterator.hasNext()) { -+ String s1 = (String) iterator.next(); -+ -+ if (matches(last, s1) && (sender.hasPermission(BASE_PERM + s1) || sender.hasPermission("bukkit.command.paper"))) { -+ results.add(s1); -+ } -+ } -+ -+ if (results.isEmpty()) { -+ iterator = collection.iterator(); -+ -+ while (iterator.hasNext()) { -+ Object object = iterator.next(); -+ -+ if (object instanceof MinecraftKey && matches(last, ((MinecraftKey) object).getKey())) { -+ results.add(String.valueOf(object)); -+ } -+ } -+ } -+ } -+ -+ return results; -+ } -+ // end copy stuff -+ -+ @Override -+ public boolean execute(CommandSender sender, String commandLabel, String[] args) { -+ if (!testPermission(sender)) return true; -+ -+ if (args.length == 0) { -+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -+ return false; -+ } -+ if (SUBCOMMANDS.contains(args[0].toLowerCase(Locale.ENGLISH))) { -+ if (!testPermission(sender, args[0].toLowerCase(Locale.ENGLISH))) return true; -+ } -+ switch (args[0].toLowerCase(Locale.ENGLISH)) { -+ case "heap": -+ dumpHeap(sender); -+ break; -+ case "entity": -+ listEntities(sender, args); -+ break; -+ case "reload": -+ doReload(sender); -+ break; -+ case "ver": -+ if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) -+ case "version": -+ Command ver = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version"); -+ if (ver != null) { -+ ver.execute(sender, commandLabel, new String[0]); -+ break; -+ } -+ // else - fall through to default -+ default: -+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -+ return false; -+ } -+ -+ return true; -+ } -+ -+ /* -+ * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 -+ */ -+ private void listEntities(CommandSender sender, String[] args) { -+ if (args.length < 2 || args[1].toLowerCase(Locale.ENGLISH).equals("help")) { -+ sender.sendMessage(ChatColor.RED + "Use /paper entity [list] help for more information on a specific command."); -+ return; -+ } -+ -+ switch (args[1].toLowerCase(Locale.ENGLISH)) { -+ case "list": -+ String filter = "*"; -+ if (args.length > 2) { -+ if (args[2].toLowerCase(Locale.ENGLISH).equals("help")) { -+ sender.sendMessage(ChatColor.RED + "Use /paper entity list [filter] [worldName] to get entity info that matches the optional filter."); -+ return; -+ } -+ filter = args[2]; -+ } -+ final String cleanfilter = filter.replace("?", ".?").replace("*", ".*?"); -+ Set names = EntityTypes.getEntityNameList().stream() -+ .filter(n -> n.toString().matches(cleanfilter)) -+ .collect(Collectors.toSet()); -+ -+ if (names.isEmpty()) { -+ sender.sendMessage(ChatColor.RED + "Invalid filter, does not match any entities. Use /paper entity list for a proper list"); -+ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); -+ return; -+ } -+ -+ String worldName; -+ if (args.length > 3) { -+ worldName = args[3]; -+ } else if (sender instanceof Player) { -+ worldName = ((Player) sender).getWorld().getName(); -+ } else { -+ sender.sendMessage(ChatColor.RED + "Please specify the name of a world"); -+ sender.sendMessage(ChatColor.RED + "To do so without a filter, specify '*' as the filter"); -+ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); -+ return; -+ } -+ -+ Map>> list = Maps.newHashMap(); -+ World bukkitWorld = Bukkit.getWorld(worldName); -+ if (bukkitWorld == null) { -+ sender.sendMessage(ChatColor.RED + "Could not load world for " + worldName + ". Please select a valid world."); -+ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); -+ return; -+ } -+ WorldServer world = ((CraftWorld) Bukkit.getWorld(worldName)).getHandle(); -+ -+ Map nonEntityTicking = Maps.newHashMap(); -+ ChunkProviderServer chunkProviderServer = world.getChunkProvider(); -+ -+ Collection entities = world.entitiesById.values(); -+ entities.forEach(e -> { -+ MinecraftKey key = new MinecraftKey(""); // TODO: update in next patch -+ -+ MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); -+ ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); -+ info.left++; -+ info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1); -+ if (!chunkProviderServer.isInEntityTickingChunk(e)) { -+ nonEntityTicking.merge(key, Integer.valueOf(1), Integer::sum); -+ } -+ }); -+ -+ if (names.size() == 1) { -+ MinecraftKey name = names.iterator().next(); -+ Pair> info = list.get(name); -+ int nonTicking = nonEntityTicking.getOrDefault(name, Integer.valueOf(0)).intValue(); -+ if (info == null) { -+ sender.sendMessage(ChatColor.RED + "No entities found."); -+ return; -+ } -+ sender.sendMessage("Entity: " + name + " Total Ticking: " + (info.getLeft() - nonTicking) + ", Total Non-Ticking: " + nonTicking); -+ info.getRight().entrySet().stream() -+ .sorted((a, b) -> !a.getValue().equals(b.getValue()) ? b.getValue() - a.getValue() : a.getKey().toString().compareTo(b.getKey().toString())) -+ .limit(10).forEach(e -> sender.sendMessage(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z + (chunkProviderServer.isEntityTickingChunk(e.getKey()) ? " (Ticking)" : " (Non-Ticking)"))); -+ } else { -+ List> info = list.entrySet().stream() -+ .filter(e -> names.contains(e.getKey())) -+ .map(e -> Pair.of(e.getKey(), e.getValue().left)) -+ .sorted((a, b) -> !a.getRight().equals(b.getRight()) ? b.getRight() - a.getRight() : a.getKey().toString().compareTo(b.getKey().toString())) -+ .collect(Collectors.toList()); -+ -+ if (info == null || info.size() == 0) { -+ sender.sendMessage(ChatColor.RED + "No entities found."); -+ return; -+ } -+ -+ int count = info.stream().mapToInt(Pair::getRight).sum(); -+ int nonTickingCount = nonEntityTicking.values().stream().mapToInt(Integer::intValue).sum(); -+ sender.sendMessage("Total Ticking: " + (count - nonTickingCount) + ", Total Non-Ticking: " + nonTickingCount); -+ info.forEach(e -> { -+ int nonTicking = nonEntityTicking.getOrDefault(e.getKey(), Integer.valueOf(0)).intValue(); -+ sender.sendMessage(" " + (e.getValue() - nonTicking) + " (" + nonTicking + ") " + ": " + e.getKey()); -+ }); -+ sender.sendMessage("* First number is ticking entities, second number is non-ticking entities"); -+ } -+ break; -+ } -+ } -+ -+ private void dumpHeap(CommandSender sender) { -+ java.nio.file.Path dir = java.nio.file.Paths.get("./dumps"); -+ String name = "heap-dump-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()); -+ -+ Command.broadcastCommandMessage(sender, ChatColor.YELLOW + "Writing JVM heap data..."); -+ -+ java.nio.file.Path file = CraftServer.dumpHeap(dir, name); -+ if (file != null) { -+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Heap dump saved to " + file); -+ } else { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Failed to write heap dump, see sever log for details"); -+ } -+ } -+ -+ private void doReload(CommandSender sender) { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues."); -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); -+ -+ MinecraftServer console = MinecraftServer.getServer(); -+ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); -+ for (WorldServer world : console.getWorlds()) { -+ world.paperConfig.init(); -+ } -+ console.server.reloadCount++; -+ -+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete."); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2c0514892d3993bef57ecf677cf8bb0fbe0216e4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +1,185 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Throwables; -+ -+import java.io.File; -+import java.io.IOException; -+import java.lang.reflect.InvocationTargetException; -+import java.lang.reflect.Method; -+import java.lang.reflect.Modifier; -+import java.util.HashMap; -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.TimeUnit; -+import java.util.logging.Level; -+import java.util.regex.Pattern; -+ -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+import org.bukkit.command.Command; -+import org.bukkit.configuration.ConfigurationSection; -+import org.bukkit.configuration.InvalidConfigurationException; -+import org.bukkit.configuration.file.YamlConfiguration; -+ -+public class PaperConfig { -+ -+ private static File CONFIG_FILE; -+ private static final String HEADER = "This is the main configuration file for Paper.\n" -+ + "As you can see, there's tons to configure. Some options may impact gameplay, so use\n" -+ + "with caution, and make sure you know what each option does before configuring.\n" -+ + "\n" -+ + "If you need help with the configuration or have any questions related to Paper,\n" -+ + "join us in our Discord or IRC channel.\n" -+ + "\n" -+ + "Discord: https://discord.gg/papermc\n" -+ + "IRC: #paper @ irc.esper.net ( https://webchat.esper.net/?channels=paper ) \n" -+ + "Website: https://papermc.io/ \n" -+ + "Docs: https://paper.readthedocs.org/ \n"; -+ /*========================================================================*/ -+ public static YamlConfiguration config; -+ static int version; -+ static Map commands; -+ private static boolean verbose; -+ private static boolean fatalError; -+ /*========================================================================*/ -+ -+ public static void init(File configFile) { -+ CONFIG_FILE = configFile; -+ config = new YamlConfiguration(); -+ try { -+ config.load(CONFIG_FILE); -+ } catch (IOException ex) { -+ } catch (InvalidConfigurationException ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Could not load paper.yml, please correct your syntax errors", ex); -+ throw Throwables.propagate(ex); -+ } -+ config.options().header(HEADER); -+ config.options().copyDefaults(true); -+ verbose = getBoolean("verbose", false); -+ -+ commands = new HashMap(); -+ commands.put("paper", new PaperCommand("paper")); -+ -+ version = getInt("config-version", 20); -+ set("config-version", 20); -+ readConfig(PaperConfig.class, null); -+ } -+ -+ protected static void logError(String s) { -+ Bukkit.getLogger().severe(s); -+ } -+ -+ protected static void fatal(String s) { -+ fatalError = true; -+ throw new RuntimeException("Fatal paper.yml config error: " + s); -+ } -+ -+ protected static void log(String s) { -+ if (verbose) { -+ Bukkit.getLogger().info(s); -+ } -+ } -+ -+ public static void registerCommands() { -+ for (Map.Entry entry : commands.entrySet()) { -+ MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); -+ } -+ } -+ -+ static void readConfig(Class clazz, Object instance) { -+ for (Method method : clazz.getDeclaredMethods()) { -+ if (Modifier.isPrivate(method.getModifiers())) { -+ if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) { -+ try { -+ method.setAccessible(true); -+ method.invoke(instance); -+ } catch (InvocationTargetException ex) { -+ throw Throwables.propagate(ex.getCause()); -+ } catch (Exception ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex); -+ } -+ } -+ } -+ } -+ -+ try { -+ config.save(CONFIG_FILE); -+ } catch (IOException ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex); -+ } -+ } -+ -+ private static final Pattern SPACE = Pattern.compile(" "); -+ private static final Pattern NOT_NUMERIC = Pattern.compile("[^-\\d.]"); -+ public static int getSeconds(String str) { -+ str = SPACE.matcher(str).replaceAll(""); -+ final char unit = str.charAt(str.length() - 1); -+ str = NOT_NUMERIC.matcher(str).replaceAll(""); -+ double num; -+ try { -+ num = Double.parseDouble(str); -+ } catch (Exception e) { -+ num = 0D; -+ } -+ switch (unit) { -+ case 'd': num *= (double) 60*60*24; break; -+ case 'h': num *= (double) 60*60; break; -+ case 'm': num *= (double) 60; break; -+ default: case 's': break; -+ } -+ return (int) num; -+ } -+ -+ protected static String timeSummary(int seconds) { -+ String time = ""; -+ -+ if (seconds > 60 * 60 * 24) { -+ time += TimeUnit.SECONDS.toDays(seconds) + "d"; -+ seconds %= 60 * 60 * 24; -+ } -+ -+ if (seconds > 60 * 60) { -+ time += TimeUnit.SECONDS.toHours(seconds) + "h"; -+ seconds %= 60 * 60; -+ } -+ -+ if (seconds > 0) { -+ time += TimeUnit.SECONDS.toMinutes(seconds) + "m"; -+ } -+ return time; -+ } -+ -+ private static void set(String path, Object val) { -+ config.set(path, val); -+ } -+ -+ private static boolean getBoolean(String path, boolean def) { -+ config.addDefault(path, def); -+ return config.getBoolean(path, config.getBoolean(path)); -+ } -+ -+ private static double getDouble(String path, double def) { -+ config.addDefault(path, def); -+ return config.getDouble(path, config.getDouble(path)); -+ } -+ -+ private static float getFloat(String path, float def) { -+ // TODO: Figure out why getFloat() always returns the default value. -+ return (float) getDouble(path, (double) def); -+ } -+ -+ private static int getInt(String path, int def) { -+ config.addDefault(path, def); -+ return config.getInt(path, config.getInt(path)); -+ } -+ -+ private static List getList(String path, T def) { -+ config.addDefault(path, def); -+ return (List) config.getList(path, config.getList(path)); -+ } -+ -+ private static String getString(String path, String def) { -+ config.addDefault(path, def); -+ return config.getString(path, config.getString(path)); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b31109d2dadd29e8852468c19265066b773d2be0 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +1,68 @@ -+package com.destroystokyo.paper; -+ -+import java.util.List; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.configuration.file.YamlConfiguration; -+import org.spigotmc.SpigotWorldConfig; -+ -+import static com.destroystokyo.paper.PaperConfig.log; -+import static com.destroystokyo.paper.PaperConfig.logError; -+ -+public class PaperWorldConfig { -+ -+ private final String worldName; -+ private final SpigotWorldConfig spigotConfig; -+ private YamlConfiguration config; -+ private boolean verbose; -+ -+ public PaperWorldConfig(String worldName, SpigotWorldConfig spigotConfig) { -+ this.worldName = worldName; -+ this.spigotConfig = spigotConfig; -+ this.config = PaperConfig.config; -+ init(); -+ } -+ -+ public void init() { -+ this.config = PaperConfig.config; // grab updated reference -+ log("-------- World Settings For [" + worldName + "] --------"); -+ PaperConfig.readConfig(PaperWorldConfig.class, this); -+ } -+ -+ private void set(String path, Object val) { -+ config.set("world-settings.default." + path, val); -+ if (config.get("world-settings." + worldName + "." + path) != null) { -+ config.set("world-settings." + worldName + "." + path, val); -+ } -+ } -+ -+ private boolean getBoolean(String path, boolean def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path)); -+ } -+ -+ private double getDouble(String path, double def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getDouble("world-settings." + worldName + "." + path, config.getDouble("world-settings.default." + path)); -+ } -+ -+ private int getInt(String path, int def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getInt("world-settings." + worldName + "." + path, config.getInt("world-settings.default." + path)); -+ } -+ -+ private float getFloat(String path, float def) { -+ // TODO: Figure out why getFloat() always returns the default value. -+ return (float) getDouble(path, (double) def); -+ } -+ -+ private List getList(String path, List def) { -+ config.addDefault("world-settings.default." + path, def); -+ return (List) config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)); -+ } -+ -+ private String getString(String path, String def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index b746e30e6fc5ea0c17465b510d737316f1ab7004..89db31061fcc3420bc8e668533a4051cdbd12253 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -103,6 +103,12 @@ public class Main { - DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(iregistrycustom_dimension, optionset); // CraftBukkit - CLI argument support - - dedicatedserversettings.save(); -+ // Paper start - load config files for access below if needed -+ org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = loadConfigFile((File) optionset.valueOf("bukkit-settings")); -+ org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = loadConfigFile((File) optionset.valueOf("spigot-settings")); -+ org.bukkit.configuration.file.YamlConfiguration paperConfiguration = loadConfigFile((File) optionset.valueOf("paper-settings")); -+ // Paper end -+ - java.nio.file.Path java_nio_file_path1 = Paths.get("eula.txt"); - EULA eula = new EULA(java_nio_file_path1); - -@@ -244,6 +250,20 @@ public class Main { - - } - -+ // Paper start - load config files -+ private static org.bukkit.configuration.file.YamlConfiguration loadConfigFile(File configFile) throws Exception { -+ org.bukkit.configuration.file.YamlConfiguration config = new org.bukkit.configuration.file.YamlConfiguration(); -+ if (configFile.exists()) { -+ try { -+ config.load(configFile); -+ } catch (Exception ex) { -+ throw new Exception("Failed to load configuration file: " + configFile.getName(), ex); -+ } -+ } -+ return config; -+ } -+ // Paper end -+ - public static void convertWorld(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, boolean flag, BooleanSupplier booleansupplier, ImmutableSet> immutableset) { // CraftBukkit - Main.LOGGER.info("Forcing world upgrade! {}", convertable_conversionsession.getLevelName()); // CraftBukkit - WorldUpgrader worldupgrader = new WorldUpgrader(convertable_conversionsession, datafixer, immutableset, flag); -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index d5628a0197125506f7aaeb89bab7bd8a811b3ad5..8e2e415a022ccd486465f19d9bbf1f287b21fb95 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -187,6 +187,15 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); - org.spigotmc.SpigotConfig.registerCommands(); - // Spigot end -+ // Paper start -+ try { -+ com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); -+ } catch (Exception e) { -+ DedicatedServer.LOGGER.error("Unable to load server configuration", e); -+ return false; -+ } -+ com.destroystokyo.paper.PaperConfig.registerCommands(); -+ // Paper end - - this.setPVP(dedicatedserverproperties.pvp); - this.setAllowFlight(dedicatedserverproperties.allowFlight); -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index e95f516756b2613972f20636443b3ff753342917..7fd6893c30fbb34367181620aa159ed79b803455 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -306,15 +306,15 @@ public class ChunkProviderServer extends IChunkProvider { - } - } - -- @Override -- public boolean a(Entity entity) { -+ public final boolean isInEntityTickingChunk(Entity entity) { return this.a(entity); } // Paper - OBFHELPER -+ @Override public boolean a(Entity entity) { - long i = ChunkCoordIntPair.pair(MathHelper.floor(entity.locX()) >> 4, MathHelper.floor(entity.locZ()) >> 4); - - return this.a(i, (Function>>) PlayerChunk::b); // CraftBukkit - decompile error - } - -- @Override -- public boolean a(ChunkCoordIntPair chunkcoordintpair) { -+ public final boolean isEntityTickingChunk(ChunkCoordIntPair chunkcoordintpair) { return this.a(chunkcoordintpair); } // Paper - OBFHELPER -+ @Override public boolean a(ChunkCoordIntPair chunkcoordintpair) { - return this.a(chunkcoordintpair.pair(), (Function>>) PlayerChunk::b); // CraftBukkit - decompile error - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 4b0b782ab19a6cea4412b5e9d8c0524aee1402e4..a32bc63ff1960bdb874d546ee42633063834da24 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -2,6 +2,7 @@ package net.minecraft.world.entity; - - import com.google.common.collect.ImmutableSet; - import java.util.Optional; -+import java.util.Set; // Paper - import java.util.UUID; - import java.util.function.Function; - import java.util.stream.Stream; -@@ -599,4 +600,10 @@ public class EntityTypes { - return new EntityTypes<>(this.a, this.b, this.d, this.e, this.f, this.g, this.c, this.j, this.h, this.i); - } - } -+ -+ // Paper start -+ public static Set getEntityNameList() { -+ return IRegistry.ENTITY_TYPE.keySet(); -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 344b7f52e85af3e543da0bb1dd14b68eb41ebb84..f794113e7cc5809d1da0c85648fb7311fb633f40 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -129,6 +129,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean populating; - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - -+ public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper -+ - public final SpigotTimings.WorldTimingsHandler timings; // Spigot - public static BlockPosition lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; -@@ -149,6 +151,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName()); // Spigot -+ this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper - this.generator = gen; - this.world = new CraftWorld((WorldServer) this, gen, env); - this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f03d83440291a329f5a1922c8710ed975025fdbb..82f5b3387f9e71ae258111b7196986623452dc02 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -807,6 +807,7 @@ public final class CraftServer implements Server { - } - - org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot -+ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper - for (WorldServer world : console.getWorlds()) { - world.worldDataServer.setDifficulty(config.difficulty); - world.setSpawnFlags(config.spawnMonsters, config.spawnAnimals); -@@ -840,6 +841,7 @@ public final class CraftServer implements Server { - world.ticksPerAmbientSpawns = this.getTicksPerAmbientSpawns(); - } - world.spigotConfig.init(); // Spigot -+ world.paperConfig.init(); // Paper - } - - pluginManager.clearPlugins(); -@@ -847,6 +849,7 @@ public final class CraftServer implements Server { - resetRecipes(); - reloadData(); - org.spigotmc.SpigotConfig.registerCommands(); // Spigot -+ com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper - overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); - ignoreVanillaPermissions = commandsConfiguration.getBoolean("ignore-vanilla-permissions"); - -@@ -2102,4 +2105,35 @@ public final class CraftServer implements Server { - return spigot; - } - // Spigot end -+ -+ // Paper start -+ @SuppressWarnings({"rawtypes", "unchecked"}) -+ public static java.nio.file.Path dumpHeap(java.nio.file.Path dir, String name) { -+ try { -+ java.nio.file.Files.createDirectories(dir); -+ -+ javax.management.MBeanServer server = java.lang.management.ManagementFactory.getPlatformMBeanServer(); -+ java.nio.file.Path file; -+ -+ try { -+ Class clazz = Class.forName("openj9.lang.management.OpenJ9DiagnosticsMXBean"); -+ Object openj9Mbean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "openj9.lang.management:type=OpenJ9Diagnostics", clazz); -+ java.lang.reflect.Method m = clazz.getMethod("triggerDumpToFile", String.class, String.class); -+ file = dir.resolve(name + ".phd"); -+ m.invoke(openj9Mbean, "heap", file.toString()); -+ } catch (ClassNotFoundException e) { -+ Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean"); -+ Object hotspotMBean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", clazz); -+ java.lang.reflect.Method m = clazz.getMethod("dumpHeap", String.class, boolean.class); -+ file = dir.resolve(name + ".hprof"); -+ m.invoke(hotspotMBean, file.toString(), true); -+ } -+ -+ return file; -+ } catch (Throwable t) { -+ Bukkit.getLogger().log(Level.SEVERE, "Could not write heap", t); -+ return null; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 46a16e31775b28c44f95a8ac5545ebcb656c74b6..05aedca561919a12ced1925c5cc9af585bb04523 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -129,6 +129,14 @@ public class Main { - .defaultsTo(new File("spigot.yml")) - .describedAs("Yml file"); - // Spigot End -+ -+ // Paper Start -+ acceptsAll(asList("paper", "paper-settings"), "File for paper settings") -+ .withRequiredArg() -+ .ofType(File.class) -+ .defaultsTo(new File("paper.yml")) -+ .describedAs("Yml file"); -+ // Paper end - } - }; - -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 83d83ff7ceffbb77723da721b869dfd0091e496d..0efcbab8f8806aeb8dd8bd6384e5a7cee375d100 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -39,36 +39,36 @@ public class SpigotWorldConfig - config.set( "world-settings.default." + path, val ); - } - -- private boolean getBoolean(String path, boolean def) -+ public boolean getBoolean(String path, boolean def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getBoolean( "world-settings." + worldName + "." + path, config.getBoolean( "world-settings.default." + path ) ); - } - -- private double getDouble(String path, double def) -+ public double getDouble(String path, double def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getDouble( "world-settings." + worldName + "." + path, config.getDouble( "world-settings.default." + path ) ); - } - -- private int getInt(String path) -+ public int getInt(String path) // Paper - private -> public - { - return config.getInt( "world-settings." + worldName + "." + path ); - } - -- private int getInt(String path, int def) -+ public int getInt(String path, int def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getInt( "world-settings." + worldName + "." + path, config.getInt( "world-settings.default." + path ) ); - } - -- private List getList(String path, T def) -+ public List getList(String path, T def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return (List) config.getList( "world-settings." + worldName + "." + path, config.getList( "world-settings.default." + path ) ); - } - -- private String getString(String path, String def) -+ public String getString(String path, String def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getString( "world-settings." + worldName + "." + path, config.getString( "world-settings.default." + path ) ); diff --git a/Unmapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch b/Unmapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch deleted file mode 100644 index 1f1f3bab60..0000000000 --- a/Unmapped-Spigot-Server-Patches/0003-MC-Dev-fixes.patch +++ /dev/null @@ -1,893 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 30 Mar 2016 19:36:20 -0400 -Subject: [PATCH] MC Dev fixes - - -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 14b1a51b9b675aa175c32990402551fa43ec1599..bc7757b929ecce998094ddcdf51a4703e165a6d6 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -65,8 +65,8 @@ public class SystemUtils { - return Collectors.toMap(Entry::getKey, Entry::getValue); - } - -- public static > String a(IBlockState iblockstate, Object object) { -- return iblockstate.a((Comparable) object); -+ public static > String a(IBlockState iblockstate, T object) { // Paper - decompile fix -+ return iblockstate.a(object); // Paper - decompile fix - } - - public static String a(String s, @Nullable MinecraftKey minecraftkey) { -@@ -234,8 +234,8 @@ public class SystemUtils { - public static T b(Iterable iterable, @Nullable T t0) { - Iterator iterator = iterable.iterator(); - -- Object object; -- Object object1; -+ T object; // Paper - decompile fix -+ T object1; // Paper - decompile fix - - for (object1 = null; iterator.hasNext(); object1 = object) { - object = iterator.next(); -@@ -260,7 +260,7 @@ public class SystemUtils { - } - - public static Strategy k() { -- return SystemUtils.IdentityHashingStrategy.INSTANCE; -+ return (Strategy) SystemUtils.IdentityHashingStrategy.INSTANCE; // Paper - decompile fix - } - - public static CompletableFuture> b(List> list) { -@@ -271,7 +271,7 @@ public class SystemUtils { - list.forEach((completablefuture1) -> { - int i = list1.size(); - -- list1.add((Object) null); -+ list1.add(null); // Paper - decompile fix - acompletablefuture[i] = completablefuture1.whenComplete((object, throwable) -> { - if (throwable != null) { - completablefuture.completeExceptionally(throwable); -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index f85889a232998520761731a17f3d293d3360fe2c..76675ad1633dbaebb180842b9914fac18741c62e 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -241,8 +241,8 @@ public class BlockPosition extends BaseBlockPosition { - }; - } - -- public static Iterable a(BlockPosition blockposition, int i, int j, int k) { -- int l = i + j + k; -+ public static Iterable a(BlockPosition blockposition, int p_i, int p_j, int p_k) { // Paper - decompile issues - variable name conflicts to inner class field refs -+ int l_decompiled = p_i + p_j + p_k; // Paper - decompile issues - int i1 = blockposition.getX(); - int j1 = blockposition.getY(); - int k1 = blockposition.getZ(); -@@ -270,15 +270,15 @@ public class BlockPosition extends BaseBlockPosition { - ++this.l; - if (this.l > this.j) { - ++this.i; -- if (this.i > l) { -+ if (this.i > l_decompiled) { // Paper - use proper l above (first line of this method) - return (BlockPosition) this.endOfData(); - } - -- this.j = Math.min(i, this.i); -+ this.j = Math.min(p_i, this.i); // Paper - decompile issues - this.l = -this.j; - } - -- this.k = Math.min(j, this.i - Math.abs(this.l)); -+ this.k = Math.min(p_j, this.i - Math.abs(this.l)); // Paper - decompile issues - this.m = -this.k; - } - -@@ -286,7 +286,7 @@ public class BlockPosition extends BaseBlockPosition { - int i2 = this.m; - int j2 = this.i - Math.abs(l1) - Math.abs(i2); - -- if (j2 <= k) { -+ if (j2 <= p_k) { // Paper - decompile issues - this.n = j2 != 0; - blockposition_mutableblockposition = this.h.d(i1 + l1, j1 + i2, k1 + j2); - } -@@ -355,13 +355,13 @@ public class BlockPosition extends BaseBlockPosition { - }; - } - -- public static Iterable a(BlockPosition blockposition, int i, EnumDirection enumdirection, EnumDirection enumdirection1) { -+ public static Iterable a(BlockPosition blockposition, int I, EnumDirection enumdirection, EnumDirection enumdirection1) { // Paper - decompile fix - Validate.validState(enumdirection.n() != enumdirection1.n(), "The two directions cannot be on the same axis", new Object[0]); - return () -> { - return new AbstractIterator() { - private final EnumDirection[] e = new EnumDirection[]{enumdirection, enumdirection1, enumdirection.opposite(), enumdirection1.opposite()}; - private final BlockPosition.MutableBlockPosition f = blockposition.i().c(enumdirection1); -- private final int g = 4 * i; -+ private final int g = 4 * I; - private int h = -1; - private int i; - private int j; -diff --git a/src/main/java/net/minecraft/core/RegistryBlockID.java b/src/main/java/net/minecraft/core/RegistryBlockID.java -index b173ed8a6abeee41ce48e03f6403f2eb4978155b..e543b6927280a14e1d1220534758289934e31282 100644 ---- a/src/main/java/net/minecraft/core/RegistryBlockID.java -+++ b/src/main/java/net/minecraft/core/RegistryBlockID.java -@@ -27,7 +27,7 @@ public class RegistryBlockID implements Registry { - this.b.put(t0, i); - - while (this.c.size() <= i) { -- this.c.add((Object) null); -+ this.c.add(null); // Paper - decompile fix - } - - this.c.set(i, t0); -@@ -41,6 +41,13 @@ public class RegistryBlockID implements Registry { - this.a(t0, this.a); - } - -+ // Paper start - decompile fix -+ @Override -+ public int a(T t) { -+ return getId(t); -+ } -+ // Paper end -+ - public int getId(T t0) { - Integer integer = (Integer) this.b.get(t0); - -diff --git a/src/main/java/net/minecraft/nbt/NBTBase.java b/src/main/java/net/minecraft/nbt/NBTBase.java -index 170a65cb13e7b87f64cd28331431ba55d53702cd..d6e51f82f6df2d7058806f3e483766e18398af77 100644 ---- a/src/main/java/net/minecraft/nbt/NBTBase.java -+++ b/src/main/java/net/minecraft/nbt/NBTBase.java -@@ -20,7 +20,7 @@ public interface NBTBase { - - NBTTagType b(); - -- NBTBase clone(); -+ public NBTBase clone(); // Paper - decompile fix - - default String asString() { - return this.toString(); -diff --git a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -index be4d54099a0deb0e0275208ac61c8a172a48b398..850d3a7bb8ae4c43c0e2f737cfe69261f338b026 100644 ---- a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -+++ b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -@@ -18,6 +18,7 @@ import java.util.zip.GZIPOutputStream; - import net.minecraft.CrashReport; - import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; -+import io.netty.buffer.ByteBufInputStream; // Paper - - public class NBTCompressedStreamTools { - -@@ -137,7 +138,7 @@ public class NBTCompressedStreamTools { - - public static NBTTagCompound a(DataInput datainput, NBTReadLimiter nbtreadlimiter) throws IOException { - // Spigot start -- if ( datainput instanceof io.netty.buffer.ByteBufInputStream ) -+ if ( datainput instanceof ByteBufInputStream) // Paper - { - datainput = new DataInputStream(new org.spigotmc.LimitStream((InputStream) datainput, nbtreadlimiter)); - } -diff --git a/src/main/java/net/minecraft/nbt/NBTTagList.java b/src/main/java/net/minecraft/nbt/NBTTagList.java -index 35cca76fb7c7aa736e64185b44016e65cfaef6cd..4f6f6f51f9807bafa88482c0fe776c8b163107d7 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagList.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagList.java -@@ -53,7 +53,7 @@ public class NBTTagList extends NBTList { - return "TAG_List"; - } - }; -- private static final ByteSet b = new ByteOpenHashSet(Arrays.asList(1, 2, 3, 4, 5, 6)); -+ private static final ByteSet b = new ByteOpenHashSet(Arrays.asList((byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6)); // Paper - decompiler fix - private final List list; - private byte type; - -diff --git a/src/main/java/net/minecraft/network/EnumProtocol.java b/src/main/java/net/minecraft/network/EnumProtocol.java -index ab08336043d4f558434ed1f38d25cc555ace1ac0..a892521db1197369bf6363bd2f5da24bf53643ab 100644 ---- a/src/main/java/net/minecraft/network/EnumProtocol.java -+++ b/src/main/java/net/minecraft/network/EnumProtocol.java -@@ -12,6 +12,8 @@ import javax.annotation.Nullable; - import net.minecraft.SystemUtils; - import net.minecraft.network.protocol.EnumProtocolDirection; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.network.protocol.game.PacketListenerPlayIn; -+import net.minecraft.network.protocol.game.PacketListenerPlayOut; - import net.minecraft.network.protocol.game.PacketPlayInAbilities; - import net.minecraft.network.protocol.game.PacketPlayInAdvancements; - import net.minecraft.network.protocol.game.PacketPlayInArmAnimation; -@@ -146,24 +148,30 @@ import net.minecraft.network.protocol.game.PacketPlayOutWindowItems; - import net.minecraft.network.protocol.game.PacketPlayOutWorldBorder; - import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.network.protocol.game.PacketPlayOutWorldParticles; -+import net.minecraft.network.protocol.handshake.PacketHandshakingInListener; - import net.minecraft.network.protocol.handshake.PacketHandshakingInSetProtocol; - import net.minecraft.network.protocol.login.PacketLoginInCustomPayload; - import net.minecraft.network.protocol.login.PacketLoginInEncryptionBegin; -+import net.minecraft.network.protocol.login.PacketLoginInListener; - import net.minecraft.network.protocol.login.PacketLoginInStart; - import net.minecraft.network.protocol.login.PacketLoginOutCustomPayload; - import net.minecraft.network.protocol.login.PacketLoginOutDisconnect; - import net.minecraft.network.protocol.login.PacketLoginOutEncryptionBegin; -+import net.minecraft.network.protocol.login.PacketLoginOutListener; - import net.minecraft.network.protocol.login.PacketLoginOutSetCompression; - import net.minecraft.network.protocol.login.PacketLoginOutSuccess; -+import net.minecraft.network.protocol.status.PacketStatusInListener; - import net.minecraft.network.protocol.status.PacketStatusInPing; - import net.minecraft.network.protocol.status.PacketStatusInStart; -+import net.minecraft.network.protocol.status.PacketStatusOutListener; - import net.minecraft.network.protocol.status.PacketStatusOutPong; - import net.minecraft.network.protocol.status.PacketStatusOutServerInfo; - import org.apache.logging.log4j.LogManager; - - public enum EnumProtocol { - -- HANDSHAKING(-1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketHandshakingInSetProtocol.class, PacketHandshakingInSetProtocol::new))), PLAY(0, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a<>()).a(PacketPlayOutSpawnEntity.class, PacketPlayOutSpawnEntity::new).a(PacketPlayOutSpawnEntityExperienceOrb.class, PacketPlayOutSpawnEntityExperienceOrb::new).a(PacketPlayOutSpawnEntityLiving.class, PacketPlayOutSpawnEntityLiving::new).a(PacketPlayOutSpawnEntityPainting.class, PacketPlayOutSpawnEntityPainting::new).a(PacketPlayOutNamedEntitySpawn.class, PacketPlayOutNamedEntitySpawn::new).a(PacketPlayOutAnimation.class, PacketPlayOutAnimation::new).a(PacketPlayOutStatistic.class, PacketPlayOutStatistic::new).a(PacketPlayOutBlockBreak.class, PacketPlayOutBlockBreak::new).a(PacketPlayOutBlockBreakAnimation.class, PacketPlayOutBlockBreakAnimation::new).a(PacketPlayOutTileEntityData.class, PacketPlayOutTileEntityData::new).a(PacketPlayOutBlockAction.class, PacketPlayOutBlockAction::new).a(PacketPlayOutBlockChange.class, PacketPlayOutBlockChange::new).a(PacketPlayOutBoss.class, PacketPlayOutBoss::new).a(PacketPlayOutServerDifficulty.class, PacketPlayOutServerDifficulty::new).a(PacketPlayOutChat.class, PacketPlayOutChat::new).a(PacketPlayOutTabComplete.class, PacketPlayOutTabComplete::new).a(PacketPlayOutCommands.class, PacketPlayOutCommands::new).a(PacketPlayOutTransaction.class, PacketPlayOutTransaction::new).a(PacketPlayOutCloseWindow.class, PacketPlayOutCloseWindow::new).a(PacketPlayOutWindowItems.class, PacketPlayOutWindowItems::new).a(PacketPlayOutWindowData.class, PacketPlayOutWindowData::new).a(PacketPlayOutSetSlot.class, PacketPlayOutSetSlot::new).a(PacketPlayOutSetCooldown.class, PacketPlayOutSetCooldown::new).a(PacketPlayOutCustomPayload.class, PacketPlayOutCustomPayload::new).a(PacketPlayOutCustomSoundEffect.class, PacketPlayOutCustomSoundEffect::new).a(PacketPlayOutKickDisconnect.class, PacketPlayOutKickDisconnect::new).a(PacketPlayOutEntityStatus.class, PacketPlayOutEntityStatus::new).a(PacketPlayOutExplosion.class, PacketPlayOutExplosion::new).a(PacketPlayOutUnloadChunk.class, PacketPlayOutUnloadChunk::new).a(PacketPlayOutGameStateChange.class, PacketPlayOutGameStateChange::new).a(PacketPlayOutOpenWindowHorse.class, PacketPlayOutOpenWindowHorse::new).a(PacketPlayOutKeepAlive.class, PacketPlayOutKeepAlive::new).a(PacketPlayOutMapChunk.class, PacketPlayOutMapChunk::new).a(PacketPlayOutWorldEvent.class, PacketPlayOutWorldEvent::new).a(PacketPlayOutWorldParticles.class, PacketPlayOutWorldParticles::new).a(PacketPlayOutLightUpdate.class, PacketPlayOutLightUpdate::new).a(PacketPlayOutLogin.class, PacketPlayOutLogin::new).a(PacketPlayOutMap.class, PacketPlayOutMap::new).a(PacketPlayOutOpenWindowMerchant.class, PacketPlayOutOpenWindowMerchant::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMove.class, PacketPlayOutEntity.PacketPlayOutRelEntityMove::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook.class, PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook::new).a(PacketPlayOutEntity.PacketPlayOutEntityLook.class, PacketPlayOutEntity.PacketPlayOutEntityLook::new).a(PacketPlayOutEntity.class, PacketPlayOutEntity::new).a(PacketPlayOutVehicleMove.class, PacketPlayOutVehicleMove::new).a(PacketPlayOutOpenBook.class, PacketPlayOutOpenBook::new).a(PacketPlayOutOpenWindow.class, PacketPlayOutOpenWindow::new).a(PacketPlayOutOpenSignEditor.class, PacketPlayOutOpenSignEditor::new).a(PacketPlayOutAutoRecipe.class, PacketPlayOutAutoRecipe::new).a(PacketPlayOutAbilities.class, PacketPlayOutAbilities::new).a(PacketPlayOutCombatEvent.class, PacketPlayOutCombatEvent::new).a(PacketPlayOutPlayerInfo.class, PacketPlayOutPlayerInfo::new).a(PacketPlayOutLookAt.class, PacketPlayOutLookAt::new).a(PacketPlayOutPosition.class, PacketPlayOutPosition::new).a(PacketPlayOutRecipes.class, PacketPlayOutRecipes::new).a(PacketPlayOutEntityDestroy.class, PacketPlayOutEntityDestroy::new).a(PacketPlayOutRemoveEntityEffect.class, PacketPlayOutRemoveEntityEffect::new).a(PacketPlayOutResourcePackSend.class, PacketPlayOutResourcePackSend::new).a(PacketPlayOutRespawn.class, PacketPlayOutRespawn::new).a(PacketPlayOutEntityHeadRotation.class, PacketPlayOutEntityHeadRotation::new).a(PacketPlayOutMultiBlockChange.class, PacketPlayOutMultiBlockChange::new).a(PacketPlayOutSelectAdvancementTab.class, PacketPlayOutSelectAdvancementTab::new).a(PacketPlayOutWorldBorder.class, PacketPlayOutWorldBorder::new).a(PacketPlayOutCamera.class, PacketPlayOutCamera::new).a(PacketPlayOutHeldItemSlot.class, PacketPlayOutHeldItemSlot::new).a(PacketPlayOutViewCentre.class, PacketPlayOutViewCentre::new).a(PacketPlayOutViewDistance.class, PacketPlayOutViewDistance::new).a(PacketPlayOutSpawnPosition.class, PacketPlayOutSpawnPosition::new).a(PacketPlayOutScoreboardDisplayObjective.class, PacketPlayOutScoreboardDisplayObjective::new).a(PacketPlayOutEntityMetadata.class, PacketPlayOutEntityMetadata::new).a(PacketPlayOutAttachEntity.class, PacketPlayOutAttachEntity::new).a(PacketPlayOutEntityVelocity.class, PacketPlayOutEntityVelocity::new).a(PacketPlayOutEntityEquipment.class, PacketPlayOutEntityEquipment::new).a(PacketPlayOutExperience.class, PacketPlayOutExperience::new).a(PacketPlayOutUpdateHealth.class, PacketPlayOutUpdateHealth::new).a(PacketPlayOutScoreboardObjective.class, PacketPlayOutScoreboardObjective::new).a(PacketPlayOutMount.class, PacketPlayOutMount::new).a(PacketPlayOutScoreboardTeam.class, PacketPlayOutScoreboardTeam::new).a(PacketPlayOutScoreboardScore.class, PacketPlayOutScoreboardScore::new).a(PacketPlayOutUpdateTime.class, PacketPlayOutUpdateTime::new).a(PacketPlayOutTitle.class, PacketPlayOutTitle::new).a(PacketPlayOutEntitySound.class, PacketPlayOutEntitySound::new).a(PacketPlayOutNamedSoundEffect.class, PacketPlayOutNamedSoundEffect::new).a(PacketPlayOutStopSound.class, PacketPlayOutStopSound::new).a(PacketPlayOutPlayerListHeaderFooter.class, PacketPlayOutPlayerListHeaderFooter::new).a(PacketPlayOutNBTQuery.class, PacketPlayOutNBTQuery::new).a(PacketPlayOutCollect.class, PacketPlayOutCollect::new).a(PacketPlayOutEntityTeleport.class, PacketPlayOutEntityTeleport::new).a(PacketPlayOutAdvancements.class, PacketPlayOutAdvancements::new).a(PacketPlayOutUpdateAttributes.class, PacketPlayOutUpdateAttributes::new).a(PacketPlayOutEntityEffect.class, PacketPlayOutEntityEffect::new).a(PacketPlayOutRecipeUpdate.class, PacketPlayOutRecipeUpdate::new).a(PacketPlayOutTags.class, PacketPlayOutTags::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketPlayInTeleportAccept.class, PacketPlayInTeleportAccept::new).a(PacketPlayInTileNBTQuery.class, PacketPlayInTileNBTQuery::new).a(PacketPlayInDifficultyChange.class, PacketPlayInDifficultyChange::new).a(PacketPlayInChat.class, PacketPlayInChat::new).a(PacketPlayInClientCommand.class, PacketPlayInClientCommand::new).a(PacketPlayInSettings.class, PacketPlayInSettings::new).a(PacketPlayInTabComplete.class, PacketPlayInTabComplete::new).a(PacketPlayInTransaction.class, PacketPlayInTransaction::new).a(PacketPlayInEnchantItem.class, PacketPlayInEnchantItem::new).a(PacketPlayInWindowClick.class, PacketPlayInWindowClick::new).a(PacketPlayInCloseWindow.class, PacketPlayInCloseWindow::new).a(PacketPlayInCustomPayload.class, PacketPlayInCustomPayload::new).a(PacketPlayInBEdit.class, PacketPlayInBEdit::new).a(PacketPlayInEntityNBTQuery.class, PacketPlayInEntityNBTQuery::new).a(PacketPlayInUseEntity.class, PacketPlayInUseEntity::new).a(PacketPlayInJigsawGenerate.class, PacketPlayInJigsawGenerate::new).a(PacketPlayInKeepAlive.class, PacketPlayInKeepAlive::new).a(PacketPlayInDifficultyLock.class, PacketPlayInDifficultyLock::new).a(PacketPlayInFlying.PacketPlayInPosition.class, PacketPlayInFlying.PacketPlayInPosition::new).a(PacketPlayInFlying.PacketPlayInPositionLook.class, PacketPlayInFlying.PacketPlayInPositionLook::new).a(PacketPlayInFlying.PacketPlayInLook.class, PacketPlayInFlying.PacketPlayInLook::new).a(PacketPlayInFlying.class, PacketPlayInFlying::new).a(PacketPlayInVehicleMove.class, PacketPlayInVehicleMove::new).a(PacketPlayInBoatMove.class, PacketPlayInBoatMove::new).a(PacketPlayInPickItem.class, PacketPlayInPickItem::new).a(PacketPlayInAutoRecipe.class, PacketPlayInAutoRecipe::new).a(PacketPlayInAbilities.class, PacketPlayInAbilities::new).a(PacketPlayInBlockDig.class, PacketPlayInBlockDig::new).a(PacketPlayInEntityAction.class, PacketPlayInEntityAction::new).a(PacketPlayInSteerVehicle.class, PacketPlayInSteerVehicle::new).a(PacketPlayInRecipeSettings.class, PacketPlayInRecipeSettings::new).a(PacketPlayInRecipeDisplayed.class, PacketPlayInRecipeDisplayed::new).a(PacketPlayInItemName.class, PacketPlayInItemName::new).a(PacketPlayInResourcePackStatus.class, PacketPlayInResourcePackStatus::new).a(PacketPlayInAdvancements.class, PacketPlayInAdvancements::new).a(PacketPlayInTrSel.class, PacketPlayInTrSel::new).a(PacketPlayInBeacon.class, PacketPlayInBeacon::new).a(PacketPlayInHeldItemSlot.class, PacketPlayInHeldItemSlot::new).a(PacketPlayInSetCommandBlock.class, PacketPlayInSetCommandBlock::new).a(PacketPlayInSetCommandMinecart.class, PacketPlayInSetCommandMinecart::new).a(PacketPlayInSetCreativeSlot.class, PacketPlayInSetCreativeSlot::new).a(PacketPlayInSetJigsaw.class, PacketPlayInSetJigsaw::new).a(PacketPlayInStruct.class, PacketPlayInStruct::new).a(PacketPlayInUpdateSign.class, PacketPlayInUpdateSign::new).a(PacketPlayInArmAnimation.class, PacketPlayInArmAnimation::new).a(PacketPlayInSpectate.class, PacketPlayInSpectate::new).a(PacketPlayInUseItem.class, PacketPlayInUseItem::new).a(PacketPlayInBlockPlace.class, PacketPlayInBlockPlace::new))), STATUS(1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketStatusInStart.class, PacketStatusInStart::new).a(PacketStatusInPing.class, PacketStatusInPing::new)).a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a<>()).a(PacketStatusOutServerInfo.class, PacketStatusOutServerInfo::new).a(PacketStatusOutPong.class, PacketStatusOutPong::new))), LOGIN(2, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a<>()).a(PacketLoginOutDisconnect.class, PacketLoginOutDisconnect::new).a(PacketLoginOutEncryptionBegin.class, PacketLoginOutEncryptionBegin::new).a(PacketLoginOutSuccess.class, PacketLoginOutSuccess::new).a(PacketLoginOutSetCompression.class, PacketLoginOutSetCompression::new).a(PacketLoginOutCustomPayload.class, PacketLoginOutCustomPayload::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketLoginInStart.class, PacketLoginInStart::new).a(PacketLoginInEncryptionBegin.class, PacketLoginInEncryptionBegin::new).a(PacketLoginInCustomPayload.class, PacketLoginInCustomPayload::new))); -+ // Paper - fix decompile error - add generic names to < > like PacketListenerPlayOut -+ HANDSHAKING(-1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketHandshakingInSetProtocol.class, PacketHandshakingInSetProtocol::new))), PLAY(0, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a()).a(PacketPlayOutSpawnEntity.class, PacketPlayOutSpawnEntity::new).a(PacketPlayOutSpawnEntityExperienceOrb.class, PacketPlayOutSpawnEntityExperienceOrb::new).a(PacketPlayOutSpawnEntityLiving.class, PacketPlayOutSpawnEntityLiving::new).a(PacketPlayOutSpawnEntityPainting.class, PacketPlayOutSpawnEntityPainting::new).a(PacketPlayOutNamedEntitySpawn.class, PacketPlayOutNamedEntitySpawn::new).a(PacketPlayOutAnimation.class, PacketPlayOutAnimation::new).a(PacketPlayOutStatistic.class, PacketPlayOutStatistic::new).a(PacketPlayOutBlockBreak.class, PacketPlayOutBlockBreak::new).a(PacketPlayOutBlockBreakAnimation.class, PacketPlayOutBlockBreakAnimation::new).a(PacketPlayOutTileEntityData.class, PacketPlayOutTileEntityData::new).a(PacketPlayOutBlockAction.class, PacketPlayOutBlockAction::new).a(PacketPlayOutBlockChange.class, PacketPlayOutBlockChange::new).a(PacketPlayOutBoss.class, PacketPlayOutBoss::new).a(PacketPlayOutServerDifficulty.class, PacketPlayOutServerDifficulty::new).a(PacketPlayOutChat.class, PacketPlayOutChat::new).a(PacketPlayOutTabComplete.class, PacketPlayOutTabComplete::new).a(PacketPlayOutCommands.class, PacketPlayOutCommands::new).a(PacketPlayOutTransaction.class, PacketPlayOutTransaction::new).a(PacketPlayOutCloseWindow.class, PacketPlayOutCloseWindow::new).a(PacketPlayOutWindowItems.class, PacketPlayOutWindowItems::new).a(PacketPlayOutWindowData.class, PacketPlayOutWindowData::new).a(PacketPlayOutSetSlot.class, PacketPlayOutSetSlot::new).a(PacketPlayOutSetCooldown.class, PacketPlayOutSetCooldown::new).a(PacketPlayOutCustomPayload.class, PacketPlayOutCustomPayload::new).a(PacketPlayOutCustomSoundEffect.class, PacketPlayOutCustomSoundEffect::new).a(PacketPlayOutKickDisconnect.class, PacketPlayOutKickDisconnect::new).a(PacketPlayOutEntityStatus.class, PacketPlayOutEntityStatus::new).a(PacketPlayOutExplosion.class, PacketPlayOutExplosion::new).a(PacketPlayOutUnloadChunk.class, PacketPlayOutUnloadChunk::new).a(PacketPlayOutGameStateChange.class, PacketPlayOutGameStateChange::new).a(PacketPlayOutOpenWindowHorse.class, PacketPlayOutOpenWindowHorse::new).a(PacketPlayOutKeepAlive.class, PacketPlayOutKeepAlive::new).a(PacketPlayOutMapChunk.class, PacketPlayOutMapChunk::new).a(PacketPlayOutWorldEvent.class, PacketPlayOutWorldEvent::new).a(PacketPlayOutWorldParticles.class, PacketPlayOutWorldParticles::new).a(PacketPlayOutLightUpdate.class, PacketPlayOutLightUpdate::new).a(PacketPlayOutLogin.class, PacketPlayOutLogin::new).a(PacketPlayOutMap.class, PacketPlayOutMap::new).a(PacketPlayOutOpenWindowMerchant.class, PacketPlayOutOpenWindowMerchant::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMove.class, PacketPlayOutEntity.PacketPlayOutRelEntityMove::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook.class, PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook::new).a(PacketPlayOutEntity.PacketPlayOutEntityLook.class, PacketPlayOutEntity.PacketPlayOutEntityLook::new).a(PacketPlayOutEntity.class, PacketPlayOutEntity::new).a(PacketPlayOutVehicleMove.class, PacketPlayOutVehicleMove::new).a(PacketPlayOutOpenBook.class, PacketPlayOutOpenBook::new).a(PacketPlayOutOpenWindow.class, PacketPlayOutOpenWindow::new).a(PacketPlayOutOpenSignEditor.class, PacketPlayOutOpenSignEditor::new).a(PacketPlayOutAutoRecipe.class, PacketPlayOutAutoRecipe::new).a(PacketPlayOutAbilities.class, PacketPlayOutAbilities::new).a(PacketPlayOutCombatEvent.class, PacketPlayOutCombatEvent::new).a(PacketPlayOutPlayerInfo.class, PacketPlayOutPlayerInfo::new).a(PacketPlayOutLookAt.class, PacketPlayOutLookAt::new).a(PacketPlayOutPosition.class, PacketPlayOutPosition::new).a(PacketPlayOutRecipes.class, PacketPlayOutRecipes::new).a(PacketPlayOutEntityDestroy.class, PacketPlayOutEntityDestroy::new).a(PacketPlayOutRemoveEntityEffect.class, PacketPlayOutRemoveEntityEffect::new).a(PacketPlayOutResourcePackSend.class, PacketPlayOutResourcePackSend::new).a(PacketPlayOutRespawn.class, PacketPlayOutRespawn::new).a(PacketPlayOutEntityHeadRotation.class, PacketPlayOutEntityHeadRotation::new).a(PacketPlayOutMultiBlockChange.class, PacketPlayOutMultiBlockChange::new).a(PacketPlayOutSelectAdvancementTab.class, PacketPlayOutSelectAdvancementTab::new).a(PacketPlayOutWorldBorder.class, PacketPlayOutWorldBorder::new).a(PacketPlayOutCamera.class, PacketPlayOutCamera::new).a(PacketPlayOutHeldItemSlot.class, PacketPlayOutHeldItemSlot::new).a(PacketPlayOutViewCentre.class, PacketPlayOutViewCentre::new).a(PacketPlayOutViewDistance.class, PacketPlayOutViewDistance::new).a(PacketPlayOutSpawnPosition.class, PacketPlayOutSpawnPosition::new).a(PacketPlayOutScoreboardDisplayObjective.class, PacketPlayOutScoreboardDisplayObjective::new).a(PacketPlayOutEntityMetadata.class, PacketPlayOutEntityMetadata::new).a(PacketPlayOutAttachEntity.class, PacketPlayOutAttachEntity::new).a(PacketPlayOutEntityVelocity.class, PacketPlayOutEntityVelocity::new).a(PacketPlayOutEntityEquipment.class, PacketPlayOutEntityEquipment::new).a(PacketPlayOutExperience.class, PacketPlayOutExperience::new).a(PacketPlayOutUpdateHealth.class, PacketPlayOutUpdateHealth::new).a(PacketPlayOutScoreboardObjective.class, PacketPlayOutScoreboardObjective::new).a(PacketPlayOutMount.class, PacketPlayOutMount::new).a(PacketPlayOutScoreboardTeam.class, PacketPlayOutScoreboardTeam::new).a(PacketPlayOutScoreboardScore.class, PacketPlayOutScoreboardScore::new).a(PacketPlayOutUpdateTime.class, PacketPlayOutUpdateTime::new).a(PacketPlayOutTitle.class, PacketPlayOutTitle::new).a(PacketPlayOutEntitySound.class, PacketPlayOutEntitySound::new).a(PacketPlayOutNamedSoundEffect.class, PacketPlayOutNamedSoundEffect::new).a(PacketPlayOutStopSound.class, PacketPlayOutStopSound::new).a(PacketPlayOutPlayerListHeaderFooter.class, PacketPlayOutPlayerListHeaderFooter::new).a(PacketPlayOutNBTQuery.class, PacketPlayOutNBTQuery::new).a(PacketPlayOutCollect.class, PacketPlayOutCollect::new).a(PacketPlayOutEntityTeleport.class, PacketPlayOutEntityTeleport::new).a(PacketPlayOutAdvancements.class, PacketPlayOutAdvancements::new).a(PacketPlayOutUpdateAttributes.class, PacketPlayOutUpdateAttributes::new).a(PacketPlayOutEntityEffect.class, PacketPlayOutEntityEffect::new).a(PacketPlayOutRecipeUpdate.class, PacketPlayOutRecipeUpdate::new).a(PacketPlayOutTags.class, PacketPlayOutTags::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketPlayInTeleportAccept.class, PacketPlayInTeleportAccept::new).a(PacketPlayInTileNBTQuery.class, PacketPlayInTileNBTQuery::new).a(PacketPlayInDifficultyChange.class, PacketPlayInDifficultyChange::new).a(PacketPlayInChat.class, PacketPlayInChat::new).a(PacketPlayInClientCommand.class, PacketPlayInClientCommand::new).a(PacketPlayInSettings.class, PacketPlayInSettings::new).a(PacketPlayInTabComplete.class, PacketPlayInTabComplete::new).a(PacketPlayInTransaction.class, PacketPlayInTransaction::new).a(PacketPlayInEnchantItem.class, PacketPlayInEnchantItem::new).a(PacketPlayInWindowClick.class, PacketPlayInWindowClick::new).a(PacketPlayInCloseWindow.class, PacketPlayInCloseWindow::new).a(PacketPlayInCustomPayload.class, PacketPlayInCustomPayload::new).a(PacketPlayInBEdit.class, PacketPlayInBEdit::new).a(PacketPlayInEntityNBTQuery.class, PacketPlayInEntityNBTQuery::new).a(PacketPlayInUseEntity.class, PacketPlayInUseEntity::new).a(PacketPlayInJigsawGenerate.class, PacketPlayInJigsawGenerate::new).a(PacketPlayInKeepAlive.class, PacketPlayInKeepAlive::new).a(PacketPlayInDifficultyLock.class, PacketPlayInDifficultyLock::new).a(PacketPlayInFlying.PacketPlayInPosition.class, PacketPlayInFlying.PacketPlayInPosition::new).a(PacketPlayInFlying.PacketPlayInPositionLook.class, PacketPlayInFlying.PacketPlayInPositionLook::new).a(PacketPlayInFlying.PacketPlayInLook.class, PacketPlayInFlying.PacketPlayInLook::new).a(PacketPlayInFlying.class, PacketPlayInFlying::new).a(PacketPlayInVehicleMove.class, PacketPlayInVehicleMove::new).a(PacketPlayInBoatMove.class, PacketPlayInBoatMove::new).a(PacketPlayInPickItem.class, PacketPlayInPickItem::new).a(PacketPlayInAutoRecipe.class, PacketPlayInAutoRecipe::new).a(PacketPlayInAbilities.class, PacketPlayInAbilities::new).a(PacketPlayInBlockDig.class, PacketPlayInBlockDig::new).a(PacketPlayInEntityAction.class, PacketPlayInEntityAction::new).a(PacketPlayInSteerVehicle.class, PacketPlayInSteerVehicle::new).a(PacketPlayInRecipeSettings.class, PacketPlayInRecipeSettings::new).a(PacketPlayInRecipeDisplayed.class, PacketPlayInRecipeDisplayed::new).a(PacketPlayInItemName.class, PacketPlayInItemName::new).a(PacketPlayInResourcePackStatus.class, PacketPlayInResourcePackStatus::new).a(PacketPlayInAdvancements.class, PacketPlayInAdvancements::new).a(PacketPlayInTrSel.class, PacketPlayInTrSel::new).a(PacketPlayInBeacon.class, PacketPlayInBeacon::new).a(PacketPlayInHeldItemSlot.class, PacketPlayInHeldItemSlot::new).a(PacketPlayInSetCommandBlock.class, PacketPlayInSetCommandBlock::new).a(PacketPlayInSetCommandMinecart.class, PacketPlayInSetCommandMinecart::new).a(PacketPlayInSetCreativeSlot.class, PacketPlayInSetCreativeSlot::new).a(PacketPlayInSetJigsaw.class, PacketPlayInSetJigsaw::new).a(PacketPlayInStruct.class, PacketPlayInStruct::new).a(PacketPlayInUpdateSign.class, PacketPlayInUpdateSign::new).a(PacketPlayInArmAnimation.class, PacketPlayInArmAnimation::new).a(PacketPlayInSpectate.class, PacketPlayInSpectate::new).a(PacketPlayInUseItem.class, PacketPlayInUseItem::new).a(PacketPlayInBlockPlace.class, PacketPlayInBlockPlace::new))), STATUS(1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketStatusInStart.class, PacketStatusInStart::new).a(PacketStatusInPing.class, PacketStatusInPing::new)).a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a()).a(PacketStatusOutServerInfo.class, PacketStatusOutServerInfo::new).a(PacketStatusOutPong.class, PacketStatusOutPong::new))), LOGIN(2, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a()).a(PacketLoginOutDisconnect.class, PacketLoginOutDisconnect::new).a(PacketLoginOutEncryptionBegin.class, PacketLoginOutEncryptionBegin::new).a(PacketLoginOutSuccess.class, PacketLoginOutSuccess::new).a(PacketLoginOutSetCompression.class, PacketLoginOutSetCompression::new).a(PacketLoginOutCustomPayload.class, PacketLoginOutCustomPayload::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketLoginInStart.class, PacketLoginInStart::new).a(PacketLoginInEncryptionBegin.class, PacketLoginInEncryptionBegin::new).a(PacketLoginInCustomPayload.class, PacketLoginInCustomPayload::new))); - - private static final EnumProtocol[] e = new EnumProtocol[4]; - private static final Map>, EnumProtocol> f = Maps.newHashMap(); -@@ -248,7 +256,7 @@ public enum EnumProtocol { - private final List>> b; - - private a() { -- this.a = (Object2IntMap) SystemUtils.a((Object) (new Object2IntOpenHashMap()), (object2intopenhashmap) -> { -+ this.a = (Object2IntMap) SystemUtils.a(new Object2IntOpenHashMap(), (object2intopenhashmap) -> { // Paper - fix decompile error - object2intopenhashmap.defaultReturnValue(-1); - }); - this.b = Lists.newArrayList(); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 6977255868dbc0a96973095fff2eb935ecf4f4fc..6d843bb69b1848ae77098dc3f45d85f405fc24cd 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1675,9 +1675,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrantmap(resourcepackrepository::a).filter(Objects::nonNull).map(ResourcePackLoader::d).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error - }, this).thenCompose((immutablelist) -> { -- return DataPackResources.a(immutablelist, this.j() ? CommandDispatcher.ServerType.DEDICATED : CommandDispatcher.ServerType.INTEGRATED, this.h(), this.executorService, this); -+ return DataPackResources.a(immutablelist, this.j() ? CommandDispatcher.ServerType.DEDICATED : CommandDispatcher.ServerType.INTEGRATED, this.h(), this.executorService, this); // Paper - decompile error - }).thenAcceptAsync((datapackresources) -> { - this.dataPackResources.close(); - this.dataPackResources = datapackresources; -diff --git a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -index 5a51f47f747382ec2a30bb47bcb1f7c61dd4c369..e066848127cb9a42e8c39422691cc65132cac6bb 100644 ---- a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -+++ b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -@@ -179,7 +179,7 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - - public void queueUpdate() { - if ((!this.c.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { -- this.b.a((Object) (() -> { -+ this.b.a((() -> { // Paper - decompile error - this.b(); - this.g.set(false); - })); -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 1c500e1193296f92f03a94e2cf085b215daaad6c..51ef4adf66c1e21093e63ab46fa47e66c2425fdb 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -23,7 +23,7 @@ public final class Ticket implements Comparable> { - } else { - int j = Integer.compare(System.identityHashCode(this.a), System.identityHashCode(ticket.a)); - -- return j != 0 ? j : this.a.a().compare(this.identifier, ticket.identifier); -+ return j != 0 ? j : this.a.a().compare(this.identifier, (T)ticket.identifier); // Paper - decompile fix - } - } - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 144c80a4f3f827d5ee0a9220d12c49ee9aa3f096..7f9a1d64d123ce54608497a0e0a37d161d8c9d3c 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1919,7 +1919,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - // CraftBukkit - decompile error -- return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(it.unimi.dsi.fastutil.objects.Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { -+ return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { // Paper - decompile fix - return it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey() + ":" + it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue(); - }).collect(Collectors.joining(",")); - } catch (Exception exception) { -diff --git a/src/main/java/net/minecraft/stats/ServerStatisticManager.java b/src/main/java/net/minecraft/stats/ServerStatisticManager.java -index 322a4b584c6223b08581affb2e9919df19c0267b..1efab34e03199879f5e0dcee0ff79ce2c23c73bc 100644 ---- a/src/main/java/net/minecraft/stats/ServerStatisticManager.java -+++ b/src/main/java/net/minecraft/stats/ServerStatisticManager.java -@@ -203,7 +203,7 @@ public class ServerStatisticManager extends StatisticManager { - ObjectIterator objectiterator = this.a.object2IntEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); -+ Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix - Statistic statistic = (Statistic) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); - - ((JsonObject) map.computeIfAbsent(statistic.getWrapper(), (statisticwrapper) -> { -diff --git a/src/main/java/net/minecraft/util/ArraySetSorted.java b/src/main/java/net/minecraft/util/ArraySetSorted.java -index e56b8e172d96c5508457fcf3f5a0cf0d2d2d8d7c..427daa94322f47b4eaf881d85a01fed239db549a 100644 ---- a/src/main/java/net/minecraft/util/ArraySetSorted.java -+++ b/src/main/java/net/minecraft/util/ArraySetSorted.java -@@ -23,11 +23,11 @@ public class ArraySetSorted extends AbstractSet { - } - - public static > ArraySetSorted a(int i) { -- return new ArraySetSorted<>(i, Comparator.naturalOrder()); -+ return new ArraySetSorted<>(i, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix - } - - private static T[] a(Object[] aobject) { -- return (Object[]) aobject; -+ return (T[])aobject; // Paper - decompile fix - } - - private int c(T t0) { -@@ -101,7 +101,7 @@ public class ArraySetSorted extends AbstractSet { - } - - public boolean remove(Object object) { -- int i = this.c(object); -+ int i = this.c((T)object); // Paper - decompile fix - - if (i >= 0) { - this.d(i); -@@ -116,7 +116,7 @@ public class ArraySetSorted extends AbstractSet { - } - - public boolean contains(Object object) { -- int i = this.c(object); -+ int i = this.c((T)object); // Paper - decompile fix - - return i >= 0; - } -@@ -135,7 +135,7 @@ public class ArraySetSorted extends AbstractSet { - - public U[] toArray(U[] au) { - if (au.length < this.c) { -- return (Object[]) Arrays.copyOf(this.b, this.c, au.getClass()); -+ return (U[])Arrays.copyOf(this.b, this.c, au.getClass()); // Paper - decompile fix - } else { - System.arraycopy(this.b, 0, au, 0, this.c); - if (au.length > this.c) { -diff --git a/src/main/java/net/minecraft/util/RegistryID.java b/src/main/java/net/minecraft/util/RegistryID.java -index d88e55c64f80707b4a9b1e271714c2dbdee9a38a..6150f7a5c5004ac79414ab22dbaa3439dc8afdb4 100644 ---- a/src/main/java/net/minecraft/util/RegistryID.java -+++ b/src/main/java/net/minecraft/util/RegistryID.java -@@ -18,11 +18,18 @@ public class RegistryID implements Registry { - - public RegistryID(int i) { - i = (int) ((float) i / 0.8F); -- this.b = (Object[]) (new Object[i]); -+ this.b = (K[]) (new Object[i]); // Paper - decompile fix - this.c = new int[i]; -- this.d = (Object[]) (new Object[i]); -+ this.d = (K[]) (new Object[i]); // Paper - decompile fix - } - -+ // Paper start - decompile fix -+ @Override -+ public int a(K k) { -+ return getId(k); -+ } -+ // Paper end -+ - public int getId(@Nullable K k0) { - return this.c(this.b(k0, this.d(k0))); - } -@@ -56,9 +63,9 @@ public class RegistryID implements Registry { - K[] ak = this.b; - int[] aint = this.c; - -- this.b = (Object[]) (new Object[i]); -+ this.b = (K[]) (new Object[i]); // Paper - decompile fix - this.c = new int[i]; -- this.d = (Object[]) (new Object[i]); -+ this.d = (K[]) (new Object[i]); // Paper - decompile fix - this.e = 0; - this.f = 0; - -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -index 6abf1459cc97c261daf3c116521574d31a77a338..2b2c03ab62816f3d21ef953c4a45f55e3997cca6 100644 ---- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -+++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -@@ -55,7 +55,7 @@ public abstract class IAsyncTaskHandler implements Mailbox implements Mailbox implements Mailbox, AutoCloseable, Runnable { - - public void run() { - try { -- this.a((i) -> { -+ this.a((int i) -> { // Paper - decompile fix - return i == 0; - }); - } finally { -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -index fe5dcce3873ca2724ac9d416d6f5d3c65d0fdafe..aa1d948e6aebef25f0f4c4c07f5131d2e8387e59 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -@@ -191,9 +191,9 @@ public class VillagePlace extends RegionFileSection { - } - - private static boolean a(ChunkSection chunksection) { -- Set set = VillagePlaceType.x; -+ Set set = VillagePlaceType.x; // Paper - decompile error - -- set.getClass(); -+ //set.getClass(); // Paper - decompile error - return chunksection.a(set::contains); - } - -@@ -211,7 +211,7 @@ public class VillagePlace extends RegionFileSection { - SectionPosition.b(new ChunkCoordIntPair(blockposition), Math.floorDiv(i, 16)).map((sectionposition) -> { - return Pair.of(sectionposition, this.d(sectionposition.s())); - }).filter((pair) -> { -- return !(Boolean) ((Optional) pair.getSecond()).map(VillagePlaceSection::a).orElse(false); -+ return !(Boolean) (pair.getSecond()).map(VillagePlaceSection::a).orElse(false); // Paper - decompile fix - }).map((pair) -> { - return ((SectionPosition) pair.getFirst()).r(); - }).filter((chunkcoordintpair) -> { -@@ -263,7 +263,7 @@ public class VillagePlace extends RegionFileSection { - - private final Predicate d; - -- private Occupancy(Predicate predicate) { -+ private Occupancy(Predicate predicate) { // Paper - decompile fix - this.d = predicate; - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -index fc1f0cd4b70cdd0dda538d8867fab4cb8443120e..c181d5f5e6108ade54fc97c665897d1db5e90719 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -@@ -65,7 +65,7 @@ public class EntityVindicator extends EntityIllagerAbstract { - this.goalSelector.a(2, new EntityIllagerAbstract.b(this)); - this.goalSelector.a(3, new EntityRaider.a(this, 10.0F)); - this.goalSelector.a(4, new EntityVindicator.c(this)); -- this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a()); -+ this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, true)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, true)); -diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -index fe1dde99f758daa730acacc78237d92aa443ab6d..764ff5d9ffb541a356a6bc8b321e619849dde747 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -+++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -@@ -47,12 +47,12 @@ import net.minecraft.world.level.saveddata.maps.WorldMap; - - public class VillagerTrades { - -- public static final Map> a = (Map) SystemUtils.a((Object) Maps.newHashMap(), (hashmap) -> { -+ public static final Map> a = SystemUtils.a(Maps.newHashMap(), (hashmap) -> { // Paper - decompile fix - hashmap.put(VillagerProfession.FARMER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WHEAT, 20, 16, 2), new VillagerTrades.b(Items.POTATO, 26, 16, 2), new VillagerTrades.b(Items.CARROT, 22, 16, 2), new VillagerTrades.b(Items.BEETROOT, 15, 16, 2), new VillagerTrades.h(Items.BREAD, 1, 6, 16, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Blocks.PUMPKIN, 6, 12, 10), new VillagerTrades.h(Items.PUMPKIN_PIE, 1, 4, 5), new VillagerTrades.h(Items.APPLE, 1, 4, 16, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.COOKIE, 3, 18, 10), new VillagerTrades.b(Blocks.MELON, 4, 12, 20)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Blocks.CAKE, 1, 1, 12, 15), new VillagerTrades.i(MobEffects.NIGHT_VISION, 100, 15), new VillagerTrades.i(MobEffects.JUMP, 160, 15), new VillagerTrades.i(MobEffects.WEAKNESS, 140, 15), new VillagerTrades.i(MobEffects.BLINDNESS, 120, 15), new VillagerTrades.i(MobEffects.POISON, 280, 15), new VillagerTrades.i(MobEffects.SATURATION, 7, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.GOLDEN_CARROT, 3, 3, 30), new VillagerTrades.h(Items.GLISTERING_MELON_SLICE, 4, 3, 30)}))); -- hashmap.put(VillagerProfession.FISHERMAN, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STRING, 20, 16, 2), new VillagerTrades.b(Items.COAL, 10, 16, 2), new VillagerTrades.g(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.h(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COD, 15, 16, 10), new VillagerTrades.g(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.h(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.SALMON, 13, 16, 20), new VillagerTrades.e(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.c(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); -+ hashmap.put(VillagerProfession.FISHERMAN, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STRING, 20, 16, 2), new VillagerTrades.b(Items.COAL, 10, 16, 2), new VillagerTrades.g(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.h(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COD, 15, 16, 10), new VillagerTrades.g(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.h(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.SALMON, 13, 16, 20), new VillagerTrades.e(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.c(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); // Paper - add to ImmutableMap..builder() - hashmap.put(VillagerProfession.SHEPHERD, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Blocks.WHITE_WOOL, 18, 16, 2), new VillagerTrades.b(Blocks.BROWN_WOOL, 18, 16, 2), new VillagerTrades.b(Blocks.BLACK_WOOL, 18, 16, 2), new VillagerTrades.b(Blocks.GRAY_WOOL, 18, 16, 2), new VillagerTrades.h(Items.SHEARS, 2, 1, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WHITE_DYE, 12, 16, 10), new VillagerTrades.b(Items.GRAY_DYE, 12, 16, 10), new VillagerTrades.b(Items.BLACK_DYE, 12, 16, 10), new VillagerTrades.b(Items.LIGHT_BLUE_DYE, 12, 16, 10), new VillagerTrades.b(Items.LIME_DYE, 12, 16, 10), new VillagerTrades.h(Blocks.WHITE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.ORANGE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.MAGENTA_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.LIGHT_BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.YELLOW_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.LIME_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.PINK_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.LIGHT_GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.CYAN_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.PURPLE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.BROWN_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.GREEN_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.RED_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.BLACK_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.WHITE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.ORANGE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.MAGENTA_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.LIGHT_BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.YELLOW_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.LIME_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.PINK_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.LIGHT_GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.CYAN_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.PURPLE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.BROWN_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.GREEN_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.RED_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.BLACK_CARPET, 1, 4, 16, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.YELLOW_DYE, 12, 16, 20), new VillagerTrades.b(Items.LIGHT_GRAY_DYE, 12, 16, 20), new VillagerTrades.b(Items.ORANGE_DYE, 12, 16, 20), new VillagerTrades.b(Items.RED_DYE, 12, 16, 20), new VillagerTrades.b(Items.PINK_DYE, 12, 16, 20), new VillagerTrades.h(Blocks.WHITE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.YELLOW_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.RED_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.BLACK_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.BLUE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.BROWN_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.CYAN_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.GRAY_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.GREEN_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.LIGHT_BLUE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.LIGHT_GRAY_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.LIME_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.MAGENTA_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.ORANGE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.PINK_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.PURPLE_BED, 3, 1, 12, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.BROWN_DYE, 12, 16, 30), new VillagerTrades.b(Items.PURPLE_DYE, 12, 16, 30), new VillagerTrades.b(Items.BLUE_DYE, 12, 16, 30), new VillagerTrades.b(Items.GREEN_DYE, 12, 16, 30), new VillagerTrades.b(Items.MAGENTA_DYE, 12, 16, 30), new VillagerTrades.b(Items.CYAN_DYE, 12, 16, 30), new VillagerTrades.h(Items.WHITE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.LIGHT_BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.RED_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.PINK_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.GREEN_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.LIME_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.GRAY_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.BLACK_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.PURPLE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.MAGENTA_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.CYAN_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.BROWN_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.YELLOW_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.ORANGE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.LIGHT_GRAY_BANNER, 3, 1, 12, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.PAINTING, 2, 3, 30)}))); - hashmap.put(VillagerProfession.FLETCHER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STICK, 32, 16, 2), new VillagerTrades.h(Items.ARROW, 1, 16, 1), new VillagerTrades.g(Blocks.GRAVEL, 10, Items.FLINT, 10, 12, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.FLINT, 26, 12, 10), new VillagerTrades.h(Items.BOW, 2, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STRING, 14, 16, 20), new VillagerTrades.h(Items.CROSSBOW, 3, 1, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.FEATHER, 24, 16, 30), new VillagerTrades.e(Items.BOW, 2, 3, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.es, 8, 12, 30), new VillagerTrades.e(Items.CROSSBOW, 3, 3, 15), new VillagerTrades.j(Items.ARROW, 5, Items.TIPPED_ARROW, 5, 2, 12, 30)}))); -- hashmap.put(VillagerProfession.LIBRARIAN, a(ImmutableMap.builder().put(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PAPER, 24, 16, 2), new VillagerTrades.d(1), new VillagerTrades.h(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.BOOK, 4, 12, 10), new VillagerTrades.d(5), new VillagerTrades.h(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.INK_SAC, 5, 12, 20), new VillagerTrades.d(10), new VillagerTrades.h(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.d(15), new VillagerTrades.h(Items.CLOCK, 5, 1, 15), new VillagerTrades.h(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.NAME_TAG, 20, 1, 30)}).build())); -+ hashmap.put(VillagerProfession.LIBRARIAN, a(ImmutableMap.builder().put(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PAPER, 24, 16, 2), new VillagerTrades.d(1), new VillagerTrades.h(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.BOOK, 4, 12, 10), new VillagerTrades.d(5), new VillagerTrades.h(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.INK_SAC, 5, 12, 20), new VillagerTrades.d(10), new VillagerTrades.h(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.d(15), new VillagerTrades.h(Items.CLOCK, 5, 1, 15), new VillagerTrades.h(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.NAME_TAG, 20, 1, 30)}).build())); // Paper - add to ImmutableMap..builder() - hashmap.put(VillagerProfession.CARTOGRAPHER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PAPER, 24, 16, 2), new VillagerTrades.h(Items.MAP, 7, 1, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.dP, 11, 16, 10), new VillagerTrades.k(13, StructureGenerator.MONUMENT, MapIcon.Type.MONUMENT, 12, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COMPASS, 1, 12, 20), new VillagerTrades.k(14, StructureGenerator.MANSION, MapIcon.Type.MANSION, 12, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.ITEM_FRAME, 7, 1, 15), new VillagerTrades.h(Items.WHITE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.BLUE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.LIGHT_BLUE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.RED_BANNER, 3, 1, 15), new VillagerTrades.h(Items.PINK_BANNER, 3, 1, 15), new VillagerTrades.h(Items.GREEN_BANNER, 3, 1, 15), new VillagerTrades.h(Items.LIME_BANNER, 3, 1, 15), new VillagerTrades.h(Items.GRAY_BANNER, 3, 1, 15), new VillagerTrades.h(Items.BLACK_BANNER, 3, 1, 15), new VillagerTrades.h(Items.PURPLE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.MAGENTA_BANNER, 3, 1, 15), new VillagerTrades.h(Items.CYAN_BANNER, 3, 1, 15), new VillagerTrades.h(Items.BROWN_BANNER, 3, 1, 15), new VillagerTrades.h(Items.YELLOW_BANNER, 3, 1, 15), new VillagerTrades.h(Items.ORANGE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.LIGHT_GRAY_BANNER, 3, 1, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.GLOBE_BANNER_PATTERN, 8, 1, 30)}))); - hashmap.put(VillagerProfession.CLERIC, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.ROTTEN_FLESH, 32, 16, 2), new VillagerTrades.h(Items.REDSTONE, 1, 2, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.GOLD_INGOT, 3, 12, 10), new VillagerTrades.h(Items.LAPIS_LAZULI, 1, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.RABBIT_FOOT, 2, 12, 20), new VillagerTrades.h(Blocks.GLOWSTONE, 4, 1, 12, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.SCUTE, 4, 12, 30), new VillagerTrades.b(Items.GLASS_BOTTLE, 9, 12, 30), new VillagerTrades.h(Items.ENDER_PEARL, 5, 1, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.NETHER_WART, 22, 12, 30), new VillagerTrades.h(Items.EXPERIENCE_BOTTLE, 3, 1, 30)}))); - hashmap.put(VillagerProfession.ARMORER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COAL, 15, 16, 2), new VillagerTrades.h(new ItemStack(Items.IRON_LEGGINGS), 7, 1, 12, 1, 0.2F), new VillagerTrades.h(new ItemStack(Items.IRON_BOOTS), 4, 1, 12, 1, 0.2F), new VillagerTrades.h(new ItemStack(Items.IRON_HELMET), 5, 1, 12, 1, 0.2F), new VillagerTrades.h(new ItemStack(Items.IRON_CHESTPLATE), 9, 1, 12, 1, 0.2F)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.IRON_INGOT, 4, 12, 10), new VillagerTrades.h(new ItemStack(Items.rj), 36, 1, 12, 5, 0.2F), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_BOOTS), 1, 1, 12, 5, 0.2F), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_LEGGINGS), 3, 1, 12, 5, 0.2F)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.LAVA_BUCKET, 1, 12, 20), new VillagerTrades.b(Items.DIAMOND, 1, 12, 20), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_HELMET), 1, 1, 12, 10, 0.2F), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_CHESTPLATE), 4, 1, 12, 10, 0.2F), new VillagerTrades.h(new ItemStack(Items.SHIELD), 5, 1, 12, 10, 0.2F)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.e(Items.DIAMOND_LEGGINGS, 14, 3, 15, 0.2F), new VillagerTrades.e(Items.DIAMOND_BOOTS, 8, 3, 15, 0.2F)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.e(Items.DIAMOND_HELMET, 8, 3, 30, 0.2F), new VillagerTrades.e(Items.DIAMOND_CHESTPLATE, 16, 3, 30, 0.2F)}))); -diff --git a/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java b/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java -index 54a636a3d5fdd0107cd0a41167ab1626469fe042..5ba58bf1a47c696235e6e7a4a6815104bc23de80 100644 ---- a/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java -+++ b/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java -@@ -75,7 +75,7 @@ public class CraftingManager extends ResourceDataJson { - } - - this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { -- return (entry1.getValue()); // CraftBukkit -+ return entry1.getValue(); // CraftBukkit // Paper - decompile fix - *shrugs internally* - })); - CraftingManager.LOGGER.info("Loaded {} recipes", map1.size()); - } -diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java -index d24f97593777d6929271520f7501a800f1aadaa6..4ece69851e7b05016f52c291ce911eb791cf3a23 100644 ---- a/src/main/java/net/minecraft/world/level/IEntityAccess.java -+++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java -@@ -167,22 +167,22 @@ public interface IEntityAccess { - - @Nullable - default T a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { -- return this.a(this.a(oclass, axisalignedbb, (Predicate) null), pathfindertargetcondition, entityliving, d0, d1, d2); -+ return this.a(this.a(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix - } - - @Nullable - default T b(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { -- return this.a(this.b(oclass, axisalignedbb, (Predicate) null), pathfindertargetcondition, entityliving, d0, d1, d2); -+ return this.a(this.b(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix - } - - @Nullable - default T a(List list, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2) { - double d3 = -1.0D; - T t0 = null; -- Iterator iterator = list.iterator(); -+ Iterator iterator = list.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t1 = (EntityLiving) iterator.next(); -+ T t1 = iterator.next(); // Paper - decompile fix - - if (pathfindertargetcondition.a(entityliving, t1)) { - double d4 = t1.h(d0, d1, d2); -@@ -215,10 +215,10 @@ public interface IEntityAccess { - default List a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, AxisAlignedBB axisalignedbb) { - List list = this.a(oclass, axisalignedbb, (Predicate) null); - List list1 = Lists.newArrayList(); -- Iterator iterator = list.iterator(); -+ Iterator iterator = list.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t0 = (EntityLiving) iterator.next(); -+ T t0 = iterator.next(); // Paper - decompile fix - - if (pathfindertargetcondition.a(entityliving, t0)) { - list1.add(t0); -diff --git a/src/main/java/net/minecraft/world/level/NextTickListEntry.java b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -index 116a5e4ded3ccf935fd143f2512098c22ec2ad76..f3bcb96232d18abbcd86b079a7c5830bb30d75d2 100644 ---- a/src/main/java/net/minecraft/world/level/NextTickListEntry.java -+++ b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -@@ -38,13 +38,13 @@ public class NextTickListEntry { - return this.a.hashCode(); - } - -- public static Comparator> a() { -+ public static Comparator a() { // Paper - decompile fix - return Comparator.comparingLong((nextticklistentry) -> { -- return nextticklistentry.b; -+ return ((NextTickListEntry) nextticklistentry).b; // Paper - decompile fix - }).thenComparing((nextticklistentry) -> { -- return nextticklistentry.c; -+ return ((NextTickListEntry) nextticklistentry).c; // Paper - decompile fix - }).thenComparingLong((nextticklistentry) -> { -- return nextticklistentry.f; -+ return ((NextTickListEntry) nextticklistentry).f; // Paper - decompile fix - }); - } - -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -index 6672d74426d6a334d52f641c48d3a352c2bb6605..7147cdda756ccb3d4f6880802128f68601783883 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -@@ -49,8 +49,15 @@ import org.apache.logging.log4j.Logger; - public final class BiomeBase { - - public static final Logger LOGGER = LogManager.getLogger(); -+ // Paper start -+ private static class dProxy extends BiomeBase.d { -+ private dProxy(Precipitation biomebase_precipitation, float f, TemperatureModifier biomebase_temperaturemodifier, float f1) { -+ super(biomebase_precipitation, f, biomebase_temperaturemodifier, f1); -+ } -+ }; -+ // Paper end - public static final Codec b = RecordCodecBuilder.create((instance) -> { -- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { -+ return instance.group(dProxy.a.forGetter((biomebase) -> { // Paper - return biomebase.j; - }), BiomeBase.Geography.r.fieldOf("category").forGetter((biomebase) -> { - return biomebase.o; -@@ -67,7 +74,7 @@ public final class BiomeBase { - })).apply(instance, BiomeBase::new); - }); - public static final Codec c = RecordCodecBuilder.create((instance) -> { -- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { -+ return instance.group(dProxy.a.forGetter((biomebase) -> { // Paper - return biomebase.j; - }), BiomeBase.Geography.r.fieldOf("category").forGetter((biomebase) -> { - return biomebase.o; -diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -index a549195e67236c0146861b896fb9e4907073af58..8d13e60f40e1b760e9e69969dc3f37bc6c70dbe9 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -@@ -160,7 +160,7 @@ public class TileEntityPiston extends TileEntity implements ITickable { - private static void a(EnumDirection enumdirection, Entity entity, double d0, EnumDirection enumdirection1) { - TileEntityPiston.h.set(enumdirection); - entity.move(EnumMoveType.PISTON, new Vec3D(d0 * (double) enumdirection1.getAdjacentX(), d0 * (double) enumdirection1.getAdjacentY(), d0 * (double) enumdirection1.getAdjacentZ())); -- TileEntityPiston.h.set((Object) null); -+ TileEntityPiston.h.set(null); // Paper - decompile fix - } - - private void g(float f) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -index 074bd5f060c6bb80568b72d23ce84c27ba774578..e4b59a85ee9b435b2e86d4c7d78b7224773f6967 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -+++ b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -@@ -28,11 +28,11 @@ public abstract class IBlockDataHolder { - } else { - IBlockState iblockstate = (IBlockState) entry.getKey(); - -- return iblockstate.getName() + "=" + this.a(iblockstate, (Comparable) entry.getValue()); -+ return iblockstate.getName() + "=" + this.a((IBlockState) iblockstate, (Comparable) entry.getValue()); // Paper - decompile fix - } - } - -- private > String a(IBlockState iblockstate, Comparable comparable) { -+ private > String a(IBlockState iblockstate, T comparable) { // Paper - decompile error - return iblockstate.a(comparable); - } - }; -@@ -48,11 +48,11 @@ public abstract class IBlockDataHolder { - } - - public > S a(IBlockState iblockstate) { -- return this.set(iblockstate, (Comparable) a(iblockstate.getValues(), (Object) this.get(iblockstate))); -+ return this.set(iblockstate, a(iblockstate.getValues(), this.get(iblockstate))); // Paper - decompile error - } - - protected static T a(Collection collection, T t0) { -- Iterator iterator = collection.iterator(); -+ Iterator iterator = collection.iterator(); // Paper - - do { - if (!iterator.hasNext()) { -@@ -94,7 +94,7 @@ public abstract class IBlockDataHolder { - if (comparable == null) { - throw new IllegalArgumentException("Cannot get property " + iblockstate + " as it does not exist in " + this.c); - } else { -- return (Comparable) iblockstate.getType().cast(comparable); -+ return iblockstate.getType().cast(comparable); // Paper - decompile error - } - } - -@@ -110,7 +110,7 @@ public abstract class IBlockDataHolder { - if (comparable == null) { - throw new IllegalArgumentException("Cannot set property " + iblockstate + " as it does not exist in " + this.c); - } else if (comparable == v0) { -- return this; -+ return (S) this; // Paper - decompile error - } else { - S s0 = this.e.get(iblockstate, v0); - -@@ -162,7 +162,7 @@ public abstract class IBlockDataHolder { - return codec.dispatch("Name", (iblockdataholder) -> { - return iblockdataholder.c; - }, (object) -> { -- S s0 = (IBlockDataHolder) function.apply(object); -+ S s0 = function.apply(object); // Paper - decompile error - - return s0.getStateMap().isEmpty() ? Codec.unit(s0) : s0.d.fieldOf("Properties").codec(); - }); -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -index a6aaf0efed5a9c5e458ca04a80a7a5e71a31d886..de85894beae7ee7d276cf2af3daa77377ce131c3 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -@@ -21,10 +21,10 @@ public class BlockStateEnum & INamable> extends IBlockState - protected BlockStateEnum(String s, Class oclass, Collection collection) { - super(s, oclass); - this.a = ImmutableSet.copyOf(collection); -- Iterator iterator = collection.iterator(); -+ Iterator iterator = collection.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t0 = (Enum) iterator.next(); -+ T t0 = iterator.next(); // Paper - Decompile fix - String s1 = ((INamable) t0).getName(); - - if (this.b.containsKey(s1)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -index 3e6ba74027685c6190426c825736e84cda87ca63..e3969bad5be64bb41e2973751605d6820c16f021 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -@@ -17,12 +17,10 @@ public abstract class IBlockState> { - private final Codec> e; - - protected IBlockState(String s, Class oclass) { -- this.d = Codec.STRING.comapFlatMap((s1) -> { -- return (DataResult) this.b(s1).map(DataResult::success).orElseGet(() -> { -- return DataResult.error("Unable to read property: " + this + " with value: " + s1); -- }); -- }, this::a); -- this.e = this.d.xmap(this::b, IBlockState.a::b); -+ this.d = Codec.STRING.comapFlatMap((s1) -> this.b(s1).map(DataResult::success).orElseGet(() -> { // Paper - decompile error -+ return DataResult.error("Unable to read property: " + this + " with value: " + s1); -+ }), this::a); -+ this.e = this.d.xmap(this::b, (IBlockState.a param) -> param.b()); // Paper - decompile fix - this.a = oclass; - this.b = s; - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -index 88c2643a18165bd7a9e6e056b926d6e894ff60d4..859561a5dccba6548967b685b20e8fcfc296db2a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -@@ -89,7 +89,7 @@ public class IOWorker implements AutoCloseable { - return this.a(() -> { - try { - this.d.a(); -- return Either.left((Object) null); -+ return Either.left(null); // Paper - decompile error - } catch (Exception exception) { - IOWorker.LOGGER.warn("Failed to synchronized chunks", exception); - return Either.right(exception); -@@ -123,13 +123,13 @@ public class IOWorker implements AutoCloseable { - } - - private void c() { -- this.c.a((Object) (new PairedQueue.b(IOWorker.Priority.LOW.ordinal(), this::b))); -+ this.c.a((new PairedQueue.b(IOWorker.Priority.LOW.ordinal(), this::b))); // Paper - decompile error - } - - private void a(ChunkCoordIntPair chunkcoordintpair, IOWorker.a ioworker_a) { - try { - this.d.write(chunkcoordintpair, ioworker_a.a); -- ioworker_a.b.complete((Object) null); -+ ioworker_a.b.complete(null); // Paper - decompile fix - } catch (Exception exception) { - IOWorker.LOGGER.error("Failed to store chunk {}", chunkcoordintpair, exception); - ioworker_a.b.completeExceptionally(exception); -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index 6fb0c92e7cb6117d919af613dae87fa4e99f5081..f727cc456bd23816c4e70be83c395d1d8ca7d876 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -430,7 +430,7 @@ public class EnderDragonBattle { - } - } - -- worldgenendtrophy.b((WorldGenFeatureConfiguration) WorldGenFeatureConfiguration.k).a(this.world, this.world.getChunkProvider().getChunkGenerator(), new Random(), this.exitPortalLocation); -+ worldgenendtrophy.b(WorldGenFeatureConfiguration.k).a(this.world, this.world.getChunkProvider().getChunkGenerator(), new Random(), this.exitPortalLocation); // Paper - decompile fix - } - - private EntityEnderDragon o() { -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -index 44ad3fb2551f681b58b82e7c4f56bbc5a3b4486e..6724927be178cb9a358a9276d01894a63154b7b3 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -@@ -71,13 +71,13 @@ public abstract class StructureGenerator - public static final StructureGenerator BASTION_REMNANT = a("Bastion_Remnant", new WorldGenFeatureBastionRemnant(WorldGenFeatureVillageConfiguration.a), WorldGenStage.Decoration.SURFACE_STRUCTURES); - public static final List> t = ImmutableList.of(StructureGenerator.PILLAGER_OUTPOST, StructureGenerator.VILLAGE, StructureGenerator.NETHER_FOSSIL); - private static final MinecraftKey w = new MinecraftKey("jigsaw"); -- private static final Map x = ImmutableMap.builder().put(new MinecraftKey("nvi"), StructureGenerator.w).put(new MinecraftKey("pcp"), StructureGenerator.w).put(new MinecraftKey("bastionremnant"), StructureGenerator.w).put(new MinecraftKey("runtime"), StructureGenerator.w).build(); -+ private static final Map x = ImmutableMap.builder().put(new MinecraftKey("nvi"), StructureGenerator.w).put(new MinecraftKey("pcp"), StructureGenerator.w).put(new MinecraftKey("bastionremnant"), StructureGenerator.w).put(new MinecraftKey("runtime"), StructureGenerator.w).build(); // Paper - decompile fix - private final Codec>> y; - - private static > F a(String s, F f0, WorldGenStage.Decoration worldgenstage_decoration) { - StructureGenerator.a.put(s.toLowerCase(Locale.ROOT), f0); - StructureGenerator.u.put(f0, worldgenstage_decoration); -- return (StructureGenerator) IRegistry.a(IRegistry.STRUCTURE_FEATURE, s.toLowerCase(Locale.ROOT), (Object) f0); -+ return (F) IRegistry.>a(IRegistry.STRUCTURE_FEATURE, s.toLowerCase(Locale.ROOT), f0); // Paper - decomp fix - } - - public StructureGenerator(Codec codec) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -index 52564cce4146f49a906729b3ed9488a7a829ea3f..befc8f846c772d58ee687ad427bb71206b4dc43e 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -@@ -34,10 +34,10 @@ public class LightEngineStorageSky extends LightEngineStorage= l) { -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -index 45c1d79e0bb2fcffea31513c3d003d28140146b9..3910daeaa177639fa8055301304634c2014dc20f 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -@@ -44,7 +44,7 @@ public class WorldPersistentData { - if (t0 != null) { - return t0; - } else { -- T t1 = (PersistentBase) supplier.get(); -+ T t1 = supplier.get(); // Paper - decompile fix - - this.a(t1); - return t1; -@@ -53,7 +53,7 @@ public class WorldPersistentData { - - @Nullable - public T b(Supplier supplier, String s) { -- PersistentBase persistentbase = (PersistentBase) this.data.get(s); -+ T persistentbase = (T) this.data.get(s); // Paper - decompile fix - - if (persistentbase == null && !this.data.containsKey(s)) { - persistentbase = this.c(supplier, s); -@@ -69,7 +69,7 @@ public class WorldPersistentData { - File file = this.a(s); - - if (file.exists()) { -- T t0 = (PersistentBase) supplier.get(); -+ T t0 = supplier.get(); // Paper - decompile fix - NBTTagCompound nbttagcompound = this.a(s, SharedConstants.getGameVersion().getWorldVersion()); - - t0.a(nbttagcompound.getCompound("data")); -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java -index 9421e175fffab7014461aa02e7e36d719837ec11..b6abbe9f1de66cd8e9d2e7127813ce56a0446faf 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java -@@ -43,7 +43,7 @@ public abstract class LootEntryAbstract implements LootEntryChildren { - - // CraftBukkit start - @Override -- public final void a(JsonObject jsonobject, T t0, JsonSerializationContext jsonserializationcontext) { -+ public void a(JsonObject jsonobject, T t0, JsonSerializationContext jsonserializationcontext) { // Paper - remove final - if (!org.apache.commons.lang3.ArrayUtils.isEmpty(t0.d)) { - jsonobject.add("conditions", jsonserializationcontext.serialize(t0.d)); - } -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -index 0e3fe138fc11bd7e648296922c651cecaab8e71e..ceb9a1e1b1d55a0a8cd74189450f356b9ad4c46c 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -@@ -132,7 +132,7 @@ public abstract class LootSelectorEntry extends LootEntryAbstract { - @Override - public T b(LootItemFunction.a lootitemfunction_a) { - this.c.add(lootitemfunction_a.b()); -- return (LootSelectorEntry.a) this.d(); -+ return this.d(); // Paper - decompile fix - } - - protected LootItemFunction[] a() { -@@ -141,12 +141,12 @@ public abstract class LootSelectorEntry extends LootEntryAbstract { - - public T a(int i) { - this.a = i; -- return (LootSelectorEntry.a) this.d(); -+ return this.d(); // Paper - decompile fix - } - - public T b(int i) { - this.b = i; -- return (LootSelectorEntry.a) this.d(); -+ return this.d(); // Paper - decompile fix - } - } - -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -index f516e7440ed306b1ace9b35ae82f70ca69df51f3..38125a60bad4830db9de3580ab6d85fd122a0689 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -@@ -89,7 +89,7 @@ public class LootItemFunctionExplorationMap extends LootItemFunctionConditional - public b() {} - - public void a(JsonObject jsonobject, LootItemFunctionExplorationMap lootitemfunctionexplorationmap, JsonSerializationContext jsonserializationcontext) { -- super.a(jsonobject, (LootItemFunctionConditional) lootitemfunctionexplorationmap, jsonserializationcontext); -+ super.a(jsonobject, lootitemfunctionexplorationmap, jsonserializationcontext); // Paper - decompile fix - if (!lootitemfunctionexplorationmap.e.equals(LootItemFunctionExplorationMap.a)) { - jsonobject.add("destination", jsonserializationcontext.serialize(lootitemfunctionexplorationmap.e.i())); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -index afd30320da51bf467d66e94f682936ed8db96d90..c58d380b96e81d65d7c254a9e53017e5157769b0 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -@@ -38,7 +38,7 @@ public final class VoxelShapeMergerList implements VoxelShapeMerger { - double d1 = flag4 ? doublelist.getDouble(i++) : doublelist1.getDouble(j++); - - if ((i != 0 && flag2 || flag4 || flag1) && (j != 0 && flag3 || !flag4 || flag)) { -- if (d0 < d1 - 1.0E-7D) { -+ if (!(d0 >= d1 - 1.0E-7D)) { // Paper - decompile error - welcome to hell - this.b.add(i - 1); - this.c.add(j - 1); - this.a.add(d1); diff --git a/Unmapped-Spigot-Server-Patches/0004-MC-Utils.patch b/Unmapped-Spigot-Server-Patches/0004-MC-Utils.patch deleted file mode 100644 index fd72ff629d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0004-MC-Utils.patch +++ /dev/null @@ -1,4850 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:55:47 -0400 -Subject: [PATCH] MC Utils - - -diff --git a/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4029dc68cf35d63aa70c4a76c35bf65a7fc6358f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java -@@ -0,0 +1,68 @@ -+package com.destroystokyo.paper.util.concurrent; -+ -+import java.util.concurrent.atomic.AtomicLong; -+ -+/** -+ * copied from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/lock/WeakSeqLock.java -+ * @author Spottedleaf -+ */ -+public final class WeakSeqLock { -+ // TODO when the switch to J11 is made, nuke this class from orbit -+ -+ protected final AtomicLong lock = new AtomicLong(); -+ -+ public WeakSeqLock() { -+ //VarHandle.storeStoreFence(); // warn: usages must be checked to ensure this behaviour isn't needed -+ } -+ -+ public void acquireWrite() { -+ // must be release-type write -+ this.lock.lazySet(this.lock.get() + 1); -+ } -+ -+ public boolean canRead(final long read) { -+ return (read & 1) == 0; -+ } -+ -+ public boolean tryAcquireWrite() { -+ this.acquireWrite(); -+ return true; -+ } -+ -+ public void releaseWrite() { -+ // must be acquire-type write -+ final long lock = this.lock.get(); // volatile here acts as store-store -+ this.lock.lazySet(lock + 1); -+ } -+ -+ public void abortWrite() { -+ // must be acquire-type write -+ final long lock = this.lock.get(); // volatile here acts as store-store -+ this.lock.lazySet(lock ^ 1); -+ } -+ -+ public long acquireRead() { -+ int failures = 0; -+ long curr; -+ -+ for (curr = this.lock.get(); !this.canRead(curr); curr = this.lock.get()) { -+ // without j11, our only backoff is the yield() call... -+ -+ if (++failures > 5_000) { /* TODO determine a threshold */ -+ Thread.yield(); -+ } -+ /* Better waiting is beyond the scope of this lock; if it is needed the lock is being misused */ -+ } -+ -+ //VarHandle.loadLoadFence(); // volatile acts as the load-load barrier -+ return curr; -+ } -+ -+ public boolean tryReleaseRead(final long read) { -+ return this.lock.get() == read; // volatile acts as the load-load barrier -+ } -+ -+ public long getSequentialCounter() { -+ return this.lock.get(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java -new file mode 100644 -index 0000000000000000000000000000000000000000..59868f37d14bbc0ece0836095cdad148778995e6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java -@@ -0,0 +1,162 @@ -+package com.destroystokyo.paper.util.map; -+ -+import com.destroystokyo.paper.util.concurrent.WeakSeqLock; -+import it.unimi.dsi.fastutil.longs.Long2IntMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import it.unimi.dsi.fastutil.longs.LongIterator; -+import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -+import it.unimi.dsi.fastutil.objects.ObjectIterator; -+ -+/** -+ * @author Spottedleaf -+ */ -+public class QueuedChangesMapLong2Int { -+ -+ protected final Long2IntOpenHashMap updatingMap; -+ protected final Long2IntOpenHashMap visibleMap; -+ protected final Long2IntOpenHashMap queuedPuts; -+ protected final LongOpenHashSet queuedRemove; -+ -+ protected int queuedDefaultReturnValue; -+ -+ // we use a seqlock as writes are not common. -+ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); -+ -+ public QueuedChangesMapLong2Int() { -+ this(16, 0.75f); -+ } -+ -+ public QueuedChangesMapLong2Int(final int capacity, final float loadFactor) { -+ this.updatingMap = new Long2IntOpenHashMap(capacity, loadFactor); -+ this.visibleMap = new Long2IntOpenHashMap(capacity, loadFactor); -+ this.queuedPuts = new Long2IntOpenHashMap(); -+ this.queuedRemove = new LongOpenHashSet(); -+ } -+ -+ public void queueDefaultReturnValue(final int dfl) { -+ this.queuedDefaultReturnValue = dfl; -+ this.updatingMap.defaultReturnValue(dfl); -+ } -+ -+ public int queueUpdate(final long k, final int v) { -+ this.queuedRemove.remove(k); -+ this.queuedPuts.put(k, v); -+ -+ return this.updatingMap.put(k, v); -+ } -+ -+ public int queueRemove(final long k) { -+ this.queuedPuts.remove(k); -+ this.queuedRemove.add(k); -+ -+ return this.updatingMap.remove(k); -+ } -+ -+ public int getUpdating(final long k) { -+ return this.updatingMap.get(k); -+ } -+ -+ public int getVisible(final long k) { -+ return this.visibleMap.get(k); -+ } -+ -+ public int getVisibleAsync(final long k) { -+ long readlock; -+ int ret = 0; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ try { -+ ret = this.visibleMap.get(k); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // ignore... -+ continue; -+ } -+ -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ public boolean performUpdates() { -+ this.updatingMapSeqLock.acquireWrite(); -+ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); -+ this.updatingMapSeqLock.releaseWrite(); -+ -+ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { -+ return false; -+ } -+ -+ // update puts -+ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); -+ while (iterator0.hasNext()) { -+ final Long2IntMap.Entry entry = iterator0.next(); -+ final long key = entry.getLongKey(); -+ final int val = entry.getIntValue(); -+ -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ this.visibleMap.put(key, val); -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+ -+ this.queuedPuts.clear(); -+ -+ final LongIterator iterator1 = this.queuedRemove.iterator(); -+ while (iterator1.hasNext()) { -+ final long key = iterator1.nextLong(); -+ -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ this.visibleMap.remove(key); -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+ -+ this.queuedRemove.clear(); -+ -+ return true; -+ } -+ -+ public boolean performUpdatesLockMap() { -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); -+ -+ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { -+ return false; -+ } -+ -+ // update puts -+ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); -+ while (iterator0.hasNext()) { -+ final Long2IntMap.Entry entry = iterator0.next(); -+ final long key = entry.getLongKey(); -+ final int val = entry.getIntValue(); -+ -+ this.visibleMap.put(key, val); -+ } -+ -+ this.queuedPuts.clear(); -+ -+ final LongIterator iterator1 = this.queuedRemove.iterator(); -+ while (iterator1.hasNext()) { -+ final long key = iterator1.nextLong(); -+ -+ this.visibleMap.remove(key); -+ } -+ -+ this.queuedRemove.clear(); -+ -+ return true; -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7bab31a312463cc963d9621cdc543a281459bd32 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java -@@ -0,0 +1,202 @@ -+package com.destroystokyo.paper.util.map; -+ -+import com.destroystokyo.paper.util.concurrent.WeakSeqLock; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator; -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.List; -+ -+/** -+ * @author Spottedleaf -+ */ -+public class QueuedChangesMapLong2Object { -+ -+ protected static final Object REMOVED = new Object(); -+ -+ protected final Long2ObjectLinkedOpenHashMap updatingMap; -+ protected final Long2ObjectLinkedOpenHashMap visibleMap; -+ protected final Long2ObjectLinkedOpenHashMap queuedChanges; -+ -+ // we use a seqlock as writes are not common. -+ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); -+ -+ public QueuedChangesMapLong2Object() { -+ this(16, 0.75f); // dfl for fastutil -+ } -+ -+ public QueuedChangesMapLong2Object(final int capacity, final float loadFactor) { -+ this.updatingMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); -+ this.visibleMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); -+ this.queuedChanges = new Long2ObjectLinkedOpenHashMap<>(); -+ } -+ -+ public V queueUpdate(final long k, final V value) { -+ this.queuedChanges.put(k, value); -+ return this.updatingMap.put(k, value); -+ } -+ -+ public V queueRemove(final long k) { -+ this.queuedChanges.put(k, REMOVED); -+ return this.updatingMap.remove(k); -+ } -+ -+ public V getUpdating(final long k) { -+ return this.updatingMap.get(k); -+ } -+ -+ public boolean updatingContainsKey(final long k) { -+ return this.updatingMap.containsKey(k); -+ } -+ -+ public V getVisible(final long k) { -+ return this.visibleMap.get(k); -+ } -+ -+ public boolean visibleContainsKey(final long k) { -+ return this.visibleMap.containsKey(k); -+ } -+ -+ public V getVisibleAsync(final long k) { -+ long readlock; -+ V ret = null; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ -+ try { -+ ret = this.visibleMap.get(k); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // ignore... -+ continue; -+ } -+ -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ public boolean visibleContainsKeyAsync(final long k) { -+ long readlock; -+ boolean ret = false; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ -+ try { -+ ret = this.visibleMap.containsKey(k); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // ignore... -+ continue; -+ } -+ -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ public Long2ObjectLinkedOpenHashMap getVisibleMap() { -+ return this.visibleMap; -+ } -+ -+ public Long2ObjectLinkedOpenHashMap getUpdatingMap() { -+ return this.updatingMap; -+ } -+ -+ public int getVisibleSize() { -+ return this.visibleMap.size(); -+ } -+ -+ public int getVisibleSizeAsync() { -+ long readlock; -+ int ret; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ ret = this.visibleMap.size(); -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map -+ public Collection getUpdatingValues() { -+ return this.updatingMap.values(); -+ } -+ -+ public List getUpdatingValuesCopy() { -+ return new ArrayList<>(this.updatingMap.values()); -+ } -+ -+ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map -+ public Collection getVisibleValues() { -+ return this.visibleMap.values(); -+ } -+ -+ public List getVisibleValuesCopy() { -+ return new ArrayList<>(this.visibleMap.values()); -+ } -+ -+ public boolean performUpdates() { -+ if (this.queuedChanges.isEmpty()) { -+ return false; -+ } -+ -+ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); -+ while (iterator.hasNext()) { -+ final Long2ObjectMap.Entry entry = iterator.next(); -+ final long key = entry.getLongKey(); -+ final Object val = entry.getValue(); -+ -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ if (val == REMOVED) { -+ this.visibleMap.remove(key); -+ } else { -+ this.visibleMap.put(key, (V)val); -+ } -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+ -+ this.queuedChanges.clear(); -+ return true; -+ } -+ -+ public boolean performUpdatesLockMap() { -+ if (this.queuedChanges.isEmpty()) { -+ return false; -+ } -+ -+ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); -+ -+ try { -+ this.updatingMapSeqLock.acquireWrite(); -+ -+ while (iterator.hasNext()) { -+ final Long2ObjectMap.Entry entry = iterator.next(); -+ final long key = entry.getLongKey(); -+ final Object val = entry.getValue(); -+ -+ if (val == REMOVED) { -+ this.visibleMap.remove(key); -+ } else { -+ this.visibleMap.put(key, (V)val); -+ } -+ } -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ -+ this.queuedChanges.clear(); -+ return true; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..bf63a0e87f8c9529e473269c0626051c81bb04ea ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java -@@ -0,0 +1,128 @@ -+package com.destroystokyo.paper.util.maplist; -+ -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import net.minecraft.world.level.chunk.Chunk; -+import java.util.Arrays; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+ -+// list with O(1) remove & contains -+/** -+ * @author Spottedleaf -+ */ -+public final class ChunkList implements Iterable { -+ -+ protected final Long2IntOpenHashMap chunkToIndex = new Long2IntOpenHashMap(2, 0.8f); -+ { -+ this.chunkToIndex.defaultReturnValue(Integer.MIN_VALUE); -+ } -+ -+ protected static final Chunk[] EMPTY_LIST = new Chunk[0]; -+ -+ protected Chunk[] chunks = EMPTY_LIST; -+ protected int count; -+ -+ public int size() { -+ return this.count; -+ } -+ -+ public boolean contains(final Chunk chunk) { -+ return this.chunkToIndex.containsKey(chunk.coordinateKey); -+ } -+ -+ public boolean remove(final Chunk chunk) { -+ final int index = this.chunkToIndex.remove(chunk.coordinateKey); -+ if (index == Integer.MIN_VALUE) { -+ return false; -+ } -+ -+ // move the entity at the end to this index -+ final int endIndex = --this.count; -+ final Chunk end = this.chunks[endIndex]; -+ if (index != endIndex) { -+ // not empty after this call -+ this.chunkToIndex.put(end.coordinateKey, index); // update index -+ } -+ this.chunks[index] = end; -+ this.chunks[endIndex] = null; -+ -+ return true; -+ } -+ -+ public boolean add(final Chunk chunk) { -+ final int count = this.count; -+ final int currIndex = this.chunkToIndex.putIfAbsent(chunk.coordinateKey, count); -+ -+ if (currIndex != Integer.MIN_VALUE) { -+ return false; // already in this list -+ } -+ -+ Chunk[] list = this.chunks; -+ -+ if (list.length == count) { -+ // resize required -+ list = this.chunks = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative -+ } -+ -+ list[count] = chunk; -+ this.count = count + 1; -+ -+ return true; -+ } -+ -+ public Chunk getChecked(final int index) { -+ if (index < 0 || index >= this.count) { -+ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); -+ } -+ return this.chunks[index]; -+ } -+ -+ public Chunk getUnchecked(final int index) { -+ return this.chunks[index]; -+ } -+ -+ public Chunk[] getRawData() { -+ return this.chunks; -+ } -+ -+ public void clear() { -+ this.chunkToIndex.clear(); -+ Arrays.fill(this.chunks, 0, this.count, null); -+ this.count = 0; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator() { -+ -+ Chunk lastRet; -+ int current; -+ -+ @Override -+ public boolean hasNext() { -+ return this.current < ChunkList.this.count; -+ } -+ -+ @Override -+ public Chunk next() { -+ if (this.current >= ChunkList.this.count) { -+ throw new NoSuchElementException(); -+ } -+ return this.lastRet = ChunkList.this.chunks[this.current++]; -+ } -+ -+ @Override -+ public void remove() { -+ final Chunk lastRet = this.lastRet; -+ -+ if (lastRet == null) { -+ throw new IllegalStateException(); -+ } -+ this.lastRet = null; -+ -+ ChunkList.this.remove(lastRet); -+ --this.current; -+ } -+ }; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0133ea6feb1ab88f021f66855669f58367e7420b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java -@@ -0,0 +1,128 @@ -+package com.destroystokyo.paper.util.maplist; -+ -+import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -+import net.minecraft.world.entity.Entity; -+import java.util.Arrays; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+ -+// list with O(1) remove & contains -+/** -+ * @author Spottedleaf -+ */ -+public final class EntityList implements Iterable { -+ -+ protected final Int2IntOpenHashMap entityToIndex = new Int2IntOpenHashMap(2, 0.8f); -+ { -+ this.entityToIndex.defaultReturnValue(Integer.MIN_VALUE); -+ } -+ -+ protected static final Entity[] EMPTY_LIST = new Entity[0]; -+ -+ protected Entity[] entities = EMPTY_LIST; -+ protected int count; -+ -+ public int size() { -+ return this.count; -+ } -+ -+ public boolean contains(final Entity entity) { -+ return this.entityToIndex.containsKey(entity.getId()); -+ } -+ -+ public boolean remove(final Entity entity) { -+ final int index = this.entityToIndex.remove(entity.getId()); -+ if (index == Integer.MIN_VALUE) { -+ return false; -+ } -+ -+ // move the entity at the end to this index -+ final int endIndex = --this.count; -+ final Entity end = this.entities[endIndex]; -+ if (index != endIndex) { -+ // not empty after this call -+ this.entityToIndex.put(end.getId(), index); // update index -+ } -+ this.entities[index] = end; -+ this.entities[endIndex] = null; -+ -+ return true; -+ } -+ -+ public boolean add(final Entity entity) { -+ final int count = this.count; -+ final int currIndex = this.entityToIndex.putIfAbsent(entity.getId(), count); -+ -+ if (currIndex != Integer.MIN_VALUE) { -+ return false; // already in this list -+ } -+ -+ Entity[] list = this.entities; -+ -+ if (list.length == count) { -+ // resize required -+ list = this.entities = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative -+ } -+ -+ list[count] = entity; -+ this.count = count + 1; -+ -+ return true; -+ } -+ -+ public Entity getChecked(final int index) { -+ if (index < 0 || index >= this.count) { -+ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); -+ } -+ return this.entities[index]; -+ } -+ -+ public Entity getUnchecked(final int index) { -+ return this.entities[index]; -+ } -+ -+ public Entity[] getRawData() { -+ return this.entities; -+ } -+ -+ public void clear() { -+ this.entityToIndex.clear(); -+ Arrays.fill(this.entities, 0, this.count, null); -+ this.count = 0; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator() { -+ -+ Entity lastRet; -+ int current; -+ -+ @Override -+ public boolean hasNext() { -+ return this.current < EntityList.this.count; -+ } -+ -+ @Override -+ public Entity next() { -+ if (this.current >= EntityList.this.count) { -+ throw new NoSuchElementException(); -+ } -+ return this.lastRet = EntityList.this.entities[this.current++]; -+ } -+ -+ @Override -+ public void remove() { -+ final Entity lastRet = this.lastRet; -+ -+ if (lastRet == null) { -+ throw new IllegalStateException(); -+ } -+ this.lastRet = null; -+ -+ EntityList.this.remove(lastRet); -+ --this.current; -+ } -+ }; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d9fdc8196e53518ceac3aeb7bf3b98a0bd348f8f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java -@@ -0,0 +1,128 @@ -+package com.destroystokyo.paper.util.maplist; -+ -+import it.unimi.dsi.fastutil.longs.LongIterator; -+import it.unimi.dsi.fastutil.shorts.Short2LongOpenHashMap; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.ChunkSection; -+import net.minecraft.world.level.chunk.DataPaletteGlobal; -+import java.util.Arrays; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class IBlockDataList { -+ -+ static final DataPaletteGlobal GLOBAL_PALETTE = (DataPaletteGlobal) ChunkSection.GLOBAL_PALETTE; -+ -+ // map of location -> (index | (location << 16) | (palette id << 32)) -+ private final Short2LongOpenHashMap map = new Short2LongOpenHashMap(2, 0.8f); -+ { -+ this.map.defaultReturnValue(Long.MAX_VALUE); -+ } -+ -+ private static final long[] EMPTY_LIST = new long[0]; -+ -+ private long[] byIndex = EMPTY_LIST; -+ private int size; -+ -+ public static int getLocationKey(final int x, final int y, final int z) { -+ return (x & 15) | (((z & 15) << 4)) | ((y & 255) << (4 + 4)); -+ } -+ -+ public static IBlockData getBlockDataFromRaw(final long raw) { -+ return GLOBAL_PALETTE.getObject((int)(raw >>> 32)); -+ } -+ -+ public static int getIndexFromRaw(final long raw) { -+ return (int)(raw & 0xFFFF); -+ } -+ -+ public static int getLocationFromRaw(final long raw) { -+ return (int)((raw >>> 16) & 0xFFFF); -+ } -+ -+ public static long getRawFromValues(final int index, final int location, final IBlockData data) { -+ return (long)index | ((long)location << 16) | (((long)GLOBAL_PALETTE.getOrCreateIdFor(data)) << 32); -+ } -+ -+ public static long setIndexRawValues(final long value, final int index) { -+ return value & ~(0xFFFF) | (index); -+ } -+ -+ public long add(final int x, final int y, final int z, final IBlockData data) { -+ return this.add(getLocationKey(x, y, z), data); -+ } -+ -+ public long add(final int location, final IBlockData data) { -+ final long curr = this.map.get((short)location); -+ -+ if (curr == Long.MAX_VALUE) { -+ final int index = this.size++; -+ final long raw = getRawFromValues(index, location, data); -+ this.map.put((short)location, raw); -+ -+ if (index >= this.byIndex.length) { -+ this.byIndex = Arrays.copyOf(this.byIndex, (int)Math.max(4L, this.byIndex.length * 2L)); -+ } -+ -+ this.byIndex[index] = raw; -+ return raw; -+ } else { -+ final int index = getIndexFromRaw(curr); -+ final long raw = this.byIndex[index] = getRawFromValues(index, location, data); -+ -+ this.map.put((short)location, raw); -+ -+ return raw; -+ } -+ } -+ -+ public long remove(final int x, final int y, final int z) { -+ return this.remove(getLocationKey(x, y, z)); -+ } -+ -+ public long remove(final int location) { -+ final long ret = this.map.remove((short)location); -+ final int index = getIndexFromRaw(ret); -+ if (ret == Long.MAX_VALUE) { -+ return ret; -+ } -+ -+ // move the entry at the end to this index -+ final int endIndex = --this.size; -+ final long end = this.byIndex[endIndex]; -+ if (index != endIndex) { -+ // not empty after this call -+ this.map.put((short)getLocationFromRaw(end), setIndexRawValues(end, index)); -+ } -+ this.byIndex[index] = end; -+ this.byIndex[endIndex] = 0L; -+ -+ return ret; -+ } -+ -+ public int size() { -+ return this.size; -+ } -+ -+ public long getRaw(final int index) { -+ return this.byIndex[index]; -+ } -+ -+ public int getLocation(final int index) { -+ return getLocationFromRaw(this.getRaw(index)); -+ } -+ -+ public IBlockData getData(final int index) { -+ return getBlockDataFromRaw(this.getRaw(index)); -+ } -+ -+ public void clear() { -+ this.size = 0; -+ this.map.clear(); -+ } -+ -+ public LongIterator getRawIterator() { -+ return this.map.values().iterator(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c3b936f54b3fff418c265639ef223292ccc89356 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java -@@ -0,0 +1,230 @@ -+package com.destroystokyo.paper.util.math; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class IntegerUtil { -+ -+ public static final int HIGH_BIT_U32 = Integer.MIN_VALUE; -+ public static final long HIGH_BIT_U64 = Long.MIN_VALUE; -+ -+ public static int ceilLog2(final int value) { -+ return Integer.SIZE - Integer.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros -+ } -+ -+ public static long ceilLog2(final long value) { -+ return Long.SIZE - Long.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros -+ } -+ -+ public static int floorLog2(final int value) { -+ // xor is optimized subtract for 2^n -1 -+ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) -+ return (Integer.SIZE - 1) ^ Integer.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros -+ } -+ -+ public static int floorLog2(final long value) { -+ // xor is optimized subtract for 2^n -1 -+ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) -+ return (Long.SIZE - 1) ^ Long.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros -+ } -+ -+ public static int roundCeilLog2(final int value) { -+ // optimized variant of 1 << (32 - leading(val - 1)) -+ // given -+ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) -+ // 1 << (32 - leading(val - 1)) = HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) -+ // HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) -+ // HIGH_BIT_32 >>> (31 - 32 + leading(val - 1)) -+ // HIGH_BIT_32 >>> (-1 + leading(val - 1)) -+ return HIGH_BIT_U32 >>> (Integer.numberOfLeadingZeros(value - 1) - 1); -+ } -+ -+ public static long roundCeilLog2(final long value) { -+ // see logic documented above -+ return HIGH_BIT_U64 >>> (Long.numberOfLeadingZeros(value - 1) - 1); -+ } -+ -+ public static int roundFloorLog2(final int value) { -+ // optimized variant of 1 << (31 - leading(val)) -+ // given -+ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) -+ // 1 << (31 - leading(val)) = HIGH_BIT_32 >> (31 - (31 - leading(val))) -+ // HIGH_BIT_32 >> (31 - (31 - leading(val))) -+ // HIGH_BIT_32 >> (31 - 31 + leading(val)) -+ return HIGH_BIT_U32 >>> Integer.numberOfLeadingZeros(value); -+ } -+ -+ public static long roundFloorLog2(final long value) { -+ // see logic documented above -+ return HIGH_BIT_U64 >>> Long.numberOfLeadingZeros(value); -+ } -+ -+ public static boolean isPowerOfTwo(final int n) { -+ // 2^n has one bit -+ // note: this rets true for 0 still -+ return IntegerUtil.getTrailingBit(n) == n; -+ } -+ -+ public static boolean isPowerOfTwo(final long n) { -+ // 2^n has one bit -+ // note: this rets true for 0 still -+ return IntegerUtil.getTrailingBit(n) == n; -+ } -+ -+ -+ public static int getTrailingBit(final int n) { -+ return -n & n; -+ } -+ -+ public static long getTrailingBit(final long n) { -+ return -n & n; -+ } -+ -+ public static int trailingZeros(final int n) { -+ return Integer.numberOfTrailingZeros(n); -+ } -+ -+ public static long trailingZeros(final long n) { -+ return Long.numberOfTrailingZeros(n); -+ } -+ -+ // from hacker's delight (signed division magic value) -+ public static int getDivisorMultiple(final long numbers) { -+ return (int)(numbers >>> 32); -+ } -+ -+ // from hacker's delight (signed division magic value) -+ public static int getDivisorShift(final long numbers) { -+ return (int)numbers; -+ } -+ -+ // copied from hacker's delight (signed division magic value) -+ // http://www.hackersdelight.org/hdcodetxt/magic.c.txt -+ public static long getDivisorNumbers(final int d) { -+ final int ad = IntegerUtil.branchlessAbs(d); -+ -+ if (ad < 2) { -+ throw new IllegalArgumentException("|number| must be in [2, 2^31 -1], not: " + d); -+ } -+ -+ final int two31 = 0x80000000; -+ final long mask = 0xFFFFFFFFL; // mask for enforcing unsigned behaviour -+ -+ int p = 31; -+ -+ // all these variables are UNSIGNED! -+ int t = two31 + (d >>> 31); -+ int anc = t - 1 - t%ad; -+ int q1 = (int)((two31 & mask)/(anc & mask)); -+ int r1 = two31 - q1*anc; -+ int q2 = (int)((two31 & mask)/(ad & mask)); -+ int r2 = two31 - q2*ad; -+ int delta; -+ -+ do { -+ p = p + 1; -+ q1 = 2*q1; // Update q1 = 2**p/|nc|. -+ r1 = 2*r1; // Update r1 = rem(2**p, |nc|). -+ if ((r1 & mask) >= (anc & mask)) {// (Must be an unsigned comparison here) -+ q1 = q1 + 1; -+ r1 = r1 - anc; -+ } -+ q2 = 2*q2; // Update q2 = 2**p/|d|. -+ r2 = 2*r2; // Update r2 = rem(2**p, |d|). -+ if ((r2 & mask) >= (ad & mask)) {// (Must be an unsigned comparison here) -+ q2 = q2 + 1; -+ r2 = r2 - ad; -+ } -+ delta = ad - r2; -+ } while ((q1 & mask) < (delta & mask) || (q1 == delta && r1 == 0)); -+ -+ int magicNum = q2 + 1; -+ if (d < 0) { -+ magicNum = -magicNum; -+ } -+ int shift = p - 32; -+ return ((long)magicNum << 32) | shift; -+ } -+ -+ public static int branchlessAbs(final int val) { -+ // -n = -1 ^ n + 1 -+ final int mask = val >> (Integer.SIZE - 1); // -1 if < 0, 0 if >= 0 -+ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 -+ } -+ -+ public static long branchlessAbs(final long val) { -+ // -n = -1 ^ n + 1 -+ final long mask = val >> (Long.SIZE - 1); // -1 if < 0, 0 if >= 0 -+ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 -+ } -+ -+ //https://github.com/skeeto/hash-prospector for hash functions -+ -+ //score = ~590.47984224483832 -+ public static int hash0(int x) { -+ x *= 0x36935555; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ //score = ~310.01596637036749 -+ public static int hash1(int x) { -+ x ^= x >>> 15; -+ x *= 0x356aaaad; -+ x ^= x >>> 17; -+ return x; -+ } -+ -+ public static int hash2(int x) { -+ x ^= x >>> 16; -+ x *= 0x7feb352d; -+ x ^= x >>> 15; -+ x *= 0x846ca68b; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ public static int hash3(int x) { -+ x ^= x >>> 17; -+ x *= 0xed5ad4bb; -+ x ^= x >>> 11; -+ x *= 0xac4c1b51; -+ x ^= x >>> 15; -+ x *= 0x31848bab; -+ x ^= x >>> 14; -+ return x; -+ } -+ -+ //score = ~365.79959673201887 -+ public static long hash1(long x) { -+ x ^= x >>> 27; -+ x *= 0xb24924b71d2d354bL; -+ x ^= x >>> 28; -+ return x; -+ } -+ -+ //h2 hash -+ public static long hash2(long x) { -+ x ^= x >>> 32; -+ x *= 0xd6e8feb86659fd93L; -+ x ^= x >>> 32; -+ x *= 0xd6e8feb86659fd93L; -+ x ^= x >>> 32; -+ return x; -+ } -+ -+ public static long hash3(long x) { -+ x ^= x >>> 45; -+ x *= 0xc161abe5704b6c79L; -+ x ^= x >>> 41; -+ x *= 0xe3e5389aedbc90f7L; -+ x ^= x >>> 56; -+ x *= 0x1f9aba75a52db073L; -+ x ^= x >>> 53; -+ return x; -+ } -+ -+ private IntegerUtil() { -+ throw new RuntimeException(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..24407a3e653ba32ef6b921c346571ec734a72245 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java -@@ -0,0 +1,453 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import com.destroystokyo.paper.util.math.IntegerUtil; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import javax.annotation.Nullable; -+import java.util.Iterator; -+ -+/** @author Spottedleaf */ -+public abstract class AreaMap { -+ -+ /* Tested via https://gist.github.com/Spottedleaf/520419c6f41ef348fe9926ce674b7217 */ -+ -+ protected final Object2LongOpenHashMap objectToLastCoordinate = new Object2LongOpenHashMap<>(); -+ protected final Object2IntOpenHashMap objectToViewDistance = new Object2IntOpenHashMap<>(); -+ -+ { -+ this.objectToViewDistance.defaultReturnValue(-1); -+ this.objectToLastCoordinate.defaultReturnValue(Long.MIN_VALUE); -+ } -+ -+ // we use linked for better iteration. -+ // map of: coordinate to set of objects in coordinate -+ protected final Long2ObjectOpenHashMap> areaMap = new Long2ObjectOpenHashMap<>(1024, 0.7f); -+ protected final PooledLinkedHashSets pooledHashSets; -+ -+ protected final ChangeCallback addCallback; -+ protected final ChangeCallback removeCallback; -+ protected final ChangeSourceCallback changeSourceCallback; -+ -+ public AreaMap() { -+ this(new PooledLinkedHashSets<>()); -+ } -+ -+ // let users define a "global" or "shared" pooled sets if they wish -+ public AreaMap(final PooledLinkedHashSets pooledHashSets) { -+ this(pooledHashSets, null, null); -+ } -+ -+ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback) { -+ this(pooledHashSets, addCallback, removeCallback, null); -+ } -+ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { -+ this.pooledHashSets = pooledHashSets; -+ this.addCallback = addCallback; -+ this.removeCallback = removeCallback; -+ this.changeSourceCallback = changeSourceCallback; -+ } -+ -+ @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final long key) { -+ return this.areaMap.get(key); -+ } -+ -+ @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final ChunkCoordIntPair chunkPos) { -+ return this.areaMap.get(MCUtil.getCoordinateKey(chunkPos)); -+ } -+ -+ @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final int chunkX, final int chunkZ) { -+ return this.areaMap.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); -+ } -+ -+ // Long.MIN_VALUE indicates the object is not mapped -+ public final long getLastCoordinate(final E object) { -+ return this.objectToLastCoordinate.getOrDefault(object, Long.MIN_VALUE); -+ } -+ -+ // -1 indicates the object is not mapped -+ public final int getLastViewDistance(final E object) { -+ return this.objectToViewDistance.getOrDefault(object, -1); -+ } -+ -+ // returns the total number of mapped chunks -+ public final int size() { -+ return this.areaMap.size(); -+ } -+ -+ public final void addOrUpdate(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int oldViewDistance = this.objectToViewDistance.put(object, viewDistance); -+ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ final long oldPos = this.objectToLastCoordinate.put(object, newPos); -+ -+ if (oldViewDistance == -1) { -+ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); -+ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); -+ } else { -+ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); -+ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); -+ } -+ //this.validate(object, viewDistance); -+ } -+ -+ public final boolean update(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int oldViewDistance = this.objectToViewDistance.replace(object, viewDistance); -+ if (oldViewDistance == -1) { -+ return false; -+ } else { -+ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ final long oldPos = this.objectToLastCoordinate.put(object, newPos); -+ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); -+ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); -+ } -+ //this.validate(object, viewDistance); -+ return true; -+ } -+ -+ // called after the distance map updates -+ protected void updateObjectCallback(final E Object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { -+ if (newPosition != oldPosition && this.changeSourceCallback != null) { -+ this.changeSourceCallback.accept(Object, oldPosition, newPosition); -+ } -+ } -+ -+ public final boolean add(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int oldViewDistance = this.objectToViewDistance.putIfAbsent(object, viewDistance); -+ if (oldViewDistance != -1) { -+ return false; -+ } -+ -+ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ this.objectToLastCoordinate.put(object, newPos); -+ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); -+ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); -+ -+ //this.validate(object, viewDistance); -+ -+ return true; -+ } -+ -+ // called after the distance map updates -+ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} -+ -+ public final boolean remove(final E object) { -+ final long position = this.objectToLastCoordinate.removeLong(object); -+ final int viewDistance = this.objectToViewDistance.removeInt(object); -+ -+ if (viewDistance == -1) { -+ return false; -+ } -+ -+ final int currentX = MCUtil.getCoordinateX(position); -+ final int currentZ = MCUtil.getCoordinateZ(position); -+ -+ this.removeObject(object, currentX, currentZ, currentX, currentZ, viewDistance); -+ this.removeObjectCallback(object, currentX, currentZ, viewDistance); -+ //this.validate(object, -1); -+ return true; -+ } -+ -+ // called after the distance map updates -+ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} -+ -+ protected abstract PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final E object); -+ -+ // expensive op, only for debug -+ protected void validate(final E object, final int viewDistance) { -+ int entiesGot = 0; -+ int expectedEntries = (2 * viewDistance + 1); -+ expectedEntries *= expectedEntries; -+ if (viewDistance < 0) { -+ expectedEntries = 0; -+ } -+ -+ final long currPosition = this.objectToLastCoordinate.getLong(object); -+ -+ final int centerX = MCUtil.getCoordinateX(currPosition); -+ final int centerZ = MCUtil.getCoordinateZ(currPosition); -+ -+ for (Iterator>> iterator = this.areaMap.long2ObjectEntrySet().fastIterator(); -+ iterator.hasNext();) { -+ -+ final Long2ObjectLinkedOpenHashMap.Entry> entry = iterator.next(); -+ final long key = entry.getLongKey(); -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); -+ -+ if (map.referenceCount == 0) { -+ throw new IllegalStateException("Invalid map"); -+ } -+ -+ if (map.contains(object)) { -+ ++entiesGot; -+ -+ final int chunkX = MCUtil.getCoordinateX(key); -+ final int chunkZ = MCUtil.getCoordinateZ(key); -+ -+ final int dist = Math.max(IntegerUtil.branchlessAbs(chunkX - centerX), IntegerUtil.branchlessAbs(chunkZ - centerZ)); -+ -+ if (dist > viewDistance) { -+ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); -+ } -+ } -+ } -+ -+ if (entiesGot != expectedEntries) { -+ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); -+ } -+ } -+ -+ private void addObjectTo(final E object, final int chunkX, final int chunkZ, final int currChunkX, -+ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { -+ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet empty = this.getEmptySetFor(object); -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.putIfAbsent(key, empty); -+ -+ if (current != null) { -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWith(current, object); -+ if (next == current) { -+ throw new IllegalStateException("Expected different map: got " + next.toString()); -+ } -+ this.areaMap.put(key, next); -+ -+ current = next; -+ // fall through to callback -+ } else { -+ current = empty; -+ } -+ -+ if (this.addCallback != null) { -+ try { -+ this.addCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, current); -+ } catch (final Throwable ex) { -+ if (ex instanceof ThreadDeath) { -+ throw (ThreadDeath)ex; -+ } -+ MinecraftServer.LOGGER.error("Add callback for map threw exception ", ex); -+ } -+ } -+ } -+ -+ private void removeObjectFrom(final E object, final int chunkX, final int chunkZ, final int currChunkX, -+ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { -+ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.get(key); -+ -+ if (current == null) { -+ throw new IllegalStateException("Current map may not be null for " + object + ", (" + chunkX + "," + chunkZ + ")"); -+ } -+ -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWithout(current, object); -+ -+ if (next == current) { -+ throw new IllegalStateException("Current map [" + next.toString() + "] should have contained " + object + ", (" + chunkX + "," + chunkZ + ")"); -+ } -+ -+ if (next != null) { -+ this.areaMap.put(key, next); -+ } else { -+ this.areaMap.remove(key); -+ } -+ -+ if (this.removeCallback != null) { -+ try { -+ this.removeCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, next); -+ } catch (final Throwable ex) { -+ if (ex instanceof ThreadDeath) { -+ throw (ThreadDeath)ex; -+ } -+ MinecraftServer.LOGGER.error("Remove callback for map threw exception ", ex); -+ } -+ } -+ } -+ -+ private void addObject(final E object, final int chunkX, final int chunkZ, final int prevChunkX, final int prevChunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.addObjectTo(object, x, z, chunkX, chunkZ, prevChunkX, prevChunkZ); -+ } -+ } -+ } -+ -+ private void removeObject(final E object, final int chunkX, final int chunkZ, final int currentChunkX, final int currentChunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.removeObjectFrom(object, x, z, currentChunkX, currentChunkZ, chunkX, chunkZ); -+ } -+ } -+ } -+ -+ /* math sign function except 0 returns 1 */ -+ protected static int sign(int val) { -+ return 1 | (val >> (Integer.SIZE - 1)); -+ } -+ -+ private void updateObject(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { -+ final int toX = MCUtil.getCoordinateX(newPosition); -+ final int toZ = MCUtil.getCoordinateZ(newPosition); -+ final int fromX = MCUtil.getCoordinateX(oldPosition); -+ final int fromZ = MCUtil.getCoordinateZ(oldPosition); -+ -+ final int dx = toX - fromX; -+ final int dz = toZ - fromZ; -+ -+ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); -+ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); -+ -+ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { -+ // teleported? -+ this.removeObject(object, fromX, fromZ, fromX, fromZ, oldViewDistance); -+ this.addObject(object, toX, toZ, fromX, fromZ, newViewDistance); -+ return; -+ } -+ -+ if (oldViewDistance != newViewDistance) { -+ // remove loop -+ -+ final int oldMinX = fromX - oldViewDistance; -+ final int oldMinZ = fromZ - oldViewDistance; -+ final int oldMaxX = fromX + oldViewDistance; -+ final int oldMaxZ = fromZ + oldViewDistance; -+ for (int currX = oldMinX; currX <= oldMaxX; ++currX) { -+ for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) { -+ -+ // only remove if we're outside the new view distance... -+ if (Math.max(IntegerUtil.branchlessAbs(currX - toX), IntegerUtil.branchlessAbs(currZ - toZ)) > newViewDistance) { -+ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ // add loop -+ -+ final int newMinX = toX - newViewDistance; -+ final int newMinZ = toZ - newViewDistance; -+ final int newMaxX = toX + newViewDistance; -+ final int newMaxZ = toZ + newViewDistance; -+ for (int currX = newMinX; currX <= newMaxX; ++currX) { -+ for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) { -+ -+ // only add if we're outside the old view distance... -+ if (Math.max(IntegerUtil.branchlessAbs(currX - fromX), IntegerUtil.branchlessAbs(currZ - fromZ)) > oldViewDistance) { -+ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ return; -+ } -+ -+ // x axis is width -+ // z axis is height -+ // right refers to the x axis of where we moved -+ // top refers to the z axis of where we moved -+ -+ // same view distance -+ -+ // used for relative positioning -+ final int up = sign(dz); // 1 if dz >= 0, -1 otherwise -+ final int right = sign(dx); // 1 if dx >= 0, -1 otherwise -+ -+ // The area excluded by overlapping the two view distance squares creates four rectangles: -+ // Two on the left, and two on the right. The ones on the left we consider the "removed" section -+ // and on the right the "added" section. -+ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually -+ // exclusive to the regions they surround. -+ -+ // 4 points of the rectangle -+ int maxX; // exclusive -+ int minX; // inclusive -+ int maxZ; // exclusive -+ int minZ; // inclusive -+ -+ if (dx != 0) { -+ // handle right addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX + (oldViewDistance * right) + right; // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle up addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = toX - (oldViewDistance * right); // inclusive -+ maxZ = toZ + (oldViewDistance * up) + up; // exclusive -+ minZ = fromZ + (oldViewDistance * up) + up; // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ if (dx != 0) { -+ // handle left removal -+ -+ maxX = toX - (oldViewDistance * right); // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle down removal -+ -+ maxX = fromX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = toZ - (oldViewDistance * up); // exclusive -+ minZ = fromZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface ChangeCallback { -+ -+ // if there is no previous position, then prevPos = Integer.MIN_VALUE -+ void accept(final E object, final int rangeX, final int rangeZ, final int currPosX, final int currPosZ, final int prevPosX, final int prevPosZ, -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState); -+ -+ } -+ -+ @FunctionalInterface -+ public static interface ChangeSourceCallback { -+ void accept(final E object, final long prevPos, final long newPos); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..905b76d1d65744fe35f56bb78ef75f49178a6a24 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java -@@ -0,0 +1,175 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import com.destroystokyo.paper.util.math.IntegerUtil; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.ChunkCoordIntPair; -+ -+/** @author Spottedleaf */ -+public abstract class DistanceTrackingAreaMap extends AreaMap { -+ -+ // use this map only if you need distance tracking, the tracking here is obviously going to hit harder. -+ -+ protected final Long2IntOpenHashMap chunkToNearestDistance = new Long2IntOpenHashMap(1024, 0.7f); -+ { -+ this.chunkToNearestDistance.defaultReturnValue(-1); -+ } -+ -+ protected final DistanceChangeCallback distanceChangeCallback; -+ -+ public DistanceTrackingAreaMap() { -+ this(new PooledLinkedHashSets<>()); -+ } -+ -+ // let users define a "global" or "shared" pooled sets if they wish -+ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { -+ this(pooledHashSets, null, null, null); -+ } -+ -+ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, -+ final DistanceChangeCallback distanceChangeCallback) { -+ super(pooledHashSets, addCallback, removeCallback); -+ this.distanceChangeCallback = distanceChangeCallback; -+ } -+ -+ // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final long key) { -+ return this.chunkToNearestDistance.get(key); -+ } -+ -+ // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final ChunkCoordIntPair chunkPos) { -+ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkPos)); -+ } -+ -+ // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final int chunkX, final int chunkZ) { -+ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); -+ } -+ -+ protected final void recalculateDistance(final int chunkX, final int chunkZ) { -+ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state = this.areaMap.get(key); -+ if (state == null) { -+ final int oldDistance = this.chunkToNearestDistance.remove(key); -+ // nothing here. -+ if (oldDistance == -1) { -+ // nothing was here previously -+ return; -+ } -+ if (this.distanceChangeCallback != null) { -+ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, -1, null); -+ } -+ return; -+ } -+ -+ int newDistance = Integer.MAX_VALUE; -+ -+ final Object[] rawData = state.getBackingSet(); -+ for (int i = 0, len = rawData.length; i < len; ++i) { -+ final Object raw = rawData[i]; -+ -+ if (raw == null) { -+ continue; -+ } -+ -+ final E object = (E)raw; -+ final long location = this.objectToLastCoordinate.getLong(object); -+ -+ final int distance = Math.max(IntegerUtil.branchlessAbs(chunkX - MCUtil.getCoordinateX(location)), IntegerUtil.branchlessAbs(chunkZ - MCUtil.getCoordinateZ(location))); -+ -+ if (distance < newDistance) { -+ newDistance = distance; -+ } -+ } -+ -+ final int oldDistance = this.chunkToNearestDistance.put(key, newDistance); -+ -+ if (oldDistance != newDistance) { -+ if (this.distanceChangeCallback != null) { -+ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, newDistance, state); -+ } -+ } -+ } -+ -+ @Override -+ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.recalculateDistance(x, z); -+ } -+ } -+ } -+ -+ @Override -+ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.recalculateDistance(x, z); -+ } -+ } -+ } -+ -+ @Override -+ protected void updateObjectCallback(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { -+ if (oldPosition == newPosition && newViewDistance == oldViewDistance) { -+ return; -+ } -+ -+ final int toX = MCUtil.getCoordinateX(newPosition); -+ final int toZ = MCUtil.getCoordinateZ(newPosition); -+ final int fromX = MCUtil.getCoordinateX(oldPosition); -+ final int fromZ = MCUtil.getCoordinateZ(oldPosition); -+ -+ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); -+ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); -+ -+ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { -+ // teleported? -+ this.removeObjectCallback(object, fromX, fromZ, oldViewDistance); -+ this.addObjectCallback(object, toX, toZ, newViewDistance); -+ return; -+ } -+ -+ final int minX = Math.min(fromX - oldViewDistance, toX - newViewDistance); -+ final int maxX = Math.max(fromX + oldViewDistance, toX + newViewDistance); -+ final int minZ = Math.min(fromZ - oldViewDistance, toZ - newViewDistance); -+ final int maxZ = Math.max(fromZ + oldViewDistance, toZ + newViewDistance); -+ -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ final int distXOld = IntegerUtil.branchlessAbs(x - fromX); -+ final int distZOld = IntegerUtil.branchlessAbs(z - fromZ); -+ -+ if (Math.max(distXOld, distZOld) <= oldViewDistance) { -+ this.recalculateDistance(x, z); -+ continue; -+ } -+ -+ final int distXNew = IntegerUtil.branchlessAbs(x - toX); -+ final int distZNew = IntegerUtil.branchlessAbs(z - toZ); -+ -+ if (Math.max(distXNew, distZNew) <= newViewDistance) { -+ this.recalculateDistance(x, z); -+ continue; -+ } -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface DistanceChangeCallback { -+ -+ void accept(final int posX, final int posZ, final int oldNearestDistance, final int newNearestDistance, -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state); -+ -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ed6133b07bc6c4662bd2099ea7dc8aabec37c853 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java -@@ -0,0 +1,32 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import net.minecraft.server.level.EntityPlayer; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class PlayerAreaMap extends AreaMap { -+ -+ public PlayerAreaMap() { -+ super(); -+ } -+ -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets) { -+ super(pooledHashSets); -+ } -+ -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback) { -+ this(pooledHashSets, addCallback, removeCallback, null); -+ } -+ -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { -+ super(pooledHashSets, addCallback, removeCallback, changeSourceCallback); -+ } -+ -+ @Override -+ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final EntityPlayer player) { -+ return player.cachedSingleHashSet; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..eca1fea17184076635563717bb32c81187e2f6f7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java -@@ -0,0 +1,24 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import net.minecraft.server.level.EntityPlayer; -+ -+public class PlayerDistanceTrackingAreaMap extends DistanceTrackingAreaMap { -+ -+ public PlayerDistanceTrackingAreaMap() { -+ super(); -+ } -+ -+ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { -+ super(pooledHashSets); -+ } -+ -+ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback, final DistanceChangeCallback distanceChangeCallback) { -+ super(pooledHashSets, addCallback, removeCallback, distanceChangeCallback); -+ } -+ -+ @Override -+ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final EntityPlayer player) { -+ return player.cachedSingleHashSet; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e51104e65a07b6ea7bbbcbb6afb066ef6401cc5b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java -@@ -0,0 +1,287 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -+import java.lang.ref.WeakReference; -+ -+/** @author Spottedleaf */ -+public class PooledLinkedHashSets { -+ -+ /* Tested via https://gist.github.com/Spottedleaf/a93bb7a8993d6ce142d3efc5932bf573 */ -+ -+ // we really want to avoid that equals() check as much as possible... -+ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(128, 0.25f); -+ -+ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { -+ if (current.referenceCount == 0) { -+ throw new IllegalStateException("Cannot decrement reference count for " + current); -+ } -+ if (current.referenceCount == -1 || --current.referenceCount > 0) { -+ return; -+ } -+ -+ this.mapPool.remove(current); -+ return; -+ } -+ -+ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { -+ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); -+ -+ if (cached != null) { -+ decrementReferenceCount(current); -+ -+ if (cached.referenceCount == 0) { -+ // bring the map back from the dead -+ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); -+ if (contending != null) { -+ // a map already exists with the elements we want -+ if (contending.referenceCount != -1) { -+ ++contending.referenceCount; -+ } -+ current.updateAddCache(object, contending); -+ return contending; -+ } -+ -+ cached.referenceCount = 1; -+ } else if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ return cached; -+ } -+ -+ if (!current.add(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.remove(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.remove(object); -+ } -+ -+ current.updateAddCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ // rets null if current.size() == 1 -+ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { -+ if (current.set.size() == 1) { -+ decrementReferenceCount(current); -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); -+ -+ if (cached != null) { -+ decrementReferenceCount(current); -+ -+ if (cached.referenceCount == 0) { -+ // bring the map back from the dead -+ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); -+ if (contending != null) { -+ // a map already exists with the elements we want -+ if (contending.referenceCount != -1) { -+ ++contending.referenceCount; -+ } -+ current.updateRemoveCache(object, contending); -+ return contending; -+ } -+ -+ cached.referenceCount = 1; -+ } else if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ return cached; -+ } -+ -+ if (!current.remove(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.add(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.add(object); -+ } -+ -+ current.updateRemoveCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ static final class RawSetObjectLinkedOpenHashSet extends ObjectOpenHashSet { -+ -+ public RawSetObjectLinkedOpenHashSet() { -+ super(); -+ } -+ -+ public RawSetObjectLinkedOpenHashSet(final int capacity) { -+ super(capacity); -+ } -+ -+ public RawSetObjectLinkedOpenHashSet(final int capacity, final float loadFactor) { -+ super(capacity, loadFactor); -+ } -+ -+ @Override -+ public RawSetObjectLinkedOpenHashSet clone() { -+ return (RawSetObjectLinkedOpenHashSet)super.clone(); -+ } -+ -+ public E[] getRawSet() { -+ return this.key; -+ } -+ } -+ -+ public static final class PooledObjectLinkedOpenHashSet { -+ -+ private static final WeakReference NULL_REFERENCE = new WeakReference<>(null); -+ -+ final RawSetObjectLinkedOpenHashSet set; -+ int referenceCount; // -1 if special -+ int hash; // optimize hashcode -+ -+ // add cache -+ WeakReference lastAddObject = NULL_REFERENCE; -+ WeakReference> lastAddMap = NULL_REFERENCE; -+ -+ // remove cache -+ WeakReference lastRemoveObject = NULL_REFERENCE; -+ WeakReference> lastRemoveMap = NULL_REFERENCE; -+ -+ public PooledObjectLinkedOpenHashSet(final PooledLinkedHashSets pooledSets) { -+ this.set = new RawSetObjectLinkedOpenHashSet<>(2, 0.8f); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final E single) { -+ this((PooledLinkedHashSets)null); -+ this.referenceCount = -1; -+ this.add(single); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { -+ this.set = other.set.clone(); -+ this.hash = other.hash; -+ } -+ -+ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java -+ // generated by https://github.com/skeeto/hash-prospector -+ private static int hash0(int x) { -+ x *= 0x36935555; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ PooledObjectLinkedOpenHashSet getAddCache(final E element) { -+ final E currentAdd = this.lastAddObject.get(); -+ -+ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { -+ return null; -+ } -+ -+ return this.lastAddMap.get(); -+ } -+ -+ PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { -+ final E currentRemove = this.lastRemoveObject.get(); -+ -+ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { -+ return null; -+ } -+ -+ return this.lastRemoveMap.get(); -+ } -+ -+ void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastAddObject = new WeakReference<>(element); -+ this.lastAddMap = new WeakReference<>(map); -+ } -+ -+ void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastRemoveObject = new WeakReference<>(element); -+ this.lastRemoveMap = new WeakReference<>(map); -+ } -+ -+ boolean add(final E element) { -+ boolean added = this.set.add(element); -+ -+ if (added) { -+ this.hash += hash0(element.hashCode()); -+ } -+ -+ return added; -+ } -+ -+ boolean remove(Object element) { -+ boolean removed = this.set.remove(element); -+ -+ if (removed) { -+ this.hash -= hash0(element.hashCode()); -+ } -+ -+ return removed; -+ } -+ -+ public boolean contains(final Object element) { -+ return this.set.contains(element); -+ } -+ -+ public E[] getBackingSet() { -+ return this.set.getRawSet(); -+ } -+ -+ public int size() { -+ return this.set.size(); -+ } -+ -+ @Override -+ public int hashCode() { -+ return this.hash; -+ } -+ -+ @Override -+ public boolean equals(final Object other) { -+ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { -+ return false; -+ } -+ if (this.referenceCount == 0) { -+ return other == this; -+ } else { -+ if (other == this) { -+ // Unfortunately we are never equal to our own instance while in use! -+ return false; -+ } -+ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); -+ } -+ } -+ -+ @Override -+ public String toString() { -+ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + -+ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d0c77068e9a53d1b8bbad0f3f6b420d6bc85f8c8 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java -@@ -0,0 +1,85 @@ -+package com.destroystokyo.paper.util.pooled; -+ -+import net.minecraft.server.MCUtil; -+import org.apache.commons.lang3.mutable.MutableInt; -+ -+import java.util.ArrayDeque; -+import java.util.function.Consumer; -+import java.util.function.Supplier; -+ -+public final class PooledObjects { -+ -+ /** -+ * Wrapper for an object that will be have a cleaner registered for it, and may be automatically returned to pool. -+ */ -+ public class AutoReleased { -+ private final E object; -+ private final Runnable cleaner; -+ -+ public AutoReleased(E object, Runnable cleaner) { -+ this.object = object; -+ this.cleaner = cleaner; -+ } -+ -+ public final E getObject() { -+ return object; -+ } -+ -+ public final Runnable getCleaner() { -+ return cleaner; -+ } -+ } -+ -+ public static final PooledObjects POOLED_MUTABLE_INTEGERS = new PooledObjects<>(MutableInt::new, 1024); -+ -+ private final Supplier creator; -+ private final Consumer releaser; -+ private final int maxPoolSize; -+ private final ArrayDeque queue; -+ -+ public PooledObjects(final Supplier creator, int maxPoolSize) { -+ this(creator, maxPoolSize, null); -+ } -+ public PooledObjects(final Supplier creator, int maxPoolSize, Consumer releaser) { -+ if (creator == null) { -+ throw new NullPointerException("Creator must not be null"); -+ } -+ if (maxPoolSize <= 0) { -+ throw new IllegalArgumentException("Max pool size must be greater-than 0"); -+ } -+ -+ this.queue = new ArrayDeque<>(maxPoolSize); -+ this.maxPoolSize = maxPoolSize; -+ this.creator = creator; -+ this.releaser = releaser; -+ } -+ -+ public AutoReleased acquireCleaner(Object holder) { -+ return acquireCleaner(holder, this::release); -+ } -+ -+ public AutoReleased acquireCleaner(Object holder, Consumer releaser) { -+ E resource = acquire(); -+ Runnable cleaner = MCUtil.registerCleaner(holder, resource, releaser); -+ return new AutoReleased(resource, cleaner); -+ } -+ -+ public final E acquire() { -+ E value; -+ synchronized (queue) { -+ value = this.queue.pollLast(); -+ } -+ return value != null ? value : this.creator.get(); -+ } -+ -+ public final void release(final E value) { -+ if (this.releaser != null) { -+ this.releaser.accept(value); -+ } -+ synchronized (this.queue) { -+ if (queue.size() < this.maxPoolSize) { -+ this.queue.addLast(value); -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -@@ -0,0 +1,67 @@ -+package com.destroystokyo.paper.util.set; -+ -+import java.util.Collection; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class OptimizedSmallEnumSet> { -+ -+ private final Class enumClass; -+ private long backingSet; -+ -+ public OptimizedSmallEnumSet(final Class clazz) { -+ if (clazz == null) { -+ throw new IllegalArgumentException("Null class"); -+ } -+ if (!clazz.isEnum()) { -+ throw new IllegalArgumentException("Class must be enum, not " + clazz.getCanonicalName()); -+ } -+ this.enumClass = clazz; -+ } -+ -+ public boolean addUnchecked(final E element) { -+ final int ordinal = element.ordinal(); -+ final long key = 1L << ordinal; -+ -+ final long prev = this.backingSet; -+ this.backingSet = prev | key; -+ -+ return (prev & key) == 0; -+ } -+ -+ public boolean removeUnchecked(final E element) { -+ final int ordinal = element.ordinal(); -+ final long key = 1L << ordinal; -+ -+ final long prev = this.backingSet; -+ this.backingSet = prev & ~key; -+ -+ return (prev & key) != 0; -+ } -+ -+ public void clear() { -+ this.backingSet = 0L; -+ } -+ -+ public int size() { -+ return Long.bitCount(this.backingSet); -+ } -+ -+ public void addAllUnchecked(final Collection enums) { -+ for (final E element : enums) { -+ if (element == null) { -+ throw new NullPointerException("Null element"); -+ } -+ this.backingSet |= (1L << element.ordinal()); -+ } -+ } -+ -+ public long getBackingSet() { -+ return this.backingSet; -+ } -+ -+ public boolean hasCommonElements(final OptimizedSmallEnumSet other) { -+ return (other.backingSet & this.backingSet) != 0; -+ } -+} -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index bc7757b929ecce998094ddcdf51a4703e165a6d6..c8bb06a31242089ad950713bd5f94abbfe12adc8 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -78,7 +78,7 @@ public class SystemUtils { - } - - public static long getMonotonicNanos() { -- return SystemUtils.a.getAsLong(); -+ return System.nanoTime(); // Paper - } - - public static long getTimeMillis() { -diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java -index fe3a3ce150de0e689c452b67d480b9d69471b330..25fdd55a7548cfaa45a541ad77f22f33c33e7471 100644 ---- a/src/main/java/net/minecraft/core/BaseBlockPosition.java -+++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java -@@ -18,9 +18,9 @@ public class BaseBlockPosition implements Comparable { - return IntStream.of(new int[]{baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()}); - }); - public static final BaseBlockPosition ZERO = new BaseBlockPosition(0, 0, 0); -- private int a; -- private int b; -- private int e; -+ private int a;public final void setX(final int x) { this.a = x; } // Paper - OBFHELPER -+ private int b;public final void setY(final int y) { this.b = y; } // Paper - OBFHELPER -+ private int e;public final void setZ(final int z) { this.e = z; } // Paper - OBFHELPER - - public BaseBlockPosition(int i, int j, int k) { - this.a = i; -@@ -64,15 +64,15 @@ public class BaseBlockPosition implements Comparable { - return this.e; - } - -- protected void o(int i) { -+ public void o(int i) { // Paper - protected -> public - this.a = i; - } - -- protected void p(int i) { -+ public void p(int i) { // Paper - protected -> public - this.b = i; - } - -- protected void q(int i) { -+ public void q(int i) { // Paper - protected -> public - this.e = i; - } - -@@ -108,6 +108,7 @@ public class BaseBlockPosition implements Comparable { - return this.distanceSquared(iposition.getX(), iposition.getY(), iposition.getZ(), true) < d0 * d0; - } - -+ public final double distanceSquared(BaseBlockPosition baseblockposition) { return j(baseblockposition); } // Paper - OBFHELPER - public double j(BaseBlockPosition baseblockposition) { - return this.distanceSquared((double) baseblockposition.getX(), (double) baseblockposition.getY(), (double) baseblockposition.getZ(), true); - } -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 76675ad1633dbaebb180842b9914fac18741c62e..9fb6db18c5c1f39b5a564c0f5f70498825defa97 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -105,6 +105,7 @@ public class BlockPosition extends BaseBlockPosition { - return d0 == 0.0D && d1 == 0.0D && d2 == 0.0D ? this : new BlockPosition((double) this.getX() + d0, (double) this.getY() + d1, (double) this.getZ() + d2); - } - -+ public final BlockPosition add(int i, int j, int k) {return b(i, j, k);} // Paper - OBFHELPER - public BlockPosition b(int i, int j, int k) { - return i == 0 && j == 0 && k == 0 ? this : new BlockPosition(this.getX() + i, this.getY() + j, this.getZ() + k); - } -@@ -436,6 +437,7 @@ public class BlockPosition extends BaseBlockPosition { - return super.a(enumblockrotation).immutableCopy(); - } - -+ public final BlockPosition.MutableBlockPosition setValues(int i, int j, int k) { return d(i, j, k);} // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition d(int i, int j, int k) { - this.o(i); - this.p(j); -@@ -443,6 +445,7 @@ public class BlockPosition extends BaseBlockPosition { - return this; - } - -+ public final BlockPosition.MutableBlockPosition setValues(double d0, double d1, double d2) { return c(d0, d1, d2);} // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition c(double d0, double d1, double d2) { - return this.d(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); - } -@@ -496,6 +499,7 @@ public class BlockPosition extends BaseBlockPosition { - } - } - -+ /* // Paper start - comment out useless overrides @Override - @Override - public void o(int i) { - super.o(i); -@@ -506,10 +510,10 @@ public class BlockPosition extends BaseBlockPosition { - super.p(i); - } - -- @Override - public void q(int i) { - super.q(i); - } -+ */ // Paper end - - @Override - public BlockPosition immutableCopy() { -diff --git a/src/main/java/net/minecraft/core/RegistryBlockID.java b/src/main/java/net/minecraft/core/RegistryBlockID.java -index e543b6927280a14e1d1220534758289934e31282..d5bec8b0e155ea5ae5746b6da571754a98e4125e 100644 ---- a/src/main/java/net/minecraft/core/RegistryBlockID.java -+++ b/src/main/java/net/minecraft/core/RegistryBlockID.java -@@ -64,6 +64,7 @@ public class RegistryBlockID implements Registry { - return Iterators.filter(this.c.iterator(), Predicates.notNull()); - } - -+ public int size() { return this.a(); } // Paper - OBFHELPER - public int a() { - return this.b.size(); - } -diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -index b2fb24e9ae19ab6e7039a98fc0c265f801be8a99..bf4826e90976fed2ae95e84cadc7f29433af1ddf 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -@@ -76,7 +76,7 @@ public class NBTTagCompound implements NBTBase { - return "TAG_Compound"; - } - }; -- private final Map map; -+ public final Map map; // Paper - - protected NBTTagCompound(Map map) { - this.map = map; -@@ -139,10 +139,16 @@ public class NBTTagCompound implements NBTBase { - this.map.put(s, NBTTagLong.a(i)); - } - -+ public void setUUID(String prefix, UUID uuid) { a(prefix, uuid); } // Paper - OBFHELPER - public void a(String s, UUID uuid) { - this.map.put(s, GameProfileSerializer.a(uuid)); - } - -+ -+ /** -+ * You must use {@link #hasUUID(String)} before or else it will throw an NPE. -+ */ -+ public UUID getUUID(String prefix) { return a(prefix); } // Paper - OBFHELPER - public UUID a(String s) { - return GameProfileSerializer.a(this.get(s)); - } -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 82d8a163df294e68b4db685b95553637f905db48..f093b465b868e6003bb2b5ee634a624b5b054493 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -168,6 +168,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - } - -+ private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER - private void b(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { - EnumProtocol enumprotocol = EnumProtocol.a(packet); - EnumProtocol enumprotocol1 = (EnumProtocol) this.channel.attr(NetworkManager.c).get(); -@@ -208,6 +209,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - } - -+ private void sendPacketQueue() { this.p(); } // Paper - OBFHELPER - private void p() { - if (this.channel != null && this.channel.isOpen()) { - Queue queue = this.packetQueue; -@@ -344,9 +346,9 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - static class QueuedPacket { - -- private final Packet a; -+ private final Packet a; private final Packet getPacket() { return this.a; } // Paper - OBFHELPER - @Nullable -- private final GenericFutureListener> b; -+ private final GenericFutureListener> b; private final GenericFutureListener> getGenericFutureListener() { return this.b; } // Paper - OBFHELPER - - public QueuedPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { - this.a = packet; -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index f94e96406d6dc9c75091ae7563dd5b325f4f0c22..5413bf93f7f0f4491fca1f07c47a925fdace7751 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -49,6 +49,7 @@ public class PacketDataSerializer extends ByteBuf { - this.a = bytebuf; - } - -+ public static int countBytes(int i) { return PacketDataSerializer.a(i); } // Paper - OBFHELPER - public static int a(int i) { - for (int j = 1; j < 5; ++j) { - if ((i & -1 << j * 7) == 0) { -diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index 06098698e4adc31aa96f9592975e441f965b5558..dc8cc8d6c00176c8562086282f726dc1b24b2c65 100644 ---- a/src/main/java/net/minecraft/network/PacketEncoder.java -+++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -44,6 +44,7 @@ public class PacketEncoder extends MessageToByteEncoder> { - packet.b(packetdataserializer); - } catch (Throwable throwable) { - PacketEncoder.LOGGER.error(throwable); -+ throwable.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? - if (packet.a()) { - throw new SkipEncodeException(throwable); - } else { -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java -index d748e07f8870023e74796910a457d58ee0361ca6..2b8358995e4933d3fc3498407a7df7475d7b7e26 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java -@@ -7,7 +7,7 @@ import net.minecraft.world.item.ItemStack; - - public class PacketPlayInBEdit implements Packet { - -- private ItemStack a; -+ private ItemStack a; public ItemStack getBook() { return a; } // Paper - OBFHELPER - private boolean b; - private int c; - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index 820ba7c59e7bc7b6f3311f1a4ec3d724e265a2af..b6b55d5baa5e8a6b69a3e4865c06bc8a4d61a4f3 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -28,7 +28,7 @@ public class PacketPlayOutMapChunk implements Packet { - private NBTTagCompound d; - @Nullable - private int[] e; -- private byte[] f; -+ private byte[] f; private byte[] getData() { return this.f; } // Paper - OBFHELPER - private List g; - private boolean h; - -@@ -140,6 +140,7 @@ public class PacketPlayOutMapChunk implements Packet { - return bytebuf; - } - -+ public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, chunkSectionSelector); } // Paper - OBFHELPER - public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i) { - int j = 0; - ChunkSection[] achunksection = chunk.getSections(); -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..18b56b59fd6efd618e6ff6f9cf3a02f57588d244 ---- /dev/null -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -0,0 +1,510 @@ -+package net.minecraft.server; -+ -+import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.google.common.util.concurrent.ThreadFactoryBuilder; -+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; -+import net.minecraft.core.BlockPosition; -+import net.minecraft.core.EnumDirection; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.RayTrace; -+import net.minecraft.world.level.World; -+import org.apache.commons.lang.exception.ExceptionUtils; -+import org.bukkit.Location; -+import org.bukkit.block.BlockFace; -+import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.util.Waitable; -+import org.spigotmc.AsyncCatcher; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.util.List; -+import java.util.Queue; -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.ExecutionException; -+import java.util.concurrent.LinkedBlockingQueue; -+import java.util.concurrent.ThreadPoolExecutor; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.function.BiConsumer; -+import java.util.function.Consumer; -+import java.util.function.Supplier; -+ -+public final class MCUtil { -+ public static final ThreadPoolExecutor asyncExecutor = new ThreadPoolExecutor( -+ 0, 2, 60L, TimeUnit.SECONDS, -+ new LinkedBlockingQueue(), -+ new ThreadFactoryBuilder().setNameFormat("Paper Async Task Handler Thread - %1$d").build() -+ ); -+ public static final ThreadPoolExecutor cleanerExecutor = new ThreadPoolExecutor( -+ 1, 1, 0L, TimeUnit.SECONDS, -+ new LinkedBlockingQueue(), -+ new ThreadFactoryBuilder().setNameFormat("Paper Object Cleaner").build() -+ ); -+ -+ public static final long INVALID_CHUNK_KEY = getCoordinateKey(Integer.MAX_VALUE, Integer.MAX_VALUE); -+ -+ -+ public static Runnable once(Runnable run) { -+ AtomicBoolean ran = new AtomicBoolean(false); -+ return () -> { -+ if (ran.compareAndSet(false, true)) { -+ run.run(); -+ } -+ }; -+ } -+ -+ public static Runnable once(List list, Consumer cb) { -+ return once(() -> { -+ list.forEach(cb); -+ }); -+ } -+ -+ private static Runnable makeCleanerCallback(Runnable run) { -+ return once(() -> cleanerExecutor.execute(run)); -+ } -+ -+ /** -+ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! -+ * @param obj -+ * @param run -+ * @return -+ */ -+ public static Runnable registerCleaner(Object obj, Runnable run) { -+ // Wrap callback in its own method above or the lambda will leak object -+ Runnable cleaner = makeCleanerCallback(run); -+ co.aikar.cleaner.Cleaner.register(obj, cleaner); -+ return cleaner; -+ } -+ -+ /** -+ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! -+ * @param obj -+ * @param list -+ * @param cleaner -+ * @param -+ * @return -+ */ -+ public static Runnable registerListCleaner(Object obj, List list, Consumer cleaner) { -+ return registerCleaner(obj, () -> { -+ list.forEach(cleaner); -+ list.clear(); -+ }); -+ } -+ -+ /** -+ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! -+ * @param obj -+ * @param resource -+ * @param cleaner -+ * @param -+ * @return -+ */ -+ public static Runnable registerCleaner(Object obj, T resource, java.util.function.Consumer cleaner) { -+ return registerCleaner(obj, () -> cleaner.accept(resource)); -+ } -+ -+ public static List getSpiralOutChunks(BlockPosition blockposition, int radius) { -+ List list = com.google.common.collect.Lists.newArrayList(); -+ -+ list.add(new ChunkCoordIntPair(blockposition.getX() >> 4, blockposition.getZ() >> 4)); -+ for (int r = 1; r <= radius; r++) { -+ int x = -r; -+ int z = r; -+ -+ // Iterates the edge of half of the box; then negates for other half. -+ while (x <= r && z > -r) { -+ list.add(new ChunkCoordIntPair((blockposition.getX() + (x << 4)) >> 4, (blockposition.getZ() + (z << 4)) >> 4)); -+ list.add(new ChunkCoordIntPair((blockposition.getX() - (x << 4)) >> 4, (blockposition.getZ() - (z << 4)) >> 4)); -+ -+ if (x < r) { -+ x++; -+ } else { -+ z--; -+ } -+ } -+ } -+ return list; -+ } -+ -+ public static int fastFloor(double x) { -+ int truncated = (int)x; -+ return x < (double)truncated ? truncated - 1 : truncated; -+ } -+ -+ public static int fastFloor(float x) { -+ int truncated = (int)x; -+ return x < (double)truncated ? truncated - 1 : truncated; -+ } -+ -+ public static float normalizeYaw(float f) { -+ float f1 = f % 360.0F; -+ -+ if (f1 >= 180.0F) { -+ f1 -= 360.0F; -+ } -+ -+ if (f1 < -180.0F) { -+ f1 += 360.0F; -+ } -+ -+ return f1; -+ } -+ -+ /** -+ * Quickly generate a stack trace for current location -+ * -+ * @return Stacktrace -+ */ -+ public static String stack() { -+ return ExceptionUtils.getFullStackTrace(new Throwable()); -+ } -+ -+ /** -+ * Quickly generate a stack trace for current location with message -+ * -+ * @param str -+ * @return Stacktrace -+ */ -+ public static String stack(String str) { -+ return ExceptionUtils.getFullStackTrace(new Throwable(str)); -+ } -+ -+ public static long getCoordinateKey(final BlockPosition blockPos) { -+ return ((long)(blockPos.getZ() >> 4) << 32) | ((blockPos.getX() >> 4) & 0xFFFFFFFFL); -+ } -+ -+ public static long getCoordinateKey(final Entity entity) { -+ return ((long)(MCUtil.fastFloor(entity.locZ()) >> 4) << 32) | ((MCUtil.fastFloor(entity.locX()) >> 4) & 0xFFFFFFFFL); -+ } -+ -+ public static long getCoordinateKey(final ChunkCoordIntPair pair) { -+ return ((long)pair.z << 32) | (pair.x & 0xFFFFFFFFL); -+ } -+ -+ public static long getCoordinateKey(final int x, final int z) { -+ return ((long)z << 32) | (x & 0xFFFFFFFFL); -+ } -+ -+ public static int getCoordinateX(final long key) { -+ return (int)key; -+ } -+ -+ public static int getCoordinateZ(final long key) { -+ return (int)(key >>> 32); -+ } -+ -+ public static int getChunkCoordinate(final double coordinate) { -+ return MCUtil.fastFloor(coordinate) >> 4; -+ } -+ -+ public static int getBlockCoordinate(final double coordinate) { -+ return MCUtil.fastFloor(coordinate); -+ } -+ -+ public static long getBlockKey(final int x, final int y, final int z) { -+ return ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54); -+ } -+ -+ public static long getBlockKey(final BlockPosition pos) { -+ return ((long)pos.getX() & 0x7FFFFFF) | (((long)pos.getZ() & 0x7FFFFFF) << 27) | ((long)pos.getY() << 54); -+ } -+ -+ public static long getBlockKey(final Entity entity) { -+ return getBlockKey(getBlockCoordinate(entity.locX()), getBlockCoordinate(entity.locY()), getBlockCoordinate(entity.locZ())); -+ } -+ -+ // assumes the sets have the same comparator, and if this comparator is null then assume T is Comparable -+ public static void mergeSortedSets(final java.util.function.Consumer consumer, final java.util.Comparator comparator, final java.util.SortedSet...sets) { -+ final ObjectRBTreeSet all = new ObjectRBTreeSet<>(comparator); -+ // note: this is done in log(n!) ~ nlogn time. It could be improved if it were to mimic what mergesort does. -+ for (java.util.SortedSet set : sets) { -+ if (set != null) { -+ all.addAll(set); -+ } -+ } -+ all.forEach(consumer); -+ } -+ -+ private MCUtil() {} -+ -+ public static final java.util.concurrent.Executor MAIN_EXECUTOR = (run) -> { -+ if (!isMainThread()) { -+ MinecraftServer.getServer().execute(run); -+ } else { -+ run.run(); -+ } -+ }; -+ -+ public static CompletableFuture ensureMain(CompletableFuture future) { -+ return future.thenApplyAsync(r -> r, MAIN_EXECUTOR); -+ } -+ -+ public static void thenOnMain(CompletableFuture future, Consumer consumer) { -+ future.thenAcceptAsync(consumer, MAIN_EXECUTOR); -+ } -+ public static void thenOnMain(CompletableFuture future, BiConsumer consumer) { -+ future.whenCompleteAsync(consumer, MAIN_EXECUTOR); -+ } -+ -+ public static boolean isMainThread() { -+ return MinecraftServer.getServer().isMainThread(); -+ } -+ -+ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable) { -+ return scheduleTask(ticks, runnable, null); -+ } -+ -+ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable, String taskName) { -+ return MinecraftServer.getServer().server.getScheduler().scheduleInternalTask(runnable, ticks, taskName); -+ } -+ -+ public static void processQueue() { -+ Runnable runnable; -+ Queue processQueue = getProcessQueue(); -+ while ((runnable = processQueue.poll()) != null) { -+ try { -+ runnable.run(); -+ } catch (Exception e) { -+ MinecraftServer.LOGGER.error("Error executing task", e); -+ } -+ } -+ } -+ public static T processQueueWhileWaiting(CompletableFuture future) { -+ try { -+ if (isMainThread()) { -+ while (!future.isDone()) { -+ try { -+ return future.get(1, TimeUnit.MILLISECONDS); -+ } catch (TimeoutException ignored) { -+ processQueue(); -+ } -+ } -+ } -+ return future.get(); -+ } catch (Exception e) { -+ throw new RuntimeException(e); -+ } -+ } -+ -+ public static void ensureMain(Runnable run) { -+ ensureMain(null, run); -+ } -+ /** -+ * Ensures the target code is running on the main thread -+ * @param reason -+ * @param run -+ * @return -+ */ -+ public static void ensureMain(String reason, Runnable run) { -+ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { -+ if (reason != null) { -+ new IllegalStateException("Asynchronous " + reason + "!").printStackTrace(); -+ } -+ getProcessQueue().add(run); -+ return; -+ } -+ run.run(); -+ } -+ -+ private static Queue getProcessQueue() { -+ return MinecraftServer.getServer().processQueue; -+ } -+ -+ public static T ensureMain(Supplier run) { -+ return ensureMain(null, run); -+ } -+ /** -+ * Ensures the target code is running on the main thread -+ * @param reason -+ * @param run -+ * @param -+ * @return -+ */ -+ public static T ensureMain(String reason, Supplier run) { -+ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { -+ if (reason != null) { -+ new IllegalStateException("Asynchronous " + reason + "! Blocking thread until it returns ").printStackTrace(); -+ } -+ Waitable wait = new Waitable() { -+ @Override -+ protected T evaluate() { -+ return run.get(); -+ } -+ }; -+ getProcessQueue().add(wait); -+ try { -+ return wait.get(); -+ } catch (InterruptedException | ExecutionException e) { -+ e.printStackTrace(); -+ } -+ return null; -+ } -+ return run.get(); -+ } -+ -+ /** -+ * Calculates distance between 2 entities -+ * @param e1 -+ * @param e2 -+ * @return -+ */ -+ public static double distance(Entity e1, Entity e2) { -+ return Math.sqrt(distanceSq(e1, e2)); -+ } -+ -+ -+ /** -+ * Calculates distance between 2 block positions -+ * @param e1 -+ * @param e2 -+ * @return -+ */ -+ public static double distance(BlockPosition e1, BlockPosition e2) { -+ return Math.sqrt(distanceSq(e1, e2)); -+ } -+ -+ /** -+ * Gets the distance between 2 positions -+ * @param x1 -+ * @param y1 -+ * @param z1 -+ * @param x2 -+ * @param y2 -+ * @param z2 -+ * @return -+ */ -+ public static double distance(double x1, double y1, double z1, double x2, double y2, double z2) { -+ return Math.sqrt(distanceSq(x1, y1, z1, x2, y2, z2)); -+ } -+ -+ /** -+ * Get's the distance squared between 2 entities -+ * @param e1 -+ * @param e2 -+ * @return -+ */ -+ public static double distanceSq(Entity e1, Entity e2) { -+ return distanceSq(e1.locX(),e1.locY(),e1.locZ(), e2.locX(),e2.locY(),e2.locZ()); -+ } -+ -+ /** -+ * Gets the distance sqaured between 2 block positions -+ * @param pos1 -+ * @param pos2 -+ * @return -+ */ -+ public static double distanceSq(BlockPosition pos1, BlockPosition pos2) { -+ return distanceSq(pos1.getX(), pos1.getY(), pos1.getZ(), pos2.getX(), pos2.getY(), pos2.getZ()); -+ } -+ -+ /** -+ * Gets the distance squared between 2 positions -+ * @param x1 -+ * @param y1 -+ * @param z1 -+ * @param x2 -+ * @param y2 -+ * @param z2 -+ * @return -+ */ -+ public static double distanceSq(double x1, double y1, double z1, double x2, double y2, double z2) { -+ return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2); -+ } -+ -+ /** -+ * Converts a NMS World/BlockPosition to Bukkit Location -+ * @param world -+ * @param x -+ * @param y -+ * @param z -+ * @return -+ */ -+ public static Location toLocation(World world, double x, double y, double z) { -+ return new Location(world.getWorld(), x, y, z); -+ } -+ -+ /** -+ * Converts a NMS World/BlockPosition to Bukkit Location -+ * @param world -+ * @param pos -+ * @return -+ */ -+ public static Location toLocation(World world, BlockPosition pos) { -+ return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()); -+ } -+ -+ /** -+ * Converts an NMS entity's current location to a Bukkit Location -+ * @param entity -+ * @return -+ */ -+ public static Location toLocation(Entity entity) { -+ return new Location(entity.getWorld().getWorld(), entity.locX(), entity.locY(), entity.locZ()); -+ } -+ -+ public static org.bukkit.block.Block toBukkitBlock(World world, BlockPosition pos) { -+ return world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); -+ } -+ -+ public static BlockPosition toBlockPosition(Location loc) { -+ return new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); -+ } -+ -+ public static boolean isEdgeOfChunk(BlockPosition pos) { -+ final int modX = pos.getX() & 15; -+ final int modZ = pos.getZ() & 15; -+ return (modX == 0 || modX == 15 || modZ == 0 || modZ == 15); -+ } -+ -+ /** -+ * Posts a task to be executed asynchronously -+ * @param run -+ */ -+ public static void scheduleAsyncTask(Runnable run) { -+ asyncExecutor.execute(run); -+ } -+ -+ @Nonnull -+ public static WorldServer getNMSWorld(@Nonnull org.bukkit.World world) { -+ return ((CraftWorld) world).getHandle(); -+ } -+ -+ public static WorldServer getNMSWorld(@Nonnull org.bukkit.entity.Entity entity) { -+ return getNMSWorld(entity.getWorld()); -+ } -+ -+ public static RayTrace.FluidCollisionOption getNMSFluidCollisionOption(TargetBlockInfo.FluidMode fluidMode) { -+ if (fluidMode == TargetBlockInfo.FluidMode.NEVER) { -+ return RayTrace.FluidCollisionOption.NONE; -+ } -+ if (fluidMode == TargetBlockInfo.FluidMode.SOURCE_ONLY) { -+ return RayTrace.FluidCollisionOption.SOURCE_ONLY; -+ } -+ if (fluidMode == TargetBlockInfo.FluidMode.ALWAYS) { -+ return RayTrace.FluidCollisionOption.ANY; -+ } -+ return null; -+ } -+ -+ public static BlockFace toBukkitBlockFace(EnumDirection enumDirection) { -+ switch (enumDirection) { -+ case DOWN: -+ return BlockFace.DOWN; -+ case UP: -+ return BlockFace.UP; -+ case NORTH: -+ return BlockFace.NORTH; -+ case SOUTH: -+ return BlockFace.SOUTH; -+ case WEST: -+ return BlockFace.WEST; -+ case EAST: -+ return BlockFace.EAST; -+ default: -+ return null; -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 6d843bb69b1848ae77098dc3f45d85f405fc24cd..5ce0dfade68257b51ad4a19a829e1fc0a0bbc3db 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -884,6 +884,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant public - private final LightEngineThreaded lightEngine; - private final ChunkProviderServer.a serverThreadQueue; - public final PlayerChunkMap playerChunkMap; -@@ -62,6 +63,158 @@ public class ChunkProviderServer extends IChunkProvider { - private final IChunkAccess[] cacheChunk = new IChunkAccess[4]; - @Nullable - private SpawnerCreature.d p; -+ // Paper start -+ final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock(); -+ final Long2ObjectOpenHashMap loadedChunkMap = new Long2ObjectOpenHashMap<>(8192, 0.5f); -+ -+ private final Chunk[] lastLoadedChunks = new Chunk[4 * 4]; -+ -+ private static int getChunkCacheKey(int x, int z) { -+ return x & 3 | ((z & 3) << 2); -+ } -+ -+ public void addLoadedChunk(Chunk chunk) { -+ this.loadedChunkMapSeqLock.acquireWrite(); -+ try { -+ this.loadedChunkMap.put(chunk.coordinateKey, chunk); -+ } finally { -+ this.loadedChunkMapSeqLock.releaseWrite(); -+ } -+ -+ // rewrite cache if we have to -+ // we do this since we also cache null chunks -+ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); -+ -+ this.lastLoadedChunks[cacheKey] = chunk; -+ } -+ -+ public void removeLoadedChunk(Chunk chunk) { -+ this.loadedChunkMapSeqLock.acquireWrite(); -+ try { -+ this.loadedChunkMap.remove(chunk.coordinateKey); -+ } finally { -+ this.loadedChunkMapSeqLock.releaseWrite(); -+ } -+ -+ // rewrite cache if we have to -+ // we do this since we also cache null chunks -+ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); -+ -+ Chunk cachedChunk = this.lastLoadedChunks[cacheKey]; -+ if (cachedChunk != null && cachedChunk.coordinateKey == chunk.coordinateKey) { -+ this.lastLoadedChunks[cacheKey] = null; -+ } -+ } -+ -+ public final Chunk getChunkAtIfLoadedMainThread(int x, int z) { -+ int cacheKey = getChunkCacheKey(x, z); -+ -+ Chunk cachedChunk = this.lastLoadedChunks[cacheKey]; -+ if (cachedChunk != null && cachedChunk.locX == x & cachedChunk.locZ == z) { -+ return this.lastLoadedChunks[cacheKey]; -+ } -+ -+ long chunkKey = ChunkCoordIntPair.pair(x, z); -+ -+ cachedChunk = this.loadedChunkMap.get(chunkKey); -+ // Skipping a null check to avoid extra instructions to improve inline capability -+ this.lastLoadedChunks[cacheKey] = cachedChunk; -+ return cachedChunk; -+ } -+ -+ public final Chunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) { -+ return this.loadedChunkMap.get(ChunkCoordIntPair.pair(x, z)); -+ } -+ -+ public final Chunk getChunkAtMainThread(int x, int z) { -+ Chunk ret = this.getChunkAtIfLoadedMainThread(x, z); -+ if (ret != null) { -+ return ret; -+ } -+ return (Chunk)this.getChunkAt(x, z, ChunkStatus.FULL, true); -+ } -+ -+ private long chunkFutureAwaitCounter; -+ -+ public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { -+ this.serverThreadQueue.execute(() -> { -+ ChunkProviderServer.this.getEntityTickingChunkAsync(x, z, onLoad); -+ }); -+ return; -+ } -+ this.getChunkFutureAsynchronously(x, z, 31, PlayerChunk::getEntityTickingFuture, onLoad); -+ } -+ -+ public void getTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { -+ this.serverThreadQueue.execute(() -> { -+ ChunkProviderServer.this.getTickingChunkAsync(x, z, onLoad); -+ }); -+ return; -+ } -+ this.getChunkFutureAsynchronously(x, z, 32, PlayerChunk::getTickingFuture, onLoad); -+ } -+ -+ public void getFullChunkAsync(int x, int z, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { -+ this.serverThreadQueue.execute(() -> { -+ ChunkProviderServer.this.getFullChunkAsync(x, z, onLoad); -+ }); -+ return; -+ } -+ this.getChunkFutureAsynchronously(x, z, 33, PlayerChunk::getFullChunkFuture, onLoad); -+ } -+ -+ private void getChunkFutureAsynchronously(int x, int z, int ticketLevel, Function>> futureGet, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { -+ throw new IllegalStateException(); -+ } -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); -+ Long identifier = this.chunkFutureAwaitCounter++; -+ this.chunkMapDistance.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); -+ this.tickDistanceManager(); -+ -+ PlayerChunk chunk = this.playerChunkMap.getUpdatingChunk(chunkPos.pair()); -+ -+ if (chunk == null) { -+ throw new IllegalStateException("Expected playerchunk " + chunkPos + " in world '" + this.world.getWorld().getName() + "'"); -+ } -+ -+ CompletableFuture> future = futureGet.apply(chunk); -+ -+ future.whenCompleteAsync((either, throwable) -> { -+ try { -+ if (throwable != null) { -+ if (throwable instanceof ThreadDeath) { -+ throw (ThreadDeath)throwable; -+ } -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "'", throwable); -+ } else if (either.right().isPresent()) { -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "': " + either.right().get().toString()); -+ } -+ -+ try { -+ if (onLoad != null) { -+ playerChunkMap.callbackExecutor.execute(() -> { -+ onLoad.accept(either == null ? null : either.left().orElse(null)); // indicate failure to the callback. -+ }); -+ } -+ } catch (Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Load callback for future await failed " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "'", thr); -+ return; -+ } -+ } finally { -+ // due to odd behaviour with CB unload implementation we need to have these AFTER the load callback. -+ ChunkProviderServer.this.chunkMapDistance.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); -+ ChunkProviderServer.this.chunkMapDistance.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); -+ } -+ }, this.serverThreadQueue); -+ } -+ // Paper end - - public ChunkProviderServer(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, boolean flag, WorldLoadListener worldloadlistener, Supplier supplier) { - this.world = worldserver; -@@ -123,6 +276,49 @@ public class ChunkProviderServer extends IChunkProvider { - this.cacheChunk[0] = ichunkaccess; - } - -+ // Paper start - "real" get chunk if loaded -+ // Note: Partially copied from the getChunkAt method below -+ @Nullable -+ public Chunk getChunkAtIfCachedImmediately(int x, int z) { -+ long k = ChunkCoordIntPair.pair(x, z); -+ -+ // Note: Bypass cache since we need to check ticket level, and to make this MT-Safe -+ -+ PlayerChunk playerChunk = this.getChunk(k); -+ if (playerChunk == null) { -+ return null; -+ } -+ -+ return playerChunk.getFullChunkIfCached(); -+ } -+ -+ @Nullable -+ public Chunk getChunkAtIfLoadedImmediately(int x, int z) { -+ long k = ChunkCoordIntPair.pair(x, z); -+ -+ if (Thread.currentThread() == this.serverThread) { -+ return this.getChunkAtIfLoadedMainThread(x, z); -+ } -+ -+ Chunk ret = null; -+ long readlock; -+ do { -+ readlock = this.loadedChunkMapSeqLock.acquireRead(); -+ try { -+ ret = this.loadedChunkMap.get(k); -+ } catch (Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // re-try, this means a CME occurred... -+ continue; -+ } -+ } while (!this.loadedChunkMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ // Paper end -+ - @Nullable - @Override - public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { -@@ -405,10 +601,9 @@ public class ChunkProviderServer extends IChunkProvider { - - this.p = spawnercreature_d; - this.world.getMethodProfiler().exit(); -- List list = Lists.newArrayList(this.playerChunkMap.f()); -- -- Collections.shuffle(list); -- list.forEach((playerchunk) -> { -+ //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper -+ //Collections.shuffle(list); // Paper -+ this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - - if (optional.isPresent()) { -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 2d297902e3b0f99a3d9f64606f9edcdabecbe83a..3fa2e077912949f6ca7b14da93c2206215ebcc7e 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -224,6 +224,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public Integer clientViewDistance; - // CraftBukkit end - -+ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper -+ - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); - this.spawnDimension = World.OVERWORLD; -@@ -236,6 +238,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.c(worldserver); - this.co = minecraftserver.a(this); - -+ this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -+ - // CraftBukkit start - this.displayName = this.getName(); - this.canPickUpLoot = true; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 254953c1d8ad80173bcc9ed703bacaf32ca89c9a..7dea5e783ce2a1f8ddd2b3ab7a19e03a56c36ba1 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -46,9 +46,9 @@ public class PlayerChunk { - private static final List CHUNK_STATUSES = ChunkStatus.a(); - private static final PlayerChunk.State[] CHUNK_STATES = PlayerChunk.State.values(); - private final AtomicReferenceArray>> statusFutures; -- private volatile CompletableFuture> fullChunkFuture; -- private volatile CompletableFuture> tickingFuture; -- private volatile CompletableFuture> entityTickingFuture; -+ private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage -+ private volatile CompletableFuture> tickingFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage -+ private volatile CompletableFuture> entityTickingFuture; private volatile boolean isEntityTickingReady; // Paper - cache chunk ticking stage - private CompletableFuture chunkSave; - public int oldTicketLevel; - private int ticketLevel; -@@ -64,6 +64,8 @@ public class PlayerChunk { - private boolean hasBeenLoaded; - private boolean x; - -+ private final PlayerChunkMap chunkMap; // Paper -+ - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -@@ -79,10 +81,49 @@ public class PlayerChunk { - this.ticketLevel = this.oldTicketLevel; - this.n = this.oldTicketLevel; - this.a(i); -+ this.chunkMap = (PlayerChunkMap)playerchunk_d; // Paper -+ } -+ -+ // Paper start -+ @Nullable -+ public final Chunk getEntityTickingChunk() { -+ CompletableFuture> completablefuture = this.entityTickingFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ @Nullable -+ public final Chunk getTickingChunk() { -+ CompletableFuture> completablefuture = this.tickingFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ @Nullable -+ public final Chunk getFullReadyChunk() { -+ CompletableFuture> completablefuture = this.fullChunkFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ public final boolean isEntityTickingReady() { -+ return this.isEntityTickingReady; -+ } -+ -+ public final boolean isTickingReady() { -+ return this.isTickingReady; -+ } -+ -+ public final boolean isFullChunkReady() { -+ return this.isFullChunkReady; - } -+ // Paper end - - // CraftBukkit start -- public Chunk getFullChunk() { -+ public final Chunk getFullChunk() { // Paper - final for inline - if (!getChunkState(this.oldTicketLevel).isAtLeast(PlayerChunk.State.BORDER)) return null; // note: using oldTicketLevel for isLoaded checks - return this.getFullChunkUnchecked(); - } -@@ -93,6 +134,14 @@ public class PlayerChunk { - return (either == null) ? null : (Chunk) either.left().orElse(null); - } - // CraftBukkit end -+ // Paper start - "real" get full chunk immediately -+ public final Chunk getFullChunkIfCached() { -+ // Note: Copied from above without ticket level check -+ CompletableFuture> statusFuture = this.getStatusFutureUnchecked(ChunkStatus.FULL); -+ Either either = (Either) statusFuture.getNow(null); -+ return either == null ? null : (Chunk) either.left().orElse(null); -+ } -+ // Paper end - - public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { - CompletableFuture> completablefuture = (CompletableFuture) this.statusFutures.get(chunkstatus.c()); -@@ -104,20 +153,23 @@ public class PlayerChunk { - return getChunkStatus(this.ticketLevel).b(chunkstatus) ? this.getStatusFutureUnchecked(chunkstatus) : PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE; - } - -- public CompletableFuture> a() { -+ public final CompletableFuture> getTickingFuture() { return this.a(); } // Paper - OBFHELPER -+ public final CompletableFuture> a() { // Paper - final for inline - return this.tickingFuture; - } - -- public CompletableFuture> b() { -+ public final CompletableFuture> getEntityTickingFuture() { return this.b(); } // Paper - OBFHELPER -+ public final CompletableFuture> b() { // Paper - final for inline - return this.entityTickingFuture; - } - -- public CompletableFuture> c() { -+ public final CompletableFuture> getFullChunkFuture() { return this.c(); } // Paper - OBFHELPER -+ public final CompletableFuture> c() { // Paper - final for inline - return this.fullChunkFuture; - } - - @Nullable -- public Chunk getChunk() { -+ public final Chunk getChunk() { // Paper - final for inline - CompletableFuture> completablefuture = this.a(); - Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error - -@@ -142,7 +194,7 @@ public class PlayerChunk { - return null; - } - -- public CompletableFuture getChunkSave() { -+ public final CompletableFuture getChunkSave() { // Paper - final for inline - return this.chunkSave; - } - -@@ -283,11 +335,11 @@ public class PlayerChunk { - }); - } - -- public ChunkCoordIntPair i() { -+ public final ChunkCoordIntPair i() { // Paper - final for inline - return this.location; - } - -- public int getTicketLevel() { -+ public final int getTicketLevel() { // Paper - final for inline - return this.ticketLevel; - } - -@@ -358,13 +410,27 @@ public class PlayerChunk { - - this.hasBeenLoaded |= flag3; - if (!flag2 && flag3) { -- this.fullChunkFuture = playerchunkmap.b(this); -+ // Paper start - cache ticking ready status -+ int expectCreateCount = ++this.fullChunkCreateCount; -+ this.fullChunkFuture = playerchunkmap.b(this); this.fullChunkFuture.thenAccept((either) -> { -+ if (either.left().isPresent() && PlayerChunk.this.fullChunkCreateCount == expectCreateCount) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ Chunk fullChunk = either.left().get(); -+ PlayerChunk.this.isFullChunkReady = true; -+ fullChunk.playerChunk = PlayerChunk.this; -+ -+ -+ } -+ }); -+ // Paper end - this.a(this.fullChunkFuture); - } - - if (flag2 && !flag3) { - completablefuture = this.fullChunkFuture; - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -+ ++this.fullChunkCreateCount; // Paper - cache ticking ready status -+ this.isFullChunkReady = false; // Paper - cache ticking ready status - this.a(((CompletableFuture>) completablefuture).thenApply((either1) -> { // CraftBukkit - decompile error - playerchunkmap.getClass(); - return either1.ifLeft(playerchunkmap::a); -@@ -375,12 +441,24 @@ public class PlayerChunk { - boolean flag5 = playerchunk_state1.isAtLeast(PlayerChunk.State.TICKING); - - if (!flag4 && flag5) { -- this.tickingFuture = playerchunkmap.a(this); -+ // Paper start - cache ticking ready status -+ this.tickingFuture = playerchunkmap.a(this); this.tickingFuture.thenAccept((either) -> { -+ if (either.left().isPresent()) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ Chunk tickingChunk = either.left().get(); -+ PlayerChunk.this.isTickingReady = true; -+ -+ -+ -+ -+ } -+ }); -+ // Paper end - this.a(this.tickingFuture); - } - - if (flag4 && !flag5) { -- this.tickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); -+ this.tickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isTickingReady = false; // Paper - cache chunk ticking stage - this.tickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; - } - -@@ -392,12 +470,24 @@ public class PlayerChunk { - throw (IllegalStateException) SystemUtils.c((Throwable) (new IllegalStateException())); - } - -- this.entityTickingFuture = playerchunkmap.b(this.location); -+ // Paper start - cache ticking ready status -+ this.entityTickingFuture = playerchunkmap.b(this.location); this.entityTickingFuture.thenAccept((either) -> { -+ if (either.left().isPresent()) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ Chunk entityTickingChunk = either.left().get(); -+ PlayerChunk.this.isEntityTickingReady = true; -+ -+ -+ -+ -+ } -+ }); -+ // Paper end - this.a(this.entityTickingFuture); - } - - if (flag6 && !flag7) { -- this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); -+ this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage - this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 565aa1690d5427f5059ab117c4c15b0754e8830b..19856555793f742abb1178ede72dea5623f0e383 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -54,6 +54,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; - import net.minecraft.network.protocol.game.PacketPlayOutMount; - import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.progress.WorldLoadListener; - import net.minecraft.util.CSVWriter; - import net.minecraft.util.EntitySlice; -@@ -146,6 +147,26 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }; - // CraftBukkit end - -+ // Paper start - distance maps -+ private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); -+ -+ void addPlayerToDistanceMaps(EntityPlayer player) { -+ int chunkX = MCUtil.getChunkCoordinate(player.locX()); -+ int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); -+ // Note: players need to be explicitly added to distance maps before they can be updated -+ } -+ -+ void removePlayerFromDistanceMaps(EntityPlayer player) { -+ -+ } -+ -+ void updateMaps(EntityPlayer player) { -+ int chunkX = MCUtil.getChunkCoordinate(player.locX()); -+ int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); -+ // Note: players need to be explicitly added to distance maps before they can be updated -+ } -+ // Paper end -+ - public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag); - this.visibleChunks = this.updatingChunks.clone(); -@@ -235,6 +256,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }; - } - -+ // Paper start -+ public final int getEffectiveViewDistance() { -+ // TODO this needs to be checked on update -+ // Mojang currently sets it to +1 of the configured view distance. So subtract one to get the one we really want. -+ return this.viewDistance - 1; -+ } -+ // Paper end -+ - private CompletableFuture, PlayerChunk.Failure>> a(ChunkCoordIntPair chunkcoordintpair, int i, IntFunction intfunction) { - List>> list = Lists.newArrayList(); - int j = chunkcoordintpair.x; -@@ -953,6 +982,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (!flag1) { - this.chunkDistanceManager.a(SectionPosition.a((Entity) entityplayer), entityplayer); - } -+ this.addPlayerToDistanceMaps(entityplayer); // Paper - distance maps - } else { - SectionPosition sectionposition = entityplayer.O(); - -@@ -960,6 +990,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (!flag2) { - this.chunkDistanceManager.b(sectionposition, entityplayer); - } -+ this.removePlayerFromDistanceMaps(entityplayer); // Paper - distance maps - } - - for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { -@@ -1070,6 +1101,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - } - -+ this.updateMaps(entityplayer); // Paper - distance maps -+ - } - - @Override -diff --git a/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java b/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java -index 91d9e6b554964e1f4dd67deea220a738f2715aee..04006caeeb42b523d986efc313828557854718d7 100644 ---- a/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java -+++ b/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java -@@ -141,6 +141,26 @@ public class RegionLimitedWorldAccess implements GeneratorAccessSeed { - return i >= this.n.x && i <= this.o.x && j >= this.n.z && j <= this.o.z; - } - -+ // Paper start - if loaded util -+ @Nullable -+ @Override -+ public IChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ return this.getChunkAt(x, z, ChunkStatus.FULL, false); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getType(blockposition); -+ } -+ -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getFluid(blockposition); -+ } -+ // Paper end -+ - @Override - public IBlockData getType(BlockPosition blockposition) { - return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4).getType(blockposition); -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 9cae7fed34df3ff81d75105b2fcbc4510f2a0e71..285a03b57431bd6a4d26bb84e916d2c6e1eb0213 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -25,6 +25,7 @@ public class TicketType { - public static final TicketType UNKNOWN = a("unknown", Comparator.comparingLong(ChunkCoordIntPair::pair), 1); - public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit - public static final TicketType PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit -+ public static final TicketType FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper - - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 7f9a1d64d123ce54608497a0e0a37d161d8c9d3c..780e541b8d594a8a6dc3a8626a82218f2502a5c7 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -12,6 +12,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry; - import it.unimi.dsi.fastutil.longs.LongSet; - import it.unimi.dsi.fastutil.longs.LongSets; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.ObjectIterator; - import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; - import java.io.BufferedWriter; -@@ -169,7 +170,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - private final Map entitiesByUUID = Maps.newHashMap(); - private final Queue entitiesToAdd = Queues.newArrayDeque(); - private final List players = Lists.newArrayList(); -- private final ChunkProviderServer chunkProvider; -+ public final ChunkProviderServer chunkProvider; // Paper - public - boolean tickingEntities; - private final MinecraftServer server; - public final WorldDataServer worldDataServer; // CraftBukkit - type -@@ -1688,7 +1689,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - ObjectIterator objectiterator = spawnercreature_d.b().object2IntEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); -+ Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix - - bufferedwriter.write(String.format("spawn_count.%s: %d\n", ((EnumCreatureType) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey()).b(), it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue())); - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 5ce4b27b329c242f48fd3b24c32403281895bda5..265004691f12b3476f3892f5555768717e9c6d19 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -220,9 +220,9 @@ public class PlayerConnection implements PacketListenerPlayIn { - private final MinecraftServer minecraftServer; - public EntityPlayer player; - private int e; -- private long lastKeepAlive; -- private boolean awaitingKeepAlive; -- private long h; -+ private long lastKeepAlive; private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER -+ private boolean awaitingKeepAlive; private void setPendingPing(boolean isPending) { this.awaitingKeepAlive = isPending;}; private boolean isPendingPing() { return this.awaitingKeepAlive;}; // Paper - OBFHELPER -+ private long h; private void setKeepAliveID(long keepAliveID) { this.h = keepAliveID;}; private long getKeepAliveID() {return this.h; }; // Paper - OBFHELPER - // CraftBukkit start - multithreaded fields - private volatile int chatThrottle; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); -diff --git a/src/main/java/net/minecraft/util/DataBits.java b/src/main/java/net/minecraft/util/DataBits.java -index 54974a941a334dc0c8e62ffb8ca094772888b8fa..0c0576c8730069fb5364d8383dec8ab7e698658d 100644 ---- a/src/main/java/net/minecraft/util/DataBits.java -+++ b/src/main/java/net/minecraft/util/DataBits.java -@@ -84,6 +84,7 @@ public class DataBits { - return (int) (k >> l & this.d); - } - -+ public final long[] getDataBits() { return this.a(); } // Paper - OBFHELPER - public long[] a() { - return this.b; - } -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -index 2b2c03ab62816f3d21ef953c4a45f55e3997cca6..e5641f2b41d89a57285fc072a48b951aa03a14a7 100644 ---- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -+++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -@@ -68,6 +68,15 @@ public abstract class IAsyncTaskHandler implements Mailbox entitytypes, World world) { - super(entitytypes, world); - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index b91bb7f562d5c43ec1d0d88ba417e43b07dbf0f3..dbfcdc3cc7c1dccf785f5e13634e84c5af088985 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -225,6 +225,7 @@ public abstract class EntityInsentient extends EntityLiving { - return this.goalTarget; - } - -+ public org.bukkit.craftbukkit.entity.CraftMob getBukkitMob() { return (org.bukkit.craftbukkit.entity.CraftMob) super.getBukkitEntity(); } // Paper - public void setGoalTarget(@Nullable EntityLiving entityliving) { - // CraftBukkit start - fire event - setGoalTarget(entityliving, EntityTargetEvent.TargetReason.UNKNOWN, true); -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 4e5f16882b4cef33411ed2bbe2b2ca67073e4f04..f88c3dfecdce58fbdb695103fd481e9cbd0c266c 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -231,6 +231,7 @@ public abstract class EntityLiving extends Entity { - public boolean collides = true; - public Set collidableExemptions = new HashSet<>(); - public boolean canPickUpLoot; -+ public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper - - @Override - public float getBukkitYaw() { -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index a32bc63ff1960bdb874d546ee42633063834da24..ac57ab9992e141c91cf48f033148ad78433b364c 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -3,6 +3,7 @@ package net.minecraft.world.entity; - import com.google.common.collect.ImmutableSet; - import java.util.Optional; - import java.util.Set; // Paper -+import java.util.Map; // Paper - import java.util.UUID; - import java.util.function.Function; - import java.util.stream.Stream; -@@ -441,8 +442,8 @@ public class EntityTypes { - return this.br.height; - } - -- @Nullable -- public T a(World world) { -+ public T create(World world) { return this.a(world); } // Paper - OBFHELPER -+ @Nullable public T a(World world) { // Paper - OBFHELPER - return this.bf.create(this, world); - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java b/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java -index acebee991eca1e19fc1094718dc40822b66756e1..c484e27650364b6537fe6b2e8e14de98382b86a3 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java -@@ -27,6 +27,7 @@ import net.minecraft.world.level.WorldAccess; - - public abstract class EntityMonster extends EntityCreature implements IMonster { - -+ public org.bukkit.craftbukkit.entity.CraftMonster getBukkitMonster() { return (org.bukkit.craftbukkit.entity.CraftMonster) super.getBukkitEntity(); } // Paper - protected EntityMonster(EntityTypes entitytypes, World world) { - super(entitytypes, world); - this.f = 5; -diff --git a/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java b/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java -index 97db41acf626eec3e587964d0e73c370e5695bf0..2df3ae0b72ccb5f816d55fed15396ba5a1affb7f 100644 ---- a/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java -+++ b/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java -@@ -38,7 +38,7 @@ public class PlayerInventory implements IInventory, INamableTileEntity { - public final NonNullList items; - public final NonNullList armor; - public final NonNullList extraSlots; -- private final List> f; -+ private final List> f; public final List> getComponents() { return f; } // Paper - OBFHELPER - public int itemInHandIndex; - public final EntityHuman player; - private ItemStack carried; -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index dee2714cd9fc930a1a13e97d752ab2df39cd31ed..4010152dccc93019f2e7f284d80b92bae0d91c34 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -103,7 +103,7 @@ public final class ItemStack { - })).apply(instance, ItemStack::new); - }); - private static final Logger LOGGER = LogManager.getLogger(); -- public static final ItemStack b = new ItemStack((Item) null); -+ public static final ItemStack b = new ItemStack((Item) null);public static final ItemStack NULL_ITEM = b; // Paper - OBFHELPER - public static final DecimalFormat c = (DecimalFormat) SystemUtils.a((new DecimalFormat("#.##")), (decimalformat) -> { // CraftBukkit - decompile error - decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); - }); -@@ -660,6 +660,24 @@ public final class ItemStack { - return this.tag != null ? this.tag.getList("Enchantments", 10) : new NBTTagList(); - } - -+ // Paper start - (this is just a good no conflict location) -+ public org.bukkit.inventory.ItemStack asBukkitMirror() { -+ return CraftItemStack.asCraftMirror(this); -+ } -+ public org.bukkit.inventory.ItemStack asBukkitCopy() { -+ return CraftItemStack.asCraftMirror(this.cloneItemStack()); -+ } -+ public static ItemStack fromBukkitCopy(org.bukkit.inventory.ItemStack itemstack) { -+ return CraftItemStack.asNMSCopy(itemstack); -+ } -+ private org.bukkit.craftbukkit.inventory.CraftItemStack bukkitStack; -+ public org.bukkit.inventory.ItemStack getBukkitStack() { -+ if (bukkitStack == null || bukkitStack.getHandle() != this) { -+ bukkitStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this); -+ } -+ return bukkitStack; -+ } -+ // Paper end - public void setTag(@Nullable NBTTagCompound nbttagcompound) { - this.tag = nbttagcompound; - if (this.getItem().usesDurability()) { -@@ -758,6 +776,7 @@ public final class ItemStack { - return this.tag != null && this.tag.hasKeyOfType("Enchantments", 9) ? !this.tag.getList("Enchantments", 10).isEmpty() : false; - } - -+ public void getOrCreateTagAndSet(String s, NBTBase nbtbase) { a(s, nbtbase);} // Paper - OBFHELPER - public void a(String s, NBTBase nbtbase) { - this.getOrCreateTag().set(s, nbtbase); - } -@@ -843,6 +862,7 @@ public final class ItemStack { - // CraftBukkit start - @Deprecated - public void setItem(Item item) { -+ this.bukkitStack = null; // Paper - this.item = item; - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java b/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java -index daad63e731008eddccd3f51418a2a9b2d587f77b..795bc60a73e1e628590803fd515ffb78302d4f97 100644 ---- a/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java -+++ b/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java -@@ -121,6 +121,7 @@ public class PotionUtil { - return nbttagcompound == null ? Potions.EMPTY : PotionRegistry.a(nbttagcompound.getString("Potion")); - } - -+ public static ItemStack addPotionToItemStack(ItemStack itemstack, PotionRegistry potionregistry) { return a(itemstack, potionregistry); } // Paper - OBFHELPER - public static ItemStack a(ItemStack itemstack, PotionRegistry potionregistry) { - MinecraftKey minecraftkey = IRegistry.POTION.getKey(potionregistry); - -diff --git a/src/main/java/net/minecraft/world/level/BlockAccessAir.java b/src/main/java/net/minecraft/world/level/BlockAccessAir.java -index 5f8022745f709b6d542182d2ac94147aefdd3f0f..543b13c1e43135c044f834c2a6231e174536b623 100644 ---- a/src/main/java/net/minecraft/world/level/BlockAccessAir.java -+++ b/src/main/java/net/minecraft/world/level/BlockAccessAir.java -@@ -20,6 +20,18 @@ public enum BlockAccessAir implements IBlockAccess { - return null; - } - -+ // Paper start - If loaded util -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ return this.getFluid(blockposition); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ return this.getType(blockposition); -+ } -+ // Paper end -+ - @Override - public IBlockData getType(BlockPosition blockposition) { - return Blocks.AIR.getBlockData(); -diff --git a/src/main/java/net/minecraft/world/level/ChunkCache.java b/src/main/java/net/minecraft/world/level/ChunkCache.java -index 8541e87a34612e8bc86cf5c291164e091641d1af..7a760ef0264c9041c38bdfb8fd31333052c26139 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkCache.java -+++ b/src/main/java/net/minecraft/world/level/ChunkCache.java -@@ -4,6 +4,7 @@ import java.util.function.Predicate; - import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.TileEntity; -@@ -23,7 +24,7 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - protected final int b; - protected final IChunkAccess[][] c; - protected boolean d; -- protected final World e; -+ protected final World e; protected final World getWorld() { return e; } // Paper - OBFHELPER - - public ChunkCache(World world, BlockPosition blockposition, BlockPosition blockposition1) { - this.e = world; -@@ -42,7 +43,7 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - - for (k = this.a; k <= i; ++k) { - for (l = this.b; l <= j; ++l) { -- this.c[k - this.a][l - this.b] = ichunkprovider.a(k, l); -+ this.c[k - this.a][l - this.b] = ((WorldServer)world).getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(k, l); // Paper - } - } - -@@ -67,7 +68,7 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - int k = i - this.a; - int l = j - this.b; - -- if (k >= 0 && k < this.c.length && l >= 0 && l < this.c[k].length) { -+ if (k >= 0 && k < this.c.length && l >= 0 && l < this.c[k].length) { // Paper - if this changes, update getChunkIfLoaded below - IChunkAccess ichunkaccess = this.c[k][l]; - - return (IChunkAccess) (ichunkaccess != null ? ichunkaccess : new ChunkEmpty(this.e, new ChunkCoordIntPair(i, j))); -@@ -86,6 +87,29 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - return this.a(i, j); - } - -+ // Paper start - if loaded util -+ private IChunkAccess getChunkIfLoaded(int x, int z) { -+ int k = x - this.a; -+ int l = z - this.b; -+ -+ if (k >= 0 && k < this.c.length && l >= 0 && l < this.c[k].length) { -+ return this.c[k][l]; -+ } -+ return null; -+ } -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getFluid(blockposition); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getType(blockposition); -+ } -+ // Paper end -+ - @Nullable - @Override - public TileEntity getTileEntity(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -index 14e55bf842e928d1e8e2137f9efdef0f7c336362..9a88791be443a5b18934e7d752aee6dcdb8aa38f 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -+++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -@@ -12,27 +12,32 @@ public class ChunkCoordIntPair { - public static final long a = pair(1875016, 1875016); - public final int x; - public final int z; -+ public final long longKey; // Paper - - public ChunkCoordIntPair(int i, int j) { - this.x = i; - this.z = j; -+ this.longKey = pair(this.x, this.z); // Paper - } - - public ChunkCoordIntPair(BlockPosition blockposition) { - this.x = blockposition.getX() >> 4; - this.z = blockposition.getZ() >> 4; -+ this.longKey = pair(this.x, this.z); // Paper - } - - public ChunkCoordIntPair(long i) { - this.x = (int) i; - this.z = (int) (i >> 32); -+ this.longKey = pair(this.x, this.z); // Paper - } - - public long pair() { -- return pair(this.x, this.z); -+ return longKey; // Paper - } - -- public static long pair(int i, int j) { -+ public static long pair(final BlockPosition pos) { return pair(pos.getX() >> 4, pos.getZ() >> 4); } // Paper - OBFHELPER -+ public static long pair(int i, int j) { - return (long) i & 4294967295L | ((long) j & 4294967295L) << 32; - } - -diff --git a/src/main/java/net/minecraft/world/level/IBlockAccess.java b/src/main/java/net/minecraft/world/level/IBlockAccess.java -index 25e50b57f42dde156443480d73c6c9985df6f0c6..e799765ecfada1eec78beb71651e52ad355a30aa 100644 ---- a/src/main/java/net/minecraft/world/level/IBlockAccess.java -+++ b/src/main/java/net/minecraft/world/level/IBlockAccess.java -@@ -8,9 +8,11 @@ import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.util.MathHelper; -+import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.material.Fluid; -+import net.minecraft.world.level.material.Material; - import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.Vec3D; -@@ -22,6 +24,19 @@ public interface IBlockAccess { - TileEntity getTileEntity(BlockPosition blockposition); - - IBlockData getType(BlockPosition blockposition); -+ // Paper start - if loaded util -+ IBlockData getTypeIfLoaded(BlockPosition blockposition); -+ default Material getMaterialIfLoaded(BlockPosition blockposition) { -+ IBlockData type = this.getTypeIfLoaded(blockposition); -+ return type == null ? null : type.getMaterial(); -+ } -+ -+ default Block getBlockIfLoaded(BlockPosition blockposition) { -+ IBlockData type = this.getTypeIfLoaded(blockposition); -+ return type == null ? null : type.getBlock(); -+ } -+ Fluid getFluidIfLoaded(BlockPosition blockposition); -+ // Paper end - - Fluid getFluid(BlockPosition blockposition); - -diff --git a/src/main/java/net/minecraft/world/level/IWorldReader.java b/src/main/java/net/minecraft/world/level/IWorldReader.java -index d3d33e77ce09d485552076c5ab6faf08a16d90db..5f12b290d59e0b5e843d644bf7f608a946ef02c0 100644 ---- a/src/main/java/net/minecraft/world/level/IWorldReader.java -+++ b/src/main/java/net/minecraft/world/level/IWorldReader.java -@@ -18,6 +18,7 @@ import net.minecraft.world.phys.AxisAlignedBB; - - public interface IWorldReader extends IBlockLightAccess, ICollisionAccess, BiomeManager.Provider { - -+ @Nullable IChunkAccess getChunkIfLoadedImmediately(int x, int z); // Paper - ifLoaded api (we need this since current impl blocks if the chunk is loading) - @Nullable - IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag); - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index f794113e7cc5809d1da0c85648fb7311fb633f40..0cbebc2095489c240fecd3fd32f5373be2a3d684 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -74,6 +74,7 @@ import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.block.CapturedBlockState; -+import org.bukkit.craftbukkit.block.CraftBlockState; - import org.bukkit.craftbukkit.block.data.CraftBlockData; - import org.bukkit.event.block.BlockPhysicsEvent; - // CraftBukkit end -@@ -255,17 +256,50 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return i < 0 || i >= 256; - } - -- public Chunk getChunkAtWorldCoords(BlockPosition blockposition) { -+ public final Chunk getChunkAtWorldCoords(BlockPosition blockposition) { // Paper - help inline - return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); - } - - @Override -- public Chunk getChunkAt(int i, int j) { -- return (Chunk) this.getChunkAt(i, j, ChunkStatus.FULL); -+ public final Chunk getChunkAt(int i, int j) { // Paper - final to help inline -+ return (Chunk) this.getChunkAt(i, j, ChunkStatus.FULL, true); // Paper - avoid a method jump -+ } -+ -+ // Paper start - if loaded -+ @Nullable -+ @Override -+ public final IChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ return ((WorldServer)this).chunkProvider.getChunkAtIfLoadedImmediately(x, z); - } - - @Override -- public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { -+ public final IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ // CraftBukkit start - tree generation -+ if (captureTreeGeneration) { -+ CraftBlockState previous = capturedBlockStates.get(blockposition); -+ if (previous != null) { -+ return previous.getHandle(); -+ } -+ } -+ // CraftBukkit end -+ if (!isValidLocation(blockposition)) { -+ return Blocks.AIR.getBlockData(); -+ } -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ -+ return chunk == null ? null : chunk.getType(blockposition); -+ } -+ -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ -+ return chunk == null ? null : chunk.getFluid(blockposition); -+ } -+ // Paper end -+ -+ @Override -+ public final IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { // Paper - final for inline - IChunkAccess ichunkaccess = this.getChunkProvider().getChunkAt(i, j, chunkstatus, flag); - - if (ichunkaccess == null && flag) { -@@ -276,7 +310,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - @Override -- public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) { -+ public final boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) { // Paper - final for inline - return this.a(blockposition, iblockdata, i, 512); - } - -@@ -422,8 +456,9 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - public void a(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1) {} - -- @Override -- public boolean a(BlockPosition blockposition, boolean flag) { -+ public boolean setAir(BlockPosition blockposition) { return this.a(blockposition, false); } // Paper - OBFHELPER -+ public boolean setAir(BlockPosition blockposition, boolean moved) { return this.a(blockposition, moved); } // Paper - OBFHELPER -+ @Override public boolean a(BlockPosition blockposition, boolean flag) { // Paper - OBFHELPER - Fluid fluid = this.getFluid(blockposition); - - return this.setTypeAndData(blockposition, fluid.getBlockData(), 3 | (flag ? 64 : 0)); -@@ -569,7 +604,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - if (isOutsideWorld(blockposition)) { - return Blocks.VOID_AIR.getBlockData(); - } else { -- Chunk chunk = this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ Chunk chunk = (Chunk) this.getChunkProvider().getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, true); // Paper - manually inline to reduce hops and avoid unnecessary null check to reduce total byte code size, this should never return null and if it does we will see it the next line but the real stack trace will matter in the chunk engine - - return chunk.getType(blockposition); - } -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index ef652d8f3eb7371c9ddfc3afe67fd1bd669a77c0..2902117fd2803741b053a04fda7f4414fb8593cb 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -688,6 +688,7 @@ public abstract class BlockBase { - return this.a != null ? this.a.d : Block.a(this.getCollisionShape(iblockaccess, blockposition)); - } - -+ public final IBlockData getBlockData() { return p(); } // Paper - OBFHELPER - protected abstract IBlockData p(); - - public boolean isRequiresSpecialTool() { -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 79f645ff1b6274bbdf5dc3f96a762b3b63397c82..2bb03f1cb9671a7754a68059219f783d4508eeb9 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -47,6 +47,7 @@ public class WorldBorder { - return this.b(entity.locX(), entity.locZ()); - } - -+ public final VoxelShape asVoxelShape(){ return c();} // Paper - OBFHELPER - public VoxelShape c() { - return this.j.m(); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 4561cf94fe1dce51abad0ac8635749ed87c8b307..b15200c2a3923bd8be2ee5e73fdadfeea3e3a8dc 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -60,7 +60,7 @@ public class Chunk implements IChunkAccess { - - private static final Logger LOGGER = LogManager.getLogger(); - @Nullable -- public static final ChunkSection a = null; -+ public static final ChunkSection a = null; public static final ChunkSection EMPTY_CHUNK_SECTION = a; // Paper - OBFHELPER - private final ChunkSection[] sections; - private BiomeStorage d; - private final Map e; -@@ -83,7 +83,7 @@ public class Chunk implements IChunkAccess { - private Supplier u; - @Nullable - private Consumer v; -- private final ChunkCoordIntPair loc; -+ private final ChunkCoordIntPair loc; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key - private volatile boolean x; - - public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage) { -@@ -100,7 +100,8 @@ public class Chunk implements IChunkAccess { - this.n = new ShortList[16]; - this.entitySlices = (List[]) (new List[16]); // Spigot - this.world = (WorldServer) world; // CraftBukkit - type -- this.loc = chunkcoordintpair; -+ this.locX = chunkcoordintpair.x; this.locZ = chunkcoordintpair.z; // Paper - reduce need for field look ups -+ this.loc = chunkcoordintpair; this.coordinateKey = ChunkCoordIntPair.pair(locX, locZ); // Paper - cache long key - this.i = chunkconverter; - HeightMap.Type[] aheightmap_type = HeightMap.Type.values(); - int j = aheightmap_type.length; -@@ -146,6 +147,110 @@ public class Chunk implements IChunkAccess { - public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY); - // CraftBukkit end - -+ // Paper start -+ public final com.destroystokyo.paper.util.maplist.EntityList entities = new com.destroystokyo.paper.util.maplist.EntityList(); -+ public PlayerChunk playerChunk; -+ -+ static final int NEIGHBOUR_CACHE_RADIUS = 3; -+ public static int getNeighbourCacheRadius() { -+ return NEIGHBOUR_CACHE_RADIUS; -+ } -+ -+ boolean loadedTicketLevel; -+ private long neighbourChunksLoadedBitset; -+ private final Chunk[] loadedNeighbourChunks = new Chunk[(NEIGHBOUR_CACHE_RADIUS * 2 + 1) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)]; -+ -+ private static int getNeighbourIndex(final int relativeX, final int relativeZ) { -+ // index = (relativeX + NEIGHBOUR_CACHE_RADIUS) + (relativeZ + NEIGHBOUR_CACHE_RADIUS) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1) -+ // optimised variant of the above by moving some of the ops to compile time -+ return relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))); -+ } -+ -+ public final Chunk getRelativeNeighbourIfLoaded(final int relativeX, final int relativeZ) { -+ return this.loadedNeighbourChunks[getNeighbourIndex(relativeX, relativeZ)]; -+ } -+ -+ public final boolean isNeighbourLoaded(final int relativeX, final int relativeZ) { -+ return (this.neighbourChunksLoadedBitset & (1L << getNeighbourIndex(relativeX, relativeZ))) != 0; -+ } -+ -+ public final void setNeighbourLoaded(final int relativeX, final int relativeZ, final Chunk chunk) { -+ if (chunk == null) { -+ throw new IllegalArgumentException("Chunk must be non-null, neighbour: (" + relativeX + "," + relativeZ + "), chunk: " + this.loc); -+ } -+ final long before = this.neighbourChunksLoadedBitset; -+ final int index = getNeighbourIndex(relativeX, relativeZ); -+ this.loadedNeighbourChunks[index] = chunk; -+ this.neighbourChunksLoadedBitset |= (1L << index); -+ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); -+ } -+ -+ public final void setNeighbourUnloaded(final int relativeX, final int relativeZ) { -+ final long before = this.neighbourChunksLoadedBitset; -+ final int index = getNeighbourIndex(relativeX, relativeZ); -+ this.loadedNeighbourChunks[index] = null; -+ this.neighbourChunksLoadedBitset &= ~(1L << index); -+ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); -+ } -+ -+ public final void resetNeighbours() { -+ final long before = this.neighbourChunksLoadedBitset; -+ this.neighbourChunksLoadedBitset = 0L; -+ java.util.Arrays.fill(this.loadedNeighbourChunks, null); -+ this.onNeighbourChange(before, 0L); -+ } -+ -+ protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { -+ -+ } -+ -+ public final boolean isAnyNeighborsLoaded() { -+ return neighbourChunksLoadedBitset != 0; -+ } -+ public final boolean areNeighboursLoaded(final int radius) { -+ return Chunk.areNeighboursLoaded(this.neighbourChunksLoadedBitset, radius); -+ } -+ -+ public static boolean areNeighboursLoaded(final long bitset, final int radius) { -+ // index = relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))) -+ switch (radius) { -+ case 0: { -+ return (bitset & (1L << getNeighbourIndex(0, 0))) != 0; -+ } -+ case 1: { -+ long mask = 0L; -+ for (int dx = -1; dx <= 1; ++dx) { -+ for (int dz = -1; dz <= 1; ++dz) { -+ mask |= (1L << getNeighbourIndex(dx, dz)); -+ } -+ } -+ return (bitset & mask) == mask; -+ } -+ case 2: { -+ long mask = 0L; -+ for (int dx = -2; dx <= 2; ++dx) { -+ for (int dz = -2; dz <= 2; ++dz) { -+ mask |= (1L << getNeighbourIndex(dx, dz)); -+ } -+ } -+ return (bitset & mask) == mask; -+ } -+ case 3: { -+ long mask = 0L; -+ for (int dx = -3; dx <= 3; ++dx) { -+ for (int dz = -3; dz <= 3; ++dz) { -+ mask |= (1L << getNeighbourIndex(dx, dz)); -+ } -+ } -+ return (bitset & mask) == mask; -+ } -+ -+ default: -+ throw new IllegalArgumentException("Radius not recognized: " + radius); -+ } -+ } -+ // Paper end -+ - public Chunk(World world, ProtoChunk protochunk) { - this(world, protochunk.getPos(), protochunk.getBiomeIndex(), protochunk.p(), protochunk.n(), protochunk.o(), protochunk.getInhabitedTime(), protochunk.getSections(), (Consumer) null); - Iterator iterator = protochunk.y().iterator(); -@@ -251,6 +356,18 @@ public class Chunk implements IChunkAccess { - } - } - -+ // Paper start - If loaded util -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ return this.getFluid(blockposition); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ return this.getType(blockposition); -+ } -+ // Paper end -+ - @Override - public Fluid getFluid(BlockPosition blockposition) { - return this.a(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -@@ -391,6 +508,7 @@ public class Chunk implements IChunkAccess { - entity.chunkX = this.loc.x; - entity.chunkY = k; - entity.chunkZ = this.loc.z; -+ this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); - } - -@@ -414,6 +532,7 @@ public class Chunk implements IChunkAccess { - } - - this.entitySlices[i].remove(entity); -+ this.entities.remove(entity); // Paper - } - - @Override -@@ -435,6 +554,7 @@ public class Chunk implements IChunkAccess { - return this.a(blockposition, Chunk.EnumTileEntityState.CHECK); - } - -+ @Nullable public final TileEntity getTileEntityImmediately(BlockPosition pos) { return this.a(pos, EnumTileEntityState.IMMEDIATE); } // Paper - OBFHELPER - @Nullable - public TileEntity a(BlockPosition blockposition, Chunk.EnumTileEntityState chunk_enumtileentitystate) { - // CraftBukkit start -@@ -546,7 +666,25 @@ public class Chunk implements IChunkAccess { - - // CraftBukkit start - public void loadCallback() { -+ // Paper start - neighbour cache -+ int chunkX = this.loc.x; -+ int chunkZ = this.loc.z; -+ ChunkProviderServer chunkProvider = ((WorldServer)this.world).getChunkProvider(); -+ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { -+ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { -+ Chunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); -+ if (neighbour != null) { -+ neighbour.setNeighbourLoaded(-dx, -dz, this); -+ // should be in cached already -+ this.setNeighbourLoaded(dx, dz, neighbour); -+ } -+ } -+ } -+ this.setNeighbourLoaded(0, 0, this); -+ this.loadedTicketLevel = true; -+ // Paper end - neighbour cache - org.bukkit.Server server = this.world.getServer(); -+ ((WorldServer)this.world).getChunkProvider().addLoadedChunk(this); // Paper - if (server != null) { - /* - * If it's a new world, the first few chunks are generated inside -@@ -585,6 +723,22 @@ public class Chunk implements IChunkAccess { - server.getPluginManager().callEvent(unloadEvent); - // note: saving can be prevented, but not forced if no saving is actually required - this.mustNotSave = !unloadEvent.isSaveChunk(); -+ ((WorldServer)this.world).getChunkProvider().removeLoadedChunk(this); // Paper -+ // Paper start - neighbour cache -+ int chunkX = this.loc.x; -+ int chunkZ = this.loc.z; -+ ChunkProviderServer chunkProvider = ((WorldServer)this.world).getChunkProvider(); -+ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { -+ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { -+ Chunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); -+ if (neighbour != null) { -+ neighbour.setNeighbourUnloaded(-dx, -dz); -+ } -+ } -+ } -+ this.loadedTicketLevel = false; -+ this.resetNeighbours(); -+ // Paper end - } - // CraftBukkit end - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index cf2dd6da5ce88aafdcc4db63af18eda9396a066a..a4e2eb1a753e8fcb48982d78fe80e505bce5c476 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -139,6 +139,7 @@ public class ChunkSection { - return this.blockIds; - } - -+ public void writeChunkSection(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER - public void b(PacketDataSerializer packetdataserializer) { - packetdataserializer.writeShort(this.nonEmptyBlockCount); - this.blockIds.b(packetdataserializer); -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPalette.java b/src/main/java/net/minecraft/world/level/chunk/DataPalette.java -index f1dd62541187d007a69087f0279508b6b18d5166..44fe0ee179eebfa6c4c0403a7f06735d7da5c773 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPalette.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPalette.java -@@ -7,10 +7,12 @@ import net.minecraft.network.PacketDataSerializer; - - public interface DataPalette { - -+ default int getOrCreateIdFor(T object) { return this.a(object); } // Paper - OBFHELPER - int a(T t0); - - boolean a(Predicate predicate); - -+ @Nullable default T getObject(int dataBits) { return this.a(dataBits); } // Paper - OBFHELPER - @Nullable - T a(int i); - -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index fe441146757a4ac0562d5b493fb6430e33b9ee28..e397b871b846c3a90bc75d0e1cf0683b6a3d0ca9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -19,7 +19,7 @@ import net.minecraft.util.MathHelper; - - public class DataPaletteBlock implements DataPaletteExpandable { - -- private final DataPalette b; -+ private final DataPalette b; private final DataPalette getDataPaletteGlobal() { return this.b; } // Paper - OBFHELPER - private final DataPaletteExpandable c = (i, object) -> { - return 0; - }; -@@ -27,9 +27,9 @@ public class DataPaletteBlock implements DataPaletteExpandable { - private final Function e; - private final Function f; - private final T g; -- protected DataBits a; -- private DataPalette h; -- private int i; -+ protected DataBits a; public final DataBits getDataBits() { return this.a; } // Paper - OBFHELPER -+ private DataPalette h; private DataPalette getDataPalette() { return this.h; } // Paper - OBFHELPER -+ private int i; private int getBitsPerObject() { return this.i; } // Paper - OBFHELPER - private final ReentrantLock j = new ReentrantLock(); - - public void a() { -@@ -64,6 +64,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - return j << 8 | k << 4 | i; - } - -+ private void initialize(int bitsPerObject) { this.b(bitsPerObject); } // Paper - OBFHELPER - private void b(int i) { - if (i != this.i) { - this.i = i; -@@ -141,6 +142,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - return t0 == null ? this.g : t0; - } - -+ public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER - public void b(PacketDataSerializer packetdataserializer) { - this.a(); - packetdataserializer.writeByte(this.i); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 4192d30ad2117a12a4058b48581d6cf93b50088c..7572ca53a5cca8ca5085d18c24048b85dda4daa9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -99,6 +99,18 @@ public class ProtoChunk implements IChunkAccess { - - } - -+ // Paper start - If loaded util -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ return this.getFluid(blockposition); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ return this.getType(blockposition); -+ } -+ // Paper end -+ - @Override - public IBlockData getType(BlockPosition blockposition) { - int i = blockposition.getY(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -index 859561a5dccba6548967b685b20e8fcfc296db2a..9ebf2806122a308f7655cdbee1f642cd80c9932c 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -@@ -27,7 +27,7 @@ public class IOWorker implements AutoCloseable { - private static final Logger LOGGER = LogManager.getLogger(); - private final AtomicBoolean b = new AtomicBoolean(); - private final ThreadedMailbox c; -- private final RegionFileCache d; -+ private final RegionFileCache d;public RegionFileCache getRegionFileCache() { return d; } // Paper - OBFHELPER - private final Map e = Maps.newLinkedHashMap(); - - protected IOWorker(File file, boolean flag, String s) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 5e3bbc6d89794e23df7b60b13ae48c0f5136f20e..d1b761055c508a4b80436b50a832e00d0449d8cb 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -112,6 +112,7 @@ public class RegionFile implements AutoCloseable { - return this.e.resolve(s); - } - -+ @Nullable public synchronized DataInputStream getReadStream(ChunkCoordIntPair chunkCoordIntPair) throws IOException { return a(chunkCoordIntPair);} // Paper - OBFHELPER - @Nullable - public synchronized DataInputStream a(ChunkCoordIntPair chunkcoordintpair) throws IOException { - int i = this.getOffset(chunkcoordintpair); -diff --git a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -index 633a484cebc99f4a2f071b7f84b0b63d0ec3f985..3941dd33da4b5c09d0087143f1d8a2d76fc18792 100644 ---- a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -+++ b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -@@ -194,10 +194,12 @@ public class AxisAlignedBB { - return this.d(vec3d.x, vec3d.y, vec3d.z); - } - -+ public final boolean intersects(AxisAlignedBB axisalignedbb) { return this.c(axisalignedbb); } // Paper - OBFHELPER - public boolean c(AxisAlignedBB axisalignedbb) { - return this.a(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ, axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ); - } - -+ public final boolean intersects(double d0, double d1, double d2, double d3, double d4, double d5) { return a(d0, d1, d2, d3, d4, d5); } // Paper - OBFHELPER - public boolean a(double d0, double d1, double d2, double d3, double d4, double d5) { - return this.minX < d3 && this.maxX > d0 && this.minY < d4 && this.maxY > d1 && this.minZ < d5 && this.maxZ > d2; - } -@@ -210,6 +212,7 @@ public class AxisAlignedBB { - return d0 >= this.minX && d0 < this.maxX && d1 >= this.minY && d1 < this.maxY && d2 >= this.minZ && d2 < this.maxZ; - } - -+ public final double getAverageSideLength(){return a();} // Paper - OBFHELPER - public double a() { - double d0 = this.b(); - double d1 = this.c(); -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index 44d37272a337fee9606ebaa1b6f647c0fd392320..fdd9e37a8c90fc3311e515355af0a0593efbdacc 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -31,10 +31,12 @@ public final class VoxelShapes { - public static final VoxelShape a = create(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); - private static final VoxelShape c = new VoxelShapeArray(new VoxelShapeBitSet(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); - -+ public static final VoxelShape empty() {return a();} // Paper - OBFHELPER - public static VoxelShape a() { - return VoxelShapes.c; - } - -+ public static final VoxelShape fullCube() {return b();} // Paper - OBFHELPER - public static VoxelShape b() { - return VoxelShapes.b; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 52fa8a38545be43a31363d1d57e42471bbb0c499..275b943a59ef28c831a068987e111e84ebba3bb7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -85,6 +85,7 @@ public final class CraftItemStack extends ItemStack { - } - - net.minecraft.world.item.ItemStack handle; -+ public net.minecraft.world.item.ItemStack getHandle() { return handle; } // Paper - - /** - * Mirror -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 9ad17c560c8d99a396543ab9f97c34de648f6544..4bf48f77f3f7cd62a91590543f5af441c8268029 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -43,6 +43,7 @@ import org.bukkit.scheduler.BukkitWorker; - */ - public class CraftScheduler implements BukkitScheduler { - -+ static Plugin MINECRAFT = new MinecraftInternalPlugin(); - /** - * Counter for IDs. Order doesn't matter, only uniqueness. - */ -@@ -177,6 +178,11 @@ public class CraftScheduler implements BukkitScheduler { - runTaskTimer(plugin, (Object) task, delay, period); - } - -+ public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { -+ final CraftTask task = new CraftTask(run, nextId(), taskName); -+ return handle(task, delay); -+ } -+ - public BukkitTask runTaskTimer(Plugin plugin, Object runnable, long delay, long period) { - validate(plugin, runnable); - if (delay < 0L) { -@@ -400,13 +406,20 @@ public class CraftScheduler implements BukkitScheduler { - task.run(); - task.timings.stopTiming(); // Spigot - } catch (final Throwable throwable) { -- task.getOwner().getLogger().log( -+ // Paper start -+ String msg = String.format( -+ "Task #%s for %s generated an exception", -+ task.getTaskId(), -+ task.getOwner().getDescription().getFullName()); -+ if (task.getOwner() == MINECRAFT) { -+ net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable); -+ } else { -+ task.getOwner().getLogger().log( - Level.WARNING, -- String.format( -- "Task #%s for %s generated an exception", -- task.getTaskId(), -- task.getOwner().getDescription().getFullName()), -+ msg, - throwable); -+ } -+ // Paper end - } finally { - currentTask = null; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -index 3c7066192ea4c05c101404bb56cbc839771f4200..09aa6809c5400ce8548ac902908b750ce7c964ec 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -@@ -39,6 +39,21 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - CraftTask(final Object task) { - this(null, task, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); - } -+ // Paper start -+ public String taskName = null; -+ boolean internal = false; -+ CraftTask(final Object task, int id, String taskName) { -+ this.rTask = (Runnable) task; -+ this.cTask = null; -+ this.plugin = CraftScheduler.MINECRAFT; -+ this.taskName = taskName; -+ this.internal = true; -+ this.id = id; -+ this.period = CraftTask.NO_REPEATING; -+ this.taskName = taskName; -+ this.timings = null; // Will be changed in later patch -+ } -+ // Paper end - - CraftTask(final Plugin plugin, final Object task, final int id, final long period) { - this.plugin = plugin; -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java -new file mode 100644 -index 0000000000000000000000000000000000000000..49dc0c441b9dd7e7745cf15ced67f383ebee1f99 ---- /dev/null -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java -@@ -0,0 +1,132 @@ -+package org.bukkit.craftbukkit.scheduler; -+ -+ -+import org.bukkit.Server; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+import org.bukkit.configuration.file.FileConfiguration; -+import org.bukkit.generator.ChunkGenerator; -+import org.bukkit.plugin.PluginBase; -+import org.bukkit.plugin.PluginDescriptionFile; -+import org.bukkit.plugin.PluginLoader; -+import org.bukkit.plugin.PluginLogger; -+ -+import java.io.File; -+import java.io.InputStream; -+import java.util.List; -+ -+public class MinecraftInternalPlugin extends PluginBase { -+ private boolean enabled = true; -+ -+ private final String pluginName; -+ private PluginDescriptionFile pdf; -+ -+ public MinecraftInternalPlugin() { -+ this.pluginName = "Minecraft"; -+ pdf = new PluginDescriptionFile(pluginName, "1.0", "nms"); -+ } -+ -+ public void setEnabled(boolean enabled) { -+ this.enabled = enabled; -+ } -+ -+ @Override -+ public File getDataFolder() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public PluginDescriptionFile getDescription() { -+ return pdf; -+ } -+ -+ @Override -+ public FileConfiguration getConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public InputStream getResource(String filename) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void saveConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void saveDefaultConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void saveResource(String resourcePath, boolean replace) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void reloadConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public PluginLogger getLogger() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public PluginLoader getPluginLoader() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public Server getServer() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @Override -+ public void onDisable() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void onLoad() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void onEnable() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public boolean isNaggable() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void setNaggable(boolean canNag) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -index f4ea5809f48fda39e32738529b4ae8f74acadb90..b2b14eada44231a619622a2baef27abdb798aa47 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -@@ -168,7 +168,23 @@ public class DummyGeneratorAccess implements GeneratorAccess { - public Fluid getFluid(BlockPosition blockposition) { - throw new UnsupportedOperationException("Not supported yet."); - } -+ // Paper start - if loaded util -+ @javax.annotation.Nullable -+ @Override -+ public IChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } - -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } -+ // Paper end - @Override - public WorldBorder getWorldBorder() { - throw new UnsupportedOperationException("Not supported yet."); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -index 1aec70a1f1a9d8fd2cd06bde4033e19e769ab331..f72c13bedaa6fa45e26f5dcad564835bdd4af61f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -@@ -17,7 +17,7 @@ import java.util.RandomAccess; - public class UnsafeList extends AbstractList implements List, RandomAccess, Cloneable, Serializable { - private static final long serialVersionUID = 8683452581112892191L; - -- private transient Object[] data; -+ private transient Object[] data; public final Object[] getRawDataArray() { return this.data; } // Paper - expose for raw get - private int size; - private int initialCapacity; - -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 724c6a47846f4266c858b783f68f162e0508d2fa..c04d912adf0da8f7a5b75dd2f58739a11ca31601 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -118,7 +118,11 @@ public class SpigotConfig - } - } - } -- -+ // Paper start -+ SpigotConfig.save(); -+ } -+ public static void save() { -+ // Paper end - try - { - config.save( CONFIG_FILE ); diff --git a/Unmapped-Spigot-Server-Patches/0005-Paper-Metrics.patch b/Unmapped-Spigot-Server-Patches/0005-Paper-Metrics.patch deleted file mode 100644 index 45ad445357..0000000000 --- a/Unmapped-Spigot-Server-Patches/0005-Paper-Metrics.patch +++ /dev/null @@ -1,735 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 24 Mar 2017 23:56:01 -0500 -Subject: [PATCH] Paper Metrics - -Removes Spigot's mcstats metrics in favor of a system using bStats - -To disable for privacy or other reasons go to the bStats folder in your plugins folder -and edit the config.yml file present there. - -Please keep in mind the data collected is anonymous and collection should have no -tangible effect on server performance. The data is used to allow the authors of -PaperMC to track version and platform usage so that we can make better management -decisions on behalf of the project. - -diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0b9e689d57705965721b5c55bc45d36657f360e4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/Metrics.java -@@ -0,0 +1,670 @@ -+package com.destroystokyo.paper; -+ -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+import org.bukkit.configuration.file.YamlConfiguration; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.plugin.Plugin; -+ -+import org.json.simple.JSONArray; -+import org.json.simple.JSONObject; -+ -+import javax.net.ssl.HttpsURLConnection; -+import java.io.ByteArrayOutputStream; -+import java.io.DataOutputStream; -+import java.io.File; -+import java.io.IOException; -+import java.net.URL; -+import java.util.*; -+import java.util.concurrent.Callable; -+import java.util.concurrent.Executors; -+import java.util.concurrent.ScheduledExecutorService; -+import java.util.concurrent.TimeUnit; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+import java.util.zip.GZIPOutputStream; -+ -+/** -+ * bStats collects some data for plugin authors. -+ * -+ * Check out https://bStats.org/ to learn more about bStats! -+ */ -+public class Metrics { -+ -+ // Executor service for requests -+ // We use an executor service because the Bukkit scheduler is affected by server lags -+ private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); -+ -+ // The version of this bStats class -+ public static final int B_STATS_VERSION = 1; -+ -+ // The url to which the data is sent -+ private static final String URL = "https://bStats.org/submitData/server-implementation"; -+ -+ // Should failed requests be logged? -+ private static boolean logFailedRequests = false; -+ -+ // The logger for the failed requests -+ private static Logger logger = Logger.getLogger("bStats"); -+ -+ // The name of the server software -+ private final String name; -+ -+ // The uuid of the server -+ private final String serverUUID; -+ -+ // A list with all custom charts -+ private final List charts = new ArrayList<>(); -+ -+ /** -+ * Class constructor. -+ * -+ * @param name The name of the server software. -+ * @param serverUUID The uuid of the server. -+ * @param logFailedRequests Whether failed requests should be logged or not. -+ * @param logger The logger for the failed requests. -+ */ -+ public Metrics(String name, String serverUUID, boolean logFailedRequests, Logger logger) { -+ this.name = name; -+ this.serverUUID = serverUUID; -+ Metrics.logFailedRequests = logFailedRequests; -+ Metrics.logger = logger; -+ -+ // Start submitting the data -+ startSubmitting(); -+ } -+ -+ /** -+ * Adds a custom chart. -+ * -+ * @param chart The chart to add. -+ */ -+ public void addCustomChart(CustomChart chart) { -+ if (chart == null) { -+ throw new IllegalArgumentException("Chart cannot be null!"); -+ } -+ charts.add(chart); -+ } -+ -+ /** -+ * Starts the Scheduler which submits our data every 30 minutes. -+ */ -+ private void startSubmitting() { -+ final Runnable submitTask = this::submitData; -+ -+ // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the -+ // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. -+ // WARNING: You must not modify any part of this Metrics class, including the submit delay or frequency! -+ // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! -+ long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); -+ long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); -+ scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); -+ scheduler.scheduleAtFixedRate(submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); -+ } -+ -+ /** -+ * Gets the plugin specific data. -+ * -+ * @return The plugin specific data. -+ */ -+ private JSONObject getPluginData() { -+ JSONObject data = new JSONObject(); -+ -+ data.put("pluginName", name); // Append the name of the server software -+ JSONArray customCharts = new JSONArray(); -+ for (CustomChart customChart : charts) { -+ // Add the data of the custom charts -+ JSONObject chart = customChart.getRequestJsonObject(); -+ if (chart == null) { // If the chart is null, we skip it -+ continue; -+ } -+ customCharts.add(chart); -+ } -+ data.put("customCharts", customCharts); -+ -+ return data; -+ } -+ -+ /** -+ * Gets the server specific data. -+ * -+ * @return The server specific data. -+ */ -+ private JSONObject getServerData() { -+ // OS specific data -+ String osName = System.getProperty("os.name"); -+ String osArch = System.getProperty("os.arch"); -+ String osVersion = System.getProperty("os.version"); -+ int coreCount = Runtime.getRuntime().availableProcessors(); -+ -+ JSONObject data = new JSONObject(); -+ -+ data.put("serverUUID", serverUUID); -+ -+ data.put("osName", osName); -+ data.put("osArch", osArch); -+ data.put("osVersion", osVersion); -+ data.put("coreCount", coreCount); -+ -+ return data; -+ } -+ -+ /** -+ * Collects the data and sends it afterwards. -+ */ -+ private void submitData() { -+ final JSONObject data = getServerData(); -+ -+ JSONArray pluginData = new JSONArray(); -+ pluginData.add(getPluginData()); -+ data.put("plugins", pluginData); -+ -+ try { -+ // We are still in the Thread of the timer, so nothing get blocked :) -+ sendData(data); -+ } catch (Exception e) { -+ // Something went wrong! :( -+ if (logFailedRequests) { -+ logger.log(Level.WARNING, "Could not submit stats of " + name, e); -+ } -+ } -+ } -+ -+ /** -+ * Sends the data to the bStats server. -+ * -+ * @param data The data to send. -+ * @throws Exception If the request failed. -+ */ -+ private static void sendData(JSONObject data) throws Exception { -+ if (data == null) { -+ throw new IllegalArgumentException("Data cannot be null!"); -+ } -+ HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); -+ -+ // Compress the data to save bandwidth -+ byte[] compressedData = compress(data.toString()); -+ -+ // Add headers -+ connection.setRequestMethod("POST"); -+ connection.addRequestProperty("Accept", "application/json"); -+ connection.addRequestProperty("Connection", "close"); -+ connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request -+ connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); -+ connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format -+ connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); -+ -+ // Send data -+ connection.setDoOutput(true); -+ DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); -+ outputStream.write(compressedData); -+ outputStream.flush(); -+ outputStream.close(); -+ -+ connection.getInputStream().close(); // We don't care about the response - Just send our data :) -+ } -+ -+ /** -+ * Gzips the given String. -+ * -+ * @param str The string to gzip. -+ * @return The gzipped String. -+ * @throws IOException If the compression failed. -+ */ -+ private static byte[] compress(final String str) throws IOException { -+ if (str == null) { -+ return null; -+ } -+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); -+ GZIPOutputStream gzip = new GZIPOutputStream(outputStream); -+ gzip.write(str.getBytes("UTF-8")); -+ gzip.close(); -+ return outputStream.toByteArray(); -+ } -+ -+ /** -+ * Represents a custom chart. -+ */ -+ public static abstract class CustomChart { -+ -+ // The id of the chart -+ final String chartId; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ */ -+ CustomChart(String chartId) { -+ if (chartId == null || chartId.isEmpty()) { -+ throw new IllegalArgumentException("ChartId cannot be null or empty!"); -+ } -+ this.chartId = chartId; -+ } -+ -+ private JSONObject getRequestJsonObject() { -+ JSONObject chart = new JSONObject(); -+ chart.put("chartId", chartId); -+ try { -+ JSONObject data = getChartData(); -+ if (data == null) { -+ // If the data is null we don't send the chart. -+ return null; -+ } -+ chart.put("data", data); -+ } catch (Throwable t) { -+ if (logFailedRequests) { -+ logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t); -+ } -+ return null; -+ } -+ return chart; -+ } -+ -+ protected abstract JSONObject getChartData() throws Exception; -+ -+ } -+ -+ /** -+ * Represents a custom simple pie. -+ */ -+ public static class SimplePie extends CustomChart { -+ -+ private final Callable callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public SimplePie(String chartId, Callable callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ String value = callable.call(); -+ if (value == null || value.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("value", value); -+ return data; -+ } -+ } -+ -+ /** -+ * Represents a custom advanced pie. -+ */ -+ public static class AdvancedPie extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public AdvancedPie(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean allSkipped = true; -+ for (Map.Entry entry : map.entrySet()) { -+ if (entry.getValue() == 0) { -+ continue; // Skip this invalid -+ } -+ allSkipped = false; -+ values.put(entry.getKey(), entry.getValue()); -+ } -+ if (allSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ } -+ -+ /** -+ * Represents a custom drilldown pie. -+ */ -+ public static class DrilldownPie extends CustomChart { -+ -+ private final Callable>> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public DrilldownPie(String chartId, Callable>> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ public JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map> map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean reallyAllSkipped = true; -+ for (Map.Entry> entryValues : map.entrySet()) { -+ JSONObject value = new JSONObject(); -+ boolean allSkipped = true; -+ for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { -+ value.put(valueEntry.getKey(), valueEntry.getValue()); -+ allSkipped = false; -+ } -+ if (!allSkipped) { -+ reallyAllSkipped = false; -+ values.put(entryValues.getKey(), value); -+ } -+ } -+ if (reallyAllSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ } -+ -+ /** -+ * Represents a custom single line chart. -+ */ -+ public static class SingleLineChart extends CustomChart { -+ -+ private final Callable callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public SingleLineChart(String chartId, Callable callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ int value = callable.call(); -+ if (value == 0) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("value", value); -+ return data; -+ } -+ -+ } -+ -+ /** -+ * Represents a custom multi line chart. -+ */ -+ public static class MultiLineChart extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public MultiLineChart(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean allSkipped = true; -+ for (Map.Entry entry : map.entrySet()) { -+ if (entry.getValue() == 0) { -+ continue; // Skip this invalid -+ } -+ allSkipped = false; -+ values.put(entry.getKey(), entry.getValue()); -+ } -+ if (allSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ -+ } -+ -+ /** -+ * Represents a custom simple bar chart. -+ */ -+ public static class SimpleBarChart extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public SimpleBarChart(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ for (Map.Entry entry : map.entrySet()) { -+ JSONArray categoryValues = new JSONArray(); -+ categoryValues.add(entry.getValue()); -+ values.put(entry.getKey(), categoryValues); -+ } -+ data.put("values", values); -+ return data; -+ } -+ -+ } -+ -+ /** -+ * Represents a custom advanced bar chart. -+ */ -+ public static class AdvancedBarChart extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public AdvancedBarChart(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean allSkipped = true; -+ for (Map.Entry entry : map.entrySet()) { -+ if (entry.getValue().length == 0) { -+ continue; // Skip this invalid -+ } -+ allSkipped = false; -+ JSONArray categoryValues = new JSONArray(); -+ for (int categoryValue : entry.getValue()) { -+ categoryValues.add(categoryValue); -+ } -+ values.put(entry.getKey(), categoryValues); -+ } -+ if (allSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ -+ } -+ -+ static class PaperMetrics { -+ static void startMetrics() { -+ // Get the config file -+ File configFile = new File(new File((File) MinecraftServer.getServer().options.valueOf("plugins"), "bStats"), "config.yml"); -+ YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); -+ -+ // Check if the config file exists -+ if (!config.isSet("serverUuid")) { -+ -+ // Add default values -+ config.addDefault("enabled", true); -+ // Every server gets it's unique random id. -+ config.addDefault("serverUuid", UUID.randomUUID().toString()); -+ // Should failed request be logged? -+ config.addDefault("logFailedRequests", false); -+ -+ // Inform the server owners about bStats -+ config.options().header( -+ "bStats collects some data for plugin authors like how many servers are using their plugins.\n" + -+ "To honor their work, you should not disable it.\n" + -+ "This has nearly no effect on the server performance!\n" + -+ "Check out https://bStats.org/ to learn more :)" -+ ).copyDefaults(true); -+ try { -+ config.save(configFile); -+ } catch (IOException ignored) { -+ } -+ } -+ // Load the data -+ String serverUUID = config.getString("serverUuid"); -+ boolean logFailedRequests = config.getBoolean("logFailedRequests", false); -+ // Only start Metrics, if it's enabled in the config -+ if (config.getBoolean("enabled", true)) { -+ Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger()); -+ -+ metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { -+ String minecraftVersion = Bukkit.getVersion(); -+ minecraftVersion = minecraftVersion.substring(minecraftVersion.indexOf("MC: ") + 4, minecraftVersion.length() - 1); -+ return minecraftVersion; -+ })); -+ -+ metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); -+ metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() || PaperConfig.isProxyOnlineMode() ? "online" : "offline")); -+ metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); -+ -+ metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { -+ Map> map = new HashMap<>(); -+ String javaVersion = System.getProperty("java.version"); -+ Map entry = new HashMap<>(); -+ entry.put(javaVersion, 1); -+ -+ // http://openjdk.java.net/jeps/223 -+ // Java decided to change their versioning scheme and in doing so modified the java.version system -+ // property to return $major[.$minor][.$secuity][-ea], as opposed to 1.$major.0_$identifier -+ // we can handle pre-9 by checking if the "major" is equal to "1", otherwise, 9+ -+ String majorVersion = javaVersion.split("\\.")[0]; -+ String release; -+ -+ int indexOf = javaVersion.lastIndexOf('.'); -+ -+ if (majorVersion.equals("1")) { -+ release = "Java " + javaVersion.substring(0, indexOf); -+ } else { -+ // of course, it really wouldn't be all that simple if they didn't add a quirk, now would it -+ // valid strings for the major may potentially include values such as -ea to deannotate a pre release -+ Matcher versionMatcher = Pattern.compile("\\d+").matcher(majorVersion); -+ if (versionMatcher.find()) { -+ majorVersion = versionMatcher.group(0); -+ } -+ release = "Java " + majorVersion; -+ } -+ map.put(release, entry); -+ -+ return map; -+ })); -+ -+ metrics.addCustomChart(new Metrics.DrilldownPie("legacy_plugins", () -> { -+ Map> map = new HashMap<>(); -+ -+ // count legacy plugins -+ int legacy = 0; -+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { -+ if (CraftMagicNumbers.isLegacy(plugin.getDescription())) { -+ legacy++; -+ } -+ } -+ -+ // insert real value as lower dimension -+ Map entry = new HashMap<>(); -+ entry.put(String.valueOf(legacy), 1); -+ -+ // create buckets as higher dimension -+ if (legacy == 0) { -+ map.put("0 \uD83D\uDE0E", entry); // :sunglasses: -+ } else if (legacy <= 5) { -+ map.put("1-5", entry); -+ } else if (legacy <= 10) { -+ map.put("6-10", entry); -+ } else if (legacy <= 25) { -+ map.put("11-25", entry); -+ } else if (legacy <= 50) { -+ map.put("26-50", entry); -+ } else { -+ map.put("50+ \uD83D\uDE2D", entry); // :cry: -+ } -+ -+ return map; -+ })); -+ } -+ -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 2c0514892d3993bef57ecf677cf8bb0fbe0216e4..da922f395f0fff0881ead893c900c5b2623f48f0 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -42,6 +42,7 @@ public class PaperConfig { - private static boolean verbose; - private static boolean fatalError; - /*========================================================================*/ -+ private static boolean metricsStarted; - - public static void init(File configFile) { - CONFIG_FILE = configFile; -@@ -84,6 +85,11 @@ public class PaperConfig { - for (Map.Entry entry : commands.entrySet()) { - MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); - } -+ -+ if (!metricsStarted) { -+ Metrics.PaperMetrics.startMetrics(); -+ metricsStarted = true; -+ } - } - - static void readConfig(Class clazz, Object instance) { -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index c04d912adf0da8f7a5b75dd2f58739a11ca31601..3c93a497a790b8d800852db2ac48feca41f45cef 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -83,6 +83,7 @@ public class SpigotConfig - MinecraftServer.getServer().server.getCommandMap().register( entry.getKey(), "Spigot", entry.getValue() ); - } - -+ /* // Paper - Replace with our own - if ( metrics == null ) - { - try -@@ -94,6 +95,7 @@ public class SpigotConfig - Bukkit.getServer().getLogger().log( Level.SEVERE, "Could not start metrics service", ex ); - } - } -+ */ // Paper end - } - - static void readConfig(Class clazz, Object instance) diff --git a/Unmapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch b/Unmapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch deleted file mode 100644 index a390f7960d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 01:40:13 -0400 -Subject: [PATCH] Add MinecraftKey Information to Objects - -Stores the reference to the objects respective MinecraftKey - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 68cd4134cb6a00c1768100462f8e9e94f3fa6279..6943524c2dd8b12691b8ac5b08daee823ce50c3d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -208,7 +208,7 @@ public class PaperCommand extends Command { - - Collection entities = world.entitiesById.values(); - entities.forEach(e -> { -- MinecraftKey key = new MinecraftKey(""); // TODO: update in next patch -+ MinecraftKey key = e.getMinecraftKey(); - - MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); - ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); -diff --git a/src/main/java/net/minecraft/server/KeyedObject.java b/src/main/java/net/minecraft/server/KeyedObject.java -new file mode 100644 -index 0000000000000000000000000000000000000000..500477f0d98a277145c2b0dbb4d1496e2a588542 ---- /dev/null -+++ b/src/main/java/net/minecraft/server/KeyedObject.java -@@ -0,0 +1,11 @@ -+package net.minecraft.server; -+ -+import net.minecraft.resources.MinecraftKey; -+ -+public interface KeyedObject { -+ MinecraftKey getMinecraftKey(); -+ default String getMinecraftKeyString() { -+ MinecraftKey key = getMinecraftKey(); -+ return key != null ? key.toString() : null; -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 3c8767d5fab575e61ca179b517f0bff1a38405ce..ec553e7d7595ef3652bfa3325a07483bb3c32245 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -136,7 +136,7 @@ import org.bukkit.event.player.PlayerTeleportEvent; - import org.bukkit.plugin.PluginManager; - // CraftBukkit end - --public abstract class Entity implements INamableTileEntity, ICommandListener { -+public abstract class Entity implements INamableTileEntity, ICommandListener, net.minecraft.server.KeyedObject { // Paper - - // CraftBukkit start - private static final int CURRENT_LEVEL = 2; -@@ -1762,12 +1762,31 @@ public abstract class Entity implements INamableTileEntity, ICommandListener { - return true; - } - -+ // Paper start -+ private MinecraftKey entityKey; -+ private String entityKeyString; -+ -+ @Override -+ public MinecraftKey getMinecraftKey() { -+ if (entityKey == null) { -+ this.entityKey = EntityTypes.getName(this.getEntityType()); -+ this.entityKeyString = this.entityKey != null ? this.entityKey.toString() : null; -+ } -+ return entityKey; -+ } -+ -+ @Override -+ public String getMinecraftKeyString() { -+ getMinecraftKey(); // Try to load if it doesn't exists. see: https://github.com/PaperMC/Paper/issues/1280 -+ return entityKeyString; -+ } - @Nullable - public final String getSaveID() { - EntityTypes entitytypes = this.getEntityType(); - MinecraftKey minecraftkey = EntityTypes.getName(entitytypes); - -- return entitytypes.a() && minecraftkey != null ? minecraftkey.toString() : null; -+ return entitytypes != null && entitytypes.isPersistable() ? getMinecraftKeyString() : null; -+ // Paper end - } - - protected abstract void loadData(NBTTagCompound nbttagcompound); -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index ac57ab9992e141c91cf48f033148ad78433b364c..dc92b112770955f9fa49a408262da2e5bbc4bf98 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -384,6 +384,7 @@ public class EntityTypes { - } - } - -+ public boolean isPersistable() { return a(); } // Paper - OBFHELPER - public boolean a() { - return this.bi; - } -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 72d43b38de3e797a509de6591874af12fa7b9ec0..2b58ae6d91fe0d0f36eedbb78a3c8a8a66d92405 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -23,7 +23,7 @@ import org.bukkit.inventory.InventoryHolder; - - import org.spigotmc.CustomTimingsHandler; // Spigot - --public abstract class TileEntity { -+public abstract class TileEntity implements net.minecraft.server.KeyedObject { // Paper - - public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot - // CraftBukkit start - data containers -@@ -31,7 +31,7 @@ public abstract class TileEntity { - public CraftPersistentDataContainer persistentDataContainer; - // CraftBukkit end - private static final Logger LOGGER = LogManager.getLogger(); -- private final TileEntityTypes tileType; -+ private final TileEntityTypes tileType; public TileEntityTypes getTileEntityType() { return tileType; } // Paper - OBFHELPER - @Nullable - protected World world; - protected BlockPosition position; -@@ -45,6 +45,26 @@ public abstract class TileEntity { - this.tileType = tileentitytypes; - } - -+ // Paper start -+ private String tileEntityKeyString = null; -+ private MinecraftKey tileEntityKey = null; -+ -+ @Override -+ public MinecraftKey getMinecraftKey() { -+ if (tileEntityKey == null) { -+ tileEntityKey = TileEntityTypes.a(this.getTileEntityType()); -+ tileEntityKeyString = tileEntityKey != null ? tileEntityKey.toString() : null; -+ } -+ return tileEntityKey; -+ } -+ -+ @Override -+ public String getMinecraftKeyString() { -+ getMinecraftKey(); // Try to load if it doesn't exists. -+ return tileEntityKeyString; -+ } -+ // Paper end -+ - @Nullable - public World getWorld() { - return this.world; diff --git a/Unmapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch b/Unmapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch deleted file mode 100644 index 873dc9de7e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 02:10:36 -0400 -Subject: [PATCH] Store reference to current Chunk for Entity and Block - Entities - -This enables us a fast reference to the entities current chunk instead -of having to look it up by hashmap lookups. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index ec553e7d7595ef3652bfa3325a07483bb3c32245..2bea2f4748cadf479dd4f89792ef5ffdd88e9cab 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -261,7 +261,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean isChunkLoaded() { -- return world.isChunkLoaded((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); -+ return getCurrentChunk() != null; - } - // CraftBukkit end - -@@ -1763,6 +1763,23 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - // Paper start -+ public java.lang.ref.WeakReference currentChunk = null; -+ -+ public void setCurrentChunk(net.minecraft.world.level.chunk.Chunk chunk) { -+ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; -+ } -+ /** -+ * Returns the entities current registered chunk. If the entity is not added to a chunk yet, it will return null -+ */ -+ public net.minecraft.world.level.chunk.Chunk getCurrentChunk() { -+ final net.minecraft.world.level.chunk.Chunk chunk = currentChunk != null ? currentChunk.get() : null; -+ if (chunk != null && chunk.loaded) { -+ return chunk; -+ } -+ -+ return !inChunk ? null : ((WorldServer)world).getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(chunkX, chunkZ); -+ } -+ - private MinecraftKey entityKey; - private String entityKeyString; - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 2b58ae6d91fe0d0f36eedbb78a3c8a8a66d92405..75110c41af3e0097aef65091a2497dd87d08b4b2 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -11,6 +11,7 @@ import net.minecraft.world.level.World; - import net.minecraft.world.level.block.EnumBlockMirror; - import net.minecraft.world.level.block.EnumBlockRotation; - import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.Chunk; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - import org.apache.logging.log4j.util.Supplier; -@@ -63,6 +64,15 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - getMinecraftKey(); // Try to load if it doesn't exists. - return tileEntityKeyString; - } -+ -+ private java.lang.ref.WeakReference currentChunk = null; -+ public Chunk getCurrentChunk() { -+ final Chunk chunk = currentChunk != null ? currentChunk.get() : null; -+ return chunk != null && chunk.loaded ? chunk : null; -+ } -+ public void setCurrentChunk(Chunk chunk) { -+ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; -+ } - // Paper end - - @Nullable -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index b15200c2a3923bd8be2ee5e73fdadfeea3e3a8dc..929f6fcd4b9f1b9a1488e170d6a77a5d64beecf3 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -90,11 +90,36 @@ public class Chunk implements IChunkAccess { - this(world, chunkcoordintpair, biomestorage, ChunkConverter.a, TickListEmpty.b(), TickListEmpty.b(), 0L, (ChunkSection[]) null, (Consumer) null); - } - -+ // Paper start -+ private class TileEntityHashMap extends java.util.HashMap { -+ @Override -+ public TileEntity put(BlockPosition key, TileEntity value) { -+ TileEntity replaced = super.put(key, value); -+ if (replaced != null) { -+ replaced.setCurrentChunk(null); -+ } -+ if (value != null) { -+ value.setCurrentChunk(Chunk.this); -+ } -+ return replaced; -+ } -+ -+ @Override -+ public TileEntity remove(Object key) { -+ TileEntity removed = super.remove(key); -+ if (removed != null) { -+ removed.setCurrentChunk(null); -+ } -+ return removed; -+ } -+ } -+ // Paper end -+ - public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList ticklist, TickList ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer consumer) { - this.sections = new ChunkSection[16]; - this.e = Maps.newHashMap(); - this.heightMap = Maps.newEnumMap(HeightMap.Type.class); -- this.tileEntities = Maps.newHashMap(); -+ this.tileEntities = new TileEntityHashMap(); // Paper - this.l = Maps.newHashMap(); - this.m = Maps.newHashMap(); - this.n = new ShortList[16]; -@@ -505,6 +530,7 @@ public class Chunk implements IChunkAccess { - } - - entity.inChunk = true; -+ entity.setCurrentChunk(this); // Paper - entity.chunkX = this.loc.x; - entity.chunkY = k; - entity.chunkZ = this.loc.z; -@@ -517,6 +543,7 @@ public class Chunk implements IChunkAccess { - ((HeightMap) this.heightMap.get(heightmap_type)).a(along); - } - -+ public final void removeEntity(Entity entity) { this.b(entity); } // Paper - OBFHELPER - public void b(Entity entity) { - this.a(entity, entity.chunkY); - } -@@ -531,7 +558,12 @@ public class Chunk implements IChunkAccess { - i = this.entitySlices.length - 1; - } - -- this.entitySlices[i].remove(entity); -+ // Paper start -+ if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); -+ if (!this.entitySlices[i].remove(entity)) { -+ return; -+ } -+ // Paper end - this.entities.remove(entity); // Paper - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index df7e5f1d17ddfeffc15df02906c3bf9f9461d82b..eea242af23825ad29ada6e997205e87edffb6bb9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -145,6 +145,7 @@ import net.minecraft.world.entity.vehicle.EntityMinecartMobSpawner; - import net.minecraft.world.entity.vehicle.EntityMinecartRideable; - import net.minecraft.world.entity.vehicle.EntityMinecartTNT; - import net.minecraft.world.phys.AxisAlignedBB; -+import org.bukkit.Chunk; // Paper - import org.bukkit.EntityEffect; - import org.bukkit.Location; - import org.bukkit.Server; -@@ -186,6 +187,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - this.entity = entity; - } - -+ @Override -+ public Chunk getChunk() { -+ net.minecraft.world.level.chunk.Chunk currentChunk = entity.getCurrentChunk(); -+ return currentChunk != null ? currentChunk.bukkitChunk : getLocation().getChunk(); -+ } -+ - public static CraftEntity getEntity(CraftServer server, Entity entity) { - /* - * Order is *EXTREMELY* important -- keep it right! =D diff --git a/Unmapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch b/Unmapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch deleted file mode 100644 index 73d224306f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 02:13:59 -0400 -Subject: [PATCH] Store counts for each Entity/Block Entity Type - -Opens door for future patches to optimize performance - -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 929f6fcd4b9f1b9a1488e170d6a77a5d64beecf3..acdcece38a4b30d6c89eb4342918ae8997db9f0b 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -91,15 +91,19 @@ public class Chunk implements IChunkAccess { - } - - // Paper start -+ public final co.aikar.util.Counter entityCounts = new co.aikar.util.Counter<>(); -+ public final co.aikar.util.Counter tileEntityCounts = new co.aikar.util.Counter<>(); - private class TileEntityHashMap extends java.util.HashMap { - @Override - public TileEntity put(BlockPosition key, TileEntity value) { - TileEntity replaced = super.put(key, value); - if (replaced != null) { - replaced.setCurrentChunk(null); -+ tileEntityCounts.decrement(replaced.getMinecraftKeyString()); - } - if (value != null) { - value.setCurrentChunk(Chunk.this); -+ tileEntityCounts.increment(value.getMinecraftKeyString()); - } - return replaced; - } -@@ -109,6 +113,7 @@ public class Chunk implements IChunkAccess { - TileEntity removed = super.remove(key); - if (removed != null) { - removed.setCurrentChunk(null); -+ tileEntityCounts.decrement(removed.getMinecraftKeyString()); - } - return removed; - } -@@ -529,6 +534,7 @@ public class Chunk implements IChunkAccess { - k = this.entitySlices.length - 1; - } - -+ if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper - entity.inChunk = true; - entity.setCurrentChunk(this); // Paper - entity.chunkX = this.loc.x; -@@ -563,6 +569,7 @@ public class Chunk implements IChunkAccess { - if (!this.entitySlices[i].remove(entity)) { - return; - } -+ entityCounts.decrement(entity.getMinecraftKeyString()); - // Paper end - this.entities.remove(entity); // Paper - } diff --git a/Unmapped-Spigot-Server-Patches/0009-Timings-v2.patch b/Unmapped-Spigot-Server-Patches/0009-Timings-v2.patch deleted file mode 100644 index 6113ef6b52..0000000000 --- a/Unmapped-Spigot-Server-Patches/0009-Timings-v2.patch +++ /dev/null @@ -1,2309 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 04:00:11 -0600 -Subject: [PATCH] Timings v2 - - -diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fed920e5ec65409377f181d74dcf9274d45aadc1 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -0,0 +1,151 @@ -+package co.aikar.timings; -+ -+import com.google.common.collect.MapMaker; -+import net.minecraft.commands.CustomFunction; -+import net.minecraft.network.protocol.Packet; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.TileEntity; -+import org.bukkit.plugin.Plugin; -+import org.bukkit.scheduler.BukkitTask; -+ -+import org.bukkit.craftbukkit.scheduler.CraftTask; -+ -+import java.util.Map; -+ -+// TODO: Re-implement missing timers -+public final class MinecraftTimings { -+ -+ public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); -+ public static final Timing playerListTimer = Timings.ofSafe("Player List"); -+ public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); -+ public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); -+ public static final Timing tickablesTimer = Timings.ofSafe("Tickables"); -+ public static final Timing minecraftSchedulerTimer = Timings.ofSafe("Minecraft Scheduler"); -+ public static final Timing bukkitSchedulerTimer = Timings.ofSafe("Bukkit Scheduler"); -+ public static final Timing bukkitSchedulerPendingTimer = Timings.ofSafe("Bukkit Scheduler - Pending"); -+ public static final Timing bukkitSchedulerFinishTimer = Timings.ofSafe("Bukkit Scheduler - Finishing"); -+ public static final Timing chunkIOTickTimer = Timings.ofSafe("ChunkIOTick"); -+ public static final Timing timeUpdateTimer = Timings.ofSafe("Time Update"); -+ public static final Timing serverCommandTimer = Timings.ofSafe("Server Command"); -+ public static final Timing savePlayers = Timings.ofSafe("Save Players"); -+ -+ public static final Timing tickEntityTimer = Timings.ofSafe("## tickEntity"); -+ public static final Timing tickTileEntityTimer = Timings.ofSafe("## tickTileEntity"); -+ public static final Timing packetProcessTimer = Timings.ofSafe("## Packet Processing"); -+ public static final Timing scheduledBlocksTimer = Timings.ofSafe("## Scheduled Blocks"); -+ public static final Timing structureGenerationTimer = Timings.ofSafe("Structure Generation"); -+ -+ public static final Timing processQueueTimer = Timings.ofSafe("processQueue"); -+ public static final Timing processTasksTimer = Timings.ofSafe("processTasks"); -+ -+ public static final Timing playerCommandTimer = Timings.ofSafe("playerCommand"); -+ -+ public static final Timing entityActivationCheckTimer = Timings.ofSafe("entityActivationCheck"); -+ -+ public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update"); -+ public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate"); -+ -+ private static final Map, String> taskNameCache = new MapMaker().weakKeys().makeMap(); -+ -+ private MinecraftTimings() {} -+ -+ public static Timing getInternalTaskName(String taskName) { -+ return Timings.ofSafe(taskName); -+ } -+ -+ /** -+ * Gets a timer associated with a plugins tasks. -+ * @param bukkitTask -+ * @param period -+ * @return -+ */ -+ public static Timing getPluginTaskTimings(BukkitTask bukkitTask, long period) { -+ if (!bukkitTask.isSync()) { -+ return NullTimingHandler.NULL; -+ } -+ Plugin plugin; -+ -+ CraftTask craftTask = (CraftTask) bukkitTask; -+ -+ final Class taskClass = craftTask.getTaskClass(); -+ if (bukkitTask.getOwner() != null) { -+ plugin = bukkitTask.getOwner(); -+ } else { -+ plugin = TimingsManager.getPluginByClassloader(taskClass); -+ } -+ -+ final String taskname = taskNameCache.computeIfAbsent(taskClass, clazz -> { -+ try { -+ String clsName = !clazz.isMemberClass() -+ ? clazz.getName() -+ : clazz.getCanonicalName(); -+ if (clsName != null && clsName.contains("$Lambda$")) { -+ clsName = clsName.replaceAll("(Lambda\\$.*?)/.*", "$1"); -+ } -+ return clsName != null ? clsName : "UnknownTask"; -+ } catch (Throwable ex) { -+ new Exception("Error occurred detecting class name", ex).printStackTrace(); -+ return "MangledClassFile"; -+ } -+ }); -+ -+ StringBuilder name = new StringBuilder(64); -+ name.append("Task: ").append(taskname); -+ if (period > 0) { -+ name.append(" (interval:").append(period).append(")"); -+ } else { -+ name.append(" (Single)"); -+ } -+ -+ if (plugin == null) { -+ return Timings.ofSafe(null, name.toString()); -+ } -+ -+ return Timings.ofSafe(plugin, name.toString()); -+ } -+ -+ /** -+ * Get a named timer for the specified entity type to track type specific timings. -+ * @param entityType -+ * @return -+ */ -+ public static Timing getEntityTimings(String entityType, String type) { -+ return Timings.ofSafe("Minecraft", "## tickEntity - " + entityType + " - " + type, tickEntityTimer); -+ } -+ -+ /** -+ * Get a named timer for the specified tile entity type to track type specific timings. -+ * @param entity -+ * @return -+ */ -+ public static Timing getTileEntityTimings(TileEntity entity) { -+ String entityType = entity.getClass().getName(); -+ return Timings.ofSafe("Minecraft", "## tickTileEntity - " + entityType, tickTileEntityTimer); -+ } -+ public static Timing getCancelTasksTimer() { -+ return Timings.ofSafe("Cancel Tasks"); -+ } -+ public static Timing getCancelTasksTimer(Plugin plugin) { -+ return Timings.ofSafe(plugin, "Cancel Tasks"); -+ } -+ -+ public static void stopServer() { -+ TimingsManager.stopServer(); -+ } -+ -+ public static Timing getBlockTiming(Block block) { -+ return Timings.ofSafe("## Scheduled Block: " + block.toString(), scheduledBlocksTimer); -+ } -+/* -+ public static Timing getStructureTiming(StructureGenerator structureGenerator) { -+ return Timings.ofSafe("Structure Generator - " + structureGenerator.getName(), structureGenerationTimer); -+ }*/ -+ -+ public static Timing getPacketTiming(Packet packet) { -+ return Timings.ofSafe("## Packet - " + packet.getClass().getName(), packetProcessTimer); -+ } -+ -+ public static Timing getCommandFunctionTiming(CustomFunction function) { -+ return Timings.ofSafe("Command Function - " + function.getMinecraftKey().toString()); -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d4ebcf8f66197299256bd6b65710a1488c90ea41 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -0,0 +1,377 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import com.google.common.collect.Sets; -+import net.minecraft.server.MinecraftServer; -+import org.apache.commons.lang.StringUtils; -+import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; -+import org.bukkit.Material; -+import org.bukkit.configuration.ConfigurationSection; -+import org.bukkit.configuration.MemorySection; -+import org.bukkit.craftbukkit.util.CraftChatMessage; -+import org.bukkit.entity.EntityType; -+import org.json.simple.JSONObject; -+import org.json.simple.JSONValue; -+ -+import java.io.ByteArrayOutputStream; -+import java.io.IOException; -+import java.io.InputStream; -+import java.io.OutputStream; -+import java.lang.management.ManagementFactory; -+import java.lang.management.OperatingSystemMXBean; -+import java.lang.management.RuntimeMXBean; -+import java.net.HttpURLConnection; -+import java.net.InetAddress; -+import java.net.URL; -+import java.util.List; -+import java.util.Map; -+import java.util.Set; -+import java.util.logging.Level; -+import java.util.zip.GZIPOutputStream; -+ -+import static co.aikar.timings.TimingsManager.HISTORY; -+import static co.aikar.util.JSONUtil.appendObjectData; -+import static co.aikar.util.JSONUtil.createObject; -+import static co.aikar.util.JSONUtil.pair; -+import static co.aikar.util.JSONUtil.toArray; -+import static co.aikar.util.JSONUtil.toArrayMapper; -+import static co.aikar.util.JSONUtil.toObjectMapper; -+ -+@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) -+public class TimingsExport extends Thread { -+ -+ private final TimingsReportListener listeners; -+ private final Map out; -+ private final TimingHistory[] history; -+ private static long lastReport = 0; -+ -+ private TimingsExport(TimingsReportListener listeners, Map out, TimingHistory[] history) { -+ super("Timings paste thread"); -+ this.listeners = listeners; -+ this.out = out; -+ this.history = history; -+ } -+ -+ /** -+ * Checks if any pending reports are being requested, and builds one if needed. -+ */ -+ public static void reportTimings() { -+ if (Timings.requestingReport.isEmpty()) { -+ return; -+ } -+ TimingsReportListener listeners = new TimingsReportListener(Timings.requestingReport); -+ listeners.addConsoleIfNeeded(); -+ -+ Timings.requestingReport.clear(); -+ long now = System.currentTimeMillis(); -+ final long lastReportDiff = now - lastReport; -+ if (lastReportDiff < 60000) { -+ listeners.sendMessage(ChatColor.RED + "Please wait at least 1 minute in between Timings reports. (" + (int)((60000 - lastReportDiff) / 1000) + " seconds)"); -+ listeners.done(); -+ return; -+ } -+ final long lastStartDiff = now - TimingsManager.timingStart; -+ if (lastStartDiff < 180000) { -+ listeners.sendMessage(ChatColor.RED + "Please wait at least 3 minutes before generating a Timings report. Unlike Timings v1, v2 benefits from longer timings and is not as useful with short timings. (" + (int)((180000 - lastStartDiff) / 1000) + " seconds)"); -+ listeners.done(); -+ return; -+ } -+ listeners.sendMessage(ChatColor.GREEN + "Preparing Timings Report..."); -+ lastReport = now; -+ Map parent = createObject( -+ // Get some basic system details about the server -+ pair("version", Bukkit.getVersion()), -+ pair("maxplayers", Bukkit.getMaxPlayers()), -+ pair("start", TimingsManager.timingStart / 1000), -+ pair("end", System.currentTimeMillis() / 1000), -+ pair("online-mode", Bukkit.getServer().getOnlineMode()), -+ pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), -+ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().d(), pack -> { -+ // Don't feel like obf helper'ing these, non fatal if its temp missed. -+ return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); -+ })) -+ ); -+ if (!TimingsManager.privacy) { -+ appendObjectData(parent, -+ pair("server", Bukkit.getUnsafe().getTimingsServerName()), -+ pair("motd", Bukkit.getServer().getMotd()), -+ pair("icon", Bukkit.getServer().getServerIcon().getData()) -+ ); -+ } -+ -+ final Runtime runtime = Runtime.getRuntime(); -+ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); -+ -+ OperatingSystemMXBean osInfo = ManagementFactory.getOperatingSystemMXBean(); -+ -+ parent.put("system", createObject( -+ pair("timingcost", getCost()), -+ pair("loadavg", osInfo.getSystemLoadAverage()), -+ pair("name", System.getProperty("os.name")), -+ pair("version", System.getProperty("os.version")), -+ pair("jvmversion", System.getProperty("java.version")), -+ pair("arch", System.getProperty("os.arch")), -+ pair("maxmem", runtime.maxMemory()), -+ pair("memory", createObject( -+ pair("heap", ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().toString()), -+ pair("nonheap", ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().toString()), -+ pair("finalizing", ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount()) -+ )), -+ pair("cpu", runtime.availableProcessors()), -+ pair("runtime", runtimeBean.getUptime()), -+ pair("flags", StringUtils.join(runtimeBean.getInputArguments(), " ")), -+ pair("gc", toObjectMapper(ManagementFactory.getGarbageCollectorMXBeans(), input -> pair(input.getName(), toArray(input.getCollectionCount(), input.getCollectionTime())))) -+ ) -+ ); -+ -+ parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getWorlds(), world -> { -+ if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; -+ return pair(world.getWorldData().getName(), createObject( -+ pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { -+ return pair(rule, world.getWorld().getGameRuleValue(rule)); -+ })), -+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) -+ )); -+ })); -+ -+ Set tileEntityTypeSet = Sets.newHashSet(); -+ Set entityTypeSet = Sets.newHashSet(); -+ -+ int size = HISTORY.size(); -+ TimingHistory[] history = new TimingHistory[size + 1]; -+ int i = 0; -+ for (TimingHistory timingHistory : HISTORY) { -+ tileEntityTypeSet.addAll(timingHistory.tileEntityTypeSet); -+ entityTypeSet.addAll(timingHistory.entityTypeSet); -+ history[i++] = timingHistory; -+ } -+ -+ history[i] = new TimingHistory(); // Current snapshot -+ tileEntityTypeSet.addAll(history[i].tileEntityTypeSet); -+ entityTypeSet.addAll(history[i].entityTypeSet); -+ -+ -+ Map handlers = createObject(); -+ Map groupData; -+ synchronized (TimingIdentifier.GROUP_MAP) { -+ for (TimingIdentifier.TimingGroup group : TimingIdentifier.GROUP_MAP.values()) { -+ synchronized (group.handlers) { -+ for (TimingHandler id : group.handlers) { -+ -+ if (!id.isTimed() && !id.isSpecial()) { -+ continue; -+ } -+ -+ String name = id.identifier.name; -+ if (name.startsWith("##")) { -+ name = name.substring(3); -+ } -+ handlers.put(id.id, toArray( -+ group.id, -+ name -+ )); -+ } -+ } -+ } -+ -+ groupData = toObjectMapper( -+ TimingIdentifier.GROUP_MAP.values(), group -> pair(group.id, group.name)); -+ } -+ -+ parent.put("idmap", createObject( -+ pair("groups", groupData), -+ pair("handlers", handlers), -+ pair("worlds", toObjectMapper(TimingHistory.worldMap.entrySet(), input -> pair(input.getValue(), input.getKey()))), -+ pair("tileentity", -+ toObjectMapper(tileEntityTypeSet, input -> pair(input.ordinal(), input.name()))), -+ pair("entity", -+ toObjectMapper(entityTypeSet, input -> pair(input.ordinal(), input.name()))) -+ )); -+ -+ // Information about loaded plugins -+ -+ parent.put("plugins", toObjectMapper(Bukkit.getPluginManager().getPlugins(), -+ plugin -> pair(plugin.getName(), createObject( -+ pair("version", plugin.getDescription().getVersion()), -+ pair("description", String.valueOf(plugin.getDescription().getDescription()).trim()), -+ pair("website", plugin.getDescription().getWebsite()), -+ pair("authors", StringUtils.join(plugin.getDescription().getAuthors(), ", ")) -+ )))); -+ -+ -+ -+ // Information on the users Config -+ -+ parent.put("config", createObject( -+ pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), -+ pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), -+ pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) -+ )); -+ -+ new TimingsExport(listeners, parent, history).start(); -+ } -+ -+ static long getCost() { -+ // Benchmark the users System.nanotime() for cost basis -+ int passes = 100; -+ TimingHandler SAMPLER1 = Timings.ofSafe("Timings Sampler 1"); -+ TimingHandler SAMPLER2 = Timings.ofSafe("Timings Sampler 2"); -+ TimingHandler SAMPLER3 = Timings.ofSafe("Timings Sampler 3"); -+ TimingHandler SAMPLER4 = Timings.ofSafe("Timings Sampler 4"); -+ TimingHandler SAMPLER5 = Timings.ofSafe("Timings Sampler 5"); -+ TimingHandler SAMPLER6 = Timings.ofSafe("Timings Sampler 6"); -+ -+ long start = System.nanoTime(); -+ for (int i = 0; i < passes; i++) { -+ SAMPLER1.startTiming(); -+ SAMPLER2.startTiming(); -+ SAMPLER3.startTiming(); -+ SAMPLER3.stopTiming(); -+ SAMPLER4.startTiming(); -+ SAMPLER5.startTiming(); -+ SAMPLER6.startTiming(); -+ SAMPLER6.stopTiming(); -+ SAMPLER5.stopTiming(); -+ SAMPLER4.stopTiming(); -+ SAMPLER2.stopTiming(); -+ SAMPLER1.stopTiming(); -+ } -+ long timingsCost = (System.nanoTime() - start) / passes / 6; -+ SAMPLER1.reset(true); -+ SAMPLER2.reset(true); -+ SAMPLER3.reset(true); -+ SAMPLER4.reset(true); -+ SAMPLER5.reset(true); -+ SAMPLER6.reset(true); -+ return timingsCost; -+ } -+ -+ private static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) { -+ -+ JSONObject object = new JSONObject(); -+ for (String key : config.getKeys(false)) { -+ String fullKey = (parentKey != null ? parentKey + "." + key : key); -+ if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld")) { -+ continue; -+ } -+ final Object val = config.get(key); -+ -+ object.put(key, valAsJSON(val, fullKey)); -+ } -+ return object; -+ } -+ -+ private static Object valAsJSON(Object val, final String parentKey) { -+ if (!(val instanceof MemorySection)) { -+ if (val instanceof List) { -+ Iterable v = (Iterable) val; -+ return toArrayMapper(v, input -> valAsJSON(input, parentKey)); -+ } else { -+ return String.valueOf(val); -+ } -+ } else { -+ return mapAsJSON((ConfigurationSection) val, parentKey); -+ } -+ } -+ -+ @Override -+ public void run() { -+ out.put("data", toArrayMapper(history, TimingHistory::export)); -+ -+ -+ String response = null; -+ String timingsURL = null; -+ try { -+ HttpURLConnection con = (HttpURLConnection) new URL("http://timings.aikar.co/post").openConnection(); -+ con.setDoOutput(true); -+ String hostName = "BrokenHost"; -+ try { -+ hostName = InetAddress.getLocalHost().getHostName(); -+ } catch (Exception ignored) {} -+ con.setRequestProperty("User-Agent", "Paper/" + Bukkit.getUnsafe().getTimingsServerName() + "/" + hostName); -+ con.setRequestMethod("POST"); -+ con.setInstanceFollowRedirects(false); -+ -+ OutputStream request = new GZIPOutputStream(con.getOutputStream()) {{ -+ this.def.setLevel(7); -+ }}; -+ -+ request.write(JSONValue.toJSONString(out).getBytes("UTF-8")); -+ request.close(); -+ -+ response = getResponse(con); -+ -+ if (con.getResponseCode() != 302) { -+ listeners.sendMessage( -+ ChatColor.RED + "Upload Error: " + con.getResponseCode() + ": " + con.getResponseMessage()); -+ listeners.sendMessage(ChatColor.RED + "Check your logs for more information"); -+ if (response != null) { -+ Bukkit.getLogger().log(Level.SEVERE, response); -+ } -+ return; -+ } -+ -+ timingsURL = con.getHeaderField("Location"); -+ listeners.sendMessage(ChatColor.GREEN + "View Timings Report: " + timingsURL); -+ -+ if (response != null && !response.isEmpty()) { -+ Bukkit.getLogger().log(Level.INFO, "Timing Response: " + response); -+ } -+ } catch (IOException ex) { -+ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); -+ if (response != null) { -+ Bukkit.getLogger().log(Level.SEVERE, response); -+ } -+ Bukkit.getLogger().log(Level.SEVERE, "Could not paste timings", ex); -+ } finally { -+ this.listeners.done(timingsURL); -+ } -+ } -+ -+ private String getResponse(HttpURLConnection con) throws IOException { -+ InputStream is = null; -+ try { -+ is = con.getInputStream(); -+ ByteArrayOutputStream bos = new ByteArrayOutputStream(); -+ -+ byte[] b = new byte[1024]; -+ int bytesRead; -+ while ((bytesRead = is.read(b)) != -1) { -+ bos.write(b, 0, bytesRead); -+ } -+ return bos.toString(); -+ -+ } catch (IOException ex) { -+ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); -+ Bukkit.getLogger().log(Level.WARNING, con.getResponseMessage(), ex); -+ return null; -+ } finally { -+ if (is != null) { -+ is.close(); -+ } -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fa154ed68187a2020e814db6345a8cc1119ab4ba ---- /dev/null -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -0,0 +1,119 @@ -+package co.aikar.timings; -+ -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.storage.WorldDataServer; -+ -+/** -+ * Set of timers per world, to track world specific timings. -+ */ -+// TODO: Re-implement missing timers -+public class WorldTimingsHandler { -+ public final Timing mobSpawn; -+ public final Timing doChunkUnload; -+ public final Timing doPortalForcer; -+ public final Timing scheduledBlocks; -+ public final Timing scheduledBlocksCleanup; -+ public final Timing scheduledBlocksTicking; -+ public final Timing chunkTicks; -+ public final Timing lightChunk; -+ public final Timing chunkTicksBlocks; -+ public final Timing doVillages; -+ public final Timing doChunkMap; -+ public final Timing doChunkMapUpdate; -+ public final Timing doChunkMapToUpdate; -+ public final Timing doChunkMapSortMissing; -+ public final Timing doChunkMapSortSendToPlayers; -+ public final Timing doChunkMapPlayersNeedingChunks; -+ public final Timing doChunkMapPendingSendToPlayers; -+ public final Timing doChunkMapUnloadChunks; -+ public final Timing doChunkGC; -+ public final Timing doSounds; -+ public final Timing entityRemoval; -+ public final Timing entityTick; -+ public final Timing tileEntityTick; -+ public final Timing tileEntityPending; -+ public final Timing tracker1; -+ public final Timing tracker2; -+ public final Timing doTick; -+ public final Timing tickEntities; -+ public final Timing chunks; -+ public final Timing newEntities; -+ public final Timing raids; -+ public final Timing chunkProviderTick; -+ public final Timing broadcastChunkUpdates; -+ public final Timing countNaturalMobs; -+ -+ public final Timing chunkLoad; -+ public final Timing chunkLoadPopulate; -+ public final Timing syncChunkLoad; -+ public final Timing chunkLoadLevelTimer; -+ public final Timing chunkIO; -+ public final Timing chunkPostLoad; -+ public final Timing worldSave; -+ public final Timing worldSaveChunks; -+ public final Timing worldSaveLevel; -+ public final Timing chunkSaveData; -+ -+ -+ public final Timing miscMobSpawning; -+ -+ public WorldTimingsHandler(World server) { -+ String name = ((WorldDataServer) server.getWorldData()).getName() + " - "; -+ -+ mobSpawn = Timings.ofSafe(name + "mobSpawn"); -+ doChunkUnload = Timings.ofSafe(name + "doChunkUnload"); -+ scheduledBlocks = Timings.ofSafe(name + "Scheduled Blocks"); -+ scheduledBlocksCleanup = Timings.ofSafe(name + "Scheduled Blocks - Cleanup"); -+ scheduledBlocksTicking = Timings.ofSafe(name + "Scheduled Blocks - Ticking"); -+ chunkTicks = Timings.ofSafe(name + "Chunk Ticks"); -+ lightChunk = Timings.ofSafe(name + "Light Chunk"); -+ chunkTicksBlocks = Timings.ofSafe(name + "Chunk Ticks - Blocks"); -+ doVillages = Timings.ofSafe(name + "doVillages"); -+ doChunkMap = Timings.ofSafe(name + "doChunkMap"); -+ doChunkMapUpdate = Timings.ofSafe(name + "doChunkMap - Update"); -+ doChunkMapToUpdate = Timings.ofSafe(name + "doChunkMap - To Update"); -+ doChunkMapSortMissing = Timings.ofSafe(name + "doChunkMap - Sort Missing"); -+ doChunkMapSortSendToPlayers = Timings.ofSafe(name + "doChunkMap - Sort Send To Players"); -+ doChunkMapPlayersNeedingChunks = Timings.ofSafe(name + "doChunkMap - Players Needing Chunks"); -+ doChunkMapPendingSendToPlayers = Timings.ofSafe(name + "doChunkMap - Pending Send To Players"); -+ doChunkMapUnloadChunks = Timings.ofSafe(name + "doChunkMap - Unload Chunks"); -+ doSounds = Timings.ofSafe(name + "doSounds"); -+ doChunkGC = Timings.ofSafe(name + "doChunkGC"); -+ doPortalForcer = Timings.ofSafe(name + "doPortalForcer"); -+ entityTick = Timings.ofSafe(name + "entityTick"); -+ entityRemoval = Timings.ofSafe(name + "entityRemoval"); -+ tileEntityTick = Timings.ofSafe(name + "tileEntityTick"); -+ tileEntityPending = Timings.ofSafe(name + "tileEntityPending"); -+ -+ chunkLoad = Timings.ofSafe(name + "Chunk Load"); -+ chunkLoadPopulate = Timings.ofSafe(name + "Chunk Load - Populate"); -+ syncChunkLoad = Timings.ofSafe(name + "Sync Chunk Load"); -+ chunkLoadLevelTimer = Timings.ofSafe(name + "Chunk Load - Load Level"); -+ chunkIO = Timings.ofSafe(name + "Chunk Load - DiskIO"); -+ chunkPostLoad = Timings.ofSafe(name + "Chunk Load - Post Load"); -+ worldSave = Timings.ofSafe(name + "World Save"); -+ worldSaveLevel = Timings.ofSafe(name + "World Save - Level"); -+ worldSaveChunks = Timings.ofSafe(name + "World Save - Chunks"); -+ chunkSaveData = Timings.ofSafe(name + "Chunk Save - Data"); -+ -+ tracker1 = Timings.ofSafe(name + "tracker stage 1"); -+ tracker2 = Timings.ofSafe(name + "tracker stage 2"); -+ doTick = Timings.ofSafe(name + "doTick"); -+ tickEntities = Timings.ofSafe(name + "tickEntities"); -+ -+ chunks = Timings.ofSafe(name + "Chunks"); -+ newEntities = Timings.ofSafe(name + "New entity registration"); -+ raids = Timings.ofSafe(name + "Raids"); -+ chunkProviderTick = Timings.ofSafe(name + "Chunk provider tick"); -+ broadcastChunkUpdates = Timings.ofSafe(name + "Broadcast chunk updates"); -+ countNaturalMobs = Timings.ofSafe(name + "Count natural mobs"); -+ -+ -+ miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ } -+ -+ public static Timing getTickList(WorldServer worldserver, String timingsType) { -+ return Timings.ofSafe(((WorldDataServer) worldserver.getWorldData()).getName() + " - Scheduled " + timingsType); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index da922f395f0fff0881ead893c900c5b2623f48f0..1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -14,12 +14,15 @@ import java.util.concurrent.TimeUnit; - import java.util.logging.Level; - import java.util.regex.Pattern; - -+import com.google.common.collect.Lists; - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; - import org.bukkit.command.Command; - import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.InvalidConfigurationException; - import org.bukkit.configuration.file.YamlConfiguration; -+import co.aikar.timings.Timings; -+import co.aikar.timings.TimingsManager; - - public class PaperConfig { - -@@ -188,4 +191,30 @@ public class PaperConfig { - config.addDefault(path, def); - return config.getString(path, config.getString(path)); - } -+ -+ public static String timingsServerName; -+ private static void timings() { -+ boolean timings = getBoolean("timings.enabled", true); -+ boolean verboseTimings = getBoolean("timings.verbose", true); -+ TimingsManager.privacy = getBoolean("timings.server-name-privacy", false); -+ TimingsManager.hiddenConfigs = getList("timings.hidden-config-entries", Lists.newArrayList("database", "settings.bungeecord-addresses", "settings.velocity-support.secret")); -+ if (!TimingsManager.hiddenConfigs.contains("settings.velocity-support.secret")) { -+ TimingsManager.hiddenConfigs.add("settings.velocity-support.secret"); -+ } -+ int timingHistoryInterval = getInt("timings.history-interval", 300); -+ int timingHistoryLength = getInt("timings.history-length", 3600); -+ timingsServerName = getString("timings.server-name", "Unknown Server"); -+ -+ -+ Timings.setVerboseTimingsEnabled(verboseTimings); -+ Timings.setTimingsEnabled(timings); -+ Timings.setHistoryInterval(timingHistoryInterval * 20); -+ Timings.setHistoryLength(timingHistoryLength * 20); -+ -+ log("Timings: " + timings + -+ " - Verbose: " + verboseTimings + -+ " - Interval: " + timeSummary(Timings.getHistoryInterval() / 20) + -+ " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + -+ " - Server Name: " + timingsServerName); -+ } - } -diff --git a/src/main/java/net/minecraft/commands/CustomFunction.java b/src/main/java/net/minecraft/commands/CustomFunction.java -index f96b132bb51c2d97703964a70fcb058f0649ac13..4c146ac041332230f6d9a01be28b6852c7624416 100644 ---- a/src/main/java/net/minecraft/commands/CustomFunction.java -+++ b/src/main/java/net/minecraft/commands/CustomFunction.java -@@ -15,12 +15,22 @@ public class CustomFunction { - - private final CustomFunction.c[] a; - private final MinecraftKey b; -+ // Paper start -+ public co.aikar.timings.Timing timing; -+ public co.aikar.timings.Timing getTiming() { -+ if (timing == null) { -+ timing = co.aikar.timings.MinecraftTimings.getCommandFunctionTiming(this); -+ } -+ return timing; -+ } -+ // Paper end - - public CustomFunction(MinecraftKey minecraftkey, CustomFunction.c[] acustomfunction_c) { - this.b = minecraftkey; - this.a = acustomfunction_c; - } - -+ public final MinecraftKey getMinecraftKey() { return this.a(); } // Paper - OBFHELPER - public MinecraftKey a() { - return this.b; - } -diff --git a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -index 989683265a99fc51607aa130733e00033b444a6a..e47da20ab8ce4da34755e105bf55d8542fb50138 100644 ---- a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -+++ b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -@@ -6,6 +6,8 @@ import net.minecraft.server.level.WorldServer; - import net.minecraft.util.thread.IAsyncTaskHandler; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - // CraftBukkit start - import net.minecraft.server.MinecraftServer; -@@ -22,10 +24,13 @@ public class PlayerConnectionUtils { - - public static void ensureMainThread(Packet packet, T t0, IAsyncTaskHandler iasynctaskhandler) throws CancelledPacketHandleException { - if (!iasynctaskhandler.isMainThread()) { -+ Timing timing = MinecraftTimings.getPacketTiming(packet); // Paper - timings - iasynctaskhandler.execute(() -> { - if (MinecraftServer.getServer().hasStopped() || (t0 instanceof PlayerConnection && ((PlayerConnection) t0).processedDisconnect)) return; // CraftBukkit, MC-142590 - if (t0.a().isConnected()) { -+ try (Timing ignored = timing.startTiming()) { // Paper - timings - packet.a(t0); -+ } // Paper - timings - } else { - PlayerConnectionUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); - } -diff --git a/src/main/java/net/minecraft/server/CustomFunctionData.java b/src/main/java/net/minecraft/server/CustomFunctionData.java -index 21f5474a1cd60168ca059da542a432d40d88b514..07ca1234ad6ffa797003f7317fb88abf732bc159 100644 ---- a/src/main/java/net/minecraft/server/CustomFunctionData.java -+++ b/src/main/java/net/minecraft/server/CustomFunctionData.java -@@ -75,7 +75,7 @@ public class CustomFunctionData { - } else { - int j; - -- try { -+ try (co.aikar.timings.Timing timing = customfunction.getTiming().startTiming()) { // Paper - this.d = true; - int k = 0; - CustomFunction.c[] acustomfunction_c = customfunction.b(); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 5ce0dfade68257b51ad4a19a829e1fc0a0bbc3db..85c96e3f70a3ffecb6195a1d83053412eb180d78 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -174,7 +174,7 @@ import org.bukkit.craftbukkit.Main; - import org.bukkit.event.server.ServerLoadEvent; - // CraftBukkit end - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot - - public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { -@@ -228,8 +228,8 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -- return !this.canSleepForTick(); -+ return !this.canSleepForTickNoOversleep(); // Paper - move oversleep into full server tick - }); - } - -@@ -1122,10 +1135,18 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ return !this.canOversleep(); -+ }); -+ isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -+ // Paper end -+ - ++this.ticks; - this.b(booleansupplier); - if (i - this.T >= 5000000000L) { -@@ -1143,14 +1164,12 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit -- SpigotTimings.worldSaveTimer.startTiming(); // Spigot - MinecraftServer.LOGGER.debug("Autosave started"); - this.methodProfiler.enter("save"); - this.playerList.savePlayers(); - this.saveChunks(true, false, false); - this.methodProfiler.exit(); - MinecraftServer.LOGGER.debug("Autosave finished"); -- SpigotTimings.worldSaveTimer.stopTiming(); // Spigot - } - - this.methodProfiler.enter("snooper"); -@@ -1163,6 +1182,13 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { - // CraftBukkit start - fire RemoteServerCommandEvent -@@ -680,10 +682,39 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - if (event.isCancelled()) { - return; - } -+ // Paper start -+ if (s.toLowerCase().startsWith("timings") && s.toLowerCase().matches("timings (report|paste|get|merged|seperate)")) { -+ org.bukkit.command.BufferedCommandSender sender = new org.bukkit.command.BufferedCommandSender(); -+ Waitable waitable = new Waitable() { -+ @Override -+ protected String evaluate() { -+ return sender.getBuffer(); -+ } -+ }; -+ waitableArray[0] = waitable; -+ co.aikar.timings.Timings.generateReport(new co.aikar.timings.TimingsReportListener(sender, waitable)); -+ } else { -+ // Paper end - ServerCommand serverCommand = new ServerCommand(event.getCommand(), remoteControlCommandListener.getWrapper()); - server.dispatchServerCommand(remoteConsole, serverCommand); -+ } // Paper - // CraftBukkit end - }); -+ // Paper start -+ if (waitableArray[0] != null) { -+ //noinspection unchecked -+ Waitable waitable = waitableArray[0]; -+ try { -+ return waitable.get(); -+ } catch (java.util.concurrent.ExecutionException e) { -+ throw new RuntimeException("Exception processing rcon command " + s, e.getCause()); -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // Maintain interrupted state -+ throw new RuntimeException("Interrupted processing rcon command " + s, e); -+ } -+ -+ } -+ // Paper end - return this.remoteControlCommandListener.getMessages(); - } - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0b5bcb60472c778574702a5ac26a6d02d54bfeac..3351c6bcc5244fd7565ba7af08f63ea4d999ce97 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -344,11 +344,13 @@ public class ChunkProviderServer extends IChunkProvider { - } - - gameprofilerfiller.c("getChunkCacheMiss"); -- world.timings.syncChunkLoadTimer.startTiming(); // Spigot - CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag); - -+ if (!completablefuture.isDone()) { // Paper -+ this.world.timings.syncChunkLoad.startTiming(); // Paper - this.serverThreadQueue.awaitTasks(completablefuture::isDone); -- world.timings.syncChunkLoadTimer.stopTiming(); // Spigot -+ this.world.timings.syncChunkLoad.stopTiming(); // Paper -+ } // Paper - ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { - return ichunkaccess1; - }, (playerchunk_failure) -> { -@@ -535,7 +537,9 @@ public class ChunkProviderServer extends IChunkProvider { - - public void save(boolean flag) { - this.tickDistanceManager(); -+ try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { // Paper - Timings - this.playerChunkMap.save(flag); -+ } // Paper - Timings - } - - @Override -@@ -572,7 +576,9 @@ public class ChunkProviderServer extends IChunkProvider { - this.tickDistanceManager(); - this.world.timings.doChunkMap.stopTiming(); // Spigot - this.world.getMethodProfiler().exitEnter("chunks"); -+ this.world.timings.chunks.startTiming(); // Paper - timings - this.tickChunks(); -+ this.world.timings.chunks.stopTiming(); // Paper - timings - this.world.timings.doChunkUnload.startTiming(); // Spigot - this.world.getMethodProfiler().exitEnter("unload"); - this.playerChunkMap.unloadChunks(booleansupplier); -@@ -596,19 +602,24 @@ public class ChunkProviderServer extends IChunkProvider { - boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit - - this.world.getMethodProfiler().enter("naturalSpawnCount"); -+ this.world.timings.countNaturalMobs.startTiming(); // Paper - timings - int l = this.chunkMapDistance.b(); - SpawnerCreature.d spawnercreature_d = SpawnerCreature.a(l, this.world.A(), this::a); -+ this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings - - this.p = spawnercreature_d; - this.world.getMethodProfiler().exit(); - //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper - //Collections.shuffle(list); // Paper -+ this.world.timings.chunkTicks.startTiming(); // Paper - this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - - if (optional.isPresent()) { - this.world.getMethodProfiler().enter("broadcast"); -+ this.world.timings.broadcastChunkUpdates.startTiming(); // Paper - timings - playerchunk.a((Chunk) optional.get()); -+ this.world.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings - this.world.getMethodProfiler().exit(); - Optional optional1 = ((Either) playerchunk.b().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - -@@ -622,25 +633,26 @@ public class ChunkProviderServer extends IChunkProvider { - SpawnerCreature.a(this.world, chunk, spawnercreature_d, this.allowAnimals, this.allowMonsters, flag2); - } - -- this.world.timings.doTickTiles.startTiming(); // Spigot -+ //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper - this.world.a(chunk, k); -- this.world.timings.doTickTiles.stopTiming(); // Spigot -+ //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper - } - } - } - }); -+ this.world.timings.chunkTicks.stopTiming(); // Paper - this.world.getMethodProfiler().enter("customSpawners"); - if (flag1) { -+ try (co.aikar.timings.Timing ignored = this.world.timings.miscMobSpawning.startTiming()) { // Paper - timings - this.world.doMobSpawning(this.allowMonsters, this.allowAnimals); -+ } // Paper - timings - } - - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().exit(); - } - -- this.world.timings.tracker.startTiming(); // Spigot - this.playerChunkMap.g(); -- this.world.timings.tracker.stopTiming(); // Spigot - } - - private void a(long i, Consumer consumer) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 19856555793f742abb1178ede72dea5623f0e383..62245fa420390dc0a70ba9a95505dc46cd8aa64a 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1,7 +1,9 @@ - package net.minecraft.server.level; - -+import co.aikar.timings.Timing; // Paper - import com.google.common.collect.ImmutableList; - import com.google.common.collect.Iterables; -+import com.google.common.collect.ComparisonChain; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Queues; - import com.google.common.collect.Sets; -@@ -554,11 +556,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - private CompletableFuture> f(ChunkCoordIntPair chunkcoordintpair) { - return CompletableFuture.supplyAsync(() -> { -- try { -+ try (Timing ignored = this.world.timings.chunkLoad.startTimingIfSync()) { // Paper - this.world.getMethodProfiler().c("chunkLoad"); -- NBTTagCompound nbttagcompound = this.readChunkData(chunkcoordintpair); -+ NBTTagCompound nbttagcompound; // Paper -+ try (Timing ignored2 = this.world.timings.chunkIO.startTimingIfSync()) { // Paper start - timings -+ nbttagcompound = this.readChunkData(chunkcoordintpair); -+ } // Paper end - -- if (nbttagcompound != null) { -+ if (nbttagcompound != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings - boolean flag = nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8); - - if (flag) { -@@ -570,7 +575,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - PlayerChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", chunkcoordintpair); -- } -+ }} // Paper - } catch (ReportedException reportedexception) { - Throwable throwable = reportedexception.getCause(); - -@@ -607,7 +612,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return "chunkGenerate " + chunkstatus.d(); - }); - return completablefuture.thenComposeAsync((either) -> { -- return (CompletableFuture) either.map((list) -> { -+ return either.map((list) -> { // Paper - Shut up. - try { - CompletableFuture> completablefuture1 = chunkstatus.a(this.world, this.chunkGenerator, this.definedStructureManager, this.lightEngine, (ichunkaccess) -> { - return this.c(playerchunk); -@@ -660,6 +665,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ChunkStatus chunkstatus = PlayerChunk.getChunkStatus(playerchunk.getTicketLevel()); - - return !chunkstatus.b(ChunkStatus.FULL) ? PlayerChunk.UNLOADED_CHUNK_ACCESS : either.mapLeft((ichunkaccess) -> { -+ try (Timing ignored = world.timings.chunkPostLoad.startTimingIfSync()) { // Paper - ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); - Chunk chunk; - -@@ -719,6 +725,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - return chunk; -+ } // Paper - }); - }, (runnable) -> { - Mailbox mailbox = this.mailboxMain; -@@ -1177,6 +1184,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - PlayerChunkMap.EntityTracker playerchunkmap_entitytracker; - ObjectIterator objectiterator; -+ world.timings.tracker1.startTiming(); // Paper - - for (objectiterator = this.trackedEntities.values().iterator(); objectiterator.hasNext(); playerchunkmap_entitytracker.trackerEntry.a()) { - playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); -@@ -1194,16 +1202,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - playerchunkmap_entitytracker.e = sectionposition1; - } - } -+ world.timings.tracker1.stopTiming(); // Paper - - if (!list.isEmpty()) { - objectiterator = this.trackedEntities.values().iterator(); - -+ world.timings.tracker2.startTiming(); // Paper - while (objectiterator.hasNext()) { - playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); - playerchunkmap_entitytracker.track(list); - } -+ world.timings.tracker2.stopTiming(); // Paper - } - -+ - } - - protected void broadcast(Entity entity, Packet packet) { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 780e541b8d594a8a6dc3a8626a82218f2502a5c7..cf38d517821659e25e786a805e229ef2d626d75f 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -2,6 +2,8 @@ package net.minecraft.server.level; - - import com.google.common.annotations.VisibleForTesting; - import com.google.common.collect.Iterables; -+import co.aikar.timings.TimingHistory; // Paper -+import co.aikar.timings.Timings; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Queues; -@@ -153,7 +155,6 @@ import net.minecraft.world.level.block.ITileEntity; - import net.minecraft.world.level.storage.WorldDataServer; - import org.bukkit.Bukkit; - import org.bukkit.WeatherType; --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.event.CraftEventFactory; - import org.bukkit.craftbukkit.util.WorldUUID; - import org.bukkit.event.entity.CreatureSpawnEvent; -@@ -209,10 +210,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit end - this.nextTickListBlock = new TickListServer<>(this, (block) -> { - return block == null || block.getBlockData().isAir(); -- }, IRegistry.BLOCK::getKey, this::b); -+ }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings - this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { - return fluidtype == null || fluidtype == FluidTypes.EMPTY; -- }, IRegistry.FLUID::getKey, this::a); -+ }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings - this.navigators = Sets.newHashSet(); - this.L = new ObjectLinkedOpenHashSet(); - this.Q = flag1; -@@ -442,17 +443,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.Q(); - this.b(); - gameprofilerfiller.exitEnter("chunkSource"); -+ this.timings.chunkProviderTick.startTiming(); // Paper - timings - this.getChunkProvider().tick(booleansupplier); -+ this.timings.chunkProviderTick.stopTiming(); // Paper - timings - gameprofilerfiller.exitEnter("tickPending"); -- timings.doTickPending.startTiming(); // Spigot -+ timings.scheduledBlocks.startTiming(); // Paper - if (!this.isDebugWorld()) { - this.nextTickListBlock.b(); - this.nextTickListFluid.b(); - } -- timings.doTickPending.stopTiming(); // Spigot -+ timings.scheduledBlocks.stopTiming(); // Paper - - gameprofilerfiller.exitEnter("raid"); -+ this.timings.raids.startTiming(); // Paper - timings - this.persistentRaid.a(); -+ this.timings.raids.stopTiming(); // Paper - timings - gameprofilerfiller.exitEnter("blockEvents"); - timings.doSounds.startTiming(); // Spigot - this.ak(); -@@ -624,6 +629,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - gameprofilerfiller.exitEnter("tickBlocks"); -+ timings.chunkTicksBlocks.startTiming(); // Paper - if (i > 0) { - ChunkSection[] achunksection = chunk.getSections(); - int l = achunksection.length; -@@ -655,7 +661,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - } -- -+ timings.chunkTicksBlocks.stopTiming(); // Paper - gameprofilerfiller.exit(); - } - -@@ -753,14 +759,22 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (!(entity instanceof EntityHuman) && !this.getChunkProvider().a(entity)) { - this.chunkCheck(entity); - } else { -+ ++TimingHistory.entityTicks; // Paper - timings - // Spigot start -+ co.aikar.timings.Timing timer; // Paper - if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { - entity.ticksLived++; -+ timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings - entity.inactiveTick(); -+ } finally { timer.stopTiming(); } // Paper - return; - } - // Spigot end -- entity.tickTimer.startTiming(); // Spigot -+ // Paper start- timings -+ TimingHistory.activatedEntityTicks++; -+ timer = entity.getVehicle() != null ? entity.getEntityType().passengerTickTimer.startTiming() : entity.getEntityType().tickTimer.startTiming(); -+ try { -+ // Paper end - timings - entity.g(entity.locX(), entity.locY(), entity.locZ()); - entity.lastYaw = entity.yaw; - entity.lastPitch = entity.pitch; -@@ -787,7 +801,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.a(entity, entity1); - } - } -- entity.tickTimer.stopTiming(); // Spigot -+ } finally { timer.stopTiming(); } // Paper - timings - - } - } -@@ -865,6 +879,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - if (!flag1) { - org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit -+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper - if (iprogressupdate != null) { - iprogressupdate.a(new ChatMessage("menu.savingLevel")); - } -@@ -874,7 +889,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { - iprogressupdate.c(new ChatMessage("menu.savingChunks")); - } - -+ timings.worldSaveChunks.startTiming(); // Paper - chunkproviderserver.save(flag); -+ timings.worldSaveChunks.stopTiming(); // Paper -+ } // Paper - } - - // CraftBukkit start - moved from MinecraftServer.saveChunks -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 265004691f12b3476f3892f5555768717e9c6d19..536a351e1879fcb8066546d1179ad1af034b95da 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -211,6 +211,7 @@ import org.bukkit.inventory.EquipmentSlot; - import org.bukkit.inventory.InventoryView; - import org.bukkit.inventory.SmithingInventory; - import org.bukkit.util.NumberConversions; -+import co.aikar.timings.MinecraftTimings; // Paper - // CraftBukkit end - - public class PlayerConnection implements PacketListenerPlayIn { -@@ -293,7 +294,6 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - - public void tick() { -- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.startTiming(); // Spigot - this.syncPosition(); - this.player.lastX = this.player.locX(); - this.player.lastY = this.player.locY(); -@@ -369,7 +369,6 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854 - this.disconnect(new ChatMessage("multiplayer.disconnect.idling")); - } -- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.stopTiming(); // Spigot - - } - -@@ -1917,7 +1916,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - - private void handleCommand(String s) { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot -+ MinecraftTimings.playerCommandTimer.startTiming(); // Paper - // CraftBukkit start - whole method - if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot - this.LOGGER.info(this.player.getName() + " issued server command: " + s); -@@ -1928,7 +1927,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.server.getPluginManager().callEvent(event); - - if (event.isCancelled()) { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot -+ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper - return; - } - -@@ -1941,7 +1940,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - java.util.logging.Logger.getLogger(PlayerConnection.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); - return; - } finally { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot -+ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper - } - // this.minecraftServer.getCommandDispatcher().a(this.player.getCommandListener(), s); - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 5d1bbc42b4d65aa735570c53e4e6bc9e08899749..c601a5c577e438a3fa8dd4c5f36dbe9494b03d52 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.players; - -+import co.aikar.timings.MinecraftTimings; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -1022,10 +1023,11 @@ public abstract class PlayerList { - } - - public void savePlayers() { -+ MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { - this.savePlayerFile((EntityPlayer) this.players.get(i)); - } -- -+ MinecraftTimings.savePlayers.stopTiming(); // Paper - } - - public WhiteList getWhitelist() { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 2bea2f4748cadf479dd4f89792ef5ffdd88e9cab..306f6c0db2333cce5dfc4bf1c09bfef05119a28b 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -116,7 +116,6 @@ import org.bukkit.craftbukkit.event.CraftPortalEvent; - import org.bukkit.entity.Hanging; - import org.bukkit.entity.LivingEntity; - import org.bukkit.entity.Vehicle; --import org.spigotmc.CustomTimingsHandler; // Spigot - import org.bukkit.event.entity.EntityCombustByEntityEvent; - import org.bukkit.event.hanging.HangingBreakByEntityEvent; - import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; -@@ -248,7 +247,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only - public boolean forceExplosionKnockback; // SPIGOT-949 - public boolean persistentInvisibility = false; -- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot - // Spigot start - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; -@@ -617,7 +615,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public void move(EnumMoveType enummovetype, Vec3D vec3d) { -- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot - if (this.noclip) { - this.a(this.getBoundingBox().c(vec3d)); - this.recalcPosition(); -@@ -753,7 +750,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - this.world.getMethodProfiler().exit(); - } -- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot - } - - protected BlockPosition ap() { -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index f88c3dfecdce58fbdb695103fd481e9cbd0c266c..e771d84c972cea4ca1b4b5d25cd573cfcbce4579 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -135,7 +135,7 @@ import org.bukkit.event.entity.EntityTeleportEvent; - import org.bukkit.event.player.PlayerItemConsumeEvent; - // CraftBukkit end - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class EntityLiving extends Entity { - -@@ -2458,7 +2458,6 @@ public abstract class EntityLiving extends Entity { - - @Override - public void tick() { -- SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot - super.tick(); - this.t(); - this.v(); -@@ -2507,9 +2506,7 @@ public abstract class EntityLiving extends Entity { - } - } - -- SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot - this.movementTick(); -- SpigotTimings.timerEntityTickRest.startTiming(); // Spigot - double d0 = this.locX() - this.lastX; - double d1 = this.locZ() - this.lastZ; - float f = (float) (d0 * d0 + d1 * d1); -@@ -2589,8 +2586,6 @@ public abstract class EntityLiving extends Entity { - if (this.isSleeping()) { - this.pitch = 0.0F; - } -- -- SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot - } - - public void updateEquipment() { -@@ -2772,7 +2767,6 @@ public abstract class EntityLiving extends Entity { - - this.setMot(d4, d5, d6); - this.world.getMethodProfiler().enter("ai"); -- SpigotTimings.timerEntityAI.startTiming(); // Spigot - if (this.isFrozen()) { - this.jumping = false; - this.aR = 0.0F; -@@ -2782,7 +2776,6 @@ public abstract class EntityLiving extends Entity { - this.doTick(); - this.world.getMethodProfiler().exit(); - } -- SpigotTimings.timerEntityAI.stopTiming(); // Spigot - - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().enter("jump"); -@@ -2817,9 +2810,9 @@ public abstract class EntityLiving extends Entity { - this.r(); - AxisAlignedBB axisalignedbb = this.getBoundingBox(); - -- SpigotTimings.timerEntityAIMove.startTiming(); // Spigot -+ // SpigotTimings.timerEntityAIMove.startTiming(); // Spigot // Paper - this.g(new Vec3D((double) this.aR, (double) this.aS, (double) this.aT)); -- SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot -+ // SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot // Paper - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().enter("push"); - if (this.bf > 0) { -@@ -2827,9 +2820,7 @@ public abstract class EntityLiving extends Entity { - this.a(axisalignedbb, this.getBoundingBox()); - } - -- SpigotTimings.timerEntityAICollision.startTiming(); // Spigot - this.collideNearby(); -- SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot - this.world.getMethodProfiler().exit(); - if (!this.world.isClientSide && this.dO() && this.aG()) { - this.damageEntity(DamageSource.DROWN, 1.0F); -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index dc92b112770955f9fa49a408262da2e5bbc4bf98..a707ba365e25ea15e2e9d22110696b6136aa0c6f 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -281,7 +281,9 @@ public class EntityTypes { - return IRegistry.ENTITY_TYPE.getOptional(MinecraftKey.a(s)); - } - -- public EntityTypes(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntitySize entitysize, int i, int j) { -+ public final String id; -+ public EntityTypes(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntitySize entitysize, int i, int j) { this(entitytypes_b, enumcreaturetype, flag, flag1, flag2, flag3, immutableset, entitysize, i, j, "custom"); } // Paper - old signature -+ public EntityTypes(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntitySize entitysize, int i, int j, String id) { // Paper - add id - this.bf = entitytypes_b; - this.bg = enumcreaturetype; - this.bl = flag3; -@@ -292,6 +294,14 @@ public class EntityTypes { - this.br = entitysize; - this.bm = i; - this.bn = j; -+ -+ // Paper start - timings -+ this.id = id; -+ this.tickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "tick"); -+ this.inactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "inactiveTick"); -+ this.passengerTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerTick"); -+ this.passengerInactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerInactiveTick"); -+ // Paper end - } - - @Nullable -@@ -512,6 +522,12 @@ public class EntityTypes { - return this.bn; - } - -+ // Paper start - timings -+ public final co.aikar.timings.Timing tickTimer; -+ public final co.aikar.timings.Timing inactiveTickTimer; -+ public final co.aikar.timings.Timing passengerTickTimer; -+ public final co.aikar.timings.Timing passengerInactiveTickTimer; -+ // Paper end - public boolean isDeltaTracking() { - return this != EntityTypes.PLAYER && this != EntityTypes.LLAMA_SPIT && this != EntityTypes.WITHER && this != EntityTypes.BAT && this != EntityTypes.ITEM_FRAME && this != EntityTypes.LEASH_KNOT && this != EntityTypes.PAINTING && this != EntityTypes.END_CRYSTAL && this != EntityTypes.EVOKER_FANGS; - } -@@ -599,7 +615,7 @@ public class EntityTypes { - SystemUtils.a(DataConverterTypes.ENTITY_TREE, s); - } - -- return new EntityTypes<>(this.a, this.b, this.d, this.e, this.f, this.g, this.c, this.j, this.h, this.i); -+ return new EntityTypes<>(this.a, this.b, this.d, this.e, this.f, this.g, this.c, this.j, this.h, this.i, s); // Paper - add id - } - } - -diff --git a/src/main/java/net/minecraft/world/level/TickListServer.java b/src/main/java/net/minecraft/world/level/TickListServer.java -index e7296b8684d6d8c2f256d4a9da87f408a198c331..c221e5caf518b8c588390e438346fa58fa8c5a38 100644 ---- a/src/main/java/net/minecraft/world/level/TickListServer.java -+++ b/src/main/java/net/minecraft/world/level/TickListServer.java -@@ -38,12 +38,17 @@ public class TickListServer implements TickList { - private final List> g = Lists.newArrayList(); - private final Consumer> h; - -- public TickListServer(WorldServer worldserver, Predicate predicate, Function function, Consumer> consumer) { -+ public TickListServer(WorldServer worldserver, Predicate predicate, Function function, Consumer> consumer, String timingsType) { // Paper - this.a = predicate; - this.b = function; - this.e = worldserver; - this.h = consumer; -+ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Cleanup"); -+ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Ticking"); - } -+ private final co.aikar.timings.Timing timingCleanup; // Paper -+ private final co.aikar.timings.Timing timingTicking; // Paper -+ // Paper end - - public void b() { - int i = this.nextTickList.size(); -@@ -66,6 +71,7 @@ public class TickListServer implements TickList { - - this.e.getMethodProfiler().enter("cleaning"); - -+ this.timingCleanup.startTiming(); // Paper - NextTickListEntry nextticklistentry; - - while (i > 0 && iterator.hasNext()) { -@@ -81,7 +87,9 @@ public class TickListServer implements TickList { - --i; - } - } -+ this.timingCleanup.stopTiming(); // Paper - -+ this.timingTicking.startTiming(); // Paper - this.e.getMethodProfiler().exitEnter("ticking"); - - while ((nextticklistentry = (NextTickListEntry) this.f.poll()) != null) { -@@ -101,6 +109,7 @@ public class TickListServer implements TickList { - } - } - -+ this.timingTicking.stopTiming(); // Paper - this.e.getMethodProfiler().exit(); - this.g.clear(); - this.f.clear(); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0cbebc2095489c240fecd3fd32f5373be2a3d684..1b03c69fa7ffeca4083470a179e18be828b0a957 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -70,7 +70,6 @@ import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.level.border.IWorldBorderListener; - import org.bukkit.Bukkit; --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.block.CapturedBlockState; -@@ -132,7 +131,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper - -- public final SpigotTimings.WorldTimingsHandler timings; // Spigot -+ public final co.aikar.timings.WorldTimingsHandler timings; // Paper - public static BlockPosition lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; -@@ -217,7 +216,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public void c(WorldBorder worldborder, double d0) {} - }); - // CraftBukkit end -- timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings -+ timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings - this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } -@@ -797,15 +796,14 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - timings.tileEntityPending.stopTiming(); // Spigot -+ co.aikar.timings.TimingHistory.tileEntityTicks += this.tileEntityListTick.size(); // Paper - gameprofilerfiller.exit(); - spigotConfig.currentPrimedTnt = 0; // Spigot - } - - public void a(Consumer consumer, Entity entity) { - try { -- SpigotTimings.tickEntityTimer.startTiming(); // Spigot - consumer.accept(entity); -- SpigotTimings.tickEntityTimer.stopTiming(); // Spigot - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Ticking entity"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being ticked"); -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index bab55395ba92d0f3788e798ae0e154d62c4ec2fa..d285c4e3d9f938973bf7fb904680044b414e6236 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -61,6 +61,15 @@ public class Block extends BlockBase implements IMaterial { - }); - protected final BlockStateList blockStateList; - private IBlockData blockData; -+ // Paper start -+ public co.aikar.timings.Timing timing; -+ public co.aikar.timings.Timing getTiming() { -+ if (timing == null) { -+ timing = co.aikar.timings.MinecraftTimings.getBlockTiming(this); -+ } -+ return timing; -+ } -+ // Paper end - @Nullable - private String name; - @Nullable -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 75110c41af3e0097aef65091a2497dd87d08b4b2..9ebd91e1309938f81583eb3d4dd97fd39bcc930a 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -23,10 +23,12 @@ import org.bukkit.inventory.InventoryHolder; - // CraftBukkit end - - import org.spigotmc.CustomTimingsHandler; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - public abstract class TileEntity implements net.minecraft.server.KeyedObject { // Paper - -- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot -+ public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper - // CraftBukkit start - data containers - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); - public CraftPersistentDataContainer persistentDataContainer; -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index acdcece38a4b30d6c89eb4342918ae8997db9f0b..ac576d268b23148089d404cb22d8c2f9d1a79d6e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -733,6 +733,7 @@ public class Chunk implements IChunkAccess { - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(this.bukkitChunk, this.needsDecoration)); - - if (this.needsDecoration) { -+ try (co.aikar.timings.Timing ignored = this.world.timings.chunkLoadPopulate.startTiming()) { // Paper - this.needsDecoration = false; - java.util.Random random = new java.util.Random(); - random.setSeed(world.getSeed()); -@@ -752,6 +753,7 @@ public class Chunk implements IChunkAccess { - } - } - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); -+ } // Paper - } - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 27703b807735d52313b93f8f606aa263571525d2..f301c7ba4b17b92c6cf2fcee6da1e67081dad4fa 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.chunk.storage; - -+import co.aikar.timings.Timings; - import com.google.common.collect.Maps; - import it.unimi.dsi.fastutil.longs.LongOpenHashSet; - import it.unimi.dsi.fastutil.longs.LongSet; -@@ -446,7 +447,6 @@ public class ChunkRegionLoader { - private static void loadEntities(NBTTagCompound nbttagcompound, Chunk chunk) { - NBTTagList nbttaglist = nbttagcompound.getList("Entities", 10); - World world = chunk.getWorld(); -- world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot - - for (int i = 0; i < nbttaglist.size(); ++i) { - NBTTagCompound nbttagcompound1 = nbttaglist.getCompound(i); -@@ -458,8 +458,6 @@ public class ChunkRegionLoader { - chunk.d(true); - } - -- world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot -- world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot - NBTTagList nbttaglist1 = nbttagcompound.getList("TileEntities", 10); - - for (int j = 0; j < nbttaglist1.size(); ++j) { -@@ -477,8 +475,6 @@ public class ChunkRegionLoader { - } - } - } -- world.timings.syncChunkLoadTileEntitiesTimer.stopTiming(); // Spigot -- - } - - private static NBTTagCompound a(ChunkCoordIntPair chunkcoordintpair, Map, StructureStart> map, Map, LongSet> map1) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 82f5b3387f9e71ae258111b7196986623452dc02..0c1e12b0b43f949d4ace600b2ccdffe52faab1e6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2074,12 +2074,31 @@ public final class CraftServer implements Server { - private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() - { - -+ @Deprecated - @Override - public YamlConfiguration getConfig() - { - return org.spigotmc.SpigotConfig.config; - } - -+ @Override -+ public YamlConfiguration getBukkitConfig() -+ { -+ return configuration; -+ } -+ -+ @Override -+ public YamlConfiguration getSpigotConfig() -+ { -+ return org.spigotmc.SpigotConfig.config; -+ } -+ -+ @Override -+ public YamlConfiguration getPaperConfig() -+ { -+ return com.destroystokyo.paper.PaperConfig.config; -+ } -+ - @Override - public void restart() { - org.spigotmc.RestartCommand.restart(); -diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -index ebf2c62e9ea126577a6cbcbbeb3f3aba259a1f63..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 ---- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -+++ b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -@@ -1,163 +0,0 @@ --package org.bukkit.craftbukkit; -- --import java.util.HashMap; --import net.minecraft.world.entity.Entity; --import net.minecraft.world.level.World; --import net.minecraft.world.level.block.entity.TileEntity; --import net.minecraft.world.level.storage.WorldDataServer; --import org.bukkit.craftbukkit.scheduler.CraftTask; --import org.bukkit.plugin.java.JavaPluginLoader; --import org.bukkit.scheduler.BukkitTask; --import org.spigotmc.CustomTimingsHandler; -- --public class SpigotTimings { -- -- public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); -- public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); -- public static final CustomTimingsHandler commandFunctionsTimer = new CustomTimingsHandler("Command Functions"); -- public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler"); -- public static final CustomTimingsHandler playerConnectionTimer = new CustomTimingsHandler("** PlayerConnection"); -- public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); -- public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); -- public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update"); -- public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command"); -- public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save"); -- -- public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); -- public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); -- public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); -- public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); -- -- public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); -- public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); -- public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); -- public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); -- public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); -- -- public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue"); -- public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer); -- -- public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); -- -- public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); -- public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); -- -- public static final HashMap entityTypeTimingMap = new HashMap(); -- public static final HashMap tileEntityTypeTimingMap = new HashMap(); -- public static final HashMap pluginTaskTimingMap = new HashMap(); -- -- /** -- * Gets a timer associated with a plugins tasks. -- * @param task -- * @param period -- * @return -- */ -- public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { -- if (!task.isSync()) { -- return null; -- } -- String plugin; -- final CraftTask ctask = (CraftTask) task; -- -- if (task.getOwner() != null) { -- plugin = task.getOwner().getDescription().getFullName(); -- } else { -- plugin = "Unknown"; -- } -- String taskname = ctask.getTaskName(); -- -- String name = "Task: " + plugin + " Runnable: " + taskname; -- if (period > 0) { -- name += "(interval:" + period + ")"; -- } else { -- name += "(Single)"; -- } -- CustomTimingsHandler result = pluginTaskTimingMap.get(name); -- if (result == null) { -- result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); -- pluginTaskTimingMap.put(name, result); -- } -- return result; -- } -- -- /** -- * Get a named timer for the specified entity type to track type specific timings. -- * @param entity -- * @return -- */ -- public static CustomTimingsHandler getEntityTimings(Entity entity) { -- String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = entityTypeTimingMap.get(entityType); -- if (result == null) { -- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), activatedEntityTimer); -- entityTypeTimingMap.put(entityType, result); -- } -- return result; -- } -- -- /** -- * Get a named timer for the specified tile entity type to track type specific timings. -- * @param entity -- * @return -- */ -- public static CustomTimingsHandler getTileEntityTimings(TileEntity entity) { -- String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = tileEntityTypeTimingMap.get(entityType); -- if (result == null) { -- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), tickTileEntityTimer); -- tileEntityTypeTimingMap.put(entityType, result); -- } -- return result; -- } -- -- /** -- * Set of timers per world, to track world specific timings. -- */ -- public static class WorldTimingsHandler { -- public final CustomTimingsHandler mobSpawn; -- public final CustomTimingsHandler doChunkUnload; -- public final CustomTimingsHandler doTickPending; -- public final CustomTimingsHandler doTickTiles; -- public final CustomTimingsHandler doChunkMap; -- public final CustomTimingsHandler doSounds; -- public final CustomTimingsHandler entityTick; -- public final CustomTimingsHandler tileEntityTick; -- public final CustomTimingsHandler tileEntityPending; -- public final CustomTimingsHandler tracker; -- public final CustomTimingsHandler doTick; -- public final CustomTimingsHandler tickEntities; -- -- public final CustomTimingsHandler syncChunkLoadTimer; -- public final CustomTimingsHandler syncChunkLoadStructuresTimer; -- public final CustomTimingsHandler syncChunkLoadEntitiesTimer; -- public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer; -- public final CustomTimingsHandler syncChunkLoadTileTicksTimer; -- public final CustomTimingsHandler syncChunkLoadPostTimer; -- -- public WorldTimingsHandler(World server) { -- String name = ((WorldDataServer) server.worldData).getName() + " - "; -- -- mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); -- doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); -- doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); -- doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); -- doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); -- doSounds = new CustomTimingsHandler("** " + name + "doSounds"); -- entityTick = new CustomTimingsHandler("** " + name + "entityTick"); -- tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); -- tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending"); -- -- syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); -- syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); -- syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); -- syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); -- syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); -- syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); -- -- -- tracker = new CustomTimingsHandler(name + "tracker"); -- doTick = new CustomTimingsHandler(name + "doTick"); -- tickEntities = new CustomTimingsHandler(name + "tickEntities"); -- } -- } --} -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index c3a06eabbff3c37c88b1f09fe4bf806418e3a4d4..b51a874e4665f977a154792e6216e03e04525f39 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1808,6 +1808,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - packet.components = components; - getHandle().playerConnection.sendPacket(packet); - } -+ -+ // Paper start -+ @Override -+ public int getPing() -+ { -+ return getHandle().ping; -+ } -+ // Paper end - }; - - public Player.Spigot spigot() -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 4bf48f77f3f7cd62a91590543f5af441c8268029..ffe9cc1011226d604dc5499e7692e9a9a5132b72 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.scheduler; - -+import co.aikar.timings.MinecraftTimings; // Paper - import com.google.common.util.concurrent.ThreadFactoryBuilder; - import java.util.ArrayList; - import java.util.Comparator; -@@ -179,7 +180,8 @@ public class CraftScheduler implements BukkitScheduler { - } - - public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { -- final CraftTask task = new CraftTask(run, nextId(), taskName); -+ final CraftTask task = new CraftTask(run, nextId(), "Internal - " + (taskName != null ? taskName : "Unknown")); -+ task.internal = true; - return handle(task, delay); - } - -@@ -260,7 +262,7 @@ public class CraftScheduler implements BukkitScheduler { - } - return false; - } -- }); -+ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer();}}; // Paper - handle(task, 0L); - for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { - if (taskPending == task) { -@@ -295,7 +297,7 @@ public class CraftScheduler implements BukkitScheduler { - } - } - } -- }); -+ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer(plugin);}}; // Paper - handle(task, 0L); - for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { - if (taskPending == task) { -@@ -402,9 +404,7 @@ public class CraftScheduler implements BukkitScheduler { - if (task.isSync()) { - currentTask = task; - try { -- task.timings.startTiming(); // Spigot - task.run(); -- task.timings.stopTiming(); // Spigot - } catch (final Throwable throwable) { - // Paper start - String msg = String.format( -@@ -438,8 +438,10 @@ public class CraftScheduler implements BukkitScheduler { - runners.remove(task.getTaskId()); - } - } -+ MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); - pending.addAll(temp); - temp.clear(); -+ MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); - debugHead = debugHead.getNextHead(currentTick); - } - -@@ -472,6 +474,7 @@ public class CraftScheduler implements BukkitScheduler { - } - - private void parsePending() { -+ MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); - CraftTask head = this.head; - CraftTask task = head.getNext(); - CraftTask lastTask = head; -@@ -490,6 +493,7 @@ public class CraftScheduler implements BukkitScheduler { - task.setNext(null); - } - this.head = lastTask; -+ MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); - } - - private boolean isReady(final int currentTick) { -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -index 09aa6809c5400ce8548ac902908b750ce7c964ec..3c96807e97657502849093e4371e9fef3584a346 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -@@ -1,12 +1,15 @@ - package org.bukkit.craftbukkit.scheduler; - - import java.util.function.Consumer; -+ -+import co.aikar.timings.NullTimingHandler; - import org.bukkit.Bukkit; - import org.bukkit.plugin.Plugin; - import org.bukkit.scheduler.BukkitTask; - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.spigotmc.CustomTimingsHandler; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - public class CraftTask implements BukkitTask, Runnable { // Spigot - -@@ -26,12 +29,12 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - */ - private volatile long period; - private long nextRun; -- private final Runnable rTask; -- private final Consumer cTask; -+ public final Runnable rTask; // Paper -+ public final Consumer cTask; // Paper -+ public Timing timings; // Paper - private final Plugin plugin; - private final int id; - -- final CustomTimingsHandler timings; // Spigot - CraftTask() { - this(null, null, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); - } -@@ -51,7 +54,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - this.id = id; - this.period = CraftTask.NO_REPEATING; - this.taskName = taskName; -- this.timings = null; // Will be changed in later patch -+ this.timings = MinecraftTimings.getInternalTaskName(taskName); - } - // Paper end - -@@ -72,7 +75,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - } - this.id = id; - this.period = period; -- this.timings = this.isSync() ? SpigotTimings.getPluginTaskTimings(this, period) : null; // Spigot -+ timings = task != null ? MinecraftTimings.getPluginTaskTimings(this, period) : NullTimingHandler.NULL; // Paper - } - - @Override -@@ -92,11 +95,13 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - - @Override - public void run() { -+ try (Timing ignored = timings.startTiming()) { // Paper - if (rTask != null) { - rTask.run(); - } else { - cTask.accept(this); - } -+ } // Paper - } - - long getPeriod() { -@@ -123,7 +128,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - this.next = next; - } - -- Class getTaskClass() { -+ public Class getTaskClass() { - return (rTask != null) ? rTask.getClass() : ((cTask != null) ? cTask.getClass() : null); - } - -@@ -147,9 +152,4 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - return true; - } - -- // Spigot start -- public String getTaskName() { -- return (getTaskClass() == null) ? "Unknown" : getTaskClass().getName(); -- } -- // Spigot end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -index e52ef47b783785dc214746b678e7b549aea9a274..3d90b3426873a3528af14f7f1ab0adae0027da2e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -@@ -5,6 +5,7 @@ import org.bukkit.util.CachedServerIcon; - public class CraftIconCache implements CachedServerIcon { - public final String value; - -+ public String getData() { return value; } // Paper - public CraftIconCache(final String value) { - this.value = value; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 972840fd32cd4b6cb73b7f97d06dcd5699c28ba4..65131f0977fa55c4761c34ce52720170feb61a72 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -158,6 +158,12 @@ public final class CraftMagicNumbers implements UnsafeValues { - return CraftNamespacedKey.toMinecraft(mat.getKey()); - } - // ======================================================================== -+ // Paper start -+ @Override -+ public void reportTimings() { -+ co.aikar.timings.TimingsExport.reportTimings(); -+ } -+ // Paper end - - public static byte toLegacyData(IBlockData data) { - return CraftLegacy.toLegacyData(data); -@@ -332,6 +338,13 @@ public final class CraftMagicNumbers implements UnsafeValues { - return clazz; - } - -+ // Paper start -+ @Override -+ public String getTimingsServerName() { -+ return com.destroystokyo.paper.PaperConfig.timingsServerName; -+ } -+ // Paper end -+ - /** - * This helper class represents the different NBT Tags. - *

    -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 44a7323ffbdf91f8e0672e0fadf0d3d26ed9a290..69c5d4e51ebf747d931fadc819973e36f001f5bc 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -29,7 +29,7 @@ import net.minecraft.world.entity.raid.EntityRaider; - import net.minecraft.world.level.World; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.phys.AxisAlignedBB; --import org.bukkit.craftbukkit.SpigotTimings; -+import co.aikar.timings.MinecraftTimings; - - public class ActivationRange - { -@@ -73,8 +73,8 @@ public class ActivationRange - /** - * These entities are excluded from Activation range checks. - * -- * @param entity -- * @param config -+ * @param entity Entity to initialize -+ * @param config Spigot config to determine ranges - * @return boolean If it should always tick. - */ - public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) -@@ -109,7 +109,7 @@ public class ActivationRange - */ - public static void activateEntities(World world) - { -- SpigotTimings.entityActivationCheckTimer.startTiming(); -+ MinecraftTimings.entityActivationCheckTimer.startTiming(); - final int miscActivationRange = world.spigotConfig.miscActivationRange; - final int raiderActivationRange = world.spigotConfig.raiderActivationRange; - final int animalActivationRange = world.spigotConfig.animalActivationRange; -@@ -146,7 +146,7 @@ public class ActivationRange - } - } - } -- SpigotTimings.entityActivationCheckTimer.stopTiming(); -+ MinecraftTimings.entityActivationCheckTimer.stopTiming(); - } - - /** -@@ -243,10 +243,8 @@ public class ActivationRange - */ - public static boolean checkIfActive(Entity entity) - { -- SpigotTimings.checkIfActiveTimer.startTiming(); - // Never safe to skip fireworks or entities not yet added to chunk - if ( !entity.inChunk || entity instanceof EntityFireworks ) { -- SpigotTimings.checkIfActiveTimer.stopTiming(); - return true; - } - -@@ -270,7 +268,6 @@ public class ActivationRange - { - isActive = false; - } -- SpigotTimings.checkIfActiveTimer.stopTiming(); - return isActive; - } - } diff --git a/Unmapped-Spigot-Server-Patches/0010-Adventure.patch b/Unmapped-Spigot-Server-Patches/0010-Adventure.patch deleted file mode 100644 index 51208a5517..0000000000 --- a/Unmapped-Spigot-Server-Patches/0010-Adventure.patch +++ /dev/null @@ -1,3278 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Fri, 29 Jan 2021 17:54:03 +0100 -Subject: [PATCH] Adventure - -Co-authored-by: zml -Co-authored-by: Jake Potrebic - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7..429b74474ced04d8dd8f038b8590b8dfe178bf4d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -217,4 +217,9 @@ public class PaperConfig { - " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + - " - Server Name: " + timingsServerName); - } -+ -+ public static boolean useDisplayNameInQuit = false; -+ private static void useDisplayNameInQuit() { -+ useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); -+ } - } -diff --git a/src/main/java/io/papermc/paper/adventure/AdventureComponent.java b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..89597b4a3064c3c6001c7e927a848ee73a1b1fd9 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java -@@ -0,0 +1,77 @@ -+package io.papermc.paper.adventure; -+ -+import com.google.gson.JsonElement; -+import com.google.gson.JsonSerializationContext; -+import com.google.gson.JsonSerializer; -+import java.lang.reflect.Type; -+import java.util.List; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextComponent; -+import net.minecraft.network.chat.ChatModifier; -+import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.network.chat.IChatMutableComponent; -+import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+ -+public final class AdventureComponent implements IChatBaseComponent { -+ final Component wrapped; -+ private @MonotonicNonNull IChatBaseComponent converted; -+ -+ public AdventureComponent(final Component wrapped) { -+ this.wrapped = wrapped; -+ } -+ -+ public IChatBaseComponent deepConverted() { -+ IChatBaseComponent converted = this.converted; -+ if (converted == null) { -+ converted = PaperAdventure.WRAPPER_AWARE_SERIALIZER.serialize(this.wrapped); -+ this.converted = converted; -+ } -+ return converted; -+ } -+ -+ public @Nullable IChatBaseComponent deepConvertedIfPresent() { -+ return this.converted; -+ } -+ -+ @Override -+ public ChatModifier getChatModifier() { -+ return this.deepConverted().getChatModifier(); -+ } -+ -+ @Override -+ public String getText() { -+ if (this.wrapped instanceof TextComponent) { -+ return ((TextComponent) this.wrapped).content(); -+ } else { -+ return this.deepConverted().getText(); -+ } -+ } -+ -+ @Override -+ public String getString() { -+ return PaperAdventure.PLAIN.serialize(this.wrapped); -+ } -+ -+ @Override -+ public List getSiblings() { -+ return this.deepConverted().getSiblings(); -+ } -+ -+ @Override -+ public IChatMutableComponent g() { -+ return this.deepConverted().g(); -+ } -+ -+ @Override -+ public IChatMutableComponent mutableCopy() { -+ return this.deepConverted().mutableCopy(); -+ } -+ -+ public static class Serializer implements JsonSerializer { -+ @Override -+ public JsonElement serialize(final AdventureComponent src, final Type type, final JsonSerializationContext context) { -+ return PaperAdventure.GSON.serializer().toJsonTree(src.wrapped, Component.class); -+ } -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..909968952a7ae2aa0196f12d1b3177cade380db2 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -@@ -0,0 +1,215 @@ -+package io.papermc.paper.adventure; -+ -+import io.papermc.paper.chat.ChatRenderer; -+import io.papermc.paper.event.player.AbstractChatEvent; -+import io.papermc.paper.event.player.AsyncChatEvent; -+import io.papermc.paper.event.player.ChatEvent; -+import java.util.Set; -+import java.util.concurrent.ExecutionException; -+import java.util.function.Consumer; -+import java.util.regex.Pattern; -+ -+import net.kyori.adventure.audience.Audience; -+import net.kyori.adventure.audience.MessageType; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextReplacementConfig; -+import net.kyori.adventure.text.event.ClickEvent; -+import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+import org.bukkit.craftbukkit.util.LazyPlayerSet; -+import org.bukkit.craftbukkit.util.Waitable; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.AsyncPlayerChatEvent; -+import org.bukkit.event.player.PlayerChatEvent; -+ -+public final class ChatProcessor { -+ // <-- copied from adventure-text-serializer-legacy -+ private static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?"); -+ private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("^[a-z][a-z0-9+\\-.]*:"); -+ private static final TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder() -+ .match(DEFAULT_URL_PATTERN) -+ .replacement(url -> { -+ String clickUrl = url.content(); -+ if (!URL_SCHEME_PATTERN.matcher(clickUrl).find()) { -+ clickUrl = "http://" + clickUrl; -+ } -+ return url.clickEvent(ClickEvent.openUrl(clickUrl)); -+ }) -+ .build(); -+ // copied from adventure-text-serializer-legacy --> -+ final MinecraftServer server; -+ final EntityPlayer player; -+ final String message; -+ final boolean async; -+ final Component originalMessage; -+ -+ public ChatProcessor(final MinecraftServer server, final EntityPlayer player, final String message, final boolean async) { -+ this.server = server; -+ this.player = player; -+ this.message = message; -+ this.async = async; -+ this.originalMessage = Component.text(message); -+ } -+ -+ @SuppressWarnings({"CodeBlock2Expr", "deprecated"}) -+ public void process() { -+ this.processingLegacyFirst( -+ // continuing from AsyncPlayerChatEvent (without PlayerChatEvent) -+ event -> { -+ this.processModern( -+ legacyRenderer(event.getFormat()), -+ event.getRecipients(), -+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), -+ event.isCancelled() -+ ); -+ }, -+ // continuing from AsyncPlayerChatEvent and PlayerChatEvent -+ event -> { -+ this.processModern( -+ legacyRenderer(event.getFormat()), -+ event.getRecipients(), -+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), -+ event.isCancelled() -+ ); -+ }, -+ // no legacy events called, all nice and fresh! -+ () -> { -+ this.processModern( -+ ChatRenderer.defaultRenderer(), -+ new LazyPlayerSet(this.server), -+ Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG), -+ false -+ ); -+ } -+ ); -+ } -+ -+ @SuppressWarnings("deprecation") -+ private void processingLegacyFirst( -+ final Consumer continueAfterAsync, -+ final Consumer continueAfterAsyncAndSync, -+ final Runnable modernOnly -+ ) { -+ final boolean listenersOnAsyncEvent = anyListeners(AsyncPlayerChatEvent.getHandlerList()); -+ final boolean listenersOnSyncEvent = anyListeners(PlayerChatEvent.getHandlerList()); -+ if (listenersOnAsyncEvent || listenersOnSyncEvent) { -+ final CraftPlayer player = this.player.getBukkitEntity(); -+ final AsyncPlayerChatEvent ae = new AsyncPlayerChatEvent(this.async, player, this.message, new LazyPlayerSet(this.server)); -+ post(ae); -+ if (listenersOnSyncEvent) { -+ final PlayerChatEvent se = new PlayerChatEvent(player, ae.getMessage(), ae.getFormat(), ae.getRecipients()); -+ se.setCancelled(ae.isCancelled()); // propagate cancelled state -+ this.queueIfAsyncOrRunImmediately(new Waitable() { -+ @Override -+ protected Void evaluate() { -+ post(se); -+ return null; -+ } -+ }); -+ continueAfterAsyncAndSync.accept(se); -+ } else { -+ continueAfterAsync.accept(ae); -+ } -+ } else { -+ modernOnly.run(); -+ } -+ } -+ -+ private void processModern(final ChatRenderer renderer, final Set recipients, final Component message, final boolean cancelled) { -+ final AsyncChatEvent ae = this.createAsync(renderer, recipients, new LazyChatAudienceSet(), message); -+ ae.setCancelled(cancelled); // propagate cancelled state -+ post(ae); -+ final boolean listenersOnSyncEvent = anyListeners(ChatEvent.getHandlerList()); -+ if (listenersOnSyncEvent) { -+ this.continueWithSyncFromWhereAsyncLeftOff(ae); -+ } else { -+ this.complete(ae); -+ } -+ } -+ -+ private void continueWithSyncFromWhereAsyncLeftOff(final AsyncChatEvent ae) { -+ this.queueIfAsyncOrRunImmediately(new Waitable() { -+ @Override -+ protected Void evaluate() { -+ final ChatEvent se = ChatProcessor.this.createSync(ae.renderer(), ae.recipients(), ae.viewers(), ae.message()); -+ se.setCancelled(ae.isCancelled()); // propagate cancelled state -+ post(se); -+ ChatProcessor.this.complete(se); -+ return null; -+ } -+ }); -+ } -+ -+ private void complete(final AbstractChatEvent event) { -+ if (event.isCancelled()) { -+ return; -+ } -+ -+ final CraftPlayer player = this.player.getBukkitEntity(); -+ final Component displayName = displayName(player); -+ final Component message = event.message(); -+ final ChatRenderer renderer = event.renderer(); -+ -+ final Set viewers = event.viewers(); -+ final Set recipients = event.recipients(); -+ if (viewers instanceof LazyChatAudienceSet && recipients instanceof LazyPlayerSet && -+ (!((LazyChatAudienceSet) viewers).isLazy() || ((LazyPlayerSet) recipients).isLazy())) { -+ for (final Audience viewer : viewers) { -+ viewer.sendMessage(player, renderer.render(player, displayName, message, viewer), MessageType.CHAT); -+ } -+ } else { -+ this.server.console.sendMessage(player, renderer.render(player, displayName, message, this.server.console), MessageType.CHAT); -+ for (final Player recipient : recipients) { -+ recipient.sendMessage(player, renderer.render(player, displayName, message, recipient), MessageType.CHAT); -+ } -+ } -+ } -+ -+ private AsyncChatEvent createAsync(final ChatRenderer renderer, final Set recipients, final Set viewers, final Component message) { -+ return new AsyncChatEvent(this.async, this.player.getBukkitEntity(), recipients, viewers, renderer, message, this.originalMessage); -+ } -+ -+ private ChatEvent createSync(final ChatRenderer renderer, final Set recipients, final Set viewers, final Component message) { -+ return new ChatEvent(this.player.getBukkitEntity(), recipients, viewers, renderer, message, this.originalMessage); -+ } -+ -+ private static String legacyDisplayName(final CraftPlayer player) { -+ return player.getDisplayName(); -+ } -+ -+ private static Component displayName(final CraftPlayer player) { -+ return player.displayName(); -+ } -+ -+ private static ChatRenderer legacyRenderer(final String format) { -+ return (player, displayName, message, recipient) -> PaperAdventure.LEGACY_SECTION_UXRC.deserialize(String.format(format, legacyDisplayName((CraftPlayer) player), PaperAdventure.LEGACY_SECTION_UXRC.serialize(message))).replaceText(URL_REPLACEMENT_CONFIG); -+ } -+ -+ private void queueIfAsyncOrRunImmediately(final Waitable waitable) { -+ if (this.async) { -+ this.server.processQueue.add(waitable); -+ } else { -+ waitable.run(); -+ } -+ try { -+ waitable.get(); -+ } catch (final InterruptedException e) { -+ Thread.currentThread().interrupt(); // tag, you're it -+ } catch (final ExecutionException e) { -+ throw new RuntimeException("Exception processing chat", e.getCause()); -+ } -+ } -+ -+ private static void post(final Event event) { -+ Bukkit.getPluginManager().callEvent(event); -+ } -+ -+ private static boolean anyListeners(final HandlerList handlers) { -+ return handlers.getRegisteredListeners().length > 0; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/DisplayNames.java b/src/main/java/io/papermc/paper/adventure/DisplayNames.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b1d9d6276eb577ed3c66df1f89b3266d2c48eaf2 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/DisplayNames.java -@@ -0,0 +1,22 @@ -+package io.papermc.paper.adventure; -+ -+import net.minecraft.server.level.EntityPlayer; -+import org.bukkit.ChatColor; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+ -+public final class DisplayNames { -+ private DisplayNames() { -+ } -+ -+ public static String getLegacy(final CraftPlayer player) { -+ return getLegacy(player.getHandle()); -+ } -+ -+ public static String getLegacy(final EntityPlayer player) { -+ final String legacy = player.displayName; -+ if (legacy != null) { -+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName) + ChatColor.getLastColors(player.displayName); -+ } -+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..10f08e2b73610ab06928d1f63348920fef8e91fa ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java -@@ -0,0 +1,21 @@ -+package io.papermc.paper.adventure; -+ -+import net.kyori.adventure.audience.Audience; -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.util.LazyHashSet; -+import org.bukkit.craftbukkit.util.LazyPlayerSet; -+import org.bukkit.entity.Player; -+ -+import java.util.HashSet; -+import java.util.Set; -+ -+final class LazyChatAudienceSet extends LazyHashSet { -+ @Override -+ protected Set makeReference() { -+ final Set playerSet = LazyPlayerSet.makePlayerSet(MinecraftServer.getServer()); -+ final HashSet audiences = new HashSet<>(playerSet); -+ audiences.add(Bukkit.getConsoleSender()); -+ return audiences; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..caa9708f321f04cd02534161231c05999bda4acd ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java -@@ -0,0 +1,88 @@ -+package io.papermc.paper.adventure; -+ -+import com.mojang.brigadier.exceptions.CommandSyntaxException; -+import java.io.IOException; -+import java.util.UUID; -+import net.kyori.adventure.key.Key; -+import net.kyori.adventure.nbt.api.BinaryTagHolder; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.event.HoverEvent; -+import net.kyori.adventure.text.serializer.gson.LegacyHoverEventSerializer; -+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; -+import net.kyori.adventure.util.Codec; -+import net.minecraft.nbt.MojangsonParser; -+import net.minecraft.nbt.NBTBase; -+import net.minecraft.nbt.NBTTagCompound; -+ -+final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer { -+ public static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer(); -+ private static final Codec SNBT_CODEC = Codec.of(MojangsonParser::parse, NBTBase::toString); -+ -+ static final String ITEM_TYPE = "id"; -+ static final String ITEM_COUNT = "Count"; -+ static final String ITEM_TAG = "tag"; -+ -+ static final String ENTITY_NAME = "name"; -+ static final String ENTITY_TYPE = "type"; -+ static final String ENTITY_ID = "id"; -+ -+ NBTLegacyHoverEventSerializer() { -+ } -+ -+ @Override -+ public HoverEvent.ShowItem deserializeShowItem(final Component input) throws IOException { -+ final String raw = PlainComponentSerializer.plain().serialize(input); -+ try { -+ final NBTTagCompound contents = SNBT_CODEC.decode(raw); -+ final NBTTagCompound tag = contents.getCompound(ITEM_TAG); -+ return HoverEvent.ShowItem.of( -+ Key.key(contents.getString(ITEM_TYPE)), -+ contents.hasKey(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1, -+ tag.isEmpty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC) -+ ); -+ } catch (final CommandSyntaxException ex) { -+ throw new IOException(ex); -+ } -+ } -+ -+ @Override -+ public HoverEvent.ShowEntity deserializeShowEntity(final Component input, final Codec.Decoder componentCodec) throws IOException { -+ final String raw = PlainComponentSerializer.plain().serialize(input); -+ try { -+ final NBTTagCompound contents = SNBT_CODEC.decode(raw); -+ return HoverEvent.ShowEntity.of( -+ Key.key(contents.getString(ENTITY_TYPE)), -+ UUID.fromString(contents.getString(ENTITY_ID)), -+ componentCodec.decode(contents.getString(ENTITY_NAME)) -+ ); -+ } catch (final CommandSyntaxException ex) { -+ throw new IOException(ex); -+ } -+ } -+ -+ @Override -+ public Component serializeShowItem(final HoverEvent.ShowItem input) throws IOException { -+ final NBTTagCompound tag = new NBTTagCompound(); -+ tag.setString(ITEM_TYPE, input.item().asString()); -+ tag.setByte(ITEM_COUNT, (byte) input.count()); -+ if (input.nbt() != null) { -+ try { -+ tag.set(ITEM_TAG, input.nbt().get(SNBT_CODEC)); -+ } catch (final CommandSyntaxException ex) { -+ throw new IOException(ex); -+ } -+ } -+ return Component.text(SNBT_CODEC.encode(tag)); -+ } -+ -+ @Override -+ public Component serializeShowEntity(final HoverEvent.ShowEntity input, final Codec.Encoder componentCodec) throws IOException { -+ final NBTTagCompound tag = new NBTTagCompound(); -+ tag.setString(ENTITY_ID, input.id().toString()); -+ tag.setString(ENTITY_TYPE, input.type().asString()); -+ if (input.name() != null) { -+ tag.setString(ENTITY_NAME, componentCodec.encode(input.name())); -+ } -+ return Component.text(SNBT_CODEC.encode(tag)); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7b14b3c2486f03778d4673cf9684aa576dc2724a ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -@@ -0,0 +1,344 @@ -+package io.papermc.paper.adventure; -+ -+import com.mojang.brigadier.exceptions.CommandSyntaxException; -+import io.netty.util.AttributeKey; -+import java.io.IOException; -+import java.util.ArrayList; -+import java.util.List; -+import java.util.Locale; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+import net.kyori.adventure.bossbar.BossBar; -+import net.kyori.adventure.inventory.Book; -+import net.kyori.adventure.key.Key; -+import net.kyori.adventure.nbt.api.BinaryTagHolder; -+import net.kyori.adventure.sound.Sound; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TranslatableComponent; -+import net.kyori.adventure.text.flattener.ComponentFlattener; -+import net.kyori.adventure.text.format.TextColor; -+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; -+import net.kyori.adventure.translation.GlobalTranslator; -+import net.kyori.adventure.util.Codec; -+import net.minecraft.EnumChatFormat; -+import net.minecraft.locale.LocaleLanguage; -+import net.minecraft.nbt.MojangsonParser; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; -+import net.minecraft.nbt.NBTTagString; -+import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.sounds.SoundCategory; -+import net.minecraft.world.BossBattle; -+import net.minecraft.world.item.ItemStack; -+import org.bukkit.ChatColor; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+ -+public final class PaperAdventure { -+ public static final AttributeKey LOCALE_ATTRIBUTE = AttributeKey.valueOf("adventure:locale"); -+ private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s"); -+ public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder() -+ .complexMapper(TranslatableComponent.class, (translatable, consumer) -> { -+ final @NonNull String translated = LocaleLanguage.a().a(translatable.key()); -+ -+ final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated); -+ final List args = translatable.args(); -+ int argPosition = 0; -+ int lastIdx = 0; -+ while (matcher.find()) { -+ // append prior -+ if (lastIdx < matcher.start()) { -+ consumer.accept(Component.text(translated.substring(lastIdx, matcher.start()))); -+ } -+ lastIdx = matcher.end(); -+ -+ final @Nullable String argIdx = matcher.group(1); -+ // calculate argument position -+ if (argIdx != null) { -+ try { -+ final int idx = Integer.parseInt(argIdx) - 1; -+ if (idx < args.size()) { -+ consumer.accept(args.get(idx)); -+ } -+ } catch (final NumberFormatException ex) { -+ // ignore, drop the format placeholder -+ } -+ } else { -+ final int idx = argPosition++; -+ if (idx < args.size()) { -+ consumer.accept(args.get(idx)); -+ } -+ } -+ } -+ -+ // append tail -+ if (lastIdx < translated.length()) { -+ consumer.accept(Component.text(translated.substring(lastIdx))); -+ } -+ }) -+ .build(); -+ public static final LegacyComponentSerializer LEGACY_SECTION_UXRC = LegacyComponentSerializer.builder().flattener(FLATTENER).hexColors().useUnusualXRepeatedCharacterHexFormat().build(); -+ public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build(); -+ public static final GsonComponentSerializer GSON = GsonComponentSerializer.builder() -+ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) -+ .build(); -+ public static final GsonComponentSerializer COLOR_DOWNSAMPLING_GSON = GsonComponentSerializer.builder() -+ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) -+ .downsampleColors() -+ .build(); -+ private static final Codec NBT_CODEC = new Codec() { -+ @Override -+ public @NonNull NBTTagCompound decode(final @NonNull String encoded) throws IOException { -+ try { -+ return MojangsonParser.parse(encoded); -+ } catch (final CommandSyntaxException e) { -+ throw new IOException(e); -+ } -+ } -+ -+ @Override -+ public @NonNull String encode(final @NonNull NBTTagCompound decoded) { -+ return decoded.toString(); -+ } -+ }; -+ static final WrapperAwareSerializer WRAPPER_AWARE_SERIALIZER = new WrapperAwareSerializer(); -+ -+ private PaperAdventure() { -+ } -+ -+ // Key -+ -+ public static MinecraftKey asVanilla(final Key key) { -+ return new MinecraftKey(key.namespace(), key.value()); -+ } -+ -+ public static MinecraftKey asVanillaNullable(final Key key) { -+ if (key == null) { -+ return null; -+ } -+ return new MinecraftKey(key.namespace(), key.value()); -+ } -+ -+ // Component -+ -+ public static Component asAdventure(final IChatBaseComponent component) { -+ return component == null ? Component.empty() : GSON.serializer().fromJson(IChatBaseComponent.ChatSerializer.toJsonTree(component), Component.class); -+ } -+ -+ public static ArrayList asAdventure(final List vanillas) { -+ final ArrayList adventures = new ArrayList<>(vanillas.size()); -+ for (final IChatBaseComponent vanilla : vanillas) { -+ adventures.add(asAdventure(vanilla)); -+ } -+ return adventures; -+ } -+ -+ public static ArrayList asAdventureFromJson(final List jsonStrings) { -+ final ArrayList adventures = new ArrayList<>(jsonStrings.size()); -+ for (final String json : jsonStrings) { -+ adventures.add(GsonComponentSerializer.gson().deserialize(json)); -+ } -+ return adventures; -+ } -+ -+ public static List asJson(final List adventures) { -+ final List jsons = new ArrayList<>(adventures.size()); -+ for (final Component component : adventures) { -+ jsons.add(GsonComponentSerializer.gson().serialize(component)); -+ } -+ return jsons; -+ } -+ -+ public static IChatBaseComponent asVanilla(final Component component) { -+ if (true) return new AdventureComponent(component); -+ return IChatBaseComponent.ChatSerializer.fromJsonTree(GSON.serializer().toJsonTree(component)); -+ } -+ -+ public static List asVanilla(final List adventures) { -+ final List vanillas = new ArrayList<>(adventures.size()); -+ for (final Component adventure : adventures) { -+ vanillas.add(asVanilla(adventure)); -+ } -+ return vanillas; -+ } -+ -+ public static String asJsonString(final Component component, final Locale locale) { -+ return GSON.serialize( -+ GlobalTranslator.render( -+ component, -+ // play it safe -+ locale != null -+ ? locale -+ : Locale.US -+ ) -+ ); -+ } -+ -+ public static String asJsonString(final IChatBaseComponent component, final Locale locale) { -+ if (component instanceof AdventureComponent) { -+ return asJsonString(((AdventureComponent) component).wrapped, locale); -+ } -+ return IChatBaseComponent.ChatSerializer.componentToJson(component); -+ } -+ -+ // thank you for being worse than wet socks, Bukkit -+ public static String superHackyLegacyRepresentationOfComponent(final Component component, final String string) { -+ return LEGACY_SECTION_UXRC.serialize(component) + ChatColor.getLastColors(string); -+ } -+ -+ // BossBar -+ -+ public static BossBattle.BarColor asVanilla(final BossBar.Color color) { -+ if (color == BossBar.Color.PINK) { -+ return BossBattle.BarColor.PINK; -+ } else if (color == BossBar.Color.BLUE) { -+ return BossBattle.BarColor.BLUE; -+ } else if (color == BossBar.Color.RED) { -+ return BossBattle.BarColor.RED; -+ } else if (color == BossBar.Color.GREEN) { -+ return BossBattle.BarColor.GREEN; -+ } else if (color == BossBar.Color.YELLOW) { -+ return BossBattle.BarColor.YELLOW; -+ } else if (color == BossBar.Color.PURPLE) { -+ return BossBattle.BarColor.PURPLE; -+ } else if (color == BossBar.Color.WHITE) { -+ return BossBattle.BarColor.WHITE; -+ } -+ throw new IllegalArgumentException(color.name()); -+ } -+ -+ public static BossBar.Color asAdventure(final BossBattle.BarColor color) { -+ if(color == BossBattle.BarColor.PINK) { -+ return BossBar.Color.PINK; -+ } else if(color == BossBattle.BarColor.BLUE) { -+ return BossBar.Color.BLUE; -+ } else if(color == BossBattle.BarColor.RED) { -+ return BossBar.Color.RED; -+ } else if(color == BossBattle.BarColor.GREEN) { -+ return BossBar.Color.GREEN; -+ } else if(color == BossBattle.BarColor.YELLOW) { -+ return BossBar.Color.YELLOW; -+ } else if(color == BossBattle.BarColor.PURPLE) { -+ return BossBar.Color.PURPLE; -+ } else if(color == BossBattle.BarColor.WHITE) { -+ return BossBar.Color.WHITE; -+ } -+ throw new IllegalArgumentException(color.name()); -+ } -+ -+ public static BossBattle.BarStyle asVanilla(final BossBar.Overlay overlay) { -+ if (overlay == BossBar.Overlay.PROGRESS) { -+ return BossBattle.BarStyle.PROGRESS; -+ } else if (overlay == BossBar.Overlay.NOTCHED_6) { -+ return BossBattle.BarStyle.NOTCHED_6; -+ } else if (overlay == BossBar.Overlay.NOTCHED_10) { -+ return BossBattle.BarStyle.NOTCHED_10; -+ } else if (overlay == BossBar.Overlay.NOTCHED_12) { -+ return BossBattle.BarStyle.NOTCHED_12; -+ } else if (overlay == BossBar.Overlay.NOTCHED_20) { -+ return BossBattle.BarStyle.NOTCHED_20; -+ } -+ throw new IllegalArgumentException(overlay.name()); -+ } -+ -+ public static BossBar.Overlay asAdventure(final BossBattle.BarStyle overlay) { -+ if (overlay == BossBattle.BarStyle.PROGRESS) { -+ return BossBar.Overlay.PROGRESS; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_6) { -+ return BossBar.Overlay.NOTCHED_6; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_10) { -+ return BossBar.Overlay.NOTCHED_10; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_12) { -+ return BossBar.Overlay.NOTCHED_12; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_20) { -+ return BossBar.Overlay.NOTCHED_20; -+ } -+ throw new IllegalArgumentException(overlay.name()); -+ } -+ -+ public static void setFlag(final BossBar bar, final BossBar.Flag flag, final boolean value) { -+ if (value) { -+ bar.addFlag(flag); -+ } else { -+ bar.removeFlag(flag); -+ } -+ } -+ -+ // Book -+ -+ public static ItemStack asItemStack(final Book book, final Locale locale) { -+ final ItemStack item = new ItemStack(net.minecraft.world.item.Items.WRITTEN_BOOK, 1); -+ final NBTTagCompound tag = item.getOrCreateTag(); -+ tag.setString("title", asJsonString(book.title(), locale)); -+ tag.setString("author", asJsonString(book.author(), locale)); -+ final NBTTagList pages = new NBTTagList(); -+ for (final Component page : book.pages()) { -+ pages.add(NBTTagString.create(asJsonString(page, locale))); -+ } -+ tag.set("pages", pages); -+ return item; -+ } -+ -+ // Sounds -+ -+ public static SoundCategory asVanilla(final Sound.Source source) { -+ if (source == Sound.Source.MASTER) { -+ return SoundCategory.MASTER; -+ } else if (source == Sound.Source.MUSIC) { -+ return SoundCategory.MUSIC; -+ } else if (source == Sound.Source.RECORD) { -+ return SoundCategory.RECORDS; -+ } else if (source == Sound.Source.WEATHER) { -+ return SoundCategory.WEATHER; -+ } else if (source == Sound.Source.BLOCK) { -+ return SoundCategory.BLOCKS; -+ } else if (source == Sound.Source.HOSTILE) { -+ return SoundCategory.HOSTILE; -+ } else if (source == Sound.Source.NEUTRAL) { -+ return SoundCategory.NEUTRAL; -+ } else if (source == Sound.Source.PLAYER) { -+ return SoundCategory.PLAYERS; -+ } else if (source == Sound.Source.AMBIENT) { -+ return SoundCategory.AMBIENT; -+ } else if (source == Sound.Source.VOICE) { -+ return SoundCategory.VOICE; -+ } -+ throw new IllegalArgumentException(source.name()); -+ } -+ -+ public static @Nullable SoundCategory asVanillaNullable(final Sound.@Nullable Source source) { -+ if (source == null) { -+ return null; -+ } -+ return asVanilla(source); -+ } -+ -+ // NBT -+ -+ public static @Nullable BinaryTagHolder asBinaryTagHolder(final @Nullable NBTTagCompound tag) { -+ if (tag == null) { -+ return null; -+ } -+ try { -+ return BinaryTagHolder.encode(tag, NBT_CODEC); -+ } catch (final IOException e) { -+ return null; -+ } -+ } -+ -+ // Colors -+ -+ public static @NonNull TextColor asAdventure(EnumChatFormat minecraftColor) { -+ if (minecraftColor.e() == null) { -+ throw new IllegalArgumentException("Not a valid color"); -+ } -+ return TextColor.color(minecraftColor.e()); -+ } -+ -+ public static @Nullable EnumChatFormat asVanilla(TextColor color) { -+ return EnumChatFormat.getByHexValue(color.value()); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3a4158781e464d9a860bab72ed719a41929c8add ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java -@@ -0,0 +1,41 @@ -+package io.papermc.paper.adventure; -+ -+import java.util.Set; -+import java.util.function.Consumer; -+import net.kyori.adventure.bossbar.BossBar; -+import net.kyori.adventure.text.Component; -+import net.minecraft.network.protocol.game.PacketPlayOutBoss; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+public final class VanillaBossBarListener implements BossBar.Listener { -+ private final Consumer action; -+ -+ public VanillaBossBarListener(final Consumer action) { -+ this.action = action; -+ } -+ -+ @Override -+ public void bossBarNameChanged(final @NonNull BossBar bar, final @NonNull Component oldName, final @NonNull Component newName) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_NAME); -+ } -+ -+ @Override -+ public void bossBarProgressChanged(final @NonNull BossBar bar, final float oldProgress, final float newProgress) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_PCT); -+ } -+ -+ @Override -+ public void bossBarColorChanged(final @NonNull BossBar bar, final BossBar.@NonNull Color oldColor, final BossBar.@NonNull Color newColor) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_STYLE); -+ } -+ -+ @Override -+ public void bossBarOverlayChanged(final @NonNull BossBar bar, final BossBar.@NonNull Overlay oldOverlay, final BossBar.@NonNull Overlay newOverlay) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_STYLE); -+ } -+ -+ @Override -+ public void bossBarFlagsChanged(final @NonNull BossBar bar, final @NonNull Set flagsAdded, final @NonNull Set flagsRemoved) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_PROPERTIES); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..625b57a4274d6348a85897b92ff07fee7ae3a7ab ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java -@@ -0,0 +1,20 @@ -+package io.papermc.paper.adventure; -+ -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.serializer.ComponentSerializer; -+import net.minecraft.network.chat.IChatBaseComponent; -+ -+final class WrapperAwareSerializer implements ComponentSerializer { -+ @Override -+ public Component deserialize(final IChatBaseComponent input) { -+ if (input instanceof AdventureComponent) { -+ return ((AdventureComponent) input).wrapped; -+ } -+ return PaperAdventure.GSON.serializer().fromJson(IChatBaseComponent.ChatSerializer.toJsonTree(input), Component.class); -+ } -+ -+ @Override -+ public IChatBaseComponent serialize(final Component component) { -+ return IChatBaseComponent.ChatSerializer.fromJsonTree(PaperAdventure.GSON.serializer().toJsonTree(component)); -+ } -+} -diff --git a/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b3e26b9ecca7055760d05975d36c9ae74e0d7d4b ---- /dev/null -+++ b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java -@@ -0,0 +1,36 @@ -+package net.kyori.adventure.bossbar; -+ -+import io.papermc.paper.adventure.PaperAdventure; -+import io.papermc.paper.adventure.VanillaBossBarListener; -+import net.minecraft.server.level.BossBattleServer; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+ -+public abstract class HackyBossBarPlatformBridge { -+ public BossBattleServer vanilla$bar; -+ private VanillaBossBarListener vanilla$listener; -+ -+ public final void paper$playerShow(final CraftPlayer player) { -+ if (this.vanilla$bar == null) { -+ final BossBar $this = (BossBar) this; -+ this.vanilla$bar = new BossBattleServer( -+ PaperAdventure.asVanilla($this.name()), -+ PaperAdventure.asVanilla($this.color()), -+ PaperAdventure.asVanilla($this.overlay()) -+ ); -+ this.vanilla$bar.adventure = $this; -+ this.vanilla$listener = new VanillaBossBarListener(this.vanilla$bar::sendUpdate); -+ $this.addListener(this.vanilla$listener); -+ } -+ this.vanilla$bar.addPlayer(player.getHandle()); -+ } -+ -+ public final void paper$playerHide(final CraftPlayer player) { -+ if (this.vanilla$bar != null) { -+ this.vanilla$bar.removePlayer(player.getHandle()); -+ if (this.vanilla$bar.getPlayers().isEmpty()) { -+ ((BossBar) this).removeListener(this.vanilla$listener); -+ this.vanilla$bar = null; -+ } -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/EnumChatFormat.java b/src/main/java/net/minecraft/EnumChatFormat.java -index 75e38f05c10713f773a8763100dfc0777521dba6..cd93f99e939438c572a4258d299a6038ebfc60a8 100644 ---- a/src/main/java/net/minecraft/EnumChatFormat.java -+++ b/src/main/java/net/minecraft/EnumChatFormat.java -@@ -61,6 +61,7 @@ public enum EnumChatFormat { - return !this.A && this != EnumChatFormat.RESET; - } - -+ @Nullable public Integer getHexValue() { return this.e(); } // Paper - OBFHELPER - @Nullable - public Integer e() { - return this.D; -@@ -84,6 +85,18 @@ public enum EnumChatFormat { - return s == null ? null : (EnumChatFormat) EnumChatFormat.w.get(c(s)); - } - -+ // Paper start -+ @Nullable public static EnumChatFormat getByHexValue(int i) { -+ for (EnumChatFormat value : values()) { -+ if (value.getHexValue() != null && value.getHexValue() == i) { -+ return value; -+ } -+ } -+ -+ return null; -+ } -+ // Paper end -+ - @Nullable - public static EnumChatFormat a(int i) { - if (i < 0) { -diff --git a/src/main/java/net/minecraft/nbt/NBTTagString.java b/src/main/java/net/minecraft/nbt/NBTTagString.java -index e26ef49d9dde8ed0fb4267b48cb597563967f313..0e41fdb6ba711fbd2240d62e2030b3a12e14c8d6 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagString.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagString.java -@@ -43,6 +43,7 @@ public class NBTTagString implements NBTBase { - this.data = s; - } - -+ public static NBTTagString create(final String value) { return a(value); } // Paper - OBFHELPER - public static NBTTagString a(String s) { - return s.isEmpty() ? NBTTagString.b : new NBTTagString(s); - } -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index 5413bf93f7f0f4491fca1f07c47a925fdace7751..5f1c5dd7902f6cff5acae05e8c6bf58a1ba5bdf1 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -10,6 +10,7 @@ import io.netty.buffer.ByteBufOutputStream; - import io.netty.handler.codec.DecoderException; - import io.netty.handler.codec.EncoderException; - import io.netty.util.ByteProcessor; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.io.DataInput; - import java.io.DataOutput; - import java.io.IOException; -@@ -44,6 +45,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit - public class PacketDataSerializer extends ByteBuf { - - private final ByteBuf a; -+ public java.util.Locale adventure$locale; // Paper - - public PacketDataSerializer(ByteBuf bytebuf) { - this.a = bytebuf; -@@ -165,8 +167,15 @@ public class PacketDataSerializer extends ByteBuf { - return IChatBaseComponent.ChatSerializer.a(this.e(262144)); - } - -+ // Paper start -+ public PacketDataSerializer writeComponent(final net.kyori.adventure.text.Component component) { -+ return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); -+ } -+ // Paper end -+ - public PacketDataSerializer a(IChatBaseComponent ichatbasecomponent) { -- return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); -+ //return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); // Paper - comment -+ return this.writeUtf(PaperAdventure.asJsonString(ichatbasecomponent, this.adventure$locale), 262144); // Paper - } - - public > T a(Class oclass) { -@@ -349,6 +358,7 @@ public class PacketDataSerializer extends ByteBuf { - return this.a(s, 32767); - } - -+ public PacketDataSerializer writeUtf(final String string, final int maxLength) { return this.a(string, maxLength); } // Paper - OBFHELPER - public PacketDataSerializer a(String s, int i) { - byte[] abyte = s.getBytes(StandardCharsets.UTF_8); - -diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index dc8cc8d6c00176c8562086282f726dc1b24b2c65..2f6da89d6b25ba5144ec15b1bf0e8ed13278e85e 100644 ---- a/src/main/java/net/minecraft/network/PacketEncoder.java -+++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -3,6 +3,7 @@ package net.minecraft.network; - import io.netty.buffer.ByteBuf; - import io.netty.channel.ChannelHandlerContext; - import io.netty.handler.codec.MessageToByteEncoder; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.io.IOException; - import net.minecraft.network.protocol.EnumProtocolDirection; - import net.minecraft.network.protocol.Packet; -@@ -37,6 +38,7 @@ public class PacketEncoder extends MessageToByteEncoder> { - throw new IOException("Can't serialize unregistered packet"); - } else { - PacketDataSerializer packetdataserializer = new PacketDataSerializer(bytebuf); -+ packetdataserializer.adventure$locale = channelhandlercontext.channel().attr(PaperAdventure.LOCALE_ATTRIBUTE).get(); // Paper - - packetdataserializer.d(integer); - -diff --git a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -index 85140d961722e86abfe7006a0ad752751e73c721..e96fa348a37a39c381b6659f612232933686c2a7 100644 ---- a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -+++ b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -@@ -1,5 +1,6 @@ - package net.minecraft.network.chat; - -+import io.papermc.paper.adventure.AdventureComponent; // Paper - import com.google.gson.Gson; - import com.google.gson.GsonBuilder; - import com.google.gson.JsonArray; -@@ -111,6 +112,7 @@ public interface IChatBaseComponent extends Message, IChatFormatted, Iterable { - - private IChatBaseComponent a; -+ public net.kyori.adventure.text.Component adventure$message; // Paper - public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot - private ChatMessageType b; - private UUID c; -@@ -32,6 +33,11 @@ public class PacketPlayOutChat implements Packet { - - @Override - public void b(PacketDataSerializer packetdataserializer) throws IOException { -+ // Paper start -+ if (this.adventure$message != null) { -+ packetdataserializer.writeComponent(this.adventure$message); -+ } else -+ // Paper end - // Spigot start - if (components != null) { - packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java -index 0268b8e6595ee919bcd55a74ba872a2b7d2a17d8..4ff73a4fc5e8a8739e57d2bac65076812cbe5132 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java -@@ -9,6 +9,10 @@ public class PacketPlayOutPlayerListHeaderFooter implements Packet 0 && flag) { // TODO: allow plugins to override? -- IChatBaseComponent ichatbasecomponent; -- if (deathMessage.equals(deathmessage)) { -- ichatbasecomponent = this.getCombatTracker().getDeathMessage(); -- } else { -- ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage); -- } -+ if (deathMessage != null && deathMessage != net.kyori.adventure.text.Component.empty() && flag) { // Paper - Adventure // TODO: allow plugins to override? -+ IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(deathMessage); // Paper - Adventure - - this.playerConnection.a((Packet) (new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, ichatbasecomponent)), (future) -> { - if (!future.isSuccess()) { -@@ -1669,6 +1666,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.a(ichatbasecomponent, ChatMessageType.SYSTEM, uuid); - } - -+ public void sendMessage(final IChatBaseComponent message, final ChatMessageType type, final UUID sender) { this.a(message, type, sender); } // Paper - OBFHELPER - public void a(IChatBaseComponent ichatbasecomponent, ChatMessageType chatmessagetype, UUID uuid) { - this.playerConnection.a((Packet) (new PacketPlayOutChat(ichatbasecomponent, chatmessagetype, uuid)), (future) -> { - if (!future.isSuccess() && (chatmessagetype == ChatMessageType.GAME_INFO || chatmessagetype == ChatMessageType.SYSTEM)) { -@@ -1691,6 +1689,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - public String locale = "en_us"; // CraftBukkit - add, lowercase -+ public java.util.Locale adventure$locale = java.util.Locale.US; // Paper - public void a(PacketPlayInSettings packetplayinsettings) { - // CraftBukkit start - if (getMainHand() != packetplayinsettings.getMainHand()) { -@@ -1702,6 +1701,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.server.server.getPluginManager().callEvent(event); - } - this.locale = packetplayinsettings.locale; -+ // Paper start -+ this.adventure$locale = net.kyori.adventure.translation.Translator.parseLocale(this.locale); -+ this.playerConnection.networkManager.channel.attr(PaperAdventure.LOCALE_ATTRIBUTE).set(this.adventure$locale); -+ // Paper end - this.clientViewDistance = packetplayinsettings.viewDistance; - // CraftBukkit end - this.bY = packetplayinsettings.d(); -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 16275208954bfc008115aa169c5bfc149f6a4eeb..49a0aefc7f9544b36175fdf3161b255e878952a6 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -37,6 +37,7 @@ import org.apache.logging.log4j.Logger; - - // CraftBukkit start - import net.minecraft.network.chat.ChatComponentText; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import org.bukkit.craftbukkit.util.Waitable; - import org.bukkit.event.player.AsyncPlayerPreLoginEvent; - import org.bukkit.event.player.PlayerPreLoginEvent; -@@ -301,7 +302,7 @@ public class LoginListener implements PacketLoginInListener { - if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { - final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); - if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { -- event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); -+ event.disallow(asyncEvent.getResult(), asyncEvent.kickMessage()); // Paper - Adventure - } - Waitable waitable = new Waitable() { - @Override -@@ -312,12 +313,12 @@ public class LoginListener implements PacketLoginInListener { - - LoginListener.this.server.processQueue.add(waitable); - if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { -- disconnect(event.getKickMessage()); -+ disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure - return; - } - } else { - if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { -- disconnect(asyncEvent.getKickMessage()); -+ disconnect(PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure - return; - } - } -diff --git a/src/main/java/net/minecraft/server/network/PacketStatusListener.java b/src/main/java/net/minecraft/server/network/PacketStatusListener.java -index 2a96564c1656d42a74c331a6178e511cd5347a66..d219eda271a71f786808a6958b829fca40a1aaba 100644 ---- a/src/main/java/net/minecraft/server/network/PacketStatusListener.java -+++ b/src/main/java/net/minecraft/server/network/PacketStatusListener.java -@@ -56,7 +56,7 @@ public class PacketStatusListener implements PacketStatusInListener { - CraftIconCache icon = minecraftServer.server.getServerIcon(); - - ServerListPingEvent() { -- super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.getMotd(), minecraftServer.getPlayerList().getMaxPlayers()); -+ super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.server.motd(), minecraftServer.getPlayerList().getMaxPlayers()); // Paper - Adventure - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 536a351e1879fcb8066546d1179ad1af034b95da..5db09e60c2ac1f4cb0da3190e57896ccae7c58a3 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -159,6 +159,8 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - // CraftBukkit start -+import io.papermc.paper.adventure.ChatProcessor; // Paper -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.util.concurrent.ExecutionException; - import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - import net.minecraft.network.protocol.game.PacketPlayOutAttachEntity; -@@ -390,21 +392,24 @@ public class PlayerConnection implements PacketListenerPlayIn { - return this.minecraftServer.a(this.player.getProfile()); - } - -- // CraftBukkit start -- @Deprecated -- public void disconnect(IChatBaseComponent ichatbasecomponent) { -- disconnect(CraftChatMessage.fromComponent(ichatbasecomponent)); -+ public void disconnect(String s) { -+ // Paper start -+ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); - } -- // CraftBukkit end - -- public void disconnect(String s) { -+ public void disconnect(final IChatBaseComponent reason) { -+ this.disconnect(PaperAdventure.asAdventure(reason)); -+ } -+ -+ public void disconnect(net.kyori.adventure.text.Component reason) { -+ // Paper end - // CraftBukkit start - fire PlayerKickEvent - if (this.processedDisconnect) { - return; - } -- String leaveMessage = EnumChatFormat.YELLOW + this.player.getName() + " left the game."; -+ net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure - -- PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), s, leaveMessage); -+ PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure - - if (this.server.getServer().isRunning()) { - this.server.getPluginManager().callEvent(event); -@@ -415,8 +420,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - return; - } - // Send the possibly modified leave message -- s = event.getReason(); -- final IChatBaseComponent ichatbasecomponent = CraftChatMessage.fromString(s, true)[0]; -+ final IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure - // CraftBukkit end - - this.networkManager.sendPacket(new PacketPlayOutKickDisconnect(ichatbasecomponent), (future) -> { -@@ -1633,9 +1637,11 @@ public class PlayerConnection implements PacketListenerPlayIn { - */ - - this.player.p(); -- String quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); -- if ((quitMessage != null) && (quitMessage.length() > 0)) { -- this.minecraftServer.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); -+ // Paper start - Adventure -+ net.kyori.adventure.text.Component quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); -+ if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) { -+ this.minecraftServer.getPlayerList().sendMessage(PaperAdventure.asVanilla(quitMessage)); -+ // Paper end - } - // CraftBukkit end - ITextFilter itextfilter = this.player.Q(); -@@ -1851,8 +1857,13 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.handleCommand(s); - } else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) { - // Do nothing, this is coming from a plugin -- } else { -- Player player = this.getPlayer(); -+ // Paper start -+ } else if (true) { -+ final ChatProcessor cp = new ChatProcessor(this.minecraftServer, this.player, s, async); -+ cp.process(); -+ // Paper end -+ } else if (false) { // Paper -+ Player player = this.getPlayer(); // Paper - AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(minecraftServer)); - this.server.getPluginManager().callEvent(event); - -@@ -2670,21 +2681,20 @@ public class PlayerConnection implements PacketListenerPlayIn { - return; - } - -- // CraftBukkit start -- Player player = this.server.getPlayer(this.player); -- int x = packetplayinupdatesign.b().getX(); -- int y = packetplayinupdatesign.b().getY(); -- int z = packetplayinupdatesign.b().getZ(); -- String[] lines = new String[4]; -+ // CraftBukkit start // Paper start - Adventure -+ List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines[i] = EnumChatFormat.a(new ChatComponentText(EnumChatFormat.a((String) list.get(i))).getString()); -+ lines.add(net.kyori.adventure.text.Component.text(list.get(i))); - } -- SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.server.getPlayer(this.player), lines); -+ SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.server.getPluginManager().callEvent(event); - - if (!event.isCancelled()) { -- System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.lines, 0, 4); -+ for (int i = 0; i < 4; i++) { -+ tileentitysign.a(i, PaperAdventure.asVanilla(event.line(i))); -+ } -+ // Paper end - tileentitysign.isEditable = false; - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index c601a5c577e438a3fa8dd4c5f36dbe9494b03d52..6ebd4ec781aa215c2b941261250c15c87c223cab 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -8,6 +8,7 @@ import com.mojang.authlib.GameProfile; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.adventure.PaperAdventure; - import java.io.File; - import java.net.SocketAddress; - import java.text.SimpleDateFormat; -@@ -92,6 +93,7 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - // CraftBukkit start -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import com.google.common.base.Predicate; - import com.google.common.collect.Iterables; - -@@ -255,7 +257,7 @@ public abstract class PlayerList { - } - // CraftBukkit start - chatmessage.a(EnumChatFormat.YELLOW); -- String joinMessage = CraftChatMessage.fromComponent(chatmessage); -+ IChatBaseComponent joinMessage = chatmessage; // Paper - Adventure - - playerconnection.a(entityplayer.locX(), entityplayer.locY(), entityplayer.locZ(), entityplayer.yaw, entityplayer.pitch); - this.players.add(entityplayer); -@@ -264,19 +266,18 @@ public abstract class PlayerList { - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below - - // CraftBukkit start -- PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(cserver.getPlayer(entityplayer), joinMessage); -+ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - cserver.getPluginManager().callEvent(playerJoinEvent); - - if (!entityplayer.playerConnection.networkManager.isConnected()) { - return; - } - -- joinMessage = playerJoinEvent.getJoinMessage(); -+ final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); - -- if (joinMessage != null && joinMessage.length() > 0) { -- for (IChatBaseComponent line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { -- server.getPlayerList().sendAll(new PacketPlayOutChat(line, ChatMessageType.SYSTEM, SystemUtils.b)); -- } -+ if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure -+ joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure -+ server.getPlayerList().sendAll(new PacketPlayOutChat(joinMessage, ChatMessageType.SYSTEM, SystemUtils.b)); // Paper - Adventure - } - // CraftBukkit end - -@@ -473,7 +474,7 @@ public abstract class PlayerList { - - } - -- public String disconnect(EntityPlayer entityplayer) { // CraftBukkit - return string -+ public net.kyori.adventure.text.Component disconnect(EntityPlayer entityplayer) { // Paper - return Component - WorldServer worldserver = entityplayer.getWorldServer(); - - entityplayer.a(StatisticList.LEAVE_GAME); -@@ -484,7 +485,7 @@ public abstract class PlayerList { - entityplayer.closeInventory(); - } - -- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getName() + " left the game"); -+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); - cserver.getPluginManager().callEvent(playerQuitEvent); - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - -@@ -545,7 +546,7 @@ public abstract class PlayerList { - cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); - // CraftBukkit end - -- return playerQuitEvent.getQuitMessage(); // CraftBukkit -+ return playerQuitEvent.quitMessage(); // Paper - Adventure - } - - // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer -@@ -591,10 +592,10 @@ public abstract class PlayerList { - } - - // return chatmessage; -- if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); // Spigot -+ if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure - } else if (!this.isWhitelisted(gameprofile)) { - chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); -- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot -+ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure - } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { - IpBanEntry ipbanentry = this.l.get(socketaddress); - -@@ -604,17 +605,17 @@ public abstract class PlayerList { - } - - // return chatmessage; -- event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); -+ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - } else { - // return this.players.size() >= this.maxPlayers && !this.f(gameprofile) ? new ChatMessage("multiplayer.disconnect.server_full") : null; - if (this.players.size() >= this.maxPlayers && !this.f(gameprofile)) { -- event.disallow(PlayerLoginEvent.Result.KICK_FULL, org.spigotmc.SpigotConfig.serverFullMessage); // Spigot -+ event.disallow(PlayerLoginEvent.Result.KICK_FULL, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure - } - } - - cserver.getPluginManager().callEvent(event); - if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { -- loginlistener.disconnect(event.getKickMessage()); -+ loginlistener.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure - return null; - } - return entity; -@@ -1135,7 +1136,7 @@ public abstract class PlayerList { - public void shutdown() { - // CraftBukkit start - disconnect safely - for (EntityPlayer player : this.players) { -- player.playerConnection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message -+ player.playerConnection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure - } - // CraftBukkit end - -diff --git a/src/main/java/net/minecraft/world/BossBattle.java b/src/main/java/net/minecraft/world/BossBattle.java -index f9154b306379c45f15fe55406aaa00351b0471e8..1fb9fea7683075f427edfa411c7747d60928d537 100644 ---- a/src/main/java/net/minecraft/world/BossBattle.java -+++ b/src/main/java/net/minecraft/world/BossBattle.java -@@ -1,5 +1,6 @@ - package net.minecraft.world; - -+import io.papermc.paper.adventure.PaperAdventure; - import java.util.UUID; - import net.minecraft.EnumChatFormat; - import net.minecraft.network.chat.IChatBaseComponent; -@@ -14,6 +15,7 @@ public abstract class BossBattle { - protected boolean e; - protected boolean f; - protected boolean g; -+ public net.kyori.adventure.bossbar.BossBar adventure; // Paper - - public BossBattle(UUID uuid, IChatBaseComponent ichatbasecomponent, BossBattle.BarColor bossbattle_barcolor, BossBattle.BarStyle bossbattle_barstyle) { - this.h = uuid; -@@ -28,61 +30,75 @@ public abstract class BossBattle { - } - - public IChatBaseComponent j() { -+ if(this.adventure != null) return PaperAdventure.asVanilla(this.adventure.name()); // Paper - return this.title; - } - - public void a(IChatBaseComponent ichatbasecomponent) { -+ if (this.adventure != null) this.adventure.name(PaperAdventure.asAdventure(ichatbasecomponent)); // Paper - this.title = ichatbasecomponent; - } - - public float getProgress() { -+ if (this.adventure != null) return this.adventure.progress(); // Paper - return this.b; - } - - public void a(float f) { -+ if (this.adventure != null) this.adventure.progress(f); // Paper - this.b = f; - } - - public BossBattle.BarColor l() { -+ if (this.adventure != null) return PaperAdventure.asVanilla(this.adventure.color()); // Paper - return this.color; - } - - public void a(BossBattle.BarColor bossbattle_barcolor) { -+ if(this.adventure != null) this.adventure.color(PaperAdventure.asAdventure(bossbattle_barcolor)); // Paper - this.color = bossbattle_barcolor; - } - - public BossBattle.BarStyle m() { -+ if(this.adventure != null) return PaperAdventure.asVanilla(this.adventure.overlay()); // Paper - return this.style; - } - - public void a(BossBattle.BarStyle bossbattle_barstyle) { -+ if(this.adventure != null) this.adventure.overlay(PaperAdventure.asAdventure(bossbattle_barstyle)); // Paper - this.style = bossbattle_barstyle; - } - - public boolean isDarkenSky() { -+ if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.DARKEN_SCREEN); // Paper - return this.e; - } - - public BossBattle a(boolean flag) { -+ if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.DARKEN_SCREEN, flag); // Paper - this.e = flag; - return this; - } - - public boolean isPlayMusic() { -+ if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.PLAY_BOSS_MUSIC); // Paper - return this.f; - } - - public BossBattle b(boolean flag) { -+ if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.PLAY_BOSS_MUSIC, flag); // Paper - this.f = flag; - return this; - } - - public BossBattle c(boolean flag) { -+ if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.CREATE_WORLD_FOG, flag); // Paper - this.g = flag; - return this; - } - - public boolean isCreateFog() { -+ if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.CREATE_WORLD_FOG); // Paper - return this.g; - } - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 4010152dccc93019f2e7f284d80b92bae0d91c34..f1a780768e3f4bdb43a7ca6d7850befefb71bf57 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -867,6 +867,7 @@ public final class ItemStack { - } - // CraftBukkit end - -+ public IChatBaseComponent displayName() { return this.C(); } // Paper - OBFHELPER - public IChatBaseComponent C() { - IChatMutableComponent ichatmutablecomponent = (new ChatComponentText("")).addSibling(this.getName()); - -diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -index 0134bbda9e6fc900b7eefa05442e25539bab3431..b76ef55145336cc8dc4857b79767f5a738ad5144 100644 ---- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -+++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -@@ -94,6 +94,7 @@ public abstract class Enchantment { - return this.f(); - } - -+ public final IChatBaseComponent getTranslationComponentForLevel(int level) { return this.d(level); } // Paper - OBFHELPER - public IChatBaseComponent d(int i) { - ChatMessage chatmessage = new ChatMessage(this.g()); - -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -index 7ec93ddd7e7c9dc54e3e4dcfe0d1654c0b0a8536..3f057f0bd23bc1c693c8f04ee8acd6626c620008 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -@@ -32,6 +32,7 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - // CraftBukkit start -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.util.UUID; - - import org.bukkit.craftbukkit.CraftServer; -@@ -473,7 +474,7 @@ public class WorldMap extends PersistentBase { - for ( org.bukkit.map.MapCursor cursor : render.cursors) { - - if (cursor.isVisible()) { -- icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); -+ icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure - } - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0c1e12b0b43f949d4ace600b2ccdffe52faab1e6..2ad09749f3005c3eff143d83580e25910341aa6b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -562,8 +562,10 @@ public final class CraftServer implements Server { - } - - @Override -+ @Deprecated // Paper start - public int broadcastMessage(String message) { -- return broadcast(message, BROADCAST_CHANNEL_USERS); -+ return this.broadcast(message, BROADCAST_CHANNEL_USERS); -+ // Paper end - } - - public Player getPlayer(final EntityPlayer entity) { -@@ -1307,7 +1309,15 @@ public final class CraftServer implements Server { - return configuration.getInt("settings.spawn-radius", -1); - } - -+ // Paper start - @Override -+ public net.kyori.adventure.text.Component shutdownMessage() { -+ String msg = getShutdownMessage(); -+ return msg != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(msg) : null; -+ } -+ // Paper end -+ @Override -+ @Deprecated // Paper - public String getShutdownMessage() { - return configuration.getString("settings.shutdown-message"); - } -@@ -1423,7 +1433,20 @@ public final class CraftServer implements Server { - } - - @Override -+ @Deprecated // Paper - public int broadcast(String message, String permission) { -+ // Paper start - Adventure -+ return this.broadcast(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(message), permission); -+ } -+ -+ @Override -+ public int broadcast(net.kyori.adventure.text.Component message) { -+ return this.broadcast(message, BROADCAST_CHANNEL_USERS); -+ } -+ -+ @Override -+ public int broadcast(net.kyori.adventure.text.Component message, String permission) { -+ // Paper end - Set recipients = new HashSet<>(); - for (Permissible permissible : getPluginManager().getPermissionSubscriptions(permission)) { - if (permissible instanceof CommandSender && permissible.hasPermission(permission)) { -@@ -1431,14 +1454,14 @@ public final class CraftServer implements Server { - } - } - -- BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); -+ BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); // Paper - Adventure - getPluginManager().callEvent(broadcastMessageEvent); - - if (broadcastMessageEvent.isCancelled()) { - return 0; - } - -- message = broadcastMessageEvent.getMessage(); -+ message = broadcastMessageEvent.message(); // Paper - Adventure - - for (CommandSender recipient : recipients) { - recipient.sendMessage(message); -@@ -1664,6 +1687,14 @@ public final class CraftServer implements Server { - return CraftInventoryCreator.INSTANCE.createInventory(owner, type); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); -+ return CraftInventoryCreator.INSTANCE.createInventory(owner, type, title); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); -@@ -1676,13 +1707,28 @@ public final class CraftServer implements Server { - return CraftInventoryCreator.INSTANCE.createInventory(owner, size); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) throws IllegalArgumentException { -+ Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); -+ return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, int size, String title) throws IllegalArgumentException { - Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); - return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); - } - -+ // Paper start -+ @Override -+ public Merchant createMerchant(net.kyori.adventure.text.Component title) { -+ return new org.bukkit.craftbukkit.inventory.CraftMerchantCustom(title == null ? InventoryType.MERCHANT.defaultTitle() : title); -+ } -+ // Paper end - @Override -+ @Deprecated // Paper - public Merchant createMerchant(String title) { - return new CraftMerchantCustom(title == null ? InventoryType.MERCHANT.getDefaultTitle() : title); - } -@@ -1726,6 +1772,12 @@ public final class CraftServer implements Server { - return Thread.currentThread().equals(console.serverThread) || console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog) - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component motd() { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(new net.minecraft.network.chat.ChatComponentText(console.getMotd())); -+ } -+ // Paper end - @Override - public String getMotd() { - return console.getMotd(); -@@ -2154,5 +2206,15 @@ public final class CraftServer implements Server { - return null; - } - } -+ -+ // Paper start -+ private Iterable adventure$audiences; -+ @Override -+ public Iterable audiences() { -+ if (this.adventure$audiences == null) { -+ this.adventure$audiences = com.google.common.collect.Iterables.concat(java.util.Collections.singleton(this.getConsoleSender()), this.getOnlinePlayers()); -+ } -+ return this.adventure$audiences; -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 05aedca561919a12ced1925c5cc9af585bb04523..ce9f10f890a5866ab6208c7253b15b09fe323a81 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -19,6 +19,12 @@ public class Main { - public static boolean useConsole = true; - - public static void main(String[] args) { -+ // Paper start -+ final String warnWhenLegacyFormattingDetected = String.join(".", "net", "kyori", "adventure", "text", "warnWhenLegacyFormattingDetected"); -+ if (false && System.getProperty(warnWhenLegacyFormattingDetected) == null) { -+ System.setProperty(warnWhenLegacyFormattingDetected, String.valueOf(true)); -+ } -+ // Paper end - // Todo: Installation script - OptionParser parser = new OptionParser() { - { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -index ae735836accc6bf6f0831f72ff882720b69df792..d3ae5cadd88f9012203d2c04cbe38af9b215ef0b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -@@ -70,6 +70,19 @@ public class CraftBeacon extends CraftBlockEntityState impleme - this.getSnapshot().secondaryEffect = (effect != null) ? MobEffectList.fromId(effect.getId()) : null; - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component customName() { -+ final TileEntityBeacon be = this.getSnapshot(); -+ return be.customName != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.customName) : null; -+ } -+ -+ @Override -+ public void customName(final net.kyori.adventure.text.Component customName) { -+ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); -+ } -+ // Paper end -+ - @Override - public String getCustomName() { - TileEntityBeacon beacon = this.getSnapshot(); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java -index e8ce890c551c9b809e8ba3f7449dc33f3a3a6b80..c99a59573653ee5d14e780137c769116bf781ea7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java -@@ -32,6 +32,19 @@ public abstract class CraftContainer extends Craf - this.getSnapshot().chestLock = (key == null) ? ChestLock.a : new ChestLock(key); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component customName() { -+ final T be = this.getSnapshot(); -+ return be.hasCustomName() ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.getCustomName()) : null; -+ } -+ -+ @Override -+ public void customName(final net.kyori.adventure.text.Component customName) { -+ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); -+ } -+ // Paper end -+ - @Override - public String getCustomName() { - T container = this.getSnapshot(); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java -index a559a77aae870988f4dd5e6f5f1f08feb3fad054..75ee5cc96c0e54f99e2ce820289bb74f57c426a2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java -@@ -16,6 +16,19 @@ public class CraftEnchantingTable extends CraftBlockEntityState implements Sign { - - // Lazily initialized only if requested: -- private String[] originalLines = null; -- private String[] lines = null; -+ // Paper start -+ private java.util.ArrayList originalLines = null; // ArrayList for RandomAccess -+ private java.util.ArrayList lines = null; // ArrayList for RandomAccess -+ // Paper end - - public CraftSign(final Block block) { - super(block, TileEntitySign.class); -@@ -24,27 +26,52 @@ public class CraftSign extends CraftBlockEntityState implements - super(material, te); - } - -+ // Paper start - @Override -- public String[] getLines() { -- if (lines == null) { -- // Lazy initialization: -- TileEntitySign sign = this.getSnapshot(); -- lines = new String[sign.lines.length]; -- System.arraycopy(revertComponents(sign.lines), 0, lines, 0, lines.length); -- originalLines = new String[lines.length]; -- System.arraycopy(lines, 0, originalLines, 0, originalLines.length); -+ public java.util.List lines() { -+ this.loadLines(); -+ return this.lines; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.Component line(int index) { -+ this.loadLines(); -+ return this.lines.get(index); -+ } -+ -+ @Override -+ public void line(int index, net.kyori.adventure.text.Component line) { -+ this.loadLines(); -+ this.lines.set(index, line); -+ } -+ -+ private void loadLines() { -+ if (lines != null) { -+ return; - } -- return lines; -+ -+ // Lazy initialization: -+ TileEntitySign sign = this.getSnapshot(); -+ lines = io.papermc.paper.adventure.PaperAdventure.asAdventure(com.google.common.collect.Lists.newArrayList(sign.lines)); -+ originalLines = new java.util.ArrayList<>(lines); -+ } -+ // Paper end -+ @Override -+ public String[] getLines() { -+ this.loadLines(); -+ return this.lines.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).toArray(String[]::new); // Paper - } - - @Override - public String getLine(int index) throws IndexOutOfBoundsException { -- return getLines()[index]; -+ this.loadLines(); -+ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(this.lines.get(index)); // Paper - } - - @Override - public void setLine(int index, String line) throws IndexOutOfBoundsException { -- getLines()[index] = line; -+ this.loadLines(); -+ this.lines.set(index, line != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(line) : net.kyori.adventure.text.Component.empty()); // Paper - } - - @Override -@@ -72,16 +99,32 @@ public class CraftSign extends CraftBlockEntityState implements - super.applyTo(sign); - - if (lines != null) { -- for (int i = 0; i < lines.length; i++) { -- String line = (lines[i] == null) ? "" : lines[i]; -- if (line.equals(originalLines[i])) { -+ // Paper start -+ for (int i = 0; i < this.lines.size(); ++i) { -+ net.kyori.adventure.text.Component component = this.lines.get(i); -+ net.kyori.adventure.text.Component origComp = this.originalLines.get(i); -+ if (component.equals(origComp)) { - continue; // The line contents are still the same, skip. - } -- sign.lines[i] = CraftChatMessage.fromString(line)[0]; -+ sign.lines[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(component); - } -+ // Paper end - } - } - -+ // Paper start -+ public static IChatBaseComponent[] sanitizeLines(java.util.List lines) { -+ IChatBaseComponent[] components = new IChatBaseComponent[4]; -+ for (int i = 0; i < 4; i++) { -+ if (i < lines.size() && lines.get(i) != null) { -+ components[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(lines.get(i)); -+ } else { -+ components[i] = new ChatComponentText(""); -+ } -+ } -+ return components; -+ } -+ // Paper end - public static IChatBaseComponent[] sanitizeLines(String[] lines) { - IChatBaseComponent[] components = new IChatBaseComponent[4]; - -diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -index 089fe4a3458ed3106fa214f89a7004a5d3c6bb95..af986adfdb547cb61fbd52f0f89858f1a9e52cc3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -@@ -80,4 +80,11 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co - public boolean isConversing() { - return conversationTracker.isConversing(); - } -+ -+ // Paper start -+ @Override -+ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { -+ this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); -+ } -+ // 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 8f694de2fb3827b9be0dd768ad90eb72c7d708e4..5a14430f63894bbe9daa42900cf5a6519bea4f45 100644 ---- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -+++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -@@ -187,6 +187,12 @@ public class CraftEnchantment extends Enchantment { - CraftEnchantment ench = (CraftEnchantment) other; - return !target.isCompatible(ench.target); - } -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName(int level) { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); -+ } -+ // Paper end - - public net.minecraft.world.item.enchantment.Enchantment getHandle() { - return target; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index eea242af23825ad29ada6e997205e87edffb6bb9..3cf81734c8580f4d88ea97b6ac737a370b413c84 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -768,6 +768,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return getHandle().getVehicle().getBukkitEntity(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component customName() { -+ final IChatBaseComponent name = this.getHandle().getCustomName(); -+ return name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(name) : null; -+ } -+ -+ @Override -+ public void customName(final net.kyori.adventure.text.Component customName) { -+ this.getHandle().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); -+ } -+ // Paper end -+ - @Override - public void setCustomName(String name) { - // sane limit for name length -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 816f2cbebe849a9d9533f985298bcd5d36f660eb..24e856473a0050c0b097c179776350379d464d0c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -318,9 +318,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - container = CraftEventFactory.callInventoryOpenEvent(player, container); - if (container == null) return; - -- String title = container.getBukkitView().getTitle(); -+ //String title = container.getBukkitView().getTitle(); // Paper - comment -+ net.kyori.adventure.text.Component adventure$title = container.getBukkitView().title(); // Paper -+ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper - -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); -+ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment -+ player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - getHandle().activeContainer = container; - getHandle().activeContainer.addSlotListener(player); - } -@@ -389,8 +392,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - - // Now open the window - Containers windowType = CraftContainer.getNotchInventoryType(inventory.getTopInventory()); -- String title = inventory.getTitle(); -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); -+ -+ //String title = inventory.getTitle(); // Paper - comment -+ net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper -+ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper -+ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment -+ player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - player.activeContainer = container; - player.activeContainer.addSlotListener(player); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b51a874e4665f977a154792e6216e03e04525f39..6ab14bccb1fcd108931bf7ec331e60f652e0b42d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -240,14 +240,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public String getDisplayName() { -+ if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper - return getHandle().displayName; - } - - @Override - public void setDisplayName(final String name) { -+ this.getHandle().adventure$displayName = name != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(name) : net.kyori.adventure.text.Component.text(this.getName()); // Paper - getHandle().displayName = name == null ? getName() : name; - } - -+ // Paper start -+ @Override -+ public void playerListName(net.kyori.adventure.text.Component name) { -+ getHandle().listName = name == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(name); -+ for (EntityPlayer player : server.getHandle().players) { -+ if (player.getBukkitEntity().canSee(this)) { -+ player.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, getHandle())); -+ } -+ } -+ } -+ @Override -+ public net.kyori.adventure.text.Component playerListName() { -+ return getHandle().listName == null ? net.kyori.adventure.text.Component.text(getName()) : io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().listName); -+ } -+ @Override -+ public net.kyori.adventure.text.Component playerListHeader() { -+ return playerListHeader; -+ } -+ @Override -+ public net.kyori.adventure.text.Component playerListFooter() { -+ return playerListFooter; -+ } -+ // Paper end - @Override - public String getPlayerListName() { - return getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(getHandle().listName); -@@ -266,35 +291,35 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - } - -- private IChatBaseComponent playerListHeader; -- private IChatBaseComponent playerListFooter; -+ private net.kyori.adventure.text.Component playerListHeader; // Paper - Adventure -+ private net.kyori.adventure.text.Component playerListFooter; // Paper - Adventure - - @Override - public String getPlayerListHeader() { -- return (playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader); -+ return (playerListHeader == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListHeader); // Paper - Adventure - } - - @Override - public String getPlayerListFooter() { -- return (playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter); -+ return (playerListFooter == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListFooter); // Paper - Adventure - } - - @Override - public void setPlayerListHeader(String header) { -- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); -+ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure - updatePlayerListHeaderFooter(); - } - - @Override - public void setPlayerListFooter(String footer) { -- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); -+ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure - updatePlayerListHeaderFooter(); - } - - @Override - public void setPlayerListHeaderFooter(String header, String footer) { -- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); -- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); -+ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure -+ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure - updatePlayerListHeaderFooter(); - } - -@@ -302,8 +327,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (getHandle().playerConnection == null) return; - - PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); -- packet.header = (this.playerListHeader == null) ? new ChatComponentText("") : this.playerListHeader; -- packet.footer = (this.playerListFooter == null) ? new ChatComponentText("") : this.playerListFooter; -+ packet.header = (this.playerListHeader == null) ? new ChatComponentText("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListHeader); // Paper - Adventure -+ packet.footer = (this.playerListFooter == null) ? new ChatComponentText("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListFooter); // Paper - Adventure - getHandle().playerConnection.sendPacket(packet); - } - -@@ -335,6 +360,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getHandle().playerConnection.disconnect(message == null ? "" : message); - } - -+ // Paper start -+ @Override -+ public void kick(final net.kyori.adventure.text.Component message) { -+ org.spigotmc.AsyncCatcher.catchOp("player kick"); -+ final PlayerConnection connection = this.getHandle().playerConnection; -+ if (connection != null) { -+ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); -+ } -+ } -+ // Paper end -+ - @Override - public void setCompassTarget(Location loc) { - if (getHandle().playerConnection == null) return; -@@ -561,6 +597,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getHandle().playerConnection.sendPacket(packet); - } - -+ // Paper start -+ @Override -+ public void sendSignChange(Location loc, List lines) { -+ this.sendSignChange(loc, lines, org.bukkit.DyeColor.BLACK); -+ } -+ @Override -+ public void sendSignChange(Location loc, List lines, DyeColor dyeColor) { -+ if (getHandle().playerConnection == null) { -+ return; -+ } -+ if (lines == null) { -+ lines = new java.util.ArrayList<>(4); -+ } -+ Validate.notNull(loc, "Location cannot be null"); -+ Validate.notNull(dyeColor, "DyeColor cannot be null"); -+ if (lines.size() < 4) { -+ throw new IllegalArgumentException("Must have at least 4 lines"); -+ } -+ IChatBaseComponent[] components = CraftSign.sanitizeLines(lines); -+ this.sendSignChange0(components, loc, dyeColor); -+ } -+ -+ private void sendSignChange0(IChatBaseComponent[] components, Location loc, DyeColor dyeColor) { -+ TileEntitySign sign = new TileEntitySign(); -+ sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); -+ sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); -+ System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); -+ -+ getHandle().playerConnection.sendPacket(sign.getUpdatePacket()); -+ } -+ // Paper end - @Override - public void sendSignChange(Location loc, String[] lines) { - sendSignChange(loc, lines, DyeColor.BLACK); -@@ -583,12 +650,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - IChatBaseComponent[] components = CraftSign.sanitizeLines(lines); -- TileEntitySign sign = new TileEntitySign(); -+ /*TileEntitySign sign = new TileEntitySign(); // Paper - sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); - sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); - System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); - -- getHandle().playerConnection.sendPacket(sign.getUpdatePacket()); -+ getHandle().playerConnection.sendPacket(sign.getUpdatePacket());*/ // Paper -+ this.sendSignChange0(components, loc, dyeColor); // Paper - } - - @Override -@@ -1688,6 +1756,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return (getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : getHandle().clientViewDistance; - } - -+ // Paper start -+ @Override -+ public java.util.Locale locale() { -+ return getHandle().adventure$locale; -+ } -+ // Paper end - @Override - public int getPing() { - return getHandle().ping; -@@ -1716,6 +1790,138 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getInventory().setItemInMainHand(hand); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() { -+ return this.getHandle().adventure$displayName; -+ } -+ -+ @Override -+ public void displayName(final net.kyori.adventure.text.Component displayName) { -+ this.getHandle().adventure$displayName = displayName != null ? displayName : net.kyori.adventure.text.Component.text(this.getName()); -+ this.getHandle().displayName = null; -+ } -+ -+ @Override -+ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { -+ final PacketPlayOutChat packet = new PacketPlayOutChat(null, type == net.kyori.adventure.audience.MessageType.CHAT ? net.minecraft.network.chat.ChatMessageType.CHAT : net.minecraft.network.chat.ChatMessageType.SYSTEM, identity.uuid()); -+ packet.adventure$message = message; -+ this.getHandle().playerConnection.sendPacket(packet); -+ } -+ -+ @Override -+ public void sendActionBar(final net.kyori.adventure.text.Component message) { -+ final PacketPlayOutTitle packet = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, null); -+ packet.adventure$text = message; -+ this.getHandle().playerConnection.sendPacket(packet); -+ } -+ -+ @Override -+ public void sendPlayerListHeader(final net.kyori.adventure.text.Component header) { -+ this.playerListHeader = header; -+ this.adventure$sendPlayerListHeaderAndFooter(); -+ } -+ -+ @Override -+ public void sendPlayerListFooter(final net.kyori.adventure.text.Component footer) { -+ this.playerListFooter = footer; -+ this.adventure$sendPlayerListHeaderAndFooter(); -+ } -+ -+ @Override -+ public void sendPlayerListHeaderAndFooter(final net.kyori.adventure.text.Component header, final net.kyori.adventure.text.Component footer) { -+ this.playerListHeader = header; -+ this.playerListFooter = footer; -+ this.adventure$sendPlayerListHeaderAndFooter(); -+ } -+ -+ private void adventure$sendPlayerListHeaderAndFooter() { -+ final PlayerConnection connection = this.getHandle().playerConnection; -+ if (connection == null) return; -+ final PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); -+ packet.adventure$header = (this.playerListHeader == null) ? net.kyori.adventure.text.Component.empty() : this.playerListHeader; -+ packet.adventure$footer = (this.playerListFooter == null) ? net.kyori.adventure.text.Component.empty() : this.playerListFooter; -+ connection.sendPacket(packet); -+ } -+ -+ @Override -+ public void showTitle(final net.kyori.adventure.title.Title title) { -+ final PlayerConnection connection = this.getHandle().playerConnection; -+ final net.kyori.adventure.title.Title.Times times = title.times(); -+ if (times != null) { -+ connection.sendPacket(new PacketPlayOutTitle(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut()))); -+ } -+ final PacketPlayOutTitle sp = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, null); -+ sp.adventure$text = title.subtitle(); -+ connection.sendPacket(sp); -+ final PacketPlayOutTitle tp = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, null); -+ tp.adventure$text = title.title(); -+ connection.sendPacket(tp); -+ } -+ -+ private static int ticks(final java.time.Duration duration) { -+ if (duration == null) { -+ return -1; -+ } -+ return (int) (duration.toMillis() / 50L); -+ } -+ -+ @Override -+ public void clearTitle() { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.CLEAR, null)); -+ } -+ -+ // resetTitle implemented above -+ -+ @Override -+ public void showBossBar(final net.kyori.adventure.bossbar.BossBar bar) { -+ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerShow(this); -+ } -+ -+ @Override -+ public void hideBossBar(final net.kyori.adventure.bossbar.BossBar bar) { -+ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerHide(this); -+ } -+ -+ @Override -+ public void playSound(final net.kyori.adventure.sound.Sound sound) { -+ final Vec3D pos = this.getHandle().getPositionVector(); -+ this.playSound(sound, pos.x, pos.y, pos.z); -+ } -+ -+ @Override -+ public void playSound(final net.kyori.adventure.sound.Sound sound, final double x, final double y, final double z) { -+ final MinecraftKey name = io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.name()); -+ final java.util.Optional event = net.minecraft.core.IRegistry.SOUND_EVENT.getOptional(name); -+ if (event.isPresent()) { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(event.get(), io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), x, y, z, sound.volume(), sound.pitch())); -+ } else { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutCustomSoundEffect(name, io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), new Vec3D(x, y, z), sound.volume(), sound.pitch())); -+ } -+ } -+ -+ @Override -+ public void stopSound(final net.kyori.adventure.sound.SoundStop stop) { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutStopSound( -+ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.sound()), -+ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.source()) -+ )); -+ } -+ -+ @Override -+ public void openBook(final net.kyori.adventure.inventory.Book book) { -+ final java.util.Locale locale = this.getHandle().adventure$locale; -+ final net.minecraft.world.item.ItemStack item = io.papermc.paper.adventure.PaperAdventure.asItemStack(book, locale); -+ final EntityPlayer player = this.getHandle(); -+ final PlayerConnection connection = player.playerConnection; -+ final net.minecraft.world.entity.player.PlayerInventory inventory = player.inventory; -+ final int slot = inventory.items.size() + inventory.itemInHandIndex; -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutSetSlot(0, slot, item)); -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutOpenBook(net.minecraft.world.EnumHand.MAIN_HAND)); -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutSetSlot(0, slot, inventory.getItemInHand())); -+ } -+ // Paper end -+ - // Spigot start - private final Player.Spigot spigot = new Player.Spigot() - { -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 5df71cbc9d5b7a481fd087623a0d02c98e5fefc4..8a7511fc1876dc6761826dd2636bce19d177d2e8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -788,9 +788,9 @@ public class CraftEventFactory { - return event; - } - -- public static PlayerDeathEvent callPlayerDeathEvent(EntityPlayer victim, List drops, String deathMessage, boolean keepInventory) { -+ public static PlayerDeathEvent callPlayerDeathEvent(EntityPlayer victim, List drops, net.kyori.adventure.text.Component deathMessage, String stringDeathMessage, boolean keepInventory) { // Paper - Adventure - CraftPlayer entity = victim.getBukkitEntity(); -- PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage); -+ PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure - event.setKeepInventory(keepInventory); - org.bukkit.World world = entity.getWorld(); - Bukkit.getServer().getPluginManager().callEvent(event); -@@ -814,7 +814,7 @@ public class CraftEventFactory { - * Server methods - */ - public static ServerListPingEvent callServerListPingEvent(Server craftServer, InetAddress address, String motd, int numPlayers, int maxPlayers) { -- ServerListPingEvent event = new ServerListPingEvent(address, motd, numPlayers, maxPlayers); -+ ServerListPingEvent event = new ServerListPingEvent(address, craftServer.motd(), numPlayers, maxPlayers); // Paper - Adventure - craftServer.getPluginManager().callEvent(event); - return event; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -index 384520dd734449d4e4f5243fbaad5f666b0c965c..614ab2d73db2293116f2272f6cd5c16da446132d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -@@ -39,6 +39,7 @@ public class CraftContainer extends Container { - - private final InventoryView view; - private InventoryType cachedType; -+ private net.kyori.adventure.text.Component adventure$title; // Paper - private String cachedTitle; - private Container delegate; - private final int cachedSize; -@@ -50,7 +51,9 @@ public class CraftContainer extends Container { - IInventory top = ((CraftInventory) view.getTopInventory()).getInventory(); - PlayerInventory bottom = (PlayerInventory) ((CraftInventory) view.getBottomInventory()).getInventory(); - cachedType = view.getType(); -- cachedTitle = view.getTitle(); -+ this.adventure$title = view.title(); // Paper -+ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper -+ //cachedTitle = view.getTitle(); // Paper - comment - cachedSize = getSize(); - setupSlots(top, bottom, player); - } -@@ -77,6 +80,13 @@ public class CraftContainer extends Container { - return inventory.getType(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component title() { -+ return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).title() : net.kyori.adventure.text.Component.text(inventory.getType().getDefaultTitle()); -+ } -+ // Paper end -+ - @Override - public String getTitle() { - return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).getTitle() : inventory.getType().getDefaultTitle(); -@@ -95,7 +105,8 @@ public class CraftContainer extends Container { - - @Override - public boolean c(EntityHuman entityhuman) { -- if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { -+ if (cachedType == view.getType() && cachedSize == getSize() && this.adventure$title.equals(view.title())) { // Paper -+ //if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { // Paper - comment - return true; - } - // If the window type has changed for some reason, update the player -@@ -103,7 +114,9 @@ public class CraftContainer extends Container { - // as good a place as any to put something like this. - boolean typeChanged = (cachedType != view.getType()); - cachedType = view.getType(); -- cachedTitle = view.getTitle(); -+ this.adventure$title = view.title(); // Paper -+ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper -+ //cachedTitle = view.getTitle(); // Paper - comment - if (view.getPlayer() instanceof CraftPlayer) { - CraftPlayer player = (CraftPlayer) view.getPlayer(); - Containers type = getNotchInventoryType(view.getTopInventory()); -@@ -115,7 +128,8 @@ public class CraftContainer extends Container { - setupSlots(top, bottom, player.getHandle()); - } - int size = getSize(); -- player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, new ChatComponentText(cachedTitle))); -+ player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, io.papermc.paper.adventure.PaperAdventure.asVanilla(this.adventure$title))); // Paper -+ //player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, new ChatComponentText(cachedTitle))); // Paper - comment - player.updateInventory(); - } - return true; -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -index a537cc4ac5d052168f96a1ae73b6b17a380436ab..21347cf02cc01c90a81e7dd8264ef11968d9f145 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -@@ -19,6 +19,12 @@ public class CraftInventoryCustom extends CraftInventory { - super(new MinecraftInventory(owner, type)); - } - -+ // Paper start -+ public CraftInventoryCustom(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ super(new MinecraftInventory(owner, type, title)); -+ } -+ // Paper end -+ - public CraftInventoryCustom(InventoryHolder owner, InventoryType type, String title) { - super(new MinecraftInventory(owner, type, title)); - } -@@ -27,6 +33,12 @@ public class CraftInventoryCustom extends CraftInventory { - super(new MinecraftInventory(owner, size)); - } - -+ // Paper start -+ public CraftInventoryCustom(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { -+ super(new MinecraftInventory(owner, size, title)); -+ } -+ // Paper end -+ - public CraftInventoryCustom(InventoryHolder owner, int size, String title) { - super(new MinecraftInventory(owner, size, title)); - } -@@ -36,9 +48,17 @@ public class CraftInventoryCustom extends CraftInventory { - private int maxStack = MAX_STACK; - private final List viewers; - private final String title; -+ private final net.kyori.adventure.text.Component adventure$title; // Paper - private InventoryType type; - private final InventoryHolder owner; - -+ // Paper start -+ public MinecraftInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ this(owner, type.getDefaultSize(), title); -+ this.type = type; -+ } -+ // Paper end -+ - public MinecraftInventory(InventoryHolder owner, InventoryType type) { - this(owner, type.getDefaultSize(), type.getDefaultTitle()); - this.type = type; -@@ -57,11 +77,24 @@ public class CraftInventoryCustom extends CraftInventory { - Validate.notNull(title, "Title cannot be null"); - this.items = NonNullList.a(size, ItemStack.b); - this.title = title; -+ this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(title); - this.viewers = new ArrayList(); - this.owner = owner; - this.type = InventoryType.CHEST; - } - -+ // Paper start -+ public MinecraftInventory(final InventoryHolder owner, final int size, final net.kyori.adventure.text.Component title) { -+ Validate.notNull(title, "Title cannot be null"); -+ this.items = NonNullList.a(size, ItemStack.b); -+ this.title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); -+ this.adventure$title = title; -+ this.viewers = new ArrayList(); -+ this.owner = owner; -+ this.type = InventoryType.CHEST; -+ } -+ // Paper end -+ - @Override - public int getSize() { - return items.size(); -@@ -183,6 +216,12 @@ public class CraftInventoryCustom extends CraftInventory { - return null; - } - -+ // Paper start -+ public net.kyori.adventure.text.Component title() { -+ return this.adventure$title; -+ } -+ // Paper end -+ - public String getTitle() { - return title; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -index 04073ed45f8068d80e58d3927b5ebc3160c6a8c6..9949bb8cac73b2f1f02b51079c0e244f923af8e9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -@@ -64,6 +64,13 @@ public class CraftInventoryView extends InventoryView { - return CraftItemStack.asCraftMirror(container.getSlot(slot).getItem()); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component title() { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.container.getTitle()); -+ } -+ // Paper end -+ - @Override - public String getTitle() { - return CraftChatMessage.fromComponent(container.getTitle()); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 89a3617068421bb86baf4e8bfd9df2d0626adff7..ccd27aa93b4ab1dc09a8d684b43b5ecb69100ed8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -334,4 +334,17 @@ public final class CraftItemFactory implements ItemFactory { - public Material updateMaterial(ItemMeta meta, Material material) throws IllegalArgumentException { - return ((CraftMetaItem) meta).updateMaterial(material); - } -+ -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final ItemStack item, final java.util.function.UnaryOperator op) { -+ final net.minecraft.nbt.NBTTagCompound tag = CraftItemStack.asNMSCopy(item).getTag(); -+ return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowItem.of(item.getType().getKey(), item.getAmount(), io.papermc.paper.adventure.PaperAdventure.asBinaryTagHolder(tag)))); -+ } -+ -+ @Override -+ public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -index ef10c7ab1d615cdba182eca63eb14309339a5314..206c133ebc6c44038585236b0628543b8bed278c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -@@ -14,10 +14,17 @@ import org.apache.commons.lang.Validate; - - public class CraftMerchantCustom extends CraftMerchant { - -+ @Deprecated // Paper - Adventure - public CraftMerchantCustom(String title) { - super(new MinecraftMerchant(title)); - getMerchant().craftMerchant = this; - } -+ // Paper start -+ public CraftMerchantCustom(net.kyori.adventure.text.Component title) { -+ super(new MinecraftMerchant(title)); -+ getMerchant().craftMerchant = this; -+ } -+ // Paper end - - @Override - public String toString() { -@@ -37,10 +44,17 @@ public class CraftMerchantCustom extends CraftMerchant { - private World tradingWorld; - protected CraftMerchant craftMerchant; - -+ @Deprecated // Paper - Adventure - public MinecraftMerchant(String title) { - Validate.notNull(title, "Title cannot be null"); - this.title = new ChatComponentText(title); - } -+ // Paper start -+ public MinecraftMerchant(net.kyori.adventure.text.Component title) { -+ Validate.notNull(title, "Title cannot be null"); -+ this.title = io.papermc.paper.adventure.PaperAdventure.asVanilla(title); -+ } -+ // Paper end - - @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 4cdc504df4cad6f7725f6d18482e88433523943a..65b6d32e3e1130a64df33082f3292cb1ce6f500a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -1,8 +1,9 @@ - package org.bukkit.craftbukkit.inventory; - - import com.google.common.collect.ImmutableList; --import com.google.common.collect.ImmutableMap.Builder; - import com.google.common.collect.Lists; -+ -+import com.google.common.collect.ImmutableMap; // Paper - import java.util.ArrayList; - import java.util.Arrays; - import java.util.List; -@@ -21,6 +22,7 @@ import org.bukkit.craftbukkit.util.CraftChatMessage; - import org.bukkit.craftbukkit.util.CraftMagicNumbers; - import org.bukkit.inventory.meta.BookMeta; - import org.bukkit.inventory.meta.BookMeta.Generation; -+import org.checkerframework.checker.nullness.qual.NonNull; - - // Spigot start - import static org.spigotmc.ValidateUtils.*; -@@ -269,6 +271,141 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - this.generation = (generation == null) ? null : generation.ordinal(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component title() { -+ return this.title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.title); -+ } -+ -+ @Override -+ public org.bukkit.inventory.meta.BookMeta title(net.kyori.adventure.text.Component title) { -+ this.setTitle(title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title)); -+ return this; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.Component author() { -+ return this.author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.author); -+ } -+ -+ @Override -+ public org.bukkit.inventory.meta.BookMeta author(net.kyori.adventure.text.Component author) { -+ this.setAuthor(author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author)); -+ return this; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.Component page(final int page) { -+ Validate.isTrue(isValidPage(page), "Invalid page number"); -+ return this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(pages.get(page - 1)) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(pages.get(page - 1)); -+ } -+ -+ @Override -+ public void page(final int page, net.kyori.adventure.text.Component data) { -+ if (!isValidPage(page)) { -+ throw new IllegalArgumentException("Invalid page number " + page + "/" + pages.size()); -+ } -+ if (data == null) { -+ data = net.kyori.adventure.text.Component.empty(); -+ } -+ pages.set(page - 1, this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(data) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(data)); -+ } -+ -+ @Override -+ public List pages() { -+ if (this.pages == null) return ImmutableList.of(); -+ if (this instanceof CraftMetaBookSigned) -+ return pages.stream().map(net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson()::deserialize).collect(ImmutableList.toImmutableList()); -+ else -+ return pages.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::deserialize).collect(ImmutableList.toImmutableList()); -+ } -+ -+ @Override -+ public BookMeta pages(List pages) { -+ if (this.pages != null) this.pages.clear(); -+ for (net.kyori.adventure.text.Component page : pages) { -+ addPages(page); -+ } -+ return this; -+ } -+ -+ @Override -+ public BookMeta pages(net.kyori.adventure.text.Component... pages) { -+ if (this.pages != null) this.pages.clear(); -+ addPages(pages); -+ return this; -+ } -+ -+ @Override -+ public void addPages(net.kyori.adventure.text.Component... pages) { -+ if (this.pages == null) this.pages = new ArrayList<>(); -+ for (net.kyori.adventure.text.Component page : pages) { -+ if (this.pages.size() >= MAX_PAGES) { -+ return; -+ } -+ -+ if (page == null) { -+ page = net.kyori.adventure.text.Component.empty(); -+ } -+ -+ this.pages.add(this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(page) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(page)); -+ } -+ } -+ -+ private CraftMetaBook(net.kyori.adventure.text.Component title, net.kyori.adventure.text.Component author, List pages) { -+ super((org.bukkit.craftbukkit.inventory.CraftMetaItem) org.bukkit.Bukkit.getItemFactory().getItemMeta(org.bukkit.Material.WRITABLE_BOOK)); -+ this.title = title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); -+ this.author = author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author); -+ this.pages = pages.subList(0, Math.min(MAX_PAGES, pages.size())).stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).collect(java.util.stream.Collectors.toList()); -+ } -+ -+ static final class CraftMetaBookBuilder implements BookMetaBuilder { -+ private net.kyori.adventure.text.Component title = null; -+ private net.kyori.adventure.text.Component author = null; -+ private final List pages = new java.util.ArrayList<>(); -+ -+ @Override -+ public BookMetaBuilder title(net.kyori.adventure.text.Component title) { -+ this.title = title; -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder author(net.kyori.adventure.text.Component author) { -+ this.author = author; -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder addPage(net.kyori.adventure.text.Component page) { -+ this.pages.add(page); -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder pages(net.kyori.adventure.text.Component... pages) { -+ java.util.Collections.addAll(this.pages, pages); -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder pages(java.util.Collection pages) { -+ this.pages.addAll(pages); -+ return this; -+ } -+ -+ @Override -+ public BookMeta build() { -+ return new CraftMetaBook(title, author, pages); -+ } -+ } -+ -+ @Override -+ public BookMetaBuilder toBuilder() { -+ return new CraftMetaBookBuilder(); -+ } -+ -+ // Paper end - @Override - public String getPage(final int page) { - Validate.isTrue(isValidPage(page), "Invalid page number"); -@@ -413,7 +550,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - } - - @Override -- Builder serialize(Builder builder) { -+ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { - super.serialize(builder); - - if (hasTitle()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -index 0835541f51e643ae824c197be7100d5849b5e92a..0d58ec9834797ad7b9acaae6353dcf0385c53fd4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -@@ -1,6 +1,6 @@ - package org.bukkit.craftbukkit.inventory; - --import com.google.common.collect.ImmutableMap.Builder; -+import com.google.common.collect.ImmutableMap; // Paper - import java.util.Map; - import net.minecraft.nbt.NBTTagCompound; - import org.bukkit.Material; -@@ -84,7 +84,7 @@ class CraftMetaBookSigned extends CraftMetaBook implements BookMeta { - } - - @Override -- Builder serialize(Builder builder) { -+ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { - super.serialize(builder); - return builder; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 928328c292a1322cab478bc748761baf8608e4b0..7a11b2ddfa4244459253c918315aaab78ef2eb4a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -745,6 +745,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() { -+ return displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(displayName); -+ } -+ -+ @Override -+ public void displayName(final net.kyori.adventure.text.Component displayName) { -+ this.displayName = displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(displayName); -+ } -+ // Paper end -+ - @Override - public String getDisplayName() { - return CraftChatMessage.fromJSONComponent(displayName); -@@ -780,6 +792,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return this.lore != null && !this.lore.isEmpty(); - } - -+ // Paper start -+ @Override -+ public List lore() { -+ return this.lore != null ? io.papermc.paper.adventure.PaperAdventure.asAdventureFromJson(this.lore) : null; -+ } -+ -+ @Override -+ public void lore(final List lore) { -+ this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asJson(lore) : null; -+ } -+ // Paper end -+ - @Override - public boolean hasRepairCost() { - return repairCost > 0; -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java -index ed4415f6dd588c08c922efd5beebb3b124beb9d6..78a7ac47f20e84ccd67ff44d0bc7a2f2faa0d476 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java -@@ -12,6 +12,13 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve - return new CraftInventoryCustom(holder, type); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ return new CraftInventoryCustom(owner, type, title); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - return new CraftInventoryCustom(owner, type, title); -@@ -21,6 +28,12 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve - return new CraftInventoryCustom(owner, size); - } - -+ // Paper start -+ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { -+ return new CraftInventoryCustom(owner, size, title); -+ } -+ // Paper end -+ - public Inventory createInventory(InventoryHolder owner, int size, String title) { - return new CraftInventoryCustom(owner, size, title); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b833806a0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -@@ -43,6 +43,17 @@ public final class CraftInventoryCreator { - return converterMap.get(type).createInventory(holder, type); - } - -+ // Paper start -+ public Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title) { -+ // Paper start -+ if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type, title); -+ } -+ //noinspection ConstantConditions // Paper end -+ return converterMap.get(type).createInventory(holder, type, title); -+ } -+ // Paper end -+ - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - return converterMap.get(type).createInventory(holder, type, title); - } -@@ -51,6 +62,12 @@ public final class CraftInventoryCreator { - return DEFAULT_CONVERTER.createInventory(holder, size); - } - -+ // Paper start -+ public Inventory createInventory(InventoryHolder holder, int size, net.kyori.adventure.text.Component title) { -+ return DEFAULT_CONVERTER.createInventory(holder, size, title); -+ } -+ // Paper end -+ - public Inventory createInventory(InventoryHolder holder, int size, String title) { - return DEFAULT_CONVERTER.createInventory(holder, size, title); - } -@@ -59,6 +76,10 @@ public final class CraftInventoryCreator { - - Inventory createInventory(InventoryHolder holder, InventoryType type); - -+ // Paper start -+ Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title); -+ // Paper end -+ - Inventory createInventory(InventoryHolder holder, InventoryType type, String title); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -index f35e66dab9ff63ca05d7e303c71106c0e9971309..2bd4e644ffbde2e1133b25824a2829bc6b33fa84 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -@@ -31,6 +31,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return getInventory(getTileEntity()); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ IInventory te = getTileEntity(); -+ if (te instanceof TileEntityLootable) { -+ ((TileEntityLootable) te).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); -+ } -+ -+ return getInventory(te); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - IInventory te = getTileEntity(); -@@ -54,6 +66,15 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return furnace; - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ IInventory tileEntity = getTileEntity(); -+ ((TileEntityFurnace) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); -+ return getInventory(tileEntity); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - IInventory tileEntity = getTileEntity(); -@@ -74,6 +95,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return new TileEntityBrewingStand(); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ // BrewingStand does not extend TileEntityLootable -+ IInventory tileEntity = getTileEntity(); -+ if (tileEntity instanceof TileEntityBrewingStand) { -+ ((TileEntityBrewingStand) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); -+ } -+ return getInventory(tileEntity); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - // BrewingStand does not extend TileEntityLootable -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -index 8fedca656af0783f3d97a7ccde3a113f97911084..df3deee12b11508b76c5f8f927fac8db54a7e397 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -@@ -31,6 +31,21 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective - return objective.getName(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(objective.getDisplayName()); -+ } -+ @Override -+ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { -+ if (displayName == null) { -+ displayName = net.kyori.adventure.text.Component.empty(); -+ } -+ CraftScoreboard scoreboard = checkState(); -+ objective.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); -+ } -+ // Paper end - @Override - public String getDisplayName() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -index 954389b818de93cf0ab046edc5dc032fceea391b..6ea491f6308317059c4bc6735abbdce370df0f34 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -@@ -28,6 +28,27 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - public CraftObjective registerNewObjective(String name, String criteria) throws IllegalArgumentException { - return registerNewObjective(name, criteria, name); - } -+ // Paper start -+ @Override -+ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName) { -+ return registerNewObjective(name, criteria, displayName, org.bukkit.scoreboard.RenderType.INTEGER); -+ } -+ @Override -+ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName, RenderType renderType) { -+ if (displayName == null) { -+ displayName = net.kyori.adventure.text.Component.empty(); -+ } -+ Validate.notNull(name, "Objective name cannot be null"); -+ Validate.notNull(criteria, "Criteria cannot be null"); -+ Validate.notNull(displayName, "Display name cannot be null"); -+ Validate.notNull(renderType, "RenderType cannot be null"); -+ Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); -+ Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); -+ CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); -+ return new CraftObjective(this, objective); -+ } -+ // Paper end - - @Override - public CraftObjective registerNewObjective(String name, String criteria, String displayName) throws IllegalArgumentException { -@@ -36,7 +57,7 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - - @Override - public CraftObjective registerNewObjective(String name, String criteria, String displayName, RenderType renderType) throws IllegalArgumentException { -- Validate.notNull(name, "Objective name cannot be null"); -+ /*Validate.notNull(name, "Objective name cannot be null"); // Paper - Validate.notNull(criteria, "Criteria cannot be null"); - Validate.notNull(displayName, "Display name cannot be null"); - Validate.notNull(renderType, "RenderType cannot be null"); -@@ -46,7 +67,8 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - - CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); - ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); -- return new CraftObjective(this, objective); -+ return new CraftObjective(this, objective);*/ // Paper -+ return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -index a213c2e3b2680c6d1bd38853580cbdb52ae7779e..c631934fe9d205a06956c900d5b58a1d8a781c19 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -@@ -29,6 +29,55 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { - - return team.getName(); - } -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getDisplayName()); -+ } -+ @Override -+ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { -+ if (displayName == null) displayName = net.kyori.adventure.text.Component.empty(); -+ CraftScoreboard scoreboard = checkState(); -+ team.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); -+ } -+ @Override -+ public net.kyori.adventure.text.Component prefix() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPrefix()); -+ } -+ @Override -+ public void prefix(net.kyori.adventure.text.Component prefix) throws IllegalStateException, IllegalArgumentException { -+ if (prefix == null) prefix = net.kyori.adventure.text.Component.empty(); -+ CraftScoreboard scoreboard = checkState(); -+ team.setPrefix(io.papermc.paper.adventure.PaperAdventure.asVanilla(prefix)); -+ } -+ @Override -+ public net.kyori.adventure.text.Component suffix() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getSuffix()); -+ } -+ @Override -+ public void suffix(net.kyori.adventure.text.Component suffix) throws IllegalStateException, IllegalArgumentException { -+ if (suffix == null) suffix = net.kyori.adventure.text.Component.empty(); -+ CraftScoreboard scoreboard = checkState(); -+ team.setSuffix(io.papermc.paper.adventure.PaperAdventure.asVanilla(suffix)); -+ } -+ @Override -+ public net.kyori.adventure.text.format.TextColor color() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ if (team.getColor().getHexValue() == null) throw new IllegalStateException("Team colors must have hex values"); -+ net.kyori.adventure.text.format.TextColor color = net.kyori.adventure.text.format.TextColor.color(team.getColor().getHexValue()); -+ if (!(color instanceof net.kyori.adventure.text.format.NamedTextColor)) throw new IllegalStateException("Team doesn't have a NamedTextColor"); -+ return (net.kyori.adventure.text.format.NamedTextColor) color; -+ } -+ @Override -+ public void color(net.kyori.adventure.text.format.NamedTextColor color) { -+ if (color == null) color = net.kyori.adventure.text.format.NamedTextColor.WHITE; -+ CraftScoreboard scoreboard = checkState(); -+ team.setColor(io.papermc.paper.adventure.PaperAdventure.asVanilla(color)); -+ } -+ // Paper end - - @Override - public String getDisplayName() throws IllegalStateException { -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -index 6a0b4cd36ac54df41642e8499c50e59f2b347b48..666af6cc91bd12ba5d5a846d663a5aabf861fbc4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -@@ -290,6 +290,7 @@ public final class CraftChatMessage { - - public static String fromComponent(IChatBaseComponent component) { - if (component == null) return ""; -+ if (component instanceof io.papermc.paper.adventure.AdventureComponent) component = ((io.papermc.paper.adventure.AdventureComponent) component).deepConverted(); - StringBuilder out = new StringBuilder(); - - 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 65131f0977fa55c4761c34ce52720170feb61a72..8f737f63f280c00c1276bd1dc3ecf60448732ca8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -59,6 +59,33 @@ public final class CraftMagicNumbers implements UnsafeValues { - - private CraftMagicNumbers() {} - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener() { -+ return io.papermc.paper.adventure.PaperAdventure.FLATTENER; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.COLOR_DOWNSAMPLING_GSON; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.GSON; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.PLAIN; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC; -+ } -+ // Paper end -+ - public static IBlockData getBlock(MaterialData material) { - return getBlock(material.getItemType(), material.getData()); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java -index f194cf2663919ea18309a0501ddfab5e2ed639dd..4b110d6c6f22ff7c2fa0fd4b459820797066199d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java -@@ -80,7 +80,7 @@ public abstract class LazyHashSet implements Set { - return this.reference = makeReference(); - } - -- abstract Set makeReference(); -+ protected abstract Set makeReference(); // Paper - protected - - public boolean isLazy() { - return reference == null; -diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java -index e7b9250ebdd0d9034ef18a96a6cacc83e6db69c2..20ee8468bcf305139a51da61f5f9026794da27f6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java -@@ -15,10 +15,15 @@ public class LazyPlayerSet extends LazyHashSet { - } - - @Override -- HashSet makeReference() { -+ protected HashSet makeReference() { // Paper - protected - if (reference != null) { - throw new IllegalStateException("Reference already created!"); - } -+ // Paper start -+ return makePlayerSet(this.server); -+ } -+ public static HashSet makePlayerSet(final MinecraftServer server) { -+ // Paper end - List players = server.getPlayerList().players; - HashSet reference = new HashSet(players.size()); - for (EntityPlayer player : players) { diff --git a/Unmapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch b/Unmapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch deleted file mode 100644 index d184572c6b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 13:02:51 -0600 -Subject: [PATCH] Configurable cactus bamboo and reed growth heights - -Bamboo - Both the minimum fully-grown heights and the maximum are configurable -- Machine_Maker - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b31109d2dadd29e8852468c19265066b773d2be0..3618cc017feb60e257a28f67cbddca3f792a9833 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -65,4 +65,17 @@ public class PaperWorldConfig { - config.addDefault("world-settings.default." + path, def); - return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); - } -+ -+ public int cactusMaxHeight; -+ public int reedMaxHeight; -+ public int bambooMaxHeight; -+ public int bambooMinHeight; -+ private void blockGrowthHeight() { -+ cactusMaxHeight = getInt("max-growth-height.cactus", 3); -+ reedMaxHeight = getInt("max-growth-height.reeds", 3); -+ bambooMaxHeight = getInt("max-growth-height.bamboo.max", 16); -+ bambooMinHeight = getInt("max-growth-height.bamboo.min", 11); -+ log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); -+ -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBamboo.java b/src/main/java/net/minecraft/world/level/block/BlockBamboo.java -index 6d10a7cb48627f37dc91b73064edc5f18c2b5ce9..cd132eff3f82349518555d1d5a16778ca08a521b 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBamboo.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBamboo.java -@@ -124,7 +124,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - if (random.nextInt(Math.max(1, (int) (100.0F / worldserver.spigotConfig.bambooModifier) * 3)) == 0 && worldserver.isEmpty(blockposition.up()) && worldserver.getLightLevel(blockposition.up(), 0) >= 9) { // Spigot - int i = this.b(worldserver, blockposition) + 1; - -- if (i < 16) { -+ if (i < worldserver.paperConfig.bambooMaxHeight) { // Paper - this.a(iblockdata, (World) worldserver, blockposition, random, i); - } - } -@@ -155,7 +155,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - int i = this.a(iblockaccess, blockposition); - int j = this.b(iblockaccess, blockposition); - -- return i + j + 1 < 16 && (Integer) iblockaccess.getType(blockposition.up(i)).get(BlockBamboo.f) != 1; -+ return i + j + 1 < ((World) iblockaccess).paperConfig.bambooMaxHeight && (Integer) iblockaccess.getType(blockposition.up(i)).get(BlockBamboo.f) != 1; // Paper - } - - @Override -@@ -174,7 +174,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - BlockPosition blockposition1 = blockposition.up(i); - IBlockData iblockdata1 = worldserver.getType(blockposition1); - -- if (k >= 16 || !iblockdata1.a(Blocks.BAMBOO) || (Integer) iblockdata1.get(BlockBamboo.f) == 1 || !worldserver.isEmpty(blockposition1.up())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here -+ if (k >= worldserver.paperConfig.bambooMaxHeight || !iblockdata1.a(Blocks.BAMBOO) || (Integer) iblockdata1.get(BlockBamboo.f) == 1 || !worldserver.isEmpty(blockposition1.up())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here // Paper - Configurable cactus bamboo and reed growth heights - return; - } - -@@ -215,7 +215,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - } - - int j = (Integer) iblockdata.get(BlockBamboo.d) != 1 && !iblockdata2.a(Blocks.BAMBOO) ? 0 : 1; -- int k = (i < 11 || random.nextFloat() >= 0.25F) && i != 15 ? 0 : 1; -+ int k = (i < world.paperConfig.bambooMinHeight || random.nextFloat() >= 0.25F) && i != (world.paperConfig.bambooMaxHeight - 1) ? 0 : 1; // Paper - - // CraftBukkit start - if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, blockposition, blockposition.up(), (IBlockData) ((IBlockData) ((IBlockData) this.getBlockData().set(BlockBamboo.d, j)).set(BlockBamboo.e, blockpropertybamboosize)).set(BlockBamboo.f, k), 3)) { -@@ -230,7 +230,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - protected int a(IBlockAccess iblockaccess, BlockPosition blockposition) { - int i; - -- for (i = 0; i < 16 && iblockaccess.getType(blockposition.up(i + 1)).a(Blocks.BAMBOO); ++i) { -+ for (i = 0; i < ((World) iblockaccess).paperConfig.bambooMaxHeight && iblockaccess.getType(blockposition.up(i + 1)).a(Blocks.BAMBOO); ++i) { // Paper - ; - } - -@@ -240,7 +240,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - protected int b(IBlockAccess iblockaccess, BlockPosition blockposition) { - int i; - -- for (i = 0; i < 16 && iblockaccess.getType(blockposition.down(i + 1)).a(Blocks.BAMBOO); ++i) { -+ for (i = 0; i < ((World) iblockaccess).paperConfig.bambooMaxHeight && iblockaccess.getType(blockposition.down(i + 1)).a(Blocks.BAMBOO); ++i) { // Paper - ; - } - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCactus.java b/src/main/java/net/minecraft/world/level/block/BlockCactus.java -index c2316e346f9b647edae4c9709defa4531e04eaa6..9f1e9fc5361cd051b909e2e1b2095722064185da 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCactus.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCactus.java -@@ -55,7 +55,7 @@ public class BlockCactus extends Block { - ; - } - -- if (i < 3) { -+ if (i < worldserver.paperConfig.cactusMaxHeight) { // Paper - Configurable growth height - int j = (Integer) iblockdata.get(BlockCactus.AGE); - - if (j >= (byte) range(3, ((100.0F / worldserver.spigotConfig.cactusModifier) * 15) + 0.5F, 15)) { // Spigot -diff --git a/src/main/java/net/minecraft/world/level/block/BlockReed.java b/src/main/java/net/minecraft/world/level/block/BlockReed.java -index eb95d65e1a37b91a71a9ad8968710ba9047f3980..a4ede7968ba0134f0d2cf880a6b4a6b9a81f2fcd 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockReed.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockReed.java -@@ -51,7 +51,7 @@ public class BlockReed extends Block { - ; - } - -- if (i < 3) { -+ if (i < worldserver.paperConfig.reedMaxHeight) { // Paper - Configurable growth height - int j = (Integer) iblockdata.get(BlockReed.AGE); - - if (j >= (byte) range(3, ((100.0F / worldserver.spigotConfig.caneModifier) * 15) + 0.5F, 15)) { // Spigot diff --git a/Unmapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch b/Unmapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch deleted file mode 100644 index 060f23376f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 13:09:16 -0600 -Subject: [PATCH] Configurable baby zombie movement speed - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3618cc017feb60e257a28f67cbddca3f792a9833..796c17e0941922a9716212c6eae91643d8360418 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -78,4 +78,15 @@ public class PaperWorldConfig { - log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); - - } -+ -+ public double babyZombieMovementModifier; -+ private void babyZombieMovementModifier() { -+ babyZombieMovementModifier = getDouble("baby-zombie-movement-modifier", 0.5D); -+ if (PaperConfig.version < 20) { -+ babyZombieMovementModifier = getDouble("baby-zombie-movement-speed", 0.5D); -+ set("baby-zombie-movement-modifier", babyZombieMovementModifier); -+ } -+ -+ log("Baby zombies will move at the speed of " + babyZombieMovementModifier); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index daa6d1ca20f952971a2ad6a0c4cba0bef6e43bf6..219e3b1626d68ede57b08a706d24bb6bc4b13fac 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -82,7 +82,7 @@ import org.bukkit.event.entity.EntityTransformEvent; - public class EntityZombie extends EntityMonster { - - private static final UUID b = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836"); -- private static final AttributeModifier c = new AttributeModifier(EntityZombie.b, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); -+ private final AttributeModifier c = new AttributeModifier(EntityZombie.b, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); private final AttributeModifier babyModifier = this.c; // Paper - remove static - Make baby speed configurable - private static final DataWatcherObject d = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); - private static final DataWatcherObject bo = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.b); - public static final DataWatcherObject DROWN_CONVERTING = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); -@@ -185,9 +185,9 @@ public class EntityZombie extends EntityMonster { - if (this.world != null && !this.world.isClientSide) { - AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); - -- attributemodifiable.removeModifier(EntityZombie.c); -+ attributemodifiable.removeModifier(this.babyModifier); // Paper - if (flag) { -- attributemodifiable.b(EntityZombie.c); -+ attributemodifiable.b(this.babyModifier); // Paper - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch b/Unmapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch deleted file mode 100644 index b516f276ef..0000000000 --- a/Unmapped-Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 13:14:11 -0600 -Subject: [PATCH] Configurable fishing time ranges - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 796c17e0941922a9716212c6eae91643d8360418..78948c42b13194005bdbbbc69c2b7ae0732a78c5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -89,4 +89,12 @@ public class PaperWorldConfig { - - log("Baby zombies will move at the speed of " + babyZombieMovementModifier); - } -+ -+ public int fishingMinTicks; -+ public int fishingMaxTicks; -+ private void fishingTickRange() { -+ fishingMinTicks = getInt("fishing-time-range.MinimumTicks", 100); -+ fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); -+ log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 382b40a2a030993e1e98f34bc91befdd45c16895..7402e3b305d9bb7b27b97ff2078c26dd578232a1 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -@@ -85,6 +85,10 @@ public class EntityFishingHook extends IProjectile { - entityhuman.hookedFish = this; - this.an = Math.max(0, i); - this.lureLevel = Math.max(0, j); -+ // Paper start -+ minWaitTime = world.paperConfig.fishingMinTicks; -+ maxWaitTime = world.paperConfig.fishingMaxTicks; -+ // paper end - } - - public EntityFishingHook(EntityHuman entityhuman, World world, int i, int j) { diff --git a/Unmapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/Unmapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch deleted file mode 100644 index 3c4047985e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 13:24:16 -0600 -Subject: [PATCH] Allow nerfed mobs to jump and take water damage - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 78948c42b13194005bdbbbc69c2b7ae0732a78c5..b41e7922dd96c3358eb849ab39982a75736e3476 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -97,4 +97,9 @@ public class PaperWorldConfig { - fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); - log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); - } -+ -+ public boolean nerfedMobsShouldJump; -+ private void nerfedMobsShouldJump() { -+ nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 306f6c0db2333cce5dfc4bf1c09bfef05119a28b..f823763a2f7f40d0be8d058a1bd61386bcd951e6 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1105,6 +1105,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.isInWater() || this.isInRain(); - } - -+ public final boolean isInWaterOrRainOrBubble() { return aG(); } // Paper - OBFHELPER - public boolean aG() { - return this.isInWater() || this.isInRain() || this.k(); - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index dbfcdc3cc7c1dccf785f5e13634e84c5af088985..28aa0a9361e8a32763d7fe1af060f0016e8c1e50 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -98,6 +98,7 @@ public abstract class EntityInsentient extends EntityLiving { - private final EntityAIBodyControl c; - protected NavigationAbstract navigation; - public PathfinderGoalSelector goalSelector; -+ @Nullable public PathfinderGoalFloat goalFloat; // Paper - public PathfinderGoalSelector targetSelector; - private EntityLiving goalTarget; - private final EntitySenses bo; -@@ -784,7 +785,17 @@ public abstract class EntityInsentient extends EntityLiving { - @Override - protected final void doTick() { - ++this.ticksFarFromPlayer; -- if (!this.aware) return; // CraftBukkit -+ if (!this.aware) { // Paper start - Allow nerfed mobs to jump, float and take water damage -+ if (goalFloat != null) { -+ if (goalFloat.validConditions()) goalFloat.update(); -+ this.getControllerJump().jumpIfSet(); -+ } -+ if ((this instanceof EntityBlaze || this instanceof EntityEnderman) && isInWaterOrRainOrBubble()) { -+ damageEntity(DamageSource.DROWN, 1.0F); -+ } -+ return; -+ } -+ // Paper end - this.world.getMethodProfiler().enter("sensing"); - this.bo.a(); - this.world.getMethodProfiler().exit(); -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java -index 9767ac416fcd60a8a57b648dcb3f1e427bacd54d..1a9b3e0e0c090683e332dfa53708f8a62c8f14e0 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java -@@ -15,6 +15,7 @@ public class ControllerJump { - this.a = true; - } - -+ public final void jumpIfSet() { this.b(); } // Paper - OBFHELPER - public void b() { - this.b.setJumping(this.a); - this.a = false; -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java -index 8dfa1a6ade7f51e5d68b290f5376d999bb4c60ab..a6c8763139ed18fe73b2d6f6ec511e59666dc843 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java -@@ -11,15 +11,18 @@ public class PathfinderGoalFloat extends PathfinderGoal { - - public PathfinderGoalFloat(EntityInsentient entityinsentient) { - this.a = entityinsentient; -+ if (entityinsentient.getWorld().paperConfig.nerfedMobsShouldJump) entityinsentient.goalFloat = this; // Paper - this.a(EnumSet.of(PathfinderGoal.Type.JUMP)); - entityinsentient.getNavigation().d(true); - } - -+ public final boolean validConditions() { return this.a(); } // Paper - OBFHELPER - @Override - public boolean a() { - return this.a.isInWater() && this.a.b((Tag) TagsFluid.WATER) > this.a.cx() || this.a.aQ(); - } - -+ public void update() { this.e(); } // Paper - OBFHELPER - @Override - public void e() { - if (this.a.getRandom().nextFloat() < 0.8F) { diff --git a/Unmapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch b/Unmapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch deleted file mode 100644 index 0c901ddac3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Suddenly -Date: Tue, 1 Mar 2016 13:51:54 -0600 -Subject: [PATCH] Add configurable despawn distances for living entities - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b41e7922dd96c3358eb849ab39982a75736e3476..2f0d582baf0eb2bb477944d0cb1369db6ca33956 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -102,4 +102,20 @@ public class PaperWorldConfig { - private void nerfedMobsShouldJump() { - nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); - } -+ -+ public int softDespawnDistance; -+ public int hardDespawnDistance; -+ private void despawnDistances() { -+ softDespawnDistance = getInt("despawn-ranges.soft", 32); // 32^2 = 1024, Minecraft Default -+ hardDespawnDistance = getInt("despawn-ranges.hard", 128); // 128^2 = 16384, Minecraft Default -+ -+ if (softDespawnDistance > hardDespawnDistance) { -+ softDespawnDistance = hardDespawnDistance; -+ } -+ -+ log("Living Entity Despawn Ranges: Soft: " + softDespawnDistance + " Hard: " + hardDespawnDistance); -+ -+ softDespawnDistance = softDespawnDistance*softDespawnDistance; -+ hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 28aa0a9361e8a32763d7fe1af060f0016e8c1e50..6e30fc88fa7a3ff00c9b4b78842c3a533649bd50 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -763,16 +763,16 @@ public abstract class EntityInsentient extends EntityLiving { - int i = this.getEntityType().e().f(); - int j = i * i; - -- if (d0 > (double) j) { // CraftBukkit - remove isTypeNotPersistent() check -+ if (d0 > (double) world.paperConfig.hardDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances - this.die(); - } - - int k = this.getEntityType().e().g(); - int l = k * k; - -- if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d0 > (double) l) { // CraftBukkit - remove isTypeNotPersistent() check -+ if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d0 > world.paperConfig.softDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances - this.die(); -- } else if (d0 < (double) l) { -+ } else if (d0 < world.paperConfig.softDespawnDistance) { // Paper - custom despawn distances - this.ticksFarFromPlayer = 0; - } - } diff --git a/Unmapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch b/Unmapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch deleted file mode 100644 index 126f048726..0000000000 --- a/Unmapped-Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 3 Mar 2016 03:53:43 -0600 -Subject: [PATCH] Allow for toggling of spawn chunks - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2f0d582baf0eb2bb477944d0cb1369db6ca33956..89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -118,4 +118,10 @@ public class PaperWorldConfig { - softDespawnDistance = softDespawnDistance*softDespawnDistance; - hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; - } -+ -+ public boolean keepSpawnInMemory; -+ private void keepSpawnInMemory() { -+ keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); -+ log("Keep spawn chunk loaded: " + keepSpawnInMemory); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 1b03c69fa7ffeca4083470a179e18be828b0a957..62735e7908f86e31f7a89ce2071ddebe176c0385 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -217,6 +217,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - }); - // CraftBukkit end - timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings -+ this.keepSpawnInMemory = this.paperConfig.keepSpawnInMemory; // Paper - this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } diff --git a/Unmapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch b/Unmapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch deleted file mode 100644 index ec9ba5059c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Tue, 1 Mar 2016 14:14:15 -0600 -Subject: [PATCH] Drop falling block and tnt entities at the specified height - -* Dec 2, 2020 Added tnt nerf for tnt minecarts - Machine_Maker - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75..d16ae924bcbe31c964f7fb448757c748e5c4418c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -124,4 +124,14 @@ public class PaperWorldConfig { - keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); - log("Keep spawn chunk loaded: " + keepSpawnInMemory); - } -+ -+ public int fallingBlockHeightNerf; -+ public int entityTNTHeightNerf; -+ private void heightNerfs() { -+ fallingBlockHeightNerf = getInt("falling-block-height-nerf", 0); -+ entityTNTHeightNerf = getInt("tnt-entity-height-nerf", 0); -+ -+ if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); -+ if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f823763a2f7f40d0be8d058a1bd61386bcd951e6..20e4ff812960a54872f2fea8fe6baf7bb1ef077d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1850,6 +1850,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.a(itemstack, 0.0F); - } - -+ @Nullable public final EntityItem dropItem(ItemStack itemstack, float offset) { return this.a(itemstack, offset); } // Paper - OBFHELPER - @Nullable - public EntityItem a(ItemStack itemstack, float f) { - if (itemstack.isEmpty()) { -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index b3dea8d65c3d1e27e59be142ec9e2ebb4164aed0..901522f24b8bc58861e46eda400dbab92bb6401d 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -124,6 +124,17 @@ public class EntityFallingBlock extends Entity { - } - - this.move(EnumMoveType.SELF, this.getMot()); -+ -+ // Paper start - Configurable EntityFallingBlock height nerf -+ if (this.world.paperConfig.fallingBlockHeightNerf != 0 && this.locY() > this.world.paperConfig.fallingBlockHeightNerf) { -+ if (this.dropItem && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) { -+ this.a(block); -+ } -+ -+ this.die(); -+ return; -+ } -+ // Paper end - if (!this.world.isClientSide) { - blockposition = this.getChunkCoordinates(); - boolean flag = this.block.getBlock() instanceof BlockConcretePowder; -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -index c2e7161dc103c971908ff217eaf972e9f175d044..4f4b2b8d58223fa22d6a7af5c94cfb36399b9641 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -@@ -70,6 +70,12 @@ public class EntityTNTPrimed extends Entity { - } - - this.move(EnumMoveType.SELF, this.getMot()); -+ // Paper start - Configurable TNT entity height nerf -+ if (this.world.paperConfig.entityTNTHeightNerf != 0 && this.locY() > this.world.paperConfig.entityTNTHeightNerf) { -+ this.die(); -+ return; -+ } -+ // Paper end - this.setMot(this.getMot().a(0.98D)); - if (this.onGround) { - this.setMot(this.getMot().d(0.7D, -0.5D, 0.7D)); -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java -index ee31704ffb88ab68702657554d386e8ebfa05d03..4bec5c1d504b9456dafe1b76bdbb523d0a324abe 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java -@@ -47,6 +47,12 @@ public class EntityMinecartTNT extends EntityMinecartAbstract { - public void tick() { - super.tick(); - if (this.b > 0) { -+ // Paper start - Configurable TNT entity height nerf -+ if (this.world.paperConfig.entityTNTHeightNerf != 0 && this.locY() > this.world.paperConfig.entityTNTHeightNerf) { -+ this.die(); -+ return; -+ } -+ // Paper end - --this.b; - this.world.addParticle(Particles.SMOKE, this.locX(), this.locY() + 0.5D, this.locZ(), 0.0D, 0.0D, 0.0D); - } else if (this.b == 0) { diff --git a/Unmapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/Unmapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch deleted file mode 100644 index 6ff3ad51f7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 14:32:43 -0600 -Subject: [PATCH] Show 'Paper' in client crashes, server lists, and Mojang - stats - - -diff --git a/src/main/java/net/minecraft/server/EULA.java b/src/main/java/net/minecraft/server/EULA.java -index a5171d28b960b12c2743ea68a36d747bc967697d..a0f53c9eff04a40780b3ba568dbfc5bbe9bd8504 100644 ---- a/src/main/java/net/minecraft/server/EULA.java -+++ b/src/main/java/net/minecraft/server/EULA.java -@@ -72,7 +72,7 @@ public class EULA { - Properties properties = new Properties(); - - properties.setProperty("eula", "false"); -- properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula)."); -+ properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\nYou also agree that tacos are tasty, and the best food in the world."); // Paper - fix lag; - } catch (Throwable throwable1) { - throwable = throwable1; - throw throwable1; -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 85c96e3f70a3ffecb6195a1d83053412eb180d78..c21790b4de698aa6f7fc4dadab64d791cd0562b6 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1342,7 +1342,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant // CraftBukkit - cb > vanilla! -+ return "Paper"; //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! - } - - public CrashReport b(CrashReport crashreport) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 2ad09749f3005c3eff143d83580e25910341aa6b..462633df2af43959fddf5b7a8ec43063abf7b14b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -225,7 +225,7 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; - import net.md_5.bungee.api.chat.BaseComponent; // Spigot - - public final class CraftServer implements Server { -- private final String serverName = "CraftBukkit"; -+ private final String serverName = "Paper"; // Paper - private final String serverVersion; - private final String bukkitVersion = Versioning.getBukkitVersion(); - private final Logger logger = Logger.getLogger("Minecraft"); -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index ce9f10f890a5866ab6208c7253b15b09fe323a81..e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -206,12 +206,25 @@ public class Main { - deadline.add(Calendar.DAY_OF_YEAR, -28); - 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 ***"); -+ System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper - System.err.println("*** Server will start in 20 seconds ***"); - Thread.sleep(TimeUnit.SECONDS.toMillis(20)); - } - } - -+ // Paper start - Log Java and OS versioning to help with debugging plugin issues -+ java.lang.management.RuntimeMXBean runtimeMX = java.lang.management.ManagementFactory.getRuntimeMXBean(); -+ java.lang.management.OperatingSystemMXBean osMX = java.lang.management.ManagementFactory.getOperatingSystemMXBean(); -+ if (runtimeMX != null && osMX != null) { -+ String javaInfo = "Java " + runtimeMX.getSpecVersion() + " (" + runtimeMX.getVmName() + " " + runtimeMX.getVmVersion() + ")"; -+ String osInfo = "Host: " + osMX.getName() + " " + osMX.getVersion() + " (" + osMX.getArch() + ")"; -+ -+ System.out.println("System Info: " + javaInfo + " " + osInfo); -+ } else { -+ System.out.println("Unable to read system info"); -+ } -+ // Paper end -+ - System.out.println("Loading libraries, please wait..."); - net.minecraft.server.Main.main(options); - } catch (Throwable t) { -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index b4eeeb0d001e692180874bd26385a0e786a8b752..1b3a14784cac8e855633fae6172ad5479ebe9877 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -19,7 +19,7 @@ public class WatchdogThread extends Thread - - private WatchdogThread(long timeoutTime, boolean restart) - { -- super( "Spigot Watchdog Thread" ); -+ super( "Paper Watchdog Thread" ); - this.timeoutTime = timeoutTime; - this.restart = restart; - } -@@ -65,14 +65,14 @@ public class WatchdogThread extends Thread - { - Logger log = Bukkit.getServer().getLogger(); - log.log( Level.SEVERE, "------------------------------" ); -- log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Spigot bug." ); -+ log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper - log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); - log.log( Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring" ); - log.log( Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once" ); - log.log( Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes" ); -- log.log( Level.SEVERE, "If you are unsure or still think this is a Spigot bug, please report to https://www.spigotmc.org/" ); -+ log.log( Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues" ); - log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); -- log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() ); -+ log.log( Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion() ); - // - if ( net.minecraft.world.level.World.lastPhysicsProblem != null ) - { -@@ -82,7 +82,7 @@ public class WatchdogThread extends Thread - } - // - log.log( Level.SEVERE, "------------------------------" ); -- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" ); -+ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // diff --git a/Unmapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch b/Unmapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch deleted file mode 100644 index 34f3da9b88..0000000000 --- a/Unmapped-Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 27 May 2019 03:40:05 -0500 -Subject: [PATCH] Implement Paper VersionChecker - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -new file mode 100644 -index 0000000000000000000000000000000000000000..1a1b50e475b9ede544b2f6d0d36632b24b68898c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -@@ -0,0 +1,122 @@ -+package com.destroystokyo.paper; -+ -+import com.destroystokyo.paper.util.VersionFetcher; -+import com.google.common.base.Charsets; -+import com.google.common.io.Resources; -+import com.google.gson.*; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.format.NamedTextColor; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.io.*; -+import java.net.HttpURLConnection; -+import java.net.URL; -+import java.util.stream.StreamSupport; -+ -+public class PaperVersionFetcher implements VersionFetcher { -+ private static final java.util.regex.Pattern VER_PATTERN = java.util.regex.Pattern.compile("^([0-9\\.]*)\\-.*R"); // R is an anchor, will always give '-R' at end -+ private static final String GITHUB_BRANCH_NAME = "master"; -+ private static @Nullable String mcVer; -+ -+ @Override -+ public long getCacheTime() { -+ return 720000; -+ } -+ -+ @Nonnull -+ @Override -+ public Component getVersionMessage(@Nonnull String serverVersion) { -+ String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); -+ return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); -+ } -+ -+ private static @Nullable String getMinecraftVersion() { -+ if (mcVer == null) { -+ java.util.regex.Matcher matcher = VER_PATTERN.matcher(org.bukkit.Bukkit.getBukkitVersion()); -+ if (matcher.find()) { -+ String result = matcher.group(); -+ mcVer = result.substring(0, result.length() - 2); // strip 'R' anchor and trailing '-' -+ } else { -+ org.bukkit.Bukkit.getLogger().warning("Unable to match version to pattern! Report to PaperMC!"); -+ org.bukkit.Bukkit.getLogger().warning("Pattern: " + VER_PATTERN.toString()); -+ org.bukkit.Bukkit.getLogger().warning("Version: " + org.bukkit.Bukkit.getBukkitVersion()); -+ } -+ } -+ -+ return mcVer; -+ } -+ -+ private static Component getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) { -+ int distance; -+ try { -+ int jenkinsBuild = Integer.parseInt(versionInfo); -+ distance = fetchDistanceFromSiteApi(jenkinsBuild, getMinecraftVersion()); -+ } catch (NumberFormatException ignored) { -+ versionInfo = versionInfo.replace("\"", ""); -+ distance = fetchDistanceFromGitHub(repo, branch, versionInfo); -+ } -+ -+ switch (distance) { -+ case -1: -+ return Component.text("Error obtaining version information", NamedTextColor.YELLOW); -+ case 0: -+ return Component.text("You are running the latest version", NamedTextColor.GREEN); -+ case -2: -+ return Component.text("Unknown version", NamedTextColor.YELLOW); -+ default: -+ return Component.text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW); -+ } -+ } -+ -+ private static int fetchDistanceFromSiteApi(int jenkinsBuild, @Nullable String siteApiVersion) { -+ if (siteApiVersion == null) { return -1; } -+ try { -+ try (BufferedReader reader = Resources.asCharSource( -+ new URL("https://papermc.io/api/v2/projects/paper/versions/" + siteApiVersion), -+ Charsets.UTF_8 -+ ).openBufferedStream()) { -+ JsonObject json = new Gson().fromJson(reader, JsonObject.class); -+ JsonArray builds = json.getAsJsonArray("builds"); -+ int latest = StreamSupport.stream(builds.spliterator(), false) -+ .mapToInt(e -> e.getAsInt()) -+ .max() -+ .getAsInt(); -+ return latest - jenkinsBuild; -+ } catch (JsonSyntaxException ex) { -+ ex.printStackTrace(); -+ return -1; -+ } -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return -1; -+ } -+ } -+ -+ // Contributed by Techcable in GH-65 -+ private static int fetchDistanceFromGitHub(@Nonnull String repo, @Nonnull String branch, @Nonnull String hash) { -+ try { -+ HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + repo + "/compare/" + branch + "..." + hash).openConnection(); -+ connection.connect(); -+ if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return -2; // Unknown commit -+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) { -+ JsonObject obj = new Gson().fromJson(reader, JsonObject.class); -+ String status = obj.get("status").getAsString(); -+ switch (status) { -+ case "identical": -+ return 0; -+ case "behind": -+ return obj.get("behind_by").getAsInt(); -+ default: -+ return -1; -+ } -+ } catch (JsonSyntaxException | NumberFormatException e) { -+ e.printStackTrace(); -+ return -1; -+ } -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return -1; -+ } -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 8f737f63f280c00c1276bd1dc3ecf60448732ca8..8aa9e7796ea39c09a965750d06c3d358250f33b8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -370,6 +370,11 @@ public final class CraftMagicNumbers implements UnsafeValues { - public String getTimingsServerName() { - return com.destroystokyo.paper.PaperConfig.timingsServerName; - } -+ -+ @Override -+ public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { -+ return new com.destroystokyo.paper.PaperVersionFetcher(); -+ } - // Paper end - - /** diff --git a/Unmapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch b/Unmapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch deleted file mode 100644 index a115cf4943..0000000000 --- a/Unmapped-Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Thu, 1 Mar 2018 19:37:52 -0600 -Subject: [PATCH] Add version history to version command - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -index 1a1b50e475b9ede544b2f6d0d36632b24b68898c..580bae0d414d371a07a6bfeefc41fdd989dc0083 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -@@ -5,7 +5,9 @@ import com.google.common.base.Charsets; - import com.google.common.io.Resources; - import com.google.gson.*; - import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextComponent; - import net.kyori.adventure.text.format.NamedTextColor; -+import net.kyori.adventure.text.format.TextDecoration; - - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -@@ -28,7 +30,10 @@ public class PaperVersionFetcher implements VersionFetcher { - @Override - public Component getVersionMessage(@Nonnull String serverVersion) { - String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); -- return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); -+ final Component updateMessage = getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); -+ final Component history = getHistory(); -+ -+ return history != null ? TextComponent.ofChildren(updateMessage, Component.newline(), history) : updateMessage; - } - - private static @Nullable String getMinecraftVersion() { -@@ -119,4 +124,19 @@ public class PaperVersionFetcher implements VersionFetcher { - return -1; - } - } -+ -+ @Nullable -+ private Component getHistory() { -+ final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); -+ if (data == null) { -+ return null; -+ } -+ -+ final String oldVersion = data.getOldVersion(); -+ if (oldVersion == null) { -+ return null; -+ } -+ -+ return Component.text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..aac3f66cb23d260729c2a48d8710a9de2346aa22 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java -@@ -0,0 +1,145 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.MoreObjects; -+import com.google.gson.Gson; -+import com.google.gson.JsonSyntaxException; -+import java.io.BufferedReader; -+import java.io.BufferedWriter; -+import java.io.IOException; -+import java.nio.charset.StandardCharsets; -+import java.nio.file.Files; -+import java.nio.file.Path; -+import java.nio.file.Paths; -+import java.nio.file.StandardOpenOption; -+import java.util.Objects; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+import org.bukkit.Bukkit; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+ -+public enum VersionHistoryManager { -+ INSTANCE; -+ -+ private final Gson gson = new Gson(); -+ -+ private final Logger logger = Bukkit.getLogger(); -+ -+ private VersionData currentData = null; -+ -+ VersionHistoryManager() { -+ final Path path = Paths.get("version_history.json"); -+ -+ if (Files.exists(path)) { -+ // Basic file santiy checks -+ if (!Files.isRegularFile(path)) { -+ if (Files.isDirectory(path)) { -+ logger.severe(path + " is a directory, cannot be used for version history"); -+ } else { -+ logger.severe(path + " is not a regular file, cannot be used for version history"); -+ } -+ // We can't continue -+ return; -+ } -+ -+ try (final BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { -+ currentData = gson.fromJson(reader, VersionData.class); -+ } catch (final IOException e) { -+ logger.log(Level.SEVERE, "Failed to read version history file '" + path + "'", e); -+ return; -+ } catch (final JsonSyntaxException e) { -+ logger.log(Level.SEVERE, "Invalid json syntax for file '" + path + "'", e); -+ return; -+ } -+ -+ final String version = Bukkit.getVersion(); -+ if (version == null) { -+ logger.severe("Failed to retrieve current version"); -+ return; -+ } -+ -+ if (!version.equals(currentData.getCurrentVersion())) { -+ // The version appears to have changed -+ currentData.setOldVersion(currentData.getCurrentVersion()); -+ currentData.setCurrentVersion(version); -+ writeFile(path); -+ } -+ } else { -+ // File doesn't exist, start fresh -+ currentData = new VersionData(); -+ // oldVersion is null -+ currentData.setCurrentVersion(Bukkit.getVersion()); -+ writeFile(path); -+ } -+ } -+ -+ private void writeFile(@Nonnull final Path path) { -+ try (final BufferedWriter writer = Files.newBufferedWriter( -+ path, -+ StandardCharsets.UTF_8, -+ StandardOpenOption.WRITE, -+ StandardOpenOption.CREATE, -+ StandardOpenOption.TRUNCATE_EXISTING -+ )) { -+ gson.toJson(currentData, writer); -+ } catch (final IOException e) { -+ logger.log(Level.SEVERE, "Failed to write to version history file", e); -+ } -+ } -+ -+ @Nullable -+ public VersionData getVersionData() { -+ return currentData; -+ } -+ -+ public static class VersionData { -+ private String oldVersion; -+ -+ private String currentVersion; -+ -+ @Nullable -+ public String getOldVersion() { -+ return oldVersion; -+ } -+ -+ public void setOldVersion(@Nullable String oldVersion) { -+ this.oldVersion = oldVersion; -+ } -+ -+ @Nullable -+ public String getCurrentVersion() { -+ return currentVersion; -+ } -+ -+ public void setCurrentVersion(@Nullable String currentVersion) { -+ this.currentVersion = currentVersion; -+ } -+ -+ @Override -+ public String toString() { -+ return MoreObjects.toStringHelper(this) -+ .add("oldVersion", oldVersion) -+ .add("currentVersion", currentVersion) -+ .toString(); -+ } -+ -+ @Override -+ public boolean equals(@Nullable Object o) { -+ if (this == o) { -+ return true; -+ } -+ if (o == null || getClass() != o.getClass()) { -+ return false; -+ } -+ final VersionData versionData = (VersionData) o; -+ return Objects.equals(oldVersion, versionData.oldVersion) && -+ Objects.equals(currentVersion, versionData.currentVersion); -+ } -+ -+ @Override -+ public int hashCode() { -+ return Objects.hash(oldVersion, currentVersion); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 59942eb6bb6e8e1e9a988bce0d09757e575018b9..faf4d00bf288359db806913c4d2964324e8706b7 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -196,6 +196,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - return false; - } - com.destroystokyo.paper.PaperConfig.registerCommands(); -+ com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now - // Paper end - - this.setPVP(dedicatedserverproperties.pvp); diff --git a/Unmapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch b/Unmapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch deleted file mode 100644 index 0ccd83d4e5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0021-Player-affects-spawning-API.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Tue, 1 Mar 2016 14:47:52 -0600 -Subject: [PATCH] Player affects spawning API - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 20e4ff812960a54872f2fea8fe6baf7bb1ef077d..cae9da158f54438d2a397665c7ce964f6f755469 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1354,6 +1354,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return MathHelper.c(f * f + f1 * f1 + f2 * f2); - } - -+ public double getDistanceSquared(double x, double y, double z) { return h(x, y, z); } // Paper - OBFHELPER - public double h(double d0, double d1, double d2) { - double d3 = this.locX() - d0; - double d4 = this.locY() - d1; -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 6e30fc88fa7a3ff00c9b4b78842c3a533649bd50..31bb5df7bc63c993230bf595bd9b66bfaadb4d50 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -756,7 +756,7 @@ public abstract class EntityInsentient extends EntityLiving { - if (this.world.getDifficulty() == EnumDifficulty.PEACEFUL && this.L()) { - this.die(); - } else if (!this.isPersistent() && !this.isSpecialPersistence()) { -- EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D); -+ EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D, IEntitySelector.affectsSpawning); // Paper - - if (entityhuman != null) { - double d0 = entityhuman.h((Entity) this); // CraftBukkit - decompile error -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index 6e78192a5898df017d96acba845a288011d24e35..dfcfdb31ca9531913d705aaaf85fb67399cfdc8c 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -29,6 +29,12 @@ public final class IEntitySelector { - return !entity.isSpectator(); - }; - -+ // Paper start -+ public static final Predicate affectsSpawning = (entity) -> { -+ return !entity.isSpectator() && entity.isAlive() && (entity instanceof EntityPlayer) && ((EntityPlayer) entity).affectsSpawning; -+ }; -+ // Paper end -+ - public static Predicate a(double d0, double d1, double d2, double d3) { - double d4 = d3 * d3; - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -index 0b3b430766fba602e74727f78173567ca10fabc6..e1fcb1be102822e87eaf7757fbd64a516b2f58ac 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -@@ -122,7 +122,7 @@ public class EntitySilverfish extends EntityMonster { - if (c(entitytypes, generatoraccess, enummobspawn, blockposition, random)) { - EntityHuman entityhuman = generatoraccess.a((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, 5.0D, true); - -- return entityhuman == null; -+ return !(entityhuman != null && !entityhuman.affectsSpawning) && entityhuman == null; // Paper - Affects Spawning API - } else { - return false; - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 1017ee73b8617ce2b6734469fa49aaff7563c2b1..f42e16589476c1bd10b13214dda5ac7bb3e52131 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -164,6 +164,9 @@ public abstract class EntityHuman extends EntityLiving { - private final ItemCooldown bM; - @Nullable - public EntityFishingHook hookedFish; -+ // Paper start -+ public boolean affectsSpawning = true; -+ // Paper end - - // CraftBukkit start - public boolean fauxSleeping; -diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java -index 4ece69851e7b05016f52c291ce911eb791cf3a23..6d5d4c3df65995b9a13b66d070ba08d553cc98a2 100644 ---- a/src/main/java/net/minecraft/world/level/IEntityAccess.java -+++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java -@@ -92,8 +92,9 @@ public interface IEntityAccess { - } - } - -- @Nullable -- default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { -+ default EntityHuman findNearbyPlayer(Entity entity, double d0, @Nullable Predicate predicate) { return this.findNearbyPlayer(entity.locX(), entity.locY(), entity.locZ(), d0, predicate); } // Paper -+ @Nullable default EntityHuman findNearbyPlayer(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { return a(d0, d1, d2, d3, predicate); } // Paper - OBFHELPER -+ @Nullable default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { // Paper - double d4 = -1.0D; - EntityHuman entityhuman = null; - Iterator iterator = this.getPlayers().iterator(); -@@ -126,6 +127,27 @@ public interface IEntityAccess { - return this.a(d0, d1, d2, d3, predicate); - } - -+ // Paper end -+ default boolean isAffectsSpawningPlayerNearby(double d0, double d1, double d2, double d3) { -+ Iterator iterator = this.getPlayers().iterator(); -+ double d4; -+ do { -+ EntityHuman entityhuman; -+ do { -+ if (!iterator.hasNext()) { -+ return false; -+ } -+ -+ entityhuman = (EntityHuman) iterator.next(); -+ } while (!IEntitySelector.affectsSpawning.test(entityhuman)); -+ -+ d4 = entityhuman.getDistanceSquared(d0, d1, d2); -+ } while (d3 >= 0.0D && d4 >= d3 * d3); -+ -+ return true; -+ } -+ // Paper end -+ - default boolean isPlayerNearby(double d0, double d1, double d2, double d3) { - Iterator iterator = this.getPlayers().iterator(); - -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 33cba4e475edc0573b901f70c61d3659fd63ad62..8d8b03074df1635946f81bec0feae18d2f3e20aa 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -66,7 +66,7 @@ public abstract class MobSpawnerAbstract { - private boolean h() { - BlockPosition blockposition = this.b(); - -- return this.a().isPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); -+ return this.a().isAffectsSpawningPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper - } - - public void c() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 6ab14bccb1fcd108931bf7ec331e60f652e0b42d..cc471418b37a745ecea1af964e81bc0362cf7d94 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1770,8 +1770,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - @Override - public String getLocale() { - return getHandle().locale; -+ -+ } -+ -+ // Paper start -+ public void setAffectsSpawning(boolean affects) { -+ this.getHandle().affectsSpawning = affects; - } - -+ @Override -+ public boolean getAffectsSpawning() { -+ return this.getHandle().affectsSpawning; -+ } -+ // Paper end -+ - @Override - public void updateCommands() { - if (getHandle().playerConnection == null) return; diff --git a/Unmapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch b/Unmapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch deleted file mode 100644 index 2aeae2d5b4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Tue, 1 Mar 2016 15:08:03 -0600 -Subject: [PATCH] Remove invalid mob spawner tile entities - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index ac576d268b23148089d404cb22d8c2f9d1a79d6e..a2d80c2c8e4f080f60746548f75631c5946ba8e2 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -40,9 +40,11 @@ import net.minecraft.world.level.TickListChunk; - import net.minecraft.world.level.TickListEmpty; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.BlockMobSpawner; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.ITileEntity; - import net.minecraft.world.level.block.entity.TileEntity; -+import net.minecraft.world.level.block.entity.TileEntityMobSpawner; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.levelgen.ChunkProviderDebug; - import net.minecraft.world.level.levelgen.HeightMap; -@@ -648,6 +650,10 @@ public class Chunk implements IChunkAccess { - } - - // CraftBukkit start -+ // Paper start - Remove invalid mob spawner tile entities -+ } else if (tileentity instanceof TileEntityMobSpawner && !(getBlockData(blockposition.getX(), blockposition.getY(), blockposition.getZ()).getBlock() instanceof BlockMobSpawner)) { -+ this.tileEntities.remove(blockposition); -+ // Paper end - } else { - System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ() - + " (" + getType(blockposition) + ") where there was no entity tile!"); diff --git a/Unmapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch b/Unmapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch deleted file mode 100644 index a556c9c8da..0000000000 --- a/Unmapped-Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch +++ /dev/null @@ -1,248 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 8 Mar 2015 22:55:25 -0600 -Subject: [PATCH] Optimize TileEntity Ticking - - -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index d4ebcf8f66197299256bd6b65710a1488c90ea41..c9164dfdb27ddf3709129c8aec54903a1df121ff 100644 ---- a/src/main/java/co/aikar/timings/TimingsExport.java -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -109,7 +109,7 @@ public class TimingsExport extends Thread { - pair("end", System.currentTimeMillis() / 1000), - pair("online-mode", Bukkit.getServer().getOnlineMode()), - pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), -- pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().d(), pack -> { -+ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().e(), pack -> { - // Don't feel like obf helper'ing these, non fatal if its temp missed. - return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); - })) -@@ -148,8 +148,8 @@ public class TimingsExport extends Thread { - ); - - parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getWorlds(), world -> { -- if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; -- return pair(world.getWorldData().getName(), createObject( -+ if (world.getWorld().getName().equals("worldeditregentempworld")) return null; -+ return pair(world.getWorld().getName(), createObject( - pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { - return pair(rule, world.getWorld().getGameRuleValue(rule)); - })), -diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java -index 60e7dc1910ae9214d84d65b011cfec278b6b32ae..b229faad99120c67b089f7680d800fbe594fe7da 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockChest.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java -@@ -54,8 +54,8 @@ import net.minecraft.world.phys.shapes.VoxelShapeCollision; - public class BlockChest extends BlockChestAbstract implements IBlockWaterlogged { - - public static final BlockStateDirection FACING = BlockFacingHorizontal.FACING; -- public static final BlockStateEnum c = BlockProperties.aF; -- public static final BlockStateBoolean d = BlockProperties.C; -+ public static final BlockStateEnum c = BlockProperties.aF; public static final BlockStateEnum CHEST_TYPE_PROPERTY = c; // Paper - OBFHELPER -+ public static final BlockStateBoolean d = BlockProperties.C; public static final BlockStateBoolean waterlogged() { return d; } // Paper OBFHELPER - protected static final VoxelShape e = Block.a(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D); - protected static final VoxelShape f = Block.a(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D); - protected static final VoxelShape g = Block.a(0.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -index eed95b370d1d624ffc6b7a35357b7028ec58c584..51167d776c710decb0107bebcb35bdf43103772b 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -@@ -8,6 +8,7 @@ import net.minecraft.core.NonNullList; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -33,7 +34,7 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity; - import org.bukkit.entity.HumanEntity; - // CraftBukkit end - --public class TileEntityChest extends TileEntityLootable implements ITickable { -+public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITickable - - private NonNullList items; - protected float a; -@@ -111,14 +112,20 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - return nbttagcompound; - } - -- @Override - public void tick() { - int i = this.position.getX(); - int j = this.position.getY(); - int k = this.position.getZ(); - - ++this.j; -- this.viewingCount = a(this.world, this, this.j, i, j, k, this.viewingCount); -+ } -+ -+ public void doOpenLogic() { -+ int i = this.position.getX(); -+ int j = this.position.getY(); -+ int k = this.position.getZ(); -+ -+ //this.viewingCount = a(this.world, this, this.j, i, j, k, this.viewingCount); // Paper - check is faulty given our logic is called before active container set - this.b = this.a; - float f = 0.1F; - -@@ -132,8 +139,11 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - if (this.viewingCount > 0 && this.a == 0.0F) { - this.playOpenSound(SoundEffects.BLOCK_CHEST_OPEN); - } -+ } - -- if (this.viewingCount == 0 && this.a > 0.0F || this.viewingCount > 0 && this.a < 1.0F) { -+ public void doCloseLogic() { -+ if (this.viewingCount == 0 /* && this.a > 0.0F || this.viewingCount > 0 && this.a < 1.0F */) { // Paper - disable all but player count check -+ /* // Paper - disable animation stuff - float f1 = this.a; - - if (this.viewingCount > 0) { -@@ -149,8 +159,11 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - float f2 = 0.5F; - - if (this.a < 0.5F && f1 >= 0.5F) { -+ */ -+ MCUtil.scheduleTask(10, () -> { - this.playOpenSound(SoundEffects.BLOCK_CHEST_CLOSE); -- } -+ }, "Chest Sounds"); -+ //} // Paper end - - if (this.a < 0.0F) { - this.a = 0.0F; -@@ -189,6 +202,7 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - } - - public void playOpenSound(SoundEffect soundeffect) { -+ if (!this.getBlock().contains(BlockChest.CHEST_TYPE_PROPERTY)) { return; } // Paper - this can be delayed, double check exists - Fixes GH-2074 - BlockPropertyChestType blockpropertychesttype = (BlockPropertyChestType) this.getBlock().get(BlockChest.c); - - if (blockpropertychesttype != BlockPropertyChestType.LEFT) { -@@ -227,6 +241,7 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - - ++this.viewingCount; - if (this.world == null) return; // CraftBukkit -+ doOpenLogic(); // Paper - - // CraftBukkit start - Call redstone event - if (this.getBlock().getBlock() == Blocks.TRAPPED_CHEST) { -@@ -249,6 +264,7 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - --this.viewingCount; - - // CraftBukkit start - Call redstone event -+ doCloseLogic(); // Paper - if (this.getBlock().getBlock() == Blocks.TRAPPED_CHEST) { - int newPower = Math.max(0, Math.min(15, this.viewingCount)); - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -index 930f1bd091d9754f7ca5d9e36cdf49b2be03eb23..2bc4213c70be47ca8bbc24898cc92e43f4228821 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -@@ -1,11 +1,12 @@ - package net.minecraft.world.level.block.entity; - -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.block.Blocks; - --public class TileEntityEnderChest extends TileEntity implements ITickable { -+public class TileEntityEnderChest extends TileEntity { // Paper - Remove ITickable - - public float a; - public float b; -@@ -16,18 +17,28 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { - super(TileEntityTypes.ENDER_CHEST); - } - -- @Override - public void tick() { - if (++this.g % 20 * 4 == 0) { - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); - } - - this.b = this.a; -+ /* // Paper - int i = this.position.getX(); - int j = this.position.getY(); - int k = this.position.getZ(); - float f = 0.1F; - double d0; -+ // Paper start -+ */ -+ } -+ -+ private void doOpenLogic() { -+ int i = this.position.getX(); -+ int j = this.position.getY(); -+ int k = this.position.getZ(); -+ double d0; -+ // Paper end - - if (this.c > 0 && this.a == 0.0F) { - double d1 = (double) i + 0.5D; -@@ -35,8 +46,17 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { - d0 = (double) k + 0.5D; - this.world.playSound((EntityHuman) null, d1, (double) j + 0.5D, d0, SoundEffects.BLOCK_ENDER_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); - } -+ // Paper start -+ } - -- if (this.c == 0 && this.a > 0.0F || this.c > 0 && this.a < 1.0F) { -+ private void doCloseLogic() { -+ int i = this.position.getX(); -+ int j = this.position.getY(); -+ int k = this.position.getZ(); -+ double d0; -+ -+ if (this.c == 0) { /* && this.a > 0.0F || this.c > 0 && this.a < 1.0F) { -+ // Paper end - float f1 = this.a; - - if (this.c > 0) { -@@ -52,11 +72,14 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { - float f2 = 0.5F; - - if (this.a < 0.5F && f1 >= 0.5F) { -+ // Paper start -+ */ - d0 = (double) i + 0.5D; - double d2 = (double) k + 0.5D; - -+ MCUtil.scheduleTask(10, () -> { - this.world.playSound((EntityHuman) null, d0, (double) j + 0.5D, d2, SoundEffects.BLOCK_ENDER_CHEST_CLOSE, SoundCategory.BLOCKS, 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); -- } -+ }, "Chest Sounds"); - - if (this.a < 0.0F) { - this.a = 0.0F; -@@ -84,11 +107,13 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { - public void d() { - ++this.c; - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); -+ doOpenLogic(); // Paper - } - - public void f() { - --this.c; - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); -+ doCloseLogic(); // Paper - } - - public boolean a(EntityHuman entityhuman) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -index e4b59a85ee9b435b2e86d4c7d78b7224773f6967..ba046cffdd8331c7e0427f19fa54d0c7a99077d9 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -+++ b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -@@ -84,6 +84,7 @@ public abstract class IBlockDataHolder { - return Collections.unmodifiableCollection(this.b.keySet()); - } - -+ public > boolean contains(IBlockState iblockstate) { return this.b(iblockstate); } // Paper - OBFHELPER - public > boolean b(IBlockState iblockstate) { - return this.b.containsKey(iblockstate); - } diff --git a/Unmapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch b/Unmapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch deleted file mode 100644 index 4ac7537099..0000000000 --- a/Unmapped-Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch +++ /dev/null @@ -1,208 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 Mar 2016 23:09:29 -0600 -Subject: [PATCH] Further improve server tick loop - -Improves how the catchup buffer is handled, allowing it to roll both ways -increasing the effeciency of the thread sleep so it only will sleep once. - -Also increases the buffer of the catchup to ensure server stays at 20 TPS unless extreme conditions - -Previous implementation did not calculate TPS correctly. -Switch to a realistic rolling average and factor in std deviation as an extra reporting variable - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index c21790b4de698aa6f7fc4dadab64d791cd0562b6..fb0d985b5c977a7c63701484678b75928d9ee382 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -253,7 +253,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; - public CommandDispatcher vanillaCommandDispatcher; -@@ -262,7 +262,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 5000L && this.nextTick - this.lastOverloadTime >= 30000L) { // CraftBukkit - long j = i / 50L; - - if (server.getWarnOnOverload()) // CraftBukkit -- MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); -+ MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); - this.nextTick += j * 50L; - this.lastOverloadTime = this.nextTick; - } - -- if ( tickCount++ % SAMPLE_INTERVAL == 0 ) -+ if ( ++MinecraftServer.currentTick % SAMPLE_INTERVAL == 0 ) - { -- double currentTps = 1E3 / ( curTime - tickSection ) * SAMPLE_INTERVAL; -- recentTps[0] = calcTps( recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min) -- recentTps[1] = calcTps( recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min) -- recentTps[2] = calcTps( recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min) -+ final long diff = curTime - tickSection; -+ java.math.BigDecimal currentTps = TPS_BASE.divide(new java.math.BigDecimal(diff), 30, java.math.RoundingMode.HALF_UP); -+ tps1.add(currentTps, diff); -+ tps5.add(currentTps, diff); -+ tps15.add(currentTps, diff); -+ // Backwards compat with bad plugins -+ recentTps[0] = tps1.getAverage(); -+ recentTps[1] = tps5.getAverage(); -+ recentTps[2] = tps15.getAverage(); -+ // Paper end - tickSection = curTime; - } - // Spigot end - -- MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit -+ //MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit // Paper - don't overwrite current tick time -+ lastTick = curTime; - this.nextTick += 50L; - GameProfilerTick gameprofilertick = GameProfilerTick.a("Server"); - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 462633df2af43959fddf5b7a8ec43063abf7b14b..b4b592faaa699b6e62f77ddf57b239c5e15948ff 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2122,6 +2122,17 @@ public final class CraftServer implements Server { - return CraftMagicNumbers.INSTANCE; - } - -+ // Paper - Add getTPS API - Further improve tick loop -+ @Override -+ public double[] getTPS() { -+ return new double[] { -+ net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(), -+ net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(), -+ net.minecraft.server.MinecraftServer.getServer().tps15.getAverage() -+ }; -+ } -+ // Paper end -+ - // Spigot start - private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() - { -diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java -index f5b6dec1cbe7501ce2ee9125920e810bc94670cc..e62890433ffbe0b4e48942fe6c38b599a19e58fd 100644 ---- a/src/main/java/org/spigotmc/TicksPerSecondCommand.java -+++ b/src/main/java/org/spigotmc/TicksPerSecondCommand.java -@@ -24,22 +24,30 @@ public class TicksPerSecondCommand extends Command - return true; - } - -- StringBuilder sb = new StringBuilder( ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " ); -- for ( double tps : MinecraftServer.getServer().recentTps ) -- { -- sb.append( format( tps ) ); -- sb.append( ", " ); -+ // Paper start - Further improve tick handling -+ double[] tps = org.bukkit.Bukkit.getTPS(); -+ String[] tpsAvg = new String[tps.length]; -+ -+ for ( int i = 0; i < tps.length; i++) { -+ tpsAvg[i] = format( tps[i] ); -+ } -+ sender.sendMessage(ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " + org.apache.commons.lang.StringUtils.join(tpsAvg, ", ")); -+ if (args.length > 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) { -+ sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); -+ if (!hasShownMemoryWarning) { -+ sender.sendMessage(ChatColor.RED + "Warning: " + ChatColor.GOLD + " Memory usage on modern garbage collectors is not a stable value and it is perfectly normal to see it reach max. Please do not pay it much attention."); -+ hasShownMemoryWarning = true; -+ } - } -- sender.sendMessage( sb.substring( 0, sb.length() - 2 ) ); -- sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " -- + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); -+ // Paper end - - return true; - } - -- private String format(double tps) -+ private boolean hasShownMemoryWarning; // Paper -+ private static String format(double tps) // Paper - Made static - { - return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString() -- + ( ( tps > 20.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); -+ + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise - } - } diff --git a/Unmapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch b/Unmapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch deleted file mode 100644 index ae353e8f8a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 23:12:03 -0600 -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 cc471418b37a745ecea1af964e81bc0362cf7d94..fb792de46ff80a6bad77a47954861cddfd17f2d9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1439,12 +1439,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public void setFlying(boolean value) { -+ boolean needsUpdate = getHandle().abilities.isFlying != value; // Paper - Only refresh abilities if needed - if (!getAllowFlight() && value) { - throw new IllegalArgumentException("Cannot make player fly if getAllowFlight() is false"); - } - - getHandle().abilities.isFlying = value; -- getHandle().updateAbilities(); -+ if (needsUpdate) getHandle().updateAbilities(); // Paper - Only refresh abilities if needed - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch b/Unmapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch deleted file mode 100644 index bf9cbb5345..0000000000 --- a/Unmapped-Spigot-Server-Patches/0026-Entity-Origin-API.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Tue, 1 Mar 2016 23:45:08 -0600 -Subject: [PATCH] Entity Origin API - - -diff --git a/src/main/java/net/minecraft/nbt/NBTTagList.java b/src/main/java/net/minecraft/nbt/NBTTagList.java -index 4f6f6f51f9807bafa88482c0fe776c8b163107d7..ce6572df63c4e7341708aee60330fb214a3fe416 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagList.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagList.java -@@ -190,6 +190,7 @@ public class NBTTagList extends NBTList { - return new int[0]; - } - -+ public final double getDoubleAt(int i) { return this.h(i); } // Paper - OBFHELPER - public double h(int i) { - if (i >= 0 && i < this.list.size()) { - NBTBase nbtbase = (NBTBase) this.list.get(i); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index cf38d517821659e25e786a805e229ef2d626d75f..26d461196b4a998b445f8c6e67fd7ec0606344f6 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1246,6 +1246,11 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.navigators.add(((EntityInsentient) entity).getNavigation()); - } - entity.valid = true; // CraftBukkit -+ // Paper start - Set origin location when the entity is being added to the world -+ if (entity.origin == null) { -+ entity.origin = entity.getBukkitEntity().getLocation(); -+ } -+ // Paper end - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index cae9da158f54438d2a397665c7ce964f6f755469..f6f0d551e22ff085935c1543bf84392de0368214 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -247,6 +247,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only - public boolean forceExplosionKnockback; // SPIGOT-949 - public boolean persistentInvisibility = false; -+ public org.bukkit.Location origin; // Paper - // Spigot start - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; -@@ -1625,6 +1626,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.bukkitEntity.storeBukkitValues(nbttagcompound); - } - // CraftBukkit end -+ // Paper start - Save the entity's origin location -+ if (this.origin != null) { -+ nbttagcompound.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); -+ nbttagcompound.set("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); -+ } -+ // Paper end - return nbttagcompound; - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Saving entity NBT"); -@@ -1747,6 +1754,17 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - -+ // Paper start - Restore the entity's origin location -+ NBTTagList originTag = nbttagcompound.getList("Paper.Origin", 6); -+ if (!originTag.isEmpty()) { -+ org.bukkit.World originWorld = world.getWorld(); -+ if (nbttagcompound.hasKey("Paper.OriginWorld")) { -+ originWorld = Bukkit.getWorld(nbttagcompound.getUUID("Paper.OriginWorld")); -+ } -+ origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); -+ } -+ // Paper end -+ - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Loading entity NBT"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being loaded"); -@@ -1808,6 +1826,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - protected abstract void saveData(NBTTagCompound nbttagcompound); - -+ protected final NBTTagList createList(double... adouble) { return a(adouble); } // Paper - OBFHELPER - protected NBTTagList a(double... adouble) { - NBTTagList nbttaglist = new NBTTagList(); - double[] adouble1 = adouble; -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 901522f24b8bc58861e46eda400dbab92bb6401d..3f10e41b18e09186635fd6f7c653b04db7b39d8e 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -293,6 +293,14 @@ public class EntityFallingBlock extends Entity { - this.block = Blocks.SAND.getBlockData(); - } - -+ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility -+ if (nbttagcompound.hasKey("SourceLoc_x")) { -+ int srcX = nbttagcompound.getInt("SourceLoc_x"); -+ int srcY = nbttagcompound.getInt("SourceLoc_y"); -+ int srcZ = nbttagcompound.getInt("SourceLoc_z"); -+ origin = new org.bukkit.Location(world.getWorld(), srcX, srcY, srcZ); -+ } -+ // Paper end - } - - public void a(boolean flag) { -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -index 4f4b2b8d58223fa22d6a7af5c94cfb36399b9641..535e7d7297d81026b8586d5049b72fa65519b464 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -@@ -120,6 +120,14 @@ public class EntityTNTPrimed extends Entity { - @Override - protected void loadData(NBTTagCompound nbttagcompound) { - this.setFuseTicks(nbttagcompound.getShort("Fuse")); -+ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility -+ if (nbttagcompound.hasKey("SourceLoc_x")) { -+ int srcX = nbttagcompound.getInt("SourceLoc_x"); -+ int srcY = nbttagcompound.getInt("SourceLoc_y"); -+ int srcZ = nbttagcompound.getInt("SourceLoc_z"); -+ origin = new org.bukkit.Location(world.getWorld(), srcX, srcY, srcZ); -+ } -+ // Paper end - } - - @Nullable -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 3cf81734c8580f4d88ea97b6ac737a370b413c84..220bad90bbb9a90c3f23562bf0fb109fce379682 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1062,4 +1062,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return spigot; - } - // Spigot end -+ -+ // Paper start -+ @Override -+ public Location getOrigin() { -+ Location origin = getHandle().origin; -+ return origin == null ? null : origin.clone(); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch b/Unmapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch deleted file mode 100644 index 7abd9f5960..0000000000 --- a/Unmapped-Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 Mar 2016 23:52:34 -0600 -Subject: [PATCH] Prevent tile entity and entity crashes - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 62735e7908f86e31f7a89ce2071ddebe176c0385..87e37c38825ad20fc11f41ea2a4512753266d2b4 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -737,11 +737,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - gameprofilerfiller.exit(); - } catch (Throwable throwable) { -- CrashReport crashreport = CrashReport.a(throwable, "Ticking block entity"); -- CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block entity being ticked"); -- -- tileentity.a(crashreportsystemdetails); -- throw new ReportedException(crashreport); -+ // Paper start - Prevent tile entity and entity crashes -+ System.err.println("TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ()); -+ throwable.printStackTrace(); -+ tilesThisCycle--; -+ this.tileEntityListTick.remove(tileTickPosition--); -+ continue; -+ // Paper end - // Spigot start - } finally { - tileentity.tickTimer.stopTiming(); -@@ -806,11 +808,12 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - try { - consumer.accept(entity); - } catch (Throwable throwable) { -- CrashReport crashreport = CrashReport.a(throwable, "Ticking entity"); -- CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being ticked"); -- -- entity.appendEntityCrashDetails(crashreportsystemdetails); -- throw new ReportedException(crashreport); -+ // Paper start - Prevent tile entity and entity crashes -+ System.err.println("Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ()); -+ throwable.printStackTrace(); -+ entity.dead = true; -+ return; -+ // Paper end - } - } - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 9ebd91e1309938f81583eb3d4dd97fd39bcc930a..58789a6e285c31947508deae37caefe7e182278c 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -208,7 +208,12 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - return IRegistry.BLOCK_ENTITY_TYPE.getKey(this.getTileType()) + " // " + this.getClass().getCanonicalName(); - }); - if (this.world != null) { -- CrashReportSystemDetails.a(crashreportsystemdetails, this.position, this.getBlock()); -+ // Paper start - Prevent TileEntity and Entity crashes -+ IBlockData block = this.getBlock(); -+ if (block != null) { -+ CrashReportSystemDetails.a(crashreportsystemdetails, this.position, block); -+ } -+ // Paper end - CrashReportSystemDetails.a(crashreportsystemdetails, this.position, this.world.getType(this.position)); - } - } diff --git a/Unmapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch b/Unmapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch deleted file mode 100644 index a06ff56c4c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 23:58:50 -0600 -Subject: [PATCH] Configurable top of nether void damage - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index d16ae924bcbe31c964f7fb448757c748e5c4418c..4bba6977a0287837b8927718c040ac61463f0469 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -134,4 +134,19 @@ public class PaperWorldConfig { - if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); - if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); - } -+ -+ public int netherVoidTopDamageHeight; -+ public boolean doNetherTopVoidDamage() { return netherVoidTopDamageHeight > 0; } -+ private void netherVoidTopDamageHeight() { -+ netherVoidTopDamageHeight = getInt("nether-ceiling-void-damage-height", 0); -+ log("Top of the nether void damage height: " + netherVoidTopDamageHeight); -+ -+ if (PaperConfig.version < 18) { -+ boolean legacy = getBoolean("nether-ceiling-void-damage", false); -+ if (legacy) { -+ netherVoidTopDamageHeight = 128; -+ set("nether-ceiling-void-damage-height", netherVoidTopDamageHeight); -+ } -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f6f0d551e22ff085935c1543bf84392de0368214..df2582c3b00977d799b189214d7d4f30ded5b66d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -500,9 +500,16 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.fallDistance *= 0.5F; - } - -+ // Paper start - Configurable nether ceiling damage -+ -+ // Extracted to own function -+ /* - if (this.locY() < -64.0D) { - this.an(); - } -+ */ -+ this.performVoidDamage(); -+ // Paper end - - if (!this.world.isClientSide) { - this.setFlag(0, this.fireTicks > 0); -@@ -595,6 +602,17 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.setFireTicks(0); - } - -+ // Paper start -+ protected void performVoidDamage() { -+ if (this.locY() < -64.0D || (this.world.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER -+ && world.paperConfig.doNetherTopVoidDamage() -+ && this.locY() >= world.paperConfig.netherVoidTopDamageHeight)) { -+ this.doVoidDamage(); -+ } -+ } -+ // Paper end -+ -+ protected final void doVoidDamage() { this.an(); } // Paper - OBFHELPER - protected void an() { - this.die(); - } -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 37785b27c3d9ffd010f09f53b2ca09941f609872..1f94cc096d95129d85a6278b1e369729df93d27d 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -330,9 +330,15 @@ public abstract class EntityMinecartAbstract extends Entity { - this.setDamage(this.getDamage() - 1.0F); - } - -+ // Paper start - Configurable nether ceiling damage -+ // Extracted to own function -+ /* - if (this.locY() < -64.0D) { - this.an(); - } -+ */ -+ this.performVoidDamage(); -+ // Paper end - - // this.doPortalTick(); // CraftBukkit - handled in postTick - if (this.world.isClientSide) { diff --git a/Unmapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch b/Unmapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch deleted file mode 100644 index 386f7f1615..0000000000 --- a/Unmapped-Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Mar 2016 00:03:55 -0600 -Subject: [PATCH] Check online mode before converting and renaming player data - - -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -index c3a1b5943b0dad8701d566c45b9b474dac7e5c8a..191c9e9a00b9871038f60d54bc22620322f6bdbd 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -@@ -56,7 +56,7 @@ public class WorldNBTStorage { - File file = new File(this.playerDir, entityhuman.getUniqueIDString() + ".dat"); - // Spigot Start - boolean usingWrongFile = false; -- if ( !file.exists() ) -+ if ( org.bukkit.Bukkit.getOnlineMode() && !file.exists() ) // Paper - Check online mode first - { - file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + entityhuman.getName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); - if ( file.exists() ) diff --git a/Unmapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch b/Unmapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch deleted file mode 100644 index 4352384dba..0000000000 --- a/Unmapped-Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Mar 2016 00:32:25 -0600 -Subject: [PATCH] Always tick falling blocks - - -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 69c5d4e51ebf747d931fadc819973e36f001f5bc..58d22363124a9343188d8c19476e5a92f2f0b80b 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -91,6 +91,7 @@ public class ActivationRange - || entity instanceof EntityFireball - || entity instanceof EntityLightning - || entity instanceof EntityTNTPrimed -+ || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks - || entity instanceof EntityEnderCrystal - || entity instanceof EntityFireworks - || entity instanceof EntityThrownTrident ) diff --git a/Unmapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch b/Unmapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch deleted file mode 100644 index 202de91202..0000000000 --- a/Unmapped-Spigot-Server-Patches/0031-Configurable-end-credits.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DoctorDark -Date: Wed, 16 Mar 2016 02:21:39 -0500 -Subject: [PATCH] Configurable end credits - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4bba6977a0287837b8927718c040ac61463f0469..e6e18f309dc09ea9416ea37dcc697ddc2b571a96 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -149,4 +149,10 @@ public class PaperWorldConfig { - } - } - } -+ -+ public boolean disableEndCredits; -+ private void disableEndCredits() { -+ disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); -+ log("End credits disabled: " + disableEndCredits); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 5ef8b66cf266488df75ce7399596f75273b90761..808bb68b3c5115b1219a65d0dd253bd60d543652 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -191,7 +191,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - private long ca = SystemUtils.getMonotonicMillis(); - private Entity spectatedEntity; - public boolean worldChangeInvuln; -- private boolean cd; -+ private boolean cd; private void setHasSeenCredits(boolean has) { this.cd = has; } // Paper - OBFHELPER - private final RecipeBookServer recipeBook = new RecipeBookServer(); - private Vec3D cf; - private int cg; -@@ -896,6 +896,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.decouple(); - this.getWorldServer().removePlayer(this); - if (!this.viewingCredits) { -+ if (world.paperConfig.disableEndCredits) this.setHasSeenCredits(true); // Paper - Toggle to always disable end credits - this.viewingCredits = true; - this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.e, this.cd ? 0.0F : 1.0F)); - this.cd = true; diff --git a/Unmapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch b/Unmapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch deleted file mode 100644 index 85ee818286..0000000000 --- a/Unmapped-Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Iceee -Date: Wed, 2 Mar 2016 01:39:52 -0600 -Subject: [PATCH] Fix lag from explosions processing dead entities - - -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 9c1ad56e4362cd86e7ffe2aef7fd9ec301cf9002..7786a06ba09aacaa70c346e85a9eeed9f2ffec6e 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -182,7 +182,7 @@ public class Explosion { - int i1 = MathHelper.floor(this.posY + (double) f2 + 1.0D); - int j1 = MathHelper.floor(this.posZ - (double) f2 - 1.0D); - int k1 = MathHelper.floor(this.posZ + (double) f2 + 1.0D); -- List list = this.world.getEntities(this.source, new AxisAlignedBB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1)); -+ List list = this.world.getEntities(this.source, new AxisAlignedBB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1), (com.google.common.base.Predicate) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities - Vec3D vec3d = new Vec3D(this.posX, this.posY, this.posZ); - - for (int l1 = 0; l1 < list.size(); ++l1) { diff --git a/Unmapped-Spigot-Server-Patches/0033-Optimize-explosions.patch b/Unmapped-Spigot-Server-Patches/0033-Optimize-explosions.patch deleted file mode 100644 index d539442720..0000000000 --- a/Unmapped-Spigot-Server-Patches/0033-Optimize-explosions.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 11:59:48 -0600 -Subject: [PATCH] Optimize explosions - -The process of determining an entity's exposure from explosions can be -expensive when there are hundreds or more entities in range. - -This patch adds a per-tick cache that is used for storing and retrieving -an entity's exposure during an explosion. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e6e18f309dc09ea9416ea37dcc697ddc2b571a96..4881b03d470646843bad1bc343eb6a6ab9072d8e 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -155,4 +155,10 @@ public class PaperWorldConfig { - disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); - log("End credits disabled: " + disableEndCredits); - } -+ -+ public boolean optimizeExplosions; -+ private void optimizeExplosions() { -+ optimizeExplosions = getBoolean("optimize-explosions", false); -+ log("Optimize explosions: " + optimizeExplosions); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index fb0d985b5c977a7c63701484678b75928d9ee382..ed71de473d461528d74ca5b95c33b97e98128aff 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1326,6 +1326,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant>> 32)); -+ temp = Double.doubleToLongBits(posY); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(posZ); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(minX); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(minY); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(minZ); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(maxX); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(maxY); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(maxZ); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ return result; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 87e37c38825ad20fc11f41ea2a4512753266d2b4..06455fb3916e347c075c6aa84977dca7e25760c2 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -136,6 +136,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; - private int tileTickPosition; -+ public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions - - public CraftWorld getWorld() { - return this.world; diff --git a/Unmapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch b/Unmapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch deleted file mode 100644 index 1e714c3621..0000000000 --- a/Unmapped-Spigot-Server-Patches/0034-Disable-explosion-knockback.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 14:48:03 -0600 -Subject: [PATCH] Disable explosion knockback - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4881b03d470646843bad1bc343eb6a6ab9072d8e..2222c1bb5f8625eee4d88946e4bfdfa2fe598977 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -161,4 +161,9 @@ public class PaperWorldConfig { - optimizeExplosions = getBoolean("optimize-explosions", false); - log("Optimize explosions: " + optimizeExplosions); - } -+ -+ public boolean disableExplosionKnockback; -+ private void disableExplosionKnockback(){ -+ disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index e771d84c972cea4ca1b4b5d25cd573cfcbce4579..49e95369882847c90ee7417abea6270386cd622f 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -1283,6 +1283,7 @@ public abstract class EntityLiving extends Entity { - } - } - -+ boolean knockbackCancelled = world.paperConfig.disableExplosionKnockback && damagesource.isExplosion() && this instanceof EntityHuman; // Paper - Disable explosion knockback - if (flag1) { - if (flag) { - this.world.broadcastEntityEffect(this, (byte) 29); -@@ -1301,6 +1302,7 @@ public abstract class EntityLiving extends Entity { - b0 = 2; - } - -+ if (!knockbackCancelled) // Paper - Disable explosion knockback - this.world.broadcastEntityEffect(this, b0); - } - -@@ -1324,6 +1326,7 @@ public abstract class EntityLiving extends Entity { - } - } - -+ if (knockbackCancelled) this.world.broadcastEntityEffect(this, (byte) 2); // Paper - Disable explosion knockback - if (this.dl()) { - if (!this.f(damagesource)) { - SoundEffect soundeffect = this.getSoundDeath(); -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 6a7af2c0c3c294b10c6ddbf98babb0f30d7d5f56..618cf4e0d71b4b04085807314e79a02785f8a498 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -217,14 +217,14 @@ public class Explosion { - double d14 = d13; - - if (entity instanceof EntityLiving) { -- d14 = EnchantmentProtection.a((EntityLiving) entity, d13); -+ d14 = entity instanceof EntityHuman && world.paperConfig.disableExplosionKnockback ? 0 : EnchantmentProtection.a((EntityLiving) entity, d13); // Paper - Disable explosion knockback - } - - entity.setMot(entity.getMot().add(d8 * d14, d9 * d14, d10 * d14)); - if (entity instanceof EntityHuman) { - EntityHuman entityhuman = (EntityHuman) entity; - -- if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.isFlying)) { -+ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.isFlying) && !world.paperConfig.disableExplosionKnockback) { // Paper - Disable explosion knockback - this.n.put(entityhuman, new Vec3D(d8 * d13, d9 * d13, d10 * d13)); - } - } diff --git a/Unmapped-Spigot-Server-Patches/0035-Disable-thunder.patch b/Unmapped-Spigot-Server-Patches/0035-Disable-thunder.patch deleted file mode 100644 index 9c0e1d9856..0000000000 --- a/Unmapped-Spigot-Server-Patches/0035-Disable-thunder.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 14:52:43 -0600 -Subject: [PATCH] Disable thunder - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2222c1bb5f8625eee4d88946e4bfdfa2fe598977..083e421f8496b5336af473b108498ed28b984774 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -166,4 +166,9 @@ public class PaperWorldConfig { - private void disableExplosionKnockback(){ - disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); - } -+ -+ public boolean disableThunder; -+ private void disableThunder() { -+ disableThunder = getBoolean("disable-thunder", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 26d461196b4a998b445f8c6e67fd7ec0606344f6..8845b5c6dc9ebff30e8aa3abd3c905addaeb3e1d 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -586,7 +586,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - gameprofilerfiller.enter("thunder"); - BlockPosition blockposition; - -- if (flag && this.W() && this.random.nextInt(100000) == 0) { -+ if (!this.paperConfig.disableThunder && flag && this.W() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder - blockposition = this.a(this.a(j, 0, k, 15)); - if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); diff --git a/Unmapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch b/Unmapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch deleted file mode 100644 index 0ce64ee502..0000000000 --- a/Unmapped-Spigot-Server-Patches/0036-Disable-ice-and-snow.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 14:57:24 -0600 -Subject: [PATCH] Disable ice and snow - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 083e421f8496b5336af473b108498ed28b984774..2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -171,4 +171,9 @@ public class PaperWorldConfig { - private void disableThunder() { - disableThunder = getBoolean("disable-thunder", false); - } -+ -+ public boolean disableIceAndSnow; -+ private void disableIceAndSnow(){ -+ disableIceAndSnow = getBoolean("disable-ice-and-snow", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 8845b5c6dc9ebff30e8aa3abd3c905addaeb3e1d..a1769df6a3f6150d322f145199caba3839871dff 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -610,7 +610,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - gameprofilerfiller.exitEnter("iceandsnow"); -- if (this.random.nextInt(16) == 0) { -+ if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow - blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, this.a(j, 0, k, 15)); - BlockPosition blockposition1 = blockposition.down(); - BiomeBase biomebase = this.getBiome(blockposition); diff --git a/Unmapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch b/Unmapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch deleted file mode 100644 index 0ced9bb837..0000000000 --- a/Unmapped-Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 15:03:53 -0600 -Subject: [PATCH] Configurable mob spawner tick rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2..4de86b09c6bc3c1974ce61b550ccb73d37f6f170 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -176,4 +176,9 @@ public class PaperWorldConfig { - private void disableIceAndSnow(){ - disableIceAndSnow = getBoolean("disable-ice-and-snow", false); - } -+ -+ public int mobSpawnerTickRate; -+ private void mobSpawnerTickRate() { -+ mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 8d8b03074df1635946f81bec0feae18d2f3e20aa..76c98d576d3e567ec4482b30219f5a9107cb9703 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -41,6 +41,7 @@ public abstract class MobSpawnerAbstract { - public int maxNearbyEntities = 6; - public int requiredPlayerRange = 16; - public int spawnRange = 4; -+ private int tickDelay = 0; // Paper - - public MobSpawnerAbstract() {} - -@@ -70,6 +71,10 @@ public abstract class MobSpawnerAbstract { - } - - public void c() { -+ // Paper start - Configurable mob spawner tick rate -+ if (spawnDelay > 0 && --tickDelay > 0) return; -+ tickDelay = this.a().paperConfig.mobSpawnerTickRate; -+ // Paper end - if (!this.h()) { - this.f = this.e; - } else { -@@ -84,18 +89,18 @@ public abstract class MobSpawnerAbstract { - world.addParticle(Particles.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); - world.addParticle(Particles.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D); - if (this.spawnDelay > 0) { -- --this.spawnDelay; -+ this.spawnDelay -= tickDelay; // Paper - } - - this.f = this.e; - this.e = (this.e + (double) (1000.0F / ((float) this.spawnDelay + 200.0F))) % 360.0D; - } else { -- if (this.spawnDelay == -1) { -+ if (this.spawnDelay < -tickDelay) { // Paper - this.i(); - } - - if (this.spawnDelay > 0) { -- --this.spawnDelay; -+ this.spawnDelay -= tickDelay; // Paper - return; - } - diff --git a/Unmapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch b/Unmapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch deleted file mode 100644 index c6d0215417..0000000000 --- a/Unmapped-Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Wed, 2 Mar 2016 23:13:07 -0600 -Subject: [PATCH] Send absolute position the first time an entity is seen - - -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index 9ad74b380a92e3a563e1a891e81401d8b4707bcf..beb0beb716869978be6bc5a78ce3b6cf785c5aee 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -4,6 +4,7 @@ import com.google.common.collect.Lists; - import com.mojang.datafixers.util.Pair; - import java.util.Collection; - import java.util.Collections; -+import java.util.HashSet; - import java.util.Iterator; - import java.util.List; - import java.util.Set; -@@ -52,7 +53,7 @@ public class EntityTrackerEntry { - private final Entity tracker; - private final int d; - private final boolean e; -- private final Consumer> f; -+ private final Consumer> f; private Consumer> getPacketConsumer() { return f; } // Paper - OBFHELPER - private long xLoc; - private long yLoc; - private long zLoc; -@@ -67,8 +68,23 @@ public class EntityTrackerEntry { - private boolean r; - // CraftBukkit start - private final Set trackedPlayers; -+ // Paper start -+ private java.util.Map trackedPlayerMap = null; -+ -+ /** -+ * Requested in https://github.com/PaperMC/Paper/issues/1537 to allow intercepting packets -+ */ -+ public void sendPlayerPacket(EntityPlayer player, Packet packet) { -+ player.playerConnection.sendPacket(packet); -+ } -+ -+ public EntityTrackerEntry(WorldServer worldserver, Entity entity, int i, boolean flag, Consumer> consumer, java.util.Map trackedPlayers) { -+ this(worldserver, entity, i, flag, consumer, trackedPlayers.keySet()); -+ trackedPlayerMap = trackedPlayers; -+ } - - public EntityTrackerEntry(WorldServer worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { -+ // Paper end - this.trackedPlayers = trackedPlayers; - // CraftBukkit end - this.m = Vec3D.ORIGIN; -@@ -189,7 +205,25 @@ public class EntityTrackerEntry { - } - - if (packet1 != null) { -- this.f.accept(packet1); -+ // paper start -+ if (trackedPlayerMap == null || packet1 instanceof PacketPlayOutEntityTeleport) { -+ this.f.accept((packet1)); -+ } else { -+ PacketPlayOutEntityTeleport teleportPacket = null; -+ -+ for (java.util.Map.Entry viewer : trackedPlayerMap.entrySet()) { -+ if (viewer.getValue()) { -+ viewer.setValue(false); -+ if (teleportPacket == null) { -+ teleportPacket = new PacketPlayOutEntityTeleport(this.tracker); -+ } -+ sendPlayerPacket(viewer.getKey(), teleportPacket); -+ } else { -+ sendPlayerPacket(viewer.getKey(), packet1); -+ } -+ } -+ } -+ // Paper end - } - - this.c(); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 62245fa420390dc0a70ba9a95505dc46cd8aa64a..788a45d5426f0752509442aec2d28b1f32f63cb1 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1303,10 +1303,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final Entity tracker; - private final int trackingDistance; - private SectionPosition e; -- public final Set trackedPlayers = Sets.newHashSet(); -+ // Paper start -+ // Replace trackedPlayers Set with a Map. The value is true until the player receives -+ // their first update (which is forced to have absolute coordinates), false afterward. -+ public java.util.Map trackedPlayerMap = new java.util.HashMap<>(); -+ public Set trackedPlayers = trackedPlayerMap.keySet(); - - public EntityTracker(Entity entity, int i, int j, boolean flag) { -- this.trackerEntry = new EntityTrackerEntry(PlayerChunkMap.this.world, entity, j, flag, this::broadcast, trackedPlayers); // CraftBukkit -+ this.trackerEntry = new EntityTrackerEntry(PlayerChunkMap.this.world, entity, j, flag, this::broadcast, trackedPlayerMap); // CraftBukkit // Paper - this.tracker = entity; - this.trackingDistance = i; - this.e = SectionPosition.a(entity); -@@ -1388,7 +1392,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - entityplayer.removeQueue.remove(Integer.valueOf(this.tracker.getId())); - // CraftBukkit end - -- if (flag1 && this.trackedPlayers.add(entityplayer)) { -+ if (flag1 && this.trackedPlayerMap.putIfAbsent(entityplayer, true) == null) { // Paper - this.trackerEntry.b(entityplayer); - } - } else if (this.trackedPlayers.remove(entityplayer)) { diff --git a/Unmapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch b/Unmapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch deleted file mode 100644 index 9ca515c4b7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 23:30:53 -0600 -Subject: [PATCH] Add BeaconEffectEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -index c6914c8d2a3d1057c98537a3538097d3ac6149e0..4098357d60165a4c670a7bc5134abf66178124c6 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -@@ -42,6 +42,11 @@ import net.minecraft.world.phys.AxisAlignedBB; - import org.bukkit.craftbukkit.potion.CraftPotionUtil; - import org.bukkit.potion.PotionEffect; - // CraftBukkit end -+// Paper start -+import org.bukkit.craftbukkit.event.CraftEventFactory; -+import org.bukkit.entity.Player; -+import com.destroystokyo.paper.event.block.BeaconEffectEvent; -+// Paper end - - public class TileEntityBeacon extends TileEntity implements ITileInventory, ITickable { - -@@ -268,14 +273,30 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - } - - private void applyEffect(List list, MobEffectList effects, int i, int b0) { -+ // Paper - BeaconEffectEvent -+ applyEffect(list, effects, i, b0, true); -+ } -+ -+ private void applyEffect(List list, MobEffectList effects, int i, int b0, boolean isPrimary) { -+ // Paper - BeaconEffectEvent - { - Iterator iterator = list.iterator(); - - EntityHuman entityhuman; - -+ // Paper start - BeaconEffectEvent -+ org.bukkit.block.Block block = world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); -+ PotionEffect effect = CraftPotionUtil.toBukkit(new MobEffect(effects, i, b0, true, true)); -+ // Paper end -+ - while (iterator.hasNext()) { - entityhuman = (EntityHuman) iterator.next(); -- entityhuman.addEffect(new MobEffect(effects, i, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); -+ -+ // Paper start - BeaconEffectEvent -+ BeaconEffectEvent event = new BeaconEffectEvent(block, effect, (Player) entityhuman.getBukkitEntity(), isPrimary); -+ if (CraftEventFactory.callEvent(event).isCancelled()) continue; -+ entityhuman.addEffect(new MobEffect(CraftPotionUtil.fromBukkit(event.getEffect())), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); -+ // Paper end - } - } - } -@@ -298,10 +319,10 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - int i = getLevel(); - List list = getHumansInRange(); - -- applyEffect(list, this.primaryEffect, i, b0); -+ applyEffect(list, this.primaryEffect, i, b0, true); // Paper - BeaconEffectEvent - - if (hasSecondaryEffect()) { -- applyEffect(list, this.secondaryEffect, i, 0); -+ applyEffect(list, this.secondaryEffect, i, 0, false); // Paper - BeaconEffectEvent - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch b/Unmapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch deleted file mode 100644 index 75bd09e685..0000000000 --- a/Unmapped-Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 23:34:44 -0600 -Subject: [PATCH] Configurable container update tick rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4de86b09c6bc3c1974ce61b550ccb73d37f6f170..5a4c3a8c511f22c8c3240c9c7cd83a65119c1054 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -181,4 +181,9 @@ public class PaperWorldConfig { - private void mobSpawnerTickRate() { - mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); - } -+ -+ public int containerUpdateTickRate; -+ private void containerUpdateTickRate() { -+ containerUpdateTickRate = getInt("container-update-tick-rate", 1); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 808bb68b3c5115b1219a65d0dd253bd60d543652..cda0e7f8f9a9d66ac4e5a3f52609a4271bf0c4b5 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -210,6 +210,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean e; - public int ping; - public boolean viewingCredits; -+ private int containerUpdateDelay; // Paper - - // CraftBukkit start - public String displayName; -@@ -534,7 +535,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - --this.noDamageTicks; - } - -- this.activeContainer.c(); -+ // Paper start - Configurable container update tick rate -+ if (--containerUpdateDelay <= 0) { -+ this.activeContainer.c(); -+ containerUpdateDelay = world.paperConfig.containerUpdateTickRate; -+ } -+ // Paper end - if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { - this.closeInventory(); - this.activeContainer = this.defaultContainer; diff --git a/Unmapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch b/Unmapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch deleted file mode 100644 index 1def3bad81..0000000000 --- a/Unmapped-Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Wed, 2 Mar 2016 23:42:37 -0600 -Subject: [PATCH] Use UserCache for player heads - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index b8cac55c9fdcebe7703f179d25ad8cfb15c78a0e..dff67a48961399f3746f99b4f2363724bfe51c36 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -@@ -166,7 +166,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - if (name == null) { - setProfile(null); - } else { -- setProfile(new GameProfile(null, name)); -+ // Paper start - Use Online Players Skull -+ GameProfile newProfile = null; -+ net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayer(name); -+ if (player != null) newProfile = player.getProfile(); -+ if (newProfile == null) newProfile = new GameProfile(null, name); -+ setProfile(newProfile); -+ // Paper end - } - - return true; diff --git a/Unmapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch b/Unmapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch deleted file mode 100644 index 54851e5ccf..0000000000 --- a/Unmapped-Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Mar 2016 23:45:17 -0600 -Subject: [PATCH] Disable spigot tick limiters - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 06455fb3916e347c075c6aa84977dca7e25760c2..26d9388badb0328735abf0319a42bd633c90dc4b 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -707,9 +707,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // Spigot start - // Iterator iterator = this.tileEntityListTick.iterator(); - int tilesThisCycle = 0; -- for (tileLimiter.initTick(); -- tilesThisCycle < tileEntityListTick.size() && (tilesThisCycle % 10 != 0 || tileLimiter.shouldContinue()); -- tileTickPosition++, tilesThisCycle++) { -+ for (tileTickPosition = 0; tileTickPosition < tileEntityListTick.size(); tileTickPosition++) { // Paper - Disable tick limiters - tileTickPosition = (tileTickPosition < tileEntityListTick.size()) ? tileTickPosition : 0; - TileEntity tileentity = (TileEntity) this.tileEntityListTick.get(tileTickPosition); - // Spigot start diff --git a/Unmapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch b/Unmapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch deleted file mode 100644 index f3fdc63315..0000000000 --- a/Unmapped-Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Steve Anton -Date: Thu, 3 Mar 2016 00:09:38 -0600 -Subject: [PATCH] Add PlayerInitialSpawnEvent - -For modifying a player's initial spawn location as they join the server - -This is a duplicate API from spigot, so use our duplicate subclass and -improve setPosition to use raw - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 6ebd4ec781aa215c2b941261250c15c87c223cab..46c516b9ff089a3c885d635244942fd5a6ecf132 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -213,7 +213,7 @@ public abstract class PlayerList { - - // Spigot start - spawn location event - Player bukkitPlayer = entityplayer.getBukkitEntity(); -- org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(bukkitPlayer, bukkitPlayer.getLocation()); -+ org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(bukkitPlayer, bukkitPlayer.getLocation()); // Paper use our duplicate event - cserver.getPluginManager().callEvent(ev); - - Location loc = ev.getSpawnLocation(); -@@ -221,7 +221,10 @@ public abstract class PlayerList { - - entityplayer.spawnIn(worldserver1); - entityplayer.playerInteractManager.a((WorldServer) entityplayer.world); -- entityplayer.setLocation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); -+ // Paper start - set raw so we aren't fully joined to the world (not added to chunk or world) -+ entityplayer.setPositionRaw(loc.getX(), loc.getY(), loc.getZ()); -+ entityplayer.setYawPitch(loc.getYaw(), loc.getPitch()); -+ // Paper end - // Spigot end - - // CraftBukkit - Moved message to after join -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index df2582c3b00977d799b189214d7d4f30ded5b66d..77cc0aeb979369df2156f8fb916067f608b61ebf 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -398,7 +398,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return d1 * d1 + d2 * d2 + d3 * d3 < d0 * d0; - } - -- protected void setYawPitch(float f, float f1) { -+ public void setYawPitch(float f, float f1) { // Paper - protected -> public - // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 - if (Float.isNaN(f)) { - f = 0; diff --git a/Unmapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch b/Unmapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch deleted file mode 100644 index 9c34c4ef30..0000000000 --- a/Unmapped-Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 01:13:45 -0600 -Subject: [PATCH] Configurable Disabling Cat Chest Detection - -Offers a gameplay feature to stop cats from blocking chests - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5a4c3a8c511f22c8c3240c9c7cd83a65119c1054..70e074cdf2087e638af8e0f3878d0ef8eb7305cc 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -186,4 +186,9 @@ public class PaperWorldConfig { - private void containerUpdateTickRate() { - containerUpdateTickRate = getInt("container-update-tick-rate", 1); - } -+ -+ public boolean disableChestCatDetection; -+ private void disableChestCatDetection() { -+ disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java -index b229faad99120c67b089f7680d800fbe594fe7da..b2c29cff5883868cb56a4e376ab946ac929abc94 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockChest.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java -@@ -312,6 +312,11 @@ public class BlockChest extends BlockChestAbstract implements I - } - - private static boolean b(GeneratorAccess generatoraccess, BlockPosition blockposition) { -+ // Paper start - Option to disable chest cat detection -+ if (((World) generatoraccess).paperConfig.disableChestCatDetection) { -+ return false; -+ } -+ // Paper end - List list = generatoraccess.a(EntityCat.class, new AxisAlignedBB((double) blockposition.getX(), (double) (blockposition.getY() + 1), (double) blockposition.getZ(), (double) (blockposition.getX() + 1), (double) (blockposition.getY() + 2), (double) (blockposition.getZ() + 1))); - - if (!list.isEmpty()) { diff --git a/Unmapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch b/Unmapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch deleted file mode 100644 index f0a462da4a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 01:17:12 -0600 -Subject: [PATCH] Ensure commands are not ran async - -Plugins calling Player.chat("/foo") or Server.dispatchCommand() could -trigger the server to execute a command while on another thread. - -These commands would then process EXPECTING to be on the main thread, leaving to -very hard to trace concurrency issues. - -This change will synchronize the command execution back to the main thread, causing a -big slowdown in execution but throwing an exception at same time to raise awareness -that it is happening so that plugin authors can fix their code to stop executing commands async. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 5db09e60c2ac1f4cb0da3190e57896ccae7c58a3..865d8efa2d480ae7edc286e3e79f2997a191ee5c 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1854,6 +1854,29 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - if (!async && s.startsWith("/")) { -+ // Paper Start -+ if (!org.spigotmc.AsyncCatcher.shuttingDown && !org.bukkit.Bukkit.isPrimaryThread()) { -+ final String fCommandLine = s; -+ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Command Dispatched Async: " + fCommandLine); -+ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); -+ Waitable wait = new Waitable() { -+ @Override -+ protected Object evaluate() { -+ chat(fCommandLine, false); -+ return null; -+ } -+ }; -+ minecraftServer.processQueue.add(wait); -+ try { -+ wait.get(); -+ return; -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! -+ } catch (Exception e) { -+ throw new RuntimeException("Exception processing chat command", e.getCause()); -+ } -+ } -+ // Paper End - this.handleCommand(s); - } else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) { - // Do nothing, this is coming from a plugin -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index b4b592faaa699b6e62f77ddf57b239c5e15948ff..b7de5049dfd6807de1c84a9454b9097141399660 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -760,6 +760,29 @@ public final class CraftServer implements Server { - Validate.notNull(commandLine, "CommandLine cannot be null"); - org.spigotmc.AsyncCatcher.catchOp("command dispatch"); // Spigot - -+ // Paper Start -+ if (!org.spigotmc.AsyncCatcher.shuttingDown && !Bukkit.isPrimaryThread()) { -+ final CommandSender fSender = sender; -+ final String fCommandLine = commandLine; -+ Bukkit.getLogger().log(Level.SEVERE, "Command Dispatched Async: " + commandLine); -+ Bukkit.getLogger().log(Level.SEVERE, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); -+ org.bukkit.craftbukkit.util.Waitable wait = new org.bukkit.craftbukkit.util.Waitable() { -+ @Override -+ protected Boolean evaluate() { -+ return dispatchCommand(fSender, fCommandLine); -+ } -+ }; -+ net.minecraft.server.MinecraftServer.getServer().processQueue.add(wait); -+ try { -+ return wait.get(); -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! -+ } catch (Exception e) { -+ throw new RuntimeException("Exception processing dispatch command", e.getCause()); -+ } -+ } -+ // Paper End -+ - if (commandMap.dispatch(sender, commandLine)) { - return true; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index ddef523ea8762c927f37f7d16d581e43367e8c6b..70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -13,6 +13,7 @@ public class ServerShutdownThread extends Thread { - public void run() { - try { - org.spigotmc.AsyncCatcher.enabled = false; // Spigot -+ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper - server.close(); - } finally { - try { -diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java -index aeed7697254af17ffefe8e578353ad216e15f9f3..9f7d2ef932ab41cef5d3d0736d20a7c7e4a2c888 100644 ---- a/src/main/java/org/spigotmc/AsyncCatcher.java -+++ b/src/main/java/org/spigotmc/AsyncCatcher.java -@@ -6,6 +6,7 @@ public class AsyncCatcher - { - - public static boolean enabled = true; -+ public static boolean shuttingDown = false; // Paper - - public static void catchOp(String reason) - { -diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index d76e01d73da7413f192132134caf201d7780e3f1..a45155cdd7d7a302c119f75bfe2b428ae5e8ab47 100644 ---- a/src/main/java/org/spigotmc/RestartCommand.java -+++ b/src/main/java/org/spigotmc/RestartCommand.java -@@ -43,6 +43,7 @@ public class RestartCommand extends Command - private static void restart(final String restartScript) - { - AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us -+ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper - try - { - String[] split = restartScript.split( " " ); diff --git a/Unmapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch b/Unmapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch deleted file mode 100644 index 48622f89ba..0000000000 --- a/Unmapped-Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: vemacs -Date: Thu, 3 Mar 2016 01:19:22 -0600 -Subject: [PATCH] All chunks are slime spawn chunks toggle - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 70e074cdf2087e638af8e0f3878d0ef8eb7305cc..416a6760883cb40367535c7c5acd779742bb8af5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -191,4 +191,9 @@ public class PaperWorldConfig { - private void disableChestCatDetection() { - disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); - } -+ -+ public boolean allChunksAreSlimeChunks; -+ private void allChunksAreSlimeChunks() { -+ allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -index 292789d76da400d15d0742e2e0979f4ac6ec4b75..01d5b0db9a34d88172e8c7c84c4e1d0b2562217c 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -@@ -325,7 +325,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { - } - - ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(blockposition); -- boolean flag = SeededRandom.a(chunkcoordintpair.x, chunkcoordintpair.z, ((GeneratorAccessSeed) generatoraccess).getSeed(), generatoraccess.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot -+ boolean flag = generatoraccess.getMinecraftWorld().paperConfig.allChunksAreSlimeChunks || SeededRandom.a(chunkcoordintpair.x, chunkcoordintpair.z, ((GeneratorAccessSeed) generatoraccess).getSeed(), generatoraccess.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper - - if (random.nextInt(10) == 0 && flag && blockposition.getY() < 40) { - return a(entitytypes, generatoraccess, enummobspawn, blockposition, random); diff --git a/Unmapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch b/Unmapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch deleted file mode 100644 index 60c4376ef8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0047-Expose-server-CommandMap.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Thu, 3 Mar 2016 02:15:57 -0600 -Subject: [PATCH] Expose server CommandMap - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index b7de5049dfd6807de1c84a9454b9097141399660..f78f5e4f2c04b64dff1d2229a137c600f18e7051 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1761,6 +1761,7 @@ public final class CraftServer implements Server { - return helpMap; - } - -+ @Override // Paper - add override - public SimpleCommandMap getCommandMap() { - return commandMap; - } diff --git a/Unmapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch b/Unmapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch deleted file mode 100644 index 6f72badc91..0000000000 --- a/Unmapped-Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Thu, 3 Mar 2016 02:18:39 -0600 -Subject: [PATCH] Be a bit more informative in maxHealth exception - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index da0a7a60cbabe0dafa9630b8dcba98e64dcc8d3a..d863fc9fa6b932b76a89871a09378a9c0697c108 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -111,7 +111,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setHealth(double health) { - health = (float) health; - if ((health < 0) || (health > getMaxHealth())) { -- throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + "(" + health + ")"); -+ // Paper - Be more informative -+ throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + ", but was " + health -+ + ". (attribute base value: " + this.getHandle().getAttributeInstance(GenericAttributes.MAX_HEALTH).getBaseValue() -+ + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); - } - - getHandle().setHealth((float) health); diff --git a/Unmapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch b/Unmapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch deleted file mode 100644 index 9eeb0fdfdd..0000000000 --- a/Unmapped-Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Thu, 3 Mar 2016 02:32:10 -0600 -Subject: [PATCH] Player Tab List and Title APIs - - -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index 5f1c5dd7902f6cff5acae05e8c6bf58a1ba5bdf1..df459918c14589155a574730205cb35d463b8079 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -171,6 +171,11 @@ public class PacketDataSerializer extends ByteBuf { - public PacketDataSerializer writeComponent(final net.kyori.adventure.text.Component component) { - return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); - } -+ -+ @Deprecated -+ public PacketDataSerializer writeComponent(final net.md_5.bungee.api.chat.BaseComponent[] component) { -+ return this.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(component), 262144); -+ } - // Paper end - - public PacketDataSerializer a(IChatBaseComponent ichatbasecomponent) { -diff --git a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -index e96fa348a37a39c381b6659f612232933686c2a7..a002125e454f8a86924e9010e0b20a95742fa04b 100644 ---- a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -+++ b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -@@ -364,6 +364,7 @@ public interface IChatBaseComponent extends Message, IChatFormatted, Iterable -Date: Thu, 3 Mar 2016 02:33:53 -0600 -Subject: [PATCH] Ensure inv drag is in bounds - - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index 2410214a300407ef20ea14244db5db2ebede2759..e9733fd9dac89d31dbad391cb22a8c84216045db 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -239,7 +239,7 @@ public abstract class Container { - this.d(); - } - } else if (this.h == 1) { -- Slot slot = (Slot) this.slots.get(i); -+ Slot slot = i < this.slots.size() ? this.slots.get(i) : null; // Paper - Ensure drag in bounds - - itemstack1 = playerinventory.getCarried(); - if (slot != null && a(slot, itemstack1, true) && slot.isAllowed(itemstack1) && (this.dragType == 2 || itemstack1.getCount() > this.i.size()) && this.b(slot)) { diff --git a/Unmapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch b/Unmapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch deleted file mode 100644 index 05bc8dac6d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:39:54 -0600 -Subject: [PATCH] Change implementation of (tile)entity removal list - -use sets for faster removal - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 26d9388badb0328735abf0319a42bd633c90dc4b..33469b719d679c65d4bcb8366008e6e107eb3a0b 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -89,7 +89,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public final List tileEntityList = Lists.newArrayList(); - public final List tileEntityListTick = Lists.newArrayList(); - protected final List tileEntityListPending = Lists.newArrayList(); -- protected final List tileEntityListUnload = Lists.newArrayList(); -+ protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); - public final Thread serverThread; - private final boolean debugWorld; - private int d; diff --git a/Unmapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch b/Unmapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch deleted file mode 100644 index e6151a7682..0000000000 --- a/Unmapped-Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:46:17 -0600 -Subject: [PATCH] Add configurable portal search radius - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 416a6760883cb40367535c7c5acd779742bb8af5..670efbe53241a0ae32d618c83da601ccc1f26e37 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -196,4 +196,13 @@ public class PaperWorldConfig { - private void allChunksAreSlimeChunks() { - allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); - } -+ -+ public int portalSearchRadius; -+ public int portalCreateRadius; -+ public boolean portalSearchVanillaDimensionScaling; -+ private void portalSearchRadius() { -+ portalSearchRadius = getInt("portal-search-radius", 128); -+ portalCreateRadius = getInt("portal-create-radius", 16); -+ portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 77cc0aeb979369df2156f8fb916067f608b61ebf..caae8bdae592a1ae4f99861088458d7461f4c97a 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2618,7 +2618,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - double d4 = DimensionManager.a(this.world.getDimensionManager(), worldserver.getDimensionManager()); - BlockPosition blockposition = new BlockPosition(MathHelper.a(this.locX() * d4, d0, d2), this.locY(), MathHelper.a(this.locZ() * d4, d1, d3)); - // CraftBukkit start -- CraftPortalEvent event = callPortalEvent(this, worldserver, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); -+ // Paper start -+ int portalSearchRadius = worldserver.paperConfig.portalSearchRadius; -+ if (world.paperConfig.portalSearchVanillaDimensionScaling && flag2) { // == THE_NETHER -+ portalSearchRadius = (int) (portalSearchRadius / worldserver.getDimensionManager().getCoordinateScale()); -+ } -+ // Paper end -+ CraftPortalEvent event = callPortalEvent(this, worldserver, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, portalSearchRadius, worldserver.paperConfig.portalCreateRadius); // Paper start - configurable portal radius - if (event == null) { - return null; - } -diff --git a/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java b/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java -index 7b8e8a7dae47ecc42a57e3f9444caa2ee5b1ef3b..77dfa7eaf178baa55041a829c9dec4851efeedfc 100644 ---- a/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java -+++ b/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java -@@ -31,7 +31,7 @@ public class PortalTravelAgent { - - public Optional findPortal(BlockPosition blockposition, boolean flag) { - // CraftBukkit start -- return findPortal(blockposition, flag ? 16 : 128); // Search Radius -+ return findPortal(blockposition, flag ? world.paperConfig.portalCreateRadius : world.paperConfig.portalSearchRadius); // Paper - search Radius - } - - public Optional findPortal(BlockPosition blockposition, int i) { diff --git a/Unmapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch b/Unmapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch deleted file mode 100644 index 41c25af3bd..0000000000 --- a/Unmapped-Spigot-Server-Patches/0053-Add-velocity-warnings.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:48:12 -0600 -Subject: [PATCH] Add velocity warnings - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f78f5e4f2c04b64dff1d2229a137c600f18e7051..22b4dec4944b7f823996645af95fbef2d1d8a83b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -261,6 +261,7 @@ public final class CraftServer implements Server { - public boolean ignoreVanillaPermissions = false; - private final List playerView; - public int reloadCount; -+ public static Exception excessiveVelEx; // Paper - Velocity warnings - - static { - ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 220bad90bbb9a90c3f23562bf0fb109fce379682..a58626b1a0160983a738a45c8a1d411eb347e6a2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -424,10 +424,41 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public void setVelocity(Vector velocity) { - Preconditions.checkArgument(velocity != null, "velocity"); - velocity.checkFinite(); -+ // Paper start - Warn server owners when plugins try to set super high velocities -+ if (!(this instanceof org.bukkit.entity.Projectile) && isUnsafeVelocity(velocity)) { -+ CraftServer.excessiveVelEx = new Exception("Excessive velocity set detected: tried to set velocity of entity " + entity.getName() + " id #" + getEntityId() + " to (" + velocity.getX() + "," + velocity.getY() + "," + velocity.getZ() + ")."); -+ } -+ // Paper end -+ - entity.setMot(CraftVector.toNMS(velocity)); - entity.velocityChanged = true; - } - -+ // Paper start -+ /** -+ * Checks if the given velocity is not necessarily safe in all situations. -+ * This function returning true does not mean the velocity is dangerous or to be avoided, only that it may be -+ * a detriment to performance on the server. -+ * -+ * It is not to be used as a hard rule of any sort. -+ * Paper only uses it to warn server owners in watchdog crashes. -+ * -+ * @param vel incoming velocity to check -+ * @return if the velocity has the potential to be a performance detriment -+ */ -+ private static boolean isUnsafeVelocity(Vector vel) { -+ final double x = vel.getX(); -+ final double y = vel.getY(); -+ final double z = vel.getZ(); -+ -+ if (x > 4 || x < -4 || y > 4 || y < -4 || z > 4 || z < -4) { -+ return true; -+ } -+ -+ return false; -+ } -+ // Paper end -+ - @Override - public double getHeight() { - return getHandle().getHeight(); -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 1b3a14784cac8e855633fae6172ad5479ebe9877..69e5054886b5858664fed333aca8c25a76e5cb11 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -80,7 +80,19 @@ public class WatchdogThread extends Thread - log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" ); - log.log( Level.SEVERE, "near " + net.minecraft.world.level.World.lastPhysicsProblem ); - } -- // -+ // Paper start - Warn in watchdog if an excessive velocity was ever set -+ if ( org.bukkit.craftbukkit.CraftServer.excessiveVelEx != null ) -+ { -+ log.log( Level.SEVERE, "------------------------------" ); -+ log.log( Level.SEVERE, "During the run of the server, a plugin set an excessive velocity on an entity" ); -+ log.log( Level.SEVERE, "This may be the cause of the issue, or it may be entirely unrelated" ); -+ log.log( Level.SEVERE, org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getMessage()); -+ for ( StackTraceElement stack : org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getStackTrace() ) -+ { -+ log.log( Level.SEVERE, "\t\t" + stack ); -+ } -+ } -+ // Paper end - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); diff --git a/Unmapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch b/Unmapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch deleted file mode 100644 index 789bab195f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Thu, 3 Mar 2016 02:50:31 -0600 -Subject: [PATCH] Configurable inter-world teleportation safety - -People are able to abuse the way Bukkit handles teleportation across worlds since it provides a built in teleportation -safety check. - -To abuse the safety check, players are required to get into a location deemed unsafe by Bukkit e.g. be within a chest -or door block. While they are in this block, they accept a teleport request from a player within a different world. Once -the player teleports, Minecraft will recursively search upwards for a safe location, this could eventually land within a -player's skybase. - -Example setup to perform the glitch: http://puu.sh/ng3PC/cf072dcbdb.png -The wanted destination was on top of the emerald block however the player ended on top of the diamond block. -This only is the case if the player is teleporting between worlds. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 670efbe53241a0ae32d618c83da601ccc1f26e37..abbbe1786eb68af02f9d39650aad730ac44aac8a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -205,4 +205,9 @@ public class PaperWorldConfig { - portalCreateRadius = getInt("portal-create-radius", 16); - portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); - } -+ -+ public boolean disableTeleportationSuffocationCheck; -+ private void disableTeleportationSuffocationCheck() { -+ disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 1ad5863dc12b2288a38efed71b7fa4b84296d96d..f2228933719a2325a518be15237fedf56c994d1f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -863,7 +863,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (fromWorld == toWorld) { - entity.playerConnection.teleport(to); - } else { -- server.getHandle().moveToWorld(entity, toWorld, true, to, true); -+ server.getHandle().moveToWorld(entity, toWorld, true, to, !toWorld.paperConfig.disableTeleportationSuffocationCheck); // Paper - } - return true; - } diff --git a/Unmapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch b/Unmapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch deleted file mode 100644 index b032c03199..0000000000 --- a/Unmapped-Spigot-Server-Patches/0055-Add-exception-reporting-event.patch +++ /dev/null @@ -1,264 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 03:15:41 -0600 -Subject: [PATCH] Add exception reporting event - - -diff --git a/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f699ce18ca044f813e194ef2786b7ea853ea86e7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java -@@ -0,0 +1,38 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.craftbukkit.scheduler.CraftTask; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerSchedulerException; -+ -+/** -+ * Reporting wrapper to catch exceptions not natively -+ */ -+public class ServerSchedulerReportingWrapper implements Runnable { -+ -+ private final CraftTask internalTask; -+ -+ public ServerSchedulerReportingWrapper(CraftTask internalTask) { -+ this.internalTask = Preconditions.checkNotNull(internalTask, "internalTask"); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ internalTask.run(); -+ } catch (RuntimeException e) { -+ internalTask.getOwner().getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(e, internalTask)) -+ ); -+ throw e; -+ } catch (Throwable t) { -+ internalTask.getOwner().getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(t, internalTask)) -+ ); //Do not rethrow, since it is not permitted with Runnable#run -+ } -+ } -+ -+ public CraftTask getInternalTask() { -+ return internalTask; -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 788a45d5426f0752509442aec2d28b1f32f63cb1..2511fbe7aa5ff1ace71b513d2938975e388295c6 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -815,6 +815,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return true; - } catch (Exception exception) { - PlayerChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - return false; - } - } -diff --git a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -index 107979178e8be5ee6cf885d42f992fabf3bd00b0..8a343a857dc4661ba256e39cf391dd2c7a1cc970 100644 ---- a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -+++ b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.players; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.io.Files; -@@ -363,6 +364,7 @@ public class NameReferencingFileConverter { - root = NBTCompressedStreamTools.a(new java.io.FileInputStream(file5)); - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - } - - if (root != null) { -@@ -376,6 +378,7 @@ public class NameReferencingFileConverter { - NBTCompressedStreamTools.a(root, new java.io.FileOutputStream(file2)); - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -index 928ca3189af1ddaba797628a087cd6c6a9016f5c..eaa97eb11d893266253fb108249ced1e0e96a4dc 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -@@ -1,5 +1,7 @@ - package net.minecraft.world.entity.ai.village; - -+import com.destroystokyo.paper.exception.ServerInternalException; -+ - import java.util.Iterator; - import javax.annotation.Nullable; - import net.minecraft.core.BaseBlockPosition; -@@ -119,6 +121,7 @@ public class VillageSiege implements MobSpawner { - entityzombie.prepare(worldserver, worldserver.getDamageScaler(entityzombie.getChunkCoordinates()), EnumMobSpawn.EVENT, (GroupDataEntity) null, (NBTTagCompound) null); - } catch (Exception exception) { - VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception); -+ ServerInternalException.reportInternalException(exception); // Paper - return; - } - -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index 2d02b2fc502a0f7e541f7943ed647ff7177acee8..fd0595fd584046326eccacdf0a6afe40c5e84eed 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -301,6 +301,7 @@ public final class SpawnerCreature { - } - } catch (Exception exception) { - SpawnerCreature.LOGGER.warn("Failed to create mob", exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - return null; - } - } -@@ -407,6 +408,7 @@ public final class SpawnerCreature { - entity = biomesettingsmobs_c.c.a((World) worldaccess.getMinecraftWorld()); - } catch (Exception exception) { - SpawnerCreature.LOGGER.warn("Failed to create mob", exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - continue; - } - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 33469b719d679c65d4bcb8366008e6e107eb3a0b..01cb0c8dd9875986e0c08371e876f0dba3f0cf5a 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -1,5 +1,10 @@ - package net.minecraft.world.level; - -+import co.aikar.timings.Timing; -+import co.aikar.timings.Timings; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerInternalException; -+import com.google.common.base.MoreObjects; - import com.google.common.collect.Lists; - import com.mojang.serialization.Codec; - import java.io.IOException; -@@ -737,8 +742,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - gameprofilerfiller.exit(); - } catch (Throwable throwable) { - // Paper start - Prevent tile entity and entity crashes -- System.err.println("TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ()); -+ String msg = "TileEntity threw exception at " + tileentity.getWorld().getWorld().getName() + ":" + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ(); -+ System.err.println(msg); - throwable.printStackTrace(); -+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); -+ // Paper end - tilesThisCycle--; - this.tileEntityListTick.remove(tileTickPosition--); - continue; -@@ -808,8 +816,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - consumer.accept(entity); - } catch (Throwable throwable) { - // Paper start - Prevent tile entity and entity crashes -- System.err.println("Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ()); -+ String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ(); -+ System.err.println(msg); - throwable.printStackTrace(); -+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); - entity.dead = true; - return; - // Paper end -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index a2d80c2c8e4f080f60746548f75631c5946ba8e2..4b3de29b1a6e9d75b28962073c62bbe8d666165f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.chunk; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; - import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -@@ -655,10 +656,15 @@ public class Chunk implements IChunkAccess { - this.tileEntities.remove(blockposition); - // Paper end - } else { -- System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ() -- + " (" + getType(blockposition) + ") where there was no entity tile!"); -- System.out.println("Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16)); -- new Exception().printStackTrace(); -+ // Paper start -+ ServerInternalException e = new ServerInternalException( -+ "Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getPosition().getX() + "," -+ + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ() -+ + " (" + getType(blockposition) + ") where there was no entity tile!\n" + -+ "Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16)); -+ e.printStackTrace(); -+ ServerInternalException.reportInternalException(e); -+ // Paper end - // CraftBukkit end - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index d1b761055c508a4b80436b50a832e00d0449d8cb..1638f7902290e1bb233f11e5d0bbf83a9e863939 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -265,6 +265,7 @@ public class RegionFile implements AutoCloseable { - return true; - } - } catch (IOException ioexception) { -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper - return false; - } - } -@@ -337,6 +338,7 @@ public class RegionFile implements AutoCloseable { - filechannel.write(bytebuffer); - } catch (Throwable throwable1) { - throwable = throwable1; -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper - throw throwable1; - } finally { - if (filechannel != null) { -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -index 3910daeaa177639fa8055301304634c2014dc20f..d61960d80599dc5e7b70cc990e4b0b174eb6e34e 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -@@ -150,6 +150,7 @@ public class WorldPersistentData { - } - } catch (Throwable throwable6) { - throwable = throwable6; -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper - throw throwable6; - } finally { - if (fileinputstream != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index ffe9cc1011226d604dc5499e7692e9a9a5132b72..9b6d9373abb59a30c2835ca891282d07559281f5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -16,6 +16,9 @@ import java.util.concurrent.atomic.AtomicInteger; - import java.util.concurrent.atomic.AtomicReference; - import java.util.function.Consumer; - import java.util.logging.Level; -+import com.destroystokyo.paper.ServerSchedulerReportingWrapper; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerSchedulerException; - import org.apache.commons.lang.Validate; - import org.bukkit.plugin.IllegalPluginAccessException; - import org.bukkit.plugin.Plugin; -@@ -419,6 +422,8 @@ public class CraftScheduler implements BukkitScheduler { - msg, - throwable); - } -+ org.bukkit.Bukkit.getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task))); - // Paper end - } finally { - currentTask = null; -@@ -426,7 +431,7 @@ public class CraftScheduler implements BukkitScheduler { - parsePending(); - } else { - debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); -- executor.execute(task); -+ executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper - // We don't need to parse pending - // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) - } diff --git a/Unmapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/Unmapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch deleted file mode 100644 index e8a68b30bb..0000000000 --- a/Unmapped-Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Tue, 8 Mar 2016 18:28:43 -0800 -Subject: [PATCH] Don't nest if we don't need to when cerealising text - components - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -index edae451a54bfcd6b54e89c1619fb112a7763eb3b..f6a1c5ac9acb34b1ef2262721adbbb1a5b0feaf7 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -@@ -40,7 +40,14 @@ public class PacketPlayOutChat implements Packet { - // Paper end - // Spigot start - if (components != null) { -- packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); -+ //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below -+ // Paper start - don't nest if we don't need to so that we can preserve formatting -+ if (this.components.length == 1) { -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); -+ } else { -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); -+ } -+ // Paper end - } else { - packetdataserializer.a(this.a); - } diff --git a/Unmapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch b/Unmapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch deleted file mode 100644 index 60640fef2b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 8 Mar 2016 23:25:45 -0500 -Subject: [PATCH] Disable Scoreboards for non players by default - -Entities collision is checking for scoreboards setting. -This is very heavy to do map lookups for every collision to check -this setting. - -So avoid looking up scoreboards and short circuit to the "not on a team" -logic which is most likely to be true. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index abbbe1786eb68af02f9d39650aad730ac44aac8a..3ac2ac3db9b1c271b3c21930bb13716669ff64d3 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -210,4 +210,9 @@ public class PaperWorldConfig { - private void disableTeleportationSuffocationCheck() { - disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); - } -+ -+ public boolean nonPlayerEntitiesOnScoreboards = false; -+ private void nonPlayerEntitiesOnScoreboards() { -+ nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index caae8bdae592a1ae4f99861088458d7461f4c97a..bfced192c1e8fd3fa0250a0f93adfc061d7e71e5 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2289,6 +2289,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - @Nullable - public ScoreboardTeamBase getScoreboardTeam() { -+ if (!this.world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { return null; } // Paper - return this.world.getScoreboard().getPlayerTeam(this.getName()); - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 49e95369882847c90ee7417abea6270386cd622f..70211129e6ab2f7cdb975adcb532be595bc3834f 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -741,6 +741,7 @@ public abstract class EntityLiving extends Entity { - if (nbttagcompound.hasKeyOfType("Team", 8)) { - String s = nbttagcompound.getString("Team"); - ScoreboardTeam scoreboardteam = this.world.getScoreboard().getTeam(s); -+ if (!world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { scoreboardteam = null; } // Paper - boolean flag = scoreboardteam != null && this.world.getScoreboard().addPlayerToTeam(this.getUniqueIDString(), scoreboardteam); - - if (!flag) { diff --git a/Unmapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Unmapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch deleted file mode 100644 index 6885002825..0000000000 --- a/Unmapped-Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mrapple -Date: Sun, 25 Nov 2012 13:43:39 -0600 -Subject: [PATCH] Add methods for working with arrows stuck in living entities - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index d863fc9fa6b932b76a89871a09378a9c0697c108..c654026587bc9bf77b39f59a0c89991ac581da1e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -689,4 +689,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - getHandle().persistentInvisibility = invisible; - getHandle().setFlag(5, invisible); - } -+ -+ // Paper start -+ @Override -+ public int getArrowsStuck() { -+ return getHandle().getArrowCount(); -+ } -+ -+ @Override -+ public void setArrowsStuck(int arrows) { -+ getHandle().setArrowCount(arrows); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch b/Unmapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch deleted file mode 100644 index 396e787eb7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0059-Complete-resource-pack-API.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 4 Apr 2015 23:17:52 -0400 -Subject: [PATCH] Complete resource pack API - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 865d8efa2d480ae7edc286e3e79f2997a191ee5c..af0a7dc9464e1acf1451f45464bab8546207950e 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1605,7 +1605,11 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit start - public void a(PacketPlayInResourcePackStatus packetplayinresourcepackstatus) { - PlayerConnectionUtils.ensureMainThread(packetplayinresourcepackstatus, this, this.player.getWorldServer()); -- this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()])); -+ // Paper start -+ PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()]; -+ player.getBukkitEntity().setResourcePackStatus(packStatus); -+ this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), packStatus)); -+ // Paper end - } - // CraftBukkit end - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index f2228933719a2325a518be15237fedf56c994d1f..ed5680e6e0fcfbaf948bdede98d206cff2b26467 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -138,6 +138,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - private double health = 20; - private boolean scaledHealth = false; - private double healthScale = 20; -+ // Paper start -+ private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; -+ private String resourcePackHash; -+ // Paper end - - public CraftPlayer(CraftServer server, EntityPlayer entity) { - super(server, entity); -@@ -1874,6 +1878,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public boolean getAffectsSpawning() { - return this.getHandle().affectsSpawning; - } -+ -+ @Override -+ public void setResourcePack(String url, String hash) { -+ Validate.notNull(url, "Resource pack URL cannot be null"); -+ Validate.notNull(hash, "Hash cannot be null"); -+ this.getHandle().setResourcePack(url, hash); -+ } -+ -+ @Override -+ public org.bukkit.event.player.PlayerResourcePackStatusEvent.Status getResourcePackStatus() { -+ return this.resourcePackStatus; -+ } -+ -+ @Override -+ public String getResourcePackHash() { -+ return this.resourcePackHash; -+ } -+ -+ @Override -+ public boolean hasResourcePack() { -+ return this.resourcePackStatus == org.bukkit.event.player.PlayerResourcePackStatusEvent.Status.SUCCESSFULLY_LOADED; -+ } -+ -+ public void setResourcePackStatus(org.bukkit.event.player.PlayerResourcePackStatusEvent.Status status) { -+ this.resourcePackStatus = status; -+ } - // Paper end - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch b/Unmapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch deleted file mode 100644 index 03f01b1583..0000000000 --- a/Unmapped-Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 4 Mar 2013 23:46:10 -0500 -Subject: [PATCH] Chunk Save Reattempt - -We commonly have "Stream Closed" errors on chunk saving, so this code should re-try to save the chunk in the event of failure and hopefully prevent rollbacks. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 1638f7902290e1bb233f11e5d0bbf83a9e863939..4bf3e0cb4602d33a2e00c502b1dd212032b22a8f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -265,7 +265,7 @@ public class RegionFile implements AutoCloseable { - return true; - } - } catch (IOException ioexception) { -- com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioexception); // Paper - we want the upper try/catch to retry this - return false; - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index de125077656f249d5cf9b76f07981b55e690e015..8310dd6bfc04b8ac0a51545baa3a264e6cb42eac 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -11,6 +11,7 @@ import java.io.IOException; - import javax.annotation.Nullable; - import net.minecraft.nbt.NBTCompressedStreamTools; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionSuppressor; - import net.minecraft.world.level.ChunkCoordIntPair; - -@@ -92,6 +93,7 @@ public final class RegionFileCache implements AutoCloseable { - - protected void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { - RegionFile regionfile = this.getFile(chunkcoordintpair, false); // CraftBukkit -+ int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper - DataOutputStream dataoutputstream = regionfile.c(chunkcoordintpair); - Throwable throwable = null; - -@@ -115,6 +117,18 @@ public final class RegionFileCache implements AutoCloseable { - - } - -+ // Paper start -+ return; -+ } catch (Exception ex) { -+ laste = ex; -+ } -+ } -+ -+ if (laste != null) { -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(laste); -+ MinecraftServer.LOGGER.error("Failed to save chunk", laste); -+ } -+ // Paper end - } - - public void close() throws IOException { diff --git a/Unmapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch b/Unmapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch deleted file mode 100644 index 6ae4874a0a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 13:17:38 -0400 -Subject: [PATCH] Default loading permissions.yml before plugins - -Under previous behavior, plugins were not able to check if a player had a permission -if it was defined in permissions.yml. there is no clean way for a plugin to fix that either. - -This will change the order so that by default, permissions.yml loads BEFORE plugins instead of after. - -This gives plugins expected permission checks. - -It also helps improve the expected logic, as servers should set the initial defaults, and then let plugins -modify that. Under the previous logic, plugins were unable (cleanly) override permissions.yml. - -A config option has been added for those who depend on the previous behavior, but I don't expect that. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 429b74474ced04d8dd8f038b8590b8dfe178bf4d..716f285e67019b8a62922d09c15883c99f9421aa 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -222,4 +222,9 @@ public class PaperConfig { - private static void useDisplayNameInQuit() { - useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); - } -+ -+ public static boolean loadPermsBeforePlugins = true; -+ private static void loadPermsBeforePlugins() { -+ loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 22b4dec4944b7f823996645af95fbef2d1d8a83b..6eec60b5739edb8f7278608e525b38bdac15bba8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -398,6 +398,7 @@ public final class CraftServer implements Server { - if (type == PluginLoadOrder.STARTUP) { - helpMap.clear(); - helpMap.initializeGeneralTopics(); -+ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper - } - - Plugin[] plugins = pluginManager.getPlugins(); -@@ -417,7 +418,7 @@ public final class CraftServer implements Server { - commandMap.registerServerAliases(); - DefaultPermissions.registerCorePermissions(); - CraftDefaultPermissions.registerCorePermissions(); -- loadCustomPermissions(); -+ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper - helpMap.initializeCommands(); - syncCommands(); - } diff --git a/Unmapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch b/Unmapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch deleted file mode 100644 index 46a0159c74..0000000000 --- a/Unmapped-Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William -Date: Fri, 18 Mar 2016 03:30:17 -0400 -Subject: [PATCH] Allow Reloading of Custom Permissions - -https://github.com/PaperMC/Paper/issues/49 - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6eec60b5739edb8f7278608e525b38bdac15bba8..6d66a899912bfab2ce610fb6fb2dbec87cbb5790 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2253,5 +2253,23 @@ public final class CraftServer implements Server { - } - return this.adventure$audiences; - } -+ -+ @Override -+ public void reloadPermissions() { -+ pluginManager.clearPermissions(); -+ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); -+ for (Plugin plugin : pluginManager.getPlugins()) { -+ for (Permission perm : plugin.getDescription().getPermissions()) { -+ try { -+ pluginManager.addPermission(perm); -+ } catch (IllegalArgumentException ex) { -+ getLogger().log(Level.WARNING, "Plugin " + plugin.getDescription().getFullName() + " tried to register permission '" + perm.getName() + "' but it's already registered", ex); -+ } -+ } -+ } -+ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); -+ DefaultPermissions.registerCorePermissions(); -+ CraftDefaultPermissions.registerCorePermissions(); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch b/Unmapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch deleted file mode 100644 index 54d6959b3b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 13:50:14 -0400 -Subject: [PATCH] Remove Metadata on reload - -Metadata is not meant to persist reload as things break badly with non primitive types -This will remove metadata on reload so it does not crash everything if a plugin uses it. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6d66a899912bfab2ce610fb6fb2dbec87cbb5790..e670f484d454f7c706a0ec92c98087fa1373c492 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -871,8 +871,18 @@ public final class CraftServer implements Server { - world.paperConfig.init(); // Paper - } - -+ Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper - pluginManager.clearPlugins(); - commandMap.clearCommands(); -+ -+ // Paper start -+ for (Plugin plugin : pluginClone) { -+ entityMetadata.removeAll(plugin); -+ worldMetadata.removeAll(plugin); -+ playerMetadata.removeAll(plugin); -+ } -+ // Paper end -+ - resetRecipes(); - reloadData(); - org.spigotmc.SpigotConfig.registerCommands(); // Spigot diff --git a/Unmapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch b/Unmapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch deleted file mode 100644 index 777dfb5014..0000000000 --- a/Unmapped-Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch +++ /dev/null @@ -1,331 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 28 May 2015 23:00:19 -0400 -Subject: [PATCH] Handle Item Meta Inconsistencies - -First, Enchantment order would blow away seeing 2 items as the same, -however the Client forces enchantment list in a certain order, as well -as does the /enchant command. Anvils can insert it into forced order, -causing 2 same items to be considered different. - -This change makes unhandled NBT Tags and Enchantments use a sorted tree map, -so they will always be in a consistent order. - -Additionally, the old enchantment API was never updated when ItemMeta -was added, resulting in 2 different ways to modify an items enchantments. - -For consistency, the old API methods now forward to use the -ItemMeta API equivalents, and should deprecate the old API's. - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index f1a780768e3f4bdb43a7ca6d7850befefb71bf57..201ba7250b298f4a91bc45f5954f54ae557305f2 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -9,6 +9,8 @@ import com.mojang.serialization.Codec; - import com.mojang.serialization.codecs.RecordCodecBuilder; - import java.text.DecimalFormat; - import java.text.DecimalFormatSymbols; -+import java.util.Collections; -+import java.util.Comparator; - import java.util.Locale; - import java.util.Objects; - import java.util.Optional; -@@ -120,6 +122,23 @@ public final class ItemStack { - private ShapeDetectorBlock n; - private boolean o; - -+ // Paper start -+ private static final java.util.Comparator enchantSorter = java.util.Comparator.comparing(o -> o.getString("id")); -+ private void processEnchantOrder(NBTTagCompound tag) { -+ if (tag == null || !tag.hasKeyOfType("Enchantments", 9)) { -+ return; -+ } -+ NBTTagList list = tag.getList("Enchantments", 10); -+ if (list.size() < 2) { -+ return; -+ } -+ try { -+ //noinspection unchecked -+ list.sort((Comparator) enchantSorter); // Paper -+ } catch (Exception ignored) {} -+ } -+ // Paper end -+ - public ItemStack(IMaterial imaterial) { - this(imaterial, 1); - } -@@ -162,6 +181,7 @@ public final class ItemStack { - if (nbttagcompound.hasKeyOfType("tag", 10)) { - // CraftBukkit start - make defensive copy as this data may be coming from the save thread - this.tag = (NBTTagCompound) nbttagcompound.getCompound("tag").clone(); -+ processEnchantOrder(this.tag); // Paper - this.getItem().b(this.tag); - // CraftBukkit end - } -@@ -680,6 +700,7 @@ public final class ItemStack { - // Paper end - public void setTag(@Nullable NBTTagCompound nbttagcompound) { - this.tag = nbttagcompound; -+ processEnchantOrder(this.tag); // Paper - if (this.getItem().usesDurability()) { - this.setDamage(this.getDamage()); - } -@@ -770,6 +791,7 @@ public final class ItemStack { - nbttagcompound.setString("id", String.valueOf(IRegistry.ENCHANTMENT.getKey(enchantment))); - nbttagcompound.setShort("lvl", (short) ((byte) i)); - nbttaglist.add(nbttagcompound); -+ processEnchantOrder(nbttagcompound); // Paper - } - - public boolean hasEnchantments() { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 275b943a59ef28c831a068987e111e84ebba3bb7..7221ac52c9f66ae0af6f6cbf15c8d47f9c0291a0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -178,28 +178,11 @@ public final class CraftItemStack extends ItemStack { - public void addUnsafeEnchantment(Enchantment ench, int level) { - Validate.notNull(ench, "Cannot add null enchantment"); - -- if (!makeTag(handle)) { -- return; -- } -- NBTTagList list = getEnchantmentList(handle); -- if (list == null) { -- list = new NBTTagList(); -- handle.getTag().set(ENCHANTMENTS.NBT, list); -- } -- int size = list.size(); -- -- for (int i = 0; i < size; i++) { -- NBTTagCompound tag = (NBTTagCompound) list.get(i); -- String id = tag.getString(ENCHANTMENTS_ID.NBT); -- if (id.equals(ench.getKey().toString())) { -- tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level); -- return; -- } -- } -- NBTTagCompound tag = new NBTTagCompound(); -- tag.setString(ENCHANTMENTS_ID.NBT, ench.getKey().toString()); -- tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level); -- list.add(tag); -+ // Paper start - Replace whole method -+ final ItemMeta itemMeta = getItemMeta(); -+ itemMeta.addEnchant(ench, level, true); -+ setItemMeta(itemMeta); -+ // Paper end - } - - static boolean makeTag(net.minecraft.world.item.ItemStack item) { -@@ -216,66 +199,33 @@ public final class CraftItemStack extends ItemStack { - - @Override - public boolean containsEnchantment(Enchantment ench) { -- return getEnchantmentLevel(ench) > 0; -+ return hasItemMeta() && getItemMeta().hasEnchant(ench); // Paper - use meta - } - - @Override - public int getEnchantmentLevel(Enchantment ench) { -- Validate.notNull(ench, "Cannot find null enchantment"); -- if (handle == null) { -- return 0; -- } -- return EnchantmentManager.getEnchantmentLevel(CraftEnchantment.getRaw(ench), handle); -+ return hasItemMeta() ? getItemMeta().getEnchantLevel(ench) : 0; // Paper - replace entire method with meta - } - - @Override - public int removeEnchantment(Enchantment ench) { - Validate.notNull(ench, "Cannot remove null enchantment"); - -- NBTTagList list = getEnchantmentList(handle), listCopy; -- if (list == null) { -- return 0; -- } -- int index = Integer.MIN_VALUE; -- int level = Integer.MIN_VALUE; -- int size = list.size(); -- -- for (int i = 0; i < size; i++) { -- NBTTagCompound enchantment = (NBTTagCompound) list.get(i); -- String id = enchantment.getString(ENCHANTMENTS_ID.NBT); -- if (id.equals(ench.getKey().toString())) { -- index = i; -- level = 0xffff & enchantment.getShort(ENCHANTMENTS_LVL.NBT); -- break; -- } -- } -- -- if (index == Integer.MIN_VALUE) { -- return 0; -- } -- if (size == 1) { -- handle.getTag().remove(ENCHANTMENTS.NBT); -- if (handle.getTag().isEmpty()) { -- handle.setTag(null); -- } -- return level; -- } -- -- // This is workaround for not having an index removal -- listCopy = new NBTTagList(); -- for (int i = 0; i < size; i++) { -- if (i != index) { -- listCopy.add(list.get(i)); -- } -+ // Paper start - replace entire method -+ final ItemMeta itemMeta = getItemMeta(); -+ int level = itemMeta.getEnchantLevel(ench); -+ if (level > 0) { -+ itemMeta.removeEnchant(ench); -+ setItemMeta(itemMeta); - } -- handle.getTag().set(ENCHANTMENTS.NBT, listCopy); -+ // Paper end - - return level; - } - - @Override - public Map getEnchantments() { -- return getEnchantments(handle); -+ return hasItemMeta() ? getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta - } - - 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 7a11b2ddfa4244459253c918315aaab78ef2eb4a..57a6e66866ea82caccbbbfd55948a081f50f6bbe 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; - import com.google.common.collect.ImmutableMap; - import com.google.common.collect.ImmutableMultimap; - import com.google.common.collect.LinkedHashMultimap; -+import com.google.common.collect.ImmutableSortedMap; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Multimap; - import com.google.common.collect.SetMultimap; -@@ -22,6 +23,7 @@ import java.lang.reflect.InvocationTargetException; - import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; -+import java.util.Comparator; // Paper - import java.util.EnumSet; - import java.util.HashMap; - import java.util.Iterator; -@@ -32,6 +34,7 @@ import java.util.Map; - import java.util.NoSuchElementException; - import java.util.Objects; - import java.util.Set; -+import java.util.TreeMap; // Paper - import java.util.logging.Level; - import java.util.logging.Logger; - import javax.annotation.Nonnull; -@@ -271,7 +274,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - private List lore; // null and empty are two different states internally - private Integer customModelData; - private NBTTagCompound blockData; -- private Map enchantments; -+ private EnchantmentMap enchantments; // Paper - private Multimap attributeModifiers; - private int repairCost; - private int hideFlag; -@@ -282,7 +285,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); - - private NBTTagCompound internalTag; -- private final Map unhandledTags = new HashMap(); -+ private final Map unhandledTags = new TreeMap<>(); // Paper - private CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); - - private int version = CraftMagicNumbers.INSTANCE.getDataVersion(); // Internal use only -@@ -303,7 +306,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - this.blockData = meta.blockData; - - if (meta.enchantments != null) { // Spigot -- this.enchantments = new LinkedHashMap(meta.enchantments); -+ this.enchantments = new EnchantmentMap(meta.enchantments); // Paper - } - - if (meta.hasAttributeModifiers()) { -@@ -386,13 +389,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -- static Map buildEnchantments(NBTTagCompound tag, ItemMetaKey key) { -+ static EnchantmentMap buildEnchantments(NBTTagCompound tag, ItemMetaKey key) { // Paper - if (!tag.hasKey(key.NBT)) { - return null; - } - - NBTTagList ench = tag.getList(key.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); -- Map enchantments = new LinkedHashMap(ench.size()); -+ EnchantmentMap enchantments = new EnchantmentMap(); // Paper - - for (int i = 0; i < ench.size(); i++) { - String id = ((NBTTagCompound) ench.get(i)).getString(ENCHANTMENTS_ID.NBT); -@@ -545,13 +548,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -- static Map buildEnchantments(Map map, ItemMetaKey key) { -+ static EnchantmentMap buildEnchantments(Map map, ItemMetaKey key) { // Paper - Map ench = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); - if (ench == null) { - return null; - } - -- Map enchantments = new LinkedHashMap(ench.size()); -+ EnchantmentMap enchantments = new EnchantmentMap(); // Paper - for (Map.Entry entry : ench.entrySet()) { - // Doctor older enchants - String enchantKey = entry.getKey().toString(); -@@ -827,14 +830,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - - @Override - public Map getEnchants() { -- return hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); -+ return hasEnchants() ? ImmutableSortedMap.copyOfSorted(enchantments) : ImmutableMap.of(); // Paper - } - - @Override - public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { - Validate.notNull(ench, "Enchantment cannot be null"); - if (enchantments == null) { -- enchantments = new LinkedHashMap(4); -+ enchantments = new EnchantmentMap(); // Paper - } - - if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { -@@ -1215,7 +1218,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - clone.customModelData = this.customModelData; - clone.blockData = this.blockData; - if (this.enchantments != null) { -- clone.enchantments = new LinkedHashMap(this.enchantments); -+ clone.enchantments = new EnchantmentMap(this.enchantments); // Paper - } - if (this.hasAttributeModifiers()) { - clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); -@@ -1447,4 +1450,22 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return HANDLED_TAGS; - } - } -+ -+ // Paper start -+ private static class EnchantmentMap extends TreeMap { -+ private EnchantmentMap(Map enchantments) { -+ this(); -+ putAll(enchantments); -+ } -+ -+ private EnchantmentMap() { -+ super(Comparator.comparing(o -> o.getKey().toString())); -+ } -+ -+ public EnchantmentMap clone() { -+ return (EnchantmentMap) super.clone(); -+ } -+ } -+ // Paper end -+ - } diff --git a/Unmapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/Unmapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch deleted file mode 100644 index 1aea311bfb..0000000000 --- a/Unmapped-Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 15:12:22 -0400 -Subject: [PATCH] Configurable Non Player Arrow Despawn Rate - -Can set a much shorter despawn rate for arrows that players can not pick up. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3ac2ac3db9b1c271b3c21930bb13716669ff64d3..3c78d3234054ce2dc46ef77decb6adb0cbd10620 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -215,4 +215,19 @@ public class PaperWorldConfig { - private void nonPlayerEntitiesOnScoreboards() { - nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); - } -+ -+ public int nonPlayerArrowDespawnRate = -1; -+ public int creativeArrowDespawnRate = -1; -+ private void nonPlayerArrowDespawnRate() { -+ nonPlayerArrowDespawnRate = getInt("non-player-arrow-despawn-rate", -1); -+ if (nonPlayerArrowDespawnRate == -1) { -+ nonPlayerArrowDespawnRate = spigotConfig.arrowDespawnRate; -+ } -+ creativeArrowDespawnRate = getInt("creative-arrow-despawn-rate", -1); -+ if (creativeArrowDespawnRate == -1) { -+ creativeArrowDespawnRate = spigotConfig.arrowDespawnRate; -+ } -+ log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); -+ log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index 04af85e0ccb7a98e0796afcdcce33f8595b1db8c..7868259a94766a6100d7b278c4296dde0a7f9397 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -283,7 +283,7 @@ public abstract class EntityArrow extends IProjectile { - - protected void h() { - ++this.despawnCounter; -- if (this.despawnCounter >= ((this instanceof EntityThrownTrident) ? world.spigotConfig.tridentDespawnRate : world.spigotConfig.arrowDespawnRate)) { // Spigot -+ if (this.despawnCounter >= (fromPlayer == PickupStatus.CREATIVE_ONLY ? world.paperConfig.creativeArrowDespawnRate : (fromPlayer == PickupStatus.DISALLOWED ? world.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof EntityThrownTrident) ? world.spigotConfig.tridentDespawnRate : world.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? - this.die(); - } - diff --git a/Unmapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch b/Unmapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch deleted file mode 100644 index ff0b627ecc..0000000000 --- a/Unmapped-Spigot-Server-Patches/0066-Add-World-Util-Methods.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 20:16:03 -0400 -Subject: [PATCH] Add World Util Methods - -Methods that can be used for other patches to help improve logic. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index a1769df6a3f6150d322f145199caba3839871dff..3ea4ec748c229031a5f0d973988bb20e55679971 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -197,7 +197,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final Convertable.ConversionSession convertable; - public final UUID uuid; - -- public Chunk getChunkIfLoaded(int x, int z) { -+ @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkProvider.getChunkAt(x, z, false); - } - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 01cb0c8dd9875986e0c08371e876f0dba3f0cf5a..a570998e4ef6c3ff83403881bf1d24c8cbcfcf67 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -297,11 +297,27 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - @Override -- public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ public final Fluid getFluidIfLoaded(BlockPosition blockposition) { - IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); - - return chunk == null ? null : chunk.getFluid(blockposition); - } -+ -+ public final boolean isLoadedAndInBounds(BlockPosition blockposition) { // Paper - final for inline -+ return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; -+ } -+ -+ public Chunk getChunkIfLoaded(int x, int z) { // Overridden in WorldServer for ABI compat which has final -+ return ((WorldServer) this).getChunkProvider().getChunkAtIfLoadedImmediately(x, z); -+ } -+ public final Chunk getChunkIfLoaded(BlockPosition blockposition) { -+ return ((WorldServer) this).getChunkProvider().getChunkAtIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ } -+ -+ // reduces need to do isLoaded before getType -+ public final IBlockData getTypeIfLoadedAndInBounds(BlockPosition blockposition) { -+ return getWorldBorder().isInBounds(blockposition) ? getTypeIfLoaded(blockposition) : null; -+ } - // Paper end - - @Override -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 2bb03f1cb9671a7754a68059219f783d4508eeb9..f16c76df5d7b184d57f4cc397f069eac9cc430cb 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -31,6 +31,7 @@ public class WorldBorder { - - public WorldBorder() {} - -+ public final boolean isInBounds(BlockPosition blockposition) { return this.a(blockposition); } // Paper - OBFHELPER - public boolean a(BlockPosition blockposition) { - return (double) (blockposition.getX() + 1) > this.e() && (double) blockposition.getX() < this.g() && (double) (blockposition.getZ() + 1) > this.f() && (double) blockposition.getZ() < this.h(); - } diff --git a/Unmapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch b/Unmapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch deleted file mode 100644 index bf2af97bfc..0000000000 --- a/Unmapped-Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sun, 21 Jun 2015 15:07:20 -0400 -Subject: [PATCH] Custom replacement for eaten items - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 70211129e6ab2f7cdb975adcb532be595bc3834f..759592fc6a4654c0760ff8a1d7f3b87c364b045a 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3205,9 +3205,10 @@ public abstract class EntityLiving extends Entity { - this.b(this.activeItem, 16); - // CraftBukkit start - fire PlayerItemConsumeEvent - ItemStack itemstack; -+ PlayerItemConsumeEvent event = null; // Paper - if (this instanceof EntityPlayer) { - org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.activeItem); -- PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); -+ event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); // Paper - world.getServer().getPluginManager().callEvent(event); - - if (event.isCancelled()) { -@@ -3221,6 +3222,13 @@ public abstract class EntityLiving extends Entity { - } else { - itemstack = this.activeItem.a(this.world, this); - } -+ -+ // Paper start - save the default replacement item and change it if necessary -+ final ItemStack defaultReplacement = itemstack; -+ if (event != null && event.getReplacement() != null) { -+ itemstack = CraftItemStack.asNMSCopy(event.getReplacement()); -+ } -+ // Paper end - // CraftBukkit end - - if (itemstack != this.activeItem) { -@@ -3228,6 +3236,11 @@ public abstract class EntityLiving extends Entity { - } - - this.clearActiveItem(); -+ // Paper start - if the replacement is anything but the default, update the client inventory -+ if (this instanceof EntityPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { -+ ((EntityPlayer) this).getBukkitEntity().updateInventory(); -+ } -+ // Paper end - } - - } diff --git a/Unmapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/Unmapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch deleted file mode 100644 index a64c157fce..0000000000 --- a/Unmapped-Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 27 Sep 2015 01:18:02 -0400 -Subject: [PATCH] handle NaN health/absorb values and repair bad data - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 759592fc6a4654c0760ff8a1d7f3b87c364b045a..375284b7e321cb03a7a30aedea165ca7a2fd1091 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -702,7 +702,13 @@ public abstract class EntityLiving extends Entity { - - @Override - public void loadData(NBTTagCompound nbttagcompound) { -- this.setAbsorptionHearts(nbttagcompound.getFloat("AbsorptionAmount")); -+ // Paper start - jvm keeps optimizing the setter -+ float absorptionAmount = nbttagcompound.getFloat("AbsorptionAmount"); -+ if (Float.isNaN(absorptionAmount)) { -+ absorptionAmount = 0; -+ } -+ this.setAbsorptionHearts(absorptionAmount); -+ // Paper end - if (nbttagcompound.hasKeyOfType("Attributes", 9) && this.world != null && !this.world.isClientSide) { - this.getAttributeMap().a(nbttagcompound.getList("Attributes", 10)); - } -@@ -1151,6 +1157,10 @@ public abstract class EntityLiving extends Entity { - } - - public void setHealth(float f) { -+ // Paper start -+ if (Float.isNaN(f)) { f = getMaxHealth(); if (this.valid) { -+ System.err.println("[NAN-HEALTH] " + getName() + " had NaN health set"); -+ } } // Paper end - // CraftBukkit start - Handle scaled health - if (this instanceof EntityPlayer) { - org.bukkit.craftbukkit.entity.CraftPlayer player = ((EntityPlayer) this).getBukkitEntity(); -@@ -3045,7 +3055,7 @@ public abstract class EntityLiving extends Entity { - } - - public void setAbsorptionHearts(float f) { -- if (f < 0.0F) { -+ if (f < 0.0F || Float.isNaN(f)) { // Paper - f = 0.0F; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ed5680e6e0fcfbaf948bdede98d206cff2b26467..ab7e731cb04a75b829f0cd24d7b94f7ddad166e8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1680,6 +1680,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void setRealHealth(double health) { -+ if (Double.isNaN(health)) {return;} // Paper - this.health = health; - } - diff --git a/Unmapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch b/Unmapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch deleted file mode 100644 index 23a114a451..0000000000 --- a/Unmapped-Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 22 Mar 2016 00:33:47 -0400 -Subject: [PATCH] Use a Shared Random for Entities - -Reduces memory usage and provides ensures more randomness, Especially since a lot of garbage entity objects get created. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index bfced192c1e8fd3fa0250a0f93adfc061d7e71e5..415935739716df3b8b3319aac19519d29aaa5776 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -143,6 +143,21 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; - } - -+ // Paper start -+ public static Random SHARED_RANDOM = new Random() { -+ private boolean locked = false; -+ @Override -+ public synchronized void setSeed(long seed) { -+ if (locked) { -+ LogManager.getLogger().error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable()); -+ } else { -+ super.setSeed(seed); -+ locked = true; -+ } -+ } -+ }; -+ // Paper end -+ - private CraftEntity bukkitEntity; - - public CraftEntity getBukkitEntity() { -@@ -272,7 +287,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.x = Vec3D.ORIGIN; - this.am = 1.0F; - this.an = 1.0F; -- this.random = new Random(); -+ this.random = SHARED_RANDOM; // Paper - this.fireTicks = -this.getMaxFireTicks(); - this.M = new Object2DoubleArrayMap(2); - this.justCreated = true; diff --git a/Unmapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch b/Unmapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch deleted file mode 100644 index 768d4bc95d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 22 Mar 2016 12:04:28 -0500 -Subject: [PATCH] Configurable spawn chances for skeleton horses - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3c78d3234054ce2dc46ef77decb6adb0cbd10620..cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -230,4 +230,12 @@ public class PaperWorldConfig { - log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); - log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); - } -+ -+ public double skeleHorseSpawnChance; -+ private void skeleHorseSpawnChance() { -+ skeleHorseSpawnChance = getDouble("skeleton-horse-thunder-spawn-chance", 0.01D); -+ if (skeleHorseSpawnChance < 0) { -+ skeleHorseSpawnChance = 0.01D; // Vanilla value -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 3ea4ec748c229031a5f0d973988bb20e55679971..5cd864e58b85fa163489557437f5c2eec9f008b7 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -590,7 +590,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - blockposition = this.a(this.a(j, 0, k, 15)); - if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); -- boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * 0.01D; -+ boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper - - if (flag1) { - EntityHorseSkeleton entityhorseskeleton = (EntityHorseSkeleton) EntityTypes.SKELETON_HORSE.a((World) this); diff --git a/Unmapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/Unmapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch deleted file mode 100644 index 9f9e1ddd60..0000000000 --- a/Unmapped-Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch +++ /dev/null @@ -1,206 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 02:07:55 -0600 -Subject: [PATCH] Optimize isValidLocation, getType and getBlockData for - inlining - -Hot methods, so reduce # of instructions for the method. - -Move is valid location test to the BlockPosition class so that it can access local variables. - -Replace all calls to the new place to the unnecessary forward. - -Optimize getType and getBlockData to manually inline and optimize the calls - -diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java -index 25fdd55a7548cfaa45a541ad77f22f33c33e7471..4b56683336fdab06804efdc8ca1f7c130b77291f 100644 ---- a/src/main/java/net/minecraft/core/BaseBlockPosition.java -+++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java -@@ -22,6 +22,15 @@ public class BaseBlockPosition implements Comparable { - private int b;public final void setY(final int y) { this.b = y; } // Paper - OBFHELPER - private int e;public final void setZ(final int z) { this.e = z; } // Paper - OBFHELPER - -+ // Paper start -+ public boolean isValidLocation() { -+ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && getY() >= 0 && getY() < 256; -+ } -+ public boolean isInvalidYLocation() { -+ return b < 0 || b >= 256; -+ } -+ // Paper end -+ - public BaseBlockPosition(int i, int j, int k) { - this.a = i; - this.b = j; -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index a570998e4ef6c3ff83403881bf1d24c8cbcfcf67..a22be13b097052b2a88707c9436b88c84298e46b 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -239,7 +239,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - public static boolean isValidLocation(BlockPosition blockposition) { -- return !isOutsideWorld(blockposition) && D(blockposition); -+ return blockposition.isValidLocation(); // Paper - use better/optimized check - } - - public static boolean l(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 4b3de29b1a6e9d75b28962073c62bbe8d666165f..fdc491f978560c394eec22116572585f9bbdec9f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -348,12 +348,27 @@ public class Chunk implements IChunkAccess { - return this.sections; - } - -- @Override -+ // Paper start - Optimize getBlockData to reduce instructions -+ public final IBlockData getBlockData(BlockPosition pos) { return getBlockData(pos.getX(), pos.getY(), pos.getZ()); } // Paper - public IBlockData getType(BlockPosition blockposition) { -- int i = blockposition.getX(); -- int j = blockposition.getY(); -- int k = blockposition.getZ(); -+ return this.getBlockData(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ } -+ -+ public IBlockData getType(final int x, final int y, final int z) { -+ return getBlockData(x, y, z); -+ } -+ public final IBlockData getBlockData(final int x, final int y, final int z) { -+ // Method body / logic copied from below -+ final int i = y >> 4; -+ if (y < 0 || i >= this.sections.length || this.sections[i] == null || this.sections[i].nonEmptyBlockCount == 0) { -+ return Blocks.AIR.getBlockData(); -+ } -+ // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) -+ return this.sections[i].blockIds.a((y & 15) << 8 | (z & 15) << 4 | x & 15); -+ } - -+ public IBlockData getBlockData_unused(int i, int j, int k) { -+ // Paper end - if (this.world.isDebugWorld()) { - IBlockData iblockdata = null; - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -index 395d21afaabcbd99f9ce0551d647f5db9507a518..89efd0b68b04457e1cd617dcc8bb1a6ea1c4717c 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -@@ -23,7 +23,7 @@ import net.minecraft.world.phys.AxisAlignedBB; - - public class ChunkEmpty extends Chunk { - -- private static final BiomeBase[] b = (BiomeBase[]) SystemUtils.a((Object) (new BiomeBase[BiomeStorage.a]), (abiomebase) -> { -+ private static final BiomeBase[] b = SystemUtils.a((new BiomeBase[BiomeStorage.a]), (abiomebase) -> { // Paper - decompile error - Arrays.fill(abiomebase, BiomeRegistry.a); - }); - -@@ -31,6 +31,11 @@ public class ChunkEmpty extends Chunk { - super(world, chunkcoordintpair, new BiomeStorage(world.r().b(IRegistry.ay), ChunkEmpty.b)); - } - -+ // Paper start -+ @Override public IBlockData getType(int x, int y, int z) { -+ return Blocks.VOID_AIR.getBlockData(); -+ } -+ // Paper end - @Override - public IBlockData getType(BlockPosition blockposition) { - return Blocks.VOID_AIR.getBlockData(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index a4e2eb1a753e8fcb48982d78fe80e505bce5c476..eea4a30428293eaf7afbe303a37adec60b44c2b4 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -13,10 +13,10 @@ public class ChunkSection { - - public static final DataPalette GLOBAL_PALETTE = new DataPaletteGlobal<>(Block.REGISTRY_ID, Blocks.AIR.getBlockData()); - private final int yPos; -- private short nonEmptyBlockCount; -+ short nonEmptyBlockCount; // Paper - package-private - private short tickingBlockCount; - private short e; -- private final DataPaletteBlock blockIds; -+ final DataPaletteBlock blockIds; // Paper - package-private - - public ChunkSection(int i) { - this(i, (short) 0, (short) 0, (short) 0); -@@ -30,8 +30,8 @@ public class ChunkSection { - this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); - } - -- public IBlockData getType(int i, int j, int k) { -- return (IBlockData) this.blockIds.a(i, j, k); -+ public final IBlockData getType(int i, int j, int k) { // Paper -+ return this.blockIds.a(j << 8 | k << 4 | i); // Paper - inline - } - - public Fluid b(int i, int j, int k) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index e397b871b846c3a90bc75d0e1cf0683b6a3d0ca9..8928157b01bb4f0dfe043732777b33708c23cda7 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -133,7 +133,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - } - - public T a(int i, int j, int k) { -- return this.a(b(i, j, k)); -+ return this.a(j << 8 | k << 4 | i); // Paper - inline - } - - protected T a(int i) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -index 2cd04abd72f1135446182ad6294003e526f99a4b..e570dc58efa56bd0aa5ada5575b4054ee38d505e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -+++ b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -@@ -25,6 +25,7 @@ import org.apache.logging.log4j.LogManager; - - public interface IChunkAccess extends IBlockAccess, IStructureAccess { - -+ IBlockData getType(final int x, final int y, final int z); // Paper - @Nullable - IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag); - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 7572ca53a5cca8ca5085d18c24048b85dda4daa9..9eeb99a21a6ed7f71ff64cf4cfdff646d31abbcf 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -113,16 +113,18 @@ public class ProtoChunk implements IChunkAccess { - - @Override - public IBlockData getType(BlockPosition blockposition) { -- int i = blockposition.getY(); -- -- if (World.b(i)) { -+ return getType(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ } -+ // Paper start -+ public IBlockData getType(final int x, final int y, final int z) { -+ if (y < 0 || y >= 256) { - return Blocks.VOID_AIR.getBlockData(); - } else { -- ChunkSection chunksection = this.getSections()[i >> 4]; -- -- return ChunkSection.a(chunksection) ? Blocks.AIR.getBlockData() : chunksection.getType(blockposition.getX() & 15, i & 15, blockposition.getZ() & 15); -+ ChunkSection chunksection = this.getSections()[y >> 4]; -+ return chunksection == Chunk.EMPTY_CHUNK_SECTION || chunksection.c() ? Blocks.AIR.getBlockData() : chunksection.getType(x & 15, y & 15, z & 15); - } - } -+ // Paper end - - @Override - public Fluid getFluid(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -index c059d3d055c35b492680556e8605966e2caaf7fd..9351e6ba541d440c485b6e4a3209170c5756e31e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -@@ -42,6 +42,11 @@ public class ProtoChunkExtension extends ProtoChunk { - public IBlockData getType(BlockPosition blockposition) { - return this.a.getType(blockposition); - } -+ // Paper start -+ public final IBlockData getType(final int x, final int y, final int z) { -+ return this.a.getBlockData(x, y, z); -+ } -+ // Paper end - - @Override - public Fluid getFluid(BlockPosition blockposition) { diff --git a/Unmapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/Unmapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch deleted file mode 100644 index b10153a490..0000000000 --- a/Unmapped-Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 19:55:45 -0400 -Subject: [PATCH] Only process BlockPhysicsEvent if a plugin has a listener - -Saves on some object allocation and processing when no plugin listens to this - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index ed71de473d461528d74ca5b95c33b97e98128aff..b141c744b8ffbc37b09cb4347c4051a77bb7049e 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1292,6 +1292,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper - - this.methodProfiler.a(() -> { - return worldserver + " " + worldserver.getDimensionKey().a(); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 5cd864e58b85fa163489557437f5c2eec9f008b7..a82affb9ffd0b2a513dcbf29402e99b49ed95d63 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -196,6 +196,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - private int tickPosition; - public final Convertable.ConversionSession convertable; - public final UUID uuid; -+ public boolean hasPhysicsEvent = true; // Paper - - @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkProvider.getChunkAt(x, z, false); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index a22be13b097052b2a88707c9436b88c84298e46b..9236e480d21340d4295caa16dae34363e182f483 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -458,7 +458,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // CraftBukkit start - iblockdata1.b(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam - CraftWorld world = ((WorldServer) this).getWorld(); -- if (world != null) { -+ if (world != null && ((WorldServer)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); - this.getServer().getPluginManager().callEvent(event); - -@@ -560,7 +560,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - try { - // CraftBukkit start - CraftWorld world = ((WorldServer) this).getWorld(); -- if (world != null) { -+ if (world != null && ((WorldServer)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata), world.getBlockAt(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ())); - this.getServer().getPluginManager().callEvent(event); - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPlant.java b/src/main/java/net/minecraft/world/level/block/BlockPlant.java -index 33a5c5a4dc1478ab211dbb2e09df87570b06644f..97dfe5c5e3ea1d9691de87ffbf4b1a29a83a65b4 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPlant.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPlant.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; - - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.IBlockAccess; - import net.minecraft.world.level.IWorldReader; -@@ -23,7 +24,7 @@ public class BlockPlant extends Block { - public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { - // CraftBukkit start - if (!iblockdata.canPlace(generatoraccess, blockposition)) { -- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(generatoraccess, blockposition).isCancelled()) { -+ if (!(generatoraccess instanceof WorldServer && ((WorldServer) generatoraccess).hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(generatoraccess, blockposition).isCancelled()) { // Paper - return Blocks.AIR.getBlockData(); - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java b/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java -index ca22187625f7ac6c43b663fd4d66cbf0c943c655..1a5d29ecc9edc52bac14ed5d05ef5376fd5b8a9c 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java -@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; -@@ -83,7 +84,7 @@ public class BlockTallPlant extends BlockPlant { - - protected static void b(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman) { - // CraftBukkit start -- if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { -+ if (((WorldServer)world).hasPhysicsEvent && org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { // Paper - return; - } - // CraftBukkit end diff --git a/Unmapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch b/Unmapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch deleted file mode 100644 index 61e53caa2c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:32:58 -0400 -Subject: [PATCH] Entity AddTo/RemoveFrom World Events - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index a82affb9ffd0b2a513dcbf29402e99b49ed95d63..24a45e5ac9b17feb528e9a047d1ad1761569ebfa 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1214,7 +1214,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (entity instanceof EntityInsentient) { - this.navigators.remove(((EntityInsentient) entity).getNavigation()); - } -- -+ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - entity.valid = false; // CraftBukkit - } - -@@ -1252,6 +1252,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - entity.origin = entity.getBukkitEntity().getLocation(); - } - // Paper end -+ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - } - - } diff --git a/Unmapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch b/Unmapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch deleted file mode 100644 index aec9c86c64..0000000000 --- a/Unmapped-Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:46:14 -0400 -Subject: [PATCH] Configurable Chunk Inhabited Time - -Vanilla stores how long a chunk has been active on a server, and dynamically scales some -aspects of vanilla gameplay to this factor. - -For people who want all chunks to be treated equally, you can chose a fixed value. - -This allows to fine-tune vanilla gameplay. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0..74ba5dbb83c13ce1721619b755036a7864a1fb90 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -238,4 +238,14 @@ public class PaperWorldConfig { - skeleHorseSpawnChance = 0.01D; // Vanilla value - } - } -+ -+ public int fixedInhabitedTime; -+ private void fixedInhabitedTime() { -+ if (PaperConfig.version < 16) { -+ if (!config.getBoolean("world-settings.default.use-chunk-inhabited-timer", true)) config.set("world-settings.default.fixed-chunk-inhabited-time", 0); -+ if (!config.getBoolean("world-settings." + worldName + ".use-chunk-inhabited-timer", true)) config.set("world-settings." + worldName + ".fixed-chunk-inhabited-time", 0); -+ set("use-chunk-inhabited-timer", null); -+ } -+ fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index fdc491f978560c394eec22116572585f9bbdec9f..b6898cd6e6117fef65198db32b98a64c806811d4 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -1022,7 +1022,7 @@ public class Chunk implements IChunkAccess { - - @Override - public long getInhabitedTime() { -- return this.inhabitedTime; -+ return world.paperConfig.fixedInhabitedTime < 0 ? this.inhabitedTime : world.paperConfig.fixedInhabitedTime; // Paper - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch b/Unmapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch deleted file mode 100644 index 84caa9a7de..0000000000 --- a/Unmapped-Spigot-Server-Patches/0075-EntityPathfindEvent.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 21:22:26 -0400 -Subject: [PATCH] EntityPathfindEvent - -Fires when an Entity decides to start moving to a location. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java -index 942e03578836524ba746bc37699677eb06cc7803..703d06b2b29f1500301d82df78dc377141085145 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java -@@ -75,7 +75,7 @@ public class Navigation extends NavigationAbstract { - - @Override - public PathEntity a(Entity entity, int i) { -- return this.a(entity.getChunkCoordinates(), i); -+ return this.a(entity.getChunkCoordinates(), entity, i); // Paper - Forward target entity - } - - private int u() { -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index 8848a7552a0ef3944560a71f71620c6bd0f08c10..58225877ce4f2533c19d34e143ae374dc289bce5 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -10,6 +10,7 @@ import net.minecraft.core.BaseBlockPosition; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IPosition; - import net.minecraft.network.protocol.game.PacketDebug; -+import net.minecraft.server.MCUtil; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityInsentient; -@@ -28,7 +29,7 @@ import net.minecraft.world.phys.Vec3D; - - public abstract class NavigationAbstract { - -- protected final EntityInsentient a; -+ protected final EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER - protected final World b; - @Nullable - protected PathEntity c; -@@ -115,16 +116,26 @@ public abstract class NavigationAbstract { - - @Nullable - public PathEntity a(BlockPosition blockposition, int i) { -- return this.a(ImmutableSet.of(blockposition), 8, false, i); -+ // Paper start - add target parameter -+ return this.a(blockposition, null, i); -+ } -+ @Nullable public PathEntity a(BlockPosition blockposition, Entity target, int i) { -+ return this.a(ImmutableSet.of(blockposition), target, 8, false, i); -+ // Paper end - } - - @Nullable - public PathEntity a(Entity entity, int i) { -- return this.a(ImmutableSet.of(entity.getChunkCoordinates()), 16, true, i); -+ return this.a(ImmutableSet.of(entity.getChunkCoordinates()), entity, 16, true, i); // Paper - } - - @Nullable -+ // Paper start - Add target - protected PathEntity a(Set set, int i, boolean flag, int j) { -+ return this.a(set, null, i, flag, j); -+ } -+ @Nullable protected PathEntity a(Set set, Entity target, int i, boolean flag, int j) { -+ // Paper end - if (set.isEmpty()) { - return null; - } else if (this.a.locY() < 0.0D) { -@@ -134,6 +145,23 @@ public abstract class NavigationAbstract { - } else if (this.c != null && !this.c.c() && set.contains(this.p)) { - return this.c; - } else { -+ // Paper start - Pathfind event -+ boolean copiedSet = false; -+ for (BlockPosition possibleTarget : set) { -+ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), -+ MCUtil.toLocation(getEntity().world, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { -+ if (!copiedSet) { -+ copiedSet = true; -+ set = new java.util.HashSet<>(set); -+ } -+ // note: since we copy the set this remove call is safe, since we're iterating over the old copy -+ set.remove(possibleTarget); -+ if (set.isEmpty()) { -+ return null; -+ } -+ } -+ } -+ // Paper end - this.b.getMethodProfiler().enter("pathfind"); - float f = (float) this.a.b(GenericAttributes.FOLLOW_RANGE); - BlockPosition blockposition = flag ? this.a.getChunkCoordinates().up() : this.a.getChunkCoordinates(); -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java -index 2e1efe7a048f64d494260d10a4ae5dba86af5e6c..f5664b8c0762f775f3cd106d156eb74b48bcedc2 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java -@@ -37,7 +37,7 @@ public class NavigationFlying extends NavigationAbstract { - - @Override - public PathEntity a(Entity entity, int i) { -- return this.a(entity.getChunkCoordinates(), i); -+ return this.a(entity.getChunkCoordinates(), entity, i); // Paper - Forward target entity - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch b/Unmapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch deleted file mode 100644 index d60c778cea..0000000000 --- a/Unmapped-Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Antony Riley -Date: Tue, 29 Mar 2016 08:22:55 +0300 -Subject: [PATCH] Sanitise RegionFileCache and make configurable. - -RegionFileCache prior to this patch would close every single open region -file upon reaching a size of 256. -This patch modifies that behaviour so it closes the the least recently -used RegionFile. -The implementation uses a LinkedHashMap as an LRU cache (modified from HashMap). -The maximum size of the RegionFileCache is also made configurable. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 716f285e67019b8a62922d09c15883c99f9421aa..439dcc6effdc91830d2b7ede9063982998b37120 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -227,4 +227,9 @@ public class PaperConfig { - private static void loadPermsBeforePlugins() { - loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); - } -+ -+ public static int regionFileCacheSize = 256; -+ private static void regionFileCacheSize() { -+ regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index 8310dd6bfc04b8ac0a51545baa3a264e6cb42eac..75b10a3755392870d8f5b51239a09a0e7fd75a42 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -33,7 +33,7 @@ public final class RegionFileCache implements AutoCloseable { - if (regionfile != null) { - return regionfile; - } else { -- if (this.cache.size() >= 256) { -+ if (this.cache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable - ((RegionFile) this.cache.removeLast()).close(); - } - diff --git a/Unmapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch b/Unmapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch deleted file mode 100644 index 6086fc3ad7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 31 Mar 2016 19:17:58 -0400 -Subject: [PATCH] Do not load chunks for Pathfinding - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index 58225877ce4f2533c19d34e143ae374dc289bce5..d71a6e5991629ce59c8529d7cc8064960e385236 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -48,7 +48,7 @@ public abstract class NavigationAbstract { - private BlockPosition p; - private int q; - private float r; -- private final Pathfinder s; -+ private final Pathfinder s; public Pathfinder getPathfinder() { return this.s; } // Paper - OBFHELPER - private boolean t; - - public NavigationAbstract(EntityInsentient entityinsentient, World world) { -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -index 39cd22a820fdc4c75aefb625b45b0c8c6ce1f199..5784be69098805e4d550a0923ac8daa5aada73f9 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -@@ -20,7 +20,7 @@ public class Pathfinder { - - private final PathPoint[] a = new PathPoint[32]; - private final int b; -- private final PathfinderAbstract c; -+ private final PathfinderAbstract c; public PathfinderAbstract getPathfinder() { return this.c; } // Paper - OBFHELPER - private final Path d = new Path(); - - public Pathfinder(PathfinderAbstract pathfinderabstract, int i) { -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -index ed9c1dfbc84b9573784e6531186b3cd9513ddf75..d14f2800237c2a80912bf6f2d418a9ba9031070d 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -@@ -479,7 +479,12 @@ public class PathfinderNormal extends PathfinderAbstract { - for (int j1 = -1; j1 <= 1; ++j1) { - if (l != 0 || j1 != 0) { - blockposition_mutableblockposition.d(i + l, j + i1, k + j1); -- IBlockData iblockdata = iblockaccess.getType(blockposition_mutableblockposition); -+ // Paper start -+ IBlockData iblockdata = iblockaccess.getTypeIfLoaded(blockposition_mutableblockposition); -+ if (iblockdata == null) { -+ pathtype = PathType.BLOCKED; -+ } else { -+ // Paper end - - if (iblockdata.a(Blocks.CACTUS)) { - return PathType.DANGER_CACTUS; -@@ -496,6 +501,7 @@ public class PathfinderNormal extends PathfinderAbstract { - if (iblockaccess.getFluid(blockposition_mutableblockposition).a((Tag) TagsFluid.WATER)) { - return PathType.WATER_BORDER; - } -+ } // Paper - } - } - } -@@ -505,7 +511,8 @@ public class PathfinderNormal extends PathfinderAbstract { - } - - protected static PathType b(IBlockAccess iblockaccess, BlockPosition blockposition) { -- IBlockData iblockdata = iblockaccess.getType(blockposition); -+ IBlockData iblockdata = iblockaccess.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return PathType.BLOCKED; // Paper - Block block = iblockdata.getBlock(); - Material material = iblockdata.getMaterial(); - diff --git a/Unmapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch b/Unmapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch deleted file mode 100644 index 5eeb9183da..0000000000 --- a/Unmapped-Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 2 Apr 2016 05:09:16 -0400 -Subject: [PATCH] Add PlayerUseUnknownEntityEvent - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java -index 9f3f8568ef9484ba226deaa6429f819c325b7a26..ce63f3e5ac4d1a4311c0ebeb7574d999d45987d9 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java -@@ -11,7 +11,7 @@ import net.minecraft.world.phys.Vec3D; - - public class PacketPlayInUseEntity implements Packet { - -- private int a; -+ private int a; public int getEntityId() { return this.a; } // Paper - add accessor - private PacketPlayInUseEntity.EnumEntityUseAction action; - private Vec3D c; - private EnumHand d; -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index af0a7dc9464e1acf1451f45464bab8546207950e..d3938e1fbab0a01ae5045858b1f421e041b768e2 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2200,6 +2200,16 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - } - } -+ // Paper start - fire event -+ else { -+ this.server.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( -+ this.getPlayer(), -+ packetplayinuseentity.getEntityId(), -+ packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK, -+ packetplayinuseentity.c() == EnumHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND -+ )); -+ } -+ // Paper end - - } - diff --git a/Unmapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch b/Unmapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch deleted file mode 100644 index c5364da582..0000000000 --- a/Unmapped-Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 2 Apr 2016 20:37:03 -0400 -Subject: [PATCH] Fix reducedDebugInfo not initialized on client - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 46c516b9ff089a3c885d635244942fd5a6ecf132..9d327f1255dd9d6b11840f7bb8ffc302bc33dbcf 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -246,6 +246,7 @@ public abstract class PlayerList { - playerconnection.sendPacket(new PacketPlayOutHeldItemSlot(entityplayer.inventory.itemInHandIndex)); - playerconnection.sendPacket(new PacketPlayOutRecipeUpdate(this.server.getCraftingManager().b())); - playerconnection.sendPacket(new PacketPlayOutTags(this.server.getTagRegistry())); -+ playerconnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, (byte) (worldserver1.getGameRules().getBoolean(GameRules.REDUCED_DEBUG_INFO) ? 22 : 23))); // Paper - fix this rule not being initialized on the client - this.d(entityplayer); - entityplayer.getStatisticManager().c(); - entityplayer.getRecipeBook().a(entityplayer); diff --git a/Unmapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch b/Unmapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch deleted file mode 100644 index 78ce2d0001..0000000000 --- a/Unmapped-Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 Apr 2016 16:28:17 -0400 -Subject: [PATCH] Configurable Grass Spread Tick Rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 74ba5dbb83c13ce1721619b755036a7864a1fb90..db2dddd12f54e6d15916c4cee623676541de37fb 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -248,4 +248,10 @@ public class PaperWorldConfig { - } - fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); - } -+ -+ public int grassUpdateRate = 1; -+ private void grassUpdateRate() { -+ grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); -+ log("Grass Spread Tick Rate: " + grassUpdateRate); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java b/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java -index a98392f06e66959ec1b75df8d2ecf3b5267980af..712596420af83e6e1b9d147ae2fd8d8a1f36e1b9 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java -@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; - import java.util.Random; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsFluid; -@@ -41,6 +42,7 @@ public abstract class BlockDirtSnowSpreadable extends BlockDirtSnow { - - @Override - public void tick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { -+ if (this instanceof BlockGrass && worldserver.paperConfig.grassUpdateRate != 1 && (worldserver.paperConfig.grassUpdateRate < 1 || (MinecraftServer.currentTick + blockposition.hashCode()) % worldserver.paperConfig.grassUpdateRate != 0)) { return; } // Paper - if (!b(iblockdata, (IWorldReader) worldserver, blockposition)) { - // CraftBukkit start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, Blocks.DIRT.getBlockData()).isCancelled()) { diff --git a/Unmapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/Unmapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch deleted file mode 100644 index d855eabdf8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 Apr 2016 17:48:50 -0400 -Subject: [PATCH] Fix Cancelling BlockPlaceEvent triggering physics - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 9236e480d21340d4295caa16dae34363e182f483..8da8141c2320c0c1a9b95826a9be2dbe22e11c14 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -518,6 +518,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public void b(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1) {} - - public void applyPhysics(BlockPosition blockposition, Block block) { -+ if (captureBlockStates) { return; } // Paper - Cancel all physics during placement - this.a(blockposition.west(), block, blockposition); - this.a(blockposition.east(), block, blockposition); - this.a(blockposition.down(), block, blockposition); diff --git a/Unmapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch b/Unmapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch deleted file mode 100644 index 61a9ac3f61..0000000000 --- a/Unmapped-Spigot-Server-Patches/0082-Optimize-DataBits.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Apr 2016 21:38:58 -0400 -Subject: [PATCH] Optimize DataBits - -Remove Debug checks as these are super hot and causing noticeable hits - -Before: http://i.imgur.com/nQsMzAE.png -After: http://i.imgur.com/nJ46crB.png - -Optimize redundant converting of static fields into an unsigned long each call by precomputing it in ctor - -diff --git a/src/main/java/net/minecraft/util/DataBits.java b/src/main/java/net/minecraft/util/DataBits.java -index 0c0576c8730069fb5364d8383dec8ab7e698658d..c4f3b680512fb15cea01ad12d0a00c6e60bf34b7 100644 ---- a/src/main/java/net/minecraft/util/DataBits.java -+++ b/src/main/java/net/minecraft/util/DataBits.java -@@ -13,8 +13,8 @@ public class DataBits { - private final long d; - private final int e; - private final int f; -- private final int g; -- private final int h; -+ private final int g;private final long g_unsigned; // Paper - referenced in b(int) with 2 Integer.toUnsignedLong calls -+ private final int h;private final long h_unsigned; // Paper - private final int i; - - public DataBits(int i, int j) { -@@ -29,8 +29,8 @@ public class DataBits { - this.f = (char) (64 / i); - int k = 3 * (this.f - 1); - -- this.g = DataBits.a[k + 0]; -- this.h = DataBits.a[k + 1]; -+ this.g = DataBits.a[k + 0]; this.g_unsigned = Integer.toUnsignedLong(this.g); // Paper -+ this.h = DataBits.a[k + 1]; this.h_unsigned = Integer.toUnsignedLong(this.h); // Paper - this.i = DataBits.a[k + 2]; - int l = (j + this.f - 1) / this.f; - -@@ -47,15 +47,15 @@ public class DataBits { - } - - private int b(int i) { -- long j = Integer.toUnsignedLong(this.g); -- long k = Integer.toUnsignedLong(this.h); -+ //long j = Integer.toUnsignedLong(this.g); // Paper -+ //long k = Integer.toUnsignedLong(this.h); // Paper - -- return (int) ((long) i * j + k >> 32 >> this.i); -+ return (int) ((long) i * this.g_unsigned + this.h_unsigned >> 32 >> this.i); // Paper - } - -- public int a(int i, int j) { -- Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); -- Validate.inclusiveBetween(0L, this.d, (long) j); -+ public final int a(int i, int j) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper -+ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper - int k = this.b(i); - long l = this.b[k]; - int i1 = (i - k * this.f) * this.c; -@@ -65,9 +65,9 @@ public class DataBits { - return j1; - } - -- public void b(int i, int j) { -- Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); -- Validate.inclusiveBetween(0L, this.d, (long) j); -+ public final void b(int i, int j) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper -+ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper - int k = this.b(i); - long l = this.b[k]; - int i1 = (i - k * this.f) * this.c; -@@ -75,8 +75,8 @@ public class DataBits { - this.b[k] = l & ~(this.d << i1) | ((long) j & this.d) << i1; - } - -- public int a(int i) { -- Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); -+ public final int a(int i) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper - int j = this.b(i); - long k = this.b[j]; - int l = (i - j * this.f) * this.c; diff --git a/Unmapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/Unmapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch deleted file mode 100644 index 1cdc8fed9c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 6 Apr 2016 01:04:23 -0500 -Subject: [PATCH] Option to use vanilla per-world scoreboard coloring on names - -This change is basically a bandaid to fix CB's complete and utter lack -of support for vanilla scoreboard name modifications. - -In the future, finding a way to merge the vanilla expectations in with -bukkit's concept of a display name would be preferable. There was a PR -for this on CB at one point but I can't find it. We may need to do this -ourselves at some point in the future. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index db2dddd12f54e6d15916c4cee623676541de37fb..1942f5224aaebb18adb591d6f70a419cfc1a7bdd 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -254,4 +254,9 @@ public class PaperWorldConfig { - grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); - log("Grass Spread Tick Rate: " + grassUpdateRate); - } -+ -+ public boolean useVanillaScoreboardColoring; -+ private void useVanillaScoreboardColoring() { -+ useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); -+ } - } -diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -index 909968952a7ae2aa0196f12d1b3177cade380db2..1fcb01abc93c3c6ad172f209f55421d8b98629d5 100644 ---- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -@@ -17,7 +17,11 @@ import net.kyori.adventure.text.event.ClickEvent; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.world.scores.ScoreboardTeam; -+import net.minecraft.world.scores.ScoreboardTeamBase; - import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; -+import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.craftbukkit.util.LazyPlayerSet; - import org.bukkit.craftbukkit.util.Waitable; -@@ -179,10 +183,22 @@ public final class ChatProcessor { - } - - private static String legacyDisplayName(final CraftPlayer player) { -+ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { -+ final EntityPlayer ep = player.getHandle(); -+ IChatBaseComponent name = ep.getDisplayName(); -+ final ScoreboardTeamBase team = ep.getScoreboardTeam(); -+ if (team != null) { -+ name = team.getFormattedName(name); -+ } -+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(PaperAdventure.asAdventure(name)) + ChatColor.RESET; -+ } - return player.getDisplayName(); - } - - private static Component displayName(final CraftPlayer player) { -+ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { -+ return PaperAdventure.asAdventure(ScoreboardTeam.a(player.getHandle().getScoreboardTeam(), player.getHandle().getDisplayName())); -+ } - return player.displayName(); - } - diff --git a/Unmapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch b/Unmapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch deleted file mode 100644 index ec42a6a21a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 10 Apr 2016 03:23:32 -0500 -Subject: [PATCH] Workaround for setting passengers on players - -SPIGOT-1915 & GH-114 - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ab7e731cb04a75b829f0cd24d7b94f7ddad166e8..4bb57229c045956bab631982e12c0fc420db450e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -872,6 +872,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return true; - } - -+ // Paper start - Ugly workaround for SPIGOT-1915 & GH-114 -+ @Override -+ public boolean setPassenger(org.bukkit.entity.Entity passenger) { -+ boolean wasSet = super.setPassenger(passenger); -+ if (wasSet) { -+ this.getHandle().playerConnection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutMount(this.getHandle())); -+ } -+ return wasSet; -+ } -+ // Paper end -+ - @Override - public void setSneaking(boolean sneak) { - getHandle().setSneaking(sneak); diff --git a/Unmapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch b/Unmapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch deleted file mode 100644 index 8cdf182378..0000000000 --- a/Unmapped-Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 Apr 2016 00:25:28 -0400 -Subject: [PATCH] Remove unused World Tile Entity List - -Massive hit to performance and it is completely unnecessary. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 24a45e5ac9b17feb528e9a047d1ad1761569ebfa..75424a5dd6db57dded3b6d895e6b5b102e91c77e 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1721,7 +1721,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - bufferedwriter.write(String.format("entities: %d\n", this.entitiesById.size())); -- bufferedwriter.write(String.format("block_entities: %d\n", this.tileEntityList.size())); -+ bufferedwriter.write(String.format("block_entities: %d\n", this.tileEntityListTick.size())); // Paper - remove unused list - bufferedwriter.write(String.format("block_ticks: %d\n", this.getBlockTickList().a())); - bufferedwriter.write(String.format("fluid_ticks: %d\n", this.getFluidTickList().a())); - bufferedwriter.write("distance_manager: " + playerchunkmap.e().c() + "\n"); -@@ -1860,7 +1860,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - private void a(Writer writer) throws IOException { - CSVWriter csvwriter = CSVWriter.a().a("x").a("y").a("z").a("type").a(writer); -- Iterator iterator = this.tileEntityList.iterator(); -+ Iterator iterator = this.tileEntityListTick.iterator(); // Paper - remove unused list - - while (iterator.hasNext()) { - TileEntity tileentity = (TileEntity) iterator.next(); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 8da8141c2320c0c1a9b95826a9be2dbe22e11c14..cad86b0273c05767f78bcb3bdfaa9ea01e26af4e 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -91,7 +91,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public static final ResourceKey THE_NETHER = ResourceKey.a(IRegistry.L, new MinecraftKey("the_nether")); - public static final ResourceKey THE_END = ResourceKey.a(IRegistry.L, new MinecraftKey("the_end")); - private static final EnumDirection[] a = EnumDirection.values(); -- public final List tileEntityList = Lists.newArrayList(); -+ //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list - public final List tileEntityListTick = Lists.newArrayList(); - protected final List tileEntityListPending = Lists.newArrayList(); - protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); -@@ -683,9 +683,9 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - }, tileentity::getPosition}); - } - -- boolean flag = this.tileEntityList.add(tileentity); -+ boolean flag = true; // Paper - remove unused list - -- if (flag && tileentity instanceof ITickable) { -+ if (flag && tileentity instanceof ITickable && !this.tileEntityListTick.contains(tileentity)) { // Paper - this.tileEntityListTick.add(tileentity); - } - -@@ -721,7 +721,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - timings.tileEntityTick.startTiming(); // Spigot - if (!this.tileEntityListUnload.isEmpty()) { - this.tileEntityListTick.removeAll(this.tileEntityListUnload); -- this.tileEntityList.removeAll(this.tileEntityListUnload); -+ //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list - this.tileEntityListUnload.clear(); - } - -@@ -781,7 +781,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - tilesThisCycle--; - this.tileEntityListTick.remove(tileTickPosition--); - // Spigot end -- this.tileEntityList.remove(tileentity); -+ //this.tileEntityList.remove(tileentity); // Paper - remove unused list - if (this.isLoaded(tileentity.getPosition())) { - this.getChunkAtWorldCoords(tileentity.getPosition()).removeTileEntity(tileentity.getPosition()); - } -@@ -811,7 +811,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.notify(tileentity1.getPosition(), iblockdata, iblockdata, 3); - // CraftBukkit start - // From above, don't screw this up - SPIGOT-1746 -- if (!this.tileEntityList.contains(tileentity1)) { -+ if (true) { // Paper - remove unused list - this.a(tileentity1); - } - // CraftBukkit end -@@ -957,7 +957,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } else { - if (tileentity != null) { - this.tileEntityListPending.remove(tileentity); -- this.tileEntityList.remove(tileentity); -+ //this.tileEntityList.remove(tileentity); // Paper - remove unused list - this.tileEntityListTick.remove(tileentity); - } - diff --git a/Unmapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch b/Unmapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch deleted file mode 100644 index 26489896ab..0000000000 --- a/Unmapped-Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 Apr 2016 00:30:10 -0400 -Subject: [PATCH] Don't tick Skulls - unused code - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -index 87a5f352c8a6336c65008d6e21a771fd6332773c..22217f24b4a87f10b6d5a3e37d23a1164af84ace 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -@@ -33,7 +33,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.world.entity.player.EntityHuman; - // Spigot end - --public class TileEntitySkull extends TileEntity implements ITickable { -+public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Paper - remove tickable - - @Nullable - private static UserCache userCache; -@@ -136,7 +136,7 @@ public class TileEntitySkull extends TileEntity implements ITickable { - - } - -- @Override -+ // Paper - remove override - public void tick() { - IBlockData iblockdata = this.getBlock(); - diff --git a/Unmapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch b/Unmapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch deleted file mode 100644 index ceaba1942c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0087-Configurable-Player-Collision.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 Apr 2016 02:10:49 -0400 -Subject: [PATCH] Configurable Player Collision - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 439dcc6effdc91830d2b7ede9063982998b37120..504efea7b6f50a0d17f4f353781953dfb18bdeca 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -232,4 +232,9 @@ public class PaperConfig { - private static void regionFileCacheSize() { - regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); - } -+ -+ public static boolean enablePlayerCollisions = true; -+ private static void enablePlayerCollisions() { -+ enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); -+ } - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java -index bc40f2cbe1645fd60c4cee106b90f17cd043d32d..c1bb5c325286119891e8d68ce8f7328c99edb486 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java -@@ -112,7 +112,7 @@ public class PacketPlayOutScoreboardTeam implements Packet toRemove = scoreboard.getTeams().stream().filter(team -> team.getName().startsWith("collideRule_")).map(ScoreboardTeam::getName).collect(java.util.stream.Collectors.toList()); -+ for (String teamName : toRemove) { -+ scoreboard.removeTeam(scoreboard.getTeam(teamName)); // Clean up after ourselves -+ } -+ -+ if (!com.destroystokyo.paper.PaperConfig.enablePlayerCollisions) { -+ this.getPlayerList().collideRuleTeamName = org.apache.commons.lang3.StringUtils.left("collideRule_" + java.util.concurrent.ThreadLocalRandom.current().nextInt(), 16); -+ ScoreboardTeam collideTeam = scoreboard.createTeam(this.getPlayerList().collideRuleTeamName); -+ collideTeam.setCanSeeFriendlyInvisibles(false); // Because we want to mimic them not being on a team at all -+ } -+ // Paper end -+ - this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); - this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); - this.serverConnection.acceptConnections(); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 9d327f1255dd9d6b11840f7bb8ffc302bc33dbcf..49f1aed92fd5fa46b74a979f317a2eb0672991e9 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -86,6 +86,7 @@ import net.minecraft.world.level.storage.SavedFile; - import net.minecraft.world.level.storage.WorldData; - import net.minecraft.world.level.storage.WorldNBTStorage; - import net.minecraft.world.phys.Vec3D; -+import net.minecraft.world.scores.Scoreboard; - import net.minecraft.world.scores.ScoreboardObjective; - import net.minecraft.world.scores.ScoreboardTeam; - import net.minecraft.world.scores.ScoreboardTeamBase; -@@ -145,6 +146,7 @@ public abstract class PlayerList { - // CraftBukkit start - private CraftServer cserver; - private final Map playersByName = new java.util.HashMap<>(); -+ public @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule - - public PlayerList(MinecraftServer minecraftserver, IRegistryCustom.Dimension iregistrycustom_dimension, WorldNBTStorage worldnbtstorage, int i) { - this.cserver = minecraftserver.server = new CraftServer((DedicatedServer) minecraftserver, this); -@@ -376,6 +378,13 @@ public abstract class PlayerList { - } - - entityplayer.syncInventory(); -+ // Paper start - Add to collideRule team if needed -+ final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); -+ final ScoreboardTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName); -+ if (this.collideRuleTeamName != null && collideRuleTeam != null && entityplayer.getScoreboardTeam() == null) { -+ scoreboard.addPlayerToTeam(entityplayer.getName(), collideRuleTeam); -+ } -+ // Paper end - // CraftBukkit - Moved from above, added world - PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getDisplayName().getString(), s1, entityplayer.getId(), worldserver1.worldDataServer.getName(), entityplayer.locX(), entityplayer.locY(), entityplayer.locZ()); - } -@@ -496,6 +505,16 @@ public abstract class PlayerList { - entityplayer.playerTick(); // SPIGOT-924 - // CraftBukkit end - -+ // Paper start - Remove from collideRule team if needed -+ if (this.collideRuleTeamName != null) { -+ final Scoreboard scoreBoard = this.server.getWorldServer(World.OVERWORLD).getScoreboard(); -+ final ScoreboardTeam team = scoreBoard.getTeam(this.collideRuleTeamName); -+ if (entityplayer.getScoreboardTeam() == team && team != null) { -+ scoreBoard.removePlayerFromTeam(entityplayer.getName(), team); -+ } -+ } -+ // Paper end -+ - this.savePlayerFile(entityplayer); - if (entityplayer.isPassenger()) { - Entity entity = entityplayer.getRootVehicle(); -@@ -1144,6 +1163,13 @@ public abstract class PlayerList { - } - // CraftBukkit end - -+ // Paper start - Remove collideRule team if it exists -+ if (this.collideRuleTeamName != null) { -+ final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); -+ final ScoreboardTeam team = scoreboard.getTeam(this.collideRuleTeamName); -+ if (team != null) scoreboard.removeTeam(team); -+ } -+ // Paper end - } - - // CraftBukkit start diff --git a/Unmapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Unmapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch deleted file mode 100644 index 0648fd73b6..0000000000 --- a/Unmapped-Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 13 Apr 2016 20:21:38 -0700 -Subject: [PATCH] Add handshake event to allow plugins to handle client - handshaking logic themselves - - -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 9b24afa4f4fe41d2261b16aaecec2144ac7d049f..1164782be686c91379494b236ebded817a002a6f 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -29,7 +29,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - // CraftBukkit end - private static final IChatBaseComponent a = new ChatComponentText("Ignoring status request"); - private final MinecraftServer b; -- private final NetworkManager c; -+ private final NetworkManager c; final NetworkManager getNetworkManager() { return this.c; } // Paper - OBFHELPER - - public HandshakeListener(MinecraftServer minecraftserver, NetworkManager networkmanager) { - this.b = minecraftserver; -@@ -88,8 +88,35 @@ public class HandshakeListener implements PacketHandshakingInListener { - this.c.close(chatmessage); - } else { - this.c.setPacketListener(new LoginListener(this.b, this.c)); -+ // Paper start - handshake event -+ boolean proxyLogicEnabled = org.spigotmc.SpigotConfig.bungee; -+ boolean handledByEvent = false; -+ // Try and handle the handshake through the event -+ if (com.destroystokyo.paper.event.player.PlayerHandshakeEvent.getHandlerList().getRegisteredListeners().length != 0) { // Hello? Can you hear me? -+ java.net.SocketAddress socketAddress = this.getNetworkManager().socketAddress; -+ String hostnameOfRemote = socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getHostString() : InetAddress.getLoopbackAddress().getHostAddress(); -+ com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packethandshakinginsetprotocol.hostname, hostnameOfRemote, !proxyLogicEnabled); -+ if (event.callEvent()) { -+ // If we've failed somehow, let the client know so and go no further. -+ if (event.isFailed()) { -+ chatmessage = new ChatMessage(event.getFailMessage()); -+ this.getNetworkManager().sendPacket(new PacketLoginOutDisconnect(chatmessage)); -+ this.getNetworkManager().close(chatmessage); -+ return; -+ } -+ -+ if (event.getServerHostname() != null) packethandshakinginsetprotocol.hostname = event.getServerHostname(); -+ if (event.getSocketAddressHostname() != null) this.getNetworkManager().socketAddress = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); -+ this.getNetworkManager().spoofedUUID = event.getUniqueId(); -+ this.getNetworkManager().spoofedProfile = gson.fromJson(event.getPropertiesJson(), com.mojang.authlib.properties.Property[].class); -+ handledByEvent = true; // Hooray, we did it! -+ } -+ } -+ // Don't try and handle default logic if it's been handled by the event. -+ if (!handledByEvent && proxyLogicEnabled) { -+ // Paper end - // Spigot Start -- if (org.spigotmc.SpigotConfig.bungee) { -+ //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! - String[] split = packethandshakinginsetprotocol.hostname.split("\00"); - if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { - packethandshakinginsetprotocol.hostname = split[0]; diff --git a/Unmapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch b/Unmapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch deleted file mode 100644 index 05f3461032..0000000000 --- a/Unmapped-Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 16 Apr 2016 00:39:33 -0400 -Subject: [PATCH] Configurable RCON IP address - -For servers with multiple IP's, ability to bind to a specific interface. - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index 0ecff9f5e2ba444b196d80da341ff851dd5ce26f..b7cf02301c02ed0a6b696384e656426762ae2105 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -@@ -67,6 +67,8 @@ public class DedicatedServerProperties extends PropertyManager.EditableProperty whiteList; - public final GeneratorSettings generatorSettings; - -+ public final String rconIp; // Paper - Add rcon ip -+ - // CraftBukkit start - public DedicatedServerProperties(Properties properties, IRegistryCustom iregistrycustom, OptionSet optionset) { - super(properties, optionset); -@@ -118,6 +120,10 @@ public class DedicatedServerProperties extends PropertyManager> { - }; - } - -- @Nullable -- private String c(String s) { -+ @Nullable String getSettingIfExists(final String path) { return this.c(path); } // Paper - OBFHELPER -+ @Nullable private String c(String s) { // Paper - OBFHELPER - return (String) getOverride(s, this.properties.getProperty(s)); // CraftBukkit - } - -diff --git a/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java b/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java -index 797a450a08da1b799e32fae2a71a7a50bb90d127..3b3e21d1d86629d6c5e06108e53d1c5e807074d8 100644 ---- a/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java -+++ b/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java -@@ -62,7 +62,7 @@ public class RemoteControlListener extends RemoteConnectionThread { - @Nullable - public static RemoteControlListener a(IMinecraftServer iminecraftserver) { - DedicatedServerProperties dedicatedserverproperties = iminecraftserver.getDedicatedServerProperties(); -- String s = iminecraftserver.h_(); -+ String s = dedicatedserverproperties.rconIp; // Paper - Configurable rcon ip - - if (s.isEmpty()) { - s = "0.0.0.0"; diff --git a/Unmapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch b/Unmapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch deleted file mode 100644 index c379b25eba..0000000000 --- a/Unmapped-Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 17 Apr 2016 17:27:09 -0400 -Subject: [PATCH] Prevent Fire from loading chunks & wrongly spread - -This causes the nether to spam unload/reload chunks, plus overall -bad behavior. - -This also stops fire from spreading to illegal locations. - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java -index ee5400fd3e493e1f0518a9e47ddbc997e7a0fb92..c22fad0038fdb0769e23db782e3341206fbd80f9 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java -@@ -135,7 +135,7 @@ public class BlockFire extends BlockFireAbstract { - BlockStateBoolean blockstateboolean = (BlockStateBoolean) BlockFire.h.get(enumdirection); - - if (blockstateboolean != null) { -- iblockdata1 = (IBlockData) iblockdata1.set(blockstateboolean, this.e(iblockaccess.getType(blockposition.shift(enumdirection)))); -+ iblockdata1 = (IBlockData) iblockdata1.set(blockstateboolean, this.e(iblockaccess.getTypeIfLoaded(blockposition.shift(enumdirection)))); // Paper - prevent chunk loads - } - } - -@@ -215,6 +215,7 @@ public class BlockFire extends BlockFireAbstract { - } - - blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, l, j1, i1); -+ if (blockposition_mutableblockposition.isInvalidYLocation() || !worldserver.isLoaded(blockposition_mutableblockposition)) continue; // Paper - int l1 = this.a((IWorldReader) worldserver, (BlockPosition) blockposition_mutableblockposition); - - if (l1 > 0) { -@@ -260,10 +261,16 @@ public class BlockFire extends BlockFireAbstract { - } - - private void trySpread(World world, BlockPosition blockposition, int i, Random random, int j, BlockPosition sourceposition) { // CraftBukkit add sourceposition -- int k = this.getBurnChance(world.getType(blockposition)); -+ // Paper start -+ final IBlockData iblockdata = world.getTypeIfLoaded(blockposition); -+ if (iblockdata == null) { -+ return; -+ } -+ int k = this.getBurnChance(iblockdata); -+ // Paper end - - if (random.nextInt(i) < k) { -- IBlockData iblockdata = world.getType(blockposition); -+ //IBlockData iblockdata = world.getType(blockposition); // Paper - - // CraftBukkit start - org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -@@ -309,7 +316,7 @@ public class BlockFire extends BlockFireAbstract { - for (int j = 0; j < i; ++j) { - EnumDirection enumdirection = aenumdirection[j]; - -- if (this.e(iblockaccess.getType(blockposition.shift(enumdirection)))) { -+ if (this.e(iblockaccess.getTypeIfLoaded(blockposition.shift(enumdirection)))) { // Paper - prevent chunk loads - return true; - } - } -@@ -327,7 +334,12 @@ public class BlockFire extends BlockFireAbstract { - - for (int k = 0; k < j; ++k) { - EnumDirection enumdirection = aenumdirection[k]; -- IBlockData iblockdata = iworldreader.getType(blockposition.shift(enumdirection)); -+ // Paper start -+ IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition.shift(enumdirection)); -+ if (iblockdata == null) { -+ continue; -+ } -+ // Paper end - - i = Math.max(this.getFlameChance(iblockdata), i); - } -@@ -338,7 +350,7 @@ public class BlockFire extends BlockFireAbstract { - - @Override - protected boolean e(IBlockData iblockdata) { -- return this.getFlameChance(iblockdata) > 0; -+ return iblockdata != null && this.getFlameChance(iblockdata) > 0; // Paper - iblockdata can be nullable if chunk is unloaded now - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch deleted file mode 100644 index 56e55d42db..0000000000 --- a/Unmapped-Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Isaac Moore -Date: Tue, 19 Apr 2016 14:09:31 -0500 -Subject: [PATCH] Implement PlayerLocaleChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index cda0e7f8f9a9d66ac4e5a3f52609a4271bf0c4b5..3f1f8f7fe9452f66b18a08ef480d50ef78ad3351 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1695,7 +1695,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - return s; - } - -- public String locale = "en_us"; // CraftBukkit - add, lowercase -+ public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null - public java.util.Locale adventure$locale = java.util.Locale.US; // Paper - public void a(PacketPlayInSettings packetplayinsettings) { - // CraftBukkit start -@@ -1703,9 +1703,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT); - this.server.server.getPluginManager().callEvent(event); - } -- if (!this.locale.equals(packetplayinsettings.locale)) { -+ if (this.locale == null || !this.locale.equals(packetplayinsettings.locale)) { // Paper - check for null - PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), packetplayinsettings.locale); - this.server.server.getPluginManager().callEvent(event); -+ new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.locale, packetplayinsettings.locale).callEvent(); // Paper - } - this.locale = packetplayinsettings.locale; - // Paper start -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 4bb57229c045956bab631982e12c0fc420db450e..5698ef90bfeceec37eaf7f23361246ef125b3cd1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1877,8 +1877,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public String getLocale() { -- return getHandle().locale; -- -+ // Paper start - Locale change event -+ final String locale = getHandle().locale; -+ return locale != null ? locale : "en_us"; -+ // Paper end - } - - // Paper start diff --git a/Unmapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch b/Unmapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch deleted file mode 100644 index 43f4080f06..0000000000 --- a/Unmapped-Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 22 Apr 2016 01:43:11 -0500 -Subject: [PATCH] EntityRegainHealthEvent isFastRegen API - -Don't even get me started - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 375284b7e321cb03a7a30aedea165ca7a2fd1091..db5c0d2da9ed9993ee83adccfa74e77f4e364f2a 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -1130,10 +1130,16 @@ public abstract class EntityLiving extends Entity { - } - - public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { -+ // Paper start - Forward -+ heal(f, regainReason, false); -+ } -+ -+ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason, boolean isFastRegen) { -+ // Paper end - float f1 = this.getHealth(); - - if (f1 > 0.0F) { -- EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); -+ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason, isFastRegen); // Paper - // Suppress during worldgen - if (this.valid) { - this.world.getServer().getPluginManager().callEvent(event); -diff --git a/src/main/java/net/minecraft/world/food/FoodMetaData.java b/src/main/java/net/minecraft/world/food/FoodMetaData.java -index 7ed321acba6d46159f7d67b8d10a0a3e06ac88a9..e455b25b0809af15f6fde957121d0110da7eb08f 100644 ---- a/src/main/java/net/minecraft/world/food/FoodMetaData.java -+++ b/src/main/java/net/minecraft/world/food/FoodMetaData.java -@@ -87,7 +87,7 @@ public class FoodMetaData { - if (this.foodTickTimer >= this.saturatedRegenRate) { // CraftBukkit - float f = Math.min(this.saturationLevel, 6.0F); - -- entityhuman.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason -+ entityhuman.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED, true); // CraftBukkit - added RegainReason // Paper - This is fast regen - // this.a(f); CraftBukkit - EntityExhaustionEvent - entityhuman.applyExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent - this.foodTickTimer = 0; diff --git a/Unmapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch b/Unmapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch deleted file mode 100644 index c48a22b74f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Thu, 21 Apr 2016 23:51:55 -0700 -Subject: [PATCH] Add ability to configure frosted_ice properties - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1942f5224aaebb18adb591d6f70a419cfc1a7bdd..5baccb8d50c135ab20c38ffd0690f585514ce5af 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -259,4 +259,14 @@ public class PaperWorldConfig { - private void useVanillaScoreboardColoring() { - useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); - } -+ -+ public boolean frostedIceEnabled = true; -+ public int frostedIceDelayMin = 20; -+ public int frostedIceDelayMax = 40; -+ private void frostedIce() { -+ this.frostedIceEnabled = this.getBoolean("frosted-ice.enabled", this.frostedIceEnabled); -+ this.frostedIceDelayMin = this.getInt("frosted-ice.delay.min", this.frostedIceDelayMin); -+ this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); -+ log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -index 7239a30bd4a5dc4ed09802eea8f7126485ebb635..e32e94868386ff06ff29254e6cc3bee9b446a293 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -@@ -30,6 +30,7 @@ public class BlockIceFrost extends BlockIce { - - @Override - public void tickAlways(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { -+ if (!worldserver.paperConfig.frostedIceEnabled) return; // Paper - add ability to disable frosted ice - if ((random.nextInt(3) == 0 || this.a(worldserver, blockposition, 4)) && worldserver.getLightLevel(blockposition) > 11 - (Integer) iblockdata.get(BlockIceFrost.a) - iblockdata.b((IBlockAccess) worldserver, blockposition) && this.e(iblockdata, (World) worldserver, blockposition)) { - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); - EnumDirection[] aenumdirection = EnumDirection.values(); -@@ -42,12 +43,12 @@ public class BlockIceFrost extends BlockIce { - IBlockData iblockdata1 = worldserver.getType(blockposition_mutableblockposition); - - if (iblockdata1.a((Block) this) && !this.e(iblockdata1, (World) worldserver, blockposition_mutableblockposition)) { -- worldserver.getBlockTickList().a(blockposition_mutableblockposition, this, MathHelper.nextInt(random, 20, 40)); -+ worldserver.getBlockTickList().a(blockposition_mutableblockposition, this, MathHelper.nextInt(random, worldserver.paperConfig.frostedIceDelayMin, worldserver.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay - } - } - - } else { -- worldserver.getBlockTickList().a(blockposition, this, MathHelper.nextInt(random, 20, 40)); -+ worldserver.getBlockTickList().a(blockposition, this, MathHelper.nextInt(random, worldserver.paperConfig.frostedIceDelayMin, worldserver.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch b/Unmapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch deleted file mode 100644 index a59d0ec3f4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 28 Apr 2016 00:57:27 -0400 -Subject: [PATCH] remove null possibility for getServer singleton - -to stop IDE complaining about potential NPE - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 8df60cedc1198916dfce8fcea7ca4a49f98429ba..ed00ee8e56e6ca38a1ac689458c4675eff6e3eea 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -180,6 +180,7 @@ import org.spigotmc.SlackActivityAccountant; // Spigot - - public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { - -+ private static MinecraftServer SERVER; // Paper - public static final Logger LOGGER = LogManager.getLogger(); - public static final File b = new File("usercache.json"); - public static final WorldSettings c = new WorldSettings("Demo World", EnumGamemode.SURVIVAL, false, EnumDifficulty.NORMAL, false, new GameRules(), DataPackConfiguration.a); -@@ -286,6 +287,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Fri, 29 Apr 2016 20:02:00 -0400 -Subject: [PATCH] Improve Maps (in item frames) performance and bug fixes - -Maps used a modified version of rendering to support plugin controlled -imaging on maps. The Craft Map Renderer is much slower than Vanilla, -causing maps in item frames to cause a noticeable hit on server performance. - -This updates the map system to not use the Craft system if we detect that no -custom renderers are in use, defaulting to the much simpler Vanilla system. - -Additionally, numerous issues to player position tracking on maps has been fixed. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 75424a5dd6db57dded3b6d895e6b5b102e91c77e..c7652d6bff7630e2eefbb4c3b0deb6e17b9c98d0 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1170,6 +1170,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - { - if ( iter.next().trackee == entity ) - { -+ map.decorations.remove(entity.getDisplayName().getString()); // Paper - iter.remove(); - } - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index f42e16589476c1bd10b13214dda5ac7bb3e52131..e3e3426a00128b56d523bb43a59b814b915ad0ff 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -86,6 +86,7 @@ import net.minecraft.world.item.ItemElytra; - import net.minecraft.world.item.ItemProjectileWeapon; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.ItemSword; -+import net.minecraft.world.item.ItemWorldMap; - import net.minecraft.world.item.Items; - import net.minecraft.world.item.crafting.IRecipe; - import net.minecraft.world.item.enchantment.EnchantmentManager; -@@ -104,6 +105,7 @@ import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.block.entity.TileEntityStructure; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.block.state.pattern.ShapeDetectorBlock; -+import net.minecraft.world.level.saveddata.maps.WorldMap; - import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.Vec3D; - import net.minecraft.world.scores.Scoreboard; -@@ -689,6 +691,12 @@ public abstract class EntityHuman extends EntityLiving { - return null; - } - // CraftBukkit end -+ // Paper start - remove player from map on drop -+ if (itemstack.getItem() == Items.FILLED_MAP) { -+ WorldMap worldmap = ItemWorldMap.getSavedMap(itemstack, this.world); -+ worldmap.updateSeenPlayers(this, itemstack); -+ } -+ // Paper end - - return entityitem; - } -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -index 3f057f0bd23bc1c693c8f04ee8acd6626c620008..d470af1814af332595c1c0beb1cdc552e186a6bb 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -@@ -57,6 +57,7 @@ public class WorldMap extends PersistentBase { - private final Map m = Maps.newHashMap(); - public final Map decorations = Maps.newLinkedHashMap(); - private final Map n = Maps.newHashMap(); -+ private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper - - // CraftBukkit start - public final CraftMapView mapView; -@@ -69,6 +70,7 @@ public class WorldMap extends PersistentBase { - // CraftBukkit start - mapView = new CraftMapView(this); - server = (CraftServer) org.bukkit.Bukkit.getServer(); -+ vanillaRender.buffer = colors; // Paper - // CraftBukkit end - } - -@@ -136,6 +138,7 @@ public class WorldMap extends PersistentBase { - this.m.put(mapiconbanner.f(), mapiconbanner); - this.a(mapiconbanner.c(), (GeneratorAccess) null, mapiconbanner.f(), (double) mapiconbanner.a().getX(), (double) mapiconbanner.a().getZ(), 180.0D, mapiconbanner.d()); - } -+ this.vanillaRender.buffer = colors; // Paper - - NBTTagList nbttaglist1 = nbttagcompound.getList("frames", 10); - -@@ -216,6 +219,7 @@ public class WorldMap extends PersistentBase { - this.b(); - } - -+ public void updateSeenPlayers(EntityHuman entityhuman, ItemStack itemstack) { this.a(entityhuman, itemstack); } // Paper - OBFHELPER - public void a(EntityHuman entityhuman, ItemStack itemstack) { - if (!this.humans.containsKey(entityhuman)) { - WorldMap.WorldMapHumanTracker worldmap_worldmaphumantracker = new WorldMap.WorldMapHumanTracker(entityhuman); -@@ -451,6 +455,21 @@ public class WorldMap extends PersistentBase { - - public class WorldMapHumanTracker { - -+ // Paper start -+ private void addSeenPlayers(java.util.Collection icons) { -+ org.bukkit.entity.Player player = (org.bukkit.entity.Player) trackee.getBukkitEntity(); -+ WorldMap.this.decorations.forEach((name, mapIcon) -> { -+ // If this cursor is for a player check visibility with vanish system -+ org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayerExact(name); // Spigot -+ if (other == null || player.canSee(other)) { -+ icons.add(mapIcon); -+ } -+ }); -+ } -+ private boolean shouldUseVanillaMap() { -+ return mapView.getRenderers().size() == 1 && mapView.getRenderers().get(0).getClass() == org.bukkit.craftbukkit.map.CraftMapRenderer.class; -+ } -+ // Paper end - public final EntityHuman trackee; - private boolean d = true; - private int e; -@@ -467,9 +486,12 @@ public class WorldMap extends PersistentBase { - @Nullable - public Packet a(ItemStack itemstack) { - // CraftBukkit start -- org.bukkit.craftbukkit.map.RenderData render = WorldMap.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.trackee.getBukkitEntity()); // CraftBukkit -+ if (!this.d && this.i % 5 != 0) { this.i++; return null; } // Paper - this won't end up sending, so don't render it! -+ boolean vanillaMaps = shouldUseVanillaMap(); // Paper -+ org.bukkit.craftbukkit.map.RenderData render = !vanillaMaps ? WorldMap.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.trackee.getBukkitEntity()) : WorldMap.this.vanillaRender; // CraftBukkit // Paper - - java.util.Collection icons = new java.util.ArrayList(); -+ if (vanillaMaps) addSeenPlayers(icons); // Paper - - for ( org.bukkit.map.MapCursor cursor : render.cursors) { - -diff --git a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java -index 256a131781721c86dd6cdbc329335964570cbe8c..5768cd512ec166f1e8d1f4a28792015347297c3f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java -+++ b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java -@@ -5,7 +5,7 @@ import org.bukkit.map.MapCursor; - - public class RenderData { - -- public final byte[] buffer; -+ public byte[] buffer; // Paper - public final ArrayList cursors; - - public RenderData() { diff --git a/Unmapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch b/Unmapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch deleted file mode 100644 index 52eb70b9df..0000000000 --- a/Unmapped-Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch +++ /dev/null @@ -1,736 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 1 May 2016 21:19:14 -0400 -Subject: [PATCH] LootTable API & Replenishable Lootables Feature - -Provides an API to control the loot table for an object. -Also provides a feature that any Lootable Inventory (Chests in Structures) -can automatically replenish after a given time. - -This feature is good for long term worlds so that newer players -do not suffer with "Every chest has been looted" - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5baccb8d50c135ab20c38ffd0690f585514ce5af..eb04fdb172a50ec1f5b7fe78fa0e7655246abd60 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -269,4 +269,26 @@ public class PaperWorldConfig { - this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); - log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); - } -+ -+ public boolean autoReplenishLootables; -+ public boolean restrictPlayerReloot; -+ public boolean changeLootTableSeedOnFill; -+ public int maxLootableRefills; -+ public int lootableRegenMin; -+ public int lootableRegenMax; -+ private void enhancedLootables() { -+ autoReplenishLootables = getBoolean("lootables.auto-replenish", false); -+ restrictPlayerReloot = getBoolean("lootables.restrict-player-reloot", true); -+ changeLootTableSeedOnFill = getBoolean("lootables.reset-seed-on-fill", true); -+ maxLootableRefills = getInt("lootables.max-refills", -1); -+ lootableRegenMin = PaperConfig.getSeconds(getString("lootables.refresh-min", "12h")); -+ lootableRegenMax = PaperConfig.getSeconds(getString("lootables.refresh-max", "2d")); -+ if (autoReplenishLootables) { -+ log("Lootables: Replenishing every " + -+ PaperConfig.timeSummary(lootableRegenMin) + " to " + -+ PaperConfig.timeSummary(lootableRegenMax) + -+ (restrictPlayerReloot ? " (restricting reloot)" : "") -+ ); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5dfc3c8008d64ad4ed71b4904c897f5005491349 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java -@@ -0,0 +1,33 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.core.BlockPosition; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.entity.TileEntityLootable; -+import org.bukkit.Chunk; -+import org.bukkit.block.Block; -+ -+public interface PaperLootableBlockInventory extends LootableBlockInventory, PaperLootableInventory { -+ -+ TileEntityLootable getTileEntity(); -+ -+ @Override -+ default LootableInventory getAPILootableInventory() { -+ return this; -+ } -+ -+ @Override -+ default World getNMSWorld() { -+ return getTileEntity().getWorld(); -+ } -+ -+ default Block getBlock() { -+ final BlockPosition position = getTileEntity().getPosition(); -+ final Chunk bukkitChunk = getTileEntity().getWorld().getChunkAtWorldCoords(position).bukkitChunk; -+ return bukkitChunk.getBlock(position.getX(), position.getY(), position.getZ()); -+ } -+ -+ @Override -+ default PaperLootableInventoryData getLootableData() { -+ return getTileEntity().lootableData; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..019a06fa2b43cacd3bbd4d58aba71b3728f37581 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java -@@ -0,0 +1,28 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.world.level.World; -+import org.bukkit.entity.Entity; -+ -+public interface PaperLootableEntityInventory extends LootableEntityInventory, PaperLootableInventory { -+ -+ net.minecraft.world.entity.Entity getHandle(); -+ -+ @Override -+ default LootableInventory getAPILootableInventory() { -+ return this; -+ } -+ -+ default Entity getEntity() { -+ return getHandle().getBukkitEntity(); -+ } -+ -+ @Override -+ default World getNMSWorld() { -+ return getHandle().getWorld(); -+ } -+ -+ @Override -+ default PaperLootableInventoryData getLootableData() { -+ return getHandle().lootableData; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..59e8aea749bbba079e3304d9a5854280db2692e9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java -@@ -0,0 +1,71 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.world.level.World; -+import org.bukkit.loot.Lootable; -+ -+import java.util.UUID; -+ -+public interface PaperLootableInventory extends LootableInventory, Lootable { -+ -+ PaperLootableInventoryData getLootableData(); -+ LootableInventory getAPILootableInventory(); -+ -+ World getNMSWorld(); -+ -+ default org.bukkit.World getBukkitWorld() { -+ return getNMSWorld().getWorld(); -+ } -+ -+ @Override -+ default boolean isRefillEnabled() { -+ return getNMSWorld().paperConfig.autoReplenishLootables; -+ } -+ -+ @Override -+ default boolean hasBeenFilled() { -+ return getLastFilled() != -1; -+ } -+ -+ @Override -+ default boolean hasPlayerLooted(UUID player) { -+ return getLootableData().hasPlayerLooted(player); -+ } -+ -+ @Override -+ default Long getLastLooted(UUID player) { -+ return getLootableData().getLastLooted(player); -+ } -+ -+ @Override -+ default boolean setHasPlayerLooted(UUID player, boolean looted) { -+ final boolean hasLooted = hasPlayerLooted(player); -+ if (hasLooted != looted) { -+ getLootableData().setPlayerLootedState(player, looted); -+ } -+ return hasLooted; -+ } -+ -+ @Override -+ default boolean hasPendingRefill() { -+ long nextRefill = getLootableData().getNextRefill(); -+ return nextRefill != -1 && nextRefill > getLootableData().getLastFill(); -+ } -+ -+ @Override -+ default long getLastFilled() { -+ return getLootableData().getLastFill(); -+ } -+ -+ @Override -+ default long getNextRefill() { -+ return getLootableData().getNextRefill(); -+ } -+ -+ @Override -+ default long setNextRefill(long refillAt) { -+ if (refillAt < -1) { -+ refillAt = -1; -+ } -+ return getLootableData().setNextRefill(refillAt); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java -new file mode 100644 -index 0000000000000000000000000000000000000000..904332454ede006f4ee33337d46b11674d78bef7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java -@@ -0,0 +1,181 @@ -+package com.destroystokyo.paper.loottable; -+ -+import com.destroystokyo.paper.PaperWorldConfig; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; -+import net.minecraft.world.entity.player.EntityHuman; -+import org.bukkit.entity.Player; -+import org.bukkit.loot.LootTable; -+ -+import javax.annotation.Nullable; -+import java.util.HashMap; -+import java.util.Map; -+import java.util.Random; -+import java.util.UUID; -+ -+public class PaperLootableInventoryData { -+ -+ private static final Random RANDOM = new Random(); -+ -+ private long lastFill = -1; -+ private long nextRefill = -1; -+ private int numRefills = 0; -+ private Map lootedPlayers; -+ private final PaperLootableInventory lootable; -+ -+ public PaperLootableInventoryData(PaperLootableInventory lootable) { -+ this.lootable = lootable; -+ } -+ -+ long getLastFill() { -+ return this.lastFill; -+ } -+ -+ long getNextRefill() { -+ return this.nextRefill; -+ } -+ -+ long setNextRefill(long nextRefill) { -+ long prev = this.nextRefill; -+ this.nextRefill = nextRefill; -+ return prev; -+ } -+ -+ public boolean shouldReplenish(@Nullable EntityHuman player) { -+ LootTable table = this.lootable.getLootTable(); -+ -+ // No Loot Table associated -+ if (table == null) { -+ return false; -+ } -+ -+ // ALWAYS process the first fill or if the feature is disabled -+ if (this.lastFill == -1 || !this.lootable.getNMSWorld().paperConfig.autoReplenishLootables) { -+ return true; -+ } -+ -+ // Only process refills when a player is set -+ if (player == null) { -+ return false; -+ } -+ -+ // Chest is not scheduled for refill -+ if (this.nextRefill == -1) { -+ return false; -+ } -+ -+ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; -+ -+ // Check if max refills has been hit -+ if (paperConfig.maxLootableRefills != -1 && this.numRefills >= paperConfig.maxLootableRefills) { -+ return false; -+ } -+ -+ // Refill has not been reached -+ if (this.nextRefill > System.currentTimeMillis()) { -+ return false; -+ } -+ -+ -+ final Player bukkitPlayer = (Player) player.getBukkitEntity(); -+ LootableInventoryReplenishEvent event = new LootableInventoryReplenishEvent(bukkitPlayer, lootable.getAPILootableInventory()); -+ if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUniqueID())) { -+ event.setCancelled(true); -+ } -+ return event.callEvent(); -+ } -+ public void processRefill(@Nullable EntityHuman player) { -+ this.lastFill = System.currentTimeMillis(); -+ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; -+ if (paperConfig.autoReplenishLootables) { -+ int min = paperConfig.lootableRegenMin; -+ int max = paperConfig.lootableRegenMax; -+ this.nextRefill = this.lastFill + (min + RANDOM.nextInt(max - min + 1)) * 1000L; -+ this.numRefills++; -+ if (paperConfig.changeLootTableSeedOnFill) { -+ this.lootable.setSeed(0); -+ } -+ if (player != null) { // This means that numRefills can be incremented without a player being in the lootedPlayers list - Seems to be EntityMinecartChest specific -+ this.setPlayerLootedState(player.getUniqueID(), true); -+ } -+ } else { -+ this.lootable.clearLootTable(); -+ } -+ } -+ -+ -+ public void loadNbt(NBTTagCompound base) { -+ if (!base.hasKeyOfType("Paper.LootableData", 10)) { // 10 = compound -+ return; -+ } -+ NBTTagCompound comp = base.getCompound("Paper.LootableData"); -+ if (comp.hasKey("lastFill")) { -+ this.lastFill = comp.getLong("lastFill"); -+ } -+ if (comp.hasKey("nextRefill")) { -+ this.nextRefill = comp.getLong("nextRefill"); -+ } -+ -+ if (comp.hasKey("numRefills")) { -+ this.numRefills = comp.getInt("numRefills"); -+ } -+ if (comp.hasKeyOfType("lootedPlayers", 9)) { // 9 = list -+ NBTTagList list = comp.getList("lootedPlayers", 10); // 10 = compound -+ final int size = list.size(); -+ if (size > 0) { -+ this.lootedPlayers = new HashMap<>(list.size()); -+ } -+ for (int i = 0; i < size; i++) { -+ final NBTTagCompound cmp = list.getCompound(i); -+ lootedPlayers.put(cmp.getUUID("UUID"), cmp.getLong("Time")); -+ } -+ } -+ } -+ public void saveNbt(NBTTagCompound base) { -+ NBTTagCompound comp = new NBTTagCompound(); -+ if (this.nextRefill != -1) { -+ comp.setLong("nextRefill", this.nextRefill); -+ } -+ if (this.lastFill != -1) { -+ comp.setLong("lastFill", this.lastFill); -+ } -+ if (this.numRefills != 0) { -+ comp.setInt("numRefills", this.numRefills); -+ } -+ if (this.lootedPlayers != null && !this.lootedPlayers.isEmpty()) { -+ NBTTagList list = new NBTTagList(); -+ for (Map.Entry entry : this.lootedPlayers.entrySet()) { -+ NBTTagCompound cmp = new NBTTagCompound(); -+ cmp.setUUID("UUID", entry.getKey()); -+ cmp.setLong("Time", entry.getValue()); -+ list.add(cmp); -+ } -+ comp.set("lootedPlayers", list); -+ } -+ -+ if (!comp.isEmpty()) { -+ base.set("Paper.LootableData", comp); -+ } -+ } -+ -+ void setPlayerLootedState(UUID player, boolean looted) { -+ if (looted && this.lootedPlayers == null) { -+ this.lootedPlayers = new HashMap<>(); -+ } -+ if (looted) { -+ if (!this.lootedPlayers.containsKey(player)) { -+ this.lootedPlayers.put(player, System.currentTimeMillis()); -+ } -+ } else if (this.lootedPlayers != null) { -+ this.lootedPlayers.remove(player); -+ } -+ } -+ -+ boolean hasPlayerLooted(UUID player) { -+ return this.lootedPlayers != null && this.lootedPlayers.containsKey(player); -+ } -+ -+ Long getLastLooted(UUID player) { -+ return lootedPlayers != null ? lootedPlayers.get(player) : null; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c682bd7700d8103533026d46cfc63a7abde5a5f4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java -@@ -0,0 +1,62 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.vehicle.EntityMinecartContainer; -+import net.minecraft.world.level.World; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.util.CraftNamespacedKey; -+ -+public class PaperMinecartLootableInventory implements PaperLootableEntityInventory { -+ -+ private EntityMinecartContainer entity; -+ -+ public PaperMinecartLootableInventory(EntityMinecartContainer entity) { -+ this.entity = entity; -+ } -+ -+ @Override -+ public org.bukkit.loot.LootTable getLootTable() { -+ return entity.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.lootTable)) : null; -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { -+ setLootTable(table); -+ setSeed(seed); -+ } -+ -+ @Override -+ public void setSeed(long seed) { -+ entity.lootTableSeed = seed; -+ } -+ -+ @Override -+ public long getSeed() { -+ return entity.lootTableSeed; -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table) { -+ entity.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); -+ } -+ -+ @Override -+ public PaperLootableInventoryData getLootableData() { -+ return entity.lootableData; -+ } -+ -+ @Override -+ public Entity getHandle() { -+ return entity; -+ } -+ -+ @Override -+ public LootableInventory getAPILootableInventory() { -+ return (LootableInventory) entity.getBukkitEntity(); -+ } -+ -+ @Override -+ public World getNMSWorld() { -+ return entity.world; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9dae34370d014a291f025f83b55e18bff4619a23 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java -@@ -0,0 +1,65 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.entity.TileEntityLootable; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.util.CraftNamespacedKey; -+ -+public class PaperTileEntityLootableInventory implements PaperLootableBlockInventory { -+ private TileEntityLootable tileEntityLootable; -+ -+ public PaperTileEntityLootableInventory(TileEntityLootable tileEntityLootable) { -+ this.tileEntityLootable = tileEntityLootable; -+ } -+ -+ @Override -+ public org.bukkit.loot.LootTable getLootTable() { -+ return tileEntityLootable.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null; -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { -+ setLootTable(table); -+ setSeed(seed); -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table) { -+ tileEntityLootable.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); -+ } -+ -+ @Override -+ public void setSeed(long seed) { -+ tileEntityLootable.lootTableSeed = seed; -+ } -+ -+ @Override -+ public long getSeed() { -+ return tileEntityLootable.lootTableSeed; -+ } -+ -+ @Override -+ public PaperLootableInventoryData getLootableData() { -+ return tileEntityLootable.lootableData; -+ } -+ -+ @Override -+ public TileEntityLootable getTileEntity() { -+ return tileEntityLootable; -+ } -+ -+ @Override -+ public LootableInventory getAPILootableInventory() { -+ World world = tileEntityLootable.getWorld(); -+ if (world == null) { -+ return null; -+ } -+ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, tileEntityLootable.getPosition())).getState(); -+ } -+ -+ @Override -+ public World getNMSWorld() { -+ return tileEntityLootable.getWorld(); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 415935739716df3b8b3319aac19519d29aaa5776..092ee75f9527af25a48ab052659e3304986b50e0 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -158,6 +158,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - }; - // Paper end - -+ public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - - public CraftEntity getBukkitEntity() { -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java -index c4b970c37b1792ac0022936f2df4740183621a0d..0166d11cb540a536390f486e1069d6119d8d23d6 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java -@@ -46,6 +46,7 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - public long lootTableSeed; - - // CraftBukkit start -+ { this.lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperMinecartLootableInventory(this)); } // Paper - public List transaction = new java.util.ArrayList(); - private int maxStack = MAX_STACK; - -@@ -203,12 +204,13 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - @Override - protected void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); -+ this.lootableData.saveNbt(nbttagcompound); // Paper - if (this.lootTable != null) { - nbttagcompound.setString("LootTable", this.lootTable.toString()); - if (this.lootTableSeed != 0L) { - nbttagcompound.setLong("LootTableSeed", this.lootTableSeed); - } -- } else { -+ } if (true) { // Paper - Always save the items, Table may stick around - ContainerUtil.a(nbttagcompound, this.items); - } - -@@ -217,11 +219,12 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - @Override - protected void loadData(NBTTagCompound nbttagcompound) { - super.loadData(nbttagcompound); -+ this.lootableData.loadNbt(nbttagcompound); // Paper - this.items = NonNullList.a(this.getSize(), ItemStack.b); - if (nbttagcompound.hasKeyOfType("LootTable", 8)) { - this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable")); - this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); -- } else { -+ } if (true) { // Paper - always load the items, table may still remain - ContainerUtil.b(nbttagcompound, this.items); - } - -@@ -252,14 +255,15 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - } - - public void d(@Nullable EntityHuman entityhuman) { -- if (this.lootTable != null && this.world.getMinecraftServer() != null) { -+ if (this.lootableData.shouldReplenish(entityhuman) && this.world.getMinecraftServer() != null) { // Paper - LootTable loottable = this.world.getMinecraftServer().getLootTableRegistry().getLootTable(this.lootTable); - - if (entityhuman instanceof EntityPlayer) { - CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable); - } - -- this.lootTable = null; -+ //this.lootTable = null; // Paper -+ this.lootableData.processRefill(entityhuman); // Paper - LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).set(LootContextParameters.ORIGIN, this.getPositionVector()).a(this.lootTableSeed); - - if (entityhuman != null) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -index 62e6833a90d7adae3c7df33e3bc73b4288e0370b..1508e267a38555820e2d31f3075adca185fbd4b6 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -@@ -27,6 +27,7 @@ public abstract class TileEntityLootable extends TileEntityContainer { - @Nullable - public MinecraftKey lootTable; - public long lootTableSeed; -+ public final com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperTileEntityLootableInventory(this)); // Paper - - protected TileEntityLootable(TileEntityTypes tileentitytypes) { - super(tileentitytypes); -@@ -42,16 +43,19 @@ public abstract class TileEntityLootable extends TileEntityContainer { - } - - protected boolean b(NBTTagCompound nbttagcompound) { -+ this.lootableData.loadNbt(nbttagcompound); // Paper - if (nbttagcompound.hasKeyOfType("LootTable", 8)) { - this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable")); -+ try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate - this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); -- return true; -+ return false; // Paper - always load the items, table may still remain - } else { - return false; - } - } - - protected boolean c(NBTTagCompound nbttagcompound) { -+ this.lootableData.saveNbt(nbttagcompound); // Paper - if (this.lootTable == null) { - return false; - } else { -@@ -60,19 +64,20 @@ public abstract class TileEntityLootable extends TileEntityContainer { - nbttagcompound.setLong("LootTableSeed", this.lootTableSeed); - } - -- return true; -+ return false; // Paper - always save the items, table may still remain - } - } - - public void d(@Nullable EntityHuman entityhuman) { -- if (this.lootTable != null && this.world.getMinecraftServer() != null) { -+ if (this.lootableData.shouldReplenish(entityhuman) && this.world.getMinecraftServer() != null) { // Paper - LootTable loottable = this.world.getMinecraftServer().getLootTableRegistry().getLootTable(this.lootTable); - - if (entityhuman instanceof EntityPlayer) { - CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable); - } - -- this.lootTable = null; -+ //this.lootTable = null; // Paper -+ this.lootableData.processRefill(entityhuman); // Paper - LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).set(LootContextParameters.ORIGIN, Vec3D.a((BaseBlockPosition) this.position)).a(this.lootTableSeed); - - if (entityhuman != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 524f27830752f424493c3ae8d793b871f6495594..dcf3f9265b0b00a7bbb9ff428e10da3c198ba08a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -64,7 +64,7 @@ public class CraftBlockEntityState extends CraftBlockState - } - - // gets the wrapped TileEntity -- protected T getTileEntity() { -+ public T getTileEntity() { // Paper - protected -> public - return tileEntity; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -index 486fa8937d644f59a770db163482259525a7e465..54eb170fd533b0e91572601268fcbc167ed9bb5c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -@@ -12,8 +12,9 @@ import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.inventory.CraftInventory; - import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest; - import org.bukkit.inventory.Inventory; -+import com.destroystokyo.paper.loottable.PaperLootableBlockInventory; // Paper - --public class CraftChest extends CraftLootable implements Chest { -+public class CraftChest extends CraftLootable implements Chest, PaperLootableBlockInventory { // Paper - - public CraftChest(final Block block) { - super(block, TileEntityChest.class); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -index f0a7e61a26c4668a9aa823d641f29bdecd42dd1f..3512054ede5fd1dd7605444e827e30a0be47f935 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -@@ -10,7 +10,7 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; - import org.bukkit.loot.LootTable; - import org.bukkit.loot.Lootable; - --public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable { -+public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable, com.destroystokyo.paper.loottable.PaperLootableBlockInventory { // Paper - - public CraftLootable(Block block, Class tileEntityClass) { - super(block, tileEntityClass); -@@ -54,7 +54,7 @@ public abstract class CraftLootable extends CraftC - setLootTable(getLootTable(), seed); - } - -- private void setLootTable(LootTable table, long seed) { -+ public void setLootTable(LootTable table, long seed) { // Paper - public - MinecraftKey key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); - getSnapshot().setLootTable(key, seed); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -index cbd121c21adfaf098dadca33de16a2e68d83c19a..d9a2552782c9242fb84cc0c8309a614a44777509 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -@@ -8,7 +8,7 @@ import org.bukkit.entity.minecart.StorageMinecart; - import org.bukkit.inventory.Inventory; - - @SuppressWarnings("deprecation") --public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart { -+public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper - private final CraftInventory inventory; - - public CraftMinecartChest(CraftServer server, EntityMinecartChest entity) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -index 5ffb8108f456c2f7f3ed1a25249baccb4cbf4add..bf8b5b25d1af0c5129261e10abf2866521b2c375 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -@@ -47,7 +47,7 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo - return getHandle().lootTableSeed; - } - -- private void setLootTable(LootTable table, long seed) { -+ public void setLootTable(LootTable table, long seed) { // Paper - MinecraftKey newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); - getHandle().setLootTable(newKey, seed); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -index 17a42aec76f32a28b0c9885c60d1ed50c6727161..bfdcf01d2c6570493e86330d56500427dbb23146 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -@@ -7,7 +7,7 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.minecart.HopperMinecart; - import org.bukkit.inventory.Inventory; - --public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart { -+public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper - private final CraftInventory inventory; - - public CraftMinecartHopper(CraftServer server, EntityMinecartHopper entity) { diff --git a/Unmapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/Unmapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch deleted file mode 100644 index a61442ff71..0000000000 --- a/Unmapped-Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 May 2016 23:33:08 -0400 -Subject: [PATCH] Don't save empty scoreboard teams to scoreboard.dat - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 504efea7b6f50a0d17f4f353781953dfb18bdeca..1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -237,4 +237,9 @@ public class PaperConfig { - private static void enablePlayerCollisions() { - enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); - } -+ -+ public static boolean saveEmptyScoreboardTeams = false; -+ private static void saveEmptyScoreboardTeams() { -+ saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java b/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java -index 3998565ccd87c966c0fb9e6757cd1861faa5bc15..52f27bdbd0df8bbbf2ad5144bc262b5093d83413 100644 ---- a/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java -+++ b/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java -@@ -182,6 +182,7 @@ public class PersistentScoreboard extends PersistentBase { - - while (iterator.hasNext()) { - ScoreboardTeam scoreboardteam = (ScoreboardTeam) iterator.next(); -+ if (!com.destroystokyo.paper.PaperConfig.saveEmptyScoreboardTeams && scoreboardteam.getPlayerNameSet().isEmpty()) continue; // Paper - NBTTagCompound nbttagcompound = new NBTTagCompound(); - - nbttagcompound.setString("Name", scoreboardteam.getName()); diff --git a/Unmapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch b/Unmapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch deleted file mode 100644 index 1cbedf26ca..0000000000 --- a/Unmapped-Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 12 May 2016 23:02:58 -0500 -Subject: [PATCH] System property for disabling watchdoge - - -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 69e5054886b5858664fed333aca8c25a76e5cb11..4e0291be4bd5876bb5b5f62ebfa156635d4c758f 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -61,7 +61,7 @@ public class WatchdogThread extends Thread - while ( !stopping ) - { - // -- if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime ) -+ if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable - { - Logger log = Bukkit.getServer().getLogger(); - log.log( Level.SEVERE, "------------------------------" ); diff --git a/Unmapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch b/Unmapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch deleted file mode 100644 index a7c61c2859..0000000000 --- a/Unmapped-Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 16 May 2016 20:47:41 -0400 -Subject: [PATCH] Optimize UserCache / Thread Safe - -Because Techable keeps complaining about how this isn't thread safe, -easier to do this than replace the entire thing. - -Additionally, move Saving of the User cache to be done async, incase -the user never changed the default setting for Spigot's save on stop only. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index ed00ee8e56e6ca38a1ac689458c4675eff6e3eea..20dffd9dc4cb3868638151b70535f353a3bf1a44 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -907,7 +907,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { // Paper - - try { - BufferedWriter bufferedwriter = Files.newWriter(this.g, StandardCharsets.UTF_8); -@@ -268,6 +270,14 @@ public class UserCache { - } catch (IOException ioexception) { - ; - } -+ // Paper start -+ }; -+ if (asyncSave) { -+ MCUtil.scheduleAsyncTask(save); -+ } else { -+ save.run(); -+ } -+ // Paper end - - } - diff --git a/Unmapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch b/Unmapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch deleted file mode 100644 index dd0b2f44b9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 16 May 2016 23:19:16 -0400 -Subject: [PATCH] Avoid blocking on Network Manager creation - -Per Paper issue 294 - -diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java -index f66a5ba901601c1d359a287861a2edd8e3a106a7..d992cb5cd827e0fe655809e1088939cdad9c2301 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnection.java -@@ -52,6 +52,15 @@ public class ServerConnection { - public volatile boolean c; - private final List listeningChannels = Collections.synchronizedList(Lists.newArrayList()); - private final List connectedChannels = Collections.synchronizedList(Lists.newArrayList()); -+ // Paper start - prevent blocking on adding a new network manager while the server is ticking -+ private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private void addPending() { -+ NetworkManager manager = null; -+ while ((manager = pending.poll()) != null) { -+ connectedChannels.add(manager); -+ } -+ } -+ // Paper end - - public ServerConnection(MinecraftServer minecraftserver) { - this.e = minecraftserver; -@@ -87,7 +96,8 @@ public class ServerConnection { - int j = ServerConnection.this.e.k(); - Object object = j > 0 ? new NetworkManagerServer(j) : new NetworkManager(EnumProtocolDirection.SERVERBOUND); - -- ServerConnection.this.connectedChannels.add((NetworkManager) object); // CraftBukkit - decompile error -+ //ServerConnection.this.connectedChannels.add((NetworkManager) object); // CraftBukkit - decompile error -+ pending.add((NetworkManager) object); // Paper - channel.pipeline().addLast("packet_handler", (ChannelHandler) object); - ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object)); - } -@@ -126,6 +136,7 @@ public class ServerConnection { - - synchronized (this.connectedChannels) { - // Spigot Start -+ this.addPending(); // Paper - // This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order - if ( org.spigotmc.SpigotConfig.playerShuffle > 0 && MinecraftServer.currentTick % org.spigotmc.SpigotConfig.playerShuffle == 0 ) - { diff --git a/Unmapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch b/Unmapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch deleted file mode 100644 index 8f5d535c75..0000000000 --- a/Unmapped-Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 22 May 2016 20:20:55 -0500 -Subject: [PATCH] Optional TNT doesn't move in water - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index eb04fdb172a50ec1f5b7fe78fa0e7655246abd60..6eca3f300020006f02dd36253b522db442e3cc33 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -2,7 +2,6 @@ package com.destroystokyo.paper; - - import java.util.List; - --import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -291,4 +290,14 @@ public class PaperWorldConfig { - ); - } - } -+ -+ public boolean preventTntFromMovingInWater; -+ private void preventTntFromMovingInWater() { -+ if (PaperConfig.version < 13) { -+ boolean oldVal = getBoolean("enable-old-tnt-cannon-behaviors", false); -+ set("prevent-tnt-from-moving-in-water", oldVal); -+ } -+ preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); -+ log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index beb0beb716869978be6bc5a78ce3b6cf785c5aee..e3cdea3c85d762af6984f3dbe544fdfe101f6ff6 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -67,7 +67,7 @@ public class EntityTrackerEntry { - private boolean q; - private boolean r; - // CraftBukkit start -- private final Set trackedPlayers; -+ final Set trackedPlayers; // Paper - private -> package - // Paper start - private java.util.Map trackedPlayerMap = null; - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 092ee75f9527af25a48ab052659e3304986b50e0..d314cdd9341e6aa5748a5b1afdd9569bec956c74 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2771,6 +2771,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean bV() { -+ // Paper start -+ return this.pushedByWater(); -+ } -+ public boolean pushedByWater() { -+ // Paper end - return true; - } - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -index 535e7d7297d81026b8586d5049b72fa65519b464..63b35feac07f01b200dd68c4836ceb419e951660 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -@@ -4,10 +4,14 @@ import javax.annotation.Nullable; - import net.minecraft.core.particles.Particles; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport; -+import net.minecraft.network.protocol.game.PacketPlayOutEntityVelocity; - import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.EntityPose; -@@ -96,7 +100,27 @@ public class EntityTNTPrimed extends Entity { - this.world.addParticle(Particles.SMOKE, this.locX(), this.locY() + 0.5D, this.locZ(), 0.0D, 0.0D, 0.0D); - } - } -- -+ // Paper start - Optional prevent TNT from moving in water -+ if (!this.dead && this.inWater && this.world.paperConfig.preventTntFromMovingInWater) { -+ /* -+ * Author: Jedediah Smith -+ */ -+ // Send position and velocity updates to nearby players on every tick while the TNT is in water. -+ // This does pretty well at keeping their clients in sync with the server. -+ PlayerChunkMap.EntityTracker ete = ((WorldServer)this.world).getChunkProvider().playerChunkMap.trackedEntities.get(this.getId()); -+ if (ete != null) { -+ PacketPlayOutEntityVelocity velocityPacket = new PacketPlayOutEntityVelocity(this); -+ PacketPlayOutEntityTeleport positionPacket = new PacketPlayOutEntityTeleport(this); -+ -+ ete.trackedPlayers.stream() -+ .filter(viewer -> (viewer.locX() - this.locX()) * (viewer.locY() - this.locY()) * (viewer.locZ() - this.locZ()) < 16 * 16) -+ .forEach(viewer -> { -+ viewer.playerConnection.sendPacket(velocityPacket); -+ viewer.playerConnection.sendPacket(positionPacket); -+ }); -+ } -+ } -+ // Paper end - } - - private void explode() { -@@ -165,4 +189,11 @@ public class EntityTNTPrimed extends Entity { - public Packet P() { - return new PacketPlayOutSpawnEntity(this); - } -+ -+ // Paper start - Optional prevent TNT from moving in water -+ @Override -+ public boolean pushedByWater() { -+ return !world.paperConfig.preventTntFromMovingInWater && super.pushedByWater(); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch b/Unmapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch deleted file mode 100644 index 7aa9554cd7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Panzer -Date: Mon, 23 May 2016 12:12:37 +0200 -Subject: [PATCH] Faster redstone torch rapid clock removal - -Only resize the the redstone torch list once, since resizing arrays / lists is costly - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index cad86b0273c05767f78bcb3bdfaa9ea01e26af4e..d8ab2e22a5c0144decb5c657a123cc61722fcbf5 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -44,6 +44,7 @@ import net.minecraft.world.level.biome.BiomeBase; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.BlockFireAbstract; -+import net.minecraft.world.level.block.BlockRedstoneTorch; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.ITickable; - import net.minecraft.world.level.block.entity.TileEntity; -@@ -142,6 +143,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - private org.spigotmc.TickLimiter tileLimiter; - private int tileTickPosition; - public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions -+ public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here - - public CraftWorld getWorld() { - return this.world; -diff --git a/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java b/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java -index 8142c0be2978d8975612488b17da9c2e25f3b5dd..6771c16b4228c1495950484422b73928f6184929 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java -@@ -22,7 +22,7 @@ import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit - public class BlockRedstoneTorch extends BlockTorch { - - public static final BlockStateBoolean LIT = BlockProperties.r; -- private static final Map> b = new WeakHashMap(); -+ // Paper - Move the mapped list to World - - protected BlockRedstoneTorch(BlockBase.Info blockbase_info) { - super(blockbase_info, ParticleParamRedstone.a); -@@ -69,11 +69,15 @@ public class BlockRedstoneTorch extends BlockTorch { - @Override - public void tickAlways(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { - boolean flag = this.a((World) worldserver, blockposition, iblockdata); -- List list = (List) BlockRedstoneTorch.b.get(worldserver); -- -- while (list != null && !list.isEmpty() && worldserver.getTime() - ((BlockRedstoneTorch.RedstoneUpdateInfo) list.get(0)).b > 60L) { -- list.remove(0); -+ // Paper start -+ java.util.ArrayDeque redstoneUpdateInfos = worldserver.redstoneUpdateInfos; -+ if (redstoneUpdateInfos != null) { -+ BlockRedstoneTorch.RedstoneUpdateInfo curr; -+ while ((curr = redstoneUpdateInfos.peek()) != null && worldserver.getTime() - curr.getTime() > 60L) { -+ redstoneUpdateInfos.poll(); -+ } - } -+ // Paper end - - // CraftBukkit start - org.bukkit.plugin.PluginManager manager = worldserver.getServer().getPluginManager(); -@@ -138,9 +142,12 @@ public class BlockRedstoneTorch extends BlockTorch { - } - - private static boolean a(World world, BlockPosition blockposition, boolean flag) { -- List list = (List) BlockRedstoneTorch.b.computeIfAbsent(world, (iblockaccess) -> { -- return Lists.newArrayList(); -- }); -+ // Paper start -+ java.util.ArrayDeque list = world.redstoneUpdateInfos; -+ if (list == null) { -+ list = world.redstoneUpdateInfos = new java.util.ArrayDeque<>(); -+ } -+ - - if (flag) { - list.add(new BlockRedstoneTorch.RedstoneUpdateInfo(blockposition.immutableCopy(), world.getTime())); -@@ -148,9 +155,9 @@ public class BlockRedstoneTorch extends BlockTorch { - - int i = 0; - -- for (int j = 0; j < list.size(); ++j) { -- BlockRedstoneTorch.RedstoneUpdateInfo blockredstonetorch_redstoneupdateinfo = (BlockRedstoneTorch.RedstoneUpdateInfo) list.get(j); -- -+ for (java.util.Iterator iterator = list.iterator(); iterator.hasNext();) { -+ BlockRedstoneTorch.RedstoneUpdateInfo blockredstonetorch_redstoneupdateinfo = iterator.next(); -+ // Paper end - if (blockredstonetorch_redstoneupdateinfo.a.equals(blockposition)) { - ++i; - if (i >= 8) { -@@ -165,7 +172,7 @@ public class BlockRedstoneTorch extends BlockTorch { - public static class RedstoneUpdateInfo { - - private final BlockPosition a; -- private final long b; -+ private final long b; final long getTime() { return this.b; } // Paper - OBFHELPER - - public RedstoneUpdateInfo(BlockPosition blockposition, long i) { - this.a = blockposition; diff --git a/Unmapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch b/Unmapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch deleted file mode 100644 index 50ec621547..0000000000 --- a/Unmapped-Spigot-Server-Patches/0103-Add-server-name-parameter.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Panzer -Date: Sat, 28 May 2016 16:54:03 +0200 -Subject: [PATCH] Add server-name parameter - - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index e8c225fcd1a3fa5a7e1971683b1876dd6462a1e2..b849b2afd009da433fe6cea5837b3ee9bb5c52b4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -143,6 +143,14 @@ public class Main { - .defaultsTo(new File("paper.yml")) - .describedAs("Yml file"); - // Paper end -+ -+ // Paper start -+ acceptsAll(asList("server-name"), "Name of the server") -+ .withRequiredArg() -+ .ofType(String.class) -+ .defaultsTo("Unknown Server") -+ .describedAs("Name"); -+ // Paper end - } - }; - diff --git a/Unmapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/Unmapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch deleted file mode 100644 index 0b6b3e6fdb..0000000000 --- a/Unmapped-Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 May 2016 22:53:50 -0400 -Subject: [PATCH] Only send Dragon/Wither Death sounds to same world - -Also fix view distance lookup - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 6c58cf9d39cc0f0eb0dc7ddb126b8a3cf6a08fe7..74802de01dba30e38e09f6fc1f61e7bb64cf5f09 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -619,8 +619,9 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - if (this.deathAnimationTicks == 1 && !this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1028, this.getChunkCoordinates(), 0); -- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; -- for (net.minecraft.server.level.EntityPlayer player : this.world.getMinecraftServer().getPlayerList().players) { -+ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ for (net.minecraft.server.level.EntityPlayer player : (List) ((WorldServer)world).getPlayers()) { -+ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index f74949c855aea32ceb16d8cb07f266d50045b57e..145767e8b0fc4105a0afa47af17dcdbb75e952bc 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -258,8 +258,9 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - if (!this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1023, new BlockPosition(this), 0); -- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; -- for (EntityPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { -+ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ for (EntityPlayer player : (List)this.world.getPlayers()) { -+ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; diff --git a/Unmapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch b/Unmapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch deleted file mode 100644 index 45f6cacfcf..0000000000 --- a/Unmapped-Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 21 Jun 2016 22:54:34 -0400 -Subject: [PATCH] Fix Double World Add issues - -Vanilla will double add Spider Jockeys to the world, so ignore already added. - -Also add debug if something else tries to, and abort before world gets bad state - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index c7652d6bff7630e2eefbb4c3b0deb6e17b9c98d0..811e80ebb65715b7cdd1443aa33186c3ce2ec70c 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1038,6 +1038,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -+ if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper - if (entity.dead) { - // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit - return false; diff --git a/Unmapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch b/Unmapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch deleted file mode 100644 index e06e531049..0000000000 --- a/Unmapped-Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 17 Jun 2016 20:50:11 -0400 -Subject: [PATCH] Fix Old Sign Conversion - -1) Sign loading code was trying to parse the JSON before the check for oldSign. - That code could then skip the old sign converting code if it triggers a JSON parse exception. -2) New Mojang Schematic system has Tile Entities in the new converted format, but missing the Bukkit.isConverted flag - This causes Igloos and such to render broken signs. We fix this by ignoring sign conversion for Defined Structures - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 58789a6e285c31947508deae37caefe7e182278c..9b44ca96669ce423e5649f11743226dfdd9ce746 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -34,6 +34,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public CraftPersistentDataContainer persistentDataContainer; - // CraftBukkit end - private static final Logger LOGGER = LogManager.getLogger(); -+ public boolean isLoadingStructure = false; // Paper - private final TileEntityTypes tileType; public TileEntityTypes getTileEntityType() { return tileType; } // Paper - OBFHELPER - @Nullable - protected World world; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -index 29db550d91cf9e5a23052772df6e482a5e2b0b90..ec550aaa4e7943af4ecdd2275f1f32c21edf770a 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -@@ -78,13 +78,14 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - } - - try { -- IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); -+ //IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); // Paper - move down - the old format might throw a json error - -- if (oldSign) { -+ if (oldSign && !isLoadingStructure) { // Paper - saved structures will be in the new format, but will not have isConverted - lines[i] = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s)[0]; - continue; - } - // CraftBukkit end -+ IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); // Paper - after old sign - - if (this.world instanceof WorldServer) { - try { -diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java -index a2bc771df054923a9a96c0024a426ef707624359..9b82ff37faaafc3a799413f6949fb88a993aa9a0 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java -@@ -278,9 +278,11 @@ public class DefinedStructure { - definedstructure_blockinfo.c.setLong("LootTableSeed", random.nextLong()); - } - -+ tileentity.isLoadingStructure = true; // Paper - tileentity.load(definedstructure_blockinfo.b, definedstructure_blockinfo.c); - tileentity.a(definedstructureinfo.c()); - tileentity.a(definedstructureinfo.d()); -+ tileentity.isLoadingStructure = false; // Paper - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/Unmapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch deleted file mode 100644 index 60ded56167..0000000000 --- a/Unmapped-Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 16 Jul 2016 19:11:17 -0500 -Subject: [PATCH] Don't lookup game profiles that have no UUID and no name - - -diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java -index 39d1c379b781c08bfdd720cd6810a9c0bb9f0d09..4ad084e7cea3b341ca0dbaa6e853cfc685a555ff 100644 ---- a/src/main/java/net/minecraft/server/players/UserCache.java -+++ b/src/main/java/net/minecraft/server/players/UserCache.java -@@ -92,7 +92,7 @@ public class UserCache { - gameprofilerepository.findProfilesByNames(new String[]{s}, Agent.MINECRAFT, profilelookupcallback); - GameProfile gameprofile = (GameProfile) atomicreference.get(); - -- if (!c() && gameprofile == null) { -+ if (!c() && gameprofile == null && !org.apache.commons.lang3.StringUtils.isBlank(s)) { // Paper - Don't lookup a profile with a blank name - UUID uuid = EntityHuman.a(new GameProfile((UUID) null, s)); - - gameprofile = new GameProfile(uuid, s); diff --git a/Unmapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch b/Unmapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch deleted file mode 100644 index 0cec0451f3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabriele C -Date: Fri, 5 Aug 2016 01:03:08 +0200 -Subject: [PATCH] Add setting for proxy online mode status - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2..c52dc0346f93527965ef29a0ccdc4bf3debe302e 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -23,6 +23,7 @@ import org.bukkit.configuration.InvalidConfigurationException; - import org.bukkit.configuration.file.YamlConfiguration; - import co.aikar.timings.Timings; - import co.aikar.timings.TimingsManager; -+import org.spigotmc.SpigotConfig; - - public class PaperConfig { - -@@ -242,4 +243,13 @@ public class PaperConfig { - private static void saveEmptyScoreboardTeams() { - saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); - } -+ -+ public static boolean bungeeOnlineMode = true; -+ private static void bungeeOnlineMode() { -+ bungeeOnlineMode = getBoolean("settings.bungee-online-mode", true); -+ } -+ -+ public static boolean isProxyOnlineMode() { -+ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); -+ } - } -diff --git a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -index 8a343a857dc4661ba256e39cf391dd2c7a1cc970..8c1f328ca1ba12ed63ec7bd7efad54ff633ba802 100644 ---- a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -+++ b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -@@ -66,7 +66,8 @@ public class NameReferencingFileConverter { - return new String[i]; - }); - -- if (minecraftserver.getOnlineMode() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. -+ if (minecraftserver.getOnlineMode() -+ || (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode())) { // Spigot: bungee = online mode, for now. // Paper - Handle via setting - minecraftserver.getGameProfileRepository().findProfilesByNames(astring, Agent.MINECRAFT, profilelookupcallback); - } else { - String[] astring1 = astring; -diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java -index 4ad084e7cea3b341ca0dbaa6e853cfc685a555ff..b9f94f957dd5372c8b02d785204690e4ade36a98 100644 ---- a/src/main/java/net/minecraft/server/players/UserCache.java -+++ b/src/main/java/net/minecraft/server/players/UserCache.java -@@ -89,6 +89,7 @@ public class UserCache { - } - }; - -+ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) // Paper - only run in online mode - 100 COL - gameprofilerepository.findProfilesByNames(new String[]{s}, Agent.MINECRAFT, profilelookupcallback); - GameProfile gameprofile = (GameProfile) atomicreference.get(); - -@@ -106,7 +107,7 @@ public class UserCache { - } - - private static boolean c() { -- return UserCache.b; -+ return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper - } - - public synchronized void a(GameProfile gameprofile) { // Paper - synchronize -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e670f484d454f7c706a0ec92c98087fa1373c492..b392f7703222dbba30cdd81ac83e93da36ec043f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1516,7 +1516,8 @@ public final class CraftServer implements Server { - // Spigot Start - GameProfile profile = null; - // Only fetch an online UUID in online mode -- if ( getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) -+ if ( getOnlineMode() -+ || com.destroystokyo.paper.PaperConfig.isProxyOnlineMode() ) // Paper - Handle via setting - { - profile = console.getUserCache().getProfile( name ); - } diff --git a/Unmapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch b/Unmapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch deleted file mode 100644 index 909f6b5273..0000000000 --- a/Unmapped-Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Fri, 19 Aug 2016 01:52:56 +0100 -Subject: [PATCH] Optimise BlockState's hashCode/equals - -These are singleton "single instance" objects. We can rely on -object identity checks safely. - -Use a simpler optimized hashcode - -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java -index 0701c1a178852345b6bf01bce8b1d0559c535d45..f2f94950681b198ae7a4c31a044fd62e98e448ab 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java -@@ -30,8 +30,7 @@ public class BlockStateBoolean extends IBlockState { - return obool.toString(); - } - -- @Override -- public boolean equals(Object object) { -+ public boolean equals_unused(Object object) { // Paper - if (this == object) { - return true; - } else if (object instanceof BlockStateBoolean && super.equals(object)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -index de85894beae7ee7d276cf2af3daa77377ce131c3..3079cd13ea1465f4221fde4fec7df639f7c1eb49 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -@@ -50,8 +50,7 @@ public class BlockStateEnum & INamable> extends IBlockState - return ((INamable) t0).getName(); - } - -- @Override -- public boolean equals(Object object) { -+ public boolean equals_unused(Object object) { // Paper - if (this == object) { - return true; - } else if (object instanceof BlockStateEnum && super.equals(object)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java -index 518c2ebe4cdfe4704bbec2abe81522cbca38da55..190978c889222185b47065e9e5f96a82e59c7b4e 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java -@@ -38,8 +38,7 @@ public class BlockStateInteger extends IBlockState { - return this.a; - } - -- @Override -- public boolean equals(Object object) { -+ public boolean equals_unused(Object object) { // Paper - if (this == object) { - return true; - } else if (object instanceof BlockStateInteger && super.equals(object)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -index e3969bad5be64bb41e2973751605d6820c16f021..759d6a4adaa511488ace5e2650eb685cbb6c4c16 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -@@ -60,23 +60,17 @@ public abstract class IBlockState> { - } - - public boolean equals(Object object) { -- if (this == object) { -- return true; -- } else if (!(object instanceof IBlockState)) { -- return false; -- } else { -- IBlockState iblockstate = (IBlockState) object; -- -- return this.a.equals(iblockstate.a) && this.b.equals(iblockstate.b); -- } -+ return this == object; // Paper - only one instance per configuration - } - -+ private static final java.util.concurrent.atomic.AtomicInteger hashId = new java.util.concurrent.atomic.AtomicInteger(1); // Paper - only one instance per configuration -+ private final int hashCode = 92821 * hashId.getAndIncrement(); // Paper - only one instance per configuration - public final int hashCode() { - if (this.c == null) { - this.c = this.b(); - } - -- return this.c; -+ return this.hashCode; // Paper - only one instance per configuration - } - - public int b() { diff --git a/Unmapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch b/Unmapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch deleted file mode 100644 index e9da45ba0e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 11 Sep 2016 14:30:57 -0500 -Subject: [PATCH] Configurable packet in spam threshold - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index c52dc0346f93527965ef29a0ccdc4bf3debe302e..64d7c9058ee757a6d3cf3b648596092a810e105c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -252,4 +252,13 @@ public class PaperConfig { - public static boolean isProxyOnlineMode() { - return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); - } -+ -+ public static int packetInSpamThreshold = 300; -+ private static void packetInSpamThreshold() { -+ if (version < 11) { -+ int oldValue = getInt("settings.play-in-use-item-spam-threshold", 300); -+ set("settings.incoming-packet-spam-threshold", oldValue); -+ } -+ packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index d3938e1fbab0a01ae5045858b1f421e041b768e2..09fa4bd7899ad01c43ce35ed2306eec434ebc0fe 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1465,13 +1465,14 @@ public class PlayerConnection implements PacketListenerPlayIn { - // Spigot start - limit place/interactions - private int limitedPackets; - private long lastLimitedPacket = -1; -+ private static final int THRESHOLD = com.destroystokyo.paper.PaperConfig.packetInSpamThreshold; // Paper - Configurable threshold - - private boolean checkLimit(long timestamp) { -- if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < 30 && limitedPackets++ >= 4) { -+ if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < THRESHOLD && limitedPackets++ >= 8) { // Paper - Use threshold, raise packet limit to 8 - return false; - } - -- if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= 30) { -+ if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= THRESHOLD) { // Paper - lastLimitedPacket = timestamp; - limitedPackets = 0; - return true; diff --git a/Unmapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch b/Unmapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch deleted file mode 100644 index 22c865ee62..0000000000 --- a/Unmapped-Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Tue, 20 Sep 2016 00:58:01 +0000 -Subject: [PATCH] Configurable flying kick messages - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 64d7c9058ee757a6d3cf3b648596092a810e105c..4e2f243faa209925dcb7c3ef89df3ed875c5ff78 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -261,4 +261,11 @@ public class PaperConfig { - } - packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); - } -+ -+ public static String flyingKickPlayerMessage = "Flying is not enabled on this server"; -+ public static String flyingKickVehicleMessage = "Flying is not enabled on this server"; -+ private static void flyingKickMessages() { -+ flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); -+ flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 09fa4bd7899ad01c43ce35ed2306eec434ebc0fe..15daf87d6a6d80b5ebce5360e6999fd604c66cb5 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -307,7 +307,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - if (this.B && !this.player.isSleeping()) { - if (++this.C > 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", this.player.getDisplayName().getString()); -- this.disconnect(new ChatMessage("multiplayer.disconnect.flying")); -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message - return; - } - } else { -@@ -326,7 +326,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - if (this.D && this.player.getRootVehicle().getRidingPassenger() == this.player) { - if (++this.E > 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getDisplayName().getString()); -- this.disconnect(new ChatMessage("multiplayer.disconnect.flying")); -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message - return; - } - } else { diff --git a/Unmapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch b/Unmapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch deleted file mode 100644 index ada089c700..0000000000 --- a/Unmapped-Spigot-Server-Patches/0112-Chunk-registration-fixes.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Sep 2016 22:54:28 -0400 -Subject: [PATCH] Chunk registration fixes - -World checks and the Chunk Add logic are inconsistent on how Y > 256, < 0, is treated - -Keep them consistent - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 811e80ebb65715b7cdd1443aa33186c3ce2ec70c..744ec6f09a1b3ccdf0d74fe50f1e1c913ee2df86 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -847,7 +847,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (entity.cl()) { - this.getMethodProfiler().enter("chunkCheck"); - int i = MathHelper.floor(entity.locX() / 16.0D); -- int j = MathHelper.floor(entity.locY() / 16.0D); -+ int j = Math.min(15, Math.max(0, MathHelper.floor(entity.locY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior - int k = MathHelper.floor(entity.locZ() / 16.0D); - - if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) { diff --git a/Unmapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/Unmapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch deleted file mode 100644 index ea0d507b64..0000000000 --- a/Unmapped-Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 16 Jun 2016 00:17:23 -0400 -Subject: [PATCH] Remove FishingHook reference on Craft Entity removal - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -index 4dd3deaabfdb383ded92920e1a313b61a1b9262b..4805bce05f2856289608f45df4fca322de161b31 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -@@ -119,4 +119,14 @@ public class CraftFishHook extends CraftProjectile implements FishHook { - public HookState getState() { - return HookState.values()[getHandle().hookState.ordinal()]; - } -+ -+ // Paper start -+ @Override -+ public void remove() { -+ super.remove(); -+ if (getHandle().getOwner() != null) { -+ getHandle().getOwner().hookedFish = null; -+ } -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch b/Unmapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch deleted file mode 100644 index b4d980555f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Sep 2016 23:48:39 -0400 -Subject: [PATCH] Auto fix bad Y levels on player login - -Bring down to a saner Y level if super high, as this can cause the server to crash - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 3f1f8f7fe9452f66b18a08ef480d50ef78ad3351..3fca9c3566b5d9a1fafeb0700942d7658cd5a279 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -340,6 +340,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - @Override - public void loadData(NBTTagCompound nbttagcompound) { - super.loadData(nbttagcompound); -+ if (this.locY() > 300) this.setPositionRaw(locX(), 257, locZ()); // Paper - bring down to a saner Y level if out of world - if (nbttagcompound.hasKeyOfType("playerGameType", 99)) { - if (this.getMinecraftServer().getForceGamemode()) { - this.playerInteractManager.a(this.getMinecraftServer().getGamemode(), EnumGamemode.NOT_SET); diff --git a/Unmapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch b/Unmapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch deleted file mode 100644 index c9e047b2c4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 5 Oct 2016 16:27:36 -0500 -Subject: [PATCH] Option to remove corrupt tile entities - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6eca3f300020006f02dd36253b522db442e3cc33..622affa0dc3cc1eadaed400511f2ca2cde3fca2a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -300,4 +300,9 @@ public class PaperWorldConfig { - preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); - log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); - } -+ -+ public boolean removeCorruptTEs = false; -+ private void removeCorruptTEs() { -+ removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index b6898cd6e6117fef65198db32b98a64c806811d4..7918dd4ad3e8cbb905b3929062a70fb7961b7d68 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -679,6 +679,12 @@ public class Chunk implements IChunkAccess { - "Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16)); - e.printStackTrace(); - ServerInternalException.reportInternalException(e); -+ -+ if (this.world.paperConfig.removeCorruptTEs) { -+ this.removeTileEntity(tileentity.getPosition()); -+ this.markDirty(); -+ org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); -+ } - // Paper end - // CraftBukkit end - } diff --git a/Unmapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch b/Unmapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch deleted file mode 100644 index 40404fd392..0000000000 --- a/Unmapped-Spigot-Server-Patches/0116-Add-EntityZapEvent.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlphaBlend -Date: Sun, 16 Oct 2016 23:19:30 -0700 -Subject: [PATCH] Add EntityZapEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -index cc31c8f31a385f3a8bfe334e75c3553689397750..d6e1697f64e60f2a567288c604a1690159955f37 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -@@ -255,6 +255,11 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { - } - - entitypigzombie.setPersistent(); -+ // Paper start -+ if (CraftEventFactory.callEntityZapEvent(this, entitylightning, entitypigzombie).isCancelled()) { -+ return; -+ } -+ // Paper end - // CraftBukkit start - if (CraftEventFactory.callPigZapEvent(this, entitylightning, entitypigzombie).isCancelled()) { - return; -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index ef838bbcc23145ebd5203963923030a8f971cd6e..72ed4de72c87e9c241507838ddb42eaa4c05ef32 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -787,6 +787,12 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - EntityVillager.LOGGER.info("Villager {} was struck by lightning {}.", this, entitylightning); - EntityWitch entitywitch = (EntityWitch) EntityTypes.WITCH.a((World) worldserver); - -+ // Paper start -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, entitylightning, entitywitch).isCancelled()) { -+ return; -+ } -+ // Paper end -+ - entitywitch.setPositionRotation(this.locX(), this.locY(), this.locZ(), this.yaw, this.pitch); - entitywitch.prepare(worldserver, worldserver.getDamageScaler(entitywitch.getChunkCoordinates()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (NBTTagCompound) 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 8a7511fc1876dc6761826dd2636bce19d177d2e8..aa484fb733e87c17cc77e56b36f6e1126e8ca4cf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1098,6 +1098,14 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start -+ public static com.destroystokyo.paper.event.entity.EntityZapEvent callEntityZapEvent (Entity entity, Entity lightning, Entity changedEntity) { -+ com.destroystokyo.paper.event.entity.EntityZapEvent event = new com.destroystokyo.paper.event.entity.EntityZapEvent(entity.getBukkitEntity(), (LightningStrike) lightning.getBukkitEntity(), changedEntity.getBukkitEntity()); -+ entity.getBukkitEntity().getServer().getPluginManager().callEvent(event); -+ return event; -+ } -+ // Paper end -+ - public static HorseJumpEvent callHorseJumpEvent(Entity horse, float power) { - HorseJumpEvent event = new HorseJumpEvent((AbstractHorse) horse.getBukkitEntity(), power); - horse.getBukkitEntity().getServer().getPluginManager().callEvent(event); diff --git a/Unmapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/Unmapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch deleted file mode 100644 index 4ed73d0d74..0000000000 --- a/Unmapped-Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 12 Nov 2016 23:25:22 -0600 -Subject: [PATCH] Filter bad data from ArmorStand and SpawnEgg items - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 622affa0dc3cc1eadaed400511f2ca2cde3fca2a..e83216be5a00d5b927d8c2fc364551bd3077c974 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -2,6 +2,7 @@ package com.destroystokyo.paper; - - import java.util.List; - -+import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -305,4 +306,12 @@ public class PaperWorldConfig { - private void removeCorruptTEs() { - removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); - } -+ -+ public boolean filterNBTFromSpawnEgg = true; -+ private void fitlerNBTFromSpawnEgg() { -+ filterNBTFromSpawnEgg = getBoolean("filter-nbt-data-from-spawn-eggs-and-related", true); -+ if (!filterNBTFromSpawnEgg) { -+ Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 3f10e41b18e09186635fd6f7c653b04db7b39d8e..411e3915c0aa00249aacb6658ed04309665d2fb4 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -272,6 +272,13 @@ public class EntityFallingBlock extends Entity { - @Override - protected void loadData(NBTTagCompound nbttagcompound) { - this.block = GameProfileSerializer.c(nbttagcompound.getCompound("BlockState")); -+ // Paper start - Block FallingBlocks with Command Blocks -+ // Check mappings on update - dc = "repeating_command_block" - dd = "chain_command_block" -+ final Block b = this.block.getBlock(); -+ if (this.world.paperConfig.filterNBTFromSpawnEgg && (b == Blocks.COMMAND_BLOCK || b == Blocks.REPEATING_COMMAND_BLOCK || b == Blocks.CHAIN_COMMAND_BLOCK)) { -+ this.block = Blocks.STONE.getBlockData(); -+ } -+ // Paper end - this.ticksLived = nbttagcompound.getInt("Time"); - if (nbttagcompound.hasKeyOfType("HurtEntities", 99)) { - this.hurtEntities = nbttagcompound.getBoolean("HurtEntities"); diff --git a/Unmapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch b/Unmapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch deleted file mode 100644 index 48d9a082cd..0000000000 --- a/Unmapped-Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: vemacs -Date: Wed, 23 Nov 2016 08:31:45 -0500 -Subject: [PATCH] Cache user authenticator threads - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 3fca9c3566b5d9a1fafeb0700942d7658cd5a279..e6dacf68cd678d64547dcdc23b1175a4cfd279d1 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -4,7 +4,9 @@ import com.google.common.collect.Lists; - import com.mojang.authlib.GameProfile; - import com.mojang.datafixers.util.Either; - import com.mojang.serialization.DataResult; -+import java.util.ArrayDeque; // Paper - import java.util.Collection; -+import java.util.Deque; // Paper - import java.util.Iterator; - import java.util.List; - import java.util.Optional; -@@ -172,7 +174,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public PlayerConnection playerConnection; - public final MinecraftServer server; - public final PlayerInteractManager playerInteractManager; -- public final List removeQueue = Lists.newLinkedList(); -+ public final Deque removeQueue = new ArrayDeque<>(); // Paper - private final AdvancementDataPlayer advancementDataPlayer; - private final ServerStatisticManager serverStatisticManager; - private float lastHealthScored = Float.MIN_VALUE; -@@ -550,13 +552,20 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - while (!this.removeQueue.isEmpty()) { - int i = Math.min(this.removeQueue.size(), Integer.MAX_VALUE); - int[] aint = new int[i]; -- Iterator iterator = this.removeQueue.iterator(); -+ //Iterator iterator = this.removeQueue.iterator(); // Paper - int j = 0; - -- while (iterator.hasNext() && j < i) { -+ // Paper start -+ /* while (iterator.hasNext() && j < i) { - aint[j++] = (Integer) iterator.next(); - iterator.remove(); -+ } */ -+ -+ Integer integer; -+ while (j < i && (integer = this.removeQueue.poll()) != null) { -+ aint[j++] = integer.intValue(); - } -+ // Paper end - - this.playerConnection.sendPacket(new PacketPlayOutEntityDestroy(aint)); - } -@@ -1561,7 +1570,14 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.lastHealthSent = -1.0F; - this.lastFoodSent = -1; - // this.recipeBook.a((RecipeBook) entityplayer.recipeBook); // CraftBukkit -- this.removeQueue.addAll(entityplayer.removeQueue); -+ // Paper start - Optimize remove queue - vanilla copies player objects, but CB doesn't. This method currently only -+ // Applies to the same player, so we need to not duplicate our removal queue. The rest of this method does "resetting" -+ // type logic so it does need to be called, maybe? This is silly. -+ // this.removeQueue.addAll(entityplayer.removeQueue); -+ if (this.removeQueue != entityplayer.removeQueue) { -+ this.removeQueue.addAll(entityplayer.removeQueue); -+ } -+ // Paper end - this.cd = entityplayer.cd; - this.ci = entityplayer.ci; - this.setShoulderEntityLeft(entityplayer.getShoulderEntityLeft()); diff --git a/Unmapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch b/Unmapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch deleted file mode 100644 index c45413d9b2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0119-Optimise-removeQueue.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Fri, 25 Nov 2016 13:22:40 +0000 -Subject: [PATCH] Optimise removeQueue - - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 49a0aefc7f9544b36175fdf3161b255e878952a6..c45647f2d05ed6b170aad10c0a3fb94570d2dd90 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -116,6 +116,12 @@ public class LoginListener implements PacketLoginInListener { - - } - -+ // Paper start - Cache authenticator threads -+ private static final AtomicInteger threadId = new AtomicInteger(0); -+ private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool( -+ r -> new Thread(r, "User Authenticator #" + threadId.incrementAndGet()) -+ ); -+ // Paper end - // Spigot start - public void initUUID() - { -@@ -195,8 +201,8 @@ public class LoginListener implements PacketLoginInListener { - this.networkManager.sendPacket(new PacketLoginOutEncryptionBegin("", this.server.getKeyPair().getPublic().getEncoded(), this.e)); - } else { - // Spigot start -- new Thread("User Authenticator #" + LoginListener.b.incrementAndGet()) { -- -+ // Paper start - Cache authenticator threads -+ authenticatorPool.execute(new Runnable() { - @Override - public void run() { - try { -@@ -207,7 +213,8 @@ public class LoginListener implements PacketLoginInListener { - server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + i.getName(), ex); - } - } -- }.start(); -+ }); -+ // Paper end - // Spigot end - } - -@@ -236,7 +243,8 @@ public class LoginListener implements PacketLoginInListener { - throw new IllegalStateException("Protocol error", cryptographyexception); - } - -- Thread thread = new Thread("User Authenticator #" + LoginListener.b.incrementAndGet()) { -+ // Paper start - Cache authenticator threads -+ authenticatorPool.execute(new Runnable() { - public void run() { - GameProfile gameprofile = LoginListener.this.i; - -@@ -281,10 +289,8 @@ public class LoginListener implements PacketLoginInListener { - - return LoginListener.this.server.W() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; - } -- }; -- -- thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LoginListener.LOGGER)); -- thread.start(); -+ }); -+ // Paper end - } - - // Spigot start diff --git a/Unmapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch b/Unmapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch deleted file mode 100644 index 24d1829ae5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: willies952002 -Date: Mon, 28 Nov 2016 10:21:52 -0500 -Subject: [PATCH] Allow Reloading of Command Aliases - -Reload the aliases stored in commands.yml - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index b392f7703222dbba30cdd81ac83e93da36ec043f..539577a0378754cbe0942a79140f6d137eb825ed 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2282,5 +2282,24 @@ public final class CraftServer implements Server { - DefaultPermissions.registerCorePermissions(); - CraftDefaultPermissions.registerCorePermissions(); - } -+ -+ @Override -+ public boolean reloadCommandAliases() { -+ Set removals = getCommandAliases().keySet().stream() -+ .map(key -> key.toLowerCase(java.util.Locale.ENGLISH)) -+ .collect(java.util.stream.Collectors.toSet()); -+ getCommandMap().getKnownCommands().keySet().removeIf(removals::contains); -+ File file = getCommandsConfigFile(); -+ try { -+ commandsConfiguration.load(file); -+ } catch (FileNotFoundException ex) { -+ return false; -+ } catch (IOException | org.bukkit.configuration.InvalidConfigurationException ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex); -+ return false; -+ } -+ commandMap.registerServerAliases(); -+ return true; -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch deleted file mode 100644 index 3fac6707a6..0000000000 --- a/Unmapped-Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlphaBlend -Date: Thu, 8 Sep 2016 08:48:33 -0700 -Subject: [PATCH] Add source to PlayerExpChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index a52cd6d0318e0fee28fc5d252a4b596b92860320..a17812943b5402684c68ddeac5408dc939e42cf6 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -203,7 +203,7 @@ public class EntityExperienceOrb extends Entity { - } - - if (this.value > 0) { -- entityhuman.giveExp(CraftEventFactory.callPlayerExpChangeEvent(entityhuman, this.value).getAmount()); // CraftBukkit - this.value -> event.getAmount() -+ entityhuman.giveExp(CraftEventFactory.callPlayerExpChangeEvent(entityhuman, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object - } - - this.die(); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index aa484fb733e87c17cc77e56b36f6e1126e8ca4cf..6bee8bcd653737748c442b03a8ce3bedc57dff20 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -121,6 +121,7 @@ import org.bukkit.entity.ThrownPotion; - import org.bukkit.entity.Vehicle; - import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; -+import org.bukkit.entity.ExperienceOrb; // Paper - import org.bukkit.event.Cancellable; - import org.bukkit.event.Event; - import org.bukkit.event.Event.Result; -@@ -1057,6 +1058,17 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start - Add orb -+ public static PlayerExpChangeEvent callPlayerExpChangeEvent(EntityHuman entity, EntityExperienceOrb entityOrb) { -+ Player player = (Player) entity.getBukkitEntity(); -+ ExperienceOrb source = (ExperienceOrb) entityOrb.getBukkitEntity(); -+ int expAmount = source.getExperience(); -+ PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, source, expAmount); -+ Bukkit.getPluginManager().callEvent(event); -+ return event; -+ } -+ // Paper end -+ - public static boolean handleBlockGrowEvent(World world, BlockPosition pos, IBlockData block) { - return handleBlockGrowEvent(world, pos, block, 3); - } diff --git a/Unmapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch b/Unmapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch deleted file mode 100644 index 34efb26a3c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 16 Dec 2016 16:03:19 -0600 -Subject: [PATCH] Don't let fishinghooks use portals - - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 7402e3b305d9bb7b27b97ff2078c26dd578232a1..2067af9b13c7ce28cd8ad6c785e2d0a7ff013430 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -@@ -240,6 +240,11 @@ public class EntityFishingHook extends IProjectile { - - this.setMot(this.getMot().a(0.92D)); - this.af(); -+ // Paper start - These shouldn't be going through portals -+ if (this.inPortal) { -+ this.die(); -+ } -+ // Paper end - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch b/Unmapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch deleted file mode 100644 index ad461a95e3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Fri, 16 Dec 2016 21:25:39 -0600 -Subject: [PATCH] Add ProjectileCollideEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index 7868259a94766a6100d7b278c4296dde0a7f9397..c325c9fe680d9033b20909bcd6100ecc4b0195f6 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -198,6 +198,17 @@ public abstract class EntityArrow extends IProjectile { - } - } - -+ // Paper start - Call ProjectileCollideEvent -+ // TODO: flag - noclip - call cancelled? -+ if (object instanceof MovingObjectPositionEntity) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)object); -+ if (event.isCancelled()) { -+ object = null; -+ movingobjectpositionentity = null; -+ } -+ } -+ // Paper end -+ - if (object != null && !flag) { - this.preOnHit((MovingObjectPosition) object); // CraftBukkit - projectile hit event - this.impulse = true; -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -index 2ceae34365c437f2a15ae8587fa9517ea47ad6f2..9660dc2263c48a5818b767843658eeb9ee1748ea 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -@@ -13,6 +13,7 @@ import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.level.World; - import net.minecraft.world.phys.MovingObjectPosition; -+import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; - - import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit -@@ -72,7 +73,16 @@ public abstract class EntityFireball extends IProjectile { - - MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); - -- if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { -+ // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition instanceof MovingObjectPositionEntity) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)movingobjectposition); -+ if (event.isCancelled()) { -+ movingobjectposition = null; -+ } -+ } -+ // Paper end -+ -+ if (movingobjectposition != null && movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { // Paper - add null check in case cancelled - this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event - - // CraftBukkit start - Fire ProjectileHitEvent -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java -index 149588433cd0ea0f71b45267e39b28697ccfd2c0..8bc65e9c0fa5e134a8eb4e03f0da5b2ccd06cd7c 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java -@@ -14,6 +14,7 @@ import net.minecraft.world.level.block.entity.TileEntityEndGateway; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; -+import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; - - public abstract class EntityProjectile extends IProjectile { -@@ -57,7 +58,17 @@ public abstract class EntityProjectile extends IProjectile { - } - - if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS && !flag) { -+ // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition instanceof MovingObjectPositionEntity) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)movingobjectposition); -+ if (event.isCancelled()) { -+ movingobjectposition = null; -+ } -+ } -+ if (movingobjectposition != null) { -+ // Paper end - this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event -+ } // Paper - } - - this.checkBlockCollisions(); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 6bee8bcd653737748c442b03a8ce3bedc57dff20..d07c146119980358aeaf8f9dc5f419fd1385ced5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1202,6 +1202,16 @@ public class CraftEventFactory { - return CraftItemStack.asNMSCopy(bitem); - } - -+ // Paper start -+ public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, MovingObjectPositionEntity position) { -+ 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); -+ Bukkit.getPluginManager().callEvent(event); -+ return event; -+ } -+ // Paper end -+ - public static ProjectileLaunchEvent callProjectileLaunchEvent(Entity entity) { - Projectile bukkitEntity = (Projectile) entity.getBukkitEntity(); - ProjectileLaunchEvent event = new ProjectileLaunchEvent(bukkitEntity); diff --git a/Unmapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch b/Unmapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch deleted file mode 100644 index d30b0eae33..0000000000 --- a/Unmapped-Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 19 Dec 2016 23:07:42 -0500 -Subject: [PATCH] Prevent Pathfinding out of World Border - -This prevents Entities from trying to run outside of the World Border - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index d71a6e5991629ce59c8529d7cc8064960e385236..d134333c736dc1ee1c722d680d7a9c22c1b265bd 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -148,7 +148,7 @@ public abstract class NavigationAbstract { - // Paper start - Pathfind event - boolean copiedSet = false; - for (BlockPosition possibleTarget : set) { -- if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), -+ if (!getEntity().getWorld().getWorldBorder().isInBounds(possibleTarget) || !new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), // Paper - don't path out of world border - MCUtil.toLocation(getEntity().world, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { - if (!copiedSet) { - copiedSet = true; diff --git a/Unmapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch b/Unmapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch deleted file mode 100644 index 2bc6bb0583..0000000000 --- a/Unmapped-Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 2 Dec 2016 00:11:43 -0500 -Subject: [PATCH] Optimize World.isLoaded(BlockPosition)Z - -Reduce method invocations for World.isLoaded(BlockPosition)Z - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index d8ab2e22a5c0144decb5c657a123cc61722fcbf5..bd08ff18d8d7dbe63ed33c1efb6099b58aa02caa 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -305,6 +305,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return chunk == null ? null : chunk.getFluid(blockposition); - } - -+ public final boolean isLoaded(BlockPosition blockposition) { -+ return getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; // Paper -+ } -+ - public final boolean isLoadedAndInBounds(BlockPosition blockposition) { // Paper - final for inline - return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; - } diff --git a/Unmapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch b/Unmapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch deleted file mode 100644 index 212f2d89eb..0000000000 --- a/Unmapped-Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 20 Dec 2016 15:15:11 -0500 -Subject: [PATCH] Bound Treasure Maps to World Border - -Make it so a Treasure Map does not target a structure outside of the -World Border, where players are not even able to reach. - -This also would help the case where a players close to the border, and one -that is outside happens to be closer, but unreachable, yet another reachable -one is in border that would of been missed. - -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index f16c76df5d7b184d57f4cc397f069eac9cc430cb..50e2085766caabec1125ca24a2117549efd1a354 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -36,6 +36,18 @@ public class WorldBorder { - return (double) (blockposition.getX() + 1) > this.e() && (double) blockposition.getX() < this.g() && (double) (blockposition.getZ() + 1) > this.f() && (double) blockposition.getZ() < this.h(); - } - -+ // Paper start -+ private final BlockPosition.MutableBlockPosition mutPos = new BlockPosition.MutableBlockPosition(); -+ public boolean isBlockInBounds(int chunkX, int chunkZ) { -+ this.mutPos.setValues(chunkX, 64, chunkZ); -+ return this.isInBounds(this.mutPos); -+ } -+ public boolean isChunkInBounds(int chunkX, int chunkZ) { -+ this.mutPos.setValues(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15); -+ return this.isInBounds(this.mutPos); -+ } -+ // Paper end -+ - public boolean isInBounds(ChunkCoordIntPair chunkcoordintpair) { - return (double) chunkcoordintpair.f() > this.e() && (double) chunkcoordintpair.d() < this.g() && (double) chunkcoordintpair.g() > this.f() && (double) chunkcoordintpair.e() < this.h(); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -index 6724927be178cb9a358a9276d01894a63154b7b3..ea7e3e15fa778c573d24f956f72f60579ea0b1a1 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -@@ -175,6 +175,7 @@ public abstract class StructureGenerator - int i2 = l + k * k1; - int j2 = i1 + k * l1; - ChunkCoordIntPair chunkcoordintpair = this.a(structuresettingsfeature, j, seededrandom, i2, j2); -+ if (!iworldreader.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper - IChunkAccess ichunkaccess = iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); - StructureStart structurestart = structuremanager.a(SectionPosition.a(ichunkaccess.getPos(), 0), this, ichunkaccess); - diff --git a/Unmapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch b/Unmapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch deleted file mode 100644 index 82ccdd75a9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 20 Dec 2016 15:26:27 -0500 -Subject: [PATCH] Configurable Cartographer Treasure Maps - -Allow configuring for cartographers to return the same map location - -Also allow turning off treasure maps all together as they can eat up Map ID's -which are limited in quantity. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e83216be5a00d5b927d8c2fc364551bd3077c974..2dc58b9f769ea43b737804456aafab47ecc143b8 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -314,4 +314,14 @@ public class PaperWorldConfig { - Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); - } - } -+ -+ public boolean enableTreasureMaps = true; -+ public boolean treasureMapsAlreadyDiscovered = false; -+ private void treasureMapsAlreadyDiscovered() { -+ enableTreasureMaps = getBoolean("enable-treasure-maps", true); -+ treasureMapsAlreadyDiscovered = getBoolean("treasure-maps-return-already-discovered", false); -+ if (treasureMapsAlreadyDiscovered) { -+ log("Treasure Maps will return already discovered locations"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -index 764ff5d9ffb541a356a6bc8b321e619849dde747..0a34e319998a95a9654822e55a22eb964b2d626b 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -+++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -@@ -124,7 +124,8 @@ public class VillagerTrades { - return null; - } else { - WorldServer worldserver = (WorldServer) entity.world; -- BlockPosition blockposition = worldserver.a(this.b, entity.getChunkCoordinates(), 100, true); -+ if (!worldserver.paperConfig.enableTreasureMaps) return null; // Paper -+ BlockPosition blockposition = worldserver.a(this.b, entity.getChunkCoordinates(), 100, !worldserver.paperConfig.treasureMapsAlreadyDiscovered); // Paper - - if (blockposition != null) { - ItemStack itemstack = ItemWorldMap.createFilledMapView(worldserver, blockposition.getX(), blockposition.getZ(), (byte) 2, true, true); -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -index 38125a60bad4830db9de3580ab6d85fd122a0689..7bf16c5a3f2bb5525ce1ca0c0190c7671fc94797 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -@@ -64,7 +64,16 @@ public class LootItemFunctionExplorationMap extends LootItemFunctionConditional - - if (vec3d != null) { - WorldServer worldserver = loottableinfo.getWorld(); -- BlockPosition blockposition = worldserver.a(this.e, new BlockPosition(vec3d), this.h, this.i); -+ // Paper start -+ if (!worldserver.paperConfig.enableTreasureMaps) { -+ /* -+ * NOTE: I fear users will just get a plain map as their "treasure" -+ * This is preferable to disrespecting the config. -+ */ -+ return itemstack; -+ } -+ // Paper end -+ BlockPosition blockposition = worldserver.a(this.e, new BlockPosition(vec3d), this.h, !worldserver.paperConfig.treasureMapsAlreadyDiscovered && this.i); // Paper - - if (blockposition != null) { - ItemStack itemstack1 = ItemWorldMap.createFilledMapView(worldserver, blockposition.getX(), blockposition.getZ(), this.g, true, true); diff --git a/Unmapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch b/Unmapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch deleted file mode 100644 index 011e094dc5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Dec 2016 03:48:29 -0500 -Subject: [PATCH] Optimize ItemStack.isEmpty() - -Remove hashMap lookup every check, simplify code to remove ternary - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 201ba7250b298f4a91bc45f5954f54ae557305f2..cac92ccacc9d5ff17c70ee266cf12bacce6242ea 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -208,7 +208,7 @@ public final class ItemStack { - } - - public boolean isEmpty() { -- return this == ItemStack.b ? true : (this.getItem() != null && this.getItem() != Items.AIR ? this.count <= 0 : true); -+ return this == ItemStack.NULL_ITEM || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper - } - - public ItemStack cloneAndSubtract(int i) { diff --git a/Unmapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch b/Unmapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch deleted file mode 100644 index 8d198833bc..0000000000 --- a/Unmapped-Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 21 Dec 2016 11:47:25 -0600 -Subject: [PATCH] Add API methods to control if armour stands can move - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 31bb5df7bc63c993230bf595bd9b66bfaadb4d50..ccdfc8068a8205d6e66ab9458764b1440f8c4b97 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -38,6 +38,7 @@ import net.minecraft.world.entity.ai.control.ControllerLook; - import net.minecraft.world.entity.ai.control.ControllerMove; - import net.minecraft.world.entity.ai.control.EntityAIBodyControl; - import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; - import net.minecraft.world.entity.ai.goal.PathfinderGoalSelector; - import net.minecraft.world.entity.ai.navigation.Navigation; - import net.minecraft.world.entity.ai.navigation.NavigationAbstract; -@@ -45,6 +46,8 @@ import net.minecraft.world.entity.ai.sensing.EntitySenses; - import net.minecraft.world.entity.decoration.EntityHanging; - import net.minecraft.world.entity.decoration.EntityLeash; - import net.minecraft.world.entity.item.EntityItem; -+import net.minecraft.world.entity.monster.EntityBlaze; -+import net.minecraft.world.entity.monster.EntityEnderman; - import net.minecraft.world.entity.monster.IMonster; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.vehicle.EntityBoat; -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 72e53968c5fb03301ddec7a0cf937ac2f8cf0901..2ef991aa7f739d3577fbbf4386064557e8f7c904 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -28,6 +28,7 @@ import net.minecraft.world.entity.EntitySize; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumItemSlot; - import net.minecraft.world.entity.EnumMainHand; -+import net.minecraft.world.entity.EnumMoveType; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.projectile.EntityArrow; - import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; -@@ -79,6 +80,7 @@ public class EntityArmorStand extends EntityLiving { - public Vector3f rightArmPose; - public Vector3f leftLegPose; - public Vector3f rightLegPose; -+ public boolean canMove = true; // Paper - - public EntityArmorStand(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -862,4 +864,13 @@ public class EntityArmorStand extends EntityLiving { - private EntitySize s(boolean flag) { - return flag ? EntityArmorStand.bp : (this.isBaby() ? EntityArmorStand.bq : this.getEntityType().l()); - } -+ -+ // Paper start -+ @Override -+ public void move(EnumMoveType moveType, Vec3D vec3d) { -+ if (this.canMove) { -+ super.move(moveType, vec3d); -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 86c8662b3864b264e26f8c63474fdd39bd6c873c..6f922e4cbb095439fcd76ee0d0c08bc4160b8107 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -229,4 +229,15 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public boolean hasEquipmentLock(EquipmentSlot equipmentSlot, LockType lockType) { - return (getHandle().disabledSlots & (1 << CraftEquipmentSlot.getNMS(equipmentSlot).getSlotFlag() + lockType.ordinal() * 8)) != 0; - } -+ // Paper start -+ @Override -+ public boolean canMove() { -+ return getHandle().canMove; -+ } -+ -+ @Override -+ public void setCanMove(boolean move) { -+ getHandle().canMove = move; -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch b/Unmapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch deleted file mode 100644 index 6cb65771f2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Tue, 27 Dec 2016 01:57:57 +0000 -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/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index e6dacf68cd678d64547dcdc23b1175a4cfd279d1..5b2ae94ed7d499e401a058691eb6ed413b626150 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -2069,8 +2069,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - @Override -- public boolean isFrozen() { -- return super.isFrozen() || !getBukkitEntity().isOnline(); -+ protected boolean isFrozen() { -+ return super.isFrozen() || (this.playerConnection != null && this.playerConnection.isDisconnected()); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 15daf87d6a6d80b5ebce5360e6999fd604c66cb5..d507d050f9a1ebd65383adb2b21699a01d9b0385 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2820,7 +2820,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - public final boolean isDisconnected() { -- return !this.player.joining && !this.networkManager.isConnected(); -+ return (!this.player.joining && !this.networkManager.isConnected()) || this.processedDisconnect; // Paper - } - // CraftBukkit end - diff --git a/Unmapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch b/Unmapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch deleted file mode 100644 index 08c66ad7f1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 27 Dec 2016 15:02:42 -0500 -Subject: [PATCH] String based Action Bar API - - -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index c8bb06a31242089ad950713bd5f94abbfe12adc8..68ce7605bd63ea280b96db8230463d2afb0a6cb1 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -58,7 +58,7 @@ public class SystemUtils { - private static final ExecutorService e = a("Main"); - private static final ExecutorService f = n(); - public static LongSupplier a = System::nanoTime; -- public static final UUID b = new UUID(0L, 0L); -+ public static final UUID b = new UUID(0L, 0L); public static final UUID getNullUUID() {return b;} // Paper OBFHELPER - private static final Logger LOGGER = LogManager.getLogger(); - - public static Collector, ?, Map> a() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 5698ef90bfeceec37eaf7f23361246ef125b3cd1..3ab71629699f4978cd2dab36ec7e3b32a1681f91 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -244,6 +244,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - // Paper start -+ @Override -+ public void sendActionBar(BaseComponent[] message) { -+ if (getHandle().playerConnection == null) return; -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, message, -1, -1, -1)); -+ } -+ -+ @Override -+ public void sendActionBar(String message) { -+ if (getHandle().playerConnection == null || message == null || message.isEmpty()) return; -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, CraftChatMessage.fromStringOrNull(message))); -+ } -+ -+ @Override -+ public void sendActionBar(char alternateChar, String message) { -+ if (message == null || message.isEmpty()) return; -+ sendActionBar(org.bukkit.ChatColor.translateAlternateColorCodes(alternateChar, message)); -+ } -+ - @Override - public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { - if (header != null) { diff --git a/Unmapped-Spigot-Server-Patches/0132-Firework-API-s.patch b/Unmapped-Spigot-Server-Patches/0132-Firework-API-s.patch deleted file mode 100644 index c220b785aa..0000000000 --- a/Unmapped-Spigot-Server-Patches/0132-Firework-API-s.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 28 Dec 2016 07:18:33 +0100 -Subject: [PATCH] Firework API's - - -diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -index bf4826e90976fed2ae95e84cadc7f29433af1ddf..d5508deff819309034554abc7b36aac40fa33503 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -@@ -153,6 +153,7 @@ public class NBTTagCompound implements NBTBase { - return GameProfileSerializer.a(this.get(s)); - } - -+ public final boolean hasUUID(String s) { return this.b(s); } // Paper - OBFHELPER - public boolean b(String s) { - NBTBase nbtbase = this.get(s); - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java -index 6ca5c8a4308c56d35bddbabc0be724325a8a73e3..ca7a10c4b04766d7eb55be9252e96ef939e76df3 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java -@@ -38,7 +38,8 @@ public class EntityFireworks extends IProjectile { - public static final DataWatcherObject SHOT_AT_ANGLE = DataWatcher.a(EntityFireworks.class, DataWatcherRegistry.i); - private int ticksFlown; - public int expectedLifespan; -- private EntityLiving ridingEntity; -+ public EntityLiving ridingEntity; // Paper - public -+ public java.util.UUID spawningEntity; // Paper - - public EntityFireworks(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -285,6 +286,11 @@ public class EntityFireworks extends IProjectile { - } - - nbttagcompound.setBoolean("ShotAtAngle", (Boolean) this.datawatcher.get(EntityFireworks.SHOT_AT_ANGLE)); -+ // Paper start -+ if (this.spawningEntity != null) { -+ nbttagcompound.setUUID("SpawningEntity", this.spawningEntity); -+ } -+ // Paper end - } - - @Override -@@ -301,7 +307,11 @@ public class EntityFireworks extends IProjectile { - if (nbttagcompound.hasKey("ShotAtAngle")) { - this.datawatcher.set(EntityFireworks.SHOT_AT_ANGLE, nbttagcompound.getBoolean("ShotAtAngle")); - } -- -+ // Paper start -+ if (nbttagcompound.hasUUID("SpawningEntity")) { -+ this.spawningEntity = nbttagcompound.getUUID("SpawningEntity"); -+ } -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/item/ItemCrossbow.java b/src/main/java/net/minecraft/world/item/ItemCrossbow.java -index d52f3cb5d76bde1cf29c654dade6d8379b44c2e5..ec6c0836f02e7ac5b72fd224a3022a844dce55cb 100644 ---- a/src/main/java/net/minecraft/world/item/ItemCrossbow.java -+++ b/src/main/java/net/minecraft/world/item/ItemCrossbow.java -@@ -205,6 +205,7 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable - - if (flag1) { - object = new EntityFireworks(world, itemstack1, entityliving, entityliving.locX(), entityliving.getHeadY() - 0.15000000596046448D, entityliving.locZ(), true); -+ ((EntityFireworks) object).spawningEntity = entityliving.getUniqueID(); // Paper - } else { - object = a(world, entityliving, itemstack, itemstack1); - if (flag || f3 != 0.0F) { -diff --git a/src/main/java/net/minecraft/world/item/ItemFireworks.java b/src/main/java/net/minecraft/world/item/ItemFireworks.java -index 9153945c2e245b9a2a098bdf58b0dcab052084ff..a2950faa48021782f10db0673d12d178443f7ccc 100644 ---- a/src/main/java/net/minecraft/world/item/ItemFireworks.java -+++ b/src/main/java/net/minecraft/world/item/ItemFireworks.java -@@ -27,6 +27,7 @@ public class ItemFireworks extends Item { - Vec3D vec3d = itemactioncontext.getPos(); - EnumDirection enumdirection = itemactioncontext.getClickedFace(); - EntityFireworks entityfireworks = new EntityFireworks(world, itemactioncontext.getEntity(), vec3d.x + (double) enumdirection.getAdjacentX() * 0.15D, vec3d.y + (double) enumdirection.getAdjacentY() * 0.15D, vec3d.z + (double) enumdirection.getAdjacentZ() * 0.15D, itemstack); -+ entityfireworks.spawningEntity = itemactioncontext.getEntity().getUniqueID(); // Paper - - world.addEntity(entityfireworks); - itemstack.subtract(1); -@@ -41,7 +42,11 @@ public class ItemFireworks extends Item { - ItemStack itemstack = entityhuman.b(enumhand); - - if (!world.isClientSide) { -- world.addEntity(new EntityFireworks(world, itemstack, entityhuman)); -+ // Paper start -+ final EntityFireworks entityfireworks = new EntityFireworks(world, itemstack, entityhuman); -+ entityfireworks.spawningEntity = entityhuman.getUniqueID(); -+ world.addEntity(entityfireworks); -+ // Paper end - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -index 33162fd419ab9a7b650ca9d4270a0c03f06f19f6..73c2da316e41329114fcb3d30cb009d9cc7de7b9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -@@ -1,6 +1,7 @@ - package org.bukkit.craftbukkit.entity; - - import java.util.Random; -+import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.projectile.EntityFireworks; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; -@@ -78,4 +79,17 @@ public class CraftFirework extends CraftProjectile implements Firework { - public void setShotAtAngle(boolean shotAtAngle) { - getHandle().getDataWatcher().set(EntityFireworks.SHOT_AT_ANGLE, shotAtAngle); - } -+ -+ // Paper start -+ @Override -+ public java.util.UUID getSpawningEntity() { -+ return getHandle().spawningEntity; -+ } -+ -+ @Override -+ public org.bukkit.entity.LivingEntity getBoostedEntity() { -+ EntityLiving boostedEntity = getHandle().ridingEntity; -+ return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null; -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch b/Unmapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch deleted file mode 100644 index 6e0a520b62..0000000000 --- a/Unmapped-Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 31 Dec 2016 21:44:50 -0500 -Subject: [PATCH] PlayerTeleportEndGatewayEvent - -Allows you to access the Gateway being used in a teleport event - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -index 0c5d9600eadc0a550cc2d5e7b4ee665c030faa89..2808cd0b100bd65a730aba315ab47a59a4621b30 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -@@ -10,6 +10,7 @@ import net.minecraft.data.worldgen.BiomeDecoratorGroups; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.MathHelper; -@@ -180,7 +181,7 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick - location.setPitch(player.getLocation().getPitch()); - location.setYaw(player.getLocation().getYaw()); - -- PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); -+ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(world, this.getPosition()).getBlock())); // Paper - Bukkit.getPluginManager().callEvent(teleEvent); - if (teleEvent.isCancelled()) { - return; diff --git a/Unmapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch b/Unmapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch deleted file mode 100644 index 753735ecac..0000000000 --- a/Unmapped-Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 15:24:46 -0500 -Subject: [PATCH] Provide E/TE/Chunk count stat methods - -Provides counts without the ineffeciency of using .getEntities().size() -which creates copy of the collections. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index b50ed67714fea93fc6708f2680ae909f403deb00..29f5311260d0d5ee321db94031ffc3ed528d6b02 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -282,6 +282,48 @@ public class CraftWorld implements World { - private int waterAmbientSpawn = -1; - private int ambientSpawn = -1; - -+ // Paper start - Provide fast information methods -+ public int getEntityCount() { -+ int ret = 0; -+ for (net.minecraft.world.entity.Entity entity : world.entitiesById.values()) { -+ if (entity.isChunkLoaded()) { -+ ++ret; -+ } -+ } -+ return ret; -+ } -+ public int getTileEntityCount() { -+ // We don't use the full world tile entity list, so we must iterate chunks -+ Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; -+ int size = 0; -+ for (PlayerChunk playerchunk : chunks.values()) { -+ net.minecraft.world.level.chunk.Chunk chunk = playerchunk.getChunk(); -+ if (chunk == null) { -+ continue; -+ } -+ size += chunk.tileEntities.size(); -+ } -+ return size; -+ } -+ public int getTickableTileEntityCount() { -+ return world.tileEntityListTick.size(); -+ } -+ public int getChunkCount() { -+ int ret = 0; -+ -+ for (PlayerChunk chunkHolder : world.getChunkProvider().playerChunkMap.visibleChunks.values()) { -+ if (chunkHolder.getChunk() != null) { -+ ++ret; -+ } -+ } -+ -+ return ret; -+ } -+ public int getPlayerCount() { -+ return world.players.size(); -+ } -+ // Paper end -+ - private static final Random rand = new Random(); - - public CraftWorld(WorldServer world, ChunkGenerator gen, Environment env) { diff --git a/Unmapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch b/Unmapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch deleted file mode 100644 index 92ee3f9334..0000000000 --- a/Unmapped-Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 15:41:58 -0500 -Subject: [PATCH] Enforce Sync Player Saves - -Saving players async is extremely dangerous. This will force it to main -the same way we handle async chunk loads. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 49f1aed92fd5fa46b74a979f317a2eb0672991e9..f0928684f2bb56b490bea7cd80eb9300d2647f0c 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1047,11 +1047,13 @@ public abstract class PlayerList { - } - - public void savePlayers() { -+ MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { - this.savePlayerFile((EntityPlayer) this.players.get(i)); - } - MinecraftTimings.savePlayers.stopTiming(); // Paper -+ return null; }); // Paper - ensure main - } - - public WhiteList getWhitelist() { diff --git a/Unmapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch b/Unmapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch deleted file mode 100644 index 1b3ac3e9b4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Sun, 8 Jan 2017 04:31:36 +0000 -Subject: [PATCH] Don't allow entities to ride themselves - #572 - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d314cdd9341e6aa5748a5b1afdd9569bec956c74..00e79363b3f961111595c50758332f6c1c1b31bb 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2046,6 +2046,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - protected boolean addPassenger(Entity entity) { // CraftBukkit -+ if (entity == this) throw new IllegalArgumentException("Entities cannot become a passenger of themselves"); // Paper - issue 572 - if (entity.getVehicle() != this) { - throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)"); - } else { diff --git a/Unmapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/Unmapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch deleted file mode 100644 index 1fd6d1e437..0000000000 --- a/Unmapped-Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch +++ /dev/null @@ -1,315 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 16:31:46 -0500 -Subject: [PATCH] ExperienceOrbs API for Reason/Source/Triggering player - -Adds lots of information about why this orb exists. - -Replaces isFromBottle() with logic that persists entity reloads too. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 164fd6b867bc68f6aba3fa2c17371e87495baea3..74b4b127f39a0ad06e8f9add6861763724ab70ba 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -409,7 +409,7 @@ public class PlayerInteractManager { - - // Drop event experience - if (flag && event != null) { -- iblockdata.getBlock().dropExperience(this.world, blockposition, event.getExpToDrop()); -+ iblockdata.getBlock().dropExperience(this.world, blockposition, event.getExpToDrop(), this.player); // Paper - } - - return true; -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index a17812943b5402684c68ddeac5408dc939e42cf6..f4da22b33c704e675510b4b1a3aa7c180088be29 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -31,9 +31,59 @@ public class EntityExperienceOrb extends Entity { - public int value; - private EntityHuman targetPlayer; - private int targetTime; -+ // Paper start -+ public java.util.UUID sourceEntityId; -+ public java.util.UUID triggerEntityId; -+ public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; -+ -+ private void loadPaperNBT(NBTTagCompound nbttagcompound) { -+ if (!nbttagcompound.hasKeyOfType("Paper.ExpData", 10)) { // 10 = compound -+ return; -+ } -+ NBTTagCompound comp = nbttagcompound.getCompound("Paper.ExpData"); -+ if (comp.hasUUID("source")) { -+ this.sourceEntityId = comp.getUUID("source"); -+ } -+ if (comp.hasUUID("trigger")) { -+ this.triggerEntityId = comp.getUUID("trigger"); -+ } -+ if (comp.hasKey("reason")) { -+ String reason = comp.getString("reason"); -+ try { -+ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason); -+ } catch (Exception e) { -+ this.world.getServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason); -+ } -+ } -+ } -+ private void savePaperNBT(NBTTagCompound nbttagcompound) { -+ NBTTagCompound comp = new NBTTagCompound(); -+ if (this.sourceEntityId != null) { -+ comp.setUUID("source", this.sourceEntityId); -+ } -+ if (this.triggerEntityId != null) { -+ comp.setUUID("trigger", triggerEntityId); -+ } -+ if (this.spawnReason != null && this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) { -+ comp.setString("reason", this.spawnReason.name()); -+ } -+ nbttagcompound.set("Paper.ExpData", comp); -+ } - - public EntityExperienceOrb(World world, double d0, double d1, double d2, int i) { -+ this(world, d0, d1, d2, i, null, null); -+ } -+ -+ public EntityExperienceOrb(World world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { -+ this(world, d0, d1, d2, i, reason, triggerId, null); -+ } -+ -+ public EntityExperienceOrb(World world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { - this(EntityTypes.EXPERIENCE_ORB, world); -+ this.sourceEntityId = sourceId != null ? sourceId.getUniqueID() : null; -+ this.triggerEntityId = triggerId != null ? triggerId.getUniqueID() : null; -+ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; -+ // Paper end - this.setPosition(d0, d1, d2); - this.yaw = (float) (this.random.nextDouble() * 360.0D); - this.setMot((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D); -@@ -168,6 +218,7 @@ public class EntityExperienceOrb extends Entity { - nbttagcompound.setShort("Health", (short) this.e); - nbttagcompound.setShort("Age", (short) this.c); - nbttagcompound.setShort("Value", (short) this.value); -+ this.savePaperNBT(nbttagcompound); // Paper - } - - @Override -@@ -175,6 +226,7 @@ public class EntityExperienceOrb extends Entity { - this.e = nbttagcompound.getShort("Health"); - this.c = nbttagcompound.getShort("Age"); - this.value = nbttagcompound.getShort("Value"); -+ this.loadPaperNBT(nbttagcompound); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index db5c0d2da9ed9993ee83adccfa74e77f4e364f2a..f26f02856e7cca0ca62325adf992619dd15b3885 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -1594,7 +1594,8 @@ public abstract class EntityLiving extends Entity { - int j = EntityExperienceOrb.getOrbValue(i); - - i -= j; -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j)); -+ EntityLiving attacker = killer != null ? killer : lastDamager; // Paper -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j, this instanceof EntityPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this)); // Paper - } - this.expToDrop = 0; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java -index b9a681c2f7435c38dda074fbabbf53974ebbc705..4de0a733819d408e8b9a55b604f455281d7732c5 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java -@@ -262,7 +262,7 @@ public abstract class EntityAnimal extends EntityAgeable { - if (worldserver.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { - // CraftBukkit start - use event experience - if (experience > 0) { -- worldserver.addEntity(new EntityExperienceOrb(worldserver, this.locX(), this.locY(), this.locZ(), experience)); -+ worldserver.addEntity(new EntityExperienceOrb(worldserver, this.locX(), this.locY(), this.locZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper - } - // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -index c1e3b90098605cf809aa2ecfb5edc0ad78f2257c..77de0706aaa32b565cb1e14754e93a1c4a6e15bd 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -@@ -1306,7 +1306,7 @@ public class EntityFox extends EntityAnimal { - if (this.b.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { - // CraftBukkit start - use event experience - if (experience > 0) { -- this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), experience)); -+ this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityfox)); // Paper - } - // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -index 5d08b83e2832cad2c8726ae817e003d970bc52a0..bf224c97854daa379c61affff6a0ac9524c2c35d 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -@@ -561,7 +561,7 @@ public class EntityTurtle extends EntityAnimal { - Random random = this.animal.getRandom(); - - if (this.b.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { -- this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), random.nextInt(7) + 1)); -+ this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), random.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper; - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 74802de01dba30e38e09f6fc1f61e7bb64cf5f09..97ef4c65c8cc569a99d9697f56bd44d32b151328 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -661,7 +661,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - int j = EntityExperienceOrb.getOrbValue(i); - - i -= j; -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j)); -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.killer, this)); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 72ed4de72c87e9c241507838ddb42eaa4c05ef32..881bca30d2271560e2f2063f7d50753ec67a23f6 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -600,7 +600,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - - if (merchantrecipe.isRewardExp()) { -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i)); -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTrader(), this)); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -index 46da22aeef6132a96e413301935c4fef7a96e0ee..4f81a97b1451fec0bb5fd1479acad97846c40c7c 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -@@ -189,7 +189,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - if (merchantrecipe.isRewardExp()) { - int i = 3 + this.random.nextInt(4); - -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i)); -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTrader(), this)); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 2067af9b13c7ce28cd8ad6c785e2d0a7ff013430..38bcc5a4435c4018b3233cc5e4c9142259e4396d 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -@@ -503,7 +503,7 @@ public class EntityFishingHook extends IProjectile { - this.world.addEntity(entityitem); - // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() - if (playerFishEvent.getExpToDrop() > 0) { -- entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop())); -+ entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getOwner(), this)); // Paper - } - // CraftBukkit end - if (itemstack1.getItem().a((Tag) TagsItem.FISHES)) { -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java b/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java -index 87fe16c81b57ba07399f5566ab8bd77d71db36a1..e07353a6b34196e3d275ba482fbef7e4d209c31d 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java -@@ -54,7 +54,7 @@ public class EntityThrownExpBottle extends EntityProjectileThrowable { - int j = EntityExperienceOrb.getOrbValue(i); - - i -= j; -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j)); -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, getShooter(), this)); // Paper - } - - this.die(); -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -index cba1de50f3035ae1b9366f474745d50a1f8fc014..fad7355a549aef811bca43be198af3d1c0a53980 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -@@ -94,7 +94,7 @@ public class ContainerGrindstone extends Container { - int k = EntityExperienceOrb.getOrbValue(j); - - j -= k; -- world.addEntity(new EntityExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k)); -+ world.addEntity(new EntityExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k, org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, entityhuman)); // Paper - } - - world.triggerEffect(1042, blockposition, 0); -diff --git a/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java b/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java -index 48324295913dd9a9bd31332b5b811a729b621dfb..a114e576e5d80c25cc7f2b17f0dc3ad706a1b877 100644 ---- a/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java -+++ b/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java -@@ -7,7 +7,7 @@ import net.minecraft.world.level.block.entity.TileEntityFurnace; - - public class SlotFurnaceResult extends Slot { - -- private final EntityHuman a; -+ private final EntityHuman a; public final EntityHuman getPlayer() { return this.a; } // Paper OBFHELPER - private int b; - - public SlotFurnaceResult(EntityHuman entityhuman, IInventory iinventory, int i, int j, int k) { -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index d285c4e3d9f938973bf7fb904680044b414e6236..615a4418fd276cd3e0b3686d962ebaf13ef5d4be 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -267,13 +267,13 @@ public class Block extends BlockBase implements IMaterial { - } - } - -- public void dropExperience(WorldServer worldserver, BlockPosition blockposition, int i) { -+ public void dropExperience(WorldServer worldserver, BlockPosition blockposition, int i, net.minecraft.server.level.EntityPlayer player) { // Paper - if (worldserver.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) { - while (i > 0) { - int j = EntityExperienceOrb.getOrbValue(i); - - i -= j; -- worldserver.addEntity(new EntityExperienceOrb(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j)); -+ worldserver.addEntity(new EntityExperienceOrb(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player)); // Paper - } - } - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index 9744d51a52c5eb99c4cf9e36d9380c49674dd136..deaa4c136c23dc6c258cc1ce68523b3c007c80f9 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -603,7 +603,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - int k = EntityExperienceOrb.getOrbValue(j); - - j -= k; -- world.addEntity(new EntityExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k)); -+ world.addEntity(new EntityExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman)); // Paper - } - - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 29f5311260d0d5ee321db94031ffc3ed528d6b02..d7d58a0feac2d0b4303c625b7952103613e8c33e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1835,7 +1835,7 @@ public class CraftWorld implements World { - } else if (TNTPrimed.class.isAssignableFrom(clazz)) { - entity = new EntityTNTPrimed(world, x, y, z, null); - } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { -- entity = new EntityExperienceOrb(world, x, y, z, 0); -+ entity = new EntityExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper - } else if (LightningStrike.class.isAssignableFrom(clazz)) { - entity = EntityTypes.LIGHTNING_BOLT.a(world); - } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -index da14f59aec2b6854c3a47fb531aadc9ddb74954c..c6880830720baa2723ab003e51be1b48574d7319 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -@@ -20,6 +20,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { - getHandle().value = value; - } - -+ // Paper start -+ public java.util.UUID getTriggerEntityId() { -+ return getHandle().triggerEntityId; -+ } -+ public java.util.UUID getSourceEntityId() { -+ return getHandle().sourceEntityId; -+ } -+ public SpawnReason getSpawnReason() { -+ return getHandle().spawnReason; -+ } -+ // Paper end -+ - @Override - public EntityExperienceOrb getHandle() { - return (EntityExperienceOrb) entity; diff --git a/Unmapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch b/Unmapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch deleted file mode 100644 index d620a07721..0000000000 --- a/Unmapped-Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 22 Jan 2017 18:07:56 -0500 -Subject: [PATCH] Cap Entity Collisions - -Limit a single entity to colliding a max of configurable times per tick. -This will alleviate issues where living entities are hoarded in 1x1 pens - -This is not tied to the maxEntityCramming rule. Cramming will still apply -just as it does in Vanilla, but entity pushing logic will be capped. - -You can set this to 0 to disable collisions. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2dc58b9f769ea43b737804456aafab47ecc143b8..c611b5a63498f5ad1f50a75ccd5d7299e27df7e3 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -324,4 +324,10 @@ public class PaperWorldConfig { - log("Treasure Maps will return already discovered locations"); - } - } -+ -+ public int maxCollisionsPerEntity; -+ private void maxEntityCollision() { -+ maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); -+ log( "Max Entity Collisions: " + maxCollisionsPerEntity ); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 00e79363b3f961111595c50758332f6c1c1b31bb..dcaf5c107bb77b63333f924a33961f9e5cad7082 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -268,6 +268,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; -+ protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index f26f02856e7cca0ca62325adf992619dd15b3885..dd9c51b28e32389429887e9c9cef0a554eff8a40 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -2903,8 +2903,11 @@ public abstract class EntityLiving extends Entity { - } - } - -- for (j = 0; j < list.size(); ++j) { -+ numCollisions = Math.max(0, numCollisions - world.paperConfig.maxCollisionsPerEntity); // Paper -+ for (j = 0; j < list.size() && numCollisions < world.paperConfig.maxCollisionsPerEntity; ++j) { // Paper - Entity entity = (Entity) list.get(j); -+ entity.numCollisions++; // Paper -+ numCollisions++; // Paper - - this.C(entity); - } diff --git a/Unmapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch b/Unmapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch deleted file mode 100644 index db58842a96..0000000000 --- a/Unmapped-Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 5 Feb 2017 00:04:04 -0500 -Subject: [PATCH] Remove CraftScheduler Async Task Debugger - -I have not once ever seen this system help debug a crash. -One report of a suspected memory leak with the system. - -This adds additional overhead to asynchronous task dispatching - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 9b6d9373abb59a30c2835ca891282d07559281f5..0e0f361c3af363539d5d1d865603114bdb84fd67 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -430,7 +430,7 @@ public class CraftScheduler implements BukkitScheduler { - } - parsePending(); - } else { -- debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); -+ //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper - executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper - // We don't need to parse pending - // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) -@@ -447,7 +447,7 @@ public class CraftScheduler implements BukkitScheduler { - pending.addAll(temp); - temp.clear(); - MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); -- debugHead = debugHead.getNextHead(currentTick); -+ //debugHead = debugHead.getNextHead(currentTick); // Paper - } - - private void addTask(final CraftTask task) { -@@ -507,10 +507,15 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public String toString() { -+ // Paper start -+ return ""; -+ /* - int debugTick = currentTick; - StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - RECENT_TICKS).append('-').append(debugTick).append('{'); - debugHead.debugTo(string); - return string.append('}').toString(); -+ */ -+ // Paper end - } - - @Deprecated diff --git a/Unmapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/Unmapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch deleted file mode 100644 index 3d1bc3912d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 7 Feb 2017 16:55:35 -0600 -Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 2511fbe7aa5ff1ace71b513d2938975e388295c6..1d71a19a7bbe463f537861531113dd1ed3e5b977 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -121,7 +121,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final PlayerMap playerMap; - public final Int2ObjectMap trackedEntities; - private final Long2ByteMap z; -- private final Queue A; -+ private final Queue A; private final Queue getUnloadQueueTasks() { return this.A; } // Paper - OBFHELPER - private int viewDistance; - - // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() -@@ -179,7 +179,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerMap = new PlayerMap(); - this.trackedEntities = new Int2ObjectOpenHashMap(); - this.z = new Long2ByteOpenHashMap(); -- this.A = Queues.newConcurrentLinkedQueue(); -+ this.A = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size() - this.definedStructureManager = definedstructuremanager; - this.w = convertable_conversionsession.a(worldserver.getDimensionKey()); - this.world = worldserver; -@@ -437,7 +437,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Spigot start - org.spigotmc.SlackActivityAccountant activityAccountant = this.world.getMinecraftServer().slackActivityAccountant; - activityAccountant.startActivity(0.5); -- int targetSize = (int) (this.unloadQueue.size() * UNLOAD_QUEUE_RESIZE_FACTOR); -+ int targetSize = Math.min(this.unloadQueue.size() - 100, (int) (this.unloadQueue.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive - // Spigot end - while (longiterator.hasNext()) { // Spigot - long j = longiterator.nextLong(); -@@ -459,7 +459,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - Runnable runnable; - -- while ((booleansupplier.getAsBoolean() || this.A.size() > 2000) && (runnable = (Runnable) this.A.poll()) != null) { -+ int queueTarget = Math.min(this.getUnloadQueueTasks().size() - 100, (int) (this.getUnloadQueueTasks().size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well -+ while ((booleansupplier.getAsBoolean() || this.getUnloadQueueTasks().size() > queueTarget) && (runnable = (Runnable)this.getUnloadQueueTasks().poll()) != null) { // Paper - Target this queue as well - runnable.run(); - } - diff --git a/Unmapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch b/Unmapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch deleted file mode 100644 index 4141d9b9b2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 18 Feb 2017 19:29:58 -0600 -Subject: [PATCH] Do not let armorstands drown - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index dd9c51b28e32389429887e9c9cef0a554eff8a40..036577b0237e9c8a7ab22ede7477eefa1abecf96 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -338,6 +338,7 @@ public abstract class EntityLiving extends Entity { - super.a(d0, flag, iblockdata, blockposition); - } - -+ public boolean canBreatheUnderwater() { return this.cM(); } // Paper - OBFHELPER - public boolean cM() { - return this.getMonsterType() == EnumMonsterType.UNDEAD; - } -@@ -381,7 +382,7 @@ public abstract class EntityLiving extends Entity { - - if (this.isAlive()) { - if (this.a((Tag) TagsFluid.WATER) && !this.world.getType(new BlockPosition(this.locX(), this.getHeadY(), this.locZ())).a(Blocks.BUBBLE_COLUMN)) { -- if (!this.cM() && !MobEffectUtil.c(this) && !flag1) { -+ if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { // Paper - use OBFHELPER so it can be overridden - this.setAirTicks(this.l(this.getAirTicks())); - if (this.getAirTicks() == -20) { - this.setAirTicks(0); -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 2ef991aa7f739d3577fbbf4386064557e8f7c904..57e0ea95df34fab22d6c5868ab839d56a3fa85fc 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -872,5 +872,10 @@ public class EntityArmorStand extends EntityLiving { - super.move(moveType, vec3d); - } - } -+ -+ @Override -+ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization -+ return true; -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch b/Unmapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch deleted file mode 100644 index 108fec7080..0000000000 --- a/Unmapped-Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch +++ /dev/null @@ -1,307 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 12 May 2017 23:34:11 -0500 -Subject: [PATCH] Properly handle async calls to restart the server - -The watchdog thread calls the server restart function asynchronously. Prior to -this change, it attempted to do several non-safe operations from the watchdog -thread, rather than the main. Specifically, because of a separate upstream change, -it causes player entities to be ticked asynchronously, among other things. - -This is dangerous. - -This patch moves the old handling into a synchronous variant, for calls from the -restart command, and adds separate handling for async calls, such as those from -the watchdog thread. - -When calling from the watchdog thread, we cannot assume the main thread is in a -tickable state; it may be completely deadlocked. In order to handle this, we mark -the server as stopping, in order to account for situations where the server should -complete a tick reasonbly soon, i.e. 99% of cases. - -Should the server not enter a state where it is stopping within 10 seconds, We -will assume that the server has in fact deadlocked and will proceed to force -kill the server. - -This modification does not force restart the server should we actually enter a -deadlocked state where the server is stopping, whereas this will in most cases -exit within a reasonable amount of time, to put a fixed limit on a process that -will have plugins and worlds saving to the disk has a high potential to result -in corruption/dataloss. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 20dffd9dc4cb3868638151b70535f353a3bf1a44..fae7e4a7adcc930a7252634dc535339b5a5bd3b9 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -201,6 +201,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant, WorldServer> worldServer; - private PlayerList playerList; - private volatile boolean isRunning; -+ private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart - private boolean isStopped; - private int ticks; - protected final Proxy proxy; -@@ -860,7 +861,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && new File( split[0] ).isFile() ) -+ // Paper - extract method and cleanup -+ boolean isRestarting = addShutdownHook( restartScript ); -+ if ( isRestarting ) - { -- System.out.println( "Attempting to restart with " + restartScript ); -+ System.out.println( "Attempting to restart with " + SpigotConfig.restartScript ); -+ } else -+ { -+ System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); -+ } -+ // Stop the watchdog -+ WatchdogThread.doStop(); - -- // Disable Watchdog -- WatchdogThread.doStop(); -+ shutdownServer( isRestarting ); -+ // Paper end -+ } catch ( Exception ex ) -+ { -+ ex.printStackTrace(); -+ } -+ } - -- // Kick all players -- for ( EntityPlayer p : (List) MinecraftServer.getServer().getPlayerList().players ) -- { -- p.playerConnection.disconnect(SpigotConfig.restartMessage); -- } -- // Give the socket a chance to send the packets -- try -- { -- Thread.sleep( 100 ); -- } catch ( InterruptedException ex ) -- { -- } -- // Close the socket so we can rebind with the new process -- MinecraftServer.getServer().getServerConnection().b(); -+ // Paper start - sync copied from above with minor changes, async added -+ private static void shutdownServer(boolean isRestarting) -+ { -+ if ( MinecraftServer.getServer().isMainThread() ) -+ { -+ // Kick all players -+ for ( EntityPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) -+ { -+ p.playerConnection.disconnect(SpigotConfig.restartMessage); -+ } -+ // Give the socket a chance to send the packets -+ try -+ { -+ Thread.sleep( 100 ); -+ } catch ( InterruptedException ex ) -+ { -+ } - -- // Give time for it to kick in -- try -- { -- Thread.sleep( 100 ); -- } catch ( InterruptedException ex ) -- { -- } -+ closeSocket(); - -- // Actually shutdown -- try -- { -- MinecraftServer.getServer().close(); -- } catch ( Throwable t ) -- { -- } -+ // Actually shutdown -+ try -+ { -+ MinecraftServer.getServer().close(); // calls stop() -+ } catch ( Throwable t ) -+ { -+ } -+ -+ // Actually stop the JVM -+ System.exit( 0 ); - -- // This will be done AFTER the server has completely halted -- Thread shutdownHook = new Thread() -+ } else -+ { -+ // Mark the server to shutdown at the end of the tick -+ MinecraftServer.getServer().safeShutdown( false, isRestarting ); -+ -+ // wait 10 seconds to see if we're actually going to try shutdown -+ try -+ { -+ Thread.sleep( 10000 ); -+ } -+ catch (InterruptedException ignored) -+ { -+ } -+ -+ // Check if we've actually hit a state where the server is going to safely shutdown -+ // if we have, let the server stop as usual -+ if (MinecraftServer.getServer().isStopped()) return; -+ -+ // If the server hasn't stopped by now, assume worse case and kill -+ closeSocket(); -+ System.exit( 0 ); -+ } -+ } -+ // Paper end -+ -+ // Paper - Split from moved code -+ private static void closeSocket() -+ { -+ // Close the socket so we can rebind with the new process -+ MinecraftServer.getServer().getServerConnection().b(); -+ -+ // Give time for it to kick in -+ try -+ { -+ Thread.sleep( 100 ); -+ } catch ( InterruptedException ex ) -+ { -+ } -+ } -+ // Paper end -+ -+ // Paper start - copied from above and modified to return if the hook registered -+ private static boolean addShutdownHook(String restartScript) -+ { -+ String[] split = restartScript.split( " " ); -+ if ( split.length > 0 && new File( split[0] ).isFile() ) -+ { -+ Thread shutdownHook = new Thread() -+ { -+ @Override -+ public void run() - { -- @Override -- public void run() -+ try - { -- try -+ String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); -+ if ( os.contains( "win" ) ) - { -- String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); -- if ( os.contains( "win" ) ) -- { -- Runtime.getRuntime().exec( "cmd /c start " + restartScript ); -- } else -- { -- Runtime.getRuntime().exec( "sh " + restartScript ); -- } -- } catch ( Exception e ) -+ Runtime.getRuntime().exec( "cmd /c start " + restartScript ); -+ } else - { -- e.printStackTrace(); -+ Runtime.getRuntime().exec( "sh " + restartScript ); - } -+ } catch ( Exception e ) -+ { -+ e.printStackTrace(); - } -- }; -- -- shutdownHook.setDaemon( true ); -- Runtime.getRuntime().addShutdownHook( shutdownHook ); -- } else -- { -- System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); -- -- // Actually shutdown -- try -- { -- MinecraftServer.getServer().close(); -- } catch ( Throwable t ) -- { - } -- } -- System.exit( 0 ); -- } catch ( Exception ex ) -+ }; -+ -+ shutdownHook.setDaemon( true ); -+ Runtime.getRuntime().addShutdownHook( shutdownHook ); -+ return true; -+ } else - { -- ex.printStackTrace(); -+ return false; - } - } -+ // Paper end -+ - } diff --git a/Unmapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch b/Unmapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch deleted file mode 100644 index dd733c5fb3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 13 May 2017 20:11:21 -0500 -Subject: [PATCH] Add system property to disable book size limits - -If anyone comes in with a watchdog crash related to books after this patch -you will not only be publicly shamed but also made an example of. - -Disables the security limits on books entirely, allowing plugins AND players -to make books with as much data as they want. Do not use this without -limiting incoming data from packets in some other way. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index 65b6d32e3e1130a64df33082f3292cb1ce6f500a..1a4c1763e883e445433b3780fe20db7f62b780e8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -41,6 +41,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - static final int MAX_PAGES = 100; - static final int MAX_PAGE_LENGTH = 320; // 256 limit + 64 characters to allow for psuedo colour codes - static final int MAX_TITLE_LENGTH = 32; -+ private static final boolean OVERRIDE_CHECKS = Boolean.getBoolean("disable.book-limits"); // Paper - Add override - - protected String title; - protected String author; -@@ -243,7 +244,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - if (title == null) { - this.title = null; - return true; -- } else if (title.length() > MAX_TITLE_LENGTH) { -+ } else if (title.length() > MAX_TITLE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override - return false; - } - -@@ -440,7 +441,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - String validatePage(String page) { - if (page == null) { - page = ""; -- } else if (page.length() > MAX_PAGE_LENGTH) { -+ } else if (page.length() > MAX_PAGE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override - page = page.substring(0, MAX_PAGE_LENGTH); - } - return page; -@@ -450,7 +451,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - // asserted: page != null - if (this.pages == null) { - this.pages = new ArrayList(); -- } else if (this.pages.size() >= MAX_PAGES) { -+ } else if (this.pages.size() >= MAX_PAGES && !OVERRIDE_CHECKS) {// Paper - Add override - return; - } - this.pages.add(page); diff --git a/Unmapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/Unmapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch deleted file mode 100644 index bc90566e9b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 16 May 2017 21:29:08 -0500 -Subject: [PATCH] Add option to make parrots stay on shoulders despite movement - -Makes parrots not fall off whenever the player changes height, or touches water, or gets hit by a passing leaf. -Instead, switches the behavior so that players have to sneak to make the birds leave. - -I suspect Mojang may switch to this behavior before full release. - -To be converted into a Paper-API event at some point in the future? - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c611b5a63498f5ad1f50a75ccd5d7299e27df7e3..9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -330,4 +330,10 @@ public class PaperWorldConfig { - maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); - log( "Max Entity Collisions: " + maxCollisionsPerEntity ); - } -+ -+ public boolean parrotsHangOnBetter; -+ private void parrotsHangOnBetter() { -+ parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); -+ log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index d507d050f9a1ebd65383adb2b21699a01d9b0385..8c39dc4f05becea92f3ec86c4103be4e34f2b835 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2053,6 +2053,13 @@ public class PlayerConnection implements PacketListenerPlayIn { - switch (packetplayinentityaction.c()) { - case PRESS_SHIFT_KEY: - this.player.setSneaking(true); -+ -+ // Paper start - Hang on! -+ if (this.player.world.paperConfig.parrotsHangOnBetter) { -+ this.player.releaseShoulderEntities(); -+ } -+ // Paper end -+ - break; - case RELEASE_SHIFT_KEY: - this.player.setSneaking(false); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index e3e3426a00128b56d523bb43a59b814b915ad0ff..ba26fc2405e17d582da971d03147fb1865e9b546 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -532,7 +532,7 @@ public abstract class EntityHuman extends EntityLiving { - this.j(this.getShoulderEntityLeft()); - this.j(this.getShoulderEntityRight()); - if (!this.world.isClientSide && (this.fallDistance > 0.5F || this.isInWater()) || this.abilities.isFlying || this.isSleeping()) { -- this.releaseShoulderEntities(); -+ if (!this.world.paperConfig.parrotsHangOnBetter) this.releaseShoulderEntities(); // Paper - Hang on! - } - - } diff --git a/Unmapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch b/Unmapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch deleted file mode 100644 index 1d7d21727e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Fri, 9 Jun 2017 07:24:34 -0700 -Subject: [PATCH] Add configuration option to prevent player names from being - suggested - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 4e2f243faa209925dcb7c3ef89df3ed875c5ff78..48319aaf1c525c6fb7bdee5c2f570a0d056d4eae 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -268,4 +268,9 @@ public class PaperConfig { - flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); - flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); - } -+ -+ public static boolean suggestPlayersWhenNullTabCompletions = true; -+ private static void suggestPlayersWhenNull() { -+ suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 539577a0378754cbe0942a79140f6d137eb825ed..0ed8e95d464cf17dc0355056775a9a375a4e7a86 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2301,5 +2301,10 @@ public final class CraftServer implements Server { - commandMap.registerServerAliases(); - return true; - } -+ -+ @Override -+ public boolean suggestPlayerNamesWhenNullTabCompletions() { -+ return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch b/Unmapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch deleted file mode 100644 index 80016ae985..0000000000 --- a/Unmapped-Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch +++ /dev/null @@ -1,549 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Fri, 9 Jun 2017 19:03:43 +0200 -Subject: [PATCH] Use TerminalConsoleAppender for console improvements - -Rewrite console improvements (console colors, tab completion, -persistent input line, ...) using JLine 3.x and TerminalConsoleAppender. - -New features: - - Support console colors for Vanilla commands - - Add console colors for warnings and errors - - Server can now be turned off safely using CTRL + C. JLine catches - the signal and the implementation shuts down the server cleanly. - - Support console colors and persistent input line when running in - IntelliJ IDEA - -Other changes: - - Server starts 1-2 seconds faster thanks to optimizations in Log4j - configuration - -diff --git a/pom.xml b/pom.xml -index a5d87d22cb1588d15e08da3b37e51c5e261c7799..3841fe3630c090f8a468333d43caeb2b5841329d 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -57,10 +57,26 @@ - compile - - -- jline -- jline -- 2.12.1 -- compile -+ net.minecrell -+ terminalconsoleappender -+ 1.2.0 -+ -+ -+ org.jline -+ jline-terminal-jansi -+ 3.12.1 -+ runtime -+ -+ -+ -+ org.apache.logging.log4j -+ log4j-core -+ runtime - - - org.apache.logging.log4j -@@ -334,10 +350,18 @@ - - META-INF/services/java.sql.Driver - -+ - - - - -+ -+ -+ com.github.edwgiz -+ maven-shade-plugin.log4j2-cachefile-transformer -+ 2.13.1 -+ -+ - - - org.apache.maven.plugins -diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -new file mode 100644 -index 0000000000000000000000000000000000000000..89eeb9d202405747409e65fcf226d95379987e29 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.console; -+ -+import net.minecraft.server.dedicated.DedicatedServer; -+import net.minecrell.terminalconsole.SimpleTerminalConsole; -+import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; -+import org.jline.reader.LineReader; -+import org.jline.reader.LineReaderBuilder; -+ -+public final class PaperConsole extends SimpleTerminalConsole { -+ -+ private final DedicatedServer server; -+ -+ public PaperConsole(DedicatedServer server) { -+ this.server = server; -+ } -+ -+ @Override -+ protected LineReader buildReader(LineReaderBuilder builder) { -+ return super.buildReader(builder -+ .appName("Paper") -+ .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) -+ .completer(new ConsoleCommandCompleter(this.server)) -+ ); -+ } -+ -+ @Override -+ protected boolean isRunning() { -+ return !this.server.isStopped() && this.server.isRunning(); -+ } -+ -+ @Override -+ protected void runCommand(String command) { -+ this.server.issueCommand(command, this.server.getServerCommandListener()); -+ } -+ -+ @Override -+ protected void shutdown() { -+ this.server.safeShutdown(false); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java -new file mode 100644 -index 0000000000000000000000000000000000000000..685deaa0e5d1ddc13e3a7c0471b1cfcf1710c869 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.console; -+ -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; -+import org.bukkit.craftbukkit.command.CraftConsoleCommandSender; -+ -+public class TerminalConsoleCommandSender extends CraftConsoleCommandSender { -+ -+ private static final Logger LOGGER = LogManager.getRootLogger(); -+ -+ @Override -+ public void sendRawMessage(String message) { -+ // TerminalConsoleAppender supports color codes directly in log messages -+ LOGGER.info(message); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index fae7e4a7adcc930a7252634dc535339b5a5bd3b9..71496fff9faeb72e28dfc2842ed8105a9cb835c1 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -12,6 +12,7 @@ import com.mojang.datafixers.DataFixer; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -160,7 +161,7 @@ import org.apache.logging.log4j.Logger; - import com.mojang.serialization.DynamicOps; - import com.mojang.serialization.Lifecycle; - import com.google.common.collect.ImmutableSet; --import jline.console.ConsoleReader; -+// import jline.console.ConsoleReader; // Paper - import joptsimple.OptionSet; - import net.minecraft.nbt.DynamicOpsNBT; - import net.minecraft.nbt.NBTBase; -@@ -255,7 +256,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; -@@ -324,7 +325,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant replacements = new EnumMap(ChatColor.class); - private final ChatColor[] colors = ChatColor.values(); -@@ -93,5 +91,5 @@ public class ColouredConsoleSender extends CraftConsoleCommandSender { - } else { - return new ColouredConsoleSender(); - } -- } -+ }*/ // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index befcc19f9b56df9096b98a23b0020f1db793ea5b..a957695457cf3252848ce6ef37069692841b8e28 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -4,20 +4,31 @@ import java.util.Collections; - import java.util.List; - import java.util.concurrent.ExecutionException; - import java.util.logging.Level; --import jline.console.completer.Completer; -+import net.minecraft.server.dedicated.DedicatedServer; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.util.Waitable; -+ -+// Paper start - JLine update -+import org.jline.reader.Candidate; -+import org.jline.reader.Completer; -+import org.jline.reader.LineReader; -+import org.jline.reader.ParsedLine; -+// Paper end - import org.bukkit.event.server.TabCompleteEvent; - - public class ConsoleCommandCompleter implements Completer { -- private final CraftServer server; -+ private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer - -- public ConsoleCommandCompleter(CraftServer server) { -+ public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer - this.server = server; - } - -+ // Paper start - Change method signature for JLine update - @Override -- public int complete(final String buffer, final int cursor, final List candidates) { -+ public void complete(LineReader reader, ParsedLine line, List candidates) { -+ final CraftServer server = this.server.server; -+ final String buffer = line.line(); -+ // Paper end - Waitable> waitable = new Waitable>() { - @Override - protected List evaluate() { -@@ -29,25 +40,37 @@ public class ConsoleCommandCompleter implements Completer { - return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); - } - }; -- this.server.getServer().processQueue.add(waitable); -+ server.getServer().processQueue.add(waitable); // Paper - Remove "this." - try { - List offers = waitable.get(); - if (offers == null) { -- return cursor; -+ return; // Paper - Method returns void -+ } -+ -+ // Paper start - JLine update -+ for (String completion : offers) { -+ if (completion.isEmpty()) { -+ continue; -+ } -+ -+ candidates.add(new Candidate(completion)); - } -- candidates.addAll(offers); -+ // Paper end - -+ // Paper start - JLine handles cursor now -+ /* - final int lastSpace = buffer.lastIndexOf(' '); - if (lastSpace == -1) { - return cursor - buffer.length(); - } else { - return cursor - (buffer.length() - lastSpace - 1); - } -+ */ -+ // Paper end - } catch (ExecutionException e) { -- this.server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); -+ server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); // Paper - Remove "this." - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } -- return cursor; - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index 70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe..449e99d1b673870ed6892f6ab2c715a2db35c35d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -17,7 +17,7 @@ public class ServerShutdownThread extends Thread { - server.close(); - } finally { - try { -- server.reader.getTerminal().restore(); -+ net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender - } catch (Exception e) { - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -index 99564fed7ce77e29dbdc591bcfe656af741acf8a..9a2da548b8860b496e396564b2c8f6383f020193 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -@@ -5,12 +5,12 @@ import java.io.IOException; - import java.io.OutputStream; - import java.util.logging.Level; - import java.util.logging.Logger; --import jline.console.ConsoleReader; -+//import jline.console.ConsoleReader; - import org.bukkit.craftbukkit.Main; --import org.fusesource.jansi.Ansi; --import org.fusesource.jansi.Ansi.Erase; -+//import org.fusesource.jansi.Ansi; -+//import org.fusesource.jansi.Ansi.Erase; - --public class TerminalConsoleWriterThread extends Thread { -+public class TerminalConsoleWriterThread /*extends Thread*/ {/* // Paper - disable - private final ConsoleReader reader; - private final OutputStream output; - -@@ -54,5 +54,5 @@ public class TerminalConsoleWriterThread extends Thread { - Logger.getLogger(TerminalConsoleWriterThread.class.getName()).log(Level.SEVERE, null, ex); - } - } -- } -+ }*/ - } -diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties -new file mode 100644 -index 0000000000000000000000000000000000000000..0694b21465fb9e4164e71862ff24b62241b191f2 ---- /dev/null -+++ b/src/main/resources/log4j2.component.properties -@@ -0,0 +1 @@ -+log4j.skipJansi=true -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 722ca84968cbbbdeffd09939abff0cccd0a84010..620b9490e5f159080e50289d127404a1b56adbef 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -1,17 +1,14 @@ - - - -- -- -- - - - -- -- -- -+ -+ -+ - -- -+ - - - -@@ -24,10 +21,9 @@ - - - -- - -- - -+ - - - diff --git a/Unmapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch b/Unmapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch deleted file mode 100644 index d2c710ef94..0000000000 --- a/Unmapped-Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 11 Jun 2017 21:01:18 +0100 -Subject: [PATCH] provide a configurable option to disable creeper lingering - effect spawns - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1..90ca51dfdbb3045dd528450225cba96f5834166e 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -336,4 +336,10 @@ public class PaperWorldConfig { - parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); - log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); - } -+ -+ public boolean disableCreeperLingeringEffect; -+ private void setDisableCreeperLingeringEffect() { -+ disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); -+ log("Creeper lingering effect: " + disableCreeperLingeringEffect); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -index 4106cce3071ac8bfe33e94b0fc7f67cfeef214b4..08292753f925f33d75f3aca835c1fd19494b22ec 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -@@ -262,7 +262,7 @@ public class EntityCreeper extends EntityMonster { - private void createEffectCloud() { - Collection collection = this.getEffects(); - -- if (!collection.isEmpty()) { -+ if (!collection.isEmpty() && !world.paperConfig.disableCreeperLingeringEffect) { // Paper - EntityAreaEffectCloud entityareaeffectcloud = new EntityAreaEffectCloud(this.world, this.locX(), this.locY(), this.locZ()); - - entityareaeffectcloud.setSource(this); // CraftBukkit diff --git a/Unmapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch b/Unmapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch deleted file mode 100644 index 1bb1f6f355..0000000000 --- a/Unmapped-Spigot-Server-Patches/0148-Item-canEntityPickup.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 5 May 2017 03:57:17 -0500 -Subject: [PATCH] Item#canEntityPickup - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index ccdfc8068a8205d6e66ab9458764b1440f8c4b97..2cc15ac22000343dc540454ba971993bf5b2f5a3 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -607,6 +607,11 @@ public abstract class EntityInsentient extends EntityLiving { - EntityItem entityitem = (EntityItem) iterator.next(); - - if (!entityitem.dead && !entityitem.getItemStack().isEmpty() && !entityitem.p() && this.i(entityitem.getItemStack())) { -+ // Paper Start -+ if (!entityitem.canMobPickup) { -+ continue; -+ } -+ // Paper End - this.b(entityitem); - } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 38b91b450c6bdc25efaed495ce26d909a52531bf..c486c07a358c0b444e1a1372b6d0fa2901840eac 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -47,6 +47,7 @@ public class EntityItem extends Entity { - private UUID owner; - public final float b; - private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit -+ public boolean canMobPickup = true; // Paper - - public EntityItem(EntityTypes entitytypes, World world) { - super(entitytypes, world); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -index f333dd2726f554a3137a3a78d162905f4ed1435e..5988cdd18b7e4bfca0075fd2356cfe9c4e673954 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -@@ -49,6 +49,16 @@ public class CraftItem extends CraftEntity implements Item { - item.age = value; - } - -+ // Paper Start -+ public boolean canMobPickup() { -+ return item.canMobPickup; -+ } -+ -+ public void setCanMobPickup(boolean canMobPickup) { -+ item.canMobPickup = canMobPickup; -+ } -+ // Paper End -+ - @Override - public void setOwner(UUID uuid) { - item.setOwner(uuid); diff --git a/Unmapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch b/Unmapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch deleted file mode 100644 index 2bbbc7656e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 May 2017 06:26:09 -0500 -Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer - - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index c486c07a358c0b444e1a1372b6d0fa2901840eac..3b72032f6f4f4bd64d1202658cc0c6ee4fb76ea9 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -363,6 +363,7 @@ public class EntityItem extends Entity { - // CraftBukkit start - fire PlayerPickupItemEvent - int canHold = entityhuman.inventory.canHold(itemstack); - int remaining = i - canHold; -+ boolean flyAtPlayer = false; // Paper - - if (this.pickupDelay <= 0 && canHold > 0) { - itemstack.setCount(canHold); -@@ -370,8 +371,14 @@ public class EntityItem extends Entity { - PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); - playerEvent.setCancelled(!entityhuman.canPickUpLoot); - this.world.getServer().getPluginManager().callEvent(playerEvent); -+ flyAtPlayer = playerEvent.getFlyAtPlayer(); // Paper - if (playerEvent.isCancelled()) { - itemstack.setCount(i); // SPIGOT-5294 - restore count -+ // Paper Start -+ if (flyAtPlayer) { -+ entityhuman.receive(this, i); -+ } -+ // Paper End - return; - } - -@@ -401,7 +408,11 @@ public class EntityItem extends Entity { - // CraftBukkit end - - if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(entityhuman.getUniqueID())) && entityhuman.inventory.pickup(itemstack)) { -- entityhuman.receive(this, i); -+ // Paper Start -+ if (flyAtPlayer) { -+ entityhuman.receive(this, i); -+ } -+ // Paper End - if (itemstack.isEmpty()) { - this.die(); - itemstack.setCount(i); diff --git a/Unmapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch b/Unmapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch deleted file mode 100644 index 13d2f54354..0000000000 --- a/Unmapped-Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 11 Jun 2017 16:30:30 -0500 -Subject: [PATCH] PlayerAttemptPickupItemEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 3b72032f6f4f4bd64d1202658cc0c6ee4fb76ea9..de11fd9772f30ac72c3ca52ec4efc3fef4091425 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -36,6 +36,7 @@ import net.minecraft.server.MinecraftServer; - import org.bukkit.event.entity.EntityPickupItemEvent; - import org.bukkit.event.player.PlayerPickupItemEvent; - // CraftBukkit end -+import org.bukkit.event.player.PlayerAttemptPickupItemEvent; // Paper - - public class EntityItem extends Entity { - -@@ -365,6 +366,22 @@ public class EntityItem extends Entity { - int remaining = i - canHold; - boolean flyAtPlayer = false; // Paper - -+ // Paper start -+ if (this.pickupDelay <= 0) { -+ PlayerAttemptPickupItemEvent attemptEvent = new PlayerAttemptPickupItemEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); -+ this.world.getServer().getPluginManager().callEvent(attemptEvent); -+ -+ flyAtPlayer = attemptEvent.getFlyAtPlayer(); -+ if (attemptEvent.isCancelled()) { -+ if (flyAtPlayer) { -+ entityhuman.receive(this, i); -+ } -+ -+ return; -+ } -+ } -+ // Paper end -+ - if (this.pickupDelay <= 0 && canHold > 0) { - itemstack.setCount(canHold); - // Call legacy event diff --git a/Unmapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch b/Unmapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch deleted file mode 100644 index b03b0cc9b6..0000000000 --- a/Unmapped-Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sweepyoface -Date: Sat, 17 Jun 2017 18:48:21 -0400 -Subject: [PATCH] Add UnknownCommandEvent - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 2a05ef7553e3b05d5757e69e69c247e24ba29249..9e974159476e7a359f59c0cdf5aae1be4422d1c0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -791,7 +791,13 @@ public final class CraftServer implements Server { - - // Spigot start - if (!org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty()) { -- sender.sendMessage(org.spigotmc.SpigotConfig.unknownCommandMessage); -+ // Paper start -+ org.bukkit.event.command.UnknownCommandEvent event = new org.bukkit.event.command.UnknownCommandEvent(sender, commandLine, org.spigotmc.SpigotConfig.unknownCommandMessage); -+ Bukkit.getServer().getPluginManager().callEvent(event); -+ if (event.message() != null) { -+ sender.sendMessage(event.message()); -+ } -+ // Paper end - } - // Spigot end - diff --git a/Unmapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch b/Unmapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch deleted file mode 100644 index 5a9faa7622..0000000000 --- a/Unmapped-Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch +++ /dev/null @@ -1,575 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 15 Jan 2018 22:11:48 -0500 -Subject: [PATCH] Basic PlayerProfile API - -Establishes base extension of profile systems for future edits too - -diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3d9452892a4077e64f37424052a9e52d76dd7a6d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java -@@ -0,0 +1,301 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.destroystokyo.paper.PaperConfig; -+import com.google.common.base.Charsets; -+import com.mojang.authlib.GameProfile; -+import com.mojang.authlib.properties.Property; -+import com.mojang.authlib.properties.PropertyMap; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.players.UserCache; -+import org.apache.commons.lang3.Validate; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+import org.spigotmc.SpigotConfig; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.util.AbstractSet; -+import java.util.Collection; -+import java.util.Iterator; -+import java.util.Objects; -+import java.util.Set; -+import java.util.UUID; -+ -+public class CraftPlayerProfile implements PlayerProfile { -+ -+ private GameProfile profile; -+ private final PropertySet properties = new PropertySet(); -+ -+ public CraftPlayerProfile(CraftPlayer player) { -+ this.profile = player.getHandle().getProfile(); -+ } -+ -+ public CraftPlayerProfile(UUID id, String name) { -+ this.profile = new GameProfile(id, name); -+ } -+ -+ public CraftPlayerProfile(GameProfile profile) { -+ Validate.notNull(profile, "GameProfile cannot be null!"); -+ this.profile = profile; -+ } -+ -+ @Override -+ public boolean hasProperty(String property) { -+ return profile.getProperties().containsKey(property); -+ } -+ -+ @Override -+ public void setProperty(ProfileProperty property) { -+ String name = property.getName(); -+ PropertyMap properties = profile.getProperties(); -+ properties.removeAll(name); -+ properties.put(name, new Property(name, property.getValue(), property.getSignature())); -+ } -+ -+ public GameProfile getGameProfile() { -+ return profile; -+ } -+ -+ @Nullable -+ @Override -+ public UUID getId() { -+ return profile.getId(); -+ } -+ -+ @Override -+ public UUID setId(@Nullable UUID uuid) { -+ GameProfile prev = this.profile; -+ this.profile = new GameProfile(uuid, prev.getName()); -+ copyProfileProperties(prev, this.profile); -+ return prev.getId(); -+ } -+ -+ @Nullable -+ @Override -+ public String getName() { -+ return profile.getName(); -+ } -+ -+ @Override -+ public String setName(@Nullable String name) { -+ GameProfile prev = this.profile; -+ this.profile = new GameProfile(prev.getId(), name); -+ copyProfileProperties(prev, this.profile); -+ return prev.getName(); -+ } -+ -+ @Nonnull -+ @Override -+ public Set getProperties() { -+ return properties; -+ } -+ -+ @Override -+ public void setProperties(Collection properties) { -+ properties.forEach(this::setProperty); -+ } -+ -+ @Override -+ public void clearProperties() { -+ profile.getProperties().clear(); -+ } -+ -+ @Override -+ public boolean removeProperty(String property) { -+ return !profile.getProperties().removeAll(property).isEmpty(); -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ CraftPlayerProfile that = (CraftPlayerProfile) o; -+ return Objects.equals(profile, that.profile); -+ } -+ -+ @Override -+ public int hashCode() { -+ return profile.hashCode(); -+ } -+ -+ @Override -+ public String toString() { -+ return profile.toString(); -+ } -+ -+ @Override -+ public CraftPlayerProfile clone() { -+ CraftPlayerProfile clone = new CraftPlayerProfile(this.getId(), this.getName()); -+ clone.setProperties(getProperties()); -+ return clone; -+ } -+ -+ @Override -+ public boolean isComplete() { -+ return profile.isComplete(); -+ } -+ -+ @Override -+ public boolean completeFromCache() { -+ MinecraftServer server = MinecraftServer.getServer(); -+ return completeFromCache(false, PaperConfig.isProxyOnlineMode()); -+ } -+ -+ public boolean completeFromCache(boolean onlineMode) { -+ return completeFromCache(false, onlineMode); -+ } -+ -+ public boolean completeFromCache(boolean lookupUUID, boolean onlineMode) { -+ MinecraftServer server = MinecraftServer.getServer(); -+ String name = profile.getName(); -+ UserCache userCache = server.getUserCache(); -+ if (profile.getId() == null) { -+ final GameProfile profile; -+ if (onlineMode) { -+ profile = lookupUUID ? userCache.getProfile(name) : userCache.getProfileIfCached(name); -+ } else { -+ // Make an OfflinePlayer using an offline mode UUID since the name has no profile -+ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); -+ } -+ if (profile != null) { -+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't -+ copyProfileProperties(this.profile, profile); -+ this.profile = profile; -+ } -+ } -+ -+ if ((profile.getName() == null || !hasTextures()) && profile.getId() != null) { -+ GameProfile profile = userCache.getProfile(this.profile.getId()); -+ if (profile != null) { -+ if (this.profile.getName() == null) { -+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't -+ copyProfileProperties(this.profile, profile); -+ this.profile = profile; -+ } else { -+ copyProfileProperties(profile, this.profile); -+ } -+ } -+ } -+ return this.profile.isComplete(); -+ } -+ -+ public boolean complete(boolean textures) { -+ MinecraftServer server = MinecraftServer.getServer(); -+ return complete(textures, PaperConfig.isProxyOnlineMode()); -+ } -+ public boolean complete(boolean textures, boolean onlineMode) { -+ MinecraftServer server = MinecraftServer.getServer(); -+ -+ boolean isCompleteFromCache = this.completeFromCache(true, onlineMode); -+ if (onlineMode && (!isCompleteFromCache || textures && !hasTextures())) { -+ GameProfile result = server.getMinecraftSessionService().fillProfileProperties(profile, true); -+ if (result != null) { -+ copyProfileProperties(result, this.profile, true); -+ } -+ if (this.profile.isComplete()) { -+ server.getUserCache().saveProfile(this.profile); -+ } -+ } -+ return profile.isComplete() && (!onlineMode || !textures || hasTextures()); -+ } -+ -+ private static void copyProfileProperties(GameProfile source, GameProfile target) { -+ copyProfileProperties(source, target, false); -+ } -+ -+ private static void copyProfileProperties(GameProfile source, GameProfile target, boolean clearTarget) { -+ PropertyMap sourceProperties = source.getProperties(); -+ PropertyMap targetProperties = target.getProperties(); -+ if (clearTarget) targetProperties.clear(); -+ if (sourceProperties.isEmpty()) { -+ return; -+ } -+ -+ for (Property property : sourceProperties.values()) { -+ targetProperties.removeAll(property.getName()); -+ targetProperties.put(property.getName(), property); -+ } -+ } -+ -+ private static ProfileProperty toBukkit(Property property) { -+ return new ProfileProperty(property.getName(), property.getValue(), property.getSignature()); -+ } -+ -+ public static PlayerProfile asBukkitCopy(GameProfile gameProfile) { -+ CraftPlayerProfile profile = new CraftPlayerProfile(gameProfile.getId(), gameProfile.getName()); -+ copyProfileProperties(gameProfile, profile.profile); -+ return profile; -+ } -+ -+ public static PlayerProfile asBukkitMirror(GameProfile profile) { -+ return new CraftPlayerProfile(profile); -+ } -+ -+ public static Property asAuthlib(ProfileProperty property) { -+ return new Property(property.getName(), property.getValue(), property.getSignature()); -+ } -+ -+ public static GameProfile asAuthlibCopy(PlayerProfile profile) { -+ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); -+ return asAuthlib(craft.clone()); -+ } -+ -+ public static GameProfile asAuthlib(PlayerProfile profile) { -+ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); -+ return craft.getGameProfile(); -+ } -+ -+ private class PropertySet extends AbstractSet { -+ -+ @Override -+ @Nonnull -+ public Iterator iterator() { -+ return new ProfilePropertyIterator(profile.getProperties().values().iterator()); -+ } -+ -+ @Override -+ public int size() { -+ return profile.getProperties().size(); -+ } -+ -+ @Override -+ public boolean add(ProfileProperty property) { -+ setProperty(property); -+ return true; -+ } -+ -+ @Override -+ public boolean addAll(Collection c) { -+ //noinspection unchecked -+ setProperties((Collection) c); -+ return true; -+ } -+ -+ @Override -+ public boolean contains(Object o) { -+ return o instanceof ProfileProperty && profile.getProperties().containsKey(((ProfileProperty) o).getName()); -+ } -+ -+ private class ProfilePropertyIterator implements Iterator { -+ private final Iterator iterator; -+ -+ ProfilePropertyIterator(Iterator iterator) { -+ this.iterator = iterator; -+ } -+ -+ @Override -+ public boolean hasNext() { -+ return iterator.hasNext(); -+ } -+ -+ @Override -+ public ProfileProperty next() { -+ return toBukkit(iterator.next()); -+ } -+ -+ @Override -+ public void remove() { -+ iterator.remove(); -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d64d45eb01c65864fca1077982d89bc05e0f811b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.*; -+import com.mojang.authlib.minecraft.MinecraftSessionService; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilEnvironment; -+ -+import java.net.Proxy; -+ -+public class PaperAuthenticationService extends YggdrasilAuthenticationService { -+ private final Environment environment; -+ public PaperAuthenticationService(Proxy proxy) { -+ super(proxy); -+ this.environment = (Environment)EnvironmentParser.getEnvironmentFromProperties().orElse(YggdrasilEnvironment.PROD);; -+ } -+ -+ @Override -+ public UserAuthentication createUserAuthentication(Agent agent) { -+ return new PaperUserAuthentication(this, agent); -+ } -+ -+ @Override -+ public MinecraftSessionService createMinecraftSessionService() { -+ return new PaperMinecraftSessionService(this, this.environment); -+ } -+ -+ @Override -+ public GameProfileRepository createProfileRepository() { -+ return new PaperGameProfileRepository(this, this.environment); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -new file mode 100644 -index 0000000000000000000000000000000000000000..582c169c85ac66f1f9430f79042e4655f776c157 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -@@ -0,0 +1,18 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.Agent; -+import com.mojang.authlib.Environment; -+import com.mojang.authlib.ProfileLookupCallback; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; -+ -+public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { -+ public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { -+ super(authenticationService, environment); -+ } -+ -+ @Override -+ public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { -+ super.findProfilesByNames(names, agent, callback); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -new file mode 100644 -index 0000000000000000000000000000000000000000..93d73c27340645c7502acafdc0b2cfbc1a759dd8 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -@@ -0,0 +1,30 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.Environment; -+import com.mojang.authlib.GameProfile; -+import com.mojang.authlib.minecraft.MinecraftProfileTexture; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; -+ -+import java.util.Map; -+ -+public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionService { -+ protected PaperMinecraftSessionService(YggdrasilAuthenticationService authenticationService, Environment environment) { -+ super(authenticationService, environment); -+ } -+ -+ @Override -+ public Map getTextures(GameProfile profile, boolean requireSecure) { -+ return super.getTextures(profile, requireSecure); -+ } -+ -+ @Override -+ public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { -+ return super.fillProfileProperties(profile, requireSecure); -+ } -+ -+ @Override -+ protected GameProfile fillGameProfile(GameProfile profile, boolean requireSecure) { -+ return super.fillGameProfile(profile, requireSecure); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3cdd06d3af7ff94f1fe1a11b9a9275e17c695a38 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java -@@ -0,0 +1,12 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.Agent; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; -+import java.util.UUID; -+ -+public class PaperUserAuthentication extends YggdrasilUserAuthentication { -+ public PaperUserAuthentication(YggdrasilAuthenticationService authenticationService, Agent agent) { -+ super(authenticationService, UUID.randomUUID().toString(), agent); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 18b56b59fd6efd618e6ff6f9cf3a02f57588d244..cd7dc7d90efddb8a1bb50cd964b43d18cf9c83d1 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -1,6 +1,8 @@ - package net.minecraft.server; - - import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import com.google.common.util.concurrent.ThreadFactoryBuilder; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; - import net.minecraft.core.BlockPosition; -@@ -11,6 +13,7 @@ import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.RayTrace; - import net.minecraft.world.level.World; - import org.apache.commons.lang.exception.ExceptionUtils; -+import com.mojang.authlib.GameProfile; - import org.bukkit.Location; - import org.bukkit.block.BlockFace; - import org.bukkit.craftbukkit.CraftWorld; -@@ -345,6 +348,10 @@ public final class MCUtil { - return run.get(); - } - -+ public static PlayerProfile toBukkit(GameProfile profile) { -+ return CraftPlayerProfile.asBukkitMirror(profile); -+ } -+ - /** - * Calculates distance between 2 entities - * @param e1 -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 89db31061fcc3420bc8e668533a4051cdbd12253..191a74bd9b894f9d64d0a55747cb17e07ceef597 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -132,7 +132,7 @@ public class Main { - } - - File file = (File) optionset.valueOf("universe"); // CraftBukkit -- YggdrasilAuthenticationService yggdrasilauthenticationservice = new YggdrasilAuthenticationService(Proxy.NO_PROXY); -+ YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper - MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); - GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); - UserCache usercache = new UserCache(gameprofilerepository, new File(file, MinecraftServer.b.getName())); -diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java -index b9f94f957dd5372c8b02d785204690e4ade36a98..692d95c94df85d752a3ddc66e1f2af765565b160 100644 ---- a/src/main/java/net/minecraft/server/players/UserCache.java -+++ b/src/main/java/net/minecraft/server/players/UserCache.java -@@ -45,7 +45,7 @@ public class UserCache { - - private static final Logger LOGGER = LogManager.getLogger(); - private static boolean b; -- private final Map c = Maps.newConcurrentMap(); -+ private final Map c = Maps.newConcurrentMap();private final Map nameCache = c; // Paper - OBFHELPER // Paper - private final Map d = Maps.newConcurrentMap(); - private final GameProfileRepository e; - private final Gson f = (new GsonBuilder()).create(); -@@ -110,6 +110,7 @@ public class UserCache { - return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper - } - -+ public void saveProfile(GameProfile gameprofile) { a(gameprofile); } // Paper - OBFHELPER - public synchronized void a(GameProfile gameprofile) { // Paper - synchronize - Calendar calendar = Calendar.getInstance(); - -@@ -159,6 +160,13 @@ public class UserCache { - return gameprofile; - } - -+ // Paper start -+ @Nullable public GameProfile getProfileIfCached(String name) { -+ UserCache.UserCacheEntry entry = this.nameCache.get(name.toLowerCase(Locale.ROOT)); -+ return entry == null ? null : entry.getProfile(); -+ } -+ // Paper end -+ - @Nullable - public GameProfile getProfile(UUID uuid) { - UserCache.UserCacheEntry usercache_usercacheentry = (UserCache.UserCacheEntry) this.d.get(uuid); -@@ -341,7 +349,7 @@ public class UserCache { - - static class UserCacheEntry { - -- private final GameProfile a; -+ private final GameProfile a;public GameProfile getProfile() { return a; } // Paper - OBFHELPER - private final Date b; - private volatile long c; - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 9e974159476e7a359f59c0cdf5aae1be4422d1c0..bda96a2f64ae27d53e5a5c6d36ffb5441fee112f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -224,6 +224,9 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; - - import net.md_5.bungee.api.chat.BaseComponent; // Spigot - -+import javax.annotation.Nullable; // Paper -+import javax.annotation.Nonnull; // Paper -+ - public final class CraftServer implements Server { - private final String serverName = "Paper"; // Paper - private final String serverVersion; -@@ -2316,5 +2319,24 @@ public final class CraftServer implements Server { - public boolean suggestPlayerNamesWhenNullTabCompletions() { - return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; - } -+ -+ @Override -+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { -+ return createProfile(uuid, null); -+ } -+ -+ @Override -+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull String name) { -+ return createProfile(null, name); -+ } -+ -+ @Override -+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { -+ Player player = uuid != null ? Bukkit.getPlayer(uuid) : (name != null ? Bukkit.getPlayerExact(name) : null); -+ if (player != null) { -+ return new com.destroystokyo.paper.profile.CraftPlayerProfile((CraftPlayer)player); -+ } -+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index dff67a48961399f3746f99b4f2363724bfe51c36..8298ae9bf1c5635f08552c15f004b3d0f6e9f19b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -@@ -80,6 +80,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - } - - private void setProfile(GameProfile profile) { -+ // Paper start -+ if (profile != null) { -+ com.destroystokyo.paper.profile.CraftPlayerProfile paperProfile = new com.destroystokyo.paper.profile.CraftPlayerProfile(profile); -+ paperProfile.completeFromCache(false, true); -+ profile = paperProfile.getGameProfile(); -+ } -+ // Paper end - this.profile = profile; - this.serializedProfile = (profile == null) ? null : GameProfileSerializer.serialize(new NBTTagCompound(), profile); - } diff --git a/Unmapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch b/Unmapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch deleted file mode 100644 index af2c2b7c23..0000000000 --- a/Unmapped-Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 17 Jun 2017 15:18:30 -0400 -Subject: [PATCH] Shoulder Entities Release API - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index ba26fc2405e17d582da971d03147fb1865e9b546..63e8062ae3f3407b92b72b5fccaa958c39282fb8 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1880,20 +1880,44 @@ public abstract class EntityHuman extends EntityLiving { - - } - -+ // Paper start -+ public Entity releaseLeftShoulderEntity() { -+ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityLeft()); -+ if (entity != null) { -+ this.setShoulderEntityLeft(new NBTTagCompound()); -+ } -+ return entity; -+ } -+ -+ public Entity releaseRightShoulderEntity() { -+ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityRight()); -+ if (entity != null) { -+ this.setShoulderEntityRight(new NBTTagCompound()); -+ } -+ return entity; -+ } -+ // Paper - maintain old signature - private boolean spawnEntityFromShoulder(NBTTagCompound nbttagcompound) { // CraftBukkit void->boolean -- if (!this.world.isClientSide && !nbttagcompound.isEmpty()) { -+ return spawnEntityFromShoulder0(nbttagcompound) != null; -+ } -+ -+ // Paper - return entity -+ private Entity spawnEntityFromShoulder0(@Nullable NBTTagCompound nbttagcompound) { -+ if (!this.world.isClientSide && nbttagcompound != null && !nbttagcompound.isEmpty()) { - return EntityTypes.a(nbttagcompound, this.world).map((entity) -> { // CraftBukkit - if (entity instanceof EntityTameableAnimal) { - ((EntityTameableAnimal) entity).setOwnerUUID(this.uniqueID); - } - - entity.setPosition(this.locX(), this.locY() + 0.699999988079071D, this.locZ()); -- return ((WorldServer) this.world).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit -- }).orElse(true); // CraftBukkit -+ boolean addedToWorld = ((WorldServer) this.world).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit -+ return addedToWorld ? entity : null; -+ }).orElse(null); // CraftBukkit // Paper - false -> null - } - -- return true; // CraftBukkit -+ return null; // Paper - return null - } -+ // Paper end - - @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 24e856473a0050c0b097c179776350379d464d0c..893cea754ea1858d2b08ba377bbbc90e7c0efd6d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -495,6 +495,32 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - getHandle().getCooldownTracker().setCooldown(CraftMagicNumbers.getItem(material), ticks); - } - -+ // Paper start -+ @Override -+ public org.bukkit.entity.Entity releaseLeftShoulderEntity() { -+ if (!getHandle().getShoulderEntityLeft().isEmpty()) { -+ Entity entity = getHandle().releaseLeftShoulderEntity(); -+ if (entity != null) { -+ return entity.getBukkitEntity(); -+ } -+ } -+ -+ return null; -+ } -+ -+ @Override -+ public org.bukkit.entity.Entity releaseRightShoulderEntity() { -+ if (!getHandle().getShoulderEntityRight().isEmpty()) { -+ Entity entity = getHandle().releaseRightShoulderEntity(); -+ if (entity != null) { -+ return entity.getBukkitEntity(); -+ } -+ } -+ -+ return null; -+ } -+ // Paper end -+ - @Override - public boolean discoverRecipe(NamespacedKey recipe) { - return discoverRecipes(Arrays.asList(recipe)) != 0; diff --git a/Unmapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch b/Unmapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch deleted file mode 100644 index a9a4210f19..0000000000 --- a/Unmapped-Spigot-Server-Patches/0154-Profile-Lookup-Events.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 17 Jun 2017 17:00:32 -0400 -Subject: [PATCH] Profile Lookup Events - -Adds a Pre Lookup Event and a Post Lookup Event so that plugins may prefill in profile data, and cache the responses from -profiles that had to be looked up. - -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -index 582c169c85ac66f1f9430f79042e4655f776c157..08fdb681a68e8be6e4062af0630957ce3e524806 100644 ---- a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -@@ -1,11 +1,16 @@ - package com.destroystokyo.paper.profile; - -+import com.destroystokyo.paper.event.profile.LookupProfileEvent; -+import com.destroystokyo.paper.event.profile.PreLookupProfileEvent; -+import com.google.common.collect.Sets; - import com.mojang.authlib.Agent; - import com.mojang.authlib.Environment; -+import com.mojang.authlib.GameProfile; - import com.mojang.authlib.ProfileLookupCallback; - import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; - import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; - -+import java.util.Set; - public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { - public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { - super(authenticationService, environment); -@@ -13,6 +18,50 @@ public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { - - @Override - public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { -- super.findProfilesByNames(names, agent, callback); -+ Set unfoundNames = Sets.newHashSet(); -+ for (String name : names) { -+ PreLookupProfileEvent event = new PreLookupProfileEvent(name); -+ event.callEvent(); -+ if (event.getUUID() != null) { -+ // Plugin provided UUI, we can skip network call. -+ GameProfile gameprofile = new GameProfile(event.getUUID(), name); -+ // We might even have properties! -+ Set profileProperties = event.getProfileProperties(); -+ if (!profileProperties.isEmpty()) { -+ for (ProfileProperty property : profileProperties) { -+ gameprofile.getProperties().put(property.getName(), CraftPlayerProfile.asAuthlib(property)); -+ } -+ } -+ callback.onProfileLookupSucceeded(gameprofile); -+ } else { -+ unfoundNames.add(name); -+ } -+ } -+ -+ // Some things were not found.... Proceed to look up. -+ if (!unfoundNames.isEmpty()) { -+ String[] namesArr = unfoundNames.toArray(new String[unfoundNames.size()]); -+ super.findProfilesByNames(namesArr, agent, new PreProfileLookupCallback(callback)); -+ } -+ } -+ -+ private static class PreProfileLookupCallback implements ProfileLookupCallback { -+ private final ProfileLookupCallback callback; -+ -+ PreProfileLookupCallback(ProfileLookupCallback callback) { -+ this.callback = callback; -+ } -+ -+ @Override -+ public void onProfileLookupSucceeded(GameProfile gameProfile) { -+ PlayerProfile from = CraftPlayerProfile.asBukkitMirror(gameProfile); -+ new LookupProfileEvent(from).callEvent(); -+ callback.onProfileLookupSucceeded(gameProfile); -+ } -+ -+ @Override -+ public void onProfileLookupFailed(GameProfile gameProfile, Exception e) { -+ callback.onProfileLookupFailed(gameProfile, e); -+ } - } - } diff --git a/Unmapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch b/Unmapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch deleted file mode 100644 index 389a5de905..0000000000 --- a/Unmapped-Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 2 Jul 2017 21:35:56 -0500 -Subject: [PATCH] Block player logins during server shutdown - - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index c45647f2d05ed6b170aad10c0a3fb94570d2dd90..401833b7aeb9955fad2a3f1fe51d195cf0131094 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -68,6 +68,12 @@ public class LoginListener implements PacketLoginInListener { - } - - public void tick() { -+ // Paper start - Do not allow logins while the server is shutting down -+ if (!MinecraftServer.getServer().isRunning()) { -+ this.disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(org.spigotmc.SpigotConfig.restartMessage)[0]); -+ return; -+ } -+ // Paper end - if (this.g == LoginListener.EnumProtocolState.READY_TO_ACCEPT) { - this.c(); - } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { diff --git a/Unmapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch b/Unmapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch deleted file mode 100644 index 92e16b769b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 18 Jun 2017 18:17:05 -0500 -Subject: [PATCH] Entity#fromMobSpawner() - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index dcaf5c107bb77b63333f924a33961f9e5cad7082..43039c14e087259e3ce4b5091b887759b66fe52d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -268,6 +268,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; -+ public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one - protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end -@@ -1666,6 +1667,10 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - nbttagcompound.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); - nbttagcompound.set("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); - } -+ // Save entity's from mob spawner status -+ if (spawnedViaMobSpawner) { -+ nbttagcompound.setBoolean("Paper.FromMobSpawner", true); -+ } - // Paper end - return nbttagcompound; - } catch (Throwable throwable) { -@@ -1798,6 +1803,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); - } -+ -+ spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status - // Paper end - - } catch (Throwable throwable) { -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 76c98d576d3e567ec4482b30219f5a9107cb9703..43fcc001bb9815b352cb74af10290b2a4ccaa540 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -160,6 +160,7 @@ public abstract class MobSpawnerAbstract { - } - // Spigot End - } -+ entity.spawnedViaMobSpawner = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { - Entity vehicle = entity.getVehicle(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index a58626b1a0160983a738a45c8a1d411eb347e6a2..4c2a35fb33da19a15a220dc5e0c9fa3233d657fb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1100,5 +1100,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - Location origin = getHandle().origin; - return origin == null ? null : origin.clone(); - } -+ -+ @Override -+ public boolean fromMobSpawner() { -+ return getHandle().spawnedViaMobSpawner; -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch b/Unmapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch deleted file mode 100644 index 5587fd6b92..0000000000 --- a/Unmapped-Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 10 Dec 2016 16:24:06 -0500 -Subject: [PATCH] Improve the Saddle API for Horses - -Not all horses with Saddles have armor. This lets us break up the horses with saddles -and access their saddle state separately from an interface shared with Armor. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -index 00b97d9ee7a3dd622c87e8efa288795d34db8fc7..62ccef35e4b4238c50faf778fbf3ea9a494ca387 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -@@ -6,6 +6,7 @@ import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; - import org.apache.commons.lang.Validate; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.inventory.CraftInventoryAbstractHorse; -+import org.bukkit.craftbukkit.inventory.CraftSaddledInventory; - import org.bukkit.entity.AbstractHorse; - import org.bukkit.entity.AnimalTamer; - import org.bukkit.entity.Horse; -@@ -99,6 +100,6 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac - - @Override - public AbstractHorseInventory getInventory() { -- return new CraftInventoryAbstractHorse(getHandle().inventoryChest); -+ return new CraftSaddledInventory(getHandle().inventoryChest); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java -index c3599b29c0b32d6fcf18a4a0adfbe8454c37834d..0389d15f8e0b6bb68316eaed0cf91acab8951cc7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java -@@ -4,7 +4,7 @@ import net.minecraft.world.IInventory; - import org.bukkit.inventory.HorseInventory; - import org.bukkit.inventory.ItemStack; - --public class CraftInventoryHorse extends CraftInventoryAbstractHorse implements HorseInventory { -+public class CraftInventoryHorse extends CraftSaddledInventory implements HorseInventory { - - public CraftInventoryHorse(IInventory inventory) { - super(inventory); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8c2674ca1be1346ea84bcd7c9c5d6ea540802a5f ---- /dev/null -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java -@@ -0,0 +1,12 @@ -+package org.bukkit.craftbukkit.inventory; -+ -+import net.minecraft.world.IInventory; -+import org.bukkit.inventory.SaddledHorseInventory; -+ -+public class CraftSaddledInventory extends CraftInventoryAbstractHorse implements SaddledHorseInventory { -+ -+ public CraftSaddledInventory(IInventory inventory) { -+ super(inventory); -+ } -+ -+} diff --git a/Unmapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch b/Unmapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch deleted file mode 100644 index f7c4a06144..0000000000 --- a/Unmapped-Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 May 2016 22:43:12 -0400 -Subject: [PATCH] Implement ensureServerConversions API - -This will take a Bukkit ItemStack and run it through any conversions a server process would perform on it, -to ensure it meets latest minecraft expectations. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index ccd27aa93b4ab1dc09a8d684b43b5ecb69100ed8..8206e85cefb0b02b1ac9b370808c06019211cdb1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -346,5 +346,11 @@ public final class CraftItemFactory implements ItemFactory { - public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { - return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); - } -+ -+ // Paper start -+ @Override -+ public ItemStack ensureServerConversions(ItemStack item) { -+ return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch b/Unmapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch deleted file mode 100644 index 17848eb001..0000000000 --- a/Unmapped-Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 May 2016 23:59:38 -0400 -Subject: [PATCH] Implement getI18NDisplayName - -Gets the Display name as seen in the Client. -Currently the server only supports the English language. To override this, -You must replace the language file embedded in the server jar. - -diff --git a/src/main/java/net/minecraft/locale/LocaleLanguage.java b/src/main/java/net/minecraft/locale/LocaleLanguage.java -index 9b8d5e7e4c86a699e26b1b4d0b82e88887a44054..5218214225b50ac4059ab704086a457318e93e00 100644 ---- a/src/main/java/net/minecraft/locale/LocaleLanguage.java -+++ b/src/main/java/net/minecraft/locale/LocaleLanguage.java -@@ -30,7 +30,7 @@ public abstract class LocaleLanguage { - - private static LocaleLanguage c() { - Builder builder = ImmutableMap.builder(); -- BiConsumer biconsumer = builder::put; -+ BiConsumer biconsumer = builder::put; // Paper - decompile fix - - try { - InputStream inputstream = LocaleLanguage.class.getResourceAsStream("/assets/minecraft/lang/en_us.json"); -@@ -87,10 +87,12 @@ public abstract class LocaleLanguage { - - } - -+ public static LocaleLanguage getInstance() { return a(); } // Paper - OBFHELPER - public static LocaleLanguage a() { - return LocaleLanguage.d; - } - -+ public String translateKey(String key) { return a(key); } // Paper - OBFHELPER - public abstract String a(String s); - - public abstract boolean b(String s); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 8206e85cefb0b02b1ac9b370808c06019211cdb1..910c6109783dfef86e127a0a5b7d7d3865150d89 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -352,5 +352,18 @@ public final class CraftItemFactory implements ItemFactory { - public ItemStack ensureServerConversions(ItemStack item) { - return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); - } -+ -+ @Override -+ public String getI18NDisplayName(ItemStack item) { -+ net.minecraft.world.item.ItemStack nms = null; -+ if (item instanceof CraftItemStack) { -+ nms = ((CraftItemStack) item).handle; -+ } -+ if (nms == null) { -+ nms = CraftItemStack.asNMSCopy(item); -+ } -+ -+ return nms != null ? net.minecraft.locale.LocaleLanguage.getInstance().translateKey(nms.getItem().getName()) : null; -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch b/Unmapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch deleted file mode 100644 index a0dfecf59f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 3 Jul 2017 18:11:10 -0500 -Subject: [PATCH] ProfileWhitelistVerifyEvent - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8348dfa43c1f6e07c01024b40f4b3ebc05c10035..bd8bcc3891b29d31742bcfd6080a3972e4a9bee7 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -615,9 +615,9 @@ public abstract class PlayerList { - - // return chatmessage; - if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure -- } else if (!this.isWhitelisted(gameprofile)) { -- chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); -- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure -+ } else if (!this.isWhitelisted(gameprofile, event)) { // Paper -+ //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper -+ //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted - } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { - IpBanEntry ipbanentry = this.l.get(socketaddress); - -@@ -1009,9 +1009,25 @@ public abstract class PlayerList { - this.server.getCommandDispatcher().a(entityplayer); - } - -+ // Paper start - public boolean isWhitelisted(GameProfile gameprofile) { -- return !this.hasWhitelist || this.operators.d(gameprofile) || this.whitelist.d(gameprofile); -+ return isWhitelisted(gameprofile, null); - } -+ public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { -+ boolean isOp = this.operators.d(gameprofile); -+ boolean isWhitelisted = !this.hasWhitelist || isOp || this.whitelist.d(gameprofile); -+ final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; -+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.hasWhitelist, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); -+ event.callEvent(); -+ if (!event.isWhitelisted()) { -+ if (loginEvent != null) { -+ loginEvent.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getKickMessage() == null ? org.spigotmc.SpigotConfig.whitelistMessage : event.getKickMessage())); -+ } -+ return false; -+ } -+ return true; -+ } -+ // Paper end - - public boolean isOp(GameProfile gameprofile) { - return this.operators.d(gameprofile) || this.server.a(gameprofile) && this.server.getSaveData().o() || this.v; diff --git a/Unmapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch b/Unmapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch deleted file mode 100644 index 8eacc81f8c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DemonWav -Date: Sun, 6 Aug 2017 17:17:53 -0500 -Subject: [PATCH] Fix this stupid bullshit - -Disable the 15 second sleep when the server jar hasn't been rebuilt within a period of time. - -modified in order to prevent merge conflicts when Spigot changes/disables the warning, -and to provide some level of hint without being disruptive. - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 60d9980ccca6f1ac55b70f7684b917ddceac380a..808a7688ed81bdfef623ee0a151ff8f94df2a3d7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -224,10 +224,12 @@ public class Main { - Calendar deadline = Calendar.getInstance(); - deadline.add(Calendar.DAY_OF_YEAR, -28); - if (buildDate.before(deadline.getTime())) { -- System.err.println("*** Error, this build is outdated ***"); -+ // Paper start - This is some stupid bullshit -+ System.err.println("*** Warning, you've not updated in a while! ***"); - System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper -- System.err.println("*** Server will start in 20 seconds ***"); -- Thread.sleep(TimeUnit.SECONDS.toMillis(20)); -+ //System.err.println("*** Server will start in 20 seconds ***"); -+ //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); -+ // Paper End - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch b/Unmapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch deleted file mode 100644 index e460482610..0000000000 --- a/Unmapped-Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:54:40 -0500 -Subject: [PATCH] Ocelot despawns should honor nametags and leash - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -index b0296cef410aa5af42dcf89217dd8853f3800663..f3e9c73f28584bcccd6f82d8974eabe4b4a892fa 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -@@ -128,7 +128,7 @@ public class EntityOcelot extends EntityAnimal { - - @Override - public boolean isTypeNotPersistent(double d0) { -- return !this.isTrusting() /*&& this.ticksLived > 2400*/; // CraftBukkit -+ return !this.isTrusting() && !this.hasCustomName() && !this.isLeashed() /*&& this.ticksLived > 2400*/; // CraftBukkit // Paper - honor name and leash - } - - public static AttributeProvider.Builder eK() { diff --git a/Unmapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/Unmapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch deleted file mode 100644 index 442ca85737..0000000000 --- a/Unmapped-Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:45:19 -0500 -Subject: [PATCH] Reset spawner timer when spawner event is cancelled - - -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 43fcc001bb9815b352cb74af10290b2a4ccaa540..883c724fbb86a84ee903b5e7127f14726fe4cf24 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -161,6 +161,7 @@ public abstract class MobSpawnerAbstract { - // Spigot End - } - entity.spawnedViaMobSpawner = true; // Paper -+ flag = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { - Entity vehicle = entity.getVehicle(); -@@ -184,7 +185,7 @@ public abstract class MobSpawnerAbstract { - ((EntityInsentient) entity).doSpawnEffect(); - } - -- flag = true; -+ /*flag = true;*/ // Paper - moved up above cancellable event - } - } - } diff --git a/Unmapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/Unmapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch deleted file mode 100644 index 3dbcb05b98..0000000000 --- a/Unmapped-Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mezz -Date: Wed, 9 Aug 2017 17:51:22 -0500 -Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index bd08ff18d8d7dbe63ed33c1efb6099b58aa02caa..8d4a28f98bd9c8a2dd1262f0f640909a456897fa 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -726,7 +726,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - gameprofilerfiller.enter("blockEntities"); - timings.tileEntityTick.startTiming(); // Spigot - if (!this.tileEntityListUnload.isEmpty()) { -- this.tileEntityListTick.removeAll(this.tileEntityListUnload); -+ // Paper start - Use alternate implementation with faster contains -+ java.util.Set toRemove = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); -+ toRemove.addAll(tileEntityListUnload); -+ this.tileEntityListTick.removeAll(toRemove); -+ // Paper end - //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list - this.tileEntityListUnload.clear(); - } diff --git a/Unmapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch b/Unmapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch deleted file mode 100644 index 1ac2a8b392..0000000000 --- a/Unmapped-Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Thu, 17 Aug 2017 16:08:20 -0700 -Subject: [PATCH] Allow specifying a custom "authentication servers down" kick - message - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 48319aaf1c525c6fb7bdee5c2f570a0d056d4eae..52954fc3bf932cfc9d5ce63e3d3cace351305790 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper; - -+import com.google.common.base.Strings; - import com.google.common.base.Throwables; - - import java.io.File; -@@ -273,4 +274,9 @@ public class PaperConfig { - private static void suggestPlayersWhenNull() { - suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); - } -+ -+ public static String authenticationServersDownKickMessage = ""; // empty = use translatable message -+ private static void authenticationServersDownKickMessage() { -+ authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 401833b7aeb9955fad2a3f1fe51d195cf0131094..9e175747e110e32be80498ed27a71d21e8c01c5e 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -277,6 +277,10 @@ public class LoginListener implements PacketLoginInListener { - LoginListener.this.i = LoginListener.this.a(gameprofile); - LoginListener.this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT; - } else { -+ // Paper start -+ if (com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage != null) { -+ LoginListener.this.disconnect(new ChatComponentText(com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage)); -+ } else // Paper end - LoginListener.this.disconnect(new ChatMessage("multiplayer.disconnect.authservers_down")); - LoginListener.LOGGER.error("Couldn't verify username because servers are unavailable"); - } diff --git a/Unmapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch b/Unmapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch deleted file mode 100644 index db8677912c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0166-LivingEntity-setKiller.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:49:48 -0500 -Subject: [PATCH] LivingEntity#setKiller - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 036577b0237e9c8a7ab22ede7477eefa1abecf96..752cd55d8eb9e2e26e7cbfb9ce18b4ba56538002 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -180,7 +180,7 @@ public abstract class EntityLiving extends Entity { - public float aE; - @Nullable - public EntityHuman killer; -- protected int lastDamageByPlayerTime; -+ public int lastDamageByPlayerTime; // Paper - protected -> public - protected boolean killed; - protected int ticksFarFromPlayer; - protected float aJ; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index c654026587bc9bf77b39f59a0c89991ac581da1e..c43c300963bae9bca6ab9c9389dd53e42318715c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -8,6 +8,7 @@ import java.util.Iterator; - import java.util.List; - import java.util.Set; - import java.util.UUID; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.EnumHand; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.effect.MobEffect; -@@ -344,6 +345,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().killer == null ? null : (Player) getHandle().killer.getBukkitEntity(); - } - -+ // Paper start -+ @Override -+ public void setKiller(Player killer) { -+ EntityPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle(); -+ getHandle().killer = entityPlayer; -+ getHandle().lastDamager = entityPlayer; -+ getHandle().lastDamageByPlayerTime = entityPlayer == null ? 0 : 100; // 100 value taken from EntityLiving#damageEntity -+ } -+ // Paper end -+ - @Override - public boolean addPotionEffect(PotionEffect effect) { - return addPotionEffect(effect, false); diff --git a/Unmapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch b/Unmapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch deleted file mode 100644 index 25a1431c58..0000000000 --- a/Unmapped-Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Thu, 21 Sep 2017 16:14:55 +0200 -Subject: [PATCH] Handle plugin prefixes using Log4J configuration - -Display logger name in the console for all loggers except the -root logger, Bukkit's logger ("Minecraft") and Minecraft loggers. -Since plugins now use the plugin name as logger name this will -restore the plugin prefixes without having to prepend them manually -to the log messages. - -Logger prefixes are shown by default for all loggers except for -the root logger, the Minecraft/Mojang loggers and the Bukkit loggers. -This may cause additional prefixes to be disabled for plugins bypassing -the plugin logger. - -diff --git a/pom.xml b/pom.xml -index 3841fe3630c090f8a468333d43caeb2b5841329d..f5429f2f1979542fd93956d2f436d20d0e3a66b8 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -76,7 +76,7 @@ - - org.apache.logging.log4j - log4j-core -- runtime -+ compile - - - org.apache.logging.log4j -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 3c93a497a790b8d800852db2ac48feca41f45cef..e8e5e5b568ba53dd006f1461cb4f027ceeae5528 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -290,7 +290,7 @@ public class SpigotConfig - private static void playerSample() - { - playerSample = getInt( "settings.sample-count", 12 ); -- System.out.println( "Server Ping Player Sample Count: " + playerSample ); -+ Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger - } - - public static int playerShuffle; -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 620b9490e5f159080e50289d127404a1b56adbef..a8bdaaeaa1a9316848416f0533739b9b083ca151 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -5,10 +5,22 @@ - - - -- -+ -+ -+ -+ -+ -+ - - -- -+ -+ -+ -+ -+ -+ - - - diff --git a/Unmapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch b/Unmapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch deleted file mode 100644 index 5afb9562c0..0000000000 --- a/Unmapped-Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Sat, 23 Sep 2017 21:07:20 +0200 -Subject: [PATCH] Improve Log4J Configuration / Plugin Loggers - -Add full exceptions to log4j to not truncate stack traces - -Disable logger prefix for various plugins bypassing the plugin logger - -Some plugins bypass the plugin logger and add the plugin prefix -manually to the log message. Since they use other logger names -(e.g. qualified class names) these would now also appear in the -log. Disable the logger prefix for these plugins so the messages -show up correctly. - -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index a8bdaaeaa1a9316848416f0533739b9b083ca151..476f4a5cbe664ddd05474cb88553018bd334a5b8 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -6,19 +6,21 @@ - - - -- -+ - -- -+ -+ - - - - - -- -+ - -- -+ -+ - - - diff --git a/Unmapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch b/Unmapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch deleted file mode 100644 index edf45162bd..0000000000 --- a/Unmapped-Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 28 Sep 2017 17:21:44 -0400 -Subject: [PATCH] Add PlayerJumpEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 8c39dc4f05becea92f3ec86c4103be4e34f2b835..156acc9e1f3bb9d7663009530220a3958a1ff94d 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1168,7 +1168,34 @@ public class PlayerConnection implements PacketListenerPlayIn { - boolean flag = d8 > 0.0D; - - if (this.player.isOnGround() && !packetplayinflying.b() && flag) { -- this.player.jump(); -+ // Paper start - Add player jump event -+ Player player = this.getPlayer(); -+ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. -+ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. -+ -+ // If the packet contains movement information then we update the To location with the correct XYZ. -+ if (packetplayinflying.hasPos) { -+ to.setX(packetplayinflying.x); -+ to.setY(packetplayinflying.y); -+ to.setZ(packetplayinflying.z); -+ } -+ -+ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. -+ if (packetplayinflying.hasLook) { -+ to.setYaw(packetplayinflying.yaw); -+ to.setPitch(packetplayinflying.pitch); -+ } -+ -+ com.destroystokyo.paper.event.player.PlayerJumpEvent event = new com.destroystokyo.paper.event.player.PlayerJumpEvent(player, from, to); -+ -+ if (event.callEvent()) { -+ this.player.jump(); -+ } else { -+ from = event.getFrom(); -+ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet()); -+ return; -+ } -+ // Paper end - } - - this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9)); diff --git a/Unmapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch b/Unmapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch deleted file mode 100644 index 236692cc75..0000000000 --- a/Unmapped-Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 5 Oct 2017 01:54:07 +0100 -Subject: [PATCH] handle PacketPlayInKeepAlive async - -In 1.12.2, Mojang moved the processing of PacketPlayInKeepAlive off the main -thread, while entirely correct for the server, this causes issues with -plugins which are expecting the PlayerQuitEvent on the main thread. - -In order to counteract some bad behavior, we will post handling of the -disconnection to the main thread, but leave the actual processing of the packet -off the main thread. - -also adding some additional logging in order to help work out what is causing -random disconnections for clients. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 156acc9e1f3bb9d7663009530220a3958a1ff94d..f0e4737377ae99afca5b624a1367d95c42ab4fa0 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2779,14 +2779,18 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInKeepAlive packetplayinkeepalive) { -- PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit -+ //PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit // Paper - This shouldn't be on the main thread - if (this.awaitingKeepAlive && packetplayinkeepalive.b() == this.h) { - int i = (int) (SystemUtils.getMonotonicMillis() - this.lastKeepAlive); - - this.player.ping = (this.player.ping * 3 + i) / 4; - this.awaitingKeepAlive = false; - } else if (!this.isExemptPlayer()) { -+ // Paper start - This needs to be handled on the main thread for plugins -+ minecraftServer.scheduleOnMain(() -> { - this.disconnect(new ChatMessage("disconnect.timeout")); -+ }); -+ // Paper end - } - - } diff --git a/Unmapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch b/Unmapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch deleted file mode 100644 index 370d5ecde6..0000000000 --- a/Unmapped-Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Tue, 10 Oct 2017 18:45:20 +0200 -Subject: [PATCH] Expose client protocol version and virtual host - - -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8a716c1647aa29906be26ac262e93ebd2c1adfaa ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java -@@ -0,0 +1,50 @@ -+package com.destroystokyo.paper.network; -+ -+import net.minecraft.network.NetworkManager; -+ -+import java.net.InetSocketAddress; -+ -+import javax.annotation.Nullable; -+ -+public class PaperNetworkClient implements NetworkClient { -+ -+ private final NetworkManager networkManager; -+ -+ PaperNetworkClient(NetworkManager networkManager) { -+ this.networkManager = networkManager; -+ } -+ -+ @Override -+ public InetSocketAddress getAddress() { -+ return (InetSocketAddress) this.networkManager.getSocketAddress(); -+ } -+ -+ @Override -+ public int getProtocolVersion() { -+ return this.networkManager.protocolVersion; -+ } -+ -+ @Nullable -+ @Override -+ public InetSocketAddress getVirtualHost() { -+ return this.networkManager.virtualHost; -+ } -+ -+ public static InetSocketAddress prepareVirtualHost(String host, int port) { -+ int len = host.length(); -+ -+ // FML appends a marker to the host to recognize FML clients (\0FML\0) -+ int pos = host.indexOf('\0'); -+ if (pos >= 0) { -+ len = pos; -+ } -+ -+ // When clients connect with a SRV record, their host contains a trailing '.' -+ if (len > 0 && host.charAt(len - 1) == '.') { -+ len--; -+ } -+ -+ return InetSocketAddress.createUnresolved(host.substring(0, len), port); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index f093b465b868e6003bb2b5ee634a624b5b054493..60e4a4aa3854aaeb250d1318f2f25cf3591ea1d3 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -70,6 +70,10 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - private float s; - private int t; - private boolean u; -+ // Paper start - NetworkClient implementation -+ public int protocolVersion; -+ public java.net.InetSocketAddress virtualHost; -+ // Paper end - - public NetworkManager(EnumProtocolDirection enumprotocoldirection) { - this.h = enumprotocoldirection; -diff --git a/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java b/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java -index b290ddfbc19aed3e44169281c3dae5429dac0062..14c002376540d2039fc2fe2ef746e53471a9cb08 100644 ---- a/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java -+++ b/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java -@@ -39,6 +39,7 @@ public class PacketHandshakingInSetProtocol implements Packet -Date: Sun, 15 Oct 2017 00:29:07 +0100 -Subject: [PATCH] revert serverside behavior of keepalives - -This patch intends to bump up the time that a client has to reply to the -server back to 30 seconds as per pre 1.12.2, which allowed clients -more than enough time to reply potentially allowing them to be less -tempermental due to lag spikes on the network thread, e.g. that caused -by plugins that are interacting with netty. - -We also add a system property to allow people to tweak how long the server -will wait for a reply. There is a compromise here between lower and higher -values, lower values will mean that dead connections can be closed sooner, -whereas higher values will make this less sensitive to issues such as spikes -from networking or during connections flood of chunk packets on slower clients, - at the cost of dead connections being kept open for longer. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index f0e4737377ae99afca5b624a1367d95c42ab4fa0..301b63db3abc348441c3580a6606b65f550d8a78 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -223,7 +223,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - private final MinecraftServer minecraftServer; - public EntityPlayer player; - private int e; -- private long lastKeepAlive; private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER -+ private long lastKeepAlive = SystemUtils.getMonotonicMillis(); private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER - private boolean awaitingKeepAlive; private void setPendingPing(boolean isPending) { this.awaitingKeepAlive = isPending;}; private boolean isPendingPing() { return this.awaitingKeepAlive;}; // Paper - OBFHELPER - private long h; private void setKeepAliveID(long keepAliveID) { this.h = keepAliveID;}; private long getKeepAliveID() {return this.h; }; // Paper - OBFHELPER - // CraftBukkit start - multithreaded fields -@@ -254,6 +254,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - private int E; - private int receivedMovePackets; - private int processedMovePackets; -+ private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - - public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { - this.minecraftServer = minecraftserver; -@@ -340,18 +341,25 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - this.minecraftServer.getMethodProfiler().enter("keepAlive"); -- long i = SystemUtils.getMonotonicMillis(); -- -- if (i - this.lastKeepAlive >= 25000L) { // CraftBukkit -- if (this.awaitingKeepAlive) { -- this.disconnect(new ChatMessage("disconnect.timeout")); -- } else { -- this.awaitingKeepAlive = true; -- this.lastKeepAlive = i; -- this.h = i; -- this.sendPacket(new PacketPlayOutKeepAlive(this.h)); -+ // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings -+ // This should effectively place the keepalive handling back to "as it was" before 1.12.2 -+ long currentTime = SystemUtils.getMonotonicMillis(); -+ long elapsedTime = currentTime - this.getLastPing(); -+ -+ if (this.isPendingPing()) { -+ if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected -+ PlayerConnection.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getName()); // more info -+ this.disconnect(new ChatMessage("disconnect.timeout", new Object[0])); -+ } -+ } else { -+ if (elapsedTime >= 15000L) { // 15 seconds -+ this.setPendingPing(true); -+ this.setLastPing(currentTime); -+ this.setKeepAliveID(currentTime); -+ this.sendPacket(new PacketPlayOutKeepAlive(this.getKeepAliveID())); - } - } -+ // Paper end - - this.minecraftServer.getMethodProfiler().exit(); - // CraftBukkit start diff --git a/Unmapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch b/Unmapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch deleted file mode 100644 index 5c3d2d05c3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 31 Oct 2017 03:26:18 +0100 -Subject: [PATCH] Send attack SoundEffects only to players who can see the - attacker - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 63e8062ae3f3407b92b72b5fccaa958c39282fb8..f9d0623a3ed5f49758cd5e97fe9f63a5b3198e58 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -28,6 +28,7 @@ import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.chat.IChatMutableComponent; - import net.minecraft.network.protocol.game.PacketPlayOutEntityVelocity; -+import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -@@ -1126,7 +1127,7 @@ public abstract class EntityHuman extends EntityLiving { - int i = b0 + EnchantmentManager.b((EntityLiving) this); - - if (this.isSprinting() && flag) { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_KNOCKBACK, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_KNOCKBACK, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - ++i; - flag1 = true; - } -@@ -1201,7 +1202,7 @@ public abstract class EntityHuman extends EntityLiving { - } - } - -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_SWEEP, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_SWEEP, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - this.ex(); - } - -@@ -1229,15 +1230,15 @@ public abstract class EntityHuman extends EntityLiving { - } - - if (flag2) { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_CRIT, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_CRIT, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - this.a(entity); - } - - if (!flag2 && !flag3) { - if (flag) { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_STRONG, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_STRONG, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - } else { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_WEAK, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_WEAK, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - } - } - -@@ -1289,7 +1290,7 @@ public abstract class EntityHuman extends EntityLiving { - - this.applyExhaustion(world.spigotConfig.combatExhaustion, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value - } else { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_NODAMAGE, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_NODAMAGE, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - if (flag4) { - entity.extinguish(); - } -@@ -1724,6 +1725,14 @@ public abstract class EntityHuman extends EntityLiving { - public int getExpToLevel() { - return this.expLevel >= 30 ? 112 + (this.expLevel - 30) * 9 : (this.expLevel >= 15 ? 37 + (this.expLevel - 15) * 5 : 7 + this.expLevel * 2); - } -+ // Paper start - send SoundEffect to everyone who can see fromEntity -+ private static void sendSoundEffect(EntityHuman fromEntity, double x, double y, double z, SoundEffect soundEffect, SoundCategory soundCategory, float volume, float pitch) { -+ fromEntity.world.playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself -+ if (fromEntity instanceof EntityPlayer) { -+ ((EntityPlayer) fromEntity).playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(soundEffect, soundCategory, x, y, z, volume, pitch)); -+ } -+ } -+ // Paper end - - // CraftBukkit start - public void applyExhaustion(float f) { diff --git a/Unmapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch b/Unmapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch deleted file mode 100644 index 3edec22afc..0000000000 --- a/Unmapped-Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 10 Nov 2017 23:03:12 -0500 -Subject: [PATCH] Option for maximum exp value when merging orbs - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 90ca51dfdbb3045dd528450225cba96f5834166e..6c692e58cde22003ecbf6dc5695799147c39905a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -342,4 +342,10 @@ public class PaperWorldConfig { - disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); - log("Creeper lingering effect: " + disableCreeperLingeringEffect); - } -+ -+ public int expMergeMaxValue; -+ private void expMergeMaxValue() { -+ expMergeMaxValue = getInt("experience-merge-max-value", -1); -+ log("Experience Merge Max Value: " + expMergeMaxValue); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index d07c146119980358aeaf8f9dc5f419fd1385ced5..aa984540917e363438cc38cdb3004d3fc4987ab4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -599,16 +599,32 @@ public class CraftEventFactory { - EntityExperienceOrb xp = (EntityExperienceOrb) entity; - double radius = world.spigotConfig.expMerge; - if (radius > 0) { -+ // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics -+ final int maxValue = world.paperConfig.expMergeMaxValue; -+ final boolean mergeUnconditionally = world.paperConfig.expMergeMaxValue <= 0; -+ if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary -+ - List entities = world.getEntities(entity, entity.getBoundingBox().grow(radius, radius, radius)); - for (Entity e : entities) { - if (e instanceof EntityExperienceOrb) { - EntityExperienceOrb loopItem = (EntityExperienceOrb) e; -- if (!loopItem.dead) { -- xp.value += loopItem.value; -- loopItem.die(); -+ // Paper start -+ if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { -+ long newTotal = (long)xp.value + (long)loopItem.value; -+ if ((int) newTotal < 0) continue; // Overflow -+ if (maxValue > 0 && newTotal > (long)maxValue) { -+ loopItem.value = (int) (newTotal - maxValue); -+ xp.value = maxValue; -+ } else { -+ xp.value += loopItem.value; -+ loopItem.die(); -+ } -+ // Paper end - } - } - } -+ -+ } // Paper end - End iteration skip check - All tweaking ends here - } - // Spigot end - } else if (!(entity instanceof EntityPlayer)) { diff --git a/Unmapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch deleted file mode 100644 index 2a23c19157..0000000000 --- a/Unmapped-Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: pkt77 -Date: Fri, 10 Nov 2017 23:46:34 -0500 -Subject: [PATCH] Add PlayerArmorChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 752cd55d8eb9e2e26e7cbfb9ce18b4ba56538002..91be4df855a0a249518f0b562d05d9647169aa92 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.entity; - -+import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; // Paper - import com.google.common.base.Objects; - import com.google.common.collect.ImmutableList; - import com.google.common.collect.ImmutableMap; -@@ -2646,6 +2647,13 @@ public abstract class EntityLiving extends Entity { - ItemStack itemstack1 = this.getEquipment(enumitemslot); - - if (!ItemStack.matches(itemstack1, itemstack)) { -+ // Paper start - PlayerArmorChangeEvent -+ if (this instanceof EntityPlayer && enumitemslot.getType() == EnumItemSlot.Function.ARMOR) { -+ final org.bukkit.inventory.ItemStack oldItem = CraftItemStack.asBukkitCopy(itemstack); -+ final org.bukkit.inventory.ItemStack newItem = CraftItemStack.asBukkitCopy(itemstack1); -+ new PlayerArmorChangeEvent((Player) this.getBukkitEntity(), PlayerArmorChangeEvent.SlotType.valueOf(enumitemslot.name()), oldItem, newItem).callEvent(); -+ } -+ // Paper end - if (map == null) { - map = Maps.newEnumMap(EnumItemSlot.class); - } -diff --git a/src/main/java/net/minecraft/world/entity/EnumItemSlot.java b/src/main/java/net/minecraft/world/entity/EnumItemSlot.java -index 8e7673c6072c3f8ddcebd7a719304ea41d809a36..59ad7d8dc1c8ee00d142dc6063c3416ccdce4ff8 100644 ---- a/src/main/java/net/minecraft/world/entity/EnumItemSlot.java -+++ b/src/main/java/net/minecraft/world/entity/EnumItemSlot.java -@@ -16,6 +16,7 @@ public enum EnumItemSlot { - this.j = s; - } - -+ public EnumItemSlot.Function getType() { return this.a(); } // Paper - OBFHELPER - public EnumItemSlot.Function a() { - return this.g; - } diff --git a/Unmapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch b/Unmapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch deleted file mode 100644 index ad5a02fae5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: killme -Date: Sun, 12 Nov 2017 19:40:01 +0100 -Subject: [PATCH] Prevent logins from being processed when the player has - disconnected - - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 9e175747e110e32be80498ed27a71d21e8c01c5e..f95f5a8b30f42c8f5b6cee3ef6adb1f4e09832dc 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -75,7 +75,11 @@ public class LoginListener implements PacketLoginInListener { - } - // Paper end - if (this.g == LoginListener.EnumProtocolState.READY_TO_ACCEPT) { -- this.c(); -+ // Paper start - prevent logins to be processed even though disconnect was called -+ if (networkManager.isConnected()) { -+ this.c(); -+ } -+ // Paper end - } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { - EntityPlayer entityplayer = this.server.getPlayerList().getPlayer(this.i.getId()); - diff --git a/Unmapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch b/Unmapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch deleted file mode 100644 index 4dc684be75..0000000000 --- a/Unmapped-Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 16 Nov 2017 12:12:41 +0000 -Subject: [PATCH] use CB BlockState implementations for captured blocks - -When modifying the world, CB will store a copy of the affected -blocks in order to restore their state in the case that the event -is cancelled. This change only modifies the collection of blocks -in the world by normal means, e.g. not during tree population, -as the potentially marginal overheads would serve no advantage. - -CB was using a CraftBlockState for all blocks, which causes issues -should any block that uses information beyond a data ID would suffer -from missing information, e.g. Skulls. - -By using CBs CraftBlock#getState(), we will maintain a proper copy of -the blockstate that will be valid for restoration, as opposed to dropping -information on restoration when the event is cancelled. - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 8d4a28f98bd9c8a2dd1262f0f640909a456897fa..a9e7da1c848a6fe08fc112e445ceec1b7715d682 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -124,7 +124,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; -- public Map capturedBlockStates = new java.util.LinkedHashMap<>(); -+ public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper - public Map capturedTileEntities = new HashMap<>(); - public List captureDrops; - public long ticksPerAnimalSpawns; -@@ -346,7 +346,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) { - // CraftBukkit start - tree generation - if (this.captureTreeGeneration) { -- CapturedBlockState blockstate = capturedBlockStates.get(blockposition); -+ CraftBlockState blockstate = capturedBlockStates.get(blockposition); - if (blockstate == null) { - blockstate = CapturedBlockState.getTreeBlockState(this, blockposition, i); - this.capturedBlockStates.put(blockposition.immutableCopy(), blockstate); -@@ -366,7 +366,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // CraftBukkit start - capture blockstates - boolean captured = false; - if (this.captureBlockStates && !this.capturedBlockStates.containsKey(blockposition)) { -- CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, blockposition, i); -+ CraftBlockState blockstate = (CraftBlockState) world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()).getState(); // Paper - use CB getState to get a suitable snapshot -+ blockstate.setFlag(i); // Paper - set flag - this.capturedBlockStates.put(blockposition.immutableCopy(), blockstate); - captured = true; - } -@@ -624,7 +625,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public IBlockData getType(BlockPosition blockposition) { - // CraftBukkit start - tree generation - if (captureTreeGeneration) { -- CapturedBlockState previous = capturedBlockStates.get(blockposition); -+ CraftBlockState previous = capturedBlockStates.get(blockposition); // Paper - if (previous != null) { - return previous.getHandle(); - } diff --git a/Unmapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch b/Unmapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch deleted file mode 100644 index 5fe5db1a81..0000000000 --- a/Unmapped-Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 6 Nov 2017 21:08:22 -0500 -Subject: [PATCH] API to get a BlockState without a snapshot - -This allows you to get a BlockState without creating a snapshot, operating -on the real tile entity. - -This is useful for where performance is needed - -also Avoid NPE during CraftBlockEntityState load if could not get TE - -If Tile Entity was null, correct Sign to return empty lines instead of null - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 9b44ca96669ce423e5649f11743226dfdd9ce746..48daa039ffa8ccb7b6f3ca47bdc56394addf9254 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -47,6 +47,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public TileEntity(TileEntityTypes tileentitytypes) { - this.position = BlockPosition.ZERO; - this.tileType = tileentitytypes; -+ persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init - } - - // Paper start -@@ -95,7 +96,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) { - this.position = new BlockPosition(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); - // CraftBukkit start - read container -- this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); -+ this.persistentDataContainer.clear(); // Paper - clear instead of reinit - - net.minecraft.nbt.NBTBase persistentDataTag = nbttagcompound.get("PublicBukkitValues"); - if (persistentDataTag instanceof NBTTagCompound) { -@@ -245,7 +246,12 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - } - - // CraftBukkit start - add method -+ // Paper start - public InventoryHolder getOwner() { -+ return getOwner(true); -+ } -+ public InventoryHolder getOwner(boolean useSnapshot) { -+ // Paper end - if (world == null) return null; - // Spigot start - org.bukkit.block.Block block = world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); -@@ -254,7 +260,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - return null; - } - // Spigot end -- org.bukkit.block.BlockState state = block.getState(); -+ org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper - if (state instanceof InventoryHolder) return (InventoryHolder) state; - return null; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 255aac0803b436434bc00822f3698c4f3ba7e0ac..8a6d8f21937ce7e2ac4623a3083421ed5ef9aa63 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -316,6 +316,20 @@ public class CraftBlock implements Block { - - @Override - public BlockState getState() { -+ // Paper start - allow disabling the use of snapshots -+ return getState(true); -+ } -+ public BlockState getState(boolean useSnapshot) { -+ boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT; -+ CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot; -+ try { -+ return getState0(); -+ } finally { -+ CraftBlockEntityState.DISABLE_SNAPSHOT = prev; -+ } -+ } -+ public BlockState getState0() { -+ // Paper end - Material material = getType(); - - switch (material) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index dcf3f9265b0b00a7bbb9ff428e10da3c198ba08a..2f0b48869077c27d0cacea81a99c9e34ff59c684 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -26,20 +26,40 @@ public class CraftBlockEntityState extends CraftBlockState - this.tileEntity = tileEntityClass.cast(world.getHandle().getTileEntity(this.getPosition())); - Preconditions.checkState(this.tileEntity != null, "Tile is null, asynchronous access? %s", block); - -+ // Paper start -+ this.snapshotDisabled = DISABLE_SNAPSHOT; -+ if (DISABLE_SNAPSHOT) { -+ this.snapshot = this.tileEntity; -+ } else { -+ this.snapshot = this.createSnapshot(this.tileEntity); -+ } - // copy tile entity data: -- this.snapshot = this.createSnapshot(tileEntity); -- this.load(snapshot); -+ if(this.snapshot != null) { -+ this.load(this.snapshot); -+ } -+ // Paper end - } - -+ public final boolean snapshotDisabled; // Paper -+ public static boolean DISABLE_SNAPSHOT = false; // Paper -+ - public CraftBlockEntityState(Material material, T tileEntity) { - super(material); - - this.tileEntityClass = (Class) tileEntity.getClass(); - this.tileEntity = tileEntity; -- -+ // Paper start -+ this.snapshotDisabled = DISABLE_SNAPSHOT; -+ if (DISABLE_SNAPSHOT) { -+ this.snapshot = this.tileEntity; -+ } else { -+ this.snapshot = this.createSnapshot(this.tileEntity); -+ } - // copy tile entity data: -- this.snapshot = this.createSnapshot(tileEntity); -- this.load(snapshot); -+ if(this.snapshot != null) { -+ this.load(this.snapshot); -+ } -+ // Paper end - } - - private T createSnapshot(T tileEntity) { -diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -index f342feee4e2274cdc51fef6caace52cc31eefb18..a4c888236bf09a25f234831a041ca5a4a2c972ef 100644 ---- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -@@ -155,4 +155,10 @@ public final class CraftPersistentDataContainer implements PersistentDataContain - public Map serialize() { - return (Map) CraftNBTTagConfigSerializer.serialize(toTagCompound()); - } -+ -+ // Paper start -+ public void clear() { -+ this.customDataTags.clear(); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch b/Unmapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch deleted file mode 100644 index 1eefab71c5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 26 Nov 2017 13:19:58 -0500 -Subject: [PATCH] AsyncTabCompleteEvent - -Let plugins be able to control tab completion of commands and chat async. - -This will be useful for frameworks like ACF so we can define async safe completion handlers, -and avoid going to main for tab completions. - -Especially useful if you need to query a database in order to obtain the results for tab -completion, such as offline players. - -Also adds isCommand and getLocation to the sync TabCompleteEvent - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 301b63db3abc348441c3580a6606b65f550d8a78..1860def3971d1e17429bdde51c2bc336887da233 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -713,10 +713,10 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInTabComplete packetplayintabcomplete) { -- PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); -+ // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async - // CraftBukkit start - if (chatSpamField.addAndGet(this, 1) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { -- this.disconnect(new ChatMessage("disconnect.spam", new Object[0])); -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper - return; - } - // CraftBukkit end -@@ -726,12 +726,35 @@ public class PlayerConnection implements PacketListenerPlayIn { - stringreader.skip(); - } - -- ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); -+ // Paper start - async tab completion -+ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -+ java.util.List completions = new java.util.ArrayList<>(); -+ String buffer = packetplayintabcomplete.c(); -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, -+ buffer, true, null); -+ event.callEvent(); -+ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server -+ if (!event.isHandled()) { -+ if (!event.isCancelled()) { - -- this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -- this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); -- }); -+ this.minecraftServer.scheduleOnMain(() -> { // Paper - This needs to be on main -+ ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); -+ -+ this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -+ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); -+ }); -+ }); -+ } -+ } else if (!completions.isEmpty()) { -+ com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); -+ -+ builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); -+ completions.forEach(builder::suggest); -+ player.playerConnection.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), builder.buildFuture().join())); -+ } -+ // Paper end - async tab completion - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index bda96a2f64ae27d53e5a5c6d36ffb5441fee112f..3aed540b6359df9940a26901c55f0306743ad085 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1851,7 +1851,7 @@ public final class CraftServer implements Server { - offers = tabCompleteChat(player, message); - } - -- TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers); -+ TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? net.minecraft.server.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), new BlockPosition(pos)) : null); // Paper - getPluginManager().callEvent(tabEvent); - - return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index a957695457cf3252848ce6ef37069692841b8e28..c5e00bd9e2790992202aadf8eec2002fc88c78f1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -28,6 +28,39 @@ public class ConsoleCommandCompleter implements Completer { - public void complete(LineReader reader, ParsedLine line, List candidates) { - final CraftServer server = this.server.server; - final String buffer = line.line(); -+ // Async Tab Complete -+ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -+ java.util.List completions = new java.util.ArrayList<>(); -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, -+ buffer, true, null); -+ event.callEvent(); -+ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ -+ if (event.isCancelled() || event.isHandled()) { -+ // Still fire sync event with the provided completions, if someone is listening -+ if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { -+ List finalCompletions = completions; -+ Waitable> syncCompletions = new Waitable>() { -+ @Override -+ protected List evaluate() { -+ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); -+ return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); -+ } -+ }; -+ server.getServer().processQueue.add(syncCompletions); -+ try { -+ completions = syncCompletions.get(); -+ } catch (InterruptedException | ExecutionException e1) { -+ e1.printStackTrace(); -+ } -+ } -+ -+ if (!completions.isEmpty()) { -+ candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); -+ } -+ return; -+ } -+ - // Paper end - Waitable> waitable = new Waitable>() { - @Override diff --git a/Unmapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch b/Unmapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch deleted file mode 100644 index 22279d4515..0000000000 --- a/Unmapped-Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 29 Nov 2017 22:18:54 -0500 -Subject: [PATCH] Avoid NPE in PathfinderGoalTempt - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java -index 54b345b5d2fc8d3c511533281f6d387f046f8000..9a120ab9c5c6c858bf3d1690196fe657e76cc1b7 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java -@@ -65,7 +65,7 @@ public class PathfinderGoalTempt extends PathfinderGoal { - } - this.target = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle(); - } -- return tempt; -+ return tempt && this.target != null; // Paper - must have target - plugin might of cancelled - // CraftBukkit end - } - } diff --git a/Unmapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch b/Unmapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch deleted file mode 100644 index 994fed3ea2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:02:53 -0500 -Subject: [PATCH] PlayerPickupExperienceEvent - -Allows plugins to cancel a player picking up an experience orb - -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index f4da22b33c704e675510b4b1a3aa7c180088be29..e3dfb018b06c0139594ddbb88fab2ca8d43ab12f 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -5,6 +5,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityExperienceOrb; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsFluid; -@@ -232,7 +233,7 @@ public class EntityExperienceOrb extends Entity { - @Override - public void pickup(EntityHuman entityhuman) { - if (!this.world.isClientSide) { -- if (this.d == 0 && entityhuman.bu == 0) { -+ if (this.d == 0 && entityhuman.bu == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((EntityPlayer) entityhuman).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - entityhuman.bu = 2; - entityhuman.receive(this, 1); - Entry entry = EnchantmentManager.a(Enchantments.MENDING, (EntityLiving) entityhuman, ItemStack::f); diff --git a/Unmapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch b/Unmapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch deleted file mode 100644 index 41f53d153e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:57:26 -0500 -Subject: [PATCH] ExperienceOrbMergeEvent - -Fired when the server is about to merge 2 experience orbs -Plugins can cancel this if they want to ensure experience orbs do not lose important -metadata such as spawn reason, or conditionally move data from source to target. - -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index aa984540917e363438cc38cdb3004d3fc4987ab4..69b5c76b312d055603ce62ad7b0c88cd01272ba9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -609,7 +609,7 @@ public class CraftEventFactory { - if (e instanceof EntityExperienceOrb) { - EntityExperienceOrb loopItem = (EntityExperienceOrb) e; - // Paper start -- if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { -+ if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper - long newTotal = (long)xp.value + (long)loopItem.value; - if ((int) newTotal < 0) continue; // Overflow - if (maxValue > 0 && newTotal > (long)maxValue) { diff --git a/Unmapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch b/Unmapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch deleted file mode 100644 index d494effb54..0000000000 --- a/Unmapped-Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 20 Dec 2017 17:36:49 -0500 -Subject: [PATCH] Ability to apply mending to XP API - -This allows plugins that give players the ability to apply the experience -points to the Item Mending formula, which will repair an item instead -of giving the player experience points. - -Both an API To standalone mend, and apply mending logic to .giveExp has been added. - -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index e3dfb018b06c0139594ddbb88fab2ca8d43ab12f..3387a19044b3ee2a1ef549c328c8bc354a5b6d23 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -265,10 +265,12 @@ public class EntityExperienceOrb extends Entity { - } - } - -+ public final int durToXp(int i) { return b(i); } // Paper OBFHELPER - private int b(int i) { - return i / 2; - } - -+ public final int xpToDur(int i) { return c(i); } // Paper OBFHELPER - private int c(int i) { - return i * 2; - } -diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java -index d313b02f41e4f4a90676cbb37afce4e92dd4d664..72afbf8f537770540e90a2880ea81de137ea10f5 100644 ---- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java -+++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java -@@ -269,8 +269,8 @@ public class EnchantmentManager { - return getEnchantmentLevel(Enchantments.CHANNELING, itemstack) > 0; - } - -- @Nullable -- public static Entry b(Enchantment enchantment, EntityLiving entityliving) { -+ public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, EntityLiving entityliving) { Entry entry = b(enchantment, entityliving); return entry != null ? entry.getValue() : ItemStack.NULL_ITEM; } // Paper - OBFHELPER -+ @Nullable public static Entry b(Enchantment enchantment, EntityLiving entityliving) { - return a(enchantment, entityliving, (itemstack) -> { - 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 b9a12d59e0144becc7e9c06d9a3c3079d006b583..e00b33493208865c0bd1bd11a96dd2ed1348da7c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -58,13 +58,17 @@ import net.minecraft.server.level.WorldServer; - import net.minecraft.server.network.PlayerConnection; - import net.minecraft.server.players.WhiteListEntry; - import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityExperienceOrb; - import net.minecraft.world.entity.EntityLiving; -+import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.ai.attributes.AttributeMapBase; - import net.minecraft.world.entity.ai.attributes.AttributeModifiable; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.inventory.Container; - import net.minecraft.world.item.EnumColor; -+import net.minecraft.world.item.enchantment.EnchantmentManager; -+import net.minecraft.world.item.enchantment.Enchantments; - import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.saveddata.maps.MapIcon; -@@ -1178,8 +1182,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return GameMode.getByValue(getHandle().playerInteractManager.getGameMode().getId()); - } - -+ // Paper start - @Override -- public void giveExp(int exp) { -+ public int applyMending(int amount) { -+ EntityPlayer handle = getHandle(); -+ // Logic copied from EntityExperienceOrb and remapped to unobfuscated methods/properties -+ net.minecraft.world.item.ItemStack itemstack = EnchantmentManager.getRandomEquippedItemWithEnchant(Enchantments.MENDING, handle); -+ if (!itemstack.isEmpty() && itemstack.getItem().usesDurability()) { -+ -+ EntityExperienceOrb orb = EntityTypes.EXPERIENCE_ORB.create(handle.world); -+ orb.value = amount; -+ orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM; -+ orb.setPositionRaw(handle.locX(), handle.locY(), handle.locZ()); -+ -+ int i = Math.min(orb.xpToDur(amount), itemstack.getDamage()); -+ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, i); -+ i = event.getRepairAmount(); -+ orb.dead = true; -+ if (!event.isCancelled()) { -+ amount -= orb.durToXp(i); -+ itemstack.setDamage(itemstack.getDamage() - i); -+ } -+ } -+ return amount; -+ } -+ -+ @Override -+ public void giveExp(int exp, boolean applyMending) { -+ if (applyMending) { -+ exp = this.applyMending(exp); -+ } -+ // Paper end - getHandle().giveExp(exp); - } - diff --git a/Unmapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch b/Unmapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch deleted file mode 100644 index d6706377d7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 11 Jan 2018 16:47:28 -0600 -Subject: [PATCH] Make max squid spawn height configurable - -I don't know why upstream made only the minimum height configurable but -whatever - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6c692e58cde22003ecbf6dc5695799147c39905a..3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -348,4 +348,9 @@ public class PaperWorldConfig { - expMergeMaxValue = getInt("experience-merge-max-value", -1); - log("Experience Merge Max Value: " + expMergeMaxValue); - } -+ -+ public double squidMaxSpawnHeight; -+ private void squidMaxSpawnHeight() { -+ squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -index 3cc9af925aaf116140d5f36cfc56aa001ffb4e35..7ce5e2597b34d3a4d2a79d73c15e893c064fc88c 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -@@ -196,7 +196,8 @@ public class EntitySquid extends EntityWaterAnimal { - } - - public static boolean b(EntityTypes entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { -- return blockposition.getY() > generatoraccess.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && blockposition.getY() < generatoraccess.getSeaLevel(); // Spigot -+ final double maxHeight = generatoraccess.getMinecraftWorld().paperConfig.squidMaxSpawnHeight > 0 ? generatoraccess.getMinecraftWorld().paperConfig.squidMaxSpawnHeight : generatoraccess.getSeaLevel(); // Paper -+ return blockposition.getY() > generatoraccess.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && blockposition.getY() < maxHeight; // Spigot // Paper - } - - public void a(float f, float f1, float f2) { diff --git a/Unmapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch b/Unmapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch deleted file mode 100644 index bd4df8d022..0000000000 --- a/Unmapped-Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch +++ /dev/null @@ -1,200 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 17:01:31 -0500 -Subject: [PATCH] PreCreatureSpawnEvent - -Adds an event to fire before an Entity is created, so that plugins that need to cancel -CreatureSpawnEvent can do so from this event instead. - -Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste -as it's done after the Entity object has been fully created. - -Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event -instead and save a lot of server resources. - -See: https://github.com/PaperMC/Paper/issues/917 - -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index a707ba365e25ea15e2e9d22110696b6136aa0c6f..1355c074353611669c947cb0f06c67be0ab418aa 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -17,6 +17,7 @@ import net.minecraft.nbt.NBTTagList; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; -@@ -317,6 +318,20 @@ public class EntityTypes { - - @Nullable - public T spawnCreature(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ // Paper start - Call PreCreatureSpawnEvent -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(this).getKey()); -+ if (type != null) { -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(worldserver, blockposition), -+ type, -+ spawnReason -+ ); -+ if (!event.callEvent()) { -+ return null; -+ } -+ } -+ // Paper end - T t0 = this.createCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); - - if (t0 != null) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java -index 41f1aecbf6b506231a1b3b525fe0ce23b35c7840..6c01e460d3a1ff7f865ebc34dfd28d55b16aab98 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java -@@ -33,7 +33,7 @@ public class SensorGolemLastSeen extends Sensor { - Optional> optional = entityliving.getBehaviorController().getMemory(MemoryModuleType.MOBS); - - if (optional.isPresent()) { -- boolean flag = ((List) optional.get()).stream().anyMatch((entityliving1) -> { -+ boolean flag = optional.get().stream().anyMatch((entityliving1) -> { // Paper - decompile fixes - return entityliving1.getEntityType().equals(EntityTypes.IRON_GOLEM); - }); - -@@ -44,6 +44,7 @@ public class SensorGolemLastSeen extends Sensor { - } - } - -+ public static void setDetectedRecently(EntityLiving entityLiving) { b(entityLiving); } // Paper - OBFHELPER - public static void b(EntityLiving entityliving) { - entityliving.getBehaviorController().a(MemoryModuleType.GOLEM_DETECTED_RECENTLY, true, 600L); - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 881bca30d2271560e2f2063f7d50753ec67a23f6..29957e79161db862c3eee5d0ed0cb8edb5dceb1c 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.PacketDebug; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; -@@ -943,6 +944,21 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - BlockPosition blockposition1 = this.a(blockposition, d0, d1); - - if (blockposition1 != null) { -+ // Paper start - Call PreCreatureSpawnEvent -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(world, blockposition1), -+ org.bukkit.entity.EntityType.IRON_GOLEM, -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE -+ ); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ SensorGolemLastSeen.b(this); // Set Golem Last Seen to stop it from spawning another one -+ return null; -+ } -+ break; -+ } -+ // Paper end - EntityIronGolem entityirongolem = (EntityIronGolem) EntityTypes.IRON_GOLEM.createCreature(worldserver, (NBTTagCompound) null, (IChatBaseComponent) null, (EntityHuman) null, blockposition1, EnumMobSpawn.MOB_SUMMONED, false, false); - - if (entityirongolem != null) { -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 883c724fbb86a84ee903b5e7127f14726fe4cf24..d4b8126f12fdf7d9b4f882d3ed7d8da544ed9e8a 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -12,6 +12,7 @@ import net.minecraft.core.particles.Particles; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.UtilColor; - import net.minecraft.util.WeightedRandom; -@@ -125,6 +126,27 @@ public abstract class MobSpawnerAbstract { - WorldServer worldserver = (WorldServer) world; - - if (EntityPositionTypes.a((EntityTypes) optional.get(), worldserver, EnumMobSpawn.SPAWNER, new BlockPosition(d3, d4, d5), world.getRandom())) { -+ // Paper start -+ EntityTypes entityType = optional.get(); -+ String key = EntityTypes.getName(entityType).getKey(); -+ -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); -+ if (type != null) { -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(world, d3, d4, d5), -+ type, -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER -+ ); -+ if (!event.callEvent()) { -+ flag = true; -+ if (event.shouldAbortSpawn()) { -+ break; -+ } -+ continue; -+ } -+ } -+ // Paper end - Entity entity = EntityTypes.a(nbttagcompound, world, (entity1) -> { - entity1.setPositionRotation(d3, d4, d5, entity1.yaw, entity1.pitch); - return entity1; -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index fd0595fd584046326eccacdf0a6afe40c5e84eed..1969d1002b3182338614a2be0519fcdc385b7a44 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -15,6 +15,7 @@ import net.minecraft.core.EnumDirection; - import net.minecraft.core.IPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; -@@ -216,9 +217,16 @@ public final class SpawnerCreature { - j1 = biomesettingsmobs_c.d + worldserver.random.nextInt(1 + biomesettingsmobs_c.e - biomesettingsmobs_c.d); - } - -- if (a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { -+ // Paper start -+ Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); -+ if (doSpawning == null) { -+ return; -+ } -+ if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { -+ // Paper end - EntityInsentient entityinsentient = a(worldserver, biomesettingsmobs_c.c); - -+ - if (entityinsentient == null) { - return; - } -@@ -271,8 +279,24 @@ public final class SpawnerCreature { - } - } - -- private static boolean a(WorldServer worldserver, EnumCreatureType enumcreaturetype, StructureManager structuremanager, ChunkGenerator chunkgenerator, BiomeSettingsMobs.c biomesettingsmobs_c, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { -+ private static Boolean a(WorldServer worldserver, EnumCreatureType enumcreaturetype, StructureManager structuremanager, ChunkGenerator chunkgenerator, BiomeSettingsMobs.c biomesettingsmobs_c, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { // Paper - EntityTypes entitytypes = biomesettingsmobs_c.c; -+ // Paper start -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(entitytypes).getKey()); -+ if (type != null) { -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(worldserver, blockposition_mutableblockposition), -+ type, SpawnReason.NATURAL -+ ); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ return null; -+ } -+ return false; -+ } -+ } -+ // Paper end - - if (entitytypes.e() == EnumCreatureType.MISC) { - return false; diff --git a/Unmapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch b/Unmapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch deleted file mode 100644 index e413709840..0000000000 --- a/Unmapped-Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 17:36:02 -0500 -Subject: [PATCH] PlayerNaturallySpawnCreaturesEvent - -This event can be used for when you want to exclude a certain player -from triggering monster spawns on a server. - -Also a highly more effecient way to blanket block spawns in a world - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 3351c6bcc5244fd7565ba7af08f63ea4d999ce97..677c185aca2cdd64bead9dbed147a87c5bcf1678 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -611,6 +611,15 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.getMethodProfiler().exit(); - //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper - //Collections.shuffle(list); // Paper -+ //Paper start - call player naturally spawn event -+ int chunkRange = world.spigotConfig.mobSpawnRange; -+ chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; -+ chunkRange = Math.min(chunkRange, 8); -+ for (EntityPlayer entityPlayer : this.world.getPlayers()) { -+ entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); -+ entityPlayer.playerNaturallySpawnedEvent.callEvent(); -+ }; -+ // Paper end - this.world.timings.chunkTicks.startTiming(); // Paper - this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 5b2ae94ed7d499e401a058691eb6ed413b626150..de7167ddf7b36ef266e511187789f99244401c21 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.level; - -+import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent; - import com.google.common.collect.Lists; - import com.mojang.authlib.GameProfile; - import com.mojang.datafixers.util.Either; -@@ -228,6 +229,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean sentListPacket = false; - public Integer clientViewDistance; - // CraftBukkit end -+ public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - - public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 1d71a19a7bbe463f537861531113dd1ed3e5b977..d1e45dfb99074ec027d4f943391a024c726d93b2 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -966,12 +966,23 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; - chunkRange = (chunkRange > 8) ? 8 : chunkRange; - -- double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; -+ final int finalChunkRange = chunkRange; // Paper for lambda below -+ //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event - // Spigot end - long i = chunkcoordintpair.pair(); - - return !this.chunkDistanceManager.d(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { -- return !entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot -+ // Paper start - -+ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; -+ double blockRange = 16384.0D; -+ if (reducedRange) { -+ event = entityplayer.playerNaturallySpawnedEvent; -+ if (event == null || event.isCancelled()) return false; -+ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); -+ } -+ -+ return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot -+ // Paper end - }); - } - diff --git a/Unmapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch b/Unmapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch deleted file mode 100644 index da897bd972..0000000000 --- a/Unmapped-Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 19 Jan 2018 00:36:25 -0500 -Subject: [PATCH] Add setPlayerProfile API for Skulls - -This allows you to create already filled textures on Skulls to avoid texture lookups -which commonly cause rate limit issues with Mojang API - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -index 80ee7ab69ff70431d51321d403e5e3400a24bd67..00fb749f4d181d8d830496cf741d589e10af5098 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -@@ -1,5 +1,7 @@ - package org.bukkit.craftbukkit.block; - -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import com.google.common.base.Preconditions; - import com.mojang.authlib.GameProfile; - import net.minecraft.server.MinecraftServer; -@@ -15,6 +17,7 @@ import org.bukkit.block.data.BlockData; - import org.bukkit.block.data.Directional; - import org.bukkit.block.data.Rotatable; - import org.bukkit.craftbukkit.entity.CraftPlayer; -+import javax.annotation.Nullable; - - public class CraftSkull extends CraftBlockEntityState implements Skull { - -@@ -105,6 +108,20 @@ public class CraftSkull extends CraftBlockEntityState implement - } - } - -+ // Paper start -+ @Override -+ public void setPlayerProfile(PlayerProfile profile) { -+ Preconditions.checkNotNull(profile, "profile"); -+ this.profile = CraftPlayerProfile.asAuthlibCopy(profile); -+ } -+ -+ @Nullable -+ @Override -+ public PlayerProfile getPlayerProfile() { -+ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; -+ } -+ // Paper end -+ - @Override - public BlockFace getRotation() { - BlockData blockData = getBlockData(); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index 8298ae9bf1c5635f08552c15f004b3d0f6e9f19b..6db0d35eba647a0e81ca464fa52dc4a404ddd2ab 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -@@ -8,6 +8,8 @@ import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.world.level.block.entity.TileEntitySkull; -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import org.bukkit.Bukkit; - import org.bukkit.Material; - import org.bukkit.OfflinePlayer; -@@ -18,6 +20,7 @@ import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta; - import org.bukkit.craftbukkit.util.CraftMagicNumbers; - import org.bukkit.inventory.meta.SkullMeta; - -+import javax.annotation.Nullable; - @DelegateDeserialization(SerializableMeta.class) - class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - -@@ -149,6 +152,19 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - return hasOwner() ? profile.getName() : null; - } - -+ // Paper start -+ @Override -+ public void setPlayerProfile(@Nullable PlayerProfile profile) { -+ setProfile((profile == null) ? null : CraftPlayerProfile.asAuthlibCopy(profile)); -+ } -+ -+ @Nullable -+ @Override -+ public PlayerProfile getPlayerProfile() { -+ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; -+ } -+ // Paper end -+ - @Override - public OfflinePlayer getOwningPlayer() { - if (hasOwner()) { -@@ -175,7 +191,7 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - } else { - // Paper start - Use Online Players Skull - GameProfile newProfile = null; -- net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayer(name); -+ net.minecraft.server.level.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayer(name); - if (player != null) newProfile = player.getProfile(); - if (newProfile == null) newProfile = new GameProfile(null, name); - setProfile(newProfile); diff --git a/Unmapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch b/Unmapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch deleted file mode 100644 index 30643d081c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 2 Jan 2018 00:31:26 -0500 -Subject: [PATCH] Fill Profile Property Events - -Allows plugins to populate profile properties from local sources to avoid calls out to Mojang API -to fill in textures for example. - -If Mojang API does need to be hit, event fire so you can get the results. - -This is useful for implementing a ProfileCache for Player Skulls - -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -index 93d73c27340645c7502acafdc0b2cfbc1a759dd8..5c7d2ee19243d0911a3a00af3ae42078a2ccba94 100644 ---- a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -@@ -1,6 +1,8 @@ - package com.destroystokyo.paper.profile; - - import com.mojang.authlib.Environment; -+import com.destroystokyo.paper.event.profile.FillProfileEvent; -+import com.destroystokyo.paper.event.profile.PreFillProfileEvent; - import com.mojang.authlib.GameProfile; - import com.mojang.authlib.minecraft.MinecraftProfileTexture; - import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -@@ -20,7 +22,15 @@ public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionServi - - @Override - public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { -- return super.fillProfileProperties(profile, requireSecure); -+ CraftPlayerProfile playerProfile = (CraftPlayerProfile) CraftPlayerProfile.asBukkitMirror(profile); -+ new PreFillProfileEvent(playerProfile).callEvent(); -+ profile = playerProfile.getGameProfile(); -+ if (profile.isComplete() && profile.getProperties().containsKey("textures")) { -+ return profile; -+ } -+ GameProfile gameProfile = super.fillProfileProperties(profile, requireSecure); -+ new FillProfileEvent(CraftPlayerProfile.asBukkitMirror(gameProfile)).callEvent(); -+ return gameProfile; - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch b/Unmapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch deleted file mode 100644 index e919ba3032..0000000000 --- a/Unmapped-Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 19 Jan 2018 08:15:29 -0600 -Subject: [PATCH] PlayerAdvancementCriterionGrantEvent - - -diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index d832cc2f3cc1ee73299a7f07eb2ccc3d392d5cf8..7d37626277823d5db05189c20bb1ebf91aa2a286 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -297,6 +297,12 @@ public class AdvancementDataPlayer { - boolean flag1 = advancementprogress.isDone(); - - if (advancementprogress.a(s)) { -+ // Paper start -+ if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.bukkit, s).callEvent()) { -+ advancementprogress.b(s); -+ return false; -+ } -+ // Paper end - this.d(advancement); - this.j.add(advancement); - flag = true; diff --git a/Unmapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch b/Unmapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch deleted file mode 100644 index 658b0384d9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch +++ /dev/null @@ -1,296 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 27 Jan 2018 17:04:14 -0500 -Subject: [PATCH] Add ArmorStand Item Meta - -This is adds basic item meta for armor stands. It does not add all -possible metadata however. - -There are armor, hand, and equipment types, as well as position data -that can also be added here. This initial addition should serve a -starting point for future additions in this area. - -Fixes GH-559 - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -index c593499aee3a2737cd80739ce61e7fba133d11ec..6b460841a8428727dd55a841fe5af06de9b1bdd1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -@@ -9,9 +9,22 @@ import org.bukkit.configuration.serialization.DelegateDeserialization; - import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey; - - @DelegateDeserialization(CraftMetaItem.SerializableMeta.class) --public class CraftMetaArmorStand extends CraftMetaItem { -+public class CraftMetaArmorStand extends CraftMetaItem implements com.destroystokyo.paper.inventory.meta.ArmorStandMeta { // Paper - - static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag"); -+ // Paper start -+ static final ItemMetaKey INVISIBLE = new ItemMetaKey("Invisible", "invisible"); -+ static final ItemMetaKey NO_BASE_PLATE = new ItemMetaKey("NoBasePlate", "no-base-plate"); -+ static final ItemMetaKey SHOW_ARMS = new ItemMetaKey("ShowArms", "show-arms"); -+ static final ItemMetaKey SMALL = new ItemMetaKey("Small", "small"); -+ static final ItemMetaKey MARKER = new ItemMetaKey("Marker", "marker"); -+ -+ private boolean invisible; -+ private boolean noBasePlate; -+ private boolean showArms; -+ private boolean small; -+ private boolean marker; -+ // Paper end - NBTTagCompound entityTag; - - CraftMetaArmorStand(CraftMetaItem meta) { -@@ -22,6 +35,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { - } - - CraftMetaArmorStand armorStand = (CraftMetaArmorStand) meta; -+ // Paper start -+ this.invisible = armorStand.invisible; -+ this.noBasePlate = armorStand.noBasePlate; -+ this.showArms = armorStand.showArms; -+ this.small = armorStand.small; -+ this.marker = armorStand.marker; -+ // Paper end - this.entityTag = armorStand.entityTag; - } - -@@ -30,11 +50,47 @@ public class CraftMetaArmorStand extends CraftMetaItem { - - if (tag.hasKey(ENTITY_TAG.NBT)) { - entityTag = tag.getCompound(ENTITY_TAG.NBT); -+ -+ // Paper start -+ if (entityTag.hasKey(INVISIBLE.NBT)) { -+ invisible = entityTag.getBoolean(INVISIBLE.NBT); -+ } -+ -+ if (entityTag.hasKey(NO_BASE_PLATE.NBT)) { -+ noBasePlate = entityTag.getBoolean(NO_BASE_PLATE.NBT); -+ } -+ -+ if (entityTag.hasKey(SHOW_ARMS.NBT)) { -+ showArms = entityTag.getBoolean(SHOW_ARMS.NBT); -+ } -+ -+ if (entityTag.hasKey(SMALL.NBT)) { -+ small = entityTag.getBoolean(SMALL.NBT); -+ } -+ -+ if (entityTag.hasKey(MARKER.NBT)) { -+ marker = entityTag.getBoolean(MARKER.NBT); -+ } -+ // Paper end - } - } - - CraftMetaArmorStand(Map map) { - super(map); -+ -+ // Paper start -+ boolean invis = SerializableMeta.getBoolean(map, INVISIBLE.BUKKIT); -+ boolean noBase = SerializableMeta.getBoolean(map, NO_BASE_PLATE.BUKKIT); -+ boolean showArms = SerializableMeta.getBoolean(map, SHOW_ARMS.BUKKIT); -+ boolean small = SerializableMeta.getBoolean(map, SMALL.BUKKIT); -+ boolean marker = SerializableMeta.getBoolean(map, MARKER.BUKKIT); -+ -+ this.invisible = invis; -+ this.noBasePlate = noBase; -+ this.showArms = showArms; -+ this.small = small; -+ this.marker = marker; -+ // Paper end - } - - @Override -@@ -57,6 +113,32 @@ public class CraftMetaArmorStand extends CraftMetaItem { - void applyToItem(NBTTagCompound tag) { - super.applyToItem(tag); - -+ // Paper start -+ if (!isArmorStandEmpty() && entityTag == null) { -+ entityTag = new NBTTagCompound(); -+ } -+ -+ if (isInvisible()) { -+ entityTag.setBoolean(INVISIBLE.NBT, invisible); -+ } -+ -+ if (hasNoBasePlate()) { -+ entityTag.setBoolean(NO_BASE_PLATE.NBT, noBasePlate); -+ } -+ -+ if (shouldShowArms()) { -+ entityTag.setBoolean(SHOW_ARMS.NBT, showArms); -+ } -+ -+ if (isSmall()) { -+ entityTag.setBoolean(SMALL.NBT, small); -+ } -+ -+ if (isMarker()) { -+ entityTag.setBoolean(MARKER.NBT, marker); -+ } -+ // Paper end -+ - if (entityTag != null) { - tag.set(ENTITY_TAG.NBT, entityTag); - } -@@ -78,7 +160,7 @@ public class CraftMetaArmorStand extends CraftMetaItem { - } - - boolean isArmorStandEmpty() { -- return !(entityTag != null); -+ return !(isInvisible() || hasNoBasePlate() || shouldShowArms() || isSmall() || isMarker() || entityTag != null); - } - - @Override -@@ -89,7 +171,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { - if (meta instanceof CraftMetaArmorStand) { - CraftMetaArmorStand that = (CraftMetaArmorStand) meta; - -- return entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : entityTag == null; -+ // Paper start -+ return invisible == that.invisible && -+ noBasePlate == that.noBasePlate && -+ showArms == that.showArms && -+ small == that.small && -+ marker == that.marker; -+ // Paper end - } - return true; - } -@@ -104,9 +192,14 @@ public class CraftMetaArmorStand extends CraftMetaItem { - final int original; - int hash = original = super.applyHash(); - -- if (entityTag != null) { -- hash = 73 * hash + entityTag.hashCode(); -- } -+ // Paper start -+ hash += entityTag != null ? 73 * hash + entityTag.hashCode() : 0; -+ hash += isInvisible() ? 61 * hash + 1231 : 0; -+ hash += hasNoBasePlate() ? 61 * hash + 1231 : 0; -+ hash += shouldShowArms() ? 61 * hash + 1231 : 0; -+ hash += isSmall() ? 61 * hash + 1231 : 0; -+ hash += isMarker() ? 61 * hash + 1231 : 0; -+ // Paper end - - return original != hash ? CraftMetaArmorStand.class.hashCode() ^ hash : hash; - } -@@ -115,6 +208,28 @@ public class CraftMetaArmorStand extends CraftMetaItem { - Builder serialize(Builder builder) { - super.serialize(builder); - -+ // Paper start -+ if (isInvisible()) { -+ builder.put(INVISIBLE.BUKKIT, invisible); -+ } -+ -+ if (hasNoBasePlate()) { -+ builder.put(NO_BASE_PLATE.BUKKIT, noBasePlate); -+ } -+ -+ if (shouldShowArms()) { -+ builder.put(SHOW_ARMS.BUKKIT, showArms); -+ } -+ -+ if (isSmall()) { -+ builder.put(SMALL.BUKKIT, small); -+ } -+ -+ if (isMarker()) { -+ builder.put(MARKER.BUKKIT, marker); -+ } -+ // Paper end -+ - return builder; - } - -@@ -128,4 +243,56 @@ public class CraftMetaArmorStand extends CraftMetaItem { - - return clone; - } -+ -+ // Paper start -+ @Override -+ public boolean isInvisible() { -+ return invisible; -+ } -+ -+ @Override -+ public boolean hasNoBasePlate() { -+ return noBasePlate; -+ } -+ -+ @Override -+ public boolean shouldShowArms() { -+ return showArms; -+ } -+ -+ @Override -+ public boolean isSmall() { -+ return small; -+ } -+ -+ @Override -+ public boolean isMarker() { -+ return marker; -+ } -+ -+ @Override -+ public void setInvisible(boolean invisible) { -+ this.invisible = invisible; -+ } -+ -+ @Override -+ public void setNoBasePlate(boolean noBasePlate) { -+ this.noBasePlate = noBasePlate; -+ } -+ -+ @Override -+ public void setShowArms(boolean showArms) { -+ this.showArms = showArms; -+ } -+ -+ @Override -+ public void setSmall(boolean small) { -+ this.small = small; -+ } -+ -+ @Override -+ public void setMarker(boolean marker) { -+ this.marker = marker; -+ } -+ // 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 57a6e66866ea82caccbbbfd55948a081f50f6bbe..7f790c484fec77e1d1f1dc6abe0daa19d009ae46 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -1442,6 +1442,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - CraftMetaCrossbow.CHARGED.NBT, - CraftMetaCrossbow.CHARGED_PROJECTILES.NBT, - CraftMetaSuspiciousStew.EFFECTS.NBT, -+ // Paper start -+ CraftMetaArmorStand.ENTITY_TAG.NBT, -+ CraftMetaArmorStand.INVISIBLE.NBT, -+ CraftMetaArmorStand.NO_BASE_PLATE.NBT, -+ CraftMetaArmorStand.SHOW_ARMS.NBT, -+ CraftMetaArmorStand.SMALL.NBT, -+ CraftMetaArmorStand.MARKER.NBT, -+ // Paper end - CraftMetaCompass.LODESTONE_DIMENSION.NBT, - CraftMetaCompass.LODESTONE_POS.NBT, - CraftMetaCompass.LODESTONE_TRACKED.NBT -diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -index 9a351c137776ac622f4df7353bb353142b3a6ccc..42f577ed3508ba5a380648461e149f16ce97c9bd 100644 ---- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -@@ -313,6 +313,7 @@ public class ItemMetaTest extends AbstractTestingBase { - final CraftMetaArmorStand meta = (CraftMetaArmorStand) cleanStack.getItemMeta(); - meta.entityTag = new NBTTagCompound(); - meta.entityTag.setBoolean("Small", true); -+ meta.setInvisible(true); // Paper - cleanStack.setItemMeta(meta); - return cleanStack; - } diff --git a/Unmapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch b/Unmapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch deleted file mode 100644 index d3407a908a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 11 Feb 2018 10:43:46 +0000 -Subject: [PATCH] Extend Player Interact cancellation - -GUIs are opened on the client, meaning that the server cannot block them from opening, -However, it is possible to close these GUIs from the server. - -Flower pots are also not updated on the client when interaction is cancelled, this patch -also resolves this. - -Update adjacent blocks of doors, double plants, pistons and beds -when cancelling interaction. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 74b4b127f39a0ad06e8f9add6861763724ab70ba..14f287d30c9a141f78f6311bef02a6fc4fa17564 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -6,6 +6,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.network.protocol.game.PacketPlayInBlockDig; - import net.minecraft.network.protocol.game.PacketPlayOutBlockBreak; -+import net.minecraft.network.protocol.game.PacketPlayOutCloseWindow; - import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo; - import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; -@@ -18,6 +19,7 @@ import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.BlockCommand; -+import net.minecraft.world.level.block.BlockFlowerPot; - import net.minecraft.world.level.block.BlockJigsaw; - import net.minecraft.world.level.block.BlockStructure; - import net.minecraft.world.level.block.entity.TileEntity; -@@ -180,6 +182,11 @@ public class PlayerInteractManager { - PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, enumdirection, this.player.inventory.getItemInHand(), EnumHand.MAIN_HAND); - if (event.isCancelled()) { - // Let the client know the block still exists -+ // Paper start - brute force neighbor blocks for any attached blocks -+ for (EnumDirection dir : EnumDirection.values()) { -+ this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition.shift(dir))); -+ } -+ // Paper end - this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(this.world, blockposition)); - // Update any tile entity data for this block - TileEntity tileentity = this.world.getTileEntity(blockposition); -@@ -484,6 +491,7 @@ public class PlayerInteractManager { - interactItemStack = itemstack.cloneItemStack(); - - if (event.useInteractedBlock() == Event.Result.DENY) { -+ - // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. - if (iblockdata.getBlock() instanceof BlockDoor) { - boolean bottom = iblockdata.get(BlockDoor.HALF) == BlockPropertyDoubleBlockHalf.LOWER; -@@ -496,7 +504,13 @@ public class PlayerInteractManager { - - // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) - entityplayer.playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition.up())); -+ // Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method -+ } else if (iblockdata.getBlock() instanceof BlockStructure) { -+ entityplayer.playerConnection.sendPacket(new PacketPlayOutCloseWindow()); -+ } else if (iblockdata.getBlock() instanceof BlockCommand) { -+ entityplayer.playerConnection.sendPacket(new PacketPlayOutCloseWindow()); - } -+ // Paper end - extend Player Interact cancellation - entityplayer.getBukkitEntity().updateInventory(); // SPIGOT-2867 - enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? EnumInteractionResult.SUCCESS : EnumInteractionResult.PASS; - } else if (this.gamemode == EnumGamemode.SPECTATOR) { diff --git a/Unmapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch b/Unmapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch deleted file mode 100644 index eae20f237a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 24 Feb 2018 01:14:55 -0500 -Subject: [PATCH] Tameable#getOwnerUniqueId API - -This is faster if all you need is the UUID, as .getOwner() will cause -an OfflinePlayer to be loaded from disk. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -index 62ccef35e4b4238c50faf778fbf3ea9a494ca387..5b66165471197aad57e23f9a6669b11f25a5e4f2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -@@ -90,6 +90,9 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac - } - } - -+ public UUID getOwnerUniqueId() { -+ return getOwnerUUID(); -+ } - public UUID getOwnerUUID() { - return getHandle().getOwnerUUID(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -index 3ac6623199f991ba16dbd62f4d6eed9982b22bcb..73a8ae346fb2ca5af172d96fa6b28e4d41a8c294 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -@@ -17,6 +17,9 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat - return (EntityTameableAnimal) super.getHandle(); - } - -+ public UUID getOwnerUniqueId() { -+ return getOwnerUUID(); -+ } - public UUID getOwnerUUID() { - try { - return getHandle().getOwnerUUID(); diff --git a/Unmapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch b/Unmapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch deleted file mode 100644 index 70c6b6d3e1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Sat, 10 Mar 2018 00:50:24 +0100 -Subject: [PATCH] Toggleable player crits, helps mitigate hacked clients. - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2..48f0385c7203c7955de5a015f3dc42be2ab7b681 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -192,6 +192,11 @@ public class PaperWorldConfig { - disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); - } - -+ public boolean disablePlayerCrits; -+ private void disablePlayerCrits() { -+ disablePlayerCrits = getBoolean("game-mechanics.disable-player-crits", false); -+ } -+ - public boolean allChunksAreSlimeChunks; - private void allChunksAreSlimeChunks() { - allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index f9d0623a3ed5f49758cd5e97fe9f63a5b3198e58..18b0020d184e46c8957e82100681c8c66b1c3b62 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1134,6 +1134,7 @@ public abstract class EntityHuman extends EntityLiving { - - boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.isClimbing() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && entity instanceof EntityLiving; - -+ flag2 = flag2 && !world.paperConfig.disablePlayerCrits; // Paper - flag2 = flag2 && !this.isSprinting(); - if (flag2) { - f *= 1.5F; diff --git a/Unmapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/Unmapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch deleted file mode 100644 index 8ea2e3bb74..0000000000 --- a/Unmapped-Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 10 Mar 2018 16:33:15 -0500 -Subject: [PATCH] Prevent Frosted Ice from loading/holding chunks - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -index e32e94868386ff06ff29254e6cc3bee9b446a293..cbe8a6db356396f9fd9ce7cc61a5845bb8e6499d 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -@@ -40,7 +40,8 @@ public class BlockIceFrost extends BlockIce { - EnumDirection enumdirection = aenumdirection[j]; - - blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, enumdirection); -- IBlockData iblockdata1 = worldserver.getType(blockposition_mutableblockposition); -+ IBlockData iblockdata1 = worldserver.getTypeIfLoaded(blockposition_mutableblockposition); // Paper -+ if (iblockdata1 == null) { continue; } // Paper - - if (iblockdata1.a((Block) this) && !this.e(iblockdata1, (World) worldserver, blockposition_mutableblockposition)) { - worldserver.getBlockTickList().a(blockposition_mutableblockposition, this, MathHelper.nextInt(random, worldserver.paperConfig.frostedIceDelayMin, worldserver.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay -@@ -83,7 +84,9 @@ public class BlockIceFrost extends BlockIce { - EnumDirection enumdirection = aenumdirection[l]; - - blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, enumdirection); -- if (iblockaccess.getType(blockposition_mutableblockposition).a((Block) this)) { -+ // Paper start -+ IBlockData type = iblockaccess.getTypeIfLoaded(blockposition_mutableblockposition); -+ if (type != null && type.a((Block) this)) { // Paper end - ++j; - if (j >= i) { - return false; diff --git a/Unmapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch b/Unmapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch deleted file mode 100644 index c5919e14be..0000000000 --- a/Unmapped-Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 11 Mar 2018 14:13:33 -0400 -Subject: [PATCH] Disable Explicit Network Manager Flushing - -This seems completely pointless, as packet dispatch uses .writeAndFlush. - -Things seem to work fine without explicit flushing, but incase issues arise, -provide a System property to re-enable it using improved logic of doing the -flushing on the netty event loop, so it won't do the flush on the main thread. - -Renable flushing by passing -Dpaper.explicit-flush=true - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 60e4a4aa3854aaeb250d1318f2f25cf3591ea1d3..297820baef99e97e1216a64c527219e9ccc3e320 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -73,6 +73,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - // Paper start - NetworkClient implementation - public int protocolVersion; - public java.net.InetSocketAddress virtualHost; -+ private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); - // Paper end - - public NetworkManager(EnumProtocolDirection enumprotocoldirection) { -@@ -240,7 +241,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - - if (this.channel != null) { -- this.channel.flush(); -+ if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version - } - - if (this.t++ % 20 == 0) { diff --git a/Unmapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch b/Unmapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch deleted file mode 100644 index a0c59c93c8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch +++ /dev/null @@ -1,283 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 15:56:26 +0200 -Subject: [PATCH] Implement extended PaperServerListPingEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e7f1efd0466a5d7bb9584ffbd6fbac1ecc6153a5 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; -+import org.bukkit.entity.Player; -+import org.bukkit.util.CachedServerIcon; -+ -+import javax.annotation.Nullable; -+ -+class PaperServerListPingEventImpl extends PaperServerListPingEvent { -+ -+ private final MinecraftServer server; -+ -+ PaperServerListPingEventImpl(MinecraftServer server, StatusClient client, int protocolVersion, @Nullable CachedServerIcon icon) { -+ super(client, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers(), -+ server.getServerModName() + ' ' + server.getVersion(), protocolVersion, icon); -+ this.server = server; -+ } -+ -+ @Override -+ protected final Object[] getOnlinePlayers() { -+ return this.server.getPlayerList().players.toArray(); -+ } -+ -+ @Override -+ protected final Player getBukkitPlayer(Object player) { -+ return ((EntityPlayer) player).getBukkitEntity(); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..46e84ac6ba5d32d030267fb0c991c281a673c716 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java -@@ -0,0 +1,11 @@ -+package com.destroystokyo.paper.network; -+ -+import net.minecraft.network.NetworkManager; -+ -+class PaperStatusClient extends PaperNetworkClient implements StatusClient { -+ -+ PaperStatusClient(NetworkManager networkManager) { -+ super(networkManager); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..174326871df9b61beec51ef6a1e5f26932404b6a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java -@@ -0,0 +1,110 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; -+import com.google.common.base.MoreObjects; -+import com.google.common.base.Strings; -+import com.mojang.authlib.GameProfile; -+import io.papermc.paper.adventure.AdventureComponent; -+import java.util.List; -+import java.util.UUID; -+import javax.annotation.Nonnull; -+import net.minecraft.network.NetworkManager; -+import net.minecraft.network.protocol.status.PacketStatusOutServerInfo; -+import net.minecraft.network.protocol.status.ServerPing; -+import net.minecraft.server.MinecraftServer; -+ -+public final class StandardPaperServerListPingEventImpl extends PaperServerListPingEventImpl { -+ -+ private static final GameProfile[] EMPTY_PROFILES = new GameProfile[0]; -+ private static final UUID FAKE_UUID = new UUID(0, 0); -+ -+ private GameProfile[] originalSample; -+ -+ private StandardPaperServerListPingEventImpl(MinecraftServer server, NetworkManager networkManager, ServerPing ping) { -+ super(server, new PaperStatusClient(networkManager), ping.getServerData() != null ? ping.getServerData().getProtocolVersion() : -1, server.server.getServerIcon()); -+ this.originalSample = ping.getPlayers() == null ? null : ping.getPlayers().getSample(); // GH-1473 - pre-tick race condition NPE -+ } -+ -+ @Nonnull -+ @Override -+ public List getPlayerSample() { -+ List sample = super.getPlayerSample(); -+ -+ if (this.originalSample != null) { -+ for (GameProfile profile : this.originalSample) { -+ sample.add(CraftPlayerProfile.asBukkitCopy(profile)); -+ } -+ this.originalSample = null; -+ } -+ -+ return sample; -+ } -+ -+ private GameProfile[] getPlayerSampleHandle() { -+ if (this.originalSample != null) { -+ return this.originalSample; -+ } -+ -+ List entries = super.getPlayerSample(); -+ if (entries.isEmpty()) { -+ return EMPTY_PROFILES; -+ } -+ -+ GameProfile[] profiles = new GameProfile[entries.size()]; -+ for (int i = 0; i < profiles.length; i++) { -+ /* -+ * Avoid null UUIDs/names since that will make the response invalid -+ * on the client. -+ * Instead, fall back to a fake/empty UUID and an empty string as name. -+ * This can be used to create custom lines in the player list that do not -+ * refer to a specific player. -+ */ -+ -+ PlayerProfile profile = entries.get(i); -+ if (profile.getId() != null && profile.getName() != null) { -+ profiles[i] = CraftPlayerProfile.asAuthlib(profile); -+ } else { -+ profiles[i] = new GameProfile(MoreObjects.firstNonNull(profile.getId(), FAKE_UUID), Strings.nullToEmpty(profile.getName())); -+ } -+ } -+ -+ return profiles; -+ } -+ -+ @SuppressWarnings("deprecation") -+ public static void processRequest(MinecraftServer server, NetworkManager networkManager) { -+ StandardPaperServerListPingEventImpl event = new StandardPaperServerListPingEventImpl(server, networkManager, server.getServerPing()); -+ server.server.getPluginManager().callEvent(event); -+ -+ // Close connection immediately if event is cancelled -+ if (event.isCancelled()) { -+ networkManager.close(null); -+ return; -+ } -+ -+ // Setup response -+ ServerPing ping = new ServerPing(); -+ -+ // Description -+ ping.setMOTD(new AdventureComponent(event.motd())); -+ -+ // Players -+ if (!event.shouldHidePlayers()) { -+ ping.setPlayerSample(new ServerPing.ServerPingPlayerSample(event.getMaxPlayers(), event.getNumPlayers())); -+ ping.getPlayers().setSample(event.getPlayerSampleHandle()); -+ } -+ -+ // Version -+ ping.setServerInfo(new ServerPing.ServerData(event.getVersion(), event.getProtocolVersion())); -+ -+ // Favicon -+ if (event.getServerIcon() != null) { -+ ping.setFavicon(event.getServerIcon().getData()); -+ } -+ -+ // Send response -+ networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java b/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java -index 0ebeacaaeb265d202f52c758566a5160c42e8a55..cb37805c8cc5a064391f338c6359df518f6db39a 100644 ---- a/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java -+++ b/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java -@@ -2,6 +2,7 @@ package net.minecraft.network.protocol.status; - - import com.google.gson.Gson; - import com.google.gson.GsonBuilder; -+import io.papermc.paper.adventure.AdventureComponent; // Paper - import java.io.IOException; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.chat.ChatModifier; -@@ -12,7 +13,9 @@ import net.minecraft.util.ChatTypeAdapterFactory; - - public class PacketStatusOutServerInfo implements Packet { - -- private static final Gson a = (new GsonBuilder()).registerTypeAdapter(ServerPing.ServerData.class, new ServerPing.ServerData.Serializer()).registerTypeAdapter(ServerPing.ServerPingPlayerSample.class, new ServerPing.ServerPingPlayerSample.Serializer()).registerTypeAdapter(ServerPing.class, new ServerPing.Serializer()).registerTypeHierarchyAdapter(IChatBaseComponent.class, new IChatBaseComponent.ChatSerializer()).registerTypeHierarchyAdapter(ChatModifier.class, new ChatModifier.ChatModifierSerializer()).registerTypeAdapterFactory(new ChatTypeAdapterFactory()).create(); -+ private static final Gson a = (new GsonBuilder()).registerTypeAdapter(ServerPing.ServerData.class, new ServerPing.ServerData.Serializer()).registerTypeAdapter(ServerPing.ServerPingPlayerSample.class, new ServerPing.ServerPingPlayerSample.Serializer()).registerTypeAdapter(ServerPing.class, new ServerPing.Serializer()).registerTypeHierarchyAdapter(IChatBaseComponent.class, new IChatBaseComponent.ChatSerializer()).registerTypeHierarchyAdapter(ChatModifier.class, new ChatModifier.ChatModifierSerializer()).registerTypeAdapterFactory(new ChatTypeAdapterFactory()) -+ .registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()) -+ .create(); - private ServerPing b; - - public PacketStatusOutServerInfo() {} -diff --git a/src/main/java/net/minecraft/network/protocol/status/ServerPing.java b/src/main/java/net/minecraft/network/protocol/status/ServerPing.java -index 005ae7a75dfb19152abb606da29acad07c85e499..b9e36a83837913cd3e5abe598f695ba7a9ffc417 100644 ---- a/src/main/java/net/minecraft/network/protocol/status/ServerPing.java -+++ b/src/main/java/net/minecraft/network/protocol/status/ServerPing.java -@@ -31,6 +31,7 @@ public class ServerPing { - this.a = ichatbasecomponent; - } - -+ public ServerPingPlayerSample getPlayers() { return b(); } // Paper - OBFHELPER - public ServerPing.ServerPingPlayerSample b() { - return this.b; - } -@@ -162,10 +163,12 @@ public class ServerPing { - return this.b; - } - -+ public GameProfile[] getSample() { return c(); } // Paper - OBFHELPER - public GameProfile[] c() { - return this.c; - } - -+ public void setSample(GameProfile[] sample) { a(sample); } // Paper - OBFHELPER - public void a(GameProfile[] agameprofile) { - this.c = agameprofile; - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 71496fff9faeb72e28dfc2842ed8105a9cb835c1..5bbd3bb52b76b8b6cdf90c94bcb29f122f31c543 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2,6 +2,9 @@ package net.minecraft.server; - - import com.google.common.base.Splitter; - import com.google.common.collect.ImmutableList; -+import co.aikar.timings.Timings; -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+import com.google.common.base.Stopwatch; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -1240,7 +1243,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant= 5000000000L) { - this.T = i; - this.serverPing.setPlayerSample(new ServerPing.ServerPingPlayerSample(this.getMaxPlayers(), this.getPlayerCount())); -- GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), 12)]; -+ GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), org.spigotmc.SpigotConfig.playerSample)]; // Paper - int j = MathHelper.nextInt(this.r, 0, this.getPlayerCount() - agameprofile.length); - - for (int k = 0; k < agameprofile.length; ++k) { -diff --git a/src/main/java/net/minecraft/server/network/PacketStatusListener.java b/src/main/java/net/minecraft/server/network/PacketStatusListener.java -index d219eda271a71f786808a6958b829fca40a1aaba..e1997563984540e6edf5d3b697d029dc5f3c40e1 100644 ---- a/src/main/java/net/minecraft/server/network/PacketStatusListener.java -+++ b/src/main/java/net/minecraft/server/network/PacketStatusListener.java -@@ -48,6 +48,8 @@ public class PacketStatusListener implements PacketStatusInListener { - this.networkManager.close(PacketStatusListener.a); - } else { - this.d = true; -+ // Paper start - Replace everything -+ /* - // CraftBukkit start - // this.networkManager.sendPacket(new PacketStatusOutServerInfo(this.minecraftServer.getServerPing())); - final Object[] players = minecraftServer.getPlayerList().players.toArray(); -@@ -143,6 +145,9 @@ public class PacketStatusListener implements PacketStatusInListener { - ping.setServerInfo(new ServerPing.ServerData(minecraftServer.getServerModName() + " " + minecraftServer.getVersion(), version)); - - this.networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); -+ */ -+ com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.minecraftServer, this.networkManager); -+ // Paper end - } - // CraftBukkit end - } -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index e8e5e5b568ba53dd006f1461cb4f027ceeae5528..11f8a2e5bf43013bce8675ea310ff42eacf14754 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -289,7 +289,7 @@ public class SpigotConfig - public static int playerSample; - private static void playerSample() - { -- playerSample = getInt( "settings.sample-count", 12 ); -+ playerSample = Math.max( getInt( "settings.sample-count", 12 ), 0 ); // Paper - Avoid negative counts - Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger - } - diff --git a/Unmapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch b/Unmapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch deleted file mode 100644 index b0ae823221..0000000000 --- a/Unmapped-Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch +++ /dev/null @@ -1,370 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 16 Mar 2018 22:59:43 -0400 -Subject: [PATCH] Improved Async Task Scheduler - -The Craft Scheduler still uses the primary thread for task scheduling. -This results in the main thread still having to do work as part of the -dispatching of async tasks. - -If plugins make use of lots of async tasks, such as particle emitters -that want to keep the logic off the main thread, the main thread still -receives quite a bit of load from processing all of these queued tasks. - -Additionally, resizing and managing the pending entries for all of -these asynchronous tasks takes up time on the main thread too. - -This commit replaces the implementation of the scheduler when working -with asynchronous tasks, by forwarding calls to the new scheduler. - -The Async Scheduler uses a single thread executor for "management" tasks. -The Management Thread is responsible for all adding and dispatching of -scheduled tasks. - -The mainThreadHeartbeat will send a heartbeat task to the management thread -with the currentTick value, so that it can find which tasks to execute. - -Scheduling of an async tasks also dispatches a management task, ensuring -that any Queue resizing operation occurs off of the main thread. - -The async queue uses a complete separate PriorityQueue, ensuring that resize -operations are decoupled from the sync tasks queue. - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3c1992e212a6d6f1db4d5b807b38d71913619fc0 ---- /dev/null -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java -@@ -0,0 +1,122 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+package org.bukkit.craftbukkit.scheduler; -+ -+import com.destroystokyo.paper.ServerSchedulerReportingWrapper; -+import com.google.common.util.concurrent.ThreadFactoryBuilder; -+import org.bukkit.plugin.Plugin; -+ -+import java.util.ArrayList; -+import java.util.Iterator; -+import java.util.List; -+import java.util.concurrent.Executor; -+import java.util.concurrent.Executors; -+import java.util.concurrent.SynchronousQueue; -+import java.util.concurrent.ThreadPoolExecutor; -+import java.util.concurrent.TimeUnit; -+ -+public class CraftAsyncScheduler extends CraftScheduler { -+ -+ private final ThreadPoolExecutor executor = new ThreadPoolExecutor( -+ 4, Integer.MAX_VALUE,30L, TimeUnit.SECONDS, new SynchronousQueue<>(), -+ new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").build()); -+ private final Executor management = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder() -+ .setNameFormat("Craft Async Scheduler Management Thread").build()); -+ private final List temp = new ArrayList<>(); -+ -+ CraftAsyncScheduler() { -+ super(true); -+ executor.allowCoreThreadTimeOut(true); -+ executor.prestartAllCoreThreads(); -+ } -+ -+ @Override -+ public void cancelTask(int taskId) { -+ this.management.execute(() -> this.removeTask(taskId)); -+ } -+ -+ private synchronized void removeTask(int taskId) { -+ parsePending(); -+ this.pending.removeIf((task) -> { -+ if (task.getTaskId() == taskId) { -+ task.cancel0(); -+ return true; -+ } -+ return false; -+ }); -+ } -+ -+ @Override -+ public void mainThreadHeartbeat(int currentTick) { -+ this.currentTick = currentTick; -+ this.management.execute(() -> this.runTasks(currentTick)); -+ } -+ -+ private synchronized void runTasks(int currentTick) { -+ parsePending(); -+ while (!this.pending.isEmpty() && this.pending.peek().getNextRun() <= currentTick) { -+ CraftTask task = this.pending.remove(); -+ if (executeTask(task)) { -+ final long period = task.getPeriod(); -+ if (period > 0) { -+ task.setNextRun(currentTick + period); -+ temp.add(task); -+ } -+ } -+ parsePending(); -+ } -+ this.pending.addAll(temp); -+ temp.clear(); -+ } -+ -+ private boolean executeTask(CraftTask task) { -+ if (isValid(task)) { -+ this.runners.put(task.getTaskId(), task); -+ this.executor.execute(new ServerSchedulerReportingWrapper(task)); -+ return true; -+ } -+ return false; -+ } -+ -+ @Override -+ public synchronized void cancelTasks(Plugin plugin) { -+ parsePending(); -+ for (Iterator iterator = this.pending.iterator(); iterator.hasNext(); ) { -+ CraftTask task = iterator.next(); -+ if (task.getTaskId() != -1 && (plugin == null || task.getOwner().equals(plugin))) { -+ task.cancel0(); -+ iterator.remove(); -+ } -+ } -+ } -+ -+ /** -+ * Task is not cancelled -+ * @param runningTask -+ * @return -+ */ -+ static boolean isValid(CraftTask runningTask) { -+ return runningTask.getPeriod() >= CraftTask.NO_REPEATING; -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483ca3c7c2a8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -63,7 +63,7 @@ public class CraftScheduler implements BukkitScheduler { - /** - * Main thread logic only - */ -- private final PriorityQueue pending = new PriorityQueue(10, -+ final PriorityQueue pending = new PriorityQueue(10, // Paper - new Comparator() { - @Override - public int compare(final CraftTask o1, final CraftTask o2) { -@@ -80,12 +80,13 @@ public class CraftScheduler implements BukkitScheduler { - /** - * These are tasks that are currently active. It's provided for 'viewing' the current state. - */ -- private final ConcurrentHashMap runners = new ConcurrentHashMap(); -+ final ConcurrentHashMap runners = new ConcurrentHashMap(); // Paper - /** - * The sync task that is currently running on the main thread. - */ - private volatile CraftTask currentTask = null; -- private volatile int currentTick = -1; -+ // Paper start - Improved Async Task Scheduler -+ volatile int currentTick = -1;/* - private final Executor executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %d").build()); - private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) { - @Override -@@ -94,12 +95,31 @@ public class CraftScheduler implements BukkitScheduler { - } - }; - private CraftAsyncDebugger debugTail = debugHead; -+ -+ */ // Paper end - private static final int RECENT_TICKS; - - static { - RECENT_TICKS = 30; - } - -+ -+ // Paper start -+ private final CraftScheduler asyncScheduler; -+ private final boolean isAsyncScheduler; -+ public CraftScheduler() { -+ this(false); -+ } -+ -+ public CraftScheduler(boolean isAsync) { -+ this.isAsyncScheduler = isAsync; -+ if (isAsync) { -+ this.asyncScheduler = this; -+ } else { -+ this.asyncScheduler = new CraftAsyncScheduler(); -+ } -+ } -+ // Paper end - @Override - public int scheduleSyncDelayedTask(final Plugin plugin, final Runnable task) { - return this.scheduleSyncDelayedTask(plugin, task, 0L); -@@ -222,7 +242,7 @@ public class CraftScheduler implements BukkitScheduler { - } else if (period < CraftTask.NO_REPEATING) { - period = CraftTask.NO_REPEATING; - } -- return handle(new CraftAsyncTask(runners, plugin, runnable, nextId(), period), delay); -+ return handle(new CraftAsyncTask(this.asyncScheduler.runners, plugin, runnable, nextId(), period), delay); // Paper - } - - @Override -@@ -238,6 +258,11 @@ public class CraftScheduler implements BukkitScheduler { - if (taskId <= 0) { - return; - } -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ this.asyncScheduler.cancelTask(taskId); -+ } -+ // Paper end - CraftTask task = runners.get(taskId); - if (task != null) { - task.cancel0(); -@@ -280,6 +305,11 @@ public class CraftScheduler implements BukkitScheduler { - @Override - public void cancelTasks(final Plugin plugin) { - Validate.notNull(plugin, "Cannot cancel tasks of null plugin"); -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ this.asyncScheduler.cancelTasks(plugin); -+ } -+ // Paper end - final CraftTask task = new CraftTask( - new Runnable() { - @Override -@@ -319,6 +349,13 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public boolean isCurrentlyRunning(final int taskId) { -+ // Paper start -+ if (!isAsyncScheduler) { -+ if (this.asyncScheduler.isCurrentlyRunning(taskId)) { -+ return true; -+ } -+ } -+ // Paper end - final CraftTask task = runners.get(taskId); - if (task == null) { - return false; -@@ -337,6 +374,11 @@ public class CraftScheduler implements BukkitScheduler { - if (taskId <= 0) { - return false; - } -+ // Paper start -+ if (!this.isAsyncScheduler && this.asyncScheduler.isQueued(taskId)) { -+ return true; -+ } -+ // Paper end - for (CraftTask task = head.getNext(); task != null; task = task.getNext()) { - if (task.getTaskId() == taskId) { - return task.getPeriod() >= CraftTask.NO_REPEATING; // The task will run -@@ -348,6 +390,12 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public List getActiveWorkers() { -+ // Paper start -+ if (!isAsyncScheduler) { -+ //noinspection TailRecursion -+ return this.asyncScheduler.getActiveWorkers(); -+ } -+ // Paper end - final ArrayList workers = new ArrayList(); - for (final CraftTask taskObj : runners.values()) { - // Iterator will be a best-effort (may fail to grab very new values) if called from an async thread -@@ -385,6 +433,11 @@ public class CraftScheduler implements BukkitScheduler { - pending.add(task); - } - } -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ pending.addAll(this.asyncScheduler.getPendingTasks()); -+ } -+ // Paper end - return pending; - } - -@@ -392,6 +445,11 @@ public class CraftScheduler implements BukkitScheduler { - * This method is designed to never block or wait for locks; an immediate execution of all current tasks. - */ - public void mainThreadHeartbeat(final int currentTick) { -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ this.asyncScheduler.mainThreadHeartbeat(currentTick); -+ } -+ // Paper end - this.currentTick = currentTick; - final List temp = this.temp; - parsePending(); -@@ -431,7 +489,7 @@ public class CraftScheduler implements BukkitScheduler { - parsePending(); - } else { - //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper -- executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper -+ task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Paper"); // Paper - // We don't need to parse pending - // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) - } -@@ -450,7 +508,7 @@ public class CraftScheduler implements BukkitScheduler { - //debugHead = debugHead.getNextHead(currentTick); // Paper - } - -- private void addTask(final CraftTask task) { -+ protected void addTask(final CraftTask task) { - final AtomicReference tail = this.tail; - CraftTask tailTask = tail.get(); - while (!tail.compareAndSet(tailTask, task)) { -@@ -459,7 +517,13 @@ public class CraftScheduler implements BukkitScheduler { - tailTask.setNext(task); - } - -- private CraftTask handle(final CraftTask task, final long delay) { -+ protected CraftTask handle(final CraftTask task, final long delay) { // Paper -+ // Paper start -+ if (!this.isAsyncScheduler && !task.isSync()) { -+ this.asyncScheduler.handle(task, delay); -+ return task; -+ } -+ // Paper end - task.setNextRun(currentTick + delay); - addTask(task); - return task; -@@ -478,8 +542,8 @@ public class CraftScheduler implements BukkitScheduler { - return ids.incrementAndGet(); - } - -- private void parsePending() { -- MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); -+ void parsePending() { // Paper -+ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); // Paper - CraftTask head = this.head; - CraftTask task = head.getNext(); - CraftTask lastTask = head; -@@ -498,7 +562,7 @@ public class CraftScheduler implements BukkitScheduler { - task.setNext(null); - } - this.head = lastTask; -- MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); -+ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); // Paper - } - - private boolean isReady(final int currentTick) { diff --git a/Unmapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/Unmapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch deleted file mode 100644 index 9b4622cc44..0000000000 --- a/Unmapped-Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 18 Mar 2018 11:45:57 -0400 -Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent - -This will allow you to change the players name or skin on login. - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index f95f5a8b30f42c8f5b6cee3ef6adb1f4e09832dc..31d404c5343c33b9b64724c5ac40d0c52ad5af66 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -1,5 +1,7 @@ - package net.minecraft.server.network; - -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import com.mojang.authlib.GameProfile; - import com.mojang.authlib.exceptions.AuthenticationUnavailableException; - import java.math.BigInteger; -@@ -38,6 +40,7 @@ import org.apache.logging.log4j.Logger; - // CraftBukkit start - import net.minecraft.network.chat.ChatComponentText; - import io.papermc.paper.adventure.PaperAdventure; // Paper -+import org.bukkit.Bukkit; - import org.bukkit.craftbukkit.util.Waitable; - import org.bukkit.event.player.AsyncPlayerPreLoginEvent; - import org.bukkit.event.player.PlayerPreLoginEvent; -@@ -316,8 +319,16 @@ public class LoginListener implements PacketLoginInListener { - java.util.UUID uniqueId = i.getId(); - final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; - -- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); -+ // Paper start -+ PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); -+ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); - server.getPluginManager().callEvent(asyncEvent); -+ profile = asyncEvent.getPlayerProfile(); -+ profile.complete(); -+ i = CraftPlayerProfile.asAuthlibCopy(profile); -+ playerName = i.getName(); -+ uniqueId = i.getId(); -+ // Paper end - - if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { - final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); diff --git a/Unmapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch b/Unmapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch deleted file mode 100644 index 2fc79938cb..0000000000 --- a/Unmapped-Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 18 Mar 2018 12:29:48 -0400 -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/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 31d404c5343c33b9b64724c5ac40d0c52ad5af66..21e70a133278d85ecd65fec36a273ed4faabf6cc 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -56,7 +56,7 @@ public class LoginListener implements PacketLoginInListener { - public final NetworkManager networkManager; - private LoginListener.EnumProtocolState g; - private int h; -- private GameProfile i; -+ private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } private GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER - private final String j; - private SecretKey loginKey; - private EntityPlayer l; -@@ -320,12 +320,12 @@ public class LoginListener implements PacketLoginInListener { - final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; - - // Paper start -- PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); -+ PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); - AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); - server.getPluginManager().callEvent(asyncEvent); - profile = asyncEvent.getPlayerProfile(); -- profile.complete(); -- i = CraftPlayerProfile.asAuthlibCopy(profile); -+ profile.complete(true); -+ setGameProfile(CraftPlayerProfile.asAuthlib(profile)); - playerName = i.getName(); - uniqueId = i.getId(); - // Paper end -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 18b0020d184e46c8957e82100681c8c66b1c3b62..41dd46c6ef95f7dc41d9ca36a5f0b85f5608fdeb 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -162,7 +162,7 @@ public abstract class EntityHuman extends EntityLiving { - protected int bG; - protected final float bH = 0.02F; - private int g; -- private final GameProfile bJ; -+ private GameProfile bJ; public final void setProfile(final GameProfile profile) { this.bJ = profile; } // Paper - OBFHELPER - private ItemStack bL; - private final ItemCooldown bM; - @Nullable -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index e00b33493208865c0bd1bd11a96dd2ed1348da7c..e1d1aaa278287214e2edac5f690d4f5257696ed0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -70,6 +70,7 @@ import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.item.enchantment.Enchantments; - import net.minecraft.world.level.EnumGamemode; -+import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.saveddata.maps.MapIcon; - import net.minecraft.world.phys.Vec3D; -@@ -1310,8 +1311,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - hiddenPlayers.put(player.getUniqueId(), hidingPlugins); - - // Remove this player from the hidden player's EntityTrackerEntry -- PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; -+ // Paper start - EntityPlayer other = ((CraftPlayer) player).getHandle(); -+ unregisterPlayer(other); -+ } -+ private void unregisterPlayer(EntityPlayer other) { -+ PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; -+ // Paper end - PlayerChunkMap.EntityTracker entry = tracker.trackedEntities.get(other.getId()); - if (entry != null) { - entry.clear(getHandle()); -@@ -1352,8 +1358,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - hiddenPlayers.remove(player.getUniqueId()); - -- PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; -+ // Paper start - EntityPlayer other = ((CraftPlayer) player).getHandle(); -+ registerPlayer(other); -+ } -+ private void registerPlayer(EntityPlayer other) { -+ PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; -+ // Paper end - - getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, other)); - -@@ -1362,6 +1373,50 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - entry.updatePlayer(getHandle()); - } - } -+ // Paper start -+ private void reregisterPlayer(EntityPlayer player) { -+ if (!hiddenPlayers.containsKey(player.getUniqueID())) { -+ unregisterPlayer(player); -+ registerPlayer(player); -+ } -+ } -+ public void setPlayerProfile(com.destroystokyo.paper.profile.PlayerProfile profile) { -+ EntityPlayer self = getHandle(); -+ self.setProfile(com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile)); -+ if (!self.sentListPacket) { -+ return; -+ } -+ List players = server.getServer().getPlayerList().players; -+ for (EntityPlayer player : players) { -+ player.getBukkitEntity().reregisterPlayer(self); -+ } -+ refreshPlayer(); -+ } -+ public com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile() { -+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(this).clone(); -+ } -+ -+ private void refreshPlayer() { -+ EntityPlayer handle = getHandle(); -+ -+ Location loc = getLocation(); -+ -+ PlayerConnection connection = handle.playerConnection; -+ reregisterPlayer(handle); -+ -+ //Respawn the player then update their position and selected slot -+ WorldServer worldserver = handle.getWorldServer(); -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutRespawn(worldserver.getDimensionManager(), worldserver.getDimensionKey(), BiomeManager.a(worldserver.getSeed()), handle.playerInteractManager.getGameMode(), handle.playerInteractManager.c(), worldserver.isDebugWorld(), worldserver.isFlatWorld(), true)); -+ handle.updateAbilities(); -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutPosition(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), new HashSet<>(), 0)); -+ net.minecraft.server.MinecraftServer.getServer().getPlayerList().updateClient(handle); -+ -+ if (this.isOp()) { -+ this.setOp(false); -+ this.setOp(true); -+ } -+ } -+ // Paper end - - public void removeDisconnectingPlayer(Player player) { - hiddenPlayers.remove(player.getUniqueId()); diff --git a/Unmapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch b/Unmapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch deleted file mode 100644 index 1ec120745b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Mar 2018 20:52:07 -0400 -Subject: [PATCH] Fix Dragon Server Crashes - -If the dragon tries to find "ground" and hits a hole, or off edge, -it will infinitely keep looking for non air and eventually crash. - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -index fbecb61b8c511fc7daa21690b2a653254be74246..5adbd9fe858aad9c775a10254eb53b34719a9bd6 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -@@ -63,7 +63,7 @@ public class DragonControllerLandedFlame extends AbstractDragonControllerLanded - double d3 = d2; - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(d0, d2, d1); - -- while (this.a.world.isEmpty(blockposition_mutableblockposition)) { -+ while (this.a.world.isEmpty(blockposition_mutableblockposition ) && d2 > 0) { // Paper - --d3; - if (d3 < 0.0D) { - d3 = d2; diff --git a/Unmapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch b/Unmapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch deleted file mode 100644 index c89810dd72..0000000000 --- a/Unmapped-Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 22 Mar 2018 01:40:24 -0400 -Subject: [PATCH] getPlayerUniqueId API - -Gets the unique ID of the player currently known as the specified player name -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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 3aed540b6359df9940a26901c55f0306743ad085..47443fae011fb8cdf18c38e6c4b443b874bd26e4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1518,6 +1518,25 @@ public final class CraftServer implements Server { - return recipients.size(); - } - -+ // Paper start -+ @Nullable -+ public UUID getPlayerUniqueId(String name) { -+ Player player = Bukkit.getPlayerExact(name); -+ if (player != null) { -+ return player.getUniqueId(); -+ } -+ GameProfile profile; -+ // Only fetch an online UUID in online mode -+ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) { -+ profile = console.getUserCache().getProfile( name ); -+ } else { -+ // Make an OfflinePlayer using an offline mode UUID since the name has no profile -+ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); -+ } -+ return profile != null ? profile.getId() : null; -+ } -+ // Paper end -+ - @Override - @Deprecated - public OfflinePlayer getOfflinePlayer(String name) { diff --git a/Unmapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch b/Unmapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch deleted file mode 100644 index 7a7b4d1993..0000000000 --- a/Unmapped-Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Mon, 26 Mar 2018 18:30:53 +0300 -Subject: [PATCH] Make player data saving configurable - -Upstream has added a patch which negates the need for this patch, -however, we should still migrate our configuration back upstream, -to prevent unexpected situations - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 52954fc3bf932cfc9d5ce63e3d3cace351305790..05a5abb951abe37f30a719cb75376d2d43c0d252 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -279,4 +279,13 @@ public class PaperConfig { - private static void authenticationServersDownKickMessage() { - authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); - } -+ -+ private static void savePlayerData() { -+ Object val = config.get("settings.save-player-data"); -+ if (val instanceof Boolean) { -+ SpigotConfig.disablePlayerDataSaving = !(Boolean) val; -+ SpigotConfig.config.set("players.disable-saving", SpigotConfig.disableAdvancementSaving); -+ SpigotConfig.save(); -+ } -+ } - } diff --git a/Unmapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch b/Unmapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch deleted file mode 100644 index a437521ba2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 18:22:50 +0200 -Subject: [PATCH] Make legacy ping handler more reliable - -The Minecraft server often fails to respond to old ("legacy") pings -from old Minecraft versions using the protocol used before the switch -to Netty in Minecraft 1.7. - -Due to packet fragmentation[1], we might not have all needed bytes -available when the LegacyPingHandler is called. In this case, it will -run into an error, remove the handler and continue using the modern -protocol. - -This is unlikely to happen for the first two revisions of the legacy -ping protocol (used in Minecraft 1.5.x and older) since the request -consists of only one or two bytes, but happens frequently for the -last/third revision introduced in Minecraft 1.6. - -It has much larger, variable packet sizes due to the inclusion of -the virtual host (the hostname/port used to connect to the server). - -The solution[2] is simple: If we find more than two matching bytes, -we buffer the remaining bytes until we have enough to fully read and -respond to the request. - -[1]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h3-11 -[2]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h4-13 - -diff --git a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -index e0edebf3eb93c11de2ed5c9013565950b4ad2375..0286d30b63e42224028b343315e1d1a9db2fe3d1 100644 ---- a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -+++ b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -@@ -15,6 +15,7 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - - private static final Logger LOGGER = LogManager.getLogger(); - private final ServerConnection b; -+ private ByteBuf buf; // Paper - - public LegacyPingHandler(ServerConnection serverconnection) { - this.b = serverconnection; -@@ -23,6 +24,16 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) throws Exception { - ByteBuf bytebuf = (ByteBuf) object; - -+ // Paper start - Make legacy ping handler more reliable -+ if (this.buf != null) { -+ try { -+ readLegacy1_6(channelhandlercontext, bytebuf); -+ } finally { -+ bytebuf.release(); -+ } -+ return; -+ } -+ // Paper end - bytebuf.markReaderIndex(); - boolean flag = true; - -@@ -53,6 +64,10 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - this.a(channelhandlercontext, this.a(s)); - break; - default: -+ // Paper start - Replace with improved version below -+ if (bytebuf.readUnsignedByte() != 0x01 || bytebuf.readUnsignedByte() != 0xFA) return; -+ readLegacy1_6(channelhandlercontext, bytebuf); -+ /* - boolean flag1 = bytebuf.readUnsignedByte() == 1; - - flag1 &= bytebuf.readUnsignedByte() == 250; -@@ -76,6 +91,7 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - } finally { - bytebuf1.release(); - } -+ */ // Paper end - Replace with improved version below - } - - bytebuf.release(); -@@ -93,6 +109,90 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - - } - -+ // Paper start -+ private static String readLegacyString(ByteBuf buf) { -+ int size = buf.readShort() * Character.BYTES; -+ if (!buf.isReadable(size)) { -+ return null; -+ } -+ -+ String result = buf.toString(buf.readerIndex(), size, StandardCharsets.UTF_16BE); -+ buf.skipBytes(size); // toString doesn't increase readerIndex automatically -+ return result; -+ } -+ -+ private void readLegacy1_6(ChannelHandlerContext ctx, ByteBuf part) { -+ ByteBuf buf = this.buf; -+ -+ if (buf == null) { -+ this.buf = buf = ctx.alloc().buffer(); -+ buf.markReaderIndex(); -+ } else { -+ buf.resetReaderIndex(); -+ } -+ -+ buf.writeBytes(part); -+ -+ if (!buf.isReadable(Short.BYTES + Short.BYTES + Byte.BYTES + Short.BYTES + Integer.BYTES)) { -+ return; -+ } -+ -+ String s = readLegacyString(buf); -+ if (s == null) { -+ return; -+ } -+ -+ if (!s.equals("MC|PingHost")) { -+ removeHandler(ctx); -+ return; -+ } -+ -+ if (!buf.isReadable(Short.BYTES) || !buf.isReadable(buf.readShort())) { -+ return; -+ } -+ -+ MinecraftServer server = this.b.d(); -+ int protocolVersion = buf.readByte(); -+ String host = readLegacyString(buf); -+ if (host == null) { -+ removeHandler(ctx); -+ return; -+ } -+ int port = buf.readInt(); -+ -+ if (buf.isReadable()) { -+ removeHandler(ctx); -+ return; -+ } -+ -+ buf.release(); -+ this.buf = null; -+ -+ LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); -+ -+ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", -+ Byte.MAX_VALUE, server.getVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); -+ this.a(ctx, this.a(response)); -+ } -+ -+ private void removeHandler(ChannelHandlerContext ctx) { -+ ByteBuf buf = this.buf; -+ this.buf = null; -+ -+ buf.resetReaderIndex(); -+ ctx.pipeline().remove(this); -+ ctx.fireChannelRead(buf); -+ } -+ -+ @Override -+ public void handlerRemoved(ChannelHandlerContext ctx) { -+ if (this.buf != null) { -+ this.buf.release(); -+ this.buf = null; -+ } -+ } -+ // Paper end -+ - private void a(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf) { - channelhandlercontext.pipeline().firstContext().writeAndFlush(bytebuf).addListener(ChannelFutureListener.CLOSE); - } diff --git a/Unmapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch b/Unmapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch deleted file mode 100644 index 9274b7f30a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch +++ /dev/null @@ -1,154 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 19:30:51 +0200 -Subject: [PATCH] Call PaperServerListPingEvent for legacy pings - - -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..74c012fd40491f1d870fbc1aa8c318a2197eb106 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java -@@ -0,0 +1,73 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+import net.minecraft.server.MinecraftServer; -+import org.apache.commons.lang3.StringUtils; -+import org.bukkit.ChatColor; -+ -+import java.net.InetSocketAddress; -+ -+import javax.annotation.Nullable; -+ -+public final class PaperLegacyStatusClient implements StatusClient { -+ -+ private final InetSocketAddress address; -+ private final int protocolVersion; -+ @Nullable private final InetSocketAddress virtualHost; -+ -+ private PaperLegacyStatusClient(InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { -+ this.address = address; -+ this.protocolVersion = protocolVersion; -+ this.virtualHost = virtualHost; -+ } -+ -+ @Override -+ public InetSocketAddress getAddress() { -+ return this.address; -+ } -+ -+ @Override -+ public int getProtocolVersion() { -+ return this.protocolVersion; -+ } -+ -+ @Nullable -+ @Override -+ public InetSocketAddress getVirtualHost() { -+ return this.virtualHost; -+ } -+ -+ @Override -+ public boolean isLegacy() { -+ return true; -+ } -+ -+ public static PaperServerListPingEvent processRequest(MinecraftServer server, -+ InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { -+ -+ PaperServerListPingEvent event = new PaperServerListPingEventImpl(server, -+ new PaperLegacyStatusClient(address, protocolVersion, virtualHost), Byte.MAX_VALUE, null); -+ server.server.getPluginManager().callEvent(event); -+ -+ if (event.isCancelled()) { -+ return null; -+ } -+ -+ return event; -+ } -+ -+ public static String getMotd(PaperServerListPingEvent event) { -+ return getFirstLine(event.getMotd()); -+ } -+ -+ public static String getUnformattedMotd(PaperServerListPingEvent event) { -+ // Strip color codes and all other occurrences of the color char (because it's used as delimiter) -+ return getFirstLine(StringUtils.remove(ChatColor.stripColor(event.getMotd()), ChatColor.COLOR_CHAR)); -+ } -+ -+ private static String getFirstLine(String s) { -+ int pos = s.indexOf('\n'); -+ return pos >= 0 ? s.substring(0, pos) : s; -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -index 0286d30b63e42224028b343315e1d1a9db2fe3d1..765dea6653b450802d45b76c7d2ac3d5778da9df 100644 ---- a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -+++ b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -@@ -1,5 +1,7 @@ - package net.minecraft.server.network; - -+import com.destroystokyo.paper.network.PaperLegacyStatusClient; -+ - import io.netty.buffer.ByteBuf; - import io.netty.buffer.Unpooled; - import io.netty.channel.ChannelFutureListener; -@@ -46,12 +48,19 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - MinecraftServer minecraftserver = this.b.d(); - int i = bytebuf.readableBytes(); - String s; -- org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit -+ //org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit // Paper -+ com.destroystokyo.paper.event.server.PaperServerListPingEvent event; // Paper - - switch (i) { - case 0: - LegacyPingHandler.LOGGER.debug("Ping: (<1.3.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); -- s = String.format("%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit -+ // Paper start - Call PaperServerListPingEvent and use results -+ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 39, null); -+ if (event == null) { -+ channelhandlercontext.close(); -+ break; -+ } -+ s = String.format("%s\u00a7%d\u00a7%d", PaperLegacyStatusClient.getUnformattedMotd(event), event.getNumPlayers(), event.getMaxPlayers()); - this.a(channelhandlercontext, this.a(s)); - break; - case 1: -@@ -60,7 +69,14 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - } - - LegacyPingHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); -- s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit -+ // Paper start - Call PaperServerListPingEvent and use results -+ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 127, null); // Paper -+ if (event == null) { -+ channelhandlercontext.close(); -+ break; -+ } -+ s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", new Object[] { event.getProtocolVersion(), minecraftserver.getVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()}); // CraftBukkit -+ // Paper end - this.a(channelhandlercontext, this.a(s)); - break; - default: -@@ -170,8 +186,16 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - - LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); - -- String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", -- Byte.MAX_VALUE, server.getVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); -+ InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port); -+ com.destroystokyo.paper.event.server.PaperServerListPingEvent event = PaperLegacyStatusClient.processRequest( -+ server, (InetSocketAddress) ctx.channel().remoteAddress(), protocolVersion, virtualHost); -+ if (event == null) { -+ ctx.close(); -+ return; -+ } -+ -+ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", event.getProtocolVersion(), event.getVersion(), -+ PaperLegacyStatusClient.getMotd(event), event.getNumPlayers(), event.getMaxPlayers()); - this.a(ctx, this.a(response)); - } - diff --git a/Unmapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch b/Unmapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch deleted file mode 100644 index 96390756fc..0000000000 --- a/Unmapped-Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 31 Mar 2018 17:04:26 +0100 -Subject: [PATCH] Flag to disable the channel limit - -In some enviroments, the channel limit set by spigot can cause issues, -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 e1d1aaa278287214e2edac5f690d4f5257696ed0..2abd5157b0964fc02994ca7a9317d2fb5539dc1c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -146,6 +146,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - // Paper start - private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; - private String resourcePackHash; -+ private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit - // Paper end - - public CraftPlayer(CraftServer server, EntityPlayer entity) { -@@ -1579,7 +1580,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void addChannel(String channel) { -- Preconditions.checkState(channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); -+ Preconditions.checkState(DISABLE_CHANNEL_LIMIT || channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); // Paper - flag to disable channel limit - channel = StandardMessenger.validateAndCorrectChannel(channel); - if (channels.add(channel)) { - server.getPluginManager().callEvent(new PlayerRegisterChannelEvent(this, channel)); diff --git a/Unmapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch b/Unmapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch deleted file mode 100644 index 857ab9d50a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 1 Apr 2018 02:29:37 +0300 -Subject: [PATCH] Add method to open already placed sign - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 893cea754ea1858d2b08ba377bbbc90e7c0efd6d..1333d425147e6dc7f21f755a9b25ead9723d4a28 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -29,6 +29,7 @@ import net.minecraft.world.level.block.BlockEnchantmentTable; - import net.minecraft.world.level.block.BlockWorkbench; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.TileEntity; -+import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.block.state.IBlockData; - import org.bukkit.GameMode; - import org.bukkit.Location; -@@ -605,6 +606,17 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - } - } - -+ // Paper start - Add method to open already placed sign -+ @Override -+ public void openSign(org.bukkit.block.Sign sign) { -+ org.apache.commons.lang.Validate.isTrue(sign.getWorld().equals(this.getWorld()), "Sign must be in the same world as player is in"); -+ org.bukkit.craftbukkit.block.CraftSign craftSign = (org.bukkit.craftbukkit.block.CraftSign) sign; -+ TileEntitySign teSign = craftSign.getTileEntity(); -+ // Make sign editable temporarily, will be set back to false in PlayerConnection later -+ teSign.isEditable = true; -+ getHandle().openSign(teSign); -+ } -+ // Paper end - @Override - public boolean dropItem(boolean dropAll) { - return getHandle().dropItem(dropAll); diff --git a/Unmapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch b/Unmapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch deleted file mode 100644 index 99fb21f6e5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Sat, 14 Apr 2018 20:20:46 +0200 -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/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 48f0385c7203c7955de5a015f3dc42be2ab7b681..cebf1a623a9bec72d60fdd23dda01868ef6431d4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -358,4 +358,9 @@ public class PaperWorldConfig { - private void squidMaxSpawnHeight() { - squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); - } -+ -+ public boolean disableSprintInterruptionOnAttack; -+ private void disableSprintInterruptionOnAttack() { -+ disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 41dd46c6ef95f7dc41d9ca36a5f0b85f5608fdeb..7839553662d7f1f378969d42fb7a560e489852f4 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1183,7 +1183,11 @@ public abstract class EntityHuman extends EntityLiving { - } - - this.setMot(this.getMot().d(0.6D, 1.0D, 0.6D)); -- this.setSprinting(false); -+ // Paper start - Configuration option to disable automatic sprint interruption -+ if (!world.paperConfig.disableSprintInterruptionOnAttack) { -+ this.setSprinting(false); -+ } -+ // Paper end - } - - if (flag3) { diff --git a/Unmapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/Unmapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch deleted file mode 100644 index a63e823a9b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: 0x22 <0x22@futureclient.net> -Date: Thu, 26 Apr 2018 04:41:11 -0400 -Subject: [PATCH] Fix exploit that allowed colored signs to be created - - -diff --git a/src/main/java/net/minecraft/SharedConstants.java b/src/main/java/net/minecraft/SharedConstants.java -index b92975aa85fd79c70d6bec014284e8f55d0d3a4b..d5d6c545182b9b0b6aa5e52f1f9858450a17038e 100644 ---- a/src/main/java/net/minecraft/SharedConstants.java -+++ b/src/main/java/net/minecraft/SharedConstants.java -@@ -20,6 +20,7 @@ public class SharedConstants { - return c0 != 167 && c0 >= ' ' && c0 != 127; - } - -+ public static String filterAllowedChatCharacters(String input) { return a(input); } // Paper - OBFHELPER - public static String a(String s) { - StringBuilder stringbuilder = new StringBuilder(); - char[] achar = s.toCharArray(); -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 1860def3971d1e17429bdde51c2bc336887da233..6c5966901ffdc3c7f9950ff8b40fbf2489acbd4b 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2788,7 +2788,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines.add(net.kyori.adventure.text.Component.text(list.get(i))); -+ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. - } - SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.server.getPluginManager().callEvent(event); diff --git a/Unmapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch b/Unmapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch deleted file mode 100644 index 428f29678a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0209-EndermanEscapeEvent.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 13:15:55 -0400 -Subject: [PATCH] EndermanEscapeEvent - -Fires an event anytime an enderman intends to teleport away from the player - -You may cancel this, enabling ranged attacks to damage the enderman for example. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index 2de3210bd8988b156b756723d0f781fd92bc151a..b889c1954df39b6180351c418393f5c772702589 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster; - - import java.util.EnumSet; - import java.util.Optional; -+import com.destroystokyo.paper.event.entity.EndermanEscapeEvent; // Paper - import java.util.Random; - import java.util.UUID; - import java.util.function.Predicate; -@@ -109,6 +110,12 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - setGoalTarget(entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, true); - } - -+ // Paper start -+ private boolean tryEscape(EndermanEscapeEvent.Reason reason) { -+ return new EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent(); -+ } -+ // Paper end -+ - @Override - public boolean setGoalTarget(EntityLiving entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { - if (!super.setGoalTarget(entityliving, reason, fireEvent)) { -@@ -262,7 +269,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - if (this.world.isDay() && this.ticksLived >= this.bs + 600) { - float f = this.aR(); - -- if (f > 0.5F && this.world.e(this.getChunkCoordinates()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) { -+ if (f > 0.5F && this.world.e(this.getChunkCoordinates()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper - this.setGoalTarget((EntityLiving) null); - this.eL(); - } -@@ -360,17 +367,19 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - if (this.isInvulnerable(damagesource)) { - return false; - } else if (damagesource instanceof EntityDamageSourceIndirect) { -+ if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start - for (int i = 0; i < 64; ++i) { - if (this.eL()) { - return true; - } - } -+ } // Paper end - - return false; - } else { - boolean flag = super.damageEntity(damagesource, f); - -- if (!this.world.s_() && !(damagesource.getEntity() instanceof EntityLiving) && this.random.nextInt(10) != 0) { -+ if (!this.world.s_() && !(damagesource.getEntity() instanceof EntityLiving) && this.random.nextInt(10) != 0 && this.tryEscape(damagesource == DamageSource.DROWN ? EndermanEscapeEvent.Reason.DROWN : EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - use to be critical hits as else, but mojang removed critical hits in 1.16.2 due to MC-185684 - this.eL(); - } - -@@ -515,7 +524,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - - static class PathfinderGoalPlayerWhoLookedAtTarget extends PathfinderGoalNearestAttackableTarget { - -- private final EntityEnderman i; -+ private final EntityEnderman i; public final EntityEnderman getEnderman() { return this.i; } // Paper - OBFHELPER - private EntityHuman j; - private int k; - private int l; -@@ -578,7 +587,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - } else { - if (this.c != null && !this.i.isPassenger()) { - if (this.i.g((EntityHuman) this.c)) { -- if (this.c.h((Entity) this.i) < 16.0D) { -+ if (this.c.h((Entity) this.i) < 16.0D && this.getEnderman().tryEscape(EndermanEscapeEvent.Reason.STARE)) { // Paper - this.i.eL(); - } - diff --git a/Unmapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch b/Unmapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch deleted file mode 100644 index b64598e139..0000000000 --- a/Unmapped-Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 13:29:44 -0400 -Subject: [PATCH] Enderman.teleportRandomly() - -Ability to trigger the vanilla "teleport randomly" mechanic of an enderman. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index b889c1954df39b6180351c418393f5c772702589..ef2f0211cd4d20dad0d3757c38c3c2882e99b2f2 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -278,6 +278,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - super.mobTick(); - } - -+ public final boolean teleportRandomly() { return this.eL(); } // Paper - OBFHELPER - protected boolean eL() { - if (!this.world.s_() && this.isAlive()) { - double d0 = this.locX() + (this.random.nextDouble() - 0.5D) * 64.0D; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -index 8894d619796c7b81acde9ff27d0f9191122eade4..f54175a4b13ddedc475ef028942edb08eb4ff631 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -@@ -16,6 +16,7 @@ public class CraftEnderman extends CraftMonster implements Enderman { - super(server, entity); - } - -+ @Override public boolean teleportRandomly() { return getHandle().teleportRandomly(); } // Paper - @Override - public MaterialData getCarriedMaterial() { - IBlockData blockData = getHandle().getCarried(); diff --git a/Unmapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch b/Unmapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch deleted file mode 100644 index 38fdf2a105..0000000000 --- a/Unmapped-Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 17:15:26 -0400 -Subject: [PATCH] Block Enderpearl Travel Exploit - -Players are able to use alt accounts and enderpearls to travel -long distances utilizing the pearls in unloaded chunks and loading -the chunk later when convenient. - -This disables that by not saving the thrower when the chunk is unloaded. - -This is mainly useful for survival servers that do not allow freeform teleporting. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index cebf1a623a9bec72d60fdd23dda01868ef6431d4..e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -363,4 +363,10 @@ public class PaperWorldConfig { - private void disableSprintInterruptionOnAttack() { - disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); - } -+ -+ public boolean disableEnderpearlExploit = true; -+ private void disableEnderpearlExploit() { -+ disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); -+ log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index 5c9ffd02b4f2977ee13a962a214887f74c91594f..8f14e1ebefe172e056a04bd7b6f55b9bbb1e7b2e 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -63,6 +63,7 @@ public abstract class IProjectile extends Entity { - protected void loadData(NBTTagCompound nbttagcompound) { - if (nbttagcompound.b("Owner")) { - this.shooter = nbttagcompound.a("Owner"); -+ if (this instanceof EntityEnderPearl && this.world != null && this.world.paperConfig.disableEnderpearlExploit) { this.shooter = null; } // Paper - Don't store shooter name for pearls to block enderpearl travel exploit - } - - this.d = nbttagcompound.getBoolean("LeftOwner"); diff --git a/Unmapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch b/Unmapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch deleted file mode 100644 index da5eceecb8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 15 Aug 2017 22:29:12 -0400 -Subject: [PATCH] Expand World.spawnParticle API and add Builder - -Adds ability to control who receives it and who is the source/sender (vanish API) -the standard API is to send the packet to everyone in the world, which is ineffecient. -Adds an option to control the force mode of the particle. - -This adds a new Builder API which is much friendlier to use. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 744ec6f09a1b3ccdf0d74fe50f1e1c913ee2df86..b73315df7dae243dd76e44d586dfc1d8f9017a56 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -170,7 +170,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final Int2ObjectMap entitiesById = new Int2ObjectLinkedOpenHashMap(); - private final Map entitiesByUUID = Maps.newHashMap(); - private final Queue entitiesToAdd = Queues.newArrayDeque(); -- private final List players = Lists.newArrayList(); -+ public final List players = Lists.newArrayList(); // Paper - private -> public - public final ChunkProviderServer chunkProvider; // Paper - public - boolean tickingEntities; - private final MinecraftServer server; -@@ -1478,12 +1478,17 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - public int sendParticles(EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { -+ // Paper start - Particle API Expansion -+ return sendParticles(players, sender, t0, d0, d1, d2, i, d3, d4, d5, d6, force); -+ } -+ public int sendParticles(List receivers, EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { -+ // Paper end - PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); - // CraftBukkit end - int j = 0; - -- for (int k = 0; k < this.players.size(); ++k) { -- EntityPlayer entityplayer = (EntityPlayer) this.players.get(k); -+ for (EntityHuman entityhuman : receivers) { // Paper - Particle API Expansion -+ EntityPlayer entityplayer = (EntityPlayer) entityhuman; // Paper - Particle API Expansion - if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit - - if (this.a(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index d7d58a0feac2d0b4303c625b7952103613e8c33e..13d3b6accfb86383660a7d0e991519fd930bd518 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2352,11 +2352,17 @@ public class CraftWorld implements World { - - @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) { -+ // Paper start - Particle API Expansion -+ spawnParticle(particle, null, null, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, force); -+ } -+ public void spawnParticle(Particle particle, List receivers, Player sender, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) { -+ // Paper end - if (data != null && !particle.getDataType().isInstance(data)) { - throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); - } - getHandle().sendParticles( -- null, // Sender -+ receivers == null ? getHandle().players : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API Expansion -+ sender != null ? ((CraftPlayer) sender).getHandle() : null, // Sender // Paper - Particle API Expansion - CraftParticle.toNMS(particle, data), // Particle - x, y, z, // Position - count, // Count diff --git a/Unmapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch b/Unmapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch deleted file mode 100644 index 08c3406719..0000000000 --- a/Unmapped-Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 May 2018 20:18:54 -0400 -Subject: [PATCH] EndermanAttackPlayerEvent - -Allow control over whether or not an enderman aggros a player. - -This allows you to override/extend the pumpkin/stare logic. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index ef2f0211cd4d20dad0d3757c38c3c2882e99b2f2..aa6cb15637144c9d8db1b1861e58f3f02d68357a 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -221,7 +221,15 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - this.a((WorldServer) this.world, nbttagcompound); - } - -+ // Paper start - OBFHELPER - ok not really, but verify this on updates - private boolean g(EntityHuman entityhuman) { -+ boolean shouldAttack = g_real(entityhuman); -+ com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) entityhuman.getBukkitEntity()); -+ event.setCancelled(!shouldAttack); -+ return event.callEvent(); -+ } -+ private boolean g_real(EntityHuman entityhuman) { -+ // Paper end - ItemStack itemstack = (ItemStack) entityhuman.inventory.armor.get(3); - - if (itemstack.getItem() == Blocks.CARVED_PUMPKIN.getItem()) { diff --git a/Unmapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch b/Unmapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch deleted file mode 100644 index 4c85394244..0000000000 --- a/Unmapped-Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 16 May 2018 20:35:16 -0400 -Subject: [PATCH] WitchConsumePotionEvent - -Fires when a witch consumes the potion in their hand - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index 814ef118e983ee6807108b2e07cd9b35ef9dae15..0bfdcbe4a792e8243de86ded6c64d930ec6e4de8 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -124,7 +124,11 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - - this.setSlot(EnumItemSlot.MAINHAND, ItemStack.b); - if (itemstack.getItem() == Items.POTION) { -- List list = PotionUtil.getEffects(itemstack); -+ // Paper start -+ com.destroystokyo.paper.event.entity.WitchConsumePotionEvent event = new com.destroystokyo.paper.event.entity.WitchConsumePotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); -+ -+ List list = event.callEvent() ? PotionUtil.getEffects(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion())) : null; -+ // Paper end - - if (list != null) { - Iterator iterator = list.iterator(); diff --git a/Unmapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch b/Unmapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch deleted file mode 100644 index a9232360d4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 16 May 2018 20:44:58 -0400 -Subject: [PATCH] WitchThrowPotionEvent - -Fired when a witch throws a potion at a player - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index 0bfdcbe4a792e8243de86ded6c64d930ec6e4de8..2e65f6107ffecfe00c9c09baa60dec3021aac527 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -224,9 +224,16 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - potionregistry = Potions.WEAKNESS; - } - -+ // Paper start -+ ItemStack potion = PotionUtil.a(new ItemStack(Items.SPLASH_POTION), potionregistry); -+ com.destroystokyo.paper.event.entity.WitchThrowPotionEvent event = new com.destroystokyo.paper.event.entity.WitchThrowPotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+ if (!event.callEvent()) { -+ return; -+ } -+ potion = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion()); - EntityPotion entitypotion = new EntityPotion(this.world, this); -- -- entitypotion.setItem(PotionUtil.a(new ItemStack(Items.SPLASH_POTION), potionregistry)); -+ entitypotion.setItem(potion); -+ // Paper end - entitypotion.pitch -= -20.0F; - entitypotion.shoot(d0, d1 + (double) (f1 * 0.2F), d2, 0.75F, 8.0F); - if (!this.isSilent()) { diff --git a/Unmapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/Unmapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch deleted file mode 100644 index e6991dda17..0000000000 --- a/Unmapped-Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 4 Jun 2018 20:39:20 -0400 -Subject: [PATCH] Allow spawning Item entities with World.spawnEntity - -This API has more capabilities than .dropItem with the Consumer function - -Item can be set inside of the Consumer pre spawn function. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 13d3b6accfb86383660a7d0e991519fd930bd518..2cc25177110d669e0f425668e26a38794c11c101 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1515,6 +1515,10 @@ public class CraftWorld implements World { - if (Boat.class.isAssignableFrom(clazz)) { - entity = new EntityBoat(world, x, y, z); - entity.setPositionRotation(x, y, z, yaw, pitch); -+ // Paper start -+ } else if (org.bukkit.entity.Item.class.isAssignableFrom(clazz)) { -+ entity = new EntityItem(world, x, y, z, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Item.getItemOf(net.minecraft.world.level.block.Blocks.DIRT))); -+ // Paper end - } else if (FallingBlock.class.isAssignableFrom(clazz)) { - entity = new EntityFallingBlock(world, x, y, z, world.getType(new BlockPosition(x, y, z))); - } else if (Projectile.class.isAssignableFrom(clazz)) { diff --git a/Unmapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch b/Unmapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch deleted file mode 100644 index 379b2c1751..0000000000 --- a/Unmapped-Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 22:47:26 -0400 -Subject: [PATCH] WitchReadyPotionEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index 2e65f6107ffecfe00c9c09baa60dec3021aac527..c6d79125e7dd982fc528ce61144005194cbaa323 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -157,7 +157,11 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - } - - if (potionregistry != null) { -- this.setSlot(EnumItemSlot.MAINHAND, PotionUtil.a(new ItemStack(Items.POTION), potionregistry)); -+ // Paper start -+ ItemStack potion = PotionUtil.a(new ItemStack(Items.POTION), potionregistry); -+ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+ this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+ // Paper end - this.bq = this.getItemInMainHand().k(); - this.v(true); - if (!this.isSilent()) { diff --git a/Unmapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch b/Unmapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch deleted file mode 100644 index e22c07338a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 23:00:29 -0400 -Subject: [PATCH] ItemStack#getMaxItemUseDuration - -Allows you to determine how long it takes to use a usable/consumable item - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index cac92ccacc9d5ff17c70ee266cf12bacce6242ea..2ac8b6ac38bdca26cddfb8652f13b0be0c4000fe 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -606,6 +606,7 @@ public final class ItemStack { - this.getItem().b(this, world, entityhuman); - } - -+ public int getItemUseMaxDuration() { return k(); } // Paper - OBFHELPER - public int k() { - return this.getItem().e_(this); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 7221ac52c9f66ae0af6f6cbf15c8d47f9c0291a0..315addab147dfecf4aa88d32d154cefe850d0a78 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -174,6 +174,13 @@ public final class CraftItemStack extends ItemStack { - return (handle == null) ? Material.AIR.getMaxStackSize() : handle.getItem().getMaxStackSize(); - } - -+ // Paper start -+ @Override -+ public int getMaxItemUseDuration() { -+ return handle == null ? 0 : handle.getItemUseMaxDuration(); -+ } -+ // Paper end -+ - @Override - public void addUnsafeEnchantment(Enchantment ench, int level) { - Validate.notNull(ench, "Cannot add null enchantment"); diff --git a/Unmapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch b/Unmapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch deleted file mode 100644 index 188e408423..0000000000 --- a/Unmapped-Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 9 Jun 2018 14:08:39 +0200 -Subject: [PATCH] Implement EntityTeleportEndGatewayEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -index 2808cd0b100bd65a730aba315ab47a59a4621b30..b7548d0b3938d95328fc86db4000190532eaa8f5 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -@@ -194,9 +194,20 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick - - } - // CraftBukkit end -+ // Paper start - EntityTeleportEndGatewayEvent - replicated from above -+ org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity = entity.getBukkitEntity(); -+ org.bukkit.Location location = new Location(world.getWorld(), (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); -+ location.setPitch(bukkitEntity.getLocation().getPitch()); -+ location.setYaw(bukkitEntity.getLocation().getYaw()); -+ -+ com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent event = new com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent(bukkitEntity, bukkitEntity.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(world, this.getPosition()).getBlock())); -+ if (!event.callEvent()) { -+ return; -+ } -+ // Paper end - - entity1.resetPortalCooldown(); -- entity1.enderTeleportAndLoad((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D); -+ entity1.enderTeleportAndLoad(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); // Paper - } - - this.h(); diff --git a/Unmapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/Unmapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch deleted file mode 100644 index 72ccc51e06..0000000000 --- a/Unmapped-Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 Jun 2018 01:18:49 -0400 -Subject: [PATCH] Unset Ignited flag on cancel of Explosion Event - -Otherwise the creeper infinite explodes - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -index 08292753f925f33d75f3aca835c1fd19494b22ec..cbb973e077e04e5221bcc837f434b7093bdbcc2a 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -@@ -48,7 +48,7 @@ public class EntityCreeper extends EntityMonster { - - private static final DataWatcherObject b = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.b); - private static final DataWatcherObject POWERED = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.i); -- private static final DataWatcherObject d = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.i); -+ private static final DataWatcherObject d = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.i); private static final DataWatcherObject isIgnitedDW = d; // Paper OBFHELPER - private int bo; - public int fuseTicks; // PAIL - public int maxFuseTicks = 30; -@@ -253,6 +253,7 @@ public class EntityCreeper extends EntityMonster { - this.createEffectCloud(); - } else { - fuseTicks = 0; -+ this.datawatcher.set(isIgnitedDW, Boolean.valueOf(false)); // Paper - } - // CraftBukkit end - } diff --git a/Unmapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch b/Unmapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch deleted file mode 100644 index bb0a09f3ce..0000000000 --- a/Unmapped-Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 Jun 2018 20:20:15 -0400 -Subject: [PATCH] Fix CraftEntity hashCode - -hashCodes are not allowed to change, however bukkit used a value -that does change, the entityId. - -When an entity is teleported dimensions, the entity reference is -replaced with a new one with a new entity ID. - -For hashCode, we can simply use the UUID's hashCode to keep -the hashCode from changing. - -equals() is ok to use getEntityId() because equals() should only -be true if both the left and right are the same reference. - -Since entity ids can not duplicate during runtime, this -check is essentially the same as this.getHandle() == other.getHandle() - -However, replaced it too to make it clearer of intent. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 4c2a35fb33da19a15a220dc5e0c9fa3233d657fb..3642b17cafffd2818ee7a18d26bc25645f596115 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -745,14 +745,15 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return false; - } - final CraftEntity other = (CraftEntity) obj; -- return (this.getEntityId() == other.getEntityId()); -+ return (this.getHandle() == other.getHandle()); // Paper - while logically the same, this is clearer - } - -+ // Paper - Fix hashCode. entity ID's are not static. -+ // A CraftEntity can change reference to a new entity with a new ID, and hash codes should never change - @Override - public int hashCode() { -- int hash = 7; -- hash = 29 * hash + this.getEntityId(); -- return hash; -+ return getUniqueId().hashCode(); -+ // Paper end - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch b/Unmapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch deleted file mode 100644 index e0ee8431f3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 15 Jun 2018 00:30:32 -0400 -Subject: [PATCH] Configurable Alternative LootPool Luck Formula - -Rewrites the Vanilla luck application formula so that luck can be -applied to items that do not have any quality defined. - -See: https://luckformula.emc.gs for data and details ------------ - -The rough summary is: -My goal was that in a pool, when luck was applied, the pool -rebalances so the percentages for bigger items is -lowered and smaller items is boosted. - -Do this by boosting and then reducing the weight value, -so that larger numbers are penalized more than smaller numbers. -resulting in a larger reduction of entries for more common -items than the reduction on small weights, -giving smaller weights more of a chance - ------------ - -This work kind of obsoletes quality, but quality would be useful -for 2 items with same weight that you want luck to impact -in varying directions. - -Fishing still falls into that as the weights are closer, so luck -will invalidate junk more. - -This change will result in some major changes to fishing formulas. - ------------ - -I would love to see this change in Vanilla, so Mojang please pull :) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 05a5abb951abe37f30a719cb75376d2d43c0d252..77a03abd59db4a43f6f2d59d4c7ef176e782f205 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -288,4 +288,12 @@ public class PaperConfig { - SpigotConfig.save(); - } - } -+ -+ public static boolean useAlternativeLuckFormula = false; -+ private static void useAlternativeLuckFormula() { -+ useAlternativeLuckFormula = getBoolean("settings.use-alternative-luck-formula", false); -+ if (useAlternativeLuckFormula) { -+ Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -index ceb9a1e1b1d55a0a8cd74189450f356b9ad4c46c..632002c4db01ca3f3c19aa583226cf36f17afe7f 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -@@ -20,8 +20,8 @@ import org.apache.commons.lang3.ArrayUtils; - - public abstract class LootSelectorEntry extends LootEntryAbstract { - -- protected final int c; -- protected final int e; -+ protected final int c; public int getWeight() { return c; } // Paper - OBFHELPER -+ protected final int e; public int getQuality() { return e; } // Paper - OBFHELPER - protected final LootItemFunction[] f; - private final BiFunction g; - private final LootEntry h = new LootSelectorEntry.c() { -@@ -152,11 +152,38 @@ public abstract class LootSelectorEntry extends LootEntryAbstract { - - public abstract class c implements LootEntry { - -- protected c() {} -+ protected c() { -+ } - - @Override - public int a(float f) { -- return Math.max(MathHelper.d((float) LootSelectorEntry.this.c + (float) LootSelectorEntry.this.e * f), 0); -+ // Paper start - Offer an alternative loot formula to refactor how luck bonus applies -+ // SEE: https://luckformula.emc.gs for details and data -+ if (lastLuck != null && lastLuck == f) { -+ return lastWeight; -+ } -+ // This is vanilla -+ float qualityModifer = (float) getQuality() * f; -+ double baseWeight = (getWeight() + qualityModifer); -+ if (com.destroystokyo.paper.PaperConfig.useAlternativeLuckFormula) { -+ // Random boost to avoid losing precision in the final int cast on return -+ final int weightBoost = 100; -+ baseWeight *= weightBoost; -+ // If we have vanilla 1, bump that down to 0 so nothing is is impacted -+ // vanilla 3 = 300, 200 basis = impact 2% -+ // =($B2*(($B2-100)/100/100)) -+ double impacted = baseWeight * ((baseWeight - weightBoost) / weightBoost / 100); -+ // =($B$7/100) -+ float luckModifier = Math.min(100, f * 10) / 100; -+ // =B2 - (C2 *($B$7/100)) -+ baseWeight = Math.ceil(baseWeight - (impacted * luckModifier)); -+ } -+ lastLuck = f; -+ lastWeight = (int) Math.max(0, Math.floor(baseWeight)); -+ return lastWeight; - } - } -+ private Float lastLuck = null; -+ private int lastWeight = 0; -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch b/Unmapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch deleted file mode 100644 index de373f15f0..0000000000 --- a/Unmapped-Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 15 Jun 2018 20:37:03 -0400 -Subject: [PATCH] Print Error details when failing to save player data - - -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -index 191c9e9a00b9871038f60d54bc22620322f6bdbd..4d30ca69dd303f1d76c8e6292021deda97851773 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -@@ -43,7 +43,7 @@ public class WorldNBTStorage { - - SystemUtils.a(file1, file, file2); - } catch (Exception exception) { -- WorldNBTStorage.LOGGER.warn("Failed to save player data for {}", entityhuman.getDisplayName().getString()); -+ WorldNBTStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getName(), exception); // Paper - } - - } diff --git a/Unmapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch b/Unmapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch deleted file mode 100644 index ceedc3c799..0000000000 --- a/Unmapped-Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 16 Jun 2018 01:18:16 -0500 -Subject: [PATCH] Make shield blocking delay configurable - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec..3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -369,4 +369,9 @@ public class PaperWorldConfig { - disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); - log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); - } -+ -+ public int shieldBlockingDelay = 5; -+ private void shieldBlockingDelay() { -+ shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 91be4df855a0a249518f0b562d05d9647169aa92..b776b14a62919fdfe86095c5eb6dfd039486b4a7 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3311,7 +3311,7 @@ public abstract class EntityLiving extends Entity { - if (this.isHandRaised() && !this.activeItem.isEmpty()) { - Item item = this.activeItem.getItem(); - -- return item.d_(this.activeItem) != EnumAnimation.BLOCK ? false : item.e_(this.activeItem) - this.bd >= 5; -+ return item.d_(this.activeItem) != EnumAnimation.BLOCK ? false : item.e_(this.activeItem) - this.bd >= getShieldBlockingDelay(); // Paper - shieldBlockingDelay - } else { - return false; - } -@@ -3590,4 +3590,15 @@ public abstract class EntityLiving extends Entity { - public void broadcastItemBreak(EnumHand enumhand) { - this.broadcastItemBreak(enumhand == EnumHand.MAIN_HAND ? EnumItemSlot.MAINHAND : EnumItemSlot.OFFHAND); - } -+ // Paper start -+ public int shieldBlockingDelay = world.paperConfig.shieldBlockingDelay; -+ -+ public int getShieldBlockingDelay() { -+ return shieldBlockingDelay; -+ } -+ -+ public void setShieldBlockingDelay(int shieldBlockingDelay) { -+ this.shieldBlockingDelay = shieldBlockingDelay; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index c43c300963bae9bca6ab9c9389dd53e42318715c..2d1c54eed8fa6885837d63014ff1f4b33dd35bd7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -711,5 +711,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setArrowsStuck(int arrows) { - getHandle().setArrowCount(arrows); - } -+ -+ @Override -+ public int getShieldBlockingDelay() { -+ return getHandle().getShieldBlockingDelay(); -+ } -+ -+ @Override -+ public void setShieldBlockingDelay(int delay) { -+ getHandle().setShieldBlockingDelay(delay); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch b/Unmapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch deleted file mode 100644 index 4d145bf944..0000000000 --- a/Unmapped-Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 15 Jun 2013 19:51:17 -0400 -Subject: [PATCH] Improve EntityShootBowEvent - -Adds missing call to Illagers and also adds Arrow ItemStack to skeltons - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java -index 54a4a295660375a0fcc54e02d80d569d9a32e73e..fee9a5140f097225b5da58b18bfbd528dffdc77b 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java -@@ -171,8 +171,18 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan - double d3 = (double) MathHelper.sqrt(d0 * d0 + d2 * d2); - - entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.world.getDifficulty().a() * 4)); -+ // Paper start -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), entityarrow.getOriginalItemStack(), entityarrow, entityliving.getRaisedHand(), 0.8F, true); -+ if (event.isCancelled()) { -+ event.getProjectile().remove(); -+ return; -+ } -+ -+ if (event.getProjectile() == entityarrow.getBukkitEntity()) { -+ this.world.addEntity(entityarrow); -+ } - this.playSound(SoundEffects.ENTITY_SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); -- this.world.addEntity(entityarrow); -+ // Paper end - } - - class a extends EntityIllagerWizard.PathfinderGoalCastSpell { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -index a2a67bccf38464731670e98cb155348df94474c5..4dca5ea9127c15b2739483b2ad74a5296a6b96ad 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -@@ -197,7 +197,7 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - - entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.world.getDifficulty().a() * 4)); - // CraftBukkit start -- org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), null, entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), entityarrow.getOriginalItemStack(), entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); // Paper - if (event.isCancelled()) { - event.getProjectile().remove(); - return; diff --git a/Unmapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch b/Unmapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch deleted file mode 100644 index 48c889f719..0000000000 --- a/Unmapped-Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 18 Jun 2018 01:12:53 -0400 -Subject: [PATCH] PlayerReadyArrowEvent - -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/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 7839553662d7f1f378969d42fb7a560e489852f4..408732c59ed817c056671a78e43a734b048a818e 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -2142,6 +2142,17 @@ public abstract class EntityHuman extends EntityLiving { - return ImmutableList.of(EntityPose.STANDING, EntityPose.CROUCHING, EntityPose.SWIMMING); - } - -+ // Paper start -+ protected boolean tryReadyArrow(ItemStack bow, ItemStack itemstack) { -+ return !(this instanceof EntityPlayer) || -+ new com.destroystokyo.paper.event.player.PlayerReadyArrowEvent( -+ ((EntityPlayer) this).getBukkitEntity(), -+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(bow), -+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack) -+ ).callEvent(); -+ // Paper end -+ } -+ - @Override - public ItemStack f(ItemStack itemstack) { - if (!(itemstack.getItem() instanceof ItemProjectileWeapon)) { -@@ -2158,7 +2169,7 @@ public abstract class EntityHuman extends EntityLiving { - for (int i = 0; i < this.inventory.getSize(); ++i) { - ItemStack itemstack2 = this.inventory.getItem(i); - -- if (predicate.test(itemstack2)) { -+ if (predicate.test(itemstack2) && tryReadyArrow(itemstack, itemstack2)) { // Paper - return itemstack2; - } - } diff --git a/Unmapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch b/Unmapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch deleted file mode 100644 index 0a66bfbf73..0000000000 --- a/Unmapped-Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Mon, 18 Jun 2018 15:46:23 +0200 -Subject: [PATCH] Implement EntityKnockbackByEntityEvent - -This event is called when an entity receives knockback by another entity. - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 2cc15ac22000343dc540454ba971993bf5b2f5a3..e177483dace853ccd01d410fc7deea17663e9a3d 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -1568,7 +1568,7 @@ public abstract class EntityInsentient extends EntityLiving { - - if (flag) { - if (f1 > 0.0F && entity instanceof EntityLiving) { -- ((EntityLiving) entity).a(f1 * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F))); -+ ((EntityLiving) entity).doKnockback(f1 * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F)), this); // Paper - this.setMot(this.getMot().d(0.6D, 1.0D, 0.6D)); - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index b776b14a62919fdfe86095c5eb6dfd039486b4a7..daf09f3f0e6be57f540641d70e9c944de7fe6622 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -1339,7 +1339,7 @@ public abstract class EntityLiving extends Entity { - } - - this.ap = (float) (MathHelper.d(d1, d0) * 57.2957763671875D - (double) this.yaw); -- this.a(0.4F, d0, d1); -+ this.doKnockback(0.4F, d0, d1, entity1); // Paper - } else { - this.ap = (float) ((int) (Math.random() * 2.0D) * 180); - } -@@ -1387,7 +1387,7 @@ public abstract class EntityLiving extends Entity { - } - - protected void e(EntityLiving entityliving) { -- entityliving.a(0.5F, entityliving.locX() - this.locX(), entityliving.locZ() - this.locZ()); -+ entityliving.doKnockback(0.5F, entityliving.locX() - this.locX(), entityliving.locZ() - this.locZ(), this); // Paper - } - - private boolean f(DamageSource damagesource) { -@@ -1630,6 +1630,11 @@ public abstract class EntityLiving extends Entity { - } - - public void a(float f, double d0, double d1) { -+ // Paper start - add knockbacking entity parameter -+ this.doKnockback(f, d0, d1, null); -+ } -+ public void doKnockback(float f, double d0, double d1, Entity knockingBackEntity) { -+ // Paper end - add knockbacking entity parameter - f = (float) ((double) f * (1.0D - this.b(GenericAttributes.KNOCKBACK_RESISTANCE))); - if (f > 0.0F) { - this.impulse = true; -@@ -1637,6 +1642,16 @@ public abstract class EntityLiving extends Entity { - Vec3D vec3d1 = (new Vec3D(d0, 0.0D, d1)).d().a((double) f); - - this.setMot(vec3d.x / 2.0D - vec3d1.x, this.onGround ? Math.min(0.4D, vec3d.y / 2.0D + (double) f) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); -+ -+ // Paper start - call EntityKnockbackByEntityEvent -+ Vec3D currentMot = this.getMot(); -+ org.bukkit.util.Vector delta = new org.bukkit.util.Vector(currentMot.x - vec3d.x, currentMot.y - vec3d.y, currentMot.z - vec3d.z); -+ // Restore old velocity to be able to access it in the event -+ this.setMot(vec3d); -+ if (knockingBackEntity == null || new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent((LivingEntity) getBukkitEntity(), knockingBackEntity.getBukkitEntity(), f, delta).callEvent()) { -+ this.setMot(vec3d.x + delta.getX(), vec3d.y + delta.getY(), vec3d.z + delta.getZ()); -+ } -+ // Paper end - } - } - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 408732c59ed817c056671a78e43a734b048a818e..3c49d7acd4ad0717886adf6c469e8a49a58e859b 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1177,7 +1177,7 @@ public abstract class EntityHuman extends EntityLiving { - if (flag5) { - if (i > 0) { - if (entity instanceof EntityLiving) { -- ((EntityLiving) entity).a((float) i * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F))); -+ ((EntityLiving) entity).doKnockback((float) i * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F)), this); // Paper - } else { - entity.i((double) (-MathHelper.sin(this.yaw * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (MathHelper.cos(this.yaw * 0.017453292F) * (float) i * 0.5F)); - } -@@ -1201,7 +1201,7 @@ public abstract class EntityHuman extends EntityLiving { - if (entityliving != this && entityliving != entity && !this.r(entityliving) && (!(entityliving instanceof EntityArmorStand) || !((EntityArmorStand) entityliving).isMarker()) && this.h((Entity) entityliving) < 9.0D) { - // CraftBukkit start - Only apply knockback if the damage hits - if (entityliving.damageEntity(DamageSource.playerAttack(this).sweep(), f4)) { -- entityliving.a(0.4F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F))); -+ entityliving.doKnockback(0.4F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F)), this); // Paper - } - // CraftBukkit end - } diff --git a/Unmapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch b/Unmapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch deleted file mode 100644 index 2dcb0871e7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0228-Expand-Explosions-API.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 20 Jun 2018 23:17:24 -0400 -Subject: [PATCH] Expand Explosions API - -Add Entity as a Source capability, and add more API choices, and on Location. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 2cc25177110d669e0f425668e26a38794c11c101..1fce5548544f00fd79839a23e05ec5690f6f0621 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -889,6 +889,11 @@ public class CraftWorld implements World { - public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) { - return !world.createExplosion(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, breakBlocks ? Explosion.Effect.BREAK : Explosion.Effect.NONE).wasCanceled; - } -+ // Paper start -+ public boolean createExplosion(Entity source, Location loc, float power, boolean setFire, boolean breakBlocks) { -+ return !world.createExplosion(source != null ? ((org.bukkit.craftbukkit.entity.CraftEntity) source).getHandle() : null, loc.getX(), loc.getY(), loc.getZ(), power, setFire, breakBlocks ? Explosion.Effect.BREAK : Explosion.Effect.NONE).wasCanceled; -+ } -+ // Paper end - - @Override - public boolean createExplosion(Location loc, float power) { diff --git a/Unmapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch b/Unmapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch deleted file mode 100644 index 7ef5cf4e29..0000000000 --- a/Unmapped-Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 Jun 2018 00:21:28 -0400 -Subject: [PATCH] LivingEntity Hand Raised/Item Use API - -How long an entity has raised hands to charge an attack or use an item - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index daf09f3f0e6be57f540641d70e9c944de7fe6622..a530f13526ef1ee947adb22e24d5c9afb705a01d 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -212,7 +212,7 @@ public abstract class EntityLiving extends Entity { - private float bu; - private int jumpTicks; - private float bw; -- protected ItemStack activeItem; -+ public ItemStack activeItem; // Paper - public - protected int bd; - protected int be; - private BlockPosition bx; -@@ -3294,10 +3294,12 @@ public abstract class EntityLiving extends Entity { - return this.activeItem; - } - -+ public int getItemUseRemainingTime() { return this.dZ(); } // Paper - OBFHELPER - public int dZ() { - return this.bd; - } - -+ public int getHandRaisedTime() { return this.ea(); } // Paper - OBFHELPER - public int ea() { - return this.isHandRaised() ? this.activeItem.k() - this.dZ() : 0; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 2d1c54eed8fa6885837d63014ff1f4b33dd35bd7..a0b006f24829ff9f5754293fbe389d19a14dc001 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -721,5 +721,30 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setShieldBlockingDelay(int delay) { - getHandle().setShieldBlockingDelay(delay); - } -+ -+ @Override -+ public ItemStack getActiveItem() { -+ return getHandle().activeItem.asBukkitMirror(); -+ } -+ -+ @Override -+ public int getItemUseRemainingTime() { -+ return getHandle().getItemUseRemainingTime(); -+ } -+ -+ @Override -+ public int getHandRaisedTime() { -+ return getHandle().getHandRaisedTime(); -+ } -+ -+ @Override -+ public boolean isHandRaised() { -+ return getHandle().isHandRaised(); -+ } -+ -+ @Override -+ public org.bukkit.inventory.EquipmentSlot getHandRaised() { -+ return getHandle().getRaisedHand() == net.minecraft.world.EnumHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0230-RangedEntity-API.patch b/Unmapped-Spigot-Server-Patches/0230-RangedEntity-API.patch deleted file mode 100644 index e8c055fe8b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0230-RangedEntity-API.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 26 Jun 2018 22:00:49 -0400 -Subject: [PATCH] RangedEntity API - -Allows you to determine if an entity is capable of ranged attacks, -and to perform an attack. - -diff --git a/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0195d4036f06db0f3f56f134dbfbc4360d44ed86 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java -@@ -0,0 +1,19 @@ -+package com.destroystokyo.paper.entity; -+ -+import net.minecraft.world.entity.monster.IRangedEntity; -+import org.bukkit.craftbukkit.entity.CraftLivingEntity; -+import org.bukkit.entity.LivingEntity; -+ -+public interface CraftRangedEntity extends RangedEntity { -+ T getHandle(); -+ -+ @Override -+ default void rangedAttack(LivingEntity target, float charge) { -+ getHandle().rangedAttack(((CraftLivingEntity) target).getHandle(), charge); -+ } -+ -+ @Override -+ default void setChargingAttack(boolean raiseHands) { -+ getHandle().setChargingAttack(raiseHands); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java b/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java -index d79e6b28c77edc468c6471d909306c2135b496c7..0f0aaa8a15301dea8405e26333d30b385831506c 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java -+++ b/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java -@@ -4,5 +4,8 @@ import net.minecraft.world.entity.EntityLiving; - - public interface IRangedEntity { - -- void a(EntityLiving entityliving, float f); -+ void a(EntityLiving entityliving, float f); default void rangedAttack(EntityLiving entityliving, float f) { a(entityliving, f); } // Paper - OBFHELPER -+ -+ // - see EntitySkeletonAbstract melee goal -+ void setAggressive(boolean flag); default void setChargingAttack(boolean charging) { setAggressive(charging); }; // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -index 3bb39dae11847bea1330ef68f53c90309fd2a095..bba2e3fba5b225e90744e78df085b3c318a029ce 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.Drowned; - import org.bukkit.entity.EntityType; - --public class CraftDrowned extends CraftZombie implements Drowned { -+public class CraftDrowned extends CraftZombie implements Drowned, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftDrowned(CraftServer server, EntityDrowned entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -index 0dabb012b37b6dda58368765b220b7d0aaf8e2d4..3763fb13920c98bb7cd250883ec89cdd1805dbd6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Illusioner; - --public class CraftIllusioner extends CraftSpellcaster implements Illusioner { -+public class CraftIllusioner extends CraftSpellcaster implements Illusioner, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftIllusioner(CraftServer server, EntityIllagerIllusioner entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -index 6dcf196fd83f2175a5d34c8d138d923c32ddb899..818034c62893a71808e3af0aa33393605611acdd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.entity.CraftRangedEntity; - import com.google.common.base.Preconditions; - import net.minecraft.world.entity.animal.horse.EntityLlama; - import org.bukkit.craftbukkit.CraftServer; -@@ -10,7 +11,7 @@ import org.bukkit.entity.Llama; - import org.bukkit.entity.Llama.Color; - import org.bukkit.inventory.LlamaInventory; - --public class CraftLlama extends CraftChestedHorse implements Llama { -+public class CraftLlama extends CraftChestedHorse implements Llama, CraftRangedEntity { // Paper - - public CraftLlama(CraftServer server, EntityLlama entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -index 0327f3d9e1f4f9078ad7838bc03c63d2cff35f9b..45239f1b0c654a7b8450d03189b5b935771598ad 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -@@ -14,7 +14,7 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.Piglin; - import org.bukkit.inventory.Inventory; - --public class CraftPiglin extends CraftPiglinAbstract implements Piglin { -+public class CraftPiglin extends CraftPiglinAbstract implements Piglin, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftPiglin(CraftServer server, EntityPiglin entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -index 72ac9eae71028a40541f949d617ce326c00c6369..87eeb5b632b581dca7613973bc9a25f152839a33 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -@@ -7,7 +7,7 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.Pillager; - import org.bukkit.inventory.Inventory; - --public class CraftPillager extends CraftIllager implements Pillager { -+public class CraftPillager extends CraftIllager implements Pillager, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftPillager(CraftServer server, EntityPillager entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -index cebb90fd4a84c0a97d7493a6923d16d0c4215f5e..c2acfa2cc27a187154e17b7f45908682b41b52af 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -@@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.Skeleton; - import org.bukkit.entity.Skeleton.SkeletonType; - --public class CraftSkeleton extends CraftMonster implements Skeleton { -+public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftSkeleton(CraftServer server, EntitySkeletonAbstract entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -index 5720bdf64eadec1ebe1a2253e2b537ca299ffa6d..a262cf88eefca2767eb6e5da856626be34352ccd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Snowman; - --public class CraftSnowman extends CraftGolem implements Snowman { -+public class CraftSnowman extends CraftGolem implements Snowman, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftSnowman(CraftServer server, EntitySnowman entity) { - super(server, entity); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -index 796bd26d41b52941c38d81411688116af7053535..9cc34cdb43596eff34625045f884b93da3f27ab6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Witch; - --public class CraftWitch extends CraftRaider implements Witch { -+public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftWitch(CraftServer server, EntityWitch entity) { - super(server, entity); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -index 7150702d8dac0d9db44661b1b17f520302988b45..1d94aeec37dcb9758d88ef25a5cad1333bbfbf6c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -@@ -7,7 +7,7 @@ import org.bukkit.craftbukkit.boss.CraftBossBar; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Wither; - --public class CraftWither extends CraftMonster implements Wither { -+public class CraftWither extends CraftMonster implements Wither, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - private BossBar bossBar; - diff --git a/Unmapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch b/Unmapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch deleted file mode 100644 index 153410f43a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 22 Jun 2018 10:38:31 -0500 -Subject: [PATCH] Add config to disable ender dragon legacy check - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77..4813f62d1e382d5ac6971b2244df3f13c80d1950 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -374,4 +374,9 @@ public class PaperWorldConfig { - private void shieldBlockingDelay() { - shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); - } -+ -+ public boolean scanForLegacyEnderDragon = true; -+ private void scanForLegacyEnderDragon() { -+ scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index f727cc456bd23816c4e70be83c395d1d8ca7d876..0869af4670f040344f5b6c2c10bff5e5226f707c 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -73,7 +73,7 @@ public class EnderDragonBattle { - private boolean dragonKilled; - private boolean previouslyKilled; - public UUID dragonUUID; -- private boolean n; -+ private boolean n; private void setScanForLegacyFight(boolean scanForLegacyFight) { this.n = scanForLegacyFight; } private boolean scanForLegacyFight() { return this.n; } // Paper - OBFHELPER - public BlockPosition exitPortalLocation; - public EnumDragonRespawn respawnPhase; - private int q; -@@ -83,6 +83,10 @@ public class EnderDragonBattle { - this.bossBattle = (BossBattleServer) (new BossBattleServer(new ChatMessage("entity.minecraft.ender_dragon"), BossBattle.BarColor.PINK, BossBattle.BarStyle.PROGRESS)).setPlayMusic(true).c(true); - this.gateways = Lists.newArrayList(); - this.n = true; -+ // Paper start -+ setScanForLegacyFight(worldserver.paperConfig.scanForLegacyEnderDragon); -+ if (!scanForLegacyFight()) dragonKilled = true; -+ // Paper end - this.world = worldserver; - if (nbttagcompound.hasKeyOfType("DragonKilled", 99)) { - if (nbttagcompound.b("Dragon")) { diff --git a/Unmapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch b/Unmapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch deleted file mode 100644 index 8856ce729b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 3 Jul 2018 16:08:14 +0200 -Subject: [PATCH] Implement World.getEntity(UUID) API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 1fce5548544f00fd79839a23e05ec5690f6f0621..a2b3f5106edc8328ba7edd65dedd56e0dc8d33d2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1304,6 +1304,15 @@ public class CraftWorld implements World { - return list; - } - -+ // Paper start - getEntity by UUID API -+ @Override -+ public Entity getEntity(UUID uuid) { -+ Validate.notNull(uuid, "UUID cannot be null"); -+ net.minecraft.world.entity.Entity entity = world.getEntity(uuid); -+ return entity == null ? null : entity.getBukkitEntity(); -+ } -+ // Paper end -+ - @Override - public void save() { - org.spigotmc.AsyncCatcher.catchOp("world save"); // Spigot diff --git a/Unmapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch b/Unmapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch deleted file mode 100644 index 3a779bd68c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch +++ /dev/null @@ -1,227 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 3 Jul 2018 21:56:23 -0400 -Subject: [PATCH] InventoryCloseEvent Reason API - -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/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index de7167ddf7b36ef266e511187789f99244401c21..b581a6d3ec06498a4c6db92eb50c5d2b28038131 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -547,7 +547,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - // Paper end - if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.activeContainer = this.defaultContainer; - } - -@@ -720,7 +720,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - // SPIGOT-943 - only call if they have an inventory open - if (this.activeContainer != this.defaultContainer) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DEATH); // Paper - } - - net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure -@@ -1293,7 +1293,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - return OptionalInt.empty(); - } else { - if (this.activeContainer != this.defaultContainer) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - - this.nextContainerCounter(); -@@ -1353,7 +1353,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - // CraftBukkit end - if (this.activeContainer != this.defaultContainer) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - - // this.nextContainerCounter(); // CraftBukkit - moved up -@@ -1417,7 +1417,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - @Override - public void closeInventory() { -- CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit -+ // Paper start -+ closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); -+ } -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit -+ // Paper end - this.playerConnection.sendPacket(new PacketPlayOutCloseWindow(this.activeContainer.windowId)); - this.o(); - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index b73315df7dae243dd76e44d586dfc1d8f9017a56..eb19b6fc87bfd4e500ea7836c1010a80b36abab2 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1125,7 +1125,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - for (TileEntity tileentity : chunk.getTileEntities().values()) { - if (tileentity instanceof net.minecraft.world.IInventory) { - for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((net.minecraft.world.IInventory) tileentity).getViewers())) { -- h.closeInventory(); -+ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - } - } - } -@@ -1183,7 +1183,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // Spigot Start - if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder) { - for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) { -- h.closeInventory(); -+ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - } - } - // Spigot End -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 6c5966901ffdc3c7f9950ff8b40fbf2489acbd4b..2a1ad096515247382da741fbcdc84f6d5b1001c5 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -190,6 +190,7 @@ import org.bukkit.event.inventory.ClickType; - import org.bukkit.event.inventory.CraftItemEvent; - import org.bukkit.event.inventory.InventoryAction; - import org.bukkit.event.inventory.InventoryClickEvent; -+import org.bukkit.event.inventory.InventoryCloseEvent; // Paper - import org.bukkit.event.inventory.InventoryCreativeEvent; - import org.bukkit.event.inventory.InventoryType.SlotType; - import org.bukkit.event.inventory.SmithItemEvent; -@@ -2311,10 +2312,15 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInCloseWindow packetplayinclosewindow) { -+ // Paper start -+ handleContainerClose(packetplayinclosewindow, InventoryCloseEvent.Reason.PLAYER); -+ } -+ public void handleContainerClose(PacketPlayInCloseWindow packetplayinclosewindow, InventoryCloseEvent.Reason reason) { -+ // Paper end - PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.getWorldServer()); - - if (this.player.isFrozen()) return; // CraftBukkit -- CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit -+ CraftEventFactory.handleInventoryCloseEvent(this.player, reason); // CraftBukkit // Paper - - this.player.o(); - } -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index bd8bcc3891b29d31742bcfd6080a3972e4a9bee7..80934fc662b33b1c88dd7a3033792d612a7c7930 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -494,7 +494,7 @@ public abstract class PlayerList { - // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it - // See SPIGOT-5799, SPIGOT-6145 - if (entityplayer.activeContainer != entityplayer.defaultContainer) { -- entityplayer.closeInventory(); -+ entityplayer.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - } - - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 3c49d7acd4ad0717886adf6c469e8a49a58e859b..b6effe1037f3ae59e6faa5f5d039b6ad54bca5d4 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -252,7 +252,7 @@ public abstract class EntityHuman extends EntityLiving { - this.et(); - super.tick(); - if (!this.world.isClientSide && this.activeContainer != null && !this.activeContainer.canUse(this)) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.activeContainer = this.defaultContainer; - } - -@@ -447,6 +447,13 @@ public abstract class EntityHuman extends EntityLiving { - return 20; - } - -+ // Paper start - unused code, but to keep signatures aligned -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ closeInventory(); -+ this.activeContainer = this.defaultContainer; -+ } -+ // Paper end -+ - public void closeInventory() { - this.activeContainer = this.defaultContainer; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 1333d425147e6dc7f21f755a9b25ead9723d4a28..3b3e6076f2565e02fa6f13e369094f8b6cac5382 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -375,7 +375,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - if (((EntityPlayer) getHandle()).playerConnection == null) return; - if (getHandle().activeContainer != getHandle().defaultContainer) { - // fire INVENTORY_CLOSE if one already open -- ((EntityPlayer) getHandle()).playerConnection.a(new PacketPlayInCloseWindow(getHandle().activeContainer.windowId)); -+ ((EntityPlayer) getHandle()).playerConnection.handleContainerClose(new PacketPlayInCloseWindow(getHandle().activeContainer.windowId), org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - EntityPlayer player = (EntityPlayer) getHandle(); - Container container; -@@ -445,8 +445,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - - @Override - public void closeInventory() { -- getHandle().closeInventory(); -+ // Paper start -+ getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); - } -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ getHandle().closeInventory(reason); -+ } -+ // Paper end - - @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 2abd5157b0964fc02994ca7a9317d2fb5539dc1c..ee3fbf0789b4841a113727397ba6809b2600ff83 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -898,7 +898,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - // Close any foreign inventory - if (getHandle().activeContainer != getHandle().defaultContainer) { -- getHandle().closeInventory(); -+ getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper - } - - // 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 69b5c76b312d055603ce62ad7b0c88cd01272ba9..7a245a0bc67ba7aaa986d20443d23e1a8a831dce 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1187,7 +1187,7 @@ public class CraftEventFactory { - - public static Container callInventoryOpenEvent(EntityPlayer player, Container container, boolean cancelled) { - if (player.activeContainer != player.defaultContainer) { // fire INVENTORY_CLOSE if one already open -- player.playerConnection.a(new PacketPlayInCloseWindow(player.activeContainer.windowId)); -+ player.playerConnection.handleContainerClose(new PacketPlayInCloseWindow(player.activeContainer.windowId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - - CraftServer server = player.world.getServer(); -@@ -1353,8 +1353,18 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start -+ /** -+ * Incase plugins hooked into this or Spigot adds a new inventory close event. Prefer to pass a reason -+ * @param human -+ */ -+ @Deprecated - public static void handleInventoryCloseEvent(EntityHuman human) { -- InventoryCloseEvent event = new InventoryCloseEvent(human.activeContainer.getBukkitView()); -+ handleInventoryCloseEvent(human, org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); -+ } -+ public static void handleInventoryCloseEvent(EntityHuman human, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ // Paper end -+ InventoryCloseEvent event = new InventoryCloseEvent(human.activeContainer.getBukkitView(), reason); // Paper - human.world.getServer().getPluginManager().callEvent(event); - human.activeContainer.transferTo(human.defaultContainer, human.getBukkitEntity()); - } diff --git a/Unmapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch b/Unmapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch deleted file mode 100644 index c70d5e9bb3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0234-Vex-getSummoner-API.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 15:30:22 -0400 -Subject: [PATCH] Vex#getSummoner API - -Get's the NPC that summoned this Vex - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -index 3acf36a500424808cd91dc607df1ffbe23720c16..3b74ade60b3b0ae0e908866cb4ac11acd75620ff 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -@@ -124,6 +124,7 @@ public class EntityVex extends EntityMonster { - - } - -+ public EntityInsentient getOwner() { return eK(); } // Paper - OBFHELPER - public EntityInsentient eK() { - return this.c; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -index ccaccffbf5eb18108760d1da09c4c1b2f33ebc42..962d6017f6acc47ebe4b754ccd9b97a1fc97cc58 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -@@ -16,6 +16,13 @@ public class CraftVex extends CraftMonster implements Vex { - return (EntityVex) super.getHandle(); - } - -+ // Paper start -+ public org.bukkit.entity.Mob getSummoner() { -+ net.minecraft.world.entity.EntityInsentient owner = getHandle().getOwner(); -+ return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; -+ } -+ // Paper end -+ - @Override - public String toString() { - return "CraftVex"; diff --git a/Unmapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/Unmapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch deleted file mode 100644 index 052bf8e2fc..0000000000 --- a/Unmapped-Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Fri, 13 Jul 2018 14:54:43 +0200 -Subject: [PATCH] Refresh player inventory when cancelling - PlayerInteractEntityEvent - -When interacting with entities with an item, the client will assume -the interaction is successful, and update the held item on the -client. However, if the interaction is cancelled on the server side, -the client will still mistakenly remove/replace the item in hand. - -Examples for this are milking cows with a bucket or dyeing sheep. -The bucket is replaced with milk and the dye removed from inventory. - -Refresh the player inventory when PlayerInteractEntityEvent is -cancelled to avoid this problem. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 2a1ad096515247382da741fbcdc84f6d5b1001c5..ed5e13f668d09dcf56cec8c6269a5fbd93d156bd 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2224,6 +2224,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - if (event.isCancelled()) { -+ this.player.updateInventory(this.player.activeContainer); // Paper - Refresh player inventory - return; - } - // CraftBukkit end diff --git a/Unmapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch b/Unmapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch deleted file mode 100644 index 7640438b07..0000000000 --- a/Unmapped-Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 19 Jul 2018 01:05:00 -0400 -Subject: [PATCH] Don't change the Entity Random seed for squids - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -index 7ce5e2597b34d3a4d2a79d73c15e893c064fc88c..1f5f3e0d209426b97e32b82dd15176b800f85816 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -@@ -48,7 +48,7 @@ public class EntitySquid extends EntityWaterAnimal { - - public EntitySquid(EntityTypes entitytypes, World world) { - super(entitytypes, world); -- this.random.setSeed((long) this.getId()); -+ //this.random.setSeed((long) this.getId()); // Paper - this.bu = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; - } - diff --git a/Unmapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch b/Unmapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch deleted file mode 100644 index e2a6edf92c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 19 Jul 2018 01:08:05 -0400 -Subject: [PATCH] Re-add vanilla entity warnings for duplicates - -These are a critical sign that somethin went wrong, and you've lost some data.... - -We should kind of know about these things you know. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index eb19b6fc87bfd4e500ea7836c1010a80b36abab2..d6a4ec132cadf8134a21f625f4ca978d37c643d0 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1077,7 +1077,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (entity1 == null) { - return false; - } else { -- // WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit -+ WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit // Paper - return true; - } - } diff --git a/Unmapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch b/Unmapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch deleted file mode 100644 index aded79d749..0000000000 --- a/Unmapped-Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 16 Jul 2018 12:42:20 +0200 -Subject: [PATCH] Avoid item merge if stack size above max stack size - - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index de11fd9772f30ac72c3ca52ec4efc3fef4091425..4cfe3475fa913cd46116f13ea8ed9caf5372a41a 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -209,6 +209,10 @@ public class EntityItem extends Entity { - - private void mergeNearby() { - if (this.z()) { -+ // Paper start - avoid item merge if stack size above max stack size -+ ItemStack stack = getItemStack(); -+ if (stack.getCount() >= stack.getMaxStackSize()) return; -+ // Paper end - // Spigot start - double radius = world.spigotConfig.itemMerge; - List list = this.world.a(EntityItem.class, this.getBoundingBox().grow(radius, radius, radius), (entityitem) -> { diff --git a/Unmapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch b/Unmapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch deleted file mode 100644 index fd4a4b705a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Tue, 17 Jul 2018 16:42:17 +0200 -Subject: [PATCH] Use asynchronous Log4j 2 loggers - - -diff --git a/pom.xml b/pom.xml -index f5429f2f1979542fd93956d2f436d20d0e3a66b8..4c8a057e790c96b0ab5123549d0566371acacb46 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -88,6 +88,13 @@ - log4j-iostreams - compile - -+ -+ -+ com.lmax -+ disruptor -+ 3.4.2 -+ runtime -+ - - org.ow2.asm - asm -diff --git a/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java -new file mode 100644 -index 0000000000000000000000000000000000000000..db652a1f7abc80bc751fd94925abaec58ab1a563 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.log; -+ -+import org.apache.logging.log4j.Level; -+import org.apache.logging.log4j.core.async.AsyncQueueFullPolicy; -+import org.apache.logging.log4j.core.async.EventRoute; -+ -+public final class LogFullPolicy implements AsyncQueueFullPolicy { -+ -+ /* -+ * Prevents log calls being logged out of order when the log queue is full. -+ */ -+ -+ @Override -+ public EventRoute getRoute(final long backgroundThreadId, final Level level) { -+ return EventRoute.ENQUEUE; -+ } -+} -diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties -index 0694b21465fb9e4164e71862ff24b62241b191f2..30efeb5faf8e7faccf1b252fa0ed6a9fc31c40a7 100644 ---- a/src/main/resources/log4j2.component.properties -+++ b/src/main/resources/log4j2.component.properties -@@ -1 +1,3 @@ -+Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector -+log4j2.AsyncQueueFullPolicy="com.destroystokyo.paper.log.LogFullPolicy" - log4j.skipJansi=true diff --git a/Unmapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch b/Unmapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch deleted file mode 100644 index c07f4b837a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 19 Jul 2018 01:13:28 -0400 -Subject: [PATCH] add more information to Entity.toString() - -UUID, ticks lived, valid, dead - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 43039c14e087259e3ce4b5091b887759b66fe52d..f15c60e56fc32a7dd525eefb2d622c33e00037c7 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2527,7 +2527,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public String toString() { -- return String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getDisplayName().getString(), this.id, this.world == null ? "~NULL~" : this.world.toString(), this.locX(), this.locY(), this.locZ()); -+ return String.format(Locale.ROOT, "%s['%s'/%d, uuid='%s', l='%s', x=%.2f, y=%.2f, z=%.2f, cx=%d, cz=%d, tl=%d, v=%b, d=%b]", new Object[] { this.getClass().getSimpleName(), this.getDisplayName().getString(), Integer.valueOf(this.id), this.uniqueID.toString(), this.world == null ? "~NULL~" : this.world.toString(), Double.valueOf(this.locX()), Double.valueOf(this.locY()), Double.valueOf(this.locZ()), chunkX, chunkZ, this.ticksLived, this.valid, this.dead}); // Paper - add more information - } - - public boolean isInvulnerable(DamageSource damagesource) { diff --git a/Unmapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/Unmapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch deleted file mode 100644 index 88a4b140ae..0000000000 --- a/Unmapped-Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 21 Jul 2018 08:25:40 -0400 -Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues - -Add -Ddebug.entities=true to your JVM flags to gain more information - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index d1e45dfb99074ec027d4f943391a024c726d93b2..66c808244bba70f827d8f15a96814251d352a046 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1147,6 +1147,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } else { - PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = new PlayerChunkMap.EntityTracker(entity, i, j, entitytypes.isDeltaTracking()); - -+ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker - this.trackedEntities.put(entity.getId(), playerchunkmap_entitytracker); - playerchunkmap_entitytracker.track(this.world.getPlayers()); - if (entity instanceof EntityPlayer) { -@@ -1188,7 +1189,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (playerchunkmap_entitytracker1 != null) { - playerchunkmap_entitytracker1.a(); - } -- -+ entity.tracker = null; // Paper - We're no longer tracked - } - - protected void g() { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index d6a4ec132cadf8134a21f625f4ca978d37c643d0..650015f08ef4defe7510ff2f5cbd25364b733515 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -197,6 +197,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final Convertable.ConversionSession convertable; - public final UUID uuid; - public boolean hasPhysicsEvent = true; // Paper -+ private static Throwable getAddToWorldStackTrace(Entity entity) { -+ return new Throwable(entity + " Added to world at " + new java.util.Date()); -+ } - - @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkProvider.getChunkAt(x, z, false); -@@ -1038,8 +1041,28 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -- if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper -+ // Paper start -+ if (entity.valid) { -+ MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); -+ -+ if (DEBUG_ENTITIES) { -+ Throwable thr = entity.addedToWorldStack; -+ if (thr == null) { -+ MinecraftServer.LOGGER.error("Double add entity has no add stacktrace"); -+ } else { -+ MinecraftServer.LOGGER.error("Double add stacktrace: ", thr); -+ } -+ } -+ return true; -+ } -+ // Paper end - if (entity.dead) { -+ // Paper start -+ if (DEBUG_ENTITIES) { -+ new Throwable("Tried to add entity " + entity + " but it was marked as removed already").printStackTrace(); // CraftBukkit -+ getAddToWorldStackTrace(entity).printStackTrace(); -+ } -+ // Paper end - // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit - return false; - } else if (this.isUUIDTaken(entity)) { -@@ -1237,7 +1260,24 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - -- this.entitiesByUUID.put(entity.getUniqueID(), entity); -+ if (DEBUG_ENTITIES) { -+ entity.addedToWorldStack = getAddToWorldStackTrace(entity); -+ } -+ -+ Entity old = this.entitiesByUUID.put(entity.getUniqueID(), entity); -+ if (old != null && old.getId() != entity.getId() && old.valid) { -+ Logger logger = LogManager.getLogger(); -+ logger.error("Overwrote an existing entity " + old + " with " + entity); -+ if (DEBUG_ENTITIES) { -+ if (old.addedToWorldStack != null) { -+ old.addedToWorldStack.printStackTrace(); -+ } else { -+ logger.error("Oddly, the old entity was not added to the world in the normal way. Plugins?"); -+ } -+ entity.addedToWorldStack.printStackTrace(); -+ } -+ } -+ - this.getChunkProvider().addEntity(entity); - // CraftBukkit start - SPIGOT-5278 - if (entity instanceof EntityDrowned) { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f15c60e56fc32a7dd525eefb2d622c33e00037c7..5d34c5c16942198c2ee998a8fb3c5bcd4bb3d1b5 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -48,6 +48,7 @@ import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -161,6 +162,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - -+ PlayerChunkMap.EntityTracker tracker; // Paper -+ public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { - bukkitEntity = CraftEntity.getEntity(world.getServer(), this); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index a9e7da1c848a6fe08fc112e445ceec1b7715d682..0d375af209e9768f430e08bd7a4bde1863b14da5 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -121,6 +121,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean pvpMode; - public boolean keepSpawnInMemory = true; - public org.bukkit.generator.ChunkGenerator generator; -+ public static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper - - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; diff --git a/Unmapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch b/Unmapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch deleted file mode 100644 index 2ac7798d52..0000000000 --- a/Unmapped-Spigot-Server-Patches/0242-EnderDragon-Events.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:51:27 -0500 -Subject: [PATCH] EnderDragon Events - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -index 5adbd9fe858aad9c775a10254eb53b34719a9bd6..91de4e6c1d478e001c8672d34b4ffe57f6cba0a6 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -@@ -80,7 +80,11 @@ public class DragonControllerLandedFlame extends AbstractDragonControllerLanded - this.d.setDuration(200); - this.d.setParticle(Particles.DRAGON_BREATH); - this.d.addEffect(new MobEffect(MobEffects.HARM)); -+ if (new com.destroystokyo.paper.event.entity.EnderDragonFlameEvent((org.bukkit.entity.EnderDragon) this.a.getBukkitEntity(), (org.bukkit.entity.AreaEffectCloud) this.d.getBukkitEntity()).callEvent()) { // Paper - this.a.world.addEntity(this.d); -+ } else { -+ this.removeAreaEffect(); -+ } - } - - } -@@ -91,8 +95,8 @@ public class DragonControllerLandedFlame extends AbstractDragonControllerLanded - ++this.c; - } - -- @Override -- public void e() { -+ public final void removeAreaEffect() { this.e(); } // Paper - OBFHELPER -+ @Override public void e() { - if (this.d != null) { - this.d.die(); - this.d = null; -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java -index db3cef26c8d5cdf740bb151a5525d8740a0e8bbd..1a5d5d39d3090acc3914e40e8d30c4a09789dbc9 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java -@@ -81,7 +81,9 @@ public class DragonControllerStrafe extends AbstractDragonController { - EntityDragonFireball entitydragonfireball = new EntityDragonFireball(this.a.world, this.a, d9, d10, d11); - - entitydragonfireball.setPositionRotation(d6, d7, d8, 0.0F, 0.0F); -+ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) a.getBukkitEntity(), (org.bukkit.entity.DragonFireball) entitydragonfireball.getBukkitEntity()).callEvent()) // Paper - this.a.world.addEntity(entitydragonfireball); -+ else entitydragonfireball.die(); // Paper - this.c = 0; - if (this.d != null) { - while (!this.d.c()) { -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java -index 59b5484731a5f71005c3efa56cbe40012d9641b5..27853f510e15e40c66da2cb4905c43f5e8f99d3d 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java -@@ -58,8 +58,10 @@ public class EntityDragonFireball extends EntityFireball { - } - } - -+ if (new com.destroystokyo.paper.event.entity.EnderDragonFireballHitEvent((org.bukkit.entity.DragonFireball) this.getBukkitEntity(), list.stream().map(EntityLiving::getBukkitLivingEntity).collect(java.util.stream.Collectors.toList()), (org.bukkit.entity.AreaEffectCloud) entityareaeffectcloud.getBukkitEntity()).callEvent()) { // Paper - this.world.triggerEffect(2006, this.getChunkCoordinates(), this.isSilent() ? -1 : 1); - this.world.addEntity(entityareaeffectcloud); -+ } else entityareaeffectcloud.die(); // Paper - this.die(); - } - diff --git a/Unmapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch b/Unmapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch deleted file mode 100644 index 684680a7ed..0000000000 --- a/Unmapped-Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:59:59 -0500 -Subject: [PATCH] PlayerElytraBoostEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ItemFireworks.java b/src/main/java/net/minecraft/world/item/ItemFireworks.java -index a2950faa48021782f10db0673d12d178443f7ccc..79e9be800385b94c4493bd8970620d76bfbd65ae 100644 ---- a/src/main/java/net/minecraft/world/item/ItemFireworks.java -+++ b/src/main/java/net/minecraft/world/item/ItemFireworks.java -@@ -45,11 +45,16 @@ public class ItemFireworks extends Item { - // Paper start - final EntityFireworks entityfireworks = new EntityFireworks(world, itemstack, entityhuman); - entityfireworks.spawningEntity = entityhuman.getUniqueID(); -- world.addEntity(entityfireworks); -- // Paper end -- if (!entityhuman.abilities.canInstantlyBuild) { -- itemstack.subtract(1); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entityfireworks)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } else if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); - } -+ // Paper end - } - - return InteractionResultWrapper.a(entityhuman.b(enumhand), world.s_()); diff --git a/Unmapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch b/Unmapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch deleted file mode 100644 index 9d4fb270ac..0000000000 --- a/Unmapped-Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Wed, 30 Nov 2016 20:56:58 -0600 -Subject: [PATCH] Improve BlockPosition inlining - -Normally the JVM can inline virtual getters by having two sets of code, one is the 'optimized' code and the other is the 'deoptimized' code. -If a single type is used 99% of the time, then its worth it to inline, and to revert to 'deoptimized' the 1% of the time we encounter other types. -But if two types are encountered commonly, then the JVM can't inline them both, and the call overhead remains. - -This scenario also occurs with BlockPos and MutableBlockPos. -The variables in BlockPos are final, so MutableBlockPos can't modify them. -MutableBlockPos fixes this by adding custom mutable variables, and overriding the getters to access them. - -This approach with utility methods that operate on MutableBlockPos and BlockPos. -Specific examples are BlockPosition.up(), and World.isValidLocation(). -It makes these simple methods much slower than they need to be. - -This should result in an across the board speedup in anything that accesses blocks or does logic with positions. - -This is based upon conclusions drawn from inspecting the assenmbly generated bythe JIT compiler on my microbenchmarks. -They had 'callq' (invoke) instead of 'mov' (get from memory) instructions. - -diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java -index 4b56683336fdab06804efdc8ca1f7c130b77291f..a44bcdb053877a6281e566ffe03ef72ffd50ca08 100644 ---- a/src/main/java/net/minecraft/core/BaseBlockPosition.java -+++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java -@@ -41,7 +41,7 @@ public class BaseBlockPosition implements Comparable { - this(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); - } - -- public boolean equals(Object object) { -+ public final boolean equals(Object object) { // Paper - if (this == object) { - return true; - } else if (!(object instanceof BaseBlockPosition)) { -@@ -53,7 +53,7 @@ public class BaseBlockPosition implements Comparable { - } - } - -- public int hashCode() { -+ public final int hashCode() { // Paper - return (this.getY() + this.getZ() * 31) * 31 + this.getX(); - } - -@@ -61,15 +61,15 @@ public class BaseBlockPosition implements Comparable { - return this.getY() == baseblockposition.getY() ? (this.getZ() == baseblockposition.getZ() ? this.getX() - baseblockposition.getX() : this.getZ() - baseblockposition.getZ()) : this.getY() - baseblockposition.getY(); - } - -- public int getX() { -+ public final int getX() { // Paper - return this.a; - } - -- public int getY() { -+ public final int getY() { // Paper - return this.b; - } - -- public int getZ() { -+ public final int getZ() { // Paper - return this.e; - } - -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 9fb6db18c5c1f39b5a564c0f5f70498825defa97..370b2c4460d6b52b5ef7da89f5ebf7ef50deb582 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -88,6 +88,7 @@ public class BlockPosition extends BaseBlockPosition { - return a(this.getX(), this.getY(), this.getZ()); - } - -+ public static long asLong(int x, int y, int z) { return a(x, y, z); } // Paper - OBFHELPER - public static long a(int i, int j, int k) { - long l = 0L; - diff --git a/Unmapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch b/Unmapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch deleted file mode 100644 index 028620de8b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Mon, 23 Jul 2018 13:08:19 -0400 -Subject: [PATCH] Optimize RegistryID.c() - -This is a frequent hotspot for world loading/saving. - -diff --git a/src/main/java/net/minecraft/util/RegistryID.java b/src/main/java/net/minecraft/util/RegistryID.java -index 6150f7a5c5004ac79414ab22dbaa3439dc8afdb4..a59dbfa01743137702b122f73c778452e63115b5 100644 ---- a/src/main/java/net/minecraft/util/RegistryID.java -+++ b/src/main/java/net/minecraft/util/RegistryID.java -@@ -15,12 +15,14 @@ public class RegistryID implements Registry { - private K[] d; - private int e; - private int f; -+ private java.util.BitSet usedIds; // Paper - - public RegistryID(int i) { - i = (int) ((float) i / 0.8F); - this.b = (K[]) (new Object[i]); // Paper - decompile fix - this.c = new int[i]; - this.d = (K[]) (new Object[i]); // Paper - decompile fix -+ this.usedIds = new java.util.BitSet(); // Paper - } - - // Paper start - decompile fix -@@ -52,9 +54,14 @@ public class RegistryID implements Registry { - } - - private int c() { -+ // Paper start -+ /* - while (this.e < this.d.length && this.d[this.e] != null) { - ++this.e; - } -+ */ -+ this.e = this.usedIds.nextClearBit(0); -+ // Paper end - - return this.e; - } -@@ -68,6 +75,7 @@ public class RegistryID implements Registry { - this.d = (K[]) (new Object[i]); // Paper - decompile fix - this.e = 0; - this.f = 0; -+ this.usedIds.clear(); // Paper - - for (int j = 0; j < ak.length; ++j) { - if (ak[j] != null) { -@@ -93,6 +101,7 @@ public class RegistryID implements Registry { - this.b[k] = k0; - this.c[k] = i; - this.d[i] = k0; -+ this.usedIds.set(i); // Paper - ++this.f; - if (i == this.e) { - ++this.e; -@@ -157,6 +166,7 @@ public class RegistryID implements Registry { - Arrays.fill(this.d, (Object) null); - this.e = 0; - this.f = 0; -+ this.usedIds.clear(); // Paper - } - - public int b() { diff --git a/Unmapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/Unmapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch deleted file mode 100644 index d24d23f2ac..0000000000 --- a/Unmapped-Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 23 Jul 2018 12:57:39 +0200 -Subject: [PATCH] Option to prevent armor stands from doing entity lookups - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4813f62d1e382d5ac6971b2244df3f13c80d1950..3562950df4868b1393790b1a1ff1fe0dc589c155 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -379,4 +379,9 @@ public class PaperWorldConfig { - private void scanForLegacyEnderDragon() { - scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); - } -+ -+ public boolean armorStandEntityLookups = true; -+ private void armorStandEntityLookups() { -+ armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 57e0ea95df34fab22d6c5868ab839d56a3fa85fc..829013f57128cc6c92a45098c6883f2305cf4ea5 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -356,6 +356,7 @@ public class EntityArmorStand extends EntityLiving { - - @Override - protected void collideNearby() { -+ if (!world.paperConfig.armorStandEntityLookups) return; // Paper - List list = this.world.getEntities(this, this.getBoundingBox(), EntityArmorStand.br); - - for (int i = 0; i < list.size(); ++i) { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0d375af209e9768f430e08bd7a4bde1863b14da5..8c7263f9dbb00cf6484e7f70b8d97639bab0cefc 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -37,6 +37,7 @@ import net.minecraft.world.DifficultyDamageScaler; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.decoration.EntityArmorStand; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.crafting.CraftingManager; -@@ -854,6 +855,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // Paper end - } - } -+ // Paper start - Prevent armor stands from doing entity lookups -+ @Override -+ public boolean getCubes(@Nullable Entity entity, AxisAlignedBB axisAlignedBB) { -+ if (entity instanceof EntityArmorStand && !entity.world.paperConfig.armorStandEntityLookups) return false; -+ return GeneratorAccess.super.getCubes(entity, axisAlignedBB); -+ } -+ // Paper end - - public Explosion explode(@Nullable Entity entity, double d0, double d1, double d2, float f, Explosion.Effect explosion_effect) { - return this.createExplosion(entity, (DamageSource) null, (ExplosionDamageCalculator) null, d0, d1, d2, f, false, explosion_effect); diff --git a/Unmapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch b/Unmapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch deleted file mode 100644 index 2ec7ae0aca..0000000000 --- a/Unmapped-Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch +++ /dev/null @@ -1,194 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 23 Jul 2018 14:22:26 +0200 -Subject: [PATCH] Vanished players don't have rights - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 5d34c5c16942198c2ee998a8fb3c5bcd4bb3d1b5..ae2f5664c3022b452b6cba8f9ce36b493fa9fec8 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -184,7 +184,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - private static double e = 1.0D; - private final EntityTypes f; - private int id; -- public boolean i; -+ public boolean i; public final boolean blocksEntitySpawning() { return this.i; } // Paper - OBFHELPER - public final List passengers; - protected int j; - @Nullable -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index 8f14e1ebefe172e056a04bd7b6f55b9bbb1e7b2e..b44b18341331e5176e0f1851aa60cc425ccbd439 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -4,6 +4,7 @@ import java.util.Iterator; - import java.util.UUID; - import javax.annotation.Nullable; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; -@@ -158,8 +159,14 @@ public abstract class IProjectile extends Entity { - protected boolean a(Entity entity) { - if (!entity.isSpectator() && entity.isAlive() && entity.isInteractable()) { - Entity entity1 = this.getShooter(); -- -+ // Paper start - Cancel hit for vanished players -+ if (entity1 instanceof EntityPlayer && entity instanceof EntityPlayer) { -+ org.bukkit.entity.Player collided = (org.bukkit.entity.Player) entity.getBukkitEntity(); -+ org.bukkit.entity.Player shooter = (org.bukkit.entity.Player) entity1.getBukkitEntity(); -+ if (!shooter.canSee(collided)) return false; -+ } - return entity1 == null || this.d || !entity1.isSameVehicle(entity); -+ // Paper end - } else { - return false; - } -diff --git a/src/main/java/net/minecraft/world/item/ItemBlock.java b/src/main/java/net/minecraft/world/item/ItemBlock.java -index ec12bea9de910824927ba31628b49f6713f31a29..59d52c252b2e59923b8e513dd4d2e1ec9ce34dc7 100644 ---- a/src/main/java/net/minecraft/world/item/ItemBlock.java -+++ b/src/main/java/net/minecraft/world/item/ItemBlock.java -@@ -177,7 +177,8 @@ public class ItemBlock extends Item { - EntityHuman entityhuman = blockactioncontext.getEntity(); - VoxelShapeCollision voxelshapecollision = entityhuman == null ? VoxelShapeCollision.a() : VoxelShapeCollision.a((Entity) entityhuman); - // CraftBukkit start - store default return -- boolean defaultReturn = (!this.isCheckCollisions() || iblockdata.canPlace(blockactioncontext.getWorld(), blockactioncontext.getClickPosition())) && blockactioncontext.getWorld().a(iblockdata, blockactioncontext.getClickPosition(), voxelshapecollision); -+ World world = blockactioncontext.getWorld(); // Paper -+ boolean defaultReturn = (!this.isCheckCollisions() || iblockdata.canPlace(blockactioncontext.getWorld(), blockactioncontext.getClickPosition())) && world.checkEntityCollision(iblockdata, entityhuman, voxelshapecollision, blockactioncontext.getClickPosition(), true); // Paper - org.bukkit.entity.Player player = (blockactioncontext.getEntity() instanceof EntityPlayer) ? (org.bukkit.entity.Player) blockactioncontext.getEntity().getBukkitEntity() : null; - - BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(blockactioncontext.getWorld(), blockactioncontext.getClickPosition()), player, CraftBlockData.fromData(iblockdata), defaultReturn); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 8c7263f9dbb00cf6484e7f70b8d97639bab0cefc..07c5cdd00930a55fd412ef95f71f55ee908189a1 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -27,6 +27,7 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; -@@ -65,6 +66,10 @@ import net.minecraft.world.level.saveddata.maps.WorldMap; - import net.minecraft.world.level.storage.WorldData; - import net.minecraft.world.level.storage.WorldDataMutable; - import net.minecraft.world.phys.AxisAlignedBB; -+import net.minecraft.world.phys.shapes.OperatorBoolean; -+import net.minecraft.world.phys.shapes.VoxelShape; -+import net.minecraft.world.phys.shapes.VoxelShapeCollision; -+import net.minecraft.world.phys.shapes.VoxelShapes; - import net.minecraft.world.scores.Scoreboard; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -232,6 +237,46 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } - -+ // Paper start -+ // ret true if no collision -+ public final boolean checkEntityCollision(IBlockData data, Entity source, VoxelShapeCollision voxelshapedcollision, -+ BlockPosition position, boolean checkCanSee) { -+ // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape) -+ VoxelShape voxelshape = data.getCollisionShape(this, position, voxelshapedcollision); -+ if (voxelshape.isEmpty()) { -+ return true; -+ } -+ -+ voxelshape = voxelshape.offset((double) position.getX(), (double) position.getY(), (double) position.getZ()); -+ if (voxelshape.isEmpty()) { -+ return true; -+ } -+ -+ List entities = this.getEntities(null, voxelshape.getBoundingBox()); -+ for (int i = 0, len = entities.size(); i < len; ++i) { -+ Entity entity = entities.get(i); -+ -+ if (checkCanSee && source instanceof EntityPlayer && entity instanceof EntityPlayer -+ && !((EntityPlayer) source).getBukkitEntity().canSee(((EntityPlayer) entity).getBukkitEntity())) { -+ continue; -+ } -+ -+ // !entity1.dead && entity1.i && (entity == null || !entity1.x(entity)); -+ // elide the last check since vanilla calls with entity = null -+ // only we care about the source for the canSee check -+ if (entity.dead || !entity.blocksEntitySpawning()) { -+ continue; -+ } -+ -+ if (VoxelShapes.applyOperation(voxelshape, VoxelShapes.of(entity.getBoundingBox()), OperatorBoolean.AND)) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ // Paper end -+ - @Override - public boolean s_() { - return this.isClientSide; -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 2902117fd2803741b053a04fda7f4414fb8593cb..10f4015b8c36e4e27cf7d0745ba70b8a9e60aff3 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -505,6 +505,7 @@ public abstract class BlockBase { - return this.a != null ? this.a.b : this.b(iblockaccess, blockposition, VoxelShapeCollision.a()); - } - -+ public final VoxelShape getCollisionShape(IBlockAccess iblockaccess, BlockPosition blockposition, VoxelShapeCollision voxelshapecollision) { return this.b(iblockaccess, blockposition, voxelshapecollision); } // Paper - OBFHELPER - public VoxelShape b(IBlockAccess iblockaccess, BlockPosition blockposition, VoxelShapeCollision voxelshapecollision) { - return this.getBlock().c(this.p(), iblockaccess, blockposition, voxelshapecollision); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -index 1b82349b96b3ec9490d06d1c1d1cbf2b1578d313..887016224c16f8a38c10a98eb0e2ae6cb353a153 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -@@ -54,6 +54,7 @@ public abstract class VoxelShape { - return this.a.a(); - } - -+ public final VoxelShape offset(double x, double y, double z) { return this.a(x, y, z); } // Paper - OBFHELPER - public VoxelShape a(double d0, double d1, double d2) { - return (VoxelShape) (this.isEmpty() ? VoxelShapes.a() : new VoxelShapeArray(this.a, new DoubleListOffset(this.a(EnumDirection.EnumAxis.X), d0), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Y), d1), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Z), d2))); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index fdd9e37a8c90fc3311e515355af0a0593efbdacc..cf32a4f63e8e59535c02a3f9c57f98833a2b0e83 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -45,6 +45,7 @@ public final class VoxelShapes { - return a(new AxisAlignedBB(d0, d1, d2, d3, d4, d5)); - } - -+ public static final VoxelShape of(AxisAlignedBB axisAlignedbb) { return VoxelShapes.a(axisAlignedbb); } // Paper - OBFHELPER - public static VoxelShape a(AxisAlignedBB axisalignedbb) { - int i = a(axisalignedbb.minX, axisalignedbb.maxX); - int j = a(axisalignedbb.minY, axisalignedbb.maxY); -@@ -139,6 +140,7 @@ public final class VoxelShapes { - } - } - -+ public static final boolean applyOperation(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { return VoxelShapes.c(voxelshape, voxelshape1, operatorboolean); } // Paper - OBFHELPER - public static boolean c(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { - if (operatorboolean.apply(false, false)) { - throw (IllegalArgumentException) SystemUtils.c((Throwable) (new IllegalArgumentException())); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 7a245a0bc67ba7aaa986d20443d23e1a8a831dce..31358b90784a6e983ff8b687021c721ed5d43eab 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1223,6 +1223,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); -+ -+ if (projectile.getShooter() instanceof Player && collided instanceof Player) { -+ if (!((Player) projectile.getShooter()).canSee((Player) collided)) { -+ event.setCancelled(true); -+ return event; -+ } -+ } -+ - Bukkit.getPluginManager().callEvent(event); - return event; - } diff --git a/Unmapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch b/Unmapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch deleted file mode 100644 index a5f5fb4d8d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 23 Jul 2018 22:18:31 -0400 -Subject: [PATCH] Mark chunk dirty anytime entities change to guarantee it - saves - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 7918dd4ad3e8cbb905b3929062a70fb7961b7d68..f56ff8e727c74870229d4d146b13534863f620d6 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -560,6 +560,7 @@ public class Chunk implements IChunkAccess { - entity.chunkZ = this.loc.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ this.markDirty(); // Paper - } - - @Override -@@ -588,6 +589,7 @@ public class Chunk implements IChunkAccess { - return; - } - entityCounts.decrement(entity.getMinecraftKeyString()); -+ this.markDirty(); // Paper - // Paper end - this.entities.remove(entity); // Paper - } diff --git a/Unmapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch b/Unmapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch deleted file mode 100644 index 1f08354596..0000000000 --- a/Unmapped-Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 23 Jul 2018 22:44:23 -0400 -Subject: [PATCH] Add some Debug to Chunk Entity slices - -If we detect unexpected state, log and try to recover - -This should hopefully avoid duplicate entities ever being created -if the entity was to end up in 2 different chunk slices - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index ae2f5664c3022b452b6cba8f9ce36b493fa9fec8..a6f0cde7bdc930abced5063da237bcd27ddcd20f 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -157,6 +157,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - } - }; -+ public List entitySlice = null; - // Paper end - - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index f56ff8e727c74870229d4d146b13534863f620d6..e4accac8f2e8daa58f9b0c279ffcad9347448bb0 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -26,6 +26,8 @@ import net.minecraft.ReportedException; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.EntitySlice; -@@ -551,6 +553,25 @@ public class Chunk implements IChunkAccess { - if (k >= this.entitySlices.length) { - k = this.entitySlices.length - 1; - } -+ // Paper - remove from any old list if its in one -+ List nextSlice = this.entitySlices[k]; // the next list to be added to -+ List currentSlice = entity.entitySlice; -+ if (nextSlice == currentSlice) { -+ if (World.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity was already in this chunk!" + entity, new Throwable()); -+ return; // ??? silly plugins -+ } -+ if (currentSlice != null && currentSlice.contains(entity)) { -+ // Still in an old chunk... -+ if (World.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity is still in another chunk!" + entity, new Throwable()); -+ Chunk chunk = entity.getCurrentChunk(); -+ if (chunk != null) { -+ chunk.removeEntity(entity); -+ } else { -+ removeEntity(entity); -+ } -+ currentSlice.remove(entity); // Just incase the above did not remove from the previous slice -+ } -+ // Paper end - - if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper - entity.inChunk = true; -@@ -560,6 +581,7 @@ public class Chunk implements IChunkAccess { - entity.chunkZ = this.loc.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ entity.entitySlice = this.entitySlices[k]; // Paper - this.markDirty(); // Paper - } - -@@ -585,6 +607,10 @@ public class Chunk implements IChunkAccess { - - // Paper start - if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); -+ if (entitySlices[i] == entity.entitySlice) { -+ entity.entitySlice = null; -+ entity.inChunk = false; -+ } - if (!this.entitySlices[i].remove(entity)) { - return; - } diff --git a/Unmapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch b/Unmapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch deleted file mode 100644 index 96ea01f30a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 27 Jul 2018 22:36:31 -0500 -Subject: [PATCH] SkeletonHorse Additions - - -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index dfcfdb31ca9531913d705aaaf85fb67399cfdc8c..4776a47566aac487dc77fd6b4b9b42b95974e31a 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -25,6 +25,7 @@ public final class IEntitySelector { - public static final Predicate f = (entity) -> { - return !(entity instanceof EntityHuman) || !entity.isSpectator() && !((EntityHuman) entity).isCreative() && entity.world.getDifficulty() != EnumDifficulty.PEACEFUL; - }; -+ public static Predicate notSpectator() { return g; } // Paper - OBFHELPER - public static final Predicate g = (entity) -> { - return !entity.isSpectator(); - }; -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -index 0ddb676a2d1c38c97cd7750c1594fd6468156d0a..da5365372e89b847d626e52c5541544467f14702 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -@@ -26,7 +26,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - - private final PathfinderGoalHorseTrap bw = new PathfinderGoalHorseTrap(this); - private boolean bx; -- private int by; -+ private int by; public int getTrapTime() { return this.by; } // Paper - OBFHELPER - - public EntityHorseSkeleton(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -145,10 +145,12 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - return 0.96F; - } - -+ public boolean isTrap() { return this.eM(); } // Paper - OBFHELPER - public boolean eM() { - return this.bx; - } - -+ public void setTrap(boolean trap) { this.t(trap); } // Paper - OBFHELPER - public void t(boolean flag) { - if (flag != this.bx) { - this.bx = flag; -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java b/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java -index 9b6a4f93dca6eeddad43d5f5675c551fb3fd2fdb..cf250cc6b7a77a7af742eab0b89cff2bc17fc5e4 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java -@@ -15,9 +15,14 @@ import net.minecraft.world.item.Items; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.level.World; - -+import org.bukkit.entity.HumanEntity; -+ -+import java.util.List; -+ - public class PathfinderGoalHorseTrap extends PathfinderGoal { - - private final EntityHorseSkeleton a; -+ private List eligiblePlayers; // Paper - - public PathfinderGoalHorseTrap(EntityHorseSkeleton entityhorseskeleton) { - this.a = entityhorseskeleton; -@@ -25,12 +30,13 @@ public class PathfinderGoalHorseTrap extends PathfinderGoal { - - @Override - public boolean a() { -- return this.a.world.isPlayerNearby(this.a.locX(), this.a.locY(), this.a.locZ(), 10.0D); -+ return !(eligiblePlayers = this.a.world.findNearbyBukkitPlayers(this.a.locX(), this.a.locY(), this.a.locZ(), 10.0D, false)).isEmpty(); // Paper - } - - @Override - public void e() { - WorldServer worldserver = (WorldServer) this.a.world; -+ if (!new com.destroystokyo.paper.event.entity.SkeletonHorseTrapEvent((org.bukkit.entity.SkeletonHorse) this.a.getBukkitEntity(), eligiblePlayers).callEvent()) return; // Paper - DifficultyDamageScaler difficultydamagescaler = worldserver.getDamageScaler(this.a.getChunkCoordinates()); - - this.a.t(false); -diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java -index 6d5d4c3df65995b9a13b66d070ba08d553cc98a2..8fdc4b22e8c99d653bd213fe64339c133b46b4e9 100644 ---- a/src/main/java/net/minecraft/world/level/IEntityAccess.java -+++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java -@@ -1,6 +1,9 @@ - package net.minecraft.world.level; - -+import com.google.common.collect.ImmutableList; - import com.google.common.collect.Lists; -+import org.bukkit.entity.HumanEntity; -+ - import java.util.Iterator; - import java.util.List; - import java.util.UUID; -@@ -115,6 +118,28 @@ public interface IEntityAccess { - return entityhuman; - } - -+ // Paper start -+ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, boolean notSpectator) { -+ return findNearbyBukkitPlayers(x, y, z, radius, notSpectator ? IEntitySelector.notSpectator() : IEntitySelector.canAITarget()); -+ } -+ -+ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate predicate) { -+ ImmutableList.Builder builder = ImmutableList.builder(); -+ -+ for (EntityHuman human : this.getPlayers()) { -+ if (predicate == null || predicate.test(human)) { -+ double distanceSquared = human.getDistanceSquared(x, y, z); -+ -+ if (radius < 0.0D || distanceSquared < radius * radius) { -+ builder.add(human.getBukkitEntity()); -+ } -+ } -+ } -+ -+ return builder.build(); -+ } -+ // Paper end -+ - @Nullable - default EntityHuman findNearbyPlayer(Entity entity, double d0) { - return this.a(entity.locX(), entity.locY(), entity.locZ(), d0, false); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -index 4aec5fdb6b0379b0797969ff3c8f8a9629a18bfb..7366d56cefad45883f353ea5fb16b41f87006ec1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -@@ -26,4 +26,26 @@ public class CraftSkeletonHorse extends CraftAbstractHorse implements SkeletonHo - public Variant getVariant() { - return Variant.SKELETON_HORSE; - } -+ -+ // Paper start -+ @Override -+ public EntityHorseSkeleton getHandle() { -+ return (EntityHorseSkeleton) super.getHandle(); -+ } -+ -+ @Override -+ public int getTrapTime() { -+ return getHandle().getTrapTime(); -+ } -+ -+ @Override -+ public boolean isTrap() { -+ return getHandle().isTrap(); -+ } -+ -+ @Override -+ public void setTrap(boolean trap) { -+ getHandle().setTrap(trap); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch b/Unmapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch deleted file mode 100644 index f9e9f4cd9f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 26 Jul 2018 00:11:12 -0400 -Subject: [PATCH] Prevent Saving Bad entities to chunks - -See https://github.com/PaperMC/Paper/issues/1223 - -Minecraft is saving invalid entities to the chunk files. - -Avoid saving bad data, and also make improvements to handle -loading these chunks. Any invalid entity will be instant killed, -so lets avoid adding it to the world... - -This lets us be safer about the dupe UUID resolver too, as now -we can ignore instant killed entities and avoid risk of duplicating -an invalid entity. - -This should reduce log occurrences of dupe uuid messages. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 650015f08ef4defe7510ff2f5cbd25364b733515..e39f1ea4eefb0d8e0ca379b116b3699c13bb3f35 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1157,6 +1157,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - List[] aentityslice = chunk.getEntitySlices(); // Spigot - int i = aentityslice.length; - -+ java.util.List toMoveChunks = new java.util.ArrayList<>(); // Paper - for (int j = 0; j < i; ++j) { - List entityslice = aentityslice[j]; // Spigot - Iterator iterator = entityslice.iterator(); -@@ -1169,11 +1170,25 @@ public class WorldServer extends World implements GeneratorAccessSeed { - throw (IllegalStateException) SystemUtils.c((Throwable) (new IllegalStateException("Removing entity while ticking!"))); - } - -+ // Paper start - move out entities that shouldn't be in this chunk before it unloads -+ if (!entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { -+ toMoveChunks.add(entity); -+ continue; -+ } -+ // Paper end -+ - this.entitiesById.remove(entity.getId()); - this.unregisterEntity(entity); -+ -+ if (entity.dead) iterator.remove(); // Paper - don't save dead entities during unload - } - } - } -+ // Paper start - move out entities that shouldn't be in this chunk before it unloads -+ for (Entity entity : toMoveChunks) { -+ this.chunkCheck(entity); -+ } -+ // Paper end - - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index f301c7ba4b17b92c6cf2fcee6da1e67081dad4fa..69bc9dc18bab157851d8080a672504598e8572a8 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -26,6 +26,7 @@ import net.minecraft.nbt.NBTTagList; - import net.minecraft.nbt.NBTTagLongArray; - import net.minecraft.nbt.NBTTagShort; - import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.LightEngineThreaded; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; -@@ -349,6 +350,7 @@ public class ChunkRegionLoader { - nbttagcompound1.set("TileEntities", nbttaglist1); - NBTTagList nbttaglist2 = new NBTTagList(); - -+ java.util.List toUpdate = new java.util.ArrayList<>(); // Paper - if (ichunkaccess.getChunkStatus().getType() == ChunkStatus.Type.LEVELCHUNK) { - Chunk chunk = (Chunk) ichunkaccess; - -@@ -366,13 +368,28 @@ public class ChunkRegionLoader { - while (iterator1.hasNext()) { - Entity entity = (Entity) iterator1.next(); - NBTTagCompound nbttagcompound4 = new NBTTagCompound(); -- -+ // Paper start -+ if ((int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { -+ toUpdate.add(entity); -+ continue; -+ } -+ if (entity.dead || hasPlayerPassenger(entity)) { -+ continue; -+ } -+ // Paper end - if (entity.d(nbttagcompound4)) { - chunk.d(true); - nbttaglist2.add(nbttagcompound4); - } - } - } -+ -+ // Paper start - move entities to the correct chunk -+ for (Entity entity : toUpdate) { -+ worldserver.chunkCheck(entity); -+ } -+ // Paper end -+ - } else { - ProtoChunk protochunk = (ProtoChunk) ichunkaccess; - -@@ -431,6 +448,19 @@ public class ChunkRegionLoader { - nbttagcompound1.set("Structures", a(chunkcoordintpair, ichunkaccess.h(), ichunkaccess.v())); - return nbttagcompound; - } -+ // Paper start - this is saved with the player -+ private static boolean hasPlayerPassenger(Entity entity) { -+ for (Entity passenger : entity.passengers) { -+ if (passenger instanceof EntityPlayer) { -+ return true; -+ } -+ if (hasPlayerPassenger(passenger)) { -+ return true; -+ } -+ } -+ return false; -+ } -+ // Paper end - - public static ChunkStatus.Type a(@Nullable NBTTagCompound nbttagcompound) { - if (nbttagcompound != null) { diff --git a/Unmapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch b/Unmapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch deleted file mode 100644 index ab3543b44f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Thu, 26 Jul 2018 14:10:23 +0200 -Subject: [PATCH] Don't call getItemMeta on hasItemMeta - -Spigot 1.13 checks if any field (which are manually copied from the ItemStack's "tag" NBT tag) on the ItemMeta class of an ItemStack is set. - -We could just check if the "tag" NBT tag is empty, albeit that would break some plugins. The only general tag added on 1.13 is "Damage", and we can just check if the "tag" NBT tag contains any other tag that's not "Damage" (https://minecraft.gamepedia.com/Player.dat_format#Item_structure) making the `hasItemStack` method behave as before. - -Returns true if getDamage() == 0 or has damage tag or other tag is set. -Check the `ItemMetaTest#testTaggedButNotMeta` method to see how this method behaves. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 315addab147dfecf4aa88d32d154cefe850d0a78..09d7a86b5f6cffdf6664ad657dd4f8dd8eabdd70 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -570,7 +570,7 @@ public final class CraftItemStack extends ItemStack { - - @Override - public boolean hasItemMeta() { -- return hasItemMeta(handle) && !CraftItemFactory.instance().equals(getItemMeta(), null); -+ return hasItemMeta(handle) && (handle.getDamage() != 0 || (handle.getTag() != null && handle.getTag().map.size() >= (handle.getTag().hasKey(CraftMetaItem.DAMAGE.NBT) ? 2 : 1))); // Paper - keep 1.12 CraftBukkit behavior without calling getItemMeta - } - - static boolean hasItemMeta(net.minecraft.world.item.ItemStack item) { -diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -index 42f577ed3508ba5a380648461e149f16ce97c9bd..b85a0a4c4f134dd6012d9141244ecf97b4300b65 100644 ---- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -@@ -96,6 +96,34 @@ public class ItemMetaTest extends AbstractTestingBase { - assertThat(itemMeta.hasConflictingEnchant(null), is(false)); - } - -+ // Paper start -+ private void testItemMeta(ItemStack stack) { -+ assertThat("Should not have ItemMeta", stack.hasItemMeta(), is(false)); -+ -+ stack.setDurability((short) 0); -+ assertThat("ItemStack with zero durability should not have ItemMeta", stack.hasItemMeta(), is(false)); -+ -+ stack.setDurability((short) 2); -+ assertThat("ItemStack with non-zero durability should have ItemMeta", stack.hasItemMeta(), is(true)); -+ -+ stack.setLore(java.util.Collections.singletonList("Lore")); -+ assertThat("ItemStack with lore and durability should have ItemMeta", stack.hasItemMeta(), is(true)); -+ -+ stack.setDurability((short) 0); -+ assertThat("ItemStack with lore should have ItemMeta", stack.hasItemMeta(), is(true)); -+ -+ stack.setLore(null); -+ } -+ -+ @Test -+ public void testHasItemMeta() { -+ ItemStack itemStack = new ItemStack(Material.SHEARS); -+ -+ testItemMeta(itemStack); -+ testItemMeta(CraftItemStack.asCraftCopy(itemStack)); -+ } -+ // Paper end -+ - @Test - public void testConflictingStoredEnchantment() { - EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) Bukkit.getItemFactory().getItemMeta(Material.ENCHANTED_BOOK); diff --git a/Unmapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch b/Unmapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch deleted file mode 100644 index a055870972..0000000000 --- a/Unmapped-Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 28 Jul 2018 12:18:27 -0400 -Subject: [PATCH] Ignore Dead Entities in entityList iteration - -A spigot change delays removal of entities from the entity list. -This causes a change in behavior from Vanilla where getEntities type -methods will return dead entities that they shouldn't otherwise be doing. - -This will ensure that dead entities are skipped from iteration since -they shouldn't of been in the list in the first place. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 6943524c2dd8b12691b8ac5b08daee823ce50c3d..b67bd98cca4a06bc0ebaed577195dffc3b3251ec 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -209,6 +209,7 @@ public class PaperCommand extends Command { - Collection entities = world.entitiesById.values(); - entities.forEach(e -> { - MinecraftKey key = e.getMinecraftKey(); -+ if (e.shouldBeRemoved) return; // Paper - - MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); - ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index e39f1ea4eefb0d8e0ca379b116b3699c13bb3f35..9151d84e2f6fb316525c74466589178769fbc8ef 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1309,6 +1309,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - entity.origin = entity.getBukkitEntity().getLocation(); - } - // Paper end -+ entity.shouldBeRemoved = false; // Paper - shouldn't be removed after being re-added - new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - } - -@@ -1321,6 +1322,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.removeEntityFromChunk(entity); - this.entitiesById.remove(entity.getId()); - this.unregisterEntity(entity); -+ entity.shouldBeRemoved = true; // Paper - } - } - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a6f0cde7bdc930abced5063da237bcd27ddcd20f..37497d7ff04b84d4758997970dbdbf88b40d0493 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -276,6 +276,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end -+ public boolean shouldBeRemoved; // Paper - - public float getBukkitYaw() { - return this.yaw; -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index e4accac8f2e8daa58f9b0c279ffcad9347448bb0..79ff96f18c53f3d1ce4a00be2e2d8fe68f77bf54 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -863,6 +863,7 @@ public class Chunk implements IChunkAccess { - - for (int i1 = 0; i1 < l; ++i1) { - Entity entity1 = (Entity) list1.get(i1); -+ if (entity1.shouldBeRemoved) continue; // Paper - - if (entity1.getBoundingBox().c(axisalignedbb) && entity1 != entity) { - if (predicate == null || predicate.test(entity1)) { -@@ -900,6 +901,7 @@ public class Chunk implements IChunkAccess { - - while (iterator.hasNext()) { - T entity = (T) iterator.next(); // CraftBukkit - decompile error -+ if (entity.shouldBeRemoved) continue; // Paper - - if ((entitytypes == null || entity.getEntityType() == entitytypes) && entity.getBoundingBox().c(axisalignedbb) && predicate.test(entity)) { - list.add(entity); -@@ -922,6 +924,7 @@ public class Chunk implements IChunkAccess { - - while (iterator.hasNext()) { - T t0 = (T) iterator.next(); // CraftBukkit - decompile error -+ if (t0.shouldBeRemoved) continue; // Paper - - if (oclass.isInstance(t0) && t0.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.test(t0))) { // Spigot - instance check - list.add(t0); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index a2b3f5106edc8328ba7edd65dedd56e0dc8d33d2..e7103b8021141071712759b1056eccb5e3da93b7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1040,6 +1040,7 @@ public class CraftWorld implements World { - for (Object o : world.entitiesById.values()) { - if (o instanceof net.minecraft.world.entity.Entity) { - net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; -+ if (mcEnt.shouldBeRemoved) continue; // Paper - Entity bukkitEntity = mcEnt.getBukkitEntity(); - - // Assuming that bukkitEntity isn't null -@@ -1059,6 +1060,7 @@ public class CraftWorld implements World { - for (Object o : world.entitiesById.values()) { - if (o instanceof net.minecraft.world.entity.Entity) { - net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; -+ if (mcEnt.shouldBeRemoved) continue; // Paper - Entity bukkitEntity = mcEnt.getBukkitEntity(); - - // Assuming that bukkitEntity isn't null -@@ -1085,6 +1087,7 @@ public class CraftWorld implements World { - - for (Object entity: world.entitiesById.values()) { - if (entity instanceof net.minecraft.world.entity.Entity) { -+ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper - Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); - - if (bukkitEntity == null) { -@@ -1108,6 +1111,7 @@ public class CraftWorld implements World { - - for (Object entity: world.entitiesById.values()) { - if (entity instanceof net.minecraft.world.entity.Entity) { -+ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper - Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); - - if (bukkitEntity == null) { diff --git a/Unmapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch b/Unmapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch deleted file mode 100644 index 55ff4fad22..0000000000 --- a/Unmapped-Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: willies952002 -Date: Thu, 26 Jul 2018 02:25:46 -0400 -Subject: [PATCH] Implement Expanded ArmorStand API - -Add the following: -- Add proper methods for getting and setting items in both hands. Deprecates old methods -- Enable/Disable slot interactions - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 829013f57128cc6c92a45098c6883f2305cf4ea5..e97d25339b37a70f91022dcb021bbe82fb8f5eda 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -430,6 +430,7 @@ public class EntityArmorStand extends EntityLiving { - return enumitemslot; - } - -+ public final boolean isSlotDisabled(EnumItemSlot slot) { return this.d(slot); } // Paper - OBFHELPER - private boolean d(EnumItemSlot enumitemslot) { - return (this.disabledSlots & 1 << enumitemslot.getSlotFlag()) != 0 || enumitemslot.a() == EnumItemSlot.Function.HAND && !this.hasArms(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 6f922e4cbb095439fcd76ee0d0c08bc4160b8107..103f935d9b7a2cbe9639528c587d8ac2e5f14d07 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -1,6 +1,7 @@ - package org.bukkit.craftbukkit.entity; - - import net.minecraft.core.Vector3f; -+import net.minecraft.world.entity.EnumItemSlot; - import net.minecraft.world.entity.decoration.EntityArmorStand; - import org.bukkit.craftbukkit.CraftEquipmentSlot; - import org.bukkit.craftbukkit.CraftServer; -@@ -239,5 +240,78 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public void setCanMove(boolean move) { - getHandle().canMove = move; - } -+ -+ @Override -+ public ItemStack getItem(org.bukkit.inventory.EquipmentSlot slot) { -+ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); -+ return getHandle().getEquipment(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)).asBukkitMirror(); -+ } -+ -+ @Override -+ public void setItem(org.bukkit.inventory.EquipmentSlot slot, ItemStack item) { -+ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); -+ switch (slot) { -+ case HAND: -+ getEquipment().setItemInMainHand(item); -+ return; -+ case OFF_HAND: -+ getEquipment().setItemInOffHand(item); -+ return; -+ case FEET: -+ setBoots(item); -+ return; -+ case LEGS: -+ setLeggings(item); -+ return; -+ case CHEST: -+ setChestplate(item); -+ return; -+ case HEAD: -+ setHelmet(item); -+ return; -+ } -+ throw new UnsupportedOperationException(slot.name()); -+ } -+ -+ @Override -+ public java.util.Set getDisabledSlots() { -+ java.util.Set disabled = new java.util.HashSet<>(); -+ for (org.bukkit.inventory.EquipmentSlot slot : org.bukkit.inventory.EquipmentSlot.values()) { -+ if (this.isSlotDisabled(slot)) { -+ disabled.add(slot); -+ } -+ } -+ return disabled; -+ } -+ -+ @Override -+ public void setDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { -+ int disabled = 0; -+ for (org.bukkit.inventory.EquipmentSlot slot : slots) { -+ if (slot == org.bukkit.inventory.EquipmentSlot.OFF_HAND) continue; -+ EnumItemSlot nmsSlot = org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot); -+ disabled += (1 << nmsSlot.getSlotFlag()) + (1 << (nmsSlot.getSlotFlag() + 8)) + (1 << (nmsSlot.getSlotFlag() + 16)); -+ } -+ getHandle().disabledSlots = disabled; -+ } -+ -+ @Override -+ public void addDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { -+ java.util.Set disabled = getDisabledSlots(); -+ java.util.Collections.addAll(disabled, slots); -+ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); -+ } -+ -+ @Override -+ public void removeDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { -+ java.util.Set disabled = getDisabledSlots(); -+ for (final org.bukkit.inventory.EquipmentSlot slot : slots) disabled.remove(slot); -+ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); -+ } -+ -+ @Override -+ public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { -+ return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch b/Unmapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch deleted file mode 100644 index 3862e6017e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0255-AnvilDamageEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 20 Jul 2018 23:37:03 -0500 -Subject: [PATCH] AnvilDamageEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -index 9658c8206b5bab07838284935e9d5e0879e405f2..ff618bbb3fc4acfce51f5e5e6a504a63e9ad77cd 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -@@ -80,7 +80,16 @@ public class ContainerAnvil extends ContainerAnvilAbstract { - - if (!entityhuman.abilities.canInstantlyBuild && iblockdata.a((Tag) TagsBlock.ANVIL) && entityhuman.getRandom().nextFloat() < 0.12F) { - IBlockData iblockdata1 = BlockAnvil.c(iblockdata); -- -+ // Paper start -+ com.destroystokyo.paper.event.block.AnvilDamagedEvent event = new com.destroystokyo.paper.event.block.AnvilDamagedEvent(getBukkitView(), iblockdata1 != null ? org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(iblockdata1) : null); -+ if (!event.callEvent()) { -+ return; -+ } else if (event.getDamageState() == com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState.BROKEN) { -+ iblockdata1 = null; -+ } else { -+ iblockdata1 = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getDamageState().getMaterial().createBlockData()).getState().set(BlockAnvil.FACING, iblockdata.get(BlockAnvil.FACING)); -+ } -+ // Paper end - if (iblockdata1 == null) { - world.a(blockposition, false); - world.triggerEffect(1029, blockposition, 0); diff --git a/Unmapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch b/Unmapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch deleted file mode 100644 index e848d18de0..0000000000 --- a/Unmapped-Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Mon, 16 Jul 2018 00:05:05 +0300 -Subject: [PATCH] Add TNTPrimeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 97ef4c65c8cc569a99d9697f56bd44d32b151328..51993191e01f55e16667c25b8b57d6a6ddaf493b 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -61,6 +61,7 @@ import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.event.entity.EntityExplodeEvent; - import org.bukkit.event.entity.EntityRegainHealthEvent; - // CraftBukkit end -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - - public class EntityEnderDragon extends EntityInsentient implements IMonster { - -@@ -515,6 +516,11 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - }); - craftBlock.getNMS().dropNaturally((WorldServer) world, blockposition, ItemStack.b); - } -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, explosionSource.getSource().getBukkitEntity()).callEvent()) -+ continue; -+ // Paper end - nmsBlock.wasExploded(world, blockposition, explosionSource); - - this.world.a(blockposition, false); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java -index c22fad0038fdb0769e23db782e3341206fbd80f9..5ef38414d87fbce453e3ab11579c89a8ff089ae0 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java -@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; - import com.google.common.collect.ImmutableMap; - import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - import java.util.Map; - import java.util.Random; - import java.util.function.Function; -@@ -11,6 +12,7 @@ import net.minecraft.SystemUtils; - import net.minecraft.core.BaseBlockPosition; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.item.context.BlockActionContext; - import net.minecraft.world.level.GameRules; -@@ -289,7 +291,7 @@ public class BlockFire extends BlockFireAbstract { - - world.setTypeAndData(blockposition, this.a(world, blockposition, l), 3); - } else { -- world.a(blockposition, false); -+ if(iblockdata.getBlock() != Blocks.TNT) world.a(blockposition, false); // Paper - TNTPrimeEvent - We might be cancelling it below, move the setAir down - } - - Block block = iblockdata.getBlock(); -@@ -297,6 +299,13 @@ public class BlockFire extends BlockFireAbstract { - if (block instanceof BlockTNT) { - BlockTNT blocktnt = (BlockTNT) block; - -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = MCUtil.toBukkitBlock(world, blockposition); -+ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.FIRE, null).callEvent()) { -+ return; -+ } -+ world.setAir(blockposition, false); -+ // Paper end - BlockTNT.a(world, blockposition); - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTNT.java b/src/main/java/net/minecraft/world/level/block/BlockTNT.java -index b5d40898bb4a10b3170cd1f42f1a44de539d53c3..71c46d5042f7e4585b364682cd5464edccdf43f6 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTNT.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTNT.java -@@ -22,6 +22,7 @@ import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.block.state.properties.BlockProperties; - import net.minecraft.world.level.block.state.properties.BlockStateBoolean; - import net.minecraft.world.phys.MovingObjectPositionBlock; -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - - public class BlockTNT extends Block { - -@@ -36,6 +37,11 @@ public class BlockTNT extends Block { - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - if (!iblockdata1.a(iblockdata.getBlock())) { - if (world.isBlockIndirectlyPowered(blockposition)) { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition);; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) -+ return; -+ // Paper end - a(world, blockposition); - world.a(blockposition, false); - } -@@ -46,6 +52,11 @@ public class BlockTNT extends Block { - @Override - public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { - if (world.isBlockIndirectlyPowered(blockposition)) { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition);; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) -+ return; -+ // Paper end - a(world, blockposition); - world.a(blockposition, false); - } -@@ -64,6 +75,12 @@ public class BlockTNT extends Block { - @Override - public void wasExploded(World world, BlockPosition blockposition, Explosion explosion) { - if (!world.isClientSide) { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); -+ org.bukkit.entity.Entity source = explosion.source != null ? explosion.source.getBukkitEntity() : null; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) -+ return; -+ // Paper end - EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, explosion.getSource()); - - entitytntprimed.setFuseTicks((short) (world.random.nextInt(entitytntprimed.getFuseTicks() / 4) + entitytntprimed.getFuseTicks() / 8)); -@@ -92,6 +109,11 @@ public class BlockTNT extends Block { - if (item != Items.FLINT_AND_STEEL && item != Items.FIRE_CHARGE) { - return super.interact(iblockdata, world, blockposition, entityhuman, enumhand, movingobjectpositionblock); - } else { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.ITEM, entityhuman.getBukkitEntity()).callEvent()) -+ return EnumInteractionResult.FAIL; -+ // Paper end - a(world, blockposition, (EntityLiving) entityhuman); - world.setTypeAndData(blockposition, Blocks.AIR.getBlockData(), 11); - if (!entityhuman.isCreative()) { -@@ -121,6 +143,13 @@ public class BlockTNT extends Block { - } - // CraftBukkit end - -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); -+ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.PROJECTILE, iprojectile.getBukkitEntity()).callEvent()) { -+ return; -+ } -+ // Paper end -+ - a(world, blockposition, entity instanceof EntityLiving ? (EntityLiving) entity : null); - world.a(blockposition, false); - } diff --git a/Unmapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch b/Unmapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch deleted file mode 100644 index 79865d178b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 29 Jul 2018 05:02:15 +0100 -Subject: [PATCH] Break up and make tab spam limits configurable - -Due to the changes in 1.13, clients will send a tab completion request -for all bukkit commands in order to factor in the lack of support for -brigadier and provide backwards support in the API. - -Craftbukkit, however; has moved the chat spam limiter to also interact -with the tab completion request, which while good for avoiding abuse, -causes 1.13 clients to easilly be kicked from a server in bukkit due -to this. Removing the spam limit could cause issues for servers, however, -there is no way for servers to manipulate this without blindly cancelling -kick events, which only causes additional complications. This also causes -issues in that the tab spam limit and chat share the same field but different -limits, meaning that a player having typed a long command may be kicked from -the server. - -Splitting the field up and making it configurable allows for server owners -to take the burden of this into their own hand without having to rely on -plugins doing unsafe things. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 77a03abd59db4a43f6f2d59d4c7ef176e782f205..bd508025b771424c942fd856c31d520b6f548082 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -296,4 +296,18 @@ public class PaperConfig { - Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); - } - } -+ -+ public static int tabSpamIncrement = 1; -+ public static int tabSpamLimit = 500; -+ private static void tabSpamLimiters() { -+ tabSpamIncrement = getInt("settings.spam-limiter.tab-spam-increment", tabSpamIncrement); -+ // Older versions used a smaller limit, which is too low for 1.13, we'll bump this up if default -+ if (version < 14) { -+ if (tabSpamIncrement == 10) { -+ set("settings.spam-limiter.tab-spam-increment", 2); -+ tabSpamIncrement = 2; -+ } -+ } -+ tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index ed5e13f668d09dcf56cec8c6269a5fbd93d156bd..b9825537599a8df8d772b2db4d56d5e28cc2bbe9 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -230,6 +230,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit start - multithreaded fields - private volatile int chatThrottle; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); -+ private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits - // CraftBukkit end - private int j; - private final Int2ShortMap k = new Int2ShortOpenHashMap(); -@@ -365,6 +366,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.minecraftServer.getMethodProfiler().exit(); - // CraftBukkit start - for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; -+ if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable - /* Use thread-safe field access instead - if (this.chatThrottle > 0) { - --this.chatThrottle; -@@ -716,7 +718,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - public void a(PacketPlayInTabComplete packetplayintabcomplete) { - // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async - // CraftBukkit start -- if (chatSpamField.addAndGet(this, 1) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { -+ if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { // Paper start - split and make configurable - minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper - return; - } diff --git a/Unmapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch b/Unmapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch deleted file mode 100644 index 32d4088d7a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Thu, 2 Aug 2018 08:44:35 -0500 -Subject: [PATCH] Add hand to bucket events - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 9151d84e2f6fb316525c74466589178769fbc8ef..ecb4cb5df868673e5aa2eec3fdd8618dbea09655 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1657,15 +1657,17 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.getMinecraftServer().getPlayerList().sendAll(new PacketPlayOutSpawnPosition(blockposition, f)); - } - -- public BlockPosition getSpawn() { -- BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); -- -- if (!this.getWorldBorder().a(blockposition)) { -- blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); -- } -- -- return blockposition; -- } -+ // Paper - moved up to World -+ //public BlockPosition getSpawn() { -+ // BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); -+ // -+ // if (!this.getWorldBorder().a(blockposition)) { -+ // blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); -+ // } -+ // -+ // return blockposition; -+ //} -+ // Paper end - - public float v() { - return this.worldData.d(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -index ef48ae4d398a1dd5bc67262ccdb5d8fc6bb2769c..1b43688ad232620410aa924cef02b54630ab1313 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -@@ -88,7 +88,7 @@ public class EntityCow extends EntityAnimal { - - if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) { - // CraftBukkit start - Got milk? -- org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET); -+ org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET, enumhand); // Paper - add enumHand - - if (event.isCancelled()) { - return EnumInteractionResult.PASS; -diff --git a/src/main/java/net/minecraft/world/item/ItemBucket.java b/src/main/java/net/minecraft/world/item/ItemBucket.java -index 4bcac8defeaa146713cce43e04a51c1c9afddb1f..d126f668828e0788e369294c0b376ef52b344f2c 100644 ---- a/src/main/java/net/minecraft/world/item/ItemBucket.java -+++ b/src/main/java/net/minecraft/world/item/ItemBucket.java -@@ -71,7 +71,7 @@ public class ItemBucket extends Item { - if (iblockdata.getBlock() instanceof IFluidSource) { - // CraftBukkit start - FluidType dummyFluid = ((IFluidSource) iblockdata.getBlock()).removeFluid(DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); -- PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) world, entityhuman, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.a()); -+ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) world, entityhuman, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.a(), enumhand); // Paper - add enumhand - - if (event.isCancelled()) { - ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) -@@ -99,7 +99,7 @@ public class ItemBucket extends Item { - iblockdata = world.getType(blockposition); - BlockPosition blockposition2 = iblockdata.getBlock() instanceof IFluidContainer && this.fluidType == FluidTypes.WATER ? blockposition : blockposition1; - -- if (this.a(entityhuman, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack)) { // CraftBukkit -+ if (this.a(entityhuman, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack, enumhand)) { // CraftBukkit // Paper - add enumhand - this.a(world, itemstack, blockposition2); - if (entityhuman instanceof EntityPlayer) { - CriterionTriggers.y.a((EntityPlayer) entityhuman, blockposition2, itemstack); -@@ -124,10 +124,12 @@ public class ItemBucket extends Item { - public void a(World world, ItemStack itemstack, BlockPosition blockposition) {} - - public boolean a(@Nullable EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock) { -- return a(entityhuman, world, blockposition, movingobjectpositionblock, null, null, null); -+ // Paper start - add enumHand -+ return a(entityhuman, world, blockposition, movingobjectpositionblock, null, null, null, null); - } - -- public boolean a(EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock, EnumDirection enumdirection, BlockPosition clicked, ItemStack itemstack) { -+ public boolean a(EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock, EnumDirection enumdirection, BlockPosition clicked, ItemStack itemstack, EnumHand enumhand) { -+ // Paper end - // CraftBukkit end - if (!(this.fluidType instanceof FluidTypeFlowing)) { - return false; -@@ -140,7 +142,7 @@ public class ItemBucket extends Item { - - // CraftBukkit start - if (flag1 && entityhuman != null) { -- PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((WorldServer) world, entityhuman, blockposition, clicked, enumdirection, itemstack); -+ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((WorldServer) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); // Paper - add enumhand - if (event.isCancelled()) { - ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition)); // SPIGOT-4238: needed when looking through entity - ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 -@@ -149,7 +151,7 @@ public class ItemBucket extends Item { - } - // CraftBukkit end - if (!flag1) { -- return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPosition().shift(movingobjectpositionblock.getDirection()), (MovingObjectPositionBlock) null, enumdirection, clicked, itemstack); // CraftBukkit -+ return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPosition().shift(movingobjectpositionblock.getDirection()), (MovingObjectPositionBlock) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit // Paper - add enumhand - } else if (world.getDimensionManager().isNether() && this.fluidType.a((Tag) TagsFluid.WATER)) { - int i = blockposition.getX(); - int j = blockposition.getY(); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 07c5cdd00930a55fd412ef95f71f55ee908189a1..88b1a0235bfc0b41ae1855f8900632e425730d1c 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -277,6 +277,17 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - // Paper end - -+ // Paper start - moved up from WorldServer -+ public BlockPosition getSpawn() { -+ BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); -+ -+ if (!this.getWorldBorder().a(blockposition)) { -+ blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); -+ } -+ -+ return blockposition; -+ } -+ // Paper end - @Override - public boolean s_() { - 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 31358b90784a6e983ff8b687021c721ed5d43eab..338b319910d12cf62ab9c5977257ad1ccec5544a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -234,7 +234,7 @@ public class CraftEventFactory { - public static Entity entityDamage; // For use in EntityDamageByEntityEvent - - // helper methods -- private static boolean canBuild(WorldServer world, Player player, int x, int z) { -+ private static boolean canBuild(World world, Player player, int x, int z) { - int spawnSize = Bukkit.getServer().getSpawnRadius(); - - if (world.getDimensionKey() != World.OVERWORLD) return true; -@@ -424,6 +424,20 @@ public class CraftEventFactory { - } - - private static PlayerEvent getPlayerBucketEvent(boolean isFilling, WorldServer world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item) { -+ // Paper start - add enumHand -+ return getPlayerBucketEvent(isFilling, world, who, changed, clicked, clickedFace, itemstack, item, null); -+ } -+ -+ public static PlayerBucketEmptyEvent callPlayerBucketEmptyEvent(World world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemstack, EnumHand enumHand) { -+ return (PlayerBucketEmptyEvent) getPlayerBucketEvent(false, world, who, changed, clicked, clickedFace, itemstack, Items.BUCKET, enumHand); -+ } -+ -+ public static PlayerBucketFillEvent callPlayerBucketFillEvent(World world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemInHand, net.minecraft.world.item.Item bucket, EnumHand enumHand) { -+ return (PlayerBucketFillEvent) getPlayerBucketEvent(true, world, who, clicked, changed, clickedFace, itemInHand, bucket, enumHand); -+ } -+ -+ private static PlayerEvent getPlayerBucketEvent(boolean isFilling, World world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item, EnumHand enumHand) { -+ // Paper end - Player player = (Player) who.getBukkitEntity(); - CraftItemStack itemInHand = CraftItemStack.asNewCraftStack(item); - Material bucket = CraftMagicNumbers.getMaterial(itemstack.getItem()); -@@ -436,10 +450,10 @@ public class CraftEventFactory { - - PlayerEvent event; - if (isFilling) { -- event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand); -+ event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == EnumHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand - ((PlayerBucketFillEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); - } else { -- event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand); -+ event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == EnumHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand - ((PlayerBucketEmptyEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); - } - diff --git a/Unmapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch b/Unmapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch deleted file mode 100644 index 7c85de6290..0000000000 --- a/Unmapped-Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 3 Aug 2018 00:04:54 -0400 -Subject: [PATCH] MC-135506: Experience should save as Integers - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index 3387a19044b3ee2a1ef549c328c8bc354a5b6d23..a7551e95185895a290be70d501496279eaf884ae 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -218,7 +218,7 @@ public class EntityExperienceOrb extends Entity { - public void saveData(NBTTagCompound nbttagcompound) { - nbttagcompound.setShort("Health", (short) this.e); - nbttagcompound.setShort("Age", (short) this.c); -- nbttagcompound.setShort("Value", (short) this.value); -+ nbttagcompound.setInt("Value", this.value); // Paper - save as Integer - this.savePaperNBT(nbttagcompound); // Paper - } - -@@ -226,7 +226,7 @@ public class EntityExperienceOrb extends Entity { - public void loadData(NBTTagCompound nbttagcompound) { - this.e = nbttagcompound.getShort("Health"); - this.c = nbttagcompound.getShort("Age"); -- this.value = nbttagcompound.getShort("Value"); -+ this.value = nbttagcompound.getInt("Value"); // Paper - load as Integer - this.loadPaperNBT(nbttagcompound); // Paper - } - diff --git a/Unmapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch b/Unmapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch deleted file mode 100644 index 93f74c95ce..0000000000 --- a/Unmapped-Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 22 Nov 2016 00:40:42 -0500 -Subject: [PATCH] Fix client rendering skulls from same user - -See: https://github.com/PaperMC/Paper/issues/1304 - -Changes the UUID sent to client to be based on either -the texture payload, or random. - -This allows the client to render multiple skull textures from the same user, -for when different skins were used when skull was made. - -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index df459918c14589155a574730205cb35d463b8079..5a1187b001004afe22d208bc5d7c288e796e16a6 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -37,6 +37,7 @@ import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.world.item.Item; - import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.level.block.entity.TileEntitySkull; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.Vec3D; - -@@ -311,9 +312,18 @@ public class PacketDataSerializer extends ByteBuf { - if (item.usesDurability() || item.n()) { - // Spigot start - filter - itemstack = itemstack.cloneItemStack(); -- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); -+ //CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported - // Spigot end - nbttagcompound = itemstack.getTag(); -+ // Paper start -+ if (nbttagcompound != null && nbttagcompound.hasKeyOfType("SkullOwner", 10)) { -+ NBTTagCompound owner = nbttagcompound.getCompound("SkullOwner"); -+ if (owner.hasUUID("Id")) { -+ nbttagcompound.setUUID("SkullOwnerOrig", owner.getUUID("Id")); -+ TileEntitySkull.sanitizeUUID(owner); -+ } -+ } -+ // Paper end - } - - this.a(nbttagcompound); -@@ -333,7 +343,16 @@ public class PacketDataSerializer extends ByteBuf { - itemstack.setTag(this.l()); - // CraftBukkit start - if (itemstack.getTag() != null) { -- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); -+ // Paper start - Fix skulls of same owner - restore orig ID since we changed it on send to client -+ if (itemstack.tag.hasKey("SkullOwnerOrig")) { -+ NBTTagCompound owner = itemstack.tag.getCompound("SkullOwner"); -+ if (itemstack.tag.hasKey("SkullOwnerOrig")) { -+ owner.map.put("Id", itemstack.tag.map.get("SkullOwnerOrig")); -+ itemstack.tag.remove("SkullOwnerOrig"); -+ } -+ } -+ // Paper end -+ // CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported - } - // CraftBukkit end - return itemstack; -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index b6b55d5baa5e8a6b69a3e4865c06bc8a4d61a4f3..152118729b1a95dcae05d32aa4289034ba394226 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -15,6 +15,7 @@ import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.protocol.Packet; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.block.entity.TileEntity; -+import net.minecraft.world.level.block.entity.TileEntitySkull; - import net.minecraft.world.level.chunk.BiomeStorage; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkSection; -@@ -69,6 +70,7 @@ public class PacketPlayOutMapChunk implements Packet { - - if (this.f() || (i & 1 << j) != 0) { - NBTTagCompound nbttagcompound = tileentity.b(); -+ if (tileentity instanceof TileEntitySkull) { TileEntitySkull.sanitizeTileEntityUUID(nbttagcompound); } // Paper - - this.g.add(nbttagcompound); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 2ac8b6ac38bdca26cddfb8652f13b0be0c4000fe..24db5dedf8b41b26fa990a7c7317cdb3e89e7fcd 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -114,7 +114,7 @@ public final class ItemStack { - private int g; - @Deprecated - private Item item; -- private NBTTagCompound tag; -+ public NBTTagCompound tag; // Paper private -> public - private boolean j; - private Entity k; - private ShapeDetectorBlock l; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -index 22217f24b4a87f10b6d5a3e37d23a1164af84ace..4f7c014fa609a39cac651ccc6d3397d7edb77d8d 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -@@ -9,6 +9,7 @@ import java.util.UUID; - import javax.annotation.Nullable; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; - import net.minecraft.server.players.UserCache; - import net.minecraft.util.UtilColor; -@@ -154,9 +155,37 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa - @Nullable - @Override - public PacketPlayOutTileEntityData getUpdatePacket() { -- return new PacketPlayOutTileEntityData(this.position, 4, this.b()); -+ return new PacketPlayOutTileEntityData(this.position, 4, sanitizeTileEntityUUID(this.b())); // Paper - } - -+ // Paper start -+ public static NBTTagCompound sanitizeTileEntityUUID(NBTTagCompound cmp) { -+ NBTTagCompound owner = cmp.getCompound("Owner"); -+ if (!owner.isEmpty()) { -+ sanitizeUUID(owner); -+ } -+ return cmp; -+ } -+ -+ public static void sanitizeUUID(NBTTagCompound owner) { -+ NBTTagCompound properties = owner.getCompound("Properties"); -+ NBTTagList list = null; -+ if (!properties.isEmpty()) { -+ list = properties.getList("textures", 10); -+ } -+ -+ if (list != null && !list.isEmpty()) { -+ String textures = ((NBTTagCompound)list.get(0)).getString("Value"); -+ if (textures != null && textures.length() > 3) { -+ UUID uuid = UUID.nameUUIDFromBytes(textures.getBytes()); -+ owner.setUUID("Id", uuid); -+ return; -+ } -+ } -+ owner.setUUID("Id", UUID.randomUUID()); -+ } -+ // Paper end -+ - @Override - public NBTTagCompound b() { - return this.save(new NBTTagCompound()); diff --git a/Unmapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch b/Unmapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch deleted file mode 100644 index 98af37509a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Wed, 8 Aug 2018 15:30:52 -0400 -Subject: [PATCH] Add Early Warning Feature to WatchDog - -Detect when the server has been hung for a long duration, and start printing -thread dumps at an interval until the point of crash. - -This will help diagnose what was going on in that time before the crash. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index bd508025b771424c942fd856c31d520b6f548082..62621562137cba4804f0465c58d25ca2786328e5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -25,6 +25,7 @@ import org.bukkit.configuration.file.YamlConfiguration; - import co.aikar.timings.Timings; - import co.aikar.timings.TimingsManager; - import org.spigotmc.SpigotConfig; -+import org.spigotmc.WatchdogThread; - - public class PaperConfig { - -@@ -297,6 +298,14 @@ public class PaperConfig { - } - } - -+ public static int watchdogPrintEarlyWarningEvery = 5000; -+ public static int watchdogPrintEarlyWarningDelay = 10000; -+ private static void watchdogEarlyWarning() { -+ watchdogPrintEarlyWarningEvery = getInt("settings.watchdog.early-warning-every", 5000); -+ watchdogPrintEarlyWarningDelay = getInt("settings.watchdog.early-warning-delay", 10000); -+ WatchdogThread.doStart(SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash ); -+ } -+ - public static int tabSpamIncrement = 1; - public static int tabSpamLimit = 500; - private static void tabSpamLimiters() { -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 5bbd3bb52b76b8b6cdf90c94bcb29f122f31c543..52c0dd4f2779125116d9dcccc2aef7a11af92945 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1019,6 +1019,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable -+ // Paper start -+ Logger log = Bukkit.getServer().getLogger(); -+ long currentTime = monotonicMillis(); -+ if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) - { -- Logger log = Bukkit.getServer().getLogger(); -+ boolean isLongTimeout = currentTime > lastTick + timeoutTime; -+ // Don't spam early warning dumps -+ if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; -+ if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... -+ lastEarlyWarning = currentTime; -+ if (isLongTimeout) { -+ // Paper end - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper - log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); -@@ -93,29 +108,46 @@ public class WatchdogThread extends Thread - } - } - // Paper end -+ } else -+ { -+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); -+ log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump"); -+ } -+ // Paper end - Different message for short timeout - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // -+ // Paper start - Only print full dump on long timeouts -+ if ( isLongTimeout ) -+ { - log.log( Level.SEVERE, "Entire Thread Dump:" ); - ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); - for ( ThreadInfo thread : threads ) - { - dumpThread( thread, log ); - } -+ } else { -+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---"); -+ } -+ -+ - log.log( Level.SEVERE, "------------------------------" ); - -+ if ( isLongTimeout ) -+ { - if ( restart && !MinecraftServer.getServer().hasStopped() ) - { - RestartCommand.restart(); - } - break; -+ } // Paper end - } - - try - { -- sleep( 10000 ); -+ sleep( 1000 ); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout - } catch ( InterruptedException ex ) - { - interrupt(); diff --git a/Unmapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch b/Unmapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch deleted file mode 100644 index cce5f2ddd2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 10 Aug 2018 22:11:49 -0400 -Subject: [PATCH] Make EnderDragon implement Mob - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java -index 3550eb81b66cad3cdfa41ddb5bb554b541cbbfe1..b537732070c784a97a96ccb77c211646b00580cc 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java -@@ -1,17 +1,18 @@ - package org.bukkit.craftbukkit.entity; - -+import net.minecraft.world.entity.EntityInsentient; // Paper - import net.minecraft.world.entity.EntityLiving; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.ComplexLivingEntity; - --public abstract class CraftComplexLivingEntity extends CraftLivingEntity implements ComplexLivingEntity { -- public CraftComplexLivingEntity(CraftServer server, EntityLiving entity) { -+public abstract class CraftComplexLivingEntity extends CraftMob implements ComplexLivingEntity { // Paper -+ public CraftComplexLivingEntity(CraftServer server, EntityInsentient entity) { // Paper - super(server, entity); - } - - @Override -- public EntityLiving getHandle() { -- return (EntityLiving) entity; -+ public EntityInsentient getHandle() { // Paper -+ return (EntityInsentient) entity; // Paper - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch b/Unmapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch deleted file mode 100644 index 8582eff151..0000000000 --- a/Unmapped-Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: egg82 -Date: Tue, 7 Aug 2018 01:24:23 -0600 -Subject: [PATCH] Use ConcurrentHashMap in JsonList - -This is specifically aimed at fixing #471 - -Using a ConcurrentHashMap because thread safety -The performance benefit of Map over ConcurrentMap is negligabe at best in this scenaio, as most operations will be get and not add or remove -Even without considering the use-case the benefits are still negligable - -Original ideas for the system included an expiration policy and/or handler -The simpler solution was to use a computeIfPresent in the get method -This will simultaneously have an O(1) lookup time and automatically expire any values -Since the get method (nor other similar methods) don't seem to have a critical need to flush the map to disk at any of these points further processing is simply wasteful -Meaning the original function expired values unrelated to the current value without actually having any explicit need to - -The h method was heavily modified to be much more efficient in its processing -Also instead of being called on every get, it's now called just before a save -This will eliminate stale values being flushed to disk - -Modified isEmpty to use the isEmpty() method instead of the slightly confusing size() < 1 -The point of this is readability, but does have a side-benefit of a small microptimization - -Finally, added a couple obfhelpers for the modified code - -diff --git a/src/main/java/net/minecraft/server/players/JsonList.java b/src/main/java/net/minecraft/server/players/JsonList.java -index 52256f72b00d3b868ef1a60e15a3836197c769d9..cd35b833d3047a38be980ee550641e87bd3b9b01 100644 ---- a/src/main/java/net/minecraft/server/players/JsonList.java -+++ b/src/main/java/net/minecraft/server/players/JsonList.java -@@ -12,6 +12,8 @@ import java.io.BufferedReader; - import java.io.BufferedWriter; - import java.io.File; - import java.io.IOException; -+import java.lang.reflect.ParameterizedType; // Paper -+import java.lang.reflect.Type; // Paper - import java.nio.charset.StandardCharsets; - import java.util.Collection; - import java.util.Iterator; -@@ -28,7 +30,22 @@ public abstract class JsonList> { - protected static final Logger LOGGER = LogManager.getLogger(); - private static final Gson b = (new GsonBuilder()).setPrettyPrinting().create(); - private final File c; -- private final Map d = Maps.newHashMap(); -+ // Paper - replace HashMap is ConcurrentHashMap -+ private final Map d = Maps.newConcurrentMap(); private final Map getBackingMap() { return this.d; } // Paper - OBFHELPER -+ private boolean e = true; -+ private static final ParameterizedType f = new ParameterizedType() { -+ public Type[] getActualTypeArguments() { -+ return new Type[]{JsonListEntry.class}; -+ } -+ -+ public Type getRawType() { -+ return List.class; -+ } -+ -+ public Type getOwnerType() { -+ return null; -+ } -+ }; - - public JsonList(File file) { - this.c = file; -@@ -51,8 +68,13 @@ public abstract class JsonList> { - - @Nullable - public V get(K k0) { -- this.g(); -- return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error -+ // Paper start -+ // this.g(); -+ // return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error -+ return (V) this.getBackingMap().computeIfPresent(this.getMappingKey(k0), (k, v) -> { -+ return v.hasExpired() ? null : v; -+ }); -+ // Paper end - } - - public void remove(K k0) { -@@ -81,9 +103,11 @@ public abstract class JsonList> { - // CraftBukkit end - - public boolean isEmpty() { -- return this.d.size() < 1; -+ // return this.d.size() < 1; // Paper -+ return this.getBackingMap().isEmpty(); // Paper - readability is the goal. As an aside, isEmpty() uses only sumCount() and a comparison. size() uses sumCount(), casts, and boolean logic - } - -+ protected final String getMappingKey(K k0) { return a(k0); } // Paper - OBFHELPER - protected String a(K k0) { - return k0.toString(); - } -@@ -92,8 +116,9 @@ public abstract class JsonList> { - return this.d.containsKey(this.a(k0)); - } - -+ private void removeStaleEntries() { g(); } // Paper - OBFHELPER - private void g() { -- List list = Lists.newArrayList(); -+ /*List list = Lists.newArrayList(); - Iterator iterator = this.d.values().iterator(); - - while (iterator.hasNext()) { -@@ -110,8 +135,10 @@ public abstract class JsonList> { - K k0 = (K) iterator.next(); // CraftBukkit - decompile error - - this.d.remove(this.a(k0)); -- } -+ }*/ - -+ this.getBackingMap().values().removeIf(JsonListEntry::hasExpired); -+ // Paper end - } - - protected abstract JsonListEntry a(JsonObject jsonobject); -@@ -121,6 +148,7 @@ public abstract class JsonList> { - } - - public void save() throws IOException { -+ this.removeStaleEntries(); // Paper - remove expired values before saving - JsonArray jsonarray = new JsonArray(); - - this.d.values().stream().map((jsonlistentry) -> { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 80934fc662b33b1c88dd7a3033792d612a7c7930..2299581fa889c0e8ddc6b2cc1d3551d02ff8dc2d 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -618,7 +618,7 @@ public abstract class PlayerList { - } else if (!this.isWhitelisted(gameprofile, event)) { // Paper - //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper - //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted -- } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { -+ } else if (getIPBans().isBanned(socketaddress) && getIPBans().get(socketaddress) != null && !getIPBans().get(socketaddress).hasExpired()) { // Paper - fix NPE with temp ip bans - IpBanEntry ipbanentry = this.l.get(socketaddress); - - chatmessage = new ChatMessage("multiplayer.disconnect.banned_ip.reason", new Object[]{ipbanentry.getReason()}); diff --git a/Unmapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch b/Unmapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch deleted file mode 100644 index eead0924bc..0000000000 --- a/Unmapped-Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 12 Aug 2018 02:33:39 -0400 -Subject: [PATCH] Use a Queue for Queueing Commands - -Lists are bad as Queues mmmkay. - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index a0804c4df6f047cf913ae70970219617052e853f..2d42b863b3fd83d1ee0532d1fcb63861641ec47b 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -75,7 +75,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - - private static final Logger LOGGER = LogManager.getLogger(); - private static final Pattern k = Pattern.compile("^[a-fA-F0-9]{40}$"); -- private final List serverCommandQueue = Collections.synchronizedList(Lists.newArrayList()); -+ private final java.util.Queue serverCommandQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Paper - use a proper queue - private RemoteStatusListener remoteStatusListener; - public final RemoteControlCommandListener remoteControlCommandListener; - private RemoteControlListener remoteControlListener; -@@ -434,8 +434,10 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - - public void handleCommandQueue() { - MinecraftTimings.serverCommandTimer.startTiming(); // Spigot -- while (!this.serverCommandQueue.isEmpty()) { -- ServerCommand servercommand = (ServerCommand) this.serverCommandQueue.remove(0); -+ // Paper start - use proper queue -+ ServerCommand servercommand; -+ while ((servercommand = this.serverCommandQueue.poll()) != null) { -+ // Paper end - - // CraftBukkit start - ServerCommand for preprocessing - ServerCommandEvent event = new ServerCommandEvent(console, servercommand.command); diff --git a/Unmapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/Unmapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch deleted file mode 100644 index 2e0e968f6b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 15 Aug 2018 01:16:34 -0400 -Subject: [PATCH] Ability to get Tile Entities from a chunk without snapshots - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index 32e4e59767587455272e685dfd23f945ba05f976..a8e94f69faec93661dc6ae2efeec44b8bfd2e965 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -3,8 +3,10 @@ package org.bukkit.craftbukkit; - import com.google.common.base.Preconditions; - import com.google.common.base.Predicates; - import java.lang.ref.WeakReference; -+import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; -+import java.util.List; - import java.util.function.Predicate; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; -@@ -130,9 +132,16 @@ public class CraftChunk implements Chunk { - - @Override - public BlockState[] getTileEntities() { -+ // Paper start -+ return getTileEntities(true); -+ } -+ -+ @Override -+ public BlockState[] getTileEntities(boolean useSnapshot) { - if (!isLoaded()) { - getWorld().getChunkAt(x, z); // Transient load for this tick - } -+ // Paper end - int index = 0; - net.minecraft.world.level.chunk.Chunk chunk = getHandle(); - -@@ -144,11 +153,33 @@ public class CraftChunk implements Chunk { - } - - BlockPosition position = (BlockPosition) obj; -- entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(); -+ entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(useSnapshot); // Paper -+ } -+ -+ return entities; -+ } -+ -+ // Paper start -+ @Override -+ public Collection getTileEntities(Predicate blockPredicate, boolean useSnapshot) { -+ Preconditions.checkNotNull(blockPredicate, "blockPredicate"); -+ if (!isLoaded()) { -+ getWorld().getChunkAt(x, z); // Transient load for this tick -+ } -+ net.minecraft.world.level.chunk.Chunk chunk = getHandle(); -+ -+ List entities = new ArrayList<>(); -+ -+ for (BlockPosition position : chunk.tileEntities.keySet()) { -+ Block block = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); -+ if (blockPredicate.test(block)) { -+ entities.add(block.getState(useSnapshot)); -+ } - } - - return entities; - } -+ // Paper end - - @Override - public boolean isLoaded() { diff --git a/Unmapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch b/Unmapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch deleted file mode 100644 index 788112651f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 15 Aug 2018 01:26:09 -0700 -Subject: [PATCH] Allow disabling armour stand ticking - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3562950df4868b1393790b1a1ff1fe0dc589c155..5ab0e7183e48134b7a0f736462516b1a8a333b04 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -384,4 +384,10 @@ public class PaperWorldConfig { - private void armorStandEntityLookups() { - armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); - } -+ -+ public boolean armorStandTick = true; -+ private void armorStandTick() { -+ this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); -+ log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index e97d25339b37a70f91022dcb021bbe82fb8f5eda..8d35240405d7f7245f3c7b0b611973d58fa4384f 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -81,9 +81,16 @@ public class EntityArmorStand extends EntityLiving { - public Vector3f leftLegPose; - public Vector3f rightLegPose; - public boolean canMove = true; // Paper -+ // Paper start - Allow ArmorStands not to tick -+ public boolean canTick = true; -+ public boolean canTickSetByAPI = false; -+ private boolean noTickPoseDirty = false; -+ private boolean noTickEquipmentDirty = false; -+ // Paper end - - public EntityArmorStand(EntityTypes entitytypes, World world) { - super(entitytypes, world); -+ if (world != null) this.canTick = world.paperConfig.armorStandTick; // Paper - armour stand ticking - this.handItems = NonNullList.a(2, ItemStack.b); - this.armorItems = NonNullList.a(4, ItemStack.b); - this.headPose = EntityArmorStand.bj; -@@ -179,6 +186,7 @@ public class EntityArmorStand extends EntityLiving { - this.armorItems.set(enumitemslot.b(), itemstack); - } - -+ this.noTickEquipmentDirty = true; // Paper - Allow equipment to be updated even when tick disabled - } - - @Override -@@ -259,6 +267,7 @@ public class EntityArmorStand extends EntityLiving { - } - - nbttagcompound.set("Pose", this.B()); -+ if (this.canTickSetByAPI) nbttagcompound.setBoolean("Paper.CanTickOverride", this.canTick); // Paper - persist no tick setting - } - - @Override -@@ -290,6 +299,12 @@ public class EntityArmorStand extends EntityLiving { - this.setBasePlate(nbttagcompound.getBoolean("NoBasePlate")); - this.setMarker(nbttagcompound.getBoolean("Marker")); - this.noclip = !this.A(); -+ // Paper start - persist no tick -+ if (nbttagcompound.hasKey("Paper.CanTickOverride")) { -+ this.canTick = nbttagcompound.getBoolean("Paper.CanTickOverride"); -+ this.canTickSetByAPI = true; -+ } -+ // Paper end - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Pose"); - - this.g(nbttagcompound1); -@@ -645,7 +660,29 @@ public class EntityArmorStand extends EntityLiving { - - @Override - public void tick() { -+ // Paper start -+ if (!this.canTick) { -+ if (this.noTickPoseDirty) { -+ this.noTickPoseDirty = false; -+ this.updatePose(); -+ } -+ -+ if (this.noTickEquipmentDirty) { -+ this.noTickEquipmentDirty = false; -+ this.updateEquipment(); -+ } -+ -+ return; -+ } -+ // Paper end -+ - super.tick(); -+ // Paper start - Split into separate method -+ updatePose(); -+ } -+ -+ public void updatePose() { -+ // Paper end - Vector3f vector3f = (Vector3f) this.datawatcher.get(EntityArmorStand.c); - - if (!this.headPose.equals(vector3f)) { -@@ -768,29 +805,36 @@ public class EntityArmorStand extends EntityLiving { - public void setHeadPose(Vector3f vector3f) { - this.headPose = vector3f; - this.datawatcher.set(EntityArmorStand.c, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setBodyPose(Vector3f vector3f) { - this.bodyPose = vector3f; - this.datawatcher.set(EntityArmorStand.d, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setLeftArmPose(Vector3f vector3f) { - this.leftArmPose = vector3f; - this.datawatcher.set(EntityArmorStand.e, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setRightArmPose(Vector3f vector3f) { - this.rightArmPose = vector3f; - this.datawatcher.set(EntityArmorStand.f, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setLeftLegPose(Vector3f vector3f) { -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - this.leftLegPose = vector3f; - this.datawatcher.set(EntityArmorStand.g, vector3f); -+ - } - - public void setRightLegPose(Vector3f vector3f) { -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - this.rightLegPose = vector3f; - this.datawatcher.set(EntityArmorStand.bh, vector3f); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 103f935d9b7a2cbe9639528c587d8ac2e5f14d07..348993f3839f984be65daaf87f3510865e8e4670 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -313,5 +313,16 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { - return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); - } -+ -+ @Override -+ public boolean canTick() { -+ return this.getHandle().canTick; -+ } -+ -+ @Override -+ public void setCanTick(final boolean tick) { -+ this.getHandle().canTick = tick; -+ this.getHandle().canTickSetByAPI = true; -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch b/Unmapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch deleted file mode 100644 index d248d915c6..0000000000 --- a/Unmapped-Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Aug 2018 12:05:12 -0700 -Subject: [PATCH] Optimize BlockPosition helper methods - -Resolves #1338 - -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 370b2c4460d6b52b5ef7da89f5ebf7ef50deb582..4c9ec211470f95d538d1d95c74796190edf99b87 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -121,58 +121,75 @@ public class BlockPosition extends BaseBlockPosition { - - @Override - public BlockPosition up() { -- return this.shift(EnumDirection.UP); -+ return new BlockPosition(this.getX(), this.getY() + 1, this.getZ()); // Paper - Optimize BlockPosition - } - - @Override - public BlockPosition up(int i) { -- return this.shift(EnumDirection.UP, i); -+ return i == 0 ? this : new BlockPosition(this.getX(), this.getY() + i, this.getZ()); // Paper - Optimize BlockPosition - } - - @Override - public BlockPosition down() { -- return this.shift(EnumDirection.DOWN); -+ return new BlockPosition(this.getX(), this.getY() - 1, this.getZ()); // Paper - Optimize BlockPosition - } - - @Override - public BlockPosition down(int i) { -- return this.shift(EnumDirection.DOWN, i); -+ return i == 0 ? this : new BlockPosition(this.getX(), this.getY() - i, this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition north() { -- return this.shift(EnumDirection.NORTH); -+ return new BlockPosition(this.getX(), this.getY(), this.getZ() - 1); // Paper - Optimize BlockPosition - } - - public BlockPosition north(int i) { -- return this.shift(EnumDirection.NORTH, i); -+ return i == 0 ? this : new BlockPosition(this.getX(), this.getY(), this.getZ() - i); // Paper - Optimize BlockPosition - } - - public BlockPosition south() { -- return this.shift(EnumDirection.SOUTH); -+ return new BlockPosition(this.getX(), this.getY(), this.getZ() + 1); // Paper - Optimize BlockPosition - } - - public BlockPosition south(int i) { -- return this.shift(EnumDirection.SOUTH, i); -+ return i == 0 ? this : new BlockPosition(this.getX(), this.getY(), this.getZ() + i); // Paper - Optimize BlockPosition - } - - public BlockPosition west() { -- return this.shift(EnumDirection.WEST); -+ return new BlockPosition(this.getX() - 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition west(int i) { -- return this.shift(EnumDirection.WEST, i); -+ return i == 0 ? this : new BlockPosition(this.getX() - i, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition east() { -- return this.shift(EnumDirection.EAST); -+ return new BlockPosition(this.getX() + 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition east(int i) { -- return this.shift(EnumDirection.EAST, i); -+ return i == 0 ? this : new BlockPosition(this.getX() + i, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition shift(EnumDirection enumdirection) { -- return new BlockPosition(this.getX() + enumdirection.getAdjacentX(), this.getY() + enumdirection.getAdjacentY(), this.getZ() + enumdirection.getAdjacentZ()); -+ // Paper Start - Optimize BlockPosition -+ switch(enumdirection) { -+ case UP: -+ return new BlockPosition(this.getX(), this.getY() + 1, this.getZ()); -+ case DOWN: -+ return new BlockPosition(this.getX(), this.getY() - 1, this.getZ()); -+ case NORTH: -+ return new BlockPosition(this.getX(), this.getY(), this.getZ() - 1); -+ case SOUTH: -+ return new BlockPosition(this.getX(), this.getY(), this.getZ() + 1); -+ case WEST: -+ return new BlockPosition(this.getX() - 1, this.getY(), this.getZ()); -+ case EAST: -+ return new BlockPosition(this.getX() + 1, this.getY(), this.getZ()); -+ default: -+ return new BlockPosition(this.getX() + enumdirection.getAdjacentX(), this.getY() + enumdirection.getAdjacentY(), this.getZ() + enumdirection.getAdjacentZ()); -+ } -+ // Paper End - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/Unmapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch deleted file mode 100644 index 50cfc368af..0000000000 --- a/Unmapped-Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Aug 2018 12:43:16 -0400 -Subject: [PATCH] Restore vanlla default mob-spawn-range and water animals - limit - - -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 0efcbab8f8806aeb8dd8bd6384e5a7cee375d100..34ee684901906fc2ef5f0d09680d2686b813e52b 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -165,7 +165,7 @@ public class SpigotWorldConfig - public byte mobSpawnRange; - private void mobSpawnRange() - { -- mobSpawnRange = (byte) getInt( "mob-spawn-range", 6 ); -+ mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla - log( "Mob Spawn Range: " + mobSpawnRange ); - } - -diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml -index 6474a7fb738e1238cc272afc5ff14b645947e688..6d71bd0db752e6f523364ca5351579b6bcb434c8 100644 ---- a/src/main/resources/configurations/bukkit.yml -+++ b/src/main/resources/configurations/bukkit.yml -@@ -26,7 +26,7 @@ settings: - spawn-limits: - monsters: 70 - animals: 10 -- water-animals: 15 -+ water-animals: 5 - water-ambient: 20 - ambient: 15 - chunk-gc: diff --git a/Unmapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch b/Unmapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch deleted file mode 100644 index c9e838ba63..0000000000 --- a/Unmapped-Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch +++ /dev/null @@ -1,167 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 08:18:42 -0500 -Subject: [PATCH] Slime Pathfinder Events - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -index 01d5b0db9a34d88172e8c7c84c4e1d0b2562217c..40e39e382092b1a8f831da0cea1557a781c98600 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -@@ -45,6 +45,14 @@ import net.minecraft.world.level.levelgen.SeededRandom; - import net.minecraft.world.level.storage.loot.LootTables; - import net.minecraft.world.phys.Vec3D; - -+// Paper start -+import com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent; -+import com.destroystokyo.paper.event.entity.SlimeSwimEvent; -+import com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent; -+import com.destroystokyo.paper.event.entity.SlimeWanderEvent; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Slime; -+// Paper end - // CraftBukkit start - import java.util.ArrayList; - import java.util.List; -@@ -105,6 +113,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { - @Override - public void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); -+ nbttagcompound.setBoolean("Paper.canWander", this.canWander); // Paper - nbttagcompound.setInt("Size", this.getSize() - 1); - nbttagcompound.setBoolean("wasOnGround", this.bp); - } -@@ -119,6 +128,11 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - this.setSize(i + 1, false); - super.loadData(nbttagcompound); -+ // Paper start - check exists before loading or this will be loaded as false -+ if (nbttagcompound.hasKey("Paper.canWander")) { -+ this.canWander = nbttagcompound.getBoolean("Paper.canWander"); -+ } -+ // Paper end - this.bp = nbttagcompound.getBoolean("wasOnGround"); - } - -@@ -398,7 +412,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - @Override - public boolean a() { -- return !this.a.isPassenger(); -+ return !this.a.isPassenger() && this.a.canWander && new SlimeWanderEvent((Slime) this.a.getBukkitEntity()).callEvent(); // Paper - } - - @Override -@@ -419,7 +433,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - @Override - public boolean a() { -- return (this.a.isInWater() || this.a.aQ()) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime; -+ return (this.a.isInWater() || this.a.aQ()) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime && this.a.canWander && new SlimeSwimEvent((Slime) this.a.getBukkitEntity()).callEvent(); // Paper - } - - @Override -@@ -445,14 +459,18 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - @Override - public boolean a() { -- return this.a.getGoalTarget() == null && (this.a.onGround || this.a.isInWater() || this.a.aQ() || this.a.hasEffect(MobEffects.LEVITATION)) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime; -+ return this.a.getGoalTarget() == null && (this.a.onGround || this.a.isInWater() || this.a.aQ() || this.a.hasEffect(MobEffects.LEVITATION)) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime && this.a.canWander; // Paper - add canWander - } - - @Override - public void e() { - if (--this.c <= 0) { - this.c = 40 + this.a.getRandom().nextInt(60); -- this.b = (float) this.a.getRandom().nextInt(360); -+ // Paper start -+ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((Slime) this.a.getBukkitEntity(), (float) this.a.getRandom().nextInt(360)); -+ if (!this.a.canWander || !event.callEvent()) return; -+ this.b = event.getNewYaw(); -+ // Paper end - } - - ((EntitySlime.ControllerMoveSlime) this.a.getControllerMove()).a(this.b, false); -@@ -473,7 +491,15 @@ public class EntitySlime extends EntityInsentient implements IMonster { - public boolean a() { - EntityLiving entityliving = this.a.getGoalTarget(); - -- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable ? false : this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime)); -+ // Paper start -+ if (entityliving == null || !entityliving.isAlive()) { -+ return false; -+ } -+ if (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable) { -+ return false; -+ } -+ return this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime && this.a.canWander && new SlimeTargetLivingEntityEvent((Slime) this.a.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); -+ // Paper end - } - - @Override -@@ -486,7 +512,15 @@ public class EntitySlime extends EntityInsentient implements IMonster { - public boolean b() { - EntityLiving entityliving = this.a.getGoalTarget(); - -- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable ? false : --this.b > 0)); -+ // Paper start -+ if (entityliving == null || !entityliving.isAlive()) { -+ return false; -+ } -+ if (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable) { -+ return false; -+ } -+ return --this.b > 0 && this.a.canWander && new SlimeTargetLivingEntityEvent((Slime) this.a.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); -+ // Paper end - } - - @Override -@@ -494,6 +528,13 @@ public class EntitySlime extends EntityInsentient implements IMonster { - this.a.a((Entity) this.a.getGoalTarget(), 10.0F, 10.0F); - ((EntitySlime.ControllerMoveSlime) this.a.getControllerMove()).a(this.a.yaw, this.a.eL()); - } -+ -+ // Paper start - clear timer and target when goal resets -+ public void d() { -+ this.b = 0; -+ this.a.setGoalTarget(null); -+ } -+ // Paper end - } - - static class ControllerMoveSlime extends ControllerMove { -@@ -552,4 +593,15 @@ public class EntitySlime extends EntityInsentient implements IMonster { - } - } - } -+ -+ // Paper start -+ private boolean canWander = true; -+ public boolean canWander() { -+ return canWander; -+ } -+ -+ public void setWander(boolean canWander) { -+ this.canWander = canWander; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -index aa0ac8d8493dc79dda3fed2ff4d80c5b7a7e3df6..cf5c6030105e56813f526e710e5db0c59d88c99e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -@@ -35,4 +35,14 @@ public class CraftSlime extends CraftMob implements Slime { - public EntityType getType() { - return EntityType.SLIME; - } -+ -+ // Paper start -+ public boolean canWander() { -+ return getHandle().canWander(); -+ } -+ -+ public void setWander(boolean canWander) { -+ getHandle().setWander(canWander); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch b/Unmapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch deleted file mode 100644 index 55ef5bbfa1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 8 Aug 2018 16:33:21 -0600 -Subject: [PATCH] Configurable speed for water flowing over lava - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5ab0e7183e48134b7a0f736462516b1a8a333b04..f280dbff4a09bc611a9ca565c6d697d08801f53b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -390,4 +390,10 @@ public class PaperWorldConfig { - this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); - log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); - } -+ -+ public int waterOverLavaFlowSpeed; -+ private void waterOverLavaFlowSpeed() { -+ waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); -+ log("Water over lava flow speed: " + waterOverLavaFlowSpeed); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFluids.java b/src/main/java/net/minecraft/world/level/block/BlockFluids.java -index 0654c77ab059dea2ad06cb16d07950e153d3f15d..0ed8d938b8fafdb03e01a00a201ba3f8597ac6e9 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFluids.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFluids.java -@@ -23,6 +23,7 @@ import net.minecraft.world.level.material.Fluid; - import net.minecraft.world.level.material.FluidType; - import net.minecraft.world.level.material.FluidTypeFlowing; - import net.minecraft.world.level.material.FluidTypes; -+import net.minecraft.world.level.material.Material; - import net.minecraft.world.level.pathfinder.PathMode; - import net.minecraft.world.level.storage.loot.LootTableInfo; - import net.minecraft.world.phys.shapes.VoxelShape; -@@ -100,11 +101,28 @@ public class BlockFluids extends Block implements IFluidSource { - @Override - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - if (this.a(world, blockposition, iblockdata)) { -- world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.b.a((IWorldReader) world)); -+ world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.getFlowSpeed(world, blockposition)); // Paper - } - - } - -+ // Paper start - Get flow speed. Throttle if its water and flowing adjacent to lava -+ public int getFlowSpeed(World world, BlockPosition blockposition) { -+ if (this.material == Material.WATER) { -+ if ( -+ world.getMaterialIfLoaded(blockposition.north(1)) == Material.LAVA || -+ world.getMaterialIfLoaded(blockposition.south(1)) == Material.LAVA || -+ world.getMaterialIfLoaded(blockposition.west(1)) == Material.LAVA || -+ world.getMaterialIfLoaded(blockposition.east(1)) == Material.LAVA -+ ) { -+ return world.paperConfig.waterOverLavaFlowSpeed; -+ } -+ } -+ return this.b.a(world); -+ } -+ // Paper end -+ -+ - @Override - public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { - if (iblockdata.getFluid().isSource() || iblockdata1.getFluid().isSource()) { -@@ -117,7 +135,7 @@ public class BlockFluids extends Block implements IFluidSource { - @Override - public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { - if (this.a(world, blockposition, iblockdata)) { -- world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.b.a((IWorldReader) world)); -+ world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.getFlowSpeed(world, blockposition)); // Paper - } - - } diff --git a/Unmapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch b/Unmapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch deleted file mode 100644 index 727414b274..0000000000 --- a/Unmapped-Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Thu, 23 Aug 2018 11:45:32 -0400 -Subject: [PATCH] Optimize CraftBlockData Creation - -Avoids a hashmap lookup by cacheing a reference to the CraftBlockData -and cloning it when one is needed. - -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 10f4015b8c36e4e27cf7d0745ba70b8a9e60aff3..57857cc33603cf278de424b540a3d4a5943584c9 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -375,6 +375,14 @@ public abstract class BlockBase { - this.o = blockbase_info.t; - this.p = blockbase_info.u; - } -+ // Paper start - impl cached craft block data, lazy load to fix issue with loading at the wrong time -+ private org.bukkit.craftbukkit.block.data.CraftBlockData cachedCraftBlockData; -+ -+ public org.bukkit.craftbukkit.block.data.CraftBlockData createCraftBlockData() { -+ if (cachedCraftBlockData == null) cachedCraftBlockData = org.bukkit.craftbukkit.block.data.CraftBlockData.createData(getBlockData()); -+ return (org.bukkit.craftbukkit.block.data.CraftBlockData) cachedCraftBlockData.clone(); -+ } -+ // Paper end - - public void a() { - if (!this.getBlock().o()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -index 76fd1fea386d0e65c63c529dba772f01d9888407..ed88da727feddc319a650fb35710d16727f6dbd7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -@@ -509,7 +509,17 @@ public class CraftBlockData implements BlockData { - return craft; - } - -+ // Paper start - optimize creating BlockData to not need a map lookup -+ static { -+ // Initialize cached data for all IBlockData instances after registration -+ Block.REGISTRY_ID.iterator().forEachRemaining(IBlockData::createCraftBlockData); -+ } - public static CraftBlockData fromData(IBlockData data) { -+ return data.createCraftBlockData(); -+ } -+ -+ public static CraftBlockData createData(IBlockData data) { -+ // Paper end - return MAP.getOrDefault(data.getBlock().getClass(), CraftBlockData::new).apply(data); - } - diff --git a/Unmapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch b/Unmapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch deleted file mode 100644 index a37df72fa3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 26 Aug 2018 20:49:50 -0400 -Subject: [PATCH] Optimize RegistryMaterials - -Use larger initial sizes to increase bucket capacity on the BiMap - -BiMap.get was seen to be using a good bit of CPU time. - -diff --git a/src/main/java/net/minecraft/core/RegistryMaterials.java b/src/main/java/net/minecraft/core/RegistryMaterials.java -index f3f6ed83d509d228944d15fc2b2b4cb85b05e366..18f78a5cb03dd9c8349c28b99d013752e32c9167 100644 ---- a/src/main/java/net/minecraft/core/RegistryMaterials.java -+++ b/src/main/java/net/minecraft/core/RegistryMaterials.java -@@ -30,6 +30,7 @@ import net.minecraft.SystemUtils; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.RegistryDataPackCodec; - import net.minecraft.resources.ResourceKey; -+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; // Paper - import org.apache.commons.lang3.Validate; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -38,7 +39,7 @@ public class RegistryMaterials extends IRegistryWritable { - - protected static final Logger LOGGER = LogManager.getLogger(); - private final ObjectList bf = new ObjectArrayList(256); -- private final Object2IntMap bg = new Object2IntOpenCustomHashMap(SystemUtils.k()); -+ private final Reference2IntOpenHashMap bg = new Reference2IntOpenHashMap(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map - private final BiMap bh; - private final BiMap, T> bi; - private final Map bj; -@@ -49,9 +50,9 @@ public class RegistryMaterials extends IRegistryWritable { - public RegistryMaterials(ResourceKey> resourcekey, Lifecycle lifecycle) { - super(resourcekey, lifecycle); - this.bg.defaultReturnValue(-1); -- this.bh = HashBiMap.create(); -- this.bi = HashBiMap.create(); -- this.bj = Maps.newIdentityHashMap(); -+ this.bh = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions -+ this.bi = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions -+ this.bj = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions - this.bk = lifecycle; - } - -@@ -195,7 +196,7 @@ public class RegistryMaterials extends IRegistryWritable { - this.b = collection.toArray(new Object[collection.size()]); - } - -- return SystemUtils.a(this.b, random); -+ return (T) SystemUtils.a(this.b, random); // Paper - Decompile fix - } - - public static Codec> a(ResourceKey> resourcekey, Lifecycle lifecycle, Codec codec) { -@@ -215,7 +216,7 @@ public class RegistryMaterials extends IRegistryWritable { - Iterator iterator = registrymaterials.iterator(); - - while (iterator.hasNext()) { -- T t0 = iterator.next(); -+ T t0 = (T) iterator.next(); // Paper - Decompile fix - - builder.add(new RegistryMaterials.a<>((ResourceKey) registrymaterials.c(t0).get(), registrymaterials.a(t0), t0)); - } diff --git a/Unmapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch b/Unmapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch deleted file mode 100644 index dca07a67d6..0000000000 --- a/Unmapped-Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 25 Aug 2018 19:56:51 -0500 -Subject: [PATCH] Add PhantomPreSpawnEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -index 6053894c5250e9a1a0c4aa2d681127dfd652b34f..6c498d4345df35a411d155799ac56e47c9c48114 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -@@ -161,6 +161,11 @@ public class EntityPhantom extends EntityFlying implements IMonster { - } - - this.setSize(nbttagcompound.getInt("Size")); -+ // Paper start -+ if (nbttagcompound.hasUUID("Paper.SpawningEntity")) { -+ this.spawningEntity = nbttagcompound.getUUID("Paper.SpawningEntity"); -+ } -+ // Paper end - } - - @Override -@@ -170,6 +175,11 @@ public class EntityPhantom extends EntityFlying implements IMonster { - nbttagcompound.setInt("AY", this.d.getY()); - nbttagcompound.setInt("AZ", this.d.getZ()); - nbttagcompound.setInt("Size", this.getSize()); -+ // Paper start -+ if (this.spawningEntity != null) { -+ nbttagcompound.setUUID("Paper.SpawningEntity", this.spawningEntity); -+ } -+ // Paper end - } - - @Override -@@ -216,6 +226,15 @@ public class EntityPhantom extends EntityFlying implements IMonster { - return entitysize.a(f); - } - -+ // Paper start -+ java.util.UUID spawningEntity; -+ -+ public java.util.UUID getSpawningEntity() { -+ return spawningEntity; -+ } -+ public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } -+ // Paper end -+ - class b extends PathfinderGoal { - - private final PathfinderTargetCondition b; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -index cfc32acee1e456a0fda12a5faa4035e29d0c3d5e..96a5a6569387a25b15a06aaab3bd9d033547e875 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -@@ -4,6 +4,7 @@ import java.util.Iterator; - import java.util.Random; - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.stats.ServerStatisticManager; -@@ -73,8 +74,17 @@ public class MobSpawnerPhantom implements MobSpawner { - int k = 1 + random.nextInt(difficultydamagescaler.a().a() + 1); - - for (int l = 0; l < k; ++l) { -+ // Paper start -+ com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(MCUtil.toLocation(worldserver, blockposition1), ((EntityPlayer) entityhuman).getBukkitEntity(), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ break; -+ } -+ continue; -+ } -+ // Paper end - EntityPhantom entityphantom = (EntityPhantom) EntityTypes.PHANTOM.a((World) worldserver); -- -+ entityphantom.setSpawningEntity(entityhuman.getUniqueID()); // Paper - entityphantom.setPositionRotation(blockposition1, 0.0F, 0.0F); - groupdataentity = entityphantom.prepare(worldserver, difficultydamagescaler, EnumMobSpawn.NATURAL, groupdataentity, (NBTTagCompound) null); - worldserver.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -index 6ec7cf434b6586342da3f351466f5c7d72df290d..0cea1d8e23da3a79ef06e43752665a5401b01b4b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -@@ -35,4 +35,10 @@ public class CraftPhantom extends CraftFlying implements Phantom { - public EntityType getType() { - return EntityType.PHANTOM; - } -+ -+ // Paper start -+ public java.util.UUID getSpawningEntity() { -+ return getHandle().getSpawningEntity(); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch b/Unmapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch deleted file mode 100644 index faced7350e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0274-Add-More-Creeper-API.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 11:50:26 -0500 -Subject: [PATCH] Add More Creeper API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -index cbb973e077e04e5221bcc837f434b7093bdbcc2a..b47f71ca1f1c8bbd1a521836d9cb5d676a33ec76 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -@@ -290,7 +290,18 @@ public class EntityCreeper extends EntityMonster { - } - - public void ignite() { -- this.datawatcher.set(EntityCreeper.d, true); -+ // Paper start -+ setIgnited(true); -+ } -+ -+ public void setIgnited(boolean ignited) { -+ if (isIgnited() != ignited) { -+ com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited); -+ if (event.callEvent()) { -+ this.datawatcher.set(EntityCreeper.d, event.isIgnited()); -+ } -+ } -+ // Paper end - } - - public boolean canCauseHeadDrop() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -index 167b8f0c742be07ee0c5d698e04d6e29addda70c..629518d4bb314a1d46e32397b6fb7b90bce94e83 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -@@ -101,4 +101,14 @@ public class CraftCreeper extends CraftMonster implements Creeper { - public EntityType getType() { - return EntityType.CREEPER; - } -+ -+ // Paper start -+ public void setIgnited(boolean ignited) { -+ getHandle().setIgnited(ignited); -+ } -+ -+ public boolean isIgnited() { -+ return getHandle().isIgnited(); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch b/Unmapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch deleted file mode 100644 index 8d4a86803e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 28 Aug 2018 23:04:15 -0400 -Subject: [PATCH] Inventory#removeItemAnySlot - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index 4211bdfb213db0781107c67f1522e9689aa7ecfe..45634fded9916dca35a246921efb87964c860339 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -223,10 +223,16 @@ public class CraftInventory implements Inventory { - } - - private int first(ItemStack item, boolean withAmount) { -+ // Paper start -+ return first(item, withAmount, getStorageContents()); -+ } -+ -+ private int first(ItemStack item, boolean withAmount, ItemStack[] inventory) { -+ // Paper end - if (item == null) { - return -1; - } -- ItemStack[] inventory = getStorageContents(); -+ //ItemStack[] inventory = getStorageContents(); // Paper - let param deal - for (int i = 0; i < inventory.length; i++) { - if (inventory[i] == null) continue; - -@@ -349,6 +355,17 @@ public class CraftInventory implements Inventory { - - @Override - public HashMap removeItem(ItemStack... items) { -+ // Paper start -+ return removeItem(false, items); -+ } -+ -+ @Override -+ public HashMap removeItemAnySlot(ItemStack... items) { -+ return removeItem(true, items); -+ } -+ -+ private HashMap removeItem(boolean searchEntire, ItemStack... items) { -+ // Paper end - Validate.notNull(items, "Items cannot be null"); - HashMap leftover = new HashMap(); - -@@ -359,7 +376,10 @@ public class CraftInventory implements Inventory { - int toDelete = item.getAmount(); - - while (true) { -- int first = first(item, false); -+ // Paper start - Allow searching entire contents -+ ItemStack[] toSearch = searchEntire ? getContents() : getStorageContents(); -+ int first = first(item, false, toSearch); -+ // Paper end - - // Drat! we don't have this type in the inventory - if (first == -1) { diff --git a/Unmapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/Unmapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch deleted file mode 100644 index 9fbcd0bc70..0000000000 --- a/Unmapped-Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 2 Sep 2018 19:34:33 -0700 -Subject: [PATCH] Make CraftWorld#loadChunk(int, int, false) load unconverted - chunks - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index e7103b8021141071712759b1056eccb5e3da93b7..880bbf09f77f59824184c1c9dd1ca3c3df09dae9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -508,7 +508,7 @@ public class CraftWorld implements World { - @Override - public boolean loadChunk(int x, int z, boolean generate) { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -- IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); -+ IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper - - // If generate = false, but the chunk already exists, we will get this back. - if (chunk instanceof ProtoChunkExtension) { diff --git a/Unmapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch b/Unmapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch deleted file mode 100644 index 41b6518aab..0000000000 --- a/Unmapped-Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 3 Sep 2018 18:20:03 -0500 -Subject: [PATCH] Add ray tracing methods to LivingEntity - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index a530f13526ef1ee947adb22e24d5c9afb705a01d..bfbfdeffe668ac3363ffdab2c5cb7b19217f55ea 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3608,6 +3608,23 @@ public abstract class EntityLiving extends Entity { - this.broadcastItemBreak(enumhand == EnumHand.MAIN_HAND ? EnumItemSlot.MAINHAND : EnumItemSlot.OFFHAND); - } - // Paper start -+ public MovingObjectPosition getRayTrace(int maxDistance) { -+ return getRayTrace(maxDistance, RayTrace.FluidCollisionOption.NONE); -+ } -+ -+ public MovingObjectPosition getRayTrace(int maxDistance, RayTrace.FluidCollisionOption fluidCollisionOption) { -+ if (maxDistance < 1 || maxDistance > 120) { -+ throw new IllegalArgumentException("maxDistance must be between 1-120"); -+ } -+ -+ Vec3D start = new Vec3D(locX(), locY() + getHeadHeight(), locZ()); -+ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance); -+ Vec3D end = new Vec3D(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ()); -+ RayTrace raytrace = new RayTrace(start, end, RayTrace.BlockCollisionOption.OUTLINE, fluidCollisionOption, this); -+ -+ return world.rayTrace(raytrace); -+ } -+ - public int shieldBlockingDelay = world.paperConfig.shieldBlockingDelay; - - public int getShieldBlockingDelay() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index a0b006f24829ff9f5754293fbe389d19a14dc001..194583522c53ae838dfc0ccfa49f906c1a628984 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.block.TargetBlockInfo; - import com.google.common.base.Preconditions; - import com.google.common.collect.Sets; - import java.util.ArrayList; -@@ -8,6 +9,7 @@ import java.util.Iterator; - import java.util.List; - import java.util.Set; - import java.util.UUID; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.EnumHand; - import net.minecraft.world.damagesource.DamageSource; -@@ -40,6 +42,8 @@ import net.minecraft.world.entity.projectile.EntityThrownExpBottle; - import net.minecraft.world.entity.projectile.EntityThrownTrident; - import net.minecraft.world.entity.projectile.EntityTippedArrow; - import net.minecraft.world.entity.projectile.EntityWitherSkull; -+import net.minecraft.world.phys.MovingObjectPosition; -+import net.minecraft.world.phys.MovingObjectPositionBlock; - import org.apache.commons.lang.Validate; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -49,6 +53,7 @@ import org.bukkit.attribute.AttributeInstance; - import org.bukkit.block.Block; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.entity.memory.CraftMemoryKey; - import org.bukkit.craftbukkit.entity.memory.CraftMemoryMapper; - import org.bukkit.craftbukkit.inventory.CraftEntityEquipment; -@@ -202,6 +207,28 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return blocks.get(0); - } - -+ // Paper start -+ @Override -+ public Block getTargetBlock(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ MovingObjectPosition rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof MovingObjectPositionBlock) ? null : CraftBlock.at(getHandle().world, ((MovingObjectPositionBlock)rayTrace).getBlockPosition()); -+ } -+ -+ @Override -+ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ MovingObjectPosition rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof MovingObjectPositionBlock) ? null : MCUtil.toBukkitBlockFace(((MovingObjectPositionBlock)rayTrace).getDirection()); -+ } -+ -+ @Override -+ public TargetBlockInfo getTargetBlockInfo(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ MovingObjectPosition rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof MovingObjectPositionBlock) ? null : -+ new TargetBlockInfo(CraftBlock.at(getHandle().world, ((MovingObjectPositionBlock)rayTrace).getBlockPosition()), -+ MCUtil.toBukkitBlockFace(((MovingObjectPositionBlock)rayTrace).getDirection())); -+ } -+ // Paper end -+ - @Override - public List getLastTwoTargetBlocks(Set transparent, int maxDistance) { - return getLineOfSight(transparent, maxDistance, 2); diff --git a/Unmapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch b/Unmapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch deleted file mode 100644 index 74caa5c1f1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 4 Sep 2018 15:02:00 -0500 -Subject: [PATCH] Expose attack cooldown methods for Player - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index b6effe1037f3ae59e6faa5f5d039b6ad54bca5d4..87374174dcbf9e7ee448a1cdd9a3528557c3a2ea 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -2103,6 +2103,7 @@ public abstract class EntityHuman extends EntityLiving { - this.datawatcher.set(EntityHuman.bl, nbttagcompound); - } - -+ public float getCooldownPeriod() { return this.eR(); } // Paper - OBFHELPER - public float eR() { - return (float) (1.0D / this.b(GenericAttributes.ATTACK_SPEED) * 20.0D); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ee3fbf0789b4841a113727397ba6809b2600ff83..a13867ff6d188e7633a91f1e1600116286ac0cd4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2189,6 +2189,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutOpenBook(net.minecraft.world.EnumHand.MAIN_HAND)); - connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutSetSlot(0, slot, inventory.getItemInHand())); - } -+ -+ public float getCooldownPeriod() { -+ return getHandle().getCooldownPeriod(); -+ } -+ -+ public float getCooledAttackStrength(float adjustTicks) { -+ return getHandle().getAttackCooldown(adjustTicks); -+ } -+ -+ public void resetCooldown() { -+ getHandle().resetAttackCooldown(); -+ } - // Paper end - - // Spigot start diff --git a/Unmapped-Spigot-Server-Patches/0279-Improve-death-events.patch b/Unmapped-Spigot-Server-Patches/0279-Improve-death-events.patch deleted file mode 100644 index 3ba91d6451..0000000000 --- a/Unmapped-Spigot-Server-Patches/0279-Improve-death-events.patch +++ /dev/null @@ -1,425 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 21 Aug 2018 01:39:35 +0100 -Subject: [PATCH] Improve death events - -This adds the ability to cancel the death events and to modify the sound -an entity makes when dying. (In cases were no sound should it will be -called with shouldPlaySound set to false allowing unsilencing of silent -entities) - -It makes handling of entity deaths a lot nicer as you no longer need -to listen on the damage event and calculate if the entity dies yourself -to cancel the death which has the benefit of also receiving the dropped -items and experience which is otherwise only properly possible by using -internal code. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index b581a6d3ec06498a4c6db92eb50c5d2b28038131..ae9e0f55ddc194aaef1e57e81863569d9bc7b8f3 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -214,6 +214,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public int ping; - public boolean viewingCredits; - private int containerUpdateDelay; // Paper -+ // Paper start - cancellable death event -+ public boolean queueHealthUpdatePacket = false; -+ public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; -+ // Paper end - - // CraftBukkit start - public String displayName; -@@ -717,6 +721,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - IChatBaseComponent defaultMessage = this.getCombatTracker().getDeathMessage(); - - org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure -+ // Paper start - cancellable death event -+ if (event.isCancelled()) { -+ // make compatible with plugins that might have already set the health in an event listener -+ if (this.getHealth() <= 0) { -+ this.setHealth((float) event.getReviveHealth()); -+ } -+ return; -+ } -+ // Paper end - - // SPIGOT-943 - only call if they have an inventory open - if (this.activeContainer != this.defaultContainer) { -@@ -863,8 +876,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - } - } -- -- return super.damageEntity(damagesource, f); -+ // Paper start - cancellable death events -+ //return super.damageEntity(damagesource, f); -+ this.queueHealthUpdatePacket = true; -+ boolean damaged = super.damageEntity(damagesource, f); -+ this.queueHealthUpdatePacket = false; -+ if (this.queuedHealthUpdatePacket != null) { -+ this.playerConnection.sendPacket(this.queuedHealthUpdatePacket); -+ this.queuedHealthUpdatePacket = null; -+ } -+ return damaged; -+ // Paper end - } - } - } -diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -index f6f79ed9c38206cc6a4feb5504e854a476868aec..7d2b947b3c2b255c01241f2c4a6d7377a0a7c671 100644 ---- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -+++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -@@ -203,6 +203,7 @@ public class CombatTracker { - this.h = null; - } - -+ public final void reset() { this.g(); } // Paper - OBFHELPER - public void g() { - int i = this.f ? 300 : 100; - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 37497d7ff04b84d4758997970dbdbf88b40d0493..28390d3830ed9f3f5d97ab38913e6c40f9943a70 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1538,6 +1538,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - -+ public final void runKillTrigger(Entity entity, int kills, DamageSource damageSource) { this.a(entity, kills, damageSource); } // Paper - OBFHELPER - public void a(Entity entity, int i, DamageSource damagesource) { - if (entity instanceof EntityPlayer) { - CriterionTriggers.c.a((EntityPlayer) entity, this, damagesource); -@@ -2442,6 +2443,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.fallDistance = 0.0F; - } - -+ public final void onKill(WorldServer worldserver, EntityLiving entityLiving) { this.a(worldserver, entityLiving); } // Paper - OBFHELPER - public void a(WorldServer worldserver, EntityLiving entityliving) {} - - protected void l(double d0, double d1, double d2) { -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index bfbfdeffe668ac3363ffdab2c5cb7b19217f55ea..e20acbd904f12e9036cb0565d6aa9a3f63008d43 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -189,7 +189,7 @@ public abstract class EntityLiving extends Entity { - protected float aL; - protected float aM; - protected float aN; -- protected int aO; -+ protected int aO;protected int getKillCount() { return this.aO; } // Paper - OBFHELPER - public float lastDamage; - protected boolean jumping; - public float aR; -@@ -233,6 +233,7 @@ public abstract class EntityLiving extends Entity { - public Set collidableExemptions = new HashSet<>(); - public boolean canPickUpLoot; - public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper -+ public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event - - @Override - public float getBukkitYaw() { -@@ -1348,13 +1349,17 @@ public abstract class EntityLiving extends Entity { - if (knockbackCancelled) this.world.broadcastEntityEffect(this, (byte) 2); // Paper - Disable explosion knockback - if (this.dl()) { - if (!this.f(damagesource)) { -- SoundEffect soundeffect = this.getSoundDeath(); -+ // Paper start - moved into CraftEventFactory event caller for cancellable death event -+ //SoundEffect soundeffect = this.getSoundDeath(); - -- if (flag1 && soundeffect != null) { -- this.playSound(soundeffect, this.getSoundVolume(), this.dH()); -- } -+// if (flag1 && soundeffect != null) { -+// this.playSound(soundeffect, this.getSoundVolume(), this.dH()); -+// } -+ this.silentDeath = !flag1; // mark entity as dying silently -+ // Paper end - - this.die(damagesource); -+ this.silentDeath = false; // Paper - cancellable death event - reset to default - } - } else if (flag1) { - this.c(damagesource); -@@ -1493,6 +1498,7 @@ public abstract class EntityLiving extends Entity { - Entity entity = damagesource.getEntity(); - EntityLiving entityliving = this.getKillingEntity(); - -+ /* // Paper - move down to make death event cancellable - this is the runKillTrigger below - if (this.aO >= 0 && entityliving != null) { - entityliving.a(this, this.aO, damagesource); - } -@@ -1500,20 +1506,40 @@ public abstract class EntityLiving extends Entity { - if (this.isSleeping()) { - this.entityWakeup(); - } -+ */ // Paper - - this.killed = true; -- this.getCombatTracker().g(); -+ // this.getCombatTracker().g(); // Paper - moved into if below as .reset() - if (this.world instanceof WorldServer) { - if (entity != null) { -- entity.a((WorldServer) this.world, this); -+ // entity.a((WorldServer) this.world, this); // Paper - move below into if for onKill - } - -- this.d(damagesource); -+ // Paper start -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.d(damagesource); -+ if (deathEvent == null || !deathEvent.isCancelled()) { -+ if (this.getKillCount() >= 0 && entityliving != null) { -+ entityliving.runKillTrigger(this, this.getKillCount(), damagesource); -+ } -+ if (this.isSleeping()) { -+ this.entityWakeup(); -+ } -+ this.getCombatTracker().reset(); -+ if (entity != null) { -+ entity.onKill((WorldServer) this.world, this); -+ } -+ } else { -+ this.killed = false; -+ this.setHealth((float) deathEvent.getReviveHealth()); -+ } -+ // Paper end - this.f(entityliving); - } - -+ if (this.killed) { // Paper - this.world.broadcastEntityEffect(this, (byte) 3); - this.setPose(EntityPose.DYING); -+ } // Paper - } - } - -@@ -1521,7 +1547,7 @@ public abstract class EntityLiving extends Entity { - if (!this.world.isClientSide) { - boolean flag = false; - -- if (entityliving instanceof EntityWither) { -+ if (this.killed && entityliving instanceof EntityWither) { // Paper - if (this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { - BlockPosition blockposition = this.getChunkCoordinates(); - IBlockData iblockdata = Blocks.WITHER_ROSE.getBlockData(); -@@ -1549,7 +1575,8 @@ public abstract class EntityLiving extends Entity { - } - } - -- protected void d(DamageSource damagesource) { -+ protected org.bukkit.event.entity.EntityDeathEvent processDeath(DamageSource damagesource) { return d(damagesource); } // Paper - OBFHELPER -+ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper - Entity entity = damagesource.getEntity(); - int i; - -@@ -1567,15 +1594,18 @@ public abstract class EntityLiving extends Entity { - this.dropDeathLoot(damagesource, i, flag); - } - // CraftBukkit start - Call death event -- CraftEventFactory.callEntityDeathEvent(this, this.drops); -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper -+ this.postDeathDropItems(deathEvent); // Paper - this.drops = new ArrayList<>(); - // CraftBukkit end - - // this.dropInventory();// CraftBukkit - moved up - this.dropExperience(); -+ return deathEvent; // Paper - } - - protected void dropInventory() {} -+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled - - // CraftBukkit start - public int getExpReward() { -@@ -1660,6 +1690,7 @@ public abstract class EntityLiving extends Entity { - return SoundEffects.ENTITY_GENERIC_HURT; - } - -+ public final SoundEffect getDeathSoundEffect() { return this.getSoundDeath(); } // Paper - OBFHELPER - @Nullable - protected SoundEffect getSoundDeath() { - return SoundEffects.ENTITY_GENERIC_DEATH; -@@ -2196,10 +2227,12 @@ public abstract class EntityLiving extends Entity { - - } - -+ public final float getDeathSoundVolume() { return this.getSoundVolume(); } // Paper - OBFHELPER - protected float getSoundVolume() { - return 1.0F; - } - -+ public float getSoundPitch() { return dH();} // Paper - OBFHELPER - protected float dH() { - return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.5F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -index 77de0706aaa32b565cb1e14754e93a1c4a6e15bd..b7fa24318ef43918b6b10ff4ea8acb960527296e 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -@@ -647,15 +647,25 @@ public class EntityFox extends EntityAnimal { - } - - @Override -- protected void d(DamageSource damagesource) { -- ItemStack itemstack = this.getEquipment(EnumItemSlot.MAINHAND); -+ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper -+ ItemStack itemstack = this.getEquipment(EnumItemSlot.MAINHAND).cloneItemStack(); // Paper -+ -+ // Paper start - Cancellable death event -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.d(damagesource); -+ -+ // Below is code to drop -+ -+ if (deathEvent == null || deathEvent.isCancelled()) { -+ return deathEvent; -+ } -+ // Paper end - - if (!itemstack.isEmpty()) { - this.a(itemstack); - this.setSlot(EnumItemSlot.MAINHAND, ItemStack.b); - } - -- super.d(damagesource); -+ return deathEvent; // Paper - } - - public static boolean a(EntityFox entityfox, EntityLiving entityliving) { -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java -index aa12a0c9f30cd2b8a6de75ff9822843da808ae64..3daa1780a332128bd472fa80039112f3ca9bc4e9 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java -@@ -68,11 +68,19 @@ public abstract class EntityHorseChestedAbstract extends EntityHorseAbstract { - this.a((IMaterial) Blocks.CHEST); - } - -- this.setCarryingChest(false); -+ //this.setCarryingChest(false); // Paper - moved to post death logic - } - - } - -+ // Paper start -+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) { -+ if (this.isCarryingChest() && (event == null || !event.isCancelled())) { -+ this.setCarryingChest(false); -+ } -+ } -+ // Paper end -+ - @Override - public void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 8d35240405d7f7245f3c7b0b611973d58fa4384f..69361caebf0d3caa5195b519a16691705ac5e16a 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -746,7 +746,8 @@ public class EntityArmorStand extends EntityLiving { - - @Override - public void killEntity() { -- org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event -+ org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event // Paper - make cancellable -+ if (event.isCancelled()) return; // Paper - make cancellable - this.die(); - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index a13867ff6d188e7633a91f1e1600116286ac0cd4..6c5075ef2420131aa21b403623a5dfa485ee73e5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1839,7 +1839,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void sendHealthUpdate() { -- getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); -+ // Paper start - cancellable death event -+ //getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); -+ PacketPlayOutUpdateHealth packet = new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel()); -+ if (this.getHandle().queueHealthUpdatePacket) { -+ this.getHandle().queuedHealthUpdatePacket = packet; -+ } else { -+ this.getHandle().playerConnection.sendPacket(packet); -+ } -+ // Paper end - } - - 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 338b319910d12cf62ab9c5977257ad1ccec5544a..b7ebd2e3e919d09ee99997f2358cc0c399d5041b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -18,6 +18,8 @@ import net.minecraft.network.protocol.game.PacketPlayInCloseWindow; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; -+import net.minecraft.sounds.SoundCategory; -+import net.minecraft.sounds.SoundEffect; - import net.minecraft.util.Unit; - import net.minecraft.world.EnumHand; - import net.minecraft.world.IInventory; -@@ -805,9 +807,16 @@ public class CraftEventFactory { - public static EntityDeathEvent callEntityDeathEvent(EntityLiving victim, List drops) { - CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); - EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward()); -+ populateFields(victim, event); // Paper - make cancellable - CraftWorld world = (CraftWorld) entity.getWorld(); - Bukkit.getServer().getPluginManager().callEvent(event); - -+ // Paper start - make cancellable -+ if (event.isCancelled()) { -+ return event; -+ } -+ playDeathSound(victim, event); -+ // Paper end - victim.expToDrop = event.getDroppedExp(); - - for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { -@@ -823,8 +832,15 @@ public class CraftEventFactory { - CraftPlayer entity = victim.getBukkitEntity(); - PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure - event.setKeepInventory(keepInventory); -+ populateFields(victim, event); // Paper - make cancellable - org.bukkit.World world = entity.getWorld(); - Bukkit.getServer().getPluginManager().callEvent(event); -+ // Paper start - make cancellable -+ if (event.isCancelled()) { -+ return event; -+ } -+ playDeathSound(victim, event); -+ // Paper end - - victim.keepLevel = event.getKeepLevel(); - victim.newLevel = event.getNewLevel(); -@@ -841,6 +857,31 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start - helper methods for making death event cancellable -+ // Add information to death event -+ private static void populateFields(EntityLiving victim, EntityDeathEvent event) { -+ event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue()); -+ event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent()); -+ SoundEffect soundEffect = victim.getDeathSoundEffect(); -+ event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null); -+ event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundCategory().name())); -+ event.setDeathSoundVolume(victim.getDeathSoundVolume()); -+ event.setDeathSoundPitch(victim.getSoundPitch()); -+ } -+ -+ // Play death sound manually -+ private static void playDeathSound(EntityLiving victim, EntityDeathEvent event) { -+ if (event.shouldPlayDeathSound() && event.getDeathSound() != null && event.getDeathSoundCategory() != null) { -+ EntityHuman source = victim instanceof EntityHuman ? (EntityHuman) victim : null; -+ double x = event.getEntity().getLocation().getX(); -+ double y = event.getEntity().getLocation().getY(); -+ double z = event.getEntity().getLocation().getZ(); -+ SoundEffect soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound()); -+ SoundCategory soundCategory = SoundCategory.valueOf(event.getDeathSoundCategory().name()); -+ victim.world.playSound(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch()); -+ } -+ } -+ // Paper end - /** - * Server methods - */ diff --git a/Unmapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch b/Unmapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch deleted file mode 100644 index d861678244..0000000000 --- a/Unmapped-Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 8 Sep 2018 18:43:31 -0500 -Subject: [PATCH] Allow chests to be placed with NBT data - - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 24db5dedf8b41b26fa990a7c7317cdb3e89e7fcd..852f9d99001b35f8c97f4445d8f605533d7f6f2f 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -298,6 +298,7 @@ public final class ItemStack { - enuminteractionresult = EnumInteractionResult.FAIL; // cancel placement - // PAIL: Remove this when MC-99075 fixed - placeEvent.getPlayer().updateInventory(); -+ world.capturedTileEntities.clear(); // Paper - clear out tile entities as chests and such will pop loot - // revert back all captured blocks - for (BlockState blockstate : blocks) { - blockstate.update(true, false); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -index 51167d776c710decb0107bebcb35bdf43103772b..111f62d0e5b40e945793b8f504f2c035c0884a6a 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -@@ -327,7 +327,7 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic - // CraftBukkit start - @Override - public boolean isFilteredNBT() { -- return true; -+ return false; // Paper - } - // CraftBukkit end - } diff --git a/Unmapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch b/Unmapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch deleted file mode 100644 index 34e0d63bf2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch +++ /dev/null @@ -1,290 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 9 Sep 2018 13:30:00 -0400 -Subject: [PATCH] Mob Pathfinding API - -Implements Pathfinding API for mobs - -diff --git a/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9a3edd114c4736b1843844c6ca49da7aea7983d1 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java -@@ -0,0 +1,141 @@ -+package com.destroystokyo.paper.entity; -+ -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.level.pathfinder.PathEntity; -+import net.minecraft.world.level.pathfinder.PathPoint; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.entity.CraftLivingEntity; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Mob; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.util.ArrayList; -+import java.util.List; -+ -+public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder { -+ -+ private final EntityInsentient entity; -+ -+ public PaperPathfinder(EntityInsentient entity) { -+ this.entity = entity; -+ } -+ -+ @Override -+ public Mob getEntity() { -+ return entity.getBukkitMob(); -+ } -+ -+ @Override -+ public void stopPathfinding() { -+ entity.getNavigation().stopPathfinding(); -+ } -+ -+ @Override -+ public boolean hasPath() { -+ return entity.getNavigation().getPathEntity() != null; -+ } -+ -+ @Nullable -+ @Override -+ public PathResult getCurrentPath() { -+ PathEntity path = entity.getNavigation().getPathEntity(); -+ return path != null ? new PaperPathResult(path) : null; -+ } -+ -+ @Nullable -+ @Override -+ public PathResult findPath(Location loc) { -+ Validate.notNull(loc, "Location can not be null"); -+ PathEntity path = entity.getNavigation().calculateDestination(loc.getX(), loc.getY(), loc.getZ()); -+ return path != null ? new PaperPathResult(path) : null; -+ } -+ -+ @Nullable -+ @Override -+ public PathResult findPath(LivingEntity target) { -+ Validate.notNull(target, "Target can not be null"); -+ PathEntity path = entity.getNavigation().calculateDestination(((CraftLivingEntity) target).getHandle()); -+ return path != null ? new PaperPathResult(path) : null; -+ } -+ -+ @Override -+ public boolean moveTo(@Nonnull PathResult path, double speed) { -+ Validate.notNull(path, "PathResult can not be null"); -+ PathEntity pathEntity = ((PaperPathResult) path).path; -+ return entity.getNavigation().setDestination(pathEntity, speed); -+ } -+ -+ @Override -+ public boolean canOpenDoors() { -+ return entity.getNavigation().getPathfinder().getPathfinder().shouldOpenDoors(); -+ } -+ -+ @Override -+ public void setCanOpenDoors(boolean canOpenDoors) { -+ entity.getNavigation().getPathfinder().getPathfinder().setShouldOpenDoors(canOpenDoors); -+ } -+ -+ @Override -+ public boolean canPassDoors() { -+ return entity.getNavigation().getPathfinder().getPathfinder().shouldPassDoors(); -+ } -+ -+ @Override -+ public void setCanPassDoors(boolean canPassDoors) { -+ entity.getNavigation().getPathfinder().getPathfinder().setShouldPassDoors(canPassDoors); -+ } -+ -+ @Override -+ public boolean canFloat() { -+ return entity.getNavigation().getPathfinder().getPathfinder().shouldFloat(); -+ } -+ -+ @Override -+ public void setCanFloat(boolean canFloat) { -+ entity.getNavigation().getPathfinder().getPathfinder().setShouldFloat(canFloat); -+ } -+ -+ public class PaperPathResult implements com.destroystokyo.paper.entity.PaperPathfinder.PathResult { -+ -+ private final PathEntity path; -+ PaperPathResult(PathEntity path) { -+ this.path = path; -+ } -+ -+ @Nullable -+ @Override -+ public Location getFinalPoint() { -+ PathPoint point = path.getFinalPoint(); -+ return point != null ? toLoc(point) : null; -+ } -+ -+ @Override -+ public List getPoints() { -+ List points = new ArrayList<>(); -+ for (PathPoint point : path.getPoints()) { -+ points.add(toLoc(point)); -+ } -+ return points; -+ } -+ -+ @Override -+ public int getNextPointIndex() { -+ return path.getNextIndex(); -+ } -+ -+ @Nullable -+ @Override -+ public Location getNextPoint() { -+ if (!path.hasNext()) { -+ return null; -+ } -+ return toLoc(path.getPoints().get(path.getNextIndex())); -+ } -+ } -+ -+ private Location toLoc(PathPoint point) { -+ return new Location(entity.world.getWorld(), point.getX(), point.getY(), point.getZ()); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index d134333c736dc1ee1c722d680d7a9c22c1b265bd..06d05b511d623d0247d44989bee85b383a8fb52f 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -100,7 +100,7 @@ public abstract class NavigationAbstract { - } - - @Nullable -- public final PathEntity a(double d0, double d1, double d2, int i) { -+ public final PathEntity calculateDestination(double d0, double d1, double d2) { return a(d0, d1, d2, 0); } public final PathEntity a(double d0, double d1, double d2, int i) { // Paper - OBFHELPER - return this.a(new BlockPosition(d0, d1, d2), i); - } - -@@ -125,7 +125,7 @@ public abstract class NavigationAbstract { - } - - @Nullable -- public PathEntity a(Entity entity, int i) { -+ public final PathEntity calculateDestination(Entity entity) { return a(entity, 0); } public PathEntity a(Entity entity, int i) { - return this.a(ImmutableSet.of(entity.getChunkCoordinates()), entity, 16, true, i); // Paper - } - -@@ -190,6 +190,7 @@ public abstract class NavigationAbstract { - return pathentity != null && this.a(pathentity, d0); - } - -+ public boolean setDestination(@Nullable PathEntity pathentity, double speed) { return a(pathentity, speed); } // Paper - OBFHELPER - public boolean a(@Nullable PathEntity pathentity, double d0) { - if (pathentity == null) { - this.c = null; -@@ -217,7 +218,7 @@ public abstract class NavigationAbstract { - } - } - -- @Nullable -+ @Nullable public PathEntity getPathEntity() { return k(); } @Nullable // Paper - OBFHELPER - public PathEntity k() { - return this.c; - } -@@ -341,6 +342,7 @@ public abstract class NavigationAbstract { - return !this.m(); - } - -+ public void stopPathfinding() { o(); } // Paper - OBFHELPER - public void o() { - this.c = null; - } -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java b/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java -index 606027de777750f6d2ab0d7f1ef387ed4f0c6092..81c3cb9da3f901d2bcf384f7113bdc5c60f9962f 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java -@@ -8,13 +8,14 @@ import net.minecraft.world.phys.Vec3D; - - public class PathEntity { - -- private final List a; -+ private final List a; public List getPoints() { return a; } // Paper - OBFHELPER - private PathPoint[] b = new PathPoint[0]; - private PathPoint[] c = new PathPoint[0]; -- private int e; -+ private int e; public int getNextIndex() { return this.e; } // Paper - OBFHELPER - private final BlockPosition f; - private final float g; - private final boolean h; -+ public boolean hasNext() { return getNextIndex() < getPoints().size(); } // Paper - - public PathEntity(List list, BlockPosition blockposition, boolean flag) { - this.a = list; -@@ -36,7 +37,7 @@ public class PathEntity { - } - - @Nullable -- public PathPoint d() { -+ public PathPoint getFinalPoint() { return d(); } @Nullable public PathPoint d() { // Paper - OBFHELPER - return !this.a.isEmpty() ? (PathPoint) this.a.get(this.a.size() - 1) : null; - } - -@@ -84,7 +85,7 @@ public class PathEntity { - return this.a(entity, this.e); - } - -- public BlockPosition g() { -+ public BlockPosition getNext() { return g(); } public BlockPosition g() { // Paper - OBFHELPER - return ((PathPoint) this.a.get(this.e)).a(); - } - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java b/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java -index 43cc9430972a18cbf03a590d576ed200e3836017..c260b0ca70cb18811158761c574aee9c3166da28 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java -@@ -5,9 +5,9 @@ import net.minecraft.util.MathHelper; - - public class PathPoint { - -- public final int a; -- public final int b; -- public final int c; -+ public final int a; public final int getX() { return a; } // Paper - OBFHELPER -+ public final int b; public final int getY() { return b; } // Paper - OBFHELPER -+ public final int c; public final int getZ() { return c; } // Paper - OBFHELPER - private final int m; - public int d = -1; - public float e; -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java -index f2080bd50db04af6eabec4b4b757d6dadfb1a2f5..88be03bd77656235322522c3782b9f9a878b86b1 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java -@@ -16,9 +16,9 @@ public abstract class PathfinderAbstract { - protected int d; - protected int e; - protected int f; -- protected boolean g; -- protected boolean h; -- protected boolean i; -+ protected boolean g; public boolean shouldPassDoors() { return g; } public void setShouldPassDoors(boolean b) { g = b; } // Paper - obfhelper -+ protected boolean h; public boolean shouldOpenDoors() { return h; } public void setShouldOpenDoors(boolean b) { h = b; } // Paper - obfhelper -+ protected boolean i; public boolean shouldFloat() { return i; } public void setShouldFloat(boolean b) { i = b; } // Paper - obfhelper - - public PathfinderAbstract() {} - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index eb275ac45def34d5bb1ed696b4f6a4d53d282ab3..28a4e90130f51fd2fda7003fde5b4d0a410e1aef 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -12,8 +12,11 @@ import org.bukkit.loot.LootTable; - public abstract class CraftMob extends CraftLivingEntity implements Mob { - public CraftMob(CraftServer server, EntityInsentient entity) { - super(server, entity); -+ paperPathfinder = new com.destroystokyo.paper.entity.PaperPathfinder(entity); // Paper - } - -+ private final com.destroystokyo.paper.entity.PaperPathfinder paperPathfinder; // Paper -+ @Override public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { return paperPathfinder; } // Paper - @Override - public void setTarget(LivingEntity target) { - EntityInsentient entity = getHandle(); diff --git a/Unmapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch b/Unmapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch deleted file mode 100644 index 3b7bb307af..0000000000 --- a/Unmapped-Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 10 Sep 2018 23:36:16 -0400 -Subject: [PATCH] Prevent chunk loading from Fluid Flowing - - -diff --git a/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java b/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java -index 2f0f8a44d808875d70123a63487ce1ebe02f53a9..6bb4ec00e40795ced73648fefcd1f5027e0113cd 100644 ---- a/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java -+++ b/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java -@@ -176,7 +176,8 @@ public abstract class FluidTypeFlowing extends FluidType { - EnumDirection enumdirection = (EnumDirection) entry.getKey(); - Fluid fluid1 = (Fluid) entry.getValue(); - BlockPosition blockposition1 = blockposition.shift(enumdirection); -- IBlockData iblockdata1 = generatoraccess.getType(blockposition1); -+ IBlockData iblockdata1 = generatoraccess.getTypeIfLoaded(blockposition1); // Paper -+ if (iblockdata1 == null) continue; // Paper - - if (this.a(generatoraccess, blockposition, iblockdata, enumdirection, blockposition1, iblockdata1, generatoraccess.getFluid(blockposition1), fluid1.getType())) { - // CraftBukkit start -@@ -203,7 +204,8 @@ public abstract class FluidTypeFlowing extends FluidType { - while (iterator.hasNext()) { - EnumDirection enumdirection = (EnumDirection) iterator.next(); - BlockPosition blockposition1 = blockposition.shift(enumdirection); -- IBlockData iblockdata1 = iworldreader.getType(blockposition1); -+ IBlockData iblockdata1 = iworldreader.getTypeIfLoaded(blockposition1); // Paper -+ if (iblockdata1 == null) continue; // Paper - Fluid fluid = iblockdata1.getFluid(); - - if (fluid.getType().a((FluidType) this) && this.a(enumdirection, (IBlockAccess) iworldreader, blockposition, iblockdata, blockposition1, iblockdata1)) { -@@ -320,11 +322,18 @@ public abstract class FluidTypeFlowing extends FluidType { - if (enumdirection1 != enumdirection) { - BlockPosition blockposition2 = blockposition.shift(enumdirection1); - short short0 = a(blockposition1, blockposition2); -- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (k) -> { -- IBlockData iblockdata1 = iworldreader.getType(blockposition2); -+ // Paper start - avoid loading chunks -+ Pair pair = short2objectmap.get(short0); -+ if (pair == null) { -+ IBlockData iblockdatax = iworldreader.getTypeIfLoaded(blockposition2); -+ if (iblockdatax == null) { -+ continue; -+ } - -- return Pair.of(iblockdata1, iblockdata1.getFluid()); -- }); -+ pair = Pair.of(iblockdatax, iblockdatax.getFluid()); -+ short2objectmap.put(short0, pair); -+ } -+ // Paper end - IBlockData iblockdata1 = (IBlockData) pair.getFirst(); - Fluid fluid = (Fluid) pair.getSecond(); - -@@ -396,11 +405,16 @@ public abstract class FluidTypeFlowing extends FluidType { - EnumDirection enumdirection = (EnumDirection) iterator.next(); - BlockPosition blockposition1 = blockposition.shift(enumdirection); - short short0 = a(blockposition, blockposition1); -- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (j) -> { -- IBlockData iblockdata1 = iworldreader.getType(blockposition1); -- -- return Pair.of(iblockdata1, iblockdata1.getFluid()); -- }); -+ // Paper start -+ Pair pair = (Pair) short2objectmap.get(short0); -+ if (pair == null) { -+ IBlockData iblockdatax = iworldreader.getTypeIfLoaded(blockposition1); -+ if (iblockdatax == null) continue; -+ -+ pair = Pair.of(iblockdatax, iblockdatax.getFluid()); -+ short2objectmap.put(short0, pair); -+ } -+ // Paper end - IBlockData iblockdata1 = (IBlockData) pair.getFirst(); - Fluid fluid = (Fluid) pair.getSecond(); - Fluid fluid1 = this.a(iworldreader, blockposition1, iblockdata1); diff --git a/Unmapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/Unmapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch deleted file mode 100644 index 22d4952f48..0000000000 --- a/Unmapped-Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch +++ /dev/null @@ -1,446 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Wed, 12 Sep 2018 18:53:55 +0300 -Subject: [PATCH] Implement an API for CanPlaceOn and CanDestroy NBT values - - -diff --git a/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java b/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java -index 7e53d8b787c42f8592140f7de8974bc63e5149b2..d72b800e5f03422d0b2518980b1955ec7d2b08e8 100644 ---- a/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java -+++ b/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java -@@ -57,7 +57,7 @@ public class ArgumentBlock { - private final boolean j; - private final Map, Comparable> k = Maps.newLinkedHashMap(); // CraftBukkit - stable - private final Map l = Maps.newHashMap(); -- private MinecraftKey m = new MinecraftKey(""); -+ private MinecraftKey m = new MinecraftKey(""); public final MinecraftKey getBlockKey() { return this.m; } // Paper - OBFHELPER - private BlockStateList n; - private IBlockData o; - @Nullable -@@ -86,11 +86,13 @@ public class ArgumentBlock { - return this.p; - } - -+ public final @Nullable MinecraftKey getTagKey() { return d(); } // Paper - OBFHELPER - @Nullable - public MinecraftKey d() { - return this.q; - } - -+ public final ArgumentBlock parse(boolean parseTile) throws CommandSyntaxException { return this.a(parseTile); } // Paper - OBFHELPER - public ArgumentBlock a(boolean flag) throws CommandSyntaxException { - this.s = this::l; - if (this.i.canRead() && this.i.peek() == '#') { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 7f790c484fec77e1d1f1dc6abe0daa19d009ae46..8f8dccd6fb2e49d65383d6e8f3fc5ffbabd2b7a5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -39,12 +39,14 @@ import java.util.logging.Level; - import java.util.logging.Logger; - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -+import net.minecraft.commands.arguments.blocks.ArgumentBlock; - import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTCompressedStreamTools; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.chat.ChatComponentText; -+import net.minecraft.resources.MinecraftKey; - import net.minecraft.world.entity.EnumItemSlot; - import net.minecraft.world.item.ItemBlock; - import org.apache.commons.codec.binary.Base64; -@@ -84,6 +86,12 @@ import org.bukkit.persistence.PersistentDataContainer; - import static org.spigotmc.ValidateUtils.*; - // Spigot end - -+// Paper start -+import com.destroystokyo.paper.Namespaced; -+import com.destroystokyo.paper.NamespacedTag; -+import java.util.Collections; -+// Paper end -+ - /** - * Children must include the following: - * -@@ -267,6 +275,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Specific(Specific.To.NBT) - static final ItemMetaKey BLOCK_DATA = new ItemMetaKey("BlockStateTag"); - static final ItemMetaKey BUKKIT_CUSTOM_TAG = new ItemMetaKey("PublicBukkitValues"); -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ static final ItemMetaKey CAN_DESTROY = new ItemMetaKey("CanDestroy"); -+ static final ItemMetaKey CAN_PLACE_ON = new ItemMetaKey("CanPlaceOn"); -+ // Paper end - - // We store the raw original JSON representation of all text data. See SPIGOT-5063, SPIGOT-5656, SPIGOT-5304 - private String displayName; -@@ -280,6 +292,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - private int hideFlag; - private boolean unbreakable; - private int damage; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ private Set placeableKeys = Sets.newHashSet(); -+ private Set destroyableKeys = Sets.newHashSet(); -+ // Paper end - - private static final Set HANDLED_TAGS = Sets.newHashSet(); - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); -@@ -317,6 +333,15 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - this.hideFlag = meta.hideFlag; - this.unbreakable = meta.unbreakable; - this.damage = meta.damage; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (meta.hasPlaceableKeys()) { -+ this.placeableKeys = new java.util.HashSet<>(meta.placeableKeys); -+ } -+ -+ if (meta.hasDestroyableKeys()) { -+ this.destroyableKeys = new java.util.HashSet<>(meta.destroyableKeys); -+ } -+ // Paper end - this.unhandledTags.putAll(meta.unhandledTags); - this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw()); - -@@ -380,6 +405,31 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - persistentDataContainer.put(key, compound.get(key)); - } - } -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (tag.hasKey(CAN_DESTROY.NBT)) { -+ NBTTagList list = tag.getList(CAN_DESTROY.NBT, CraftMagicNumbers.NBT.TAG_STRING); -+ for (int i = 0; i < list.size(); i++) { -+ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); -+ if (namespaced == null) { -+ continue; -+ } -+ -+ this.destroyableKeys.add(namespaced); -+ } -+ } -+ -+ if (tag.hasKey(CAN_PLACE_ON.NBT)) { -+ NBTTagList list = tag.getList(CAN_PLACE_ON.NBT, CraftMagicNumbers.NBT.TAG_STRING); -+ for (int i = 0; i < list.size(); i++) { -+ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); -+ if (namespaced == null) { -+ continue; -+ } -+ -+ this.placeableKeys.add(namespaced); -+ } -+ } -+ // Paper end - - Set keys = tag.getKeys(); - for (String key : keys) { -@@ -518,6 +568,34 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - setDamage(damage); - } - -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ Iterable canPlaceOnSerialized = SerializableMeta.getObject(Iterable.class, map, CAN_PLACE_ON.BUKKIT, true); -+ if (canPlaceOnSerialized != null) { -+ for (Object canPlaceOnElement : canPlaceOnSerialized) { -+ String canPlaceOnRaw = (String) canPlaceOnElement; -+ Namespaced value = this.deserializeNamespaced(canPlaceOnRaw); -+ if (value == null) { -+ continue; -+ } -+ -+ this.placeableKeys.add(value); -+ } -+ } -+ -+ Iterable canDestroySerialized = SerializableMeta.getObject(Iterable.class, map, CAN_DESTROY.BUKKIT, true); -+ if (canDestroySerialized != null) { -+ for (Object canDestroyElement : canDestroySerialized) { -+ String canDestroyRaw = (String) canDestroyElement; -+ Namespaced value = this.deserializeNamespaced(canDestroyRaw); -+ if (value == null) { -+ continue; -+ } -+ -+ this.destroyableKeys.add(value); -+ } -+ } -+ // Paper end -+ - String internal = SerializableMeta.getString(map, "internal", true); - if (internal != null) { - ByteArrayInputStream buf = new ByteArrayInputStream(Base64.decodeBase64(internal)); -@@ -646,6 +724,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - if (hasDamage()) { - itemTag.setInt(DAMAGE.NBT, damage); - } -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (hasPlaceableKeys()) { -+ List items = this.placeableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ itemTag.set(CAN_PLACE_ON.NBT, createNonComponentStringList(items)); -+ } -+ -+ if (hasDestroyableKeys()) { -+ List items = this.destroyableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ itemTag.set(CAN_DESTROY.NBT, createNonComponentStringList(items)); -+ } -+ // Paper end - - for (Map.Entry e : unhandledTags.entrySet()) { - itemTag.set(e.getKey(), e.getValue()); -@@ -662,6 +757,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -+ // Paper start -+ static NBTTagList createNonComponentStringList(List list) { -+ if (list == null || list.isEmpty()) { -+ return null; -+ } -+ -+ NBTTagList tagList = new NBTTagList(); -+ for (String value : list) { -+ tagList.add(NBTTagString.a(value)); // Paper - NBTTagString.of(String str) -+ } -+ -+ return tagList; -+ } -+ // Paper end -+ - NBTTagList createStringList(List list) { - if (list == null) { - return null; -@@ -745,7 +855,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - - @Overridden - boolean isEmpty() { -- return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); -+ return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers() || hasPlaceableKeys() || hasDestroyableKeys()); // Paper - Implement an API for CanPlaceOn and CanDestroy NBT values - } - - // Paper start -@@ -1169,7 +1279,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - && (this.hideFlag == that.hideFlag) - && (this.isUnbreakable() == that.isUnbreakable()) - && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) -- && (this.version == that.version); -+ && (this.version == that.version) -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ && (this.hasPlaceableKeys() ? that.hasPlaceableKeys() && this.placeableKeys.equals(that.placeableKeys) : !that.hasPlaceableKeys()) -+ && (this.hasDestroyableKeys() ? that.hasDestroyableKeys() && this.destroyableKeys.equals(that.destroyableKeys) : !that.hasDestroyableKeys()); -+ // Paper end - } - - /** -@@ -1204,6 +1318,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - hash = 61 * hash + (hasDamage() ? this.damage : 0); - hash = 61 * hash + (hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); - hash = 61 * hash + version; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ hash = 61 * hash + (hasPlaceableKeys() ? this.placeableKeys.hashCode() : 0); -+ hash = 61 * hash + (hasDestroyableKeys() ? this.destroyableKeys.hashCode() : 0); -+ // Paper end - return hash; - } - -@@ -1228,6 +1346,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - clone.unbreakable = this.unbreakable; - clone.damage = this.damage; - clone.version = this.version; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (this.placeableKeys != null) { -+ clone.placeableKeys = Sets.newHashSet(this.placeableKeys); -+ } -+ if (this.destroyableKeys != null) { -+ clone.destroyableKeys = Sets.newHashSet(this.destroyableKeys); -+ } -+ // Paper end - return clone; - } catch (CloneNotSupportedException e) { - throw new Error(e); -@@ -1285,6 +1411,24 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - builder.put(DAMAGE.BUKKIT, damage); - } - -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (hasPlaceableKeys()) { -+ List cerealPlaceable = this.placeableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ builder.put(CAN_PLACE_ON.BUKKIT, cerealPlaceable); -+ } -+ -+ if (hasDestroyableKeys()) { -+ List cerealDestroyable = this.destroyableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ builder.put(CAN_DESTROY.BUKKIT, cerealDestroyable); -+ } -+ // Paper end -+ - final Map internalTags = new HashMap(unhandledTags); - serializeInternal(internalTags); - if (!internalTags.isEmpty()) { -@@ -1449,6 +1593,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - CraftMetaArmorStand.SHOW_ARMS.NBT, - CraftMetaArmorStand.SMALL.NBT, - CraftMetaArmorStand.MARKER.NBT, -+ CAN_DESTROY.NBT, -+ CAN_PLACE_ON.NBT, - // Paper end - CraftMetaCompass.LODESTONE_DIMENSION.NBT, - CraftMetaCompass.LODESTONE_POS.NBT, -@@ -1476,4 +1622,147 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - // Paper end - -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ @Override -+ @SuppressWarnings("deprecation") -+ public Set getCanDestroy() { -+ return !hasDestroyableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.destroyableKeys); -+ } -+ -+ @Override -+ @SuppressWarnings("deprecation") -+ public void setCanDestroy(Set canDestroy) { -+ Validate.notNull(canDestroy, "Cannot replace with null set!"); -+ legacyClearAndReplaceKeys(this.destroyableKeys, canDestroy); -+ } -+ -+ @Override -+ @SuppressWarnings("deprecation") -+ public Set getCanPlaceOn() { -+ return !hasPlaceableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.placeableKeys); -+ } -+ -+ @Override -+ @SuppressWarnings("deprecation") -+ public void setCanPlaceOn(Set canPlaceOn) { -+ Validate.notNull(canPlaceOn, "Cannot replace with null set!"); -+ legacyClearAndReplaceKeys(this.placeableKeys, canPlaceOn); -+ } -+ -+ @Override -+ public Set getDestroyableKeys() { -+ return !hasDestroyableKeys() ? Collections.emptySet() : Sets.newHashSet(this.destroyableKeys); -+ } -+ -+ @Override -+ public void setDestroyableKeys(Collection canDestroy) { -+ Validate.notNull(canDestroy, "Cannot replace with null collection!"); -+ Validate.isTrue(ofAcceptableType(canDestroy), "Can only use NamespacedKey or NamespacedTag objects!"); -+ this.destroyableKeys.clear(); -+ this.destroyableKeys.addAll(canDestroy); -+ } -+ -+ @Override -+ public Set getPlaceableKeys() { -+ return !hasPlaceableKeys() ? Collections.emptySet() : Sets.newHashSet(this.placeableKeys); -+ } -+ -+ @Override -+ public void setPlaceableKeys(Collection canPlaceOn) { -+ Validate.notNull(canPlaceOn, "Cannot replace with null collection!"); -+ Validate.isTrue(ofAcceptableType(canPlaceOn), "Can only use NamespacedKey or NamespacedTag objects!"); -+ this.placeableKeys.clear(); -+ this.placeableKeys.addAll(canPlaceOn); -+ } -+ -+ @Override -+ public boolean hasPlaceableKeys() { -+ return this.placeableKeys != null && !this.placeableKeys.isEmpty(); -+ } -+ -+ @Override -+ public boolean hasDestroyableKeys() { -+ return this.destroyableKeys != null && !this.destroyableKeys.isEmpty(); -+ } -+ -+ @Deprecated -+ private void legacyClearAndReplaceKeys(Collection toUpdate, Collection beingSet) { -+ if (beingSet.stream().anyMatch(Material::isLegacy)) { -+ throw new IllegalArgumentException("Set must not contain any legacy materials!"); -+ } -+ -+ toUpdate.clear(); -+ toUpdate.addAll(beingSet.stream().map(Material::getKey).collect(java.util.stream.Collectors.toSet())); -+ } -+ -+ @Deprecated -+ private Set legacyGetMatsFromKeys(Collection names) { -+ Set mats = Sets.newHashSet(); -+ for (Namespaced key : names) { -+ if (!(key instanceof org.bukkit.NamespacedKey)) { -+ continue; -+ } -+ -+ Material material = Material.matchMaterial(key.toString(), false); -+ if (material != null) { -+ mats.add(material); -+ } -+ } -+ -+ return mats; -+ } -+ -+ private @Nullable Namespaced deserializeNamespaced(String raw) { -+ boolean isTag = raw.length() > 0 && raw.codePointAt(0) == '#'; -+ ArgumentBlock blockParser = new ArgumentBlock(new com.mojang.brigadier.StringReader(raw), true); -+ try { -+ blockParser = blockParser.parse(false); -+ } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) { -+ e.printStackTrace(); -+ return null; -+ } -+ -+ MinecraftKey key; -+ if (isTag) { -+ key = blockParser.getTagKey(); -+ } else { -+ key = blockParser.getBlockKey(); -+ } -+ -+ if (key == null) { -+ return null; -+ } -+ -+ // don't DC the player if something slips through somehow -+ Namespaced resource = null; -+ try { -+ if (isTag) { -+ resource = new NamespacedTag(key.getNamespace(), key.getKey()); -+ } else { -+ resource = CraftNamespacedKey.fromMinecraft(key); -+ } -+ } catch (IllegalArgumentException ex) { -+ org.bukkit.Bukkit.getLogger().warning("Namespaced resource does not validate: " + key.toString()); -+ ex.printStackTrace(); -+ } -+ -+ return resource; -+ } -+ -+ private @Nonnull String serializeNamespaced(Namespaced resource) { -+ return resource.toString(); -+ } -+ -+ // not a fan of this -+ private boolean ofAcceptableType(Collection namespacedResources) { -+ -+ for (Namespaced resource : namespacedResources) { -+ if (!(resource instanceof org.bukkit.NamespacedKey || resource instanceof com.destroystokyo.paper.NamespacedTag)) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/Unmapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch deleted file mode 100644 index 29f93fd83f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 10 Sep 2018 23:56:36 -0400 -Subject: [PATCH] Prevent Mob AI Rules from Loading Chunks - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java -index b5c7b39a49afae1089a293b9b06bdd94deed1f64..61a62c093b24c43064f116630d85096159e082d3 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java -@@ -30,11 +30,13 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - private final Block g; - private final EntityInsentient entity; - private int i; -+ private World world; // Paper - - public PathfinderGoalRemoveBlock(Block block, EntityCreature entitycreature, double d0, int i) { - super(entitycreature, d0, 24, i); - this.g = block; - this.entity = entitycreature; -+ this.world = entitycreature.world; // Paper - } - - @Override -@@ -132,7 +134,9 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - - @Nullable - private BlockPosition a(BlockPosition blockposition, IBlockAccess iblockaccess) { -- if (iblockaccess.getType(blockposition).a(this.g)) { -+ Block block = world.getBlockIfLoaded(blockposition); // Paper -+ if (block == null) return null; // Paper -+ if (block.a(this.g)) { // Paper - return blockposition; - } else { - BlockPosition[] ablockposition = new BlockPosition[]{blockposition.down(), blockposition.west(), blockposition.east(), blockposition.north(), blockposition.south(), blockposition.down().down()}; -@@ -142,7 +146,7 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - for (int j = 0; j < i; ++j) { - BlockPosition blockposition1 = ablockposition1[j]; - -- if (iblockaccess.getType(blockposition1).a(this.g)) { -+ if (iblockaccess.getBlockIfLoaded(blockposition1).a(this.g)) { // Paper - return blockposition1; - } - } -@@ -153,7 +157,7 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - - @Override - protected boolean a(IWorldReader iworldreader, BlockPosition blockposition) { -- IChunkAccess ichunkaccess = iworldreader.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, false); -+ IChunkAccess ichunkaccess = iworldreader.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper - - return ichunkaccess == null ? false : ichunkaccess.getType(blockposition).a(this.g) && ichunkaccess.getType(blockposition.up()).isAir() && ichunkaccess.getType(blockposition.up(2)).isAir(); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java b/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java -index 129ea3857969ddb99e15ae817ee3eec67b4c3ccf..f9c40c8223109a9a40e7e7523c8f1f2e5aeddba1 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java -+++ b/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java -@@ -13,6 +13,7 @@ import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.EntityCreature; - import net.minecraft.world.entity.ai.navigation.NavigationAbstract; - import net.minecraft.world.level.IBlockAccess; -+import net.minecraft.world.level.material.Fluid; - import net.minecraft.world.level.pathfinder.PathType; - import net.minecraft.world.level.pathfinder.PathfinderNormal; - import net.minecraft.world.phys.Vec3D; -@@ -128,6 +129,7 @@ public class RandomPositionGenerator { - } - - blockposition2 = new BlockPosition((double) k1 + entitycreature.locX(), (double) l1 + entitycreature.locY(), (double) i2 + entitycreature.locZ()); -+ if (!entitycreature.world.isLoaded(blockposition2)) continue; // Paper - if (blockposition2.getY() >= 0 && blockposition2.getY() <= entitycreature.world.getBuildHeight() && (!flag3 || entitycreature.a(blockposition2)) && (!flag2 || navigationabstract.a(blockposition2))) { - if (flag1) { - blockposition2 = a(blockposition2, random.nextInt(l + 1) + i1, entitycreature.world.getBuildHeight(), (blockposition3) -> { -@@ -135,7 +137,8 @@ public class RandomPositionGenerator { - }); - } - -- if (flag || !entitycreature.world.getFluid(blockposition2).a((Tag) TagsFluid.WATER)) { -+ Fluid fluid = entitycreature.world.getFluidIfLoaded(blockposition2); // Paper -+ if (flag || (fluid != null && !fluid.a((Tag) TagsFluid.WATER))) { // Paper - PathType pathtype = PathfinderNormal.a((IBlockAccess) entitycreature.world, blockposition2.i()); - - if (entitycreature.a(pathtype) == 0.0F) { diff --git a/Unmapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch b/Unmapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch deleted file mode 100644 index 7a20915052..0000000000 --- a/Unmapped-Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 12 Sep 2018 21:12:57 -0400 -Subject: [PATCH] Prevent mob spawning from loading/generating chunks - -also prevents if out of world border bounds - -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index 1969d1002b3182338614a2be0519fcdc385b7a44..5307488fa48ffa91446dd4457de1ce6a8f61da61 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -176,9 +176,9 @@ public final class SpawnerCreature { - StructureManager structuremanager = worldserver.getStructureManager(); - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); - int i = blockposition.getY(); -- IBlockData iblockdata = ichunkaccess.getType(blockposition); -+ IBlockData iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn - -- if (!iblockdata.isOccluding(ichunkaccess, blockposition)) { -+ if (iblockdata != null && !iblockdata.isOccluding(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); - int j = 0; - int k = 0; -@@ -207,7 +207,7 @@ public final class SpawnerCreature { - if (entityhuman != null) { - double d2 = entityhuman.h(d0, (double) i, d1); - -- if (a(worldserver, ichunkaccess, blockposition_mutableblockposition, d2)) { -+ if (a(worldserver, ichunkaccess, blockposition_mutableblockposition, d2) && worldserver.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn - if (biomesettingsmobs_c == null) { - biomesettingsmobs_c = a(worldserver, structuremanager, chunkgenerator, enumcreaturetype, worldserver.random, (BlockPosition) blockposition_mutableblockposition); - if (biomesettingsmobs_c == null) { diff --git a/Unmapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/Unmapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch deleted file mode 100644 index 681fbbbb31..0000000000 --- a/Unmapped-Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 12 Sep 2018 21:47:01 -0400 -Subject: [PATCH] Optimize Biome Mob Lookups for Mob Spawning - -Uses an EnumMap as well as a Set paired List for O(1) contains calls. - -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java b/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java -index 5adaf5fdaaec25220878213df2c0839ccf025d63..233ae33b5cbf1aafc7d2632149ccb84c0b243162 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java -@@ -30,18 +30,27 @@ public class BiomeSettingsMobs { - }, (enumcreaturetype) -> { - return ImmutableList.of(); - })), ImmutableMap.of(), false); -+ // Paper start- decompile error workaround -+ private static class bProxy extends BiomeSettingsMobs.b { -+ private bProxy(double d0, double d1) { -+ super(d0, d1); -+ } -+ } -+ private static class cProxy extends BiomeSettingsMobs.c { -+ public cProxy(EntityTypes entitytypes, int i, int j, int k) { -+ super(entitytypes, i, j, k); -+ } -+ }; -+ // Paper end - public static final MapCodec c = RecordCodecBuilder.mapCodec((instance) -> { -- RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { -+ RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { // Paper - add type to builder - return biomesettingsmobs.d; - }); -- Codec codec = EnumCreatureType.g; -- Codec codec1 = BiomeSettingsMobs.c.b.listOf(); -- Logger logger = BiomeSettingsMobs.LOGGER; -+ // Paper - remove unused vars - -- logger.getClass(); -- return instance.group(recordcodecbuilder, Codec.simpleMap(codec, codec1.promotePartial(SystemUtils.a("Spawn data: ", logger::error)), INamable.a(EnumCreatureType.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { -+ return instance.group(recordcodecbuilder, Codec.simpleMap(EnumCreatureType.g, cProxy.b.listOf().promotePartial(SystemUtils.a("Spawn data: ", BiomeSettingsMobs.LOGGER::error)), INamable.a(EnumCreatureType.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { // Paper - inline codec, cProxy, LOGGER - return biomesettingsmobs.e; -- }), Codec.simpleMap(IRegistry.ENTITY_TYPE, BiomeSettingsMobs.b.a, IRegistry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { -+ }), Codec.simpleMap(IRegistry.ENTITY_TYPE, bProxy.a, IRegistry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { // Paper - decompile error - bProxy - return biomesettingsmobs.f; - }), Codec.BOOL.fieldOf("player_spawn_friendly").orElse(false).forGetter(BiomeSettingsMobs::b)).apply(instance, BiomeSettingsMobs::new); - }); -@@ -76,11 +85,43 @@ public class BiomeSettingsMobs { - - public static class a { - -- private final Map> a = (Map) Stream.of(EnumCreatureType.values()).collect(ImmutableMap.toImmutableMap((enumcreaturetype) -> { -+ // Paper start - keep track of data in a pair set to give O(1) contains calls - we have to hook removals incase plugins mess with it -+ public static class MobList extends java.util.ArrayList { -+ java.util.Set biomes = new java.util.HashSet<>(); -+ -+ @Override -+ public boolean contains(Object o) { -+ return biomes.contains(o); -+ } -+ -+ @Override -+ public boolean add(BiomeSettingsMobs.c BiomeSettingsMobs) { -+ biomes.add(BiomeSettingsMobs); -+ return super.add(BiomeSettingsMobs); -+ } -+ -+ @Override -+ public BiomeSettingsMobs.c remove(int index) { -+ BiomeSettingsMobs.c removed = super.remove(index); -+ if (removed != null) { -+ biomes.remove(removed); -+ } -+ return removed; -+ } -+ -+ @Override -+ public void clear() { -+ biomes.clear(); -+ super.clear(); -+ } -+ } -+ // use toImmutableEnumMap collector -+ private final Map> a = (Map) Stream.of(EnumCreatureType.values()).collect(Maps.toImmutableEnumMap((enumcreaturetype) -> { - return enumcreaturetype; - }, (enumcreaturetype) -> { -- return Lists.newArrayList(); -+ return new MobList(); // Use MobList instead of ArrayList - })); -+ // Paper end - private final Map, BiomeSettingsMobs.b> b = Maps.newLinkedHashMap(); - private float c = 0.1F; - private boolean d; diff --git a/Unmapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch b/Unmapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch deleted file mode 100644 index 110e0093a4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tassu -Date: Thu, 13 Sep 2018 08:45:21 +0300 -Subject: [PATCH] Implement furnace cook speed multiplier API - -Signed-off-by: Tassu - -Fixed an issue where a furnace's cook-speed multiplier rounds down -to the nearest Integer when updating its current cook time. - -Modified by: Eric Su - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index deaa4c136c23dc6c258cc1ce68523b3c007c80f9..e630e8d3e115d2a0177849ad8258a2304b9d3e9d 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -40,6 +40,7 @@ import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.phys.Vec3D; - - // CraftBukkit start -+import java.util.List; - import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.entity.CraftHumanEntity; - import org.bukkit.craftbukkit.inventory.CraftItemStack; -@@ -58,6 +59,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - protected NonNullList items; - public int burnTime; - private int ticksForCurrentFuel; -+ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API - public int cookTime; - public int cookTimeTotal; - protected final IContainerProperties b; -@@ -258,6 +260,11 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - this.n.put(new MinecraftKey(s), nbttagcompound1.getInt(s)); - } - -+ // Paper start - cook speed API -+ if (nbttagcompound.hasKey("Paper.CookSpeedMultiplier")) { -+ this.cookSpeedMultiplier = nbttagcompound.getDouble("Paper.CookSpeedMultiplier"); -+ } -+ // Paper end - } - - @Override -@@ -266,6 +273,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - nbttagcompound.setShort("BurnTime", (short) this.burnTime); - nbttagcompound.setShort("CookTime", (short) this.cookTime); - nbttagcompound.setShort("CookTimeTotal", (short) this.cookTimeTotal); -+ nbttagcompound.setDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API - ContainerUtil.a(nbttagcompound, this.items); - NBTTagCompound nbttagcompound1 = new NBTTagCompound(); - -@@ -326,7 +334,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - - if (this.isBurning() && this.canBurn(irecipe)) { - ++this.cookTime; -- if (this.cookTime == this.cookTimeTotal) { -+ if (this.cookTime >= this.cookTimeTotal) { // Paper - cook speed multiplier API - this.cookTime = 0; - this.cookTimeTotal = this.getRecipeCookingTime(); - this.burn(irecipe); -@@ -426,9 +434,13 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - } - } - -- protected int getRecipeCookingTime() { -- return (this.hasWorld()) ? (Integer) this.world.getCraftingManager().craft((Recipes) this.c, this, this.world).map(RecipeCooking::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail -+ // Paper begin - Expose this function so CraftFurnace can correctly scale the total cooking time to a new multiplier -+ public int getRecipeCookingTime() { -+ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */ -+ int cookTime = (this.hasWorld()) ? (Integer) this.world.getCraftingManager().craft((Recipes) this.c, this, this.world).map(RecipeCooking::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail -+ return (int) Math.ceil (cookTime / this.cookSpeedMultiplier); - } -+ // Paper end - - public static boolean isFuel(ItemStack itemstack) { - return f().containsKey(itemstack.getItem()); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -index 760fe719f2f8836c41f6a49d8a795703b2474390..86ad5f78eecc01863897838cb1f311f5dd3d996d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -@@ -63,4 +63,20 @@ public abstract class CraftFurnace extends CraftCon - public void setCookTimeTotal(int cookTimeTotal) { - this.getSnapshot().cookTimeTotal = cookTimeTotal; - } -+ -+ // Paper start - cook speed multiplier API -+ @Override -+ public double getCookSpeedMultiplier() { -+ return this.getSnapshot().cookSpeedMultiplier; -+ } -+ -+ @Override -+ public void setCookSpeedMultiplier(double multiplier) { -+ com.google.common.base.Preconditions.checkArgument(multiplier >= 0, "Furnace speed multiplier cannot be negative"); -+ com.google.common.base.Preconditions.checkArgument(multiplier <= 200, "Furnace speed multiplier cannot more than 200"); -+ T snapshot = this.getSnapshot(); -+ snapshot.cookSpeedMultiplier = multiplier; -+ snapshot.cookTimeTotal = snapshot.getRecipeCookingTime(); // Update the snapshot's current total cook time to scale with the newly set multiplier -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch b/Unmapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch deleted file mode 100644 index df8c61a859..0000000000 --- a/Unmapped-Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 18 Sep 2018 23:53:23 +0100 -Subject: [PATCH] PreSpawnerSpawnEvent - -This adds a separate event before an entity is spawned by a spawner -which contains the location of the spawner too similarly to how the -SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for -spawners. - -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index d4b8126f12fdf7d9b4f882d3ed7d8da544ed9e8a..867478484c0ba4ff467b96e458689937299b981d 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -132,11 +132,11 @@ public abstract class MobSpawnerAbstract { - - org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); - if (type != null) { -- com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -- event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent( - MCUtil.toLocation(world, d3, d4, d5), - type, -- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER -+ MCUtil.toLocation(world, blockposition) - ); - if (!event.callEvent()) { - flag = true; diff --git a/Unmapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch b/Unmapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch deleted file mode 100644 index 21a0e7b36d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 22 Sep 2018 15:56:59 -0400 -Subject: [PATCH] Catch JsonParseException in Entity and TE names - -As a result, data that no longer parses correctly will not crash the server -instead just logging the exception and continuing (and in most cases should -fix the data) - -Player data is fixed pretty much immediately but some block data (like -Shulkers) may need to be changed in order for it to re-save properly - -No more crashing though. - -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index cd7dc7d90efddb8a1bb50cd964b43d18cf9c83d1..35d1444c5b75d9a3a6cface5dd70aea0a08ac89d 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -7,6 +7,8 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkCoordIntPair; -@@ -514,4 +516,19 @@ public final class MCUtil { - return null; - } - } -+ -+ @Nullable -+ public static IChatBaseComponent getBaseComponentFromNbt(String key, NBTTagCompound compound) { -+ if (!compound.hasKey(key)) { -+ return null; -+ } -+ String string = compound.getString(key); -+ try { -+ return IChatBaseComponent.ChatSerializer.jsonToComponent(string); -+ } catch (com.google.gson.JsonParseException e) { -+ org.bukkit.Bukkit.getLogger().warning("Unable to parse " + key + " from " + compound +": " + e.getMessage()); -+ } -+ -+ return null; -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -index 94adf4d3b3a367e2a7fa383f1da6fb3b02b35c85..3fcdff3649c725580456dfc965d6c83bd5afe3da 100644 ---- a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -@@ -12,6 +12,7 @@ import net.minecraft.commands.ICommandListener; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.UtilColor; -@@ -72,7 +73,7 @@ public abstract class CommandBlockListenerAbstract implements ICommandListener { - this.command = nbttagcompound.getString("Command"); - this.successCount = nbttagcompound.getInt("SuccessCount"); - if (nbttagcompound.hasKeyOfType("CustomName", 8)) { -- this.setName(IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName"))); -+ this.setName(MCUtil.getBaseComponentFromNbt("CustomName", nbttagcompound)); // Paper - Catch ParseException - } - - if (nbttagcompound.hasKeyOfType("TrackOutput", 1)) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java -index fd8d39d04f39ea8aa389deb66ca0ddaa3e282c40..45958ffedca64e08e347ae65033700c0d798beb5 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java -@@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagList; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.world.INamableTileEntity; - import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.ItemStack; -@@ -70,7 +71,7 @@ public class TileEntityBanner extends TileEntity implements INamableTileEntity { - public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) { - super.load(iblockdata, nbttagcompound); - if (nbttagcompound.hasKeyOfType("CustomName", 8)) { -- this.a = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName")); -+ this.a = MCUtil.getBaseComponentFromNbt("CustomName", nbttagcompound); // Paper - Catch ParseException - } - - if (this.hasWorld()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java -index 19739ad1fb01c767288da2667a48909e4c1c36cc..fb7a1a854efcf42f0351ef521aff67d5fcc4ab27 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java -@@ -4,6 +4,7 @@ import javax.annotation.Nullable; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.ChestLock; -@@ -30,7 +31,7 @@ public abstract class TileEntityContainer extends TileEntity implements IInvento - super.load(iblockdata, nbttagcompound); - this.chestLock = ChestLock.b(nbttagcompound); - if (nbttagcompound.hasKeyOfType("CustomName", 8)) { -- this.customName = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName")); -+ this.customName = MCUtil.getBaseComponentFromNbt("CustomName", nbttagcompound); // Paper - Catch ParseException - } - - } diff --git a/Unmapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch b/Unmapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch deleted file mode 100644 index e69ce43f71..0000000000 --- a/Unmapped-Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Sep 2018 20:59:53 -0500 -Subject: [PATCH] Honor EntityAgeable.ageLock - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityAgeable.java b/src/main/java/net/minecraft/world/entity/EntityAgeable.java -index ea356ff0f91083195899cc2bb84b2fde504163b4..850135582c41893823c43a78a016c7791755b8b5 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityAgeable.java -+++ b/src/main/java/net/minecraft/world/entity/EntityAgeable.java -@@ -82,6 +82,7 @@ public abstract class EntityAgeable extends EntityCreature { - } - - public void setAge(int i, boolean flag) { -+ if (ageLocked) return; // Paper - GH-1459 - int j = this.getAge(); - int k = j; - diff --git a/Unmapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch b/Unmapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch deleted file mode 100644 index 4f33aeb255..0000000000 --- a/Unmapped-Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 2 Oct 2018 09:57:50 +0100 -Subject: [PATCH] Configurable connection throttle kick message - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 62621562137cba4804f0465c58d25ca2786328e5..7178b37f7978c7e9031a22726005c5099fd78fe0 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -281,6 +281,11 @@ public class PaperConfig { - authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); - } - -+ public static String connectionThrottleKickMessage = "Connection throttled! Please wait before reconnecting."; -+ private static void connectionThrottleKickMessage() { -+ connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); -+ } -+ - private static void savePlayerData() { - Object val = config.get("settings.save-player-data"); - if (val instanceof Boolean) { -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 93c67654bce188cd1eaf294abe7f765381ee0353..c4ba5c02c1be94bda2eb652415b48bf5a38400f6 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -50,7 +50,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - synchronized (throttleTracker) { - if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { - throttleTracker.put(address, currentTime); -- ChatMessage chatmessage = new ChatMessage("Connection throttled! Please wait before reconnecting."); -+ ChatMessage chatmessage = new ChatMessage(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message - this.c.sendPacket(new PacketLoginOutDisconnect(chatmessage)); - this.c.close(chatmessage); - return; diff --git a/Unmapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch b/Unmapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch deleted file mode 100644 index 06025aa8c5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 3 Oct 2018 20:09:18 -0400 -Subject: [PATCH] Hook into CB plugin rewrites - -Allows us to do fun stuff like rewrite the OBC util fastutil location to -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 45cbdcfc131bbc0e2bf23cc30a572df72eecd51c..49e5a86c223f1b28ce7da6ced276b2f880777856 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -@@ -6,7 +6,9 @@ import java.io.FileOutputStream; - import java.io.InputStream; - import java.util.Arrays; - import java.util.Enumeration; -+import java.util.HashMap; - import java.util.HashSet; -+import java.util.Map; - import java.util.Set; - import java.util.jar.JarEntry; - import java.util.jar.JarFile; -@@ -20,10 +22,15 @@ import org.bukkit.plugin.AuthorNagException; - import org.objectweb.asm.ClassReader; - import org.objectweb.asm.ClassVisitor; - import org.objectweb.asm.ClassWriter; -+import org.objectweb.asm.FieldVisitor; -+import org.objectweb.asm.Handle; -+import org.objectweb.asm.Label; - import org.objectweb.asm.MethodVisitor; - import org.objectweb.asm.Opcodes; - import org.objectweb.asm.Type; - -+import javax.annotation.Nonnull; -+ - /** - * This file is imported from Commodore. - * -@@ -46,6 +53,42 @@ public class Commodore - "org/bukkit/inventory/ItemStack (I)V setTypeId" - ) ); - -+ // Paper start - Plugin rewrites -+ private static final Map SEARCH_AND_REMOVE = initReplacementsMap(); -+ private static Map initReplacementsMap() -+ { -+ Map getAndRemove = new HashMap<>(); -+ // Be wary of maven shade's relocations -+ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/libs/it/unimi/dsi/fastutil/" ), "org/bukkit/".concat( "craftbukkit/libs/" ) ); // Remap fastutil to our location -+ -+ if ( Boolean.getBoolean( "debug.rewriteForIde" ) ) -+ { -+ // unversion incoming calls for pre-relocate debug work -+ final String NMS_REVISION_PACKAGE = "v1_16_R3/"; -+ -+ getAndRemove.put( "net/minecraft/".concat( "server/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); -+ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); -+ } -+ -+ return getAndRemove; -+ } -+ -+ @Nonnull -+ private static String getOriginalOrRewrite(@Nonnull String original) -+ { -+ String rewrite = null; -+ for ( Map.Entry entry : SEARCH_AND_REMOVE.entrySet() ) -+ { -+ if ( original.contains( entry.getKey() ) ) -+ { -+ rewrite = original.replace( entry.getValue(), "" ); -+ } -+ } -+ -+ return rewrite != null ? rewrite : original; -+ } -+ // Paper end -+ - public static void main(String[] args) - { - OptionParser parser = new OptionParser(); -@@ -130,15 +173,86 @@ public class Commodore - - cr.accept( new ClassVisitor( Opcodes.ASM9, cw ) - { -+ // Paper start - Rewrite plugins -+ @Override -+ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) -+ { -+ desc = getOriginalOrRewrite( desc ); -+ if ( signature != null ) { -+ signature = getOriginalOrRewrite( signature ); -+ } -+ -+ return super.visitField( access, name, desc, signature, value) ; -+ } -+ // Paper end -+ - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) - { - return new MethodVisitor( api, super.visitMethod( access, name, desc, signature, exceptions ) ) - { -+ // Paper start - Plugin rewrites -+ @Override -+ public void visitInvokeDynamicInsn(String name, String desc, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) -+ { -+ // Paper start - Rewrite plugins -+ name = getOriginalOrRewrite( name ); -+ if ( desc != null ) -+ { -+ desc = getOriginalOrRewrite( desc ); -+ } -+ // Paper end -+ -+ super.visitInvokeDynamicInsn( name, desc, bootstrapMethodHandle, bootstrapMethodArguments ); -+ } -+ -+ @Override -+ public void visitTypeInsn(int opcode, String type) -+ { -+ type = getOriginalOrRewrite( type ); -+ -+ super.visitTypeInsn( opcode, type ); -+ } -+ -+ @Override -+ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { -+ for ( int i = 0; i < local.length; i++ ) -+ { -+ if ( !( local[i] instanceof String ) ) { continue; } -+ -+ local[i] = getOriginalOrRewrite( (String) local[i] ); -+ } -+ -+ for ( int i = 0; i < stack.length; i++ ) -+ { -+ if ( !( stack[i] instanceof String ) ) { continue; } -+ -+ stack[i] = getOriginalOrRewrite( (String) stack[i] ); -+ } -+ -+ super.visitFrame( type, nLocal, local, nStack, stack ); -+ } -+ -+ @Override -+ public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) -+ { -+ descriptor = getOriginalOrRewrite( descriptor ); -+ -+ super.visitLocalVariable( name, descriptor, signature, start, end, index ); -+ } -+ // Paper end - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) - { -+ // Paper start - Rewrite plugins -+ owner = getOriginalOrRewrite( owner ); -+ if ( desc != null ) -+ { -+ desc = getOriginalOrRewrite( desc ); -+ } -+ // Paper end -+ - if ( owner.equals( "org/bukkit/block/Biome" ) ) - { - switch ( name ) -@@ -270,6 +384,14 @@ public class Commodore - return; - } - -+ // Paper start - Rewrite plugins -+ owner = getOriginalOrRewrite( owner) ; -+ if (desc != null) -+ { -+ desc = getOriginalOrRewrite(desc); -+ } -+ // Paper end -+ - if ( modern ) - { - if ( owner.equals( "org/bukkit/Material" ) ) diff --git a/Unmapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch b/Unmapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch deleted file mode 100644 index d97a31a735..0000000000 --- a/Unmapped-Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 6 Oct 2018 21:47:44 -0500 -Subject: [PATCH] Allow setting the vex's summoner - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -index 3b74ade60b3b0ae0e908866cb4ac11acd75620ff..9645d052069957311478a1ceca42ad52f7a9aa0b 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -@@ -165,6 +165,7 @@ public class EntityVex extends EntityMonster { - this.a(1, flag); - } - -+ public void setOwner(EntityInsentient entityinsentient) { a(entityinsentient); } // Paper - OBFHELPER - public void a(EntityInsentient entityinsentient) { - this.c = entityinsentient; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -index 962d6017f6acc47ebe4b754ccd9b97a1fc97cc58..30e2c169388b09b94d801be7543e75ea0bd56fcd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -@@ -21,6 +21,10 @@ public class CraftVex extends CraftMonster implements Vex { - net.minecraft.world.entity.EntityInsentient owner = getHandle().getOwner(); - return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; - } -+ -+ public void setSummoner(org.bukkit.entity.Mob summoner) { -+ getHandle().setOwner(summoner == null ? null : ((CraftMob) summoner).getHandle()); -+ } - // Paper end - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch b/Unmapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch deleted file mode 100644 index 7d5adc05ed..0000000000 --- a/Unmapped-Spigot-Server-Patches/0294-Add-sun-related-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 Oct 2018 00:54:21 -0500 -Subject: [PATCH] Add sun related API - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index e177483dace853ccd01d410fc7deea17663e9a3d..0489fb4869c9a0b56df6f44ef3925de7651baef2 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -1597,6 +1597,7 @@ public abstract class EntityInsentient extends EntityLiving { - - } - -+ public boolean isInDaylight() { return this.eG(); } // Paper - OBFHELPER - protected boolean eG() { - if (this.world.isDay() && !this.world.isClientSide) { - float f = this.aR(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 880bbf09f77f59824184c1c9dd1ca3c3df09dae9..95b4774b7696fa9711d7169d06a23c70364bfdb2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -865,6 +865,13 @@ public class CraftWorld implements World { - } - } - -+ // Paper start -+ @Override -+ public boolean isDayTime() { -+ return getHandle().isDay(); -+ } -+ // Paper end -+ - @Override - public long getGameTime() { - return world.worldData.getTime(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index 28a4e90130f51fd2fda7003fde5b4d0a410e1aef..06cbe63ef04e0de824ac0b9d545b6da1f53701b3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -78,4 +78,11 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { - public long getSeed() { - return getHandle().lootTableSeed; - } -+ -+ // Paper start -+ @Override -+ public boolean isInDaylight() { -+ return getHandle().isInDaylight(); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0295-Turtle-API.patch b/Unmapped-Spigot-Server-Patches/0295-Turtle-API.patch deleted file mode 100644 index 5d55bbc3f4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0295-Turtle-API.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 29 Sep 2018 16:08:23 -0500 -Subject: [PATCH] Turtle API - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -index 62276550627bfe453794a2b3101426fe05a585ff..6a156a488bc073b3b60f4d1081e3f2ab65ba9e96 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -@@ -14,7 +14,7 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - protected int c; - protected int d; - private int g; -- protected BlockPosition e; -+ protected BlockPosition e;public final BlockPosition getTargetPosition() { return this.e; } // Paper - OBFHELPER - private boolean h; - private final int i; - private final int j; -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -index bf224c97854daa379c61affff6a0ac9524c2c35d..09a6310af6712d36c20167256b60dc3235e76021 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -@@ -14,6 +14,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -93,7 +94,7 @@ public class EntityTurtle extends EntityAnimal { - this.datawatcher.set(EntityTurtle.bp, blockposition); - } - -- private BlockPosition getHomePos() { -+ public BlockPosition getHomePos() { // Paper - public - return (BlockPosition) this.datawatcher.get(EntityTurtle.bp); - } - -@@ -109,31 +110,37 @@ public class EntityTurtle extends EntityAnimal { - return (Boolean) this.datawatcher.get(EntityTurtle.bq); - } - -- private void setHasEgg(boolean flag) { -+ public void setHasEgg(boolean flag) { // Paper - this.datawatcher.set(EntityTurtle.bq, flag); - } - -+ public final boolean isDigging() { return this.eL(); } // Paper - OBFHELPER - public boolean eL() { - return (Boolean) this.datawatcher.get(EntityTurtle.br); - } - -+ public final void setDigging(boolean digging) { this.u(digging); } // Paper - OBFHELPER - private void u(boolean flag) { - this.bv = flag ? 1 : 0; - this.datawatcher.set(EntityTurtle.br, flag); - } - -+ public final boolean isGoingHome() { return this.eU(); } // Paper - OBFHELPER - private boolean eU() { - return (Boolean) this.datawatcher.get(EntityTurtle.bt); - } - -+ public final void setGoingHome(boolean goingHome) { this.v(goingHome); } // Paper - OBFHELPER - private void v(boolean flag) { - this.datawatcher.set(EntityTurtle.bt, flag); - } - -+ public final boolean isTravelling() { return this.eV(); } // Paper - OBFHELPER - private boolean eV() { - return (Boolean) this.datawatcher.get(EntityTurtle.bu); - } - -+ public final void setTravelling(boolean travelling) { this.w(travelling); } // Paper - OBFHELPER - private void w(boolean flag) { - this.datawatcher.set(EntityTurtle.bu, flag); - } -@@ -500,14 +507,17 @@ public class EntityTurtle extends EntityAnimal { - - if (!this.g.isInWater() && this.l()) { - if (this.g.bv < 1) { -- this.g.u(true); -+ this.g.setDigging(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.g.getBukkitEntity(), MCUtil.toLocation(this.g.world, this.getTargetPosition())).callEvent()); // Paper - } else if (this.g.bv > 200) { - World world = this.g.world; - - // CraftBukkit start -- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.g, this.e.up(), (IBlockData) Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, this.g.random.nextInt(4) + 1)).isCancelled()) { -+ // Paper start -+ int eggCount = this.g.random.nextInt(4) + 1; -+ com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.g.getBukkitEntity(), MCUtil.toLocation(this.g.world, this.e.up()), eggCount); -+ if (layEggEvent.callEvent() && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.g, this.e.up(), Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, layEggEvent.getEggCount())).isCancelled()) { - world.playSound((EntityHuman) null, blockposition, SoundEffects.ENTITY_TURTLE_LAY_EGG, SoundCategory.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); -- world.setTypeAndData(this.e.up(), (IBlockData) Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, this.g.random.nextInt(4) + 1), 3); -+ world.setTypeAndData(this.e.up(), (IBlockData) Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, layEggEvent.getEggCount()), 3); - } - // CraftBukkit end - this.g.setHasEgg(false); -@@ -636,7 +646,7 @@ public class EntityTurtle extends EntityAnimal { - - @Override - public boolean a() { -- return this.a.isBaby() ? false : (this.a.hasEgg() ? true : (this.a.getRandom().nextInt(700) != 0 ? false : !this.a.getHomePos().a((IPosition) this.a.getPositionVector(), 64.0D))); -+ return this.a.isBaby() ? false : (this.a.hasEgg() ? true : (this.a.getRandom().nextInt(700) != 0 ? false : !this.a.getHomePos().a((IPosition) this.a.getPositionVector(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.a.getBukkitEntity()).callEvent(); // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -index b46bb75926c14ab54ea309a400eb57405b11ce27..31f1a6b2b9a432cdd25826ced884424eeb50df97 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -@@ -25,4 +25,36 @@ public class CraftTurtle extends CraftAnimals implements Turtle { - public EntityType getType() { - return EntityType.TURTLE; - } -+ -+ // Paper start -+ @Override -+ public org.bukkit.Location getHome() { -+ return net.minecraft.server.MCUtil.toLocation(getHandle().world, getHandle().getHomePos()); -+ } -+ -+ @Override -+ public void setHome(org.bukkit.Location location) { -+ getHandle().setHomePos(net.minecraft.server.MCUtil.toBlockPosition(location)); -+ } -+ -+ @Override -+ public boolean isGoingHome() { -+ return getHandle().isGoingHome(); -+ } -+ -+ @Override -+ public boolean isDigging() { -+ return getHandle().isDigging(); -+ } -+ -+ @Override -+ public boolean hasEgg() { -+ return getHandle().hasEgg(); -+ } -+ -+ @Override -+ public void setHasEgg(boolean hasEgg) { -+ getHandle().setHasEgg(hasEgg); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/Unmapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch deleted file mode 100644 index ab9d26a523..0000000000 --- a/Unmapped-Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 17 Oct 2018 19:17:27 -0400 -Subject: [PATCH] MC-50319: Check other worlds for shooter of projectiles - -Say a player shoots an arrow through a nether portal, the game -would lose the shooter for determining things such as Player Kills, -because the entity is in another world. - -If the projectile fails to find the shooter in the current world, check -other worlds. - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index b44b18341331e5176e0f1851aa60cc425ccbd439..29834a3613c7701d46e879d170779eb7e6f664e1 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -45,7 +45,18 @@ public abstract class IProjectile extends Entity { - - @Nullable - public Entity getShooter() { -- return this.shooter != null && this.world instanceof WorldServer ? ((WorldServer) this.world).getEntity(this.shooter) : (this.c != 0 ? this.world.getEntity(this.c) : null); -+ // Paper start - MC-50319 - shooter might be in another world (arrows through portals) -+ Entity entity = this.shooter != null && this.world instanceof WorldServer ? ((WorldServer) this.world).getEntity(this.shooter) : (this.c != 0 ? this.world.getEntity(this.c) : null); -+ if (entity == null) { -+ for (WorldServer world : world.getMinecraftServer().getWorlds()) { -+ entity = world.getEntity(this.shooter); -+ if (entity != null) { -+ break; -+ } -+ } -+ } -+ return entity; -+ // Paper end - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch b/Unmapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch deleted file mode 100644 index 7a0ba42f33..0000000000 --- a/Unmapped-Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Caleb Bassham -Date: Fri, 28 Sep 2018 02:32:19 -0500 -Subject: [PATCH] Call player spectator target events and improve - implementation - -Use a proper teleport for teleporting to entities in different -worlds. - -Implementation improvements authored by Spottedleaf -Validate that the target entity is valid and deny spectate -requests from frozen players. - -Also, make sure the entity is spawned to the client before -sending the camera packet. If the entity isn't spawned clientside -when it receives the camera packet, then the client will not -spectate the target entity. - -Co-authored-by: Spottedleaf - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index ae9e0f55ddc194aaef1e57e81863569d9bc7b8f3..f5be9554e1fd01a35b926196b30fd64f1567a799 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1820,15 +1820,59 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - return (Entity) (this.spectatedEntity == null ? this : this.spectatedEntity); - } - -- public void setSpectatorTarget(Entity entity) { -+ public void setSpectatorTarget(Entity newSpectatorTarget) { -+ // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event and improve implementation - Entity entity1 = this.getSpecatorTarget(); - -- this.spectatedEntity = (Entity) (entity == null ? this : entity); -- if (entity1 != this.spectatedEntity) { -- this.playerConnection.sendPacket(new PacketPlayOutCamera(this.spectatedEntity)); -- this.playerConnection.a(this.spectatedEntity.locX(), this.spectatedEntity.locY(), this.spectatedEntity.locZ(), this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit -+ if (newSpectatorTarget == null) { -+ newSpectatorTarget = this; - } - -+ if (entity1 == newSpectatorTarget) return; // new spec target is the current spec target -+ -+ if (newSpectatorTarget == this) { -+ com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent playerStopSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity()); -+ -+ if (!playerStopSpectatingEntityEvent.callEvent()) { -+ return; -+ } -+ } else { -+ com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent playerStartSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity(), newSpectatorTarget.getBukkitEntity()); -+ -+ if (!playerStartSpectatingEntityEvent.callEvent()) { -+ return; -+ } -+ } -+ // Validate -+ if (newSpectatorTarget != this) { -+ if (newSpectatorTarget.dead || newSpectatorTarget.shouldBeRemoved || !newSpectatorTarget.valid || newSpectatorTarget.world == null) { -+ MinecraftServer.LOGGER.info("Blocking player " + this.toString() + " from spectating invalid entity " + newSpectatorTarget.toString()); -+ return; -+ } -+ if (this.isFrozen()) { -+ // use debug: clients might maliciously spam this -+ MinecraftServer.LOGGER.debug("Blocking frozen player " + this.toString() + " from spectating entity " + newSpectatorTarget.toString()); -+ return; -+ } -+ } -+ -+ this.spectatedEntity = newSpectatorTarget; // only set after validating state -+ -+ if (newSpectatorTarget != this) { -+ // Make sure we're in the right place -+ this.ejectPassengers(); // teleport can fail if we have passengers... -+ this.getBukkitEntity().teleport(new Location(newSpectatorTarget.getWorld().getWorld(), newSpectatorTarget.locX(), newSpectatorTarget.locY(), newSpectatorTarget.locZ(), this.yaw, this.pitch), TeleportCause.SPECTATE); // Correctly handle cross-world entities from api calls by using CB teleport -+ -+ // Make sure we're tracking the entity before sending -+ PlayerChunkMap.EntityTracker tracker = ((WorldServer)newSpectatorTarget.world).getChunkProvider().playerChunkMap.trackedEntities.get(newSpectatorTarget.getId()); -+ if (tracker != null) { // dumb plugins... -+ tracker.updatePlayer(this); -+ } -+ } else { -+ this.playerConnection.teleport(this.spectatedEntity.locX(), this.spectatedEntity.locY(), this.spectatedEntity.locZ(), this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit -+ } -+ this.playerConnection.sendPacket(new PacketPlayOutCamera(newSpectatorTarget)); -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index b9825537599a8df8d772b2db4d56d5e28cc2bbe9..9a5f510d3a43df40934efb56d24956dee2c62380 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1355,6 +1355,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - // CraftBukkit start - Delegate to teleport(Location) -+ public final void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { this.a(d0, d1, d2, f, f1, cause); } // Paper - OBFHELPER - public void a(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { - this.a(d0, d1, d2, f, f1, Collections.emptySet(), cause); - } diff --git a/Unmapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch b/Unmapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch deleted file mode 100644 index d09f71796d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch +++ /dev/null @@ -1,307 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Mon, 8 Oct 2018 14:36:14 -0400 -Subject: [PATCH] Add Velocity IP Forwarding Support - -While Velocity supports BungeeCord-style IP forwarding, it is not secure. Users -have a lot of problems setting up firewalls or setting up plugins like IPWhitelist. -Further, the BungeeCord IP forwarding protocol still retains essentially its original -form, when there is brand new support for custom login plugin messages in 1.13. - -Velocity's modern IP forwarding uses an HMAC-SHA256 code to ensure authenticity -of messages, is packed into a binary format that is smaller than BungeeCord's -forwarding, and is integrated into the Minecraft login process by using the 1.13 -login plugin message packet. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 7178b37f7978c7e9031a22726005c5099fd78fe0..3139c194f9b1bc3510d51a81f13ae43d00a3dc29 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -8,6 +8,7 @@ import java.io.IOException; - import java.lang.reflect.InvocationTargetException; - import java.lang.reflect.Method; - import java.lang.reflect.Modifier; -+import java.nio.charset.StandardCharsets; - import java.util.HashMap; - import java.util.List; - import java.util.Map; -@@ -252,7 +253,7 @@ public class PaperConfig { - } - - public static boolean isProxyOnlineMode() { -- return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); -+ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode) || (velocitySupport && velocityOnlineMode); - } - - public static int packetInSpamThreshold = 300; -@@ -324,4 +325,18 @@ public class PaperConfig { - } - tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); - } -+ -+ public static boolean velocitySupport; -+ public static boolean velocityOnlineMode; -+ public static byte[] velocitySecretKey; -+ private static void velocitySupport() { -+ velocitySupport = getBoolean("settings.velocity-support.enabled", false); -+ velocityOnlineMode = getBoolean("settings.velocity-support.online-mode", false); -+ String secret = getString("settings.velocity-support.secret", ""); -+ if (velocitySupport && secret.isEmpty()) { -+ fatal("Velocity support is enabled, but no secret key was specified. A secret key is required!"); -+ } else { -+ velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e6afaa41df086b1eb3950ce870c91dd5bf5a663b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java -@@ -0,0 +1,67 @@ -+package com.destroystokyo.paper.proxy; -+ -+import com.destroystokyo.paper.PaperConfig; -+import com.google.common.net.InetAddresses; -+import com.mojang.authlib.GameProfile; -+import com.mojang.authlib.properties.Property; -+import net.minecraft.network.PacketDataSerializer; -+import net.minecraft.resources.MinecraftKey; -+ -+import java.net.InetAddress; -+import java.security.InvalidKeyException; -+import java.security.MessageDigest; -+import java.security.NoSuchAlgorithmException; -+ -+import javax.crypto.Mac; -+import javax.crypto.spec.SecretKeySpec; -+ -+public class VelocityProxy { -+ private static final int SUPPORTED_FORWARDING_VERSION = 1; -+ public static final MinecraftKey PLAYER_INFO_CHANNEL = new MinecraftKey("velocity", "player_info"); -+ -+ public static boolean checkIntegrity(final PacketDataSerializer buf) { -+ final byte[] signature = new byte[32]; -+ buf.readBytes(signature); -+ -+ final byte[] data = new byte[buf.readableBytes()]; -+ buf.getBytes(buf.readerIndex(), data); -+ -+ try { -+ final Mac mac = Mac.getInstance("HmacSHA256"); -+ mac.init(new SecretKeySpec(PaperConfig.velocitySecretKey, "HmacSHA256")); -+ final byte[] mySignature = mac.doFinal(data); -+ if (!MessageDigest.isEqual(signature, mySignature)) { -+ return false; -+ } -+ } catch (final InvalidKeyException | NoSuchAlgorithmException e) { -+ throw new AssertionError(e); -+ } -+ -+ int version = buf.readVarInt(); -+ if (version != SUPPORTED_FORWARDING_VERSION) { -+ throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted " + SUPPORTED_FORWARDING_VERSION); -+ } -+ -+ return true; -+ } -+ -+ public static InetAddress readAddress(final PacketDataSerializer buf) { -+ return InetAddresses.forString(buf.readUTF(Short.MAX_VALUE)); -+ } -+ -+ public static GameProfile createProfile(final PacketDataSerializer buf) { -+ final GameProfile profile = new GameProfile(buf.readUUID(), buf.readUTF(16)); -+ readProperties(buf, profile); -+ return profile; -+ } -+ -+ private static void readProperties(final PacketDataSerializer buf, final GameProfile profile) { -+ final int properties = buf.readVarInt(); -+ for (int i1 = 0; i1 < properties; i1++) { -+ final String name = buf.readUTF(Short.MAX_VALUE); -+ final String value = buf.readUTF(Short.MAX_VALUE); -+ final String signature = buf.readBoolean() ? buf.readUTF(Short.MAX_VALUE) : null; -+ profile.getProperties().put(name, new Property(name, value, signature)); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index 5a1187b001004afe22d208bc5d7c288e796e16a6..579eb1260c7266cd41025cff177de4fb00ac0cec 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -192,6 +192,7 @@ public class PacketDataSerializer extends ByteBuf { - return this.d(oenum.ordinal()); - } - -+ public int readVarInt() { return i(); } // Paper - OBFHELPER - public int i() { - int i = 0; - int j = 0; -@@ -232,6 +233,7 @@ public class PacketDataSerializer extends ByteBuf { - return this; - } - -+ public UUID readUUID() { return k(); } // Paper - OBFHELPER - public UUID k() { - return new UUID(this.readLong(), this.readLong()); - } -@@ -359,6 +361,7 @@ public class PacketDataSerializer extends ByteBuf { - } - } - -+ public String readUTF(int maxLength) { return this.e(maxLength); } // Paper - OBFHELPER - public String e(int i) { - int j = this.i(); - -diff --git a/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java b/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java -index c1bac2d07e5107c1346f246f5d5d929c73912bfd..c47c2d774a1990ad5007bbdc7bd3a81b3f3817e3 100644 ---- a/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java -+++ b/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java -@@ -6,8 +6,8 @@ import net.minecraft.network.protocol.Packet; - - public class PacketLoginInCustomPayload implements Packet { - -- private int a; -- private PacketDataSerializer b; -+ private int a; public int getId() { return a; } // Paper - OBFHELPER -+ private PacketDataSerializer b; public PacketDataSerializer getBuf() { return b; } // Paper - OBFHELPER - - public PacketLoginInCustomPayload() {} - -diff --git a/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java b/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java -index eb970c1e954cb0aa83aa12e83c471778809e69b2..2d8c917509f10a96fc82404908b452cb385c7c60 100644 ---- a/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java -+++ b/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java -@@ -13,6 +13,14 @@ public class PacketLoginOutCustomPayload implements Packet { -+ try { -+ new LoginHandler().fireEvents(); -+ } catch (Exception ex) { -+ disconnect("Failed to verify username!"); -+ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + i.getName(), ex); -+ } -+ }); -+ return; -+ } -+ // Paper end - this.disconnect(new ChatMessage("multiplayer.disconnect.unexpected_query_response")); - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index ba982907b97faace89b73365aef1c91dab692ff1..22f9d8c0189293b88353bbe1bcc40dd1d431d458 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -681,7 +681,7 @@ public final class CraftServer implements Server { - @Override - public long getConnectionThrottle() { - // Spigot Start - Automatically set connection throttle for bungee configurations -- if (org.spigotmc.SpigotConfig.bungee) { -+ if (org.spigotmc.SpigotConfig.bungee || com.destroystokyo.paper.PaperConfig.velocitySupport) { // Paper - Velocity support - return -1; - } else { - return this.configuration.getInt("settings.connection-throttle"); diff --git a/Unmapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch b/Unmapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch deleted file mode 100644 index fe9e372e32..0000000000 --- a/Unmapped-Spigot-Server-Patches/0299-Add-more-Witch-API.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 12 Oct 2018 14:10:46 -0500 -Subject: [PATCH] Add more Witch API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index c6d79125e7dd982fc528ce61144005194cbaa323..63fb08e7b4290353e5148d1acb58f091dc5b08be 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -1,5 +1,11 @@ - package net.minecraft.world.entity.monster; - -+// Paper start -+import com.destroystokyo.paper.event.entity.WitchReadyPotionEvent; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.entity.Witch; -+// Paper end -+ - import java.util.Iterator; - import java.util.List; - import java.util.UUID; -@@ -49,7 +55,7 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - private static final UUID b = UUID.fromString("5CD17E52-A79A-43D3-A529-90FDE04B181E"); - private static final AttributeModifier bo = new AttributeModifier(EntityWitch.b, "Drinking speed penalty", -0.25D, AttributeModifier.Operation.ADDITION); - private static final DataWatcherObject bp = DataWatcher.a(EntityWitch.class, DataWatcherRegistry.i); -- private int bq; -+ private int bq; public int getPotionUseTimeLeft() { return bq; } public void setPotionUseTimeLeft(int timeLeft) { bq = timeLeft; } // Paper - OBFHELPER - private PathfinderGoalNearestHealableRaider br; - private PathfinderGoalNearestAttackableTargetWitch bs; - -@@ -95,10 +101,12 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - return SoundEffects.ENTITY_WITCH_DEATH; - } - -+ public void setDrinkingPotion(boolean drinkingPotion) { v(drinkingPotion); } // Paper - OBFHELPER - public void v(boolean flag) { - this.getDataWatcher().set(EntityWitch.bp, flag); - } - -+ public boolean isDrinkingPotion() { return m(); } // Paper - OBFHELPER - public boolean m() { - return (Boolean) this.getDataWatcher().get(EntityWitch.bp); - } -@@ -157,21 +165,24 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - } - - if (potionregistry != null) { -- // Paper start - ItemStack potion = PotionUtil.a(new ItemStack(Items.POTION), potionregistry); -- org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -- this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+ // Paper start - logic moved into setDrinkingPotion, copy exact impl into the method and then comment out -+ this.setDrinkingPotion(potion); -+// org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+// this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+// // Paper end -+// this.bq = this.getItemInMainHand().k(); -+// this.v(true); -+// if (!this.isSilent()) { -+// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); -+// } -+// -+// AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); -+// -+// attributemodifiable.removeModifier(EntityWitch.bo); -+// attributemodifiable.b(EntityWitch.bo); - // Paper end -- this.bq = this.getItemInMainHand().k(); -- this.v(true); -- if (!this.isSilent()) { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); -- } - -- AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); -- -- attributemodifiable.removeModifier(EntityWitch.bo); -- attributemodifiable.b(EntityWitch.bo); - } - } - -@@ -183,6 +194,24 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - super.movementTick(); - } - -+ // Paper start - moved to its own method -+ public void setDrinkingPotion(ItemStack potion) { -+ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+ this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+ // Paper end -+ this.bq = this.getItemInMainHand().k(); -+ this.v(true); -+ if (!this.isSilent()) { -+ this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); -+ } -+ -+ AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); -+ -+ attributemodifiable.removeModifier(EntityWitch.bo); -+ attributemodifiable.b(EntityWitch.bo); -+ } -+ // Paper end -+ - @Override - public SoundEffect eL() { - return SoundEffects.ENTITY_WITCH_CELEBRATE; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -index 9cc34cdb43596eff34625045f884b93da3f27ab6..3b553c2455948a4102754b2617c2301c49f476d6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -@@ -4,6 +4,13 @@ import net.minecraft.world.entity.monster.EntityWitch; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Witch; -+// Paper start -+import com.destroystokyo.paper.entity.CraftRangedEntity; -+import com.google.common.base.Preconditions; -+import org.bukkit.Material; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.inventory.ItemStack; -+// Paper end - - public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftWitch(CraftServer server, EntityWitch entity) { -@@ -24,4 +31,28 @@ public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo. - public EntityType getType() { - return EntityType.WITCH; - } -+ -+ // Paper start -+ public boolean isDrinkingPotion() { -+ return getHandle().isDrinkingPotion(); -+ } -+ -+ public int getPotionUseTimeLeft() { -+ return getHandle().getPotionUseTimeLeft(); -+ } -+ -+ @Override -+ public void setPotionUseTimeLeft(int ticks) { -+ getHandle().setPotionUseTimeLeft(ticks); -+ } -+ -+ public ItemStack getDrinkingPotion() { -+ return CraftItemStack.asCraftMirror(getHandle().getItemInMainHand()); -+ } -+ -+ public void setDrinkingPotion(ItemStack potion) { -+ Preconditions.checkArgument(potion == null || potion.getType().isEmpty() || potion.getType() == Material.POTION, "must be potion, air, or null"); -+ getHandle().setDrinkingPotion(CraftItemStack.asNMSCopy(potion)); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch b/Unmapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch deleted file mode 100644 index efb266e1a5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Wed, 10 Oct 2018 21:22:44 -0500 -Subject: [PATCH] Check Drowned for Villager Aggression Config - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -index c3457fc7c0f72af79b12dc50c270ca24b7590c22..e4794760fc918cccbdc3f8d10ab21dd9b6f29e8e 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -@@ -82,7 +82,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { - this.goalSelector.a(7, new PathfinderGoalRandomStroll(this, 1.0D)); - this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityDrowned.class})).a(EntityPigZombie.class)); - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::i)); -- this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)); -+ if ( world.spigotConfig.zombieAggressiveTowardsVillager ) this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)); // Paper - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, true)); - this.targetSelector.a(5, new PathfinderGoalNearestAttackableTarget<>(this, EntityTurtle.class, 10, true, false, EntityTurtle.bo)); - } diff --git a/Unmapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch b/Unmapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch deleted file mode 100644 index b9a50189c2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0301-Here-s-Johnny.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 12 Oct 2018 01:37:22 -0500 -Subject: [PATCH] Here's Johnny! - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -index c181d5f5e6108ade54fc97c665897d1db5e90719..c45dcb56af95f3e87e292b92b697a336461f01bc 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -@@ -51,7 +51,7 @@ public class EntityVindicator extends EntityIllagerAbstract { - private static final Predicate b = (enumdifficulty) -> { - return enumdifficulty == EnumDifficulty.NORMAL || enumdifficulty == EnumDifficulty.HARD; - }; -- private boolean bo; -+ private boolean bo; public boolean isJohnny() { return bo; } public void setJohnny(boolean johnny) { bo = johnny; } // Paper - OBFHELPER - - public EntityVindicator(EntityTypes entitytypes, World world) { - super(entitytypes, world); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -index e793820e1ede4bd4d31e6fe12ca8189707674ffe..b128e8291f2d7652a98f1271d763e33afa5de9f7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -@@ -25,4 +25,14 @@ public class CraftVindicator extends CraftIllager implements Vindicator { - public EntityType getType() { - return EntityType.VINDICATOR; - } -+ -+ // Paper start -+ public boolean isJohnny() { -+ return getHandle().isJohnny(); -+ } -+ -+ public void setJohnny(boolean johnny) { -+ getHandle().setJohnny(johnny); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch b/Unmapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch deleted file mode 100644 index aa55d56895..0000000000 --- a/Unmapped-Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabriele C -Date: Mon, 22 Oct 2018 17:34:10 +0200 -Subject: [PATCH] Add option to prevent players from moving into unloaded - chunks #1551 - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index f280dbff4a09bc611a9ca565c6d697d08801f53b..fbf3ccfb347a5ba6e895339e9576629d940d1aa4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -396,4 +396,9 @@ public class PaperWorldConfig { - waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); - log("Water over lava flow speed: " + waterOverLavaFlowSpeed); - } -+ -+ public boolean preventMovingIntoUnloadedChunks = false; -+ private void preventMovingIntoUnloadedChunks() { -+ preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 9a5f510d3a43df40934efb56d24956dee2c62380..f48683ef9afe3e5d0e0e5959c698152e9086632b 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -543,6 +543,13 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - speed *= 2f; // TODO: Get the speed of the vehicle instead of the player - -+ // Paper start - Prevent moving into unloaded chunks -+ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && worldserver.getChunkIfLoadedImmediately((int) Math.floor(packetplayinvehiclemove.getX()) >> 4, (int) Math.floor(packetplayinvehiclemove.getZ()) >> 4) == null) { -+ this.networkManager.sendPacket(new PacketPlayOutVehicleMove(entity)); -+ return; -+ } -+ // Paper end -+ - if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isExemptPlayer()) { - // CraftBukkit end - PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getDisplayName().getString(), this.player.getDisplayName().getString(), d6, d7, d8); -@@ -1141,9 +1148,9 @@ public class PlayerConnection implements PacketListenerPlayIn { - double d1 = this.player.locY(); - double d2 = this.player.locZ(); - double d3 = this.player.locY(); -- double d4 = packetplayinflying.a(this.player.locX()); -+ double d4 = packetplayinflying.a(this.player.locX());double toX = d4; // Paper - OBFHELPER - double d5 = packetplayinflying.b(this.player.locY()); -- double d6 = packetplayinflying.c(this.player.locZ()); -+ double d6 = packetplayinflying.c(this.player.locZ());double toZ = d6; // Paper - OBFHELPER - float f = packetplayinflying.a(this.player.yaw); - float f1 = packetplayinflying.b(this.player.pitch); - double d7 = d4 - this.l; -@@ -1182,6 +1189,12 @@ public class PlayerConnection implements PacketListenerPlayIn { - } else { - speed = player.abilities.walkSpeed * 10f; - } -+ // Paper start - Prevent moving into unloaded chunks -+ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && !worldserver.isChunkLoaded((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { -+ this.internalTeleport(this.player.locX(), this.player.locY(), this.player.locZ(), this.player.yaw, this.player.pitch, Collections.emptySet()); -+ return; -+ } -+ // Paper end - - if (!this.player.H() && (!this.player.getWorldServer().getGameRules().getBoolean(GameRules.DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isGliding())) { - float f2 = this.player.isGliding() ? 300.0F : 100.0F; diff --git a/Unmapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch b/Unmapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch deleted file mode 100644 index a2e59dc39e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: GreenMeanie -Date: Sat, 20 Oct 2018 22:34:02 -0400 -Subject: [PATCH] Reset players airTicks on respawn - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index f5be9554e1fd01a35b926196b30fd64f1567a799..3e7ac6699ad1f147220c286e251ce0ec1ca25035 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -2162,6 +2162,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - this.setHealth(this.getMaxHealth()); -+ this.setAirTicks(this.getMaxAirTicks()); // Paper - this.fireTicks = 0; - this.fallDistance = 0; - this.foodData = new FoodMetaData(this); -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 28390d3830ed9f3f5d97ab38913e6c40f9943a70..2292295bac55651850b5e033f1ca9819bb7fa96f 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2355,6 +2355,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - } - -+ public final int getMaxAirTicks() { return bH(); } // Paper - OBFHELPER - public int bH() { - return 300; - } diff --git a/Unmapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch b/Unmapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch deleted file mode 100644 index 01be147e24..0000000000 --- a/Unmapped-Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 23 Oct 2018 20:25:05 -0400 -Subject: [PATCH] Don't sleep after profile lookups if not needed - -Mojang was sleeping even if we had no more requests to go after -the current one finished, resulting in 100ms lost per profile lookup - -diff --git a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -index a3ab666b5fa89aad7ee167d9aeff2f62019a4a78..8e182fdd69dba6e1c52e2f6a893534d77fb3bfaa 100644 ---- a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -+++ b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -@@ -43,6 +43,7 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { - } - - final int page = 0; -+ boolean hasRequested = false; // Paper - - for (final List request : Iterables.partition(criteria, ENTRIES_PER_PAGE)) { - int failCount = 0; -@@ -68,6 +69,12 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { - LOGGER.debug("Couldn't find profile {}", name); - callback.onProfileLookupFailed(new GameProfile(null, name), new ProfileNotFoundException("Server did not find the requested profile")); - } -+ // Paper start -+ if (!hasRequested) { -+ hasRequested = true; -+ continue; -+ } -+ // Paper end - - try { - Thread.sleep(DELAY_BETWEEN_PAGES); diff --git a/Unmapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/Unmapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch deleted file mode 100644 index 88f88070b9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 23 Oct 2018 23:14:38 -0400 -Subject: [PATCH] Improve Server Thread Pool and Thread Priorities - -Use a simple executor since Fork join is a much more complex pool -type and we are not using its capabilities. - -Set thread priorities so main thread has above normal priority over -server threads - -Allow usage of a single thread executor by not using ForkJoin so single core CPU's. - -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 68ce7605bd63ea280b96db8230463d2afb0a6cb1..46d82c1548088b8305f758699388edf0d5d4d050 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -45,6 +45,7 @@ import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.DispenserRegistry; -+import net.minecraft.server.ServerWorkerThread; - import net.minecraft.util.MathHelper; - import net.minecraft.util.datafix.DataConverterRegistry; - import net.minecraft.world.level.block.state.properties.IBlockState; -@@ -54,8 +55,8 @@ import org.apache.logging.log4j.Logger; - public class SystemUtils { - - private static final AtomicInteger c = new AtomicInteger(1); -- private static final ExecutorService d = a("Bootstrap"); -- private static final ExecutorService e = a("Main"); -+ private static final ExecutorService d = a("Bootstrap", -2); // Paper - add -2 priority -+ private static final ExecutorService e = a("Main", -1); // Paper - add -1 priority - private static final ExecutorService f = n(); - public static LongSupplier a = System::nanoTime; - public static final UUID b = new UUID(0L, 0L); public static final UUID getNullUUID() {return b;} // Paper OBFHELPER -@@ -85,15 +86,18 @@ public class SystemUtils { - return Instant.now().toEpochMilli(); - } - -- private static ExecutorService a(String s) { -- int i = MathHelper.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, 7); -- Object object; -+ private static ExecutorService a(String s, int priorityModifier) { // Paper - add priority -+ // Paper start - use simpler thread pool that allows 1 thread -+ int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1)); -+ i = Integer.getInteger("Paper.WorkerThreadCount", i); -+ ExecutorService object; - - if (i <= 0) { - object = MoreExecutors.newDirectExecutorService(); - } else { -- object = new ForkJoinPool(i, (forkjoinpool) -> { -- ForkJoinWorkerThread forkjoinworkerthread = new ForkJoinWorkerThread(forkjoinpool) { -+ object = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue(), target -> new ServerWorkerThread(target, s, priorityModifier)); -+ } -+ /* - protected void onTermination(Throwable throwable) { - if (throwable != null) { - SystemUtils.LOGGER.warn("{} died", this.getName(), throwable); -@@ -109,6 +113,7 @@ public class SystemUtils { - return forkjoinworkerthread; - }, SystemUtils::a, true); - } -+ }*/ // Paper end - - return (ExecutorService) object; - } -@@ -157,6 +162,7 @@ public class SystemUtils { - }); - } - -+ public static void onThreadError(Thread thread, Throwable throwable) { a(thread, throwable); } // Paper - OBFHELPER - private static void a(Thread thread, Throwable throwable) { - c(throwable); - if (throwable instanceof CompletionException) { -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 52c0dd4f2779125116d9dcccc2aef7a11af92945..7d1ed99a919194296ee08a67cc543bedcf48395a 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -286,6 +286,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Fri, 2 Nov 2018 23:11:51 -0400 -Subject: [PATCH] Optimize World Time Updates - -Splits time updates into incremental updates as well as does -the updates per world, so that we can re-use the same packet -object for every player unless they have per-player time enabled. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 7d1ed99a919194296ee08a67cc543bedcf48395a..419448fe02b58e08c17795c903c945ad8a3ce1b5 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1316,12 +1316,24 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Mon, 5 Nov 2018 04:23:51 +0000 -Subject: [PATCH] Restore custom InventoryHolder support - -Upstream removed the ability to consistently use a custom InventoryHolder, -However, the implementation does not use an InventoryHolder in any form -outside of custom inventories. - -We can take that knowledge and apply some expected behavior, if we're given -an inventory holder, we should use it and return a custom inventory with the -holder, otherwise, create an inventory backed by the intended inventory, as -per upstream behavior. - -This provides a "best of both worlds" scenario: plugins with InventoryHolder's -will always work as intended in the past, those without will create implementation -based inventories. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -index 94d807c5d09f165c6eedd0a1c4026c2b833806a0..3e56de295be0d03dddd3e54fcd7b05d4b9c74dc4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -@@ -40,6 +40,11 @@ public final class CraftInventoryCreator { - } - - public Inventory createInventory(InventoryHolder holder, InventoryType type) { -+ // Paper start -+ if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type); -+ } -+ //noinspection ConstantConditions // Paper end - return converterMap.get(type).createInventory(holder, type); - } - -@@ -55,6 +60,11 @@ public final class CraftInventoryCreator { - // Paper end - - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { -+ // Paper start -+ if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type, title); -+ } -+ //noinspection ConstantConditions // Paper end - return converterMap.get(type).createInventory(holder, type, title); - } - diff --git a/Unmapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch b/Unmapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch deleted file mode 100644 index 7e7e806b36..0000000000 --- a/Unmapped-Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 8 Nov 2018 21:33:09 -0500 -Subject: [PATCH] Use Vanilla Minecart Speeds - -CraftBukkit changed the values on flying speed, restore back to vanilla - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 1f94cc096d95129d85a6278b1e369729df93d27d..7d91e6b75a8a827853b0ca8e53b8ec19e2cf1092 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -100,9 +100,9 @@ public abstract class EntityMinecartAbstract extends Entity { - private double derailedX = 0.5; - private double derailedY = 0.5; - private double derailedZ = 0.5; -- private double flyingX = 0.95; -- private double flyingY = 0.95; -- private double flyingZ = 0.95; -+ private double flyingX = 0.949999988079071D; // Paper - restore vanilla precision -+ private double flyingY = 0.949999988079071D; // Paper - restore vanilla precision -+ private double flyingZ = 0.949999988079071D; // Paper - restore vanilla precision - public double maxSpeed = 0.4D; - // CraftBukkit end - diff --git a/Unmapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch b/Unmapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch deleted file mode 100644 index f0c682b058..0000000000 --- a/Unmapped-Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 10 Nov 2018 05:15:21 +0000 -Subject: [PATCH] Fix SpongeAbsortEvent handling - -Only process drops when the block is actually going to be removed - -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 615a4418fd276cd3e0b3686d962ebaf13ef5d4be..e5c43b383a93fac76333a67b41535ab009d1dcf3 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -228,6 +228,7 @@ public class Block extends BlockBase implements IMaterial { - - } - -+ public static void dropNaturally(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, @Nullable TileEntity tileentity) { a(iblockdata, generatoraccess, blockposition, tileentity); } - public static void a(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, @Nullable TileEntity tileentity) { - if (generatoraccess instanceof WorldServer) { - a(iblockdata, (WorldServer) generatoraccess, blockposition, tileentity).forEach((itemstack) -> { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockSponge.java b/src/main/java/net/minecraft/world/level/block/BlockSponge.java -index ef48ad0ab68e2e050bc8aca484d850297990b78e..d80eee47390ab202eea0368571421bbc94655ab1 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockSponge.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockSponge.java -@@ -129,8 +129,11 @@ public class BlockSponge extends Block { - // NOP - } else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) { - TileEntity tileentity = iblockdata.getBlock().isTileEntity() ? world.getTileEntity(blockposition2) : null; -- -- a(iblockdata, world, blockposition2, tileentity); -+ // Paper start -+ if (block.getHandle().getMaterial() == Material.AIR) { -+ dropNaturally(iblockdata, world, blockposition2, tileentity); -+ } -+ // Paper end - } - } - world.setTypeAndData(blockposition2, block.getHandle(), block.getFlag()); diff --git a/Unmapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch b/Unmapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch deleted file mode 100644 index 2447748fec..0000000000 --- a/Unmapped-Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 11 Nov 2018 21:01:09 +0000 -Subject: [PATCH] Don't allow digging into unloaded chunks - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 14f287d30c9a141f78f6311bef02a6fc4fa17564..d86b1e528b53db809ac993aa2f1d2799d4f1a574 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -114,8 +114,8 @@ public class PlayerInteractManager { - IBlockData iblockdata; - - if (this.j) { -- iblockdata = this.world.getType(this.k); -- if (iblockdata.isAir()) { -+ iblockdata = this.world.getTypeIfLoaded(this.k); // Paper -+ if (iblockdata == null || iblockdata.isAir()) { // Paper - this.j = false; - } else { - float f = this.a(iblockdata, this.k, this.l); -@@ -126,7 +126,13 @@ public class PlayerInteractManager { - } - } - } else if (this.f) { -- iblockdata = this.world.getType(this.h); -+ // Paper start - don't want to do same logic as above, return instead -+ iblockdata = this.world.getTypeIfLoaded(this.h); -+ if (iblockdata == null) { -+ this.f = false; -+ return; -+ } -+ // Paper end - if (iblockdata.isAir()) { - this.world.a(this.player.getId(), this.h, -1); - this.m = -1; -@@ -290,10 +296,12 @@ public class PlayerInteractManager { - this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(blockposition, this.world.getType(blockposition), packetplayinblockdig_enumplayerdigtype, true, "stopped destroying")); - } else if (packetplayinblockdig_enumplayerdigtype == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { - this.f = false; -- if (!Objects.equals(this.h, blockposition)) { -+ if (!Objects.equals(this.h, blockposition) && !BlockPosition.ZERO.equals(this.h)) { - PlayerInteractManager.LOGGER.debug("Mismatch in destroy block pos: " + this.h + " " + blockposition); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled -- this.world.a(this.player.getId(), this.h, -1); -- this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(this.h, this.world.getType(this.h), packetplayinblockdig_enumplayerdigtype, true, "aborted mismatched destroying")); -+ IBlockData type = this.world.getTypeIfLoaded(this.h); // Paper - don't load unloaded chunks for stale records here -+ if (type != null) this.world.a(this.player.getId(), this.h, -1); // Paper -+ if (type != null) this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(this.h, type, packetplayinblockdig_enumplayerdigtype, true, "aborted mismatched destroying")); // Paper -+ this.h = BlockPosition.ZERO; // Paper - } - - this.world.a(this.player.getId(), blockposition, -1); -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index f48683ef9afe3e5d0e0e5959c698152e9086632b..6f40d9fd45b42935d6eb58981f1d7aac2b4c2454 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1520,6 +1520,11 @@ public class PlayerConnection implements PacketListenerPlayIn { - case START_DESTROY_BLOCK: - case ABORT_DESTROY_BLOCK: - case STOP_DESTROY_BLOCK: -+ // Paper start - Don't allow digging in unloaded chunks -+ if (this.player.world.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { -+ return; -+ } -+ // Paper end - Don't allow digging in unloaded chunks - this.player.playerInteractManager.a(blockposition, packetplayinblockdig_enumplayerdigtype, packetplayinblockdig.c(), this.minecraftServer.getMaxBuildHeight()); - return; - default: diff --git a/Unmapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch b/Unmapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch deleted file mode 100644 index cbabef0949..0000000000 --- a/Unmapped-Spigot-Server-Patches/0311-Book-Size-Limits.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 16 Nov 2018 23:08:50 -0500 -Subject: [PATCH] Book Size Limits - -Puts some limits on the size of books. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 3139c194f9b1bc3510d51a81f13ae43d00a3dc29..13edb435b3fa65b4980bd7472aa5a5196f4d5b2b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -339,4 +339,11 @@ public class PaperConfig { - velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); - } - } -+ -+ public static int maxBookPageSize = 2560; -+ public static double maxBookTotalSizeMultiplier = 0.98D; -+ private static void maxBookSize() { -+ maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); -+ maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 6f40d9fd45b42935d6eb58981f1d7aac2b4c2454..54399a2f2d1d86b650e27f6a31dce89035e7aeba 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1001,6 +1001,52 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInBEdit packetplayinbedit) { -+ // Paper start -+ ItemStack testStack = packetplayinbedit.getBook(); -+ if (!server.isPrimaryThread() && !testStack.isEmpty() && testStack.getTag() != null) { -+ NBTTagList pageList = testStack.getTag().getList("pages", 8); -+ if (pageList.size() > 100) { -+ PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with too many pages"); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ return; -+ } -+ long byteTotal = 0; -+ int maxBookPageSize = com.destroystokyo.paper.PaperConfig.maxBookPageSize; -+ double multiplier = Math.max(0.3D, Math.min(1D, com.destroystokyo.paper.PaperConfig.maxBookTotalSizeMultiplier)); -+ long byteAllowed = maxBookPageSize; -+ for (int i = 0; i < pageList.size(); ++i) { -+ String testString = pageList.getString(i); -+ int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; -+ if (byteLength > 256 * 4) { -+ PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with with a page too large!"); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ return; -+ } -+ byteTotal += byteLength; -+ int length = testString.length(); -+ int multibytes = 0; -+ if (byteLength != length) { -+ for (char c : testString.toCharArray()) { -+ if (c > 127) { -+ multibytes++; -+ } -+ } -+ } -+ byteAllowed += (maxBookPageSize * Math.min(1, Math.max(0.1D, (double) length / 255D))) * multiplier; -+ -+ if (multibytes > 1) { -+ // penalize MB -+ byteAllowed -= multibytes; -+ } -+ } -+ -+ if (byteTotal > byteAllowed) { -+ PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ return; -+ } -+ } -+ // Paper end - // CraftBukkit start - if (this.lastBookTick + 20 > MinecraftServer.currentTick) { - this.disconnect("Book edited too quickly!"); diff --git a/Unmapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch b/Unmapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch deleted file mode 100644 index 89df9fee73..0000000000 --- a/Unmapped-Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 18 Nov 2018 19:49:56 +0000 -Subject: [PATCH] Make the default permission message configurable - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 13edb435b3fa65b4980bd7472aa5a5196f4d5b2b..469f78775b03cf363d88e35c69c0dc185c22547c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -19,6 +19,7 @@ import java.util.regex.Pattern; - import com.google.common.collect.Lists; - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; - import org.bukkit.command.Command; - import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.InvalidConfigurationException; -@@ -287,6 +288,11 @@ public class PaperConfig { - connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); - } - -+ public static String noPermissionMessage = "&cI'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error."; -+ private static void noPermissionMessage() { -+ noPermissionMessage = ChatColor.translateAlternateColorCodes('&', getString("messages.no-permission", noPermissionMessage)); -+ } -+ - private static void savePlayerData() { - Object val = config.get("settings.save-player-data"); - if (val instanceof Boolean) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 22f9d8c0189293b88353bbe1bcc40dd1d431d458..aff20bc4a4d9834b2555f5fe4fa9c46751eae2ba 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2341,6 +2341,11 @@ public final class CraftServer implements Server { - return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; - } - -+ @Override -+ public String getPermissionMessage() { -+ return com.destroystokyo.paper.PaperConfig.noPermissionMessage; -+ } -+ - @Override - public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { - return createProfile(uuid, null); diff --git a/Unmapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch b/Unmapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch deleted file mode 100644 index 0295326280..0000000000 --- a/Unmapped-Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 26 Nov 2018 19:21:58 -0500 -Subject: [PATCH] Prevent rayTrace from loading chunks - -ray tracing into an unloaded chunk should be treated as a miss -this saves a ton of lag for when AI tries to raytrace near unloaded chunks. - -diff --git a/src/main/java/net/minecraft/world/level/IBlockAccess.java b/src/main/java/net/minecraft/world/level/IBlockAccess.java -index e799765ecfada1eec78beb71651e52ad355a30aa..21ce19b9caf3150535a3f84027242a93bdd0d263 100644 ---- a/src/main/java/net/minecraft/world/level/IBlockAccess.java -+++ b/src/main/java/net/minecraft/world/level/IBlockAccess.java -@@ -58,7 +58,15 @@ public interface IBlockAccess { - - // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace - default MovingObjectPositionBlock rayTraceBlock(RayTrace raytrace1, BlockPosition blockposition) { -- IBlockData iblockdata = this.getType(blockposition); -+ // Paper start - Prevent raytrace from loading chunks -+ IBlockData iblockdata = this.getTypeIfLoaded(blockposition); -+ if (iblockdata == null) { -+ // copied the last function parameter (listed below) -+ Vec3D vec3d = raytrace1.b().d(raytrace1.a()); -+ -+ return MovingObjectPositionBlock.a(raytrace1.a(), EnumDirection.a(vec3d.x, vec3d.y, vec3d.z), new BlockPosition(raytrace1.a())); -+ } -+ // Paper end - Fluid fluid = this.getFluid(blockposition); - Vec3D vec3d = raytrace1.b(); - Vec3D vec3d1 = raytrace1.a(); diff --git a/Unmapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch b/Unmapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch deleted file mode 100644 index 9f62fd514e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 27 Nov 2018 21:18:06 -0500 -Subject: [PATCH] Handle Large Packets disconnecting client - -If a players inventory is too big to send in a single packet, -split the inventory set into multiple packets instead. - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 297820baef99e97e1216a64c527219e9ccc3e320..dc788d75a6a34fbbae990609bfbbd13ca6cdee5a 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -12,6 +12,7 @@ import io.netty.channel.epoll.EpollEventLoopGroup; - import io.netty.channel.local.LocalChannel; - import io.netty.channel.local.LocalServerChannel; - import io.netty.channel.nio.NioEventLoopGroup; -+import io.netty.handler.codec.EncoderException; // Paper - import io.netty.handler.timeout.TimeoutException; - import io.netty.util.AttributeKey; - import io.netty.util.concurrent.Future; -@@ -107,6 +108,15 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - - public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { -+ // Paper start -+ if (throwable instanceof EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) { -+ if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) { -+ return; -+ } else { -+ throwable = throwable.getCause(); -+ } -+ } -+ // Paper end - if (throwable instanceof SkipEncodeException) { - NetworkManager.LOGGER.debug("Skipping packet due to errors", throwable.getCause()); - } else { -diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index 2f6da89d6b25ba5144ec15b1bf0e8ed13278e85e..037d989522d24a55eced1c462d40a6dc2a7ecfce 100644 ---- a/src/main/java/net/minecraft/network/PacketEncoder.java -+++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -53,7 +53,31 @@ public class PacketEncoder extends MessageToByteEncoder> { - throw throwable; - } - } -+ -+ // Paper start -+ int packetLength = bytebuf.readableBytes(); -+ if (packetLength > MAX_PACKET_SIZE) { -+ throw new PacketTooLargeException(packet, packetLength); -+ } -+ // Paper end - } - } - } -+ -+ // Paper start -+ private static int MAX_PACKET_SIZE = 2097152; -+ -+ public static class PacketTooLargeException extends RuntimeException { -+ private final Packet packet; -+ -+ PacketTooLargeException(Packet packet, int packetLength) { -+ super("PacketTooLarge - " + packet.getClass().getSimpleName() + " is " + packetLength + ". Max is " + MAX_PACKET_SIZE); -+ this.packet = packet; -+ } -+ -+ public Packet getPacket() { -+ return packet; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index cd4493a023748264748d4e892815f14d8a7bd7f6..0783b0777c8d7788bbf6780b464b709bf6dc2191 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -12,6 +12,12 @@ public interface Packet { - - void a(T t0); - -+ // Paper start -+ default boolean packetTooLarge(NetworkManager manager) { -+ return false; -+ } -+ // Paper end -+ - default boolean a() { - return false; - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index 152118729b1a95dcae05d32aa4289034ba394226..0059ede4ba3ff271d47dd38ea87fddc2399aa008 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -91,7 +91,7 @@ public class PacketPlayOutMapChunk implements Packet { - - int i = packetdataserializer.i(); - -- if (i > 2097152) { -+ if (i > 2097152) { // Paper - if this changes, update PacketEncoder - throw new RuntimeException("Chunk Packet trying to allocate too much memory on read."); - } else { - this.f = new byte[i]; -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java -index b90e35a0099a2482f8fc2998bd079fc2fe6439e6..e540f95a370c627d3d81e0d3670049d01923559d 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java -@@ -4,6 +4,7 @@ import java.io.IOException; - import java.util.Iterator; - import java.util.List; - import net.minecraft.core.NonNullList; -+import net.minecraft.network.NetworkManager; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.protocol.Packet; - import net.minecraft.world.item.ItemStack; -@@ -13,6 +14,15 @@ public class PacketPlayOutWindowItems implements Packet { - private int a; - private List b; - -+ //Paper start -+ @Override -+ public boolean packetTooLarge(NetworkManager manager) { -+ for (int i = 0 ; i < this.b.size() ; i++) { -+ manager.sendPacket(new PacketPlayOutSetSlot(this.a, i, this.b.get(i))); -+ } -+ return true; -+ } -+ // Paper end - public PacketPlayOutWindowItems() {} - - public PacketPlayOutWindowItems(int i, NonNullList nonnulllist) { diff --git a/Unmapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch b/Unmapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch deleted file mode 100644 index 966dd873fc..0000000000 --- a/Unmapped-Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 15 Nov 2018 13:38:37 +0000 -Subject: [PATCH] force entity dismount during teleportation - -Entities must be dismounted before teleportation in order to avoid -multiple issues in the server with regards to teleportation, shamefully, -too many plugins rely on the events firing, which means that not firing -these events caues more issues than it solves; - -In order to counteract this, Entity dismount/exit vehicle events have -been modified to supress cancellation (and has a method to allow plugins -to check if this has been set), noting that cancellation will be silently -surpressed given that plugins are not expecting this event to not be cancellable. - -This is a far from ideal scenario, however: given the current state of this -event and other alternatives causing issues elsewhere, I believe that -this is going to be the best soultion all around. - -Improvements/suggestions welcome! - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 3e7ac6699ad1f147220c286e251ce0ec1ca25035..e755191435e74246b309f8fe5a668dae2e499df1 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1261,11 +1261,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - } - -- @Override -- public void stopRiding() { -+ // Paper start -+ @Override public void stopRiding() { stopRiding(false); } -+ @Override public void stopRiding(boolean suppressCancellation) { -+ // paper end - Entity entity = this.getVehicle(); - -- super.stopRiding(); -+ super.stopRiding(suppressCancellation); // Paper - Entity entity1 = this.getVehicle(); - - if (entity1 != entity && this.playerConnection != null) { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 2292295bac55651850b5e033f1ca9819bb7fa96f..af38b81df3f60163cafc341543ecad0865225943 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2045,12 +2045,15 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - } - -- public void bf() { -+ // Paper start -+ public void bf() { stopRiding(false); } -+ public void stopRiding(boolean suppressCancellation) { -+ // Paper end - if (this.vehicle != null) { - Entity entity = this.vehicle; - - this.vehicle = null; -- if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit -+ if (!entity.removePassenger(this, suppressCancellation)) this.vehicle = entity; // CraftBukkit // Paper - } - - } -@@ -2105,7 +2108,10 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return true; // CraftBukkit - } - -- protected boolean removePassenger(Entity entity) { // CraftBukkit -+ // Paper start -+ protected boolean removePassenger(Entity entity) { return removePassenger(entity, false);} -+ protected boolean removePassenger(Entity entity, boolean suppressCancellation) { // CraftBukkit -+ // Paper end - if (entity.getVehicle() == this) { - throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); - } else { -@@ -2115,7 +2121,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { - VehicleExitEvent event = new VehicleExitEvent( - (Vehicle) getBukkitEntity(), -- (LivingEntity) entity.getBukkitEntity() -+ (LivingEntity) entity.getBukkitEntity(), !suppressCancellation // Paper - ); - // Suppress during worldgen - if (this.valid) { -@@ -2129,7 +2135,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - // Spigot start -- org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity()); -+ org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity(), !suppressCancellation); // Paper - // Suppress during worldgen - if (this.valid) { - Bukkit.getPluginManager().callEvent(event); -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index e20acbd904f12e9036cb0565d6aa9a3f63008d43..32a2d6fd22ba69694a2f620174f618a95964074d 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3015,11 +3015,13 @@ public abstract class EntityLiving extends Entity { - return ((Byte) this.datawatcher.get(EntityLiving.ag) & 4) != 0; - } - -- @Override -- public void stopRiding() { -+ // Paper start -+ @Override public void stopRiding() { stopRiding(false); } -+ @Override public void stopRiding(boolean suppressCancellation) { -+ // Paper end - Entity entity = this.getVehicle(); - -- super.stopRiding(); -+ super.stopRiding(suppressCancellation); // Paper - suppress - if (entity != null && entity != this.getVehicle() && !this.world.isClientSide) { - this.a(entity); - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 87374174dcbf9e7ee448a1cdd9a3528557c3a2ea..564dfa98c166fde509044e6e1938efb321ece53d 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1039,9 +1039,11 @@ public abstract class EntityHuman extends EntityLiving { - return -0.35D; - } - -- @Override -- public void bf() { -- super.bf(); -+ // Paper start -+ @Override public void bf() { stopRiding(false); } -+ @Override public void stopRiding(boolean suppressCancellation) { -+ // Paper end -+ super.stopRiding(suppressCancellation); // Paper - suppress - this.j = 0; - } - diff --git a/Unmapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch b/Unmapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch deleted file mode 100644 index c620328b1a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0316-Add-more-Zombie-API.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 Oct 2018 04:29:59 -0500 -Subject: [PATCH] Add more Zombie API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 219e3b1626d68ede57b08a706d24bb6bc4b13fac..79d34b0296f88e5b4fe0351fe2483fc0128deabc 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -94,6 +94,7 @@ public class EntityZombie extends EntityMonster { - private int bt; - public int drownedConversionTime; - private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field -+ private boolean shouldBurnInDay = true; // Paper - - public EntityZombie(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -262,6 +263,12 @@ public class EntityZombie extends EntityMonster { - super.movementTick(); - } - -+ // Paper start -+ public void stopDrowning() { -+ this.drownedConversionTime = -1; -+ this.getDataWatcher().set(EntityZombie.DROWN_CONVERTING, false); -+ } -+ // Paper end - public void startDrownedConversion(int i) { - this.lastTick = MinecraftServer.currentTick; // CraftBukkit - this.drownedConversionTime = i; -@@ -290,9 +297,16 @@ public class EntityZombie extends EntityMonster { - - } - -+ public boolean shouldBurnInDay() { return T_(); } // Paper - OBFHELPER - protected boolean T_() { -- return true; -+ return this.shouldBurnInDay; // Paper - use api value instead -+ } -+ -+ // Paper start -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ this.shouldBurnInDay = shouldBurnInDay; - } -+ // Paper end - - @Override - public boolean damageEntity(DamageSource damagesource, float f) { -@@ -413,6 +427,7 @@ public class EntityZombie extends EntityMonster { - nbttagcompound.setBoolean("CanBreakDoors", this.eU()); - nbttagcompound.setInt("InWaterTime", this.isInWater() ? this.bt : -1); - nbttagcompound.setInt("DrownedConversionTime", this.isDrownConverting() ? this.drownedConversionTime : -1); -+ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); // Paper - } - - @Override -@@ -424,7 +439,11 @@ public class EntityZombie extends EntityMonster { - if (nbttagcompound.hasKeyOfType("DrownedConversionTime", 99) && nbttagcompound.getInt("DrownedConversionTime") > -1) { - this.startDrownedConversion(nbttagcompound.getInt("DrownedConversionTime")); - } -- -+ // Paper start -+ if (nbttagcompound.hasKey("Paper.ShouldBurnInDay")) { -+ shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); -+ } -+ // Paper end - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 8ba92b7edacc088d610a9ed46eb7f61ebd8101a8..42d98d798bb8fe2d3c7cc2bfcf2ec38d97d99bd2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -@@ -94,6 +94,42 @@ public class CraftZombie extends CraftMonster implements Zombie { - @Override - public void setAgeLock(boolean b) { - } -+ // Paper start -+ @Override -+ public boolean isDrowning() { -+ return getHandle().isDrownConverting(); -+ } -+ -+ @Override -+ public void startDrowning(int drownedConversionTime) { -+ getHandle().startDrownedConversion(drownedConversionTime); -+ } -+ -+ @Override -+ public void stopDrowning() { -+ getHandle().stopDrowning(); -+ } -+ -+ @Override -+ public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); -+ } -+ -+ @Override -+ public boolean isArmsRaised() { -+ return getHandle().isAggressive(); -+ } -+ -+ @Override -+ public void setArmsRaised(final boolean raised) { -+ getHandle().setAggressive(raised); -+ } -+ -+ @Override -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ getHandle().setShouldBurnInDay(shouldBurnInDay); -+ } -+ // Paper end - - @Override - public boolean getAgeLock() { diff --git a/Unmapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch b/Unmapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch deleted file mode 100644 index 4911606848..0000000000 --- a/Unmapped-Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 7 Oct 2018 12:05:28 -0700 -Subject: [PATCH] Add PlayerConnectionCloseEvent - -This event is invoked when a player has disconnected. It is guaranteed that, -if the server is in online-mode, that the provided uuid and username have been -validated. - -The event is invoked for players who have not yet logged into the world, whereas -PlayerQuitEvent is only invoked on players who have logged into the world. - -The event is invoked for players who have already logged into the world, -although whether or not the player exists in the world at the time of -firing is undefined. (That is, whether the plugin can retrieve a Player object -using the event parameters is undefined). However, it is guaranteed that this -event is invoked AFTER PlayerQuitEvent, if the player has already logged into -the world. - -This event is guaranteed to never fire unless AsyncPlayerPreLoginEvent has -been called beforehand, and this event may not be called in parallel with -AsyncPlayerPreLoginEvent for the same connection. - -Cancelling the AsyncPlayerPreLoginEvent guarantees the corresponding -PlayerConnectionCloseEvent is never called. - -The event may be invoked asynchronously or synchronously. As it stands, -it is never invoked asynchronously. However, plugins should check -Event#isAsynchronous to be future-proof. - -On purpose, the deprecated PlayerPreLoginEvent event is left out of the -API spec for this event. Plugins should not be using that event, and -how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent -is undefined. - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index dc788d75a6a34fbbae990609bfbbd13ca6cdee5a..6d40ade5a52383ed86d28d272c3dc83dbdcbd218 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -350,6 +350,26 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - this.j().a(new ChatMessage("multiplayer.disconnect.generic")); - } - this.packetQueue.clear(); // Free up packet queue. -+ // Paper start - Add PlayerConnectionCloseEvent -+ final PacketListener packetListener = this.j(); -+ if (packetListener instanceof PlayerConnection) { -+ /* Player was logged in */ -+ final PlayerConnection playerConnection = (PlayerConnection) packetListener; -+ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(playerConnection.player.getUniqueID(), -+ playerConnection.player.getName(), ((java.net.InetSocketAddress)socketAddress).getAddress(), false).callEvent(); -+ } else if (packetListener instanceof LoginListener) { -+ /* Player is login stage */ -+ final LoginListener loginListener = (LoginListener) packetListener; -+ switch (loginListener.getLoginState()) { -+ case READY_TO_ACCEPT: -+ case DELAY_ACCEPT: -+ case ACCEPTED: -+ final com.mojang.authlib.GameProfile profile = loginListener.getGameProfile(); /* Should be non-null at this stage */ -+ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(profile.getId(), profile.getName(), -+ ((java.net.InetSocketAddress)socketAddress).getAddress(), false).callEvent(); -+ } -+ } -+ // Paper end - } - - } -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index b89a8ee2ea03d00a3d6af63d6e3e0fd62af31130..2e995103fba15c21dbe89321896c7df03ae5e67b 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -57,9 +57,9 @@ public class LoginListener implements PacketLoginInListener { - private final byte[] e = new byte[4]; - private final MinecraftServer server; - public final NetworkManager networkManager; -- private LoginListener.EnumProtocolState g; -+ private LoginListener.EnumProtocolState g; public final LoginListener.EnumProtocolState getLoginState() { return this.g; }; // Paper - OBFHELPER - private int h; -- private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } private GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER -+ private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } public GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER - private final String j; - private SecretKey loginKey; - private EntityPlayer l; diff --git a/Unmapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch b/Unmapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch deleted file mode 100644 index 86be24f3d4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 18 Dec 2018 02:15:08 +0000 -Subject: [PATCH] Prevent Enderman from loading chunks - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index aa6cb15637144c9d8db1b1861e58f3f02d68357a..e993b1849beb60515c51ee4f37617faab63ca223 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -434,7 +434,8 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - int j = MathHelper.floor(this.enderman.locY() + random.nextDouble() * 3.0D); - int k = MathHelper.floor(this.enderman.locZ() - 2.0D + random.nextDouble() * 4.0D); - BlockPosition blockposition = new BlockPosition(i, j, k); -- IBlockData iblockdata = world.getType(blockposition); -+ IBlockData iblockdata = world.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return; // Paper - Block block = iblockdata.getBlock(); - Vec3D vec3d = new Vec3D((double) MathHelper.floor(this.enderman.locX()) + 0.5D, (double) j + 0.5D, (double) MathHelper.floor(this.enderman.locZ()) + 0.5D); - Vec3D vec3d1 = new Vec3D((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); -@@ -474,7 +475,8 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - int j = MathHelper.floor(this.a.locY() + random.nextDouble() * 2.0D); - int k = MathHelper.floor(this.a.locZ() - 1.0D + random.nextDouble() * 2.0D); - BlockPosition blockposition = new BlockPosition(i, j, k); -- IBlockData iblockdata = world.getType(blockposition); -+ IBlockData iblockdata = world.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return; // Paper - BlockPosition blockposition1 = blockposition.down(); - IBlockData iblockdata1 = world.getType(blockposition1); - IBlockData iblockdata2 = this.a.getCarried(); diff --git a/Unmapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/Unmapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch deleted file mode 100644 index aefc2dfd10..0000000000 --- a/Unmapped-Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Jan 2019 00:35:43 -0600 -Subject: [PATCH] Add APIs to replace OfflinePlayer#getLastPlayed - -Currently OfflinePlayer#getLastPlayed could more accurately be described -as "OfflinePlayer#getLastTimeTheirDataWasSaved". - -The API doc says it should return the last time the server "witnessed" -the player, whilst also saying it should return the last time they -logged in. The current implementation does neither. - -Given this interesting contradiction in the API documentation and the -current defacto implementation, I've elected to deprecate (with no -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/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index e755191435e74246b309f8fe5a668dae2e499df1..8d88ed3d68146fbcb090847351945689518e59a9 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -214,6 +214,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public int ping; - public boolean viewingCredits; - private int containerUpdateDelay; // Paper -+ public long loginTime; // Paper - // Paper start - cancellable death event - public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 2299581fa889c0e8ddc6b2cc1d3551d02ff8dc2d..7515e9ddbc89de882373469cf3c46046c76af974 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -168,6 +168,7 @@ public abstract class PlayerList { - } - - public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { -+ entityplayer.loginTime = System.currentTimeMillis(); // Paper - GameProfile gameprofile = entityplayer.getProfile(); - UserCache usercache = this.server.getUserCache(); - GameProfile gameprofile1 = usercache.getProfile(gameprofile.getId()); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -index 9b8d7b176e288fa715177196e7aff92900d8567a..1e741158bbcc0991259436bec549b32df61f0c54 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -@@ -244,6 +244,61 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa - return getData() != null; - } - -+ // Paper start -+ @Override -+ public long getLastLogin() { -+ Player player = getPlayer(); -+ if (player != null) return player.getLastLogin(); -+ -+ NBTTagCompound data = getPaperData(); -+ -+ if (data != null) { -+ if (data.hasKey("LastLogin")) { -+ return data.getLong("LastLogin"); -+ } else { -+ // if the player file cannot provide accurate data, this is probably the closest we can approximate -+ File file = getDataFile(); -+ return file.lastModified(); -+ } -+ } else { -+ return 0; -+ } -+ } -+ -+ @Override -+ public long getLastSeen() { -+ Player player = getPlayer(); -+ if (player != null) return player.getLastSeen(); -+ -+ NBTTagCompound data = getPaperData(); -+ -+ if (data != null) { -+ if (data.hasKey("LastSeen")) { -+ return data.getLong("LastSeen"); -+ } else { -+ // if the player file cannot provide accurate data, this is probably the closest we can approximate -+ File file = getDataFile(); -+ return file.lastModified(); -+ } -+ } else { -+ return 0; -+ } -+ } -+ -+ private NBTTagCompound getPaperData() { -+ NBTTagCompound result = getData(); -+ -+ if (result != null) { -+ if (!result.hasKey("Paper")) { -+ result.set("Paper", new NBTTagCompound()); -+ } -+ result = result.getCompound("Paper"); -+ } -+ -+ return result; -+ } -+ // Paper end -+ - @Override - public Location getBedSpawnLocation() { - NBTTagCompound data = getData(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 6c5075ef2420131aa21b403623a5dfa485ee73e5..25e0d0dd7b114560896679f0314cea288d7a768c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -147,6 +147,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; - private String resourcePackHash; - private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit -+ private long lastSaveTime; - // Paper end - - public CraftPlayer(CraftServer server, EntityPlayer entity) { -@@ -1483,6 +1484,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - this.firstPlayed = firstPlayed; - } - -+ // Paper start -+ @Override -+ public long getLastLogin() { -+ return getHandle().loginTime; -+ } -+ -+ @Override -+ public long getLastSeen() { -+ return isOnline() ? System.currentTimeMillis() : this.lastSaveTime; -+ } -+ // Paper end -+ - public void readExtraData(NBTTagCompound nbttagcompound) { - hasPlayedBefore = true; - if (nbttagcompound.hasKey("bukkit")) { -@@ -1505,6 +1518,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void setExtraData(NBTTagCompound nbttagcompound) { -+ this.lastSaveTime = System.currentTimeMillis(); // Paper -+ - if (!nbttagcompound.hasKey("bukkit")) { - nbttagcompound.set("bukkit", new NBTTagCompound()); - } -@@ -1519,6 +1534,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - data.setLong("firstPlayed", getFirstPlayed()); - data.setLong("lastPlayed", System.currentTimeMillis()); - data.setString("lastKnownName", handle.getName()); -+ -+ // Paper start - persist for use in offline save data -+ if (!nbttagcompound.hasKey("Paper")) { -+ nbttagcompound.set("Paper", new NBTTagCompound()); -+ } -+ -+ NBTTagCompound paper = nbttagcompound.getCompound("Paper"); -+ paper.setLong("LastLogin", handle.loginTime); -+ paper.setLong("LastSeen", System.currentTimeMillis()); -+ // Paper end - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/Unmapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch deleted file mode 100644 index dcefdae5b4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: connorhartley -Date: Mon, 7 Jan 2019 14:43:48 -0600 -Subject: [PATCH] Workaround for vehicle tracking issue on disconnect - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 8d88ed3d68146fbcb090847351945689518e59a9..82f49078a91b6ac471d303bc68891d80e201bd1f 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1527,6 +1527,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public void p() { - this.ch = true; - this.ejectPassengers(); -+ -+ // Paper start - Workaround an issue where the vehicle doesn't track the passenger disconnection dismount. -+ if (this.isPassenger() && this.getVehicle() instanceof EntityPlayer) { -+ this.stopRiding(); -+ } -+ // Paper end -+ - if (this.isSleeping()) { - this.wakeup(true, false); - } diff --git a/Unmapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/Unmapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch deleted file mode 100644 index 79adf82b5f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 31 Jan 2019 16:33:36 -0500 -Subject: [PATCH] Fire BlockPistonRetractEvent for all empty pistons - -There is an explicit check in the handling code for empty pistons that -prevents sticky pistons from firing the event. However when we look back -at the history we see that this check was originally added so that ONLY -sticky pistons would fire the retract event. I'm not sure why. -https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1092acbddf07edfa4100bc6824504ac75088e913 - -Over the course of several updates, the meaning of that field appears to -have changed from "is NOT sticky" to "is sticky". So now its having the -opposite effect. Only normal pistons fire the retraction event. And like -all things in CB, it's just been carried around since. - -If we are to believe the history, the correct fix for this issue is to -flip it so it only fires for sticky pistons, but that puts us in a -bind. It's already firing for non-sticky pistons, changing it now would -likely result in breakage. Furthermore, there is little documentation as -to WHY that was ever intended to be the case. - -Instead we opt to remove the check entirely so that the event fires for -all piston types. - -diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -index 869aaae93bc83b8271644147bb569c868ab13fb8..7de86d6232eb84642fb6423a1b0a9f30d9df9f2b 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -@@ -141,7 +141,7 @@ public class BlockPiston extends BlockDirectional { - } - - // CraftBukkit start -- if (!this.sticky) { -+ //if (!this.sticky) { // Paper - Prevents empty sticky pistons from firing retract - history behind is odd - org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); - BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); - world.getServer().getPluginManager().callEvent(event); -@@ -149,7 +149,7 @@ public class BlockPiston extends BlockDirectional { - if (event.isCancelled()) { - return; - } -- } -+ //} // Paper - // PAIL: checkME - what happened to setTypeAndData? - // CraftBukkit end - world.playBlockAction(blockposition, this, b0, enumdirection.c()); diff --git a/Unmapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch b/Unmapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch deleted file mode 100644 index 64d8d081f7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 4 Feb 2019 23:33:24 -0500 -Subject: [PATCH] Block Entity#remove from being called on Players - -This doesn't result in the same behavior as other entities and causes -several problems. Anyone ever complain about the "Cannot send chat -message" thing? That's one of the issues this causes, among others. - -If a plugin developer can come up with a valid reason to call this on a -Player we will look at limiting the scope of this change. It appears to -be unintentional in the few cases we've seen so far. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 25e0d0dd7b114560896679f0314cea288d7a768c..f57ad014fb3d2ce2405bdd63db4c730458aac17a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2234,6 +2234,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public void resetCooldown() { - getHandle().resetAttackCooldown(); - } -+ -+ @Override -+ public void remove() { -+ if (this.getHandle().getClass().equals(EntityPlayer.class)) { // special case for NMS plugins inheriting -+ throw new UnsupportedOperationException("Calling Entity#remove on players produces undefined (bad) behavior"); -+ } else { -+ super.remove(); -+ } -+ } - // Paper end - - // Spigot start diff --git a/Unmapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch b/Unmapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch deleted file mode 100644 index c27cd38c27..0000000000 --- a/Unmapped-Spigot-Server-Patches/0323-BlockDestroyEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 Feb 2019 00:20:33 -0500 -Subject: [PATCH] BlockDestroyEvent - -Adds an event for when the server is going to destroy a current block, -potentially causing it to drop. This event can be cancelled to avoid -the block destruction, such as preventing signs from popping when -floating in the air. - -This can replace many uses of BlockPhysicsEvent - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 88b1a0235bfc0b41ae1855f8900632e425730d1c..3b5ddc083719608e944bdefa38e1fd3909e8e200 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -26,6 +26,7 @@ import net.minecraft.core.particles.ParticleParam; - import net.minecraft.network.protocol.Packet; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunk; -@@ -559,8 +560,20 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return false; - } else { - Fluid fluid = this.getFluid(blockposition); -+ // Paper start - while the above setAir method is named same and looks very similar -+ // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent, -+ // it doesn't imply destruction of a block that plays a sound effect / drops an item. -+ boolean playEffect = true; -+ if (com.destroystokyo.paper.event.block.BlockDestroyEvent.getHandlerList().getRegisteredListeners().length > 0) { -+ com.destroystokyo.paper.event.block.BlockDestroyEvent event = new com.destroystokyo.paper.event.block.BlockDestroyEvent(MCUtil.toBukkitBlock(this, blockposition), fluid.getBlockData().createCraftBlockData(), flag); -+ if (!event.callEvent()) { -+ return false; -+ } -+ playEffect = event.playEffect(); -+ } -+ // Paper end - -- if (!(iblockdata.getBlock() instanceof BlockFireAbstract)) { -+ if (playEffect && !(iblockdata.getBlock() instanceof BlockFireAbstract)) { // Paper - this.triggerEffect(2001, blockposition, Block.getCombinedId(iblockdata)); - } - diff --git a/Unmapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/Unmapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch deleted file mode 100644 index e98607e7c3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Jan 2019 00:08:15 -0500 -Subject: [PATCH] Fix Custom Shapeless Custom Crafting Recipes - -Mojang implemented Shapeless different than Shaped - -This made the Bukkit RecipeChoice API not work for Shapeless. - -This reimplements vanilla logic using the same test logic as Shaped - -diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java -index 9226602691ccbf39835f2dd071f171c2375b0a16..e112d149fc3a7af7f0c9a5280c94c9b03b2aba2d 100644 ---- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java -+++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java -@@ -72,16 +72,49 @@ public class ShapelessRecipes implements RecipeCrafting { - AutoRecipeStackManager autorecipestackmanager = new AutoRecipeStackManager(); - int i = 0; - -+ // Paper start -+ java.util.List providedItems = new java.util.ArrayList<>(); -+ co.aikar.util.Counter matchedProvided = new co.aikar.util.Counter<>(); -+ co.aikar.util.Counter matchedIngredients = new co.aikar.util.Counter<>(); -+ // Paper end - for (int j = 0; j < inventorycrafting.getSize(); ++j) { - ItemStack itemstack = inventorycrafting.getItem(j); - - if (!itemstack.isEmpty()) { -- ++i; -- autorecipestackmanager.a(itemstack, 1); -+ // Paper start -+ itemstack = itemstack.cloneItemStack(); -+ providedItems.add(itemstack); -+ for (RecipeItemStack ingredient : ingredients) { -+ if (ingredient.test(itemstack)) { -+ matchedProvided.increment(itemstack); -+ matchedIngredients.increment(ingredient); -+ } -+ } -+ // Paper end - } - } - -- return i == this.ingredients.size() && autorecipestackmanager.a(this, (IntList) null); -+ // Paper start -+ if (matchedProvided.isEmpty() || matchedIngredients.isEmpty()) { -+ return false; -+ } -+ java.util.List ingredients = new java.util.ArrayList<>(this.ingredients); -+ providedItems.sort(java.util.Comparator.comparingInt((ItemStack c) -> (int) matchedProvided.getCount(c)).reversed()); -+ ingredients.sort(java.util.Comparator.comparingInt((RecipeItemStack c) -> (int) matchedIngredients.getCount(c))); -+ -+ PROVIDED: -+ for (ItemStack provided : providedItems) { -+ for (Iterator itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) { -+ RecipeItemStack ingredient = itIngredient.next(); -+ if (ingredient.test(provided)) { -+ itIngredient.remove(); -+ continue PROVIDED; -+ } -+ } -+ return false; -+ } -+ return ingredients.isEmpty(); -+ // Paper end - } - - public ItemStack a(InventoryCrafting inventorycrafting) { diff --git a/Unmapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch b/Unmapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch deleted file mode 100644 index 223cbe60ae..0000000000 --- a/Unmapped-Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 28 Feb 2019 00:15:28 -0500 -Subject: [PATCH] Fix sign edit memory leak - -when a player edits a sign, a reference to their Entity is never cleand up. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 54399a2f2d1d86b650e27f6a31dce89035e7aeba..b7b431a649c6bc3066c267783007eee4384d27bd 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2852,7 +2852,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - - TileEntitySign tileentitysign = (TileEntitySign) tileentity; - -- if (!tileentitysign.d() || tileentitysign.f() != this.player) { -+ if (!tileentitysign.d() || tileentitysign.signEditor == null || !tileentitysign.signEditor.equals(this.player.getUniqueID())) { - PlayerConnection.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getDisplayName().getString()); - this.sendPacket(tileentity.getUpdatePacket()); // CraftBukkit - return; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -index ec550aaa4e7943af4ecdd2275f1f32c21edf770a..6d0fe58d7e574ce5189e1f7a8485060d60b466d9 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -@@ -30,6 +30,7 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - private EntityHuman c; - private final FormattedString[] g; - private EnumColor color; -+ public java.util.UUID signEditor; // Paper - - public TileEntitySign() { - super(TileEntityTypes.SIGN); -@@ -131,7 +132,10 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - } - - public void a(EntityHuman entityhuman) { -- this.c = entityhuman; -+ // Paper start -+ //this.c = entityhuman; -+ signEditor = entityhuman != null ? entityhuman.getUniqueID() : null; -+ // Paper end - } - - public EntityHuman f() { diff --git a/Unmapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch b/Unmapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch deleted file mode 100644 index d3b0d1f52d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Feb 2019 22:18:40 -0500 -Subject: [PATCH] Limit Client Sign length more - -modified clients can send more data from the client -to the server and it would get stored on the sign as sent. - -Mojang has a limit of 384 which is much higher than reasonable. - -the client can barely render around 16 characters as-is, but formatting -codes can get it to be more than 16 actual length. - -Set a limit of 80 which should give an average of 16 characters 2 -sets of legacy formatting codes which should be plenty for all uses. - -This does not strip any existing data from the NBT as plugins -may use this for storing data out of the rendered area. - -it only impacts data sent from the client. - -Set -DPaper.maxSignLength=XX to change limit or -1 to disable - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index b7b431a649c6bc3066c267783007eee4384d27bd..c0c9af81a933135e940587c10155a24cd399b922 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -256,6 +256,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - private int E; - private int receivedMovePackets; - private int processedMovePackets; -+ private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); - private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - - public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { -@@ -2862,7 +2863,17 @@ public class PlayerConnection implements PacketListenerPlayIn { - List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. -+ // Paper start - cap line length - modified clients can send longer data than normal -+ String currentLine = list.get(i); -+ if (MAX_SIGN_LINE_LENGTH > 0 && currentLine.length() > MAX_SIGN_LINE_LENGTH) { -+ // This handles multibyte characters as 1 -+ int offset = currentLine.codePoints().limit(MAX_SIGN_LINE_LENGTH).map(Character::charCount).sum(); -+ if (offset < currentLine.length()) { -+ list.set(i, currentLine = currentLine.substring(0, offset)); -+ } -+ } -+ // Paper end -+ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(currentLine))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. - } - SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.server.getPluginManager().callEvent(event); diff --git a/Unmapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/Unmapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch deleted file mode 100644 index 033181274d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 2 Mar 2019 11:11:29 -0500 -Subject: [PATCH] Don't check ConvertSigns boolean every sign save - -property lookups arent super cheap. they synchronize, validate -and check security managers. - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -index 6d0fe58d7e574ce5189e1f7a8485060d60b466d9..7f78f388584899b13ff983f0dc37c679bfb1507e 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -@@ -31,6 +31,7 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - private final FormattedString[] g; - private EnumColor color; - public java.util.UUID signEditor; // Paper -+ private static final boolean CONVERT_LEGACY_SIGNS = Boolean.getBoolean("convertLegacySigns"); // Paper - - public TileEntitySign() { - super(TileEntityTypes.SIGN); -@@ -51,7 +52,7 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - } - - // CraftBukkit start -- if (Boolean.getBoolean("convertLegacySigns")) { -+ if (CONVERT_LEGACY_SIGNS) { // Paper - nbttagcompound.setBoolean("Bukkit.isConverted", true); - } - // CraftBukkit end diff --git a/Unmapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/Unmapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch deleted file mode 100644 index 053340619f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch +++ /dev/null @@ -1,390 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 04:53:35 -0400 -Subject: [PATCH] Optimize Network Manager and add advanced packet support - -Adds ability for 1 packet to bundle other packets to follow it -Adds ability for a packet to delay sending more packets until a state is ready. - -Removes synchronization from sending packets -Removes processing packet queue off of main thread - - for the few cases where it is allowed, order is not necessary nor - should it even be happening concurrently in first place (handshaking/login/status) - -Ensures packets sent asynchronously are dispatched on main thread - -This helps ensure safety for ProtocolLib as packet listeners -are commonly accessing world state. This will allow you to schedule -a packet to be sent async, but itll be dispatched sync for packet -listeners to process. - -This should solve some deadlock risks - -Also adds Netty Channel Flush Consolidation to reduce the amount of flushing - -Also avoids spamming closed channel exception by rechecking closed state in dispatch -and then catch exceptions and close if they fire. - -Part of this commit was authored by: Spottedleaf - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 6d40ade5a52383ed86d28d272c3dc83dbdcbd218..ab70eeaeca222de7de7cab1b3db14b2c4761c3c3 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -25,8 +25,15 @@ import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.EnumProtocolDirection; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.network.protocol.game.PacketPlayOutBoss; -+import net.minecraft.network.protocol.game.PacketPlayOutChat; -+import net.minecraft.network.protocol.game.PacketPlayOutKeepAlive; - import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; -+import net.minecraft.network.protocol.game.PacketPlayOutTabComplete; -+import net.minecraft.network.protocol.game.PacketPlayOutTitle; - import net.minecraft.server.CancelledPacketHandleException; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.network.LoginListener; - import net.minecraft.server.network.PlayerConnection; - import net.minecraft.util.LazyInitVar; -@@ -75,6 +82,10 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - public int protocolVersion; - public java.net.InetSocketAddress virtualHost; - private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); -+ // Optimize network -+ public boolean isPending = true; -+ public boolean queueImmunity = false; -+ public EnumProtocol protocol; - // Paper end - - public NetworkManager(EnumProtocolDirection enumprotocoldirection) { -@@ -98,6 +109,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - - public void setProtocol(EnumProtocol enumprotocol) { -+ protocol = enumprotocol; // Paper - this.channel.attr(NetworkManager.c).set(enumprotocol); - this.channel.config().setAutoRead(true); - NetworkManager.LOGGER.debug("Enabled auto read"); -@@ -168,19 +180,84 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - Validate.notNull(packetlistener, "packetListener", new Object[0]); - this.packetListener = packetlistener; - } -+ // Paper start -+ public EntityPlayer getPlayer() { -+ if (packetListener instanceof PlayerConnection) { -+ return ((PlayerConnection) packetListener).player; -+ } else { -+ return null; -+ } -+ } -+ private static class InnerUtil { // Attempt to hide these methods from ProtocolLib so it doesn't accidently pick them up. -+ private static java.util.List buildExtraPackets(Packet packet) { -+ java.util.List extra = packet.getExtraPackets(); -+ if (extra == null || extra.isEmpty()) { -+ return null; -+ } -+ java.util.List ret = new java.util.ArrayList<>(1 + extra.size()); -+ buildExtraPackets0(extra, ret); -+ return ret; -+ } -+ -+ private static void buildExtraPackets0(java.util.List extraPackets, java.util.List into) { -+ for (Packet extra : extraPackets) { -+ into.add(extra); -+ java.util.List extraExtra = extra.getExtraPackets(); -+ if (extraExtra != null && !extraExtra.isEmpty()) { -+ buildExtraPackets0(extraExtra, into); -+ } -+ } -+ } -+ // Paper start -+ private static boolean canSendImmediate(NetworkManager networkManager, Packet packet) { -+ return networkManager.isPending || networkManager.protocol != EnumProtocol.PLAY || -+ packet instanceof PacketPlayOutKeepAlive || -+ packet instanceof PacketPlayOutChat || -+ packet instanceof PacketPlayOutTabComplete || -+ packet instanceof PacketPlayOutTitle || -+ packet instanceof PacketPlayOutBoss; -+ } -+ // Paper end -+ } -+ // Paper end - - public void sendPacket(Packet packet) { - this.sendPacket(packet, (GenericFutureListener) null); - } - - public void sendPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { -- if (this.isConnected()) { -- this.p(); -- this.b(packet, genericfuturelistener); -- } else { -- this.packetQueue.add(new NetworkManager.QueuedPacket(packet, genericfuturelistener)); -+ // Paper start - handle oversized packets better -+ boolean connected = this.isConnected(); -+ if (!connected && !preparing) { -+ return; // Do nothing -+ } -+ packet.onPacketDispatch(getPlayer()); -+ if (connected && (InnerUtil.canSendImmediate(this, packet) || ( -+ MCUtil.isMainThread() && packet.isReady() && this.packetQueue.isEmpty() && -+ (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) -+ ))) { -+ this.dispatchPacket(packet, genericfuturelistener); -+ return; - } -+ // write the packets to the queue, then flush - antixray hooks there already -+ java.util.List extraPackets = InnerUtil.buildExtraPackets(packet); -+ boolean hasExtraPackets = extraPackets != null && !extraPackets.isEmpty(); -+ if (!hasExtraPackets) { -+ this.packetQueue.add(new NetworkManager.QueuedPacket(packet, genericfuturelistener)); -+ } else { -+ java.util.List packets = new java.util.ArrayList<>(1 + extraPackets.size()); -+ packets.add(new NetworkManager.QueuedPacket(packet, null)); // delay the future listener until the end of the extra packets -+ -+ for (int i = 0, len = extraPackets.size(); i < len;) { -+ Packet extra = extraPackets.get(i); -+ boolean end = ++i == len; -+ packets.add(new NetworkManager.QueuedPacket(extra, end ? genericfuturelistener : null)); // append listener to the end -+ } - -+ this.packetQueue.addAll(packets); // atomic -+ } -+ this.sendPacketQueue(); -+ // Paper end - } - - private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER -@@ -194,51 +271,116 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - this.channel.config().setAutoRead(false); - } - -+ EntityPlayer player = getPlayer(); // Paper - if (this.channel.eventLoop().inEventLoop()) { - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end - - ChannelFuture channelfuture = this.channel.writeAndFlush(packet); - - if (genericfuturelistener != null) { - channelfuture.addListener(genericfuturelistener); - } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end - - channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end - } else { - this.channel.eventLoop().execute(() -> { - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } - -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end - ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet); - -+ - if (genericfuturelistener != null) { - channelfuture1.addListener(genericfuturelistener); - } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end - - channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end - }); - } - - } - -- private void sendPacketQueue() { this.p(); } // Paper - OBFHELPER -- private void p() { -- if (this.channel != null && this.channel.isOpen()) { -- Queue queue = this.packetQueue; -- -+ // Paper start - rewrite this to be safer if ran off main thread -+ private boolean sendPacketQueue() { return this.p(); } // OBFHELPER // void -> boolean -+ private boolean p() { // void -> boolean -+ if (!isConnected()) { -+ return true; -+ } -+ if (MCUtil.isMainThread()) { -+ return processQueue(); -+ } else if (isPending) { -+ // Should only happen during login/status stages - synchronized (this.packetQueue) { -- NetworkManager.QueuedPacket networkmanager_queuedpacket; -- -- while ((networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.packetQueue.poll()) != null) { -- this.b(networkmanager_queuedpacket.a, networkmanager_queuedpacket.b); -- } -+ return this.processQueue(); -+ } -+ } -+ return false; -+ } -+ private boolean processQueue() { -+ if (this.packetQueue.isEmpty()) return true; -+ // If we are on main, we are safe here in that nothing else should be processing queue off main anymore -+ // But if we are not on main due to login/status, the parent is synchronized on packetQueue -+ java.util.Iterator iterator = this.packetQueue.iterator(); -+ while (iterator.hasNext()) { -+ NetworkManager.QueuedPacket queued = iterator.next(); // poll -> peek -+ -+ // Fix NPE (Spigot bug caused by handleDisconnection()) -+ if (queued == null) { -+ return true; -+ } - -+ Packet packet = queued.getPacket(); -+ if (!packet.isReady()) { -+ return false; -+ } else { -+ iterator.remove(); -+ this.dispatchPacket(packet, queued.getGenericFutureListener()); - } - } -+ return true; - } -+ // Paper end - - public void a() { - this.p(); -@@ -271,9 +413,21 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - return this.socketAddress; - } - -+ // Paper start -+ public void clearPacketQueue() { -+ EntityPlayer player = getPlayer(); -+ packetQueue.forEach(queuedPacket -> { -+ Packet packet = queuedPacket.getPacket(); -+ if (packet.hasFinishListener()) { -+ packet.onPacketDispatchFinish(player, null); -+ } -+ }); -+ packetQueue.clear(); -+ } // Paper end - public void close(IChatBaseComponent ichatbasecomponent) { - // Spigot Start - this.preparing = false; -+ clearPacketQueue(); // Paper - // Spigot End - if (this.channel.isOpen()) { - this.channel.close(); // We can't wait as this may be called from an event loop. -@@ -341,7 +495,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - public void handleDisconnection() { - if (this.channel != null && !this.channel.isOpen()) { - if (this.o) { -- NetworkManager.LOGGER.warn("handleDisconnection() called twice"); -+ //NetworkManager.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message - } else { - this.o = true; - if (this.k() != null) { -@@ -349,7 +503,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } else if (this.j() != null) { - this.j().a(new ChatMessage("multiplayer.disconnect.generic")); - } -- this.packetQueue.clear(); // Free up packet queue. -+ clearPacketQueue(); // Paper - // Paper start - Add PlayerConnectionCloseEvent - final PacketListener packetListener = this.j(); - if (packetListener instanceof PlayerConnection) { -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index 0783b0777c8d7788bbf6780b464b709bf6dc2191..b644c91cecd8a347319dfe8c8923fd05919a9795 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -1,5 +1,6 @@ - package net.minecraft.network.protocol; - -+import io.netty.channel.ChannelFuture; // Paper - import java.io.IOException; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.PacketListener; -@@ -13,6 +14,20 @@ public interface Packet { - void a(T t0); - - // Paper start -+ -+ /** -+ * @param player Null if not at PLAY stage yet -+ */ -+ default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} -+ -+ /** -+ * @param player Null if not at PLAY stage yet -+ * @param future Can be null if packet was cancelled -+ */ -+ default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} -+ default boolean hasFinishListener() { return false; } -+ default boolean isReady() { return true; } -+ default java.util.List getExtraPackets() { return null; } - default boolean packetTooLarge(NetworkManager manager) { - return false; - } -diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java -index d992cb5cd827e0fe655809e1088939cdad9c2301..dc362724ea0cc1b2f9d9ceffff483217b4356c40 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnection.java -@@ -16,6 +16,7 @@ import io.netty.channel.epoll.EpollServerSocketChannel; - import io.netty.channel.nio.NioEventLoopGroup; - import io.netty.channel.socket.ServerSocketChannel; - import io.netty.channel.socket.nio.NioServerSocketChannel; -+import io.netty.handler.flush.FlushConsolidationHandler; // Paper - import io.netty.handler.timeout.ReadTimeoutHandler; - import java.io.IOException; - import java.net.InetAddress; -@@ -54,10 +55,12 @@ public class ServerConnection { - private final List connectedChannels = Collections.synchronizedList(Lists.newArrayList()); - // Paper start - prevent blocking on adding a new network manager while the server is ticking - private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private static final boolean disableFlushConsolidation = Boolean.getBoolean("Paper.disableFlushConsolidate"); // Paper - private void addPending() { - NetworkManager manager = null; - while ((manager = pending.poll()) != null) { - connectedChannels.add(manager); -+ manager.isPending = false; - } - } - // Paper end -@@ -92,6 +95,7 @@ public class ServerConnection { - ; - } - -+ if (!disableFlushConsolidation) channel.pipeline().addFirst(new FlushConsolidationHandler()); // Paper - channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyPingHandler(ServerConnection.this)).addLast("splitter", new PacketSplitter()).addLast("decoder", new PacketDecoder(EnumProtocolDirection.SERVERBOUND)).addLast("prepender", new PacketPrepender()).addLast("encoder", new PacketEncoder(EnumProtocolDirection.CLIENTBOUND)); - int j = ServerConnection.this.e.k(); - Object object = j > 0 ? new NetworkManagerServer(j) : new NetworkManager(EnumProtocolDirection.SERVERBOUND); diff --git a/Unmapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch b/Unmapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch deleted file mode 100644 index ee9073137c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 05:00:57 -0400 -Subject: [PATCH] Handle Oversized Tile Entities in chunks - -Splits out Extra Packets if too many TE's are encountered to prevent -creating too large of a packet to sed. - -Co authored by Spottedleaf - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index 0059ede4ba3ff271d47dd38ea87fddc2399aa008..a7d10d124021f3427f23fcd533f885367b64515c 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -34,7 +34,15 @@ public class PacketPlayOutMapChunk implements Packet { - private boolean h; - - public PacketPlayOutMapChunk() {} -+ // Paper start -+ private final java.util.List extraPackets = new java.util.ArrayList<>(); -+ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); - -+ @Override -+ public java.util.List getExtraPackets() { -+ return extraPackets; -+ } -+ // Paper end - public PacketPlayOutMapChunk(Chunk chunk, int i) { - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - -@@ -61,6 +69,7 @@ public class PacketPlayOutMapChunk implements Packet { - this.c = this.a(new PacketDataSerializer(this.j()), chunk, i); - this.g = Lists.newArrayList(); - iterator = chunk.getTileEntities().entrySet().iterator(); -+ int totalTileEntities = 0; // Paper - - while (iterator.hasNext()) { - entry = (Entry) iterator.next(); -@@ -69,6 +78,15 @@ public class PacketPlayOutMapChunk implements Packet { - int j = blockposition.getY() >> 4; - - if (this.f() || (i & 1 << j) != 0) { -+ // Paper start - improve oversized chunk data packet handling -+ if (++totalTileEntities > TE_LIMIT) { -+ PacketPlayOutTileEntityData updatePacket = tileentity.getUpdatePacket(); -+ if (updatePacket != null) { -+ this.extraPackets.add(updatePacket); -+ continue; -+ } -+ } -+ // Paper end - NBTTagCompound nbttagcompound = tileentity.b(); - if (tileentity instanceof TileEntitySkull) { TileEntitySkull.sanitizeTileEntityUUID(nbttagcompound); } // Paper - diff --git a/Unmapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/Unmapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch deleted file mode 100644 index fe3dd5e8b2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 2 Mar 2019 16:12:35 -0500 -Subject: [PATCH] MC-145260: Fix Whitelist On/Off inconsistency - -mojang stored whitelist state in 2 places (Whitelist Object, PlayerList) - -some things checked PlayerList, some checked object. This moves -everything to the Whitelist object. - -https://github.com/PaperMC/Paper/issues/1880 - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7515e9ddbc89de882373469cf3c46046c76af974..1a4ae92065f729ec521752bb87df8343d747f566 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -55,6 +55,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutViewDistance; - import net.minecraft.network.protocol.game.PacketPlayOutWorldBorder; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.AdvancementDataPlayer; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.ScoreboardServer; - import net.minecraft.server.level.DemoPlayerInteractManager; -@@ -1016,9 +1017,9 @@ public abstract class PlayerList { - } - public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { - boolean isOp = this.operators.d(gameprofile); -- boolean isWhitelisted = !this.hasWhitelist || isOp || this.whitelist.d(gameprofile); -+ boolean isWhitelisted = !this.getHasWhitelist() || isOp || this.whitelist.d(gameprofile); - final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; -- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.hasWhitelist, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); -+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.getHasWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); - event.callEvent(); - if (!event.isWhitelisted()) { - if (loginEvent != null) { diff --git a/Unmapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/Unmapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch deleted file mode 100644 index 30e7bd3924..0000000000 --- a/Unmapped-Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 4 Mar 2019 02:23:28 -0500 -Subject: [PATCH] Set Zombie last tick at start of drowning process - -Fixes GH-1887 - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 79d34b0296f88e5b4fe0351fe2483fc0128deabc..f406826945dd752e6528743a0c8cad3cfdfc4a95 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -223,6 +223,7 @@ public class EntityZombie extends EntityMonster { - ++this.bt; - if (this.bt >= 600) { - this.startDrownedConversion(300); -+ this.lastTick = MinecraftServer.currentTick; // Paper - Make sure this is set at start of process - GH-1887 - } - } else { - this.bt = -1; diff --git a/Unmapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch b/Unmapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch deleted file mode 100644 index 56fb7e5bc7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch +++ /dev/null @@ -1,272 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 15 Feb 2019 01:08:19 -0500 -Subject: [PATCH] Allow Saving of Oversized Chunks - -The Minecraft World Region File format has a hard cap of 1MB per chunk. -This is due to the fact that the header of the file format only allocates -a single byte for sector count, meaning a maximum of 256 sectors, at 4k per sector. - -This limit can be reached fairly easily with books, resulting in the chunk being unable -to save to the world. Worse off, is that nothing printed when this occured, and silently -performed a chunk rollback on next load. - -This leads to security risk with duplication and is being actively exploited. - -This patch catches the too large scenario, falls back and moves any large Entity -or Tile Entity into a new compound, and this compound is saved into a different file. - -On Chunk Load, we check for oversized status, and if so, we load the extra file and -merge the Entities and Tile Entities from the oversized chunk back into the level to -then be loaded as normal. - -Once a chunk is returned back to normal size, the oversized flag will clear, and no -extra data file will exist. - -This fix maintains compatability with all existing Anvil Region Format tools as it -does not alter the save format. They will just not know about the extra entities. - -This fix also maintains compatability if someone switches server jars to one without -this fix, as the data will remain in the oversized file. Once the server returns -to a jar with this fix, the data will be restored. - -diff --git a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -index 850d3a7bb8ae4c43c0e2f737cfe69261f338b026..20410a5853e34c90c872f5e9592d50c4727e914d 100644 ---- a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -+++ b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -@@ -132,6 +132,7 @@ public class NBTCompressedStreamTools { - - } - -+ public static NBTTagCompound readNBT(DataInput datainput) throws IOException { return a(datainput); } // Paper - OBFHELPER - public static NBTTagCompound a(DataInput datainput) throws IOException { - return a(datainput, NBTReadLimiter.a); - } -@@ -152,6 +153,7 @@ public class NBTCompressedStreamTools { - } - } - -+ public static void writeNBT(NBTTagCompound nbttagcompound, DataOutput dataoutput) throws IOException { a(nbttagcompound, dataoutput); } // Paper - OBFHELPER - public static void a(NBTTagCompound nbttagcompound, DataOutput dataoutput) throws IOException { - a((NBTBase) nbttagcompound, dataoutput); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 4bf3e0cb4602d33a2e00c502b1dd212032b22a8f..00cef1c0bc19976a000389e57a1af5d93690c0e7 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -20,8 +20,12 @@ import java.nio.file.LinkOption; - import java.nio.file.Path; - import java.nio.file.StandardCopyOption; - import java.nio.file.StandardOpenOption; -+import java.util.zip.InflaterInputStream; // Paper -+ - import javax.annotation.Nullable; - import net.minecraft.SystemUtils; -+import net.minecraft.nbt.NBTCompressedStreamTools; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.world.level.ChunkCoordIntPair; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -38,6 +42,7 @@ public class RegionFile implements AutoCloseable { - private final IntBuffer i; - @VisibleForTesting - protected final RegionFileBitSet freeSectors; -+ public final File file; // Paper - - public RegionFile(File file, File file1, boolean flag) throws IOException { - this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag); -@@ -45,6 +50,8 @@ public class RegionFile implements AutoCloseable { - - public RegionFile(Path path, Path path1, RegionFileCompression regionfilecompression, boolean flag) throws IOException { - this.g = ByteBuffer.allocateDirect(8192); -+ this.file = path.toFile(); // Paper -+ initOversizedState(); // Paper - this.freeSectors = new RegionFileBitSet(); - this.f = regionfilecompression; - if (!Files.isDirectory(path1, new LinkOption[0])) { -@@ -408,6 +415,74 @@ public class RegionFile implements AutoCloseable { - void run() throws IOException; - } - -+ // Paper start -+ private final byte[] oversized = new byte[1024]; -+ private int oversizedCount = 0; -+ -+ private synchronized void initOversizedState() throws IOException { -+ File metaFile = getOversizedMetaFile(); -+ if (metaFile.exists()) { -+ final byte[] read = java.nio.file.Files.readAllBytes(metaFile.toPath()); -+ System.arraycopy(read, 0, oversized, 0, oversized.length); -+ for (byte temp : oversized) { -+ oversizedCount += temp; -+ } -+ } -+ } -+ -+ private static int getChunkIndex(int x, int z) { -+ return (x & 31) + (z & 31) * 32; -+ } -+ synchronized boolean isOversized(int x, int z) { -+ return this.oversized[getChunkIndex(x, z)] == 1; -+ } -+ synchronized void setOversized(int x, int z, boolean oversized) throws IOException { -+ final int offset = getChunkIndex(x, z); -+ boolean previous = this.oversized[offset] == 1; -+ this.oversized[offset] = (byte) (oversized ? 1 : 0); -+ if (!previous && oversized) { -+ oversizedCount++; -+ } else if (!oversized && previous) { -+ oversizedCount--; -+ } -+ if (previous && !oversized) { -+ File oversizedFile = getOversizedFile(x, z); -+ if (oversizedFile.exists()) { -+ oversizedFile.delete(); -+ } -+ } -+ if (oversizedCount > 0) { -+ if (previous != oversized) { -+ writeOversizedMeta(); -+ } -+ } else if (previous) { -+ File oversizedMetaFile = getOversizedMetaFile(); -+ if (oversizedMetaFile.exists()) { -+ oversizedMetaFile.delete(); -+ } -+ } -+ } -+ -+ private void writeOversizedMeta() throws IOException { -+ java.nio.file.Files.write(getOversizedMetaFile().toPath(), oversized); -+ } -+ -+ private File getOversizedMetaFile() { -+ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + ".oversized.nbt"); -+ } -+ -+ private File getOversizedFile(int x, int z) { -+ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); -+ } -+ -+ synchronized NBTTagCompound getOversizedData(int x, int z) throws IOException { -+ File file = getOversizedFile(x, z); -+ try (DataInputStream out = new DataInputStream(new BufferedInputStream(new InflaterInputStream(new java.io.FileInputStream(file))))) { -+ return NBTCompressedStreamTools.readNBT((java.io.DataInput) out); -+ } -+ -+ } -+ // Paper end - class ChunkBuffer extends ByteArrayOutputStream { - - private final ChunkCoordIntPair b; -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index 75b10a3755392870d8f5b51239a09a0e7fd75a42..ab9f4d40fd1126a3d7ba5b16fdc6ab09de4a7fdb 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -9,8 +9,10 @@ import java.io.DataOutputStream; - import java.io.File; - import java.io.IOException; - import javax.annotation.Nullable; -+import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTCompressedStreamTools; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; - import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionSuppressor; - import net.minecraft.world.level.ChunkCoordIntPair; -@@ -50,6 +52,74 @@ public final class RegionFileCache implements AutoCloseable { - } - } - -+ // Paper start -+ private static void printOversizedLog(String msg, File file, int x, int z) { -+ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); -+ } -+ -+ private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 8; -+ private static final int OVERZEALOUS_TOTAL_THRESHOLD = 1024 * 64; -+ private static final int OVERZEALOUS_THRESHOLD = 1024; -+ private static int SIZE_THRESHOLD = DEFAULT_SIZE_THRESHOLD; -+ private static void resetFilterThresholds() { -+ SIZE_THRESHOLD = Math.max(1024 * 4, Integer.getInteger("Paper.FilterThreshhold", DEFAULT_SIZE_THRESHOLD)); -+ } -+ static { -+ resetFilterThresholds(); -+ } -+ -+ static boolean isOverzealous() { -+ return SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD; -+ } -+ -+ -+ private static NBTTagCompound readOversizedChunk(RegionFile regionfile, ChunkCoordIntPair chunkCoordinate) throws IOException { -+ synchronized (regionfile) { -+ try (DataInputStream datainputstream = regionfile.getReadStream(chunkCoordinate)) { -+ NBTTagCompound oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); -+ NBTTagCompound chunk = NBTCompressedStreamTools.readNBT((DataInput) datainputstream); -+ if (oversizedData == null) { -+ return chunk; -+ } -+ NBTTagCompound oversizedLevel = oversizedData.getCompound("Level"); -+ NBTTagCompound level = chunk.getCompound("Level"); -+ -+ mergeChunkList(level, oversizedLevel, "Entities"); -+ mergeChunkList(level, oversizedLevel, "TileEntities"); -+ -+ chunk.set("Level", level); -+ -+ return chunk; -+ } catch (Throwable throwable) { -+ throwable.printStackTrace(); -+ throw throwable; -+ } -+ } -+ } -+ -+ private static void mergeChunkList(NBTTagCompound level, NBTTagCompound oversizedLevel, String key) { -+ NBTTagList levelList = level.getList(key, 10); -+ NBTTagList oversizedList = oversizedLevel.getList(key, 10); -+ -+ if (!oversizedList.isEmpty()) { -+ levelList.addAll(oversizedList); -+ level.set(key, levelList); -+ } -+ } -+ -+ private static int getNBTSize(NBTBase nbtBase) { -+ DataOutputStream test = new DataOutputStream(new org.apache.commons.io.output.NullOutputStream()); -+ try { -+ nbtBase.write(test); -+ return test.size(); -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return 0; -+ } -+ } -+ -+ // Paper End -+ - @Nullable - public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { - // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing -@@ -59,6 +129,12 @@ public final class RegionFileCache implements AutoCloseable { - } - // CraftBukkit end - DataInputStream datainputstream = regionfile.a(chunkcoordintpair); -+ // Paper start -+ if (regionfile.isOversized(chunkcoordintpair.x, chunkcoordintpair.z)) { -+ printOversizedLog("Loading Oversized Chunk!", regionfile.file, chunkcoordintpair.x, chunkcoordintpair.z); -+ return readOversizedChunk(regionfile, chunkcoordintpair); -+ } -+ // Paper end - Throwable throwable = null; - - NBTTagCompound nbttagcompound; -@@ -99,6 +175,7 @@ public final class RegionFileCache implements AutoCloseable { - - try { - NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream); -+ regionfile.setOversized(chunkcoordintpair.x, chunkcoordintpair.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone - } catch (Throwable throwable1) { - throwable = throwable1; - throw throwable1; diff --git a/Unmapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/Unmapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch deleted file mode 100644 index f3f9b1eb62..0000000000 --- a/Unmapped-Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Wed, 13 Mar 2019 20:08:09 +0200 -Subject: [PATCH] Call WhitelistToggleEvent when whitelist is toggled - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 1a4ae92065f729ec521752bb87df8343d747f566..1ae969aff1d44ad9af28fc94d8821884b9ad0563 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1135,6 +1135,7 @@ public abstract class PlayerList { - } - - public void setHasWhitelist(boolean flag) { -+ new com.destroystokyo.paper.event.server.WhitelistToggleEvent(flag).callEvent(); - this.hasWhitelist = flag; - } - diff --git a/Unmapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch b/Unmapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch deleted file mode 100644 index d372c84865..0000000000 --- a/Unmapped-Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch +++ /dev/null @@ -1,187 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 22 Sep 2018 00:33:08 -0500 -Subject: [PATCH] Add LivingEntity#getTargetEntity - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index af38b81df3f60163cafc341543ecad0865225943..413f715c98dc0a0953e60032ad1ebef2b0b3bbe3 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1504,6 +1504,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.c(f - 90.0F, f1); - } - -+ public final Vec3D getEyePosition(float partialTicks) { return j(partialTicks); } // Paper - OBFHELPER - public final Vec3D j(float f) { - if (f == 1.0F) { - return new Vec3D(this.locX(), this.getHeadY(), this.locZ()); -@@ -2154,6 +2155,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.getPassengers().size() < 1; - } - -+ public final float getCollisionBorderSize() { return bg(); } // Paper - OBFHELPER - public float bg() { - return 0.0F; - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 32a2d6fd22ba69694a2f620174f618a95964074d..4e2039e46741e8a09f3af7d3d9e98ef7a5b27abc 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -108,6 +108,7 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParameterSet - import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; - import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.MovingObjectPosition; -+import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; - import net.minecraft.world.scores.ScoreboardTeam; - import org.apache.logging.log4j.Logger; -@@ -3660,6 +3661,37 @@ public abstract class EntityLiving extends Entity { - return world.rayTrace(raytrace); - } - -+ public MovingObjectPositionEntity getTargetEntity(int maxDistance) { -+ if (maxDistance < 1 || maxDistance > 120) { -+ throw new IllegalArgumentException("maxDistance must be between 1-120"); -+ } -+ -+ Vec3D start = this.getEyePosition(1.0F); -+ Vec3D direction = this.getLookDirection(); -+ Vec3D end = start.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance); -+ -+ List entityList = world.getEntities(this, getBoundingBox().expand(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance).grow(1.0D, 1.0D, 1.0D), IEntitySelector.canAITarget().and(Entity::isInteractable)); -+ -+ double distance = 0.0D; -+ MovingObjectPositionEntity result = null; -+ -+ for (Entity entity : entityList) { -+ AxisAlignedBB aabb = entity.getBoundingBox().grow((double) entity.getCollisionBorderSize()); -+ Optional rayTraceResult = aabb.calculateIntercept(start, end); -+ -+ if (rayTraceResult.isPresent()) { -+ Vec3D rayTrace = rayTraceResult.get(); -+ double distanceTo = start.distanceSquared(rayTrace); -+ if (distanceTo < distance || distance == 0.0D) { -+ result = new MovingObjectPositionEntity(entity, rayTrace); -+ distance = distanceTo; -+ } -+ } -+ } -+ -+ return result; -+ } -+ - public int shieldBlockingDelay = world.paperConfig.shieldBlockingDelay; - - public int getShieldBlockingDelay() { -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index 4776a47566aac487dc77fd6b4b9b42b95974e31a..cb5cda5e6497edeb801ef712f9bd8823cb055750 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -22,6 +22,7 @@ public final class IEntitySelector { - public static final Predicate e = (entity) -> { - return !(entity instanceof EntityHuman) || !entity.isSpectator() && !((EntityHuman) entity).isCreative(); - }; -+ public static Predicate canAITarget() { return f; } // Paper - OBFHELPER - public static final Predicate f = (entity) -> { - return !(entity instanceof EntityHuman) || !entity.isSpectator() && !((EntityHuman) entity).isCreative() && entity.world.getDifficulty() != EnumDifficulty.PEACEFUL; - }; -diff --git a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -index 3941dd33da4b5c09d0087143f1d8a2d76fc18792..62513c812b497bb9d8dafe1d9c2f574059aebf15 100644 ---- a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -+++ b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -@@ -116,6 +116,7 @@ public class AxisAlignedBB { - return this.b(vec3d.x, vec3d.y, vec3d.z); - } - -+ public final AxisAlignedBB expand(double x, double y, double z) { return b(x, y, z); } // Paper - OBFHELPER - public AxisAlignedBB b(double d0, double d1, double d2) { - double d3 = this.minX; - double d4 = this.minY; -@@ -145,6 +146,12 @@ public class AxisAlignedBB { - return new AxisAlignedBB(d3, d4, d5, d6, d7, d8); - } - -+ // Paper start -+ public AxisAlignedBB grow(double d0) { -+ return grow(d0, d0, d0); -+ } -+ // Paper end -+ - public AxisAlignedBB grow(double d0, double d1, double d2) { - double d3 = this.minX - d0; - double d4 = this.minY - d1; -@@ -204,6 +211,7 @@ public class AxisAlignedBB { - return this.minX < d3 && this.maxX > d0 && this.minY < d4 && this.maxY > d1 && this.minZ < d5 && this.maxZ > d2; - } - -+ public final boolean contains(Vec3D vec3d) { return d(vec3d); } // Paper - OBFHELPER - public boolean d(Vec3D vec3d) { - return this.e(vec3d.x, vec3d.y, vec3d.z); - } -@@ -237,6 +245,7 @@ public class AxisAlignedBB { - return this.g(-d0); - } - -+ public final Optional calculateIntercept(Vec3D vec3d, Vec3D vec3d1) { return b(vec3d, vec3d1); } // Paper - OBFHELPER - public Optional b(Vec3D vec3d, Vec3D vec3d1) { - double[] adouble = new double[]{1.0D}; - double d0 = vec3d1.x - vec3d.x; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 194583522c53ae838dfc0ccfa49f906c1a628984..db5d9a8107babd42200f911d2b8ebdc15b4d7c8b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -1,6 +1,7 @@ - package org.bukkit.craftbukkit.entity; - - import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.destroystokyo.paper.entity.TargetEntityInfo; - import com.google.common.base.Preconditions; - import com.google.common.collect.Sets; - import java.util.ArrayList; -@@ -42,8 +43,11 @@ import net.minecraft.world.entity.projectile.EntityThrownExpBottle; - import net.minecraft.world.entity.projectile.EntityThrownTrident; - import net.minecraft.world.entity.projectile.EntityTippedArrow; - import net.minecraft.world.entity.projectile.EntityWitherSkull; -+import net.minecraft.world.level.RayTrace; - import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; -+import net.minecraft.world.phys.MovingObjectPositionEntity; -+import net.minecraft.world.phys.Vec3D; - import org.apache.commons.lang.Validate; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -227,6 +231,33 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - new TargetBlockInfo(CraftBlock.at(getHandle().world, ((MovingObjectPositionBlock)rayTrace).getBlockPosition()), - MCUtil.toBukkitBlockFace(((MovingObjectPositionBlock)rayTrace).getDirection())); - } -+ -+ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks) { -+ MovingObjectPositionEntity rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); -+ return rayTrace == null ? null : rayTrace.getEntity().getBukkitEntity(); -+ } -+ -+ public TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks) { -+ MovingObjectPositionEntity rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); -+ return rayTrace == null ? null : new TargetEntityInfo(rayTrace.getEntity().getBukkitEntity(), new org.bukkit.util.Vector(rayTrace.getPos().x, rayTrace.getPos().y, rayTrace.getPos().z)); -+ } -+ -+ public MovingObjectPositionEntity rayTraceEntity(int maxDistance, boolean ignoreBlocks) { -+ MovingObjectPositionEntity rayTrace = getHandle().getTargetEntity(maxDistance); -+ if (rayTrace == null) { -+ return null; -+ } -+ if (!ignoreBlocks) { -+ MovingObjectPosition rayTraceBlocks = getHandle().getRayTrace(maxDistance, RayTrace.FluidCollisionOption.NONE); -+ if (rayTraceBlocks != null) { -+ Vec3D eye = getHandle().getEyePosition(1.0F); -+ if (eye.distanceSquared(rayTraceBlocks.getPos()) <= eye.distanceSquared(rayTrace.getPos())) { -+ return null; -+ } -+ } -+ } -+ return rayTrace; -+ } - // Paper end - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/Unmapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch deleted file mode 100644 index b9eefdc882..0000000000 --- a/Unmapped-Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 20 Mar 2019 21:19:29 -0700 -Subject: [PATCH] Use proper max length when serialising BungeeCord text - component - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -index f6a1c5ac9acb34b1ef2262721adbbb1a5b0feaf7..fefcacf27d71c67403555502685a992a5a706099 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -@@ -9,7 +9,7 @@ import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.Packet; - - public class PacketPlayOutChat implements Packet { -- -+ private static final int MAX_LENGTH = Short.MAX_VALUE * 8 + 8; // Paper - private IChatBaseComponent a; - public net.kyori.adventure.text.Component adventure$message; // Paper - public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot -@@ -43,9 +43,9 @@ public class PacketPlayOutChat implements Packet { - //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below - // Paper start - don't nest if we don't need to so that we can preserve formatting - if (this.components.length == 1) { -- packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]), MAX_LENGTH); // Paper - use proper max length - } else { -- packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components), MAX_LENGTH); // Paper - use proper max length - } - // Paper end - } else { diff --git a/Unmapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch b/Unmapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch deleted file mode 100644 index ff4a1a2635..0000000000 --- a/Unmapped-Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 00:24:52 -0400 -Subject: [PATCH] Entity#getEntitySpawnReason - -Allows you to return the SpawnReason for why an Entity Spawned - -Pre existing entities will return NATURAL if it was a non -persistenting Living Entity, SPAWNER for spawners, -or DEFAULT since data was not stored. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index ecb4cb5df868673e5aa2eec3fdd8618dbea09655..d7c6f49ba1c84c45b387e155d9ae7452e5171df6 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1041,6 +1041,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -+ if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper - // Paper start - if (entity.valid) { - MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 1ae969aff1d44ad9af28fc94d8821884b9ad0563..47aa69dfe43390b811c264adc0af1d01bcd5ce4d 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -335,7 +335,7 @@ public abstract class PlayerList { - // CraftBukkit start - WorldServer finalWorldServer = worldserver1; - Entity entity = EntityTypes.a(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { -- return !finalWorldServer.addEntitySerialized(entity1) ? null : entity1; -+ return !finalWorldServer.addEntitySerialized(entity1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity1; // Paper - // CraftBukkit end - }); - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 413f715c98dc0a0953e60032ad1ebef2b0b3bbe3..712c81fe2cf6da6b80fea21fd6c3d0e0adc5a35a 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -63,6 +63,8 @@ import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.INamableTileEntity; - import net.minecraft.world.damagesource.DamageSource; -+import net.minecraft.world.entity.animal.EntityAnimal; -+import net.minecraft.world.entity.animal.EntityFish; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.vehicle.EntityBoat; -@@ -158,6 +160,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - }; - public List entitySlice = null; -+ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; - // Paper end - - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper -@@ -1674,6 +1677,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - nbttagcompound.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); - nbttagcompound.set("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); - } -+ if (spawnReason != null) { -+ nbttagcompound.setString("Paper.SpawnReason", spawnReason.name()); -+ } - // Save entity's from mob spawner status - if (spawnedViaMobSpawner) { - nbttagcompound.setBoolean("Paper.FromMobSpawner", true); -@@ -1812,6 +1818,26 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ if (nbttagcompound.hasKey("Paper.SpawnReason")) { -+ String spawnReasonName = nbttagcompound.getString("Paper.SpawnReason"); -+ try { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName); -+ } catch (Exception ignored) { -+ LogManager.getLogger().error("Unknown SpawnReason " + spawnReasonName + " for " + this); -+ } -+ } -+ if (spawnReason == null) { -+ if (spawnedViaMobSpawner) { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; -+ } else if (this instanceof EntityInsentient && (this instanceof EntityAnimal || this instanceof EntityFish) && !((EntityInsentient) this).isTypeNotPersistent(0.0)) { -+ if (!nbttagcompound.getBoolean("PersistenceRequired")) { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL; -+ } -+ } -+ } -+ if (spawnReason == null) { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; -+ } - // Paper end - - } catch (Throwable throwable) { -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 867478484c0ba4ff467b96e458689937299b981d..34bcee4ff55ba118ba393e94b3c25ee2b84feaa2 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -183,6 +183,7 @@ public abstract class MobSpawnerAbstract { - // Spigot End - } - entity.spawnedViaMobSpawner = true; // Paper -+ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper - flag = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 3642b17cafffd2818ee7a18d26bc25645f596115..93bbf63e9d38f32d5528c7693633d4b65655bb9d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1106,5 +1106,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public boolean fromMobSpawner() { - return getHandle().spawnedViaMobSpawner; - } -+ -+ @Override -+ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { -+ return getHandle().spawnReason; -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch b/Unmapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch deleted file mode 100644 index 8e4f0f1b36..0000000000 --- a/Unmapped-Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AgentTroll -Date: Fri, 22 Mar 2019 22:24:03 -0700 -Subject: [PATCH] Update entity Metadata for all tracked players - - -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index e3cdea3c85d762af6984f3dbe544fdfe101f6ff6..6110d7723b70df5380338a42b5cbff3446294bac 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -421,6 +421,12 @@ public class EntityTrackerEntry { - return PacketPlayOutEntity.a(this.xLoc, this.yLoc, this.zLoc); - } - -+ // Paper start - Add broadcast method -+ void broadcast(Packet packet) { -+ this.getPacketConsumer().accept(packet); -+ } -+ // Paper end -+ - private void broadcastIncludingSelf(Packet packet) { - this.f.accept(packet); - if (this.tracker instanceof EntityPlayer) { -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index c0c9af81a933135e940587c10155a24cd399b922..d279c5673f1daf34914203ade0e893ea994fc607 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2288,7 +2288,14 @@ public class PlayerConnection implements PacketListenerPlayIn { - - if (event.isCancelled() || this.player.inventory.getItemInHand() == null || this.player.inventory.getItemInHand().getItem() != origItem) { - // Refresh the current entity metadata -- this.sendPacket(new PacketPlayOutEntityMetadata(entity.getId(), entity.getDataWatcher(), true)); -+ // Paper start - update entity for all players -+ PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entity.getId(), entity.getDataWatcher(), true); -+ if (entity.tracker != null) { -+ entity.tracker.broadcast(packet); -+ } else { -+ this.sendPacket(packet); -+ } -+ // Paper end - } - - if (event.isCancelled()) { diff --git a/Unmapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch b/Unmapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch deleted file mode 100644 index 8a761d4f0c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterVector -Date: Fri, 26 Oct 2018 21:31:00 -0700 -Subject: [PATCH] Implement PlayerPostRespawnEvent - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 47aa69dfe43390b811c264adc0af1d01bcd5ce4d..ec4e84f6275f8b305fb5a64f9c0cff24729d73ec 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -741,9 +741,14 @@ public abstract class PlayerList { - // this.a(entityplayer1, entityplayer, worldserver1); // CraftBukkit - removed - boolean flag2 = false; - -+ // Paper start -+ boolean isBedSpawn = false; -+ boolean isRespawn = false; -+ // Paper end -+ - // CraftBukkit start - fire PlayerRespawnEvent - if (location == null) { -- boolean isBedSpawn = false; -+ // boolean isBedSpawn = false; // Paper - moved up - WorldServer worldserver1 = this.server.getWorldServer(entityplayer.getSpawnDimension()); - if (worldserver1 != null) { - Optional optional; -@@ -794,6 +799,7 @@ public abstract class PlayerList { - - location = respawnEvent.getRespawnLocation(); - if (!flag) entityplayer.reset(); // SPIGOT-4785 -+ isRespawn = true; // Paper - } else { - location.setWorld(worldserver.getWorld()); - } -@@ -851,6 +857,13 @@ public abstract class PlayerList { - if (entityplayer.playerConnection.isDisconnected()) { - this.savePlayerFile(entityplayer); - } -+ -+ // Paper start -+ if (isRespawn) { -+ cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(entityplayer.getBukkitEntity(), location, isBedSpawn)); -+ } -+ // Paper end -+ - // CraftBukkit end - return entityplayer1; - } diff --git a/Unmapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/Unmapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch deleted file mode 100644 index f77a4f7db2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 18:09:20 -0400 -Subject: [PATCH] don't go below 0 for pickupDelay, breaks picking up items - -vanilla checks for == 0 - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 4cfe3475fa913cd46116f13ea8ed9caf5372a41a..02e4d6891adc902f73ed349f15dae3a429bd283a 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -87,6 +87,7 @@ public class EntityItem extends Entity { - // CraftBukkit start - Use wall time for pickup and despawn timers - int elapsedTicks = MinecraftServer.currentTick - this.lastTick; - if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; -+ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 - if (this.age != -32768) this.age += elapsedTicks; - this.lastTick = MinecraftServer.currentTick; - // CraftBukkit end -@@ -179,6 +180,7 @@ public class EntityItem extends Entity { - // CraftBukkit start - Use wall time for pickup and despawn timers - int elapsedTicks = MinecraftServer.currentTick - this.lastTick; - if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; -+ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 - if (this.age != -32768) this.age += elapsedTicks; - this.lastTick = MinecraftServer.currentTick; - // CraftBukkit end diff --git a/Unmapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch b/Unmapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch deleted file mode 100644 index 4d6df2d1b0..0000000000 --- a/Unmapped-Spigot-Server-Patches/0340-Server-Tick-Events.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Mar 2019 22:48:45 -0400 -Subject: [PATCH] Server Tick Events - -Fires event at start and end of a server tick - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 419448fe02b58e08c17795c903c945ad8a3ce1b5..fa7935cccb450ae5f782fec5ebe27275fe6dd510 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1239,6 +1239,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Wed, 27 Mar 2019 23:01:33 -0400 -Subject: [PATCH] PlayerDeathEvent#getItemsToKeep - -Exposes a mutable array on items a player should keep on death - -Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4 - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 82f49078a91b6ac471d303bc68891d80e201bd1f..a15b119b24090ffc607bfc9003d5b95f3acf3b2f 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -695,6 +695,46 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - }); - } - -+ // Paper start - process inventory -+ private static void processKeep(org.bukkit.event.entity.PlayerDeathEvent event, NonNullList inv) { -+ List itemsToKeep = event.getItemsToKeep(); -+ if (inv == null) { -+ // remainder of items left in toKeep - plugin added stuff on death that wasn't in the initial loot? -+ if (!itemsToKeep.isEmpty()) { -+ for (org.bukkit.inventory.ItemStack itemStack : itemsToKeep) { -+ event.getEntity().getInventory().addItem(itemStack); -+ } -+ } -+ -+ return; -+ } -+ -+ for (int i = 0; i < inv.size(); ++i) { -+ ItemStack item = inv.get(i); -+ if (EnchantmentManager.shouldNotDrop(item) || itemsToKeep.isEmpty() || item.isEmpty()) { -+ inv.set(i, ItemStack.NULL_ITEM); -+ continue; -+ } -+ -+ final org.bukkit.inventory.ItemStack bukkitStack = item.getBukkitStack(); -+ boolean keep = false; -+ final Iterator iterator = itemsToKeep.iterator(); -+ while (iterator.hasNext()) { -+ final org.bukkit.inventory.ItemStack itemStack = iterator.next(); -+ if (bukkitStack.equals(itemStack)) { -+ iterator.remove(); -+ keep = true; -+ break; -+ } -+ } -+ -+ if (!keep) { -+ inv.set(i, ItemStack.NULL_ITEM); -+ } -+ } -+ } -+ // Paper end -+ - @Override - public void die(DamageSource damagesource) { - boolean flag = this.world.getGameRules().getBoolean(GameRules.SHOW_DEATH_MESSAGES); -@@ -778,7 +818,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.dropExperience(); - // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. - if (!event.getKeepInventory()) { -- this.inventory.clear(); -+ // Paper start - replace logic -+ for (NonNullList inv : this.inventory.getComponents()) { -+ processKeep(event, inv); -+ } -+ processKeep(event, null); -+ // Paper end - } - - this.setSpectatorTarget(this); // Remove spectated target diff --git a/Unmapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch b/Unmapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch deleted file mode 100644 index bcc3098364..0000000000 --- a/Unmapped-Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 6 Apr 2019 10:16:48 -0400 -Subject: [PATCH] Optimize Captured TileEntity Lookup - -upstream was doing a containsKey/get pattern, and always doing it at that. -that scenario is only even valid if were in the middle of a block place. - -Optimize to check if the captured list even has values in it, and also to -just do a get call since the value can never be null. - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 3b5ddc083719608e944bdefa38e1fd3909e8e200..b6b9a471426ddf911a1f6bf38543c0304bfc31f6 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -968,12 +968,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return null; - } else { - // CraftBukkit start -- if (capturedTileEntities.containsKey(blockposition)) { -- return capturedTileEntities.get(blockposition); -+ TileEntity tileentity = null; // Paper -+ if (!capturedTileEntities.isEmpty() && (tileentity = capturedTileEntities.get(blockposition)) != null) { // Paper -+ return tileentity; // Paper - } - // CraftBukkit end - -- TileEntity tileentity = null; -+ //TileEntity tileentity = null; // Paper - move up - - if (this.tickingTileEntities) { - tileentity = this.E(blockposition); diff --git a/Unmapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch b/Unmapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch deleted file mode 100644 index f2e6c95731..0000000000 --- a/Unmapped-Spigot-Server-Patches/0343-Add-Heightmap-API.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 1 Jan 2019 02:22:01 -0800 -Subject: [PATCH] Add Heightmap API - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index b6b9a471426ddf911a1f6bf38543c0304bfc31f6..12ac3608736b45447afe6b0d35ead1441390be5e 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -670,8 +670,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - } - -- @Override -- public int a(HeightMap.Type heightmap_type, int i, int j) { -+ public final int getHighestBlockY(final HeightMap.Type heightmap, final int x, final int z) { return this.a(heightmap, x, z); } // Paper - OBFHELPER -+ @Override public int a(HeightMap.Type heightmap_type, int i, int j) { // Paper - OBFHELPER - int k; - - if (i >= -30000000 && j >= -30000000 && i < 30000000 && j < 30000000) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 95b4774b7696fa9711d7169d06a23c70364bfdb2..9e44b60843a6463951382cb66c93f1fab24e5e5d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -343,6 +343,29 @@ public class CraftWorld implements World { - return getHighestBlockYAt(x, z, org.bukkit.HeightMap.MOTION_BLOCKING); - } - -+ // Paper start - Implement heightmap api -+ @Override -+ public int getHighestBlockYAt(final int x, final int z, final com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { -+ this.getChunkAt(x >> 4, z >> 4); // heightmap will ret 0 on unloaded areas -+ -+ switch (heightmap) { -+ case LIGHT_BLOCKING: -+ throw new UnsupportedOperationException(); // TODO -+ //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z); -+ case ANY: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.WORLD_SURFACE, x, z); -+ case SOLID: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.OCEAN_FLOOR, x, z); -+ case SOLID_OR_LIQUID: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.MOTION_BLOCKING, x, z); -+ case SOLID_OR_LIQUID_NO_LEAVES: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, x, z); -+ default: -+ throw new UnsupportedOperationException(); -+ } -+ } -+ // Paper end -+ - @Override - public Location getSpawnLocation() { - BlockPosition spawn = world.getSpawn(); diff --git a/Unmapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch b/Unmapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch deleted file mode 100644 index 37f6cfaac5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 19 Apr 2019 12:41:13 -0500 -Subject: [PATCH] Mob Spawner API Enhancements - - -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 34bcee4ff55ba118ba393e94b3c25ee2b84feaa2..5538404456dfee42257fad9040fcc0fefdfc5fab 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -65,6 +65,7 @@ public abstract class MobSpawnerAbstract { - this.mobs.clear(); // CraftBukkit - SPIGOT-3496, MC-92282 - } - -+ public boolean isActivated() { return h(); } // Paper - OBFHELPER - private boolean h() { - BlockPosition blockposition = this.b(); - -@@ -221,6 +222,7 @@ public abstract class MobSpawnerAbstract { - } - } - -+ public void resetTimer() { i(); } // Paper - OBFHELPER - private void i() { - if (this.maxSpawnDelay <= this.minSpawnDelay) { - this.spawnDelay = this.minSpawnDelay; -@@ -238,7 +240,13 @@ public abstract class MobSpawnerAbstract { - } - - public void a(NBTTagCompound nbttagcompound) { -+ // Paper start - use larger int if set -+ if (nbttagcompound.hasKey("Paper.Delay")) { -+ this.spawnDelay = nbttagcompound.getInt("Paper.Delay"); -+ } else { - this.spawnDelay = nbttagcompound.getShort("Delay"); -+ } -+ // Paper end - this.mobs.clear(); - if (nbttagcompound.hasKeyOfType("SpawnPotentials", 9)) { - NBTTagList nbttaglist = nbttagcompound.getList("SpawnPotentials", 10); -@@ -253,10 +261,15 @@ public abstract class MobSpawnerAbstract { - } else if (!this.mobs.isEmpty()) { - this.setSpawnData((MobSpawnerData) WeightedRandom.a(this.a().random, this.mobs)); - } -- -+ // Paper start - use ints if set -+ if (nbttagcompound.hasKeyOfType("Paper.MinSpawnDelay", 99)) { -+ this.minSpawnDelay = nbttagcompound.getInt("Paper.MinSpawnDelay"); -+ this.maxSpawnDelay = nbttagcompound.getInt("Paper.MaxSpawnDelay"); -+ this.spawnCount = nbttagcompound.getShort("SpawnCount"); -+ } else // Paper end - if (nbttagcompound.hasKeyOfType("MinSpawnDelay", 99)) { -- this.minSpawnDelay = nbttagcompound.getShort("MinSpawnDelay"); -- this.maxSpawnDelay = nbttagcompound.getShort("MaxSpawnDelay"); -+ this.minSpawnDelay = nbttagcompound.getInt("MinSpawnDelay"); -+ this.maxSpawnDelay = nbttagcompound.getInt("MaxSpawnDelay"); - this.spawnCount = nbttagcompound.getShort("SpawnCount"); - } - -@@ -281,9 +294,20 @@ public abstract class MobSpawnerAbstract { - if (minecraftkey == null) { - return nbttagcompound; - } else { -- nbttagcompound.setShort("Delay", (short) this.spawnDelay); -- nbttagcompound.setShort("MinSpawnDelay", (short) this.minSpawnDelay); -- nbttagcompound.setShort("MaxSpawnDelay", (short) this.maxSpawnDelay); -+ // Paper start -+ if (spawnDelay > Short.MAX_VALUE) { -+ nbttagcompound.setInt("Paper.Delay", this.spawnDelay); -+ } -+ nbttagcompound.setShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay)); -+ -+ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) { -+ nbttagcompound.setInt("Paper.MinSpawnDelay", this.minSpawnDelay); -+ nbttagcompound.setInt("Paper.MaxSpawnDelay", this.maxSpawnDelay); -+ } -+ -+ nbttagcompound.setShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay)); -+ nbttagcompound.setShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay)); -+ // Paper end - nbttagcompound.setShort("SpawnCount", (short) this.spawnCount); - nbttagcompound.setShort("MaxNearbyEntities", (short) this.maxNearbyEntities); - nbttagcompound.setShort("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 28295ebd338806a35cbef164cb014abfe7dae769..3d29be926e36b9a5a981eea1f2a1ec54a4c43393 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -@@ -1,13 +1,21 @@ - package org.bukkit.craftbukkit.block; - - import com.google.common.base.Preconditions; -+import net.minecraft.core.IRegistry; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.level.MobSpawnerData; - import net.minecraft.world.level.block.entity.TileEntityMobSpawner; - import org.bukkit.Material; - import org.bukkit.block.Block; - import org.bukkit.block.CreatureSpawner; - import org.bukkit.entity.EntityType; -+// Paper start -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.inventory.ItemStack; -+// Paper end - - public class CraftCreatureSpawner extends CraftBlockEntityState implements CreatureSpawner { - -@@ -121,4 +129,30 @@ public class CraftCreatureSpawner extends CraftBlockEntityState -Date: Mon, 6 May 2019 01:29:25 -0400 -Subject: [PATCH] Per-Player View Distance API placeholders - -I hope to look at this more in-depth soon. It appears doable. -However this should not block the update. - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 51993191e01f55e16667c25b8b57d6a6ddaf493b..5168a40eb53565bb3028efe559601acf72bddae5 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -625,9 +625,10 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - if (this.deathAnimationTicks == 1 && !this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1028, this.getChunkCoordinates(), 0); -- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API - for (net.minecraft.server.level.EntityPlayer player : (List) ((WorldServer)world).getPlayers()) { -- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // Paper end - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 145767e8b0fc4105a0afa47af17dcdbb75e952bc..174eb12722872182b2d9b54841e5bb57893695a1 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -258,9 +258,9 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - if (!this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1023, new BlockPosition(this), 0); -- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API - for (EntityPlayer player : (List)this.world.getPlayers()) { -- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index f57ad014fb3d2ce2405bdd63db4c730458aac17a..dc8545241ed62f6b654b2559e025c3b34c00575f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2243,6 +2243,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - super.remove(); - } - } -+ -+ @Override -+ public int getViewDistance() { -+ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO -+ } -+ -+ @Override -+ public void setViewDistance(int viewDistance) { -+ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO -+ } - // Paper end - - // Spigot start diff --git a/Unmapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch b/Unmapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch deleted file mode 100644 index 66128f4cbe..0000000000 --- a/Unmapped-Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Fri, 10 May 2019 18:38:19 +0100 -Subject: [PATCH] Fix CB call to changed postToMainThread method - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index d279c5673f1daf34914203ade0e893ea994fc607..c3a3837badb4b2a2ab51e6fb2d7cfbaa2f4d8edb 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -445,7 +445,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.networkManager.getClass(); - // CraftBukkit - Don't wait -- minecraftserver.postToMainThread(networkmanager::handleDisconnection); -+ minecraftserver.scheduleOnMain(networkmanager::handleDisconnection); // Paper - } - - private void a(T t0, Consumer consumer, BiFunction>> bifunction) { diff --git a/Unmapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/Unmapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch deleted file mode 100644 index 05a0bc0d4c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sat, 27 Apr 2019 20:00:43 +0100 -Subject: [PATCH] Fix sounds when item frames are modified (MC-123450) - -This also fixes the adding sound playing when the item frame direction is changed. - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java -index 584f64946821092afab57b9409bc249403bc16e7..43152a6c70c9433d627a58051101530ddd693307 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java -@@ -277,7 +277,7 @@ public class EntityItemFrame extends EntityHanging { - } - - this.getDataWatcher().set(EntityItemFrame.ITEM, itemstack); -- if (!itemstack.isEmpty() && playSound) { // CraftBukkit -+ if (!itemstack.isEmpty() && flag && playSound) { // CraftBukkit // Paper - only play sound when update flag is set - this.playSound(SoundEffects.ENTITY_ITEM_FRAME_ADD_ITEM, 1.0F, 1.0F); - } - diff --git a/Unmapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/Unmapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch deleted file mode 100644 index 0e8169316d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 13 May 2019 21:10:59 -0700 -Subject: [PATCH] Fix CraftServer#isPrimaryThread and MinecraftServer - isMainThread - -md_5 changed it so he could shut down the server asynchronously -from watchdog, although we have patches that prevent that type -of behavior for this exact reason. - -md_5 also placed code in PlayerConnectionUtils that would have -solved https://bugs.mojang.com/browse/MC-142590, making the change -to MinecraftServer#isMainThread irrelevant. -By reverting his change to MinecraftServer#isMainThread packet -handling that should have been handled synchronously will be handled -synchronously when the server gets shut down. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index fa7935cccb450ae5f782fec5ebe27275fe6dd510..5a5e097b131500d7cb9f61ea0f96f9006fabb941 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2192,7 +2192,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Fri, 28 Sep 2018 21:49:53 -0400 -Subject: [PATCH] Fix issues with entity loss due to unloaded chunks - -Vanilla has risk of losing entities by causing them to be -removed from all chunks if they try to move into an unloaded chunk. - -This pretty much means high chance this entity will be lost in this -scenario. - -There is another case that adding an entity to the world can fail if -the chunk isn't loaded. - -Lots of the server is designed around addEntity never expecting to fail -for these reasons, nor is it really logical. - -This change ensures the chunks are always loaded when entities are -added to the world, or a valid entity moves between chunks. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index d7c6f49ba1c84c45b387e155d9ae7452e5171df6..4e26db120e544d8867d895395241e425f23f575b 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -854,11 +854,18 @@ public class WorldServer extends World implements GeneratorAccessSeed { - int k = MathHelper.floor(entity.locZ() / 16.0D); - - if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) { -+ // Paper start - remove entity if its in a chunk more correctly. -+ Chunk currentChunk = entity.getCurrentChunk(); -+ if (currentChunk != null) { -+ currentChunk.removeEntity(entity); -+ } -+ // Paper end -+ - if (entity.inChunk && this.isChunkLoaded(entity.chunkX, entity.chunkZ)) { - this.getChunkAt(entity.chunkX, entity.chunkZ).a(entity, entity.chunkY); - } - -- if (!entity.ck() && !this.isChunkLoaded(i, k)) { -+ if (!entity.valid && !entity.ck() && !this.isChunkLoaded(i, k)) { // Paper - always load chunks to register valid entities location - if (entity.inChunk) { - WorldServer.LOGGER.warn("Entity {} left loaded chunk area", entity); - } -@@ -1073,7 +1080,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return false; - } - // CraftBukkit end -- IChunkAccess ichunkaccess = this.getChunkAt(MathHelper.floor(entity.locX() / 16.0D), MathHelper.floor(entity.locZ() / 16.0D), ChunkStatus.FULL, entity.attachedToPlayer); -+ IChunkAccess ichunkaccess = this.getChunkAt(MathHelper.floor(entity.locX() / 16.0D), MathHelper.floor(entity.locZ() / 16.0D), ChunkStatus.FULL, true); // Paper - always load chunks for entity adds - - if (!(ichunkaccess instanceof Chunk)) { - return false; diff --git a/Unmapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch b/Unmapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch deleted file mode 100644 index 3583743eaf..0000000000 --- a/Unmapped-Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch +++ /dev/null @@ -1,249 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 21 Jul 2018 14:27:34 -0400 -Subject: [PATCH] Duplicate UUID Resolve Option - -Due to a bug in https://github.com/PaperMC/Paper/commit/2e29af3df05ec0a383f48be549d1c03200756d24 -which was added all the way back in March of 2016, it was unknown (potentially not at the time) -that an entity might actually change the seed of the random object. - -At some point, EntitySquid did start setting the seed. Due to this shared random, this caused -every entity to use a Random object with a predictable seed. - -This has caused entities to potentially generate with the same UUID.... - -Over the years, servers have had entities disappear, but no sign of trouble -because CraftBukkit removed the log lines indicating that something was wrong. - -We have fixed the root issue causing duplicate UUID's, however we now have chunk -files full of entities that have the same UUID as another entity! - -When these chunks load, the 2nd entity will not be added to the world correctly. - -If that chunk loads in a different order in the future, then it will reverse and the -missing one is now the one added to the world and not the other. This results in very -inconsistent entity behavior. - -This change allows you to recover any duplicate entity by generating a new UUID for it. -This also lets you delete them instead if you don't want to risk having new entities added to -the world that you previously did not see. - -But for those who are ok with leaving this inconsistent behavior, you may use WARN or NOTHING options. - -It is recommended you regenerate the entities, as these were legit entities, and deserve your love. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index fbf3ccfb347a5ba6e895339e9576629d940d1aa4..38d25a12c6a52d8a83214e2a0f43a218cf15ceac 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -401,4 +401,43 @@ public class PaperWorldConfig { - private void preventMovingIntoUnloadedChunks() { - preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); - } -+ -+ public enum DuplicateUUIDMode { -+ SAFE_REGEN, DELETE, NOTHING, WARN -+ } -+ public DuplicateUUIDMode duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; -+ public int duplicateUUIDDeleteRange = 32; -+ private void repairDuplicateUUID() { -+ String desiredMode = getString("duplicate-uuid-resolver", "saferegen").toLowerCase().trim(); -+ duplicateUUIDDeleteRange = getInt("duplicate-uuid-saferegen-delete-range", duplicateUUIDDeleteRange); -+ switch (desiredMode.toLowerCase()) { -+ case "regen": -+ case "regenerate": -+ case "saferegen": -+ case "saferegenerate": -+ duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; -+ log("Duplicate UUID Resolve: Regenerate New UUID if distant (Delete likely duplicates within " + duplicateUUIDDeleteRange + " blocks)"); -+ break; -+ case "remove": -+ case "delete": -+ duplicateUUIDMode = DuplicateUUIDMode.DELETE; -+ log("Duplicate UUID Resolve: Delete Entity"); -+ break; -+ case "silent": -+ case "nothing": -+ duplicateUUIDMode = DuplicateUUIDMode.NOTHING; -+ logError("Duplicate UUID Resolve: Do Nothing (no logs) - Warning, may lose indication of bad things happening"); -+ break; -+ case "log": -+ case "warn": -+ duplicateUUIDMode = DuplicateUUIDMode.WARN; -+ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); -+ break; -+ default: -+ duplicateUUIDMode = DuplicateUUIDMode.WARN; -+ logError("Warning: Invalid duplicate-uuid-resolver config " + desiredMode + " - must be one of: regen, delete, nothing, warn"); -+ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); -+ break; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 66c808244bba70f827d8f15a96814251d352a046..b736917891afb17e412f94c5d8713aa653b8dc46 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1,6 +1,7 @@ - package net.minecraft.server.level; - - import co.aikar.timings.Timing; // Paper -+import com.destroystokyo.paper.PaperWorldConfig; // Paper - import com.google.common.collect.ImmutableList; - import com.google.common.collect.Iterables; - import com.google.common.collect.ComparisonChain; // Paper -@@ -23,14 +24,17 @@ import it.unimi.dsi.fastutil.objects.ObjectIterator; - import java.io.File; - import java.io.IOException; - import java.io.Writer; -+import java.util.HashMap; // Paper - import java.util.Collection; - import java.util.Iterator; - import java.util.List; -+import java.util.Map; // Paper - import java.util.Objects; - import java.util.Optional; - import java.util.Queue; - import java.util.Set; - import java.util.concurrent.CancellationException; -+import java.util.UUID; // Paper - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.CompletionException; - import java.util.concurrent.Executor; -@@ -73,6 +77,7 @@ import net.minecraft.world.entity.boss.EntityComplexPart; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.GameRules; -+import net.minecraft.world.level.World; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkConverter; - import net.minecraft.world.level.chunk.ChunkGenerator; -@@ -699,18 +704,18 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (chunk.needsDecoration) { - net.minecraft.server.dedicated.DedicatedServer server = this.world.getServer().getServer(); - if (!server.getSpawnNPCs() && entity instanceof net.minecraft.world.entity.npc.NPC) { -- entity.die(); -+ entity.dead = true; // Paper - needsRemoval = true; - } - - if (!server.getSpawnAnimals() && (entity instanceof net.minecraft.world.entity.animal.EntityAnimal || entity instanceof net.minecraft.world.entity.animal.EntityWaterAnimal)) { -- entity.die(); -+ entity.dead = true; // Paper - needsRemoval = true; - } - } -- -- if (!(entity instanceof EntityHuman) && (needsRemoval || !this.world.addEntityChunk(entity))) { -- // CraftBukkit end -+ // CraftBukkit end -+ checkDupeUUID(entity); // Paper -+ if (!(entity instanceof EntityHuman) && (entity.dead || !this.world.addEntityChunk(entity))) { // Paper - if (list == null) { - list = Lists.newArrayList(new Entity[]{entity}); - } else { -@@ -737,6 +742,44 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }); - } - -+ // Paper start -+ private void checkDupeUUID(Entity entity) { -+ PaperWorldConfig.DuplicateUUIDMode mode = world.paperConfig.duplicateUUIDMode; -+ if (mode != PaperWorldConfig.DuplicateUUIDMode.WARN -+ && mode != PaperWorldConfig.DuplicateUUIDMode.DELETE -+ && mode != PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN) { -+ return; -+ } -+ Entity other = world.getEntity(entity.getUniqueID()); -+ -+ if (mode == PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN && other != null && !other.dead -+ && Objects.equals(other.getSaveID(), entity.getSaveID()) -+ && entity.getBukkitEntity().getLocation().distance(other.getBukkitEntity().getLocation()) < world.paperConfig.duplicateUUIDDeleteRange -+ ) { -+ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + " because it was near the duplicate and likely an actual duplicate. See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ entity.dead = true; -+ return; -+ } -+ if (other != null && !other.dead) { -+ switch (mode) { -+ case SAFE_REGEN: { -+ entity.setUUID(UUID.randomUUID()); -+ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", regenerated UUID for " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ break; -+ } -+ case DELETE: { -+ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ entity.dead = true; -+ break; -+ } -+ default: -+ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", doing nothing to " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ break; -+ } -+ } -+ } -+ // Paper end -+ - public CompletableFuture> a(PlayerChunk playerchunk) { - ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); - CompletableFuture, PlayerChunk.Failure>> completablefuture = this.a(chunkcoordintpair, 1, (i) -> { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 4e26db120e544d8867d895395241e425f23f575b..fbff779fa581a661cc03850bffa0da346ce15625 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -4,6 +4,8 @@ import com.google.common.annotations.VisibleForTesting; - import com.google.common.collect.Iterables; - import co.aikar.timings.TimingHistory; // Paper - import co.aikar.timings.Timings; // Paper -+ -+import com.destroystokyo.paper.PaperWorldConfig; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Queues; -@@ -1108,7 +1110,22 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (entity1 == null) { - return false; - } else { -+ // Paper start -+ if (entity1.dead) { -+ unregisterEntity(entity1); // remove the existing entity -+ return false; -+ } -+ // Paper end - WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit // Paper -+ // Paper start -+ if (DEBUG_ENTITIES && entity.world.paperConfig.duplicateUUIDMode != PaperWorldConfig.DuplicateUUIDMode.NOTHING) { -+ if (entity1.addedToWorldStack != null) { -+ entity1.addedToWorldStack.printStackTrace(); -+ } -+ -+ getAddToWorldStackTrace(entity).printStackTrace(); -+ } -+ // Paper end - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 712c81fe2cf6da6b80fea21fd6c3d0e0adc5a35a..efa8d9a16e87475adf7e71a0dfa2861653f73c06 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2804,6 +2804,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - }); - } - -+ public final void setUUID(UUID uuid) { a_(uuid); } // Paper - OBFHELPER - public void a_(UUID uuid) { - this.uniqueID = uuid; - this.ae = this.uniqueID.toString(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 79ff96f18c53f3d1ce4a00be2e2d8fe68f77bf54..3f926ed8e2b2c9dbf1e2493870af7eff3b6db019 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -542,6 +542,7 @@ public class Chunk implements IChunkAccess { - if (i != this.loc.x || j != this.loc.z) { - Chunk.LOGGER.warn("Wrong location! ({}, {}) should be ({}, {}), {}", i, j, this.loc.x, this.loc.z, entity); - entity.dead = true; -+ return; // Paper - } - - int k = MathHelper.floor(entity.locY() / 16.0D); diff --git a/Unmapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch b/Unmapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch deleted file mode 100644 index 111ce24a81..0000000000 --- a/Unmapped-Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 21 May 2019 02:34:04 +0100 -Subject: [PATCH] improve CraftWorld#isChunkLoaded - -getChunkAt will request the chunk using vanillas chunk loading system, -which while we're not going to load the chunk, does involve the server -waiting for the execution queue to get to our request; We can just query -the chunk status and get a response now, vs having to wait - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 9e44b60843a6463951382cb66c93f1fab24e5e5d..5a5f920954effbe549cacdaa39474989dc98ad75 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -414,13 +414,13 @@ public class CraftWorld implements World { - - @Override - public boolean isChunkLoaded(int x, int z) { -- return world.getChunkProvider().isChunkLoaded(x, z); -+ return world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z) != null; // Paper - } - - @Override - public boolean isChunkGenerated(int x, int z) { - try { -- return isChunkLoaded(x, z) || world.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)) != null; -+ return world.getChunkProvider().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)) != null; // Paper (TODO check if the first part can be removed) - } catch (IOException ex) { - throw new RuntimeException(ex); - } diff --git a/Unmapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/Unmapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch deleted file mode 100644 index aedba49bc7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ /dev/null @@ -1,261 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 13 Sep 2014 23:14:43 -0400 -Subject: [PATCH] Configurable Keep Spawn Loaded range per world - -This lets you disable it for some worlds and lower it for others. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 38d25a12c6a52d8a83214e2a0f43a218cf15ceac..ffe9b1a63d78925e1d77b9e730aef42fed6d58fa 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -440,4 +440,10 @@ public class PaperWorldConfig { - break; - } - } -+ -+ public short keepLoadedRange; -+ private void keepLoadedRange() { -+ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); -+ log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 5a5e097b131500d7cb9f61ea0f96f9006fabb941..aa2f4958fff659ef6b166b4644c81b5f1d8200a8 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -718,35 +718,36 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant> 4).forEach(pair -> { -+ getChunkProvider().getChunkAtMainThread(pair.x, pair.z); -+ }); -+ } -+ public void removeTicketsForSpawn(int radiusInBlocks, BlockPosition spawn) { -+ // In order to respect vanilla behavior, which is ensuring everything but the spawn border can tick, we added tickets -+ // with level 31 for the non-border spawn chunks -+ ChunkProviderServer chunkproviderserver = this.getChunkProvider(); -+ int tickRadius = radiusInBlocks - 16; -+ -+ // remove ticking chunks -+ for (int x = -tickRadius; x <= tickRadius; x += 16) { -+ for (int z = -tickRadius; z <= tickRadius; z += 16) { -+ // radius of 2 will have the current chunk be level 31 -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, z)), 2, Unit.INSTANCE); -+ } -+ } -+ -+ // remove border chunks -+ -+ // remove border along x axis (including corner chunks) -+ for (int x = -radiusInBlocks; x <= radiusInBlocks; x += 16) { -+ // top -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32 -+ // bottom -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, -radiusInBlocks)), 1, Unit.INSTANCE); // level 32 -+ } -+ -+ // remove border along z axis (excluding corner chunks) -+ for (int z = -radiusInBlocks + 16; z < radiusInBlocks; z += 16) { -+ // right -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 -+ // left -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 -+ } -+ } -+ // Paper end -+ - public void a(BlockPosition blockposition, float f) { -- ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); -+ // Paper - configurable spawn radius -+ BlockPosition prevSpawn = this.getSpawn(); -+ //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); - - this.worldData.setSpawn(blockposition, f); -- this.getChunkProvider().removeTicket(TicketType.START, chunkcoordintpair, 11, Unit.INSTANCE); -- this.getChunkProvider().addTicket(TicketType.START, new ChunkCoordIntPair(blockposition), 11, Unit.INSTANCE); -+ if (this.keepSpawnInMemory) { -+ // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add -+ this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); -+ this.addTicketsForSpawn(this.paperConfig.keepLoadedRange, blockposition); -+ } - this.getMinecraftServer().getPlayerList().sendAll(new PacketPlayOutSpawnPosition(blockposition, f)); - } - -diff --git a/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java b/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java -index de011b5e3a5e751160b4d3b65b50f28e6c6a5f52..4d9c167a41366779dbfb5ded6ea0115ffbf06ed7 100644 ---- a/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java -+++ b/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java -@@ -11,4 +11,6 @@ public interface WorldLoadListener { - void a(ChunkCoordIntPair chunkcoordintpair, @Nullable ChunkStatus chunkstatus); - - void b(); -+ -+ void setChunkRadius(int radius); // Paper - allow changing chunk radius - } -diff --git a/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java b/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java -index 872d00de41533ab7f4b43874de6c1747022e2ac5..ca81664d884e80e5cb1eb376a2c2ef1e017f16c0 100644 ---- a/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java -+++ b/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java -@@ -12,16 +12,24 @@ import org.apache.logging.log4j.Logger; - public class WorldLoadListenerLogger implements WorldLoadListener { - - private static final Logger LOGGER = LogManager.getLogger(); -- private final int b; -+ private int b; // Paper - remove final - private int c; - private long d; - private long e = Long.MAX_VALUE; - - public WorldLoadListenerLogger(int i) { -- int j = i * 2 + 1; -+ // Paper start - Allow changing radius later for configurable spawn patch -+ this.setChunkRadius(i); // Move to method -+ } -+ -+ @Override -+ public void setChunkRadius(int radius) { -+ // Paper - copied from above -+ int j = radius * 2 + 1; - - this.b = j * j; - } -+ // Paper end - - @Override - public void a(ChunkCoordIntPair chunkcoordintpair) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 5a5f920954effbe549cacdaa39474989dc98ad75..ec9f9fdf1be4f1e68eea5554a6721efd11a53958 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1972,15 +1972,21 @@ public class CraftWorld implements World { - - @Override - public void setKeepSpawnInMemory(boolean keepLoaded) { -+ // Paper start - Configurable spawn radius -+ if (keepLoaded == world.keepSpawnInMemory) { -+ // do nothing, nothing has changed -+ return; -+ } - world.keepSpawnInMemory = keepLoaded; - // Grab the worlds spawn chunk -- BlockPosition chunkcoordinates = this.world.getSpawn(); -+ BlockPosition prevSpawn = this.world.getSpawn(); - if (keepLoaded) { -- world.getChunkProvider().addTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE); -+ world.addTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); - } else { -- // TODO: doesn't work well if spawn changed.... -- world.getChunkProvider().removeTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE); -+ // TODO: doesn't work well if spawn changed.... // paper - resolved -+ world.removeTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); - } -+ // Paper end - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch b/Unmapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch deleted file mode 100644 index be4c0838f1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Mon, 27 May 2019 17:35:39 -0500 -Subject: [PATCH] MC-114618 - Fix EntityAreaEffectCloud from going negative - size - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java -index 47099ecd70e5077cad8372446d54e28398785bec..679dfe75ea68e38679cd7d6348d0e24ca61911e4 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java -+++ b/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java -@@ -196,6 +196,12 @@ public class EntityAreaEffectCloud extends Entity { - super.tick(); - boolean flag = this.k(); - float f = this.getRadius(); -+ // Paper start - fix MC-114618 -+ if (f < 0.0F) { -+ this.die(); -+ return; -+ } -+ // Paper end - - if (this.world.isClientSide) { - ParticleParam particleparam = this.getParticle(); diff --git a/Unmapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch b/Unmapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch deleted file mode 100644 index 148847522f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Wed, 29 May 2019 04:01:22 +0100 -Subject: [PATCH] ChunkMapDistance CME - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 6ef404ee29ddc79aeca534a58ec182e0e8b1b6c8..961257ebc28a8b4753faf3c2d5b6abaea4ffc0dd 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -39,7 +39,16 @@ public abstract class ChunkMapDistance { - private final ChunkMapDistance.a ticketLevelTracker = new ChunkMapDistance.a(); - private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); - private final ChunkMapDistance.c g = new ChunkMapDistance.c(33); -- private final Set pendingChunkUpdates = Sets.newHashSet(); -+ // Paper start use a queue, but still keep unique requirement -+ public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { -+ @Override -+ public boolean add(PlayerChunk o) { -+ if (o.isUpdateQueued) return true; -+ o.isUpdateQueued = true; -+ return super.add(o); -+ } -+ }; -+ // Paper end - private final ChunkTaskQueueSorter i; - private final Mailbox> j; - private final Mailbox k; -@@ -100,26 +109,14 @@ public abstract class ChunkMapDistance { - ; - } - -+ // Paper start - if (!this.pendingChunkUpdates.isEmpty()) { -- // CraftBukkit start -- // Iterate pending chunk updates with protection against concurrent modification exceptions -- java.util.Iterator iter = this.pendingChunkUpdates.iterator(); -- int expectedSize = this.pendingChunkUpdates.size(); -- do { -- PlayerChunk playerchunk = iter.next(); -- iter.remove(); -- expectedSize--; -- -- playerchunk.a(playerchunkmap); -- -- // Reset iterator if set was modified using add() -- if (this.pendingChunkUpdates.size() != expectedSize) { -- expectedSize = this.pendingChunkUpdates.size(); -- iter = this.pendingChunkUpdates.iterator(); -- } -- } while (iter.hasNext()); -- // CraftBukkit end -- -+ while(!this.pendingChunkUpdates.isEmpty()) { -+ PlayerChunk remove = this.pendingChunkUpdates.remove(); -+ remove.isUpdateQueued = false; -+ remove.a(playerchunkmap); -+ } -+ // Paper end - return true; - } else { - if (!this.l.isEmpty()) { -@@ -373,7 +370,7 @@ public abstract class ChunkMapDistance { - ObjectIterator objectiterator = this.a.long2ByteEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); -+ Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix - byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); - long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 7dea5e783ce2a1f8ddd2b3ab7a19e03a56c36ba1..2c3d9a5d118cc4f3b5e78daf943911bb7386488a 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -45,6 +45,7 @@ public class PlayerChunk { - private static final CompletableFuture> UNLOADED_CHUNK_FUTURE = CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK); - private static final List CHUNK_STATUSES = ChunkStatus.a(); - private static final PlayerChunk.State[] CHUNK_STATES = PlayerChunk.State.values(); -+ boolean isUpdateQueued = false; // Paper - private final AtomicReferenceArray>> statusFutures; - private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage - private volatile CompletableFuture> tickingFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage diff --git a/Unmapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch b/Unmapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch deleted file mode 100644 index 722e63e63a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: simpleauthority -Date: Tue, 28 May 2019 03:48:51 -0700 -Subject: [PATCH] Implement CraftBlockSoundGroup - - -diff --git a/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java -new file mode 100644 -index 0000000000000000000000000000000000000000..34b3b858f616c4a1f877e6e58d315de2d8ff0720 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java -@@ -0,0 +1,38 @@ -+package com.destroystokyo.paper.block; -+ -+import net.minecraft.world.level.block.SoundEffectType; -+import org.bukkit.Sound; -+import org.bukkit.craftbukkit.CraftSound; -+ -+public class CraftBlockSoundGroup implements BlockSoundGroup { -+ private final SoundEffectType soundEffectType; -+ -+ public CraftBlockSoundGroup(SoundEffectType soundEffectType) { -+ this.soundEffectType = soundEffectType; -+ } -+ -+ @Override -+ public Sound getBreakSound() { -+ return CraftSound.getBukkit(soundEffectType.getBreakSound()); -+ } -+ -+ @Override -+ public Sound getStepSound() { -+ return CraftSound.getBukkit(soundEffectType.getStepSound()); -+ } -+ -+ @Override -+ public Sound getPlaceSound() { -+ return CraftSound.getBukkit(soundEffectType.getPlaceSound()); -+ } -+ -+ @Override -+ public Sound getHitSound() { -+ return CraftSound.getBukkit(soundEffectType.getHitSound()); -+ } -+ -+ @Override -+ public Sound getFallSound() { -+ return CraftSound.getBukkit(soundEffectType.getFallSound()); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/level/block/SoundEffectType.java b/src/main/java/net/minecraft/world/level/block/SoundEffectType.java -index 0987b25ac586d5d7b7954256c740fdf736498dae..b2a52c6bad5a83f34188b8f3db18c61ff9f52869 100644 ---- a/src/main/java/net/minecraft/world/level/block/SoundEffectType.java -+++ b/src/main/java/net/minecraft/world/level/block/SoundEffectType.java -@@ -54,10 +54,10 @@ public class SoundEffectType { - public static final SoundEffectType U = new SoundEffectType(1.0F, 1.0F, SoundEffects.BLOCK_GILDED_BLACKSTONE_BREAK, SoundEffects.BLOCK_GILDED_BLACKSTONE_STEP, SoundEffects.BLOCK_GILDED_BLACKSTONE_PLACE, SoundEffects.BLOCK_GILDED_BLACKSTONE_HIT, SoundEffects.BLOCK_GILDED_BLACKSTONE_FALL); - public final float volume; - public final float pitch; -- public final SoundEffect breakSound; -+ public final SoundEffect breakSound; public final SoundEffect getBreakSound() { return this.breakSound; } // Paper - OBFHELPER // PAIL private -> public, rename breakSound - private final SoundEffect stepSound; - private final SoundEffect placeSound; -- public final SoundEffect hitSound; -+ public final SoundEffect hitSound; public final SoundEffect getHitSound() { return this.hitSound; } // Paper - OBFHELPER // PAIL private -> public, rename hitSound - private final SoundEffect fallSound; - - public SoundEffectType(float f, float f1, SoundEffect soundeffect, SoundEffect soundeffect1, SoundEffect soundeffect2, SoundEffect soundeffect3, SoundEffect soundeffect4) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 8a6d8f21937ce7e2ac4623a3083421ed5ef9aa63..724b230259b1b44bc9fdde6c4fcbcdde5f690e05 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -750,4 +750,11 @@ public class CraftBlock implements Block { - AxisAlignedBB aabb = shape.getBoundingBox(); - return new BoundingBox(getX() + aabb.minX, getY() + aabb.minY, getZ() + aabb.minZ, getX() + aabb.maxX, getY() + aabb.maxY, getZ() + aabb.maxZ); - } -+ -+ // Paper start -+ @Override -+ public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { -+ return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().getBlockData().getStepSound()); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch b/Unmapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch deleted file mode 100644 index bb3f023d4a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0356-Chunk-debug-command.patch +++ /dev/null @@ -1,486 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 1 Jun 2019 13:00:55 -0700 -Subject: [PATCH] Chunk debug command - -Prints all chunk information to a text file into the debug -folder in the root server folder. The format is in JSON, and -the data format is described in MCUtil#dumpChunks(File) - -The command will output server version and all online players to the -file as well. We do not log anything but the location, world and -username of the player. - -Also logs the value of these config values (note not all are paper's): -- keep spawn loaded value -- spawn radius -- view distance - -Each chunk has the following logged: -- Coordinate -- Ticket level & its corresponding state -- Whether it is queued for unload -- Chunk status (may be unloaded) -- All tickets on the chunk - -Example log: -https://gist.githubusercontent.com/Spottedleaf/0131e7710ffd5d531e5fd246c3367380/raw/169ae1b2e240485f99bc7a6bd8e78d90e3af7397/chunks-2019-06-01_19.57.05.txt - -For references on certain keywords (ticket, status, etc), please see: - -https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528273&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528273 -https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528577&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528577 - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index b67bd98cca4a06bc0ebaed577195dffc3b3251ec..a7a02072e5c7ce62cbecbb638fcc74abf2fb57ee 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -9,10 +9,12 @@ import com.google.common.collect.Maps; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.server.MCUtil; - import org.apache.commons.lang3.tuple.MutablePair; - import org.apache.commons.lang3.tuple.Pair; - import org.bukkit.Bukkit; -@@ -41,7 +43,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); - - public PaperCommand(String name) { - super(name); -@@ -69,6 +71,21 @@ public class PaperCommand extends Command { - if (args.length == 3) - return getListMatchingLast(sender, args, EntityTypes.getEntityNameList().stream().map(MinecraftKey::toString).sorted().toArray(String[]::new)); - break; -+ case "debug": -+ if (args.length == 2) { -+ return getListMatchingLast(sender, args, "help", "chunks"); -+ } -+ break; -+ case "chunkinfo": -+ List worldNames = new ArrayList<>(); -+ worldNames.add("*"); -+ for (org.bukkit.World world : Bukkit.getWorlds()) { -+ worldNames.add(world.getName()); -+ } -+ if (args.length == 2) { -+ return getListMatchingLast(sender, args, worldNames); -+ } -+ break; - } - return Collections.emptyList(); - } -@@ -135,6 +152,12 @@ public class PaperCommand extends Command { - case "reload": - doReload(sender); - break; -+ case "debug": -+ doDebug(sender, args); -+ break; -+ case "chunkinfo": -+ doChunkInfo(sender, args); -+ break; - case "ver": - if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) - case "version": -@@ -152,6 +175,114 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doChunkInfo(CommandSender sender, String[] args) { -+ List worlds; -+ if (args.length < 2 || args[1].equals("*")) { -+ worlds = Bukkit.getWorlds(); -+ } else { -+ worlds = new ArrayList<>(args.length - 1); -+ for (int i = 1; i < args.length; ++i) { -+ org.bukkit.World world = Bukkit.getWorld(args[i]); -+ if (world == null) { -+ sender.sendMessage(ChatColor.RED + "World '" + args[i] + "' is invalid"); -+ return; -+ } -+ worlds.add(world); -+ } -+ } -+ -+ int accumulatedTotal = 0; -+ int accumulatedInactive = 0; -+ int accumulatedBorder = 0; -+ int accumulatedTicking = 0; -+ int accumulatedEntityTicking = 0; -+ -+ for (org.bukkit.World bukkitWorld : worlds) { -+ WorldServer world = ((CraftWorld)bukkitWorld).getHandle(); -+ -+ int total = 0; -+ int inactive = 0; -+ int border = 0; -+ int ticking = 0; -+ int entityTicking = 0; -+ -+ for (PlayerChunk chunk : world.getChunkProvider().playerChunkMap.updatingChunks.values()) { -+ if (chunk.getFullChunkIfCached() == null) { -+ continue; -+ } -+ -+ ++total; -+ -+ PlayerChunk.State state = PlayerChunk.getChunkState(chunk.getTicketLevel()); -+ -+ switch (state) { -+ case INACCESSIBLE: -+ ++inactive; -+ continue; -+ case BORDER: -+ ++border; -+ continue; -+ case TICKING: -+ ++ticking; -+ continue; -+ case ENTITY_TICKING: -+ ++entityTicking; -+ continue; -+ } -+ } -+ -+ accumulatedTotal += total; -+ accumulatedInactive += inactive; -+ accumulatedBorder += border; -+ accumulatedTicking += ticking; -+ accumulatedEntityTicking += entityTicking; -+ -+ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + bukkitWorld.getName() + ChatColor.DARK_AQUA + ":"); -+ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + total + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA -+ + inactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + border + ChatColor.BLUE + " Ticking: " -+ + ChatColor.DARK_AQUA + ticking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + entityTicking); -+ } -+ if (worlds.size() > 1) { -+ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + "all listed worlds" + ChatColor.DARK_AQUA + ":"); -+ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + accumulatedTotal + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA -+ + accumulatedInactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + accumulatedBorder + ChatColor.BLUE + " Ticking: " -+ + ChatColor.DARK_AQUA + accumulatedTicking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + accumulatedEntityTicking); -+ } -+ } -+ -+ private void doDebug(CommandSender sender, String[] args) { -+ if (args.length < 2) { -+ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); -+ return; -+ } -+ -+ String debugType = args[1].toLowerCase(Locale.ENGLISH); -+ switch (debugType) { -+ case "chunks": -+ if (args.length >= 3 && args[2].toLowerCase(Locale.ENGLISH).equals("help")) { -+ sender.sendMessage(ChatColor.RED + "Use /paper debug chunks to dump loaded chunk information to a file"); -+ break; -+ } -+ File file = new File(new File(new File("."), "debug"), -+ "chunks-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); -+ sender.sendMessage(ChatColor.GREEN + "Writing chunk information dump to " + file.toString()); -+ try { -+ MCUtil.dumpChunks(file); -+ sender.sendMessage(ChatColor.GREEN + "Successfully written chunk information!"); -+ } catch (Throwable thr) { -+ MinecraftServer.LOGGER.warn("Failed to dump chunk information to file " + file.toString(), thr); -+ sender.sendMessage(ChatColor.RED + "Failed to dump chunk information, see console"); -+ } -+ -+ break; -+ case "help": -+ // fall through to default -+ default: -+ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); -+ return; -+ } -+ } -+ - /* - * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 - */ -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 35d1444c5b75d9a3a6cface5dd70aea0a08ac89d..fbd33aef21b4539d249c367609a36491530fb7ca 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -9,13 +9,27 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.level.ChunkMapDistance; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.Ticket; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.RayTrace; - import net.minecraft.world.level.World; -+import net.minecraft.world.level.chunk.ChunkStatus; -+import net.minecraft.world.level.chunk.IChunkAccess; - import org.apache.commons.lang.exception.ExceptionUtils; -+import com.google.gson.JsonArray; -+import com.google.gson.JsonObject; -+import com.google.gson.internal.Streams; -+import com.google.gson.stream.JsonWriter; - import com.mojang.authlib.GameProfile; -+import com.mojang.datafixers.util.Either; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; - import org.bukkit.Location; - import org.bukkit.block.BlockFace; - import org.bukkit.craftbukkit.CraftWorld; -@@ -24,8 +38,11 @@ import org.spigotmc.AsyncCatcher; - - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -+import java.io.*; -+import java.util.ArrayList; - import java.util.List; - import java.util.Queue; -+import java.util.Set; - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.ExecutionException; - import java.util.concurrent.LinkedBlockingQueue; -@@ -531,4 +548,170 @@ public final class MCUtil { - - return null; - } -+ -+ public static ChunkStatus getChunkStatus(PlayerChunk chunk) { -+ List statuses = ChunkProviderServer.getPossibleChunkStatuses(); -+ for (int i = statuses.size() - 1; i >= 0; --i) { -+ ChunkStatus curr = statuses.get(i); -+ CompletableFuture> future = chunk.getStatusFutureUnchecked(curr); -+ if (future != PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE) { -+ return curr; -+ } -+ } -+ return null; // unloaded -+ } -+ -+ public static void dumpChunks(File file) throws IOException { -+ file.getParentFile().mkdirs(); -+ file.createNewFile(); -+ /* -+ * Json format: -+ * -+ * Main data format: -+ * -server-version: -+ * -data-version: -+ * -worlds: -+ * -name: -+ * -view-distance: -+ * -keep-spawn-loaded: -+ * -keep-spawn-loaded-range: -+ * -visible-chunk-count: -+ * -loaded-chunk-count: -+ * -verified-fully-loaded-chunks: -+ * -players: -+ * -chunk-data: -+ * -+ * Player format: -+ * -name: -+ * -x: -+ * -y: -+ * -z: -+ * -+ * Chunk Format: -+ * -x: -+ * -z: -+ * -ticket-level: -+ * -state: -+ * -queued-for-unload: -+ * -status: -+ * -tickets: -+ * -+ * -+ * Ticket format: -+ * -ticket-type: -+ * -ticket-level: -+ * -add-tick: -+ * -object-reason: // This depends on the type of ticket. ie POST_TELEPORT -> entity id -+ */ -+ List worlds = org.bukkit.Bukkit.getWorlds(); -+ JsonObject data = new JsonObject(); -+ -+ data.addProperty("server-version", org.bukkit.Bukkit.getVersion()); -+ data.addProperty("data-version", 0); -+ -+ JsonArray worldsData = new JsonArray(); -+ -+ for (org.bukkit.World bukkitWorld : worlds) { -+ JsonObject worldData = new JsonObject(); -+ -+ WorldServer world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); -+ PlayerChunkMap chunkMap = world.getChunkProvider().playerChunkMap; -+ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunks; -+ ChunkMapDistance chunkMapDistance = chunkMap.chunkDistanceManager; -+ List allChunks = new ArrayList<>(visibleChunks.values()); -+ List players = world.players; -+ -+ int fullLoadedChunks = 0; -+ -+ for (PlayerChunk chunk : allChunks) { -+ if (chunk.getFullChunkIfCached() != null) { -+ ++fullLoadedChunks; -+ } -+ } -+ -+ // sorting by coordinate makes the log easier to read -+ allChunks.sort((PlayerChunk v1, PlayerChunk v2) -> { -+ if (v1.location.x != v2.location.x) { -+ return Integer.compare(v1.location.x, v2.location.x); -+ } -+ return Integer.compare(v1.location.z, v2.location.z); -+ }); -+ -+ worldData.addProperty("name", world.getWorld().getName()); -+ worldData.addProperty("view-distance", world.spigotConfig.viewDistance); -+ worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); -+ worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); -+ worldData.addProperty("visible-chunk-count", visibleChunks.size()); -+ worldData.addProperty("loaded-chunk-count", chunkMap.loadedChunks.size()); -+ worldData.addProperty("verified-fully-loaded-chunks", fullLoadedChunks); -+ -+ JsonArray playersData = new JsonArray(); -+ -+ for (EntityPlayer player : players) { -+ JsonObject playerData = new JsonObject(); -+ -+ playerData.addProperty("name", player.getName()); -+ playerData.addProperty("x", player.locX()); -+ playerData.addProperty("y", player.locY()); -+ playerData.addProperty("z", player.locZ()); -+ -+ playersData.add(playerData); -+ -+ } -+ -+ worldData.add("players", playersData); -+ -+ JsonArray chunksData = new JsonArray(); -+ -+ for (PlayerChunk playerChunk : allChunks) { -+ JsonObject chunkData = new JsonObject(); -+ -+ Set> tickets = chunkMapDistance.tickets.get(playerChunk.location.pair()); -+ ChunkStatus status = getChunkStatus(playerChunk); -+ -+ chunkData.addProperty("x", playerChunk.location.x); -+ chunkData.addProperty("z", playerChunk.location.z); -+ chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); -+ chunkData.addProperty("state", PlayerChunk.getChunkState(playerChunk.getTicketLevel()).toString()); -+ chunkData.addProperty("queued-for-unload", chunkMap.unloadQueue.contains(playerChunk.location.pair())); -+ chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); -+ -+ JsonArray ticketsData = new JsonArray(); -+ -+ if (tickets != null) { -+ for (Ticket ticket : tickets) { -+ JsonObject ticketData = new JsonObject(); -+ -+ ticketData.addProperty("ticket-type", ticket.getTicketType().toString()); -+ ticketData.addProperty("ticket-level", ticket.getTicketLevel()); -+ ticketData.addProperty("object-reason", String.valueOf(ticket.getObjectReason())); -+ ticketData.addProperty("add-tick", ticket.getCreationTick()); -+ -+ ticketsData.add(ticketData); -+ } -+ } -+ -+ chunkData.add("tickets", ticketsData); -+ chunksData.add(chunkData); -+ } -+ -+ -+ worldData.add("chunk-data", chunksData); -+ worldsData.add(worldData); -+ } -+ -+ data.add("worlds", worldsData); -+ -+ StringWriter stringWriter = new StringWriter(); -+ JsonWriter jsonWriter = new JsonWriter(stringWriter); -+ jsonWriter.setIndent(" "); -+ jsonWriter.setLenient(false); -+ Streams.write(data, jsonWriter); -+ -+ String fileData = stringWriter.toString(); -+ -+ try (PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) { -+ out.print(fileData); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 677c185aca2cdd64bead9dbed147a87c5bcf1678..3425ae4d036bbfa413e60eccfd6d82b8dae3775b 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -46,7 +46,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper - - public class ChunkProviderServer extends IChunkProvider { - -- private static final List b = ChunkStatus.a(); -+ private static final List b = ChunkStatus.a(); public static final List getPossibleChunkStatuses() { return ChunkProviderServer.b; } // Paper - OBFHELPER - private final ChunkMapDistance chunkMapDistance; - public final ChunkGenerator chunkGenerator; - private final WorldServer world; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 2c3d9a5d118cc4f3b5e78daf943911bb7386488a..9891cf98f8c740f84f9135ee8176e67abb648b3a 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -54,7 +54,7 @@ public class PlayerChunk { - public int oldTicketLevel; - private int ticketLevel; - private int n; -- private final ChunkCoordIntPair location; -+ final ChunkCoordIntPair location; // Paper - private -> package - private boolean p; - private final ShortSet[] dirtyBlocks; - private int r; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index b736917891afb17e412f94c5d8713aa653b8dc46..e10c661755796e9c4e40f62a649b45dd1a71b46c 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -106,7 +106,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final Long2ObjectLinkedOpenHashMap updatingChunks = new Long2ObjectLinkedOpenHashMap(); - public volatile Long2ObjectLinkedOpenHashMap visibleChunks; - private final Long2ObjectLinkedOpenHashMap pendingUnload; -- private final LongSet loadedChunks; -+ public final LongSet loadedChunks; // Paper - private -> public - public final WorldServer world; - private final LightEngineThreaded lightEngine; - private final IAsyncTaskHandler executor; -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 51ef4adf66c1e21093e63ab46fa47e66c2425fdb..e06fe77f6ea05a93e95fce223bcfd0d16394f96f 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -6,8 +6,8 @@ public final class Ticket implements Comparable> { - - private final TicketType a; - private final int b; -- public final T identifier; -- private long d; -+ public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER -+ private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER - - protected Ticket(TicketType tickettype, int i, T t0) { - this.a = tickettype; -@@ -51,6 +51,7 @@ public final class Ticket implements Comparable> { - return this.a; - } - -+ public final int getTicketLevel() { return this.b(); } // Paper - OBFHELPER - public int b() { - return this.b; - } diff --git a/Unmapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch b/Unmapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch deleted file mode 100644 index 44ad23e85f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 10 Jun 2019 09:36:40 +0100 -Subject: [PATCH] Catch exceptions from dispenser entity spawns - - -diff --git a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -index a7d690cb2289a79ee2b8fc665caef58a10ddab3e..50911632341d1b861c00f01077cae43884147fe0 100644 ---- a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -+++ b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -@@ -8,6 +8,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.core.IPosition; - import net.minecraft.core.ISourceBlock; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -237,7 +238,14 @@ public interface IDispenseBehavior { - } - } - -+ try { // Paper - entitytypes.spawnCreature(isourceblock.getWorld(), itemstack, (EntityHuman) null, isourceblock.getBlockPosition().shift(enumdirection), EnumMobSpawn.DISPENSER, enumdirection != EnumDirection.UP, false); -+ // Paper start -+ } catch (Exception ex){ -+ MinecraftServer.LOGGER.warn("An exception occurred dispensing entity at {}[{}]", worldserver.getWorld().getName(), isourceblock.getBlockPosition(), ex); -+ } -+ // Paper end -+ - // itemstack.subtract(1); // Handled during event processing - // CraftBukkit end - return itemstack; diff --git a/Unmapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch b/Unmapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch deleted file mode 100644 index 2da0e88e20..0000000000 --- a/Unmapped-Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch +++ /dev/null @@ -1,390 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 15 Jun 2019 08:54:33 -0700 -Subject: [PATCH] Fix World#isChunkGenerated calls - -Optimize World#loadChunk() too -This patch also adds a chunk status cache on region files (note that -its only purpose is to cache the status on DISK) - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 3425ae4d036bbfa413e60eccfd6d82b8dae3775b..34b68443ff300f8626e9f7a8335cff75580bebfc 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -52,7 +52,7 @@ public class ChunkProviderServer extends IChunkProvider { - private final WorldServer world; - public final Thread serverThread; // Paper - private -> public - private final LightEngineThreaded lightEngine; -- private final ChunkProviderServer.a serverThreadQueue; -+ public final ChunkProviderServer.a serverThreadQueue; // Paper private -> public - public final PlayerChunkMap playerChunkMap; - private final WorldPersistentData worldPersistentData; - private long lastTickTime; -@@ -317,6 +317,21 @@ public class ChunkProviderServer extends IChunkProvider { - - return ret; - } -+ -+ @Nullable -+ public IChunkAccess getChunkAtImmediately(int x, int z) { -+ long k = ChunkCoordIntPair.pair(x, z); -+ -+ // Note: Bypass cache to make this MT-Safe -+ -+ PlayerChunk playerChunk = this.getChunk(k); -+ if (playerChunk == null) { -+ return null; -+ } -+ -+ return playerChunk.getAvailableChunkNow(); -+ -+ } - // Paper end - - @Nullable -@@ -770,7 +785,7 @@ public class ChunkProviderServer extends IChunkProvider { - return this.p; - } - -- final class a extends IAsyncTaskHandler { -+ public final class a extends IAsyncTaskHandler { // Paper - package -> public - - private a(World world) { - super("Chunk source main thread executor for " + world.getDimensionKey().a()); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 9891cf98f8c740f84f9135ee8176e67abb648b3a..6bced8533df49d7bfdb32dfa0caad9d788ffc2c8 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -142,6 +142,19 @@ public class PlayerChunk { - Either either = (Either) statusFuture.getNow(null); - return either == null ? null : (Chunk) either.left().orElse(null); - } -+ -+ public IChunkAccess getAvailableChunkNow() { -+ // TODO can we just getStatusFuture(EMPTY)? -+ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) { -+ CompletableFuture> future = this.getStatusFutureUnchecked(curr); -+ Either either = future.getNow(null); -+ if (either == null || !either.left().isPresent()) { -+ continue; -+ } -+ return either.left().get(); -+ } -+ return null; -+ } - // Paper end - - public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index e10c661755796e9c4e40f62a649b45dd1a71b46c..ed454f8dff7b0d94d4bde914a6f26bb019e82296 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -993,12 +993,61 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - @Nullable -- private NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { -+ public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public - NBTTagCompound nbttagcompound = this.read(chunkcoordintpair); -+ // Paper start - Cache chunk status on disk -+ if (nbttagcompound == null) { -+ return null; -+ } -+ -+ nbttagcompound = this.getChunkData(this.world.getTypeKey(), this.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit -+ if (nbttagcompound == null) { -+ return null; -+ } -+ -+ this.updateChunkStatusOnDisk(chunkcoordintpair, nbttagcompound); -+ -+ return nbttagcompound; -+ // Paper end -+ } -+ -+ // Paper start - chunk status cache "api" -+ public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); -+ -+ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } -+ -+ public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); -+ -+ if (regionFile == null || !regionFile.chunkExists(chunkPos)) { -+ return null; -+ } -+ -+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ -+ if (status != null) { -+ return status; -+ } -+ -+ this.readChunkData(chunkPos); - -- return nbttagcompound == null ? null : this.getChunkData(this.world.getTypeKey(), this.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit -+ return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); - } - -+ public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ -+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); -+ } -+ -+ public IChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { -+ PlayerChunk chunkHolder = this.pendingUnload.get(ChunkCoordIntPair.pair(chunkX, chunkZ)); -+ return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow(); -+ } -+ // Paper end -+ - boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair) { - // Spigot start - return isOutsideOfRange(chunkcoordintpair, false); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -index 5e4c162654349f884becc10e8fbae4ded6889deb..711308cf84a816f09d116a7414f9cbee803c8713 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -@@ -193,6 +193,7 @@ public class ChunkStatus { - return this.s; - } - -+ public ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER - public ChunkStatus e() { - return this.u; - } -@@ -213,6 +214,17 @@ public class ChunkStatus { - return this.y; - } - -+ // Paper start -+ public static ChunkStatus getStatus(String name) { -+ try { -+ // We need this otherwise we return EMPTY for invalid names -+ MinecraftKey key = new MinecraftKey(name); -+ return IRegistry.CHUNK_STATUS.getOptional(key).orElse(null); -+ } catch (Exception ex) { -+ return null; // invalid name -+ } -+ } -+ // Paper end - public static ChunkStatus a(String s) { - return (ChunkStatus) IRegistry.CHUNK_STATUS.get(MinecraftKey.a(s)); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 69bc9dc18bab157851d8080a672504598e8572a8..98bc26c7ae01884eb53766e72fc7cbabbf065e6e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -462,6 +462,17 @@ public class ChunkRegionLoader { - } - // Paper end - -+ // Paper start -+ public static ChunkStatus getStatus(NBTTagCompound compound) { -+ if (compound == null) { -+ return null; -+ } -+ -+ // Note: Copied from below -+ return ChunkStatus.getStatus(compound.getCompound("Level").getString("Status")); -+ } -+ // Paper end -+ - public static ChunkStatus.Type a(@Nullable NBTTagCompound nbttagcompound) { - if (nbttagcompound != null) { - ChunkStatus chunkstatus = ChunkStatus.a(nbttagcompound.getCompound("Level").getString("Status")); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -index 247d14a3ca56734bbbf4dc0ec247d60a1f241e7a..d785f44cd503d4d91589f3fc4bc8dc805dff3d41 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -@@ -25,7 +25,7 @@ import net.minecraft.world.level.dimension.DimensionManager; - - public class IChunkLoader implements AutoCloseable { - -- private final IOWorker a; -+ private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER - protected final DataFixer b; - @Nullable - private PersistentStructureLegacy c; -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 00cef1c0bc19976a000389e57a1af5d93690c0e7..d50b9c9d030016f951e2ed7fb519250b7408c833 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -27,6 +27,7 @@ import net.minecraft.SystemUtils; - import net.minecraft.nbt.NBTCompressedStreamTools; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.chunk.ChunkStatus; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -44,6 +45,30 @@ public class RegionFile implements AutoCloseable { - protected final RegionFileBitSet freeSectors; - public final File file; // Paper - -+ // Paper start - Cache chunk status -+ private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; -+ -+ private boolean closed; -+ -+ // invoked on write/read -+ public void setStatus(int x, int z, ChunkStatus status) { -+ if (this.closed) { -+ // We've used an invalid region file. -+ throw new IllegalStateException("RegionFile is closed"); -+ } -+ this.statuses[getChunkLocation(x, z)] = status; -+ } -+ -+ public ChunkStatus getStatusIfCached(int x, int z) { -+ if (this.closed) { -+ // We've used an invalid region file. -+ throw new IllegalStateException("RegionFile is closed"); -+ } -+ final int location = getChunkLocation(x, z); -+ return this.statuses[location]; -+ } -+ // Paper end -+ - public RegionFile(File file, File file1, boolean flag) throws IOException { - this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag); - } -@@ -380,11 +405,13 @@ public class RegionFile implements AutoCloseable { - return this.getOffset(chunkcoordintpair) != 0; - } - -+ private static int getChunkLocation(int x, int z) { return (x & 31) + (z & 31) * 32; } // Paper - OBFHELPER - sort of, mirror of logic below - private static int g(ChunkCoordIntPair chunkcoordintpair) { - return chunkcoordintpair.j() + chunkcoordintpair.k() * 32; - } - - public void close() throws IOException { -+ this.closed = true; // Paper - try { - this.d(); - } finally { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index ab9f4d40fd1126a3d7ba5b16fdc6ab09de4a7fdb..55e7e983d2c760a8052d7b3ddbdc8447f619a60f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -28,7 +28,14 @@ public final class RegionFileCache implements AutoCloseable { - this.c = flag; - } - -- private RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit -+ -+ // Paper start -+ public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { -+ return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); -+ } -+ -+ // Paper end -+ public RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public - long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); - RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i); - -@@ -175,6 +182,7 @@ public final class RegionFileCache implements AutoCloseable { - - try { - NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream); -+ regionfile.setStatus(chunkcoordintpair.x, chunkcoordintpair.z, ChunkRegionLoader.getStatus(nbttagcompound)); // Paper - cache status on disk - regionfile.setOversized(chunkcoordintpair.x, chunkcoordintpair.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone - } catch (Throwable throwable1) { - throwable = throwable1; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index ec9f9fdf1be4f1e68eea5554a6721efd11a53958..d46c513512c25e55ccdb0be16524f19444c358c5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -19,6 +19,7 @@ import java.util.Objects; - import java.util.Random; - import java.util.Set; - import java.util.UUID; -+import java.util.concurrent.CompletableFuture; - import java.util.function.Predicate; - import java.util.stream.Collectors; - import net.minecraft.core.BlockPosition; -@@ -419,8 +420,22 @@ public class CraftWorld implements World { - - @Override - public boolean isChunkGenerated(int x, int z) { -+ // Paper start - Fix this method -+ if (!Bukkit.isPrimaryThread()) { -+ return CompletableFuture.supplyAsync(() -> { -+ return CraftWorld.this.isChunkGenerated(x, z); -+ }, world.getChunkProvider().serverThreadQueue).join(); -+ } -+ IChunkAccess chunk = world.getChunkProvider().getChunkAtImmediately(x, z); -+ if (chunk == null) { -+ chunk = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); -+ } -+ if (chunk != null) { -+ return chunk instanceof ProtoChunkExtension || chunk instanceof net.minecraft.world.level.chunk.Chunk; -+ } - try { -- return world.getChunkProvider().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)) != null; // Paper (TODO check if the first part can be removed) -+ return world.getChunkProvider().playerChunkMap.getChunkStatusOnDisk(new ChunkCoordIntPair(x, z)) == ChunkStatus.FULL; -+ // Paper end - } catch (IOException ex) { - throw new RuntimeException(ex); - } -@@ -531,20 +546,48 @@ public class CraftWorld implements World { - @Override - public boolean loadChunk(int x, int z, boolean generate) { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -- IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper -+ // Paper start - Optimize this method -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); - -- // If generate = false, but the chunk already exists, we will get this back. -- if (chunk instanceof ProtoChunkExtension) { -- // We then cycle through again to get the full chunk immediately, rather than after the ticket addition -- chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); -- } -+ if (!generate) { -+ IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); -+ if (immediate == null) { -+ immediate = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); -+ } -+ if (immediate != null) { -+ if (!(immediate instanceof ProtoChunkExtension) && !(immediate instanceof net.minecraft.world.level.chunk.Chunk)) { -+ return false; // not full status -+ } -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkAt(x, z); // make sure we're at ticket level 32 or lower -+ return true; -+ } - -- if (chunk instanceof net.minecraft.world.level.chunk.Chunk) { -- world.getChunkProvider().addTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE); -- return true; -+ net.minecraft.world.level.chunk.storage.RegionFile file; -+ try { -+ file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ ChunkStatus status = file.getStatusIfCached(x, z); -+ if (!file.chunkExists(chunkPos) || (status != null && status != ChunkStatus.FULL)) { -+ return false; -+ } -+ -+ IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.EMPTY, true); -+ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.world.level.chunk.Chunk)) { -+ return false; -+ } -+ -+ // fall through to load -+ // we do this so we do not re-read the chunk data on disk - } - -- return false; -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); -+ return true; -+ // Paper end - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch b/Unmapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch deleted file mode 100644 index 8c64eb071a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 15 Jun 2019 10:28:25 -0700 -Subject: [PATCH] Show blockstate location if we failed to read it - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 2f0b48869077c27d0cacea81a99c9e34ff59c684..a4bd0d352c2babdbb31cdf49d63e2db3af4de146 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -19,6 +19,8 @@ public class CraftBlockEntityState extends CraftBlockState - public CraftBlockEntityState(Block block, Class tileEntityClass) { - super(block); - -+ try {// Paper - show location on failure -+ - this.tileEntityClass = tileEntityClass; - - // get tile entity from block: -@@ -38,6 +40,14 @@ public class CraftBlockEntityState extends CraftBlockState - this.load(this.snapshot); - } - // Paper end -+ // Paper start - show location on failure -+ } catch (Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ throw new RuntimeException("Failed to read BlockState at: world: " + block.getWorld().getName() + " location: (" + block.getX() + ", " + block.getY() + ", " + block.getZ() + ")", thr); -+ } -+ // Paper end - } - - public final boolean snapshotDisabled; // Paper diff --git a/Unmapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch b/Unmapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch deleted file mode 100644 index 1dcdb2ef23..0000000000 --- a/Unmapped-Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 May 2020 20:29:02 -0400 -Subject: [PATCH] Synchronize DataPaletteBlock instead of ReentrantLock - -Mojang has flaws in their logic about chunks being concurrently -wrote to. So we constantly see crashes around multiple threads writing. - -Additionally, java has optimized synchronization so well that its -in many times faster than trying to manage read wrote locks for low -contention situations. - -And this is extremely a low contention situation. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index 8928157b01bb4f0dfe043732777b33708c23cda7..cc0c5995dc3840ce66ea849849f7c37555d3b5e6 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -32,7 +32,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - private int i; private int getBitsPerObject() { return this.i; } // Paper - OBFHELPER - private final ReentrantLock j = new ReentrantLock(); - -- public void a() { -+ public void a() { /* // Paper start - disable this - use proper synchronization - if (this.j.isLocked() && !this.j.isHeldByCurrentThread()) { - String s = (String) Thread.getAllStackTraces().keySet().stream().filter(Objects::nonNull).map((thread) -> { - return thread.getName() + ": \n\tat " + (String) Arrays.stream(thread.getStackTrace()).map(Object::toString).collect(Collectors.joining("\n\tat ")); -@@ -44,11 +44,11 @@ public class DataPaletteBlock implements DataPaletteExpandable { - throw new ReportedException(crashreport); - } else { - this.j.lock(); -- } -+ } */ // Paper end - } - - public void b() { -- this.j.unlock(); -+ //this.j.unlock(); // Paper - disable this - } - - public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0) { -@@ -84,7 +84,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - } - - @Override -- public int onResize(int i, T t0) { -+ public synchronized int onResize(int i, T t0) { // Paper - synchronize - this.a(); - DataBits databits = this.a; - DataPalette datapalette = this.h; -@@ -107,18 +107,18 @@ public class DataPaletteBlock implements DataPaletteExpandable { - } - - public T setBlock(int i, int j, int k, T t0) { -- this.a(); -- T t1 = this.a(b(i, j, k), t0); -+ //this.a(); // Paper - remove to reduce ops - synchronize handled below -+ return this.a(b(i, j, k), t0); // Paper - -- this.b(); -- return t1; -+ //this.b(); // Paper -+ //return t1; // PAper - } - - public T b(int i, int j, int k, T t0) { - return this.a(b(i, j, k), t0); - } - -- protected T a(int i, T t0) { -+ protected synchronized T a(int i, T t0) { // Paper - synchronize - writes - int j = this.h.a(t0); - int k = this.a.a(i, j); - T t1 = this.h.a(k); -@@ -143,7 +143,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - } - - public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER -- public void b(PacketDataSerializer packetdataserializer) { -+ public synchronized void b(PacketDataSerializer packetdataserializer) { // Paper - synchronize - this.a(); - packetdataserializer.writeByte(this.i); - this.h.b(packetdataserializer); -@@ -151,7 +151,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - this.b(); - } - -- public void a(NBTTagList nbttaglist, long[] along) { -+ public synchronized void a(NBTTagList nbttaglist, long[] along) { // Paper - synchronize - this.a(); - int i = Math.max(4, MathHelper.e(nbttaglist.size())); - -@@ -184,7 +184,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - this.b(); - } - -- public void a(NBTTagCompound nbttagcompound, String s, String s1) { -+ public synchronized void a(NBTTagCompound nbttagcompound, String s, String s1) { // Paper - synchronize - this.a(); - DataPaletteHash datapalettehash = new DataPaletteHash<>(this.d, this.i, this.c, this.e, this.f); - T t0 = this.g; diff --git a/Unmapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch b/Unmapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch deleted file mode 100644 index 87d8a2e957..0000000000 --- a/Unmapped-Spigot-Server-Patches/0361-incremental-chunk-saving.patch +++ /dev/null @@ -1,317 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 9 Jun 2019 03:53:22 +0100 -Subject: [PATCH] incremental chunk saving - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index ffe9b1a63d78925e1d77b9e730aef42fed6d58fa..1278d09f70c1e97607ef20d87a178dc252c7f723 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -446,4 +446,19 @@ public class PaperWorldConfig { - keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); - log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); - } -+ -+ public int autoSavePeriod = -1; -+ private void autoSavePeriod() { -+ autoSavePeriod = getInt("auto-save-interval", -1); -+ if (autoSavePeriod > 0) { -+ log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)"); -+ } else if (autoSavePeriod < 0) { -+ autoSavePeriod = net.minecraft.server.MinecraftServer.getServer().autosavePeriod; -+ } -+ } -+ -+ public int maxAutoSaveChunksPerTick = 24; -+ private void maxAutoSaveChunksPerTick() { -+ maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index aa2f4958fff659ef6b166b4644c81b5f1d8200a8..8b922136336d5dc8fc302cc0f4879c4968a1cc67 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -263,6 +263,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; -+ public boolean serverAutoSave = false; // Paper - public CommandDispatcher vanillaCommandDispatcher; - private boolean forceTicks; - // CraftBukkit end -@@ -1258,14 +1259,24 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit -- MinecraftServer.LOGGER.debug("Autosave started"); -+ //if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down -+ //MinecraftServer.LOGGER.debug("Autosave started"); // Paper -+ serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper - this.methodProfiler.enter("save"); -+ if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper - this.playerList.savePlayers(); -- this.saveChunks(true, false, false); -+ }// Paper -+ // Paper start -+ for (WorldServer world : getWorlds()) { -+ if (world.paperConfig.autoSavePeriod > 0) { -+ world.saveIncrementally(serverAutoSave); -+ } -+ } -+ // Paper end -+ - this.methodProfiler.exit(); -- MinecraftServer.LOGGER.debug("Autosave finished"); -- } -+ //MinecraftServer.LOGGER.debug("Autosave finished"); // Paper -+ //} // Paper - - this.methodProfiler.enter("snooper"); - if (((DedicatedServer) this).getDedicatedServerProperties().snooperEnabled && !this.snooper.d() && this.ticks > 100) { // Spigot -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 34b68443ff300f8626e9f7a8335cff75580bebfc..8c497da1a4bde904e234a8fa00bf04a12787c7ed 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -557,6 +557,15 @@ public class ChunkProviderServer extends IChunkProvider { - } // Paper - Timings - } - -+ // Paper start - duplicate save, but call incremental -+ public void saveIncrementally() { -+ this.tickDistanceManager(); -+ try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { // Paper - Timings -+ this.playerChunkMap.saveIncrementally(); -+ } // Paper - Timings -+ } -+ // Paper end -+ - @Override - public void close() throws IOException { - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 6bced8533df49d7bfdb32dfa0caad9d788ffc2c8..75d4a8fc394449ccc006fe67a8842edcd9f36854 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -67,6 +67,9 @@ public class PlayerChunk { - - private final PlayerChunkMap chunkMap; // Paper - -+ long lastAutoSaveTime; // Paper - incremental autosave -+ long inactiveTimeStart; // Paper - incremental autosave -+ - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -@@ -422,7 +425,19 @@ public class PlayerChunk { - boolean flag2 = playerchunk_state.isAtLeast(PlayerChunk.State.BORDER); - boolean flag3 = playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER); - -+ boolean prevHasBeenLoaded = this.hasBeenLoaded; // Paper - this.hasBeenLoaded |= flag3; -+ // Paper start - incremental autosave -+ if (this.hasBeenLoaded & !prevHasBeenLoaded) { -+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; -+ if (timeSinceAutoSave < 0) { -+ // safest bet is to assume autosave is needed here -+ timeSinceAutoSave = this.chunkMap.world.paperConfig.autoSavePeriod; -+ } -+ this.lastAutoSaveTime = this.chunkMap.world.getTime() - timeSinceAutoSave; -+ this.chunkMap.autoSaveQueue.add(this); -+ } -+ // Paper end - if (!flag2 && flag3) { - // Paper start - cache ticking ready status - int expectCreateCount = ++this.fullChunkCreateCount; -@@ -542,8 +557,32 @@ public class PlayerChunk { - } - - public void m() { -+ boolean prev = this.hasBeenLoaded; // Paper -+ this.hasBeenLoaded = getChunkState(this.ticketLevel).isAtLeast(PlayerChunk.State.BORDER); -+ // Paper start - incremental autosave -+ if (prev != this.hasBeenLoaded) { -+ if (this.hasBeenLoaded) { -+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; -+ if (timeSinceAutoSave < 0) { -+ // safest bet is to assume autosave is needed here -+ timeSinceAutoSave = this.chunkMap.world.paperConfig.autoSavePeriod; -+ } -+ this.lastAutoSaveTime = this.chunkMap.world.getTime() - timeSinceAutoSave; -+ this.chunkMap.autoSaveQueue.add(this); -+ } else { -+ this.inactiveTimeStart = this.chunkMap.world.getTime(); -+ this.chunkMap.autoSaveQueue.remove(this); -+ } -+ } -+ // Paper end -+ } -+ -+ // Paper start - incremental autosave -+ public boolean setHasBeenLoaded() { - this.hasBeenLoaded = getChunkState(this.ticketLevel).isAtLeast(PlayerChunk.State.BORDER); -+ return this.hasBeenLoaded; - } -+ // Paper end - - public void a(ProtoChunkExtension protochunkextension) { - for (int i = 0; i < this.statusFutures.length(); ++i) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index ed454f8dff7b0d94d4bde914a6f26bb019e82296..ca05fe4ed0773b94035c63f8f8db6c034f0b92e2 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -93,6 +93,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStruct - import net.minecraft.world.level.storage.Convertable; - import net.minecraft.world.level.storage.WorldPersistentData; - import net.minecraft.world.phys.Vec3D; -+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper - import org.apache.commons.lang3.mutable.MutableBoolean; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -380,6 +381,64 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ // Paper start - incremental autosave -+ final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((playerchunk1, playerchunk2) -> { -+ int timeCompare = Long.compare(playerchunk1.lastAutoSaveTime, playerchunk2.lastAutoSaveTime); -+ if (timeCompare != 0) { -+ return timeCompare; -+ } -+ -+ return Long.compare(MCUtil.getCoordinateKey(playerchunk1.location), MCUtil.getCoordinateKey(playerchunk2.location)); -+ }); -+ -+ protected void saveIncrementally() { -+ int savedThisTick = 0; -+ // optimized since we search far less chunks to hit ones that need to be saved -+ List reschedule = new java.util.ArrayList<>(this.world.paperConfig.maxAutoSaveChunksPerTick); -+ long currentTick = this.world.getTime(); -+ long maxSaveTime = currentTick - this.world.paperConfig.autoSavePeriod; -+ -+ for (Iterator iterator = this.autoSaveQueue.iterator(); iterator.hasNext();) { -+ PlayerChunk playerchunk = iterator.next(); -+ if (playerchunk.lastAutoSaveTime > maxSaveTime) { -+ break; -+ } -+ -+ iterator.remove(); -+ -+ IChunkAccess ichunkaccess = playerchunk.getChunkSave().getNow(null); -+ if (ichunkaccess instanceof Chunk) { -+ boolean shouldSave = ((Chunk)ichunkaccess).lastSaved <= maxSaveTime; -+ -+ if (shouldSave && this.saveChunk(ichunkaccess)) { -+ ++savedThisTick; -+ -+ if (!playerchunk.setHasBeenLoaded()) { -+ // do not fall through to reschedule logic -+ playerchunk.inactiveTimeStart = currentTick; -+ if (savedThisTick >= this.world.paperConfig.maxAutoSaveChunksPerTick) { -+ break; -+ } -+ continue; -+ } -+ } -+ } -+ -+ reschedule.add(playerchunk); -+ -+ if (savedThisTick >= this.world.paperConfig.maxAutoSaveChunksPerTick) { -+ break; -+ } -+ } -+ -+ for (int i = 0, len = reschedule.size(); i < len; ++i) { -+ PlayerChunk playerchunk = reschedule.get(i); -+ playerchunk.lastAutoSaveTime = this.world.getTime(); -+ this.autoSaveQueue.add(playerchunk); -+ } -+ } -+ // Paper end -+ - protected void save(boolean flag) { - if (flag) { - List list = (List) this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList()); -@@ -490,6 +549,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - this.world.unloadChunk(chunk); - } -+ this.autoSaveQueue.remove(playerchunk); // Paper - - this.lightEngine.a(ichunkaccess.getPos()); - this.lightEngine.queueUpdate(); -@@ -682,6 +742,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - playerchunk.a(new ProtoChunkExtension(chunk)); - } - -+ chunk.setLastSaved(this.world.getTime() - 1); // Paper - avoid autosaving newly generated/loaded chunks -+ - chunk.a(() -> { - return PlayerChunk.getChunkState(playerchunk.getTicketLevel()); - }); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index d308197995a92f5be8f5b928fa9ae83dd659545c..12e34e1514f060ffef96cdd3ac57d0495dd37321 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -888,6 +888,38 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return !this.server.a(this, blockposition, entityhuman) && this.getWorldBorder().a(blockposition); - } - -+ // Paper start - derived from below -+ public void saveIncrementally(boolean doFull) { -+ ChunkProviderServer chunkproviderserver = this.getChunkProvider(); -+ -+ if (doFull) { -+ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); -+ } -+ -+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { -+ if (doFull) { -+ this.saveData(); -+ } -+ -+ timings.worldSaveChunks.startTiming(); // Paper -+ if (!this.isSavingDisabled()) chunkproviderserver.saveIncrementally(); -+ timings.worldSaveChunks.stopTiming(); // Paper -+ -+ -+ // Copied from save() -+ // CraftBukkit start - moved from MinecraftServer.saveChunks -+ if (doFull) { // Paper -+ WorldServer worldserver1 = this; -+ -+ worldDataServer.a(worldserver1.getWorldBorder().t()); -+ worldDataServer.setCustomBossEvents(this.server.getBossBattleCustomData().save()); -+ convertable.a(this.server.customRegistry, this.worldDataServer, this.server.getPlayerList().save()); -+ } -+ // CraftBukkit end -+ } -+ } -+ // Paper end -+ - public void save(@Nullable IProgressUpdate iprogressupdate, boolean flag, boolean flag1) { - ChunkProviderServer chunkproviderserver = this.getChunkProvider(); - -@@ -918,6 +950,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit end - } - -+ private void saveData() { this.aj(); } // Paper - OBFHELPER - private void aj() { - if (this.dragonBattle != null) { - this.worldDataServer.a(this.dragonBattle.a()); // CraftBukkit -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 3f926ed8e2b2c9dbf1e2493870af7eff3b6db019..2690c44eaae193a259fe195c95e59d07d5e1cc5a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -81,7 +81,7 @@ public class Chunk implements IChunkAccess { - private TickList o; - private TickList p; - private boolean q; -- private long lastSaved; -+ public long lastSaved; // Paper - private volatile boolean s; - private long inhabitedTime; - @Nullable diff --git a/Unmapped-Spigot-Server-Patches/0362-Anti-Xray.patch b/Unmapped-Spigot-Server-Patches/0362-Anti-Xray.patch deleted file mode 100644 index ddd0aa5463..0000000000 --- a/Unmapped-Spigot-Server-Patches/0362-Anti-Xray.patch +++ /dev/null @@ -1,1567 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: stonar96 -Date: Mon, 20 Aug 2018 03:03:58 +0200 -Subject: [PATCH] Anti-Xray - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1278d09f70c1e97607ef20d87a178dc252c7f723..c45493e88bf7e8811be2759ff9ac19e3fe9d938a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -1,7 +1,9 @@ - package com.destroystokyo.paper; - -+import java.util.Arrays; - import java.util.List; - -+import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; - import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; -@@ -461,4 +463,38 @@ public class PaperWorldConfig { - private void maxAutoSaveChunksPerTick() { - maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); - } -+ -+ public boolean antiXray; -+ public EngineMode engineMode; -+ public int maxChunkSectionIndex; -+ public int updateRadius; -+ public boolean lavaObscures; -+ public boolean usePermission; -+ public List hiddenBlocks; -+ public List replacementBlocks; -+ private void antiXray() { -+ antiXray = getBoolean("anti-xray.enabled", false); -+ engineMode = EngineMode.getById(getInt("anti-xray.engine-mode", EngineMode.HIDE.getId())); -+ engineMode = engineMode == null ? EngineMode.HIDE : engineMode; -+ maxChunkSectionIndex = getInt("anti-xray.max-chunk-section-index", 3); -+ maxChunkSectionIndex = maxChunkSectionIndex > 15 ? 15 : maxChunkSectionIndex; -+ updateRadius = getInt("anti-xray.update-radius", 2); -+ lavaObscures = getBoolean("anti-xray.lava-obscures", false); -+ usePermission = getBoolean("anti-xray.use-permission", false); -+ hiddenBlocks = getList("anti-xray.hidden-blocks", Arrays.asList("gold_ore", "iron_ore", "coal_ore", "lapis_ore", "mossy_cobblestone", "obsidian", "chest", "diamond_ore", "redstone_ore", "clay", "emerald_ore", "ender_chest")); -+ replacementBlocks = getList("anti-xray.replacement-blocks", Arrays.asList("stone", "oak_planks")); -+ if (PaperConfig.version < 19) { -+ hiddenBlocks.remove("lit_redstone_ore"); -+ int index = replacementBlocks.indexOf("planks"); -+ if (index != -1) { -+ replacementBlocks.set(index, "oak_planks"); -+ } -+ set("anti-xray.hidden-blocks", hiddenBlocks); -+ set("anti-xray.replacement-blocks", replacementBlocks); -+ } -+ log("Anti-Xray: " + (antiXray ? "enabled" : "disabled") + " / Engine Mode: " + engineMode.getDescription() + " / Up to " + ((maxChunkSectionIndex + 1) * 16) + " blocks / Update Radius: " + updateRadius); -+ if (antiXray && usePermission) { -+ Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java -new file mode 100644 -index 0000000000000000000000000000000000000000..83a023ae018cbb79b5f151b1c7a5c8ba0c3bf1bf ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java -@@ -0,0 +1,45 @@ -+package com.destroystokyo.paper.antixray; -+ -+import net.minecraft.core.BlockPosition; -+import net.minecraft.core.EnumDirection; -+import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerInteractManager; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.Chunk; -+import net.minecraft.world.level.chunk.ChunkSection; -+import net.minecraft.world.level.chunk.IChunkAccess; -+ -+public class ChunkPacketBlockController { -+ -+ public static final ChunkPacketBlockController NO_OPERATION_INSTANCE = new ChunkPacketBlockController(); -+ -+ protected ChunkPacketBlockController() { -+ -+ } -+ -+ public IBlockData[] getPredefinedBlockData(World world, IChunkAccess chunk, ChunkSection chunkSection, boolean initializeBlocks) { -+ return null; -+ } -+ -+ public boolean shouldModify(EntityPlayer entityPlayer, Chunk chunk, int chunkSectionSelector) { -+ return false; -+ } -+ -+ public ChunkPacketInfo getChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { -+ return null; -+ } -+ -+ public void modifyBlocks(PacketPlayOutMapChunk packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { -+ packetPlayOutMapChunk.setReady(true); -+ } -+ -+ public void onBlockChange(World world, BlockPosition blockPosition, IBlockData newBlockData, IBlockData oldBlockData, int flag) { -+ -+ } -+ -+ public void onPlayerLeftClickBlock(PlayerInteractManager playerInteractManager, BlockPosition blockPosition, EnumDirection enumDirection) { -+ -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java -new file mode 100644 -index 0000000000000000000000000000000000000000..cd3b5b62d470ab6753b44f9b13dcf5522e4cbd15 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java -@@ -0,0 +1,650 @@ -+package com.destroystokyo.paper.antixray; -+ -+import java.util.ArrayList; -+import java.util.LinkedHashSet; -+import java.util.LinkedList; -+import java.util.List; -+import java.util.Set; -+import java.util.concurrent.Executor; -+import java.util.concurrent.ThreadLocalRandom; -+import java.util.function.IntSupplier; -+ -+import net.minecraft.core.BlockPosition; -+import net.minecraft.core.EnumDirection; -+import net.minecraft.core.IRegistry; -+import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerInteractManager; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.Blocks; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.Chunk; -+import net.minecraft.world.level.chunk.ChunkEmpty; -+import net.minecraft.world.level.chunk.ChunkSection; -+import net.minecraft.world.level.chunk.DataPalette; -+import net.minecraft.world.level.chunk.IChunkAccess; -+import org.bukkit.Bukkit; -+import org.bukkit.World.Environment; -+ -+import com.destroystokyo.paper.PaperWorldConfig; -+ -+public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockController { -+ -+ private final Executor executor; -+ private final EngineMode engineMode; -+ private final int maxChunkSectionIndex; -+ private final int updateRadius; -+ private final boolean usePermission; -+ private final IBlockData[] predefinedBlockData; -+ private final IBlockData[] predefinedBlockDataFull; -+ private final IBlockData[] predefinedBlockDataStone; -+ private final IBlockData[] predefinedBlockDataNetherrack; -+ private final IBlockData[] predefinedBlockDataEndStone; -+ private final int[] predefinedBlockDataBitsGlobal; -+ private final int[] predefinedBlockDataBitsStoneGlobal; -+ private final int[] predefinedBlockDataBitsNetherrackGlobal; -+ private final int[] predefinedBlockDataBitsEndStoneGlobal; -+ private final boolean[] solidGlobal = new boolean[Block.REGISTRY_ID.size()]; -+ private final boolean[] obfuscateGlobal = new boolean[Block.REGISTRY_ID.size()]; -+ private final ChunkSection[] emptyNearbyChunkSections = {Chunk.EMPTY_CHUNK_SECTION, Chunk.EMPTY_CHUNK_SECTION, Chunk.EMPTY_CHUNK_SECTION, Chunk.EMPTY_CHUNK_SECTION}; -+ private final int maxBlockYUpdatePosition; -+ -+ public ChunkPacketBlockControllerAntiXray(World world, Executor executor) { -+ PaperWorldConfig paperWorldConfig = world.paperConfig; -+ engineMode = paperWorldConfig.engineMode; -+ maxChunkSectionIndex = paperWorldConfig.maxChunkSectionIndex; -+ updateRadius = paperWorldConfig.updateRadius; -+ usePermission = paperWorldConfig.usePermission; -+ -+ this.executor = executor; -+ -+ List toObfuscate; -+ -+ if (engineMode == EngineMode.HIDE) { -+ toObfuscate = paperWorldConfig.hiddenBlocks; -+ predefinedBlockData = null; -+ predefinedBlockDataFull = null; -+ predefinedBlockDataStone = new IBlockData[] {Blocks.STONE.getBlockData()}; -+ predefinedBlockDataNetherrack = new IBlockData[] {Blocks.NETHERRACK.getBlockData()}; -+ predefinedBlockDataEndStone = new IBlockData[] {Blocks.END_STONE.getBlockData()}; -+ predefinedBlockDataBitsGlobal = null; -+ predefinedBlockDataBitsStoneGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.STONE.getBlockData())}; -+ predefinedBlockDataBitsNetherrackGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.NETHERRACK.getBlockData())}; -+ predefinedBlockDataBitsEndStoneGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.END_STONE.getBlockData())}; -+ } else { -+ toObfuscate = new ArrayList<>(paperWorldConfig.replacementBlocks); -+ List predefinedBlockDataList = new LinkedList(); -+ -+ for (String id : paperWorldConfig.hiddenBlocks) { -+ Block block = IRegistry.BLOCK.getOptional(new MinecraftKey(id)).orElse(null); -+ -+ if (block != null && !block.isTileEntity()) { -+ toObfuscate.add(id); -+ predefinedBlockDataList.add(block.getBlockData()); -+ } -+ } -+ -+ // The doc of the LinkedHashSet(Collection c) constructor doesn't specify that the insertion order is the predictable iteration order of the specified Collection, although it is in the implementation -+ Set predefinedBlockDataSet = new LinkedHashSet(); -+ // Therefore addAll(Collection c) is used, which guarantees this order in the doc -+ predefinedBlockDataSet.addAll(predefinedBlockDataList); -+ predefinedBlockData = predefinedBlockDataSet.size() == 0 ? new IBlockData[] {Blocks.DIAMOND_ORE.getBlockData()} : predefinedBlockDataSet.toArray(new IBlockData[0]); -+ predefinedBlockDataFull = predefinedBlockDataSet.size() == 0 ? new IBlockData[] {Blocks.DIAMOND_ORE.getBlockData()} : predefinedBlockDataList.toArray(new IBlockData[0]); -+ predefinedBlockDataStone = null; -+ predefinedBlockDataNetherrack = null; -+ predefinedBlockDataEndStone = null; -+ predefinedBlockDataBitsGlobal = new int[predefinedBlockDataFull.length]; -+ -+ for (int i = 0; i < predefinedBlockDataFull.length; i++) { -+ predefinedBlockDataBitsGlobal[i] = ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(predefinedBlockDataFull[i]); -+ } -+ -+ predefinedBlockDataBitsStoneGlobal = null; -+ predefinedBlockDataBitsNetherrackGlobal = null; -+ predefinedBlockDataBitsEndStoneGlobal = null; -+ } -+ -+ for (String id : toObfuscate) { -+ Block block = IRegistry.BLOCK.getOptional(new MinecraftKey(id)).orElse(null); -+ -+ // Don't obfuscate air because air causes unnecessary block updates and causes block updates to fail in the void -+ if (block != null && !block.getBlockData().isAir()) { -+ // Replace all block states of a specified block -+ // No OBFHELPER for nms.BlockStateList#a() due to too many decompile errors -+ // The OBFHELPER should be getBlockDataList() -+ for (IBlockData blockData : block.getStates().a()) { -+ obfuscateGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(blockData)] = true; -+ } -+ } -+ } -+ -+ ChunkEmpty emptyChunk = new ChunkEmpty(world, new ChunkCoordIntPair(0, 0)); -+ BlockPosition zeroPos = new BlockPosition(0, 0, 0); -+ -+ for (int i = 0; i < solidGlobal.length; i++) { -+ IBlockData blockData = ChunkSection.GLOBAL_PALETTE.getObject(i); -+ -+ if (blockData != null) { -+ solidGlobal[i] = blockData.isOccluding(emptyChunk, zeroPos) -+ && blockData.getBlock() != Blocks.SPAWNER && blockData.getBlock() != Blocks.BARRIER && blockData.getBlock() != Blocks.SHULKER_BOX && blockData.getBlock() != Blocks.SLIME_BLOCK || paperWorldConfig.lavaObscures && blockData == Blocks.LAVA.getBlockData(); -+ // Comparing blockData == Blocks.LAVA.getBlockData() instead of blockData.getBlock() == Blocks.LAVA ensures that only "stationary lava" is used -+ // shulker box checks TE. -+ } -+ } -+ -+ this.maxBlockYUpdatePosition = (maxChunkSectionIndex + 1) * 16 + updateRadius - 1; -+ } -+ -+ private int getPredefinedBlockDataFullLength() { -+ return engineMode == EngineMode.HIDE ? 1 : predefinedBlockDataFull.length; -+ } -+ -+ @Override -+ public IBlockData[] getPredefinedBlockData(World world, IChunkAccess chunk, ChunkSection chunkSection, boolean initializeBlocks) { -+ // Return the block data which should be added to the data palettes so that they can be used for the obfuscation -+ if (chunkSection.getYPosition() >> 4 <= maxChunkSectionIndex) { -+ switch (engineMode) { -+ case HIDE: -+ switch (world.getWorld().getEnvironment()) { -+ case NETHER: -+ return predefinedBlockDataNetherrack; -+ case THE_END: -+ return predefinedBlockDataEndStone; -+ default: -+ return predefinedBlockDataStone; -+ } -+ default: -+ return predefinedBlockData; -+ } -+ } -+ -+ return null; -+ } -+ -+ @Override -+ public boolean shouldModify(EntityPlayer entityPlayer, Chunk chunk, int chunkSectionSelector) { -+ return !usePermission || !entityPlayer.getBukkitEntity().hasPermission("paper.antixray.bypass"); -+ } -+ -+ @Override -+ public ChunkPacketInfoAntiXray getChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { -+ // Return a new instance to collect data and objects in the right state while creating the chunk packet for thread safe access later -+ // Note: As of 1.14 this has to be moved later due to the chunk system. -+ ChunkPacketInfoAntiXray chunkPacketInfoAntiXray = new ChunkPacketInfoAntiXray(packetPlayOutMapChunk, chunk, chunkSectionSelector, this); -+ return chunkPacketInfoAntiXray; -+ } -+ -+ @Override -+ public void modifyBlocks(PacketPlayOutMapChunk packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { -+ if (chunkPacketInfo == null) { -+ packetPlayOutMapChunk.setReady(true); -+ return; -+ } -+ -+ if (!Bukkit.isPrimaryThread()) { -+ // plugins? -+ MinecraftServer.getServer().scheduleOnMain(() -> { -+ this.modifyBlocks(packetPlayOutMapChunk, chunkPacketInfo); -+ }); -+ return; -+ } -+ -+ Chunk chunk = chunkPacketInfo.getChunk(); -+ int x = chunk.getPos().x; -+ int z = chunk.getPos().z; -+ WorldServer world = (WorldServer)chunk.world; -+ ((ChunkPacketInfoAntiXray) chunkPacketInfo).setNearbyChunks( -+ (Chunk) world.getChunkIfLoadedImmediately(x - 1, z), -+ (Chunk) world.getChunkIfLoadedImmediately(x + 1, z), -+ (Chunk) world.getChunkIfLoadedImmediately(x, z - 1), -+ (Chunk) world.getChunkIfLoadedImmediately(x, z + 1)); -+ -+ executor.execute((ChunkPacketInfoAntiXray) chunkPacketInfo); -+ } -+ -+ // Actually these fields should be variables inside the obfuscate method but in sync mode or with SingleThreadExecutor in async mode it's okay (even without ThreadLocal) -+ // If an ExecutorService with multiple threads is used, ThreadLocal must be used here -+ private final ThreadLocal predefinedBlockDataBits = ThreadLocal.withInitial(() -> new int[getPredefinedBlockDataFullLength()]); -+ private static final ThreadLocal solid = ThreadLocal.withInitial(() -> new boolean[Block.REGISTRY_ID.size()]); -+ private static final ThreadLocal obfuscate = ThreadLocal.withInitial(() -> new boolean[Block.REGISTRY_ID.size()]); -+ // These boolean arrays represent chunk layers, true means don't obfuscate, false means obfuscate -+ private static final ThreadLocal current = ThreadLocal.withInitial(() -> new boolean[16][16]); -+ private static final ThreadLocal next = ThreadLocal.withInitial(() -> new boolean[16][16]); -+ private static final ThreadLocal nextNext = ThreadLocal.withInitial(() -> new boolean[16][16]); -+ -+ public void obfuscate(ChunkPacketInfoAntiXray chunkPacketInfoAntiXray) { -+ int[] predefinedBlockDataBits = this.predefinedBlockDataBits.get(); -+ boolean[] solid = this.solid.get(); -+ boolean[] obfuscate = this.obfuscate.get(); -+ boolean[][] current = this.current.get(); -+ boolean[][] next = this.next.get(); -+ boolean[][] nextNext = this.nextNext.get(); -+ // dataBitsReader, dataBitsWriter and nearbyChunkSections could also be reused (with ThreadLocal if necessary) but it's not worth it -+ DataBitsReader dataBitsReader = new DataBitsReader(); -+ DataBitsWriter dataBitsWriter = new DataBitsWriter(); -+ ChunkSection[] nearbyChunkSections = new ChunkSection[4]; -+ boolean[] solidTemp = null; -+ boolean[] obfuscateTemp = null; -+ dataBitsReader.setDataBits(chunkPacketInfoAntiXray.getData()); -+ dataBitsWriter.setDataBits(chunkPacketInfoAntiXray.getData()); -+ int numberOfBlocks = predefinedBlockDataBits.length; -+ // Keep the lambda expressions as simple as possible. They are used very frequently. -+ IntSupplier random = numberOfBlocks == 1 ? (() -> 0) : new IntSupplier() { -+ private int state; -+ -+ { -+ while ((state = ThreadLocalRandom.current().nextInt()) == 0); -+ } -+ -+ @Override -+ public int getAsInt() { -+ // https://en.wikipedia.org/wiki/Xorshift -+ state ^= state << 13; -+ state ^= state >>> 17; -+ state ^= state << 5; -+ // https://www.pcg-random.org/posts/bounded-rands.html -+ return (int) ((Integer.toUnsignedLong(state) * numberOfBlocks) >>> 32); -+ } -+ }; -+ -+ for (int chunkSectionIndex = 0; chunkSectionIndex <= maxChunkSectionIndex; chunkSectionIndex++) { -+ if (chunkPacketInfoAntiXray.isWritten(chunkSectionIndex) && chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) != null) { -+ int[] predefinedBlockDataBitsTemp; -+ -+ if (chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex) == ChunkSection.GLOBAL_PALETTE) { -+ predefinedBlockDataBitsTemp = engineMode == EngineMode.HIDE ? chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.NETHER ? predefinedBlockDataBitsNetherrackGlobal : chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.THE_END ? predefinedBlockDataBitsEndStoneGlobal : predefinedBlockDataBitsStoneGlobal : predefinedBlockDataBitsGlobal; -+ } else { -+ // If it's this.predefinedBlockData, use this.predefinedBlockDataFull instead -+ IBlockData[] predefinedBlockDataFull = chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) == predefinedBlockData ? this.predefinedBlockDataFull : chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex); -+ predefinedBlockDataBitsTemp = predefinedBlockDataBits; -+ -+ for (int i = 0; i < predefinedBlockDataBitsTemp.length; i++) { -+ predefinedBlockDataBitsTemp[i] = chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex).getOrCreateIdFor(predefinedBlockDataFull[i]); -+ } -+ } -+ -+ dataBitsWriter.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); -+ -+ // Check if the chunk section below was not obfuscated -+ if (chunkSectionIndex == 0 || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex - 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex - 1) == null) { -+ // If so, initialize some stuff -+ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); -+ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); -+ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), solid, solidGlobal); -+ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), obfuscate, obfuscateGlobal); -+ // Read the blocks of the upper layer of the chunk section below if it exists -+ ChunkSection belowChunkSection = null; -+ boolean skipFirstLayer = chunkSectionIndex == 0 || (belowChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex - 1]) == Chunk.EMPTY_CHUNK_SECTION; -+ -+ for (int z = 0; z < 16; z++) { -+ for (int x = 0; x < 16; x++) { -+ current[z][x] = true; -+ next[z][x] = skipFirstLayer || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(belowChunkSection.getType(x, 15, z))]; -+ } -+ } -+ -+ // Abuse the obfuscateLayer method to read the blocks of the first layer of the current chunk section -+ dataBitsWriter.setBitsPerObject(0); -+ obfuscateLayer(-1, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, emptyNearbyChunkSections, random); -+ } -+ -+ dataBitsWriter.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); -+ nearbyChunkSections[0] = chunkPacketInfoAntiXray.getNearbyChunks()[0] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[0].getSections()[chunkSectionIndex]; -+ nearbyChunkSections[1] = chunkPacketInfoAntiXray.getNearbyChunks()[1] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[1].getSections()[chunkSectionIndex]; -+ nearbyChunkSections[2] = chunkPacketInfoAntiXray.getNearbyChunks()[2] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[2].getSections()[chunkSectionIndex]; -+ nearbyChunkSections[3] = chunkPacketInfoAntiXray.getNearbyChunks()[3] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[3].getSections()[chunkSectionIndex]; -+ -+ // Obfuscate all layers of the current chunk section except the upper one -+ for (int y = 0; y < 15; y++) { -+ boolean[][] temp = current; -+ current = next; -+ next = nextNext; -+ nextNext = temp; -+ obfuscateLayer(y, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); -+ } -+ -+ // Check if the chunk section above doesn't need obfuscation -+ if (chunkSectionIndex == maxChunkSectionIndex || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex + 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex + 1) == null) { -+ // If so, obfuscate the upper layer of the current chunk section by reading blocks of the first layer from the chunk section above if it exists -+ ChunkSection aboveChunkSection; -+ -+ if (chunkSectionIndex != 15 && (aboveChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex + 1]) != Chunk.EMPTY_CHUNK_SECTION) { -+ boolean[][] temp = current; -+ current = next; -+ next = nextNext; -+ nextNext = temp; -+ -+ for (int z = 0; z < 16; z++) { -+ for (int x = 0; x < 16; x++) { -+ if (!solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(aboveChunkSection.getType(x, 0, z))]) { -+ current[z][x] = true; -+ } -+ } -+ } -+ -+ // There is nothing to read anymore -+ dataBitsReader.setBitsPerObject(0); -+ solid[0] = true; -+ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solid, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); -+ } -+ } else { -+ // If not, initialize the reader and other stuff for the chunk section above to obfuscate the upper layer of the current chunk section -+ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex + 1)); -+ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex + 1)); -+ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), solid, solidGlobal); -+ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), obfuscate, obfuscateGlobal); -+ boolean[][] temp = current; -+ current = next; -+ next = nextNext; -+ nextNext = temp; -+ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); -+ } -+ -+ dataBitsWriter.finish(); -+ } -+ } -+ -+ chunkPacketInfoAntiXray.getPacketPlayOutMapChunk().setReady(true); -+ } -+ -+ private void obfuscateLayer(int y, DataBitsReader dataBitsReader, DataBitsWriter dataBitsWriter, boolean[] solid, boolean[] obfuscate, int[] predefinedBlockDataBits, boolean[][] current, boolean[][] next, boolean[][] nextNext, ChunkSection[] nearbyChunkSections, IntSupplier random) { -+ // First block of first line -+ int dataBits = dataBitsReader.read(); -+ -+ if (nextNext[0][0] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[0][1] = true; -+ next[1][0] = true; -+ } else { -+ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(0, y, 15))] || nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, 0))] || current[0][0]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[0][0] = true; -+ } -+ -+ // First line -+ for (int x = 1; x < 15; x++) { -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[0][x] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[0][x - 1] = true; -+ next[0][x + 1] = true; -+ next[1][x] = true; -+ } else { -+ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(x, y, 15))] || current[0][x]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[0][x] = true; -+ } -+ } -+ -+ // Last block of first line -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[0][15] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[0][14] = true; -+ next[1][15] = true; -+ } else { -+ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(15, y, 15))] || nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, 0))] || current[0][15]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[0][15] = true; -+ } -+ -+ // All inner lines -+ for (int z = 1; z < 15; z++) { -+ // First block -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[z][0] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[z][1] = true; -+ next[z - 1][0] = true; -+ next[z + 1][0] = true; -+ } else { -+ if (nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, z))] || current[z][0]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[z][0] = true; -+ } -+ -+ // All inner blocks -+ for (int x = 1; x < 15; x++) { -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[z][x] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[z][x - 1] = true; -+ next[z][x + 1] = true; -+ next[z - 1][x] = true; -+ next[z + 1][x] = true; -+ } else { -+ if (current[z][x]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[z][x] = true; -+ } -+ } -+ -+ // Last block -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[z][15] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[z][14] = true; -+ next[z - 1][15] = true; -+ next[z + 1][15] = true; -+ } else { -+ if (nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, z))] || current[z][15]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[z][15] = true; -+ } -+ } -+ -+ // First block of last line -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[15][0] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[15][1] = true; -+ next[14][0] = true; -+ } else { -+ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(0, y, 0))] || nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, 15))] || current[15][0]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[15][0] = true; -+ } -+ -+ // Last line -+ for (int x = 1; x < 15; x++) { -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[15][x] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[15][x - 1] = true; -+ next[15][x + 1] = true; -+ next[14][x] = true; -+ } else { -+ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(x, y, 0))] || current[15][x]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[15][x] = true; -+ } -+ } -+ -+ // Last block of last line -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[15][15] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[15][14] = true; -+ next[14][15] = true; -+ } else { -+ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(15, y, 0))] || nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, 15))] || current[15][15]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[15][15] = true; -+ } -+ } -+ -+ private boolean[] readDataPalette(DataPalette dataPalette, boolean[] temp, boolean[] global) { -+ if (dataPalette == ChunkSection.GLOBAL_PALETTE) { -+ return global; -+ } -+ -+ IBlockData blockData; -+ -+ for (int i = 0; (blockData = dataPalette.getObject(i)) != null; i++) { -+ temp[i] = global[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(blockData)]; -+ } -+ -+ return temp; -+ } -+ -+ @Override -+ public void onBlockChange(World world, BlockPosition blockPosition, IBlockData newBlockData, IBlockData oldBlockData, int flag) { -+ if (oldBlockData != null && solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(oldBlockData)] && !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(newBlockData)] && blockPosition.getY() <= maxBlockYUpdatePosition) { -+ updateNearbyBlocks(world, blockPosition); -+ } -+ } -+ -+ @Override -+ public void onPlayerLeftClickBlock(PlayerInteractManager playerInteractManager, BlockPosition blockPosition, EnumDirection enumDirection) { -+ if (blockPosition.getY() <= maxBlockYUpdatePosition) { -+ updateNearbyBlocks(playerInteractManager.world, blockPosition); -+ } -+ } -+ -+ private void updateNearbyBlocks(World world, BlockPosition blockPosition) { -+ if (updateRadius >= 2) { -+ BlockPosition temp = blockPosition.west(); -+ updateBlock(world, temp); -+ updateBlock(world, temp.west()); -+ updateBlock(world, temp.down()); -+ updateBlock(world, temp.up()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.east()); -+ updateBlock(world, temp.east()); -+ updateBlock(world, temp.down()); -+ updateBlock(world, temp.up()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.down()); -+ updateBlock(world, temp.down()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.up()); -+ updateBlock(world, temp.up()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.north()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp = blockPosition.south()); -+ updateBlock(world, temp.south()); -+ } else if (updateRadius == 1) { -+ updateBlock(world, blockPosition.west()); -+ updateBlock(world, blockPosition.east()); -+ updateBlock(world, blockPosition.down()); -+ updateBlock(world, blockPosition.up()); -+ updateBlock(world, blockPosition.north()); -+ updateBlock(world, blockPosition.south()); -+ } else { -+ // Do nothing if updateRadius <= 0 (test mode) -+ } -+ } -+ -+ private void updateBlock(World world, BlockPosition blockPosition) { -+ IBlockData blockData = world.getTypeIfLoaded(blockPosition); -+ -+ if (blockData != null && obfuscateGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(blockData)]) { -+ // world.notify(blockPosition, blockData, blockData, 3); -+ ((WorldServer)world).getChunkProvider().flagDirty(blockPosition); // We only need to re-send to client -+ } -+ } -+ -+ public enum EngineMode { -+ -+ HIDE(1, "hide ores"), -+ OBFUSCATE(2, "obfuscate"); -+ -+ private final int id; -+ private final String description; -+ -+ EngineMode(int id, String description) { -+ this.id = id; -+ this.description = description; -+ } -+ -+ public static EngineMode getById(int id) { -+ for (EngineMode engineMode : values()) { -+ if (engineMode.id == id) { -+ return engineMode; -+ } -+ } -+ -+ return null; -+ } -+ -+ public int getId() { -+ return id; -+ } -+ -+ public String getDescription() { -+ return description; -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..22c9adefc3e51e9e4b8d611a40d1497d2a16a8d2 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java -@@ -0,0 +1,81 @@ -+package com.destroystokyo.paper.antixray; -+ -+import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; -+import net.minecraft.world.level.chunk.Chunk; -+import net.minecraft.world.level.chunk.DataPalette; -+ -+public class ChunkPacketInfo { -+ -+ private final PacketPlayOutMapChunk packetPlayOutMapChunk; -+ private final Chunk chunk; -+ private final int chunkSectionSelector; -+ private byte[] data; -+ private final int[] bitsPerObject = new int[16]; -+ private final Object[] dataPalettes = new Object[16]; -+ private final int[] dataBitsIndexes = new int[16]; -+ private final Object[][] predefinedObjects = new Object[16][]; -+ -+ public ChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { -+ this.packetPlayOutMapChunk = packetPlayOutMapChunk; -+ this.chunk = chunk; -+ this.chunkSectionSelector = chunkSectionSelector; -+ } -+ -+ public PacketPlayOutMapChunk getPacketPlayOutMapChunk() { -+ return packetPlayOutMapChunk; -+ } -+ -+ public Chunk getChunk() { -+ return chunk; -+ } -+ -+ public int getChunkSectionSelector() { -+ return chunkSectionSelector; -+ } -+ -+ public byte[] getData() { -+ return data; -+ } -+ -+ public void setData(byte[] data) { -+ this.data = data; -+ } -+ -+ public int getBitsPerObject(int chunkSectionIndex) { -+ return bitsPerObject[chunkSectionIndex]; -+ } -+ -+ public void setBitsPerObject(int chunkSectionIndex, int bitsPerObject) { -+ this.bitsPerObject[chunkSectionIndex] = bitsPerObject; -+ } -+ -+ @SuppressWarnings("unchecked") -+ public DataPalette getDataPalette(int chunkSectionIndex) { -+ return (DataPalette) dataPalettes[chunkSectionIndex]; -+ } -+ -+ public void setDataPalette(int chunkSectionIndex, DataPalette dataPalette) { -+ dataPalettes[chunkSectionIndex] = dataPalette; -+ } -+ -+ public int getDataBitsIndex(int chunkSectionIndex) { -+ return dataBitsIndexes[chunkSectionIndex]; -+ } -+ -+ public void setDataBitsIndex(int chunkSectionIndex, int dataBitsIndex) { -+ dataBitsIndexes[chunkSectionIndex] = dataBitsIndex; -+ } -+ -+ @SuppressWarnings("unchecked") -+ public T[] getPredefinedObjects(int chunkSectionIndex) { -+ return (T[]) predefinedObjects[chunkSectionIndex]; -+ } -+ -+ public void setPredefinedObjects(int chunkSectionIndex, T[] predefinedObjects) { -+ this.predefinedObjects[chunkSectionIndex] = predefinedObjects; -+ } -+ -+ public boolean isWritten(int chunkSectionIndex) { -+ return bitsPerObject[chunkSectionIndex] != 0; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4b64964e52b11bea4d2c0d0f64f55ad08d2189be ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java -@@ -0,0 +1,30 @@ -+package com.destroystokyo.paper.antixray; -+ -+import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.Chunk; -+ -+public final class ChunkPacketInfoAntiXray extends ChunkPacketInfo implements Runnable { -+ -+ private Chunk[] nearbyChunks; -+ private final ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray; -+ -+ public ChunkPacketInfoAntiXray(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector, -+ ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray) { -+ super(packetPlayOutMapChunk, chunk, chunkSectionSelector); -+ this.chunkPacketBlockControllerAntiXray = chunkPacketBlockControllerAntiXray; -+ } -+ -+ public Chunk[] getNearbyChunks() { -+ return nearbyChunks; -+ } -+ -+ public void setNearbyChunks(Chunk... nearbyChunks) { -+ this.nearbyChunks = nearbyChunks; -+ } -+ -+ @Override -+ public void run() { -+ chunkPacketBlockControllerAntiXray.obfuscate(this); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java -new file mode 100644 -index 0000000000000000000000000000000000000000..298ea423084dbcc1b61f991bcd82b8ae51bf0977 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java -@@ -0,0 +1,51 @@ -+package com.destroystokyo.paper.antixray; -+ -+public final class DataBitsReader { -+ -+ private byte[] dataBits; -+ private int bitsPerObject; -+ private int mask; -+ private int longInDataBitsIndex; -+ private int bitInLongIndex; -+ private long current; -+ -+ public void setDataBits(byte[] dataBits) { -+ this.dataBits = dataBits; -+ } -+ -+ public void setBitsPerObject(int bitsPerObject) { -+ this.bitsPerObject = bitsPerObject; -+ mask = (1 << bitsPerObject) - 1; -+ } -+ -+ public void setIndex(int index) { -+ this.longInDataBitsIndex = index; -+ bitInLongIndex = 0; -+ init(); -+ } -+ -+ private void init() { -+ if (dataBits.length > longInDataBitsIndex + 7) { -+ current = ((((long) dataBits[longInDataBitsIndex]) << 56) -+ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) -+ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) -+ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) -+ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) -+ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) -+ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) -+ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); -+ } -+ } -+ -+ public int read() { -+ if (bitInLongIndex + bitsPerObject > 64) { -+ bitInLongIndex = 0; -+ longInDataBitsIndex += 8; -+ init(); -+ } -+ -+ int value = (int) (current >>> bitInLongIndex) & mask; -+ bitInLongIndex += bitsPerObject; -+ return value; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..333763936897befda5bb6c077944d2667f922799 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java -@@ -0,0 +1,79 @@ -+package com.destroystokyo.paper.antixray; -+ -+public final class DataBitsWriter { -+ -+ private byte[] dataBits; -+ private int bitsPerObject; -+ private long mask; -+ private int longInDataBitsIndex; -+ private int bitInLongIndex; -+ private long current; -+ private boolean dirty; -+ -+ public void setDataBits(byte[] dataBits) { -+ this.dataBits = dataBits; -+ } -+ -+ public void setBitsPerObject(int bitsPerObject) { -+ this.bitsPerObject = bitsPerObject; -+ mask = (1 << bitsPerObject) - 1; -+ } -+ -+ public void setIndex(int index) { -+ this.longInDataBitsIndex = index; -+ bitInLongIndex = 0; -+ init(); -+ } -+ -+ private void init() { -+ if (dataBits.length > longInDataBitsIndex + 7) { -+ current = ((((long) dataBits[longInDataBitsIndex]) << 56) -+ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) -+ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) -+ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) -+ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) -+ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) -+ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) -+ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); -+ } -+ -+ dirty = false; -+ } -+ -+ public void finish() { -+ if (dirty && dataBits.length > longInDataBitsIndex + 7) { -+ dataBits[longInDataBitsIndex] = (byte) (current >> 56 & 0xff); -+ dataBits[longInDataBitsIndex + 1] = (byte) (current >> 48 & 0xff); -+ dataBits[longInDataBitsIndex + 2] = (byte) (current >> 40 & 0xff); -+ dataBits[longInDataBitsIndex + 3] = (byte) (current >> 32 & 0xff); -+ dataBits[longInDataBitsIndex + 4] = (byte) (current >> 24 & 0xff); -+ dataBits[longInDataBitsIndex + 5] = (byte) (current >> 16 & 0xff); -+ dataBits[longInDataBitsIndex + 6] = (byte) (current >> 8 & 0xff); -+ dataBits[longInDataBitsIndex + 7] = (byte) (current & 0xff); -+ } -+ } -+ -+ public void write(int value) { -+ if (bitInLongIndex + bitsPerObject > 64) { -+ finish(); -+ bitInLongIndex = 0; -+ longInDataBitsIndex += 8; -+ init(); -+ } -+ -+ current = current & ~(mask << bitInLongIndex) | (value & mask) << bitInLongIndex; -+ dirty = true; -+ bitInLongIndex += bitsPerObject; -+ } -+ -+ public void skip() { -+ bitInLongIndex += bitsPerObject; -+ -+ if (bitInLongIndex > 64) { -+ finish(); -+ bitInLongIndex = bitsPerObject; -+ longInDataBitsIndex += 8; -+ init(); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index a7d10d124021f3427f23fcd533f885367b64515c..3047cf8c4ec1b664d6b790f18d2b1657e4b00435 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -1,5 +1,6 @@ - package net.minecraft.network.protocol.game; - -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import com.google.common.collect.Lists; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.Unpooled; -@@ -16,6 +17,7 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.entity.TileEntitySkull; -+import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.chunk.BiomeStorage; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkSection; -@@ -33,7 +35,13 @@ public class PacketPlayOutMapChunk implements Packet { - private List g; - private boolean h; - -- public PacketPlayOutMapChunk() {} -+ // Paper start - Async-Anti-Xray - Set the ready flag to true -+ private volatile boolean ready; // Paper - Async-Anti-Xray - Ready flag for the network manager -+ public PacketPlayOutMapChunk() { -+ this.ready = true; -+ } -+ // Paper end -+ - // Paper start - private final java.util.List extraPackets = new java.util.ArrayList<>(); - private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); -@@ -43,7 +51,11 @@ public class PacketPlayOutMapChunk implements Packet { - return extraPackets; - } - // Paper end -- public PacketPlayOutMapChunk(Chunk chunk, int i) { -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public PacketPlayOutMapChunk(Chunk chunk, int i) { this(chunk, i, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public PacketPlayOutMapChunk(Chunk chunk, int i, boolean modifyBlocks) { -+ ChunkPacketInfo chunkPacketInfo = modifyBlocks ? chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i) : null; -+ // Paper end - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - - this.a = chunkcoordintpair.x; -@@ -66,7 +78,12 @@ public class PacketPlayOutMapChunk implements Packet { - } - - this.f = new byte[this.a(chunk, i)]; -- this.c = this.a(new PacketDataSerializer(this.j()), chunk, i); -+ // Paper start - Anti-Xray - Add chunk packet info -+ if (chunkPacketInfo != null) { -+ chunkPacketInfo.setData(this.getData()); -+ } -+ this.c = this.writeChunk(new PacketDataSerializer(this.j()), chunk, i, chunkPacketInfo); -+ // Paper end - this.g = Lists.newArrayList(); - iterator = chunk.getTileEntities().entrySet().iterator(); - int totalTileEntities = 0; // Paper -@@ -93,8 +110,19 @@ public class PacketPlayOutMapChunk implements Packet { - this.g.add(nbttagcompound); - } - } -+ chunk.world.chunkPacketBlockController.modifyBlocks(this, chunkPacketInfo); // Paper - Anti-Xray - Modify blocks -+ } - -+ // Paper start - Async-Anti-Xray - Getter and Setter for the ready flag -+ @Override -+ public boolean isReady() { -+ return this.ready; -+ } -+ -+ public void setReady(boolean ready) { -+ this.ready = ready; - } -+ // Paper end - - @Override - public void a(PacketDataSerializer packetdataserializer) throws IOException { -@@ -160,8 +188,12 @@ public class PacketPlayOutMapChunk implements Packet { - return bytebuf; - } - -- public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, chunkSectionSelector); } // Paper - OBFHELPER -- public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i) { -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, chunkSectionSelector); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i) { return this.writeChunk(packetdataserializer, chunk, i, null); } // Notice for updates: Please make sure this method isn't used anywhere -+ public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector, ChunkPacketInfo chunkPacketInfo) { return this.a(packetDataSerializer, chunk, chunkSectionSelector, chunkPacketInfo); } // OBFHELPER -+ public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i, ChunkPacketInfo chunkPacketInfo) { -+ // Paper end - int j = 0; - ChunkSection[] achunksection = chunk.getSections(); - int k = 0; -@@ -171,7 +203,7 @@ public class PacketPlayOutMapChunk implements Packet { - - if (chunksection != Chunk.a && (!this.f() || !chunksection.c()) && (i & 1 << k) != 0) { - j |= 1 << k; -- chunksection.b(packetdataserializer); -+ chunksection.writeChunkSection(packetdataserializer, chunkPacketInfo); // Paper - Anti-Xray - Add chunk packet info - } - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index ca05fe4ed0773b94035c63f8f8db6c034f0b92e2..5a11765c8a7d754ec86d829fa5e85d2809dd937e 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -656,7 +656,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - this.g(chunkcoordintpair); -- return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a)); -+ return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter - }, this.executor); - } - -@@ -1404,9 +1404,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ private final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { - if (apacket[0] == null) { -- apacket[0] = new PacketPlayOutMapChunk(chunk, 65535); -+ apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(entityplayer, chunk, 65535)); // Paper - Anti-Xray - Bypass - apacket[1] = new PacketPlayOutLightUpdate(chunk.getPos(), this.lightEngine, true); - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index d86b1e528b53db809ac993aa2f1d2799d4f1a574..fbd8a6985a261396789c87e4b687140bd49cea0d 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -309,6 +309,8 @@ public class PlayerInteractManager { - } - - } -+ -+ this.world.chunkPacketBlockController.onPlayerLeftClickBlock(this, blockposition, enumdirection); // Paper - Anti-Xray - } - - public void a(BlockPosition blockposition, PacketPlayInBlockDig.EnumPlayerDigType packetplayinblockdig_enumplayerdigtype, String s) { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 12e34e1514f060ffef96cdd3ac57d0495dd37321..024e0bf39b73076fba5c4187c4ff5066e663cf7e 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -210,7 +210,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { -- super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env); -+ super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor - this.pvpMode = minecraftserver.getPVP(); - convertable = convertable_conversionsession; - uuid = WorldUUID.getUUID(convertable_conversionsession.folder.toFile()); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 12ac3608736b45447afe6b0d35ead1441390be5e..15da3511a9e57c320f4cf409852bee07109095bc 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -2,6 +2,8 @@ package net.minecraft.world.level; - - import co.aikar.timings.Timing; - import co.aikar.timings.Timings; -+import com.destroystokyo.paper.antixray.ChunkPacketBlockController; // Paper - Anti-Xray -+import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray; // Paper - Anti-Xray - import com.destroystokyo.paper.event.server.ServerExceptionEvent; - import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.base.MoreObjects; -@@ -144,6 +146,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - - public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper -+ public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray - - public final co.aikar.timings.WorldTimingsHandler timings; // Paper - public static BlockPosition lastPhysicsProblem; // Spigot -@@ -165,9 +168,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return typeKey; - } - -- protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { -+ protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName()); // Spigot - this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper -+ this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray - this.generator = gen; - this.world = new CraftWorld((WorldServer) this, gen, env); - this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit -@@ -433,6 +437,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // CraftBukkit end - - IBlockData iblockdata1 = chunk.setType(blockposition, iblockdata, (i & 64) != 0, (i & 1024) == 0); // CraftBukkit custom NO_PLACE flag -+ this.chunkPacketBlockController.onBlockChange(this, blockposition, iblockdata, iblockdata1, i); // Paper - Anti-Xray - - if (iblockdata1 == null) { - // CraftBukkit start - remove blockstate if failed (or the same) -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 2690c44eaae193a259fe195c95e59d07d5e1cc5a..3fdce0e6fa34eb4b1eafc618068a3fb06abd5ec1 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -465,7 +465,7 @@ public class Chunk implements IChunkAccess { - return null; - } - -- chunksection = new ChunkSection(j >> 4 << 4); -+ chunksection = new ChunkSection(j >> 4 << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters - this.sections[j >> 4] = chunksection; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -index 89efd0b68b04457e1cd617dcc8bb1a6ea1c4717c..9fb8d20e9e1a8cc716c32a100b1d70e90f385eca 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -@@ -8,6 +8,7 @@ import net.minecraft.SystemUtils; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.data.worldgen.biome.BiomeRegistry; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkCoordIntPair; -@@ -28,7 +29,7 @@ public class ChunkEmpty extends Chunk { - }); - - public ChunkEmpty(World world, ChunkCoordIntPair chunkcoordintpair) { -- super(world, chunkcoordintpair, new BiomeStorage(world.r().b(IRegistry.ay), ChunkEmpty.b)); -+ super(world, chunkcoordintpair, new BiomeStorage(MinecraftServer.getServer().getCustomRegistry().b(IRegistry.ay), ChunkEmpty.b)); // Paper - world isnt ready yet for anti xray use here, use server singleton for registry - } - - // Paper start -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index eea4a30428293eaf7afbe303a37adec60b44c2b4..0b4e346daaea91565fde2f789fafa8b431a7b042 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -1,9 +1,11 @@ - package net.minecraft.world.level.chunk; - - import java.util.function.Predicate; -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import javax.annotation.Nullable; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.network.PacketDataSerializer; -+import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; -@@ -18,16 +20,22 @@ public class ChunkSection { - private short e; - final DataPaletteBlock blockIds; // Paper - package-private - -- public ChunkSection(int i) { -- this(i, (short) 0, (short) 0, (short) 0); -+ // Paper start - Anti-Xray - Add parameters -+ @Deprecated public ChunkSection(int i) { this(i, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ChunkSection(int i, IChunkAccess chunk, World world, boolean initializeBlocks) { -+ this(i, (short) 0, (short) 0, (short) 0, chunk, world, initializeBlocks); -+ // Paper end - } - -- public ChunkSection(int i, short short0, short short1, short short2) { -+ // Paper start - Anti-Xray - Add parameters -+ @Deprecated public ChunkSection(int i, short short0, short short1, short short2) { this(i, short0, short1, short2, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ChunkSection(int i, short short0, short short1, short short2, IChunkAccess chunk, World world, boolean initializeBlocks) { -+ // Paper end - this.yPos = i; - this.nonEmptyBlockCount = short0; - this.tickingBlockCount = short1; - this.e = short2; -- this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); -+ this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData(), world == null ? null : world.chunkPacketBlockController.getPredefinedBlockData(world, chunk, this, initializeBlocks), initializeBlocks); // Paper - Anti-Xray - Add predefined block data - } - - public final IBlockData getType(int i, int j, int k) { // Paper -@@ -139,10 +147,14 @@ public class ChunkSection { - return this.blockIds; - } - -- public void writeChunkSection(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER -- public void b(PacketDataSerializer packetdataserializer) { -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public final void writeChunkSection(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public final void b(PacketDataSerializer packetdataserializer) { this.writeChunkSection(packetdataserializer, null); } // Notice for updates: Please make sure this method isn't used anywhere -+ public final void writeChunkSection(PacketDataSerializer packetDataSerializer, ChunkPacketInfo chunkPacketInfo) { this.b(packetDataSerializer, chunkPacketInfo); } // OBFHELPER -+ public void b(PacketDataSerializer packetdataserializer, ChunkPacketInfo chunkPacketInfo) { -+ // Paper end - packetdataserializer.writeShort(this.nonEmptyBlockCount); -- this.blockIds.b(packetdataserializer); -+ this.blockIds.writeDataPaletteBlock(packetdataserializer, chunkPacketInfo, this.yPos >> 4); // Paper - Anti-Xray - Add chunk packet info - } - - public int j() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index cc0c5995dc3840ce66ea849849f7c37555d3b5e6..68d53a51acc9790b9cda20ec4d2ec6edd1baac1a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -1,6 +1,7 @@ - package net.minecraft.world.level.chunk; - - import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import java.util.Arrays; - import java.util.Objects; - import java.util.concurrent.locks.ReentrantLock; -@@ -27,6 +28,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - private final Function e; - private final Function f; - private final T g; -+ private final T[] predefinedObjects; // Paper - Anti-Xray - Add predefined objects - protected DataBits a; public final DataBits getDataBits() { return this.a; } // Paper - OBFHELPER - private DataPalette h; private DataPalette getDataPalette() { return this.h; } // Paper - OBFHELPER - private int i; private int getBitsPerObject() { return this.i; } // Paper - OBFHELPER -@@ -51,14 +53,47 @@ public class DataPaletteBlock implements DataPaletteExpandable { - //this.j.unlock(); // Paper - disable this - } - -- public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0) { -+ // Paper start - Anti-Xray - Add predefined objects -+ @Deprecated public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0) { this(datapalette, registryblockid, function, function1, t0, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0, T[] predefinedObjects, boolean initialize) { -+ // Paper end - this.b = datapalette; - this.d = registryblockid; - this.e = function; - this.f = function1; - this.g = t0; -- this.b(4); -+ // Paper start - Anti-Xray - Add predefined objects -+ this.predefinedObjects = predefinedObjects; -+ -+ if (initialize) { -+ if (predefinedObjects == null) { -+ // Default -+ this.initialize(4); -+ } else { -+ // MathHelper.d() is trailingBits(roundCeilPow2(n)), alternatively; (int)ceil(log2(n)); however it's trash, use numberOfLeadingZeros instead -+ // Count the bits of the maximum array index to initialize a data palette with enough space from the beginning -+ // The length of the array is used because air is also added to the data palette from the beginning -+ // Start with at least 4 -+ int maxIndex = predefinedObjects.length >> 4; -+ int bitCount = (32 - Integer.numberOfLeadingZeros(Math.max(16, maxIndex) - 1)); -+ -+ // Initialize with at least 15 free indixes -+ this.initialize((1 << bitCount) - predefinedObjects.length < 16 ? bitCount + 1 : bitCount); -+ this.addPredefinedObjects(); -+ } -+ } -+ // Paper end -+ } -+ -+ // Paper start - Anti-Xray - Add predefined objects -+ private void addPredefinedObjects() { -+ if (this.predefinedObjects != null && this.getDataPalette() != this.getDataPaletteGlobal()) { -+ for (int i = 0; i < this.predefinedObjects.length; i++) { -+ this.getDataPalette().getOrCreateIdFor(this.predefinedObjects[i]); -+ } -+ } - } -+ // Paper end - - private static int b(int i, int j, int k) { - return j << 8 | k << 4 | i; -@@ -93,6 +128,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - - int j; - -+ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects - for (j = 0; j < databits.b(); ++j) { - T t1 = datapalette.a(databits.a(j)); - -@@ -142,24 +178,38 @@ public class DataPaletteBlock implements DataPaletteExpandable { - return t0 == null ? this.g : t0; - } - -- public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER -- public synchronized void b(PacketDataSerializer packetdataserializer) { // Paper - synchronize -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public void b(PacketDataSerializer packetdataserializer) { this.writeDataPaletteBlock(packetdataserializer, null, 0); } // Notice for updates: Please make sure this method isn't used anywhere -+ public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { this.b(packetDataSerializer, chunkPacketInfo, chunkSectionIndex); } // OBFHELPER -+ public synchronized void b(PacketDataSerializer packetdataserializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { // Paper - synchronize -+ // Paper end - this.a(); - packetdataserializer.writeByte(this.i); - this.h.b(packetdataserializer); -+ // Paper start - Anti-Xray - Add chunk packet info -+ if (chunkPacketInfo != null) { -+ chunkPacketInfo.setBitsPerObject(chunkSectionIndex, this.getBitsPerObject()); -+ chunkPacketInfo.setDataPalette(chunkSectionIndex, this.getDataPalette()); -+ chunkPacketInfo.setDataBitsIndex(chunkSectionIndex, packetdataserializer.writerIndex() + PacketDataSerializer.countBytes(this.getDataBits().getDataBits().length)); -+ chunkPacketInfo.setPredefinedObjects(chunkSectionIndex, this.predefinedObjects); -+ } -+ // Paper end - packetdataserializer.a(this.a.a()); - this.b(); - } - - public synchronized void a(NBTTagList nbttaglist, long[] along) { // Paper - synchronize - this.a(); -- int i = Math.max(4, MathHelper.e(nbttaglist.size())); -+ // Paper - Anti-Xray - TODO: Should this.predefinedObjects.length just be added here (faster) or should the contents be compared to calculate the size (less RAM)? -+ int i = Math.max(4, MathHelper.e(nbttaglist.size() + (this.predefinedObjects == null ? 0 : this.predefinedObjects.length))); // Paper - Anti-Xray - Calculate the size with predefined objects - -- if (i != this.i) { -+ if (true || i != this.i) { // Paper - Anti-Xray - Not initialized yet - this.b(i); - } - - this.h.a(nbttaglist); -+ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects - int j = along.length * 64 / 4096; - - if (this.h == this.b) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 9eeb99a21a6ed7f71ff64cf4cfdff646d31abbcf..9b308a10554b037ede0c455fbd3e906021218ddc 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -64,16 +64,24 @@ public class ProtoChunk implements IChunkAccess { - private long s; - private final Map t; - private volatile boolean u; -+ private final World world; // Paper - Anti-Xray - Add world - -- public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { -+ // Paper start - Anti-Xray - Add world -+ @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { this(chunkcoordintpair, chunkconverter, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, World world) { -+ // Paper end - this(chunkcoordintpair, chunkconverter, (ChunkSection[]) null, new ProtoChunkTickList<>((block) -> { - return block == null || block.getBlockData().isAir(); - }, chunkcoordintpair), new ProtoChunkTickList<>((fluidtype) -> { - return fluidtype == null || fluidtype == FluidTypes.EMPTY; -- }, chunkcoordintpair)); -+ }, chunkcoordintpair), world); // Paper - Anti-Xray - Add world - } - -- public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, @Nullable ChunkSection[] achunksection, ProtoChunkTickList protochunkticklist, ProtoChunkTickList protochunkticklist1) { -+ // Paper start - Anti-Xray - Add world -+ @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, @Nullable ChunkSection[] achunksection, ProtoChunkTickList protochunkticklist, ProtoChunkTickList protochunkticklist1) { this(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, @Nullable ChunkSection[] achunksection, ProtoChunkTickList protochunkticklist, ProtoChunkTickList protochunkticklist1, World world) { -+ this.world = world; -+ // Paper end - this.f = Maps.newEnumMap(HeightMap.Type.class); - this.g = ChunkStatus.EMPTY; - this.h = Maps.newHashMap(); -@@ -228,7 +236,7 @@ public class ProtoChunk implements IChunkAccess { - - public ChunkSection a(int i) { - if (this.j[i] == Chunk.a) { -- this.j[i] = new ChunkSection(i << 4); -+ this.j[i] = new ChunkSection(i << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters - } - - return this.j[i]; -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -index 9351e6ba541d440c485b6e4a3209170c5756e31e..7a82d43d51d80a3054e0871bf4b9aa7635920efc 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -@@ -27,7 +27,7 @@ public class ProtoChunkExtension extends ProtoChunk { - private final Chunk a; - - public ProtoChunkExtension(Chunk chunk) { -- super(chunk.getPos(), ChunkConverter.a); -+ super(chunk.getPos(), ChunkConverter.a, chunk.world); // Paper - Anti-Xray - Add parameter - this.a = chunk; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 98bc26c7ae01884eb53766e72fc7cbabbf065e6e..c652897aae99c48c6cc020b5d64f6a8b02beecb5 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -101,7 +101,7 @@ public class ChunkRegionLoader { - byte b0 = nbttagcompound2.getByte("Y"); - - if (nbttagcompound2.hasKeyOfType("Palette", 9) && nbttagcompound2.hasKeyOfType("BlockStates", 12)) { -- ChunkSection chunksection = new ChunkSection(b0 << 4); -+ ChunkSection chunksection = new ChunkSection(b0 << 4, null, worldserver, false); // Paper - Anti-Xray - Add parameters - - chunksection.getBlocks().a(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); - chunksection.recalcBlockCounts(); -@@ -165,7 +165,7 @@ public class ChunkRegionLoader { - // CraftBukkit end - }); - } else { -- ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1); -+ ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter - - protochunk.a(biomestorage); - object = protochunk; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index a8e94f69faec93661dc6ae2efeec44b8bfd2e965..c36f55f178166eb099cc5c64784be5a9f4750199 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -44,7 +44,7 @@ public class CraftChunk implements Chunk { - private final WorldServer worldServer; - private final int x; - private final int z; -- private static final DataPaletteBlock emptyBlockIDs = new ChunkSection(0).getBlocks(); -+ private static final DataPaletteBlock emptyBlockIDs = new ChunkSection(0, null, null, true).getBlocks(); // Paper - Anti-Xray - Add parameters - private static final byte[] emptyLight = new byte[2048]; - - public CraftChunk(net.minecraft.world.level.chunk.Chunk chunk) { -@@ -288,7 +288,7 @@ public class CraftChunk implements Chunk { - NBTTagCompound data = new NBTTagCompound(); - cs[i].getBlocks().a(data, "Palette", "BlockStates"); - -- DataPaletteBlock blockids = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, net.minecraft.world.level.block.Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); // TODO: snapshot whole ChunkSection -+ DataPaletteBlock blockids = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, net.minecraft.world.level.block.Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData(), null, false); // TODO: snapshot whole ChunkSection // Paper - Anti-Xray - Add no predefined block data and don't initialize because it's done in the line below internally - blockids.a(data.getList("Palette", CraftMagicNumbers.NBT.TAG_COMPOUND), data.getLongArray("BlockStates")); - - sectionBlockIDs[i] = blockids; -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index 3d15915275331cb767750c24c89b4b43d43033ef..afca0038bb74ac53f07a25729a3c1542e244c6fd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -21,9 +21,11 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - private final int maxHeight; - private final ChunkSection[] sections; - private Set tiles; -+ private World world; // Paper - Anti-Xray - Add world - - public CraftChunkData(World world) { - this(world.getMaxHeight()); -+ this.world = world; // Paper - Anti-Xray - Add world - } - - /* pp for tests */ CraftChunkData(int maxHeight) { -@@ -157,7 +159,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - private ChunkSection getChunkSection(int y, boolean create) { - ChunkSection section = sections[y >> 4]; - if (create && section == null) { -- sections[y >> 4] = section = new ChunkSection(y >> 4 << 4); -+ sections[y >> 4] = section = new ChunkSection(y >> 4 << 4, null, world instanceof org.bukkit.craftbukkit.CraftWorld ? ((org.bukkit.craftbukkit.CraftWorld) world).getHandle() : null, true); // Paper - Anti-Xray - Add parameters - } - return section; - } diff --git a/Unmapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/Unmapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch deleted file mode 100644 index 528f3c9022..0000000000 --- a/Unmapped-Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 01:01:32 -0400 -Subject: [PATCH] Only count Natural Spawned mobs towards natural spawn mob - limit - -This resolves the super common complaint about mobs not spawning. - -This was ultimately a flaw in the vanilla count algorithim that allows -spawners and other misc mobs to count against the mob limit, which are -not bounded, and can prevent the entire world from spawning new. - -I believe Bukkits changes around persistence may of actually made it -worse than vanilla. - -This should fully solve all of the issues around it so that only natural -influences natural spawns. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c45493e88bf7e8811be2759ff9ac19e3fe9d938a..384cb363eed794551bee6b0ec11ba1be92a3d7ac 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -464,6 +464,16 @@ public class PaperWorldConfig { - maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); - } - -+ public boolean countAllMobsForSpawning = false; -+ private void countAllMobsForSpawning() { -+ countAllMobsForSpawning = getBoolean("count-all-mobs-for-spawning", false); -+ if (countAllMobsForSpawning) { -+ log("Counting all mobs for spawning. Mob farms may reduce natural spawns elsewhere in world."); -+ } else { -+ log("Using improved mob spawn limits (Only Natural Spawns impact spawn limits for more natural spawns)"); -+ } -+ } -+ - public boolean antiXray; - public EngineMode engineMode; - public int maxChunkSectionIndex; -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index 5307488fa48ffa91446dd4457de1ce6a8f61da61..d30a3de84dc75a57680052904337af02b6b80636 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -81,6 +81,13 @@ public final class SpawnerCreature { - EnumCreatureType enumcreaturetype = entity.getEntityType().e(); - - if (enumcreaturetype != EnumCreatureType.MISC) { -+ // Paper start - Only count natural spawns -+ if (!entity.world.paperConfig.countAllMobsForSpawning && -+ !(entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL || -+ entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { -+ continue; -+ } -+ // Paper end - BlockPosition blockposition = entity.getChunkCoordinates(); - long j = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4); - diff --git a/Unmapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch b/Unmapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch deleted file mode 100644 index 0f0d7c1e91..0000000000 --- a/Unmapped-Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lucavon -Date: Tue, 23 Jul 2019 20:29:20 -0500 -Subject: [PATCH] Configurable projectile relative velocity - -This patch adds an option "disable relative projectile velocity", which, when -nabled, will cause projectiles to ignore the shooter's current velocity, -like they did in Minecraft 1.8 and prior. -If a player is falling, for example, their shooting range will be drastically -reduced, as a downwards velocity is applied to the projectile. This prevents -players from saving themselves from falling off floating islands, for example, -as a thrown ender pearl will not make it back to the island, while it would -have in 1.8. - -While this could easily be done with plugins, too, there are multiple problems: -P1) If multiple plugins cancel the velocity by subtracting the shooter's velocity -from the projectile's velocity, the projectile's velocity would be different. -As there's no way to detect whether the projectile's velocity has already been -adjusted to ignore the player's velocity, plugins can't not do it if it's not -necessary. -P2) I've noticed some inconsistencies, e.g. weird velocity when shooting while -using an elytra. Checking for those inconsistencies is possible, but not as -efficient as just not applying the velocity in the first place. -P3) Solutions for 1) and especially 2) might not be future-proof, while this -server-internal fix makes this change future-proof. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 384cb363eed794551bee6b0ec11ba1be92a3d7ac..1ee2cced100626e48eb36ee14f84b9257c79a2f8 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -507,4 +507,9 @@ public class PaperWorldConfig { - Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); - } - } -+ -+ public boolean disableRelativeProjectileVelocity; -+ private void disableRelativeProjectileVelocity() { -+ disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index 29834a3613c7701d46e879d170779eb7e6f664e1..8fe98404ebb8b3b5d1fdac0896b27da10736026d 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -130,7 +130,7 @@ public abstract class IProjectile extends Entity { - this.shoot((double) f5, (double) f6, (double) f7, f3, f4); - Vec3D vec3d = entity.getMot(); - -- this.setMot(this.getMot().add(vec3d.x, entity.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); -+ if (!entity.world.paperConfig.disableRelativeProjectileVelocity) this.setMot(this.getMot().add(vec3d.x, entity.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); // Paper - allow disabling relative velocity - } - - // CraftBukkit start - call projectile hit event diff --git a/Unmapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch b/Unmapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch deleted file mode 100644 index 63ff602a83..0000000000 --- a/Unmapped-Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 28 Jul 2019 00:51:11 +0100 -Subject: [PATCH] Mark entities as being ticked when notifying navigation - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 024e0bf39b73076fba5c4187c4ff5066e663cf7e..3eb337d42f0292ed7b85a5fdbf6b450bc446b81a 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1475,6 +1475,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition); - - if (VoxelShapes.c(voxelshape, voxelshape1, OperatorBoolean.NOT_SAME)) { -+ boolean wasTicking = this.tickingEntities; this.tickingEntities = true; // Paper - Iterator iterator = this.navigators.iterator(); - - while (iterator.hasNext()) { -@@ -1496,6 +1497,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - -+ this.tickingEntities = wasTicking; // Paper - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch b/Unmapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch deleted file mode 100644 index b2190b5c55..0000000000 --- a/Unmapped-Spigot-Server-Patches/0366-offset-item-frame-ticking.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Tue, 30 Jul 2019 03:17:16 +0500 -Subject: [PATCH] offset item frame ticking - - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java b/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java -index 477c86bec21159608707c1b3bf2ad5f2b455214f..9d491240bcb3ba6ffbee963a13d31aa7b6cd5d45 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java -@@ -37,7 +37,7 @@ public abstract class EntityHanging extends Entity { - protected static final Predicate b = (entity) -> { - return entity instanceof EntityHanging; - }; -- private int e; -+ private int e; { this.e = this.getId() % this.world.spigotConfig.hangingTickFrequency; } // Paper - public BlockPosition blockPosition; - protected EnumDirection direction; - diff --git a/Unmapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch b/Unmapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch deleted file mode 100644 index 77f09da2e9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CullanP -Date: Thu, 3 Mar 2016 02:13:38 -0600 -Subject: [PATCH] Avoid hopper searches if there are no items - -Hoppers searching for items and minecarts is the most expensive part of hopper ticking. -We keep track of the number of minecarts and items in a chunk. -If there are no items in the chunk, we skip searching for items. -If there are no minecarts in the chunk, we skip searching for them. - -Usually hoppers aren't near items, so we can skip most item searches. -And since minecart hoppers are used _very_ rarely near we can avoid alot of searching there. - -Combined, this adds up a lot. - -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index cb5cda5e6497edeb801ef712f9bd8823cb055750..1a6f8aec32af85717f5d56e0b00a02cda88ce028 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -16,6 +16,7 @@ public final class IEntitySelector { - public static final Predicate c = (entity) -> { - return entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); - }; -+ public static final Predicate isInventory() { return d; } // Paper - OBFHELPER - public static final Predicate d = (entity) -> { - return entity instanceof IInventory && entity.isAlive(); - }; -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 3fdce0e6fa34eb4b1eafc618068a3fb06abd5ec1..e7bb33125a25b9e5a68013b15d7b5b6b6769ab9b 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -32,10 +32,13 @@ import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.EntitySlice; - import net.minecraft.util.MathHelper; -+import net.minecraft.world.IInventory; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.IEntitySelector; - import net.minecraft.world.entity.boss.EntityComplexPart; - import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; -+import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.TickList; -@@ -123,6 +126,10 @@ public class Chunk implements IChunkAccess { - return removed; - } - } -+ // Track the number of minecarts and items -+ // Keep this synced with entitySlices.add() and entitySlices.remove() -+ private final int[] itemCounts = new int[16]; -+ private final int[] inventoryEntityCounts = new int[16]; - // Paper end - - public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList ticklist, TickList ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer consumer) { -@@ -582,6 +589,13 @@ public class Chunk implements IChunkAccess { - entity.chunkZ = this.loc.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ // Paper start -+ if (entity instanceof EntityItem) { -+ itemCounts[k]++; -+ } else if (entity instanceof IInventory) { -+ inventoryEntityCounts[k]++; -+ } -+ // Paper end - entity.entitySlice = this.entitySlices[k]; // Paper - this.markDirty(); // Paper - } -@@ -615,6 +629,11 @@ public class Chunk implements IChunkAccess { - if (!this.entitySlices[i].remove(entity)) { - return; - } -+ if (entity instanceof EntityItem) { -+ itemCounts[i]--; -+ } else if (entity instanceof IInventory) { -+ inventoryEntityCounts[i]--; -+ } - entityCounts.decrement(entity.getMinecraftKeyString()); - this.markDirty(); // Paper - // Paper end -@@ -900,6 +919,14 @@ public class Chunk implements IChunkAccess { - for (int k = i; k <= j; ++k) { - Iterator iterator = this.entitySlices[k].iterator(); // Spigot - -+ // Paper start - Don't search for inventories if we have none, and that is all we want -+ /* -+ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` -+ * -+ * Make sure the inventory selector stays in sync. -+ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -+ */ -+ if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; - while (iterator.hasNext()) { - T entity = (T) iterator.next(); // CraftBukkit - decompile error - if (entity.shouldBeRemoved) continue; // Paper -@@ -920,9 +947,29 @@ public class Chunk implements IChunkAccess { - i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); - j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); - -+ // Paper start -+ int[] counts; -+ if (EntityItem.class.isAssignableFrom(oclass)) { -+ counts = itemCounts; -+ } else if (IInventory.class.isAssignableFrom(oclass)) { -+ counts = inventoryEntityCounts; -+ } else { -+ counts = null; -+ } -+ // Paper end - for (int k = i; k <= j; ++k) { -+ if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for - Iterator iterator = this.entitySlices[k].iterator(); // Spigot - -+ // Paper start - Don't search for inventories if we have none, and that is all we want -+ /* -+ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` -+ * -+ * Make sure the inventory selector stays in sync. -+ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -+ */ -+ if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; -+ // Paper end - while (iterator.hasNext()) { - T t0 = (T) iterator.next(); // CraftBukkit - decompile error - if (t0.shouldBeRemoved) continue; // Paper diff --git a/Unmapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch b/Unmapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch deleted file mode 100644 index c091706a07..0000000000 --- a/Unmapped-Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch +++ /dev/null @@ -1,4203 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 13 Jul 2019 09:23:10 -0700 -Subject: [PATCH] Asynchronous chunk IO and loading - -This patch re-adds a file IO thread as well as shoving de-serializing -chunk NBT data onto worker threads. This patch also will shove -chunk data serialization onto the same worker threads when the chunk -is unloaded - this cannot be done for regular saves since that's unsafe. - -The file IO Thread - -Unlike 1.13 and below, the file IO thread is prioritized - IO tasks can -be reoredered, however they are "stuck" to a world & coordinate. - -Scheduling IO tasks works as follows, given a world & coordinate - location: - -The IO thread has been designed to ensure that reads and writes appear to -occur synchronously for a given location, however the implementation also -has the unfortunate side-effect of making every write appear as if -they occur without failure. - -The IO thread has also been designed to accomodate Mojang's decision to -store chunk data and POI data separately. It can independently schedule -tasks for each. - -However threads can wait for writes to complete and check if: - - The write was overwriten by another scheduler - - The write failed (however it does not indicate whether it was overwritten by another scheduler) - -Scheduling reads: - - - If a write task is in progress, the task is not scheduled and returns the in-progress write data - This means that readers cannot modify the NBTTagCompound returned and must clone if it they wish to write - - If a write task is not in progress but a read task is in progress, then the read task is simply chained - This means that again, readers cannot modify the NBTTagCompound returned - -Scheduling writes: - - - If a read task is in progress, ignore the read task and schedule the write - We cannot complete the read task since we assume it wants old data - not current - - If a write task is pending, overwrite the write data - The file IO thread does correctly handle cases where the data is overwritten when it - is writing data (before completing a task it will check if the data was overwritten and - will retry). - -When the file IO thread executes a task for a location, the it will -execute the read task first (if it exists), then it will execute the -write task. This ensures that, even when scheduling at different -priorities, that reads/writes for a location act synchronously. - -The downside of the file IO thread is that write failure can only be -indicated to the scheduling thread if: - -- No other thread decides to schedule another write for the location -concurrently -- The scheduling thread blocks on the write to complete (however the -current implementation can be modified to indicate success -asynchronously) - -The file io thread can be modified easily to provide indications -of write failure and write overwriting if needed. - -The upside of the file IO thread is that if a write failures, then -chunk data is not lost until server restart. This leaves more room -for spurious failure. - -Finally, the io thread will indicate to the console when reads -or writes fail - with relevant detail. - -Asynchronous chunk data serialization for unloading chunks - -When chunks unload they make a call to PlayerChunkMap#saveChunk(IChunkAccess). -Even if I make the IO asynchronous for this call, the data serialization -still hits pretty hard. And given that now the chunk system will -aggressively unload chunks more often (queued immediately at -ticket level 45 or higher), unloads occur more often, and -combined with our changes to the unload queue to make it -significantly more aggresive - chunk unloads can hit pretty hard. -Especially players running around with elytras and fireworks. - -For serializing chunk data off main, there are some tasks which cannot be -done asynchronously. Lighting data must be saved beforehand as well as -potentially some tick lists. These are completed before scheduling the -asynchronous save. - -However serializing chunk data off of the main thread is still risky. -Even though this patch schedules the save to occur after ALL references -of the chunk are removed from the world, plugins can still technically -access entities inside the chunks. For this, if the serialization task -fails for any reason, it will be re-scheduled to be serialized on the -main thread - with the hopes that the reason it failed was due to a plugin -and not an error with the save code itself. Like vanilla code - if the -serialization fails, the chunk data is lost. - -Asynchronous chunk io/loading - -Mojang's current implementation for loading chunk data off disk is -to return a CompletableFuture that will be completed by scheduling a -task to be executed on the world's chunk queue (which is only drained -on the main thread). This task will read the IO off disk and it will -apply data conversions & deserialization synchronously. Obviously -all 3 of these operations are expensive however all can be completed -asynchronously instead. - -The solution this patch uses is as follows: - -0. If an asynchronous chunk save is in progress (see above), wait -for that task to complete. It will use the serialized NBTTagCompound -created by the task. If the task fails to complete, then we would continue -with step 1. If it does not, we skip step 1. (Note: We actually load -POI data no matter what in this case). -1. Schedule an IO task to read chunk & poi data off disk. -2. The IO task will schedule a chunk load task. -3. The chunk load task executes on the async chunk loader threads -and will apply datafixers & de-serialize the chunk into a ProtoChunk -or ProtoChunkExtension. -4. The in progress chunk is then passed on to the world's chunk queue -to complete the ComletableFuture and execute any of the synchronous -tasks required to be executed by the chunk load task (i.e lighting -and some poi tasks). - -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -index fa154ed68187a2020e814db6345a8cc1119ab4ba..2da28784ee427001b1137c859f0b4c350abd3110 100644 ---- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -58,6 +58,17 @@ public class WorldTimingsHandler { - - public final Timing miscMobSpawning; - -+ public final Timing poiUnload; -+ public final Timing chunkUnload; -+ public final Timing poiSaveDataSerialization; -+ public final Timing chunkSave; -+ public final Timing chunkSaveOverwriteCheck; -+ public final Timing chunkSaveDataSerialization; -+ public final Timing chunkSaveIOWait; -+ public final Timing chunkUnloadPrepareSave; -+ public final Timing chunkUnloadPOISerialization; -+ public final Timing chunkUnloadDataSave; -+ - public WorldTimingsHandler(World server) { - String name = ((WorldDataServer) server.getWorldData()).getName() + " - "; - -@@ -111,6 +122,17 @@ public class WorldTimingsHandler { - - - miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ -+ poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); -+ chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); -+ poiSaveDataSerialization = Timings.ofSafe(name + "Chunk save - POI Data serialization"); -+ chunkSave = Timings.ofSafe(name + "Chunk save - Chunk"); -+ chunkSaveOverwriteCheck = Timings.ofSafe(name + "Chunk save - Chunk Overwrite Check"); -+ chunkSaveDataSerialization = Timings.ofSafe(name + "Chunk save - Chunk Data serialization"); -+ chunkSaveIOWait = Timings.ofSafe(name + "Chunk save - Chunk IO Wait"); -+ chunkUnloadPrepareSave = Timings.ofSafe(name + "Chunk unload - Async Save Prepare"); -+ chunkUnloadPOISerialization = Timings.ofSafe(name + "Chunk unload - POI Data Serialization"); -+ chunkUnloadDataSave = Timings.ofSafe(name + "Chunk unload - Data Serialization"); - } - - public static Timing getTickList(WorldServer worldserver, String timingsType) { -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index a7a02072e5c7ce62cbecbb638fcc74abf2fb57ee..f657e9b6bb3d24a6c77ef584711a003d1eea0341 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper; - -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; - import com.google.common.base.Functions; - import com.google.common.base.Joiner; - import com.google.common.collect.ImmutableSet; -@@ -43,7 +44,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); - - public PaperCommand(String name) { - super(name); -@@ -155,6 +156,9 @@ public class PaperCommand extends Command { - case "debug": - doDebug(sender, args); - break; -+ case "dumpwaiting": -+ ChunkTaskManager.dumpAllChunkLoadInfo(); -+ break; - case "chunkinfo": - doChunkInfo(sender, args); - break; -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 469f78775b03cf363d88e35c69c0dc185c22547c..8bf4d2b8c38c02d6a5b2fea37113689a252f1571 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper; - -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; - import com.google.common.base.Strings; - import com.google.common.base.Throwables; - -@@ -352,4 +353,54 @@ public class PaperConfig { - maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); - maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); - } -+ -+ public static boolean asyncChunks = false; -+ private static void asyncChunks() { -+ ConfigurationSection section; -+ if (version < 15) { -+ section = config.createSection("settings.async-chunks"); -+ section.set("threads", -1); -+ } else { -+ section = config.getConfigurationSection("settings.async-chunks"); -+ if (section == null) { -+ section = config.createSection("settings.async-chunks"); -+ } -+ } -+ // Clean up old configs -+ if (section.contains("load-threads")) { -+ if (!section.contains("threads")) { -+ section.set("threads", section.get("load-threads")); -+ } -+ section.set("load-threads", null); -+ } -+ section.set("generation", null); -+ section.set("enabled", null); -+ section.set("thread-per-world-generation", null); -+ -+ int threads = getInt("settings.async-chunks.threads", -1); -+ int cpus = Runtime.getRuntime().availableProcessors(); -+ if (threads <= 0) { -+ threads = (int) Math.min(Integer.getInteger("paper.maxChunkThreads", 8), Math.max(1, cpus - 1)); -+ } -+ if (cpus == 1 && !Boolean.getBoolean("Paper.allowAsyncChunksSingleCore")) { -+ asyncChunks = false; -+ } else { -+ asyncChunks = true; -+ } -+ -+ // Let Shared Host set some limits -+ String sharedHostThreads = System.getenv("PAPER_ASYNC_CHUNKS_SHARED_HOST_THREADS"); -+ if (sharedHostThreads != null) { -+ try { -+ threads = Math.max(1, Math.min(threads, Integer.parseInt(sharedHostThreads))); -+ } catch (NumberFormatException ignored) {} -+ } -+ -+ if (!asyncChunks) { -+ log("Async Chunks: Disabled - Chunks will be managed synchronously, and will cause tremendous lag."); -+ } else { -+ ChunkTaskManager.initGlobalLoadThreads(threads); -+ log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/io/IOUtil.java b/src/main/java/com/destroystokyo/paper/io/IOUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5af0ac3d9e87c06053e65433060f15779c156c2a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/IOUtil.java -@@ -0,0 +1,62 @@ -+package com.destroystokyo.paper.io; -+ -+import org.bukkit.Bukkit; -+ -+public final class IOUtil { -+ -+ /* Copied from concrete or concurrentutil */ -+ -+ public static long getCoordinateKey(final int x, final int z) { -+ return ((long)z << 32) | (x & 0xFFFFFFFFL); -+ } -+ -+ public static int getCoordinateX(final long key) { -+ return (int)key; -+ } -+ -+ public static int getCoordinateZ(final long key) { -+ return (int)(key >>> 32); -+ } -+ -+ public static int getRegionCoordinate(final int chunkCoordinate) { -+ return chunkCoordinate >> 5; -+ } -+ -+ public static int getChunkInRegion(final int chunkCoordinate) { -+ return chunkCoordinate & 31; -+ } -+ -+ public static String genericToString(final Object object) { -+ return object == null ? "null" : object.getClass().getName() + ":" + object.toString(); -+ } -+ -+ public static T notNull(final T obj) { -+ if (obj == null) { -+ throw new NullPointerException(); -+ } -+ return obj; -+ } -+ -+ public static T notNull(final T obj, final String msgIfNull) { -+ if (obj == null) { -+ throw new NullPointerException(msgIfNull); -+ } -+ return obj; -+ } -+ -+ public static void arrayBounds(final int off, final int len, final int arrayLength, final String msgPrefix) { -+ if (off < 0 || len < 0 || (arrayLength - off) < len) { -+ throw new ArrayIndexOutOfBoundsException(msgPrefix + ": off: " + off + ", len: " + len + ", array length: " + arrayLength); -+ } -+ } -+ -+ public static int getPriorityForCurrentThread() { -+ return Bukkit.isPrimaryThread() ? PrioritizedTaskQueue.HIGHEST_PRIORITY : PrioritizedTaskQueue.NORMAL_PRIORITY; -+ } -+ -+ @SuppressWarnings("unchecked") -+ public static void rethrow(final Throwable throwable) throws T { -+ throw (T)throwable; -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9fe91f9512ee8c2589fc8da76bda5f6d70c9fac4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java -@@ -0,0 +1,606 @@ -+package com.destroystokyo.paper.io; -+ -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.chunk.storage.RegionFile; -+import org.apache.logging.log4j.Logger; -+ -+import java.io.IOException; -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.atomic.AtomicLong; -+import java.util.function.Consumer; -+import java.util.function.Function; -+ -+/** -+ * Prioritized singleton thread responsible for all chunk IO that occurs in a minecraft server. -+ * -+ *

    -+ * Singleton access: {@link Holder#INSTANCE} -+ *

    -+ * -+ *

    -+ * All functions provided are MT-Safe, however certain ordering constraints are (but not enforced): -+ *

  • -+ * Chunk saves may not occur for unloaded chunks. -+ *
  • -+ *
  • -+ * Tasks must be scheduled on the main thread. -+ *
  • -+ *

    -+ * -+ * @see Holder#INSTANCE -+ * @see #scheduleSave(WorldServer, int, int, NBTTagCompound, NBTTagCompound, int) -+ * @see #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean) -+ */ -+public final class PaperFileIOThread extends QueueExecutorThread { -+ -+ public static final Logger LOGGER = MinecraftServer.LOGGER; -+ public static final NBTTagCompound FAILURE_VALUE = new NBTTagCompound(); -+ -+ public static final class Holder { -+ -+ public static final PaperFileIOThread INSTANCE = new PaperFileIOThread(); -+ -+ static { -+ INSTANCE.start(); -+ } -+ } -+ -+ private final AtomicLong writeCounter = new AtomicLong(); -+ -+ private PaperFileIOThread() { -+ super(new PrioritizedTaskQueue<>(), (int)(1.0e6)); // 1.0ms spinwait time -+ this.setName("Paper RegionFile IO Thread"); -+ this.setPriority(Thread.NORM_PRIORITY - 1); // we keep priority close to normal because threads can wait on us -+ this.setUncaughtExceptionHandler((final Thread unused, final Throwable thr) -> { -+ LOGGER.fatal("Uncaught exception thrown from IO thread, report this!", thr); -+ }); -+ } -+ -+ /* run() is implemented by superclass */ -+ -+ /* -+ * -+ * IO thread will perform reads before writes -+ * -+ * How reads/writes are scheduled: -+ * -+ * If read in progress while scheduling write, ignore read and schedule write -+ * If read in progress while scheduling read (no write in progress), chain the read task -+ * -+ * -+ * If write in progress while scheduling read, use the pending write data and ret immediately -+ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data -+ * -+ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however -+ * it fails to properly propagate write failures. When writes fail the data is kept so future reads will actually -+ * read the failed write data. This should hopefully act as a way to prevent data loss for spurious fails for writing data. -+ * -+ */ -+ -+ /** -+ * Attempts to bump the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority level to try to bump to -+ */ -+ public void bumpPriority(final WorldServer world, final int chunkX, final int chunkZ, final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); -+ -+ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); -+ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); -+ -+ if (poiTask != null) { -+ poiTask.raisePriority(priority); -+ } -+ if (chunkTask != null) { -+ chunkTask.raisePriority(priority); -+ } -+ } -+ -+ public NBTTagCompound getPendingWrite(final WorldServer world, final int chunkX, final int chunkZ, final boolean poiData) { -+ final ChunkDataController taskController = poiData ? world.poiDataController : world.chunkDataController; -+ -+ final ChunkDataTask dataTask = taskController.tasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); -+ -+ if (dataTask == null) { -+ return null; -+ } -+ -+ final ChunkDataController.InProgressWrite write = dataTask.inProgressWrite; -+ -+ if (write == null) { -+ return null; -+ } -+ -+ return write.data; -+ } -+ -+ /** -+ * Sets the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority level to set to -+ */ -+ public void setPriority(final WorldServer world, final int chunkX, final int chunkZ, final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); -+ -+ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); -+ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); -+ -+ if (poiTask != null) { -+ poiTask.updatePriority(priority); -+ } -+ if (chunkTask != null) { -+ chunkTask.updatePriority(priority); -+ } -+ } -+ -+ /** -+ * Schedules the chunk data to be written asynchronously. -+ *

    -+ * Impl notes: -+ *

    -+ *
  • -+ * This function presumes a chunk load for the coordinates is not called during this function (anytime after is OK). This means -+ * saves must be scheduled before a chunk is unloaded. -+ *
  • -+ *
  • -+ * Writes may be called concurrently, although only the "later" write will go through. -+ *
  • -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param poiData Chunk point of interest data. If {@code null}, then no poi data is saved. -+ * @param chunkData Chunk data. If {@code null}, then no chunk data is saved. -+ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} -+ * @throws IllegalArgumentException If both {@code poiData} and {@code chunkData} are {@code null}. -+ * @throws IllegalStateException If the file io thread has shutdown. -+ */ -+ public void scheduleSave(final WorldServer world, final int chunkX, final int chunkZ, -+ final NBTTagCompound poiData, final NBTTagCompound chunkData, -+ final int priority) throws IllegalArgumentException { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ final long writeCounter = this.writeCounter.getAndIncrement(); -+ -+ if (poiData != null) { -+ this.scheduleWrite(world.poiDataController, world, chunkX, chunkZ, poiData, priority, writeCounter); -+ } -+ if (chunkData != null) { -+ this.scheduleWrite(world.chunkDataController, world, chunkX, chunkZ, chunkData, priority, writeCounter); -+ } -+ } -+ -+ private void scheduleWrite(final ChunkDataController dataController, final WorldServer world, -+ final int chunkX, final int chunkZ, final NBTTagCompound data, final int priority, final long writeCounter) { -+ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask taskRunning) -> { -+ if (taskRunning == null) { -+ // no task is scheduled -+ -+ // create task -+ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); -+ newTask.inProgressWrite = new ChunkDataController.InProgressWrite(); -+ newTask.inProgressWrite.writeCounter = writeCounter; -+ newTask.inProgressWrite.data = data; -+ -+ PaperFileIOThread.this.queueTask(newTask); // schedule -+ return newTask; -+ } -+ -+ taskRunning.raisePriority(priority); -+ -+ if (taskRunning.inProgressWrite == null) { -+ taskRunning.inProgressWrite = new ChunkDataController.InProgressWrite(); -+ } -+ -+ boolean reschedule = taskRunning.inProgressWrite.writeCounter == -1L; -+ -+ // synchronize for readers -+ //noinspection SynchronizationOnLocalVariableOrMethodParameter -+ synchronized (taskRunning) { -+ taskRunning.inProgressWrite.data = data; -+ taskRunning.inProgressWrite.writeCounter = writeCounter; -+ } -+ -+ if (reschedule) { -+ // We need to reschedule this task since the previous one is not currently scheduled since it failed -+ taskRunning.reschedule(priority); -+ } -+ -+ return taskRunning; -+ }); -+ } -+ -+ /** -+ * Same as {@link #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns -+ * a {@link CompletableFuture} which is potentially completed ASYNCHRONOUSLY ON THE FILE IO THREAD when the load task -+ * has completed. -+ *

    -+ * Note that if the chunk fails to load the returned future is completed with {@code null}. -+ *

    -+ */ -+ public CompletableFuture loadChunkDataAsyncFuture(final WorldServer world, final int chunkX, final int chunkZ, -+ final int priority, final boolean readPoiData, final boolean readChunkData, -+ final boolean intendingToBlock) { -+ final CompletableFuture future = new CompletableFuture<>(); -+ this.loadChunkDataAsync(world, chunkX, chunkZ, priority, future::complete, readPoiData, readChunkData, intendingToBlock); -+ return future; -+ } -+ -+ /** -+ * Schedules a load to be executed asynchronously. -+ *

    -+ * Impl notes: -+ *

    -+ *
  • -+ * If a chunk fails to load, the {@code onComplete} parameter is completed with {@code null}. -+ *
  • -+ *
  • -+ * It is possible for the {@code onComplete} parameter to be given {@link ChunkData} containing data -+ * this call did not request. -+ *
  • -+ *
  • -+ * The {@code onComplete} parameter may be completed during the execution of this function synchronously or it may -+ * be completed asynchronously on this file io thread. Interacting with the file IO thread in the completion of -+ * data is undefined behaviour, and can cause deadlock. -+ *
  • -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} -+ * @param onComplete Consumer to execute once this task has completed -+ * @param readPoiData Whether to read point of interest data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. -+ * @param readChunkData Whether to read chunk data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. -+ * @return The {@link PrioritizedTaskQueue.PrioritizedTask} associated with this task. Note that this task does not support -+ * cancellation. -+ */ -+ public void loadChunkDataAsync(final WorldServer world, final int chunkX, final int chunkZ, -+ final int priority, final Consumer onComplete, -+ final boolean readPoiData, final boolean readChunkData, -+ final boolean intendingToBlock) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ if (!(readPoiData | readChunkData)) { -+ throw new IllegalArgumentException("Must read chunk data or poi data"); -+ } -+ -+ final ChunkData complete = new ChunkData(); -+ final boolean[] requireCompletion = new boolean[] { readPoiData, readChunkData }; -+ -+ if (readPoiData) { -+ this.scheduleRead(world.poiDataController, world, chunkX, chunkZ, (final NBTTagCompound poiData) -> { -+ complete.poiData = poiData; -+ -+ final boolean finished; -+ -+ // avoid a race condition where the file io thread completes and we complete synchronously -+ // Note: Synchronization can be elided if both of the accesses are volatile -+ synchronized (requireCompletion) { -+ requireCompletion[0] = false; // 0 -> poi data -+ finished = !requireCompletion[1]; // 1 -> chunk data -+ } -+ -+ if (finished) { -+ onComplete.accept(complete); -+ } -+ }, priority, intendingToBlock); -+ } -+ -+ if (readChunkData) { -+ this.scheduleRead(world.chunkDataController, world, chunkX, chunkZ, (final NBTTagCompound chunkData) -> { -+ complete.chunkData = chunkData; -+ -+ final boolean finished; -+ -+ // avoid a race condition where the file io thread completes and we complete synchronously -+ // Note: Synchronization can be elided if both of the accesses are volatile -+ synchronized (requireCompletion) { -+ requireCompletion[1] = false; // 1 -> chunk data -+ finished = !requireCompletion[0]; // 0 -> poi data -+ } -+ -+ if (finished) { -+ onComplete.accept(complete); -+ } -+ }, priority, intendingToBlock); -+ } -+ -+ } -+ -+ // Note: the onComplete may be called asynchronously or synchronously here. -+ private void scheduleRead(final ChunkDataController dataController, final WorldServer world, -+ final int chunkX, final int chunkZ, final Consumer onComplete, final int priority, -+ final boolean intendingToBlock) { -+ -+ Function tryLoadFunction = (final RegionFile file) -> { -+ if (file == null) { -+ return Boolean.TRUE; -+ } -+ return Boolean.valueOf(file.chunkExists(new ChunkCoordIntPair(chunkX, chunkZ))); -+ }; -+ -+ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask running) -> { -+ if (running == null) { -+ // not scheduled -+ -+ final Boolean shouldSchedule = intendingToBlock ? dataController.computeForRegionFile(chunkX, chunkZ, tryLoadFunction) : -+ dataController.computeForRegionFileIfLoaded(chunkX, chunkZ, tryLoadFunction); -+ -+ if (shouldSchedule == Boolean.FALSE) { -+ // not on disk -+ onComplete.accept(null); -+ return null; -+ } -+ -+ // set up task -+ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); -+ newTask.inProgressRead = new ChunkDataController.InProgressRead(); -+ newTask.inProgressRead.readFuture.thenAccept(onComplete); -+ -+ PaperFileIOThread.this.queueTask(newTask); // schedule task -+ return newTask; -+ } -+ -+ running.raisePriority(priority); -+ -+ if (running.inProgressWrite == null) { -+ // chain to the read future -+ running.inProgressRead.readFuture.thenAccept(onComplete); -+ return running; -+ } -+ -+ // at this stage we have to use the in progress write's data to avoid an order issue -+ // we don't synchronize since all writes to data occur in the compute() call -+ onComplete.accept(running.inProgressWrite.data); -+ return running; -+ }); -+ } -+ -+ /** -+ * Same as {@link #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns -+ * the {@link ChunkData} associated with the specified chunk when the task is complete. -+ * @return The chunk data, or {@code null} if the chunk failed to load. -+ */ -+ public ChunkData loadChunkData(final WorldServer world, final int chunkX, final int chunkZ, final int priority, -+ final boolean readPoiData, final boolean readChunkData) { -+ return this.loadChunkDataAsyncFuture(world, chunkX, chunkZ, priority, readPoiData, readChunkData, true).join(); -+ } -+ -+ /** -+ * Schedules the given task at the specified priority to be executed on the IO thread. -+ *

    -+ * Internal api. Do not use. -+ *

    -+ */ -+ public void runTask(final int priority, final Runnable runnable) { -+ this.queueTask(new GeneralTask(priority, runnable)); -+ } -+ -+ static final class GeneralTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { -+ -+ private final Runnable run; -+ -+ public GeneralTask(final int priority, final Runnable run) { -+ super(priority); -+ this.run = IOUtil.notNull(run, "Task may not be null"); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ this.run.run(); -+ } catch (final Throwable throwable) { -+ if (throwable instanceof ThreadDeath) { -+ throw (ThreadDeath)throwable; -+ } -+ LOGGER.fatal("Failed to execute general task on IO thread " + IOUtil.genericToString(this.run), throwable); -+ } -+ } -+ } -+ -+ public static final class ChunkData { -+ -+ public NBTTagCompound poiData; -+ public NBTTagCompound chunkData; -+ -+ public ChunkData() {} -+ -+ public ChunkData(final NBTTagCompound poiData, final NBTTagCompound chunkData) { -+ this.poiData = poiData; -+ this.chunkData = chunkData; -+ } -+ } -+ -+ public static abstract class ChunkDataController { -+ -+ // ConcurrentHashMap synchronizes per chain, so reduce the chance of task's hashes colliding. -+ public final ConcurrentHashMap tasks = new ConcurrentHashMap<>(64, 0.5f); -+ -+ public abstract void writeData(final int x, final int z, final NBTTagCompound compound) throws IOException; -+ public abstract NBTTagCompound readData(final int x, final int z) throws IOException; -+ -+ public abstract T computeForRegionFile(final int chunkX, final int chunkZ, final Function function); -+ public abstract T computeForRegionFileIfLoaded(final int chunkX, final int chunkZ, final Function function); -+ -+ public static final class InProgressWrite { -+ public long writeCounter; -+ public NBTTagCompound data; -+ } -+ -+ public static final class InProgressRead { -+ public final CompletableFuture readFuture = new CompletableFuture<>(); -+ } -+ } -+ -+ public static final class ChunkDataTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { -+ -+ public ChunkDataController.InProgressWrite inProgressWrite; -+ public ChunkDataController.InProgressRead inProgressRead; -+ -+ private final WorldServer world; -+ private final int x; -+ private final int z; -+ private final ChunkDataController taskController; -+ -+ public ChunkDataTask(final int priority, final WorldServer world, final int x, final int z, final ChunkDataController taskController) { -+ super(priority); -+ this.world = world; -+ this.x = x; -+ this.z = z; -+ this.taskController = taskController; -+ } -+ -+ @Override -+ public String toString() { -+ return "Task for world: '" + this.world.getWorld().getName() + "' at " + this.x + "," + this.z + -+ " poi: " + (this.taskController == this.world.poiDataController) + ", hash: " + this.hashCode(); -+ } -+ -+ /* -+ * -+ * IO thread will perform reads before writes -+ * -+ * How reads/writes are scheduled: -+ * -+ * If read in progress while scheduling write, ignore read and schedule write -+ * If read in progress while scheduling read (no write in progress), chain the read task -+ * -+ * -+ * If write in progress while scheduling read, use the pending write data and ret immediately -+ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data -+ * -+ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however -+ * it fails to properly propagate write failures -+ * -+ */ -+ -+ void reschedule(final int priority) { -+ // priority is checked before this stage // TODO what -+ this.queue.lazySet(null); -+ this.priority.lazySet(priority); -+ PaperFileIOThread.Holder.INSTANCE.queueTask(this); -+ } -+ -+ @Override -+ public void run() { -+ ChunkDataController.InProgressRead read = this.inProgressRead; -+ if (read != null) { -+ NBTTagCompound compound = PaperFileIOThread.FAILURE_VALUE; -+ try { -+ compound = this.taskController.readData(this.x, this.z); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ LOGGER.fatal("Failed to read chunk data for task: " + this.toString(), thr); -+ // fall through to complete with null data -+ } -+ read.readFuture.complete(compound); -+ } -+ -+ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(this.x, this.z)); -+ -+ ChunkDataController.InProgressWrite write = this.inProgressWrite; -+ -+ if (write == null) { -+ // IntelliJ warns this is invalid, however it does not consider that writes to the task map & the inProgress field can occur concurrently. -+ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { -+ if (valueInMap == null) { -+ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); -+ } -+ if (valueInMap != ChunkDataTask.this) { -+ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); -+ } -+ return valueInMap.inProgressWrite == null ? null : valueInMap; -+ }); -+ -+ if (inMap == null) { -+ return; // set the task value to null, indicating we're done -+ } -+ -+ // not null, which means there was a concurrent write -+ write = this.inProgressWrite; -+ } -+ -+ // check if another process is writing -+ /*try { TODO: Can we restore this? -+ ((WorldServer)this.world).checkSession(); -+ } catch (final Exception ex) { -+ LOGGER.fatal("Couldn't save chunk; already in use by another instance of Minecraft?", ex); -+ // we don't need to set the write counter to -1 as we know at this stage there's no point in re-scheduling -+ // writes since they'll fail anyways. -+ return; -+ } -+*/ -+ for (;;) { -+ final long writeCounter; -+ final NBTTagCompound data; -+ -+ //noinspection SynchronizationOnLocalVariableOrMethodParameter -+ synchronized (write) { -+ writeCounter = write.writeCounter; -+ data = write.data; -+ } -+ -+ boolean failedWrite = false; -+ -+ try { -+ this.taskController.writeData(this.x, this.z, data); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ LOGGER.fatal("Failed to write chunk data for task: " + this.toString(), thr); -+ failedWrite = true; -+ } -+ -+ boolean finalFailWrite = failedWrite; -+ -+ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { -+ if (valueInMap == null) { -+ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); -+ } -+ if (valueInMap != ChunkDataTask.this) { -+ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); -+ } -+ if (valueInMap.inProgressWrite.writeCounter == writeCounter) { -+ if (finalFailWrite) { -+ valueInMap.inProgressWrite.writeCounter = -1L; -+ } -+ -+ return null; -+ } -+ return valueInMap; -+ // Hack end -+ }); -+ -+ if (inMap == null) { -+ // write counter matched, so we wrote the most up-to-date pending data, we're done here -+ // or we failed to write and successfully set the write counter to -1 -+ return; // we're done here -+ } -+ -+ // fetch & write new data -+ continue; -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java -new file mode 100644 -index 0000000000000000000000000000000000000000..97f2e433c483f1ebd7500ae142269e144ef5fda4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java -@@ -0,0 +1,277 @@ -+package com.destroystokyo.paper.io; -+ -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.concurrent.atomic.AtomicInteger; -+import java.util.concurrent.atomic.AtomicReference; -+ -+public class PrioritizedTaskQueue { -+ -+ // lower numbers are a higher priority (except < 0) -+ // higher priorities are always executed before lower priorities -+ -+ /** -+ * Priority value indicating the task has completed or is being completed. -+ */ -+ public static final int COMPLETING_PRIORITY = -1; -+ -+ /** -+ * Highest priority, should only be used for main thread tasks or tasks that are blocking the main thread. -+ */ -+ public static final int HIGHEST_PRIORITY = 0; -+ -+ /** -+ * Should be only used in an IO task so that chunk loads do not wait on other IO tasks. -+ * This only exists because IO tasks are scheduled before chunk load tasks to decrease IO waiting times. -+ */ -+ public static final int HIGHER_PRIORITY = 1; -+ -+ /** -+ * Should be used for scheduling chunk loads/generation that would increase response times to users. -+ */ -+ public static final int HIGH_PRIORITY = 2; -+ -+ /** -+ * Default priority. -+ */ -+ public static final int NORMAL_PRIORITY = 3; -+ -+ /** -+ * Use for tasks not at all critical and can potentially be delayed. -+ */ -+ public static final int LOW_PRIORITY = 4; -+ -+ /** -+ * Use for tasks that should "eventually" execute. -+ */ -+ public static final int LOWEST_PRIORITY = 5; -+ -+ private static final int TOTAL_PRIORITIES = 6; -+ -+ final ConcurrentLinkedQueue[] queues = (ConcurrentLinkedQueue[])new ConcurrentLinkedQueue[TOTAL_PRIORITIES]; -+ -+ private final AtomicBoolean shutdown = new AtomicBoolean(); -+ -+ { -+ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { -+ this.queues[i] = new ConcurrentLinkedQueue<>(); -+ } -+ } -+ -+ /** -+ * Returns whether the specified priority is valid -+ */ -+ public static boolean validPriority(final int priority) { -+ return priority >= 0 && priority < TOTAL_PRIORITIES; -+ } -+ -+ /** -+ * Queues a task. -+ * @throws IllegalStateException If the task has already been queued. Use {@link PrioritizedTask#raisePriority(int)} to -+ * raise a task's priority. -+ * This can also be thrown if the queue has shutdown. -+ */ -+ public void add(final T task) throws IllegalStateException { -+ int priority = task.getPriority(); -+ if (priority != COMPLETING_PRIORITY) { -+ task.setQueue(this); -+ this.queues[priority].add(task); -+ } -+ if (this.shutdown.get()) { -+ // note: we're not actually sure at this point if our task will go through -+ throw new IllegalStateException("Queue has shutdown, refusing to execute task " + IOUtil.genericToString(task)); -+ } -+ } -+ -+ /** -+ * Polls the highest priority task currently available. {@code null} if none. -+ */ -+ public T poll() { -+ T task; -+ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { -+ final ConcurrentLinkedQueue queue = this.queues[i]; -+ -+ while ((task = queue.poll()) != null) { -+ final int prevPriority = task.tryComplete(i); -+ if (prevPriority != COMPLETING_PRIORITY && prevPriority <= i) { -+ // if the prev priority was greater-than or equal to our current priority -+ return task; -+ } -+ } -+ } -+ -+ return null; -+ } -+ -+ /** -+ * Returns whether this queue may have tasks queued. -+ *

    -+ * This operation is not atomic, but is MT-Safe. -+ *

    -+ * @return {@code true} if tasks may be queued, {@code false} otherwise -+ */ -+ public boolean hasTasks() { -+ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { -+ final ConcurrentLinkedQueue queue = this.queues[i]; -+ -+ if (queue.peek() != null) { -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ /** -+ * Prevent further additions to this queue. Attempts to add after this call has completed (potentially during) will -+ * result in {@link IllegalStateException} being thrown. -+ *

    -+ * This operation is atomic with respect to other shutdown calls -+ *

    -+ *

    -+ * After this call has completed, regardless of return value, this queue will be shutdown. -+ *

    -+ * @return {@code true} if the queue was shutdown, {@code false} if it has shut down already -+ */ -+ public boolean shutdown() { -+ return this.shutdown.getAndSet(false); -+ } -+ -+ public abstract static class PrioritizedTask { -+ -+ protected final AtomicReference queue = new AtomicReference<>(); -+ -+ protected final AtomicInteger priority; -+ -+ protected PrioritizedTask() { -+ this(PrioritizedTaskQueue.NORMAL_PRIORITY); -+ } -+ -+ protected PrioritizedTask(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority " + priority); -+ } -+ this.priority = new AtomicInteger(priority); -+ } -+ -+ /** -+ * Returns the current priority. Note that {@link PrioritizedTaskQueue#COMPLETING_PRIORITY} will be returned -+ * if this task is completing or has completed. -+ */ -+ public final int getPriority() { -+ return this.priority.get(); -+ } -+ -+ /** -+ * Returns whether this task is scheduled to execute, or has been already executed. -+ */ -+ public boolean isScheduled() { -+ return this.queue.get() != null; -+ } -+ -+ final int tryComplete(final int minPriority) { -+ for (int curr = this.getPriorityVolatile();;) { -+ if (curr == COMPLETING_PRIORITY) { -+ return COMPLETING_PRIORITY; -+ } -+ if (curr > minPriority) { -+ // curr is lower priority -+ return curr; -+ } -+ -+ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, COMPLETING_PRIORITY))) { -+ return curr; -+ } -+ continue; -+ } -+ } -+ -+ /** -+ * Forces this task to be completed. -+ * @return {@code true} if the task was cancelled, {@code false} if the task has already completed or is being completed. -+ */ -+ public boolean cancel() { -+ return this.exchangePriorityVolatile(PrioritizedTaskQueue.COMPLETING_PRIORITY) != PrioritizedTaskQueue.COMPLETING_PRIORITY; -+ } -+ -+ /** -+ * Attempts to raise the priority to the priority level specified. -+ * @param priority Priority specified -+ * @return {@code true} if successful, {@code false} otherwise. -+ */ -+ public boolean raisePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority"); -+ } -+ -+ for (int curr = this.getPriorityVolatile();;) { -+ if (curr == COMPLETING_PRIORITY) { -+ return false; -+ } -+ if (priority >= curr) { -+ return true; -+ } -+ -+ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { -+ PrioritizedTaskQueue queue = this.queue.get(); -+ if (queue != null) { -+ //noinspection unchecked -+ queue.queues[priority].add(this); // silently fail on shutdown -+ } -+ return true; -+ } -+ continue; -+ } -+ } -+ -+ /** -+ * Attempts to set this task's priority level to the level specified. -+ * @param priority Specified priority level. -+ * @return {@code true} if successful, {@code false} if this task is completing or has completed. -+ */ -+ public boolean updatePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority"); -+ } -+ -+ for (int curr = this.getPriorityVolatile();;) { -+ if (curr == COMPLETING_PRIORITY) { -+ return false; -+ } -+ if (curr == priority) { -+ return true; -+ } -+ -+ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { -+ PrioritizedTaskQueue queue = this.queue.get(); -+ if (queue != null) { -+ //noinspection unchecked -+ queue.queues[priority].add(this); // silently fail on shutdown -+ } -+ return true; -+ } -+ continue; -+ } -+ } -+ -+ void setQueue(final PrioritizedTaskQueue queue) { -+ this.queue.set(queue); -+ } -+ -+ /* priority */ -+ -+ protected final int getPriorityVolatile() { -+ return this.priority.get(); -+ } -+ -+ protected final int compareAndExchangePriorityVolatile(final int expect, final int update) { -+ if (this.priority.compareAndSet(expect, update)) { -+ return expect; -+ } -+ return this.priority.get(); -+ } -+ -+ protected final int exchangePriorityVolatile(final int value) { -+ return this.priority.getAndSet(value); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ee906b594b306906c170180a29a8b61997d05168 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java -@@ -0,0 +1,241 @@ -+package com.destroystokyo.paper.io; -+ -+import net.minecraft.server.MinecraftServer; -+import org.apache.logging.log4j.Logger; -+ -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.concurrent.locks.LockSupport; -+ -+public class QueueExecutorThread extends Thread { -+ -+ private static final Logger LOGGER = MinecraftServer.LOGGER; -+ -+ protected final PrioritizedTaskQueue queue; -+ protected final long spinWaitTime; -+ -+ protected volatile boolean closed; -+ -+ protected final AtomicBoolean parked = new AtomicBoolean(); -+ -+ protected volatile ConcurrentLinkedQueue flushQueue = new ConcurrentLinkedQueue<>(); -+ protected volatile long flushCycles; -+ -+ public QueueExecutorThread(final PrioritizedTaskQueue queue) { -+ this(queue, (int)(1.e6)); // 1.0ms -+ } -+ -+ public QueueExecutorThread(final PrioritizedTaskQueue queue, final long spinWaitTime) { // in ms -+ this.queue = queue; -+ this.spinWaitTime = spinWaitTime; -+ } -+ -+ @Override -+ public void run() { -+ final long spinWaitTime = this.spinWaitTime; -+ main_loop: -+ for (;;) { -+ this.pollTasks(true); -+ -+ // spinwait -+ -+ final long start = System.nanoTime(); -+ -+ for (;;) { -+ // If we are interrpted for any reason, park() will always return immediately. Clear so that we don't needlessly use cpu in such an event. -+ Thread.interrupted(); -+ LockSupport.parkNanos("Spinwaiting on tasks", 1000L); // 1us -+ -+ if (this.pollTasks(true)) { -+ // restart loop, found tasks -+ continue main_loop; -+ } -+ -+ if (this.handleClose()) { -+ return; // we're done -+ } -+ -+ if ((System.nanoTime() - start) >= spinWaitTime) { -+ break; -+ } -+ } -+ -+ if (this.handleClose()) { -+ return; -+ } -+ -+ this.parked.set(true); -+ -+ // We need to parse here to avoid a race condition where a thread queues a task before we set parked to true -+ // (i.e it will not notify us) -+ if (this.pollTasks(true)) { -+ this.parked.set(false); -+ continue; -+ } -+ -+ if (this.handleClose()) { -+ return; -+ } -+ -+ // we don't need to check parked before sleeping, but we do need to check parked in a do-while loop -+ // LockSupport.park() can fail for any reason -+ do { -+ Thread.interrupted(); -+ LockSupport.park("Waiting on tasks"); -+ } while (this.parked.get()); -+ } -+ } -+ -+ protected boolean handleClose() { -+ if (this.closed) { -+ this.pollTasks(true); // this ensures we've emptied the queue -+ this.handleFlushThreads(true); -+ return true; -+ } -+ return false; -+ } -+ -+ protected boolean pollTasks(boolean flushTasks) { -+ Runnable task; -+ boolean ret = false; -+ -+ while ((task = this.queue.poll()) != null) { -+ ret = true; -+ try { -+ task.run(); -+ } catch (final Throwable throwable) { -+ if (throwable instanceof ThreadDeath) { -+ throw (ThreadDeath)throwable; -+ } -+ LOGGER.fatal("Exception thrown from prioritized runnable task in thread '" + this.getName() + "': " + IOUtil.genericToString(task), throwable); -+ } -+ } -+ -+ if (flushTasks) { -+ this.handleFlushThreads(false); -+ } -+ -+ return ret; -+ } -+ -+ protected void handleFlushThreads(final boolean shutdown) { -+ Thread parking; -+ ConcurrentLinkedQueue flushQueue = this.flushQueue; -+ do { -+ ++flushCycles; // may be plain read opaque write -+ while ((parking = flushQueue.poll()) != null) { -+ LockSupport.unpark(parking); -+ } -+ } while (this.pollTasks(false)); -+ -+ if (shutdown) { -+ this.flushQueue = null; -+ -+ // defend against a race condition where a flush thread double-checks right before we set to null -+ while ((parking = flushQueue.poll()) != null) { -+ LockSupport.unpark(parking); -+ } -+ } -+ } -+ -+ /** -+ * Notify's this thread that a task has been added to its queue -+ * @return {@code true} if this thread was waiting for tasks, {@code false} if it is executing tasks -+ */ -+ public boolean notifyTasks() { -+ if (this.parked.get() && this.parked.getAndSet(false)) { -+ LockSupport.unpark(this); -+ return true; -+ } -+ return false; -+ } -+ -+ protected void queueTask(final T task) { -+ this.queue.add(task); -+ this.notifyTasks(); -+ } -+ -+ /** -+ * Waits until this thread's queue is empty. -+ * -+ * @throws IllegalStateException If the current thread is {@code this} thread. -+ */ -+ public void flush() { -+ final Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread == this) { -+ // avoid deadlock -+ throw new IllegalStateException("Cannot flush the queue executor thread while on the queue executor thread"); -+ } -+ -+ // order is important -+ -+ int successes = 0; -+ long lastCycle = -1L; -+ -+ do { -+ final ConcurrentLinkedQueue flushQueue = this.flushQueue; -+ if (flushQueue == null) { -+ return; -+ } -+ -+ flushQueue.add(currentThread); -+ -+ // double check flush queue -+ if (this.flushQueue == null) { -+ return; -+ } -+ -+ final long currentCycle = this.flushCycles; // may be opaque read -+ -+ if (currentCycle == lastCycle) { -+ Thread.yield(); -+ continue; -+ } -+ -+ // force response -+ this.parked.set(false); -+ LockSupport.unpark(this); -+ -+ LockSupport.park("flushing queue executor thread"); -+ -+ // returns whether there are tasks queued, does not return whether there are tasks executing -+ // this is why we cycle twice twice through flush (we know a pollTask call is made after a flush cycle) -+ // we really only need to guarantee that the tasks this thread has queued has gone through, and can leave -+ // tasks queued concurrently that are unsychronized with this thread as undefined behavior -+ if (this.queue.hasTasks()) { -+ successes = 0; -+ } else { -+ ++successes; -+ } -+ -+ } while (successes != 2); -+ -+ } -+ -+ /** -+ * Closes this queue executor's queue and optionally waits for it to empty. -+ *

    -+ * If wait is {@code true}, then the queue will be empty by the time this call completes. -+ *

    -+ *

    -+ * This function is MT-Safe. -+ *

    -+ * @param wait If this call is to wait until the queue is empty -+ * @param killQueue Whether to shutdown this thread's queue -+ * @return whether this thread shut down the queue -+ */ -+ public boolean close(final boolean wait, final boolean killQueue) { -+ boolean ret = !killQueue ? false : this.queue.shutdown(); -+ this.closed = true; -+ -+ // force thread to respond to the shutdown -+ this.parked.set(false); -+ LockSupport.unpark(this); -+ -+ if (wait) { -+ this.flush(); -+ } -+ return ret; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9a2b51d005efc9d31b3685e8298fd00b341c7dc7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java -@@ -0,0 +1,146 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import co.aikar.timings.Timing; -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.IOUtil; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; -+ -+import java.util.ArrayDeque; -+import java.util.function.Consumer; -+ -+public final class ChunkLoadTask extends ChunkTask { -+ -+ public boolean cancelled; -+ -+ Consumer onComplete; -+ public PaperFileIOThread.ChunkData chunkData; -+ -+ private boolean hasCompleted; -+ -+ public ChunkLoadTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, -+ final ChunkTaskManager taskManager, -+ final Consumer onComplete) { -+ super(world, chunkX, chunkZ, priority, taskManager); -+ this.onComplete = onComplete; -+ } -+ -+ private static final ArrayDeque EMPTY_QUEUE = new ArrayDeque<>(); -+ -+ private static ChunkRegionLoader.InProgressChunkHolder createEmptyHolder() { -+ return new ChunkRegionLoader.InProgressChunkHolder(null, EMPTY_QUEUE); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ this.executeTask(); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.error("Failed to execute chunk load task: " + this.toString(), ex); -+ if (!this.hasCompleted) { -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ } -+ } -+ } -+ -+ private boolean checkCancelled() { -+ if (this.cancelled) { -+ // IntelliJ does not understand writes may occur to cancelled concurrently. -+ return this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != ChunkLoadTask.this) { -+ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); -+ } -+ -+ if (valueInMap.cancelled) { -+ return null; -+ } -+ return valueInMap; -+ }) == null; -+ } -+ return false; -+ } -+ -+ public void executeTask() { -+ if (this.checkCancelled()) { -+ return; -+ } -+ -+ // either executed synchronously or asynchronously -+ final PaperFileIOThread.ChunkData chunkData = this.chunkData; -+ -+ if (chunkData.poiData == PaperFileIOThread.FAILURE_VALUE || chunkData.chunkData == PaperFileIOThread.FAILURE_VALUE) { -+ PaperFileIOThread.LOGGER.error("Could not load chunk for task: " + this.toString() + ", file IO thread has dumped the relevant exception above"); -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ return; -+ } -+ -+ if (chunkData.chunkData == null) { -+ // not on disk -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ return; -+ } -+ -+ final ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(this.chunkX, this.chunkZ); -+ -+ final PlayerChunkMap chunkManager = this.world.getChunkProvider().playerChunkMap; -+ -+ try (Timing ignored = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { -+ final ChunkRegionLoader.InProgressChunkHolder chunkHolder; -+ -+ // apply fixes -+ -+ try { -+ chunkData.chunkData = chunkManager.getChunkData(this.world.getTypeKey(), -+ chunkManager.getWorldPersistentDataSupplier(), chunkData.chunkData, chunkPos, this.world); // clone data for safety, file IO thread does not clone -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.error("Could not apply datafixers for chunk task: " + this.toString(), ex); -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ } -+ -+ if (this.checkCancelled()) { -+ return; -+ } -+ -+ try { -+ this.world.getChunkProvider().playerChunkMap.updateChunkStatusOnDisk(chunkPos, chunkData.chunkData); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.warn("Failed to update chunk status cache for task: " + this.toString(), ex); -+ // non-fatal, continue -+ } -+ -+ try { -+ chunkHolder = ChunkRegionLoader.loadChunk(this.world, -+ chunkManager.definedStructureManager, chunkManager.getVillagePlace(), chunkPos, -+ chunkData.chunkData, true); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.error("Could not de-serialize chunk data for task: " + this.toString(), ex); -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ return; -+ } -+ -+ this.complete(chunkHolder); -+ } -+ } -+ -+ private void complete(final ChunkRegionLoader.InProgressChunkHolder holder) { -+ this.hasCompleted = true; -+ holder.poiData = this.chunkData == null ? null : this.chunkData.poiData; -+ -+ this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != ChunkLoadTask.this) { -+ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); -+ } -+ if (valueInMap.cancelled) { -+ return null; -+ } -+ try { -+ ChunkLoadTask.this.onComplete.accept(holder); -+ } catch (final Throwable thr) { -+ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); -+ } -+ return null; -+ }); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e3ad8f50b51c4e9bf38ffa5911444cc88d3f67eb ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java -@@ -0,0 +1,111 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import co.aikar.timings.Timing; -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.IOUtil; -+import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+ -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.atomic.AtomicInteger; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.chunk.IChunkAccess; -+import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; -+ -+public final class ChunkSaveTask extends ChunkTask { -+ -+ public final ChunkRegionLoader.AsyncSaveData asyncSaveData; -+ public final IChunkAccess chunk; -+ public final CompletableFuture onComplete = new CompletableFuture<>(); -+ -+ private final AtomicInteger attemptedPriority; -+ -+ public ChunkSaveTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, -+ final ChunkTaskManager taskManager, final ChunkRegionLoader.AsyncSaveData asyncSaveData, -+ final IChunkAccess chunk) { -+ super(world, chunkX, chunkZ, priority, taskManager); -+ this.chunk = chunk; -+ this.asyncSaveData = asyncSaveData; -+ this.attemptedPriority = new AtomicInteger(priority); -+ } -+ -+ @Override -+ public void run() { -+ // can be executed asynchronously or synchronously -+ final NBTTagCompound compound; -+ -+ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTimingIfSync()) { -+ compound = ChunkRegionLoader.saveChunk(this.world, this.chunk, this.asyncSaveData); -+ } catch (final Throwable ex) { -+ // has a plugin modified something it should not have and made us CME? -+ PaperFileIOThread.LOGGER.error("Failed to serialize unloading chunk data for task: " + this.toString() + ", falling back to a synchronous execution", ex); -+ -+ // Note: We add to the server thread queue here since this is what the server will drain tasks from -+ // when waiting for chunks -+ ChunkTaskManager.queueChunkWaitTask(() -> { -+ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTiming()) { -+ NBTTagCompound data = PaperFileIOThread.FAILURE_VALUE; -+ -+ try { -+ data = ChunkRegionLoader.saveChunk(this.world, this.chunk, this.asyncSaveData); -+ PaperFileIOThread.LOGGER.info("Successfully serialized chunk data for task: " + this.toString() + " synchronously"); -+ } catch (final Throwable ex1) { -+ PaperFileIOThread.LOGGER.fatal("Failed to synchronously serialize unloading chunk data for task: " + this.toString() + "! Chunk data will be lost", ex1); -+ } -+ -+ ChunkSaveTask.this.complete(data); -+ } -+ }); -+ -+ return; // the main thread will now complete the data -+ } -+ -+ this.complete(compound); -+ } -+ -+ @Override -+ public boolean raisePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalStateException("Invalid priority: " + priority); -+ } -+ -+ // we know priority is valid here -+ for (int curr = this.attemptedPriority.get();;) { -+ if (curr <= priority) { -+ break; // curr is higher/same priority -+ } -+ if (this.attemptedPriority.compareAndSet(curr, priority)) { -+ break; -+ } -+ curr = this.attemptedPriority.get(); -+ } -+ -+ return super.raisePriority(priority); -+ } -+ -+ @Override -+ public boolean updatePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalStateException("Invalid priority: " + priority); -+ } -+ this.attemptedPriority.set(priority); -+ return super.updatePriority(priority); -+ } -+ -+ private void complete(final NBTTagCompound compound) { -+ try { -+ this.onComplete.complete(compound); -+ } catch (final Throwable thr) { -+ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); -+ } -+ if (compound != PaperFileIOThread.FAILURE_VALUE) { -+ PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, this.chunkX, this.chunkZ, null, compound, this.attemptedPriority.get()); -+ } -+ this.taskManager.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { -+ if (valueInMap != ChunkSaveTask.this) { -+ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", this: " + ChunkSaveTask.this); -+ } -+ return null; -+ }); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9c1370c7d85262da9d64871e03e5a8a8c5e087d7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java -@@ -0,0 +1,40 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+import net.minecraft.server.level.WorldServer; -+ -+abstract class ChunkTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { -+ -+ public final WorldServer world; -+ public final int chunkX; -+ public final int chunkZ; -+ public final ChunkTaskManager taskManager; -+ -+ public ChunkTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, -+ final ChunkTaskManager taskManager) { -+ super(priority); -+ this.world = world; -+ this.chunkX = chunkX; -+ this.chunkZ = chunkZ; -+ this.taskManager = taskManager; -+ } -+ -+ @Override -+ public String toString() { -+ return "Chunk task: class:" + this.getClass().getName() + ", for world '" + this.world.getWorld().getName() + -+ "', (" + this.chunkX + "," + this.chunkZ + "), hashcode:" + this.hashCode() + ", priority: " + this.getPriority(); -+ } -+ -+ @Override -+ public boolean raisePriority(final int priority) { -+ PaperFileIOThread.Holder.INSTANCE.bumpPriority(this.world, this.chunkX, this.chunkZ, priority); -+ return super.raisePriority(priority); -+ } -+ -+ @Override -+ public boolean updatePriority(final int priority) { -+ PaperFileIOThread.Holder.INSTANCE.setPriority(this.world, this.chunkX, this.chunkZ, priority); -+ return super.updatePriority(priority); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8e642f450b974d81f128d26edfd40915554db638 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -@@ -0,0 +1,513 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.IOUtil; -+import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+import com.destroystokyo.paper.io.QueueExecutorThread; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.util.thread.IAsyncTaskHandler; -+import net.minecraft.world.level.chunk.ChunkStatus; -+import net.minecraft.world.level.chunk.IChunkAccess; -+import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; -+import org.apache.commons.lang.StringUtils; -+import org.apache.logging.log4j.Level; -+import org.bukkit.Bukkit; -+import org.spigotmc.AsyncCatcher; -+ -+import java.util.ArrayDeque; -+import java.util.HashSet; -+import java.util.Set; -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.function.Consumer; -+ -+public final class ChunkTaskManager { -+ -+ private final QueueExecutorThread[] workers; -+ private final WorldServer world; -+ -+ private final PrioritizedTaskQueue queue; -+ private final boolean perWorldQueue; -+ -+ final ConcurrentHashMap chunkLoadTasks = new ConcurrentHashMap<>(64, 0.5f); -+ final ConcurrentHashMap chunkSaveTasks = new ConcurrentHashMap<>(64, 0.5f); -+ -+ private final PrioritizedTaskQueue chunkTasks = new PrioritizedTaskQueue<>(); // used if async chunks are disabled in config -+ -+ protected static QueueExecutorThread[] globalWorkers; -+ protected static QueueExecutorThread globalUrgentWorker; -+ protected static PrioritizedTaskQueue globalQueue; -+ protected static PrioritizedTaskQueue globalUrgentQueue; -+ -+ protected static final ConcurrentLinkedQueue CHUNK_WAIT_QUEUE = new ConcurrentLinkedQueue<>(); -+ -+ public static final ArrayDeque WAITING_CHUNKS = new ArrayDeque<>(); // stack -+ -+ private static final class ChunkInfo { -+ -+ public final int chunkX; -+ public final int chunkZ; -+ public final WorldServer world; -+ -+ public ChunkInfo(final int chunkX, final int chunkZ, final WorldServer world) { -+ this.chunkX = chunkX; -+ this.chunkZ = chunkZ; -+ this.world = world; -+ } -+ -+ @Override -+ public String toString() { -+ return "[( " + this.chunkX + "," + this.chunkZ + ") in '" + this.world.getWorld().getName() + "']"; -+ } -+ } -+ -+ public static void pushChunkWait(final WorldServer world, final int chunkX, final int chunkZ) { -+ synchronized (WAITING_CHUNKS) { -+ WAITING_CHUNKS.push(new ChunkInfo(chunkX, chunkZ, world)); -+ } -+ } -+ -+ public static void popChunkWait() { -+ synchronized (WAITING_CHUNKS) { -+ WAITING_CHUNKS.pop(); -+ } -+ } -+ -+ private static ChunkInfo[] getChunkInfos() { -+ ChunkInfo[] chunks; -+ synchronized (WAITING_CHUNKS) { -+ chunks = WAITING_CHUNKS.toArray(new ChunkInfo[0]); -+ } -+ return chunks; -+ } -+ -+ public static void dumpAllChunkLoadInfo() { -+ ChunkInfo[] chunks = getChunkInfos(); -+ if (chunks.length > 0) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk wait task info below: "); -+ -+ for (final ChunkInfo chunkInfo : chunks) { -+ final long key = IOUtil.getCoordinateKey(chunkInfo.chunkX, chunkInfo.chunkZ); -+ final ChunkLoadTask loadTask = chunkInfo.world.asyncChunkTaskManager.chunkLoadTasks.get(key); -+ final ChunkSaveTask saveTask = chunkInfo.world.asyncChunkTaskManager.chunkSaveTasks.get(key); -+ -+ PaperFileIOThread.LOGGER.log(Level.ERROR, chunkInfo.chunkX + "," + chunkInfo.chunkZ + " in '" + chunkInfo.world.getWorld().getName() + ":"); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Load Task - " + (loadTask == null ? "none" : loadTask.toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Save Task - " + (saveTask == null ? "none" : saveTask.toString())); -+ // log current status of chunk to indicate whether we're waiting on generation or loading -+ PlayerChunk chunkHolder = chunkInfo.world.getChunkProvider().playerChunkMap.getVisibleChunk(key); -+ -+ dumpChunkInfo(new HashSet<>(), chunkHolder, chunkInfo.chunkX, chunkInfo.chunkZ); -+ } -+ } -+ } -+ -+ static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z) { -+ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); -+ } -+ -+ static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z, int indent, int maxDepth) { -+ if (seenChunks.contains(chunkHolder)) { -+ return; -+ } -+ if (indent > maxDepth) { -+ return; -+ } -+ seenChunks.add(chunkHolder); -+ String indentStr = StringUtils.repeat(" ", indent); -+ if (chunkHolder == null) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - null for (" + x +"," + z +")"); -+ } else { -+ IChunkAccess chunk = chunkHolder.getAvailableChunkNow(); -+ ChunkStatus holderStatus = chunkHolder.getChunkHolderStatus(); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - non-null"); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getChunkStatus().toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + PlayerChunk.getChunkStatus(chunkHolder.getTicketLevel())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); -+ } -+ } -+ -+ public static void initGlobalLoadThreads(int threads) { -+ if (threads <= 0 || globalWorkers != null) { -+ return; -+ } -+ -+ globalWorkers = new QueueExecutorThread[threads]; -+ globalQueue = new PrioritizedTaskQueue<>(); -+ globalUrgentQueue = new PrioritizedTaskQueue<>(); -+ -+ for (int i = 0; i < threads; ++i) { -+ globalWorkers[i] = new QueueExecutorThread<>(globalQueue, (long)0.10e6); //0.1ms -+ globalWorkers[i].setName("Paper Async Chunk Task Thread #" + i); -+ globalWorkers[i].setPriority(Thread.NORM_PRIORITY - 1); -+ globalWorkers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { -+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); -+ }); -+ -+ globalWorkers[i].start(); -+ } -+ -+ globalUrgentWorker = new QueueExecutorThread<>(globalUrgentQueue, (long)0.10e6); //0.1ms -+ globalUrgentWorker.setName("Paper Async Chunk Urgent Task Thread"); -+ globalUrgentWorker.setPriority(Thread.NORM_PRIORITY+1); -+ globalUrgentWorker.setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { -+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); -+ }); -+ -+ globalUrgentWorker.start(); -+ } -+ -+ /** -+ * Creates this chunk task manager to operate off the specified number of threads. If the specified number of threads is -+ * less-than or equal to 0, then this chunk task manager will operate off of the world's chunk task queue. -+ * @param world Specified world. -+ * @param threads Specified number of threads. -+ * @see ChunkProviderServer#serverThreadQueue -+ */ -+ public ChunkTaskManager(final WorldServer world, final int threads) { -+ this.world = world; -+ this.workers = threads <= 0 ? null : new QueueExecutorThread[threads]; -+ this.queue = new PrioritizedTaskQueue<>(); -+ this.perWorldQueue = true; -+ -+ for (int i = 0; i < threads; ++i) { -+ this.workers[i] = new QueueExecutorThread<>(this.queue, (long)0.10e6); //0.1ms -+ this.workers[i].setName("Async chunk loader thread #" + i + " for world: " + world.getWorld().getName()); -+ this.workers[i].setPriority(Thread.NORM_PRIORITY - 1); -+ this.workers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { -+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); -+ }); -+ -+ this.workers[i].start(); -+ } -+ } -+ -+ /** -+ * Creates the chunk task manager to work from the global workers. When {@link #close(boolean)} is invoked, -+ * the global queue is not shutdown. If the global workers is configured to be disabled or use 0 threads, then -+ * this chunk task manager will operate off of the world's chunk task queue. -+ * @param world The world that this task manager is responsible for -+ * @see ChunkProviderServer#serverThreadQueue -+ */ -+ public ChunkTaskManager(final WorldServer world) { -+ this.world = world; -+ this.workers = globalWorkers; -+ this.queue = globalQueue; -+ this.perWorldQueue = false; -+ } -+ -+ public boolean pollNextChunkTask() { -+ final ChunkTask task = this.chunkTasks.poll(); -+ -+ if (task != null) { -+ task.run(); -+ return true; -+ } -+ return false; -+ } -+ -+ /** -+ * Polls and runs the next available chunk wait queue task. This is to be used when the server is waiting on a chunk queue. -+ * (per-world can cause issues if all the worker threads are blocked waiting for a response from the main thread) -+ */ -+ public static boolean pollChunkWaitQueue() { -+ final Runnable run = CHUNK_WAIT_QUEUE.poll(); -+ if (run != null) { -+ run.run(); -+ return true; -+ } -+ return false; -+ } -+ -+ /** -+ * Queues a chunk wait task. Note that this will execute out of order with respect to tasks scheduled on a world's -+ * chunk task queue, since this is the global chunk wait queue. -+ */ -+ public static void queueChunkWaitTask(final Runnable runnable) { -+ CHUNK_WAIT_QUEUE.add(runnable); -+ } -+ -+ private static void drainChunkWaitQueue() { -+ Runnable run; -+ while ((run = CHUNK_WAIT_QUEUE.poll()) != null) { -+ run.run(); -+ } -+ } -+ -+ /** -+ * The exact same as {@link #scheduleChunkLoad(int, int, int, Consumer, boolean)}, except that the chunk data is provided as -+ * the {@code data} parameter. -+ */ -+ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, -+ final Consumer onComplete, -+ final boolean intendingToBlock, final CompletableFuture dataFuture) { -+ final WorldServer world = this.world; -+ -+ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != null) { -+ if (!valueInMap.cancelled) { -+ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); -+ } -+ valueInMap.cancelled = false; -+ valueInMap.onComplete = onComplete; -+ return valueInMap; -+ } -+ -+ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); -+ -+ dataFuture.thenAccept((final NBTTagCompound data) -> { -+ final boolean failed = data == PaperFileIOThread.FAILURE_VALUE; -+ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { -+ ret.chunkData = chunkData; -+ if (!failed) { -+ chunkData.chunkData = data; -+ } -+ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here -+ }, true, failed, intendingToBlock); // read data off disk if the future fails -+ }); -+ -+ return ret; -+ }); -+ } -+ -+ public void cancelChunkLoad(final int chunkX, final int chunkZ) { -+ this.chunkLoadTasks.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap == null) { -+ return null; -+ } -+ -+ if (valueInMap.cancelled) { -+ PaperFileIOThread.LOGGER.warn("Task " + valueInMap.toString() + " is already cancelled!"); -+ } -+ valueInMap.cancelled = true; -+ if (valueInMap.cancel()) { -+ return null; -+ } -+ -+ return valueInMap; -+ }); -+ } -+ -+ /** -+ * Schedules an asynchronous chunk load for the specified coordinates. The onComplete parameter may be invoked asynchronously -+ * on a worker thread or on the world's chunk executor queue. As such the code that is executed for the parameter should be -+ * carefully chosen. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority for this task -+ * @param onComplete The consumer to invoke with the {@link ChunkRegionLoader.InProgressChunkHolder} object once this task is complete -+ * @param intendingToBlock Whether the caller is intending to block on this task completing (this is a performance tune, and has no adverse side-effects) -+ * @return The {@link ChunkLoadTask} associated with -+ */ -+ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, -+ final Consumer onComplete, -+ final boolean intendingToBlock) { -+ final WorldServer world = this.world; -+ -+ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != null) { -+ if (!valueInMap.cancelled) { -+ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); -+ } -+ valueInMap.cancelled = false; -+ valueInMap.onComplete = onComplete; -+ return valueInMap; -+ } -+ -+ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); -+ -+ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { -+ ret.chunkData = chunkData; -+ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here -+ }, true, true, intendingToBlock); -+ -+ return ret; -+ }); -+ } -+ -+ /** -+ * Schedules an async save for the specified chunk. The chunk, at the beginning of this call, must be completely unloaded -+ * from the world. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority for this task -+ * @param asyncSaveData Async save data. See {@link ChunkRegionLoader#getAsyncSaveData(WorldServer, IChunkAccess)} -+ * @param chunk Chunk to save -+ * @return The {@link ChunkSaveTask} associated with the save task. -+ */ -+ public ChunkSaveTask scheduleChunkSave(final int chunkX, final int chunkZ, final int priority, -+ final ChunkRegionLoader.AsyncSaveData asyncSaveData, -+ final IChunkAccess chunk) { -+ AsyncCatcher.catchOp("chunk save schedule"); -+ -+ final WorldServer world = this.world; -+ -+ return this.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { -+ if (valueInMap != null) { -+ throw new IllegalStateException("Double scheduling chunk save for task: " + valueInMap.toString()); -+ } -+ -+ final ChunkSaveTask ret = new ChunkSaveTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, asyncSaveData, chunk); -+ -+ ChunkTaskManager.this.internalSchedule(ret); -+ -+ return ret; -+ }); -+ } -+ -+ /** -+ * Returns a completable future which will be completed with the un-copied chunk data for an in progress async save. -+ * Returns {@code null} if no save is in progress. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ */ -+ public CompletableFuture getChunkSaveFuture(final int chunkX, final int chunkZ) { -+ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); -+ if (chunkSaveTask == null) { -+ return null; -+ } -+ return chunkSaveTask.onComplete; -+ } -+ -+ /** -+ * Returns the chunk object being used to serialize data async for an unloaded chunk. Note that modifying this chunk -+ * is not safe to do as another thread is handling its save. The chunk is also not loaded into the world. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @return Chunk object for an in-progress async save, or {@code null} if no save is in progress -+ */ -+ public IChunkAccess getChunkInSaveProgress(final int chunkX, final int chunkZ) { -+ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); -+ if (chunkSaveTask == null) { -+ return null; -+ } -+ return chunkSaveTask.chunk; -+ } -+ -+ public void flush() { -+ // flush here since we schedule tasks on the IO thread that can schedule tasks here -+ drainChunkWaitQueue(); -+ PaperFileIOThread.Holder.INSTANCE.flush(); -+ drainChunkWaitQueue(); -+ -+ if (this.workers == null) { -+ if (Bukkit.isPrimaryThread() || MinecraftServer.getServer().hasStopped()) { -+ ((IAsyncTaskHandler)this.world.getChunkProvider().serverThreadQueue).executeAll(); -+ } else { -+ CompletableFuture wait = new CompletableFuture<>(); -+ MinecraftServer.getServer().scheduleOnMain(() -> { -+ ((IAsyncTaskHandler)this.world.getChunkProvider().serverThreadQueue).executeAll(); -+ }); -+ wait.join(); -+ } -+ } else { -+ for (final QueueExecutorThread worker : this.workers) { -+ worker.flush(); -+ } -+ } -+ if (globalUrgentWorker != null) globalUrgentWorker.flush(); -+ -+ // flush again since tasks we execute async saves -+ drainChunkWaitQueue(); -+ PaperFileIOThread.Holder.INSTANCE.flush(); -+ } -+ -+ public void close(final boolean wait) { -+ // flush here since we schedule tasks on the IO thread that can schedule tasks to this task manager -+ // we do this regardless of the wait param since after we invoke close no tasks can be queued -+ PaperFileIOThread.Holder.INSTANCE.flush(); -+ -+ if (this.workers == null) { -+ if (wait) { -+ this.flush(); -+ } -+ return; -+ } -+ -+ if (this.workers != globalWorkers) { -+ for (final QueueExecutorThread worker : this.workers) { -+ worker.close(false, this.perWorldQueue); -+ } -+ } -+ -+ if (wait) { -+ this.flush(); -+ } -+ } -+ -+ public void raisePriority(final int chunkX, final int chunkZ, final int priority) { -+ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); -+ -+ ChunkTask chunkSaveTask = this.chunkSaveTasks.get(chunkKey); -+ if (chunkSaveTask != null) { -+ // don't bump save into urgent queue -+ raiseTaskPriority(chunkSaveTask, priority != PrioritizedTaskQueue.HIGHEST_PRIORITY ? priority : PrioritizedTaskQueue.HIGH_PRIORITY); -+ } -+ -+ ChunkLoadTask chunkLoadTask = this.chunkLoadTasks.get(chunkKey); -+ if (chunkLoadTask != null) { -+ raiseTaskPriority(chunkLoadTask, priority); -+ } -+ } -+ -+ private void raiseTaskPriority(ChunkTask task, int priority) { -+ final boolean raised = task.raisePriority(priority); -+ if (task.isScheduled() && raised && this.workers != null) { -+ // only notify if we're in queue to be executed -+ if (priority == PrioritizedTaskQueue.HIGHEST_PRIORITY) { -+ // was in another queue but became urgent later, add to urgent queue and the previous -+ // queue will just have to ignore this task if it has already been started. -+ // Ultimately, we now have 2 potential queues that can pull it out whoever gets it first -+ // but the urgent queue has dedicated thread(s) so it's likely to win.... -+ globalUrgentQueue.add(task); -+ this.internalScheduleNotifyUrgent(); -+ } else { -+ this.internalScheduleNotify(); -+ } -+ } -+ } -+ -+ protected void internalSchedule(final ChunkTask task) { -+ if (this.workers == null) { -+ this.chunkTasks.add(task); -+ return; -+ } -+ -+ // It's important we order the task to be executed before notifying. Avoid a race condition where the worker thread -+ // wakes up and goes to sleep before we actually schedule (or it's just about to sleep) -+ if (task.getPriority() == PrioritizedTaskQueue.HIGHEST_PRIORITY) { -+ globalUrgentQueue.add(task); -+ this.internalScheduleNotifyUrgent(); -+ } else { -+ this.queue.add(task); -+ this.internalScheduleNotify(); -+ } -+ -+ } -+ -+ protected void internalScheduleNotify() { -+ if (this.workers == null) { -+ return; -+ } -+ for (final QueueExecutorThread worker : this.workers) { -+ if (worker.notifyTasks()) { -+ // break here since we only want to wake up one worker for scheduling one task -+ break; -+ } -+ } -+ } -+ -+ -+ protected void internalScheduleNotifyUrgent() { -+ if (globalUrgentWorker == null) { -+ return; -+ } -+ globalUrgentWorker.notifyTasks(); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java -index e201e4efd4ecc65ec3c38528a4ec5336e2d51ab2..45f3f8964a587c382b6ea82560e9da30be42987f 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java -@@ -14,7 +14,7 @@ public class PacketPlayInTabComplete implements Packet { - @Override - public void a(PacketDataSerializer packetdataserializer) throws IOException { - this.a = packetdataserializer.i(); -- this.b = packetdataserializer.e(32500); -+ this.b = packetdataserializer.e(2048); - } - - @Override -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index fbd33aef21b4539d249c367609a36491530fb7ca..5a410550cfb48505c9de9979465ed1528c8fbf05 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -714,4 +714,9 @@ public final class MCUtil { - out.print(fileData); - } - } -+ -+ public static int getTicketLevelFor(ChunkStatus status) { -+ // TODO make sure the constant `33` is correct on future updates. See getChunkAt(int, int, ChunkStatus, boolean) -+ return 33 + ChunkStatus.getTicketLevelOffset(status); -+ } - } -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 191a74bd9b894f9d64d0a55747cb17e07ceef597..1732fc552c290d294b68d6f92f2a58d985fbef21 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -42,6 +42,7 @@ import net.minecraft.server.players.UserCache; - import net.minecraft.util.MathHelper; - import net.minecraft.util.datafix.DataConverterRegistry; - import net.minecraft.util.worldupdate.WorldUpgrader; -+import net.minecraft.world.entity.npc.VillagerTrades; - import net.minecraft.world.level.DataPackConfiguration; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.World; -@@ -210,6 +211,7 @@ public class Main { - - convertable_conversionsession.a((IRegistryCustom) iregistrycustom_dimension, (SaveData) object); - */ -+ Class.forName(VillagerTrades.class.getName());// Paper - load this sync so it won't fail later async - final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.a((thread) -> { - DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataConverterRegistry.a(), minecraftsessionservice, gameprofilerepository, usercache, WorldLoadListenerLogger::new); - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 8b922136336d5dc8fc302cc0f4879c4968a1cc67..e6e8ab0b39a11b0aed247b9b80a6c1f97505546b 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -922,7 +922,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant> getChunkAtAsynchronously(int x, int z, boolean gen, boolean isUrgent) { -+ if (Thread.currentThread() != this.serverThread) { -+ CompletableFuture> future = new CompletableFuture>(); -+ this.serverThreadQueue.execute(() -> { -+ this.getChunkAtAsynchronously(x, z, gen, isUrgent).whenComplete((chunk, ex) -> { -+ if (ex != null) { -+ future.completeExceptionally(ex); -+ } else { -+ future.complete(chunk); -+ } -+ }); -+ }); -+ return future; -+ } -+ -+ if (!com.destroystokyo.paper.PaperConfig.asyncChunks) { -+ world.getWorld().loadChunk(x, z, gen); -+ Chunk chunk = getChunkAtIfLoadedMainThread(x, z); -+ return CompletableFuture.completedFuture(chunk != null ? Either.left(chunk) : PlayerChunk.UNLOADED_CHUNK_ACCESS); -+ } -+ -+ long k = ChunkCoordIntPair.pair(x, z); -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); -+ -+ IChunkAccess ichunkaccess; -+ -+ // try cache -+ for (int l = 0; l < 4; ++l) { -+ if (k == this.cachePos[l] && ChunkStatus.FULL == this.cacheStatus[l]) { -+ ichunkaccess = this.cacheChunk[l]; -+ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime -+ -+ // move to first in cache -+ -+ for (int i1 = 3; i1 > 0; --i1) { -+ this.cachePos[i1] = this.cachePos[i1 - 1]; -+ this.cacheStatus[i1] = this.cacheStatus[i1 - 1]; -+ this.cacheChunk[i1] = this.cacheChunk[i1 - 1]; -+ } -+ -+ this.cachePos[0] = k; -+ this.cacheStatus[0] = ChunkStatus.FULL; -+ this.cacheChunk[0] = ichunkaccess; -+ -+ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); -+ } -+ } -+ } -+ -+ if (gen) { -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ IChunkAccess current = this.getChunkAtImmediately(x, z); // we want to bypass ticket restrictions -+ if (current != null) { -+ if (!(current instanceof ProtoChunkExtension) && !(current instanceof Chunk)) { -+ return CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK_ACCESS); -+ } -+ // we know the chunk is at full status here (either in read-only mode or the real thing) -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ ChunkStatus status = world.getChunkProvider().playerChunkMap.getStatusOnDiskNoLoad(x, z); -+ -+ if (status != null && status != ChunkStatus.FULL) { -+ // does not exist on disk -+ return CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK_ACCESS); -+ } -+ -+ if (status == ChunkStatus.FULL) { -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ // status is null here -+ -+ // here we don't know what status it is and we're not supposed to generate -+ // so we asynchronously load empty status -+ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.EMPTY, isUrgent).thenCompose((either) -> { -+ IChunkAccess chunk = either.left().orElse(null); -+ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof Chunk)) { -+ // the chunk on disk was not a full status chunk -+ return CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK_ACCESS); -+ } -+ ; // bring to full status if required -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ }); -+ } -+ -+ private CompletableFuture> bringToFullStatusAsync(int x, int z, ChunkCoordIntPair chunkPos, boolean isUrgent) { -+ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.FULL, isUrgent); -+ } -+ -+ private CompletableFuture> bringToStatusAsync(int x, int z, ChunkCoordIntPair chunkPos, ChunkStatus status, boolean isUrgent) { -+ CompletableFuture> future = this.getChunkFutureMainThread(x, z, status, true, isUrgent); -+ Long identifier = Long.valueOf(this.asyncLoadSeqCounter++); -+ int ticketLevel = MCUtil.getTicketLevelFor(status); -+ this.addTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); -+ -+ return future.thenComposeAsync((Either either) -> { -+ // either left -> success -+ // either right -> failure -+ -+ this.removeTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); -+ this.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); // allow unloading -+ -+ Optional failure = either.right(); -+ -+ if (failure.isPresent()) { -+ // failure -+ throw new IllegalStateException("Chunk failed to load: " + failure.get().toString()); -+ } -+ -+ return CompletableFuture.completedFuture(either); -+ }, this.serverThreadQueue); -+ } -+ -+ public void addTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { -+ this.chunkMapDistance.addTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); -+ } -+ -+ public void removeTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { -+ this.chunkMapDistance.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); -+ } - // Paper end - - @Nullable - @Override - public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { -+ final int x = i; final int z = j; // Paper - conflict on variable change - if (Thread.currentThread() != this.serverThread) { - return (IChunkAccess) CompletableFuture.supplyAsync(() -> { - return this.getChunkAt(i, j, chunkstatus, flag); -@@ -359,11 +487,16 @@ public class ChunkProviderServer extends IChunkProvider { - } - - gameprofilerfiller.c("getChunkCacheMiss"); -- CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag); -+ CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag, true); // Paper - - if (!completablefuture.isDone()) { // Paper -+ // Paper start - async chunk io/loading -+ this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); -+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z); -+ // Paper end - this.world.timings.syncChunkLoad.startTiming(); // Paper - this.serverThreadQueue.awaitTasks(completablefuture::isDone); -+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug - this.world.timings.syncChunkLoad.stopTiming(); // Paper - } // Paper - ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { -@@ -429,6 +562,11 @@ public class ChunkProviderServer extends IChunkProvider { - } - - private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag) { -+ // Paper start - add isUrgent - old sig left in place for dirty nms plugins -+ return getChunkFutureMainThread(i, j, chunkstatus, flag, false); -+ } -+ private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag, boolean isUrgent) { -+ // Paper end - ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i, j); - long k = chunkcoordintpair.pair(); - int l = 33 + ChunkStatus.a(chunkstatus); -@@ -830,11 +968,12 @@ public class ChunkProviderServer extends IChunkProvider { - protected boolean executeNext() { - // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task - try { -+ boolean execChunkTask = com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ChunkProviderServer.this.world.asyncChunkTaskManager.pollNextChunkTask(); // Paper - if (ChunkProviderServer.this.tickDistanceManager()) { - return true; - } else { - ChunkProviderServer.this.lightEngine.queueUpdate(); -- return super.executeNext(); -+ return super.executeNext() || execChunkTask; // Paper - } - } finally { - playerChunkMap.callbackExecutor.run(); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 75d4a8fc394449ccc006fe67a8842edcd9f36854..6433463938d8bb717840c8f57fe6e7079e1030f2 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -158,6 +158,18 @@ public class PlayerChunk { - } - return null; - } -+ -+ public ChunkStatus getChunkHolderStatus() { -+ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) { -+ CompletableFuture> future = this.getStatusFutureUnchecked(curr); -+ Either either = future.getNow(null); -+ if (either == null || !either.left().isPresent()) { -+ continue; -+ } -+ return curr; -+ } -+ return null; -+ } - // Paper end - - public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { -@@ -376,7 +388,7 @@ public class PlayerChunk { - ChunkStatus chunkstatus = getChunkStatus(this.oldTicketLevel); - ChunkStatus chunkstatus1 = getChunkStatus(this.ticketLevel); - boolean flag = this.oldTicketLevel <= PlayerChunkMap.GOLDEN_TICKET; -- boolean flag1 = this.ticketLevel <= PlayerChunkMap.GOLDEN_TICKET; -+ boolean flag1 = this.ticketLevel <= PlayerChunkMap.GOLDEN_TICKET; // Paper - diff on change: (flag1 = new ticket level is in loadable range) - PlayerChunk.State playerchunk_state = getChunkState(this.oldTicketLevel); - PlayerChunk.State playerchunk_state1 = getChunkState(this.ticketLevel); - // CraftBukkit start -@@ -412,6 +424,12 @@ public class PlayerChunk { - } - }); - -+ // Paper start -+ if (!flag1) { -+ playerchunkmap.world.asyncChunkTaskManager.cancelChunkLoad(this.location.x, this.location.z); -+ } -+ // Paper end -+ - for (int i = flag1 ? chunkstatus1.c() + 1 : 0; i <= chunkstatus.c(); ++i) { - completablefuture = (CompletableFuture) this.statusFutures.get(i); - if (completablefuture != null) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 5a11765c8a7d754ec86d829fa5e85d2809dd937e..46c91230ab6f12db77b453c312fa7382b76fad34 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -88,6 +88,7 @@ import net.minecraft.world.level.chunk.ProtoChunk; - import net.minecraft.world.level.chunk.ProtoChunkExtension; - import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; - import net.minecraft.world.level.chunk.storage.IChunkLoader; -+import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureManager; - import net.minecraft.world.level.storage.Convertable; -@@ -112,7 +113,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final LightEngineThreaded lightEngine; - private final IAsyncTaskHandler executor; - public final ChunkGenerator chunkGenerator; -- private final Supplier l; -+ private final Supplier l; public final Supplier getWorldPersistentDataSupplier() { return this.l; } // Paper - OBFHELPER - private final VillagePlace m; - public final LongSet unloadQueue; - private boolean updatingChunksModified; -@@ -122,7 +123,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final WorldLoadListener worldLoadListener; - public final PlayerChunkMap.a chunkDistanceManager; - private final AtomicInteger u; -- private final DefinedStructureManager definedStructureManager; -+ public final DefinedStructureManager definedStructureManager; // Paper - private -> public - private final File w; - private final PlayerMap playerMap; - public final Int2ObjectMap trackedEntities; -@@ -205,7 +206,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false)); - this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); - this.l = supplier; -- this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag); -+ this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper - this.setViewDistance(i); - } - -@@ -247,12 +248,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - @Nullable -- protected PlayerChunk getUpdatingChunk(long i) { -+ public PlayerChunk getUpdatingChunk(long i) { // Paper - return (PlayerChunk) this.updatingChunks.get(i); - } - - @Nullable -- protected PlayerChunk getVisibleChunk(long i) { -+ public PlayerChunk getVisibleChunk(long i) { // Paper - protected -> public - return (PlayerChunk) this.visibleChunks.get(i); - } - -@@ -374,6 +375,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public void close() throws IOException { - try { - this.p.close(); -+ this.world.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line - this.m.close(); - } finally { - super.close(); -@@ -465,7 +467,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.b(() -> { - return true; - }); -- this.i(); -+ this.world.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour -+// this.i(); // Paper - nuke IOWorker - PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName()); - } else { - this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { -@@ -481,16 +484,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot -+ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more - - protected void unloadChunks(BooleanSupplier booleansupplier) { - GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); - -+ try (Timing ignored = this.world.timings.poiUnload.startTiming()) { // Paper - gameprofilerfiller.enter("poi"); - this.m.a(booleansupplier); -+ } // Paper - gameprofilerfiller.exitEnter("chunk_unload"); - if (!this.world.isSavingDisabled()) { -+ try (Timing ignored = this.world.timings.chunkUnload.startTiming()) { // Paper - this.b(booleansupplier); -+ }// Paper - } - - gameprofilerfiller.exit(); -@@ -511,12 +518,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (playerchunk != null) { - this.pendingUnload.put(j, playerchunk); - this.updatingChunksModified = true; -+ this.a(j, playerchunk); // Paper - Move up - don't leak chunks - // Spigot start - if (!booleansupplier.getAsBoolean() && this.unloadQueue.size() <= targetSize && activityAccountant.activityTimeIsExhausted()) { - break; - } - // Spigot end -- this.a(j, playerchunk); -+ //this.a(j, playerchunk); // Paper - move up because spigot did a dumb - } - } - activityAccountant.endActivity(); // Spigot -@@ -530,6 +538,60 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ // Paper start - async chunk save for unload -+ // Note: This is very unsafe to call if the chunk is still in use. -+ // This is also modeled after PlayerChunkMap#saveChunk(IChunkAccess, boolean), with the intentional difference being -+ // serializing the chunk is left to a worker thread. -+ private void asyncSave(IChunkAccess chunk) { -+ ChunkCoordIntPair chunkPos = chunk.getPos(); -+ NBTTagCompound poiData; -+ try (Timing ignored = this.world.timings.chunkUnloadPOISerialization.startTiming()) { -+ poiData = this.getVillagePlace().getData(chunk.getPos()); -+ } -+ -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkPos.x, chunkPos.z, -+ poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); -+ -+ if (!chunk.isNeedsSaving()) { -+ return; -+ } -+ -+ ChunkStatus chunkstatus = chunk.getChunkStatus(); -+ -+ // Copied from PlayerChunkMap#saveChunk(IChunkAccess, boolean) -+ if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) { -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper -+ // Paper start - Optimize save by using status cache -+ try { -+ ChunkStatus statusOnDisk = this.getChunkStatusOnDisk(chunkPos); -+ if (statusOnDisk != null && statusOnDisk.getType() == ChunkStatus.Type.LEVELCHUNK) { -+ // Paper end -+ return; -+ } -+ -+ if (chunkstatus == ChunkStatus.EMPTY && chunk.h().values().stream().noneMatch(StructureStart::e)) { -+ return; -+ } -+ } catch (IOException ex) { -+ ex.printStackTrace(); -+ return; -+ } -+ } -+ } -+ -+ ChunkRegionLoader.AsyncSaveData asyncSaveData; -+ try (Timing ignored = this.world.timings.chunkUnloadPrepareSave.startTiming()) { -+ asyncSaveData = ChunkRegionLoader.getAsyncSaveData(this.world, chunk); -+ } -+ -+ this.world.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY, -+ asyncSaveData, chunk); -+ -+ chunk.setLastSaved(this.world.getTime()); -+ chunk.setNeedsSaving(false); -+ } -+ // Paper end -+ - private void a(long i, PlayerChunk playerchunk) { - CompletableFuture completablefuture = playerchunk.getChunkSave(); - Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error -@@ -543,7 +605,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ((Chunk) ichunkaccess).setLoaded(false); - } - -- this.saveChunk(ichunkaccess); -+ //this.saveChunk(ichunkaccess);// Paper - delay - if (this.loadedChunks.remove(i) && ichunkaccess instanceof Chunk) { - Chunk chunk = (Chunk) ichunkaccess; - -@@ -551,6 +613,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - this.autoSaveQueue.remove(playerchunk); // Paper - -+ try { -+ this.asyncSave(ichunkaccess); // Paper - async chunk saving -+ } catch (Throwable ex) { -+ LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex); -+ this.saveChunk(ichunkaccess); -+ } -+ - this.lightEngine.a(ichunkaccess.getPos()); - this.lightEngine.queueUpdate(); - this.worldLoadListener.a(ichunkaccess.getPos(), (ChunkStatus) null); -@@ -621,19 +690,23 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - private CompletableFuture> f(ChunkCoordIntPair chunkcoordintpair) { -- return CompletableFuture.supplyAsync(() -> { -+ // Paper start - Async chunk io -+ final java.util.function.BiFunction> syncLoadComplete = (chunkHolder, ioThrowable) -> { - try (Timing ignored = this.world.timings.chunkLoad.startTimingIfSync()) { // Paper - this.world.getMethodProfiler().c("chunkLoad"); -- NBTTagCompound nbttagcompound; // Paper -- try (Timing ignored2 = this.world.timings.chunkIO.startTimingIfSync()) { // Paper start - timings -- nbttagcompound = this.readChunkData(chunkcoordintpair); -- } // Paper end -+ // Paper start -+ if (ioThrowable != null) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable); -+ } - -- if (nbttagcompound != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings -- boolean flag = nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8); -+ this.getVillagePlace().loadInData(chunkcoordintpair, chunkHolder.poiData); -+ chunkHolder.tasks.forEach(Runnable::run); -+ // Paper end - -- if (flag) { -- ProtoChunk protochunk = ChunkRegionLoader.loadChunk(this.world, this.definedStructureManager, this.m, chunkcoordintpair, nbttagcompound); -+ if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async -+ -+ if (true) { -+ ProtoChunk protochunk = chunkHolder.protoChunk; - - protochunk.setLastSaved(this.world.getTime()); - this.a(chunkcoordintpair, protochunk.getChunkStatus().getType()); -@@ -657,7 +730,32 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - this.g(chunkcoordintpair); - return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter -- }, this.executor); -+ // Paper start - Async chunk io -+ }; -+ CompletableFuture> ret = new CompletableFuture<>(); -+ -+ Consumer chunkHolderConsumer = (ChunkRegionLoader.InProgressChunkHolder holder) -> { -+ // Go into the chunk load queue and not server task queue so we can be popped out even faster. -+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.queueChunkWaitTask(() -> { -+ try { -+ ret.complete(syncLoadComplete.apply(holder, null)); -+ } catch (Exception e) { -+ ret.completeExceptionally(e); -+ } -+ }); -+ }; -+ -+ CompletableFuture chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z); -+ if (chunkSaveFuture != null) { -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); -+ this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); -+ } else { -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); -+ } -+ return ret; -+ // Paper end - } - - private void g(ChunkCoordIntPair chunkcoordintpair) { -@@ -892,6 +990,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - public boolean saveChunk(IChunkAccess ichunkaccess) { -+ try (co.aikar.timings.Timing ignored = this.world.timings.chunkSave.startTiming()) { // Paper - this.m.a(ichunkaccess.getPos()); - if (!ichunkaccess.isNeedsSaving()) { - return false; -@@ -904,6 +1003,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ChunkStatus chunkstatus = ichunkaccess.getChunkStatus(); - - if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) { -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper - if (this.h(chunkcoordintpair)) { - return false; - } -@@ -911,12 +1011,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (chunkstatus == ChunkStatus.EMPTY && ichunkaccess.h().values().stream().noneMatch(StructureStart::e)) { - return false; - } -+ } // Paper - } - - this.world.getMethodProfiler().c("chunkSave"); -- NBTTagCompound nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess); -+ NBTTagCompound nbttagcompound; -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveDataSerialization.startTiming()) { // Paper -+ nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess); -+ } // Paper -+ - -- this.a(chunkcoordintpair, nbttagcompound); -+ // Paper start - async chunk io -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkcoordintpair.x, chunkcoordintpair.z, -+ null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); -+ // Paper end - async chunk io - this.a(chunkcoordintpair, chunkstatus.getType()); - return true; - } catch (Exception exception) { -@@ -925,6 +1033,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return false; - } - } -+ } // Paper - } - - private boolean h(ChunkCoordIntPair chunkcoordintpair) { -@@ -1054,6 +1163,35 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - } - -+ // Paper start - Asynchronous chunk io -+ @Nullable -+ @Override -+ public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { -+ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ NBTTagCompound ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), -+ false, true, true).join().chunkData; -+ -+ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { -+ throw new IOException("See logs for further detail"); -+ } -+ return ret; -+ } -+ return super.read(chunkcoordintpair); -+ } -+ -+ @Override -+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { -+ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( -+ this.world, chunkcoordintpair.x, chunkcoordintpair.z, null, nbttagcompound, -+ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); -+ return; -+ } -+ super.write(chunkcoordintpair, nbttagcompound); -+ } -+ // Paper end -+ - @Nullable - public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public - NBTTagCompound nbttagcompound = this.read(chunkcoordintpair); -@@ -1075,33 +1213,55 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - // Paper start - chunk status cache "api" - public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); -+ synchronized (this) { // Paper -+ RegionFile regionFile = this.regionFileCache.getRegionFileIfLoaded(chunkPos); - - return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } // Paper - } - - public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); -+ // Paper start - async chunk save for unload -+ IChunkAccess unloadingChunk = this.world.asyncChunkTaskManager.getChunkInSaveProgress(chunkPos.x, chunkPos.z); -+ if (unloadingChunk != null) { -+ return unloadingChunk.getChunkStatus(); -+ } -+ // Paper end -+ // Paper start - async io -+ NBTTagCompound inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .getPendingWrite(this.world, chunkPos.x, chunkPos.z, false); - -- if (regionFile == null || !regionFile.chunkExists(chunkPos)) { -- return null; -+ if (inProgressWrite != null) { -+ return ChunkRegionLoader.getStatus(inProgressWrite); - } -+ // Paper end -+ synchronized (this) { // Paper - async io -+ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, true); -+ -+ if (regionFile == null || !regionFile.chunkExists(chunkPos)) { -+ return null; -+ } - -- ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); - -- if (status != null) { -- return status; -+ if (status != null) { -+ return status; -+ } -+ // Paper start - async io - } - -- this.readChunkData(chunkPos); -+ NBTTagCompound compound = this.readChunkData(chunkPos); - -- return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ return ChunkRegionLoader.getStatus(compound); -+ // Paper end - } - - public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ synchronized (this) { -+ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, false); - -- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); -+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); -+ } - } - - public IChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { -@@ -1110,6 +1270,39 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - // Paper end - -+ -+ // Paper start - async io -+ // this function will not load chunk data off disk to check for status -+ // ret null for unknown, empty for empty status on disk or absent from disk -+ public ChunkStatus getStatusOnDiskNoLoad(int x, int z) { -+ // Paper start - async chunk save for unload -+ IChunkAccess unloadingChunk = this.world.asyncChunkTaskManager.getChunkInSaveProgress(x, z); -+ if (unloadingChunk != null) { -+ return unloadingChunk.getChunkStatus(); -+ } -+ // Paper end -+ // Paper start - async io -+ NBTTagCompound inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .getPendingWrite(this.world, x, z, false); -+ -+ if (inProgressWrite != null) { -+ return ChunkRegionLoader.getStatus(inProgressWrite); -+ } -+ // Paper end -+ // variant of PlayerChunkMap#getChunkStatusOnDisk that does not load data off disk, but loads the region file -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); -+ synchronized (world.getChunkProvider().playerChunkMap) { -+ RegionFile file; -+ try { -+ file = world.getChunkProvider().playerChunkMap.regionFileCache.getFile(chunkPos, false); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return !file.chunkExists(chunkPos) ? ChunkStatus.EMPTY : file.getStatusIfCached(x, z); -+ } -+ } -+ - boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair) { - // Spigot start - return isOutsideOfRange(chunkcoordintpair, false); -@@ -1456,6 +1649,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ public VillagePlace getVillagePlace() { return this.h(); } // Paper - OBFHELPER - protected VillagePlace h() { - return this.m; - } -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 285a03b57431bd6a4d26bb84e916d2c6e1eb0213..218dc900e125a11548485887b1918742072c7a77 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -26,6 +26,7 @@ public class TicketType { - public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit - public static final TicketType PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit - public static final TicketType FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper -+ public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper - - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 3eb337d42f0292ed7b85a5fdbf6b450bc446b81a..52d22da115212eae6c380bb5012398e3df92f5f3 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -51,6 +51,7 @@ import net.minecraft.core.IRegistry; - import net.minecraft.core.IRegistryCustom; - import net.minecraft.core.SectionPosition; - import net.minecraft.core.particles.ParticleParam; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.Packet; -@@ -126,6 +127,7 @@ import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.chunk.ChunkSection; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.IChunkAccess; -+import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.dimension.DimensionManager; - import net.minecraft.world.level.dimension.end.EnderDragonBattle; - import net.minecraft.world.level.levelgen.HeightMap; -@@ -208,6 +210,79 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return this.chunkProvider.getChunkAt(x, z, false); - } - -+ // Paper start - Asynchronous IO -+ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController poiDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { -+ @Override -+ public void writeData(int x, int z, NBTTagCompound compound) throws java.io.IOException { -+ WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().write(new ChunkCoordIntPair(x, z), compound); -+ } -+ -+ @Override -+ public NBTTagCompound readData(int x, int z) throws java.io.IOException { -+ return WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().read(new ChunkCoordIntPair(x, z)); -+ } -+ -+ @Override -+ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace()) { -+ RegionFile file; -+ -+ try { -+ file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getFile(new ChunkCoordIntPair(chunkX, chunkZ), false); -+ } catch (java.io.IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return function.apply(file); -+ } -+ } -+ -+ @Override -+ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace()) { -+ RegionFile file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getRegionFileIfLoaded(new ChunkCoordIntPair(chunkX, chunkZ)); -+ return function.apply(file); -+ } -+ } -+ }; -+ -+ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController chunkDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { -+ @Override -+ public void writeData(int x, int z, NBTTagCompound compound) throws java.io.IOException { -+ WorldServer.this.getChunkProvider().playerChunkMap.write(new ChunkCoordIntPair(x, z), compound); -+ } -+ -+ @Override -+ public NBTTagCompound readData(int x, int z) throws java.io.IOException { -+ return WorldServer.this.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)); -+ } -+ -+ @Override -+ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap) { -+ RegionFile file; -+ -+ try { -+ file = WorldServer.this.getChunkProvider().playerChunkMap.regionFileCache.getFile(new ChunkCoordIntPair(chunkX, chunkZ), false); -+ } catch (java.io.IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return function.apply(file); -+ } -+ } -+ -+ @Override -+ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap) { -+ RegionFile file = WorldServer.this.getChunkProvider().playerChunkMap.regionFileCache.getRegionFileIfLoaded(new ChunkCoordIntPair(chunkX, chunkZ)); -+ return function.apply(file); -+ } -+ } -+ }; -+ public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; -+ // Paper end -+ - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor -@@ -255,6 +330,8 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.dragonBattle = null; - } - this.getServer().addWorld(this.getWorld()); // CraftBukkit -+ -+ this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper - } - - // CraftBukkit start -@@ -1743,7 +1820,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - MCUtil.getSpiralOutChunks(spawn, radiusInBlocks >> 4).forEach(pair -> { -- getChunkProvider().getChunkAtMainThread(pair.x, pair.z); -+ getChunkProvider().getChunkAtAsynchronously(pair.x, pair.z, true, false).exceptionally((ex) -> { -+ ex.printStackTrace(); -+ return null; -+ }); - }); - } - public void removeTicketsForSpawn(int radiusInBlocks, BlockPosition spawn) { -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index c3a3837badb4b2a2ab51e6fb2d7cfbaa2f4d8edb..d74d6abfff647c148e524905cd733c4b7fc6591f 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -730,6 +730,13 @@ public class PlayerConnection implements PacketListenerPlayIn { - minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper - return; - } -+ // Paper start -+ String str = packetplayintabcomplete.c(); int index = -1; -+ if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper -+ return; -+ } -+ // Paper end - // CraftBukkit end - StringReader stringreader = new StringReader(packetplayintabcomplete.c()); - -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -index e5641f2b41d89a57285fc072a48b951aa03a14a7..ca23ca14d8011fc8daa7e20f2eaa550a8ff92c53 100644 ---- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -+++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -@@ -91,7 +91,7 @@ public abstract class IAsyncTaskHandler implements Mailbox public - while (this.executeNext()) { - ; - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -index aa1d948e6aebef25f0f4c4c07f5131d2e8387e59..04b01cb841dc4f34ded5aaa4ea7a8e6d4b470183 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -@@ -22,7 +22,9 @@ import java.util.stream.Stream; - import net.minecraft.SystemUtils; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.SectionPosition; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.server.level.LightEngineGraphSection; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.IWorldReader; -@@ -36,8 +38,16 @@ public class VillagePlace extends RegionFileSection { - private final VillagePlace.a a = new VillagePlace.a(); - private final LongSet b = new LongOpenHashSet(); - -+ private final WorldServer world; // Paper -+ - public VillagePlace(File file, DataFixer datafixer, boolean flag) { -+ // Paper start - add world parameter -+ this(file, datafixer, flag, null); -+ } -+ public VillagePlace(File file, DataFixer datafixer, boolean flag, WorldServer world) { - super(file, VillagePlaceSection::a, VillagePlaceSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); -+ this.world = world; -+ // Paper end - add world parameter - } - - public void a(BlockPosition blockposition, VillagePlaceType villageplacetype) { -@@ -155,7 +165,23 @@ public class VillagePlace extends RegionFileSection { - - @Override - public void a(BooleanSupplier booleansupplier) { -- super.a(booleansupplier); -+ // Paper start - async chunk io -+ if (this.world == null) { -+ super.a(booleansupplier); -+ } else { -+ //super.a(booleansupplier); // re-implement below -+ while (!((RegionFileSection)this).d.isEmpty() && booleansupplier.getAsBoolean()) { -+ ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(((RegionFileSection)this).d.firstLong()).r(); -+ -+ NBTTagCompound data; -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) { -+ data = this.getData(chunkcoordintpair); -+ } -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, -+ chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); -+ } -+ } -+ // Paper end - this.a.a(); - } - -@@ -255,6 +281,35 @@ public class VillagePlace extends RegionFileSection { - } - } - -+ // Paper start - Asynchronous chunk io -+ @javax.annotation.Nullable -+ @Override -+ public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws java.io.IOException { -+ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ NBTTagCompound ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), -+ true, false, true).join().poiData; -+ -+ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { -+ throw new java.io.IOException("See logs for further detail"); -+ } -+ return ret; -+ } -+ return super.read(chunkcoordintpair); -+ } -+ -+ @Override -+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws java.io.IOException { -+ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( -+ this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, -+ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); -+ return; -+ } -+ super.write(chunkcoordintpair, nbttagcompound); -+ } -+ // Paper end -+ - public static enum Occupancy { - - HAS_SPACE(VillagePlaceRecord::d), IS_OCCUPIED(VillagePlaceRecord::e), ANY((villageplacerecord) -> { -diff --git a/src/main/java/net/minecraft/world/level/NextTickListEntry.java b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -index f3bcb96232d18abbcd86b079a7c5830bb30d75d2..37b7dd82a227a88b720c13a813dd7e8caf803e03 100644 ---- a/src/main/java/net/minecraft/world/level/NextTickListEntry.java -+++ b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -@@ -5,7 +5,7 @@ import net.minecraft.core.BlockPosition; - - public class NextTickListEntry { - -- private static long d; -+ private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading - private final T e; - public final BlockPosition a; - public final long b; -@@ -17,7 +17,7 @@ public class NextTickListEntry { - } - - public NextTickListEntry(BlockPosition blockposition, T t0, long i, TickListPriority ticklistpriority) { -- this.f = (long) (NextTickListEntry.d++); -+ this.f = (long) (NextTickListEntry.COUNTER.getAndIncrement()); // Paper - async chunk loading - this.a = blockposition.immutableCopy(); - this.e = t0; - this.b = i; -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -index 711308cf84a816f09d116a7414f9cbee803c8713..f094ddf6b4d155f3c7a08a3b811c98b0862fd098 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -@@ -170,6 +170,7 @@ public class ChunkStatus { - return ChunkStatus.q.size(); - } - -+ public static int getTicketLevelOffset(ChunkStatus status) { return ChunkStatus.a(status); } // Paper - OBFHELPER - public static int a(ChunkStatus chunkstatus) { - return ChunkStatus.r.getInt(chunkstatus.c()); - } -@@ -185,6 +186,7 @@ public class ChunkStatus { - this.t = chunkstatus == null ? 0 : chunkstatus.c() + 1; - } - -+ public final int getStatusIndex() { return c(); } // Paper - OBFHELPER - public int c() { - return this.t; - } -@@ -193,7 +195,7 @@ public class ChunkStatus { - return this.s; - } - -- public ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER -+ public final ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER - public ChunkStatus e() { - return this.u; - } -@@ -206,6 +208,7 @@ public class ChunkStatus { - return this.w.doWork(this, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess); - } - -+ public final int getNeighborRadius() { return this.f(); } // Paper - OBFHELPER - public int f() { - return this.x; - } -@@ -233,6 +236,7 @@ public class ChunkStatus { - return this.z; - } - -+ public final boolean isAtLeastStatus(ChunkStatus chunkstatus) { return b(chunkstatus); } // Paper - OBFHELPER - public boolean b(ChunkStatus chunkstatus) { - return this.c() >= chunkstatus.c(); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -index a2518fdadd1d7239e8614f498a5223144f1c2a36..86b4db483787c5fd10461f7d7e90a772ee049599 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -+++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -@@ -73,6 +73,7 @@ public class NibbleArray { - return this.a; - } - -+ public NibbleArray copy() { return this.b(); } // Paper - OBFHELPER - public NibbleArray b() { - return this.a == null ? new NibbleArray() : new NibbleArray((byte[]) this.a.clone()); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index c652897aae99c48c6cc020b5d64f6a8b02beecb5..c95fcdf47db8bfe59a83c0d28f4744b4d8540ef8 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet; - import it.unimi.dsi.fastutil.longs.LongSet; - import it.unimi.dsi.fastutil.shorts.ShortList; - import it.unimi.dsi.fastutil.shorts.ShortListIterator; -+import java.util.ArrayDeque; // Paper - import java.util.Arrays; - import java.util.BitSet; - import java.util.EnumSet; -@@ -66,7 +67,29 @@ public class ChunkRegionLoader { - - private static final Logger LOGGER = LogManager.getLogger(); - -+ // Paper start -+ public static final class InProgressChunkHolder { -+ -+ public final ProtoChunk protoChunk; -+ public final ArrayDeque tasks; -+ -+ public NBTTagCompound poiData; -+ -+ public InProgressChunkHolder(final ProtoChunk protoChunk, final ArrayDeque tasks) { -+ this.protoChunk = protoChunk; -+ this.tasks = tasks; -+ } -+ } -+ - public static ProtoChunk loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { -+ InProgressChunkHolder holder = loadChunk(worldserver, definedstructuremanager, villageplace, chunkcoordintpair, nbttagcompound, true); -+ holder.tasks.forEach(Runnable::run); -+ return holder.protoChunk; -+ } -+ -+ public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) { -+ ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); -+ // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); - WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); -@@ -93,7 +116,9 @@ public class ChunkRegionLoader { - LightEngine lightengine = chunkproviderserver.getLightEngine(); - - if (flag) { -- lightengine.b(chunkcoordintpair, true); -+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main -+ lightengine.b(chunkcoordintpair, true); -+ }); // Paper - delay this task since we're executing off-main - } - - for (int i = 0; i < nbttaglist.size(); ++i) { -@@ -109,16 +134,28 @@ public class ChunkRegionLoader { - achunksection[b0] = chunksection; - } - -- villageplace.a(chunkcoordintpair, chunksection); -+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main -+ villageplace.a(chunkcoordintpair, chunksection); -+ }); // Paper - delay this task since we're executing off-main - } - - if (flag) { - if (nbttagcompound2.hasKeyOfType("BlockLight", 7)) { -- lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), new NibbleArray(nbttagcompound2.getByteArray("BlockLight")), true); -+ // Paper start - delay this task since we're executing off-main -+ NibbleArray blockLight = new NibbleArray(nbttagcompound2.getByteArray("BlockLight")); -+ tasksToExecuteOnMain.add(() -> { -+ lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), blockLight, true); -+ }); -+ // Paper end - delay this task since we're executing off-main - } - - if (flag2 && nbttagcompound2.hasKeyOfType("SkyLight", 7)) { -- lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), new NibbleArray(nbttagcompound2.getByteArray("SkyLight")), true); -+ // Paper start - delay this task since we're executing off-main -+ NibbleArray skyLight = new NibbleArray(nbttagcompound2.getByteArray("SkyLight")); -+ tasksToExecuteOnMain.add(() -> { -+ lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), skyLight, true); -+ }); -+ // Paper end - delay this task since we're executing off-main - } - } - } -@@ -227,7 +264,7 @@ public class ChunkRegionLoader { - } - - if (chunkstatus_type == ChunkStatus.Type.LEVELCHUNK) { -- return new ProtoChunkExtension((Chunk) object); -+ return new InProgressChunkHolder(new ProtoChunkExtension((Chunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading - } else { - ProtoChunk protochunk1 = (ProtoChunk) object; - -@@ -266,11 +303,83 @@ public class ChunkRegionLoader { - protochunk1.a(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1))); - } - -- return protochunk1; -+ return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading -+ } -+ } -+ -+ // Paper start - async chunk save for unload -+ public static final class AsyncSaveData { -+ public final NibbleArray[] blockLight; // null or size of 17 (for indices -1 through 15) -+ public final NibbleArray[] skyLight; -+ -+ public final NBTTagList blockTickList; // non-null if we had to go to the server's tick list -+ public final NBTTagList fluidTickList; // non-null if we had to go to the server's tick list -+ -+ public final long worldTime; -+ -+ public AsyncSaveData(NibbleArray[] blockLight, NibbleArray[] skyLight, NBTTagList blockTickList, NBTTagList fluidTickList, -+ long worldTime) { -+ this.blockLight = blockLight; -+ this.skyLight = skyLight; -+ this.blockTickList = blockTickList; -+ this.fluidTickList = fluidTickList; -+ this.worldTime = worldTime; - } - } - -+ // must be called sync -+ public static AsyncSaveData getAsyncSaveData(WorldServer world, IChunkAccess chunk) { -+ org.spigotmc.AsyncCatcher.catchOp("preparation of chunk data for async save"); -+ ChunkCoordIntPair chunkPos = chunk.getPos(); -+ -+ LightEngineThreaded lightenginethreaded = world.getChunkProvider().getLightEngine(); -+ -+ NibbleArray[] blockLight = new NibbleArray[17 - (-1)]; -+ NibbleArray[] skyLight = new NibbleArray[17 - (-1)]; -+ -+ for (int i = -1; i < 17; ++i) { -+ NibbleArray blockArray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkPos, i)); -+ NibbleArray skyArray = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkPos, i)); -+ -+ // copy data for safety -+ if (blockArray != null) { -+ blockArray = blockArray.copy(); -+ } -+ if (skyArray != null) { -+ skyArray = skyArray.copy(); -+ } -+ -+ // apply offset of 1 for -1 starting index -+ blockLight[i + 1] = blockArray; -+ skyLight[i + 1] = skyArray; -+ } -+ -+ TickList blockTickList = chunk.n(); -+ -+ NBTTagList blockTickListSerialized; -+ if (blockTickList instanceof ProtoChunkTickList || blockTickList instanceof TickListChunk) { -+ blockTickListSerialized = null; -+ } else { -+ blockTickListSerialized = world.getBlockTickList().a(chunkPos); -+ } -+ -+ TickList fluidTickList = chunk.o(); -+ -+ NBTTagList fluidTickListSerialized; -+ if (fluidTickList instanceof ProtoChunkTickList || fluidTickList instanceof TickListChunk) { -+ fluidTickListSerialized = null; -+ } else { -+ fluidTickListSerialized = world.getFluidTickList().a(chunkPos); -+ } -+ -+ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, world.getTime()); -+ } -+ - public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess) { -+ return saveChunk(worldserver, ichunkaccess, null); -+ } -+ public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { -+ // Paper end - ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); - NBTTagCompound nbttagcompound = new NBTTagCompound(); - NBTTagCompound nbttagcompound1 = new NBTTagCompound(); -@@ -279,7 +388,7 @@ public class ChunkRegionLoader { - nbttagcompound.set("Level", nbttagcompound1); - nbttagcompound1.setInt("xPos", chunkcoordintpair.x); - nbttagcompound1.setInt("zPos", chunkcoordintpair.z); -- nbttagcompound1.setLong("LastUpdate", worldserver.getTime()); -+ nbttagcompound1.setLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getTime()); // Paper - async chunk unloading - nbttagcompound1.setLong("InhabitedTime", ichunkaccess.getInhabitedTime()); - nbttagcompound1.setString("Status", ichunkaccess.getChunkStatus().d()); - ChunkConverter chunkconverter = ichunkaccess.p(); -@@ -295,14 +404,22 @@ public class ChunkRegionLoader { - - NBTTagCompound nbttagcompound2; - -- for (int i = -1; i < 17; ++i) { -+ for (int i = -1; i < 17; ++i) { // Paper - conflict on loop parameter change - int finalI = i; // CraftBukkit - decompile errors - ChunkSection chunksection = (ChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { - return chunksection1 != null && chunksection1.getYPosition() >> 4 == finalI; // CraftBukkit - decompile errors - }).findFirst().orElse(Chunk.a); -- NibbleArray nibblearray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, i)); -- NibbleArray nibblearray1 = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, i)); -- -+ // Paper start - async chunk save for unload -+ NibbleArray nibblearray; // block light -+ NibbleArray nibblearray1; // sky light -+ if (asyncsavedata == null) { -+ nibblearray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, i)); /// Paper - diff on method change (see getAsyncSaveData) -+ nibblearray1 = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, i)); // Paper - diff on method change (see getAsyncSaveData) -+ } else { -+ nibblearray = asyncsavedata.blockLight[i + 1]; // +1 to offset the -1 starting index -+ nibblearray1 = asyncsavedata.skyLight[i + 1]; // +1 to offset the -1 starting index -+ } -+ // Paper end - if (chunksection != Chunk.a || nibblearray != null || nibblearray1 != null) { - nbttagcompound2 = new NBTTagCompound(); - nbttagcompound2.setByte("Y", (byte) (i & 255)); -@@ -369,7 +486,7 @@ public class ChunkRegionLoader { - Entity entity = (Entity) iterator1.next(); - NBTTagCompound nbttagcompound4 = new NBTTagCompound(); - // Paper start -- if ((int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { -+ if (asyncsavedata == null && !entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { - toUpdate.add(entity); - continue; - } -@@ -412,24 +529,32 @@ public class ChunkRegionLoader { - } - - nbttagcompound1.set("Entities", nbttaglist2); -- TickList ticklist = ichunkaccess.n(); -+ TickList ticklist = ichunkaccess.n(); // Paper - diff on method change (see getAsyncSaveData) - - if (ticklist instanceof ProtoChunkTickList) { - nbttagcompound1.set("ToBeTicked", ((ProtoChunkTickList) ticklist).b()); - } else if (ticklist instanceof TickListChunk) { - nbttagcompound1.set("TileTicks", ((TickListChunk) ticklist).b()); -+ // Paper start - async chunk save for unload -+ } else if (asyncsavedata != null) { -+ nbttagcompound1.set("TileTicks", asyncsavedata.blockTickList); -+ // Paper end - } else { -- nbttagcompound1.set("TileTicks", worldserver.getBlockTickList().a(chunkcoordintpair)); -+ nbttagcompound1.set("TileTicks", worldserver.getBlockTickList().a(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) - } - -- TickList ticklist1 = ichunkaccess.o(); -+ TickList ticklist1 = ichunkaccess.o(); // Paper - diff on method change (see getAsyncSaveData) - - if (ticklist1 instanceof ProtoChunkTickList) { - nbttagcompound1.set("LiquidsToBeTicked", ((ProtoChunkTickList) ticklist1).b()); - } else if (ticklist1 instanceof TickListChunk) { - nbttagcompound1.set("LiquidTicks", ((TickListChunk) ticklist1).b()); -+ // Paper start - async chunk save for unload -+ } else if (asyncsavedata != null) { -+ nbttagcompound1.set("LiquidTicks", asyncsavedata.fluidTickList); -+ // Paper end - } else { -- nbttagcompound1.set("LiquidTicks", worldserver.getFluidTickList().a(chunkcoordintpair)); -+ nbttagcompound1.set("LiquidTicks", worldserver.getFluidTickList().a(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) - } - - nbttagcompound1.set("PostProcessing", a(ichunkaccess.l())); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -index d785f44cd503d4d91589f3fc4bc8dc805dff3d41..01ae13385dd0208c9f34da8b3897b571f86305d0 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -@@ -3,6 +3,10 @@ package net.minecraft.world.level.chunk.storage; - import com.mojang.datafixers.DataFixer; - import java.io.File; - import java.io.IOException; -+// Paper start -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.CompletionException; -+// Paper end - import java.util.function.Supplier; - import javax.annotation.Nullable; - import net.minecraft.SharedConstants; -@@ -25,32 +29,41 @@ import net.minecraft.world.level.dimension.DimensionManager; - - public class IChunkLoader implements AutoCloseable { - -- private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER -+ // Paper - OBFHELPER - nuke IOWorker - protected final DataFixer b; - @Nullable -- private PersistentStructureLegacy c; -+ private volatile PersistentStructureLegacy c; // Paper - async chunk loading -+ -+ private final Object persistentDataLock = new Object(); // Paper -+ public final RegionFileCache regionFileCache; - - public IChunkLoader(File file, DataFixer datafixer, boolean flag) { -+ this.regionFileCache = new RegionFileCache(file, flag); // Paper - nuke IOWorker - this.b = datafixer; -- this.a = new IOWorker(file, flag, "chunk"); -+ // Paper - nuke IOWorker - } - - // CraftBukkit start - private boolean check(ChunkProviderServer cps, int x, int z) throws IOException { - ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z); - if (cps != null) { -- com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); -- if (cps.isLoaded(x, z)) { -+ //com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe -+ if (cps.getChunkAtIfCachedImmediately(x, z) != null) { // Paper - isLoaded is a ticket level check, not a chunk loaded check! - return true; - } - } - -- NBTTagCompound nbt = read(pos); -- if (nbt != null) { -- NBTTagCompound level = nbt.getCompound("Level"); -- if (level.getBoolean("TerrainPopulated")) { -- return true; -- } -+ -+ // Paper start - prioritize -+ NBTTagCompound nbt = cps == null ? read(pos) : -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.loadChunkData((WorldServer)cps.getWorld(), x, z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHER_PRIORITY, false, true).chunkData; -+ // Paper end -+ if (nbt != null) { -+ NBTTagCompound level = nbt.getCompound("Level"); -+ if (level.getBoolean("TerrainPopulated")) { -+ return true; -+ } - - ChunkStatus status = ChunkStatus.a(level.getString("Status")); - if (status != null && status.b(ChunkStatus.FEATURES)) { -@@ -81,11 +94,13 @@ public class IChunkLoader implements AutoCloseable { - if (i < 1493) { - nbttagcompound = GameProfileSerializer.a(this.b, DataFixTypes.CHUNK, nbttagcompound, i, 1493); - if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { -+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading - if (this.c == null) { - this.c = PersistentStructureLegacy.a(resourcekey, (WorldPersistentData) supplier.get()); - } - - nbttagcompound = this.c.a(nbttagcompound); -+ } // Paper - Async chunk loading - } - } - -@@ -103,22 +118,20 @@ public class IChunkLoader implements AutoCloseable { - - @Nullable - public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { -- return this.a.a(chunkcoordintpair); -+ return this.regionFileCache.read(chunkcoordintpair); - } - -- public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { -- this.a.a(chunkcoordintpair, nbttagcompound); -+ public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER -+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) -+ this.regionFileCache.write(chunkcoordintpair, nbttagcompound); - if (this.c != null) { -+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading - this.c.a(chunkcoordintpair.pair()); -+ } // Paper - Async chunk loading} - } -- -- } -- -- public void i() { -- this.a.a().join(); - } - - public void close() throws IOException { -- this.a.close(); -+ this.regionFileCache.close(); - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index d50b9c9d030016f951e2ed7fb519250b7408c833..1b0535ba211904b2384cc80c02c21ed1a606e752 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -45,6 +45,8 @@ public class RegionFile implements AutoCloseable { - protected final RegionFileBitSet freeSectors; - public final File file; // Paper - -+ public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper -+ - // Paper start - Cache chunk status - private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; - -@@ -251,7 +253,7 @@ public class RegionFile implements AutoCloseable { - return (i + 4096 - 1) / 4096; - } - -- public boolean b(ChunkCoordIntPair chunkcoordintpair) { -+ public synchronized boolean b(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronized - int i = this.getOffset(chunkcoordintpair); - - if (i == 0) { -@@ -411,6 +413,11 @@ public class RegionFile implements AutoCloseable { - } - - public void close() throws IOException { -+ // Paper start - Prevent regionfiles from being closed during use -+ this.fileLock.lock(); -+ synchronized (this) { -+ try { -+ // Paper end - this.closed = true; // Paper - try { - this.d(); -@@ -421,6 +428,10 @@ public class RegionFile implements AutoCloseable { - this.dataFile.close(); - } - } -+ } finally { // Paper start - Prevent regionfiles from being closed during use -+ this.fileLock.unlock(); -+ } -+ } // Paper end - - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index 55e7e983d2c760a8052d7b3ddbdc8447f619a60f..ebb0d6988f87013ea5d523ab4a1b31cb669ccc43 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -17,7 +17,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionSuppressor; - import net.minecraft.world.level.ChunkCoordIntPair; - --public final class RegionFileCache implements AutoCloseable { -+public class RegionFileCache implements AutoCloseable { // Paper - no final - - public final Long2ObjectLinkedOpenHashMap cache = new Long2ObjectLinkedOpenHashMap(); - private final File b; -@@ -30,16 +30,27 @@ public final class RegionFileCache implements AutoCloseable { - - - // Paper start -- public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { -+ public synchronized RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronize for async io - return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); - } - - // Paper end -- public RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public -+ public synchronized RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public, synchronize -+ // Paper start - add lock parameter -+ return this.getFile(chunkcoordintpair, existingOnly, false); -+ } -+ public synchronized RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly, boolean lock) throws IOException { -+ // Paper end - long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); - RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i); - - if (regionfile != null) { -+ // Paper start -+ if (lock) { -+ // must be in this synchronized block -+ regionfile.fileLock.lock(); -+ } -+ // Paper end - return regionfile; - } else { - if (this.cache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable -@@ -55,6 +66,12 @@ public final class RegionFileCache implements AutoCloseable { - RegionFile regionfile1 = new RegionFile(file, this.b, this.c); - - this.cache.putAndMoveToFirst(i, regionfile1); -+ // Paper start -+ if (lock) { -+ // must be in this synchronized block -+ regionfile1.fileLock.lock(); -+ } -+ // Paper end - return regionfile1; - } - } -@@ -130,11 +147,12 @@ public final class RegionFileCache implements AutoCloseable { - @Nullable - public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { - // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing -- RegionFile regionfile = this.getFile(chunkcoordintpair, true); -+ RegionFile regionfile = this.getFile(chunkcoordintpair, true, true); // Paper - if (regionfile == null) { - return null; - } - // CraftBukkit end -+ try { // Paper - DataInputStream datainputstream = regionfile.a(chunkcoordintpair); - // Paper start - if (regionfile.isOversized(chunkcoordintpair.x, chunkcoordintpair.z)) { -@@ -172,10 +190,14 @@ public final class RegionFileCache implements AutoCloseable { - } - - return nbttagcompound; -+ } finally { // Paper start -+ regionfile.fileLock.unlock(); -+ } // Paper end - } - - protected void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { -- RegionFile regionfile = this.getFile(chunkcoordintpair, false); // CraftBukkit -+ RegionFile regionfile = this.getFile(chunkcoordintpair, false, true); // CraftBukkit // Paper -+ try { // Paper - int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper - DataOutputStream dataoutputstream = regionfile.c(chunkcoordintpair); - Throwable throwable = null; -@@ -214,9 +236,12 @@ public final class RegionFileCache implements AutoCloseable { - MinecraftServer.LOGGER.error("Failed to save chunk", laste); - } - // Paper end -+ } finally { // Paper start -+ regionfile.fileLock.unlock(); -+ } // Paper end - } - -- public void close() throws IOException { -+ public synchronized void close() throws IOException { // Paper -> synchronized - ExceptionSuppressor exceptionsuppressor = new ExceptionSuppressor<>(); - ObjectIterator objectiterator = this.cache.values().iterator(); - -@@ -243,4 +268,12 @@ public final class RegionFileCache implements AutoCloseable { - } - - } -+ -+ // CraftBukkit start -+ public synchronized boolean chunkExists(ChunkCoordIntPair pos) throws IOException { // Paper - synchronize -+ RegionFile regionfile = getFile(pos, true); -+ -+ return regionfile != null ? regionfile.chunkExists(pos) : false; -+ } -+ // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java -index 8ad97a8a2189553da88810380b1c240079eacc93..d3b9a9e4695655860c72db5f2188472681e8d37a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java -@@ -30,28 +30,29 @@ import net.minecraft.world.level.World; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - --public class RegionFileSection implements AutoCloseable { -+public class RegionFileSection extends RegionFileCache implements AutoCloseable { // Paper - nuke IOWorker - - private static final Logger LOGGER = LogManager.getLogger(); -- private final IOWorker b; -+ // Paper - nuke IOWorker - private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); -- private final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); -+ public final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> public - private final Function> e; - private final Function f; - private final DataFixer g; - private final DataFixTypes h; - - public RegionFileSection(File file, Function> function, Function function1, DataFixer datafixer, DataFixTypes datafixtypes, boolean flag) { -+ super(file, flag); // Paper - nuke IOWorker - this.e = function; - this.f = function1; - this.g = datafixer; - this.h = datafixtypes; -- this.b = new IOWorker(file, flag, file.getName()); -+ //this.b = new IOWorker(file, flag, file.getName()); // Paper - nuke IOWorker - } - - protected void a(BooleanSupplier booleansupplier) { - while (!this.d.isEmpty() && booleansupplier.getAsBoolean()) { -- ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).r(); -+ ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).r(); // Paper - conflict here to avoid obfhelpers - - this.d(chunkcoordintpair); - } -@@ -105,13 +106,18 @@ public class RegionFileSection implements AutoCloseable { - } - - private void b(ChunkCoordIntPair chunkcoordintpair) { -- this.a(chunkcoordintpair, DynamicOpsNBT.a, this.c(chunkcoordintpair)); -+ // Paper start - load data in function -+ this.loadInData(chunkcoordintpair, this.c(chunkcoordintpair)); -+ } -+ public void loadInData(ChunkCoordIntPair chunkPos, NBTTagCompound compound) { -+ this.a(chunkPos, DynamicOpsNBT.a, compound); -+ // Paper end - } - - @Nullable - private NBTTagCompound c(ChunkCoordIntPair chunkcoordintpair) { - try { -- return this.b.a(chunkcoordintpair); -+ return this.read(chunkcoordintpair); // Paper - nuke IOWorker - } catch (IOException ioexception) { - RegionFileSection.LOGGER.error("Error reading chunk {} data from disk", chunkcoordintpair, ioexception); - return null; -@@ -157,17 +163,31 @@ public class RegionFileSection implements AutoCloseable { - } - - private void d(ChunkCoordIntPair chunkcoordintpair) { -- Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); -+ Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); // Paper - conflict here to avoid adding obfhelpers :) - NBTBase nbtbase = (NBTBase) dynamic.getValue(); - - if (nbtbase instanceof NBTTagCompound) { -- this.b.a(chunkcoordintpair, (NBTTagCompound) nbtbase); -+ try { this.write(chunkcoordintpair, (NBTTagCompound) nbtbase); } catch (IOException ioexception) { RegionFileSection.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker // TODO make this write async - } else { - RegionFileSection.LOGGER.error("Expected compound tag, got {}", nbtbase); - } - - } - -+ // Paper start - internal get data function, copied from above -+ private NBTTagCompound getDataInternal(ChunkCoordIntPair chunkcoordintpair) { -+ Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); -+ NBTBase nbtbase = (NBTBase) dynamic.getValue(); -+ -+ if (nbtbase instanceof NBTTagCompound) { -+ return (NBTTagCompound)nbtbase; -+ } else { -+ RegionFileSection.LOGGER.error("Expected compound tag, got {}", nbtbase); -+ } -+ return null; -+ } -+ // Paper end -+ - private Dynamic a(ChunkCoordIntPair chunkcoordintpair, DynamicOps dynamicops) { - Map map = Maps.newHashMap(); - -@@ -213,9 +233,9 @@ public class RegionFileSection implements AutoCloseable { - public void a(ChunkCoordIntPair chunkcoordintpair) { - if (!this.d.isEmpty()) { - for (int i = 0; i < 16; ++i) { -- long j = SectionPosition.a(chunkcoordintpair, i).s(); -+ long j = SectionPosition.a(chunkcoordintpair, i).s(); // Paper - conflict here to avoid obfhelpers - -- if (this.d.contains(j)) { -+ if (this.d.contains(j)) { // Paper - conflict here to avoid obfhelpers - this.d(chunkcoordintpair); - return; - } -@@ -224,7 +244,26 @@ public class RegionFileSection implements AutoCloseable { - - } - -- public void close() throws IOException { -- this.b.close(); -+// Paper start - nuke IOWorker -+// public void close() throws IOException { -+// this.b.close(); -+// } -+// Paper end -+ -+ // Paper start - get data function -+ public NBTTagCompound getData(ChunkCoordIntPair chunkcoordintpair) { -+ // Note: Copied from above -+ // This is checking if the data exists, then it builds it later in getDataInternal(ChunkCoordIntPair) -+ if (!this.d.isEmpty()) { -+ for (int i = 0; i < 16; ++i) { -+ long j = SectionPosition.a(chunkcoordintpair, i).s(); -+ -+ if (this.d.contains(j)) { -+ return this.getDataInternal(chunkcoordintpair); -+ } -+ } -+ } -+ return null; - } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index d46c513512c25e55ccdb0be16524f19444c358c5..6aaf868cf3213e1935080c64c652c3055cb58e0c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -563,22 +563,23 @@ public class CraftWorld implements World { - return true; - } - -- net.minecraft.world.level.chunk.storage.RegionFile file; -- try { -- file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -- } catch (IOException ex) { -- throw new RuntimeException(ex); -- } -+ ChunkStatus status = world.getChunkProvider().playerChunkMap.getStatusOnDiskNoLoad(x, z); // Paper - async io - move to own method - -- ChunkStatus status = file.getStatusIfCached(x, z); -- if (!file.chunkExists(chunkPos) || (status != null && status != ChunkStatus.FULL)) { -+ // Paper start - async io -+ if (status == ChunkStatus.EMPTY) { -+ // does not exist on disk - return false; - } - -+ if (status == null) { // at this stage we don't know what it is on disk - IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.EMPTY, true); - if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.world.level.chunk.Chunk)) { - return false; - } -+ } else if (status != ChunkStatus.FULL) { -+ return false; // not full status on disk -+ } -+ // Paper end - - // fall through to load - // we do this so we do not re-read the chunk data on disk -@@ -2501,6 +2502,34 @@ public class CraftWorld implements World { - public DragonBattle getEnderDragonBattle() { - return (getHandle().getDragonBattle() == null) ? null : new CraftDragonBattle(getHandle().getDragonBattle()); - } -+ // Paper start -+ @Override -+ public CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { -+ if (Bukkit.isPrimaryThread()) { -+ net.minecraft.world.level.chunk.Chunk immediate = this.world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); -+ if (immediate != null) { -+ return CompletableFuture.completedFuture(immediate.getBukkitChunk()); -+ } -+ } else { -+ CompletableFuture future = new CompletableFuture(); -+ world.getMinecraftServer().execute(() -> { -+ getChunkAtAsync(x, z, gen, urgent).whenComplete((chunk, err) -> { -+ if (err != null) { -+ future.completeExceptionally(err); -+ } else { -+ future.complete(chunk); -+ } -+ }); -+ }); -+ return future; -+ } -+ -+ return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { -+ net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); -+ return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); -+ }, net.minecraft.server.MinecraftServer.getServer()); -+ } -+ // Paper end - - // Spigot start - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 93bbf63e9d38f32d5528c7693633d4b65655bb9d..266b2cbd6bfaf10743929a1eeb9732a5d1fb4c62 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -12,6 +12,9 @@ import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.TicketType; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityAreaEffectCloud; -@@ -144,6 +147,7 @@ import net.minecraft.world.entity.vehicle.EntityMinecartHopper; - import net.minecraft.world.entity.vehicle.EntityMinecartMobSpawner; - import net.minecraft.world.entity.vehicle.EntityMinecartRideable; - import net.minecraft.world.entity.vehicle.EntityMinecartTNT; -+import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.phys.AxisAlignedBB; - import org.bukkit.Chunk; // Paper - import org.bukkit.EntityEffect; -@@ -508,6 +512,28 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - entity.setHeadRotation(yaw); - } - -+ @Override// Paper start -+ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { -+ PlayerChunkMap playerChunkMap = ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().playerChunkMap; -+ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); -+ -+ loc.getWorld().getChunkAtAsyncUrgently(loc).thenCompose(chunk -> { -+ ChunkCoordIntPair pair = new ChunkCoordIntPair(chunk.getX(), chunk.getZ()); -+ ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().addTicketAtLevel(TicketType.POST_TELEPORT, pair, 31, 0); -+ PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pair.pair()); -+ if (updatingChunk != null) { -+ return updatingChunk.getEntityTickingFuture(); -+ } else { -+ return java.util.concurrent.CompletableFuture.completedFuture(com.mojang.datafixers.util.Either.left(((org.bukkit.craftbukkit.CraftChunk)chunk).getHandle())); -+ } -+ }).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { -+ future.completeExceptionally(ex); -+ return null; -+ }); -+ return future; -+ } -+ // Paper end -+ - @Override - public boolean teleport(Location location) { - return teleport(location, TeleportCause.PLUGIN); -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index abaefa0b71104756e4b458abefe13d179e7a1724..58e50bf0fb0f309227e1f4c1f6bb11c01d8e08d3 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -6,6 +6,7 @@ import java.lang.management.ThreadInfo; - import java.util.logging.Level; - import java.util.logging.Logger; - import com.destroystokyo.paper.PaperConfig; -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; // Paper - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; - -@@ -116,6 +117,7 @@ public class WatchdogThread extends Thread - // Paper end - Different message for short timeout - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper -+ ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // diff --git a/Unmapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch b/Unmapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch deleted file mode 100644 index 7b764afb8b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 8 Jul 2019 00:13:36 -0700 -Subject: [PATCH] Use getChunkIfLoadedImmediately in places - -This prevents us from hitting chunk loads for chunks at or less-than -ticket level 33 (yes getChunkIfLoaded will actually perform a chunk -load in that case). - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 52d22da115212eae6c380bb5012398e3df92f5f3..13c99bdb8894d08f297f84ee1f98f50c811f7f4b 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -207,7 +207,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI -- return this.chunkProvider.getChunkAt(x, z, false); -+ return this.chunkProvider.getChunkAtIfLoadedImmediately(x, z); // Paper - } - - // Paper start - Asynchronous IO -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index d74d6abfff647c148e524905cd733c4b7fc6591f..24dfdb3807dbf6e9acc59d35d7c76f7ac0185219 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1244,7 +1244,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - speed = player.abilities.walkSpeed * 10f; - } - // Paper start - Prevent moving into unloaded chunks -- if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && !worldserver.isChunkLoaded((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { -+ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && worldserver.getChunkIfLoadedImmediately((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4) == null) { // Paper - use getIfLoadedImmediately - this.internalTeleport(this.player.locX(), this.player.locY(), this.player.locZ(), this.player.yaw, this.player.pitch, Collections.emptySet()); - return; - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 15da3511a9e57c320f4cf409852bee07109095bc..b620d7e0d824c8d0758a66a8fbe872c3e45103d2 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -164,6 +164,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return (CraftServer) Bukkit.getServer(); - } - -+ // Paper start -+ @Override -+ public boolean isChunkLoaded(int x, int z) { -+ return ((WorldServer)this).getChunkIfLoaded(x, z) != null; -+ } -+ // Paper end -+ - public ResourceKey getTypeKey() { - return typeKey; - } -@@ -1062,14 +1069,14 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - public boolean p(BlockPosition blockposition) { -- return isOutsideWorld(blockposition) ? false : this.getChunkProvider().b(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return isOutsideWorld(blockposition) ? false : isChunkLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper - } - - public boolean a(BlockPosition blockposition, Entity entity, EnumDirection enumdirection) { - if (isOutsideWorld(blockposition)) { - return false; - } else { -- IChunkAccess ichunkaccess = this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, false); -+ IChunkAccess ichunkaccess = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper - - return ichunkaccess == null ? false : ichunkaccess.getType(blockposition).a((IBlockAccess) this, blockposition, entity, enumdirection); - } -@@ -1190,7 +1197,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- Chunk chunk = ichunkprovider.a(i1, j1); -+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.a(oclass, axisalignedbb, list, predicate); -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 58d22363124a9343188d8c19476e5a92f2f0b80b..53d0541aba207b5eaea2e49edbb56df918d30333 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -140,9 +140,10 @@ public class ActivationRange - { - for ( int j1 = k; j1 <= l; ++j1 ) - { -- if ( world.getWorld().isChunkLoaded( i1, j1 ) ) -+ Chunk chunk = (Chunk) world.getChunkIfLoadedImmediately( i1, j1 ); -+ if ( chunk != null ) - { -- activateChunkEntities( world.getChunkAt( i1, j1 ) ); -+ activateChunkEntities( chunk ); - } - } - } diff --git a/Unmapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch b/Unmapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch deleted file mode 100644 index 7b195978a9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0370-Reduce-sync-loads.patch +++ /dev/null @@ -1,342 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 19 Jul 2019 03:29:14 -0700 -Subject: [PATCH] Reduce sync loads - -This reduces calls to getChunkAt which would load chunks. - -This patch also adds a tool to find calls which are doing this, however -it must be enabled by setting the startup flag -Dpaper.debug-sync-loads=true - -To get a debug log for sync loads, the command is /paper syncloadinfo - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index f657e9b6bb3d24a6c77ef584711a003d1eea0341..eb1e86e8bb0f421e3686ffa02a4015a588107863 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -1,6 +1,7 @@ - package com.destroystokyo.paper; - - import com.destroystokyo.paper.io.chunk.ChunkTaskManager; -+import com.destroystokyo.paper.io.SyncLoadFinder; - import com.google.common.base.Functions; - import com.google.common.base.Joiner; - import com.google.common.collect.ImmutableSet; -@@ -8,6 +9,10 @@ import com.google.common.collect.Iterables; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import net.minecraft.resources.MinecraftKey; -+import com.google.gson.JsonObject; -+import com.google.gson.internal.Streams; -+import com.google.gson.stream.JsonWriter; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkProviderServer; - import net.minecraft.server.level.PlayerChunk; -@@ -29,6 +34,9 @@ import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.entity.Player; - - import java.io.File; -+import java.io.FileOutputStream; -+import java.io.PrintStream; -+import java.io.StringWriter; - import java.time.LocalDateTime; - import java.time.format.DateTimeFormatter; - import java.util.ArrayList; -@@ -44,7 +52,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); - - public PaperCommand(String name) { - super(name); -@@ -162,6 +170,9 @@ public class PaperCommand extends Command { - case "chunkinfo": - doChunkInfo(sender, args); - break; -+ case "syncloadinfo": -+ this.doSyncLoadInfo(sender, args); -+ break; - case "ver": - if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) - case "version": -@@ -179,6 +190,40 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doSyncLoadInfo(CommandSender sender, String[] args) { -+ if (!SyncLoadFinder.ENABLED) { -+ sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); -+ return; -+ } -+ File file = new File(new File(new File("."), "debug"), -+ "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); -+ file.getParentFile().mkdirs(); -+ sender.sendMessage(ChatColor.GREEN + "Writing sync load info to " + file.toString()); -+ -+ -+ try { -+ final JsonObject data = SyncLoadFinder.serialize(); -+ -+ StringWriter stringWriter = new StringWriter(); -+ JsonWriter jsonWriter = new JsonWriter(stringWriter); -+ jsonWriter.setIndent(" "); -+ jsonWriter.setLenient(false); -+ Streams.write(data, jsonWriter); -+ -+ String fileData = stringWriter.toString(); -+ -+ try ( -+ PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8") -+ ) { -+ out.print(fileData); -+ } -+ sender.sendMessage(ChatColor.GREEN + "Successfully written sync load information!"); -+ } catch (Throwable thr) { -+ sender.sendMessage(ChatColor.RED + "Failed to write sync load information"); -+ thr.printStackTrace(); -+ } -+ } -+ - private void doChunkInfo(CommandSender sender, String[] args) { - List worlds; - if (args.length < 2 || args[1].equals("*")) { -diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d381f91cf105bfc01846ada90da8971a3618e784 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -@@ -0,0 +1,171 @@ -+package com.destroystokyo.paper.io; -+ -+import com.google.gson.JsonArray; -+import com.google.gson.JsonObject; -+import com.mojang.datafixers.util.Pair; -+import it.unimi.dsi.fastutil.longs.Long2IntMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -+ -+import java.util.ArrayList; -+import java.util.List; -+import java.util.Map; -+import java.util.WeakHashMap; -+import net.minecraft.world.level.World; -+ -+public class SyncLoadFinder { -+ -+ public static final boolean ENABLED = Boolean.getBoolean("paper.debug-sync-loads"); -+ -+ private static final WeakHashMap> SYNC_LOADS = new WeakHashMap<>(); -+ -+ private static final class SyncLoadInformation { -+ -+ public int times; -+ -+ public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); -+ } -+ -+ public static void logSyncLoad(final World world, final int chunkX, final int chunkZ) { -+ if (!ENABLED) { -+ return; -+ } -+ -+ final ThrowableWithEquals stacktrace = new ThrowableWithEquals(Thread.currentThread().getStackTrace()); -+ -+ SYNC_LOADS.compute(world, (final World keyInMap, Object2ObjectOpenHashMap map) -> { -+ if (map == null) { -+ map = new Object2ObjectOpenHashMap<>(); -+ } -+ -+ map.compute(stacktrace, (ThrowableWithEquals keyInMap0, SyncLoadInformation valueInMap) -> { -+ if (valueInMap == null) { -+ valueInMap = new SyncLoadInformation(); -+ } -+ -+ ++valueInMap.times; -+ -+ valueInMap.coordinateTimes.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (Long keyInMap1, Integer valueInMap1) -> { -+ return valueInMap1 == null ? Integer.valueOf(1) : Integer.valueOf(valueInMap1.intValue() + 1); -+ }); -+ -+ return valueInMap; -+ }); -+ -+ return map; -+ }); -+ } -+ -+ public static JsonObject serialize() { -+ final JsonObject ret = new JsonObject(); -+ -+ final JsonArray worldsData = new JsonArray(); -+ -+ for (final Map.Entry> entry : SYNC_LOADS.entrySet()) { -+ final World world = entry.getKey(); -+ -+ final JsonObject worldData = new JsonObject(); -+ -+ worldData.addProperty("name", world.getWorld().getName()); -+ -+ final List> data = new ArrayList<>(); -+ -+ entry.getValue().forEach((ThrowableWithEquals stacktrace, SyncLoadInformation times) -> { -+ data.add(new Pair<>(stacktrace, times)); -+ }); -+ -+ data.sort((Pair pair1, Pair pair2) -> { -+ return Integer.compare(pair2.getSecond().times, pair1.getSecond().times); // reverse order -+ }); -+ -+ final JsonArray stacktraces = new JsonArray(); -+ -+ for (Pair pair : data) { -+ final JsonObject stacktrace = new JsonObject(); -+ -+ stacktrace.addProperty("times", pair.getSecond().times); -+ -+ final JsonArray traces = new JsonArray(); -+ -+ for (StackTraceElement element : pair.getFirst().stacktrace) { -+ traces.add(String.valueOf(element)); -+ } -+ -+ stacktrace.add("stacktrace", traces); -+ -+ final JsonArray coordinates = new JsonArray(); -+ -+ for (Long2IntMap.Entry coordinate : pair.getSecond().coordinateTimes.long2IntEntrySet()) { -+ final long key = coordinate.getLongKey(); -+ final int times = coordinate.getIntValue(); -+ coordinates.add("(" + IOUtil.getCoordinateX(key) + "," + IOUtil.getCoordinateZ(key) + "): " + times); -+ } -+ -+ stacktrace.add("coordinates", coordinates); -+ -+ stacktraces.add(stacktrace); -+ } -+ -+ -+ worldData.add("stacktraces", stacktraces); -+ worldsData.add(worldData); -+ } -+ -+ ret.add("worlds", worldsData); -+ -+ return ret; -+ } -+ -+ static final class ThrowableWithEquals { -+ -+ private final StackTraceElement[] stacktrace; -+ private final int hash; -+ -+ public ThrowableWithEquals(final StackTraceElement[] stacktrace) { -+ this.stacktrace = stacktrace; -+ this.hash = ThrowableWithEquals.hash(stacktrace); -+ } -+ -+ public static int hash(final StackTraceElement[] stacktrace) { -+ int hash = 0; -+ -+ for (int i = 0; i < stacktrace.length; ++i) { -+ hash *= 31; -+ hash += stacktrace[i].hashCode(); -+ } -+ -+ return hash; -+ } -+ -+ @Override -+ public int hashCode() { -+ return this.hash; -+ } -+ -+ @Override -+ public boolean equals(final Object obj) { -+ if (obj == null || obj.getClass() != this.getClass()) { -+ return false; -+ } -+ -+ final ThrowableWithEquals other = (ThrowableWithEquals)obj; -+ final StackTraceElement[] otherStackTrace = other.stacktrace; -+ -+ if (this.stacktrace.length != otherStackTrace.length || this.hash != other.hash) { -+ return false; -+ } -+ -+ if (this == obj) { -+ return true; -+ } -+ -+ for (int i = 0; i < this.stacktrace.length; ++i) { -+ if (!this.stacktrace[i].equals(otherStackTrace[i])) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 2a5df37a94b4b609a2d1b045f8e6a7f08d3f8eaa..24201665f8e7fb635839334308a1bad8fc4ac7b9 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -494,6 +494,7 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z); - // Paper end -+ com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.world, x, z); // Paper - sync load info - this.world.timings.syncChunkLoad.startTiming(); // Paper - this.serverThreadQueue.awaitTasks(completablefuture::isDone); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 13c99bdb8894d08f297f84ee1f98f50c811f7f4b..fbb550cce96e7e5539c69bae1459326090d0c508 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -282,6 +282,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { - }; - public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; - // Paper end -+ // Paper start -+ @Override -+ public boolean isChunkLoaded(int x, int z) { -+ return this.getChunkProvider().getChunkAtIfLoadedImmediately(x, z) != null; -+ } -+ // Paper end - - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index b620d7e0d824c8d0758a66a8fbe872c3e45103d2..6781b25cc8e15be2556bb1bb8dc8c18c106b40ec 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -1130,7 +1130,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - for (int i1 = i; i1 <= j; ++i1) { - for (int j1 = k; j1 <= l; ++j1) { -- Chunk chunk = ichunkprovider.getChunkAt(i1, j1, false); -+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.a(entity, axisalignedbb, list, predicate); -@@ -1151,7 +1151,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- Chunk chunk = this.getChunkProvider().getChunkAt(i1, j1, false); -+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.a(entitytypes, axisalignedbb, list, predicate); -@@ -1174,7 +1174,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- Chunk chunk = ichunkprovider.getChunkAt(i1, j1, false); -+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.a(oclass, axisalignedbb, list, predicate); diff --git a/Unmapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch b/Unmapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch deleted file mode 100644 index 4af6ed58d8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Mon, 3 Jun 2019 02:02:39 -0400 -Subject: [PATCH] Implement alternative item-despawn-rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1ee2cced100626e48eb36ee14f84b9257c79a2f8..b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -1,10 +1,15 @@ - package com.destroystokyo.paper; - - import java.util.Arrays; -+import java.util.EnumMap; -+import java.util.HashMap; - import java.util.List; -+import java.util.Map; - - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; - import org.bukkit.Bukkit; -+import org.bukkit.Material; -+import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -512,4 +517,52 @@ public class PaperWorldConfig { - private void disableRelativeProjectileVelocity() { - disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); - } -+ -+ public boolean altItemDespawnRateEnabled; -+ public Map altItemDespawnRateMap; -+ private void altItemDespawnRate() { -+ String path = "alt-item-despawn-rate"; -+ -+ altItemDespawnRateEnabled = getBoolean(path + ".enabled", false); -+ -+ Map altItemDespawnRateMapDefault = new EnumMap<>(Material.class); -+ altItemDespawnRateMapDefault.put(Material.COBBLESTONE, 300); -+ for (Material key : altItemDespawnRateMapDefault.keySet()) { -+ config.addDefault("world-settings.default." + path + ".items." + key, altItemDespawnRateMapDefault.get(key)); -+ } -+ -+ Map rawMap = new HashMap<>(); -+ try { -+ ConfigurationSection mapSection = config.getConfigurationSection("world-settings." + worldName + "." + path + ".items"); -+ if (mapSection == null) { -+ mapSection = config.getConfigurationSection("world-settings.default." + path + ".items"); -+ } -+ for (String key : mapSection.getKeys(false)) { -+ int val = mapSection.getInt(key); -+ rawMap.put(key, val); -+ } -+ } -+ catch (Exception e) { -+ logError("alt-item-despawn-rate was malformatted"); -+ altItemDespawnRateEnabled = false; -+ } -+ -+ altItemDespawnRateMap = new EnumMap<>(Material.class); -+ if (!altItemDespawnRateEnabled) { -+ return; -+ } -+ -+ for(String key : rawMap.keySet()) { -+ try { -+ altItemDespawnRateMap.put(Material.valueOf(key), rawMap.get(key)); -+ } catch (Exception e) { -+ logError("Could not add item " + key + " to altItemDespawnRateMap: " + e.getMessage()); -+ } -+ } -+ if(altItemDespawnRateEnabled) { -+ for(Material key : altItemDespawnRateMap.keySet()) { -+ log("Alternative item despawn rate of " + key + ": " + altItemDespawnRateMap.get(key)); -+ } -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 02e4d6891adc902f73ed349f15dae3a429bd283a..0b2e6e72a85e05f239d56afb6785c91da5b25d55 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -33,6 +33,7 @@ import net.minecraft.world.phys.Vec3D; - - // CraftBukkit start - import net.minecraft.server.MinecraftServer; -+import org.bukkit.Material; // Paper - import org.bukkit.event.entity.EntityPickupItemEvent; - import org.bukkit.event.player.PlayerPickupItemEvent; - // CraftBukkit end -@@ -161,7 +162,7 @@ public class EntityItem extends Entity { - } - } - -- if (!this.world.isClientSide && this.age >= world.spigotConfig.itemDespawnRate) { // Spigot -+ if (!this.world.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper - // CraftBukkit start - fire ItemDespawnEvent - if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { - this.age = 0; -@@ -185,7 +186,7 @@ public class EntityItem extends Entity { - this.lastTick = MinecraftServer.currentTick; - // CraftBukkit end - -- if (!this.world.isClientSide && this.age >= world.spigotConfig.itemDespawnRate) { // Spigot -+ if (!this.world.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper - // CraftBukkit start - fire ItemDespawnEvent - if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { - this.age = 0; -@@ -535,9 +536,16 @@ public class EntityItem extends Entity { - - public void s() { - this.o(); -- this.age = world.spigotConfig.itemDespawnRate - 1; // Spigot -+ this.age = this.getDespawnRate() - 1; // Spigot // Paper - } - -+ // Paper start -+ public int getDespawnRate(){ -+ Material material = this.getItemStack().getBukkitStack().getType(); -+ return world.paperConfig.altItemDespawnRateMap.getOrDefault(material, world.spigotConfig.itemDespawnRate); -+ } -+ // Paper end -+ - @Override - public Packet P() { - return new PacketPlayOutSpawnEntity(this); diff --git a/Unmapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/Unmapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch deleted file mode 100644 index 4968b9eb2f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Paul Sauve -Date: Sun, 14 Jul 2019 21:05:03 -0500 -Subject: [PATCH] Do less work if we have a custom Bukkit generator - -If the Bukkit generator already has a spawn, use it immediately instead -of spending time generating one that we won't use - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e6e8ab0b39a11b0aed247b9b80a6c1f97505546b..eb134ccb68dc135ab6db4c5a1d29edb321cf3f59 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -630,12 +630,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -- return biomebase.b().b(); -- }, random); -- ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition); -+ // Paper start - moved down - // CraftBukkit start - if (worldserver.generator != null) { - Random rand = new Random(worldserver.getSeed()); -@@ -651,6 +646,15 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ return biomebase.b().b(); -+ }, random); -+ ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition); -+ // Paper end - - if (blockposition == null) { - MinecraftServer.LOGGER.warn("Unable to find spawn biome"); diff --git a/Unmapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch b/Unmapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch deleted file mode 100644 index 023ce89b91..0000000000 --- a/Unmapped-Spigot-Server-Patches/0373-Fix-MC-158900.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 13 Aug 2019 06:35:17 -0700 -Subject: [PATCH] Fix MC-158900 - -The problem was we were checking isExpired() on the entry, but if it -was expired at that point, then it would be null. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index ec4e84f6275f8b305fb5a64f9c0cff24729d73ec..553b14f7167673938d1bc83d79c730692a4ef105 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -607,8 +607,10 @@ public abstract class PlayerList { - Player player = entity.getBukkitEntity(); - PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress()); - -- if (getProfileBans().isBanned(gameprofile) && !getProfileBans().get(gameprofile).hasExpired()) { -- GameProfileBanEntry gameprofilebanentry = (GameProfileBanEntry) this.k.get(gameprofile); -+ // Paper start - Fix MC-158900 -+ GameProfileBanEntry gameprofilebanentry; -+ if (getProfileBans().isBanned(gameprofile) && (gameprofilebanentry = getProfileBans().get(gameprofile)) != null) { -+ // Paper end - - chatmessage = new ChatMessage("multiplayer.disconnect.banned.reason", new Object[]{gameprofilebanentry.getReason()}); - if (gameprofilebanentry.getExpires() != null) { diff --git a/Unmapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch b/Unmapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch deleted file mode 100644 index 54831e29f7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch +++ /dev/null @@ -1,848 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Mon, 19 Aug 2019 01:27:58 +0500 -Subject: [PATCH] implement optional per player mob spawns - - -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -index 2da28784ee427001b1137c859f0b4c350abd3110..c5f594d45012016d99b83a778a2b9d20a7c086ac 100644 ---- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -57,6 +57,7 @@ public class WorldTimingsHandler { - - - public final Timing miscMobSpawning; -+ public final Timing playerMobDistanceMapUpdate; - - public final Timing poiUnload; - public final Timing chunkUnload; -@@ -122,6 +123,7 @@ public class WorldTimingsHandler { - - - miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ playerMobDistanceMapUpdate = Timings.ofSafe(name + "Per Player Mob Spawning - Distance Map Update"); - - poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); - chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920..6aec502eb529d4090306e12e837117cde7e114eb 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -565,4 +565,9 @@ public class PaperWorldConfig { - } - } - } -+ -+ public boolean perPlayerMobSpawns = false; -+ private void perPlayerMobSpawns() { -+ perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6124b54d99adbb2a5bb9bb09dfd02522a67ab3ba ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java -@@ -0,0 +1,252 @@ -+package com.destroystokyo.paper.util; -+ -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; -+import java.util.List; -+import java.util.Map; -+import net.minecraft.core.SectionPosition; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import org.spigotmc.AsyncCatcher; -+import java.util.HashMap; -+ -+/** @author Spottedleaf */ -+public final class PlayerMobDistanceMap { -+ -+ private static final PooledHashSets.PooledObjectLinkedOpenHashSet EMPTY_SET = new PooledHashSets.PooledObjectLinkedOpenHashSet<>(); -+ -+ private final Map players = new HashMap<>(); -+ // we use linked for better iteration. -+ private final Long2ObjectOpenHashMap> playerMap = new Long2ObjectOpenHashMap<>(32, 0.5f); -+ private int viewDistance; -+ -+ private final PooledHashSets pooledHashSets = new PooledHashSets<>(); -+ -+ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final ChunkCoordIntPair chunkPos) { -+ return this.getPlayersInRange(chunkPos.x, chunkPos.z); -+ } -+ -+ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final int chunkX, final int chunkZ) { -+ return this.playerMap.getOrDefault(ChunkCoordIntPair.pair(chunkX, chunkZ), EMPTY_SET); -+ } -+ -+ public void update(final List currentPlayers, final int newViewDistance) { -+ AsyncCatcher.catchOp("Distance map update"); -+ final ObjectLinkedOpenHashSet gone = new ObjectLinkedOpenHashSet<>(this.players.keySet()); -+ -+ final int oldViewDistance = this.viewDistance; -+ this.viewDistance = newViewDistance; -+ -+ for (final EntityPlayer player : currentPlayers) { -+ if (player.isSpectator() || !player.affectsSpawning) { -+ continue; // will be left in 'gone' (or not added at all) -+ } -+ -+ gone.remove(player); -+ -+ final SectionPosition newPosition = player.getPlayerMapSection(); -+ final SectionPosition oldPosition = this.players.put(player, newPosition); -+ -+ if (oldPosition == null) { -+ this.addNewPlayer(player, newPosition, newViewDistance); -+ } else { -+ this.updatePlayer(player, oldPosition, newPosition, oldViewDistance, newViewDistance); -+ } -+ //this.validatePlayer(player, newViewDistance); // debug only -+ } -+ -+ for (final EntityPlayer player : gone) { -+ final SectionPosition oldPosition = this.players.remove(player); -+ if (oldPosition != null) { -+ this.removePlayer(player, oldPosition, oldViewDistance); -+ } -+ } -+ } -+ -+ // expensive op, only for debug -+ private void validatePlayer(final EntityPlayer player, final int viewDistance) { -+ int entiesGot = 0; -+ int expectedEntries = (2 * viewDistance + 1); -+ expectedEntries *= expectedEntries; -+ -+ final SectionPosition currPosition = player.getPlayerMapSection(); -+ -+ final int centerX = currPosition.getX(); -+ final int centerZ = currPosition.getZ(); -+ -+ for (final Long2ObjectLinkedOpenHashMap.Entry> entry : this.playerMap.long2ObjectEntrySet()) { -+ final long key = entry.getLongKey(); -+ final PooledHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); -+ -+ if (map.referenceCount == 0) { -+ throw new IllegalStateException("Invalid map"); -+ } -+ -+ if (map.set.contains(player)) { -+ ++entiesGot; -+ -+ final int chunkX = ChunkCoordIntPair.getX(key); -+ final int chunkZ = ChunkCoordIntPair.getZ(key); -+ -+ final int dist = Math.max(Math.abs(chunkX - centerX), Math.abs(chunkZ - centerZ)); -+ -+ if (dist > viewDistance) { -+ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); -+ } -+ } -+ } -+ -+ if (entiesGot != expectedEntries) { -+ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); -+ } -+ } -+ -+ private void addPlayerTo(final EntityPlayer player, final int chunkX, final int chunkZ) { -+ this.playerMap.compute(ChunkCoordIntPair.pair(chunkX, chunkZ), (final Long key, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { -+ if (players == null) { -+ return player.cachedSingleMobDistanceMap; -+ } else { -+ return PlayerMobDistanceMap.this.pooledHashSets.findMapWith(players, player); -+ } -+ }); -+ } -+ -+ private void removePlayerFrom(final EntityPlayer player, final int chunkX, final int chunkZ) { -+ this.playerMap.compute(ChunkCoordIntPair.pair(chunkX, chunkZ), (final Long keyInMap, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { -+ return PlayerMobDistanceMap.this.pooledHashSets.findMapWithout(players, player); // rets null instead of an empty map -+ }); -+ } -+ -+ private void updatePlayer(final EntityPlayer player, final SectionPosition oldPosition, final SectionPosition newPosition, final int oldViewDistance, final int newViewDistance) { -+ final int toX = newPosition.getX(); -+ final int toZ = newPosition.getZ(); -+ final int fromX = oldPosition.getX(); -+ final int fromZ = oldPosition.getZ(); -+ -+ final int dx = toX - fromX; -+ final int dz = toZ - fromZ; -+ -+ final int totalX = Math.abs(fromX - toX); -+ final int totalZ = Math.abs(fromZ - toZ); -+ -+ if (Math.max(totalX, totalZ) > (2 * oldViewDistance)) { -+ // teleported? -+ this.removePlayer(player, oldPosition, oldViewDistance); -+ this.addNewPlayer(player, newPosition, newViewDistance); -+ return; -+ } -+ -+ // x axis is width -+ // z axis is height -+ // right refers to the x axis of where we moved -+ // top refers to the z axis of where we moved -+ -+ if (oldViewDistance == newViewDistance) { -+ // same view distance -+ -+ // used for relative positioning -+ final int up = 1 | (dz >> (Integer.SIZE - 1)); // 1 if dz >= 0, -1 otherwise -+ final int right = 1 | (dx >> (Integer.SIZE - 1)); // 1 if dx >= 0, -1 otherwise -+ -+ // The area excluded by overlapping the two view distance squares creates four rectangles: -+ // Two on the left, and two on the right. The ones on the left we consider the "removed" section -+ // and on the right the "added" section. -+ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually -+ // exclusive to the regions they surround. -+ -+ // 4 points of the rectangle -+ int maxX; // exclusive -+ int minX; // inclusive -+ int maxZ; // exclusive -+ int minZ; // inclusive -+ -+ if (dx != 0) { -+ // handle right addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX + (oldViewDistance * right) + right; // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addPlayerTo(player, currX, currZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle up addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = toX - (oldViewDistance * right); // inclusive -+ maxZ = toZ + (oldViewDistance * up) + up; // exclusive -+ minZ = fromZ + (oldViewDistance * up) + up; // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addPlayerTo(player, currX, currZ); -+ } -+ } -+ } -+ -+ if (dx != 0) { -+ // handle left removal -+ -+ maxX = toX - (oldViewDistance * right); // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removePlayerFrom(player, currX, currZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle down removal -+ -+ maxX = fromX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = toZ - (oldViewDistance * up); // exclusive -+ minZ = fromZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removePlayerFrom(player, currX, currZ); -+ } -+ } -+ } -+ } else { -+ // different view distance -+ // for now :) -+ this.removePlayer(player, oldPosition, oldViewDistance); -+ this.addNewPlayer(player, newPosition, newViewDistance); -+ } -+ } -+ -+ private void removePlayer(final EntityPlayer player, final SectionPosition position, final int viewDistance) { -+ final int x = position.getX(); -+ final int z = position.getZ(); -+ -+ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { -+ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { -+ this.removePlayerFrom(player, x + xoff, z + zoff); -+ } -+ } -+ } -+ -+ private void addNewPlayer(final EntityPlayer player, final SectionPosition position, final int viewDistance) { -+ final int x = position.getX(); -+ final int z = position.getZ(); -+ -+ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { -+ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { -+ this.addPlayerTo(player, x + xoff, z + zoff); -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4f13d3ff8391793a99f067189f854078334499c6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java -@@ -0,0 +1,241 @@ -+package com.destroystokyo.paper.util; -+ -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; -+import java.lang.ref.WeakReference; -+import java.util.Iterator; -+ -+/** @author Spottedleaf */ -+public class PooledHashSets { -+ -+ // we really want to avoid that equals() check as much as possible... -+ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(64, 0.25f); -+ -+ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { -+ if (current.referenceCount == 0) { -+ throw new IllegalStateException("Cannot decrement reference count for " + current); -+ } -+ if (current.referenceCount == -1 || --current.referenceCount > 0) { -+ return; -+ } -+ -+ this.mapPool.remove(current); -+ return; -+ } -+ -+ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { -+ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); -+ -+ if (cached != null) { -+ if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ decrementReferenceCount(current); -+ -+ return cached; -+ } -+ -+ if (!current.add(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.remove(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.remove(object); -+ } -+ -+ current.updateAddCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ // rets null if current.size() == 1 -+ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { -+ if (current.set.size() == 1) { -+ decrementReferenceCount(current); -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); -+ -+ if (cached != null) { -+ if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ decrementReferenceCount(current); -+ -+ return cached; -+ } -+ -+ if (!current.remove(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.add(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.add(object); -+ } -+ -+ current.updateRemoveCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ public static final class PooledObjectLinkedOpenHashSet implements Iterable { -+ -+ private static final WeakReference NULL_REFERENCE = new WeakReference(null); -+ -+ final ObjectLinkedOpenHashSet set; -+ int referenceCount; // -1 if special -+ int hash; // optimize hashcode -+ -+ // add cache -+ WeakReference lastAddObject = NULL_REFERENCE; -+ WeakReference> lastAddMap = NULL_REFERENCE; -+ -+ // remove cache -+ WeakReference lastRemoveObject = NULL_REFERENCE; -+ WeakReference> lastRemoveMap = NULL_REFERENCE; -+ -+ public PooledObjectLinkedOpenHashSet() { -+ this.set = new ObjectLinkedOpenHashSet<>(2, 0.6f); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final E single) { -+ this(); -+ this.referenceCount = -1; -+ this.add(single); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { -+ this.set = other.set.clone(); -+ this.hash = other.hash; -+ } -+ -+ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java -+ // generated by https://github.com/skeeto/hash-prospector -+ static int hash0(int x) { -+ x *= 0x36935555; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ public PooledObjectLinkedOpenHashSet getAddCache(final E element) { -+ final E currentAdd = this.lastAddObject.get(); -+ -+ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet map = this.lastAddMap.get(); -+ if (map == null || map.referenceCount == 0) { -+ // we need to ret null if ref count is zero as calling code will assume the map is in use -+ return null; -+ } -+ -+ return map; -+ } -+ -+ public PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { -+ final E currentRemove = this.lastRemoveObject.get(); -+ -+ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet map = this.lastRemoveMap.get(); -+ if (map == null || map.referenceCount == 0) { -+ // we need to ret null if ref count is zero as calling code will assume the map is in use -+ return null; -+ } -+ -+ return map; -+ } -+ -+ public void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastAddObject = new WeakReference<>(element); -+ this.lastAddMap = new WeakReference<>(map); -+ } -+ -+ public void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastRemoveObject = new WeakReference<>(element); -+ this.lastRemoveMap = new WeakReference<>(map); -+ } -+ -+ boolean add(final E element) { -+ boolean added = this.set.add(element); -+ -+ if (added) { -+ this.hash += hash0(element.hashCode()); -+ } -+ -+ return added; -+ } -+ -+ boolean remove(Object element) { -+ boolean removed = this.set.remove(element); -+ -+ if (removed) { -+ this.hash -= hash0(element.hashCode()); -+ } -+ -+ return removed; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return this.set.iterator(); -+ } -+ -+ @Override -+ public int hashCode() { -+ return this.hash; -+ } -+ -+ @Override -+ public boolean equals(final Object other) { -+ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { -+ return false; -+ } -+ if (this.referenceCount == 0) { -+ return other == this; -+ } else { -+ if (other == this) { -+ // Unfortunately we are never equal to our own instance while in use! -+ return false; -+ } -+ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); -+ } -+ } -+ -+ @Override -+ public String toString() { -+ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + -+ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 24201665f8e7fb635839334308a1bad8fc4ac7b9..12b9be00d486ec960ef0ebc750f56011c90ce37c 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -767,7 +767,22 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.getMethodProfiler().enter("naturalSpawnCount"); - this.world.timings.countNaturalMobs.startTiming(); // Paper - timings - int l = this.chunkMapDistance.b(); -- SpawnerCreature.d spawnercreature_d = SpawnerCreature.a(l, this.world.A(), this::a); -+ // Paper start - per player mob spawning -+ SpawnerCreature.d spawnercreature_d; // moved down -+ if (this.playerChunkMap.playerMobDistanceMap != null) { -+ // update distance map -+ this.world.timings.playerMobDistanceMapUpdate.startTiming(); -+ this.playerChunkMap.playerMobDistanceMap.update(this.world.players, this.playerChunkMap.viewDistance); -+ this.world.timings.playerMobDistanceMapUpdate.stopTiming(); -+ // re-set mob counts -+ for (EntityPlayer player : this.world.players) { -+ Arrays.fill(player.mobCounts, 0); -+ } -+ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, true); -+ } else { -+ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, false); -+ } -+ // Paper end - this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings - - this.p = spawnercreature_d; -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index a15b119b24090ffc607bfc9003d5b95f3acf3b2f..f0c3bfb0e641b9f1a22fb6873ab3645be6e481c4 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -94,6 +94,7 @@ import net.minecraft.world.effect.MobEffects; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityLiving; -+import net.minecraft.world.entity.EnumCreatureType; - import net.minecraft.world.entity.EnumMainHand; - import net.minecraft.world.entity.IEntityAngerable; - import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; -@@ -219,6 +220,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; - // Paper end -+ // Paper start - mob spawning rework -+ public static final int ENUMCREATURETYPE_TOTAL_ENUMS = EnumCreatureType.values().length; -+ public final int[] mobCounts = new int[ENUMCREATURETYPE_TOTAL_ENUMS]; // Paper -+ public final com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet cachedSingleMobDistanceMap; -+ // Paper end - - // CraftBukkit start - public String displayName; -@@ -257,6 +263,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getName()); // Paper - this.canPickUpLoot = true; - this.maxHealthCache = this.getMaxHealth(); -+ this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper - } - - // Yes, this doesn't match Vanilla, but it's the best we can do for now. -@@ -2061,6 +2068,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - } - -+ public final SectionPosition getPlayerMapSection() { return this.O(); } // Paper - OBFHELPER - public SectionPosition O() { - return this.cj; - } -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 46c91230ab6f12db77b453c312fa7382b76fad34..d00dc8d7933be61f1401f598e5d675f5ae5d7029 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -72,6 +72,7 @@ import net.minecraft.util.thread.ThreadedMailbox; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.EnumCreatureType; - import net.minecraft.world.entity.ai.village.poi.VillagePlace; - import net.minecraft.world.entity.boss.EntityComplexPart; - import net.minecraft.world.entity.player.EntityHuman; -@@ -129,7 +130,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final Int2ObjectMap trackedEntities; - private final Long2ByteMap z; - private final Queue A; private final Queue getUnloadQueueTasks() { return this.A; } // Paper - OBFHELPER -- private int viewDistance; -+ int viewDistance; // Paper - private -> package private -+ public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper - - // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() - public final CallbackExecutor callbackExecutor = new CallbackExecutor(); -@@ -208,6 +210,24 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.l = supplier; - this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper - this.setViewDistance(i); -+ this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper -+ } -+ -+ public void updatePlayerMobTypeMap(Entity entity) { -+ if (!this.world.paperConfig.perPlayerMobSpawns) { -+ return; -+ } -+ int chunkX = (int)Math.floor(entity.locX()) >> 4; -+ int chunkZ = (int)Math.floor(entity.locZ()) >> 4; -+ int index = entity.getEntityType().getEnumCreatureType().ordinal(); -+ -+ for (EntityPlayer player : this.playerMobDistanceMap.getPlayersInRange(chunkX, chunkZ)) { -+ ++player.mobCounts[index]; -+ } -+ } -+ -+ public int getMobCountNear(EntityPlayer entityPlayer, EnumCreatureType enumCreatureType) { -+ return entityPlayer.mobCounts[enumCreatureType.ordinal()]; - } - - private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) { -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 1355c074353611669c947cb0f06c67be0ab418aa..9d2955f05aadd4bbc6dcfec068a55d7fe6950ba0 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -426,6 +426,7 @@ public class EntityTypes { - return this.bl; - } - -+ public final EnumCreatureType getEnumCreatureType() { return this.e(); } // Paper - OBFHELPER - public EnumCreatureType e() { - return this.bg; - } -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index d30a3de84dc75a57680052904337af02b6b80636..24771c3522ea74ac12058591137eafc21adf3762 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -16,6 +16,7 @@ import net.minecraft.core.IPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; -@@ -62,6 +63,11 @@ public final class SpawnerCreature { - }); - - public static SpawnerCreature.d a(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b) { -+ // Paper start - add countMobs parameter -+ return countMobs(i, iterable, spawnercreature_b, false); -+ } -+ public static SpawnerCreature.d countMobs(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b, boolean countMobs) { -+ // Paper end - add countMobs parameter - SpawnerCreatureProbabilities spawnercreatureprobabilities = new SpawnerCreatureProbabilities(); - Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); - Iterator iterator = iterable.iterator(); -@@ -99,6 +105,11 @@ public final class SpawnerCreature { - } - - object2intopenhashmap.addTo(enumcreaturetype, 1); -+ // Paper start -+ if (countMobs) { -+ ((WorldServer)chunk.world).getChunkProvider().playerChunkMap.updatePlayerMobTypeMap(entity); -+ } -+ // Paper end - }); - } - } -@@ -157,13 +168,31 @@ public final class SpawnerCreature { - continue; - } - -- if ((flag || !enumcreaturetype.d()) && (flag1 || enumcreaturetype.d()) && (flag2 || !enumcreaturetype.e()) && spawnercreature_d.a(enumcreaturetype, limit)) { -+ // Paper start - only allow spawns upto the limit per chunk and update count afterwards -+ int currEntityCount = spawnercreature_d.getEntityCountsByType().getInt(enumcreaturetype); -+ int k1 = limit * spawnercreature_d.getSpawnerChunks() / SpawnerCreature.b; -+ int difference = k1 - currEntityCount; -+ -+ if (worldserver.paperConfig.perPlayerMobSpawns) { -+ int minDiff = Integer.MAX_VALUE; -+ for (EntityPlayer entityplayer : worldserver.getChunkProvider().playerChunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) { -+ minDiff = Math.min(limit - worldserver.getChunkProvider().playerChunkMap.getMobCountNear(entityplayer, enumcreaturetype), minDiff); -+ } -+ difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff; -+ } -+ // Paper end -+ -+ // Paper start - per player mob spawning -+ if ((flag || !enumcreaturetype.d()) && (flag1 || enumcreaturetype.d()) && (flag2 || !enumcreaturetype.e()) && difference > 0) { - // CraftBukkit end -- a(enumcreaturetype, worldserver, chunk, (entitytypes, blockposition, ichunkaccess) -> { -+ int spawnCount = spawnMobs(enumcreaturetype, worldserver, chunk, (entitytypes, blockposition, ichunkaccess) -> { - return spawnercreature_d.a(entitytypes, blockposition, ichunkaccess); - }, (entityinsentient, ichunkaccess) -> { - spawnercreature_d.a(entityinsentient, ichunkaccess); -- }); -+ }, -+ difference, worldserver.paperConfig.perPlayerMobSpawns ? worldserver.getChunkProvider().playerChunkMap::updatePlayerMobTypeMap : null); -+ spawnercreature_d.getEntityCountsByType().mergeInt(enumcreaturetype, spawnCount, Integer::sum); -+ // Paper end - per player mob spawning - } - } - -@@ -172,22 +201,34 @@ public final class SpawnerCreature { - } - - public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a) { -+ // Paper start - add parameters and int ret type -+ spawnMobs(enumcreaturetype, worldserver, chunk, spawnercreature_c, spawnercreature_a, Integer.MAX_VALUE, null); -+ } -+ public static int spawnMobs(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer trackEntity) { -+ // Paper end - add parameters and int ret type - BlockPosition blockposition = getRandomPosition(worldserver, chunk); - - if (blockposition.getY() >= 1) { -- a(enumcreaturetype, worldserver, (IChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a); -+ return spawnMobsInternal(enumcreaturetype, worldserver, (IChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a, maxSpawns, trackEntity); - } -+ return 0; // Paper - } - - public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition blockposition, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a) { -+ // Paper start - add maxSpawns parameter and return spawned mobs -+ spawnMobsInternal(enumcreaturetype, worldserver, ichunkaccess, blockposition, spawnercreature_c, spawnercreature_a, Integer.MAX_VALUE, null); -+ } -+ public static int spawnMobsInternal(EnumCreatureType enumcreaturetype, WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition blockposition, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer trackEntity) { -+ // Paper end - add maxSpawns parameter and return spawned mobs - StructureManager structuremanager = worldserver.getStructureManager(); - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); - int i = blockposition.getY(); - IBlockData iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn -+ int j = 0; // Paper - moved up - - if (iblockdata != null && !iblockdata.isOccluding(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); -- int j = 0; -+ // Paper - moved up - int k = 0; - - while (k < 3) { -@@ -227,7 +268,7 @@ public final class SpawnerCreature { - // Paper start - Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); - if (doSpawning == null) { -- return; -+ return j; // Paper - } - if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { - // Paper end -@@ -235,7 +276,7 @@ public final class SpawnerCreature { - - - if (entityinsentient == null) { -- return; -+ return j; // Paper - } - - entityinsentient.setPositionRotation(d0, (double) i, d1, worldserver.random.nextFloat() * 360.0F, 0.0F); -@@ -244,13 +285,18 @@ public final class SpawnerCreature { - // CraftBukkit start - worldserver.addAllEntities(entityinsentient, SpawnReason.NATURAL); - if (!entityinsentient.dead) { -- ++j; -+ ++j; // Paper - force diff on name change - we expect this to be the total amount spawned - ++k1; - spawnercreature_a.run(entityinsentient, ichunkaccess); -+ // Paper start -+ if (trackEntity != null) { -+ trackEntity.accept(entityinsentient); -+ } -+ // Paper end - } - // CraftBukkit end -- if (j >= entityinsentient.getMaxSpawnGroup()) { -- return; -+ if (j >= entityinsentient.getMaxSpawnGroup() || j >= maxSpawns) { // Paper -+ return j; // Paper - } - - if (entityinsentient.c(k1)) { -@@ -272,6 +318,7 @@ public final class SpawnerCreature { - } - - } -+ return j; // Paper - } - - private static boolean a(WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { -@@ -512,8 +559,8 @@ public final class SpawnerCreature { - - public static class d { - -- private final int a; -- private final Object2IntOpenHashMap b; -+ private final int a; final int getSpawnerChunks() { return this.a; } // Paper - OBFHELPER -+ private final Object2IntOpenHashMap b; final Object2IntMap getEntityCountsByType() { return this.b; } // Paper - OBFHELPER - private final SpawnerCreatureProbabilities c; - private final Object2IntMap d; - @Nullable -@@ -574,7 +621,7 @@ public final class SpawnerCreature { - - // CraftBukkit start - private boolean a(EnumCreatureType enumcreaturetype, int limit) { -- int i = limit * this.a / SpawnerCreature.b; -+ int i = limit * this.a / SpawnerCreature.b; // Paper - diff on change, needed in the spawn method - // CraftBukkit end - - return this.b.getInt(enumcreaturetype) < i; diff --git a/Unmapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch b/Unmapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch deleted file mode 100644 index 053e08edc4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Mon, 19 Aug 2019 19:42:35 +0500 -Subject: [PATCH] Prevent consuming the wrong itemstack - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 4e2039e46741e8a09f3af7d3d9e98ef7a5b27abc..48f932b2e049741ebee5824e158e4bda87d42faf 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3201,10 +3201,13 @@ public abstract class EntityLiving extends Entity { - this.datawatcher.set(EntityLiving.ag, (byte) j); - } - -- public void c(EnumHand enumhand) { -+ // Paper start -- OBFHELPER and forwarder to method with forceUpdate parameter -+ public void c(EnumHand enumhand) { this.updateActiveItem(enumhand, false); } -+ public void updateActiveItem(EnumHand enumhand, boolean forceUpdate) { -+ // Paper end - ItemStack itemstack = this.b(enumhand); - -- if (!itemstack.isEmpty() && !this.isHandRaised()) { -+ if (!itemstack.isEmpty() && !this.isHandRaised() || forceUpdate) { // Paper use override flag - this.activeItem = itemstack; - this.bd = itemstack.k(); - if (!this.world.isClientSide) { -@@ -3282,6 +3285,7 @@ public abstract class EntityLiving extends Entity { - this.releaseActiveItem(); - } else { - if (!this.activeItem.isEmpty() && this.isHandRaised()) { -+ this.updateActiveItem(this.getRaisedHand(), true); // Paper - this.b(this.activeItem, 16); - // CraftBukkit start - fire PlayerItemConsumeEvent - ItemStack itemstack; -@@ -3316,8 +3320,8 @@ public abstract class EntityLiving extends Entity { - } - - this.clearActiveItem(); -- // Paper start - if the replacement is anything but the default, update the client inventory -- if (this instanceof EntityPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { -+ // Paper start -+ if (this instanceof EntityPlayer) { - ((EntityPlayer) this).getBukkitEntity().updateInventory(); - } - // Paper end diff --git a/Unmapped-Spigot-Server-Patches/0376-Generator-Settings.patch b/Unmapped-Spigot-Server-Patches/0376-Generator-Settings.patch deleted file mode 100644 index 35a2520f5f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0376-Generator-Settings.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 02:17:54 -0600 -Subject: [PATCH] Generator Settings - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6aec502eb529d4090306e12e837117cde7e114eb..290e49cf0077909ad7ab8127c01ef93cf7b70b51 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -570,4 +570,9 @@ public class PaperWorldConfig { - private void perPlayerMobSpawns() { - perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); - } -+ -+ public boolean generateFlatBedrock; -+ private void generatorSettings() { -+ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -index e570dc58efa56bd0aa5ada5575b4054ee38d505e..cdf612d7553a8f4aaebb5e0e66bd2a47a280457a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -+++ b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -@@ -25,6 +25,18 @@ import org.apache.logging.log4j.LogManager; - - public interface IChunkAccess extends IBlockAccess, IStructureAccess { - -+ // Paper start -+ default boolean generateFlatBedrock() { -+ if (this instanceof ProtoChunk) { -+ return ((ProtoChunk)this).world.paperConfig.generateFlatBedrock; -+ } else if (this instanceof Chunk) { -+ return ((Chunk)this).world.paperConfig.generateFlatBedrock; -+ } else { -+ return false; -+ } -+ } -+ // Paper end -+ - IBlockData getType(final int x, final int y, final int z); // Paper - @Nullable - IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 9b308a10554b037ede0c455fbd3e906021218ddc..7bfac4e852c4a6697435647dab173913df6034e9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -64,7 +64,7 @@ public class ProtoChunk implements IChunkAccess { - private long s; - private final Map t; - private volatile boolean u; -- private final World world; // Paper - Anti-Xray - Add world -+ final World world; // Paper - Anti-Xray - Add world // Paper - private -> default - - // Paper start - Anti-Xray - Add world - @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { this(chunkcoordintpair, chunkconverter, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -diff --git a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -index b137d65953fe1e44709e9a6dab3a4533df644d06..700b32322e8d0fbb8ec2824e50a340be16b48f81 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -@@ -408,8 +408,8 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - int i = ichunkaccess.getPos().d(); - int j = ichunkaccess.getPos().e(); - GeneratorSettingBase generatorsettingbase = (GeneratorSettingBase) this.h.get(); -- int k = generatorsettingbase.f(); -- int l = this.x - 1 - generatorsettingbase.e(); -+ int k = generatorsettingbase.f(); final int floorHeight = k; // Paper -+ int l = this.x - 1 - generatorsettingbase.e(); final int roofHeight = l; // Paper - boolean flag = true; - boolean flag1 = l + 4 >= 0 && l < this.x; - boolean flag2 = k + 4 >= 0 && k < this.x; -@@ -423,7 +423,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - - if (flag1) { - for (i1 = 0; i1 < 5; ++i1) { -- if (i1 <= random.nextInt(5)) { -+ if (i1 <= (ichunkaccess.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof - ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), l - i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false); - } - } -@@ -431,7 +431,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - - if (flag2) { - for (i1 = 4; i1 >= 0; --i1) { -- if (i1 <= random.nextInt(5)) { -+ if (i1 <= (ichunkaccess.generateFlatBedrock() ? floorHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor - ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), k + i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false); - } - } diff --git a/Unmapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch b/Unmapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch deleted file mode 100644 index 8ef2ece0bd..0000000000 --- a/Unmapped-Spigot-Server-Patches/0377-Fix-MC-161754.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 24 Sep 2019 16:03:00 -0700 -Subject: [PATCH] Fix MC-161754 - -Fixes https://github.com/PaperMC/Paper/issues/2580 - -We can use an entity valid check since this method is invoked for -each inventory iteraction (thanks to CB) and on player tick (vanilla). - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerHorse.java b/src/main/java/net/minecraft/world/inventory/ContainerHorse.java -index ecabe8e52865b71b6f89d09850b37741e7e79b50..ea64ef313a8378fa7dee086e137e1e5f43376804 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerHorse.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerHorse.java -@@ -85,7 +85,7 @@ public class ContainerHorse extends Container { - - @Override - public boolean canUse(EntityHuman entityhuman) { -- return this.c.a(entityhuman) && this.d.isAlive() && this.d.g((Entity) entityhuman) < 8.0F; -+ return this.c.a(entityhuman) && (this.d.isAlive() && this.d.valid) && this.d.g((Entity) entityhuman) < 8.0F; // Paper - Fix MC-161754 - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch b/Unmapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch deleted file mode 100644 index 0b09feb060..0000000000 --- a/Unmapped-Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: wea_ondara -Date: Thu, 10 Oct 2019 11:29:42 +0200 -Subject: [PATCH] Performance improvement for Chunk.getEntities - -This patch aims to reduce performance cost used by collecting the -entities of a chunk. Previously the entitySlices were copied into an -extra array with List.toArray() with is a costly and unneccessary -operation. This patch will reduce the load of plugins which for example -implement custom moblimits and depend on Chunk.getEntities(). - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index c36f55f178166eb099cc5c64784be5a9f4750199..8ade81a693286cdf65f8c0eeca2121a217c90350 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -117,14 +117,14 @@ public class CraftChunk implements Chunk { - Entity[] entities = new Entity[count]; - - for (int i = 0; i < 16; i++) { -- -- for (Object obj : chunk.entitySlices[i].toArray()) { -- if (!(obj instanceof net.minecraft.world.entity.Entity)) { -+ // Paper start - speed up (was with chunk.entitySlices[i].toArray() and cast checks which costs a lot of performance if called often) -+ for (net.minecraft.world.entity.Entity entity : chunk.entitySlices[i]) { -+ if (entity == null) { - continue; - } -- -- entities[index++] = ((net.minecraft.world.entity.Entity) obj).getBukkitEntity(); -+ entities[index++] = entity.getBukkitEntity(); - } -+ // Paper end - } - - return entities; diff --git a/Unmapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/Unmapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch deleted file mode 100644 index 225102e634..0000000000 --- a/Unmapped-Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterErwin -Date: Wed, 30 Oct 2019 16:57:54 +0100 -Subject: [PATCH] Fix spawning of hanging entities that are not ItemFrames and - can not face UP or DOWN - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 6aaf868cf3213e1935080c64c652c3055cb58e0c..fcad64fcfc22af227be19741b634b773aca7a98d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1886,7 +1886,12 @@ public class CraftWorld implements World { - height = 9; - } - -- BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; -+ // Paper start - In addition to d65a2576e40e58c8e446b330febe6799d13a604f do not check UP/DOWN for non item frames -+ // BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; -+ BlockFace[] faces = (ItemFrame.class.isAssignableFrom(clazz)) -+ ? new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN} -+ : new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH}; -+ // Paper end - final BlockPosition pos = new BlockPosition(x, y, z); - for (BlockFace dir : faces) { - IBlockData nmsBlock = world.getType(pos.shift(CraftBlock.blockFaceToNotch(dir))); diff --git a/Unmapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch b/Unmapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch deleted file mode 100644 index 336ed3d11d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 20 Apr 2019 19:47:34 -0500 -Subject: [PATCH] Expose the internal current tick - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 40ed419457982e1dae1605915aeccd10703df57b..b76da976d8710d9e91b8b00fa3b888adfc791dc3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2364,5 +2364,10 @@ public final class CraftServer implements Server { - } - return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); - } -+ -+ @Override -+ public int getCurrentTick() { -+ return net.minecraft.server.MinecraftServer.currentTick; -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/Unmapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch deleted file mode 100644 index 5535fda04e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 9 Oct 2019 21:51:43 -0500 -Subject: [PATCH] Fix stuck in sneak when changing worlds (MC-10657) - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index f0c3bfb0e641b9f1a22fb6873ab3645be6e481c4..a0c426afaa7a18f7596d56699f02dcd665f7aa9d 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1073,6 +1073,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.lastHealthSent = -1.0F; - this.lastFoodSent = -1; - -+ setSneaking(false); // Paper - fix MC-10657 -+ - // CraftBukkit start - PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); - this.world.getServer().getPluginManager().callEvent(changeEvent); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 553b14f7167673938d1bc83d79c730692a4ef105..9af1d81475d2def60a682ed23e88f1afbbc4c7e6 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -846,6 +846,8 @@ public abstract class PlayerList { - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityEffect(entityplayer.getId(), mobEffect)); - } - -+ entityplayer.setSneaking(false); // Paper - fix MC-10657 -+ - // Fire advancement trigger - entityplayer.triggerDimensionAdvancements(((CraftWorld) fromWorld).getHandle()); - diff --git a/Unmapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch b/Unmapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch deleted file mode 100644 index 7adaa55dec..0000000000 --- a/Unmapped-Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 9 Oct 2019 21:46:15 -0500 -Subject: [PATCH] Add option to disable pillager patrols - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 290e49cf0077909ad7ab8127c01ef93cf7b70b51..e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -575,4 +575,9 @@ public class PaperWorldConfig { - private void generatorSettings() { - generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); - } -+ -+ public boolean disablePillagerPatrols = false; -+ private void pillagerSettings() { -+ disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -index 04a1af9c6742f7aa944dec80e75ff8a4ca4bf57f..cba98adb7f2711fb97c7e4120d962f46a59682e7 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -@@ -26,6 +26,7 @@ public class MobSpawnerPatrol implements MobSpawner { - - @Override - public int a(WorldServer worldserver, boolean flag, boolean flag1) { -+ if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper - if (!flag) { - return 0; - } else if (!worldserver.getGameRules().getBoolean(GameRules.DO_PATROL_SPAWNING)) { diff --git a/Unmapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/Unmapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch deleted file mode 100644 index 904f78b816..0000000000 --- a/Unmapped-Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lukasz Derlatka -Date: Mon, 11 Nov 2019 16:08:13 +0100 -Subject: [PATCH] Fix AssertionError when player hand set to empty type - -Fixes an AssertionError when setting the player's item in hand to null or a new ItemStack of Air in PlayerInteractEvent -Fixes GH-2718 - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 24dfdb3807dbf6e9acc59d35d7c76f7ac0185219..72df753d8c8e12cb3efaa02f37b05496701cc9f9 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1708,6 +1708,10 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 - return; - } -+ // Paper start -+ itemstack = this.player.getItemInHand(enumhand); -+ if (itemstack.isEmpty()) return; -+ // Paper end - EnumInteractionResult enuminteractionresult = this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand); - - if (enuminteractionresult.b()) { -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 48f932b2e049741ebee5824e158e4bda87d42faf..cd880fb9e61dad7dff185d0b4fa2b8c5dee04861 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -2156,6 +2156,7 @@ public abstract class EntityLiving extends Entity { - return predicate.test(this.getItemInMainHand().getItem()) || predicate.test(this.getItemInOffHand().getItem()); - } - -+ public final ItemStack getItemInHand(EnumHand enumhand) { return this.b(enumhand); } // Paper - OBFHELPER - public ItemStack b(EnumHand enumhand) { - if (enumhand == EnumHand.MAIN_HAND) { - return this.getEquipment(EnumItemSlot.MAINHAND); diff --git a/Unmapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch b/Unmapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch deleted file mode 100644 index ceeb9bcd0e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch +++ /dev/null @@ -1,329 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 03:11:03 -0500 -Subject: [PATCH] PlayerLaunchProjectileEvent - - -diff --git a/src/main/java/net/minecraft/world/InteractionResultWrapper.java b/src/main/java/net/minecraft/world/InteractionResultWrapper.java -index dd17c111670e637b574f5c7f38d27848900ce194..8cecc3d909a51b1892b4a299a5e6ec3518db9b39 100644 ---- a/src/main/java/net/minecraft/world/InteractionResultWrapper.java -+++ b/src/main/java/net/minecraft/world/InteractionResultWrapper.java -@@ -10,6 +10,7 @@ public class InteractionResultWrapper { - this.b = t0; - } - -+ public EnumInteractionResult getResult() { return this.a(); } // Paper - OBFHELPER - public EnumInteractionResult a() { - return this.a; - } -diff --git a/src/main/java/net/minecraft/world/item/ItemEgg.java b/src/main/java/net/minecraft/world/item/ItemEgg.java -index 2083ab6e0dc7e48d409a5ee33e712e34abd6f6bf..4b1a6ee784da4595931396a905f1358b7a13f3dd 100644 ---- a/src/main/java/net/minecraft/world/item/ItemEgg.java -+++ b/src/main/java/net/minecraft/world/item/ItemEgg.java -@@ -25,21 +25,35 @@ public class ItemEgg extends Item { - - entityegg.setItem(itemstack); - entityegg.a(entityhuman, entityhuman.pitch, entityhuman.yaw, 0.0F, 1.5F, 1.0F); -- // CraftBukkit start -- if (!world.addEntity(entityegg)) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityegg.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entityegg)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { -+ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ } else { - if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { - ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); - } -- return InteractionResultWrapper.fail(itemstack); -+ return new InteractionResultWrapper(net.minecraft.world.EnumInteractionResult.FAIL, itemstack); - } -- // CraftBukkit end -+ // Paper end -+ -+ - } - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemEgg.RANDOM.nextFloat() * 0.4F + 0.8F)); // CraftBukkit - from above - -+ /* // Paper start - moved up - entityhuman.b(StatisticList.ITEM_USED.b(this)); - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultWrapper.a(itemstack, world.s_()); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemEnderPearl.java b/src/main/java/net/minecraft/world/item/ItemEnderPearl.java -index 5349282b9a5b43c4c3539e1677971463e2ca5a17..9896d77381e7fadf1ef2619210713e190c1445d0 100644 ---- a/src/main/java/net/minecraft/world/item/ItemEnderPearl.java -+++ b/src/main/java/net/minecraft/world/item/ItemEnderPearl.java -@@ -25,22 +25,37 @@ public class ItemEnderPearl extends Item { - - entityenderpearl.setItem(itemstack); - entityenderpearl.a(entityhuman, entityhuman.pitch, entityhuman.yaw, 0.0F, 1.5F, 1.0F); -- if (!world.addEntity(entityenderpearl)) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityenderpearl.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entityenderpearl)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { -+ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ entityhuman.getCooldownTracker().setCooldown(this, 20); -+ } else { -+ // Paper end - if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { - ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); - } -- return InteractionResultWrapper.fail(itemstack); -+ return new InteractionResultWrapper(net.minecraft.world.EnumInteractionResult.FAIL, itemstack); - } - } - -- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F)); -- entityhuman.getCooldownTracker().setCooldown(this, 20); -- // CraftBukkit end -- -- entityhuman.b(StatisticList.ITEM_USED.b(this)); -- if (!entityhuman.abilities.canInstantlyBuild) { -- itemstack.subtract(1); -- } -+ // Paper start - moved up -+// world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F)); -+// entityhuman.getCooldownTracker().setCooldown(this, 20); -+// // CraftBukkit end -+// -+// entityhuman.b(StatisticList.ITEM_USED.b(this)); -+// if (!entityhuman.abilities.canInstantlyBuild) { -+// itemstack.subtract(1); -+// } -+ // Paper end - moved up - - return InteractionResultWrapper.a(itemstack, world.s_()); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemExpBottle.java b/src/main/java/net/minecraft/world/item/ItemExpBottle.java -index 3f41fe5bf1a0cc283d6a72824779026fdad75708..cf36ec4769dc316e3ed16262043cb78cbba340ab 100644 ---- a/src/main/java/net/minecraft/world/item/ItemExpBottle.java -+++ b/src/main/java/net/minecraft/world/item/ItemExpBottle.java -@@ -1,10 +1,13 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.stats.StatisticList; - import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; -+import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.projectile.EntityThrownExpBottle; - import net.minecraft.world.level.World; -@@ -24,19 +27,38 @@ public class ItemExpBottle extends Item { - public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { - ItemStack itemstack = entityhuman.b(enumhand); - -- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); -+ //world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); // Paper - moved down - if (!world.isClientSide) { - EntityThrownExpBottle entitythrownexpbottle = new EntityThrownExpBottle(world, entityhuman); - - entitythrownexpbottle.setItem(itemstack); - entitythrownexpbottle.a(entityhuman, entityhuman.pitch, entityhuman.yaw, -20.0F, 0.7F, 1.0F); -- world.addEntity(entitythrownexpbottle); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitythrownexpbottle.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entitythrownexpbottle)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ } else { -+ if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ return new InteractionResultWrapper(EnumInteractionResult.FAIL, itemstack); -+ } -+ // Paper end - } - -+ /* // Paper start - moved up - entityhuman.b(StatisticList.ITEM_USED.b(this)); - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultWrapper.a(itemstack, world.s_()); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemFireworks.java b/src/main/java/net/minecraft/world/item/ItemFireworks.java -index 79e9be800385b94c4493bd8970620d76bfbd65ae..e7f958d137257da912ce9b83db017b4423959943 100644 ---- a/src/main/java/net/minecraft/world/item/ItemFireworks.java -+++ b/src/main/java/net/minecraft/world/item/ItemFireworks.java -@@ -3,6 +3,7 @@ package net.minecraft.world.item; - import java.util.Arrays; - import java.util.Comparator; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; -@@ -29,8 +30,12 @@ public class ItemFireworks extends Item { - EntityFireworks entityfireworks = new EntityFireworks(world, itemactioncontext.getEntity(), vec3d.x + (double) enumdirection.getAdjacentX() * 0.15D, vec3d.y + (double) enumdirection.getAdjacentY() * 0.15D, vec3d.z + (double) enumdirection.getAdjacentZ() * 0.15D, itemstack); - entityfireworks.spawningEntity = itemactioncontext.getEntity().getUniqueID(); // Paper - -- world.addEntity(entityfireworks); -- itemstack.subtract(1); -+ // Paper start - PlayerLaunchProjectileEvent -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) itemactioncontext.getEntity().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); -+ if (!event.callEvent() || !world.addEntity(entityfireworks)) return EnumInteractionResult.PASS; -+ if (event.shouldConsume() && !itemactioncontext.getEntity().abilities.canInstantlyBuild) itemstack.subtract(1); -+ else if (itemactioncontext.getEntity() instanceof EntityPlayer) ((EntityPlayer) itemactioncontext.getEntity()).getBukkitEntity().updateInventory(); -+ // Paper end - } - - return EnumInteractionResult.a(world.isClientSide); -diff --git a/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java b/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java -index a75f374f0639e8143772aa863666afe25d2020cf..0e073a8c23d24afb8b0198a9cfd8dc7d0b9d0a6b 100644 ---- a/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java -+++ b/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java -@@ -3,6 +3,7 @@ package net.minecraft.world.item; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.World; -@@ -15,7 +16,12 @@ public class ItemLingeringPotion extends ItemPotionThrowable { - - @Override - public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { -- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_LINGERING_POTION_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemLingeringPotion.RANDOM.nextFloat() * 0.4F + 0.8F)); -- return super.a(world, entityhuman, enumhand); -+ // Paper start -+ InteractionResultWrapper wrapper = super.a(world, entityhuman, enumhand); -+ if (wrapper.getResult() != EnumInteractionResult.FAIL) { -+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_LINGERING_POTION_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemLingeringPotion.RANDOM.nextFloat() * 0.4F + 0.8F)); -+ } -+ return wrapper; -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java b/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java -index d050243946ad7023d5dd3958d7056cddcaf185a4..27c61fc4e61b0d76565ca6893514b3c73247c954 100644 ---- a/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java -+++ b/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java -@@ -1,7 +1,9 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.stats.StatisticList; - import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.projectile.EntityPotion; -@@ -22,13 +24,31 @@ public class ItemPotionThrowable extends ItemPotion { - - entitypotion.setItem(itemstack); - entitypotion.a(entityhuman, entityhuman.pitch, entityhuman.yaw, -20.0F, 0.5F, 1.0F); -- world.addEntity(entitypotion); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitypotion.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entitypotion)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ } else { -+ if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ return new InteractionResultWrapper(EnumInteractionResult.FAIL, itemstack); -+ } -+ // Paper end - } - -+ /* // Paper start - moved up - entityhuman.b(StatisticList.ITEM_USED.b(this)); - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultWrapper.a(itemstack, world.s_()); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemSnowball.java b/src/main/java/net/minecraft/world/item/ItemSnowball.java -index e5200b2a7d6d5c2d549e585ed157ec5217edae8e..8a1d59cb1ea5a8959c52272aa762ec35307246d7 100644 ---- a/src/main/java/net/minecraft/world/item/ItemSnowball.java -+++ b/src/main/java/net/minecraft/world/item/ItemSnowball.java -@@ -26,14 +26,20 @@ public class ItemSnowball extends Item { - - entitysnowball.setItem(itemstack); - entitysnowball.a(entityhuman, entityhuman.pitch, entityhuman.yaw, 0.0F, 1.5F, 1.0F); -- if (world.addEntity(entitysnowball)) { -- if (!entityhuman.abilities.canInstantlyBuild) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entitysnowball)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ // Paper end - itemstack.subtract(1); -+ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { // Paper -+ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // Paper - } - - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemSnowball.RANDOM.nextFloat() * 0.4F + 0.8F)); -- } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { -- ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } else { // Paper -+ if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // Paper -+ return new InteractionResultWrapper(net.minecraft.world.EnumInteractionResult.FAIL, itemstack); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/item/ItemSplashPotion.java b/src/main/java/net/minecraft/world/item/ItemSplashPotion.java -index 98f29fac4bf087ad15f1cc7e85b408e22ec07efd..971491a461ccb7a707c6ca1a5b7c16d8823a7a80 100644 ---- a/src/main/java/net/minecraft/world/item/ItemSplashPotion.java -+++ b/src/main/java/net/minecraft/world/item/ItemSplashPotion.java -@@ -3,6 +3,7 @@ package net.minecraft.world.item; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.World; -@@ -15,7 +16,12 @@ public class ItemSplashPotion extends ItemPotionThrowable { - - @Override - public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { -+ // Paper start -+ InteractionResultWrapper wrapper = super.a(world, entityhuman, enumhand); -+ if (wrapper.getResult() != EnumInteractionResult.FAIL) { - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SPLASH_POTION_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemSplashPotion.RANDOM.nextFloat() * 0.4F + 0.8F)); -- return super.a(world, entityhuman, enumhand); -+ } -+ return wrapper; -+ // Paper end - } - } diff --git a/Unmapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch b/Unmapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch deleted file mode 100644 index abf6eb1d92..0000000000 --- a/Unmapped-Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BlackHole -Date: Sun, 15 Dec 2019 19:12:39 +0100 -Subject: [PATCH] Add CraftMagicNumbers.isSupportedApiVersion() - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 8aa9e7796ea39c09a965750d06c3d358250f33b8..7e4cceff7ce9ffaff00caf21088fd7bc59e66933 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -375,6 +375,11 @@ public final class CraftMagicNumbers implements UnsafeValues { - public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { - return new com.destroystokyo.paper.PaperVersionFetcher(); - } -+ -+ @Override -+ public boolean isSupportedApiVersion(String apiVersion) { -+ return apiVersion != null && SUPPORTED_API.contains(apiVersion); -+ } - // Paper end - - /** diff --git a/Unmapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/Unmapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch deleted file mode 100644 index 0188a5ae7f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Callahan -Date: Mon, 13 Jan 2020 23:47:28 -0600 -Subject: [PATCH] Prevent sync chunk loads when villagers try to find beds - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java -index 84eba4c91e8e608b84623d6c71233e2512b77a54..ce86301723d20e79f95207cce1084bac091742fe 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java -@@ -46,7 +46,8 @@ public class BehaviorSleep extends Behavior { - } - } - -- IBlockData iblockdata = worldserver.getType(globalpos.getBlockPosition()); -+ IBlockData iblockdata = worldserver.getTypeIfLoaded(globalpos.getBlockPosition()); // Paper -+ if (iblockdata == null) { return false; } // Paper - - return globalpos.getBlockPosition().a((IPosition) entityliving.getPositionVector(), 2.0D) && iblockdata.getBlock().a((Tag) TagsBlock.BEDS) && !(Boolean) iblockdata.get(BlockBed.OCCUPIED); - } diff --git a/Unmapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch b/Unmapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch deleted file mode 100644 index 342a7deea1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 18 Dec 2019 22:21:35 -0600 -Subject: [PATCH] MC-145656 Fix Follow Range Initial Target - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5..edda2121f8c1046478beaa77030ebb36d403b334 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -580,4 +580,9 @@ public class PaperWorldConfig { - private void pillagerSettings() { - disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); - } -+ -+ public boolean entitiesTargetWithFollowRange = false; -+ private void entitiesTargetWithFollowRange() { -+ entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java -index 4f0a2cbdd6d42e3e4721345e21bf0ef33ec48e1e..44f21c3f7af17e9d39777a48c6715a22fc085da6 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java -@@ -32,6 +32,7 @@ public class PathfinderGoalNearestAttackableTarget exten - this.b = i; - this.a(EnumSet.of(PathfinderGoal.Type.TARGET)); - this.d = (new PathfinderTargetCondition()).a(this.k()).a(predicate); -+ if (entityinsentient.world.paperConfig.entitiesTargetWithFollowRange) this.d.useFollowRange(); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java -index 0de32bcf24a94efe5af922b877d4cdc3578e0cbd..e6988f7ea428f1503e3db63876b13e57f898ee30 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java -+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java -@@ -4,6 +4,8 @@ import java.util.function.Predicate; - import javax.annotation.Nullable; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityLiving; -+import net.minecraft.world.entity.ai.attributes.AttributeModifiable; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - - public class PathfinderTargetCondition { - -@@ -82,7 +84,7 @@ public class PathfinderTargetCondition { - - if (this.b > 0.0D) { - double d0 = this.g ? entityliving1.A(entityliving) : 1.0D; -- double d1 = Math.max(this.b * d0, 2.0D); -+ double d1 = Math.max((useFollowRange ? getFollowRange(entityliving) : this.b) * d0, 2.0D); // Paper - double d2 = entityliving.h(entityliving1.locX(), entityliving1.locY(), entityliving1.locZ()); - - if (d2 > d1 * d1) { -@@ -98,4 +100,18 @@ public class PathfinderTargetCondition { - return true; - } - } -+ -+ // Paper start -+ private boolean useFollowRange = false; -+ -+ public PathfinderTargetCondition useFollowRange() { -+ this.useFollowRange = true; -+ return this; -+ } -+ -+ private double getFollowRange(EntityLiving entityliving) { -+ AttributeModifiable attributeinstance = entityliving.getAttributeInstance(GenericAttributes.FOLLOW_RANGE); -+ return attributeinstance == null ? 16.0D : attributeinstance.getValue(); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch b/Unmapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch deleted file mode 100644 index 52b5dc57f2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0388-Optimize-Hoppers.patch +++ /dev/null @@ -1,517 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Apr 2016 22:09:52 -0400 -Subject: [PATCH] Optimize Hoppers - -* Removes unnecessary extra calls to .update() that are very expensive -* Lots of itemstack cloning removed. Only clone if the item is actually moved -* Return true when a plugin cancels inventory move item event instead of false, as false causes pulls to cycle through all items. - However, pushes do not exhibit the same behavior, so this is not something plugins could of been relying on. -* Add option (Default on) to cooldown hoppers when they fail to move an item due to full inventory -* Skip subsequent InventoryMoveItemEvents if a plugin does not use the item after first event fire for an iteration -* Don't check for Entities with Inventories if the block above us is also occluding (not just Inventoried) -* Remove Streams from Item Suck In and restore restore 1.12 AABB checks which is simpler and no voxel allocations (was doing TWO Item Suck ins) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index edda2121f8c1046478beaa77030ebb36d403b334..7fbd501d70dccf869a4454e2789a5d68f2e15754 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -585,4 +585,13 @@ public class PaperWorldConfig { - private void entitiesTargetWithFollowRange() { - entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); - } -+ -+ public boolean cooldownHopperWhenFull = true; -+ public boolean disableHopperMoveEvents = false; -+ private void hopperOptimizations() { -+ cooldownHopperWhenFull = getBoolean("hopper.cooldown-when-full", cooldownHopperWhenFull); -+ log("Cooldown Hoppers when Full: " + (cooldownHopperWhenFull ? "enabled" : "disabled")); -+ disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); -+ log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index eb134ccb68dc135ab6db4c5a1d29edb321cf3f59..566b7c88ca467a92bcba2665edb852f77f8acd1e 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -129,6 +129,7 @@ import net.minecraft.world.level.WorldSettings; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.biome.WorldChunkManager; - import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.TileEntityHopper; - import net.minecraft.world.level.border.IWorldBorderListener; - import net.minecraft.world.level.border.WorldBorder; - import net.minecraft.world.level.chunk.ChunkGenerator; -@@ -1362,6 +1363,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper -+ TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - - this.methodProfiler.a(() -> { - return worldserver + " " + worldserver.getDimensionKey().a(); -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 852f9d99001b35f8c97f4445d8f605533d7f6f2f..7b1df591007b9c50bcaf4bcd30562396a9549193 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -540,11 +540,12 @@ public final class ItemStack { - return this.getItem().a(this, entityhuman, entityliving, enumhand); - } - -- public ItemStack cloneItemStack() { -- if (this.isEmpty()) { -+ public ItemStack cloneItemStack() { return cloneItemStack(false); } // Paper -+ public ItemStack cloneItemStack(boolean origItem) { // Paper -+ if (!origItem && this.isEmpty()) { // Paper - return ItemStack.b; - } else { -- ItemStack itemstack = new ItemStack(this.getItem(), this.count); -+ ItemStack itemstack = new ItemStack(origItem ? this.item : this.getItem(), this.count); // Paper - - itemstack.d(this.D()); - if (this.tag != null) { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 6781b25cc8e15be2556bb1bb8dc8c18c106b40ec..d1738b57efd3f5e6c51603553a773173e4b09bb5 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -1162,8 +1162,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return list; - } - -- @Override -- public List a(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { -+ public List getEntities(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { return a(oclass, axisalignedbb, predicate); } // Paper - OBFHELPER -+ @Override public List a(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { - this.getMethodProfiler().c("getEntities"); - int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D); - int j = MathHelper.f((axisalignedbb.maxX + 2.0D) / 16.0D); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/IHopper.java b/src/main/java/net/minecraft/world/level/block/entity/IHopper.java -index d0943ae1f372784716195666212ff83e6ee4873e..1db7b7bfe98658d0b20800a4178556f8daaf881a 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/IHopper.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/IHopper.java -@@ -1,6 +1,7 @@ - package net.minecraft.world.level.block.entity; - - import javax.annotation.Nullable; -+import net.minecraft.core.BlockPosition; - import net.minecraft.world.IInventory; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; -@@ -17,12 +18,13 @@ public interface IHopper extends IInventory { - return IHopper.c; - } - -- @Nullable -+ //@Nullable // Paper - it's annoying - World getWorld(); -+ default BlockPosition getBlockPosition() { return new BlockPosition(getX(), getY(), getZ()); } // Paper - -- double x(); -+ double x(); default double getX() { return this.x(); } // Paper - OBFHELPER - -- double z(); -+ double z(); default double getY() { return this.z(); } // Paper - OBFHELPER - -- double A(); -+ double A(); default double getZ() { return this.A(); } // Paper - OBFHELPER - } -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 48daa039ffa8ccb7b6f3ca47bdc56394addf9254..f1e586754396439dfb70a4d63e3b8b34fb36ebf4 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -77,6 +77,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public void setCurrentChunk(Chunk chunk) { - this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; - } -+ static boolean IGNORE_TILE_UPDATES = false; - // Paper end - - @Nullable -@@ -155,6 +156,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - - public void update() { - if (this.world != null) { -+ if (IGNORE_TILE_UPDATES) return; // Paper - this.c = this.world.getType(this.position); - this.world.b(this.position, this); - if (!this.c.isAir()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java -index 5fe715e8dbe9d925170acce6e0f18312d9f998f2..537dc52e5ff3325555ee6049bc7f277952983b76 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java -@@ -196,6 +196,160 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - return false; - } - -+ // Paper start - Optimize Hoppers -+ private static boolean skipPullModeEventFire = false; -+ private static boolean skipPushModeEventFire = false; -+ public static boolean skipHopperEvents = false; -+ -+ private boolean hopperPush(IInventory iinventory, EnumDirection enumdirection) { -+ skipPushModeEventFire = skipHopperEvents; -+ boolean foundItem = false; -+ for (int i = 0; i < this.getSize(); ++i) { -+ ItemStack item = this.getItem(i); -+ if (!item.isEmpty()) { -+ foundItem = true; -+ ItemStack origItemStack = item; -+ ItemStack itemstack = origItemStack; -+ -+ final int origCount = origItemStack.getCount(); -+ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); -+ origItemStack.setCount(moved); -+ -+ // We only need to fire the event once to give protection plugins a chance to cancel this event -+ // Because nothing uses getItem, every event call should end up the same result. -+ if (!skipPushModeEventFire) { -+ itemstack = callPushMoveEvent(iinventory, itemstack); -+ if (itemstack == null) { // cancelled -+ origItemStack.setCount(origCount); -+ return false; -+ } -+ } -+ final ItemStack itemstack2 = addItem(this, iinventory, itemstack, enumdirection); -+ final int remaining = itemstack2.getCount(); -+ if (remaining != moved) { -+ origItemStack = origItemStack.cloneItemStack(true); -+ origItemStack.setCount(origCount); -+ if (!origItemStack.isEmpty()) { -+ origItemStack.setCount(origCount - moved + remaining); -+ } -+ this.setItem(i, origItemStack); -+ iinventory.update(); -+ return true; -+ } -+ origItemStack.setCount(origCount); -+ } -+ } -+ if (foundItem && world.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown -+ this.setCooldown(world.spigotConfig.hopperTransfer); -+ } -+ return false; -+ } -+ -+ private static boolean hopperPull(IHopper ihopper, IInventory iinventory, ItemStack origItemStack, int i) { -+ ItemStack itemstack = origItemStack; -+ final int origCount = origItemStack.getCount(); -+ final World world = ihopper.getWorld(); -+ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); -+ itemstack.setCount(moved); -+ -+ if (!skipPullModeEventFire) { -+ itemstack = callPullMoveEvent(ihopper, iinventory, itemstack); -+ if (itemstack == null) { // cancelled -+ origItemStack.setCount(origCount); -+ // Drastically improve performance by returning true. -+ // No plugin could of relied on the behavior of false as the other call -+ // site for IMIE did not exhibit the same behavior -+ return true; -+ } -+ } -+ -+ final ItemStack itemstack2 = addItem(iinventory, ihopper, itemstack, null); -+ final int remaining = itemstack2.getCount(); -+ if (remaining != moved) { -+ origItemStack = origItemStack.cloneItemStack(true); -+ origItemStack.setCount(origCount); -+ if (!origItemStack.isEmpty()) { -+ origItemStack.setCount(origCount - moved + remaining); -+ } -+ IGNORE_TILE_UPDATES = true; -+ iinventory.setItem(i, origItemStack); -+ IGNORE_TILE_UPDATES = false; -+ iinventory.update(); -+ return true; -+ } -+ origItemStack.setCount(origCount); -+ -+ if (world.paperConfig.cooldownHopperWhenFull) { -+ cooldownHopper(ihopper); -+ } -+ -+ return false; -+ } -+ -+ private ItemStack callPushMoveEvent(IInventory iinventory, ItemStack itemstack) { -+ Inventory destinationInventory = getInventory(iinventory); -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner(false).getInventory(), -+ CraftItemStack.asCraftMirror(itemstack), destinationInventory, true); -+ boolean result = event.callEvent(); -+ if (!event.calledGetItem && !event.calledSetItem) { -+ skipPushModeEventFire = true; -+ } -+ if (!result) { -+ cooldownHopper(this); -+ return null; -+ } -+ -+ if (event.calledSetItem) { -+ return CraftItemStack.asNMSCopy(event.getItem()); -+ } else { -+ return itemstack; -+ } -+ } -+ -+ private static ItemStack callPullMoveEvent(IHopper hopper, IInventory iinventory, ItemStack itemstack) { -+ Inventory sourceInventory = getInventory(iinventory); -+ Inventory destination = getInventory(hopper); -+ -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, -+ // Mirror is safe as we no plugins ever use this item -+ CraftItemStack.asCraftMirror(itemstack), destination, false); -+ boolean result = event.callEvent(); -+ if (!event.calledGetItem && !event.calledSetItem) { -+ skipPullModeEventFire = true; -+ } -+ if (!result) { -+ cooldownHopper(hopper); -+ return null; -+ } -+ -+ if (event.calledSetItem) { -+ return CraftItemStack.asNMSCopy(event.getItem()); -+ } else { -+ return itemstack; -+ } -+ } -+ -+ private static Inventory getInventory(IInventory iinventory) { -+ Inventory sourceInventory;// Have to special case large chests as they work oddly -+ if (iinventory instanceof InventoryLargeChest) { -+ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); -+ } else if (iinventory instanceof TileEntity) { -+ sourceInventory = ((TileEntity) iinventory).getOwner(false).getInventory(); -+ } else { -+ sourceInventory = iinventory.getOwner().getInventory(); -+ } -+ return sourceInventory; -+ } -+ -+ private static void cooldownHopper(IHopper hopper) { -+ if (hopper instanceof TileEntityHopper) { -+ ((TileEntityHopper) hopper).setCooldown(hopper.getWorld().spigotConfig.hopperTransfer); -+ } else if (hopper instanceof EntityMinecartHopper) { -+ ((EntityMinecartHopper) hopper).setCooldown(hopper.getWorld().spigotConfig.hopperTransfer / 2); -+ } -+ } -+ // Paper end -+ - private boolean k() { - IInventory iinventory = this.l(); - -@@ -207,6 +361,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - if (this.b(iinventory, enumdirection)) { - return false; - } else { -+ return hopperPush(iinventory, enumdirection); /* // Paper - disable rest - for (int i = 0; i < this.getSize(); ++i) { - if (!this.getItem(i).isEmpty()) { - ItemStack itemstack = this.getItem(i).cloneItemStack(); -@@ -244,7 +399,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - } - -- return false; -+ return false;*/ // Paper - end commenting out replaced block for Hopper Optimizations - } - } - } -@@ -253,18 +408,54 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - return iinventory instanceof IWorldInventory ? IntStream.of(((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) : IntStream.range(0, iinventory.getSize()); - } - -- private boolean b(IInventory iinventory, EnumDirection enumdirection) { -- return a(iinventory, enumdirection).allMatch((i) -> { -- ItemStack itemstack = iinventory.getItem(i); -+ private static boolean allMatch(IInventory iinventory, EnumDirection enumdirection, java.util.function.BiPredicate test) { -+ if (iinventory instanceof IWorldInventory) { -+ for (int i : ((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) { -+ if (!test.test(iinventory.getItem(i), i)) { -+ return false; -+ } -+ } -+ } else { -+ int size = iinventory.getSize(); -+ for (int i = 0; i < size; i++) { -+ if (!test.test(iinventory.getItem(i), i)) { -+ return false; -+ } -+ } -+ } -+ return true; -+ } - -- return itemstack.getCount() >= itemstack.getMaxStackSize(); -- }); -+ private static boolean anyMatch(IInventory iinventory, EnumDirection enumdirection, java.util.function.BiPredicate test) { -+ if (iinventory instanceof IWorldInventory) { -+ for (int i : ((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) { -+ if (test.test(iinventory.getItem(i), i)) { -+ return true; -+ } -+ } -+ } else { -+ int size = iinventory.getSize(); -+ for (int i = 0; i < size; i++) { -+ if (test.test(iinventory.getItem(i), i)) { -+ return true; -+ } -+ } -+ } -+ return true; -+ } -+ private static final java.util.function.BiPredicate STACK_SIZE_TEST = (itemstack, i) -> itemstack.getCount() >= itemstack.getMaxStackSize(); -+ private static final java.util.function.BiPredicate IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty(); -+ -+ // Paper end -+ -+ private boolean b(IInventory iinventory, EnumDirection enumdirection) { -+ // Paper start - no streams -+ return allMatch(iinventory, enumdirection, STACK_SIZE_TEST); -+ // Paper end - } - - private static boolean c(IInventory iinventory, EnumDirection enumdirection) { -- return a(iinventory, enumdirection).allMatch((i) -> { -- return iinventory.getItem(i).isEmpty(); -- }); -+ return allMatch(iinventory, enumdirection, IS_EMPTY_TEST); - } - - public static boolean a(IHopper ihopper) { -@@ -273,9 +464,17 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - if (iinventory != null) { - EnumDirection enumdirection = EnumDirection.DOWN; - -- return c(iinventory, enumdirection) ? false : a(iinventory, enumdirection).anyMatch((i) -> { -- return a(ihopper, iinventory, i, enumdirection); -+ // Paper start - optimize hoppers and remove streams -+ skipPullModeEventFire = skipHopperEvents; -+ return !c(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { -+ // Logic copied from below to avoid extra getItem calls -+ if (!item.isEmpty() && canTakeItem(iinventory, item, i, enumdirection)) { -+ return hopperPull(ihopper, iinventory, item, i); -+ } else { -+ return false; -+ } - }); -+ // Paper end - } else { - Iterator iterator = c(ihopper).iterator(); - -@@ -293,10 +492,11 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - } - -- private static boolean a(IHopper ihopper, IInventory iinventory, int i, EnumDirection enumdirection) { -+ private static boolean a(IHopper ihopper, IInventory iinventory, int i, EnumDirection enumdirection) {// Paper - method unused as logic is inlined above - ItemStack itemstack = iinventory.getItem(i); - -- if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { -+ if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { // If this logic changes, update above. this is left inused incase reflective plugins -+ return hopperPull(ihopper, iinventory, itemstack, i); /* // Paper - disable rest - ItemStack itemstack1 = itemstack.cloneItemStack(); - // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null); - // CraftBukkit start - Call event on collection of items from inventories into the hopper -@@ -333,7 +533,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - - itemstack1.subtract(origCount - itemstack2.getCount()); // Spigot -- iinventory.setItem(i, itemstack1); -+ iinventory.setItem(i, itemstack1);*/ // Paper - end commenting out replaced block for Hopper Optimizations - } - - return false; -@@ -342,7 +542,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - public static boolean a(IInventory iinventory, EntityItem entityitem) { - boolean flag = false; - // CraftBukkit start -- InventoryPickupItemEvent event = new InventoryPickupItemEvent(iinventory.getOwner().getInventory(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); -+ InventoryPickupItemEvent event = new InventoryPickupItemEvent(getInventory(iinventory), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); // Paper - use getInventory() to avoid snapshot creation - entityitem.world.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return false; -@@ -384,6 +584,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - return !iinventory.b(i, itemstack) ? false : !(iinventory instanceof IWorldInventory) || ((IWorldInventory) iinventory).canPlaceItemThroughFace(i, itemstack, enumdirection); - } - -+ private static boolean canTakeItem(IInventory iinventory, ItemStack itemstack, int i, EnumDirection enumdirection) { return b(iinventory, itemstack, i, enumdirection); } // Paper - OBFHELPER - private static boolean b(IInventory iinventory, ItemStack itemstack, int i, EnumDirection enumdirection) { - return !(iinventory instanceof IWorldInventory) || ((IWorldInventory) iinventory).canTakeItemThroughFace(i, itemstack, enumdirection); - } -@@ -396,7 +597,9 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - boolean flag1 = iinventory1.isEmpty(); - - if (itemstack1.isEmpty()) { -+ IGNORE_TILE_UPDATES = true; // Paper - iinventory1.setItem(i, itemstack); -+ IGNORE_TILE_UPDATES = false; // Paper - itemstack = ItemStack.b; - flag = true; - } else if (a(itemstack1, itemstack)) { -@@ -447,18 +650,24 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - - public static List c(IHopper ihopper) { -- return (List) ihopper.aa_().d().stream().flatMap((axisalignedbb) -> { -- return ihopper.getWorld().a(EntityItem.class, axisalignedbb.d(ihopper.x() - 0.5D, ihopper.z() - 0.5D, ihopper.A() - 0.5D), IEntitySelector.a).stream(); -- }).collect(Collectors.toList()); -+ // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?! -+ World world = ihopper.getWorld(); -+ double d0 = ihopper.getX(); -+ double d1 = ihopper.getY(); -+ double d2 = ihopper.getZ(); -+ AxisAlignedBB bb = new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); -+ return world.getEntities(EntityItem.class, bb, Entity::isAlive); -+ // Paper end - } - - @Nullable - public static IInventory b(World world, BlockPosition blockposition) { -- return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); -+ return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, true); // Paper - } - - @Nullable -- public static IInventory a(World world, double d0, double d1, double d2) { -+ public static IInventory a(World world, double d0, double d1, double d2) { return a(world, d0, d1, d2, false); } // Paper - overload to default false -+ public static IInventory a(World world, double d0, double d1, double d2, boolean optimizeEntities) { // Paper - Object object = null; - BlockPosition blockposition = new BlockPosition(d0, d1, d2); - if ( !world.isLoaded( blockposition ) ) return null; // Spigot -@@ -478,7 +687,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - } - -- if (object == null) { -+ if (object == null && (!optimizeEntities || !org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(block).isOccluding())) { // Paper - List list = world.getEntities((Entity) null, new AxisAlignedBB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), IEntitySelector.d); - - if (!list.isEmpty()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -index 1508e267a38555820e2d31f3075adca185fbd4b6..f0da819627035bed83561128a11059424d2b7e30 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -@@ -97,12 +97,19 @@ public abstract class TileEntityLootable extends TileEntityContainer { - @Override - public boolean isEmpty() { - this.d((EntityHuman) null); -- return this.f().stream().allMatch(ItemStack::isEmpty); -+ // Paper start -+ for (ItemStack itemStack : this.f()) { -+ if (!itemStack.isEmpty()) { -+ return false; -+ } -+ } -+ // Paper end -+ return true; - } - - @Override - public ItemStack getItem(int i) { -- this.d((EntityHuman) null); -+ if (i == 0) this.d((EntityHuman) null); // Paper - return (ItemStack) this.f().get(i); - } - diff --git a/Unmapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch b/Unmapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch deleted file mode 100644 index 805bed1302..0000000000 --- a/Unmapped-Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 24 Dec 2019 00:35:42 +0000 -Subject: [PATCH] PlayerDeathEvent#shouldDropExperience - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index a0c426afaa7a18f7596d56699f02dcd665f7aa9d..f5212a7ec0f2dd27fb1c06e0dfc37f2aff595fde 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -822,7 +822,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.eW(); - } - // SPIGOT-5478 must be called manually now -- this.dropExperience(); -+ if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event - // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. - if (!event.getKeepInventory()) { - // Paper start - replace logic diff --git a/Unmapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch b/Unmapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch deleted file mode 100644 index 224000580d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 5 Jan 2020 17:24:34 -0600 -Subject: [PATCH] Prevent bees loading chunks checking hive position - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -index 1554f1d1d35084c283b573b3e58e48c6747fe7d6..1ecf73f874f404f58a99316ae027f76db6b557db 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -@@ -442,6 +442,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - if (!this.hasHivePos()) { - return false; - } else { -+ if (world.getChunkIfLoadedImmediately(hivePos.getX() >> 4, hivePos.getZ() >> 4) == null) return true; // Paper - just assume the hive is still there, no need to load the chunk(s) - TileEntity tileentity = this.world.getTileEntity(this.hivePos); - - return tileentity != null && tileentity.getTileType() == TileEntityTypes.BEEHIVE; diff --git a/Unmapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/Unmapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch deleted file mode 100644 index 34cdbbb716..0000000000 --- a/Unmapped-Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Nov 2016 20:28:12 -0400 -Subject: [PATCH] Don't load Chunks from Hoppers and other things - -Hoppers call this to I guess "get the primary side" of a double sided chest. - -If the double sided chest crosses chunk lines, it causes the chunk to load. -This will end up causing sync chunk loads, which will unload with Chunk GC, -only to be reloaded again the next tick. - -This of course is undesirable, so just return the loaded side as "primary" -and treat it as a single chest if the other sides are unloaded - -diff --git a/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java b/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java -index d51f89fed6129c4b37ef63971f8f61dc14e8032d..efa98e87eead036246348f3915b401f0f52f2242 100644 ---- a/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java -+++ b/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java -@@ -29,7 +29,12 @@ public class DoubleBlockFinder { - return new DoubleBlockFinder.Result.Single<>(s0); - } else { - BlockPosition blockposition1 = blockposition.shift((EnumDirection) function1.apply(iblockdata)); -- IBlockData iblockdata1 = generatoraccess.getType(blockposition1); -+ // Paper start -+ IBlockData iblockdata1 = generatoraccess.getTypeIfLoaded(blockposition1); -+ if (iblockdata1 == null) { -+ return new DoubleBlockFinder.Result.Single<>(s0); -+ } -+ // Paper end - - if (iblockdata1.a(iblockdata.getBlock())) { - DoubleBlockFinder.BlockType doubleblockfinder_blocktype1 = (DoubleBlockFinder.BlockType) function.apply(iblockdata1); diff --git a/Unmapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch b/Unmapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch deleted file mode 100644 index 1c55da068c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 27 Dec 2019 09:42:26 -0800 -Subject: [PATCH] Guard against serializing mismatching chunk coordinate - -Should help if something dumb happens - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index c95fcdf47db8bfe59a83c0d28f4744b4d8540ef8..e16e046d165330326ed220c9c440a637007f3137 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -67,6 +67,13 @@ public class ChunkRegionLoader { - - private static final Logger LOGGER = LogManager.getLogger(); - -+ // Paper start - guard against serializing mismatching coordinates -+ // TODO Note: This needs to be re-checked each update -+ public static ChunkCoordIntPair getChunkCoordinate(NBTTagCompound chunkData) { -+ NBTTagCompound levelData = chunkData.getCompound("Level"); -+ return new ChunkCoordIntPair(levelData.getInt("xPos"), levelData.getInt("zPos")); -+ } -+ // Paper end - // Paper start - public static final class InProgressChunkHolder { - -@@ -92,8 +99,8 @@ public class ChunkRegionLoader { - // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); - WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); -- NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); -- ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); -+ NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate -+ ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate - - if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { - ChunkRegionLoader.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -index 01ae13385dd0208c9f34da8b3897b571f86305d0..890362d28ab9cb760c73fe5014e144fb08ada6b8 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -@@ -13,6 +13,7 @@ import net.minecraft.SharedConstants; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.World; -@@ -123,6 +124,13 @@ public class IChunkLoader implements AutoCloseable { - - public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER - public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) -+ // Paper start -+ if (!chunkcoordintpair.equals(ChunkRegionLoader.getChunkCoordinate(nbttagcompound))) { -+ String world = (this instanceof PlayerChunkMap) ? ((PlayerChunkMap)this).world.getWorld().getName() : null; -+ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkcoordintpair.toString() -+ + " but compound says coordinate is " + ChunkRegionLoader.getChunkCoordinate(nbttagcompound).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); -+ } -+ // Paper end - this.regionFileCache.write(chunkcoordintpair, nbttagcompound); - if (this.c != null) { - synchronized (this.persistentDataLock) { // Paper - Async chunk loading diff --git a/Unmapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch b/Unmapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch deleted file mode 100644 index cd0b940339..0000000000 --- a/Unmapped-Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 11 Jan 2020 21:50:56 -0800 -Subject: [PATCH] Optimise IEntityAccess#getPlayerByUUID - -Use the world entity map instead of iterating over all players - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index fbb550cce96e7e5539c69bae1459326090d0c508..de4e0477c5c777ce9ac601f88d24f2dd2786eb6f 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -289,6 +289,15 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - // Paper end - -+ // Paper start - optimise getPlayerByUUID -+ @Nullable -+ @Override -+ public EntityHuman getPlayerByUUID(UUID uuid) { -+ Entity player = this.entitiesByUUID.get(uuid); -+ return (player instanceof EntityHuman) ? (EntityHuman)player : null; -+ } -+ // Paper end -+ - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor -diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java -index 8fdc4b22e8c99d653bd213fe64339c133b46b4e9..1ff9e771788a4ab52129070e355ca48df2949470 100644 ---- a/src/main/java/net/minecraft/world/level/IEntityAccess.java -+++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java -@@ -277,6 +277,12 @@ public interface IEntityAccess { - - @Nullable - default EntityHuman b(UUID uuid) { -+ // Paper start - allow WorldServer to override -+ return this.getPlayerByUUID(uuid); -+ } -+ @Nullable -+ default EntityHuman getPlayerByUUID(UUID uuid) { -+ // Paper end - for (int i = 0; i < this.getPlayers().size(); ++i) { - EntityHuman entityhuman = (EntityHuman) this.getPlayers().get(i); - diff --git a/Unmapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch b/Unmapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch deleted file mode 100644 index f9047f957b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AJMFactsheets -Date: Fri, 17 Jan 2020 17:17:54 -0600 -Subject: [PATCH] Fix items not falling correctly - -Since 1.14, Mojang has added an optimization which skips checking if -an item should fall every fourth tick. - -However, Spigot's entity activation range class also has an -optimization which skips ticking active entities every fourth tick. -This can result in a state where an item will never properly fall -due to its move method never being called. - -This patch resolves the conflict by offsetting checking an item's -move method from Spigot's entity activation range check. - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 0b2e6e72a85e05f239d56afb6785c91da5b25d55..11e029f6f97f1dd9c32e311d1a3800f2fa54b91f 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -116,7 +116,7 @@ public class EntityItem extends Entity { - } - } - -- if (!this.onGround || c(this.getMot()) > 9.999999747378752E-6D || (this.ticksLived + this.getId()) % 4 == 0) { -+ if (!this.onGround || c(this.getMot()) > 9.999999747378752E-6D || this.ticksLived % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check - this.move(EnumMoveType.SELF, this.getMot()); - float f1 = 0.98F; - diff --git a/Unmapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch b/Unmapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch deleted file mode 100644 index b23bae79ab..0000000000 --- a/Unmapped-Spigot-Server-Patches/0395-Lag-compensate-eating.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 14 Jan 2020 15:28:28 -0800 -Subject: [PATCH] Lag compensate eating - -When the server is lagging, players will wait longer when eating. -Change to also use a time check instead if it passes. - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index cd880fb9e61dad7dff185d0b4fa2b8c5dee04861..6a81aa44d2acde7575e0ed74ea8bf4070739f10e 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -214,7 +214,7 @@ public abstract class EntityLiving extends Entity { - private int jumpTicks; - private float bw; - public ItemStack activeItem; // Paper - public -- protected int bd; -+ protected int bd; protected final int getEatTimeTicks() { return this.bd; } protected final void setEatTimeTicks(int value) { this.bd = value; } // Paper - OBFHELPER - protected int be; - private BlockPosition bx; - private Optional by; -@@ -3151,6 +3151,11 @@ public abstract class EntityLiving extends Entity { - return ((Byte) this.datawatcher.get(EntityLiving.ag) & 2) > 0 ? EnumHand.OFF_HAND : EnumHand.MAIN_HAND; - } - -+ // Paper start - lag compensate eating -+ protected long eatStartTime; -+ protected int totalEatTimeTicks; -+ // Paper end -+ - private void t() { - if (this.isHandRaised()) { - if (ItemStack.d(this.b(this.getRaisedHand()), this.activeItem)) { -@@ -3160,7 +3165,12 @@ public abstract class EntityLiving extends Entity { - this.b(this.activeItem, 5); - } - -- if (--this.bd == 0 && !this.world.isClientSide && !this.activeItem.m()) { -+ // Paper start - lag compensate eating -+ // we add 1 to the expected time to avoid lag compensating when we should not -+ boolean shouldLagCompensate = this.activeItem.getItem().isFood() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); -+ if ((--this.bd == 0 || shouldLagCompensate) && !this.world.isClientSide && !this.activeItem.m()) { -+ this.setEatTimeTicks(0); -+ // Paper end - this.s(); - } - } else { -@@ -3210,7 +3220,10 @@ public abstract class EntityLiving extends Entity { - - if (!itemstack.isEmpty() && !this.isHandRaised() || forceUpdate) { // Paper use override flag - this.activeItem = itemstack; -- this.bd = itemstack.k(); -+ // Paper start - lag compensate eating -+ this.bd = this.totalEatTimeTicks = itemstack.k(); -+ this.eatStartTime = System.nanoTime(); -+ // Paper end - if (!this.world.isClientSide) { - this.c(1, true); - this.c(2, enumhand == EnumHand.OFF_HAND); -@@ -3234,7 +3247,10 @@ public abstract class EntityLiving extends Entity { - } - } else if (!this.isHandRaised() && !this.activeItem.isEmpty()) { - this.activeItem = ItemStack.b; -- this.bd = 0; -+ // Paper start - lag compensate eating -+ this.bd = this.totalEatTimeTicks = 0; -+ this.eatStartTime = -1L; -+ // Paper end - } - } - -@@ -3362,7 +3378,10 @@ public abstract class EntityLiving extends Entity { - } - - this.activeItem = ItemStack.b; -- this.bd = 0; -+ // Paper start - lag compensate eating -+ this.bd = this.totalEatTimeTicks = 0; -+ this.eatStartTime = -1L; -+ // Paper end - } - - public boolean isBlocking() { diff --git a/Unmapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch b/Unmapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch deleted file mode 100644 index aa68e86bd8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BrodyBeckwith -Date: Tue, 14 Jan 2020 17:49:03 -0500 -Subject: [PATCH] Optimize call to getFluid for explosions - - -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 618cf4e0d71b4b04085807314e79a02785f8a498..a9ecc2b4da587ca3d3c99f8c8af38092a02fb572 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -153,7 +153,7 @@ public class Explosion { - for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { - BlockPosition blockposition = new BlockPosition(d4, d5, d6); - IBlockData iblockdata = this.world.getType(blockposition); -- Fluid fluid = this.world.getFluid(blockposition); -+ Fluid fluid = iblockdata.getFluid(); // Paper - Optional optional = this.l.a(this, this.world, blockposition, iblockdata, fluid); - - if (optional.isPresent()) { diff --git a/Unmapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch b/Unmapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch deleted file mode 100644 index 9bb8424860..0000000000 --- a/Unmapped-Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 17 Jan 2020 18:44:55 -0800 -Subject: [PATCH] Fix last firework in stack not having effects when dispensed - - #2871 - -CB used the resulting item in the dispenser rather than the item -dispensed. The resulting item would have size == 0 and therefore -be convertered to air, hence why the effects disappeared. - -diff --git a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -index 50911632341d1b861c00f01077cae43884147fe0..0055a96b51a1d38d31e129c417c97bcfc9d0b745 100644 ---- a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -+++ b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -@@ -427,7 +427,7 @@ public interface IDispenseBehavior { - } - - itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); -- EntityFireworks entityfireworks = new EntityFireworks(isourceblock.getWorld(), itemstack, isourceblock.getX(), isourceblock.getY(), isourceblock.getX(), true); -+ EntityFireworks entityfireworks = new EntityFireworks(isourceblock.getWorld(), itemstack1, isourceblock.getX(), isourceblock.getY(), isourceblock.getX(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed - - IDispenseBehavior.a(isourceblock, entityfireworks, enumdirection); - entityfireworks.shoot((double) enumdirection.getAdjacentX(), (double) enumdirection.getAdjacentY(), (double) enumdirection.getAdjacentZ(), 0.5F, 1.0F); diff --git a/Unmapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch b/Unmapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch deleted file mode 100644 index e1c6127f7b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jan 2020 12:25:07 -0600 -Subject: [PATCH] Add effect to block break naturally - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 724b230259b1b44bc9fdde6c4fcbcdde5f690e05..e3ab0b76e5003553b29215a43bc5a762f2663648 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -633,6 +633,13 @@ public class CraftBlock implements Block { - - @Override - public boolean breakNaturally(ItemStack item) { -+ // Paper start -+ return breakNaturally(item, false); -+ } -+ -+ @Override -+ public boolean breakNaturally(ItemStack item, boolean triggerEffect) { -+ // Paper end - // Order matters here, need to drop before setting to air so skulls can get their data - net.minecraft.world.level.block.state.IBlockData iblockdata = this.getNMS(); - net.minecraft.world.level.block.Block block = iblockdata.getBlock(); -@@ -642,6 +649,7 @@ public class CraftBlock implements Block { - // Modelled off EntityHuman#hasBlock - if (block != Blocks.AIR && (item == null || !iblockdata.isRequiresSpecialTool() || nmsItem.canDestroySpecialBlock(iblockdata))) { - net.minecraft.world.level.block.Block.dropItems(iblockdata, world.getMinecraftWorld(), position, world.getTileEntity(position), null, nmsItem); -+ if (triggerEffect) world.triggerEffect(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.world.level.block.Block.getCombinedId(block.getBlockData())); // Paper - result = true; - } - diff --git a/Unmapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch b/Unmapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch deleted file mode 100644 index 8754eec0d1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Sat, 21 Dec 2019 15:22:09 -0500 -Subject: [PATCH] Tracking Range Improvements - -Sets tracking range of watermobs to animals instead of misc and simplifies code - -Also ignores Enderdragon, defaulting it to Mojang's setting - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index d00dc8d7933be61f1401f598e5d675f5ae5d7029..baef98331c07b0f8c95351f39c5e471f96a59c05 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1797,6 +1797,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); - int j = entity.getEntityType().getChunkRange() * 16; -+ j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper - - if (j > i) { - i = j; -diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java -index 0449451142d59e828a32fe237751c7d8484894a2..3277a8aaffb6a25624967aa0c62f61309a517739 100644 ---- a/src/main/java/org/spigotmc/TrackingRange.java -+++ b/src/main/java/org/spigotmc/TrackingRange.java -@@ -25,26 +25,26 @@ public class TrackingRange - if ( entity instanceof EntityPlayer ) - { - return config.playerTrackingRange; -- } else if ( entity.activationType == ActivationRange.ActivationType.MONSTER || entity.activationType == ActivationRange.ActivationType.RAIDER ) -- { -- return config.monsterTrackingRange; -- } else if ( entity instanceof EntityGhast ) -- { -- if ( config.monsterTrackingRange > config.monsterActivationRange ) -- { -+ // Paper start - Simplify and set water mobs to animal tracking range -+ } -+ switch (entity.activationType) { -+ case RAIDER: -+ case MONSTER: -+ case FLYING_MONSTER: - return config.monsterTrackingRange; -- } else -- { -- return config.monsterActivationRange; -- } -- } else if ( entity.activationType == ActivationRange.ActivationType.ANIMAL ) -- { -- return config.animalTrackingRange; -- } else if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) -+ case WATER: -+ case VILLAGER: -+ case ANIMAL: -+ return config.animalTrackingRange; -+ case MISC: -+ } -+ if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) -+ // Paper end - { - return config.miscTrackingRange; - } else - { -+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return ((net.minecraft.server.level.WorldServer)(entity.getWorld())).getChunkProvider().playerChunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt - return config.otherTrackingRange; - } - } diff --git a/Unmapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch b/Unmapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch deleted file mode 100644 index 1f2ba41bd2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch +++ /dev/null @@ -1,869 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 13 May 2016 01:38:06 -0400 -Subject: [PATCH] Entity Activation Range 2.0 - -Optimizes performance of Activation Range - -Adds many new configurations and a new wake up inactive system - -Fixes and adds new Immunities to improve gameplay behavior - -Adds water Mobs to activation range config and nerfs fish -Adds flying monsters to control ghast and phantoms -Adds villagers as separate config - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index de4e0477c5c777ce9ac601f88d24f2dd2786eb6f..17c6118fb1ea1f16d37eb13116e11f886274ba95 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -861,17 +861,17 @@ public class WorldServer extends World implements GeneratorAccessSeed { - ++TimingHistory.entityTicks; // Paper - timings - // Spigot start - co.aikar.timings.Timing timer; // Paper -- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { -+ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below - entity.ticksLived++; - timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings - entity.inactiveTick(); - } finally { timer.stopTiming(); } // Paper - return; -- } -+ }*/ // Paper - comment out EAR 2 - // Spigot end - // Paper start- timings -- TimingHistory.activatedEntityTicks++; -- timer = entity.getVehicle() != null ? entity.getEntityType().passengerTickTimer.startTiming() : entity.getEntityType().tickTimer.startTiming(); -+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); -+ timer = isActive ? entity.getEntityType().tickTimer.startTiming() : entity.getEntityType().inactiveTickTimer.startTiming(); // Paper - try { - // Paper end - timings - entity.g(entity.locX(), entity.locY(), entity.locZ()); -@@ -885,12 +885,16 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return IRegistry.ENTITY_TYPE.getKey(entity.getEntityType()).toString(); - }); - gameprofilerfiller.c("tickNonPassenger"); -+ if (isActive) { // Paper - EAR 2 -+ TimingHistory.activatedEntityTicks++; // Paper - entity.tick(); - entity.postTick(); // CraftBukkit -+ } else { entity.inactiveTick(); } // Paper - EAR 2 - gameprofilerfiller.exit(); - } - - this.chunkCheck(entity); -+ } finally { timer.stopTiming(); } // Paper - timings - if (entity.inChunk) { - Iterator iterator = entity.getPassengers().iterator(); - -@@ -900,7 +904,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.a(entity, entity1); - } - } -- } finally { timer.stopTiming(); } // Paper - timings -+ //} finally { timer.stopTiming(); } // Paper - timings - move up - - } - } -@@ -908,6 +912,11 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public void a(Entity entity, Entity entity1) { - if (!entity1.dead && entity1.getVehicle() == entity) { - if (entity1 instanceof EntityHuman || this.getChunkProvider().a(entity1)) { -+ // Paper - EAR 2 -+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity1); -+ co.aikar.timings.Timing timer = isActive ? entity1.getEntityType().passengerTickTimer.startTiming() : entity1.getEntityType().passengerInactiveTickTimer.startTiming(); // Paper -+ try { -+ // Paper end - entity1.g(entity1.locX(), entity1.locY(), entity1.locZ()); - entity1.lastYaw = entity1.yaw; - entity1.lastPitch = entity1.pitch; -@@ -919,8 +928,17 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return IRegistry.ENTITY_TYPE.getKey(entity1.getEntityType()).toString(); - }); - gameprofilerfiller.c("tickPassenger"); -+ // Paper start - EAR 2 -+ if (isActive) { - entity1.passengerTick(); - entity1.postTick(); // CraftBukkit -+ } else { -+ entity1.setMot(Vec3D.ORIGIN); -+ entity1.inactiveTick(); -+ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary -+ entity.syncPositionOf(entity1); -+ } -+ // Paper end - EAR 2 - gameprofilerfiller.exit(); - } - -@@ -933,7 +951,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - this.a(entity1, entity2); - } -- } -+ } } finally { timer.stopTiming(); } // Paper - EAR2 timings - - } - } else { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index efa8d9a16e87475adf7e71a0dfa2861653f73c06..32dad0b72ee0d0a1ac30decb0fb52f4399f9f39f 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -68,6 +68,7 @@ import net.minecraft.world.entity.animal.EntityFish; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.vehicle.EntityBoat; -+import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.item.enchantment.EnchantmentProtection; -@@ -251,7 +252,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public boolean Y; - public boolean impulse; - public int portalCooldown; -- protected boolean inPortal; -+ public boolean inPortal; // Paper - public - protected int portalTicks; - protected BlockPosition ac; - private boolean invulnerable; -@@ -275,6 +276,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; -+ public boolean isTemporarilyActive = false; // Paper - public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one - protected int numCollisions = 0; // Paper - public void inactiveTick() { } -@@ -665,6 +667,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.recalcPosition(); - } else { - if (enummovetype == EnumMoveType.PISTON) { -+ this.activatedTick = MinecraftServer.currentTick + 20; // Paper - vec3d = this.b(vec3d); - if (vec3d.equals(Vec3D.ORIGIN)) { - return; -@@ -677,6 +680,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.x = Vec3D.ORIGIN; - this.setMot(Vec3D.ORIGIN); - } -+ // Paper start - ignore movement changes while inactive. -+ if (isTemporarilyActive && !(this instanceof EntityItem || this instanceof EntityMinecartAbstract) && vec3d == getMot() && enummovetype == EnumMoveType.SELF) { -+ setMot(Vec3D.ORIGIN); -+ this.world.getMethodProfiler().exit(); -+ return; -+ } -+ // Paper end - - vec3d = this.a(vec3d, enummovetype); - Vec3D vec3d1 = this.g(vec3d); -@@ -2012,6 +2022,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - } - -+ public void syncPositionOf(Entity entity) { k(entity); } // Paper - OBFHELPER - public void k(Entity entity) { - this.a(entity, Entity::setPosition); - } -@@ -2822,6 +2833,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.ae; - } - -+ public final boolean isPushedByWater() { return this.bV(); } // Paper - OBFHELPER - the below is not an obfhelper, don't use it! - public boolean bV() { - // Paper start - return this.pushedByWater(); -diff --git a/src/main/java/net/minecraft/world/entity/EntityCreature.java b/src/main/java/net/minecraft/world/entity/EntityCreature.java -index a9322e7cd8e07a2d5578c861991d53ec85fbfbcc..bbf0f345bfdd8a3a1f7fe902a42b2b18cdcf07a5 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityCreature.java -+++ b/src/main/java/net/minecraft/world/entity/EntityCreature.java -@@ -14,6 +14,7 @@ import org.bukkit.event.entity.EntityUnleashEvent; - public abstract class EntityCreature extends EntityInsentient { - - public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper -+ public BlockPosition movingTarget = null; public BlockPosition getMovingTarget() { return movingTarget; } // Paper - - protected EntityCreature(EntityTypes entitytypes, World world) { - super(entitytypes, world); -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0489fb4869c9a0b56df6f44ef3925de7651baef2..da190d0b21098e327fab42e79a4ae18629bcf6e5 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -115,7 +115,7 @@ public abstract class EntityInsentient extends EntityLiving { - public MinecraftKey lootTableKey; - public long lootTableSeed; - @Nullable -- private Entity leashHolder; -+ public Entity leashHolder; // Paper - private -> public - private int bx; - @Nullable - private NBTTagCompound by; -@@ -196,6 +196,19 @@ public abstract class EntityInsentient extends EntityLiving { - return this.lookController; - } - -+ // Paper start -+ @Override -+ public void inactiveTick() { -+ super.inactiveTick(); -+ if (this.goalSelector.inactiveTick()) { -+ this.goalSelector.doTick(); -+ } -+ if (this.targetSelector.inactiveTick()) { -+ this.targetSelector.doTick(); -+ } -+ } -+ // Paper end -+ - public ControllerMove getControllerMove() { - if (this.isPassenger() && this.getVehicle() instanceof EntityInsentient) { - EntityInsentient entityinsentient = (EntityInsentient) this.getVehicle(); -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 6a81aa44d2acde7575e0ed74ea8bf4070739f10e..ffb4072f46456b3a2b2daa55947787cee774d26d 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -192,7 +192,7 @@ public abstract class EntityLiving extends Entity { - protected float aN; - protected int aO;protected int getKillCount() { return this.aO; } // Paper - OBFHELPER - public float lastDamage; -- protected boolean jumping; -+ public boolean jumping; // Paper protected -> public - public float aR; - public float aS; - public float aT; -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -index 5e599d88a150c907f50acbb58ad1725c3fe361e4..b505c23c57a4b84faf5906c6295455b4720c4426 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -@@ -20,7 +20,10 @@ public abstract class PathfinderGoal { - - public void c() {} - -- public void d() {} -+ public void d() { -+ onTaskReset(); // Paper -+ } -+ public void onTaskReset() {} // Paper - - public void e() {} - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -index 6a156a488bc073b3b60f4d1081e3f2ab65ba9e96..8a0515ae03c9081b03e9c2a312826345038b8fa7 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -@@ -9,12 +9,12 @@ import net.minecraft.world.level.IWorldReader; - - public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - -- protected final EntityCreature a; -+ protected final EntityCreature a;public EntityCreature getEntity() { return a; } // Paper - OBFHELPER - public final double b; - protected int c; - protected int d; - private int g; -- protected BlockPosition e;public final BlockPosition getTargetPosition() { return this.e; } // Paper - OBFHELPER -+ protected BlockPosition e; public final BlockPosition getTargetPosition() { return this.e; } public void setTargetPosition(BlockPosition pos) { this.e = pos; getEntity().movingTarget = pos != BlockPosition.ZERO ? pos : null; } // Paper - OBFHELPER - private boolean h; - private final int i; - private final int j; -@@ -23,6 +23,13 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - public PathfinderGoalGotoTarget(EntityCreature entitycreature, double d0, int i) { - this(entitycreature, d0, i, 1); - } -+ // Paper start - activation range improvements -+ @Override -+ public void onTaskReset() { -+ super.onTaskReset(); -+ setTargetPosition(BlockPosition.ZERO); -+ } -+ // Paper end - - public PathfinderGoalGotoTarget(EntityCreature entitycreature, double d0, int i, int j) { - this.e = BlockPosition.ZERO; -@@ -111,6 +118,7 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, i1, k - 1, j1); - if (this.a.a((BlockPosition) blockposition_mutableblockposition) && this.a(this.a.world, blockposition_mutableblockposition)) { - this.e = blockposition_mutableblockposition; -+ setTargetPosition(blockposition_mutableblockposition.immutableCopy()); // Paper - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -index c9aaa63fcb0abe5628798827003c677c883c2a18..8c234c09a4d9ada83e36e3cdbcc1f2f5c6202f28 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -@@ -26,10 +26,11 @@ public class PathfinderGoalSelector { - } - }; - private final Map c = new EnumMap(PathfinderGoal.Type.class); -- private final Set d = Sets.newLinkedHashSet(); -+ private final Set d = Sets.newLinkedHashSet(); private Set getTasks() { return d; }// Paper - OBFHELPER - private final Supplier e; - private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); -- private int g = 3; -+ private int g = 3;private int getTickRate() { return g; } // Paper - OBFHELPER -+ private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO - - public PathfinderGoalSelector(Supplier supplier) { - this.e = supplier; -@@ -39,6 +40,21 @@ public class PathfinderGoalSelector { - this.d.add(new PathfinderGoalWrapped(i, pathfindergoal)); - } - -+ // Paper start -+ public boolean inactiveTick() { -+ incRate(); -+ return getCurRate() % getTickRate() == 0; -+ } -+ public boolean hasTasks() { -+ for (PathfinderGoalWrapped task : getTasks()) { -+ if (task.isRunning()) { -+ return true; -+ } -+ } -+ return false; -+ } -+ // Paper end -+ - public void a(PathfinderGoal pathfindergoal) { - this.d.stream().filter((pathfindergoalwrapped) -> { - return pathfindergoalwrapped.j() == pathfindergoal; -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -index 7395335ee97237376d34e315ea1d7d46766b278a..7bb531e47668cf445083c4dedb03ccafe6a9c96b 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -@@ -64,6 +64,7 @@ public class PathfinderGoalWrapped extends PathfinderGoal { - return this.a.i(); - } - -+ public boolean isRunning() { return this.g(); } // Paper - OBFHELPER - public boolean g() { - return this.c; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -index 8b09aaa30dd753fd34bea155890bdd9e5cb180f5..2005cb484ba6b5929ad81d3d120521f247f3d4cf 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -@@ -454,6 +454,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - return this.bC != null; - } - -+ public final boolean inCaravan() { return this.fC(); } // Paper - OBFHELPER - public boolean fC() { - return this.bB != null; - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 29957e79161db862c3eee5d0ed0cb8edb5dceb1c..596450d3cdb3be4abca3e75bed743abd071fb0b0 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -213,17 +213,29 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - @Override - public void inactiveTick() { - // SPIGOT-3874, SPIGOT-3894, SPIGOT-3846, SPIGOT-5286 :( -- if (world.spigotConfig.tickInactiveVillagers && this.doAITick()) { -- this.mobTick(); -+ // Paper start -+ if (this.getUnhappy() > 0) { -+ this.setUnhappy(this.getUnhappy() - 1); - } -+ if (this.doAITick()) { -+ if (world.spigotConfig.tickInactiveVillagers) { -+ this.mobTick(); -+ } else { -+ this.mobTick(true); -+ } -+ } -+ doReputationTick(); -+ // Paper end -+ - super.inactiveTick(); - } - // Spigot End - - @Override -- protected void mobTick() { -+ protected void mobTick() { mobTick(false); } -+ protected void mobTick(boolean inactive) { - this.world.getMethodProfiler().enter("villagerBrain"); -- this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error -+ if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper - this.world.getMethodProfiler().exit(); - if (this.bF) { - this.bF = false; -@@ -247,7 +259,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - this.bv = null; - } - -- if (!this.isNoAI() && this.random.nextInt(100) == 0) { -+ if (!inactive && !this.isNoAI() && this.random.nextInt(100) == 0) { // Paper - Raid raid = ((WorldServer) this.world).b_(this.getChunkCoordinates()); - - if (raid != null && raid.v() && !raid.a()) { -@@ -258,6 +270,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.eN()) { - this.eT(); - } -+ if (inactive) return; // Paper - - super.mobTick(); - } -@@ -901,6 +914,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - } - -+ private void doReputationTick() { fw(); } // Paper - OBFHELPER - private void fw() { - long i = this.world.getTime(); - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -index 190411d6fcee8bed686a2bcfd088aa7c2513fc26..3dd80fcf9237f15bb3bf38d1529340e178f09388 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -@@ -72,10 +72,12 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - return super.prepare(worldaccess, difficultydamagescaler, enummobspawn, (GroupDataEntity) groupdataentity, nbttagcompound); - } - -+ public final int getUnhappy() { return eK(); } // Paper - OBFHELPER - public int eK() { - return (Integer) this.datawatcher.get(EntityVillagerAbstract.bp); - } - -+ public final void setUnhappy(int i) { s(i); } // Paper - OBFHELPER - public void s(int i) { - this.datawatcher.set(EntityVillagerAbstract.bp, i); - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index d1738b57efd3f5e6c51603553a773173e4b09bb5..c4680142bf23d30169555abe7db78d85811e042b 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -142,6 +142,12 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public long ticksPerWaterSpawns; - public long ticksPerWaterAmbientSpawns; - public long ticksPerAmbientSpawns; -+ // Paper start -+ public int wakeupInactiveRemainingAnimals; -+ public int wakeupInactiveRemainingFlying; -+ public int wakeupInactiveRemainingMonsters; -+ public int wakeupInactiveRemainingVillagers; -+ // Paper end - public boolean populating; - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 53d0541aba207b5eaea2e49edbb56df918d30333..663127e6e6ec507959142b18a11a5a4790d4b98b 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -31,11 +31,30 @@ import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.phys.AxisAlignedBB; - import co.aikar.timings.MinecraftTimings; - -+// Paper start -+import net.minecraft.core.BlockPosition; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.world.entity.EntityFlying; -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.BehaviorController; -+import net.minecraft.world.entity.animal.EntityBee; -+import net.minecraft.world.entity.animal.EntityWaterAnimal; -+import net.minecraft.world.entity.animal.horse.EntityLlama; -+import net.minecraft.world.entity.monster.EntityPillager; -+import net.minecraft.world.entity.monster.IMonster; -+import net.minecraft.world.entity.schedule.Activity; -+import net.minecraft.world.entity.item.EntityFallingBlock; -+import net.minecraft.world.entity.projectile.EntityEnderSignal; -+// Paper end -+ - public class ActivationRange - { - - public enum ActivationType - { -+ WATER, // Paper -+ FLYING_MONSTER, // Paper -+ VILLAGER, // Paper - MONSTER, - ANIMAL, - RAIDER, -@@ -43,6 +62,43 @@ public class ActivationRange - - AxisAlignedBB boundingBox = new AxisAlignedBB( 0, 0, 0, 0, 0, 0 ); - } -+ // Paper start -+ -+ static Activity[] VILLAGER_PANIC_IMMUNITIES = { -+ Activity.HIDE, -+ Activity.PRE_RAID, -+ Activity.RAID, -+ Activity.PANIC -+ }; -+ -+ private static int checkInactiveWakeup(Entity entity) { -+ World world = entity.world; -+ SpigotWorldConfig config = world.spigotConfig; -+ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; -+ if (entity.activationType == ActivationType.VILLAGER) { -+ if (inactiveFor > config.wakeUpInactiveVillagersEvery && world.wakeupInactiveRemainingVillagers > 0) { -+ world.wakeupInactiveRemainingVillagers--; -+ return config.wakeUpInactiveVillagersFor; -+ } -+ } else if (entity.activationType == ActivationType.ANIMAL) { -+ if (inactiveFor > config.wakeUpInactiveAnimalsEvery && world.wakeupInactiveRemainingAnimals > 0) { -+ world.wakeupInactiveRemainingAnimals--; -+ return config.wakeUpInactiveAnimalsFor; -+ } -+ } else if (entity.activationType == ActivationType.FLYING_MONSTER) { -+ if (inactiveFor > config.wakeUpInactiveFlyingEvery && world.wakeupInactiveRemainingFlying > 0) { -+ world.wakeupInactiveRemainingFlying--; -+ return config.wakeUpInactiveFlyingFor; -+ } -+ } else if (entity.activationType == ActivationType.MONSTER || entity.activationType == ActivationType.RAIDER) { -+ if (inactiveFor > config.wakeUpInactiveMonstersEvery && world.wakeupInactiveRemainingMonsters > 0) { -+ world.wakeupInactiveRemainingMonsters--; -+ return config.wakeUpInactiveMonstersFor; -+ } -+ } -+ return -1; -+ } -+ // Paper end - - static AxisAlignedBB maxBB = new AxisAlignedBB( 0, 0, 0, 0, 0, 0 ); - -@@ -55,10 +111,13 @@ public class ActivationRange - */ - public static ActivationType initializeEntityActivationType(Entity entity) - { -+ if (entity instanceof EntityWaterAnimal) { return ActivationType.WATER; } // Paper -+ else if (entity instanceof EntityVillager) { return ActivationType.VILLAGER; } // Paper -+ else if (entity instanceof EntityFlying && entity instanceof IMonster) { return ActivationType.FLYING_MONSTER; } // Paper - doing & Monster incase Flying no longer includes monster in future - if ( entity instanceof EntityRaider ) - { - return ActivationType.RAIDER; -- } else if ( entity instanceof EntityMonster || entity instanceof EntitySlime ) -+ } else if ( entity instanceof IMonster ) // Paper - correct monster check - { - return ActivationType.MONSTER; - } else if ( entity instanceof EntityCreature || entity instanceof EntityAmbient ) -@@ -79,10 +138,14 @@ public class ActivationRange - */ - public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) - { -- if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange == 0 ) -- || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange == 0 ) -- || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange == 0 ) -- || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange == 0 ) -+ if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.VILLAGER && config.villagerActivationRange <= 0 ) // Paper -+ || ( entity.activationType == ActivationType.WATER && config.waterActivationRange <= 0 ) // Paper -+ || ( entity.activationType == ActivationType.FLYING_MONSTER && config.flyingMonsterActivationRange <= 0 ) // Paper -+ || entity instanceof EntityEnderSignal // Paper - || entity instanceof EntityHuman - || entity instanceof EntityProjectile - || entity instanceof EntityEnderDragon -@@ -115,10 +178,25 @@ public class ActivationRange - final int raiderActivationRange = world.spigotConfig.raiderActivationRange; - final int animalActivationRange = world.spigotConfig.animalActivationRange; - final int monsterActivationRange = world.spigotConfig.monsterActivationRange; -+ // Paper start -+ final int waterActivationRange = world.spigotConfig.waterActivationRange; -+ final int flyingActivationRange = world.spigotConfig.flyingMonsterActivationRange; -+ final int villagerActivationRange = world.spigotConfig.villagerActivationRange; -+ world.wakeupInactiveRemainingAnimals = Math.min(world.wakeupInactiveRemainingAnimals + 1, world.spigotConfig.wakeUpInactiveAnimals); -+ world.wakeupInactiveRemainingVillagers = Math.min(world.wakeupInactiveRemainingVillagers + 1, world.spigotConfig.wakeUpInactiveVillagers); -+ world.wakeupInactiveRemainingMonsters = Math.min(world.wakeupInactiveRemainingMonsters + 1, world.spigotConfig.wakeUpInactiveMonsters); -+ world.wakeupInactiveRemainingFlying = Math.min(world.wakeupInactiveRemainingFlying + 1, world.spigotConfig.wakeUpInactiveFlying); -+ final ChunkProviderServer chunkProvider = (ChunkProviderServer) world.getChunkProvider(); -+ // Paper end - - int maxRange = Math.max( monsterActivationRange, animalActivationRange ); - maxRange = Math.max( maxRange, raiderActivationRange ); - maxRange = Math.max( maxRange, miscActivationRange ); -+ // Paper start -+ maxRange = Math.max( maxRange, flyingActivationRange ); -+ maxRange = Math.max( maxRange, waterActivationRange ); -+ maxRange = Math.max( maxRange, villagerActivationRange ); -+ // Paper end - maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); - - for ( EntityHuman player : world.getPlayers() ) -@@ -130,6 +208,11 @@ public class ActivationRange - ActivationType.RAIDER.boundingBox = player.getBoundingBox().grow( raiderActivationRange, 256, raiderActivationRange ); - ActivationType.ANIMAL.boundingBox = player.getBoundingBox().grow( animalActivationRange, 256, animalActivationRange ); - ActivationType.MONSTER.boundingBox = player.getBoundingBox().grow( monsterActivationRange, 256, monsterActivationRange ); -+ // Paper start -+ ActivationType.WATER.boundingBox = player.getBoundingBox().grow( waterActivationRange, 256, waterActivationRange ); -+ ActivationType.FLYING_MONSTER.boundingBox = player.getBoundingBox().grow( flyingActivationRange, 256, flyingActivationRange ); -+ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().grow( villagerActivationRange, 256, waterActivationRange ); -+ // Paper end - - int i = MathHelper.floor( maxBB.minX / 16.0D ); - int j = MathHelper.floor( maxBB.maxX / 16.0D ); -@@ -140,7 +223,7 @@ public class ActivationRange - { - for ( int j1 = k; j1 <= l; ++j1 ) - { -- Chunk chunk = (Chunk) world.getChunkIfLoadedImmediately( i1, j1 ); -+ Chunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper - if ( chunk != null ) - { - activateChunkEntities( chunk ); -@@ -158,19 +241,15 @@ public class ActivationRange - */ - private static void activateChunkEntities(Chunk chunk) - { -- for ( java.util.List slice : chunk.entitySlices ) -- { -- for ( Entity entity : (Collection) slice ) -+ // Paper start -+ Entity[] rawData = chunk.entities.getRawData(); -+ for (int i = 0; i < chunk.entities.size(); i++) { -+ Entity entity = rawData[i]; -+ //for ( Entity entity : (Collection) slice ) -+ // Paper end - { -- if ( MinecraftServer.currentTick > entity.activatedTick ) -- { -- if ( entity.defaultActivationState ) -- { -- entity.activatedTick = MinecraftServer.currentTick; -- continue; -- } -- if ( entity.activationType.boundingBox.c( entity.getBoundingBox() ) ) -- { -+ if (MinecraftServer.currentTick > entity.activatedTick) { -+ if (entity.defaultActivationState || entity.activationType.boundingBox.c(entity.getBoundingBox())) { // Paper - entity.activatedTick = MinecraftServer.currentTick; - } - } -@@ -185,56 +264,105 @@ public class ActivationRange - * @param entity - * @return - */ -- public static boolean checkEntityImmunities(Entity entity) -+ public static int checkEntityImmunities(Entity entity) // Paper - return # of ticks to get immunity - { -+ // Paper start -+ SpigotWorldConfig config = entity.world.spigotConfig; -+ int inactiveWakeUpImmunity = checkInactiveWakeup(entity); -+ if (inactiveWakeUpImmunity > -1) { -+ return inactiveWakeUpImmunity; -+ } -+ if (entity.fireTicks > 0) { -+ return 2; -+ } -+ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; -+ // Paper end - // quick checks. -- if ( entity.inWater || entity.fireTicks > 0 ) -+ if ( (entity.activationType != ActivationType.WATER && entity.inWater && entity.isPushedByWater()) ) // Paper - { -- return true; -+ return 100; // Paper - } - if ( !( entity instanceof EntityArrow ) ) - { -- if ( !entity.isOnGround() || !entity.passengers.isEmpty() || entity.isPassenger() ) -+ if ( (!entity.isOnGround() && !(entity instanceof EntityFlying)) ) // Paper - remove passengers logic - { -- return true; -+ return 10; // Paper - } - } else if ( !( (EntityArrow) entity ).inGround ) - { -- return true; -+ return 1; // Paper - } - // special cases. - if ( entity instanceof EntityLiving ) - { - EntityLiving living = (EntityLiving) entity; -- if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTicks > 0 || living.effects.size() > 0 ) -+ if ( living.isClimbing() || living.jumping || living.hurtTicks > 0 || living.effects.size() > 0 ) // Paper - { -- return true; -+ return 1; // Paper - } -- if ( entity instanceof EntityCreature && ( (EntityCreature) entity ).getGoalTarget() != null ) -+ if ( entity instanceof EntityInsentient && ((EntityInsentient) entity ).getGoalTarget() != null) // Paper - { -- return true; -+ return 20; // Paper - } -- if ( entity instanceof EntityVillager && ( (EntityVillager) entity ).canBreed() ) -+ // Paper start -+ if (entity instanceof EntityBee) { -+ EntityBee bee = (EntityBee)entity; -+ BlockPosition movingTarget = bee.getMovingTarget(); -+ if (bee.isAngry() || -+ (bee.getHivePos() != null && bee.getHivePos().equals(movingTarget)) || -+ (bee.getFlowerPos() != null && bee.getFlowerPos().equals(movingTarget)) -+ ) { -+ return 20; -+ } -+ } -+ if ( entity instanceof EntityVillager ) { -+ BehaviorController behaviorController = ((EntityVillager) entity).getBehaviorController(); -+ -+ if (config.villagersActiveForPanic) { -+ for (Activity activity : VILLAGER_PANIC_IMMUNITIES) { -+ if (behaviorController.c(activity)) { -+ return 20*5; -+ } -+ } -+ } -+ -+ if (config.villagersWorkImmunityAfter > 0 && inactiveFor >= config.villagersWorkImmunityAfter) { -+ if (behaviorController.c(Activity.WORK)) { -+ return config.villagersWorkImmunityFor; -+ } -+ } -+ } -+ if ( entity instanceof EntityLlama && ( (EntityLlama) entity ).inCaravan() ) - { -- return true; -+ return 1; - } -+ // Paper end - if ( entity instanceof EntityAnimal ) - { - EntityAnimal animal = (EntityAnimal) entity; - if ( animal.isBaby() || animal.isInLove() ) - { -- return true; -+ return 5; // Paper - } - if ( entity instanceof EntitySheep && ( (EntitySheep) entity ).isSheared() ) - { -- return true; -+ return 1; // Paper - } - } - if (entity instanceof EntityCreeper && ((EntityCreeper) entity).isIgnited()) { // isExplosive -- return true; -+ return 20; // Paper - } -+ // Paper start -+ if (entity instanceof EntityInsentient && ((EntityInsentient) entity).targetSelector.hasTasks() ) { -+ return 0; -+ } -+ if (entity instanceof EntityPillager) { -+ EntityPillager pillager = (EntityPillager) entity; -+ // TODO:? -+ } -+ // Paper end - } -- return false; -+ return -1; // Paper - } - - /** -@@ -249,8 +377,19 @@ public class ActivationRange - if ( !entity.inChunk || entity instanceof EntityFireworks ) { - return true; - } -+ // Paper start - special case always immunities -+ // immunize brand new entities, dead entities, and portal scenarios -+ if (entity.defaultActivationState || entity.ticksLived < 20*10 || !entity.isAlive() || entity.inPortal || entity.portalCooldown > 0) { -+ return true; -+ } -+ // immunize leashed entities -+ if (entity instanceof EntityInsentient && ((EntityInsentient)entity).leashHolder instanceof EntityHuman) { -+ return true; -+ } -+ // Paper end - -- boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; -+ boolean isActive = entity.activatedTick >= MinecraftServer.currentTick; -+ entity.isTemporarilyActive = false; // Paper - - // Should this entity tick? - if ( !isActive ) -@@ -258,15 +397,19 @@ public class ActivationRange - if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) - { - // Check immunities every 20 ticks. -- if ( checkEntityImmunities( entity ) ) -- { -- // Triggered some sort of immunity, give 20 full ticks before we check again. -- entity.activatedTick = MinecraftServer.currentTick + 20; -+ // Paper start -+ int immunity = checkEntityImmunities(entity); -+ if (immunity >= 0) { -+ entity.activatedTick = MinecraftServer.currentTick + immunity; -+ } else { -+ entity.isTemporarilyActive = true; - } -+ // Paper end - isActive = true; -+ - } - // Add a little performance juice to active entities. Skip 1/4 if not immune. -- } else if ( !entity.defaultActivationState && entity.ticksLived % 4 == 0 && !checkEntityImmunities( entity ) ) -+ } else if (entity.ticksLived % 4 == 0 && checkEntityImmunities( entity) < 0 ) // Paper - { - isActive = false; - } -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 34ee684901906fc2ef5f0d09680d2686b813e52b..6b015c1f26facb4e82d75b252164dec05731ca6c 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -180,13 +180,59 @@ public class SpigotWorldConfig - public int monsterActivationRange = 32; - public int raiderActivationRange = 48; - public int miscActivationRange = 16; -+ // Paper start -+ public int flyingMonsterActivationRange = 32; -+ public int waterActivationRange = 16; -+ public int villagerActivationRange = 32; -+ public int wakeUpInactiveAnimals = 4; -+ public int wakeUpInactiveAnimalsEvery = 60*20; -+ public int wakeUpInactiveAnimalsFor = 5*20; -+ public int wakeUpInactiveMonsters = 8; -+ public int wakeUpInactiveMonstersEvery = 20*20; -+ public int wakeUpInactiveMonstersFor = 5*20; -+ public int wakeUpInactiveVillagers = 4; -+ public int wakeUpInactiveVillagersEvery = 30*20; -+ public int wakeUpInactiveVillagersFor = 5*20; -+ public int wakeUpInactiveFlying = 8; -+ public int wakeUpInactiveFlyingEvery = 10*20; -+ public int wakeUpInactiveFlyingFor = 5*20; -+ public int villagersWorkImmunityAfter = 5*20; -+ public int villagersWorkImmunityFor = 20; -+ public boolean villagersActiveForPanic = true; -+ // Paper end - public boolean tickInactiveVillagers = true; - private void activationRange() - { -+ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", animalActivationRange) != animalActivationRange; // Paper - animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange ); - monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange ); - raiderActivationRange = getInt( "entity-activation-range.raiders", raiderActivationRange ); - miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange ); -+ // Paper start -+ waterActivationRange = getInt( "entity-activation-range.water", waterActivationRange ); -+ villagerActivationRange = getInt( "entity-activation-range.villagers", hasAnimalsConfig ? animalActivationRange : villagerActivationRange ); -+ flyingMonsterActivationRange = getInt( "entity-activation-range.flying-monsters", flyingMonsterActivationRange ); -+ -+ wakeUpInactiveAnimals = getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", wakeUpInactiveAnimals); -+ wakeUpInactiveAnimalsEvery = getInt("entity-activation-range.wake-up-inactive.animals-every", wakeUpInactiveAnimalsEvery); -+ wakeUpInactiveAnimalsFor = getInt("entity-activation-range.wake-up-inactive.animals-for", wakeUpInactiveAnimalsFor); -+ -+ wakeUpInactiveMonsters = getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", wakeUpInactiveMonsters); -+ wakeUpInactiveMonstersEvery = getInt("entity-activation-range.wake-up-inactive.monsters-every", wakeUpInactiveMonstersEvery); -+ wakeUpInactiveMonstersFor = getInt("entity-activation-range.wake-up-inactive.monsters-for", wakeUpInactiveMonstersFor); -+ -+ wakeUpInactiveVillagers = getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", wakeUpInactiveVillagers); -+ wakeUpInactiveVillagersEvery = getInt("entity-activation-range.wake-up-inactive.villagers-every", wakeUpInactiveVillagersEvery); -+ wakeUpInactiveVillagersFor = getInt("entity-activation-range.wake-up-inactive.villagers-for", wakeUpInactiveVillagersFor); -+ -+ wakeUpInactiveFlying = getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", wakeUpInactiveFlying); -+ wakeUpInactiveFlyingEvery = getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", wakeUpInactiveFlyingEvery); -+ wakeUpInactiveFlyingFor = getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", wakeUpInactiveFlyingFor); -+ -+ villagersWorkImmunityAfter = getInt( "entity-activation-range.villagers-work-immunity-after", villagersWorkImmunityAfter ); -+ villagersWorkImmunityFor = getInt( "entity-activation-range.villagers-work-immunity-for", villagersWorkImmunityFor ); -+ villagersActiveForPanic = getBoolean( "entity-activation-range.villagers-active-for-panic", villagersActiveForPanic ); -+ // Paper end - tickInactiveVillagers = getBoolean( "entity-activation-range.tick-inactive-villagers", tickInactiveVillagers ); - log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Ra " + raiderActivationRange + " / Mi " + miscActivationRange + " / Tiv " + tickInactiveVillagers ); - } diff --git a/Unmapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch b/Unmapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch deleted file mode 100644 index 721133fa97..0000000000 --- a/Unmapped-Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AJMFactsheets -Date: Wed, 22 Jan 2020 19:52:28 -0600 -Subject: [PATCH] Fix items vanishing through end portal - -If the Paper configuration option "keep-spawn-loaded" is set to false, -items entering the overworld from the end will spawn at Y = 0. - -This is due to logic in the getHighestBlockYAt method in World.java -only searching the heightmap if the chunk is loaded. - -Quickly loading the exact world spawn chunk before searching the -heightmap resolves the issue without having to load all spawn chunks. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 32dad0b72ee0d0a1ac30decb0fb52f4399f9f39f..b1495da5fdead24caf9e936a385d97fd2db2a0cc 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2735,6 +2735,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - BlockPosition blockposition1; - - if (flag1) { -+ // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate -+ this.world.getChunkAtWorldCoords(this.world.getSpawn()); -+ // Paper end - blockposition1 = WorldServer.a; - } else { - blockposition1 = worldserver.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver.getSpawn()); diff --git a/Unmapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/Unmapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch deleted file mode 100644 index 7fbf667ed7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 26 Jan 2020 16:30:19 -0600 -Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java -index 4044861622294a317fef7e93aa86e96e8474b513..2aa5789437ba7eb20579da238c407a65a25b1d44 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java -@@ -16,7 +16,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; - - public class ControllerMove { - -- protected final EntityInsentient a; -+ protected final EntityInsentient a; public final EntityInsentient getEntity() { return a; } // Paper - OBFHELPER - protected double b; - protected double c; - protected double d; -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java -index 80cba36bc59e89c40c96ca556594a4285f06fc6f..d0cbc429144b89498a7f4dc6ff64924c5ba54ad8 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java -@@ -16,7 +16,7 @@ public class ControllerMoveFlying extends ControllerMove { - } - - @Override -- public void a() { -+ public void a() { tick(); } public void tick() { // Paper - OBFHELPER - if (this.h == ControllerMove.Operation.MOVE_TO) { - this.h = ControllerMove.Operation.WAIT; - this.a.setNoGravity(true); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -index 1ecf73f874f404f58a99316ae027f76db6b557db..7ce8eaeb9af3547869f467910b6a458118c63c1f 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -@@ -111,7 +111,17 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - - public EntityBee(EntityTypes entitytypes, World world) { - super(entitytypes, world); -- this.moveController = new ControllerMoveFlying(this, 20, true); -+ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 -+ this.moveController = new ControllerMoveFlying(this, 20, true) { -+ @Override -+ public void tick() { -+ if (getEntity().locY() <= 0) { -+ getEntity().setNoGravity(false); -+ } -+ super.tick(); -+ } -+ }; -+ // Paper end - this.lookController = new EntityBee.j(this); - this.a(PathType.DANGER_FIRE, -1.0F); - this.a(PathType.WATER, -1.0F); diff --git a/Unmapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/Unmapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch deleted file mode 100644 index 87a5073590..0000000000 --- a/Unmapped-Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 25 Jan 2020 17:04:35 -0800 -Subject: [PATCH] Optimise getChunkAt calls for loaded chunks - -bypass the need to get a player chunk, then get the either, -then unwrap it... - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 12b9be00d486ec960ef0ebc750f56011c90ce37c..5caf2121f2e551d7b4f0ddc74f10a44dc28ac62b 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -470,6 +470,12 @@ public class ChunkProviderServer extends IChunkProvider { - return this.getChunkAt(i, j, chunkstatus, flag); - }, this.serverThreadQueue).join(); - } else { -+ // Paper start - optimise for loaded chunks -+ Chunk ifLoaded = this.getChunkAtIfLoadedMainThread(i, j); -+ if (ifLoaded != null) { -+ return ifLoaded; -+ } -+ // Paper end - GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); - - gameprofilerfiller.c("getChunk"); -@@ -520,39 +526,7 @@ public class ChunkProviderServer extends IChunkProvider { - if (Thread.currentThread() != this.serverThread) { - return null; - } else { -- this.world.getMethodProfiler().c("getChunkNow"); -- long k = ChunkCoordIntPair.pair(i, j); -- -- for (int l = 0; l < 4; ++l) { -- if (k == this.cachePos[l] && this.cacheStatus[l] == ChunkStatus.FULL) { -- IChunkAccess ichunkaccess = this.cacheChunk[l]; -- -- return ichunkaccess instanceof Chunk ? (Chunk) ichunkaccess : null; -- } -- } -- -- PlayerChunk playerchunk = this.getChunk(k); -- -- if (playerchunk == null) { -- return null; -- } else { -- Either either = (Either) playerchunk.b(ChunkStatus.FULL).getNow(null); // CraftBukkit - decompile error -- -- if (either == null) { -- return null; -- } else { -- IChunkAccess ichunkaccess1 = (IChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error -- -- if (ichunkaccess1 != null) { -- this.a(k, ichunkaccess1, ChunkStatus.FULL); -- if (ichunkaccess1 instanceof Chunk) { -- return (Chunk) ichunkaccess1; -- } -- } -- -- return null; -- } -- } -+ return this.getChunkAtIfLoadedMainThread(i, j); // Paper - optimise for loaded chunks - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch b/Unmapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch deleted file mode 100644 index 04082e9a36..0000000000 --- a/Unmapped-Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 8 Feb 2020 18:02:24 -0600 -Subject: [PATCH] Allow overriding the java version check - --DPaper.IgnoreJavaVersion=true - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 808a7688ed81bdfef623ee0a151ff8f94df2a3d7..c519ceca6f7788ca7c5d74ad1001dbc09f62681c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -181,7 +181,7 @@ public class Main { - float javaVersion = Float.parseFloat(System.getProperty("java.class.version")); - if (javaVersion > 60.0) { - System.err.println("Unsupported Java detected (" + javaVersion + "). Only up to Java 16 is supported."); -- return; -+ if (!Boolean.getBoolean("Paper.IgnoreJavaVersion")) return; // Paper - } - - try { diff --git a/Unmapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch b/Unmapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch deleted file mode 100644 index 60a1317040..0000000000 --- a/Unmapped-Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 9 Feb 2020 00:19:05 -0600 -Subject: [PATCH] Add ThrownEggHatchEvent - -Adds a new event similar to PlayerEggThrowEvent, but without the Player requirement -(dispensers can throw eggs to hatch them, too). - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java b/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java -index 01cee6599f5d21a29310c30a8b1e505023d1a260..dc2e51718395494f60b0376d65d496daf2f76e71 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java -@@ -67,6 +67,16 @@ public class EntityEgg extends EntityProjectileThrowable { - hatchingType = event.getHatchingType(); - } - -+ // Paper start -+ com.destroystokyo.paper.event.entity.ThrownEggHatchEvent event = new com.destroystokyo.paper.event.entity.ThrownEggHatchEvent((org.bukkit.entity.Egg) getBukkitEntity(), hatching, b0, hatchingType); -+ event.callEvent(); -+ -+ b0 = event.getNumHatches(); -+ hatching = event.isHatching(); -+ hatchingType = event.getHatchingType(); -+ // Paper end -+ -+ - if (hatching) { - for (int i = 0; i < b0; ++i) { - Entity entity = world.getWorld().createEntity(new org.bukkit.Location(world.getWorld(), this.locX(), this.locY(), this.locZ(), this.yaw, 0.0F), hatchingType.getEntityClass()); diff --git a/Unmapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch b/Unmapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch deleted file mode 100644 index 8fd5f28cc8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch +++ /dev/null @@ -1,407 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Jan 2020 21:28:00 -0800 -Subject: [PATCH] Optimise random block ticking - -Massive performance improvement for random block ticking. -The performance increase comes from the fact that the vast -majority of attempted block ticks (~95% in my testing) fail -because the randomly selected block is not tickable. - -Now only tickable blocks are targeted, however this means that -the maximum number of block ticks occurs per chunk. However, -not all chunks are going to be targeted. The percent chance -of a chunk being targeted is based on how many tickable blocks -are in the chunk. -This means that while block ticks are spread out less, the -total number of blocks ticked per world tick remains the same. -Therefore, the chance of a random tickable block being ticked -remains the same. - -diff --git a/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3edc8e52e06a62ce9f8cc734fd7458b37cfaad91 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java -@@ -0,0 +1,46 @@ -+package com.destroystokyo.paper.util.math; -+ -+import java.util.Random; -+ -+public final class ThreadUnsafeRandom extends Random { -+ -+ // See javadoc and internal comments for java.util.Random where these values come from, how they are used, and the author for them. -+ private static final long multiplier = 0x5DEECE66DL; -+ private static final long addend = 0xBL; -+ private static final long mask = (1L << 48) - 1; -+ -+ private static long initialScramble(long seed) { -+ return (seed ^ multiplier) & mask; -+ } -+ -+ private long seed; -+ -+ @Override -+ public void setSeed(long seed) { -+ // note: called by Random constructor -+ this.seed = initialScramble(seed); -+ } -+ -+ @Override -+ protected int next(int bits) { -+ // avoid the expensive CAS logic used by superclass -+ return (int) (((this.seed = this.seed * multiplier + addend) & mask) >>> (48 - bits)); -+ } -+ -+ // Taken from -+ // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ -+ // https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2016/06/25/fastrange.c -+ // Original license is public domain -+ public static int fastRandomBounded(final long randomInteger, final long limit) { -+ // randomInteger must be [0, pow(2, 32)) -+ // limit must be [0, pow(2, 32)) -+ return (int)((randomInteger * limit) >>> 32); -+ } -+ -+ @Override -+ public int nextInt(int bound) { -+ // yes this breaks random's spec -+ // however there's nothing that uses this class that relies on it -+ return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound); -+ } -+} -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 4c9ec211470f95d538d1d95c74796190edf99b87..8c0aeb51f5e230fd6109e750732eb54559bc9637 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -468,6 +468,7 @@ public class BlockPosition extends BaseBlockPosition { - return this.d(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); - } - -+ public final BlockPosition.MutableBlockPosition setValues(final BaseBlockPosition baseblockposition) { return this.g(baseblockposition); } // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition g(BaseBlockPosition baseblockposition) { - return this.d(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 17c6118fb1ea1f16d37eb13116e11f886274ba95..82f9c49233acce3c95d8a07b2a1b187d5c57552d 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -675,7 +675,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { - }); - } - -- public void a(Chunk chunk, int i) { -+ // Paper start - optimise random block ticking -+ private final BlockPosition.MutableBlockPosition chunkTickMutablePosition = new BlockPosition.MutableBlockPosition(); -+ private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom(); -+ // Paper end -+ -+ public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - boolean flag = this.isRaining(); - int j = chunkcoordintpair.d(); -@@ -683,10 +688,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { - GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); - - gameprofilerfiller.enter("thunder"); -- BlockPosition blockposition; -+ final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change - - if (!this.paperConfig.disableThunder && flag && this.W() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder -- blockposition = this.a(this.a(j, 0, k, 15)); -+ blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper - if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); - boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper -@@ -709,59 +714,77 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - gameprofilerfiller.exitEnter("iceandsnow"); -- if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow -- blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, this.a(j, 0, k, 15)); -- BlockPosition blockposition1 = blockposition.down(); -+ if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking -+ // Paper start - optimise chunk ticking -+ this.getRandomBlockPosition(j, 0, k, 15, blockposition); -+ int normalY = chunk.getHighestBlockY(HeightMap.Type.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15); -+ int downY = normalY - 1; -+ blockposition.setY(normalY); -+ // Paper end - BiomeBase biomebase = this.getBiome(blockposition); - -- if (biomebase.a(this, blockposition1)) { -- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.getBlockData(), null); // CraftBukkit -+ // Paper start - optimise chunk ticking -+ blockposition.setY(downY); -+ if (biomebase.a(this, blockposition)) { -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.ICE.getBlockData(), null); // CraftBukkit -+ // Paper end - } - -+ blockposition.setY(normalY); // Paper - if (flag && biomebase.b(this, blockposition)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.getBlockData(), null); // CraftBukkit - } - -- if (flag && this.getBiome(blockposition1).c() == BiomeBase.Precipitation.RAIN) { -- this.getType(blockposition1).getBlock().c((World) this, blockposition1); -+ // Paper start - optimise chunk ticking -+ blockposition.setY(downY); -+ if (flag && this.getBiome(blockposition).c() == BiomeBase.Precipitation.RAIN) { -+ chunk.getType(blockposition).getBlock().c((World) this, blockposition); -+ // Paper end - } - } - -- gameprofilerfiller.exitEnter("tickBlocks"); -- timings.chunkTicksBlocks.startTiming(); // Paper -+ // Paper start - optimise random block ticking -+ gameprofilerfiller.exit(); - if (i > 0) { -- ChunkSection[] achunksection = chunk.getSections(); -- int l = achunksection.length; -+ gameprofilerfiller.enter("randomTick"); -+ timings.chunkTicksBlocks.startTiming(); // Paper - -- for (int i1 = 0; i1 < l; ++i1) { -- ChunkSection chunksection = achunksection[i1]; -+ ChunkSection[] sections = chunk.getSections(); - -- if (chunksection != Chunk.a && chunksection.d()) { -- int j1 = chunksection.getYPosition(); -+ for (int sectionIndex = 0; sectionIndex < 16; ++sectionIndex) { -+ ChunkSection section = sections[sectionIndex]; -+ if (section == null || section.tickingList.size() == 0) { -+ continue; -+ } - -- for (int k1 = 0; k1 < i; ++k1) { -- BlockPosition blockposition2 = this.a(j, j1, k, 15); -+ int yPos = sectionIndex << 4; - -- gameprofilerfiller.enter("randomTick"); -- IBlockData iblockdata = chunksection.getType(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); -+ for (int a = 0; a < randomTickSpeed; ++a) { -+ int tickingBlocks = section.tickingList.size(); -+ int index = this.randomTickRandom.nextInt(16 * 16 * 16); -+ if (index >= tickingBlocks) { -+ continue; -+ } - -- if (iblockdata.isTicking()) { -- iblockdata.b(this, blockposition2, this.random); -- } -+ long raw = section.tickingList.getRaw(index); -+ int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); -+ int randomX = location & 15; -+ int randomY = ((location >>> (4 + 4)) & 255) | yPos; -+ int randomZ = (location >>> 4) & 15; - -- Fluid fluid = iblockdata.getFluid(); -+ BlockPosition blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ); -+ IBlockData iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); - -- if (fluid.f()) { -- fluid.b(this, blockposition2, this.random); -- } -+ iblockdata.b(this, blockposition2, this.randomTickRandom); - -- gameprofilerfiller.exit(); -- } -+ // We drop the fluid tick since LAVA is ALREADY TICKED by the above method. -+ // TODO CHECK ON UPDATE - } - } -+ gameprofilerfiller.exit(); -+ timings.chunkTicksBlocks.stopTiming(); // Paper -+ // Paper end - } -- timings.chunkTicksBlocks.stopTiming(); // Paper -- gameprofilerfiller.exit(); - } - - protected BlockPosition a(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/util/DataBits.java b/src/main/java/net/minecraft/util/DataBits.java -index c4f3b680512fb15cea01ad12d0a00c6e60bf34b7..cfa444cf384920d446c6dc14b23e5158fc28df3b 100644 ---- a/src/main/java/net/minecraft/util/DataBits.java -+++ b/src/main/java/net/minecraft/util/DataBits.java -@@ -112,4 +112,32 @@ public class DataBits { - } - - } -+ -+ // Paper start -+ public final void forEach(DataBitConsumer consumer) { -+ int i = 0; -+ long[] along = this.b; -+ int j = along.length; -+ -+ for (int k = 0; k < j; ++k) { -+ long l = along[k]; -+ -+ for (int i1 = 0; i1 < this.f; ++i1) { -+ consumer.accept(i, (int) (l & this.d)); -+ l >>= this.c; -+ ++i; -+ if (i >= this.e) { -+ return; -+ } -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface DataBitConsumer { -+ -+ void accept(int location, int data); -+ -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -index 09a6310af6712d36c20167256b60dc3235e76021..ecec8a3c4d4b5d491f79ad60d7ce5a118f30b3db 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -@@ -91,7 +91,7 @@ public class EntityTurtle extends EntityAnimal { - } - - public void setHomePos(BlockPosition blockposition) { -- this.datawatcher.set(EntityTurtle.bp, blockposition); -+ this.datawatcher.set(EntityTurtle.bp, blockposition.immutableCopy()); // Paper - called with mutablepos... - } - - public BlockPosition getHomePos() { // Paper - public -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index c4680142bf23d30169555abe7db78d85811e042b..cc41dcd85760b57bb8076b37e9a907d1cb4e12c7 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -1472,10 +1472,18 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public abstract ITagRegistry p(); - - public BlockPosition a(int i, int j, int k, int l) { -+ // Paper start - allow use of mutable pos -+ BlockPosition.MutableBlockPosition ret = new BlockPosition.MutableBlockPosition(); -+ this.getRandomBlockPosition(i, j, k, l, ret); -+ return ret.immutableCopy(); -+ } -+ public final BlockPosition.MutableBlockPosition getRandomBlockPosition(int i, int j, int k, int l, BlockPosition.MutableBlockPosition out) { -+ // Paper end - this.n = this.n * 3 + 1013904223; - int i1 = this.n >> 2; - -- return new BlockPosition(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); -+ out.setValues(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); // Paper - change to setValues call -+ return out; // Paper - } - - public boolean isSavingDisabled() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index e7bb33125a25b9e5a68013b15d7b5b6b6769ab9b..fc55e89260fdec2c5045e8f00e091191980ff1f2 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -640,8 +640,8 @@ public class Chunk implements IChunkAccess { - this.entities.remove(entity); // Paper - } - -- @Override -- public int getHighestBlock(HeightMap.Type heightmap_type, int i, int j) { -+ public final int getHighestBlockY(HeightMap.Type heightmap_type, int i, int j) { return this.getHighestBlock(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1 -+ @Override public int getHighestBlock(HeightMap.Type heightmap_type, int i, int j) { // Paper - return ((HeightMap) this.heightMap.get(heightmap_type)).a(i & 15, j & 15) - 1; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index 0b4e346daaea91565fde2f789fafa8b431a7b042..4bc26a7a4ae91aac90c256758ec8868d83027c0c 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -14,12 +14,14 @@ import net.minecraft.world.level.material.Fluid; - public class ChunkSection { - - public static final DataPalette GLOBAL_PALETTE = new DataPaletteGlobal<>(Block.REGISTRY_ID, Blocks.AIR.getBlockData()); -- private final int yPos; -+ final int yPos; // Paper - private -> package-private - short nonEmptyBlockCount; // Paper - package-private -- private short tickingBlockCount; -+ short tickingBlockCount; // Paper - private -> package-private - private short e; - final DataPaletteBlock blockIds; // Paper - package-private - -+ public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper -+ - // Paper start - Anti-Xray - Add parameters - @Deprecated public ChunkSection(int i) { this(i, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere - public ChunkSection(int i, IChunkAccess chunk, World world, boolean initializeBlocks) { -@@ -74,6 +76,9 @@ public class ChunkSection { - --this.nonEmptyBlockCount; - if (iblockdata1.isTicking()) { - --this.tickingBlockCount; -+ // Paper start -+ this.tickingList.remove(i, j, k); -+ // Paper end - } - } - -@@ -85,6 +90,9 @@ public class ChunkSection { - ++this.nonEmptyBlockCount; - if (iblockdata.isTicking()) { - ++this.tickingBlockCount; -+ // Paper start -+ this.tickingList.add(i, j, k, iblockdata); -+ // Paper end - } - } - -@@ -120,23 +128,29 @@ public class ChunkSection { - } - - public void recalcBlockCounts() { -+ // Paper start -+ this.tickingList.clear(); -+ // Paper end - this.nonEmptyBlockCount = 0; - this.tickingBlockCount = 0; - this.e = 0; -- this.blockIds.a((iblockdata, i) -> { -+ this.blockIds.forEachLocation((iblockdata, location) -> { // Paper - Fluid fluid = iblockdata.getFluid(); - - if (!iblockdata.isAir()) { -- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); - if (iblockdata.isTicking()) { -- this.tickingBlockCount = (short) (this.tickingBlockCount + i); -+ this.tickingBlockCount = (short) (this.tickingBlockCount + 1); -+ // Paper start -+ this.tickingList.add(location, iblockdata); -+ // Paper end - } - } - - if (!fluid.isEmpty()) { -- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); - if (fluid.f()) { -- this.e = (short) (this.e + i); -+ this.e = (short) (this.e + 1); - } - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index 68d53a51acc9790b9cda20ec4d2ec6edd1baac1a..86dfab740883c138a0df8a3da9dfb4eb9acefaa3 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -286,6 +286,14 @@ public class DataPaletteBlock implements DataPaletteExpandable { - }); - } - -+ // Paper start -+ public void forEachLocation(DataPaletteBlock.a datapaletteblock_a) { -+ this.getDataBits().forEach((int location, int data) -> { -+ datapaletteblock_a.accept(this.getDataPalette().getObject(data), location); -+ }); -+ } -+ // Paper end -+ - @FunctionalInterface - public interface a { - diff --git a/Unmapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch b/Unmapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch deleted file mode 100644 index 99dca253e4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0407-Entity-Jump-API.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 8 Feb 2020 23:26:11 -0600 -Subject: [PATCH] Entity Jump API - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index ffb4072f46456b3a2b2daa55947787cee774d26d..571e6bced3cfaacbd40378e67b01cdfda550feb7 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -2876,8 +2876,10 @@ public abstract class EntityLiving extends Entity { - } else if (this.aQ() && (!this.onGround || d7 > d8)) { - this.c((Tag) TagsFluid.LAVA); - } else if ((this.onGround || flag && d7 <= d8) && this.jumpTicks == 0) { -+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - this.jump(); - this.jumpTicks = 10; -+ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop - } - } else { - this.jumpTicks = 0; -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -index f755607872920caae1410d38c431c16b5238c00f..711b322007a0973ff0aebf3c25efbae8fc7741d0 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -@@ -490,7 +490,9 @@ public class EntityPanda extends EntityAnimal { - EntityPanda entitypanda = (EntityPanda) iterator.next(); - - if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.fh()) { -+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - entitypanda.jump(); -+ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop - } - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index db5d9a8107babd42200f911d2b8ebdc15b4d7c8b..468dca6d8c2ec77c3c77c93d04fb9dc329b1befa 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -804,5 +804,19 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public org.bukkit.inventory.EquipmentSlot getHandRaised() { - return getHandle().getRaisedHand() == net.minecraft.world.EnumHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; - } -+ -+ @Override -+ public boolean isJumping() { -+ return getHandle().jumping; -+ } -+ -+ @Override -+ public void setJumping(boolean jumping) { -+ getHandle().setJumping(jumping); -+ if (jumping && getHandle() instanceof EntityInsentient) { -+ // this is needed to actually make a mob jump -+ ((EntityInsentient) getHandle()).getControllerJump().jump(); -+ } -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch b/Unmapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch deleted file mode 100644 index 3fe02b251a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 7 Feb 2020 14:36:56 -0600 -Subject: [PATCH] Add option to nerf pigmen from nether portals - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7fbd501d70dccf869a4454e2789a5d68f2e15754..9e4591ddc4b755f4ff5a6f1078b51cb13db80480 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -594,4 +594,9 @@ public class PaperWorldConfig { - disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); - log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); - } -+ -+ public boolean nerfNetherPortalPigmen = false; -+ private void nerfNetherPortalPigmen() { -+ nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b1495da5fdead24caf9e936a385d97fd2db2a0cc..334d60c71fa13841f9d04af5404cc25acbc0ec76 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -278,6 +278,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public long activatedTick = Integer.MIN_VALUE; - public boolean isTemporarilyActive = false; // Paper - public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one -+ public boolean fromNetherPortal; // Paper - protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end -@@ -1694,6 +1695,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - if (spawnedViaMobSpawner) { - nbttagcompound.setBoolean("Paper.FromMobSpawner", true); - } -+ if (fromNetherPortal) { -+ nbttagcompound.setBoolean("Paper.FromNetherPortal", true); -+ } - // Paper end - return nbttagcompound; - } catch (Throwable throwable) { -@@ -1828,6 +1832,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ fromNetherPortal = nbttagcompound.getBoolean("Paper.FromNetherPortal"); - if (nbttagcompound.hasKey("Paper.SpawnReason")) { - String spawnReasonName = nbttagcompound.getString("Paper.SpawnReason"); - try { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPortal.java b/src/main/java/net/minecraft/world/level/block/BlockPortal.java -index e115ff86987c69f5e3571af5d7f034f24a3f6bba..5f797260eff317409a5039b88b01ad79ee2fdd91 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPortal.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPortal.java -@@ -7,6 +7,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; - import net.minecraft.world.entity.player.EntityHuman; -@@ -62,6 +63,8 @@ public class BlockPortal extends Block { - - if (entity != null) { - entity.resetPortalCooldown(); -+ entity.fromNetherPortal = true; // Paper -+ if (worldserver.paperConfig.nerfNetherPortalPigmen) ((EntityInsentient) entity).aware = false; // Paper - } - } - } diff --git a/Unmapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch b/Unmapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch deleted file mode 100644 index 93777c67a1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch +++ /dev/null @@ -1,436 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 2 Feb 2020 04:00:40 -0600 -Subject: [PATCH] Make the GUI graph fancier - - -diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphColor.java b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a4e641fdcccd3efcd1a2865dc6dc28d50671b995 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java -@@ -0,0 +1,44 @@ -+package com.destroystokyo.paper.gui; -+ -+import java.awt.Color; -+ -+public class GraphColor { -+ private static final Color[] colorLine = new Color[101]; -+ private static final Color[] colorFill = new Color[101]; -+ -+ static { -+ for (int i = 0; i < 101; i++) { -+ Color color = createColor(i); -+ colorLine[i] = new Color(color.getRed() / 2, color.getGreen() / 2, color.getBlue() / 2, 255); -+ colorFill[i] = new Color(colorLine[i].getRed(), colorLine[i].getGreen(), colorLine[i].getBlue(), 125); -+ } -+ } -+ -+ public static Color getLineColor(int percent) { -+ return colorLine[percent]; -+ } -+ -+ public static Color getFillColor(int percent) { -+ return colorFill[percent]; -+ } -+ -+ private static Color createColor(int percent) { -+ if (percent <= 50) { -+ return new Color(0X00FF00); -+ } -+ -+ int value = 510 - (int) (Math.min(Math.max(0, ((percent - 50) / 50F)), 1) * 510); -+ -+ int red, green; -+ if (value < 255) { -+ red = 255; -+ green = (int) (Math.sqrt(value) * 16); -+ } else { -+ green = 255; -+ value = value - 255; -+ red = 255 - (value * value / 255); -+ } -+ -+ return new Color(red, green, 0); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphData.java b/src/main/java/com/destroystokyo/paper/gui/GraphData.java -new file mode 100644 -index 0000000000000000000000000000000000000000..186fc722965e403f76b1480e1c2381fc34e29049 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/GraphData.java -@@ -0,0 +1,47 @@ -+package com.destroystokyo.paper.gui; -+ -+import java.awt.Color; -+ -+public class GraphData { -+ private long total; -+ private long free; -+ private long max; -+ private long usedMem; -+ private int usedPercent; -+ -+ public GraphData(long total, long free, long max) { -+ this.total = total; -+ this.free = free; -+ this.max = max; -+ this.usedMem = total - free; -+ this.usedPercent = usedMem == 0 ? 0 : (int) (usedMem * 100L / max); -+ } -+ -+ public long getTotal() { -+ return total; -+ } -+ -+ public long getFree() { -+ return free; -+ } -+ -+ public long getMax() { -+ return max; -+ } -+ -+ public long getUsedMem() { -+ return usedMem; -+ } -+ -+ public int getUsedPercent() { -+ return usedPercent; -+ } -+ -+ public Color getFillColor() { -+ return GraphColor.getFillColor(usedPercent); -+ } -+ -+ public Color getLineColor() { -+ return GraphColor.getLineColor(usedPercent); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0f29ad583e798c09b2fe3f568ed50cbc719e40e2 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.gui; -+ -+import net.minecraft.server.MinecraftServer; -+ -+import javax.swing.JPanel; -+import javax.swing.Timer; -+import java.awt.BorderLayout; -+import java.awt.Dimension; -+ -+public class GuiStatsComponent extends JPanel { -+ private final Timer timer; -+ private final RAMGraph ramGraph; -+ -+ public GuiStatsComponent(MinecraftServer server) { -+ super(new BorderLayout()); -+ -+ setOpaque(false); -+ -+ ramGraph = new RAMGraph(); -+ RAMDetails ramDetails = new RAMDetails(server); -+ -+ add(ramGraph, "North"); -+ add(ramDetails, "Center"); -+ -+ timer = new Timer(500, (event) -> { -+ ramGraph.update(); -+ ramDetails.update(); -+ }); -+ timer.start(); -+ } -+ -+ @Override -+ public Dimension getPreferredSize() { -+ return new Dimension(350, 200); -+ } -+ -+ public void stop() { a(); } public void a() { -+ timer.stop(); -+ ramGraph.stop(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -new file mode 100644 -index 0000000000000000000000000000000000000000..67d064e3959ed8d886df30ce9d97f86c2443fa39 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -@@ -0,0 +1,73 @@ -+package com.destroystokyo.paper.gui; -+ -+import net.minecraft.SystemUtils; -+import net.minecraft.server.MinecraftServer; -+ -+import javax.swing.DefaultListCellRenderer; -+import javax.swing.DefaultListSelectionModel; -+import javax.swing.JList; -+import javax.swing.border.EmptyBorder; -+import java.awt.Dimension; -+import java.text.DecimalFormat; -+import java.text.DecimalFormatSymbols; -+import java.util.Locale; -+import java.util.Vector; -+ -+public class RAMDetails extends JList { -+ public static final DecimalFormat DECIMAL_FORMAT = SystemUtils.peek(new DecimalFormat("########0.000"), (format) -+ -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT))); -+ -+ private final MinecraftServer server; -+ -+ public RAMDetails(MinecraftServer server) { -+ this.server = server; -+ -+ setBorder(new EmptyBorder(0, 10, 0, 0)); -+ setFixedCellHeight(20); -+ setOpaque(false); -+ -+ DefaultListCellRenderer renderer = new DefaultListCellRenderer(); -+ renderer.setOpaque(false); -+ setCellRenderer(renderer); -+ -+ setSelectionModel(new DefaultListSelectionModel() { -+ @Override -+ public void setAnchorSelectionIndex(final int anchorIndex) { -+ } -+ -+ @Override -+ public void setLeadAnchorNotificationEnabled(final boolean flag) { -+ } -+ -+ @Override -+ public void setLeadSelectionIndex(final int leadIndex) { -+ } -+ -+ @Override -+ public void setSelectionInterval(final int index0, final int index1) { -+ } -+ }); -+ } -+ -+ @Override -+ public Dimension getPreferredSize() { -+ return new Dimension(350, 100); -+ } -+ -+ public void update() { -+ GraphData data = RAMGraph.DATA.peekLast(); -+ Vector vector = new Vector<>(); -+ vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); -+ vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); -+ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); -+ setListData(vector); -+ } -+ -+ public double getAverage(long[] tickTimes) { -+ long total = 0L; -+ for (long value : tickTimes) { -+ total += value; -+ } -+ return ((double) total / (double) tickTimes.length) * 1.0E-6D; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c3e54da4ab6440811aab2f9dd1e218802ac13285 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java -@@ -0,0 +1,144 @@ -+package com.destroystokyo.paper.gui; -+ -+import javax.swing.JComponent; -+import javax.swing.SwingUtilities; -+import javax.swing.Timer; -+import javax.swing.ToolTipManager; -+import java.awt.Color; -+import java.awt.Dimension; -+import java.awt.Graphics; -+import java.awt.MouseInfo; -+import java.awt.Point; -+import java.awt.PointerInfo; -+import java.awt.event.MouseAdapter; -+import java.awt.event.MouseEvent; -+import java.text.SimpleDateFormat; -+import java.util.Date; -+import java.util.LinkedList; -+import java.util.concurrent.TimeUnit; -+ -+public class RAMGraph extends JComponent { -+ public static final LinkedList DATA = new LinkedList() { -+ @Override -+ public boolean add(GraphData data) { -+ if (size() >= 348) { -+ remove(); -+ } -+ return super.add(data); -+ } -+ }; -+ -+ static { -+ GraphData empty = new GraphData(0, 0, 0); -+ for (int i = 0; i < 350; i++) { -+ DATA.add(empty); -+ } -+ } -+ -+ private final Timer timer; -+ private final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); -+ -+ private int currentTick; -+ -+ public RAMGraph() { -+ ToolTipManager.sharedInstance().setInitialDelay(0); -+ -+ addMouseListener(new MouseAdapter() { -+ final int defaultDismissTimeout = ToolTipManager.sharedInstance().getDismissDelay(); -+ final int dismissDelayMinutes = (int) TimeUnit.MINUTES.toMillis(10); -+ -+ @Override -+ public void mouseEntered(MouseEvent me) { -+ ToolTipManager.sharedInstance().setDismissDelay(dismissDelayMinutes); -+ } -+ -+ @Override -+ public void mouseExited(MouseEvent me) { -+ ToolTipManager.sharedInstance().setDismissDelay(defaultDismissTimeout); -+ } -+ }); -+ -+ timer = new Timer(50, (event) -> repaint()); -+ timer.start(); -+ } -+ -+ @Override -+ public Dimension getPreferredSize() { -+ return new Dimension(350, 110); -+ } -+ -+ public void update() { -+ Runtime jvm = Runtime.getRuntime(); -+ DATA.add(new GraphData(jvm.totalMemory(), jvm.freeMemory(), jvm.maxMemory())); -+ -+ PointerInfo pointerInfo = MouseInfo.getPointerInfo(); -+ if (pointerInfo != null) { -+ Point point = pointerInfo.getLocation(); -+ if (point != null) { -+ Point loc = new Point(point); -+ SwingUtilities.convertPointFromScreen(loc, this); -+ if (this.contains(loc)) { -+ ToolTipManager.sharedInstance().mouseMoved( -+ new MouseEvent(this, -1, System.currentTimeMillis(), 0, loc.x, loc.y, -+ point.x, point.y, 0, false, 0)); -+ } -+ } -+ } -+ -+ currentTick++; -+ } -+ -+ @Override -+ public void paint(Graphics graphics) { -+ graphics.setColor(new Color(0xFFFFFFFF)); -+ graphics.fillRect(0, 0, 350, 100); -+ -+ graphics.setColor(new Color(0x888888)); -+ graphics.drawLine(1, 25, 348, 25); -+ graphics.drawLine(1, 50, 348, 50); -+ graphics.drawLine(1, 75, 348, 75); -+ -+ int i = 0; -+ for (GraphData data : DATA) { -+ i++; -+ if ((i + currentTick) % 120 == 0) { -+ graphics.setColor(new Color(0x888888)); -+ graphics.drawLine(i, 1, i, 99); -+ } -+ int used = data.getUsedPercent(); -+ if (used > 0) { -+ Color color = data.getLineColor(); -+ graphics.setColor(data.getFillColor()); -+ graphics.fillRect(i, 100 - used, 1, used); -+ graphics.setColor(color); -+ graphics.fillRect(i, 100 - used, 1, 1); -+ } -+ } -+ -+ graphics.setColor(new Color(0xFF000000)); -+ graphics.drawRect(0, 0, 348, 100); -+ -+ Point m = getMousePosition(); -+ if (m != null && m.x > 0 && m.x < 348 && m.y > 0 && m.y < 100) { -+ GraphData data = DATA.get(m.x); -+ int used = data.getUsedPercent(); -+ graphics.setColor(new Color(0x000000)); -+ graphics.drawLine(m.x, 1, m.x, 99); -+ graphics.drawOval(m.x - 2, 100 - used - 2, 5, 5); -+ graphics.setColor(data.getLineColor()); -+ graphics.fillOval(m.x - 2, 100 - used - 2, 5, 5); -+ setToolTipText(String.format("Used: %s mb (%s%%)
    %s", -+ Math.round(data.getUsedMem() / 1024F / 1024F), -+ used, getTime(m.x))); -+ } -+ } -+ -+ public String getTime(int halfSeconds) { -+ int millis = (348 - halfSeconds) / 2 * 1000; -+ return TIME_FORMAT.format(new Date((System.currentTimeMillis() - millis))); -+ } -+ -+ public void stop() { -+ timer.stop(); -+ } -+} -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 46d82c1548088b8305f758699388edf0d5d4d050..397194b3e90c9df39cfae17b401c7ac891b0dbb7 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -260,6 +260,7 @@ public class SystemUtils { - return supplier.get(); - } - -+ public static T peek(T t0, Consumer consumer) { return a(t0, consumer); } // Paper - OBFHELPER - public static T a(T t0, Consumer consumer) { - consumer.accept(t0); - return t0; -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 566b7c88ca467a92bcba2665edb852f77f8acd1e..b4e058794c3f8a827f3aabab5b98239a4c79c42c 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -218,7 +218,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ private static final DecimalFormat a = (DecimalFormat) SystemUtils.a(new DecimalFormat("########0.000"), (decimalformat) -> { // Paper - decompile error - decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); - }); - private final int[] b = new int[256]; -diff --git a/src/main/java/net/minecraft/server/gui/ServerGUI.java b/src/main/java/net/minecraft/server/gui/ServerGUI.java -index dc2a36f6dbc83ba25bcd59d981f75499adbd22e5..c2c075b9e3b70f863b6c450e4f31d6fde2935be6 100644 ---- a/src/main/java/net/minecraft/server/gui/ServerGUI.java -+++ b/src/main/java/net/minecraft/server/gui/ServerGUI.java -@@ -91,7 +91,7 @@ public class ServerGUI extends JComponent { - - private JComponent c() { - JPanel jpanel = new JPanel(new BorderLayout()); -- GuiStatsComponent guistatscomponent = new GuiStatsComponent(this.c); -+ com.destroystokyo.paper.gui.GuiStatsComponent guistatscomponent = new com.destroystokyo.paper.gui.GuiStatsComponent(this.c); // Paper - - this.e.add(guistatscomponent::a); - jpanel.add(guistatscomponent, "North"); diff --git a/Unmapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch b/Unmapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch deleted file mode 100644 index 9d62e030b8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sun, 1 Mar 2020 22:43:24 +0100 -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 b7ebd2e3e919d09ee99997f2358cc0c399d5041b..0b27d68dce9537c17701bd4944c807414564170b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -349,13 +349,18 @@ public class CraftEventFactory { - } - - org.bukkit.inventory.ItemStack item; -+ //Paper start - add hand to BlockMultiPlaceEvent -+ EquipmentSlot equipmentSlot; - if (hand == EnumHand.MAIN_HAND) { - item = player.getInventory().getItemInMainHand(); -+ equipmentSlot = EquipmentSlot.HAND; - } else { - item = player.getInventory().getItemInOffHand(); -+ equipmentSlot = EquipmentSlot.OFF_HAND; - } - -- BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild); -+ BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild, equipmentSlot); -+ //Paper end - craftServer.getPluginManager().callEvent(event); - - return event; diff --git a/Unmapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch b/Unmapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch deleted file mode 100644 index 7d5e3227f2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 3 Mar 2020 05:26:40 +0000 -Subject: [PATCH] Prevent teleporting dead entities - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 72df753d8c8e12cb3efaa02f37b05496701cc9f9..8a8f75acdd55e00ac2e7b5c621d1f522208df2c2 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1470,6 +1470,10 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { -+ if (player.dead) { -+ LOGGER.info("Attempt to teleport dead player {} restricted", player.getName()); -+ return; -+ } - // CraftBukkit start - if (Float.isNaN(f)) { - f = 0; diff --git a/Unmapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch b/Unmapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch deleted file mode 100644 index 75c8efe983..0000000000 --- a/Unmapped-Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 7 Mar 2020 00:07:51 +0000 -Subject: [PATCH] Validate tripwire hook placement before update - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java b/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java -index 8b24978cb54f2102d61f27038dedc5e3dc392dbc..5e3cf96b813d2871adf7a7f870af6c6a5dd878c1 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java -@@ -170,6 +170,7 @@ public class BlockTripwireHook extends Block { - - this.a(world, blockposition, flag4, flag5, flag2, flag3); - if (!flag) { -+ if (world.getType(blockposition).getBlock() == Blocks.TRIPWIRE_HOOK) // Paper - validate - world.setTypeAndData(blockposition, (IBlockData) iblockdata3.set(BlockTripwireHook.FACING, enumdirection), 3); - if (flag1) { - this.a(world, blockposition, enumdirection); diff --git a/Unmapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/Unmapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch deleted file mode 100644 index bc4517ce5b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 13 Apr 2019 16:50:58 -0500 -Subject: [PATCH] Add option to allow iron golems to spawn in air - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9e4591ddc4b755f4ff5a6f1078b51cb13db80480..fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -387,6 +387,11 @@ public class PaperWorldConfig { - scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); - } - -+ public boolean ironGolemsCanSpawnInAir = false; -+ private void ironGolemsCanSpawnInAir() { -+ ironGolemsCanSpawnInAir = getBoolean("iron-golems-can-spawn-in-air", ironGolemsCanSpawnInAir); -+ } -+ - public boolean armorStandEntityLookups = true; - private void armorStandEntityLookups() { - armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -index 49495cfbcf9b7742583536b87fc7cbd7c7c4c867..5e2b49d120b724cb5a7ae00940ded4f4875ea8a1 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -@@ -297,7 +297,7 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - BlockPosition blockposition1 = blockposition.down(); - IBlockData iblockdata = iworldreader.getType(blockposition1); - -- if (!iblockdata.a((IBlockAccess) iworldreader, blockposition1, (Entity) this)) { -+ if (!iblockdata.a((IBlockAccess) iworldreader, blockposition1, (Entity) this) && !world.paperConfig.ironGolemsCanSpawnInAir) { // Paper - return false; - } else { - for (int i = 1; i < 3; ++i) { diff --git a/Unmapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch b/Unmapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch deleted file mode 100644 index 0a2c05d50a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zero -Date: Sat, 22 Feb 2020 16:10:31 -0500 -Subject: [PATCH] Configurable chance of villager zombie infection - -This allows you to solve an issue in vanilla behavior where: -* On easy difficulty your villagers will NEVER get infected, meaning they will always die. -* On normal difficulty they will have a 50% of getting infected or dying. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f..525d702d78a609af987ebd2c32169b873e5c05ed 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -604,4 +604,9 @@ public class PaperWorldConfig { - private void nerfNetherPortalPigmen() { - nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); - } -+ -+ public double zombieVillagerInfectionChance = -1.0; -+ private void zombieVillagerInfectionChance() { -+ zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index f406826945dd752e6528743a0c8cad3cfdfc4a95..3d8d4a43e6cd554b6f1eeafa1c8d43cef877139a 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -450,10 +450,14 @@ public class EntityZombie extends EntityMonster { - @Override - public void a(WorldServer worldserver, EntityLiving entityliving) { - super.a(worldserver, entityliving); -- if ((worldserver.getDifficulty() == EnumDifficulty.NORMAL || worldserver.getDifficulty() == EnumDifficulty.HARD) && entityliving instanceof EntityVillager) { -- if (worldserver.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) { -+ // Paper start -+ if (world.paperConfig.zombieVillagerInfectionChance != 0.0 && (world.paperConfig.zombieVillagerInfectionChance != -1.0 || worldserver.getDifficulty() == EnumDifficulty.NORMAL || worldserver.getDifficulty() == EnumDifficulty.HARD) && entityliving instanceof EntityVillager) { -+ if (world.paperConfig.zombieVillagerInfectionChance == -1.0 && worldserver.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) { - return; - } -+ if (world.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > world.paperConfig.zombieVillagerInfectionChance) { -+ return; -+ } // Paper end - - EntityVillager entityvillager = (EntityVillager) entityliving; - // CraftBukkit start diff --git a/Unmapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch b/Unmapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch deleted file mode 100644 index 593c9aaac6..0000000000 --- a/Unmapped-Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 14 Jan 2020 14:59:08 -0800 -Subject: [PATCH] Optimise Chunk#getFluid - -Removing the try catch and generally reducing ops should make it -faster on its own, however removing the try catch makes it -easier to inline due to code size - -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index fc55e89260fdec2c5045e8f00e091191980ff1f2..bb2ff043f0d159fa18769c31b08683ee12037c58 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -431,17 +431,20 @@ public class Chunk implements IChunkAccess { - } - - public Fluid a(int i, int j, int k) { -- try { -- if (j >= 0 && j >> 4 < this.sections.length) { -- ChunkSection chunksection = this.sections[j >> 4]; -- -- if (!ChunkSection.a(chunksection)) { -- return chunksection.b(i & 15, j & 15, k & 15); -+ //try { // Paper - remove try catch -+ // Paper start - reduce the number of ops in this call -+ int index = j >> 4; -+ if (index >= 0 && index < this.sections.length) { -+ ChunkSection chunksection = this.sections[index]; -+ -+ if (chunksection != null) { -+ return chunksection.blockIds.a((j & 15) << 8 | (k & 15) << 4 | i & 15).getFluid(); - } -+ // Paper end - } - - return FluidTypes.EMPTY.h(); -- } catch (Throwable throwable) { -+ /*} catch (Throwable throwable) { // Paper - remove try catch - CrashReport crashreport = CrashReport.a(throwable, "Getting fluid state"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being got"); - -@@ -450,6 +453,7 @@ public class Chunk implements IChunkAccess { - }); - throw new ReportedException(crashreport); - } -+ */ // Paper - remove try catch - } - - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index 4bc26a7a4ae91aac90c256758ec8868d83027c0c..973aa060d6964c7d470bc7aff89b879daf1df153 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -45,7 +45,7 @@ public class ChunkSection { - } - - public Fluid b(int i, int j, int k) { -- return ((IBlockData) this.blockIds.a(i, j, k)).getFluid(); -+ return ((IBlockData) this.blockIds.a(i, j, k)).getFluid(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid. - } - - public void a() { diff --git a/Unmapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch b/Unmapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch deleted file mode 100644 index 22f8ddc9bd..0000000000 --- a/Unmapped-Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch +++ /dev/null @@ -1,1267 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 14 Feb 2020 01:24:39 -0800 -Subject: [PATCH] Optimise TickListServer by rewriting it - -In my profiling TickListServer showed up as -~10% for saving chunks and ~5% for the scheduling -of items on a server with ~90 players at -view distance = 5. Most of the performance -loss is unneccessary. - -TickListServer has numerous performance issues: - 1. Handling scheduled items is O(nlogn) - 2. Getting scheduled items for a chunk is O(n), - with n being the the number of scheduled items - for all chunks (hits saving very hard) - 3. Checking if an item is scheduled for the current tick is O(n), - with n being the number of items scheduled for current tick - 4. Items not in ticking chunks are churned in the scheduler - -The biggest issues are 4 & 2. - -We solve 1 by splitting up scheduled items into short and long scheduled, -where we expect the vast majority of our entries to be in the short scheduled -set. Handling short scheduled items is O(n) due to how the comparison -process is reduced to mapping. See TickListServerInterval. However, -this isn't memory-efficient - which is why long scheduled exists. -Long scheduled is handled the same as TickListServer. - -2 is solved by mapping what entries are in what chunks. - -3 is solved by mapping what blocks have what scheduled for them. - -4 is solved by moving the items that are not in ticking chunks -into a map of entries for that chunk. Once the chunk is moved -to ticking, the items are re-scheduled. - -This patch has also added two flags to debug excessive tick delays: --Dpaper.ticklist-warn-on-excessive-delay=true (false by default) -and -Dpaper.ticklist-excessive-delay-threshold=ticks which -sets the excessive tick delay to the specified ticks (defaults to -60 * 20 ticks, aka 60 seconds) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 8bf4d2b8c38c02d6a5b2fea37113689a252f1571..da93d38fe63035e4ff198ada84a4431f52d97c01 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -354,6 +354,13 @@ public class PaperConfig { - maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); - } - -+ public static boolean useOptimizedTickList = true; -+ private static void useOptimizedTickList() { -+ if (config.contains("settings.use-optimized-ticklist")) { // don't add default, hopefully temporary config -+ useOptimizedTickList = config.getBoolean("settings.use-optimized-ticklist"); -+ } -+ } -+ - public static boolean asyncChunks = false; - private static void asyncChunks() { - ConfigurationSection section; -diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8918bad880d6eeed30db39b6326b2f65e24edf45 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java -@@ -0,0 +1,628 @@ -+package com.destroystokyo.paper.server.ticklist; -+ -+import java.util.function.Function; -+import net.minecraft.CrashReport; -+import net.minecraft.CrashReportSystemDetails; -+import net.minecraft.ReportedException; -+import net.minecraft.core.BlockPosition; -+import net.minecraft.nbt.NBTTagList; -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; -+import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; -+import java.util.ArrayDeque; -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.Comparator; -+import java.util.Iterator; -+import java.util.List; -+import java.util.function.Consumer; -+import java.util.function.Predicate; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.NextTickListEntry; -+import net.minecraft.world.level.TickListPriority; -+import net.minecraft.world.level.TickListServer; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; -+ -+public final class PaperTickList extends TickListServer { // extend to avoid breaking ABI -+ -+ // in the order the state is expected to change (mostly) -+ public static final int STATE_UNSCHEDULED = 1 << 0; -+ public static final int STATE_SCHEDULED = 1 << 1; // scheduled for some tick -+ public static final int STATE_PENDING_TICK = 1 << 2; // for this tick -+ public static final int STATE_TICKING = 1 << 3; -+ public static final int STATE_TICKED = 1 << 4; // after this, it gets thrown back to unscheduled -+ public static final int STATE_CANCELLED_TICK = 1 << 5; // still gets moved to unscheduled after tick -+ -+ private static final int SHORT_SCHEDULE_TICK_THRESHOLD = 20 * 20 + 1; // 20 seconds -+ -+ private final WorldServer world; -+ private final Predicate excludeFromScheduling; -+ private final Function getMinecraftKeyFrom; -+ //private final Function getObjectFronMinecraftKey; -+ private final Consumer> tickFunction; -+ -+ private final co.aikar.timings.Timing timingCleanup; // Paper -+ private final co.aikar.timings.Timing timingTicking; // Paper -+ private final co.aikar.timings.Timing timingFinished; -+ -+ // note: remove ops / add ops suck on fastutil, a chained hashtable implementation would work better, but Long... -+ // try to alleviate with a very small load factor -+ private final Long2ObjectOpenHashMap>> entriesByBlock = new Long2ObjectOpenHashMap<>(1024, 0.25f); -+ private final Long2ObjectOpenHashMap>> entriesByChunk = new Long2ObjectOpenHashMap<>(1024, 0.25f); -+ private final Long2ObjectOpenHashMap>> pendingChunkTickLoad = new Long2ObjectOpenHashMap<>(1024, 0.5f); -+ -+ // fastutil has O(1) first/last while TreeMap/TreeSet are log(n) -+ private final ObjectRBTreeSet> longScheduled = new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); -+ -+ private final ArrayDeque> toTickThisTick = new ArrayDeque<>(); -+ -+ private final TickListServerInterval[] shortScheduled = new TickListServerInterval[SHORT_SCHEDULE_TICK_THRESHOLD]; -+ { -+ for (int i = 0, len = this.shortScheduled.length; i < len; ++i) { -+ this.shortScheduled[i] = new TickListServerInterval<>(); -+ } -+ } -+ private int shortScheduledIndex; -+ -+ private long currentTick; -+ -+ private static final boolean WARN_ON_EXCESSIVE_DELAY = Boolean.getBoolean("paper.ticklist-warn-on-excessive-delay"); -+ private static final long EXCESSIVE_DELAY_THRESHOLD = Long.getLong("paper.ticklist-excessive-delay-threshold", 60 * 20).longValue(); // 1 min dfl -+ -+ // assume index < length -+ private static int getWrappedIndex(final int start, final int length, final int index) { -+ final int next = start + index; -+ return next < length ? next : next - length; -+ } -+ -+ private static int getNextIndex(final int curr, final int length) { -+ final int next = curr + 1; -+ return next < length ? next : 0; -+ } -+ -+ public PaperTickList(final WorldServer world, final Predicate excludeFromScheduling, final Function getMinecraftKeyFrom, -+ final Consumer> tickFunction, final String timingsType) { -+ super(world, excludeFromScheduling, getMinecraftKeyFrom, tickFunction, timingsType); -+ this.world = world; -+ this.excludeFromScheduling = excludeFromScheduling; -+ this.getMinecraftKeyFrom = getMinecraftKeyFrom; -+ this.tickFunction = tickFunction; -+ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Cleanup"); // Paper -+ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Ticking"); // Paper -+ this.timingFinished = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Finish"); -+ this.currentTick = this.world.getTime(); -+ } -+ -+ private void queueEntryForTick(final NextTickListEntry entry, final ChunkProviderServer chunkProvider) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ if (chunkProvider.isTickingReadyMainThread(entry.getPosition())) { -+ this.toTickThisTick.add(entry); -+ entry.tickState = STATE_PENDING_TICK; -+ } else { -+ // we dump them to a map to avoid constantly re-scheduling them -+ this.addToNotTickingReady(entry); -+ } -+ } -+ } -+ -+ private void addToNotTickingReady(final NextTickListEntry entry) { -+ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (long keyInMap) -> { -+ return new ArrayList<>(); -+ }).add(entry); -+ } -+ -+ private void addToSchedule(final NextTickListEntry entry) { -+ long delay = entry.getTargetTick() - (this.currentTick + 1); -+ if (delay < SHORT_SCHEDULE_TICK_THRESHOLD) { -+ if (delay < 0) { -+ // longScheduled orders by tick time, short scheduled does not -+ this.longScheduled.add(entry); -+ } else { -+ this.shortScheduled[getWrappedIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD, (int)delay)].addEntryLast(entry); -+ } -+ } else { -+ this.longScheduled.add(entry); -+ } -+ } -+ -+ private void removeEntry(final NextTickListEntry entry) { -+ entry.tickState = STATE_CANCELLED_TICK; -+ // short/long scheduled will skip the entry -+ -+ final BlockPosition pos = entry.getPosition(); -+ final long blockKey = MCUtil.getBlockKey(pos); -+ -+ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); -+ -+ if (currentEntries.size() == 1) { -+ // it should contain our entry -+ this.entriesByBlock.remove(blockKey); -+ } else { -+ // it's more likely that this entry is at the start of the list than the end -+ for (int i = 0, len = currentEntries.size(); i < len; ++i) { -+ final NextTickListEntry currentEntry = currentEntries.get(i); -+ if (currentEntry == entry) { -+ currentEntries.remove(i); -+ break; -+ } -+ } -+ } -+ -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); -+ -+ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); -+ -+ set.remove(entry); -+ -+ if (set.isEmpty()) { -+ this.entriesByChunk.remove(chunkKey); -+ } -+ -+ ArrayList> pendingTickingLoad = this.pendingChunkTickLoad.get(chunkKey); -+ -+ if (pendingTickingLoad != null) { -+ for (int i = 0, len = pendingTickingLoad.size(); i < len; ++i) { -+ if (pendingTickingLoad.get(i) == entry) { -+ pendingTickingLoad.remove(i); -+ break; -+ } -+ } -+ -+ if (pendingTickingLoad.isEmpty()) { -+ this.pendingChunkTickLoad.remove(chunkKey); -+ } -+ } -+ -+ long delay = entry.getTargetTick() - (this.currentTick + 1); -+ if (delay >= SHORT_SCHEDULE_TICK_THRESHOLD) { -+ this.longScheduled.remove(entry); -+ } -+ } -+ -+ public void onChunkSetTicking(final int chunkX, final int chunkZ) { -+ final ArrayList> pending = this.pendingChunkTickLoad.remove(MCUtil.getCoordinateKey(chunkX, chunkZ)); -+ if (pending == null) { -+ return; -+ } -+ -+ for (int i = 0, size = pending.size(); i < size; ++i) { -+ final NextTickListEntry entry = pending.get(i); -+ // already in all the relevant reference maps, just need to add to longScheduled or shortScheduled -+ this.addToSchedule(entry); -+ } -+ } -+ -+ private void prepare() { -+ final long currentTick = this.currentTick; -+ -+ final ChunkProviderServer chunkProvider = this.world.getChunkProvider(); -+ -+ // here we setup what's going to tick -+ -+ // we don't remove items from shortScheduled (but do from longScheduled) because they're cleared at the end of -+ // this tick -+ if (this.longScheduled.isEmpty() || this.longScheduled.first().getTargetTick() > currentTick) { -+ // nothing in longScheduled to worry about -+ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; -+ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { -+ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { -+ this.queueEntryForTick(iterator.next(), chunkProvider); -+ } -+ } -+ } else { -+ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; -+ -+ // combine interval and longScheduled, keeping order -+ final Comparator> comparator = (Comparator)TickListServerInterval.ENTRY_COMPARATOR; -+ final Iterator> longScheduledIterator = this.longScheduled.iterator(); -+ NextTickListEntry longCurrent = longScheduledIterator.next(); -+ -+ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { -+ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { -+ final NextTickListEntry shortCurrent = iterator.next(); -+ if (longCurrent != null) { -+ // drain longCurrent until we can add shortCurrent -+ while (comparator.compare(longCurrent, shortCurrent) <= 0) { -+ this.queueEntryForTick(longCurrent, chunkProvider); -+ longScheduledIterator.remove(); -+ if (longScheduledIterator.hasNext()) { -+ longCurrent = longScheduledIterator.next(); -+ if (longCurrent.getTargetTick() > currentTick) { -+ longCurrent = null; -+ break; -+ } -+ } else { -+ longCurrent = null; -+ break; -+ } -+ } -+ } -+ this.queueEntryForTick(shortCurrent, chunkProvider); -+ } -+ } -+ -+ // add remaining from long scheduled -+ for (;;) { -+ if (longCurrent == null || longCurrent.getTargetTick() > currentTick) { -+ break; -+ } -+ longScheduledIterator.remove(); -+ this.queueEntryForTick(longCurrent, chunkProvider); -+ -+ if (longScheduledIterator.hasNext()) { -+ longCurrent = longScheduledIterator.next(); -+ } else { -+ break; -+ } -+ } -+ } -+ } -+ -+ private boolean warnedAboutDesync; -+ -+ @Override -+ public void nextTick() { -+ ++this.currentTick; -+ if (this.currentTick != this.world.getTime()) { -+ if (!this.warnedAboutDesync) { -+ this.warnedAboutDesync = true; -+ MinecraftServer.LOGGER.error("World tick desync detected! Expected " + this.currentTick + " ticks, but got " + this.world.getTime() + " ticks for world '" + this.world.getWorld().getName() + "'", new Throwable()); -+ MinecraftServer.LOGGER.error("Preventing redstone from breaking by refusing to accept new tick time"); -+ } -+ } -+ } -+ -+ @Override -+ public void tick() { -+ final ChunkProviderServer chunkProvider = this.world.getChunkProvider(); -+ -+ this.world.getMethodProfiler().enter("cleaning"); -+ this.timingCleanup.startTiming(); -+ -+ this.prepare(); -+ -+ // this must be done here in case something schedules in the tick code -+ this.shortScheduled[this.shortScheduledIndex].clear(); -+ this.shortScheduledIndex = getNextIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD); -+ -+ this.timingCleanup.stopTiming(); -+ this.world.getMethodProfiler().exitEnter("ticking"); -+ this.timingTicking.startTiming(); -+ -+ for (final NextTickListEntry toTick : this.toTickThisTick) { -+ if (toTick.tickState != STATE_PENDING_TICK) { -+ // onTickEnd gets called at end of tick -+ continue; -+ } -+ try { -+ if (chunkProvider.isTickingReadyMainThread(toTick.getPosition())) { -+ toTick.tickState = STATE_TICKING; -+ this.tickFunction.accept(toTick); -+ if (toTick.tickState == STATE_TICKING) { -+ toTick.tickState = STATE_TICKED; -+ } // else it's STATE_CANCELLED_TICK -+ } else { -+ // re-schedule eventually -+ toTick.tickState = STATE_SCHEDULED; -+ this.addToNotTickingReady(toTick); -+ } -+ } catch (final Throwable thr) { -+ // start copy from TickListServer // TODO check on update -+ CrashReport crashreport = CrashReport.a(thr, "Exception while ticking"); -+ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being ticked"); -+ -+ CrashReportSystemDetails.a(crashreportsystemdetails, toTick.getPosition(), (IBlockData) null); -+ throw new ReportedException(crashreport); -+ // end copy from TickListServer -+ } -+ } -+ -+ this.timingTicking.stopTiming(); -+ this.world.getMethodProfiler().exit(); -+ this.timingFinished.startTiming(); -+ -+ // finished ticking, actual cleanup time -+ for (int i = 0, len = this.toTickThisTick.size(); i < len; ++i) { -+ final NextTickListEntry entry = this.toTickThisTick.poll(); -+ if (entry.tickState != STATE_SCHEDULED) { -+ // some entries get re-scheduled due to their chunk not being loaded/at correct status, so do not -+ // call onTickEnd for them -+ this.onTickEnd(entry); -+ } -+ } -+ -+ this.timingFinished.stopTiming(); -+ } -+ -+ private void onTickEnd(final NextTickListEntry entry) { -+ if (entry.tickState == STATE_CANCELLED_TICK) { -+ return; -+ } -+ entry.tickState = STATE_UNSCHEDULED; -+ -+ final BlockPosition pos = entry.getPosition(); -+ final long blockKey = MCUtil.getBlockKey(pos); -+ -+ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); -+ -+ if (currentEntries.size() == 1) { -+ // it should contain our entry -+ this.entriesByBlock.remove(blockKey); -+ } else { -+ // it's more likely that this entry is at the start of the list than the end -+ for (int i = 0, len = currentEntries.size(); i < len; ++i) { -+ final NextTickListEntry currentEntry = currentEntries.get(i); -+ if (currentEntry == entry) { -+ currentEntries.remove(i); -+ break; -+ } -+ } -+ } -+ -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); -+ -+ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); -+ -+ set.remove(entry); -+ -+ if (set.isEmpty()) { -+ this.entriesByChunk.remove(chunkKey); -+ } -+ -+ // already removed from longScheduled or shortScheduled -+ } -+ -+ @Override -+ public boolean isPendingTickThisTick(final BlockPosition blockposition, final T data) { -+ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); -+ -+ if (entries == null) { -+ return false; -+ } -+ -+ for (int i = 0, size = entries.size(); i < size; ++i) { -+ final NextTickListEntry entry = entries.get(i); -+ if (entry.getData() == data && entry.tickState == STATE_PENDING_TICK) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ @Override -+ public boolean isScheduledForTick(final BlockPosition blockposition, final T data) { -+ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); -+ -+ if (entries == null) { -+ return false; -+ } -+ -+ for (int i = 0, size = entries.size(); i < size; ++i) { -+ final NextTickListEntry entry = entries.get(i); -+ if (entry.getData() == data && entry.tickState == STATE_SCHEDULED) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ @Override -+ public void schedule(BlockPosition blockPosition, T t, int i, TickListPriority tickListPriority) { -+ this.schedule(blockPosition, t, i + this.currentTick, tickListPriority); -+ } -+ -+ public void schedule(final NextTickListEntry entry) { -+ this.schedule(entry.getPosition(), entry.getData(), entry.getTargetTick(), entry.getPriority()); -+ } -+ -+ public void schedule(final BlockPosition pos, final T data, final long targetTick, final TickListPriority priority) { -+ final NextTickListEntry entry = new NextTickListEntry<>(pos, data, targetTick, priority); -+ if (this.excludeFromScheduling.test(entry.getData())) { -+ return; -+ } -+ -+ if (WARN_ON_EXCESSIVE_DELAY) { -+ final long delay = entry.getTargetTick() - this.currentTick; -+ if (delay >= EXCESSIVE_DELAY_THRESHOLD) { -+ MinecraftServer.LOGGER.warn("Entry " + entry.toString() + " has been scheduled with an excessive delay of: " + delay, new Throwable()); -+ } -+ } -+ -+ final long blockKey = MCUtil.getBlockKey(pos); -+ -+ final ArrayList> currentEntries = this.entriesByBlock.computeIfAbsent(blockKey, (long keyInMap) -> new ArrayList<>(3)); -+ -+ if (currentEntries.isEmpty()) { -+ currentEntries.add(entry); -+ } else { -+ for (int i = 0, size = currentEntries.size(); i < size; ++i) { -+ final NextTickListEntry currentEntry = currentEntries.get(i); -+ -+ // entries are only blocked from scheduling if currentEntry.equals(toSchedule) && currentEntry is scheduled to tick (NOT including pending) -+ if (currentEntry.getData() == entry.getData() && currentEntry.tickState == STATE_SCHEDULED) { -+ // can't add -+ return; -+ } -+ } -+ currentEntries.add(entry); -+ } -+ -+ entry.tickState = STATE_SCHEDULED; -+ -+ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (final long keyInMap) -> { -+ return new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); -+ }).add(entry); -+ -+ this.addToSchedule(entry); -+ } -+ -+ public void scheduleAll(final Iterator> iterator) { -+ while (iterator.hasNext()) { -+ this.schedule(iterator.next()); -+ } -+ } -+ -+ // this is not the standard interception calculation, but it's the one vanilla uses -+ // i.e the y value is ignored? the x, z calc isn't correct? -+ // however for the copy op they use the correct intersection, after using this one of course... -+ private static boolean isBlockInSortof(final StructureBoundingBox boundingBox, final BlockPosition pos) { -+ return pos.getX() >= boundingBox.getMinX() && pos.getX() < boundingBox.getMaxX() && pos.getZ() >= boundingBox.getMinZ() && pos.getZ() < boundingBox.getMaxZ(); -+ } -+ -+ @Override -+ public List> getEntriesInBoundingBox(final StructureBoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { -+ if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) { -+ return Collections.emptyList(); // vanilla behaviour, check isBlockInSortof above -+ } -+ -+ final int lowerChunkX = structureboundingbox.getMinX() >> 4; -+ final int upperChunkX = (structureboundingbox.getMaxX() - 1) >> 4; // subtract 1 since maxX is exclusive -+ final int lowerChunkZ = structureboundingbox.getMinZ() >> 4; -+ final int upperChunkZ = (structureboundingbox.getMaxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive -+ -+ final int xChunksLength = (upperChunkX - lowerChunkX + 1); -+ final int zChunksLength = (upperChunkZ - lowerChunkZ + 1); -+ -+ final ObjectRBTreeSet>[] containingChunks = new ObjectRBTreeSet[xChunksLength * zChunksLength]; -+ -+ final int offset = (xChunksLength * -lowerChunkZ - lowerChunkX); -+ int totalEntries = 0; -+ for (int currChunkX = lowerChunkX; currChunkX <= upperChunkX; ++currChunkX) { -+ for (int currChunkZ = lowerChunkZ; currChunkZ <= upperChunkZ; ++currChunkZ) { -+ // todo optimize -+ //final int index = (currChunkX - lowerChunkX) + xChunksLength * (currChunkZ - lowerChunkZ); -+ final int index = offset + currChunkX + xChunksLength * currChunkZ; -+ final ObjectRBTreeSet> set = containingChunks[index] = this.entriesByChunk.get(MCUtil.getCoordinateKey(currChunkX, currChunkZ)); -+ if (set != null) { -+ totalEntries += set.size(); -+ } -+ } -+ } -+ -+ final List> ret = new ArrayList<>(totalEntries); -+ -+ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); -+ -+ MCUtil.mergeSortedSets((NextTickListEntry entry) -> { -+ if (!isBlockInSortof(structureboundingbox, entry.getPosition())) { -+ return; -+ } -+ final int tickState = entry.tickState; -+ if ((tickState & matchOne) == 0) { -+ return; -+ } -+ -+ ret.add(entry); -+ return; -+ }, TickListServerInterval.ENTRY_COMPARATOR, containingChunks); -+ -+ if (removeReturned) { -+ for (NextTickListEntry entry : ret) { -+ this.removeEntry(entry); -+ } -+ } -+ -+ return ret; -+ } -+ -+ @Override -+ public void copy(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { -+ // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInBoundingBox(structureboundingbox, false, false); -+ Iterator> iterator = list.iterator(); -+ -+ while (iterator.hasNext()) { -+ NextTickListEntry nextticklistentry = iterator.next(); -+ -+ if (structureboundingbox.hasPoint( nextticklistentry.getPosition())) { -+ BlockPosition blockposition1 = nextticklistentry.getPosition().add(blockposition); -+ T t0 = nextticklistentry.getData(); -+ -+ this.schedule(new NextTickListEntry<>(blockposition1, t0, nextticklistentry.getTargetTick(), nextticklistentry.getPriority())); -+ } -+ } -+ // end copy from TickListServer -+ } -+ -+ @Override -+ public List> getEntriesInChunk(ChunkCoordIntPair chunkPos, boolean removeReturned, boolean excludeTicked) { -+ // Vanilla DOES get the entries 2 blocks out of the chunk too, but that doesn't matter since we ignore chunks -+ // not at ticking status, and ticking status requires neighbours loaded -+ // so with this method we will reduce scheduler churning -+ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); -+ -+ final ObjectRBTreeSet> entries = this.entriesByChunk.get(MCUtil.getCoordinateKey(chunkPos)); -+ -+ if (entries == null) { -+ return Collections.emptyList(); -+ } -+ -+ final List> ret = new ArrayList<>(entries.size()); -+ -+ for (NextTickListEntry entry : entries) { -+ if ((entry.tickState & matchOne) == 0) { -+ continue; -+ } -+ ret.add(entry); -+ } -+ -+ if (removeReturned) { -+ for (NextTickListEntry entry : ret) { -+ this.removeEntry(entry); -+ } -+ } -+ -+ return ret; -+ } -+ -+ @Override -+ public NBTTagList serialize(ChunkCoordIntPair chunkcoordintpair) { -+ // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInChunk(chunkcoordintpair, false, true); -+ -+ return TickListServer.serialize(this.getMinecraftKeyFrom, list, this.currentTick); -+ // end copy from TickListServer -+ } -+ -+ @Override -+ public int getTotalScheduledEntries() { -+ // good thing this is only used in debug reports // TODO check on update -+ int ret = 0; -+ -+ for (NextTickListEntry entry : this.longScheduled) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ ++ret; -+ } -+ } -+ -+ for (Iterator>>> iterator = this.pendingChunkTickLoad.long2ObjectEntrySet().iterator(); iterator.hasNext();) { -+ ArrayList> list = iterator.next().getValue(); -+ -+ for (NextTickListEntry entry : list) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ ++ret; -+ } -+ } -+ } -+ -+ for (TickListServerInterval interval : this.shortScheduled) { -+ for (Iterable> set : interval.byPriority) { -+ for (NextTickListEntry entry : set) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ ++ret; -+ } -+ } -+ } -+ } -+ -+ return ret; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b58432a8b60670562baf00cf5279c702aaad4557 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.server.ticklist; -+ -+import com.destroystokyo.paper.util.set.LinkedSortedSet; -+import java.util.Comparator; -+import net.minecraft.world.level.NextTickListEntry; -+import net.minecraft.world.level.TickListPriority; -+ -+// represents a set of entries to tick at a specified time -+public final class TickListServerInterval { -+ -+ public static final int TOTAL_PRIORITIES = TickListPriority.values().length; -+ public static final Comparator> ENTRY_COMPARATOR_BY_ID = (entry1, entry2) -> { -+ return Long.compare(entry1.getId(), entry2.getId()); -+ }; -+ public static final Comparator> ENTRY_COMPARATOR = (Comparator)NextTickListEntry.comparator(); -+ -+ // we do not record the interval, this class is meant to be used on a ring buffer -+ -+ // inlined enum map for TickListPriority -+ public final LinkedSortedSet>[] byPriority = new LinkedSortedSet[TOTAL_PRIORITIES]; -+ -+ { -+ for (int i = 0, len = this.byPriority.length; i < len; ++i) { -+ this.byPriority[i] = new LinkedSortedSet<>(ENTRY_COMPARATOR_BY_ID); -+ } -+ } -+ -+ public void addEntryLast(final NextTickListEntry entry) { -+ this.byPriority[entry.getPriority().ordinal()].addLast(entry); -+ } -+ -+ public void addEntryFirst(final NextTickListEntry entry) { -+ this.byPriority[entry.getPriority().ordinal()].addFirst(entry); -+ } -+ -+ public void clear() { -+ for (int i = 0, len = this.byPriority.length; i < len; ++i) { -+ this.byPriority[i].clear(); // O(1) clear -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..118988c39e58f28e8a2851792b9c014f341f06fc ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java -@@ -0,0 +1,142 @@ -+package com.destroystokyo.paper.util.set; -+ -+import java.util.Comparator; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+ -+public final class LinkedSortedSet implements Iterable { -+ -+ public final Comparator comparator; -+ -+ protected Link head; -+ protected Link tail; -+ -+ public LinkedSortedSet() { -+ this((Comparator)Comparator.naturalOrder()); -+ } -+ -+ public LinkedSortedSet(final Comparator comparator) { -+ this.comparator = comparator; -+ } -+ -+ public void clear() { -+ this.head = this.tail = null; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator() { -+ -+ Link next = LinkedSortedSet.this.head; -+ -+ @Override -+ public boolean hasNext() { -+ return this.next != null; -+ } -+ -+ @Override -+ public E next() { -+ final Link next = this.next; -+ if (next == null) { -+ throw new NoSuchElementException(); -+ } -+ this.next = next.next; -+ return next.element; -+ } -+ }; -+ } -+ -+ public boolean addLast(final E element) { -+ final Comparator comparator = this.comparator; -+ -+ Link curr = this.tail; -+ if (curr != null) { -+ int compare; -+ -+ while ((compare = comparator.compare(element, curr.element)) < 0) { -+ Link prev = curr; -+ curr = curr.prev; -+ if (curr != null) { -+ continue; -+ } -+ this.head = prev.prev = new Link<>(element, null, prev); -+ return true; -+ } -+ -+ if (compare != 0) { -+ // insert after curr -+ final Link next = curr.next; -+ final Link insert = new Link<>(element, curr, next); -+ curr.next = insert; -+ -+ if (next == null) { -+ this.tail = insert; -+ } else { -+ next.prev = insert; -+ } -+ return true; -+ } -+ -+ return false; -+ } else { -+ this.head = this.tail = new Link<>(element); -+ return true; -+ } -+ } -+ -+ public boolean addFirst(final E element) { -+ final Comparator comparator = this.comparator; -+ -+ Link curr = this.head; -+ if (curr != null) { -+ int compare; -+ -+ while ((compare = comparator.compare(element, curr.element)) > 0) { -+ Link prev = curr; -+ curr = curr.next; -+ if (curr != null) { -+ continue; -+ } -+ this.tail = prev.next = new Link<>(element, prev, null); -+ return true; -+ } -+ -+ if (compare != 0) { -+ // insert before curr -+ final Link prev = curr.prev; -+ final Link insert = new Link<>(element, prev, curr); -+ curr.prev = insert; -+ -+ if (prev == null) { -+ this.head = insert; -+ } else { -+ prev.next = insert; -+ } -+ return true; -+ } -+ -+ return false; -+ } else { -+ this.head = this.tail = new Link<>(element); -+ return true; -+ } -+ } -+ -+ protected static final class Link { -+ public E element; -+ public Link prev; -+ public Link next; -+ -+ public Link() {} -+ -+ public Link(final E element) { -+ this.element = element; -+ } -+ -+ public Link(final E element, final Link prev, final Link next) { -+ this.element = element; -+ this.prev = prev; -+ this.next = next; -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 8c0aeb51f5e230fd6109e750732eb54559bc9637..1fb931d4c0720a5e496030e25c865771aea3ec70 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -111,6 +111,7 @@ public class BlockPosition extends BaseBlockPosition { - return i == 0 && j == 0 && k == 0 ? this : new BlockPosition(this.getX() + i, this.getY() + j, this.getZ() + k); - } - -+ public final BlockPosition add(BaseBlockPosition baseblockposition) { return this.a(baseblockposition); } // Paper - OBFHELPER - public BlockPosition a(BaseBlockPosition baseblockposition) { - return this.b(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 5caf2121f2e551d7b4f0ddc74f10a44dc28ac62b..214098d7ad95839e90b0ec9ea997930c27b4bea4 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -21,6 +21,7 @@ import net.minecraft.SystemUtils; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.SectionPosition; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.progress.WorldLoadListener; - import net.minecraft.util.MathHelper; - import net.minecraft.util.profiling.GameProfilerFiller; -@@ -217,6 +218,13 @@ public class ChunkProviderServer extends IChunkProvider { - } - // Paper end - -+ // Paper start - rewrite ticklistserver -+ public final boolean isTickingReadyMainThread(BlockPosition pos) { -+ PlayerChunk chunk = this.playerChunkMap.getUpdatingChunk(MCUtil.getCoordinateKey(pos)); -+ return chunk != null && chunk.isTickingReady(); -+ } -+ // Paper end - rewrite ticklistserver -+ - public ChunkProviderServer(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, boolean flag, WorldLoadListener worldloadlistener, Supplier supplier) { - this.world = worldserver; - this.serverThreadQueue = new ChunkProviderServer.a(worldserver); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 6433463938d8bb717840c8f57fe6e7079e1030f2..445dba8ed210407664904b707c36c78a76f25510 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -496,7 +496,9 @@ public class PlayerChunk { - PlayerChunk.this.isTickingReady = true; - - -- -+ // Paper start - rewrite ticklistserver -+ PlayerChunk.this.chunkMap.world.onChunkSetTicking(PlayerChunk.this.location.x, PlayerChunk.this.location.z); -+ // Paper end - rewrite ticklistserver - - } - }); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 82f9c49233acce3c95d8a07b2a1b187d5c57552d..7fc75749e4983582275f794ed152af7cffce910f 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -298,6 +298,15 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - // Paper end - -+ // Paper start - rewrite ticklistserver -+ void onChunkSetTicking(int chunkX, int chunkZ) { -+ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { -+ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.nextTickListBlock).onChunkSetTicking(chunkX, chunkZ); -+ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.nextTickListFluid).onChunkSetTicking(chunkX, chunkZ); -+ } -+ } -+ // Paper end - rewrite ticklistserver -+ - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor -@@ -305,12 +314,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { - convertable = convertable_conversionsession; - uuid = WorldUUID.getUUID(convertable_conversionsession.folder.toFile()); - // CraftBukkit end -- this.nextTickListBlock = new TickListServer<>(this, (block) -> { -- return block == null || block.getBlockData().isAir(); -- }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings -- this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { -- return fluidtype == null || fluidtype == FluidTypes.EMPTY; -- }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings -+ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { -+ this.nextTickListBlock = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> { -+ return block == null || block.getBlockData().isAir(); -+ }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings -+ this.nextTickListFluid = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (fluidtype) -> { -+ return fluidtype == null || fluidtype == FluidTypes.EMPTY; -+ }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings -+ } else { -+ this.nextTickListBlock = new TickListServer<>(this, (block) -> { -+ return block == null || block.getBlockData().isAir(); -+ }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings -+ this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { -+ return fluidtype == null || fluidtype == FluidTypes.EMPTY; -+ }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings -+ } - this.navigators = Sets.newHashSet(); - this.L = new ObjectLinkedOpenHashSet(); - this.Q = flag1; -@@ -645,7 +663,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (this.Q) { - long i = this.worldData.getTime() + 1L; - -- this.worldDataServer.setTime(i); -+ this.worldDataServer.setTime(i); // Paper - diff on change, we want the below to be ran right after this -+ this.nextTickListBlock.nextTick(); // Paper -+ this.nextTickListFluid.nextTick(); // Paper - this.worldDataServer.u().a(this.server, i); - if (this.worldData.q().getBoolean(GameRules.DO_DAYLIGHT_CYCLE)) { - this.setDayTime(this.worldData.getDayTime() + 1L); -diff --git a/src/main/java/net/minecraft/world/level/NextTickListEntry.java b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -index 37b7dd82a227a88b720c13a813dd7e8caf803e03..8eb3084def3aa8776d32f8a3c942c95d24ccea3f 100644 ---- a/src/main/java/net/minecraft/world/level/NextTickListEntry.java -+++ b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -@@ -6,11 +6,13 @@ import net.minecraft.core.BlockPosition; - public class NextTickListEntry { - - private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading -- private final T e; -- public final BlockPosition a; -- public final long b; -- public final TickListPriority c; -- private final long f; -+ private final T e; public final T getData() { return this.e; } // Paper - OBFHELPER -+ public final BlockPosition a; public final BlockPosition getPosition() { return this.a; } // Paper - OBFHELPER -+ public final long b; public final long getTargetTick() { return this.b; } // Paper - OBFHELPER -+ public final TickListPriority c; public final TickListPriority getPriority() { return this.c; } // Paper - OBFHELPER -+ private final long f; public final long getId() { return this.f; } // Paper - OBFHELPER -+ private final int hash; // Paper -+ public int tickState; // Paper - - public NextTickListEntry(BlockPosition blockposition, T t0) { - this(blockposition, t0, 0L, TickListPriority.NORMAL); -@@ -22,6 +24,7 @@ public class NextTickListEntry { - this.e = t0; - this.b = i; - this.c = ticklistpriority; -+ this.hash = this.computeHash(); // Paper - } - - public boolean equals(Object object) { -@@ -34,19 +37,31 @@ public class NextTickListEntry { - } - } - -+ // Paper start - optimize hashcode -+ @Override - public int hashCode() { -+ return this.hash; -+ } -+ public final int computeHash() { -+ // Paper end - optimize hashcode - return this.a.hashCode(); - } - -- public static Comparator a() { // Paper - decompile fix -- return Comparator.comparingLong((nextticklistentry) -> { -- return ((NextTickListEntry) nextticklistentry).b; // Paper - decompile fix -- }).thenComparing((nextticklistentry) -> { -- return ((NextTickListEntry) nextticklistentry).c; // Paper - decompile fix -- }).thenComparingLong((nextticklistentry) -> { -- return ((NextTickListEntry) nextticklistentry).f; // Paper - decompile fix -- }); -+ // Paper start - let's not use more functional code for no reason. -+ public static Comparator comparator() { return NextTickListEntry.a(); } // Paper - OBFHELPER -+ public static Comparator a() { -+ return (Comparator)(Comparator)(NextTickListEntry nextticklistentry, NextTickListEntry nextticklistentry1) -> { -+ int i = Long.compare(nextticklistentry.getTargetTick(), nextticklistentry1.getTargetTick()); -+ -+ if (i != 0) { -+ return i; -+ } else { -+ i = nextticklistentry.getPriority().compareTo(nextticklistentry1.getPriority()); -+ return i != 0 ? i : Long.compare(nextticklistentry.getId(), nextticklistentry1.getId()); -+ } -+ }; - } -+ // Paper end - let's not use more functional code for no reason. - - public String toString() { - return this.e + ": " + this.a + ", " + this.b + ", " + this.c + ", " + this.f; -diff --git a/src/main/java/net/minecraft/world/level/TickListChunk.java b/src/main/java/net/minecraft/world/level/TickListChunk.java -index c3cb513d0d107ecb43e98960b25054626aa6a03f..fd293e11ec62a41a53c1e5238cb1219349d446d4 100644 ---- a/src/main/java/net/minecraft/world/level/TickListChunk.java -+++ b/src/main/java/net/minecraft/world/level/TickListChunk.java -@@ -9,6 +9,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MinecraftServer; - - public class TickListChunk implements TickList { - -@@ -61,6 +62,8 @@ public class TickListChunk implements TickList { - return nbttaglist; - } - -+ private static final int MAX_TICK_DELAY = Integer.getInteger("paper.ticklist-max-tick-delay", -1).intValue(); // Paper - clean up broken entries -+ - public static TickListChunk a(NBTTagList nbttaglist, Function function, Function function1) { - List> list = Lists.newArrayList(); - -@@ -71,7 +74,14 @@ public class TickListChunk implements TickList { - if (t0 != null) { - BlockPosition blockposition = new BlockPosition(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); - -- list.add(new TickListChunk.a<>(t0, blockposition, nbttagcompound.getInt("t"), TickListPriority.a(nbttagcompound.getInt("p")))); -+ // Paper start - clean up broken entries -+ int delay = nbttagcompound.getInt("t"); -+ if (MAX_TICK_DELAY > 0 && delay > MAX_TICK_DELAY) { -+ MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockposition + ", tick delay " + delay); -+ continue; -+ } -+ list.add(new TickListChunk.a<>(t0, blockposition, delay, TickListPriority.a(nbttagcompound.getInt("p")))); -+ // Paper end - clean up broken entries - } - } - -diff --git a/src/main/java/net/minecraft/world/level/TickListServer.java b/src/main/java/net/minecraft/world/level/TickListServer.java -index c221e5caf518b8c588390e438346fa58fa8c5a38..4fd89bbe6ce578fd3a166bcfbbe41908a7bb4753 100644 ---- a/src/main/java/net/minecraft/world/level/TickListServer.java -+++ b/src/main/java/net/minecraft/world/level/TickListServer.java -@@ -50,7 +50,16 @@ public class TickListServer implements TickList { - private final co.aikar.timings.Timing timingTicking; // Paper - // Paper end - -+ // Paper start -+ public void nextTick() {} -+ // Paper end -+ - public void b() { -+ // Paper start - allow overriding -+ this.tick(); -+ } -+ public void tick() { -+ // Paper end - int i = this.nextTickList.size(); - - if (false) { // CraftBukkit -@@ -118,10 +127,20 @@ public class TickListServer implements TickList { - - @Override - public boolean b(BlockPosition blockposition, T t0) { -+ // Paper start - allow overriding -+ return this.isPendingTickThisTick(blockposition, t0); -+ } -+ public boolean isPendingTickThisTick(BlockPosition blockposition, T t0) { -+ // Paper end - return this.f.contains(new NextTickListEntry<>(blockposition, t0)); - } - - public List> a(ChunkCoordIntPair chunkcoordintpair, boolean flag, boolean flag1) { -+ // Paper start - allow overriding -+ return this.getEntriesInChunk(chunkcoordintpair, flag, flag1); -+ } -+ public List> getEntriesInChunk(ChunkCoordIntPair chunkcoordintpair, boolean flag, boolean flag1) { -+ // Paper end - int i = (chunkcoordintpair.x << 4) - 2; - int j = i + 16 + 2; - int k = (chunkcoordintpair.z << 4) - 2; -@@ -131,6 +150,11 @@ public class TickListServer implements TickList { - } - - public List> a(StructureBoundingBox structureboundingbox, boolean flag, boolean flag1) { -+ // Paper start - allow overriding -+ return this.getEntriesInBoundingBox(structureboundingbox, flag, flag1); -+ } -+ public List> getEntriesInBoundingBox(StructureBoundingBox structureboundingbox, boolean flag, boolean flag1) { -+ // Paper end - List> list = this.a((List) null, this.nextTickList, structureboundingbox, flag); - - if (flag && list != null) { -@@ -170,6 +194,11 @@ public class TickListServer implements TickList { - } - - public void a(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { -+ // Paper start - allow overriding -+ this.copy(structureboundingbox, blockposition); -+ } -+ public void copy(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { -+ // Paper end - List> list = this.a(structureboundingbox, false, false); - Iterator iterator = list.iterator(); - -@@ -187,11 +216,17 @@ public class TickListServer implements TickList { - } - - public NBTTagList a(ChunkCoordIntPair chunkcoordintpair) { -+ // Paper start - allow overriding -+ return this.serialize(chunkcoordintpair); -+ } -+ public NBTTagList serialize(ChunkCoordIntPair chunkcoordintpair) { -+ // Paper end - List> list = this.a(chunkcoordintpair, false, true); - - return a(this.b, list, this.e.getTime()); - } - -+ public static NBTTagList serialize(Function function, Iterable> iterable, long i) { return TickListServer.a(function, iterable, i); } // Paper - OBFHELPER - private static NBTTagList a(Function function, Iterable> iterable, long i) { - NBTTagList nbttaglist = new NBTTagList(); - Iterator iterator = iterable.iterator(); -@@ -214,11 +249,21 @@ public class TickListServer implements TickList { - - @Override - public boolean a(BlockPosition blockposition, T t0) { -+ // Paper start - allow overriding -+ return this.isScheduledForTick(blockposition, t0); -+ } -+ public boolean isScheduledForTick(BlockPosition blockposition, T t0) { -+ // Paper end - return this.nextTickListHash.contains(new NextTickListEntry<>(blockposition, t0)); - } - - @Override - public void a(BlockPosition blockposition, T t0, int i, TickListPriority ticklistpriority) { -+ // Paper start - allow overriding -+ this.schedule(blockposition, t0, i, ticklistpriority); -+ } -+ public void schedule(BlockPosition blockposition, T t0, int i, TickListPriority ticklistpriority) { -+ // Paper end - if (!this.a.test(t0)) { - this.a(new NextTickListEntry<>(blockposition, t0, (long) i + this.e.getTime(), ticklistpriority)); - } -@@ -234,6 +279,11 @@ public class TickListServer implements TickList { - } - - public int a() { -+ // Paper start - allow overriding -+ return this.getTotalScheduledEntries(); -+ } -+ public int getTotalScheduledEntries() { -+ // Paper end - return this.nextTickListHash.size(); - } - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java -index b5d6c8163c686c31375fb645d7721af06c01df40..fb4b8d7167ad7f1d24d40bbbda5f52e278f25895 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java -@@ -8,12 +8,12 @@ import net.minecraft.nbt.NBTTagIntArray; - - public class StructureBoundingBox { - -- public int a; -- public int b; -- public int c; -- public int d; -- public int e; -- public int f; -+ public int a; public final int getMinX() { return this.a; } // Paper - OBFHELPER -+ public int b; public final int getMinY() { return this.b; } // Paper - OBFHELPER -+ public int c; public final int getMinZ() { return this.c; } // Paper - OBFHELPER -+ public int d; public final int getMaxX() { return this.d; } // Paper - OBFHELPER -+ public int e; public final int getMaxY() { return this.e; } // Paper - OBFHELPER -+ public int f; public final int getMaxZ() { return this.f; } // Paper - OBFHELPER - - public StructureBoundingBox() {} - -@@ -92,6 +92,7 @@ public class StructureBoundingBox { - this.e = 512; - } - -+ public final boolean intersects(StructureBoundingBox boundingBox) { return this.b(boundingBox); } // Paper - OBFHELPER - public boolean b(StructureBoundingBox structureboundingbox) { - return this.d >= structureboundingbox.a && this.a <= structureboundingbox.d && this.f >= structureboundingbox.c && this.c <= structureboundingbox.f && this.e >= structureboundingbox.b && this.b <= structureboundingbox.e; - } -@@ -126,6 +127,7 @@ public class StructureBoundingBox { - this.a(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } - -+ public final boolean hasPoint(BaseBlockPosition baseblockposition) { return this.b(baseblockposition); } // Paper - OBFHELPER - public boolean b(BaseBlockPosition baseblockposition) { - return baseblockposition.getX() >= this.a && baseblockposition.getX() <= this.d && baseblockposition.getZ() >= this.c && baseblockposition.getZ() <= this.f && baseblockposition.getY() >= this.b && baseblockposition.getY() <= this.e; - } diff --git a/Unmapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch b/Unmapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch deleted file mode 100644 index 6d6444c726..0000000000 --- a/Unmapped-Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sat, 1 Feb 2020 16:50:39 +0100 -Subject: [PATCH] Pillager patrol spawn settings and per player options - -This adds config options for defining the spawn chance, spawn delay and -spawn start day as well as toggles for handling the spawn delay and -start day per player. (Based on the time played statistic) -When not per player it will use the Vanilla mechanic of one delay per -world and the world age for the start day. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 525d702d78a609af987ebd2c32169b873e5c05ed..6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -582,10 +582,21 @@ public class PaperWorldConfig { - } - - public boolean disablePillagerPatrols = false; -+ public double patrolSpawnChance = 0.2; -+ public boolean patrolPerPlayerDelay = false; -+ public int patrolDelay = 12000; -+ public boolean patrolPerPlayerStart = false; -+ public int patrolStartDay = 5; - private void pillagerSettings() { - disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); -+ patrolSpawnChance = getDouble("game-mechanics.pillager-patrols.spawn-chance", patrolSpawnChance); -+ patrolPerPlayerDelay = getBoolean("game-mechanics.pillager-patrols.spawn-delay.per-player", patrolPerPlayerDelay); -+ patrolDelay = getInt("game-mechanics.pillager-patrols.spawn-delay.ticks", patrolDelay); -+ patrolPerPlayerStart = getBoolean("game-mechanics.pillager-patrols.start.per-player", patrolPerPlayerStart); -+ patrolStartDay = getInt("game-mechanics.pillager-patrols.start.day", patrolStartDay); - } - -+ - public boolean entitiesTargetWithFollowRange = false; - private void entitiesTargetWithFollowRange() { - entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index f5212a7ec0f2dd27fb1c06e0dfc37f2aff595fde..c0e32b13e79fa6b34ac9448d2f74339bb771274f 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -216,6 +216,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean viewingCredits; - private int containerUpdateDelay; // Paper - public long loginTime; // Paper -+ public int patrolSpawnDelay; // Paper - per player patrol spawns - // Paper start - cancellable death event - public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; -diff --git a/src/main/java/net/minecraft/stats/StatisticWrapper.java b/src/main/java/net/minecraft/stats/StatisticWrapper.java -index c1a694c4a773a41cdefca6b154711f7fc0a7fcaa..00d79ccf9c65acadc030ab1796cff4598392cb6a 100644 ---- a/src/main/java/net/minecraft/stats/StatisticWrapper.java -+++ b/src/main/java/net/minecraft/stats/StatisticWrapper.java -@@ -28,6 +28,7 @@ public class StatisticWrapper implements Iterable> { - return this.b.values().iterator(); - } - -+ public final Statistic get(T t) { return this.b(t); }; // Paper - OBFHELPER - public Statistic b(T t0) { - return this.a(t0, Counter.DEFAULT); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -index cba98adb7f2711fb97c7e4120d962f46a59682e7..111c4c1fad2f1839a8c6b7c277cf801236ae1685 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -@@ -3,7 +3,9 @@ package net.minecraft.world.level.levelgen; - import java.util.Random; - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; -+import net.minecraft.stats.StatisticList; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; - import net.minecraft.world.entity.GroupDataEntity; -@@ -20,13 +22,13 @@ import net.minecraft.world.level.block.state.IBlockData; - - public class MobSpawnerPatrol implements MobSpawner { - -- private int a; -+ private int a;private int getSpawnDelay() { return a; } private void setSpawnDelay(int spawnDelay) { this.a = spawnDelay; } // Paper - OBFHELPER - - public MobSpawnerPatrol() {} - - @Override - public int a(WorldServer worldserver, boolean flag, boolean flag1) { -- if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper -+ if (worldserver.paperConfig.disablePillagerPatrols || worldserver.paperConfig.patrolSpawnChance == 0) return 0; // Paper - if (!flag) { - return 0; - } else if (!worldserver.getGameRules().getBoolean(GameRules.DO_PATROL_SPAWNING)) { -@@ -34,23 +36,51 @@ public class MobSpawnerPatrol implements MobSpawner { - } else { - Random random = worldserver.random; - -- --this.a; -- if (this.a > 0) { -+ // Paper start - Patrol settings -+ // Random player selection moved up for per player spawning and configuration -+ int j = worldserver.getPlayers().size(); -+ if (j < 1) { - return 0; -+ } -+ -+ EntityPlayer entityhuman = worldserver.getPlayers().get(random.nextInt(j)); -+ if (entityhuman.isSpectator()) { -+ return 0; -+ } -+ -+ int patrolSpawnDelay; -+ if (worldserver.paperConfig.patrolPerPlayerDelay) { -+ --entityhuman.patrolSpawnDelay; -+ patrolSpawnDelay = entityhuman.patrolSpawnDelay; - } else { -- this.a += 12000 + random.nextInt(1200); -- long i = worldserver.getDayTime() / 24000L; -+ setSpawnDelay(getSpawnDelay() - 1); -+ patrolSpawnDelay = getSpawnDelay(); -+ } -+ -+ if (patrolSpawnDelay > 0) { -+ return 0; -+ } else { -+ long days; -+ if (worldserver.paperConfig.patrolPerPlayerStart) { -+ days = entityhuman.getStatisticManager().getStatisticValue(StatisticList.CUSTOM.get(StatisticList.PLAY_ONE_MINUTE)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang -+ } else { -+ days = worldserver.getDayTime() / 24000L; -+ } -+ if (worldserver.paperConfig.patrolPerPlayerDelay) { -+ entityhuman.patrolSpawnDelay += worldserver.paperConfig.patrolDelay + random.nextInt(1200); -+ } else { -+ setSpawnDelay(getSpawnDelay() + worldserver.paperConfig.patrolDelay + random.nextInt(1200)); -+ } - -- if (i >= 5L && worldserver.isDay()) { -- if (random.nextInt(5) != 0) { -+ if (days >= worldserver.paperConfig.patrolStartDay && worldserver.isDay()) { -+ if (random.nextDouble() >= worldserver.paperConfig.patrolSpawnChance) { -+ // Paper end - return 0; - } else { -- int j = worldserver.getPlayers().size(); - - if (j < 1) { - return 0; - } else { -- EntityHuman entityhuman = (EntityHuman) worldserver.getPlayers().get(random.nextInt(j)); - - if (entityhuman.isSpectator()) { - return 0; diff --git a/Unmapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch b/Unmapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch deleted file mode 100644 index cb8c24e677..0000000000 --- a/Unmapped-Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 29 Mar 2020 18:26:14 -0400 -Subject: [PATCH] Ensure Entity is never double registered - -If something calls register twice, and the world is ticking, it could be -enqueued to add twice. - -Vs behavior of non ticking of just overwriting state. - -We will now simply log a warning when this happens instead of crashing the server. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 7fc75749e4983582275f794ed152af7cffce910f..8f54534356408a17132578b8a39686651a97a0d5 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -649,6 +649,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - Entity entity2; - - while ((entity2 = (Entity) this.entitiesToAdd.poll()) != null) { -+ if (!entity2.isQueuedForRegister) continue; // Paper - ignore cancelled registers - this.registerEntity(entity2); - } - -@@ -1406,6 +1407,19 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - public void unregisterEntity(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot -+ // Paper start - fix entity registration issues -+ if (entity instanceof EntityComplexPart) { -+ // Usually this is a no-op for complex parts, and ID's should be removed, but go ahead and remove it anyways -+ // Dragon parts are handled special in register. they don't receive a valid = true or register by UUID etc. -+ this.entitiesById.remove(entity.getId(), entity); -+ return; -+ } -+ if (!entity.valid) { -+ // Someone called remove before we ever got added, cancel the add. -+ entity.isQueuedForRegister = false; -+ return; -+ } -+ // Paper end - // Spigot start - if ( entity instanceof EntityHuman ) - { -@@ -1472,9 +1486,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - private void registerEntity(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot -+ // Paper start - don't double enqueue entity registration -+ //noinspection ObjectEquality -+ if (this.entitiesById.get(entity.getId()) == entity) { -+ LOGGER.error(entity + " was already registered!"); -+ new Throwable().printStackTrace(); -+ return; -+ } -+ // Paper end - if (this.tickingEntities) { -- this.entitiesToAdd.add(entity); -+ if (!entity.isQueuedForRegister) { // Paper -+ this.entitiesToAdd.add(entity); -+ entity.isQueuedForRegister = true; // Paper -+ } - } else { -+ entity.isQueuedForRegister = false; // Paper - this.entitiesById.put(entity.getId(), entity); - if (entity instanceof EntityEnderDragon) { - EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity).eJ(); -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 334d60c71fa13841f9d04af5404cc25acbc0ec76..a9d8baef5db0655742e85482604db6f6208eb9b6 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -148,6 +148,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - // Paper start -+ public boolean isQueuedForRegister = false; - public static Random SHARED_RANDOM = new Random() { - private boolean locked = false; - @Override diff --git a/Unmapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch b/Unmapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch deleted file mode 100644 index eeeff7b0cc..0000000000 --- a/Unmapped-Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 Mar 2020 03:01:45 -0400 -Subject: [PATCH] Fix unregistering entities from unloading chunks - -CraftBukkit caused a regression here by making unloading chunks not -have a ticket added and returning unloaded future. - -This caused entities who were killed in same tick their chunk is unloading -to not be able to be removed from the chunk. - -This then results in dead entities lingering in the Chunk. - -Combine that with a buggy detail of the previous implementation of -the Dupe UUID patch, then this was the likely source of the "Ghost entities" - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 8f54534356408a17132578b8a39686651a97a0d5..2e45f9006eba3b52916d2fccf8f2bebe7b8b8a9c 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1565,9 +1565,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - private void removeEntityFromChunk(Entity entity) { -- IChunkAccess ichunkaccess = chunkProvider.getChunkUnchecked(entity.chunkX, entity.chunkZ); // CraftBukkit - SPIGOT-5228: getChunkAt won't find the entity's chunk if it has already been unloaded (i.e. if it switched to state INACCESSIBLE). -+ Chunk ichunkaccess = entity.getCurrentChunk(); // Paper - getChunkAt(x,z,full,false) is broken by CraftBukkit as it won't return an unloading chunk. Use our current chunk reference as this points to what chunk they need to be removed from anyways - -- if (ichunkaccess instanceof Chunk) { -+ if (ichunkaccess != null) { // Paper - ((Chunk) ichunkaccess).b(entity); - } - diff --git a/Unmapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/Unmapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch deleted file mode 100644 index f765b7f7b5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 Mar 2020 03:50:42 -0400 -Subject: [PATCH] Remote Connections shouldn't hold up shutdown - -Bugs in the connection logic appears to leave stale connections even, preventing shutdown - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 2d42b863b3fd83d1ee0532d1fcb63861641ec47b..557f80accfa36b495c9a8cffdab2e248c1cbb514 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -400,11 +400,11 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - } - - if (this.remoteControlListener != null) { -- this.remoteControlListener.b(); -+ //this.remoteControlListener.b(); // Paper - don't wait for remote connections - } - - if (this.remoteStatusListener != null) { -- this.remoteStatusListener.b(); -+ //this.remoteStatusListener.b(); // Paper - don't wait for remote connections - } - - System.exit(0); // CraftBukkit diff --git a/Unmapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/Unmapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch deleted file mode 100644 index 290489e398..0000000000 --- a/Unmapped-Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Tue, 17 Mar 2020 14:18:50 -0500 -Subject: [PATCH] Do not allow bees to load chunks for beehives - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -index 7ce8eaeb9af3547869f467910b6a458118c63c1f..1d1f71a995a99b2101891a7a5bda7bec5d67f118 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -@@ -358,6 +358,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - if (this.hivePos == null) { - return false; - } else { -+ if (!this.world.isLoadedAndInBounds(hivePos)) return false; // Paper - TileEntity tileentity = this.world.getTileEntity(this.hivePos); - - return tileentity instanceof TileEntityBeehive && ((TileEntityBeehive) tileentity).d(); -@@ -390,6 +391,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - } - - private boolean i(BlockPosition blockposition) { -+ if (!this.world.isLoadedAndInBounds(blockposition)) return false; // Paper - TileEntity tileentity = this.world.getTileEntity(blockposition); - - return tileentity instanceof TileEntityBeehive ? !((TileEntityBeehive) tileentity).isFull() : false; -@@ -632,6 +634,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - @Override - public boolean g() { - if (EntityBee.this.hasHivePos() && EntityBee.this.fd() && EntityBee.this.hivePos.a((IPosition) EntityBee.this.getPositionVector(), 2.0D)) { -+ if (!EntityBee.this.world.isLoadedAndInBounds(EntityBee.this.hivePos)) return false; // Paper - TileEntity tileentity = EntityBee.this.world.getTileEntity(EntityBee.this.hivePos); - - if (tileentity instanceof TileEntityBeehive) { -@@ -655,6 +658,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - - @Override - public void c() { -+ if (!EntityBee.this.world.isLoadedAndInBounds(EntityBee.this.hivePos)) return; // Paper - TileEntity tileentity = EntityBee.this.world.getTileEntity(EntityBee.this.hivePos); - - if (tileentity instanceof TileEntityBeehive) { diff --git a/Unmapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/Unmapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch deleted file mode 100644 index c003c40257..0000000000 --- a/Unmapped-Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 01:42:39 -0400 -Subject: [PATCH] Prevent Double PlayerChunkMap adds crashing server - -Suspected case would be around the technique used in .stopRiding -Stack will identify any causer of this and warn instead of crashing. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index baef98331c07b0f8c95351f39c5e471f96a59c05..c7619bba9115e8695b5aea2b4d059bea577e748e 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1503,6 +1503,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - protected void addEntity(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot -+ // Paper start - ignore and warn about illegal addEntity calls instead of crashing server -+ if (!entity.valid || entity.world != this.world || this.trackedEntities.containsKey(entity.getId())) { -+ new Throwable("[ERROR] Illegal PlayerChunkMap::addEntity for world " + this.world.getWorld().getName() -+ + ": " + entity + (this.trackedEntities.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : "")) -+ .printStackTrace(); -+ return; -+ } -+ // Paper end - if (!(entity instanceof EntityComplexPart)) { - EntityTypes entitytypes = entity.getEntityType(); - int i = entitytypes.getChunkRange() * 16; -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 2e45f9006eba3b52916d2fccf8f2bebe7b8b8a9c..35fc51ac93a62f6dc4b141dc94a3cda0399f0ce1 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1531,7 +1531,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - -- this.getChunkProvider().addEntity(entity); -+ // this.getChunkProvider().addEntity(entity); // Paper - moved down below valid=true - // CraftBukkit start - SPIGOT-5278 - if (entity instanceof EntityDrowned) { - this.navigators.add(((EntityDrowned) entity).navigationWater); -@@ -1542,6 +1542,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.navigators.add(((EntityInsentient) entity).getNavigation()); - } - entity.valid = true; // CraftBukkit -+ this.getChunkProvider().addEntity(entity); // Paper - from above to be below valid=true - // Paper start - Set origin location when the entity is being added to the world - if (entity.origin == null) { - entity.origin = entity.getBukkitEntity().getLocation(); diff --git a/Unmapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch b/Unmapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch deleted file mode 100644 index c69af5d666..0000000000 --- a/Unmapped-Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch +++ /dev/null @@ -1,161 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 02:37:57 -0400 -Subject: [PATCH] Optimize Collision to not load chunks - -The collision code takes an AABB and generates a cuboid of checks rather -than a cylinder, so at high velocity this can generate a lot of chunk checks. - -Treat an unloaded chunk as a collision for entities, and also for players if -the "prevent moving into unloaded chunks" setting is enabled. - -If that serting is not enabled, collisions will be ignored for players, since -movement will load only the chunk the player enters anyways and avoids loading -massive amounts of surrounding chunks due to large AABB lookups. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 9af1d81475d2def60a682ed23e88f1afbbc4c7e6..0a99ee6221c46043ecdf9e9df7a064aa63ee6951 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -61,6 +61,7 @@ import net.minecraft.server.ScoreboardServer; - import net.minecraft.server.level.DemoPlayerInteractManager; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerInteractManager; -+import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; - import net.minecraft.server.network.PlayerConnection; - import net.minecraft.sounds.SoundCategory; -@@ -74,6 +75,7 @@ import net.minecraft.world.effect.MobEffect; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.player.EntityHuman; -+import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.World; -@@ -809,6 +811,7 @@ public abstract class PlayerList { - entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - // CraftBukkit end - -+ worldserver1.getChunkProvider().addTicket(TicketType.POST_TELEPORT, new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper - while (avoidSuffocation && !worldserver1.getCubes(entityplayer1) && entityplayer1.locY() < 256.0D) { - entityplayer1.setPosition(entityplayer1.locX(), entityplayer1.locY() + 1.0D, entityplayer1.locZ()); - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a9d8baef5db0655742e85482604db6f6208eb9b6..6c368921f76fb6eb99dd20dd49d6ba5ac80cdfad 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -169,6 +169,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - private CraftEntity bukkitEntity; - - PlayerChunkMap.EntityTracker tracker; // Paper -+ public boolean collisionLoadChunks = false; // Paper - public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { -diff --git a/src/main/java/net/minecraft/world/level/ICollisionAccess.java b/src/main/java/net/minecraft/world/level/ICollisionAccess.java -index fcf6cc86e3b5d9afe3ab3b3fba2ec13846ed0b4c..fcb3e2f9dea97138e0fd4cd2eb11b54799e1d3b5 100644 ---- a/src/main/java/net/minecraft/world/level/ICollisionAccess.java -+++ b/src/main/java/net/minecraft/world/level/ICollisionAccess.java -@@ -54,7 +54,9 @@ public interface ICollisionAccess extends IBlockAccess { - } - - default boolean b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { -+ try { if (entity != null) entity.collisionLoadChunks = true; // Paper - return this.d(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty); -+ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper - } - - Stream c(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate); -diff --git a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -index fa3421c9cd8531618827627e9c524a8df77c4c58..d0cc8677f2be422722160fee9b71894b5ddd3186 100644 ---- a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -+++ b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -@@ -7,6 +7,9 @@ import java.util.function.Consumer; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.CursorPosition; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.RegionLimitedWorldAccess; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.block.Blocks; -@@ -21,13 +24,13 @@ import net.minecraft.world.phys.shapes.VoxelShapes; - public class VoxelShapeSpliterator extends AbstractSpliterator { - - @Nullable -- private final Entity a; -+ private final Entity a; final Entity getEntity() { return this.a; } // Paper - OBFHELPER - private final AxisAlignedBB b; - private final VoxelShapeCollision c; - private final CursorPosition d; -- private final BlockPosition.MutableBlockPosition e; -+ private final BlockPosition.MutableBlockPosition e; final BlockPosition.MutableBlockPosition getMutablePos() { return this.e; } // Paper - OBFHELPER - private final VoxelShape f; -- private final ICollisionAccess g; -+ private final ICollisionAccess g; final ICollisionAccess getCollisionAccess() { return this.g; } // Paper - OBFHELPER - private boolean h; - private final BiPredicate i; - -@@ -64,23 +67,37 @@ public class VoxelShapeSpliterator extends AbstractSpliterator { - boolean a(Consumer consumer) { - while (true) { - if (this.d.a()) { -- int i = this.d.b(); -- int j = this.d.c(); -- int k = this.d.d(); -+ int i = this.d.b(); final int x = i; -+ int j = this.d.c(); final int y = j; -+ int k = this.d.d(); final int z = k; - int l = this.d.e(); - - if (l == 3) { - continue; - } - -- IBlockAccess iblockaccess = this.a(i, k); -- -- if (iblockaccess == null) { -+ // Paper start - ensure we don't load chunks -+ Entity entity = this.getEntity(); -+ BlockPosition.MutableBlockPosition blockposition_mutableblockposition = this.getMutablePos(); -+ boolean far = entity != null && MCUtil.distanceSq(entity.locX(), y, entity.locZ(), x, y, z) > 14; -+ blockposition_mutableblockposition.setValues(x, y, z); -+ -+ boolean isRegionLimited = this.getCollisionAccess() instanceof RegionLimitedWorldAccess; -+ IBlockData iblockdata = isRegionLimited ? Blocks.VOID_AIR.getBlockData() : ((!far && entity instanceof EntityPlayer) || (entity != null && entity.collisionLoadChunks) -+ ? this.getCollisionAccess().getType(blockposition_mutableblockposition) -+ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition) -+ ); -+ -+ if (iblockdata == null) { -+ if (!(entity instanceof EntityPlayer) || entity.world.paperConfig.preventMovingIntoUnloadedChunks) { -+ VoxelShape voxelshape3 = VoxelShapes.of(far ? entity.getBoundingBox() : new AxisAlignedBB(new BlockPosition(x, y, z))); -+ consumer.accept(voxelshape3); -+ return true; -+ } - continue; - } -- -- this.e.d(i, j, k); -- IBlockData iblockdata = iblockaccess.getType(this.e); -+ // Paper - moved up -+ // Paper end - - if (!this.i.test(iblockdata, this.e) || l == 1 && !iblockdata.d() || l == 2 && !iblockdata.a(Blocks.MOVING_PISTON)) { - continue; -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index cf32a4f63e8e59535c02a3f9c57f98833a2b0e83..24ecac40625629b0bbe460e7fc984b147ede1f1f 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -249,7 +249,8 @@ public final class VoxelShapes { - - if (k2 < 3) { - blockposition_mutableblockposition.a(enumaxiscycle1, i2, j2, l1); -- IBlockData iblockdata = iworldreader.getType(blockposition_mutableblockposition); -+ IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition_mutableblockposition); // Paper -+ if (iblockdata == null) return 0.0D; // Paper - - if ((k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) { - d0 = iblockdata.b((IBlockAccess) iworldreader, blockposition_mutableblockposition, voxelshapecollision).a(enumdirection_enumaxis2, axisalignedbb.d((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), d0); diff --git a/Unmapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch b/Unmapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch deleted file mode 100644 index 9b85066c21..0000000000 --- a/Unmapped-Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 17:16:48 -0400 -Subject: [PATCH] Don't tick dead players - -Causes sync chunk loads and who knows what all else. -This is safe because Spectators are skipped in unloaded chunks too in vanilla. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index c0e32b13e79fa6b34ac9448d2f74339bb771274f..e3721287cc18c8df81d1353084364966eb3f55ab 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -609,7 +609,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - public void playerTick() { - try { -- if (!this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { -+ if (valid && !this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) - super.tick(); - } - diff --git a/Unmapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch b/Unmapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch deleted file mode 100644 index 04592576bc..0000000000 --- a/Unmapped-Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 19:31:16 -0400 -Subject: [PATCH] Dead Player's shouldn't be able to move - -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/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 564dfa98c166fde509044e6e1938efb321ece53d..8981dfacd10cae9de052e1b36ce5181cd0e6752d 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1049,7 +1049,7 @@ public abstract class EntityHuman extends EntityLiving { - - @Override - protected boolean isFrozen() { -- return super.isFrozen() || this.isSleeping(); -+ return super.isFrozen() || this.isSleeping() || dead || !valid; // Paper - player's who are dead or not in a world shouldn't move... - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/Unmapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch deleted file mode 100644 index a3d311fb6f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch +++ /dev/null @@ -1,294 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 8 Apr 2020 03:06:30 -0400 -Subject: [PATCH] Optimize PlayerChunkMap memory use for visibleChunks - -No longer clones visible chunks which is causing massive memory -allocation issues, likely the source of Humongous Objects on large servers. - -Instead we just synchronize, clear and rebuild, reusing the same object buffers -as before with only 2 small objects created (FastIterator/MapEntry) - -This should result in siginificant memory use reduction and improved GC behavior. - -diff --git a/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f6ff4d8132a95895680f5bc81f8f873e78f0bbdb ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java -@@ -0,0 +1,39 @@ -+package com.destroystokyo.paper.util.map; -+ -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+ -+public class Long2ObjectLinkedOpenHashMapFastCopy extends Long2ObjectLinkedOpenHashMap { -+ -+ public void copyFrom(Long2ObjectLinkedOpenHashMapFastCopy map) { -+ if (key.length != map.key.length) { -+ key = null; -+ key = new long[map.key.length]; -+ } -+ if (value.length != map.value.length) { -+ value = null; -+ //noinspection unchecked -+ value = (V[]) new Object[map.value.length]; -+ } -+ if (link.length != map.link.length) { -+ link = null; -+ link = new long[map.link.length]; -+ } -+ System.arraycopy(map.key, 0, this.key, 0, map.key.length); -+ System.arraycopy(map.value, 0, this.value, 0, map.value.length); -+ System.arraycopy(map.link, 0, this.link, 0, map.link.length); -+ this.size = map.size; -+ this.mask = map.mask; -+ this.first = map.first; -+ this.last = map.last; -+ this.n = map.n; -+ this.maxFill = map.maxFill; -+ this.containsNullKey = map.containsNullKey; -+ } -+ -+ @Override -+ public Long2ObjectLinkedOpenHashMapFastCopy clone() { -+ Long2ObjectLinkedOpenHashMapFastCopy clone = (Long2ObjectLinkedOpenHashMapFastCopy) super.clone(); -+ clone.copyFrom(this); -+ return clone; -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 5a410550cfb48505c9de9979465ed1528c8fbf05..9edbde8299bcd127e1727d34ed441f638e716b2a 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -616,7 +616,7 @@ public final class MCUtil { - - WorldServer world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); - PlayerChunkMap chunkMap = world.getChunkProvider().playerChunkMap; -- Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunks; -+ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.getVisibleChunks(); - ChunkMapDistance chunkMapDistance = chunkMap.chunkDistanceManager; - List allChunks = new ArrayList<>(visibleChunks.values()); - List players = world.players; -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 214098d7ad95839e90b0ec9ea997930c27b4bea4..13ac946487bb05b5c47ee8ee10cb6ed1c992c0e2 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -781,7 +781,7 @@ public class ChunkProviderServer extends IChunkProvider { - }; - // Paper end - this.world.timings.chunkTicks.startTiming(); // Paper -- this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... -+ this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - - if (optional.isPresent()) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index c7619bba9115e8695b5aea2b4d059bea577e748e..5ccc70f36616e1bd8cdb8b23315f7422ec5acc61 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -106,8 +106,33 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - private static final Logger LOGGER = LogManager.getLogger(); - public static final int GOLDEN_TICKET = 33 + ChunkStatus.b(); -- public final Long2ObjectLinkedOpenHashMap updatingChunks = new Long2ObjectLinkedOpenHashMap(); -- public volatile Long2ObjectLinkedOpenHashMap visibleChunks; -+ // Paper start - faster copying -+ public final Long2ObjectLinkedOpenHashMap updatingChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<>(); // Paper - faster copying -+ public final Long2ObjectLinkedOpenHashMap visibleChunks = new ProtectedVisibleChunksMap(); // Paper - faster copying -+ -+ private class ProtectedVisibleChunksMap extends com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy { -+ @Override -+ public PlayerChunk put(long k, PlayerChunk playerChunk) { -+ throw new UnsupportedOperationException("Updating visible Chunks"); -+ } -+ -+ @Override -+ public PlayerChunk remove(long k) { -+ throw new UnsupportedOperationException("Removing visible Chunks"); -+ } -+ -+ @Override -+ public PlayerChunk get(long k) { -+ return PlayerChunkMap.this.getVisibleChunk(k); -+ } -+ -+ public PlayerChunk safeGet(long k) { -+ return super.get(k); -+ } -+ } -+ // Paper end -+ public final com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy pendingVisibleChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy(); // Paper - this is used if the visible chunks is updated while iterating only -+ public transient com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy visibleChunksClone; // Paper - used for async access of visible chunks, clone and cache only when needed - private final Long2ObjectLinkedOpenHashMap pendingUnload; - public final LongSet loadedChunks; // Paper - private -> public - public final WorldServer world; -@@ -180,7 +205,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag); -- this.visibleChunks = this.updatingChunks.clone(); -+ //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning - this.pendingUnload = new Long2ObjectLinkedOpenHashMap(); - this.loadedChunks = new LongOpenHashSet(); - this.unloadQueue = new LongOpenHashSet(); -@@ -272,9 +297,52 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return (PlayerChunk) this.updatingChunks.get(i); - } - -+ // Paper start - remove cloning of visible chunks unless accessed as a collection async -+ private static final boolean DEBUG_ASYNC_VISIBLE_CHUNKS = Boolean.getBoolean("paper.debug-async-visible-chunks"); -+ private boolean isIterating = false; -+ private boolean hasPendingVisibleUpdate = false; -+ public void forEachVisibleChunk(java.util.function.Consumer consumer) { -+ org.spigotmc.AsyncCatcher.catchOp("forEachVisibleChunk"); -+ boolean prev = isIterating; -+ isIterating = true; -+ try { -+ for (PlayerChunk value : this.visibleChunks.values()) { -+ consumer.accept(value); -+ } -+ } finally { -+ this.isIterating = prev; -+ if (!this.isIterating && this.hasPendingVisibleUpdate) { -+ ((ProtectedVisibleChunksMap)this.visibleChunks).copyFrom(this.pendingVisibleChunks); -+ this.pendingVisibleChunks.clear(); -+ this.hasPendingVisibleUpdate = false; -+ } -+ } -+ } -+ public Long2ObjectLinkedOpenHashMap getVisibleChunks() { -+ if (Thread.currentThread() == this.world.serverThread) { -+ return this.visibleChunks; -+ } else { -+ synchronized (this.visibleChunks) { -+ if (DEBUG_ASYNC_VISIBLE_CHUNKS) new Throwable("Async getVisibleChunks").printStackTrace(); -+ if (this.visibleChunksClone == null) { -+ this.visibleChunksClone = this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.clone() : ((ProtectedVisibleChunksMap)this.visibleChunks).clone(); -+ } -+ return this.visibleChunksClone; -+ } -+ } -+ } -+ // Paper end -+ - @Nullable - public PlayerChunk getVisibleChunk(long i) { // Paper - protected -> public -- return (PlayerChunk) this.visibleChunks.get(i); -+ // Paper start - mt safe get -+ if (Thread.currentThread() != this.world.serverThread) { -+ synchronized (this.visibleChunks) { -+ return (PlayerChunk) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap)this.visibleChunks).safeGet(i)); -+ } -+ } -+ return (PlayerChunk) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap)this.visibleChunks).safeGet(i)); -+ // Paper end - } - - protected IntSupplier c(long i) { -@@ -462,8 +530,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper end - - protected void save(boolean flag) { -+ Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) - if (flag) { -- List list = (List) this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList()); -+ List list = (List) visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList()); // Paper - remove cloning of visible chunks - MutableBoolean mutableboolean = new MutableBoolean(); - - do { -@@ -491,7 +560,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // this.i(); // Paper - nuke IOWorker - PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName()); - } else { -- this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { -+ visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { - IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkSave().getNow(null); // CraftBukkit - decompile error - - if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) { -@@ -662,7 +731,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (!this.updatingChunksModified) { - return false; - } else { -- this.visibleChunks = this.updatingChunks.clone(); -+ // Paper start - stop cloning visibleChunks -+ synchronized (this.visibleChunks) { -+ if (isIterating) { -+ hasPendingVisibleUpdate = true; -+ this.pendingVisibleChunks.copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunks); -+ } else { -+ hasPendingVisibleUpdate = false; -+ this.pendingVisibleChunks.clear(); -+ ((ProtectedVisibleChunksMap)this.visibleChunks).copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunks); -+ this.visibleChunksClone = null; -+ } -+ } -+ // Paper end -+ - this.updatingChunksModified = false; - return true; - } -@@ -1141,12 +1223,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - protected Iterable f() { -- return Iterables.unmodifiableIterable(this.visibleChunks.values()); -+ return Iterables.unmodifiableIterable(this.getVisibleChunks().values()); // Paper - } - - void a(Writer writer) throws IOException { - CSVWriter csvwriter = CSVWriter.a().a("x").a("z").a("level").a("in_memory").a("status").a("full_status").a("accessible_ready").a("ticking_ready").a("entity_ticking_ready").a("ticket").a("spawning").a("entity_count").a("block_entity_count").a(writer); -- ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunks.long2ObjectEntrySet().iterator(); -+ ObjectBidirectionalIterator objectbidirectionaliterator = this.getVisibleChunks().long2ObjectEntrySet().iterator(); // Paper - - while (objectbidirectionaliterator.hasNext()) { - Entry entry = (Entry) objectbidirectionaliterator.next(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index fcad64fcfc22af227be19741b634b773aca7a98d..c5a4c8c4c9d90a8a081a593488f86ab487adaecb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -294,6 +294,7 @@ public class CraftWorld implements World { - return ret; - } - public int getTileEntityCount() { -+ return net.minecraft.server.MCUtil.ensureMain(() -> { - // We don't use the full world tile entity list, so we must iterate chunks - Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; - int size = 0; -@@ -305,11 +306,13 @@ public class CraftWorld implements World { - size += chunk.tileEntities.size(); - } - return size; -+ }); - } - public int getTickableTileEntityCount() { - return world.tileEntityListTick.size(); - } - public int getChunkCount() { -+ return net.minecraft.server.MCUtil.ensureMain(() -> { - int ret = 0; - - for (PlayerChunk chunkHolder : world.getChunkProvider().playerChunkMap.visibleChunks.values()) { -@@ -318,7 +321,7 @@ public class CraftWorld implements World { - } - } - -- return ret; -+ return ret; }); - } - public int getPlayerCount() { - return world.players.size(); -@@ -443,6 +446,14 @@ public class CraftWorld implements World { - - @Override - public Chunk[] getLoadedChunks() { -+ // Paper start -+ if (Thread.currentThread() != world.getMinecraftWorld().serverThread) { -+ synchronized (world.getChunkProvider().playerChunkMap.visibleChunks) { -+ Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; -+ return chunks.values().stream().map(PlayerChunk::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.Chunk::getBukkitChunk).toArray(Chunk[]::new); -+ } -+ } -+ // Paper end - Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; - return chunks.values().stream().map(PlayerChunk::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.Chunk::getBukkitChunk).toArray(Chunk[]::new); - } diff --git a/Unmapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch b/Unmapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch deleted file mode 100644 index 2b28126ee7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 8 Apr 2020 21:24:05 -0400 -Subject: [PATCH] Increase Light Queue Size - -Wiz mentioned that large WorldEdit operations cause light to run on -main thread. The queue was small, set to 5.. this bumps it to 20 -but makes it configurable per-world. - -The main risk of increasing this higher is during shutdown, some -queued light updates may be lost because mojang did not flush the -light engine on shutdown... - -The queue size only puts a cap on max loss, doesn't solve that problem. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1..cd248eb6be663e8be33f2c3c6b06b77b6d5753a4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -620,4 +620,9 @@ public class PaperWorldConfig { - private void zombieVillagerInfectionChance() { - zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); - } -+ -+ public int lightQueueSize = 20; -+ private void lightQueueSize() { -+ lightQueueSize = getInt("light-queue-size", lightQueueSize); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index b4e058794c3f8a827f3aabab5b98239a4c79c42c..34c273178e711466ec6638f24e0371554e26e134 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -777,7 +777,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Thu, 9 Apr 2020 00:09:26 -0400 -Subject: [PATCH] Mid Tick Chunk Tasks - Speed up processing of chunk loads and - generation - -Credit to Spotted for the idea - -A lot of the new chunk system requires constant back and forth the main thread -to handle priority scheduling and ensuring conflicting tasks do not run at the -same time. - -The issue is, these queues are only checked at either: - -A) Sync Chunk Loads -B) End of Tick while sleeping - -This results in generating chunks sitting waiting for a full tick to -complete before it will even start the next unit of work to do. - -Additionally, this also delays loading of chunks until this same timing. - -We will now periodically poll the chunk task queues throughout the tick, -looking for work to do. -We do this in a fair method that considers all worlds, not just the one being -ticked, so that each world can get 1 task procesed each before the next pass. - -In a view distance of 15, chunk loading performance was visually faster on the client. - -Flying at high speed in spectator mode was able to keep up with chunk loading (as long as they are already generated) - -diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -index fed920e5ec65409377f181d74dcf9274d45aadc1..b4d43ceed368552e703886213327a0c0bb5ccb92 100644 ---- a/src/main/java/co/aikar/timings/MinecraftTimings.java -+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -16,6 +16,7 @@ import java.util.Map; - public final class MinecraftTimings { - - public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); -+ public static final Timing midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks"); - public static final Timing playerListTimer = Timings.ofSafe("Player List"); - public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); - public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index da93d38fe63035e4ff198ada84a4431f52d97c01..ddbc8cb712c50038922eded75dd6ca85fe851078 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -410,4 +410,9 @@ public class PaperConfig { - log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); - } - } -+ -+ public static int midTickChunkTasks = 1000; -+ private static void midTickChunkTasks() { -+ midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 34c273178e711466ec6638f24e0371554e26e134..cb15606d528b2f94103d347ad89d3836fa93c360 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1057,6 +1057,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ midTickLoadChunks(); // will only do loads since we are still considered !canSleepForTick - return !this.canOversleep(); - }); - isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -@@ -1320,13 +1339,16 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { // Paper - safe iterator incase chunk loads, also no wrapping -+ final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - - if (optional.isPresent()) { -@@ -805,6 +808,7 @@ public class ChunkProviderServer extends IChunkProvider { - //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper - this.world.a(chunk, k); - //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper -+ if (chunksTicked[0]++ % 10 == 0) this.world.getMinecraftServer().midTickLoadChunks(); // Paper - } - } - } -@@ -962,6 +966,41 @@ public class ChunkProviderServer extends IChunkProvider { - super.executeTask(runnable); - } - -+ // Paper start -+ private long lastMidTickChunkTask = 0; -+ public boolean pollChunkLoadTasks() { -+ if (com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ChunkProviderServer.this.world.asyncChunkTaskManager.pollNextChunkTask()) { -+ try { -+ ChunkProviderServer.this.tickDistanceManager(); -+ } finally { -+ // from below: process pending Chunk loadCallback() and unloadCallback() after each run task -+ playerChunkMap.callbackExecutor.run(); -+ } -+ return true; -+ } -+ return false; -+ } -+ public void midTickLoadChunks() { -+ MinecraftServer server = ChunkProviderServer.this.world.getMinecraftServer(); -+ // always try to load chunks, restrain generation/other updates only. don't count these towards tick count -+ //noinspection StatementWithEmptyBody -+ while (pollChunkLoadTasks()) {} -+ -+ if (System.nanoTime() - lastMidTickChunkTask < 200000) { -+ return; -+ } -+ -+ for (;server.midTickChunksTasksRan < com.destroystokyo.paper.PaperConfig.midTickChunkTasks && server.canSleepForTick();) { -+ if (this.executeNext()) { -+ server.midTickChunksTasksRan++; -+ lastMidTickChunkTask = System.nanoTime(); -+ } else { -+ break; -+ } -+ } -+ } -+ // Paper end -+ - @Override - protected boolean executeNext() { - // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 35fc51ac93a62f6dc4b141dc94a3cda0399f0ce1..ce0bbd6fb467c84d14fa4eaa8f80ed5b261e07bd 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -571,6 +571,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - timings.scheduledBlocks.stopTiming(); // Paper - -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - gameprofilerfiller.exitEnter("raid"); - this.timings.raids.startTiming(); // Paper - timings - this.persistentRaid.a(); -@@ -579,6 +580,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - timings.doSounds.startTiming(); // Spigot - this.ak(); - timings.doSounds.stopTiming(); // Spigot -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - this.ticking = false; - gameprofilerfiller.exitEnter("entities"); - boolean flag3 = true || !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players -@@ -645,6 +647,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - timings.entityTick.stopTiming(); // Spigot - - this.tickingEntities = false; -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - - Entity entity2; - -@@ -654,6 +657,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - timings.tickEntities.stopTiming(); // Spigot -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - this.tickBlockEntities(); - } - diff --git a/Unmapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch b/Unmapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch deleted file mode 100644 index 17f522dfd3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 9 Apr 2020 21:20:33 -0400 -Subject: [PATCH] Don't move existing players to world spawn - -This can cause a nasty server lag the spawn chunks are not kept loaded -or they aren't finished loading yet, or if the world spawn radius is -larger than the keep loaded range. - -By skipping this, we avoid potential for a large spike on server start. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index e3721287cc18c8df81d1353084364966eb3f55ab..79003f43c4f15a7e5dd51587bc8c2f477bedb1b2 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -254,7 +254,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.serverStatisticManager = minecraftserver.getPlayerList().getStatisticManager(this); - this.advancementDataPlayer = minecraftserver.getPlayerList().f(this); - this.G = 1.0F; -- this.c(worldserver); -+ //this.c(worldserver); // Paper - don't move to spawn on login, only first join - this.co = minecraftserver.a(this); - - this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -@@ -306,6 +306,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - // CraftBukkit end - -+ public final void moveToSpawn(WorldServer worldserver) { c(worldserver); } // Paper - OBFHELPER - private void c(WorldServer worldserver) { - BlockPosition blockposition = worldserver.getSpawn(); - -@@ -483,7 +484,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - position = Vec3D.a(((WorldServer) world).getSpawn()); - } - this.world = world; -- this.setPosition(position.getX(), position.getY(), position.getZ()); -+ this.setPositionRaw(position.getX(), position.getY(), position.getZ()); // Paper - don't register to chunks yet - } - this.playerInteractManager.a((WorldServer) world); - } -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0a99ee6221c46043ecdf9e9df7a064aa63ee6951..bd272d6fe86c30c3f22418802f98609410f947f8 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -208,6 +208,8 @@ public abstract class PlayerList { - worldserver1 = worldserver; - } - -+ if (nbttagcompound == null) entityplayer.moveToSpawn(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are.... -+ - entityplayer.spawnIn(worldserver1); - entityplayer.playerInteractManager.a((WorldServer) entityplayer.world); - String s1 = "local"; diff --git a/Unmapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch b/Unmapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch deleted file mode 100644 index d32bc81676..0000000000 --- a/Unmapped-Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 5 Apr 2020 22:23:14 -0500 -Subject: [PATCH] Add tick times API and /mspt command - - -diff --git a/src/main/java/com/destroystokyo/paper/MSPTCommand.java b/src/main/java/com/destroystokyo/paper/MSPTCommand.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d0211d4f39f9d6af1d751ac66342b42cc6d7ba6d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/MSPTCommand.java -@@ -0,0 +1,64 @@ -+package com.destroystokyo.paper; -+ -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.ChatColor; -+import org.bukkit.Location; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+ -+import java.text.DecimalFormat; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collections; -+import java.util.List; -+ -+public class MSPTCommand extends Command { -+ private static final DecimalFormat DF = new DecimalFormat("########0.0"); -+ -+ public MSPTCommand(String name) { -+ super(name); -+ this.description = "View server tick times"; -+ this.usageMessage = "/mspt"; -+ this.setPermission("bukkit.command.mspt"); -+ } -+ -+ @Override -+ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { -+ return Collections.emptyList(); -+ } -+ -+ @Override -+ public boolean execute(CommandSender sender, String commandLabel, String[] args) { -+ if (!testPermission(sender)) return true; -+ -+ MinecraftServer server = MinecraftServer.getServer(); -+ -+ List times = new ArrayList<>(); -+ times.addAll(eval(server.tickTimes5s.getTimes())); -+ times.addAll(eval(server.tickTimes10s.getTimes())); -+ times.addAll(eval(server.tickTimes60s.getTimes())); -+ -+ sender.sendMessage("§6Server tick times §e(§7avg§e/§7min§e/§7max§e)§6 from last 5s§7,§6 10s§7,§6 1m§e:"); -+ sender.sendMessage(String.format("§6◴ %s§7/%s§7/%s§e, %s§7/%s§7/%s§e, %s§7/%s§7/%s", times.toArray())); -+ return true; -+ } -+ -+ private static List eval(long[] times) { -+ long min = Integer.MAX_VALUE; -+ long max = 0L; -+ long total = 0L; -+ for (long value : times) { -+ if (value > 0L && value < min) min = value; -+ if (value > max) max = value; -+ total += value; -+ } -+ double avgD = ((double) total / (double) times.length) * 1.0E-6D; -+ double minD = ((double) min) * 1.0E-6D; -+ double maxD = ((double) max) * 1.0E-6D; -+ return Arrays.asList(getColor(avgD), getColor(minD), getColor(maxD)); -+ } -+ -+ private static String getColor(double avg) { -+ return ChatColor.COLOR_CHAR + (avg >= 50 ? "c" : avg >= 40 ? "e" : "a") + DF.format(avg); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index ddbc8cb712c50038922eded75dd6ca85fe851078..78271b400c79578d043b20a5389a37b1bef9a70d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -69,6 +69,7 @@ public class PaperConfig { - - commands = new HashMap(); - commands.put("paper", new PaperCommand("paper")); -+ commands.put("mspt", new MSPTCommand("mspt")); - - version = getInt("config-version", 20); - set("config-version", 20); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index cb15606d528b2f94103d347ad89d3836fa93c360..04363d1076b428c302e045039a5d240490dc5e6a 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -219,6 +219,11 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Fri, 10 Apr 2020 21:24:12 -0400 -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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 8577451ed4dcba901ca9f74e0ff198ab0336d689..e11649b838b6c6e8745d3a0c6d093b3cfff0acda 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2379,5 +2379,10 @@ public final class CraftServer implements Server { - public int getCurrentTick() { - return net.minecraft.server.MinecraftServer.currentTick; - } -+ -+ @Override -+ public boolean isStopping() { -+ return net.minecraft.server.MinecraftServer.getServer().hasStopped(); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch b/Unmapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch deleted file mode 100644 index 292ccedef1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Thu, 30 Apr 2020 16:56:54 +0200 -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/net/minecraft/nbt/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -index 20410a5853e34c90c872f5e9592d50c4727e914d..860f084de38dc3f8723d881ff78fb1873f2b602a 100644 ---- a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -+++ b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -@@ -51,6 +51,7 @@ public class NBTCompressedStreamTools { - return nbttagcompound; - } - -+ public static NBTTagCompound readNBT(InputStream inputstream) throws IOException { return a(inputstream); } // Paper - OBFHELPER - public static NBTTagCompound a(InputStream inputstream) throws IOException { - DataInputStream datainputstream = new DataInputStream(new BufferedInputStream(new GZIPInputStream(inputstream))); - Throwable throwable = null; -@@ -106,6 +107,7 @@ public class NBTCompressedStreamTools { - - } - -+ public static void writeNBT(NBTTagCompound nbttagcompound, OutputStream outputstream) throws IOException { a(nbttagcompound, outputstream); } // Paper - OBFHELPER - public static void a(NBTTagCompound nbttagcompound, OutputStream outputstream) throws IOException { - DataOutputStream dataoutputstream = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(outputstream))); - Throwable throwable = null; -diff --git a/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java b/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java -index 6527509e6aed7187667c681af682e9a02937a224..28e36ee76da533f8aa0a09cfc4f1fc0f744af715 100644 ---- a/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java -+++ b/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java -@@ -208,6 +208,7 @@ public class DataConverterRegistry { - return datafixerbuilder.build(SystemUtils.e()); - } - -+ public static DataFixer getDataFixer() { return a(); } // Paper - OBFHELPER - public static DataFixer a() { - return DataConverterRegistry.c; - } -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 7b1df591007b9c50bcaf4bcd30562396a9549193..b88aec3b97d43018cf2733bad069a90338aa98cb 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -198,6 +198,7 @@ public final class ItemStack { - this.checkEmpty(); - } - -+ public static ItemStack fromCompound(NBTTagCompound nbttagcompound) { return a(nbttagcompound); } // Paper - OBFHELPER - public static ItemStack a(NBTTagCompound nbttagcompound) { - try { - return new ItemStack(nbttagcompound); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 7e4cceff7ce9ffaff00caf21088fd7bc59e66933..2519dbce9717ff647d50c31aed6aca68b9f4e3af 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -380,6 +380,46 @@ public final class CraftMagicNumbers implements UnsafeValues { - public boolean isSupportedApiVersion(String apiVersion) { - return apiVersion != null && SUPPORTED_API.contains(apiVersion); - } -+ -+ @Override -+ public byte[] serializeItem(ItemStack item) { -+ Preconditions.checkNotNull(item, "null cannot be serialized"); -+ Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized"); -+ -+ java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); -+ NBTTagCompound compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).getHandle() : CraftItemStack.asNMSCopy(item)).save(new NBTTagCompound()); -+ compound.setInt("DataVersion", getDataVersion()); -+ try { -+ net.minecraft.nbt.NBTCompressedStreamTools.writeNBT( -+ compound, -+ outputStream -+ ); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return outputStream.toByteArray(); -+ } -+ -+ @Override -+ public ItemStack deserializeItem(byte[] data) { -+ Preconditions.checkNotNull(data, "null cannot be deserialized"); -+ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing"); -+ -+ try { -+ NBTTagCompound compound = net.minecraft.nbt.NBTCompressedStreamTools.readNBT( -+ new java.io.ByteArrayInputStream(data) -+ ); -+ int dataVersion = compound.getInt("DataVersion"); -+ -+ Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); -+ Dynamic converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ITEM_STACK, new Dynamic(DynamicOpsNBT.a, compound), dataVersion, getDataVersion()); -+ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.fromCompound((NBTTagCompound) converted.getValue())); -+ } catch (IOException ex) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ex); -+ throw new RuntimeException(); -+ } -+ } - // Paper end - - /** diff --git a/Unmapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch b/Unmapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch deleted file mode 100644 index 4937798620..0000000000 --- a/Unmapped-Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 17:53:29 -0700 -Subject: [PATCH] Remove streams from Mob AI System - -The streams hurt performance and allocate tons of garbage, so -replace them with the standard iterator. - -Also optimise the stream.anyMatch statement to move to a bitset -where we can replace the call with a single bitwise operation. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -index b505c23c57a4b84faf5906c6295455b4720c4426..5c32cbe81c47fcb9ae347faa6fc007c5d28d79bf 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -@@ -1,10 +1,12 @@ - package net.minecraft.world.entity.ai.goal; - -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector - import java.util.EnumSet; - - public abstract class PathfinderGoal { - -- private final EnumSet a = EnumSet.noneOf(PathfinderGoal.Type.class); -+ private final EnumSet a = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. -+ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector - - public PathfinderGoal() {} - -@@ -28,16 +30,20 @@ public abstract class PathfinderGoal { - public void e() {} - - public void a(EnumSet enumset) { -- this.a.clear(); -- this.a.addAll(enumset); -+ // Paper start - remove streams from pathfindergoalselector -+ this.goalTypes.clear(); -+ this.goalTypes.addAllUnchecked(enumset); -+ // Paper end - remove streams from pathfindergoalselector - } - - public String toString() { - return this.getClass().getSimpleName(); - } - -- public EnumSet i() { -- return this.a; -+ // Paper start - remove streams from pathfindergoalselector -+ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { -+ return this.goalTypes; -+ // Paper end - remove streams from pathfindergoalselector - } - - public static enum Type { -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -index 8c234c09a4d9ada83e36e3cdbcc1f2f5c6202f28..385cd079e264a7e66e91ab3b70b90afb59688dcd 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -@@ -1,8 +1,10 @@ - package net.minecraft.world.entity.ai.goal; - -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector - import com.google.common.collect.Sets; - import java.util.EnumMap; - import java.util.EnumSet; -+import java.util.Iterator; // Paper - remove streams from pathfindergoalselector - import java.util.Map; - import java.util.Set; - import java.util.function.Supplier; -@@ -28,7 +30,8 @@ public class PathfinderGoalSelector { - private final Map c = new EnumMap(PathfinderGoal.Type.class); - private final Set d = Sets.newLinkedHashSet(); private Set getTasks() { return d; }// Paper - OBFHELPER - private final Supplier e; -- private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); -+ private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. -+ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector - private int g = 3;private int getTickRate() { return g; } // Paper - OBFHELPER - private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO - -@@ -56,35 +59,38 @@ public class PathfinderGoalSelector { - // Paper end - - public void a(PathfinderGoal pathfindergoal) { -- this.d.stream().filter((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.j() == pathfindergoal; -- }).filter(PathfinderGoalWrapped::g).forEach(PathfinderGoalWrapped::d); -- this.d.removeIf((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.j() == pathfindergoal; -- }); -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { -+ PathfinderGoalWrapped goalWrapped = iterator.next(); -+ if (goalWrapped.j() != pathfindergoal) { -+ continue; -+ } -+ if (goalWrapped.g()) { -+ goalWrapped.d(); -+ } -+ iterator.remove(); -+ } -+ // Paper end - remove streams from pathfindergoalselector - } - -+ private static final PathfinderGoal.Type[] PATHFINDER_GOAL_TYPES = PathfinderGoal.Type.values(); // Paper - remove streams from pathfindergoalselector -+ - public void doTick() { - GameProfilerFiller gameprofilerfiller = (GameProfilerFiller) this.e.get(); - - gameprofilerfiller.enter("goalCleanup"); -- this.d().filter((pathfindergoalwrapped) -> { -- boolean flag; -- -- if (pathfindergoalwrapped.g()) { -- Stream stream = pathfindergoalwrapped.i().stream(); -- EnumSet enumset = this.f; -- -- this.f.getClass(); -- if (!stream.anyMatch(enumset::contains) && pathfindergoalwrapped.b()) { -- flag = false; -- return flag; -- } -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { -+ PathfinderGoalWrapped wrappedGoal = iterator.next(); -+ if (!wrappedGoal.g()) { -+ continue; - } -- -- flag = true; -- return flag; -- }).forEach(PathfinderGoal::d); -+ if (!this.goalTypes.hasCommonElements(wrappedGoal.getGoalTypes()) && wrappedGoal.b()) { -+ continue; -+ } -+ wrappedGoal.d(); -+ } -+ // Paper end - remove streams from pathfindergoalselector - this.c.forEach((pathfindergoal_type, pathfindergoalwrapped) -> { - if (!pathfindergoalwrapped.g()) { - this.c.remove(pathfindergoal_type); -@@ -93,30 +99,58 @@ public class PathfinderGoalSelector { - }); - gameprofilerfiller.exit(); - gameprofilerfiller.enter("goalUpdate"); -- this.d.stream().filter((pathfindergoalwrapped) -> { -- return !pathfindergoalwrapped.g(); -- }).filter((pathfindergoalwrapped) -> { -- Stream stream = pathfindergoalwrapped.i().stream(); -- EnumSet enumset = this.f; -- -- this.f.getClass(); -- return stream.noneMatch(enumset::contains); -- }).filter((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.i().stream().allMatch((pathfindergoal_type) -> { -- return ((PathfinderGoalWrapped) this.c.getOrDefault(pathfindergoal_type, PathfinderGoalSelector.b)).a(pathfindergoalwrapped); -- }); -- }).filter(PathfinderGoalWrapped::a).forEach((pathfindergoalwrapped) -> { -- pathfindergoalwrapped.i().forEach((pathfindergoal_type) -> { -- PathfinderGoalWrapped pathfindergoalwrapped1 = (PathfinderGoalWrapped) this.c.getOrDefault(pathfindergoal_type, PathfinderGoalSelector.b); -- -- pathfindergoalwrapped1.d(); -- this.c.put(pathfindergoal_type, pathfindergoalwrapped); -- }); -- pathfindergoalwrapped.c(); -- }); -+ // Paper start - remove streams from pathfindergoalselector -+ goal_update_loop: for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { -+ PathfinderGoalWrapped wrappedGoal = iterator.next(); -+ if (wrappedGoal.g()) { -+ continue; -+ } -+ -+ OptimizedSmallEnumSet wrappedGoalSet = wrappedGoal.getGoalTypes(); -+ -+ if (this.goalTypes.hasCommonElements(wrappedGoalSet)) { -+ continue; -+ } -+ -+ long iterator1 = wrappedGoalSet.getBackingSet(); -+ int wrappedGoalSize = wrappedGoalSet.size(); -+ for (int i = 0; i < wrappedGoalSize; ++i) { -+ PathfinderGoal.Type type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; -+ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); -+ PathfinderGoalWrapped wrapped = this.c.getOrDefault(type, PathfinderGoalSelector.b); -+ if (!wrapped.a(wrappedGoal)) { -+ continue goal_update_loop; -+ } -+ } -+ -+ if (!wrappedGoal.a()) { -+ continue; -+ } -+ -+ iterator1 = wrappedGoalSet.getBackingSet(); -+ wrappedGoalSize = wrappedGoalSet.size(); -+ for (int i = 0; i < wrappedGoalSize; ++i) { -+ PathfinderGoal.Type type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; -+ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); -+ PathfinderGoalWrapped wrapped = this.c.getOrDefault(type, PathfinderGoalSelector.b); -+ -+ wrapped.d(); -+ this.c.put(type, wrappedGoal); -+ } -+ -+ wrappedGoal.c(); -+ } -+ // Paper end - remove streams from pathfindergoalselector - gameprofilerfiller.exit(); - gameprofilerfiller.enter("goalTick"); -- this.d().forEach(PathfinderGoalWrapped::e); -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { -+ PathfinderGoalWrapped wrappedGoal = iterator.next(); -+ if (wrappedGoal.g()) { -+ wrappedGoal.e(); -+ } -+ } -+ // Paper end - remove streams from pathfindergoalselector - gameprofilerfiller.exit(); - } - -@@ -125,11 +159,11 @@ public class PathfinderGoalSelector { - } - - public void a(PathfinderGoal.Type pathfindergoal_type) { -- this.f.add(pathfindergoal_type); -+ this.goalTypes.addUnchecked(pathfindergoal_type); // Paper - remove streams from pathfindergoalselector - } - - public void b(PathfinderGoal.Type pathfindergoal_type) { -- this.f.remove(pathfindergoal_type); -+ this.goalTypes.removeUnchecked(pathfindergoal_type); // Paper - remove streams from pathfindergoalselector - } - - public void a(PathfinderGoal.Type pathfindergoal_type, boolean flag) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -index 7bb531e47668cf445083c4dedb03ccafe6a9c96b..8c8e39d35fb56aa6cf7d456adab01dff5d13a60d 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -@@ -59,9 +59,10 @@ public class PathfinderGoalWrapped extends PathfinderGoal { - this.a.a(enumset); - } - -- @Override -- public EnumSet i() { -- return this.a.i(); -+ // Paper start - remove streams from pathfindergoalselector -+ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { -+ return this.a.getGoalTypes(); -+ // Paper end - remove streams from pathfindergoalselector - } - - public boolean isRunning() { return this.g(); } // Paper - OBFHELPER diff --git a/Unmapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch b/Unmapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch deleted file mode 100644 index b557363c64..0000000000 --- a/Unmapped-Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Apr 2020 21:23:42 -0400 -Subject: [PATCH] Delay unsafe actions until after entity ticking is done - -This will help prevent many cases of unregistering entities during entity ticking - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index ce0bbd6fb467c84d14fa4eaa8f80ed5b261e07bd..bc629c8355a0a2273bcf1285a22deb1ce1154bf9 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -178,6 +178,16 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final List players = Lists.newArrayList(); // Paper - private -> public - public final ChunkProviderServer chunkProvider; // Paper - public - boolean tickingEntities; -+ // Paper start -+ List afterEntityTickingTasks = Lists.newArrayList(); -+ public void doIfNotEntityTicking(java.lang.Runnable run) { -+ if (tickingEntities) { -+ afterEntityTickingTasks.add(run); -+ } else { -+ run.run(); -+ } -+ } -+ // Paper end - private final MinecraftServer server; - public final WorldDataServer worldDataServer; // CraftBukkit - type - public boolean savingDisabled; -@@ -647,6 +657,16 @@ public class WorldServer extends World implements GeneratorAccessSeed { - timings.entityTick.stopTiming(); // Spigot - - this.tickingEntities = false; -+ // Paper start -+ for (java.lang.Runnable run : this.afterEntityTickingTasks) { -+ try { -+ run.run(); -+ } catch (Exception e) { -+ LOGGER.error("Error in After Entity Ticking Task", e); -+ } -+ } -+ this.afterEntityTickingTasks.clear(); -+ // Paper end - this.getMinecraftServer().midTickLoadChunks(); // Paper - - Entity entity2; diff --git a/Unmapped-Spigot-Server-Patches/0435-Async-command-map-building.patch b/Unmapped-Spigot-Server-Patches/0435-Async-command-map-building.patch deleted file mode 100644 index 303aa637e9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0435-Async-command-map-building.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Callahan -Date: Wed, 8 Apr 2020 02:42:14 -0500 -Subject: [PATCH] Async command map building - - -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index 63948c78205730d4aa6a6cc418f4f9de30401beb..592b1bb2ce5cedb627f42c73ef072ade6553347e 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -29,6 +29,7 @@ import net.minecraft.network.chat.ChatHoverable; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatMutableComponent; - import net.minecraft.network.protocol.game.PacketPlayOutCommands; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.commands.CommandAdvancement; - import net.minecraft.server.commands.CommandAttribute; - import net.minecraft.server.commands.CommandBan; -@@ -328,6 +329,14 @@ public class CommandDispatcher { - if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot - // CraftBukkit start - // Register Vanilla commands into builtRoot as before -+ // Paper start - Async command map building -+ java.util.concurrent.ForkJoinPool.commonPool().execute(() -> { -+ sendAsync(entityplayer); -+ }); -+ } -+ -+ private void sendAsync(EntityPlayer entityplayer) { -+ // Paper end - Async command map building - Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues - RootCommandNode vanillaRoot = new RootCommandNode(); - -@@ -345,7 +354,14 @@ public class CommandDispatcher { - for (CommandNode node : rootcommandnode.getChildren()) { - bukkit.add(node.getName()); - } -+ // Paper start - Async command map building -+ MinecraftServer.getServer().execute(() -> { -+ runSync(entityplayer, bukkit, rootcommandnode); -+ }); -+ } - -+ private void runSync(EntityPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { -+ // Paper end - Async command map building - PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); - event.getPlayer().getServer().getPluginManager().callEvent(event); - diff --git a/Unmapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch b/Unmapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch deleted file mode 100644 index d294732178..0000000000 --- a/Unmapped-Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch +++ /dev/null @@ -1,608 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 12 Apr 2020 15:50:48 -0400 -Subject: [PATCH] Improved Watchdog Support - -Forced Watchdog Crash support and Improve Async Shutdown - -If the request to shut down the server is received while we are in -a watchdog hang, immediately treat it as a crash and begin the shutdown -process. Shutdown process is now improved to also shutdown cleanly when -not using restart scripts either. - -If a server is deadlocked, a server owner can send SIGUP (or any other signal -the JVM understands to shut down as it currently does) and the watchdog -will no longer need to wait until the full timeout, allowing you to trigger -a close process and try to shut the server down gracefully, saving player and -world data. - -Previously there was no way to trigger this outside of waiting for a full watchdog -timeout, which may be set to a really long time... - -Additionally, fix everything to do with shutting the server down asynchronously. - -Previously, nearly everything about the process was fragile and unsafe. Main might -not have actually been frozen, and might still be manipulating state. - -Or, some reuest might ask main to do something in the shutdown but main is dead. - -Or worse, other things might start closing down items such as the Console or Thread Pool -before we are fully shutdown. - -This change tries to resolve all of these issues by moving everything into the stop -method and guaranteeing only one thread is stopping the server. - -We then issue Thread Death to the main thread of another thread initiates the stop process. -We have to ensure Thread Death propagates correctly though to stop main completely. - -This is to ensure that if main isn't truely stuck, it's not manipulating state we are trying to save. - -This also moves all plugins who register "delayed init" tasks to occur just before "Done" so they -are properly accounted for and wont trip watchdog on init. - -diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index 0b9e689d57705965721b5c55bc45d36657f360e4..dee00aac05f1acf050f05d4db557a08dd0f301c8 100644 ---- a/src/main/java/com/destroystokyo/paper/Metrics.java -+++ b/src/main/java/com/destroystokyo/paper/Metrics.java -@@ -92,7 +92,12 @@ public class Metrics { - * Starts the Scheduler which submits our data every 30 minutes. - */ - private void startSubmitting() { -- final Runnable submitTask = this::submitData; -+ final Runnable submitTask = () -> { -+ if (MinecraftServer.getServer().hasStopped()) { -+ return; -+ } -+ submitData(); -+ }; - - // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the - // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. -diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java -index d0fdb9ce57b22a1f582cddec9afcc35b75d58cc6..9b7a51890c667601b195ff15b2bf0d6c76c7f19f 100644 ---- a/src/main/java/net/minecraft/CrashReport.java -+++ b/src/main/java/net/minecraft/CrashReport.java -@@ -257,6 +257,7 @@ public class CrashReport { - } - - public static CrashReport a(Throwable throwable, String s) { -+ if (throwable instanceof ThreadDeath) com.destroystokyo.paper.util.SneakyThrow.sneaky(throwable); // Paper - while (throwable instanceof CompletionException && throwable.getCause() != null) { - throwable = throwable.getCause(); - } -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 397194b3e90c9df39cfae17b401c7ac891b0dbb7..61b4c42e95994343772a91640b243b8e8224e09b 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -130,6 +130,7 @@ public class SystemUtils { - return SystemUtils.f; - } - -+ public static void shutdownServerThreadPool() { h(); } // Paper - OBFHELPER - public static void h() { - a(SystemUtils.e); - a(SystemUtils.f); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 04363d1076b428c302e045039a5d240490dc5e6a..7f67773686a2d55153f7b2bfbe24df84fe1198be 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -271,7 +271,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant S a(Function function) { - AtomicReference atomicreference = new AtomicReference(); - Thread thread = new Thread(() -> { -@@ -853,6 +856,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ world.tickingEntities = false; -+ }); -+ } -+ // Paper end - // CraftBukkit end - MinecraftServer.LOGGER.info("Stopping server"); - MinecraftTimings.stopServer(); // Paper -@@ -932,7 +953,18 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant {}; -+ } -+ // Paper end - return new TickTask(this.ticks, runnable); - } - -@@ -1423,6 +1480,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { - CompletableFuture completablefuture; -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index bc629c8355a0a2273bcf1285a22deb1ce1154bf9..524bbf9bdf5fb0e1e4ff217ae3291fdbe742437e 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -177,7 +177,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - private final Queue entitiesToAdd = Queues.newArrayDeque(); - public final List players = Lists.newArrayList(); // Paper - private -> public - public final ChunkProviderServer chunkProvider; // Paper - public -- boolean tickingEntities; -+ public boolean tickingEntities; // Paper - expose for watchdog - // Paper start - List afterEntityTickingTasks = Lists.newArrayList(); - public void doIfNotEntityTicking(java.lang.Runnable run) { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index bd272d6fe86c30c3f22418802f98609410f947f8..9eec320ca5a63a313138dc84367e93038b457c0d 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -507,7 +507,7 @@ public abstract class PlayerList { - cserver.getPluginManager().callEvent(playerQuitEvent); - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - -- entityplayer.playerTick(); // SPIGOT-924 -+ if (server.isMainThread()) entityplayer.playerTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) - // CraftBukkit end - - // Paper start - Remove from collideRule team if needed -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -index ca23ca14d8011fc8daa7e20f2eaa550a8ff92c53..158ea6d77698d62ba795aff6c061a80652e42e03 100644 ---- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -+++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -@@ -135,6 +135,7 @@ public abstract class IAsyncTaskHandler implements Mailbox asList(String... params) { - return Arrays.asList(params); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index 449e99d1b673870ed6892f6ab2c715a2db35c35d..c7ed6e0f8a989cec97700df2b15198c9c481c549 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -12,12 +12,27 @@ public class ServerShutdownThread extends Thread { - @Override - public void run() { - try { -+ // Paper start - try to shutdown on main -+ server.safeShutdown(false, false); -+ for (int i = 1000; i > 0 && !server.hasStopped(); i -= 100) { -+ Thread.sleep(100); -+ } -+ if (server.hasStopped()) { -+ while (!server.hasFullyShutdown) Thread.sleep(1000); -+ return; -+ } -+ // Looks stalled, close async - org.spigotmc.AsyncCatcher.enabled = false; // Spigot - org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper -+ server.forceTicks = true; - server.close(); -+ while (!server.hasFullyShutdown) Thread.sleep(1000); -+ } catch (InterruptedException e) { -+ e.printStackTrace(); -+ // Paper end - } finally { - try { -- net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender -+ //net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Move into stop - } catch (Exception e) { - } - } -diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index b45d7e5c108c7a8541fcbc9ad92d1a79a94746a1..6a408dc9286a60c3ca7830f88171919fb0fe6363 100644 ---- a/src/main/java/org/spigotmc/RestartCommand.java -+++ b/src/main/java/org/spigotmc/RestartCommand.java -@@ -139,7 +139,7 @@ public class RestartCommand extends Command - // Paper end - - // Paper start - copied from above and modified to return if the hook registered -- private static boolean addShutdownHook(String restartScript) -+ public static boolean addShutdownHook(String restartScript) - { - String[] split = restartScript.split( " " ); - if ( split.length > 0 && new File( split[0] ).isFile() ) -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 58e50bf0fb0f309227e1f4c1f6bb11c01d8e08d3..c58de4de8d98c6b1e79d83cc7fcd46a7590ed2a0 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -13,6 +13,7 @@ import org.bukkit.Bukkit; - public class WatchdogThread extends Thread - { - -+ public static final boolean DISABLE_WATCHDOG = Boolean.getBoolean("disable.watchdog"); // Paper - private static WatchdogThread instance; - private long timeoutTime; - private boolean restart; -@@ -41,6 +42,7 @@ public class WatchdogThread extends Thread - { - if ( instance == null ) - { -+ if (timeoutTime <= 0) timeoutTime = 300; // Paper - instance = new WatchdogThread( timeoutTime * 1000L, restart ); - instance.start(); - } else -@@ -71,12 +73,13 @@ public class WatchdogThread extends Thread - // Paper start - Logger log = Bukkit.getServer().getLogger(); - long currentTime = monotonicMillis(); -- if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) -+ MinecraftServer server = MinecraftServer.getServer(); -+ if (lastTick != 0 && timeoutTime > 0 && hasStarted && (!server.isRunning() || (currentTime > lastTick + earlyWarningEvery && !DISABLE_WATCHDOG) )) - { -- boolean isLongTimeout = currentTime > lastTick + timeoutTime; -+ boolean isLongTimeout = currentTime > lastTick + timeoutTime || (!server.isRunning() && !server.hasStopped() && currentTime > lastTick + 1000); - // Don't spam early warning dumps - if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; -- if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... -+ if ( !isLongTimeout && server.hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... - lastEarlyWarning = currentTime; - if (isLongTimeout) { - // Paper end -@@ -118,7 +121,7 @@ public class WatchdogThread extends Thread - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper -- dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); -+ dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // - // Paper start - Only print full dump on long timeouts -@@ -139,9 +142,25 @@ public class WatchdogThread extends Thread - - if ( isLongTimeout ) - { -- if ( restart && !MinecraftServer.getServer().hasStopped() ) -+ if ( !server.hasStopped() ) - { -- RestartCommand.restart(); -+ AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us -+ AsyncCatcher.shuttingDown = true; -+ server.forceTicks = true; -+ if (restart) { -+ RestartCommand.addShutdownHook( SpigotConfig.restartScript ); -+ } -+ // try one last chance to safe shutdown on main incase it 'comes back' -+ server.abnormalExit = true; -+ server.safeShutdown(false, restart); -+ try { -+ Thread.sleep(1000); -+ } catch (InterruptedException e) { -+ e.printStackTrace(); -+ } -+ if (!server.hasStopped()) { -+ server.close(); -+ } - } - break; - } // Paper end -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 476f4a5cbe664ddd05474cb88553018bd334a5b8..8af159abd3d0cc94cf155fec5b384c42f69551bf 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -1,5 +1,5 @@ - -- -+ - - - diff --git a/Unmapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch b/Unmapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch deleted file mode 100644 index 812fed5f72..0000000000 --- a/Unmapped-Spigot-Server-Patches/0437-Optimize-Pathfinding.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 02:02:07 -0600 -Subject: [PATCH] Optimize Pathfinding - -Prevents pathfinding from spamming failures for things such as -arrow attacks. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index 06d05b511d623d0247d44989bee85b383a8fb52f..e6ba9b7fbf08ae0dd083a1ebee8eb7ed8a937751 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -11,6 +11,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.IPosition; - import net.minecraft.network.protocol.game.PacketDebug; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityInsentient; -@@ -32,7 +33,7 @@ public abstract class NavigationAbstract { - protected final EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER - protected final World b; - @Nullable -- protected PathEntity c; -+ protected PathEntity c; protected final PathEntity getCurrentPath() { return this.c; } // Paper - OBFHELPER - protected double d; - protected int e; - protected int f; -@@ -184,10 +185,30 @@ public abstract class NavigationAbstract { - return this.a(this.a(d0, d1, d2, 1), d3); - } - -+ // Paper start - optimise pathfinding -+ private int lastFailure = 0; -+ private int pathfindFailures = 0; -+ // Paper end -+ - public boolean a(Entity entity, double d0) { -+ // Paper start - Pathfinding optimizations -+ if (this.pathfindFailures > 10 && this.getCurrentPath() == null && MinecraftServer.currentTick < this.lastFailure + 40) { -+ return false; -+ } -+ // Paper end - PathEntity pathentity = this.a(entity, 1); - -- return pathentity != null && this.a(pathentity, d0); -+ // Paper start - Pathfinding optimizations -+ if (pathentity != null && this.a(pathentity, d0)) { -+ this.lastFailure = 0; -+ this.pathfindFailures = 0; -+ return true; -+ } else { -+ this.pathfindFailures++; -+ this.lastFailure = MinecraftServer.currentTick; -+ return false; -+ } -+ // Paper end - } - - public boolean setDestination(@Nullable PathEntity pathentity, double speed) { return a(pathentity, speed); } // Paper - OBFHELPER diff --git a/Unmapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch b/Unmapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch deleted file mode 100644 index 0f4641263b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 18:35:09 -0700 -Subject: [PATCH] Reduce Either Optional allocation - -In order to get chunk values, we shouldn't need to create -an optional each time. - -diff --git a/src/main/java/com/mojang/datafixers/util/Either.java b/src/main/java/com/mojang/datafixers/util/Either.java -index a90adac7bd7ebd423f480e9ae0f44cb9d521fa4f..3f65fe71024928e35111fc6719a290aab9a6859e 100644 ---- a/src/main/java/com/mojang/datafixers/util/Either.java -+++ b/src/main/java/com/mojang/datafixers/util/Either.java -@@ -22,7 +22,7 @@ public abstract class Either implements App, L> { - } - - private static final class Left extends Either { -- private final L value; -+ private final L value; private Optional valueOptional; // Paper - reduce the optional allocation... - - public Left(final L value) { - this.value = value; -@@ -51,7 +51,7 @@ public abstract class Either implements App, L> { - - @Override - public Optional left() { -- return Optional.of(value); -+ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... - } - - @Override -@@ -83,7 +83,7 @@ public abstract class Either implements App, L> { - } - - private static final class Right extends Either { -- private final R value; -+ private final R value; private Optional valueOptional; // Paper - reduce the optional allocation... - - public Right(final R value) { - this.value = value; -@@ -117,7 +117,7 @@ public abstract class Either implements App, L> { - - @Override - public Optional right() { -- return Optional.of(value); -+ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch b/Unmapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch deleted file mode 100644 index f1a9a0128a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 18:10:43 -0700 -Subject: [PATCH] Remove streams from PairedQueue - -We shouldn't be doing stream calls just to see if the queue is -empty. This creates loads of garbage thanks to how often it's called. - -diff --git a/src/main/java/net/minecraft/util/thread/PairedQueue.java b/src/main/java/net/minecraft/util/thread/PairedQueue.java -index 024b414aae32c8ad32bdf031361257fc74b80eb3..56c9efa78ceeac499182eb401e605a60dad12182 100644 ---- a/src/main/java/net/minecraft/util/thread/PairedQueue.java -+++ b/src/main/java/net/minecraft/util/thread/PairedQueue.java -@@ -20,32 +20,30 @@ public interface PairedQueue { - - public static final class a implements PairedQueue { - -- private final List> a; -+ private final List> a; private final List> getQueues() { return this.a; } // Paper - OBFHELPER - - public a(int i) { -- this.a = (List) IntStream.range(0, i).mapToObj((j) -> { -- return Queues.newConcurrentLinkedQueue(); -- }).collect(Collectors.toList()); -+ // Paper start - remove streams -+ this.a = new java.util.ArrayList<>(i); // queues -+ for (int j = 0; j < i; ++j) { -+ this.getQueues().add(Queues.newConcurrentLinkedQueue()); -+ } -+ // Paper end - remove streams - } - - @Nullable - @Override - public Runnable a() { -- Iterator iterator = this.a.iterator(); -- -- Runnable runnable; -- -- do { -- if (!iterator.hasNext()) { -- return null; -+ // Paper start - remove iterator creation -+ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { -+ Queue queue = this.getQueues().get(i); -+ Runnable ret = queue.poll(); -+ if (ret != null) { -+ return ret; - } -- -- Queue queue = (Queue) iterator.next(); -- -- runnable = (Runnable) queue.poll(); -- } while (runnable == null); -- -- return runnable; -+ } -+ return null; -+ // Paper end - remove iterator creation - } - - public boolean a(PairedQueue.b pairedqueue_b) { -@@ -57,7 +55,16 @@ public interface PairedQueue { - - @Override - public boolean b() { -- return this.a.stream().allMatch(Collection::isEmpty); -+ // Paper start - remove streams -+ // why are we doing streams every time we might want to execute a task? -+ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { -+ Queue queue = this.getQueues().get(i); -+ if (!queue.isEmpty()) { -+ return false; -+ } -+ } -+ return true; -+ // Paper end - remove streams - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch b/Unmapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch deleted file mode 100644 index a8f074ccde..0000000000 --- a/Unmapped-Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 17:39:25 -0700 -Subject: [PATCH] Reduce memory footprint of NBTTagCompound - -Fastutil maps are going to have a lower memory footprint - which -is important because we clone chunk data after reading it for safety. -So, reduce the impact of the clone on GC. - -diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -index d5508deff819309034554abc7b36aac40fa33503..77afbaad5b2cb8d912f5404fcbd3a0970490f4f3 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -@@ -26,6 +26,7 @@ import net.minecraft.ReportedException; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.chat.IChatMutableComponent; -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -47,7 +48,7 @@ public class NBTTagCompound implements NBTBase { - if (i > 512) { - throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512"); - } else { -- HashMap hashmap = Maps.newHashMap(); -+ Object2ObjectOpenHashMap hashmap = new Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound - - byte b0; - -@@ -83,7 +84,7 @@ public class NBTTagCompound implements NBTBase { - } - - public NBTTagCompound() { -- this(Maps.newHashMap()); -+ this(new Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - reduce memory footprint of NBTTagCompound - } - - @Override -@@ -417,9 +418,17 @@ public class NBTTagCompound implements NBTBase { - - @Override - public NBTTagCompound clone() { -- Map map = Maps.newHashMap(Maps.transformValues(this.map, NBTBase::clone)); -+ // Paper start - reduce memory footprint of NBTTagCompound -+ Object2ObjectOpenHashMap ret = new Object2ObjectOpenHashMap<>(this.map.size(), 0.8f); - -- return new NBTTagCompound(map); -+ Iterator> iterator = (this.map instanceof Object2ObjectOpenHashMap) ? ((Object2ObjectOpenHashMap)this.map).object2ObjectEntrySet().fastIterator() : this.map.entrySet().iterator(); -+ while (iterator.hasNext()) { -+ Map.Entry entry = iterator.next(); -+ ret.put(entry.getKey(), entry.getValue().clone()); -+ } -+ -+ return new NBTTagCompound(ret); -+ // Paper end - reduce memory footprint of NBTTagCompound - } - - public boolean equals(Object object) { diff --git a/Unmapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch b/Unmapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch deleted file mode 100644 index b2d315bd4f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 13 Apr 2020 07:31:44 +0100 -Subject: [PATCH] Prevent opening inventories when frozen - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 79003f43c4f15a7e5dd51587bc8c2f477bedb1b2..5382dfbad7a33670268d5d713cf3bdd425bbe885 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -560,7 +560,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - containerUpdateDelay = world.paperConfig.containerUpdateTickRate; - } - // Paper end -- if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { -+ if (!this.world.isClientSide && this.activeContainer != this.defaultContainer && (isFrozen() || !this.activeContainer.canUse(this))) { // Paper - auto close while frozen - this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.activeContainer = this.defaultContainer; - } -@@ -1407,7 +1407,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } else { - // CraftBukkit start - this.activeContainer = container; -- this.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, container.getType(), container.getTitle())); -+ if (!isFrozen()) this.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, container.getType(), container.getTitle())); // Paper - // CraftBukkit end - container.addSlotListener(this); - return OptionalInt.of(this.containerCounter); -@@ -2209,7 +2209,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - @Override -- protected boolean isFrozen() { -+ public boolean isFrozen() { // Paper - protected > public - return super.isFrozen() || (this.playerConnection != null && this.playerConnection.isDisconnected()); // Paper - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 3b3e6076f2565e02fa6f13e369094f8b6cac5382..3bfb93890259210afd2f5e226cef100d26a11628 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -324,7 +324,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper - - //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper -+ if (!player.isFrozen()) player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - getHandle().activeContainer = container; - getHandle().activeContainer.addSlotListener(player); - } -@@ -398,7 +398,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper - if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper - //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper -+ if (!player.isFrozen()) player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - player.activeContainer = container; - player.activeContainer.addSlotListener(player); - } diff --git a/Unmapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch b/Unmapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch deleted file mode 100644 index 1ff7b9b2f9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Apr 2020 18:23:28 -0700 -Subject: [PATCH] Optimise ArraySetSorted#removeIf - -Remove iterator allocation and ensure the call is always O(n) - -diff --git a/src/main/java/net/minecraft/util/ArraySetSorted.java b/src/main/java/net/minecraft/util/ArraySetSorted.java -index 427daa94322f47b4eaf881d85a01fed239db549a..936a90272579f78832eff93f2a81d673feb669c1 100644 ---- a/src/main/java/net/minecraft/util/ArraySetSorted.java -+++ b/src/main/java/net/minecraft/util/ArraySetSorted.java -@@ -10,8 +10,8 @@ import java.util.NoSuchElementException; - public class ArraySetSorted extends AbstractSet { - - private final Comparator a; -- private T[] b; -- private int c; -+ private T[] b; private final T[] getBackingArray() { return this.b; } // Paper - OBFHELPER -+ private int c; private final int getSize() { return this.c; } private final void setSize(int value) { this.c = value; } // Paper - OBFHELPER - - private ArraySetSorted(int i, Comparator comparator) { - this.a = comparator; -@@ -22,6 +22,42 @@ public class ArraySetSorted extends AbstractSet { - } - } - -+ // Paper start - optimise removeIf -+ @Override -+ public boolean removeIf(java.util.function.Predicate filter) { -+ // prev. impl used an iterator, which could be n^2 and creates garbage -+ int i = 0, len = this.getSize(); -+ T[] backingArray = this.getBackingArray(); -+ -+ for (;;) { -+ if (i >= len) { -+ return false; -+ } -+ if (!filter.test(backingArray[i])) { -+ ++i; -+ continue; -+ } -+ break; -+ } -+ -+ // we only want to write back to backingArray if we really need to -+ -+ int lastIndex = i; // this is where new elements are shifted to -+ -+ for (; i < len; ++i) { -+ T curr = backingArray[i]; -+ if (!filter.test(curr)) { // if test throws we're screwed -+ backingArray[lastIndex++] = curr; -+ } -+ } -+ -+ // cleanup end -+ Arrays.fill(backingArray, lastIndex, len, null); -+ this.setSize(lastIndex); -+ return true; -+ } -+ // Paper end - optimise removeIf -+ - public static > ArraySetSorted a(int i) { - return new ArraySetSorted<>(i, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix - } diff --git a/Unmapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch b/Unmapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch deleted file mode 100644 index 5e3b27cf93..0000000000 --- a/Unmapped-Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Apr 2020 17:56:07 -0700 -Subject: [PATCH] Don't run entity collision code if not needed - -Will not run if max entity craming is disabled and -the max collisions per entity is less than or equal to 0 - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 571e6bced3cfaacbd40378e67b01cdfda550feb7..40fb7e96af7bbbe6c5586fa4d2a629b5a8f7b07a 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -2944,10 +2944,16 @@ public abstract class EntityLiving extends Entity { - protected void doTick() {} - - protected void collideNearby() { -+ // Paper - start don't run getEntities if we're not going to use its result -+ int i = this.world.getGameRules().getInt(GameRules.MAX_ENTITY_CRAMMING); -+ if (i <= 0 && world.paperConfig.maxCollisionsPerEntity <= 0) { -+ return; -+ } -+ // Paper - end don't run getEntities if we're not going to use its result - List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.a(this)); - - if (!list.isEmpty()) { -- int i = this.world.getGameRules().getInt(GameRules.MAX_ENTITY_CRAMMING); -+ // Paper - move up - int j; - - if (i > 0 && list.size() > i - 1 && this.random.nextInt(4) == 0) { diff --git a/Unmapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch b/Unmapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch deleted file mode 100644 index f9bae9ab71..0000000000 --- a/Unmapped-Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 16 Apr 2020 16:13:59 -0700 -Subject: [PATCH] Optimize ChunkProviderServer's chunk level checking helper - methods - -These can be hot functions (i.e entity ticking and block ticking), -so inline where possible, and avoid the abstraction of the -Either class. - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 48d0c37a1d7df9b7ac8077e1e82420566dc42718..d8355caf6f86e0bb8c16ad0b58b81d7926bc7bff 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -643,21 +643,29 @@ public class ChunkProviderServer extends IChunkProvider { - - public final boolean isInEntityTickingChunk(Entity entity) { return this.a(entity); } // Paper - OBFHELPER - @Override public boolean a(Entity entity) { -- long i = ChunkCoordIntPair.pair(MathHelper.floor(entity.locX()) >> 4, MathHelper.floor(entity.locZ()) >> 4); -- -- return this.a(i, (Function>>) PlayerChunk::b); // CraftBukkit - decompile error -+ // Paper start - optimize is ticking ready type functions -+ // entity ticking -+ PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(entity)); -+ return playerChunk != null && playerChunk.isEntityTickingReady(); -+ // Paper end - optimize is ticking ready type functions - } - - public final boolean isEntityTickingChunk(ChunkCoordIntPair chunkcoordintpair) { return this.a(chunkcoordintpair); } // Paper - OBFHELPER - @Override public boolean a(ChunkCoordIntPair chunkcoordintpair) { -- return this.a(chunkcoordintpair.pair(), (Function>>) PlayerChunk::b); // CraftBukkit - decompile error -+ // Paper start - optimize is ticking ready type functions -+ // is entity ticking ready -+ PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(chunkcoordintpair)); -+ return playerChunk != null && playerChunk.isEntityTickingReady(); -+ // Paper end - optimize is ticking ready type functions - } - - @Override - public boolean a(BlockPosition blockposition) { -- long i = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4); -- -- return this.a(i, (Function>>) PlayerChunk::a); // CraftBukkit - decompile error -+ // Paper start - optimize is ticking ready type functions -+ // is ticking ready -+ PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(blockposition)); -+ return playerChunk != null && playerChunk.isTickingReady(); -+ // Paper end - optimize is ticking ready type functions - } - - private boolean a(long i, Function>> function) { diff --git a/Unmapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch b/Unmapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch deleted file mode 100644 index ed7ce57a14..0000000000 --- a/Unmapped-Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 16 Apr 2020 20:07:29 -0500 -Subject: [PATCH] Restrict vanilla teleport command to valid locations - -Fixes GH-3165, GH-3575 - -diff --git a/src/main/java/net/minecraft/server/commands/CommandTeleport.java b/src/main/java/net/minecraft/server/commands/CommandTeleport.java -index b59763643def065cd998fa3005523c37973613fd..dcc92b0c9a7a0214a3e803d714c5e7078c17a039 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandTeleport.java -+++ b/src/main/java/net/minecraft/server/commands/CommandTeleport.java -@@ -142,6 +142,12 @@ public class CommandTeleport { - - private static void a(CommandListenerWrapper commandlistenerwrapper, Entity entity, WorldServer worldserver, double d0, double d1, double d2, Set set, float f, float f1, @Nullable CommandTeleport.a commandteleport_a) throws CommandSyntaxException { - BlockPosition blockposition = new BlockPosition(d0, d1, d2); -+ // Paper start - Don't allow teleport command to invalid locations -+ if (d0 <= -30000000 || d2 <= -30000000 || d0 > 30000000 || d2 > 30000000 || d1 > 30000000 || d1 <= -30000000) { // Copy/pasta from BaseBlockPosition#isValidLocation -+ org.bukkit.Bukkit.getLogger().warning("Refused to teleport " + entity.getName() + " to " + d0 + ", " + d1 + ", " + d2); -+ return; -+ } -+ // Paper end - - if (!World.l(blockposition)) { - throw CommandTeleport.a.create(); diff --git a/Unmapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch b/Unmapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch deleted file mode 100644 index 92a17b9c3a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch +++ /dev/null @@ -1,188 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Mon, 20 Jan 2020 21:38:15 +0100 -Subject: [PATCH] Implement Player Client Options API - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperSkinParts.java b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabba57885e1 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java -@@ -0,0 +1,74 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Objects; -+ -+import java.util.StringJoiner; -+ -+public class PaperSkinParts implements SkinParts { -+ -+ private final int raw; -+ -+ public PaperSkinParts(int raw) { -+ this.raw = raw; -+ } -+ -+ public boolean hasCapeEnabled() { -+ return (raw & 1) == 1; -+ } -+ -+ public boolean hasJacketEnabled() { -+ return (raw >> 1 & 1) == 1; -+ } -+ -+ public boolean hasLeftSleeveEnabled() { -+ return (raw >> 2 & 1) == 1; -+ } -+ -+ public boolean hasRightSleeveEnabled() { -+ return (raw >> 3 & 1) == 1; -+ } -+ -+ public boolean hasLeftPantsEnabled() { -+ return (raw >> 4 & 1) == 1; -+ } -+ -+ public boolean hasRightPantsEnabled() { -+ return (raw >> 5 & 1) == 1; -+ } -+ -+ public boolean hasHatsEnabled() { -+ return (raw >> 6 & 1) == 1; -+ } -+ -+ @Override -+ public int getRaw() { -+ return raw; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ PaperSkinParts that = (PaperSkinParts) o; -+ return raw == that.raw; -+ } -+ -+ @Override -+ public int hashCode() { -+ return Objects.hashCode(raw); -+ } -+ -+ @Override -+ public String toString() { -+ return new StringJoiner(", ", PaperSkinParts.class.getSimpleName() + "[", "]") -+ .add("raw=" + raw) -+ .add("cape=" + hasCapeEnabled()) -+ .add("jacket=" + hasJacketEnabled()) -+ .add("leftSleeve=" + hasLeftSleeveEnabled()) -+ .add("rightSleeve=" + hasRightSleeveEnabled()) -+ .add("leftPants=" + hasLeftPantsEnabled()) -+ .add("rightPants=" + hasRightPantsEnabled()) -+ .add("hats=" + hasHatsEnabled()) -+ .toString(); -+ } -+} -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java -index 90842b27f64afcdd8eb7d0e52df8cfcb418b5b5a..f47cd43f96f61475bd1d5da11bdbc7c5e5f7e1bc 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java -@@ -41,14 +41,17 @@ public class PacketPlayInSettings implements Packet { - packetlistenerplayin.a(this); - } - -+ public EnumChatVisibility getChatVisibility() { return d(); } // Paper - OBFHELPER - public EnumChatVisibility d() { - return this.c; - } - -+ public boolean hasChatColorsEnabled() { return e(); } // Paper - OBFHELPER - public boolean e() { - return this.d; - } - -+ public int getSkinParts() { return f(); } // Paper - OBFHELPER - public int f() { - return this.e; - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 5382dfbad7a33670268d5d713cf3bdd425bbe885..ff0913941a888ab529d7a4dd1b160fe9659b25cb 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -2,6 +2,7 @@ package net.minecraft.server.level; - - import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent; - import com.google.common.collect.Lists; -+import com.destroystokyo.paper.event.player.PlayerClientOptionsChangeEvent; // Paper - import com.mojang.authlib.GameProfile; - import com.mojang.datafixers.util.Either; - import com.mojang.serialization.DataResult; -@@ -191,7 +192,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public int lastSentExp = -99999999; - public int invulnerableTicks = 60; - private EnumChatVisibility bY; -- private boolean bZ = true; -+ private boolean bZ = true; public boolean hasChatColorsEnabled() { return this.bZ; } // Paper - OBFHELPER - private long ca = SystemUtils.getMonotonicMillis(); - private Entity spectatedEntity; - public boolean worldChangeInvuln; -@@ -1810,6 +1811,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null - public java.util.Locale adventure$locale = java.util.Locale.US; // Paper - public void a(PacketPlayInSettings packetplayinsettings) { -+ new PlayerClientOptionsChangeEvent(getBukkitEntity(), packetplayinsettings.locale, packetplayinsettings.viewDistance, com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(packetplayinsettings.getChatVisibility().name()), packetplayinsettings.hasChatColorsEnabled(), new com.destroystokyo.paper.PaperSkinParts(packetplayinsettings.getSkinParts()), packetplayinsettings.getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT).callEvent(); // Paper - settings event - // CraftBukkit start - if (getMainHand() != packetplayinsettings.getMainHand()) { - PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 8981dfacd10cae9de052e1b36ce5181cd0e6752d..202fa94d5dc55b549475ae0309bbcfca8f1b2c96 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -133,7 +133,7 @@ public abstract class EntityHuman extends EntityLiving { - private static final Map b = ImmutableMap.builder().put(EntityPose.STANDING, EntityHuman.bh).put(EntityPose.SLEEPING, EntityHuman.ah).put(EntityPose.FALL_FLYING, EntitySize.b(0.6F, 0.6F)).put(EntityPose.SWIMMING, EntitySize.b(0.6F, 0.6F)).put(EntityPose.SPIN_ATTACK, EntitySize.b(0.6F, 0.6F)).put(EntityPose.CROUCHING, EntitySize.b(0.6F, 1.5F)).put(EntityPose.DYING, EntitySize.c(0.2F, 0.2F)).build(); - private static final DataWatcherObject c = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.c); - private static final DataWatcherObject d = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.b); -- protected static final DataWatcherObject bi = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); -+ protected static final DataWatcherObject bi = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); public static DataWatcherObject getSkinPartsWatcher() { return bi; } // Paper - OBFHELPER - protected static final DataWatcherObject bj = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); - protected static final DataWatcherObject bk = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.p); - protected static final DataWatcherObject bl = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.p); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index dc8545241ed62f6b654b2559e025c3b34c00575f..935b5668a81db4d19a08b09c61519114532a23d9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1,5 +1,8 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.ClientOption.ChatVisibility; -+import com.destroystokyo.paper.PaperSkinParts; -+import com.destroystokyo.paper.ClientOption; - import com.destroystokyo.paper.Title; - import com.google.common.base.Preconditions; - import com.google.common.collect.ImmutableSet; -@@ -2253,6 +2256,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public void setViewDistance(int viewDistance) { - throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO - } -+ -+ @Override -+ public T getClientOption(ClientOption type) { -+ if(ClientOption.SKIN_PARTS.equals(type)) { -+ return type.getType().cast(new PaperSkinParts(getHandle().getDataWatcher().get(EntityHuman.getSkinPartsWatcher()))); -+ } else if(ClientOption.CHAT_COLORS_ENABLED.equals(type)) { -+ return type.getType().cast(getHandle().hasChatColorsEnabled()); -+ } else if(ClientOption.CHAT_VISIBILITY.equals(type)) { -+ return type.getType().cast(getHandle().getChatFlags() == null ? ChatVisibility.UNKNOWN : ChatVisibility.valueOf(getHandle().getChatFlags().name())); -+ } else if(ClientOption.LOCALE.equals(type)) { -+ return type.getType().cast(getLocale()); -+ } else if(ClientOption.MAIN_HAND.equals(type)) { -+ return type.getType().cast(getMainHand()); -+ } else if(ClientOption.VIEW_DISTANCE.equals(type)) { -+ return type.getType().cast(getClientViewDistance()); -+ } -+ throw new RuntimeException("Unknown settings type"); -+ } - // Paper end - - // Spigot start diff --git a/Unmapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch b/Unmapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch deleted file mode 100644 index 54424991d0..0000000000 --- a/Unmapped-Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Apr 2020 04:36:11 -0400 -Subject: [PATCH] Fix Chunk Post Processing deadlock risk - -See: https://gist.github.com/aikar/dd22bbd2a3d78a2fd3d92e95e9f28dc6 - -as part of post processing a chunk, we can call ChunkConverter. - -ChunkConverter then kicks off major physics updates, and when blocks -that have connections across chunk boundries occur, a recursive risk -can occur where A updates a block that triggers a physics request. - -That physics request may trigger a chunk request, that then enqueues -a task into the Mailbox ChunkTaskQueueSorter. - -If anything requests that same chunk that is in the middle of conversion, -it's mailbox queue is going to be held up, so the subsequent chunk request -will be unable to proceed. - -We delay post processing of Chunk.A() 1 "pass" by re stuffing it back into -the executor so that the mailbox ChunkQueue is now considered empty. - -This successfully fixed a reoccurring and highly reproduceable crash -for heightmaps. - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index d8355caf6f86e0bb8c16ad0b58b81d7926bc7bff..cb098defa7b93864294befa9b9a427804461188b 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -1021,6 +1021,7 @@ public class ChunkProviderServer extends IChunkProvider { - return super.executeNext() || execChunkTask; // Paper - } - } finally { -+ playerChunkMap.chunkLoadConversionCallbackExecutor.run(); // Paper - Add chunk load conversion callback executor to prevent deadlock due to recursion in the chunk task queue sorter - playerChunkMap.callbackExecutor.run(); - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index b00c5a7eaf456e6d6ce250ee790ce33dfa9bb496..6279846a92489b5dade21ad55a1bec1157073e27 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -183,6 +183,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }; - // CraftBukkit end - -+ final CallbackExecutor chunkLoadConversionCallbackExecutor = new CallbackExecutor(); // Paper -+ - // Paper start - distance maps - private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); - -@@ -1056,7 +1058,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return Either.left(chunk); - }); - }, (runnable) -> { -- this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); -+ this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, () -> PlayerChunkMap.this.chunkLoadConversionCallbackExecutor.execute(runnable))); // Paper - delay running Chunk post processing until outside of the sorter to prevent a deadlock scenario when post processing causes another chunk request. - }); - - completablefuture1.thenAcceptAsync((either) -> { diff --git a/Unmapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/Unmapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch deleted file mode 100644 index 83e1af8a9c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Apr 2020 15:59:41 -0400 -Subject: [PATCH] Don't crash if player is attempted to be removed from - untracked chunk. - -I suspect it deals with teleporting as it uses players current x/y/z - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 961257ebc28a8b4753faf3c2d5b6abaea4ffc0dd..60fcea78bf617559114b1ca1c0bf2d4cd9075a8c 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -245,8 +245,8 @@ public abstract class ChunkMapDistance { - ObjectSet objectset = (ObjectSet) this.c.get(i); - if (objectset == null) return; // CraftBukkit - SPIGOT-6208 - -- objectset.remove(entityplayer); -- if (objectset.isEmpty()) { -+ if (objectset != null) objectset.remove(entityplayer); // Paper - some state corruption happens here, don't crash, clean up gracefully. -+ if (objectset == null || objectset.isEmpty()) { // Paper - this.c.remove(i); - this.f.update(i, Integer.MAX_VALUE, false); - this.g.update(i, Integer.MAX_VALUE, false); diff --git a/Unmapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch b/Unmapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch deleted file mode 100644 index 6ffc693706..0000000000 --- a/Unmapped-Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AvrooVulcan -Date: Fri, 17 Apr 2020 00:15:23 +0100 -Subject: [PATCH] Broadcast join message to console - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 9eec320ca5a63a313138dc84367e93038b457c0d..7d336c23a57c06c3744ae5b187960da798dd07c8 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -288,7 +288,9 @@ public abstract class PlayerList { - - if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure - joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure -- server.getPlayerList().sendAll(new PacketPlayOutChat(joinMessage, ChatMessageType.SYSTEM, SystemUtils.b)); // Paper - Adventure -+ // Paper start - Removed sendAll for loop and broadcasted to console also -+ server.getPlayerList().sendMessage(joinMessage); // Paper - Adventure -+ // Paper end - } - // CraftBukkit end - diff --git a/Unmapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/Unmapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch deleted file mode 100644 index d064811c32..0000000000 --- a/Unmapped-Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 00:05:46 -0400 -Subject: [PATCH] Fix Longstanding Broken behavior of PlayerJoinEvent - -For years, plugin developers have had to delay many things they do -inside of the PlayerJoinEvent by 1 tick to make it actually work. - -This all boiled down to 1 reason why: The event fired before the -player was fully ready and joined to the world! - -Additionally, if that player logged out on a vehicle, the event -fired before the vehicle was even loaded, so that plugins had no -access to the vehicle during this event either. - -This change finally fixes this issue, fully preparing the player -into the world as a fully ready entity, vehicle included. - -There should be no plugins that break because of this change, but might -improve consistency with other plugins instead. - -For example, if 2 plugins listens to this event, and the first one -teleported the player in the event, then the 2nd plugin actually -would be getting a valid player! - -This was very non deterministic. This change will ensure every plugin -receives a deterministic result, and should no longer require 1 tick -delays anymore. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index ff0913941a888ab529d7a4dd1b160fe9659b25cb..505cb0eb74d45906132e78c5cf8741dc5fd4eaf0 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -240,6 +240,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public double maxHealthCache; - public boolean joining = true; - public boolean sentListPacket = false; -+ public boolean supressTrackerForLogin = false; // Paper - public Integer clientViewDistance; - // CraftBukkit end - public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 6279846a92489b5dade21ad55a1bec1157073e27..86cb1f33cd5269ff271129ceedd3a3a8532fa6eb 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1586,7 +1586,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }); - } - -- protected void addEntity(Entity entity) { -+ public void addEntity(Entity entity) { // Paper - protected -> public - org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot - // Paper start - ignore and warn about illegal addEntity calls instead of crashing server - if (!entity.valid || entity.world != this.world || this.trackedEntities.containsKey(entity.getId())) { -@@ -1595,6 +1595,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - .printStackTrace(); - return; - } -+ if (entity instanceof EntityPlayer && ((EntityPlayer) entity).supressTrackerForLogin) return; // Delay adding to tracker until after list packets - // Paper end - if (!(entity instanceof EntityComplexPart)) { - EntityTypes entitytypes = entity.getEntityType(); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7d336c23a57c06c3744ae5b187960da798dd07c8..66c1a9ca392b29fe2191577d32c70b214fa7293d 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -276,6 +276,12 @@ public abstract class PlayerList { - this.j.put(entityplayer.getUniqueID(), entityplayer); - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below - -+ // Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks -+ entityplayer.supressTrackerForLogin = true; -+ worldserver1.addPlayerJoin(entityplayer); -+ this.server.getBossBattleCustomData().a(entityplayer); // see commented out section below worldserver.addPlayerJoin(entityplayer); -+ mountSavedVehicle(entityplayer, worldserver1, nbttagcompound); -+ // Paper end - // CraftBukkit start - PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - cserver.getPluginManager().callEvent(playerJoinEvent); -@@ -311,6 +317,8 @@ public abstract class PlayerList { - entityplayer.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[] { entityplayer1})); - } - entityplayer.sentListPacket = true; -+ entityplayer.supressTrackerForLogin = false; // Paper -+ ((WorldServer)entityplayer.world).getChunkProvider().playerChunkMap.addEntity(entityplayer); // Paper - track entity now - // CraftBukkit end - - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityMetadata(entityplayer.getId(), entityplayer.getDataWatcher(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn -@@ -336,6 +344,11 @@ public abstract class PlayerList { - playerconnection.sendPacket(new PacketPlayOutEntityEffect(entityplayer.getId(), mobeffect)); - } - -+ // Paper start - move vehicle into method so it can be called above - short circuit around that code -+ onPlayerJoinFinish(entityplayer, worldserver1, s1); -+ } -+ private void mountSavedVehicle(EntityPlayer entityplayer, WorldServer worldserver1, NBTTagCompound nbttagcompound) { -+ // Paper end - if (nbttagcompound != null && nbttagcompound.hasKeyOfType("RootVehicle", 10)) { - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); - // CraftBukkit start -@@ -384,6 +397,10 @@ public abstract class PlayerList { - } - } - -+ // Paper start -+ } -+ public void onPlayerJoinFinish(EntityPlayer entityplayer, WorldServer worldserver1, String s1) { -+ // Paper end - entityplayer.syncInventory(); - // Paper start - Add to collideRule team if needed - final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); diff --git a/Unmapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch b/Unmapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch deleted file mode 100644 index 8a2ef5272c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch +++ /dev/null @@ -1,306 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 04:28:29 -0400 -Subject: [PATCH] Load Chunks for Login Asynchronously - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index cb098defa7b93864294befa9b9a427804461188b..fc7140e0eb11e4bec99e453647fce200bca0ed7f 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -629,7 +629,7 @@ public class ChunkProviderServer extends IChunkProvider { - return this.serverThreadQueue.executeNext(); - } - -- private boolean tickDistanceManager() { -+ public boolean tickDistanceManager() { // Paper - private -> public - boolean flag = this.chunkMapDistance.a(this.playerChunkMap); - boolean flag1 = this.playerChunkMap.b(); - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 505cb0eb74d45906132e78c5cf8741dc5fd4eaf0..39fb3a1445338c3ac1642b8e518eb8d1031f9a5c 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -31,6 +31,7 @@ import net.minecraft.core.NonNullList; - import net.minecraft.core.SectionPosition; - import net.minecraft.nbt.DynamicOpsNBT; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.network.NetworkManager; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.ChatHoverable; - import net.minecraft.network.chat.ChatMessage; -@@ -175,6 +176,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - private static final Logger LOGGER = LogManager.getLogger(); - public PlayerConnection playerConnection; -+ public NetworkManager networkManager; // Paper - public final MinecraftServer server; - public final PlayerInteractManager playerInteractManager; - public final Deque removeQueue = new ArrayDeque<>(); // Paper -@@ -241,6 +243,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean joining = true; - public boolean sentListPacket = false; - public boolean supressTrackerForLogin = false; // Paper -+ public boolean didPlayerJoinEvent = false; // Paper - public Integer clientViewDistance; - // CraftBukkit end - public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 86cb1f33cd5269ff271129ceedd3a3a8532fa6eb..6e4a47581843be42b77034fec16b1d531a5b5759 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -147,7 +147,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final Mailbox> mailboxWorldGen; - private final Mailbox> mailboxMain; - public final WorldLoadListener worldLoadListener; -- public final PlayerChunkMap.a chunkDistanceManager; -+ public final PlayerChunkMap.a chunkDistanceManager; public final ChunkMapDistance getChunkDistanceManager() { return this.chunkDistanceManager; } // Paper - OBFHELPER - private final AtomicInteger u; - public final DefinedStructureManager definedStructureManager; // Paper - private -> public - private final File w; -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 218dc900e125a11548485887b1918742072c7a77..2c932d36f982e7f8713aabff9a6c631055810366 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -21,6 +21,7 @@ public class TicketType { - public static final TicketType FORCED = a("forced", Comparator.comparingLong(ChunkCoordIntPair::pair)); - public static final TicketType LIGHT = a("light", Comparator.comparingLong(ChunkCoordIntPair::pair)); - public static final TicketType PORTAL = a("portal", BaseBlockPosition::compareTo, 300); -+ public static final TicketType LOGIN = a("login", Long::compareTo, 100); // Paper - public static final TicketType POST_TELEPORT = a("post_teleport", Integer::compareTo, 5); - public static final TicketType UNKNOWN = a("unknown", Comparator.comparingLong(ChunkCoordIntPair::pair), 1); - public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 2e995103fba15c21dbe89321896c7df03ae5e67b..ef2aa000932c222e358789fcd2629dd8a46cfe80 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -88,7 +88,7 @@ public class LoginListener implements PacketLoginInListener { - } - // Paper end - } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { -- EntityPlayer entityplayer = this.server.getPlayerList().getPlayer(this.i.getId()); -+ EntityPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.i.getId()); // Paper - - if (entityplayer == null) { - this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT; -@@ -188,7 +188,7 @@ public class LoginListener implements PacketLoginInListener { - } - - this.networkManager.sendPacket(new PacketLoginOutSuccess(this.i)); -- EntityPlayer entityplayer = this.server.getPlayerList().getPlayer(this.i.getId()); -+ EntityPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.i.getId()); // Paper - - if (entityplayer != null) { - this.g = LoginListener.EnumProtocolState.DELAY_ACCEPT; -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 8a8f75acdd55e00ac2e7b5c621d1f522208df2c2..7c1d25feab71c325ce2379afa6c61732eebd74f9 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -222,6 +222,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - private static final Logger LOGGER = LogManager.getLogger(); - public final NetworkManager networkManager; - private final MinecraftServer minecraftServer; -+ public Runnable playerJoinReady; // Paper - public EntityPlayer player; - private int e; - private long lastKeepAlive = SystemUtils.getMonotonicMillis(); private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER -@@ -300,6 +301,15 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - - public void tick() { -+ // Paper start - login async -+ Runnable playerJoinReady = this.playerJoinReady; -+ if (playerJoinReady != null) { -+ this.playerJoinReady = null; -+ playerJoinReady.run(); -+ } -+ // Don't tick if not valid (dead), otherwise we load chunks below -+ if (this.player.valid) { -+ // Paper end - this.syncPosition(); - this.player.lastX = this.player.locX(); - this.player.lastY = this.player.locY(); -@@ -341,7 +351,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.r = null; - this.D = false; - this.E = 0; -- } -+ }} // Paper - end if (valid) - - this.minecraftServer.getMethodProfiler().enter("keepAlive"); - // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 66c1a9ca392b29fe2191577d32c70b214fa7293d..c7e78d0626fa0dd18021c1a0827a10c08ab10b4a 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -41,6 +41,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutEntityStatus; - import net.minecraft.network.protocol.game.PacketPlayOutExperience; - import net.minecraft.network.protocol.game.PacketPlayOutGameStateChange; - import net.minecraft.network.protocol.game.PacketPlayOutHeldItemSlot; -+import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; - import net.minecraft.network.protocol.game.PacketPlayOutLogin; - import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo; -@@ -60,6 +61,8 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.server.ScoreboardServer; - import net.minecraft.server.level.DemoPlayerInteractManager; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.PlayerInteractManager; - import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; -@@ -128,11 +131,12 @@ public abstract class PlayerList { - private static final SimpleDateFormat g = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); - private final MinecraftServer server; - public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety -- private final Map j = Maps.newHashMap(); -+ private final Map j = Maps.newHashMap();Map getUUIDMap() { return j; } // Paper - OBFHELPER - private final GameProfileBanList k; - private final IpBanList l; - private final OpList operators; - private final WhiteList whitelist; -+ private final Map pendingPlayers = Maps.newHashMap(); // Paper - // CraftBukkit start - // private final Map o; - // private final Map p; -@@ -171,6 +175,11 @@ public abstract class PlayerList { - } - - public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { -+ EntityPlayer prev = pendingPlayers.put(entityplayer.getUniqueID(), entityplayer);// Paper -+ if (prev != null) { -+ disconnectPendingPlayer(prev); -+ } -+ entityplayer.networkManager = networkmanager; // Paper - entityplayer.loginTime = System.currentTimeMillis(); // Paper - GameProfile gameprofile = entityplayer.getProfile(); - UserCache usercache = this.server.getUserCache(); -@@ -184,7 +193,7 @@ public abstract class PlayerList { - if (nbttagcompound != null && nbttagcompound.hasKey("bukkit")) { - NBTTagCompound bukkit = nbttagcompound.getCompound("bukkit"); - s = bukkit.hasKeyOfType("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; -- } -+ }String lastKnownName = s; // Paper - // CraftBukkit end - - if (nbttagcompound != null) { -@@ -259,6 +268,51 @@ public abstract class PlayerList { - entityplayer.getRecipeBook().a(entityplayer); - this.sendScoreboard(worldserver1.getScoreboard(), entityplayer); - this.server.invalidatePingSample(); -+ // Paper start - async load spawn in chunk -+ WorldServer finalWorldserver = worldserver1; -+ int chunkX = loc.getBlockX() >> 4; -+ int chunkZ = loc.getBlockZ() >> 4; -+ final ChunkCoordIntPair pos = new ChunkCoordIntPair(chunkX, chunkZ); -+ PlayerChunkMap playerChunkMap = worldserver1.getChunkProvider().playerChunkMap; -+ playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.pair()); -+ worldserver1.getChunkProvider().tickDistanceManager(); -+ worldserver1.getChunkProvider().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { -+ PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pos.pair()); -+ if (updatingChunk != null) { -+ return updatingChunk.getEntityTickingFuture(); -+ } else { -+ return java.util.concurrent.CompletableFuture.completedFuture(chunk); -+ } -+ }).thenAccept(chunk -> { -+ playerconnection.playerJoinReady = () -> { -+ postChunkLoadJoin( -+ entityplayer, finalWorldserver, networkmanager, playerconnection, -+ nbttagcompound, networkmanager.getSocketAddress().toString(), lastKnownName -+ ); -+ }; -+ }); -+ } -+ -+ public EntityPlayer getActivePlayer(UUID uuid) { -+ EntityPlayer player = this.getUUIDMap().get(uuid); -+ return player != null ? player : pendingPlayers.get(uuid); -+ } -+ -+ void disconnectPendingPlayer(EntityPlayer entityplayer) { -+ ChatMessage msg = new ChatMessage("multiplayer.disconnect.duplicate_login", new Object[0]); -+ entityplayer.networkManager.sendPacket(new PacketPlayOutKickDisconnect(msg), (future) -> { -+ entityplayer.networkManager.close(msg); -+ entityplayer.networkManager = null; -+ }); -+ } -+ -+ private void postChunkLoadJoin(EntityPlayer entityplayer, WorldServer worldserver1, NetworkManager networkmanager, PlayerConnection playerconnection, NBTTagCompound nbttagcompound, String s1, String s) { -+ pendingPlayers.remove(entityplayer.getUniqueID(), entityplayer); -+ if (!networkmanager.isConnected()) { -+ return; -+ } -+ entityplayer.didPlayerJoinEvent = true; -+ // Paper end - ChatMessage chatmessage; - - if (entityplayer.getProfile().getName().equalsIgnoreCase(s)) { -@@ -496,6 +550,7 @@ public abstract class PlayerList { - - protected void savePlayerFile(EntityPlayer entityplayer) { - if (!entityplayer.getBukkitEntity().isPersistent()) return; // CraftBukkit -+ if (!entityplayer.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) - this.playerFileData.save(entityplayer); - ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) entityplayer.getStatisticManager(); // CraftBukkit - -@@ -523,7 +578,7 @@ public abstract class PlayerList { - } - - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); -- cserver.getPluginManager().callEvent(playerQuitEvent); -+ if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - - if (server.isMainThread()) entityplayer.playerTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) -@@ -576,6 +631,13 @@ public abstract class PlayerList { - // this.p.remove(uuid); - // CraftBukkit end - } -+ // Paper start -+ entityplayer1 = pendingPlayers.get(uuid); -+ if (entityplayer1 == entityplayer) { -+ pendingPlayers.remove(uuid); -+ } -+ entityplayer.networkManager = null; -+ // Paper end - - // CraftBukkit start - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[]{entityplayer})); -@@ -593,7 +655,7 @@ public abstract class PlayerList { - cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); - // CraftBukkit end - -- return playerQuitEvent.quitMessage(); // Paper - Adventure -+ return entityplayer.didPlayerJoinEvent ? playerQuitEvent.quitMessage() : null; // CraftBukkit // Paper - Adventure // Paper - don't print quit if we never printed join - } - - // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer -@@ -612,6 +674,13 @@ public abstract class PlayerList { - list.add(entityplayer); - } - } -+ // Paper start - check pending players too -+ entityplayer = pendingPlayers.get(uuid); -+ if (entityplayer != null) { -+ this.pendingPlayers.remove(uuid); -+ disconnectPendingPlayer(entityplayer); -+ } -+ // Paper end - - Iterator iterator = list.iterator(); - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 6c368921f76fb6eb99dd20dd49d6ba5ac80cdfad..896b4d016de78e98276d7cdf9328d8951572e3be 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1372,7 +1372,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.lastY = d1; - this.lastZ = d4; - this.setPosition(d3, d1, d4); -- world.getChunkAt((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); // CraftBukkit -+ if (valid) world.getChunkAt((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); // CraftBukkit // Paper - } - - public void d(Vec3D vec3d) { diff --git a/Unmapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/Unmapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch deleted file mode 100644 index 49becb3d56..0000000000 --- a/Unmapped-Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: 2277 <38501234+2277@users.noreply.github.com> -Date: Tue, 31 Mar 2020 10:33:55 +0100 -Subject: [PATCH] Move player to spawn point if spawn in unloaded world - -The code following this has better support for null worlds to move -them back to the world spawn. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 896b4d016de78e98276d7cdf9328d8951572e3be..fbd473d39cd71510b5fe8b7a4d34d3b824301f73 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1809,9 +1809,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - bworld = server.getWorld(worldName); - } - -- if (bworld == null) { -- bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld(); -- } -+ // Paper start - Move player to spawn point if spawn in unloaded world -+// if (bworld == null) { -+// bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld(); -+// } -+ // Paper end - Move player to spawn point if spawn in unloaded world - - spawnIn(bworld == null ? null : ((CraftWorld) bworld).getHandle()); - } diff --git a/Unmapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch b/Unmapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch deleted file mode 100644 index c5cfc7c622..0000000000 --- a/Unmapped-Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: nossr50 -Date: Thu, 26 Mar 2020 19:44:50 -0700 -Subject: [PATCH] Add PlayerAttackEntityCooldownResetEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 40fb7e96af7bbbe6c5586fa4d2a629b5a8f7b07a..13896da2194cab683782504291ede6f135ca7279 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -1931,7 +1931,16 @@ public abstract class EntityLiving extends Entity { - - EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, hardHat, blocking, armor, resistance, magic, absorption); - if (damagesource.getEntity() instanceof EntityHuman) { -- ((EntityHuman) damagesource.getEntity()).resetAttackCooldown(); // Moved from EntityHuman in order to make the cooldown reset get called after the damage event is fired -+ // Paper start - PlayerAttackEntityCooldownResetEvent -+ if (damagesource.getEntity() instanceof EntityPlayer) { -+ EntityPlayer player = (EntityPlayer) damagesource.getEntity(); -+ if (new com.destroystokyo.paper.event.player.PlayerAttackEntityCooldownResetEvent(player.getBukkitEntity(), this.getBukkitEntity(), player.getAttackCooldown(0F)).callEvent()) { -+ player.resetAttackCooldown(); -+ } -+ } else { -+ ((EntityHuman) damagesource.getEntity()).resetAttackCooldown(); -+ } -+ // Paper end - } - if (event.isCancelled()) { - return false; diff --git a/Unmapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/Unmapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch deleted file mode 100644 index df3e2c58ef..0000000000 --- a/Unmapped-Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 21 Apr 2020 03:51:53 -0400 -Subject: [PATCH] Allow multiple callbacks to schedule for Callback Executor - -ChunkMapDistance polls multiple entries for pendingChunkUpdates - -Each of these have the potential to move a chunk in and out of -"Loaded" state, which will result in multiple callbacks being -needed within a single tick of ChunkMapDistance - -Use an ArrayDeque to store this Queue - -We make sure to also implement a pattern that is recursion safe too. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 6e4a47581843be42b77034fec16b1d531a5b5759..d509cfd2da99233e5142abd176cc50ccea7c32b6 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -162,24 +162,32 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final CallbackExecutor callbackExecutor = new CallbackExecutor(); - public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { - -- private Runnable queued; -+ // Paper start - replace impl with recursive safe multi entry queue -+ // it's possible to schedule multiple tasks currently, so it's vital we change this impl -+ // If we recurse into the executor again, we will append to another queue, ensuring task order consistency -+ private java.util.ArrayDeque queued = new java.util.ArrayDeque<>(); - - @Override - public void execute(Runnable runnable) { -- if (queued != null) { -- throw new IllegalStateException("Already queued"); -+ if (queued == null) { -+ queued = new java.util.ArrayDeque<>(); - } -- queued = runnable; -+ queued.add(runnable); - } - - @Override - public void run() { -- Runnable task = queued; -+ if (queued == null) { -+ return; -+ } -+ java.util.ArrayDeque queue = queued; - queued = null; -- if (task != null) { -+ Runnable task; -+ while ((task = queue.pollFirst()) != null) { - task.run(); - } - } -+ // Paper end - }; - // CraftBukkit end - diff --git a/Unmapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch b/Unmapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch deleted file mode 100644 index 895675ad80..0000000000 --- a/Unmapped-Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 23 Apr 2020 01:36:39 -0400 -Subject: [PATCH] Don't fire BlockFade on worldgen threads - -Caused a deadlock - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java -index 5ef38414d87fbce453e3ab11579c89a8ff089ae0..e6ea1d29c7f3f4cb6039df0e35c8db94b6f38c3e 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java -@@ -94,6 +94,7 @@ public class BlockFire extends BlockFireAbstract { - @Override - public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { - // CraftBukkit start -+ if (!(generatoraccess instanceof WorldServer)) return this.canPlace(iblockdata, generatoraccess, blockposition) ? (IBlockData) this.a(generatoraccess, blockposition, (Integer) iblockdata.get(BlockFire.AGE)) : Blocks.AIR.getBlockData(); // Paper - don't fire events in world generation - if (!this.canPlace(iblockdata, generatoraccess, blockposition)) { - // Suppress during worldgen - if (!(generatoraccess instanceof World)) { -@@ -109,7 +110,7 @@ public class BlockFire extends BlockFireAbstract { - return blockState.getHandle(); - } - } -- return this.a(generatoraccess, blockposition, (Integer) iblockdata.get(BlockFire.AGE)); -+ return this.a(generatoraccess, blockposition, (Integer) iblockdata.get(BlockFire.AGE)); // Paper - diff on change, see "don't fire events in world generation" - // CraftBukkit end - } - diff --git a/Unmapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch b/Unmapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch deleted file mode 100644 index 68c8e2168d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 25 Apr 2020 15:13:41 -0500 -Subject: [PATCH] Add phantom creative and insomniac controls - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index cd248eb6be663e8be33f2c3c6b06b77b6d5753a4..46ac6d91422423f1e03b86d3efa3241f2599000d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -625,4 +625,11 @@ public class PaperWorldConfig { - private void lightQueueSize() { - lightQueueSize = getInt("light-queue-size", lightQueueSize); - } -+ -+ public boolean phantomIgnoreCreative = true; -+ public boolean phantomOnlyAttackInsomniacs = true; -+ private void phantomSettings() { -+ phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); -+ phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index 1a6f8aec32af85717f5d56e0b00a02cda88ce028..c8d7ea8cfa4945af4a6675172b931a4cc3ca2801 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -3,6 +3,9 @@ package net.minecraft.world.entity; - import com.google.common.base.Predicates; - import java.util.function.Predicate; - import javax.annotation.Nullable; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.stats.StatisticList; -+import net.minecraft.util.MathHelper; - import net.minecraft.world.EnumDifficulty; - import net.minecraft.world.IInventory; - import net.minecraft.world.entity.player.EntityHuman; -@@ -31,6 +34,7 @@ public final class IEntitySelector { - public static final Predicate g = (entity) -> { - return !entity.isSpectator(); - }; -+ public static Predicate isInsomniac = (player) -> MathHelper.clamp(((EntityPlayer) player).getStatisticManager().getStatisticValue(StatisticList.CUSTOM.get(StatisticList.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper - - // Paper start - public static final Predicate affectsSpawning = (entity) -> { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -index 6c498d4345df35a411d155799ac56e47c9c48114..42cf3fa42b73739182d26fbb524ee5b304c799b2 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -@@ -262,6 +262,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - EntityHuman entityhuman = (EntityHuman) iterator.next(); - - if (EntityPhantom.this.a((EntityLiving) entityhuman, PathfinderTargetCondition.a)) { -+ if (!world.paperConfig.phantomOnlyAttackInsomniacs || IEntitySelector.isInsomniac.test(entityhuman)) // Paper - EntityPhantom.this.setGoalTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason - return true; - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -index 96a5a6569387a25b15a06aaab3bd9d033547e875..e4f5e570636862481aac92ec9b74d6cf5723eb6e 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -@@ -53,7 +53,7 @@ public class MobSpawnerPhantom implements MobSpawner { - while (iterator.hasNext()) { - EntityHuman entityhuman = (EntityHuman) iterator.next(); - -- if (!entityhuman.isSpectator()) { -+ if (!entityhuman.isSpectator() && (!worldserver.paperConfig.phantomIgnoreCreative || !entityhuman.isCreative())) { // Paper - BlockPosition blockposition = entityhuman.getChunkCoordinates(); - - if (!worldserver.getDimensionManager().hasSkyLight() || blockposition.getY() >= worldserver.getSeaLevel() && worldserver.e(blockposition)) { diff --git a/Unmapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/Unmapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch deleted file mode 100644 index eb495bf0f5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 25 Apr 2020 06:46:35 -0400 -Subject: [PATCH] Fix numerous item duplication issues and teleport issues - -This notably fixes the newest "Donkey Dupe", but also fixes a lot -of dupe bugs in general around nether portals and entity world transfer - -We also fix item duplication generically by anytime we clone an item -to drop it on the ground, destroy the source item. - -This avoid an itemstack ever existing twice in the world state pre -clean up stage. - -So even if something NEW comes up, it would be impossible to drop the -same item twice because the source was destroyed. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index fbd473d39cd71510b5fe8b7a4d34d3b824301f73..8d8d94219f9a556212763fce736452a19249ffec 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1974,11 +1974,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } else { - // CraftBukkit start - Capture drops for death event - if (this instanceof EntityLiving && !((EntityLiving) this).forceDrops) { -- ((EntityLiving) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); -+ ((EntityLiving) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // Paper - mirror so we can destroy it later - return null; - } - // CraftBukkit end -- EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY() + (double) f, this.locZ(), itemstack); -+ EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY() + (double) f, this.locZ(), itemstack.cloneItemStack()); // Paper - clone so we can destroy original -+ itemstack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe - - entityitem.defaultPickupDelay(); - // CraftBukkit start -@@ -2626,6 +2627,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - @Nullable - public Entity teleportTo(WorldServer worldserver, BlockPosition location) { - // CraftBukkit end -+ // Paper start - fix bad state entities causing dupes -+ if (!isAlive() || !valid) { -+ LOGGER.warn("Illegal Entity Teleport " + this + " to " + worldserver + ":" + location, new Throwable()); -+ return null; -+ } -+ // Paper end - if (this.world instanceof WorldServer && !this.dead) { - this.world.getMethodProfiler().enter("changeDimension"); - // CraftBukkit start -@@ -2646,6 +2653,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - // CraftBukkit end - - this.world.getMethodProfiler().exitEnter("reloading"); -+ // Paper start - Change lead drop timing to prevent dupe -+ if (this instanceof EntityInsentient) { -+ ((EntityInsentient) this).unleash(true, true); // Paper drop lead -+ } -+ // Paper end - Entity entity = this.getEntityType().a((World) worldserver); - - if (entity != null) { -@@ -2659,10 +2671,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - // CraftBukkit start - Forward the CraftEntity to the new entity - this.getBukkitEntity().setHandle(entity); - entity.bukkitEntity = this.getBukkitEntity(); -- -- if (this instanceof EntityInsentient) { -- ((EntityInsentient) this).unleash(true, false); // Unleash to prevent duping of leads. -- } - // CraftBukkit end - } - -@@ -2787,7 +2795,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean canPortal() { -- return true; -+ return isAlive() && valid; // Paper - } - - public float a(Explosion explosion, IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, float f) { -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 69361caebf0d3caa5195b519a16691705ac5e16a..5eb900619951083b9a777b1645cb5495b99968ec 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -602,7 +602,7 @@ public class EntityArmorStand extends EntityLiving { - for (i = 0; i < this.handItems.size(); ++i) { - itemstack = (ItemStack) this.handItems.get(i); - if (!itemstack.isEmpty()) { -- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops -+ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe - this.handItems.set(i, ItemStack.b); - } - } -@@ -610,7 +610,7 @@ public class EntityArmorStand extends EntityLiving { - for (i = 0; i < this.armorItems.size(); ++i) { - itemstack = (ItemStack) this.armorItems.get(i); - if (!itemstack.isEmpty()) { -- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops -+ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe - this.armorItems.set(i, ItemStack.b); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0b27d68dce9537c17701bd4944c807414564170b..d620d3e7c023786d1b7411399a05a75028a404cc 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -827,7 +827,8 @@ public class CraftEventFactory { - for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { - if (stack == null || stack.getType() == Material.AIR || stack.getAmount() == 0) continue; - -- world.dropItem(entity.getLocation(), stack); -+ world.dropItem(entity.getLocation(), stack); // Paper - note: dropItem already clones due to this being bukkit -> NMS -+ if (stack instanceof CraftItemStack) stack.setAmount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe, but don't nuke bukkit stacks of manually added items - } - - return event; diff --git a/Unmapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch b/Unmapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch deleted file mode 100644 index 16614706f6..0000000000 --- a/Unmapped-Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 18:15:29 -0400 -Subject: [PATCH] Implement Brigadier Mojang API - -Adds AsyncPlayerSendCommandsEvent - - Allows modifying on a per command basis what command data they see. - -Adds CommandRegisteredEvent - - Allows manipulating the CommandNode to add more children/metadata for the client - -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index 592b1bb2ce5cedb627f42c73ef072ade6553347e..a13c684e1360169993f323aa4aa91078c5e8b031 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -355,6 +355,7 @@ public class CommandDispatcher { - bukkit.add(node.getName()); - } - // Paper start - Async command map building -+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper - MinecraftServer.getServer().execute(() -> { - runSync(entityplayer, bukkit, rootcommandnode); - }); -@@ -362,6 +363,7 @@ public class CommandDispatcher { - - private void runSync(EntityPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { - // Paper end - Async command map building -+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper - PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); - event.getPlayer().getServer().getPluginManager().callEvent(event); - -diff --git a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -index eb2c9d2248a8647beee9960c5016a83f35aa1247..b5ee789c8dfb7f413ab60902ff3d2ef0cf8273cd 100644 ---- a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -+++ b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -@@ -38,7 +38,7 @@ import net.minecraft.world.phys.Vec3D; - - import com.mojang.brigadier.tree.CommandNode; // CraftBukkit - --public class CommandListenerWrapper implements ICompletionProvider { -+public class CommandListenerWrapper implements ICompletionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource { // Paper - - public static final SimpleCommandExceptionType a = new SimpleCommandExceptionType(new ChatMessage("permissions.requires.player")); - public static final SimpleCommandExceptionType b = new SimpleCommandExceptionType(new ChatMessage("permissions.requires.entity")); -@@ -150,6 +150,25 @@ public class CommandListenerWrapper implements ICompletionProvider { - return this.g; - } - -+ // Paper start -+ @Override -+ public org.bukkit.entity.Entity getBukkitEntity() { -+ return getEntity() != null ? getEntity().getBukkitEntity() : null; -+ } -+ -+ @Override -+ public org.bukkit.World getBukkitWorld() { -+ return getWorld() != null ? getWorld().getWorld() : null; -+ } -+ -+ @Override -+ public org.bukkit.Location getBukkitLocation() { -+ Vec3D pos = getPosition(); -+ org.bukkit.World world = getBukkitWorld(); -+ return world != null && pos != null ? new org.bukkit.Location(world, pos.x, pos.y, pos.z) : null; -+ } -+ // Paper end -+ - @Override - public boolean hasPermission(int i) { - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 7c1d25feab71c325ce2379afa6c61732eebd74f9..358d1acf7ca9ce510325fedf31e18a27c3a784d5 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -770,8 +770,12 @@ public class PlayerConnection implements PacketListenerPlayIn { - ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); - - this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -- this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); -+ // Paper start -+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); -+ suggestEvent.setCancelled(suggestions.isEmpty()); -+ if (!suggestEvent.callEvent()) return; -+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), (com.mojang.brigadier.suggestion.Suggestions) suggestEvent.getSuggestions())); // CraftBukkit - decompile error // Paper -+ // Paper end - }); - }); - } -@@ -780,7 +784,11 @@ public class PlayerConnection implements PacketListenerPlayIn { - - builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); - completions.forEach(builder::suggest); -- player.playerConnection.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), builder.buildFuture().join())); -+ com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); -+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); -+ suggestEvent.setCancelled(suggestions.isEmpty()); -+ if (!suggestEvent.callEvent()) return; -+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestEvent.getSuggestions())); - } - // Paper end - async tab completion - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -index 23d922a8baac01144602fd7813e9e76abc5335a3..8ddd246ad69a2e53749d38c369af701c161de54e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -@@ -17,7 +17,7 @@ import net.minecraft.commands.CommandListenerWrapper; - import org.bukkit.command.Command; - import org.bukkit.craftbukkit.CraftServer; - --public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider { -+public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommand { // Paper - - private final CraftServer server; - private final Command command; -@@ -28,10 +28,19 @@ public class BukkitCommandWrapper implements com.mojang.brigadier.Command register(CommandDispatcher dispatcher, String label) { -- return dispatcher.register( -- LiteralArgumentBuilder.literal(label).requires(this).executes(this) -- .then(RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this)) -- ); -+ // Paper start - Expose Brigadier to Paper-MojangAPI -+ com.mojang.brigadier.tree.RootCommandNode root = dispatcher.getRoot(); -+ LiteralCommandNode literal = LiteralArgumentBuilder.literal(label).requires(this).executes(this).build(); -+ com.mojang.brigadier.tree.ArgumentCommandNode defaultArgs = RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this).build(); -+ literal.addChild(defaultArgs); -+ com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent event = new com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent<>(label, this, this.command, root, literal, defaultArgs); -+ if (!event.callEvent()) { -+ return null; -+ } -+ literal = event.getLiteral(); -+ root.addChild(literal); -+ return literal; -+ // Paper end - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch b/Unmapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch deleted file mode 100644 index 55095b2a01..0000000000 --- a/Unmapped-Spigot-Server-Patches/0459-Villager-Restocks-API.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: zbk -Date: Sun, 26 Apr 2020 23:49:01 -0400 -Subject: [PATCH] Villager Restocks API - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 596450d3cdb3be4abca3e75bed743abd071fb0b0..fb97325e8df33c0edabb81053877ad4a326a3d34 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -113,7 +113,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - private long bA; - private int bB; - private long bC; -- private int bD; -+ private int bD; public int getRestocksToday(){ return this.bD; } public void setRestocksToday(int restocksToday){ this.bD = restocksToday; } // Paper OBFHELPER - private long bE; - private boolean bF; - private static final ImmutableList> bG = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.MOBS, MemoryModuleType.VISIBLE_MOBS, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.WALK_TARGET, new MemoryModuleType[]{MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index b020bc9e78a524b4745844ceb99249949c5ab6a4..4b2451179cdda918808ea7001f5033c7e5a8b9ac 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -@@ -84,6 +84,18 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { - getHandle().setExperience(experience); - } - -+ // Paper start -+ @Override -+ public int getRestocksToday() { -+ return getHandle().getRestocksToday(); -+ } -+ -+ @Override -+ public void setRestocksToday(int restocksToday) { -+ getHandle().setRestocksToday(restocksToday); -+ } -+ // Paper end -+ - @Override - public boolean sleep(Location location) { - Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/Unmapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch b/Unmapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch deleted file mode 100644 index 2c474587ad..0000000000 --- a/Unmapped-Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 2 May 2020 03:09:46 -0400 -Subject: [PATCH] Validate PickItem Packet and kick for invalid - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 358d1acf7ca9ce510325fedf31e18a27c3a784d5..b491a3563bf457bcb631e05cf41b661712134966 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -883,7 +883,14 @@ public class PlayerConnection implements PacketListenerPlayIn { - @Override - public void a(PacketPlayInPickItem packetplayinpickitem) { - PlayerConnectionUtils.ensureMainThread(packetplayinpickitem, this, this.player.getWorldServer()); -- this.player.inventory.c(packetplayinpickitem.b()); -+ // Paper start - validate pick item position -+ if (!(packetplayinpickitem.b() >= 0 && packetplayinpickitem.b() < this.player.inventory.items.size())) { -+ PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getDisplayName().getString()); -+ this.disconnect("Invalid hotbar selection (Hacking?)"); -+ return; -+ } -+ this.player.inventory.c(packetplayinpickitem.b()); // Paper - Diff above if changed -+ // Paper end - this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, this.player.inventory.itemInHandIndex, this.player.inventory.getItem(this.player.inventory.itemInHandIndex))); - this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, packetplayinpickitem.b(), this.player.inventory.getItem(packetplayinpickitem.b()))); - this.player.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(this.player.inventory.itemInHandIndex)); diff --git a/Unmapped-Spigot-Server-Patches/0461-Expose-game-version.patch b/Unmapped-Spigot-Server-Patches/0461-Expose-game-version.patch deleted file mode 100644 index 24b6d2653e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0461-Expose-game-version.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Fri, 1 May 2020 17:39:26 +0300 -Subject: [PATCH] Expose game version - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 63f89916d9982caa99525e01bd0e3f153af74d0f..f6e2e54b5a1b8c2df41a0593fa15112c5195c49c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -515,6 +515,13 @@ public final class CraftServer implements Server { - return bukkitVersion; - } - -+ // Paper start - expose game version -+ @Override -+ public String getMinecraftVersion() { -+ return console.getVersion(); -+ } -+ // Paper end -+ - @Override - public List getOnlinePlayers() { - return this.playerView; diff --git a/Unmapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch b/Unmapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch deleted file mode 100644 index e817b38737..0000000000 --- a/Unmapped-Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 May 2020 22:35:09 -0400 -Subject: [PATCH] Optimize Voxel Shape Merging - -This method shows up as super hot in profiler, and also a high "self" time. - -Upon analyzing, it appears most usages of this method fall down to the final -else statement of the nasty ternary. - -Upon even further analyzation, it appears then the majority of those have a -consistent list 1.... One with Infinity head and Tails. - -First optimization is to detect these infinite states and immediately return that -VoxelShapeMergerList so we can avoid testing the rest for most cases. - -Break the method into 2 to help the JVM promote inlining of this fast path. - -Then it was also noticed that VoxelShapeMergerList constructor is also a hotspot -with a high self time... - -Well, knowing that in most cases our list 1 is actualy the same value, it allows -us to know that with an infinite list1, the result on the merger is essentially -list2 as the final values. - -This let us analyze the 2 potential states (Infinite with 2 sources or 4 sources) -and compute a deterministic result for the MergerList values. - -Additionally, this lets us avoid even allocating new objects for this too, further -reducing memory usage. - -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -index c58d380b96e81d65d7c254a9e53017e5157769b0..57a4b4fcb6f89aacadcca49b25153157c8d06cc3 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -@@ -6,10 +6,16 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; - - public final class VoxelShapeMergerList implements VoxelShapeMerger { - -- private final DoubleArrayList a; -+ private final DoubleList a; // Paper - private final IntArrayList b; - private final IntArrayList c; - -+ // Paper start -+ private static final IntArrayList INFINITE_B_1 = new IntArrayList(new int[]{1, 1}); -+ private static final IntArrayList INFINITE_B_0 = new IntArrayList(new int[]{0, 0}); -+ private static final IntArrayList INFINITE_C = new IntArrayList(new int[]{0, 1}); -+ // Paper end -+ - protected VoxelShapeMergerList(DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { - int i = 0; - int j = 0; -@@ -18,6 +24,22 @@ public final class VoxelShapeMergerList implements VoxelShapeMerger { - int l = doublelist1.size(); - int i1 = k + l; - -+ // Paper start - optimize common path of infinity doublelist -+ int size = doublelist.size(); -+ double tail = doublelist.getDouble(size - 1); -+ double head = doublelist.getDouble(0); -+ if (head == Double.NEGATIVE_INFINITY && tail == Double.POSITIVE_INFINITY && !flag && !flag1 && (size == 2 || size == 4)) { -+ this.a = doublelist1; -+ if (size == 2) { -+ this.b = INFINITE_B_0; -+ } else { -+ this.b = INFINITE_B_1; -+ } -+ this.c = INFINITE_C; -+ return; -+ } -+ // Paper end -+ - this.a = new DoubleArrayList(i1); - this.b = new IntArrayList(i1); - this.c = new IntArrayList(i1); -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index 24ecac40625629b0bbe460e7fc984b147ede1f1f..2d7405d1fa7c8f378bebe86f5d0de57a129ed92d 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -329,9 +329,21 @@ public final class VoxelShapes { - } - - @VisibleForTesting -- protected static VoxelShapeMerger a(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { -+ private static VoxelShapeMerger a(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { // Paper - private -+ // Paper start - fast track the most common scenario -+ // doublelist is usually a DoubleArrayList with Infinite head/tails that falls to the final else clause -+ // This is actually the most common path, so jump to it straight away -+ if (doublelist.getDouble(0) == Double.NEGATIVE_INFINITY && doublelist.getDouble(doublelist.size() - 1) == Double.POSITIVE_INFINITY) { -+ return new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1); -+ } -+ // Split out rest to hopefully inline the above -+ return lessCommonMerge(i, doublelist, doublelist1, flag, flag1); -+ } -+ -+ private static VoxelShapeMerger lessCommonMerge(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { - int j = doublelist.size() - 1; - int k = doublelist1.size() - 1; -+ // Paper note - Rewrite below as optimized order if instead of nasty ternary - - if (doublelist instanceof VoxelShapeCubePoint && doublelist1 instanceof VoxelShapeCubePoint) { - long l = a(j, k); -@@ -341,7 +353,22 @@ public final class VoxelShapes { - } - } - -- return (VoxelShapeMerger) (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-7D ? new VoxelShapeMergerDisjoint(doublelist, doublelist1, false) : (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-7D ? new VoxelShapeMergerDisjoint(doublelist1, doublelist, true) : (j == k && Objects.equals(doublelist, doublelist1) ? (doublelist instanceof VoxelShapeMergerIdentical ? (VoxelShapeMerger) doublelist : (doublelist1 instanceof VoxelShapeMergerIdentical ? (VoxelShapeMerger) doublelist1 : new VoxelShapeMergerIdentical(doublelist))) : new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1)))); -+ // Identical happens more often than Disjoint -+ if (j == k && Objects.equals(doublelist, doublelist1)) { -+ if (doublelist instanceof VoxelShapeMergerIdentical) { -+ return (VoxelShapeMerger) doublelist; -+ } else if (doublelist1 instanceof VoxelShapeMergerIdentical) { -+ return (VoxelShapeMerger) doublelist1; -+ } -+ return new VoxelShapeMergerIdentical(doublelist); -+ } else if (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-07) { -+ return new VoxelShapeMergerDisjoint(doublelist, doublelist1, false); -+ } else if (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-07) { -+ return new VoxelShapeMergerDisjoint(doublelist1, doublelist, true); -+ } else { -+ return new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1); -+ } -+ // Paper end - } - - public interface a { diff --git a/Unmapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/Unmapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch deleted file mode 100644 index 52eb1dbcaa..0000000000 --- a/Unmapped-Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 4 May 2020 01:08:56 -0400 -Subject: [PATCH] Set cap on JDK per-thread native byte buffer cache - -See: https://www.evanjones.ca/java-bytebuffer-leak.html - -This is potentially a source of lots of native memory usage. - -We are clearly seeing native usage upwards to 1-4GB which doesn't make sense. - -Region File usage fixed in previous patch should of tecnically only been somewhat -temporary until GC finally gets it some time later, but between all the various -plugins doing IO on various threads, this hidden detail of the JDK could be -keeping long lived large direct buffers in cache. - -Set system properly at server startup if not set already to help protect from this. - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 5c54ecf6b1cf5531e51ae4d0a318aa64b837b574..6459ec144fa54a1e6ad1f0c40776321e95b41197 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -28,6 +28,7 @@ public class Main { - } - // Paper end - // Todo: Installation script -+ if (System.getProperty("jdk.nio.maxCachedBufferSize") == null) System.setProperty("jdk.nio.maxCachedBufferSize", "262144"); // Paper - cap per-thread NIO cache size - OptionParser parser = new OptionParser() { - { - acceptsAll(asList("?", "help"), "Show the help"); diff --git a/Unmapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch b/Unmapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch deleted file mode 100644 index 3fbd0e0c30..0000000000 --- a/Unmapped-Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch +++ /dev/null @@ -1,1170 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Fri, 3 Jan 2020 16:26:19 +0100 -Subject: [PATCH] Implement Mob Goal API - - -diff --git a/pom.xml b/pom.xml -index 4c8a057e790c96b0ab5123549d0566371acacb46..1a9204c869dd36e80932b1366352db15ebd70723 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -176,6 +176,13 @@ - 1.3 - test - -+ -+ -+ io.github.classgraph -+ classgraph -+ 4.8.47 -+ test -+ - - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f62d0ee49ebda2b0c7a136562b24ee038502d048 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -@@ -0,0 +1,530 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import com.destroystokyo.paper.entity.RangedEntity; -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; -+import com.google.common.collect.BiMap; -+import com.google.common.collect.HashBiMap; -+import java.lang.reflect.Constructor; -+import java.util.EnumSet; -+import java.util.HashMap; -+import java.util.HashSet; -+import java.util.Map; -+import java.util.Set; -+import net.minecraft.world.entity.EntityAgeable; -+import net.minecraft.world.entity.EntityCreature; -+import net.minecraft.world.entity.EntityFlying; -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.EntityTameableAnimal; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import net.minecraft.world.entity.ambient.EntityAmbient; -+import net.minecraft.world.entity.ambient.EntityBat; -+import net.minecraft.world.entity.animal.EntityAnimal; -+import net.minecraft.world.entity.animal.EntityBee; -+import net.minecraft.world.entity.animal.EntityCat; -+import net.minecraft.world.entity.animal.EntityChicken; -+import net.minecraft.world.entity.animal.EntityCod; -+import net.minecraft.world.entity.animal.EntityCow; -+import net.minecraft.world.entity.animal.EntityDolphin; -+import net.minecraft.world.entity.animal.EntityFish; -+import net.minecraft.world.entity.animal.EntityFishSchool; -+import net.minecraft.world.entity.animal.EntityFox; -+import net.minecraft.world.entity.animal.EntityGolem; -+import net.minecraft.world.entity.animal.EntityIronGolem; -+import net.minecraft.world.entity.animal.EntityMushroomCow; -+import net.minecraft.world.entity.animal.EntityOcelot; -+import net.minecraft.world.entity.animal.EntityPanda; -+import net.minecraft.world.entity.animal.EntityParrot; -+import net.minecraft.world.entity.animal.EntityPerchable; -+import net.minecraft.world.entity.animal.EntityPig; -+import net.minecraft.world.entity.animal.EntityPolarBear; -+import net.minecraft.world.entity.animal.EntityPufferFish; -+import net.minecraft.world.entity.animal.EntityRabbit; -+import net.minecraft.world.entity.animal.EntitySalmon; -+import net.minecraft.world.entity.animal.EntitySheep; -+import net.minecraft.world.entity.animal.EntitySnowman; -+import net.minecraft.world.entity.animal.EntitySquid; -+import net.minecraft.world.entity.animal.EntityTropicalFish; -+import net.minecraft.world.entity.animal.EntityTurtle; -+import net.minecraft.world.entity.animal.EntityWaterAnimal; -+import net.minecraft.world.entity.animal.EntityWolf; -+import net.minecraft.world.entity.animal.horse.EntityHorse; -+import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; -+import net.minecraft.world.entity.animal.horse.EntityHorseChestedAbstract; -+import net.minecraft.world.entity.animal.horse.EntityHorseDonkey; -+import net.minecraft.world.entity.animal.horse.EntityHorseMule; -+import net.minecraft.world.entity.animal.horse.EntityHorseSkeleton; -+import net.minecraft.world.entity.animal.horse.EntityHorseZombie; -+import net.minecraft.world.entity.animal.horse.EntityLlama; -+import net.minecraft.world.entity.animal.horse.EntityLlamaTrader; -+import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; -+import net.minecraft.world.entity.boss.wither.EntityWither; -+import net.minecraft.world.entity.monster.EntityBlaze; -+import net.minecraft.world.entity.monster.EntityCaveSpider; -+import net.minecraft.world.entity.monster.EntityCreeper; -+import net.minecraft.world.entity.monster.EntityDrowned; -+import net.minecraft.world.entity.monster.EntityEnderman; -+import net.minecraft.world.entity.monster.EntityEndermite; -+import net.minecraft.world.entity.monster.EntityEvoker; -+import net.minecraft.world.entity.monster.EntityGhast; -+import net.minecraft.world.entity.monster.EntityGiantZombie; -+import net.minecraft.world.entity.monster.EntityGuardian; -+import net.minecraft.world.entity.monster.EntityGuardianElder; -+import net.minecraft.world.entity.monster.EntityIllagerAbstract; -+import net.minecraft.world.entity.monster.EntityIllagerIllusioner; -+import net.minecraft.world.entity.monster.EntityIllagerWizard; -+import net.minecraft.world.entity.monster.EntityMagmaCube; -+import net.minecraft.world.entity.monster.EntityMonster; -+import net.minecraft.world.entity.monster.EntityMonsterPatrolling; -+import net.minecraft.world.entity.monster.EntityPhantom; -+import net.minecraft.world.entity.monster.EntityPigZombie; -+import net.minecraft.world.entity.monster.EntityPillager; -+import net.minecraft.world.entity.monster.EntityRavager; -+import net.minecraft.world.entity.monster.EntityShulker; -+import net.minecraft.world.entity.monster.EntitySilverfish; -+import net.minecraft.world.entity.monster.EntitySkeleton; -+import net.minecraft.world.entity.monster.EntitySkeletonAbstract; -+import net.minecraft.world.entity.monster.EntitySkeletonStray; -+import net.minecraft.world.entity.monster.EntitySkeletonWither; -+import net.minecraft.world.entity.monster.EntitySlime; -+import net.minecraft.world.entity.monster.EntitySpider; -+import net.minecraft.world.entity.monster.EntityStrider; -+import net.minecraft.world.entity.monster.EntityVex; -+import net.minecraft.world.entity.monster.EntityVindicator; -+import net.minecraft.world.entity.monster.EntityWitch; -+import net.minecraft.world.entity.monster.EntityZoglin; -+import net.minecraft.world.entity.monster.EntityZombie; -+import net.minecraft.world.entity.monster.EntityZombieHusk; -+import net.minecraft.world.entity.monster.EntityZombieVillager; -+import net.minecraft.world.entity.monster.IRangedEntity; -+import net.minecraft.world.entity.monster.hoglin.EntityHoglin; -+import net.minecraft.world.entity.monster.piglin.EntityPiglin; -+import net.minecraft.world.entity.monster.piglin.EntityPiglinAbstract; -+import net.minecraft.world.entity.monster.piglin.EntityPiglinBrute; -+import net.minecraft.world.entity.npc.EntityVillager; -+import net.minecraft.world.entity.npc.EntityVillagerAbstract; -+import net.minecraft.world.entity.npc.EntityVillagerTrader; -+import net.minecraft.world.entity.raid.EntityRaider; -+import org.bukkit.NamespacedKey; -+import org.bukkit.entity.AbstractHorse; -+import org.bukkit.entity.AbstractVillager; -+import org.bukkit.entity.Ageable; -+import org.bukkit.entity.Ambient; -+import org.bukkit.entity.Animals; -+import org.bukkit.entity.Bat; -+import org.bukkit.entity.Bee; -+import org.bukkit.entity.Blaze; -+import org.bukkit.entity.Cat; -+import org.bukkit.entity.CaveSpider; -+import org.bukkit.entity.ChestedHorse; -+import org.bukkit.entity.Chicken; -+import org.bukkit.entity.Cod; -+import org.bukkit.entity.Cow; -+import org.bukkit.entity.Creature; -+import org.bukkit.entity.Creeper; -+import org.bukkit.entity.Dolphin; -+import org.bukkit.entity.Donkey; -+import org.bukkit.entity.Drowned; -+import org.bukkit.entity.ElderGuardian; -+import org.bukkit.entity.EnderDragon; -+import org.bukkit.entity.Enderman; -+import org.bukkit.entity.Endermite; -+import org.bukkit.entity.Evoker; -+import org.bukkit.entity.Fish; -+import org.bukkit.entity.Flying; -+import org.bukkit.entity.Fox; -+import org.bukkit.entity.Ghast; -+import org.bukkit.entity.Giant; -+import org.bukkit.entity.Golem; -+import org.bukkit.entity.Guardian; -+import org.bukkit.entity.Hoglin; -+import org.bukkit.entity.Horse; -+import org.bukkit.entity.Husk; -+import org.bukkit.entity.Illager; -+import org.bukkit.entity.Illusioner; -+import org.bukkit.entity.IronGolem; -+import org.bukkit.entity.Llama; -+import org.bukkit.entity.MagmaCube; -+import org.bukkit.entity.Mob; -+import org.bukkit.entity.Monster; -+import org.bukkit.entity.Mule; -+import org.bukkit.entity.MushroomCow; -+import org.bukkit.entity.Ocelot; -+import org.bukkit.entity.Panda; -+import org.bukkit.entity.Parrot; -+import org.bukkit.entity.Phantom; -+import org.bukkit.entity.Pig; -+import org.bukkit.entity.PigZombie; -+import org.bukkit.entity.Piglin; -+import org.bukkit.entity.PiglinAbstract; -+import org.bukkit.entity.PiglinBrute; -+import org.bukkit.entity.Pillager; -+import org.bukkit.entity.PolarBear; -+import org.bukkit.entity.PufferFish; -+import org.bukkit.entity.Rabbit; -+import org.bukkit.entity.Raider; -+import org.bukkit.entity.Ravager; -+import org.bukkit.entity.Salmon; -+import org.bukkit.entity.Sheep; -+import org.bukkit.entity.Shulker; -+import org.bukkit.entity.Silverfish; -+import org.bukkit.entity.Skeleton; -+import org.bukkit.entity.SkeletonHorse; -+import org.bukkit.entity.Slime; -+import org.bukkit.entity.Snowman; -+import org.bukkit.entity.Spellcaster; -+import org.bukkit.entity.Spider; -+import org.bukkit.entity.Squid; -+import org.bukkit.entity.Stray; -+import org.bukkit.entity.Strider; -+import org.bukkit.entity.Tameable; -+import org.bukkit.entity.TraderLlama; -+import org.bukkit.entity.TropicalFish; -+import org.bukkit.entity.Turtle; -+import org.bukkit.entity.Vex; -+import org.bukkit.entity.Villager; -+import org.bukkit.entity.Vindicator; -+import org.bukkit.entity.WanderingTrader; -+import org.bukkit.entity.WaterMob; -+import org.bukkit.entity.Witch; -+import org.bukkit.entity.Wither; -+import org.bukkit.entity.WitherSkeleton; -+import org.bukkit.entity.Wolf; -+import org.bukkit.entity.Zoglin; -+import org.bukkit.entity.Zombie; -+import org.bukkit.entity.ZombieHorse; -+import org.bukkit.entity.ZombieVillager; -+ -+public class MobGoalHelper { -+ -+ private static final BiMap deobfuscationMap = HashBiMap.create(); -+ private static final Map, Class> entityClassCache = new HashMap<>(); -+ private static final Map, Class> bukkitMap = new HashMap<>(); -+ -+ static final Set ignored = new HashSet<>(); -+ -+ static { -+ // TODO these kinda should be checked on each release, in case obfuscation changes -+ deobfuscationMap.put("bee_b", "bee_attack"); -+ deobfuscationMap.put("bee_c", "bee_become_angry"); -+ deobfuscationMap.put("bee_d", "bee_enter_hive"); -+ deobfuscationMap.put("bee_e", "bee_go_to_hive"); -+ deobfuscationMap.put("bee_f", "bee_go_to_known_flower"); -+ deobfuscationMap.put("bee_g", "bee_grow_crop"); -+ deobfuscationMap.put("bee_h", "bee_hurt_by_other"); -+ deobfuscationMap.put("bee_i", "bee_locate_hive"); -+ deobfuscationMap.put("bee_k", "bee_pollinate"); -+ deobfuscationMap.put("bee_l", "bee_wander"); -+ deobfuscationMap.put("cat_a", "cat_avoid_entity"); -+ deobfuscationMap.put("cat_b", "cat_relax_on_owner"); -+ deobfuscationMap.put("dolphin_b", "dolphin_swim_to_treasure"); -+ deobfuscationMap.put("dolphin_c", "dolphin_swim_with_player"); -+ deobfuscationMap.put("dolphin_d", "dolphin_play_with_items"); -+ deobfuscationMap.put("drowned_a", "drowned_attack"); -+ deobfuscationMap.put("drowned_b", "drowned_goto_beach"); -+ deobfuscationMap.put("drowned_c", "drowned_goto_water"); -+ deobfuscationMap.put("drowned_e", "drowned_swim_up"); -+ deobfuscationMap.put("drowned_f", "drowned_trident_attack"); -+ deobfuscationMap.put("enderman_a", "enderman_freeze_when_looked_at"); -+ deobfuscationMap.put("evoker_a", "evoker_attack_spell"); -+ deobfuscationMap.put("evoker_b", "evoker_cast_spell"); -+ deobfuscationMap.put("evoker_c", "evoker_summon_spell"); -+ deobfuscationMap.put("evoker_d", "evoker_wololo_spell"); -+ deobfuscationMap.put("fish_b", "fish_swim"); -+ deobfuscationMap.put("fox_a", "fox_defend_trusted"); -+ deobfuscationMap.put("fox_b", "fox_faceplant"); -+ deobfuscationMap.put("fox_e", "fox_breed"); -+ deobfuscationMap.put("fox_f", "fox_eat_berries"); -+ deobfuscationMap.put("fox_g", "fox_float"); -+ deobfuscationMap.put("fox_h", "fox_follow_parent"); -+ deobfuscationMap.put("fox_j", "fox_look_at_player"); -+ deobfuscationMap.put("fox_l", "fox_melee_attack"); -+ deobfuscationMap.put("fox_n", "fox_panic"); -+ deobfuscationMap.put("fox_o", "fox_pounce"); -+ deobfuscationMap.put("fox_p", "fox_search_for_items"); -+ deobfuscationMap.put("fox_q", "fox_stroll_through_village"); -+ deobfuscationMap.put("fox_r", "fox_perch_and_search"); -+ deobfuscationMap.put("fox_s", "fox_seek_shelter"); -+ deobfuscationMap.put("fox_t", "fox_sleep"); -+ deobfuscationMap.put("fox_u", "fox_stalk_prey"); -+ deobfuscationMap.put("illager_abstract_b", "raider_open_door"); -+ deobfuscationMap.put("illager_illusioner_a", "illusioner_blindness_spell"); -+ deobfuscationMap.put("illager_illusioner_b", "illusioner_mirror_spell"); -+ deobfuscationMap.put("illager_wizard_b", "spellcaster_cast_spell"); -+ deobfuscationMap.put("llama_a", "llama_attack_wolf"); -+ deobfuscationMap.put("llama_c", "llama_hurt_by"); -+ deobfuscationMap.put("llama_trader_a", "llamatrader_defended_wandering_trader"); -+ deobfuscationMap.put("monster_patrolling_a", "long_distance_patrol"); -+ deobfuscationMap.put("ocelot_a", "ocelot_avoid_entity"); -+ deobfuscationMap.put("ocelot_b", "ocelot_tempt"); -+ deobfuscationMap.put("panda_b", "panda_attack"); -+ deobfuscationMap.put("panda_c", "panda_avoid"); -+ deobfuscationMap.put("panda_d", "panda_breed"); -+ deobfuscationMap.put("panda_e", "panda_hurt_by_target"); -+ deobfuscationMap.put("panda_f", "panda_lie_on_back"); -+ deobfuscationMap.put("panda_g", "panda_look_at_player"); -+ deobfuscationMap.put("panda_i", "panda_panic"); -+ deobfuscationMap.put("panda_j", "panda_roll"); -+ deobfuscationMap.put("panda_k", "panda_sit"); -+ deobfuscationMap.put("panda_l", "panda_sneeze"); -+ deobfuscationMap.put("phantom_b", "phantom_attack_player"); -+ deobfuscationMap.put("phantom_c", "phantom_attack_strategy"); -+ deobfuscationMap.put("phantom_e", "phantom_circle_around_anchor"); -+ deobfuscationMap.put("phantom_i", "phantom_sweep_attack"); -+ deobfuscationMap.put("polar_bear_a", "polarbear_attack_players"); -+ deobfuscationMap.put("polar_bear_b", "polarbear_hurt_by"); -+ deobfuscationMap.put("polar_bear_c", "polarbear_melee"); -+ deobfuscationMap.put("polar_bear_d", "polarbear_panic"); -+ deobfuscationMap.put("puffer_fish_a", "pufferfish_puff"); -+ deobfuscationMap.put("raider_a", "raider_hold_ground"); -+ deobfuscationMap.put("raider_b", "raider_obtain_banner"); -+ deobfuscationMap.put("raider_c", "raider_celebration"); -+ deobfuscationMap.put("raider_d", "raider_move_through_village"); -+ deobfuscationMap.put("ravager_a", "ravager_melee_attack"); -+ deobfuscationMap.put("shulker_a", "shulker_attack"); -+ deobfuscationMap.put("shulker_c", "shulker_defense"); -+ deobfuscationMap.put("shulker_d", "shulker_nearest"); -+ deobfuscationMap.put("shulker_e", "shulker_peek"); -+ deobfuscationMap.put("squid_a", "squid_flee"); -+ deobfuscationMap.put("skeleton_abstract_1", "skeleton_melee"); -+ deobfuscationMap.put("strider_a", "strider_go_to_lava"); -+ deobfuscationMap.put("turtle_a", "turtle_breed"); -+ deobfuscationMap.put("turtle_b", "turtle_go_home"); -+ deobfuscationMap.put("turtle_c", "turtle_goto_water"); -+ deobfuscationMap.put("turtle_d", "turtle_lay_egg"); -+ deobfuscationMap.put("turtle_f", "turtle_panic"); -+ deobfuscationMap.put("turtle_h", "turtle_random_stroll"); -+ deobfuscationMap.put("turtle_i", "turtle_tempt"); -+ deobfuscationMap.put("turtle_j", "turtle_travel"); -+ deobfuscationMap.put("vex_a", "vex_charge_attack"); -+ deobfuscationMap.put("vex_b", "vex_copy_target_of_owner"); -+ deobfuscationMap.put("vex_d", "vex_random_move"); -+ deobfuscationMap.put("villager_trader_a", "villagertrader_wander_to_position"); -+ deobfuscationMap.put("vindicator_a", "vindicator_break_door"); -+ deobfuscationMap.put("vindicator_b", "vindicator_johnny_attack"); -+ deobfuscationMap.put("vindicator_c", "vindicator_melee_attack"); -+ deobfuscationMap.put("wither_a", "wither_do_nothing"); -+ deobfuscationMap.put("wolf_a", "wolf_avoid_entity"); -+ deobfuscationMap.put("zombie_a", "zombie_attack_turtle_egg"); -+ -+ ignored.add("selector_1"); -+ ignored.add("selector_2"); -+ ignored.add("wrapped"); -+ -+ bukkitMap.put(EntityInsentient.class, Mob.class); -+ bukkitMap.put(EntityAgeable.class, Ageable.class); -+ bukkitMap.put(EntityAmbient.class, Ambient.class); -+ bukkitMap.put(EntityAnimal.class, Animals.class); -+ bukkitMap.put(EntityBat.class, Bat.class); -+ bukkitMap.put(EntityBee.class, Bee.class); -+ bukkitMap.put(EntityBlaze.class, Blaze.class); -+ bukkitMap.put(EntityCat.class, Cat.class); -+ bukkitMap.put(EntityCaveSpider.class, CaveSpider.class); -+ bukkitMap.put(EntityChicken.class, Chicken.class); -+ bukkitMap.put(EntityCod.class, Cod.class); -+ bukkitMap.put(EntityCow.class, Cow.class); -+ bukkitMap.put(EntityCreature.class, Creature.class); -+ bukkitMap.put(EntityCreeper.class, Creeper.class); -+ bukkitMap.put(EntityDolphin.class, Dolphin.class); -+ bukkitMap.put(EntityDrowned.class, Drowned.class); -+ bukkitMap.put(EntityEnderDragon.class, EnderDragon.class); -+ bukkitMap.put(EntityEnderman.class, Enderman.class); -+ bukkitMap.put(EntityEndermite.class, Endermite.class); -+ bukkitMap.put(EntityEvoker.class, Evoker.class); -+ bukkitMap.put(EntityFish.class, Fish.class); -+ bukkitMap.put(EntityFishSchool.class, Fish.class); // close enough -+ bukkitMap.put(EntityFlying.class, Flying.class); -+ bukkitMap.put(EntityFox.class, Fox.class); -+ bukkitMap.put(EntityGhast.class, Ghast.class); -+ bukkitMap.put(EntityGiantZombie.class, Giant.class); -+ bukkitMap.put(EntityGolem.class, Golem.class); -+ bukkitMap.put(EntityGuardian.class, Guardian.class); -+ bukkitMap.put(EntityGuardianElder.class, ElderGuardian.class); -+ bukkitMap.put(EntityHorse.class, Horse.class); -+ bukkitMap.put(EntityHorseAbstract.class, AbstractHorse.class); -+ bukkitMap.put(EntityHorseChestedAbstract.class, ChestedHorse.class); -+ bukkitMap.put(EntityHorseDonkey.class, Donkey.class); -+ bukkitMap.put(EntityHorseMule.class, Mule.class); -+ bukkitMap.put(EntityHorseSkeleton.class, SkeletonHorse.class); -+ bukkitMap.put(EntityHorseZombie.class, ZombieHorse.class); -+ bukkitMap.put(EntityIllagerAbstract.class, Illager.class); -+ bukkitMap.put(EntityIllagerIllusioner.class, Illusioner.class); -+ bukkitMap.put(EntityIllagerWizard.class, Spellcaster.class); -+ bukkitMap.put(EntityIronGolem.class, IronGolem.class); -+ bukkitMap.put(EntityLlama.class, Llama.class); -+ bukkitMap.put(EntityLlamaTrader.class, TraderLlama.class); -+ bukkitMap.put(EntityMagmaCube.class, MagmaCube.class); -+ bukkitMap.put(EntityMonster.class, Monster.class); -+ bukkitMap.put(EntityMonsterPatrolling.class, Monster.class); // close enough -+ bukkitMap.put(EntityMushroomCow.class, MushroomCow.class); -+ bukkitMap.put(EntityOcelot.class, Ocelot.class); -+ bukkitMap.put(EntityPanda.class, Panda.class); -+ bukkitMap.put(EntityParrot.class, Parrot.class); -+ bukkitMap.put(EntityPerchable.class, Parrot.class); // close enough -+ bukkitMap.put(EntityPhantom.class, Phantom.class); -+ bukkitMap.put(EntityPig.class, Pig.class); -+ bukkitMap.put(EntityPigZombie.class, PigZombie.class); -+ bukkitMap.put(EntityPillager.class, Pillager.class); -+ bukkitMap.put(EntityPolarBear.class, PolarBear.class); -+ bukkitMap.put(EntityPufferFish.class, PufferFish.class); -+ bukkitMap.put(EntityRabbit.class, Rabbit.class); -+ bukkitMap.put(EntityRaider.class, Raider.class); -+ bukkitMap.put(EntityRavager.class, Ravager.class); -+ bukkitMap.put(EntitySalmon.class, Salmon.class); -+ bukkitMap.put(EntitySheep.class, Sheep.class); -+ bukkitMap.put(EntityShulker.class, Shulker.class); -+ bukkitMap.put(EntitySilverfish.class, Silverfish.class); -+ bukkitMap.put(EntitySkeleton.class, Skeleton.class); -+ bukkitMap.put(EntitySkeletonAbstract.class, Skeleton.class); -+ bukkitMap.put(EntitySkeletonStray.class, Stray.class); -+ bukkitMap.put(EntitySkeletonWither.class, WitherSkeleton.class); -+ bukkitMap.put(EntitySlime.class, Slime.class); -+ bukkitMap.put(EntitySnowman.class, Snowman.class); -+ bukkitMap.put(EntitySpider.class, Spider.class); -+ bukkitMap.put(EntitySquid.class, Squid.class); -+ bukkitMap.put(EntityTameableAnimal.class, Tameable.class); -+ bukkitMap.put(EntityTropicalFish.class, TropicalFish.class); -+ bukkitMap.put(EntityTurtle.class, Turtle.class); -+ bukkitMap.put(EntityVex.class, Vex.class); -+ bukkitMap.put(EntityVillager.class, Villager.class); -+ bukkitMap.put(EntityVillagerAbstract.class, AbstractVillager.class); -+ bukkitMap.put(EntityVillagerTrader.class, WanderingTrader.class); -+ bukkitMap.put(EntityVindicator.class, Vindicator.class); -+ bukkitMap.put(EntityWaterAnimal.class, WaterMob.class); -+ bukkitMap.put(EntityWitch.class, Witch.class); -+ bukkitMap.put(EntityWither.class, Wither.class); -+ bukkitMap.put(EntityWolf.class, Wolf.class); -+ bukkitMap.put(EntityZombie.class, Zombie.class); -+ bukkitMap.put(EntityZombieHusk.class, Husk.class); -+ bukkitMap.put(EntityZombieVillager.class, ZombieVillager.class); -+ bukkitMap.put(EntityHoglin.class, Hoglin.class); -+ bukkitMap.put(EntityPiglin.class, Piglin.class); -+ bukkitMap.put(EntityPiglinAbstract.class, PiglinAbstract.class); -+ bukkitMap.put(EntityPiglinBrute.class, PiglinBrute.class); -+ bukkitMap.put(EntityStrider.class, Strider.class); -+ bukkitMap.put(EntityZoglin.class, Zoglin.class); -+ } -+ -+ public static String getUsableName(Class clazz) { -+ String name = clazz.getName(); -+ name = name.substring(name.lastIndexOf(".") + 1); -+ boolean flag = false; -+ // inner classes -+ if (name.contains("$")) { -+ String cut = name.substring(name.indexOf("$") + 1); -+ if (cut.length() <= 2) { -+ name = name.replace("Entity", ""); -+ name = name.replace("$", "_"); -+ flag = true; -+ } else { -+ // mapped, wooo -+ name = cut; -+ } -+ } -+ name = name.replace("PathfinderGoal", ""); -+ StringBuilder sb = new StringBuilder(); -+ for (char c : name.toCharArray()) { -+ if (c >= 'A' && c <= 'Z') { -+ sb.append("_"); -+ sb.append(Character.toLowerCase(c)); -+ } else { -+ sb.append(c); -+ } -+ } -+ name = sb.toString(); -+ name = name.replaceFirst("_", ""); -+ -+ if (flag && !deobfuscationMap.containsKey(name.toLowerCase()) && !ignored.contains(name)) { -+ System.out.println("need to map " + clazz.getName() + " (" + name.toLowerCase() + ")"); -+ } -+ -+ // did we rename this key? -+ return deobfuscationMap.getOrDefault(name, name); -+ } -+ -+ public static EnumSet vanillaToPaper(OptimizedSmallEnumSet types) { -+ EnumSet goals = EnumSet.noneOf(GoalType.class); -+ for (GoalType type : GoalType.values()) { -+ if (types.hasElement(paperToVanilla(type))) { -+ goals.add(type); -+ } -+ } -+ return goals; -+ } -+ -+ public static GoalType vanillaToPaper(PathfinderGoal.Type type) { -+ switch (type) { -+ case MOVE: -+ return GoalType.MOVE; -+ case LOOK: -+ return GoalType.LOOK; -+ case JUMP: -+ return GoalType.JUMP; -+ case UNKNOWN_BEHAVIOR: -+ return GoalType.UNKNOWN_BEHAVIOR; -+ case TARGET: -+ return GoalType.TARGET; -+ default: -+ throw new IllegalArgumentException("Unknown vanilla mob goal type " + type.name()); -+ } -+ } -+ -+ public static EnumSet paperToVanilla(EnumSet types) { -+ EnumSet goals = EnumSet.noneOf(PathfinderGoal.Type.class); -+ for (GoalType type : types) { -+ goals.add(paperToVanilla(type)); -+ } -+ return goals; -+ } -+ -+ public static PathfinderGoal.Type paperToVanilla(GoalType type) { -+ switch (type) { -+ case MOVE: -+ return PathfinderGoal.Type.MOVE; -+ case LOOK: -+ return PathfinderGoal.Type.LOOK; -+ case JUMP: -+ return PathfinderGoal.Type.JUMP; -+ case UNKNOWN_BEHAVIOR: -+ return PathfinderGoal.Type.UNKNOWN_BEHAVIOR; -+ case TARGET: -+ return PathfinderGoal.Type.TARGET; -+ default: -+ throw new IllegalArgumentException("Unknown paper mob goal type " + type.name()); -+ } -+ } -+ -+ public static GoalKey getKey(Class goalClass) { -+ String name = getUsableName(goalClass); -+ if (ignored.contains(name)) { -+ //noinspection unchecked -+ return (GoalKey) GoalKey.of(Mob.class, NamespacedKey.minecraft(name)); -+ } -+ return GoalKey.of(getEntity(goalClass), NamespacedKey.minecraft(name)); -+ } -+ -+ public static Class getEntity(Class goalClass) { -+ //noinspection unchecked -+ return (Class) entityClassCache.computeIfAbsent(goalClass, key -> { -+ for (Constructor ctor : key.getDeclaredConstructors()) { -+ for (int i = 0; i < ctor.getParameterCount(); i++) { -+ Class param = ctor.getParameterTypes()[i]; -+ if (EntityInsentient.class.isAssignableFrom(param)) { -+ //noinspection unchecked -+ return toBukkitClass((Class) param); -+ } else if (IRangedEntity.class.isAssignableFrom(param)) { -+ return RangedEntity.class; -+ } -+ } -+ } -+ throw new RuntimeException("Can't figure out applicable entity for mob goal " + goalClass); // maybe just return EntityInsentient? -+ }); -+ } -+ -+ public static Class toBukkitClass(Class nmsClass) { -+ Class bukkitClass = bukkitMap.get(nmsClass); -+ if (bukkitClass == null) { -+ throw new RuntimeException("Can't figure out applicable bukkit entity for nms entity " + nmsClass); // maybe just return Mob? -+ } -+ return bukkitClass; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0b963f80857209bc73ece917203447d8839860b6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java -@@ -0,0 +1,54 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import org.bukkit.entity.Mob; -+ -+/** -+ * Wraps api in vanilla -+ */ -+public class PaperCustomGoal extends PathfinderGoal { -+ -+ private final Goal handle; -+ -+ public PaperCustomGoal(Goal handle) { -+ this.handle = handle; -+ -+ this.setTypes(MobGoalHelper.paperToVanilla(handle.getTypes())); -+ if (this.getGoalTypes().size() == 0) { -+ this.getGoalTypes().addUnchecked(Type.UNKNOWN_BEHAVIOR); -+ } -+ } -+ -+ @Override -+ public boolean shouldActivate() { -+ return handle.shouldActivate(); -+ } -+ -+ @Override -+ public boolean shouldStayActive() { -+ return handle.shouldStayActive(); -+ } -+ -+ @Override -+ public void start() { -+ handle.start(); -+ } -+ -+ @Override -+ public void onTaskReset() { -+ handle.stop(); -+ } -+ -+ @Override -+ public void tick() { -+ handle.tick(); -+ } -+ -+ public Goal getHandle() { -+ return handle; -+ } -+ -+ public GoalKey getKey() { -+ return handle.getKey(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java -new file mode 100644 -index 0000000000000000000000000000000000000000..bf792c013fe3b9a0b5800a35308b9aaa36e5350d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java -@@ -0,0 +1,222 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import java.util.Collection; -+import java.util.EnumSet; -+import java.util.HashMap; -+import java.util.HashSet; -+import java.util.LinkedList; -+import java.util.List; -+import java.util.Map; -+import java.util.Set; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import net.minecraft.world.entity.ai.goal.PathfinderGoalSelector; -+import net.minecraft.world.entity.ai.goal.PathfinderGoalWrapped; -+import org.bukkit.craftbukkit.entity.CraftMob; -+import org.bukkit.entity.Mob; -+ -+public class PaperMobGoals implements MobGoals { -+ -+ private final Map> instanceCache = new HashMap<>(); -+ -+ @Override -+ public void addGoal(T mob, int priority, Goal goal) { -+ CraftMob craftMob = (CraftMob) mob; -+ getHandle(craftMob, goal.getTypes()).addGoal(priority, new PaperCustomGoal<>(goal)); -+ } -+ -+ @Override -+ public void removeGoal(T mob, Goal goal) { -+ CraftMob craftMob = (CraftMob) mob; -+ if (goal instanceof PaperCustomGoal) { -+ getHandle(craftMob, goal.getTypes()).removeGoal((PathfinderGoal) goal); -+ } else if (goal instanceof PaperVanillaGoal) { -+ getHandle(craftMob, goal.getTypes()).removeGoal(((PaperVanillaGoal) goal).getHandle()); -+ } else { -+ List toRemove = new LinkedList<>(); -+ for (PathfinderGoalWrapped item : getHandle(craftMob, goal.getTypes()).getTasks()) { -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ if (((PaperCustomGoal) item.getGoal()).getHandle() == goal) { -+ toRemove.add(item.getGoal()); -+ } -+ } -+ } -+ -+ for (PathfinderGoal g : toRemove) { -+ getHandle(craftMob, goal.getTypes()).removeGoal(g); -+ } -+ } -+ } -+ -+ @Override -+ public void removeAllGoals(T mob) { -+ for (GoalType type : GoalType.values()) { -+ removeAllGoals(mob, type); -+ } -+ } -+ -+ @Override -+ public void removeAllGoals(T mob, GoalType type) { -+ for (Goal goal : getAllGoals(mob, type)) { -+ removeGoal(mob, goal); -+ } -+ } -+ -+ @Override -+ public void removeGoal(T mob, GoalKey key) { -+ for (Goal goal : getGoals(mob, key)) { -+ removeGoal(mob, goal); -+ } -+ } -+ -+ @Override -+ public boolean hasGoal(T mob, GoalKey key) { -+ for (Goal g : getAllGoals(mob)) { -+ if (g.getKey().equals(key)) { -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ @Override -+ public Goal getGoal(T mob, GoalKey key) { -+ for (Goal g : getAllGoals(mob)) { -+ if (g.getKey().equals(key)) { -+ return g; -+ } -+ } -+ return null; -+ } -+ -+ @Override -+ public Collection> getGoals(T mob, GoalKey key) { -+ Set> goals = new HashSet<>(); -+ for (Goal g : getAllGoals(mob)) { -+ if (g.getKey().equals(key)) { -+ goals.add(g); -+ } -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getAllGoals(T mob) { -+ Set> goals = new HashSet<>(); -+ for (GoalType type : GoalType.values()) { -+ goals.addAll(getAllGoals(mob, type)); -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getAllGoals(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ for (PathfinderGoalWrapped item : getHandle(craftMob, type).getTasks()) { -+ if (!item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { -+ continue; -+ } -+ -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getAllGoalsWithout(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ for (GoalType internalType : GoalType.values()) { -+ if (internalType == type) { -+ continue; -+ } -+ for (PathfinderGoalWrapped item : getHandle(craftMob, internalType).getTasks()) { -+ if (item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { -+ continue; -+ } -+ -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ } -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getRunningGoals(T mob) { -+ Set> goals = new HashSet<>(); -+ for (GoalType type : GoalType.values()) { -+ goals.addAll(getRunningGoals(mob, type)); -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getRunningGoals(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ getHandle(craftMob, type).getExecutingGoals() -+ .filter(item -> item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) -+ .forEach(item -> { -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ }); -+ return goals; -+ } -+ -+ @Override -+ public Collection> getRunningGoalsWithout(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ for (GoalType internalType : GoalType.values()) { -+ if (internalType == type) { -+ continue; -+ } -+ getHandle(craftMob, internalType).getExecutingGoals() -+ .filter(item -> !item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) -+ .forEach(item -> { -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ }); -+ } -+ return goals; -+ } -+ -+ private PathfinderGoalSelector getHandle(CraftMob mob, EnumSet types) { -+ if (types.contains(GoalType.TARGET)) { -+ return mob.getHandle().targetSelector; -+ } else { -+ return mob.getHandle().goalSelector; -+ } -+ } -+ -+ private PathfinderGoalSelector getHandle(CraftMob mob, GoalType type) { -+ if (type == GoalType.TARGET) { -+ return mob.getHandle().targetSelector; -+ } else { -+ return mob.getHandle().goalSelector; -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java -new file mode 100644 -index 0000000000000000000000000000000000000000..1ed6e7273bc84a406ca843bc47bb69314bb2dd74 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java -@@ -0,0 +1,62 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import java.util.EnumSet; -+ -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import org.bukkit.entity.Mob; -+ -+/** -+ * Wraps vanilla in api -+ */ -+public class PaperVanillaGoal implements VanillaGoal { -+ -+ private final PathfinderGoal handle; -+ private final GoalKey key; -+ -+ private final EnumSet types; -+ -+ public PaperVanillaGoal(PathfinderGoal handle) { -+ this.handle = handle; -+ this.key = MobGoalHelper.getKey(handle.getClass()); -+ this.types = MobGoalHelper.vanillaToPaper(handle.getGoalTypes()); -+ } -+ -+ public PathfinderGoal getHandle() { -+ return handle; -+ } -+ -+ @Override -+ public boolean shouldActivate() { -+ return handle.shouldActivate2(); -+ } -+ -+ @Override -+ public boolean shouldStayActive() { -+ return handle.shouldStayActive2(); -+ } -+ -+ @Override -+ public void start() { -+ handle.start(); -+ } -+ -+ @Override -+ public void stop() { -+ handle.onTaskReset(); -+ } -+ -+ @Override -+ public void tick() { -+ handle.tick(); -+ } -+ -+ @Override -+ public GoalKey getKey() { -+ return key; -+ } -+ -+ @Override -+ public EnumSet getTypes() { -+ return types; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -index 9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f..b3329c6fcd6758a781a51f5ba8f5052ac1c77b49 100644 ---- a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -+++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -@@ -64,4 +64,8 @@ public final class OptimizedSmallEnumSet> { - public boolean hasCommonElements(final OptimizedSmallEnumSet other) { - return (other.backingSet & this.backingSet) != 0; - } -+ -+ public boolean hasElement(final E element) { -+ return (this.backingSet & (1L << element.ordinal())) != 0; -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -index 5c32cbe81c47fcb9ae347faa6fc007c5d28d79bf..59ea1432152051ce8a60c0a526db787593f0e744 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -@@ -8,11 +8,17 @@ public abstract class PathfinderGoal { - private final EnumSet a = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. - private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector - -- public PathfinderGoal() {} -+ // Paper start make sure goaltypes is never empty -+ public PathfinderGoal() { -+ if (this.goalTypes.size() == 0) { -+ this.goalTypes.addUnchecked(Type.UNKNOWN_BEHAVIOR); -+ } -+ } -+ // paper end - -- public abstract boolean a(); -+ public boolean a() { return this.shouldActivate(); } public boolean shouldActivate() { return false;} public boolean shouldActivate2() { return a(); } // Paper - OBFHELPER, for both directions... - -- public boolean b() { -+ public boolean b() { return this.shouldStayActive(); } public boolean shouldStayActive2() { return b(); } public boolean shouldStayActive() { // Paper - OBFHELPER, for both directions... - return this.a(); - } - -@@ -20,19 +26,23 @@ public abstract class PathfinderGoal { - return true; - } - -- public void c() {} -+ public void c() { this.start(); } public void start() {} // Paper - OBFHELPER - - public void d() { - onTaskReset(); // Paper - } - public void onTaskReset() {} // Paper - -- public void e() {} -+ public void e() { this.tick(); } public void tick() {} // Paper OBFHELPER - -- public void a(EnumSet enumset) { -+ public void a(EnumSet enumset) { this.setTypes(enumset); } public void setTypes(EnumSet enumset) { // Paper - OBFHELPER - // Paper start - remove streams from pathfindergoalselector - this.goalTypes.clear(); - this.goalTypes.addAllUnchecked(enumset); -+ // make sure its never empty -+ if (this.goalTypes.size() == 0) { -+ this.goalTypes.addUnchecked(Type.UNKNOWN_BEHAVIOR); -+ } - // Paper end - remove streams from pathfindergoalselector - } - -@@ -48,7 +58,7 @@ public abstract class PathfinderGoal { - - public static enum Type { - -- MOVE, LOOK, JUMP, TARGET; -+ MOVE, LOOK, JUMP, TARGET, UNKNOWN_BEHAVIOR; // Paper - add unknown - - private Type() {} - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -index 385cd079e264a7e66e91ab3b70b90afb59688dcd..637928664f8c7b1c694a234e507c20724294e450 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -@@ -28,7 +28,7 @@ public class PathfinderGoalSelector { - } - }; - private final Map c = new EnumMap(PathfinderGoal.Type.class); -- private final Set d = Sets.newLinkedHashSet(); private Set getTasks() { return d; }// Paper - OBFHELPER -+ private final Set d = Sets.newLinkedHashSet(); public final Set getTasks() { return d; }// Paper - OBFHELPER // Paper - private -> public - private final Supplier e; - private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. - private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector -@@ -39,7 +39,7 @@ public class PathfinderGoalSelector { - this.e = supplier; - } - -- public void a(int i, PathfinderGoal pathfindergoal) { -+ public void addGoal(int priority, PathfinderGoal goal) {a(priority, goal);} public void a(int i, PathfinderGoal pathfindergoal) { // Paper - OBFHELPER - this.d.add(new PathfinderGoalWrapped(i, pathfindergoal)); - } - -@@ -58,7 +58,7 @@ public class PathfinderGoalSelector { - } - // Paper end - -- public void a(PathfinderGoal pathfindergoal) { -+ public void removeGoal(PathfinderGoal goal) {a(goal);} public void a(PathfinderGoal pathfindergoal) { // Paper - OBFHELPER - // Paper start - remove streams from pathfindergoalselector - for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { - PathfinderGoalWrapped goalWrapped = iterator.next(); -@@ -154,6 +154,7 @@ public class PathfinderGoalSelector { - gameprofilerfiller.exit(); - } - -+ public final Stream getExecutingGoals() { return d(); } // Paper - OBFHELPER - public Stream d() { - return this.d.stream().filter(PathfinderGoalWrapped::g); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -index 8c8e39d35fb56aa6cf7d456adab01dff5d13a60d..bcf6c924894f49f1c602b83b501f904e553235fd 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -@@ -5,8 +5,8 @@ import javax.annotation.Nullable; - - public class PathfinderGoalWrapped extends PathfinderGoal { - -- private final PathfinderGoal a; -- private final int b; -+ private final PathfinderGoal a; public PathfinderGoal getGoal() {return a;} // Paper - OBFHELPER -+ private final int b; public int getPriority() {return b;} // Paper - OBFHELPER - private boolean c; - - public PathfinderGoalWrapped(int i, PathfinderGoal pathfindergoal) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f6e2e54b5a1b8c2df41a0593fa15112c5195c49c..aa5efc9225bb58f9290b9aefcb5ef171c7a88e7d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2391,5 +2391,11 @@ public final class CraftServer implements Server { - public boolean isStopping() { - return net.minecraft.server.MinecraftServer.getServer().hasStopped(); - } -+ -+ private com.destroystokyo.paper.entity.ai.MobGoals mobGoals = new com.destroystokyo.paper.entity.ai.PaperMobGoals(); -+ @Override -+ public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { -+ return mobGoals; -+ } - // Paper end - } -diff --git a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c0525216a8469613c3e0d4b5774a82f69e70fb16 ---- /dev/null -+++ b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java -@@ -0,0 +1,104 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import org.junit.Assert; -+import org.junit.Test; -+ -+import java.lang.reflect.Field; -+import java.lang.reflect.Modifier; -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+import java.util.stream.Collectors; -+ -+import org.bukkit.entity.Mob; -+ -+import io.github.classgraph.ClassGraph; -+import io.github.classgraph.ScanResult; -+ -+public class VanillaMobGoalTest { -+ -+ @Test -+ public void testKeys() { -+ List> deprecated = new ArrayList<>(); -+ List> keys = new ArrayList<>(); -+ for (Field field : VanillaGoal.class.getFields()) { -+ if (field.getType().equals(GoalKey.class)) { -+ try { -+ GoalKey goalKey = (GoalKey) field.get(null); -+ if (field.getAnnotation(Deprecated.class) != null) { -+ deprecated.add(goalKey); -+ } else { -+ keys.add(goalKey); -+ } -+ } catch (IllegalAccessException e) { -+ System.out.println("Skipping " + field.getName() + ": " + e.getMessage()); -+ } -+ } -+ } -+ -+ List> classes; -+ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) { -+ classes = scanResult.getSubclasses(PathfinderGoal.class.getName()).loadClasses(); -+ } -+ -+ List> vanillaNames = classes.stream() -+ .filter(VanillaMobGoalTest::hasNoEnclosingClass) -+ .filter(clazz -> !Modifier.isAbstract(clazz.getModifiers())) -+ .map(goalClass -> MobGoalHelper.getKey((Class) goalClass)) -+ .collect(Collectors.toList()); -+ -+ List> missingFromAPI = new ArrayList<>(vanillaNames); -+ missingFromAPI.removeAll(keys); -+ missingFromAPI.removeIf(k -> MobGoalHelper.ignored.contains(k.getNamespacedKey().getKey())); -+ List> missingFromVanilla = new ArrayList<>(keys); -+ missingFromVanilla.removeAll(vanillaNames); -+ -+ boolean shouldFail = false; -+ if (missingFromAPI.size() != 0) { -+ System.out.println("Missing from API: "); -+ for (GoalKey key : missingFromAPI) { -+ System.out.println("GoalKey<" + key.getEntityClass().getSimpleName() + "> " + key.getNamespacedKey().getKey().toUpperCase() + -+ " = GoalKey.of(" + key.getEntityClass().getSimpleName() + ".class, NamespacedKey.minecraft(\"" + key.getNamespacedKey().getKey() + "\"));"); -+ } -+ shouldFail = true; -+ } -+ if (missingFromVanilla.size() != 0) { -+ System.out.println("Missing from vanilla: "); -+ missingFromVanilla.forEach(System.out::println); -+ shouldFail = true; -+ } -+ -+ if (deprecated.size() != 0) { -+ System.out.println("Deprecated (might want to remove them at some point): "); -+ deprecated.forEach(System.out::println); -+ } -+ -+ if (shouldFail) Assert.fail("See above"); -+ } -+ -+ private static boolean hasNoEnclosingClass(Class clazz) { -+ return clazz.getEnclosingClass() == null || hasNoEnclosingClass(clazz.getSuperclass()); -+ } -+ -+ @Test -+ public void testBukkitMap() { -+ List> classes; -+ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft.world.entity").scan()) { -+ classes = scanResult.getSubclasses("net.minecraft.world.entity.EntityInsentient").loadClasses(); -+ } -+ Assert.assertNotEquals("There are supposed to be more than 0 entity types!", Collections.emptyList(), classes); -+ -+ boolean shouldFail = false; -+ for (Class nmsClass : classes) { -+ Class bukkitClass = MobGoalHelper.toBukkitClass((Class) nmsClass); -+ if (bukkitClass == null) { -+ shouldFail = true; -+ System.out.println("Missing bukkitMap.put(" + nmsClass.getSimpleName() + ".class, " + nmsClass.getSimpleName().replace("Entity", "") + ".class);"); -+ } -+ } -+ -+ if (shouldFail) Assert.fail("See above"); -+ } -+} diff --git a/Unmapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch b/Unmapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch deleted file mode 100644 index 0eecb7f13e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch +++ /dev/null @@ -1,413 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 20:18:05 -0700 -Subject: [PATCH] Use distance map to optimise entity tracker - -Use the distance map to find candidate players for tracking. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 7f67773686a2d55153f7b2bfbe24df84fe1198be..1eb1da61ee2aa2cc5d28a46fd364a182cd16983b 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1654,6 +1654,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant list = this.tracker.getPassengers(); - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index d509cfd2da99233e5142abd176cc50ccea7c32b6..9fc74f08b912ff885c9478167c7ef173c32f1654 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -61,6 +61,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; - import net.minecraft.network.protocol.game.PacketPlayOutMount; - import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.progress.WorldLoadListener; - import net.minecraft.util.CSVWriter; - import net.minecraft.util.EntitySlice; -@@ -195,21 +196,55 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - // Paper start - distance maps - private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); -+ // Paper start - use distance map to optimise tracker -+ public static boolean isLegacyTrackingEntity(Entity entity) { -+ return entity.isLegacyTrackingEntity; -+ } -+ -+ // inlined EnumMap, TrackingRange.TrackingRangeType -+ static final org.spigotmc.TrackingRange.TrackingRangeType[] TRACKING_RANGE_TYPES = org.spigotmc.TrackingRange.TrackingRangeType.values(); -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap[] playerEntityTrackerTrackMaps; -+ final int[] entityTrackerTrackRanges; -+ -+ private int convertSpigotRangeToVanilla(final int vanilla) { -+ return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); -+ } -+ // Paper end - use distance map to optimise tracker - - void addPlayerToDistanceMaps(EntityPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.locX()); - int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); - // Note: players need to be explicitly added to distance maps before they can be updated -+ // Paper start - use distance map to optimise entity tracker -+ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -+ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; -+ int trackRange = this.entityTrackerTrackRanges[i]; -+ -+ trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); -+ } -+ // Paper end - use distance map to optimise entity tracker - } - - void removePlayerFromDistanceMaps(EntityPlayer player) { -- -+ // Paper start - use distance map to optimise tracker -+ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -+ this.playerEntityTrackerTrackMaps[i].remove(player); -+ } -+ // Paper end - use distance map to optimise tracker - } - - void updateMaps(EntityPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.locX()); - int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); - // Note: players need to be explicitly added to distance maps before they can be updated -+ // Paper start - use distance map to optimise entity tracker -+ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -+ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; -+ int trackRange = this.entityTrackerTrackRanges[i]; -+ -+ trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); -+ } -+ // Paper end - use distance map to optimise entity tracker - } - // Paper end - -@@ -246,6 +281,45 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper - this.setViewDistance(i); - this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper -+ // Paper start - use distance map to optimise entity tracker -+ this.playerEntityTrackerTrackMaps = new com.destroystokyo.paper.util.misc.PlayerAreaMap[TRACKING_RANGE_TYPES.length]; -+ this.entityTrackerTrackRanges = new int[TRACKING_RANGE_TYPES.length]; -+ -+ org.spigotmc.SpigotWorldConfig spigotWorldConfig = this.world.spigotConfig; -+ -+ for (int ordinal = 0, len = TRACKING_RANGE_TYPES.length; ordinal < len; ++ordinal) { -+ org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = TRACKING_RANGE_TYPES[ordinal]; -+ int configuredSpigotValue; -+ switch (trackingRangeType) { -+ case PLAYER: -+ configuredSpigotValue = spigotWorldConfig.playerTrackingRange; -+ break; -+ case ANIMAL: -+ configuredSpigotValue = spigotWorldConfig.animalTrackingRange; -+ break; -+ case MONSTER: -+ configuredSpigotValue = spigotWorldConfig.monsterTrackingRange; -+ break; -+ case MISC: -+ configuredSpigotValue = spigotWorldConfig.miscTrackingRange; -+ break; -+ case OTHER: -+ configuredSpigotValue = spigotWorldConfig.otherTrackingRange; -+ break; -+ case ENDERDRAGON: -+ configuredSpigotValue = EntityTypes.ENDER_DRAGON.getChunkRange() * 16; -+ break; -+ default: -+ throw new IllegalStateException("Missing case for enum " + trackingRangeType); -+ } -+ configuredSpigotValue = convertSpigotRangeToVanilla(configuredSpigotValue); -+ -+ int trackRange = (configuredSpigotValue >>> 4) + ((configuredSpigotValue & 15) != 0 ? 1 : 0); -+ this.entityTrackerTrackRanges[ordinal] = trackRange; -+ -+ this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); -+ } -+ // Paper end - use distance map to optimise entity tracker - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -1492,17 +1566,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - public void movePlayer(EntityPlayer entityplayer) { -- ObjectIterator objectiterator = this.trackedEntities.values().iterator(); -- -- while (objectiterator.hasNext()) { -- PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); -- -- if (playerchunkmap_entitytracker.tracker == entityplayer) { -- playerchunkmap_entitytracker.track(this.world.getPlayers()); -- } else { -- playerchunkmap_entitytracker.updatePlayer(entityplayer); -- } -- } -+ // Paper - delay this logic for the entity tracker tick, no need to duplicate it - - int i = MathHelper.floor(entityplayer.locX()) >> 4; - int j = MathHelper.floor(entityplayer.locZ()) >> 4; -@@ -1618,7 +1682,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker - this.trackedEntities.put(entity.getId(), playerchunkmap_entitytracker); -- playerchunkmap_entitytracker.track(this.world.getPlayers()); -+ playerchunkmap_entitytracker.updatePlayers(entity.getPlayersInTrackRange()); // Paper - don't search all players - if (entity instanceof EntityPlayer) { - EntityPlayer entityplayer = (EntityPlayer) entity; - -@@ -1661,7 +1725,37 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - entity.tracker = null; // Paper - We're no longer tracked - } - -+ // Paper start - optimised tracker -+ private final void processTrackQueue() { -+ this.world.timings.tracker1.startTiming(); -+ try { -+ for (EntityTracker tracker : this.trackedEntities.values()) { -+ // update tracker entry -+ tracker.updatePlayers(tracker.tracker.getPlayersInTrackRange()); -+ } -+ } finally { -+ this.world.timings.tracker1.stopTiming(); -+ } -+ -+ -+ this.world.timings.tracker2.startTiming(); -+ try { -+ for (EntityTracker tracker : this.trackedEntities.values()) { -+ tracker.trackerEntry.tick(); -+ } -+ } finally { -+ this.world.timings.tracker2.stopTiming(); -+ } -+ } -+ // Paper end - optimised tracker -+ - protected void g() { -+ // Paper start - optimized tracker -+ if (true) { -+ this.processTrackQueue(); -+ return; -+ } -+ // Paper end - optimized tracker - List list = Lists.newArrayList(); - List list1 = this.world.getPlayers(); - -@@ -1730,23 +1824,31 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - PacketDebug.a(this.world, chunk.getPos()); - List list = Lists.newArrayList(); - List list1 = Lists.newArrayList(); -- ObjectIterator objectiterator = this.trackedEntities.values().iterator(); -+ // Paper start - optimise entity tracker -+ // use the chunk entity list, not the whole trackedEntities map... -+ Entity[] entities = chunk.entities.getRawData(); -+ for (int i = 0, size = chunk.entities.size(); i < size; ++i) { -+ Entity entity = entities[i]; -+ if (entity == entityplayer) { -+ continue; -+ } -+ PlayerChunkMap.EntityTracker tracker = this.trackedEntities.get(entity.getId()); -+ if (tracker != null) { // dumb plugins... move on... -+ tracker.updatePlayer(entityplayer); -+ } - -- while (objectiterator.hasNext()) { -- PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); -- Entity entity = playerchunkmap_entitytracker.tracker; -+ // keep the vanilla logic here - this is REQUIRED or else passengers and their vehicles disappear! -+ // (and god knows what the leash thing is) - -- if (entity != entityplayer && entity.chunkX == chunk.getPos().x && entity.chunkZ == chunk.getPos().z) { -- playerchunkmap_entitytracker.updatePlayer(entityplayer); -- if (entity instanceof EntityInsentient && ((EntityInsentient) entity).getLeashHolder() != null) { -- list.add(entity); -- } -+ if (entity instanceof EntityInsentient && ((EntityInsentient)entity).getLeashHolder() != null) { -+ list.add(entity); -+ } - -- if (!entity.getPassengers().isEmpty()) { -- list1.add(entity); -- } -+ if (!entity.getPassengers().isEmpty()) { -+ list1.add(entity); - } - } -+ // Paper end - optimise entity tracker - - Iterator iterator; - Entity entity1; -@@ -1784,7 +1886,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - public class EntityTracker { - -- private final EntityTrackerEntry trackerEntry; -+ final EntityTrackerEntry trackerEntry; // Paper - private -> package private - private final Entity tracker; - private final int trackingDistance; - private SectionPosition e; -@@ -1801,6 +1903,42 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.e = SectionPosition.a(entity); - } - -+ // Paper start - use distance map to optimise tracker -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet lastTrackerCandidates; -+ -+ final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet oldTrackerCandidates = this.lastTrackerCandidates; -+ this.lastTrackerCandidates = newTrackerCandidates; -+ -+ if (newTrackerCandidates != null) { -+ Object[] rawData = newTrackerCandidates.getBackingSet(); -+ for (int i = 0, len = rawData.length; i < len; ++i) { -+ Object raw = rawData[i]; -+ if (!(raw instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)raw; -+ this.updatePlayer(player); -+ } -+ } -+ -+ if (oldTrackerCandidates == newTrackerCandidates) { -+ // this is likely the case. -+ // means there has been no range changes, so we can just use the above for tracking. -+ return; -+ } -+ -+ // stuff could have been removed, so we need to check the trackedPlayers set -+ // for players that were removed -+ -+ for (EntityPlayer player : this.trackedPlayers.toArray(new EntityPlayer[0])) { // avoid CME -+ if (newTrackerCandidates == null || !newTrackerCandidates.contains(player)) { -+ this.updatePlayer(player); -+ } -+ } -+ } -+ // Paper end - use distance map to optimise tracker -+ - public boolean equals(Object object) { - return object instanceof PlayerChunkMap.EntityTracker ? ((PlayerChunkMap.EntityTracker) object).tracker.getId() == this.tracker.getId() : false; - } -@@ -1901,7 +2039,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - int j = entity.getEntityType().getChunkRange() * 16; - j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper - -- if (j > i) { -+ if (j < i) { // Paper - we need the lowest range thanks to the fact that our tracker doesn't account for passenger logic - i = j; - } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 8d8d94219f9a556212763fce736452a19249ffec..b244f5d204938452ea19335947830de47336bbd4 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -46,6 +46,7 @@ import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunkMap; -@@ -295,6 +296,21 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - -+ // Paper start - optimise entity tracking -+ final org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = org.spigotmc.TrackingRange.getTrackingRangeType(this); -+ -+ public boolean isLegacyTrackingEntity = false; -+ -+ public final void setLegacyTrackingEntity(final boolean isLegacyTrackingEntity) { -+ this.isLegacyTrackingEntity = isLegacyTrackingEntity; -+ } -+ -+ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayersInTrackRange() { -+ return ((WorldServer)this.world).getChunkProvider().playerChunkMap.playerEntityTrackerTrackMaps[this.trackingRangeType.ordinal()] -+ .getObjectsInRange(MCUtil.getCoordinateKey(this)); -+ } -+ // Paper end - optimise entity tracking -+ - public Entity(EntityTypes entitytypes, World world) { - this.id = Entity.entityCount.incrementAndGet(); - this.passengers = Lists.newArrayList(); -diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java -index 3277a8aaffb6a25624967aa0c62f61309a517739..cd569ad95176fdd0537459b40dfba5c5127a62df 100644 ---- a/src/main/java/org/spigotmc/TrackingRange.java -+++ b/src/main/java/org/spigotmc/TrackingRange.java -@@ -21,6 +21,7 @@ public class TrackingRange - */ - public static int getEntityTrackingRange(Entity entity, int defaultRange) - { -+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return defaultRange; // Paper - enderdragon is exempt - SpigotWorldConfig config = entity.world.spigotConfig; - if ( entity instanceof EntityPlayer ) - { -@@ -44,8 +45,48 @@ public class TrackingRange - return config.miscTrackingRange; - } else - { -- if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return ((net.minecraft.server.level.WorldServer)(entity.getWorld())).getChunkProvider().playerChunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt - return config.otherTrackingRange; - } - } -+ -+ // Paper start - optimise entity tracking -+ // copied from above, TODO check on update -+ public static TrackingRangeType getTrackingRangeType(Entity entity) -+ { -+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return TrackingRangeType.ENDERDRAGON; // Paper - enderdragon is exempt -+ if ( entity instanceof EntityPlayer ) -+ { -+ return TrackingRangeType.PLAYER; -+ // Paper start - Simplify and set water mobs to animal tracking range -+ } -+ switch (entity.activationType) { -+ case RAIDER: -+ case MONSTER: -+ case FLYING_MONSTER: -+ return TrackingRangeType.MONSTER; -+ case WATER: -+ case VILLAGER: -+ case ANIMAL: -+ return TrackingRangeType.ANIMAL; -+ case MISC: -+ } -+ if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) -+ // Paper end -+ { -+ return TrackingRangeType.MISC; -+ } else -+ { -+ return TrackingRangeType.OTHER; -+ } -+ } -+ -+ public static enum TrackingRangeType { -+ PLAYER, -+ ANIMAL, -+ MONSTER, -+ MISC, -+ OTHER, -+ ENDERDRAGON; -+ } -+ // Paper end - optimise entity tracking - } diff --git a/Unmapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch b/Unmapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch deleted file mode 100644 index 9fedfd9a43..0000000000 --- a/Unmapped-Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch +++ /dev/null @@ -1,384 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 20:40:53 -0700 -Subject: [PATCH] Optimize isOutsideRange to use distance maps - -Use a distance map to find the players in range quickly - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 60fcea78bf617559114b1ca1c0bf2d4cd9075a8c..335666db1854e8aa4b2ba71d5bdc2658305cb70a 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -37,7 +37,7 @@ public abstract class ChunkMapDistance { - private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); - public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); - private final ChunkMapDistance.a ticketLevelTracker = new ChunkMapDistance.a(); -- private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); -+ public static final int MOB_SPAWN_RANGE = 8; // private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used - private final ChunkMapDistance.c g = new ChunkMapDistance.c(33); - // Paper start use a queue, but still keep unique requirement - public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { -@@ -56,6 +56,8 @@ public abstract class ChunkMapDistance { - private final Executor m; - private long currentTick; - -+ PlayerChunkMap chunkMap; // Paper -+ - protected ChunkMapDistance(Executor executor, Executor executor1) { - executor1.getClass(); - Mailbox mailbox = Mailbox.a("player ticket throttler", executor1::execute); -@@ -100,7 +102,7 @@ public abstract class ChunkMapDistance { - protected abstract PlayerChunk a(long i, int j, @Nullable PlayerChunk playerchunk, int k); - - public boolean a(PlayerChunkMap playerchunkmap) { -- this.f.a(); -+ //this.f.a(); // Paper - no longer used - this.g.a(); - int i = Integer.MAX_VALUE - this.ticketLevelTracker.a(Integer.MAX_VALUE); - boolean flag = i != 0; -@@ -236,7 +238,7 @@ public abstract class ChunkMapDistance { - ((ObjectSet) this.c.computeIfAbsent(i, (j) -> { - return new ObjectOpenHashSet(); - })).add(entityplayer); -- this.f.update(i, 0, true); -+ //this.f.update(i, 0, true); // Paper - no longer used - this.g.update(i, 0, true); - } - -@@ -248,7 +250,7 @@ public abstract class ChunkMapDistance { - if (objectset != null) objectset.remove(entityplayer); // Paper - some state corruption happens here, don't crash, clean up gracefully. - if (objectset == null || objectset.isEmpty()) { // Paper - this.c.remove(i); -- this.f.update(i, Integer.MAX_VALUE, false); -+ //this.f.update(i, Integer.MAX_VALUE, false); // Paper - no longer used - this.g.update(i, Integer.MAX_VALUE, false); - } - -@@ -272,13 +274,17 @@ public abstract class ChunkMapDistance { - } - - public int b() { -- this.f.a(); -- return this.f.a.size(); -+ // Paper start - use distance map to implement -+ // note: this is the spawn chunk count -+ return this.chunkMap.playerChunkTickRangeMap.size(); -+ // Paper end - use distance map to implement - } - - public boolean d(long i) { -- this.f.a(); -- return this.f.a.containsKey(i); -+ // Paper start - use distance map to implement -+ // note: this is the is spawn chunk method -+ return this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(i) != null; -+ // Paper end - use distance map to implement - } - - public String c() { -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index fc7140e0eb11e4bec99e453647fce200bca0ed7f..46a2e89df71654024102427859c385fc2e09cae7 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -753,6 +753,37 @@ public class ChunkProviderServer extends IChunkProvider { - boolean flag1 = this.world.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && !world.getPlayers().isEmpty(); // CraftBukkit - - if (!flag) { -+ // Paper start - optimize isOutisdeRange -+ PlayerChunkMap playerChunkMap = this.playerChunkMap; -+ for (EntityPlayer player : this.world.players) { -+ if (!player.affectsSpawning || player.isSpectator()) { -+ playerChunkMap.playerMobSpawnMap.remove(player); -+ continue; -+ } -+ -+ int viewDistance = this.playerChunkMap.getEffectiveViewDistance(); -+ -+ // copied and modified from isOutisdeRange -+ int chunkRange = world.spigotConfig.mobSpawnRange; -+ chunkRange = (chunkRange > viewDistance) ? (byte)viewDistance : chunkRange; -+ chunkRange = (chunkRange > ChunkMapDistance.MOB_SPAWN_RANGE) ? ChunkMapDistance.MOB_SPAWN_RANGE : chunkRange; -+ -+ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(player.getBukkitEntity(), (byte)chunkRange); -+ event.callEvent(); -+ if (event.isCancelled() || event.getSpawnRadius() < 0 || playerChunkMap.playerChunkTickRangeMap.getLastViewDistance(player) == -1) { -+ playerChunkMap.playerMobSpawnMap.remove(player); -+ continue; -+ } -+ -+ int range = Math.min(event.getSpawnRadius(), 32); // limit to max view distance -+ int chunkX = net.minecraft.server.MCUtil.getChunkCoordinate(player.locX()); -+ int chunkZ = net.minecraft.server.MCUtil.getChunkCoordinate(player.locZ()); -+ -+ playerChunkMap.playerMobSpawnMap.addOrUpdate(player, chunkX, chunkZ, range); -+ player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in isOutsideRange -+ player.playerNaturallySpawnedEvent = event; -+ } -+ // Paper end - optimize isOutisdeRange - this.world.getMethodProfiler().enter("pollingChunks"); - int k = this.world.getGameRules().getInt(GameRules.RANDOM_TICK_SPEED); - boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit -@@ -782,15 +813,7 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.getMethodProfiler().exit(); - //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper - //Collections.shuffle(list); // Paper -- //Paper start - call player naturally spawn event -- int chunkRange = world.spigotConfig.mobSpawnRange; -- chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; -- chunkRange = Math.min(chunkRange, 8); -- for (EntityPlayer entityPlayer : this.world.getPlayers()) { -- entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); -- entityPlayer.playerNaturallySpawnedEvent.callEvent(); -- }; -- // Paper end -+ // Paper - moved up - this.world.timings.chunkTicks.startTiming(); // Paper - final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); -@@ -807,9 +830,9 @@ public class ChunkProviderServer extends IChunkProvider { - Chunk chunk = (Chunk) optional1.get(); - ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); - -- if (!this.playerChunkMap.isOutsideOfRange(chunkcoordintpair)) { -+ if (!this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange - chunk.setInhabitedTime(chunk.getInhabitedTime() + j); -- if (flag1 && (this.allowMonsters || this.allowAnimals) && this.world.getWorldBorder().isInBounds(chunk.getPos()) && !this.playerChunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot -+ if (flag1 && (this.allowMonsters || this.allowAnimals) && this.world.getWorldBorder().isInBounds(chunk.getPos()) && !this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange - SpawnerCreature.a(this.world, chunk, spawnercreature_d, this.allowAnimals, this.allowMonsters, flag2); - } - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 39fb3a1445338c3ac1642b8e518eb8d1031f9a5c..62ed75ae7ec492d8502776fdf3cf3ee461a38a53 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -250,6 +250,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper - -+ double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks -+ - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); - this.spawnDimension = World.OVERWORLD; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 445dba8ed210407664904b707c36c78a76f25510..25484cac9c62e49de39fbbf506fcb3edc4ba6e65 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -70,6 +70,18 @@ public class PlayerChunk { - long lastAutoSaveTime; // Paper - incremental autosave - long inactiveTimeStart; // Paper - incremental autosave - -+ // Paper start - optimise isOutsideOfRange -+ // cached here to avoid a map lookup -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInMobSpawnRange; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInChunkTickRange; -+ -+ void updateRanges() { -+ long key = net.minecraft.server.MCUtil.getCoordinateKey(this.location); -+ this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key); -+ this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); -+ } -+ // Paper end - optimise isOutsideOfRange -+ - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -@@ -86,6 +98,7 @@ public class PlayerChunk { - this.n = this.oldTicketLevel; - this.a(i); - this.chunkMap = (PlayerChunkMap)playerchunk_d; // Paper -+ this.updateRanges(); // Paper - optimise isOutsideOfRange - } - - // Paper start -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 9fc74f08b912ff885c9478167c7ef173c32f1654..a6bb8e3b9e73f81bfa92ac13df27e9c44dd9e311 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -210,6 +210,17 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); - } - // Paper end - use distance map to optimise tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ // A note about the naming used here: -+ // Previously, mojang used a "spawn range" of 8 for controlling both ticking and -+ // mob spawn range. However, spigot makes the spawn range configurable by -+ // checking if the chunk is in the tick range (8) and the spawn range -+ // obviously this means a spawn range > 8 cannot be implemented -+ -+ // these maps are named after spigot's uses -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - - void addPlayerToDistanceMaps(EntityPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.locX()); -@@ -223,6 +234,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); - } - // Paper end - use distance map to optimise entity tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - void removePlayerFromDistanceMaps(EntityPlayer player) { -@@ -231,6 +245,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerEntityTrackerTrackMaps[i].remove(player); - } - // Paper end - use distance map to optimise tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerMobSpawnMap.remove(player); -+ this.playerChunkTickRangeMap.remove(player); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - void updateMaps(EntityPlayer player) { -@@ -245,6 +263,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); - } - // Paper end - use distance map to optimise entity tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - // Paper end - -@@ -276,7 +297,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.mailboxWorldGen = this.p.a(threadedmailbox, false); - this.mailboxMain = this.p.a(mailbox, false); - this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false)); -- this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); -+ this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); this.chunkDistanceManager.chunkMap = this; // Paper - this.l = supplier; - this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper - this.setViewDistance(i); -@@ -320,6 +341,38 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); - } - // Paper end - use distance map to optimise entity tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerChunkTickRangeMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInChunkTickRange = newState; -+ } -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInChunkTickRange = newState; -+ } -+ }); -+ this.playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInMobSpawnRange = newState; -+ } -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInMobSpawnRange = newState; -+ } -+ }); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -339,6 +392,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return entityPlayer.mobCounts[enumCreatureType.ordinal()]; - } - -+ private static double getDistanceSquaredFromChunk(ChunkCoordIntPair chunkPos, Entity entity) { return a(chunkPos, entity); } // Paper - OBFHELPER - private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) { - double d0 = (double) (chunkcoordintpair.x * 16 + 8); - double d1 = (double) (chunkcoordintpair.z * 16 + 8); -@@ -517,6 +571,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } else { - if (playerchunk != null) { - playerchunk.a(j); -+ playerchunk.updateRanges(); // Paper - optimise isOutsideOfRange - } - - if (playerchunk != null) { -@@ -1495,30 +1550,53 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return isOutsideOfRange(chunkcoordintpair, false); - } - -- boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { -- int chunkRange = world.spigotConfig.mobSpawnRange; -- chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; -- chunkRange = (chunkRange > 8) ? 8 : chunkRange; -+ // Paper start - optimise isOutsideOfRange -+ final boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { -+ return this.isOutsideOfRange(this.getUpdatingChunk(chunkcoordintpair.pair()), chunkcoordintpair, reducedRange); -+ } - -- final int finalChunkRange = chunkRange; // Paper for lambda below -- //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event -- // Spigot end -- long i = chunkcoordintpair.pair(); -+ final boolean isOutsideOfRange(PlayerChunk playerchunk, ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { -+ // this function is so hot that removing the map lookup call can have an order of magnitude impact on its performance -+ // tested and confirmed via System.nanoTime() -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInRange = reducedRange ? playerchunk.playersInMobSpawnRange : playerchunk.playersInChunkTickRange; - -- return !this.chunkDistanceManager.d(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { -- // Paper start - -- com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; -- double blockRange = 16384.0D; -- if (reducedRange) { -- event = entityplayer.playerNaturallySpawnedEvent; -- if (event == null || event.isCancelled()) return false; -- blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); -- } -+ if (playersInRange == null) { -+ return true; -+ } - -- return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot -- // Paper end -- }); -+ Object[] backingSet = playersInRange.getBackingSet(); -+ -+ if (reducedRange) { -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object raw = backingSet[i]; -+ if (!(raw instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer) raw; -+ // don't check spectator and whatnot, already handled by mob spawn map update -+ if (player.lastEntitySpawnRadiusSquared > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { -+ return false; // in range -+ } -+ } -+ } else { -+ final double range = (ChunkMapDistance.MOB_SPAWN_RANGE * 16) * (ChunkMapDistance.MOB_SPAWN_RANGE * 16); -+ // before spigot, mob spawn range was actually mob spawn range + tick range, but it was split -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object raw = backingSet[i]; -+ if (!(raw instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer) raw; -+ // don't check spectator and whatnot, already handled by mob spawn map update -+ if (range > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { -+ return false; // in range -+ } -+ } -+ } -+ // no players in range -+ return true; - } -+ // Paper end - optimise isOutsideOfRange - - private boolean b(EntityPlayer entityplayer) { - return entityplayer.isSpectator() && !this.world.getGameRules().getBoolean(GameRules.SPECTATORS_GENERATE_CHUNKS); diff --git a/Unmapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch b/Unmapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch deleted file mode 100644 index ef0648a1f5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch +++ /dev/null @@ -1,319 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Apr 2020 04:05:38 -0700 -Subject: [PATCH] Stop copy-on-write operations for updating light data - -Causes huge memory allocations + gc issues - -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -index 5f3d2c090d098834e38e447d93f1ea8184c8fb3e..5b1ff4ff87591dd4ff0b79e4ac6ff0494fc3d0f8 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -@@ -26,8 +26,8 @@ public abstract class LightEngineStorage> e - protected final LongSet b = new LongOpenHashSet(); - protected final LongSet c = new LongOpenHashSet(); - protected final LongSet d = new LongOpenHashSet(); -- protected volatile M e; -- protected final M f; -+ protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change -+ protected final M f; // Paper - diff on change, should be "updating" - protected final LongSet g = new LongOpenHashSet(); - protected final LongSet h = new LongOpenHashSet(); - protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); -@@ -41,8 +41,8 @@ public abstract class LightEngineStorage> e - this.l = enumskyblock; - this.m = ilightaccess; - this.f = m0; -- this.e = m0.b(); -- this.e.d(); -+ this.e_visible = m0.b(); // Paper - avoid copying light data -+ this.e_visible.d(); // Paper - avoid copying light data - } - - protected boolean g(long i) { -@@ -51,7 +51,15 @@ public abstract class LightEngineStorage> e - - @Nullable - protected NibbleArray a(long i, boolean flag) { -- return this.a(flag ? this.f : this.e, i); -+ // Paper start - avoid copying light data -+ if (flag) { -+ return this.a(this.f, i); -+ } else { -+ synchronized (this.visibleUpdateLock) { -+ return this.a(this.e_visible, i); -+ } -+ } -+ // Paper end - avoid copying light data - } - - @Nullable -@@ -364,10 +372,12 @@ public abstract class LightEngineStorage> e - - protected void e() { - if (!this.g.isEmpty()) { -+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data - M m0 = this.f.b(); - - m0.d(); -- this.e = m0; -+ this.e_visible = m0; // Paper - avoid copying light data -+ } // Paper - avoid copying light data - this.g.clear(); - } - -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -index 242a2c5dea1241b515b9eee7c334ab3c31ad9d12..ed7864c552054fc47c6010a094230ce4aebf1c54 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -@@ -9,10 +9,23 @@ public abstract class LightEngineStorageArray a; -- -- protected LightEngineStorageArray(Long2ObjectOpenHashMap long2objectopenhashmap) { -- this.a = long2objectopenhashmap; -+ protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data -+ protected final boolean isVisible; // Paper - avoid copying light data -+ java.util.function.Function lookup; // Paper - faster branchless lookup -+ -+ // Paper start - avoid copying light data -+ protected LightEngineStorageArray(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { -+ if (isVisible) { -+ data.performUpdatesLockMap(); -+ } -+ this.data = data; -+ this.isVisible = isVisible; -+ if (isVisible) { -+ lookup = data::getVisibleAsync; -+ } else { -+ lookup = data::getUpdating; -+ } -+ // Paper end - avoid copying light data - this.c(); - this.d = true; - } -@@ -20,16 +33,17 @@ public abstract class LightEngineStorageArray { - - protected LightEngineStorageBlock(ILightAccess ilightaccess) { -- super(EnumSkyBlock.BLOCK, ilightaccess, new LightEngineStorageBlock.a(new Long2ObjectOpenHashMap())); -+ super(EnumSkyBlock.BLOCK, ilightaccess, new LightEngineStorageBlock.a(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data - } - - @Override -@@ -23,13 +23,13 @@ public class LightEngineStorageBlock extends LightEngineStorage { - -- public a(Long2ObjectOpenHashMap long2objectopenhashmap) { -- super(long2objectopenhashmap); -+ public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data -+ super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data - } - - @Override - public LightEngineStorageBlock.a b() { -- return new LightEngineStorageBlock.a(this.a.clone()); -+ return new a(this.data, true); // Paper - avoid copying light data - } - } - } -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -index befc8f846c772d58ee687ad427bb71206b4dc43e..64d37f4c6a8167f47c80953a388ea6635490563a 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -@@ -23,15 +23,16 @@ public class LightEngineStorageSky extends LightEngineStorage(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data - } - - @Override - protected int d(long i) { - long j = SectionPosition.e(i); - int k = SectionPosition.c(j); -- LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e; -- int l = lightenginestoragesky_a.c.get(SectionPosition.f(j)); -+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data -+ LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e_visible; // Paper - avoid copying light data - must be after lock acquire -+ int l = lightenginestoragesky_a.otherData.getVisibleAsync(SectionPosition.f(j)); // Paper - avoid copying light data - - if (l != lightenginestoragesky_a.b && k < l) { - NibbleArray nibblearray = this.a(lightenginestoragesky_a, j); // Paper - decompile fix -@@ -52,6 +53,7 @@ public class LightEngineStorageSky extends LightEngineStorage j) { - ((LightEngineStorageSky.a) this.f).b = j; -- ((LightEngineStorageSky.a) this.f).c.defaultReturnValue(((LightEngineStorageSky.a) this.f).b); -+ ((LightEngineStorageSky.a) this.f).otherData.queueDefaultReturnValue(((LightEngineStorageSky.a) this.f).b); // Paper - avoid copying light data - } - - long k = SectionPosition.f(i); -- int l = ((LightEngineStorageSky.a) this.f).c.get(k); -+ int l = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(k); // Paper - avoid copying light data - - if (l < j + 1) { -- ((LightEngineStorageSky.a) this.f).c.put(k, j + 1); -+ ((LightEngineStorageSky.a) this.f).otherData.queueUpdate(k, j + 1); // Paper - avoid copying light data - if (this.o.contains(k)) { - this.q(i); - if (l > ((LightEngineStorageSky.a) this.f).b) { -@@ -107,7 +109,7 @@ public class LightEngineStorageSky extends LightEngineStorage= k; - } -@@ -327,18 +329,21 @@ public class LightEngineStorageSky extends LightEngineStorage { - - private int b; -- private final Long2IntOpenHashMap c; -- -- public a(Long2ObjectOpenHashMap long2objectopenhashmap, Long2IntOpenHashMap long2intopenhashmap, int i) { -- super(long2objectopenhashmap); -- this.c = long2intopenhashmap; -- long2intopenhashmap.defaultReturnValue(i); -+ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data -+ -+ // Paper start - avoid copying light data -+ public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData, int i, boolean isVisible) { -+ super(data, isVisible); -+ this.otherData = otherData; -+ otherData.queueDefaultReturnValue(i); -+ // Paper end - avoid copying light data - this.b = i; - } - - @Override - public LightEngineStorageSky.a b() { -- return new LightEngineStorageSky.a(this.a.clone(), this.c.clone(), this.b); -+ this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data -+ return new LightEngineStorageSky.a(this.data, this.otherData, this.b, true); // Paper - avoid copying light data - } - } - } diff --git a/Unmapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch b/Unmapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch deleted file mode 100644 index 1e68582fcf..0000000000 --- a/Unmapped-Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch +++ /dev/null @@ -1,774 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 21:23:34 -0700 -Subject: [PATCH] No-Tick view distance implementation - -Implements world view distance getters/setters - -Per-Player is absent due to difficulty of maintaining -the diff required to make it happen. - -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index c9164dfdb27ddf3709129c8aec54903a1df121ff..e33e889c291d37a821a4fbd40d9aac7bb079de0d 100644 ---- a/src/main/java/co/aikar/timings/TimingsExport.java -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -153,7 +153,8 @@ public class TimingsExport extends Thread { - pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { - return pair(rule, world.getWorld().getGameRuleValue(rule)); - })), -- pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) -+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()), -+ pair("notick-viewdistance", world.getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance()) - )); - })); - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 46ac6d91422423f1e03b86d3efa3241f2599000d..6463d3e4837d032a35654a035f42b8a805e0e286 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -632,4 +632,9 @@ public class PaperWorldConfig { - phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); - phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); - } -+ -+ public int noTickViewDistance; -+ private void viewDistance() { -+ this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 9edbde8299bcd127e1727d34ed441f638e716b2a..17de074111a174f3a39a4477afc3ad62e04a73b5 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -638,7 +638,8 @@ public final class MCUtil { - }); - - worldData.addProperty("name", world.getWorld().getName()); -- worldData.addProperty("view-distance", world.spigotConfig.viewDistance); -+ worldData.addProperty("view-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()); -+ worldData.addProperty("no-view-distance", world.getChunkProvider().playerChunkMap.getRawNoTickViewDistance()); - worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); - worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); - worldData.addProperty("visible-chunk-count", visibleChunks.size()); -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 335666db1854e8aa4b2ba71d5bdc2658305cb70a..2bbdcedf4856080ea9232effdf3bdae9c26c425b 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -269,7 +269,7 @@ public abstract class ChunkMapDistance { - return s; - } - -- protected void a(int i) { -+ protected void setNoTickViewDistance(int i) { // Paper - force abi breakage on usage change - this.g.a(i); - } - -@@ -388,7 +388,7 @@ public abstract class ChunkMapDistance { - - private void a(long i, int j, boolean flag, boolean flag1) { - if (flag != flag1) { -- Ticket ticket = new Ticket<>(TicketType.PLAYER, ChunkMapDistance.b, new ChunkCoordIntPair(i)); -+ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkCoordIntPair(i)); // Paper - no-tick view distance - - if (flag1) { - ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 62ed75ae7ec492d8502776fdf3cf3ee461a38a53..89a66078b722f265abd73579545a1f24df9442aa 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -252,6 +252,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks - -+ boolean needsChunkCenterUpdate; // Paper - no-tick view distance -+ - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); - this.spawnDimension = World.OVERWORLD; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 25484cac9c62e49de39fbbf506fcb3edc4ba6e65..1f6333c2c26ad04e23d2881235ed1dcf707be038 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -82,6 +82,18 @@ public class PlayerChunk { - } - // Paper end - optimise isOutsideOfRange - -+ // Paper start - no-tick view distance -+ public final Chunk getSendingChunk() { -+ // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used -+ // in Chunk's neighbour callback -+ Chunk ret = this.chunkMap.world.getChunkProvider().getChunkAtIfLoadedImmediately(this.location.x, this.location.z); -+ if (ret != null && ret.areNeighboursLoaded(1)) { -+ return ret; -+ } -+ return null; -+ } -+ // Paper end - no-tick view distance -+ - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -@@ -241,7 +253,7 @@ public class PlayerChunk { - } - - public void a(BlockPosition blockposition) { -- Chunk chunk = this.getChunk(); -+ Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { - byte b0 = (byte) SectionPosition.a(blockposition.getY()); -@@ -257,7 +269,7 @@ public class PlayerChunk { - } - - public void a(EnumSkyBlock enumskyblock, int i) { -- Chunk chunk = this.getChunk(); -+ Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { - chunk.setNeedsSaving(true); -@@ -339,9 +351,48 @@ public class PlayerChunk { - } - - private void a(Packet packet, boolean flag) { -- this.players.a(this.location, flag).forEach((entityplayer) -> { -- entityplayer.playerConnection.sendPacket(packet); -- }); -+ // Paper start - per player view distance -+ // there can be potential desync with player's last mapped section and the view distance map, so use the -+ // view distance map here. -+ com.destroystokyo.paper.util.misc.PlayerAreaMap viewDistanceMap = this.chunkMap.playerViewDistanceBroadcastMap; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = viewDistanceMap.getObjectsInRange(this.location); -+ if (players == null) { -+ return; -+ } -+ -+ if (flag) { // flag -> border only -+ Object[] backingSet = players.getBackingSet(); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ -+ int viewDistance = viewDistanceMap.getLastViewDistance(player); -+ long lastPosition = viewDistanceMap.getLastCoordinate(player); -+ -+ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - this.location.x); -+ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - this.location.z); -+ -+ if (Math.max(distX, distZ) == viewDistance) { -+ player.playerConnection.sendPacket(packet); -+ } -+ } -+ } else { -+ Object[] backingSet = players.getBackingSet(); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ player.playerConnection.sendPacket(packet); -+ } -+ } -+ -+ return; -+ // Paper end - per player view distance - } - - public CompletableFuture> a(ChunkStatus chunkstatus, PlayerChunkMap playerchunkmap) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index a6bb8e3b9e73f81bfa92ac13df27e9c44dd9e311..e4b5649fbc8cb9662e818581fe2891641de419b6 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -60,9 +60,11 @@ import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; - import net.minecraft.network.protocol.game.PacketPlayOutMount; - import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; -+import net.minecraft.network.protocol.game.PacketPlayOutViewDistance; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.progress.WorldLoadListener; -+import net.minecraft.server.network.PlayerConnection; - import net.minecraft.util.CSVWriter; - import net.minecraft.util.EntitySlice; - import net.minecraft.util.MathHelper; -@@ -146,7 +148,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private boolean updatingChunksModified; - private final ChunkTaskQueueSorter p; - private final Mailbox> mailboxWorldGen; -- private final Mailbox> mailboxMain; -+ public final Mailbox> mailboxMain; // Paper - private -> public -+ // Paper start -+ final Mailbox> mailboxLight; -+ public void addLightTask(PlayerChunk playerchunk, Runnable run) { -+ this.mailboxLight.a(ChunkTaskQueueSorter.a(playerchunk, run)); -+ } -+ // Paper end - public final WorldLoadListener worldLoadListener; - public final PlayerChunkMap.a chunkDistanceManager; public final ChunkMapDistance getChunkDistanceManager() { return this.chunkDistanceManager; } // Paper - OBFHELPER - private final AtomicInteger u; -@@ -221,6 +229,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick - public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ int noTickViewDistance; -+ public final int getRawNoTickViewDistance() { -+ return this.noTickViewDistance; -+ } -+ public final int getEffectiveNoTickViewDistance() { -+ return this.noTickViewDistance == -1 ? this.getEffectiveViewDistance() : this.noTickViewDistance; -+ } -+ public final int getLoadViewDistance() { -+ return Math.max(this.getEffectiveViewDistance(), this.getEffectiveNoTickViewDistance()); -+ } -+ -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceBroadcastMap; -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap; -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap; -+ // Paper end - no-tick view distance - - void addPlayerToDistanceMaps(EntityPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.locX()); -@@ -237,6 +261,19 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper start - optimise PlayerChunkMap#isOutsideRange - this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ int effectiveTickViewDistance = this.getEffectiveViewDistance(); -+ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); -+ -+ if (!this.cannotLoadChunks(player)) { -+ this.playerViewDistanceTickMap.add(player, chunkX, chunkZ, effectiveTickViewDistance); -+ this.playerViewDistanceNoTickMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) -+ } -+ -+ player.needsChunkCenterUpdate = true; -+ this.playerViewDistanceBroadcastMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured -+ player.needsChunkCenterUpdate = false; -+ // Paper end - no-tick view distance - } - - void removePlayerFromDistanceMaps(EntityPlayer player) { -@@ -249,6 +286,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerMobSpawnMap.remove(player); - this.playerChunkTickRangeMap.remove(player); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ this.playerViewDistanceBroadcastMap.remove(player); -+ this.playerViewDistanceTickMap.remove(player); -+ this.playerViewDistanceNoTickMap.remove(player); -+ // Paper end - no-tick view distance - } - - void updateMaps(EntityPlayer player) { -@@ -266,6 +308,19 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper start - optimise PlayerChunkMap#isOutsideRange - this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ int effectiveTickViewDistance = this.getEffectiveViewDistance(); -+ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); -+ -+ if (!this.cannotLoadChunks(player)) { -+ this.playerViewDistanceTickMap.update(player, chunkX, chunkZ, effectiveTickViewDistance); -+ this.playerViewDistanceNoTickMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) -+ } -+ -+ player.needsChunkCenterUpdate = true; -+ this.playerViewDistanceBroadcastMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured -+ player.needsChunkCenterUpdate = false; -+ // Paper end - no-tick view distance - } - // Paper end - -@@ -373,6 +428,45 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - }); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ this.setNoTickViewDistance(this.world.paperConfig.noTickViewDistance); -+ this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (newState.size() != 1) { -+ return; -+ } -+ Chunk chunk = PlayerChunkMap.this.world.getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(rangeX, rangeZ); -+ if (chunk == null || !chunk.areNeighboursLoaded(2)) { -+ return; -+ } -+ -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ); -+ PlayerChunkMap.this.world.getChunkProvider().addTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (newState != null) { -+ return; -+ } -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ); -+ PlayerChunkMap.this.world.getChunkProvider().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update -+ }); -+ this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); -+ this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (player.needsChunkCenterUpdate) { -+ player.needsChunkCenterUpdate = false; -+ player.playerConnection.sendPacket(new PacketPlayOutViewCentre(currPosX, currPosZ)); -+ } -+ PlayerChunkMap.this.sendChunk(player, new ChunkCoordIntPair(rangeX, rangeZ), new Packet[2], false, true); // unloaded, loaded -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunkMap.this.sendChunk(player, new ChunkCoordIntPair(rangeX, rangeZ), null, true, false); // unloaded, loaded -+ }); -+ // Paper end - no-tick view distance - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -1201,15 +1295,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - completablefuture1.thenAcceptAsync((either) -> { - either.mapLeft((chunk) -> { - this.u.getAndIncrement(); -- Packet[] apacket = new Packet[2]; -- -- this.a(chunkcoordintpair, false).forEach((entityplayer) -> { -- this.a(entityplayer, apacket, chunk); -- }); -+ // Paper - no-tick view distance - moved to Chunk neighbour update - return Either.left(chunk); - }); - }, (runnable) -> { -- this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); -+ this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); // Paper - diff on change, this is the scheduling method copied in Chunk used to schedule chunk broadcasts (on change it needs to be copied again) - }); - return completablefuture1; - } -@@ -1304,32 +1394,38 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - } - -- protected void setViewDistance(int i) { -- int j = MathHelper.clamp(i + 1, 3, 33); -+ public void setViewDistance(int i) { // Paper - public -+ int j = MathHelper.clamp(i + 1, 3, 33); // Paper - diff on change, these make the lower view distance limit 2 and the upper 32 - - if (j != this.viewDistance) { - int k = this.viewDistance; - - this.viewDistance = j; -- this.chunkDistanceManager.a(this.viewDistance); -- ObjectIterator objectiterator = this.updatingChunks.values().iterator(); -+ this.setNoTickViewDistance(this.getRawNoTickViewDistance()); //Paper - no-tick view distance - propagate changes to no-tick, which does the actual chunk loading/sending -+ } - -- while (objectiterator.hasNext()) { -- PlayerChunk playerchunk = (PlayerChunk) objectiterator.next(); -- ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); -- Packet[] apacket = new Packet[2]; -+ } - -- this.a(chunkcoordintpair, false).forEach((entityplayer) -> { -- int l = b(chunkcoordintpair, entityplayer, true); -- boolean flag = l <= k; -- boolean flag1 = l <= this.viewDistance; -+ // Paper start - no-tick view distance -+ public final void setNoTickViewDistance(int viewDistance) { -+ viewDistance = viewDistance == -1 ? -1 : MathHelper.clamp(viewDistance, 2, 32); - -- this.sendChunk(entityplayer, chunkcoordintpair, apacket, flag, flag1); -- }); -+ this.noTickViewDistance = viewDistance; -+ int loadViewDistance = this.getLoadViewDistance(); -+ this.chunkDistanceManager.setNoTickViewDistance(loadViewDistance + 2 + 2); // add 2 to account for the change to 31 -> 33 tickets // see notes in the distance map updating for the other + 2 -+ -+ if (this.world != null && this.world.players != null) { // this can be called from constructor, where these aren't set -+ for (EntityPlayer player : this.world.players) { -+ PlayerConnection connection = player.playerConnection; -+ if (connection != null) { -+ // moved in from PlayerList -+ connection.sendPacket(new PacketPlayOutViewDistance(loadViewDistance)); -+ } -+ this.updateMaps(player); - } - } -- - } -+ // Paper end - no-tick view distance - - protected void sendChunk(EntityPlayer entityplayer, ChunkCoordIntPair chunkcoordintpair, Packet[] apacket, boolean flag, boolean flag1) { - if (entityplayer.world == this.world) { -@@ -1337,7 +1433,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - PlayerChunk playerchunk = this.getVisibleChunk(chunkcoordintpair.pair()); - - if (playerchunk != null) { -- Chunk chunk = playerchunk.getChunk(); -+ Chunk chunk = playerchunk.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { - this.a(entityplayer, apacket, chunk); -@@ -1598,6 +1694,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - // Paper end - optimise isOutsideOfRange - -+ private boolean cannotLoadChunks(EntityPlayer entityplayer) { return this.b(entityplayer); } // Paper - OBFHELPER - private boolean b(EntityPlayer entityplayer) { - return entityplayer.isSpectator() && !this.world.getGameRules().getBoolean(GameRules.SPECTATORS_GENERATE_CHUNKS); - } -@@ -1625,13 +1722,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.removePlayerFromDistanceMaps(entityplayer); // Paper - distance maps - } - -- for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { -- for (int l = j - this.viewDistance; l <= j + this.viewDistance; ++l) { -- ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k, l); -- -- this.sendChunk(entityplayer, chunkcoordintpair, new Packet[2], !flag, flag); -- } -- } -+ // Paper - broadcast view distance map handles this (see remove/add calls above) - - } - -@@ -1639,7 +1730,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - SectionPosition sectionposition = SectionPosition.a((Entity) entityplayer); - - entityplayer.a(sectionposition); -- entityplayer.playerConnection.sendPacket(new PacketPlayOutViewCentre(sectionposition.a(), sectionposition.c())); -+ // Paper - distance map handles this now - return sectionposition; - } - -@@ -1684,6 +1775,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - int k1; - int l1; - -+ /* // Paper start - replaced by distance map - if (Math.abs(i1 - i) <= this.viewDistance * 2 && Math.abs(j1 - j) <= this.viewDistance * 2) { - k1 = Math.min(i, i1) - this.viewDistance; - l1 = Math.min(j, j1) - this.viewDistance; -@@ -1721,7 +1813,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], false, true); - } - } -- } -+ }*/ // Paper end - replaced by distance map - - this.updateMaps(entityplayer); // Paper - distance maps - -@@ -1729,11 +1821,46 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - @Override - public Stream a(ChunkCoordIntPair chunkcoordintpair, boolean flag) { -- return this.playerMap.a(chunkcoordintpair.pair()).filter((entityplayer) -> { -- int i = b(chunkcoordintpair, entityplayer, true); -+ // Paper start - per player view distance -+ // there can be potential desync with player's last mapped section and the view distance map, so use the -+ // view distance map here. -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = this.playerViewDistanceBroadcastMap.getObjectsInRange(chunkcoordintpair); - -- return i > this.viewDistance ? false : !flag || i == this.viewDistance; -- }); -+ if (inRange == null) { -+ return Stream.empty(); -+ } -+ // all current cases are inlined so we wont hit this code, it's just in case plugins or future updates use it -+ List players = new java.util.ArrayList<>(); -+ Object[] backingSet = inRange.getBackingSet(); -+ -+ if (flag) { // flag -> border only -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ int viewDistance = this.playerViewDistanceBroadcastMap.getLastViewDistance(player); -+ long lastPosition = this.playerViewDistanceBroadcastMap.getLastCoordinate(player); -+ -+ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - chunkcoordintpair.x); -+ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - chunkcoordintpair.z); -+ if (Math.max(distX, distZ) == viewDistance) { -+ players.add(player); -+ } -+ } -+ } else { -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ players.add(player); -+ } -+ } -+ return players.stream(); -+ // Paper end - per player view distance - } - - public void addEntity(Entity entity) { // Paper - protected -> public -@@ -1891,7 +2018,48 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -- private final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER -+ // Paper start -+ private static int getLightMask(final Chunk chunk) { -+ final ChunkSection[] chunkSections = chunk.getSections(); -+ int mask = 0; -+ -+ for (int i = 0; i < chunkSections.length; ++i) { -+ /* -+ -+ -+Lightmasks have 18 bits, from the -1 (void) section until the 17th (air) section. -+Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. -+ -+ */ -+ mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; -+ } -+ -+ return mask; -+ } -+ -+ private static int getCeilingLightMask(final Chunk chunk) { -+ int mask = getLightMask(chunk); -+ -+ /* -+ It is similar to get highest bit, it would turn an 001010 into an 001111 so basically the highest bit and all below. -+ We then invert this, so we'd have 110000 and compare that to the "main" chunk. -+ This is because the bug only appears when the current chunks lightmaps are higher than those of the neighbors, thus we can omit sending neighbors which are lower than the current chunks lights. -+ -+ so TLDR is that getCeilingLightMask returns a light mask with all bits set below the highest affected section. We could also count the number of leading zeros and invert them, somehow. -+ @TODO: Implement Leafs suggestion -+ either use Integer#numberOfLeadingZeros or document what this bithack is supposed to be doing then -+ */ -+ mask |= mask >> 1; -+ mask |= mask >> 2; -+ mask |= mask >> 4; -+ mask |= mask >> 8; -+ mask |= mask >> 16; -+ -+ return mask; -+ } -+ // Paper end -+ -+ public final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { - if (apacket[0] == null) { - apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(entityplayer, chunk, 65535)); // Paper - Anti-Xray - Bypass -@@ -2077,7 +2245,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(this.tracker.chunkX, this.tracker.chunkZ); - PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair.pair()); - -- if (playerchunk != null && playerchunk.getChunk() != null) { -+ if (playerchunk != null && playerchunk.getSendingChunk() != null) { // Paper - no-tick view distance - flag1 = PlayerChunkMap.b(chunkcoordintpair, entityplayer, false) <= PlayerChunkMap.this.viewDistance; - } - } -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index c7e78d0626fa0dd18021c1a0827a10c08ab10b4a..66fcd68f0a0a21b113e8741cc42c841f49009118 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -254,7 +254,7 @@ public abstract class PlayerList { - boolean flag1 = gamerules.getBoolean(GameRules.REDUCED_DEBUG_INFO); - - // Spigot - view distance -- playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.spigotConfig.viewDistance, flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); -+ playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.getChunkProvider().playerChunkMap.getLoadViewDistance(), flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); // Paper - no-tick view distance - entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit - playerconnection.sendPacket(new PacketPlayOutCustomPayload(PacketPlayOutCustomPayload.a, (new PacketDataSerializer(Unpooled.buffer())).a(this.getServer().getServerModName()))); - playerconnection.sendPacket(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); -@@ -908,7 +908,7 @@ public abstract class PlayerList { - // CraftBukkit start - WorldData worlddata = worldserver1.getWorldData(); - entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn(worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), BiomeManager.a(worldserver1.getSeed()), entityplayer1.playerInteractManager.getGameMode(), entityplayer1.playerInteractManager.c(), worldserver1.isDebugWorld(), worldserver1.isFlatWorld(), flag)); -- entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver1.spigotConfig.viewDistance)); // Spigot -+ entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver1.getChunkProvider().playerChunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance - entityplayer1.spawnIn(worldserver1); - entityplayer1.dead = false; - entityplayer1.playerConnection.teleport(new Location(worldserver1.getWorld(), entityplayer1.locX(), entityplayer1.locY(), entityplayer1.locZ(), entityplayer1.yaw, entityplayer1.pitch)); -@@ -1376,7 +1376,7 @@ public abstract class PlayerList { - - public void a(int i) { - this.viewDistance = i; -- this.sendAll(new PacketPlayOutViewDistance(i)); -+ //this.sendAll(new PacketPlayOutViewDistance(i)); // Paper - move into setViewDistance - Iterator iterator = this.server.getWorlds().iterator(); - - while (iterator.hasNext()) { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index efcfc8f0f45901d14ac8fdf8ed7b0bd67f8f94da..7ead848342bfbb5b20e95d716805f4b4fd36eb63 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -525,8 +525,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.b(blockposition, iblockdata1, iblockdata2); - } - -- if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getState() != null && chunk.getState().isAtLeast(PlayerChunk.State.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement -+ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getState() != null && chunk.getState().isAtLeast(PlayerChunk.State.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement // Paper - diff on change, see below - this.notify(blockposition, iblockdata1, iblockdata, i); -+ // Paper start - per player view distance - allow block updates for non-ticking chunks in player view distance -+ // if copied from above -+ } else if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || ((WorldServer)this).getChunkProvider().playerChunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.getCoordinateKey(blockposition)) != null)) { -+ ((WorldServer)this).getChunkProvider().flagDirty(blockposition); -+ // Paper end - per player view distance - } - - if ((i & 1) != 0) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index bb2ff043f0d159fa18769c31b08683ee12037c58..90e895e9eac6158a28de4a30589bf7538e5ec9cc 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -28,7 +28,12 @@ import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.level.ChunkTaskQueueSorter; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.EntitySlice; - import net.minecraft.util.MathHelper; -@@ -243,7 +248,51 @@ public class Chunk implements IChunkAccess { - } - - protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { -+ // Paper start - no-tick view distance -+ ChunkProviderServer chunkProviderServer = ((WorldServer)this.world).getChunkProvider(); -+ PlayerChunkMap chunkMap = chunkProviderServer.playerChunkMap; -+ // this code handles the addition of ticking tickets - the distance map handles the removal -+ if (!areNeighboursLoaded(bitsetBefore, 2) && areNeighboursLoaded(bitsetAfter, 2)) { -+ if (chunkMap.playerViewDistanceTickMap.getObjectsInRange(this.coordinateKey) != null) { -+ // now we're ready for entity ticking -+ chunkProviderServer.serverThreadQueue.execute(() -> { -+ // double check that this condition still holds. -+ if (Chunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(Chunk.this.coordinateKey) != null) { -+ chunkProviderServer.addTicketAtLevel(TicketType.PLAYER, Chunk.this.loc, 31, Chunk.this.loc); // 31 -> entity ticking, TODO check on update -+ } -+ }); -+ } -+ } - -+ // this code handles the chunk sending -+ if (!areNeighboursLoaded(bitsetBefore, 1) && areNeighboursLoaded(bitsetAfter, 1)) { -+ if (chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(this.coordinateKey) != null) { -+ // now we're ready to send -+ chunkMap.mailboxMain.a(ChunkTaskQueueSorter.a(chunkMap.getUpdatingChunk(this.coordinateKey), (() -> { // Copied frm PlayerChunkMap -+ // double check that this condition still holds. -+ if (!Chunk.this.areNeighboursLoaded(1)) { -+ return; -+ } -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(Chunk.this.coordinateKey); -+ if (inRange == null) { -+ return; -+ } -+ -+ // broadcast -+ Object[] backingSet = inRange.getBackingSet(); -+ Packet[] chunkPackets = new Packet[2]; -+ for (int index = 0, len = backingSet.length; index < len; ++index) { -+ Object temp = backingSet[index]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ chunkMap.sendChunk(player, chunkPackets, Chunk.this); -+ } -+ }))); -+ } -+ } -+ // Paper end - no-tick view distance - } - - public final boolean isAnyNeighborsLoaded() { -@@ -1132,7 +1181,7 @@ public class Chunk implements IChunkAccess { - IBlockData iblockdata = this.getType(blockposition); - IBlockData iblockdata1 = Block.b(iblockdata, (GeneratorAccess) this.world, blockposition); - -- this.world.setTypeAndData(blockposition, iblockdata1, 20); -+ this.world.setTypeAndData(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here - } - - this.n[i].clear(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index c5a4c8c4c9d90a8a081a593488f86ab487adaecb..2d90ecf04f522a4e16f44c905450a61becaa1ed2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -32,6 +32,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.level.ChunkMapDistance; - import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.Ticket; - import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; -@@ -2550,10 +2551,39 @@ public class CraftWorld implements World { - // Spigot start - @Override - public int getViewDistance() { -- return world.spigotConfig.viewDistance; -+ return getHandle().getChunkProvider().playerChunkMap.getEffectiveViewDistance(); // Paper - no-tick view distance - } - // Spigot end - -+ // Paper start - per player view distance -+ @Override -+ public void setViewDistance(int viewDistance) { -+ if (viewDistance < 2 || viewDistance > 32) { -+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); -+ } -+ PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; -+ if (viewDistance != chunkMap.getEffectiveViewDistance()) { -+ chunkMap.setViewDistance(viewDistance); -+ } -+ } -+ -+ @Override -+ public int getNoTickViewDistance() { -+ return getHandle().getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance(); -+ } -+ -+ @Override -+ public void setNoTickViewDistance(int viewDistance) { -+ if ((viewDistance < 2 || viewDistance > 32) && viewDistance != -1) { -+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); -+ } -+ PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; -+ if (viewDistance != chunkMap.getRawNoTickViewDistance()) { -+ chunkMap.setNoTickViewDistance(viewDistance); -+ } -+ } -+ // Paper end - per player view distance -+ - // Spigot start - private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot() - { -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 663127e6e6ec507959142b18a11a5a4790d4b98b..5c2eaca0bc63c7880ee928aba6a24761737aa649 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -2,6 +2,7 @@ package org.spigotmc; - - import java.util.Collection; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityCreature; -@@ -197,7 +198,7 @@ public class ActivationRange - maxRange = Math.max( maxRange, waterActivationRange ); - maxRange = Math.max( maxRange, villagerActivationRange ); - // Paper end -- maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); -+ maxRange = Math.min( ( ((WorldServer)world).getChunkProvider().playerChunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance - - for ( EntityHuman player : world.getPlayers() ) - { diff --git a/Unmapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch b/Unmapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch deleted file mode 100644 index 6b57ec94ac..0000000000 --- a/Unmapped-Spigot-Server-Patches/0469-Add-villager-reputation-API.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 22 Apr 2020 23:29:20 +0200 -Subject: [PATCH] Add villager reputation API - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0f10c333d88f2e1c56a6c7f22d421084adfd3789 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java -@@ -0,0 +1,9 @@ -+package com.destroystokyo.paper.entity.villager; -+// Must have own package due to package-level constructor. -+ -+public final class ReputationConstructor { -+ // Abuse the package-level constructor. -+ public static Reputation construct(int[] values) { -+ return new Reputation(values); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -index a7f5e4a499c1f6fb1450e536dbf117a8af3b3b84..9cc3a18636a356977577076e96cb7be706c61abf 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -@@ -27,7 +27,7 @@ import net.minecraft.core.MinecraftSerializableUUID; - - public class Reputation { - -- private final Map a = Maps.newHashMap(); -+ private final Map a = Maps.newHashMap(); public Map getReputations() { return this.a; } // Paper - add getter for reputations - - public Reputation() {} - -@@ -142,11 +142,11 @@ public class Reputation { - return k > reputationtype.h ? Math.max(reputationtype.h, i) : k; - } - -- static class a { -+ public static class a { // Paper - make public - - private final Object2IntMap a; - -- private a() { -+ public a() { // Paper - make public - update CraftVillager setReputation on change - this.a = new Object2IntOpenHashMap(); - } - -@@ -200,6 +200,28 @@ public class Reputation { - public void b(ReputationType reputationtype) { - this.a.removeInt(reputationtype); - } -+ -+ // Paper start - Add villager reputation API -+ private static final com.destroystokyo.paper.entity.villager.ReputationType[] REPUTATION_TYPES = com.destroystokyo.paper.entity.villager.ReputationType.values(); -+ public com.destroystokyo.paper.entity.villager.Reputation getPaperReputation() { -+ int[] reputation = new int[REPUTATION_TYPES.length]; -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE.ordinal()] = a.getOrDefault(ReputationType.MAJOR_NEGATIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE.ordinal()] = a.getOrDefault(ReputationType.MAJOR_POSITIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE.ordinal()] = a.getOrDefault(ReputationType.MINOR_NEGATIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE.ordinal()] = a.getOrDefault(ReputationType.MINOR_POSITIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.TRADING.ordinal()] = a.getOrDefault(ReputationType.TRADING, 0); -+ return com.destroystokyo.paper.entity.villager.ReputationConstructor.construct(reputation); -+ } -+ -+ public void assignFromPaperReputation(com.destroystokyo.paper.entity.villager.Reputation rep) { -+ int val; -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE)) != 0) this.a.put(ReputationType.MAJOR_NEGATIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE)) != 0) this.a.put(ReputationType.MAJOR_POSITIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE)) != 0) this.a.put(ReputationType.MINOR_NEGATIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE)) != 0) this.a.put(ReputationType.MINOR_POSITIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.TRADING)) != 0) this.a.put(ReputationType.TRADING, val); -+ } -+ // Paper end - } - - static class b { -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index fb97325e8df33c0edabb81053877ad4a326a3d34..5e84e33ffdda85be96c3d31fbd6a2aa3eab1106a 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -1038,6 +1038,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - this.bD = 0; - } - -+ public Reputation getReputation() { return this.fj(); } // Paper - OBFHELPER - public Reputation fj() { - return this.by; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index 4b2451179cdda918808ea7001f5033c7e5a8b9ac..073c4c518be5a32fccd82e5739ede461214007b2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -@@ -17,6 +17,13 @@ import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; - import org.bukkit.entity.Villager.Type; - -+// Paper start -+import com.destroystokyo.paper.entity.villager.Reputation; -+import com.google.common.collect.Maps; -+import java.util.Map; -+import java.util.UUID; -+// Paper end -+ - public class CraftVillager extends CraftAbstractVillager implements Villager { - - public CraftVillager(CraftServer server, EntityVillager entity) { -@@ -126,4 +133,45 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { - public static VillagerProfession bukkitToNmsProfession(Profession bukkit) { - return IRegistry.VILLAGER_PROFESSION.get(CraftNamespacedKey.toMinecraft(bukkit.getKey())); - } -+ -+ // Paper start - Add villager reputation API -+ @Override -+ public Reputation getReputation(UUID uniqueId) { -+ net.minecraft.world.entity.ai.gossip.Reputation.a rep = getHandle().getReputation().getReputations().get(uniqueId); -+ if (rep == null) { -+ return new Reputation(Maps.newHashMap()); -+ } -+ -+ return rep.getPaperReputation(); -+ } -+ -+ @Override -+ public Map getReputations() { -+ return getHandle().getReputation().getReputations().entrySet() -+ .stream() -+ .collect(java.util.stream.Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getPaperReputation())); -+ } -+ -+ @Override -+ public void setReputation(UUID uniqueId, Reputation reputation) { -+ net.minecraft.world.entity.ai.gossip.Reputation.a nmsReputation = -+ getHandle().getReputation().getReputations().computeIfAbsent( -+ uniqueId, -+ key -> new net.minecraft.world.entity.ai.gossip.Reputation.a() -+ ); -+ nmsReputation.assignFromPaperReputation(reputation); -+ } -+ -+ @Override -+ public void setReputations(Map reputations) { -+ for (Map.Entry entry : reputations.entrySet()) { -+ setReputation(entry.getKey(), entry.getValue()); -+ } -+ } -+ -+ @Override -+ public void clearReputations() { -+ getHandle().getReputation().getReputations().clear(); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch b/Unmapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch deleted file mode 100644 index 6b3d2eed34..0000000000 --- a/Unmapped-Spigot-Server-Patches/0470-Fix-Light-Command.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 7 May 2020 19:17:36 -0400 -Subject: [PATCH] Fix Light Command - -This lets you run /paper fixlight (max 5) to automatically -fix all light data in the chunks. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index eb1e86e8bb0f421e3686ffa02a4015a588107863..d165e8c232c38ba2e2faf93c60c8a127bb74c9b6 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -8,6 +8,8 @@ import com.google.common.collect.ImmutableSet; - import com.google.common.collect.Iterables; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; -+import net.minecraft.core.BlockPosition; -+import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.resources.MinecraftKey; - import com.google.gson.JsonObject; - import com.google.gson.internal.Streams; -@@ -15,12 +17,14 @@ import com.google.gson.stream.JsonWriter; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.LightEngineThreaded; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.level.ChunkCoordIntPair; --import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.chunk.Chunk; - import org.apache.commons.lang3.tuple.MutablePair; - import org.apache.commons.lang3.tuple.Pair; - import org.bukkit.Bukkit; -@@ -31,6 +35,7 @@ import org.bukkit.command.Command; - import org.bukkit.command.CommandSender; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.entity.Player; - - import java.io.File; -@@ -39,10 +44,12 @@ import java.io.PrintStream; - import java.io.StringWriter; - import java.time.LocalDateTime; - import java.time.format.DateTimeFormatter; -+import java.util.ArrayDeque; - import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; - import java.util.Collections; -+import java.util.Deque; - import java.util.Iterator; - import java.util.List; - import java.util.Locale; -@@ -52,7 +59,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); - - public PaperCommand(String name) { - super(name); -@@ -173,6 +180,9 @@ public class PaperCommand extends Command { - case "syncloadinfo": - this.doSyncLoadInfo(sender, args); - break; -+ case "fixlight": -+ this.doFixLight(sender, args); -+ break; - case "ver": - if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) - case "version": -@@ -190,6 +200,77 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doFixLight(CommandSender sender, String[] args) { -+ if (!(sender instanceof Player)) { -+ sender.sendMessage("Only players can use this command"); -+ return; -+ } -+ int radius = 2; -+ if (args.length > 1) { -+ try { -+ radius = Math.min(5, Integer.parseInt(args[1])); -+ } catch (Exception e) { -+ sender.sendMessage("Not a number"); -+ return; -+ } -+ -+ } -+ -+ CraftPlayer player = (CraftPlayer) sender; -+ EntityPlayer handle = player.getHandle(); -+ WorldServer world = (WorldServer) handle.world; -+ LightEngineThreaded lightengine = world.getChunkProvider().getLightEngine(); -+ -+ BlockPosition center = MCUtil.toBlockPosition(player.getLocation()); -+ Deque queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius)); -+ updateLight(sender, world, lightengine, queue); -+ } -+ -+ private void updateLight(CommandSender sender, WorldServer world, LightEngineThreaded lightengine, Deque queue) { -+ ChunkCoordIntPair coord = queue.poll(); -+ if (coord == null) { -+ sender.sendMessage("All Chunks Light updated"); -+ return; -+ } -+ world.getChunkProvider().getChunkAtAsynchronously(coord.x, coord.z, false, false).whenCompleteAsync((either, ex) -> { -+ if (ex != null) { -+ sender.sendMessage("Error loading chunk " + coord); -+ updateLight(sender, world, lightengine, queue); -+ return; -+ } -+ Chunk chunk = (Chunk) either.left().orElse(null); -+ if (chunk == null) { -+ updateLight(sender, world, lightengine, queue); -+ return; -+ } -+ lightengine.a(world.paperConfig.lightQueueSize + 16 * 256); // ensure full chunk can fit into queue -+ sender.sendMessage("Updating Light " + coord); -+ int cx = chunk.getPos().x << 4; -+ int cz = chunk.getPos().z << 4; -+ for (int y = 0; y < world.getHeight(); y++) { -+ for (int x = 0; x < 16; x++) { -+ for (int z = 0; z < 16; z++) { -+ BlockPosition pos = new BlockPosition(cx + x, y, cz + z); -+ lightengine.a(pos); -+ } -+ } -+ } -+ lightengine.queueUpdate(); -+ PlayerChunk visibleChunk = world.getChunkProvider().playerChunkMap.getVisibleChunk(chunk.coordinateKey); -+ if (visibleChunk != null) { -+ world.getChunkProvider().playerChunkMap.addLightTask(visibleChunk, () -> { -+ MinecraftServer.getServer().processQueue.add(() -> { -+ visibleChunk.sendPacketToTrackedPlayers(new PacketPlayOutLightUpdate(chunk.getPos(), lightengine, true), false); -+ updateLight(sender, world, lightengine, queue); -+ }); -+ }); -+ } else { -+ updateLight(sender, world, lightengine, queue); -+ } -+ lightengine.a(world.paperConfig.lightQueueSize); -+ }, MinecraftServer.getServer()); -+ } -+ - private void doSyncLoadInfo(CommandSender sender, String[] args) { - if (!SyncLoadFinder.ENABLED) { - sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 1f6333c2c26ad04e23d2881235ed1dcf707be038..e53054fc46e528f9c713eb4c03add61316e19396 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -350,6 +350,7 @@ public class PlayerChunk { - - } - -+ public void sendPacketToTrackedPlayers(Packet packet, boolean flag) { a(packet, flag); } // Paper - OBFHELPER - private void a(Packet packet, boolean flag) { - // Paper start - per player view distance - // there can be potential desync with player's last mapped section and the view distance map, so use the -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index e4b5649fbc8cb9662e818581fe2891641de419b6..a7e3a979dca4dd7705a8f80366677378f0643f27 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -346,11 +346,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - Mailbox mailbox = Mailbox.a("main", iasynctaskhandler::a); - - this.worldLoadListener = worldloadlistener; -- ThreadedMailbox threadedmailbox1 = ThreadedMailbox.a(executor, "light"); -+ ThreadedMailbox lightthreaded; ThreadedMailbox threadedmailbox1 = lightthreaded = ThreadedMailbox.a(executor, "light"); // Paper - - this.p = new ChunkTaskQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE); - this.mailboxWorldGen = this.p.a(threadedmailbox, false); - this.mailboxMain = this.p.a(mailbox, false); -+ this.mailboxLight = this.p.a(lightthreaded, false);// Paper - this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false)); - this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); this.chunkDistanceManager.chunkMap = this; // Paper - this.l = supplier; diff --git a/Unmapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch b/Unmapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch deleted file mode 100644 index 830778e6bb..0000000000 --- a/Unmapped-Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Fri, 8 May 2020 00:49:18 -0400 -Subject: [PATCH] Fix PotionEffect ignores icon flag - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 468dca6d8c2ec77c3c77c93d04fb9dc329b1befa..fdf4d258dd3e81cf4317ad66334c323be2d88fb2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -420,7 +420,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - - @Override - public boolean addPotionEffect(PotionEffect effect, boolean force) { -- getHandle().addEffect(new MobEffect(MobEffectList.fromId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN); -+ getHandle().addEffect(new MobEffect(MobEffectList.fromId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon - return true; - } - diff --git a/Unmapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch b/Unmapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch deleted file mode 100644 index e32f00ecf8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: virustotalop -Date: Thu, 16 Apr 2020 20:51:32 -0700 -Subject: [PATCH] Optimize brigadier child sorting performance - - -diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -index f0f25fa40d4a0aa0e299ad11847b6a5f9102c214..7ef6c99d2235eed38197aa76bc9553d7efbe52a4 100644 ---- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java -+++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -@@ -27,7 +27,7 @@ import java.util.stream.Collectors; - import net.minecraft.commands.CommandListenerWrapper; // CraftBukkit - - public abstract class CommandNode implements Comparable> { -- private Map> children = Maps.newLinkedHashMap(); -+ private Map> children = Maps.newTreeMap(); //Paper - Switch to tree map for automatic sorting - private Map> literals = Maps.newLinkedHashMap(); - private Map> arguments = Maps.newLinkedHashMap(); - private final Predicate requirement; -@@ -107,8 +107,7 @@ public abstract class CommandNode implements Comparable> { - arguments.put(node.getName(), (ArgumentCommandNode) node); - } - } -- -- children = children.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); -+ //Paper - Remove manual sorting, it is no longer needed - } - - public void findAmbiguities(final AmbiguityConsumer consumer) { diff --git a/Unmapped-Spigot-Server-Patches/0473-Potential-bed-API.patch b/Unmapped-Spigot-Server-Patches/0473-Potential-bed-API.patch deleted file mode 100644 index dda9b9bbad..0000000000 --- a/Unmapped-Spigot-Server-Patches/0473-Potential-bed-API.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Sun, 10 May 2020 23:06:30 -0400 -Subject: [PATCH] Potential bed API - -Adds a new method to fetch the location of a player's bed without generating any sync loads. - -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/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 3bfb93890259210afd2f5e226cef100d26a11628..4028f4bd87a183a808f4c9a19d51ee1c9b9e30f7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -13,6 +13,7 @@ import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.game.PacketPlayInCloseWindow; - import net.minecraft.network.protocol.game.PacketPlayOutOpenWindow; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.ITileInventory; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -@@ -127,6 +128,22 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - return getHandle().sleepTicks; - } - -+ // Paper start - Potential bed api -+ @Override -+ public Location getPotentialBedLocation() { -+ EntityPlayer handle = (EntityPlayer) getHandle(); -+ BlockPosition bed = handle.getSpawn(); -+ if (bed == null) { -+ return null; -+ } -+ -+ WorldServer worldServer = handle.server.getWorldServer(handle.getSpawnDimension()); -+ if (worldServer == null) { -+ return null; -+ } -+ return new Location(worldServer.getWorld(), bed.getX(), bed.getY(), bed.getZ()); -+ } -+ // Paper end - @Override - public boolean sleep(Location location, boolean force) { - Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/Unmapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch b/Unmapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch deleted file mode 100644 index f826db1c4f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 May 2020 22:16:17 -0400 -Subject: [PATCH] Wait for Async Tasks during shutdown - -Server.reload() had this logic to give time for tasks to shutdown, -however shutdown did not... - -Adds a 5 second grace period for any async tasks to finish and warns -if any are still running after that delay just as reload does. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 1eb1da61ee2aa2cc5d28a46fd364a182cd16983b..69476bb6bca963c5ea88a7cc66622ae599595e62 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -894,6 +894,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0) { -+ try { -+ Thread.sleep(100); -+ } catch (InterruptedException e) {} -+ pollCount++; -+ } -+ -+ List overdueWorkers = getScheduler().getActiveWorkers(); -+ for (BukkitWorker worker : overdueWorkers) { -+ Plugin plugin = worker.getOwner(); -+ String author = ""; -+ if (plugin.getDescription().getAuthors().size() > 0) { -+ author = plugin.getDescription().getAuthors().get(0); -+ } -+ getLogger().log(Level.SEVERE, String.format( -+ "Nag author: '%s' of '%s' about the following: %s", -+ author, -+ plugin.getDescription().getName(), -+ "This plugin is not properly shutting down its async tasks when it is being shut down. This task may throw errors during the final shutdown logs and might not complete before process dies." -+ )); -+ } -+ } -+ // Paper end -+ - @Override - public void reloadData() { - CommandReload.reload(console); diff --git a/Unmapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/Unmapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch deleted file mode 100644 index a5eab26a70..0000000000 --- a/Unmapped-Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Sat, 9 May 2020 02:01:48 -0400 -Subject: [PATCH] Ensure EntityRaider respects game and entity rules for - picking up items - - -diff --git a/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java b/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java -index b9f5ed4e9348648a248dcd23eb100ceac49f26df..ff41ee884e3e46af1b1e9fb550f0abc6998fd031 100644 ---- a/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java -+++ b/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java -@@ -523,7 +523,7 @@ public abstract class EntityRaider extends EntityMonsterPatrolling { - - public class b extends PathfinderGoal { - -- private final T b; -+ private final T b; private T getRaider() { return b; } // Paper - obfhelper - - public b(T entityraider) { // CraftBukkit - decompile error - this.b = entityraider; -@@ -532,6 +532,7 @@ public abstract class EntityRaider extends EntityMonsterPatrolling { - - @Override - public boolean a() { -+ if (!getRaider().world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) || !getRaider().canPickupLoot()) return false; // Paper - respect game and entity rules for picking up items - Raid raid = this.b.fa(); - - if (this.b.fb() && !this.b.fa().a() && this.b.eN() && !ItemStack.matches(this.b.getEquipment(EnumItemSlot.HEAD), Raid.s())) { diff --git a/Unmapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/Unmapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch deleted file mode 100644 index c5742080fb..0000000000 --- a/Unmapped-Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 May 2020 23:01:26 -0400 -Subject: [PATCH] Protect Bedrock and End Portal/Frames from being destroyed - -This fixes exploits that let players destroy bedrock by Pistons, explosions -and Mushrooom/Tree generation. - -These blocks are designed to not be broken except by creative players/commands. -So protect them from a multitude of methods of destroying them. - -A config is provided if you rather let players use these exploits, and let -them destroy the worlds End Portals and get on top of the nether easy. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 78271b400c79578d043b20a5389a37b1bef9a70d..5f3b0d95cc7e6a0434d78ea7305a70689c41c71c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -416,4 +416,17 @@ public class PaperConfig { - private static void midTickChunkTasks() { - midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); - } -+ -+ public static boolean allowBlockPermanentBreakingExploits = false; -+ private static void allowBlockPermanentBreakingExploits() { -+ if (config.contains("allow-perm-block-break-exploits")) { -+ allowBlockPermanentBreakingExploits = config.getBoolean("allow-perm-block-break-exploits", false); -+ config.set("allow-perm-block-break-exploits", null); -+ } -+ -+ config.set("settings.unsupported-settings.allow-permanent-block-break-exploits-readme", "This setting controls if players should be able to break bedrock, end portals and other intended to be permanent blocks."); -+ allowBlockPermanentBreakingExploits = getBoolean("settings.unsupported-settings.allow-permanent-block-break-exploits", allowBlockPermanentBreakingExploits); -+ -+ } -+ - } -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index a9ecc2b4da587ca3d3c99f8c8af38092a02fb572..0b3479aae8f7cad7bd0b8b64aa2dead43baf4c56 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -153,6 +153,7 @@ public class Explosion { - for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { - BlockPosition blockposition = new BlockPosition(d4, d5, d6); - IBlockData iblockdata = this.world.getType(blockposition); -+ if (!iblockdata.isDestroyable()) continue; // Paper - Fluid fluid = iblockdata.getFluid(); // Paper - Optional optional = this.l.a(this, this.world, blockposition, iblockdata, fluid); - -@@ -306,7 +307,7 @@ public class Explosion { - IBlockData iblockdata = this.world.getType(blockposition); - Block block = iblockdata.getBlock(); - -- if (!iblockdata.isAir()) { -+ if (!iblockdata.isAir() && iblockdata.isDestroyable()) { // Paper - BlockPosition blockposition1 = blockposition.immutableCopy(); - - this.world.getMethodProfiler().enter("explosion_blocks"); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 7ead848342bfbb5b20e95d716805f4b4fd36eb63..9369a0c6c0ae2d8518ebfb17f2c93ead2647ab8d 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -422,6 +422,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) { - // CraftBukkit start - tree generation - if (this.captureTreeGeneration) { -+ // Paper start -+ IBlockData type = getType(blockposition); -+ if (!type.isDestroyable()) return false; -+ // Paper end - CraftBlockState blockstate = capturedBlockStates.get(blockposition); - if (blockstate == null) { - blockstate = CapturedBlockState.getTreeBlockState(this, blockposition, i); -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index e5c43b383a93fac76333a67b41535ab009d1dcf3..cc512bd2e89382e7fdbc59b41640e95ccafbbfe9 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -62,6 +62,19 @@ public class Block extends BlockBase implements IMaterial { - protected final BlockStateList blockStateList; - private IBlockData blockData; - // Paper start -+ public final boolean isDestroyable() { -+ return com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || -+ this != Blocks.BEDROCK && -+ this != Blocks.END_PORTAL_FRAME && -+ this != Blocks.END_PORTAL && -+ this != Blocks.END_GATEWAY && -+ this != Blocks.COMMAND_BLOCK && -+ this != Blocks.REPEATING_COMMAND_BLOCK && -+ this != Blocks.CHAIN_COMMAND_BLOCK && -+ this != Blocks.BARRIER && -+ this != Blocks.STRUCTURE_BLOCK && -+ this != Blocks.JIGSAW; -+ } - public co.aikar.timings.Timing timing; - public co.aikar.timings.Timing getTiming() { - if (timing == null) { -diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -index 7de86d6232eb84642fb6423a1b0a9f30d9df9f2b..e062fd288098127fae22a55562e0207ceaf50163 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -@@ -194,6 +194,12 @@ public class BlockPiston extends BlockDirectional { - @Override - public boolean a(IBlockData iblockdata, World world, BlockPosition blockposition, int i, int j) { - EnumDirection enumdirection = (EnumDirection) iblockdata.get(BlockPiston.FACING); -+ // Paper start - prevent retracting when we're facing the wrong way (we were replaced before retraction could occur) -+ EnumDirection directionQueuedAs = EnumDirection.fromType1(j & 7); // Paper - copied from below -+ if (!com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits && enumdirection != directionQueuedAs) { -+ return false; -+ } -+ // Paper end - prevent retracting when we're facing the wrong way - - if (!world.isClientSide) { - boolean flag = this.a(world, blockposition, enumdirection); -@@ -225,7 +231,7 @@ public class BlockPiston extends BlockDirectional { - IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.MOVING_PISTON.getBlockData().set(BlockPistonMoving.a, enumdirection)).set(BlockPistonMoving.b, this.sticky ? BlockPropertyPistonType.STICKY : BlockPropertyPistonType.DEFAULT); - - world.setTypeAndData(blockposition, iblockdata1, 20); -- world.setTileEntity(blockposition, BlockPistonMoving.a((IBlockData) this.getBlockData().set(BlockPiston.FACING, EnumDirection.fromType1(j & 7)), enumdirection, false, true)); -+ world.setTileEntity(blockposition, BlockPistonMoving.a((IBlockData) this.getBlockData().set(BlockPiston.FACING, EnumDirection.fromType1(j & 7)), enumdirection, false, true)); // Paper - diff on change, j is facing direction - copy this above - world.update(blockposition, iblockdata1.getBlock()); - iblockdata1.a(world, blockposition, 2); - if (this.sticky) { -@@ -254,7 +260,14 @@ public class BlockPiston extends BlockDirectional { - } - } - } else { -- world.a(blockposition.shift(enumdirection), false); -+ // Paper start - fix headless pistons breaking blocks -+ BlockPosition headPos = blockposition.shift(enumdirection); -+ if (com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || world.getType(headPos) == Blocks.PISTON_HEAD.getBlockData().set(FACING, enumdirection)) { // double check to make sure we're not a headless piston. -+ world.setAir(headPos, false); -+ } else { -+ ((WorldServer)world).getChunkProvider().flagDirty(headPos); // ... fix client desync -+ } -+ // Paper end - fix headless pistons breaking blocks - } - - world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_PISTON_CONTRACT, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F); -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 57857cc33603cf278de424b540a3d4a5943584c9..2a785ea58a7bdc80c703a60bc6ed602dc8040aa0 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -190,7 +190,7 @@ public abstract class BlockBase { - - @Deprecated - public boolean a(IBlockData iblockdata, BlockActionContext blockactioncontext) { -- return this.material.isReplaceable() && (blockactioncontext.getItemStack().isEmpty() || blockactioncontext.getItemStack().getItem() != this.getItem()); -+ return this.material.isReplaceable() && (blockactioncontext.getItemStack().isEmpty() || blockactioncontext.getItemStack().getItem() != this.getItem()) && (iblockdata.isDestroyable() || (blockactioncontext.getEntity() != null && blockactioncontext.getEntity().abilities.canInstantlyBuild)); // Paper - } - - @Deprecated -@@ -394,7 +394,11 @@ public abstract class BlockBase { - public Block getBlock() { - return (Block) this.c; - } -- -+ // Paper start -+ public final boolean isDestroyable() { -+ return getBlock().isDestroyable(); -+ } -+ // Paper end - public Material getMaterial() { - return this.g; - } -@@ -484,7 +488,7 @@ public abstract class BlockBase { - } - - public EnumPistonReaction getPushReaction() { -- return this.getBlock().getPushReaction(this.p()); -+ return !isDestroyable() ? EnumPistonReaction.BLOCK : this.getBlock().getPushReaction(this.p()); // Paper - } - - public boolean i(IBlockAccess iblockaccess, BlockPosition blockposition) { diff --git a/Unmapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch b/Unmapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch deleted file mode 100644 index 0b519eafdf..0000000000 --- a/Unmapped-Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch +++ /dev/null @@ -1,394 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 23:30:30 -0400 -Subject: [PATCH] Optimize NibbleArray to use pooled buffers - -Massively reduces memory allocation of 2048 byte buffers by using -an object pool for these. - -Uses lots of advanced new capabilities of the Paper codebase :) - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java -index 247d969e7d1aa59d9650fce1032aaa09db3903e5..9050ff7180f63c1f5756570446c4d0a8cc767779 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java -@@ -1,12 +1,16 @@ - package net.minecraft.network.protocol.game; - - import com.google.common.collect.Lists; -+import io.netty.channel.ChannelFuture; // Paper -+ - import java.io.IOException; - import java.util.Iterator; - import java.util.List; - import net.minecraft.core.SectionPosition; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumSkyBlock; - import net.minecraft.world.level.chunk.NibbleArray; -@@ -24,14 +28,43 @@ public class PacketPlayOutLightUpdate implements Packet { - private List h; - private boolean i; - -+ // Paper start -+ java.lang.Runnable cleaner1; -+ java.lang.Runnable cleaner2; -+ java.util.concurrent.atomic.AtomicInteger remainingSends = new java.util.concurrent.atomic.AtomicInteger(0); -+ -+ @Override -+ public void onPacketDispatch(EntityPlayer player) { -+ remainingSends.incrementAndGet(); -+ } -+ -+ @Override -+ public void onPacketDispatchFinish(EntityPlayer player, ChannelFuture future) { -+ if (remainingSends.decrementAndGet() <= 0) { -+ // incase of any race conditions, schedule this delayed -+ MCUtil.scheduleTask(5, () -> { -+ if (remainingSends.get() == 0) { -+ cleaner1.run(); -+ cleaner2.run(); -+ } -+ }, "Light Packet Release"); -+ } -+ } -+ -+ @Override -+ public boolean hasFinishListener() { -+ return true; -+ } -+ -+ // Paper end - public PacketPlayOutLightUpdate() {} - - public PacketPlayOutLightUpdate(ChunkCoordIntPair chunkcoordintpair, LightEngine lightengine, boolean flag) { - this.a = chunkcoordintpair.x; - this.b = chunkcoordintpair.z; - this.i = flag; -- this.g = Lists.newArrayList(); -- this.h = Lists.newArrayList(); -+ this.g = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper -+ this.h = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper - - for (int i = 0; i < 18; ++i) { - NibbleArray nibblearray = lightengine.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, -1 + i)); -@@ -42,7 +75,7 @@ public class PacketPlayOutLightUpdate implements Packet { - this.e |= 1 << i; - } else { - this.c |= 1 << i; -- this.g.add(nibblearray.asBytes().clone()); -+ this.g.add(nibblearray.getCloneIfSet()); // Paper - } - } - -@@ -51,7 +84,7 @@ public class PacketPlayOutLightUpdate implements Packet { - this.f |= 1 << i; - } else { - this.d |= 1 << i; -- this.h.add(nibblearray1.asBytes().clone()); -+ this.h.add(nibblearray1.getCloneIfSet()); // Paper - } - } - } -@@ -64,8 +97,8 @@ public class PacketPlayOutLightUpdate implements Packet { - this.i = flag; - this.c = i; - this.d = j; -- this.g = Lists.newArrayList(); -- this.h = Lists.newArrayList(); -+ this.g = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper -+ this.h = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper - - for (int k = 0; k < 18; ++k) { - NibbleArray nibblearray; -@@ -73,7 +106,7 @@ public class PacketPlayOutLightUpdate implements Packet { - if ((this.c & 1 << k) != 0) { - nibblearray = lightengine.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, -1 + k)); - if (nibblearray != null && !nibblearray.c()) { -- this.g.add(nibblearray.asBytes().clone()); -+ this.g.add(nibblearray.getCloneIfSet()); // Paper - } else { - this.c &= ~(1 << k); - if (nibblearray != null) { -@@ -85,7 +118,7 @@ public class PacketPlayOutLightUpdate implements Packet { - if ((this.d & 1 << k) != 0) { - nibblearray = lightengine.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, -1 + k)); - if (nibblearray != null && !nibblearray.c()) { -- this.h.add(nibblearray.asBytes().clone()); -+ this.h.add(nibblearray.getCloneIfSet()); // Paper - } else { - this.d &= ~(1 << k); - if (nibblearray != null) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -index 86b4db483787c5fd10461f7d7e90a772ee049599..b82420e9a5d42a4383d24921614fe613c640edb9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -+++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -@@ -1,18 +1,78 @@ - // mc-dev import - package net.minecraft.world.level.chunk; - -+import com.destroystokyo.paper.util.pooled.PooledObjects; // Paper -+ -+import javax.annotation.Nonnull; - import javax.annotation.Nullable; - import net.minecraft.SystemUtils; -+import net.minecraft.server.MCUtil; - - public class NibbleArray { - -- @Nullable -- protected byte[] a; -+ // Paper start -+ public static byte[] EMPTY_NIBBLE = new byte[2048]; -+ private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072); -+ private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8)); -+ public static final PooledObjects BYTE_2048 = new PooledObjects<>(() -> new byte[2048], maxPoolSize); -+ public static void releaseBytes(byte[] bytes) { -+ if (bytes != null && bytes != EMPTY_NIBBLE && bytes.length == 2048) { -+ System.arraycopy(EMPTY_NIBBLE, 0, bytes, 0, 2048); -+ BYTE_2048.release(bytes); -+ } -+ } -+ -+ public NibbleArray markPoolSafe(byte[] bytes) { -+ if (bytes != EMPTY_NIBBLE) this.a = bytes; -+ return markPoolSafe(); -+ } -+ public NibbleArray markPoolSafe() { -+ poolSafe = true; -+ return this; -+ } -+ public byte[] getIfSet() { -+ return this.a != null ? this.a : EMPTY_NIBBLE; -+ } -+ public byte[] getCloneIfSet() { -+ if (a == null) { -+ return EMPTY_NIBBLE; -+ } -+ byte[] ret = BYTE_2048.acquire(); -+ System.arraycopy(getIfSet(), 0, ret, 0, 2048); -+ return ret; -+ } -+ -+ public NibbleArray cloneAndSet(byte[] bytes) { -+ if (bytes != null && bytes != EMPTY_NIBBLE) { -+ this.a = BYTE_2048.acquire(); -+ System.arraycopy(bytes, 0, this.a, 0, 2048); -+ } -+ return this; -+ } -+ boolean poolSafe = false; -+ public java.lang.Runnable cleaner; -+ private void registerCleaner() { -+ if (!poolSafe) { -+ cleaner = MCUtil.registerCleaner(this, this.a, NibbleArray::releaseBytes); -+ } else { -+ cleaner = MCUtil.once(() -> NibbleArray.releaseBytes(this.a)); -+ } -+ } -+ // Paper end -+ @Nullable protected byte[] a; -+ - - public NibbleArray() {} - - public NibbleArray(byte[] abyte) { -+ // Paper start -+ this(abyte, false); -+ } -+ public NibbleArray(byte[] abyte, boolean isSafe) { - this.a = abyte; -+ if (!isSafe) this.a = getCloneIfSet(); // Paper - clone for safety -+ registerCleaner(); -+ // Paper end - if (abyte.length != 2048) { - throw (IllegalArgumentException) SystemUtils.c((Throwable) (new IllegalArgumentException("ChunkNibbleArrays should be 2048 bytes not: " + abyte.length))); - } -@@ -46,7 +106,8 @@ public class NibbleArray { - - public void a(int i, int j) { // PAIL: private -> public - if (this.a == null) { -- this.a = new byte[2048]; -+ this.a = BYTE_2048.acquire(); // Paper -+ registerCleaner();// Paper - } - - int k = this.d(i); -@@ -68,14 +129,36 @@ public class NibbleArray { - public byte[] asBytes() { - if (this.a == null) { - this.a = new byte[2048]; -+ } else { // Paper start -+ // Accessor may need this object past garbage collection so need to clone it and return pooled value -+ // If we know its safe for pre GC access, use asBytesPoolSafe(). If you just need read, use getIfSet() -+ Runnable cleaner = this.cleaner; -+ if (cleaner != null) { -+ this.a = this.a.clone(); -+ cleaner.run(); // release the previously pooled value -+ this.cleaner = null; -+ } -+ } -+ // Paper end -+ -+ return this.a; -+ } -+ -+ @Nonnull -+ public byte[] asBytesPoolSafe() { -+ if (this.a == null) { -+ this.a = BYTE_2048.acquire(); // Paper -+ registerCleaner(); // Paper - } - -+ //noinspection ConstantConditions - return this.a; - } -+ // Paper end - - public NibbleArray copy() { return this.b(); } // Paper - OBFHELPER - public NibbleArray b() { -- return this.a == null ? new NibbleArray() : new NibbleArray((byte[]) this.a.clone()); -+ return this.a == null ? new NibbleArray() : new NibbleArray(this.a); // Paper - clone in ctor - } - - public String toString() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index e16e046d165330326ed220c9c440a637007f3137..91bcbf7156dd90b00e2d53bb6bff4abc44ecb721 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -435,11 +435,11 @@ public class ChunkRegionLoader { - } - - if (nibblearray != null && !nibblearray.c()) { -- nbttagcompound2.setByteArray("BlockLight", nibblearray.asBytes()); -+ nbttagcompound2.setByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper - } - - if (nibblearray1 != null && !nibblearray1.c()) { -- nbttagcompound2.setByteArray("SkyLight", nibblearray1.asBytes()); -+ nbttagcompound2.setByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper - } - - nbttaglist.add(nbttagcompound2); -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -index 5b1ff4ff87591dd4ff0b79e4ac6ff0494fc3d0f8..9ba9efb181b9607f25b7c921e69e4c59b182d429 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -@@ -156,7 +156,7 @@ public abstract class LightEngineStorage> e - protected NibbleArray j(long i) { - NibbleArray nibblearray = (NibbleArray) this.i.get(i); - -- return nibblearray != null ? nibblearray : new NibbleArray(); -+ return nibblearray != null ? nibblearray : new NibbleArray().markPoolSafe(); // Paper - } - - protected void a(LightEngineLayer lightenginelayer, long i) { -@@ -338,12 +338,12 @@ public abstract class LightEngineStorage> e - - protected void a(long i, @Nullable NibbleArray nibblearray, boolean flag) { - if (nibblearray != null) { -- this.i.put(i, nibblearray); -+ NibbleArray remove = this.i.put(i, nibblearray); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed - if (!flag) { - this.n.add(i); - } - } else { -- this.i.remove(i); -+ NibbleArray remove = this.i.remove(i); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed - } - - } -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -index ed7864c552054fc47c6010a094230ce4aebf1c54..da78d4c4b5f8af4648ac82d63c21f6a2a5b73ecb 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.lighting; - - import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; - import javax.annotation.Nullable; -+import net.minecraft.server.MCUtil; - import net.minecraft.world.level.chunk.NibbleArray; - - public abstract class LightEngineStorageArray> { -@@ -34,7 +35,9 @@ public abstract class LightEngineStorageArray -Date: Mon, 27 Apr 2020 02:48:06 -0700 -Subject: [PATCH] Reduce MutableInt allocations from light engine - -We can abuse the fact light is single threaded and share an instance -per light engine instance - -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -index 2a0a5a70c795ba33780c8db774eaf9769a85daa7..f6198069e3ca421b4f551939263c7cf8bd5b754e 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -@@ -16,6 +16,7 @@ public final class LightEngineBlock extends LightEngineLayer= 15) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -index 113c575a16121aa1146f21a6f41ebd9d12a0c924..37fa5faea6e2972e3eb8a3cbd1913ef38dc9456f 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -@@ -15,6 +15,7 @@ public final class LightEngineSky extends LightEngineLayer= 15) { - return k; - } else { -- MutableInt mutableint = new MutableInt(); -+ //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded - IBlockData iblockdata = this.a(j, mutableint); - - if (mutableint.getValue() >= 15) { diff --git a/Unmapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/Unmapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch deleted file mode 100644 index 40cf990128..0000000000 --- a/Unmapped-Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Apr 2020 00:04:16 -0700 -Subject: [PATCH] Reduce allocation of Vec3D by entity tracker - - -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index b64aa6c9ce906b08e43891f8c465fa4e8b2a8906..58dd349adf2bc9bac6569464ef7a7aec81729e79 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -155,8 +155,12 @@ public class EntityTrackerEntry { - ++this.o; - i = MathHelper.d(this.tracker.yaw * 256.0F / 360.0F); - j = MathHelper.d(this.tracker.pitch * 256.0F / 360.0F); -- Vec3D vec3d = this.tracker.getPositionVector().d(PacketPlayOutEntity.a(this.xLoc, this.yLoc, this.zLoc)); -- boolean flag1 = vec3d.g() >= 7.62939453125E-6D; -+ // Paper start - reduce allocation of Vec3D here -+ double vec3d_dx = this.tracker.locX() - 2.44140625E-4D*(this.xLoc); -+ double vec3d_dy = this.tracker.locY() - 2.44140625E-4D*(this.yLoc); -+ double vec3d_dz = this.tracker.locZ() - 2.44140625E-4D*(this.zLoc); -+ boolean flag1 = (vec3d_dx * vec3d_dx + vec3d_dy * vec3d_dy + vec3d_dz * vec3d_dz) >= 7.62939453125E-6D; -+ // Paper end - reduce allocation of Vec3D here - Packet packet1 = null; - boolean flag2 = flag1 || this.tickCounter % 60 == 0; - boolean flag3 = Math.abs(i - this.yRot) >= 1 || Math.abs(j - this.xRot) >= 1; -@@ -173,9 +177,11 @@ public class EntityTrackerEntry { - // CraftBukkit end - - if (this.tickCounter > 0 || this.tracker instanceof EntityArrow) { -- long k = PacketPlayOutEntity.a(vec3d.x); -- long l = PacketPlayOutEntity.a(vec3d.y); -- long i1 = PacketPlayOutEntity.a(vec3d.z); -+ // Paper start - remove allocation of Vec3D here -+ long k = PacketPlayOutEntity.a(vec3d_dx); -+ long l = PacketPlayOutEntity.a(vec3d_dy); -+ long i1 = PacketPlayOutEntity.a(vec3d_dz); -+ // Paper end - remove allocation of Vec3D here - boolean flag4 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L; - - if (!flag4 && this.o <= 400 && !this.q && this.r == this.tracker.isOnGround()) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index a7e3a979dca4dd7705a8f80366677378f0643f27..c3394b22d1a22fd83ff43473da34704ad547836f 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -2235,9 +2235,14 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - public void updatePlayer(EntityPlayer entityplayer) { - org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot - if (entityplayer != this.tracker) { -- Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 -+ // Paper start - remove allocation of Vec3D here -+ //Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 -+ double vec3d_dx = entityplayer.locX() - this.tracker.locX(); -+ double vec3d_dy = entityplayer.locY() - this.tracker.locY(); -+ double vec3d_dz = entityplayer.locZ() - this.tracker.locZ(); -+ // Paper end - remove allocation of Vec3D here - int i = Math.min(this.b(), (PlayerChunkMap.this.viewDistance - 1) * 16); -- boolean flag = vec3d.x >= (double) (-i) && vec3d.x <= (double) i && vec3d.z >= (double) (-i) && vec3d.z <= (double) i && this.tracker.a(entityplayer); -+ boolean flag = vec3d_dx >= (double) (-i) && vec3d_dx <= (double) i && vec3d_dz >= (double) (-i) && vec3d_dz <= (double) i && this.tracker.a(entityplayer); // Paper - remove allocation of Vec3D here - - if (flag) { - boolean flag1 = this.tracker.attachedToPlayer; diff --git a/Unmapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch b/Unmapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch deleted file mode 100644 index cf98a288ea..0000000000 --- a/Unmapped-Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Fri, 15 May 2020 01:10:03 -0400 -Subject: [PATCH] Ensure safe gateway teleport - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -index b7548d0b3938d95328fc86db4000190532eaa8f5..855c49164277ca96ca08fb204d851a5ad6789990 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -@@ -89,9 +89,14 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick - } else if (!this.world.isClientSide) { - List list = this.world.a(Entity.class, new AxisAlignedBB(this.getPosition()), TileEntityEndGateway::a); - -- if (!list.isEmpty()) { -- this.b((Entity) list.get(this.world.random.nextInt(list.size()))); -+ // Paper start -+ for (Entity entity : list) { -+ if (entity.canPortal()) { -+ this.b(entity); -+ break; -+ } - } -+ // Paper end - - if (this.age % 2400L == 0L) { - this.h(); diff --git a/Unmapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch b/Unmapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch deleted file mode 100644 index 908755e004..0000000000 --- a/Unmapped-Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 16 May 2020 10:12:15 +0200 -Subject: [PATCH] Add option for console having all permissions - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 5f3b0d95cc7e6a0434d78ea7305a70689c41c71c..7f140333c2e62012fa572c1a061d84432426997f 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -429,4 +429,9 @@ public class PaperConfig { - - } - -+ public static boolean consoleHasAllPermissions = false; -+ private static void consoleHasAllPermissions() { -+ consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); -+ } -+ - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 202fa94d5dc55b549475ae0309bbcfca8f1b2c96..ec0956a98c133bcd3d4f92f696c667eab6ff98f1 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1889,7 +1889,7 @@ public abstract class EntityHuman extends EntityLiving { - } - } - -- protected void releaseShoulderEntities() { -+ public void releaseShoulderEntities() { // Paper - protected -> public - if (this.e + 20L < this.world.getTime()) { - // CraftBukkit start - if (this.spawnEntityFromShoulder(this.getShoulderEntityLeft())) { -diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -index af986adfdb547cb61fbd52f0f89858f1a9e52cc3..80a67deaeaae3b3f0ceb9a298de5bb38b8ee707b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -@@ -86,5 +86,15 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co - public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { - this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); - } -+ -+ @Override -+ public boolean hasPermission(String name) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); -+ } -+ -+ @Override -+ public boolean hasPermission(org.bukkit.permissions.Permission perm) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -index 24662d58cb4a9bf2f3b252858b504165d91d4419..a6f3594def0abe076ff44fcfa61dd05bee729387 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -@@ -39,4 +39,16 @@ public class CraftRemoteConsoleCommandSender extends ServerCommandSender impleme - public void setOp(boolean value) { - throw new UnsupportedOperationException("Cannot change operator status of remote controller."); - } -+ -+ // Paper start -+ @Override -+ public boolean hasPermission(String name) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); -+ } -+ -+ @Override -+ public boolean hasPermission(org.bukkit.permissions.Permission perm) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/Unmapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch deleted file mode 100644 index 5f3ad1df79..0000000000 --- a/Unmapped-Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 23 May 2020 01:31:06 -0400 -Subject: [PATCH] Fix Non Full Status Chunk NBT Memory Leak - -Any full status chunk that was requested for any status less than full -would hold onto their entire nbt tree and every variable in that function. - -This was due to use of a lambda that persists on the Chunk object -until that chunk reaches FULL status. - -With introduction of no tick, we greatly increased the number of non -full chunks so this was really starting to hurt. - -We further improve it by making a copy of the nbt tag with only the memory -it needs, so that we dont have to hold a copy to the entire compound. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 91bcbf7156dd90b00e2d53bb6bff4abc44ecb721..8e4924cd649c350520cba54a0e1497d5acf089ff 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -22,6 +22,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.core.RegistryBlocks; - import net.minecraft.core.SectionPosition; -+import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.nbt.NBTTagLongArray; -@@ -199,15 +200,9 @@ public class ChunkRegionLoader { - object2 = protochunkticklist1; - } - -- object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { -- loadEntities(nbttagcompound1, chunk); -- // CraftBukkit start - load chunk persistent data from nbt -- net.minecraft.nbt.NBTBase persistentBase = nbttagcompound1.get("ChunkBukkitValues"); -- if (persistentBase instanceof NBTTagCompound) { -- chunk.persistentDataContainer.putAll((NBTTagCompound) persistentBase); -- } -- // CraftBukkit end -- }); -+ object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. -+ createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities", "ChunkBukkitValues")) // Paper - move CB Chunk PDC into here -+ );// Paper end - } else { - ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter - -@@ -313,6 +308,50 @@ public class ChunkRegionLoader { - return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading - } - } -+ // Paper start -+ -+ /** -+ * This wrapper will error out if any key is accessed that wasn't copied so we can catch it easy on an update -+ */ -+ private static class SafeNBTCopy extends NBTTagCompound { -+ private final java.util.Set keys = new java.util.HashSet(); -+ public SafeNBTCopy(NBTTagCompound base, String... keys) { -+ for (String key : keys) { -+ this.keys.add(key); -+ final NBTBase nbtBase = base.get(key); -+ if (nbtBase != null) { -+ this.set(key, nbtBase); -+ } -+ } -+ } -+ -+ @Override -+ public boolean hasKey(String s) { -+ if (super.hasKey(s)) { -+ return true; -+ } else if (keys.contains(s)) { -+ return false; -+ } -+ throw new IllegalStateException("Missing Key " + s + " in SafeNBTCopy"); -+ } -+ -+ @Override -+ public boolean hasKeyOfType(String s, int i) { -+ return hasKey(s) && super.hasKeyOfType(s, i); -+ } -+ } -+ private static java.util.function.Consumer createLoadEntitiesConsumer(NBTTagCompound nbt) { -+ return (chunk) -> { -+ loadEntities(nbt, chunk); -+ // CraftBukkit start - load chunk persistent data from nbt -+ NBTBase persistentBase = nbt.get("ChunkBukkitValues"); -+ if (persistentBase instanceof NBTTagCompound) { -+ chunk.persistentDataContainer.putAll((NBTTagCompound) persistentBase); -+ } -+ // CraftBukkit end -+ }; -+ } -+ // Paper end - - // Paper start - async chunk save for unload - public static final class AsyncSaveData { diff --git a/Unmapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch b/Unmapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch deleted file mode 100644 index 3581cde231..0000000000 --- a/Unmapped-Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 12 May 2020 23:02:43 +0200 -Subject: [PATCH] Workaround for Client Lag Spikes (MC-162253) - -When crossing certain chunk boundaries, the client needlessly -calculates light maps for chunk neighbours. In some specific map -configurations, these calculations cause a 500ms+ freeze on the Client. - -This patch basically serves as a workaround by sending light maps -to the client, so that it doesn't attempt to calculate them. -This mitigates the frametime impact to a minimum (but it's still there). - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index c3394b22d1a22fd83ff43473da34704ad547836f..6ddbc83a08be4e7aa5cd85cf78f14604d4759f30 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -85,6 +85,7 @@ import net.minecraft.world.level.World; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkConverter; - import net.minecraft.world.level.chunk.ChunkGenerator; -+import net.minecraft.world.level.chunk.ChunkSection; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.IChunkAccess; - import net.minecraft.world.level.chunk.ILightAccess; -@@ -2063,9 +2064,68 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - public final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { - if (apacket[0] == null) { -+ // Paper start - add 8 for light fix workaround -+ if (apacket.length != 10) { // in case Plugins call sendChunk, resize -+ apacket = new Packet[10]; -+ } -+ // Paper end - apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(entityplayer, chunk, 65535)); // Paper - Anti-Xray - Bypass - apacket[1] = new PacketPlayOutLightUpdate(chunk.getPos(), this.lightEngine, true); -+ -+ // Paper start - Fix MC-162253 -+ final int lightMask = getLightMask(chunk); -+ int i = 1; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) { -+ continue; -+ } -+ -+ ++i; -+ -+ if (!chunk.isNeighbourLoaded(x, z)) { -+ continue; -+ } -+ -+ final Chunk neighbor = chunk.getRelativeNeighbourIfLoaded(x, z); -+ final int updateLightMask = lightMask & ~getCeilingLightMask(neighbor); -+ -+ if (updateLightMask == 0) { -+ continue; -+ } -+ -+ apacket[i] = new PacketPlayOutLightUpdate(new ChunkCoordIntPair(chunk.getPos().x + x, chunk.getPos().z + z), lightEngine, updateLightMask, 0, true); -+ } -+ } -+ } -+ -+ final int viewDistance = playerViewDistanceBroadcastMap.getLastViewDistance(entityplayer); -+ final long lastPosition = playerViewDistanceBroadcastMap.getLastCoordinate(entityplayer); -+ -+ int j = 1; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) { -+ continue; -+ } -+ -+ ++j; -+ -+ Packet packet = apacket[j]; -+ if (packet == null) { -+ continue; -+ } -+ -+ final int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - (chunk.getPos().x + x)); -+ final int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - (chunk.getPos().z + z)); -+ -+ if (Math.max(distX, distZ) > viewDistance) { -+ continue; -+ } -+ entityplayer.playerConnection.sendPacket(packet); -+ } - } -+ // Paper end - Fix MC-162253 - - entityplayer.a(chunk.getPos(), apacket[0], apacket[1]); - PacketDebug.a(this.world, chunk.getPos()); -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 90e895e9eac6158a28de4a30589bf7538e5ec9cc..34a9f7b2f998f77b1279516cd09397ab6c2ac1cc 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -280,7 +280,7 @@ public class Chunk implements IChunkAccess { - - // broadcast - Object[] backingSet = inRange.getBackingSet(); -- Packet[] chunkPackets = new Packet[2]; -+ Packet[] chunkPackets = new Packet[10]; - for (int index = 0, len = backingSet.length; index < len; ++index) { - Object temp = backingSet[index]; - if (!(temp instanceof EntityPlayer)) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index 973aa060d6964c7d470bc7aff89b879daf1df153..8fe060c3b2ad0873f96218eb7d02cdff3279224e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -107,6 +107,7 @@ public class ChunkSection { - return this.nonEmptyBlockCount == 0; - } - -+ public static boolean isEmpty(@Nullable ChunkSection chunksection) { return a(chunksection) ; } // Paper - OBFHELPER - public static boolean a(@Nullable ChunkSection chunksection) { - return chunksection == Chunk.a || chunksection.c(); - } diff --git a/Unmapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/Unmapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch deleted file mode 100644 index 107312d21f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch +++ /dev/null @@ -1,1326 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Apr 2020 03:56:07 -0400 -Subject: [PATCH] Implement Chunk Priority / Urgency System for Chunks - -Mark chunks that are blocking main thread for world generation as urgent - -Implements a general priority system so that chunks that are sorted in -the generator queues can prioritize certain chunks over another. - -Urgent chunks will jump to the front of the line, ensuring that a -sync chunk load on an ungenerated chunk does not lag the server for -a long period of time if the servers generator queues are filled with -lots of chunks already. - -This massively reduces the lag spikes from sync chunk gens. - -Then we further prioritize loading order so nearby chunks have higher -priority than distant chunks, reducing the pressure a high no tick -view distance holds on you. - -Chunks in front of the player have higher priority, to help with -fast traveling players keep up with their movement. - -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -index 8e642f450b974d81f128d26edfd40915554db638..dc641664abe8ff6b36c69c7d21a3200d160ff1b6 100644 ---- a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -@@ -108,7 +108,7 @@ public final class ChunkTaskManager { - } - - static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z) { -- dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); -+ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 4); - } - - static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z, int indent, int maxDepth) { -@@ -129,6 +129,30 @@ public final class ChunkTaskManager { - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getChunkStatus().toString())); - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + PlayerChunk.getChunkStatus(chunkHolder.getTicketLevel())); - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Priority - " + chunkHolder.getCurrentPriority()); -+ -+ if (!chunkHolder.neighbors.isEmpty()) { -+ if (indent >= maxDepth) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: (Can't show, too deeply nested)"); -+ return; -+ } -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: "); -+ for (PlayerChunk neighbor : chunkHolder.neighbors.keySet()) { -+ ChunkStatus status = neighbor.getChunkHolderStatus(); -+ if (status != null && status.isAtLeastStatus(PlayerChunk.getChunkStatus(neighbor.getTicketLevel()))) { -+ continue; -+ } -+ int nx = neighbor.location.x; -+ int nz = neighbor.location.z; -+ if (seenChunks.contains(neighbor)) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + " (CIRCULAR)"); -+ continue; -+ } -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + ":"); -+ dumpChunkInfo(seenChunks, neighbor, nx, nz, indent + 1, maxDepth); -+ } -+ } -+ - } - } - -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 17de074111a174f3a39a4477afc3ad62e04a73b5..1d72af9cace7aa8f1d20c7c1c5be621f533e2dad 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -673,6 +673,7 @@ public final class MCUtil { - chunkData.addProperty("x", playerChunk.location.x); - chunkData.addProperty("z", playerChunk.location.z); - chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); -+ chunkData.addProperty("priority", playerChunk.getCurrentPriority()); - chunkData.addProperty("state", PlayerChunk.getChunkState(playerChunk.getTicketLevel()).toString()); - chunkData.addProperty("queued-for-unload", chunkMap.unloadQueue.contains(playerChunk.location.pair())); - chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 2bbdcedf4856080ea9232effdf3bdae9c26c425b..a3c44fdfca8290313b9b1117b984533183b583ad 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -21,7 +21,10 @@ import java.util.Set; - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.Executor; - import javax.annotation.Nullable; -+import net.minecraft.core.BlockPosition; - import net.minecraft.core.SectionPosition; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ArraySetSorted; - import net.minecraft.util.thread.Mailbox; - import net.minecraft.world.level.ChunkCoordIntPair; -@@ -29,6 +32,7 @@ import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkStatus; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import org.spigotmc.AsyncCatcher; // Paper - - public abstract class ChunkMapDistance { - -@@ -52,7 +56,7 @@ public abstract class ChunkMapDistance { - private final ChunkTaskQueueSorter i; - private final Mailbox> j; - private final Mailbox k; -- private final LongSet l = new LongOpenHashSet(); -+ private final LongSet l = new LongOpenHashSet(); public final LongSet getOnPlayerTicketAddQueue() { return l; } // Paper - OBFHELPER - private final Executor m; - private long currentTick; - -@@ -90,6 +94,7 @@ public abstract class ChunkMapDistance { - } - - private static int getLowestTicketLevel(ArraySetSorted> arraysetsorted) { -+ AsyncCatcher.catchOp("ChunkMapDistance::getLowestTicketLevel"); // Paper - return !arraysetsorted.isEmpty() ? ((Ticket) arraysetsorted.b()).b() : PlayerChunkMap.GOLDEN_TICKET + 1; - } - -@@ -103,6 +108,7 @@ public abstract class ChunkMapDistance { - - public boolean a(PlayerChunkMap playerchunkmap) { - //this.f.a(); // Paper - no longer used -+ AsyncCatcher.catchOp("DistanceManagerTick"); // Paper - this.g.a(); - int i = Integer.MAX_VALUE - this.ticketLevelTracker.a(Integer.MAX_VALUE); - boolean flag = i != 0; -@@ -113,11 +119,13 @@ public abstract class ChunkMapDistance { - - // Paper start - if (!this.pendingChunkUpdates.isEmpty()) { -+ this.pollingPendingChunkUpdates = true; try { - while(!this.pendingChunkUpdates.isEmpty()) { - PlayerChunk remove = this.pendingChunkUpdates.remove(); - remove.isUpdateQueued = false; - remove.a(playerchunkmap); - } -+ } finally { this.pollingPendingChunkUpdates = false; } - // Paper end - return true; - } else { -@@ -153,8 +161,10 @@ public abstract class ChunkMapDistance { - return flag; - } - } -+ boolean pollingPendingChunkUpdates = false; // Paper - - private boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean -+ AsyncCatcher.catchOp("ChunkMapDistance::addTicket"); // Paper - ArraySetSorted> arraysetsorted = this.e(i); - int j = getLowestTicketLevel(arraysetsorted); - Ticket ticket1 = (Ticket) arraysetsorted.a(ticket); // CraftBukkit - decompile error -@@ -168,7 +178,9 @@ public abstract class ChunkMapDistance { - } - - private boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean -+ AsyncCatcher.catchOp("ChunkMapDistance::removeTicket"); // Paper - ArraySetSorted> arraysetsorted = this.e(i); -+ int oldLevel = getLowestTicketLevel(arraysetsorted); // Paper - - boolean removed = false; // CraftBukkit - if (arraysetsorted.remove(ticket)) { -@@ -179,7 +191,8 @@ public abstract class ChunkMapDistance { - this.tickets.remove(i); - } - -- this.ticketLevelTracker.update(i, getLowestTicketLevel(arraysetsorted), false); -+ int newLevel = getLowestTicketLevel(arraysetsorted); // Paper -+ if (newLevel > oldLevel) this.ticketLevelTracker.update(i, newLevel, false); // Paper - return removed; // CraftBukkit - } - -@@ -188,6 +201,135 @@ public abstract class ChunkMapDistance { - this.addTicketAtLevel(tickettype, chunkcoordintpair, i, t0); - } - -+ // Paper start -+ public static final int PRIORITY_TICKET_LEVEL = PlayerChunkMap.GOLDEN_TICKET; -+ public static final int URGENT_PRIORITY = 29; -+ public boolean delayDistanceManagerTick = false; -+ public boolean markUrgent(ChunkCoordIntPair coords) { -+ return addPriorityTicket(coords, TicketType.URGENT, URGENT_PRIORITY); -+ } -+ public boolean markHighPriority(ChunkCoordIntPair coords, int priority) { -+ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); -+ return addPriorityTicket(coords, TicketType.PRIORITY, priority); -+ } -+ -+ public void markAreaHighPriority(ChunkCoordIntPair center, int priority, int radius) { -+ delayDistanceManagerTick = true; -+ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); -+ int finalPriority = priority; -+ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { -+ addPriorityTicket(coords, TicketType.PRIORITY, finalPriority); -+ }); -+ delayDistanceManagerTick = false; -+ chunkMap.world.getChunkProvider().tickDistanceManager(); -+ } -+ -+ public void clearAreaPriorityTickets(ChunkCoordIntPair center, int radius) { -+ delayDistanceManagerTick = true; -+ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { -+ this.removeTicket(coords.pair(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); -+ }); -+ delayDistanceManagerTick = false; -+ chunkMap.world.getChunkProvider().tickDistanceManager(); -+ } -+ -+ private boolean hasPlayerTicket(ChunkCoordIntPair coords, int level) { -+ ArraySetSorted> tickets = this.tickets.get(coords.pair()); -+ if (tickets == null || tickets.isEmpty()) { -+ return false; -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getTicketType() == TicketType.PLAYER && ticket.getTicketLevel() == level) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ private boolean addPriorityTicket(ChunkCoordIntPair coords, TicketType ticketType, int priority) { -+ AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket"); -+ long pair = coords.pair(); -+ PlayerChunk chunk = chunkMap.getUpdatingChunk(pair); -+ boolean needsTicket = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(pair) != null && !hasPlayerTicket(coords, 33); -+ -+ if (needsTicket) { -+ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); -+ getOnPlayerTicketAddQueue().add(pair); -+ addTicket(pair, ticket); -+ } -+ if ((chunk != null && chunk.isFullChunkReady())) { -+ if (needsTicket) { -+ chunkMap.world.getChunkProvider().tickDistanceManager(); -+ } -+ return needsTicket; -+ } -+ -+ boolean success; -+ if (!(success = updatePriorityTicket(coords, ticketType, priority))) { -+ Ticket ticket = new Ticket(ticketType, PRIORITY_TICKET_LEVEL, coords); -+ ticket.priority = priority; -+ success = this.addTicket(pair, ticket); -+ } else { -+ if (chunk == null) { -+ chunk = chunkMap.getUpdatingChunk(pair); -+ } -+ chunkMap.queueHolderUpdate(chunk); -+ } -+ -+ //chunkMap.world.getWorld().spawnParticle(priority <= 15 ? org.bukkit.Particle.EXPLOSION_HUGE : org.bukkit.Particle.EXPLOSION_NORMAL, chunkMap.world.getWorld().getPlayers(), null, coords.x << 4, 70, coords.z << 4, 2, 0, 0, 0, 1, null, true); -+ -+ chunkMap.world.getChunkProvider().tickDistanceManager(); -+ -+ return success; -+ } -+ -+ private boolean updatePriorityTicket(ChunkCoordIntPair coords, TicketType type, int priority) { -+ ArraySetSorted> tickets = this.tickets.get(coords.pair()); -+ if (tickets == null) { -+ return false; -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getTicketType() == type) { -+ // We only support increasing, not decreasing, too complicated -+ ticket.setCurrentTick(this.currentTick); -+ ticket.priority = Math.max(ticket.priority, priority); -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ public int getChunkPriority(ChunkCoordIntPair coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::getChunkPriority"); -+ ArraySetSorted> tickets = this.tickets.get(coords.pair()); -+ if (tickets == null) { -+ return 0; -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getTicketType() == TicketType.URGENT) { -+ return URGENT_PRIORITY; -+ } -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getTicketType() == TicketType.PRIORITY && ticket.priority > 0) { -+ return ticket.priority; -+ } -+ } -+ return 0; -+ } -+ -+ public void clearPriorityTickets(ChunkCoordIntPair coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::clearPriority"); -+ this.removeTicket(coords.pair(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); -+ } -+ -+ public void clearUrgent(ChunkCoordIntPair coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::clearUrgent"); -+ this.removeTicket(coords.pair(), new Ticket(TicketType.URGENT, PRIORITY_TICKET_LEVEL, coords)); -+ } -+ // Paper end - public boolean addTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkcoordintpair, int level, T identifier) { - return this.addTicket(chunkcoordintpair.pair(), new Ticket<>(ticketType, level, identifier)); - // CraftBukkit end -@@ -358,7 +500,7 @@ public abstract class ChunkMapDistance { - - class c extends ChunkMapDistance.b { - -- private int e = 0; -+ private int e = 0; private int getViewDistance() { return e; } private void setViewDistance(int value) { this.e = value; } // Paper - OBFHELPER - private final Long2IntMap f = Long2IntMaps.synchronize(new Long2IntOpenHashMap()); - private final LongSet g = new LongOpenHashSet(); - -@@ -374,41 +516,68 @@ public abstract class ChunkMapDistance { - - public void a(int i) { - ObjectIterator objectiterator = this.a.long2ByteEntrySet().iterator(); -+ // Paper start - set the view distance before scheduling chunk loads/unloads -+ int lastViewDistance = getViewDistance(); -+ setViewDistance(i); -+ // Paper end - - while (objectiterator.hasNext()) { - Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix - byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); - long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); - -- this.a(j, b0, this.c(b0), b0 <= i - 2); -+ this.a(j, b0, b0 <= lastViewDistance - 2, this.c(b0)); // Paper - } - -- this.e = i; -+ //this.e = i; // Paper - view distance is now set further up - } - - private void a(long i, int j, boolean flag, boolean flag1) { - if (flag != flag1) { -- Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkCoordIntPair(i)); // Paper - no-tick view distance -+ ChunkCoordIntPair coords = new ChunkCoordIntPair(i); // Paper -+ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); // Paper - no-tick view distance - - if (flag1) { -- ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { -+ scheduleChunkLoad(i, MinecraftServer.currentTick, j, (priority) -> { // Paper - smarter ticket delay based on frustum and distance -+ // Paper start - recheck its still valid if not cancel -+ if (!isChunkInRange(i)) { -+ ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { -+ ChunkMapDistance.this.m.execute(() -> { -+ ChunkMapDistance.this.removeTicket(i, ticket); -+ ChunkMapDistance.this.clearPriorityTickets(coords); -+ }); -+ }, i, false)); -+ return; -+ } -+ // abort early if we got a ticket already -+ if (hasPlayerTicket(coords, 33)) return; -+ // skip player ticket throttle for near chunks -+ if (priority <= 3) { -+ ChunkMapDistance.this.addTicket(i, ticket); -+ ChunkMapDistance.this.l.add(i); -+ return; -+ } -+ // Paper end -+ ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error - ChunkMapDistance.this.m.execute(() -> { -- if (this.c(this.c(i))) { -+ if (isChunkInRange(i)) { if (!hasPlayerTicket(coords, 33)) { // Paper - high priority might of already added it - ChunkMapDistance.this.addTicket(i, ticket); - ChunkMapDistance.this.l.add(i); -- } else { -- ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { -+ }} else { // Paper -+ ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error - }, i, false)); - } - - }); - }, i, () -> { -- return j; -+ return Math.min(PlayerChunkMap.GOLDEN_TICKET, priority); // Paper - })); -+ }); // Paper - } else { - ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { - ChunkMapDistance.this.m.execute(() -> { - ChunkMapDistance.this.removeTicket(i, ticket); -+ ChunkMapDistance.this.clearPriorityTickets(coords); // Paper - }); - }, i, true)); - } -@@ -416,6 +585,101 @@ public abstract class ChunkMapDistance { - - } - -+ // Paper start - smart scheduling of player tickets -+ private boolean isChunkInRange(long i) { -+ return this.isLoadedChunkLevel(this.getChunkLevel(i)); -+ } -+ public void scheduleChunkLoad(long i, long startTick, int initialDistance, java.util.function.Consumer task) { -+ long elapsed = MinecraftServer.currentTick - startTick; -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(i); -+ PlayerChunk updatingChunk = chunkMap.getUpdatingChunk(i); -+ if ((updatingChunk != null && updatingChunk.isFullChunkReady()) || !isChunkInRange(i) || getChunkPriority(chunkPos) > 0) { // Copied from above -+ // no longer needed -+ task.accept(1); -+ return; -+ } -+ -+ int desireDelay = 0; -+ double minDist = Double.MAX_VALUE; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(i); -+ if (elapsed == 0 && initialDistance <= 4) { -+ // Aim for no delay on initial 6 chunk radius tickets save on performance of the below code to only > 6 -+ minDist = initialDistance; -+ } else if (players != null) { -+ Object[] backingSet = players.getBackingSet(); -+ -+ BlockPosition blockPos = chunkPos.asPosition(); -+ -+ boolean isFront = false; -+ BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(); -+ for (int index = 0, len = backingSet.length; index < len; ++index) { -+ if (!(backingSet[index] instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer) backingSet[index]; -+ -+ ChunkCoordIntPair pointInFront = player.getChunkInFront(5); -+ pos.setValues(pointInFront.x << 4, 0, pointInFront.z << 4); -+ double frontDist = MCUtil.distanceSq(pos, blockPos); -+ -+ pos.setValues(player.locX(), 0, player.locZ()); -+ double center = MCUtil.distanceSq(pos, blockPos); -+ -+ double dist = Math.min(frontDist, center); -+ if (!isFront) { -+ ChunkCoordIntPair pointInBack = player.getChunkInFront(-7); -+ pos.setValues(pointInBack.x << 4, 0, pointInBack.z << 4); -+ double backDist = MCUtil.distanceSq(pos, blockPos); -+ if (frontDist < backDist) { -+ isFront = true; -+ } -+ } -+ if (dist < minDist) { -+ minDist = dist; -+ } -+ } -+ if (minDist == Double.MAX_VALUE) { -+ minDist = 15; -+ } else { -+ minDist = Math.sqrt(minDist) / 16; -+ } -+ if (minDist > 4) { -+ int desiredTimeDelayMax = isFront ? -+ (minDist < 10 ? 7 : 15) : // Front -+ (minDist < 10 ? 15 : 45); // Back -+ desireDelay += (desiredTimeDelayMax * 20) * (minDist / 32); -+ } -+ } else { -+ minDist = initialDistance; -+ desireDelay = 1; -+ } -+ long delay = desireDelay - elapsed; -+ if (delay <= 0 && minDist > 4 && minDist < Double.MAX_VALUE) { -+ boolean hasAnyNeighbor = false; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) continue; -+ long pair = ChunkCoordIntPair.pair(chunkPos.x + x, chunkPos.z + z); -+ PlayerChunk neighbor = chunkMap.getUpdatingChunk(pair); -+ ChunkStatus current = neighbor != null ? neighbor.getChunkHolderStatus() : null; -+ if (current != null && current.isAtLeastStatus(ChunkStatus.LIGHT)) { -+ hasAnyNeighbor = true; -+ } -+ } -+ } -+ if (!hasAnyNeighbor) { -+ delay += 20; -+ } -+ } -+ if (delay <= 0) { -+ task.accept((int) minDist); -+ } else { -+ int taskDelay = (int) Math.min(delay, minDist >= 10 ? 40 : (minDist < 6 ? 5 : 20)); -+ MCUtil.scheduleTask(taskDelay, () -> scheduleChunkLoad(i, startTick, initialDistance, task), "Player Ticket Delayer"); -+ } -+ } -+ // Paper end -+ - @Override - public void a() { - super.a(); -@@ -447,6 +711,7 @@ public abstract class ChunkMapDistance { - - } - -+ private boolean isLoadedChunkLevel(int i) { return c(i); } // Paper - OBFHELPER - private boolean c(int i) { - return i <= this.e - 2; - } -@@ -463,6 +728,7 @@ public abstract class ChunkMapDistance { - this.a.defaultReturnValue((byte) (i + 2)); - } - -+ protected final int getChunkLevel(long i) { return c(i); } // Paper - OBFHELPER - @Override - protected int c(long i) { - return this.a.get(i); -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 46a2e89df71654024102427859c385fc2e09cae7..17a4970cf78f3ee3a62a76a3f9e28251db17bac2 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -468,6 +468,26 @@ public class ChunkProviderServer extends IChunkProvider { - public void removeTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { - this.chunkMapDistance.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); - } -+ -+ public boolean markUrgent(ChunkCoordIntPair coords) { -+ return this.chunkMapDistance.markUrgent(coords); -+ } -+ -+ public boolean markHighPriority(ChunkCoordIntPair coords, int priority) { -+ return this.chunkMapDistance.markHighPriority(coords, priority); -+ } -+ -+ public void markAreaHighPriority(ChunkCoordIntPair center, int priority, int radius) { -+ this.chunkMapDistance.markAreaHighPriority(center, priority, radius); -+ } -+ -+ public void clearAreaPriorityTickets(ChunkCoordIntPair center, int radius) { -+ this.chunkMapDistance.clearAreaPriorityTickets(center, radius); -+ } -+ -+ public void clearPriorityTickets(ChunkCoordIntPair coords) { -+ this.chunkMapDistance.clearPriorityTickets(coords); -+ } - // Paper end - - @Nullable -@@ -506,6 +526,8 @@ public class ChunkProviderServer extends IChunkProvider { - - if (!completablefuture.isDone()) { // Paper - // Paper start - async chunk io/loading -+ ChunkCoordIntPair pair = new ChunkCoordIntPair(x, z); -+ this.chunkMapDistance.markUrgent(pair); - this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z); - // Paper end -@@ -514,6 +536,8 @@ public class ChunkProviderServer extends IChunkProvider { - this.serverThreadQueue.awaitTasks(completablefuture::isDone); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug - this.world.timings.syncChunkLoad.stopTiming(); // Paper -+ this.chunkMapDistance.clearPriorityTickets(pair); // Paper -+ this.chunkMapDistance.clearUrgent(pair); // Paper - } // Paper - ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { - return ichunkaccess1; -@@ -566,10 +590,12 @@ public class ChunkProviderServer extends IChunkProvider { - if (flag && !currentlyUnloading) { - // CraftBukkit end - this.chunkMapDistance.a(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); -+ if (isUrgent) this.chunkMapDistance.markUrgent(chunkcoordintpair); // Paper - if (this.a(playerchunk, l)) { - GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); - - gameprofilerfiller.enter("chunkLoad"); -+ chunkMapDistance.delayDistanceManagerTick = false; // Paper - ensure this is never false - this.tickDistanceManager(); - playerchunk = this.getChunk(k); - gameprofilerfiller.exit(); -@@ -578,8 +604,13 @@ public class ChunkProviderServer extends IChunkProvider { - } - } - } -- -- return this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap); -+ // Paper start -+ CompletableFuture> future = this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap); -+ if (isUrgent) { -+ future.thenAccept(either -> this.chunkMapDistance.clearUrgent(chunkcoordintpair)); -+ } -+ return future; -+ // Paper end - } - - private boolean a(@Nullable PlayerChunk playerchunk, int i) { -@@ -630,6 +661,7 @@ public class ChunkProviderServer extends IChunkProvider { - } - - public boolean tickDistanceManager() { // Paper - private -> public -+ if (chunkMapDistance.delayDistanceManagerTick) return false; // Paper - boolean flag = this.chunkMapDistance.a(this.playerChunkMap); - boolean flag1 = this.playerChunkMap.b(); - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 89a66078b722f265abd73579545a1f24df9442aa..8055172c806f285aa9a9e6de681d03b008fbf785 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -73,6 +73,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.AdvancementDataPlayer; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.network.ITextFilter; - import net.minecraft.server.network.PlayerConnection; -@@ -188,6 +189,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - private int lastArmorScored = Integer.MIN_VALUE; - private int lastExpLevelScored = Integer.MIN_VALUE; - private int lastExpTotalScored = Integer.MIN_VALUE; -+ public long lastHighPriorityChecked; // Paper -+ public void forceCheckHighPriority() { -+ lastHighPriorityChecked = -1; -+ getWorldServer().getChunkProvider().playerChunkMap.checkHighPriorityChunks(this); -+ } -+ public boolean isRealPlayer; // Paper - private float lastHealthSent = -1.0E8F; - private int lastFoodSent = -99999999; - private boolean lastSentSaturationZero = true; -@@ -275,6 +282,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.maxHealthCache = this.getMaxHealth(); - this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper - } -+ // Paper start -+ public BlockPosition getPointInFront(double inFront) { -+ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yaw+90)); // MC rotates yaw 90 for some odd reason -+ final double x = locX() + inFront * Math.cos(rads); -+ final double z = locZ() + inFront * Math.sin(rads); -+ return new BlockPosition(x, locY(), z); -+ } -+ -+ public ChunkCoordIntPair getChunkInFront(double inFront) { -+ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yaw+90)); // MC rotates yaw 90 for some odd reason -+ final double x = locX() + (inFront * 16) * Math.cos(rads); -+ final double z = locZ() + (inFront * 16) * Math.sin(rads); -+ return new ChunkCoordIntPair(MathHelper.floor(x) >> 4, MathHelper.floor(z) >> 4); -+ } -+ // Paper end - - // Yes, this doesn't match Vanilla, but it's the best we can do for now. - // If this is an issue, PRs are welcome -@@ -622,6 +644,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - if (valid && !this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) - super.tick(); - } -+ if (valid && isAlive() && playerConnection != null) ((WorldServer)world).getChunkProvider().playerChunkMap.checkHighPriorityChunks(this); // Paper - - for (int i = 0; i < this.inventory.getSize(); ++i) { - ItemStack itemstack = this.inventory.getItem(i); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index e53054fc46e528f9c713eb4c03add61316e19396..fc79a73c884ceb7e0ce56443c36b135c4e525193 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -1,6 +1,7 @@ - package net.minecraft.server.level; - - import com.mojang.datafixers.util.Either; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper - import it.unimi.dsi.fastutil.shorts.ShortArraySet; - import it.unimi.dsi.fastutil.shorts.ShortSet; - import java.util.List; -@@ -19,6 +20,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutBlockChange; - import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.network.protocol.game.PacketPlayOutMultiBlockChange; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.util.MathHelper; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumSkyBlock; -@@ -53,8 +55,8 @@ public class PlayerChunk { - private CompletableFuture chunkSave; - public int oldTicketLevel; - private int ticketLevel; -- private int n; -- final ChunkCoordIntPair location; // Paper - private -> package -+ volatile int n; public final int getCurrentPriority() { return n; } // Paper - OBFHELPER - make volatile since this is concurrently accessed -+ public final ChunkCoordIntPair location; // Paper - private -> public - private boolean p; - private final ShortSet[] dirtyBlocks; - private int r; -@@ -66,6 +68,7 @@ public class PlayerChunk { - private boolean x; - - private final PlayerChunkMap chunkMap; // Paper -+ public WorldServer getWorld() { return chunkMap.world; } // Paper - - long lastAutoSaveTime; // Paper - incremental autosave - long inactiveTimeStart; // Paper - incremental autosave -@@ -93,6 +96,120 @@ public class PlayerChunk { - return null; - } - // Paper end - no-tick view distance -+ // Paper start - Chunk gen/load priority system -+ volatile int neighborPriority = -1; -+ volatile int priorityBoost = 0; -+ public final java.util.concurrent.ConcurrentHashMap neighbors = new java.util.concurrent.ConcurrentHashMap<>(); -+ public final Long2ObjectOpenHashMap neighborPriorities = new Long2ObjectOpenHashMap<>(); -+ -+ private int getDemandedPriority() { -+ int priority = neighborPriority; // if we have a neighbor priority, use it -+ int myPriority = getMyPriority(); -+ -+ if (priority == -1 || (ticketLevel <= 33 && priority > myPriority)) { -+ priority = myPriority; -+ } -+ -+ return Math.max(1, Math.min(Math.max(ticketLevel, PlayerChunkMap.GOLDEN_TICKET), priority)); -+ } -+ -+ private int getMyPriority() { -+ if (priorityBoost == ChunkMapDistance.URGENT_PRIORITY) { -+ return 2; // Urgent - ticket level isn't always 31 so 33-30 = 3, but allow 1 more tasks to go below this for dependents -+ } -+ return ticketLevel - priorityBoost; -+ } -+ -+ private int getNeighborsPriority() { -+ return (neighborPriorities.isEmpty() ? getMyPriority() : getDemandedPriority()) + 1; -+ } -+ -+ public void onNeighborRequest(PlayerChunk neighbor, ChunkStatus status) { -+ neighbor.setNeighborPriority(this, getNeighborsPriority()); -+ this.neighbors.compute(neighbor, (playerChunk, currentWantedStatus) -> { -+ if (currentWantedStatus == null || !currentWantedStatus.isAtLeastStatus(status)) { -+ //System.out.println(this + " request " + neighbor + " at " + status + " currently " + currentWantedStatus); -+ return status; -+ } else { -+ //System.out.println(this + " requested " + neighbor + " at " + status + " but thats lower than other wanted status " + currentWantedStatus); -+ return currentWantedStatus; -+ } -+ }); -+ -+ } -+ -+ public void onNeighborDone(PlayerChunk neighbor, ChunkStatus chunkstatus, IChunkAccess chunk) { -+ this.neighbors.compute(neighbor, (playerChunk, wantedStatus) -> { -+ if (wantedStatus != null && chunkstatus.isAtLeastStatus(wantedStatus)) { -+ //System.out.println(this + " neighbor done at " + neighbor + " for status " + chunkstatus + " wanted " + wantedStatus); -+ neighbor.removeNeighborPriority(this); -+ return null; -+ } else { -+ //System.out.println(this + " neighbor finished our previous request at " + neighbor + " for status " + chunkstatus + " but we now want instead " + wantedStatus); -+ return wantedStatus; -+ } -+ }); -+ } -+ -+ private void removeNeighborPriority(PlayerChunk requester) { -+ synchronized (neighborPriorities) { -+ neighborPriorities.remove(requester.location.pair()); -+ recalcNeighborPriority(); -+ } -+ checkPriority(); -+ } -+ -+ -+ private void setNeighborPriority(PlayerChunk requester, int priority) { -+ synchronized (neighborPriorities) { -+ neighborPriorities.put(requester.location.pair(), Integer.valueOf(priority)); -+ recalcNeighborPriority(); -+ } -+ checkPriority(); -+ } -+ -+ private void recalcNeighborPriority() { -+ neighborPriority = -1; -+ if (!neighborPriorities.isEmpty()) { -+ synchronized (neighborPriorities) { -+ for (Integer neighbor : neighborPriorities.values()) { -+ if (neighbor < neighborPriority || neighborPriority == -1) { -+ neighborPriority = neighbor; -+ } -+ } -+ } -+ } -+ } -+ private void checkPriority() { -+ if (getCurrentPriority() != getDemandedPriority()) this.chunkMap.queueHolderUpdate(this); -+ } -+ -+ public final double getDistance(EntityPlayer player) { -+ return getDistance(player.locX(), player.locZ()); -+ } -+ public final double getDistance(double blockX, double blockZ) { -+ int cx = MCUtil.fastFloor(blockX) >> 4; -+ int cz = MCUtil.fastFloor(blockZ) >> 4; -+ final double x = location.x - cx; -+ final double z = location.z - cz; -+ return (x * x) + (z * z); -+ } -+ -+ public final double getDistanceFrom(BlockPosition pos) { -+ return getDistance(pos.getX(), pos.getZ()); -+ } -+ -+ @Override -+ public String toString() { -+ return "PlayerChunk{" + -+ "location=" + location + -+ ", ticketLevel=" + ticketLevel + "/" + getChunkStatus(this.ticketLevel) + -+ ", chunkHolderStatus=" + getChunkHolderStatus() + -+ ", neighborPriority=" + getNeighborsPriority() + -+ ", priority=(" + ticketLevel + " - " + priorityBoost +" vs N " + neighborPriority + ") = " + getDemandedPriority() + " A " + getCurrentPriority() + -+ '}'; -+ } -+ // Paper end - - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); -@@ -195,6 +312,18 @@ public class PlayerChunk { - } - return null; - } -+ public static ChunkStatus getNextStatus(ChunkStatus status) { -+ if (status == ChunkStatus.FULL) { -+ return status; -+ } -+ return CHUNK_STATUSES.get(status.getStatusIndex() + 1); -+ } -+ public CompletableFuture> getStatusFutureUncheckedMain(ChunkStatus chunkstatus) { -+ return ensureMain(getStatusFutureUnchecked(chunkstatus)); -+ } -+ public CompletableFuture ensureMain(CompletableFuture future) { -+ return future.thenApplyAsync(r -> r, chunkMap.mainInvokingExecutor); -+ } - // Paper end - - public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { -@@ -441,6 +570,7 @@ public class PlayerChunk { - return this.n; - } - -+ private void setPriority(int i) { d(i); } // Paper - OBFHELPER - private void d(int i) { - this.n = i; - } -@@ -459,7 +589,7 @@ public class PlayerChunk { - // CraftBukkit start - // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. - if (playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && !playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) { -- this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> { -+ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main - Chunk chunk = (Chunk)either.left().orElse(null); - if (chunk != null) { - playerchunkmap.callbackExecutor.execute(() -> { -@@ -524,12 +654,13 @@ public class PlayerChunk { - if (!flag2 && flag3) { - // Paper start - cache ticking ready status - int expectCreateCount = ++this.fullChunkCreateCount; -- this.fullChunkFuture = playerchunkmap.b(this); this.fullChunkFuture.thenAccept((either) -> { -+ this.fullChunkFuture = playerchunkmap.b(this); ensureMain(this.fullChunkFuture).thenAccept((either) -> { // Paper - ensure main - if (either.left().isPresent() && PlayerChunk.this.fullChunkCreateCount == expectCreateCount) { - // note: Here is a very good place to add callbacks to logic waiting on this. - Chunk fullChunk = either.left().get(); - PlayerChunk.this.isFullChunkReady = true; - fullChunk.playerChunk = PlayerChunk.this; -+ this.chunkMap.chunkDistanceManager.clearPriorityTickets(location); - - - } -@@ -554,7 +685,7 @@ public class PlayerChunk { - - if (!flag4 && flag5) { - // Paper start - cache ticking ready status -- this.tickingFuture = playerchunkmap.a(this); this.tickingFuture.thenAccept((either) -> { -+ this.tickingFuture = playerchunkmap.a(this); ensureMain(this.tickingFuture).thenAccept((either) -> { // Paper - ensure main - if (either.left().isPresent()) { - // note: Here is a very good place to add callbacks to logic waiting on this. - Chunk tickingChunk = either.left().get(); -@@ -585,7 +716,7 @@ public class PlayerChunk { - } - - // Paper start - cache ticking ready status -- this.entityTickingFuture = playerchunkmap.b(this.location); this.entityTickingFuture.thenAccept((either) -> { -+ this.entityTickingFuture = playerchunkmap.b(this.location); ensureMain(this.entityTickingFuture).thenAccept((either) -> { // Paper ensureMain - if (either.left().isPresent()) { - // note: Here is a very good place to add callbacks to logic waiting on this. - Chunk entityTickingChunk = either.left().get(); -@@ -605,12 +736,29 @@ public class PlayerChunk { - this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; - } - -- this.u.a(this.location, this::k, this.ticketLevel, this::d); -+ // Paper start - raise IO/load priority if priority changes, use our preferred priority -+ priorityBoost = chunkMap.chunkDistanceManager.getChunkPriority(location); -+ int priority = getDemandedPriority(); -+ if (getCurrentPriority() > priority) { -+ int ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; -+ if (priority <= 10) { -+ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; -+ } else if (priority <= 20) { -+ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; -+ } -+ chunkMap.world.asyncChunkTaskManager.raisePriority(location.x, location.z, ioPriority); -+ } -+ if (getCurrentPriority() != priority) { -+ this.u.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority -+ int neighborsPriority = getNeighborsPriority(); -+ this.neighbors.forEach((neighbor, neighborDesired) -> neighbor.setNeighborPriority(this, neighborsPriority)); -+ } -+ // Paper end - this.oldTicketLevel = this.ticketLevel; - // CraftBukkit start - // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. - if (!playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) { -- this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> { -+ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main - Chunk chunk = (Chunk)either.left().orElse(null); - if (chunk != null) { - playerchunkmap.callbackExecutor.execute(() -> { -@@ -692,6 +840,7 @@ public class PlayerChunk { - - public interface c { - -+ default void changePriority(ChunkCoordIntPair chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer) { a(chunkcoordintpair, intsupplier, i, intconsumer); } // Paper - OBFHELPER - void a(ChunkCoordIntPair chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer); - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 6ddbc83a08be4e7aa5cd85cf78f14604d4759f30..5bea15ba1ee3d2c8e8d78ab34ba75723164b7117 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -14,6 +14,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; - import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - import it.unimi.dsi.fastutil.longs.Long2ByteMap; - import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; // Paper - import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; - import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; - import it.unimi.dsi.fastutil.longs.LongIterator; -@@ -51,6 +52,7 @@ import net.minecraft.CrashReport; - import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; - import net.minecraft.SystemUtils; -+import net.minecraft.core.BlockPosition; - import net.minecraft.core.SectionPosition; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.Packet; -@@ -105,6 +107,7 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - import org.bukkit.entity.Player; // CraftBukkit -+import org.spigotmc.AsyncCatcher; - - public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - -@@ -142,6 +145,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final WorldServer world; - private final LightEngineThreaded lightEngine; - private final IAsyncTaskHandler executor; -+ final java.util.concurrent.Executor mainInvokingExecutor; // Paper - public final ChunkGenerator chunkGenerator; - private final Supplier l; public final Supplier getWorldPersistentDataSupplier() { return this.l; } // Paper - OBFHELPER - private final VillagePlace m; -@@ -179,6 +183,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - @Override - public void execute(Runnable runnable) { -+ AsyncCatcher.catchOp("Callback Executor execute"); - if (queued == null) { - queued = new java.util.ArrayDeque<>(); - } -@@ -187,6 +192,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - @Override - public void run() { -+ AsyncCatcher.catchOp("Callback Executor run"); - if (queued == null) { - return; - } -@@ -341,6 +347,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.world = worldserver; - this.chunkGenerator = chunkgenerator; - this.executor = iasynctaskhandler; -+ // Paper start -+ this.mainInvokingExecutor = (run) -> { -+ if (MCUtil.isMainThread()) { -+ run.run(); -+ } else { -+ iasynctaskhandler.execute(run); -+ } -+ }; -+ // Paper end - ThreadedMailbox threadedmailbox = ThreadedMailbox.a(executor, "worldgen"); - - iasynctaskhandler.getClass(); -@@ -435,6 +450,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, - (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, - com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ checkHighPriorityChunks(player); - if (newState.size() != 1) { - return; - } -@@ -453,7 +469,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ); - PlayerChunkMap.this.world.getChunkProvider().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update -- }); -+ PlayerChunkMap.this.world.getChunkProvider().clearPriorityTickets(chunkPos); -+ }, (player, prevPos, newPos) -> { -+ player.lastHighPriorityChecked = -1; // reset and recheck -+ checkHighPriorityChunks(player); -+ }); - this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); - this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, - (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -@@ -470,6 +490,115 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }); - // Paper end - no-tick view distance - } -+ // Paper start - Chunk Prioritization -+ public void queueHolderUpdate(PlayerChunk playerchunk) { -+ Runnable runnable = () -> { -+ if (isUnloading(playerchunk)) { -+ return; // unloaded -+ } -+ chunkDistanceManager.pendingChunkUpdates.add(playerchunk); -+ if (!chunkDistanceManager.pollingPendingChunkUpdates) { -+ world.getChunkProvider().tickDistanceManager(); -+ } -+ }; -+ if (MCUtil.isMainThread()) { -+ // We can't use executor here because it will not execute tasks if its currently in the middle of executing tasks... -+ runnable.run(); -+ } else { -+ executor.execute(runnable); -+ } -+ } -+ -+ private boolean isUnloading(PlayerChunk playerchunk) { -+ return playerchunk == null || unloadQueue.contains(playerchunk.location.pair()); -+ } -+ -+ private void updateChunkPriorityMap(Long2IntOpenHashMap map, long chunk, int level) { -+ int prev = map.getOrDefault(chunk, -1); -+ if (level > prev) { -+ map.put(chunk, level); -+ } -+ } -+ -+ public void checkHighPriorityChunks(EntityPlayer player) { -+ int currentTick = MinecraftServer.currentTick; -+ if (currentTick - player.lastHighPriorityChecked < 20 || !player.isRealPlayer) { // weed out fake players -+ return; -+ } -+ player.lastHighPriorityChecked = currentTick; -+ Long2IntOpenHashMap priorities = new Long2IntOpenHashMap(); -+ -+ int viewDistance = getEffectiveNoTickViewDistance(); -+ BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(); -+ -+ // Prioritize circular near -+ double playerChunkX = MathHelper.floor(player.locX()) >> 4; -+ double playerChunkZ = MathHelper.floor(player.locZ()) >> 4; -+ pos.setValues(player.locX(), 0, player.locZ()); -+ double twoThirdModifier = 2D / 3D; -+ MCUtil.getSpiralOutChunks(pos, Math.min(6, viewDistance)).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) return; -+ -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ // Prioritize immediate -+ if (dist <= 4) { -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (27 - dist)); -+ return; -+ } -+ -+ // Prioritize nearby chunks -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (20 - dist * twoThirdModifier)); -+ }); -+ -+ // Prioritize Frustum near 3 -+ ChunkCoordIntPair front3 = player.getChunkInFront(3); -+ pos.setValues(front3.x << 4, 0, front3.z << 4); -+ MCUtil.getSpiralOutChunks(pos, Math.min(5, viewDistance)).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) return; -+ -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - dist * twoThirdModifier)); -+ }); -+ -+ // Prioritize Frustum near 5 -+ if (viewDistance > 4) { -+ ChunkCoordIntPair front5 = player.getChunkInFront(5); -+ pos.setValues(front5.x << 4, 0, front5.z << 4); -+ MCUtil.getSpiralOutChunks(pos, 4).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) return; -+ -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - dist * twoThirdModifier)); -+ }); -+ } -+ -+ // Prioritize Frustum far 7 -+ if (viewDistance > 6) { -+ ChunkCoordIntPair front7 = player.getChunkInFront(7); -+ pos.setValues(front7.x << 4, 0, front7.z << 4); -+ MCUtil.getSpiralOutChunks(pos, 3).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) { -+ return; -+ } -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - dist * twoThirdModifier)); -+ }); -+ } -+ -+ if (priorities.isEmpty()) return; -+ chunkDistanceManager.delayDistanceManagerTick = true; -+ priorities.long2IntEntrySet().fastForEach(entry -> chunkDistanceManager.markHighPriority(new ChunkCoordIntPair(entry.getLongKey()), entry.getIntValue())); -+ chunkDistanceManager.delayDistanceManagerTick = false; -+ world.getChunkProvider().tickDistanceManager(); -+ -+ } -+ -+ private boolean shouldSkipPrioritization(ChunkCoordIntPair coord) { -+ if (playerViewDistanceNoTickMap.getObjectsInRange(coord.pair()) == null) return true; -+ PlayerChunk chunk = getUpdatingChunk(coord.pair()); -+ return chunk != null && (chunk.isFullChunkReady()); -+ } -+ // Paper end - - public void updatePlayerMobTypeMap(Entity entity) { - if (!this.world.paperConfig.perPlayerMobSpawns) { -@@ -599,6 +728,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - List>> list = Lists.newArrayList(); - int j = chunkcoordintpair.x; - int k = chunkcoordintpair.z; -+ PlayerChunk requestingNeighbor = getUpdatingChunk(chunkcoordintpair.pair()); // Paper - - for (int l = -i; l <= i; ++l) { - for (int i1 = -i; i1 <= i; ++i1) { -@@ -617,6 +747,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - ChunkStatus chunkstatus = (ChunkStatus) intfunction.apply(j1); - CompletableFuture> completablefuture = playerchunk.a(chunkstatus, this); -+ // Paper start -+ if (requestingNeighbor != null && requestingNeighbor != playerchunk && !completablefuture.isDone()) { -+ requestingNeighbor.onNeighborRequest(playerchunk, chunkstatus); -+ completablefuture.thenAccept(either -> { -+ requestingNeighbor.onNeighborDone(playerchunk, chunkstatus, either.left().orElse(null)); -+ }); -+ } -+ // Paper end - - list.add(completablefuture); - } -@@ -1084,14 +1222,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }; - - CompletableFuture chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z); -+ PlayerChunk playerChunk = getUpdatingChunk(chunkcoordintpair.pair()); -+ int chunkPriority = playerChunk != null ? playerChunk.getCurrentPriority() : 33; -+ int priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; -+ -+ if (chunkPriority <= 10) { -+ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; -+ } else if (chunkPriority <= 20) { -+ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; -+ } -+ boolean isHighestPriority = priority == com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; - if (chunkSaveFuture != null) { -- this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, -- com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); -- this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, priority, chunkHolderConsumer, isHighestPriority, chunkSaveFuture); - } else { -- this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, -- com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, priority, chunkHolderConsumer, isHighestPriority); - } -+ this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, priority); - return ret; - // Paper end - } -@@ -1236,7 +1382,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - long i = playerchunk.i().pair(); - - playerchunk.getClass(); -- mailbox.a(ChunkTaskQueueSorter.a(runnable, i, playerchunk::getTicketLevel)); -+ mailbox.a(ChunkTaskQueueSorter.a(runnable, i, () -> 1)); // Paper - final loads are always urgent! - }); - } - -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index e06fe77f6ea05a93e95fce223bcfd0d16394f96f..90cbd12611b7b078f35f08f910453bcc02f6665b 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -8,6 +8,7 @@ public final class Ticket implements Comparable> { - private final int b; - public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER - private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER -+ public int priority = 0; // Paper - - protected Ticket(TicketType tickettype, int i, T t0) { - this.a = tickettype; -@@ -56,6 +57,7 @@ public final class Ticket implements Comparable> { - return this.b; - } - -+ public final void setCurrentTick(long i) { this.a(i); } // Paper - OBFHELPER - protected void a(long i) { - this.d = i; - } -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 2c932d36f982e7f8713aabff9a6c631055810366..f5d18834e0e2ee0e3bcf55810456766d2f134450 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -28,6 +28,8 @@ public class TicketType { - public static final TicketType PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit - public static final TicketType FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper - public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper -+ public static final TicketType PRIORITY = a("priority", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper -+ public static final TicketType URGENT = a("urgent", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper - - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index b491a3563bf457bcb631e05cf41b661712134966..40fefdb9da9c4fd3ef3e3bb6276de215dd5265f9 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1530,6 +1530,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.A = this.e; - this.player.setLocation(d0, d1, d2, f, f1); -+ this.player.forceCheckHighPriority(); // Paper - this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.teleportAwait)); - } - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 66fcd68f0a0a21b113e8741cc42c841f49009118..b4c5915cc68a838259129b8973b3a6a39c1fc963 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -275,8 +275,8 @@ public abstract class PlayerList { - final ChunkCoordIntPair pos = new ChunkCoordIntPair(chunkX, chunkZ); - PlayerChunkMap playerChunkMap = worldserver1.getChunkProvider().playerChunkMap; - playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.pair()); -- worldserver1.getChunkProvider().tickDistanceManager(); -- worldserver1.getChunkProvider().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { -+ worldserver1.getChunkProvider().markAreaHighPriority(pos, 28, 3); -+ worldserver1.getChunkProvider().getChunkAtAsynchronously(chunkX, chunkZ, true, false).thenApply(chunk -> { - PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pos.pair()); - if (updatingChunk != null) { - return updatingChunk.getEntityTickingFuture(); -@@ -696,6 +696,7 @@ public abstract class PlayerList { - SocketAddress socketaddress = loginlistener.networkManager.getSocketAddress(); - - EntityPlayer entity = new EntityPlayer(this.server, this.server.getWorldServer(World.OVERWORLD), gameprofile, new PlayerInteractManager(this.server.getWorldServer(World.OVERWORLD))); -+ entity.isRealPlayer = true; // Paper - Player player = entity.getBukkitEntity(); - PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress()); - -@@ -902,6 +903,7 @@ public abstract class PlayerList { - // CraftBukkit end - - worldserver1.getChunkProvider().addTicket(TicketType.POST_TELEPORT, new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper -+ entityplayer1.forceCheckHighPriority(); // Player - while (avoidSuffocation && !worldserver1.getCubes(entityplayer1) && entityplayer1.locY() < 256.0D) { - entityplayer1.setPosition(entityplayer1.locX(), entityplayer1.locY() + 1.0D, entityplayer1.locZ()); - } -diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -index 9a88791be443a5b18934e7d752aee6dcdb8aa38f..e41d63596c32eee5f0c04a6f043d576d8021ff1a 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -+++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -@@ -104,6 +104,7 @@ public class ChunkCoordIntPair { - return "[" + this.x + ", " + this.z + "]"; - } - -+ public final BlockPosition asPosition() { return l(); } // Paper - OBFHELPER - public BlockPosition l() { - return new BlockPosition(this.d(), 0, this.e()); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 2d90ecf04f522a4e16f44c905450a61becaa1ed2..6034ef65ee6030948a5b76fa493addb44188ef62 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2541,6 +2541,10 @@ public class CraftWorld implements World { - return future; - } - -+ if (!urgent) { -+ // if not urgent, at least use a slightly boosted priority -+ world.getChunkProvider().markHighPriority(new ChunkCoordIntPair(x, z), 1); -+ } - return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { - net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 935b5668a81db4d19a08b09c61519114532a23d9..0f8d10c2bc7728b58528096fc0686c3aeee623a7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -60,6 +60,7 @@ import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.WorldServer; - import net.minecraft.server.network.PlayerConnection; - import net.minecraft.server.players.WhiteListEntry; -+import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityExperienceOrb; - import net.minecraft.world.entity.EntityLiving; -@@ -72,6 +73,7 @@ import net.minecraft.world.inventory.Container; - import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.item.enchantment.Enchantments; -+import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.entity.TileEntitySign; -@@ -851,6 +853,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - throw new UnsupportedOperationException("Cannot set rotation of players. Consider teleporting instead."); - } - -+ // Paper start -+ @Override -+ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull PlayerTeleportEvent.TeleportCause cause) { -+ ((CraftWorld)loc.getWorld()).getHandle().getChunkProvider().markAreaHighPriority(new ChunkCoordIntPair(MathHelper.floor(loc.getX()) >> 4, MathHelper.floor(loc.getZ()) >> 4), 28, 3); // Paper - load area high priority -+ return super.teleportAsync(loc, cause); -+ } -+ // Paper end -+ - @Override - public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) { - Preconditions.checkArgument(location != null, "location"); diff --git a/Unmapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/Unmapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch deleted file mode 100644 index ee6a2dd544..0000000000 --- a/Unmapped-Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 23 May 2020 17:03:41 -0400 -Subject: [PATCH] Optimize sending packets to nearby locations (sounds/effects) - -Instead of using the entire world or player list, use the distance -maps to only iterate players who are even seeing the chunk the packet -is originating from. - -This will drastically cut down on packet sending cost for worlds with -lots of players in them. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index b4c5915cc68a838259129b8973b3a6a39c1fc963..4c3a2e3cfd60321b3b74d143a32aa5f5d59d7e1e 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1153,16 +1153,40 @@ public abstract class PlayerList { - } - - public void sendPacketNearby(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, double d3, ResourceKey resourcekey, Packet packet) { -- for (int i = 0; i < this.players.size(); ++i) { -- EntityPlayer entityplayer = (EntityPlayer) this.players.get(i); -+ WorldServer world = null; -+ if (entityhuman != null && entityhuman.world instanceof WorldServer) { -+ world = (WorldServer) entityhuman.world; -+ } - -- // CraftBukkit start - Test if player receiving packet can see the source of the packet -- if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { -- continue; -+ // Paper start -+ if (world == null) { -+ world = server.getWorldServer(resourcekey); -+ } -+ PlayerChunkMap chunkMap = world != null ? world.getChunkProvider().playerChunkMap : null; -+ Object[] backingSet; -+ if (chunkMap == null) { -+ // Really shouldn't happen... -+ backingSet = world != null ? world.players.toArray() : players.toArray(); -+ } else { -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.fastFloor(d0) >> 4, MCUtil.fastFloor(d2) >> 4); -+ if (nearbyPlayers == null) { -+ return; - } -+ backingSet = nearbyPlayers.getBackingSet(); -+ } -+ -+ for (Object object : backingSet) { -+ if (!(object instanceof EntityPlayer)) continue; -+ EntityPlayer entityplayer = (EntityPlayer) object; -+ // Paper end -+ -+ // CraftBukkit start - Test if player receiving packet can see the source of the packet -+ //if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { // Paper -+ //continue; // Paper -+ //} // Paper - // CraftBukkit end - -- if (entityplayer != entityhuman && entityplayer.world.getDimensionKey() == resourcekey) { -+ if (entityplayer != entityhuman && entityplayer.world.getDimensionKey() == resourcekey && (!(entityhuman instanceof EntityPlayer) || entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity()))) { // Paper - double d4 = d0 - entityplayer.locX(); - double d5 = d1 - entityplayer.locY(); - double d6 = d2 - entityplayer.locZ(); diff --git a/Unmapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch b/Unmapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch deleted file mode 100644 index 969bc53a1c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 May 2020 23:32:14 -0400 -Subject: [PATCH] Improve Chunk Status Transition Speed - -When a chunk is loaded from disk that has already been generated, -the server has to promote the chunk through the system to reach -it's current desired status level. - -This results in every single status transition going from the main thread -to the world gen threads, only to discover it has no work it actually -needs to do.... and then it returns back to main. - -This back and forth costs a lot of time and can really delay chunk loads -when the server is under high TPS due to their being a lot of time in -between chunk load times, as well as hogs up the chunk threads from doing -actual generation and light work. - -Additionally, the whole task system uses a lot of CPU on the server threads anyways. - -So by optimizing status transitions for status's that are already complete, -we can run them to the desired level while on main thread (where it has -to happen anyways) instead of ever jumping to world gen thread. - -This will improve chunk loading effeciency to be reduced down to the following -scenario / path: - -1) MAIN: Chunk Requested, Load Request sent to ChunkTaskManager / IO Queue -2) IO: Once position in queue comes, submit read IO data and schedule to chunk task thread -3) CHUNK: Once IO is loaded and position in queue comes, deserialize the chunk data, process conversions, submit to main queue -4) MAIN: next Chunk Task process (Mid Tick or End Of Tick), load chunk data into world (POI, main thread tasks) -5) MAIN: process status transitions all the way to LIGHT, light schedules Threaded task -6) SERVER: Light tasks register light enablement for chunk and any lighting needing to be done -7) MAIN: Task returns to main, finish processing to FULL/TICKING status - -Previously would have hopped to SERVER around 12+ times there extra. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index fc79a73c884ceb7e0ce56443c36b135c4e525193..88022e3ccd04f9c041ced68be66a95247c1017e9 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -84,6 +84,13 @@ public class PlayerChunk { - this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); - } - // Paper end - optimise isOutsideOfRange -+ // Paper start - optimize chunk status progression without jumping through thread pool -+ public boolean canAdvanceStatus() { -+ ChunkStatus status = getChunkHolderStatus(); -+ IChunkAccess chunk = getAvailableChunkNow(); -+ return chunk != null && (status == null || chunk.getChunkStatus().isAtLeastStatus(getNextStatus(status))); -+ } -+ // Paper end - - // Paper start - no-tick view distance - public final Chunk getSendingChunk() { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 5bea15ba1ee3d2c8e8d78ab34ba75723164b7117..74146ab6bd172807fb8545c1a29e376b1224e34d 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -795,7 +795,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return either.mapLeft((list) -> { - return (Chunk) list.get(list.size() / 2); - }); -- }, this.executor); -+ }, this.mainInvokingExecutor); // Paper - } - - @Nullable -@@ -1145,7 +1145,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - IChunkAccess ichunkaccess = (IChunkAccess) optional.get(); - - if (ichunkaccess.getChunkStatus().b(chunkstatus)) { -- CompletableFuture completablefuture1; -+ CompletableFuture> completablefuture1; // Paper - - if (chunkstatus == ChunkStatus.LIGHT) { - completablefuture1 = this.b(playerchunk, chunkstatus); -@@ -1161,7 +1161,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return this.b(playerchunk, chunkstatus); - } - } -- }, this.executor); -+ }, this.mainInvokingExecutor).thenComposeAsync(CompletableFuture::completedFuture, this.mainInvokingExecutor); // Paper - optimize chunk status progression without jumping through thread pool - ensure main - } - } - -@@ -1282,6 +1282,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return CompletableFuture.completedFuture(Either.right(playerchunk_failure)); - }); - }, (runnable) -> { -+ // Paper start - optimize chunk status progression without jumping through thread pool -+ if (playerchunk.canAdvanceStatus()) { -+ this.mainInvokingExecutor.execute(runnable); -+ return; -+ } -+ // Paper end - this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); - }); - } diff --git a/Unmapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch b/Unmapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch deleted file mode 100644 index b6b2585f20..0000000000 --- a/Unmapped-Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Fri, 5 Jun 2020 20:02:04 -0500 -Subject: [PATCH] Fix villager trading demand - MC-163962 - -Prevent demand from going negative and tending to negative infinity - -diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -index d840c657a6a992c86364a5f4536da0b217515c53..9e2fe0d5e6d4ea1f4c9cea96b755ddcd1e3c9009 100644 ---- a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -+++ b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -@@ -109,7 +109,7 @@ public class MerchantRecipe { - } - - public void e() { -- this.demand = this.demand + this.uses - (this.maxUses - this.uses); -+ this.demand = Math.max(0, this.demand + this.uses - (this.maxUses - this.uses)); // Paper - } - - public ItemStack f() { diff --git a/Unmapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch b/Unmapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch deleted file mode 100644 index 28c169e754..0000000000 --- a/Unmapped-Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sun, 7 Jun 2020 21:43:42 +0100 -Subject: [PATCH] Maps shouldn't load chunks - -Previously maps would load all chunks in a certain radius depending on - their scale when trying to update their content. This would result in - main thread chunk loads when they weren't really necessary, especially - on low view distances or "slow" async chunk loads after teleports or - other prioritisation. - - This changes it to only try to render already loaded chunks based on - the assumption that the chunks around the player will get loaded - eventually anyways and that maps will get checked for update every - five ticks that movement occur in anyways. - -diff --git a/src/main/java/net/minecraft/world/item/ItemWorldMap.java b/src/main/java/net/minecraft/world/item/ItemWorldMap.java -index b18149cf048e78fefc019b50ed8f20ff8b609f5c..a1945e9ac1dd8961c5758a22bef3908d3adf0704 100644 ---- a/src/main/java/net/minecraft/world/item/ItemWorldMap.java -+++ b/src/main/java/net/minecraft/world/item/ItemWorldMap.java -@@ -120,9 +120,9 @@ public class ItemWorldMap extends ItemWorldMapBase { - int k2 = (j / i + k1 - 64) * i; - int l2 = (k / i + l1 - 64) * i; - Multiset multiset = LinkedHashMultiset.create(); -- Chunk chunk = world.getChunkAtWorldCoords(new BlockPosition(k2, 0, l2)); -+ Chunk chunk = world.getChunkIfLoaded(new BlockPosition(k2, 0, l2)); // Paper - Maps shouldn't load chunks - -- if (!chunk.isEmpty()) { -+ if (chunk != null && !chunk.isEmpty()) { // Paper - Maps shouldn't load chunks - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - int i3 = k2 & 15; - int j3 = l2 & 15; diff --git a/Unmapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/Unmapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch deleted file mode 100644 index c789a5a683..0000000000 --- a/Unmapped-Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 7 Jun 2020 19:25:13 -0400 -Subject: [PATCH] Use seed based lookup for Treasure Maps - Fixes lag from - carto/sunken maps - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 524bbf9bdf5fb0e1e4ff217ae3291fdbe742437e..a0670bdd858f59ee5719580625c9f25235e23fc4 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -421,8 +421,8 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.worldDataServer.setThundering(flag1); - } - -- @Override -- public BiomeBase a(int i, int j, int k) { -+ public BiomeBase getBiomeBySeed(int i, int j, int k) { return a(i, j, k); } // Paper - OBFHELPER -+ @Override public BiomeBase a(int i, int j, int k) { - return this.getChunkProvider().getChunkGenerator().getWorldChunkManager().getBiome(i, j, k); - } - -diff --git a/src/main/java/net/minecraft/world/item/ItemWorldMap.java b/src/main/java/net/minecraft/world/item/ItemWorldMap.java -index a1945e9ac1dd8961c5758a22bef3908d3adf0704..3aa0f19d4a924d40005a38bb95a08d4a109c5b2e 100644 ---- a/src/main/java/net/minecraft/world/item/ItemWorldMap.java -+++ b/src/main/java/net/minecraft/world/item/ItemWorldMap.java -@@ -253,7 +253,7 @@ public class ItemWorldMap extends ItemWorldMapBase { - - for (l = 0; l < 128 * i; ++l) { - for (i1 = 0; i1 < 128 * i; ++i1) { -- abiomebase[l * 128 * i + i1] = worldserver.getBiome(new BlockPosition((j / i - 64) * i + i1, 0, (k / i - 64) * i + l)); -+ abiomebase[l * 128 * i + i1] = worldserver.getBiomeBySeed((j / i - 64) * i + i1, 0, (k / i - 64) * i + l); // Paper - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch b/Unmapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch deleted file mode 100644 index 3e547b0e89..0000000000 --- a/Unmapped-Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 4 Jun 2020 02:24:49 -0400 -Subject: [PATCH] Optimize Bit Operations by inlining - -Inline bit operations and reduce instruction count to make these hot -operations faster - -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 1fb931d4c0720a5e496030e25c865771aea3ec70..eb67af795dd716d9f92ac32843accc1ec4efd647 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -31,14 +31,16 @@ public class BlockPosition extends BaseBlockPosition { - }).stable(); - private static final Logger LOGGER = LogManager.getLogger(); - public static final BlockPosition ZERO = new BlockPosition(0, 0, 0); -- private static final int f = 1 + MathHelper.f(MathHelper.c(30000000)); -- private static final int g = BlockPosition.f; -- private static final int h = 64 - BlockPosition.f - BlockPosition.g; -- private static final long i = (1L << BlockPosition.f) - 1L; -- private static final long j = (1L << BlockPosition.h) - 1L; -- private static final long k = (1L << BlockPosition.g) - 1L; -- private static final int l = BlockPosition.h; -- private static final int m = BlockPosition.h + BlockPosition.g; -+ // Paper start - static constants -+ private static final int f = 26; -+ private static final int g = 26; -+ private static final int h = 12; -+ private static final long i = 67108863; -+ private static final long j = 4095; -+ private static final long k = 67108863; -+ private static final int l = 12; -+ private static final int m = 38; -+ // Paper end - - public BlockPosition(int i, int j, int k) { - super(i, j, k); -@@ -60,28 +62,29 @@ public class BlockPosition extends BaseBlockPosition { - this(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } - -+ public static long getAdjacent(int baseX, int baseY, int baseZ, EnumDirection enumdirection) { return asLong(baseX + enumdirection.getAdjacentX(), baseY + enumdirection.getAdjacentY(), baseZ + enumdirection.getAdjacentZ()); } // Paper - public static long a(long i, EnumDirection enumdirection) { - return a(i, enumdirection.getAdjacentX(), enumdirection.getAdjacentY(), enumdirection.getAdjacentZ()); - } - - public static long a(long i, int j, int k, int l) { -- return a(b(i) + j, c(i) + k, d(i) + l); -+ return a((int) (i >> 38) + j, (int) ((i << 52) >> 52) + k, (int) ((i << 26) >> 38) + l); // Paper - simplify/inline - } - - public static int b(long i) { -- return (int) (i << 64 - BlockPosition.m - BlockPosition.f >> 64 - BlockPosition.f); -+ return (int) (i >> 38); // Paper - simplify/inline - } - - public static int c(long i) { -- return (int) (i << 64 - BlockPosition.h >> 64 - BlockPosition.h); -+ return (int) ((i << 52) >> 52); // Paper - simplify/inline - } - - public static int d(long i) { -- return (int) (i << 64 - BlockPosition.l - BlockPosition.g >> 64 - BlockPosition.g); -+ return (int) ((i << 26) >> 38); // Paper - simplify/inline - } - - public static BlockPosition fromLong(long i) { -- return new BlockPosition(b(i), c(i), d(i)); -+ return new BlockPosition((int) (i >> 38), (int) ((i << 52) >> 52), (int) ((i << 26) >> 38)); // Paper - simplify/inline - } - - public long asLong() { -@@ -90,12 +93,7 @@ public class BlockPosition extends BaseBlockPosition { - - public static long asLong(int x, int y, int z) { return a(x, y, z); } // Paper - OBFHELPER - public static long a(int i, int j, int k) { -- long l = 0L; -- -- l |= ((long) i & BlockPosition.i) << BlockPosition.m; -- l |= ((long) j & BlockPosition.j) << 0; -- l |= ((long) k & BlockPosition.k) << BlockPosition.l; -- return l; -+ return (((long) i & (long) 67108863) << 38) | (((long) j & (long) 4095)) | (((long) k & (long) 67108863) << 12); // Paper - inline constants and simplify - } - - public static long f(long i) { -diff --git a/src/main/java/net/minecraft/core/SectionPosition.java b/src/main/java/net/minecraft/core/SectionPosition.java -index 97126ae5a43bb7acb04a1ab14fb7f364c8c2675f..7d9a16eb81288b74425319c60525f57c98ad3b69 100644 ---- a/src/main/java/net/minecraft/core/SectionPosition.java -+++ b/src/main/java/net/minecraft/core/SectionPosition.java -@@ -19,7 +19,7 @@ public class SectionPosition extends BaseBlockPosition { - } - - public static SectionPosition a(BlockPosition blockposition) { -- return new SectionPosition(a(blockposition.getX()), a(blockposition.getY()), a(blockposition.getZ())); -+ return new SectionPosition(blockposition.getX() >> 4, blockposition.getY() >> 4, blockposition.getZ() >> 4); // Paper - } - - public static SectionPosition a(ChunkCoordIntPair chunkcoordintpair, int i) { -@@ -31,15 +31,23 @@ public class SectionPosition extends BaseBlockPosition { - } - - public static SectionPosition a(long i) { -- return new SectionPosition(b(i), c(i), d(i)); -+ return new SectionPosition((int) (i >> 42), (int) (i << 44 >> 44), (int) (i << 22 >> 42)); // Paper - } - - public static long a(long i, EnumDirection enumdirection) { - return a(i, enumdirection.getAdjacentX(), enumdirection.getAdjacentY(), enumdirection.getAdjacentZ()); - } - -+ // Paper start -+ public static long getAdjacentFromBlockPos(int x, int y, int z, EnumDirection enumdirection) { -+ return (((long) ((x >> 4) + enumdirection.getAdjacentX()) & 4194303L) << 42) | (((long) ((y >> 4) + enumdirection.getAdjacentY()) & 1048575L)) | (((long) ((z >> 4) + enumdirection.getAdjacentZ()) & 4194303L) << 20); -+ } -+ public static long getAdjacentFromSectionPos(int x, int y, int z, EnumDirection enumdirection) { -+ return (((long) (x + enumdirection.getAdjacentX()) & 4194303L) << 42) | (((long) ((y) + enumdirection.getAdjacentY()) & 1048575L)) | (((long) (z + enumdirection.getAdjacentZ()) & 4194303L) << 20); -+ } -+ // Paper end - public static long a(long i, int j, int k, int l) { -- return b(b(i) + j, c(i) + k, d(i) + l); -+ return (((long) ((int) (i >> 42) + j) & 4194303L) << 42) | (((long) ((int) (i << 44 >> 44) + k) & 1048575L)) | (((long) ((int) (i << 22 >> 42) + l) & 4194303L) << 20); // Simplify to reduce instruction count - } - - public static int a(int i) { -@@ -51,11 +59,7 @@ public class SectionPosition extends BaseBlockPosition { - } - - public static short b(BlockPosition blockposition) { -- int i = b(blockposition.getX()); -- int j = b(blockposition.getY()); -- int k = b(blockposition.getZ()); -- -- return (short) (i << 8 | k << 4 | j << 0); -+ return (short) ((blockposition.getX() & 15) << 8 | (blockposition.getZ() & 15) << 4 | blockposition.getY() & 15); // Paper - simplify/inline - } - - public static int a(short short0) { -@@ -114,16 +118,16 @@ public class SectionPosition extends BaseBlockPosition { - return this.getZ(); - } - -- public int d() { -- return this.a() << 4; -+ public final int d() { // Paper -+ return this.getX() << 4; // Paper - } - -- public int e() { -- return this.b() << 4; -+ public final int e() { // Paper -+ return this.getY() << 4; // Paper - } - -- public int f() { -- return this.c() << 4; -+ public final int f() { // Paper -+ return this.getZ() << 4; // Paper - } - - public int g() { -@@ -138,8 +142,10 @@ public class SectionPosition extends BaseBlockPosition { - return (this.c() << 4) + 15; - } - -+ public static long blockToSection(long i) { return e(i); } // Paper - OBFHELPER - public static long e(long i) { -- return b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); -+ // b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); -+ return (((long) (int) (i >> 42) & 4194303L) << 42) | (((long) (int) ((i << 52) >> 56) & 1048575L)) | (((long) (int) ((i << 26) >> 42) & 4194303L) << 20); // Simplify to reduce instruction count - } - - public static long f(long i) { -@@ -160,17 +166,18 @@ public class SectionPosition extends BaseBlockPosition { - return new ChunkCoordIntPair(this.a(), this.c()); - } - -+ // Paper start -+ public static long blockPosAsSectionLong(int i, int j, int k) { -+ return (((long) (i >> 4) & 4194303L) << 42) | (((long) (j >> 4) & 1048575L)) | (((long) (k >> 4) & 4194303L) << 20); -+ } -+ // Paper end -+ public static long asLong(int i, int j, int k) { return b(i, j, k); } // Paper - OBFHELPER - public static long b(int i, int j, int k) { -- long l = 0L; -- -- l |= ((long) i & 4194303L) << 42; -- l |= ((long) j & 1048575L) << 0; -- l |= ((long) k & 4194303L) << 20; -- return l; -+ return (((long) i & 4194303L) << 42) | (((long) j & 1048575L)) | (((long) k & 4194303L) << 20); // Paper - Simplify to reduce instruction count - } - - public long s() { -- return b(this.a(), this.b(), this.c()); -+ return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count - } - - public Stream t() { -@@ -178,18 +185,11 @@ public class SectionPosition extends BaseBlockPosition { - } - - public static Stream a(SectionPosition sectionposition, int i) { -- int j = sectionposition.a(); -- int k = sectionposition.b(); -- int l = sectionposition.c(); -- -- return a(j - i, k - i, l - i, j + i, k + i, l + i); -+ return a(sectionposition.getX() - i, sectionposition.getY() - i, sectionposition.getZ() - i, sectionposition.getX() + i, sectionposition.getY() + i, sectionposition.getZ() + i); // Paper - simplify/inline - } - - public static Stream b(ChunkCoordIntPair chunkcoordintpair, int i) { -- int j = chunkcoordintpair.x; -- int k = chunkcoordintpair.z; -- -- return a(j - i, 0, k - i, j + i, 15, k + i); -+ return a(chunkcoordintpair.x - i, 0, chunkcoordintpair.z - i, chunkcoordintpair.x + i, 15, chunkcoordintpair.z + i); // Paper - simplify/inline - } - - public static Stream a(final int i, final int j, final int k, final int l, final int i1, final int j1) { diff --git a/Unmapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch b/Unmapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch deleted file mode 100644 index 8e197795b4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0491-Optimize-Light-Engine.patch +++ /dev/null @@ -1,1433 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 4 Jun 2020 22:43:29 -0400 -Subject: [PATCH] Optimize Light Engine - -Massive update to light to improve performance and chunk loading/generation. - -1) Massive bit packing/unpacking optimizations and inlining. - A lot of performance has to do with constant packing and unpacking of bits. - We now inline a most bit operations, and re-use base x/y/z bits in many places. - This helps with cpu level processing to just do all the math at once instead - of having to jump in and out of function calls. - - This much logic also is likely over the JVM Inline limit for JIT too. -2) Applied a few of JellySquid's Phosphor mod optimizations such as - - ensuring we don't notify neighbor chunks when neighbor chunk doesn't need to be notified - - reduce hasLight checks in initializing light, and prob some more, they are tagged JellySquid where phosphor influence was used. -3) Optimize hot path accesses to getting updating chunk to have less branching -4) Optimize getBlock accesses to have less branching, and less unpacking -5) Have a separate urgent bucket for chunk light tasks. These tasks will always cut in line over non blocking light tasks. -6) Retain chunk priority while light tasks are enqueued. So if a task comes in at high priority but the queue is full - of tasks already at a lower priority, before the task was simply added to the end. Now it can cut in line to the front. - this applies for both urgent and non urgent tasks. -7) Buffer non urgent tasks even if queueUpdate is called multiple times to improve efficiency. -8) Fix NPE risk that crashes server in getting nibble data - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 17a4970cf78f3ee3a62a76a3f9e28251db17bac2..6770307d69c6b3934bfa804fd713cade22f0fb5c 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -1072,7 +1072,7 @@ public class ChunkProviderServer extends IChunkProvider { - if (ChunkProviderServer.this.tickDistanceManager()) { - return true; - } else { -- ChunkProviderServer.this.lightEngine.queueUpdate(); -+ ChunkProviderServer.this.lightEngine.queueUpdate(); // Paper - not needed - return super.executeNext() || execChunkTask; // Paper - } - } finally { -diff --git a/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java b/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java -index c8bb040e7ed848877ec9c2f9b30dcda137cadf35..4ee7070364a8989eece4fa4237b529926821f9c9 100644 ---- a/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java -+++ b/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java -@@ -16,14 +16,20 @@ public abstract class LightEngineGraphSection extends LightEngineGraph { - - @Override - protected void a(long i, int j, boolean flag) { -+ // Paper start -+ int x = (int) (i >> 42); -+ int y = (int) (i << 44 >> 44); -+ int z = (int) (i << 22 >> 42); -+ // Paper end - for (int k = -1; k <= 1; ++k) { - for (int l = -1; l <= 1; ++l) { - for (int i1 = -1; i1 <= 1; ++i1) { -- long j1 = SectionPosition.a(i, k, l, i1); -+ if (k == 0 && l == 0 && i1 == 0) continue; // Paper -+ long j1 = (((long) (x + k) & 4194303L) << 42) | (((long) (y + l) & 1048575L)) | (((long) (z + i1) & 4194303L) << 20); // Paper - -- if (j1 != i) { -+ //if (j1 != i) { // Paper - checked above - this.b(i, j1, j, flag); -- } -+ //} // Paper - } - } - } -@@ -34,10 +40,15 @@ public abstract class LightEngineGraphSection extends LightEngineGraph { - protected int a(long i, long j, int k) { - int l = k; - -+ // Paper start -+ int x = (int) (i >> 42); -+ int y = (int) (i << 44 >> 44); -+ int z = (int) (i << 22 >> 42); -+ // Paper end - for (int i1 = -1; i1 <= 1; ++i1) { - for (int j1 = -1; j1 <= 1; ++j1) { - for (int k1 = -1; k1 <= 1; ++k1) { -- long l1 = SectionPosition.a(i, i1, j1, k1); -+ long l1 = (((long) (x + i1) & 4194303L) << 42) | (((long) (y + j1) & 1048575L)) | (((long) (z + k1) & 4194303L) << 20); // Paper - - if (l1 == i) { - l1 = Long.MAX_VALUE; -diff --git a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -index e066848127cb9a42e8c39422691cc65132cac6bb..0b80569648c1df01aab52d0b8d47028cda925d86 100644 ---- a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -+++ b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -@@ -1,6 +1,7 @@ - package net.minecraft.server.level; - - import com.mojang.datafixers.util.Pair; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; // Paper - import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import it.unimi.dsi.fastutil.objects.ObjectList; - import it.unimi.dsi.fastutil.objects.ObjectListIterator; -@@ -16,6 +17,7 @@ import net.minecraft.util.thread.ThreadedMailbox; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumSkyBlock; - import net.minecraft.world.level.chunk.ChunkSection; -+import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.IChunkAccess; - import net.minecraft.world.level.chunk.ILightAccess; - import net.minecraft.world.level.chunk.NibbleArray; -@@ -27,15 +29,149 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - - private static final Logger LOGGER = LogManager.getLogger(); - private final ThreadedMailbox b; -- private final ObjectList> c = new ObjectArrayList(); -- private final PlayerChunkMap d; -+ // Paper start -+ private static final int MAX_PRIORITIES = PlayerChunkMap.GOLDEN_TICKET + 2; -+ -+ private boolean isChunkLightStatus(long pair) { -+ PlayerChunk playerChunk = playerChunkMap.getVisibleChunk(pair); -+ if (playerChunk == null) { -+ return false; -+ } -+ ChunkStatus status = PlayerChunk.getChunkStatus(playerChunk.getTicketLevel()); -+ return status != null && status.isAtLeastStatus(ChunkStatus.LIGHT); -+ } -+ -+ static class ChunkLightQueue { -+ public boolean shouldFastUpdate; -+ java.util.ArrayDeque pre = new java.util.ArrayDeque(); -+ java.util.ArrayDeque post = new java.util.ArrayDeque(); -+ -+ ChunkLightQueue(long chunk) {} -+ } -+ -+ static class PendingLightTask { -+ long chunkId; -+ IntSupplier priority; -+ Runnable pre; -+ Runnable post; -+ boolean fastUpdate; -+ -+ public PendingLightTask(long chunkId, IntSupplier priority, Runnable pre, Runnable post, boolean fastUpdate) { -+ this.chunkId = chunkId; -+ this.priority = priority; -+ this.pre = pre; -+ this.post = post; -+ this.fastUpdate = fastUpdate; -+ } -+ } -+ -+ -+ // Retain the chunks priority level for queued light tasks -+ class LightQueue { -+ private int size = 0; -+ private final Long2ObjectLinkedOpenHashMap[] buckets = new Long2ObjectLinkedOpenHashMap[MAX_PRIORITIES]; -+ private final java.util.concurrent.ConcurrentLinkedQueue pendingTasks = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private final java.util.concurrent.ConcurrentLinkedQueue priorityChanges = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ -+ private LightQueue() { -+ for (int i = 0; i < buckets.length; i++) { -+ buckets[i] = new Long2ObjectLinkedOpenHashMap<>(); -+ } -+ } -+ -+ public void changePriority(long pair, int currentPriority, int priority) { -+ this.priorityChanges.add(() -> { -+ ChunkLightQueue remove = this.buckets[currentPriority].remove(pair); -+ if (remove != null) { -+ ChunkLightQueue existing = this.buckets[Math.max(1, priority)].put(pair, remove); -+ if (existing != null) { -+ remove.pre.addAll(existing.pre); -+ remove.post.addAll(existing.post); -+ } -+ } -+ }); -+ } -+ -+ public final void addChunk(long chunkId, IntSupplier priority, Runnable pre, Runnable post) { -+ pendingTasks.add(new PendingLightTask(chunkId, priority, pre, post, true)); -+ queueUpdate(); -+ } -+ -+ public final void add(long chunkId, IntSupplier priority, LightEngineThreaded.Update type, Runnable run) { -+ pendingTasks.add(new PendingLightTask(chunkId, priority, type == Update.PRE_UPDATE ? run : null, type == Update.POST_UPDATE ? run : null, false)); -+ } -+ public final void add(PendingLightTask update) { -+ int priority = update.priority.getAsInt(); -+ ChunkLightQueue lightQueue = this.buckets[priority].computeIfAbsent(update.chunkId, ChunkLightQueue::new); -+ -+ if (update.pre != null) { -+ this.size++; -+ lightQueue.pre.add(update.pre); -+ } -+ if (update.post != null) { -+ this.size++; -+ lightQueue.post.add(update.post); -+ } -+ if (update.fastUpdate) { -+ lightQueue.shouldFastUpdate = true; -+ } -+ } -+ -+ public final boolean isEmpty() { -+ return this.size == 0 && this.pendingTasks.isEmpty(); -+ } -+ -+ public final int size() { -+ return this.size; -+ } -+ -+ public boolean poll(java.util.List pre, java.util.List post) { -+ PendingLightTask pending; -+ while ((pending = pendingTasks.poll()) != null) { -+ add(pending); -+ } -+ Runnable run; -+ while ((run = priorityChanges.poll()) != null) { -+ run.run(); -+ } -+ boolean hasWork = false; -+ Long2ObjectLinkedOpenHashMap[] buckets = this.buckets; -+ int priority = 0; -+ while (priority < MAX_PRIORITIES && !isEmpty()) { -+ Long2ObjectLinkedOpenHashMap bucket = buckets[priority]; -+ if (bucket.isEmpty()) { -+ priority++; -+ if (hasWork) { -+ return true; -+ } else { -+ continue; -+ } -+ } -+ ChunkLightQueue queue = bucket.removeFirst(); -+ this.size -= queue.pre.size() + queue.post.size(); -+ pre.addAll(queue.pre); -+ post.addAll(queue.post); -+ queue.pre.clear(); -+ queue.post.clear(); -+ hasWork = true; -+ if (queue.shouldFastUpdate) { -+ return true; -+ } -+ } -+ return hasWork; -+ } -+ } -+ -+ final LightQueue queue = new LightQueue(); -+ // Paper end -+ private final PlayerChunkMap d; private final PlayerChunkMap playerChunkMap; // Paper - private final Mailbox> e; - private volatile int f = 5; - private final AtomicBoolean g = new AtomicBoolean(); - - public LightEngineThreaded(ILightAccess ilightaccess, PlayerChunkMap playerchunkmap, boolean flag, ThreadedMailbox threadedmailbox, Mailbox> mailbox) { - super(ilightaccess, true, flag); -- this.d = playerchunkmap; -+ this.d = playerchunkmap; this.playerChunkMap = d; // Paper - this.e = mailbox; - this.b = threadedmailbox; - } -@@ -122,13 +258,9 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - } - - private void a(int i, int j, IntSupplier intsupplier, LightEngineThreaded.Update lightenginethreaded_update, Runnable runnable) { -- this.e.a(ChunkTaskQueueSorter.a(() -> { -- this.c.add(Pair.of(lightenginethreaded_update, runnable)); -- if (this.c.size() >= this.f) { -- this.b(); -- } -- -- }, ChunkCoordIntPair.pair(i, j), intsupplier)); -+ // Paper start - replace method -+ this.queue.add(ChunkCoordIntPair.pair(i, j), intsupplier, lightenginethreaded_update, runnable); -+ // Paper end - } - - @Override -@@ -145,8 +277,19 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - public CompletableFuture a(IChunkAccess ichunkaccess, boolean flag) { - ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); - -- ichunkaccess.b(false); -- this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { -+ // Paper start -+ //ichunkaccess.b(false); // Don't need to disable this -+ long pair = chunkcoordintpair.pair(); -+ CompletableFuture future = new CompletableFuture<>(); -+ IntSupplier prioritySupplier = playerChunkMap.getPrioritySupplier(pair); -+ boolean[] skippedPre = {false}; -+ this.queue.addChunk(pair, prioritySupplier, SystemUtils.a(() -> { -+ if (!isChunkLightStatus(pair)) { -+ future.complete(ichunkaccess); -+ skippedPre[0] = true; -+ return; -+ } -+ // Paper end - ChunkSection[] achunksection = ichunkaccess.getSections(); - - for (int i = 0; i < 16; ++i) { -@@ -164,55 +307,48 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - }); - } - -- this.d.c(chunkcoordintpair); -+ // this.d.c(chunkcoordintpair); // Paper - move into post task below - }, () -> { - return "lightChunk " + chunkcoordintpair + " " + flag; -- })); -- return CompletableFuture.supplyAsync(() -> { -+ // Paper start - merge the 2 together -+ }), () -> { -+ this.d.c(chunkcoordintpair); // Paper - release light tickets as post task to ensure they stay loaded until fully done -+ if (skippedPre[0]) return; // Paper - future's already complete - ichunkaccess.b(true); - super.b(chunkcoordintpair, false); -- return ichunkaccess; -- }, (runnable) -> { -- this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.POST_UPDATE, runnable); -+ // Paper start -+ future.complete(ichunkaccess); - }); -+ return future; -+ // Paper end - } - - public void queueUpdate() { -- if ((!this.c.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { -+ if ((!this.queue.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { // Paper - this.b.a((() -> { // Paper - decompile error - this.b(); - this.g.set(false); -+ queueUpdate(); // Paper - if we still have work to do, do it! - })); - } - - } - -+ // Paper start - replace impl -+ private final java.util.List pre = new java.util.ArrayList<>(); -+ private final java.util.List post = new java.util.ArrayList<>(); - private void b() { -- int i = Math.min(this.c.size(), this.f); -- ObjectListIterator> objectlistiterator = this.c.iterator(); -- -- Pair pair; -- int j; -- -- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { -- pair = (Pair) objectlistiterator.next(); -- if (pair.getFirst() == LightEngineThreaded.Update.PRE_UPDATE) { -- ((Runnable) pair.getSecond()).run(); -- } -+ if (queue.poll(pre, post)) { -+ pre.forEach(Runnable::run); -+ pre.clear(); -+ super.a(Integer.MAX_VALUE, true, true); -+ post.forEach(Runnable::run); -+ post.clear(); -+ } else { -+ // might have level updates to go still -+ super.a(Integer.MAX_VALUE, true, true); - } -- -- objectlistiterator.back(j); -- super.a(Integer.MAX_VALUE, true, true); -- -- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { -- pair = (Pair) objectlistiterator.next(); -- if (pair.getFirst() == LightEngineThreaded.Update.POST_UPDATE) { -- ((Runnable) pair.getSecond()).run(); -- } -- -- objectlistiterator.remove(); -- } -- -+ // Paper end - } - - public void a(int i) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 88022e3ccd04f9c041ced68be66a95247c1017e9..d6a5a0b17308913a5efd97cd27fabd0825ef68c6 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -754,6 +754,7 @@ public class PlayerChunk { - ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; - } - chunkMap.world.asyncChunkTaskManager.raisePriority(location.x, location.z, ioPriority); -+ chunkMap.world.getChunkProvider().getLightEngine().queue.changePriority(location.pair(), getCurrentPriority(), priority); - } - if (getCurrentPriority() != priority) { - this.u.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 74146ab6bd172807fb8545c1a29e376b1224e34d..169fa174f86f8a8dc42d3b9c4954a39d0a738c06 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -99,6 +99,7 @@ import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureManager; - import net.minecraft.world.level.storage.Convertable; -+import net.minecraft.world.level.storage.WorldDataServer; - import net.minecraft.world.level.storage.WorldPersistentData; - import net.minecraft.world.phys.Vec3D; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper -@@ -331,6 +332,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - // Paper end - -+ private final java.util.concurrent.ExecutorService lightThread; - public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag); - //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning -@@ -362,7 +364,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - Mailbox mailbox = Mailbox.a("main", iasynctaskhandler::a); - - this.worldLoadListener = worldloadlistener; -- ThreadedMailbox lightthreaded; ThreadedMailbox threadedmailbox1 = lightthreaded = ThreadedMailbox.a(executor, "light"); // Paper -+ // Paper start - use light thread -+ ThreadedMailbox lightthreaded; ThreadedMailbox threadedmailbox1 = lightthreaded = ThreadedMailbox.a(lightThread = java.util.concurrent.Executors.newSingleThreadExecutor(r -> { -+ Thread thread = new Thread(r); -+ thread.setName(((WorldDataServer)world.getWorldData()).getName() + " - Light"); -+ thread.setDaemon(true); -+ thread.setPriority(Thread.NORM_PRIORITY+1); -+ return thread; -+ }), "light"); -+ // Paper end - - this.p = new ChunkTaskQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE); - this.mailboxWorldGen = this.p.a(threadedmailbox, false); -@@ -708,6 +718,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper end - } - -+ protected final IntSupplier getPrioritySupplier(long i) { return c(i); } // Paper - OBFHELPER - protected IntSupplier c(long i) { - return () -> { - PlayerChunk playerchunk = this.getVisibleChunk(i); -@@ -835,6 +846,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - @Override - public void close() throws IOException { - try { -+ this.lightThread.shutdown(); // Paper - this.p.close(); - this.world.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line - this.m.close(); -diff --git a/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java b/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java -index 2efca1fe92b2e93dcbf5337eea8855b1b2b9a564..72bfda620f073fd3c3e4c43d78583386dadf95e6 100644 ---- a/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java -+++ b/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java -@@ -110,7 +110,8 @@ public class ThreadedMailbox implements Mailbox, AutoCloseable, Runnable { - - } - -- @Override -+ -+ public final void queue(T t0) { a(t0); } @Override // Paper - OBFHELPER - public void a(T t0) { - this.a.a(t0); - this.f(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -index b82420e9a5d42a4383d24921614fe613c640edb9..0fec15e141051863dbf51a2b3e1ace5028cd2fc1 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -+++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -@@ -11,6 +11,13 @@ import net.minecraft.server.MCUtil; - public class NibbleArray { - - // Paper start -+ public static final NibbleArray EMPTY_NIBBLE_ARRAY = new NibbleArray() { -+ @Override -+ public byte[] asBytes() { -+ throw new IllegalStateException(); -+ } -+ }; -+ public long lightCacheKey = Long.MIN_VALUE; - public static byte[] EMPTY_NIBBLE = new byte[2048]; - private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072); - private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8)); -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -index f6198069e3ca421b4f551939263c7cf8bd5b754e..29e98864209c51368a91fa9e530c33cbf9830b51 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -@@ -23,9 +23,11 @@ public final class LightEngineBlock extends LightEngineLayer> 38); -+ int k = (int) ((i << 52) >> 52); -+ int l = (int) ((i << 26) >> 38); -+ // Paper end - IBlockAccess iblockaccess = this.a.c(j >> 4, l >> 4); - - return iblockaccess != null ? iblockaccess.g(this.f.d(j, k, l)) : 0; -@@ -40,25 +42,33 @@ public final class LightEngineBlock extends LightEngineLayer= 15) { - return k; - } else { -- int l = Integer.signum(BlockPosition.b(j) - BlockPosition.b(i)); -- int i1 = Integer.signum(BlockPosition.c(j) - BlockPosition.c(i)); -- int j1 = Integer.signum(BlockPosition.d(j) - BlockPosition.d(i)); -+ // Paper start - reuse math - credit to JellySquid for idea -+ int jx = (int) (j >> 38); -+ int jy = (int) ((j << 52) >> 52); -+ int jz = (int) ((j << 26) >> 38); -+ int ix = (int) (i >> 38); -+ int iy = (int) ((i << 52) >> 52); -+ int iz = (int) ((i << 26) >> 38); -+ int l = Integer.signum(jx - ix); -+ int i1 = Integer.signum(jy - iy); -+ int j1 = Integer.signum(jz - iz); -+ // Paper end - EnumDirection enumdirection = EnumDirection.a(l, i1, j1); - - if (enumdirection == null) { - return 15; - } else { - //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded -- IBlockData iblockdata = this.a(j, mutableint); -- -- if (mutableint.getValue() >= 15) { -+ IBlockData iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); // Paper -+ int blockedLight = mutableint.getValue(); // Paper -+ if (blockedLight >= 15) { // Paper - return 15; - } else { -- IBlockData iblockdata1 = this.a(i, (MutableInt) null); -+ IBlockData iblockdata1 = this.getBlockOptimized(ix, iy, iz); // Paper - VoxelShape voxelshape = this.a(iblockdata1, i, enumdirection); - VoxelShape voxelshape1 = this.a(iblockdata, j, enumdirection.opposite()); - -- return VoxelShapes.b(voxelshape, voxelshape1) ? 15 : k + Math.max(1, mutableint.getValue()); -+ return VoxelShapes.b(voxelshape, voxelshape1) ? 15 : k + Math.max(1, blockedLight); // Paper - } - } - } -@@ -66,14 +76,19 @@ public final class LightEngineBlock extends LightEngineLayer> 38); -+ int y = (int) ((i << 52) >> 52); -+ int z = (int) ((i << 26) >> 38); -+ long k = SectionPosition.blockPosAsSectionLong(x, y, z); -+ // Paper end - EnumDirection[] aenumdirection = LightEngineBlock.e; - int l = aenumdirection.length; - - for (int i1 = 0; i1 < l; ++i1) { - EnumDirection enumdirection = aenumdirection[i1]; -- long j1 = BlockPosition.a(i, enumdirection); -- long k1 = SectionPosition.e(j1); -+ long j1 = BlockPosition.getAdjacent(x, y, z, enumdirection); // Paper -+ long k1 = SectionPosition.blockToSection(j1); // Paper - - if (k == k1 || ((LightEngineStorageBlock) this.c).g(k1)) { - this.b(i, j1, j, flag); -@@ -98,27 +113,37 @@ public final class LightEngineBlock extends LightEngineLayer> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long j1 = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); -+ NibbleArray nibblearray = this.c.updating.getUpdatingOptimized(j1); -+ // Paper end - EnumDirection[] aenumdirection = LightEngineBlock.e; - int k1 = aenumdirection.length; - - for (int l1 = 0; l1 < k1; ++l1) { - EnumDirection enumdirection = aenumdirection[l1]; -- long i2 = BlockPosition.a(i, enumdirection); -+ // Paper start -+ int newX = baseX + enumdirection.getAdjacentX(); -+ int newY = baseY + enumdirection.getAdjacentY(); -+ int newZ = baseZ + enumdirection.getAdjacentZ(); -+ long i2 = BlockPosition.asLong(newX, newY, newZ); - - if (i2 != j) { -- long j2 = SectionPosition.e(i2); -+ long j2 = SectionPosition.blockPosAsSectionLong(newX, newY, newZ); -+ // Paper end - NibbleArray nibblearray1; - - if (j1 == j2) { - nibblearray1 = nibblearray; - } else { -- nibblearray1 = ((LightEngineStorageBlock) this.c).a(j2, true); -+ nibblearray1 = ((LightEngineStorageBlock) this.c).updating.getUpdatingOptimized(j2); // Paper - } - - if (nibblearray1 != null) { -- int k2 = this.b(i2, i, this.a(nibblearray1, i2)); -+ int k2 = this.b(i2, i, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper - - if (l > k2) { - l = k2; -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java -index 944a8c295ff9df0d96800ddc4f6763598cf61d0d..64dad8ed7c16011d9cb3e9d22ac6f892c638e3b2 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java -@@ -10,6 +10,7 @@ import net.minecraft.world.level.EnumSkyBlock; - import net.minecraft.world.level.IBlockAccess; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.IChunkAccess; - import net.minecraft.world.level.chunk.ILightAccess; - import net.minecraft.world.level.chunk.NibbleArray; - import net.minecraft.world.phys.shapes.VoxelShape; -@@ -23,10 +24,37 @@ public abstract class LightEngineLayer, S e - protected final EnumSkyBlock b; - protected final S c; - private boolean f; -- protected final BlockPosition.MutableBlockPosition d = new BlockPosition.MutableBlockPosition(); -+ protected final BlockPosition.MutableBlockPosition d = new BlockPosition.MutableBlockPosition(); protected final BlockPosition.MutableBlockPosition pos = d; // Paper - private final long[] g = new long[2]; -- private final IBlockAccess[] h = new IBlockAccess[2]; -+ private final IChunkAccess[] h = new IChunkAccess[2]; // Paper - -+ // Paper start - see fully commented out method below (look for Bedrock) -+ // optimized method with less branching for when scenarios arent needed. -+ // avoid using mutable version if can -+ protected final IBlockData getBlockOptimized(int x, int y, int z, MutableInt mutableint) { -+ IChunkAccess iblockaccess = this.a(x >> 4, z >> 4); -+ -+ if (iblockaccess == null) { -+ mutableint.setValue(16); -+ return Blocks.BEDROCK.getBlockData(); -+ } else { -+ this.pos.setValues(x, y, z); -+ IBlockData iblockdata = iblockaccess.getType(x, y, z); -+ mutableint.setValue(iblockdata.b(this.a.getWorld(), this.pos)); -+ return iblockdata.l() && iblockdata.e() ? iblockdata : Blocks.AIR.getBlockData(); -+ } -+ } -+ protected final IBlockData getBlockOptimized(int x, int y, int z) { -+ IChunkAccess iblockaccess = this.a(x >> 4, z >> 4); -+ -+ if (iblockaccess == null) { -+ return Blocks.BEDROCK.getBlockData(); -+ } else { -+ IBlockData iblockdata = iblockaccess.getType(x, y, z); -+ return iblockdata.l() && iblockdata.e() ? iblockdata : Blocks.AIR.getBlockData(); -+ } -+ } -+ // Paper end - public LightEngineLayer(ILightAccess ilightaccess, EnumSkyBlock enumskyblock, S s0) { - super(16, 256, 8192); - this.a = ilightaccess; -@@ -45,7 +73,7 @@ public abstract class LightEngineLayer, S e - } - - @Nullable -- private IBlockAccess a(int i, int j) { -+ private IChunkAccess a(int i, int j) { // Paper - long k = ChunkCoordIntPair.pair(i, j); - - for (int l = 0; l < 2; ++l) { -@@ -54,7 +82,7 @@ public abstract class LightEngineLayer, S e - } - } - -- IBlockAccess iblockaccess = this.a.c(i, j); -+ IChunkAccess iblockaccess = (IChunkAccess) this.a.c(i, j); // Paper - - for (int i1 = 1; i1 > 0; --i1) { - this.g[i1] = this.g[i1 - 1]; -@@ -71,37 +99,39 @@ public abstract class LightEngineLayer, S e - Arrays.fill(this.h, (Object) null); - } - -- protected IBlockData a(long i, @Nullable MutableInt mutableint) { -- if (i == Long.MAX_VALUE) { -- if (mutableint != null) { -- mutableint.setValue(0); -- } -- -- return Blocks.AIR.getBlockData(); -- } else { -- int j = SectionPosition.a(BlockPosition.b(i)); -- int k = SectionPosition.a(BlockPosition.d(i)); -- IBlockAccess iblockaccess = this.a(j, k); -- -- if (iblockaccess == null) { -- if (mutableint != null) { -- mutableint.setValue(16); -- } -- -- return Blocks.BEDROCK.getBlockData(); -- } else { -- this.d.g(i); -- IBlockData iblockdata = iblockaccess.getType(this.d); -- boolean flag = iblockdata.l() && iblockdata.e(); -- -- if (mutableint != null) { -- mutableint.setValue(iblockdata.b(this.a.getWorld(), (BlockPosition) this.d)); -- } -- -- return flag ? iblockdata : Blocks.AIR.getBlockData(); -- } -- } -- } -+ // Paper start - comment out, see getBlockOptimized -+// protected IBlockData a(long i, @Nullable MutableInt mutableint) { -+// if (i == Long.MAX_VALUE) { -+// if (mutableint != null) { -+// mutableint.setValue(0); -+// } -+// -+// return Blocks.AIR.getBlockData(); -+// } else { -+// int j = SectionPosition.a(BlockPosition.b(i)); -+// int k = SectionPosition.a(BlockPosition.d(i)); -+// IBlockAccess iblockaccess = this.a(j, k); -+// -+// if (iblockaccess == null) { -+// if (mutableint != null) { -+// mutableint.setValue(16); -+// } -+// -+// return Blocks.BEDROCK.getBlockData(); -+// } else { -+// this.d.g(i); -+// IBlockData iblockdata = iblockaccess.getType(this.d); -+// boolean flag = iblockdata.l() && iblockdata.e(); -+// -+// if (mutableint != null) { -+// mutableint.setValue(iblockdata.b(this.a.getWorld(), (BlockPosition) this.d)); -+// } -+// -+// return flag ? iblockdata : Blocks.AIR.getBlockData(); -+// } -+// } -+// } -+ // Paper end - - protected VoxelShape a(IBlockData iblockdata, long i, EnumDirection enumdirection) { - return iblockdata.l() ? iblockdata.a(this.a.getWorld(), this.d.g(i), enumdirection) : VoxelShapes.a(); -@@ -136,8 +166,9 @@ public abstract class LightEngineLayer, S e - return i == Long.MAX_VALUE ? 0 : 15 - this.c.i(i); - } - -+ protected int getNibbleLightInverse(NibbleArray nibblearray, int x, int y, int z) { return 15 - nibblearray.a(x & 15, y & 15, z & 15); } // Paper - x/y/z version of below - protected int a(NibbleArray nibblearray, long i) { -- return 15 - nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i))); -+ return 15 - nibblearray.a((int) (i >> 38) & 15, (int) ((i << 52) >> 52) & 15, (int) ((i << 26) >> 38) & 15); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -index 37fa5faea6e2972e3eb8a3cbd1913ef38dc9456f..9cd2dfbfa216fdc58297fd25066d31bb92e13ec2 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -@@ -4,6 +4,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.core.SectionPosition; - import net.minecraft.world.level.EnumSkyBlock; -+import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.chunk.ILightAccess; - import net.minecraft.world.level.chunk.NibbleArray; -@@ -38,21 +39,25 @@ public final class LightEngineSky extends LightEngineLayer= 15) { -+ // Paper start - use x/y/z and optimized block lookup -+ int jx = (int) (j >> 38); -+ int jy = (int) ((j << 52) >> 52); -+ int jz = (int) ((j << 26) >> 38); -+ IBlockData iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); -+ int blockedLight = mutableint.getValue(); -+ if (blockedLight >= 15) { -+ // Paper end - return 15; - } else { -- int l = BlockPosition.b(i); -- int i1 = BlockPosition.c(i); -- int j1 = BlockPosition.d(i); -- int k1 = BlockPosition.b(j); -- int l1 = BlockPosition.c(j); -- int i2 = BlockPosition.d(j); -- boolean flag = l == k1 && j1 == i2; -- int j2 = Integer.signum(k1 - l); -- int k2 = Integer.signum(l1 - i1); -- int l2 = Integer.signum(i2 - j1); -+ // Paper start - inline math -+ int ix = (int) (i >> 38); -+ int iy = (int) ((i << 52) >> 52); -+ int iz = (int) ((i << 26) >> 38); -+ boolean flag = ix == jx && iz == jz; -+ int j2 = Integer.signum(jx - ix); -+ int k2 = Integer.signum(jy - iy); -+ int l2 = Integer.signum(jz - iz); -+ // Paper end - EnumDirection enumdirection; - - if (i == Long.MAX_VALUE) { -@@ -61,7 +66,7 @@ public final class LightEngineSky extends LightEngineLayer l1; -+ boolean flag1 = i == Long.MAX_VALUE || flag && iy > jy; // Paper rename vars to iy > jy - -- return flag1 && k == 0 && mutableint.getValue() == 0 ? 0 : k + Math.max(1, mutableint.getValue()); -+ return flag1 && k == 0 && blockedLight == 0 ? 0 : k + Math.max(1, blockedLight); // Paper - } - } - } -@@ -101,10 +106,14 @@ public final class LightEngineSky extends LightEngineLayer> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long k = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); -+ int i1 = baseY & 15; -+ int j1 = baseY >> 4; -+ // Paper end - int k1; - - if (i1 != 0) { -@@ -119,15 +128,16 @@ public final class LightEngineSky extends LightEngineLayer> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long j1 = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); -+ NibbleArray nibblearray = this.c.updating.getUpdatingOptimized(j1); -+ // Paper end - EnumDirection[] aenumdirection = LightEngineSky.e; - int k1 = aenumdirection.length; - - for (int l1 = 0; l1 < k1; ++l1) { - EnumDirection enumdirection = aenumdirection[l1]; -- long i2 = BlockPosition.a(i, enumdirection); -- long j2 = SectionPosition.e(i2); -+ // Paper start -+ int newX = baseX + enumdirection.getAdjacentX(); -+ int newY = baseY + enumdirection.getAdjacentY(); -+ int newZ = baseZ + enumdirection.getAdjacentZ(); -+ long i2 = BlockPosition.asLong(newX, newY, newZ); -+ long j2 = SectionPosition.blockPosAsSectionLong(newX, newY, newZ); -+ // Paper end - NibbleArray nibblearray1; - - if (j1 == j2) { - nibblearray1 = nibblearray; - } else { -- nibblearray1 = ((LightEngineStorageSky) this.c).a(j2, true); -+ nibblearray1 = ((LightEngineStorageSky) this.c).updating.getUpdatingOptimized(j2); // Paper - } - - if (nibblearray1 != null) { - if (i2 != j) { -- int k2 = this.b(i2, i, this.a(nibblearray1, i2)); -+ int k2 = this.b(i2, i, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper - - if (l > k2) { - l = k2; -@@ -215,7 +235,7 @@ public final class LightEngineSky extends LightEngineLayer> e - protected final LongSet c = new LongOpenHashSet(); - protected final LongSet d = new LongOpenHashSet(); - protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change -- protected final M f; // Paper - diff on change, should be "updating" -+ protected final M f; protected final M updating; // Paper - diff on change, should be "updating" - protected final LongSet g = new LongOpenHashSet(); -- protected final LongSet h = new LongOpenHashSet(); -+ protected final LongSet h = new LongOpenHashSet(); LongSet dirty = h; // Paper - OBFHELPER - protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); - private final LongSet n = new LongOpenHashSet(); - private final LongSet o = new LongOpenHashSet(); -@@ -37,33 +37,33 @@ public abstract class LightEngineStorage> e - protected volatile boolean j; - - protected LightEngineStorage(EnumSkyBlock enumskyblock, ILightAccess ilightaccess, M m0) { -- super(3, 16, 256); -+ super(3, 256, 256); // Paper - bump expected size of level sets to improve collisions and reduce rehashing (seen a lot of it) - this.l = enumskyblock; - this.m = ilightaccess; -- this.f = m0; -+ this.f = m0; updating = m0; // Paper - this.e_visible = m0.b(); // Paper - avoid copying light data - this.e_visible.d(); // Paper - avoid copying light data - } - -- protected boolean g(long i) { -- return this.a(i, true) != null; -+ protected final boolean g(long i) { // Paper - final to help inlining -+ return this.updating.getUpdatingOptimized(i) != null; // Paper - inline to avoid branching - } - - @Nullable - protected NibbleArray a(long i, boolean flag) { - // Paper start - avoid copying light data - if (flag) { -- return this.a(this.f, i); -+ return this.updating.getUpdatingOptimized(i); - } else { - synchronized (this.visibleUpdateLock) { -- return this.a(this.e_visible, i); -+ return this.e_visible.lookup.apply(i); - } - } - // Paper end - avoid copying light data - } - - @Nullable -- protected NibbleArray a(M m0, long i) { -+ protected final NibbleArray a(M m0, long i) { // Paper - return m0.c(i); - } - -@@ -77,27 +77,57 @@ public abstract class LightEngineStorage> e - protected abstract int d(long i); - - protected int i(long i) { -- long j = SectionPosition.e(i); -- NibbleArray nibblearray = this.a(j, true); -+ // Paper start - reuse and inline math, use Optimized Updating path -+ final int x = (int) (i >> 38); -+ final int y = (int) ((i << 52) >> 52); -+ final int z = (int) ((i << 26) >> 38); -+ long j = SectionPosition.blockPosAsSectionLong(x, y, z); -+ NibbleArray nibblearray = this.updating.getUpdatingOptimized(j); -+ // BUG: Sometimes returns null and crashes, try to recover, but to prevent crash just return no light. -+ if (nibblearray == null) { -+ nibblearray = this.e_visible.lookup.apply(j); -+ } -+ if (nibblearray == null) { -+ System.err.println("Null nibble, preventing crash " + BlockPosition.fromLong(i)); -+ return 0; -+ } - -- return nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i))); -+ return nibblearray.a(x & 15, y & 15, z & 15); // Paper - inline operations -+ // Paper end - } - - protected void b(long i, int j) { -- long k = SectionPosition.e(i); -+ // Paper start - cache part of the math done in loop below -+ int x = (int) (i >> 38); -+ int y = (int) ((i << 52) >> 52); -+ int z = (int) ((i << 26) >> 38); -+ long k = SectionPosition.blockPosAsSectionLong(x, y, z); -+ // Paper end - - if (this.g.add(k)) { - this.f.a(k); - } - - NibbleArray nibblearray = this.a(k, true); -- -- nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i)), j); -- -- for (int l = -1; l <= 1; ++l) { -- for (int i1 = -1; i1 <= 1; ++i1) { -- for (int j1 = -1; j1 <= 1; ++j1) { -- this.h.add(SectionPosition.e(BlockPosition.a(i, i1, j1, l))); -+ nibblearray.a(x & 15, y & 15, z & 15, j); // Paper - use already calculated x/y/z -+ -+ // Paper start - credit to JellySquid for a major optimization here: -+ /* -+ * An extremely important optimization is made here in regards to adding items to the pending notification set. The -+ * original implementation attempts to add the coordinate of every chunk which contains a neighboring block position -+ * even though a huge number of loop iterations will simply map to block positions within the same updating chunk. -+ * -+ * Our implementation here avoids this by pre-calculating the min/max chunk coordinates so we can iterate over only -+ * the relevant chunk positions once. This reduces what would always be 27 iterations to just 1-8 iterations. -+ * -+ * @reason Use faster implementation -+ * @author JellySquid -+ */ -+ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { -+ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { -+ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { -+ this.dirty.add(SectionPosition.asLong(x2, y2, z2)); -+ // Paper end - } - } - } -@@ -129,17 +159,23 @@ public abstract class LightEngineStorage> e - } - - if (k >= 2 && j != 2) { -- if (this.p.contains(i)) { -- this.p.remove(i); -- } else { -+ if (!this.p.remove(i)) { // Paper - remove useless contains - credit to JellySquid -+ //this.p.remove(i); // Paper -+ //} else { // Paper - this.f.a(i, this.j(i)); - this.g.add(i); - this.k(i); - -- for (int l = -1; l <= 1; ++l) { -- for (int i1 = -1; i1 <= 1; ++i1) { -- for (int j1 = -1; j1 <= 1; ++j1) { -- this.h.add(SectionPosition.e(BlockPosition.a(i, i1, j1, l))); -+ // Paper start - reuse x/y/z and only notify valid chunks - Credit to JellySquid (See above method for notes) -+ int x = (int) (i >> 38); -+ int y = (int) ((i << 52) >> 52); -+ int z = (int) ((i << 26) >> 38); -+ -+ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { -+ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { -+ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { -+ this.dirty.add(SectionPosition.asLong(x2, y2, z2)); -+ // Paper end - } - } - } -@@ -165,9 +201,9 @@ public abstract class LightEngineStorage> e - return SectionPosition.e(j) == i; - }); - } else { -- int j = SectionPosition.c(SectionPosition.b(i)); -- int k = SectionPosition.c(SectionPosition.c(i)); -- int l = SectionPosition.c(SectionPosition.d(i)); -+ int j = (int) (i >> 42) << 4; // Paper - inline -+ int k = (int) (i << 44 >> 44) << 4; // Paper - inline -+ int l = (int) (i << 22 >> 42) << 4; // Paper - inline - - for (int i1 = 0; i1 < 16; ++i1) { - for (int j1 = 0; j1 < 16; ++j1) { -@@ -194,7 +230,7 @@ public abstract class LightEngineStorage> e - NibbleArray nibblearray; - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.a(lightenginelayer, i); - NibbleArray nibblearray1 = (NibbleArray) this.i.remove(i); - -@@ -212,7 +248,7 @@ public abstract class LightEngineStorage> e - longiterator = this.p.iterator(); - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.l(i); - } - -@@ -223,12 +259,13 @@ public abstract class LightEngineStorage> e - Entry entry; - long j; - -+ NibbleArray test = null; // Paper - while (objectiterator.hasNext()) { - entry = (Entry) objectiterator.next(); - j = entry.getLongKey(); -- if (this.g(j)) { -+ if ((test = this.updating.getUpdatingOptimized(j)) != null) { // Paper - dont look up nibble twice - nibblearray = (NibbleArray) entry.getValue(); -- if (this.f.c(j) != nibblearray) { -+ if (test != nibblearray) { // Paper - this.a(lightenginelayer, j); - this.f.a(j, nibblearray); - this.g.add(j); -@@ -241,14 +278,14 @@ public abstract class LightEngineStorage> e - longiterator = this.i.keySet().iterator(); - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.b(lightenginelayer, i); - } - } else { - longiterator = this.n.iterator(); - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.b(lightenginelayer, i); - } - } -@@ -269,15 +306,20 @@ public abstract class LightEngineStorage> e - - private void b(LightEngineLayer lightenginelayer, long i) { - if (this.g(i)) { -- int j = SectionPosition.c(SectionPosition.b(i)); -- int k = SectionPosition.c(SectionPosition.c(i)); -- int l = SectionPosition.c(SectionPosition.d(i)); -+ // Paper start -+ int secX = (int) (i >> 42); -+ int secY = (int) (i << 44 >> 44); -+ int secZ = (int) (i << 22 >> 42); -+ int j = secX << 4; // baseX -+ int k = secY << 4; // baseY -+ int l = secZ << 4; // baseZ -+ // Paper end - EnumDirection[] aenumdirection = LightEngineStorage.k; - int i1 = aenumdirection.length; - - for (int j1 = 0; j1 < i1; ++j1) { - EnumDirection enumdirection = aenumdirection[j1]; -- long k1 = SectionPosition.a(i, enumdirection); -+ long k1 = SectionPosition.getAdjacentFromSectionPos(secX, secY, secZ, enumdirection); // Paper - avoid extra unpacking - - if (!this.i.containsKey(k1) && this.g(k1)) { - for (int l1 = 0; l1 < 16; ++l1) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -index da78d4c4b5f8af4648ac82d63c21f6a2a5b73ecb..2ce5cf2e5b6e1dae463439fbfde519fa54677714 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -@@ -7,13 +7,18 @@ import net.minecraft.world.level.chunk.NibbleArray; - - public abstract class LightEngineStorageArray> { - -- private final long[] b = new long[2]; -- private final NibbleArray[] c = new NibbleArray[2]; -+ // private final long[] b = new long[2]; // Paper - unused -+ private final NibbleArray[] c = new NibbleArray[]{NibbleArray.EMPTY_NIBBLE_ARRAY, NibbleArray.EMPTY_NIBBLE_ARRAY}; private final NibbleArray[] cache = c; // Paper - OBFHELPER - private boolean d; - protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data - protected final boolean isVisible; // Paper - avoid copying light data -- java.util.function.Function lookup; // Paper - faster branchless lookup - -+ // Paper start - faster lookups with less branching, use interface to avoid boxing instead of Function -+ public final NibbleArrayAccess lookup; -+ public interface NibbleArrayAccess { -+ NibbleArray apply(long id); -+ } -+ // Paper end - // Paper start - avoid copying light data - protected LightEngineStorageArray(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { - if (isVisible) { -@@ -21,12 +26,14 @@ public abstract class LightEngineStorageArray 0; --k) { -- this.b[k] = this.b[k - 1]; -- this.c[k] = this.c[k - 1]; -- } -- -- this.b[0] = i; -- this.c[0] = nibblearray; -- } -- -+ cache[1] = cache[0]; -+ cache[0] = nibblearray; - return nibblearray; - } - } -+ // Paper end -+ -+ @Nullable -+ public final NibbleArray c(final long i) { // Paper - final -+ // Paper start - optimize visible case or missed updating cases -+ if (this.d) { -+ // short circuit to optimized -+ return getUpdatingOptimized(i); -+ } -+ -+ return this.lookup.apply(i); -+ // Paper end -+ } - - @Nullable - public NibbleArray d(long i) { -@@ -82,13 +91,14 @@ public abstract class LightEngineStorageArray> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long j = (((long) (baseX >> 4) & 4194303L) << 42) | (((long) (baseY >> 4) & 1048575L)) | (((long) (baseZ >> 4) & 4194303L) << 20); -+ NibbleArray nibblearray = this.e_visible.lookup.apply(j); -+ return nibblearray == null ? 0 : nibblearray.a(baseX & 15, baseY & 15, baseZ & 15); -+ // Paper end - } - - public static final class a extends LightEngineStorageArray { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -index 488403a6765598317faedc2d600ae82238e99e39..6d31b19c851081a37e6fcefdcdfcb7018fce6b26 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -@@ -28,7 +28,12 @@ public class LightEngineStorageSky extends LightEngineStorage> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long j = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); -+ // Paper end - int k = SectionPosition.c(j); - synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data - LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e_visible; // Paper - avoid copying light data - must be after lock acquire -@@ -49,7 +54,7 @@ public class LightEngineStorageSky extends LightEngineStorage> 52) & 15, (int) baseZ & 15); // Paper - y changed above - } else { - return 15; - } -@@ -168,7 +173,7 @@ public class LightEngineStorageSky extends LightEngineStorage> 42) << 4; // Paper -+ int baseY = (int) (i << 44 >> 44) << 4; // Paper -+ int baseZ = (int) (i << 22 >> 42) << 4; // Paper - j = this.c(i); - if (j != 2 && !this.n.contains(i) && this.l.add(i)) { - int l; -@@ -203,10 +211,10 @@ public class LightEngineStorageSky extends LightEngineStorage> 42) << 4; // Paper -+ int baseY = (int) (i << 44 >> 44) << 4; // Paper -+ int baseZ = (int) (i << 22 >> 42) << 4; // Paper - if (this.l.remove(i) && this.g(i)) { - for (j = 0; j < 16; ++j) { - for (k = 0; k < 16; ++k) { -- long l3 = BlockPosition.a(SectionPosition.c(SectionPosition.b(i)) + j, SectionPosition.c(SectionPosition.c(i)) + 16 - 1, SectionPosition.c(SectionPosition.d(i)) + k); -+ long l3 = BlockPosition.a(baseX + j, baseY + 16 - 1, baseZ + k); // Paper - - lightenginelayer.a(Long.MAX_VALUE, l3, 15, false); - } diff --git a/Unmapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/Unmapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch deleted file mode 100644 index d2c3fa9257..0000000000 --- a/Unmapped-Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Jun 2016 23:22:12 -0400 -Subject: [PATCH] Delay Chunk Unloads based on Player Movement - -When players are moving in the world, doing things such as building or exploring, -they will commonly go back and forth in a small area. This causes a ton of chunk load -and unload activity on the edge chunks of their view distance. - -A simple back and forth movement in 6 blocks could spam a chunk to thrash a -loading and unload cycle over and over again. - -This is very wasteful. This system introduces a delay of inactivity on a chunk -before it actually unloads, which will be handled by the ticket expiry process. - -This allows servers with smaller worlds who do less long distance exploring to stop -wasting cpu cycles on saving/unloading/reloading chunks repeatedly. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6463d3e4837d032a35654a035f42b8a805e0e286..1655bca0502e7b871de4addaa163536d86547a02 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -637,4 +637,13 @@ public class PaperWorldConfig { - private void viewDistance() { - this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); - } -+ -+ public long delayChunkUnloadsBy; -+ private void delayChunkUnloadsBy() { -+ delayChunkUnloadsBy = PaperConfig.getSeconds(getString("delay-chunk-unloads-by", "10s")); -+ if (delayChunkUnloadsBy > 0) { -+ log("Delaying chunk unloads by " + delayChunkUnloadsBy + " seconds"); -+ delayChunkUnloadsBy *= 20; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index a3c44fdfca8290313b9b1117b984533183b583ad..3644e8b24b082e17752ef52934625416130aaa08 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -185,6 +185,27 @@ public abstract class ChunkMapDistance { - boolean removed = false; // CraftBukkit - if (arraysetsorted.remove(ticket)) { - removed = true; // CraftBukkit -+ // Paper start - delay chunk unloads for player tickets -+ long delayChunkUnloadsBy = chunkMap.world.paperConfig.delayChunkUnloadsBy; -+ if (ticket.getTicketType() == TicketType.PLAYER && delayChunkUnloadsBy > 0) { -+ boolean hasPlayer = false; -+ for (Ticket ticket1 : arraysetsorted) { -+ if (ticket1.getTicketType() == TicketType.PLAYER) { -+ hasPlayer = true; -+ break; -+ } -+ } -+ PlayerChunk playerChunk = chunkMap.getUpdatingChunk(i); -+ if (!hasPlayer && playerChunk != null && playerChunk.isFullChunkReady()) { -+ Ticket delayUnload = new Ticket(TicketType.DELAY_UNLOAD, 33, i); -+ delayUnload.delayUnloadBy = delayChunkUnloadsBy; -+ delayUnload.setCurrentTick(this.currentTick); -+ arraysetsorted.remove(delayUnload); -+ // refresh ticket -+ arraysetsorted.add(delayUnload); -+ } -+ } -+ // Paper end - } - - if (arraysetsorted.isEmpty()) { -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 90cbd12611b7b078f35f08f910453bcc02f6665b..6e5ae954c6eb40590bf8c83f592c22088d489be8 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -9,11 +9,13 @@ public final class Ticket implements Comparable> { - public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER - private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER - public int priority = 0; // Paper -+ public long delayUnloadBy; // Paper - - protected Ticket(TicketType tickettype, int i, T t0) { - this.a = tickettype; - this.b = i; - this.identifier = t0; -+ this.delayUnloadBy = tickettype.loadPeriod; // Paper - } - - public int compareTo(Ticket ticket) { -@@ -63,7 +65,7 @@ public final class Ticket implements Comparable> { - } - - protected boolean b(long i) { -- long j = this.a.b(); -+ long j = delayUnloadBy; // Paper - - return j != 0L && i - this.d > j; - } -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index f5d18834e0e2ee0e3bcf55810456766d2f134450..3c804c7b20a14ea6e510810e2be10c1cc89ff5c1 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -30,6 +30,7 @@ public class TicketType { - public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper - public static final TicketType PRIORITY = a("priority", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper - public static final TicketType URGENT = a("urgent", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper -+ public static final TicketType DELAY_UNLOAD = a("delay_unload", Long::compareTo, 300); // Paper - - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); diff --git a/Unmapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/Unmapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch deleted file mode 100644 index f91b76cc6e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 9 Jun 2020 03:33:03 -0400 -Subject: [PATCH] Add Plugin Tickets to API Chunk Methods - -Like previous versions, plugins loading chunks kept them loaded until -they garbage collected to avoid constant spamming of chunk loads - -This adds tickets to a few more places so that they can be unloaded. - -Additionally, this drops their ticket level to BORDER so they wont be ticking -so they will just sit inactive instead. - -Using .loadChunk to keep a chunk ticking was a horrible idea for upstream -when we have TWO methods that are able to do that already in the API. - -Also reduce their collection count down to a maximum of 1 second. Barely -anyone knows what chunk-gc is in bukkit.yml as its less relevant now, and -since this wasn't spigot behavior, this is safe to mostly ignore (unless someone -wants it to collect even faster, they can restore that setting back to 1 instead of 20+) - -Not adding it to .getType() though to keep behavior consistent with vanilla for performance reasons. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 5f03ec59588fd975ca2fb62961b10212d8a9cbec..a295ab6a7ec79775224381e94e288069f5d311fe 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -343,7 +343,7 @@ public final class CraftServer implements Server { - ambientSpawn = configuration.getInt("spawn-limits.ambient"); - console.autosavePeriod = configuration.getInt("ticks-per.autosave"); - warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); -- TicketType.PLUGIN.loadPeriod = configuration.getInt("chunk-gc.period-in-ticks"); -+ TicketType.PLUGIN.loadPeriod = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - loadIcon(); - } -@@ -833,7 +833,7 @@ public final class CraftServer implements Server { - waterAmbientSpawn = configuration.getInt("spawn-limits.water-ambient"); - ambientSpawn = configuration.getInt("spawn-limits.ambient"); - warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); -- TicketType.PLUGIN.loadPeriod = configuration.getInt("chunk-gc.period-in-ticks"); -+ TicketType.PLUGIN.loadPeriod = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - printSaveWarning = false; - console.autosavePeriod = configuration.getInt("ticks-per.autosave"); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 6034ef65ee6030948a5b76fa493addb44188ef62..80cd8ce4e70dbb740439ac530a7bc70a7a54cb85 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffect; - import net.minecraft.network.protocol.game.PacketPlayOutUpdateTime; - import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ChunkMapDistance; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.PlayerChunkMap; -@@ -407,8 +408,21 @@ public class CraftWorld implements World { - - @Override - public Chunk getChunkAt(int x, int z) { -- return this.world.getChunkProvider().getChunkAt(x, z, true).bukkitChunk; -+ // Paper start - add ticket to hold chunk for a little while longer if plugin accesses it -+ net.minecraft.world.level.chunk.Chunk chunk = world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); -+ if (chunk == null) { -+ addTicket(x, z); -+ chunk = this.world.getChunkProvider().getChunkAt(x, z, true); -+ } -+ return chunk.bukkitChunk; -+ // Paper end -+ } -+ -+ // Paper start -+ private void addTicket(int x, int z) { -+ MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkProvider().addTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 0, Unit.INSTANCE)); // Paper - } -+ // Paper end - - @Override - public Chunk getChunkAt(Block block) { -@@ -483,7 +497,7 @@ public class CraftWorld implements World { - public boolean unloadChunkRequest(int x, int z) { - org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot - if (isChunkLoaded(x, z)) { -- world.getChunkProvider().removeTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE); -+ world.getChunkProvider().removeTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 0, Unit.INSTANCE); // Paper - } - - return true; -@@ -560,9 +574,12 @@ public class CraftWorld implements World { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot - // Paper start - Optimize this method - ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); -+ IChunkAccess immediate = world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); // Paper -+ if (immediate != null) return true; // Paper - - if (!generate) { -- IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); -+ -+ //IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); // Paper - if (immediate == null) { - immediate = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); - } -@@ -570,7 +587,7 @@ public class CraftWorld implements World { - if (!(immediate instanceof ProtoChunkExtension) && !(immediate instanceof net.minecraft.world.level.chunk.Chunk)) { - return false; // not full status - } -- world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper - world.getChunkAt(x, z); // make sure we're at ticket level 32 or lower - return true; - } -@@ -597,7 +614,7 @@ public class CraftWorld implements World { - // we do this so we do not re-read the chunk data on disk - } - -- world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper - world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); - return true; - // Paper end -@@ -2547,6 +2564,7 @@ public class CraftWorld implements World { - } - return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { - net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); -+ if (chunk != null) addTicket(x, z); // Paper - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); - }, net.minecraft.server.MinecraftServer.getServer()); - } diff --git a/Unmapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch b/Unmapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch deleted file mode 100644 index 15f03e8c36..0000000000 --- a/Unmapped-Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: David Slovikosky -Date: Tue, 9 Jun 2020 00:10:03 -0700 -Subject: [PATCH] Fix missing chunks due to integer overflow - -This patch fixes a bug in the WorldChunkManagerTheEnd class where the distance -from 0,0 squared overflows the maximum size of an integer. The overflow leads -to hard chunk borders around 370,000 blocks from 0,0. After this cutoff there -is a few hundred thousand block gap before end land resuming to generate at -530,000 blocks from spawn. This is due to the integer flipping back and forth. - -The fix for the issue is quite simple, casting chunk coordinates to longs -allows the distance calculation to avoid overflow and work as intended. - -diff --git a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -index 1d46e2c4e06cfe32eac06223e1966ce39c41685e..1077972d694d604c3ec97d333d34a9ab81819c33 100644 ---- a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -+++ b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -@@ -75,7 +75,9 @@ public class WorldChunkManagerTheEnd extends WorldChunkManager { - int l = j / 2; - int i1 = i % 2; - int j1 = j % 2; -- float f = 100.0F - MathHelper.c((float) (i * i + j * j)) * 8.0F; -+ // Paper start - cast ints to long to avoid integer overflow -+ float f = 100.0F - MathHelper.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; -+ // Paper end - - f = MathHelper.a(f, -100.0F, 80.0F); - diff --git a/Unmapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/Unmapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch deleted file mode 100644 index 423af0ebf9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ossi -Date: Fri, 12 Jun 2020 01:38:06 +0300 -Subject: [PATCH] Fix CraftScheduler#runTaskTimerAsynchronously(Plugin, - Consumer, long, long) scheduling a non-repeating task instead of - a repeating one. - - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index ca90237a53c9a026919d28adaedf483ca3c7c2a8..13e461ffb2ee2e7d0440c0f60809ea99629b843c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -184,7 +184,7 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public void runTaskTimerAsynchronously(Plugin plugin, Consumer task, long delay, long period) throws IllegalArgumentException { -- runTaskTimerAsynchronously(plugin, (Object) task, delay, CraftTask.NO_REPEATING); -+ runTaskTimerAsynchronously(plugin, (Object) task, delay, period); - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch b/Unmapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch deleted file mode 100644 index 86e65e4b6f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 11 Jun 2020 17:29:42 -0700 -Subject: [PATCH] Fix piston physics inconsistency - MC-188840 - -Pistons invoke physics when they move blocks. The physics can cause -tnt blocks to ignite. However, pistons (when storing the blocks they "moved") -don't actually go back to the world state sometimes to check if something -like that happened. As a result they end up moving the tnt like it was -never ignited. This resulted in the ability to create machines -that can duplicate tnt, called "world eaters". -This patch makes the piston logic retrieve the block state from the world -prevent this from occuring. - -This patch also sets the moved pos to air immediately after creating -the moving piston TE. This prevents the block from being updated from -other physics calls by the piston. - -Tested against the following tnt duper design: -https://www.youtube.com/watch?v=mS7xxNGhjxs - -This patch also affects every type of machine that utilises -this mechanic. For example, dead coral is removed by a physics -update when being moved while it is attached to slimeblocks. - -Standard piston machines that don't destroy or modify the -blocks they move by physics updates should be entirely -unaffected. - -This patch fixes https://bugs.mojang.com/browse/MC-188840 - -This patch also fixes rail duping and carpet duping. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 7f140333c2e62012fa572c1a061d84432426997f..b67ba8f75e4a3358d7c2462918b85b0bf9b5a922 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -434,4 +434,10 @@ public class PaperConfig { - consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); - } - -+ public static boolean allowPistonDuplication; -+ private static void allowPistonDuplication() { -+ config.set("settings.unsupported-settings.allow-piston-duplication-readme", "This setting controls if player should be able to use TNT duplication, but this also allows duplicating carpet, rails and potentially other items"); -+ allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); -+ set("settings.unsupported-settings.allow-tnt-duplication", null); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -index e062fd288098127fae22a55562e0207ceaf50163..8aa51fb207820a7629d50b80ea821ec6cccf8b54 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -@@ -399,12 +399,24 @@ public class BlockPiston extends BlockDirectional { - } - - for (k = list.size() - 1; k >= 0; --k) { -- blockposition3 = (BlockPosition) list.get(k); -- iblockdata1 = world.getType(blockposition3); -+ // Paper start - fix a variety of piston desync dupes -+ boolean allowDesync = com.destroystokyo.paper.PaperConfig.allowPistonDuplication; -+ BlockPosition oldPos = blockposition3 = (BlockPosition) list.get(k); -+ iblockdata1 = allowDesync ? world.getType(oldPos) : null; -+ // Paper end - fix a variety of piston desync dupes - blockposition3 = blockposition3.shift(enumdirection1); - map.remove(blockposition3); - world.setTypeAndData(blockposition3, (IBlockData) Blocks.MOVING_PISTON.getBlockData().set(BlockPiston.FACING, enumdirection), 68); -- world.setTileEntity(blockposition3, BlockPistonMoving.a((IBlockData) list1.get(k), enumdirection, flag, false)); -+ // Paper start - fix a variety of piston desync dupes -+ if (!allowDesync) { -+ iblockdata1 = world.getType(oldPos); -+ map.replace(oldPos, iblockdata1); -+ } -+ world.setTileEntity(blockposition3, BlockPistonMoving.a(allowDesync ? list1.get(k) : iblockdata1, enumdirection, flag, false)); -+ if (!allowDesync) { -+ world.setTypeAndData(oldPos, Blocks.AIR.getBlockData(), 2 | 4 | 16 | 1024); // set air to prevent later physics updates from seeing this block -+ } -+ // Paper end - fix a variety of piston desync dupes - aiblockdata[j++] = iblockdata1; - } - -diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -index 8d13e60f40e1b760e9e69969dc3f37bc6c70dbe9..e70c3a8c9075b6c0bc73e6488d784dfe3b86e58d 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -@@ -279,7 +279,7 @@ public class TileEntityPiston extends TileEntity implements ITickable { - IBlockData iblockdata = Block.b(this.a, (GeneratorAccess) this.world, this.position); - - if (iblockdata.isAir()) { -- this.world.setTypeAndData(this.position, this.a, 84); -+ this.world.setTypeAndData(this.position, this.a, com.destroystokyo.paper.PaperConfig.allowPistonDuplication ? 84 : (84 | 2)); // Paper - force notify (flag 2), it's possible the set type by the piston block (which doesn't notify) set this block to air - Block.a(this.a, iblockdata, this.world, this.position, 3); - } else { - if (iblockdata.b(BlockProperties.C) && (Boolean) iblockdata.get(BlockProperties.C)) { diff --git a/Unmapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch b/Unmapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch deleted file mode 100644 index e3e2417078..0000000000 --- a/Unmapped-Spigot-Server-Patches/0497-Fix-sand-duping.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 12 Jun 2020 13:33:19 -0700 -Subject: [PATCH] Fix sand duping - -If the falling block dies during teleportation (entity#move), then we need -to detect that by placing a check after the move. - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 411e3915c0aa00249aacb6658ed04309665d2fb4..62d8b53c024888aa43b8fddf8a475dfb8284a4cc 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -103,6 +103,11 @@ public class EntityFallingBlock extends Entity { - - @Override - public void tick() { -+ // Paper start - fix sand duping -+ if (this.dead) { -+ return; -+ } -+ // Paper end - fix sand duping - if (this.block.isAir()) { - this.die(); - } else { -@@ -125,6 +130,12 @@ public class EntityFallingBlock extends Entity { - - this.move(EnumMoveType.SELF, this.getMot()); - -+ // Paper start - fix sand duping -+ if (this.dead) { -+ return; -+ } -+ // Paper end - fix sand duping -+ - // Paper start - Configurable EntityFallingBlock height nerf - if (this.world.paperConfig.fallingBlockHeightNerf != 0 && this.locY() > this.world.paperConfig.fallingBlockHeightNerf) { - if (this.dropItem && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) { diff --git a/Unmapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch b/Unmapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch deleted file mode 100644 index 9da724328c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 12 Jun 2020 16:51:39 -0700 -Subject: [PATCH] Prevent position desync in playerconnection causing tp - exploit - -Caused the server to revert to the player's overworld coordinates -after teleporting into the end. - -Sidenote: The underlying issue is that the move call can teleport -entities and do other things like kill the entity. In the future, -to fix all exploits derieved from this usually unexpected -behaviour, we need to move all of this dangerous logic outside -of the move call and into an appropriate place in the tick method. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 40fefdb9da9c4fd3ef3e3bb6276de215dd5265f9..3648ea649158e4f7d385eaccf08a85584e6aa869 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1326,6 +1326,11 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9)); - this.player.setOnGround(packetplayinflying.b()); // CraftBukkit - SPIGOT-5810, SPIGOT-5835: reset by this.player.move -+ // Paper start - prevent position desync -+ if (this.teleportPos != null) { -+ return; // ... thanks Mojang for letting move calls teleport across dimensions. -+ } -+ // Paper end - prevent position desync - double d12 = d8; - - d7 = d4 - this.player.locX(); diff --git a/Unmapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch b/Unmapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch deleted file mode 100644 index 6217196c77..0000000000 --- a/Unmapped-Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 12 Jun 2020 22:25:11 -0700 -Subject: [PATCH] Fix enderdragon exp dupe - -Properly track death stage when unloading/loading in the -dragon - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 5168a40eb53565bb3028efe559601acf72bddae5..c296fcf80c2f3f210fa020416973ec8d5db541ba 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -879,6 +879,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - public void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); - nbttagcompound.setInt("DragonPhase", this.bG.a().getControllerPhase().b()); -+ nbttagcompound.setInt("Paper.DeathTick", this.deathAnimationTicks); // Paper - } - - @Override -@@ -887,6 +888,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - if (nbttagcompound.hasKey("DragonPhase")) { - this.bG.setControllerPhase(DragonControllerPhase.getById(nbttagcompound.getInt("DragonPhase"))); - } -+ this.deathAnimationTicks = nbttagcompound.getInt("Paper.DeathTick"); // Paper - - } - diff --git a/Unmapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch b/Unmapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch deleted file mode 100644 index eeb9b62352..0000000000 --- a/Unmapped-Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Wed, 10 Jun 2020 23:55:15 +0100 -Subject: [PATCH] Inventory getHolder method without block snapshot - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index 45634fded9916dca35a246921efb87964c860339..c3fa97ac34e1fc61ae02f224f8afe5a0b486fb4d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -9,6 +9,7 @@ import net.minecraft.world.inventory.InventoryCrafting; - import net.minecraft.world.inventory.InventoryEnderChest; - import net.minecraft.world.inventory.InventoryMerchant; - import net.minecraft.world.level.block.entity.IHopper; -+import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.entity.TileEntityBarrel; - import net.minecraft.world.level.block.entity.TileEntityBlastFurnace; - import net.minecraft.world.level.block.entity.TileEntityBrewingStand; -@@ -526,6 +527,13 @@ public class CraftInventory implements Inventory { - return inventory.getOwner(); - } - -+ // Paper start - getHolder without snapshot -+ @Override -+ public InventoryHolder getHolder(boolean useSnapshot) { -+ return inventory instanceof TileEntity ? ((TileEntity) inventory).getOwner(useSnapshot) : getHolder(); -+ } -+ // Paper end -+ - @Override - public int getMaxStackSize() { - return inventory.getMaxStackSize(); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -index 47029af761e26453090980b9a231fd53d4238cc4..d22abb4259dfcfd3ec0e0516f87fc838a81353ce 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -@@ -64,6 +64,13 @@ public class CraftInventoryDoubleChest extends CraftInventory implements DoubleC - return new DoubleChest(this); - } - -+ // Paper start - getHolder without snapshot -+ @Override -+ public DoubleChest getHolder(boolean useSnapshot) { -+ return getHolder(); -+ } -+ // Paper end -+ - @Override - public Location getLocation() { - return getLeftSide().getLocation().add(getRightSide().getLocation()).multiply(0.5); diff --git a/Unmapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch b/Unmapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch deleted file mode 100644 index 07e4be3370..0000000000 --- a/Unmapped-Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nesaak <52047222+Nesaak@users.noreply.github.com> -Date: Sat, 23 May 2020 10:31:11 -0400 -Subject: [PATCH] Expose Arrow getItemStack - - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index c325c9fe680d9033b20909bcd6100ecc4b0195f6..ce754e0da047050daa08e5e0564fa399d334c04b 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -558,6 +558,7 @@ public abstract class EntityArrow extends IProjectile { - } - } - -+ public final ItemStack getOriginalItemStack() { return getItemStack(); } // Paper - OBFHELPER - exists purely due to overrides all as protected and dont want to change them all - protected abstract ItemStack getItemStack(); - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -index ea33a36dfa6f304946f5b998eb536678a9b2f98c..2ab41a24a22e736753276b95fa0d060017cca0bc 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -@@ -103,6 +103,13 @@ public class CraftArrow extends AbstractProjectile implements AbstractArrow { - getHandle().fromPlayer = EntityArrow.PickupStatus.a(status.ordinal()); - } - -+ // Paper start -+ @Override -+ public org.bukkit.craftbukkit.inventory.CraftItemStack getItemStack() { -+ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(getHandle().getOriginalItemStack()); -+ } -+ //Paper end -+ - @Override - public void setTicksLived(int value) { - super.setTicksLived(value); diff --git a/Unmapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch b/Unmapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch deleted file mode 100644 index 16854ab4a9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Fri, 5 Jun 2020 18:24:06 -0400 -Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 3648ea649158e4f7d385eaccf08a85584e6aa869..4c9ac550fa5556525c66bc02c8c80d375fce0fe4 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2772,9 +2772,15 @@ public class PlayerConnection implements PacketListenerPlayIn { - PlayerConnectionUtils.ensureMainThread(packetplayinautorecipe, this, this.player.getWorldServer()); - this.player.resetIdleTimer(); - if (!this.player.isSpectator() && this.player.activeContainer.windowId == packetplayinautorecipe.b() && this.player.activeContainer.c(this.player) && this.player.activeContainer instanceof ContainerRecipeBook) { -- this.minecraftServer.getCraftingManager().getRecipe(packetplayinautorecipe.c()).ifPresent((irecipe) -> { -- ((ContainerRecipeBook) this.player.activeContainer).a(packetplayinautorecipe.d(), irecipe, this.player); -- }); -+ // Paper start - fire event for clicking recipes in the recipe book -+ com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent event = new com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent( -+ player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(packetplayinautorecipe.c()), packetplayinautorecipe.d()); -+ if (event.callEvent()) { -+ this.minecraftServer.getCraftingManager().getRecipe(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getRecipe())).ifPresent((irecipe) -> { -+ ((ContainerRecipeBook) this.player.activeContainer).a(event.isMakeAll(), irecipe, this.player); -+ }); -+ } -+ // Paper end - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch b/Unmapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch deleted file mode 100644 index 9b9dd4ede4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 26 Jun 2020 22:35:08 -0700 -Subject: [PATCH] Hide sync chunk writes behind flag - -Syncing writes on each write call has terrible performance -on harddrives. - --DPaper.enable-sync-chunk-writes=true to enable - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index b7cf02301c02ed0a6b696384e656426762ae2105..1fab9b9c7d41a0d2a551096c2c15f741a887fa2d 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -@@ -111,7 +111,7 @@ public class DedicatedServerProperties extends PropertyManager { - return MathHelper.clamp(integer, 1, 29999984); - }, 29999984); -- this.syncChunkWrites = this.getBoolean("sync-chunk-writes", true); -+ this.syncChunkWrites = this.getBoolean("sync-chunk-writes", true) && Boolean.getBoolean("Paper.enable-sync-chunk-writes"); // Paper - hide behind flag - this.enableJmxMonitoring = this.getBoolean("enable-jmx-monitoring", false); - this.enableStatus = this.getBoolean("enable-status", true); - this.entityBroadcastRangePercentage = this.a("entity-broadcast-range-percentage", (integer) -> { diff --git a/Unmapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch b/Unmapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch deleted file mode 100644 index 779333c56d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Fri, 14 Sep 2018 17:42:08 +0200 -Subject: [PATCH] Limit lightning strike effect distance - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1655bca0502e7b871de4addaa163536d86547a02..978062774c1db286bfb9b0ffdef19d880b1f249b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -646,4 +646,26 @@ public class PaperWorldConfig { - delayChunkUnloadsBy *= 20; - } - } -+ -+ public double sqrMaxThunderDistance; -+ public double sqrMaxLightningImpactSoundDistance; -+ public double maxLightningFlashDistance; -+ private void lightningStrikeDistanceLimit() { -+ sqrMaxThunderDistance = getInt("lightning-strike-distance-limit.sound", -1); -+ if (sqrMaxThunderDistance > 0) { -+ sqrMaxThunderDistance *= sqrMaxThunderDistance; -+ } -+ -+ sqrMaxLightningImpactSoundDistance = getInt("lightning-strike-distance-limit.impact-sound", -1); -+ if (sqrMaxLightningImpactSoundDistance < 0) { -+ sqrMaxLightningImpactSoundDistance = 32 * 32; //Vanilla value -+ } else { -+ sqrMaxLightningImpactSoundDistance *= sqrMaxLightningImpactSoundDistance; -+ } -+ -+ maxLightningFlashDistance = getInt("lightning-strike-distance-limit.flash", -1); -+ if (maxLightningFlashDistance < 0) { -+ maxLightningFlashDistance = 512; // Vanilla value -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLightning.java b/src/main/java/net/minecraft/world/entity/EntityLightning.java -index 8946fcd93bd785a8c21683b932aa954fbf15d566..834ced9d9b385c8f1d66355244313d62a97d9c98 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLightning.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLightning.java -@@ -76,6 +76,17 @@ public class EntityLightning extends Entity { - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -+ // Paper start - Limit lightning strike effect distance -+ if (distanceSquared <= this.world.paperConfig.sqrMaxLightningImpactSoundDistance) { -+ player.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, -+ SoundCategory.WEATHER, this.locX(), this.locY(), this.locZ(), 2.0f, 0.5F + this.random.nextFloat() * 0.2F)); -+ } -+ -+ if (world.paperConfig.sqrMaxThunderDistance != -1 && distanceSquared >= world.paperConfig.sqrMaxThunderDistance) { -+ continue; -+ } -+ -+ // Paper end - if (distanceSquared > viewDistance * viewDistance) { - double deltaLength = Math.sqrt(distanceSquared); - double relativeX = player.locX() + (deltaX / deltaLength) * viewDistance; -@@ -86,7 +97,7 @@ public class EntityLightning extends Entity { - } - } - // CraftBukkit end -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); -+// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); // Paper - Limit lightning strike effect distance (the packet is now sent from inside the loop) - } - - --this.lifeTicks; diff --git a/Unmapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch b/Unmapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch deleted file mode 100644 index f2a2eb6550..0000000000 --- a/Unmapped-Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 16 May 2020 10:05:30 +0200 -Subject: [PATCH] Add permission for command blocks - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index fbd8a6985a261396789c87e4b687140bd49cea0d..984209e4f66ad23d85d2c5d02318caab1aff7324 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -387,7 +387,7 @@ public class PlayerInteractManager { - TileEntity tileentity = this.world.getTileEntity(blockposition); - Block block = iblockdata.getBlock(); - -- if ((block instanceof BlockCommand || block instanceof BlockStructure || block instanceof BlockJigsaw) && !this.player.isCreativeAndOp()) { -+ if ((block instanceof BlockCommand || block instanceof BlockStructure || block instanceof BlockJigsaw) && !this.player.isCreativeAndOp() && !(block instanceof BlockCommand && (this.player.isCreative() && this.player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission - this.world.notify(blockposition, iblockdata, iblockdata, 3); - return false; - } else if (this.player.a((World) this.world, blockposition, this.gamemode)) { -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 4c9ac550fa5556525c66bc02c8c80d375fce0fe4..168fcf3570e5af68d99944dae9a7d7275fb93ff1 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -798,7 +798,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - PlayerConnectionUtils.ensureMainThread(packetplayinsetcommandblock, this, this.player.getWorldServer()); - if (!this.minecraftServer.getEnableCommandBlock()) { - this.player.sendMessage(new ChatMessage("advMode.notEnabled"), SystemUtils.b); -- } else if (!this.player.isCreativeAndOp()) { -+ } else if (!this.player.isCreativeAndOp() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission - this.player.sendMessage(new ChatMessage("advMode.notAllowed"), SystemUtils.b); - } else { - CommandBlockListenerAbstract commandblocklistenerabstract = null; -@@ -861,7 +861,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - PlayerConnectionUtils.ensureMainThread(packetplayinsetcommandminecart, this, this.player.getWorldServer()); - if (!this.minecraftServer.getEnableCommandBlock()) { - this.player.sendMessage(new ChatMessage("advMode.notEnabled"), SystemUtils.b); -- } else if (!this.player.isCreativeAndOp()) { -+ } else if (!this.player.isCreativeAndOp() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission - this.player.sendMessage(new ChatMessage("advMode.notAllowed"), SystemUtils.b); - } else { - CommandBlockListenerAbstract commandblocklistenerabstract = packetplayinsetcommandminecart.a(this.player.world); -diff --git a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -index 3fcdff3649c725580456dfc965d6c83bd5afe3da..85e7957103d2b2e16e4d3a3ea0bd7de4935f61cd 100644 ---- a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -@@ -192,7 +192,7 @@ public abstract class CommandBlockListenerAbstract implements ICommandListener { - } - - public EnumInteractionResult a(EntityHuman entityhuman) { -- if (!entityhuman.isCreativeAndOp()) { -+ if (!entityhuman.isCreativeAndOp() && !entityhuman.isCreative() && !entityhuman.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission - return EnumInteractionResult.PASS; - } else { - if (entityhuman.getWorld().isClientSide) { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCommand.java b/src/main/java/net/minecraft/world/level/block/BlockCommand.java -index ad50f86d11ff22f055ca9f26cd02a84e75c7d8c8..f7d22282a59277375d146e9459f9f43962dd7d09 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCommand.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCommand.java -@@ -128,7 +128,7 @@ public class BlockCommand extends BlockTileEntity { - public EnumInteractionResult interact(IBlockData iblockdata, World world, BlockPosition blockposition, EntityHuman entityhuman, EnumHand enumhand, MovingObjectPositionBlock movingobjectpositionblock) { - TileEntity tileentity = world.getTileEntity(blockposition); - -- if (tileentity instanceof TileEntityCommand && entityhuman.isCreativeAndOp()) { -+ if (tileentity instanceof TileEntityCommand && (entityhuman.isCreativeAndOp() || (entityhuman.isCreative() && entityhuman.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission - entityhuman.a((TileEntityCommand) tileentity); - return EnumInteractionResult.a(world.isClientSide); - } else { -diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java -index 525ebf961e5da0687183a5e2ead23ed92cbd9d79..a4a809f302c5ff9c76cde5fc0add2ceec1bdf9b5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java -@@ -16,6 +16,7 @@ public final class CraftDefaultPermissions { - DefaultPermissions.registerPermission(ROOT + ".nbt.copy", "Gives the user the ability to copy NBT in creative", org.bukkit.permissions.PermissionDefault.TRUE, parent); - DefaultPermissions.registerPermission(ROOT + ".debugstick", "Gives the user the ability to use the debug stick in creative", org.bukkit.permissions.PermissionDefault.OP, parent); - DefaultPermissions.registerPermission(ROOT + ".debugstick.always", "Gives the user the ability to use the debug stick in all game modes", org.bukkit.permissions.PermissionDefault.FALSE, parent); -+ DefaultPermissions.registerPermission(ROOT + ".commandblock", "Gives the user the ability to use command blocks.", org.bukkit.permissions.PermissionDefault.OP, parent); // Paper - // Spigot end - parent.recalculatePermissibles(); - } diff --git a/Unmapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch b/Unmapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch deleted file mode 100644 index b0248c30f4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 May 2020 22:12:46 -0400 -Subject: [PATCH] Ensure Entity AABB's are never invalid - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b244f5d204938452ea19335947830de47336bbd4..8151403b2a7f5f8441c6810d1bd2bf3df4cefa80 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -66,6 +66,7 @@ import net.minecraft.world.INamableTileEntity; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.animal.EntityAnimal; - import net.minecraft.world.entity.animal.EntityFish; -+import net.minecraft.world.entity.decoration.EntityHanging; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.vehicle.EntityBoat; -@@ -479,7 +480,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - public void setPosition(double d0, double d1, double d2) { - this.setPositionRaw(d0, d1, d2); -- this.a(this.size.a(d0, d1, d2)); -+ //this.a(this.size.a(d0, d1, d2)); // Paper - move into setPositionRaw - if (valid) ((WorldServer) world).chunkCheck(this); // CraftBukkit - } - -@@ -2999,6 +3000,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return new AxisAlignedBB(vec3d, vec3d1); - } - -+ public final void setBoundingBox(AxisAlignedBB axisalignedbb) { a(axisalignedbb); } // Paper - OBFHELPER - public void a(AxisAlignedBB axisalignedbb) { - // CraftBukkit start - block invalid bounding boxes - double minX = axisalignedbb.minX, -@@ -3437,6 +3439,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public void setPositionRaw(double d0, double d1, double d2) { -+ // Paper start - never allow AABB to become desynced from position -+ // hanging has its own special logic -+ if (!(this instanceof EntityHanging) && (this.loc.x != d0 || this.loc.y != d1 || this.loc.z != d2)) { -+ this.setBoundingBox(this.size.a(d0, d1, d2)); -+ } -+ // Paper end - if (this.loc.x != d0 || this.loc.y != d1 || this.loc.z != d2) { - this.loc = new Vec3D(d0, d1, d2); - int i = MathHelper.floor(d0); diff --git a/Unmapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch b/Unmapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch deleted file mode 100644 index 919498d8ec..0000000000 --- a/Unmapped-Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 10 May 2020 22:49:05 -0400 -Subject: [PATCH] Optimize WorldBorder collision checks and air - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 8151403b2a7f5f8441c6810d1bd2bf3df4cefa80..a6df453acadccc6500cec0ac816ec4d1e35adad7 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -909,7 +909,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - AxisAlignedBB axisalignedbb = this.getBoundingBox(); - VoxelShapeCollision voxelshapecollision = VoxelShapeCollision.a(this); - VoxelShape voxelshape = this.world.getWorldBorder().c(); -- Stream stream = VoxelShapes.c(voxelshape, VoxelShapes.a(axisalignedbb.shrink(1.0E-7D)), OperatorBoolean.AND) ? Stream.empty() : Stream.of(voxelshape); -+ Stream stream = !this.world.getWorldBorder().isInBounds(axisalignedbb) ? Stream.empty() : Stream.of(voxelshape); // Paper - Stream stream1 = this.world.c(this, axisalignedbb.b(vec3d), (entity) -> { - return true; - }); -diff --git a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -index d0cc8677f2be422722160fee9b71894b5ddd3186..03584572fa5bf0d96fc4cecece573547f9c94cea 100644 ---- a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -+++ b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -@@ -143,10 +143,10 @@ public class VoxelShapeSpliterator extends AbstractSpliterator { - AxisAlignedBB axisalignedbb = this.a.getBoundingBox(); - - if (!a(worldborder, axisalignedbb)) { -- VoxelShape voxelshape = worldborder.c(); -- -- if (!b(voxelshape, axisalignedbb) && a(voxelshape, axisalignedbb)) { -- consumer.accept(voxelshape); -+ // Paper start -+ if (worldborder.isInBounds(axisalignedbb.shrink(1.0E-7D)) && !worldborder.isInBounds(axisalignedbb.grow(1.0E-7D))) { -+ consumer.accept(worldborder.asVoxelShape()); -+ // Paper end - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 50e2085766caabec1125ca24a2117549efd1a354..bedaa9dd6390e81df5872c2dd6e202a038367bf6 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -52,6 +52,7 @@ public class WorldBorder { - return (double) chunkcoordintpair.f() > this.e() && (double) chunkcoordintpair.d() < this.g() && (double) chunkcoordintpair.g() > this.f() && (double) chunkcoordintpair.e() < this.h(); - } - -+ public final boolean isInBounds(AxisAlignedBB aabb) { return this.a(aabb); } // Paper - OBFHELPER - public boolean a(AxisAlignedBB axisalignedbb) { - return axisalignedbb.maxX > this.e() && axisalignedbb.minX < this.g() && axisalignedbb.maxZ > this.f() && axisalignedbb.minZ < this.h(); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index 2d7405d1fa7c8f378bebe86f5d0de57a129ed92d..858d4689e618c72250447adb61e0bcc3c156f8f3 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -252,7 +252,7 @@ public final class VoxelShapes { - IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition_mutableblockposition); // Paper - if (iblockdata == null) return 0.0D; // Paper - -- if ((k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) { -+ if (!iblockdata.isAir() && (k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) { // Paper - d0 = iblockdata.b((IBlockAccess) iworldreader, blockposition_mutableblockposition, voxelshapecollision).a(enumdirection_enumaxis2, axisalignedbb.d((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), d0); - if (Math.abs(d0) < 1.0E-7D) { - return 0.0D; diff --git a/Unmapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/Unmapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch deleted file mode 100644 index e1f6589002..0000000000 --- a/Unmapped-Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 03:59:10 -0400 -Subject: [PATCH] Fix Per World Difficulty / Remembering Difficulty - -Fixes per world difficulty with /difficulty command and also -makes it so that the server keeps the last difficulty used instead -of restoring the server.properties every single load. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 69476bb6bca963c5ea88a7cc66622ae599595e62..afdbbe62eba7b4f0ad63c5126c6d21488c4e9a7a 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1647,11 +1647,15 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Sun, 28 Jun 2020 19:27:20 -0400 -Subject: [PATCH] Paper dumpitem command - -Let's you quickly view the item in your hands NBT data - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index d165e8c232c38ba2e2faf93c60c8a127bb74c9b6..4b3efe01750d79bcc27a42b5a145d9aa6b124d18 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -9,6 +9,7 @@ import com.google.common.collect.Iterables; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import net.minecraft.core.BlockPosition; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.resources.MinecraftKey; - import com.google.gson.JsonObject; -@@ -36,7 +37,9 @@ import org.bukkit.command.CommandSender; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.entity.CraftPlayer; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; - import org.bukkit.entity.Player; -+import org.bukkit.inventory.ItemStack; - - import java.io.File; - import java.io.FileOutputStream; -@@ -59,7 +62,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight", "dumpitem").build(); - - public PaperCommand(String name) { - super(name); -@@ -168,6 +171,9 @@ public class PaperCommand extends Command { - case "reload": - doReload(sender); - break; -+ case "dumpitem": -+ doDumpItem(sender); -+ break; - case "debug": - doDebug(sender, args); - break; -@@ -200,6 +206,19 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doDumpItem(CommandSender sender) { -+ ItemStack itemInHand = ((CraftPlayer) sender).getItemInHand(); -+ net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(itemInHand); -+ NBTTagCompound tag = itemStack.getTag(); -+ if (tag != null) { -+ String nbt = org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(tag.getNbtPrettyComponent()); -+ Bukkit.getConsoleSender().sendMessage(nbt); -+ sender.sendMessage(nbt); -+ } else { -+ sender.sendMessage("Item does not have NBT"); -+ } -+ } -+ - private void doFixLight(CommandSender sender, String[] args) { - if (!(sender instanceof Player)) { - sender.sendMessage("Only players can use this command"); -diff --git a/src/main/java/net/minecraft/nbt/NBTBase.java b/src/main/java/net/minecraft/nbt/NBTBase.java -index d6e51f82f6df2d7058806f3e483766e18398af77..3921b99b9a4c1a867b5159668d2cd62d7463e1ff 100644 ---- a/src/main/java/net/minecraft/nbt/NBTBase.java -+++ b/src/main/java/net/minecraft/nbt/NBTBase.java -@@ -26,6 +26,7 @@ public interface NBTBase { - return this.toString(); - } - -+ default IChatBaseComponent getNbtPrettyComponent() { return this.l(); } // Paper - OBFHELPER - default IChatBaseComponent l() { - return this.a("", 0); - } diff --git a/Unmapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch b/Unmapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch deleted file mode 100644 index b5584efc91..0000000000 --- a/Unmapped-Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 19:36:55 -0400 -Subject: [PATCH] Don't allow null UUID's for chat - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -index fefcacf27d71c67403555502685a992a5a706099..267e1baeaaed83befc7f6d6445a9416f7b8dfc0f 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -@@ -3,6 +3,7 @@ package net.minecraft.network.protocol.game; - - import java.io.IOException; - import java.util.UUID; -+import net.minecraft.SystemUtils; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.chat.ChatMessageType; - import net.minecraft.network.chat.IChatBaseComponent; -@@ -21,7 +22,7 @@ public class PacketPlayOutChat implements Packet { - public PacketPlayOutChat(IChatBaseComponent ichatbasecomponent, ChatMessageType chatmessagetype, UUID uuid) { - this.a = ichatbasecomponent; - this.b = chatmessagetype; -- this.c = uuid; -+ this.c = uuid != null ? uuid : SystemUtils.getNullUUID(); // Paper - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch b/Unmapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch deleted file mode 100644 index f63ad3aa32..0000000000 --- a/Unmapped-Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 19:08:41 -0400 -Subject: [PATCH] Improve Legacy Component serialization size - -Don't constantly send format: false for all formatting options when parent already -has it false - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -index 666af6cc91bd12ba5d5a846d663a5aabf861fbc4..189a416bd033c9ff390d359aa19cec515d0461e4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -@@ -46,6 +46,7 @@ public final class CraftChatMessage { - // Separate pattern with no group 3, new lines are part of previous string - private static final Pattern INCREMENTAL_PATTERN_KEEP_NEWLINES = Pattern.compile("(" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + "[0-9a-fk-orx])|((?:(?:https?):\\/\\/)?(?:[-\\w_\\.]{2,}\\.[a-z]{2,4}.*?(?=[\\.\\?!,;:]?(?:[" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + " ]|$))))", Pattern.CASE_INSENSITIVE); - // ChatColor.b does not explicitly reset, its more of empty -+ private static final ChatModifier EMPTY = ChatModifier.a.setItalic(false); // Paper - OBFHELPER - private static final ChatModifier RESET = ChatModifier.a.setBold(false).setItalic(false).setUnderline(false).setStrikethrough(false).setRandom(false); - - private final List list = new ArrayList(); -@@ -67,6 +68,7 @@ public final class CraftChatMessage { - Matcher matcher = (keepNewlines ? INCREMENTAL_PATTERN_KEEP_NEWLINES : INCREMENTAL_PATTERN).matcher(message); - String match = null; - boolean needsAdd = false; -+ boolean hasReset = false; // Paper - while (matcher.find()) { - int groupId = 0; - while ((match = matcher.group(++groupId)) == null) { -@@ -112,7 +114,26 @@ public final class CraftChatMessage { - throw new AssertionError("Unexpected message format"); - } - } else { // Color resets formatting -- modifier = RESET.setColor(format); -+ // Paper start - improve legacy formatting -+ ChatModifier previous = modifier; -+ modifier = (!hasReset ? RESET : EMPTY).setColor(format); -+ hasReset = true; -+ if (previous.isBold()) { -+ modifier = modifier.setBold(false); -+ } -+ if (previous.isItalic()) { -+ modifier = modifier.setItalic(false); -+ } -+ if (previous.isRandom()) { -+ modifier = modifier.setRandom(false); -+ } -+ if (previous.isStrikethrough()) { -+ modifier = modifier.setStrikethrough(false); -+ } -+ if (previous.isUnderlined()) { -+ modifier = modifier.setUnderline(false); -+ } -+ // Paper end - } - needsAdd = true; - break; diff --git a/Unmapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch b/Unmapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch deleted file mode 100644 index 8ba6c36f4a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Jun 2020 03:26:17 -0400 -Subject: [PATCH] Support old UUID format for NBT - -We have stored UUID in plenty of places that did not get DFU'd - -So just look for old format and load it if it exists. - -diff --git a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -index 0560d115288c67e46d921ce529e603f424e601f5..50515cd9287505fcc8ab52e47393fb1dc771bfc3 100644 ---- a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -+++ b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -@@ -41,6 +41,11 @@ public final class GameProfileSerializer { - s = nbttagcompound.getString("Name"); - } - -+ // Paper start - support string UUID's -+ if (nbttagcompound.hasKeyOfType("Id", 8)) { -+ uuid = UUID.fromString(nbttagcompound.getString("Id")); -+ } -+ // Paper end - if (nbttagcompound.b("Id")) { - uuid = nbttagcompound.a("Id"); - } -diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -index 77afbaad5b2cb8d912f5404fcbd3a0970490f4f3..945df83d4a2170cdcc29cb6d7b9f0f5f3940cb96 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -@@ -142,6 +142,12 @@ public class NBTTagCompound implements NBTBase { - - public void setUUID(String prefix, UUID uuid) { a(prefix, uuid); } // Paper - OBFHELPER - public void a(String s, UUID uuid) { -+ // Paper start - support old format -+ if (this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99)) { -+ this.map.remove(s + "Most"); -+ this.map.remove(s + "Least"); -+ } -+ // Paper end - this.map.put(s, GameProfileSerializer.a(uuid)); - } - -@@ -151,11 +157,21 @@ public class NBTTagCompound implements NBTBase { - */ - public UUID getUUID(String prefix) { return a(prefix); } // Paper - OBFHELPER - public UUID a(String s) { -+ // Paper start - support old format -+ if (!hasKeyOfType(s, 11) && this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99)) { -+ return new UUID(this.getLong(s + "Most"), this.getLong(s + "Least")); -+ } -+ // Paper end - return GameProfileSerializer.a(this.get(s)); - } - - public final boolean hasUUID(String s) { return this.b(s); } // Paper - OBFHELPER - public boolean b(String s) { -+ // Paper start - support old format -+ if (this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99)) { -+ return true; -+ } -+ // Paper end - NBTBase nbtbase = this.get(s); - - return nbtbase != null && nbtbase.b() == NBTTagIntArray.a && ((NBTTagIntArray) nbtbase).getInts().length == 4; diff --git a/Unmapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch b/Unmapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch deleted file mode 100644 index 7309e30816..0000000000 --- a/Unmapped-Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 1 Jul 2020 03:12:06 -0400 -Subject: [PATCH] Clean up duplicated GameProfile Properties - -We had a bug where we accidently cloned properties resulting in skulls -growing to large sizes and preventing login. - -This now automatically cleans up the extra properties. - -diff --git a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -index 50515cd9287505fcc8ab52e47393fb1dc771bfc3..a654ea9e43c4e7dd9cde1c47d0b07834f47aa751 100644 ---- a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -+++ b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -@@ -60,8 +60,8 @@ public final class GameProfileSerializer { - while (iterator.hasNext()) { - String s1 = (String) iterator.next(); - NBTTagList nbttaglist = nbttagcompound1.getList(s1, 10); -- -- for (int i = 0; i < nbttaglist.size(); ++i) { -+ if (nbttaglist.size() == 0) continue; // Paper - remove duplicate properties -+ for (int i = nbttaglist.size() - 1; i < nbttaglist.size(); ++i) { // Paper - remove duplicate properties - NBTTagCompound nbttagcompound2 = nbttaglist.getCompound(i); - String s2 = nbttagcompound2.getString("Value"); - -@@ -247,7 +247,7 @@ public final class GameProfileSerializer { - Optional optional = iblockstate.b(nbttagcompound.getString(s)); - - if (optional.isPresent()) { -- return (IBlockDataHolder) s0.set(iblockstate, (Comparable) optional.get()); -+ return s0.set(iblockstate, optional.get()); // Paper - decompile error - } else { - GameProfileSerializer.LOGGER.warn("Unable to read property: {} with value: {} for blockstate: {}", s, nbttagcompound.getString(s), nbttagcompound1.toString()); - return s0; -@@ -277,8 +277,8 @@ public final class GameProfileSerializer { - return nbttagcompound; - } - -- private static > String a(IBlockState iblockstate, Comparable comparable) { -- return iblockstate.a(comparable); -+ private static > String a(IBlockState iblockstate, Comparable comparable) {// Paper - decompile error -+ return iblockstate.a((T) comparable);// Paper - decompile error - } - - public static NBTTagCompound a(DataFixer datafixer, DataFixTypes datafixtypes, NBTTagCompound nbttagcompound, int i) { -diff --git a/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java b/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java -index 70207d1ca5b971f829911b1231160f4664062da0..47eed24fa28db8c12ce98b6b72ca1671e13e9f52 100644 ---- a/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java -+++ b/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java -@@ -59,6 +59,18 @@ public class ItemSkullPlayer extends ItemBlockWallable { - return true; - } else { - // CraftBukkit start -+ // Paper start - clean up old duplicated properties -+ NBTTagCompound properties = nbttagcompound.getCompound("SkullOwner").getCompound("Properties"); -+ for (String key : properties.getKeys()) { -+ net.minecraft.nbt.NBTTagList values = properties.getList(key, 10); -+ if (values.size() > 1) { -+ net.minecraft.nbt.NBTBase texture = values.get(values.size() - 1); -+ values = new net.minecraft.nbt.NBTTagList(); -+ values.add(texture); -+ properties.set(key, values); -+ } -+ } -+ // Paper end - net.minecraft.nbt.NBTTagList textures = nbttagcompound.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts - for (int i = 0; i < textures.size(); i++) { - if (textures.get(i) instanceof NBTTagCompound && !((NBTTagCompound) textures.get(i)).hasKeyOfType("Signature", 8) && ((NBTTagCompound) textures.get(i)).getString("Value").trim().isEmpty()) { diff --git a/Unmapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch b/Unmapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch deleted file mode 100644 index 025b86e719..0000000000 --- a/Unmapped-Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 1 Jul 2020 04:50:22 -0400 -Subject: [PATCH] Convert legacy attributes in Item Meta - - -diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -index 43fa8d3c573540682fc87ee2bf8d61ba80d3732d..673948947bd918c1dbb6c4c99486b4200e3c09fe 100644 ---- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -@@ -13,6 +13,20 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; - public class CraftAttributeMap implements Attributable { - - private final AttributeMapBase handle; -+ // Paper start - convert legacy attributes -+ private static final com.google.common.collect.ImmutableMap legacyNMS = com.google.common.collect.ImmutableMap.builder().put("generic.maxHealth", "generic.max_health").put("Max Health", "generic.max_health").put("zombie.spawnReinforcements", "zombie.spawn_reinforcements").put("Spawn Reinforcements Chance", "zombie.spawn_reinforcements").put("horse.jumpStrength", "horse.jump_strength").put("Jump Strength", "horse.jump_strength").put("generic.followRange", "generic.follow_range").put("Follow Range", "generic.follow_range").put("generic.knockbackResistance", "generic.knockback_resistance").put("Knockback Resistance", "generic.knockback_resistance").put("generic.movementSpeed", "generic.movement_speed").put("Movement Speed", "generic.movement_speed").put("generic.flyingSpeed", "generic.flying_speed").put("Flying Speed", "generic.flying_speed").put("generic.attackDamage", "generic.attack_damage").put("generic.attackKnockback", "generic.attack_knockback").put("generic.attackSpeed", "generic.attack_speed").put("generic.armorToughness", "generic.armor_toughness").build(); -+ -+ public static String convertIfNeeded(String nms) { -+ if (nms == null) { -+ return null; -+ } -+ nms = legacyNMS.getOrDefault(nms, nms); -+ if (!nms.toLowerCase().equals(nms) || nms.indexOf(' ') != -1) { -+ return null; -+ } -+ return nms; -+ } -+ // Paper end - - public CraftAttributeMap(AttributeMapBase handle) { - this.handle = handle; -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 8f8dccd6fb2e49d65383d6e8f3fc5ffbabd2b7a5..8398ac45e988c621b3e059d75101185513ddd9ab 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -481,7 +481,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - - AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); - -- String attributeName = entry.getString(ATTRIBUTES_IDENTIFIER.NBT); -+ String attributeName = CraftAttributeMap.convertIfNeeded(entry.getString(ATTRIBUTES_IDENTIFIER.NBT)); // Paper - if (attributeName == null || attributeName.isEmpty()) { - continue; - } diff --git a/Unmapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch b/Unmapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch deleted file mode 100644 index 67b43bca11..0000000000 --- a/Unmapped-Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Mon, 29 Jun 2020 17:03:06 -0400 -Subject: [PATCH] Remove some streams from structures - -This showed up a lot in the spark profiler, should have a low-medium performance improvement. - -diff --git a/src/main/java/net/minecraft/world/level/StructureManager.java b/src/main/java/net/minecraft/world/level/StructureManager.java -index 6fe276b29aa9fe1b312ef2773484fa780506fded..07dcfd56af1014ad159828dd9ee2d89c2010b9f4 100644 ---- a/src/main/java/net/minecraft/world/level/StructureManager.java -+++ b/src/main/java/net/minecraft/world/level/StructureManager.java -@@ -2,6 +2,7 @@ - package net.minecraft.world.level; - - import com.mojang.datafixers.DataFixUtils; -+import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper - import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.core.BaseBlockPosition; -@@ -12,11 +13,12 @@ import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.IStructureAccess; - import net.minecraft.world.level.levelgen.GeneratorSettings; - import net.minecraft.world.level.levelgen.feature.StructureGenerator; -+import net.minecraft.world.level.levelgen.structure.StructurePiece; - import net.minecraft.world.level.levelgen.structure.StructureStart; - - public class StructureManager { - -- private final GeneratorAccess a; -+ private final GeneratorAccess a; public GeneratorAccess getLevel() { return a; } // Paper - OBFHELPER - private final GeneratorSettings b; - - public StructureManager(GeneratorAccess generatoraccess, GeneratorSettings generatorsettings) { -@@ -42,6 +44,20 @@ public class StructureManager { - }); - } - -+ // Paper start - remove structure streams -+ public java.util.List> getFeatureStarts(SectionPosition sectionPosition, StructureGenerator structureGenerator) { -+ java.util.List> list = new ObjectArrayList<>(); -+ for (Long curLong: getLevel().getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structureGenerator)) { -+ SectionPosition sectionPosition1 = SectionPosition.a(new ChunkCoordIntPair(curLong), 0); -+ StructureStart structurestart = a(sectionPosition1, structureGenerator, getLevel().getChunkAt(sectionPosition1.a(), sectionPosition1.c(), ChunkStatus.STRUCTURE_STARTS)); -+ if (structurestart != null && structurestart.e()) { -+ list.add(structurestart); -+ } -+ } -+ return list; -+ } -+ // Paper end -+ - @Nullable - public StructureStart a(SectionPosition sectionposition, StructureGenerator structuregenerator, IStructureAccess istructureaccess) { - return istructureaccess.a(structuregenerator); -@@ -60,13 +76,21 @@ public class StructureManager { - } - - public StructureStart a(BlockPosition blockposition, boolean flag, StructureGenerator structuregenerator) { -- return (StructureStart) DataFixUtils.orElse(this.a(SectionPosition.a(blockposition), structuregenerator).filter((structurestart) -> { -- return structurestart.c().b((BaseBlockPosition) blockposition); -- }).filter((structurestart) -> { -- return !flag || structurestart.d().stream().anyMatch((structurepiece) -> { -- return structurepiece.g().b((BaseBlockPosition) blockposition); -- }); -- }).findFirst(), StructureStart.a); -+ // Paper start - remove structure streams -+ for (StructureStart structurestart : getFeatureStarts(SectionPosition.a(blockposition), structuregenerator)) { -+ if (structurestart.c().b(blockposition)) { -+ if (!flag) { -+ return structurestart; -+ } -+ for (StructurePiece structurepiece : structurestart.d()) { -+ if (structurepiece.g().b(blockposition)) { -+ return structurestart; -+ } -+ } -+ } -+ } -+ return StructureStart.a; -+ // Paper end - } - - // Spigot start -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -index 7147cdda756ccb3d4f6880802128f68601783883..15096a9c2719b8b4c099f62d0a1c808e56b63a8e 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -@@ -39,6 +39,7 @@ import net.minecraft.world.level.levelgen.WorldGenStage; - import net.minecraft.world.level.levelgen.feature.StructureGenerator; - import net.minecraft.world.level.levelgen.feature.WorldGenFeatureConfigured; - import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; -+import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.surfacebuilders.WorldGenSurfaceComposite; - import net.minecraft.world.level.levelgen.synth.NoiseGenerator3; - import net.minecraft.world.level.material.Fluid; -@@ -238,9 +239,11 @@ public final class BiomeBase { - int l1 = j1 << 4; - - try { -- structuremanager.a(SectionPosition.a(blockposition), structuregenerator).forEach((structurestart) -> { -- structurestart.a(regionlimitedworldaccess, structuremanager, chunkgenerator, seededrandom, new StructureBoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkCoordIntPair(i1, j1)); -- }); -+ // Paper start - remove structure streams -+ for (StructureStart structureStart : structuremanager.getFeatureStarts(SectionPosition.a(blockposition), structuregenerator)) { -+ structureStart.a(regionlimitedworldaccess, structuremanager, chunkgenerator, seededrandom, new StructureBoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkCoordIntPair(i1, j1)); -+ } -+ // Paper end - } catch (Exception exception) { - CrashReport crashreport = CrashReport.a(exception, "Feature placement"); - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -index 700b32322e8d0fbb8ec2824e50a340be16b48f81..369fb0bda22f02e76b901b6eb8990651c53c7577 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -@@ -40,6 +40,7 @@ import net.minecraft.world.level.levelgen.feature.structures.WorldGenFeatureDefi - import net.minecraft.world.level.levelgen.feature.structures.WorldGenFeatureDefinedStructurePoolTemplate; - import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; - import net.minecraft.world.level.levelgen.structure.StructurePiece; -+import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.WorldGenFeaturePillagerOutpostPoolPiece; - import net.minecraft.world.level.levelgen.synth.NoiseGenerator; - import net.minecraft.world.level.levelgen.synth.NoiseGenerator3; -@@ -455,7 +456,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - while (iterator.hasNext()) { - StructureGenerator structuregenerator = (StructureGenerator) iterator.next(); - -- structuremanager.a(SectionPosition.a(chunkcoordintpair, 0), structuregenerator).forEach((structurestart) -> { -+ for (StructureStart structurestart : structuremanager.getFeatureStarts(SectionPosition.a(chunkcoordintpair, 0), structuregenerator)) { // Paper - remove structure streams - Iterator iterator1 = structurestart.d().iterator(); - - while (iterator1.hasNext()) { -@@ -487,7 +488,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - } - } - -- }); -+ } // Paper - remove structure streams - } - - double[][][] adouble = new double[2][this.p + 1][this.o + 1]; diff --git a/Unmapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch b/Unmapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch deleted file mode 100644 index 2e8b227335..0000000000 --- a/Unmapped-Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 1 Jul 2020 18:01:49 -0400 -Subject: [PATCH] Remove streams from classes related villager gossip - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -index 9cc3a18636a356977577076e96cb7be706c61abf..7d34d1157786227ac210edc1595a024ccb61a3e9 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -@@ -9,6 +9,7 @@ import com.mojang.serialization.DynamicOps; - import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper - import it.unimi.dsi.fastutil.objects.ObjectIterator; - import java.util.Arrays; - import java.util.Collection; -@@ -51,8 +52,21 @@ public class Reputation { - }); - } - -+ // Paper start - Remove streams from reputation -+ private List decompress() { -+ List list = new ObjectArrayList<>(); -+ for (Map.Entry entry : getReputations().entrySet()) { -+ for (Reputation.b cur : entry.getValue().decompress(entry.getKey())) { -+ if (cur.a() != 0) -+ list.add(cur); -+ } -+ } -+ return list; -+ } -+ // Paper end -+ - private Collection a(Random random, int i) { -- List list = (List) this.c().collect(Collectors.toList()); -+ List list = decompress(); // Paper - Remove streams from reputation - - if (list.isEmpty()) { - return Collections.emptyList(); -@@ -119,7 +133,7 @@ public class Reputation { - } - - public Dynamic a(DynamicOps dynamicops) { -- return new Dynamic(dynamicops, dynamicops.createList(this.c().map((reputation_b) -> { -+ return new Dynamic(dynamicops, dynamicops.createList(this.decompress().stream().map((reputation_b) -> { - return reputation_b.a(dynamicops); - }).map(Dynamic::getValue))); - } -@@ -144,18 +158,30 @@ public class Reputation { - - public static class a { // Paper - make public - -- private final Object2IntMap a; -+ private final Object2IntMap a; private Object2IntMap getEntries() { return a; } // Paper - OBFHELPER - - public a() { // Paper - make public - update CraftVillager setReputation on change - this.a = new Object2IntOpenHashMap(); - } - - public int a(Predicate predicate) { -- return this.a.object2IntEntrySet().stream().filter((entry) -> { -- return predicate.test(entry.getKey()); -- }).mapToInt((entry) -> { -- return entry.getIntValue() * ((ReputationType) entry.getKey()).g; -- }).sum(); -+ // Paper start - Remove streams from reputation -+ int weight = 0; -+ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { -+ if (predicate.test(entry.getKey())) { -+ weight += entry.getIntValue() * entry.getKey().getWeight(); -+ } -+ } -+ return weight; -+ } -+ -+ public List decompress(UUID uuid) { -+ List list = new ObjectArrayList<>(); -+ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { -+ list.add(new Reputation.b(uuid, entry.getKey(), entry.getIntValue())); -+ } -+ return list; -+ // Paper - end - } - - public Stream a(UUID uuid) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java b/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java -index 89651e6e3bb1cfbb8eb8a120b3c3e553cd831a68..6036476aac4a81152e8b142445041ecdb2d6e5d1 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java -@@ -11,7 +11,7 @@ public enum ReputationType { - MAJOR_NEGATIVE("major_negative", -5, 100, 10, 10), MINOR_NEGATIVE("minor_negative", -1, 200, 20, 20), MINOR_POSITIVE("minor_positive", 1, 200, 1, 5), MAJOR_POSITIVE("major_positive", 5, 100, 0, 100), TRADING("trading", 1, 25, 2, 20); - - public final String f; -- public final int g; -+ public final int g; public int getWeight() { return g; } // Paper - OBFHELPER - public final int h; - public final int i; - public final int j; diff --git a/Unmapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch b/Unmapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch deleted file mode 100644 index 6f1e33b76d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Sat, 6 Jun 2020 18:13:42 +0200 -Subject: [PATCH] Support components in ItemMeta - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 8398ac45e988c621b3e059d75101185513ddd9ab..5c1319a86f6314c1d0a979af34424ee025a8030f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -875,11 +875,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return CraftChatMessage.fromJSONComponent(displayName); - } - -+ // 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(displayName); -+ } -+ // Paper end - @Override - public final void setDisplayName(String name) { - this.displayName = CraftChatMessage.fromStringOrNullToJSON(name); - } - -+ // Paper start -+ @Override -+ public void setDisplayNameComponent(net.md_5.bungee.api.chat.BaseComponent[] component) { -+ this.displayName = net.md_5.bungee.chat.ComponentSerializer.toString(component); -+ } -+ // Paper end - @Override - public boolean hasDisplayName() { - return displayName != null; -@@ -1022,6 +1034,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return this.lore == null ? null : new ArrayList(Lists.transform(this.lore, CraftChatMessage::fromJSONComponent)); - } - -+ // 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(entry) -+ ).collect(java.util.stream.Collectors.toList())); -+ } -+ // Paper end - @Override - public void setLore(List lore) { - if (lore == null || lore.isEmpty()) { -@@ -1036,6 +1056,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -+ // 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 customModelData != null; -@@ -1497,6 +1532,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - - for (Object object : addFrom) { -+ // Paper start - support components -+ if(object instanceof net.md_5.bungee.api.chat.BaseComponent[]) { -+ addTo.add(net.md_5.bungee.chat.ComponentSerializer.toString((net.md_5.bungee.api.chat.BaseComponent[]) object)); -+ } else -+ // Paper end - if (!(object instanceof String)) { - if (object != null) { - throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName()); diff --git a/Unmapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/Unmapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch deleted file mode 100644 index c5d87e17db..0000000000 --- a/Unmapped-Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 3 Jul 2020 15:03:33 -0700 -Subject: [PATCH] Improve EntityTargetLivingEntityEvent for 1.16 mobs - -CraftBukkit has a bug in their implementation and is incorrectly handling forget -Also adds more target reasons for why it forgot target. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java -index ad2e4be7483d39aeb7be3727aba6a5fe89ea9602..05c507270ff5b4c0d684d0fc4a69ee47618cd281 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java -@@ -33,15 +33,15 @@ public class BehaviorAttackTargetForget extends Beha - - protected void a(WorldServer worldserver, E e0, long i) { - if (a((EntityLiving) e0)) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // Paper - } else if (this.c(e0)) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_DIED); // Paper - } else if (this.a(e0)) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_OTHER_LEVEL); // Paper - } else if (!IEntitySelector.f.test(this.b(e0))) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper - } else if (this.b.test(this.b(e0))) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper - } - } - -@@ -65,17 +65,20 @@ public class BehaviorAttackTargetForget extends Beha - return optional.isPresent() && !((EntityLiving) optional.get()).isAlive(); - } - -- private void d(E e0) { -+ private void d(E e0, EntityTargetEvent.TargetReason reason) { - // CraftBukkit start -- EntityLiving old = e0.getBehaviorController().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); -- EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(e0, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); -+ // Paper start - fix this event -+ //EntityLiving old = e0.getBehaviorController().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); -+ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(e0, null, reason); - if (event.isCancelled()) { - return; - } -- if (event.getTarget() != null) { -+ // comment out, bad logic - bad -+ /*if (event.getTarget() != null) { - e0.getBehaviorController().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); - return; -- } -+ }*/ -+ // Paper end - // CraftBukkit end - e0.getBehaviorController().removeMemory(MemoryModuleType.ATTACK_TARGET); - } diff --git a/Unmapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch b/Unmapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch deleted file mode 100644 index f5fdce42cd..0000000000 --- a/Unmapped-Spigot-Server-Patches/0519-Add-entity-liquid-API.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jul 2020 18:11:43 -0500 -Subject: [PATCH] Add entity liquid API - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a6df453acadccc6500cec0ac816ec4d1e35adad7..f5bb9313a249bfd4e63ab77e19cfd6f997d22fb1 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1166,12 +1166,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.inWater; - } - -- private boolean isInRain() { -+ public boolean isInRain() { // Paper - private -> public - BlockPosition blockposition = this.getChunkCoordinates(); - - return this.world.isRainingAt(blockposition) || this.world.isRainingAt(new BlockPosition((double) blockposition.getX(), this.getBoundingBox().maxY, (double) blockposition.getZ())); - } - -+ public final boolean isInBubbleColumn() { return k(); } // Paper - OBFHELPER - private boolean k() { - return this.world.getType(this.getChunkCoordinates()).a(Blocks.BUBBLE_COLUMN); - } -@@ -1185,6 +1186,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.isInWater() || this.isInRain() || this.k(); - } - -+ public final boolean isInWaterOrBubbleColumn() { return aH(); } // Paper - OBFHELPER - public boolean aH() { - return this.isInWater() || this.k(); - } -@@ -1327,6 +1329,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.O == tag; - } - -+ public final boolean isInLava() { return aQ(); } // Paper - OBFHELPER - public boolean aQ() { - return !this.justCreated && this.M.getDouble(TagsFluid.LAVA) > 0.0D; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 266b2cbd6bfaf10743929a1eeb9732a5d1fb4c62..387f6f6fa9bbb1cce544cfb907f68c7993752dd7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1137,5 +1137,29 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { - return getHandle().spawnReason; - } -+ -+ public boolean isInRain() { -+ return getHandle().isInRain(); -+ } -+ -+ public boolean isInBubbleColumn() { -+ return getHandle().isInBubbleColumn(); -+ } -+ -+ public boolean isInWaterOrRain() { -+ return getHandle().isInWaterOrRain(); -+ } -+ -+ public boolean isInWaterOrBubbleColumn() { -+ return getHandle().isInWaterOrBubbleColumn(); -+ } -+ -+ public boolean isInWaterOrRainOrBubbleColumn() { -+ return getHandle().isInWaterOrRainOrBubble(); -+ } -+ -+ public boolean isInLava() { -+ return getHandle().isInLava(); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch b/Unmapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch deleted file mode 100644 index 2398718e40..0000000000 --- a/Unmapped-Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 1 Jul 2020 11:57:40 -0500 -Subject: [PATCH] Update itemstack legacy name and lore - - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index b88aec3b97d43018cf2733bad069a90338aa98cb..800d10db92a956d3ca8a3d569d12862f36044ee9 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -27,6 +27,7 @@ import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; -+import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.ChatComponentUtils; - import net.minecraft.network.chat.ChatHoverable; -@@ -137,6 +138,44 @@ public final class ItemStack { - list.sort((Comparator) enchantSorter); // Paper - } catch (Exception ignored) {} - } -+ -+ private void processText() { -+ NBTTagCompound display = getSubTag("display"); -+ if (display != null) { -+ if (display.hasKeyOfType("Name", 8)) { -+ String json = display.getString("Name"); -+ if (json != null && json.contains("\u00A7")) { -+ try { -+ display.set("Name", convert(json)); -+ } catch (JsonParseException jsonparseexception) { -+ display.remove("Name"); -+ } -+ } -+ } -+ if (display.hasKeyOfType("Lore", 9)) { -+ NBTTagList list = display.getList("Lore", 8); -+ for (int index = 0; index < list.size(); index++) { -+ String json = list.getString(index); -+ if (json != null && json.contains("\u00A7")) { // Only try if it has legacy in the unparsed json -+ try { -+ list.set(index, convert(json)); -+ } catch (JsonParseException e) { -+ list.set(index, NBTTagString.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(new ChatComponentText("")))); -+ } -+ } -+ } -+ } -+ } -+ } -+ -+ private NBTTagString convert(String json) { -+ IChatBaseComponent component = IChatBaseComponent.ChatSerializer.jsonToComponent(json); -+ if (component instanceof ChatComponentText && component.getText().contains("\u00A7") && component.getSiblings().isEmpty()) { -+ // Only convert if the root component is a single comp with legacy in it, don't convert already normal components -+ component = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(component.getText())[0]; -+ } -+ return NBTTagString.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(component)); -+ } - // Paper end - - public ItemStack(IMaterial imaterial) { -@@ -182,6 +221,7 @@ public final class ItemStack { - // CraftBukkit start - make defensive copy as this data may be coming from the save thread - this.tag = (NBTTagCompound) nbttagcompound.getCompound("tag").clone(); - processEnchantOrder(this.tag); // Paper -+ processText(); // Paper - this.getItem().b(this.tag); - // CraftBukkit end - } -@@ -665,6 +705,7 @@ public final class ItemStack { - } - } - -+ @Nullable public NBTTagCompound getSubTag(String s) { return b(s); } // Paper - OBFHELPER - @Nullable - public NBTTagCompound b(String s) { - return this.tag != null && this.tag.hasKeyOfType(s, 10) ? this.tag.getCompound(s) : null; diff --git a/Unmapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch b/Unmapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch deleted file mode 100644 index 0810b4a11b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Wyatt Childers -Date: Fri, 3 Jul 2020 14:57:05 -0400 -Subject: [PATCH] Spawn player in correct world on login - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 4c3a2e3cfd60321b3b74d143a32aa5f5d59d7e1e..34b45a6818209245fa5692a83cf4143030057095 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -196,7 +196,18 @@ public abstract class PlayerList { - }String lastKnownName = s; // Paper - // CraftBukkit end - -- if (nbttagcompound != null) { -+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID. -+ if (nbttagcompound != null && nbttagcompound.hasKey("WorldUUIDMost") && nbttagcompound.hasKey("WorldUUIDLeast")) { -+ UUID uid = new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast")); -+ org.bukkit.World bWorld = org.bukkit.Bukkit.getServer().getWorld(uid); -+ if (bWorld != null) { -+ resourcekey = ((CraftWorld) bWorld).getHandle().getDimensionKey(); -+ } else { -+ resourcekey = World.OVERWORLD; -+ } -+ } else if (nbttagcompound != null) { -+ // Vanilla migration support -+ // Paper end - DataResult dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, nbttagcompound.get("Dimension"))); - Logger logger = PlayerList.LOGGER; - diff --git a/Unmapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch b/Unmapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch deleted file mode 100644 index a94b9bff00..0000000000 --- a/Unmapped-Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 3 Jul 2020 11:58:56 -0500 -Subject: [PATCH] Add PrepareResultEvent - -Adds a new event for all crafting stations that generate a result slot item - -Anvil, Grindstone and Smithing now extend this event - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index e9733fd9dac89d31dbad391cb22a8c84216045db..e7c29d194d5c3e3b1b79228758f7a3d8aa060fbd 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -142,6 +142,7 @@ public abstract class Container { - return nonnulllist; - } - -+ public final void notifyListeners() { this.c(); } // Paper - OBFHELPER - public void c() { - int i; - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -index ff618bbb3fc4acfce51f5e5e6a504a63e9ad77cd..ae5674ae9c539720a657838a640050cd3b4dc5b5 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -@@ -307,6 +307,7 @@ public class ContainerAnvil extends ContainerAnvilAbstract { - } - - this.e(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java -index 949042d4e4a1a63c0477704265fe32c371543e8c..9d47f2253a8adbcecbbe3d8a0a42e62f1dac1408 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java -@@ -71,6 +71,7 @@ public abstract class ContainerAnvilAbstract extends Container { - super.a(iinventory); - if (iinventory == this.repairInventory) { - this.e(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerCartography.java b/src/main/java/net/minecraft/world/inventory/ContainerCartography.java -index ce3c22d6f05703874eedf634331ea92ef4c039bf..031e75dc1f3dd6fc1cee684e8e7a105b3e402127 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerCartography.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerCartography.java -@@ -148,6 +148,7 @@ public class ContainerCartography extends Container { - this.a(itemstack, itemstack1, itemstack2); - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - private void a(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2) { -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -index fad7355a549aef811bca43be198af3d1c0a53980..1d5dcbbd3870eb8e1013a97f6ce882bfc096bf95 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -@@ -157,6 +157,7 @@ public class ContainerGrindstone extends Container { - super.a(iinventory); - if (iinventory == this.craftInventory) { - this.e(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -index 350a9b6525a95a00e72e836f1cc9e1a6b99fdd7a..7980930cc712e37a788f894bf2d2ee2b1cfc1196 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -@@ -190,7 +190,8 @@ public class ContainerLoom extends Container { - } - - this.j(); -- this.c(); -+ //this.c(); // Paper - done below -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 3); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java b/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java -index 1cc0ba5b8f182ac5105d2dc493463055e32a52e5..594cbd23c5d8ee2aa88106a1f0a79db0c8ba83a3 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java -@@ -79,6 +79,7 @@ public class ContainerSmithing extends ContainerAnvilAbstract { - // CraftBukkit end - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -index cfcb2469569edd51bbb74ca8d7a35a1ec0ecb434..1589d9ca201d386d11d9fd57fa8ba6848bae215c 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -@@ -156,6 +156,7 @@ public class ContainerStonecutter extends Container { - this.a(iinventory, itemstack); - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 1); // Paper - } - - private void a(IInventory iinventory, ItemStack itemstack) { -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index d620d3e7c023786d1b7411399a05a75028a404cc..55619fbc3fdb9393d7c47a23dc337b06ce4495d6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1534,19 +1534,44 @@ public class CraftEventFactory { - return event; - } - -- public static PrepareAnvilEvent callPrepareAnvilEvent(InventoryView view, ItemStack item) { -- PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item).clone()); -- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); -+ // Paper start - disable this method, handled below -+ public static void callPrepareAnvilEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult -+ PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone -+ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // disable event - event.getInventory().setItem(2, event.getResult()); -- return event; -+ //return event; // Paper - } -+ // Paper end - -- public static PrepareSmithingEvent callPrepareSmithingEvent(InventoryView view, ItemStack item) { -- PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item).clone()); -- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); -+ // Paper start - disable this method, handled in callPrepareResultEvent -+ public static void callPrepareSmithingEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult -+ PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone -+ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // Paper - disable event - event.getInventory().setItem(2, event.getResult()); -- return event; -+ //return event; // Paper - } -+ // Paper end -+ -+ // Paper start - support specific overrides for prepare result -+ public static void callPrepareResultEvent(Container container, int resultSlot) { -+ com.destroystokyo.paper.event.inventory.PrepareResultEvent event; -+ InventoryView view = container.getBukkitView(); -+ org.bukkit.inventory.ItemStack origItem = view.getTopInventory().getItem(resultSlot); -+ CraftItemStack result = origItem != null ? CraftItemStack.asCraftCopy(origItem) : null; -+ if (view.getTopInventory() instanceof org.bukkit.inventory.AnvilInventory) { -+ event = new PrepareAnvilEvent(view, result); -+ } else if (view.getTopInventory() instanceof org.bukkit.inventory.GrindstoneInventory) { -+ event = new com.destroystokyo.paper.event.inventory.PrepareGrindstoneEvent(view, result); -+ } else if (view.getTopInventory() instanceof org.bukkit.inventory.SmithingInventory) { -+ event = new PrepareSmithingEvent(view, result); -+ } else { -+ event = new com.destroystokyo.paper.event.inventory.PrepareResultEvent(view, result); -+ } -+ event.callEvent(); -+ event.getInventory().setItem(resultSlot, event.getResult()); -+ container.notifyListeners(); -+ } -+ // Paper end - - /** - * Mob spawner event. diff --git a/Unmapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch b/Unmapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch deleted file mode 100644 index 85ce652a8e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Wed, 29 Apr 2020 02:10:32 +0200 -Subject: [PATCH] Allow delegation to vanilla chunk gen - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java b/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java -index 60ecd3a92af0f1968b10bb8babfb43147ef568d3..9077b70650d70dd294f53a1ef73e86e28ceaece9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java -@@ -36,7 +36,7 @@ import org.apache.logging.log4j.Logger; - public class ChunkConverter { - - private static final Logger LOGGER = LogManager.getLogger(); -- public static final ChunkConverter a = new ChunkConverter(); -+ public static final ChunkConverter a = new ChunkConverter(); public static ChunkConverter getEmptyConverter() { return a; } // Paper - obfhelper - private static final EnumDirection8[] c = EnumDirection8.values(); - private final EnumSet d; - private final int[][] e; -@@ -322,7 +322,7 @@ public class ChunkConverter { - if ((Integer) iblockdata.get(BlockProperties.an) >= j) { - generatoraccess.setTypeAndData(blockposition, (IBlockData) iblockdata.set(BlockProperties.an, j), 18); - if (i != 7) { -- EnumDirection[] aenumdirection = null.f; -+ EnumDirection[] aenumdirection = f; // Paper - decomp fix - int k = aenumdirection.length; - - for (int l = 0; l < k; ++l) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index a295ab6a7ec79775224381e94e288069f5d311fe..8f44857e9f61c72fa210c16c8bd6b8a6bbdac239 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2033,6 +2033,32 @@ public final class CraftServer implements Server { - return new CraftChunkData(world); - } - -+ // Paper start -+ @Override -+ public ChunkGenerator.ChunkData createVanillaChunkData(World world, int x, int z) { -+ // get empty object -+ CraftChunkData data = (CraftChunkData) createChunkData(world); -+ // do bunch of vanilla shit -+ net.minecraft.server.level.WorldServer nmsWorld = ((CraftWorld) world).getHandle(); -+ net.minecraft.world.level.chunk.ProtoChunk protoChunk = new net.minecraft.world.level.chunk.ProtoChunk(new net.minecraft.world.level.ChunkCoordIntPair(x, z), net.minecraft.world.level.chunk.ChunkConverter.getEmptyConverter(), nmsWorld); -+ List list = new ArrayList<>(); -+ list.add(protoChunk); -+ net.minecraft.server.level.RegionLimitedWorldAccess genRegion = new net.minecraft.server.level.RegionLimitedWorldAccess(nmsWorld, list); -+ // call vanilla generator, one feature after another. Order here is important! -+ net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator = nmsWorld.getChunkProvider().chunkGenerator; -+ if (chunkGenerator instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator) { -+ chunkGenerator = ((org.bukkit.craftbukkit.generator.CustomChunkGenerator) chunkGenerator).delegate; -+ } -+ chunkGenerator.createBiomes(nmsWorld.r().b(IRegistry.ay), protoChunk); -+ chunkGenerator.buildNoise(genRegion, nmsWorld.getStructureManager(), protoChunk); -+ chunkGenerator.buildBase(genRegion, protoChunk); -+ // copy over generated sections -+ data.setRawChunkData(protoChunk.getSections()); -+ // hooray! -+ return data; -+ } -+ // Paper end -+ - @Override - public BossBar createBossBar(String title, BarColor color, BarStyle style, BarFlag... flags) { - return new CraftBossBar(title, color, style, flags); -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index afca0038bb74ac53f07a25729a3c1542e244c6fd..d02281f954aac8d8b65f5d36ec70f0352e4c7cdd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -19,7 +19,7 @@ import org.bukkit.material.MaterialData; - */ - public final class CraftChunkData implements ChunkGenerator.ChunkData { - private final int maxHeight; -- private final ChunkSection[] sections; -+ private ChunkSection[] sections; // Paper - remove final - private Set tiles; - private World world; // Paper - Anti-Xray - Add world - -@@ -168,6 +168,12 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - return sections; - } - -+ // Paper start -+ public void setRawChunkData(ChunkSection[] sections) { -+ this.sections = sections; -+ } -+ // Paper end -+ - Set getTiles() { - return tiles; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -index 7ce7e13032fe43b8998410937d07bfffa6f01527..fb7f68887efb1de8ff9167dd110fcb52627e9206 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -@@ -33,7 +33,7 @@ import org.bukkit.generator.ChunkGenerator.ChunkData; - - public class CustomChunkGenerator extends InternalChunkGenerator { - -- private final net.minecraft.world.level.chunk.ChunkGenerator delegate; -+ public final net.minecraft.world.level.chunk.ChunkGenerator delegate; // Paper - public - private final ChunkGenerator generator; - private final WorldServer world; - private final Random random = new Random(); diff --git a/Unmapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/Unmapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch deleted file mode 100644 index 20d87b812e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 5 Jul 2020 14:59:31 -0400 -Subject: [PATCH] Don't check chunk for portal on world gen entity add - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 13896da2194cab683782504291ede6f135ca7279..60dfa764898b59b60aec2da9580a80634e624dbe 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3041,7 +3041,7 @@ public abstract class EntityLiving extends Entity { - Entity entity = this.getVehicle(); - - super.stopRiding(suppressCancellation); // Paper - suppress -- if (entity != null && entity != this.getVehicle() && !this.world.isClientSide) { -+ if (entity != null && entity != this.getVehicle() && !this.world.isClientSide && entity.valid) { // Paper - don't process on world gen - this.a(entity); - } - diff --git a/Unmapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch b/Unmapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch deleted file mode 100644 index 267d81608f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Sun, 5 Jul 2020 22:38:18 -0400 -Subject: [PATCH] Optimize NetworkManager Exception Handling - - -diff --git a/src/main/java/net/minecraft/network/EnumProtocol.java b/src/main/java/net/minecraft/network/EnumProtocol.java -index a892521db1197369bf6363bd2f5da24bf53643ab..46d8471ba98a5f2c659d35dd86c4c20c67f1ceac 100644 ---- a/src/main/java/net/minecraft/network/EnumProtocol.java -+++ b/src/main/java/net/minecraft/network/EnumProtocol.java -@@ -286,6 +286,7 @@ public enum EnumProtocol { - - @Nullable - public Packet a(int i) { -+ if (i < 0 || i >= this.b.size()) return null; // Paper - Supplier> supplier = (Supplier) this.b.get(i); - - return supplier != null ? (Packet) supplier.get() : null; -diff --git a/src/main/java/net/minecraft/network/PacketSplitter.java b/src/main/java/net/minecraft/network/PacketSplitter.java -index 2c7de7ab6da2106394ec668cd7cb9be1f8dabeb3..e81bfd35b9a745eeb1457ceda5fda320654bd89a 100644 ---- a/src/main/java/net/minecraft/network/PacketSplitter.java -+++ b/src/main/java/net/minecraft/network/PacketSplitter.java -@@ -9,11 +9,21 @@ import java.util.List; - - public class PacketSplitter extends ByteToMessageDecoder { - -+ private final byte[] lenBuf = new byte[3]; // Paper - public PacketSplitter() {} - - protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { -+ // Paper start - if channel is not active just discard the packet -+ if (!channelhandlercontext.channel().isActive()) { -+ bytebuf.skipBytes(bytebuf.readableBytes()); -+ return; -+ } -+ // Paper end - bytebuf.markReaderIndex(); -- byte[] abyte = new byte[3]; -+ // Paper start - reuse temporary length buffer -+ byte[] abyte = lenBuf; -+ java.util.Arrays.fill(abyte, (byte) 0); -+ // Paper end - - for (int i = 0; i < abyte.length; ++i) { - if (!bytebuf.isReadable()) { -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index b644c91cecd8a347319dfe8c8923fd05919a9795..4c583593de4dc8ab27b3e1187f4dfe1740ef07a7 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -2,8 +2,10 @@ package net.minecraft.network.protocol; - - import io.netty.channel.ChannelFuture; // Paper - import java.io.IOException; -+import net.minecraft.network.NetworkManager; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.PacketListener; -+import net.minecraft.server.level.EntityPlayer; - - public interface Packet { - -diff --git a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -index e47da20ab8ce4da34755e105bf55d8542fb50138..67d8fe8ad036a9252c774bb6a914c8ec79981876 100644 ---- a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -+++ b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -@@ -1,6 +1,9 @@ - package net.minecraft.network.protocol; - -+import net.minecraft.network.NetworkManager; - import net.minecraft.network.PacketListener; -+import net.minecraft.network.chat.ChatComponentText; -+import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; - import net.minecraft.server.CancelledPacketHandleException; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.thread.IAsyncTaskHandler; -@@ -31,6 +34,21 @@ public class PlayerConnectionUtils { - try (Timing ignored = timing.startTiming()) { // Paper - timings - packet.a(t0); - } // Paper - timings -+ // Paper start -+ catch (Exception e) { -+ NetworkManager networkmanager = t0.a(); -+ if (networkmanager.getPlayer() != null) { -+ LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getName(), networkmanager.getSocketAddress(), e); -+ } else { -+ LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getSocketAddress(), e); -+ } -+ ChatComponentText error = new ChatComponentText("Packet processing error"); -+ networkmanager.sendPacket(new PacketPlayOutKickDisconnect(error), (future) -> { -+ networkmanager.close(error); -+ }); -+ networkmanager.stopReading(); -+ } -+ // Paper end - } else { - PlayerConnectionUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); - } diff --git a/Unmapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch b/Unmapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch deleted file mode 100644 index 650fc02cf8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 6 Jul 2020 18:36:41 -0400 -Subject: [PATCH] Fix Concurrency issue in WeightedList - -if multiple threads from worldgen sort at same time, it will crash. -So make a copy of the list for sorting purposes. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java -index dc926f7e59fa350902d4a24aefc3df3eac7d75db..2d4345de154fb2d31f34695672ebdb4dac31b181 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java -@@ -17,7 +17,7 @@ public class BehaviorGate extends Behavior { - private final Set> b; - private final BehaviorGate.Order c; - private final BehaviorGate.Execution d; -- private final WeightedList> e = new WeightedList<>(); -+ private final WeightedList> e = new WeightedList<>(false); // Paper - don't use a clone - - public BehaviorGate(Map, MemoryStatus> map, Set> set, BehaviorGate.Order behaviorgate_order, BehaviorGate.Execution behaviorgate_execution, List, Integer>> list) { - super(map); -@@ -65,10 +65,9 @@ public class BehaviorGate extends Behavior { - }).forEach((behavior) -> { - behavior.g(worldserver, e0, i); - }); -- Set set = this.b; - BehaviorController behaviorcontroller = e0.getBehaviorController(); - -- set.forEach(behaviorcontroller::removeMemory); -+ this.b.forEach(behaviorcontroller::removeMemory); // Paper - decomp fix - } - - @Override -@@ -115,7 +114,7 @@ public class BehaviorGate extends Behavior { - - private final Consumer> c; - -- private Order(Consumer consumer) { -+ private Order(Consumer> consumer) { // Paper - decomp fix - this.c = consumer; - } - -diff --git a/src/main/java/net/minecraft/util/random/WeightedRandomList.java b/src/main/java/net/minecraft/util/random/WeightedRandomList.java -index f6f8c68ff3642e28901094e8b501fcf8ec2cecd7..1ca9b0595ae9d914d23590ec0b0c2e857c39b250 100644 ---- a/src/main/java/net/minecraft/util/random/WeightedRandomList.java -+++ b/src/main/java/net/minecraft/util/random/WeightedRandomList.java -@@ -6,7 +6,7 @@ import com.mojang.serialization.Codec; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import com.mojang.serialization.DynamicOps; --import com.mojang.serialization.OptionalDynamic; -+ - import java.util.Comparator; - import java.util.List; - import java.util.Random; -@@ -14,26 +14,32 @@ import java.util.stream.Stream; - - public class WeightedList { - -- protected final List> a; -+ protected final List> list; // Paper - decompile conflict - private final Random b; -+ private final boolean isUnsafe; // Paper - -- public WeightedList() { -- this(Lists.newArrayList()); -+ // Paper start - add useClone option -+ public WeightedList() { this(true); } -+ public WeightedList(boolean isUnsafe) { -+ this(Lists.newArrayList(), isUnsafe); - } - -- private WeightedList(List> list) { -+ private WeightedList(List> list) { this(list, true); } -+ private WeightedList(List> list, boolean isUnsafe) { -+ this.isUnsafe = isUnsafe; -+ // Paper end - this.b = new Random(); -- this.a = Lists.newArrayList(list); -+ this.list = Lists.newArrayList(list); // Paper - decompile conflict - } - - public static Codec> a(Codec codec) { -- return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { -- return weightedlist.a; -+ return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { // Paper - decompile conflict -+ return weightedlist.list; // Paper - decompile conflict - }); - } - - public WeightedList a(U u0, int i) { -- this.a.add(new WeightedList.a<>(u0, i)); -+ this.list.add(new WeightedList.a<>(u0, i)); // Paper - decompile conflict - return this; - } - -@@ -42,21 +48,20 @@ public class WeightedList { - } - - public WeightedList a(Random random) { -- this.a.forEach((weightedlist_a) -> { -- weightedlist_a.a(random.nextFloat()); -- }); -- this.a.sort(Comparator.comparingDouble((object) -> { -- return ((WeightedList.a) object).c(); -- })); -- return this; -+ // Paper start - make concurrent safe, work off a clone of the list -+ List> list = isUnsafe ? new java.util.ArrayList>(this.list) : this.list; -+ list.forEach((weightedlist_a) -> weightedlist_a.a(random.nextFloat())); -+ list.sort(Comparator.comparingDouble(a::c)); -+ return isUnsafe ? new WeightedList<>(list, isUnsafe) : this; -+ // Paper end - } - - public boolean b() { -- return this.a.isEmpty(); -+ return this.list.isEmpty(); // Paper - decompile conflict - } - - public Stream c() { -- return this.a.stream().map(WeightedList.a::a); -+ return this.list.stream().map(WeightedList.a::a); // Paper - decompile conflict - } - - public U b(Random random) { -@@ -64,7 +69,7 @@ public class WeightedList { - } - - public String toString() { -- return "WeightedList[" + this.a + "]"; -+ return "WeightedList[" + this.list + "]"; // Paper - decompile conflict - } - - public static class a { -@@ -98,11 +103,7 @@ public class WeightedList { - return new Codec>() { - public DataResult, T>> decode(DynamicOps dynamicops, T t0) { - Dynamic dynamic = new Dynamic(dynamicops, t0); -- OptionalDynamic optionaldynamic = dynamic.get("data"); -- Codec codec1 = codec; -- -- codec.getClass(); -- return optionaldynamic.flatMap(codec1::parse).map((object) -> { -+ return dynamic.get("data").flatMap(codec::parse).map((object) -> { // Paper - decompile error - return new WeightedList.a<>(object, dynamic.get("weight").asInt(1)); - }).map((weightedlist_a) -> { - return Pair.of(weightedlist_a, dynamicops.empty()); diff --git a/Unmapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch b/Unmapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch deleted file mode 100644 index 434cd1b5f5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Wyatt Childers -Date: Sat, 4 Jul 2020 23:07:43 -0400 -Subject: [PATCH] Optimize the advancement data player iteration to be O(N) - rather than O(N^2) - - -diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index 7d37626277823d5db05189c20bb1ebf91aa2a286..e1d3f7e63c731f9376900a86abe17282e9b55ded 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -457,6 +457,16 @@ public class AdvancementDataPlayer { - } - - private void e(Advancement advancement) { -+ // Paper start -+ e(advancement, IterationEntryPoint.ROOT); -+ } -+ private enum IterationEntryPoint { -+ ROOT, -+ ITERATOR, -+ PARENT_OF_ITERATOR -+ } -+ private void e(Advancement advancement, IterationEntryPoint entryPoint) { -+ // Paper end - boolean flag = this.f(advancement); - boolean flag1 = this.h.contains(advancement); - -@@ -472,15 +482,23 @@ public class AdvancementDataPlayer { - } - - if (flag != flag1 && advancement.b() != null) { -- this.e(advancement.b()); -+ // Paper start - If we're not coming from an iterator consider this to be a root entry, otherwise -+ // market that we're entering from the parent of an iterator. -+ this.e(advancement.b(), entryPoint == IterationEntryPoint.ITERATOR ? IterationEntryPoint.PARENT_OF_ITERATOR : IterationEntryPoint.ROOT); - } - -+ // If this is true, we've went through a child iteration, entered the parent, processed the parent -+ // and are about to reprocess the children. Stop processing here to prevent O(N^2) processing. -+ if (entryPoint == IterationEntryPoint.PARENT_OF_ITERATOR) { -+ return; -+ } // Paper end -+ - Iterator iterator = advancement.e().iterator(); - - while (iterator.hasNext()) { - Advancement advancement1 = (Advancement) iterator.next(); - -- this.e(advancement1); -+ this.e(advancement1, IterationEntryPoint.ITERATOR); // Paper - Mark this call as being from iteration - } - - } diff --git a/Unmapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch b/Unmapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch deleted file mode 100644 index 384b4e0382..0000000000 --- a/Unmapped-Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 8 Jul 2020 11:24:30 -0500 -Subject: [PATCH] Fix arrows never despawning MC-125757 - -This forces the despawn counter to start ticking regardless of -state after the arrow has been alive for 200 ticks (10 seconds) -instead of getting stuck in a never despawn state (bubble columns, -etc). - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index ce754e0da047050daa08e5e0564fa399d334c04b..b0e8e9934edbb0cf7ac063e4903452be526afbc7 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -171,6 +171,7 @@ public abstract class EntityArrow extends IProjectile { - - ++this.c; - } else { -+ if (ticksLived > 200) this.tickDespawnCounter(); // Paper - tick despawnCounter regardless after 10 seconds - this.c = 0; - Vec3D vec3d2 = this.getPositionVector(); - -@@ -292,6 +293,7 @@ public abstract class EntityArrow extends IProjectile { - - } - -+ protected final void tickDespawnCounter() { this.h(); } // Paper - OBFHELPER - protected void h() { - ++this.despawnCounter; - if (this.despawnCounter >= (fromPlayer == PickupStatus.CREATIVE_ONLY ? world.paperConfig.creativeArrowDespawnRate : (fromPlayer == PickupStatus.DISALLOWED ? world.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof EntityThrownTrident) ? world.spigotConfig.tridentDespawnRate : world.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? diff --git a/Unmapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch b/Unmapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch deleted file mode 100644 index 2786d49de2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Jul 2020 03:54:28 -0400 -Subject: [PATCH] Thread Safe Vanilla Command permission checking - -Datapacks check this on load and are built concurrently. This was breaking them badly due -to race conditions. - -Plus, .canUse we want to be safe for async anyways. - -diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -index 7ef6c99d2235eed38197aa76bc9553d7efbe52a4..c0fac7369b111e65b896a15848ae22457e5e8914 100644 ---- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java -+++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -@@ -75,10 +75,10 @@ public abstract class CommandNode implements Comparable> { - public synchronized boolean canUse(final S source) { - if (source instanceof CommandListenerWrapper) { - try { -- ((CommandListenerWrapper) source).currentCommand = this; -+ ((CommandListenerWrapper) source).currentCommand.set(this); // Paper - return requirement.test(source); - } finally { -- ((CommandListenerWrapper) source).currentCommand = null; -+ ((CommandListenerWrapper) source).currentCommand.set(null); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -index b5ee789c8dfb7f413ab60902ff3d2ef0cf8273cd..8402af32cc476d7f468842eb4f34c7521d72bcc8 100644 ---- a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -+++ b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -@@ -55,7 +55,7 @@ public class CommandListenerWrapper implements ICompletionProvider, com.destroys - private final ResultConsumer l; - private final ArgumentAnchor.Anchor m; - private final Vec2F n; -- public volatile CommandNode currentCommand; // CraftBukkit -+ public ThreadLocal currentCommand = new ThreadLocal<>(); // CraftBukkit // Paper - - public CommandListenerWrapper(ICommandListener icommandlistener, Vec3D vec3d, Vec2F vec2f, WorldServer worldserver, int i, String s, IChatBaseComponent ichatbasecomponent, MinecraftServer minecraftserver, @Nullable Entity entity) { - this(icommandlistener, vec3d, vec2f, worldserver, i, s, ichatbasecomponent, minecraftserver, entity, false, (commandcontext, flag, j) -> { -@@ -172,9 +172,11 @@ public class CommandListenerWrapper implements ICompletionProvider, com.destroys - @Override - public boolean hasPermission(int i) { - // CraftBukkit start -- CommandNode currentCommand = this.currentCommand; -+ // Paper start - fix concurrency issue -+ CommandNode currentCommand = this.currentCommand.get(); - if (currentCommand != null) { - return hasPermission(i, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); -+ // Paper end - } - // CraftBukkit end - diff --git a/Unmapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch b/Unmapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch deleted file mode 100644 index d87d776d17..0000000000 --- a/Unmapped-Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Jul 2020 19:34:11 -0700 -Subject: [PATCH] Move range check for block placing up - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index a25edac931db8c737c81962bf69233b547d038c7..8f3dd1493f3a8121376f79632b3941cf642219a7 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1663,15 +1663,19 @@ public class PlayerConnection implements PacketListenerPlayIn { - BlockPosition blockposition = movingobjectpositionblock.getBlockPosition(); - EnumDirection enumdirection = movingobjectpositionblock.getDirection(); - -+ // Paper start - move check up -+ Location eyeLoc = this.getPlayer().getEyeLocation(); -+ double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); -+ if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { -+ return; -+ } -+ // Paper end - move check up -+ - this.player.resetIdleTimer(); - if (blockposition.getY() < this.minecraftServer.getMaxBuildHeight()) { - if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.a((EntityHuman) this.player, blockposition)) { - // CraftBukkit start - Check if we can actually do something over this large a distance -- Location eyeLoc = this.getPlayer().getEyeLocation(); -- double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); -- if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { -- return; -- } -+ // Paper - move check up - this.player.clearActiveItem(); // SPIGOT-4706 - // CraftBukkit end - EnumInteractionResult enuminteractionresult = this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); diff --git a/Unmapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch b/Unmapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch deleted file mode 100644 index 06e7d808b5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 15 Jul 2020 21:42:52 -0400 -Subject: [PATCH] Fix SPIGOT-5989 - -Before this fix, if a player was respawning to a respawn anchor and -the respawn location was modified away from the anchor with the -PlayerRespawnEvent, the anchor would still lose some charge. -This fixes that by checking if the modified spawn location is -still at a respawn anchor. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 34b45a6818209245fa5692a83cf4143030057095..7f5311770f0a461f02039255fbbf1a48df4178f3 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -83,6 +83,7 @@ import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.World; - import net.minecraft.world.level.biome.BiomeManager; -+import net.minecraft.world.level.block.BlockRespawnAnchor; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.border.IWorldBorderListener; -@@ -850,6 +851,7 @@ public abstract class PlayerList { - // Paper start - boolean isBedSpawn = false; - boolean isRespawn = false; -+ boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 - // Paper end - - // CraftBukkit start - fire PlayerRespawnEvent -@@ -860,7 +862,7 @@ public abstract class PlayerList { - Optional optional; - - if (blockposition != null) { -- optional = EntityHuman.getBed(worldserver1, blockposition, f, flag1, flag); -+ optional = EntityHuman.getBed(worldserver1, blockposition, f, flag1, true); // Paper - Fix SPIGOT-5989 - } else { - optional = Optional.empty(); - } -@@ -903,7 +905,12 @@ public abstract class PlayerList { - } - // Spigot End - -- location = respawnEvent.getRespawnLocation(); -+ // Paper start - Fix SPIGOT-5989 -+ if (!location.equals(respawnEvent.getRespawnLocation()) ) { -+ location = respawnEvent.getRespawnLocation(); -+ isLocAltered = true; -+ } -+ // Paper end - if (!flag) entityplayer.reset(); // SPIGOT-4785 - isRespawn = true; // Paper - } else { -@@ -941,8 +948,12 @@ public abstract class PlayerList { - } - // entityplayer1.syncInventory(); - entityplayer1.setHealth(entityplayer1.getHealth()); -- if (flag2) { -- entityplayer1.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.BLOCK_RESPAWN_ANCHOR_DEPLETE, SoundCategory.BLOCKS, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 1.0F, 1.0F)); -+ // Paper start - Fix SPIGOT-5989 -+ if (flag2 && !isLocAltered) { -+ IBlockData data = worldserver1.getType(blockposition); -+ worldserver1.setTypeAndData(blockposition, data.set(BlockRespawnAnchor.a, data.get(BlockRespawnAnchor.a) - 1), 3); -+ entityplayer1.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.BLOCK_RESPAWN_ANCHOR_DEPLETE, SoundCategory.BLOCKS, (double) location.getX(), (double) location.getY(), (double) location.getZ(), 1.0F, 1.0F)); -+ // Paper end - } - // Added from changeDimension - updateClient(entityplayer); // Update health, etc... diff --git a/Unmapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/Unmapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch deleted file mode 100644 index c659730156..0000000000 --- a/Unmapped-Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 10 Jul 2020 13:12:33 -0500 -Subject: [PATCH] Fix SPIGOT-5824 Bukkit world-container is not used - - -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 1732fc552c290d294b68d6f92f2a58d985fbef21..3dcbeec94d86f3b56eaf05676b176f60d711f9cd 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -132,11 +132,20 @@ public class Main { - return; - } - -- File file = (File) optionset.valueOf("universe"); // CraftBukkit -+ // Paper start - fix SPIGOT-5824 -+ File file; -+ File userCacheFile = new File("usercache.json"); -+ if (optionset.has("universe")) { -+ file = (File) optionset.valueOf("universe"); // CraftBukkit -+ userCacheFile = new File(file, "usercache.json"); -+ } else { -+ file = new File(bukkitConfiguration.getString("settings.world-container", ".")); -+ } -+ // Paper end - fix SPIGOT-5824 - YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper - MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); - GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); -- UserCache usercache = new UserCache(gameprofilerepository, new File(file, MinecraftServer.b.getName())); -+ UserCache usercache = new UserCache(gameprofilerepository, userCacheFile); // Paper - only move usercache.json into folder if --universe is used, not world-container - // CraftBukkit start - String s = (String) Optional.ofNullable(optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); - Convertable convertable = Convertable.a(file.toPath()); diff --git a/Unmapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/Unmapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch deleted file mode 100644 index 3c64f53489..0000000000 --- a/Unmapped-Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 10 Jul 2020 12:38:12 -0500 -Subject: [PATCH] Fix SPIGOT-5885 Unable to disable advancements - - -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 3dcbeec94d86f3b56eaf05676b176f60d711f9cd..6818f8496ab76ee6ffc747bd6848b43830ec8914 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -132,6 +132,7 @@ public class Main { - return; - } - -+ org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init - // Paper start - fix SPIGOT-5824 - File file; - File userCacheFile = new File("usercache.json"); diff --git a/Unmapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/Unmapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch deleted file mode 100644 index e8ab744e26..0000000000 --- a/Unmapped-Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 13 Jul 2020 06:22:54 -0700 -Subject: [PATCH] Fix AdvancementDataPlayer leak due from quitting early in - login - -Move the criterion storage to the AdvancementDataPlayer object -itself, so the criterion object stores no references - and thus -needs no cleanup. - -diff --git a/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java b/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java -index c2ee816af000f0c94782d704e6372cd93fd34bb3..c6388223daa26b200dc16cd562bcef19a5a59c8f 100644 ---- a/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java -+++ b/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java -@@ -16,25 +16,25 @@ import net.minecraft.world.level.storage.loot.LootTableInfo; - - public abstract class CriterionTriggerAbstract implements CriterionTrigger { - -- private final Map>> a = Maps.newIdentityHashMap(); -+ //private final Map>> a = Maps.newIdentityHashMap(); // Paper - moved into AdvancementDataPlayer to fix memory leak - - public CriterionTriggerAbstract() {} - - @Override - public final void a(AdvancementDataPlayer advancementdataplayer, CriterionTrigger.a criteriontrigger_a) { -- ((Set) this.a.computeIfAbsent(advancementdataplayer, (advancementdataplayer1) -> { -+ (advancementdataplayer.criterionData.computeIfAbsent(this, (advancementdataplayer1) -> { // Paper - fix AdvancementDataPlayer leak - return Sets.newHashSet(); - })).add(criteriontrigger_a); - } - - @Override - public final void b(AdvancementDataPlayer advancementdataplayer, CriterionTrigger.a criteriontrigger_a) { -- Set> set = (Set) this.a.get(advancementdataplayer); -+ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak - - if (set != null) { - set.remove(criteriontrigger_a); - if (set.isEmpty()) { -- this.a.remove(advancementdataplayer); -+ advancementdataplayer.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak - } - } - -@@ -42,7 +42,7 @@ public abstract class CriterionTriggerAbstract predicate) { - AdvancementDataPlayer advancementdataplayer = entityplayer.getAdvancementData(); -- Set> set = (Set) this.a.get(advancementdataplayer); -+ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak - - if (set != null && !set.isEmpty()) { - LootTableInfo loottableinfo = CriterionConditionEntity.b(entityplayer, entityplayer); -@@ -67,7 +67,7 @@ public abstract class CriterionTriggerAbstract> criterionData = Maps.newIdentityHashMap(); -+ // Paper end - fix advancement data player leakage -+ - public AdvancementDataPlayer(DataFixer datafixer, PlayerList playerlist, AdvancementDataWorld advancementdataworld, File file, EntityPlayer entityplayer) { - this.d = datafixer; - this.e = playerlist; diff --git a/Unmapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/Unmapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch deleted file mode 100644 index 6c0360c411..0000000000 --- a/Unmapped-Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 26 Jul 2020 12:11:39 +0100 -Subject: [PATCH] Add missing strikeLighting call to - World#spigot()#strikeLightningEffect - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 80cd8ce4e70dbb740439ac530a7bc70a7a54cb85..74ee2013a47855cdd1d56a06a2e209776513fd14 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2627,6 +2627,7 @@ public class CraftWorld implements World { - lightning.teleportAndSync( loc.getX(), loc.getY(), loc.getZ() ); - lightning.isEffect = true; - lightning.isSilent = isSilent; -+ world.strikeLightning( lightning ); - return (LightningStrike) lightning.getBukkitEntity(); - } - }; diff --git a/Unmapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch b/Unmapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch deleted file mode 100644 index 9241cffb87..0000000000 --- a/Unmapped-Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 24 Jul 2020 15:56:05 -0700 -Subject: [PATCH] Fix some rails connecting improperly - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -index 61c4a57174237f5f77d841bb2274ace6297db8a4..27573a0334b06f4b6ada672057695d8f8a2bcfc4 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -@@ -71,6 +71,7 @@ public class BlockMinecartDetector extends BlockMinecartTrackAbstract { - - private void a(World world, BlockPosition blockposition, IBlockData iblockdata) { - if (this.canPlace(iblockdata, world, blockposition)) { -+ if (iblockdata.getBlock() != this) { return; } // Paper - not our block, don't do anything - boolean flag = (Boolean) iblockdata.get(BlockMinecartDetector.POWERED); - boolean flag1 = false; - List list = this.a(world, blockposition, EntityMinecartAbstract.class, (Predicate) null); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java -index f65a53347f26affd1ce8d79527a6486e6bf8fbdd..0545dd68ea1f0a27739fac1a358c7def849e6b6a 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java -@@ -62,6 +62,7 @@ public abstract class BlockMinecartTrackAbstract extends Block { - iblockdata = this.a(world, blockposition, iblockdata, true); - if (this.c) { - iblockdata.doPhysics(world, blockposition, this, blockposition, flag); -+ iblockdata = world.getType(blockposition); // Paper - don't desync, update again - } - - return iblockdata; -diff --git a/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java b/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java -index 8a8e3af0290a9483ee59d5fab061a9a9f5613f0a..436cfcde89aa780bcd58150f6167a365d8d955bc 100644 ---- a/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java -+++ b/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java -@@ -12,13 +12,19 @@ import net.minecraft.world.level.block.state.properties.BlockPropertyTrackPositi - - public class MinecartTrackLogic { - -- private final World a; -- private final BlockPosition b; -+ private final World a; public final World getWorld() { return this.a; } // Paper - OBFHELPER -+ private final BlockPosition b; public final BlockPosition getPos() { return this.b; } // Paper - OBFHELPER - private final BlockMinecartTrackAbstract c; -- private IBlockData d; -+ private IBlockData d; public final IBlockData getRailState() { return this.d; } // Paper - OBFHELPER - private final boolean e; - private final List f = Lists.newArrayList(); - -+ // Paper start - prevent desync -+ public boolean isValid() { -+ return this.getWorld().getType(this.getPos()).getBlock() == this.getRailState().getBlock(); -+ } -+ // Paper end - prevent desync -+ - public MinecartTrackLogic(World world, BlockPosition blockposition, IBlockData iblockdata) { - this.a = world; - this.b = blockposition; -@@ -153,6 +159,11 @@ public class MinecartTrackLogic { - } - - private void c(MinecartTrackLogic minecarttracklogic) { -+ // Paper start - prevent desync -+ if (!this.isValid() || !minecarttracklogic.isValid()) { -+ return; -+ } -+ // Paper end - prevent desync - this.f.add(minecarttracklogic.b); - BlockPosition blockposition = this.b.north(); - BlockPosition blockposition1 = this.b.south(); -@@ -347,11 +358,16 @@ public class MinecartTrackLogic { - this.d = (IBlockData) this.d.set(this.c.d(), blockpropertytrackposition1); - if (flag1 || this.a.getType(this.b) != this.d) { - this.a.setTypeAndData(this.b, this.d, 3); -+ // Paper start - prevent desync -+ if (!this.isValid()) { -+ return this; -+ } -+ // Paper end - prevent desync - - for (int i = 0; i < this.f.size(); ++i) { - MinecartTrackLogic minecarttracklogic = this.b((BlockPosition) this.f.get(i)); - -- if (minecarttracklogic != null) { -+ if (minecarttracklogic != null && minecarttracklogic.isValid()) { // Paper - prevent desync - minecarttracklogic.d(); - if (minecarttracklogic.b(this)) { - minecarttracklogic.c(this); -@@ -364,6 +380,6 @@ public class MinecartTrackLogic { - } - - public IBlockData c() { -- return this.d; -+ return this.getWorld().getType(this.getPos()); // Paper - prevent desync - } - } diff --git a/Unmapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/Unmapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch deleted file mode 100644 index f274992699..0000000000 --- a/Unmapped-Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 4 Aug 2020 22:24:15 +0200 -Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections - -I utilized the IDE to convert streams to non streams code, so shouldn't -be any risk of behavior change. Only did minor optimization of the -generated code set to remove unnecessary things. - -I expect us to just drop this patch on next major update and re-apply -it with the IDE again and re-apply the collections optimization. - -Optimize collection by creating a list instead of a set of the key and value. - -This lets us get faster foreach iteration, as well as avoids map lookups on -the values when needed. - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -index 5784be69098805e4d550a0923ac8daa5aada73f9..76e19f3a4ae988f6f3b59763d639fa5e084fa0bf 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -@@ -33,9 +33,12 @@ public class Pathfinder { - this.d.a(); - this.c.a(chunkcache, entityinsentient); - PathPoint pathpoint = this.c.b(); -- Map map = (Map) set.stream().collect(Collectors.toMap((blockposition) -> { -- return this.c.a((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); -- }, Function.identity())); -+ // Paper start - remove streams - and optimize collection -+ List> map = Lists.newArrayList(); -+ for (BlockPosition blockposition : set) { -+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.c.a((double) blockposition.getX(), blockposition.getY(), blockposition.getZ()), blockposition)); -+ } -+ // Paper end - PathEntity pathentity = this.a(pathpoint, map, f, i, f1); - - this.c.a(); -@@ -43,17 +46,17 @@ public class Pathfinder { - } - - @Nullable -- private PathEntity a(PathPoint pathpoint, Map map, float f, int i, float f1) { -- Set set = map.keySet(); -+ private PathEntity a(PathPoint pathpoint, List> list, float f, int i, float f1) { // Paper - optimize collection -+ //Set set = map.keySet(); // Paper - - pathpoint.e = 0.0F; -- pathpoint.f = this.a(pathpoint, set); -+ pathpoint.f = this.a(pathpoint, list); // Paper - optimize collection - pathpoint.g = pathpoint.f; - this.d.a(); - this.d.a(pathpoint); - Set set1 = ImmutableSet.of(); - int j = 0; -- Set set2 = Sets.newHashSetWithExpectedSize(set.size()); -+ List> set2 = Lists.newArrayListWithExpectedSize(list.size()); // Paper - optimize collection - int k = (int) ((float) this.b * f1); - - while (!this.d.e()) { -@@ -65,14 +68,15 @@ public class Pathfinder { - PathPoint pathpoint1 = this.d.c(); - - pathpoint1.i = true; -- Iterator iterator = set.iterator(); -- -- while (iterator.hasNext()) { -- PathDestination pathdestination = (PathDestination) iterator.next(); -+ // Paper start - optimize collection -+ for (int i1 = 0; i1 < list.size(); i1++) { -+ Map.Entry entry = list.get(i1); -+ PathDestination pathdestination = entry.getKey(); - - if (pathpoint1.c((PathPoint) pathdestination) <= (float) i) { - pathdestination.e(); -- set2.add(pathdestination); -+ set2.add(entry); -+ // Paper end - } - } - -@@ -93,7 +97,7 @@ public class Pathfinder { - if (pathpoint2.j < f && (!pathpoint2.c() || f3 < pathpoint2.e)) { - pathpoint2.h = pathpoint1; - pathpoint2.e = f3; -- pathpoint2.f = this.a(pathpoint2, set) * 1.5F; -+ pathpoint2.f = this.a(pathpoint2, list) * 1.5F; // Paper - list instead of set - if (pathpoint2.c()) { - this.d.a(pathpoint2, pathpoint2.e + pathpoint2.f); - } else { -@@ -105,28 +109,29 @@ public class Pathfinder { - } - } - -- Optional optional = !set2.isEmpty() ? set2.stream().map((pathdestination1) -> { -- return this.a(pathdestination1.d(), (BlockPosition) map.get(pathdestination1), true); -- }).min(Comparator.comparingInt(PathEntity::e)) : set.stream().map((pathdestination1) -> { -- return this.a(pathdestination1.d(), (BlockPosition) map.get(pathdestination1), false); -- }).min(Comparator.comparingDouble(PathEntity::n).thenComparingInt(PathEntity::e)); -- -- if (!optional.isPresent()) { -- return null; -- } else { -- PathEntity pathentity = (PathEntity) optional.get(); -- -- return pathentity; -+ // Paper start - remove streams - and optimize collection -+ PathEntity best = null; -+ boolean useSet1 = set2.isEmpty(); -+ Comparator comparator = useSet1 ? Comparator.comparingInt(PathEntity::e) -+ : Comparator.comparingDouble(PathEntity::n).thenComparingInt(PathEntity::e); -+ for (Map.Entry entry : useSet1 ? list : set2) { -+ PathEntity pathEntity = this.a(entry.getKey().d(), entry.getValue(), !useSet1); -+ if (best == null || comparator.compare(pathEntity, best) < 0) -+ best = pathEntity; - } -+ return best; -+ // Paper end - } - -- private float a(PathPoint pathpoint, Set set) { -+ private float a(PathPoint pathpoint, List> list) { // Paper - optimize collection - float f = Float.MAX_VALUE; - - float f1; - -- for (Iterator iterator = set.iterator(); iterator.hasNext(); f = Math.min(f1, f)) { -- PathDestination pathdestination = (PathDestination) iterator.next(); -+ // Paper start - optimize collection -+ for (int i = 0, listSize = list.size(); i < listSize; f = Math.min(f1, f), i++) { // Paper -+ PathDestination pathdestination = list.get(i).getKey(); // Paper -+ // Paper end - - f1 = pathpoint.a(pathdestination); - pathdestination.a(f1, pathpoint); diff --git a/Unmapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch b/Unmapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch deleted file mode 100644 index a7deadb443..0000000000 --- a/Unmapped-Spigot-Server-Patches/0538-Incremental-player-saving.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 9 Aug 2020 08:59:25 +0300 -Subject: [PATCH] Incremental player saving - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index b67ba8f75e4a3358d7c2462918b85b0bf9b5a922..fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -440,4 +440,15 @@ public class PaperConfig { - allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); - set("settings.unsupported-settings.allow-tnt-duplication", null); - } -+ -+ public static int playerAutoSaveRate = -1; -+ public static int maxPlayerAutoSavePerTick = 10; -+ private static void playerAutoSaveRate() { -+ playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1); -+ maxPlayerAutoSavePerTick = getInt("settings.max-player-auto-save-per-tick", -1); -+ if (maxPlayerAutoSavePerTick == -1) { // -1 Automatic / "Recommended" -+ // 10 should be safe for everyone unless you mass spamming player auto save -+ maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index afdbbe62eba7b4f0ad63c5126c6d21488c4e9a7a..5acc6cfa96084728f45cfbec0ff9571e5dd0b844 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1349,9 +1349,15 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down - //MinecraftServer.LOGGER.debug("Autosave started"); // Paper - serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper -+ // Paper start -+ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate; -+ if (playerSaveInterval < 0) { -+ playerSaveInterval = autosavePeriod; -+ } -+ // Paper end - this.methodProfiler.enter("save"); -- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper -- this.playerList.savePlayers(); -+ if (playerSaveInterval > 0) { // Paper -+ this.playerList.savePlayers(playerSaveInterval); // Paper - }// Paper - // Paper start - for (WorldServer world : getWorlds()) { -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 8055172c806f285aa9a9e6de681d03b008fbf785..3908dc27a5cf127ab3c3630da47318da1bf4e3c9 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -176,6 +176,7 @@ import org.bukkit.inventory.MainHand; - public class EntityPlayer extends EntityHuman implements ICrafting { - - private static final Logger LOGGER = LogManager.getLogger(); -+ public long lastSave = MinecraftServer.currentTick; // Paper - public PlayerConnection playerConnection; - public NetworkManager networkManager; // Paper - public final MinecraftServer server; -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7f5311770f0a461f02039255fbbf1a48df4178f3..d3f3dc4ad2c758482b7a8d5c07caa526ce1e3424 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -563,6 +563,7 @@ public abstract class PlayerList { - protected void savePlayerFile(EntityPlayer entityplayer) { - if (!entityplayer.getBukkitEntity().isPersistent()) return; // CraftBukkit - if (!entityplayer.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) -+ entityplayer.lastSave = MinecraftServer.currentTick; // Paper - this.playerFileData.save(entityplayer); - ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) entityplayer.getStatisticManager(); // CraftBukkit - -@@ -1222,10 +1223,21 @@ public abstract class PlayerList { - } - - public void savePlayers() { -+ // Paper start - incremental player saving -+ savePlayers(null); -+ } -+ public void savePlayers(Integer interval) { - MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper -+ int numSaved = 0; -+ long now = MinecraftServer.currentTick; - for (int i = 0; i < this.players.size(); ++i) { -- this.savePlayerFile((EntityPlayer) this.players.get(i)); -+ EntityPlayer entityplayer = this.players.get(i); -+ if (interval == null || now - entityplayer.lastSave >= interval) { -+ this.savePlayerFile(entityplayer); -+ if (interval != null && ++numSaved <= com.destroystokyo.paper.PaperConfig.maxPlayerAutoSavePerTick) { break; } -+ } -+ // Paper end - } - MinecraftTimings.savePlayers.stopTiming(); // Paper - return null; }); // Paper - ensure main diff --git a/Unmapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch b/Unmapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch deleted file mode 100644 index a367d82509..0000000000 --- a/Unmapped-Spigot-Server-Patches/0539-Import-fastutil-classes.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 12 Aug 2020 11:33:04 +0200 -Subject: [PATCH] Import fastutil classes - - -diff --git a/src/main/java/net/minecraft/network/syncher/DataWatcher.java b/src/main/java/net/minecraft/network/syncher/DataWatcher.java -index 3cdae5409989ea4bad8311b0083517b7815caae1..bb09b7be91b488ebc336b2b6f5deafc0ccab27a4 100644 ---- a/src/main/java/net/minecraft/network/syncher/DataWatcher.java -+++ b/src/main/java/net/minecraft/network/syncher/DataWatcher.java -@@ -17,6 +17,7 @@ import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.world.entity.Entity; -+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; // Paper - import org.apache.commons.lang3.ObjectUtils; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -26,7 +27,7 @@ public class DataWatcher { - private static final Logger LOGGER = LogManager.getLogger(); - private static final Map, Integer> b = Maps.newHashMap(); - private final Entity entity; -- private final it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap> entries = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL -+ private final Int2ObjectOpenHashMap> entries = new Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL - // private final ReadWriteLock lock = new ReentrantReadWriteLock(); // Spigot - not required - private boolean f = true; - private boolean g; diff --git a/Unmapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch b/Unmapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch deleted file mode 100644 index c694cf5898..0000000000 --- a/Unmapped-Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Fri, 14 Aug 2020 23:41:19 +0200 -Subject: [PATCH] Don't mark null chunk sections for block updates - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index d6a5a0b17308913a5efd97cd27fabd0825ef68c6..00cebd33101916f29bbc192d531ac0fba31e037b 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -450,6 +450,7 @@ public class PlayerChunk { - this.a(world, blockposition, iblockdata); - } else { - ChunkSection chunksection = chunk.getSections()[sectionposition.getY()]; -+ if (chunksection == null) chunksection = new ChunkSection(sectionposition.getY(), chunk, world, true); // Paper - make a new chunk section if none was found - PacketPlayOutMultiBlockChange packetplayoutmultiblockchange = new PacketPlayOutMultiBlockChange(sectionposition, shortset, chunksection, this.x); - - this.a(packetplayoutmultiblockchange, false); diff --git a/Unmapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch b/Unmapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch deleted file mode 100644 index 835c6e761b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Fri, 14 Aug 2020 23:59:26 +0200 -Subject: [PATCH] Remove armour stand double add to world - - -diff --git a/src/main/java/net/minecraft/world/item/ItemArmorStand.java b/src/main/java/net/minecraft/world/item/ItemArmorStand.java -index dd0dc2a321f2f99cbf1060e47deec0f690d6b948..cd46df5485ebfd597ea72360a27872d46174ee19 100644 ---- a/src/main/java/net/minecraft/world/item/ItemArmorStand.java -+++ b/src/main/java/net/minecraft/world/item/ItemArmorStand.java -@@ -53,7 +53,7 @@ public class ItemArmorStand extends Item { - return EnumInteractionResult.FAIL; - } - -- worldserver.addAllEntities(entityarmorstand); -+ // Paper - moved down - float f = (float) MathHelper.d((MathHelper.g(itemactioncontext.h() - 180.0F) + 22.5F) / 45.0F) * 45.0F; - - entityarmorstand.setPositionRotation(entityarmorstand.locX(), entityarmorstand.locY(), entityarmorstand.locZ(), f, 0.0F); -@@ -63,7 +63,7 @@ public class ItemArmorStand extends Item { - return EnumInteractionResult.FAIL; - } - // CraftBukkit end -- world.addEntity(entityarmorstand); -+ worldserver.addAllEntities(entityarmorstand); // Paper - moved down - world.playSound((EntityHuman) null, entityarmorstand.locX(), entityarmorstand.locY(), entityarmorstand.locZ(), SoundEffects.ENTITY_ARMOR_STAND_PLACE, SoundCategory.BLOCKS, 0.75F, 0.8F); - } - diff --git a/Unmapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch b/Unmapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch deleted file mode 100644 index ba23e86875..0000000000 --- a/Unmapped-Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 15 Aug 2020 08:04:49 -0500 -Subject: [PATCH] Fix MC-187716 Use configured height - - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java -index 9efe3a1dc5da760f0d8b0b39a10e642a53321aa5..ea2b107cddc7c9a6e8b8a0590e3b22a9cd7e34a6 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java -@@ -36,7 +36,7 @@ public class WorldGenSurfaceNether extends WorldGenSurface= 0; --k2) { -+ for (int k2 = k; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.d(k1, k2, l1); - IBlockData iblockdata4 = ichunkaccess.getType(blockposition_mutableblockposition); - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java -index 22926296e66866c7fca13466004c20a16e94dc47..b9523f5611b5b8d786fddcc5fd265e8a2043ab6c 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java -@@ -44,7 +44,7 @@ public abstract class WorldGenSurfaceNetherAbstract extends WorldGenSurface= 0; --k2) { -+ for (int k2 = k; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.d(k1, k2, l1); - IBlockData iblockdata5 = ichunkaccess.getType(blockposition_mutableblockposition); - int l2; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java -index 3bd78b0fc75a536e4e37f5ac67843ff778cd1b5f..a2abfc8816f2dad6c95aa89b443af0d3dec480aa 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java -@@ -34,7 +34,7 @@ public class WorldGenSurfaceNetherForest extends WorldGenSurface= 0; --k2) { -+ for (int k2 = k; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.d(k1, k2, l1); - IBlockData iblockdata3 = worldgensurfaceconfigurationbase.a(); - IBlockData iblockdata4 = ichunkaccess.getType(blockposition_mutableblockposition); diff --git a/Unmapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/Unmapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch deleted file mode 100644 index fb98e08a74..0000000000 --- a/Unmapped-Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mbax -Date: Mon, 17 Aug 2020 12:17:37 -0400 -Subject: [PATCH] Fix regex mistake in CB NBT int deserialization - -The existing regex is too open and allows for the absence of any actual -number data, detecting an NBT entry of just the letter "i" in upper or -lower case. This causes a single-character NBT entry to be processed as -an integer ending in "i", passing an empty String to to Integer.parseInt, -triggering an exception in loading the item. - -This commit forces numbers to be present prior to the ending "i" -letter. - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -index 1c5d62abcb968c2a60034e717aeb6d0df6548b92..83985a5aed4db54880c16228990abb3e495b079a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -@@ -19,7 +19,7 @@ import net.minecraft.nbt.NBTTagString; - public class CraftNBTTagConfigSerializer { - - private static final Pattern ARRAY = Pattern.compile("^\\[.*]"); -- private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)?i", Pattern.CASE_INSENSITIVE); -+ private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)i", Pattern.CASE_INSENSITIVE); // Paper - fix regex - private static final Pattern DOUBLE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", Pattern.CASE_INSENSITIVE); - private static final MojangsonParser MOJANGSON_PARSER = new MojangsonParser(new StringReader("")); - diff --git a/Unmapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch b/Unmapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch deleted file mode 100644 index 1848cd99d4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 23 Jul 2019 20:44:47 -0500 -Subject: [PATCH] Do not let the server load chunks from newer versions - -If the server attempts to load a chunk generated by a newer version of -the game, immediately stop the server to prevent data corruption. - -You can override this functionality at your own peril. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 8e4924cd649c350520cba54a0e1497d5acf089ff..2e5221bc1b9e260e33f2cef2653dc59d05e2680d 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -95,10 +95,24 @@ public class ChunkRegionLoader { - return holder.protoChunk; - } - -+ // Paper start -+ private static final int CURRENT_DATA_VERSION = SharedConstants.getGameVersion().getWorldVersion(); -+ private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion"); -+ // Paper end -+ - public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) { - ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); - // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); -+ // Paper start - Do NOT attempt to load chunks saved with newer versions -+ if (nbttagcompound.hasKeyOfType("DataVersion", 99)) { -+ int dataVersion = nbttagcompound.getInt("DataVersion"); -+ if (!JUST_CORRUPT_IT && dataVersion > CURRENT_DATA_VERSION) { -+ new RuntimeException("Server attempted to load chunk saved with newer version of minecraft! " + dataVersion + " > " + CURRENT_DATA_VERSION).printStackTrace(); -+ System.exit(1); -+ } -+ } -+ // Paper end - WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate - ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate diff --git a/Unmapped-Spigot-Server-Patches/0545-Brand-support.patch b/Unmapped-Spigot-Server-Patches/0545-Brand-support.patch deleted file mode 100644 index eb075ada53..0000000000 --- a/Unmapped-Spigot-Server-Patches/0545-Brand-support.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DigitalRegent -Date: Sat, 11 Apr 2020 13:10:58 +0200 -Subject: [PATCH] Brand support - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 8f3dd1493f3a8121376f79632b3941cf642219a7..d3449dc9eeba0d8022c3a7b0280eaffcd42e7265 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -5,6 +5,7 @@ import com.google.common.primitives.Doubles; - import com.google.common.primitives.Floats; - import com.mojang.brigadier.ParseResults; - import com.mojang.brigadier.StringReader; -+import io.netty.buffer.Unpooled; - import io.netty.util.concurrent.Future; - import io.netty.util.concurrent.GenericFutureListener; - import it.unimi.dsi.fastutil.ints.Int2ShortMap; -@@ -37,6 +38,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.NetworkManager; -+import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.ChatMessageType; -@@ -260,6 +262,8 @@ public class PlayerConnection implements PacketListenerPlayIn { - private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); - private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - -+ private String clientBrandName = null; // Paper - Brand name -+ - public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { - this.minecraftServer = minecraftserver; - this.networkManager = networkmanager; -@@ -3000,6 +3004,8 @@ public class PlayerConnection implements PacketListenerPlayIn { - private static final MinecraftKey CUSTOM_REGISTER = new MinecraftKey("register"); - private static final MinecraftKey CUSTOM_UNREGISTER = new MinecraftKey("unregister"); - -+ private static final MinecraftKey MINECRAFT_BRAND = new MinecraftKey("brand"); // Paper - Brand support -+ - @Override - public void a(PacketPlayInCustomPayload packetplayincustompayload) { - PlayerConnectionUtils.ensureMainThread(packetplayincustompayload, this, this.player.getWorldServer()); -@@ -3027,6 +3033,16 @@ public class PlayerConnection implements PacketListenerPlayIn { - try { - byte[] data = new byte[packetplayincustompayload.data.readableBytes()]; - packetplayincustompayload.data.readBytes(data); -+ -+ // Paper start - Brand support -+ if (packetplayincustompayload.tag.equals(MINECRAFT_BRAND)) { -+ try { -+ this.clientBrandName = new PacketDataSerializer(Unpooled.copiedBuffer(data)).readUTF(256); -+ } catch (StringIndexOutOfBoundsException ex) { -+ this.clientBrandName = "illegal"; -+ } -+ } -+ // Paper end - server.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packetplayincustompayload.tag.toString(), data); - } catch (Exception ex) { - PlayerConnection.LOGGER.error("Couldn\'t dispatch custom payload", ex); -@@ -3036,6 +3052,12 @@ public class PlayerConnection implements PacketListenerPlayIn { - - } - -+ // Paper start - brand support -+ public String getClientBrandName() { -+ return clientBrandName; -+ } -+ // Paper end -+ - public final boolean isDisconnected() { - return (!this.player.joining && !this.networkManager.isConnected()) || this.processedDisconnect; // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0f8d10c2bc7728b58528096fc0686c3aeee623a7..18d7cf6e783843d44715210b7c8db7bf0a5c89ae 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2388,6 +2388,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - // Paper end - }; - -+ // Paper start - brand support -+ @Override -+ public String getClientBrandName() { -+ return getHandle().playerConnection != null ? getHandle().playerConnection.getClientBrandName() : null; -+ } -+ // Paper end -+ - public Player.Spigot spigot() - { - return spigot; diff --git a/Unmapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch b/Unmapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch deleted file mode 100644 index 61129f1906..0000000000 --- a/Unmapped-Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Thu, 20 Aug 2020 19:24:13 -0700 -Subject: [PATCH] Fix MC-99259 Wither Boss Bar doesn't update until - invulnerability period is over - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 174eb12722872182b2d9b54841e5bb57893695a1..30290c0208a4725b2eb0e7764465c354e592e4ee 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -393,8 +393,9 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit - } - -- this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); -+ //this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Moved down - } -+ this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Fix MC-99259 (Boss bar does not update until Wither invulnerability period ends) - } - - public static boolean c(IBlockData iblockdata) { diff --git a/Unmapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch b/Unmapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch deleted file mode 100644 index 5c61d89c86..0000000000 --- a/Unmapped-Spigot-Server-Patches/0547-Fix-MC-197271.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ishland -Date: Sun, 23 Aug 2020 10:57:44 +0200 -Subject: [PATCH] Fix MC-197271 - -This patch only fixes an issue for servers running OpenJ9. - -diff --git a/src/main/java/net/minecraft/data/RegistryGeneration.java b/src/main/java/net/minecraft/data/RegistryGeneration.java -index 25762daca063ff5a422975d7fe64752a2deae163..2c06e3ab167443ac54c27cfe09e279f18a9f7300 100644 ---- a/src/main/java/net/minecraft/data/RegistryGeneration.java -+++ b/src/main/java/net/minecraft/data/RegistryGeneration.java -@@ -48,11 +48,11 @@ public class RegistryGeneration { - public static final IRegistry g = a(IRegistry.aw, () -> { - return ProcessorLists.b; - }); -- public static final IRegistry h = a(IRegistry.ax, WorldGenFeaturePieces::a); -+ public static final IRegistry h = a(IRegistry.ax, () -> WorldGenFeaturePieces.a()); // Paper - MC-197271 - public static final IRegistry WORLDGEN_BIOME = a(IRegistry.ay, () -> { - return BiomeRegistry.a; - }); -- public static final IRegistry j = a(IRegistry.ar, GeneratorSettingBase::i); -+ public static final IRegistry j = a(IRegistry.ar, () -> GeneratorSettingBase.i()); // Paper - MC-197271 - - private static IRegistry a(ResourceKey> resourcekey, Supplier supplier) { - return a(resourcekey, Lifecycle.stable(), supplier); -@@ -66,9 +66,9 @@ public class RegistryGeneration { - MinecraftKey minecraftkey = resourcekey.a(); - - RegistryGeneration.k.put(minecraftkey, supplier); -- IRegistryWritable iregistrywritable = RegistryGeneration.l; -+ IRegistryWritable iregistrywritable = (IRegistryWritable) RegistryGeneration.l; // Paper - decompile fix - -- return (IRegistryWritable) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); -+ return (R) iregistrywritable.a((ResourceKey) resourcekey, r0, lifecycle); // Paper - decompile fix - } - - public static T a(IRegistry iregistry, String s, T t0) { -@@ -76,11 +76,11 @@ public class RegistryGeneration { - } - - public static T a(IRegistry iregistry, MinecraftKey minecraftkey, T t0) { -- return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.f(), minecraftkey), t0, Lifecycle.stable()); -+ return (T) ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.f(), minecraftkey), t0, Lifecycle.stable()); // Paper - decompile fix - } - - public static T a(IRegistry iregistry, int i, ResourceKey resourcekey, T t0) { -- return ((IRegistryWritable) iregistry).a(i, resourcekey, t0, Lifecycle.stable()); -+ return (T) ((IRegistryWritable) iregistry).a(i, resourcekey, t0, Lifecycle.stable()); // Paper - decompile fix - } - - public static void a() {} diff --git a/Unmapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch b/Unmapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch deleted file mode 100644 index fd35ea34e4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 21 Aug 2020 21:05:28 -0400 -Subject: [PATCH] MC-197883: Bandaid decode issue - -Mojang has a mix of type and name in the data sets, but you can only -use one. - -This will retry as name if type is asked for and not found. - -diff --git a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java -index de7d1e5e0319c65775d932144c268c2d55bb7dc7..bd6a0e1b5454e880a4f2a16be7dc8da64b73e11d 100644 ---- a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java -+++ b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java -@@ -48,7 +48,12 @@ public class KeyDispatchCodec extends MapCodec { - - @Override - public DataResult decode(final DynamicOps ops, final MapLike input) { -- final T elementName = input.get(typeKey); -+ // Paper start - bandaid MC-197883 -+ T elementName = input.get(typeKey); -+ if (elementName == null && "type".equals(typeKey)) { -+ elementName = input.get("name"); -+ } -+ // Paper end - if (elementName == null) { - return DataResult.error("Input does not contain a key [" + typeKey + "]: " + input); - } diff --git a/Unmapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch b/Unmapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch deleted file mode 100644 index af8f01de47..0000000000 --- a/Unmapped-Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 22 Aug 2020 23:59:30 +0200 -Subject: [PATCH] Add #setMaxPlayers API - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index d3f3dc4ad2c758482b7a8d5c07caa526ce1e3424..8bd55e3d2b5142081a7dfe1dbbd36f2f995e5856 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -145,7 +145,7 @@ public abstract class PlayerList { - public final WorldNBTStorage playerFileData; - private boolean hasWhitelist; - private final IRegistryCustom.Dimension s; -- protected final int maxPlayers; -+ protected int maxPlayers; public final void setMaxPlayers(int maxPlayers) { this.maxPlayers = maxPlayers; } // Paper - remove final and add setter - private int viewDistance; - private EnumGamemode u; - private boolean v; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 8f44857e9f61c72fa210c16c8bd6b8a6bbdac239..4dceb2d0beb6f91526b101d4947556049a0f3251 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -614,6 +614,13 @@ public final class CraftServer implements Server { - return playerList.getMaxPlayers(); - } - -+ // Paper start -+ @Override -+ public void setMaxPlayers(int maxPlayers) { -+ this.playerList.setMaxPlayers(maxPlayers); -+ } -+ // Paper end -+ - // NOTE: These are dependent on the corresponding call in MinecraftServer - // so if that changes this will need to as well - @Override diff --git a/Unmapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch b/Unmapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch deleted file mode 100644 index 6306ebc1e9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 23 Aug 2020 19:36:22 +0200 -Subject: [PATCH] Add playPickupItemAnimation to LivingEntity - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index fdf4d258dd3e81cf4317ad66334c323be2d88fb2..de12a050739b8d12d268cc9ca496259ea2c46569 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -818,5 +818,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - ((EntityInsentient) getHandle()).getControllerJump().jump(); - } - } -+ -+ @Override -+ public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { -+ getHandle().receive(((CraftItem) item).getHandle(), quantity); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch b/Unmapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch deleted file mode 100644 index 00f9b23e6f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sun, 23 Aug 2020 19:01:04 +0200 -Subject: [PATCH] Don't require FACING data - - -diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java b/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java -index 979b862284ecd0dc504ee8a7018b27ff569b7b85..3d14ec72bb9babdf6b24aca3bde06d8b54815f9d 100644 ---- a/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java -+++ b/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java -@@ -15,20 +15,22 @@ import org.bukkit.event.block.BlockDispenseEvent; - // CraftBukkit end - - public class DispenseBehaviorItem implements IDispenseBehavior { -+ private EnumDirection enumdirection; // Paper - - public DispenseBehaviorItem() {} - - @Override - public final ItemStack dispense(ISourceBlock isourceblock, ItemStack itemstack) { -+ enumdirection = isourceblock.getBlockData().get(BlockDispenser.FACING); // Paper - cache facing direction - ItemStack itemstack1 = this.a(isourceblock, itemstack); - - this.a(isourceblock); -- this.a(isourceblock, (EnumDirection) isourceblock.getBlockData().get(BlockDispenser.FACING)); -+ this.a(isourceblock, enumdirection); // Paper - cache facing direction - return itemstack1; - } - - protected ItemStack a(ISourceBlock isourceblock, ItemStack itemstack) { -- EnumDirection enumdirection = (EnumDirection) isourceblock.getBlockData().get(BlockDispenser.FACING); -+ // Paper - cached enum direction - IPosition iposition = BlockDispenser.a(isourceblock); - ItemStack itemstack1 = itemstack.cloneAndSubtract(1); - diff --git a/Unmapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/Unmapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch deleted file mode 100644 index 99ee434bf4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 22 Aug 2020 23:36:21 +0200 -Subject: [PATCH] Fix SpawnChangeEvent not firing for all use-cases - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index a0670bdd858f59ee5719580625c9f25235e23fc4..70f8fbff2ac825b61c5c9f7c6830de3106e7926c 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1987,12 +1987,14 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - // Paper end - -+ public final void setSpawn(BlockPosition blockposition, float f) { this.a(blockposition, f); } // Paper - OBFHELPER - public void a(BlockPosition blockposition, float f) { - // Paper - configurable spawn radius - BlockPosition prevSpawn = this.getSpawn(); - //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); - - this.worldData.setSpawn(blockposition, f); -+ new org.bukkit.event.world.SpawnChangeEvent(getWorld(), MCUtil.toLocation(this, prevSpawn)).callEvent(); // Paper - if (this.keepSpawnInMemory) { - // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add - this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 74ee2013a47855cdd1d56a06a2e209776513fd14..d3f5a3d4872665b4c52a6cfad1518016919557d0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -389,11 +389,13 @@ public class CraftWorld implements World { - public boolean setSpawnLocation(int x, int y, int z, float angle) { - try { - Location previousLocation = getSpawnLocation(); -- world.worldData.setSpawn(new BlockPosition(x, y, z), angle); -+ world.setSpawn(new BlockPosition(x, y, z), angle); // Paper - use WorldServer#setSpawn - -+ // Paper start - move to nms.World - // Notify anyone who's listening. -- SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); -- server.getPluginManager().callEvent(event); -+ // SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); -+ // server.getPluginManager().callEvent(event); -+ // Paper end - - return true; - } catch (Exception e) { diff --git a/Unmapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch b/Unmapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch deleted file mode 100644 index c49db87041..0000000000 --- a/Unmapped-Spigot-Server-Patches/0553-Add-moon-phase-API.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 16:32:11 +0200 -Subject: [PATCH] Add moon phase API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index d3f5a3d4872665b4c52a6cfad1518016919557d0..76a7889b49a16ddeb8f310d3a79cfee80ad9a1db 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -328,6 +328,11 @@ public class CraftWorld implements World { - public int getPlayerCount() { - return world.players.size(); - } -+ -+ @Override -+ public io.papermc.paper.world.MoonPhase getMoonPhase() { -+ return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); -+ } - // Paper end - - private static final Random rand = new Random(); diff --git a/Unmapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch b/Unmapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch deleted file mode 100644 index f6e166986f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: commandblockguy -Date: Fri, 14 Aug 2020 14:44:14 -0500 -Subject: [PATCH] Prevent headless pistons from being created - -Prevent headless pistons from being created by explosions or tree/mushroom growth. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb..faa1b775e45563b93ac1d5b904938b1f5ad8d80c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -441,6 +441,12 @@ public class PaperConfig { - set("settings.unsupported-settings.allow-tnt-duplication", null); - } - -+ public static boolean allowHeadlessPistons; -+ private static void allowHeadlessPistons() { -+ config.set("settings.unsupported-settings.allow-headless-pistons-readme", "This setting controls if players should be able to create headless pistons."); -+ allowHeadlessPistons = getBoolean("settings.unsupported-settings.allow-headless-pistons", false); -+ } -+ - public static int playerAutoSaveRate = -1; - public static int maxPlayerAutoSavePerTick = 10; - private static void playerAutoSaveRate() { -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 0b3479aae8f7cad7bd0b8b64aa2dead43baf4c56..79008bda42558ea7d28ccf51b66405a3bdb52da7 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -16,6 +16,7 @@ import java.util.Set; - import javax.annotation.Nullable; - import net.minecraft.core.BaseBlockPosition; - import net.minecraft.core.BlockPosition; -+import net.minecraft.core.EnumDirection; - import net.minecraft.core.particles.Particles; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -34,6 +35,8 @@ import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.BlockFireAbstract; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.TileEntity; -+import net.minecraft.world.level.block.piston.BlockPistonExtension; -+import net.minecraft.world.level.block.piston.TileEntityPiston; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.material.Fluid; - import net.minecraft.world.level.storage.loot.LootTableInfo; -@@ -163,6 +166,15 @@ public class Explosion { - - if (f > 0.0F && this.l.a(this, this.world, blockposition, iblockdata, f) && blockposition.getY() < 256 && blockposition.getY() >= 0) { // CraftBukkit - don't wrap explosions - set.add(blockposition); -+ // Paper start - prevent headless pistons from forming -+ if (!com.destroystokyo.paper.PaperConfig.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) { -+ TileEntity extension = this.world.getTileEntity(blockposition); -+ if (extension instanceof TileEntityPiston && ((TileEntityPiston) extension).isHead()) { -+ EnumDirection direction = iblockdata.get(BlockPistonExtension.FACING); -+ set.add(blockposition.shift(direction.opposite())); -+ } -+ } -+ // Paper end - } - - d4 += d0 * 0.30000001192092896D; -diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -index e70c3a8c9075b6c0bc73e6488d784dfe3b86e58d..58c7a52612fe0f5c1e4ddacc0bf93cd81f1286b8 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -@@ -65,6 +65,8 @@ public class TileEntityPiston extends TileEntity implements ITickable { - return this.b; - } - -+ public final boolean isHead() { return this.h(); } // Paper - OBFHELPER -+ - public boolean h() { - return this.g; - } diff --git a/Unmapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch b/Unmapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch deleted file mode 100644 index 6352b44128..0000000000 --- a/Unmapped-Spigot-Server-Patches/0555-Add-BellRingEvent.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Eearslya Sleiarion -Date: Sun, 23 Aug 2020 13:04:02 +0200 -Subject: [PATCH] Add BellRingEvent - -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/net/minecraft/world/level/block/BlockBell.java b/src/main/java/net/minecraft/world/level/block/BlockBell.java -index 687f7acd8254294b568c9adf3e72d02d12551381..24754057bc83577f4854262bbb82db355591270e 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBell.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBell.java -@@ -1,8 +1,11 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.BellRingEvent; -+ - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.stats.StatisticList; -@@ -89,7 +92,7 @@ public class BlockBell extends BlockTileEntity { - boolean flag1 = !flag || this.a(iblockdata, enumdirection, movingobjectpositionblock.getPos().y - (double) blockposition.getY()); - - if (flag1) { -- boolean flag2 = this.a(world, blockposition, enumdirection); -+ boolean flag2 = this.handleBellRing(world, blockposition, enumdirection, entityhuman); // Paper - - if (flag2 && entityhuman != null) { - entityhuman.a(StatisticList.BELL_RING); -@@ -123,6 +126,11 @@ public class BlockBell extends BlockTileEntity { - } - - public boolean a(World world, BlockPosition blockposition, @Nullable EnumDirection enumdirection) { -+ // Paper start - add ringer param -+ return this.handleBellRing(world, blockposition, enumdirection, null); -+ } -+ public boolean handleBellRing(World world, BlockPosition blockposition, @Nullable EnumDirection enumdirection, @Nullable Entity ringer) { -+ // Paper end - TileEntity tileentity = world.getTileEntity(blockposition); - - if (!world.isClientSide && tileentity instanceof TileEntityBell) { -@@ -130,6 +138,7 @@ public class BlockBell extends BlockTileEntity { - enumdirection = (EnumDirection) world.getType(blockposition).get(BlockBell.a); - } - -+ if (!new BellRingEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, blockposition)), ringer == null ? null : ringer.getBukkitEntity()).callEvent()) return false; // Paper - BellRingEvent - ((TileEntityBell) tileentity).a(enumdirection); - world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_BELL_USE, SoundCategory.BLOCKS, 2.0F, 1.0F); - return true; diff --git a/Unmapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch b/Unmapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch deleted file mode 100644 index 2d5c7f12aa..0000000000 --- a/Unmapped-Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 15:47:34 +0200 -Subject: [PATCH] Add zombie targets turtle egg config - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 978062774c1db286bfb9b0ffdef19d880b1f249b..36ecdfce84141ac731b827e469ac842f5c666259 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -668,4 +668,9 @@ public class PaperWorldConfig { - maxLightningFlashDistance = 512; // Vanilla value - } - } -+ -+ public boolean zombiesTargetTurtleEggs = true; -+ private void zombiesTargetTurtleEggs() { -+ zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 3d8d4a43e6cd554b6f1eeafa1c8d43cef877139a..87acbdee03edf8bc35f4b3bcb9b82855ed4a3c33 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -107,7 +107,7 @@ public class EntityZombie extends EntityMonster { - - @Override - protected void initPathfinder() { -- this.goalSelector.a(4, new EntityZombie.a(this, 1.0D, 3)); -+ if (world.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.a(4, new EntityZombie.a(this, 1.0D, 3)); // Paper - this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); - this.m(); diff --git a/Unmapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch b/Unmapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch deleted file mode 100644 index 3b7cd4b59a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0557-Buffer-joins-to-world.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Wed, 19 Aug 2020 05:05:54 +0100 -Subject: [PATCH] Buffer joins to world - -This patch buffers the number of logins which will attempt to join -the world per tick, this attempts to reduce the impact that join floods -has on the server - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index faa1b775e45563b93ac1d5b904938b1f5ad8d80c..545948f20efd6c8dd42140b565af94cd6b52b661 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -457,4 +457,9 @@ public class PaperConfig { - maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; - } - } -+ -+ public static int maxJoinsPerTick; -+ private static void maxJoinsPerTick() { -+ maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); -+ } - } -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index ab70eeaeca222de7de7cab1b3db14b2c4761c3c3..878f879f8d410c428ad8a4c49e0c86c559bc47a9 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -33,6 +33,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutTabComplete; - import net.minecraft.network.protocol.game.PacketPlayOutTitle; - import net.minecraft.server.CancelledPacketHandleException; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.network.LoginListener; - import net.minecraft.server.network.PlayerConnection; -@@ -382,10 +383,22 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - // Paper end - -+ private static final int MAX_PER_TICK = com.destroystokyo.paper.PaperConfig.maxJoinsPerTick; // Paper -+ private static int joinAttemptsThisTick; // Paper -+ private static int currTick; // Paper - public void a() { - this.p(); -+ // Paper start -+ if (currTick != MinecraftServer.currentTick) { -+ currTick = MinecraftServer.currentTick; -+ joinAttemptsThisTick = 0; -+ } -+ // Paper end - if (this.packetListener instanceof LoginListener) { -+ if ( ((LoginListener) this.packetListener).getLoginState() != LoginListener.EnumProtocolState.READY_TO_ACCEPT // Paper -+ || (joinAttemptsThisTick++ < MAX_PER_TICK)) { // Paper - limit the number of joins which can be processed each tick - ((LoginListener) this.packetListener).tick(); -+ } // Paper - } - - if (this.packetListener instanceof PlayerConnection) { -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index ef2aa000932c222e358789fcd2629dd8a46cfe80..f40736a836d6097930b9704246c7077617b1f962 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -422,7 +422,7 @@ public class LoginListener implements PacketLoginInListener { - return new GameProfile(uuid, gameprofile.getName()); - } - -- static enum EnumProtocolState { -+ public enum EnumProtocolState { // Paper - package private -> public - - HELLO, KEY, AUTHENTICATING, NEGOTIATING, READY_TO_ACCEPT, DELAY_ACCEPT, ACCEPTED; - diff --git a/Unmapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch b/Unmapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch deleted file mode 100644 index 4e538c9eb3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch +++ /dev/null @@ -1,1158 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: theosib -Date: Thu, 27 Sep 2018 01:43:35 -0600 -Subject: [PATCH] Optimize redstone algorithm - -Author: theosib -Co-authored-by: egg82 - -Original license: MIT - -This patch implements theosib's redstone algorithms to completely overhaul the way redstone works. -The new algorithms should be many times faster than current vanilla ones. -From the original author's comments, it looks like it shouldn't interfere with any redstone save for very extreme edge-cases. - -Surprisingly, not a lot was touched aside from a few obfuscation helpers and BlockRedstoneWire. -A lot of this code is self-contained in a helper class. - -Aside from making the obvious class/function renames and obfhelpers I didn't need to modify much. -Just added Bukkit's event system and took a few liberties with dead code and comment misspellings. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 36ecdfce84141ac731b827e469ac842f5c666259..02bb85364560784adea47c877c13291c3d016b86 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -673,4 +673,14 @@ public class PaperWorldConfig { - private void zombiesTargetTurtleEggs() { - zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); - } -+ -+ public boolean useEigencraftRedstone = false; -+ private void useEigencraftRedstone() { -+ useEigencraftRedstone = this.getBoolean("use-faster-eigencraft-redstone", false); -+ if (useEigencraftRedstone) { -+ log("Using Eigencraft redstone algorithm by theosib."); -+ } else { -+ log("Using vanilla redstone algorithm."); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..167e0aaec8c2f83856465b7efc9ac9e5f9389d91 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java -@@ -0,0 +1,914 @@ -+package com.destroystokyo.paper.util; -+ -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.ThreadLocalRandom; -+ -+import net.minecraft.core.BlockPosition; -+import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.item.Items; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.BlockRedstoneWire; -+import net.minecraft.world.level.block.state.IBlockData; -+import org.bukkit.event.block.BlockRedstoneEvent; -+ -+import com.google.common.collect.Lists; -+import com.google.common.collect.Maps; -+ -+/** -+ * Used for the faster redstone algorithm. -+ * Original author: theosib -+ * Original license: MIT -+ * -+ * Ported to Paper and updated to 1.13 by egg82 -+ */ -+public class RedstoneWireTurbo { -+ /* -+ * This is Helper class for BlockRedstoneWire. It implements a minimally-invasive -+ * bolt-on accelerator that performs a breadth-first search through redstone wire blocks -+ * in order to more efficiently and deterministically compute new redstone wire power levels -+ * and determine the order in which other blocks should be updated. -+ * -+ * Features: -+ * - Changes to BlockRedstoneWire are very limited, no other classes are affected, and the -+ * choice between old and new redstone wire update algorithms is switchable on-line. -+ * - The vanilla implementation relied on World.notifyNeighborsOfStateChange for redstone -+ * wire blocks to communicate power level changes to each other, generating 36 block -+ * updates per call. This improved implementation propagates power level changes directly -+ * between redstone wire blocks. Redstone wire power levels are therefore computed more quickly, -+ * and block updates are sent only to non-redstone blocks, many of which may perform an -+ * action when informed of a change in redstone power level. (Note: Block updates are not -+ * the same as state changes to redstone wire. Wire block states are updated as soon -+ * as they are computed.) -+ * - Of the 36 block updates generated by a call to World.notifyNeighborsOfStateChange, -+ * 12 of them are obviously redundant (e.g. the west neighbor of the east neighbor). -+ * These are eliminated. -+ * - Updates to redstone wire and other connected blocks are propagated in a breath-first -+ * manner, radiating out from the initial trigger (a block update to a redstone wire -+ * from something other than redstone wire). -+ * - Updates are scheduled both deterministically and in an intuitive order, addressing bug -+ * MC-11193. -+ * - All redstone behavior that used to be locational now works the same in all locations. -+ * - All behaviors of redstone wire that used to be orientational now work the same in all -+ * orientations, as long as orientation can be determined; random otherwise. Some other -+ * redstone components still update directionally (e.g. switches), and this code can't -+ * compensate for that. -+ * - Information that is otherwise computed over and over again or which is expensive to -+ * to compute is cached for faster lookup. This includes coordinates of block position -+ * neighbors and block states that won't change behind our backs during the execution of -+ * this search algorithm. -+ * - Redundant block updates (both to redstone wire and to other blocks) are heavily -+ * consolidated. For worst-case scenarios (depowering of redstone wire) this results -+ * in a reduction of block updates by as much as 95% (factor of 1/21). Due to overheads, -+ * empirical testing shows a speedup better than 10x. This addresses bug MC-81098. -+ * -+ * Extensive testing has been performed to ensure that existing redstone contraptions still -+ * behave as expected. Results of early testing that identified undesirable behavior changes -+ * were addressed. Additionally, real-time performance testing revealed compute inefficiencies -+ * With earlier implementations of this accelerator. Some compatibility adjustments and -+ * performance optimizations resulted in harmless increases in block updates above the -+ * theoretical minimum. -+ * -+ * Only a single redstone machine was found to break: An instant dropper line hack that -+ * relies on powered rails and quasi-connectivity but doesn't work in all directions. The -+ * replacement is to lay redstone wire directly on top of the dropper line, which now works -+ * reliably in any direction. -+ * -+ * There are numerous other optimization that can be made, but those will be provided later in -+ * separate updates. This version is designed to be minimalistic. -+ * -+ * Many thanks to the following individuals for their help in testing this functionality: -+ * - pokechu22, _MethodZz_, WARBEN, NarcolepticFrog, CommandHelper (nessie), ilmango, -+ * OreoLamp, Xcom6000, tryashtar, RedCMD, Smokey95Dog, EDDxample, Rays Works, -+ * Nodnam, BlockyPlays, Grumm, NeunEinser, HelVince. -+ */ -+ -+ /* Reference to BlockRedstoneWire object, which uses this accelerator */ -+ private final BlockRedstoneWire wire; -+ -+ /* -+ * Implementation: -+ * -+ * RedstoneWire Blocks are updated in concentric rings or "layers" radiating out from the -+ * initial block update that came from a call to BlockRedstoneWire.neighborChanged(). -+ * All nodes put in Layer N are those with Manhattan distance N from the trigger -+ * position, reachable through connected redstone wire blocks. -+ * -+ * Layer 0 represents the trigger block position that was input to neighborChanged. -+ * Layer 1 contains the immediate neighbors of that position. -+ * Layer N contains the neighbors of blocks in layer N-1, not including -+ * those in previous layers. -+ * -+ * Layers enforce an update order that is a function of Manhattan distance -+ * from the initial coordinates input to neighborChanged. The same -+ * coordinates may appear in multiple layers, but redundant updates are minimized. -+ * Block updates are sent layer-by-layer. If multiple of a block's neighbors experience -+ * redstone wire changes before its layer is processed, then those updates will be merged. -+ * If a block's update has been sent, but its neighboring redstone changes -+ * after that, then another update will be sent. This preserves compatibility with -+ * machines that rely on zero-tick behavior, except that the new functionality is non- -+ * locational. -+ * -+ * Within each layer, updates are ordered left-to-right relative to the direction of -+ * information flow. This makes the implementation non-orientational. Only when -+ * this direction is ambiguous is randomness applied (intentionally). -+ */ -+ private List updateQueue0 = Lists.newArrayList(); -+ private List updateQueue1 = Lists.newArrayList(); -+ private List updateQueue2 = Lists.newArrayList(); -+ -+ public RedstoneWireTurbo(BlockRedstoneWire wire) { -+ this.wire = wire; -+ } -+ -+ /* -+ * Compute neighbors of a block. When a redstone wire value changes, previously it called -+ * World.notifyNeighborsOfStateChange. That lists immediately neighboring blocks in -+ * west, east, down, up, north, south order. For each of those neighbors, their own -+ * neighbors are updated in the same order. This generates 36 updates, but 12 of them are -+ * redundant; for instance the west neighbor of a block's east neighbor. -+ * -+ * Note that this ordering is only used to create the initial list of neighbors. Once -+ * the direction of signal flow is identified, the ordering of updates is completely -+ * reorganized. -+ */ -+ public static BlockPosition[] computeAllNeighbors(final BlockPosition pos) { -+ final int x = pos.getX(); -+ final int y = pos.getY(); -+ final int z = pos.getZ(); -+ final BlockPosition[] n = new BlockPosition[24]; -+ -+ // Immediate neighbors, in the same order as -+ // World.notifyNeighborsOfStateChange, etc.: -+ // west, east, down, up, north, south -+ n[0] = new BlockPosition(x - 1, y, z); -+ n[1] = new BlockPosition(x + 1, y, z); -+ n[2] = new BlockPosition(x, y - 1, z); -+ n[3] = new BlockPosition(x, y + 1, z); -+ n[4] = new BlockPosition(x, y, z - 1); -+ n[5] = new BlockPosition(x, y, z + 1); -+ -+ // Neighbors of neighbors, in the same order, -+ // except that duplicates are not included -+ n[6] = new BlockPosition(x - 2, y, z); -+ n[7] = new BlockPosition(x - 1, y - 1, z); -+ n[8] = new BlockPosition(x - 1, y + 1, z); -+ n[9] = new BlockPosition(x - 1, y, z - 1); -+ n[10] = new BlockPosition(x - 1, y, z + 1); -+ n[11] = new BlockPosition(x + 2, y, z); -+ n[12] = new BlockPosition(x + 1, y - 1, z); -+ n[13] = new BlockPosition(x + 1, y + 1, z); -+ n[14] = new BlockPosition(x + 1, y, z - 1); -+ n[15] = new BlockPosition(x + 1, y, z + 1); -+ n[16] = new BlockPosition(x, y - 2, z); -+ n[17] = new BlockPosition(x, y - 1, z - 1); -+ n[18] = new BlockPosition(x, y - 1, z + 1); -+ n[19] = new BlockPosition(x, y + 2, z); -+ n[20] = new BlockPosition(x, y + 1, z - 1); -+ n[21] = new BlockPosition(x, y + 1, z + 1); -+ n[22] = new BlockPosition(x, y, z - 2); -+ n[23] = new BlockPosition(x, y, z + 2); -+ return n; -+ } -+ -+ /* -+ * We only want redstone wires to update redstone wires that are -+ * immediately adjacent. Some more distant updates can result -+ * in cross-talk that (a) wastes time and (b) can make the update -+ * order unintuitive. Therefore (relative to the neighbor order -+ * computed by computeAllNeighbors), updates are not scheduled -+ * for redstone wire in those non-connecting positions. On the -+ * other hand, updates will always be sent to *other* types of blocks -+ * in any of the 24 neighboring positions. -+ */ -+ private static final boolean[] update_redstone = { -+ true, true, false, false, true, true, // 0 to 5 -+ false, true, true, false, false, false, // 6 to 11 -+ true, true, false, false, false, true, // 12 to 17 -+ true, false, true, true, false, false // 18 to 23 -+ }; -+ -+ // Internal numbering for cardinal directions -+ private static final int North = 0; -+ private static final int East = 1; -+ private static final int South = 2; -+ private static final int West = 3; -+ -+ /* -+ * These lookup tables completely remap neighbor positions into a left-to-right -+ * ordering, based on the cardinal direction that is determined to be forward. -+ * See below for more explanation. -+ */ -+ private static final int[] forward_is_north = {2, 3, 16, 19, 0, 4, 1, 5, 7, 8, 17, 20, 12, 13, 18, 21, 6, 9, 22, 14, 11, 10, 23, 15}; -+ private static final int[] forward_is_east = {2, 3, 16, 19, 4, 1, 5, 0, 17, 20, 12, 13, 18, 21, 7, 8, 22, 14, 11, 15, 23, 9, 6, 10}; -+ private static final int[] forward_is_south = {2, 3, 16, 19, 1, 5, 0, 4, 12, 13, 18, 21, 7, 8, 17, 20, 11, 15, 23, 10, 6, 14, 22, 9}; -+ private static final int[] forward_is_west = {2, 3, 16, 19, 5, 0, 4, 1, 18, 21, 7, 8, 17, 20, 12, 13, 23, 10, 6, 9, 22, 15, 11, 14}; -+ -+ /* For any orientation, we end up with the update order defined below. This order is relative to any redstone wire block -+ * that is itself having an update computed, and this center position is marked with C. -+ * - The update position marked 0 is computed first, and the one marked 23 is last. -+ * - Forward is determined by the local direction of information flow into position C from prior updates. -+ * - The first updates are scheduled for the four positions below and above C. -+ * - Then updates are scheduled for the four horizontal neighbors of C, followed by the positions below and above those neighbors. -+ * - Finally, updates are scheduled for the remaining positions with Manhattan distance 2 from C (at the same Y coordinate). -+ * - For a given horizontal distance from C, updates are scheduled starting from directly left and stepping clockwise to directly -+ * right. The remaining positions behind C are scheduled counterclockwise so as to maintain the left-to-right ordering. -+ * - If C is in layer N of the update schedule, then all 24 positions may be scheduled for layer N+1. For redstone wire, no -+ * updates are scheduled for positions that cannot directly connect. Additionally, the four positions above and below C -+ * are ALSO scheduled for layer N+2. -+ * - This update order was selected after experimenting with a number of alternative schedules, based on its compatibility -+ * with existing redstone designs and behaviors that were considered to be intuitive by various testers. WARBEN in particular -+ * made some of the most challenging test cases, but the 3-tick clocks (made by RedCMD) were also challenging to fix, -+ * along with the rail-based instant dropper line built by ilmango. Numerous others made test cases as well, including -+ * NarcolepticFrog, nessie, and Pokechu22. -+ * -+ * - The forward direction is determined locally. So when there are branches in the redstone wire, the left one will get updated -+ * before the right one. Each branch can have its own relative forward direction, resulting in the left side of a left branch -+ * having priority over the right branch of a left branch, which has priority over the left branch of a right branch, followed -+ * by the right branch of a right branch. And so forth. Since redstone power reduces to zero after a path distance of 15, -+ * that imposes a practical limit on the branching. Note that the branching is not tracked explicitly -- relative forward -+ * directions dictate relative sort order, which maintains the proper global ordering. This also makes it unnecessary to be -+ * concerned about branches meeting up with each other. -+ * -+ * ^ -+ * | -+ * Forward -+ * <-- Left Right --> -+ * -+ * 18 -+ * 10 17 5 19 11 -+ * 2 8 0 12 16 4 C 6 20 9 1 13 3 -+ * 14 21 7 23 15 -+ * Further 22 Further -+ * Down Down Up Up -+ * -+ * Backward -+ * | -+ * V -+ */ -+ -+ // This allows the above remapping tables to be looked up by cardial direction index -+ private static final int[][] reordering = { forward_is_north, forward_is_east, forward_is_south, forward_is_west }; -+ -+ /* -+ * Input: Array of UpdateNode objects in an order corresponding to the positions -+ * computed by computeAllNeighbors above. -+ * Output: Array of UpdateNode objects oriented using the above remapping tables -+ * corresponding to the identified heading (direction of information flow). -+ */ -+ private static void orientNeighbors(final UpdateNode[] src, final UpdateNode[] dst, final int heading) { -+ final int[] re = reordering[heading]; -+ for (int i = 0; i < 24; i++) { -+ dst[i] = src[re[i]]; -+ } -+ } -+ -+ /* -+ * Structure to keep track of redstone wire blocks and -+ * neighbors that will receive updates. -+ */ -+ private static class UpdateNode { -+ public static enum Type { -+ UNKNOWN, REDSTONE, OTHER -+ } -+ -+ IBlockData currentState; // Keep track of redstone wire value -+ UpdateNode[] neighbor_nodes; // References to neighbors (directed graph edges) -+ BlockPosition self; // UpdateNode's own position -+ BlockPosition parent; // Which block pos spawned/updated this node -+ Type type = Type.UNKNOWN; // unknown, redstone wire, other type of block -+ int layer; // Highest layer this node is scheduled in -+ boolean visited; // To keep track of information flow direction, visited restone wire is marked -+ int xbias, zbias; // Remembers directionality of ancestor nodes; helps eliminate directional ambiguities. -+ } -+ -+ /* -+ * Keep track of all block positions discovered during search and their current states. -+ * We want to remember one entry for each position. -+ */ -+ private final Map nodeCache = Maps.newHashMap(); -+ -+ /* -+ * For a newly created UpdateNode object, determine what type of block it is. -+ */ -+ private void identifyNode(final World worldIn, final UpdateNode upd1) { -+ final BlockPosition pos = upd1.self; -+ final IBlockData oldState = worldIn.getType(pos); -+ upd1.currentState = oldState; -+ -+ // Some neighbors of redstone wire are other kinds of blocks. -+ // These need to receive block updates to inform them that -+ // redstone wire values have changed. -+ final Block block = oldState.getBlock(); -+ if (block != wire) { -+ // Mark this block as not redstone wire and therefore -+ // requiring updates -+ upd1.type = UpdateNode.Type.OTHER; -+ -+ // Non-redstone blocks may propagate updates, but those updates -+ // are not handled by this accelerator. Therefore, we do not -+ // expand this position's neighbors. -+ return; -+ } -+ -+ // One job of BlockRedstoneWire.neighborChanged is to convert -+ // redstone wires to items if the block beneath was removed. -+ // With this accelerator, BlockRedstoneWire.neighborChanged -+ // is only typically called for a single wire block, while -+ // others are processed internally by the breadth first search -+ // algorithm. To preserve this game behavior, this check must -+ // be replicated here. -+ if (!wire.canPlace(null, worldIn, pos)) { -+ // Pop off the redstone dust -+ Block.a(worldIn, pos, new ItemStack(Items.REDSTONE)); // TODO -+ worldIn.setAir(pos); -+ -+ // Mark this position as not being redstone wire -+ upd1.type = UpdateNode.Type.OTHER; -+ -+ // Note: Sending updates to air blocks leads to an empty method. -+ // Testing shows this to be faster than explicitly avoiding updates to -+ // air blocks. -+ return; -+ } -+ -+ // If the above conditions fail, then this is a redstone wire block. -+ upd1.type = UpdateNode.Type.REDSTONE; -+ } -+ -+ /* -+ * Given which redstone wire blocks have been visited and not visited -+ * around the position currently being updated, compute the cardinal -+ * direction that is "forward." -+ * -+ * rx is the forward direction along the West/East axis -+ * rz is the forward direction along the North/South axis -+ */ -+ static private int computeHeading(final int rx, final int rz) { -+ // rx and rz can only take on values -1, 0, and 1, so we can -+ // compute a code number that allows us to use a single switch -+ // to determine the heading. -+ final int code = (rx + 1) + 3 * (rz + 1); -+ switch (code) { -+ case 0: { -+ // Both rx and rz are -1 (northwest) -+ // Randomly choose one to be forward. -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? North : West; -+ } -+ case 1: { -+ // rx=0, rz=-1 -+ // Definitively North -+ return North; -+ } -+ case 2: { -+ // rx=1, rz=-1 (northeast) -+ // Choose randomly between north and east -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? North : East; -+ } -+ case 3: { -+ // rx=-1, rz=0 -+ // Definitively West -+ return West; -+ } -+ case 4: { -+ // rx=0, rz=0 -+ // Heading is completely ambiguous. Choose -+ // randomly among the four cardinal directions. -+ return ThreadLocalRandom.current().nextInt(0, 4); -+ } -+ case 5: { -+ // rx=1, rz=0 -+ // Definitively East -+ return East; -+ } -+ case 6: { -+ // rx=-1, rz=1 (southwest) -+ // Choose randomly between south and west -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? South : West; -+ } -+ case 7: { -+ // rx=0, rz=1 -+ // Definitively South -+ return South; -+ } -+ case 8: { -+ // rx=1, rz=1 (southeast) -+ // Choose randomly between south and east -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? South : East; -+ } -+ } -+ -+ // We should never get here -+ return ThreadLocalRandom.current().nextInt(0, 4); -+ } -+ -+ // Select whether to use updateSurroundingRedstone from BlockRedstoneWire (old) -+ // or this helper class (new) -+ private static final boolean old_current_change = false; -+ -+ /* -+ * Process a node whose neighboring redstone wire has experienced value changes. -+ */ -+ private void updateNode(final World worldIn, final UpdateNode upd1, final int layer) { -+ final BlockPosition pos = upd1.self; -+ -+ // Mark this redstone wire as having been visited so that it can be used -+ // to calculate direction of information flow. -+ upd1.visited = true; -+ -+ // Look up the last known state. -+ // Due to the way other redstone components are updated, we do not -+ // have to worry about a state changing behind our backs. The rare -+ // exception is handled by scheduleReentrantNeighborChanged. -+ final IBlockData oldState = upd1.currentState; -+ -+ // Ask the wire block to compute its power level from its neighbors. -+ // This will also update the wire's power level and return a new -+ // state if it has changed. When a wire power level is changed, -+ // calculateCurrentChanges will immediately update the block state in the world -+ // and return the same value here to be cached in the corresponding -+ // UpdateNode object. -+ IBlockData newState; -+ if (old_current_change) { -+ newState = wire.calculateCurrentChanges(worldIn, pos, pos, oldState); -+ } else { -+ // Looking up block state is slow. This accelerator includes a version of -+ // calculateCurrentChanges that uses cahed wire values for a -+ // significant performance boost. -+ newState = this.calculateCurrentChanges(worldIn, upd1); -+ } -+ -+ // Only inform neighbors if the state has changed -+ if (newState != oldState) { -+ // Store the new state -+ upd1.currentState = newState; -+ -+ // Inform neighbors of the change -+ propagateChanges(worldIn, upd1, layer); -+ } -+ } -+ -+ /* -+ * This identifies the neighboring positions of a new UpdateNode object, -+ * determines their types, and links those to into the graph. Then based on -+ * what nodes in the redstone wire graph have been visited, the neighbors -+ * are reordered left-to-right relative to the direction of information flow. -+ */ -+ private void findNeighbors(final World worldIn, final UpdateNode upd1) { -+ final BlockPosition pos = upd1.self; -+ -+ // Get the list of neighbor coordinates -+ final BlockPosition[] neighbors = computeAllNeighbors(pos); -+ -+ // Temporary array of neighbors in cardinal ordering -+ final UpdateNode[] neighbor_nodes = new UpdateNode[24]; -+ -+ // Target array of neighbors sorted left-to-right -+ upd1.neighbor_nodes = new UpdateNode[24]; -+ -+ for (int i=0; i<24; i++) { -+ // Look up each neighbor in the node cache -+ final BlockPosition pos2 = neighbors[i]; -+ UpdateNode upd2 = nodeCache.get(pos2); -+ if (upd2 == null) { -+ // If this is a previously unreached position, create -+ // a new update node, add it to the cache, and identify what it is. -+ upd2 = new UpdateNode(); -+ upd2.self = pos2; -+ upd2.parent = pos; -+ nodeCache.put(pos2, upd2); -+ identifyNode(worldIn, upd2); -+ } -+ -+ // For non-redstone blocks, any of the 24 neighboring positions -+ // should receive a block update. However, some block coordinates -+ // may contain a redstone wire that does not directly connect to the -+ // one being expanded. To avoid redundant calculations and confusing -+ // cross-talk, those neighboring positions are not included. -+ if (update_redstone[i] || upd2.type != UpdateNode.Type.REDSTONE) { -+ neighbor_nodes[i] = upd2; -+ } -+ } -+ -+ // Determine the directions from which the redstone signal may have come from. This -+ // checks for redstone wire at the same Y level and also Y+1 and Y-1, relative to the -+ // block being expanded. -+ final boolean fromWest = (neighbor_nodes[0].visited || neighbor_nodes[7].visited || neighbor_nodes[8].visited); -+ final boolean fromEast = (neighbor_nodes[1].visited || neighbor_nodes[12].visited || neighbor_nodes[13].visited); -+ final boolean fromNorth = (neighbor_nodes[4].visited || neighbor_nodes[17].visited || neighbor_nodes[20].visited); -+ final boolean fromSouth = (neighbor_nodes[5].visited || neighbor_nodes[18].visited || neighbor_nodes[21].visited); -+ -+ int cx = 0, cz = 0; -+ if (fromWest) cx += 1; -+ if (fromEast) cx -= 1; -+ if (fromNorth) cz += 1; -+ if (fromSouth) cz -= 1; -+ -+ int heading; -+ if (cx==0 && cz==0) { -+ // If there is no clear direction, try to inherit the heading from ancestor nodes. -+ heading = computeHeading(upd1.xbias, upd1.zbias); -+ -+ // Propagate that heading to descendant nodes. -+ for (int i=0; i<24; i++) { -+ final UpdateNode nn = neighbor_nodes[i]; -+ if (nn != null) { -+ nn.xbias = upd1.xbias; -+ nn.zbias = upd1.zbias; -+ } -+ } -+ } else { -+ if (cx != 0 && cz != 0) { -+ // If the heading is somewhat ambiguous, try to disambiguate based on -+ // ancestor nodes. -+ if (upd1.xbias != 0) cz = 0; -+ if (upd1.zbias != 0) cx = 0; -+ } -+ heading = computeHeading(cx, cz); -+ -+ // Propagate that heading to descendant nodes. -+ for (int i=0; i<24; i++) { -+ final UpdateNode nn = neighbor_nodes[i]; -+ if (nn != null) { -+ nn.xbias = cx; -+ nn.zbias = cz; -+ } -+ } -+ } -+ -+ // Reorder neighboring UpdateNode objects according to the forward direction -+ // determined above. -+ orientNeighbors(neighbor_nodes, upd1.neighbor_nodes, heading); -+ } -+ -+ /* -+ * For any redstone wire block in layer N, inform neighbors to recompute their states -+ * in layers N+1 and N+2; -+ */ -+ private void propagateChanges(final World worldIn, final UpdateNode upd1, final int layer) { -+ if (upd1.neighbor_nodes == null) { -+ // If this node has not been expanded yet, find its neighbors -+ findNeighbors(worldIn, upd1); -+ } -+ -+ final BlockPosition pos = upd1.self; -+ -+ // All neighbors may be scheduled for layer N+1 -+ final int layer1 = layer + 1; -+ -+ // If the node being updated (upd1) has already been expanded, then merely -+ // schedule updates to its neighbors. -+ for (int i = 0; i < 24; i++) { -+ final UpdateNode upd2 = upd1.neighbor_nodes[i]; -+ -+ // This test ensures that an UpdateNode is never scheduled to the same layer -+ // more than once. Also, skip non-connecting redstone wire blocks -+ if (upd2 != null && layer1 > upd2.layer) { -+ upd2.layer = layer1; -+ updateQueue1.add(upd2); -+ -+ // Keep track of which block updated this neighbor -+ upd2.parent = pos; -+ } -+ } -+ -+ // Nodes above and below are scheduled ALSO for layer N+2 -+ final int layer2 = layer + 2; -+ -+ // Repeat of the loop above, but only for the first four (above and below) neighbors -+ // and for layer N+2; -+ for (int i = 0; i < 4; i++) { -+ final UpdateNode upd2 = upd1.neighbor_nodes[i]; -+ if (upd2 != null && layer2 > upd2.layer) { -+ upd2.layer = layer2; -+ updateQueue2.add(upd2); -+ upd2.parent = pos; -+ } -+ } -+ } -+ -+ // The breadth-first search below will send block updates to blocks -+ // that are not redstone wire. If one of those updates results in -+ // a distant redstone wire getting an update, then this.neighborChanged -+ // will get called. This would be a reentrant call, and -+ // it is necessary to properly integrate those updates into the -+ // on-going search through redstone wire. Thus, we make the layer -+ // currently being processed visible at the object level. -+ -+ // The current layer being processed by the breadth-first search -+ private int currentWalkLayer = 0; -+ -+ private void shiftQueue() { -+ final List t = updateQueue0; -+ t.clear(); -+ updateQueue0 = updateQueue1; -+ updateQueue1 = updateQueue2; -+ updateQueue2 = t; -+ } -+ -+ /* -+ * Perform a breadth-first (layer by layer) traversal through redstone -+ * wire blocks, propagating value changes to neighbors in an order -+ * that is a function of distance from the initial call to -+ * this.neighborChanged. -+ */ -+ private void breadthFirstWalk(final World worldIn) { -+ shiftQueue(); -+ currentWalkLayer = 1; -+ -+ // Loop over all layers -+ while (updateQueue0.size()>0 || updateQueue1.size()>0) { -+ // Get the set of blocks in this layer -+ final List thisLayer = updateQueue0; -+ -+ // Loop over all blocks in the layer. Recall that -+ // this is a List, preserving the insertion order of -+ // left-to-right based on direction of information flow. -+ for (UpdateNode upd : thisLayer) { -+ if (upd.type == UpdateNode.Type.REDSTONE) { -+ // If the node is is redstone wire, -+ // schedule updates to neighbors if its value -+ // has changed. -+ updateNode(worldIn, upd, currentWalkLayer); -+ } else { -+ // If this block is not redstone wire, send a block update. -+ // Redstone wire blocks get state updates, but they don't -+ // need block updates. Only non-redstone neighbors need updates. -+ -+ // World.neighborChanged is called from -+ // World.notifyNeighborsOfStateChange, and -+ // notifyNeighborsOfStateExcept. We don't use -+ // World.notifyNeighborsOfStateChange here, since we are -+ // already keeping track of all of the neighbor positions -+ // that need to be updated. All on its own, handling neighbors -+ // this way reduces block updates by 1/3 (24 instead of 36). -+ worldIn.neighborChanged(upd.self, wire, upd.parent); -+ } -+ } -+ -+ // Move on to the next layer -+ shiftQueue(); -+ currentWalkLayer++; -+ } -+ -+ currentWalkLayer = 0; -+ } -+ -+ /* -+ * Normally, when Minecraft is computing redstone wire power changes, and a wire power level -+ * change sends a block update to a neighboring functional component (e.g. piston, repeater, etc.), -+ * those updates are queued. Only once all redstone wire updates are complete will any component -+ * action generate any further block updates to redstone wire. Instant repeater lines, for instance, -+ * will process all wire updates for one redstone line, after which the pistons will zero-tick, -+ * after which the next redstone line performs all of its updates. Thus, each wire is processed in its -+ * own discrete wave. -+ * -+ * However, there are some corner cases where this pattern breaks, with a proof of concept discovered -+ * by Rays Works, which works the same in vanilla. The scenario is as follows: -+ * (1) A redstone wire is conducting a signal. -+ * (2) Part-way through that wave of updates, a neighbor is updated that causes an update to a completely -+ * separate redstone wire. -+ * (3) This results in a call to BlockRedstoneWire.neighborChanged for that other wire, in the middle of -+ * an already on-going propagation through the first wire. -+ * -+ * The vanilla code, being depth-first, would end up fully processing the second wire before going back -+ * to finish processing the first one. (Although technically, vanilla has no special concept of "being -+ * in the middle" of processing updates to a wire.) For the breadth-first algorithm, we give this -+ * situation special handling, where the updates for the second wire are incorporated into the schedule -+ * for the first wire, and then the callstack is allowed to unwind back to the on-going search loop in -+ * order to continue processing both the first and second wire in the order of distance from the initial -+ * trigger. -+ */ -+ private IBlockData scheduleReentrantNeighborChanged(final World worldIn, final BlockPosition pos, final IBlockData newState, final BlockPosition source) { -+ if (source != null) { -+ // If the cause of the redstone wire update is known, we can use that to help determine -+ // direction of information flow. -+ UpdateNode src = nodeCache.get(source); -+ if (src == null) { -+ src = new UpdateNode(); -+ src.self = source; -+ src.parent = source; -+ src.visited = true; -+ identifyNode(worldIn, src); -+ nodeCache.put(source, src); -+ } -+ } -+ -+ // Find or generate a node for the redstone block position receiving the update -+ UpdateNode upd = nodeCache.get(pos); -+ if (upd == null) { -+ upd = new UpdateNode(); -+ upd.self = pos; -+ upd.parent = pos; -+ upd.visited = true; -+ identifyNode(worldIn, upd); -+ nodeCache.put(pos, upd); -+ } -+ upd.currentState = newState; -+ -+ // Receiving this block update may mean something in the world changed. -+ // Therefore we clear the cached block info about all neighbors of -+ // the position receiving the update and then re-identify what they are. -+ if (upd.neighbor_nodes != null) { -+ for (int i=0; i<24; i++) { -+ final UpdateNode upd2 = upd.neighbor_nodes[i]; -+ if (upd2 == null) continue; -+ upd2.type = UpdateNode.Type.UNKNOWN; -+ upd2.currentState = null; -+ identifyNode(worldIn, upd2); -+ } -+ } -+ -+ // The block at 'pos' is a redstone wire and has been updated already by calling -+ // wire.calculateCurrentChanges, so we don't schedule that. However, we do need -+ // to schedule its neighbors. By passing the current value of 'currentWalkLayer' to -+ // propagateChanges, the neighbors of 'pos' are scheduled for layers currentWalkLayer+1 -+ // and currentWalkLayer+2. -+ propagateChanges(worldIn, upd, currentWalkLayer); -+ -+ // Return here. The call stack will unwind back to the first call to -+ // updateSurroundingRedstone, whereupon the new updates just scheduled will -+ // be propagated. This also facilitates elimination of superfluous and -+ // redundant block updates. -+ return newState; -+ } -+ -+ /* -+ * New version of pre-existing updateSurroundingRedstone, which is called from -+ * wire.updateSurroundingRedstone, which is called from wire.neighborChanged and a -+ * few other methods in BlockRedstoneWire. This sets off the breadth-first -+ * walk through all redstone dust connected to the initial position triggered. -+ */ -+ public IBlockData updateSurroundingRedstone(final World worldIn, final BlockPosition pos, final IBlockData state, final BlockPosition source) { -+ // Check this block's neighbors and see if its power level needs to change -+ // Use the calculateCurrentChanges method in BlockRedstoneWire since we have no -+ // cached block states at this point. -+ final IBlockData newState = wire.calculateCurrentChanges(worldIn, pos, pos, state); -+ -+ // If no change, exit -+ if (newState == state) { -+ return state; -+ } -+ -+ // Check to see if this update was received during an on-going breadth first search -+ if (currentWalkLayer > 0 || nodeCache.size() > 0) { -+ // As breadthFirstWalk progresses, it sends block updates to neighbors. Some of those -+ // neighbors may affect the world so as to cause yet another redstone wire block to receive -+ // an update. If that happens, we need to integrate those redstone wire updates into the -+ // already on-going graph walk being performed by breadthFirstWalk. -+ return scheduleReentrantNeighborChanged(worldIn, pos, newState, source); -+ } -+ // If there are no on-going walks through redstone wire, then start a new walk. -+ -+ // If the source of the block update to the redstone wire at 'pos' is known, we can use -+ // that to help determine the direction of information flow. -+ if (source != null) { -+ final UpdateNode src = new UpdateNode(); -+ src.self = source; -+ src.parent = source; -+ src.visited = true; -+ nodeCache.put(source, src); -+ identifyNode(worldIn, src); -+ } -+ -+ // Create a node representing the block at 'pos', and then propagate updates -+ // to its neighbors. As stated above, the call to wire.calculateCurrentChanges -+ // already performs the update to the block at 'pos', so it is not added to the schedule. -+ final UpdateNode upd = new UpdateNode(); -+ upd.self = pos; -+ upd.parent = source!=null ? source : pos; -+ upd.currentState = newState; -+ upd.type = UpdateNode.Type.REDSTONE; -+ upd.visited = true; -+ nodeCache.put(pos, upd); -+ propagateChanges(worldIn, upd, 0); -+ -+ // Perform the walk over all directly reachable redstone wire blocks, propagating wire value -+ // updates in a breadth first order out from the initial update received for the block at 'pos'. -+ breadthFirstWalk(worldIn); -+ -+ // With the whole search completed, clear the list of all known blocks. -+ // We do not want to keep around state information that may be changed by other code. -+ // In theory, we could cache the neighbor block positions, but that is a separate -+ // optimization. -+ nodeCache.clear(); -+ -+ return newState; -+ } -+ -+ // For any array of neighbors in an UpdateNode object, these are always -+ // the indices of the four immediate neighbors at the same Y coordinate. -+ private static final int[] rs_neighbors = {4, 5, 6, 7}; -+ private static final int[] rs_neighbors_up = {9, 11, 13, 15}; -+ private static final int[] rs_neighbors_dn = {8, 10, 12, 14}; -+ -+ /* -+ * Updated calculateCurrentChanges that is optimized for speed and uses -+ * the UpdateNode's neighbor array to find the redstone states of neighbors -+ * that might power it. -+ */ -+ private IBlockData calculateCurrentChanges(final World worldIn, final UpdateNode upd) { -+ IBlockData state = upd.currentState; -+ final int i = state.get(BlockRedstoneWire.POWER).intValue(); -+ int j = 0; -+ j = getMaxCurrentStrength(upd, j); -+ int l = 0; -+ -+ wire.setCanProvidePower(false); -+ // Unfortunately, World.isBlockIndirectlyGettingPowered is complicated, -+ // and I'm not ready to try to replicate even more functionality from -+ // elsewhere in Minecraft into this accelerator. So sadly, we must -+ // suffer the performance hit of this very expensive call. If there -+ // is consistency to what this call returns, we may be able to cache it. -+ final int k = worldIn.isBlockIndirectlyGettingPowered(upd.self); -+ wire.setCanProvidePower(true); -+ -+ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. -+ // If 'k' has the highest level of all neighbors, then the power level of this -+ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the -+ // following loop can affect the power level of the wire. Therefore, the loop is -+ // skipped if k is already 15. -+ if (k < 15) { -+ if (upd.neighbor_nodes == null) { -+ // If this node's neighbors are not known, expand the node -+ findNeighbors(worldIn, upd); -+ } -+ -+ // These remain constant, so pull them out of the loop. -+ // Regardless of which direction is forward, the UpdateNode for the -+ // position directly above the node being calculated is always -+ // at index 1. -+ UpdateNode center_up = upd.neighbor_nodes[1]; -+ boolean center_up_is_cube = center_up.currentState.isOccluding(worldIn, center_up.self); // TODO -+ -+ for (int m = 0; m < 4; m++) { -+ // Get the neighbor array index of each of the four cardinal -+ // neighbors. -+ int n = rs_neighbors[m]; -+ -+ // Get the max redstone power level of each of the cardinal -+ // neighbors -+ UpdateNode neighbor = upd.neighbor_nodes[n]; -+ l = getMaxCurrentStrength(neighbor, l); -+ -+ // Also check the positions above and below the cardinal -+ // neighbors -+ boolean neighbor_is_cube = neighbor.currentState.isOccluding(worldIn, neighbor.self); // TODO -+ if (!neighbor_is_cube) { -+ UpdateNode neighbor_down = upd.neighbor_nodes[rs_neighbors_dn[m]]; -+ l = getMaxCurrentStrength(neighbor_down, l); -+ } else -+ if (!center_up_is_cube) { -+ UpdateNode neighbor_up = upd.neighbor_nodes[rs_neighbors_up[m]]; -+ l = getMaxCurrentStrength(neighbor_up, l); -+ } -+ } -+ } -+ -+ // The new code sets this RedstoneWire block's power level to the highest neighbor -+ // minus 1. This usually results in wire power levels dropping by 2 at a time. -+ // This optimization alone has no impact on update order, only the number of updates. -+ j = l - 1; -+ -+ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will -+ // always be in the range of 0 to 15, the following if will correct that. -+ if (k > j) j = k; -+ -+ // egg82's amendment -+ // Adding Bukkit's BlockRedstoneEvent - er.. event. -+ if (i != j) { -+ BlockRedstoneEvent event = new BlockRedstoneEvent(worldIn.getWorld().getBlockAt(upd.self.getX(), upd.self.getY(), upd.self.getZ()), i, j); -+ worldIn.getServer().getPluginManager().callEvent(event); -+ j = event.getNewCurrent(); -+ } -+ -+ if (i != j) { -+ // If the power level has changed from its previous value, compute a new state -+ // and set it in the world. -+ // Possible optimization: Don't commit state changes to the world until they -+ // need to be known by some nearby non-redstone-wire block. -+ BlockPosition pos = new BlockPosition(upd.self.getX(), upd.self.getY(), upd.self.getZ()); -+ if (wire.canPlace(null, worldIn, pos)) { -+ state = state.set(BlockRedstoneWire.POWER, Integer.valueOf(j)); -+ worldIn.setTypeAndData(upd.self, state, 2); -+ } -+ } -+ -+ return state; -+ } -+ -+ /* -+ * Optimized function to compute a redstone wire's power level based on cached -+ * state. -+ */ -+ private static int getMaxCurrentStrength(final UpdateNode upd, final int strength) { -+ if (upd.type != UpdateNode.Type.REDSTONE) return strength; -+ final int i = upd.currentState.get(BlockRedstoneWire.POWER).intValue(); -+ return i > strength ? i : strength; -+ } -+} -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 9369a0c6c0ae2d8518ebfb17f2c93ead2647ab8d..307a89c431739ed15d8869faace7b08927626f60 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -659,6 +659,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - } - -+ public void neighborChanged(BlockPosition pos, Block blockIn, BlockPosition fromPos) { a(pos, blockIn, fromPos); } // Paper - OBFHELPER - public void a(BlockPosition blockposition, Block block, BlockPosition blockposition1) { - if (!this.isClientSide) { - IBlockData iblockdata = this.getType(blockposition); -@@ -1287,6 +1288,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return this.getBlockFacePower(blockposition.down(), EnumDirection.DOWN) > 0 ? true : (this.getBlockFacePower(blockposition.up(), EnumDirection.UP) > 0 ? true : (this.getBlockFacePower(blockposition.north(), EnumDirection.NORTH) > 0 ? true : (this.getBlockFacePower(blockposition.south(), EnumDirection.SOUTH) > 0 ? true : (this.getBlockFacePower(blockposition.west(), EnumDirection.WEST) > 0 ? true : this.getBlockFacePower(blockposition.east(), EnumDirection.EAST) > 0)))); - } - -+ public int isBlockIndirectlyGettingPowered(BlockPosition pos) { return this.s(pos); } // Paper - OBFHELPER - public int s(BlockPosition blockposition) { - int i = 0; - EnumDirection[] aenumdirection = World.a; -diff --git a/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java b/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java -index 60f0e582199472f9c5ef26e12ee1da0c3867254e..71ba55d36f5bc8a417930015c31553b30cf3e8dd 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java -@@ -1,5 +1,7 @@ - package net.minecraft.world.level.block; - -+import com.destroystokyo.paper.PaperConfig; -+import com.destroystokyo.paper.util.RedstoneWireTurbo; - import com.google.common.collect.ImmutableMap; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -50,7 +52,7 @@ public class BlockRedstoneWire extends Block { - private final Map j = Maps.newHashMap(); - private static final Vector3fa[] k = new Vector3fa[16]; - private final IBlockData o; -- private boolean p = true; -+ private boolean p = true; public final boolean canProvidePower() { return this.p; } public final void setCanProvidePower(boolean value) { this.p = value; } // Paper - OBFHELPER - - public BlockRedstoneWire(BlockBase.Info blockbase_info) { - super(blockbase_info); -@@ -237,6 +239,121 @@ public class BlockRedstoneWire extends Block { - return iblockdata.d(iblockaccess, blockposition, EnumDirection.UP) || iblockdata.a(Blocks.HOPPER); - } - -+ // Paper start - Optimize redstone -+ // The bulk of the new functionality is found in RedstoneWireTurbo.java -+ RedstoneWireTurbo turbo = new RedstoneWireTurbo(this); -+ -+ /* -+ * Modified version of pre-existing updateSurroundingRedstone, which is called from -+ * this.neighborChanged and a few other methods in this class. -+ * Note: Added 'source' argument so as to help determine direction of information flow -+ */ -+ private void updateSurroundingRedstone(World worldIn, BlockPosition pos, IBlockData state, BlockPosition source) { -+ if (worldIn.paperConfig.useEigencraftRedstone) { -+ turbo.updateSurroundingRedstone(worldIn, pos, state, source); -+ return; -+ } -+ a(worldIn, pos, state); -+ } -+ -+ /* -+ * Slightly modified method to compute redstone wire power levels from neighboring blocks. -+ * Modifications cut the number of power level changes by about 45% from vanilla, and this -+ * optimization synergizes well with the breadth-first search implemented in -+ * RedstoneWireTurbo. -+ * Note: RedstoneWireTurbo contains a faster version of this code. -+ * Note: Made this public so that RedstoneWireTurbo can access it. -+ */ -+ public IBlockData calculateCurrentChanges(World worldIn, BlockPosition pos1, BlockPosition pos2, IBlockData state) { -+ IBlockData iblockstate = state; -+ int i = state.get(POWER); -+ int j = 0; -+ j = this.getPower(j, worldIn.getType(pos2)); -+ this.setCanProvidePower(false); -+ int k = worldIn.isBlockIndirectlyGettingPowered(pos1); -+ this.setCanProvidePower(true); -+ -+ if (!worldIn.paperConfig.useEigencraftRedstone) { -+ // This code is totally redundant to if statements just below the loop. -+ if (k > 0 && k > j - 1) { -+ j = k; -+ } -+ } -+ -+ int l = 0; -+ -+ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. -+ // If 'k' has the highest level of all neighbors, then the power level of this -+ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the -+ // following loop can affect the power level of the wire. Therefore, the loop is -+ // skipped if k is already 15. -+ if (!worldIn.paperConfig.useEigencraftRedstone || k < 15) { -+ for (EnumDirection enumfacing : EnumDirection.EnumDirectionLimit.HORIZONTAL) { -+ BlockPosition blockpos = pos1.shift(enumfacing); -+ boolean flag = blockpos.getX() != pos2.getX() || blockpos.getZ() != pos2.getZ(); -+ -+ if (flag) { -+ l = this.getPower(l, worldIn.getType(blockpos)); -+ } -+ -+ if (worldIn.getType(blockpos).isOccluding(worldIn, blockpos) && !worldIn.getType(pos1.up()).isOccluding(worldIn, pos1)) { -+ if (flag && pos1.getY() >= pos2.getY()) { -+ l = this.getPower(l, worldIn.getType(blockpos.up())); -+ } -+ } else if (!worldIn.getType(blockpos).isOccluding(worldIn, blockpos) && flag && pos1.getY() <= pos2.getY()) { -+ l = this.getPower(l, worldIn.getType(blockpos.down())); -+ } -+ } -+ } -+ -+ if (!worldIn.paperConfig.useEigencraftRedstone) { -+ // The old code would decrement the wire value only by 1 at a time. -+ if (l > j) { -+ j = l - 1; -+ } else if (j > 0) { -+ --j; -+ } else { -+ j = 0; -+ } -+ -+ if (k > j - 1) { -+ j = k; -+ } -+ } else { -+ // The new code sets this RedstoneWire block's power level to the highest neighbor -+ // minus 1. This usually results in wire power levels dropping by 2 at a time. -+ // This optimization alone has no impact on update order, only the number of updates. -+ j = l - 1; -+ -+ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will -+ // always be in the range of 0 to 15, the following if will correct that. -+ if (k > j) j = k; -+ } -+ -+ if (i != j) { -+ state = state.set(POWER, j); -+ -+ if (worldIn.getType(pos1) == iblockstate) { -+ worldIn.setTypeAndData(pos1, state, 2); -+ } -+ -+ // 1.16(.1?) dropped the need for blocks needing updates. -+ // Whether this is necessary after all is to be seen. -+// if (!worldIn.paperConfig.useEigencraftRedstone) { -+// // The new search algorithm keeps track of blocks needing updates in its own data structures, -+// // so only add anything to blocksNeedingUpdate if we're using the vanilla update algorithm. -+// this.getBlocksNeedingUpdate().add(pos1); -+// -+// for (EnumDirection enumfacing1 : EnumDirection.values()) { -+// this.getBlocksNeedingUpdate().add(pos1.shift(enumfacing1)); -+// } -+// } -+ } -+ -+ return state; -+ } -+ // Paper end -+ - private void a(World world, BlockPosition blockposition, IBlockData iblockdata) { - int i = this.a(world, blockposition); - -@@ -306,6 +423,8 @@ public class BlockRedstoneWire extends Block { - return Math.max(i, j - 1); - } - -+ private int getPower(int min, IBlockData iblockdata) { return Math.max(min, getPower(iblockdata)); } // Paper - Optimize redstone -+ private int getPower(IBlockData iblockdata) { return this.o(iblockdata); } // Paper - OBFHELPER - private int o(IBlockData iblockdata) { - return iblockdata.a((Block) this) ? (Integer) iblockdata.get(BlockRedstoneWire.POWER) : 0; - } -@@ -328,7 +447,7 @@ public class BlockRedstoneWire extends Block { - @Override - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - if (!iblockdata1.a(iblockdata.getBlock()) && !world.isClientSide) { -- this.a(world, blockposition, iblockdata); -+ this.updateSurroundingRedstone(world, blockposition, iblockdata, null); // Paper - Optimize redstone - Iterator iterator = EnumDirection.EnumDirectionLimit.VERTICAL.iterator(); - - while (iterator.hasNext()) { -@@ -355,7 +474,7 @@ public class BlockRedstoneWire extends Block { - world.applyPhysics(blockposition.shift(enumdirection), this); - } - -- this.a(world, blockposition, iblockdata); -+ this.updateSurroundingRedstone(world, blockposition, iblockdata, null); // Paper - Optimize redstone - this.d(world, blockposition); - } - } -@@ -390,7 +509,7 @@ public class BlockRedstoneWire extends Block { - public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { - if (!world.isClientSide) { - if (iblockdata.canPlace(world, blockposition)) { -- this.a(world, blockposition, iblockdata); -+ this.updateSurroundingRedstone(world, blockposition, iblockdata, blockposition1); // Paper - Optimize redstone - } else { - c(iblockdata, world, blockposition); - world.a(blockposition, false); diff --git a/Unmapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch b/Unmapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch deleted file mode 100644 index 73ff3451e7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Thu, 27 Aug 2020 16:57:25 -0400 -Subject: [PATCH] Fix hex colors not working in some kick messages - - -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index c4ba5c02c1be94bda2eb652415b48bf5a38400f6..26fe1f612e9dab37e5bf6bc431eb362bd7e4803a 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -50,7 +50,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - synchronized (throttleTracker) { - if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { - throttleTracker.put(address, currentTime); -- ChatMessage chatmessage = new ChatMessage(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message -+ IChatBaseComponent chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage, true)[0]; // Paper - Configurable connection throttle kick message // Paper - Fix hex colors not working in some kick messages - this.c.sendPacket(new PacketLoginOutDisconnect(chatmessage)); - this.c.close(chatmessage); - return; -@@ -76,12 +76,12 @@ public class HandshakeListener implements PacketHandshakingInListener { - } - // CraftBukkit end - if (packethandshakinginsetprotocol.c() != SharedConstants.getGameVersion().getProtocolVersion()) { -- ChatMessage chatmessage; -+ IChatBaseComponent chatmessage; // Paper - Fix hex colors not working in some kick messages - - if (packethandshakinginsetprotocol.c() < 754) { -- chatmessage = new ChatMessage( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) ); // Spigot -+ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages - } else { -- chatmessage = new ChatMessage( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) ); // Spigot -+ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages - } - - this.c.sendPacket(new PacketLoginOutDisconnect(chatmessage)); -@@ -99,7 +99,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - if (event.callEvent()) { - // If we've failed somehow, let the client know so and go no further. - if (event.isFailed()) { -- chatmessage = new ChatMessage(event.getFailMessage()); -+ IChatBaseComponent chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(event.getFailMessage(), true)[0]; // Paper - Fix hex colors not working in some kick messages - this.getNetworkManager().sendPacket(new PacketLoginOutDisconnect(chatmessage)); - this.getNetworkManager().close(chatmessage); - return; -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index f40736a836d6097930b9704246c7077617b1f962..190fc9f764420ea5fd20d629101644aeda2d8239 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -106,14 +106,7 @@ public class LoginListener implements PacketLoginInListener { - // CraftBukkit start - @Deprecated - public void disconnect(String s) { -- try { -- IChatBaseComponent ichatbasecomponent = new ChatComponentText(s); -- LoginListener.LOGGER.info("Disconnecting {}: {}", this.d(), s); -- this.networkManager.sendPacket(new PacketLoginOutDisconnect(ichatbasecomponent)); -- this.networkManager.close(ichatbasecomponent); -- } catch (Exception exception) { -- LoginListener.LOGGER.error("Error whilst disconnecting player", exception); -- } -+ disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s, true)[0]); // Paper - Fix hex colors not working in some kick messages - } - // CraftBukkit end - diff --git a/Unmapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch b/Unmapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch deleted file mode 100644 index cfced66829..0000000000 --- a/Unmapped-Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Fri, 21 Aug 2020 20:57:54 +0200 -Subject: [PATCH] PortalCreateEvent needs to know its entity - - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 800d10db92a956d3ca8a3d569d12862f36044ee9..366ceb65d40c685117d1c79a933864ab91d8aa11 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -368,7 +368,7 @@ public final class ItemStack { - IBlockData block = world.getType(newblockposition); - - if (!(block.getBlock() instanceof BlockTileEntity)) { // Containers get placed automatically -- block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); -+ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true, itemactioncontext); // Paper - pass itemactioncontext - } - - world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getType(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java -index e6ea1d29c7f3f4cb6039df0e35c8db94b6f38c3e..70c32b7a53a1107cced3491ebac19b0eaf4fec2e 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java -@@ -15,6 +15,7 @@ import net.minecraft.core.EnumDirection; - import net.minecraft.server.MCUtil; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.item.context.BlockActionContext; -+import net.minecraft.world.item.context.ItemActionContext; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.IBlockAccess; -@@ -364,8 +365,10 @@ public class BlockFire extends BlockFireAbstract { - } - - @Override -- public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { -- super.onPlace(iblockdata, world, blockposition, iblockdata1, flag); -+ // Paper start - ItemActionContext param -+ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag, ItemActionContext itemActionContext) { -+ super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext); -+ // Paper end - world.getBlockTickList().a(blockposition, this, a(world.random)); - } - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -index b86513497b7ca8bde84176f5228ef9c479a73abb..02047bf07c2008c7de8daf3d76b660e25b77bce8 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -@@ -7,6 +7,7 @@ import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.context.BlockActionContext; -+import net.minecraft.world.item.context.ItemActionContext; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.IBlockAccess; - import net.minecraft.world.level.World; -@@ -66,14 +67,17 @@ public abstract class BlockFireAbstract extends Block { - super.a(iblockdata, world, blockposition, entity); - } - -+ // Paper start - ItemActionContext param -+ @Override public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { this.onPlace(iblockdata, world, blockposition, iblockdata1, flag, null); } - @Override -- public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { -+ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag, ItemActionContext itemActionContext) { -+ // Paper end - if (!iblockdata1.a(iblockdata.getBlock())) { - if (a(world)) { - Optional optional = BlockPortalShape.a((GeneratorAccess) world, blockposition, EnumDirection.EnumAxis.X); - - if (optional.isPresent()) { -- ((BlockPortalShape) optional.get()).createPortal(); -+ ((BlockPortalShape) optional.get()).createPortal(itemActionContext); // Paper - pass ItemActionContext param - return; - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 2a785ea58a7bdc80c703a60bc6ed602dc8040aa0..9af91784544dbb0555824a91088257659bdf2c3d 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -32,6 +32,7 @@ import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.Item; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.context.BlockActionContext; -+import net.minecraft.world.item.context.ItemActionContext; - import net.minecraft.world.level.BlockAccessAir; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.IBlockAccess; -@@ -120,6 +121,12 @@ public abstract class BlockBase { - PacketDebug.a(world, blockposition); - } - -+ // Paper start - add ItemActionContext param -+ @Deprecated -+ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag, ItemActionContext itemActionContext) { -+ this.onPlace(iblockdata, world, blockposition, iblockdata1, flag); -+ } -+ // Paper end - @Deprecated - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot -diff --git a/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java b/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java -index 7c43a12f86cce829b2afb42ebcc95c2449985c10..0bce061d5a0dd0fc08f0aa4d46ead9326beb4bc7 100644 ---- a/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java -+++ b/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java -@@ -11,6 +11,7 @@ import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.EntitySize; -+import net.minecraft.world.item.context.ItemActionContext; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.block.BlockPortal; - import net.minecraft.world.level.block.Blocks; -@@ -182,7 +183,10 @@ public class BlockPortalShape { - } - - // CraftBukkit start - return boolean -- public boolean createPortal() { -+ // Paper start - ItemActionContext param -+ @Deprecated public boolean createPortal() { return this.createPortal(null); } -+ public boolean createPortal(ItemActionContext itemActionContext) { -+ // Paper end - org.bukkit.World bworld = this.b.getMinecraftWorld().getWorld(); - - // Copy below for loop -@@ -191,8 +195,7 @@ public class BlockPortalShape { - BlockPosition.a(this.position, this.position.shift(EnumDirection.UP, this.height - 1).shift(this.d, this.width - 1)).forEach((blockposition) -> { - blocks.setTypeAndData(blockposition, iblockdata, 18); - }); -- -- PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); -+ PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, itemActionContext == null || itemActionContext.getEntity() == null ? null : itemActionContext.getEntity().getBukkitEntity(), PortalCreateEvent.CreateReason.FIRE); // Paper - pass entity param - this.b.getMinecraftWorld().getMinecraftServer().server.getPluginManager().callEvent(event); - - if (event.isCancelled()) { diff --git a/Unmapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch b/Unmapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch deleted file mode 100644 index 52281e3135..0000000000 --- a/Unmapped-Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: foss-mc <69294560+foss-mc@users.noreply.github.com> -Date: Sun, 30 Aug 2020 15:30:29 +0800 -Subject: [PATCH] Fix CraftTeam null check - - -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -index c631934fe9d205a06956c900d5b58a1d8a781c19..d637c2941ad0680299378b58ba0db7f7a6be07dc 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -@@ -254,7 +254,7 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { - - @Override - public boolean hasEntry(String entry) throws IllegalArgumentException, IllegalStateException { -- Validate.notNull("Entry cannot be null"); -+ Validate.notNull(entry, "Entry cannot be null"); // Paper - - CraftScoreboard scoreboard = checkState(); - diff --git a/Unmapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch b/Unmapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch deleted file mode 100644 index ccde2ad0c9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0562-Add-more-Evoker-API.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 15:28:35 +0200 -Subject: [PATCH] Add more Evoker API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -index 64bfd84e8a5a0c2b1fec7044b688c7cc1083f18a..2aa6b6ca93c25c59ad224348aad1bb34d9bbc6a3 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -@@ -40,7 +40,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; - - public class EntityEvoker extends EntityIllagerWizard { - -- private EntitySheep bo; -+ private EntitySheep bo; public final EntitySheep getWololoTarget() { return this.bo; } public final void setWololoTarget(EntitySheep sheep) { this.bo = sheep; } // Paper - OBFHELPER - - public EntityEvoker(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -59,7 +59,7 @@ public class EntityEvoker extends EntityIllagerWizard { - this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D)); - this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F)); - this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); -- this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a()); -+ this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix - this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300)); - this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, false)); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -index 5e8e9d95068342661a962aae9878a7eafaa06207..75a7832e9841921497a9a2d1cfd1b05807fe6ede 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import net.minecraft.world.entity.animal.EntitySheep; - import net.minecraft.world.entity.monster.EntityEvoker; - import net.minecraft.world.entity.monster.EntityIllagerWizard; - import org.bukkit.craftbukkit.CraftServer; -@@ -36,4 +37,17 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { - public void setCurrentSpell(Evoker.Spell spell) { - getHandle().setSpell(spell == null ? EntityIllagerWizard.Spell.NONE : EntityIllagerWizard.Spell.a(spell.ordinal())); - } -+ -+ // Paper start -+ @Override -+ public org.bukkit.entity.Sheep getWololoTarget() { -+ EntitySheep sheep = getHandle().getWololoTarget(); -+ return sheep == null ? null : (org.bukkit.entity.Sheep) sheep.getBukkitEntity(); -+ } -+ -+ @Override -+ public void setWololoTarget(org.bukkit.entity.Sheep sheep) { -+ getHandle().setWololoTarget(sheep == null ? null : ((org.bukkit.craftbukkit.entity.CraftSheep) sheep).getHandle()); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/Unmapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch deleted file mode 100644 index c34765c878..0000000000 --- a/Unmapped-Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 11 Aug 2020 19:16:09 +0200 -Subject: [PATCH] Add a way to get translation keys for blocks, entities and - materials - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 9d2955f05aadd4bbc6dcfec068a55d7fe6950ba0..f2cf33d42839710a3bbdf0c8ea0be28af6fcb19d 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -278,6 +278,7 @@ public class EntityTypes { - return IRegistry.ENTITY_TYPE.getKey(entitytypes); - } - -+ public static Optional> getByName(String name) { return a(name); } // Paper - OBFHELPER - public static Optional> a(String s) { - return IRegistry.ENTITY_TYPE.getOptional(MinecraftKey.a(s)); - } -@@ -431,6 +432,7 @@ public class EntityTypes { - return this.bg; - } - -+ public String getDescriptionId() { return f(); } // Paper - OBFHELPER - public String f() { - if (this.bo == null) { - this.bo = SystemUtils.a("entity", IRegistry.ENTITY_TYPE.getKey(this)); -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index ca513e7b0a416860aba89e41de6a7c5ff42baa69..467121839b94e09f59c64300de9f26d3c6caf1e5 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -56,7 +56,7 @@ public class Item implements IMaterial { - private final FoodInfo foodInfo; - - public static int getId(Item item) { -- return item == null ? 0 : IRegistry.ITEM.a((Object) item); -+ return item == null ? 0 : IRegistry.ITEM.a(item); // Paper - Fix Decompiler Issue - } - - public static Item getById(int i) { -@@ -152,6 +152,7 @@ public class Item implements IMaterial { - return IRegistry.ITEM.getKey(this).getKey(); - } - -+ public String getOrCreateDescriptionId() { return m(); } // Paper - OBFHELPER - protected String m() { - if (this.name == null) { - this.name = SystemUtils.a("item", IRegistry.ITEM.getKey(this)); -@@ -164,6 +165,7 @@ public class Item implements IMaterial { - return this.m(); - } - -+ public String getDescriptionId(ItemStack itemStack) { return f(itemStack); } // Paper - OBFHELPER - public String f(ItemStack itemstack) { - return this.getName(); - } -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index cc512bd2e89382e7fdbc59b41640e95ccafbbfe9..d4903842aebeff3e32dbf7d3f4b670af4ebad174 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -318,6 +318,7 @@ public class Block extends BlockBase implements IMaterial { - return !this.material.isBuildable() && !this.material.isLiquid(); - } - -+ public String getOrCreateDescriptionId() { return i(); } // Paper - OBFHELPER - public String i() { - if (this.name == null) { - this.name = SystemUtils.a("block", IRegistry.BLOCK.getKey(this)); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index e3ab0b76e5003553b29215a43bc5a762f2663648..ee8977a1e4a83598ba7873c4c482fea828c6b26c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -764,5 +764,10 @@ public class CraftBlock implements Block { - public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { - return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().getBlockData().getStepSound()); - } -+ -+ @Override -+ public String getTranslationKey() { -+ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); -+ } - // 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 2519dbce9717ff647d50c31aed6aca68b9f4e3af..8049063ea37f3e0eac3f3a26703adc80fc99341a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -45,6 +45,7 @@ import org.bukkit.Registry; - import org.bukkit.UnsafeValues; - import org.bukkit.advancement.Advancement; - import org.bukkit.block.data.BlockData; -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.block.data.CraftBlockData; - import org.bukkit.craftbukkit.inventory.CraftItemStack; - import org.bukkit.craftbukkit.legacy.CraftLegacy; -@@ -420,6 +421,30 @@ public final class CraftMagicNumbers implements UnsafeValues { - throw new RuntimeException(); - } - } -+ -+ @Override -+ public String getTranslationKey(Material mat) { -+ if (mat.isBlock()) { -+ return getBlock(mat).getOrCreateDescriptionId(); -+ } -+ return getItem(mat).getName(); -+ } -+ -+ @Override -+ public String getTranslationKey(org.bukkit.block.Block block) { -+ return ((org.bukkit.craftbukkit.block.CraftBlock)block).getNMS().getBlock().getOrCreateDescriptionId(); -+ } -+ -+ @Override -+ public String getTranslationKey(org.bukkit.entity.EntityType type) { -+ return net.minecraft.world.entity.EntityTypes.getByName(type.getName()).map(net.minecraft.world.entity.EntityTypes::getDescriptionId).orElse(null); -+ } -+ -+ @Override -+ public String getTranslationKey(org.bukkit.inventory.ItemStack itemStack) { -+ net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); -+ return nmsItemStack.getItem().getDescriptionId(nmsItemStack); -+ } - // Paper end - - /** diff --git a/Unmapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch b/Unmapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch deleted file mode 100644 index 1e4c77c2c5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 6 Jul 2020 22:18:04 +0200 -Subject: [PATCH] Create HoverEvent from ItemStack Entity - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 910c6109783dfef86e127a0a5b7d7d3865150d89..347c23d4b7d47198f214c3f95354e8abb660b191 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -365,5 +365,40 @@ public final class CraftItemFactory implements ItemFactory { - - return nms != null ? net.minecraft.locale.LocaleLanguage.getInstance().translateKey(nms.getItem().getName()) : null; - } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(ItemStack itemStack) { -+ net.md_5.bungee.api.chat.ItemTag itemTag = net.md_5.bungee.api.chat.ItemTag.ofNbt(CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString()); -+ return new net.md_5.bungee.api.chat.hover.content.Item( -+ itemStack.getType().getKey().toString(), -+ itemStack.getAmount(), -+ itemTag); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity) { -+ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(entity.getCustomName()) ? null : new net.md_5.bungee.api.chat.TextComponent(entity.getCustomName())); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, String customName) { -+ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(customName) ? null : new net.md_5.bungee.api.chat.TextComponent(customName)); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent customName) { -+ return new net.md_5.bungee.api.chat.hover.content.Entity( -+ entity.getType().getKey().toString(), -+ entity.getUniqueId().toString(), -+ customName); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent[] customName) { -+ return new net.md_5.bungee.api.chat.hover.content.Entity( -+ entity.getType().getKey().toString(), -+ entity.getUniqueId().toString(), -+ new net.md_5.bungee.api.chat.TextComponent(customName)); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch b/Unmapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch deleted file mode 100644 index 34db53bb63..0000000000 --- a/Unmapped-Spigot-Server-Patches/0565-Cache-block-data-strings.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Thu, 6 Dec 2018 19:52:50 -0500 -Subject: [PATCH] Cache block data strings - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 5acc6cfa96084728f45cfbec0ff9571e5dd0b844..1af99b938382d3d229f1fbf6250e1f0e09da4819 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1955,6 +1955,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant%s", nms, bukkit); - } - -+ // Paper start - cache block data strings -+ private static Map stringDataCache = new HashMap<>(); -+ -+ static { -+ // cache all of the default states at startup, will not cache ones with the custom states inside of the -+ // brackets in a different order, though -+ reloadCache(); -+ } -+ -+ public static void reloadCache() { -+ stringDataCache.clear(); -+ Block.REGISTRY_ID.forEach(blockData -> stringDataCache.put(blockData.toString(), blockData.createCraftBlockData())); -+ } -+ // Paper end -+ - public static CraftBlockData newData(Material material, String data) { - Preconditions.checkArgument(material == null || material.isBlock(), "Cannot get data for not block %s", material); - -+ // Paper start - cache block data strings -+ if (material != null) { -+ Block block = CraftMagicNumbers.getBlock(material); -+ if (block != null) { -+ MinecraftKey key = IRegistry.BLOCK.getKey(block); -+ data = data == null ? key.toString() : key + data; -+ } -+ } -+ -+ CraftBlockData cached = stringDataCache.computeIfAbsent(data, s -> createNewData(null, s)); -+ return (CraftBlockData) cached.clone(); -+ } -+ -+ private static CraftBlockData createNewData(Material material, String data) { -+ // Paper end - cache block data strings - IBlockData blockData; - Block block = CraftMagicNumbers.getBlock(material); - Map, Comparable> parsed = null; diff --git a/Unmapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/Unmapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch deleted file mode 100644 index 2e575c4648..0000000000 --- a/Unmapped-Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 25 Aug 2020 20:45:36 -0400 -Subject: [PATCH] Fix Entity Teleportation and cancel velocity if teleported - -Uses correct setPositionRotation for Entity teleporting instead of setLocation -as this is how Vanilla teleports entities. - -Cancel any pending motion when teleported. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index d3449dc9eeba0d8022c3a7b0280eaffcd42e7265..fe3bd1c54a7e366bd4f02b417f7725bae60a3ca2 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -693,7 +693,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - public void a(PacketPlayInTeleportAccept packetplayinteleportaccept) { - PlayerConnectionUtils.ensureMainThread(packetplayinteleportaccept, this, this.player.getWorldServer()); - if (packetplayinteleportaccept.b() == this.teleportAwait && this.teleportPos != null) { // CraftBukkit -- this.player.setLocation(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); -+ this.player.setPositionRotation(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); // Paper - use proper setPositionRotation for teleportation - this.o = this.teleportPos.x; - this.p = this.teleportPos.y; - this.q = this.teleportPos.z; -@@ -1538,7 +1538,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - - this.A = this.e; -- this.player.setLocation(d0, d1, d2, f, f1); -+ this.player.setPositionRotation(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation - this.player.forceCheckHighPriority(); // Paper - this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.teleportAwait)); - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f5bb9313a249bfd4e63ab77e19cfd6f997d22fb1..a1fb19d45ee3809ee6a515669ba64ea45b31428c 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -145,6 +145,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - // CraftBukkit start - private static final int CURRENT_LEVEL = 2; -+ public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation - static boolean isLevelAtLeast(NBTTagCompound tag, int level) { - return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; - } -@@ -1408,6 +1409,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public void setPositionRotation(double d0, double d1, double d2, float f, float f1) { -+ // Paper - cancel entity velocity if teleported -+ if (!preserveMotion) { -+ this.mot = Vec3D.ORIGIN; -+ } else { -+ this.preserveMotion = false; -+ } -+ // Paper end - this.g(d0, d1, d2); - this.yaw = f; - this.pitch = f1; -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 5538404456dfee42257fad9040fcc0fefdfc5fab..33a5dbcc11455f81088d9fd685a8c4b1b8f4b1f2 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -165,6 +165,7 @@ public abstract class MobSpawnerAbstract { - return; - } - -+ entity.preserveMotion = true; // Paper - preserve entity motion from tag - entity.setPositionRotation(entity.locX(), entity.locY(), entity.locZ(), world.random.nextFloat() * 360.0F, 0.0F); - if (entity instanceof EntityInsentient) { - EntityInsentient entityinsentient = (EntityInsentient) entity; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 387f6f6fa9bbb1cce544cfb907f68c7993752dd7..fb52a60437d48282f3e99e7eccb0e76b446155f9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -558,7 +558,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - } - - // entity.setLocation() throws no event, and so cannot be cancelled -- entity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); -+ entity.setPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); // Paper - use proper setPosition, as per vanilla teleporting - // SPIGOT-619: Force sync head rotation also - entity.setHeadRotation(location.getYaw()); - ((net.minecraft.server.level.WorldServer) entity.world).chunkCheck(entity); // Spigot - register to new chunk diff --git a/Unmapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch b/Unmapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch deleted file mode 100644 index 467260a9f3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 26 Aug 2020 02:12:31 -0400 -Subject: [PATCH] Add additional open container api 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 4028f4bd87a183a808f4c9a19d51ee1c9b9e30f7..0a0e9df604723802fe65d871ff48aa9fd9b756bf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -460,6 +460,70 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - return this.getHandle().activeContainer.getBukkitView(); - } - -+ // Paper start - Add additional containers -+ @Override -+ public InventoryView openAnvil(Location location, boolean force) { -+ return openInventory(location, force, Material.ANVIL); -+ } -+ -+ @Override -+ public InventoryView openCartographyTable(Location location, boolean force) { -+ return openInventory(location, force, Material.CARTOGRAPHY_TABLE); -+ } -+ -+ @Override -+ public InventoryView openGrindstone(Location location, boolean force) { -+ return openInventory(location, force, Material.GRINDSTONE); -+ } -+ -+ @Override -+ public InventoryView openLoom(Location location, boolean force) { -+ return openInventory(location, force, Material.LOOM); -+ } -+ -+ @Override -+ public InventoryView openSmithingTable(Location location, boolean force) { -+ return openInventory(location, force, Material.SMITHING_TABLE); -+ } -+ -+ @Override -+ public InventoryView openStonecutter(Location location, boolean force) { -+ return openInventory(location, force, Material.STONECUTTER); -+ } -+ -+ private InventoryView openInventory(Location location, boolean force, Material material) { -+ org.spigotmc.AsyncCatcher.catchOp("open" + material); -+ if (location == null) { -+ location = getLocation(); -+ } -+ if (!force) { -+ Block block = location.getBlock(); -+ if (block.getType() != material) { -+ return null; -+ } -+ } -+ net.minecraft.world.level.block.Block block; -+ if (material == Material.ANVIL) { -+ block = Blocks.ANVIL; -+ } else if (material == Material.CARTOGRAPHY_TABLE) { -+ block = Blocks.CARTOGRAPHY_TABLE; -+ } else if (material == Material.GRINDSTONE) { -+ block = Blocks.GRINDSTONE; -+ } else if (material == Material.LOOM) { -+ block = Blocks.LOOM; -+ } else if (material == Material.SMITHING_TABLE) { -+ block = Blocks.SMITHING_TABLE; -+ } else if (material == Material.STONECUTTER) { -+ block = Blocks.STONECUTTER; -+ } else { -+ throw new IllegalArgumentException("Unsupported inventory type: " + material); -+ } -+ getHandle().openContainer(block.getInventory(null, getHandle().world, new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()))); -+ getHandle().activeContainer.checkReachable = !force; -+ return getHandle().activeContainer.getBukkitView(); -+ } -+ // Paper end -+ - @Override - public void closeInventory() { - // Paper start diff --git a/Unmapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/Unmapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch deleted file mode 100644 index a02addc375..0000000000 --- a/Unmapped-Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 12 Sep 2020 17:21:38 -0400 -Subject: [PATCH] Cache DataFixerUpper Rewrite Rules on demand - -Mojang precaches every single potential rewrite rule that could ever -exist on server startup. This includes rules from all the way back to versions from 6+ years ago. - -This is the source of why the server hogs every CPU core at 100% every start. - -For anyone who hard resets for updates or has force upgraded their entire world, this -results in completely wasted cpu cycles. - -This massive CPU usage also delays server startup time. - -We improve this by making "min version to precache" that defaults to a future version -so that no rewrite rules are precached. - -someone who expects to be converting a lot chunks could theoretically set --DPaper.minPrecachedDatafixVersion= as a startup -parameter and only build from that point on. - -However this will likely never be needed as the server will still run -the same cache logic on demand when it's actually needed. The only -cost would be some delay on the FIRST chunk conversion, but paper already -runs chunk conversions on another thread so this will likely never be -a concern for TPS. - -This patch will significantly reduce CPU use on startup, reduce memory usage, -and improve server startup time. - -diff --git a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java -index edb77982d273e9492ab1a669ca1ad89da2ec3c3e..abc265b00044b14abb55c2628d454ee01fef467b 100644 ---- a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java -+++ b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java -@@ -26,8 +26,10 @@ public class DataFixerBuilder { - private final Int2ObjectSortedMap schemas = new Int2ObjectAVLTreeMap<>(); - private final List globalList = Lists.newArrayList(); - private final IntSortedSet fixerVersions = new IntAVLTreeSet(); -+ private final int minDataFixPrecacheVersion; // Paper - - public DataFixerBuilder(final int dataVersion) { -+ minDataFixPrecacheVersion = Integer.getInteger("Paper.minPrecachedDatafixVersion", dataVersion+1) * 10; // Paper - default to precache nothing - mojang stores versions * 10 to allow for 'sub versions' - this.dataVersion = dataVersion; - } - -@@ -65,6 +67,7 @@ public class DataFixerBuilder { - final IntBidirectionalIterator iterator = fixerUpper.fixerVersions().iterator(); - while (iterator.hasNext()) { - final int versionKey = iterator.nextInt(); -+ if (versionKey < minDataFixPrecacheVersion) continue; // Paper - final Schema schema = schemas.get(versionKey); - for (final String typeName : schema.types()) { - CompletableFuture.runAsync(() -> { diff --git a/Unmapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch b/Unmapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch deleted file mode 100644 index 679487e3af..0000000000 --- a/Unmapped-Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 17 Sep 2020 00:36:05 +0100 -Subject: [PATCH] Extend block drop capture to capture all items added to the - world - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 984209e4f66ad23d85d2c5d02318caab1aff7324..31012963815a5c7355753b8cd2749976282ef0d2 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -12,6 +12,7 @@ import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.ITileInventory; - import net.minecraft.world.InteractionResultWrapper; -+import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.context.ItemActionContext; -@@ -419,10 +420,12 @@ public class PlayerInteractManager { - // return true; // CraftBukkit - } - // CraftBukkit start -+ java.util.List itemsToDrop = world.captureDrops; // Paper - store current list -+ world.captureDrops = null; // Paper - Remove this earlier so that we can actually drop stuff - if (event.isDropItems()) { -- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, world.captureDrops); -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - use stored ref - } -- world.captureDrops = null; -+ //world.captureDrops = null; // Paper - move up - - // Drop event experience - if (flag && event != null) { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 70f8fbff2ac825b61c5c9f7c6830de3106e7926c..0f0a3b3776c607217a15c5f61d60f6a98f1c7584 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -99,6 +99,7 @@ import net.minecraft.world.entity.animal.EntityWaterAnimal; - import net.minecraft.world.entity.animal.horse.EntityHorseSkeleton; - import net.minecraft.world.entity.boss.EntityComplexPart; - import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; -+import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.npc.NPC; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.raid.PersistentRaid; -@@ -1290,6 +1291,13 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } else if (this.isUUIDTaken(entity)) { - return false; - } else { -+ // Paper start - capture all item additions to the world -+ if (captureDrops != null && entity instanceof EntityItem) { -+ captureDrops.add((EntityItem) entity); -+ return true; -+ } -+ // Paper end -+ - if (!CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { - return false; - } diff --git a/Unmapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/Unmapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch deleted file mode 100644 index 974a34ff2f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sun, 27 Sep 2020 16:25:24 +0200 -Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086) - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 00cebd33101916f29bbc192d531ac0fba31e037b..a323b76f68c273a73cb3f20167a668b2100f4944 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -389,6 +389,7 @@ public class PlayerChunk { - } - - public void a(BlockPosition blockposition) { -+ if (!blockposition.isValidLocation()) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks - Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { diff --git a/Unmapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/Unmapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch deleted file mode 100644 index f2eed564bc..0000000000 --- a/Unmapped-Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Fri, 28 Aug 2020 01:41:26 +0200 -Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and - non-conflicting Entity Ids - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a1fb19d45ee3809ee6a515669ba64ea45b31428c..9b6e5f279a22efc2d015e2d31076a8c06e6b3886 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -3478,4 +3478,10 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - void accept(Entity entity, double d0, double d1, double d2); - } -+ -+ // Paper start -+ public static int nextEntityId() { -+ return entityCount.incrementAndGet(); -+ } -+ // 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 8049063ea37f3e0eac3f3a26703adc80fc99341a..5b03187f4d76e3052ee9abe0ee2774218d41b864 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -445,6 +445,10 @@ public final class CraftMagicNumbers implements UnsafeValues { - net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); - return nmsItemStack.getItem().getDescriptionId(nmsItemStack); - } -+ -+ public int nextEntityId() { -+ return net.minecraft.world.entity.Entity.nextEntityId(); -+ } - // Paper end - - /** diff --git a/Unmapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch b/Unmapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch deleted file mode 100644 index 974e02ca68..0000000000 --- a/Unmapped-Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Sat, 3 Oct 2020 04:15:09 -0400 -Subject: [PATCH] Lazily track plugin scoreboards by default - -On servers with plugins that constantly churn through scoreboards, there is a risk of -degraded GC performance due to the number of scoreboards held on by weak references. -Most plugins don't even need the (vanilla) functionality that requires all plugin -scoreboards to be tracked by the server. Instead, only track scoreboards when an -objective is added with a non-dummy criteria. - -This is a breaking change, however the change is a much more sensible default. In case -this breaks your workflow you can always force all scoreboards to be tracked with -settings.track-plugin-scoreboards in paper.yml. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 545948f20efd6c8dd42140b565af94cd6b52b661..7d50aded88f5b7dfebaea1aebc86231f7b5c4e25 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -462,4 +462,9 @@ public class PaperConfig { - private static void maxJoinsPerTick() { - maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); - } -+ -+ public static boolean trackPluginScoreboards; -+ private static void trackPluginScoreboards() { -+ trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -index 6ea491f6308317059c4bc6735abbdce370df0f34..3dfb6ad1ed5fae773b88cbe9ad540fd2520b8b50 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -@@ -19,6 +19,7 @@ import org.bukkit.scoreboard.Team; - - public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - final Scoreboard board; -+ boolean registeredGlobally = false; // Paper - - CraftScoreboard(Scoreboard board) { - this.board = board; -@@ -45,6 +46,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); - Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); - CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ // Paper start - the block comment from the old registerNewObjective didnt cause a conflict when rebasing, so this block wasn't added to the adventure registerNewObjective -+ if (craftCriteria.criteria != net.minecraft.world.scores.criteria.IScoreboardCriteria.DUMMY && !registeredGlobally) { -+ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); -+ registeredGlobally = true; -+ } -+ // Paper end - ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); - return new CraftObjective(this, objective); - } -@@ -66,6 +73,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); - - CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ // Paper start -+ if (craftCriteria.criteria != net.minecraft.server.IScoreboardCriteria.DUMMY && !registeredGlobally) { -+ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); -+ registeredGlobally = true; -+ } -+ // Paper end - ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); - return new CraftObjective(this, objective);*/ // Paper - return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -index 73663bcea163cda26f531902141a9ad3ad7eba57..9c30a79cc55c6455aa18e3798728deaacc3434ca 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -@@ -30,6 +30,7 @@ public final class CraftScoreboardManager implements ScoreboardManager { - - public CraftScoreboardManager(MinecraftServer minecraftserver, net.minecraft.world.scores.Scoreboard scoreboardServer) { - mainScoreboard = new CraftScoreboard(scoreboardServer); -+ mainScoreboard.registeredGlobally = true; // Paper - server = minecraftserver; - scoreboards.add(mainScoreboard); - } -@@ -43,10 +44,22 @@ public final class CraftScoreboardManager implements ScoreboardManager { - public CraftScoreboard getNewScoreboard() { - org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot - CraftScoreboard scoreboard = new CraftScoreboard(new ScoreboardServer(server)); -+ // Paper start -+ if (com.destroystokyo.paper.PaperConfig.trackPluginScoreboards) { -+ scoreboard.registeredGlobally = true; - scoreboards.add(scoreboard); -+ } -+ // Paper end - return scoreboard; - } - -+ // Paper start -+ public void registerScoreboardForVanilla(CraftScoreboard scoreboard) { -+ org.spigotmc.AsyncCatcher.catchOp("scoreboard registration"); -+ scoreboards.add(scoreboard); -+ } -+ // Paper end -+ - // CraftBukkit method - public CraftScoreboard getPlayerBoard(CraftPlayer player) { - CraftScoreboard board = playerBoards.get(player); diff --git a/Unmapped-Spigot-Server-Patches/0573-Entity-isTicking.patch b/Unmapped-Spigot-Server-Patches/0573-Entity-isTicking.patch deleted file mode 100644 index c92576011d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0573-Entity-isTicking.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 21:39:16 -0500 -Subject: [PATCH] Entity#isTicking - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 9b6e5f279a22efc2d015e2d31076a8c06e6b3886..d072e3fb26f32db80be68f0e23526e34f57ff331 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -48,6 +48,7 @@ import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.TicketType; -@@ -3483,5 +3484,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public static int nextEntityId() { - return entityCount.incrementAndGet(); - } -+ -+ public boolean isTicking() { -+ return ((ChunkProviderServer) world.getChunkProvider()).isInEntityTickingChunk(this); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index fb52a60437d48282f3e99e7eccb0e76b446155f9..295ffab08672d77d88aca368cb5b56f80bc4f1b5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1161,5 +1161,9 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public boolean isInLava() { - return getHandle().isInLava(); - } -+ -+ public boolean isTicking() { -+ return getHandle().isTicking(); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/Unmapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch deleted file mode 100644 index b5c0ba6314..0000000000 --- a/Unmapped-Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 22:00:27 -0500 -Subject: [PATCH] Fix deop kicking non-whitelisted player when white list is - not enabled - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 1af99b938382d3d229f1fbf6250e1f0e09da4819..bea7887c1adee93cfef17d910c3df3eb60cb681c 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2020,6 +2020,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant list = Lists.newArrayList(playerlist.getPlayers()); - Iterator iterator = list.iterator(); - diff --git a/Unmapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch b/Unmapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch deleted file mode 100644 index 26697d6feb..0000000000 --- a/Unmapped-Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 8 Oct 2020 00:00:25 -0400 -Subject: [PATCH] Fix "Not a string" Map Conversion spam - -The maps did convert successfully, but had noisy logs due to Spigot -implementing this logic incorrectly. - -This stops the spam by converting the old format to new before -requesting the world. - -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -index d470af1814af332595c1c0beb1cdc552e186a6bb..1f9b710f2af3c5067b3c2b73bebb11f8e22c403e 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -@@ -11,8 +11,10 @@ import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.DynamicOpsNBT; - import net.minecraft.nbt.NBTBase; -+import net.minecraft.nbt.NBTNumber; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; -+import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.PacketPlayOutMap; -@@ -94,7 +96,26 @@ public class WorldMap extends PersistentBase { - - @Override - public void a(NBTTagCompound nbttagcompound) { -- DataResult> dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, nbttagcompound.get("dimension"))); // CraftBukkit - decompile error -+ // Paper start - fix "Not a string" spam -+ NBTBase dimension = nbttagcompound.get("dimension"); -+ if (dimension instanceof NBTNumber && ((NBTNumber) dimension).asInt() >= CraftWorld.CUSTOM_DIMENSION_OFFSET) { -+ long least = nbttagcompound.getLong("UUIDLeast"); -+ long most = nbttagcompound.getLong("UUIDMost"); -+ -+ if (least != 0L && most != 0L) { -+ this.uniqueId = new UUID(most, least); -+ CraftWorld world = (CraftWorld) server.getWorld(this.uniqueId); -+ if (world != null) { -+ dimension = NBTTagString.create("minecraft:" + world.getName().toLowerCase(java.util.Locale.ENGLISH)); -+ } else { -+ dimension = NBTTagString.create("bukkit:_invalidworld_"); -+ } -+ } else { -+ dimension = NBTTagString.create("bukkit:_invalidworld_"); -+ } -+ } -+ DataResult> dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, dimension)); // CraftBukkit - decompile error -+ // Paper end - fix "Not a string" spam - Logger logger = WorldMap.LOGGER; - - logger.getClass(); diff --git a/Unmapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/Unmapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch deleted file mode 100644 index 6958041776..0000000000 --- a/Unmapped-Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Sun, 4 Oct 2020 19:55:25 -0700 -Subject: [PATCH] Fix CME on adding a passenger in CreatureSpawnEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d072e3fb26f32db80be68f0e23526e34f57ff331..0841cf7e968a8a3b577e91f6dcd0487169474329 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -3182,7 +3182,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public Stream recursiveStream() { -- return Stream.concat(Stream.of(this), this.passengers.stream().flatMap(Entity::recursiveStream)); -+ return Stream.concat(Stream.of(this), com.google.common.collect.ImmutableList.copyOf(this.passengers).stream().flatMap(Entity::recursiveStream)); // Paper - } - - public boolean hasSinglePlayerPassenger() { diff --git a/Unmapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch b/Unmapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch deleted file mode 100644 index 42d7399da7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Wed, 18 Mar 2020 00:07:46 -0500 -Subject: [PATCH] MC-147729: Drop items that are extra from a crafting recipe - - -diff --git a/src/main/java/net/minecraft/recipebook/AutoRecipe.java b/src/main/java/net/minecraft/recipebook/AutoRecipe.java -index 897f7270bae601b39d74d6a56a60f0ac7f1f6090..3bcd2c5a5352b8fb92d09b0a6914a1013569c8d6 100644 ---- a/src/main/java/net/minecraft/recipebook/AutoRecipe.java -+++ b/src/main/java/net/minecraft/recipebook/AutoRecipe.java -@@ -71,7 +71,12 @@ public class AutoRecipe implements AutoRecipeAbstract -Date: Wed, 1 Jun 2016 23:29:17 -0400 -Subject: [PATCH] Reset Ender Crystals on Dragon Spawn - -Crystals can end up in a bad state in certain conditions which causes -an exception on the expected number of crystals going negative. - -This ensures the crystals/pillars are in expected state when the dragon spawns. - -See #3522 - -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index 0869af4670f040344f5b6c2c10bff5e5226f707c..c6283489dcb6e13f0d618971614aeadaee2e3007 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -445,6 +445,7 @@ public class EnderDragonBattle { - entityenderdragon.setPositionRotation(0.0D, 128.0D, 0.0D, this.world.random.nextFloat() * 360.0F, 0.0F); - this.world.addEntity(entityenderdragon); - this.dragonUUID = entityenderdragon.getUniqueID(); -+ this.resetCrystals(); // Paper - return entityenderdragon; - } - diff --git a/Unmapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch b/Unmapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch deleted file mode 100644 index ba892e4738..0000000000 --- a/Unmapped-Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 17 May 2020 23:47:33 -0700 -Subject: [PATCH] Fix for large move vectors crashing server - -Check movement distance also based on current position. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index fe3bd1c54a7e366bd4f02b417f7725bae60a3ca2..73a1730f1c683b2345a9c3d4f2288ceab20a6625 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -518,19 +518,24 @@ public class PlayerConnection implements PacketListenerPlayIn { - - if (entity != this.player && entity.getRidingPassenger() == this.player && entity == this.r) { - WorldServer worldserver = this.player.getWorldServer(); -- double d0 = entity.locX(); -- double d1 = entity.locY(); -- double d2 = entity.locZ(); -- double d3 = packetplayinvehiclemove.getX(); -- double d4 = packetplayinvehiclemove.getY(); -- double d5 = packetplayinvehiclemove.getZ(); -+ double d0 = entity.locX();double fromX = d0; // Paper - OBFHELPER -+ double d1 = entity.locY();double fromY = d1; // Paper - OBFHELPER -+ double d2 = entity.locZ();double fromZ = d2; // Paper - OBFHELPER -+ double d3 = packetplayinvehiclemove.getX();double toX = d3; // Paper - OBFHELPER -+ double d4 = packetplayinvehiclemove.getY();double toY = d4; // Paper - OBFHELPER -+ double d5 = packetplayinvehiclemove.getZ();double toZ = d5; // Paper - OBFHELPER - float f = packetplayinvehiclemove.getYaw(); - float f1 = packetplayinvehiclemove.getPitch(); - double d6 = d3 - this.s; - double d7 = d4 - this.t; - double d8 = d5 - this.u; - double d9 = entity.getMot().g(); -- double d10 = d6 * d6 + d7 * d7 + d8 * d8; -+ // Paper start - fix large move vectors killing the server -+ double currDeltaX = toX - fromX; -+ double currDeltaY = toY - fromY; -+ double currDeltaZ = toZ - fromZ; -+ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); -+ // Paper end - fix large move vectors killing the server - - - // CraftBukkit start - handle custom speeds and skipped ticks -@@ -1232,7 +1237,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - double d2 = this.player.locZ(); - double d3 = this.player.locY(); - double d4 = packetplayinflying.a(this.player.locX());double toX = d4; // Paper - OBFHELPER -- double d5 = packetplayinflying.b(this.player.locY()); -+ double d5 = packetplayinflying.b(this.player.locY());double toY = d5; // Paper - OBFHELPER - double d6 = packetplayinflying.c(this.player.locZ());double toZ = d6; // Paper - OBFHELPER - float f = packetplayinflying.a(this.player.yaw); - float f1 = packetplayinflying.b(this.player.pitch); -@@ -1240,7 +1245,12 @@ public class PlayerConnection implements PacketListenerPlayIn { - double d8 = d5 - this.m; - double d9 = d6 - this.n; - double d10 = this.player.getMot().g(); -- double d11 = d7 * d7 + d8 * d8 + d9 * d9; -+ // Paper start - fix large move vectors killing the server -+ double currDeltaX = toX - prevX; -+ double currDeltaY = toY - prevY; -+ double currDeltaZ = toZ - prevZ; -+ double d11 = Math.max(d7 * d7 + d8 * d8 + d9 * d9, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); -+ // Paper end - fix large move vectors killing the server - - if (this.player.isSleeping()) { - if (d11 > 1.0D) { diff --git a/Unmapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch b/Unmapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch deleted file mode 100644 index 16993ab18d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0580-Optimise-getType-calls.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 3 Jun 2020 11:37:13 -0700 -Subject: [PATCH] Optimise getType calls - -Remove the map lookup for converting from Block->Bukkit Material - -diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockData.java b/src/main/java/net/minecraft/world/level/block/state/IBlockData.java -index 9e1ebfd7befe9e2fc3396b4dcd5e8fc7c23ee305..ed28710fefee4fad96290b2d166ac9dfe3d1fa6e 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/IBlockData.java -+++ b/src/main/java/net/minecraft/world/level/block/state/IBlockData.java -@@ -11,6 +11,19 @@ public class IBlockData extends BlockBase.BlockData { - - public static final Codec b = a((Codec) IRegistry.BLOCK, Block::getBlockData).stable(); - -+ -+ // Paper start - optimise getType calls -+ org.bukkit.Material cachedMaterial; -+ -+ public final org.bukkit.Material getBukkitMaterial() { -+ if (this.cachedMaterial == null) { -+ this.cachedMaterial = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(this.getBlock()); -+ } -+ -+ return this.cachedMaterial; -+ } -+ // Paper end - optimise getType calls -+ - public IBlockData(Block block, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { - super(block, immutablemap, mapcodec); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -index aa20cecc93ac53ce7f1b956ea5065ae80b55cff5..fc65c138bab242d5b533381ea496a2a48fcd91ea 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -@@ -79,7 +79,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot { - public Material getBlockType(int x, int y, int z) { - CraftChunk.validateChunkCoordinates(x, y, z); - -- return CraftMagicNumbers.getMaterial(blockids[y >> 4].a(x, y & 0xF, z).getBlock()); -+ return blockids[y >> 4].a(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index ee8977a1e4a83598ba7873c4c482fea828c6b26c..f1f03bd0162a158761f300cbd96aa32101542abb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -214,7 +214,7 @@ public class CraftBlock implements Block { - - @Override - public Material getType() { -- return CraftMagicNumbers.getMaterial(world.getType(position).getBlock()); -+ return world.getType(position).getBukkitMaterial(); // Paper - optimise getType calls - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -index b7ce677572f1f5ed01f3a8caf9368222e03bb69c..1960f01b5e4d7bff96d466e9a48f1d5300f261d1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -@@ -135,7 +135,7 @@ public class CraftBlockState implements BlockState { - - @Override - public Material getType() { -- return CraftMagicNumbers.getMaterial(data.getBlock()); -+ return data.getBukkitMaterial(); // Paper - optimise getType calls - } - - public void setFlag(int flag) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -index 58f892478de74b853cd35ef2fec8c462e3a9ecee..1fe9b32c2a3717652be70786090a61c5fa7430cf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -@@ -45,7 +45,7 @@ public class CraftBlockData implements BlockData { - - @Override - public Material getMaterial() { -- return CraftMagicNumbers.getMaterial(state.getBlock()); -+ return state.getBukkitMaterial(); // Paper - optimise getType calls - } - - public IBlockData getState() { -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index d02281f954aac8d8b65f5d36ec70f0352e4c7cdd..2194232200e90fa894b45eb265b5ed08ce1e35a3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -73,7 +73,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - - @Override - public Material getType(int x, int y, int z) { -- return CraftMagicNumbers.getMaterial(getTypeId(x, y, z).getBlock()); -+ return getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch b/Unmapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch deleted file mode 100644 index 5c18995906..0000000000 --- a/Unmapped-Spigot-Server-Patches/0581-Villager-resetOffers.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Mon, 7 Oct 2019 00:15:37 -0500 -Subject: [PATCH] Villager#resetOffers - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -index 3dd80fcf9237f15bb3bf38d1529340e178f09388..a614f5d5817bf999aca0f0b50f343031c8168392 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -@@ -113,6 +113,13 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - return this.tradingPlayer != null; - } - -+ // Paper start -+ public void resetOffers() { -+ this.trades = new MerchantRecipeList(); -+ this.updateTrades(); -+ } -+ // Paper end -+ - @Override - public MerchantRecipeList getOffers() { - if (this.trades == null) { -@@ -235,6 +242,7 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - return this.world; - } - -+ protected final void updateTrades() { eW(); } // Paper - OBFHELPER - protected abstract void eW(); - - protected void a(MerchantRecipeList merchantrecipelist, VillagerTrades.IMerchantRecipeOption[] avillagertrades_imerchantrecipeoption, int i) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -index 01285d555ed084fa2e818e1f02955f8aa28002b3..ee751ed4f9f386bf9926347fe2f0958015aecffa 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -@@ -71,4 +71,11 @@ public class CraftAbstractVillager extends CraftAgeable implements AbstractVilla - public HumanEntity getTrader() { - return getMerchant().getTrader(); - } -+ -+ // Paper start -+ @Override -+ public void resetOffers() { -+ getHandle().resetOffers(); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/Unmapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch deleted file mode 100644 index 124a856cdf..0000000000 --- a/Unmapped-Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Jul 2020 20:46:50 -0700 -Subject: [PATCH] Improve inlinig for some hot IBlockData methods - - -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 9af91784544dbb0555824a91088257659bdf2c3d..3fdafc0ff0c4148ec844dbdc1455d17cdcb4a75a 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -391,7 +391,14 @@ public abstract class BlockBase { - } - // Paper end - -+ // Paper start -+ protected boolean isTicking; -+ protected Fluid fluid; -+ // Paper end -+ - public void a() { -+ this.fluid = this.getBlock().d(this.p()); // Paper - moved from getFluid() -+ this.isTicking = this.getBlock().isTicking(this.p()); // Paper - moved from isTicking() - if (!this.getBlock().o()) { - this.a = new BlockBase.BlockData.Cache(this.p()); - } -@@ -430,19 +437,19 @@ public abstract class BlockBase { - return this.getBlock().d(this.p(), iblockaccess, blockposition); - } - -- public boolean d() { -+ public final boolean d() { // Paper - return this.a == null || this.a.c; - } - -- public boolean e() { -+ public final boolean e() { // Paper - return this.e; - } - -- public int f() { -+ public final int f() { // Paper - return this.b; - } - -- public boolean isAir() { -+ public final boolean isAir() { // Paper - return this.f; - } - -@@ -508,7 +515,7 @@ public abstract class BlockBase { - } - } - -- public boolean l() { -+ public final boolean l() { // Paper - return this.k; - } - -@@ -680,12 +687,12 @@ public abstract class BlockBase { - return this.getBlock().a(block); - } - -- public Fluid getFluid() { -- return this.getBlock().d(this.p()); -+ public final Fluid getFluid() { // Paper -+ return this.fluid; // Paper - moved into init - } - -- public boolean isTicking() { -- return this.getBlock().isTicking(this.p()); -+ public final boolean isTicking() { // Paper -+ return this.isTicking; // Paper - moved into init - } - - public SoundEffectType getStepSound() { -diff --git a/src/main/java/net/minecraft/world/level/material/Fluid.java b/src/main/java/net/minecraft/world/level/material/Fluid.java -index 9a93b204973eef4c02a52f33fd9578a43603ed98..147e628bd562da4cf6f07218724a9d6c79d26e38 100644 ---- a/src/main/java/net/minecraft/world/level/material/Fluid.java -+++ b/src/main/java/net/minecraft/world/level/material/Fluid.java -@@ -20,8 +20,12 @@ public final class Fluid extends IBlockDataHolder { - - public static final Codec a = a((Codec) IRegistry.FLUID, FluidType::h).stable(); - -+ // Paper start -+ protected final boolean isEmpty; -+ // Paper end - public Fluid(FluidType fluidtype, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { - super(fluidtype, immutablemap, mapcodec); -+ this.isEmpty = fluidtype.b(); // Paper - moved from isEmpty() - } - - public FluidType getType() { -@@ -33,7 +37,7 @@ public final class Fluid extends IBlockDataHolder { - } - - public boolean isEmpty() { -- return this.getType().b(); -+ return this.isEmpty; // Paper - moved into constructor - } - - public float getHeight(IBlockAccess iblockaccess, BlockPosition blockposition) { diff --git a/Unmapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch b/Unmapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch deleted file mode 100644 index 418df80756..0000000000 --- a/Unmapped-Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 7 Aug 2020 04:27:56 -0700 -Subject: [PATCH] Retain block place order when capturing blockstates - -Fixes twisted vines not connecting properly when grown via -bonemeal by a player. - -In general, look at making this logic more robust (i.e properly handling -cases where a captured entry is overriden) - but for now this will do. - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 307a89c431739ed15d8869faace7b08927626f60..ae5f9a6af810b524f6dcbed64bc943122f0536cc 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -135,7 +135,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; - public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper -- public Map capturedTileEntities = new HashMap<>(); -+ public Map capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - public List captureDrops; - public long ticksPerAnimalSpawns; - public long ticksPerMonsterSpawns; diff --git a/Unmapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch b/Unmapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch deleted file mode 100644 index 2640189324..0000000000 --- a/Unmapped-Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 25 Apr 2020 17:10:55 -0700 -Subject: [PATCH] Reduce blockpos allocation from pathfinding - - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -index d14f2800237c2a80912bf6f2d418a9ba9031070d..a0c7d3ab747ba1a3cf07e716f3591663a8a9e14b 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -@@ -498,7 +498,7 @@ public class PathfinderNormal extends PathfinderAbstract { - return PathType.DANGER_FIRE; - } - -- if (iblockaccess.getFluid(blockposition_mutableblockposition).a((Tag) TagsFluid.WATER)) { -+ if (iblockdata.getFluid().a((Tag) TagsFluid.WATER)) { // Paper - remove another getType call - return PathType.WATER_BORDER; - } - } // Paper -@@ -528,7 +528,7 @@ public class PathfinderNormal extends PathfinderAbstract { - } else if (iblockdata.a(Blocks.COCOA)) { - return PathType.COCOA; - } else { -- Fluid fluid = iblockaccess.getFluid(blockposition); -+ Fluid fluid = iblockdata.getFluid(); // Paper - remove another get type call - - return fluid.a((Tag) TagsFluid.WATER) ? PathType.WATER : (fluid.a((Tag) TagsFluid.LAVA) ? PathType.LAVA : (a(iblockdata) ? PathType.DAMAGE_FIRE : (BlockDoor.l(iblockdata) && !(Boolean) iblockdata.get(BlockDoor.OPEN) ? PathType.DOOR_WOOD_CLOSED : (block instanceof BlockDoor && material == Material.ORE && !(Boolean) iblockdata.get(BlockDoor.OPEN) ? PathType.DOOR_IRON_CLOSED : (block instanceof BlockDoor && (Boolean) iblockdata.get(BlockDoor.OPEN) ? PathType.DOOR_OPEN : (block instanceof BlockMinecartTrackAbstract ? PathType.RAIL : (block instanceof BlockLeaves ? PathType.LEAVES : (!block.a((Tag) TagsBlock.FENCES) && !block.a((Tag) TagsBlock.WALLS) && (!(block instanceof BlockFenceGate) || (Boolean) iblockdata.get(BlockFenceGate.OPEN)) ? (!iblockdata.a(iblockaccess, blockposition, PathMode.LAND) ? PathType.BLOCKED : PathType.OPEN) : PathType.FENCE)))))))); - } diff --git a/Unmapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch b/Unmapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch deleted file mode 100644 index 764f6d7979..0000000000 --- a/Unmapped-Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 20:32:25 -0500 -Subject: [PATCH] Fix item locations dropped from campfires - -Fixes #4259 by not flooring the blockposition among other weirdness - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -index df010dc740f2dd647a418ba4e425ce3a3b1d79e2..62a19f39405cff27f34a3b98fb9310b1c9c27563 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -@@ -14,6 +14,7 @@ import net.minecraft.world.Clearable; - import net.minecraft.world.ContainerUtil; - import net.minecraft.world.InventorySubcontainer; - import net.minecraft.world.InventoryUtils; -+import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.crafting.RecipeCampfire; - import net.minecraft.world.item.crafting.Recipes; -@@ -92,7 +93,11 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab - result = blockCookEvent.getResult(); - itemstack1 = CraftItemStack.asNMSCopy(result); - // CraftBukkit end -- InventoryUtils.dropItem(this.world, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack1); -+ // Paper start -+ EntityItem droppedItem = new EntityItem(this.world, blockposition.getX() + 0.5D, blockposition.getY() + 0.5D, blockposition.getZ() + 0.5D, itemstack1.cloneAndSubtract(this.world.random.nextInt(21) + 10)); -+ droppedItem.setMot(this.world.random.nextGaussian() * 0.05D, this.world.random.nextGaussian() * 0.05D + 0.2D, this.world.random.nextGaussian() * 0.05D); -+ this.world.addEntity(droppedItem); -+ // Paper end - this.items.set(i, ItemStack.b); - this.k(); - } diff --git a/Unmapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch b/Unmapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch deleted file mode 100644 index aed9bb2247..0000000000 --- a/Unmapped-Spigot-Server-Patches/0586-Player-elytra-boost-API.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Tue, 14 Apr 2020 12:05:22 +0200 -Subject: [PATCH] Player elytra boost API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 18d7cf6e783843d44715210b7c8db7bf0a5c89ae..8337ed8bb20b8d887bcd71ddc5f29bce346c7cff 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -69,12 +69,14 @@ import net.minecraft.world.entity.ai.attributes.AttributeMapBase; - import net.minecraft.world.entity.ai.attributes.AttributeModifiable; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.player.EntityHuman; -+import net.minecraft.world.entity.projectile.EntityFireworks; - import net.minecraft.world.inventory.Container; - import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.item.enchantment.Enchantments; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; -+import net.minecraft.world.level.World; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.saveddata.maps.MapIcon; -@@ -2284,6 +2286,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - throw new RuntimeException("Unknown settings type"); - } -+ -+ @Override -+ public org.bukkit.entity.Firework boostElytra(ItemStack firework) { -+ Validate.isTrue(isGliding(), "Player must be gliding"); -+ Validate.isTrue(firework != null, "firework == null"); -+ Validate.isTrue(firework.getType() == Material.FIREWORK_ROCKET, "Firework must be Material.FIREWORK_ROCKET"); -+ -+ net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(firework); -+ World world = ((CraftWorld) getWorld()).getHandle(); -+ EntityFireworks entity = new EntityFireworks(world, item, getHandle()); -+ return world.addEntity(entity) -+ ? (org.bukkit.entity.Firework) entity.getBukkitEntity() -+ : null; -+ } - // Paper end - - // Spigot start diff --git a/Unmapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch b/Unmapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch deleted file mode 100644 index 879f752716..0000000000 --- a/Unmapped-Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: giacomo <32515303+giacomozama@users.noreply.github.com> -Date: Sat, 10 Oct 2020 12:15:33 +0200 -Subject: [PATCH] Fixed TileEntityBell memory leak - -TileEntityBell has a list of entities (entitiesAtRing) that was not being cleared at the right time, causing leaks whenever a bell would be rung near a crowd of entities. - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -index e97d229da3cf7631555f418a73bc74255494cc01..84f9f52c5b632621b509448ac1c760f64de6b062 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -@@ -27,8 +27,8 @@ public class TileEntityBell extends TileEntity implements ITickable { - public int a; - public boolean b; - public EnumDirection c; -- private List h; -- private boolean i; -+ private List h; private List getEntitiesAtRing() { return this.h; } // Paper - OBFHELPER -+ private boolean i; private boolean getShouldReveal() { return this.i; } // Paper - OBFHELPER - private int j; - - public TileEntityBell() { -@@ -57,6 +57,11 @@ public class TileEntityBell extends TileEntity implements ITickable { - - if (this.a >= 50) { - this.b = false; -+ // Paper start -+ if (!this.getShouldReveal()) { -+ this.getEntitiesAtRing().clear(); -+ } -+ // Paper end - this.a = 0; - } - -@@ -71,6 +76,7 @@ public class TileEntityBell extends TileEntity implements ITickable { - } else { - this.a(this.world); - this.b(this.world); -+ this.getEntitiesAtRing().clear(); // Paper - this.i = false; - } - } -@@ -111,11 +117,12 @@ public class TileEntityBell extends TileEntity implements ITickable { - EntityLiving entityliving = (EntityLiving) iterator.next(); - - if (entityliving.isAlive() && !entityliving.dead && blockposition.a((IPosition) entityliving.getPositionVector(), 32.0D)) { -- entityliving.getBehaviorController().setMemory(MemoryModuleType.HEARD_BELL_TIME, (Object) this.world.getTime()); -+ entityliving.getBehaviorController().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.world.getTime()); // Paper - decompile fix - } - } - } - -+ this.getEntitiesAtRing().removeIf(e -> !e.isAlive()); // Paper - } - - private boolean h() { diff --git a/Unmapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/Unmapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch deleted file mode 100644 index 183a7c372f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Toon Schoenmakers -Date: Fri, 23 Oct 2020 15:01:44 +0200 -Subject: [PATCH] Avoid error bubbling up when item stack is empty in fishing - loot - -This can realistically only happen if there's custom loot active on fishing -which can return 0 items. This would disconnect the player who's fishing. - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 38bcc5a4435c4018b3233cc5e4c9142259e4396d..45f0f004e97b20e5c6c5b1f205b088bf8aa86017 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -@@ -484,9 +484,15 @@ public class EntityFishingHook extends IProjectile { - - while (iterator.hasNext()) { - ItemStack itemstack1 = (ItemStack) iterator.next(); -- EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY(), this.locZ(), itemstack1); -+ // Paper start, new EntityItem would throw if for whatever reason (mostly shitty datapacks) the itemstack1 turns out to be empty -+ // if the item stack is empty we instead just have our entityitem as null -+ EntityItem entityitem = null; -+ if (!itemstack1.isEmpty()) { -+ entityitem = new EntityItem(this.world, this.locX(), this.locY(), this.locZ(), itemstack1); -+ } -+ // Paper end - // CraftBukkit start -- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); -+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null - playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); - this.world.getServer().getPluginManager().callEvent(playerFishEvent); - -@@ -499,8 +505,12 @@ public class EntityFishingHook extends IProjectile { - double d2 = entityhuman.locZ() - this.locZ(); - double d3 = 0.1D; - -- entityitem.setMot(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); -- this.world.addEntity(entityitem); -+ // Paper start, entity item can be null, so we need to check against this -+ if (entityitem != null) { -+ entityitem.setMot(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); -+ this.world.addEntity(entityitem); -+ } -+ // Paper end - // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() - if (playerFishEvent.getExpToDrop() > 0) { - entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getOwner(), this)); // Paper diff --git a/Unmapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch b/Unmapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch deleted file mode 100644 index 0661e01e89..0000000000 --- a/Unmapped-Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: oxygencraft <21054297+oxygencraft@users.noreply.github.com> -Date: Sun, 25 Oct 2020 18:34:50 +1100 -Subject: [PATCH] Add getOfflinePlayerIfCached(String) - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 4dceb2d0beb6f91526b101d4947556049a0f3251..7277fd5807254020054cdbfb97fbd334e05da832 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1613,6 +1613,28 @@ public final class CraftServer implements Server { - return result; - } - -+ // Paper start -+ @Override -+ @Nullable -+ public OfflinePlayer getOfflinePlayerIfCached(String name) { -+ Validate.notNull(name, "Name cannot be null"); -+ Validate.notEmpty(name, "Name cannot be empty"); -+ -+ OfflinePlayer result = getPlayerExact(name); -+ if (result == null) { -+ GameProfile profile = console.getUserCache().getProfileIfCached(name); -+ -+ if (profile != null) { -+ result = getOfflinePlayer(profile); -+ } -+ } else { -+ offlinePlayers.remove(result.getUniqueId()); -+ } -+ -+ return result; -+ } -+ // Paper end -+ - @Override - public OfflinePlayer getOfflinePlayer(UUID id) { - Validate.notNull(id, "UUID cannot be null"); diff --git a/Unmapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch b/Unmapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch deleted file mode 100644 index 1736070f08..0000000000 --- a/Unmapped-Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Mon, 9 Nov 2020 20:44:51 +0100 -Subject: [PATCH] Add ignore discounts API - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 5e84e33ffdda85be96c3d31fbd6a2aa3eab1106a..d1ddb12e8bd83d2218165340fe323c6be7bc83dd 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -460,6 +460,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - - while (iterator.hasNext()) { - MerchantRecipe merchantrecipe = (MerchantRecipe) iterator.next(); -+ if (merchantrecipe.ignoreDiscounts) continue; // Paper - - // CraftBukkit start - int bonus = -MathHelper.d((float) i * merchantrecipe.getPriceMultiplier()); -@@ -479,6 +480,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - - while (iterator1.hasNext()) { - MerchantRecipe merchantrecipe1 = (MerchantRecipe) iterator1.next(); -+ if (merchantrecipe1.ignoreDiscounts) continue; // Paper - double d0 = 0.3D + 0.0625D * (double) j; - int k = (int) Math.floor(d0 * (double) merchantrecipe1.a().getCount()); - -diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -index 9e2fe0d5e6d4ea1f4c9cea96b755ddcd1e3c9009..605d1b2514c272c0fcf3cb9d7575ad8066dad31b 100644 ---- a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -+++ b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -@@ -19,6 +19,7 @@ public class MerchantRecipe { - private int demand; - public float priceMultiplier; - public int xp; -+ public boolean ignoreDiscounts; // Paper - // CraftBukkit start - private CraftMerchantRecipe bukkitHandle; - -@@ -27,7 +28,12 @@ public class MerchantRecipe { - } - - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { -- this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier); -+ // Paper start - add ignoreDiscounts param -+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, false, bukkit); -+ } -+ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) { -+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, ignoreDiscounts); -+ // Paper end - this.bukkitHandle = bukkit; - } - // CraftBukkit end -@@ -59,6 +65,7 @@ public class MerchantRecipe { - - this.specialPrice = nbttagcompound.getInt("specialPrice"); - this.demand = nbttagcompound.getInt("demand"); -+ this.ignoreDiscounts = nbttagcompound.getBoolean("Paper.IgnoreDiscounts"); // Paper - } - - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, int i, int j, float f) { -@@ -70,10 +77,19 @@ public class MerchantRecipe { - } - - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f) { -- this(itemstack, itemstack1, itemstack2, i, j, k, f, 0); -+ // Paper start - add ignoreDiscounts param -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, false); -+ } -+ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, boolean ignoreDiscounts) { -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, 0, ignoreDiscounts); - } - - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l) { -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, l, false); -+ } -+ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l, boolean ignoreDiscounts) { -+ this.ignoreDiscounts = ignoreDiscounts; -+ // Paper end - this.rewardExp = true; - this.xp = 1; - this.buyingItem1 = itemstack; -@@ -189,6 +205,7 @@ public class MerchantRecipe { - nbttagcompound.setFloat("priceMultiplier", this.priceMultiplier); - nbttagcompound.setInt("specialPrice", this.specialPrice); - nbttagcompound.setInt("demand", this.demand); -+ nbttagcompound.setBoolean("Paper.IgnoreDiscounts", this.ignoreDiscounts); // Paper - return nbttagcompound; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -index e3b9a0ebe5cec5b47d9d225887656e00e999960b..0c8728bd8272e36d70cf8f05fcd7656ea5a48702 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -@@ -17,7 +17,12 @@ public class CraftMerchantRecipe extends MerchantRecipe { - } - - public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier) { -- super(result, uses, maxUses, experienceReward, experience, priceMultiplier); -+ // Paper start - add ignoreDiscounts param -+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, false); -+ } -+ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, boolean ignoreDiscounts) { -+ super(result, uses, maxUses, experienceReward, experience, priceMultiplier, ignoreDiscounts); -+ // Paper end - this.handle = new net.minecraft.world.item.trading.MerchantRecipe( - net.minecraft.world.item.ItemStack.b, - net.minecraft.world.item.ItemStack.b, -@@ -26,6 +31,7 @@ public class CraftMerchantRecipe extends MerchantRecipe { - maxUses, - experience, - priceMultiplier, -+ ignoreDiscounts, // Paper - add ignoreDiscounts param - this - ); - this.setExperienceReward(experienceReward); -@@ -81,6 +87,18 @@ public class CraftMerchantRecipe extends MerchantRecipe { - handle.priceMultiplier = priceMultiplier; - } - -+ // Paper start -+ @Override -+ public boolean shouldIgnoreDiscounts() { -+ return this.handle.ignoreDiscounts; -+ } -+ -+ @Override -+ public void setIgnoreDiscounts(boolean ignoreDiscounts) { -+ this.handle.ignoreDiscounts = ignoreDiscounts; -+ } -+ // Paper end -+ - public net.minecraft.world.item.trading.MerchantRecipe toMinecraft() { - List ingredients = getIngredients(); - Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients"); -@@ -95,7 +113,7 @@ public class CraftMerchantRecipe extends MerchantRecipe { - if (recipe instanceof CraftMerchantRecipe) { - return (CraftMerchantRecipe) recipe; - } else { -- CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier()); -+ CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.shouldIgnoreDiscounts()); // Paper - shouldIgnoreDiscounts - craft.setIngredients(recipe.getIngredients()); - - return craft; diff --git a/Unmapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch b/Unmapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch deleted file mode 100644 index 724d1c2111..0000000000 --- a/Unmapped-Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 30 Sep 2020 22:49:14 +0200 -Subject: [PATCH] Toggle for removing existing dragon - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 02bb85364560784adea47c877c13291c3d016b86..424754a0183b071d20c86f0420cec784a8992e2b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -683,4 +683,12 @@ public class PaperWorldConfig { - log("Using vanilla redstone algorithm."); - } - } -+ -+ public boolean shouldRemoveDragon = false; -+ private void shouldRemoveDragon() { -+ shouldRemoveDragon = getBoolean("should-remove-dragon", shouldRemoveDragon); -+ if (shouldRemoveDragon) { -+ log("The Ender Dragon will be removed if she already exists without a portal."); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index c6283489dcb6e13f0d618971614aeadaee2e3007..c0a6b340810b8ea4f454290b1ac22316ff0e6e22 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -214,7 +214,7 @@ public class EnderDragonBattle { - this.dragonUUID = entityenderdragon.getUniqueID(); - EnderDragonBattle.LOGGER.info("Found that there's a dragon still alive ({})", entityenderdragon); - this.dragonKilled = false; -- if (!flag) { -+ if (!flag && this.world.paperConfig.shouldRemoveDragon) { // Paper - EnderDragonBattle.LOGGER.info("But we didn't have a portal, let's remove it."); - entityenderdragon.die(); - this.dragonUUID = null; diff --git a/Unmapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch b/Unmapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch deleted file mode 100644 index c2ef60d3c7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Sat, 31 Oct 2020 11:49:01 -0700 -Subject: [PATCH] Fix client lag on advancement loading - -When new advancements are added via the UnsafeValues#loadAdvancement -API, it triggers a full datapack reload when this is not necessary. The -advancement is already loaded directly into the advancement registry, -and the point of saving the advancement to the Bukkit datapack seems to -be for persistence. By removing the call to reload datapacks when an -advancement is loaded, the client no longer completely freezes up when -adding a new advancement. -To ensure the client still receives the updated advancement data, we -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/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index 8e760445885f6ab92f60db0ee2a02d098b5e5f03..7a8a1960882e291c46301d07da3e1c5415516893 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -97,6 +97,7 @@ public class AdvancementDataPlayer { - - } - -+ public final void reload(AdvancementDataWorld advancementDataWorld) { this.a(advancementDataWorld); } // Paper - OBFHELPER - public void a(AdvancementDataWorld advancementdataworld) { - this.a(); - this.data.clear(); -@@ -393,6 +394,7 @@ public class AdvancementDataPlayer { - - } - -+ public final void sendUpdateIfNeeded(EntityPlayer entityPlayer) { this.b(entityPlayer); } // Paper - OBFHELPER - public void b(EntityPlayer entityplayer) { - if (this.m || !this.i.isEmpty() || !this.j.isEmpty()) { - Map map = Maps.newHashMap(); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 5b03187f4d76e3052ee9abe0ee2774218d41b864..36ad77a5a3987c1de5d0de7cbcb94cb6fe841d44 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -309,7 +309,13 @@ public final class CraftMagicNumbers implements UnsafeValues { - Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex); - } - -- MinecraftServer.getServer().getPlayerList().reload(); -+ // Paper start -+ //MinecraftServer.getServer().getPlayerList().reload(); -+ MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> { -+ player.getAdvancementData().reload(MinecraftServer.getServer().getAdvancementData()); -+ player.getAdvancementData().sendUpdateIfNeeded(player); -+ }); -+ // Paper end - - return bukkit; - } diff --git a/Unmapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch b/Unmapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch deleted file mode 100644 index 84124da98a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Smith -Date: Sat, 7 Nov 2020 01:20:33 +0000 -Subject: [PATCH] Item no age & no player pickup - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -index 5988cdd18b7e4bfca0075fd2356cfe9c4e673954..7a78ef2f6f673568c0528fa46168c69d21f51a66 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -@@ -10,6 +10,12 @@ import org.bukkit.entity.Item; - import org.bukkit.inventory.ItemStack; - - public class CraftItem extends CraftEntity implements Item { -+ -+ // Paper start -+ private final static int NO_AGE_TIME = (int) Short.MIN_VALUE; -+ private final static int NO_PICKUP_TIME = (int) Short.MAX_VALUE; -+ // Paper end -+ - private final EntityItem item; - - public CraftItem(CraftServer server, Entity entity, EntityItem item) { -@@ -57,6 +63,26 @@ public class CraftItem extends CraftEntity implements Item { - public void setCanMobPickup(boolean canMobPickup) { - item.canMobPickup = canMobPickup; - } -+ -+ @Override -+ public boolean canPlayerPickup() { -+ return item.pickupDelay != NO_PICKUP_TIME; -+ } -+ -+ @Override -+ public void setCanPlayerPickup(boolean canPlayerPickup) { -+ item.pickupDelay = canPlayerPickup ? 0 : NO_PICKUP_TIME; -+ } -+ -+ @Override -+ public boolean willAge() { -+ return item.age != NO_AGE_TIME; -+ } -+ -+ @Override -+ public void setWillAge(boolean willAge) { -+ item.age = willAge ? 0 : NO_AGE_TIME; -+ } - // Paper End - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch b/Unmapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch deleted file mode 100644 index 7b77b21a0d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 12:39:08 -0600 -Subject: [PATCH] Beacon API - custom effect ranges - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -index 4098357d60165a4c670a7bc5134abf66178124c6..cd28a731a56eb7534faae5b120195b62d5d15bd4 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -@@ -73,6 +73,26 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - return (hasSecondaryEffect()) ? CraftPotionUtil.toBukkit(new MobEffect(this.secondaryEffect, getLevel(), getAmplification(), true, true)) : null; - } - // CraftBukkit end -+ // Paper start - add field/methods for custom range -+ private final String PAPER_RANGE_TAG = "Paper.Range"; -+ private double effectRange = -1; -+ -+ public double getEffectRange() { -+ if (this.effectRange < 0) { -+ return this.levels * 10 + 10; -+ } else { -+ return effectRange; -+ } -+ } -+ -+ public void setEffectRange(double range) { -+ this.effectRange = range; -+ } -+ -+ public void resetEffectRange() { -+ this.effectRange = -1; -+ } -+ // Paper end - - public TileEntityBeacon() { - super(TileEntityTypes.BEACON); -@@ -263,7 +283,8 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - - public List getHumansInRange() { - { -- double d0 = (double) (this.levels * 10 + 10); -+ // Paper - custom beacon ranges -+ double d0 = this.getEffectRange(); - - AxisAlignedBB axisalignedbb = (new AxisAlignedBB(this.position)).g(d0).b(0.0D, (double) this.world.getBuildHeight(), 0.0D); - List list = this.world.a(EntityHuman.class, axisalignedbb); -@@ -363,6 +384,9 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - this.secondaryEffect = MobEffectList.fromId(nbttagcompound.getInt("Secondary")); - this.levels = nbttagcompound.getInt("Levels"); // SPIGOT-5053, use where available - // CraftBukkit end -+ // Paper -+ this.effectRange = nbttagcompound.hasKeyOfType(PAPER_RANGE_TAG, 6) ? nbttagcompound.getDouble(PAPER_RANGE_TAG) : -1; -+ - if (nbttagcompound.hasKeyOfType("CustomName", 8)) { - this.customName = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName")); - } -@@ -379,6 +403,8 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - if (this.customName != null) { - nbttagcompound.setString("CustomName", IChatBaseComponent.ChatSerializer.a(this.customName)); - } -+ // Paper -+ nbttagcompound.setDouble(PAPER_RANGE_TAG, this.effectRange); - - this.chestLock.a(nbttagcompound); - return nbttagcompound; -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -index d3ae5cadd88f9012203d2c04cbe38af9b215ef0b..c2e054853cba891326d45e9129bbc09e32fa3cc7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -@@ -108,4 +108,19 @@ public class CraftBeacon extends CraftBlockEntityState impleme - public void setLock(String key) { - this.getSnapshot().chestLock = (key == null) ? ChestLock.a : new ChestLock(key); - } -+ -+ @Override -+ public double getEffectRange() { -+ return this.getSnapshot().getEffectRange(); -+ } -+ -+ @Override -+ public void setEffectRange(double range) { -+ this.getSnapshot().setEffectRange(range); -+ } -+ -+ @Override -+ public void resetEffectRange() { -+ this.getSnapshot().resetEffectRange(); -+ } - } diff --git a/Unmapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch b/Unmapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch deleted file mode 100644 index be191ccc04..0000000000 --- a/Unmapped-Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 14 Nov 2020 16:19:52 +0100 -Subject: [PATCH] Add API for quit reason - - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 878f879f8d410c428ad8a4c49e0c86c559bc47a9..f86f430598026a3a7e27fb8d40cfc5fe7b9b845d 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -137,12 +137,15 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - this.u = true; - if (this.channel.isOpen()) { -+ EntityPlayer player = this.getPlayer(); // Paper - if (throwable instanceof TimeoutException) { - NetworkManager.LOGGER.debug("Timeout", throwable); -+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper - this.close(new ChatMessage("disconnect.timeout")); - } else { - ChatMessage chatmessage = new ChatMessage("disconnect.genericReason", new Object[]{"Internal Exception: " + throwable}); - -+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper - if (flag) { - NetworkManager.LOGGER.debug("Failed to sent packet", throwable); - this.sendPacket(new PacketPlayOutKickDisconnect(chatmessage), (future) -> { -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 3908dc27a5cf127ab3c3630da47318da1bf4e3c9..78fcb90c86700ee6feef0d40753fc8d8a943777f 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -261,6 +261,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks - - boolean needsChunkCenterUpdate; // Paper - no-tick view distance -+ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event - - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 73a1730f1c683b2345a9c3d4f2288ceab20a6625..cf81710e41420f6cd027231998ebf5305f23f3d5 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -449,6 +449,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - final IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure - // CraftBukkit end - -+ this.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper - this.networkManager.sendPacket(new PacketPlayOutKickDisconnect(ichatbasecomponent), (future) -> { - this.networkManager.close(ichatbasecomponent); - }); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8bd55e3d2b5142081a7dfe1dbbd36f2f995e5856..e0bbb7f3ea7ce4902cd14e64357472087ce6912a 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -590,7 +590,7 @@ public abstract class PlayerList { - entityplayer.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - } - -- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); -+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName())), entityplayer.quitReason); // Paper - quit reason - if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - diff --git a/Unmapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch b/Unmapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch deleted file mode 100644 index 29bb86682d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0596-Seed-based-feature-search.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Mon, 13 Jan 2020 15:40:32 +0100 -Subject: [PATCH] Seed based feature search - -This tries to work around the issue where the server will load -surrounding chunks up to a radius of 100 chunks in order to search for -features e.g. when running the /locate command or for treasure maps -(issue #2312). -This is done by backporting Mojang's change in 1.17 which makes it so -that the biome (generated by the seed) is checked first if the feature -can be generated before actually to load the chunk. - -Additionally to that the center location of the target chunk is simply -returned if the chunk is not loaded to avoid the sync chunk load. -As this can lead to less precise locations a toggle is provided to -enable the sync loading of the target chunk again. - -The main downside of this is that it breaks once the seed or generator -changes but this should usually not happen. A config option to disable -this completely is added though in case that should ever be necessary. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 424754a0183b071d20c86f0420cec784a8992e2b..97870622e41cca36d9c7493bfad796f35f3831f4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -337,6 +337,14 @@ public class PaperWorldConfig { - } - } - -+ public boolean seedBasedFeatureSearch = true; -+ public boolean seedBasedFeatureSearchLoadsChunks = false; -+ private void seedBasedFeatureSearch() { -+ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch); -+ seedBasedFeatureSearchLoadsChunks = getBoolean("seed-based-feature-search-loads-chunks", seedBasedFeatureSearchLoadsChunks); -+ log("Feature search is based on seed: " + seedBasedFeatureSearch + ", loads chunks:" + seedBasedFeatureSearchLoadsChunks); -+ } -+ - public int maxCollisionsPerEntity; - private void maxEntityCollision() { - maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); -diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -index e41d63596c32eee5f0c04a6f043d576d8021ff1a..53eb5b65683a2ab208edfc3f3bbf78ffee61bc85 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -+++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -@@ -68,10 +68,12 @@ public class ChunkCoordIntPair { - } - } - -+ public int getBlockX() { return d(); } // Paper - OBFHELPER - public int d() { - return this.x << 4; - } - -+ public int getBlockZ() { return e(); } // Paper - OBFHELPER - public int e() { - return this.z << 4; - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index ae5f9a6af810b524f6dcbed64bc943122f0536cc..f40be366ebc5f98b417b677565fa89d3f817f3fb 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -1511,8 +1511,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return this.methodProfiler; - } - -- @Override -- public BiomeManager d() { -+ public BiomeManager getBiomeManager() { return d(); } // Paper - OBFHELPER -+ @Override public BiomeManager d() { - return this.biomeManager; - } - -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -index 340508e0ba8b8883a3037ecaa2d4e09e61e709d3..3b1d9b26ba3249b1df0c15a22428e4211ae0e024 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -@@ -23,6 +23,7 @@ public class BiomeManager { - return new BiomeManager(worldchunkmanager, this.b, this.c); - } - -+ public BiomeBase getBiome(BlockPosition blockposition) { return a(blockposition); } // Paper - OBFHELPER - public BiomeBase a(BlockPosition blockposition) { - return this.c.a(this.b, blockposition.getX(), blockposition.getY(), blockposition.getZ(), this.a); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -index ea7e3e15fa778c573d24f956f72f60579ea0b1a1..e5c22e92a305050df0eae2da53217ea2c3249e03 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -@@ -176,7 +176,24 @@ public abstract class StructureGenerator - int j2 = i1 + k * l1; - ChunkCoordIntPair chunkcoordintpair = this.a(structuresettingsfeature, j, seededrandom, i2, j2); - if (!iworldreader.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper -- IChunkAccess ichunkaccess = iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); -+ // Paper start - seed based feature search -+ IChunkAccess ichunkaccess = null; -+ if (structuremanager.getWorld().paperConfig.seedBasedFeatureSearch) { -+ BiomeBase biomeBase = structuremanager.getWorld().getBiomeManager().getBiome(new BlockPosition(chunkcoordintpair.getBlockX() + 9, 0, chunkcoordintpair.getBlockZ() + 9)); -+ if (!biomeBase.e().a(this)) { -+ continue; -+ } -+ if (!structuremanager.getWorld().paperConfig.seedBasedFeatureSearchLoadsChunks) { -+ ichunkaccess = structuremanager.getWorld().getChunkIfLoaded(chunkcoordintpair.x, chunkcoordintpair.z); -+ if (ichunkaccess == null) { -+ return chunkcoordintpair.asPosition().add(8, blockposition.getY(), 8); -+ } -+ } -+ } -+ if (ichunkaccess == null) { -+ ichunkaccess = iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); -+ } -+ // Paper end - StructureStart structurestart = structuremanager.a(SectionPosition.a(ichunkaccess.getPos(), 0), this, ichunkaccess); - - if (structurestart != null && structurestart.e()) { diff --git a/Unmapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch b/Unmapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch deleted file mode 100644 index 0b28af3165..0000000000 --- a/Unmapped-Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Thu, 20 Aug 2020 11:20:12 -0700 -Subject: [PATCH] Add Wandering Trader spawn rate config options - -Adds config options for modifying the spawn rates of Wandering Traders. -These values are all easy to understand and configure after a quick read of this -page on the Minecraft wiki: https://minecraft.gamepedia.com/Wandering_Trader#Spawning -Usages of the vanilla WanderingTraderSpawnDelay and WanderingTraderSpawnChance values -in IWorldServerData are removed as they were only used in certain places, with hardcoded -values used in other places. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 97870622e41cca36d9c7493bfad796f35f3831f4..5a451cc855de57f79a57670ba38e3af2343cb510 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -699,4 +699,17 @@ public class PaperWorldConfig { - log("The Ender Dragon will be removed if she already exists without a portal."); - } - } -+ -+ public int wanderingTraderSpawnMinuteTicks = 1200; -+ public int wanderingTraderSpawnDayTicks = 24000; -+ public int wanderingTraderSpawnChanceFailureIncrement = 25; -+ public int wanderingTraderSpawnChanceMin = 25; -+ public int wanderingTraderSpawnChanceMax = 75; -+ private void wanderingTraderSettings() { -+ wanderingTraderSpawnMinuteTicks = getInt("wandering-trader.spawn-minute-length", wanderingTraderSpawnMinuteTicks); -+ wanderingTraderSpawnDayTicks = getInt("wandering-trader.spawn-day-length", wanderingTraderSpawnDayTicks); -+ wanderingTraderSpawnChanceFailureIncrement = getInt("wandering-trader.spawn-chance-failure-increment", wanderingTraderSpawnChanceFailureIncrement); -+ wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); -+ wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -index b74a262a62642f63fdbd17579d58d5eae68ed169..e57938b4591bb103b9dd0d0145a62b5a901f2c63 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -@@ -30,49 +30,59 @@ public class MobSpawnerTrader implements MobSpawner { - - private final Random a = new Random(); - private final IWorldDataServer b; -- private int c; -- private int d; -- private int e; -+ private int c; public final int getMinuteTimer() { return this.c; } public final void setMinuteTimer(int x) { this.c = x; } // Paper - OBFHELPER -+ private int d; public final int getDayTimer() { return this.d; } public final void setDayTimer(int x) { this.d = x; } // Paper - OBFHELPER -+ private int e; public final int getSpawnChance() { return this.e; } public final void setSpawnChance(int x) { this.e = x; } // Paper - OBFHELPER - - public MobSpawnerTrader(IWorldDataServer iworlddataserver) { - this.b = iworlddataserver; -- this.c = 1200; -- this.d = iworlddataserver.v(); -- this.e = iworlddataserver.w(); -- if (this.d == 0 && this.e == 0) { -- this.d = 24000; -- iworlddataserver.g(this.d); -- this.e = 25; -- iworlddataserver.h(this.e); -- } -+ // Paper start -+ this.setMinuteTimer(Integer.MIN_VALUE); -+ //this.d = iworlddataserver.v(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value -+ //this.e = iworlddataserver.w(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value -+ //if (this.d == 0 && this.e == 0) { -+ // this.d = 24000; -+ // iworlddataserver.g(this.d); -+ // this.e = 25; -+ // iworlddataserver.h(this.e); -+ //} -+ // Paper end - - } - - @Override - public int a(WorldServer worldserver, boolean flag, boolean flag1) { -+ // Paper start -+ if (this.getMinuteTimer() == Integer.MIN_VALUE) { -+ this.setMinuteTimer(worldserver.paperConfig.wanderingTraderSpawnMinuteTicks); -+ this.setDayTimer(worldserver.paperConfig.wanderingTraderSpawnDayTicks); -+ this.setSpawnChance(worldserver.paperConfig.wanderingTraderSpawnChanceMin); -+ } - if (!worldserver.getGameRules().getBoolean(GameRules.DO_TRADER_SPAWNING)) { - return 0; -- } else if (--this.c > 0) { -+ } else if (this.getMinuteTimer() - 1 > 0) { -+ this.setMinuteTimer(this.getMinuteTimer() - 1); - return 0; - } else { -- this.c = 1200; -- this.d -= 1200; -- this.b.g(this.d); -- if (this.d > 0) { -+ this.setMinuteTimer(worldserver.paperConfig.wanderingTraderSpawnMinuteTicks); -+ this.setDayTimer(getDayTimer() - worldserver.paperConfig.wanderingTraderSpawnMinuteTicks); -+ //this.b.g(this.d); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways -+ if (this.getDayTimer() > 0) { - return 0; - } else { -- this.d = 24000; -+ this.setDayTimer(worldserver.paperConfig.wanderingTraderSpawnDayTicks); - if (!worldserver.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING)) { - return 0; - } else { -- int i = this.e; -+ int i = this.getSpawnChance(); - -- this.e = MathHelper.clamp(this.e + 25, 25, 75); -- this.b.h(this.e); -+ this.setSpawnChance(MathHelper.clamp(i + worldserver.paperConfig.wanderingTraderSpawnChanceFailureIncrement, worldserver.paperConfig.wanderingTraderSpawnChanceMin, worldserver.paperConfig.wanderingTraderSpawnChanceMax)); -+ //this.b.h(this.e); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways - if (this.a.nextInt(100) > i) { - return 0; - } else if (this.a(worldserver)) { -- this.e = 25; -+ this.setSpawnChance(worldserver.paperConfig.wanderingTraderSpawnChanceMin); -+ // Paper end - return 1; - } else { - return 0; diff --git a/Unmapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch b/Unmapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch deleted file mode 100644 index b205a133b3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com> -Date: Tue, 3 Nov 2020 23:48:05 -0600 -Subject: [PATCH] Significantly improve performance of the end generation - -This patch implements a noise cache for the end which significantly reduces the computation time of generation. This results in about a 3x improvement. - -Original code by SuperCoder7979 and Gegy in Lithium, licensed under LGPL-3.0 (Source: https://github.com/jellysquid3/lithium-fabric) - -Co-authored-by: Gegy -Co-authored-by: Dylan Xaldin -Co-authored-by: pop4959 - -diff --git a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -index 1077972d694d604c3ec97d333d34a9ab81819c33..62fe4cc00a24e330443d2f006a88dbab3798fb28 100644 ---- a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -+++ b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -@@ -3,10 +3,12 @@ package net.minecraft.world.level.biome; - import com.google.common.collect.ImmutableList; - import com.mojang.serialization.Codec; - import com.mojang.serialization.codecs.RecordCodecBuilder; -+import it.unimi.dsi.fastutil.HashCommon; // Paper - import java.util.List; - import net.minecraft.core.IRegistry; - import net.minecraft.resources.RegistryLookupCodec; - import net.minecraft.util.MathHelper; -+import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.levelgen.SeededRandom; - import net.minecraft.world.level.levelgen.synth.NoiseGenerator3Handler; - -@@ -27,6 +29,16 @@ public class WorldChunkManagerTheEnd extends WorldChunkManager { - private final BiomeBase k; - private final BiomeBase l; - private final BiomeBase m; -+ // Paper start -+ private static final class NoiseCache { -+ public long[] keys = new long[8192]; -+ public float[] values = new float[8192]; -+ public NoiseCache() { -+ java.util.Arrays.fill(keys, Long.MIN_VALUE); -+ } -+ } -+ private static final ThreadLocal> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new); -+ // Paper end - - public WorldChunkManagerTheEnd(IRegistry iregistry, long i) { - this(iregistry, i, (BiomeBase) iregistry.d(Biomes.THE_END), (BiomeBase) iregistry.d(Biomes.END_HIGHLANDS), (BiomeBase) iregistry.d(Biomes.END_MIDLANDS), (BiomeBase) iregistry.d(Biomes.SMALL_END_ISLANDS), (BiomeBase) iregistry.d(Biomes.END_BARRENS)); -@@ -81,13 +93,27 @@ public class WorldChunkManagerTheEnd extends WorldChunkManager { - - f = MathHelper.a(f, -100.0F, 80.0F); - -+ NoiseCache cache = noiseCache.get().computeIfAbsent(noisegenerator3handler, m -> new NoiseCache()); // Paper - for (int k1 = -12; k1 <= 12; ++k1) { - for (int l1 = -12; l1 <= 12; ++l1) { - long i2 = (long) (k + k1); - long j2 = (long) (l + l1); - -- if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.a((double) i2, (double) j2) < -0.8999999761581421D) { -- float f1 = (MathHelper.e((float) i2) * 3439.0F + MathHelper.e((float) j2) * 147.0F) % 13.0F + 9.0F; -+ // Paper start - Significantly improve end generation performance by using a noise cache -+ long key = ChunkCoordIntPair.pair((int) i2, (int) j2); -+ int index = (int) HashCommon.mix(key) & 8191; -+ float f1 = Float.MIN_VALUE; -+ if (cache.keys[index] == key) { -+ f1 = cache.values[index]; -+ } else { -+ if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.a((double) i2, (double) j2) < -0.8999999761581421D) { -+ f1 = (MathHelper.e((float) i2) * 3439.0F + MathHelper.e((float) j2) * 147.0F) % 13.0F + 9.0F; -+ } -+ cache.keys[index] = key; -+ cache.values[index] = f1; -+ } -+ if (f1 != Float.MIN_VALUE) { -+ // Paper end - float f2 = (float) (i1 - k1 * 2); - float f3 = (float) (j1 - l1 * 2); - float f4 = 100.0F - MathHelper.c(f2 * f2 + f3 * f3) * f1; diff --git a/Unmapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch b/Unmapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch deleted file mode 100644 index 881cbed405..0000000000 --- a/Unmapped-Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Tue, 17 Nov 2020 19:13:09 +0200 -Subject: [PATCH] Expose world spawn angle - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index e0bbb7f3ea7ce4902cd14e64357472087ce6912a..66fbbc4c91e16a3dfb4bb756972e667121693501 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -894,7 +894,7 @@ public abstract class PlayerList { - if (location == null) { - worldserver1 = this.server.getWorldServer(World.OVERWORLD); - blockposition = entityplayer1.getSpawnPoint(worldserver1); -- location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F)); -+ location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F), worldserver1.worldData.getSpawnAngle(), 0.0F); // Paper - use world spawn angle - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldData.java b/src/main/java/net/minecraft/world/level/storage/WorldData.java -index 81ad90ba93481decdfaa38fc9fa81bca0e402781..7599488f7d4b168c92078c2d2987cb38f0dee8a9 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldData.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldData.java -@@ -12,6 +12,7 @@ public interface WorldData { - - int c(); - -+ default float getSpawnAngle() { return d(); } // Paper - OBFHELPER - float d(); - - long getTime(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 76a7889b49a16ddeb8f310d3a79cfee80ad9a1db..776733a4a913d232126b48f2d0eadbe27aa84e59 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -380,7 +380,7 @@ public class CraftWorld implements World { - @Override - public Location getSpawnLocation() { - BlockPosition spawn = world.getSpawn(); -- return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); -+ return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ(), world.worldData.getSpawnAngle(), 0.0F); // Paper - expose world spawn angle - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch b/Unmapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch deleted file mode 100644 index bdeb073a85..0000000000 --- a/Unmapped-Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ineusia -Date: Mon, 26 Oct 2020 11:48:06 -0500 -Subject: [PATCH] Add Destroy Speed API - -Co-authored-by: Jake Potrebic - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index f1f03bd0162a158761f300cbd96aa32101542abb..fab9e1e5d63c22faceae093dc88769d203d359c6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -769,5 +769,23 @@ public class CraftBlock implements Block { - public String getTranslationKey() { - return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); - } -+ -+ @Override -+ public float getDestroySpeed(ItemStack itemStack, boolean considerEnchants) { -+ net.minecraft.world.item.ItemStack nmsItemStack; -+ if (itemStack instanceof CraftItemStack) { -+ nmsItemStack = ((CraftItemStack) itemStack).getHandle(); -+ } else { -+ nmsItemStack = CraftItemStack.asNMSCopy(itemStack); -+ } -+ float speed = nmsItemStack.getItem().getDestroySpeed(nmsItemStack, this.getNMSBlock().getBlockData()); -+ if (speed > 1.0F && considerEnchants) { -+ int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentManager.getEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.DIG_SPEED, nmsItemStack); -+ if (enchantLevel > 0) { -+ speed += enchantLevel * enchantLevel + 1; -+ } -+ } -+ return speed; -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/Unmapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch deleted file mode 100644 index 54e629a54c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Esophose -Date: Sat, 3 Oct 2020 18:57:47 -0600 -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 8337ed8bb20b8d887bcd71ddc5f29bce346c7cff..41987716afa8ec34214868373df97d0e8f8b27c1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2012,7 +2012,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (data != null && !particle.getDataType().isInstance(data)) { - throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); - } -- PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(CraftParticle.toNMS(particle, data), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); -+ PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(CraftParticle.toNMS(particle, data), true, x, y, z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); // Paper - Fix x/y/z coordinate precision loss - getHandle().playerConnection.sendPacket(packetplayoutworldparticles); - - } diff --git a/Unmapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch b/Unmapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch deleted file mode 100644 index c2455803ab..0000000000 --- a/Unmapped-Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Anrza -Date: Wed, 15 Jul 2020 12:08:49 +0200 -Subject: [PATCH] Add LivingEntity#clearActiveItem - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index de12a050739b8d12d268cc9ca496259ea2c46569..3bee6903a591bbfe312c6d7e276d7cef3dafc852 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -785,6 +785,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().activeItem.asBukkitMirror(); - } - -+ // Paper start -+ @Override -+ public void clearActiveItem() { -+ getHandle().clearActiveItem(); -+ } -+ // Paper end -+ - @Override - public int getItemUseRemainingTime() { - return getHandle().getItemUseRemainingTime(); diff --git a/Unmapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch b/Unmapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch deleted file mode 100644 index 81581680ce..0000000000 --- a/Unmapped-Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Tue, 25 Aug 2020 13:48:33 +0200 -Subject: [PATCH] Add PlayerItemCooldownEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java b/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java -index 5f70e39f4da2880a6f734a225be83061b00847c8..ef9ffad211473f1cbcd0b8fd200ff04ec2051f94 100644 ---- a/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java -+++ b/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java -@@ -3,14 +3,26 @@ package net.minecraft.world.item; - import net.minecraft.network.protocol.game.PacketPlayOutSetCooldown; - import net.minecraft.server.level.EntityPlayer; - -+import io.papermc.paper.event.player.PlayerItemCooldownEvent; // Paper -+ - public class ItemCooldownPlayer extends ItemCooldown { - -- private final EntityPlayer a; -+ private final EntityPlayer a; public EntityPlayer getEntityPlayer() { return a; } // Paper - OBFHELPER - - public ItemCooldownPlayer(EntityPlayer entityplayer) { - this.a = entityplayer; - } - -+ // Paper start -+ @Override -+ public void setCooldown(Item item, int ticks) { -+ PlayerItemCooldownEvent event = new PlayerItemCooldownEvent(getEntityPlayer().getBukkitEntity(), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(item), ticks); -+ if (event.callEvent()) { -+ super.setCooldown(item, event.getCooldown()); -+ } -+ } -+ // Paper end -+ - @Override - protected void b(Item item, int i) { - super.b(item, i); diff --git a/Unmapped-Spigot-Server-Patches/0604-More-lightning-API.patch b/Unmapped-Spigot-Server-Patches/0604-More-lightning-API.patch deleted file mode 100644 index e08b3251e5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0604-More-lightning-API.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Sun, 26 Jul 2020 14:44:09 +0200 -Subject: [PATCH] More lightning API - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLightning.java b/src/main/java/net/minecraft/world/entity/EntityLightning.java -index 834ced9d9b385c8f1d66355244313d62a97d9c98..85f571a791bce63989890f277857bc7bdeec0cb5 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLightning.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLightning.java -@@ -31,7 +31,7 @@ public class EntityLightning extends Entity { - - private int lifeTicks; - public long b; -- private int d; -+ private int d; public int getFlashCount() { return d; } public void setFlashCount(int flashes) { this.d = flashes; } // Paper - OBFHELPER - public boolean isEffect; - @Nullable - private EntityPlayer f; -@@ -49,6 +49,16 @@ public class EntityLightning extends Entity { - this.isEffect = flag; - } - -+ // Paper start -+ public int getLifeTicks() { -+ return lifeTicks; -+ } -+ -+ public void setLifeTicks(int lifeTicks) { -+ this.lifeTicks = lifeTicks; -+ } -+ // Paper end -+ - @Override - public SoundCategory getSoundCategory() { - return SoundCategory.WEATHER; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -index 3e054592cef6526b769d14460a671ea78a5ef58a..395f702b14425d85ff3a7938c32f7bfd5523f3ca 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -@@ -45,4 +45,27 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike - return spigot; - } - // Spigot end -+ -+ // Paper start -+ @Override -+ public int getFlashCount() { -+ return getHandle().getFlashCount(); -+ } -+ -+ @Override -+ public void setFlashCount(int flashes) { -+ com.google.common.base.Preconditions.checkArgument(flashes >= 0, "Flashes has to be a positive number!"); -+ getHandle().setFlashCount(flashes); -+ } -+ -+ @Override -+ public int getLifeTicks() { -+ return getHandle().getLifeTicks(); -+ } -+ -+ @Override -+ public void setLifeTicks(int lifeTicks) { -+ getHandle().setLifeTicks(lifeTicks); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch b/Unmapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch deleted file mode 100644 index f9842f65c3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch +++ /dev/null @@ -1,179 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 23 Aug 2020 20:59:00 +0200 -Subject: [PATCH] Climbing should not bypass cramming gamerule - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5a451cc855de57f79a57670ba38e3af2343cb510..7d3207a9af8360ddad228281d6aa65e1a0d24157 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -712,4 +712,9 @@ public class PaperWorldConfig { - wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); - wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); - } -+ -+ public boolean fixClimbingBypassingCrammingRule = false; -+ private void fixClimbingBypassingCrammingRule() { -+ fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0841cf7e968a8a3b577e91f6dcd0487169474329..dc0e2a1348062ea79b1ec3a9fdb985d9d3fca790 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1575,6 +1575,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean isCollidable() { -+ // Paper start -+ return isCollidable(false); -+ } -+ -+ public boolean isCollidable(boolean ignoreClimbing) { -+ // Paper end - return false; - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 60dfa764898b59b60aec2da9580a80634e624dbe..b56c801c02e4f206b72db7dd74672727104bf246 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -137,7 +137,6 @@ import org.bukkit.event.entity.EntityTeleportEvent; - import org.bukkit.event.player.PlayerItemConsumeEvent; - // CraftBukkit end - --import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class EntityLiving extends Entity { - -@@ -2959,7 +2958,7 @@ public abstract class EntityLiving extends Entity { - return; - } - // Paper - end don't run getEntities if we're not going to use its result -- List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.a(this)); -+ List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.pushable(this, world.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule - - if (!list.isEmpty()) { - // Paper - move up -@@ -3097,9 +3096,16 @@ public abstract class EntityLiving extends Entity { - return !this.dead && this.collides; // CraftBukkit - } - -+ // Paper start - @Override - public boolean isCollidable() { -- return this.isAlive() && !this.isSpectator() && !this.isClimbing() && this.collides; // CraftBukkit -+ return this.isCollidable(world.paperConfig.fixClimbingBypassingCrammingRule); -+ } -+ -+ @Override -+ public boolean isCollidable(boolean ignoreClimbing) { -+ return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.isClimbing()) && this.collides; // CraftBukkit -+ // Paper end - } - - // CraftBukkit start - collidable API -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index c8d7ea8cfa4945af4a6675172b931a4cc3ca2801..f5e32faeb6d937cf90b1f3ea251b5cfc91f2338d 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -51,11 +51,17 @@ public final class IEntitySelector { - } - - public static Predicate a(Entity entity) { -+ // Paper start - ignoreClimbing param -+ return pushable(entity, false); -+ } -+ -+ public static Predicate pushable(Entity entity, boolean ignoreClimbing) { -+ // Paper end - ScoreboardTeamBase scoreboardteambase = entity.getScoreboardTeam(); - ScoreboardTeamBase.EnumTeamPush scoreboardteambase_enumteampush = scoreboardteambase == null ? ScoreboardTeamBase.EnumTeamPush.ALWAYS : scoreboardteambase.getCollisionRule(); - - return (Predicate) (scoreboardteambase_enumteampush == ScoreboardTeamBase.EnumTeamPush.NEVER ? Predicates.alwaysFalse() : IEntitySelector.g.and((entity1) -> { -- if (!entity1.canCollideWith(entity) || !entity.canCollideWith(entity1)) { // CraftBukkit - collidable API -+ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWith(entity) || !entity.canCollideWith(entity1)) { // CraftBukkit - collidable API // Paper - isCollidable - return false; - } else if (entity.world.isClientSide && (!(entity1 instanceof EntityHuman) || !((EntityHuman) entity1).ez())) { - return false; -diff --git a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -index 2167590677c68d261b804a16853bd943f16a76dd..61ebb278cf4ef57ae7a86c6c6ef1fa14559f21e2 100644 ---- a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -+++ b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -@@ -76,7 +76,7 @@ public class EntityBat extends EntityAmbient { - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return false; - } - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -index e93375171462b95e270230f5f72f7eb5c6b0ff58..699dd0ac1f8d0d340ab1a560106336fc7cc95d5b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -@@ -368,8 +368,8 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - } - - @Override -- public boolean isCollidable() { -- return super.isCollidable(); // CraftBukkit - collidable API -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper -+ return super.isCollidable(ignoreClimbing); // CraftBukkit - collidable API // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -index d05391290dc11440aae5f38328a0530c500ac601..d678e3164ecdb7f0c600597bcb39d1054dfbc4b2 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -@@ -227,7 +227,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return !this.isVehicle(); - } - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 5eb900619951083b9a777b1645cb5495b99968ec..c0e0750adef0ae6aff7635c84f6585f06c5fc38d 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -362,7 +362,7 @@ public class EntityArmorStand extends EntityLiving { - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return false; - } - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index 25a6f53888293994a50128bcbcbb88ff141c5395..add2aef0192a3b3767c1e477145978b9702c0fb4 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -150,7 +150,7 @@ public class EntityBoat extends Entity { - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return true; - } - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 7d91e6b75a8a827853b0ca8e53b8ec19e2cf1092..2e3ceab3e34f7756764b3471b13d48d1263ecba9 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -145,7 +145,7 @@ public abstract class EntityMinecartAbstract extends Entity { - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return true; - } - diff --git a/Unmapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch b/Unmapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch deleted file mode 100644 index 25843d00d1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 16 Nov 2020 12:01:52 -0800 -Subject: [PATCH] Added missing default perms for commands - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -index d5f4ece060b61de9ca5292d1f2411c709de5ece2..f0a57d225b81a505ff12425155ba838d8fad990c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -@@ -31,6 +31,59 @@ public final class CommandPermissions { - DefaultPermissions.registerPermission(PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands); -+ // Paper start -+ DefaultPermissions.registerPermission(PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "ban", "Allows the user to add players to banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "ban-ip", "Allows the user to add ip address to banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "banlist", "Allows the user to display banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "pardon", "Allows the user to remove entries from the banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "replaceitem", "Allows the user to replace items in inventories", PermissionDefault.OP, commands); // Remove in 1.17 (replaced by /item) -+ DefaultPermissions.registerPermission(PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands); -+ DefaultPermissions.registerPermission(PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands); -+ // Paper end - - DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands); - diff --git a/Unmapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch b/Unmapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch deleted file mode 100644 index 3404ded8f3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Thu, 27 Aug 2020 15:02:48 -0400 -Subject: [PATCH] Add PlayerShearBlockEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index d4903842aebeff3e32dbf7d3f4b670af4ebad174..7279893d599351785652279c8827fe0efbd72f12 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -262,7 +262,7 @@ public class Block extends BlockBase implements IMaterial { - - } - -- public static void a(World world, BlockPosition blockposition, ItemStack itemstack) { -+ public static void a(World world, BlockPosition blockposition, ItemStack itemstack) { dropItem(world, blockposition, itemstack); } public static void dropItem(World world, BlockPosition blockposition, ItemStack itemstack) { // Paper - OBFHELPER - if (!world.isClientSide && !itemstack.isEmpty() && world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) { - float f = 0.5F; - double d0 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBeehive.java b/src/main/java/net/minecraft/world/level/block/BlockBeehive.java -index ff521e64384281fc88b78bb908d19049743cf63b..828d231a963f1962d88fe170ac86590d86e1df40 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBeehive.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBeehive.java -@@ -1,5 +1,7 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts -+ - import java.util.Iterator; - import java.util.List; - import java.util.Random; -@@ -10,6 +12,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; -@@ -116,8 +119,19 @@ public class BlockBeehive extends BlockTileEntity { - - if (i >= 5) { - if (itemstack.getItem() == Items.SHEARS) { -+ // Paper start - Add PlayerShearBlockEvent -+ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), MCUtil.toBukkitBlock(world, blockposition), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (enumhand == EnumHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); -+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3))); -+ if (!event.callEvent()) { -+ return EnumInteractionResult.PASS; -+ } -+ // Paper end - world.playSound(entityhuman, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.BLOCK_BEEHIVE_SHEAR, SoundCategory.NEUTRAL, 1.0F, 1.0F); -- a(world, blockposition); -+ // Paper start - Add PlayerShearBlockEvent -+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { -+ dropItem(world, blockposition, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); -+ } -+ // Paper end - itemstack.damage(1, entityhuman, (entityhuman1) -> { - entityhuman1.broadcastItemBreak(enumhand); - }); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java b/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java -index 130b768ac7155c2960694dfa12163e46315f7797..11a9c3e76baaa50317a3cd7d81541a3666028c16 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; - - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.EnumHand; -@@ -15,6 +16,8 @@ import net.minecraft.world.level.block.state.BlockBase; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.phys.MovingObjectPositionBlock; - -+import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts -+ - public class BlockPumpkin extends BlockStemmed { - - protected BlockPumpkin(BlockBase.Info blockbase_info) { -@@ -27,15 +30,26 @@ public class BlockPumpkin extends BlockStemmed { - - if (itemstack.getItem() == Items.SHEARS) { - if (!world.isClientSide) { -+ // Paper start - Add PlayerShearBlockEvent -+ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), MCUtil.toBukkitBlock(world, blockposition), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (enumhand == EnumHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); -+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4))); -+ if (!event.callEvent()) { -+ return EnumInteractionResult.PASS; -+ } -+ // Paper end - EnumDirection enumdirection = movingobjectpositionblock.getDirection(); - EnumDirection enumdirection1 = enumdirection.n() == EnumDirection.EnumAxis.Y ? entityhuman.getDirection().opposite() : enumdirection; - - world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_PUMPKIN_CARVE, SoundCategory.BLOCKS, 1.0F, 1.0F); - world.setTypeAndData(blockposition, (IBlockData) Blocks.CARVED_PUMPKIN.getBlockData().set(BlockPumpkinCarved.a, enumdirection1), 11); -- EntityItem entityitem = new EntityItem(world, (double) blockposition.getX() + 0.5D + (double) enumdirection1.getAdjacentX() * 0.65D, (double) blockposition.getY() + 0.1D, (double) blockposition.getZ() + 0.5D + (double) enumdirection1.getAdjacentZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4)); -+ // Paper start - Add PlayerShearBlockEvent -+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { -+ EntityItem entityitem = new EntityItem(world, (double) blockposition.getX() + 0.5D + (double) enumdirection1.getAdjacentX() * 0.65D, (double) blockposition.getY() + 0.1D, (double) blockposition.getZ() + 0.5D + (double) enumdirection1.getAdjacentZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); -+ // Paper end - - entityitem.setMot(0.05D * (double) enumdirection1.getAdjacentX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double) enumdirection1.getAdjacentZ() + world.random.nextDouble() * 0.02D); - world.addEntity(entityitem); -+ } // Paper - Add PlayerShearBlockEvent - itemstack.damage(1, entityhuman, (entityhuman1) -> { - entityhuman1.broadcastItemBreak(enumhand); - }); diff --git a/Unmapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch b/Unmapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch deleted file mode 100644 index 426ebae0e9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Wed, 2 Dec 2020 21:58:45 -0800 -Subject: [PATCH] Add warning for servers not running on Java 16 - - -diff --git a/src/main/java/io/papermc/paper/util/PaperJvmChecker.java b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fdf3ff8894e5e202229d1be52fe3c92ea039ef15 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java -@@ -0,0 +1,48 @@ -+package io.papermc.paper.util; -+ -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; -+ -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+public class PaperJvmChecker { -+ -+ private static int getJvmVersion() { -+ String javaVersion = System.getProperty("java.version"); -+ final Matcher matcher = Pattern.compile("(?:1\\.)?(\\d+)").matcher(javaVersion); -+ if (!matcher.find()) { -+ LogManager.getLogger().warn("Failed to determine Java version; Could not parse: {}", javaVersion); -+ return -1; -+ } -+ -+ final String version = matcher.group(1); -+ try { -+ return Integer.parseInt(version); -+ } catch (final NumberFormatException e) { -+ LogManager.getLogger().warn("Failed to determine Java version; Could not parse {} from {}", version, javaVersion, e); -+ return -1; -+ } -+ } -+ -+ public static void checkJvm() { -+ if (getJvmVersion() < 16) { -+ final Logger logger = LogManager.getLogger(); -+ logger.warn("************************************************************"); -+ logger.warn("* WARNING - YOU ARE RUNNING AN OUTDATED VERSION OF JAVA."); -+ logger.warn("* PAPER WILL STOP BEING COMPATIBLE WITH THIS VERSION OF"); -+ logger.warn("* JAVA WHEN MINECRAFT 1.17 IS RELEASED."); -+ logger.warn("*"); -+ logger.warn("* Please update the version of Java you use to run Paper"); -+ logger.warn("* to at least Java 16. When Paper for Minecraft 1.17 is"); -+ logger.warn("* released support for versions of Java before 16 will"); -+ logger.warn("* be dropped."); -+ logger.warn("*"); -+ logger.warn("* Current Java version: {}", System.getProperty("java.version")); -+ logger.warn("*"); -+ logger.warn("* Check this forum post for more information: "); -+ logger.warn("* https://papermc.io/java16"); -+ logger.warn("************************************************************"); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index bea7887c1adee93cfef17d910c3df3eb60cb681c..e43fcdc806ff4e2db22d031006c96e68fc81f5fd 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -182,6 +182,7 @@ import org.bukkit.event.server.ServerLoadEvent; - - import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot -+import io.papermc.paper.util.PaperJvmChecker; // Paper - - public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { - -@@ -1077,6 +1078,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Wed, 2 Dec 2020 20:17:54 -0800 -Subject: [PATCH] Set spigots verbose world setting to false by def - - -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 6b015c1f26facb4e82d75b252164dec05731ca6c..094a934c168d232b0550c3efe722f2ebfbdf8e24 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -20,7 +20,7 @@ public class SpigotWorldConfig - - public void init() - { -- this.verbose = getBoolean( "verbose", true ); -+ this.verbose = getBoolean( "verbose", false ); // Paper - - log( "-------- World Settings For [" + worldName + "] --------" ); - SpigotConfig.readConfig( SpigotWorldConfig.class, this ); diff --git a/Unmapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch b/Unmapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch deleted file mode 100644 index 889f7bbbd2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 8 Dec 2020 20:14:20 -0600 -Subject: [PATCH] Fix curing zombie villager discount exploit - -This fixes the exploit used to gain absurd trading discounts with infecting -and curing a villager on repeat by simply resetting the relevant part of -the reputation when it is cured. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7d3207a9af8360ddad228281d6aa65e1a0d24157..a3b3e3e04b7a5e3a351992e06870cc91fbd8adc8 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -717,4 +717,9 @@ public class PaperWorldConfig { - private void fixClimbingBypassingCrammingRule() { - fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); - } -+ -+ public boolean fixCuringZombieVillagerDiscountExploit = true; -+ private void fixCuringExploit() { -+ fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -index 7d34d1157786227ac210edc1595a024ccb61a3e9..ce8a4cc9f642a740947c4e63d6eb78ad93a0fd44 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -@@ -223,6 +223,7 @@ public class Reputation { - - } - -+ public final void removeReputationForType(ReputationType reputationType) { this.b(reputationType); } // Paper - OBFHELPER - public void b(ReputationType reputationtype) { - this.a.removeInt(reputationtype); - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index d1ddb12e8bd83d2218165340fe323c6be7bc83dd..c29f05b6fd0664345d8d09f898777a3e44f866c4 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -1014,6 +1014,15 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - @Override - public void a(ReputationEvent reputationevent, Entity entity) { - if (reputationevent == ReputationEvent.a) { -+ // Paper start - fix MC-181190 -+ if (world.paperConfig.fixCuringZombieVillagerDiscountExploit) { -+ final Reputation.a playerReputation = this.getReputation().getReputations().get(entity.getUniqueID()); -+ if (playerReputation != null) { -+ playerReputation.removeReputationForType(ReputationType.MAJOR_POSITIVE); -+ playerReputation.removeReputationForType(ReputationType.MINOR_POSITIVE); -+ } -+ } -+ // Paper end - this.by.a(entity.getUniqueID(), ReputationType.MAJOR_POSITIVE, 20); - this.by.a(entity.getUniqueID(), ReputationType.MINOR_POSITIVE, 25); - } else if (reputationevent == ReputationEvent.e) { diff --git a/Unmapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch b/Unmapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch deleted file mode 100644 index 68ff3fe062..0000000000 --- a/Unmapped-Spigot-Server-Patches/0611-Limit-recipe-packets.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 12 Dec 2020 23:45:28 +0000 -Subject: [PATCH] Limit recipe packets - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 7d50aded88f5b7dfebaea1aebc86231f7b5c4e25..652d87fc5d566dba8018c81676329f0e0bca471b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -334,6 +334,13 @@ public class PaperConfig { - tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); - } - -+ public static int autoRecipeIncrement = 1; -+ public static int autoRecipeLimit = 20; -+ private static void autoRecipieLimiters() { -+ autoRecipeIncrement = getInt("settings.spam-limiter.recipe-spam-increment", autoRecipeIncrement); -+ autoRecipeLimit = getInt("settings.spam-limiter.recipe-spam-limit", autoRecipeLimit); -+ } -+ - public static boolean velocitySupport; - public static boolean velocityOnlineMode; - public static byte[] velocitySecretKey; -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index cf81710e41420f6cd027231998ebf5305f23f3d5..ef38900107cc62222b303517ea4a65bff06c66b1 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.network; - -+import com.destroystokyo.paper.PaperConfig; - import com.google.common.collect.Lists; - import com.google.common.primitives.Doubles; - import com.google.common.primitives.Floats; -@@ -176,6 +177,7 @@ import net.minecraft.world.inventory.InventoryClickType; - import net.minecraft.world.item.crafting.IRecipe; - import net.minecraft.world.level.RayTrace; - import net.minecraft.world.phys.MovingObjectPosition; -+import org.bukkit.Bukkit; // Paper - import org.bukkit.Location; - import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.craftbukkit.event.CraftEventFactory; -@@ -234,6 +236,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - private volatile int chatThrottle; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); - private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits -+ private final java.util.concurrent.atomic.AtomicInteger recipeSpamPackets = new java.util.concurrent.atomic.AtomicInteger(); // Paper - auto recipe limit - // CraftBukkit end - private int j; - private final Int2ShortMap k = new Int2ShortOpenHashMap(); -@@ -382,6 +385,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit start - for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; - if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable -+ if (recipeSpamPackets.get() > 0) recipeSpamPackets.getAndDecrement(); // Paper - /* Use thread-safe field access instead - if (this.chatThrottle > 0) { - --this.chatThrottle; -@@ -2788,6 +2792,14 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInAutoRecipe packetplayinautorecipe) { -+ // Paper start -+ if (!Bukkit.isPrimaryThread()) { -+ if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper -+ return; -+ } -+ } -+ // Paper end - PlayerConnectionUtils.ensureMainThread(packetplayinautorecipe, this, this.player.getWorldServer()); - this.player.resetIdleTimer(); - if (!this.player.isSpectator() && this.player.activeContainer.windowId == packetplayinautorecipe.b() && this.player.activeContainer.c(this.player) && this.player.activeContainer instanceof ContainerRecipeBook) { diff --git a/Unmapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch b/Unmapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch deleted file mode 100644 index 8a131ca40a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Thu, 17 Dec 2020 15:25:49 -0600 -Subject: [PATCH] Fix CraftSound backwards compatibility - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java -index e839d50c7b1cc3c9a6e463c497489ad580aceabd..84fb7d96bea3b47f2f6c6dc8d0086fee13d07ada 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java -@@ -27,4 +27,10 @@ public class CraftSound { - public static Sound getBukkit(SoundEffect soundEffect) { - return Registry.SOUNDS.get(CraftNamespacedKey.fromMinecraft(IRegistry.SOUND_EVENT.getKey(soundEffect))); - } -+ -+ // Paper start -+ public static String getSound(Sound sound) { -+ return sound.getKey().getKey(); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch b/Unmapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch deleted file mode 100644 index abc309a820..0000000000 --- a/Unmapped-Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 8 Dec 2020 20:24:52 -0600 -Subject: [PATCH] MC-4: Fix item position desync - -This fixes item position desync (MC-4) by running the item coordinates -through the encode/decode methods of the packet that causes the precision -loss, which forces the server to lose the same precision as the client -keeping them in sync. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 652d87fc5d566dba8018c81676329f0e0bca471b..c56e7fb18f9a56c8025eb70a524f028b5942da37 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -474,4 +474,9 @@ public class PaperConfig { - private static void trackPluginScoreboards() { - trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); - } -+ -+ public static boolean fixEntityPositionDesync = true; -+ private static void fixEntityPositionDesync() { -+ fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); -+ } - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java -index e80429368afced0299d9f41b97251cd6c64b1759..0eed10a6c4e0c7245f219d19ed1e2e5c94364db9 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java -@@ -19,11 +19,11 @@ public class PacketPlayOutEntity implements Packet { - protected boolean i; - - public static long a(double d0) { -- return MathHelper.d(d0 * 4096.0D); -+ return MathHelper.d(d0 * 4096.0D); // Paper - check EntityItem#setPositionRaw on update - } - - public static Vec3D a(long i, long j, long k) { -- return (new Vec3D((double) i, (double) j, (double) k)).a(2.44140625E-4D); -+ return (new Vec3D((double) i, (double) j, (double) k)).a(2.44140625E-4D); // Paper - check EntityItem#setPositionRaw on update - } - - public PacketPlayOutEntity() {} -diff --git a/src/main/java/net/minecraft/util/MathHelper.java b/src/main/java/net/minecraft/util/MathHelper.java -index caa628417bb9c1c65b037e4f3f762b08272c6d09..cc566784c7dd21cc2c44e0f351347f657e57ddcf 100644 ---- a/src/main/java/net/minecraft/util/MathHelper.java -+++ b/src/main/java/net/minecraft/util/MathHelper.java -@@ -9,7 +9,7 @@ import net.minecraft.core.BaseBlockPosition; - public class MathHelper { - - public static final float a = c(2.0F); -- private static final float[] b = (float[]) SystemUtils.a((Object) (new float[65536]), (afloat) -> { -+ private static final float[] b = (float[]) SystemUtils.a((new float[65536]), (afloat) -> { // Paper - decompile error - for (int i = 0; i < afloat.length; ++i) { - afloat[i] = (float) Math.sin((double) i * 3.141592653589793D * 2.0D / 65536.0D); - } -@@ -49,6 +49,7 @@ public class MathHelper { - return d0 < (double) i ? i - 1 : i; - } - -+ public static long floorLong(double d0) { return d(d0); } // Paper - OBFHELPER - public static long d(double d0) { - long i = (long) d0; - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 11e029f6f97f1dd9c32e311d1a3800f2fa54b91f..575833807ff647f30d7c2b7abcd01701c7dec85b 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -550,4 +550,16 @@ public class EntityItem extends Entity { - public Packet P() { - return new PacketPlayOutSpawnEntity(this); - } -+ -+ // Paper start - fix MC-4 -+ public void setPositionRaw(double x, double y, double z) { -+ if (com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) { -+ // encode/decode from PacketPlayOutEntity -+ x = MathHelper.floorLong(x * 4096.0D) * (1 / 4096.0D); -+ y = MathHelper.floorLong(y * 4096.0D) * (1 / 4096.0D); -+ z = MathHelper.floorLong(z * 4096.0D) * (1 / 4096.0D); -+ } -+ super.setPositionRaw(x, y, z); -+ } -+ // Paper end - fix MC-4 - } diff --git a/Unmapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch b/Unmapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch deleted file mode 100644 index a1a05e716f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 5 Oct 2020 21:25:16 +0200 -Subject: [PATCH] Player Chunk Load/Unload Events - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 78fcb90c86700ee6feef0d40753fc8d8a943777f..c0446ed3c7cc24fae2880dfba71228f5edee66d6 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -139,6 +139,8 @@ import net.minecraft.world.scores.ScoreboardScore; - import net.minecraft.world.scores.ScoreboardTeam; - import net.minecraft.world.scores.ScoreboardTeamBase; - import net.minecraft.world.scores.criteria.IScoreboardCriteria; -+import io.papermc.paper.event.packet.PlayerChunkLoadEvent; // Paper -+import io.papermc.paper.event.packet.PlayerChunkUnloadEvent; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -2098,11 +2100,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public void a(ChunkCoordIntPair chunkcoordintpair, Packet packet, Packet packet1) { - this.playerConnection.sendPacket(packet1); - this.playerConnection.sendPacket(packet); -+ // Paper start -+ if(PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0){ -+ new PlayerChunkLoadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); -+ } -+ // Paper end - } - - public void a(ChunkCoordIntPair chunkcoordintpair) { - if (this.isAlive()) { - this.playerConnection.sendPacket(new PacketPlayOutUnloadChunk(chunkcoordintpair.x, chunkcoordintpair.z)); -+ // Paper start -+ if(PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0){ -+ new PlayerChunkUnloadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); -+ } -+ // Paper end - } - - } diff --git a/Unmapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch b/Unmapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch deleted file mode 100644 index 5a4efe035c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 21 Dec 2020 11:01:42 -0500 -Subject: [PATCH] Optimize Dynamic#get Missing Keys - -get was calling toString() on every NBT object that was ever asked for an optional -key from the object to build a string for the error text. - -When done on large NBT objects, this was using a ton of computation time building the -JSON representation of the NBT object. - -Now we will just skip the value when 99.9999% of the time the text is never even printed. - -diff --git a/src/main/java/com/mojang/serialization/Dynamic.java b/src/main/java/com/mojang/serialization/Dynamic.java -index a75d3db046dc985a03b4b870c91f41de1bd66bad..044facc9de9e8e582d7953d681c0c051578979c3 100644 ---- a/src/main/java/com/mojang/serialization/Dynamic.java -+++ b/src/main/java/com/mojang/serialization/Dynamic.java -@@ -17,6 +17,7 @@ import java.util.stream.Stream; - - @SuppressWarnings("unused") - public class Dynamic extends DynamicLike { -+ private static final boolean DEBUG_MISSING_KEYS = Boolean.getBoolean("Paper.debugDynamicMissingKeys"); // Paper - private final T value; - - public Dynamic(final DynamicOps ops) { -@@ -113,7 +114,7 @@ public class Dynamic extends DynamicLike { - return new OptionalDynamic<>(ops, ops.getMap(value).flatMap(m -> { - final T value = m.get(key); - if (value == null) { -- return DataResult.error("key missing: " + key + " in " + this.value); -+ return DataResult.error(DEBUG_MISSING_KEYS ? "key missing: " + key + " in " + this.value : "key missing: " + key); // Paper - } - return DataResult.success(new Dynamic<>(ops, value)); - })); diff --git a/Unmapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch b/Unmapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch deleted file mode 100644 index 85a61eeb6e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 13 Dec 2020 05:32:05 +0200 -Subject: [PATCH] Expose LivingEntity hurt direction - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index b56c801c02e4f206b72db7dd74672727104bf246..b1adb0ddfeb94de6f92f40a7e9e586e00455160d 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -163,7 +163,7 @@ public abstract class EntityLiving extends Entity { - public int am; - public int hurtTicks; - public int hurtDuration; -- public float ap; -+ public float ap; public final float getHurtDirection() { return ap; } public final void setHurtDirection(float hurtDirection) { this.ap = hurtDirection; } // Paper - OBFHELPER - public int deathTicks; - public float ar; - public float as; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 3bee6903a591bbfe312c6d7e276d7cef3dafc852..278a1c886f15b75e62bfe4c872fc779eda83c988 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -830,5 +830,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { - getHandle().receive(((CraftItem) item).getHandle(), quantity); - } -+ -+ @Override -+ public float getHurtDirection() { -+ return getHandle().getHurtDirection(); -+ } -+ -+ @Override -+ public void setHurtDirection(float hurtDirection) { -+ getHandle().setHurtDirection(hurtDirection); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/Unmapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch deleted file mode 100644 index a29c90ad3c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 24 Dec 2020 12:43:39 -0800 -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 55619fbc3fdb9393d7c47a23dc337b06ce4495d6..94476dfc0178f924fdad51b15f131ed266268776 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -271,6 +271,10 @@ public class CraftEventFactory { - return BedEnterResult.TOO_FAR_AWAY; - case NOT_SAFE: - return BedEnterResult.NOT_SAFE; -+ // Paper start -+ case OBSTRUCTED: -+ return BedEnterResult.OBSTRUCTED; -+ // Paper end - default: - return BedEnterResult.OTHER_PROBLEM; - } diff --git a/Unmapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/Unmapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch deleted file mode 100644 index 3addc9816c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 27 Dec 2020 11:31:06 +0000 -Subject: [PATCH] Do not crash from invalid ingredient lists in - VillagerAcquireTradeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -index a614f5d5817bf999aca0f0b50f343031c8168392..10067731e6289211cb11b2b368527a1c45603314 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -@@ -273,7 +273,11 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - Bukkit.getPluginManager().callEvent(event); - } - if (!event.isCancelled()) { -- merchantrecipelist.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); -+ // Paper start -+ final CraftMerchantRecipe craftMerchantRecipe = CraftMerchantRecipe.fromBukkit(event.getRecipe()); -+ if (craftMerchantRecipe.getIngredients().isEmpty()) return; -+ merchantrecipelist.add(craftMerchantRecipe.toMinecraft()); -+ // Paper end - } - // CraftBukkit end - } diff --git a/Unmapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch b/Unmapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch deleted file mode 100644 index 7ebc2efe3b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 2 Jul 2020 16:12:10 -0700 -Subject: [PATCH] added PlayerTradeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index da190d0b21098e327fab42e79a4ae18629bcf6e5..969e5fa3080a98850f03ba64c5662c32a8d501a6 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -93,7 +93,7 @@ import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; - public abstract class EntityInsentient extends EntityLiving { - - private static final DataWatcherObject b = DataWatcher.a(EntityInsentient.class, DataWatcherRegistry.a); -- public int e; -+ public int e;public void setAmbientSoundTime(int time) { this.e = time; } // Paper - OBFHELPER - protected int f; - protected ControllerLook lookController; - protected ControllerMove moveController; -@@ -295,6 +295,7 @@ public abstract class EntityInsentient extends EntityLiving { - this.datawatcher.register(EntityInsentient.b, (byte) 0); - } - -+ public int getAmbientSoundInterval() { return D(); } // Paper - OBFHELPER - public int D() { - return 80; - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -index 10067731e6289211cb11b2b368527a1c45603314..49821f0f26864c35be84a4a4288857a04668fbba 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -@@ -39,6 +39,9 @@ import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; - import org.bukkit.entity.AbstractVillager; - import org.bukkit.event.entity.VillagerAcquireTradeEvent; - // CraftBukkit end -+// Paper start -+import io.papermc.paper.event.player.PlayerTradeEvent; -+// Paper end - - public abstract class EntityVillagerAbstract extends EntityAgeable implements NPC, IMerchant { - -@@ -135,16 +138,27 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - - @Override - public void a(MerchantRecipe merchantrecipe) { -- merchantrecipe.increaseUses(); -- this.e = -this.D(); -- this.b(merchantrecipe); -+ // Paper - moved down -+ // Paper start - if (this.tradingPlayer instanceof EntityPlayer) { -- CriterionTriggers.s.a((EntityPlayer) this.tradingPlayer, this, merchantrecipe.getSellingItem()); -+ PlayerTradeEvent event = new PlayerTradeEvent(((EntityPlayer) this.tradingPlayer).getBukkitEntity(), (AbstractVillager) this.getBukkitEntity(), merchantrecipe.asBukkit(), true, true); -+ event.callEvent(); -+ if (!event.isCancelled()) { -+ MerchantRecipe recipe = CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft(); -+ if (event.willIncreaseTradeUses()) recipe.increaseUses(); -+ this.setAmbientSoundTime(-getAmbientSoundInterval()); -+ if (event.isRewardingExp()) this.rewardTradeXp(recipe); -+ CriterionTriggers.s.a((EntityPlayer) this.tradingPlayer, this, recipe.getSellingItem()); -+ } -+ } else { -+ merchantrecipe.increaseUses(); -+ this.setAmbientSoundTime(-getAmbientSoundInterval()); -+ this.rewardTradeXp(merchantrecipe); - } -- -+ // Paper end - } - -- protected abstract void b(MerchantRecipe merchantrecipe); -+ protected abstract void b(MerchantRecipe merchantrecipe); public void rewardTradeXp(MerchantRecipe merchantrecipe) { this.b(merchantrecipe); } // Paper - OBFHELPER - - @Override - public boolean isRegularVillager() { diff --git a/Unmapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch b/Unmapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch deleted file mode 100644 index eebdc5aa97..0000000000 --- a/Unmapped-Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Wed, 25 Nov 2020 23:20:44 -0800 -Subject: [PATCH] Implement TargetHitEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTarget.java b/src/main/java/net/minecraft/world/level/block/BlockTarget.java -index c336490815dc17991d3d84d8c6f0fc58571a3e3a..a9316ce8eb3d8a645f4c0e41ac668a90f584c263 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTarget.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTarget.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.TargetHitEvent; // Paper - Need to import because 'io' class exists in nms - import java.util.Random; - import net.minecraft.advancements.CriterionTriggers; - import net.minecraft.core.BlockPosition; -@@ -34,6 +35,10 @@ public class BlockTarget extends Block { - @Override - public void a(World world, IBlockData iblockdata, MovingObjectPositionBlock movingobjectpositionblock, IProjectile iprojectile) { - int i = a((GeneratorAccess) world, iblockdata, movingobjectpositionblock, (Entity) iprojectile); -+ // Paper start -+ } -+ private static void awardTargetHitCriteria(IProjectile iprojectile, MovingObjectPositionBlock movingobjectpositionblock, int i) { -+ // Paper end - Entity entity = iprojectile.getShooter(); - - if (entity instanceof EntityPlayer) { -@@ -49,6 +54,20 @@ public class BlockTarget extends Block { - int i = a(movingobjectpositionblock, movingobjectpositionblock.getPos()); - int j = entity instanceof EntityArrow ? 20 : 8; - -+ // Paper start -+ if (entity instanceof IProjectile) { -+ final IProjectile projectile = (IProjectile) entity; -+ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(generatoraccess, movingobjectpositionblock.getBlockPosition()); -+ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(movingobjectpositionblock.getDirection()); -+ final TargetHitEvent targetHitEvent = new TargetHitEvent((org.bukkit.entity.Projectile) projectile.getBukkitEntity(), craftBlock, blockFace, i); -+ if (targetHitEvent.callEvent()) { -+ i = targetHitEvent.getSignalStrength(); -+ awardTargetHitCriteria(projectile, movingobjectpositionblock, i); -+ } else { -+ return i; -+ } -+ } -+ // Paper end - if (!generatoraccess.getBlockTickList().a(movingobjectpositionblock.getBlockPosition(), iblockdata.getBlock())) { - a(generatoraccess, iblockdata, i, movingobjectpositionblock.getBlockPosition(), j); - } diff --git a/Unmapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch b/Unmapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch deleted file mode 100644 index ba38cd24b0..0000000000 --- a/Unmapped-Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 30 Dec 2020 19:43:01 -0500 -Subject: [PATCH] Additional Block Material API's - -Faster version for isSolid() that utilizes NMS's state for isSolid instead of the slower -process to do this in the Bukkit API - -Adds API for buildable, replaceable, burnable too. - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index fab9e1e5d63c22faceae093dc88769d203d359c6..ed1c92d9f2770f7d0503c6facebc51ddcbdf75cf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -621,6 +621,25 @@ public class CraftBlock implements Block { - return getNMS().getMaterial().isLiquid(); - } - -+ // Paper start -+ @Override -+ public boolean isBuildable() { -+ return getNMS().getMaterial().isBuildable(); -+ } -+ @Override -+ public boolean isBurnable() { -+ return getNMS().getMaterial().isBurnable(); -+ } -+ @Override -+ public boolean isReplaceable() { -+ return getNMS().getMaterial().isReplaceable(); -+ } -+ @Override -+ public boolean isSolid() { -+ return getNMS().getMaterial().isSolid(); -+ } -+ // Paper end -+ - @Override - public PistonMoveReaction getPistonMoveReaction() { - return PistonMoveReaction.getById(getNMS().getPushReaction().ordinal()); diff --git a/Unmapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch b/Unmapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch deleted file mode 100644 index 0e9ad1d647..0000000000 --- a/Unmapped-Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> -Date: Thu, 23 Jul 2020 14:25:07 -0700 -Subject: [PATCH] Fix harming potion dupe - -EntityLiving#applyInstantEffect() immediately kills the player and drops their inventory. -Before this patch, instant effects would be applied before the potion ItemStack is removed and replaced with a glass bottle. This caused the potion ItemStack to be dropped before it was supposed to be removed from the inventory. It also caused the glass bottle to be put into a dead player's inventory. -This patch makes it so that instant effects are applied after the potion ItemStack is removed, and the glass bottle is only put into the player's inventory if the player is not dead. Otherwise, the glass bottle is dropped on the ground. - -diff --git a/src/main/java/net/minecraft/world/item/ItemPotion.java b/src/main/java/net/minecraft/world/item/ItemPotion.java -index b197fe561ab735e80d8bf29ac16eacfaf3fc2d21..ca2f8d522d7f2305f161cb4aa611226355ea5789 100644 ---- a/src/main/java/net/minecraft/world/item/ItemPotion.java -+++ b/src/main/java/net/minecraft/world/item/ItemPotion.java -@@ -15,6 +15,7 @@ import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.alchemy.PotionRegistry; - import net.minecraft.world.item.alchemy.PotionUtil; - import net.minecraft.world.item.alchemy.Potions; -+import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.World; - - public class ItemPotion extends Item { -@@ -36,6 +37,7 @@ public class ItemPotion extends Item { - CriterionTriggers.z.a((EntityPlayer) entityhuman, itemstack); - } - -+ List instantLater = new java.util.ArrayList<>(); // Paper - Fix harming potion dupe - if (!world.isClientSide) { - List list = PotionUtil.getEffects(itemstack); - Iterator iterator = list.iterator(); -@@ -44,7 +46,7 @@ public class ItemPotion extends Item { - MobEffect mobeffect = (MobEffect) iterator.next(); - - if (mobeffect.getMobEffect().isInstant()) { -- mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, entityliving, mobeffect.getAmplifier(), 1.0D); -+ instantLater.add(mobeffect); // Paper - Fix harming potion dupe - } else { - entityliving.addEffect(new MobEffect(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit - } -@@ -58,7 +60,20 @@ public class ItemPotion extends Item { - } - } - -+ // Paper start - Fix harming potion dupe -+ for (MobEffect mobeffect : instantLater) { -+ mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, entityliving, mobeffect.getAmplifier(), 1.0D); -+ } -+ // Paper end -+ - if (entityhuman == null || !entityhuman.abilities.canInstantlyBuild) { -+ // Paper start - Fix harming potion dupe -+ if (entityliving.getHealth() <= 0 && !entityliving.world.getGameRules().getBoolean(GameRules.KEEP_INVENTORY)) { -+ entityliving.dropItem(new ItemStack(Items.GLASS_BOTTLE), 0); -+ return ItemStack.NULL_ITEM; -+ } -+ // Paper end -+ - if (itemstack.isEmpty()) { - return new ItemStack(Items.GLASS_BOTTLE); - } diff --git a/Unmapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/Unmapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch deleted file mode 100644 index 02569905c0..0000000000 --- a/Unmapped-Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Thu, 31 Dec 2020 12:48:19 +1000 -Subject: [PATCH] Implement API to get Material from Boats and Minecarts - - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index add2aef0192a3b3767c1e477145978b9702c0fb4..2609b83573e0e8532e6c4c36d4f475bf0da6a354 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -260,6 +260,7 @@ public class EntityBoat extends Entity { - - } - -+ public final Item getBoatItem() { return this.g(); } // Paper - OBFHELPER - public Item g() { - switch (this.getType()) { - case OAK: -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -index c7a459c0c860724ef1890b8fb9a59a5508b3f6d6..16799dc565c5ca42d1fdb3122594d9dae21c74e0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -@@ -1,8 +1,10 @@ - package org.bukkit.craftbukkit.entity; - - import net.minecraft.world.entity.vehicle.EntityBoat; -+import org.bukkit.Material; // Paper - import org.bukkit.TreeSpecies; - import org.bukkit.craftbukkit.CraftServer; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper - import org.bukkit.entity.Boat; - import org.bukkit.entity.EntityType; - -@@ -66,6 +68,13 @@ public class CraftBoat extends CraftVehicle implements Boat { - getHandle().landBoats = workOnLand; - } - -+ // Paper start -+ @Override -+ public Material getBoatMaterial() { -+ return CraftMagicNumbers.getMaterial(getHandle().getBoatItem()); -+ } -+ // Paper end -+ - @Override - public EntityBoat getHandle() { - return (EntityBoat) entity; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -index 69415f5a838345826fa5cf1d855e057794520f2c..e5ebb80a44da775df6f3d5a9db5cf58295e2e960 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -@@ -1,8 +1,10 @@ - package org.bukkit.craftbukkit.entity; - - import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; -+import net.minecraft.world.item.Items; // Paper - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; -+import org.bukkit.Material; // Paper - import org.bukkit.block.data.BlockData; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.block.data.CraftBlockData; -@@ -68,6 +70,38 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart { - getHandle().setDerailedVelocityMod(derailed); - } - -+ // Paper start -+ @Override -+ public Material getMinecartMaterial() { -+ net.minecraft.world.item.Item minecartItem; -+ switch (getHandle().getMinecartType()) { -+ case CHEST: -+ minecartItem = Items.CHEST_MINECART; -+ break; -+ case FURNACE: -+ minecartItem = Items.FURNACE_MINECART; -+ break; -+ case TNT: -+ minecartItem = Items.TNT_MINECART; -+ break; -+ case HOPPER: -+ minecartItem = Items.HOPPER_MINECART; -+ break; -+ case COMMAND_BLOCK: -+ minecartItem = Items.COMMAND_BLOCK_MINECART; -+ break; -+ case RIDEABLE: -+ case SPAWNER: -+ minecartItem = Items.MINECART; -+ break; -+ default: -+ throw new IllegalStateException("Unexpected value: " + getHandle().getMinecartType()); -+ } -+ -+ return CraftMagicNumbers.getMaterial(minecartItem); -+ } -+ // Paper end -+ - @Override - public EntityMinecartAbstract getHandle() { - return (EntityMinecartAbstract) entity; diff --git a/Unmapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch b/Unmapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch deleted file mode 100644 index 522f5db773..0000000000 --- a/Unmapped-Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas -Date: Sun, 27 Dec 2020 17:19:51 +0100 -Subject: [PATCH] Optimized tick ready check - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index f40be366ebc5f98b417b677565fa89d3f817f3fb..78dcba08d6d796d5d97c8304bf1f1e7d1e650d5d 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -854,13 +854,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - if (!tileentity.isRemoved() && tileentity.hasWorld()) { - BlockPosition blockposition = tileentity.getPosition(); - -- if (this.getChunkProvider().a(blockposition) && this.getWorldBorder().a(blockposition)) { -+ Chunk chunk; PlayerChunk playerChunk; if ((chunk = tileentity.getCurrentChunk()) != null && (playerChunk = chunk.playerChunk) != null && playerChunk.isTickingReady() && this.getWorldBorder().isInBounds(blockposition)) { // Paper - optimized tick ready check by inlining ChunkProviderServer.a(BlockPosition). Chunk lookup is no longer required and we can use the PlayerChunk directly available through the tile entity - try { - gameprofilerfiller.a(() -> { - return String.valueOf(TileEntityTypes.a(tileentity.getTileType())); - }); - tileentity.tickTimer.startTiming(); // Spigot -- if (tileentity.getTileType().isValidBlock(this.getType(blockposition).getBlock())) { -+ if (tileentity.getTileType().isValidBlock(chunk.getType(blockposition).getBlock())) { // Paper - reuse the chunk from above, do not look it up again - ((ITickable) tileentity).tick(); - } else { - tileentity.w(); -@@ -893,9 +893,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.tileEntityListTick.remove(tileTickPosition--); - // Spigot end - //this.tileEntityList.remove(tileentity); // Paper - remove unused list -- if (this.isLoaded(tileentity.getPosition())) { -- this.getChunkAtWorldCoords(tileentity.getPosition()).removeTileEntity(tileentity.getPosition()); -+ // Paper - prevent double chunk lookups -+ Chunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getPosition())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again -+ chunk.removeTileEntity(tileentity.getPosition()); - } -+ // Paper end - } - } - -@@ -914,8 +916,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - // CraftBukkit end */ - -- if (this.isLoaded(tileentity1.getPosition())) { -- Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); -+ Chunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity1.getPosition())) != null) { // Paper - inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again -+ // Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); // Paper - already computed above - IBlockData iblockdata = chunk.getType(tileentity1.getPosition()); - - chunk.setTileEntity(tileentity1.getPosition(), tileentity1); diff --git a/Unmapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch b/Unmapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch deleted file mode 100644 index 1c9afd6350..0000000000 --- a/Unmapped-Spigot-Server-Patches/0625-Cache-burn-durations.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas -Date: Sun, 27 Dec 2020 16:47:00 +0100 -Subject: [PATCH] Cache burn durations - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index e630e8d3e115d2a0177849ad8258a2304b9d3e9d..54316a8079b4331a48cac3c43f3f8c506a4af091 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.block.entity; - -+import com.google.common.collect.ImmutableMap; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; -@@ -113,7 +114,15 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - this.c = recipes; - } - -+ private static Map cachedBurnDurations = null; // Paper - cache burn durations -+ -+ public static Map getBurnDurations() { return f(); } // Paper - OBFHELPER - public static Map f() { -+ // Paper start - cache burn durations -+ if(cachedBurnDurations != null) { -+ return cachedBurnDurations; -+ } -+ // Paper end - Map map = Maps.newLinkedHashMap(); - - a(map, (IMaterial) Items.LAVA_BUCKET, 20000); -@@ -176,7 +185,10 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - a(map, (IMaterial) Blocks.FLETCHING_TABLE, 300); - a(map, (IMaterial) Blocks.SMITHING_TABLE, 300); - a(map, (IMaterial) Blocks.COMPOSTER, 300); -- return map; -+ // Paper start - cache burn durations -+ cachedBurnDurations = ImmutableMap.copyOf(map); -+ return cachedBurnDurations; -+ // Paper end - } - - // CraftBukkit start - add fields and methods -@@ -430,7 +442,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - } else { - Item item = itemstack.getItem(); - -- return (Integer) f().getOrDefault(item, 0); -+ return getBurnDurations().getOrDefault(item, 0); // Paper - cache burn durations - } - } - -@@ -443,7 +455,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - // Paper end - - public static boolean isFuel(ItemStack itemstack) { -- return f().containsKey(itemstack.getItem()); -+ return getBurnDurations().containsKey(itemstack.getItem()); // Paper - cache burn durations - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/Unmapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch deleted file mode 100644 index 115f473843..0000000000 --- a/Unmapped-Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BrodyBeckwith -Date: Fri, 9 Oct 2020 20:30:12 -0400 -Subject: [PATCH] Allow disabling mob spawner spawn egg transformation - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a3b3e3e04b7a5e3a351992e06870cc91fbd8adc8..b48067c71f9de18ba40e970e2832f6245984a218 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -722,4 +722,9 @@ public class PaperWorldConfig { - private void fixCuringExploit() { - fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); - } -+ -+ public boolean disableMobSpawnerSpawnEggTransformation = false; -+ private void disableMobSpawnerSpawnEggTransformation() { -+ disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); -+ } - } -diff --git a/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java b/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java -index c170d2141504d80624e3c1a7f78f7968ea8a80ee..4d965e504a40eb52777575df839856c825a0900a 100644 ---- a/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java -+++ b/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java -@@ -60,7 +60,7 @@ public class ItemMonsterEgg extends Item { - EnumDirection enumdirection = itemactioncontext.getClickedFace(); - IBlockData iblockdata = world.getType(blockposition); - -- if (iblockdata.a(Blocks.SPAWNER)) { -+ if (!world.paperConfig.disableMobSpawnerSpawnEggTransformation && iblockdata.a(Blocks.SPAWNER)) { // Paper - TileEntity tileentity = world.getTileEntity(blockposition); - - if (tileentity instanceof TileEntityMobSpawner) { diff --git a/Unmapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch b/Unmapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch deleted file mode 100644 index 43503c58f0..0000000000 --- a/Unmapped-Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterVector -Date: Tue, 13 Aug 2019 19:45:06 -0700 -Subject: [PATCH] Implement PlayerFlowerPotManipulateEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java b/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java -index a61d1ffeebfd00a5fcd5faf95200b0640da8ea82..18fefad056d92a6fa498ab3764cd391446c26b60 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java -@@ -21,6 +21,8 @@ import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.phys.shapes.VoxelShapeCollision; - -+import io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent; // Paper -+ - public class BlockFlowerPot extends Block { - - private static final Map b = Maps.newHashMap(); -@@ -52,6 +54,27 @@ public class BlockFlowerPot extends Block { - boolean flag1 = this.c == Blocks.AIR; - - if (flag != flag1) { -+ // Paper start -+ org.bukkit.entity.Player player = (org.bukkit.entity.Player) entityhuman.getBukkitEntity(); -+ boolean placing = flag1; -+ org.bukkit.block.Block bukkitblock = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition); -+ org.bukkit.inventory.ItemStack bukkititemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack); -+ org.bukkit.Material mat = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(c); -+ org.bukkit.inventory.ItemStack bukkititemstack1 = new org.bukkit.inventory.ItemStack(mat, 1); -+ org.bukkit.inventory.ItemStack whichitem = placing ? bukkititemstack : bukkititemstack1; -+ -+ PlayerFlowerPotManipulateEvent event = new PlayerFlowerPotManipulateEvent(player, bukkitblock, whichitem, placing); -+ player.getServer().getPluginManager().callEvent(event); -+ -+ if (event.isCancelled()) { -+ // Update client -+ player.sendBlockChange(bukkitblock.getLocation(), bukkitblock.getBlockData()); -+ player.updateInventory(); -+ -+ return EnumInteractionResult.PASS; -+ } -+ // Paper end -+ - if (flag1) { - world.setTypeAndData(blockposition, block.getBlockData(), 3); - entityhuman.a(StatisticList.POT_FLOWER); diff --git a/Unmapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch b/Unmapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch deleted file mode 100644 index 011f84bd00..0000000000 --- a/Unmapped-Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheMolkaPL -Date: Sun, 21 Jun 2020 17:21:46 +0200 -Subject: [PATCH] Fix interact event not being called in adventure - -Call PlayerInteractEvent when left-clicking on a block in adventure mode - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index ef38900107cc62222b303517ea4a65bff06c66b1..c68e56562076a2ca3d099a1112404f11a5473397 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1703,7 +1703,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - IChatMutableComponent ichatmutablecomponent = (new ChatMessage("build.tooHigh", new Object[]{this.minecraftServer.getMaxBuildHeight()})).a(EnumChatFormat.RED); - - this.player.playerConnection.sendPacket(new PacketPlayOutChat(ichatmutablecomponent, ChatMessageType.GAME_INFO, SystemUtils.b)); -- } else if (enuminteractionresult.b()) { -+ } else if (enuminteractionresult.b() && !this.player.playerInteractManager.interactResult) { - this.player.swingHand(enumhand, true); - } - } -@@ -2204,7 +2204,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - Vec3D vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); - MovingObjectPosition movingobjectposition = this.player.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.OUTLINE, RayTrace.FluidCollisionOption.NONE, player)); - -- if (movingobjectposition == null || movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.BLOCK) { -+ if (movingobjectposition == null || movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.BLOCK || this.player.playerInteractManager.getGameMode() == EnumGamemode.ADVENTURE) { // Paper - call PlayerInteractEvent when left-clicking on a block in adventure mode - CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.inventory.getItemInHand(), EnumHand.MAIN_HAND); - } - diff --git a/Unmapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch b/Unmapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch deleted file mode 100644 index da61412550..0000000000 --- a/Unmapped-Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 18 Nov 2020 11:32:46 -0800 -Subject: [PATCH] Zombie API - breaking doors - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 87acbdee03edf8bc35f4b3bcb9b82855ed4a3c33..5b0c79d752d616e5824393968136f3844ce52c22 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -140,10 +140,12 @@ public class EntityZombie extends EntityMonster { - return (Boolean) this.getDataWatcher().get(EntityZombie.DROWN_CONVERTING); - } - -+ public boolean canBreakDoors() { return this.eU(); } // Paper - OBFHELPER - public boolean eU() { - return this.bs; - } - -+ public void setCanBreakDoors(boolean canBreakDoors) { this.u(canBreakDoors); } // Paper - OBFHELPER - public void u(boolean flag) { - if (this.eK() && PathfinderGoalUtil.a(this)) { - if (this.bs != flag) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 42d98d798bb8fe2d3c7cc2bfcf2ec38d97d99bd2..e1589ef97222f5e29a3628db354d4406a443a613 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -@@ -129,6 +129,16 @@ public class CraftZombie extends CraftMonster implements Zombie { - public void setShouldBurnInDay(boolean shouldBurnInDay) { - getHandle().setShouldBurnInDay(shouldBurnInDay); - } -+ -+ @Override -+ public boolean canBreakDoors() { -+ return getHandle().canBreakDoors(); -+ } -+ -+ @Override -+ public void setCanBreakDoors(boolean canBreakDoors) { -+ getHandle().setCanBreakDoors(canBreakDoors); -+ } - // Paper end - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch b/Unmapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch deleted file mode 100644 index 875960eb0b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 24 Aug 2020 08:39:06 -0700 -Subject: [PATCH] Fix nerfed slime when splitting - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -index 40e39e382092b1a8f831da0cea1557a781c98600..0af0b232ff1b6f1d58cf3fb543d32bd108be0af7 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -@@ -246,6 +246,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { - entityslime.setPersistent(); - } - -+ entityslime.aware = this.aware; // Paper - entityslime.setCustomName(ichatbasecomponent); - entityslime.setNoAI(flag); - entityslime.setInvulnerable(this.isInvulnerable()); diff --git a/Unmapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch b/Unmapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch deleted file mode 100644 index 5e9ae2150b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 7 Oct 2020 12:04:01 -0400 -Subject: [PATCH] Add EntityLoadCrossbowEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ItemCrossbow.java b/src/main/java/net/minecraft/world/item/ItemCrossbow.java -index ec6c0836f02e7ac5b72fd224a3022a844dce55cb..4e1e819c8535e8a6b9aa5f76afe568ea171b939f 100644 ---- a/src/main/java/net/minecraft/world/item/ItemCrossbow.java -+++ b/src/main/java/net/minecraft/world/item/ItemCrossbow.java -@@ -3,6 +3,8 @@ package net.minecraft.world.item; - import com.google.common.collect.Lists; - import com.mojang.math.Quaternion; - import com.mojang.math.Vector3fa; -+import org.bukkit.inventory.EquipmentSlot; // Paper -+import io.papermc.paper.event.entity.EntityLoadCrossbowEvent; // Paper - EntityLoadCrossbowEvent namespace conflicts - import java.util.List; - import java.util.Random; - import java.util.function.Predicate; -@@ -73,7 +75,11 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable - int j = this.e_(itemstack) - i; - float f = a(j, itemstack); - -- if (f >= 1.0F && !d(itemstack) && a(entityliving, itemstack)) { -+ // Paper start - EntityLoadCrossbowEvent -+ if (f >= 1.0F && !d(itemstack) /*&& a(entityliving, itemstack)*/) { -+ final EntityLoadCrossbowEvent event = new EntityLoadCrossbowEvent(entityliving.getBukkitLivingEntity(), itemstack.asBukkitMirror(), entityliving.getRaisedHand() == EnumHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND); -+ if (!event.callEvent() || !attemptProjectileLoad(entityliving, itemstack, event.shouldConsumeItem())) return; -+ // Paper end - a(itemstack, true); - SoundCategory soundcategory = entityliving instanceof EntityHuman ? SoundCategory.PLAYERS : SoundCategory.HOSTILE; - -@@ -82,10 +88,13 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable - - } - -- private static boolean a(EntityLiving entityliving, ItemStack itemstack) { -+ private static boolean attemptProjectileLoad(EntityLiving ent, ItemStack bow) { return a(ent, bow); } // Paper - EntityLoadCrossbowEvent - OBFHELPER -+ private static boolean attemptProjectileLoad(EntityLiving ent, ItemStack bow, boolean consume) { return a(ent, bow, consume); } // Paper - EntityLoadCrossbowEvent - OBFHELPER -+ private static boolean a(EntityLiving entityliving, ItemStack itemstack) { return a(entityliving, itemstack, true); };// Paper - add consume -+ private static boolean a(EntityLiving entityliving, ItemStack itemstack, boolean consume) { // Paper - add consume - int i = EnchantmentManager.getEnchantmentLevel(Enchantments.MULTISHOT, itemstack); - int j = i == 0 ? 1 : 3; -- boolean flag = entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.canInstantlyBuild; -+ boolean flag = !consume || entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.canInstantlyBuild; // Paper - add consme - ItemStack itemstack1 = entityliving.f(itemstack); - ItemStack itemstack2 = itemstack1.cloneItemStack(); - diff --git a/Unmapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch b/Unmapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch deleted file mode 100644 index 4439204159..0000000000 --- a/Unmapped-Spigot-Server-Patches/0632-Guardian-beam-workaround.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabscap -Date: Sat, 19 Mar 2016 22:25:11 +0100 -Subject: [PATCH] Guardian beam workaround - -This patch is a workaround for MC-165595 - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java -index a69e60a8934493f6786ce3d425f6dccb6e4befdd..3086ee023685781d94e2fb99fc8dff5264f01165 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java -@@ -6,7 +6,7 @@ import net.minecraft.network.protocol.Packet; - - public class PacketPlayOutUpdateTime implements Packet { - -- private long a; -+ private long a; private final void setWorldAge(final long age) { this.a = age; } private final long getWorldAge() { return this.a; } // Paper - OBFHELPER - private long b; - - public PacketPlayOutUpdateTime() {} -@@ -21,6 +21,9 @@ public class PacketPlayOutUpdateTime implements Packet { - } - } - -+ // Paper start -+ this.setWorldAge(this.getWorldAge() % 192000); -+ // Paper end - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch deleted file mode 100644 index 6eec095679..0000000000 --- a/Unmapped-Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 20 Dec 2020 16:41:44 -0800 -Subject: [PATCH] Added WorldGameRuleChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/commands/CommandGamerule.java b/src/main/java/net/minecraft/server/commands/CommandGamerule.java -index 5b5c5d1299c267f620f5c59873b261a7b7e382a9..feebe4812ff7aec17a50cb5f2789fe88e10a5032 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandGamerule.java -+++ b/src/main/java/net/minecraft/server/commands/CommandGamerule.java -@@ -31,7 +31,7 @@ public class CommandGamerule { - CommandListenerWrapper commandlistenerwrapper = (CommandListenerWrapper) commandcontext.getSource(); - T t0 = commandlistenerwrapper.getWorld().getGameRules().get(gamerules_gamerulekey); // CraftBukkit - -- t0.b(commandcontext, "value"); -+ t0.setValue(commandcontext, "value", gamerules_gamerulekey); // Paper - commandlistenerwrapper.sendMessage(new ChatMessage("commands.gamerule.set", new Object[]{gamerules_gamerulekey.a(), t0.toString()}), true); - return t0.getIntValue(); - } -diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java -index 276c28170b2a177dab6b2a0d5425044cd9f8df22..3783f3a83e3e70d77cf0fa1021f62a89c5950af5 100644 ---- a/src/main/java/net/minecraft/world/level/GameRules.java -+++ b/src/main/java/net/minecraft/world/level/GameRules.java -@@ -25,6 +25,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.event.world.WorldGameRuleChangeEvent; // Paper - - public class GameRules { - -@@ -177,8 +178,11 @@ public class GameRules { - } - - @Override -- protected void a(CommandContext commandcontext, String s) { -- this.b = BoolArgumentType.getBool(commandcontext, s); -+ protected void a(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { // Paper start -+ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(commandcontext, s))); -+ if (!event.callEvent()) return; -+ this.b = Boolean.parseBoolean(event.getValue()); -+ // Paper end - } - - public boolean a() { -@@ -237,8 +241,11 @@ public class GameRules { - } - - @Override -- protected void a(CommandContext commandcontext, String s) { -- this.b = IntegerArgumentType.getInteger(commandcontext, s); -+ protected void a(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { // Paper start -+ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(commandcontext, s))); -+ if (!event.callEvent()) return; -+ this.b = Integer.parseInt(event.getValue()); -+ // Paper end - } - - public int a() { -@@ -291,10 +298,12 @@ public class GameRules { - this.a = gamerules_gameruledefinition; - } - -- protected abstract void a(CommandContext commandcontext, String s); -+ protected void updateValue(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { this.a(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER -+ protected abstract void a(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey); // Paper - -- public void b(CommandContext commandcontext, String s) { -- this.a(commandcontext, s); -+ public void setValue(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { this.b(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER -+ public void b(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { // Paper -+ this.updateValue(commandcontext, s, gameRuleKey); // Paper - this.onChange(((CommandListenerWrapper) commandcontext.getSource()).getServer()); - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 776733a4a913d232126b48f2d0eadbe27aa84e59..05a7f5f61330bd52705640345524cdedbf105285 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2363,8 +2363,13 @@ public class CraftWorld implements World { - - if (!isGameRule(rule)) return false; - -+ // Paper start -+ GameRule gameRule = GameRule.getByName(rule); -+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, gameRule, value); -+ if (!event.callEvent()) return false; -+ // Paper end - GameRules.GameRuleValue handle = getHandle().getGameRules().get(getGameRulesNMS().get(rule)); -- handle.setValue(value); -+ handle.setValue(event.getValue().toString()); // Paper - handle.onChange(getHandle().getMinecraftServer()); - return true; - } -@@ -2399,8 +2404,12 @@ public class CraftWorld implements World { - - if (!isGameRule(rule.getName())) return false; - -+ // Paper start -+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, rule, String.valueOf(newValue)); -+ if (!event.callEvent()) return false; -+ // Paper end - GameRules.GameRuleValue handle = getHandle().getGameRules().get(getGameRulesNMS().get(rule.getName())); -- handle.setValue(newValue.toString()); -+ handle.setValue(event.getValue().toString()); // Paper - handle.onChange(getHandle().getMinecraftServer()); - return true; - } diff --git a/Unmapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch b/Unmapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch deleted file mode 100644 index 7d280a01e0..0000000000 --- a/Unmapped-Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Dec 2020 20:04:01 -0800 -Subject: [PATCH] Added ServerResourcesReloadedEvent - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e43fcdc806ff4e2db22d031006c96e68fc81f5fd..fe02a46df9c652acf4a4bc0ed194522f400cda34 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2,9 +2,6 @@ package net.minecraft.server; - - import com.google.common.base.Splitter; - import com.google.common.collect.ImmutableList; --import co.aikar.timings.Timings; --import com.destroystokyo.paper.event.server.PaperServerListPingEvent; --import com.google.common.base.Stopwatch; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -183,6 +180,7 @@ import org.bukkit.event.server.ServerLoadEvent; - import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot - import io.papermc.paper.util.PaperJvmChecker; // Paper -+import io.papermc.paper.event.server.ServerResourcesReloadedEvent; // Paper - - public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { - -@@ -1936,7 +1934,13 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant a(Collection collection) { -+ return this.reloadServerResources(collection, ServerResourcesReloadedEvent.Cause.PLUGIN); -+ } -+ public CompletableFuture reloadServerResources(Collection collection, ServerResourcesReloadedEvent.Cause cause) { -+ // Paper end - CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { - Stream stream = collection.stream(); // CraftBukkit - decompile error - ResourcePackRepository resourcepackrepository = this.resourcePackRepository; -@@ -1952,6 +1956,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant collection, CommandListenerWrapper commandlistenerwrapper) { -- commandlistenerwrapper.getServer().a(collection).exceptionally((throwable) -> { -+ commandlistenerwrapper.getServer().reloadServerResources(collection, ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally((throwable) -> { // Paper - CommandReload.LOGGER.warn("Failed to execute reload", throwable); - commandlistenerwrapper.sendFailureMessage(new ChatMessage("commands.reload.failure")); - return null; -@@ -48,7 +49,7 @@ public class CommandReload { - SaveData savedata = minecraftserver.getSaveData(); - Collection collection = resourcepackrepository.d(); - Collection collection1 = a(resourcepackrepository, savedata, collection); -- minecraftserver.a(collection1); -+ minecraftserver.reloadServerResources(collection1, ServerResourcesReloadedEvent.Cause.PLUGIN); // Paper - } - // CraftBukkit end - diff --git a/Unmapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch b/Unmapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch deleted file mode 100644 index 10e2cd6329..0000000000 --- a/Unmapped-Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 28 Nov 2020 18:43:52 -0800 -Subject: [PATCH] Added world settings for mobs picking up loot - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b48067c71f9de18ba40e970e2832f6245984a218..23a23e2ea133ce81d3dedc4ffd17435a995497ef 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -363,6 +363,14 @@ public class PaperWorldConfig { - log("Creeper lingering effect: " + disableCreeperLingeringEffect); - } - -+ public boolean zombiesAlwaysCanPickUpLoot; -+ public boolean skeletonsAlwaysCanPickUpLoot; -+ private void setMobsAlwaysCanPickUpLoot() { -+ zombiesAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.zombies", false); -+ skeletonsAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.skeletons", false); -+ log("Zombies can always pick up loot: " + zombiesAlwaysCanPickUpLoot + ". Skeletons can always pick up loot: " + skeletonsAlwaysCanPickUpLoot + "."); -+ } -+ - public int expMergeMaxValue; - private void expMergeMaxValue() { - expMergeMaxValue = getInt("experience-merge-max-value", -1); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -index 4dca5ea9127c15b2739483b2ad74a5296a6b96ad..06d50b22ede102556fdb3e2a6f1424f7ff13f120 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -@@ -149,7 +149,7 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - this.a(difficultydamagescaler); - this.b(difficultydamagescaler); - this.eL(); -- this.setCanPickupLoot(this.random.nextFloat() < 0.55F * difficultydamagescaler.d()); -+ this.setCanPickupLoot(this.world.paperConfig.skeletonsAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * difficultydamagescaler.d()); // Paper - if (this.getEquipment(EnumItemSlot.HEAD).isEmpty()) { - LocalDate localdate = LocalDate.now(); - int i = localdate.get(ChronoField.DAY_OF_MONTH); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 5b0c79d752d616e5824393968136f3844ce52c22..fb98609a38d665659076b8949b59eaf084408a17 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -497,7 +497,7 @@ public class EntityZombie extends EntityMonster { - Object object = super.prepare(worldaccess, difficultydamagescaler, enummobspawn, groupdataentity, nbttagcompound); - float f = difficultydamagescaler.d(); - -- this.setCanPickupLoot(this.random.nextFloat() < 0.55F * f); -+ this.setCanPickupLoot(this.world.paperConfig.zombiesAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * f); // Paper - if (object == null) { - object = new EntityZombie.GroupDataZombie(a(worldaccess.getRandom()), true); - } diff --git a/Unmapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch b/Unmapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch deleted file mode 100644 index c2620d5836..0000000000 --- a/Unmapped-Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheViperShow <29604693+TheViperShow@users.noreply.github.com> -Date: Wed, 22 Apr 2020 09:40:38 +0200 -Subject: [PATCH] Implemented BlockFailedDispenseEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -index 0ab6186ba3cfd7f7115c71b3982f46c5d2c921c0..966051ab3e720e5b3f0fb9ab852c8908c5f23f3b 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -@@ -81,6 +81,7 @@ public class BlockDispenser extends BlockTileEntity { - int i = tileentitydispenser.h(); - - if (i < 0) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, blockposition)) // Paper - BlockFailedDispenseEvent is called here - worldserver.triggerEffect(1001, blockposition, 0); - } else { - ItemStack itemstack = tileentitydispenser.getItem(i); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockDropper.java b/src/main/java/net/minecraft/world/level/block/BlockDropper.java -index ccab4714bf5a6be8afd92430874fd6f881d4f92f..223cc0ba06cf4b007049880daad881e55ac4e448 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockDropper.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockDropper.java -@@ -47,6 +47,7 @@ public class BlockDropper extends BlockDispenser { - int i = tileentitydispenser.h(); - - if (i < 0) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, blockposition)) // Paper - BlockFailedDispenseEvent is called here - worldserver.triggerEffect(1001, blockposition, 0); - } 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 94476dfc0178f924fdad51b15f131ed266268776..a7f8e08dcbc102041891e51cbe9c984d6f43747b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -4,6 +4,7 @@ import com.google.common.base.Function; - import com.google.common.base.Functions; - import com.google.common.collect.Lists; - import com.mojang.datafixers.util.Either; -+import io.papermc.paper.event.block.BlockFailedDispenseEvent; - import java.net.InetAddress; - import java.util.ArrayList; - import java.util.Collections; -@@ -123,7 +124,6 @@ import org.bukkit.entity.ThrownPotion; - import org.bukkit.entity.Vehicle; - import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; --import org.bukkit.entity.ExperienceOrb; // Paper - import org.bukkit.event.Cancellable; - import org.bukkit.event.Event; - import org.bukkit.event.Event.Result; -@@ -1796,4 +1796,12 @@ public class CraftEventFactory { - Bukkit.getPluginManager().callEvent(event); - return event; - } -+ -+ // Paper start -+ public static boolean handleBlockFailedDispenseEvent(WorldServer worldserver, BlockPosition blockposition) { -+ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); -+ return event.callEvent(); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch deleted file mode 100644 index eb926aff50..0000000000 --- a/Unmapped-Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 23 Nov 2020 12:58:51 -0800 -Subject: [PATCH] Added PlayerLecternPageChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index e7c29d194d5c3e3b1b79228758f7a3d8aa060fbd..9c6330da4e026a7753698b5d103c009730154c3e 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -562,6 +562,7 @@ public abstract class Container { - this.getSlot(i).set(itemstack); - } - -+ public void setData(int index, int value) { this.a(index, value); } // Paper - OBFHELPER - public void a(int i, int j) { - ((ContainerProperty) this.d.get(i)).set(j); - } -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLectern.java b/src/main/java/net/minecraft/world/inventory/ContainerLectern.java -index 70d9ebca8d176d6483f104bd03598753811fc154..65687792351fbd561b1f4d6f88bc7288b6d8346f 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerLectern.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerLectern.java -@@ -14,6 +14,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - import org.bukkit.event.player.PlayerTakeLecternBookEvent; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerLecternPageChangeEvent; // Paper - - public class ContainerLectern extends Container { - -@@ -61,6 +62,7 @@ public class ContainerLectern extends Container { - @Override - public boolean a(EntityHuman entityhuman, int i) { - int j; -+ PlayerLecternPageChangeEvent playerLecternPageChangeEvent; CraftInventoryLectern bukkitView; // Paper - - if (i >= 100) { - j = i - 100; -@@ -70,11 +72,25 @@ public class ContainerLectern extends Container { - switch (i) { - case 1: - j = this.containerProperties.getProperty(0); -- this.a(0, j - 1); -+ // Paper start -+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); -+ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, j, j - 1); -+ if (!playerLecternPageChangeEvent.callEvent()) { -+ return false; -+ } -+ this.setData(0, playerLecternPageChangeEvent.getNewPage()); -+ // Paper end - return true; - case 2: - j = this.containerProperties.getProperty(0); -- this.a(0, j + 1); -+ // Paper start -+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); -+ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, j, j + 1); -+ if (!playerLecternPageChangeEvent.callEvent()) { -+ return false; -+ } -+ this.setData(0, playerLecternPageChangeEvent.getNewPage()); -+ // Paper end - return true; - case 3: - if (!entityhuman.eK()) { diff --git a/Unmapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch b/Unmapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch deleted file mode 100644 index 24dd766968..0000000000 --- a/Unmapped-Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 17 Mar 2019 21:46:56 +0200 -Subject: [PATCH] Fire event on GS4 query - - -diff --git a/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java b/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java -index 57ff3db0a0199ef03045b880e598407886b0306b..1b6761f75d97c49b1bf1ce3db631b7250c9489bd 100644 ---- a/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java -+++ b/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java -@@ -18,15 +18,27 @@ public class RemoteStatusReply { - this.b.write(abyte, 0, abyte.length); - } - -+ public void writeString(String string) throws IOException { this.a(string); } // Paper - OBFHELPER - public void a(String s) throws IOException { - this.b.writeBytes(s); - this.b.write(0); - } -+ // Paper start - unchecked exception variant to use in Stream API -+ public void writeStringUnchecked(String string) { -+ try { -+ writeString(string); -+ } catch (IOException e) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(e); -+ } -+ } -+ // Paper end - -+ public void writeInt(int i) throws IOException { this.a(i); } // Paper - OBFHELPER - public void a(int i) throws IOException { - this.b.write(i); - } - -+ public void writeShort(short i) throws IOException { this.a(i); } // Paper - OBFHELPER - public void a(short short0) throws IOException { - this.b.writeShort(Short.reverseBytes(short0)); - } -diff --git a/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java b/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java -index 55b379af2e0c8c3513a76a346d381cd3dbcabe40..59769f7ea808b952cd02192c7121c248756998e9 100644 ---- a/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java -+++ b/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java -@@ -16,6 +16,7 @@ import java.util.Random; - import javax.annotation.Nullable; - import net.minecraft.SystemUtils; - import net.minecraft.server.IMinecraftServer; -+import net.minecraft.server.dedicated.DedicatedServer; - import net.minecraft.server.rcon.RemoteStatusReply; - import net.minecraft.server.rcon.StatusChallengeUtils; - import org.apache.logging.log4j.LogManager; -@@ -26,18 +27,18 @@ public class RemoteStatusListener extends RemoteConnectionThread { - private static final Logger LOGGER = LogManager.getLogger(); - private long e; - private final int f; -- private final int g; -- private final int h; -- private final String i; -- private final String j; -+ private final int g; private final int getServerPort() { return this.g; } // Paper - OBFHELPER -+ private final int h; private final int getMaxPlayers() { return this.h; } // Paper - OBFHELPER -+ private final String i; private final String getMotd() { return this.i; } // Paper - OBFHELPER -+ private final String j; private final String getWorldName() { return this.j; } // Paper - OBFHELPER - private DatagramSocket k; - private final byte[] l = new byte[1460]; -- private String m; -+ private String m; public final String getServerHost() { return this.m; } // Paper - OBFHELPER - private String n; - private final Map o; -- private final RemoteStatusReply p; -+ private final RemoteStatusReply p; private final RemoteStatusReply getCachedFullResponse() { return this.p; } // Paper - OBFHELPER - private long q; -- private final IMinecraftServer r; -+ private final IMinecraftServer r; private final IMinecraftServer getServer() { return this.r; } // Paper - OBFHELPER - - private RemoteStatusListener(IMinecraftServer iminecraftserver, int i) { - super("Query Listener"); -@@ -107,6 +108,7 @@ public class RemoteStatusListener extends RemoteConnectionThread { - - remotestatusreply.a((int) 0); - remotestatusreply.a(this.a(datagrampacket.getSocketAddress())); -+ /* Paper start - GS4 Query event - remotestatusreply.a(this.i); - remotestatusreply.a("SMP"); - remotestatusreply.a(this.j); -@@ -114,6 +116,31 @@ public class RemoteStatusListener extends RemoteConnectionThread { - remotestatusreply.a(Integer.toString(this.h)); - remotestatusreply.a((short) this.g); - remotestatusreply.a(this.m); -+ */ -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.BASIC; -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() -+ .motd(this.getMotd()) -+ .map(this.getWorldName()) -+ .currentPlayers(this.getServer().getPlayerCount()) -+ .maxPlayers(this.getMaxPlayers()) -+ .port(this.getServerPort()) -+ .hostname(this.getServerHost()) -+ .gameVersion(this.getServer().getVersion()) -+ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) -+ .build(); -+ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = -+ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, datagrampacket.getAddress(), queryResponse); -+ queryEvent.callEvent(); -+ queryResponse = queryEvent.getResponse(); -+ remotestatusreply.writeString(queryResponse.getMotd()); -+ remotestatusreply.writeString("SMP"); -+ remotestatusreply.writeString(queryResponse.getMap()); -+ remotestatusreply.writeString(Integer.toString(queryResponse.getCurrentPlayers())); -+ remotestatusreply.writeString(Integer.toString(queryResponse.getMaxPlayers())); -+ remotestatusreply.writeShort((short) queryResponse.getPort()); -+ remotestatusreply.writeString(queryResponse.getHostname()); -+ // Paper end - this.a(remotestatusreply.a(), datagrampacket); - RemoteStatusListener.LOGGER.debug("Status [{}]", socketaddress); - } -@@ -150,6 +177,7 @@ public class RemoteStatusListener extends RemoteConnectionThread { - this.p.a("splitnum"); - this.p.a((int) 128); - this.p.a((int) 0); -+ /* Paper start - GS4 Query event - this.p.a("hostname"); - this.p.a(this.i); - this.p.a("gametype"); -@@ -185,6 +213,79 @@ public class RemoteStatusListener extends RemoteConnectionThread { - } - - this.p.a((int) 0); -+ */ -+ // Pack plugins -+ java.util.List plugins = java.util.Collections.emptyList(); -+ org.bukkit.plugin.Plugin[] bukkitPlugins; -+ if (((DedicatedServer) this.getServer()).server.getQueryPlugins() && (bukkitPlugins = org.bukkit.Bukkit.getPluginManager().getPlugins()).length > 0) { -+ plugins = java.util.stream.Stream.of(bukkitPlugins) -+ .map(plugin -> com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation.of(plugin.getName(), plugin.getDescription().getVersion())) -+ .collect(java.util.stream.Collectors.toList()); -+ } -+ -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() -+ .motd(this.getMotd()) -+ .map(this.getWorldName()) -+ .currentPlayers(this.getServer().getPlayerCount()) -+ .maxPlayers(this.getMaxPlayers()) -+ .port(this.getServerPort()) -+ .hostname(this.getServerHost()) -+ .plugins(plugins) -+ .players(this.getServer().getPlayers()) -+ .gameVersion(this.getServer().getVersion()) -+ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) -+ .build(); -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.FULL; -+ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = -+ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, datagrampacket.getAddress(), queryResponse); -+ queryEvent.callEvent(); -+ queryResponse = queryEvent.getResponse(); -+ this.getCachedFullResponse().writeString("hostname"); -+ this.getCachedFullResponse().writeString(queryResponse.getMotd()); -+ this.getCachedFullResponse().writeString("gametype"); -+ this.getCachedFullResponse().writeString("SMP"); -+ this.getCachedFullResponse().writeString("game_id"); -+ this.getCachedFullResponse().writeString("MINECRAFT"); -+ this.getCachedFullResponse().writeString("version"); -+ this.getCachedFullResponse().writeString(queryResponse.getGameVersion()); -+ this.getCachedFullResponse().writeString("plugins"); -+ java.lang.StringBuilder pluginsString = new java.lang.StringBuilder(); -+ pluginsString.append(queryResponse.getServerVersion()); -+ if (!queryResponse.getPlugins().isEmpty()) { -+ pluginsString.append(": "); -+ java.util.Iterator iter = queryResponse.getPlugins().iterator(); -+ while (iter.hasNext()) { -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation info = iter.next(); -+ pluginsString.append(info.getName()); -+ if (info.getVersion() != null) { -+ pluginsString.append(' ').append(info.getVersion().replace(";", ",")); -+ } -+ if (iter.hasNext()) { -+ pluginsString.append(';').append(' '); -+ } -+ } -+ } -+ this.getCachedFullResponse().writeString(pluginsString.toString()); -+ this.getCachedFullResponse().writeString("map"); -+ this.getCachedFullResponse().writeString(queryResponse.getMap()); -+ this.getCachedFullResponse().writeString("numplayers"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getCurrentPlayers())); -+ this.getCachedFullResponse().writeString("maxplayers"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getMaxPlayers())); -+ this.getCachedFullResponse().writeString("hostport"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getPort())); -+ this.getCachedFullResponse().writeString("hostip"); -+ this.getCachedFullResponse().writeString(queryResponse.getHostname()); -+ // The "meaningless data" start, copied from above -+ this.getCachedFullResponse().writeInt(0); -+ this.getCachedFullResponse().writeInt(1); -+ this.getCachedFullResponse().writeString("player_"); -+ this.getCachedFullResponse().writeInt(0); -+ // "Meaningless data" end -+ queryResponse.getPlayers().forEach(this.getCachedFullResponse()::writeStringUnchecked); -+ this.getCachedFullResponse().writeInt(0); -+ // Paper end - return this.p.a(); - } - } diff --git a/Unmapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch b/Unmapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch deleted file mode 100644 index c6d4f6121a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 25 Nov 2020 16:33:27 -0800 -Subject: [PATCH] Added PlayerLoomPatternSelectEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -index 7980930cc712e37a788f894bf2d2ee2b1cfc1196..5e5367710d43fc421806bda31cd611a9cb5869f3 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -@@ -22,6 +22,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerLoomPatternSelectEvent; // Paper - - public class ContainerLoom extends Container { - -@@ -41,7 +42,7 @@ public class ContainerLoom extends Container { - } - // CraftBukkit end - private final ContainerAccess containerAccess; -- private final ContainerProperty d; -+ private final ContainerProperty d; public final ContainerProperty getSelectedBannerPattern() { return this.d; }; // Paper - OBFHELPER - private Runnable e; - private final Slot f; - private final Slot g; -@@ -160,7 +161,22 @@ public class ContainerLoom extends Container { - @Override - public boolean a(EntityHuman entityhuman, int i) { - if (i > 0 && i <= EnumBannerPatternType.R) { -- this.d.set(i); -+ // Paper start -+ int enumBannerPatternTypeOrdinal = i; -+ PlayerLoomPatternSelectEvent event = new PlayerLoomPatternSelectEvent((Player) entityhuman.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.block.banner.PatternType.getByIdentifier(EnumBannerPatternType.values()[i].getIdentifier())); -+ if (!event.callEvent()) { -+ ((Player) entityhuman.getBukkitEntity()).updateInventory(); -+ return false; -+ } -+ for (EnumBannerPatternType nms : EnumBannerPatternType.values()) { -+ if (event.getPatternType().getIdentifier().equals(nms.getIdentifier())) { -+ enumBannerPatternTypeOrdinal = nms.ordinal(); -+ break; -+ } -+ } -+ ((Player) entityhuman.getBukkitEntity()).updateInventory(); -+ this.getSelectedBannerPattern().set(enumBannerPatternTypeOrdinal); -+ // Paper end - this.j(); - return true; - } else { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java b/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java -index 988e52c675dbb5ef368c8dbb5fb6d4229eb30174..9bc27e727d11d4ac9055a0bc02d8a2ef606ff9c4 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java -@@ -33,6 +33,7 @@ public enum EnumBannerPatternType { - this.T = flag; - } - -+ public String getIdentifier() { return this.b(); } // Paper - OBFHELPER - public String b() { - return this.V; - } diff --git a/Unmapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch b/Unmapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch deleted file mode 100644 index d52bdc76ed..0000000000 --- a/Unmapped-Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 22:27:43 -0800 -Subject: [PATCH] Configurable door breaking difficulty - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 23a23e2ea133ce81d3dedc4ffd17435a995497ef..497f32e4e1c82c0403669b612d07098c625288ce 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -5,8 +5,12 @@ import java.util.EnumMap; - import java.util.HashMap; - import java.util.List; - import java.util.Map; -+import java.util.stream.Collectors; - - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; -+import net.minecraft.world.EnumDifficulty; -+import net.minecraft.world.entity.monster.EntityVindicator; -+import net.minecraft.world.entity.monster.EntityZombie; - import org.bukkit.Bukkit; - import org.bukkit.Material; - import org.bukkit.configuration.ConfigurationSection; -@@ -73,6 +77,11 @@ public class PaperWorldConfig { - return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); - } - -+ private > List getEnumList(String path, List def, Class type) { -+ config.addDefault("world-settings.default." + path, def.stream().map(Enum::name).collect(Collectors.toList())); -+ return ((List) (config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)))).stream().map(s -> Enum.valueOf(type, s)).collect(Collectors.toList()); -+ } -+ - public int cactusMaxHeight; - public int reedMaxHeight; - public int bambooMaxHeight; -@@ -735,4 +744,23 @@ public class PaperWorldConfig { - private void disableMobSpawnerSpawnEggTransformation() { - disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); - } -+ -+ public List zombieBreakDoors; -+ public List vindicatorBreakDoors; -+ private void setupEntityBreakingDoors() { -+ zombieBreakDoors = getEnumList( -+ "door-breaking-difficulty.zombie", -+ Arrays.stream(EnumDifficulty.values()) -+ .filter(EntityZombie.getDoorBreakingPredicate()) -+ .collect(Collectors.toList()), -+ EnumDifficulty.class -+ ); -+ vindicatorBreakDoors = getEnumList( -+ "door-breaking-difficulty.vindicator", -+ Arrays.stream(EnumDifficulty.values()) -+ .filter(EntityVindicator.getDoorBreakingPredicate()) -+ .collect(Collectors.toList()), -+ EnumDifficulty.class -+ ); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -index c45dcb56af95f3e87e292b92b697a336461f01bc..f0eda0b83bab8e3a8adbb569b5997402b0e08e9a 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -@@ -48,6 +48,7 @@ import net.minecraft.world.level.WorldAccess; - - public class EntityVindicator extends EntityIllagerAbstract { - -+ public static final Predicate getDoorBreakingPredicate() { return b; } // Paper - OBFHELPER - private static final Predicate b = (enumdifficulty) -> { - return enumdifficulty == EnumDifficulty.NORMAL || enumdifficulty == EnumDifficulty.HARD; - }; -@@ -204,7 +205,7 @@ public class EntityVindicator extends EntityIllagerAbstract { - static class a extends PathfinderGoalBreakDoor { - - public a(EntityInsentient entityinsentient) { -- super(entityinsentient, 6, EntityVindicator.b); -+ super(entityinsentient, 6, com.google.common.base.Predicates.in(entityinsentient.world.paperConfig.vindicatorBreakDoors)); // Paper - this.a(EnumSet.of(PathfinderGoal.Type.MOVE)); - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index fb98609a38d665659076b8949b59eaf084408a17..634416c354184bc6a2348c27c55e9868009ccd28 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -86,6 +86,7 @@ public class EntityZombie extends EntityMonster { - private static final DataWatcherObject d = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); - private static final DataWatcherObject bo = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.b); - public static final DataWatcherObject DROWN_CONVERTING = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); -+ public static final Predicate getDoorBreakingPredicate() { return bq; } // Paper - OBFHELPER - private static final Predicate bq = (enumdifficulty) -> { - return enumdifficulty == EnumDifficulty.HARD; - }; -@@ -98,7 +99,7 @@ public class EntityZombie extends EntityMonster { - - public EntityZombie(EntityTypes entitytypes, World world) { - super(entitytypes, world); -- this.br = new PathfinderGoalBreakDoor(this, EntityZombie.bq); -+ this.br = new PathfinderGoalBreakDoor(this, com.google.common.base.Predicates.in(world.paperConfig.zombieBreakDoors)); // Paper - } - - public EntityZombie(World world) { diff --git a/Unmapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch b/Unmapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch deleted file mode 100644 index 300a04163a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 6 Jan 2021 23:38:43 +0100 -Subject: [PATCH] Empty commands shall not be dispatched - - -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index a13c684e1360169993f323aa4aa91078c5e8b031..978d3b79b5f953e67263598dff09bcb40b6e3f31 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -223,6 +223,7 @@ public class CommandDispatcher { - command = event.getCommand(); - - String[] args = command.split(" "); -+ if (args.length == 0) return 0; // Paper - empty commands shall not be dispatched - - String cmd = args[0]; - if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); diff --git a/Unmapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch b/Unmapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch deleted file mode 100644 index ab1364a6c0..0000000000 --- a/Unmapped-Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Mon, 4 Jan 2021 16:40:27 +1000 -Subject: [PATCH] Implement API to expose exact interaction point - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 31012963815a5c7355753b8cd2749976282ef0d2..87722285690d9d3370610e2a2eb809e0d1f497c9 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -496,7 +496,7 @@ public class PlayerInteractManager { - cancelledBlock = true; - } - -- PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(entityplayer, Action.RIGHT_CLICK_BLOCK, blockposition, movingobjectpositionblock.getDirection(), itemstack, cancelledBlock, enumhand); -+ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(entityplayer, Action.RIGHT_CLICK_BLOCK, blockposition, movingobjectpositionblock.getDirection(), itemstack, cancelledBlock, enumhand, movingobjectpositionblock.getPos()); // Paper - firedInteract = true; - interactResult = event.useItemInHand() == Event.Result.DENY; - interactPosition = blockposition.immutableCopy(); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index a7f8e08dcbc102041891e51cbe9c984d6f43747b..365d186c5a6d985ed08e09112b74f44b7cfad688 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -70,7 +70,9 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; - import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.MovingObjectPositionEntity; -+import net.minecraft.world.phys.Vec3D; - import org.bukkit.Bukkit; -+import org.bukkit.Location; // Paper - import org.bukkit.Material; - import org.bukkit.NamespacedKey; - import org.bukkit.Server; -@@ -487,7 +489,13 @@ public class CraftEventFactory { - return callPlayerInteractEvent(who, action, position, direction, itemstack, false, hand); - } - -+ // Paper start - Add interactionPoint - public static PlayerInteractEvent callPlayerInteractEvent(EntityHuman who, Action action, BlockPosition position, EnumDirection direction, ItemStack itemstack, boolean cancelledBlock, EnumHand hand) { -+ return callPlayerInteractEvent(who, action, position, direction, itemstack, cancelledBlock, hand, null); -+ } -+ -+ public static PlayerInteractEvent callPlayerInteractEvent(EntityHuman who, Action action, BlockPosition position, EnumDirection direction, ItemStack itemstack, boolean cancelledBlock, EnumHand hand, Vec3D hitVec) { -+ // Paper end - Player player = (who == null) ? null : (Player) who.getBukkitEntity(); - CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack); - -@@ -513,7 +521,10 @@ public class CraftEventFactory { - itemInHand = null; - } - -- PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); -+ // Paper start -+ Location interactionPoint = hitVec == null ? null : new Location(craftWorld, hitVec.x, hitVec.y, hitVec.z); -+ PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND), interactionPoint); -+ // Paper end - if (cancelledBlock) { - event.setUseInteractedBlock(Event.Result.DENY); - } diff --git a/Unmapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch b/Unmapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch deleted file mode 100644 index 20a7ee92ef..0000000000 --- a/Unmapped-Spigot-Server-Patches/0643-Remove-stale-POIs.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 9 Jan 2021 14:17:07 +0100 -Subject: [PATCH] Remove stale POIs - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0f0a3b3776c607217a15c5f61d60f6a98f1c7584..ac62e4e6842a474a1284ae7ac8890cc00b55aa64 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -2077,6 +2077,11 @@ public class WorldServer extends World implements GeneratorAccessSeed { - }); - optional1.ifPresent((villageplacetype) -> { - this.getMinecraftServer().execute(() -> { -+ // Paper start -+ if (!optional.isPresent() && this.getPoiStorage().test(blockposition1, com.google.common.base.Predicates.alwaysTrue())) { -+ this.getPoiStorage().remove(blockposition1); -+ } -+ // Paper end - this.y().a(blockposition1, villageplacetype); - PacketDebug.a(this, blockposition1); - }); -@@ -2084,6 +2089,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - -+ public final VillagePlace getPoiStorage() { return this.y(); } // Paper - OBFHELPER - public VillagePlace y() { - return this.getChunkProvider().j(); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -index 04b01cb841dc4f34ded5aaa4ea7a8e6d4b470183..ce165233739c7b92a76031b949f269bd0a11149c 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -@@ -54,6 +54,7 @@ public class VillagePlace extends RegionFileSection { - ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).a(blockposition, villageplacetype); - } - -+ public void remove(BlockPosition blockposition) { this.a(blockposition); } // Paper - OBFHELPER - public void a(BlockPosition blockposition) { - ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).a(blockposition); - } -@@ -138,6 +139,7 @@ public class VillagePlace extends RegionFileSection { - return ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).c(blockposition); - } - -+ public final boolean test(BlockPosition blockposition, Predicate predicate) { return this.a(blockposition, predicate); } // Paper - OBFHELPER - public boolean a(BlockPosition blockposition, Predicate predicate) { - return (Boolean) this.d(SectionPosition.a(blockposition).s()).map((villageplacesection) -> { - return villageplacesection.a(blockposition, predicate); diff --git a/Unmapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch b/Unmapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch deleted file mode 100644 index 06ed0a695a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Mon, 11 Jan 2021 12:43:51 -0800 -Subject: [PATCH] Fix villager boat exploit - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 66fbbc4c91e16a3dfb4bb756972e667121693501..cf457f6b6ee2968f68f4eede30bb703a6a4f990b 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -77,6 +77,7 @@ import net.minecraft.util.MathHelper; - import net.minecraft.world.effect.MobEffect; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.npc.EntityVillagerAbstract; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; -@@ -621,6 +622,15 @@ public abstract class PlayerList { - - for (Iterator iterator = entity.getAllPassengers().iterator(); iterator.hasNext(); entity1.dead = true) { - entity1 = (Entity) iterator.next(); -+ // Paper start -+ if (entity1 instanceof EntityVillagerAbstract) { -+ final EntityVillagerAbstract villager = (EntityVillagerAbstract) entity1; -+ final EntityHuman human = villager.getTrader(); -+ if (human != null) { -+ villager.setTradingPlayer(null); -+ } -+ } -+ // Paper end - worldserver.removeEntity(entity1); - } - diff --git a/Unmapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch b/Unmapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch deleted file mode 100644 index b122f40024..0000000000 --- a/Unmapped-Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Wed, 18 Nov 2020 20:52:25 -0800 -Subject: [PATCH] Entity load/save limit per chunk - -Adds a config option to limit the number of entities saved and loaded -to a chunk. The default values of -1 disable the limit. Although -defaults are only included for certain entites, this allows setting -limits for any entity type. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 497f32e4e1c82c0403669b612d07098c625288ce..d052d53771d868e6fa25d8854fc675a808722c65 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -9,6 +9,7 @@ import java.util.stream.Collectors; - - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; - import net.minecraft.world.EnumDifficulty; -+import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.monster.EntityVindicator; - import net.minecraft.world.entity.monster.EntityZombie; - import org.bukkit.Bukkit; -@@ -763,4 +764,18 @@ public class PaperWorldConfig { - EnumDifficulty.class - ); - } -+ -+ public Map, Integer> entityPerChunkSaveLimits = new HashMap<>(); -+ private void entityPerChunkSaveLimits() { -+ getInt("entity-per-chunk-save-limit.experience_orb", -1); -+ getInt("entity-per-chunk-save-limit.snowball", -1); -+ getInt("entity-per-chunk-save-limit.ender_pearl", -1); -+ getInt("entity-per-chunk-save-limit.arrow", -1); -+ EntityTypes.getEntityNameList().forEach(name -> { -+ final EntityTypes type = EntityTypes.getByName(name.getKey()).orElseThrow(() -> new IllegalStateException("Unknown Entity Type: " + name.toString())); -+ final String path = ".entity-per-chunk-save-limit." + name.getKey(); -+ final int value = config.getInt("world-settings." + worldName + path, config.getInt("world-settings.default" + path, -1)); // get without setting defaults -+ if (value != -1) entityPerChunkSaveLimits.put(type, value); -+ }); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 2e5221bc1b9e260e33f2cef2653dc59d05e2680d..4eaf497d048324a85ce49fc1c6e9559991c20df7 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -539,11 +539,22 @@ public class ChunkRegionLoader { - - chunk.d(false); - -+ // Paper start -+ final Map, Integer> savedEntityCounts = Maps.newHashMap(); - for (int j = 0; j < chunk.getEntitySlices().length; ++j) { - Iterator iterator1 = chunk.getEntitySlices()[j].iterator(); - - while (iterator1.hasNext()) { - Entity entity = (Entity) iterator1.next(); -+ final EntityTypes entityType = entity.getEntityType(); -+ final int saveLimit = worldserver.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); -+ if (saveLimit > -1) { -+ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { -+ continue; -+ } -+ savedEntityCounts.merge(entityType, 1, Integer::sum); -+ } -+ // Paper end - NBTTagCompound nbttagcompound4 = new NBTTagCompound(); - // Paper start - if (asyncsavedata == null && !entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { -@@ -674,10 +685,21 @@ public class ChunkRegionLoader { - NBTTagList nbttaglist = nbttagcompound.getList("Entities", 10); - World world = chunk.getWorld(); - -+ // Paper start -+ final Map, Integer> loadedEntityCounts = Maps.newHashMap(); - for (int i = 0; i < nbttaglist.size(); ++i) { - NBTTagCompound nbttagcompound1 = nbttaglist.getCompound(i); - - EntityTypes.a(nbttagcompound1, world, (entity) -> { -+ final EntityTypes entityType = entity.getEntityType(); -+ final int saveLimit = world.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); -+ if (saveLimit > -1) { -+ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { -+ return null; -+ } -+ loadedEntityCounts.merge(entityType, 1, Integer::sum); -+ } -+ // Paper end - chunk.a(entity); - return entity; - }); diff --git a/Unmapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch b/Unmapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch deleted file mode 100644 index 382d088024..0000000000 --- a/Unmapped-Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Tue, 29 Dec 2020 15:03:03 +0100 -Subject: [PATCH] Add sendOpLevel API - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index cf457f6b6ee2968f68f4eede30bb703a6a4f990b..1358993217e601e3bab6e0a4e8c55d555865a13e 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1138,6 +1138,11 @@ public abstract class PlayerList { - } - - private void a(EntityPlayer entityplayer, int i) { -+ // Paper start - add recalculatePermissions parameter -+ this.sendPlayerOperatorStatus(entityplayer, i, true); -+ } -+ public void sendPlayerOperatorStatus(EntityPlayer entityplayer, int i, boolean recalculatePermissions) { -+ // Paper end - if (entityplayer.playerConnection != null) { - byte b0; - -@@ -1152,8 +1157,10 @@ public abstract class PlayerList { - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, b0)); - } - -+ if (recalculatePermissions) { // Paper - entityplayer.getBukkitEntity().recalculatePermissions(); // CraftBukkit - this.server.getCommandDispatcher().a(entityplayer); -+ } // Paper - } - - // Paper start -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 41987716afa8ec34214868373df97d0e8f8b27c1..e81de526a847c730abf86016354c1dc57780ec8b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2300,6 +2300,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - ? (org.bukkit.entity.Firework) entity.getBukkitEntity() - : null; - } -+ -+ @Override -+ public void sendOpLevel(byte level) { -+ Preconditions.checkArgument(level >= 0 && level <= 4, "Level must be within [0, 4]"); -+ -+ this.getHandle().getMinecraftServer().getPlayerList().sendPlayerOperatorStatus(this.getHandle(), level, false); -+ } - // Paper end - - // Spigot start diff --git a/Unmapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch b/Unmapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch deleted file mode 100644 index 3e68e76756..0000000000 --- a/Unmapped-Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: dfsek -Date: Wed, 16 Sep 2020 01:12:29 -0700 -Subject: [PATCH] Add StructureLocateEvent - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -index b1f2c424ef358f79c7fced88a61560d3ce32a2b6..f2621f61cb372ec436fe81e7a93f1aef7d360f3f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.chunk; - - import com.google.common.collect.Lists; - import com.mojang.serialization.Codec; -+import io.papermc.paper.event.world.StructureLocateEvent; // Paper - Add import due to naming conflict. - import java.util.BitSet; - import java.util.Iterator; - import java.util.List; -@@ -160,6 +161,22 @@ public abstract class ChunkGenerator { - - @Nullable - public BlockPosition findNearestMapFeature(WorldServer worldserver, StructureGenerator structuregenerator, BlockPosition blockposition, int i, boolean flag) { -+ // Paper start -+ org.bukkit.World world = worldserver.getWorld(); -+ org.bukkit.Location originLocation = new org.bukkit.Location(world, blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ StructureLocateEvent event = new StructureLocateEvent(world, originLocation, org.bukkit.StructureType.getStructureTypes().get(structuregenerator.i()), i, flag); -+ if(!event.callEvent()) return null; -+ // If event call set a final location, skip structure finding and just return set result. -+ if(event.getResult() != null) return new BlockPosition(event.getResult().getBlockX(), event.getResult().getBlockY(), event.getResult().getBlockZ()); -+ // Get origin location (re)defined by event call. -+ blockposition = new BlockPosition(event.getOrigin().getBlockX(), event.getOrigin().getBlockY(), event.getOrigin().getBlockZ()); -+ // Get world (re)defined by event call. -+ worldserver = ((org.bukkit.craftbukkit.CraftWorld) event.getOrigin().getWorld()).getHandle(); -+ // Get radius and whether to find unexplored structures (re)defined by event call. -+ i = event.getRadius(); -+ flag = event.shouldFindUnexplored(); -+ structuregenerator = StructureGenerator.a.get(event.getType().getName()); -+ // Paper end - if (!this.b.a(structuregenerator)) { - return null; - } else if (structuregenerator == StructureGenerator.STRONGHOLD) { diff --git a/Unmapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch b/Unmapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch deleted file mode 100644 index b26885d17e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 14 Nov 2020 16:48:37 +0100 -Subject: [PATCH] Collision option for requiring a player participant - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index d052d53771d868e6fa25d8854fc675a808722c65..c293efaa70c67d7a4227d779eac5d3a510a79ee0 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -718,6 +718,18 @@ public class PaperWorldConfig { - } - } - -+ public boolean onlyPlayersCollide = false; -+ public boolean allowVehicleCollisions = true; -+ private void onlyPlayersCollide() { -+ onlyPlayersCollide = getBoolean("only-players-collide", onlyPlayersCollide); -+ allowVehicleCollisions = getBoolean("allow-vehicle-collisions", allowVehicleCollisions); -+ if (onlyPlayersCollide && !allowVehicleCollisions) { -+ log("Collisions will only work if a player is one of the two entities colliding."); -+ } else if (onlyPlayersCollide) { -+ log("Collisions will only work if a player OR a vehicle is one of the two entities colliding."); -+ } -+ } -+ - public int wanderingTraderSpawnMinuteTicks = 1200; - public int wanderingTraderSpawnDayTicks = 24000; - public int wanderingTraderSpawnChanceFailureIncrement = 25; -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index dc0e2a1348062ea79b1ec3a9fdb985d9d3fca790..881db84a1afe2da5d30732c282f36b294c721c41 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1467,6 +1467,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public void collide(Entity entity) { - if (!this.isSameVehicle(entity)) { - if (!entity.noclip && !this.noclip) { -+ if (this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer || this instanceof EntityPlayer)) return; // Paper - double d0 = entity.locX() - this.locX(); - double d1 = entity.locZ() - this.locZ(); - double d2 = MathHelper.a(d0, d1); -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index 2609b83573e0e8532e6c4c36d4f475bf0da6a354..069076d3c7165440217a7632b089ab2aa0fbdb1d 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -14,6 +14,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.tags.Tag; -@@ -230,6 +231,7 @@ public class EntityBoat extends Entity { - - @Override - public void collide(Entity entity) { -+ if (!this.world.paperConfig.allowVehicleCollisions && this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer)) return; // Paper - if (entity instanceof EntityBoat) { - if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 2e3ceab3e34f7756764b3471b13d48d1263ecba9..57821301ef031995e6044a17b46c70a693322455 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -21,6 +21,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; - import net.minecraft.util.MathHelper; -@@ -767,6 +768,7 @@ public abstract class EntityMinecartAbstract extends Entity { - public void collide(Entity entity) { - if (!this.world.isClientSide) { - if (!entity.noclip && !this.noclip) { -+ if (!this.world.paperConfig.allowVehicleCollisions && this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer)) return; // Paper - if (!this.w(entity)) { - // CraftBukkit start - VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); diff --git a/Unmapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/Unmapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch deleted file mode 100644 index 21e396674c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0649-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 16 Jan 2021 14:30:12 -0500 -Subject: [PATCH] Remove ProjectileHitEvent call when fireballs dead - -The duplicate ProjectileHitEvent in EntityFireball was removed. The -event was always called before the duplicate call. - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -index 9660dc2263c48a5818b767843658eeb9ee1748ea..ba3b52691db79c83d4482664b7a9615ab9be2761 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -@@ -87,7 +87,7 @@ public abstract class EntityFireball extends IProjectile { - - // CraftBukkit start - Fire ProjectileHitEvent - if (this.dead) { -- CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); -+ // CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); // Paper - this is an undesired duplicate event - } - // CraftBukkit end - } diff --git a/Unmapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch b/Unmapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch deleted file mode 100644 index 812ef9c07e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CDFN -Date: Tue, 7 Jul 2020 17:53:23 +0200 -Subject: [PATCH] Return chat component with empty text instead of throwing - exception - - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index 9c6330da4e026a7753698b5d103c009730154c3e..bdd00608a72dd81003731ff5fbe774dfdc5220e5 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -11,6 +11,7 @@ import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; - import net.minecraft.core.IRegistry; - import net.minecraft.core.NonNullList; -+import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.util.MathHelper; - import net.minecraft.world.IInventory; -@@ -61,7 +62,12 @@ public abstract class Container { - } - private IChatBaseComponent title; - public final IChatBaseComponent getTitle() { -- Preconditions.checkState(this.title != null, "Title not set"); -+ // Paper start - return chat component with empty text instead of throwing error -+ // Preconditions.checkState(this.title != null, "Title not set"); -+ if(this.title == null){ -+ return new ChatComponentText(""); -+ } -+ // Paper end - return this.title; - } - public final void setTitle(IChatBaseComponent title) { diff --git a/Unmapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch b/Unmapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch deleted file mode 100644 index 87d12b6191..0000000000 --- a/Unmapped-Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 19:52:44 -0800 -Subject: [PATCH] Make schedule command per-world - - -diff --git a/src/main/java/net/minecraft/server/commands/CommandSchedule.java b/src/main/java/net/minecraft/server/commands/CommandSchedule.java -index b88a91072032b75f83d811d63e1b5e3808faa9be..440b25dde0299037032d535c4c751f252775d6ad 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandSchedule.java -+++ b/src/main/java/net/minecraft/server/commands/CommandSchedule.java -@@ -32,7 +32,7 @@ public class CommandSchedule { - return new ChatMessage("commands.schedule.cleared.failure", new Object[]{object}); - }); - private static final SuggestionProvider c = (commandcontext, suggestionsbuilder) -> { -- return ICompletionProvider.b((Iterable) ((CommandListenerWrapper) commandcontext.getSource()).getServer().getSaveData().H().u().a(), suggestionsbuilder); -+ return ICompletionProvider.b((Iterable) ((CommandListenerWrapper) commandcontext.getSource()).getWorld().worldDataServer.H().u().a(), suggestionsbuilder); // Paper - }; - - public static void a(CommandDispatcher commanddispatcher) { -@@ -55,7 +55,7 @@ public class CommandSchedule { - } else { - long j = commandlistenerwrapper.getWorld().getTime() + (long) i; - MinecraftKey minecraftkey = (MinecraftKey) pair.getFirst(); -- CustomFunctionCallbackTimerQueue customfunctioncallbacktimerqueue = commandlistenerwrapper.getServer().getSaveData().H().u(); -+ CustomFunctionCallbackTimerQueue customfunctioncallbacktimerqueue = commandlistenerwrapper.getWorld().worldDataServer.H().u(); // Paper - - ((Either) pair.getSecond()).ifLeft((customfunction) -> { - String s = minecraftkey.toString(); -@@ -81,7 +81,7 @@ public class CommandSchedule { - } - - private static int a(CommandListenerWrapper commandlistenerwrapper, String s) throws CommandSyntaxException { -- int i = commandlistenerwrapper.getServer().getSaveData().H().u().a(s); -+ int i = commandlistenerwrapper.getWorld().worldDataServer.H().u().a(s); // Paper - - if (i == 0) { - throw CommandSchedule.b.create(s); diff --git a/Unmapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch b/Unmapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch deleted file mode 100644 index 73febd3af8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 21:04:03 -0800 -Subject: [PATCH] Configurable max leash distance - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c293efaa70c67d7a4227d779eac5d3a510a79ee0..af7e93cb64eff1448653b27c2c9aea2d278d3ab7 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -167,6 +167,12 @@ public class PaperWorldConfig { - } - } - -+ public float maxLeashDistance = 10f; -+ private void maxLeashDistance() { -+ maxLeashDistance = getFloat("max-leash-distance", maxLeashDistance); -+ log("Max leash distance: " + maxLeashDistance); -+ } -+ - public boolean disableEndCredits; - private void disableEndCredits() { - disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); -diff --git a/src/main/java/net/minecraft/world/entity/EntityCreature.java b/src/main/java/net/minecraft/world/entity/EntityCreature.java -index bbf0f345bfdd8a3a1f7fe902a42b2b18cdcf07a5..20570580367697e37e6c45147168c3beb6c8d31b 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityCreature.java -+++ b/src/main/java/net/minecraft/world/entity/EntityCreature.java -@@ -47,7 +47,7 @@ public abstract class EntityCreature extends EntityInsentient { - float f = this.g(entity); - - if (this instanceof EntityTameableAnimal && ((EntityTameableAnimal) this).isSitting()) { -- if (f > 10.0F) { -+ if (f > entity.world.paperConfig.maxLeashDistance) { // Paper - this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit - this.unleash(true, true); - } -@@ -56,7 +56,7 @@ public abstract class EntityCreature extends EntityInsentient { - } - - this.x(f); -- if (f > 10.0F) { -+ if (f > entity.world.paperConfig.maxLeashDistance) { // Paper - this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit - this.unleash(true, true); - this.goalSelector.a(PathfinderGoal.Type.MOVE); diff --git a/Unmapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch b/Unmapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch deleted file mode 100644 index f35aec4e6d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Sun, 17 Jan 2021 13:16:09 +1000 -Subject: [PATCH] Implement BlockPreDispenseEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -index 966051ab3e720e5b3f0fb9ab852c8908c5f23f3b..9b92824f1c2797e321ced953d33d2c2fd339374a 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -@@ -88,6 +88,7 @@ public class BlockDispenser extends BlockTileEntity { - IDispenseBehavior idispensebehavior = this.a(itemstack); - - if (idispensebehavior != IDispenseBehavior.NONE) { -+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(worldserver, blockposition, itemstack, i)) return; // Paper - BlockPreDispenseEvent is called here - eventFired = false; // CraftBukkit - reset event status - tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 365d186c5a6d985ed08e09112b74f44b7cfad688..c109bbec67bd683077f0ab7331116a240a475827 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -71,6 +71,7 @@ import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; -+import io.papermc.paper.event.block.BlockPreDispenseEvent; // Paper - import org.bukkit.Bukkit; - import org.bukkit.Location; // Paper - import org.bukkit.Material; -@@ -1814,5 +1815,11 @@ public class CraftEventFactory { - BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); - return event.callEvent(); - } -+ -+ public static boolean handleBlockPreDispenseEvent(WorldServer worldserver, BlockPosition blockposition, ItemStack itemStack, int slot) { -+ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ BlockPreDispenseEvent event = new BlockPreDispenseEvent(block, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), slot); -+ return event.callEvent(); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch b/Unmapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch deleted file mode 100644 index 4d3da07cb2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 20:03:35 -0800 -Subject: [PATCH] Added Vanilla Entity Tags - - -diff --git a/src/main/java/io/papermc/paper/CraftEntityTag.java b/src/main/java/io/papermc/paper/CraftEntityTag.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2ca8e1bade5450a14125b77540792e0b18c3e19b ---- /dev/null -+++ b/src/main/java/io/papermc/paper/CraftEntityTag.java -@@ -0,0 +1,29 @@ -+package io.papermc.paper; -+ -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.tags.Tags; -+import net.minecraft.world.entity.EntityTypes; -+import org.bukkit.craftbukkit.tag.CraftTag; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.entity.EntityType; -+ -+import java.util.Collections; -+import java.util.Set; -+import java.util.stream.Collectors; -+ -+public class CraftEntityTag extends CraftTag, EntityType> { -+ -+ public CraftEntityTag(Tags> registry, MinecraftKey tag) { -+ super(registry, tag); -+ } -+ -+ @Override -+ public boolean isTagged(EntityType item) { -+ return getHandle().isTagged(CraftMagicNumbers.getEntityTypes(item)); -+ } -+ -+ @Override -+ public Set getValues() { -+ return Collections.unmodifiableSet(getHandle().getTagged().stream().map(CraftMagicNumbers::getEntityType).collect(Collectors.toSet())); -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 7277fd5807254020054cdbfb97fbd334e05da832..0f04ba41df95986b71524995738831223080cb88 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2222,6 +2222,11 @@ public final class CraftServer implements Server { - Preconditions.checkArgument(clazz == org.bukkit.Fluid.class, "Fluid namespace must have fluid type"); - - return (org.bukkit.Tag) new CraftFluidTag(console.getTagRegistry().getFluidTags(), key); -+ // Paper start -+ case org.bukkit.Tag.REGISTRY_ENTITIES: -+ Preconditions.checkArgument(clazz == org.bukkit.entity.EntityType.class, "Entity namespace must have entitytype type"); -+ return (org.bukkit.Tag) new io.papermc.paper.CraftEntityTag(console.getTagRegistry().getEntityTags(), key); -+ // Paper end - default: - throw new IllegalArgumentException(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 36ad77a5a3987c1de5d0de7cbcb94cb6fe841d44..848a704fa100c39098a5716bb25b6a9ed85d7a8c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -118,8 +118,17 @@ public final class CraftMagicNumbers implements UnsafeValues { - private static final Map MATERIAL_ITEM = new HashMap<>(); - private static final Map MATERIAL_BLOCK = new HashMap<>(); - private static final Map MATERIAL_FLUID = new HashMap<>(); -+ // Paper start -+ private static final Map> ENTITY_TYPE_ENTITY_TYPES = new HashMap<>(); -+ private static final Map, org.bukkit.entity.EntityType> ENTITY_TYPES_ENTITY_TYPE = new HashMap<>(); - - static { -+ for (org.bukkit.entity.EntityType type : org.bukkit.entity.EntityType.values()) { -+ if (type == org.bukkit.entity.EntityType.UNKNOWN) continue; -+ ENTITY_TYPE_ENTITY_TYPES.put(type, IRegistry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey()))); -+ ENTITY_TYPES_ENTITY_TYPE.put(IRegistry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey())), type); -+ } -+ // Paper end - for (Block block : IRegistry.BLOCK) { - BLOCK_MATERIAL.put(block, Material.getMaterial(IRegistry.BLOCK.getKey(block).getKey().toUpperCase(Locale.ROOT))); - } -@@ -185,6 +194,14 @@ public final class CraftMagicNumbers implements UnsafeValues { - public static MinecraftKey key(Material mat) { - return CraftNamespacedKey.toMinecraft(mat.getKey()); - } -+ // Paper start -+ public static net.minecraft.world.entity.EntityTypes getEntityTypes(org.bukkit.entity.EntityType type) { -+ return ENTITY_TYPE_ENTITY_TYPES.get(type); -+ } -+ public static org.bukkit.entity.EntityType getEntityType(net.minecraft.world.entity.EntityTypes entityTypes) { -+ return ENTITY_TYPES_ENTITY_TYPE.get(entityTypes); -+ } -+ // Paper end - // ======================================================================== - // Paper start - @Override diff --git a/Unmapped-Spigot-Server-Patches/0655-added-Wither-API.patch b/Unmapped-Spigot-Server-Patches/0655-added-Wither-API.patch deleted file mode 100644 index e4d69e8e8e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0655-added-Wither-API.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 5 Jul 2020 15:39:19 -0700 -Subject: [PATCH] added Wither API - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 30290c0208a4725b2eb0e7764465c354e592e4ee..170b085c76e092f6d7b14095c66c84fa9a96a1fc 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -82,6 +82,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - return entityliving.getMonsterType() != EnumMonsterType.UNDEAD && entityliving.ei(); - }; - private static final PathfinderTargetCondition bz = (new PathfinderTargetCondition()).a(20.0D).a(EntityWither.by); -+ // Paper start -+ private boolean canPortal = false; -+ -+ public void setCanTravelThroughPortals(boolean canPortal) { this.canPortal = canPortal; } -+ // Paper end - - public EntityWither(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -580,6 +585,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.datawatcher.set((DataWatcherObject) EntityWither.bo.get(i), j); - } - -+ public final boolean isPowered() { return this.S_(); } // Paper - OBFHELPER - public boolean S_() { - return this.getHealth() <= this.getMaxHealth() / 2.0F; - } -@@ -596,7 +602,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - - @Override - public boolean canPortal() { -- return false; -+ return super.canPortal() && canPortal; // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -index 1d94aeec37dcb9758d88ef25a5cad1333bbfbf6c..adf4ce8afa3a42ea8a184905969e03b6b756830f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -@@ -38,4 +38,31 @@ public class CraftWither extends CraftMonster implements Wither, com.destroystok - public BossBar getBossBar() { - return bossBar; - } -+ -+ // Paper start -+ @Override -+ public boolean isCharged() { -+ return getHandle().isPowered(); -+ } -+ -+ @Override -+ public int getInvulnerableTicks() { -+ return getHandle().getInvul(); -+ } -+ -+ @Override -+ public void setInvulnerableTicks(int ticks) { -+ getHandle().setInvul(ticks); -+ } -+ -+ @Override -+ public boolean canTravelThroughPortals() { -+ return getHandle().canPortal(); -+ } -+ -+ @Override -+ public void setCanTravelThroughPortals(boolean value) { -+ getHandle().setCanTravelThroughPortals(value); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/Unmapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch deleted file mode 100644 index 8300eca18e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 15:14:51 -0600 -Subject: [PATCH] Added firing of PlayerChangeBeaconEffectEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java b/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java -index 7e5a0bad616d9477e01426ab1604184ef3fab1c1..085298a9c3837dfa48dfbbf02d6261db12c79036 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java -@@ -13,6 +13,10 @@ import net.minecraft.world.entity.player.PlayerInventory; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - // CraftBukkit end - -+// Paper start -+import io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent; -+// Paper end -+ - public class ContainerBeacon extends Container { - - private final IInventory beacon; -@@ -139,9 +143,15 @@ public class ContainerBeacon extends Container { - - public void c(int i, int j) { - if (this.d.hasItem()) { -- this.containerProperties.setProperty(1, i); -- this.containerProperties.setProperty(2, j); -+ // Paper start -+ PlayerChangeBeaconEffectEvent event = new PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), org.bukkit.potion.PotionEffectType.getById(i), org.bukkit.potion.PotionEffectType.getById(j), this.containerAccess.getLocation().getBlock()); -+ if (event.callEvent()) { -+ this.containerProperties.setProperty(1, event.getPrimary() == null ? 0 : event.getPrimary().getId()); -+ this.containerProperties.setProperty(2, event.getSecondary() == null ? 0 : event.getSecondary().getId()); -+ if (!event.willConsumeItem()) return; - this.d.a(1); -+ } -+ // Paper end - } - - } diff --git a/Unmapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch b/Unmapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch deleted file mode 100644 index d05dbe7aff..0000000000 --- a/Unmapped-Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Thu, 19 Nov 2020 02:07:10 +0000 -Subject: [PATCH] Fix console spam when removing chests in water - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java -index b2c29cff5883868cb56a4e376ab946ac929abc94..a45ee959f41e7f349ff2c309f21fa44ec671cb87 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockChest.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java -@@ -239,7 +239,7 @@ public class BlockChest extends BlockChestAbstract implements I - @Override - public void remove(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - if (!iblockdata.a(iblockdata1.getBlock())) { -- TileEntity tileentity = world.getTileEntity(blockposition); -+ TileEntity tileentity = world.getTileEntity(blockposition, false); // Paper - Don't validate TE - Fix console spam when removing chests in water - - if (tileentity instanceof IInventory) { - InventoryUtils.dropInventory(world, blockposition, (IInventory) tileentity); diff --git a/Unmapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch b/Unmapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch deleted file mode 100644 index 8f200eeb9d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 26 Nov 2020 11:47:24 +0000 -Subject: [PATCH] Add toggle for always placing the dragon egg - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index af7e93cb64eff1448653b27c2c9aea2d278d3ab7..cfe617e1a08b9c6e6c12bfe89bc9effd819eaff1 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -796,4 +796,9 @@ public class PaperWorldConfig { - if (value != -1) entityPerChunkSaveLimits.put(type, value); - }); - } -+ -+ public boolean enderDragonsDeathAlwaysPlacesDragonEgg = false; -+ private void enderDragonsDeathAlwaysPlacesDragonEgg() { -+ enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index c0a6b340810b8ea4f454290b1ac22316ff0e6e22..80fcceec519ef59d057d27a81fcd0649a20447da 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -400,7 +400,7 @@ public class EnderDragonBattle { - this.bossBattle.setVisible(false); - this.generateExitPortal(true); - this.n(); -- if (!this.previouslyKilled) { -+ if (this.world.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg - this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); - } - diff --git a/Unmapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch b/Unmapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch deleted file mode 100644 index 6444ee5cbe..0000000000 --- a/Unmapped-Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 27 Nov 2020 17:14:27 -0800 -Subject: [PATCH] Added PlayerStonecutterRecipeSelectEvent - -Co-Authored-By: MiniDigger - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index bdd00608a72dd81003731ff5fbe774dfdc5220e5..b58ec4abff2840556eb06e08b241a2eaa85c2c7f 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -118,7 +118,7 @@ public abstract class Container { - return slot; - } - -- protected ContainerProperty a(ContainerProperty containerproperty) { -+ protected ContainerProperty addDataSlot(ContainerProperty containerproperty) { return a(containerproperty); } protected ContainerProperty a(ContainerProperty containerproperty) { // Paper - OBFHELPER - this.d.add(containerproperty); - return containerproperty; - } -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerProperty.java b/src/main/java/net/minecraft/world/inventory/ContainerProperty.java -index 67c3b7ddb0b0f10c82577cbea7506c9d80d41368..b9c82e68a811c2ef6bf2d5ce3ae9f858bcb263d5 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerProperty.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerProperty.java -@@ -20,7 +20,7 @@ public abstract class ContainerProperty { - }; - } - -- public static ContainerProperty a(final int[] aint, final int i) { -+ public static ContainerProperty shared(final int[] aint, final int i) { return a(aint, i); } public static ContainerProperty a(final int[] aint, final int i) { // Paper - OBFHELPER - return new ContainerProperty() { - @Override - public int get() { -@@ -54,7 +54,7 @@ public abstract class ContainerProperty { - - public abstract void set(int i); - -- public boolean c() { -+ public boolean checkAndClearUpdateFlag() { return c(); } public boolean c() { // Paper - OBFHELPER - int i = this.get(); - boolean flag = i != this.a; - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -index 1589d9ca201d386d11d9fd57fa8ba6848bae215c..dc667dd5d8514ae4c8a2087cb913f44320ebfc48 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -@@ -22,13 +22,14 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent; // Paper - - public class ContainerStonecutter extends Container { - - private final ContainerAccess containerAccess; - private final ContainerProperty containerProperty; - private final World world; -- private List i; -+ private List i; public final List getRecipes() { return this.i; } // Paper - OBFHELPER - private ItemStack j; - private long k; - final Slot c; -@@ -58,7 +59,7 @@ public class ContainerStonecutter extends Container { - - public ContainerStonecutter(int i, PlayerInventory playerinventory, final ContainerAccess containeraccess) { - super(Containers.STONECUTTER, i); -- this.containerProperty = ContainerProperty.a(); -+ this.containerProperty = addDataSlot(ContainerProperty.shared(new int[1], 0)); // Paper - allow replication - this.i = Lists.newArrayList(); - this.j = ItemStack.b; - this.l = () -> { -@@ -136,13 +137,36 @@ public class ContainerStonecutter extends Container { - @Override - public boolean a(EntityHuman entityhuman, int i) { - if (this.d(i)) { -- this.containerProperty.set(i); -+ // Paper start -+ int recipeIndex = i; -+ this.containerProperty.set(recipeIndex); -+ this.containerProperty.checkAndClearUpdateFlag(); // mark as changed -+ if (this.isValidRecipeIndex(i)) { -+ PlayerStonecutterRecipeSelectEvent event = new PlayerStonecutterRecipeSelectEvent((Player) entityhuman.getBukkitEntity(), (org.bukkit.inventory.StonecutterInventory) getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) this.getRecipes().get(i).toBukkitRecipe()); -+ if (!event.callEvent()) { -+ ((Player) entityhuman.getBukkitEntity()).updateInventory(); -+ return false; -+ } -+ int newRecipeIndex; -+ if (!this.getRecipes().get(recipeIndex).getKey().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { // If the recipe did NOT stay the same -+ for (newRecipeIndex = 0; newRecipeIndex < this.getRecipes().size(); newRecipeIndex++) { -+ if (this.getRecipes().get(newRecipeIndex).getKey().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { -+ recipeIndex = newRecipeIndex; -+ break; -+ } -+ } -+ } -+ } -+ ((Player) entityhuman.getBukkitEntity()).updateInventory(); -+ this.containerProperty.set(recipeIndex); // set new index, so that listeners can read it -+ // Paper end - this.i(); - } - - return true; - } - -+ private boolean isValidRecipeIndex(int index) { return this.d(index); } // Paper - OBFHELPER - private boolean d(int i) { - return i >= 0 && i < this.i.size(); - } diff --git a/Unmapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/Unmapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch deleted file mode 100644 index 5677ee280f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch +++ /dev/null @@ -1,156 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Fri, 29 Jan 2021 15:13:11 +0100 -Subject: [PATCH] Add dropLeash variable to EntityUnleashEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityCreature.java b/src/main/java/net/minecraft/world/entity/EntityCreature.java -index 20570580367697e37e6c45147168c3beb6c8d31b..831414980d40f4382cf7370db28dd8fae534384b 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityCreature.java -+++ b/src/main/java/net/minecraft/world/entity/EntityCreature.java -@@ -48,8 +48,11 @@ public abstract class EntityCreature extends EntityInsentient { - - if (this instanceof EntityTameableAnimal && ((EntityTameableAnimal) this).isSitting()) { - if (f > entity.world.paperConfig.maxLeashDistance) { // Paper -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit -- this.unleash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - } - - return; -@@ -57,8 +60,11 @@ public abstract class EntityCreature extends EntityInsentient { - - this.x(f); - if (f > entity.world.paperConfig.maxLeashDistance) { // Paper -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit -- this.unleash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - this.goalSelector.a(PathfinderGoal.Type.MOVE); - } else if (f > 6.0F) { - double d0 = (entity.locX() - this.locX()) / (double) f; -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 969e5fa3080a98850f03ba64c5662c32a8d501a6..5c7fafeb7fab584eded30ebe415584132f4ab8af 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -88,6 +88,7 @@ import org.bukkit.event.entity.EntityTargetEvent; - import org.bukkit.event.entity.EntityTransformEvent; - import org.bukkit.event.entity.EntityUnleashEvent; - import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; -+import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper - // CraftBukkit end - - public abstract class EntityInsentient extends EntityLiving { -@@ -1207,12 +1208,15 @@ public abstract class EntityInsentient extends EntityLiving { - return EnumInteractionResult.PASS; - } else if (this.getLeashHolder() == entityhuman) { - // CraftBukkit start - fire PlayerUnleashEntityEvent -- if (CraftEventFactory.callPlayerUnleashEntityEvent(this, entityhuman).isCancelled()) { -+ // Paper start - drop leash variable -+ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, entityhuman, !entityhuman.abilities.canInstantlyBuild); -+ if (event.isCancelled()) { -+ // Paper end - ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutAttachEntity(this, this.getLeashHolder())); - return EnumInteractionResult.PASS; - } - // CraftBukkit end -- this.unleash(true, !entityhuman.abilities.canInstantlyBuild); -+ this.unleash(true, event.isDropLeash()); // Paper - drop leash variable - return EnumInteractionResult.a(this.world.isClientSide); - } else { - EnumInteractionResult enuminteractionresult = this.c(entityhuman, enumhand); -@@ -1366,8 +1370,11 @@ public abstract class EntityInsentient extends EntityLiving { - - if (this.leashHolder != null) { - if (!this.isAlive() || !this.leashHolder.isAlive()) { -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit -- this.unleash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE, true); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - } - - } -@@ -1435,8 +1442,11 @@ public abstract class EntityInsentient extends EntityLiving { - boolean flag1 = super.a(entity, flag); - - if (flag1 && this.isLeashed()) { -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit -- this.unleash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, true); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - } - - return flag1; -@@ -1638,7 +1648,10 @@ public abstract class EntityInsentient extends EntityLiving { - @Override - protected void bN() { - super.bN(); -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit -- this.unleash(true, false); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, false); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java b/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java -index 8f6d2a6a388021f437ac5554e9ece8eca89e1f46..519f0cabadcf97a44a112fd963a8d3ab194650c4 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java -@@ -30,6 +30,8 @@ import net.minecraft.server.level.WorldServer; - import org.bukkit.craftbukkit.event.CraftEventFactory; - // CraftBukkit end - -+import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper -+ - public class EntityLeash extends EntityHanging { - - public EntityLeash(EntityTypes entitytypes, World world) { -@@ -125,11 +127,14 @@ public class EntityLeash extends EntityHanging { - entityinsentient = (EntityInsentient) iterator.next(); - if (entityinsentient.isLeashed() && entityinsentient.getLeashHolder() == this) { - // CraftBukkit start -- if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, entityhuman).isCancelled()) { -+ // Paper start - drop leash variable -+ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, entityhuman, !entityhuman.abilities.canInstantlyBuild); -+ if (event.isCancelled()) { -+ // Paper end - die = false; - continue; - } -- entityinsentient.unleash(true, !entityhuman.abilities.canInstantlyBuild); // false -> survival mode boolean -+ entityinsentient.unleash(true, event.isDropLeash()); // false -> survival mode boolean // Paper - drop leash variable - // CraftBukkit end - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index c109bbec67bd683077f0ab7331116a240a475827..e45a635b9d0948c71d5d3fcb317d2c8a228148ea 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1472,8 +1472,10 @@ public class CraftEventFactory { - return itemInHand; - } - -- public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(EntityInsentient entity, EntityHuman player) { -- PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity()); -+ // Paper start - drop leash variable -+ public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(EntityInsentient entity, EntityHuman player, boolean dropLeash) { -+ PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), dropLeash); -+ // Paper end - entity.world.getServer().getPluginManager().callEvent(event); - return event; - } diff --git a/Unmapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch b/Unmapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch deleted file mode 100644 index 091e48b00a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Beech Horn -Date: Fri, 14 Feb 2020 19:39:59 +0000 -Subject: [PATCH] Skip distance map update when spawning disabled. - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 6770307d69c6b3934bfa804fd713cade22f0fb5c..4a71f9a8a57ed123b31c725a8bd5f94ab0e2174d 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -825,7 +825,7 @@ public class ChunkProviderServer extends IChunkProvider { - int l = this.chunkMapDistance.b(); - // Paper start - per player mob spawning - SpawnerCreature.d spawnercreature_d; // moved down -- if (this.playerChunkMap.playerMobDistanceMap != null) { -+ if ((this.allowAnimals || this.allowMonsters) && this.playerChunkMap.playerMobDistanceMap != null) { // don't update when animals and monsters are disabled - // update distance map - this.world.timings.playerMobDistanceMapUpdate.startTiming(); - this.playerChunkMap.playerMobDistanceMap.update(this.world.players, this.playerChunkMap.viewDistance); diff --git a/Unmapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch b/Unmapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch deleted file mode 100644 index 93084291cf..0000000000 --- a/Unmapped-Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yive -Date: Sun, 24 Jan 2021 08:55:19 -0800 -Subject: [PATCH] Reset shield blocking on dimension change - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index c0446ed3c7cc24fae2880dfba71228f5edee66d6..3f44d5b8e3bc4f897a5dda473532004078fe0ebe 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1118,6 +1118,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.world.getServer().getPluginManager().callEvent(changeEvent); - // CraftBukkit end - } -+ // Paper start -+ if (this.isBlocking()) { -+ this.clearActiveItem(); -+ } -+ // Paper end - - return this; - } diff --git a/Unmapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch b/Unmapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch deleted file mode 100644 index 609439176d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Mon, 25 Jan 2021 14:53:57 +0100 -Subject: [PATCH] add DragonEggFormEvent - - -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index 80fcceec519ef59d057d27a81fcd0649a20447da..0ab6319aa3e4e1f5679f37be36999ca56ca2484c 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -57,6 +57,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.WorldGenFeature - import net.minecraft.world.phys.AxisAlignedBB; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.event.block.DragonEggFormEvent; // Paper - DragonEggFormEvent - - public class EnderDragonBattle { - -@@ -400,9 +401,24 @@ public class EnderDragonBattle { - this.bossBattle.setVisible(false); - this.generateExitPortal(true); - this.n(); -+ // Paper start - DragonEggFormEvent -+ BlockPosition eggPosition = this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.getPosition()); -+ org.bukkit.craftbukkit.block.CraftBlock eggBlock = org.bukkit.craftbukkit.block.CraftBlock.at(this.world, eggPosition); -+ org.bukkit.craftbukkit.block.CraftBlockState eggState = new org.bukkit.craftbukkit.block.CraftBlockState(eggBlock); -+ eggState.setData(Blocks.DRAGON_EGG.getBlockData()); -+ DragonEggFormEvent eggEvent = new DragonEggFormEvent(eggBlock, eggState, -+ new org.bukkit.craftbukkit.boss.CraftDragonBattle(this)); -+ // Paper end - DragonEggFormEvent - if (this.world.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg -- this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); -+ // Paper start - DragonEggFormEvent -+ //this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); -+ } else { -+ eggEvent.setCancelled(true); -+ } -+ if (eggEvent.callEvent()) { -+ eggEvent.getNewState().update(true); - } -+ // Paper end - DragonEggFormEvent - - this.previouslyKilled = true; - this.dragonKilled = true; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java -index 18395a3b4a7df1c99e952b9c8e738f165648eba5..851b8c2a86d7155278b49c44c6db8b1cbd2065f2 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java -@@ -14,7 +14,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.WorldGenFeature - - public class WorldGenEndTrophy extends WorldGenerator { - -- public static final BlockPosition a = BlockPosition.ZERO; -+ public static final BlockPosition a = BlockPosition.ZERO; public static BlockPosition getPosition() { return a; } // Paper - OBFHELPER - private final boolean ab; - - public WorldGenEndTrophy(boolean flag) { -@@ -22,7 +22,7 @@ public class WorldGenEndTrophy extends WorldGenerator -Date: Tue, 11 Feb 2020 21:56:48 -0600 -Subject: [PATCH] EntityMoveEvent - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index fe02a46df9c652acf4a4bc0ed194522f400cda34..454bc4c7b2e54a75dd0510263165e41cf26b1751 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -13,6 +13,7 @@ import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; - import io.papermc.paper.adventure.PaperAdventure; // Paper -+import io.papermc.paper.event.entity.EntityMoveEvent; - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -1460,6 +1461,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper -+ worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - - this.methodProfiler.a(() -> { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index ac62e4e6842a474a1284ae7ac8890cc00b55aa64..9720f60d6a58df5f5a9b2c92e2209537aab7f010 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -213,6 +213,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final Convertable.ConversionSession convertable; - public final UUID uuid; - public boolean hasPhysicsEvent = true; // Paper -+ public boolean hasEntityMoveEvent = false; // Paper - private static Throwable getAddToWorldStackTrace(Entity entity) { - return new Throwable(entity + " Added to world at " + new java.util.Date()); - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index b1adb0ddfeb94de6f92f40a7e9e586e00455160d..78d874c44cf8311af06b085db12fbe0cacd6cf7d 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -10,6 +10,7 @@ import com.mojang.datafixers.util.Pair; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import com.mojang.serialization.DynamicOps; -+import io.papermc.paper.event.entity.EntityMoveEvent; - import java.util.Collection; - import java.util.ConcurrentModificationException; - import java.util.Iterator; -@@ -2912,6 +2913,20 @@ public abstract class EntityLiving extends Entity { - - this.collideNearby(); - this.world.getMethodProfiler().exit(); -+ // Paper start -+ if (((WorldServer) world).hasEntityMoveEvent) { -+ if (lastX != locX() || lastY != locY() || lastZ != locZ() || lastYaw != yaw || lastPitch != pitch) { -+ Location from = new Location(world.getWorld(), lastX, lastY, lastZ, lastYaw, lastPitch); -+ Location to = new Location (world.getWorld(), locX(), locY(), locZ(), yaw, pitch); -+ EntityMoveEvent event = new EntityMoveEvent(getBukkitLivingEntity(), from, to.clone()); -+ if (!event.callEvent()) { -+ setLocation(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); -+ } else if (!to.equals(event.getTo())) { -+ setLocation(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); -+ } -+ } -+ } -+ // Paper end - if (!this.world.isClientSide && this.dO() && this.aG()) { - this.damageEntity(DamageSource.DROWN, 1.0F); - } diff --git a/Unmapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch b/Unmapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch deleted file mode 100644 index 972a1dc051..0000000000 --- a/Unmapped-Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas81298 -Date: Mon, 25 Jan 2021 14:37:57 +0100 -Subject: [PATCH] added option to disable pathfinding updates on block changes - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index cfe617e1a08b9c6e6c12bfe89bc9effd819eaff1..f1d384d2e235c52a00f4b6d5643ef3c1d163e94b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -801,4 +801,9 @@ public class PaperWorldConfig { - private void enderDragonsDeathAlwaysPlacesDragonEgg() { - enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); - } -+ -+ public boolean updatePathfindingOnBlockUpdate = true; -+ private void setUpdatePathfindingOnBlockUpdate() { -+ updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 9720f60d6a58df5f5a9b2c92e2209537aab7f010..fd204ab68d8245503c0a8c4e7ce1a0a6bac7d138 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1684,6 +1684,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - @Override - public void notify(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1, int i) { - this.getChunkProvider().flagDirty(blockposition); -+ if(this.paperConfig.updatePathfindingOnBlockUpdate) { // Paper - option to disable pathfinding updates - VoxelShape voxelshape = iblockdata.getCollisionShape(this, blockposition); - VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition); - -@@ -1712,6 +1713,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - this.tickingEntities = wasTicking; // Paper - } -+ } // Paper - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch b/Unmapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch deleted file mode 100644 index e044ac5972..0000000000 --- a/Unmapped-Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Mon, 18 Jan 2021 20:45:25 -0500 -Subject: [PATCH] Inline shift direction fields - -Removes a layer of indirection for EnumDirection.getAdjacent(X|Y|Z)(), which is in the -critical section for much of the server, including the lighting engine. - -diff --git a/src/main/java/net/minecraft/core/EnumDirection.java b/src/main/java/net/minecraft/core/EnumDirection.java -index a699005582293326076eaa80655c5343e6c22ff0..703bdefeb615ef8d15b428a893b5e4939d726f13 100644 ---- a/src/main/java/net/minecraft/core/EnumDirection.java -+++ b/src/main/java/net/minecraft/core/EnumDirection.java -@@ -53,6 +53,11 @@ public enum EnumDirection implements INamable { - }, (enumdirection, enumdirection1) -> { - throw new IllegalArgumentException("Duplicate keys"); - }, Long2ObjectOpenHashMap::new)); -+ // Paper start -+ private final int adjX; -+ private final int adjY; -+ private final int adjZ; -+ // Paper end - - private EnumDirection(int i, int j, int k, String s, EnumDirection.EnumAxisDirection enumdirection_enumaxisdirection, EnumDirection.EnumAxis enumdirection_enumaxis, BaseBlockPosition baseblockposition) { - this.g = i; -@@ -62,6 +67,11 @@ public enum EnumDirection implements INamable { - this.k = enumdirection_enumaxis; - this.l = enumdirection_enumaxisdirection; - this.m = baseblockposition; -+ // Paper start -+ this.adjX = baseblockposition.getX(); -+ this.adjY = baseblockposition.getY(); -+ this.adjZ = baseblockposition.getZ(); -+ // Paper end - } - - public static EnumDirection[] a(Entity entity) { -@@ -137,15 +147,15 @@ public enum EnumDirection implements INamable { - } - - public int getAdjacentX() { -- return this.m.getX(); -+ return this.adjX; // Paper - } - - public int getAdjacentY() { -- return this.m.getY(); -+ return this.adjY; // Paper - } - - public int getAdjacentZ() { -- return this.m.getZ(); -+ return this.adjZ; // Paper - } - - public String m() { diff --git a/Unmapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch b/Unmapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch deleted file mode 100644 index dda47780e0..0000000000 --- a/Unmapped-Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Wed, 20 Jan 2021 14:23:37 -0600 -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 e45a635b9d0948c71d5d3fcb317d2c8a228148ea..a678277416cd71e01cd6980bcfaf9a9803e7ea17 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -401,13 +401,30 @@ public class CraftEventFactory { - } - - public static void handleBlockDropItemEvent(Block block, BlockState state, EntityPlayer player, List items) { -- BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), Lists.transform(items, (item) -> (org.bukkit.entity.Item) item.getBukkitEntity())); -+ // Paper start -+ List list = new ArrayList<>(); -+ for (EntityItem item : items) { -+ list.add((Item) item.getBukkitEntity()); -+ } -+ BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), list); -+ // Paper end - Bukkit.getPluginManager().callEvent(event); - - if (!event.isCancelled()) { -- for (EntityItem item : items) { -- item.world.addEntity(item); -+ // Paper start -+ for (Item bukkit : list) { -+ if (!bukkit.isValid()) { -+ Entity item = ((org.bukkit.craftbukkit.entity.CraftItem) bukkit).getHandle(); -+ item.world.addEntity(item); -+ } -+ } -+ } else { -+ for (Item bukkit : list) { -+ if (bukkit.isValid()) { -+ bukkit.remove(); -+ } - } -+ // Paper end - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/Unmapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch deleted file mode 100644 index f2acd9e212..0000000000 --- a/Unmapped-Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aleksander Jagiello -Date: Sun, 24 Jan 2021 22:17:54 +0100 -Subject: [PATCH] Add getMainThreadExecutor to BukkitScheduler - - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 13e461ffb2ee2e7d0440c0f60809ea99629b843c..0be39dac4b9dd69d7d73d86d64cf1e33e4086e81 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -635,4 +635,15 @@ public class CraftScheduler implements BukkitScheduler { - public BukkitTask runTaskTimerAsynchronously(Plugin plugin, BukkitRunnable task, long delay, long period) throws IllegalArgumentException { - throw new UnsupportedOperationException("Use BukkitRunnable#runTaskTimerAsynchronously(Plugin, long, long)"); - } -+ -+ // Paper start - add getMainThreadExecutor -+ @Override -+ public Executor getMainThreadExecutor(Plugin plugin) { -+ Validate.notNull(plugin, "Plugin cannot be null"); -+ return command -> { -+ Validate.notNull(command, "Command cannot be null"); -+ this.runTask(plugin, command); -+ }; -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch b/Unmapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch deleted file mode 100644 index d30fda385f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Sat, 24 Oct 2020 16:37:44 +0200 -Subject: [PATCH] living entity allow attribute registration - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java -index 8f6b78c68da555f96033df567da581af52195e6c..e4cd1848e8700de4ab64f3037bb0c41d99e7c97d 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java -+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java -@@ -21,7 +21,7 @@ import org.apache.logging.log4j.Logger; - public class AttributeMapBase { - - private static final Logger LOGGER = LogManager.getLogger(); -- private final Map b = Maps.newHashMap(); -+ private final Map b = Maps.newHashMap(); private final Map attributeMap = b; // Paper - OBFHELPER - private final Set c = Sets.newHashSet(); - private final AttributeProvider d; - -@@ -135,4 +135,12 @@ public class AttributeMapBase { - } - - } -+ -+ // Paper - start -+ public void registerAttribute(AttributeBase attributeBase) { -+ AttributeModifiable attributeModifiable = new AttributeModifiable(attributeBase, AttributeModifiable::getAttribute); -+ attributeMap.put(attributeBase, attributeModifiable); -+ } -+ // Paper - end -+ - } -diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -index 673948947bd918c1dbb6c4c99486b4200e3c09fe..2e83b8855070077e90e5ab2c4beae819c620e480 100644 ---- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -@@ -40,6 +40,14 @@ public class CraftAttributeMap implements Attributable { - return (nms == null) ? null : new CraftAttributeInstance(nms, attribute); - } - -+ // Paper start -+ @Override -+ public void registerAttribute(Attribute attribute) { -+ Preconditions.checkArgument(attribute != null, "attribute"); -+ handle.registerAttribute(CraftAttributeMap.toMinecraft(attribute)); -+ } -+ // Paper end -+ - public static AttributeBase toMinecraft(Attribute attribute) { - return IRegistry.ATTRIBUTE.get(CraftNamespacedKey.toMinecraft(attribute.getKey())); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 278a1c886f15b75e62bfe4c872fc779eda83c988..9865eee8ec5e43f291968bfb2c4473260e5baf7c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -675,6 +675,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().craftAttributes.getAttribute(attribute); - } - -+ // Paper start -+ @Override -+ public void registerAttribute(Attribute attribute) { -+ getHandle().craftAttributes.registerAttribute(attribute); -+ } -+ // Paper end -+ - @Override - public void setAI(boolean ai) { - if (this.getHandle() instanceof EntityInsentient) { diff --git a/Unmapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch b/Unmapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch deleted file mode 100644 index 33f5d17581..0000000000 --- a/Unmapped-Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Fri, 5 Feb 2021 22:12:13 +0100 -Subject: [PATCH] fix dead slime setSize invincibility - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -index cf5c6030105e56813f526e710e5db0c59d88c99e..13ab1a430f9ad2ece73ab50455bfcddbc9b236e2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -@@ -18,7 +18,7 @@ public class CraftSlime extends CraftMob implements Slime { - - @Override - public void setSize(int size) { -- getHandle().setSize(size, true); -+ getHandle().setSize(size, /* true */ getHandle().isAlive()); // Paper - fix dead slime setSize invincibility - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch b/Unmapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch deleted file mode 100644 index f368eba156..0000000000 --- a/Unmapped-Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Wed, 10 Feb 2021 14:53:36 -0800 -Subject: [PATCH] Merchant#getRecipes should return an immutable list - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -index 00d43e4a77ed03bc9672cbaccad50b48aed0fb93..3c66d9217eb0b60595a59e2f296de332095d4a4c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -@@ -25,7 +25,7 @@ public class CraftMerchant implements Merchant { - - @Override - public List getRecipes() { -- return Collections.unmodifiableList(Lists.transform(merchant.getOffers(), new Function() { -+ return com.google.common.collect.ImmutableList.copyOf(Lists.transform(merchant.getOffers(), new Function() { // Paper - javadoc says 'an immutable list of trades' - not 'an unmodifiable view of a list of trades'. fixes issue with setRecipes(getRecipes()) - @Override - public MerchantRecipe apply(net.minecraft.world.item.trading.MerchantRecipe recipe) { - return recipe.asBukkit(); diff --git a/Unmapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch b/Unmapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch deleted file mode 100644 index da0840fc4c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0672-misc-debugging-dumps.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 18 Feb 2021 20:23:28 +0000 -Subject: [PATCH] misc debugging dumps - - -diff --git a/src/main/java/io/papermc/paper/util/TraceUtil.java b/src/main/java/io/papermc/paper/util/TraceUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2d5494d2813b773e60ddba6790b750a9a08f21f8 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/util/TraceUtil.java -@@ -0,0 +1,18 @@ -+package io.papermc.paper.util; -+ -+import org.bukkit.Bukkit; -+ -+public final class TraceUtil { -+ -+ public static void dumpTraceForThread(Thread thread, String reason) { -+ Bukkit.getLogger().warning(thread.getName() + ": " + reason); -+ StackTraceElement[] trace = thread.getStackTrace(); -+ for (StackTraceElement traceElement : trace) { -+ Bukkit.getLogger().warning("\tat " + traceElement); -+ } -+ } -+ -+ public static void dumpTraceForThread(String reason) { -+ new Throwable(reason).printStackTrace(); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 454bc4c7b2e54a75dd0510263165e41cf26b1751..879074df54e56a9275957a83c92b467094e95cd4 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -14,6 +14,7 @@ import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; - import io.papermc.paper.adventure.PaperAdventure; // Paper - import io.papermc.paper.event.entity.EntityMoveEvent; -+import io.papermc.paper.util.TraceUtil; - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -857,6 +858,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Sat, 20 Feb 2021 13:09:59 -0500 -Subject: [PATCH] Add support for hex color codes in console - -Converts upstream's hex color code legacy format into actual hex color codes in the console. - -diff --git a/src/main/java/io/papermc/paper/console/HexFormattingConverter.java b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a4315961b7a465fb4872a4d67e7c26d4b4ed1fb9 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java -@@ -0,0 +1,178 @@ -+package io.papermc.paper.console; -+ -+import net.minecrell.terminalconsole.TerminalConsoleAppender; -+import org.apache.logging.log4j.core.LogEvent; -+import org.apache.logging.log4j.core.config.Configuration; -+import org.apache.logging.log4j.core.config.plugins.Plugin; -+import org.apache.logging.log4j.core.layout.PatternLayout; -+import org.apache.logging.log4j.core.pattern.*; -+import org.apache.logging.log4j.util.PerformanceSensitive; -+import org.apache.logging.log4j.util.PropertiesUtil; -+ -+import java.util.List; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+import static net.minecrell.terminalconsole.MinecraftFormattingConverter.KEEP_FORMATTING_PROPERTY; -+ -+/** -+ * Modified version of -+ * TerminalConsoleAppender's MinecraftFormattingConverter to support hex color codes using the md_5 &x&r&r&g&g&b&b format. -+ */ -+@Plugin(name = "paperMinecraftFormatting", category = PatternConverter.CATEGORY) -+@ConverterKeys({ "paperMinecraftFormatting" }) -+@PerformanceSensitive("allocation") -+public final class HexFormattingConverter extends LogEventPatternConverter { -+ -+ private static final boolean KEEP_FORMATTING = PropertiesUtil.getProperties().getBooleanProperty(KEEP_FORMATTING_PROPERTY); -+ -+ private static final String ANSI_RESET = "\u001B[m"; -+ -+ private static final char COLOR_CHAR = '§'; -+ private static final String LOOKUP = "0123456789abcdefklmnor"; -+ -+ private static final String RGB_ANSI = "\u001B[38;2;%d;%d;%dm"; -+ private static final Pattern NAMED_PATTERN = Pattern.compile(COLOR_CHAR + "[0-9a-fk-orA-FK-OR]"); -+ private static final Pattern RGB_PATTERN = Pattern.compile(COLOR_CHAR + "x(" + COLOR_CHAR + "[0-9a-fA-F]){6}"); -+ -+ private static final String[] ansiCodes = new String[] { -+ "\u001B[0;30m", // Black §0 -+ "\u001B[0;34m", // Dark Blue §1 -+ "\u001B[0;32m", // Dark Green §2 -+ "\u001B[0;36m", // Dark Aqua §3 -+ "\u001B[0;31m", // Dark Red §4 -+ "\u001B[0;35m", // Dark Purple §5 -+ "\u001B[0;33m", // Gold §6 -+ "\u001B[0;37m", // Gray §7 -+ "\u001B[0;30;1m", // Dark Gray §8 -+ "\u001B[0;34;1m", // Blue §9 -+ "\u001B[0;32;1m", // Green §a -+ "\u001B[0;36;1m", // Aqua §b -+ "\u001B[0;31;1m", // Red §c -+ "\u001B[0;35;1m", // Light Purple §d -+ "\u001B[0;33;1m", // Yellow §e -+ "\u001B[0;37;1m", // White §f -+ "\u001B[5m", // Obfuscated §k -+ "\u001B[21m", // Bold §l -+ "\u001B[9m", // Strikethrough §m -+ "\u001B[4m", // Underline §n -+ "\u001B[3m", // Italic §o -+ ANSI_RESET, // Reset §r -+ }; -+ -+ private final boolean ansi; -+ private final List formatters; -+ -+ /** -+ * Construct the converter. -+ * -+ * @param formatters The pattern formatters to generate the text to manipulate -+ * @param strip If true, the converter will strip all formatting codes -+ */ -+ protected HexFormattingConverter(List formatters, boolean strip) { -+ super("paperMinecraftFormatting", null); -+ this.formatters = formatters; -+ this.ansi = !strip; -+ } -+ -+ @Override -+ public void format(LogEvent event, StringBuilder toAppendTo) { -+ int start = toAppendTo.length(); -+ //noinspection ForLoopReplaceableByForEach -+ for (int i = 0, size = formatters.size(); i < size; i++) { -+ formatters.get(i).format(event, toAppendTo); -+ } -+ -+ if (KEEP_FORMATTING || toAppendTo.length() == start) { -+ // Skip replacement if disabled or if the content is empty -+ return; -+ } -+ -+ boolean useAnsi = ansi && TerminalConsoleAppender.isAnsiSupported(); -+ String content = toAppendTo.substring(start); -+ content = useAnsi ? convertRGBColors(content) : stripRGBColors(content); -+ format(content, toAppendTo, start, useAnsi); -+ } -+ -+ private static String convertRGBColors(String input) { -+ Matcher matcher = RGB_PATTERN.matcher(input); -+ StringBuffer buffer = new StringBuffer(); -+ while (matcher.find()) { -+ String s = matcher.group().replace(String.valueOf(COLOR_CHAR), "").replace('x', '#'); -+ int hex = Integer.decode(s); -+ int red = (hex >> 16) & 0xFF; -+ int green = (hex >> 8) & 0xFF; -+ int blue = hex & 0xFF; -+ String replacement = String.format(RGB_ANSI, red, green, blue); -+ matcher.appendReplacement(buffer, replacement); -+ } -+ matcher.appendTail(buffer); -+ return buffer.toString(); -+ } -+ -+ private static String stripRGBColors(String input) { -+ Matcher matcher = RGB_PATTERN.matcher(input); -+ StringBuffer buffer = new StringBuffer(); -+ while (matcher.find()) { -+ matcher.appendReplacement(buffer, ""); -+ } -+ matcher.appendTail(buffer); -+ return buffer.toString(); -+ } -+ -+ static void format(String content, StringBuilder result, int start, boolean ansi) { -+ int next = content.indexOf(COLOR_CHAR); -+ int last = content.length() - 1; -+ if (next == -1 || next == last) { -+ result.setLength(start); -+ result.append(content); -+ if (ansi) { -+ result.append(ANSI_RESET); -+ } -+ return; -+ } -+ -+ Matcher matcher = NAMED_PATTERN.matcher(content); -+ StringBuffer buffer = new StringBuffer(); -+ while (matcher.find()) { -+ int format = LOOKUP.indexOf(Character.toLowerCase(matcher.group().charAt(1))); -+ if (format != -1) { -+ matcher.appendReplacement(buffer, ansi ? ansiCodes[format] : ""); -+ } -+ } -+ matcher.appendTail(buffer); -+ -+ result.setLength(start); -+ result.append(buffer.toString()); -+ if (ansi) { -+ result.append(ANSI_RESET); -+ } -+ } -+ -+ /** -+ * Gets a new instance of the {@link HexFormattingConverter} with the -+ * specified options. -+ * -+ * @param config The current configuration -+ * @param options The pattern options -+ * @return The new instance -+ * -+ * @see HexFormattingConverter -+ */ -+ public static HexFormattingConverter newInstance(Configuration config, String[] options) { -+ if (options.length < 1 || options.length > 2) { -+ LOGGER.error("Incorrect number of options on paperMinecraftFormatting. Expected at least 1, max 2 received " + options.length); -+ return null; -+ } -+ if (options[0] == null) { -+ LOGGER.error("No pattern supplied on paperMinecraftFormatting"); -+ return null; -+ } -+ -+ PatternParser parser = PatternLayout.createPatternParser(config); -+ List formatters = parser.parse(options[0]); -+ boolean strip = options.length > 1 && "strip".equals(options[1]); -+ return new HexFormattingConverter(formatters, strip); -+ } -+ -+} -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 8af159abd3d0cc94cf155fec5b384c42f69551bf..67da1aa7a21622fb231d19dede3775a282a4a12e 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -6,21 +6,21 @@ - - - -- -+ - - - -+ pattern="%highlightError{[%d{HH:mm:ss} %level]: %paperMinecraftFormatting{%msg}%n%xEx{full}}" /> - - - - - -- -+ - - - -+ pattern="[%d{HH:mm:ss}] [%t/%level]: %paperMinecraftFormatting{%msg}{strip}%n%xEx{full}" /> - - - diff --git a/Unmapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch b/Unmapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch deleted file mode 100644 index 5f1ef784b9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tom -Date: Fri, 26 Feb 2021 16:10:53 -0600 -Subject: [PATCH] Clear SyncLoadInfo - -This patch merely adds the extra argument "clear" after /paper syncloadinfo to clear currently stored syncload info. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 4b3efe01750d79bcc27a42b5a145d9aa6b124d18..12313a37ceeb6a0b6a539c38fdba67e5e43d7413 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -295,6 +295,13 @@ public class PaperCommand extends Command { - sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); - return; - } -+ -+ if (args.length > 1 && args[1].equals("clear")) { -+ SyncLoadFinder.clear(); -+ sender.sendMessage(ChatColor.GRAY + "Sync load data cleared."); -+ return; -+ } -+ - File file = new File(new File(new File("."), "debug"), - "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); - file.getParentFile().mkdirs(); -diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -index d381f91cf105bfc01846ada90da8971a3618e784..c51401bcfac0a1e45099af1dd355073c19790476 100644 ---- a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -+++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -@@ -26,6 +26,10 @@ public class SyncLoadFinder { - public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); - } - -+ public static void clear() { -+ SYNC_LOADS.clear(); -+ } -+ - public static void logSyncLoad(final World world, final int chunkX, final int chunkZ) { - if (!ENABLED) { - return; diff --git a/Unmapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch b/Unmapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch deleted file mode 100644 index 2ee6abd643..0000000000 --- a/Unmapped-Spigot-Server-Patches/0675-Expose-Tracked-Players.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tom -Date: Fri, 26 Feb 2021 16:24:25 -0600 -Subject: [PATCH] Expose Tracked Players - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 881db84a1afe2da5d30732c282f36b294c721c41..d62179765f93738e8444b507238b4fd79a1e9443 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -172,7 +172,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - -- PlayerChunkMap.EntityTracker tracker; // Paper -+ public PlayerChunkMap.EntityTracker tracker; // Paper package private -> public - public boolean collisionLoadChunks = false; // Paper - public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index e81de526a847c730abf86016354c1dc57780ec8b..05248f560d643080a3eac581c01aa89fb3709e6c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -16,6 +16,7 @@ import java.net.InetSocketAddress; - import java.net.SocketAddress; - import java.util.ArrayList; - import java.util.Collection; -+import java.util.Collections; // Paper - import java.util.HashMap; - import java.util.HashSet; - import java.util.LinkedHashMap; -@@ -2309,6 +2310,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - // Paper end - -+ // Paper start -+ @Override -+ public Set getTrackedPlayers() { -+ if (entity.tracker == null) { -+ return Collections.emptySet(); -+ } -+ -+ Set set = new HashSet<>(entity.tracker.trackedPlayers.size()); -+ for (EntityPlayer entityPlayer : entity.tracker.trackedPlayers) { -+ set.add(entityPlayer.getBukkitEntity().getPlayer()); -+ } -+ return set; -+ } -+ // Paper end -+ - // Spigot start - private final Player.Spigot spigot = new Player.Spigot() - { diff --git a/Unmapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch b/Unmapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch deleted file mode 100644 index d5ee1c60ca..0000000000 --- a/Unmapped-Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Bjarne Koll -Date: Wed, 3 Mar 2021 12:48:48 +0100 -Subject: [PATCH] Remove streams from SensorNearest - -The behavioural nearby sensors are validated every tick on the entities -that registered the respective sensors and are therefore a good subject -to performance improvements. - -More specifically this commit replaces the Stream#filter usage with -ArrayList#removeIf as the removeIf method on an array list is heavily -optimized towards a single internal array re-allocation without any -further overhead on the removeIf call. - -The only negative of this change is the rather agressive diff these -patches introduce as the methods are basically being reimplemented -compared to the previous stream-based implementation. - -See: https://nipafx.dev/java-stream-performance/ - -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java -index 418cd6d8b40d35aa3be73eb12f2e3b75597238b9..2e3149a0b15299468079796bd3ea56eabdb4998c 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java -@@ -27,18 +27,16 @@ public class SensorNearestItems extends Sensor { - List list = worldserver.a(EntityItem.class, entityinsentient.getBoundingBox().grow(8.0D, 4.0D, 8.0D), (entityitem) -> { - return true; - }); -- -- entityinsentient.getClass(); -+ // Paper start - remove streams in favour of lists - list.sort(Comparator.comparingDouble(entityinsentient::h)); -- Stream stream = list.stream().filter((entityitem) -> { -- return entityinsentient.i(entityitem.getItemStack()); -- }).filter((entityitem) -> { -- return entityitem.a((Entity) entityinsentient, 9.0D); -- }); -- -- entityinsentient.getClass(); -- Optional optional = stream.filter(entityinsentient::hasLineOfSight).findFirst(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); -+ EntityItem nearest = null; -+ for (EntityItem entityItem : list) { -+ if (entityinsentient.i(entityItem.getItemStack()) && entityItem.a(entityinsentient, 9.0D) && entityinsentient.hasLineOfSight(entityItem)) { -+ nearest = entityItem; -+ break; -+ } -+ } -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java -index d3bb1c02d80fcd3586030b07f84e7ebdd97d873e..0bc17d148e91277efdf72541e5470fa56d455670 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java -@@ -26,10 +26,12 @@ public class SensorNearestLivingEntities extends Sensor { - list.sort(Comparator.comparingDouble(entityliving::h)); - BehaviorController behaviorcontroller = entityliving.getBehaviorController(); - -- behaviorcontroller.setMemory(MemoryModuleType.MOBS, (Object) list); -- behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, list.stream().filter((entityliving1) -> { -- return a(entityliving, entityliving1); -- }).collect(Collectors.toList())); -+ behaviorcontroller.setMemory(MemoryModuleType.MOBS, list); // Paper - decompile error -+ // Paper start - remove streams in favour of lists -+ List visibleMobs = new java.util.ArrayList<>(list); -+ visibleMobs.removeIf(otherEntityLiving -> !Sensor.a(entityliving, otherEntityLiving)); -+ behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, visibleMobs); -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java -index 29abc7feec5358dce7d16958f0c5807f4bda992f..60e4da9217d4d950b5077baf6b50eaee20f8df09 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java -@@ -26,22 +26,26 @@ public class SensorNearestPlayers extends Sensor { - - @Override - protected void a(WorldServer worldserver, EntityLiving entityliving) { -- Stream stream = worldserver.getPlayers().stream().filter(IEntitySelector.g).filter((entityplayer) -> { -- return entityliving.a((Entity) entityplayer, 16.0D); -- }); -+ // Paper start - remove streams in favour of lists -+ List players = new java.util.ArrayList<>(worldserver.getPlayers()); -+ players.removeIf(player -> !IEntitySelector.notSpectator().test(player) || !entityliving.a(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator -+ players.sort(Comparator.comparingDouble(entityliving::h)); - -- entityliving.getClass(); -- List list = (List) stream.sorted(Comparator.comparingDouble(entityliving::h)).collect(Collectors.toList()); - BehaviorController behaviorcontroller = entityliving.getBehaviorController(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, (Object) list); -- List list1 = (List) list.stream().filter((entityhuman) -> { -- return a(entityliving, (EntityLiving) entityhuman); -- }).collect(Collectors.toList()); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, (Object) (list1.isEmpty() ? null : (EntityHuman) list1.get(0))); -- Optional optional = list1.stream().filter(IEntitySelector.f).findFirst(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, optional); -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); -+ -+ EntityHuman nearest = null, nearestTargetable = null; -+ for (EntityHuman player : players) { -+ if (Sensor.a(entityliving, player)) { -+ if (nearest == null) nearest = player; -+ if (IEntitySelector.canAITarget().test(player)) { -+ nearestTargetable = player; -+ break; // Both variables are assigned, no reason to loop further -+ } -+ } -+ } -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, nearestTargetable); -+ // Paper end - } - } diff --git a/Unmapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch b/Unmapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch deleted file mode 100644 index 98382964ad..0000000000 --- a/Unmapped-Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch +++ /dev/null @@ -1,239 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas81298 -Date: Sun, 13 Dec 2020 13:42:55 +0100 -Subject: [PATCH] do not create unnecessary copies of passenger list - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java -index edc6fff87c4abad2c123b1a46d6e5b792602b3be..5e739b26b6b5490b2c7651d3e9ff8649e776137e 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java -@@ -15,7 +15,7 @@ public class PacketPlayOutMount implements Packet { - - public PacketPlayOutMount(Entity entity) { - this.a = entity.getId(); -- List list = entity.getPassengers(); -+ List list = entity.passengers; // Paper - do not create a copy of the list - - this.b = new int[list.size()]; - -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index 58dd349adf2bc9bac6569464ef7a7aec81729e79..1df8fb8cb3fcf8201e1c5fa8ca13f7a9c632c379 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -103,10 +103,10 @@ public class EntityTrackerEntry { - - public final void tick() { this.a(); } // Paper - OBFHELPER - public void a() { -- List list = this.tracker.getPassengers(); -+ List list = this.tracker.passengers; // Paper - do not copy list - - if (!list.equals(this.p)) { -- this.p = list; -+ this.p = com.google.common.collect.ImmutableList.copyOf(list); // Paper - only copy list if something has changed - this.broadcastIncludingSelf(new PacketPlayOutMount(this.tracker)); // CraftBukkit - } - -@@ -376,7 +376,7 @@ public class EntityTrackerEntry { - } - } - -- if (!this.tracker.getPassengers().isEmpty()) { -+ if (!this.tracker.passengers.isEmpty()) { // Paper - do not create copy of list - consumer.accept(new PacketPlayOutMount(this.tracker)); - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 169fa174f86f8a8dc42d3b9c4954a39d0a738c06..6835401bd7863bbd655502547a9fd4ae0f298da1 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -2315,7 +2315,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - list.add(entity); - } - -- if (!entity.getPassengers().isEmpty()) { -+ if (!entity.passengers.isEmpty()) { // Paper - do not copy list - list1.add(entity); - } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d62179765f93738e8444b507238b4fd79a1e9443..89b2be0e9e42d65b7d2d2833de4e6cd1c6e17e8e 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2235,7 +2235,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - protected boolean q(Entity entity) { -- return this.getPassengers().size() < 1; -+ return this.passengers.size() < 1; // Paper - do not copy list - } - - public final float getCollisionBorderSize() { return bg(); } // Paper - OBFHELPER -@@ -2331,7 +2331,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean isVehicle() { -- return !this.getPassengers().isEmpty(); -+ return !this.passengers.isEmpty(); // Paper - do not copy list - } - - public boolean bt() { -@@ -3143,7 +3143,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean w(Entity entity) { -- Iterator iterator = this.getPassengers().iterator(); -+ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list - - Entity entity1; - -@@ -3159,7 +3159,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean a(Class oclass) { -- Iterator iterator = this.getPassengers().iterator(); -+ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list - - Entity entity; - -@@ -3176,7 +3176,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - public Collection getAllPassengers() { - Set set = Sets.newHashSet(); -- Iterator iterator = this.getPassengers().iterator(); -+ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); -@@ -3202,7 +3202,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - private void a(boolean flag, Set set) { - Entity entity; - -- for (Iterator iterator = this.getPassengers().iterator(); iterator.hasNext(); entity.a(flag, set)) { -+ for (Iterator iterator = this.passengers.iterator(); iterator.hasNext(); entity.a(flag, set)) { // Paper - do not copy list - entity = (Entity) iterator.next(); - if (!flag || EntityPlayer.class.isAssignableFrom(entity.getClass())) { - set.add(entity); -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java -index ec51a5532576ce25465bacf61c716ddaffca514e..d285f5aa66fa81a2f56920c05afb4506cb82fa54 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java -@@ -52,7 +52,7 @@ public class PathfinderGoalTame extends PathfinderGoal { - @Override - public void e() { - if (!this.entity.isTamed() && this.entity.getRandom().nextInt(50) == 0) { -- Entity entity = (Entity) this.entity.getPassengers().get(0); -+ Entity entity = this.entity.passengers.isEmpty() ? null : this.entity.passengers.get(0); // Paper - do not copy list, fixed array out of bounds exception as well - - if (entity == null) { - return; -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -index d6e1697f64e60f2a567288c604a1690159955f37..676ca381a5e111fc15f319e73504e4e60dbf0d2b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -@@ -86,7 +86,7 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { - @Nullable - @Override - public Entity getRidingPassenger() { -- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -index d678e3164ecdb7f0c600597bcb39d1054dfbc4b2..1e41c45af6dbcf097d7d6104e63db637f199301a 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -@@ -972,7 +972,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - @Nullable - @Override - public Entity getRidingPassenger() { -- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - } - - @Nullable -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -index 7781386da593a1c4f3ad7e7e8761767dda7cb66c..16d5cae64887b82e67eeb61ccb714e6125ff0c09 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -@@ -134,7 +134,7 @@ public class EntityRavager extends EntityRaider { - @Nullable - @Override - public Entity getRidingPassenger() { -- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index 069076d3c7165440217a7632b089ab2aa0fbdb1d..5e2c13bd6e52ffe182ef034e05ba6fe1cb301005 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -317,7 +317,7 @@ public class EntityBoat extends Entity { - super.tick(); - this.r(); - if (this.cs()) { -- if (this.getPassengers().isEmpty() || !(this.getPassengers().get(0) instanceof EntityHuman)) { -+ if (this.passengers.isEmpty() || !(this.passengers.get(0) instanceof EntityHuman)) { // Paper - do not copy list - this.a(false, false); - } - -@@ -380,7 +380,7 @@ public class EntityBoat extends Entity { - Entity entity = (Entity) list.get(j); - - if (!entity.w(this)) { -- if (flag && this.getPassengers().size() < 2 && !entity.isPassenger() && entity.getWidth() < this.getWidth() && entity instanceof EntityLiving && !(entity instanceof EntityWaterAnimal) && !(entity instanceof EntityHuman)) { -+ if (flag && this.passengers.size() < 2 && !entity.isPassenger() && entity.getWidth() < this.getWidth() && entity instanceof EntityLiving && !(entity instanceof EntityWaterAnimal) && !(entity instanceof EntityHuman)) { // Paper - do not copy passenger list - entity.startRiding(this); - } else { - this.collide(entity); -@@ -727,8 +727,8 @@ public class EntityBoat extends Entity { - float f = 0.0F; - float f1 = (float) ((this.dead ? 0.009999999776482582D : this.bc()) + entity.bb()); - -- if (this.getPassengers().size() > 1) { -- int i = this.getPassengers().indexOf(entity); -+ if (this.passengers.size() > 1) { // Paper - do not copy list -+ int i = this.passengers.indexOf(entity); // Paper - do not copy list - - if (i == 0) { - f = 0.2F; -@@ -747,7 +747,7 @@ public class EntityBoat extends Entity { - entity.yaw += this.ak; - entity.setHeadRotation(entity.getHeadRotation() + this.ak); - this.a(entity); -- if (entity instanceof EntityAnimal && this.getPassengers().size() > 1) { -+ if (entity instanceof EntityAnimal && this.passengers.size() > 1) { // Paper - do not copy list - int j = entity.getId() % 2 == 0 ? 90 : 270; - - entity.n(((EntityAnimal) entity).aA + (float) j); -@@ -907,13 +907,13 @@ public class EntityBoat extends Entity { - - @Override - protected boolean q(Entity entity) { -- return this.getPassengers().size() < 2 && !this.a((Tag) TagsFluid.WATER); -+ return this.passengers.size() < 2 && !this.a((Tag) TagsFluid.WATER); // Paper - do not copy list - } - - @Nullable - @Override - public Entity getRidingPassenger() { -- List list = this.getPassengers(); -+ List list = this.passengers; // Paper - do not copy list - - return list.isEmpty() ? null : (Entity) list.get(0); - } -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 57821301ef031995e6044a17b46c70a693322455..75a88ab5d5b0fdb98ea8d61bb6b82049b21101f3 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -561,7 +561,7 @@ public abstract class EntityMinecartAbstract extends Entity { - - vec3d1 = new Vec3D(d8 * d4 / d6, vec3d1.y, d8 * d5 / d6); - this.setMot(vec3d1); -- Entity entity = this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ Entity entity = this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - - if (entity instanceof EntityHuman) { - Vec3D vec3d2 = entity.getMot(); diff --git a/Unmapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch b/Unmapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch deleted file mode 100644 index 78875ff589..0000000000 --- a/Unmapped-Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheShermanTanker -Date: Thu, 1 Oct 2020 01:11:03 +0800 -Subject: [PATCH] MC-29274: Fix Wither hostility towards players - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index f1d384d2e235c52a00f4b6d5643ef3c1d163e94b..7ddeecc6496926350d59d9b8725a4b161750f1e1 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -806,4 +806,10 @@ public class PaperWorldConfig { - private void setUpdatePathfindingOnBlockUpdate() { - updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); - } -+ -+ public boolean fixWitherTargetingBug = false; -+ private void witherSettings() { -+ fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); -+ log("Withers properly target players: " + fixWitherTargetingBug); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 170b085c76e092f6d7b14095c66c84fa9a96a1fc..635b1493eeb6c13cc5ef489bd747ac557bc131d8 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -104,6 +104,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this)); - this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0])); -+ if(this.world.paperConfig.fixWitherTargetingBug) this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 0, false, false, null)); // Paper - Fix MC-29274 - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityInsentient.class, 0, false, false, EntityWither.by)); - } - diff --git a/Unmapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch b/Unmapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch deleted file mode 100644 index a65efb398f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sun, 1 Nov 2020 16:43:11 +0100 -Subject: [PATCH] Throw proper exception on empty JsonList file - - -diff --git a/src/main/java/net/minecraft/server/players/JsonList.java b/src/main/java/net/minecraft/server/players/JsonList.java -index cd35b833d3047a38be980ee550641e87bd3b9b01..c960852dc60d0598012c5eef0d139fe38bde63fb 100644 ---- a/src/main/java/net/minecraft/server/players/JsonList.java -+++ b/src/main/java/net/minecraft/server/players/JsonList.java -@@ -189,6 +189,7 @@ public abstract class JsonList> { - - try { - JsonArray jsonarray = (JsonArray) JsonList.b.fromJson(bufferedreader, JsonArray.class); -+ com.google.common.base.Preconditions.checkState(jsonarray != null, "The file \"" + this.c.getName() + "\" is either empty or corrupt"); // Paper - - this.d.clear(); - Iterator iterator = jsonarray.iterator(); diff --git a/Unmapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch b/Unmapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch deleted file mode 100644 index ae8862a977..0000000000 --- a/Unmapped-Spigot-Server-Patches/0680-Improve-ServerGUI.patch +++ /dev/null @@ -1,400 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com> -Date: Sat, 3 Oct 2020 08:27:40 +0200 -Subject: [PATCH] Improve ServerGUI - -- Added logo to server frame -- Show tps in the server stats - -diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -index 67d064e3959ed8d886df30ce9d97f86c2443fa39..dc6bc1910ad0f9b27144d5750078c3ca607d03d3 100644 ---- a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -+++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -@@ -57,9 +57,18 @@ public class RAMDetails extends JList { - public void update() { - GraphData data = RAMGraph.DATA.peekLast(); - Vector vector = new Vector<>(); -+ -+ double[] tps = new double[] {server.tps1.getAverage(), server.tps5.getAverage(), server.tps15.getAverage()}; -+ String[] tpsAvg = new String[tps.length]; -+ -+ for ( int g = 0; g < tps.length; g++) { -+ tpsAvg[g] = format( tps[g] ); -+ } - vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); - vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); - vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); -+ vector.add("TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg)); -+ - setListData(vector); - } - -@@ -70,4 +79,9 @@ public class RAMDetails extends JList { - } - return ((double) total / (double) tickTimes.length) * 1.0E-6D; - } -+ -+ private static String format(double tps) -+ { -+ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); -+ } - } -diff --git a/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java b/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java -index f85a4079bb2931fd29a526379ba350eb7e8ae636..79cc587d8ad9f576f9e4478a41baabcaf690c568 100644 ---- a/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java -+++ b/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java -@@ -18,7 +18,7 @@ public class GuiStatsComponent extends JComponent { - }); - private final int[] b = new int[256]; - private int c; -- private final String[] d = new String[11]; -+ private final String[] d = new String[12]; public String[] getStatEntries() { return this.d; } // Paper - change size, OBFHELPER - private final MinecraftServer e; - private final Timer f; - -@@ -37,8 +37,18 @@ public class GuiStatsComponent extends JComponent { - private void b() { - long i = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - -+ // Paper start - Add tps entry -+ double[] tps = org.bukkit.Bukkit.getTPS(); -+ String[] tpsAvg = new String[tps.length]; -+ -+ for ( int g = 0; g < tps.length; g++) { -+ tpsAvg[g] = format( tps[g] ); -+ } - this.d[0] = "Memory use: " + i / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)"; - this.d[1] = "Avg tick: " + GuiStatsComponent.a.format(this.a(this.e.h) * 1.0E-6D) + " ms"; -+ getStatEntries()[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg); -+ // Paper end -+ - this.b[this.c++ & 255] = (int) (i * 100L / Runtime.getRuntime().maxMemory()); - this.repaint(); - } -@@ -85,4 +95,10 @@ public class GuiStatsComponent extends JComponent { - public void a() { - this.f.stop(); - } -+ -+ // Paper - start Add tps entry -+ private static String format(double tps) { -+ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/server/gui/ServerGUI.java b/src/main/java/net/minecraft/server/gui/ServerGUI.java -index c2c075b9e3b70f863b6c450e4f31d6fde2935be6..d1d98c2f192514a3f511bebb00c088b03e6be84c 100644 ---- a/src/main/java/net/minecraft/server/gui/ServerGUI.java -+++ b/src/main/java/net/minecraft/server/gui/ServerGUI.java -@@ -31,6 +31,11 @@ import net.minecraft.DefaultUncaughtExceptionHandler; - import net.minecraft.server.dedicated.DedicatedServer; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+// Paper start -+import java.io.IOException; -+import java.util.Objects; -+import javax.imageio.ImageIO; -+// Paper end - - public class ServerGUI extends JComponent { - -@@ -56,6 +61,15 @@ public class ServerGUI extends JComponent { - jframe.pack(); - jframe.setLocationRelativeTo((Component) null); - jframe.setVisible(true); -+ jframe.setName("Minecraft server"); // Paper -+ -+ // Paper start - Add logo as frame image -+ try { -+ jframe.setIconImage(ImageIO.read(Objects.requireNonNull(ServerGUI.class.getClassLoader().getResourceAsStream("logo.png")))); -+ } catch (IOException ignore) { -+ } -+ // Paper end -+ - jframe.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent windowevent) { - if (!servergui.f.getAndSet(true)) { -diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png -new file mode 100644 -index 0000000000000000000000000000000000000000..a7d785f60c884ee4ee487cc364402d66c3dc2ecc -GIT binary patch -literal 14310 -zcmXY21yoy2uugDycPmm{N^yd_Q`}vP7YOd|PH`>8wLo!q*HRn`6f5rV?*HD)IX5{c -zxpy-=`|Zxo_svGBD$Agwkf4A-AaprdNp;|J21vifLD%hMrT$lZeEex|7Xe0mqFAZArC{!qp)zJmbab@utqA`6 -z61Z~|e!k$IbXNT?PvGuuzT7G514$8e!}lsR>%nURMm+~pde``@(!O=ISt0%B93;Ez -za-qRi4n0Q>zQ2#2^_y08QOl3jT*!Ir5@<8VrFx(6f9sP|H8ttjftN;wrX>jP4BcG1;MfU5x^L`zc09u!bDBt#+ll=7@ -zB;}A$BKgu}V?#qfHvm`~pt%wG2y{MOc%B!8I`p|pc -zO#?sq!Zd&j8UPmvY4RQnfo>!6{a}GFV!}g@qu<3Wu$07X(O`vikNW$~q!ngF23Ls2 -z53p8js<-B_Qd?xX6rtq43Mdz(jOg2QXx#Wng_9^1^^~KqFNq{Kvb@Ap9}bf&xFA-C -z5+#cQ`#v$A=kd0O=agATcleBaxXf_(dnqbQz|cL9R&&Ni1omTs+6~YApmk)MCghxj -z1}mq&IU>1nEiF=q=PI`%jQbyRd=hVI83Sm{E-4uTc#w;NNwEW)C(C`xvWzY_%`_MmO -zD&g-sEaE)}6(&g)y-N&rNy;5@+{M`}!{60Y8wMgF5;HmO#B~hG`W$;7xLG*yF((rq -zxP6I#r#o`B3FppK{v(q1!C+YLFSfySDcHyoW!}EfzuCB1B|C5+oP}dtocnwkcNy1EZ6#5JX4=ePl&cu~0tMnt&79+I4%PaK>VqFx;r!QdNmnxlEqdU-QR%Nmu{aWP -zJxwXvt5fFTCOVgB)Zq -z%H0U=9q7Y0lu&1kc4zYT3*lHA@XJfoK>3WFM&WWf2u6^+wCm8##D$x@Gkw+t^HoO( -z4pxDRqg;$5S=t^k22H5^V3V0Qfy%Ogl8I%LD$52=7)J>Ki9Ej1HyEi_ujELlz8$-+?cdD1Zxi02kW0 -zaY=caFq4~s^R?zxcc3Z0X|az}Aww<{P$>6rk+5Di5J7$kWor0{Q&>+DWSBH^Gf`SP -zT{4}IOFh-hB7xwBdewq%de)q6QvxorV(()2>@j8i!kj)=^hN -zl_N{$9xTHHA;V&Zx#tX&1pOO;v^NiOP#_UK@J;;lp+OOhOOO2mlMdxM;Qv-mWG+^vzox|8t`w| -z=gPlM3)y6G*hfV1WwuMe>bO-vP9g`h5BqgO9x{ROBD;aPl>XDmvt(3PUxt|4RFRpK -z5OEtRz{(Oa_W_!Z4XHf#h;Z-~71XM7wlF*L!-#h_Uy2tGuy-rAZ)4{qE~feNkp}qf -zgvBtLkFPI~I7%C=OHZfPZz$j>L9)rb;l -z@J^dxncy52;wmHg=wC3|Xn6jPYCR7xc}~D0wNjoYxmoRh_zh=6@8coM1UQIa_z*1)cZPw4v40qoZQp-uy#DLv=oP -zX9b3vzFA2r8}|_AO8W1(OMG__0{1AUD&Z%&7-(>s+Z-X6Sv}G5QguIbZ3mYa--?09 -z;wNw?n=yAag4%m#w$$-YZ{(ZJUcwHfzu&!gykNjG)e}!=q8xy2_KS=ULsQwv45NK! -zVqqD8#S{vRjg4(Q6HM_F&tihNIQns<%DVjE$cv33ET>Dvc^#{z&#u&&9RgXO?ZLuebczKv#;! -zCS|2lIa37Bp#3RWj0$V3=I2>o40{(J^LD|EUH?!2;Z&HS*>7*V%{v1)wHaUP85mcX -z%q!K}Ntr*IzJD%++btJ;VQO*OjJL1t{GvR3cy@OC-~pe^bV?N`z0QKCr?Tom)4u%A -z3mi2k&eIgh0^rGI#Di+&3lrsy-r+}zwBkDQtswtPbkj!Y^l`{f!# -zLseC0M;DiifDa!({-G4{W$Wxsgv*(NX%HMyXhArVwY105dUHg?+=@6Sy8n@slS76x -zU7%PI8ToKm#qahfR;7kn#|t@9y(0EkooWBDqA1(mpO)>BBz))giBi8xVHlj#dR9U8 -zRo%`iBdlj8%_tRn^qa%T>{nsLLwTNld&WHLyfbPzv2W62m6q=Nsdxnk -z#{P==5!Lidx3bcr_qlUl%BX!xjywA?jv>FU^mJDa0zQT9Kw8RRHq>7B -zb~DXw0(oqBrOQunsm2ghWV2i1VmN{F?)U;0%*j{FEUxazAJ3)KSWomuhklkDi?5h*MTLDS5ma_Nk1sNZYzZ#$maGRyiXBzjG@(G__fuyBl(^A>s&{jF+J%5| -zv#7nD1XK806#_U_4#N2ANAxznk%;U$Y$z#{K*O07mADqx6LjACqwP<`HFV#C6Q*wx -z8JVP_qGF}V7B?^8)f*2F5AON7v$L~Kr?2}oPai_kG!_6MI(U`LS~+Mo*CSyrw>pPE -zllqxy -z^&rnDn4XA@AUY7~`1lwTCrm8KlVRqX&!kZFH&;i9@=R}UDxNSh*)Iq2U+#9}@ag1t -z%KUOEw0DXT)>hQoLTprY^z=BC=8NAyi3pZWT7A`?;rI<3%65Nqb93%pJ=!+dNtB>W -z7f3O-e-S7ZBgBntcyt~wOG_p$AU2zlGH8=%TEm+z8kLYReEMTkIo#2YiA=iKWrH); -zS%uT3xAyyY=!U)0Evpgx{{38MPR2nN<3913M<0O#YCO=TSt^4IzV3^D%2zC>t_OO} -z_h~AVOk+IIi$Ov;-g93a4j@WaekCC#HFm2_Vu9s)8-GbYtr{LgrxnSIN^PW9)!jYX -z?%-yssA~&R3F)C)wj5i|@!atCx?Qy%P1QEGSZm;iUNai`-F(8a%y+_a>CMzx$XEKx -z>sW|JbN36s+Y{4SZsrspH%UH=+Q6J`c&_-JLGL&5|$XUA1vFOC+rgoc&xT{dFT&pMaEBKwyD;plX0>2nla;jTlQ{!fn2M=Ak*=K*g% -zBm0-$ly1~}CT-5gv){jex9)7&b8u!a+vYHXU>=NF2>g3+_rN{(LUMGwRWKk49sS$v -zazyX8zZ1hwZ|U*5{fK@i@hRl*U%Q2cg+!iIfb)6W%S5F{91qinEZE%~4Gl>rBw9S< -zMP5$exl1jESyt}d~jo?hf`z^32b!}UGtJH+w9(0UrI#~Ei*ii&6z(AVE?(}k_A -zE9Z@mj7HF-ch46I0ipe3gapRj{=zk_J1E^b_JwdrhKi4ytBuwP)m>e$@9v`A{1N{h -zwUN6H=_W+h(a?rGaQ%%LP5C4)XiZ*`1uUwgqWvk`LyDD!Ps#Q5oI($KDJ%8n5kBi- -zghsLx`~mf<>WT)6-cJBbp|htk1NfkZ@e#B4@l?UH7!MDMpO?1NETGk_Eg{z!N3!D< -zWg8gtgS%b(0Bg7dw9u35xq)1vNdnM8iu7Eje*u?#sZ~%^q*HDaZC?5z4ZzhSA%ndS -z4&$M&7(|(9nWY%QShCnuN0 -z`n9&UeypypUgx;R+x;XM#8uDM{p`9~j<49)^dotHJVO*A@HL&g7F={FP#trj@{dzm -zeQUiqRWJ&pkKkA1O-|vOf8O1UQ$$0lIExffio|}F@ROV#MXcPH$ -z?$$kxAF@B#KT}u;R@SVyIO>1sw1!i?C(_013w9@?8$bKaLQi34zC$g*^}F&(%NEO6 -zQzD-^6}HQMnGJ{h$J*)HjSxjblWegsW&rLC8Ov_r_20jLjUS$Ptnm|p9fK%r0j+4; -z57^mjL&lISh8>DC;eB$B69$h4XxE3qU4T&zUpDeV@4g>or%D-x@qhie>6mqD959ck74(h?S0BA0}YQ18d?hr6}%}y{%ZNJ^-(?=Op~; -z#2-UNh)jH9>RXmvPJ(Y!8(uhyW|sFpyvv)AaNeljHj^Fx+RC -z!`@c->W1C^FUKHmG2w_atkdsMnzY+l!CV8havQ8-Gu)<8t{#V*2Pwp4h?ayXsi5Z> -zo!guta>TA~iv#iJpQkN>#)QF%As@2WgU&V_Y^qm#E*O}M_ijJfFWq}ts)-l4>D)kCqJJ@MG2$69ph0jzwI8ry1u8D@CyinC$oT?7S*Z}Eg -zYs}PWLqr4u@)w}#!{cMx;KxO6W2H6~3k$laJjAt+C{0mmCRnfs=OJYbh}HMh&e`#> -zj;jrpjqKCh41OK{FOS`@_sPP$iCm46G^EMNk8(l-1f>!gEV+4vMVRZ#8infUenP+k -zL^tBOHF^=)k&U-Tw{gfijqQ&^ -z-RHHII5yp}2|o8pTsf6x7$teW9Em!~iy2DN?D@|U)g%I6VG%JBO$|~;c~1Q^3|x`1 -z6HRbq1#~Ke)wWpALcc&@P;m+*sGavR0{aOx3=IwUE3YPWAwV45pzD$~02inxi7(6X -z$zk683M=_r#M*+6fQ)&FK0y|lm7JLwS)K=t&ZJk!U_-y%_o@fhr{s37MUEQOF*M)3 -zB$;4>Zx;Xk*(hwFjb>1iJ1f*D#nyWL{=>{2|9*^vCNN!%bF8Oe<`xz#s;jFz?;I}4M3lL;!fy_;J-E96Of+;sG%K=fZdR)99pJ}fM( -zq%(s8UrsEL{NrdF`!#RY+VjFyPpE_vtqPMM!MQ+QnE)+_g9Z^{4^;k&Sa^=w*yuxB_*Z!U%!3{_9Qr)Jfz4IeS#io4oj_Kqhq`HCUub|Ke!v$1-$v=kc+O#rlCej?%dhY -zxxKUTsFPG1nfoFp3%7@gh9S?vM0N27#*fpJyaX;Vy{!pt*}!9_mX9uC#J5RyjknW2Dm3dCvZYU -zSW?0kvI9!o2un}*%`AYhr^CQT1aZF=-Nt^atn@Kt%b2!hT(pK!|MclbBv3-<+6{>_ -z8toMfWc9rpOk(8|KW>Z-k>Fr(xc_+q9ocf`8!_n}XYUrW?Ax|*_|=5m*4F0V+46wJ -z1IGS^Z5t=0Zj86J2MfJc -zUq#WKCfhoB<;P2&&`*_G4^_0uqDR20m!>T8ay_rxSzA&9_v5##g6tzXTkx+KRfz32 -z9vvpp?+YxHTxDthCBu7)&Q052y4s9*$M4_2w-OdPyK?F-EBoUuSsIk@@(!gA*A_!0 -z2eu1y;-Q$Ut(M>8FCOtw?vZR-%*ly^x)<95vK@P0tJoZws@+M*NGhg_NU`!}DZnWBHQz%*@6))$BWN;EM0xAF+B4Mph#S??J?K+&viwPmes*n^HGDL9iBf -zCk|mDu46wwughN!isu&G((DO>Ws`(VLY?^#w=RONxUgFGby--Y=5NJ|(>qXOS`;lZhmXyMEyBdVM@jJh71E-})~`?t4w8^Kwy) -z<+KACjs!F^TS-;FT24_iWF+=l(nR}j7U#;Vd -z)IT3=b&}A}1PUKFa6DKfgHkJci!~7u?a%k9h7Rri^{y`|;;xNDoQbV}+oJ=LdApL}|77o@C= -z;~aed)XpbrMtt1x3gHPWxbliQH4nKBCew{9 -z*-_PTyn~`1VrwKcc4ZrhI^!MsZ{D0O0%O2!SHHi^Dfyr9*x*DGFKwc()b;q6nM*M7 -zvA$x_?$BMJJHN5HIn9Ps{_7-sn79~BZegaa5V;s(BA<5BnU?^AeJHXtd)cIj_UCjA -zW|N@MjV~vrJz{sE0Dzv}tXxUDQAXm)1(kX7C_ZVFX%!TlZ850i(P1A0BxaJu)#LcH -zoxMFRzxoxw$bM=B6gpuMD#vcsa^00?%=D+T9-dQqV*=zD|)W!3BLun2&^n)~$ -z2_^{i9~sGXOAsF_S=k&4mWJ@`mD+G%MiPTlhuomboeFNwHb(< -zVpVR!mwf;JmpO3JL|B%L-!;@7TG}+`HZA;-{VIlQGY|T=f|!9!S=!c?sq5|KeEQ*~ -zm!1xeZcJPbSsfjU9e>K|=Ni<+YgrIG!|5@|Z>4bjx+`1j^O-{QK8XARf -zUG$nLRiTEtt;)9F30rvw>nj)@vCF{$d7>o2n>}~Y2^^C79l@s`uXRZOcuy>^%2@t- -zRGv={pKlDXFUgvG_^DWGR==il1rIzn{$p4r(FVOQxZi!_*Ksfl2hR{Aj>01RbFAM= -zpr0wzMwlOwlkt4|JLK)$>VL+{4nv>^`yMa)T;(9f*B(9;{T+)_=M4dN>M&&hS-#(G -z)-sW(WxVkHR)`x#g)25Lu7qnN;~Q-bvKDZ=;^fyLy@okDpvt&ZU{!U)WVtmnp -zAN-CzM{jPFWep9NAKDDq@=kynkGi_GQ@Z2y_Wn)xc_q3-&+9`qdGy_{PF-2c^$)%x -zd0sonEJhtG*2|P*Q-f_3`Akk96HzBz2 -z!5tnJaCcA2hGQrSw*{F)epvfYX?7toP=O0dN -zizY2w`>O@4Vqff!dBhQ^><#TjMP}loM9ProiD-Og@$V=*zQ|Avg0D!+96lr^u(1fl -z3J52PHoJYDdvdiIW?q?JIC*r?88VruLx#bp0lys39v$(c6uC*j}2IFFh -zViOX|K+DH18cd9%Rgjs$*sXuoW<>p^Fv-7CV|zpgTUnj812pyyX-nhA4TZ^UyYY9; -z?}BOarTT1q;0xSTjV_DPWE11?Y2+wSA*ybzebDoy8JwhznKa6SvYxE$WswX7Z6pG$ -zsA2GgHFFL3^zA@XTYK{a+6$Q8di%@1-|q9U15y+~R-L7Kwx8*xr(FP{g*JDPa`e((jSl#~?Rx=3ne(nLfeP9k0grubJK -zU4euzZqt~$Cl%k^{-!e6YQZi|D3#+MUS}VsYZ)0S>y@)kyqRI?A_esvAu-{`1Uq@! -zC+b`wnMK&<_mitl+k@e*$*{&S>vayX*>D>Q5sw2FZ?l(8ff%(8lo<^mBMrwQXOXe+ -z*7sZdWzBTIwZO$y^F)qZL1XbOMY<@M_a56y{({Vg@YN<_y}toq41V%~w=+4ZQvg)X -zVw~l$z-sId^nKU%dlk7W(mG}eS&KV2BdYqNJnX-p=YrG&&`_m0fzA_|iKD${5?oL* -zdS$heR@%Q+(3!!T&k;tIN|v2j=UI))rgkvyC7MTTrKP3g>Fma@_R0`GE5(tL%sS$7 -zG41ag%(Y(xZ5cjlk=R~(3XC+$25r*Fo=G5OhGgR}i!nDoG?^sult?Eo*x$x6CH-3L@LtZ0dfq!Bbbw-S}RwlN%lpH8c=4l2qH -z1wRszHSPh~=esnWvXD8B{D4<}?}6cA+@Ob1760Is6`g!zl@WL(L&={LA}SxAt0>Tw -z%b7i^&yNKM;(vGcNwuxAK{g|S3Y1&pH_6U1G -z3M4zx5FU=O;=l_?VzQ-~bx~xN1axPgYI0am3d25BjYmfSTX7Q}==Vcryl6@Se0(Jv -zxKW_o%H`jdnC7QXlkFbCsACHN1Dx=0gf<~@PW-&<=`1Hd)@#ypH7%OpalDj-P=ts+3^~yWs~TV}BD20HjkW6zc1L -z0#HzMkn3JV%7N-18_@tgE82*YnmEzxirriDSx#_|<|q1vL{k}7>^mRzO(ueTSN2~H -zG}kxp)Qn!&)><3|e>62+GXSpQKcemfqU!&BHZ5Ca;DT<63bBM&uV1BDS?MM$M;x8w>gShAPMxJM^BbMZn}Unm{OC9^4x3%% -zlmX8!km-u$N4fQXQ>jRe`7)3+RFGjhz -z18zf(Fo2<>YV^7LJO^UTZ2Ivd#mpN}o?7pBV&q=f%ID>haV7M8R3jsF*@a%iwIy>| -zsZ!-y{!%&j7`B?W8TcF4NH-RHH1xZ{;7BsA<#APu!;cND)te)FhoXz$BIU}2&^7WP -zT}TX>ZO58$VNPuh6JV7~s(W$vAj`^%AtUamex3YdVl3~4+pqk?G)qUibNMrj0*M25 -zY>5Ac|Dnv6xBQmV#$3JA?&HTN(lYl~J}@$l{*TY^kORrCB)3dDO}^^v!dcLf^CHty -zanjllIQeSLmpuG+h&ae`r*v!C*0A&W^a&q>93?BAXzG7n -z2*3TGPIcN`-_hY9&oaiv#fiv~>}7`T`4=pInEqWX*3e8+yPm^9h-tr&ts55$l+388 -zW)~F}2JH!}VLbQ>?6~H@&k`MnSsTeVj0TRVP4jGbP*!!CwM6`Z11c)yI2w$+R0zxo -zT|obYS1&&`{>>Z9(jnVU&=yI*%PGe*f78ie*_9oap?sd7fx7{r^WT>=XHF -zl`f{=UJEn2?tRw`Fem?eRE6#*nOes(ebRcmaK3~a3{a3EyE1zXSF0p7I_iDJ&%;3V -zU;AS}e?*mH#Yh2P9E3QBigIqu2iXf=@t)2+I~f*_E^JtEP1@IR{CBfTj%T}E3e#n% -zUa{@vU?D$l4DEANwkkK@ruP4ta)E*e^KLGg%$PizyPmHvKNMWtuJQ6sPXY=(1m#>W -z7V?9E!Vj}>a|KfQx5ESpH+q6$@gAp-P#~lbz`aj1_?xinN>3o8b2-Z3w>UZ3QZ}W0 -zWg-!>p>AADDcU^4;0*L4UFgB0QLlXd^y1E&4>txV!T|!`RwjZGl`;-4ZgFf>luHIy -zZ8d8Rh{I3r!g-ht6mAZxMB6VxRqnA0UY`h|mJZy2 -z17BazT$jMKFL3J6Ue_HL1^)4s%$Jj~Qx~1HG#tS@kwL(KP_ZI3dWz0SH(sqj#-*TNGsIWqPj>cj?!GyWvfdEiNOu4$>MIqL=F&Cc0{g*~L5 -zA1wt)=_zMFUkCT5$l!G{1-Y9QtGQ#qm5E(3fYPms_EP*sSVI)bfXN|uNO`BqVuCvd -zv)z8IGRgtM1<_trndVhQ^xA)wn~*W~#d*X@E=W)jcQWI8+?kdzHe;DZ`%+JE%gE}m -z6H=FO8rJxM{N90S=Gi!Mel)TyanxPa;E}C?hJl@e9UWad->;S|v;axgFjrY$z3(rV{MiJ}3M)t;Q?P5wZy0e3G{dcDO7n}3slDXLMrB$;#*W@Qv)D$=?Xs$F(8eTcyGIQ~IWgD%Gn&E>F9y#o>cR-7spE;Rur<_E~Pu)e0I -z#&y1|@8D~8c55<|KMf;&x;hg!A%VOZ38_+uk`jH4#=b9M&xcpxV-7cMN{jXVRnKSe -zlKJJ%=VBV{$DNeI1QkiA;DfdVT?$;O#22z6v6bTK9)fjrfIh!Hq__l~KzuNqT{&kA -zKs@YV6^1ZLGjTgR%(=NHS-DvWnnP)NM#qbHINqmQdCE5??co$3nuikqgm=s7*#Kd*+j_weKrZjMeLeHEoiJm>zuDRU` -zh~ggr^knneWU!Nn}AQt=0Id6Hk; -z4bJqse|V$H`stT?NS0yreYvaZ9YF!fw+N}{3#yXRU!C7?exl35BDC%+!jDMGT^DN# -zN9FGd#5t#;$h}5UgQ?q-Gr15>C6=nLUszle9<+_!!oi_m@_L^-R>_Qty7_g|C%m|5 -z-7^5X5V_ARi?h9_LW%2vByD3X_IvUktqBv{%SYXO1&;e&O#Ll_cfC`Wv1u+l_#RI< -zQ5Kly0;P`%TXaQN(heOg~>V&L{d+ZDA%eq-UKo#1)$rkjSm=nzAE2r -z5--RyKhxfXoGVU3^ab{5XGlyL1+26foG)4HZvN -zG@&I3h0fnK5lIjcrg*XxPy1(gK3_TN`&VYnxP;C|j$~0rT$0f|*#=OzM^NbE-1T5D -z%Csnt)n!sx3N#b(8G&+G3W~Q_B#StA6jZZ=p#wuu`DrAMXm{T@#S;ku4Dme@{Njmk -zCtrh3z6O>o)~o{&Htx+6kn*)$NNBH-biu^aYtWUq -z(G>4rCEKr#tO>!x8A@%W@6g)Xs%2Hq!y#Mbb@9R2@GDWi&!{jhZvzQ1D9nMuPoOS+ -z+cj{9nx5X{jJOIavbFf)Kz5Jnbe5Bu#(XE-z$j&iaP%c9W59OoT0~|N#D*(N2kz={ -zs(|)nH!_+_g1)#ZH2xk>ZTG#6WN#qa3BxZM{NWxq`*#$H255k6Ky?hw*hSA6`c_fl -zT@Ua%E5Ez3;~`kQFmrC#$Nlvc_Uy3#yzhd-6UYuuIwgIBZZC-`dwOBJbfurL(FfhH -z{YkjE+9OrOveY`{t{sGw&51YO1@{iO4)Ki=!Z5#q=m_Hi)_j0`>?;t2j);vv%BUif -z;wpTZdLQLsGvZ()DCdxYudn^Pt;BZ}Rin$4F8h{R`HxT2z`uc&aMXIQOvwgA5%{&) -zFW52MiN!$!EXgx}Px~e1!EMp;#&kY65oDho95j~!qD%YJr`+aK4jCJ4UJ^;q>w@Lf -zvDfg|M`S^@DGxu+7aR3Cx#;%?advj&1~L-m -zJqCP9&TW3migV*`Z$#)Qa>3>Jf)g9D6Ki28P@iX(uso)hic8Dp1F< -zeF;(n8Po8A*~^T{De(J)Z2nqLl@Vv3yoSlGwq0aeOg4ymI(KIkTeur-=J-yp9z?qe)it6gq-wl@I -z0D-_I{|T<5kwD9uH3yf1GWXp5*8eOgJf*q0IRoK|+r{}Fug&0WpNDKMTC@(Xc)9K8 -zy`lByMn!1fnY)1KYP(0Je1)c~WilUuh<&Q8^OE?L9Q^xK*Y@M$`6D6TDCZ^@l8{|} -zxmmNw)mng$hYBii+&ZqedxWT0dnV#LG4zC%+kzcK+-??vEHT>Q-T8zu|s_1IbA#OV)^+1pg1OmmZn` - -literal 0 -HcmV?d00001 - diff --git a/Unmapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/Unmapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch deleted file mode 100644 index 852ff8decb..0000000000 --- a/Unmapped-Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Tue, 2 Feb 2021 09:17:59 +0100 -Subject: [PATCH] stop firing pressure plate EntityInteractEvent for ignored - entities - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java -index 4c4c8b23c39d26c646b1950023a20446ac798c6f..fba720bf2349a69d0f93642eea4e77063f83380c 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java -@@ -82,6 +82,7 @@ public class BlockPressurePlateBinary extends BlockPressurePlateAbstract { - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); -+ if (entity.isIgnoreBlockTrigger()) continue; // Paper - don't call event for ignored entities - - // CraftBukkit start - Call interact event when turning on a pressure plate - if (this.getPower(world.getType(blockposition)) == 0) { diff --git a/Unmapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch b/Unmapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch deleted file mode 100644 index ef2fcdd893..0000000000 --- a/Unmapped-Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 19:49:15 -0800 -Subject: [PATCH] fix converting txt to json file - - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -index b13e6f9923a9c5703f4eaeab2d0c112e4726b496..a762cf4c4a52bcbc8dbfd60b3ad7fef5489ba5c5 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -@@ -18,6 +18,11 @@ public class DedicatedPlayerList extends PlayerList { - - this.a(dedicatedserverproperties.viewDistance); - super.setHasWhitelist((Boolean) dedicatedserverproperties.whiteList.get()); -+ // Paper start - moved from constructor -+ } -+ @Override -+ public void loadAndSaveFiles() { -+ // Paper end - this.y(); - this.w(); - this.x(); -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index a5b1f33473e8c82511fdd0c218f4fe744f584de8..cac3df2ca054b3b2fb5b6437ab2950afc3ace8fb 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -198,6 +198,12 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); - org.spigotmc.SpigotConfig.registerCommands(); - // Spigot end -+ // Paper start - moved up to right after PlayerList creation but before file load/save -+ if (this.convertNames()) { -+ this.getUserCache().save(false); // Paper -+ } -+ this.getPlayerList().loadAndSaveFiles(); // Must be after convertNames -+ // Paper end - // Paper start - try { - com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); -@@ -260,10 +266,6 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - DedicatedServer.LOGGER.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file."); - } - -- if (this.convertNames()) { -- this.getUserCache().b(false); // Paper -- } -- - if (!NameReferencingFileConverter.e(this)) { - return false; - } else { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 1358993217e601e3bab6e0a4e8c55d555865a13e..484c7cea458dda38e4816fe5f1c05c6836fa38b9 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -175,6 +175,7 @@ public abstract class PlayerList { - this.maxPlayers = i; - this.playerFileData = worldnbtstorage; - } -+ abstract public void loadAndSaveFiles(); // Paper - moved from DedicatedPlayerList constructor - - public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { - EntityPlayer prev = pendingPlayers.put(entityplayer.getUniqueID(), entityplayer);// Paper -diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java -index 692d95c94df85d752a3ddc66e1f2af765565b160..c617b7dd5a992770fc87113987807947ae68be81 100644 ---- a/src/main/java/net/minecraft/server/players/UserCache.java -+++ b/src/main/java/net/minecraft/server/players/UserCache.java -@@ -243,6 +243,7 @@ public class UserCache { - return arraylist; - } - -+ public void save(boolean asyncSave) { b(asyncSave); } // Paper - OBFHELPER - public void b(boolean asyncSave) { // Paper - JsonArray jsonarray = new JsonArray(); - DateFormat dateformat = e(); diff --git a/Unmapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch b/Unmapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch deleted file mode 100644 index 49bf0c1ca5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0683-Add-worldborder-events.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 22:40:34 -0800 -Subject: [PATCH] Add worldborder events - - -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index bedaa9dd6390e81df5872c2dd6e202a038367bf6..3c25021835d6d8fd112fc89636616bfd744e7f1a 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -14,6 +14,9 @@ import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.shapes.OperatorBoolean; - import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.phys.shapes.VoxelShapes; -+import io.papermc.paper.event.world.border.WorldBorderBoundsChangeFinishEvent; // Paper -+import io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent; // Paper -+import io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent; // Paper - - public class WorldBorder { - -@@ -102,15 +105,19 @@ public class WorldBorder { - } - - public void setCenter(double d0, double d1) { -- this.g = d0; -- this.h = d1; -+ // Paper start -+ WorldBorderCenterChangeEvent event = new WorldBorderCenterChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), new org.bukkit.Location(world.getWorld(), this.getCenterX(), 0, this.getCenterZ()), new org.bukkit.Location(world.getWorld(), d0, 0, d1)); -+ if (!event.callEvent()) return; -+ this.g = event.getNewCenter().getX(); -+ this.h = event.getNewCenter().getZ(); -+ // Paper end - this.j.k(); - Iterator iterator = this.l().iterator(); - - while (iterator.hasNext()) { - IWorldBorderListener iworldborderlistener = (IWorldBorderListener) iterator.next(); - -- iworldborderlistener.a(this, d0, d1); -+ iworldborderlistener.a(this, event.getNewCenter().getX(), event.getNewCenter().getZ()); // Paper - } - - } -@@ -128,25 +135,43 @@ public class WorldBorder { - } - - public void setSize(double d0) { -- this.j = new WorldBorder.d(d0); -+ // Paper start -+ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE, getSize(), d0, 0); -+ if (!event.callEvent()) return; -+ if (event.getType() == WorldBorderBoundsChangeEvent.Type.STARTED_MOVE && event.getDuration() > 0) { // If changed to a timed transition -+ transitionSizeBetween(event.getOldSize(), event.getNewSize(), event.getDuration()); -+ return; -+ } -+ this.j = new WorldBorder.d(event.getNewSize()); -+ // Paper end - Iterator iterator = this.l().iterator(); - - while (iterator.hasNext()) { - IWorldBorderListener iworldborderlistener = (IWorldBorderListener) iterator.next(); - -- iworldborderlistener.a(this, d0); -+ iworldborderlistener.a(this, event.getNewSize()); // Paper - } - - } - - public void transitionSizeBetween(double d0, double d1, long i) { -- this.j = (WorldBorder.a) (d0 == d1 ? new WorldBorder.d(d1) : new WorldBorder.b(d0, d1, i)); -+ // Paper start -+ WorldBorderBoundsChangeEvent.Type type; -+ if (d0 == d1) { // new size = old size -+ type = WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE; // Use INSTANT_MOVE because below it creates a Static border if they are equal. -+ } else { -+ type = WorldBorderBoundsChangeEvent.Type.STARTED_MOVE; -+ } -+ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), type, d0, d1, i); -+ if (!event.callEvent()) return; -+ this.j = (WorldBorder.a) (d0 == event.getNewSize() ? new WorldBorder.d(event.getNewSize()) : new WorldBorder.b(d0, event.getNewSize(), event.getDuration())); -+ // Paper end - Iterator iterator = this.l().iterator(); - - while (iterator.hasNext()) { - IWorldBorderListener iworldborderlistener = (IWorldBorderListener) iterator.next(); - -- iworldborderlistener.a(this, d0, d1, i); -+ iworldborderlistener.a(this, d0, event.getNewSize(), event.getDuration()); // Paper - } - - } -@@ -434,11 +459,11 @@ public class WorldBorder { - - class b implements WorldBorder.a { - -- private final double b; -- private final double c; -+ private final double b; public final double getOldSize() { return this.b; } // Paper - OBFHELPER -+ private final double c; public final double getNewSize() { return this.c; } // Paper - OBFHELPER - private final long d; - private final long e; -- private final double f; -+ private final double f; public final double getDuration() { return this.f; } // Paper - OBFHELPER - - private b(double d0, double d1, long i) { - this.b = d0; -@@ -493,6 +518,7 @@ public class WorldBorder { - - @Override - public WorldBorder.a l() { -+ if (this.getLerpTimeRemaining() <= 0L) new WorldBorderBoundsChangeFinishEvent(world.getWorld(), world.getWorld().getWorldBorder(), getOldSize(), getNewSize(), getDuration()).callEvent(); // Paper - return (WorldBorder.a) (this.g() <= 0L ? WorldBorder.this.new d(this.c) : this); - } - -@@ -514,6 +540,7 @@ public class WorldBorder { - - double e(); - -+ default long getLerpTimeRemaining() { return g(); } // Paper - OBFHELPER - long g(); - - double h(); diff --git a/Unmapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch b/Unmapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch deleted file mode 100644 index c4ab87d789..0000000000 --- a/Unmapped-Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 5 Jul 2020 00:33:54 -0700 -Subject: [PATCH] added PlayerNameEntityEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ItemNameTag.java b/src/main/java/net/minecraft/world/item/ItemNameTag.java -index 140a865f4f8fb3e4f787cf8d334d20fac6cb5eef..b9b2b27e534ba87a1aae3c521f393a066a18a199 100644 ---- a/src/main/java/net/minecraft/world/item/ItemNameTag.java -+++ b/src/main/java/net/minecraft/world/item/ItemNameTag.java -@@ -1,11 +1,17 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.player.EntityHuman; - -+// Paper start -+import io.papermc.paper.adventure.PaperAdventure; -+import io.papermc.paper.event.player.PlayerNameEntityEvent; -+// Paper end -+ - public class ItemNameTag extends Item { - - public ItemNameTag(Item.Info item_info) { -@@ -16,11 +22,15 @@ public class ItemNameTag extends Item { - public EnumInteractionResult a(ItemStack itemstack, EntityHuman entityhuman, EntityLiving entityliving, EnumHand enumhand) { - if (itemstack.hasName() && !(entityliving instanceof EntityHuman)) { - if (!entityhuman.world.isClientSide && entityliving.isAlive()) { -- entityliving.setCustomName(itemstack.getName()); -- if (entityliving instanceof EntityInsentient) { -- ((EntityInsentient) entityliving).setPersistent(); -+ // Paper start -+ PlayerNameEntityEvent event = new PlayerNameEntityEvent(((EntityPlayer) entityhuman).getBukkitEntity(), entityliving.getBukkitLivingEntity(), PaperAdventure.asAdventure(itemstack.getName()), true); -+ if (!event.callEvent()) return EnumInteractionResult.PASS; -+ EntityLiving newEntityLiving = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle(); -+ newEntityLiving.setCustomName(event.getName() != null ? PaperAdventure.asVanilla(event.getName()) : null); -+ if (event.isPersistent() && newEntityLiving instanceof EntityInsentient) { -+ ((EntityInsentient) newEntityLiving).setPersistent(); - } -- -+ // Paper end - itemstack.subtract(1); - } - diff --git a/Unmapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch b/Unmapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch deleted file mode 100644 index 7eba41fbef..0000000000 --- a/Unmapped-Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Tue, 16 Feb 2021 21:37:51 -0600 -Subject: [PATCH] Prevent grindstones from overstacking items - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -index 1d5dcbbd3870eb8e1013a97f6ce882bfc096bf95..a841c47c25287080738b04352ea4e8eaa77dacdd 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -@@ -196,13 +196,13 @@ public class ContainerGrindstone extends Container { - i = Math.max(item.getMaxDurability() - l, 0); - itemstack2 = this.b(itemstack, itemstack1); - if (!itemstack2.e()) { -- if (!ItemStack.matches(itemstack, itemstack1)) { -+ if (!ItemStack.matches(itemstack, itemstack1) || itemstack2.getMaxStackSize() == 1) { // Paper - add max stack size check - this.resultInventory.setItem(0, ItemStack.b); - this.c(); - return; - } - -- b0 = 2; -+ b0 = 2; // Paper - the problem line for above change, causing over-stacking - } - } else { - boolean flag3 = !itemstack.isEmpty(); diff --git a/Unmapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch b/Unmapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch deleted file mode 100644 index 41d4ad4460..0000000000 --- a/Unmapped-Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> -Date: Wed, 6 Jan 2021 12:04:03 -0800 -Subject: [PATCH] Add recipe to cook events - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -index 62a19f39405cff27f34a3b98fb9310b1c9c27563..08759f461ec947c0d5655557f49d8717afee6f00 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -@@ -74,7 +74,10 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab - - if (this.cookingTimes[i] >= this.cookingTotalTimes[i]) { - InventorySubcontainer inventorysubcontainer = new InventorySubcontainer(new ItemStack[]{itemstack}); -- ItemStack itemstack1 = (ItemStack) this.world.getCraftingManager().craft(Recipes.CAMPFIRE_COOKING, inventorysubcontainer, this.world).map((recipecampfire) -> { -+ // Paper start -+ Optional recipe = this.world.getCraftingManager().craft(Recipes.CAMPFIRE_COOKING, inventorysubcontainer, this.world); -+ ItemStack itemstack1 = (ItemStack) recipe.map((recipecampfire) -> { -+ // Paper end - return recipecampfire.a(inventorysubcontainer); - }).orElse(itemstack); - BlockPosition blockposition = this.getPosition(); -@@ -83,7 +86,7 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab - CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); - -- BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.world, this.position), source, result); -+ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.world, this.position), source, result, (org.bukkit.inventory.CookingRecipe) recipe.map(RecipeCampfire::toBukkitRecipe).orElse(null)); // Paper - this.world.getServer().getPluginManager().callEvent(blockCookEvent); - - if (blockCookEvent.isCancelled()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index 54316a8079b4331a48cac3c43f3f8c506a4af091..1997139fb87dc1947acfdf02e1f116577c3fa943 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -395,7 +395,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); - -- FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()), source, result); -+ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()), source, result, (org.bukkit.inventory.CookingRecipe) irecipe.toBukkitRecipe()); // Paper - this.world.getServer().getPluginManager().callEvent(furnaceSmeltEvent); - - if (furnaceSmeltEvent.isCancelled()) { diff --git a/Unmapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch b/Unmapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch deleted file mode 100644 index 6cfa745ab3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0687-Add-Block-isValidTool.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 6 Jul 2020 12:44:31 -0700 -Subject: [PATCH] Add Block#isValidTool - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index ed1c92d9f2770f7d0503c6facebc51ddcbdf75cf..0006b3cad5fe46e50b0efeae99102f9d80276d61 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -806,5 +806,9 @@ public class CraftBlock implements Block { - } - return speed; - } -+ -+ public boolean isValidTool(ItemStack itemStack) { -+ return getDrops(itemStack).size() != 0; -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch b/Unmapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch deleted file mode 100644 index 2cec392ea8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Anton Lindroth -Date: Wed, 15 Apr 2020 01:54:02 +0200 -Subject: [PATCH] Allow using signs inside spawn protection - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7ddeecc6496926350d59d9b8725a4b161750f1e1..0dd0795af0d0deeff5637a2a1a4a165dec26af15 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -812,4 +812,9 @@ public class PaperWorldConfig { - fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); - log("Withers properly target players: " + fixWitherTargetingBug); - } -+ -+ public boolean allowUsingSignsInsideSpawnProtection = false; -+ private void allowUsingSignsInsideSpawnProtection() { -+ allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index c68e56562076a2ca3d099a1112404f11a5473397..7d584e6d7b4e7b27ca0d51e0eb52a47169aa4b58 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -143,6 +143,7 @@ import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.IWorldReader; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.BlockCommand; -+import net.minecraft.world.level.block.BlockSign; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.entity.TileEntityCommand; -@@ -1692,7 +1693,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.player.resetIdleTimer(); - if (blockposition.getY() < this.minecraftServer.getMaxBuildHeight()) { -- if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.a((EntityHuman) this.player, blockposition)) { -+ if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && (worldserver.a((EntityHuman) this.player, blockposition) || (worldserver.paperConfig.allowUsingSignsInsideSpawnProtection && worldserver.getType(blockposition).getBlock() instanceof BlockSign))) { // Paper - // CraftBukkit start - Check if we can actually do something over this large a distance - // Paper - move check up - this.player.clearActiveItem(); // SPIGOT-4706 diff --git a/Unmapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch b/Unmapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch deleted file mode 100644 index 914a3c28d5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 6 Jan 2021 00:34:04 -0800 -Subject: [PATCH] Implement Keyed on World - - -diff --git a/src/main/java/net/minecraft/core/IRegistry.java b/src/main/java/net/minecraft/core/IRegistry.java -index 3e9ebeffdf66f8a959630b344149d17137c6901c..4f04d8081912e0fe771f0db9e086c789328f246f 100644 ---- a/src/main/java/net/minecraft/core/IRegistry.java -+++ b/src/main/java/net/minecraft/core/IRegistry.java -@@ -130,7 +130,7 @@ public abstract class IRegistry implements Codec, Keyable, Registry { - public static final ResourceKey> I = a("loot_function_type"); - public static final ResourceKey> J = a("loot_condition_type"); - public static final ResourceKey> K = a("dimension_type"); -- public static final ResourceKey> L = a("dimension"); -+ public static final ResourceKey> L = a("dimension"); public static final ResourceKey> getWorldRegistry() { return L; } // Paper - OBFHELPER - public static final ResourceKey> M = a("dimension"); - public static final IRegistry SOUND_EVENT = a(IRegistry.g, () -> { - return SoundEffects.ENTITY_ITEM_PICKUP; -@@ -339,9 +339,9 @@ public abstract class IRegistry implements Codec, Keyable, Registry { - MinecraftKey minecraftkey = resourcekey.a(); - - IRegistry.a.put(minecraftkey, supplier); -- IRegistryWritable iregistrywritable = IRegistry.e; -+ IRegistryWritable iregistrywritable = IRegistry.e; // Paper - decompile fix - -- return (IRegistryWritable) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); -+ return (R) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); // Paper - decompile fix - } - - protected IRegistry(ResourceKey> resourcekey, Lifecycle lifecycle) { -@@ -428,11 +428,11 @@ public abstract class IRegistry implements Codec, Keyable, Registry { - } - - public static T a(IRegistry iregistry, MinecraftKey minecraftkey, T t0) { -- return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.b, minecraftkey), t0, Lifecycle.stable()); -+ return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.b, minecraftkey), t0, Lifecycle.stable()); // Paper - decompile fix - } - - public static T a(IRegistry iregistry, int i, String s, T t0) { -- return ((IRegistryWritable) iregistry).a(i, ResourceKey.a(iregistry.b, new MinecraftKey(s)), t0, Lifecycle.stable()); -+ return ((IRegistryWritable) iregistry).a(i, ResourceKey.a(iregistry.b, new MinecraftKey(s)), t0, Lifecycle.stable()); // Paper - decompile fix - } - - static { -diff --git a/src/main/java/net/minecraft/resources/ResourceKey.java b/src/main/java/net/minecraft/resources/ResourceKey.java -index 760579921927b4c8b0f20b2611b95fd626e4b27f..3075700dfa992da81b10246fcf7c7ad1115c4ba3 100644 ---- a/src/main/java/net/minecraft/resources/ResourceKey.java -+++ b/src/main/java/net/minecraft/resources/ResourceKey.java -@@ -12,6 +12,7 @@ public class ResourceKey { - private final MinecraftKey b; - private final MinecraftKey c; - -+ public static ResourceKey newResourceKey(ResourceKey> registryKey, MinecraftKey minecraftKey) { return a(registryKey, minecraftKey); } // Paper - OBFHELPER - public static ResourceKey a(ResourceKey> resourcekey, MinecraftKey minecraftkey) { - return a(resourcekey.c, minecraftkey); - } -@@ -41,6 +42,7 @@ public class ResourceKey { - return this.b.equals(resourcekey.a()); - } - -+ public MinecraftKey getLocation() { return a(); } // Paper - OBFHELPER - public MinecraftKey a() { - return this.c; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e5c78b4e7537c8a042dcc41ca6b77c000c4317de..706dad235de3b7ffe014f564e1c68f18e1edeefc 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1157,7 +1157,7 @@ public final class CraftServer implements Server { - } else if (name.equals(levelName + "_the_end")) { - worldKey = net.minecraft.world.level.World.THE_END; - } else { -- worldKey = ResourceKey.a(IRegistry.L, new MinecraftKey(name.toLowerCase(java.util.Locale.ENGLISH))); -+ worldKey = ResourceKey.newResourceKey(IRegistry.getWorldRegistry(), new net.minecraft.resources.MinecraftKey(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper - } - - WorldServer internal = (WorldServer) new WorldServer(console, console.executorService, worldSession, worlddata, worldKey, dimensionmanager, getServer().worldLoadListenerFactory.create(11), -@@ -1247,6 +1247,15 @@ public final class CraftServer implements Server { - return null; - } - -+ // Paper start -+ @Override -+ public World getWorld(NamespacedKey worldKey) { -+ WorldServer worldServer = console.getWorldServer(ResourceKey.newResourceKey(IRegistry.getWorldRegistry(), CraftNamespacedKey.toMinecraft(worldKey))); -+ if (worldServer == null) return null; -+ return worldServer.getWorld(); -+ } -+ // Paper end -+ - public void addWorld(World world) { - // Check if a World already exists with the UID. - if (getWorld(world.getUID()) != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 05a7f5f61330bd52705640345524cdedbf105285..a152d5bec8bf0dd87239b0a3432fb589cea61bd8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2584,6 +2584,11 @@ public class CraftWorld implements World { - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); - }, net.minecraft.server.MinecraftServer.getServer()); - } -+ -+ @Override -+ public org.bukkit.NamespacedKey getKey() { -+ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(world.getDimensionKey().getLocation()); -+ } - // Paper end - - // Spigot start diff --git a/Unmapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch b/Unmapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch deleted file mode 100644 index 65430ea1e7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Irmo van den Berge -Date: Wed, 10 Mar 2021 21:26:31 +0100 -Subject: [PATCH] Add fast alternative constructor for Vector3f - -Signed-off-by: Irmo van den Berge - -diff --git a/src/main/java/net/minecraft/core/Vector3f.java b/src/main/java/net/minecraft/core/Vector3f.java -index 93590ceb0bbe369a1bda987f0c4c21ea6a3b3a1a..da53e294fa5e28406b25614039db49b48c2dcdac 100644 ---- a/src/main/java/net/minecraft/core/Vector3f.java -+++ b/src/main/java/net/minecraft/core/Vector3f.java -@@ -19,6 +19,18 @@ public class Vector3f { - this(nbttaglist.i(0), nbttaglist.i(1), nbttaglist.i(2)); - } - -+ // Paper start - faster alternative constructor -+ private Vector3f(float x, float y, float z, Void dummy_var) { -+ this.x = x; -+ this.y = y; -+ this.z = z; -+ } -+ -+ public static Vector3f createWithoutValidityChecks(float x, float y, float z) { -+ return new Vector3f(x, y, z, null); -+ } -+ // Paper end -+ - public NBTTagList a() { - NBTTagList nbttaglist = new NBTTagList(); - diff --git a/Unmapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch b/Unmapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch deleted file mode 100644 index d98d46c7ed..0000000000 --- a/Unmapped-Spigot-Server-Patches/0691-Item-Rarity-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 12 Mar 2021 17:09:42 -0800 -Subject: [PATCH] Item Rarity API - - -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 467121839b94e09f59c64300de9f26d3c6caf1e5..f7758ee4aa8bbb31a80ec2e331b3fd3c55069808 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -45,7 +45,7 @@ public class Item implements IMaterial { - protected static final UUID g = UUID.fromString("FA233E1C-4180-4865-B01B-BCCE9785ACA3"); - protected static final Random RANDOM = new Random(); - protected final CreativeModeTab i; -- private final EnumItemRarity a; -+ private final EnumItemRarity a; public final EnumItemRarity getItemRarity() { return a; } // Paper - OBFHELPER - private final int maxStackSize; - private final int durability; - private final boolean d; -@@ -209,6 +209,7 @@ public class Item implements IMaterial { - return itemstack.hasEnchantments(); - } - -+ public EnumItemRarity getItemStackRarity(ItemStack itemStack) { return i(itemStack); } // Paper - OBFHELPER - public EnumItemRarity i(ItemStack itemstack) { - if (!itemstack.hasEnchantments()) { - return this.a; -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 848a704fa100c39098a5716bb25b6a9ed85d7a8c..de6a9d795ebaf9c608944415c7dc18c6aee23245 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -472,6 +472,20 @@ public final class CraftMagicNumbers implements UnsafeValues { - public int nextEntityId() { - return net.minecraft.world.entity.Entity.nextEntityId(); - } -+ -+ @Override -+ public io.papermc.paper.inventory.ItemRarity getItemRarity(org.bukkit.Material material) { -+ Item item = getItem(material); -+ if (item == null) { -+ throw new IllegalArgumentException(material + " is not an item, and rarity does not apply to blocks"); -+ } -+ return io.papermc.paper.inventory.ItemRarity.values()[item.getItemRarity().ordinal()]; -+ } -+ -+ @Override -+ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { -+ return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; -+ } - // Paper end - - /** diff --git a/Unmapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/Unmapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch deleted file mode 100644 index 61d73b8e95..0000000000 --- a/Unmapped-Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Fri, 19 Mar 2021 16:07:21 -0700 -Subject: [PATCH] Only set despawnTimer for Wandering Traders spawned by - MobSpawnerTrader - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index f2cf33d42839710a3bbdf0c8ea0be28af6fcb19d..80c229c1852199fda85c03453d64cae33e413e89 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -319,6 +319,12 @@ public class EntityTypes { - - @Nullable - public T spawnCreature(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ // Paper start - add consumer to modify entity before spawn -+ return this.spawnCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1, spawnReason, null); -+ } -+ @Nullable -+ public T spawnCreature(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason, @Nullable java.util.function.Consumer op) { -+ // Paper end - // Paper start - Call PreCreatureSpawnEvent - org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(this).getKey()); - if (type != null) { -@@ -334,6 +340,7 @@ public class EntityTypes { - } - // Paper end - T t0 = this.createCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); -+ if (t0 != null && op != null) op.accept(t0); // Paper - - if (t0 != null) { - worldserver.addAllEntities(t0, spawnReason); -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -index 4f81a97b1451fec0bb5fd1479acad97846c40c7c..37e1b2bf33510c3603efadf219b462e667f573c2 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -@@ -62,7 +62,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - public EntityVillagerTrader(EntityTypes entitytypes, World world) { - super(entitytypes, world); - this.attachedToPlayer = true; -- this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader -+ //this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set. - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -index e57938b4591bb103b9dd0d0145a62b5a901f2c63..7c8a2151be8a0f48cba1c15d231d5dbdb500b4d6 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -@@ -114,7 +114,7 @@ public class MobSpawnerTrader implements MobSpawner { - return false; - } - -- EntityVillagerTrader entityvillagertrader = (EntityVillagerTrader) EntityTypes.WANDERING_TRADER.spawnCreature(worldserver, (NBTTagCompound) null, (IChatBaseComponent) null, (EntityHuman) null, blockposition2, EnumMobSpawn.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit -+ EntityVillagerTrader entityvillagertrader = EntityTypes.WANDERING_TRADER.spawnCreature(worldserver, null, null, null, blockposition2, EnumMobSpawn.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, trader -> trader.setDespawnDelay(48000)); // CraftBukkit // Paper - set despawnTimer before spawn events called - - if (entityvillagertrader != null) { - for (int i = 0; i < 2; ++i) { diff --git a/Unmapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch b/Unmapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch deleted file mode 100644 index 25bfef8508..0000000000 --- a/Unmapped-Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 23 Mar 2021 06:43:30 +0000 -Subject: [PATCH] copy TESign#isEditable from snapshots - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -index f4b601277ef75e5bc39d541a0d13c6eed3b1ef2c..f7e2e23e7468928b6bd6961f223c50ca2826a813 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -@@ -110,6 +110,7 @@ public class CraftSign extends CraftBlockEntityState implements - } - // Paper end - } -+ sign.isEditable = getSnapshot().isEditable; // Paper - copy manually - } - - // Paper start diff --git a/Unmapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch b/Unmapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch deleted file mode 100644 index 06a6b95c91..0000000000 --- a/Unmapped-Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dmitry Sidorov -Date: Thu, 4 Feb 2021 20:32:01 +0300 -Subject: [PATCH] Drop carried item when player has disconnected - -Fixes disappearance of held items, when a player gets disconnected and PlayerDropItemEvent is cancelled. -Closes #5036 - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 484c7cea458dda38e4816fe5f1c05c6836fa38b9..b257d58a298e82f255b09e9575ee42a56a4b7cee 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -79,6 +79,7 @@ import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.npc.EntityVillagerAbstract; - import net.minecraft.world.entity.player.EntityHuman; -+import net.minecraft.world.item.ItemStack; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.GameRules; -@@ -609,6 +610,14 @@ public abstract class PlayerList { - } - // Paper end - -+ // Paper - Drop carried item when player has disconnected -+ if (!entityplayer.inventory.getCarried().isEmpty()) { -+ ItemStack carried = entityplayer.inventory.getCarried(); -+ entityplayer.inventory.setCarried(ItemStack.NULL_ITEM); -+ entityplayer.drop(carried, false); -+ } -+ // Paper end -+ - this.savePlayerFile(entityplayer); - if (entityplayer.isPassenger()) { - Entity entity = entityplayer.getRootVehicle(); diff --git a/Unmapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch b/Unmapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch deleted file mode 100644 index 70f01cbb40..0000000000 --- a/Unmapped-Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sat, 27 Mar 2021 09:24:23 +0100 -Subject: [PATCH] forced whitelist: use configurable kick message - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 879074df54e56a9275957a83c92b467094e95cd4..b3ebf5cd59c827b7426069eda0cb3d47b4386792 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2042,7 +2042,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Mon, 29 Mar 2021 09:07:25 +0200 -Subject: [PATCH] Make sure to remove correct TE during TE tick - -This looks like it can cause premature TE removal. - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 78dcba08d6d796d5d97c8304bf1f1e7d1e650d5d..6581fe0d93a5c2e7b444a44c01726e02d4a28e63 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -895,7 +895,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - //this.tileEntityList.remove(tileentity); // Paper - remove unused list - // Paper - prevent double chunk lookups - Chunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getPosition())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again -- chunk.removeTileEntity(tileentity.getPosition()); -+ chunk.removeTileEntity(tileentity.getPosition(), tileentity); // Paper - remove correct TE - } - // Paper end - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 34a9f7b2f998f77b1279516cd09397ab6c2ac1cc..0727b12b5ff146b4efa9204bf4f495f2f1aa20b9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -819,10 +819,18 @@ public class Chunk implements IChunkAccess { - - @Override - public void removeTileEntity(BlockPosition blockposition) { -+ // Paper start - remove correct TE -+ removeTileEntity(blockposition, null); -+ } -+ public void removeTileEntity(BlockPosition blockposition, TileEntity match) { -+ // Paper end - if (this.loaded || this.world.s_()) { -- TileEntity tileentity = (TileEntity) this.tileEntities.remove(blockposition); -+ // Paper start -+ TileEntity tileentity = (TileEntity) this.tileEntities.get(blockposition); - -- if (tileentity != null) { -+ if (tileentity != null && (match == null || match == tileentity)) { -+ this.tileEntities.remove(blockposition); -+ // Paper end - tileentity.al_(); - } - } diff --git a/Unmapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/Unmapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch deleted file mode 100644 index 2dc26ac6f5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Mon, 5 Apr 2021 18:35:15 -0700 -Subject: [PATCH] Don't ignore result of PlayerEditBookEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 7d584e6d7b4e7b27ca0d51e0eb52a47169aa4b58..ed1e24f12590b8c37d2bd8e234f043bc30dd6cc8 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1146,7 +1146,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - list.stream().map(NBTTagString::a).forEach(nbttaglist::add); - ItemStack old = itemstack.cloneItemStack(); // CraftBukkit - itemstack.a("pages", (NBTBase) nbttaglist); -- CraftEventFactory.handleEditBookEvent(player, i, old, itemstack); // CraftBukkit -+ this.player.inventory.setItem(i, CraftEventFactory.handleEditBookEvent(player, i, old, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch b/Unmapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch deleted file mode 100644 index 099ef07a97..0000000000 --- a/Unmapped-Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sat, 27 Mar 2021 11:13:30 +0100 -Subject: [PATCH] fix cancelling block falling causing client desync - - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 62d8b53c024888aa43b8fddf8a475dfb8284a4cc..2a61c24dd26edf4c72e977c6024fe233bab08a2f 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -14,6 +14,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; - import net.minecraft.tags.TagsFluid; -@@ -43,6 +44,7 @@ import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.Vec3D; - -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit - - public class EntityFallingBlock extends Entity { -@@ -116,8 +118,18 @@ public class EntityFallingBlock extends Entity { - - if (this.ticksLived++ == 0) { - blockposition = this.getChunkCoordinates(); -- if (this.world.getType(blockposition).a(block) && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { -- this.world.a(blockposition, false); -+ // Paper start - fix cancelling block falling causing client desync -+ if (this.world.getType(blockposition).isSameInstance(block)) { -+ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { -+ if (this.world.getType(blockposition).isSameInstance(block)) { //if listener didn't update the block -+ ((WorldServer) world).getChunkProvider().flagDirty(blockposition); -+ } -+ this.die(); -+ return; -+ } else { -+ this.world.setAir(blockposition, false); -+ } -+ // Paper end - fix cancelling block falling causing client desync - } else if (!this.world.isClientSide) { - this.die(); - return; -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 3fdafc0ff0c4148ec844dbdc1455d17cdcb4a75a..0d26250887f80d0c250bcd6bc7de303362427d3e 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -683,6 +683,7 @@ public abstract class BlockBase { - return this.getBlock().a(tag) && predicate.test(this); - } - -+ public final boolean isSameInstance(Block block) { return a(block); } // Paper - OBFHELPER - public boolean a(Block block) { - return this.getBlock().a(block); - } diff --git a/Unmapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch b/Unmapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch deleted file mode 100644 index 529b859804..0000000000 --- a/Unmapped-Spigot-Server-Patches/0699-Expose-protocol-version.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Fri, 26 Mar 2021 11:23:17 +0100 -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 de6a9d795ebaf9c608944415c7dc18c6aee23245..697949abbe662a55fc31ad811863717e35b9d1b6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -486,6 +486,11 @@ public final class CraftMagicNumbers implements UnsafeValues { - public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { - return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; - } -+ -+ @Override -+ public int getProtocolVersion() { -+ return net.minecraft.SharedConstants.getGameVersion().getProtocolVersion(); -+ } - // Paper end - - /** diff --git a/Unmapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/Unmapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch deleted file mode 100644 index 069a5fb10f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Thu, 1 Apr 2021 00:34:02 -0700 -Subject: [PATCH] Allow for Component suggestion tooltips in - AsyncTabCompleteEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index ed1e24f12590b8c37d2bd8e234f043bc30dd6cc8..a0d48ef2b27267da0864baa9059c7c3e5aef6f48 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -771,12 +771,11 @@ public class PlayerConnection implements PacketListenerPlayIn { - - // Paper start - async tab completion - com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -- java.util.List completions = new java.util.ArrayList<>(); - String buffer = packetplayintabcomplete.c(); -- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), - buffer, true, null); - event.callEvent(); -- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ java.util.List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); - // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server - if (!event.isHandled()) { - if (!event.isCancelled()) { -@@ -795,10 +794,16 @@ public class PlayerConnection implements PacketListenerPlayIn { - }); - } - } else if (!completions.isEmpty()) { -- com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); -+ com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); - -- builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); -- completions.forEach(builder::suggest); -+ final com.mojang.brigadier.suggestion.SuggestionsBuilder builder = builder0.createOffset(builder0.getInput().lastIndexOf(' ') + 1); -+ completions.forEach(completion -> { -+ if (completion.tooltip() == null) { -+ builder.suggest(completion.suggestion()); -+ } else { -+ builder.suggest(completion.suggestion(), PaperAdventure.asVanilla(completion.tooltip())); -+ } -+ }); - com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); - com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); - suggestEvent.setCancelled(suggestions.isEmpty()); -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index c5e00bd9e2790992202aadf8eec2002fc88c78f1..dd8e87ad192c19743577bb95253a127072ea196c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -29,34 +29,56 @@ public class ConsoleCommandCompleter implements Completer { - final CraftServer server = this.server.server; - final String buffer = line.line(); - // Async Tab Complete -- com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -- java.util.List completions = new java.util.ArrayList<>(); -- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, -- buffer, true, null); -+ final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event = -+ new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), buffer, true, null); - event.callEvent(); -- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ final List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); - - if (event.isCancelled() || event.isHandled()) { - // Still fire sync event with the provided completions, if someone is listening - if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { -- List finalCompletions = completions; -+ List finalCompletions = new java.util.ArrayList<>(completions); - Waitable> syncCompletions = new Waitable>() { - @Override - protected List evaluate() { -- org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); -+ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, -+ finalCompletions.stream() -+ .map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::suggestion) -+ .collect(java.util.stream.Collectors.toList())); - return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); - } - }; - server.getServer().processQueue.add(syncCompletions); - try { -- completions = syncCompletions.get(); -+ final List legacyCompletions = syncCompletions.get(); -+ completions.removeIf(it -> !legacyCompletions.contains(it.suggestion())); // remove any suggestions that were removed -+ // add any new suggestions -+ for (final String completion : legacyCompletions) { -+ if (notNewSuggestion(completions, completion)) { -+ continue; -+ } -+ completions.add(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion(completion)); -+ } - } catch (InterruptedException | ExecutionException e1) { - e1.printStackTrace(); - } - } - - if (!completions.isEmpty()) { -- candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); -+ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { -+ if (completion.suggestion().isEmpty()) { -+ continue; -+ } -+ candidates.add(new Candidate( -+ completion.suggestion(), -+ completion.suggestion(), -+ null, -+ io.papermc.paper.adventure.PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null), -+ null, -+ null, -+ false -+ )); -+ } - } - return; - } -@@ -106,4 +128,15 @@ public class ConsoleCommandCompleter implements Completer { - Thread.currentThread().interrupt(); - } - } -+ -+ // Paper start -+ private boolean notNewSuggestion(final List completions, final String completion) { -+ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion it : completions) { -+ if (it.suggestion().equals(completion)) { -+ return true; -+ } -+ } -+ return false; -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch b/Unmapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch deleted file mode 100644 index 9b4a89bc49..0000000000 --- a/Unmapped-Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch +++ /dev/null @@ -1,316 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Tue, 30 Mar 2021 16:06:08 -0700 -Subject: [PATCH] Enhance console tab completions for brigadier commands - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index c56e7fb18f9a56c8025eb70a524f028b5942da37..efc1e42d606e1c9feb1a4871c0714933ae92a1b2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -479,4 +479,11 @@ public class PaperConfig { - private static void fixEntityPositionDesync() { - fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); - } -+ -+ public static boolean enableBrigadierConsoleHighlighting = true; -+ public static boolean enableBrigadierConsoleCompletions = true; -+ private static void consoleSettings() { -+ enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); -+ enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -index 89eeb9d202405747409e65fcf226d95379987e29..ad87b575a0261200b280884e054a59e3ce59c41c 100644 ---- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -+++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -@@ -1,5 +1,7 @@ - package com.destroystokyo.paper.console; - -+import com.destroystokyo.paper.PaperConfig; -+import io.papermc.paper.console.BrigadierCommandHighlighter; - import net.minecraft.server.dedicated.DedicatedServer; - import net.minecrell.terminalconsole.SimpleTerminalConsole; - import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; -@@ -16,11 +18,15 @@ public final class PaperConsole extends SimpleTerminalConsole { - - @Override - protected LineReader buildReader(LineReaderBuilder builder) { -- return super.buildReader(builder -+ builder - .appName("Paper") - .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) - .completer(new ConsoleCommandCompleter(this.server)) -- ); -+ .option(LineReader.Option.COMPLETE_IN_WORD, true); -+ if (PaperConfig.enableBrigadierConsoleHighlighting) { -+ builder.highlighter(new BrigadierCommandHighlighter(this.server, this.server.getServerCommandListener())); -+ } -+ return super.buildReader(builder); - } - - @Override -diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..edd231d95a04a1c4832f1ca8a3da6a56e9472ca1 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java -@@ -0,0 +1,95 @@ -+package io.papermc.paper.console; -+ -+import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion; -+import com.mojang.brigadier.CommandDispatcher; -+import com.mojang.brigadier.ParseResults; -+import com.mojang.brigadier.StringReader; -+import com.mojang.brigadier.suggestion.Suggestion; -+import io.papermc.paper.adventure.PaperAdventure; -+import net.minecraft.commands.CommandListenerWrapper; -+import net.minecraft.network.chat.ChatComponentUtils; -+import net.minecraft.server.dedicated.DedicatedServer; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.jline.reader.Candidate; -+import org.jline.reader.LineReader; -+import org.jline.reader.ParsedLine; -+ -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+ -+import static com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion; -+ -+public final class BrigadierCommandCompleter { -+ private final CommandListenerWrapper commandSourceStack; -+ private final DedicatedServer server; -+ -+ public BrigadierCommandCompleter(final @NonNull DedicatedServer server, final @NonNull CommandListenerWrapper commandSourceStack) { -+ this.server = server; -+ this.commandSourceStack = commandSourceStack; -+ } -+ -+ public void complete(final @NonNull LineReader reader, final @NonNull ParsedLine line, final @NonNull List candidates, final @NonNull List existing) { -+ if (!com.destroystokyo.paper.PaperConfig.enableBrigadierConsoleCompletions) { -+ this.addCandidates(candidates, Collections.emptyList(), existing); -+ return; -+ } -+ final CommandDispatcher dispatcher = this.server.getCommandDispatcher().dispatcher(); -+ final ParseResults results = dispatcher.parse(prepareStringReader(line.line()), this.commandSourceStack); -+ this.addCandidates( -+ candidates, -+ dispatcher.getCompletionSuggestions(results, line.cursor()).join().getList(), -+ existing -+ ); -+ } -+ -+ private void addCandidates( -+ final @NonNull List candidates, -+ final @NonNull List brigSuggestions, -+ final @NonNull List existing -+ ) { -+ final List completions = new ArrayList<>(); -+ brigSuggestions.forEach(it -> completions.add(toCompletion(it))); -+ for (final Completion completion : existing) { -+ if (completion.suggestion().isEmpty() || brigSuggestions.stream().anyMatch(it -> it.getText().equals(completion.suggestion()))) { -+ continue; -+ } -+ completions.add(completion); -+ } -+ for (final Completion completion : completions) { -+ if (completion.suggestion().isEmpty()) { -+ continue; -+ } -+ candidates.add(toCandidate(completion)); -+ } -+ } -+ -+ private static @NonNull Candidate toCandidate(final @NonNull Completion completion) { -+ final String suggestionText = completion.suggestion(); -+ final String suggestionTooltip = PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null); -+ return new Candidate( -+ suggestionText, -+ suggestionText, -+ null, -+ suggestionTooltip, -+ null, -+ null, -+ false -+ ); -+ } -+ -+ private static @NonNull Completion toCompletion(final @NonNull Suggestion suggestion) { -+ if (suggestion.getTooltip() == null) { -+ return completion(suggestion.getText()); -+ } -+ return completion(suggestion.getText(), PaperAdventure.asAdventure(ChatComponentUtils.fromMessage(suggestion.getTooltip()))); -+ } -+ -+ static @NonNull StringReader prepareStringReader(final @NonNull String line) { -+ final StringReader stringReader = new StringReader(line); -+ if (stringReader.canRead() && stringReader.peek() == '/') { -+ stringReader.skip(); -+ } -+ return stringReader; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d51d20a6d1c0c956cdf425503a6c1401acd9c854 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java -@@ -0,0 +1,57 @@ -+package io.papermc.paper.console; -+ -+import com.mojang.brigadier.ParseResults; -+import com.mojang.brigadier.context.ParsedCommandNode; -+import com.mojang.brigadier.tree.LiteralCommandNode; -+import net.minecraft.commands.CommandListenerWrapper; -+import net.minecraft.server.dedicated.DedicatedServer; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.jline.reader.Highlighter; -+import org.jline.reader.LineReader; -+import org.jline.utils.AttributedString; -+import org.jline.utils.AttributedStringBuilder; -+import org.jline.utils.AttributedStyle; -+ -+public final class BrigadierCommandHighlighter implements Highlighter { -+ private static final int[] COLORS = {AttributedStyle.CYAN, AttributedStyle.YELLOW, AttributedStyle.GREEN, AttributedStyle.MAGENTA, /* Client uses GOLD here, not BLUE, however there is no GOLD AttributedStyle. */ AttributedStyle.BLUE}; -+ private final CommandListenerWrapper commandSourceStack; -+ private final DedicatedServer server; -+ -+ public BrigadierCommandHighlighter(final @NonNull DedicatedServer server, final @NonNull CommandListenerWrapper commandSourceStack) { -+ this.server = server; -+ this.commandSourceStack = commandSourceStack; -+ } -+ -+ @Override -+ public AttributedString highlight(final @NonNull LineReader reader, final @NonNull String buffer) { -+ final AttributedStringBuilder builder = new AttributedStringBuilder(); -+ final ParseResults results = this.server.getCommandDispatcher().dispatcher().parse(BrigadierCommandCompleter.prepareStringReader(buffer), this.commandSourceStack); -+ int pos = 0; -+ if (buffer.startsWith("/")) { -+ builder.append("/", AttributedStyle.DEFAULT); -+ pos = 1; -+ } -+ int component = -1; -+ for (final ParsedCommandNode node : results.getContext().getLastChild().getNodes()) { -+ if (node.getRange().getStart() >= buffer.length()) { -+ break; -+ } -+ final int start = node.getRange().getStart(); -+ final int end = Math.min(node.getRange().getEnd(), buffer.length()); -+ builder.append(buffer.substring(pos, start), AttributedStyle.DEFAULT); -+ if (node.getNode() instanceof LiteralCommandNode) { -+ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT); -+ } else { -+ if (++component >= COLORS.length) { -+ component = 0; -+ } -+ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT.foreground(COLORS[component])); -+ } -+ pos = end; -+ } -+ if (pos < buffer.length()) { -+ builder.append((buffer.substring(pos)), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)); -+ } -+ return builder.toAttributedString(); -+ } -+} -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index 978d3b79b5f953e67263598dff09bcb40b6e3f31..47dc8450fff5583d70c969c0b92b96a665a02305 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -440,7 +440,7 @@ public class CommandDispatcher { - }; - } - -- public com.mojang.brigadier.CommandDispatcher a() { -+ public com.mojang.brigadier.CommandDispatcher a() { return this.dispatcher(); } public com.mojang.brigadier.CommandDispatcher dispatcher() { // Paper - OBFHELPER - return this.b; - } - -diff --git a/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java b/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java -index b00e5d811ddfa12937f57bac4debb2fdd057d6e1..d14e4bf09bc43e78a9da07ea062ed886d27c7cc0 100644 ---- a/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java -+++ b/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java -@@ -90,7 +90,7 @@ public class ChatComponentUtils { - ChatComponentText chatcomponenttext = new ChatComponentText(""); - boolean flag = true; - -- for (Iterator iterator = collection.iterator(); iterator.hasNext(); flag = false) { -+ for (Iterator iterator = collection.iterator(); iterator.hasNext(); flag = false) { // Paper - decompile fix - T t0 = iterator.next(); - - if (!flag) { -@@ -108,7 +108,7 @@ public class ChatComponentUtils { - return new ChatMessage("chat.square_brackets", new Object[]{ichatbasecomponent}); - } - -- public static IChatBaseComponent a(Message message) { -+ public static IChatBaseComponent a(Message message) { return fromMessage(message); } public static IChatBaseComponent fromMessage(final @org.checkerframework.checker.nullness.qual.NonNull Message message) { // Paper - OBFHELPER - return (IChatBaseComponent) (message instanceof IChatBaseComponent ? (IChatBaseComponent) message : new ChatComponentText(message.getString())); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index dd8e87ad192c19743577bb95253a127072ea196c..5e1312941f9a554fc83adc02e81980069b8d015d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -18,9 +18,11 @@ import org.bukkit.event.server.TabCompleteEvent; - - public class ConsoleCommandCompleter implements Completer { - private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer -+ private final io.papermc.paper.console.BrigadierCommandCompleter brigadierCompleter; // Paper - - public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer - this.server = server; -+ this.brigadierCompleter = new io.papermc.paper.console.BrigadierCommandCompleter(this.server, this.server.getServerCommandListener()); // Paper - } - - // Paper start - Change method signature for JLine update -@@ -64,7 +66,7 @@ public class ConsoleCommandCompleter implements Completer { - } - } - -- if (!completions.isEmpty()) { -+ if (false && !completions.isEmpty()) { - for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { - if (completion.suggestion().isEmpty()) { - continue; -@@ -80,6 +82,7 @@ public class ConsoleCommandCompleter implements Completer { - )); - } - } -+ this.addCompletions(reader, line, candidates, completions); - return; - } - -@@ -99,10 +102,12 @@ public class ConsoleCommandCompleter implements Completer { - try { - List offers = waitable.get(); - if (offers == null) { -+ this.addCompletions(reader, line, candidates, Collections.emptyList()); // Paper - return; // Paper - Method returns void - } - - // Paper start - JLine update -+ /* - for (String completion : offers) { - if (completion.isEmpty()) { - continue; -@@ -110,6 +115,8 @@ public class ConsoleCommandCompleter implements Completer { - - candidates.add(new Candidate(completion)); - } -+ */ -+ this.addCompletions(reader, line, candidates, offers.stream().map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::completion).collect(java.util.stream.Collectors.toList())); - // Paper end - - // Paper start - JLine handles cursor now -@@ -138,5 +145,9 @@ public class ConsoleCommandCompleter implements Completer { - } - return false; - } -+ -+ private void addCompletions(final LineReader reader, final ParsedLine line, final List candidates, final List existing) { -+ this.brigadierCompleter.complete(reader, line, candidates, existing); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/Unmapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch deleted file mode 100644 index 05cbf1582f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Fri, 19 Mar 2021 00:33:15 -0500 -Subject: [PATCH] Fix PlayerItemConsumeEvent cancelling properly - -When the active item is not cleared, the item is still readied -for use and will repeatedly trigger the PlayerItemConsumeEvent -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/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 78d874c44cf8311af06b085db12fbe0cacd6cf7d..2657dd71213455e2da3a4ff4d338a33896ffe855 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3351,6 +3351,7 @@ public abstract class EntityLiving extends Entity { - world.getServer().getPluginManager().callEvent(event); - - if (event.isCancelled()) { -+ this.clearActiveItem(); // Paper - event is using an item, clear active item to reset its use - // Update client - ((EntityPlayer) this).getBukkitEntity().updateInventory(); - ((EntityPlayer) this).getBukkitEntity().updateScaledHealth(); diff --git a/Unmapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch b/Unmapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch deleted file mode 100644 index b28224aedf..0000000000 --- a/Unmapped-Spigot-Server-Patches/0703-Add-bypass-host-check.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 18 Apr 2021 21:27:01 +0100 -Subject: [PATCH] Add bypass host check - -Paper.bypassHostCheck - -Seriously, fix your firewalls. -.- - -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 26fe1f612e9dab37e5bf6bc431eb362bd7e4803a..74006c0af831c0e6a2b84b3638e397ab54984dc5 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -30,6 +30,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - private static final IChatBaseComponent a = new ChatComponentText("Ignoring status request"); - private final MinecraftServer b; - private final NetworkManager c; final NetworkManager getNetworkManager() { return this.c; } // Paper - OBFHELPER -+ private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper - - public HandshakeListener(MinecraftServer minecraftserver, NetworkManager networkmanager) { - this.b = minecraftserver; -@@ -118,7 +119,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - // Spigot Start - //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! - String[] split = packethandshakinginsetprotocol.hostname.split("\00"); -- if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { -+ if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper - packethandshakinginsetprotocol.hostname = split[0]; - c.socketAddress = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) c.getSocketAddress()).getPort()); - c.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); diff --git a/Unmapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch b/Unmapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch deleted file mode 100644 index eb77500117..0000000000 --- a/Unmapped-Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 20 Apr 2021 01:15:04 +0100 -Subject: [PATCH] don't throw when loading invalid TEs - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index f1e586754396439dfb70a4d63e3b8b34fb36ebf4..93d02ccb87c17404c55884f52ae40c7b7ddfb103 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.block.entity; - - import javax.annotation.Nullable; - import net.minecraft.CrashReportSystemDetails; -+import net.minecraft.ResourceKeyInvalidException; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; -@@ -133,7 +134,13 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public static TileEntity create(IBlockData iblockdata, NBTTagCompound nbttagcompound) { - String s = nbttagcompound.getString("id"); - -- return (TileEntity) IRegistry.BLOCK_ENTITY_TYPE.getOptional(new MinecraftKey(s)).map((tileentitytypes) -> { -+ // Paper -+ MinecraftKey minecraftKey = null; -+ try { -+ minecraftKey = new MinecraftKey(s); -+ } catch (ResourceKeyInvalidException ex) {} -+ // Paper end -+ return (TileEntity) IRegistry.BLOCK_ENTITY_TYPE.getOptional(minecraftKey).map((tileentitytypes) -> { - try { - return tileentitytypes.a(); - } catch (Throwable throwable) { diff --git a/Unmapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch b/Unmapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch deleted file mode 100644 index 25e0a9b5a8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Mon, 5 Apr 2021 16:58:20 -0400 -Subject: [PATCH] Set area affect cloud rotation - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index a152d5bec8bf0dd87239b0a3432fb589cea61bd8..42417aee4796d39d110e69cb707bd3b7bac30027 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1977,6 +1977,7 @@ public class CraftWorld implements World { - entity = EntityTypes.LIGHTNING_BOLT.a(world); - } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { - entity = new EntityAreaEffectCloud(world, x, y, z); -+ entity.setPositionRotation(x, y, z, yaw, pitch); // Paper - Set area effect cloud Rotation - } else if (EvokerFangs.class.isAssignableFrom(clazz)) { - entity = new EntityEvokerFangs(world, x, y, z, (float) Math.toRadians(yaw), 0, null); - } diff --git a/Unmapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch b/Unmapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch deleted file mode 100644 index fe93a5a26e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 8 Apr 2021 17:36:10 -0700 -Subject: [PATCH] add isDeeplySleeping 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 0a0e9df604723802fe65d871ff48aa9fd9b756bf..6e28e0247200fbbc470ba317575f0c714f74d5bf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -123,6 +123,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - } - } - -+ // Paper start -+ @Override -+ public boolean isDeeplySleeping() { -+ return getHandle().isDeeplySleeping(); -+ } -+ // Paper end -+ - @Override - public int getSleepTicks() { - return getHandle().sleepTicks; diff --git a/Unmapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch b/Unmapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch deleted file mode 100644 index cee651ba1d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alphaesia -Date: Fri, 23 Apr 2021 09:57:56 +1200 -Subject: [PATCH] Fix duplicating /give items on item drop cancel - -Fixes SPIGOT-2942 (Give command fires PlayerDropItemEvent, cancelling it causes item duplication). - -For every stack of items to give, /give puts the item stack straight -into the player's inventory. However, it also summons a "fake item" -at the player's location. When the PlayerDropItemEvent for this fake -item is cancelled, the server attempts to put the item back into the -player's inventory. The result is that the fake item, which is never -meant to be obtained, is combined with the real items injected directly -into the player's inventory. This means more items than the amount -specified in /give are given to the player - one for every stack of -items given. (e.g. /give @s dirt 1 gives you 2 dirt). - -While this isn't a big issue for general building usage, it can affect -e.g. adventure maps where the number of items the player receives is -important (and you want to restrict the player from throwing items). - -If there are any overflow items that didn't make it into the inventory -(insufficient space), those items are dropped as a real item instead -of a fake one. While cancelling this drop would also result in the -server attempting to put those items into the inventory, since it is -full this has no effect. - -Just ignoring cancellation of the PlayerDropItemEvent seems like the -cleanest and least intrusive way to fix it. - -diff --git a/src/main/java/net/minecraft/server/commands/CommandGive.java b/src/main/java/net/minecraft/server/commands/CommandGive.java -index 6685bf1757458d908e32d4069f7a8a22a28c28d7..a10207f7cb9455e29db7e6906cb2138ad5609a1f 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandGive.java -+++ b/src/main/java/net/minecraft/server/commands/CommandGive.java -@@ -49,7 +49,7 @@ public class CommandGive { - - if (flag && itemstack.isEmpty()) { - itemstack.setCount(1); -- entityitem = entityplayer.drop(itemstack, false); -+ entityitem = entityplayer.drop(itemstack, false, false, true); // Paper - Fix duplicating /give items on item drop cancel - if (entityitem != null) { - entityitem.s(); - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index ec0956a98c133bcd3d4f92f696c667eab6ff98f1..3a62bde04d7fbb6c571cfef11d4f6891e11c7ac8 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -642,6 +642,13 @@ public abstract class EntityHuman extends EntityLiving { - - @Nullable - public EntityItem a(ItemStack itemstack, boolean flag, boolean flag1) { -+ // Paper start - Fix duplicating /give items on item drop cancel -+ return this.drop(itemstack, flag, flag1, false); -+ } -+ -+ @Nullable -+ public EntityItem drop(ItemStack itemstack, boolean flag, boolean flag1, boolean alwaysSucceed) { -+ // Paper end - if (itemstack.isEmpty()) { - return null; - } else { -@@ -683,7 +690,7 @@ public abstract class EntityHuman extends EntityLiving { - PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); - this.world.getServer().getPluginManager().callEvent(event); - -- if (event.isCancelled()) { -+ if (event.isCancelled() && !alwaysSucceed) { // Paper - Fix duplicating /give items on item drop cancel - org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); - if (flag1 && (cur == null || cur.getAmount() == 0)) { - // The complete stack was dropped diff --git a/Unmapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch b/Unmapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch deleted file mode 100644 index 410ceaf296..0000000000 --- a/Unmapped-Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 16:45:28 -0700 -Subject: [PATCH] add consumeFuel to FurnaceBurnEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index 1997139fb87dc1947acfdf02e1f116577c3fa943..9ce19b89c16eb6edd3d5d5cc87a966a37f66895c 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -331,7 +331,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - if (this.isBurning() && furnaceBurnEvent.isBurning()) { - // CraftBukkit end - flag1 = true; -- if (!itemstack.isEmpty()) { -+ if (!itemstack.isEmpty() && furnaceBurnEvent.willConsumeFuel()) { // Paper - Item item = itemstack.getItem(); - - itemstack.subtract(1); diff --git a/Unmapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch b/Unmapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch deleted file mode 100644 index c205b0e09c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 00:28:11 -0700 -Subject: [PATCH] add get-set drop chance to EntityEquipment - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -index 27e0e2767b11195231055f64446afb7ae5e08988..064d8adb47404b0fb839cfa646dfe04f2a2eefb6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -@@ -245,6 +245,17 @@ public class CraftEntityEquipment implements EntityEquipment { - public void setBootsDropChance(float chance) { - setDropChance(EnumItemSlot.FEET, chance); - } -+ // Paper start -+ @Override -+ public float getDropChance(EquipmentSlot slot) { -+ return getDropChance(CraftEquipmentSlot.getNMS(slot)); -+ } -+ -+ @Override -+ public void setDropChance(EquipmentSlot slot, float chance) { -+ setDropChance(CraftEquipmentSlot.getNMS(slot), chance); -+ } -+ // Paper end - - private void setDropChance(EnumItemSlot slot, float chance) { - if (slot == EnumItemSlot.MAINHAND || slot == EnumItemSlot.OFFHAND) { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -index b812e1af411dd7f4509620b6b49b7897603dc970..dacb8e127403ef5234d6bca62aa4a35431724e9e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -@@ -354,4 +354,15 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i - public void setBootsDropChance(float chance) { - throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); - } -+ // Paper start -+ @Override -+ public float getDropChance(EquipmentSlot slot) { -+ return 1; -+ } -+ -+ @Override -+ public void setDropChance(EquipmentSlot slot, float chance) { -+ throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch b/Unmapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch deleted file mode 100644 index 532dace60c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Thu, 18 Mar 2021 21:38:01 +0100 -Subject: [PATCH] fix PigZombieAngerEvent cancellation - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -index 59ea1432152051ce8a60c0a526db787593f0e744..1212c8e2af1f7e658d8bec7e5474a35190b1949e 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -@@ -28,6 +28,7 @@ public abstract class PathfinderGoal { - - public void c() { this.start(); } public void start() {} // Paper - OBFHELPER - -+ public final void onTaskResetObfHelper() { d(); } // Paper - OBFHELPER - public void d() { - onTaskReset(); // Paper - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -index cc1bff409cad2eb6264d4b691599576960080ccd..d10d1b768601236b9892461ee41d61c7239d1a07 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -@@ -49,6 +49,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { - private UUID br; - private static final IntRange bs = TimeRange.a(4, 6); - private int bt; -+ private PathfinderGoalHurtByTarget pathfinderGoalHurtByTarget; // Paper - - public EntityPigZombie(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -69,7 +70,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { - protected void m() { - this.goalSelector.a(2, new PathfinderGoalZombieAttack(this, 1.0D, false)); - this.goalSelector.a(7, new PathfinderGoalRandomStrollLand(this, 1.0D)); -- this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this).a(new Class[0])); // CraftBukkit - decompile error -+ this.targetSelector.a(1, pathfinderGoalHurtByTarget = new PathfinderGoalHurtByTarget(this).a(new Class[0])); // CraftBukkit - decompile error // Paper - assign field - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_)); - this.targetSelector.a(3, new PathfinderGoalUniversalAngerReset<>(this, true)); - } -@@ -172,6 +173,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { - this.world.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - this.setAngerTarget(null); -+ pathfinderGoalHurtByTarget.onTaskResetObfHelper(); // Paper - clear goalTargets to fix cancellation - return; - } - this.setAnger(event.getNewAnger()); diff --git a/Unmapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch b/Unmapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch deleted file mode 100644 index 0a4779d24e..0000000000 --- a/Unmapped-Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Sun, 4 Apr 2021 14:25:04 -0400 -Subject: [PATCH] Fix checkReach check for Shulker boxes - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java b/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java -index fdc47411aa3e0e27d3a20c18274fef0a0db9a5b1..6ef70e209a8e282f7c00d80678636c2b8aa49b7a 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java -@@ -65,6 +65,7 @@ public class ContainerShulkerBox extends Container { - - @Override - public boolean canUse(EntityHuman entityhuman) { -+ if (!this.checkReachable) return true; // Paper - Add reachable override for ContainerShulkerBox - return this.c.a(entityhuman); - } - diff --git a/Unmapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch b/Unmapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch deleted file mode 100644 index 83d6c945b5..0000000000 --- a/Unmapped-Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Thu, 22 Apr 2021 19:02:07 -0700 -Subject: [PATCH] fix PlayerItemHeldEvent firing twice - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java -index d68f3e6b35f0af846c8a66710c5752508c095179..0e8ee44d0104ca7c666f57bdb54e0957935d5b34 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java -@@ -24,6 +24,7 @@ public class PacketPlayInHeldItemSlot implements Packet { - packetlistenerplayin.a(this); - } - -+ public int getItemInHandIndex() { return b(); } // Paper - OBFHELPER - public int b() { - return this.itemInHandIndex; - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index a0d48ef2b27267da0864baa9059c7c3e5aef6f48..957d3b56aea116f947ca8fb74127f652de72b701 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1909,6 +1909,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - PlayerConnectionUtils.ensureMainThread(packetplayinhelditemslot, this, this.player.getWorldServer()); - if (this.player.isFrozen()) return; // CraftBukkit - if (packetplayinhelditemslot.b() >= 0 && packetplayinhelditemslot.b() < PlayerInventory.getHotbarSize()) { -+ if (packetplayinhelditemslot.getItemInHandIndex() == this.player.inventory.itemInHandIndex) { return; } // Paper - don't fire itemheldevent when there wasn't a slot change - PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.itemInHandIndex, packetplayinhelditemslot.b()); - this.server.getPluginManager().callEvent(event); - if (event.isCancelled()) { diff --git a/Unmapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch b/Unmapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch deleted file mode 100644 index cf56b0987c..0000000000 --- a/Unmapped-Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 21 Apr 2021 15:58:19 -0700 -Subject: [PATCH] Added PlayerDeepSleepEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 3a62bde04d7fbb6c571cfef11d4f6891e11c7ac8..3a13e7a050db7f5c93d810afe56325495cec7aa4 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -235,6 +235,11 @@ public abstract class EntityHuman extends EntityLiving { - - if (this.isSleeping()) { - ++this.sleepTicks; -+ // Paper start -+ if (this.sleepTicks == 100) { -+ if (!new io.papermc.paper.event.player.PlayerDeepSleepEvent((Player) getBukkitEntity()).callEvent()) { this.sleepTicks = Integer.MIN_VALUE; } -+ } -+ // Paper end - if (this.sleepTicks > 100) { - this.sleepTicks = 100; - } diff --git a/Unmapped-Spigot-Server-Patches/0714-More-World-API.patch b/Unmapped-Spigot-Server-Patches/0714-More-World-API.patch deleted file mode 100644 index 5fbdab5402..0000000000 --- a/Unmapped-Spigot-Server-Patches/0714-More-World-API.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 7 Jul 2020 10:52:34 -0700 -Subject: [PATCH] More World API - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index fd204ab68d8245503c0a8c4e7ce1a0a6bac7d138..6aace2155258d8257d53ebfcb20c37ea7497c02c 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1869,6 +1869,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return !this.worldDataServer.getGeneratorSettings().shouldGenerateMapFeatures() ? null : this.getChunkProvider().getChunkGenerator().findNearestMapFeature(this, structuregenerator, blockposition, i, flag); // CraftBukkit - } - -+ public BlockPosition getNearestBiome(BiomeBase biomeBase, BlockPosition blockPosition, int radius, int step) { return this.a(biomeBase, blockPosition, radius, step); } // Paper - OBFHELPER - @Nullable - public BlockPosition a(BiomeBase biomebase, BlockPosition blockposition, int i, int j) { - return this.getChunkProvider().getChunkGenerator().getWorldChunkManager().a(blockposition.getX(), blockposition.getY(), blockposition.getZ(), i, j, (biomebase1) -> { -@@ -1891,6 +1892,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return this.savingDisabled; - } - -+ public IRegistryCustom getWorldCustomRegistry() { return r(); } // Paper - OBFHELPER - @Override - public IRegistryCustom r() { - return this.server.getCustomRegistry(); -diff --git a/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java b/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java -index 72bc1a1e1c2153550313e93cf7df901a514a9bef..be6d63bcf15027e02a0bfbee0792c24f2300b27e 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java -+++ b/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java -@@ -142,10 +142,10 @@ public class DimensionManager { - public static IRegistryCustom.Dimension a(IRegistryCustom.Dimension iregistrycustom_dimension) { - IRegistryWritable iregistrywritable = iregistrycustom_dimension.b(IRegistry.K); - -- iregistrywritable.a(DimensionManager.OVERWORLD, (Object) DimensionManager.OVERWORLD_IMPL, Lifecycle.stable()); -- iregistrywritable.a(DimensionManager.l, (Object) DimensionManager.m, Lifecycle.stable()); -- iregistrywritable.a(DimensionManager.THE_NETHER, (Object) DimensionManager.THE_NETHER_IMPL, Lifecycle.stable()); -- iregistrywritable.a(DimensionManager.THE_END, (Object) DimensionManager.THE_END_IMPL, Lifecycle.stable()); -+ iregistrywritable.a(DimensionManager.OVERWORLD, DimensionManager.OVERWORLD_IMPL, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.a(DimensionManager.l, DimensionManager.m, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.a(DimensionManager.THE_NETHER, DimensionManager.THE_NETHER_IMPL, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.a(DimensionManager.THE_END, DimensionManager.THE_END_IMPL, Lifecycle.stable()); // Paper - decompile fix - return iregistrycustom_dimension; - } - -@@ -164,10 +164,10 @@ public class DimensionManager { - public static RegistryMaterials a(IRegistry iregistry, IRegistry iregistry1, IRegistry iregistry2, long i) { - RegistryMaterials registrymaterials = new RegistryMaterials<>(IRegistry.M, Lifecycle.experimental()); - -- registrymaterials.a(WorldDimension.THE_NETHER, (Object) (new WorldDimension(() -> { -+ registrymaterials.a(WorldDimension.THE_NETHER, (new WorldDimension(() -> { // Paper - decompile fix - return (DimensionManager) iregistry.d(DimensionManager.THE_NETHER); - }, b(iregistry1, iregistry2, i))), Lifecycle.stable()); -- registrymaterials.a(WorldDimension.THE_END, (Object) (new WorldDimension(() -> { -+ registrymaterials.a(WorldDimension.THE_END, (new WorldDimension(() -> { // Paper - decompile fix - return (DimensionManager) iregistry.d(DimensionManager.THE_END); - }, a(iregistry1, iregistry2, i))), Lifecycle.stable()); - return registrymaterials; -@@ -256,6 +256,7 @@ public class DimensionManager { - return this.E[i]; - } - -+ public Tag getInfiniburnTag() { return o(); } // Paper - OBFHELPER - public Tag o() { - Tag tag = TagsBlock.a().a(this.infiniburn); - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 42417aee4796d39d110e69cb707bd3b7bac30027..3b3eda95c0ff8b129adedbae6561bba2d01c2f3a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2533,6 +2533,75 @@ public class CraftWorld implements World { - return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); - } - -+ // Paper start -+ @Override -+ public Location locateNearestBiome(Location origin, Biome biome, int radius) { -+ return this.locateNearestBiome(origin, biome, radius, 8); -+ } -+ -+ @Override -+ public Location locateNearestBiome(Location origin, Biome biome, int radius, int step) { -+ BlockPosition originPos = new BlockPosition(origin.getX(), origin.getY(), origin.getZ()); -+ BlockPosition nearest = getHandle().getNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().getWorldCustomRegistry().b(IRegistry.ay), biome), originPos, radius, step); -+ return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); -+ } -+ -+ @Override -+ public boolean isUltrawarm() { -+ return getHandle().getDimensionManager().isNether(); -+ } -+ -+ @Override -+ public boolean isNatural() { -+ return getHandle().getDimensionManager().isNatural(); -+ } -+ -+ @Override -+ public double getCoordinateScale() { -+ return getHandle().getDimensionManager().getCoordinateScale(); -+ } -+ -+ @Override -+ public boolean hasSkylight() { -+ return getHandle().getDimensionManager().hasSkyLight(); -+ } -+ -+ @Override -+ public boolean hasBedrockCeiling() { -+ return getHandle().getDimensionManager().hasSkyLight(); -+ } -+ -+ @Override -+ public boolean isPiglinSafe() { -+ return getHandle().getDimensionManager().isPiglinSafe(); -+ } -+ -+ @Override -+ public boolean doesBedWork() { -+ return getHandle().getDimensionManager().isBedWorks(); -+ } -+ -+ @Override -+ public boolean doesRespawnAnchorWork() { -+ return getHandle().getDimensionManager().isRespawnAnchorWorks(); -+ } -+ -+ @Override -+ public boolean hasRaids() { -+ return getHandle().getDimensionManager().hasRaids(); -+ } -+ -+ @Override -+ public boolean isFixedTime() { -+ return getHandle().getDimensionManager().isFixedTime(); -+ } -+ -+ @Override -+ public Collection getInfiniburn() { -+ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().getDimensionManager().getInfiniburnTag().getTagged().iterator(), CraftMagicNumbers::getMaterial)); -+ } -+ // Paper end -+ - @Override - public Raid locateNearestRaid(Location location, int radius) { - Validate.notNull(location, "Location cannot be null"); diff --git a/Unmapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch b/Unmapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch deleted file mode 100644 index 16189aeee4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 24 Dec 2020 12:27:41 -0800 -Subject: [PATCH] Added PlayerBedFailEnterEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 3a13e7a050db7f5c93d810afe56325495cec7aa4..c39c50e53549e9cb9d3520bc7e8b7e89cfa20163 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -2233,6 +2233,7 @@ public abstract class EntityHuman extends EntityLiving { - this.g = ichatbasecomponent; - } - -+ public @Nullable IChatBaseComponent getChatComponent() { return this.a(); }; // Paper - OBFHELPER - @Nullable - public IChatBaseComponent a() { - return this.g; -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBed.java b/src/main/java/net/minecraft/world/level/block/BlockBed.java -index eca84595342756e3550883551e487aaf79574fde..00a01a157deec004bcf2f8587723a0ecd0bfef85 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBed.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBed.java -@@ -43,6 +43,8 @@ import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.phys.shapes.VoxelShapeCollision; - import net.minecraft.world.phys.shapes.VoxelShapes; - import org.apache.commons.lang3.ArrayUtils; -+import io.papermc.paper.event.player.PlayerBedFailEnterEvent; // Paper -+import io.papermc.paper.adventure.PaperAdventure; // Paper - - public class BlockBed extends BlockFacingHorizontal implements ITileEntity { - -@@ -101,14 +103,23 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity { - BlockPosition finalblockposition = blockposition; - // CraftBukkit end - entityhuman.sleep(blockposition).ifLeft((entityhuman_enumbedresult) -> { -+ // Paper start - PlayerBedFailEnterEvent -+ if (entityhuman_enumbedresult != null) { -+ PlayerBedFailEnterEvent event = new PlayerBedFailEnterEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), PlayerBedFailEnterEvent.FailReason.VALUES[entityhuman_enumbedresult.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(world, finalblockposition), entityhuman_enumbedresult == EntityHuman.EnumBedResult.NOT_POSSIBLE_HERE, PaperAdventure.asAdventure(entityhuman_enumbedresult.getChatComponent())); -+ if (!event.callEvent()) { -+ return; -+ } -+ // Paper end - // CraftBukkit start - handling bed explosion from below here -- if (entityhuman_enumbedresult == EntityHuman.EnumBedResult.NOT_POSSIBLE_HERE) { -+ if (event.getWillExplode()) { // Paper - this.explodeBed(finaliblockdata, world, finalblockposition); - } else - // CraftBukkit end - if (entityhuman_enumbedresult != null) { -- entityhuman.a(entityhuman_enumbedresult.a(), true); -+ final net.kyori.adventure.text.Component message = event.getMessage(); // Paper -+ if(message != null) entityhuman.a(PaperAdventure.asVanilla(message), true); // Paper - } -+ } // Paper - - }); - return EnumInteractionResult.SUCCESS; diff --git a/Unmapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch b/Unmapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch deleted file mode 100644 index 4726476710..0000000000 --- a/Unmapped-Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Sat, 24 Apr 2021 02:09:32 -0700 -Subject: [PATCH] Implement methods to convert between Component and - Brigadier's Message - - -diff --git a/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fb1d6632788ae886b7a0e56fb490920c6ba2ce22 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java -@@ -0,0 +1,30 @@ -+package io.papermc.paper.brigadier; -+ -+import com.mojang.brigadier.Message; -+import io.papermc.paper.adventure.PaperAdventure; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.ComponentLike; -+import net.minecraft.network.chat.ChatComponentUtils; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+import static java.util.Objects.requireNonNull; -+ -+public enum PaperBrigadierProviderImpl implements PaperBrigadierProvider { -+ INSTANCE; -+ -+ PaperBrigadierProviderImpl() { -+ PaperBrigadierProvider.initialize(this); -+ } -+ -+ @Override -+ public @NonNull Message message(final @NonNull ComponentLike componentLike) { -+ requireNonNull(componentLike, "componentLike"); -+ return PaperAdventure.asVanilla(componentLike.asComponent()); -+ } -+ -+ @Override -+ public @NonNull Component componentFromMessage(final @NonNull Message message) { -+ requireNonNull(message, "message"); -+ return PaperAdventure.asAdventure(ChatComponentUtils.fromMessage(message)); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index cac3df2ca054b3b2fb5b6437ab2950afc3ace8fb..04ca3ed64d8fb9bce38d715d3618ab5c73d8cbfa 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -213,6 +213,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - } - com.destroystokyo.paper.PaperConfig.registerCommands(); - com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now -+ io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider - // Paper end - - this.setPVP(dedicatedserverproperties.pvp); diff --git a/Unmapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/Unmapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch deleted file mode 100644 index 3d7c4fd05d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Fri, 23 Apr 2021 22:42:42 +0100 -Subject: [PATCH] Fix anchor respawn acting as a bed respawn from the end - portal - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index b257d58a298e82f255b09e9575ee42a56a4b7cee..a83d8cfac8c5ed84dd5224cc3f18f55dba4741af 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -871,6 +871,7 @@ public abstract class PlayerList { - - // Paper start - boolean isBedSpawn = false; -+ boolean isAnchorSpawn = false; - boolean isRespawn = false; - boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 - // Paper end -@@ -891,6 +892,7 @@ public abstract class PlayerList { - if (optional.isPresent()) { - IBlockData iblockdata = worldserver1.getType(blockposition); - boolean flag3 = iblockdata.a(Blocks.RESPAWN_ANCHOR); -+ isAnchorSpawn = flag3; // Paper - Fix anchor respawn acting as a bed respawn from the end portal - Vec3D vec3d = (Vec3D) optional.get(); - float f1; - -@@ -918,7 +920,7 @@ public abstract class PlayerList { - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); -- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag2, flag2); -+ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal - cserver.getPluginManager().callEvent(respawnEvent); - // Spigot Start - if (entityplayer.playerConnection.isDisconnected()) { diff --git a/Unmapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch b/Unmapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch deleted file mode 100644 index fc6f31d8c9..0000000000 --- a/Unmapped-Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 17:17:47 -0700 -Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 957d3b56aea116f947ca8fb74127f652de72b701..d1073b69e3fcee219123e4fe0c7ab5374dd71d32 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2442,7 +2442,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - case PERFORM_RESPAWN: - if (this.player.viewingCredits) { - this.player.viewingCredits = false; -- this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, true); -+ this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, this.minecraftServer.getWorldServer(this.player.getSpawnDimension()), true, null, true, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); // Paper - add isEndCreditsRespawn argument - CriterionTriggers.v.a(this.player, World.THE_END, World.OVERWORLD); - } else { - if (this.player.getHealth() > 0.0F) { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index a83d8cfac8c5ed84dd5224cc3f18f55dba4741af..2a76c3624c64e93509a96579f48c507e29901625 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -820,7 +820,13 @@ public abstract class PlayerList { - return this.moveToWorld(entityplayer, this.server.getWorldServer(entityplayer.getSpawnDimension()), flag, null, true); - } - -+ // Paper start - public EntityPlayer moveToWorld(EntityPlayer entityplayer, WorldServer worldserver, boolean flag, Location location, boolean avoidSuffocation) { -+ return moveToWorld(entityplayer, worldserver, flag, location, avoidSuffocation, new org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag[0]); -+ } -+ -+ public EntityPlayer moveToWorld(EntityPlayer entityplayer, WorldServer worldserver, boolean flag, Location location, boolean avoidSuffocation, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag...respawnFlags) { -+ // Paper end - entityplayer.stopRiding(); // CraftBukkit - this.players.remove(entityplayer); - this.playersByName.remove(entityplayer.getName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -920,7 +926,7 @@ public abstract class PlayerList { - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); -- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal -+ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn, com.google.common.collect.ImmutableSet.builder().add(respawnFlags)); // Paper - Fix anchor respawn acting as a bed respawn from the end portal - cserver.getPluginManager().callEvent(respawnEvent); - // Spigot Start - if (entityplayer.playerConnection.isDisconnected()) { diff --git a/Unmapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch b/Unmapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch deleted file mode 100644 index f8c74eacff..0000000000 --- a/Unmapped-Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spyridon Pagkalos -Date: Thu, 25 Mar 2021 20:28:04 +0200 -Subject: [PATCH] Introduce beacon activation/deactivation events - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -index cd28a731a56eb7534faae5b120195b62d5d15bd4..f7b210e6d60533d9faf60183a80a562b25f945d0 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -@@ -201,6 +201,15 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - this.a(SoundEffects.BLOCK_BEACON_AMBIENT); - } - } -+ // Paper start - beacon activation/deactivation events -+ if (!(i1 > 0) && this.levels > 0) { -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); -+ new io.papermc.paper.event.block.BeaconActivatedEvent(block).callEvent(); -+ } else if (i1 > 0 && !(this.levels > 0)) { -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); -+ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); -+ } -+ // Paper end - - if (this.i >= l) { - this.i = -1; -@@ -257,6 +266,10 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - - @Override - public void al_() { -+ // Paper start - BeaconDeactivatedEvent -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); -+ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); -+ // Paper end - this.a(SoundEffects.BLOCK_BEACON_DEACTIVATE); - super.al_(); - } diff --git a/Unmapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch b/Unmapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch deleted file mode 100644 index 0f5e146c08..0000000000 --- a/Unmapped-Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Thu, 29 Apr 2021 21:19:33 +0200 -Subject: [PATCH] Add Channel initialization listeners - - -diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..88099df34c2d74daba9645aadf65b446ca795a91 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java -@@ -0,0 +1,15 @@ -+package io.papermc.paper.network; -+ -+import io.netty.channel.Channel; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+/** -+ * Internal API to register channel initialization listeners. -+ *

    -+ * This is not officially supported API and we make no guarantees to the existence or state of this interface. -+ */ -+@FunctionalInterface -+public interface ChannelInitializeListener { -+ -+ void afterInitChannel(@NonNull Channel channel); -+} -diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..30e62719e0a83525daa33cf41cb61df360c0e046 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java -@@ -0,0 +1,74 @@ -+package io.papermc.paper.network; -+ -+import io.netty.channel.Channel; -+import net.kyori.adventure.key.Key; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+ -+import java.util.Collections; -+import java.util.HashMap; -+import java.util.Map; -+ -+/** -+ * Internal API to register channel initialization listeners. -+ *

    -+ * This is not officially supported API and we make no guarantees to the existence or state of this class. -+ */ -+public final class ChannelInitializeListenerHolder { -+ -+ private static final Map LISTENERS = new HashMap<>(); -+ private static final Map IMMUTABLE_VIEW = Collections.unmodifiableMap(LISTENERS); -+ -+ private ChannelInitializeListenerHolder() { -+ } -+ -+ /** -+ * Registers whether an initialization listener is registered under the given key. -+ * -+ * @param key key -+ * @return whether an initialization listener is registered under the given key -+ */ -+ public static boolean hasListener(@NonNull Key key) { -+ return LISTENERS.containsKey(key); -+ } -+ -+ /** -+ * Registers a channel initialization listener called after ServerConnection is initialized. -+ * -+ * @param key key -+ * @param listener initialization listeners -+ */ -+ public static void addListener(@NonNull Key key, @NonNull ChannelInitializeListener listener) { -+ LISTENERS.put(key, listener); -+ } -+ -+ /** -+ * Removes and returns an initialization listener registered by the given key if present. -+ * -+ * @param key key -+ * @return removed initialization listener if present -+ */ -+ public static @Nullable ChannelInitializeListener removeListener(@NonNull Key key) { -+ return LISTENERS.remove(key); -+ } -+ -+ /** -+ * Returns an immutable map of registered initialization listeners. -+ * -+ * @return immutable map of registered initialization listeners -+ */ -+ public static @NonNull Map getListeners() { -+ return IMMUTABLE_VIEW; -+ } -+ -+ /** -+ * Calls the registered listeners with the given channel. -+ * -+ * @param channel channel -+ */ -+ public static void callListeners(@NonNull Channel channel) { -+ for (ChannelInitializeListener listener : LISTENERS.values()) { -+ listener.afterInitChannel(channel); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java -index dc362724ea0cc1b2f9d9ceffff483217b4356c40..69fc2789df88344587b6052f93661ed38f24a503 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnection.java -@@ -104,6 +104,7 @@ public class ServerConnection { - pending.add((NetworkManager) object); // Paper - channel.pipeline().addLast("packet_handler", (ChannelHandler) object); - ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object)); -+ io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper - } - }).group((EventLoopGroup) lazyinitvar.a()).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit - } diff --git a/Unmapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch b/Unmapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch deleted file mode 100644 index 2fefc38db3..0000000000 --- a/Unmapped-Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 26 Apr 2021 01:27:08 +0100 -Subject: [PATCH] Send empty commands if tab completion is disabled - - -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index 47dc8450fff5583d70c969c0b92b96a665a02305..7e30ec9a08d919d2ae9218ee0a11f77719129f07 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -327,7 +327,12 @@ public class CommandDispatcher { - } - - public void a(EntityPlayer entityplayer) { -- if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot -+ // Paper start - Send empty commands if tab completion is disabled -+ if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) { //return; // Spigot -+ entityplayer.playerConnection.sendPacket(new PacketPlayOutCommands(new RootCommandNode<>())); -+ return; -+ } -+ // Paper end - // CraftBukkit start - // Register Vanilla commands into builtRoot as before - // Paper start - Async command map building diff --git a/Unmapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch b/Unmapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch deleted file mode 100644 index 4679f25de7..0000000000 --- a/Unmapped-Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Thu, 6 May 2021 14:56:43 +0100 -Subject: [PATCH] Add more WanderingTrader API - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -index 37e1b2bf33510c3603efadf219b462e667f573c2..69044827ed6b34924ffd89a977afa06df0dcefc3 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -@@ -58,6 +58,10 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - @Nullable - private BlockPosition bp; - private int despawnDelay; -+ // Paper start - Add more WanderingTrader API -+ public boolean canDrinkPotion = true; -+ public boolean canDrinkMilk = true; -+ // Paper end - - public EntityVillagerTrader(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -69,10 +73,10 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); - this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, PotionUtil.a(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEffects.ENTITY_WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { -- return this.world.isNight() && !entityvillagertrader.isInvisible(); -+ return canDrinkPotion && this.world.isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API - })); - this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, new ItemStack(Items.MILK_BUCKET), SoundEffects.ENTITY_WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { -- return this.world.isDay() && entityvillagertrader.isInvisible(); -+ return canDrinkMilk && this.world.isDay() && entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API - })); - this.goalSelector.a(1, new PathfinderGoalTradeWithPlayer(this)); - this.goalSelector.a(1, new PathfinderGoalAvoidTarget<>(this, EntityZombie.class, 8.0F, 0.5D, 0.5D)); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -index c8344ce0a85030b12139d0b2bbe45acdcd33e1e7..6dad8ca649a2fa0a80a4b88c8a3e284fe218f31f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -@@ -35,4 +35,26 @@ public class CraftWanderingTrader extends CraftAbstractVillager implements Wande - public void setDespawnDelay(int despawnDelay) { - getHandle().setDespawnDelay(despawnDelay); - } -+ -+ // Paper start - Add more WanderingTrader API -+ @Override -+ public void setCanDrinkPotion(boolean bool) { -+ getHandle().canDrinkPotion = bool; -+ } -+ -+ @Override -+ public boolean canDrinkPotion() { -+ return getHandle().canDrinkPotion; -+ } -+ -+ @Override -+ public void setCanDrinkMilk(boolean bool) { -+ getHandle().canDrinkMilk = bool; -+ } -+ -+ @Override -+ public boolean canDrinkMilk() { -+ return getHandle().canDrinkMilk; -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch b/Unmapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch deleted file mode 100644 index 3fc2d1a337..0000000000 --- a/Unmapped-Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Mon, 5 Apr 2021 18:12:29 -0400 -Subject: [PATCH] Add EntityBlockStorage#clearEntities() - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java -index 3cbcbb028b864f1d14e004628bbc0829f71ab476..80083a6666a28372946cf0e68ded44d075357f7d 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java -@@ -120,6 +120,11 @@ public class TileEntityBeehive extends TileEntity implements ITickable { - return this.bees.size(); - } - -+ // Paper start - Add EntityBlockStorage clearEntities -+ public void clearBees() { -+ this.bees.clear(); -+ } -+ // Paper end - public static int a(IBlockData iblockdata) { - return (Integer) iblockdata.get(BlockBeehive.b); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java -index af691b28b38e388617d241008c2e9d403bc5c15d..9f4fb1ff9c945799d10d6905c8b73376e4133d23 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java -@@ -83,4 +83,10 @@ public class CraftBeehive extends CraftBlockEntityState imple - - getSnapshot().addBee(((CraftBee) entity).getHandle(), false); - } -+ // Paper start - Add EntityBlockStorage clearEntities -+ @Override -+ public void clearEntities() { -+ getSnapshot().clearBees(); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/Unmapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch deleted file mode 100644 index 07309399fa..0000000000 --- a/Unmapped-Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alvinn8 <42838560+Alvinn8@users.noreply.github.com> -Date: Fri, 8 Jan 2021 20:31:13 +0100 -Subject: [PATCH] Add Adventure message to PlayerAdvancementDoneEvent - - -diff --git a/src/main/java/net/minecraft/advancements/Advancement.java b/src/main/java/net/minecraft/advancements/Advancement.java -index e3d5d55a2fe5d86db621d3e0c9322f553386d731..2f3d9e5b849093027d3c2ef434494cd600f52a31 100644 ---- a/src/main/java/net/minecraft/advancements/Advancement.java -+++ b/src/main/java/net/minecraft/advancements/Advancement.java -@@ -76,6 +76,7 @@ public class Advancement { - return this.parent; - } - -+ public final @Nullable AdvancementDisplay getAdvancementDisplay() { return this.c(); } // Paper - OBFHELPER - @Nullable - public AdvancementDisplay c() { - return this.display; -@@ -125,6 +126,7 @@ public class Advancement { - return this.requirements; - } - -+ public final IChatBaseComponent getChatComponent() { return this.j(); } // Paper - OBFHELPER - public IChatBaseComponent j() { - return this.chatComponent; - } -diff --git a/src/main/java/net/minecraft/advancements/AdvancementDisplay.java b/src/main/java/net/minecraft/advancements/AdvancementDisplay.java -index 721d7fbab447117349994f710338ca616ab11067..adc6779e53e7b2ee04a80e2ea714e3378b8e6f39 100644 ---- a/src/main/java/net/minecraft/advancements/AdvancementDisplay.java -+++ b/src/main/java/net/minecraft/advancements/AdvancementDisplay.java -@@ -54,10 +54,12 @@ public class AdvancementDisplay { - return this.b; - } - -+ public final AdvancementFrameType getFrameType() { return this.e(); } // Paper - OBFHELPER - public AdvancementFrameType e() { - return this.e; - } - -+ public final boolean shouldAnnounceToChat() { return this.i(); } // Paper - OBFHELPER - public boolean i() { - return this.g; - } -diff --git a/src/main/java/net/minecraft/advancements/AdvancementFrameType.java b/src/main/java/net/minecraft/advancements/AdvancementFrameType.java -index f5d24950d317c78a971472821595fc1b44befc6e..32380346555e194227423999a79f1ebcbbe38d3b 100644 ---- a/src/main/java/net/minecraft/advancements/AdvancementFrameType.java -+++ b/src/main/java/net/minecraft/advancements/AdvancementFrameType.java -@@ -20,6 +20,7 @@ public enum AdvancementFrameType { - this.g = new ChatMessage("advancements.toast." + s); - } - -+ public final String getId() { return this.a(); } // Paper - OBFHELPER - public String a() { - return this.d; - } -diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index 7a8a1960882e291c46301d07da3e1c5415516893..dfdbc028f68ced197ad179248ed3b1e9d70ba057 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -51,6 +51,7 @@ import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.GameRules; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - - public class AdvancementDataPlayer { - -@@ -313,10 +314,18 @@ public class AdvancementDataPlayer { - this.j.add(advancement); - flag = true; - if (!flag1 && advancementprogress.isDone()) { -- this.player.world.getServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit)); // CraftBukkit -+ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent -+ boolean announceToChat = advancement.getAdvancementDisplay() != null && advancement.getAdvancementDisplay().shouldAnnounceToChat(); -+ net.kyori.adventure.text.Component message = announceToChat ? PaperAdventure.asAdventure(new ChatMessage("chat.type.advancement." + advancement.getAdvancementDisplay().getFrameType().getId(), this.player.getScoreboardDisplayName(), advancement.getChatComponent())) : null; -+ org.bukkit.event.player.PlayerAdvancementDoneEvent event = new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit, message); -+ this.player.world.getServer().getPluginManager().callEvent(event); -+ message = event.message(); -+ // Paper end - advancement.d().a(this.player); -- if (advancement.c() != null && advancement.c().i() && this.player.world.getGameRules().getBoolean(GameRules.ANNOUNCE_ADVANCEMENTS)) { -- this.e.sendMessage(new ChatMessage("chat.type.advancement." + advancement.c().e().a(), new Object[]{this.player.getScoreboardDisplayName(), advancement.j()}), ChatMessageType.SYSTEM, SystemUtils.b); -+ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent -+ if (message != null && this.player.world.getGameRules().getBoolean(GameRules.ANNOUNCE_ADVANCEMENTS)) { -+ this.e.sendMessage(PaperAdventure.asVanilla(message), ChatMessageType.SYSTEM, SystemUtils.getNullUUID()); -+ // Paper end - } - } - } diff --git a/Unmapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/Unmapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch deleted file mode 100644 index 5e64169b09..0000000000 --- a/Unmapped-Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Wed, 12 May 2021 08:09:19 +0100 -Subject: [PATCH] Add raw address to AsyncPlayerPreLoginEvent - - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 190fc9f764420ea5fd20d629101644aeda2d8239..5b69126142140c7fc96435a4d246752581f47c33 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -327,12 +327,13 @@ public class LoginListener implements PacketLoginInListener { - // Paper end - String playerName = i.getName(); - java.net.InetAddress address = ((java.net.InetSocketAddress) networkManager.getSocketAddress()).getAddress(); -+ java.net.InetAddress rawAddress = ((java.net.InetSocketAddress) networkManager.getRawAddress()).getAddress(); // Paper - java.util.UUID uniqueId = i.getId(); - final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; - - // Paper start - PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); -- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); -+ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile); - server.getPluginManager().callEvent(asyncEvent); - profile = asyncEvent.getPlayerProfile(); - profile.complete(true); diff --git a/Unmapped-Spigot-Server-Patches/0726-Inventory-close.patch b/Unmapped-Spigot-Server-Patches/0726-Inventory-close.patch deleted file mode 100644 index 79f0c20686..0000000000 --- a/Unmapped-Spigot-Server-Patches/0726-Inventory-close.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 11 May 2021 14:54:56 -0700 -Subject: [PATCH] Inventory#close - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index c3fa97ac34e1fc61ae02f224f8afe5a0b486fb4d..f6001047ada8308cfa1d9b26677a7a5d7774de51 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -449,6 +449,14 @@ public class CraftInventory implements Inventory { - clear(i); - } - } -+ // Paper start -+ @Override -+ public int close() { -+ int count = this.inventory.getViewers().size(); -+ com.google.common.collect.Lists.newArrayList(this.inventory.getViewers()).forEach(HumanEntity::closeInventory); -+ return count; -+ } -+ // Paper end - - @Override - public ListIterator iterator() { diff --git a/Unmapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch b/Unmapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch deleted file mode 100644 index 21890b59ca..0000000000 --- a/Unmapped-Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 12 May 2021 03:21:22 -0700 -Subject: [PATCH] call PortalCreateEvent players and end platform - - -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index eb67af795dd716d9f92ac32843accc1ec4efd647..4abc87b7e737bc652e84f76a508ab85501d1556f 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -496,6 +496,7 @@ public class BlockPosition extends BaseBlockPosition { - return this.d(this.getX() + enumdirection.getAdjacentX() * i, this.getY() + enumdirection.getAdjacentY() * i, this.getZ() + enumdirection.getAdjacentZ() * i); - } - -+ public BlockPosition.MutableBlockPosition withOffset(int x, int y, int z) { return e(x, y, z); } // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition e(int i, int j, int k) { - return this.d(this.getX() + i, this.getY() + j, this.getZ() + k); - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 3f44d5b8e3bc4f897a5dda473532004078fe0ebe..8683d6ddc5d8ce4a302fa6e2665b7dcd64f6a00a 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1145,15 +1145,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - private void a(WorldServer worldserver, BlockPosition blockposition) { - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = blockposition.i(); - -+ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(worldserver); // Paper - for (int i = -2; i <= 2; ++i) { - for (int j = -2; j <= 2; ++j) { - for (int k = -1; k < 3; ++k) { - IBlockData iblockdata = k == -1 ? Blocks.OBSIDIAN.getBlockData() : Blocks.AIR.getBlockData(); - -- worldserver.setTypeUpdate(blockposition_mutableblockposition.g(blockposition).e(j, k, i), iblockdata); -+ blockList.setTypeAndData(blockposition_mutableblockposition.setValues(blockposition).withOffset(j, k, i), iblockdata, 3); // Paper - } - } - } -+ // Paper start -+ if (new org.bukkit.event.world.PortalCreateEvent((List< org.bukkit.block.BlockState>) (List) blockList.getList(), worldserver.getWorld(), this.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM).callEvent()) { -+ blockList.updateList(); -+ } -+ // Paper end - - } - diff --git a/Unmapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/Unmapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch deleted file mode 100644 index 70f7b8aa41..0000000000 --- a/Unmapped-Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 11 May 2021 00:48:33 +0200 -Subject: [PATCH] Add a "should burn in sunlight" API for Phantoms and - Skeletons - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -index 42cf3fa42b73739182d26fbb524ee5b304c799b2..16c0c960aa1e4d35093b810c7648b5638175e106 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -@@ -134,7 +134,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - - @Override - public void movementTick() { -- if (this.isAlive() && this.eG()) { -+ if (this.isAlive() && shouldBurnInDay && this.eG()) { // Paper - Configurable Burning - this.setOnFire(8); - } - -@@ -165,6 +165,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - if (nbttagcompound.hasUUID("Paper.SpawningEntity")) { - this.spawningEntity = nbttagcompound.getUUID("Paper.SpawningEntity"); - } -+ this.shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); - // Paper end - } - -@@ -179,6 +180,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - if (this.spawningEntity != null) { - nbttagcompound.setUUID("Paper.SpawningEntity", this.spawningEntity); - } -+ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); - // Paper end - } - -@@ -233,6 +235,10 @@ public class EntityPhantom extends EntityFlying implements IMonster { - return spawningEntity; - } - public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } -+ -+ private boolean shouldBurnInDay = true; -+ public boolean shouldBurnInDay() { return shouldBurnInDay; } -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } - // Paper end - - class b extends PathfinderGoal { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -index 06d50b22ede102556fdb3e2a6f1424f7ff13f120..f8358e40c42f219232bf928f4e0073339a5e19d5 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -@@ -98,9 +98,15 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - return EnumMonsterType.UNDEAD; - } - -+ // Paper start -+ private boolean shouldBurnInDay = true; -+ public boolean shouldBurnInDay() { return shouldBurnInDay; } -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } -+ // Paper end -+ - @Override - public void movementTick() { -- boolean flag = this.eG(); -+ boolean flag = shouldBurnInDay && this.eG(); // Paper - Configurable Burning - - if (flag) { - ItemStack itemstack = this.getEquipment(EnumItemSlot.HEAD); -@@ -224,7 +230,16 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - public void loadData(NBTTagCompound nbttagcompound) { - super.loadData(nbttagcompound); - this.eL(); -+ this.shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); // Paper -+ } -+ -+ // Paper start -+ @Override -+ public void saveData(NBTTagCompound nbttagcompound) { -+ super.saveData(nbttagcompound); -+ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); - } -+ // Paper end - - @Override - public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -index 0cea1d8e23da3a79ef06e43752665a5401b01b4b..476339ef8cafad2d6c78bccb6fd9f3c882b89148 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -@@ -40,5 +40,15 @@ public class CraftPhantom extends CraftFlying implements Phantom { - public java.util.UUID getSpawningEntity() { - return getHandle().getSpawningEntity(); - } -+ -+ @Override -+ public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); -+ } -+ -+ @Override -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ getHandle().setShouldBurnInDay(shouldBurnInDay); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -index c2acfa2cc27a187154e17b7f45908682b41b52af..f48c4225dbc3467aaf8d14bc4047430548cc7c78 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -@@ -36,4 +36,16 @@ public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroy - public void setSkeletonType(SkeletonType type) { - throw new UnsupportedOperationException("Not supported."); - } -+ -+ // Paper start -+ @Override -+ public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); -+ } -+ -+ @Override -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ getHandle().setShouldBurnInDay(shouldBurnInDay); -+ } -+ // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch b/Unmapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch deleted file mode 100644 index e2ecdf706b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sceri -Date: Fri, 14 May 2021 19:06:51 +0500 -Subject: [PATCH] Fix CraftPotionBrewer cache - - -diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -index 7156bd1c8938a0b111be11d93ed2645a58d75611..4d108ed58a768a5a5e2e33213921f0a89487b6a2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -@@ -15,12 +15,18 @@ import org.bukkit.potion.PotionEffectType; - import org.bukkit.potion.PotionType; - - public class CraftPotionBrewer implements PotionBrewer { -- private static final Map> cache = Maps.newHashMap(); -+ private static final Map> cache = Maps.newHashMap(); // Paper - - @Override - public Collection getEffects(PotionType damage, boolean upgraded, boolean extended) { -- if (cache.containsKey(damage)) -- return cache.get(damage); -+ // Paper start -+ int key = damage.ordinal() << 2; -+ key |= (upgraded ? 1 : 0) << 1; -+ key |= extended ? 1 : 0; -+ -+ if (cache.containsKey(key)) -+ return cache.get(key); -+ // Paper end - - List mcEffects = PotionRegistry.a(CraftPotionUtil.fromBukkit(new PotionData(damage, extended, upgraded))).a(); - -@@ -29,9 +35,9 @@ public class CraftPotionBrewer implements PotionBrewer { - builder.add(CraftPotionUtil.toBukkit(effect)); - } - -- cache.put(damage, builder.build()); -+ cache.put(key, builder.build()); // Paper - -- return cache.get(damage); -+ return cache.get(key); // Paper - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch b/Unmapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch deleted file mode 100644 index 7d34bf75bc..0000000000 --- a/Unmapped-Spigot-Server-Patches/0730-Add-basic-Datapack-API.patch +++ /dev/null @@ -1,175 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Sun, 16 May 2021 15:07:34 +0100 -Subject: [PATCH] Add basic Datapack API - - -diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6426f646afdd2a75df89d522068a36cf170d697d ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java -@@ -0,0 +1,51 @@ -+package io.papermc.paper.datapack; -+ -+import io.papermc.paper.event.server.ServerResourcesReloadedEvent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.packs.repository.ResourcePackLoader; -+ -+import java.util.List; -+import java.util.stream.Collectors; -+ -+public class PaperDatapack implements Datapack { -+ private final String name; -+ private final Compatibility compatibility; -+ private final boolean enabled; -+ -+ PaperDatapack(ResourcePackLoader loader, boolean enabled) { -+ this.name = loader.getName(); -+ this.compatibility = Compatibility.valueOf(loader.getVersion().name()); -+ this.enabled = enabled; -+ } -+ -+ @Override -+ public String getName() { -+ return name; -+ } -+ -+ @Override -+ public Compatibility getCompatibility() { -+ return compatibility; -+ } -+ -+ @Override -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @Override -+ public void setEnabled(boolean enabled) { -+ if (enabled == this.enabled) { -+ return; -+ } -+ -+ MinecraftServer server = MinecraftServer.getServer(); -+ List enabledKeys = server.getResourcePackRepository().getEnabledPacks().stream().map(ResourcePackLoader::getName).collect(Collectors.toList()); -+ if (enabled) { -+ enabledKeys.add(this.name); -+ } else { -+ enabledKeys.remove(this.name); -+ } -+ server.reloadServerResources(enabledKeys, ServerResourcesReloadedEvent.Cause.PLUGIN); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..378aaeebd7e011565fdc505da68c5b5285339add ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java -@@ -0,0 +1,26 @@ -+package io.papermc.paper.datapack; -+ -+import net.minecraft.server.packs.repository.ResourcePackLoader; -+import net.minecraft.server.packs.repository.ResourcePackRepository; -+ -+import java.util.Collection; -+import java.util.stream.Collectors; -+ -+public class PaperDatapackManager implements DatapackManager { -+ private final ResourcePackRepository repository; -+ -+ public PaperDatapackManager(ResourcePackRepository repository) { -+ this.repository = repository; -+ } -+ -+ @Override -+ public Collection getPacks() { -+ Collection enabledPacks = repository.getEnabledPacks(); -+ return repository.getPacks().stream().map(loader -> new PaperDatapack(loader, enabledPacks.contains(loader))).collect(Collectors.toList()); -+ } -+ -+ @Override -+ public Collection getEnabledPacks() { -+ return repository.getEnabledPacks().stream().map(loader -> new PaperDatapack(loader, true)).collect(Collectors.toList()); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java b/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java -index 5c038c02955d8517db0686f3b73c8573d3770466..01c4fda33a138b2d1f6b7c1335378445423a66a9 100644 ---- a/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java -+++ b/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java -@@ -102,6 +102,7 @@ public class ResourcePackLoader implements AutoCloseable { - }); - } - -+ public final EnumResourcePackVersion getVersion() { return this.c(); } // Paper - OBFHELPER - public EnumResourcePackVersion c() { - return this.g; - } -@@ -110,6 +111,7 @@ public class ResourcePackLoader implements AutoCloseable { - return (IResourcePack) this.d.get(); - } - -+ public final String getName() { return this.e(); } // Paper - OBFHELPER - public String e() { - return this.c; - } -diff --git a/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java b/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java -index e87523612d0423d71eab7b9af851c1c268cdf84f..568da9686c41a41e43ede3fe15e0ca53c9688f8b 100644 ---- a/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java -+++ b/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java -@@ -88,6 +88,7 @@ public class ResourcePackRepository implements AutoCloseable { - return this.b.keySet(); - } - -+ public final Collection getPacks() { return this.c(); } // Paper - OBFHELPER - public Collection c() { - return this.b.values(); - } -@@ -96,6 +97,7 @@ public class ResourcePackRepository implements AutoCloseable { - return (Collection) this.c.stream().map(ResourcePackLoader::e).collect(ImmutableSet.toImmutableSet()); - } - -+ public final Collection getEnabledPacks() { return this.e(); } // Paper - OBFHELPER - public Collection e() { - return this.c; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 706dad235de3b7ffe014f564e1c68f18e1edeefc..89244c152665c97cb539bea07fedd1774ed626f1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -18,6 +18,7 @@ import com.mojang.serialization.Lifecycle; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.datapack.PaperDatapackManager; // Paper - import io.papermc.paper.util.TraceUtil; - import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; - import java.awt.image.BufferedImage; -@@ -265,6 +266,7 @@ public final class CraftServer implements Server { - public boolean ignoreVanillaPermissions = false; - private final List playerView; - public int reloadCount; -+ private final PaperDatapackManager datapackManager; // Paper - public static Exception excessiveVelEx; // Paper - Velocity warnings - - static { -@@ -347,6 +349,7 @@ public final class CraftServer implements Server { - TicketType.PLUGIN.loadPeriod = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - loadIcon(); -+ datapackManager = new PaperDatapackManager(console.getResourcePackRepository()); // Paper - } - - public boolean getCommandBlockOverride(String command) { -@@ -2497,5 +2500,11 @@ public final class CraftServer implements Server { - public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { - return mobGoals; - } -+ -+ @Override -+ public PaperDatapackManager getDatapackManager() { -+ return datapackManager; -+ } -+ - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch b/Unmapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch deleted file mode 100644 index 272a91a04d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0731-Add-environment-variable-to-disable-server-gui.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Mon, 17 May 2021 00:34:55 -0700 -Subject: [PATCH] Add environment variable to disable server gui - - -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 6818f8496ab76ee6ffc747bd6848b43830ec8914..bf4051349917cc1d727fc5544237e0291cb6f1e6 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -233,6 +233,7 @@ public class Main { - */ - boolean flag1 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui"); - -+ if(!Boolean.parseBoolean(System.getenv().getOrDefault("PAPER_DISABLE_SERVER_GUI", String.valueOf(false)))) // Paper - if (flag1 && !GraphicsEnvironment.isHeadless()) { - dedicatedserver1.bd(); - } diff --git a/Unmapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch deleted file mode 100644 index fdf582f3e8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0732-additions-to-PlayerGameModeChangeEvent.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 10:04:43 -0700 -Subject: [PATCH] additions to PlayerGameModeChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/commands/CommandGamemode.java b/src/main/java/net/minecraft/server/commands/CommandGamemode.java -index 376d5eac9c17365266d8a4986bf4c19030454c9a..8da48d9cbadfbe83ae8410cf49d78df49f50fb08 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandGamemode.java -+++ b/src/main/java/net/minecraft/server/commands/CommandGamemode.java -@@ -62,13 +62,13 @@ public class CommandGamemode { - EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - - if (entityplayer.playerInteractManager.getGameMode() != enumgamemode) { -- entityplayer.a(enumgamemode); -- // CraftBukkit start - handle event cancelling the change -- if (entityplayer.playerInteractManager.getGameMode() != enumgamemode) { -- commandcontext.getSource().sendFailureMessage(new net.minecraft.network.chat.ChatComponentText("Failed to set the gamemode of '" + entityplayer.getName() + "'")); -+ // Paper start - handle event cancelling the change -+ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); -+ if (event != null && event.isCancelled()) { -+ commandcontext.getSource().sendMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); - continue; - } -- // CraftBukkit end -+ // Paper end - a((CommandListenerWrapper) commandcontext.getSource(), entityplayer, enumgamemode); - ++i; - } -diff --git a/src/main/java/net/minecraft/server/commands/CommandGamemodeDefault.java b/src/main/java/net/minecraft/server/commands/CommandGamemodeDefault.java -index 5790699b3898910dfde46f588996dd8af42757d1..2a731594c22bb266d3dfef4d64d55b9772565cca 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandGamemodeDefault.java -+++ b/src/main/java/net/minecraft/server/commands/CommandGamemodeDefault.java -@@ -43,7 +43,13 @@ public class CommandGamemodeDefault { - EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - - if (entityplayer.playerInteractManager.getGameMode() != enumgamemode) { -- entityplayer.a(enumgamemode); -+ // Paper start - handle event cancelling the change -+ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); -+ if (event != null && event.isCancelled()) { -+ commandlistenerwrapper.sendMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); -+ continue; -+ } -+ // Paper end - ++i; - } - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 8683d6ddc5d8ce4a302fa6e2665b7dcd64f6a00a..558af73ac16550ee6964c4dce681a404633b2552 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -396,7 +396,16 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - if (this.locY() > 300) this.setPositionRaw(locX(), 257, locZ()); // Paper - bring down to a saner Y level if out of world - if (nbttagcompound.hasKeyOfType("playerGameType", 99)) { - if (this.getMinecraftServer().getForceGamemode()) { -+ // Paper start - call PlayerGameModeChangeEvent on join for players that do not have the correct gamemode -+ if (this.getMinecraftServer().getGamemode() != EnumGamemode.getById(nbttagcompound.getInt("playerGameType"))) { -+ if (new org.bukkit.event.player.PlayerGameModeChangeEvent(this.getBukkitEntity(), GameMode.getByValue(this.getMinecraftServer().getGamemode().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) { - this.playerInteractManager.a(this.getMinecraftServer().getGamemode(), EnumGamemode.NOT_SET); -+ } else { -+ this.playerInteractManager.a(EnumGamemode.getById(nbttagcompound.getInt("playerGameType")), nbttagcompound.hasKeyOfType("previousPlayerGameType", 3) ? EnumGamemode.getById(nbttagcompound.getInt("previousPlayerGameType")) : EnumGamemode.NOT_SET); // copied from below; if cancelled, set gamemode normally -+ } -+ } else { -+ this.playerInteractManager.a(EnumGamemode.getById(nbttagcompound.getInt("playerGameType")), nbttagcompound.hasKeyOfType("previousPlayerGameType", 3) ? EnumGamemode.getById(nbttagcompound.getInt("previousPlayerGameType")) : EnumGamemode.NOT_SET); // copied from below; if no change needed, set gamemode normally -+ } // Paper end - } else { - this.playerInteractManager.a(EnumGamemode.getById(nbttagcompound.getInt("playerGameType")), nbttagcompound.hasKeyOfType("previousPlayerGameType", 3) ? EnumGamemode.getById(nbttagcompound.getInt("previousPlayerGameType")) : EnumGamemode.NOT_SET); - } -@@ -1792,15 +1801,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - @Override - public void a(EnumGamemode enumgamemode) { -+ // Paper start - Add cause and nullable message to event -+ setGamemode(enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null); -+ } -+ -+ public PlayerGameModeChangeEvent setGamemode(EnumGamemode enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component message) { -+ // Paper end - // CraftBukkit start - if (enumgamemode == this.playerInteractManager.getGameMode()) { -- return; -+ return null; // Paper - } - -- PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(enumgamemode.getId())); -+ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(enumgamemode.getId()), cause, message); // Paper - world.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { -- return; -+ return event; // Paper - } - // CraftBukkit end - -@@ -1815,6 +1830,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - this.updateAbilities(); - this.dU(); -+ return event; // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index d1073b69e3fcee219123e4fe0c7ab5374dd71d32..304310cad03bce78a25ab0fb3e5e5f62ebd5558b 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2451,7 +2451,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, false); - if (this.minecraftServer.isHardcore()) { -- this.player.a(EnumGamemode.SPECTATOR); -+ this.player.setGamemode(EnumGamemode.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper - ((GameRules.GameRuleBoolean) this.player.getWorldServer().getGameRules().get(GameRules.SPECTATORS_GENERATE_CHUNKS)).a(false, this.minecraftServer); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 05248f560d643080a3eac581c01aa89fb3709e6c..34395248e3daea47178cb40aad53680fbce73600 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1193,7 +1193,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - throw new IllegalArgumentException("Mode cannot be null"); - } - -- getHandle().a(EnumGamemode.getById(mode.getValue())); -+ getHandle().setGamemode(EnumGamemode.getById(mode.getValue()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.PLUGIN, null); // Paper - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch b/Unmapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch deleted file mode 100644 index 006fed82d1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0733-ItemStack-repair-check-API.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 22:11:11 -0700 -Subject: [PATCH] ItemStack repair check API - - -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index f7758ee4aa8bbb31a80ec2e331b3fd3c55069808..7c9ef73983c2c7f4b7386a472e5a79dce7fa7ea7 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -269,6 +269,7 @@ public class Item implements IMaterial { - return this.i; - } - -+ public boolean canRepair(ItemStack toBeRepaired, ItemStack repairMaterial) { return a(toBeRepaired, repairMaterial); } // Paper - OBFHELPER - public boolean a(ItemStack itemstack, ItemStack itemstack1) { - return false; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 697949abbe662a55fc31ad811863717e35b9d1b6..a386beea01056a7fb448596ba45342d832a4c63d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -487,6 +487,14 @@ public final class CraftMagicNumbers implements UnsafeValues { - return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; - } - -+ @Override -+ public boolean isValidRepairItemStack(org.bukkit.inventory.ItemStack itemToBeRepaired, org.bukkit.inventory.ItemStack repairMaterial) { -+ if (!itemToBeRepaired.getType().isItem() || !repairMaterial.getType().isItem()) { -+ return false; -+ } -+ return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); -+ } -+ - @Override - public int getProtocolVersion() { - return net.minecraft.SharedConstants.getGameVersion().getProtocolVersion(); -diff --git a/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8d9c9b3bd53d407391d4fcb7fc773153d1a7b402 ---- /dev/null -+++ b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java -@@ -0,0 +1,48 @@ -+package io.papermc.paper.util; -+ -+import org.bukkit.Material; -+import org.bukkit.inventory.ItemStack; -+import org.bukkit.support.AbstractTestingBase; -+import org.junit.Test; -+ -+import static org.junit.Assert.assertFalse; -+import static org.junit.Assert.assertThrows; -+import static org.junit.Assert.assertTrue; -+ -+public class ItemStackRepairCheckTest extends AbstractTestingBase { -+ -+ @Test -+ public void testIsRepariableBy() { -+ ItemStack diamondPick = new ItemStack(Material.DIAMOND_PICKAXE); -+ -+ assertTrue("diamond pick isn't repairable by a diamond", diamondPick.isRepairableBy(new ItemStack(Material.DIAMOND))); -+ } -+ -+ @Test -+ public void testCanRepair() { -+ ItemStack diamond = new ItemStack(Material.DIAMOND); -+ -+ assertTrue("diamond can't repair a diamond axe", diamond.canRepair(new ItemStack(Material.DIAMOND_AXE))); -+ } -+ -+ @Test -+ public void testIsNotRepairableBy() { -+ ItemStack notDiamondPick = new ItemStack(Material.ACACIA_SAPLING); -+ -+ assertFalse("acacia sapling is repairable by a diamond", notDiamondPick.isRepairableBy(new ItemStack(Material.DIAMOND))); -+ } -+ -+ @Test -+ public void testCanNotRepair() { -+ ItemStack diamond = new ItemStack(Material.DIAMOND); -+ -+ assertFalse("diamond can repair oak button", diamond.canRepair(new ItemStack(Material.OAK_BUTTON))); -+ } -+ -+ @Test -+ public void testInvalidItem() { -+ ItemStack badItemStack = new ItemStack(Material.ACACIA_WALL_SIGN); -+ -+ assertFalse("acacia wall sign is repairable by diamond", badItemStack.isRepairableBy(new ItemStack(Material.DIAMOND))); -+ } -+} diff --git a/Unmapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch b/Unmapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch deleted file mode 100644 index 6cca0743b1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0734-More-Enchantment-API.patch +++ /dev/null @@ -1,202 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 6 May 2021 19:57:58 -0700 -Subject: [PATCH] More Enchantment API - - -diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -index b76ef55145336cc8dc4857b79767f5a738ad5144..c719c1c1f837753f61eb7be83b6ec2a214ab6819 100644 ---- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -+++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -@@ -17,7 +17,7 @@ import net.minecraft.world.item.ItemStack; - - public abstract class Enchantment { - -- private final EnumItemSlot[] a; -+ private final EnumItemSlot[] a; public final EnumItemSlot[] getSlots() { return this.a; } // Paper - OBFHELPER - private final Enchantment.Rarity d; - public final EnchantmentSlotType itemTarget; - @Nullable -@@ -46,6 +46,7 @@ public abstract class Enchantment { - return map; - } - -+ public Enchantment.Rarity getRarity() { return d(); } // Paper - OBFHELPER - public Enchantment.Rarity d() { - return this.d; - } -@@ -70,6 +71,7 @@ public abstract class Enchantment { - return 0; - } - -+ public float getDamageIncrease(int level, EnumMonsterType enumMonsterType) { return a(level, enumMonsterType); } // Paper - OBFHELPER - public float a(int i, EnumMonsterType enummonstertype) { - return 0.0F; - } -@@ -123,14 +125,17 @@ public abstract class Enchantment { - return false; - } - -+ public boolean isCursed() { return c(); } // Paper - OBFHELPER - public boolean c() { - return false; - } - -+ public boolean isTradeable() { return h(); } // Paper - OBFHELPER - public boolean h() { - return true; - } - -+ public boolean isDiscoverable() { return i(); } // Paper - OBFHELPER - public boolean i() { - return true; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -index 5a14430f63894bbe9daa42900cf5a6519bea4f45..3b83852249e56609074ef1e8cdad6416db66007b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -+++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -@@ -71,7 +71,7 @@ public class CraftEnchantment extends Enchantment { - - @Override - public boolean isCursed() { -- return target instanceof EnchantmentBinding || target instanceof EnchantmentVanishing; -+ return target.isCursed(); // Paper - } - - @Override -@@ -192,6 +192,45 @@ public class CraftEnchantment extends Enchantment { - public net.kyori.adventure.text.Component displayName(int level) { - return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); - } -+ -+ @Override -+ public boolean isTradeable() { -+ return target.isTradeable(); -+ } -+ -+ @Override -+ public boolean isDiscoverable() { -+ return target.isDiscoverable(); -+ } -+ -+ @Override -+ public io.papermc.paper.enchantments.EnchantmentRarity getRarity() { -+ return fromNMSRarity(target.getRarity()); -+ } -+ -+ @Override -+ public float getDamageIncrease(int level, org.bukkit.entity.EntityCategory entityCategory) { -+ return target.getDamageIncrease(level, org.bukkit.craftbukkit.entity.CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); -+ } -+ -+ @Override -+ public java.util.Set getActiveSlots() { -+ return java.util.stream.Stream.of(target.getSlots()).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet()); -+ } -+ -+ public static io.papermc.paper.enchantments.EnchantmentRarity fromNMSRarity(net.minecraft.world.item.enchantment.Enchantment.Rarity nmsRarity) { -+ if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.COMMON) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.COMMON; -+ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.UNCOMMON) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.UNCOMMON; -+ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.RARE) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.RARE; -+ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.VERY_RARE) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.VERY_RARE; -+ } -+ -+ throw new IllegalArgumentException(String.format("Unable to convert %s to a enum value of %s.", nmsRarity, io.papermc.paper.enchantments.EnchantmentRarity.class)); -+ } - // Paper end - - public net.minecraft.world.item.enchantment.Enchantment getHandle() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 9865eee8ec5e43f291968bfb2c4473260e5baf7c..32428b1260bbc4bae67ec74969c67f71272de418 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -847,5 +847,21 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setHurtDirection(float hurtDirection) { - getHandle().setHurtDirection(hurtDirection); - } -+ -+ public static EnumMonsterType fromBukkitEntityCategory(EntityCategory entityCategory) { -+ switch (entityCategory) { -+ case NONE: -+ return EnumMonsterType.UNDEFINED; -+ case UNDEAD: -+ return EnumMonsterType.UNDEAD; -+ case ARTHROPOD: -+ return EnumMonsterType.ARTHROPOD; -+ case ILLAGER: -+ return EnumMonsterType.ILLAGER; -+ case WATER: -+ return EnumMonsterType.WATER_MOB; -+ } -+ throw new IllegalArgumentException(entityCategory + " is an unrecognized entity category"); -+ } - // Paper end - } -diff --git a/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..62b56b5b43696b03fc72cac59f986d006edc3f76 ---- /dev/null -+++ b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java -@@ -0,0 +1,18 @@ -+package io.papermc.paper.enchantments; -+ -+import net.minecraft.world.item.enchantment.Enchantment.Rarity; -+import org.bukkit.craftbukkit.enchantments.CraftEnchantment; -+import org.junit.Test; -+ -+import static org.junit.Assert.assertNotNull; -+ -+public class EnchantmentRarityTest { -+ -+ @Test -+ public void test() { -+ for (Rarity nmsRarity : Rarity.values()) { -+ // Will throw exception if a bukkit counterpart is not found -+ CraftEnchantment.fromNMSRarity(nmsRarity); -+ } -+ } -+} -diff --git a/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..adb0e5b4268fa115b814143cf29d9a3688e4bc17 ---- /dev/null -+++ b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java -@@ -0,0 +1,34 @@ -+package io.papermc.paper.entity; -+ -+import com.google.common.base.Joiner; -+import com.google.common.collect.Maps; -+import com.google.common.collect.Sets; -+import net.minecraft.world.entity.EnumMonsterType; -+import org.bukkit.craftbukkit.entity.CraftLivingEntity; -+import org.bukkit.entity.EntityCategory; -+import org.junit.Test; -+ -+import java.lang.reflect.Field; -+import java.util.Map; -+import java.util.Set; -+ -+import static org.junit.Assert.assertTrue; -+ -+public class EntityCategoryTest { -+ -+ @Test -+ public void test() throws IllegalAccessException { -+ -+ Map enumMonsterTypeFieldMap = Maps.newHashMap(); -+ for (Field field : EnumMonsterType.class.getDeclaredFields()) { -+ if (field.getType() == EnumMonsterType.class) { -+ enumMonsterTypeFieldMap.put( (EnumMonsterType) field.get(null), field.getName()); -+ } -+ } -+ -+ for (EntityCategory entityCategory : EntityCategory.values()) { -+ enumMonsterTypeFieldMap.remove(CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); -+ } -+ assertTrue(EnumMonsterType.class.getName() + " instance(s): " + Joiner.on(", ").join(enumMonsterTypeFieldMap.values()) + " do not have bukkit equivalents", enumMonsterTypeFieldMap.size() == 0); -+ } -+} diff --git a/Unmapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/Unmapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch deleted file mode 100644 index d91f63378b..0000000000 --- a/Unmapped-Spigot-Server-Patches/0735-Add-command-line-option-to-load-extra-plugin-jars-no.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Tue, 18 May 2021 14:39:44 -0700 -Subject: [PATCH] Add command line option to load extra plugin jars not in the - plugins folder - -ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 89244c152665c97cb539bea07fedd1774ed626f1..8209f188dbc932114268486a2ebd77df989a86ec 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -385,8 +385,13 @@ public final class CraftServer implements Server { - - File pluginFolder = (File) console.options.valueOf("plugins"); - -- if (pluginFolder.exists()) { -- Plugin[] plugins = pluginManager.loadPlugins(pluginFolder); -+ // Paper start -+ if (true || pluginFolder.exists()) { -+ if (!pluginFolder.exists()) { -+ pluginFolder.mkdirs(); -+ } -+ Plugin[] plugins = pluginManager.loadPlugins(pluginFolder, this.extraPluginJars()); -+ // Paper end - for (Plugin plugin : plugins) { - try { - String message = String.format("Loading %s", plugin.getDescription().getFullName()); -@@ -401,6 +406,18 @@ public final class CraftServer implements Server { - } - } - -+ // Paper start -+ private List extraPluginJars() { -+ @SuppressWarnings("unchecked") -+ final List jars = (List) this.console.options.valuesOf("add-plugin"); -+ return jars.stream() -+ .filter(File::exists) -+ .filter(File::isFile) -+ .filter(file -> file.getName().endsWith(".jar")) -+ .collect(java.util.stream.Collectors.toList()); -+ } -+ // Paper end -+ - public void enablePlugins(PluginLoadOrder type) { - if (type == PluginLoadOrder.STARTUP) { - helpMap.clear(); -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 6459ec144fa54a1e6ad1f0c40776321e95b41197..ecd1f0784493dfc758483b7912ce086c3b0d7aa0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -153,6 +153,12 @@ public class Main { - .ofType(String.class) - .defaultsTo("Unknown Server") - .describedAs("Name"); -+ -+ acceptsAll(asList("add-plugin", "add-extra-plugin-jar")) -+ .withRequiredArg() -+ .ofType(File.class) -+ .defaultsTo(new File[] {}) -+ .describedAs("Specify paths to extra plugin jars to be loaded in addition to those in the plugins folder. This argument can be specified multiple times, once for each extra plugin jar path."); - // Paper end - } - }; diff --git a/Unmapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/Unmapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch deleted file mode 100644 index 8f6ee51048..0000000000 --- a/Unmapped-Spigot-Server-Patches/0736-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 10 May 2021 15:46:57 -0700 -Subject: [PATCH] Fix incorrect status dataconverter for pre 1.13 chunks - -Vanilla was setting non-populated OR non-lit chunks to empty, but -really this is just completely wrong. It should be set to "carved" -at minmum, because pre 1.13 chunks went through 3 distinct stages -of generation: carving, population, and lighting - in this order. -There is no "empty" status, because a chunk was simply carved -or it didn't exist. So mapping any chunk data to empty is simply -invalid. - -If the chunk is terrain populated, then obviously it must be at -minmum "decorated." If the chunk is lit and populated, then it is marked -"mobs_spawned" (which is what Vanilla is doing, and this is the last -stage before moving to full so it looks correct). - -So now here is a table representing the new status conversion: - -Chunk is lit Chunk is populated Vanilla - F F empty - T F empty - F T empty - T T mobs_spawned - -Chunk is lit Chunk is populated Paper - F F carved - T F carved - F T decorated - T T mobs_spawned - -This should fix some problems converting old data, as the -changes here are going to prevent the chunk from being regenerated -incorrectly. - -diff --git a/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java b/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java -index 3a114931cb88791bf73d08accf13993ba8842af2..7c0efe98af0bf99b04c0be6d6208d13af6e3cee4 100644 ---- a/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java -+++ b/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java -@@ -43,13 +43,21 @@ public class DataConverterProtoChunk extends DataFix { - return dynamic.asStreamOpt().result(); - }); - Dynamic dynamic = (Dynamic) typed1.get(DSL.remainderFinder()); -- boolean flag = dynamic.get("TerrainPopulated").asBoolean(false) && (!dynamic.get("LightPopulated").asNumber().result().isPresent() || dynamic.get("LightPopulated").asBoolean(false)); -- -- dynamic = dynamic.set("Status", dynamic.createString(flag ? "mobs_spawned" : "empty")); -+ // Paper start - fix incorrect status conversion -+ // Vanilla is setting chunks to incorrect status here, they should be using at minimum carved. -+ // for populated chunks, it should be at minimum decorated -+ // and for lit and populated, mobs_spawned is correct (technically mobs_spawned should be for populated, -+ // but if it's not lit then it can't be set above lit) -+ final boolean terrainPopulated = dynamic.get("TerrainPopulated").asBoolean(false); -+ final boolean lightPopulated = dynamic.get("LightPopulated").asBoolean(false) || dynamic.get("LightPopulated").asNumber().result().isPresent(); -+ final String newStatus = !terrainPopulated ? "carved" : (lightPopulated ? "mobs_spawned" : "decorated"); -+ -+ dynamic = dynamic.set("Status", dynamic.createString(newStatus)); - dynamic = dynamic.set("hasLegacyStructureData", dynamic.createBoolean(true)); -- Dynamic dynamic1; -+ // Paper end - fix incorrect status conversion -+ Dynamic dynamic1; // Paper - decompile fix - -- if (flag) { -+ if (true) { // Paper - fix incorrect status conversion - Optional optional1 = dynamic.get("Biomes").asByteBufferOpt().result(); - - if (optional1.isPresent()) { -@@ -70,7 +78,7 @@ public class DataConverterProtoChunk extends DataFix { - }).collect(Collectors.toList()); - - if (optional.isPresent()) { -- ((Stream) optional.get()).forEach((dynamic2) -> { -+ optional.get().forEach((dynamic2) -> { // Paper - decompile fix - int j = dynamic2.get("x").asInt(0); - int k = dynamic2.get("y").asInt(0); - int l = dynamic2.get("z").asInt(0); -@@ -78,11 +86,11 @@ public class DataConverterProtoChunk extends DataFix { - - ((ShortList) list.get(k >> 4)).add(short0); - }); -+ Dynamic finalDynamic = dynamic; // Paper - decompile fix - dynamic = dynamic.set("ToBeTicked", dynamic.createList(list.stream().map((shortlist) -> { -- Stream stream = shortlist.stream(); -+ Stream stream = shortlist.stream(); // Paper - decompile fix - -- dynamic.getClass(); -- return dynamic.createList(stream.map(dynamic::createShort)); -+ return finalDynamic.createList(stream.map(finalDynamic::createShort)); - }))); - } - diff --git a/Unmapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch b/Unmapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch deleted file mode 100644 index 5eb9b4adc2..0000000000 --- a/Unmapped-Spigot-Server-Patches/0737-Fix-MC-148809-Increase-structure-block-data-length-t.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: SamB440 -Date: Fri, 21 May 2021 00:22:09 +0100 -Subject: [PATCH] Fix MC-148809: Increase structure block data length to 128 - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInStruct.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInStruct.java -index 2e19ac6b4e27c5d1bbefd5e99f8298650919d917..de3c33ae24e38471ab34d905f07992cb75dc0789 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInStruct.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInStruct.java -@@ -43,7 +43,7 @@ public class PacketPlayInStruct implements Packet { - this.f = new BlockPosition(MathHelper.clamp(packetdataserializer.readByte(), 0, 48), MathHelper.clamp(packetdataserializer.readByte(), 0, 48), MathHelper.clamp(packetdataserializer.readByte(), 0, 48)); - this.g = (EnumBlockMirror) packetdataserializer.a(EnumBlockMirror.class); - this.h = (EnumBlockRotation) packetdataserializer.a(EnumBlockRotation.class); -- this.i = packetdataserializer.e(12); -+ this.i = packetdataserializer.e(128); // Paper - Fix MC-148809, increase max character input to 128 - this.m = MathHelper.a(packetdataserializer.readFloat(), 0.0F, 1.0F); - this.n = packetdataserializer.j(); - byte b0 = packetdataserializer.readByte(); diff --git a/Unmapped-Spigot-Server-Patches/0738-Fix-and-optimise-world-force-upgrading.patch b/Unmapped-Spigot-Server-Patches/0738-Fix-and-optimise-world-force-upgrading.patch deleted file mode 100644 index 74f1536633..0000000000 --- a/Unmapped-Spigot-Server-Patches/0738-Fix-and-optimise-world-force-upgrading.patch +++ /dev/null @@ -1,411 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 20 May 2021 07:02:22 -0700 -Subject: [PATCH] Fix and optimise world force upgrading - -The WorldUpgrader class was incorrectly modified by -CB. It will store an IChunkLoader instance for all -dimension types in the world, but obviously with how -CB shifts around worlds only one dimension type exists -per world. But this would be OK if CB did this -change correctly. All IChunkLoader instances -will point to the same regionfiles. And all -IChunkLoader instances are going to be read from. - -This problem hasn't really been reported because -it relies on the persistent legacy data to be converted -as well to cause corruption. Why? Because the legacy -data is also shared, it will result in different -outputs from conversion (as once conversion for legacy -persistent data takes place, it is REMOVED - so the next -convert will _not_ have the data). Which means different -sizes on disk. Which means different regionfile sector -allocations. Which means there are 3 different possible -regionfile sector allocations in memory, and none of them -are going to be correct. - -I've fixed this by writing a world upgrader suited to -CB's changes to world folder format. It was brain dead -easy to add threading, so I did. - -diff --git a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java -new file mode 100644 -index 0000000000000000000000000000000000000000..db9f1241094a7529662ed643ba651d86ec86e09c ---- /dev/null -+++ b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java -@@ -0,0 +1,200 @@ -+package io.papermc.paper.world; -+ -+import com.mojang.datafixers.DataFixer; -+import net.minecraft.SharedConstants; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.resources.ResourceKey; -+import net.minecraft.util.worldupdate.WorldUpgrader; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.chunk.storage.IChunkLoader; -+import net.minecraft.world.level.chunk.storage.RegionFileCache; -+import net.minecraft.world.level.dimension.DimensionManager; -+import net.minecraft.world.level.dimension.WorldDimension; -+import net.minecraft.world.level.storage.Convertable; -+import net.minecraft.world.level.storage.WorldPersistentData; -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; -+import java.io.File; -+import java.io.IOException; -+import java.text.DecimalFormat; -+import java.util.concurrent.ExecutorService; -+import java.util.concurrent.Executors; -+import java.util.concurrent.ThreadFactory; -+import java.util.concurrent.atomic.AtomicInteger; -+import java.util.concurrent.atomic.AtomicLong; -+import java.util.function.Supplier; -+ -+public class ThreadedWorldUpgrader { -+ -+ private static final Logger LOGGER = LogManager.getLogger(); -+ -+ private final ResourceKey dimensionType; -+ private final ResourceKey worldKey; -+ private final String worldName; -+ private final ExecutorService threadPool; -+ private final DataFixer dataFixer; -+ private final boolean removeCaches; -+ -+ public ThreadedWorldUpgrader(final ResourceKey dimensionType, final ResourceKey worldKey, final String worldName, final int threads, -+ final DataFixer dataFixer, final boolean removeCaches) { -+ this.dimensionType = dimensionType; -+ this.worldKey = worldKey; -+ this.worldName = worldName; -+ this.threadPool = Executors.newFixedThreadPool(Math.max(1, threads), new ThreadFactory() { -+ private final AtomicInteger threadCounter = new AtomicInteger(); -+ -+ @Override -+ public Thread newThread(final Runnable run) { -+ final Thread ret = new Thread(run); -+ -+ ret.setName("World upgrader thread for world " + ThreadedWorldUpgrader.this.worldName + " #" + this.threadCounter.getAndIncrement()); -+ ret.setUncaughtExceptionHandler((thread, throwable) -> { -+ LOGGER.fatal("Error upgrading world", throwable); -+ }); -+ -+ return ret; -+ } -+ }); -+ this.dataFixer = dataFixer; -+ this.removeCaches = removeCaches; -+ } -+ -+ public void convert() { -+ final File worldFolder = Convertable.getFolder(new File(this.worldName), this.dimensionType); -+ final WorldPersistentData worldPersistentData = new WorldPersistentData(new File(worldFolder, "data"), this.dataFixer); -+ -+ final File regionFolder = new File(worldFolder, "region"); -+ -+ LOGGER.info("Force upgrading " + this.worldName); -+ LOGGER.info("Counting regionfiles for " + this.worldName); -+ final File[] regionFiles = regionFolder.listFiles((final File dir, final String name) -> { -+ return WorldUpgrader.getRegionfileRegex().matcher(name).matches(); -+ }); -+ if (regionFiles == null) { -+ LOGGER.info("Found no regionfiles to convert for world " + this.worldName); -+ return; -+ } -+ LOGGER.info("Found " + regionFiles.length + " regionfiles to convert"); -+ LOGGER.info("Starting conversion now for world " + this.worldName); -+ -+ final WorldInfo info = new WorldInfo(() -> worldPersistentData, -+ new IChunkLoader(regionFolder, this.dataFixer, false), this.removeCaches, this.worldKey); -+ -+ long expectedChunks = (long)regionFiles.length * (32L * 32L); -+ -+ for (final File regionFile : regionFiles) { -+ final ChunkCoordIntPair regionPos = RegionFileCache.getRegionFileCoordinates(regionFile); -+ if (regionPos == null) { -+ expectedChunks -= (32L * 32L); -+ continue; -+ } -+ -+ this.threadPool.execute(new ConvertTask(info, regionPos.x >> 5, regionPos.z >> 5)); -+ } -+ this.threadPool.shutdown(); -+ -+ final DecimalFormat format = new DecimalFormat("#0.00"); -+ -+ final long start = System.nanoTime(); -+ -+ while (!this.threadPool.isTerminated()) { -+ final long current = info.convertedChunks.get(); -+ -+ LOGGER.info("{}% completed ({} / {} chunks)...", format.format((double)current / (double)expectedChunks * 100.0), current, expectedChunks); -+ -+ try { -+ Thread.sleep(1000L); -+ } catch (final InterruptedException ignore) {} -+ } -+ -+ final long end = System.nanoTime(); -+ -+ try { -+ info.loader.close(); -+ } catch (final IOException ex) { -+ LOGGER.fatal("Failed to close chunk loader", ex); -+ } -+ LOGGER.info("Completed conversion. Took {}s, {} out of {} chunks needed to be converted/modified ({}%)", -+ (int)Math.ceil((end - start) * 1.0e-9), info.modifiedChunks.get(), expectedChunks, format.format((double)info.modifiedChunks.get() / (double)expectedChunks * 100.0)); -+ } -+ -+ private static final class WorldInfo { -+ -+ public final Supplier persistentDataSupplier; -+ public final IChunkLoader loader; -+ public final boolean removeCaches; -+ public final ResourceKey worldKey; -+ public final AtomicLong convertedChunks = new AtomicLong(); -+ public final AtomicLong modifiedChunks = new AtomicLong(); -+ -+ private WorldInfo(final Supplier persistentDataSupplier, final IChunkLoader loader, final boolean removeCaches, -+ final ResourceKey worldKey) { -+ this.persistentDataSupplier = persistentDataSupplier; -+ this.loader = loader; -+ this.removeCaches = removeCaches; -+ this.worldKey = worldKey; -+ } -+ } -+ -+ private static final class ConvertTask implements Runnable { -+ -+ private final WorldInfo worldInfo; -+ private final int regionX; -+ private final int regionZ; -+ -+ public ConvertTask(final WorldInfo worldInfo, final int regionX, final int regionZ) { -+ this.worldInfo = worldInfo; -+ this.regionX = regionX; -+ this.regionZ = regionZ; -+ } -+ -+ @Override -+ public void run() { -+ final int regionCX = this.regionX << 5; -+ final int regionCZ = this.regionZ << 5; -+ -+ final Supplier persistentDataSupplier = this.worldInfo.persistentDataSupplier; -+ final IChunkLoader loader = this.worldInfo.loader; -+ final boolean removeCaches = this.worldInfo.removeCaches; -+ final ResourceKey worldKey = this.worldInfo.worldKey; -+ -+ for (int cz = regionCZ; cz < (regionCZ + 32); ++cz) { -+ for (int cx = regionCX; cx < (regionCX + 32); ++cx) { -+ final ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(cx, cz); -+ try { -+ // no need to check the coordinate of the chunk, the regionfilecache does that for us -+ -+ NBTTagCompound chunkNBT = loader.read(chunkPos); -+ -+ if (chunkNBT == null) { -+ continue; -+ } -+ -+ final int versionBefore = IChunkLoader.getVersion(chunkNBT); -+ -+ chunkNBT = loader.getChunkData(worldKey, persistentDataSupplier, chunkNBT, chunkPos, null); -+ -+ boolean modified = versionBefore < SharedConstants.getGameVersion().getWorldVersion(); -+ -+ if (removeCaches) { -+ final NBTTagCompound level = chunkNBT.getCompound("Level"); -+ modified |= level.hasKey("Heightmaps"); -+ level.remove("Heightmaps"); -+ modified |= level.hasKey("isLightOn"); -+ level.remove("isLightOn"); -+ } -+ -+ if (modified) { -+ this.worldInfo.modifiedChunks.getAndIncrement(); -+ loader.write(chunkPos, chunkNBT); -+ } -+ } catch (final Exception ex) { -+ LOGGER.error("Error upgrading chunk {}", chunkPos, ex); -+ } finally { -+ this.worldInfo.convertedChunks.getAndIncrement(); -+ } -+ } -+ } -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index bf4051349917cc1d727fc5544237e0291cb6f1e6..15b972b4a93b8fe3655acec47bc84b0f2c4620a6 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -15,6 +15,7 @@ import java.nio.file.Paths; - import java.util.Optional; - import java.util.concurrent.CompletableFuture; - import java.util.function.BooleanSupplier; -+import io.papermc.paper.world.ThreadedWorldUpgrader; - import joptsimple.NonOptionArgumentSpec; - import joptsimple.OptionParser; - import joptsimple.OptionSet; -@@ -277,6 +278,15 @@ public class Main { - } - // Paper end - -+ // Paper start - fix and optimise world upgrading -+ public static void convertWorldButItWorks(ResourceKey dimensionType, ResourceKey worldKey, String worldName, -+ DataFixer dataFixer, boolean removeCaches) { -+ int threads = Runtime.getRuntime().availableProcessors() * 3 / 8; -+ final ThreadedWorldUpgrader worldUpgrader = new ThreadedWorldUpgrader(dimensionType, worldKey, worldName, threads, dataFixer, removeCaches); -+ worldUpgrader.convert(); -+ } -+ // Paper end - fix and optimise world upgrading -+ - public static void convertWorld(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, boolean flag, BooleanSupplier booleansupplier, ImmutableSet> immutableset) { // CraftBukkit - Main.LOGGER.info("Forcing world upgrade! {}", convertable_conversionsession.getLevelName()); // CraftBukkit - WorldUpgrader worldupgrader = new WorldUpgrader(convertable_conversionsession, datafixer, immutableset, flag); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index b3ebf5cd59c827b7426069eda0cb3d47b4386792..e47c9b7b64095f2a5cf6cb365550398eeeed724f 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -515,13 +515,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -- return true; -- }, worlddata.getGeneratorSettings().d().d().stream().map((entry1) -> { -- return ResourceKey.a(IRegistry.K, ((ResourceKey) entry1.getKey()).a()); -- }).collect(ImmutableSet.toImmutableSet())); -- } -+ // Paper - move down - - IWorldDataServer iworlddataserver = worlddata; - GeneratorSettings generatorsettings = worlddata.getGeneratorSettings(); -@@ -541,6 +535,14 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant worldKey = ResourceKey.a(IRegistry.L, dimensionKey.a()); - - if (dimensionKey == WorldDimension.OVERWORLD) { -diff --git a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java -index a4970654496c52fcd02c5c055ff5ac551bd19da3..dca2e9e45116df22d8c95d1be8f0a7e3c2d2b6b1 100644 ---- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java -+++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java -@@ -55,7 +55,7 @@ public class WorldUpgrader { - private volatile int m; - private final Object2FloatMap> n = Object2FloatMaps.synchronize(new Object2FloatOpenCustomHashMap(SystemUtils.k())); // CraftBukkit - private volatile IChatBaseComponent o = new ChatMessage("optimizeWorld.stage.counting"); -- private static final Pattern p = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); -+ private static final Pattern p = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); public static final Pattern getRegionfileRegex() { return p; } // Paper - OBFHELPER - private final WorldPersistentData q; - - public WorldUpgrader(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, ImmutableSet> immutableset, boolean flag) { // CraftBukkit -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 6581fe0d93a5c2e7b444a44c01726e02d4a28e63..f7f593a9e58b537109fa6ca1c783f6614f4bfad5 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -181,6 +181,15 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return typeKey; - } - -+ // Paper start - fix and optimise world upgrading -+ // copied from below -+ public static ResourceKey getDimensionKey(DimensionManager manager) { -+ return ((org.bukkit.craftbukkit.CraftServer)org.bukkit.Bukkit.getServer()).getHandle().getServer().customRegistry.a().c(manager).orElseThrow(() -> { -+ return new IllegalStateException("Unregistered dimension type: " + manager); -+ }); -+ } -+ // Paper end - fix and optimise world upgrading -+ - protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName()); // Spigot - this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -index 890362d28ab9cb760c73fe5014e144fb08ada6b8..e20b9e6c46093d48d5fa5eb3006087d4e998c205 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -@@ -113,6 +113,7 @@ public class IChunkLoader implements AutoCloseable { - return nbttagcompound; - } - -+ public static int getVersion(NBTTagCompound nbttagcompound) { return a(nbttagcompound); } // Paper - OBFHELPER - public static int a(NBTTagCompound nbttagcompound) { - return nbttagcompound.hasKeyOfType("DataVersion", 99) ? nbttagcompound.getInt("DataVersion") : -1; - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index ebb0d6988f87013ea5d523ab4a1b31cb669ccc43..74d826853389b8e01ffe2b076cf2b179d29da216 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -30,6 +30,28 @@ public class RegionFileCache implements AutoCloseable { // Paper - no final - - - // Paper start -+ public static ChunkCoordIntPair getRegionFileCoordinates(File file) { -+ String fileName = file.getName(); -+ if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) { -+ return null; -+ } -+ -+ String[] split = fileName.split("\\."); -+ -+ if (split.length != 4) { -+ return null; -+ } -+ -+ try { -+ int x = Integer.parseInt(split[1]); -+ int z = Integer.parseInt(split[2]); -+ -+ return new ChunkCoordIntPair(x << 5, z << 5); -+ } catch (NumberFormatException ex) { -+ return null; -+ } -+ } -+ - public synchronized RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronize for async io - return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 8209f188dbc932114268486a2ebd77df989a86ec..cebecee640ed5a7fc2b978e00ff7eb012228267d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1146,14 +1146,7 @@ public final class CraftServer implements Server { - } - worlddata.checkName(name); - worlddata.a(console.getServerModName(), console.getModded().isPresent()); -- -- if (console.options.has("forceUpgrade")) { -- net.minecraft.server.Main.convertWorld(worldSession, DataConverterRegistry.a(), console.options.has("eraseCache"), () -> { -- return true; -- }, worlddata.getGeneratorSettings().d().d().stream().map((entry) -> { -- return ResourceKey.a(IRegistry.K, ((ResourceKey) entry.getKey()).a()); -- }).collect(ImmutableSet.toImmutableSet())); -- } -+ // Paper - move down - - long j = BiomeManager.a(creator.seed()); - List list = ImmutableList.of(new MobSpawnerPhantom(), new MobSpawnerPatrol(), new MobSpawnerCat(), new VillageSiege(), new MobSpawnerTrader(worlddata)); -@@ -1170,6 +1163,14 @@ public final class CraftServer implements Server { - chunkgenerator = worlddimension.c(); - } - -+ // Paper start - fix and optimise world upgrading -+ if (console.options.has("forceUpgrade")) { -+ net.minecraft.server.Main.convertWorldButItWorks( -+ actualDimension, net.minecraft.world.level.World.getDimensionKey(dimensionmanager), worldSession.getLevelName(), DataConverterRegistry.getDataFixer(), console.options.has("eraseCache") -+ ); -+ } -+ // Paper end - fix and optimise world upgrading -+ - ResourceKey worldKey; - String levelName = this.getServer().getDedicatedServerProperties().levelName; - if (name.equals(levelName + "_nether")) { diff --git a/Unmapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch b/Unmapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch deleted file mode 100644 index ba3abe238f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0739-Add-Mob-lookAt-API.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 14 May 2021 13:42:17 -0500 -Subject: [PATCH] Add Mob#lookAt API - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 5c7fafeb7fab584eded30ebe415584132f4ab8af..6c024a5fdd290e5eb219e677e28718d663b72f25 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -852,14 +852,17 @@ public abstract class EntityInsentient extends EntityLiving { - - protected void mobTick() {} - -+ public int getMaxHeadXRot() { return O(); } // Paper - OBFHELPER - public int O() { - return 40; - } - -+ public int getMaxHeadYRot() { return Q(); } // Paper - OBFHELPER - public int Q() { - return 75; - } - -+ public int getHeadRotSpeed() { return ep(); } // Paper - OBFHELPER - public int ep() { - return 10; - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerLook.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerLook.java -index 3ce9edde641c8b8eea75479615bcd2866ffd2198..dadbaa7f43b8678b09c649e19a6eac8ec8b47d9d 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerLook.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerLook.java -@@ -20,18 +20,28 @@ public class ControllerLook { - this.a = entityinsentient; - } - -+ public void lookAt(Vec3D vec3d) { a(vec3d); } // Paper - OBFHELPER - public void a(Vec3D vec3d) { - this.a(vec3d.x, vec3d.y, vec3d.z); - } - -+ // Paper start -+ public void lookAt(Entity entity) { -+ this.lookAt(entity.locX(), getWantedY(entity), entity.locZ()); -+ } -+ // Paper end -+ -+ public void lookAt(Entity entity, float f, float f1) { a(entity, f, f1); } // Paper - OBFHELPER - public void a(Entity entity, float f, float f1) { - this.a(entity.locX(), b(entity), entity.locZ(), f, f1); - } - -+ public void lookAt(double d0, double d1, double d2) { a(d0, d1, d2); } // Paper - OBFHELPER - public void a(double d0, double d1, double d2) { - this.a(d0, d1, d2, (float) this.a.ep(), (float) this.a.O()); - } - -+ public void lookAt(double d0, double d1, double d2, float f, float f1) { a(d0, d1, d2, f, f1); } // Paper - OBFHELPER - public void a(double d0, double d1, double d2, float f, float f1) { - this.e = d0; - this.f = d1; -@@ -103,6 +113,7 @@ public class ControllerLook { - return f + f4; - } - -+ public static double getWantedY(Entity entity) { return b(entity); } // Paper - OBFHELPER - private static double b(Entity entity) { - return entity instanceof EntityLiving ? entity.getHeadY() : (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0D; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index 06cbe63ef04e0de824ac0b9d545b6da1f53701b3..125be4ca56d38c6cba1d1f4e7587abda075ee491 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -84,5 +84,53 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { - public boolean isInDaylight() { - return getHandle().isInDaylight(); - } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location) { -+ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); -+ getHandle().getControllerLook().lookAt(location.getX(), location.getY(), location.getZ()); -+ } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location, float headRotationSpeed, float maxHeadPitch) { -+ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); -+ getHandle().getControllerLook().lookAt(location.getX(), location.getY(), location.getZ(), headRotationSpeed, maxHeadPitch); -+ } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity) { -+ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); -+ getHandle().getControllerLook().lookAt(((CraftEntity) entity).getHandle()); -+ } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity, float headRotationSpeed, float maxHeadPitch) { -+ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); -+ getHandle().getControllerLook().lookAt(((CraftEntity) entity).getHandle(), headRotationSpeed, maxHeadPitch); -+ } -+ -+ @Override -+ public void lookAt(double x, double y, double z) { -+ getHandle().getControllerLook().lookAt(x, y, z); -+ } -+ -+ @Override -+ public void lookAt(double x, double y, double z, float headRotationSpeed, float maxHeadPitch) { -+ getHandle().getControllerLook().lookAt(x, y, z, headRotationSpeed, maxHeadPitch); -+ } -+ -+ @Override -+ public int getHeadRotationSpeed() { -+ return getHandle().getHeadRotSpeed(); -+ } -+ -+ @Override -+ public int getMaxHeadPitch() { -+ return getHandle().getMaxHeadXRot(); -+ } - // Paper end - } diff --git a/Unmapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch b/Unmapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch deleted file mode 100644 index 0d2f573873..0000000000 --- a/Unmapped-Spigot-Server-Patches/0740-Add-Unix-domain-socket-support.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Tue, 11 May 2021 17:39:22 -0400 -Subject: [PATCH] Add Unix domain socket support - -For Windows and ARM support, JEP-380 is required: -https://inside.java/2021/02/03/jep380-unix-domain-sockets-channels/ -This will be possible as of the Minecraft 1.17 Java version bump. - -Tested-by: Mariell Hoversholm -Reviewed-by: Mariell Hoversholm - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index f86f430598026a3a7e27fb8d40cfc5fe7b9b845d..bf0c01eaf593972bbb18c22cfdb3abd658ec6498 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -564,6 +564,11 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - // Spigot Start - public SocketAddress getRawAddress() - { -+ // Paper start - this can be nullable in the case of a Unix domain socket, so if it is, fake something -+ if (this.channel.remoteAddress() == null) { -+ return new java.net.InetSocketAddress(java.net.InetAddress.getLoopbackAddress(), 0); -+ } -+ // Paper end - return this.channel.remoteAddress(); - } - // Spigot End -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 04ca3ed64d8fb9bce38d715d3618ab5c73d8cbfa..1929b992be3aeaa37c7b04c458f0ee41a60c692e 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -225,6 +225,20 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - this.i(dedicatedserverproperties.enforceWhitelist); - // this.saveData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading - DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode); -+ // Paper start - Unix domain socket support -+ java.net.SocketAddress bindAddress; -+ if (this.getServerIp().startsWith("unix:")) { -+ if (!io.netty.channel.epoll.Epoll.isAvailable()) { -+ DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!"); -+ DedicatedServer.LOGGER.fatal("You are trying to use a Unix domain socket but you're not on a supported OS."); -+ return false; -+ } else if (!com.destroystokyo.paper.PaperConfig.velocitySupport && !org.spigotmc.SpigotConfig.bungee) { -+ DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!"); -+ DedicatedServer.LOGGER.fatal("Unix domain sockets require IPs to be forwarded from a proxy."); -+ return false; -+ } -+ bindAddress = new io.netty.channel.unix.DomainSocketAddress(this.getServerIp().substring("unix:".length())); -+ } else { - InetAddress inetaddress = null; - - if (!this.getServerIp().isEmpty()) { -@@ -234,12 +248,15 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - if (this.getPort() < 0) { - this.setPort(dedicatedserverproperties.serverPort); - } -+ bindAddress = new java.net.InetSocketAddress(inetaddress, this.getPort()); -+ } -+ // Paper end - - this.P(); - DedicatedServer.LOGGER.info("Starting Minecraft server on {}:{}", this.getServerIp().isEmpty() ? "*" : this.getServerIp(), this.getPort()); - - try { -- this.getServerConnection().a(inetaddress, this.getPort()); -+ this.getServerConnection().bind(bindAddress); // Paper - Unix domain socket support - } catch (IOException ioexception) { - DedicatedServer.LOGGER.warn("**** FAILED TO BIND TO PORT!"); - DedicatedServer.LOGGER.warn("The exception was: {}", ioexception.toString()); -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 74006c0af831c0e6a2b84b3638e397ab54984dc5..82540af8170f0b8cb52b13061ae8f956f1a6e46f 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -44,6 +44,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - this.c.setProtocol(EnumProtocol.LOGIN); - // CraftBukkit start - Connection throttle - try { -+ if (!(this.c.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress)) { // Paper - the connection throttle is useless when you have a Unix domain socket - long currentTime = System.currentTimeMillis(); - long connectionThrottle = this.b.server.getConnectionThrottle(); - InetAddress address = ((java.net.InetSocketAddress) this.c.getSocketAddress()).getAddress(); -@@ -72,6 +73,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - } - } - } -+ } // Paper - add closing bracket for if check above - } catch (Throwable t) { - org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); - } -@@ -120,8 +122,11 @@ public class HandshakeListener implements PacketHandshakingInListener { - //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! - String[] split = packethandshakinginsetprotocol.hostname.split("\00"); - if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper -+ // Paper start - Unix domain socket support -+ java.net.SocketAddress socketAddress = c.getSocketAddress(); - packethandshakinginsetprotocol.hostname = split[0]; -- c.socketAddress = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) c.getSocketAddress()).getPort()); -+ c.socketAddress = new java.net.InetSocketAddress(split[1], socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); -+ // Paper end - c.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); - } else - { -diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java -index 69fc2789df88344587b6052f93661ed38f24a503..06b0ed65905b9829564dfddd29012218af0f403d 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnection.java -@@ -70,7 +70,12 @@ public class ServerConnection { - this.c = true; - } - -+ // Paper start - public void a(@Nullable InetAddress inetaddress, int i) throws IOException { -+ bind(new java.net.InetSocketAddress(inetaddress, i)); -+ } -+ public void bind(java.net.SocketAddress address) throws IOException { -+ // Paper end - List list = this.listeningChannels; - - synchronized (this.listeningChannels) { -@@ -78,7 +83,11 @@ public class ServerConnection { - LazyInitVar lazyinitvar; - - if (Epoll.isAvailable() && this.e.l()) { -+ if (address instanceof io.netty.channel.unix.DomainSocketAddress) { -+ oclass = io.netty.channel.epoll.EpollServerDomainSocketChannel.class; -+ } else { - oclass = EpollServerSocketChannel.class; -+ } - lazyinitvar = ServerConnection.b; - ServerConnection.LOGGER.info("Using epoll channel type"); - } else { -@@ -106,7 +115,7 @@ public class ServerConnection { - ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object)); - io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper - } -- }).group((EventLoopGroup) lazyinitvar.a()).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit -+ }).group((EventLoopGroup) lazyinitvar.a()).localAddress(address)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit // Paper - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch b/Unmapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch deleted file mode 100644 index 20d8b726d4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0741-Add-EntityInsideBlockEvent.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 8 May 2021 18:02:36 -0700 -Subject: [PATCH] Add EntityInsideBlockEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBubbleColumn.java b/src/main/java/net/minecraft/world/level/block/BlockBubbleColumn.java -index efeae8cd002a3f801b8d5054389f9a0c74187fc4..e117853e8255cc4702e33ea7491a4e8d0d9b554a 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBubbleColumn.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBubbleColumn.java -@@ -33,6 +33,7 @@ public class BlockBubbleColumn extends Block implements IFluidSource { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - IBlockData iblockdata1 = world.getType(blockposition.up()); - - if (iblockdata1.isAir()) { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockButtonAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockButtonAbstract.java -index e62112f00d5c9c444aef4a142290ad28caa05264..be8e175e4f4fb2606a0393739d1a470bdacdb440 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockButtonAbstract.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockButtonAbstract.java -@@ -180,6 +180,7 @@ public abstract class BlockButtonAbstract extends BlockAttachable { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!world.isClientSide && this.v && !(Boolean) iblockdata.get(BlockButtonAbstract.POWERED)) { - this.e(iblockdata, world, blockposition); - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCactus.java b/src/main/java/net/minecraft/world/level/block/BlockCactus.java -index 9f1e9fc5361cd051b909e2e1b2095722064185da..dc0e87b2f7d2923822e45efb129c7c6da2790298 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCactus.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCactus.java -@@ -116,6 +116,7 @@ public class BlockCactus extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - CraftEventFactory.blockDamage = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); // CraftBukkit - entity.damageEntity(DamageSource.CACTUS, 1.0F); - CraftEventFactory.blockDamage = null; // CraftBukkit -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCampfire.java b/src/main/java/net/minecraft/world/level/block/BlockCampfire.java -index 21baa8fb99b0587da503e14e2b04abf3134d03bc..023128e5c737ad26e40e4019e70df856395addcb 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCampfire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCampfire.java -@@ -88,6 +88,7 @@ public class BlockCampfire extends BlockTileEntity implements IBlockWaterlogged - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!entity.isFireProof() && (Boolean) iblockdata.get(BlockCampfire.LIT) && entity instanceof EntityLiving && !EnchantmentManager.i((EntityLiving) entity)) { - entity.damageEntity(DamageSource.FIRE, (float) this.h); - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCauldron.java b/src/main/java/net/minecraft/world/level/block/BlockCauldron.java -index 66d0a08f250fc947ec2d978a527ad77e32114b84..7fc66d4bf6b6f84ce7c7bda282788abc855b3ea8 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCauldron.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCauldron.java -@@ -59,6 +59,7 @@ public class BlockCauldron extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - int i = (Integer) iblockdata.get(BlockCauldron.LEVEL); - float f = (float) blockposition.getY() + (6.0F + (float) (3 * i)) / 16.0F; - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCrops.java b/src/main/java/net/minecraft/world/level/block/BlockCrops.java -index 09f15d9087f1c40e5d50cb56f8c764ddaa992e41..32d71b6fc3fd0300386fb80e6d12d5f7c2361efe 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCrops.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCrops.java -@@ -160,6 +160,7 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (entity instanceof EntityRavager && !CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.getBlockData(), !world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { // CraftBukkit - world.a(blockposition, true, entity); - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java -index fc89b3bf5075497596885548d80e4ed0b800ea89..ed916f69747b44b75eb06db4cf27adaf5e47fd1e 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java -@@ -43,6 +43,7 @@ public class BlockEnderPortal extends BlockTileEntity { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (world instanceof WorldServer && !entity.isPassenger() && !entity.isVehicle() && entity.canPortal() && VoxelShapes.c(VoxelShapes.a(entity.getBoundingBox().d((double) (-blockposition.getX()), (double) (-blockposition.getY()), (double) (-blockposition.getZ()))), iblockdata.getShape(world, blockposition), OperatorBoolean.AND)) { - ResourceKey resourcekey = world.getTypeKey() == DimensionManager.THE_END ? World.OVERWORLD : World.THE_END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends - WorldServer worldserver = ((WorldServer) world).getMinecraftServer().getWorldServer(resourcekey); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -index 02047bf07c2008c7de8daf3d76b660e25b77bce8..a256ab003d3798407d2e9432006bfea161bec1d2 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -@@ -48,6 +48,7 @@ public abstract class BlockFireAbstract extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!entity.isFireProof()) { - entity.setFireTicks(entity.getFireTicks() + 1); - if (entity.getFireTicks() == 0) { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockHoney.java b/src/main/java/net/minecraft/world/level/block/BlockHoney.java -index d62cd3717f05c014f0ba26fc459318e10519def4..47b0ef3796413025cd5e10628f6ab92fead92ea9 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockHoney.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockHoney.java -@@ -49,6 +49,7 @@ public class BlockHoney extends BlockHalfTransparent { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (this.a(blockposition, entity)) { - this.a(entity, blockposition); - this.d(entity); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockHopper.java b/src/main/java/net/minecraft/world/level/block/BlockHopper.java -index f9f5d11dee04f4056395fb8edb61a4616051350a..3555c2bdba01bcfadbd72459d69a850da35d3bdc 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockHopper.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockHopper.java -@@ -197,6 +197,7 @@ public class BlockHopper extends BlockTileEntity { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - TileEntity tileentity = world.getTileEntity(blockposition); - - if (tileentity instanceof TileEntityHopper) { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -index 27573a0334b06f4b6ada672057695d8f8a2bcfc4..5bff21c47c608eeddf564270ba433f83ccaea1ea 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -@@ -45,6 +45,7 @@ public class BlockMinecartDetector extends BlockMinecartTrackAbstract { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!world.isClientSide) { - if (!(Boolean) iblockdata.get(BlockMinecartDetector.POWERED)) { - this.a(world, blockposition, iblockdata); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPortal.java b/src/main/java/net/minecraft/world/level/block/BlockPortal.java -index 5f797260eff317409a5039b88b01ad79ee2fdd91..f030aa3ddd001e018539ae93c238f2afb26e0fc2 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPortal.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPortal.java -@@ -82,6 +82,7 @@ public class BlockPortal extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!entity.isPassenger() && !entity.isVehicle() && entity.canPortal()) { - // CraftBukkit start - Entity in portal - EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ())); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateAbstract.java -index 5b03e2ddf31db372607e6a997840ebe7f179801f..4fc3cf7c255a183f3da19fd91c13cd5e3c0550b6 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateAbstract.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateAbstract.java -@@ -66,6 +66,7 @@ public abstract class BlockPressurePlateAbstract extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!world.isClientSide) { - int i = this.getPower(iblockdata); - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockSweetBerryBush.java b/src/main/java/net/minecraft/world/level/block/BlockSweetBerryBush.java -index 46459c3840ea23d11d2f44befc687018be2cf7e5..24c9863bd063390aa2911a86dc9c9d6c77f7ecd7 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockSweetBerryBush.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockSweetBerryBush.java -@@ -67,6 +67,7 @@ public class BlockSweetBerryBush extends BlockPlant implements IBlockFragilePlan - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (entity instanceof EntityLiving && entity.getEntityType() != EntityTypes.FOX && entity.getEntityType() != EntityTypes.BEE) { - entity.a(iblockdata, new Vec3D(0.800000011920929D, 0.75D, 0.800000011920929D)); - if (!world.isClientSide && (Integer) iblockdata.get(BlockSweetBerryBush.a) > 0 && (entity.D != entity.locX() || entity.F != entity.locZ())) { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTripwire.java b/src/main/java/net/minecraft/world/level/block/BlockTripwire.java -index 74037572010c40b363af62fd251d3f514a0940e9..46a4dd932d84bf72c1837e36add56f219d6b5e77 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTripwire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTripwire.java -@@ -119,6 +119,7 @@ public class BlockTripwire extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!world.isClientSide) { - if (!(Boolean) iblockdata.get(BlockTripwire.POWERED)) { - this.a(world, blockposition); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockWaterLily.java b/src/main/java/net/minecraft/world/level/block/BlockWaterLily.java -index f32993d037bad535ef9867ae7634da5d53681dba..97bb8c7677ca56692666e54bf67ec43d403d3eec 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockWaterLily.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockWaterLily.java -@@ -25,6 +25,7 @@ public class BlockWaterLily extends BlockPlant { - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { - super.a(iblockdata, world, blockposition, entity); -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (world instanceof WorldServer && entity instanceof EntityBoat && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { // CraftBukkit - world.a(new BlockPosition(blockposition), true, entity); - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockWeb.java b/src/main/java/net/minecraft/world/level/block/BlockWeb.java -index a574878b1e69538430d9967b708e8d6a5060233d..d88663610c4833004c2fd33b8570a67fc884d380 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockWeb.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockWeb.java -@@ -15,6 +15,7 @@ public class BlockWeb extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - entity.a(iblockdata, new Vec3D(0.25D, 0.05000000074505806D, 0.25D)); - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockWitherRose.java b/src/main/java/net/minecraft/world/level/block/BlockWitherRose.java -index 3c43e498fb3aa61fb7ee6592623581764b27f160..2692c205d099880205ccd73a739679f3946839ab 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockWitherRose.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockWitherRose.java -@@ -26,6 +26,7 @@ public class BlockWitherRose extends BlockFlowers { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!world.isClientSide && world.getDifficulty() != EnumDifficulty.PEACEFUL) { - if (entity instanceof EntityLiving) { - EntityLiving entityliving = (EntityLiving) entity; diff --git a/Unmapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch b/Unmapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch deleted file mode 100644 index 7c9a583959..0000000000 --- a/Unmapped-Spigot-Server-Patches/0742-Attributes-API-for-item-defaults.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 8 May 2021 15:01:54 -0700 -Subject: [PATCH] Attributes API for item defaults - - -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 7c9ef73983c2c7f4b7386a472e5a79dce7fa7ea7..0486a3158eb81947f78cef11aa4d4f141c40dfb5 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -274,6 +274,7 @@ public class Item implements IMaterial { - return false; - } - -+ public Multimap getAttributesForSlot(EnumItemSlot enumItemSlot) { return a(enumItemSlot); } // Paper - OBFHELPER - public Multimap a(EnumItemSlot enumitemslot) { - return ImmutableMultimap.of(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index a386beea01056a7fb448596ba45342d832a4c63d..6cb8608f8238c4a8c346b92ba672c8cc1c0cbcc4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -495,6 +495,19 @@ public final class CraftMagicNumbers implements UnsafeValues { - return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); - } - -+ @Override -+ public com.google.common.collect.Multimap getItemAttributes(org.bukkit.Material material, org.bukkit.inventory.EquipmentSlot equipmentSlot) { -+ Item item = this.getItem(material); -+ if (item == null) { -+ throw new IllegalArgumentException(material + " is not an item and therefore does not have attributes"); -+ } -+ com.google.common.collect.ImmutableMultimap.Builder attributeMapBuilder = com.google.common.collect.ImmutableMultimap.builder(); -+ item.getAttributesForSlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(equipmentSlot)).forEach((attributeBase, attributeModifier) -> { -+ attributeMapBuilder.put(org.bukkit.Registry.ATTRIBUTE.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.IRegistry.ATTRIBUTE.getKey(attributeBase))), org.bukkit.craftbukkit.attribute.CraftAttributeInstance.convert(attributeModifier)); -+ }); -+ return attributeMapBuilder.build(); -+ } -+ - @Override - public int getProtocolVersion() { - return net.minecraft.SharedConstants.getGameVersion().getProtocolVersion(); diff --git a/Unmapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/Unmapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch deleted file mode 100644 index 154ff25eb1..0000000000 --- a/Unmapped-Spigot-Server-Patches/0743-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alexander -Date: Thu, 6 May 2021 13:01:25 +0100 -Subject: [PATCH] Have CraftMerchantCustom emit PlayerPurchaseEvent - - -diff --git a/src/main/java/net/minecraft/world/item/trading/IMerchant.java b/src/main/java/net/minecraft/world/item/trading/IMerchant.java -index 5644affeadc51ac3209ee9a087b3d2dd887e401c..7c54ca6af424b9d31f73187df9015f5df84762f4 100644 ---- a/src/main/java/net/minecraft/world/item/trading/IMerchant.java -+++ b/src/main/java/net/minecraft/world/item/trading/IMerchant.java -@@ -19,7 +19,7 @@ public interface IMerchant { - - MerchantRecipeList getOffers(); - -- void a(MerchantRecipe merchantrecipe); -+ void a(MerchantRecipe merchantrecipe); default void handlePurchase(MerchantRecipe merchantRecipe) { a(merchantRecipe); } // Paper - OBFHELPER - - void k(ItemStack itemstack); - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -index 206c133ebc6c44038585236b0628543b8bed278c..a7230776b8e85d5d1873ab2dc4e10c5bf78889bb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -@@ -81,6 +81,35 @@ public class CraftMerchantCustom extends CraftMerchant { - - @Override - public void a(MerchantRecipe merchantrecipe) { -+ // Paper start -+ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerAbstract#b(MerchantRecipe)} */ -+ if (getTrader() instanceof net.minecraft.server.level.EntityPlayer) { -+ final net.minecraft.server.level.EntityPlayer trader = (net.minecraft.server.level.EntityPlayer) getTrader(); -+ final io.papermc.paper.event.player.PlayerPurchaseEvent event = new io.papermc.paper.event.player.PlayerPurchaseEvent( -+ trader.getBukkitEntity(), -+ merchantrecipe.asBukkit(), -+ false, // reward xp? -+ true); // should increase uses? -+ event.callEvent(); -+ if (event.isCancelled()) { -+ return; -+ } -+ final org.bukkit.inventory.MerchantRecipe eventTrade = event.getTrade(); -+ if (event.willIncreaseTradeUses()) { -+ eventTrade.setUses(eventTrade.getUses() + 1); -+ } -+ if (event.isRewardingExp() && eventTrade.hasExperienceReward()) { -+ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerTrader#b(MerchantRecipe)} */ -+ final int xp = 3 + net.minecraft.world.entity.Entity.SHARED_RANDOM.nextInt(4); -+ final World world = trader.getWorld(); -+ world.addEntity(new net.minecraft.world.entity.EntityExperienceOrb( -+ world, trader.locX(), trader.locY() + 0.5d, trader.locZ(), xp, -+ org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, trader, null)); -+ } -+ return; -+ } -+ // Paper end -+ - // increase recipe's uses - merchantrecipe.increaseUses(); - } diff --git a/Unmapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch b/Unmapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch deleted file mode 100644 index 291410ed1d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0744-Add-cause-to-Weather-ThunderChangeEvents.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Dec 2020 18:23:26 -0800 -Subject: [PATCH] Add cause to Weather/ThunderChangeEvents - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 6aace2155258d8257d53ebfcb20c37ea7497c02c..f68a252378a94c8fcab622d2d89d738aceab45a4 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -419,8 +419,8 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.worldDataServer.setClearWeatherTime(i); - this.worldDataServer.setWeatherDuration(j); - this.worldDataServer.setThunderDuration(j); -- this.worldDataServer.setStorm(flag); -- this.worldDataServer.setThundering(flag1); -+ this.worldDataServer.setStorm(flag, org.bukkit.event.weather.WeatherChangeEvent.Cause.COMMAND); // Paper -+ this.worldDataServer.setThundering(flag1, org.bukkit.event.weather.ThunderChangeEvent.Cause.COMMAND); // Paper - } - - public BiomeBase getBiomeBySeed(int i, int j, int k) { return a(i, j, k); } // Paper - OBFHELPER -@@ -482,8 +482,8 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.worldDataServer.setThunderDuration(j); - this.worldDataServer.setWeatherDuration(k); - this.worldDataServer.setClearWeatherTime(i); -- this.worldDataServer.setThundering(flag1); -- this.worldDataServer.setStorm(flag2); -+ this.worldDataServer.setThundering(flag1, org.bukkit.event.weather.ThunderChangeEvent.Cause.NATURAL); // Paper -+ this.worldDataServer.setStorm(flag2, org.bukkit.event.weather.WeatherChangeEvent.Cause.NATURAL); // Paper - } - - this.lastThunderLevel = this.thunderLevel; -@@ -885,14 +885,14 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - private void clearWeather() { - // CraftBukkit start -- this.worldDataServer.setStorm(false); -+ this.worldDataServer.setStorm(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - when passing the night - // If we stop due to everyone sleeping we should reset the weather duration to some other random value. - // Not that everyone ever manages to get the whole server to sleep at the same time.... - if (!this.worldDataServer.hasStorm()) { - this.worldDataServer.setWeatherDuration(0); - } - // CraftBukkit end -- this.worldDataServer.setThundering(false); -+ this.worldDataServer.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - when passing the night - // CraftBukkit start - // If we stop due to everyone sleeping we should reset the weather duration to some other random value. - // Not that everyone ever manages to get the whole server to sleep at the same time.... -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldDataServer.java b/src/main/java/net/minecraft/world/level/storage/WorldDataServer.java -index 202d0aea445003a6dc3355ff2f2663cc675d4504..16ebfe8d873ba05521e0a49156325f14e8bd6eb9 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldDataServer.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldDataServer.java -@@ -327,6 +327,11 @@ public class WorldDataServer implements IWorldDataServer, SaveData { - - @Override - public void setThundering(boolean flag) { -+ // Paper start -+ this.setThundering(flag, org.bukkit.event.weather.ThunderChangeEvent.Cause.UNKNOWN); -+ } -+ public void setThundering(boolean flag, org.bukkit.event.weather.ThunderChangeEvent.Cause cause) { -+ // Paper end - // CraftBukkit start - if (this.thundering == flag) { - return; -@@ -334,7 +339,7 @@ public class WorldDataServer implements IWorldDataServer, SaveData { - - org.bukkit.World world = Bukkit.getWorld(getName()); - if (world != null) { -- ThunderChangeEvent thunder = new ThunderChangeEvent(world, flag); -+ ThunderChangeEvent thunder = new ThunderChangeEvent(world, flag, cause); // Paper - Bukkit.getServer().getPluginManager().callEvent(thunder); - if (thunder.isCancelled()) { - return; -@@ -361,6 +366,12 @@ public class WorldDataServer implements IWorldDataServer, SaveData { - - @Override - public void setStorm(boolean flag) { -+ // Paper start -+ this.setStorm(flag, org.bukkit.event.weather.WeatherChangeEvent.Cause.UNKNOWN); -+ } -+ -+ public void setStorm(boolean flag, org.bukkit.event.weather.WeatherChangeEvent.Cause cause) { -+ // Paper end - // CraftBukkit start - if (this.raining == flag) { - return; -@@ -368,7 +379,7 @@ public class WorldDataServer implements IWorldDataServer, SaveData { - - org.bukkit.World world = Bukkit.getWorld(getName()); - if (world != null) { -- WeatherChangeEvent weather = new WeatherChangeEvent(world, flag); -+ WeatherChangeEvent weather = new WeatherChangeEvent(world, flag, cause); // Paper - Bukkit.getServer().getPluginManager().callEvent(weather); - if (weather.isCancelled()) { - return; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 3b3eda95c0ff8b129adedbae6561bba2d01c2f3a..9d858f91828d6c2787ff1dc677a247bcab172701 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1470,7 +1470,7 @@ public class CraftWorld implements World { - - @Override - public void setStorm(boolean hasStorm) { -- world.worldData.setStorm(hasStorm); -+ world.worldDataServer.setStorm(hasStorm, org.bukkit.event.weather.WeatherChangeEvent.Cause.PLUGIN); // Paper - setWeatherDuration(0); // Reset weather duration (legacy behaviour) - setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) - } -@@ -1492,7 +1492,7 @@ public class CraftWorld implements World { - - @Override - public void setThundering(boolean thundering) { -- world.worldDataServer.setThundering(thundering); -+ world.worldDataServer.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.PLUGIN); // Paper - setThunderDuration(0); // Reset weather duration (legacy behaviour) - setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) - } diff --git a/Unmapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch b/Unmapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch deleted file mode 100644 index a6ca6b4eca..0000000000 --- a/Unmapped-Spigot-Server-Patches/0745-More-Lidded-Block-API.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: LemonCaramel -Date: Sun, 23 May 2021 17:49:51 +0900 -Subject: [PATCH] More Lidded Block API - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -index 2bc4213c70be47ca8bbc24898cc92e43f4228821..d03c4d100783b5d9f882c010a63dda3451db3c2e 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -@@ -10,8 +10,9 @@ public class TileEntityEnderChest extends TileEntity { // Paper - Remove ITickab - - public float a; - public float b; -- public int c; -+ public int c; public int getViewerCount() { return c; } // Paper - OBFHELPER - private int g; -+ public boolean opened; // Paper - More Lidded Block API - - public TileEntityEnderChest() { - super(TileEntityTypes.ENDER_CHEST); -@@ -106,12 +107,14 @@ public class TileEntityEnderChest extends TileEntity { // Paper - Remove ITickab - - public void d() { - ++this.c; -+ if (opened) return; // Paper - More Lidded Block API - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); - doOpenLogic(); // Paper - } - - public void f() { - --this.c; -+ if (opened) return; // Paper - More Lidded Block API - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); - doCloseLogic(); // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java -index e27f5d689d689d4f65c285802bf327e96c113c46..f47fd41981bd89879627c2f0bb05d0ff70cc20fe 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java -@@ -59,4 +59,11 @@ public class CraftBarrel extends CraftLootable implements Barr - } - getTileEntity().opened = false; - } -+ -+ // Paper start - More Lidded Block API -+ @Override -+ public boolean isOpen() { -+ return getTileEntity().opened; -+ } -+ // Paper end - More Lidded Block API - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -index 54eb170fd533b0e91572601268fcbc167ed9bb5c..374034e659f856895843f3e33cce750d5cca0244 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -@@ -78,4 +78,11 @@ public class CraftChest extends CraftLootable implements Chest, - } - getTileEntity().opened = false; - } -+ -+ // Paper start - More Lidded Block API -+ @Override -+ public boolean isOpen() { -+ return getTileEntity().opened; -+ } -+ // Paper end - More Lidded Block API - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java -index 3c0b28faa86fb2ebb6165ff9efb0e7e41230c5e4..01192a3a1354d36c1d5541ddcf4037e983fd3cf9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java -@@ -14,4 +14,33 @@ public class CraftEnderChest extends CraftBlockEntityState - public CraftEnderChest(final Material material, final TileEntityEnderChest te) { - super(material, te); - } -+ -+ // Paper start - More Lidded Block API -+ @Override -+ public void open() { -+ requirePlaced(); -+ if (!getTileEntity().opened) { -+ net.minecraft.world.level.World world = getTileEntity().getWorld(); -+ world.playBlockAction(getTileEntity().getPosition(), getTileEntity().getBlock().getBlock(), 1, getTileEntity().getViewerCount() + 1); -+ world.playSound(null, getPosition(), net.minecraft.sounds.SoundEffects.BLOCK_ENDER_CHEST_OPEN, net.minecraft.sounds.SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); -+ } -+ getTileEntity().opened = true; -+ } -+ -+ @Override -+ public void close() { -+ requirePlaced(); -+ if (getTileEntity().opened) { -+ net.minecraft.world.level.World world = getTileEntity().getWorld(); -+ world.playBlockAction(getTileEntity().getPosition(), getTileEntity().getBlock().getBlock(), 1, 0); -+ world.playSound(null, getPosition(), net.minecraft.sounds.SoundEffects.BLOCK_ENDER_CHEST_CLOSE, net.minecraft.sounds.SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); -+ } -+ getTileEntity().opened = false; -+ } -+ -+ @Override -+ public boolean isOpen() { -+ return getTileEntity().opened; -+ } -+ // Paper end - More Lidded Block API - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java -index fcf2a1810729fda56e4064702f5f3b4d2b3f1523..ffd10dfdaf348625e1653e2fd8add5e58f895bdd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java -@@ -62,8 +62,15 @@ public class CraftShulkerBox extends CraftLootable impleme - if (getTileEntity().opened) { - World world = getTileEntity().getWorld(); - world.playBlockAction(getPosition(), getTileEntity().getBlock().getBlock(), 1, 0); -- world.playSound(null, getPosition(), SoundEffects.BLOCK_SHULKER_BOX_OPEN, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); -+ world.playSound(null, getPosition(), SoundEffects.BLOCK_SHULKER_BOX_CLOSE, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); // Paper - More Lidded Block API (Wrong sound) - } - getTileEntity().opened = false; - } -+ -+ // Paper start - More Lidded Block API -+ @Override -+ public boolean isOpen() { -+ return getTileEntity().opened; -+ } -+ // Paper end - More Lidded Block API - } diff --git a/Unmapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch b/Unmapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch deleted file mode 100644 index 7c600c021d..0000000000 --- a/Unmapped-Spigot-Server-Patches/0746-Add-PlayerKickEvent-causes.patch +++ /dev/null @@ -1,393 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 20:30:45 -0700 -Subject: [PATCH] Add PlayerKickEvent causes - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e47c9b7b64095f2a5cf6cb365550398eeeed724f..bf80e870e6a2a6fe1d4ae1bea355bcd7a0735d3b 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2044,7 +2044,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", this.player.getDisplayName().getString()); -- this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_PLAYER); // Paper - use configurable kick message & kick event cause - return; - } - } else { -@@ -348,7 +348,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - if (this.D && this.player.getRootVehicle().getRidingPassenger() == this.player) { - if (++this.E > 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getDisplayName().getString()); -- this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_VEHICLE); // Paper - use configurable kick message & kick event cause - return; - } - } else { -@@ -370,7 +370,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - if (this.isPendingPing()) { - if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected - PlayerConnection.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getName()); // more info -- this.disconnect(new ChatMessage("disconnect.timeout", new Object[0])); -+ this.disconnect(new ChatMessage("disconnect.timeout", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause - } - } else { - if (elapsedTime >= 15000L) { // 15 seconds -@@ -400,7 +400,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - - if (this.player.F() > 0L && this.minecraftServer.getIdleTimeout() > 0 && SystemUtils.getMonotonicMillis() - this.player.F() > (long) (this.minecraftServer.getIdleTimeout() * 1000 * 60)) { - this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854 -- this.disconnect(new ChatMessage("multiplayer.disconnect.idling")); -+ this.disconnect(new ChatMessage("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause - } - - } -@@ -425,14 +425,22 @@ public class PlayerConnection implements PacketListenerPlayIn { - - public void disconnect(String s) { - // Paper start -- this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); -+ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); -+ } -+ -+ public void disconnect(String s, PlayerKickEvent.Cause cause) { -+ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s), cause); - } - - public void disconnect(final IChatBaseComponent reason) { -- this.disconnect(PaperAdventure.asAdventure(reason)); -+ this.disconnect(PaperAdventure.asAdventure(reason), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); -+ } -+ -+ public void disconnect(final IChatBaseComponent reason, PlayerKickEvent.Cause cause) { -+ this.disconnect(PaperAdventure.asAdventure(reason), cause); - } - -- public void disconnect(net.kyori.adventure.text.Component reason) { -+ public void disconnect(net.kyori.adventure.text.Component reason, org.bukkit.event.player.PlayerKickEvent.Cause cause) { - // Paper end - // CraftBukkit start - fire PlayerKickEvent - if (this.processedDisconnect) { -@@ -440,7 +448,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure - -- PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure -+ PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), reason, leaveMessage, cause); // Paper - Adventure & kick event reason - - if (this.server.getServer().isRunning()) { - this.server.getPluginManager().callEvent(event); -@@ -518,7 +526,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - public void a(PacketPlayInVehicleMove packetplayinvehiclemove) { - PlayerConnectionUtils.ensureMainThread(packetplayinvehiclemove, this, this.player.getWorldServer()); - if (b(packetplayinvehiclemove)) { -- this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_vehicle_movement")); -+ this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_vehicle_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_VEHICLE_MOVEMENT); // Paper - kick event cause - } else { - Entity entity = this.player.getRootVehicle(); - -@@ -752,13 +760,13 @@ public class PlayerConnection implements PacketListenerPlayIn { - // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async - // CraftBukkit start - if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { // Paper start - split and make configurable -- minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause - return; - } - // Paper start - String str = packetplayintabcomplete.c(); int index = -1; - if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { -- minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause - return; - } - // Paper end -@@ -906,7 +914,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - // Paper start - validate pick item position - if (!(packetplayinpickitem.b() >= 0 && packetplayinpickitem.b() < this.player.inventory.items.size())) { - PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getDisplayName().getString()); -- this.disconnect("Invalid hotbar selection (Hacking?)"); -+ this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause - return; - } - this.player.inventory.c(packetplayinpickitem.b()); // Paper - Diff above if changed -@@ -1060,7 +1068,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - NBTTagList pageList = testStack.getTag().getList("pages", 8); - if (pageList.size() > 100) { - PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with too many pages"); -- minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause - return; - } - long byteTotal = 0; -@@ -1072,7 +1080,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; - if (byteLength > 256 * 4) { - PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with with a page too large!"); -- minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause - return; - } - byteTotal += byteLength; -@@ -1095,14 +1103,14 @@ public class PlayerConnection implements PacketListenerPlayIn { - - if (byteTotal > byteAllowed) { - PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); -- minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause - return; - } - } - // Paper end - // CraftBukkit start - if (this.lastBookTick + 20 > MinecraftServer.currentTick) { -- this.disconnect("Book edited too quickly!"); -+ this.disconnect("Book edited too quickly!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause - return; - } - this.lastBookTick = MinecraftServer.currentTick; -@@ -1214,7 +1222,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - public void a(PacketPlayInFlying packetplayinflying) { - PlayerConnectionUtils.ensureMainThread(packetplayinflying, this, this.player.getWorldServer()); - if (b(packetplayinflying)) { -- this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_player_movement")); -+ this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause - } else { - WorldServer worldserver = this.player.getWorldServer(); - -@@ -1613,7 +1621,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.dropCount++; - if (this.dropCount >= 20) { - LOGGER.warn(this.player.getName() + " dropped their items too quickly!"); -- this.disconnect("You dropped your items too quickly (Hacking?)"); -+ this.disconnect("You dropped your items too quickly (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause - return; - } - } -@@ -1926,7 +1934,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.player.resetIdleTimer(); - } else { - PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getDisplayName().getString()); -- this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit -+ this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // CraftBukkit // Paper - kick event cause - } - } - -@@ -1963,7 +1971,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - Waitable waitable = new Waitable() { - @Override - protected Object evaluate() { -- PlayerConnection.this.disconnect(new ChatMessage("multiplayer.disconnect.illegal_characters")); -+ PlayerConnection.this.disconnect(new ChatMessage("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause - return null; - } - }; -@@ -1978,7 +1986,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - throw new RuntimeException(e); - } - } else { -- this.disconnect(new ChatMessage("multiplayer.disconnect.illegal_characters")); -+ this.disconnect(new ChatMessage("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause - } - // CraftBukkit end - return; -@@ -2032,7 +2040,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - Waitable waitable = new Waitable() { - @Override - protected Object evaluate() { -- PlayerConnection.this.disconnect(new ChatMessage("disconnect.spam")); -+ PlayerConnection.this.disconnect(new ChatMessage("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause - return null; - } - }; -@@ -2047,7 +2055,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - throw new RuntimeException(e); - } - } else { -- this.disconnect(new ChatMessage("disconnect.spam")); -+ this.disconnect(new ChatMessage("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause - } - // CraftBukkit end - } -@@ -2320,7 +2328,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - // Spigot Start - if ( entity == player && !player.isSpectator() ) - { -- disconnect( "Cannot interact with self!" ); -+ disconnect( "Cannot interact with self!", org.bukkit.event.player.PlayerKickEvent.Cause.SELF_INTERACTION ); // Paper - kick event cause - return; - } - // Spigot End -@@ -2397,7 +2405,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - } else if (packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { - if (entity instanceof EntityItem || entity instanceof EntityExperienceOrb || entity instanceof EntityArrow || (entity == this.player && !player.isSpectator())) { // CraftBukkit -- this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_entity_attacked")); -+ this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_entity_attacked"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_ENTITY_ATTACKED); // Paper - kick event cause - PlayerConnection.LOGGER.warn("Player {} tried to attack an invalid entity", this.player.getDisplayName().getString()); - return; - } -@@ -2802,7 +2810,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - // Paper start - if (!Bukkit.isPrimaryThread()) { - if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { -- minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause - return; - } - } -@@ -3001,7 +3009,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } else if (!this.isExemptPlayer()) { - // Paper start - This needs to be handled on the main thread for plugins - minecraftServer.scheduleOnMain(() -> { -- this.disconnect(new ChatMessage("disconnect.timeout")); -+ this.disconnect(new ChatMessage("disconnect.timeout"), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause - }); - // Paper end - } -@@ -3047,7 +3055,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - } catch (Exception ex) { - PlayerConnection.LOGGER.error("Couldn\'t register custom payload", ex); -- this.disconnect("Invalid payload REGISTER!"); -+ this.disconnect("Invalid payload REGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause - } - } else if (packetplayincustompayload.tag.equals(CUSTOM_UNREGISTER)) { - try { -@@ -3057,7 +3065,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - } catch (Exception ex) { - PlayerConnection.LOGGER.error("Couldn\'t unregister custom payload", ex); -- this.disconnect("Invalid payload UNREGISTER!"); -+ this.disconnect("Invalid payload UNREGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause - } - } else { - try { -@@ -3076,7 +3084,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - server.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packetplayincustompayload.tag.toString(), data); - } catch (Exception ex) { - PlayerConnection.LOGGER.error("Couldn\'t dispatch custom payload", ex); -- this.disconnect("Invalid custom payload!"); -+ this.disconnect("Invalid custom payload!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause - } - } - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 2a76c3624c64e93509a96579f48c507e29901625..90776231b1faffb11e4394f555f336ca248e3004 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -720,7 +720,7 @@ public abstract class PlayerList { - while (iterator.hasNext()) { - entityplayer = (EntityPlayer) iterator.next(); - savePlayerFile(entityplayer); // CraftBukkit - Force the player's inventory to be saved -- entityplayer.playerConnection.disconnect(new ChatMessage("multiplayer.disconnect.duplicate_login", new Object[0])); -+ entityplayer.playerConnection.disconnect(new ChatMessage("multiplayer.disconnect.duplicate_login", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause - } - - // Instead of kicking then returning, we need to store the kick reason -@@ -1389,8 +1389,8 @@ public abstract class PlayerList { - public void shutdown(boolean isRestarting) { - // CraftBukkit start - disconnect safely - for (EntityPlayer player : this.players) { -- if (isRestarting) player.playerConnection.disconnect(org.spigotmc.SpigotConfig.restartMessage); else // Paper -- player.playerConnection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure -+ if (isRestarting) player.playerConnection.disconnect(org.spigotmc.SpigotConfig.restartMessage, org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); else // Paper - kick event cause (cause is never used here) -+ player.playerConnection.disconnect(this.server.server.shutdownMessage(), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); // CraftBukkit - add custom shutdown message // Paper - Adventure & KickEventCause (cause is never used here) - } - // CraftBukkit end - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 34395248e3daea47178cb40aad53680fbce73600..cfe6898dc373fe55a08acf5c90e200061aa7d0fc 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -499,16 +499,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - org.spigotmc.AsyncCatcher.catchOp("player kick"); // Spigot - if (getHandle().playerConnection == null) return; - -- getHandle().playerConnection.disconnect(message == null ? "" : message); -+ getHandle().playerConnection.disconnect(message == null ? "" : message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause - } - - // Paper start - @Override - public void kick(final net.kyori.adventure.text.Component message) { -+ kick(message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); -+ } -+ -+ @Override -+ public void kick(net.kyori.adventure.text.Component message, org.bukkit.event.player.PlayerKickEvent.Cause cause) { - org.spigotmc.AsyncCatcher.catchOp("player kick"); - final PlayerConnection connection = this.getHandle().playerConnection; - if (connection != null) { -- connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); -+ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message, cause); - } - } - // Paper end -diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index 6a408dc9286a60c3ca7830f88171919fb0fe6363..dc8da0448193a5fbf16cfe3b070923cfb8a23c6d 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 ( EntityPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) - { -- p.playerConnection.disconnect(SpigotConfig.restartMessage); -+ p.playerConnection.disconnect(SpigotConfig.restartMessage, 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/Unmapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch b/Unmapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch deleted file mode 100644 index 93cb1e1686..0000000000 --- a/Unmapped-Spigot-Server-Patches/0747-Limit-item-frame-cursors-on-maps.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yive -Date: Wed, 26 May 2021 15:09:33 -0700 -Subject: [PATCH] Limit item frame cursors on maps - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0dd0795af0d0deeff5637a2a1a4a165dec26af15..467f4bd13c58f6724cdda580b95a0d58f516ec12 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -817,4 +817,9 @@ public class PaperWorldConfig { - private void allowUsingSignsInsideSpawnProtection() { - allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); - } -+ -+ public int mapItemFrameCursorLimit = 128; -+ private void mapItemFrameCursorLimit() { -+ mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -index 1f9b710f2af3c5067b3c2b73bebb11f8e22c403e..97fe61dcd066ec0ee05e81fc22409d6aa6b3a6d5 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -@@ -279,8 +279,12 @@ public class WorldMap extends PersistentBase { - - WorldMapFrame worldmapframe1 = new WorldMapFrame(blockposition, entityitemframe.getDirection().get2DRotationValue() * 90, entityitemframe.getId()); - -+ // Paper start -+ if (this.decorations.size() < entityhuman.world.paperConfig.mapItemFrameCursorLimit) { - this.a(MapIcon.Type.FRAME, entityhuman.world, "frame-" + entityitemframe.getId(), (double) blockposition.getX(), (double) blockposition.getZ(), (double) (entityitemframe.getDirection().get2DRotationValue() * 90), (IChatBaseComponent) null); - this.n.put(worldmapframe1.e(), worldmapframe1); -+ } -+ // Paper end - } - - NBTTagCompound nbttagcompound = itemstack.getTag(); diff --git a/Unmapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch b/Unmapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch deleted file mode 100644 index df5245c824..0000000000 --- a/Unmapped-Spigot-Server-Patches/0748-Add-PufferFishStateChangeEvent.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Mon, 10 May 2021 16:59:05 +0100 -Subject: [PATCH] Add PufferFishStateChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java -index e9f20d387ccdacfbb1a48dc31e2a6cd4843a0d7b..4e4327b3cb84367534c6f5855cf8b89763b1419d 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java -@@ -89,25 +89,39 @@ public class EntityPufferFish extends EntityFish { - public void tick() { - if (!this.world.isClientSide && this.isAlive() && this.doAITick()) { - if (this.c > 0) { -+ boolean increase = true; // Paper - Add PufferFishStateChangeEvent - if (this.getPuffState() == 0) { -+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent - this.playSound(SoundEffects.ENTITY_PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.dH()); - this.setPuffState(1); -+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } else if (this.c > 40 && this.getPuffState() == 1) { -+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 2).callEvent()) { // Paper - Add PufferFishStateChangeEvent - this.playSound(SoundEffects.ENTITY_PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.dH()); - this.setPuffState(2); -+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } - -+ if (increase) { // Paper - Add PufferFishStateChangeEvent - ++this.c; -+ } // Paper - Add PufferFishStateChangeEvent - } else if (this.getPuffState() != 0) { -+ boolean increase = true; // Paper - Add PufferFishStateChangeEvent - if (this.d > 60 && this.getPuffState() == 2) { -+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent - this.playSound(SoundEffects.ENTITY_PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.dH()); - this.setPuffState(1); -+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } else if (this.d > 100 && this.getPuffState() == 1) { -+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 0).callEvent()) { // Paper - Add PufferFishStateChangeEvent - this.playSound(SoundEffects.ENTITY_PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.dH()); - this.setPuffState(0); -+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } - -+ if (increase) { // Paper - Add PufferFishStateChangeEvent - ++this.d; -+ } // Paper - Add PufferFishStateChangeEvent - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/Unmapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch deleted file mode 100644 index 841559fd82..0000000000 --- a/Unmapped-Spigot-Server-Patches/0749-Fix-PlayerBucketEmptyEvent-result-itemstack.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 20 May 2021 22:16:37 -0700 -Subject: [PATCH] Fix PlayerBucketEmptyEvent result itemstack - -Fixes SPIGOT-2560: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-2560 - -diff --git a/src/main/java/net/minecraft/world/item/ItemBucket.java b/src/main/java/net/minecraft/world/item/ItemBucket.java -index d126f668828e0788e369294c0b376ef52b344f2c..f97447d77890cd65b5613899c389483bcf82be01 100644 ---- a/src/main/java/net/minecraft/world/item/ItemBucket.java -+++ b/src/main/java/net/minecraft/world/item/ItemBucket.java -@@ -118,6 +118,13 @@ public class ItemBucket extends Item { - } - - protected ItemStack a(ItemStack itemstack, EntityHuman entityhuman) { -+ // Paper -+ if (itemLeftInHandAfterPlayerBucketEmptyEvent != null) { -+ ItemStack itemInHand = itemLeftInHandAfterPlayerBucketEmptyEvent; -+ itemLeftInHandAfterPlayerBucketEmptyEvent = null; -+ return itemInHand; -+ } -+ // Paper - return !entityhuman.abilities.canInstantlyBuild ? new ItemStack(Items.BUCKET) : itemstack; - } - -@@ -128,6 +135,7 @@ public class ItemBucket extends Item { - return a(entityhuman, world, blockposition, movingobjectpositionblock, null, null, null, null); - } - -+ private ItemStack itemLeftInHandAfterPlayerBucketEmptyEvent = null; // Paper - public boolean a(EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock, EnumDirection enumdirection, BlockPosition clicked, ItemStack itemstack, EnumHand enumhand) { - // Paper end - // CraftBukkit end -@@ -148,6 +156,9 @@ public class ItemBucket extends Item { - ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 - return false; - } -+ // Paper start -+ itemLeftInHandAfterPlayerBucketEmptyEvent = event.getItemStack().equals(CraftItemStack.asNewCraftStack(net.minecraft.world.item.Items.BUCKET)) ? null : CraftItemStack.asNMSCopy(event.getItemStack()); -+ // Paper end - } - // CraftBukkit end - if (!flag1) { diff --git a/Unmapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch b/Unmapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch deleted file mode 100644 index a407870cd4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0750-Add-option-to-fix-items-merging-through-walls.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: GioSDA -Date: Wed, 10 Mar 2021 10:06:45 -0800 -Subject: [PATCH] Add option to fix items merging through walls - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 467f4bd13c58f6724cdda580b95a0d58f516ec12..25db335f457eefd13798394ebfb6b6684be26610 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -822,4 +822,9 @@ public class PaperWorldConfig { - private void mapItemFrameCursorLimit() { - mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); - } -+ -+ public boolean fixItemsMergingThroughWalls; -+ private void fixItemsMergingThroughWalls() { -+ fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 575833807ff647f30d7c2b7abcd01701c7dec85b..8b79220c27292f9b92d9884bbbe4b16d7762343c 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -228,6 +228,14 @@ public class EntityItem extends Entity { - EntityItem entityitem = (EntityItem) iterator.next(); - - if (entityitem.z()) { -+ // Paper Start - Fix items merging through walls -+ if (this.world.paperConfig.fixItemsMergingThroughWalls) { -+ net.minecraft.world.level.RayTrace rayTrace = new net.minecraft.world.level.RayTrace(this.getPositionVector(), entityitem.getPositionVector(), -+ net.minecraft.world.level.RayTrace.BlockCollisionOption.COLLIDER, net.minecraft.world.level.RayTrace.FluidCollisionOption.NONE, this); -+ net.minecraft.world.phys.MovingObjectPositionBlock rayTraceResult = world.rayTrace(rayTrace); -+ if (rayTraceResult.getType() == net.minecraft.world.phys.MovingObjectPosition.EnumMovingObjectType.BLOCK) continue; -+ } -+ // Paper End - this.a(entityitem); - if (this.dead) { - break; diff --git a/Unmapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch b/Unmapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch deleted file mode 100644 index a19790a857..0000000000 --- a/Unmapped-Spigot-Server-Patches/0751-Add-BellRevealRaiderEvent.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Wed, 26 May 2021 17:09:07 -0400 -Subject: [PATCH] Add BellRevealRaiderEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -index 84f9f52c5b632621b509448ac1c760f64de6b062..83626417aa9a00096680851a9a14f52f84fc7887 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -@@ -6,6 +6,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.core.IPosition; - import net.minecraft.core.particles.Particles; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.tags.Tag; -@@ -181,6 +182,7 @@ public class TileEntityBell extends TileEntity implements ITickable { - } - - private void b(EntityLiving entityliving) { -+ if (!new io.papermc.paper.event.block.BellRevealRaiderEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, position)), entityliving.getBukkitEntity()).callEvent()) return; // Paper - BellRevealRaiderEvent - entityliving.addEffect(new MobEffect(MobEffects.GLOWING, 60)); - } - } diff --git a/Unmapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch b/Unmapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch deleted file mode 100644 index 35b32af72a..0000000000 --- a/Unmapped-Spigot-Server-Patches/0752-Fix-invulnerable-end-crystals.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Max Lee -Date: Thu, 27 May 2021 14:52:30 -0700 -Subject: [PATCH] Fix invulnerable end crystals - -MC-108513 - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 25db335f457eefd13798394ebfb6b6684be26610..5c91c007691efeea1d4383efcd1ca06990d0660c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -827,4 +827,9 @@ public class PaperWorldConfig { - private void fixItemsMergingThroughWalls() { - fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); - } -+ -+ public boolean fixInvulnerableEndCrystalExploit = true; -+ private void fixInvulnerableEndCrystalExploit() { -+ fixInvulnerableEndCrystalExploit = getBoolean("unsupported-settings.fix-invulnerable-end-crystal-exploit", fixInvulnerableEndCrystalExploit); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java -index 9658d93615a51375204481cfe0a1fce6f105fd70..5d48c2640f776c9e29598e19afe779ed6997acfc 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java -@@ -30,6 +30,7 @@ public class EntityEnderCrystal extends Entity { - private static final DataWatcherObject> c = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.m); - private static final DataWatcherObject d = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.i); - public int b; -+ public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals - - public EntityEnderCrystal(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -66,6 +67,17 @@ public class EntityEnderCrystal extends Entity { - } - // CraftBukkit end - } -+ // Paper start - Fix invulnerable end crystals -+ if (this.world.paperConfig.fixInvulnerableEndCrystalExploit && this.generatedByDragonFight && this.isInvulnerable()) { -+ if ((this.origin.getWorld() != null && !((WorldServer) this.world).uuid.equals(this.origin.getWorld().getUID())) -+ || ((WorldServer) this.world).getDragonBattle() == null -+ || ((WorldServer) this.world).getDragonBattle().respawnPhase == null -+ || ((WorldServer) this.world).getDragonBattle().respawnPhase.ordinal() > net.minecraft.world.level.dimension.end.EnumDragonRespawn.SUMMONING_DRAGON.ordinal()) { -+ this.setInvulnerable(false); -+ this.setBeamTarget(null); -+ } -+ } -+ // Paper end - } - - } -@@ -77,6 +89,7 @@ public class EntityEnderCrystal extends Entity { - } - - nbttagcompound.setBoolean("ShowBottom", this.isShowingBottom()); -+ if (this.generatedByDragonFight) nbttagcompound.setBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals - } - - @Override -@@ -88,6 +101,7 @@ public class EntityEnderCrystal extends Entity { - if (nbttagcompound.hasKeyOfType("ShowBottom", 1)) { - this.setShowingBottom(nbttagcompound.getBoolean("ShowBottom")); - } -+ if (nbttagcompound.hasKeyOfType("Paper.GeneratedByDragonFight", 1)) this.generatedByDragonFight = nbttagcompound.getBoolean("Paper.GeneratedByDragonFight"); // Paper - Fix invulnerable end crystals - - } - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEnder.java b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEnder.java -index dd623702131eaa1a65937a19a0e986e865322258..1bf09c99ba318813755ea3d3456d0fbb60847e5c 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEnder.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEnder.java -@@ -42,7 +42,7 @@ public class WorldGenEnder extends WorldGenerator list = worldgenfeatureendspikeconfiguration.c(); - - if (list.isEmpty()) { -@@ -106,6 +106,7 @@ public class WorldGenEnder extends WorldGenerator -Date: Fri, 19 Mar 2021 23:39:09 -0400 -Subject: [PATCH] Add ElderGuardianAppearanceEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java -index 9bd6f5d988c1e50e1bb729c407178b9cbcc62115..300efeb98bb68b24faa68a4af9d703bf2b8c405c 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java -@@ -77,10 +77,12 @@ public class EntityGuardianElder extends EntityGuardian { - while (iterator.hasNext()) { - EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - -+ if (new io.papermc.paper.event.entity.ElderGuardianAppearanceEvent(getBukkitEntity(), entityplayer.getBukkitEntity()).callEvent()) { // Paper - Add Guardian Appearance Event - if (!entityplayer.hasEffect(mobeffectlist) || entityplayer.getEffect(mobeffectlist).getAmplifier() < 2 || entityplayer.getEffect(mobeffectlist).getDuration() < 1200) { - entityplayer.playerConnection.sendPacket(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.k, this.isSilent() ? 0.0F : 1.0F)); - entityplayer.addEffect(new MobEffect(mobeffectlist, 6000, 2), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit - } -+ } // Paper - Add Guardian Appearance Event - } - } - diff --git a/Unmapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch b/Unmapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch deleted file mode 100644 index 4839fe3bfb..0000000000 --- a/Unmapped-Spigot-Server-Patches/0754-Reset-villager-inventory-on-cancelled-pickup-event.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 1 Jun 2021 22:05:08 -0500 -Subject: [PATCH] Reset villager inventory on cancelled pickup event - - -diff --git a/src/main/java/net/minecraft/world/InventorySubcontainer.java b/src/main/java/net/minecraft/world/InventorySubcontainer.java -index 12dad3fe0eee8b0cd8959df6dba449d90bc95844..b8aca5f1c950c8ab28c432d93a6cec5d32e48b9e 100644 ---- a/src/main/java/net/minecraft/world/InventorySubcontainer.java -+++ b/src/main/java/net/minecraft/world/InventorySubcontainer.java -@@ -34,6 +34,16 @@ public class InventorySubcontainer implements IInventory, AutoRecipeOutput { - return this.items; - } - -+ // Paper start -+ public void setContents(List items) { -+ this.items.clear(); -+ for(int i = 0; i < items.size(); i++) { -+ this.items.set(i, items.get(i)); -+ } -+ this.update(); -+ } -+ // Paper end -+ - public void onOpen(CraftHumanEntity who) { - transaction.add(who); - } -@@ -148,6 +158,7 @@ public class InventorySubcontainer implements IInventory, AutoRecipeOutput { - return itemstack; - } - -+ public ItemStack addItem(ItemStack itemstack) { return a(itemstack); } // Paper - OBFHELPER - public ItemStack a(ItemStack itemstack) { - ItemStack itemstack1 = itemstack.cloneItemStack(); - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index c29f05b6fd0664345d8d09f898777a3e44f866c4..85374ac8f5460790de03b47d7c3ce19ed5596afe 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -845,15 +845,19 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - - // CraftBukkit start -- ItemStack remaining = new InventorySubcontainer(inventorysubcontainer).a(itemstack); -- if (CraftEventFactory.callEntityPickupItemEvent(this, entityitem, remaining.getCount(), false).isCancelled()) { -+ // Paper start -+ List contentsSnapshot = new java.util.ArrayList<>(inventorysubcontainer.getContents()); -+ ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); -+ if (CraftEventFactory.callEntityPickupItemEvent(this, entityitem, itemstack1.getCount(), false).isCancelled()) { -+ inventorysubcontainer.setContents(contentsSnapshot); -+ // Paper end - return; - } - // CraftBukkit end - - this.a(entityitem); - this.receive(entityitem, itemstack.getCount()); -- ItemStack itemstack1 = inventorysubcontainer.a(itemstack); -+ // ItemStack itemstack1 = inventorysubcontainer.a(itemstack); // Paper - moved up - - if (itemstack1.isEmpty()) { - entityitem.die(); diff --git a/Unmapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch b/Unmapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch deleted file mode 100644 index 211ffbfc31..0000000000 --- a/Unmapped-Spigot-Server-Patches/0755-Fix-dangerous-end-portal-logic.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 4 Jun 2021 17:06:52 -0400 -Subject: [PATCH] Fix dangerous end portal logic - -End portals could teleport entities during move calls. Stupid -logic given the caller will never expect that kind of thing, -and will result in all kinds of dupes. - -Move the tick logic into the post tick, where portaling was -designed to happen in the first place. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 558af73ac16550ee6964c4dce681a404633b2552..75bcfb3a2b4a104aeebb2fe3298714b2e5b569d2 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1023,6 +1023,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - return b(worldserver, TeleportCause.UNKNOWN); - } - -+ @Nullable public final Entity changeDimension(WorldServer worldserver, PlayerTeleportEvent.TeleportCause cause) { return this.b(worldserver, cause); } // Paper - OBFHELPER - @Nullable - public Entity b(WorldServer worldserver, PlayerTeleportEvent.TeleportCause cause) { - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 89b2be0e9e42d65b7d2d2833de4e6cd1c6e17e8e..6e1304f7169c11f67c573b2c8dc11825bcc7da0d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -314,6 +314,37 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // Paper end - optimise entity tracking - -+ // Paper start - make end portalling safe -+ public BlockPosition portalBlock; -+ public WorldServer portalWorld; -+ public void tickEndPortal() { -+ BlockPosition pos = this.portalBlock; -+ WorldServer world = this.portalWorld; -+ this.portalBlock = null; -+ this.portalWorld = null; -+ -+ if (pos == null || world == null || world != this.world) { -+ return; -+ } -+ -+ if (this.isPassenger() || this.isVehicle() || !this.canPortal() || this.dead || !this.valid || !this.isAlive()) { -+ return; -+ } -+ -+ ResourceKey resourcekey = world.getTypeKey() == DimensionManager.THE_END ? World.OVERWORLD : World.THE_END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends -+ WorldServer worldserver = world.getMinecraftServer().getWorldServer(resourcekey); -+ -+ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(this.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); -+ event.callEvent(); -+ -+ if (this instanceof EntityPlayer) { -+ ((EntityPlayer)this).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); -+ return; -+ } -+ this.teleportTo(worldserver, null); -+ } -+ // Paper end - make end portalling safe -+ - public Entity(EntityTypes entitytypes, World world) { - this.id = Entity.entityCount.incrementAndGet(); - this.passengers = Lists.newArrayList(); -@@ -2299,6 +2330,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - this.E(); -+ this.tickEndPortal(); // Paper - make end portalling safe - } - } - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java -index ed916f69747b44b75eb06db4cf27adaf5e47fd1e..9483d75fbe2a8c8f7cce00355e93ff1f943f3444 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java -@@ -52,16 +52,10 @@ public class BlockEnderPortal extends BlockTileEntity { - // return; // CraftBukkit - always fire event in case plugins wish to change it - } - -- // CraftBukkit start - Entity in portal -- EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ())); -- world.getServer().getPluginManager().callEvent(event); -- -- if (entity instanceof EntityPlayer) { -- ((EntityPlayer) entity).b(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); -- return; -- } -- // CraftBukkit end -- entity.b(worldserver); -+ // Paper start - move all of this logic into portal tick -+ entity.portalWorld = ((WorldServer)world); -+ entity.portalBlock = blockposition.immutableCopy(); -+ // Paper end - move all of this logic into portal tick - } - - } diff --git a/Unmapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch b/Unmapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch deleted file mode 100644 index de1cd74d97..0000000000 --- a/Unmapped-Spigot-Server-Patches/0756-Make-item-validations-configurable.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 4 Jun 2021 12:12:35 -0700 -Subject: [PATCH] Make item validations configurable - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index efc1e42d606e1c9feb1a4871c0714933ae92a1b2..7acf077bc131af718c7548cc29deef558c04e463 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -486,4 +486,19 @@ public class PaperConfig { - enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); - enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); - } -+ -+ public static int itemValidationDisplayNameLength = 8192; -+ public static int itemValidationLocNameLength = 8192; -+ public static int itemValidationLoreLineLength = 8192; -+ public static int itemValidationBookTitleLength = 8192; -+ public static int itemValidationBookAuthorLength = 8192; -+ public static int itemValidationBookPageLength = 16384; -+ private static void itemValidationSettings() { -+ itemValidationDisplayNameLength = getInt("settings.item-validation.display-name", itemValidationDisplayNameLength); -+ itemValidationLocNameLength = getInt("settings.item-validation.loc-name", itemValidationLocNameLength); -+ itemValidationLoreLineLength = getInt("settings.item-validation.lore-line", itemValidationLoreLineLength); -+ itemValidationBookTitleLength = getInt("settings.item-validation.book.title", itemValidationBookTitleLength); -+ itemValidationBookAuthorLength = getInt("settings.item-validation.book.author", itemValidationBookAuthorLength); -+ itemValidationBookPageLength = getInt("settings.item-validation.book.page", itemValidationBookPageLength); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index 1a4c1763e883e445433b3780fe20db7f62b780e8..bf1b6fa34b32730b493c37d3a0aa69a904c2d2b6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -92,11 +92,11 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - super(tag); - - if (tag.hasKey(BOOK_TITLE.NBT)) { -- this.title = limit( tag.getString(BOOK_TITLE.NBT), 8192 ); // Spigot -+ this.title = limit( tag.getString(BOOK_TITLE.NBT), com.destroystokyo.paper.PaperConfig.itemValidationBookTitleLength); // Spigot // Paper - make configurable - } - - if (tag.hasKey(BOOK_AUTHOR.NBT)) { -- this.author = limit( tag.getString(BOOK_AUTHOR.NBT), 8192 ); // Spigot -+ this.author = limit( tag.getString(BOOK_AUTHOR.NBT), com.destroystokyo.paper.PaperConfig.itemValidationBookAuthorLength ); // Spigot // Paper - make configurable - } - - if (tag.hasKey(RESOLVED.NBT)) { -@@ -124,7 +124,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - } else { - page = validatePage(page); - } -- this.pages.add( limit( page, 16384 ) ); // Spigot -+ this.pages.add( limit( page, com.destroystokyo.paper.PaperConfig.itemValidationBookPageLength ) ); // Spigot // Paper - make configurable - } - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 5c1319a86f6314c1d0a979af34424ee025a8030f..3db4826139f3e1f3859c04bae72310bfe2c53c1d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -358,18 +358,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - NBTTagCompound display = tag.getCompound(DISPLAY.NBT); - - if (display.hasKey(NAME.NBT)) { -- displayName = limit( display.getString(NAME.NBT), 8192 ); // Spigot -+ displayName = limit( display.getString(NAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationDisplayNameLength); // Spigot // Paper - make configurable - } - - if (display.hasKey(LOCNAME.NBT)) { -- locName = limit( display.getString(LOCNAME.NBT), 8192 ); // Spigot -+ locName = limit( display.getString(LOCNAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationLocNameLength ); // Spigot // Paper - make configurable - } - - if (display.hasKey(LORE.NBT)) { - NBTTagList list = display.getList(LORE.NBT, CraftMagicNumbers.NBT.TAG_STRING); - lore = new ArrayList(list.size()); - for (int index = 0; index < list.size(); index++) { -- String line = limit( list.getString(index), 8192 ); // Spigot -+ String line = limit( list.getString(index), com.destroystokyo.paper.PaperConfig.itemValidationLoreLineLength ); // Spigot // Paper - make configurable - lore.add(line); - } - } diff --git a/Unmapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch b/Unmapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch deleted file mode 100644 index 7398a6e72f..0000000000 --- a/Unmapped-Spigot-Server-Patches/0757-Add-more-line-of-sight-methods.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TwoLeggedCat <80929284+TwoLeggedCat@users.noreply.github.com> -Date: Sat, 29 May 2021 14:33:25 -0500 -Subject: [PATCH] Add more line of sight methods - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 2657dd71213455e2da3a4ff4d338a33896ffe855..b7b07b652b29e6f84f87fc92add99ce68f8bbd09 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3094,6 +3094,7 @@ public abstract class EntityLiving extends Entity { - Vec3D vec3d = new Vec3D(this.locX(), this.getHeadY(), this.locZ()); - Vec3D vec3d1 = new Vec3D(entity.locX(), entity.getHeadY(), entity.locZ()); - -+ // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists - return this.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, this)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 9d858f91828d6c2787ff1dc677a247bcab172701..02198dbe9e80c2990e8a09b2b763748dae727a03 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -333,6 +333,17 @@ public class CraftWorld implements World { - public io.papermc.paper.world.MoonPhase getMoonPhase() { - return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); - } -+ -+ @Override -+ public boolean lineOfSightExists(Location from, Location to) { -+ Validate.notNull(from, "from parameter in lineOfSightExists cannot be null"); -+ Validate.notNull(to, "to parameter in lineOfSightExists cannot be null"); -+ if (from.getWorld() != to.getWorld()) return false; -+ Vec3D vec3d = new Vec3D(from.getX(), from.getY(), from.getZ()); -+ Vec3D vec3d1 = new Vec3D(to.getX(), to.getY(), to.getZ()); -+ -+ return this.getHandle().rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, null)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS; -+ } - // Paper end - - private static final Random rand = new Random(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 32428b1260bbc4bae67ec74969c67f71272de418..592dacf8cc924caac339a8810ba5b0d85448ed90 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -561,6 +561,17 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().hasLineOfSight(((CraftEntity) other).getHandle()); - } - -+ // Paper start -+ @Override -+ public boolean hasLineOfSight(Location loc) { -+ if (this.getHandle().world != ((CraftWorld) loc.getWorld()).getHandle()) return false; -+ Vec3D vec3d = new Vec3D(this.getHandle().locX(), this.getHandle().getHeadY(), this.getHandle().locZ()); -+ Vec3D vec3d1 = new Vec3D(loc.getX(), loc.getY(), loc.getZ()); -+ -+ return this.getHandle().world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, this.getHandle())).getType() == MovingObjectPosition.EnumMovingObjectType.MISS; -+ } -+ // Paper end -+ - @Override - public boolean getRemoveWhenFarAway() { - return getHandle() instanceof EntityInsentient && !((EntityInsentient) getHandle()).persistent; diff --git a/Unmapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch b/Unmapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch deleted file mode 100644 index 0dcc7093e4..0000000000 --- a/Unmapped-Spigot-Server-Patches/0758-add-per-world-spawn-limits.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chase -Date: Wed, 2 Dec 2020 22:43:39 -0800 -Subject: [PATCH] add per world spawn limits - -Taken from #2982. Credit to Chasewhip8 - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5c91c007691efeea1d4383efcd1ca06990d0660c..fcacc08db8f5a58ddd06be7f9f2cb2cf6b2231c3 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -653,6 +653,19 @@ public class PaperWorldConfig { - zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); - } - -+ public int spawnLimitMonsters = -1; -+ public int spawnLimitAnimals = -1; -+ public int spawnLimitWaterAnimals = -1; -+ public int spawnLimitWaterAmbient = -1; -+ public int spawnLimitAmbient = -1; -+ private void perWorldSpawnLimits() { -+ spawnLimitMonsters = getInt("spawn-limits.monsters", spawnLimitMonsters); -+ spawnLimitAnimals = getInt("spawn-limits.animals", spawnLimitAnimals); -+ spawnLimitWaterAnimals = getInt("spawn-limits.water-animals", spawnLimitWaterAnimals); -+ spawnLimitWaterAmbient = getInt("spawn-limits.water-ambient", spawnLimitWaterAmbient); -+ spawnLimitAmbient = getInt("spawn-limits.ambient", spawnLimitAmbient); -+ } -+ - public int lightQueueSize = 20; - private void lightQueueSize() { - lightQueueSize = getInt("light-queue-size", lightQueueSize); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 02198dbe9e80c2990e8a09b2b763748dae727a03..c0b49a0eaeda06b89a4fb425eec3d5bfa9717379 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -353,6 +353,13 @@ public class CraftWorld implements World { - this.generator = gen; - - environment = env; -+ // Paper start - per world spawn limits -+ this.monsterSpawn = this.world.paperConfig.spawnLimitMonsters; -+ this.animalSpawn = this.world.paperConfig.spawnLimitAnimals; -+ this.waterAnimalSpawn = this.world.paperConfig.spawnLimitWaterAnimals; -+ this.waterAmbientSpawn = this.world.paperConfig.spawnLimitWaterAmbient; -+ this.ambientSpawn = this.world.paperConfig.spawnLimitAmbient; -+ // Paper end - } - - @Override diff --git a/Unmapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch b/Unmapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch deleted file mode 100644 index a6d7f10ad8..0000000000 --- a/Unmapped-Spigot-Server-Patches/0759-Fix-PotionSplashEvent-for-water-splash-potions.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 20 May 2021 20:40:53 -0700 -Subject: [PATCH] Fix PotionSplashEvent for water splash potions - -Fixes SPIGOT-6221: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-6221 - -diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -index 53ea8a6d90faf4f7f8fd0819be4499422bdd4cbe..e6bf78f46acc37d9515d58cec3587e236ac0733c 100644 ---- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java -+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -@@ -99,6 +99,7 @@ public class DamageSource { - return (new EntityDamageSourceIndirect("thrown", entity, entity1)).c(); - } - -+ public static DamageSource indirectMagic(Entity target, Entity cause) { return c(target, cause); } // Paper - OBFHELPER - public static DamageSource c(Entity entity, @Nullable Entity entity1) { - return (new EntityDamageSourceIndirect("indirectMagic", entity, entity1)).setIgnoreArmor().setMagic(); - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java b/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java -index dbc0afc5fb9e358a3e6d596692f57fb28303c4da..9348288fb752e758fe7aee8c2a630ea0fb7b9a8c 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java -@@ -124,6 +124,7 @@ public class EntityPotion extends EntityProjectileThrowable { - private void splash() { - AxisAlignedBB axisalignedbb = this.getBoundingBox().grow(4.0D, 2.0D, 4.0D); - List list = this.world.a(EntityLiving.class, axisalignedbb, EntityPotion.b); -+ Map affected = new HashMap<>(); // Paper - - if (!list.isEmpty()) { - Iterator iterator = list.iterator(); -@@ -133,11 +134,22 @@ public class EntityPotion extends EntityProjectileThrowable { - double d0 = this.h(entityliving); - - if (d0 < 16.0D && entityliving.dO()) { -- entityliving.damageEntity(DamageSource.c(entityliving, this.getShooter()), 1.0F); -+ // Paper start -+ double intensity = 1.0D - Math.sqrt(d0) / 4.0D; -+ affected.put(entityliving.getBukkitLivingEntity(), intensity); -+ // entityliving.damageEntity(DamageSource.c(entityliving, this.getShooter()), 1.0F); // Paper - moved down - } - } - } - -+ org.bukkit.event.entity.PotionSplashEvent event = CraftEventFactory.callPotionSplashEvent(this, affected); -+ if (!event.isCancelled()) { -+ for (LivingEntity affectedEntity : event.getAffectedEntities()) { -+ EntityLiving entityliving = ((CraftLivingEntity) affectedEntity).getHandle(); -+ entityliving.damageEntity(DamageSource.indirectMagic(entityliving, this.getShooter()), 1.0F); -+ } -+ } -+ // Paper end - } - - private void a(List list, @Nullable Entity entity) { -@@ -155,6 +167,7 @@ public class EntityPotion extends EntityProjectileThrowable { - double d0 = this.h(entityliving); - - if (d0 < 16.0D) { -+ // Paper - diff on change, used when calling the splash event for water splash potions - double d1 = 1.0D - Math.sqrt(d0) / 4.0D; - - if (entityliving == entity) { From 716a3139b72bae26049a06efd5fcb587b7baedc9 Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Sat, 12 Jun 2021 12:30:37 -0700 Subject: [PATCH 051/226] more patches (#5808) --- ...=> 0089-Player.setPlayerProfile-API.patch} | 0 .../0090-getPlayerUniqueId-API.patch} | 4 +- ...support-to-PaperServerListPingEvent.patch} | 0 ...-method-to-open-already-placed-sign.patch} | 2 +- ...3-Add-Ban-Methods-to-Player-Objects.patch} | 2 +- .../0094-EndermanEscapeEvent.patch} | 0 .../0095-Enderman.teleportRandomly.patch} | 0 ...ional-world.getNearbyEntities-API-s.patch} | 4 +- .../0097-Location.isChunkLoaded-API.patch} | 0 ...d.spawnParticle-API-and-add-Builder.patch} | 0 .../0099-EndermanAttackPlayerEvent.patch} | 0 ...ose-Plugin-Class-Loaders-on-Disable.patch} | 2 +- .../0101-WitchConsumePotionEvent.patch} | 0 .../0102-WitchThrowPotionEvent.patch} | 0 ...on.toBlockLocation-toCenterLocation.patch} | 0 .../0104-PotionEffect-clone-methods.patch} | 0 .../0105-WitchReadyPotionEvent.patch} | 0 ...106-ItemStack-getMaxItemUseDuration.patch} | 2 +- ...7-Add-EntityTeleportEndGatewayEvent.patch} | 0 ...-shield-blocking-delay-configurable.patch} | 0 ...nt-consumeArrow-and-getArrowItem-AP.patch} | 0 ...dd-getNearbyXXX-methods-to-Location.patch} | 0 .../0111-PlayerReadyArrowEvent.patch} | 0 ...12-Add-EntityKnockbackByEntityEvent.patch} | 0 .../0113-Expand-Explosions-API.patch} | 2 +- ...I-additions-for-quantity-flags-lore.patch} | 2 +- ...vingEntity-Hand-Raised-Item-Use-API.patch} | 0 .../0116-RangedEntity-API.patch} | 0 .../0117-Add-World.getEntity-UUID-API.patch} | 2 +- ...0118-InventoryCloseEvent-Reason-API.patch} | 2 +- .../0185-Fix-Dragon-Server-Crashes.patch} | 20 ++-- ...sted-Ice-from-loading-holding-chunks.patch | 32 ------- ...-allowed-colored-signs-to-be-created.patch | 31 ------ .../0215-EndermanAttackPlayerEvent.patch | 46 --------- ...0220-ItemStack-getMaxItemUseDuration.patch | 37 ------- ...ed-flag-on-cancel-of-Explosion-Event.patch | 28 ------ .../0227-Improve-EntityShootBowEvent.patch | 44 --------- ...ivingEntity-Hand-Raised-Item-Use-API.patch | 68 ------------- ...rovide-E-TE-Chunk-count-stat-methods.patch | 17 +--- .../0185-getPlayerUniqueId-API.patch} | 2 +- ...ake-player-data-saving-configurable.patch} | 0 ...e-legacy-ping-handler-more-reliable.patch} | 29 ++---- ...erverListPingEvent-for-legacy-pings.patch} | 8 +- ...9-Flag-to-disable-the-channel-limit.patch} | 12 +-- ...-method-to-open-already-placed-sign.patch} | 18 +--- ...rable-sprint-interruption-on-attack.patch} | 8 +- ...-allowed-colored-signs-to-be-created.patch | 22 +++++ .../0193-EndermanEscapeEvent.patch} | 36 +++---- .../0194-Enderman.teleportRandomly.patch} | 15 +-- ...195-Block-Enderpearl-Travel-Exploit.patch} | 16 ++-- ...d.spawnParticle-API-and-add-Builder.patch} | 21 ++-- ...sted-Ice-from-loading-holding-chunks.patch | 33 +++++++ .../0198-EndermanAttackPlayerEvent.patch | 30 ++++++ .../0199-WitchConsumePotionEvent.patch} | 4 +- .../0200-WitchThrowPotionEvent.patch} | 8 +- ...tem-entities-with-World.spawnEntity.patch} | 8 +- .../0202-WitchReadyPotionEvent.patch} | 2 +- ...0203-ItemStack-getMaxItemUseDuration.patch | 25 +++++ ...ement-EntityTeleportEndGatewayEvent.patch} | 12 +-- ...ed-flag-on-cancel-of-Explosion-Event.patch | 19 ++++ .../0206-Fix-CraftEntity-hashCode.patch} | 4 +- ...e-Alternative-LootPool-Luck-Formula.patch} | 47 +++------ ...ls-when-failing-to-save-player-data.patch} | 6 +- ...-shield-blocking-delay-configurable.patch} | 21 ++-- .../0210-Improve-EntityShootBowEvent.patch | 96 +++++++++++++++++++ .../0211-PlayerReadyArrowEvent.patch} | 6 +- ...lement-EntityKnockbackByEntityEvent.patch} | 65 +++++++------ .../0213-Expand-Explosions-API.patch} | 7 +- ...ivingEntity-Hand-Raised-Item-Use-API.patch | 42 ++++++++ .../0215-RangedEntity-API.patch} | 27 ++---- ...o-disable-ender-dragon-legacy-check.patch} | 26 ++--- ...-Implement-World.getEntity-UUID-API.patch} | 4 +- ...0218-InventoryCloseEvent-Reason-API.patch} | 94 +++++++++--------- 73 files changed, 515 insertions(+), 605 deletions(-) rename patches/api/{0088-Player.setPlayerProfile-API.patch => 0089-Player.setPlayerProfile-API.patch} (100%) rename patches/{api-unmapped/0089-getPlayerUniqueId-API.patch => api/0090-getPlayerUniqueId-API.patch} (91%) rename patches/{api-unmapped/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch => api/0091-Add-legacy-ping-support-to-PaperServerListPingEvent.patch} (100%) rename patches/{api-unmapped/0091-Add-method-to-open-already-placed-sign.patch => api/0092-Add-method-to-open-already-placed-sign.patch} (90%) rename patches/{api-unmapped/0092-Add-Ban-Methods-to-Player-Objects.patch => api/0093-Add-Ban-Methods-to-Player-Objects.patch} (98%) rename patches/{api-unmapped/0093-EndermanEscapeEvent.patch => api/0094-EndermanEscapeEvent.patch} (100%) rename patches/{api-unmapped/0094-Enderman.teleportRandomly.patch => api/0095-Enderman.teleportRandomly.patch} (100%) rename patches/{api-unmapped/0095-Additional-world.getNearbyEntities-API-s.patch => api/0096-Additional-world.getNearbyEntities-API-s.patch} (98%) rename patches/{api-unmapped/0096-Location.isChunkLoaded-API.patch => api/0097-Location.isChunkLoaded-API.patch} (100%) rename patches/{api-unmapped/0097-Expand-World.spawnParticle-API-and-add-Builder.patch => api/0098-Expand-World.spawnParticle-API-and-add-Builder.patch} (100%) rename patches/{api-unmapped/0098-EndermanAttackPlayerEvent.patch => api/0099-EndermanAttackPlayerEvent.patch} (100%) rename patches/{api-unmapped/0099-Close-Plugin-Class-Loaders-on-Disable.patch => api/0100-Close-Plugin-Class-Loaders-on-Disable.patch} (98%) rename patches/{api-unmapped/0100-WitchConsumePotionEvent.patch => api/0101-WitchConsumePotionEvent.patch} (100%) rename patches/{api-unmapped/0101-WitchThrowPotionEvent.patch => api/0102-WitchThrowPotionEvent.patch} (100%) rename patches/{api-unmapped/0102-Location.toBlockLocation-toCenterLocation.patch => api/0103-Location.toBlockLocation-toCenterLocation.patch} (100%) rename patches/{api-unmapped/0103-PotionEffect-clone-methods.patch => api/0104-PotionEffect-clone-methods.patch} (100%) rename patches/{api-unmapped/0104-WitchReadyPotionEvent.patch => api/0105-WitchReadyPotionEvent.patch} (100%) rename patches/{api-unmapped/0105-ItemStack-getMaxItemUseDuration.patch => api/0106-ItemStack-getMaxItemUseDuration.patch} (91%) rename patches/{api-unmapped/0106-Add-EntityTeleportEndGatewayEvent.patch => api/0107-Add-EntityTeleportEndGatewayEvent.patch} (100%) rename patches/{api-unmapped/0107-Make-shield-blocking-delay-configurable.patch => api/0108-Make-shield-blocking-delay-configurable.patch} (100%) rename patches/{api-unmapped/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch => api/0109-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch} (100%) rename patches/{api-unmapped/0109-Add-getNearbyXXX-methods-to-Location.patch => api/0110-Add-getNearbyXXX-methods-to-Location.patch} (100%) rename patches/{api-unmapped/0110-PlayerReadyArrowEvent.patch => api/0111-PlayerReadyArrowEvent.patch} (100%) rename patches/{api-unmapped/0111-Add-EntityKnockbackByEntityEvent.patch => api/0112-Add-EntityKnockbackByEntityEvent.patch} (100%) rename patches/{api-unmapped/0112-Expand-Explosions-API.patch => api/0113-Expand-Explosions-API.patch} (98%) rename patches/{api-unmapped/0113-ItemStack-API-additions-for-quantity-flags-lore.patch => api/0114-ItemStack-API-additions-for-quantity-flags-lore.patch} (98%) rename patches/{api-unmapped/0114-LivingEntity-Hand-Raised-Item-Use-API.patch => api/0115-LivingEntity-Hand-Raised-Item-Use-API.patch} (100%) rename patches/{api-unmapped/0115-RangedEntity-API.patch => api/0116-RangedEntity-API.patch} (100%) rename patches/{api-unmapped/0116-Add-World.getEntity-UUID-API.patch => api/0117-Add-World.getEntity-UUID-API.patch} (91%) rename patches/{api-unmapped/0117-InventoryCloseEvent-Reason-API.patch => api/0118-InventoryCloseEvent-Reason-API.patch} (96%) rename patches/{server-remapped/0202-Fix-Dragon-Server-Crashes.patch => removed/1.17/0185-Fix-Dragon-Server-Crashes.patch} (56%) delete mode 100644 patches/removed/1.17/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch delete mode 100644 patches/server-remapped/0210-Fix-exploit-that-allowed-colored-signs-to-be-created.patch delete mode 100644 patches/server-remapped/0215-EndermanAttackPlayerEvent.patch delete mode 100644 patches/server-remapped/0220-ItemStack-getMaxItemUseDuration.patch delete mode 100644 patches/server-remapped/0222-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch delete mode 100644 patches/server-remapped/0227-Improve-EntityShootBowEvent.patch delete mode 100644 patches/server-remapped/0231-LivingEntity-Hand-Raised-Item-Use-API.patch rename patches/{server-remapped/0203-getPlayerUniqueId-API.patch => server/0185-getPlayerUniqueId-API.patch} (94%) rename patches/{server-remapped/0204-Make-player-data-saving-configurable.patch => server/0186-Make-player-data-saving-configurable.patch} (100%) rename patches/{server-remapped/0205-Make-legacy-ping-handler-more-reliable.patch => server/0187-Make-legacy-ping-handler-more-reliable.patch} (79%) rename patches/{server-remapped/0206-Call-PaperServerListPingEvent-for-legacy-pings.patch => server/0188-Call-PaperServerListPingEvent-for-legacy-pings.patch} (96%) rename patches/{server-remapped/0207-Flag-to-disable-the-channel-limit.patch => server/0189-Flag-to-disable-the-channel-limit.patch} (69%) rename patches/{server-remapped/0208-Add-method-to-open-already-placed-sign.patch => server/0190-Add-method-to-open-already-placed-sign.patch} (61%) rename patches/{server-remapped/0209-Configurable-sprint-interruption-on-attack.patch => server/0191-Configurable-sprint-interruption-on-attack.patch} (85%) create mode 100644 patches/server/0192-Fix-exploit-that-allowed-colored-signs-to-be-created.patch rename patches/{server-remapped/0211-EndermanEscapeEvent.patch => server/0193-EndermanEscapeEvent.patch} (65%) rename patches/{server-remapped/0212-Enderman.teleportRandomly.patch => server/0194-Enderman.teleportRandomly.patch} (70%) rename patches/{server-remapped/0213-Block-Enderpearl-Travel-Exploit.patch => server/0195-Block-Enderpearl-Travel-Exploit.patch} (78%) rename patches/{server-remapped/0214-Expand-World.spawnParticle-API-and-add-Builder.patch => server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch} (74%) create mode 100644 patches/server/0197-Prevent-Frosted-Ice-from-loading-holding-chunks.patch create mode 100644 patches/server/0198-EndermanAttackPlayerEvent.patch rename patches/{server-remapped/0216-WitchConsumePotionEvent.patch => server/0199-WitchConsumePotionEvent.patch} (89%) rename patches/{server-remapped/0217-WitchThrowPotionEvent.patch => server/0200-WitchThrowPotionEvent.patch} (83%) rename patches/{server-remapped/0218-Allow-spawning-Item-entities-with-World.spawnEntity.patch => server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch} (79%) rename patches/{server-remapped/0219-WitchReadyPotionEvent.patch => server/0202-WitchReadyPotionEvent.patch} (93%) create mode 100644 patches/server/0203-ItemStack-getMaxItemUseDuration.patch rename patches/{server-remapped/0221-Implement-EntityTeleportEndGatewayEvent.patch => server/0204-Implement-EntityTeleportEndGatewayEvent.patch} (71%) create mode 100644 patches/server/0205-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch rename patches/{server-remapped/0223-Fix-CraftEntity-hashCode.patch => server/0206-Fix-CraftEntity-hashCode.patch} (91%) rename patches/{server-remapped/0224-Configurable-Alternative-LootPool-Luck-Formula.patch => server/0207-Configurable-Alternative-LootPool-Luck-Formula.patch} (68%) rename patches/{server-remapped/0225-Print-Error-details-when-failing-to-save-player-data.patch => server/0208-Print-Error-details-when-failing-to-save-player-data.patch} (72%) rename patches/{server-remapped/0226-Make-shield-blocking-delay-configurable.patch => server/0209-Make-shield-blocking-delay-configurable.patch} (78%) create mode 100644 patches/server/0210-Improve-EntityShootBowEvent.patch rename patches/{server-remapped/0228-PlayerReadyArrowEvent.patch => server/0211-PlayerReadyArrowEvent.patch} (88%) rename patches/{server-remapped/0229-Implement-EntityKnockbackByEntityEvent.patch => server/0212-Implement-EntityKnockbackByEntityEvent.patch} (53%) rename patches/{server-remapped/0230-Expand-Explosions-API.patch => server/0213-Expand-Explosions-API.patch} (74%) create mode 100644 patches/server/0214-LivingEntity-Hand-Raised-Item-Use-API.patch rename patches/{server-remapped/0232-RangedEntity-API.patch => server/0215-RangedEntity-API.patch} (89%) rename patches/{server-remapped/0233-Add-config-to-disable-ender-dragon-legacy-check.patch => server/0216-Add-config-to-disable-ender-dragon-legacy-check.patch} (59%) rename patches/{server-remapped/0234-Implement-World.getEntity-UUID-API.patch => server/0217-Implement-World.getEntity-UUID-API.patch} (84%) rename patches/{server-remapped/0235-InventoryCloseEvent-Reason-API.patch => server/0218-InventoryCloseEvent-Reason-API.patch} (71%) diff --git a/patches/api/0088-Player.setPlayerProfile-API.patch b/patches/api/0089-Player.setPlayerProfile-API.patch similarity index 100% rename from patches/api/0088-Player.setPlayerProfile-API.patch rename to patches/api/0089-Player.setPlayerProfile-API.patch diff --git a/patches/api-unmapped/0089-getPlayerUniqueId-API.patch b/patches/api/0090-getPlayerUniqueId-API.patch similarity index 91% rename from patches/api-unmapped/0089-getPlayerUniqueId-API.patch rename to patches/api/0090-getPlayerUniqueId-API.patch index 6586351ea9..696884eae1 100644 --- a/patches/api-unmapped/0089-getPlayerUniqueId-API.patch +++ b/patches/api/0090-getPlayerUniqueId-API.patch @@ -9,7 +9,7 @@ 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 f5d3a7370390871d1b6075f32846d1a942b05b7f..2d7f8e128e23934a8fe26baf19198b7ffc8447bb 100644 +index c9f00ffe05c8624619b23ad22cf61233cede440e..1f4532e60abe62b88472a9bb0ef8d1af1f921220 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -504,6 +504,20 @@ public final class Bukkit { @@ -34,7 +34,7 @@ index f5d3a7370390871d1b6075f32846d1a942b05b7f..2d7f8e128e23934a8fe26baf19198b7f * 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 38d138b217734e598581ed14065ff2015135ee9a..01657abaff86cf7bb3ffb857024c5032781b8660 100644 +index f2448c6dc8ef64393127a13c33eb14b0d5cd92c0..ca4e2d3b27f629e0d5e672fc915a5d03f0c0581d 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -429,6 +429,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api-unmapped/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch b/patches/api/0091-Add-legacy-ping-support-to-PaperServerListPingEvent.patch similarity index 100% rename from patches/api-unmapped/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch rename to patches/api/0091-Add-legacy-ping-support-to-PaperServerListPingEvent.patch diff --git a/patches/api-unmapped/0091-Add-method-to-open-already-placed-sign.patch b/patches/api/0092-Add-method-to-open-already-placed-sign.patch similarity index 90% rename from patches/api-unmapped/0091-Add-method-to-open-already-placed-sign.patch rename to patches/api/0092-Add-method-to-open-already-placed-sign.patch index c75d281c23..c2a5530280 100644 --- a/patches/api-unmapped/0091-Add-method-to-open-already-placed-sign.patch +++ b/patches/api/0092-Add-method-to-open-already-placed-sign.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add method to open already placed sign diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index d212d5123b6294f7873d72f125505a006c290b05..7430bc85301d0fcb34c6035fbe08ae245c76e043 100644 +index 8ba6a59066234b834aedb0fb414ee7391aa2ac18..2e86d4c9ee85cf0f9096472b8c3d131522181215 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java @@ -461,6 +461,14 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder diff --git a/patches/api-unmapped/0092-Add-Ban-Methods-to-Player-Objects.patch b/patches/api/0093-Add-Ban-Methods-to-Player-Objects.patch similarity index 98% rename from patches/api-unmapped/0092-Add-Ban-Methods-to-Player-Objects.patch rename to patches/api/0093-Add-Ban-Methods-to-Player-Objects.patch index 540eeb4d36..772bc38bed 100644 --- a/patches/api-unmapped/0092-Add-Ban-Methods-to-Player-Objects.patch +++ b/patches/api/0093-Add-Ban-Methods-to-Player-Objects.patch @@ -74,7 +74,7 @@ index 58313929f81509030216a0e5e3869da63e11108e..6cf05fed701c67a2c797a4e0839c7958 /** * Checks if this player is whitelisted or not diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 6769330f336afcd5f26c0f7286defa00bead543c..88fd4cdeaad4d27f414c6b268022cdedf73492e7 100644 +index 3ae4d670059f80bd057870a37f4025261e397dfa..257bf4a75393d1e25839bcae0ca5551ee832c627 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -5,6 +5,10 @@ import java.util.UUID; diff --git a/patches/api-unmapped/0093-EndermanEscapeEvent.patch b/patches/api/0094-EndermanEscapeEvent.patch similarity index 100% rename from patches/api-unmapped/0093-EndermanEscapeEvent.patch rename to patches/api/0094-EndermanEscapeEvent.patch diff --git a/patches/api-unmapped/0094-Enderman.teleportRandomly.patch b/patches/api/0095-Enderman.teleportRandomly.patch similarity index 100% rename from patches/api-unmapped/0094-Enderman.teleportRandomly.patch rename to patches/api/0095-Enderman.teleportRandomly.patch diff --git a/patches/api-unmapped/0095-Additional-world.getNearbyEntities-API-s.patch b/patches/api/0096-Additional-world.getNearbyEntities-API-s.patch similarity index 98% rename from patches/api-unmapped/0095-Additional-world.getNearbyEntities-API-s.patch rename to patches/api/0096-Additional-world.getNearbyEntities-API-s.patch index cde5bb2148..489e0a5c4c 100644 --- a/patches/api-unmapped/0095-Additional-world.getNearbyEntities-API-s.patch +++ b/patches/api/0096-Additional-world.getNearbyEntities-API-s.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Additional world.getNearbyEntities API's Provides more methods to get nearby entities, and filter by types and predicates diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 0f86a9c67797fd662cbbfdb808789bcab95caba4..cae848ce698337d0b254bd48938abfc1e68ad561 100644 +index 8804be419520859355b69660e6f3166d1aa8b1ea..6cc9c7fc913f229c4869a976e73253acb74fcda3 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -1,6 +1,9 @@ @@ -277,7 +277,7 @@ index 0f86a9c67797fd662cbbfdb808789bcab95caba4..cae848ce698337d0b254bd48938abfc1 * Get a list of all players in this World * diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -index a40b57edb1aeff71fc0b9767d410950da5c06283..184d9462ebbc500d8b81aaf14fe138d247bf2470 100644 +index d512c23ad0275061593d99f005c72292dbb07e81..c9af02b0f62b3d18da1e91d1ea02ce0864fc60b9 100644 --- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java @@ -42,8 +42,7 @@ public class AsyncPlayerPreLoginEvent extends Event { diff --git a/patches/api-unmapped/0096-Location.isChunkLoaded-API.patch b/patches/api/0097-Location.isChunkLoaded-API.patch similarity index 100% rename from patches/api-unmapped/0096-Location.isChunkLoaded-API.patch rename to patches/api/0097-Location.isChunkLoaded-API.patch diff --git a/patches/api-unmapped/0097-Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/api/0098-Expand-World.spawnParticle-API-and-add-Builder.patch similarity index 100% rename from patches/api-unmapped/0097-Expand-World.spawnParticle-API-and-add-Builder.patch rename to patches/api/0098-Expand-World.spawnParticle-API-and-add-Builder.patch diff --git a/patches/api-unmapped/0098-EndermanAttackPlayerEvent.patch b/patches/api/0099-EndermanAttackPlayerEvent.patch similarity index 100% rename from patches/api-unmapped/0098-EndermanAttackPlayerEvent.patch rename to patches/api/0099-EndermanAttackPlayerEvent.patch diff --git a/patches/api-unmapped/0099-Close-Plugin-Class-Loaders-on-Disable.patch b/patches/api/0100-Close-Plugin-Class-Loaders-on-Disable.patch similarity index 98% rename from patches/api-unmapped/0099-Close-Plugin-Class-Loaders-on-Disable.patch rename to patches/api/0100-Close-Plugin-Class-Loaders-on-Disable.patch index 6580fe3c76..e6b629f072 100644 --- a/patches/api-unmapped/0099-Close-Plugin-Class-Loaders-on-Disable.patch +++ b/patches/api/0100-Close-Plugin-Class-Loaders-on-Disable.patch @@ -53,7 +53,7 @@ index 41e26451fe12d8e6e0ef73c85731b24b4e3f200c..86cc5025ad98f7a752c51713b7cd6a39 * Gets a {@link Permission} from its fully qualified name * diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 8b33d914d29897c0276f9e2e7ce83bd2c316d5e2..a7393d2830b95d7167121b02066a3f357cee6085 100644 +index 2d27dfb859c312d46a14d0356c7c3f227e965a67..892ec4b43cc97a235df0819d30391a8a3770cbcb 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -492,17 +492,28 @@ public final class SimplePluginManager implements PluginManager { diff --git a/patches/api-unmapped/0100-WitchConsumePotionEvent.patch b/patches/api/0101-WitchConsumePotionEvent.patch similarity index 100% rename from patches/api-unmapped/0100-WitchConsumePotionEvent.patch rename to patches/api/0101-WitchConsumePotionEvent.patch diff --git a/patches/api-unmapped/0101-WitchThrowPotionEvent.patch b/patches/api/0102-WitchThrowPotionEvent.patch similarity index 100% rename from patches/api-unmapped/0101-WitchThrowPotionEvent.patch rename to patches/api/0102-WitchThrowPotionEvent.patch diff --git a/patches/api-unmapped/0102-Location.toBlockLocation-toCenterLocation.patch b/patches/api/0103-Location.toBlockLocation-toCenterLocation.patch similarity index 100% rename from patches/api-unmapped/0102-Location.toBlockLocation-toCenterLocation.patch rename to patches/api/0103-Location.toBlockLocation-toCenterLocation.patch diff --git a/patches/api-unmapped/0103-PotionEffect-clone-methods.patch b/patches/api/0104-PotionEffect-clone-methods.patch similarity index 100% rename from patches/api-unmapped/0103-PotionEffect-clone-methods.patch rename to patches/api/0104-PotionEffect-clone-methods.patch diff --git a/patches/api-unmapped/0104-WitchReadyPotionEvent.patch b/patches/api/0105-WitchReadyPotionEvent.patch similarity index 100% rename from patches/api-unmapped/0104-WitchReadyPotionEvent.patch rename to patches/api/0105-WitchReadyPotionEvent.patch diff --git a/patches/api-unmapped/0105-ItemStack-getMaxItemUseDuration.patch b/patches/api/0106-ItemStack-getMaxItemUseDuration.patch similarity index 91% rename from patches/api-unmapped/0105-ItemStack-getMaxItemUseDuration.patch rename to patches/api/0106-ItemStack-getMaxItemUseDuration.patch index b00193d717..5a5b635adb 100644 --- a/patches/api-unmapped/0105-ItemStack-getMaxItemUseDuration.patch +++ b/patches/api/0106-ItemStack-getMaxItemUseDuration.patch @@ -6,7 +6,7 @@ Subject: [PATCH] ItemStack#getMaxItemUseDuration Allows you to determine how long it takes to use a usable/consumable item diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 82bd3e6701dbd7df9f0f8c3801c5ae1baba4eec5..f41701e6374ca23eca4bdb092e385053a12eb718 100644 +index e8783b0116f4efd5447a5f6f260506000983ffd2..9fee2f157ac5149cd65136bf8468deaca410fbf4 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -636,5 +636,13 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor diff --git a/patches/api-unmapped/0106-Add-EntityTeleportEndGatewayEvent.patch b/patches/api/0107-Add-EntityTeleportEndGatewayEvent.patch similarity index 100% rename from patches/api-unmapped/0106-Add-EntityTeleportEndGatewayEvent.patch rename to patches/api/0107-Add-EntityTeleportEndGatewayEvent.patch diff --git a/patches/api-unmapped/0107-Make-shield-blocking-delay-configurable.patch b/patches/api/0108-Make-shield-blocking-delay-configurable.patch similarity index 100% rename from patches/api-unmapped/0107-Make-shield-blocking-delay-configurable.patch rename to patches/api/0108-Make-shield-blocking-delay-configurable.patch diff --git a/patches/api-unmapped/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch b/patches/api/0109-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch similarity index 100% rename from patches/api-unmapped/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch rename to patches/api/0109-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch diff --git a/patches/api-unmapped/0109-Add-getNearbyXXX-methods-to-Location.patch b/patches/api/0110-Add-getNearbyXXX-methods-to-Location.patch similarity index 100% rename from patches/api-unmapped/0109-Add-getNearbyXXX-methods-to-Location.patch rename to patches/api/0110-Add-getNearbyXXX-methods-to-Location.patch diff --git a/patches/api-unmapped/0110-PlayerReadyArrowEvent.patch b/patches/api/0111-PlayerReadyArrowEvent.patch similarity index 100% rename from patches/api-unmapped/0110-PlayerReadyArrowEvent.patch rename to patches/api/0111-PlayerReadyArrowEvent.patch diff --git a/patches/api-unmapped/0111-Add-EntityKnockbackByEntityEvent.patch b/patches/api/0112-Add-EntityKnockbackByEntityEvent.patch similarity index 100% rename from patches/api-unmapped/0111-Add-EntityKnockbackByEntityEvent.patch rename to patches/api/0112-Add-EntityKnockbackByEntityEvent.patch diff --git a/patches/api-unmapped/0112-Expand-Explosions-API.patch b/patches/api/0113-Expand-Explosions-API.patch similarity index 98% rename from patches/api-unmapped/0112-Expand-Explosions-API.patch rename to patches/api/0113-Expand-Explosions-API.patch index 389fec9570..b26bf20578 100644 --- a/patches/api-unmapped/0112-Expand-Explosions-API.patch +++ b/patches/api/0113-Expand-Explosions-API.patch @@ -106,7 +106,7 @@ index 4cf22afc3c1f1cc19b6e5350043431215908a612..af2ee43f2c5133668c18710f526a107d * Returns a list of entities within a bounding box centered around a Location. * diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 05643d0f2bf2cb2dedb0a2ad693b2121565d3f1f..c7cdbc36f96a8ee9eaac2a2145afbfc76bc38cc9 100644 +index ca2b1cbff153c53ec9182e44a1979350bacd695b..53407b999258967a116241ab7d791ac52a344b80 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -1442,6 +1442,88 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad diff --git a/patches/api-unmapped/0113-ItemStack-API-additions-for-quantity-flags-lore.patch b/patches/api/0114-ItemStack-API-additions-for-quantity-flags-lore.patch similarity index 98% rename from patches/api-unmapped/0113-ItemStack-API-additions-for-quantity-flags-lore.patch rename to patches/api/0114-ItemStack-API-additions-for-quantity-flags-lore.patch index d5b56b9832..285bb74979 100644 --- a/patches/api-unmapped/0113-ItemStack-API-additions-for-quantity-flags-lore.patch +++ b/patches/api/0114-ItemStack-API-additions-for-quantity-flags-lore.patch @@ -5,7 +5,7 @@ Subject: [PATCH] ItemStack API additions for quantity/flags/lore diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index f41701e6374ca23eca4bdb092e385053a12eb718..07fd8a495828ff79239359c736c425c4902543a4 100644 +index 9fee2f157ac5149cd65136bf8468deaca410fbf4..686e2a0b9fe061816b41435ef2337870dbdca8e5 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -2,7 +2,9 @@ package org.bukkit.inventory; diff --git a/patches/api-unmapped/0114-LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/api/0115-LivingEntity-Hand-Raised-Item-Use-API.patch similarity index 100% rename from patches/api-unmapped/0114-LivingEntity-Hand-Raised-Item-Use-API.patch rename to patches/api/0115-LivingEntity-Hand-Raised-Item-Use-API.patch diff --git a/patches/api-unmapped/0115-RangedEntity-API.patch b/patches/api/0116-RangedEntity-API.patch similarity index 100% rename from patches/api-unmapped/0115-RangedEntity-API.patch rename to patches/api/0116-RangedEntity-API.patch diff --git a/patches/api-unmapped/0116-Add-World.getEntity-UUID-API.patch b/patches/api/0117-Add-World.getEntity-UUID-API.patch similarity index 91% rename from patches/api-unmapped/0116-Add-World.getEntity-UUID-API.patch rename to patches/api/0117-Add-World.getEntity-UUID-API.patch index bb7e7eafdf..339775b32f 100644 --- a/patches/api-unmapped/0116-Add-World.getEntity-UUID-API.patch +++ b/patches/api/0117-Add-World.getEntity-UUID-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add World.getEntity(UUID) API diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index c7cdbc36f96a8ee9eaac2a2145afbfc76bc38cc9..edf136ef50c9cdd8ccea2e35508e4464c3de99bd 100644 +index 53407b999258967a116241ab7d791ac52a344b80..a7bd869fb5b8e35274eee0d8dae9dd6fe3c1c540 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -946,6 +946,17 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad diff --git a/patches/api-unmapped/0117-InventoryCloseEvent-Reason-API.patch b/patches/api/0118-InventoryCloseEvent-Reason-API.patch similarity index 96% rename from patches/api-unmapped/0117-InventoryCloseEvent-Reason-API.patch rename to patches/api/0118-InventoryCloseEvent-Reason-API.patch index c03581bf2f..cbacde69b0 100644 --- a/patches/api-unmapped/0117-InventoryCloseEvent-Reason-API.patch +++ b/patches/api/0118-InventoryCloseEvent-Reason-API.patch @@ -7,7 +7,7 @@ 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 7430bc85301d0fcb34c6035fbe08ae245c76e043..3418133d07250a7fd50caad8d97924b86fb30bad 100644 +index 2e86d4c9ee85cf0f9096472b8c3d131522181215..3cf96a3656d3366952f15744c9970e752e97be9a 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java @@ -153,6 +153,15 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder diff --git a/patches/server-remapped/0202-Fix-Dragon-Server-Crashes.patch b/patches/removed/1.17/0185-Fix-Dragon-Server-Crashes.patch similarity index 56% rename from patches/server-remapped/0202-Fix-Dragon-Server-Crashes.patch rename to patches/removed/1.17/0185-Fix-Dragon-Server-Crashes.patch index 334aa02f71..270cd5951a 100644 --- a/patches/server-remapped/0202-Fix-Dragon-Server-Crashes.patch +++ b/patches/removed/1.17/0185-Fix-Dragon-Server-Crashes.patch @@ -6,16 +6,18 @@ Subject: [PATCH] Fix Dragon Server Crashes If the dragon tries to find "ground" and hits a hole, or off edge, it will infinitely keep looking for non air and eventually crash. +Fixed in 1.15 + diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java -index 5e701b02e464889fe433b08018d13e63b24506eb..0c2a5f5c4d7d7516793eba20205b5703fe1450d5 100644 +index df44bfce8cc492cd901dfa86331b9be7f1e13837..9eca797b4db96c5f2bb93d260f8e84077d92854a 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java -@@ -63,7 +63,7 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { - double d3 = d2; - BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(d0, d2, d1); +@@ -64,7 +64,7 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { + double h = g; + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(d, g, e); -- while (this.dragon.level.isEmptyBlock(blockposition_mutableblockposition)) { -+ while (this.dragon.level.isEmptyBlock(blockposition_mutableblockposition ) && d2 > 0) { // Paper - --d3; - if (d3 < 0.0D) { - d3 = d2; +- while(this.dragon.level.isEmptyBlock(mutableBlockPos)) { ++ while(this.dragon.level.isEmptyBlock(mutableBlockPos) && g > 0) { // Paper + --h; + if (h < 0.0D) { + h = g; diff --git a/patches/removed/1.17/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/patches/removed/1.17/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch deleted file mode 100644 index b7ea1f0c46..0000000000 --- a/patches/removed/1.17/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 10 Mar 2018 16:33:15 -0500 -Subject: [PATCH] Prevent Frosted Ice from loading/holding chunks - -1.17: Shouldn't be needed as blocks no longer tick without at least 1 radius chunk loaded. - -diff --git a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java -index ae2f5acd008d5d7163b56cb4a2d29354299959ca..99843f1ca4737d40ae0626fce931c97bbf5ab81d 100644 ---- a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java -@@ -40,7 +40,8 @@ public class FrostedIceBlock extends IceBlock { - Direction enumdirection = aenumdirection[j]; - - blockposition_mutableblockposition.setWithOffset((Vec3i) pos, enumdirection); -- BlockState iblockdata1 = world.getBlockState(blockposition_mutableblockposition); -+ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper -+ if (iblockdata1 == null) { continue; } // Paper - - if (iblockdata1.is((Block) this) && !this.slightlyMelt(iblockdata1, (Level) world, blockposition_mutableblockposition)) { - world.getBlockTicks().scheduleTick(blockposition_mutableblockposition, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay -@@ -83,7 +84,9 @@ public class FrostedIceBlock extends IceBlock { - Direction enumdirection = aenumdirection[l]; - - blockposition_mutableblockposition.setWithOffset((Vec3i) pos, enumdirection); -- if (world.getBlockState(blockposition_mutableblockposition).is((Block) this)) { -+ // Paper start -+ BlockState type = world.getTypeIfLoaded(blockposition_mutableblockposition); -+ if (type != null && type.is((Block) this)) { // Paper end - ++j; - if (j >= maxNeighbors) { - return false; diff --git a/patches/server-remapped/0210-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/patches/server-remapped/0210-Fix-exploit-that-allowed-colored-signs-to-be-created.patch deleted file mode 100644 index 68cdac63bd..0000000000 --- a/patches/server-remapped/0210-Fix-exploit-that-allowed-colored-signs-to-be-created.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: 0x22 <0x22@futureclient.net> -Date: Thu, 26 Apr 2018 04:41:11 -0400 -Subject: [PATCH] Fix exploit that allowed colored signs to be created - - -diff --git a/src/main/java/net/minecraft/SharedConstants.java b/src/main/java/net/minecraft/SharedConstants.java -index a70c3d25930e7414fc9e897de8d2e0c12f11c0e4..04b8783417bbcd826d6d1c302551fbad9c48bd01 100644 ---- a/src/main/java/net/minecraft/SharedConstants.java -+++ b/src/main/java/net/minecraft/SharedConstants.java -@@ -20,6 +20,7 @@ public class SharedConstants { - return chr != 167 && chr >= ' ' && chr != 127; - } - -+ public static String filterAllowedChatCharacters(String input) { return filterText(input); } // Paper - OBFHELPER - public static String filterText(String s) { - StringBuilder stringbuilder = new StringBuilder(); - char[] achar = s.toCharArray(); -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 8d0c44b6c2c99d5161c5d4b79209b79ff6db75e4..fb36aa08cd2fbe3f7262dccb8cf0f7cae55aea9c 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2786,7 +2786,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines.add(net.kyori.adventure.text.Component.text(list.get(i))); -+ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. - } - SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.craftServer.getPluginManager().callEvent(event); diff --git a/patches/server-remapped/0215-EndermanAttackPlayerEvent.patch b/patches/server-remapped/0215-EndermanAttackPlayerEvent.patch deleted file mode 100644 index 3341055b48..0000000000 --- a/patches/server-remapped/0215-EndermanAttackPlayerEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 May 2018 20:18:54 -0400 -Subject: [PATCH] EndermanAttackPlayerEvent - -Allow control over whether or not an enderman aggros a player. - -This allows you to override/extend the pumpkin/stare logic. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -index 1981c08af85b16d45531ffae4fe790bb31edec04..d190b58bea310f4006ea3deaf0d42c502d441284 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -@@ -221,20 +221,28 @@ public class EnderMan extends Monster implements NeutralMob { - this.readPersistentAngerSaveData((ServerLevel) this.level, tag); - } - -+ // Paper start - OBFHELPER - ok not really, but verify this on updates - private boolean isLookingAtMe(Player player) { -- ItemStack itemstack = (ItemStack) player.inventory.armor.get(3); -+ boolean shouldAttack = g_real(player); -+ com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) player.getBukkitEntity()); -+ event.setCancelled(!shouldAttack); -+ return event.callEvent(); -+ } -+ private boolean g_real(Player entityhuman) { -+ // Paper end -+ ItemStack itemstack = (ItemStack) entityhuman.inventory.armor.get(3); - - if (itemstack.getItem() == Blocks.CARVED_PUMPKIN.asItem()) { - return false; - } else { -- Vec3 vec3d = player.getViewVector(1.0F).normalize(); -- Vec3 vec3d1 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ()); -+ Vec3 vec3d = entityhuman.getViewVector(1.0F).normalize(); -+ Vec3 vec3d1 = new Vec3(this.getX() - entityhuman.getX(), this.getEyeY() - entityhuman.getEyeY(), this.getZ() - entityhuman.getZ()); - double d0 = vec3d1.length(); - - vec3d1 = vec3d1.normalize(); - double d1 = vec3d.dot(vec3d1); - -- return d1 > 1.0D - 0.025D / d0 ? player.canSee(this) : false; -+ return d1 > 1.0D - 0.025D / d0 ? entityhuman.canSee(this) : false; - } - } - diff --git a/patches/server-remapped/0220-ItemStack-getMaxItemUseDuration.patch b/patches/server-remapped/0220-ItemStack-getMaxItemUseDuration.patch deleted file mode 100644 index 2b415bf929..0000000000 --- a/patches/server-remapped/0220-ItemStack-getMaxItemUseDuration.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 23:00:29 -0400 -Subject: [PATCH] ItemStack#getMaxItemUseDuration - -Allows you to determine how long it takes to use a usable/consumable item - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index a0815c0d7f68f345dc48c73b8253de637c7a3e0f..34187197efd5ceff0503682dc6ce313220ca916f 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -604,6 +604,7 @@ public final class ItemStack { - this.getItem().onCraftedBy(this, world, player); - } - -+ public int getItemUseMaxDuration() { return getUseDuration(); } // Paper - OBFHELPER - public int getUseDuration() { - return this.getItem().getUseDuration(this); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 5f0ccdeb8565505278caa591f7390047eab49cf4..44caf00330e4f4f74745973dbe709980f0b61269 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -173,6 +173,13 @@ public final class CraftItemStack extends ItemStack { - return (handle == null) ? Material.AIR.getMaxStackSize() : handle.getItem().getMaxStackSize(); - } - -+ // Paper start -+ @Override -+ public int getMaxItemUseDuration() { -+ return handle == null ? 0 : handle.getItemUseMaxDuration(); -+ } -+ // Paper end -+ - @Override - public void addUnsafeEnchantment(Enchantment ench, int level) { - Validate.notNull(ench, "Cannot add null enchantment"); diff --git a/patches/server-remapped/0222-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/patches/server-remapped/0222-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch deleted file mode 100644 index 1bda08648d..0000000000 --- a/patches/server-remapped/0222-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 Jun 2018 01:18:49 -0400 -Subject: [PATCH] Unset Ignited flag on cancel of Explosion Event - -Otherwise the creeper infinite explodes - -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 8f8d0a23d011936150854a0606be3d63b18c57af..d9b5cf8ac01289801ded01d928fa7ead96551be5 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -@@ -47,7 +47,7 @@ public class Creeper extends Monster { - - private static final EntityDataAccessor DATA_SWELL_DIR = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.INT); - private static final EntityDataAccessor DATA_IS_POWERED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); -- private static final EntityDataAccessor DATA_IS_IGNITED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); -+ private static final EntityDataAccessor DATA_IS_IGNITED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); private static final EntityDataAccessor isIgnitedDW = DATA_IS_IGNITED; // Paper OBFHELPER - private int oldSwell; - public int swell; // PAIL - public int maxSwell = 30; -@@ -252,6 +252,7 @@ public class Creeper extends Monster { - this.spawnLingeringCloud(); - } else { - swell = 0; -+ this.entityData.set(isIgnitedDW, Boolean.valueOf(false)); // Paper - } - // CraftBukkit end - } diff --git a/patches/server-remapped/0227-Improve-EntityShootBowEvent.patch b/patches/server-remapped/0227-Improve-EntityShootBowEvent.patch deleted file mode 100644 index 4fc5ab999a..0000000000 --- a/patches/server-remapped/0227-Improve-EntityShootBowEvent.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 15 Jun 2013 19:51:17 -0400 -Subject: [PATCH] Improve EntityShootBowEvent - -Adds missing call to Illagers and also adds Arrow ItemStack to skeltons - -diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -index e8ad820b11dd1b89e442bb057d5761c90c4b1923..76027a7c9615495af64102744e264d7ba7c9b87e 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -+++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -@@ -197,7 +197,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo - - entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level.getDifficulty().getId() * 4)); - // CraftBukkit start -- org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), null, entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getOriginalItemStack(), entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper - if (event.isCancelled()) { - event.getProjectile().remove(); - return; -diff --git a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java -index ab8c41e72c15ee9e5256eba2ba2681a33ce8a8d9..2d07e9cf4c84bc32a7624f65173c4e8a6dc07165 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java -@@ -171,8 +171,18 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { - double d3 = (double) Mth.sqrt(d0 * d0 + d2 * d2); - - entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level.getDifficulty().getId() * 4)); -+ // Paper start -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getOriginalItemStack(), entityarrow, target.getUsedItemHand(), 0.8F, true); -+ if (event.isCancelled()) { -+ event.getProjectile().remove(); -+ return; -+ } -+ -+ if (event.getProjectile() == entityarrow.getBukkitEntity()) { -+ this.level.addFreshEntity(entityarrow); -+ } - this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); -- this.level.addFreshEntity(entityarrow); -+ // Paper end - } - - class IllusionerBlindnessSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { diff --git a/patches/server-remapped/0231-LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/server-remapped/0231-LivingEntity-Hand-Raised-Item-Use-API.patch deleted file mode 100644 index 181103a79c..0000000000 --- a/patches/server-remapped/0231-LivingEntity-Hand-Raised-Item-Use-API.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 Jun 2018 00:21:28 -0400 -Subject: [PATCH] LivingEntity Hand Raised/Item Use API - -How long an entity has raised hands to charge an attack or use an item - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 04489a915d11ba970a5188a5a913432ab4ef9faa..205c639d26652befebae925fc6e40976c370710f 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -209,7 +209,7 @@ public abstract class LivingEntity extends Entity { - private float speed; - private int noJumpDelay; - private float absorptionAmount; -- protected ItemStack useItem; -+ public ItemStack useItem; // Paper - public - protected int useItemRemaining; - protected int fallFlyTicks; - private BlockPos lastPos; -@@ -3291,10 +3291,12 @@ public abstract class LivingEntity extends Entity { - return this.useItem; - } - -+ public int getItemUseRemainingTime() { return this.getUseItemRemainingTicks(); } // Paper - OBFHELPER - public int getUseItemRemainingTicks() { - return this.useItemRemaining; - } - -+ public int getHandRaisedTime() { return this.getTicksUsingItem(); } // Paper - OBFHELPER - public int getTicksUsingItem() { - return this.isUsingItem() ? this.useItem.getUseDuration() - this.getUseItemRemainingTicks() : 0; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 663887d9aecc2823fe7d02a9b108a291cd27102c..6dd7a722e10a2727f68318b880f2726bb816f198 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -709,5 +709,30 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setShieldBlockingDelay(int delay) { - getHandle().setShieldBlockingDelay(delay); - } -+ -+ @Override -+ public ItemStack getActiveItem() { -+ return getHandle().useItem.asBukkitMirror(); -+ } -+ -+ @Override -+ public int getItemUseRemainingTime() { -+ return getHandle().getItemUseRemainingTime(); -+ } -+ -+ @Override -+ public int getHandRaisedTime() { -+ return getHandle().getHandRaisedTime(); -+ } -+ -+ @Override -+ public boolean isHandRaised() { -+ return getHandle().isUsingItem(); -+ } -+ -+ @Override -+ public org.bukkit.inventory.EquipmentSlot getHandRaised() { -+ return getHandle().getUsedItemHand() == net.minecraft.world.InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; -+ } - // Paper end - } diff --git a/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch index dacafbaa5b..b9b48eb821 100644 --- a/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch +++ b/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch @@ -6,19 +6,6 @@ Subject: [PATCH] Provide E/TE/Chunk count stat methods Provides counts without the ineffeciency of using .getEntities().size() which creates copy of the collections. -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 8323ddb363f49d266dd95f11241a30a9a27250aa..2cd34f326f374e3ad46a4eea8c84be326cd489a0 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -173,7 +173,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - public static final BlockPos END_SPAWN_POINT = new BlockPos(100, 50, 0); - private static final Logger LOGGER = LogManager.getLogger(); - private static final int EMPTY_TIME_NO_TICK = 300; -- final List players; -+ final List players; public final int getPlayerListSize() { return this.players.size(); } // Paper - public final ServerChunkCache chunkSource; // Paper - public - private final MinecraftServer server; - public final PrimaryLevelData serverLevelData; // CraftBukkit - type diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index 52d80086deff664fcfd8952b7cabbfa1f48ad131..a86b5272c0ac4dd64f796f7fd025c7a34a5d2f8d 100644 --- a/src/main/java/net/minecraft/world/level/Level.java @@ -33,7 +20,7 @@ index 52d80086deff664fcfd8952b7cabbfa1f48ad131..a86b5272c0ac4dd64f796f7fd025c7a3 private boolean tickingBlockEntities; public final Thread thread; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 5133febf4b3a83b2870fee2f9e45b1d12894df54..e11a1a21bff1fc5e730d6c63c5b0c623b3b2e037 100644 +index 5133febf4b3a83b2870fee2f9e45b1d12894df54..10b046ed843acac205608fa2fa3ffd4e4a277b5c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -270,6 +270,57 @@ public class CraftWorld implements World { @@ -87,7 +74,7 @@ index 5133febf4b3a83b2870fee2f9e45b1d12894df54..e11a1a21bff1fc5e730d6c63c5b0c623 + + @Override + public int getPlayerCount() { -+ return world.getPlayerListSize(); ++ return world.players().size(); + } + // Paper end + diff --git a/patches/server-remapped/0203-getPlayerUniqueId-API.patch b/patches/server/0185-getPlayerUniqueId-API.patch similarity index 94% rename from patches/server-remapped/0203-getPlayerUniqueId-API.patch rename to patches/server/0185-getPlayerUniqueId-API.patch index 64d63b916e..bdb836561a 100644 --- a/patches/server-remapped/0203-getPlayerUniqueId-API.patch +++ b/patches/server/0185-getPlayerUniqueId-API.patch @@ -9,7 +9,7 @@ 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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 10addb128a357e7719854bf4f9d75f5def32b27d..20915e40fbcf28faed603d449a99bf2157fcf972 100644 +index cb09b6170a74984628f2c3dbacad2ddc9fe56faf..df94ac3f5319cd990f5592d57d2e319c84f51524 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -1517,6 +1517,25 @@ public final class CraftServer implements Server { diff --git a/patches/server-remapped/0204-Make-player-data-saving-configurable.patch b/patches/server/0186-Make-player-data-saving-configurable.patch similarity index 100% rename from patches/server-remapped/0204-Make-player-data-saving-configurable.patch rename to patches/server/0186-Make-player-data-saving-configurable.patch diff --git a/patches/server-remapped/0205-Make-legacy-ping-handler-more-reliable.patch b/patches/server/0187-Make-legacy-ping-handler-more-reliable.patch similarity index 79% rename from patches/server-remapped/0205-Make-legacy-ping-handler-more-reliable.patch rename to patches/server/0187-Make-legacy-ping-handler-more-reliable.patch index 72dfa9fd8e..f529d88f16 100644 --- a/patches/server-remapped/0205-Make-legacy-ping-handler-more-reliable.patch +++ b/patches/server/0187-Make-legacy-ping-handler-more-reliable.patch @@ -28,19 +28,19 @@ respond to the request. [2]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h4-13 diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java -index e2867a3de87a778a897b4963212fa4aab566a643..1d11802876c1a94ecf991cd8249bd6a911c0ac20 100644 +index a2b0237a27379d05e8ca15cb033ee3fd2a5bb29b..6a759cfd0c2df4daaf126d12d20ac8d701e41f9d 100644 --- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java +++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java -@@ -15,6 +15,7 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { - +@@ -16,6 +16,7 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { private static final Logger LOGGER = LogManager.getLogger(); + public static final int FAKE_PROTOCOL_VERSION = 127; private final ServerConnectionListener serverConnectionListener; + private ByteBuf buf; // Paper public LegacyQueryHandler(ServerConnectionListener networkIo) { this.serverConnectionListener = networkIo; -@@ -23,6 +24,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { - public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) throws Exception { +@@ -24,6 +25,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) { ByteBuf bytebuf = (ByteBuf) object; + // Paper start - Make legacy ping handler more reliable @@ -56,7 +56,7 @@ index e2867a3de87a778a897b4963212fa4aab566a643..1d11802876c1a94ecf991cd8249bd6a9 bytebuf.markReaderIndex(); boolean flag = true; -@@ -53,6 +64,10 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { +@@ -54,6 +65,10 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); break; default: @@ -67,20 +67,7 @@ index e2867a3de87a778a897b4963212fa4aab566a643..1d11802876c1a94ecf991cd8249bd6a9 boolean flag1 = bytebuf.readUnsignedByte() == 1; flag1 &= bytebuf.readUnsignedByte() == 250; -@@ -67,15 +82,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { - return; - } - -- LegacyQueryHandler.LOGGER.debug("Ping: (1.6) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); -- String s1 = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit -- ByteBuf bytebuf1 = this.createReply(s1); -+ LegacyPingHandler.LOGGER.debug("Ping: (1.6) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); -+ String s1 = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit -+ ByteBuf bytebuf1 = this.a(s1); - - try { -- this.sendFlushAndClose(channelhandlercontext, bytebuf1); -+ this.a(channelhandlercontext, bytebuf1); +@@ -77,6 +92,7 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { } finally { bytebuf1.release(); } @@ -88,7 +75,7 @@ index e2867a3de87a778a897b4963212fa4aab566a643..1d11802876c1a94ecf991cd8249bd6a9 } bytebuf.release(); -@@ -93,6 +109,90 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { +@@ -94,6 +110,90 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { } diff --git a/patches/server-remapped/0206-Call-PaperServerListPingEvent-for-legacy-pings.patch b/patches/server/0188-Call-PaperServerListPingEvent-for-legacy-pings.patch similarity index 96% rename from patches/server-remapped/0206-Call-PaperServerListPingEvent-for-legacy-pings.patch rename to patches/server/0188-Call-PaperServerListPingEvent-for-legacy-pings.patch index 90d915afd6..459475062d 100644 --- a/patches/server-remapped/0206-Call-PaperServerListPingEvent-for-legacy-pings.patch +++ b/patches/server/0188-Call-PaperServerListPingEvent-for-legacy-pings.patch @@ -84,7 +84,7 @@ index 0000000000000000000000000000000000000000..74c012fd40491f1d870fbc1aa8c318a2 + +} diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java -index 1d11802876c1a94ecf991cd8249bd6a911c0ac20..dfe2cd46f2432dca2028b7436c4108e3f190787f 100644 +index 6a759cfd0c2df4daaf126d12d20ac8d701e41f9d..3962e82d4e4c5f792a37e825891e6960e737452d 100644 --- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java +++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java @@ -1,5 +1,7 @@ @@ -95,7 +95,7 @@ index 1d11802876c1a94ecf991cd8249bd6a911c0ac20..dfe2cd46f2432dca2028b7436c4108e3 import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; -@@ -46,12 +48,19 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { +@@ -47,12 +49,19 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { MinecraftServer minecraftserver = this.serverConnectionListener.getServer(); int i = bytebuf.readableBytes(); String s; @@ -117,7 +117,7 @@ index 1d11802876c1a94ecf991cd8249bd6a911c0ac20..dfe2cd46f2432dca2028b7436c4108e3 this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); break; case 1: -@@ -60,7 +69,14 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { +@@ -61,7 +70,14 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { } LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); @@ -133,7 +133,7 @@ index 1d11802876c1a94ecf991cd8249bd6a911c0ac20..dfe2cd46f2432dca2028b7436c4108e3 this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); break; default: -@@ -170,8 +186,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { +@@ -171,8 +187,16 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); diff --git a/patches/server-remapped/0207-Flag-to-disable-the-channel-limit.patch b/patches/server/0189-Flag-to-disable-the-channel-limit.patch similarity index 69% rename from patches/server-remapped/0207-Flag-to-disable-the-channel-limit.patch rename to patches/server/0189-Flag-to-disable-the-channel-limit.patch index 467dda42a9..c2ee900d0d 100644 --- a/patches/server-remapped/0207-Flag-to-disable-the-channel-limit.patch +++ b/patches/server/0189-Flag-to-disable-the-channel-limit.patch @@ -9,10 +9,10 @@ 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 9d853733ff9054cc48925e22c8bb3c8d9b898808..46338fe5693003698de9c7b37a860c3481e06233 100644 +index 8bf0c74ee32e8cb7c0f48bc964552811ad6ee468..8df1894df3583840412ccc7ccdc4b23db6dd6265 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -143,6 +143,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -148,6 +148,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Paper start private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; private String resourcePackHash; @@ -20,12 +20,12 @@ index 9d853733ff9054cc48925e22c8bb3c8d9b898808..46338fe5693003698de9c7b37a860c34 // Paper end public CraftPlayer(CraftServer server, ServerPlayer entity) { -@@ -1576,7 +1577,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1589,7 +1590,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void addChannel(String channel) { -- Preconditions.checkState(channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); -+ Preconditions.checkState(DISABLE_CHANNEL_LIMIT || channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); // Paper - flag to disable channel limit +- Preconditions.checkState(this.channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); ++ Preconditions.checkState(DISABLE_CHANNEL_LIMIT || this.channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); // Paper - flag to disable channel limit channel = StandardMessenger.validateAndCorrectChannel(channel); - if (channels.add(channel)) { + if (this.channels.add(channel)) { server.getPluginManager().callEvent(new PlayerRegisterChannelEvent(this, channel)); diff --git a/patches/server-remapped/0208-Add-method-to-open-already-placed-sign.patch b/patches/server/0190-Add-method-to-open-already-placed-sign.patch similarity index 61% rename from patches/server-remapped/0208-Add-method-to-open-already-placed-sign.patch rename to patches/server/0190-Add-method-to-open-already-placed-sign.patch index 9a923369d1..01f8ae7ef7 100644 --- a/patches/server-remapped/0208-Add-method-to-open-already-placed-sign.patch +++ b/patches/server/0190-Add-method-to-open-already-placed-sign.patch @@ -5,18 +5,10 @@ Subject: [PATCH] Add method to open already placed sign diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index c62d01719f21762aa10294815ab88e450e4dce3f..4aec1c2b26d48cb5bea3dfb9e183526763bdb98f 100644 +index 6c404878e58f68c9ac86a1771c23e528f3817e32..7f7322b5174a7580675b0607b0f282f7bf75a3e2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -28,6 +28,7 @@ import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.CraftingTableBlock; - import net.minecraft.world.level.block.EnchantmentTableBlock; - import net.minecraft.world.level.block.entity.BlockEntity; -+import net.minecraft.world.level.block.entity.SignBlockEntity; - import net.minecraft.world.level.block.state.BlockState; - import org.bukkit.GameMode; - import org.bukkit.Location; -@@ -604,6 +605,17 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -604,6 +604,17 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { } } @@ -25,12 +17,12 @@ index c62d01719f21762aa10294815ab88e450e4dce3f..4aec1c2b26d48cb5bea3dfb9e1835267 + public void openSign(org.bukkit.block.Sign sign) { + org.apache.commons.lang.Validate.isTrue(sign.getWorld().equals(this.getWorld()), "Sign must be in the same world as player is in"); + org.bukkit.craftbukkit.block.CraftSign craftSign = (org.bukkit.craftbukkit.block.CraftSign) sign; -+ SignBlockEntity teSign = craftSign.getTileEntity(); ++ net.minecraft.world.level.block.entity.SignBlockEntity teSign = craftSign.getTileEntity(); + // Make sign editable temporarily, will be set back to false in PlayerConnection later + teSign.isEditable = true; -+ getHandle().openTextEdit(teSign); ++ this.getHandle().openTextEdit(teSign); + } + // Paper end @Override public boolean dropItem(boolean dropAll) { - return getHandle().drop(dropAll); + return this.getHandle().drop(dropAll); diff --git a/patches/server-remapped/0209-Configurable-sprint-interruption-on-attack.patch b/patches/server/0191-Configurable-sprint-interruption-on-attack.patch similarity index 85% rename from patches/server-remapped/0209-Configurable-sprint-interruption-on-attack.patch rename to patches/server/0191-Configurable-sprint-interruption-on-attack.patch index dfe307fc2f..70eed87733 100644 --- a/patches/server-remapped/0209-Configurable-sprint-interruption-on-attack.patch +++ b/patches/server/0191-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/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 48f0385c7203c7955de5a015f3dc42be2ab7b681..cebf1a623a9bec72d60fdd23dda01868ef6431d4 100644 +index da4a110809eee691c1d5b072de335d75e1516eae..9225372cb9ef51a8cfbd4cee543c250aa2ac9c49 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -358,4 +358,9 @@ public class PaperWorldConfig { +@@ -352,4 +352,9 @@ public class PaperWorldConfig { private void squidMaxSpawnHeight() { squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); } @@ -20,10 +20,10 @@ index 48f0385c7203c7955de5a015f3dc42be2ab7b681..cebf1a623a9bec72d60fdd23dda01868 + } } 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 c4aa824d03de952fe6b306e539baa47af979add1..552920f59aae9de2cad3edcdc8c48a91dff49093 100644 +index 3c0aca2b90521da83cf494d9fff953a17a57701d..a3f719d9dc63af9decc54a789f04595bb2d55710 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1180,7 +1180,11 @@ public abstract class Player extends LivingEntity { +@@ -1240,7 +1240,11 @@ public abstract class Player extends LivingEntity { } this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); diff --git a/patches/server/0192-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/patches/server/0192-Fix-exploit-that-allowed-colored-signs-to-be-created.patch new file mode 100644 index 0000000000..a1458e6d99 --- /dev/null +++ b/patches/server/0192-Fix-exploit-that-allowed-colored-signs-to-be-created.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 0x22 <0x22@futureclient.net> +Date: Thu, 26 Apr 2018 04:41:11 -0400 +Subject: [PATCH] Fix exploit that allowed colored signs to be created + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 205e4ef25f49edc11a408c302d9ba68a59c68a5a..35a00a622ff0c3582e08dbbefb1d34a84e590a81 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2787,9 +2787,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + for (int i = 0; i < list.size(); ++i) { + if (this.player.isTextFilteringEnabled()) { +- lines.add(net.kyori.adventure.text.Component.text(list.get(i).getFiltered())); ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(list.get(i).getFiltered()))); + } else { +- lines.add(net.kyori.adventure.text.Component.text(list.get(i).getRaw())); ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(list.get(i).getRaw()))); + } + } + SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.cserver.getPlayer(this.player), lines); diff --git a/patches/server-remapped/0211-EndermanEscapeEvent.patch b/patches/server/0193-EndermanEscapeEvent.patch similarity index 65% rename from patches/server-remapped/0211-EndermanEscapeEvent.patch rename to patches/server/0193-EndermanEscapeEvent.patch index 038bdea2df..1a3a418587 100644 --- a/patches/server-remapped/0211-EndermanEscapeEvent.patch +++ b/patches/server/0193-EndermanEscapeEvent.patch @@ -8,44 +8,36 @@ Fires an event anytime an enderman intends to teleport away from the player You may cancel this, enabling ranged attacks to damage the enderman for example. diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -index 1c2998c89fd660d6b26b7ff48cddd1862b9b1828..1b9c77666204765a3ed5648b0f8eaa820f578e58 100644 +index a18765fe0be5a83ee2da3638aa5107e9345f19b6..29e53aebd1dc22d5dd2753cc7acbea425cb0054e 100644 --- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster; - - import java.util.EnumSet; - import java.util.Optional; -+import com.destroystokyo.paper.event.entity.EndermanEscapeEvent; // Paper - import java.util.Random; - import java.util.UUID; - import java.util.function.Predicate; -@@ -109,6 +110,12 @@ public class EnderMan extends Monster implements NeutralMob { - setGoalTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, true); +@@ -109,6 +109,12 @@ public class EnderMan extends Monster implements NeutralMob { + this.setGoalTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, true); } + // Paper start -+ private boolean tryEscape(EndermanEscapeEvent.Reason reason) { -+ return new EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent(); ++ private boolean tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason reason) { ++ return new com.destroystokyo.paper.event.entity.EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent(); + } + // Paper end + @Override public boolean setGoalTarget(LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { if (!super.setGoalTarget(entityliving, reason, fireEvent)) { -@@ -262,7 +269,7 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -262,7 +268,7 @@ public class EnderMan extends Monster implements NeutralMob { if (this.level.isDay() && this.tickCount >= this.targetChangeTime + 600) { float f = this.getBrightness(); - if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) { -+ if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper ++ if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper this.setTarget((LivingEntity) null); this.teleport(); } -@@ -360,17 +367,19 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -360,17 +366,19 @@ public class EnderMan extends Monster implements NeutralMob { if (this.isInvulnerableTo(source)) { return false; } else if (source instanceof IndirectEntityDamageSource) { -+ if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start ++ if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start for (int i = 0; i < 64; ++i) { if (this.teleport()) { return true; @@ -58,25 +50,25 @@ index 1c2998c89fd660d6b26b7ff48cddd1862b9b1828..1b9c77666204765a3ed5648b0f8eaa82 boolean flag = super.hurt(source, amount); - if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) { -+ if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0 && this.tryEscape(source == DamageSource.DROWN ? EndermanEscapeEvent.Reason.DROWN : EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - use to be critical hits as else, but mojang removed critical hits in 1.16.2 due to MC-185684 ++ if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0 && this.tryEscape(source == DamageSource.DROWN ? com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.DROWN : com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - use to be critical hits as else, but mojang removed critical hits in 1.16.2 due to MC-185684 this.teleport(); } -@@ -515,7 +524,7 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -516,7 +524,7 @@ public class EnderMan extends Monster implements NeutralMob { - static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal { + private static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal { - private final EnderMan enderman; + private final EnderMan enderman; public final EnderMan getEnderman() { return this.enderman; } // Paper - OBFHELPER private Player pendingTarget; private int aggroTime; private int teleportTime; -@@ -578,7 +587,7 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -579,7 +587,7 @@ public class EnderMan extends Monster implements NeutralMob { } else { if (this.target != null && !this.enderman.isPassenger()) { if (this.enderman.isLookingAtMe((Player) this.target)) { - if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D) { -+ if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D && this.getEnderman().tryEscape(EndermanEscapeEvent.Reason.STARE)) { // Paper ++ if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D && this.getEnderman().tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.STARE)) { // Paper this.enderman.teleport(); } diff --git a/patches/server-remapped/0212-Enderman.teleportRandomly.patch b/patches/server/0194-Enderman.teleportRandomly.patch similarity index 70% rename from patches/server-remapped/0212-Enderman.teleportRandomly.patch rename to patches/server/0194-Enderman.teleportRandomly.patch index f76f4023f9..c39817ff58 100644 --- a/patches/server-remapped/0212-Enderman.teleportRandomly.patch +++ b/patches/server/0194-Enderman.teleportRandomly.patch @@ -6,26 +6,27 @@ Subject: [PATCH] Enderman.teleportRandomly() Ability to trigger the vanilla "teleport randomly" mechanic of an enderman. diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -index 1b9c77666204765a3ed5648b0f8eaa820f578e58..1981c08af85b16d45531ffae4fe790bb31edec04 100644 +index 29e53aebd1dc22d5dd2753cc7acbea425cb0054e..dedab212105f55ebce31f2309e34d8c3136c193f 100644 --- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -@@ -278,6 +278,7 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -277,7 +277,7 @@ public class EnderMan extends Monster implements NeutralMob { super.customServerAiStep(); } -+ public final boolean teleportRandomly() { return this.teleport(); } // Paper - OBFHELPER - protected boolean teleport() { +- protected boolean teleport() { ++ public boolean teleport() { // Paper - protected->public if (!this.level.isClientSide() && this.isAlive()) { double d0 = this.getX() + (this.random.nextDouble() - 0.5D) * 64.0D; + double d1 = this.getY() + (double) (this.random.nextInt(64) - 32); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -index d17ed71e800ebcd12b69745f239fa7dbc8a0c808..1edb45490b35b6517201acc8551da8d3c5a489de 100644 +index b72d7ade10075a13a617a370e2b8021326c9478d..ae669a970aa1f17ed786640de8a481364543c58e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java @@ -16,6 +16,7 @@ public class CraftEnderman extends CraftMonster implements Enderman { super(server, entity); } -+ @Override public boolean teleportRandomly() { return getHandle().teleportRandomly(); } // Paper ++ @Override public boolean teleportRandomly() { return getHandle().teleport(); } // Paper @Override public MaterialData getCarriedMaterial() { - BlockState blockData = getHandle().getCarriedBlock(); + BlockState blockData = this.getHandle().getCarriedBlock(); diff --git a/patches/server-remapped/0213-Block-Enderpearl-Travel-Exploit.patch b/patches/server/0195-Block-Enderpearl-Travel-Exploit.patch similarity index 78% rename from patches/server-remapped/0213-Block-Enderpearl-Travel-Exploit.patch rename to patches/server/0195-Block-Enderpearl-Travel-Exploit.patch index 47a535288c..12f29c1d31 100644 --- a/patches/server-remapped/0213-Block-Enderpearl-Travel-Exploit.patch +++ b/patches/server/0195-Block-Enderpearl-Travel-Exploit.patch @@ -12,10 +12,10 @@ This disables that by not saving the thrower when the chunk is unloaded. This is mainly useful for survival servers that do not allow freeform teleporting. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index cebf1a623a9bec72d60fdd23dda01868ef6431d4..e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec 100644 +index 9225372cb9ef51a8cfbd4cee543c250aa2ac9c49..a0a846a2e60bdc17537bd697137f65321c1a61d8 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -363,4 +363,10 @@ public class PaperWorldConfig { +@@ -357,4 +357,10 @@ public class PaperWorldConfig { private void disableSprintInterruptionOnAttack() { disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); } @@ -27,14 +27,14 @@ index cebf1a623a9bec72d60fdd23dda01868ef6431d4..e8e1e7dafaf1c105b2f58cf3e118e3d6 + } } diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index 14ed4f212a9c9c3128c4ddbef7b2e243c925b509..16b554675a276471851846d4f2bea06fdcc166d9 100644 +index c72ec22beff6aa1f7932fa44dc7d591ceeec1158..c25cb17ef1a7c56e10ce3ccb5665c9dce3e6efa6 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -62,6 +62,7 @@ public abstract class Projectile extends Entity { - protected void readAdditionalSaveData(CompoundTag tag) { - if (tag.hasUUID("Owner")) { - this.ownerUUID = tag.getUUID("Owner"); +@@ -88,6 +88,7 @@ public abstract class Projectile extends Entity { + protected void readAdditionalSaveData(CompoundTag nbt) { + if (nbt.hasUUID("Owner")) { + this.ownerUUID = nbt.getUUID("Owner"); + if (this instanceof ThrownEnderpearl && this.level != null && this.level.paperConfig.disableEnderpearlExploit) { this.ownerUUID = null; } // Paper - Don't store shooter name for pearls to block enderpearl travel exploit } - this.leftOwner = tag.getBoolean("LeftOwner"); + this.leftOwner = nbt.getBoolean("LeftOwner"); diff --git a/patches/server-remapped/0214-Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch similarity index 74% rename from patches/server-remapped/0214-Expand-World.spawnParticle-API-and-add-Builder.patch rename to patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch index e2c16b5648..45e96cfdf8 100644 --- a/patches/server-remapped/0214-Expand-World.spawnParticle-API-and-add-Builder.patch +++ b/patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch @@ -10,19 +10,10 @@ Adds an option to control the force mode of the particle. This adds a new Builder API which is much friendlier to use. diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 20650bfd10abfa010e71cfeede06c461d50d19a3..5110f2c70d96284e8e7592b3d89266b867b9a466 100644 +index 8323ddb363f49d266dd95f11241a30a9a27250aa..cf074ef0cb01bc2cbd8c529e7233ceb9443f764d 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -164,7 +164,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - public final Int2ObjectMap entitiesById = new Int2ObjectLinkedOpenHashMap(); - private final Map entitiesByUuid = Maps.newHashMap(); - private final Queue toAddAfterTick = Queues.newArrayDeque(); -- private final List players = Lists.newArrayList(); -+ public final List players = Lists.newArrayList(); // Paper - private -> public - public final ServerChunkCache chunkSource; // Paper - public - boolean tickingEntities; - private final MinecraftServer server; -@@ -1472,12 +1472,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1287,12 +1287,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } public int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { @@ -43,10 +34,10 @@ index 20650bfd10abfa010e71cfeede06c461d50d19a3..5110f2c70d96284e8e7592b3d89266b8 if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 88658d4deacc29128c537e2e02fdc8f684090a2c..beb7219312be5143a50b0841c25efea5dbcc1267 100644 +index bc80e0062ef679e7cb147bd1a6da52bf95da52b8..ab59b0e9dc827e7ebe0c4dea633680908dcb5874 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2334,11 +2334,17 @@ public class CraftWorld implements World { +@@ -2355,11 +2355,17 @@ public class CraftWorld implements World { @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) { @@ -58,9 +49,9 @@ index 88658d4deacc29128c537e2e02fdc8f684090a2c..beb7219312be5143a50b0841c25efea5 if (data != null && !particle.getDataType().isInstance(data)) { throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); } - getHandle().sendParticles( + this.getHandle().sendParticles( - null, // Sender -+ receivers == null ? getHandle().players : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API Expansion ++ receivers == null ? getHandle().players() : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API Expansion + sender != null ? ((CraftPlayer) sender).getHandle() : null, // Sender // Paper - Particle API Expansion CraftParticle.toNMS(particle, data), // Particle x, y, z, // Position diff --git a/patches/server/0197-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/patches/server/0197-Prevent-Frosted-Ice-from-loading-holding-chunks.patch new file mode 100644 index 0000000000..4b233954b2 --- /dev/null +++ b/patches/server/0197-Prevent-Frosted-Ice-from-loading-holding-chunks.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 10 Mar 2018 16:33:15 -0500 +Subject: [PATCH] Prevent Frosted Ice from loading/holding chunks + +1.17: Shouldn't be needed as blocks no longer tick without at least 1 radius chunk loaded. + +diff --git a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +index 54eb7ba0265bb155dd1c753661242fa9d299ff80..5b5d606a794c885267b6f5e2bbfe9b0a318ad767 100644 +--- a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +@@ -38,7 +38,8 @@ public class FrostedIceBlock extends IceBlock { + + for(Direction direction : Direction.values()) { + mutableBlockPos.setWithOffset(pos, direction); +- BlockState blockState = world.getBlockState(mutableBlockPos); ++ BlockState blockState = world.getTypeIfLoaded(mutableBlockPos); // Paper ++ if (blockState == null) { continue; } // Paper + if (blockState.is(this) && !this.slightlyMelt(blockState, world, mutableBlockPos)) { + world.getBlockTicks().scheduleTick(mutableBlockPos, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay + } +@@ -75,7 +76,10 @@ public class FrostedIceBlock extends IceBlock { + + for(Direction direction : Direction.values()) { + mutableBlockPos.setWithOffset(pos, direction); +- if (world.getBlockState(mutableBlockPos).is(this)) { ++ // Paper start ++ BlockState blockState = world.getTypeIfLoaded(mutableBlockPos); ++ if (blockState != null && blockState.is(this)) { ++ // Paper end + ++i; + if (i >= maxNeighbors) { + return false; diff --git a/patches/server/0198-EndermanAttackPlayerEvent.patch b/patches/server/0198-EndermanAttackPlayerEvent.patch new file mode 100644 index 0000000000..ce7100da5d --- /dev/null +++ b/patches/server/0198-EndermanAttackPlayerEvent.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 1 May 2018 20:18:54 -0400 +Subject: [PATCH] EndermanAttackPlayerEvent + +Allow control over whether or not an enderman aggros a player. + +This allows you to override/extend the pumpkin/stare logic. + +diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index dedab212105f55ebce31f2309e34d8c3136c193f..abd1130529dd74780054e26bac89cf757ba9cdc1 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -220,7 +220,15 @@ public class EnderMan extends Monster implements NeutralMob { + this.readPersistentAngerSaveData(this.level, nbt); + } + +- boolean isLookingAtMe(Player player) { ++ // Paper start - EndermanAttackPlayerEvent ++ private boolean isLookingAtMe(Player player) { ++ boolean shouldAttack = isLookingAtMe_check(player); ++ com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) player.getBukkitEntity()); ++ event.setCancelled(!shouldAttack); ++ return event.callEvent(); ++ } ++ private boolean isLookingAtMe_check(Player player) { ++ // Paper end + ItemStack itemstack = (ItemStack) player.getInventory().armor.get(3); + + if (itemstack.is(Blocks.CARVED_PUMPKIN.asItem())) { diff --git a/patches/server-remapped/0216-WitchConsumePotionEvent.patch b/patches/server/0199-WitchConsumePotionEvent.patch similarity index 89% rename from patches/server-remapped/0216-WitchConsumePotionEvent.patch rename to patches/server/0199-WitchConsumePotionEvent.patch index b17791b352..cbd042f32a 100644 --- a/patches/server-remapped/0216-WitchConsumePotionEvent.patch +++ b/patches/server/0199-WitchConsumePotionEvent.patch @@ -6,13 +6,13 @@ Subject: [PATCH] WitchConsumePotionEvent Fires when a witch consumes the potion in their hand diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java -index 9b0269bdd25123f5c0662187de49a869ead3ee81..dd5976d81ff57e8691ba60f425af37572edd26e7 100644 +index 0c04665c6e2f5624e21e269d706fea842d54cefd..ecb3843ff3b4f0034f6aaa16cfc09cbd046d9008 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Witch.java +++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java @@ -124,7 +124,11 @@ public class Witch extends Raider implements RangedAttackMob { this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); - if (itemstack.getItem() == Items.POTION) { + if (itemstack.is(Items.POTION)) { - List list = PotionUtils.getMobEffects(itemstack); + // Paper start + com.destroystokyo.paper.event.entity.WitchConsumePotionEvent event = new com.destroystokyo.paper.event.entity.WitchConsumePotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); diff --git a/patches/server-remapped/0217-WitchThrowPotionEvent.patch b/patches/server/0200-WitchThrowPotionEvent.patch similarity index 83% rename from patches/server-remapped/0217-WitchThrowPotionEvent.patch rename to patches/server/0200-WitchThrowPotionEvent.patch index 0630f7d920..c913ecabce 100644 --- a/patches/server-remapped/0217-WitchThrowPotionEvent.patch +++ b/patches/server/0200-WitchThrowPotionEvent.patch @@ -6,10 +6,10 @@ Subject: [PATCH] WitchThrowPotionEvent Fired when a witch throws a potion at a player diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java -index dd5976d81ff57e8691ba60f425af37572edd26e7..7cefabfb0d8a264cae24f23c06f1c5f552ff0158 100644 +index ecb3843ff3b4f0034f6aaa16cfc09cbd046d9008..e2762c6c37975eb2da59d408998a5c0368c146d1 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Witch.java +++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java -@@ -224,9 +224,16 @@ public class Witch extends Raider implements RangedAttackMob { +@@ -236,9 +236,16 @@ public class Witch extends Raider implements RangedAttackMob { potionregistry = Potions.WEAKNESS; } @@ -25,6 +25,6 @@ index dd5976d81ff57e8691ba60f425af37572edd26e7..7cefabfb0d8a264cae24f23c06f1c5f5 - entitypotion.setItem(PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potionregistry)); + entitypotion.setItem(potion); + // Paper end - entitypotion.xRot -= -20.0F; - entitypotion.shoot(d0, d1 + (double) (f1 * 0.2F), d2, 0.75F, 8.0F); + entitypotion.setXRot(entitypotion.getXRot() - -20.0F); + entitypotion.shoot(d0, d1 + d3 * 0.2D, d2, 0.75F, 8.0F); if (!this.isSilent()) { diff --git a/patches/server-remapped/0218-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch similarity index 79% rename from patches/server-remapped/0218-Allow-spawning-Item-entities-with-World.spawnEntity.patch rename to patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch index 7e80925cf5..7c6dcd87e2 100644 --- a/patches/server-remapped/0218-Allow-spawning-Item-entities-with-World.spawnEntity.patch +++ b/patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch @@ -8,17 +8,17 @@ This API has more capabilities than .dropItem with the Consumer function Item can be set inside of the Consumer pre spawn function. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index beb7219312be5143a50b0841c25efea5dbcc1267..2dc9daaeea600fff1f2efddf74b6849fd745a28c 100644 +index ab59b0e9dc827e7ebe0c4dea633680908dcb5874..058346b89c07d44a5425a61abedcfc440cb9ee21 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1497,6 +1497,10 @@ public class CraftWorld implements World { +@@ -1505,6 +1505,10 @@ public class CraftWorld implements World { if (Boat.class.isAssignableFrom(clazz)) { - entity = new net.minecraft.world.entity.vehicle.Boat(world, x, y, z); + entity = new net.minecraft.world.entity.vehicle.Boat(this.world, x, y, z); entity.moveTo(x, y, z, yaw, pitch); + // Paper start + } else if (org.bukkit.entity.Item.class.isAssignableFrom(clazz)) { + entity = new ItemEntity(world, x, y, z, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Item.byBlock(net.minecraft.world.level.block.Blocks.DIRT))); + // Paper end } else if (FallingBlock.class.isAssignableFrom(clazz)) { - entity = new FallingBlockEntity(world, x, y, z, world.getBlockState(new BlockPos(x, y, z))); + entity = new FallingBlockEntity(this.world, x, y, z, this.world.getBlockState(new BlockPos(x, y, z))); } else if (Projectile.class.isAssignableFrom(clazz)) { diff --git a/patches/server-remapped/0219-WitchReadyPotionEvent.patch b/patches/server/0202-WitchReadyPotionEvent.patch similarity index 93% rename from patches/server-remapped/0219-WitchReadyPotionEvent.patch rename to patches/server/0202-WitchReadyPotionEvent.patch index 2177cecc8f..62a6ed06e9 100644 --- a/patches/server-remapped/0219-WitchReadyPotionEvent.patch +++ b/patches/server/0202-WitchReadyPotionEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] WitchReadyPotionEvent diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java -index 7cefabfb0d8a264cae24f23c06f1c5f552ff0158..a37ee32b46aa87be6e3eeca2892b4e7294fd1aef 100644 +index e2762c6c37975eb2da59d408998a5c0368c146d1..5e2e8cb5eba4ba36065f07abed954b2aad022321 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Witch.java +++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java @@ -157,7 +157,11 @@ public class Witch extends Raider implements RangedAttackMob { diff --git a/patches/server/0203-ItemStack-getMaxItemUseDuration.patch b/patches/server/0203-ItemStack-getMaxItemUseDuration.patch new file mode 100644 index 0000000000..3a1ceb4922 --- /dev/null +++ b/patches/server/0203-ItemStack-getMaxItemUseDuration.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 5 Jun 2018 23:00:29 -0400 +Subject: [PATCH] ItemStack#getMaxItemUseDuration + +Allows you to determine how long it takes to use a usable/consumable item + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +index 51c1f62af5c25fe620f1d8a9cb03473e849db68d..3fbfe4f77c4b82d96ed022498b2d9175d548e247 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +@@ -173,6 +173,13 @@ public final class CraftItemStack extends ItemStack { + return (this.handle == null) ? Material.AIR.getMaxStackSize() : this.handle.getItem().getMaxStackSize(); + } + ++ // Paper start ++ @Override ++ public int getMaxItemUseDuration() { ++ return handle == null ? 0 : handle.getUseDuration(); ++ } ++ // Paper end ++ + @Override + public void addUnsafeEnchantment(Enchantment ench, int level) { + Validate.notNull(ench, "Cannot add null enchantment"); diff --git a/patches/server-remapped/0221-Implement-EntityTeleportEndGatewayEvent.patch b/patches/server/0204-Implement-EntityTeleportEndGatewayEvent.patch similarity index 71% rename from patches/server-remapped/0221-Implement-EntityTeleportEndGatewayEvent.patch rename to patches/server/0204-Implement-EntityTeleportEndGatewayEvent.patch index 007bf52a29..3c1584cc23 100644 --- a/patches/server-remapped/0221-Implement-EntityTeleportEndGatewayEvent.patch +++ b/patches/server/0204-Implement-EntityTeleportEndGatewayEvent.patch @@ -5,28 +5,28 @@ Subject: [PATCH] Implement EntityTeleportEndGatewayEvent diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -index 2c974f9801d209907733bed8e6c4c9ef46e2b610..b70e0633435a272ae1e9fbd12d7f18862de0b951 100644 +index 2bf65c8da827c6bdbfb74a9d8ee5754584c40c53..f9cd4c28db815205e548ac59515cd80989741bab 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -@@ -191,9 +191,20 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements +@@ -225,9 +225,20 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { } // CraftBukkit end + // Paper start - EntityTeleportEndGatewayEvent - replicated from above + org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity = entity.getBukkitEntity(); -+ org.bukkit.Location location = new Location(level.getWorld(), (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); ++ org.bukkit.Location location = new Location(world.getWorld(), (double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D); + location.setPitch(bukkitEntity.getLocation().getPitch()); + location.setYaw(bukkitEntity.getLocation().getYaw()); + -+ com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent event = new com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent(bukkitEntity, bukkitEntity.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(level, this.getBlockPos()).getBlock())); ++ com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent event = new com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent(bukkitEntity, bukkitEntity.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(world, blockEntity.getBlockPos()).getBlock())); + if (!event.callEvent()) { + return; + } + // Paper end entity1.setPortalCooldown(); -- entity1.teleportToWithTicket((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D); +- entity1.teleportToWithTicket((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY(), (double) blockposition1.getZ() + 0.5D); + entity1.teleportToWithTicket(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); // Paper } - this.triggerCooldown(); + TheEndGatewayBlockEntity.triggerCooldown(world, pos, state, blockEntity); diff --git a/patches/server/0205-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/patches/server/0205-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch new file mode 100644 index 0000000000..ce293a68a0 --- /dev/null +++ b/patches/server/0205-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 10 Jun 2018 01:18:49 -0400 +Subject: [PATCH] Unset Ignited flag on cancel of Explosion Event + +Otherwise the creeper infinite explodes + +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 ddc48d37f962b6743f3f356745c9ebe6a06f79f1..3bbf6c9bfbb79fd4242cf66d7ace1d8f87404636 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +@@ -272,6 +272,7 @@ public class Creeper extends Monster implements PowerableMob { + this.spawnLingeringCloud(); + } else { + this.swell = 0; ++ this.entityData.set(DATA_IS_IGNITED, Boolean.valueOf(false)); // Paper + } + // CraftBukkit end + } diff --git a/patches/server-remapped/0223-Fix-CraftEntity-hashCode.patch b/patches/server/0206-Fix-CraftEntity-hashCode.patch similarity index 91% rename from patches/server-remapped/0223-Fix-CraftEntity-hashCode.patch rename to patches/server/0206-Fix-CraftEntity-hashCode.patch index dbc0942196..35cf02c08d 100644 --- a/patches/server-remapped/0223-Fix-CraftEntity-hashCode.patch +++ b/patches/server/0206-Fix-CraftEntity-hashCode.patch @@ -21,10 +21,10 @@ check is essentially the same as this.getHandle() == other.getHandle() However, replaced it too to make it clearer of intent. diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index ecb5f5ca547930f91602d539e541964cd9f10287..e1bbaf620f3ed2a6cb9ce8007a78c4cee47b653e 100644 +index 1fd891b53c54153c28d636b2679b4a083510ba3c..0bc816407157264bf3e736da678535d08b4d85f2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -745,14 +745,15 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -782,14 +782,15 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return false; } final CraftEntity other = (CraftEntity) obj; diff --git a/patches/server-remapped/0224-Configurable-Alternative-LootPool-Luck-Formula.patch b/patches/server/0207-Configurable-Alternative-LootPool-Luck-Formula.patch similarity index 68% rename from patches/server-remapped/0224-Configurable-Alternative-LootPool-Luck-Formula.patch rename to patches/server/0207-Configurable-Alternative-LootPool-Luck-Formula.patch index 5a10f8c4d8..c5666f4c82 100644 --- a/patches/server-remapped/0224-Configurable-Alternative-LootPool-Luck-Formula.patch +++ b/patches/server/0207-Configurable-Alternative-LootPool-Luck-Formula.patch @@ -53,47 +53,22 @@ index 05a5abb951abe37f30a719cb75376d2d43c0d252..77a03abd59db4a43f6f2d59d4c7ef176 + } } diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java -index ceb5e5405ed20c8de954847bbb269109107a43fc..d99bc0b8a1e9c4749b176a823b879ced9efdd7d6 100644 +index 710a66e9aafe8bd622f9f37789c281aba98d030e..558f43580d976d7bde32779e47e24c9ad388892d 100644 --- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java +++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java -@@ -8,7 +8,6 @@ import java.util.List; - import java.util.function.BiFunction; - import java.util.function.Consumer; - import net.minecraft.util.GsonHelper; --import net.minecraft.util.Mth; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.level.storage.loot.LootContext; - import net.minecraft.world.level.storage.loot.ValidationContext; -@@ -20,8 +19,8 @@ import org.apache.commons.lang3.ArrayUtils; - - public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer { - -- protected final int weight; -- protected final int quality; -+ protected final int weight; public int getWeight() { return weight; } // Paper - OBFHELPER -+ protected final int quality; public int getQuality() { return quality; } // Paper - OBFHELPER - protected final LootItemFunction[] functions; - private final BiFunction compositeFunction; - private final LootPoolEntry entry = new LootPoolSingletonContainer.EntryBase() { -@@ -152,11 +151,38 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer - - public abstract class EntryBase implements LootPoolEntry { - -- protected EntryBase() {} -+ protected EntryBase() { -+ } - +@@ -113,9 +113,35 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer + protected abstract class EntryBase implements LootPoolEntry { @Override public int getWeight(float luck) { -- return Math.max(Mth.floor((float) LootPoolSingletonContainer.this.weight + (float) LootPoolSingletonContainer.this.quality * luck), 0); +- return Math.max(Mth.floor((float)LootPoolSingletonContainer.this.weight + (float)LootPoolSingletonContainer.this.quality * luck), 0); + // Paper start - Offer an alternative loot formula to refactor how luck bonus applies + // SEE: https://luckformula.emc.gs for details and data -+ if (lastLuck != null && lastLuck == luck) { ++ if (LootPoolSingletonContainer.this.lastLuck != null && LootPoolSingletonContainer.this.lastLuck == luck) { + return lastWeight; + } + // This is vanilla -+ float qualityModifer = (float) getQuality() * luck; -+ double baseWeight = (getWeight() + qualityModifer); ++ float qualityModifer = (float) LootPoolSingletonContainer.this.quality * luck; ++ double baseWeight = (LootPoolSingletonContainer.this.weight + qualityModifer); + if (com.destroystokyo.paper.PaperConfig.useAlternativeLuckFormula) { + // Random boost to avoid losing precision in the final int cast on return + final int weightBoost = 100; @@ -107,12 +82,14 @@ index ceb5e5405ed20c8de954847bbb269109107a43fc..d99bc0b8a1e9c4749b176a823b879ced + // =B2 - (C2 *($B$7/100)) + baseWeight = Math.ceil(baseWeight - (impacted * luckModifier)); + } -+ lastLuck = luck; -+ lastWeight = (int) Math.max(0, Math.floor(baseWeight)); ++ LootPoolSingletonContainer.this.lastLuck = luck; ++ LootPoolSingletonContainer.this.lastWeight = (int) Math.max(Math.floor(baseWeight), 0); + return lastWeight; } } + private Float lastLuck = null; + private int lastWeight = 0; + // Paper end - } + + @FunctionalInterface + protected interface EntryConstructor { diff --git a/patches/server-remapped/0225-Print-Error-details-when-failing-to-save-player-data.patch b/patches/server/0208-Print-Error-details-when-failing-to-save-player-data.patch similarity index 72% rename from patches/server-remapped/0225-Print-Error-details-when-failing-to-save-player-data.patch rename to patches/server/0208-Print-Error-details-when-failing-to-save-player-data.patch index 368773ef81..eed7562471 100644 --- a/patches/server-remapped/0225-Print-Error-details-when-failing-to-save-player-data.patch +++ b/patches/server/0208-Print-Error-details-when-failing-to-save-player-data.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Print Error details when failing to save player data diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java -index 60fe01e824e4657d2601797d7858d5de339ab255..5b2a558d4d357d0de033ec2d7a9b4686f202c903 100644 +index 7b367e273c2a6869f8d8929c24ee45efdf6d4b1e..6727468946ea5f60bd80549f827a7c2b9a42b98b 100644 --- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java @@ -43,7 +43,7 @@ public class PlayerDataStorage { Util.safeReplaceFile(file1, file, file2); } catch (Exception exception) { -- PlayerDataStorage.LOGGER.warn("Failed to save player data for {}", entityhuman.getName().getString()); -+ PlayerDataStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getScoreboardName(), exception); // Paper +- PlayerDataStorage.LOGGER.warn("Failed to save player data for {}", player.getName().getString()); ++ PlayerDataStorage.LOGGER.warn("Failed to save player data for {}", player.getScoreboardName(), exception); // Paper } } diff --git a/patches/server-remapped/0226-Make-shield-blocking-delay-configurable.patch b/patches/server/0209-Make-shield-blocking-delay-configurable.patch similarity index 78% rename from patches/server-remapped/0226-Make-shield-blocking-delay-configurable.patch rename to patches/server/0209-Make-shield-blocking-delay-configurable.patch index 9472536ee6..44cc55e1d5 100644 --- a/patches/server-remapped/0226-Make-shield-blocking-delay-configurable.patch +++ b/patches/server/0209-Make-shield-blocking-delay-configurable.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make shield blocking delay configurable diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec..3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77 100644 +index a0a846a2e60bdc17537bd697137f65321c1a61d8..e1110274a9f6b8f7007537732ec8eff7e72040ee 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -369,4 +369,9 @@ public class PaperWorldConfig { +@@ -363,4 +363,9 @@ public class PaperWorldConfig { disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); } @@ -19,10 +19,10 @@ index e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec..3e4bd1d6718d3ad2498fe9bd72eaac45 + } } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 8b0d1f4fbc43a6f37a5f9c453b5dd142a4f69745..af2e81137d9c686f8d94a1d0d7241619fa1f352c 100644 +index 28de49c8b5771491b168bba26e6033669c48e3c9..a3af689df12852ac47bd658f28c9f5b9991d3301 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3308,7 +3308,7 @@ public abstract class LivingEntity extends Entity { +@@ -3665,12 +3665,24 @@ public abstract class LivingEntity extends Entity { if (this.isUsingItem() && !this.useItem.isEmpty()) { Item item = this.useItem.getItem(); @@ -31,10 +31,8 @@ index 8b0d1f4fbc43a6f37a5f9c453b5dd142a4f69745..af2e81137d9c686f8d94a1d0d7241619 } else { return false; } -@@ -3587,4 +3587,15 @@ public abstract class LivingEntity extends Entity { - public void broadcastBreakEvent(InteractionHand hand) { - this.broadcastBreakEvent(hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); } + + // Paper start + public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; + @@ -46,12 +44,15 @@ index 8b0d1f4fbc43a6f37a5f9c453b5dd142a4f69745..af2e81137d9c686f8d94a1d0d7241619 + this.shieldBlockingDelay = shieldBlockingDelay; + } + // Paper end - } ++ + public boolean isSuppressingSlidingDownLadder() { + return this.isShiftKeyDown(); + } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 006f4c71bbcda61b55815e7ceab91731ab062da0..663887d9aecc2823fe7d02a9b108a291cd27102c 100644 +index 4e9565def5a28a7391f8f541d066c2981d0bbc92..dea64f96139fbf4e1ff860b75f2005169a55c395 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -699,5 +699,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -707,5 +707,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { public void setArrowsStuck(int arrows) { getHandle().setArrowCount(arrows); } diff --git a/patches/server/0210-Improve-EntityShootBowEvent.patch b/patches/server/0210-Improve-EntityShootBowEvent.patch new file mode 100644 index 0000000000..fa63c641cd --- /dev/null +++ b/patches/server/0210-Improve-EntityShootBowEvent.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 15 Jun 2013 19:51:17 -0400 +Subject: [PATCH] Improve EntityShootBowEvent + +Adds missing call to Illagers and also adds Arrow ItemStack to skeltons + +diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +index d7bca8fa71e325ba1967537d4102ccb207c4d717..3d8f3e22223e4effeaf52cb18c14c60276d4689c 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -196,7 +196,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + + entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level.getDifficulty().getId() * 4)); + // CraftBukkit start +- org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), null, entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getPickupItem(), entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper + if (event.isCancelled()) { + event.getProjectile().remove(); + return; +diff --git a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +index ff38ad2ac16ff49a290976e392175e96fa986925..c9fa01b910de7ecb494d3000afebea9a2bd1276a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +@@ -196,8 +196,18 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { + double d3 = Math.sqrt(d0 * d0 + d2 * d2); + + entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level.getDifficulty().getId() * 4)); ++ // Paper start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getPickupItem(), entityarrow, target.getUsedItemHand(), 0.8F, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ this.level.addFreshEntity(entityarrow); ++ } + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level.addFreshEntity(entityarrow); ++ // Paper end + } + + @Override +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 71f0de893fe0243cc226fd36685f2a3fba02575f..988986d549dae93cfcb8147126c84f263efe3452 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -586,7 +586,7 @@ public abstract class AbstractArrow extends Projectile { + } + } + +- protected abstract ItemStack getPickupItem(); ++ public abstract ItemStack getPickupItem(); // Paper - protected -> public + + @Override + protected Entity.MovementEmission getMovementEmission() { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Arrow.java b/src/main/java/net/minecraft/world/entity/projectile/Arrow.java +index 1b71df52df1e1d408d2cdf5bef5fbea95fdced80..c0a3bfde24ef5e4b9c1bb1c0b8fbffdde3604513 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Arrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Arrow.java +@@ -244,7 +244,7 @@ public class Arrow extends AbstractArrow { + } + + @Override +- protected ItemStack getPickupItem() { ++ public ItemStack getPickupItem() { // Paper - protected -> public + if (this.effects.isEmpty() && this.potion == Potions.EMPTY) { + return new ItemStack(Items.ARROW); + } else { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/SpectralArrow.java b/src/main/java/net/minecraft/world/entity/projectile/SpectralArrow.java +index 4f62f72d125504602d4b0278119247d36d58b3c9..f6081e0fdf71d6b2b80c94f2ffd3395c08fb84a7 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/SpectralArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/SpectralArrow.java +@@ -36,7 +36,7 @@ public class SpectralArrow extends AbstractArrow { + } + + @Override +- protected ItemStack getPickupItem() { ++ public ItemStack getPickupItem() { // Paper - protected -> public + return new ItemStack(Items.SPECTRAL_ARROW); + } + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java +index 04c6c3bf372186182b91a03e11dba0495357393d..227cb0834a075cbe2db136bf6dc9820d2a04c458 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java +@@ -98,7 +98,7 @@ public class ThrownTrident extends AbstractArrow { + } + + @Override +- protected ItemStack getPickupItem() { ++ public ItemStack getPickupItem() { // Paper - protected -> public + return this.tridentItem.copy(); + } + diff --git a/patches/server-remapped/0228-PlayerReadyArrowEvent.patch b/patches/server/0211-PlayerReadyArrowEvent.patch similarity index 88% rename from patches/server-remapped/0228-PlayerReadyArrowEvent.patch rename to patches/server/0211-PlayerReadyArrowEvent.patch index 1250005dcb..12d94370eb 100644 --- a/patches/server-remapped/0228-PlayerReadyArrowEvent.patch +++ b/patches/server/0211-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 552920f59aae9de2cad3edcdc8c48a91dff49093..b88d8f2c377322290002e84e217f3f2f6e4e71e8 100644 +index a3f719d9dc63af9decc54a789f04595bb2d55710..a4bb172ed720869578575562738521e99a53acca 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -2139,6 +2139,17 @@ public abstract class Player extends LivingEntity { +@@ -2186,6 +2186,17 @@ public abstract class Player extends LivingEntity { return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING); } @@ -28,7 +28,7 @@ index 552920f59aae9de2cad3edcdc8c48a91dff49093..b88d8f2c377322290002e84e217f3f2f @Override public ItemStack getProjectile(ItemStack stack) { if (!(stack.getItem() instanceof ProjectileWeaponItem)) { -@@ -2155,7 +2166,7 @@ public abstract class Player extends LivingEntity { +@@ -2202,7 +2213,7 @@ public abstract class Player extends LivingEntity { for (int i = 0; i < this.inventory.getContainerSize(); ++i) { ItemStack itemstack2 = this.inventory.getItem(i); diff --git a/patches/server-remapped/0229-Implement-EntityKnockbackByEntityEvent.patch b/patches/server/0212-Implement-EntityKnockbackByEntityEvent.patch similarity index 53% rename from patches/server-remapped/0229-Implement-EntityKnockbackByEntityEvent.patch rename to patches/server/0212-Implement-EntityKnockbackByEntityEvent.patch index 79e858a274..e2301e4e1b 100644 --- a/patches/server-remapped/0229-Implement-EntityKnockbackByEntityEvent.patch +++ b/patches/server/0212-Implement-EntityKnockbackByEntityEvent.patch @@ -6,50 +6,49 @@ Subject: [PATCH] Implement EntityKnockbackByEntityEvent This event is called when an entity receives knockback by another entity. diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index af2e81137d9c686f8d94a1d0d7241619fa1f352c..04489a915d11ba970a5188a5a913432ab4ef9faa 100644 +index a3af689df12852ac47bd658f28c9f5b9991d3301..acf6f04fa229fb0850217ff3d50bf3b8c16cafdf 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1336,7 +1336,7 @@ public abstract class LivingEntity extends Entity { +@@ -1437,7 +1437,7 @@ public abstract class LivingEntity extends Entity { } - this.hurtDir = (float) (Mth.atan2(d1, d0) * 57.2957763671875D - (double) this.yRot); -- this.knockback(0.4F, d0, d1); -+ this.doKnockback(0.4F, d0, d1, entity1); // Paper + this.hurtDir = (float) (Mth.atan2(d1, d0) * 57.2957763671875D - (double) this.getYRot()); +- this.knockback(0.4000000059604645D, d0, d1); ++ this.knockback(0.4000000059604645D, d0, d1, entity1); } else { this.hurtDir = (float) ((int) (Math.random() * 2.0D) * 180); } -@@ -1384,7 +1384,7 @@ public abstract class LivingEntity extends Entity { +@@ -1485,7 +1485,7 @@ public abstract class LivingEntity extends Entity { } protected void blockedByShield(LivingEntity target) { -- target.knockback(0.5F, target.getX() - this.getX(), target.getZ() - this.getZ()); -+ target.doKnockback(0.5F, target.getX() - this.getX(), target.getZ() - this.getZ(), this); // Paper +- target.knockback(0.5D, target.getX() - this.getX(), target.getZ() - this.getZ()); ++ target.knockback(0.5D, target.getX() - this.getX(), target.getZ() - this.getZ(), this); } private boolean checkTotemDeathProtection(DamageSource source) { -@@ -1627,6 +1627,11 @@ public abstract class LivingEntity extends Entity { +@@ -1733,6 +1733,11 @@ public abstract class LivingEntity extends Entity { } - public void knockback(float f, double d0, double d1) { + public void knockback(double strength, double x, double z) { + // Paper start - add knockbacking entity parameter -+ this.doKnockback(f, d0, d1, null); ++ this.knockback(strength, x, z, null); + } -+ public void doKnockback(float f, double d0, double d1, Entity knockingBackEntity) { ++ public void knockback(double strength, double x, double z, Entity knockingBackEntity) { + // Paper end - add knockbacking entity parameter - f = (float) ((double) f * (1.0D - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE))); - if (f > 0.0F) { + strength *= 1.0D - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); + if (strength > 0.0D) { this.hasImpulse = true; -@@ -1634,6 +1639,16 @@ public abstract class LivingEntity extends Entity { - Vec3 vec3d1 = (new Vec3(d0, 0.0D, d1)).normalize().scale((double) f); +@@ -1740,6 +1745,15 @@ public abstract class LivingEntity extends Entity { + Vec3 vec3d1 = (new Vec3(x, 0.0D, z)).normalize().scale(strength); - this.setDeltaMovement(vec3d.x / 2.0D - vec3d1.x, this.onGround ? Math.min(0.4D, vec3d.y / 2.0D + (double) f) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); -+ + this.setDeltaMovement(vec3d.x / 2.0D - vec3d1.x, this.onGround ? Math.min(0.4D, vec3d.y / 2.0D + strength) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); + // Paper start - call EntityKnockbackByEntityEvent -+ Vec3 currentMot = this.getDeltaMovement(); -+ org.bukkit.util.Vector delta = new org.bukkit.util.Vector(currentMot.x - vec3d.x, currentMot.y - vec3d.y, currentMot.z - vec3d.z); ++ Vec3 currentMovement = this.getDeltaMovement(); ++ org.bukkit.util.Vector delta = new org.bukkit.util.Vector(currentMovement.x - vec3d.x, currentMovement.y - vec3d.y, currentMovement.z - vec3d.z); + // Restore old velocity to be able to access it in the event + this.setDeltaMovement(vec3d); -+ if (knockingBackEntity == null || new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent((org.bukkit.entity.LivingEntity) getBukkitEntity(), knockingBackEntity.getBukkitEntity(), f, delta).callEvent()) { ++ if (knockingBackEntity == null || new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent((org.bukkit.entity.LivingEntity) getBukkitEntity(), knockingBackEntity.getBukkitEntity(), (float) strength, delta).callEvent()) { + this.setDeltaMovement(vec3d.x + delta.getX(), vec3d.y + delta.getY(), vec3d.z + delta.getZ()); + } + // Paper end @@ -57,37 +56,37 @@ index af2e81137d9c686f8d94a1d0d7241619fa1f352c..04489a915d11ba970a5188a5a913432a } diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index eb35c69bb777ba8d83b2304ff9f862512643e745..f3690ea49cf90c816b8b3554b47d6f2d9dfbe016 100644 +index 2ed756c73b0cfddb559126d85316f37c3f958c0c..8451baff82cb7ec7615ab50a409724897ccf4d95 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -1566,7 +1566,7 @@ public abstract class Mob extends LivingEntity { +@@ -1532,7 +1532,7 @@ public abstract class Mob extends LivingEntity { if (flag) { if (f1 > 0.0F && target instanceof LivingEntity) { -- ((LivingEntity) target).knockback(f1 * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F))); -+ ((LivingEntity) target).doKnockback(f1 * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)), this); // Paper +- ((LivingEntity) target).knockback((double) (f1 * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ ((LivingEntity) target).knockback((double) (f1 * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this); // Paper this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); } 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 b88d8f2c377322290002e84e217f3f2f6e4e71e8..5e6a86b0b8999a5c47d2f9bdd9857ab5f0772033 100644 +index a4bb172ed720869578575562738521e99a53acca..0d6e024208182d5779be3d84cff193ce904ad541 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1174,7 +1174,7 @@ public abstract class Player extends LivingEntity { +@@ -1234,7 +1234,7 @@ public abstract class Player extends LivingEntity { if (flag5) { if (i > 0) { if (target instanceof LivingEntity) { -- ((LivingEntity) target).knockback((float) i * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F))); -+ ((LivingEntity) target).doKnockback((float) i * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)), this); // Paper +- ((LivingEntity) target).knockback((double) ((float) i * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ ((LivingEntity) target).knockback((double) ((float) i * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this); // Paper } else { - target.push((double) (-Mth.sin(this.yRot * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.yRot * 0.017453292F) * (float) i * 0.5F)); + target.push((double) (-Mth.sin(this.getYRot() * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.getYRot() * 0.017453292F) * (float) i * 0.5F)); } -@@ -1198,7 +1198,7 @@ public abstract class Player extends LivingEntity { +@@ -1258,7 +1258,7 @@ public abstract class Player extends LivingEntity { if (entityliving != this && entityliving != target && !this.isAlliedTo(entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) { // CraftBukkit start - Only apply knockback if the damage hits if (entityliving.hurt(DamageSource.playerAttack(this).sweep(), f4)) { -- entityliving.knockback(0.4F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F))); -+ entityliving.doKnockback(0.4F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)), this); // Paper +- entityliving.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ entityliving.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this); // Paper } // CraftBukkit end } diff --git a/patches/server-remapped/0230-Expand-Explosions-API.patch b/patches/server/0213-Expand-Explosions-API.patch similarity index 74% rename from patches/server-remapped/0230-Expand-Explosions-API.patch rename to patches/server/0213-Expand-Explosions-API.patch index 01be1df09c..00de92415e 100644 --- a/patches/server-remapped/0230-Expand-Explosions-API.patch +++ b/patches/server/0213-Expand-Explosions-API.patch @@ -6,14 +6,15 @@ Subject: [PATCH] Expand Explosions API Add Entity as a Source capability, and add more API choices, and on Location. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 2dc9daaeea600fff1f2efddf74b6849fd745a28c..9b5a1c3ab8ffde524e194fdeaa8eaef6b286b57b 100644 +index 058346b89c07d44a5425a61abedcfc440cb9ee21..df6b4f65dd84621b8477b42a504f9e62c633a6b5 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -871,6 +871,11 @@ public class CraftWorld implements World { +@@ -889,6 +889,12 @@ public class CraftWorld implements World { public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) { - return !world.explode(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; + return !this.world.explode(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; } + // Paper start ++ @Override + public boolean createExplosion(Entity source, Location loc, float power, boolean setFire, boolean breakBlocks) { + return !world.explode(source != null ? ((org.bukkit.craftbukkit.entity.CraftEntity) source).getHandle() : null, loc.getX(), loc.getY(), loc.getZ(), power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; + } diff --git a/patches/server/0214-LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/server/0214-LivingEntity-Hand-Raised-Item-Use-API.patch new file mode 100644 index 0000000000..0195a35046 --- /dev/null +++ b/patches/server/0214-LivingEntity-Hand-Raised-Item-Use-API.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 Jun 2018 00:21:28 -0400 +Subject: [PATCH] LivingEntity Hand Raised/Item Use API + +How long an entity has raised hands to charge an attack or use an item + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index dea64f96139fbf4e1ff860b75f2005169a55c395..5194da5a141718390a317d75b31205f951cec7a2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -717,5 +717,30 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setShieldBlockingDelay(int delay) { + getHandle().setShieldBlockingDelay(delay); + } ++ ++ @Override ++ public ItemStack getActiveItem() { ++ return getHandle().getUseItem().asBukkitMirror(); ++ } ++ ++ @Override ++ public int getItemUseRemainingTime() { ++ return getHandle().getUseItemRemainingTicks(); ++ } ++ ++ @Override ++ public int getHandRaisedTime() { ++ return getHandle().getTicksUsingItem(); ++ } ++ ++ @Override ++ public boolean isHandRaised() { ++ return getHandle().isUsingItem(); ++ } ++ ++ @Override ++ public org.bukkit.inventory.EquipmentSlot getHandRaised() { ++ return getHandle().getUsedItemHand() == net.minecraft.world.InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; ++ } + // Paper end + } diff --git a/patches/server-remapped/0232-RangedEntity-API.patch b/patches/server/0215-RangedEntity-API.patch similarity index 89% rename from patches/server-remapped/0232-RangedEntity-API.patch rename to patches/server/0215-RangedEntity-API.patch index 40db6f9590..96a8f6424a 100644 --- a/patches/server-remapped/0232-RangedEntity-API.patch +++ b/patches/server/0215-RangedEntity-API.patch @@ -32,13 +32,13 @@ index 0000000000000000000000000000000000000000..e75e1d0d833c96af139fd955b2585ec2 + } +} diff --git a/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java b/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java -index b3ad4d54eeb1b894c24a5a76e8b12b8d9568cd56..ae10f3933fe78f74995952a6a8acf09ef4e99823 100644 +index 6c3162606ccf799e99d591da33fd649847db54b8..7ff5d0410ac281da20a031e748e8c15f3156d809 100644 --- a/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java +++ b/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java -@@ -4,5 +4,8 @@ import net.minecraft.world.entity.LivingEntity; +@@ -3,5 +3,8 @@ package net.minecraft.world.entity.monster; + import net.minecraft.world.entity.LivingEntity; public interface RangedAttackMob { - - void performRangedAttack(LivingEntity target, float pullProgress); + void performRangedAttack(LivingEntity target, float pullProgress); default void rangedAttack(LivingEntity entityliving, float f) { performRangedAttack(entityliving, f); } // Paper - OBFHELPER + @@ -72,27 +72,20 @@ index 59b866e54e0d7e1dd8815ffa85275e36271113da..bbf7189a0fc9921e7a6007494f91229d public CraftIllusioner(CraftServer server, net.minecraft.world.entity.monster.Illusioner entity) { super(server, entity); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -index 04f716af67939b2dc34875f722816dd1ffdc4966..ed3b8fcc221d6c0789eb92eb4716d640ba0fec9f 100644 +index bda998c9e621bd9bca6642bfa86befed08f4902b..6ad12711a82d7be42ba41c0428779f86536fd900 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.entity.CraftRangedEntity; - import com.google.common.base.Preconditions; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.inventory.CraftInventoryLlama; -@@ -9,7 +10,7 @@ import org.bukkit.entity.Llama; +@@ -9,7 +9,7 @@ import org.bukkit.entity.Llama; import org.bukkit.entity.Llama.Color; import org.bukkit.inventory.LlamaInventory; -public class CraftLlama extends CraftChestedHorse implements Llama { -+public class CraftLlama extends CraftChestedHorse implements Llama, CraftRangedEntity { // Paper ++public class CraftLlama extends CraftChestedHorse implements Llama, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper public CraftLlama(CraftServer server, net.minecraft.world.entity.animal.horse.Llama entity) { super(server, entity); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -index 12bce49fcb164b6311a81024d1749a582ab1be25..c06fea6e0eaf58b8e7441ccf8595d6ca8417526a 100644 +index 27763d1eca832abda76c8b3c22595cbaf9b1fe45..aeda5fc001fe4ce55ee467240b275b6050a29f98 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java @@ -13,7 +13,7 @@ import org.bukkit.entity.EntityType; @@ -105,7 +98,7 @@ index 12bce49fcb164b6311a81024d1749a582ab1be25..c06fea6e0eaf58b8e7441ccf8595d6ca public CraftPiglin(CraftServer server, net.minecraft.world.entity.monster.piglin.Piglin entity) { super(server, entity); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -index fc86b8ecc349ed59c9eb6de03086d4027cb4e08d..949260d6750e71f148229955c94bcbaad9d54a2d 100644 +index 06786fba1fef36e8fc3d0f5650160123f728a6d1..beea227855f0b978e655efc298024120df8f4945 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java @@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; @@ -131,7 +124,7 @@ index 4cd3dfd3466f384aab06dacd388e8053b045b046..b2d3244cca4d9d108159f3537d8a9aac public CraftSkeleton(CraftServer server, AbstractSkeleton entity) { super(server, entity); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -index fcce4aa391d0c448531815e99e0e32c84203c1b8..a7164a921f479c928049d4e812eab50567e96fc2 100644 +index 6a82d567d96a42bfea0e38afb4e8de13eb3ad5a2..659e2959c5330e4764ea1edc7f8de9f464f9ff52 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java @@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; @@ -157,7 +150,7 @@ index 60e00e539d214eb8854a53364c92c3cf55ca1062..d4eeb071dbbfca3ecea256228853bcb5 super(server, entity); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -index 728a8c0f5781f33bdb096aefb569e9509dda8c89..fdcd680b972da54f9cdb41dff5563e42bd12d8e3 100644 +index 54a7defa85542765f3dd0d7ccb770dafd9c7d484..640b0860fbe3412da32d03187e6f355ba8f099ea 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java @@ -7,7 +7,7 @@ import org.bukkit.craftbukkit.boss.CraftBossBar; diff --git a/patches/server-remapped/0233-Add-config-to-disable-ender-dragon-legacy-check.patch b/patches/server/0216-Add-config-to-disable-ender-dragon-legacy-check.patch similarity index 59% rename from patches/server-remapped/0233-Add-config-to-disable-ender-dragon-legacy-check.patch rename to patches/server/0216-Add-config-to-disable-ender-dragon-legacy-check.patch index 1ba8695871..76ede6a09a 100644 --- a/patches/server-remapped/0233-Add-config-to-disable-ender-dragon-legacy-check.patch +++ b/patches/server/0216-Add-config-to-disable-ender-dragon-legacy-check.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add config to disable ender dragon legacy check diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77..4813f62d1e382d5ac6971b2244df3f13c80d1950 100644 +index e1110274a9f6b8f7007537732ec8eff7e72040ee..8f8a3ea51823a9cfba985efeb7e320ae42e0da8a 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -374,4 +374,9 @@ public class PaperWorldConfig { +@@ -368,4 +368,9 @@ public class PaperWorldConfig { private void shieldBlockingDelay() { shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); } @@ -19,15 +19,17 @@ index 3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77..4813f62d1e382d5ac6971b2244df3f13 + } } diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 2386ffeec60851ba192b89bc6fd7ffff9c56aff5..4b18931225ef60dbcffd7fcc20d0e9ce62348a07 100644 +index 758af2c2d66073aeaee766adb672c465d2993eab..711be01abe9d47bdc9bfe8b09a2719d666b986fb 100644 --- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -73,7 +73,7 @@ public class EndDragonFight { - private boolean dragonKilled; - private boolean previouslyKilled; - public UUID dragonUUID; -- private boolean needsStateScanning; -+ private boolean needsStateScanning; private void setScanForLegacyFight(boolean scanForLegacyFight) { this.needsStateScanning = scanForLegacyFight; } private boolean scanForLegacyFight() { return this.needsStateScanning; } // Paper - OBFHELPER - public BlockPos portalLocation; - public DragonRespawnAnimation respawnStage; - private int respawnTime; +@@ -84,6 +84,10 @@ public class EndDragonFight { + private List respawnCrystals; + + public EndDragonFight(ServerLevel world, long gatewaysSeed, CompoundTag nbt) { ++ // Paper start ++ this.needsStateScanning = world.paperConfig.scanForLegacyEnderDragon; ++ if (!this.needsStateScanning) this.dragonKilled = true; ++ // Paper end + this.level = world; + if (nbt.contains("NeedsStateScanning")) { + this.needsStateScanning = nbt.getBoolean("NeedsStateScanning"); diff --git a/patches/server-remapped/0234-Implement-World.getEntity-UUID-API.patch b/patches/server/0217-Implement-World.getEntity-UUID-API.patch similarity index 84% rename from patches/server-remapped/0234-Implement-World.getEntity-UUID-API.patch rename to patches/server/0217-Implement-World.getEntity-UUID-API.patch index 6bcd99431d..1024259266 100644 --- a/patches/server-remapped/0234-Implement-World.getEntity-UUID-API.patch +++ b/patches/server/0217-Implement-World.getEntity-UUID-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Implement World.getEntity(UUID) API diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 9b5a1c3ab8ffde524e194fdeaa8eaef6b286b57b..3a3466cd9bbd34dbc0b79567f5579e84a81d6009 100644 +index df6b4f65dd84621b8477b42a504f9e62c633a6b5..e7f5cd35869790baf616e6c65f49169aa5349e89 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1286,6 +1286,15 @@ public class CraftWorld implements World { +@@ -1295,6 +1295,15 @@ public class CraftWorld implements World { return list; } diff --git a/patches/server-remapped/0235-InventoryCloseEvent-Reason-API.patch b/patches/server/0218-InventoryCloseEvent-Reason-API.patch similarity index 71% rename from patches/server-remapped/0235-InventoryCloseEvent-Reason-API.patch rename to patches/server/0218-InventoryCloseEvent-Reason-API.patch index c1daa66bf3..b7296c49de 100644 --- a/patches/server-remapped/0235-InventoryCloseEvent-Reason-API.patch +++ b/patches/server/0218-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/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 5110f2c70d96284e8e7592b3d89266b867b9a466..ea1b15495481157912140bf5de9bf4a949c16910 100644 +index cf074ef0cb01bc2cbd8c529e7233ceb9443f764d..ca0907601c6262d27c3406cea806a40421bc4ace 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1119,7 +1119,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1055,7 +1055,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl for (BlockEntity tileentity : chunk.getBlockEntities().values()) { if (tileentity instanceof net.minecraft.world.Container) { for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((net.minecraft.world.Container) tileentity).getViewers())) { @@ -19,20 +19,20 @@ index 5110f2c70d96284e8e7592b3d89266b867b9a466..ea1b15495481157912140bf5de9bf4a9 } } } -@@ -1177,7 +1177,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - // Spigot Start - if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder) { - for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) { -- h.closeInventory(); -+ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper +@@ -1937,7 +1937,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // Spigot Start + if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder) { + for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) { +- h.closeInventory(); ++ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper + } } - } - // Spigot End + // 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 0fa977a31cf945b74f3a046b6be302b10f494ad1..1441a461e749dbfa303095f6b51d655c45f68ce0 100644 +index 7159a433e9a264d2151dddc84a74689d0bc7635b..171500918c8ee248689909ae97230eb18adc33e5 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -544,7 +544,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -602,7 +602,7 @@ public class ServerPlayer extends Player { } // Paper end if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { @@ -41,7 +41,7 @@ index 0fa977a31cf945b74f3a046b6be302b10f494ad1..1441a461e749dbfa303095f6b51d655c this.containerMenu = this.inventoryMenu; } -@@ -717,7 +717,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -754,7 +754,7 @@ public class ServerPlayer extends Player { // SPIGOT-943 - only call if they have an inventory open if (this.containerMenu != this.inventoryMenu) { @@ -50,7 +50,7 @@ index 0fa977a31cf945b74f3a046b6be302b10f494ad1..1441a461e749dbfa303095f6b51d655c } net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure -@@ -1290,7 +1290,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1341,7 +1341,7 @@ public class ServerPlayer extends Player { return OptionalInt.empty(); } else { if (this.containerMenu != this.inventoryMenu) { @@ -59,7 +59,7 @@ index 0fa977a31cf945b74f3a046b6be302b10f494ad1..1441a461e749dbfa303095f6b51d655c } this.nextContainerCounter(); -@@ -1350,7 +1350,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1401,7 +1401,7 @@ public class ServerPlayer extends Player { } // CraftBukkit end if (this.containerMenu != this.inventoryMenu) { @@ -68,22 +68,23 @@ index 0fa977a31cf945b74f3a046b6be302b10f494ad1..1441a461e749dbfa303095f6b51d655c } // this.nextContainerCounter(); // CraftBukkit - moved up -@@ -1414,7 +1414,12 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1430,7 +1430,13 @@ public class ServerPlayer extends Player { @Override public void closeContainer() { - CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit + // Paper start -+ closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); + } -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ @Override ++ public void closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { + CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit + // Paper end this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); this.doCloseContainer(); } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index fb36aa08cd2fbe3f7262dccb8cf0f7cae55aea9c..d322e99170b3cb6594efc824a879ab9a538ea1eb 100644 +index 35a00a622ff0c3582e08dbbefb1d34a84e590a81..ce88f701f296e67afc67d7e3882406e86147408e 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -188,6 +188,7 @@ import org.bukkit.event.inventory.ClickType; @@ -94,7 +95,7 @@ index fb36aa08cd2fbe3f7262dccb8cf0f7cae55aea9c..d322e99170b3cb6594efc824a879ab9a import org.bukkit.event.inventory.InventoryCreativeEvent; import org.bukkit.event.inventory.InventoryType.SlotType; import org.bukkit.event.inventory.SmithItemEvent; -@@ -2309,10 +2310,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2332,10 +2333,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @Override public void handleContainerClose(ServerboundContainerClosePacket packet) { @@ -113,10 +114,10 @@ index fb36aa08cd2fbe3f7262dccb8cf0f7cae55aea9c..d322e99170b3cb6594efc824a879ab9a this.player.doCloseContainer(); } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index ae60b233c4d56a4964b388f96e9cc66410774e8d..51b1ce465d23b971f7e08a3175319a33183d0398 100644 +index 429e6c7f9a5e5355e26deeae1e89ffea7439cd96..7c5a75fb34640bb4e7ef839412dbb30b0d0fc8e8 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -490,7 +490,7 @@ public abstract class PlayerList { +@@ -494,7 +494,7 @@ public abstract class PlayerList { // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it // See SPIGOT-5799, SPIGOT-6145 if (entityplayer.containerMenu != entityplayer.inventoryMenu) { @@ -124,12 +125,12 @@ index ae60b233c4d56a4964b388f96e9cc66410774e8d..51b1ce465d23b971f7e08a3175319a33 + entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper } - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(this.cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); 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 5e6a86b0b8999a5c47d2f9bdd9857ab5f0772033..709e930eef7bae5694238ed8c4d0ef59316bb715 100644 +index 0d6e024208182d5779be3d84cff193ce904ad541..e0e33dd92b686939f622f0a7da0d5a971f43d0d6 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -249,7 +249,7 @@ public abstract class Player extends LivingEntity { +@@ -264,7 +264,7 @@ public abstract class Player extends LivingEntity { this.updateIsUnderwater(); super.tick(); if (!this.level.isClientSide && this.containerMenu != null && !this.containerMenu.stillValid(this)) { @@ -138,12 +139,12 @@ index 5e6a86b0b8999a5c47d2f9bdd9857ab5f0772033..709e930eef7bae5694238ed8c4d0ef59 this.containerMenu = this.inventoryMenu; } -@@ -444,6 +444,13 @@ public abstract class Player extends LivingEntity { - return 20; +@@ -487,6 +487,13 @@ public abstract class Player extends LivingEntity { + } + // Paper start - unused code, but to keep signatures aligned -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ public void closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { + closeContainer(); + this.containerMenu = this.inventoryMenu; + } @@ -153,26 +154,29 @@ index 5e6a86b0b8999a5c47d2f9bdd9857ab5f0772033..709e930eef7bae5694238ed8c4d0ef59 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 4aec1c2b26d48cb5bea3dfb9e183526763bdb98f..a73c6ddd6bf66cc21ae5b25daacdece8cbfeeeac 100644 +index 7f7322b5174a7580675b0607b0f282f7bf75a3e2..662a4cec1d292428f06ec5a1f862a1f8d8834c09 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -374,7 +374,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - if (((ServerPlayer) getHandle()).connection == null) return; - if (getHandle().containerMenu != getHandle().inventoryMenu) { +@@ -373,7 +373,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 -- ((ServerPlayer) getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(getHandle().containerMenu.containerId)); -+ ((ServerPlayer) getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(getHandle().containerMenu.containerId), org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper +- ((ServerPlayer) this.getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(this.getHandle().containerMenu.containerId)); ++ ((ServerPlayer) this.getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(this.getHandle().containerMenu.containerId), org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper } - ServerPlayer player = (ServerPlayer) getHandle(); + ServerPlayer player = (ServerPlayer) this.getHandle(); AbstractContainerMenu container; -@@ -444,8 +444,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -443,8 +443,16 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @Override public void closeInventory() { -- getHandle().closeContainer(); +- this.getHandle().closeContainer(); ++ this.getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); ++ getHandle().closeContainer(); + // Paper start + getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); } ++ @Override + public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { + getHandle().closeContainer(reason); + } @@ -181,23 +185,23 @@ index 4aec1c2b26d48cb5bea3dfb9e183526763bdb98f..a73c6ddd6bf66cc21ae5b25daacdece8 @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 46338fe5693003698de9c7b37a860c3481e06233..c7f66dddf0a0850ca4048dd47cd2ded114caa07e 100644 +index 8df1894df3583840412ccc7ccdc4b23db6dd6265..f8155d7edb4e13c2ec5ed832231f02ee6eff3f35 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -895,7 +895,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -908,7 +908,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Close any foreign inventory - if (getHandle().containerMenu != getHandle().inventoryMenu) { -- getHandle().closeContainer(); -+ getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper + if (this.getHandle().containerMenu != this.getHandle().inventoryMenu) { +- this.getHandle().closeContainer(); ++ this.getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper } // 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 5e8ff18f98b03741ccbb927f87499ae36d775a86..c2f58b95db41b2205fbf2728c6a99419c6a63dfa 100644 +index 56900b5810db623a49559ad218a5385c110bf479..375e9e45331d5be237c67f11af94c6998409418b 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1175,7 +1175,7 @@ public class CraftEventFactory { +@@ -1154,7 +1154,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 @@ -206,7 +210,7 @@ index 5e8ff18f98b03741ccbb927f87499ae36d775a86..c2f58b95db41b2205fbf2728c6a99419 } CraftServer server = player.level.getCraftServer(); -@@ -1341,8 +1341,18 @@ public class CraftEventFactory { +@@ -1320,8 +1320,18 @@ public class CraftEventFactory { return event; } From a968aefd32cc38c3646e44a044ec2df864f83303 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sat, 12 Jun 2021 14:31:35 -0700 Subject: [PATCH 052/226] more patches --- build-data/mappings-patch.tiny | 4 +- ...19-Allow-setting-the-vex-s-summoner.patch} | 0 .../0120-Entity-getChunk-API.patch} | 9 +- ...d-an-asterisk-to-legacy-API-plugins.patch} | 0 .../0122-EnderDragon-Events.patch} | 0 .../0123-PlayerElytraBoostEvent.patch} | 0 .../0124-PlayerLaunchProjectileEvent.patch} | 0 ...nilla-entity-warnings-for-duplicates.patch | 2 + ...ies-option-to-debug-dupe-uuid-issues.patch | 2 + .../0245-PlayerElytraBoostEvent.patch | 31 -- ...9-Vanished-players-don-t-have-rights.patch | 194 ---------- ...295-Allow-setting-the-vex-s-summoner.patch | 33 -- .../0386-PlayerLaunchProjectileEvent.patch | 351 ------------------ .../0219-Vex-get-setSummoner-API.patch} | 29 +- ...ventory-when-cancelling-PlayerInter.patch} | 16 +- ...-if-stack-size-above-max-stack-size.patch} | 4 +- ...22-Use-asynchronous-Log4j-2-loggers.patch} | 20 +- ...more-information-to-Entity.toString.patch} | 6 +- ...tMagicNumbers.isSupportedApiVersion.patch} | 2 +- .../0225-EnderDragon-Events.patch} | 47 +-- .../server/0226-PlayerElytraBoostEvent.patch | 33 ++ .../0227-PlayerLaunchProjectileEvent.patch | 276 ++++++++++++++ ...0228-Improve-BlockPosition-inlining.patch} | 24 +- ...timize-IntIdentityHashBiMiap-nextId.patch} | 41 +- ...-armor-stands-from-doing-entity-loo.patch} | 22 +- ...1-Vanished-players-don-t-have-rights.patch | 119 ++++++ 26 files changed, 535 insertions(+), 730 deletions(-) rename patches/{api-unmapped/0155-Allow-setting-the-vex-s-summoner.patch => api/0119-Allow-setting-the-vex-s-summoner.patch} (100%) rename patches/{api-unmapped/0118-Entity-getChunk-API.patch => api/0120-Entity-getChunk-API.patch} (79%) rename patches/{api-unmapped/0119-Add-an-asterisk-to-legacy-API-plugins.patch => api/0121-Add-an-asterisk-to-legacy-API-plugins.patch} (100%) rename patches/{api-unmapped/0120-EnderDragon-Events.patch => api/0122-EnderDragon-Events.patch} (100%) rename patches/{api-unmapped/0122-PlayerElytraBoostEvent.patch => api/0123-PlayerElytraBoostEvent.patch} (100%) rename patches/{api-unmapped/0121-PlayerLaunchProjectileEvent.patch => api/0124-PlayerLaunchProjectileEvent.patch} (100%) rename patches/{server-remapped => removed/1.17}/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch (97%) rename patches/{server-remapped => removed/1.17}/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch (99%) delete mode 100644 patches/server-remapped/0245-PlayerElytraBoostEvent.patch delete mode 100644 patches/server-remapped/0249-Vanished-players-don-t-have-rights.patch delete mode 100644 patches/server-remapped/0295-Allow-setting-the-vex-s-summoner.patch delete mode 100644 patches/server-remapped/0386-PlayerLaunchProjectileEvent.patch rename patches/{server-remapped/0236-Vex-getSummoner-API.patch => server/0219-Vex-get-setSummoner-API.patch} (51%) rename patches/{server-remapped/0237-Refresh-player-inventory-when-cancelling-PlayerInter.patch => server/0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch} (66%) rename patches/{server-remapped/0240-Avoid-item-merge-if-stack-size-above-max-stack-size.patch => server/0221-Avoid-item-merge-if-stack-size-above-max-stack-size.patch} (86%) rename patches/{server-remapped/0241-Use-asynchronous-Log4j-2-loggers.patch => server/0222-Use-asynchronous-Log4j-2-loggers.patch} (73%) rename patches/{server-remapped/0242-add-more-information-to-Entity.toString.patch => server/0223-add-more-information-to-Entity.toString.patch} (58%) rename patches/{server-remapped/0387-Add-CraftMagicNumbers.isSupportedApiVersion.patch => server/0224-Add-CraftMagicNumbers.isSupportedApiVersion.patch} (90%) rename patches/{server-remapped/0244-EnderDragon-Events.patch => server/0225-EnderDragon-Events.patch} (61%) create mode 100644 patches/server/0226-PlayerElytraBoostEvent.patch create mode 100644 patches/server/0227-PlayerLaunchProjectileEvent.patch rename patches/{server-remapped/0246-Improve-BlockPosition-inlining.patch => server/0228-Improve-BlockPosition-inlining.patch} (67%) rename patches/{server-remapped/0247-Optimize-RegistryID.c.patch => server/0229-Optimize-IntIdentityHashBiMiap-nextId.patch} (57%) rename patches/{server-remapped/0248-Option-to-prevent-armor-stands-from-doing-entity-loo.patch => server/0230-Option-to-prevent-armor-stands-from-doing-entity-loo.patch} (69%) create mode 100644 patches/server/0231-Vanished-players-don-t-have-rights.patch diff --git a/build-data/mappings-patch.tiny b/build-data/mappings-patch.tiny index b15b9e635c..b592b1991b 100644 --- a/build-data/mappings-patch.tiny +++ b/build-data/mappings-patch.tiny @@ -38,8 +38,8 @@ c net/minecraft/world/entity/projectile/EntityTippedArrow net/minecraft/world/en # CraftBukkit adds a new `a` method which allows passing the Entity parameter # It uses `a` to match the original method (with just 1 param), so this patch makes them match -#c net/minecraft/server/level/WorldServer net/minecraft/server/level/ServerLevel -# m (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/Entity;)V a makeObsidianPlatform +c net/minecraft/server/level/WorldServer net/minecraft/server/level/ServerLevel + m (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/Entity;)V a makeObsidianPlatform # CraftBukkit adds `getMinecraftWorld()` to `GeneratorAccess`, which matches `WorldAccess.getMinecraftWorld()` # But that method in `WorldAccess` is called `getLevel()` in Mojang mappings diff --git a/patches/api-unmapped/0155-Allow-setting-the-vex-s-summoner.patch b/patches/api/0119-Allow-setting-the-vex-s-summoner.patch similarity index 100% rename from patches/api-unmapped/0155-Allow-setting-the-vex-s-summoner.patch rename to patches/api/0119-Allow-setting-the-vex-s-summoner.patch diff --git a/patches/api-unmapped/0118-Entity-getChunk-API.patch b/patches/api/0120-Entity-getChunk-API.patch similarity index 79% rename from patches/api-unmapped/0118-Entity-getChunk-API.patch rename to patches/api/0120-Entity-getChunk-API.patch index 1a598ac537..8de03dab49 100644 --- a/patches/api-unmapped/0118-Entity-getChunk-API.patch +++ b/patches/api/0120-Entity-getChunk-API.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Entity#getChunk API Get the chunk the entity is currently registered to diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index fdc95c87a6020bdcaee5b0b8ab5a996c0e241b33..76c20d84fee011af4f1850d0cab8ac00a69f2b34 100644 +index fdc95c87a6020bdcaee5b0b8ab5a996c0e241b33..ef95afb92f7a6fea77fe483e26ee3cf6d1bdd041 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java @@ -3,6 +3,7 @@ package org.bukkit.entity; @@ -17,7 +17,7 @@ index fdc95c87a6020bdcaee5b0b8ab5a996c0e241b33..76c20d84fee011af4f1850d0cab8ac00 import org.bukkit.EntityEffect; import org.bukkit.Location; import org.bukkit.Nameable; -@@ -672,5 +673,13 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent +@@ -672,5 +673,16 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent * @return True if entity spawned from a mob spawner */ boolean fromMobSpawner(); @@ -28,6 +28,9 @@ index fdc95c87a6020bdcaee5b0b8ab5a996c0e241b33..76c20d84fee011af4f1850d0cab8ac00 + * @return The current, or most recent chunk if the entity is invalid (which may load the chunk) + */ + @NotNull -+ Chunk getChunk(); ++ default Chunk getChunk() { ++ // TODO remove impl here ++ return getLocation().getChunk(); ++ } // Paper end } diff --git a/patches/api-unmapped/0119-Add-an-asterisk-to-legacy-API-plugins.patch b/patches/api/0121-Add-an-asterisk-to-legacy-API-plugins.patch similarity index 100% rename from patches/api-unmapped/0119-Add-an-asterisk-to-legacy-API-plugins.patch rename to patches/api/0121-Add-an-asterisk-to-legacy-API-plugins.patch diff --git a/patches/api-unmapped/0120-EnderDragon-Events.patch b/patches/api/0122-EnderDragon-Events.patch similarity index 100% rename from patches/api-unmapped/0120-EnderDragon-Events.patch rename to patches/api/0122-EnderDragon-Events.patch diff --git a/patches/api-unmapped/0122-PlayerElytraBoostEvent.patch b/patches/api/0123-PlayerElytraBoostEvent.patch similarity index 100% rename from patches/api-unmapped/0122-PlayerElytraBoostEvent.patch rename to patches/api/0123-PlayerElytraBoostEvent.patch diff --git a/patches/api-unmapped/0121-PlayerLaunchProjectileEvent.patch b/patches/api/0124-PlayerLaunchProjectileEvent.patch similarity index 100% rename from patches/api-unmapped/0121-PlayerLaunchProjectileEvent.patch rename to patches/api/0124-PlayerLaunchProjectileEvent.patch diff --git a/patches/server-remapped/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch b/patches/removed/1.17/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch similarity index 97% rename from patches/server-remapped/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch rename to patches/removed/1.17/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch index 4deb8f2bc2..93a070fe0e 100644 --- a/patches/server-remapped/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch +++ b/patches/removed/1.17/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch @@ -7,6 +7,8 @@ These are a critical sign that somethin went wrong, and you've lost some data... We should kind of know about these things you know. +Spigot did not remove the warning in 1.17 + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index ea1b15495481157912140bf5de9bf4a949c16910..914241a57c304fde220bc546261d6e959445772a 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/server-remapped/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/patches/removed/1.17/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch similarity index 99% rename from patches/server-remapped/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch rename to patches/removed/1.17/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch index be88eeb2df..4f79f9fe1b 100644 --- a/patches/server-remapped/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch +++ b/patches/removed/1.17/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch @@ -5,6 +5,8 @@ Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues Add -Ddebug.entities=true to your JVM flags to gain more information +1.17: Needs to be reworked for new entity storage system + diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java index 97d5437df10a6d0124e944404e88650547b7d8a8..083db6c1899b5391231b6d5d5044a334212f148c 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java diff --git a/patches/server-remapped/0245-PlayerElytraBoostEvent.patch b/patches/server-remapped/0245-PlayerElytraBoostEvent.patch deleted file mode 100644 index be2454e01e..0000000000 --- a/patches/server-remapped/0245-PlayerElytraBoostEvent.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:59:59 -0500 -Subject: [PATCH] PlayerElytraBoostEvent - - -diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -index dba52063d402eb2371441fa244b730a3313444fc..28cffbe299acccc59c34d5dbd2cf458704be5ee5 100644 ---- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -+++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -@@ -45,11 +45,16 @@ public class FireworkRocketItem extends Item { - // Paper start - final FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, itemstack, user); - entityfireworks.spawningEntity = user.getUUID(); -- world.addFreshEntity(entityfireworks); -- // Paper end -- if (!user.abilities.instabuild) { -- itemstack.shrink(1); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); -+ if (event.callEvent() && world.addFreshEntity(entityfireworks)) { -+ if (event.shouldConsume() && !user.abilities.instabuild) { -+ itemstack.shrink(1); -+ } else ((EntityPlayer) user).getBukkitEntity().updateInventory(); -+ } else if (user instanceof EntityPlayer) { -+ ((EntityPlayer) user).getBukkitEntity().updateInventory(); - } -+ // Paper end - } - - return InteractionResultHolder.sidedSuccess(user.getItemInHand(hand), world.isClientSide()); diff --git a/patches/server-remapped/0249-Vanished-players-don-t-have-rights.patch b/patches/server-remapped/0249-Vanished-players-don-t-have-rights.patch deleted file mode 100644 index f0b596c503..0000000000 --- a/patches/server-remapped/0249-Vanished-players-don-t-have-rights.patch +++ /dev/null @@ -1,194 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 23 Jul 2018 14:22:26 +0200 -Subject: [PATCH] Vanished players don't have rights - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 9d8682d367522bd85894947ad2f2a53cf0aa123a..a2cc3e58d59ed3d9f443b77c44d8200cc09b4da9 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -183,7 +183,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - private static double viewScale = 1.0D; - private final EntityType type; - private int id; -- public boolean blocksBuilding; -+ public boolean blocksBuilding; public final boolean blocksEntitySpawning() { return this.blocksBuilding; } // Paper - OBFHELPER - public final List passengers; - protected int boardingCooldown; - @Nullable -diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index 16b554675a276471851846d4f2bea06fdcc166d9..d1dd173c11d751b15c3afd4309e386931fd9cf8d 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -5,6 +5,7 @@ import java.util.UUID; - import javax.annotation.Nullable; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -@@ -157,8 +158,14 @@ public abstract class Projectile extends Entity { - protected boolean canHitEntity(Entity entity) { - if (!entity.isSpectator() && entity.isAlive() && entity.isPickable()) { - Entity entity1 = this.getOwner(); -- -+ // Paper start - Cancel hit for vanished players -+ if (entity1 instanceof ServerPlayer && entity instanceof ServerPlayer) { -+ org.bukkit.entity.Player collided = (org.bukkit.entity.Player) entity.getBukkitEntity(); -+ org.bukkit.entity.Player shooter = (org.bukkit.entity.Player) entity1.getBukkitEntity(); -+ if (!shooter.canSee(collided)) return false; -+ } - return entity1 == null || this.leftOwner || !entity1.isPassengerOfSameVehicle(entity); -+ // Paper end - } else { - return false; - } -diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java -index 1ba89fa106dc24abf68d5d13c39a8d80f5582f1f..59522e367327224e5fe0fe2307858077ed812ba6 100644 ---- a/src/main/java/net/minecraft/world/item/BlockItem.java -+++ b/src/main/java/net/minecraft/world/item/BlockItem.java -@@ -174,7 +174,8 @@ public class BlockItem extends Item { - Player entityhuman = context.getPlayer(); - CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of((Entity) entityhuman); - // CraftBukkit start - store default return -- boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision); -+ Level world = context.getLevel(); // Paper -+ boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && world.checkEntityCollision(state, entityhuman, voxelshapecollision, context.getClickedPos(), true); // Paper - org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; - - BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn); -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 7b135a3951bc168ccebdbb4e3acdc07397a820d3..7a9ccd203885b9b369767d1fb8c53783201d0f0f 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -30,6 +30,7 @@ import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkHolder; - import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvent; - import net.minecraft.sounds.SoundSource; - import net.minecraft.tags.TagContainer; -@@ -69,6 +70,10 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; - import net.minecraft.world.level.storage.LevelData; - import net.minecraft.world.level.storage.WritableLevelData; - import net.minecraft.world.phys.AABB; -+import net.minecraft.world.phys.shapes.BooleanOp; -+import net.minecraft.world.phys.shapes.CollisionContext; -+import net.minecraft.world.phys.shapes.Shapes; -+import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.scores.Scoreboard; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -232,6 +237,46 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } - -+ // Paper start -+ // ret true if no collision -+ public final boolean checkEntityCollision(BlockState data, Entity source, CollisionContext voxelshapedcollision, -+ BlockPos position, boolean checkCanSee) { -+ // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape) -+ VoxelShape voxelshape = data.getCollisionShape(this, position, voxelshapedcollision); -+ if (voxelshape.isEmpty()) { -+ return true; -+ } -+ -+ voxelshape = voxelshape.offset((double) position.getX(), (double) position.getY(), (double) position.getZ()); -+ if (voxelshape.isEmpty()) { -+ return true; -+ } -+ -+ List entities = this.getEntities(null, voxelshape.bounds()); -+ for (int i = 0, len = entities.size(); i < len; ++i) { -+ Entity entity = entities.get(i); -+ -+ if (checkCanSee && source instanceof ServerPlayer && entity instanceof ServerPlayer -+ && !((ServerPlayer) source).getBukkitEntity().canSee(((ServerPlayer) entity).getBukkitEntity())) { -+ continue; -+ } -+ -+ // !entity1.dead && entity1.i && (entity == null || !entity1.x(entity)); -+ // elide the last check since vanilla calls with entity = null -+ // only we care about the source for the canSee check -+ if (entity.removed || !entity.blocksEntitySpawning()) { -+ continue; -+ } -+ -+ if (Shapes.applyOperation(voxelshape, Shapes.of(entity.getBoundingBox()), BooleanOp.AND)) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ // Paper end -+ - @Override - public boolean isClientSide() { - return this.isClientSide; -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index e6928557a79f51302975f2832ec911c2692eaaeb..5d7794c9533bd37193f196bda616adaaace2bbde 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -504,6 +504,7 @@ public abstract class BlockBehaviour { - return this.cache != null ? this.cache.collisionShape : this.getCollisionShape(world, pos, CollisionContext.empty()); - } - -+ public final VoxelShape getCollisionShape(BlockGetter iblockaccess, BlockPos blockposition, CollisionContext voxelshapecollision) { return this.getCollisionShape(iblockaccess, blockposition, voxelshapecollision); } // Paper - OBFHELPER - public VoxelShape getCollisionShape(BlockGetter world, BlockPos pos, CollisionContext context) { - return this.getBlock().getCollisionShape(this.asState(), world, pos, context); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -index 2371b52b450e2b43fa9b9549a91f853c702a9dc0..fa2942d0b0424390daee2121f8959034c5352e0b 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -@@ -45,6 +45,7 @@ public final class Shapes { - return create(new AABB(xMin, yMin, zMin, xMax, yMax, zMax)); - } - -+ public static final VoxelShape of(AABB axisAlignedbb) { return Shapes.create(axisAlignedbb); } // Paper - OBFHELPER - public static VoxelShape create(AABB box) { - int i = findBits(box.minX, box.maxX); - int j = findBits(box.minY, box.maxY); -@@ -139,6 +140,7 @@ public final class Shapes { - } - } - -+ public static final boolean applyOperation(VoxelShape voxelshape, VoxelShape voxelshape1, BooleanOp operatorboolean) { return Shapes.joinIsNotEmpty(voxelshape, voxelshape1, operatorboolean); } // Paper - OBFHELPER - public static boolean joinIsNotEmpty(VoxelShape shape1, VoxelShape shape2, BooleanOp predicate) { - if (predicate.apply(false, false)) { - throw (IllegalArgumentException) Util.pauseInIde((Throwable) (new IllegalArgumentException())); -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -index 026759567c58b5e7687ed1eec26fb4ffc60f9fa7..67ecdaada9f87304a9ae83d7917c7aca4676d195 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -@@ -54,6 +54,7 @@ public abstract class VoxelShape { - return this.shape.isEmpty(); - } - -+ public final VoxelShape offset(double x, double y, double z) { return this.move(x, y, z); } // Paper - OBFHELPER - public VoxelShape move(double x, double y, double z) { - return (VoxelShape) (this.isEmpty() ? Shapes.empty() : new ArrayVoxelShape(this.shape, new OffsetDoubleList(this.getCoords(Direction.Axis.X), x), new OffsetDoubleList(this.getCoords(Direction.Axis.Y), y), new OffsetDoubleList(this.getCoords(Direction.Axis.Z), z))); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index c2f58b95db41b2205fbf2728c6a99419c6a63dfa..4cd08821305590e21a01cc4dda05370c2b721ac2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1211,6 +1211,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); -+ -+ if (projectile.getShooter() instanceof Player && collided instanceof Player) { -+ if (!((Player) projectile.getShooter()).canSee((Player) collided)) { -+ event.setCancelled(true); -+ return event; -+ } -+ } -+ - Bukkit.getPluginManager().callEvent(event); - return event; - } diff --git a/patches/server-remapped/0295-Allow-setting-the-vex-s-summoner.patch b/patches/server-remapped/0295-Allow-setting-the-vex-s-summoner.patch deleted file mode 100644 index ee472ab644..0000000000 --- a/patches/server-remapped/0295-Allow-setting-the-vex-s-summoner.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 6 Oct 2018 21:47:44 -0500 -Subject: [PATCH] Allow setting the vex's summoner - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java -index ec4f6d96360e759ffc19de838fdbf3027164a424..a4be2bddc5f51601d419647a280c89f7101371f2 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Vex.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java -@@ -165,6 +165,7 @@ public class Vex extends Monster { - this.setVexFlag(1, charging); - } - -+ public void setOwner(Mob entityinsentient) { setOwner(entityinsentient); } // Paper - OBFHELPER - public void setOwner(Mob owner) { - this.owner = owner; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -index 56bec4350f36a94d4dfa71a234872a795c2dcb3f..07c470f8b049bea930337abc1cc87f4669d2f11a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -@@ -20,6 +20,10 @@ public class CraftVex extends CraftMonster implements Vex { - net.minecraft.world.entity.Mob owner = getHandle().getOwner(); - return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; - } -+ -+ public void setSummoner(org.bukkit.entity.Mob summoner) { -+ getHandle().setOwner(summoner == null ? null : ((CraftMob) summoner).getHandle()); -+ } - // Paper end - - @Override diff --git a/patches/server-remapped/0386-PlayerLaunchProjectileEvent.patch b/patches/server-remapped/0386-PlayerLaunchProjectileEvent.patch deleted file mode 100644 index 886004a317..0000000000 --- a/patches/server-remapped/0386-PlayerLaunchProjectileEvent.patch +++ /dev/null @@ -1,351 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 03:11:03 -0500 -Subject: [PATCH] PlayerLaunchProjectileEvent - - -diff --git a/src/main/java/net/minecraft/world/InteractionResultHolder.java b/src/main/java/net/minecraft/world/InteractionResultHolder.java -index 3bc22b977e00c1901a9025112e354e59fcc08a74..c12e2a65d30ca22db0c522e4b245009bcc38c4f4 100644 ---- a/src/main/java/net/minecraft/world/InteractionResultHolder.java -+++ b/src/main/java/net/minecraft/world/InteractionResultHolder.java -@@ -10,6 +10,7 @@ public class InteractionResultHolder { - this.object = value; - } - -+ public InteractionResult getResult() { return this.getResult(); } // Paper - OBFHELPER - public InteractionResult getResult() { - return this.result; - } -diff --git a/src/main/java/net/minecraft/world/item/EggItem.java b/src/main/java/net/minecraft/world/item/EggItem.java -index d2c4241104343a2d2283c358ab2247e333cf0dbf..5d03dcaf79a14946934a6732c94a195d3d65c56d 100644 ---- a/src/main/java/net/minecraft/world/item/EggItem.java -+++ b/src/main/java/net/minecraft/world/item/EggItem.java -@@ -25,21 +25,35 @@ public class EggItem extends Item { - - entityegg.setItem(itemstack); - entityegg.shootFromRotation(user, user.xRot, user.yRot, 0.0F, 1.5F, 1.0F); -- // CraftBukkit start -- if (!world.addFreshEntity(entityegg)) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityegg.getBukkitEntity()); -+ if (event.callEvent() && world.addFreshEntity(entityegg)) { -+ if (event.shouldConsume() && !user.abilities.instabuild) { -+ itemstack.shrink(1); -+ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { -+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ user.awardStat(Stats.ITEM_USED.get(this)); -+ } else { - if (user instanceof net.minecraft.server.level.ServerPlayer) { - ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); - } -- return InteractionResultHolder.fail(itemstack); -+ return new InteractionResultHolder(net.minecraft.world.InteractionResult.FAIL, itemstack); - } -- // CraftBukkit end -+ // Paper end -+ -+ - } - world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (EggItem.random.nextFloat() * 0.4F + 0.8F)); // CraftBukkit - from above - -- user.awardStat(Stats.ITEM_USED.get(this)); -- if (!user.abilities.instabuild) { -- itemstack.shrink(1); -+ /* // Paper start - moved up -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ if (!entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); - } -diff --git a/src/main/java/net/minecraft/world/item/EnderpearlItem.java b/src/main/java/net/minecraft/world/item/EnderpearlItem.java -index 347e95cc393e773de98b74e18cebbe05f612bdf6..a57c59b330766a2c784ddb7431719e9c1cc2fca8 100644 ---- a/src/main/java/net/minecraft/world/item/EnderpearlItem.java -+++ b/src/main/java/net/minecraft/world/item/EnderpearlItem.java -@@ -25,22 +25,37 @@ public class EnderpearlItem extends Item { - - entityenderpearl.setItem(itemstack); - entityenderpearl.shootFromRotation(user, user.xRot, user.yRot, 0.0F, 1.5F, 1.0F); -- if (!world.addFreshEntity(entityenderpearl)) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityenderpearl.getBukkitEntity()); -+ if (event.callEvent() && world.addFreshEntity(entityenderpearl)) { -+ if (event.shouldConsume() && !user.abilities.instabuild) { -+ itemstack.shrink(1); -+ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { -+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ user.awardStat(Stats.ITEM_USED.get(this)); -+ user.getCooldowns().addCooldown(this, 20); -+ } else { -+ // Paper end - if (user instanceof net.minecraft.server.level.ServerPlayer) { - ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); - } -- return InteractionResultHolder.fail(itemstack); -+ return new InteractionResultHolder(net.minecraft.world.InteractionResult.FAIL, itemstack); - } - } - -- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (EnderpearlItem.random.nextFloat() * 0.4F + 0.8F)); -- user.getCooldowns().addCooldown(this, 20); -- // CraftBukkit end -- -- user.awardStat(Stats.ITEM_USED.get(this)); -- if (!user.abilities.instabuild) { -- itemstack.shrink(1); -- } -+ // Paper start - moved up -+// world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F)); -+// entityhuman.getCooldownTracker().setCooldown(this, 20); -+// // CraftBukkit end -+// -+// entityhuman.b(StatisticList.ITEM_USED.b(this)); -+// if (!entityhuman.abilities.canInstantlyBuild) { -+// itemstack.subtract(1); -+// } -+ // Paper end - moved up - - return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); - } -diff --git a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java -index 032c476892c58a873242b00ca71fe084c719dcaa..0bd65165eacf6a54cdcc348991cf9adb44077bee 100644 ---- a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java -+++ b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java -@@ -1,10 +1,13 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.stats.Stats; - import net.minecraft.world.InteractionHand; -+import net.minecraft.world.InteractionResult; - import net.minecraft.world.InteractionResultHolder; -+import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.projectile.ThrownExperienceBottle; - import net.minecraft.world.level.Level; -@@ -24,19 +27,38 @@ public class ExperienceBottleItem extends Item { - public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { - ItemStack itemstack = user.getItemInHand(hand); - -- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (ExperienceBottleItem.random.nextFloat() * 0.4F + 0.8F)); -+ //world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); // Paper - moved down - if (!world.isClientSide) { - ThrownExperienceBottle entitythrownexpbottle = new ThrownExperienceBottle(world, user); - - entitythrownexpbottle.setItem(itemstack); - entitythrownexpbottle.shootFromRotation(user, user.xRot, user.yRot, -20.0F, 0.7F, 1.0F); -- world.addFreshEntity(entitythrownexpbottle); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitythrownexpbottle.getBukkitEntity()); -+ if (event.callEvent() && world.addFreshEntity(entitythrownexpbottle)) { -+ if (event.shouldConsume() && !user.abilities.instabuild) { -+ itemstack.shrink(1); -+ } else if (user instanceof ServerPlayer) { -+ ((ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ user.awardStat(Stats.ITEM_USED.get(this)); -+ } else { -+ if (user instanceof ServerPlayer) { -+ ((ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } -+ return new InteractionResultHolder(InteractionResult.FAIL, itemstack); -+ } -+ // Paper end - } - -- user.awardStat(Stats.ITEM_USED.get(this)); -- if (!user.abilities.instabuild) { -- itemstack.shrink(1); -+ /* // Paper start - moved up -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ if (!entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); - } -diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -index 28cffbe299acccc59c34d5dbd2cf458704be5ee5..4a70582bada607e1efcd826d58d725a0cc95e3c3 100644 ---- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -+++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -@@ -3,6 +3,7 @@ package net.minecraft.world.item; - import java.util.Arrays; - import java.util.Comparator; - import net.minecraft.core.Direction; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.InteractionHand; - import net.minecraft.world.InteractionResult; - import net.minecraft.world.InteractionResultHolder; -@@ -29,8 +30,12 @@ public class FireworkRocketItem extends Item { - FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, context.getPlayer(), vec3d.x + (double) enumdirection.getStepX() * 0.15D, vec3d.y + (double) enumdirection.getStepY() * 0.15D, vec3d.z + (double) enumdirection.getStepZ() * 0.15D, itemstack); - entityfireworks.spawningEntity = context.getPlayer().getUUID(); // Paper - -- world.addFreshEntity(entityfireworks); -- itemstack.shrink(1); -+ // Paper start - PlayerLaunchProjectileEvent -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) context.getPlayer().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); -+ if (!event.callEvent() || !world.addFreshEntity(entityfireworks)) return InteractionResult.PASS; -+ if (event.shouldConsume() && !context.getPlayer().abilities.instabuild) itemstack.shrink(1); -+ else if (context.getPlayer() instanceof ServerPlayer) ((ServerPlayer) context.getPlayer()).getBukkitEntity().updateInventory(); -+ // Paper end - } - - return InteractionResult.sidedSuccess(world.isClientSide); -@@ -50,9 +55,9 @@ public class FireworkRocketItem extends Item { - if (event.callEvent() && world.addFreshEntity(entityfireworks)) { - if (event.shouldConsume() && !user.abilities.instabuild) { - itemstack.shrink(1); -- } else ((EntityPlayer) user).getBukkitEntity().updateInventory(); -- } else if (user instanceof EntityPlayer) { -- ((EntityPlayer) user).getBukkitEntity().updateInventory(); -+ } else ((ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } else if (user instanceof ServerPlayer) { -+ ((ServerPlayer) user).getBukkitEntity().updateInventory(); - } - // Paper end - } -diff --git a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java -index 813a9c8464e253b9baa15af666111be104b4aa29..1957561f83645a57df5925b4b0b54153ebf4aeef 100644 ---- a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java -+++ b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java -@@ -3,6 +3,7 @@ package net.minecraft.world.item; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.world.InteractionHand; -+import net.minecraft.world.InteractionResult; - import net.minecraft.world.InteractionResultHolder; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.level.Level; -@@ -15,7 +16,12 @@ public class LingeringPotionItem extends ThrowablePotionItem { - - @Override - public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { -- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.LINGERING_POTION_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (LingeringPotionItem.random.nextFloat() * 0.4F + 0.8F)); -- return super.use(world, user, hand); -+ // Paper start -+ InteractionResultHolder wrapper = super.use(world, user, hand); -+ if (wrapper.getResult() != InteractionResult.FAIL) { -+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.LINGERING_POTION_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (LingeringPotionItem.random.nextFloat() * 0.4F + 0.8F)); -+ } -+ return wrapper; -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/item/SnowballItem.java b/src/main/java/net/minecraft/world/item/SnowballItem.java -index 50adbfc5d57b2b5f25c0efdc51da1701197c66e6..b053d105a1513a6b138972cdb9d28116fc6b8c81 100644 ---- a/src/main/java/net/minecraft/world/item/SnowballItem.java -+++ b/src/main/java/net/minecraft/world/item/SnowballItem.java -@@ -26,14 +26,20 @@ public class SnowballItem extends Item { - - entitysnowball.setItem(itemstack); - entitysnowball.shootFromRotation(user, user.xRot, user.yRot, 0.0F, 1.5F, 1.0F); -- if (world.addFreshEntity(entitysnowball)) { -- if (!user.abilities.instabuild) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity()); -+ if (event.callEvent() && world.addFreshEntity(entitysnowball)) { -+ if (event.shouldConsume() && !user.abilities.instabuild) { -+ // Paper end - itemstack.shrink(1); -+ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { // Paper -+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper - } - - world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (SnowballItem.random.nextFloat() * 0.4F + 0.8F)); -- } else if (user instanceof net.minecraft.server.level.ServerPlayer) { -- ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } else { // Paper -+ if (user instanceof net.minecraft.server.level.ServerPlayer) ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper -+ return new InteractionResultHolder(net.minecraft.world.InteractionResult.FAIL, itemstack); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/item/SplashPotionItem.java b/src/main/java/net/minecraft/world/item/SplashPotionItem.java -index 9c7547988fe90e9b87868636a1c1a7b4dff32622..6d3ab7fea3b5ebba4c304cdec5dd36dbea31f2c6 100644 ---- a/src/main/java/net/minecraft/world/item/SplashPotionItem.java -+++ b/src/main/java/net/minecraft/world/item/SplashPotionItem.java -@@ -3,6 +3,7 @@ package net.minecraft.world.item; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.world.InteractionHand; -+import net.minecraft.world.InteractionResult; - import net.minecraft.world.InteractionResultHolder; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.level.Level; -@@ -15,7 +16,12 @@ public class SplashPotionItem extends ThrowablePotionItem { - - @Override - public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { -+ // Paper start -+ InteractionResultHolder wrapper = super.use(world, user, hand); -+ if (wrapper.getResult() != InteractionResult.FAIL) { - world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SPLASH_POTION_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (SplashPotionItem.random.nextFloat() * 0.4F + 0.8F)); -- return super.use(world, user, hand); -+ } -+ return wrapper; -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java -index 3615bc9222db4489189537f7f5d7a7d338053d6d..e12c7ebc0a4ff4f132512dc1677db7f79db41b03 100644 ---- a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java -+++ b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java -@@ -1,7 +1,9 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.stats.Stats; - import net.minecraft.world.InteractionHand; -+import net.minecraft.world.InteractionResult; - import net.minecraft.world.InteractionResultHolder; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.projectile.ThrownPotion; -@@ -22,13 +24,31 @@ public class ThrowablePotionItem extends PotionItem { - - entitypotion.setItem(itemstack); - entitypotion.shootFromRotation(user, user.xRot, user.yRot, -20.0F, 0.5F, 1.0F); -- world.addFreshEntity(entitypotion); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitypotion.getBukkitEntity()); -+ if (event.callEvent() && world.addFreshEntity(entitypotion)) { -+ if (event.shouldConsume() && !user.abilities.instabuild) { -+ itemstack.shrink(1); -+ } else if (user instanceof ServerPlayer) { -+ ((ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } -+ -+ user.awardStat(Stats.ITEM_USED.get(this)); -+ } else { -+ if (user instanceof ServerPlayer) { -+ ((ServerPlayer) user).getBukkitEntity().updateInventory(); -+ } -+ return new InteractionResultHolder(InteractionResult.FAIL, itemstack); -+ } -+ // Paper end - } - -- user.awardStat(Stats.ITEM_USED.get(this)); -- if (!user.abilities.instabuild) { -- itemstack.shrink(1); -+ /* // Paper start - moved up -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ if (!entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); - } diff --git a/patches/server-remapped/0236-Vex-getSummoner-API.patch b/patches/server/0219-Vex-get-setSummoner-API.patch similarity index 51% rename from patches/server-remapped/0236-Vex-getSummoner-API.patch rename to patches/server/0219-Vex-get-setSummoner-API.patch index 0689023cf1..ec419aa9d5 100644 --- a/patches/server-remapped/0236-Vex-getSummoner-API.patch +++ b/patches/server/0219-Vex-get-setSummoner-API.patch @@ -1,35 +1,32 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Wed, 4 Jul 2018 15:30:22 -0400 -Subject: [PATCH] Vex#getSummoner API +Subject: [PATCH] Vex#get/setSummoner API -Get's the NPC that summoned this Vex +Get's the NPC that summoned this Vex and +Allow setting the vex's summoner + +Co-authored-by: BillyGalbreath -diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java -index 3204ae9a9243818727bedfa060c07bc34d3b4c66..ec4f6d96360e759ffc19de838fdbf3027164a424 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Vex.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java -@@ -124,6 +124,7 @@ public class Vex extends Monster { - - } - -+ public Mob getOwner() { return getOwner(); } // Paper - OBFHELPER - public Mob getOwner() { - return this.owner; - } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -index 2b4e9ddca5c6429c01d780d65a64ef6a59446c69..56bec4350f36a94d4dfa71a234872a795c2dcb3f 100644 +index d07d956e727483bb0b85dce618acb2adc8d89872..0f5c81c0d599d3b58f7864d1527391ad50983c4e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -@@ -15,6 +15,13 @@ public class CraftVex extends CraftMonster implements Vex { +@@ -15,6 +15,19 @@ public class CraftVex extends CraftMonster implements Vex { return (net.minecraft.world.entity.monster.Vex) super.getHandle(); } + // Paper start ++ @Override + public org.bukkit.entity.Mob getSummoner() { + net.minecraft.world.entity.Mob owner = getHandle().getOwner(); + return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; + } ++ ++ @Override ++ public void setSummoner(org.bukkit.entity.Mob summoner) { ++ getHandle().setOwner(summoner == null ? null : ((CraftMob) summoner).getHandle()); ++ } + // Paper end + @Override diff --git a/patches/server-remapped/0237-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/patches/server/0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch similarity index 66% rename from patches/server-remapped/0237-Refresh-player-inventory-when-cancelling-PlayerInter.patch rename to patches/server/0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch index 5cab7fe140..c21462446e 100644 --- a/patches/server-remapped/0237-Refresh-player-inventory-when-cancelling-PlayerInter.patch +++ b/patches/server/0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch @@ -16,14 +16,14 @@ Refresh the player inventory when PlayerInteractEntityEvent is cancelled to avoid this problem. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index d322e99170b3cb6594efc824a879ab9a538ea1eb..645f7b7c862acf77d70ca0b05308945424bc4d32 100644 +index ce88f701f296e67afc67d7e3882406e86147408e..902eab82912b9a7002485f73df7ae25e370b7e25 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2222,6 +2222,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - } +@@ -2217,6 +2217,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } - if (event.isCancelled()) { -+ this.player.refreshContainer(this.player.containerMenu); // Paper - Refresh player inventory - return; - } - // CraftBukkit end + if (event.isCancelled()) { ++ ServerGamePacketListenerImpl.this.player.containerMenu.sendAllDataToRemote(); // Paper - Refresh player inventory + return; + } + // CraftBukkit end diff --git a/patches/server-remapped/0240-Avoid-item-merge-if-stack-size-above-max-stack-size.patch b/patches/server/0221-Avoid-item-merge-if-stack-size-above-max-stack-size.patch similarity index 86% rename from patches/server-remapped/0240-Avoid-item-merge-if-stack-size-above-max-stack-size.patch rename to patches/server/0221-Avoid-item-merge-if-stack-size-above-max-stack-size.patch index b47c9efed4..ef92cd2b92 100644 --- a/patches/server-remapped/0240-Avoid-item-merge-if-stack-size-above-max-stack-size.patch +++ b/patches/server/0221-Avoid-item-merge-if-stack-size-above-max-stack-size.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Avoid item merge if stack size above max stack size diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index de69f7c3c0ee1e74682b0db91bdaae09175690e9..70f719ba3c68c8e9414e6b4bc68002f7c962e2b9 100644 +index 54025e401eb02fceb47afb182f0ede620ca23a8d..0741dcbd06395b4696eb6083128a5d9b679cb3fb 100644 --- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -208,6 +208,10 @@ public class ItemEntity extends Entity { +@@ -223,6 +223,10 @@ public class ItemEntity extends Entity { private void mergeWithNeighbours() { if (this.isMergable()) { diff --git a/patches/server-remapped/0241-Use-asynchronous-Log4j-2-loggers.patch b/patches/server/0222-Use-asynchronous-Log4j-2-loggers.patch similarity index 73% rename from patches/server-remapped/0241-Use-asynchronous-Log4j-2-loggers.patch rename to patches/server/0222-Use-asynchronous-Log4j-2-loggers.patch index fd4a4b705a..8c37425010 100644 --- a/patches/server-remapped/0241-Use-asynchronous-Log4j-2-loggers.patch +++ b/patches/server/0222-Use-asynchronous-Log4j-2-loggers.patch @@ -4,13 +4,25 @@ Date: Tue, 17 Jul 2018 16:42:17 +0200 Subject: [PATCH] Use asynchronous Log4j 2 loggers +diff --git a/build.gradle.kts b/build.gradle.kts +index ac607a3be84bc02dedb95cab9a5eace40e33b511..b967ab10155bbf26e864bedadb8ae2ab5fdd38c1 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -42,6 +42,7 @@ dependencies { + } + runtimeOnly("org.xerial:sqlite-jdbc:3.34.0") + runtimeOnly("mysql:mysql-connector-java:8.0.23") // Paper ++ runtimeOnly("com.lmax:disruptor:3.4.2") // Paper + + runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.1") + runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/pom.xml b/pom.xml -index f5429f2f1979542fd93956d2f436d20d0e3a66b8..4c8a057e790c96b0ab5123549d0566371acacb46 100644 +index f5e74f74e32095c4ad1f8094a0dd64be8e193f0c..86cce7143abd317326cc755118bf61435e82e479 100644 --- a/pom.xml +++ b/pom.xml -@@ -88,6 +88,13 @@ - log4j-iostreams - compile +@@ -57,6 +57,13 @@ + + + + diff --git a/patches/server-remapped/0242-add-more-information-to-Entity.toString.patch b/patches/server/0223-add-more-information-to-Entity.toString.patch similarity index 58% rename from patches/server-remapped/0242-add-more-information-to-Entity.toString.patch rename to patches/server/0223-add-more-information-to-Entity.toString.patch index b0de783dec..bfc1e37644 100644 --- a/patches/server-remapped/0242-add-more-information-to-Entity.toString.patch +++ b/patches/server/0223-add-more-information-to-Entity.toString.patch @@ -6,15 +6,15 @@ Subject: [PATCH] add more information to Entity.toString() UUID, ticks lived, valid, dead diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 7e70bae5bc54ad17980789fa965fd539a7f193ea..e49fe2de6a53bdd16f0cd09b691f01f1866ffb4f 100644 +index 1603a0ff6a0c82e18ef5446c129a1c05488abf86..960c3e75a60ef33141e615bd8b256528eeaf399c 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2526,7 +2526,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2784,7 +2784,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } public String toString() { - return String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getName().getString(), this.id, this.level == null ? "~NULL~" : this.level.toString(), this.getX(), this.getY(), this.getZ()); -+ return String.format(Locale.ROOT, "%s['%s'/%d, uuid='%s', l='%s', x=%.2f, y=%.2f, z=%.2f, cx=%d, cz=%d, tl=%d, v=%b, d=%b]", new Object[] { this.getClass().getSimpleName(), this.getName().getString(), Integer.valueOf(this.id), this.uuid.toString(), this.level == null ? "~NULL~" : this.level.toString(), Double.valueOf(this.getX()), Double.valueOf(this.getY()), Double.valueOf(this.getZ()), xChunk, zChunk, this.tickCount, this.valid, this.removed}); // Paper - add more information ++ return String.format(Locale.ROOT, "%s['%s'/%d, uuid='%s', l='%s', x=%.2f, y=%.2f, z=%.2f, cpos=%s, tl=%d, v=%b, rR=%s]", new Object[] { this.getClass().getSimpleName(), this.getName().getString(), Integer.valueOf(this.id), this.uuid.toString(), this.level == null ? "~NULL~" : this.level.toString(), Double.valueOf(this.getX()), Double.valueOf(this.getY()), Double.valueOf(this.getZ()), this.chunkPosition(), this.tickCount, this.valid, this.removalReason}); // Paper - add more information } public boolean isInvulnerableTo(DamageSource damageSource) { diff --git a/patches/server-remapped/0387-Add-CraftMagicNumbers.isSupportedApiVersion.patch b/patches/server/0224-Add-CraftMagicNumbers.isSupportedApiVersion.patch similarity index 90% rename from patches/server-remapped/0387-Add-CraftMagicNumbers.isSupportedApiVersion.patch rename to patches/server/0224-Add-CraftMagicNumbers.isSupportedApiVersion.patch index 509fc426f4..ea875b26f8 100644 --- a/patches/server-remapped/0387-Add-CraftMagicNumbers.isSupportedApiVersion.patch +++ b/patches/server/0224-Add-CraftMagicNumbers.isSupportedApiVersion.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add CraftMagicNumbers.isSupportedApiVersion() diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 21052d0e88351b075733331d71e07b086354b820..86b319337fc41a09dd45df466df60cadaed1343f 100644 +index c49d2dd323e7164ded499e561821da2c0e4be9da..ad8d6a84e1a66e03ae15269e36bc787148f12396 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -373,6 +373,11 @@ public final class CraftMagicNumbers implements UnsafeValues { diff --git a/patches/server-remapped/0244-EnderDragon-Events.patch b/patches/server/0225-EnderDragon-Events.patch similarity index 61% rename from patches/server-remapped/0244-EnderDragon-Events.patch rename to patches/server/0225-EnderDragon-Events.patch index 14fc4f84c6..f59ce271f5 100644 --- a/patches/server-remapped/0244-EnderDragon-Events.patch +++ b/patches/server/0225-EnderDragon-Events.patch @@ -5,58 +5,49 @@ Subject: [PATCH] EnderDragon Events diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java -index 0c2a5f5c4d7d7516793eba20205b5703fe1450d5..6b28cfb1e79903c43702f6e78e226dc78e3ccec2 100644 +index df44bfce8cc492cd901dfa86331b9be7f1e13837..7490674d59d152a70e24a790bdbc717998ed2c52 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java -@@ -80,7 +80,11 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { +@@ -81,7 +81,13 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { this.flame.setDuration(200); this.flame.setParticle(ParticleTypes.DRAGON_BREATH); this.flame.addEffect(new MobEffectInstance(MobEffects.HARM)); + if (new com.destroystokyo.paper.event.entity.EnderDragonFlameEvent((org.bukkit.entity.EnderDragon) this.dragon.getBukkitEntity(), (org.bukkit.entity.AreaEffectCloud) this.flame.getBukkitEntity()).callEvent()) { // Paper this.dragon.level.addFreshEntity(this.flame); ++ // Paper start + } else { -+ this.removeAreaEffect(); ++ this.end(); + } ++ // Paper end } } -@@ -91,8 +95,8 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { - ++this.flameCount; - } - -- @Override -- public void end() { -+ public final void removeAreaEffect() { this.end(); } // Paper - OBFHELPER -+ @Override public void end() { - if (this.flame != null) { - this.flame.remove(); - this.flame = null; diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java -index 01442af7b0c7340f0ece2fa0faa0f783b1b81c48..a43ef94f8a5c7a9d1581667beb4516cc26f30a0d 100644 +index 974895ef23e9d2b8c520abd262a2e80d28be5860..318a288a9170254b682955d96a150e99ca89b345 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java -@@ -81,7 +81,9 @@ public class DragonStrafePlayerPhase extends AbstractDragonPhaseInstance { - DragonFireball entitydragonfireball = new DragonFireball(this.dragon.level, this.dragon, d9, d10, d11); +@@ -71,7 +71,9 @@ public class DragonStrafePlayerPhase extends AbstractDragonPhaseInstance { - entitydragonfireball.moveTo(d6, d7, d8, 0.0F, 0.0F); -+ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) dragon.getBukkitEntity(), (org.bukkit.entity.DragonFireball) entitydragonfireball.getBukkitEntity()).callEvent()) // Paper - this.dragon.level.addFreshEntity(entitydragonfireball); -+ else entitydragonfireball.remove(); // Paper + DragonFireball dragonFireball = new DragonFireball(this.dragon.level, this.dragon, r, s, t); + dragonFireball.moveTo(o, p, q, 0.0F, 0.0F); ++ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) dragon.getBukkitEntity(), (org.bukkit.entity.DragonFireball) dragonFireball.getBukkitEntity()).callEvent()) // Paper + this.dragon.level.addFreshEntity(dragonFireball); ++ else dragonFireball.discard(); // Paper this.fireballCharge = 0; if (this.currentPath != null) { - while (!this.currentPath.isDone()) { + while(!this.currentPath.isDone()) { diff --git a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java -index 76dc15e07ce9ef01ad7908e289a0d695b65b2fc9..1629e409a83b11b76e1627247a838c9ebd11a648 100644 +index a7935042497a108a21814c28b01a0ab27aefbbc4..6afe37e42d88701af38df5793a9ea9d7d2cda5c5 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java +++ b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java -@@ -58,8 +58,10 @@ public class DragonFireball extends AbstractHurtingProjectile { +@@ -52,8 +52,10 @@ public class DragonFireball extends AbstractHurtingProjectile { } } -+ if (new com.destroystokyo.paper.event.entity.EnderDragonFireballHitEvent((org.bukkit.entity.DragonFireball) this.getBukkitEntity(), list.stream().map(LivingEntity::getBukkitLivingEntity).collect(java.util.stream.Collectors.toList()), (org.bukkit.entity.AreaEffectCloud) entityareaeffectcloud.getBukkitEntity()).callEvent()) { // Paper ++ if (new com.destroystokyo.paper.event.entity.EnderDragonFireballHitEvent((org.bukkit.entity.DragonFireball) this.getBukkitEntity(), list.stream().map(LivingEntity::getBukkitLivingEntity).collect(java.util.stream.Collectors.toList()), (org.bukkit.entity.AreaEffectCloud) areaEffectCloud.getBukkitEntity()).callEvent()) { // Paper this.level.levelEvent(2006, this.blockPosition(), this.isSilent() ? -1 : 1); - this.level.addFreshEntity(entityareaeffectcloud); -+ } else entityareaeffectcloud.remove(); // Paper - this.remove(); + this.level.addFreshEntity(areaEffectCloud); ++ } else areaEffectCloud.discard(); // Paper + this.discard(); } diff --git a/patches/server/0226-PlayerElytraBoostEvent.patch b/patches/server/0226-PlayerElytraBoostEvent.patch new file mode 100644 index 0000000000..00826b935f --- /dev/null +++ b/patches/server/0226-PlayerElytraBoostEvent.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 01:59:59 -0500 +Subject: [PATCH] PlayerElytraBoostEvent + + +diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index 10385dcb851bb435821afba322ed11f59e7ad3e6..561f98b442788814cbc6cbb7e144207d14f67ff8 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -61,12 +61,19 @@ public class FireworkRocketItem extends Item { + if (!world.isClientSide) { + FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(world, itemStack, user); + fireworkRocketEntity.spawningEntity = user.getUUID(); // Paper +- world.addFreshEntity(fireworkRocketEntity); +- if (!user.getAbilities().instabuild) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Firework) fireworkRocketEntity.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(fireworkRocketEntity)) { ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ if (event.shouldConsume() && !user.getAbilities().instabuild) { + itemStack.shrink(1); ++ } else ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ // Paper end + } + +- user.awardStat(Stats.ITEM_USED.get(this)); ++ // user.awardStat(Stats.ITEM_USED.get(this)); // Paper - move up + } + + return InteractionResultHolder.sidedSuccess(user.getItemInHand(hand), world.isClientSide()); diff --git a/patches/server/0227-PlayerLaunchProjectileEvent.patch b/patches/server/0227-PlayerLaunchProjectileEvent.patch new file mode 100644 index 0000000000..2191c9d370 --- /dev/null +++ b/patches/server/0227-PlayerLaunchProjectileEvent.patch @@ -0,0 +1,276 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 21 Jul 2018 03:11:03 -0500 +Subject: [PATCH] PlayerLaunchProjectileEvent + + +diff --git a/src/main/java/net/minecraft/world/item/EggItem.java b/src/main/java/net/minecraft/world/item/EggItem.java +index 3516cd8ec5816e13df9850c6dc62ddd69b5cfaed..784c5c2b8299a5309ae190fef9923778fcfa00b4 100644 +--- a/src/main/java/net/minecraft/world/item/EggItem.java ++++ b/src/main/java/net/minecraft/world/item/EggItem.java +@@ -23,21 +23,33 @@ public class EggItem extends Item { + + entityegg.setItem(itemstack); + entityegg.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F); +- // CraftBukkit start +- if (!world.addFreshEntity(entityegg)) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityegg.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entityegg)) { ++ if (event.shouldConsume() && !user.getAbilities().instabuild) { ++ itemstack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), net.minecraft.sounds.SoundEvents.EGG_THROW, net.minecraft.sounds.SoundSource.PLAYERS, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ } else { + if (user instanceof net.minecraft.server.level.ServerPlayer) { + ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); + } + return InteractionResultHolder.fail(itemstack); + } +- // CraftBukkit end ++ // Paper end + } + // world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); // CraftBukkit - from above + ++ /* // Paper start - moved up + user.awardStat(Stats.ITEM_USED.get(this)); + if (!user.getAbilities().instabuild) { + itemstack.shrink(1); + } ++ */ // Paper end + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/EnderpearlItem.java b/src/main/java/net/minecraft/world/item/EnderpearlItem.java +index c7d4745aed77b23562cde7c68b8870fa239428d4..749ab72edc0d2e9c6f1161415ab8d59d3d6ca976 100644 +--- a/src/main/java/net/minecraft/world/item/EnderpearlItem.java ++++ b/src/main/java/net/minecraft/world/item/EnderpearlItem.java +@@ -25,7 +25,20 @@ public class EnderpearlItem extends Item { + + entityenderpearl.setItem(itemstack); + entityenderpearl.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F); +- if (!world.addFreshEntity(entityenderpearl)) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityenderpearl.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entityenderpearl)) { ++ if (event.shouldConsume() && !user.getAbilities().instabuild) { ++ itemstack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ user.getCooldowns().addCooldown(this, 20); ++ } else { ++ // Paper end + if (user instanceof net.minecraft.server.level.ServerPlayer) { + ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); + } +@@ -33,6 +46,7 @@ public class EnderpearlItem extends Item { + } + } + ++ /* // Paper start - moved up + world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + user.getCooldowns().addCooldown(this, 20); + // CraftBukkit end +@@ -41,6 +55,7 @@ public class EnderpearlItem extends Item { + if (!user.getAbilities().instabuild) { + itemstack.shrink(1); + } ++ */ // Paper end - moved up + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java +index 72dfb7b652f515bf9df201d524a851ab56706544..b80bedb5f27b474d7f66e9e1cc38ca3b692fc92b 100644 +--- a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java ++++ b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java +@@ -22,18 +22,37 @@ public class ExperienceBottleItem extends Item { + @Override + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { + ItemStack itemStack = user.getItemInHand(hand); +- world.playSound((Player)null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); ++ // world.playSound((Player)null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); // Paper - moved down + if (!world.isClientSide) { + ThrownExperienceBottle thrownExperienceBottle = new ThrownExperienceBottle(world, user); + thrownExperienceBottle.setItem(itemStack); + thrownExperienceBottle.shootFromRotation(user, user.getXRot(), user.getYRot(), -20.0F, 0.7F, 1.0F); +- world.addFreshEntity(thrownExperienceBottle); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) thrownExperienceBottle.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(thrownExperienceBottle)) { ++ if (event.shouldConsume() && !user.getAbilities().instabuild) { ++ itemStack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ } else { ++ if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ return InteractionResultHolder.fail(itemStack); ++ } ++ // Paper end + } + ++ /* // Paper start - moved up + user.awardStat(Stats.ITEM_USED.get(this)); + if (!user.getAbilities().instabuild) { + itemStack.shrink(1); + } ++ */ // Paper end + + return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index 561f98b442788814cbc6cbb7e144207d14f67ff8..543a08f920319a2547258640bafebb1e70af65c4 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -13,6 +13,7 @@ import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.stats.Stats; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.InteractionHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; +@@ -47,8 +48,12 @@ public class FireworkRocketItem extends Item { + Direction direction = context.getClickedFace(); + FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(level, context.getPlayer(), vec3.x + (double)direction.getStepX() * 0.15D, vec3.y + (double)direction.getStepY() * 0.15D, vec3.z + (double)direction.getStepZ() * 0.15D, itemStack); + fireworkRocketEntity.spawningEntity = context.getPlayer() == null ? null : context.getPlayer().getUUID(); // Paper +- level.addFreshEntity(fireworkRocketEntity); +- itemStack.shrink(1); ++ // Paper start - PlayerLaunchProjectileEvent ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) context.getPlayer().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Firework) fireworkRocketEntity.getBukkitEntity()); ++ if (!event.callEvent() || !level.addFreshEntity(fireworkRocketEntity)) return InteractionResult.PASS; ++ if (event.shouldConsume() && !context.getPlayer().getAbilities().instabuild) itemStack.shrink(1); ++ else if (context.getPlayer() instanceof ServerPlayer) ((ServerPlayer) context.getPlayer()).getBukkitEntity().updateInventory(); ++ // Paper end + } + + return InteractionResult.sidedSuccess(level.isClientSide); +diff --git a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java +index db0492f6337de562210ef062f46e98992c908200..f2d1b4e3fc08f6a06beb391bc6e60f62a9bf82b9 100644 +--- a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java ++++ b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java +@@ -23,7 +23,12 @@ public class LingeringPotionItem extends ThrowablePotionItem { + + @Override + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { ++ // Paper start ++ InteractionResultHolder wrapper = super.use(world, user, hand); ++ if (wrapper.getResult() != net.minecraft.world.InteractionResult.FAIL) { + world.playSound((Player)null, user.getX(), user.getY(), user.getZ(), SoundEvents.LINGERING_POTION_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); +- return super.use(world, user, hand); ++ } ++ return wrapper; ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/item/SnowballItem.java b/src/main/java/net/minecraft/world/item/SnowballItem.java +index 516afa893035539a879a71eb327eed0596c31d48..717f90a2ca41734f7ee09401f21474820fa1cf48 100644 +--- a/src/main/java/net/minecraft/world/item/SnowballItem.java ++++ b/src/main/java/net/minecraft/world/item/SnowballItem.java +@@ -26,18 +26,26 @@ public class SnowballItem extends Item { + + entitysnowball.setItem(itemstack); + entitysnowball.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F); +- if (world.addFreshEntity(entitysnowball)) { +- if (!user.getAbilities().instabuild) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entitysnowball)) { ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ if (event.shouldConsume() && !user.getAbilities().instabuild) { ++ // Paper end + itemstack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { // Paper ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper + } + + world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); +- } else if (user instanceof net.minecraft.server.level.ServerPlayer) { +- ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } else { // Paper ++ if (user instanceof net.minecraft.server.level.ServerPlayer) ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper ++ return InteractionResultHolder.fail(itemstack); // Paper + } + } + // CraftBukkit end + ++ /* // Paper tart - moved up + user.awardStat(Stats.ITEM_USED.get(this)); + // CraftBukkit start - moved up + /* +@@ -45,6 +53,7 @@ public class SnowballItem extends Item { + itemstack.subtract(1); + } + */ ++ // Paper end + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/SplashPotionItem.java b/src/main/java/net/minecraft/world/item/SplashPotionItem.java +index 317e20052bcac9118e1adeb619bedaacc6fcd690..ece19f30064e9f59d4df077683e1f894455a84b7 100644 +--- a/src/main/java/net/minecraft/world/item/SplashPotionItem.java ++++ b/src/main/java/net/minecraft/world/item/SplashPotionItem.java +@@ -14,7 +14,12 @@ public class SplashPotionItem extends ThrowablePotionItem { + + @Override + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { ++ // Paper start ++ InteractionResultHolder wrapper = super.use(world, user, hand); ++ if (wrapper.getResult() != net.minecraft.world.InteractionResult.FAIL) { + world.playSound((Player)null, user.getX(), user.getY(), user.getZ(), SoundEvents.SPLASH_POTION_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); +- return super.use(world, user, hand); ++ } ++ return wrapper; ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java +index 0673f62f25532955f3552b64f122e644d42027e4..de5bdceb4c8578fb972a2fd5ee0dfdae509e46dc 100644 +--- a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java ++++ b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java +@@ -19,13 +19,31 @@ public class ThrowablePotionItem extends PotionItem { + ThrownPotion thrownPotion = new ThrownPotion(world, user); + thrownPotion.setItem(itemStack); + thrownPotion.shootFromRotation(user, user.getXRot(), user.getYRot(), -20.0F, 0.5F, 1.0F); +- world.addFreshEntity(thrownPotion); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) thrownPotion.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(thrownPotion)) { ++ if (event.shouldConsume() && !user.getAbilities().instabuild) { ++ itemStack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ } else { ++ if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ return InteractionResultHolder.fail(itemStack); ++ } ++ // Paper end + } + ++ /* // Paper start - moved up + user.awardStat(Stats.ITEM_USED.get(this)); + if (!user.getAbilities().instabuild) { + itemStack.shrink(1); + } ++ */ // Paper end + + return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide()); + } diff --git a/patches/server-remapped/0246-Improve-BlockPosition-inlining.patch b/patches/server/0228-Improve-BlockPosition-inlining.patch similarity index 67% rename from patches/server-remapped/0246-Improve-BlockPosition-inlining.patch rename to patches/server/0228-Improve-BlockPosition-inlining.patch index 675f0c0360..b667b7f9bc 100644 --- a/patches/server-remapped/0246-Improve-BlockPosition-inlining.patch +++ b/patches/server/0228-Improve-BlockPosition-inlining.patch @@ -20,42 +20,30 @@ This should result in an across the board speedup in anything that accesses bloc This is based upon conclusions drawn from inspecting the assenmbly generated bythe JIT compiler on my microbenchmarks. They had 'callq' (invoke) instead of 'mov' (get from memory) instructions. -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 6a58059a05e16d96894b67a544c2f595d9546c78..c5089b0da33a68e7cadbc4841b07f9d772d224a0 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -88,6 +88,7 @@ public class BlockPos extends Vec3i { - return asLong(this.getX(), this.getY(), this.getZ()); - } - -+ public static long asLong(int x, int y, int z) { return asLong(x, y, z); } // Paper - OBFHELPER - public static long asLong(int x, int y, int z) { - long l = 0L; - diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java -index c22de593be404c4e921724bba6a69c13759a95fd..fc4e652ada7b228cb99a3c8fb372ae9af5ddfba4 100644 +index c66ae4d9eea993f3b7fcc6e253259db3346229d1..ea496a990e7e49bc83f7a8b98f71f2b11d9fc56c 100644 --- a/src/main/java/net/minecraft/core/Vec3i.java +++ b/src/main/java/net/minecraft/core/Vec3i.java @@ -41,7 +41,7 @@ public class Vec3i implements Comparable { - this(Mth.floor(x), Mth.floor(y), Mth.floor(z)); } + @Override - public boolean equals(Object object) { + public final boolean equals(Object object) { // Paper if (this == object) { return true; } else if (!(object instanceof Vec3i)) { -@@ -53,7 +53,7 @@ public class Vec3i implements Comparable { - } +@@ -59,7 +59,7 @@ public class Vec3i implements Comparable { } + @Override - public int hashCode() { + public final int hashCode() { // Paper return (this.getY() + this.getZ() * 31) * 31 + this.getX(); } -@@ -61,15 +61,15 @@ public class Vec3i implements Comparable { - return this.getY() == baseblockposition.getY() ? (this.getZ() == baseblockposition.getZ() ? this.getX() - baseblockposition.getX() : this.getZ() - baseblockposition.getZ()) : this.getY() - baseblockposition.getY(); +@@ -72,15 +72,15 @@ public class Vec3i implements Comparable { + } } - public int getX() { diff --git a/patches/server-remapped/0247-Optimize-RegistryID.c.patch b/patches/server/0229-Optimize-IntIdentityHashBiMiap-nextId.patch similarity index 57% rename from patches/server-remapped/0247-Optimize-RegistryID.c.patch rename to patches/server/0229-Optimize-IntIdentityHashBiMiap-nextId.patch index e8d895a808..9eeaac8ad2 100644 --- a/patches/server-remapped/0247-Optimize-RegistryID.c.patch +++ b/patches/server/0229-Optimize-IntIdentityHashBiMiap-nextId.patch @@ -1,39 +1,38 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Mon, 23 Jul 2018 13:08:19 -0400 -Subject: [PATCH] Optimize RegistryID.c() +Subject: [PATCH] Optimize IntIdentityHashBiMiap#nextId() + +Optimizes CrudeIncrementalIntIdentityHashBiMap#nextId() This is a frequent hotspot for world loading/saving. diff --git a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java -index 66ad412e4368a8615cc66a97ac442c572813a3dd..fa4a2d29b3b4c20d7396e973801d69c4acadddda 100644 +index feaa9572a450b88a26659d850a269d09465259ee..62440dbb35263cddc90ba594c3d5777d7643e527 100644 --- a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java +++ b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java -@@ -15,12 +15,14 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { +@@ -16,12 +16,14 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { private K[] byId; private int nextId; private int size; + private java.util.BitSet usedIds; // Paper public CrudeIncrementalIntIdentityHashBiMap(int size) { - size = (int) ((float) size / 0.8F); - this.keys = (K[]) (new Object[size]); // Paper - decompile fix + size = (int)((float)size / 0.8F); + this.keys = (K[])(new Object[size]); this.values = new int[size]; - this.byId = (K[]) (new Object[size]); // Paper - decompile fix + this.byId = (K[])(new Object[size]); + this.usedIds = new java.util.BitSet(); // Paper } - // Paper start - decompile fix -@@ -52,9 +54,14 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + @Override +@@ -54,9 +56,13 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { } private int nextId() { -- while (this.nextId < this.byId.length && this.byId[this.nextId] != null) { -- ++this.nextId; -+ // Paper start -+ /* -+ while (this.e < this.d.length && this.d[this.e] != null) { -+ ++this.e; ++ /* // Paper start + while(this.nextId < this.byId.length && this.byId[this.nextId] != null) { + ++this.nextId; } + */ + this.nextId = this.usedIds.nextClearBit(0); @@ -41,15 +40,15 @@ index 66ad412e4368a8615cc66a97ac442c572813a3dd..fa4a2d29b3b4c20d7396e973801d69c4 return this.nextId; } -@@ -68,6 +75,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { - this.byId = (K[]) (new Object[newSize]); // Paper - decompile fix +@@ -69,6 +75,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + this.byId = (K[])(new Object[newSize]); this.nextId = 0; this.size = 0; + this.usedIds.clear(); // Paper - for (int j = 0; j < ak.length; ++j) { - if (ak[j] != null) { -@@ -93,6 +101,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + for(int i = 0; i < objects.length; ++i) { + if (objects[i] != null) { +@@ -92,6 +99,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { this.keys[k] = value; this.values[k] = id; this.byId[id] = value; @@ -57,8 +56,8 @@ index 66ad412e4368a8615cc66a97ac442c572813a3dd..fa4a2d29b3b4c20d7396e973801d69c4 ++this.size; if (id == this.nextId) { ++this.nextId; -@@ -157,6 +166,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { - Arrays.fill(this.byId, (Object) null); +@@ -153,6 +161,7 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + Arrays.fill(this.byId, (Object)null); this.nextId = 0; this.size = 0; + this.usedIds.clear(); // Paper diff --git a/patches/server-remapped/0248-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/patches/server/0230-Option-to-prevent-armor-stands-from-doing-entity-loo.patch similarity index 69% rename from patches/server-remapped/0248-Option-to-prevent-armor-stands-from-doing-entity-loo.patch rename to patches/server/0230-Option-to-prevent-armor-stands-from-doing-entity-loo.patch index f39334e396..7e1ddc6588 100644 --- a/patches/server-remapped/0248-Option-to-prevent-armor-stands-from-doing-entity-loo.patch +++ b/patches/server/0230-Option-to-prevent-armor-stands-from-doing-entity-loo.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Option to prevent armor stands from doing entity lookups diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4813f62d1e382d5ac6971b2244df3f13c80d1950..3562950df4868b1393790b1a1ff1fe0dc589c155 100644 +index 8f8a3ea51823a9cfba985efeb7e320ae42e0da8a..1f6b37bd3cbc825abab5ad2f673200ef5061746a 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -379,4 +379,9 @@ public class PaperWorldConfig { +@@ -373,4 +373,9 @@ public class PaperWorldConfig { private void scanForLegacyEnderDragon() { scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); } @@ -19,10 +19,10 @@ index 4813f62d1e382d5ac6971b2244df3f13c80d1950..3562950df4868b1393790b1a1ff1fe0d + } } diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 59239e202e8e99870ce3be515d2f040ad9786892..7fc69adc8afa971ee3cf815c6002628ae2149a5b 100644 +index cda073a8ab9daed75f284cbbe4459991fba348f0..449f9b87ea6ff313f7e0e9104a641f1bf7729f24 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -352,6 +352,7 @@ public class ArmorStand extends LivingEntity { +@@ -339,6 +339,7 @@ public class ArmorStand extends LivingEntity { @Override protected void pushEntities() { @@ -31,25 +31,17 @@ index 59239e202e8e99870ce3be515d2f040ad9786892..7fc69adc8afa971ee3cf815c6002628a for (int i = 0; i < list.size(); ++i) { diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 0c6c3b211b05eda8f9ab47ef0a01cc520ae28201..7b135a3951bc168ccebdbb4e3acdc07397a820d3 100644 +index 8859b0483ca71e1a36c164f7d386684540f0bf18..2c86a5ae8bbf7d80e7ce8cd08319ed6a17b86dbb 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -39,6 +39,7 @@ import net.minecraft.world.DifficultyInstance; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.entity.decoration.ArmorStand; - import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; -@@ -854,6 +855,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -767,6 +767,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { // Paper end } } + // Paper start - Prevent armor stands from doing entity lookups + @Override + public boolean noCollision(@Nullable Entity entity, AABB box) { -+ if (entity instanceof ArmorStand && !entity.level.paperConfig.armorStandEntityLookups) return false; ++ if (entity instanceof net.minecraft.world.entity.decoration.ArmorStand && !entity.level.paperConfig.armorStandEntityLookups) return false; + return LevelAccessor.super.noCollision(entity, box); + } + // Paper end diff --git a/patches/server/0231-Vanished-players-don-t-have-rights.patch b/patches/server/0231-Vanished-players-don-t-have-rights.patch new file mode 100644 index 0000000000..8e9dcb152a --- /dev/null +++ b/patches/server/0231-Vanished-players-don-t-have-rights.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Manrique +Date: Mon, 23 Jul 2018 14:22:26 +0200 +Subject: [PATCH] Vanished players don't have rights + + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index c25cb17ef1a7c56e10ce3ccb5665c9dce3e6efa6..30118ff975da9491fa41db2133d217c2a797a8e3 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -209,7 +209,14 @@ public abstract class Projectile extends Entity { + if (!entity.isSpectator() && entity.isAlive() && entity.isPickable()) { + Entity entity1 = this.getOwner(); + ++ // Paper start - Cancel hit for vanished players ++ if (entity1 instanceof net.minecraft.server.level.ServerPlayer && entity instanceof net.minecraft.server.level.ServerPlayer) { ++ org.bukkit.entity.Player collided = (org.bukkit.entity.Player) entity.getBukkitEntity(); ++ org.bukkit.entity.Player shooter = (org.bukkit.entity.Player) entity1.getBukkitEntity(); ++ if (!shooter.canSee(collided)) return false; ++ } + return entity1 == null || this.leftOwner || !entity1.isPassengerOfSameVehicle(entity); ++ // Paper end + } else { + return false; + } +diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java +index 86d245c9a817be5fd2be7f331d3a3a5f3169e8c2..44b28773fe8e79931e738d493bd9405e0ee3dca9 100644 +--- a/src/main/java/net/minecraft/world/item/BlockItem.java ++++ b/src/main/java/net/minecraft/world/item/BlockItem.java +@@ -191,7 +191,8 @@ public class BlockItem extends Item { + Player entityhuman = context.getPlayer(); + CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of((Entity) entityhuman); + // CraftBukkit start - store default return +- boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision); ++ Level world = context.getLevel(); // Paper ++ boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && world.checkEntityCollision(state, entityhuman, voxelshapecollision, context.getClickedPos(), true); // Paper + org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; + + BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 2c86a5ae8bbf7d80e7ce8cd08319ed6a17b86dbb..c1cf7f5bff2878281d4a9787ea7160e984268352 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -71,6 +71,10 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + import net.minecraft.world.level.storage.LevelData; + import net.minecraft.world.level.storage.WritableLevelData; + import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.shapes.BooleanOp; ++import net.minecraft.world.phys.shapes.CollisionContext; ++import net.minecraft.world.phys.shapes.Shapes; ++import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.scores.Scoreboard; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -248,6 +252,45 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + } + ++ // Paper start ++ // ret true if no collision ++ public final boolean checkEntityCollision(BlockState data, Entity source, CollisionContext voxelshapedcollision, ++ BlockPos position, boolean checkCanSee) { ++ // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape) ++ VoxelShape voxelshape = data.getCollisionShape(this, position, voxelshapedcollision); ++ if (voxelshape.isEmpty()) { ++ return true; ++ } ++ ++ voxelshape = voxelshape.move((double) position.getX(), (double) position.getY(), (double) position.getZ()); ++ if (voxelshape.isEmpty()) { ++ return true; ++ } ++ ++ List entities = this.getEntities(null, voxelshape.bounds()); ++ for (int i = 0, len = entities.size(); i < len; ++i) { ++ Entity entity = entities.get(i); ++ ++ if (checkCanSee && source instanceof net.minecraft.server.level.ServerPlayer && entity instanceof net.minecraft.server.level.ServerPlayer ++ && !((net.minecraft.server.level.ServerPlayer) source).getBukkitEntity().canSee(((net.minecraft.server.level.ServerPlayer) entity).getBukkitEntity())) { ++ continue; ++ } ++ ++ // !entity1.dead && entity1.i && (entity == null || !entity1.x(entity)); ++ // elide the last check since vanilla calls with entity = null ++ // only we care about the source for the canSee check ++ if (entity.isRemoved() || !entity.blocksBuilding) { ++ continue; ++ } ++ ++ if (Shapes.joinIsNotEmpty(voxelshape, Shapes.create(entity.getBoundingBox()), BooleanOp.AND)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ // Paper end + @Override + 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 375e9e45331d5be237c67f11af94c6998409418b..966d06e2da7e6f9b4e78ca8ed02f3a6472bc8c05 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1190,6 +1190,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); ++ ++ if (projectile.getShooter() instanceof Player && collided instanceof Player) { ++ if (!((Player) projectile.getShooter()).canSee((Player) collided)) { ++ event.setCancelled(true); ++ return event; ++ } ++ } ++ + Bukkit.getPluginManager().callEvent(event); + return event; + } From 0c2d1544ac97a6c9a6060ee6bc1599aa673a28a1 Mon Sep 17 00:00:00 2001 From: mechoriet Date: Sat, 12 Jun 2021 23:34:05 +0200 Subject: [PATCH 053/226] gradlew.bat crlf fix (#5810) --- gradlew.bat | 178 ++++++++++++++++++++++++++-------------------------- 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/gradlew.bat b/gradlew.bat index ac1b06f938..107acd32c4 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,89 +1,89 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega From 2ba2c29b2ebd35a12d4f49ad6930feb9b0787430 Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Sat, 12 Jun 2021 16:45:00 -0700 Subject: [PATCH 054/226] more patches (#5811) --- .../0125-EntityTransformedEvent.patch} | 0 ...llow-disabling-armour-stand-ticking.patch} | 2 +- .../0127-SkeletonHorse-Additions.patch} | 0 ...28-Expand-Location-Manipulation-API.patch} | 0 .../0129-Expand-ArmorStand-API.patch} | 2 +- .../0130-AnvilDamageEvent.patch} | 0 ...eadlock-risk-in-firing-async-events.patch} | 15 +- .../0132-Add-hand-to-bucket-events.patch} | 0 .../0133-Add-TNTPrimeEvent.patch} | 0 ...ide-Chunk-Coordinates-as-a-Long-API.patch} | 2 +- .../0135-Make-EnderDragon-extend-Mob.patch} | 0 ...le-Entities-from-a-chunk-without-sn.patch} | 0 ...ots-for-Timings-Tile-Entity-reports.patch} | 0 ...locks-to-be-accessed-via-a-long-key.patch} | 4 +- .../0139-Slime-Pathfinder-Events.patch} | 0 .../0140-Add-PhantomPreSpawnEvent.patch} | 0 .../0141-Add-More-Creeper-API.patch} | 0 .../0142-isChunkGenerated-API.patch} | 12 +- ...d-source-block-to-BlockPhysicsEvent.patch} | 0 .../0144-Inventory-removeItemAnySlot.patch} | 0 ...-anytime-entities-change-to-guarante.patch | 1 + ...dd-some-Debug-to-Chunk-Entity-slices.patch | 2 + ...revent-Saving-Bad-entities-to-chunks.patch | 2 + ...ead-Entities-in-entityList-iteration.patch | 2 + .../0260-Add-hand-to-bucket-events.patch | 341 ------------------ ...6-Experience-should-save-as-Integers.patch | 28 -- .../0271-Slime-Pathfinder-Events.patch | 229 ------------ .../0274-Optimize-RegistryMaterials.patch | 96 ----- ...llow-disabling-armour-stand-ticking.patch} | 83 ++--- .../0233-SkeletonHorse-Additions.patch} | 76 +--- ...n-t-call-getItemMeta-on-hasItemMeta.patch} | 12 +- ...5-Implement-Expanded-ArmorStand-API.patch} | 24 +- .../0236-AnvilDamageEvent.patch} | 9 +- .../0237-Add-hand-to-bucket-events.patch | 196 ++++++++++ .../0238-Add-TNTPrimeEvent.patch} | 87 ++--- ...d-make-tab-spam-limits-configurable.patch} | 24 +- ...6-Experience-should-save-as-Integers.patch | 28 ++ ...ent-rendering-skulls-from-same-user.patch} | 64 ++-- ...d-Early-Warning-Feature-to-WatchDog.patch} | 52 ++- ...0243-Make-EnderDragon-implement-Mob.patch} | 0 ...4-Use-ConcurrentHashMap-in-JsonList.patch} | 26 +- ...5-Use-a-Queue-for-Queueing-Commands.patch} | 10 +- ...le-Entities-from-a-chunk-without-sn.patch} | 27 +- ...timize-BlockPosition-helper-methods.patch} | 22 +- ...fault-mob-spawn-range-and-water-ani.patch} | 8 +- .../server/0249-Slime-Pathfinder-Events.patch | 167 +++++++++ ...e-speed-for-water-flowing-over-lava.patch} | 27 +- ...51-Optimize-CraftBlockData-Creation.patch} | 10 +- .../server/0252-Optimize-MappedRegistry.patch | 35 ++ .../0253-Add-PhantomPreSpawnEvent.patch} | 32 +- .../0254-Add-More-Creeper-API.patch} | 10 +- .../0255-Inventory-removeItemAnySlot.patch} | 10 +- ...oadChunk-int-int-false-load-unconve.patch} | 8 +- 53 files changed, 711 insertions(+), 1074 deletions(-) rename patches/{api-unmapped/0123-EntityTransformedEvent.patch => api/0125-EntityTransformedEvent.patch} (100%) rename patches/{api-unmapped/0124-Allow-disabling-armour-stand-ticking.patch => api/0126-Allow-disabling-armour-stand-ticking.patch} (91%) rename patches/{api-unmapped/0125-SkeletonHorse-Additions.patch => api/0127-SkeletonHorse-Additions.patch} (100%) rename patches/{api-unmapped/0126-Expand-Location-Manipulation-API.patch => api/0128-Expand-Location-Manipulation-API.patch} (100%) rename patches/{api-unmapped/0127-Expand-ArmorStand-API.patch => api/0129-Expand-ArmorStand-API.patch} (97%) rename patches/{api-unmapped/0128-AnvilDamageEvent.patch => api/0130-AnvilDamageEvent.patch} (100%) rename patches/{api-unmapped/0129-Remove-deadlock-risk-in-firing-async-events.patch => api/0131-Remove-deadlock-risk-in-firing-async-events.patch} (86%) rename patches/{api-unmapped/0130-Add-hand-to-bucket-events.patch => api/0132-Add-hand-to-bucket-events.patch} (100%) rename patches/{api-unmapped/0131-Add-TNTPrimeEvent.patch => api/0133-Add-TNTPrimeEvent.patch} (100%) rename patches/{api-unmapped/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch => api/0134-Provide-Chunk-Coordinates-as-a-Long-API.patch} (96%) rename patches/{api-unmapped/0134-Make-EnderDragon-extend-Mob.patch => api/0135-Make-EnderDragon-extend-Mob.patch} (100%) rename patches/{api-unmapped/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch => api/0136-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch} (100%) rename patches/{api-unmapped/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch => api/0137-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch} (100%) rename patches/{api-unmapped/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch => api/0138-Allow-Blocks-to-be-accessed-via-a-long-key.patch} (96%) rename patches/{api-unmapped/0138-Slime-Pathfinder-Events.patch => api/0139-Slime-Pathfinder-Events.patch} (100%) rename patches/{api-unmapped/0141-Add-PhantomPreSpawnEvent.patch => api/0140-Add-PhantomPreSpawnEvent.patch} (100%) rename patches/{api-unmapped/0140-Add-More-Creeper-API.patch => api/0141-Add-More-Creeper-API.patch} (100%) rename patches/{api-unmapped/0139-isChunkGenerated-API.patch => api/0142-isChunkGenerated-API.patch} (88%) rename patches/{api-unmapped/0142-Add-source-block-to-BlockPhysicsEvent.patch => api/0143-Add-source-block-to-BlockPhysicsEvent.patch} (100%) rename patches/{api-unmapped/0143-Inventory-removeItemAnySlot.patch => api/0144-Inventory-removeItemAnySlot.patch} (100%) rename patches/{server-remapped => removed/1.17}/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch (98%) rename patches/{server-remapped => removed/1.17}/0251-Add-some-Debug-to-Chunk-Entity-slices.patch (99%) rename patches/{server-remapped => removed/1.17}/0253-Prevent-Saving-Bad-entities-to-chunks.patch (99%) rename patches/{server-remapped => removed/1.17}/0255-Ignore-Dead-Entities-in-entityList-iteration.patch (99%) delete mode 100644 patches/server-remapped/0260-Add-hand-to-bucket-events.patch delete mode 100644 patches/server-remapped/0261-MC-135506-Experience-should-save-as-Integers.patch delete mode 100644 patches/server-remapped/0271-Slime-Pathfinder-Events.patch delete mode 100644 patches/server-remapped/0274-Optimize-RegistryMaterials.patch rename patches/{server-remapped/0268-Allow-disabling-armour-stand-ticking.patch => server/0232-Allow-disabling-armour-stand-ticking.patch} (63%) rename patches/{server-remapped/0252-SkeletonHorse-Additions.patch => server/0233-SkeletonHorse-Additions.patch} (56%) rename patches/{server-remapped/0254-Don-t-call-getItemMeta-on-hasItemMeta.patch => server/0234-Don-t-call-getItemMeta-on-hasItemMeta.patch} (79%) rename patches/{server-remapped/0256-Implement-Expanded-ArmorStand-API.patch => server/0235-Implement-Expanded-ArmorStand-API.patch} (85%) rename patches/{server-remapped/0257-AnvilDamageEvent.patch => server/0236-AnvilDamageEvent.patch} (83%) create mode 100644 patches/server/0237-Add-hand-to-bucket-events.patch rename patches/{server-remapped/0258-Add-TNTPrimeEvent.patch => server/0238-Add-TNTPrimeEvent.patch} (56%) rename patches/{server-remapped/0259-Break-up-and-make-tab-spam-limits-configurable.patch => server/0239-Break-up-and-make-tab-spam-limits-configurable.patch} (76%) create mode 100644 patches/server/0240-MC-135506-Experience-should-save-as-Integers.patch rename patches/{server-remapped/0262-Fix-client-rendering-skulls-from-same-user.patch => server/0241-Fix-client-rendering-skulls-from-same-user.patch} (67%) rename patches/{server-remapped/0263-Add-Early-Warning-Feature-to-WatchDog.patch => server/0242-Add-Early-Warning-Feature-to-WatchDog.patch} (78%) rename patches/{server-remapped/0264-Make-EnderDragon-implement-Mob.patch => server/0243-Make-EnderDragon-implement-Mob.patch} (100%) rename patches/{server-remapped/0265-Use-ConcurrentHashMap-in-JsonList.patch => server/0244-Use-ConcurrentHashMap-in-JsonList.patch} (84%) rename patches/{server-remapped/0266-Use-a-Queue-for-Queueing-Commands.patch => server/0245-Use-a-Queue-for-Queueing-Commands.patch} (84%) rename patches/{server-remapped/0267-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch => server/0246-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch} (71%) rename patches/{server-remapped/0269-Optimize-BlockPosition-helper-methods.patch => server/0247-Optimize-BlockPosition-helper-methods.patch} (86%) rename patches/{server-remapped/0270-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch => server/0248-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch} (76%) create mode 100644 patches/server/0249-Slime-Pathfinder-Events.patch rename patches/{server-remapped/0272-Configurable-speed-for-water-flowing-over-lava.patch => server/0250-Configurable-speed-for-water-flowing-over-lava.patch} (69%) rename patches/{server-remapped/0273-Optimize-CraftBlockData-Creation.patch => server/0251-Optimize-CraftBlockData-Creation.patch} (84%) create mode 100644 patches/server/0252-Optimize-MappedRegistry.patch rename patches/{server-remapped/0275-Add-PhantomPreSpawnEvent.patch => server/0253-Add-PhantomPreSpawnEvent.patch} (81%) rename patches/{server-remapped/0276-Add-More-Creeper-API.patch => server/0254-Add-More-Creeper-API.patch} (82%) rename patches/{server-remapped/0277-Inventory-removeItemAnySlot.patch => server/0255-Inventory-removeItemAnySlot.patch} (85%) rename patches/{server-remapped/0278-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch => server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch} (63%) diff --git a/patches/api-unmapped/0123-EntityTransformedEvent.patch b/patches/api/0125-EntityTransformedEvent.patch similarity index 100% rename from patches/api-unmapped/0123-EntityTransformedEvent.patch rename to patches/api/0125-EntityTransformedEvent.patch diff --git a/patches/api-unmapped/0124-Allow-disabling-armour-stand-ticking.patch b/patches/api/0126-Allow-disabling-armour-stand-ticking.patch similarity index 91% rename from patches/api-unmapped/0124-Allow-disabling-armour-stand-ticking.patch rename to patches/api/0126-Allow-disabling-armour-stand-ticking.patch index 30f0bf5227..bb053752f5 100644 --- a/patches/api-unmapped/0124-Allow-disabling-armour-stand-ticking.patch +++ b/patches/api/0126-Allow-disabling-armour-stand-ticking.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Allow disabling armour stand ticking diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java -index fddc063798edc8084ca695578a47485204a7f3cd..365d3a3c5fc4a47efe56225ef1eb87b5046034f4 100644 +index de9ddd2c40261486ee8de6693d118cffaa2dd793..575f48213cd8df038e41bead4c9d0fcba717f40f 100644 --- a/src/main/java/org/bukkit/entity/ArmorStand.java +++ b/src/main/java/org/bukkit/entity/ArmorStand.java @@ -360,5 +360,21 @@ public interface ArmorStand extends LivingEntity { diff --git a/patches/api-unmapped/0125-SkeletonHorse-Additions.patch b/patches/api/0127-SkeletonHorse-Additions.patch similarity index 100% rename from patches/api-unmapped/0125-SkeletonHorse-Additions.patch rename to patches/api/0127-SkeletonHorse-Additions.patch diff --git a/patches/api-unmapped/0126-Expand-Location-Manipulation-API.patch b/patches/api/0128-Expand-Location-Manipulation-API.patch similarity index 100% rename from patches/api-unmapped/0126-Expand-Location-Manipulation-API.patch rename to patches/api/0128-Expand-Location-Manipulation-API.patch diff --git a/patches/api-unmapped/0127-Expand-ArmorStand-API.patch b/patches/api/0129-Expand-ArmorStand-API.patch similarity index 97% rename from patches/api-unmapped/0127-Expand-ArmorStand-API.patch rename to patches/api/0129-Expand-ArmorStand-API.patch index 036951f69d..c57b85b936 100644 --- a/patches/api-unmapped/0127-Expand-ArmorStand-API.patch +++ b/patches/api/0129-Expand-ArmorStand-API.patch @@ -8,7 +8,7 @@ Add the following: - Enable/Disable slot interactions diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java -index 365d3a3c5fc4a47efe56225ef1eb87b5046034f4..8ca6c9eba926f436203af211c6e274a59ddb15e8 100644 +index 575f48213cd8df038e41bead4c9d0fcba717f40f..2f0c6af7fa6688a98d6aa0bd3f0e6556af8330d0 100644 --- a/src/main/java/org/bukkit/entity/ArmorStand.java +++ b/src/main/java/org/bukkit/entity/ArmorStand.java @@ -13,7 +13,7 @@ public interface ArmorStand extends LivingEntity { diff --git a/patches/api-unmapped/0128-AnvilDamageEvent.patch b/patches/api/0130-AnvilDamageEvent.patch similarity index 100% rename from patches/api-unmapped/0128-AnvilDamageEvent.patch rename to patches/api/0130-AnvilDamageEvent.patch diff --git a/patches/api-unmapped/0129-Remove-deadlock-risk-in-firing-async-events.patch b/patches/api/0131-Remove-deadlock-risk-in-firing-async-events.patch similarity index 86% rename from patches/api-unmapped/0129-Remove-deadlock-risk-in-firing-async-events.patch rename to patches/api/0131-Remove-deadlock-risk-in-firing-async-events.patch index 2725c79f2e..27e5ca7dfe 100644 --- a/patches/api-unmapped/0129-Remove-deadlock-risk-in-firing-async-events.patch +++ b/patches/api/0131-Remove-deadlock-risk-in-firing-async-events.patch @@ -15,21 +15,8 @@ which results in a hard crash. This change removes the synchronize and adds some protection around enable/disable -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 9b8823279524d1c1566176c589aa5794eb8aafbc..707638c327077a74c777a603b9f2392f46b51c0c 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable; - */ - public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource { // Paper - -- /** -+ /* - * Gets the entity's current position - * - * @return a new copy of Location containing the position of this entity diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index a7393d2830b95d7167121b02066a3f357cee6085..a1a805004941d67abb0b9aa1721e0370c45b5289 100644 +index 892ec4b43cc97a235df0819d30391a8a3770cbcb..b83637f872be5fc73500b10c917d71802976b340 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -462,7 +462,7 @@ public final class SimplePluginManager implements PluginManager { diff --git a/patches/api-unmapped/0130-Add-hand-to-bucket-events.patch b/patches/api/0132-Add-hand-to-bucket-events.patch similarity index 100% rename from patches/api-unmapped/0130-Add-hand-to-bucket-events.patch rename to patches/api/0132-Add-hand-to-bucket-events.patch diff --git a/patches/api-unmapped/0131-Add-TNTPrimeEvent.patch b/patches/api/0133-Add-TNTPrimeEvent.patch similarity index 100% rename from patches/api-unmapped/0131-Add-TNTPrimeEvent.patch rename to patches/api/0133-Add-TNTPrimeEvent.patch diff --git a/patches/api-unmapped/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch b/patches/api/0134-Provide-Chunk-Coordinates-as-a-Long-API.patch similarity index 96% rename from patches/api-unmapped/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch rename to patches/api/0134-Provide-Chunk-Coordinates-as-a-Long-API.patch index 3616f82f03..17690209af 100644 --- a/patches/api-unmapped/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch +++ b/patches/api/0134-Provide-Chunk-Coordinates-as-a-Long-API.patch @@ -44,7 +44,7 @@ index beac1439c71fb28f1a3baecf56157237e12ccfd5..fa576096e908f8fbdbef53e1bd91215a * Gets the world containing this chunk * diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 9c4f2d9e1a4011e3a9860d913e1a718030696bed..e372b3d43960ac7df58985609ef729c68fca0533 100644 +index a7bd869fb5b8e35274eee0d8dae9dd6fe3c1c540..85c9ea1241d580386be00fb85ea1446addd376c4 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -207,6 +207,22 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad diff --git a/patches/api-unmapped/0134-Make-EnderDragon-extend-Mob.patch b/patches/api/0135-Make-EnderDragon-extend-Mob.patch similarity index 100% rename from patches/api-unmapped/0134-Make-EnderDragon-extend-Mob.patch rename to patches/api/0135-Make-EnderDragon-extend-Mob.patch diff --git a/patches/api-unmapped/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/patches/api/0136-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch similarity index 100% rename from patches/api-unmapped/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch rename to patches/api/0136-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch diff --git a/patches/api-unmapped/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch b/patches/api/0137-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch similarity index 100% rename from patches/api-unmapped/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch rename to patches/api/0137-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch diff --git a/patches/api-unmapped/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch b/patches/api/0138-Allow-Blocks-to-be-accessed-via-a-long-key.patch similarity index 96% rename from patches/api-unmapped/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch rename to patches/api/0138-Allow-Blocks-to-be-accessed-via-a-long-key.patch index 568d6bcd6e..d9fc1f8e59 100644 --- a/patches/api-unmapped/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch +++ b/patches/api/0138-Allow-Blocks-to-be-accessed-via-a-long-key.patch @@ -48,7 +48,7 @@ index 369ce9ff6c8bb97a64a8e229115564412e6e7654..e700875beb76dadd55b585aca748338d * @return A new location where X/Y/Z are the center of the block */ diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 3f231c28842f02f80fd3136c36fe99b41726137f..d8674c773d61517f79d0fe77276392e47fd3e1e1 100644 +index 85c9ea1241d580386be00fb85ea1446addd376c4..4f563c6afc3568a5a45594bcc87790eeefc4148d 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -90,6 +90,38 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad @@ -91,7 +91,7 @@ index 3f231c28842f02f80fd3136c36fe99b41726137f..d8674c773d61517f79d0fe77276392e4 * Gets the highest non-empty (impassable) coordinate at the given * coordinates. diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index e89c8079625525667f496c06207da655fe43d749..d6f74dbcfeb153d4b17be2827e2989f2d8160d21 100644 +index 969a6cf404d99c186e73321659240195b8650ffc..b090938f883c486e703cb7c036c47925f3016704 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java @@ -153,6 +153,72 @@ public interface Block extends Metadatable { diff --git a/patches/api-unmapped/0138-Slime-Pathfinder-Events.patch b/patches/api/0139-Slime-Pathfinder-Events.patch similarity index 100% rename from patches/api-unmapped/0138-Slime-Pathfinder-Events.patch rename to patches/api/0139-Slime-Pathfinder-Events.patch diff --git a/patches/api-unmapped/0141-Add-PhantomPreSpawnEvent.patch b/patches/api/0140-Add-PhantomPreSpawnEvent.patch similarity index 100% rename from patches/api-unmapped/0141-Add-PhantomPreSpawnEvent.patch rename to patches/api/0140-Add-PhantomPreSpawnEvent.patch diff --git a/patches/api-unmapped/0140-Add-More-Creeper-API.patch b/patches/api/0141-Add-More-Creeper-API.patch similarity index 100% rename from patches/api-unmapped/0140-Add-More-Creeper-API.patch rename to patches/api/0141-Add-More-Creeper-API.patch diff --git a/patches/api-unmapped/0139-isChunkGenerated-API.patch b/patches/api/0142-isChunkGenerated-API.patch similarity index 88% rename from patches/api-unmapped/0139-isChunkGenerated-API.patch rename to patches/api/0142-isChunkGenerated-API.patch index a26301e9c3..ce9303e154 100644 --- a/patches/api-unmapped/0139-isChunkGenerated-API.patch +++ b/patches/api/0142-isChunkGenerated-API.patch @@ -34,13 +34,14 @@ index e700875beb76dadd55b585aca748338def286908..9c91c49ed7302c12fcb1d8e9bc58712e /** * Sets the position of this Location and returns itself diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index d8674c773d61517f79d0fe77276392e47fd3e1e1..cf831f96efa302f789cf26a384a091df51215a76 100644 +index 4f563c6afc3568a5a45594bcc87790eeefc4148d..868e34482a3a5773dfbdc80b36adcee25239614a 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java -@@ -254,6 +254,17 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad +@@ -253,6 +253,17 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + public default Chunk getChunkAt(long chunkKey) { return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); } - ++ + /** + * Checks if a {@link Chunk} has been generated at the specified chunk key, + * which is the X and Z packed into a long. @@ -51,7 +52,6 @@ index d8674c773d61517f79d0fe77276392e47fd3e1e1..cf831f96efa302f789cf26a384a091df + public default boolean isChunkGenerated(long chunkKey) { + return isChunkGenerated((int) chunkKey, (int) (chunkKey >> 32)); + } -+ + // Paper end + /** - * This is the Legacy API before Java 8 was supported. Java 8 Consumer is provided, - * as well as future support diff --git a/patches/api-unmapped/0142-Add-source-block-to-BlockPhysicsEvent.patch b/patches/api/0143-Add-source-block-to-BlockPhysicsEvent.patch similarity index 100% rename from patches/api-unmapped/0142-Add-source-block-to-BlockPhysicsEvent.patch rename to patches/api/0143-Add-source-block-to-BlockPhysicsEvent.patch diff --git a/patches/api-unmapped/0143-Inventory-removeItemAnySlot.patch b/patches/api/0144-Inventory-removeItemAnySlot.patch similarity index 100% rename from patches/api-unmapped/0143-Inventory-removeItemAnySlot.patch rename to patches/api/0144-Inventory-removeItemAnySlot.patch diff --git a/patches/server-remapped/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch b/patches/removed/1.17/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch similarity index 98% rename from patches/server-remapped/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch rename to patches/removed/1.17/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch index a8a2ab7437..802c1e0e25 100644 --- a/patches/server-remapped/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch +++ b/patches/removed/1.17/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch @@ -4,6 +4,7 @@ Date: Mon, 23 Jul 2018 22:18:31 -0400 Subject: [PATCH] Mark chunk dirty anytime entities change to guarantee it saves +Useless in 1.17 - leaf diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java index d69ccb1f31f31ebeee477df20ce1410f9e485eb7..bd9b19d988ecf72e099efeff6ec3483a352174ec 100644 diff --git a/patches/server-remapped/0251-Add-some-Debug-to-Chunk-Entity-slices.patch b/patches/removed/1.17/0251-Add-some-Debug-to-Chunk-Entity-slices.patch similarity index 99% rename from patches/server-remapped/0251-Add-some-Debug-to-Chunk-Entity-slices.patch rename to patches/removed/1.17/0251-Add-some-Debug-to-Chunk-Entity-slices.patch index 1978f629cd..562e663109 100644 --- a/patches/server-remapped/0251-Add-some-Debug-to-Chunk-Entity-slices.patch +++ b/patches/removed/1.17/0251-Add-some-Debug-to-Chunk-Entity-slices.patch @@ -8,6 +8,8 @@ If we detect unexpected state, log and try to recover This should hopefully avoid duplicate entities ever being created if the entity was to end up in 2 different chunk slices +Useless in 1.17 + diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index a2cc3e58d59ed3d9f443b77c44d8200cc09b4da9..7847078c54154e28ab066ea8a329f929df1e1a37 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java diff --git a/patches/server-remapped/0253-Prevent-Saving-Bad-entities-to-chunks.patch b/patches/removed/1.17/0253-Prevent-Saving-Bad-entities-to-chunks.patch similarity index 99% rename from patches/server-remapped/0253-Prevent-Saving-Bad-entities-to-chunks.patch rename to patches/removed/1.17/0253-Prevent-Saving-Bad-entities-to-chunks.patch index 946c608327..bf9a9d15a4 100644 --- a/patches/server-remapped/0253-Prevent-Saving-Bad-entities-to-chunks.patch +++ b/patches/removed/1.17/0253-Prevent-Saving-Bad-entities-to-chunks.patch @@ -17,6 +17,8 @@ an invalid entity. This should reduce log occurrences of dupe uuid messages. +1.17, not a concern anymore + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index a5d7781b13a6d61238d026f064512f7162e1e868..8e8e5f30c512ed7d8ee987550c22d3e9df845043 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/server-remapped/0255-Ignore-Dead-Entities-in-entityList-iteration.patch b/patches/removed/1.17/0255-Ignore-Dead-Entities-in-entityList-iteration.patch similarity index 99% rename from patches/server-remapped/0255-Ignore-Dead-Entities-in-entityList-iteration.patch rename to patches/removed/1.17/0255-Ignore-Dead-Entities-in-entityList-iteration.patch index ae6ea8935e..b80a13b2b7 100644 --- a/patches/server-remapped/0255-Ignore-Dead-Entities-in-entityList-iteration.patch +++ b/patches/removed/1.17/0255-Ignore-Dead-Entities-in-entityList-iteration.patch @@ -10,6 +10,8 @@ methods will return dead entities that they shouldn't otherwise be doing. This will ensure that dead entities are skipped from iteration since they shouldn't of been in the list in the first place. +Not relevant in 1.17 + diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java index e95b91cefb0374bd5bb57cc090f5ecd566d7a618..8fd716bf2e1402694798b8be03fd85821153be44 100644 --- a/src/main/java/com/destroystokyo/paper/PaperCommand.java diff --git a/patches/server-remapped/0260-Add-hand-to-bucket-events.patch b/patches/server-remapped/0260-Add-hand-to-bucket-events.patch deleted file mode 100644 index 80b6896fe7..0000000000 --- a/patches/server-remapped/0260-Add-hand-to-bucket-events.patch +++ /dev/null @@ -1,341 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Thu, 2 Aug 2018 08:44:35 -0500 -Subject: [PATCH] Add hand to bucket events - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index d34da1eb172a7dcda564680afecf3dc145bf09f3..125a75576442eaa4f1ff6dd153bdb31097497a3f 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -724,7 +724,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop cachedSingleHashSet; // Paper - - public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { -- super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); -+ super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); - this.respawnDimension = Level.OVERWORLD; - interactionManager.player = this; - this.gameMode = interactionManager; -@@ -254,7 +254,7 @@ public class ServerPlayer extends Player implements ContainerListener { - // Yes, this doesn't match Vanilla, but it's the best we can do for now. - // If this is an issue, PRs are welcome - public final BlockPos getSpawnPoint(ServerLevel worldserver) { -- BlockPos blockposition = worldserver.getSharedSpawnPos(); -+ BlockPos blockposition = worldserver.getSpawn(); - - if (worldserver.dimensionType().hasSkyLight() && worldserver.worldDataServer.getGameType() != GameType.ADVENTURE) { - int i = Math.max(0, this.server.getSpawnRadius(worldserver)); -@@ -291,7 +291,7 @@ public class ServerPlayer extends Player implements ContainerListener { - // CraftBukkit end - - private void fudgeSpawnLocation(ServerLevel world) { -- BlockPos blockposition = world.getSharedSpawnPos(); -+ BlockPos blockposition = world.getSpawn(); - - if (world.dimensionType().hasSkyLight() && world.worldDataServer.getGameType() != GameType.ADVENTURE) { // CraftBukkit - int i = Math.max(0, this.server.getSpawnRadius(world)); -@@ -464,7 +464,7 @@ public class ServerPlayer extends Player implements ContainerListener { - } - if (world == null || position == null) { - world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(); -- position = Vec3.atCenterOf(((ServerLevel) world).getSharedSpawnPos()); -+ position = Vec3.atCenterOf(((ServerLevel) world).getSpawn()); - } - this.level = world; - this.setPos(position.x(), position.y(), position.z()); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 51b1ce465d23b971f7e08a3175319a33183d0398..0bb397407b55bd1c464ac603ec4c189045aabbb2 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -808,7 +808,7 @@ public abstract class PlayerList { - entityplayer1.setShiftKeyDown(false); - - // entityplayer1.playerConnection.a(entityplayer1.locX(), entityplayer1.locY(), entityplayer1.locZ(), entityplayer1.yaw, entityplayer1.pitch); -- entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSharedSpawnPos(), worldserver1.getSharedSpawnAngle())); -+ entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSpawn(), worldserver1.getSharedSpawnAngle())); - entityplayer1.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); - entityplayer1.connection.send(new ClientboundSetExperiencePacket(entityplayer1.experienceProgress, entityplayer1.totalExperience, entityplayer1.experienceLevel)); - this.sendLevelInfo(entityplayer1, worldserver1); -@@ -1090,7 +1090,7 @@ public abstract class PlayerList { - - player.connection.send(new ClientboundSetBorderPacket(worldborder, ClientboundSetBorderPacket.Type.INITIALIZE)); - player.connection.send(new ClientboundSetTimePacket(world.getGameTime(), world.getDayTime(), world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); -- player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(world.getSharedSpawnPos(), world.getSharedSpawnAngle())); -+ player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(world.getSpawn(), world.getSharedSpawnAngle())); - if (world.isRaining()) { - // CraftBukkit start - handle player weather - // entityplayer.playerConnection.sendPacket(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.b, 0.0F)); -diff --git a/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java b/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java -index c283ea9528493fb95088870c84c6d6e3963aabb7..2633aca30601682a53b0236b94a12f0f18a87fc2 100644 ---- a/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java -+++ b/src/main/java/net/minecraft/server/rcon/RconConsoleSource.java -@@ -33,7 +33,7 @@ public class RconConsoleSource implements CommandSource { - public CommandSourceStack createCommandSourceStack() { - ServerLevel worldserver = this.server.overworld(); - -- return new CommandSourceStack(this, Vec3.atLowerCornerOf((Vec3i) worldserver.getSharedSpawnPos()), Vec2.ZERO, worldserver, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null); -+ return new CommandSourceStack(this, Vec3.atLowerCornerOf((Vec3i) worldserver.getSpawn()), Vec2.ZERO, worldserver, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null); - } - - // CraftBukkit start - Send a String -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 5bf6bc6a01ccde8a4d67b49293bb326cb09248d8..4503bd65b3454bad94bb7b869f4e72e3121d8a3d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2688,7 +2688,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - if (flag1) { - blockposition1 = ServerLevel.END_SPAWN_POINT; - } else { -- blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos()); -+ blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSpawn()); - } - // CraftBukkit start - CraftPortalEvent event = callPortalEvent(this, destination, blockposition1, PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); -diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java -index 90393bb196c0895f387259c2dccbb29e2ca11c87..9c67b603d4d0ee5cb7f86b25ed8754afaf9cf7b3 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Cow.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Cow.java -@@ -87,7 +87,7 @@ public class Cow extends Animal { - - if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) { - // CraftBukkit start - Got milk? -- org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET); -+ org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); // Paper - add enumHand - - if (event.isCancelled()) { - return InteractionResult.PASS; -diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java -index b426e155d13a1b2eb5ddb24a2d83cd7d1e92026b..d0e847e58483695d2af1c1410826bb25231cd6f6 100644 ---- a/src/main/java/net/minecraft/world/item/BucketItem.java -+++ b/src/main/java/net/minecraft/world/item/BucketItem.java -@@ -69,7 +69,7 @@ public class BucketItem extends Item { - if (iblockdata.getBlock() instanceof BucketPickup) { - // CraftBukkit start - Fluid dummyFluid = ((BucketPickup) iblockdata.getBlock()).takeLiquid(DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); -- PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getBucket()); -+ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getBucket(), hand); // Paper - add enumhand - - if (event.isCancelled()) { - ((ServerPlayer) user).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) -@@ -97,7 +97,7 @@ public class BucketItem extends Item { - iblockdata = world.getBlockState(blockposition); - BlockPos blockposition2 = iblockdata.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockposition : blockposition1; - -- if (this.a(user, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack)) { // CraftBukkit -+ if (this.a(user, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack, hand)) { // CraftBukkit // Paper - add enumhand - this.checkExtraContent(world, itemstack, blockposition2); - if (user instanceof ServerPlayer) { - CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) user, blockposition2, itemstack); -@@ -122,10 +122,12 @@ public class BucketItem extends Item { - public void checkExtraContent(Level world, ItemStack stack, BlockPos pos) {} - - public boolean emptyBucket(@Nullable Player player, Level world, BlockPos pos, @Nullable BlockHitResult movingobjectpositionblock) { -- return a(player, world, pos, movingobjectpositionblock, null, null, null); -+ // Paper start - add enumHand -+ return a(player, world, pos, movingobjectpositionblock, null, null, null, null); - } - -- public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack) { -+ public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, InteractionHand enumhand) { -+ // Paper end - // CraftBukkit end - if (!(this.content instanceof FlowingFluid)) { - return false; -@@ -138,7 +140,7 @@ public class BucketItem extends Item { - - // CraftBukkit start - if (flag1 && entityhuman != null) { -- PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack); -+ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); // Paper - add enumhand - if (event.isCancelled()) { - ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity - ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 -@@ -147,7 +149,7 @@ public class BucketItem extends Item { - } - // CraftBukkit end - if (!flag1) { -- return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack); // CraftBukkit -+ return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit // Paper - add enumhand - } else if (world.dimensionType().ultraWarm() && this.content.is((Tag) FluidTags.WATER)) { - int i = blockposition.getX(); - int j = blockposition.getY(); -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 7a9ccd203885b9b369767d1fb8c53783201d0f0f..b75ffafb6840b6acab6e5b0ef5e222c4fa130977 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -277,6 +277,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - // Paper end - -+ // Paper start - moved up from WorldServer -+ public BlockPos getSpawn() { -+ BlockPos blockposition = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn()); -+ -+ if (!this.getWorldBorder().isWithinBounds(blockposition)) { -+ blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, new BlockPos(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); -+ } -+ -+ return blockposition; -+ } -+ // Paper end - @Override - public boolean isClientSide() { - return this.isClientSide; -diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 8a71eaf2855be0d415d1f7b18dbec98353fe5b47..b90a275a0dc2913809ce16659eed445501e486de 100644 ---- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java -+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -268,7 +268,7 @@ public final class NaturalSpawner { - private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) { - if (squaredDistance <= 576.0D) { - return false; -- } else if (world.getSharedSpawnPos().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D)) { -+ } else if (world.getSpawn().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D)) { - return false; - } else { - ChunkPos chunkcoordintpair = new ChunkPos(pos); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 9807612aed6c4393cbe1f4b6078e45bf1ba3deb2..159c32d6678e83f2d98ea6a1ad48346c9de017e1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -327,7 +327,7 @@ public class CraftWorld implements World { - - @Override - public Location getSpawnLocation() { -- BlockPos spawn = world.getSharedSpawnPos(); -+ BlockPos spawn = world.getSpawn(); - return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); - } - -@@ -1926,7 +1926,7 @@ public class CraftWorld implements World { - public void setKeepSpawnInMemory(boolean keepLoaded) { - world.keepSpawnInMemory = keepLoaded; - // Grab the worlds spawn chunk -- BlockPos chunkcoordinates = this.world.getSharedSpawnPos(); -+ BlockPos chunkcoordinates = this.world.getSpawn(); - if (keepLoaded) { - world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); - } else { -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 4cd08821305590e21a01cc4dda05370c2b721ac2..1877267344df1ff5b4de6a4e0c239f488cd52c1f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -222,7 +222,7 @@ public class CraftEventFactory { - public static Entity entityDamage; // For use in EntityDamageByEntityEvent - - // helper methods -- private static boolean canBuild(ServerLevel world, Player player, int x, int z) { -+ private static boolean canBuild(Level world, Player player, int x, int z) { - int spawnSize = Bukkit.getServer().getSpawnRadius(); - - if (world.dimension() != Level.OVERWORLD) return true; -@@ -230,7 +230,7 @@ public class CraftEventFactory { - if (((CraftServer) Bukkit.getServer()).getHandle().getOps().isEmpty()) return true; - if (player.isOp()) return true; - -- BlockPos chunkcoordinates = world.getSharedSpawnPos(); -+ BlockPos chunkcoordinates = world.getSpawn(); - - int distanceFromSpawn = Math.max(Math.abs(x - chunkcoordinates.getX()), Math.abs(z - chunkcoordinates.getZ())); - return distanceFromSpawn > spawnSize; -@@ -412,6 +412,20 @@ public class CraftEventFactory { - } - - private static PlayerEvent getPlayerBucketEvent(boolean isFilling, ServerLevel world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item) { -+ // Paper start - add enumHand -+ return getPlayerBucketEvent(isFilling, world, who, changed, clicked, clickedFace, itemstack, item, null); -+ } -+ -+ public static PlayerBucketEmptyEvent callPlayerBucketEmptyEvent(Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, InteractionHand enumHand) { -+ return (PlayerBucketEmptyEvent) getPlayerBucketEvent(false, world, who, changed, clicked, clickedFace, itemstack, Items.BUCKET, enumHand); -+ } -+ -+ public static PlayerBucketFillEvent callPlayerBucketFillEvent(Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemInHand, net.minecraft.world.item.Item bucket, InteractionHand enumHand) { -+ return (PlayerBucketFillEvent) getPlayerBucketEvent(true, world, who, clicked, changed, clickedFace, itemInHand, bucket, enumHand); -+ } -+ -+ private static PlayerEvent getPlayerBucketEvent(boolean isFilling, Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item, InteractionHand enumHand) { -+ // Paper end - Player player = (Player) who.getBukkitEntity(); - CraftItemStack itemInHand = CraftItemStack.asNewCraftStack(item); - Material bucket = CraftMagicNumbers.getMaterial(itemstack.getItem()); -@@ -424,10 +438,10 @@ public class CraftEventFactory { - - PlayerEvent event; - if (isFilling) { -- event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand); -+ event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand - ((PlayerBucketFillEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); - } else { -- event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand); -+ event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand - ((PlayerBucketEmptyEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); - } - diff --git a/patches/server-remapped/0261-MC-135506-Experience-should-save-as-Integers.patch b/patches/server-remapped/0261-MC-135506-Experience-should-save-as-Integers.patch deleted file mode 100644 index 07dc1c1b3f..0000000000 --- a/patches/server-remapped/0261-MC-135506-Experience-should-save-as-Integers.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 3 Aug 2018 00:04:54 -0400 -Subject: [PATCH] MC-135506: Experience should save as Integers - - -diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index 52b90ef3a145325209d3d903a2b7c9a44c332cbe..37758cff3c4a8406c2f1496ae827ecdc953cf9f4 100644 ---- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -217,7 +217,7 @@ public class ExperienceOrb extends Entity { - public void addAdditionalSaveData(CompoundTag tag) { - tag.putShort("Health", (short) this.health); - tag.putShort("Age", (short) this.age); -- tag.putShort("Value", (short) this.value); -+ tag.putInt("Value", this.value); // Paper - save as Integer - this.savePaperNBT(tag); // Paper - } - -@@ -225,7 +225,7 @@ public class ExperienceOrb extends Entity { - public void readAdditionalSaveData(CompoundTag tag) { - this.health = tag.getShort("Health"); - this.age = tag.getShort("Age"); -- this.value = tag.getShort("Value"); -+ this.value = tag.getInt("Value"); // Paper - load as Integer - this.loadPaperNBT(tag); // Paper - } - diff --git a/patches/server-remapped/0271-Slime-Pathfinder-Events.patch b/patches/server-remapped/0271-Slime-Pathfinder-Events.patch deleted file mode 100644 index 1156074828..0000000000 --- a/patches/server-remapped/0271-Slime-Pathfinder-Events.patch +++ /dev/null @@ -1,229 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 08:18:42 -0500 -Subject: [PATCH] Slime Pathfinder Events - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java -index fc8f26e988f1e4826dcfdcf071293bb356163e62..120ceb28ee3aee8a09cf67b45ac95d3d6613c133 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Slime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java -@@ -24,7 +24,6 @@ import net.minecraft.world.effect.MobEffects; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityDimensions; - import net.minecraft.world.entity.EntityType; --import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.Mob; - import net.minecraft.world.entity.MobSpawnType; - import net.minecraft.world.entity.Pose; -@@ -43,6 +42,13 @@ import net.minecraft.world.level.WorldGenLevel; - import net.minecraft.world.level.biome.Biomes; - import net.minecraft.world.level.levelgen.WorldgenRandom; - import net.minecraft.world.phys.Vec3; -+// Paper start -+import com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent; -+import com.destroystokyo.paper.event.entity.SlimeSwimEvent; -+import com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent; -+import com.destroystokyo.paper.event.entity.SlimeWanderEvent; -+import org.bukkit.entity.LivingEntity; -+// Paper end - // CraftBukkit start - import java.util.ArrayList; - import java.util.List; -@@ -103,6 +109,7 @@ public class Slime extends Mob implements Enemy { - @Override - public void addAdditionalSaveData(CompoundTag tag) { - super.addAdditionalSaveData(tag); -+ tag.putBoolean("Paper.canWander", this.canWander); // Paper - tag.putInt("Size", this.getSize() - 1); - tag.putBoolean("wasOnGround", this.wasOnGround); - } -@@ -117,6 +124,11 @@ public class Slime extends Mob implements Enemy { - - this.setSize(i + 1, false); - super.readAdditionalSaveData(tag); -+ // Paper start - check exists before loading or this will be loaded as false -+ if (tag.contains("Paper.canWander")) { -+ this.canWander = tag.getBoolean("Paper.canWander"); -+ } -+ // Paper end - this.wasOnGround = tag.getBoolean("wasOnGround"); - } - -@@ -218,7 +230,7 @@ public class Slime extends Mob implements Enemy { - super.remove(); - return; - } -- List slimes = new ArrayList<>(j); -+ List slimes = new ArrayList<>(j); - // CraftBukkit end - - for (int l = 0; l < k; ++l) { -@@ -242,7 +254,7 @@ public class Slime extends Mob implements Enemy { - if (CraftEventFactory.callEntityTransformEvent(this, slimes, EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { - return; - } -- for (LivingEntity living : slimes) { -+ for (net.minecraft.world.entity.LivingEntity living : slimes) { - this.level.addEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason - } - // CraftBukkit end -@@ -255,7 +267,7 @@ public class Slime extends Mob implements Enemy { - public void push(Entity entity) { - super.push(entity); - if (entity instanceof IronGolem && this.isDealsDamage()) { -- this.dealDamage((LivingEntity) entity); -+ this.dealDamage((net.minecraft.world.entity.LivingEntity) entity); - } - - } -@@ -263,18 +275,18 @@ public class Slime extends Mob implements Enemy { - @Override - public void playerTouch(Player player) { - if (this.isDealsDamage()) { -- this.dealDamage((LivingEntity) player); -+ this.dealDamage((net.minecraft.world.entity.LivingEntity) player); - } - - } - -- protected void dealDamage(LivingEntity target) { -+ protected void dealDamage(net.minecraft.world.entity.LivingEntity target) { - if (this.isAlive()) { - int i = this.getSize(); - - if (this.distanceToSqr((Entity) target) < 0.6D * (double) i * 0.6D * (double) i && this.canSee(target) && target.hurt(DamageSource.mobAttack(this), this.getAttackDamage())) { - this.playSound(SoundEvents.SLIME_ATTACK, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); -- this.doEnchantDamageEffects((LivingEntity) this, (Entity) target); -+ this.doEnchantDamageEffects((net.minecraft.world.entity.LivingEntity) this, (Entity) target); - } - } - -@@ -396,7 +408,7 @@ public class Slime extends Mob implements Enemy { - - @Override - public boolean canUse() { -- return !this.slime.isPassenger(); -+ return !this.slime.isPassenger() && this.slime.canWander && new SlimeWanderEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper - } - - @Override -@@ -417,7 +429,7 @@ public class Slime extends Mob implements Enemy { - - @Override - public boolean canUse() { -- return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; -+ return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new SlimeSwimEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper - } - - @Override -@@ -443,14 +455,18 @@ public class Slime extends Mob implements Enemy { - - @Override - public boolean canUse() { -- return this.slime.getTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; -+ return this.slime.getTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander; // Paper - add canWander - } - - @Override - public void tick() { - if (--this.nextRandomizeTime <= 0) { - this.nextRandomizeTime = 40 + this.slime.getRandom().nextInt(60); -- this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); -+ // Paper start -+ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (float) this.slime.getRandom().nextInt(360)); -+ if (!this.slime.canWander || !event.callEvent()) return; -+ this.chosenDegrees = event.getNewYaw(); -+ // Paper end - } - - ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.chosenDegrees, false); -@@ -469,9 +485,17 @@ public class Slime extends Mob implements Enemy { - - @Override - public boolean canUse() { -- LivingEntity entityliving = this.slime.getTarget(); -+ net.minecraft.world.entity.LivingEntity entityliving = this.slime.getTarget(); - -- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable ? false : this.slime.getMoveControl() instanceof Slime.SlimeMoveControl)); -+ // Paper start -+ if (entityliving == null || !entityliving.isAlive()) { -+ return false; -+ } -+ if (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable) { -+ return false; -+ } -+ return this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); -+ // Paper end - } - - @Override -@@ -482,9 +506,17 @@ public class Slime extends Mob implements Enemy { - - @Override - public boolean canContinueToUse() { -- LivingEntity entityliving = this.slime.getTarget(); -+ net.minecraft.world.entity.LivingEntity entityliving = this.slime.getTarget(); - -- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable ? false : --this.growTiredTimer > 0)); -+ // Paper start -+ if (entityliving == null || !entityliving.isAlive()) { -+ return false; -+ } -+ if (entityliving instanceof Player && ((Player) entityliving).abilities.invulnerable) { -+ return false; -+ } -+ return --this.growTiredTimer > 0 && this.slime.canWander && new SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); -+ // Paper end - } - - @Override -@@ -492,6 +524,13 @@ public class Slime extends Mob implements Enemy { - this.slime.lookAt((Entity) this.slime.getTarget(), 10.0F, 10.0F); - ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.slime.yRot, this.slime.isDealsDamage()); - } -+ -+ // Paper start - clear timer and target when goal resets -+ public void stop() { -+ this.growTiredTimer = 0; -+ this.slime.setTarget(null); -+ } -+ // Paper end - } - - static class SlimeMoveControl extends MoveControl { -@@ -550,4 +589,15 @@ public class Slime extends Mob implements Enemy { - } - } - } -+ -+ // Paper start -+ private boolean canWander = true; -+ public boolean canWander() { -+ return canWander; -+ } -+ -+ public void setWander(boolean canWander) { -+ this.canWander = canWander; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -index 93af0fd9e15954d7d9f28d7dc29ee18055908348..340036135588d06e43cbd229dd3a6613b04bb9ab 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -@@ -34,4 +34,14 @@ public class CraftSlime extends CraftMob implements Slime { - public EntityType getType() { - return EntityType.SLIME; - } -+ -+ // Paper start -+ public boolean canWander() { -+ return getHandle().canWander(); -+ } -+ -+ public void setWander(boolean canWander) { -+ getHandle().setWander(canWander); -+ } -+ // Paper end - } diff --git a/patches/server-remapped/0274-Optimize-RegistryMaterials.patch b/patches/server-remapped/0274-Optimize-RegistryMaterials.patch deleted file mode 100644 index 9ee9585d10..0000000000 --- a/patches/server-remapped/0274-Optimize-RegistryMaterials.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 26 Aug 2018 20:49:50 -0400 -Subject: [PATCH] Optimize RegistryMaterials - -Use larger initial sizes to increase bucket capacity on the BiMap - -BiMap.get was seen to be using a good bit of CPU time. - -diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java -index 928d4b980a1f703915454ffb304dc329fa4223df..da3733db4a5817673703f6c0cf37b5ee3bf91a99 100644 ---- a/src/main/java/net/minecraft/core/MappedRegistry.java -+++ b/src/main/java/net/minecraft/core/MappedRegistry.java -@@ -30,6 +30,7 @@ import net.minecraft.Util; - import net.minecraft.resources.RegistryDataPackCodec; - import net.minecraft.resources.ResourceKey; - import net.minecraft.resources.ResourceLocation; -+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; // Paper - import org.apache.commons.lang3.Validate; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -38,7 +39,7 @@ public class MappedRegistry extends WritableRegistry { - - protected static final Logger LOGGER = LogManager.getLogger(); - private final ObjectList byId = new ObjectArrayList(256); -- private final Object2IntMap toId = new Object2IntOpenCustomHashMap(Util.identityStrategy()); -+ private final Reference2IntOpenHashMap bg = new Reference2IntOpenHashMap(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map - private final BiMap storage; - private final BiMap, T> keyStorage; - private final Map lifecycles; -@@ -48,10 +49,10 @@ public class MappedRegistry extends WritableRegistry { - - public MappedRegistry(ResourceKey> key, Lifecycle lifecycle) { - super(key, lifecycle); -- this.toId.defaultReturnValue(-1); -- this.storage = HashBiMap.create(); -- this.keyStorage = HashBiMap.create(); -- this.lifecycles = Maps.newIdentityHashMap(); -+ this.bg.defaultReturnValue(-1); -+ this.storage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions -+ this.keyStorage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions -+ this.lifecycles = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions - this.elementsLifecycle = lifecycle; - } - -@@ -77,7 +78,7 @@ public class MappedRegistry extends WritableRegistry { - Validate.notNull(entry); - this.byId.size(Math.max(this.byId.size(), rawId + 1)); - this.byId.set(rawId, entry); -- this.toId.put(entry, rawId); -+ this.bg.put(entry, rawId); - this.randomCache = null; - if (checkDuplicateKeys && this.keyStorage.containsKey(key)) { - MappedRegistry.LOGGER.debug("Adding duplicate key '{}' to registry", key); -@@ -113,12 +114,12 @@ public class MappedRegistry extends WritableRegistry { - if (t0 == null) { - i = rawId.isPresent() ? rawId.getAsInt() : this.nextId; - } else { -- i = this.toId.getInt(t0); -+ i = this.bg.getInt(t0); - if (rawId.isPresent() && rawId.getAsInt() != i) { - throw new IllegalStateException("ID mismatch"); - } - -- this.toId.removeInt(t0); -+ this.bg.removeInt(t0); - this.lifecycles.remove(t0); - } - -@@ -138,7 +139,7 @@ public class MappedRegistry extends WritableRegistry { - - @Override - public int getId(@Nullable T entry) { -- return this.toId.getInt(entry); -+ return this.bg.getInt(entry); - } - - @Nullable -@@ -195,7 +196,7 @@ public class MappedRegistry extends WritableRegistry { - this.randomCache = collection.toArray(new Object[collection.size()]); - } - -- return Util.getRandom(this.randomCache, random); -+ return (T) Util.getRandom(this.randomCache, random); // Paper - Decompile fix - } - - public static Codec> networkCodec(ResourceKey> resourcekey, Lifecycle lifecycle, Codec entryCodec) { -@@ -215,7 +216,7 @@ public class MappedRegistry extends WritableRegistry { - Iterator iterator = registrymaterials.iterator(); - - while (iterator.hasNext()) { -- T t0 = iterator.next(); -+ T t0 = (T) iterator.next(); // Paper - Decompile fix - - builder.add(new MappedRegistry.RegistryEntry<>((ResourceKey) registrymaterials.getResourceKey(t0).get(), registrymaterials.getId(t0), t0)); - } diff --git a/patches/server-remapped/0268-Allow-disabling-armour-stand-ticking.patch b/patches/server/0232-Allow-disabling-armour-stand-ticking.patch similarity index 63% rename from patches/server-remapped/0268-Allow-disabling-armour-stand-ticking.patch rename to patches/server/0232-Allow-disabling-armour-stand-ticking.patch index b471e98ef0..2075008fed 100644 --- a/patches/server-remapped/0268-Allow-disabling-armour-stand-ticking.patch +++ b/patches/server/0232-Allow-disabling-armour-stand-ticking.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow disabling armour stand ticking diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3562950df4868b1393790b1a1ff1fe0dc589c155..5ab0e7183e48134b7a0f736462516b1a8a333b04 100644 +index 1f6b37bd3cbc825abab5ad2f673200ef5061746a..8bb33e1b631c3aa99cef2a63c140f0b0e11325e0 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -384,4 +384,10 @@ public class PaperWorldConfig { +@@ -378,4 +378,10 @@ public class PaperWorldConfig { private void armorStandEntityLookups() { armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); } @@ -20,10 +20,10 @@ index 3562950df4868b1393790b1a1ff1fe0dc589c155..5ab0e7183e48134b7a0f736462516b1a + } } diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 06e52a0c5decf717e35c605d6bcb46c3c7b29656..2994eee1d381af2c9ff3649dd48a2ae14c38c9d7 100644 +index 449f9b87ea6ff313f7e0e9104a641f1bf7729f24..33f1e486f3732c156289b16d973297e771da82b9 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -77,9 +77,16 @@ public class ArmorStand extends LivingEntity { +@@ -93,9 +93,16 @@ public class ArmorStand extends LivingEntity { public Rotations leftLegPose; public Rotations rightLegPose; public boolean canMove = true; // Paper @@ -37,10 +37,10 @@ index 06e52a0c5decf717e35c605d6bcb46c3c7b29656..2994eee1d381af2c9ff3649dd48a2ae1 public ArmorStand(EntityType type, Level world) { super(type, world); + if (world != null) this.canTick = world.paperConfig.armorStandTick; // Paper - armour stand ticking - this.handItems = NonNullList.a(2, ItemStack.EMPTY); - this.armorItems = NonNullList.a(4, ItemStack.EMPTY); + this.handItems = NonNullList.withSize(2, ItemStack.EMPTY); + this.armorItems = NonNullList.withSize(4, ItemStack.EMPTY); this.headPose = ArmorStand.DEFAULT_HEAD_POSE; -@@ -175,6 +182,7 @@ public class ArmorStand extends LivingEntity { +@@ -192,6 +199,7 @@ public class ArmorStand extends LivingEntity { this.armorItems.set(enumitemslot.getIndex(), itemstack); } @@ -48,28 +48,28 @@ index 06e52a0c5decf717e35c605d6bcb46c3c7b29656..2994eee1d381af2c9ff3649dd48a2ae1 } @Override -@@ -255,6 +263,7 @@ public class ArmorStand extends LivingEntity { +@@ -242,6 +250,7 @@ public class ArmorStand extends LivingEntity { } - tag.put("Pose", this.writePose()); -+ if (this.canTickSetByAPI) tag.putBoolean("Paper.CanTickOverride", this.canTick); // Paper - persist no tick setting + nbt.put("Pose", this.writePose()); ++ if (this.canTickSetByAPI) nbt.putBoolean("Paper.CanTickOverride", this.canTick); // Paper - persist no tick setting } @Override -@@ -286,6 +295,12 @@ public class ArmorStand extends LivingEntity { - this.setNoBasePlate(tag.getBoolean("NoBasePlate")); - this.setMarker(tag.getBoolean("Marker")); +@@ -273,6 +282,12 @@ public class ArmorStand extends LivingEntity { + this.setNoBasePlate(nbt.getBoolean("NoBasePlate")); + this.setMarker(nbt.getBoolean("Marker")); this.noPhysics = !this.hasPhysics(); + // Paper start - persist no tick -+ if (tag.contains("Paper.CanTickOverride")) { -+ this.canTick = tag.getBoolean("Paper.CanTickOverride"); ++ if (nbt.contains("Paper.CanTickOverride")) { ++ this.canTick = nbt.getBoolean("Paper.CanTickOverride"); + this.canTickSetByAPI = true; + } + // Paper end - CompoundTag nbttagcompound1 = tag.getCompound("Pose"); + CompoundTag nbttagcompound1 = nbt.getCompound("Pose"); this.readPose(nbttagcompound1); -@@ -641,7 +656,29 @@ public class ArmorStand extends LivingEntity { +@@ -654,7 +669,29 @@ public class ArmorStand extends LivingEntity { @Override public void tick() { @@ -99,50 +99,51 @@ index 06e52a0c5decf717e35c605d6bcb46c3c7b29656..2994eee1d381af2c9ff3649dd48a2ae1 Rotations vector3f = (Rotations) this.entityData.get(ArmorStand.DATA_HEAD_POSE); if (!this.headPose.equals(vector3f)) { -@@ -764,29 +801,36 @@ public class ArmorStand extends LivingEntity { - public void setHeadPose(Rotations vector3f) { - this.headPose = vector3f; - this.entityData.set(ArmorStand.DATA_HEAD_POSE, vector3f); +@@ -777,31 +814,37 @@ public class ArmorStand extends LivingEntity { + public void setHeadPose(Rotations angle) { + this.headPose = angle; + this.entityData.set(ArmorStand.DATA_HEAD_POSE, angle); + this.noTickPoseDirty = true; // Paper - Allow updates when not ticking } - public void setBodyPose(Rotations vector3f) { - this.bodyPose = vector3f; - this.entityData.set(ArmorStand.DATA_BODY_POSE, vector3f); + public void setBodyPose(Rotations angle) { + this.bodyPose = angle; + this.entityData.set(ArmorStand.DATA_BODY_POSE, angle); + this.noTickPoseDirty = true; // Paper - Allow updates when not ticking } - public void setLeftArmPose(Rotations vector3f) { - this.leftArmPose = vector3f; - this.entityData.set(ArmorStand.DATA_LEFT_ARM_POSE, vector3f); + public void setLeftArmPose(Rotations angle) { + this.leftArmPose = angle; + this.entityData.set(ArmorStand.DATA_LEFT_ARM_POSE, angle); + this.noTickPoseDirty = true; // Paper - Allow updates when not ticking } - public void setRightArmPose(Rotations vector3f) { - this.rightArmPose = vector3f; - this.entityData.set(ArmorStand.DATA_RIGHT_ARM_POSE, vector3f); + public void setRightArmPose(Rotations angle) { + this.rightArmPose = angle; + this.entityData.set(ArmorStand.DATA_RIGHT_ARM_POSE, angle); + this.noTickPoseDirty = true; // Paper - Allow updates when not ticking } - public void setLeftLegPose(Rotations vector3f) { + public void setLeftLegPose(Rotations angle) { + this.leftLegPose = angle; + this.entityData.set(ArmorStand.DATA_LEFT_LEG_POSE, angle); + this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - this.leftLegPose = vector3f; - this.entityData.set(ArmorStand.DATA_LEFT_LEG_POSE, vector3f); -+ } - public void setRightLegPose(Rotations vector3f) { + public void setRightLegPose(Rotations angle) { + this.rightLegPose = angle; + this.entityData.set(ArmorStand.DATA_RIGHT_LEG_POSE, angle); + this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - this.rightLegPose = vector3f; - this.entityData.set(ArmorStand.DATA_RIGHT_LEG_POSE, vector3f); } + + public Rotations getHeadPose() { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index d4da5214a39b718671dcaf687cb0ff8668ce9728..8363b1b2267da30cda2fb8ea4e844598e20e1422 100644 +index 06cedeea447f53d100e32a6eba6f83b4719cb231..82b9ee993b0d2e7e0685231f7bad2b85756ec959 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -311,5 +311,16 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { - return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); +@@ -238,5 +238,16 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public void setCanMove(boolean move) { + getHandle().canMove = move; } + + @Override diff --git a/patches/server-remapped/0252-SkeletonHorse-Additions.patch b/patches/server/0233-SkeletonHorse-Additions.patch similarity index 56% rename from patches/server-remapped/0252-SkeletonHorse-Additions.patch rename to patches/server/0233-SkeletonHorse-Additions.patch index 6599e06859..b4a112f8f9 100644 --- a/patches/server-remapped/0252-SkeletonHorse-Additions.patch +++ b/patches/server/0233-SkeletonHorse-Additions.patch @@ -4,64 +4,32 @@ Date: Fri, 27 Jul 2018 22:36:31 -0500 Subject: [PATCH] SkeletonHorse Additions -diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index a3bad391a719363077740aa810c9412df34b4ae5..e92a8c4c49c452e1f3f0c06398f2a74e3432262f 100644 ---- a/src/main/java/net/minecraft/world/entity/EntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -25,6 +25,7 @@ public final class EntitySelector { - public static final Predicate ATTACK_ALLOWED = (entity) -> { - return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative() && entity.level.getDifficulty() != Difficulty.PEACEFUL; - }; -+ public static Predicate notSpectator() { return NO_SPECTATORS; } // Paper - OBFHELPER - public static final Predicate NO_SPECTATORS = (entity) -> { - return !entity.isSpectator(); - }; diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java -index 7ef99acaa24525c68b1528bd3232738baab8e1c6..eaab482ae341ddda0754e726357cd845121fb043 100644 +index b5446b417963850f25c715abe52403c731b6ef01..9c5c7ef3b915afe5fe54144f51e383a83c1eb752 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java -@@ -26,7 +26,7 @@ public class SkeletonHorse extends AbstractHorse { - +@@ -23,7 +23,7 @@ public class SkeletonHorse extends AbstractHorse { private final SkeletonTrapGoal skeletonTrapGoal = new SkeletonTrapGoal(this); + private static final int TRAP_MAX_LIFE = 18000; private boolean isTrap; - private int trapTime; -+ private int trapTime; public int getTrapTime() { return this.trapTime; } // Paper - OBFHELPER ++ public int trapTime; // Paper private -> public public SkeletonHorse(EntityType type, Level world) { super(type, world); -@@ -145,10 +145,12 @@ public class SkeletonHorse extends AbstractHorse { - return 0.96F; - } - -+ public boolean isTrap() { return this.isTrap(); } // Paper - OBFHELPER - public boolean isTrap() { - return this.isTrap; - } - -+ public void setTrap(boolean trap) { this.setTrap(trap); } // Paper - OBFHELPER - public void setTrap(boolean trapped) { - if (trapped != this.isTrap) { - this.isTrap = trapped; diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java -index 6c2cbaae2afe076c8b7bc53ffa91fe37e423d120..7f5fb28a7deabe1b62ed21e5ed1ea1ecca0d15b8 100644 +index 67afaab789041f49407233ca8a856a3b0131fcf6..1b874f8a72f5b1ac64dd66621b039295f5dc1f18 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java -@@ -14,10 +14,14 @@ import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; - import net.minecraft.world.item.enchantment.EnchantmentHelper; - import net.minecraft.world.level.Level; -+import org.bukkit.entity.HumanEntity; -+ -+import java.util.List; - +@@ -18,6 +18,7 @@ import net.minecraft.world.level.Level; public class SkeletonTrapGoal extends Goal { private final SkeletonHorse horse; -+ private List eligiblePlayers; // Paper ++ private java.util.List eligiblePlayers; // Paper public SkeletonTrapGoal(SkeletonHorse skeletonHorse) { this.horse = skeletonHorse; -@@ -25,12 +29,13 @@ public class SkeletonTrapGoal extends Goal { +@@ -25,12 +26,13 @@ public class SkeletonTrapGoal extends Goal { @Override public boolean canUse() { @@ -77,30 +45,20 @@ index 6c2cbaae2afe076c8b7bc53ffa91fe37e423d120..7f5fb28a7deabe1b62ed21e5ed1ea1ec this.horse.setTrap(false); diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index 66681b9f0e2531d3da25629e44180417b32b4d66..6a5430fe54a5c8ad119a0f3842961825a54d8d7a 100644 +index 0b6e5ee9872a73823219bff7f642375fdc4ec243..b0cafe6e0bdb3f297c13f310fdbe9e3158a6715d 100644 --- a/src/main/java/net/minecraft/world/level/EntityGetter.java +++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -1,6 +1,9 @@ - package net.minecraft.world.level; - -+import com.google.common.collect.ImmutableList; - import com.google.common.collect.Lists; -+import org.bukkit.entity.HumanEntity; -+ - import java.util.Iterator; - import java.util.List; - import java.util.UUID; -@@ -115,6 +118,28 @@ public interface EntityGetter { - return entityhuman; +@@ -90,6 +90,28 @@ public interface EntityGetter { + return player; } + // Paper start -+ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, boolean notSpectator) { -+ return findNearbyBukkitPlayers(x, y, z, radius, notSpectator ? EntitySelector.notSpectator() : EntitySelector.canAITarget()); ++ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, boolean notSpectator) { ++ return findNearbyBukkitPlayers(x, y, z, radius, notSpectator ? EntitySelector.NO_SPECTATORS : net.minecraft.world.entity.EntitySelector.NO_CREATIVE_OR_SPECTATOR); + } + -+ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate predicate) { -+ ImmutableList.Builder builder = ImmutableList.builder(); ++ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate predicate) { ++ com.google.common.collect.ImmutableList.Builder builder = com.google.common.collect.ImmutableList.builder(); + + for (Player human : this.players()) { + if (predicate == null || predicate.test(human)) { @@ -120,7 +78,7 @@ index 66681b9f0e2531d3da25629e44180417b32b4d66..6a5430fe54a5c8ad119a0f3842961825 default Player getNearestPlayer(Entity entity, double maxDistance) { return this.getNearestPlayer(entity.getX(), entity.getY(), entity.getZ(), maxDistance, false); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -index b52ca4a612e30542ef4029cb1340f616bc4c36e6..7f984639fc2697cad9d0393467b0cb896d1e55a4 100644 +index b52ca4a612e30542ef4029cb1340f616bc4c36e6..90a61d1472afea12637814256f91dbd2f5acb42e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java @@ -25,4 +25,26 @@ public class CraftSkeletonHorse extends CraftAbstractHorse implements SkeletonHo @@ -136,7 +94,7 @@ index b52ca4a612e30542ef4029cb1340f616bc4c36e6..7f984639fc2697cad9d0393467b0cb89 + + @Override + public int getTrapTime() { -+ return getHandle().getTrapTime(); ++ return getHandle().trapTime; + } + + @Override diff --git a/patches/server-remapped/0254-Don-t-call-getItemMeta-on-hasItemMeta.patch b/patches/server/0234-Don-t-call-getItemMeta-on-hasItemMeta.patch similarity index 79% rename from patches/server-remapped/0254-Don-t-call-getItemMeta-on-hasItemMeta.patch rename to patches/server/0234-Don-t-call-getItemMeta-on-hasItemMeta.patch index 0133184a69..de9d451a6f 100644 --- a/patches/server-remapped/0254-Don-t-call-getItemMeta-on-hasItemMeta.patch +++ b/patches/server/0234-Don-t-call-getItemMeta-on-hasItemMeta.patch @@ -11,23 +11,23 @@ Returns true if getDamage() == 0 or has damage tag or other tag is set. Check the `ItemMetaTest#testTaggedButNotMeta` method to see how this method behaves. diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 44caf00330e4f4f74745973dbe709980f0b61269..9e06912b0c13c3d61bc95e526acaa28f96b46fb9 100644 +index 3fbfe4f77c4b82d96ed022498b2d9175d548e247..383c34a611f8371dd6ebcb858c1c0ba148d0660b 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -569,7 +569,7 @@ public final class CraftItemStack extends ItemStack { +@@ -572,7 +572,7 @@ public final class CraftItemStack extends ItemStack { @Override public boolean hasItemMeta() { -- return hasItemMeta(handle) && !CraftItemFactory.instance().equals(getItemMeta(), null); -+ return hasItemMeta(handle) && (handle.getDamageValue() != 0 || (handle.getTag() != null && handle.getTag().tags.size() >= (handle.getTag().contains(CraftMetaItem.DAMAGE.NBT) ? 2 : 1))); // Paper - keep 1.12 CraftBukkit behavior without calling getItemMeta +- return CraftItemStack.hasItemMeta(this.handle) && !CraftItemFactory.instance().equals(this.getItemMeta(), null); ++ return CraftItemStack.hasItemMeta(this.handle) && (this.handle.getDamageValue() != 0 || (this.handle.getTag() != null && this.handle.getTag().tags.size() >= (this.handle.getTag().contains(CraftMetaItem.DAMAGE.NBT) ? 2 : 1))); // Paper - keep 1.12 CraftBukkit behavior without calling getItemMeta } static boolean hasItemMeta(net.minecraft.world.item.ItemStack item) { diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -index 42f577ed3508ba5a380648461e149f16ce97c9bd..b85a0a4c4f134dd6012d9141244ecf97b4300b65 100644 +index b0bb30aebdba99a8fa929ec3c56e46b59d2467c9..34eba991c838950c16d565ef6c767bd6a6159bdc 100644 --- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -@@ -96,6 +96,34 @@ public class ItemMetaTest extends AbstractTestingBase { +@@ -97,6 +97,34 @@ public class ItemMetaTest extends AbstractTestingBase { assertThat(itemMeta.hasConflictingEnchant(null), is(false)); } diff --git a/patches/server-remapped/0256-Implement-Expanded-ArmorStand-API.patch b/patches/server/0235-Implement-Expanded-ArmorStand-API.patch similarity index 85% rename from patches/server-remapped/0256-Implement-Expanded-ArmorStand-API.patch rename to patches/server/0235-Implement-Expanded-ArmorStand-API.patch index 4909987c8f..9db2b90a04 100644 --- a/patches/server-remapped/0256-Implement-Expanded-ArmorStand-API.patch +++ b/patches/server/0235-Implement-Expanded-ArmorStand-API.patch @@ -8,26 +8,26 @@ Add the following: - Enable/Disable slot interactions diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 7fc69adc8afa971ee3cf815c6002628ae2149a5b..06e52a0c5decf717e35c605d6bcb46c3c7b29656 100644 +index 33f1e486f3732c156289b16d973297e771da82b9..4adde11daa5ca97a2bf9c164c43c5c011a89b33d 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -426,6 +426,7 @@ public class ArmorStand extends LivingEntity { +@@ -428,7 +428,7 @@ public class ArmorStand extends LivingEntity { return enumitemslot; } -+ public final boolean isSlotDisabled(net.minecraft.world.entity.EquipmentSlot slot) { return this.isDisabled(slot); } // Paper - OBFHELPER - private boolean isDisabled(net.minecraft.world.entity.EquipmentSlot slot) { +- private boolean isDisabled(net.minecraft.world.entity.EquipmentSlot slot) { ++ public boolean isDisabled(net.minecraft.world.entity.EquipmentSlot slot) { // Paper - private -> public return (this.disabledSlots & 1 << slot.getFilterFlag()) != 0 || slot.getType() == net.minecraft.world.entity.EquipmentSlot.Type.HAND && !this.isShowArms(); } + diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 16f996d505b96da8a40c7709214ebbd2a0d0d9f3..d4da5214a39b718671dcaf687cb0ff8668ce9728 100644 +index 82b9ee993b0d2e7e0685231f7bad2b85756ec959..f4065938bbfd04519d1363ee8781c316aca468ab 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -238,5 +238,78 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public void setCanMove(boolean move) { +@@ -239,6 +239,79 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { getHandle().canMove = move; } -+ + + @Override + public ItemStack getItem(org.bukkit.inventory.EquipmentSlot slot) { + com.google.common.base.Preconditions.checkNotNull(slot, "slot"); @@ -98,7 +98,9 @@ index 16f996d505b96da8a40c7709214ebbd2a0d0d9f3..d4da5214a39b718671dcaf687cb0ff86 + + @Override + public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { -+ return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); ++ return getHandle().isDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); + } - // Paper end - } ++ + @Override + public boolean canTick() { + return this.getHandle().canTick; diff --git a/patches/server-remapped/0257-AnvilDamageEvent.patch b/patches/server/0236-AnvilDamageEvent.patch similarity index 83% rename from patches/server-remapped/0257-AnvilDamageEvent.patch rename to patches/server/0236-AnvilDamageEvent.patch index 8e4a474184..8b62260475 100644 --- a/patches/server-remapped/0257-AnvilDamageEvent.patch +++ b/patches/server/0236-AnvilDamageEvent.patch @@ -5,14 +5,13 @@ Subject: [PATCH] AnvilDamageEvent diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java -index aa4b03dc9a0d6b3f387f081a1887672b90c60ef9..3d53edae7e3d5bb00913384ad0eb67551a65750e 100644 +index 6a9597572714706052103677bfb6142a5be2e134..1dad9577370bb58b27b32b997a505ce5145a6769 100644 --- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java -@@ -80,7 +80,16 @@ public class AnvilMenu extends ItemCombinerMenu { - - if (!player.abilities.instabuild && iblockdata.is((Tag) BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { +@@ -90,6 +90,16 @@ public class AnvilMenu extends ItemCombinerMenu { + if (!player.getAbilities().instabuild && iblockdata.is((Tag) BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { BlockState iblockdata1 = AnvilBlock.damage(iblockdata); -- + + // Paper start + com.destroystokyo.paper.event.block.AnvilDamagedEvent event = new com.destroystokyo.paper.event.block.AnvilDamagedEvent(getBukkitView(), iblockdata1 != null ? org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(iblockdata1) : null); + if (!event.callEvent()) { diff --git a/patches/server/0237-Add-hand-to-bucket-events.patch b/patches/server/0237-Add-hand-to-bucket-events.patch new file mode 100644 index 0000000000..6bd9341130 --- /dev/null +++ b/patches/server/0237-Add-hand-to-bucket-events.patch @@ -0,0 +1,196 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Thu, 2 Aug 2018 08:44:35 -0500 +Subject: [PATCH] Add hand to bucket events + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 5751a9318867df781568dd92ad4f51d1f40bc23c..dae19715582d75d24744d44a87f94dd86f90c1c7 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1419,15 +1419,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.getServer().getPlayerList().broadcastAll(new ClientboundSetDefaultSpawnPositionPacket(pos, angle)); + } + +- public BlockPos getSharedSpawnPos() { +- BlockPos blockposition = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn()); +- +- if (!this.getWorldBorder().isWithinBounds(blockposition)) { +- blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, new BlockPos(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); +- } +- +- return blockposition; +- } ++ // Paper - moved up to Level ++ //public BlockPosition getSpawn() { ++ // BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); ++ // ++ // if (!this.getWorldBorder().a(blockposition)) { ++ // blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); ++ // } ++ // ++ // return blockposition; ++ //} ++ // Paper end + + public float getSharedSpawnAngle() { + return this.levelData.getSpawnAngle(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java +index 4656c2a524bc5d397715c55799362c4b97f96009..41d5f4bf470bccbc0967df64e1630a01a5c6f27a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Cow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Cow.java +@@ -87,7 +87,7 @@ public class Cow extends Animal { + + if (itemstack.is(Items.BUCKET) && !this.isBaby()) { + // CraftBukkit start - Got milk? +- org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET); ++ org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); // Paper - add enumHand + + if (event.isCancelled()) { + return InteractionResult.PASS; +diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java +index f6aa7ac23288c67178e22b194f831d337dd4dda0..580f3e8de2e10ddc01430e84fc42e243736c4810 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java ++++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java +@@ -166,7 +166,7 @@ public class Goat extends Animal { + + if (itemstack.is(Items.BUCKET) && !this.isBaby()) { + // CraftBukkit start - Got milk? +- org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET); ++ org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); // Paper - add enumHand + + if (event.isCancelled()) { + return InteractionResult.PASS; +diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java +index 24272b384b96bb98a8231fe8583f404ad0c96de5..7c3e94c6bf8337ef660473d8ed451606d56082a5 100644 +--- a/src/main/java/net/minecraft/world/item/BucketItem.java ++++ b/src/main/java/net/minecraft/world/item/BucketItem.java +@@ -71,7 +71,7 @@ public class BucketItem extends Item implements DispensibleContainerItem { + BucketPickup ifluidsource = (BucketPickup) iblockdata.getBlock(); + // CraftBukkit start + ItemStack dummyFluid = ifluidsource.pickupBlock(DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); +- PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getItem()); ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getItem(), hand); // Paper - add enumhand + + if (event.isCancelled()) { + ((ServerPlayer) user).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) +@@ -102,7 +102,7 @@ public class BucketItem extends Item implements DispensibleContainerItem { + iblockdata = world.getBlockState(blockposition); + BlockPos blockposition2 = iblockdata.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockposition : blockposition1; + +- if (this.a(user, world, blockposition2, movingobjectpositionblock, movingobjectpositionblock.getDirection(), blockposition, itemstack)) { // CraftBukkit ++ if (this.emptyContents(user, world, blockposition2, movingobjectpositionblock, movingobjectpositionblock.getDirection(), blockposition, itemstack, hand)) { // CraftBukkit // Paper - add enumhand + this.checkExtraContent(user, world, itemstack, blockposition2); + if (user instanceof ServerPlayer) { + CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) user, blockposition2, itemstack); +@@ -129,10 +129,12 @@ public class BucketItem extends Item implements DispensibleContainerItem { + + @Override + public boolean emptyContents(@Nullable Player player, Level world, BlockPos pos, @Nullable BlockHitResult hitResult) { +- return this.a(player, world, pos, hitResult, null, null, null); ++ // Paper start - add enumHand ++ return emptyContents(player, world, pos, hitResult, null, null, null, null); + } + +- public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack) { ++ public boolean emptyContents(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, InteractionHand enumhand) { ++ // Paper end + // CraftBukkit end + if (!(this.content instanceof FlowingFluid)) { + return false; +@@ -145,7 +147,7 @@ public class BucketItem extends Item implements DispensibleContainerItem { + + // CraftBukkit start + if (flag1 && entityhuman != null) { +- PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack); ++ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); // Paper - add enumhand + if (event.isCancelled()) { + ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity + ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 +@@ -154,7 +156,7 @@ public class BucketItem extends Item implements DispensibleContainerItem { + } + // CraftBukkit end + if (!flag1) { +- return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack); // CraftBukkit ++ return movingobjectpositionblock != null && this.emptyContents(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit // Paper - add enumhand + } else if (world.dimensionType().ultraWarm() && this.content.is((Tag) FluidTags.WATER)) { + int i = blockposition.getX(); + int j = blockposition.getY(); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index c1cf7f5bff2878281d4a9787ea7160e984268352..8d4f8719b30a66fbb68c9407ee8484312f05b3fb 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -291,6 +291,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return true; + } + // Paper end ++ // Paper start - moved up from ServerLevel ++ public BlockPos getSharedSpawnPos() { ++ BlockPos blockposition = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn()); ++ ++ if (!this.getWorldBorder().isWithinBounds(blockposition)) { ++ blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, new BlockPos(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); ++ } ++ ++ return blockposition; ++ } ++ // Paper end + @Override + public boolean isClientSide() { + return this.isClientSide; +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index 59fae60116167baf989e85596334824e9004e6fb..9c079d32e81cabfa7b8b28e3e8d5741d8d951d79 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -558,3 +558,4 @@ public final class NaturalSpawner { + void run(Mob entity, ChunkAccess chunk); + } + } ++ +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 966d06e2da7e6f9b4e78ca8ed02f3a6472bc8c05..a81fc5212648056766824113b372a7c772c19e5a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -222,7 +222,7 @@ public class CraftEventFactory { + public static Entity entityDamage; // For use in EntityDamageByEntityEvent + + // helper methods +- private static boolean canBuild(ServerLevel world, Player player, int x, int z) { ++ private static boolean canBuild(Level world, Player player, int x, int z) { + int spawnSize = Bukkit.getServer().getSpawnRadius(); + + if (world.dimension() != Level.OVERWORLD) return true; +@@ -416,6 +416,20 @@ public class CraftEventFactory { + } + + private static PlayerEvent getPlayerBucketEvent(boolean isFilling, ServerLevel world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item) { ++ // Paper start - add enumHand ++ return getPlayerBucketEvent(isFilling, world, who, changed, clicked, clickedFace, itemstack, item, null); ++ } ++ ++ public static PlayerBucketEmptyEvent callPlayerBucketEmptyEvent(Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, InteractionHand enumHand) { ++ return (PlayerBucketEmptyEvent) getPlayerBucketEvent(false, world, who, changed, clicked, clickedFace, itemstack, Items.BUCKET, enumHand); ++ } ++ ++ public static PlayerBucketFillEvent callPlayerBucketFillEvent(Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemInHand, net.minecraft.world.item.Item bucket, InteractionHand enumHand) { ++ return (PlayerBucketFillEvent) getPlayerBucketEvent(true, world, who, clicked, changed, clickedFace, itemInHand, bucket, enumHand); ++ } ++ ++ private static PlayerEvent getPlayerBucketEvent(boolean isFilling, Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item, InteractionHand enumHand) { ++ // Paper end + Player player = (Player) who.getBukkitEntity(); + CraftItemStack itemInHand = CraftItemStack.asNewCraftStack(item); + Material bucket = CraftMagicNumbers.getMaterial(itemstack.getItem()); +@@ -428,10 +442,10 @@ public class CraftEventFactory { + + PlayerEvent event; + if (isFilling) { +- event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand); ++ event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand + ((PlayerBucketFillEvent) event).setCancelled(!CraftEventFactory.canBuild(world, player, changed.getX(), changed.getZ())); + } else { +- event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand); ++ event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand + ((PlayerBucketEmptyEvent) event).setCancelled(!CraftEventFactory.canBuild(world, player, changed.getX(), changed.getZ())); + } + diff --git a/patches/server-remapped/0258-Add-TNTPrimeEvent.patch b/patches/server/0238-Add-TNTPrimeEvent.patch similarity index 56% rename from patches/server-remapped/0258-Add-TNTPrimeEvent.patch rename to patches/server/0238-Add-TNTPrimeEvent.patch index 812624262a..995e6db562 100644 --- a/patches/server-remapped/0258-Add-TNTPrimeEvent.patch +++ b/patches/server/0238-Add-TNTPrimeEvent.patch @@ -5,50 +5,26 @@ Subject: [PATCH] Add TNTPrimeEvent diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index ae3cf71f14526e1f356216dfaa899c8f5083d46d..37a9e9df7f7f816c214c37e545288bf9329626ed 100644 +index e286d4ed03eba05b862741cb98db8a031224cd98..bd61f2b3940bfba7948dbb0a52173144c9ef08bd 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -61,6 +61,7 @@ import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.event.entity.EntityExplodeEvent; - import org.bukkit.event.entity.EntityRegainHealthEvent; - // CraftBukkit end -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - - public class EnderDragon extends Mob implements Enemy { - -@@ -515,6 +516,11 @@ public class EnderDragon extends Mob implements Enemy { +@@ -536,6 +536,11 @@ public class EnderDragon extends Mob implements Enemy { }); craftBlock.getNMS().spawnAfterBreak((ServerLevel) level, blockposition, ItemStack.EMPTY); } + // Paper start - TNTPrimeEvent + org.bukkit.block.Block tntBlock = level.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, explosionSource.getSourceMob().getBukkitEntity()).callEvent()) ++ if(!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.EXPLOSION, explosionSource.getSourceMob().getBukkitEntity()).callEvent()) + continue; + // Paper end nmsBlock.wasExploded(level, blockposition, explosionSource); this.level.removeBlock(blockposition, false); diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java -index 85170008de6e77cfb8e4f55ae440a8428d868af4..31b6c1333c7d0af28385e804e94348cef398748b 100644 +index dd19c31360891245dbe465cf94a9f456cf71e23d..ad0b485dbc77717f16191d6950a2e91faaede94a 100644 --- a/src/main/java/net/minecraft/world/level/block/FireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java -@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; - import com.google.common.collect.ImmutableMap; - import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - import java.util.Map; - import java.util.Random; - import java.util.function.Function; -@@ -11,6 +12,7 @@ import net.minecraft.Util; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; - import net.minecraft.core.Vec3i; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.item.context.BlockPlaceContext; - import net.minecraft.world.level.BlockGetter; -@@ -288,7 +290,7 @@ public class FireBlock extends BaseFireBlock { +@@ -290,7 +290,7 @@ public class FireBlock extends BaseFireBlock { world.setBlock(blockposition, this.getStateWithAge(world, blockposition, l), 3); } else { @@ -57,13 +33,13 @@ index 85170008de6e77cfb8e4f55ae440a8428d868af4..31b6c1333c7d0af28385e804e94348ce } Block block = iblockdata.getBlock(); -@@ -296,6 +298,13 @@ public class FireBlock extends BaseFireBlock { +@@ -298,6 +298,13 @@ public class FireBlock extends BaseFireBlock { if (block instanceof TntBlock) { TntBlock blocktnt = (TntBlock) block; + // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = MCUtil.toBukkitBlock(world, blockposition); -+ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.FIRE, null).callEvent()) { ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); ++ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.FIRE, null).callEvent()) { + return; + } + world.setAir(blockposition, false); @@ -72,77 +48,68 @@ index 85170008de6e77cfb8e4f55ae440a8428d868af4..31b6c1333c7d0af28385e804e94348ce } } diff --git a/src/main/java/net/minecraft/world/level/block/TntBlock.java b/src/main/java/net/minecraft/world/level/block/TntBlock.java -index 5c06e2f69f6c0a03f12fab6accc5f9a79ae37118..76665be4b3f2e2821c35d3d6d6407c4da4f224e7 100644 +index 390dfe9d2a148468b9ed3e3fb39fc944e7aa4d5c..151d412df2fce6e51d0297dc1c070056c31ec196 100644 --- a/src/main/java/net/minecraft/world/level/block/TntBlock.java +++ b/src/main/java/net/minecraft/world/level/block/TntBlock.java -@@ -22,6 +22,7 @@ import net.minecraft.world.level.block.state.StateDefinition; - import net.minecraft.world.level.block.state.properties.BlockStateProperties; - import net.minecraft.world.level.block.state.properties.BooleanProperty; - import net.minecraft.world.phys.BlockHitResult; -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - - public class TntBlock extends Block { - -@@ -36,6 +37,11 @@ public class TntBlock extends Block { +@@ -38,6 +38,11 @@ public class TntBlock extends Block { public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { if (!oldState.is(state.getBlock())) { if (world.hasNeighborSignal(pos)) { + // Paper start - TNTPrimeEvent + org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos);; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) ++ if(!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) + return; + // Paper end - explode(world, pos); + TntBlock.explode(world, pos); world.removeBlock(pos, false); } -@@ -46,6 +52,11 @@ public class TntBlock extends Block { +@@ -48,6 +53,11 @@ public class TntBlock extends Block { @Override public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { if (world.hasNeighborSignal(pos)) { + // Paper start - TNTPrimeEvent + org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos);; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) ++ if(!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) + return; + // Paper end - explode(world, pos); + TntBlock.explode(world, pos); world.removeBlock(pos, false); } -@@ -64,6 +75,12 @@ public class TntBlock extends Block { +@@ -66,6 +76,12 @@ public class TntBlock extends Block { @Override public void wasExploded(Level world, BlockPos pos, Explosion explosion) { if (!world.isClientSide) { + // Paper start - TNTPrimeEvent + org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos); + org.bukkit.entity.Entity source = explosion.source != null ? explosion.source.getBukkitEntity() : null; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) ++ if(!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) + return; + // Paper end PrimedTnt entitytntprimed = new PrimedTnt(world, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, explosion.getSourceMob()); + int i = entitytntprimed.getFuse(); - entitytntprimed.setFuse((short) (world.random.nextInt(entitytntprimed.getLife() / 4) + entitytntprimed.getLife() / 8)); -@@ -92,6 +109,11 @@ public class TntBlock extends Block { - if (item != Items.FLINT_AND_STEEL && item != Items.FIRE_CHARGE) { +@@ -95,6 +111,11 @@ public class TntBlock extends Block { + if (!itemstack.is(Items.FLINT_AND_STEEL) && !itemstack.is(Items.FIRE_CHARGE)) { return super.use(state, world, pos, player, hand, hit); } else { + // Paper start - TNTPrimeEvent + org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos); -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.ITEM, player.getBukkitEntity()).callEvent()) ++ if(!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.ITEM, player.getBukkitEntity()).callEvent()) + return InteractionResult.FAIL; + // Paper end - explode(world, pos, (LivingEntity) player); + TntBlock.explode(world, pos, (LivingEntity) player); world.setBlock(pos, Blocks.AIR.defaultBlockState(), 11); - if (!player.isCreative()) { -@@ -121,6 +143,13 @@ public class TntBlock extends Block { + Item item = itemstack.getItem(); +@@ -126,6 +147,12 @@ public class TntBlock extends Block { + return; } // CraftBukkit end - + // Paper start - TNTPrimeEvent + org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); -+ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.PROJECTILE, projectile.getBukkitEntity()).callEvent()) { ++ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.PROJECTILE, projectile.getBukkitEntity()).callEvent()) { + return; + } + // Paper end -+ - explode(world, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null); + TntBlock.explode(world, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null); world.removeBlock(blockposition, false); } diff --git a/patches/server-remapped/0259-Break-up-and-make-tab-spam-limits-configurable.patch b/patches/server/0239-Break-up-and-make-tab-spam-limits-configurable.patch similarity index 76% rename from patches/server-remapped/0259-Break-up-and-make-tab-spam-limits-configurable.patch rename to patches/server/0239-Break-up-and-make-tab-spam-limits-configurable.patch index a6f013522a..c88867bf3a 100644 --- a/patches/server-remapped/0259-Break-up-and-make-tab-spam-limits-configurable.patch +++ b/patches/server/0239-Break-up-and-make-tab-spam-limits-configurable.patch @@ -45,31 +45,31 @@ index 77a03abd59db4a43f6f2d59d4c7ef176e782f205..bd508025b771424c942fd856c31d520b + } } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 645f7b7c862acf77d70ca0b05308945424bc4d32..900c9b1106a153bc386f6c3d9c11226f8ac69f86 100644 +index 902eab82912b9a7002485f73df7ae25e370b7e25..6ea367295d07c444d7cce0366261a884d299185a 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -228,6 +228,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -228,6 +228,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + private long keepAliveChallenge; // CraftBukkit start - multithreaded fields - private volatile int chatSpamTickCount; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(ServerGamePacketListenerImpl.class, "chatThrottle"); + private AtomicInteger chatSpamTickCount = new AtomicInteger(); + private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits // CraftBukkit end private int dropSpamTickCount; - private final Int2ShortMap expectedAcks = new Int2ShortOpenHashMap(); -@@ -363,6 +364,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + private double firstGoodX; +@@ -360,6 +361,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.server.getProfiler().pop(); // CraftBukkit start - for (int spam; (spam = this.chatSpamTickCount) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; + for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !this.chatSpamTickCount.compareAndSet(spam, spam - 1); ) ; + if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable /* Use thread-safe field access instead - if (this.chatThrottle > 0) { - --this.chatThrottle; -@@ -714,7 +716,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + if (this.chatSpamTickCount > 0) { + --this.chatSpamTickCount; +@@ -706,7 +708,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async // CraftBukkit start -- if (chatSpamField.addAndGet(this, 1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { -+ if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable +- if (this.chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ if (this.chatSpamTickCount.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper return; } diff --git a/patches/server/0240-MC-135506-Experience-should-save-as-Integers.patch b/patches/server/0240-MC-135506-Experience-should-save-as-Integers.patch new file mode 100644 index 0000000000..0136141c94 --- /dev/null +++ b/patches/server/0240-MC-135506-Experience-should-save-as-Integers.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 3 Aug 2018 00:04:54 -0400 +Subject: [PATCH] MC-135506: Experience should save as Integers + + +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 71fb831ed3359e7986e279c987211f39c581ab23..9c91d8453c6a1ad020ecab45775bd81302b817d3 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -286,7 +286,7 @@ public class ExperienceOrb extends Entity { + public void addAdditionalSaveData(CompoundTag nbt) { + nbt.putShort("Health", (short) this.health); + nbt.putShort("Age", (short) this.age); +- nbt.putShort("Value", (short) this.value); ++ nbt.putInt("Value", this.value); // Paper - save as Integer + nbt.putInt("Count", this.count); + this.savePaperNBT(nbt); // Paper + } +@@ -295,7 +295,7 @@ public class ExperienceOrb extends Entity { + public void readAdditionalSaveData(CompoundTag nbt) { + this.health = nbt.getShort("Health"); + this.age = nbt.getShort("Age"); +- this.value = nbt.getShort("Value"); ++ this.value = nbt.getInt("Value"); // Paper - load as Integer + this.count = Math.max(nbt.getInt("Count"), 1); + this.loadPaperNBT(nbt); // Paper + } diff --git a/patches/server-remapped/0262-Fix-client-rendering-skulls-from-same-user.patch b/patches/server/0241-Fix-client-rendering-skulls-from-same-user.patch similarity index 67% rename from patches/server-remapped/0262-Fix-client-rendering-skulls-from-same-user.patch rename to patches/server/0241-Fix-client-rendering-skulls-from-same-user.patch index 057731ba61..5864436e44 100644 --- a/patches/server-remapped/0262-Fix-client-rendering-skulls-from-same-user.patch +++ b/patches/server/0241-Fix-client-rendering-skulls-from-same-user.patch @@ -12,38 +12,30 @@ This allows the client to render multiple skull textures from the same user, for when different skins were used when skull was made. diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -index b4542ce6a8c37ab31e6ecaeb4cbad4742cca0f9b..10f1e3d761af83507bf71a00092641e22d0c8049 100644 +index c0966a873ea5e265936e17796bf6bbee62eea9b4..813814a09ad4c8040d9bf7fff12c8c7b88f164c2 100644 --- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java +++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -@@ -37,6 +37,7 @@ import net.minecraft.network.chat.Component; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.world.item.Item; - import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.level.block.entity.SkullBlockEntity; - import net.minecraft.world.phys.BlockHitResult; - import net.minecraft.world.phys.Vec3; - import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit -@@ -310,9 +311,18 @@ public class FriendlyByteBuf extends ByteBuf { +@@ -473,9 +473,18 @@ public class FriendlyByteBuf extends ByteBuf { if (item.canBeDepleted() || item.shouldOverrideMultiplayerNbt()) { // Spigot start - filter - itemstack = itemstack.copy(); -- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); -+ //CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported + stack = stack.copy(); +- CraftItemStack.setItemMeta(stack, CraftItemStack.getItemMeta(stack)); ++ // CraftItemStack.setItemMeta(stack, CraftItemStack.getItemMeta(stack)); // Paper - This is no longer needed due to NBT being supported // Spigot end - nbttagcompound = itemstack.getTag(); + nbttagcompound = stack.getTag(); + // Paper start + if (nbttagcompound != null && nbttagcompound.contains("SkullOwner", 10)) { + CompoundTag owner = nbttagcompound.getCompound("SkullOwner"); + if (owner.hasUUID("Id")) { + nbttagcompound.setUUID("SkullOwnerOrig", owner.getUUID("Id")); -+ SkullBlockEntity.sanitizeUUID(owner); ++ net.minecraft.world.level.block.entity.SkullBlockEntity.sanitizeUUID(owner); + } + } + // Paper end } this.writeNbt(nbttagcompound); -@@ -332,7 +342,16 @@ public class FriendlyByteBuf extends ByteBuf { +@@ -495,7 +504,16 @@ public class FriendlyByteBuf extends ByteBuf { itemstack.setTag(this.readNbt()); // CraftBukkit start if (itemstack.getTag() != null) { @@ -62,30 +54,22 @@ index b4542ce6a8c37ab31e6ecaeb4cbad4742cca0f9b..10f1e3d761af83507bf71a00092641e2 // CraftBukkit end return itemstack; diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -index e5d4363edb8c494d2db69d2e0223a2db1519f64b..4fe15aa331ca18319ca46d1b426f0d6fd24341f0 100644 +index 3bdb09ab00ec05ed532a0c26b9fd321e1f05c1a0..1451a98d69b185dd15a2d1d7681bcecb6a4f99c1 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -@@ -15,6 +15,7 @@ import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.protocol.Packet; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.block.entity.BlockEntity; -+import net.minecraft.world.level.block.entity.SkullBlockEntity; - import net.minecraft.world.level.chunk.ChunkBiomeContainer; - import net.minecraft.world.level.chunk.LevelChunk; - import net.minecraft.world.level.chunk.LevelChunkSection; -@@ -69,6 +70,7 @@ public class ClientboundLevelChunkPacket implements Packet entry2 : chunk.getBlockEntities().entrySet()) { + BlockEntity blockEntity = entry2.getValue(); + CompoundTag compoundTag = blockEntity.getUpdateTag(); ++ if (blockEntity instanceof net.minecraft.world.level.block.entity.SkullBlockEntity) { net.minecraft.world.level.block.entity.SkullBlockEntity.sanitizeTileEntityUUID(compoundTag); } // Paper + this.blockEntitiesTags.add(compoundTag); + } - if (this.isFullChunk() || (includedSectionsMask & 1 << j) != 0) { - CompoundTag nbttagcompound = tileentity.getUpdateTag(); -+ if (tileentity instanceof SkullBlockEntity) { SkullBlockEntity.sanitizeTileEntityUUID(nbttagcompound); } // Paper - - this.blockEntitiesTags.add(nbttagcompound); - } diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 34187197efd5ceff0503682dc6ce313220ca916f..79a7c37f15840dbd97510874ac12437d2b854999 100644 +index 4d4b471bbfb2d9174391c8adc6075ec11295408b..8b3cf3b882ea6c0d48df8b551f4b85b87b889c58 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -112,7 +112,7 @@ public final class ItemStack { +@@ -143,7 +143,7 @@ public final class ItemStack { private int popTime; @Deprecated private Item item; @@ -95,18 +79,18 @@ index 34187197efd5ceff0503682dc6ce313220ca916f..79a7c37f15840dbd97510874ac12437d private Entity entityRepresentation; private BlockInWorld cachedBreakBlock; diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java -index eebaeaccc3ba1a9ec089d84b8de6c9d36034868f..6a1289424421083876d1808b7328cd3f01063a7e 100644 +index eaf586eb386e13e954bc593f6ddbc45929cec204..f0192a009f6a21d1781ce709624a9187048d9a08 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java -@@ -25,6 +25,7 @@ import java.util.concurrent.Executors; - import java.util.concurrent.Future; - import java.util.concurrent.TimeUnit; +@@ -10,6 +10,7 @@ import java.util.function.Consumer; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; - import net.minecraft.server.MinecraftServer; -@@ -152,9 +153,37 @@ public class SkullBlockEntity extends BlockEntity /*implements ITickable*/ { // + import net.minecraft.server.players.GameProfileCache; +@@ -91,9 +92,37 @@ public class SkullBlockEntity extends BlockEntity { @Nullable @Override public ClientboundBlockEntityDataPacket getUpdatePacket() { diff --git a/patches/server-remapped/0263-Add-Early-Warning-Feature-to-WatchDog.patch b/patches/server/0242-Add-Early-Warning-Feature-to-WatchDog.patch similarity index 78% rename from patches/server-remapped/0263-Add-Early-Warning-Feature-to-WatchDog.patch rename to patches/server/0242-Add-Early-Warning-Feature-to-WatchDog.patch index 4f9ee3cc3e..35278841db 100644 --- a/patches/server-remapped/0263-Add-Early-Warning-Feature-to-WatchDog.patch +++ b/patches/server/0242-Add-Early-Warning-Feature-to-WatchDog.patch @@ -36,10 +36,10 @@ index bd508025b771424c942fd856c31d520b6f548082..62621562137cba4804f0465c58d25ca2 public static int tabSpamLimit = 500; private static void tabSpamLimiters() { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 125a75576442eaa4f1ff6dd153bdb31097497a3f..5a76ca77b974ff6fe862c9e05a88b507a34b44be 100644 +index a0c436fd5e7e03a0a01e59c046e65ebdcd88021a..cf92c3275869e4a0209fd4b07ad723e11717dc86 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1017,6 +1017,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable + // +- if ( this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.monotonicMillis() > this.lastTick + this.timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable + // Paper start + Logger log = Bukkit.getServer().getLogger(); -+ long currentTime = monotonicMillis(); -+ if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) ++ long currentTime = WatchdogThread.monotonicMillis(); ++ if ( this.lastTick != 0 && this.timeoutTime > 0 && currentTime > this.lastTick + this.earlyWarningEvery && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable { - Logger log = Bukkit.getServer().getLogger(); + boolean isLongTimeout = currentTime > lastTick + timeoutTime; @@ -134,7 +133,7 @@ index ee0cca25ef458f2f0f7e450a2edea2b2adb7e846..16f6163bb53e73aa4ab6e22365342613 log.log( Level.SEVERE, "------------------------------" ); log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); -@@ -93,29 +108,46 @@ public class WatchdogThread extends Thread +@@ -93,29 +109,45 @@ public class WatchdogThread extends Thread } } // Paper end @@ -146,7 +145,7 @@ index ee0cca25ef458f2f0f7e450a2edea2b2adb7e846..16f6163bb53e73aa4ab6e22365342613 + // Paper end - Different message for short timeout log.log( Level.SEVERE, "------------------------------" ); log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); log.log( Level.SEVERE, "------------------------------" ); // + // Paper start - Only print full dump on long timeouts @@ -156,18 +155,17 @@ index ee0cca25ef458f2f0f7e450a2edea2b2adb7e846..16f6163bb53e73aa4ab6e22365342613 ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); for ( ThreadInfo thread : threads ) { - dumpThread( thread, log ); + WatchdogThread.dumpThread( thread, log ); } + } else { + log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---"); + } -+ + log.log( Level.SEVERE, "------------------------------" ); + if ( isLongTimeout ) + { - if ( restart && !MinecraftServer.getServer().hasStopped() ) + if ( this.restart && !MinecraftServer.getServer().hasStopped() ) { RestartCommand.restart(); } diff --git a/patches/server-remapped/0264-Make-EnderDragon-implement-Mob.patch b/patches/server/0243-Make-EnderDragon-implement-Mob.patch similarity index 100% rename from patches/server-remapped/0264-Make-EnderDragon-implement-Mob.patch rename to patches/server/0243-Make-EnderDragon-implement-Mob.patch diff --git a/patches/server-remapped/0265-Use-ConcurrentHashMap-in-JsonList.patch b/patches/server/0244-Use-ConcurrentHashMap-in-JsonList.patch similarity index 84% rename from patches/server-remapped/0265-Use-ConcurrentHashMap-in-JsonList.patch rename to patches/server/0244-Use-ConcurrentHashMap-in-JsonList.patch index b981b8b044..2500d0813a 100644 --- a/patches/server-remapped/0265-Use-ConcurrentHashMap-in-JsonList.patch +++ b/patches/server/0244-Use-ConcurrentHashMap-in-JsonList.patch @@ -25,20 +25,20 @@ The point of this is readability, but does have a side-benefit of a small microp Finally, added a couple obfhelpers for the modified code diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0bb397407b55bd1c464ac603ec4c189045aabbb2..7c307a16ca3962db65be09a0ddd058a4ce81c7be 100644 +index 7c5a75fb34640bb4e7ef839412dbb30b0d0fc8e8..b62aa9f934c33b4d22b985b5e56937baa8454677 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -614,7 +614,7 @@ public abstract class PlayerList { +@@ -610,7 +610,7 @@ public abstract class PlayerList { } else if (!this.isWhitelisted(gameprofile, event)) { // Paper //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted -- } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { -+ } else if (getIpBans().isBanned(socketaddress) && getIpBans().get(socketaddress) != null && !getIpBans().get(socketaddress).hasExpired()) { // Paper - fix NPE with temp ip bans +- } else if (this.getIpBans().isBanned(socketaddress) && !this.getIpBans().get(socketaddress).hasExpired()) { ++ } else if (this.getIpBans().isBanned(socketaddress) && getIpBans().get(socketaddress) != null && !this.getIpBans().get(socketaddress).hasExpired()) { // Paper - fix NPE with temp ip bans IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); chatmessage = new TranslatableComponent("multiplayer.disconnect.banned_ip.reason", new Object[]{ipbanentry.getReason()}); diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java -index 2cb235d695c244863a37454df22d5d94a291524d..e2982a8ac5448110378bc92247952332bdffe12c 100644 +index 00e3662e25618459447d4ce5f56f7e046bfe47e2..4b85943a704e0a5ca6b95f9cfcbfd1f9505c3b68 100644 --- a/src/main/java/net/minecraft/server/players/StoredUserList.java +++ b/src/main/java/net/minecraft/server/players/StoredUserList.java @@ -12,6 +12,8 @@ import java.io.BufferedReader; @@ -50,7 +50,7 @@ index 2cb235d695c244863a37454df22d5d94a291524d..e2982a8ac5448110378bc92247952332 import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Iterator; -@@ -28,7 +30,22 @@ public abstract class StoredUserList> { +@@ -30,7 +32,22 @@ public abstract class StoredUserList> { protected static final Logger LOGGER = LogManager.getLogger(); private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create(); private final File file; @@ -74,7 +74,7 @@ index 2cb235d695c244863a37454df22d5d94a291524d..e2982a8ac5448110378bc92247952332 public StoredUserList(File file) { this.file = file; -@@ -51,8 +68,13 @@ public abstract class StoredUserList> { +@@ -53,8 +70,13 @@ public abstract class StoredUserList> { @Nullable public V get(K key) { @@ -90,7 +90,7 @@ index 2cb235d695c244863a37454df22d5d94a291524d..e2982a8ac5448110378bc92247952332 } public void remove(K key) { -@@ -81,9 +103,11 @@ public abstract class StoredUserList> { +@@ -83,9 +105,11 @@ public abstract class StoredUserList> { // CraftBukkit end public boolean isEmpty() { @@ -103,7 +103,7 @@ index 2cb235d695c244863a37454df22d5d94a291524d..e2982a8ac5448110378bc92247952332 protected String getKeyForUser(K profile) { return profile.toString(); } -@@ -92,15 +116,16 @@ public abstract class StoredUserList> { +@@ -94,15 +118,16 @@ public abstract class StoredUserList> { return this.map.containsKey(this.getKeyForUser(k0)); } @@ -123,7 +123,7 @@ index 2cb235d695c244863a37454df22d5d94a291524d..e2982a8ac5448110378bc92247952332 } } -@@ -109,9 +134,11 @@ public abstract class StoredUserList> { +@@ -111,9 +136,11 @@ public abstract class StoredUserList> { while (iterator.hasNext()) { K k0 = (K) iterator.next(); // CraftBukkit - decompile error @@ -137,11 +137,11 @@ index 2cb235d695c244863a37454df22d5d94a291524d..e2982a8ac5448110378bc92247952332 } protected abstract StoredUserEntry createEntry(JsonObject json); -@@ -121,6 +148,7 @@ public abstract class StoredUserList> { +@@ -123,6 +150,7 @@ public abstract class StoredUserList> { } public void save() throws IOException { + this.removeStaleEntries(); // Paper - remove expired values before saving JsonArray jsonarray = new JsonArray(); - - this.map.values().stream().map((jsonlistentry) -> { + Stream stream = this.map.values().stream().map((jsonlistentry) -> { // CraftBukkit - decompile error + JsonObject jsonobject = new JsonObject(); diff --git a/patches/server-remapped/0266-Use-a-Queue-for-Queueing-Commands.patch b/patches/server/0245-Use-a-Queue-for-Queueing-Commands.patch similarity index 84% rename from patches/server-remapped/0266-Use-a-Queue-for-Queueing-Commands.patch rename to patches/server/0245-Use-a-Queue-for-Queueing-Commands.patch index b220fa4eb9..949a914440 100644 --- a/patches/server-remapped/0266-Use-a-Queue-for-Queueing-Commands.patch +++ b/patches/server/0245-Use-a-Queue-for-Queueing-Commands.patch @@ -6,19 +6,19 @@ Subject: [PATCH] Use a Queue for Queueing Commands Lists are bad as Queues mmmkay. diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 9143fe99e43236bf65e6f098a30d522302ad78b7..4862a9519d4ba5f05b634a0335837bea9812edee 100644 +index 45ae21718df16e16b5a3835a92afbf714959950e..6f9b7c3cf22d0c44f31b81bcbfa3cb1f8c065083 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -72,7 +72,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - - private static final Logger LOGGER = LogManager.getLogger(); +@@ -78,7 +78,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + private static final int CONVERSION_RETRY_DELAY_MS = 5000; + private static final int CONVERSION_RETRIES = 2; private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$"); - private final List consoleInput = Collections.synchronizedList(Lists.newArrayList()); + private final java.util.Queue serverCommandQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Paper - use a proper queue private QueryThreadGs4 queryThreadGs4; public final RconConsoleSource rconConsoleSource; private RconThread rconThread; -@@ -426,13 +426,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -473,13 +473,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } public void handleConsoleInput(String command, CommandSourceStack commandSource) { diff --git a/patches/server-remapped/0267-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/patches/server/0246-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch similarity index 71% rename from patches/server-remapped/0267-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch rename to patches/server/0246-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch index 52dbc8ee7e..9b7b000848 100644 --- a/patches/server-remapped/0267-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch +++ b/patches/server/0246-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Ability to get Tile Entities from a chunk without snapshots diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index 93b9e9d5932764f7e946dd3f8ab8191189c5d38f..423594177fe78600755d913f169f28dd1bfa2b37 100644 +index 810fb066b76dc915a050cc1fb80b6efc7538becc..245d764d3dcc549fa8acbd7c9024a3c88d2d2a74 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java @@ -3,8 +3,10 @@ package org.bukkit.craftbukkit; @@ -19,7 +19,7 @@ index 93b9e9d5932764f7e946dd3f8ab8191189c5d38f..423594177fe78600755d913f169f28dd import java.util.function.Predicate; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; -@@ -129,9 +131,16 @@ public class CraftChunk implements Chunk { +@@ -117,6 +119,13 @@ public class CraftChunk implements Chunk { @Override public BlockState[] getTileEntities() { @@ -29,25 +29,22 @@ index 93b9e9d5932764f7e946dd3f8ab8191189c5d38f..423594177fe78600755d913f169f28dd + + @Override + public BlockState[] getTileEntities(boolean useSnapshot) { - if (!isLoaded()) { - getWorld().getChunkAt(x, z); // Transient load for this tick - } + // Paper end - int index = 0; - net.minecraft.world.level.chunk.LevelChunk chunk = getHandle(); - -@@ -143,11 +152,33 @@ public class CraftChunk implements Chunk { + if (!this.isLoaded()) { + this.getWorld().getChunkAt(x, z); // Transient load for this tick + } +@@ -131,7 +140,29 @@ public class CraftChunk implements Chunk { } BlockPos position = (BlockPos) obj; -- entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(); -+ entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(useSnapshot); // Paper +- entities[index++] = this.worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(); ++ // Paper start ++ entities[index++] = this.worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(useSnapshot); + } + + return entities; + } + -+ // Paper start + @Override + public Collection getTileEntities(Predicate blockPredicate, boolean useSnapshot) { + Preconditions.checkNotNull(blockPredicate, "blockPredicate"); @@ -63,11 +60,7 @@ index 93b9e9d5932764f7e946dd3f8ab8191189c5d38f..423594177fe78600755d913f169f28dd + if (blockPredicate.test(block)) { + entities.add(block.getState(useSnapshot)); + } ++ // Paper end } return entities; - } -+ // Paper end - - @Override - public boolean isLoaded() { diff --git a/patches/server-remapped/0269-Optimize-BlockPosition-helper-methods.patch b/patches/server/0247-Optimize-BlockPosition-helper-methods.patch similarity index 86% rename from patches/server-remapped/0269-Optimize-BlockPosition-helper-methods.patch rename to patches/server/0247-Optimize-BlockPosition-helper-methods.patch index fa154eb153..b31d553b36 100644 --- a/patches/server-remapped/0269-Optimize-BlockPosition-helper-methods.patch +++ b/patches/server/0247-Optimize-BlockPosition-helper-methods.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Optimize BlockPosition helper methods Resolves #1338 diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index c5089b0da33a68e7cadbc4841b07f9d772d224a0..b13e5d05d862ea8c6031b8071f525f00bc48f7e7 100644 +index c2309751e3798874eee6b469129121c2e317fbc3..dd1d76867ac3832ad515f304925c595c9a021c8f 100644 --- a/src/main/java/net/minecraft/core/BlockPos.java +++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -121,58 +121,75 @@ public class BlockPos extends Vec3i { +@@ -131,67 +131,84 @@ public class BlockPos extends Vec3i { @Override public BlockPos above() { @@ -30,53 +30,61 @@ index c5089b0da33a68e7cadbc4841b07f9d772d224a0..b13e5d05d862ea8c6031b8071f525f00 } @Override - public BlockPos below(int distance) { -- return this.relative(Direction.DOWN, distance); -+ return distance == 0 ? this : new BlockPos(this.getX(), this.getY() - distance, this.getZ()); // Paper - Optimize BlockPosition + public BlockPos below(int i) { +- return this.relative(Direction.DOWN, i); ++ return i == 0 ? this : new BlockPos(this.getX(), this.getY() - i, this.getZ()); // Paper - Optimize BlockPosition } + @Override public BlockPos north() { - return this.relative(Direction.NORTH); + return new BlockPos(this.getX(), this.getY(), this.getZ() - 1); // Paper - Optimize BlockPosition } + @Override public BlockPos north(int distance) { - return this.relative(Direction.NORTH, distance); + return distance == 0 ? this : new BlockPos(this.getX(), this.getY(), this.getZ() - distance); // Paper - Optimize BlockPosition } + @Override public BlockPos south() { - return this.relative(Direction.SOUTH); + return new BlockPos(this.getX(), this.getY(), this.getZ() + 1); // Paper - Optimize BlockPosition } + @Override public BlockPos south(int distance) { - return this.relative(Direction.SOUTH, distance); + return distance == 0 ? this : new BlockPos(this.getX(), this.getY(), this.getZ() + distance); // Paper - Optimize BlockPosition } + @Override public BlockPos west() { - return this.relative(Direction.WEST); + return new BlockPos(this.getX() - 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition } + @Override public BlockPos west(int distance) { - return this.relative(Direction.WEST, distance); + return distance == 0 ? this : new BlockPos(this.getX() - distance, this.getY(), this.getZ()); // Paper - Optimize BlockPosition } + @Override public BlockPos east() { - return this.relative(Direction.EAST); + return new BlockPos(this.getX() + 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition } + @Override public BlockPos east(int distance) { - return this.relative(Direction.EAST, distance); + return distance == 0 ? this : new BlockPos(this.getX() + distance, this.getY(), this.getZ()); // Paper - Optimize BlockPosition } + @Override public BlockPos relative(Direction direction) { -- return new BlockPos(this.getX() + direction.getStepX(), this.getY() + direction.getStepY(), this.getZ() + direction.getStepZ()); + // Paper Start - Optimize BlockPosition + switch(direction) { + case UP: @@ -92,7 +100,7 @@ index c5089b0da33a68e7cadbc4841b07f9d772d224a0..b13e5d05d862ea8c6031b8071f525f00 + case EAST: + return new BlockPos(this.getX() + 1, this.getY(), this.getZ()); + default: -+ return new BlockPos(this.getX() + direction.getStepX(), this.getY() + direction.getStepY(), this.getZ() + direction.getStepZ()); + return new BlockPos(this.getX() + direction.getStepX(), this.getY() + direction.getStepY(), this.getZ() + direction.getStepZ()); + } + // Paper End } diff --git a/patches/server-remapped/0270-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/patches/server/0248-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch similarity index 76% rename from patches/server-remapped/0270-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch rename to patches/server/0248-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch index 50cfc368af..84ff27f268 100644 --- a/patches/server-remapped/0270-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch +++ b/patches/server/0248-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch @@ -6,16 +6,16 @@ Subject: [PATCH] Restore vanlla default mob-spawn-range and water animals diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 0efcbab8f8806aeb8dd8bd6384e5a7cee375d100..34ee684901906fc2ef5f0d09680d2686b813e52b 100644 +index 9a31d8b709b28bba658603106c623560c5362947..8e6eae7cc27f66faede9a3dc74571e1814df3652 100644 --- a/src/main/java/org/spigotmc/SpigotWorldConfig.java +++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java @@ -165,7 +165,7 @@ public class SpigotWorldConfig public byte mobSpawnRange; private void mobSpawnRange() { -- mobSpawnRange = (byte) getInt( "mob-spawn-range", 6 ); -+ mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla - log( "Mob Spawn Range: " + mobSpawnRange ); +- this.mobSpawnRange = (byte) this.getInt( "mob-spawn-range", 6 ); ++ this.mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla + this.log( "Mob Spawn Range: " + this.mobSpawnRange ); } diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml diff --git a/patches/server/0249-Slime-Pathfinder-Events.patch b/patches/server/0249-Slime-Pathfinder-Events.patch new file mode 100644 index 0000000000..4cb18162ec --- /dev/null +++ b/patches/server/0249-Slime-Pathfinder-Events.patch @@ -0,0 +1,167 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 24 Aug 2018 08:18:42 -0500 +Subject: [PATCH] Slime Pathfinder Events + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java +index 53130b34e5964acec191e1d8de6bde996f498699..6a199e148929d8df9b1f39733dd821c503380973 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java +@@ -44,6 +44,12 @@ import net.minecraft.world.level.biome.Biomes; + import net.minecraft.world.level.levelgen.WorldgenRandom; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + import net.minecraft.world.phys.Vec3; ++// Paper start ++import com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent; ++import com.destroystokyo.paper.event.entity.SlimeSwimEvent; ++import com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent; ++import com.destroystokyo.paper.event.entity.SlimeWanderEvent; ++// Paper end + // CraftBukkit start + import java.util.ArrayList; + import java.util.List; +@@ -108,6 +114,7 @@ public class Slime extends Mob implements Enemy { + @Override + public void addAdditionalSaveData(CompoundTag nbt) { + super.addAdditionalSaveData(nbt); ++ nbt.putBoolean("Paper.canWander", this.canWander); // Paper + nbt.putInt("Size", this.getSize() - 1); + nbt.putBoolean("wasOnGround", this.wasOnGround); + } +@@ -116,6 +123,11 @@ public class Slime extends Mob implements Enemy { + public void readAdditionalSaveData(CompoundTag nbt) { + this.setSize(nbt.getInt("Size") + 1, false); + super.readAdditionalSaveData(nbt); ++ // Paper start - check exists before loading or this will be loaded as false ++ if (nbt.contains("Paper.canWander")) { ++ this.canWander = nbt.getBoolean("Paper.canWander"); ++ } ++ // Paper end + this.wasOnGround = nbt.getBoolean("wasOnGround"); + } + +@@ -453,7 +465,7 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; ++ return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new SlimeSwimEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper + } + + @Override +@@ -480,7 +492,15 @@ public class Slime extends Mob implements Enemy { + public boolean canUse() { + LivingEntity entityliving = this.slime.getTarget(); + +- return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : this.slime.getMoveControl() instanceof Slime.SlimeMoveControl); ++ // Paper start ++ if (entityliving == null || !entityliving.isAlive()) { ++ return false; ++ } ++ if (!this.slime.canAttack(entityliving)) { ++ return false; ++ } ++ return this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity()).callEvent(); ++ // Paper end + } + + @Override +@@ -493,7 +513,15 @@ public class Slime extends Mob implements Enemy { + public boolean canContinueToUse() { + LivingEntity entityliving = this.slime.getTarget(); + +- return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : --this.growTiredTimer > 0); ++ // Paper start ++ if (entityliving == null || !entityliving.isAlive()) { ++ return false; ++ } ++ if (!this.slime.canAttack(entityliving)) { ++ return false; ++ } ++ return --this.growTiredTimer > 0 && this.slime.canWander && new SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity()).callEvent(); ++ // Paper end + } + + @Override +@@ -501,6 +529,13 @@ public class Slime extends Mob implements Enemy { + this.slime.lookAt((Entity) this.slime.getTarget(), 10.0F, 10.0F); + ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.slime.getYRot(), this.slime.isDealsDamage()); + } ++ ++ // Paper start - clear timer and target when goal resets ++ public void stop() { ++ this.growTiredTimer = 0; ++ this.slime.setTarget(null); ++ } ++ // Paper end + } + + private static class SlimeRandomDirectionGoal extends Goal { +@@ -516,14 +551,18 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- return this.slime.getTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; ++ return this.slime.getTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander; // Paper - add canWander + } + + @Override + public void tick() { + if (--this.nextRandomizeTime <= 0) { + this.nextRandomizeTime = 40 + this.slime.getRandom().nextInt(60); +- this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); ++ // Paper start ++ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (float) this.slime.getRandom().nextInt(360)); ++ if (!this.slime.canWander || !event.callEvent()) return; ++ this.chosenDegrees = event.getNewYaw(); ++ // Paper end + } + + ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.chosenDegrees, false); +@@ -541,7 +580,7 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- return !this.slime.isPassenger(); ++ return !this.slime.isPassenger() && this.slime.canWander && new SlimeWanderEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper + } + + @Override +@@ -549,4 +588,15 @@ public class Slime extends Mob implements Enemy { + ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setWantedMovement(1.0D); + } + } ++ ++ // Paper start ++ private boolean canWander = true; ++ public boolean canWander() { ++ return canWander; ++ } ++ ++ public void setWander(boolean canWander) { ++ this.canWander = canWander; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +index 67fc37f909639e1effe6034526990f10d575d14d..4d401403de2399919043651345eed91c11ac986f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +@@ -34,4 +34,16 @@ public class CraftSlime extends CraftMob implements Slime { + public EntityType getType() { + return EntityType.SLIME; + } ++ ++ // Paper start ++ @Override ++ public boolean canWander() { ++ return getHandle().canWander(); ++ } ++ ++ @Override ++ public void setWander(boolean canWander) { ++ getHandle().setWander(canWander); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0272-Configurable-speed-for-water-flowing-over-lava.patch b/patches/server/0250-Configurable-speed-for-water-flowing-over-lava.patch similarity index 69% rename from patches/server-remapped/0272-Configurable-speed-for-water-flowing-over-lava.patch rename to patches/server/0250-Configurable-speed-for-water-flowing-over-lava.patch index c8fef8a86f..a2e8efe507 100644 --- a/patches/server-remapped/0272-Configurable-speed-for-water-flowing-over-lava.patch +++ b/patches/server/0250-Configurable-speed-for-water-flowing-over-lava.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable speed for water flowing over lava diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5ab0e7183e48134b7a0f736462516b1a8a333b04..f280dbff4a09bc611a9ca565c6d697d08801f53b 100644 +index 8bb33e1b631c3aa99cef2a63c140f0b0e11325e0..c17c504acdc12b6ef37d6643eb98a57fa5ca40c9 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -390,4 +390,10 @@ public class PaperWorldConfig { +@@ -384,4 +384,10 @@ public class PaperWorldConfig { this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); } @@ -20,23 +20,23 @@ index 5ab0e7183e48134b7a0f736462516b1a8a333b04..f280dbff4a09bc611a9ca565c6d697d0 + } } diff --git a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java -index f99b90e4b3210747077f2bf3adbcf7b5fb9821ec..97f2d9082e49010fb8780c5fdd8957f71b31e43e 100644 +index db4bcb600ab43439ef65d4510fb20d770ce9dba3..087601ffdeea97ec4cbb9959607bdcbcbae7c6fa 100644 --- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java +++ b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java -@@ -23,6 +23,7 @@ import net.minecraft.world.level.material.FlowingFluid; +@@ -26,6 +26,7 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.material.FlowingFluid; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; - import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.level.material.Material; import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.phys.shapes.CollisionContext; -@@ -100,11 +101,28 @@ public class LiquidBlock extends Block implements BucketPickup { +@@ -109,11 +110,27 @@ public class LiquidBlock extends Block implements BucketPickup { @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { if (this.shouldSpreadLiquid(world, pos, state)) { -- world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); -+ world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper +- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); ++ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper } } @@ -56,17 +56,16 @@ index f99b90e4b3210747077f2bf3adbcf7b5fb9821ec..97f2d9082e49010fb8780c5fdd8957f7 + return this.fluid.getTickDelay(world); + } + // Paper end -+ + @Override - public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { - if (state.getFluidState().isSource() || newState.getFluidState().isSource()) { -@@ -117,7 +135,7 @@ public class LiquidBlock extends Block implements BucketPickup { + public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { + if (state.getFluidState().isSource() || neighborState.getFluidState().isSource()) { +@@ -126,7 +143,7 @@ public class LiquidBlock extends Block implements BucketPickup { @Override public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { if (this.shouldSpreadLiquid(world, pos, state)) { -- world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); -+ world.getLiquidTicks().a(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper +- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); ++ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper } } diff --git a/patches/server-remapped/0273-Optimize-CraftBlockData-Creation.patch b/patches/server/0251-Optimize-CraftBlockData-Creation.patch similarity index 84% rename from patches/server-remapped/0273-Optimize-CraftBlockData-Creation.patch rename to patches/server/0251-Optimize-CraftBlockData-Creation.patch index b9e1c45f8f..ddae1a7ae7 100644 --- a/patches/server-remapped/0273-Optimize-CraftBlockData-Creation.patch +++ b/patches/server/0251-Optimize-CraftBlockData-Creation.patch @@ -7,10 +7,10 @@ Avoids a hashmap lookup by cacheing a reference to the CraftBlockData and cloning it when one is needed. diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index 5d7794c9533bd37193f196bda616adaaace2bbde..57eedaeedaa24bd274fb55c6e4521f1305382645 100644 +index 549eb8a5f0f20db88abd17136f69f7bb00883011..d99ca942f5885b4d9af054547832c05ddb5634eb 100644 --- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -374,6 +374,14 @@ public abstract class BlockBehaviour { +@@ -637,6 +637,14 @@ public abstract class BlockBehaviour { this.hasPostProcess = blockbase_info.hasPostProcess; this.emissiveRendering = blockbase_info.emissiveRendering; } @@ -26,10 +26,10 @@ index 5d7794c9533bd37193f196bda616adaaace2bbde..57eedaeedaa24bd274fb55c6e4521f13 public void initCache() { if (!this.getBlock().hasDynamicShape()) { diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -index 3a90b504ebbe86350f5fee5baa818e40d884d24f..0b6c6dfc380cea87bd88c3eb8a199e072dcbf56c 100644 +index c6a9ce2a67591205cbeb436b5043e737331c3527..3594f432a25b580173e8577bf324be954f5eddd1 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -@@ -509,7 +509,17 @@ public class CraftBlockData implements BlockData { +@@ -527,7 +527,17 @@ public class CraftBlockData implements BlockData { return craft; } @@ -44,6 +44,6 @@ index 3a90b504ebbe86350f5fee5baa818e40d884d24f..0b6c6dfc380cea87bd88c3eb8a199e07 + + public static CraftBlockData createData(BlockState data) { + // Paper end - return MAP.getOrDefault(data.getBlock().getClass(), CraftBlockData::new).apply(data); + return CraftBlockData.MAP.getOrDefault(data.getBlock().getClass(), CraftBlockData::new).apply(data); } diff --git a/patches/server/0252-Optimize-MappedRegistry.patch b/patches/server/0252-Optimize-MappedRegistry.patch new file mode 100644 index 0000000000..047b65a8df --- /dev/null +++ b/patches/server/0252-Optimize-MappedRegistry.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 26 Aug 2018 20:49:50 -0400 +Subject: [PATCH] Optimize MappedRegistry + +Use larger initial sizes to increase bucket capacity on the BiMap + +BiMap.get was seen to be using a good bit of CPU time. + +diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java +index 889c213205738ba637a28895977714df2d025b6d..87ea9b851531ac98a2dce66651f1730c5eb5e7d4 100644 +--- a/src/main/java/net/minecraft/core/MappedRegistry.java ++++ b/src/main/java/net/minecraft/core/MappedRegistry.java +@@ -37,7 +37,7 @@ import org.apache.logging.log4j.Logger; + public class MappedRegistry extends WritableRegistry { + protected static final Logger LOGGER = LogManager.getLogger(); + private final ObjectList byId = new ObjectArrayList<>(256); +- private final Object2IntMap toId = new Object2IntOpenCustomHashMap<>(Util.identityStrategy()); ++ private final it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap toId = new it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map + private final BiMap storage; + private final BiMap, T> keyStorage; + private final Map lifecycles; +@@ -48,9 +48,9 @@ public class MappedRegistry extends WritableRegistry { + public MappedRegistry(ResourceKey> key, Lifecycle lifecycle) { + super(key, lifecycle); + this.toId.defaultReturnValue(-1); +- this.storage = HashBiMap.create(); +- this.keyStorage = HashBiMap.create(); +- this.lifecycles = Maps.newIdentityHashMap(); ++ this.storage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions ++ this.keyStorage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions ++ this.lifecycles = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions + this.elementsLifecycle = lifecycle; + } + diff --git a/patches/server-remapped/0275-Add-PhantomPreSpawnEvent.patch b/patches/server/0253-Add-PhantomPreSpawnEvent.patch similarity index 81% rename from patches/server-remapped/0275-Add-PhantomPreSpawnEvent.patch rename to patches/server/0253-Add-PhantomPreSpawnEvent.patch index a3b507be83..e68cfb61b6 100644 --- a/patches/server-remapped/0275-Add-PhantomPreSpawnEvent.patch +++ b/patches/server/0253-Add-PhantomPreSpawnEvent.patch @@ -5,34 +5,34 @@ Subject: [PATCH] Add PhantomPreSpawnEvent diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index 4a2fecdfbda34d6360d50e2ac017907a62b4a043..e37137a2890330b92e05d6f76c46ffc99a527803 100644 +index dcfd0b107ac7bd1633f3b681cd5f5e26ce87bd63..2ddb7b4c0a75c6f41910c84c8b9341f56fcb1116 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java +++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -@@ -161,6 +161,11 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -172,6 +172,11 @@ public class Phantom extends FlyingMob implements Enemy { } - this.setPhantomSize(tag.getInt("Size")); + this.setPhantomSize(nbt.getInt("Size")); + // Paper start -+ if (tag.hasUUID("Paper.SpawningEntity")) { -+ this.spawningEntity = tag.getUUID("Paper.SpawningEntity"); ++ if (nbt.hasUUID("Paper.SpawningEntity")) { ++ this.spawningEntity = nbt.getUUID("Paper.SpawningEntity"); + } + // Paper end } @Override -@@ -170,6 +175,11 @@ public class Phantom extends FlyingMob implements Enemy { - tag.putInt("AY", this.anchorPoint.getY()); - tag.putInt("AZ", this.anchorPoint.getZ()); - tag.putInt("Size", this.getPhantomSize()); +@@ -181,6 +186,11 @@ public class Phantom extends FlyingMob implements Enemy { + nbt.putInt("AY", this.anchorPoint.getY()); + nbt.putInt("AZ", this.anchorPoint.getZ()); + nbt.putInt("Size", this.getPhantomSize()); + // Paper start + if (this.spawningEntity != null) { -+ tag.setUUID("Paper.SpawningEntity", this.spawningEntity); ++ nbt.setUUID("Paper.SpawningEntity", this.spawningEntity); + } + // Paper end } @Override -@@ -216,6 +226,15 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -232,6 +242,14 @@ public class Phantom extends FlyingMob implements Enemy { return entitysize.scale(f); } @@ -44,10 +44,9 @@ index 4a2fecdfbda34d6360d50e2ac017907a62b4a043..e37137a2890330b92e05d6f76c46ffc9 + } + public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } + // Paper end -+ - class PhantomAttackPlayerTargetGoal extends Goal { + private static enum AttackPhase { - private final TargetingConditions attackTargeting; + CIRCLE, SWOOP; diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java index ee18e2826f6390ef5a29557b733fd00db5bc409f..42effcbd3ca7c38a4e8b1aa835543ad243112a33 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java @@ -80,15 +79,16 @@ index ee18e2826f6390ef5a29557b733fd00db5bc409f..42effcbd3ca7c38a4e8b1aa835543ad2 groupdataentity = entityphantom.finalizeSpawn(world, difficultydamagescaler, MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); world.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -index 15eb09595dad996314c169f9dd7d381e43f77be9..92162fa22f5e98b7837bde5830bd47c31b8b52d8 100644 +index f77b83bee6eb739220b55793a0807f0267cfc8a9..c9dab70b0b284fe1c1daafd3c1f5bd08b14fa35d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -@@ -34,4 +34,10 @@ public class CraftPhantom extends CraftFlying implements Phantom { +@@ -34,4 +34,11 @@ public class CraftPhantom extends CraftFlying implements Phantom { public EntityType getType() { return EntityType.PHANTOM; } + + // Paper start ++ @Override + public java.util.UUID getSpawningEntity() { + return getHandle().getSpawningEntity(); + } diff --git a/patches/server-remapped/0276-Add-More-Creeper-API.patch b/patches/server/0254-Add-More-Creeper-API.patch similarity index 82% rename from patches/server-remapped/0276-Add-More-Creeper-API.patch rename to patches/server/0254-Add-More-Creeper-API.patch index 3a4091fe8d..50f647dd01 100644 --- a/patches/server-remapped/0276-Add-More-Creeper-API.patch +++ b/patches/server/0254-Add-More-Creeper-API.patch @@ -5,10 +5,10 @@ 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 d9b5cf8ac01289801ded01d928fa7ead96551be5..336736fae0b49a05e48c1c70a225da316bb73e66 100644 +index 3bbf6c9bfbb79fd4242cf66d7ace1d8f87404636..e8c36e8541f041a0d72a86f49ced2a3ce1549be0 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java +++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -@@ -289,7 +289,18 @@ public class Creeper extends Monster { +@@ -309,7 +309,18 @@ public class Creeper extends Monster implements PowerableMob { } public void ignite() { @@ -29,19 +29,21 @@ index d9b5cf8ac01289801ded01d928fa7ead96551be5..336736fae0b49a05e48c1c70a225da31 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 ded0b7c1619aada95492e7ec25c0e0f3d008d0ad..9f68beb8c79ed1c429ee9f9efab8b8604258293b 100644 +index 9b0079eac44b7b4e2ff45be92244ae1b81c46241..0cb5bb2d571a4b618515bc6d80935be90cbd26a8 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -@@ -100,4 +100,14 @@ public class CraftCreeper extends CraftMonster implements Creeper { +@@ -100,4 +100,16 @@ public class CraftCreeper extends CraftMonster implements Creeper { public EntityType getType() { return EntityType.CREEPER; } + + // Paper start ++ @Override + public void setIgnited(boolean ignited) { + getHandle().setIgnited(ignited); + } + ++ @Override + public boolean isIgnited() { + return getHandle().isIgnited(); + } diff --git a/patches/server-remapped/0277-Inventory-removeItemAnySlot.patch b/patches/server/0255-Inventory-removeItemAnySlot.patch similarity index 85% rename from patches/server-remapped/0277-Inventory-removeItemAnySlot.patch rename to patches/server/0255-Inventory-removeItemAnySlot.patch index b542a82e8a..0582ff7e52 100644 --- a/patches/server-remapped/0277-Inventory-removeItemAnySlot.patch +++ b/patches/server/0255-Inventory-removeItemAnySlot.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Inventory#removeItemAnySlot diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index 9d70ef8c3967596491a804e4d66f2ec1b13992c9..ef2d18d19a86b3701855aa1ac126462e663f8fcd 100644 +index 758bbe839b71917b594fdb8c9cd66cda0aa4745c..56bd3290fdf011590594d68128eb3fe9ca71506c 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java @@ -222,10 +222,16 @@ public class CraftInventory implements Inventory { @@ -21,8 +21,8 @@ index 9d70ef8c3967596491a804e4d66f2ec1b13992c9..ef2d18d19a86b3701855aa1ac126462e if (item == null) { return -1; } -- ItemStack[] inventory = getStorageContents(); -+ //ItemStack[] inventory = getStorageContents(); // Paper - let param deal +- ItemStack[] inventory = this.getStorageContents(); ++ // ItemStack[] inventory = this.getStorageContents(); // Paper - let param deal for (int i = 0; i < inventory.length; i++) { if (inventory[i] == null) continue; @@ -48,10 +48,10 @@ index 9d70ef8c3967596491a804e4d66f2ec1b13992c9..ef2d18d19a86b3701855aa1ac126462e int toDelete = item.getAmount(); while (true) { -- int first = first(item, false); +- int first = this.first(item, false); + // Paper start - Allow searching entire contents + ItemStack[] toSearch = searchEntire ? getContents() : getStorageContents(); -+ int first = first(item, false, toSearch); ++ int first = this.first(item, false, toSearch); + // Paper end // Drat! we don't have this type in the inventory diff --git a/patches/server-remapped/0278-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/patches/server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch similarity index 63% rename from patches/server-remapped/0278-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch rename to patches/server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch index 3b436ea5af..5c607fe650 100644 --- a/patches/server-remapped/0278-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch +++ b/patches/server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch @@ -6,15 +6,15 @@ Subject: [PATCH] Make CraftWorld#loadChunk(int, int, false) load unconverted diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 159c32d6678e83f2d98ea6a1ad48346c9de017e1..57a2af56b53567371fdb6d0a55866e1e4e37cf3b 100644 +index e7f5cd35869790baf616e6c65f49169aa5349e89..2a9a57263ff116c1a7f51eac127292559de48b11 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -490,7 +490,7 @@ public class CraftWorld implements World { +@@ -505,7 +505,7 @@ public class CraftWorld implements World { @Override public boolean loadChunk(int x, int z, boolean generate) { org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -- ChunkAccess chunk = world.getChunkSource().getChunk(x, z, generate ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); -+ ChunkAccess chunk = world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper +- ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); ++ ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper // If generate = false, but the chunk already exists, we will get this back. if (chunk instanceof ImposterProtoChunk) { From fa637ed8ddc23b1938978ce08d17be62527ff966 Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Sat, 12 Jun 2021 19:31:26 -0500 Subject: [PATCH 055/226] Cleanup project build config --- build.gradle.kts | 7 +------ gradle.properties | 5 +++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index c72aad1bc8..9c49ca8942 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,13 +4,10 @@ plugins { id("io.papermc.paperweight.core") version "1.0.0-SNAPSHOT" } -group = "io.papermc.paper" -version = providers.gradleProperty("projectVersion").forUseAtConfigurationTime().get() - val mcVersion = providers.gradleProperty("mcVersion") val packageVersion = providers.gradleProperty("packageVersion") -allprojects { +subprojects { apply(plugin = "java") java { @@ -18,9 +15,7 @@ allprojects { languageVersion.set(JavaLanguageVersion.of(16)) } } -} -subprojects { tasks.withType().configureEach { options.encoding = "UTF-8" options.release.set(16) diff --git a/gradle.properties b/gradle.properties index c26ed1b3da..31b3057617 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,5 @@ +group = "io.papermc.paper" +version = 1.17-R0.1-SNAPSHOT + mcVersion = 1.17 -projectVersion = 1.17-R0.1-SNAPSHOT packageVersion = 1_17_R1 -org.gradle.jvmargs=-Xmx3G From 672c5365f422f2b9247b0fa5edc887352f512046 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 12 Jun 2021 18:28:41 -0700 Subject: [PATCH 056/226] Write API version to pom.properties for Versioning to read Maven writes this metadata normally, but we don't use maven. Maybe should modify Versioning instead in the future, but this works just fine for now. --- gradle.properties | 2 +- .../api/0001-Convert-project-to-Gradle.patch | 17 +++++++++++++++-- patches/api/0002-POM-changes.patch | 4 ++-- patches/api/0003-Add-FastUtil-to-Bukkit.patch | 4 ++-- patches/api/0006-Adventure.patch | 4 ++-- .../api/0024-Use-ASM-for-event-executors.patch | 4 ++-- ...Allow-plugins-to-use-SLF4J-for-logging.patch | 4 ++-- 7 files changed, 26 insertions(+), 13 deletions(-) diff --git a/gradle.properties b/gradle.properties index 31b3057617..071cb6fb13 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -group = "io.papermc.paper" +group = io.papermc.paper version = 1.17-R0.1-SNAPSHOT mcVersion = 1.17 diff --git a/patches/api/0001-Convert-project-to-Gradle.patch b/patches/api/0001-Convert-project-to-Gradle.patch index d34ab3ef3c..1fb1db17ac 100644 --- a/patches/api/0001-Convert-project-to-Gradle.patch +++ b/patches/api/0001-Convert-project-to-Gradle.patch @@ -16,10 +16,12 @@ index e431e3435737e28394d81b56568a08b3c3148b9b..c484aff2c192bf42059b5689327909e4 /.project diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 -index 0000000000000000000000000000000000000000..a0f1c1d1ac63fdcce942922ffe68a8d44c712513 +index 0000000000000000000000000000000000000000..f3dd92e136a71aa39e422de7b2c5f2f3fdec554e --- /dev/null +++ b/build.gradle.kts -@@ -0,0 +1,54 @@ +@@ -0,0 +1,67 @@ ++import java.util.Locale ++ +plugins { + `java-library` + checkstyle @@ -53,7 +55,18 @@ index 0000000000000000000000000000000000000000..a0f1c1d1ac63fdcce942922ffe68a8d4 + checkstyle("com.puppycrawl.tools:checkstyle:8.39") +} + ++val generateApiVersioningFile by tasks.registering { ++ val pomProps = layout.buildDirectory.file("pom.properties") ++ outputs.file(pomProps) ++ doLast { ++ pomProps.get().asFile.writeText("version=${project.version}") ++ } ++} ++ +tasks.jar { ++ from(generateApiVersioningFile.map { it.outputs.files.singleFile }) { ++ into("META-INF/maven/${project.group}/${project.name.toLowerCase(Locale.ENGLISH)}") ++ } + manifest { + attributes += mapOf( + "Automatic-Module-Name" to "org.bukkit" diff --git a/patches/api/0002-POM-changes.patch b/patches/api/0002-POM-changes.patch index 274e996a2c..1422974313 100644 --- a/patches/api/0002-POM-changes.patch +++ b/patches/api/0002-POM-changes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] POM changes diff --git a/build.gradle.kts b/build.gradle.kts -index a0f1c1d1ac63fdcce942922ffe68a8d44c712513..fd47081fbc8cc5d88a57689d1beee5eddc78f845 100644 +index f3dd92e136a71aa39e422de7b2c5f2f3fdec554e..b75ac1f11c3171a3f0c8edb30be3555216f51b0a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -15,10 +15,12 @@ dependencies { +@@ -17,10 +17,12 @@ dependencies { api("com.google.code.gson:gson:2.8.0") api("net.md-5:bungeecord-chat:1.16-R0.4") api("org.yaml:snakeyaml:1.29") diff --git a/patches/api/0003-Add-FastUtil-to-Bukkit.patch b/patches/api/0003-Add-FastUtil-to-Bukkit.patch index 5ce84dd993..8e8ee65d9e 100644 --- a/patches/api/0003-Add-FastUtil-to-Bukkit.patch +++ b/patches/api/0003-Add-FastUtil-to-Bukkit.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add FastUtil to Bukkit Doesn't expose to plugins, just allows Paper-API to use it for optimization diff --git a/build.gradle.kts b/build.gradle.kts -index fd47081fbc8cc5d88a57689d1beee5eddc78f845..95327c3971cd57e01da2a62e1b72ba15fcbb63f4 100644 +index b75ac1f11c3171a3f0c8edb30be3555216f51b0a..218e9c682e7b91dc27f2caf46316ba7a7982e5f3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -16,6 +16,7 @@ dependencies { +@@ -18,6 +18,7 @@ dependencies { api("net.md-5:bungeecord-chat:1.16-R0.4") api("org.yaml:snakeyaml:1.29") api("com.googlecode.json-simple:json-simple:1.1.1") // Paper diff --git a/patches/api/0006-Adventure.patch b/patches/api/0006-Adventure.patch index 002a345853..1037cf46f7 100644 --- a/patches/api/0006-Adventure.patch +++ b/patches/api/0006-Adventure.patch @@ -7,10 +7,10 @@ Co-authored-by: zml Co-authored-by: Jake Potrebic diff --git a/build.gradle.kts b/build.gradle.kts -index 95327c3971cd57e01da2a62e1b72ba15fcbb63f4..4c197e7d9966f8789e6709461e59fc89355afd9c 100644 +index 218e9c682e7b91dc27f2caf46316ba7a7982e5f3..50c3a01826f0ff939e3ee935d5a4e446f46c8cce 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -17,6 +17,11 @@ dependencies { +@@ -19,6 +19,11 @@ dependencies { api("org.yaml:snakeyaml:1.29") api("com.googlecode.json-simple:json-simple:1.1.1") // Paper api("it.unimi.dsi:fastutil:8.2.2") diff --git a/patches/api/0024-Use-ASM-for-event-executors.patch b/patches/api/0024-Use-ASM-for-event-executors.patch index 6c76c6b4f0..2cb4f1f832 100644 --- a/patches/api/0024-Use-ASM-for-event-executors.patch +++ b/patches/api/0024-Use-ASM-for-event-executors.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Use ASM for event executors. Uses method handles for private or static methods. diff --git a/build.gradle.kts b/build.gradle.kts -index 4c197e7d9966f8789e6709461e59fc89355afd9c..9451f8660ec248619383d516df4b95e20e24828a 100644 +index 50c3a01826f0ff939e3ee935d5a4e446f46c8cce..c976d4458886603feeb05b7c854a5c1e54fcb287 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -22,6 +22,8 @@ dependencies { +@@ -24,6 +24,8 @@ dependencies { api("net.kyori:adventure-text-serializer-gson") api("net.kyori:adventure-text-serializer-legacy") api("net.kyori:adventure-text-serializer-plain") diff --git a/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch b/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch index 0555a52329..b59af7a1bd 100644 --- a/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch +++ b/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch @@ -14,10 +14,10 @@ it without having to shade it in the plugin and going through several layers of logging abstraction. diff --git a/build.gradle.kts b/build.gradle.kts -index 9451f8660ec248619383d516df4b95e20e24828a..9657dcb900267cb5cd1ad7a850eb15bc74479314 100644 +index c976d4458886603feeb05b7c854a5c1e54fcb287..9633529a71556a453edae71b09a573a957d65c60 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -24,6 +24,7 @@ dependencies { +@@ -26,6 +26,7 @@ dependencies { api("net.kyori:adventure-text-serializer-plain") api("org.ow2.asm:asm:9.0") api("org.ow2.asm:asm-commons:9.0") From cc19211cf98d3c6bda4749be1100cfbaf5be43e4 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sat, 12 Jun 2021 19:16:10 -0700 Subject: [PATCH 057/226] wowe --- .../0134-Async-Chunks-API.patch} | 10 +- ...ide-Chunk-Coordinates-as-a-Long-API.patch} | 2 +- ...=> 0136-Make-EnderDragon-extend-Mob.patch} | 0 ...le-Entities-from-a-chunk-without-sn.patch} | 0 ...ots-for-Timings-Tile-Entity-reports.patch} | 0 ...locks-to-be-accessed-via-a-long-key.patch} | 2 +- ...tch => 0140-Slime-Pathfinder-Events.patch} | 0 ...ch => 0141-Add-PhantomPreSpawnEvent.patch} | 0 ....patch => 0142-Add-More-Creeper-API.patch} | 0 ....patch => 0143-isChunkGenerated-API.patch} | 2 +- ...d-source-block-to-BlockPhysicsEvent.patch} | 0 ...=> 0145-Inventory-removeItemAnySlot.patch} | 0 ...7-Asynchronous-chunk-IO-and-loading.patch} | 1379 +++++------------ 13 files changed, 378 insertions(+), 1017 deletions(-) rename patches/{api-unmapped/0133-Async-Chunks-API.patch => api/0134-Async-Chunks-API.patch} (98%) rename patches/api/{0134-Provide-Chunk-Coordinates-as-a-Long-API.patch => 0135-Provide-Chunk-Coordinates-as-a-Long-API.patch} (96%) rename patches/api/{0135-Make-EnderDragon-extend-Mob.patch => 0136-Make-EnderDragon-extend-Mob.patch} (100%) rename patches/api/{0136-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch => 0137-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch} (100%) rename patches/api/{0137-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch => 0138-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch} (100%) rename patches/api/{0138-Allow-Blocks-to-be-accessed-via-a-long-key.patch => 0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch} (98%) rename patches/api/{0139-Slime-Pathfinder-Events.patch => 0140-Slime-Pathfinder-Events.patch} (100%) rename patches/api/{0140-Add-PhantomPreSpawnEvent.patch => 0141-Add-PhantomPreSpawnEvent.patch} (100%) rename patches/api/{0141-Add-More-Creeper-API.patch => 0142-Add-More-Creeper-API.patch} (100%) rename patches/api/{0142-isChunkGenerated-API.patch => 0143-isChunkGenerated-API.patch} (96%) rename patches/api/{0143-Add-source-block-to-BlockPhysicsEvent.patch => 0144-Add-source-block-to-BlockPhysicsEvent.patch} (100%) rename patches/api/{0144-Inventory-removeItemAnySlot.patch => 0145-Inventory-removeItemAnySlot.patch} (100%) rename patches/{server-remapped/0370-Asynchronous-chunk-IO-and-loading.patch => server/0257-Asynchronous-chunk-IO-and-loading.patch} (73%) diff --git a/patches/api-unmapped/0133-Async-Chunks-API.patch b/patches/api/0134-Async-Chunks-API.patch similarity index 98% rename from patches/api-unmapped/0133-Async-Chunks-API.patch rename to patches/api/0134-Async-Chunks-API.patch index 992af6f95b..060c8b69df 100644 --- a/patches/api-unmapped/0133-Async-Chunks-API.patch +++ b/patches/api/0134-Async-Chunks-API.patch @@ -8,12 +8,12 @@ Adds API's to load or generate chunks asynchronously. Also adds utility methods to Entity to teleport asynchronously. diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index e372b3d43960ac7df58985609ef729c68fca0533..3f231c28842f02f80fd3136c36fe99b41726137f 100644 +index a7bd869fb5b8e35274eee0d8dae9dd6fe3c1c540..e88c98528ca9e8d636e0b30f4209f7205c5eb9f6 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java -@@ -221,6 +221,482 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - public default Chunk getChunkAt(long chunkKey) { - return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); +@@ -910,6 +910,482 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + } + return nearby; } + + /** @@ -495,7 +495,7 @@ index e372b3d43960ac7df58985609ef729c68fca0533..3f231c28842f02f80fd3136c36fe99b4 /** diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 707638c327077a74c777a603b9f2392f46b51c0c..c137199ed0537874010f1abf311a9cbee56831ac 100644 +index ef95afb92f7a6fea77fe483e26ee3cf6d1bdd041..896b86c212767264c81eb1868a061979e4536c6c 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java @@ -163,6 +163,33 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent diff --git a/patches/api/0134-Provide-Chunk-Coordinates-as-a-Long-API.patch b/patches/api/0135-Provide-Chunk-Coordinates-as-a-Long-API.patch similarity index 96% rename from patches/api/0134-Provide-Chunk-Coordinates-as-a-Long-API.patch rename to patches/api/0135-Provide-Chunk-Coordinates-as-a-Long-API.patch index 17690209af..ba1c7af8ea 100644 --- a/patches/api/0134-Provide-Chunk-Coordinates-as-a-Long-API.patch +++ b/patches/api/0135-Provide-Chunk-Coordinates-as-a-Long-API.patch @@ -44,7 +44,7 @@ index beac1439c71fb28f1a3baecf56157237e12ccfd5..fa576096e908f8fbdbef53e1bd91215a * Gets the world containing this chunk * diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index a7bd869fb5b8e35274eee0d8dae9dd6fe3c1c540..85c9ea1241d580386be00fb85ea1446addd376c4 100644 +index e88c98528ca9e8d636e0b30f4209f7205c5eb9f6..f45bea24a350c3700bdbf4c44aeb1c0562e57d9e 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -207,6 +207,22 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad diff --git a/patches/api/0135-Make-EnderDragon-extend-Mob.patch b/patches/api/0136-Make-EnderDragon-extend-Mob.patch similarity index 100% rename from patches/api/0135-Make-EnderDragon-extend-Mob.patch rename to patches/api/0136-Make-EnderDragon-extend-Mob.patch diff --git a/patches/api/0136-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/patches/api/0137-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch similarity index 100% rename from patches/api/0136-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch rename to patches/api/0137-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch diff --git a/patches/api/0137-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch b/patches/api/0138-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch similarity index 100% rename from patches/api/0137-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch rename to patches/api/0138-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch diff --git a/patches/api/0138-Allow-Blocks-to-be-accessed-via-a-long-key.patch b/patches/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch similarity index 98% rename from patches/api/0138-Allow-Blocks-to-be-accessed-via-a-long-key.patch rename to patches/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch index d9fc1f8e59..7014671c66 100644 --- a/patches/api/0138-Allow-Blocks-to-be-accessed-via-a-long-key.patch +++ b/patches/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch @@ -48,7 +48,7 @@ index 369ce9ff6c8bb97a64a8e229115564412e6e7654..e700875beb76dadd55b585aca748338d * @return A new location where X/Y/Z are the center of the block */ diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 85c9ea1241d580386be00fb85ea1446addd376c4..4f563c6afc3568a5a45594bcc87790eeefc4148d 100644 +index f45bea24a350c3700bdbf4c44aeb1c0562e57d9e..a653a09968123724f9ec5501760257b3944b49c9 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -90,6 +90,38 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad diff --git a/patches/api/0139-Slime-Pathfinder-Events.patch b/patches/api/0140-Slime-Pathfinder-Events.patch similarity index 100% rename from patches/api/0139-Slime-Pathfinder-Events.patch rename to patches/api/0140-Slime-Pathfinder-Events.patch diff --git a/patches/api/0140-Add-PhantomPreSpawnEvent.patch b/patches/api/0141-Add-PhantomPreSpawnEvent.patch similarity index 100% rename from patches/api/0140-Add-PhantomPreSpawnEvent.patch rename to patches/api/0141-Add-PhantomPreSpawnEvent.patch diff --git a/patches/api/0141-Add-More-Creeper-API.patch b/patches/api/0142-Add-More-Creeper-API.patch similarity index 100% rename from patches/api/0141-Add-More-Creeper-API.patch rename to patches/api/0142-Add-More-Creeper-API.patch diff --git a/patches/api/0142-isChunkGenerated-API.patch b/patches/api/0143-isChunkGenerated-API.patch similarity index 96% rename from patches/api/0142-isChunkGenerated-API.patch rename to patches/api/0143-isChunkGenerated-API.patch index ce9303e154..38bf3da063 100644 --- a/patches/api/0142-isChunkGenerated-API.patch +++ b/patches/api/0143-isChunkGenerated-API.patch @@ -34,7 +34,7 @@ index e700875beb76dadd55b585aca748338def286908..9c91c49ed7302c12fcb1d8e9bc58712e /** * Sets the position of this Location and returns itself diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 4f563c6afc3568a5a45594bcc87790eeefc4148d..868e34482a3a5773dfbdc80b36adcee25239614a 100644 +index a653a09968123724f9ec5501760257b3944b49c9..1264c65235e622f648d71ef10d804ef5193da973 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -253,6 +253,17 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad diff --git a/patches/api/0143-Add-source-block-to-BlockPhysicsEvent.patch b/patches/api/0144-Add-source-block-to-BlockPhysicsEvent.patch similarity index 100% rename from patches/api/0143-Add-source-block-to-BlockPhysicsEvent.patch rename to patches/api/0144-Add-source-block-to-BlockPhysicsEvent.patch diff --git a/patches/api/0144-Inventory-removeItemAnySlot.patch b/patches/api/0145-Inventory-removeItemAnySlot.patch similarity index 100% rename from patches/api/0144-Inventory-removeItemAnySlot.patch rename to patches/api/0145-Inventory-removeItemAnySlot.patch diff --git a/patches/server-remapped/0370-Asynchronous-chunk-IO-and-loading.patch b/patches/server/0257-Asynchronous-chunk-IO-and-loading.patch similarity index 73% rename from patches/server-remapped/0370-Asynchronous-chunk-IO-and-loading.patch rename to patches/server/0257-Asynchronous-chunk-IO-and-loading.patch index c4fd709325..dd159ddcda 100644 --- a/patches/server-remapped/0370-Asynchronous-chunk-IO-and-loading.patch +++ b/patches/server/0257-Asynchronous-chunk-IO-and-loading.patch @@ -121,10 +121,10 @@ tasks required to be executed by the chunk load task (i.e lighting and some poi tasks). diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -index 79ede25e4fe7a648b1d29c49d876482a2158f892..24eac9400fbf971742e89bbf47b0ba52b587c4eb 100644 +index 0fda52841b5e1643efeda92106124998abc4e0aa..fe79c0add4f7cb18d487c5bb9415c40c5b551ea2 100644 --- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java +++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -59,6 +59,17 @@ public class WorldTimingsHandler { +@@ -58,6 +58,16 @@ public class WorldTimingsHandler { public final Timing miscMobSpawning; @@ -132,7 +132,6 @@ index 79ede25e4fe7a648b1d29c49d876482a2158f892..24eac9400fbf971742e89bbf47b0ba52 + public final Timing chunkUnload; + public final Timing poiSaveDataSerialization; + public final Timing chunkSave; -+ public final Timing chunkSaveOverwriteCheck; + public final Timing chunkSaveDataSerialization; + public final Timing chunkSaveIOWait; + public final Timing chunkUnloadPrepareSave; @@ -142,7 +141,7 @@ index 79ede25e4fe7a648b1d29c49d876482a2158f892..24eac9400fbf971742e89bbf47b0ba52 public WorldTimingsHandler(Level server) { String name = ((PrimaryLevelData) server.getLevelData()).getLevelName() + " - "; -@@ -112,6 +123,17 @@ public class WorldTimingsHandler { +@@ -111,6 +121,16 @@ public class WorldTimingsHandler { miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); @@ -151,7 +150,6 @@ index 79ede25e4fe7a648b1d29c49d876482a2158f892..24eac9400fbf971742e89bbf47b0ba52 + chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); + poiSaveDataSerialization = Timings.ofSafe(name + "Chunk save - POI Data serialization"); + chunkSave = Timings.ofSafe(name + "Chunk save - Chunk"); -+ chunkSaveOverwriteCheck = Timings.ofSafe(name + "Chunk save - Chunk Overwrite Check"); + chunkSaveDataSerialization = Timings.ofSafe(name + "Chunk save - Chunk Data serialization"); + chunkSaveIOWait = Timings.ofSafe(name + "Chunk save - Chunk IO Wait"); + chunkUnloadPrepareSave = Timings.ofSafe(name + "Chunk unload - Async Save Prepare"); @@ -160,38 +158,8 @@ index 79ede25e4fe7a648b1d29c49d876482a2158f892..24eac9400fbf971742e89bbf47b0ba52 } public static Timing getTickList(ServerLevel worldserver, String timingsType) { -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 53dd6c18de8e80378852bbb141016d9574d42162..62711d95db62221a2e4e6423c518afe13a6c7dbe 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper; - -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; - import com.google.common.base.Functions; - import com.google.common.base.Joiner; - import com.google.common.collect.ImmutableSet; -@@ -43,7 +44,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); - - public PaperCommand(String name) { - super(name); -@@ -155,6 +156,9 @@ public class PaperCommand extends Command { - case "debug": - doDebug(sender, args); - break; -+ case "dumpwaiting": -+ ChunkTaskManager.dumpAllChunkLoadInfo(); -+ break; - case "chunkinfo": - doChunkInfo(sender, args); - break; diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 469f78775b03cf363d88e35c69c0dc185c22547c..8bf4d2b8c38c02d6a5b2fea37113689a252f1571 100644 +index 62621562137cba4804f0465c58d25ca2786328e5..ee8ead249d89bc81f87bfff6a1f594a9aeb21250 100644 --- a/src/main/java/com/destroystokyo/paper/PaperConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java @@ -1,5 +1,6 @@ @@ -201,9 +169,9 @@ index 469f78775b03cf363d88e35c69c0dc185c22547c..8bf4d2b8c38c02d6a5b2fea37113689a import com.google.common.base.Strings; import com.google.common.base.Throwables; -@@ -352,4 +353,54 @@ public class PaperConfig { - maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); - maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); +@@ -319,4 +320,54 @@ public class PaperConfig { + } + tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); } + + public static boolean asyncChunks = false; @@ -1468,10 +1436,10 @@ index 0000000000000000000000000000000000000000..ee906b594b306906c170180a29a8b619 +} diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java new file mode 100644 -index 0000000000000000000000000000000000000000..26a5da48c87674f320aa9f7382217cde2c93e08c +index 0000000000000000000000000000000000000000..7c4b19f565a77b63ab9d3b56557af126d0438eac --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java -@@ -0,0 +1,145 @@ +@@ -0,0 +1,138 @@ +package com.destroystokyo.paper.io.chunk; + +import co.aikar.timings.Timing; @@ -1577,13 +1545,6 @@ index 0000000000000000000000000000000000000000..26a5da48c87674f320aa9f7382217cde + } + + try { -+ this.world.getChunkSource().chunkMap.updateChunkStatusOnDisk(chunkPos, chunkData.chunkData); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.warn("Failed to update chunk status cache for task: " + this.toString(), ex); -+ // non-fatal, continue -+ } -+ -+ try { + chunkHolder = ChunkSerializer.loadChunk(this.world, + chunkManager.structureManager, chunkManager.getVillagePlace(), chunkPos, + chunkData.chunkData, true); @@ -1782,7 +1743,7 @@ index 0000000000000000000000000000000000000000..058fb5a41565e6ce2acbd1f4d071a1b8 +} diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java new file mode 100644 -index 0000000000000000000000000000000000000000..499aff1f1e1ffc01ba8f9de43ca17899525a306f +index 0000000000000000000000000000000000000000..18ae2e2b339d357fbe0f6f2b18bc14c0dfe4c222 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java @@ -0,0 +1,513 @@ @@ -1911,7 +1872,7 @@ index 0000000000000000000000000000000000000000..499aff1f1e1ffc01ba8f9de43ca17899 + if (chunkHolder == null) { + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - null for (" + x +"," + z +")"); + } else { -+ ChunkAccess chunk = chunkHolder.getAvailableChunkNow(); ++ ChunkAccess chunk = chunkHolder.getLastAvailable(); + ChunkStatus holderStatus = chunkHolder.getChunkHolderStatus(); + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - non-null"); + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); @@ -2300,12 +2261,12 @@ index 0000000000000000000000000000000000000000..499aff1f1e1ffc01ba8f9de43ca17899 + +} diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java -index 354783f862986bf939639a86a9076ac0f5ed97e3..c171860bc117199ca00085bf37507f867d51fb62 100644 +index a5e438a834826161c52ca9db57d234d9ff80a591..b8bc1b9b8e8a33df90a963f9f9769292bf595642 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java @@ -14,7 +14,7 @@ public class ServerboundCommandSuggestionPacket implements Packet { DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataFixers.getDataFixer(), minecraftsessionservice, gameprofilerepository, usercache, LoggerChunkProgressListener::new); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index aab1a055c065d1f1a92461e4442ec2cdd8e0b347..643d75b999c3da006eaaab11f4acd77e807683d4 100644 +index cf92c3275869e4a0209fd4b07ad723e11717dc86..5f2f341e647d4b697b7cd4271cb4ca12fe1a94f5 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -920,7 +920,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> future = this.getFutureIfPresentUnchecked(curr); + Either either = future.getNow(null); + if (either == null || !either.left().isPresent()) { @@ -2377,21 +2331,19 @@ index 491a9e78fdcec8c211499e8f48cceb829f1e5c8b..77d3969200ac6f88f3af9add05def0b6 + } + return curr; + } -+ return null; -+ } - // Paper end - public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { -@@ -375,7 +387,7 @@ public class ChunkHolder { - ChunkStatus chunkstatus = getStatus(this.oldTicketLevel); - ChunkStatus chunkstatus1 = getStatus(this.ticketLevel); + return null; + } +@@ -378,7 +390,7 @@ public class ChunkHolder { + ChunkStatus chunkstatus = ChunkHolder.getStatus(this.oldTicketLevel); + ChunkStatus chunkstatus1 = ChunkHolder.getStatus(this.ticketLevel); boolean flag = this.oldTicketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; - boolean flag1 = this.ticketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; + boolean flag1 = this.ticketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; // Paper - diff on change: (flag1 = new ticket level is in loadable range) - ChunkHolder.FullChunkStatus playerchunk_state = getFullChunkStatus(this.oldTicketLevel); - ChunkHolder.FullChunkStatus playerchunk_state1 = getFullChunkStatus(this.ticketLevel); + ChunkHolder.FullChunkStatus playerchunk_state = ChunkHolder.getFullChunkStatus(this.oldTicketLevel); + ChunkHolder.FullChunkStatus playerchunk_state1 = ChunkHolder.getFullChunkStatus(this.ticketLevel); // CraftBukkit start -@@ -411,6 +423,12 @@ public class ChunkHolder { +@@ -414,6 +426,12 @@ public class ChunkHolder { } }); @@ -2403,20 +2355,12 @@ index 491a9e78fdcec8c211499e8f48cceb829f1e5c8b..77d3969200ac6f88f3af9add05def0b6 + for (int i = flag1 ? chunkstatus1.getIndex() + 1 : 0; i <= chunkstatus.getIndex(); ++i) { completablefuture = (CompletableFuture) this.futures.get(i); - if (completablefuture != null) { + if (completablefuture == null) { diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f327e2113 100644 +index 4b349960daaacd87c042b055adf36c0a66748f7f..8311d921ded1c81a1f561dc13db2010d2b7ce5d6 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -86,6 +86,7 @@ import net.minecraft.world.level.chunk.ProtoChunk; - import net.minecraft.world.level.chunk.UpgradeData; - import net.minecraft.world.level.chunk.storage.ChunkSerializer; - import net.minecraft.world.level.chunk.storage.ChunkStorage; -+import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; - import net.minecraft.world.level.storage.DimensionDataStorage; -@@ -110,7 +111,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -115,7 +115,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider private final ThreadedLevelLightEngine lightEngine; private final BlockableEventLoop mainThreadExecutor; public final ChunkGenerator generator; @@ -2425,8 +2369,8 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f private final PoiManager poiManager; public final LongSet toDrop; private boolean modified; -@@ -120,7 +121,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public final ChunkProgressListener progressListener; +@@ -126,7 +126,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private final ChunkStatusUpdateListener chunkStatusListener; public final ChunkMap.ChunkDistanceManager distanceManager; private final AtomicInteger tickingGenerated; - private final StructureManager structureManager; @@ -2434,31 +2378,22 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f private final File storageFolder; private final PlayerMap playerMap; public final Int2ObjectMap entityMap; -@@ -203,7 +204,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); - this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); - this.overworldDataStorage = supplier; -- this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag); -+ this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper - this.setViewDistance(i); - } - -@@ -245,12 +246,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -252,12 +252,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } @Nullable - protected ChunkHolder getUpdatingChunkIfPresent(long pos) { -+ public ChunkHolder getUpdatingChunkIfPresent(long pos) { // Paper ++ public final ChunkHolder getUpdatingChunkIfPresent(long pos) { // Paper - protected -> public return (ChunkHolder) this.updatingChunkMap.get(pos); } @Nullable - protected ChunkHolder getVisibleChunkIfPresent(long pos) { -+ public ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public ++ public final ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public return (ChunkHolder) this.visibleChunkMap.get(pos); } -@@ -372,6 +373,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -406,6 +406,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public void close() throws IOException { try { this.queueSorter.close(); @@ -2466,7 +2401,7 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f this.poiManager.close(); } finally { super.close(); -@@ -463,7 +465,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -442,7 +443,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.processUnloads(() -> { return true; }); @@ -2476,7 +2411,7 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); } else { this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { -@@ -479,16 +482,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -458,16 +460,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } @@ -2498,7 +2433,7 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f } gameprofilerfiller.pop(); -@@ -509,12 +516,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -488,12 +494,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (playerchunk != null) { this.pendingUnloads.put(j, playerchunk); this.modified = true; @@ -2513,13 +2448,13 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f } } activityAccountant.endActivity(); // Spigot -@@ -528,6 +536,60 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -507,6 +514,46 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } + // Paper start - async chunk save for unload + // Note: This is very unsafe to call if the chunk is still in use. -+ // This is also modeled after PlayerChunkMap#saveChunk(IChunkAccess, boolean), with the intentional difference being ++ // This is also modeled after PlayerChunkMap#save(IChunkAccess, boolean), with the intentional difference being + // serializing the chunk is left to a worker thread. + private void asyncSave(ChunkAccess chunk) { + ChunkPos chunkPos = chunk.getPos(); @@ -2537,24 +2472,11 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f + + ChunkStatus chunkstatus = chunk.getStatus(); + -+ // Copied from PlayerChunkMap#saveChunk(IChunkAccess, boolean) ++ // Copied from PlayerChunkMap#save(IChunkAccess, boolean) + if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { -+ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper -+ // Paper start - Optimize save by using status cache -+ try { -+ ChunkStatus statusOnDisk = this.getChunkStatusOnDisk(chunkPos); -+ if (statusOnDisk != null && statusOnDisk.getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { -+ // Paper end -+ return; -+ } -+ -+ if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::e)) { -+ return; -+ } -+ } catch (IOException ex) { -+ ex.printStackTrace(); -+ return; -+ } ++ // Paper start - Optimize save by using status cache ++ if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::isValid)) { ++ return; + } + } + @@ -2566,38 +2488,40 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f + this.level.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY, + asyncSaveData, chunk); + -+ chunk.setLastSaveTime(this.level.getGameTime()); + chunk.setUnsaved(false); + } + // Paper end + - private void scheduleUnload(long pos, ChunkHolder playerchunk) { - CompletableFuture completablefuture = playerchunk.getChunkToSave(); + private void scheduleUnload(long pos, ChunkHolder holder) { + CompletableFuture completablefuture = holder.getChunkToSave(); Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error -@@ -541,7 +603,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -520,13 +567,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider ((LevelChunk) ichunkaccess).setLoaded(false); } - this.save(ichunkaccess); -+ //this.saveChunk(ichunkaccess);// Paper - delay ++ //this.save(ichunkaccess);// Paper - delay if (this.entitiesInLevel.remove(pos) && ichunkaccess instanceof LevelChunk) { LevelChunk chunk = (LevelChunk) ichunkaccess; -@@ -549,6 +611,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.level.unload(chunk); } - this.autoSaveQueue.remove(playerchunk); // Paper ++ // Paper start - async chunk saving + try { -+ this.asyncSave(ichunkaccess); // Paper - async chunk saving ++ this.asyncSave(ichunkaccess); ++ } catch (ThreadDeath ex) { ++ throw ex; // bye + } catch (Throwable ex) { + LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex); + this.save(ichunkaccess); + } ++ // Paper end - async chunk saving + this.lightEngine.updateChunkStatus(ichunkaccess.getPos()); this.lightEngine.tryScheduleUpdate(); this.progressListener.onStatusChange(ichunkaccess.getPos(), (ChunkStatus) null); -@@ -619,19 +688,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -581,19 +639,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } private CompletableFuture> scheduleChunkLoad(ChunkPos pos) { @@ -2614,26 +2538,26 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f + if (ioThrowable != null) { + com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable); + } -+ + +- if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings +- boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8); + this.getVillagePlace().loadInData(pos, chunkHolder.poiData); + chunkHolder.tasks.forEach(Runnable::run); + // Paper end -- if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings -- boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8); -+ if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async - - if (flag) { - ProtoChunk protochunk = ChunkSerializer.read(this.level, this.structureManager, this.poiManager, pos, nbttagcompound); ++ if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async ++ + if (true) { + ProtoChunk protochunk = chunkHolder.protoChunk; - protochunk.setLastSaveTime(this.level.getGameTime()); this.markPosition(pos, protochunk.getStatus().getChunkType()); -@@ -655,7 +728,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return Either.left(protochunk); +@@ -616,7 +678,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.markPositionReplaceable(pos); - return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level)); // Paper - Anti-Xray - Add parameter + return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level)); - }, this.mainThreadExecutor); + // Paper start - Async chunk io + }; @@ -2664,7 +2588,7 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f } private void markPositionReplaceable(ChunkPos chunkcoordintpair) { -@@ -890,6 +988,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -798,6 +885,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } public boolean save(ChunkAccess chunk) { @@ -2672,19 +2596,16 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f this.poiManager.flush(chunk.getPos()); if (!chunk.isUnsaved()) { return false; -@@ -902,6 +1001,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -809,7 +897,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider ChunkStatus chunkstatus = chunk.getStatus(); if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { -+ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper - if (this.isExistingChunkFull(chunkcoordintpair)) { +- if (this.isExistingChunkFull(chunkcoordintpair)) { ++ if (false && this.isExistingChunkFull(chunkcoordintpair)) { // Paper return false; } -@@ -909,12 +1009,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::e)) { - return false; - } -+ } // Paper + +@@ -819,9 +907,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } this.level.getProfiler().incrementCounter("chunkSave"); @@ -2693,9 +2614,9 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f + try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper + nbttagcompound = ChunkSerializer.write(this.level, chunk); + } // Paper ++ - this.write(chunkcoordintpair, nbttagcompound); -+ + // Paper start - async chunk io + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z, + null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); @@ -2703,7 +2624,7 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f this.markPosition(chunkcoordintpair, chunkstatus.getChunkType()); return true; } catch (Exception exception) { -@@ -923,6 +1031,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -830,6 +925,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return false; } } @@ -2711,7 +2632,7 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f } private boolean isExistingChunkFull(ChunkPos chunkcoordintpair) { -@@ -1052,6 +1161,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -957,6 +1053,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } } @@ -2745,116 +2666,9 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f + // Paper end + @Nullable - public CompoundTag readChunk(ChunkPos pos) throws IOException { // Paper - private -> public + private CompoundTag readChunk(ChunkPos pos) throws IOException { CompoundTag nbttagcompound = this.read(pos); -@@ -1073,33 +1211,55 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - // Paper start - chunk status cache "api" - public ChunkStatus getChunkStatusOnDiskIfCached(ChunkPos chunkPos) { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); -+ synchronized (this) { // Paper -+ RegionFile regionFile = this.regionFileCache.getRegionFileIfLoaded(chunkPos); - - return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } // Paper - } - - public ChunkStatus getChunkStatusOnDisk(ChunkPos chunkPos) throws IOException { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); -+ // Paper start - async chunk save for unload -+ ChunkAccess unloadingChunk = this.level.asyncChunkTaskManager.getChunkInSaveProgress(chunkPos.x, chunkPos.z); -+ if (unloadingChunk != null) { -+ return unloadingChunk.getStatus(); -+ } -+ // Paper end -+ // Paper start - async io -+ CompoundTag inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .getPendingWrite(this.level, chunkPos.x, chunkPos.z, false); - -- if (regionFile == null || !regionFile.chunkExists(chunkPos)) { -- return null; -+ if (inProgressWrite != null) { -+ return ChunkSerializer.getStatus(inProgressWrite); - } -+ // Paper end -+ synchronized (this) { // Paper - async io -+ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, true); -+ -+ if (regionFile == null || !regionFile.hasChunk(chunkPos)) { -+ return null; -+ } - -- ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); - -- if (status != null) { -- return status; -+ if (status != null) { -+ return status; -+ } -+ // Paper start - async io - } - -- this.readChunk(chunkPos); -+ CompoundTag compound = this.readChunk(chunkPos); - -- return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ return ChunkSerializer.getStatus(compound); -+ // Paper end - } - - public void updateChunkStatusOnDisk(ChunkPos chunkPos, @Nullable CompoundTag compound) throws IOException { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ synchronized (this) { -+ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, false); - -- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); -+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); -+ } - } - - public ChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { -@@ -1108,6 +1268,39 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - // Paper end - -+ -+ // Paper start - async io -+ // this function will not load chunk data off disk to check for status -+ // ret null for unknown, empty for empty status on disk or absent from disk -+ public ChunkStatus getStatusOnDiskNoLoad(int x, int z) { -+ // Paper start - async chunk save for unload -+ ChunkAccess unloadingChunk = this.level.asyncChunkTaskManager.getChunkInSaveProgress(x, z); -+ if (unloadingChunk != null) { -+ return unloadingChunk.getStatus(); -+ } -+ // Paper end -+ // Paper start - async io -+ CompoundTag inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .getPendingWrite(this.level, x, z, false); -+ -+ if (inProgressWrite != null) { -+ return ChunkSerializer.getStatus(inProgressWrite); -+ } -+ // Paper end -+ // variant of PlayerChunkMap#getChunkStatusOnDisk that does not load data off disk, but loads the region file -+ ChunkPos chunkPos = new ChunkPos(x, z); -+ synchronized (level.getChunkSource().chunkMap) { -+ RegionFile file; -+ try { -+ file = level.getChunkSource().chunkMap.regionFileCache.getFile(chunkPos, false); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return !file.hasChunk(chunkPos) ? ChunkStatus.EMPTY : file.getStatusIfCached(x, z); -+ } -+ } -+ - boolean noPlayersCloseForSpawning(ChunkPos chunkcoordintpair) { - // Spigot start - return isOutsideOfRange(chunkcoordintpair, false); -@@ -1454,6 +1647,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1310,6 +1435,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } @@ -2863,21 +2677,31 @@ index b2d668607c2b5122d06fa75f77b3cef44100fe28..c00f7c60ce7b497d697d1abdf230f91f return this.poiManager; } diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index c1aa40c01a80a8870478193b8cd7354b0d71045c..120b604d91643248ab375969f95f62a74cbf6be7 100644 +index 4a343fa19566f468aca17228379f4d75f3f56f28..71ac5cf0fdedcfe422bf6f5e6ffb15ce4138aa04 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -37,6 +37,7 @@ import net.minecraft.world.level.chunk.ChunkAccess; - import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.chunk.ChunkSource; - import net.minecraft.world.level.chunk.ChunkStatus; -+import net.minecraft.world.level.chunk.ImposterProtoChunk; - import net.minecraft.world.level.chunk.LevelChunk; - import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; - import net.minecraft.world.level.storage.DimensionDataStorage; -@@ -332,11 +333,138 @@ public class ServerChunkCache extends ChunkSource { - return playerChunk.getAvailableChunkNow(); - +@@ -55,7 +55,7 @@ public class ServerChunkCache extends ChunkSource { + final ServerLevel level; + public final Thread mainThread; // Paper - package-private -> public + final ThreadedLevelLightEngine lightEngine; +- private final ServerChunkCache.MainThreadExecutor mainThreadProcessor; ++ public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; // Paper - private -> public + public final ChunkMap chunkMap; + private final DimensionDataStorage dataStorage; + private long lastInhabitedUpdate; +@@ -323,10 +323,128 @@ public class ServerChunkCache extends ChunkSource { + return ret; } + // Paper end ++ // Paper start - async chunk io ++ public ChunkAccess getChunkAtImmediately(int x, int z) { ++ ChunkHolder holder = this.chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); ++ if (holder == null) { ++ return null; ++ } ++ ++ return holder.getLastAvailable(); ++ } + + private long asyncLoadSeqCounter; + @@ -2896,12 +2720,6 @@ index c1aa40c01a80a8870478193b8cd7354b0d71045c..120b604d91643248ab375969f95f62a7 + return future; + } + -+ if (!com.destroystokyo.paper.PaperConfig.asyncChunks) { -+ level.getWorld().loadChunk(x, z, gen); -+ LevelChunk chunk = getChunkAtIfLoadedMainThread(x, z); -+ return CompletableFuture.completedFuture(chunk != null ? Either.left(chunk) : ChunkHolder.UNLOADED_CHUNK); -+ } -+ + long k = ChunkPos.asLong(x, z); + ChunkPos chunkPos = new ChunkPos(x, z); + @@ -2936,35 +2754,22 @@ index c1aa40c01a80a8870478193b8cd7354b0d71045c..120b604d91643248ab375969f95f62a7 + + ChunkAccess current = this.getChunkAtImmediately(x, z); // we want to bypass ticket restrictions + if (current != null) { -+ if (!(current instanceof ImposterProtoChunk) && !(current instanceof LevelChunk)) { ++ if (!(current instanceof net.minecraft.world.level.chunk.ImposterProtoChunk) && !(current instanceof LevelChunk)) { + return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); + } + // we know the chunk is at full status here (either in read-only mode or the real thing) + return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); + } + -+ ChunkStatus status = level.getChunkSource().chunkMap.getStatusOnDiskNoLoad(x, z); -+ -+ if (status != null && status != ChunkStatus.FULL) { -+ // does not exist on disk -+ return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); -+ } -+ -+ if (status == ChunkStatus.FULL) { -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ // status is null here -+ + // here we don't know what status it is and we're not supposed to generate + // so we asynchronously load empty status + return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.EMPTY, isUrgent).thenCompose((either) -> { + ChunkAccess chunk = either.left().orElse(null); -+ if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof LevelChunk)) { ++ if (!(chunk instanceof net.minecraft.world.level.chunk.ImposterProtoChunk) && !(chunk instanceof LevelChunk)) { + // the chunk on disk was not a full status chunk + return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); + } -+ ; // bring to full status if required ++ // bring to full status if required + return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); + }); + } @@ -2976,7 +2781,7 @@ index c1aa40c01a80a8870478193b8cd7354b0d71045c..120b604d91643248ab375969f95f62a7 + private CompletableFuture> bringToStatusAsync(int x, int z, ChunkPos chunkPos, ChunkStatus status, boolean isUrgent) { + CompletableFuture> future = this.getChunkFutureMainThread(x, z, status, true, isUrgent); + Long identifier = Long.valueOf(this.asyncLoadSeqCounter++); -+ int ticketLevel = MCUtil.getTicketLevelFor(status); ++ int ticketLevel = net.minecraft.server.MCUtil.getTicketLevelFor(status); + this.addTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); + + return future.thenComposeAsync((Either either) -> { @@ -3004,7 +2809,7 @@ index c1aa40c01a80a8870478193b8cd7354b0d71045c..120b604d91643248ab375969f95f62a7 + public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { + this.distanceManager.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); + } - // Paper end ++ // Paper end - async chunk io @Nullable @Override @@ -3013,62 +2818,41 @@ index c1aa40c01a80a8870478193b8cd7354b0d71045c..120b604d91643248ab375969f95f62a7 if (Thread.currentThread() != this.mainThread) { return (ChunkAccess) CompletableFuture.supplyAsync(() -> { return this.getChunk(x, z, leastStatus, create); -@@ -359,11 +487,16 @@ public class ServerChunkCache extends ChunkSource { +@@ -349,13 +467,18 @@ public class ServerChunkCache extends ChunkSource { } gameprofilerfiller.incrementCounter("getChunkCacheMiss"); - CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); + CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper + ServerChunkCache.MainThreadExecutor chunkproviderserver_a = this.mainThreadProcessor; + Objects.requireNonNull(completablefuture); if (!completablefuture.isDone()) { // Paper + // Paper start - async chunk io/loading + this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); + // Paper end this.level.timings.syncChunkLoad.startTiming(); // Paper - this.mainThreadProcessor.managedBlock(completablefuture::isDone); + chunkproviderserver_a.managedBlock(completablefuture::isDone); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug this.level.timings.syncChunkLoad.stopTiming(); // Paper } // Paper ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { -@@ -429,9 +562,14 @@ public class ServerChunkCache extends ChunkSource { +@@ -442,6 +565,11 @@ public class ServerChunkCache extends ChunkSource { } - private CompletableFuture> getChunkFutureMainThread(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { -- ChunkPos chunkcoordintpair = new ChunkPos(chunkX, chunkZ); + private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag) { + // Paper start - add isUrgent - old sig left in place for dirty nms plugins -+ return getChunkFutureMainThread(chunkX, chunkZ, leastStatus, create, false); ++ return getChunkFutureMainThread(i, j, chunkstatus, flag, false); + } + private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag, boolean isUrgent) { + // Paper end -+ ChunkPos chunkcoordintpair = new ChunkPos(i, j); + ChunkPos chunkcoordintpair = new ChunkPos(i, j); long k = chunkcoordintpair.toLong(); -- int l = 33 + ChunkStatus.getDistance(leastStatus); -+ int l = 33 + ChunkStatus.getDistance(chunkstatus); - ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); - - // CraftBukkit start - don't add new ticket for currently unloading chunk -@@ -441,7 +579,7 @@ public class ServerChunkCache extends ChunkSource { - ChunkHolder.FullChunkStatus currentChunkState = ChunkHolder.getFullChunkStatus(playerchunk.getTicketLevel()); - currentlyUnloading = (oldChunkState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !currentChunkState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)); - } -- if (create && !currentlyUnloading) { -+ if (flag && !currentlyUnloading) { - // CraftBukkit end - this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); - if (this.chunkAbsent(playerchunk, l)) { -@@ -457,7 +595,7 @@ public class ServerChunkCache extends ChunkSource { - } - } - -- return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(leastStatus, this.chunkMap); -+ return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkstatus, this.chunkMap); - } - - private boolean chunkAbsent(@Nullable ChunkHolder holder, int maxLevel) { -@@ -831,11 +969,12 @@ public class ServerChunkCache extends ChunkSource { - protected boolean pollTask() { + int l = 33 + ChunkStatus.getDistance(chunkstatus); +@@ -830,11 +958,12 @@ public class ServerChunkCache extends ChunkSource { // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task + public boolean pollTask() { try { + boolean execChunkTask = com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ServerChunkCache.this.level.asyncChunkTaskManager.pollNextChunkTask(); // Paper if (ServerChunkCache.this.runDistanceManagerUpdates()) { @@ -3081,45 +2865,29 @@ index c1aa40c01a80a8870478193b8cd7354b0d71045c..120b604d91643248ab375969f95f62a7 } finally { chunkMap.callbackExecutor.run(); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index a811ced17721b70bb51837f47e466c2261db2466..95eff4f6165024d21e5c4268a9ae1b7a4268de4b 100644 +index dae19715582d75d24744d44a87f94dd86f90c1c7..f2a14f386116d7b30f110d4b7f63eb39b83fe171 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -51,6 +51,7 @@ import net.minecraft.core.RegistryAccess; - import net.minecraft.core.SectionPos; - import net.minecraft.core.Vec3i; - import net.minecraft.core.particles.ParticleOptions; -+import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.network.protocol.Packet; -@@ -122,6 +123,7 @@ import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.LevelChunk; - import net.minecraft.world.level.chunk.LevelChunkSection; -+import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.dimension.DimensionType; - import net.minecraft.world.level.dimension.end.EndDragonFight; - import net.minecraft.world.level.levelgen.Heightmap; -@@ -202,6 +204,79 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -207,6 +207,79 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl return this.chunkSource.getChunk(x, z, false); } + // Paper start - Asynchronous IO + public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController poiDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { + @Override -+ public void writeData(int x, int z, CompoundTag compound) throws java.io.IOException { ++ public void writeData(int x, int z, net.minecraft.nbt.CompoundTag compound) throws java.io.IOException { + ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().write(new ChunkPos(x, z), compound); + } + + @Override -+ public CompoundTag readData(int x, int z) throws java.io.IOException { ++ public net.minecraft.nbt.CompoundTag readData(int x, int z) throws java.io.IOException { + return ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().read(new ChunkPos(x, z)); + } + + @Override -+ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { ++ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { + synchronized (ServerLevel.this.getChunkSource().chunkMap.getVillagePlace()) { -+ RegionFile file; ++ net.minecraft.world.level.chunk.storage.RegionFile file; + + try { + file = ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().getFile(new ChunkPos(chunkX, chunkZ), false); @@ -3132,9 +2900,9 @@ index a811ced17721b70bb51837f47e466c2261db2466..95eff4f6165024d21e5c4268a9ae1b7a + } + + @Override -+ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { ++ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { + synchronized (ServerLevel.this.getChunkSource().chunkMap.getVillagePlace()) { -+ RegionFile file = ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().getRegionFileIfLoaded(new ChunkPos(chunkX, chunkZ)); ++ net.minecraft.world.level.chunk.storage.RegionFile file = ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().getRegionFileIfLoaded(new ChunkPos(chunkX, chunkZ)); + return function.apply(file); + } + } @@ -3142,19 +2910,19 @@ index a811ced17721b70bb51837f47e466c2261db2466..95eff4f6165024d21e5c4268a9ae1b7a + + public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController chunkDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { + @Override -+ public void writeData(int x, int z, CompoundTag compound) throws java.io.IOException { ++ public void writeData(int x, int z, net.minecraft.nbt.CompoundTag compound) throws java.io.IOException { + ServerLevel.this.getChunkSource().chunkMap.write(new ChunkPos(x, z), compound); + } + + @Override -+ public CompoundTag readData(int x, int z) throws java.io.IOException { ++ public net.minecraft.nbt.CompoundTag readData(int x, int z) throws java.io.IOException { + return ServerLevel.this.getChunkSource().chunkMap.read(new ChunkPos(x, z)); + } + + @Override -+ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { ++ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { + synchronized (ServerLevel.this.getChunkSource().chunkMap) { -+ RegionFile file; ++ net.minecraft.world.level.chunk.storage.RegionFile file; + + try { + file = ServerLevel.this.getChunkSource().chunkMap.regionFileCache.getFile(new ChunkPos(chunkX, chunkZ), false); @@ -3167,9 +2935,9 @@ index a811ced17721b70bb51837f47e466c2261db2466..95eff4f6165024d21e5c4268a9ae1b7a + } + + @Override -+ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { ++ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { + synchronized (ServerLevel.this.getChunkSource().chunkMap) { -+ RegionFile file = ServerLevel.this.getChunkSource().chunkMap.regionFileCache.getRegionFileIfLoaded(new ChunkPos(chunkX, chunkZ)); ++ net.minecraft.world.level.chunk.storage.RegionFile file = ServerLevel.this.getChunkSource().chunkMap.regionFileCache.getRegionFileIfLoaded(new ChunkPos(chunkX, chunkZ)); + return function.apply(file); + } + } @@ -3179,45 +2947,33 @@ index a811ced17721b70bb51837f47e466c2261db2466..95eff4f6165024d21e5c4268a9ae1b7a + // Add env and gen to constructor, WorldData -> WorldDataServer public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor -@@ -249,6 +324,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.dragonFight = null; - } + // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error +@@ -278,6 +351,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + this.sleepStatus = new SleepStatus(); this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit + + this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper } // CraftBukkit start -@@ -1737,7 +1814,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - MCUtil.getSpiralOutChunks(spawn, radiusInBlocks >> 4).forEach(pair -> { -- getChunkSource().getChunkAtMainThread(pair.x, pair.z); -+ getChunkSource().getChunkAtAsynchronously(pair.x, pair.z, true, false).exceptionally((ex) -> { -+ ex.printStackTrace(); -+ return null; -+ }); - }); - } - public void removeTicketsForSpawn(int radiusInBlocks, BlockPos spawn) { diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index cf3ced15c9a87e7a4dbccba17c57a7b32b77566c..d09e4857b6c40410d134fa81b48e95919a7373bd 100644 +index 0d536d72ac918fbd403397ff369d10143ee9c204..be677d437d17b74c6188ce1bd5fc6fdc228fd92f 100644 --- a/src/main/java/net/minecraft/server/level/TicketType.java +++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -26,6 +26,7 @@ public class TicketType { - public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit - public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit +@@ -8,6 +8,7 @@ import net.minecraft.world.level.ChunkPos; + + public class TicketType { public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper + public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper - public static TicketType create(String name, Comparator comparator) { - return new TicketType<>(name, comparator, 0L); + private final String name; + private final Comparator comparator; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 4f99c3d06e3b994708c699395adf481a6828e097..5dd99709d6b0ed15bbcee184fe33a28bc1c19dac 100644 +index 6ea367295d07c444d7cce0366261a884d299185a..65a40c912ec20b06e5da01faebf3798c4b613faa 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -728,6 +728,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -712,6 +712,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper return; } @@ -3232,85 +2988,64 @@ index 4f99c3d06e3b994708c699395adf481a6828e097..5dd99709d6b0ed15bbcee184fe33a28b StringReader stringreader = new StringReader(packet.getCommand()); diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -index e48fcfe2e4ff151258ae1d84cc0995d2cd54e9a6..a5ce61be7d6e85ac289730d9671e66a7190529f9 100644 +index 5b38966093fe60b298844961d015d5a9f03412a2..0ef3c4982df88a7991a56d983ac733daa8adc507 100644 --- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -@@ -91,7 +91,7 @@ public abstract class BlockableEventLoop implements Processo - +@@ -106,7 +106,7 @@ public abstract class BlockableEventLoop implements Profiler + this.pendingRunnables.clear(); } - protected void runAllTasks() { + public void runAllTasks() { // Paper - protected -> public - while (this.pollTask()) { - ; + while(this.pollTask()) { } + diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -index 33a8604fa6c6431ccc5f61e484c163e09f1625a0..d082af8cf4c0c7ca434598aa370712c62e05bb24 100644 +index 3ca8b13744b406c3e563747f0cb69647c94103df..6c3455823f996e0421975b7f4a00f4e333e9f514 100644 --- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -@@ -22,7 +22,9 @@ import java.util.stream.Stream; - import net.minecraft.Util; - import net.minecraft.core.BlockPos; - import net.minecraft.core.SectionPos; -+import net.minecraft.nbt.CompoundTag; - import net.minecraft.server.level.SectionTracker; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.LevelReader; -@@ -36,8 +38,16 @@ public class PoiManager extends SectionStorage { - private final PoiManager.DistanceTracker distanceTracker = new PoiManager.DistanceTracker(); +@@ -37,9 +37,11 @@ public class PoiManager extends SectionStorage { + public static final int VILLAGE_SECTION_SIZE = 1; + private final PoiManager.DistanceTracker distanceTracker; private final LongSet loadedChunks = new LongOpenHashSet(); ++ private final net.minecraft.server.level.ServerLevel world; // Paper -+ private final ServerLevel world; // Paper -+ - public PoiManager(File directory, DataFixer datafixer, boolean flag) { -- super(directory, PoiSection::codec, PoiSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); -+ // Paper start - add world parameter -+ this(directory, datafixer, flag, null); -+ } -+ public PoiManager(File file, DataFixer datafixer, boolean flag, ServerLevel world) { -+ super(file, PoiSection::codec, PoiSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); -+ this.world = world; -+ // Paper end - add world parameter + public PoiManager(File directory, DataFixer dataFixer, boolean dsync, LevelHeightAccessor world) { + super(directory, PoiSection::codec, PoiSection::new, dataFixer, DataFixTypes.POI_CHUNK, dsync, world); ++ this.world = (net.minecraft.server.level.ServerLevel)world; // Paper + this.distanceTracker = new PoiManager.DistanceTracker(); } - public void add(BlockPos pos, PoiType type) { -@@ -155,7 +165,23 @@ public class PoiManager extends SectionStorage { +@@ -172,7 +174,18 @@ public class PoiManager extends SectionStorage { @Override public void tick(BooleanSupplier shouldKeepTicking) { - super.tick(shouldKeepTicking); + // Paper start - async chunk io -+ if (this.world == null) { -+ super.tick(shouldKeepTicking); -+ } else { -+ //super.a(booleansupplier); // re-implement below -+ while (!((SectionStorage)this).dirty.isEmpty() && shouldKeepTicking.getAsBoolean()) { -+ ChunkPos chunkcoordintpair = SectionPos.of(((SectionStorage)this).dirty.firstLong()).chunk(); ++ while (!this.dirty.isEmpty() && shouldKeepTicking.getAsBoolean()) { ++ ChunkPos chunkcoordintpair = SectionPos.of(this.dirty.firstLong()).chunk(); + -+ CompoundTag data; -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) { -+ data = this.getData(chunkcoordintpair); -+ } -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, -+ chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); ++ net.minecraft.nbt.CompoundTag data; ++ try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) { ++ data = this.getData(chunkcoordintpair); + } ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, ++ chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); + } + // Paper end this.distanceTracker.runAllUpdates(); } -@@ -255,6 +281,35 @@ public class PoiManager extends SectionStorage { +@@ -265,6 +278,35 @@ public class PoiManager extends SectionStorage { } } + // Paper start - Asynchronous chunk io + @javax.annotation.Nullable + @Override -+ public CompoundTag read(ChunkPos chunkcoordintpair) throws java.io.IOException { ++ public net.minecraft.nbt.CompoundTag read(ChunkPos chunkcoordintpair) throws java.io.IOException { + if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ net.minecraft.nbt.CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE + .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), + true, false, true).join().poiData; + @@ -3323,7 +3058,7 @@ index 33a8604fa6c6431ccc5f61e484c163e09f1625a0..d082af8cf4c0c7ca434598aa370712c6 + } + + @Override -+ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws java.io.IOException { ++ public void write(ChunkPos chunkcoordintpair, net.minecraft.nbt.CompoundTag nbttagcompound) throws java.io.IOException { + if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( + this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, @@ -3335,184 +3070,81 @@ index 33a8604fa6c6431ccc5f61e484c163e09f1625a0..d082af8cf4c0c7ca434598aa370712c6 + // Paper end + public static enum Occupancy { - - HAS_SPACE(PoiRecord::hasSpace), IS_OCCUPIED(PoiRecord::isOccupied), ANY((villageplacerecord) -> { + HAS_SPACE(PoiRecord::hasSpace), + IS_OCCUPIED(PoiRecord::isOccupied), diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java -index d97e266b83bb331fcd4031046a5843d29ce53164..90833389022d7412bdda8868a356b84f62a00e03 100644 +index 3af31dc2c82c11ee78d497c5777615c17cb13c7a..3b8c04f6ffd7e6c197465aa1caf633ba92529472 100644 --- a/src/main/java/net/minecraft/world/level/TickNextTickData.java +++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java -@@ -5,7 +5,7 @@ import net.minecraft.core.BlockPos; +@@ -4,7 +4,7 @@ import java.util.Comparator; + import net.minecraft.core.BlockPos; public class TickNextTickData { - - private static long counter; + private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading private final T type; public final BlockPos pos; public final long triggerTick; -@@ -17,7 +17,7 @@ public class TickNextTickData { +@@ -16,7 +16,7 @@ public class TickNextTickData { } public TickNextTickData(BlockPos pos, T t, long time, TickPriority priority) { -- this.c = (long) (TickNextTickData.counter++); -+ this.c = (long) (TickNextTickData.COUNTER.getAndIncrement()); // Paper - async chunk loading +- this.c = (long)(counter++); ++ this.c = (TickNextTickData.COUNTER.getAndIncrement()); // Paper - async chunk loading this.pos = pos.immutable(); this.type = t; this.triggerTick = time; -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -index 46d5a24332c1fd3c164b760ec2a2d5bf859b1ab6..3c85b0d39a3fc5c8ec073d92f48b360c0b0be245 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -@@ -170,6 +170,7 @@ public class ChunkStatus { - return ChunkStatus.STATUS_BY_RANGE.size(); - } - -+ public static int getTicketLevelOffset(ChunkStatus status) { return ChunkStatus.getDistance(status); } // Paper - OBFHELPER - public static int getDistance(ChunkStatus status) { - return ChunkStatus.RANGE_BY_STATUS.getInt(status.getIndex()); - } -@@ -185,6 +186,7 @@ public class ChunkStatus { - this.index = previous == null ? 0 : previous.getIndex() + 1; - } - -+ public final int getStatusIndex() { return getIndex(); } // Paper - OBFHELPER - public int getIndex() { - return this.index; - } -@@ -193,7 +195,7 @@ public class ChunkStatus { - return this.name; - } - -- public ChunkStatus getPreviousStatus() { return this.getParent(); } // Paper - OBFHELPER -+ public final ChunkStatus getPreviousStatus() { return this.getParent(); } // Paper - OBFHELPER - public ChunkStatus getParent() { - return this.parent; - } -@@ -206,6 +208,7 @@ public class ChunkStatus { - return this.loadingTask.doWork(this, world, structureManager, lightingProvider, function, chunk); - } - -+ public final int getNeighborRadius() { return this.getRange(); } // Paper - OBFHELPER - public int getRange() { - return this.range; - } -@@ -233,6 +236,7 @@ public class ChunkStatus { - return this.heightmapsAfter; - } - -+ public final boolean isAtLeastStatus(ChunkStatus chunkstatus) { return isOrAfter(chunkstatus); } // Paper - OBFHELPER - public boolean isOrAfter(ChunkStatus chunk) { - return this.getIndex() >= chunk.getIndex(); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java -index 808f69a10589a4a7d6c238c05f6d3e0f272681d3..2b798f4e556302f6f79d54182a309f4716a84f04 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java -@@ -73,6 +73,7 @@ public class DataLayer { - return this.data; - } - -+ public DataLayer copy() { return this.copy(); } // Paper - OBFHELPER - public DataLayer copy() { - return this.data == null ? new DataLayer() : new DataLayer((byte[]) this.data.clone()); - } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2..be67dc16bf70e4517efd213ca9002f116f60b57c 100644 +index 22d5c4cc3aea19cbf53ea320765ecceb4daf7428..2621739b8dd11860084ea574c243cb8ba167ac40 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet; - import it.unimi.dsi.fastutil.longs.LongSet; - import it.unimi.dsi.fastutil.shorts.ShortList; - import it.unimi.dsi.fastutil.shorts.ShortListIterator; -+import java.util.ArrayDeque; // Paper - import java.util.Arrays; - import java.util.BitSet; - import java.util.EnumSet; -@@ -66,34 +67,58 @@ public class ChunkSerializer { +@@ -69,7 +69,30 @@ public class ChunkSerializer { - private static final Logger LOGGER = LogManager.getLogger(); + public ChunkSerializer() {} + // Paper start + public static final class InProgressChunkHolder { + + public final ProtoChunk protoChunk; -+ public final ArrayDeque tasks; ++ public final java.util.ArrayDeque tasks; + + public CompoundTag poiData; + -+ public InProgressChunkHolder(final ProtoChunk protoChunk, final ArrayDeque tasks) { ++ public InProgressChunkHolder(final ProtoChunk protoChunk, final java.util.ArrayDeque tasks) { + this.protoChunk = protoChunk; + this.tasks = tasks; + } + } ++ // Paper end + - public static ProtoChunk read(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag tag) { -- ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); -+ InProgressChunkHolder holder = loadChunk(world, structureManager, poiStorage, pos, tag, true); + public static ProtoChunk read(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt) { ++ // Paper start - add variant for async calls ++ InProgressChunkHolder holder = loadChunk(world, structureManager, poiStorage, pos, nbt, true); + holder.tasks.forEach(Runnable::run); + return holder.protoChunk; + } -+ -+ public static InProgressChunkHolder loadChunk(ServerLevel worldserver, StructureManager definedstructuremanager, PoiManager villageplace, ChunkPos chunkcoordintpair, CompoundTag nbttagcompound, boolean distinguish) { -+ ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); ++ public static InProgressChunkHolder loadChunk(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt, boolean distinguish) { ++ java.util.ArrayDeque tasksToExecuteOnMain = new java.util.ArrayDeque<>(); + // Paper end -+ ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); -- CompoundTag nbttagcompound1 = tag.getCompound("Level"); -+ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); - ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); - -- if (!Objects.equals(pos, chunkcoordintpair1)) { -- ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", pos, pos, chunkcoordintpair1); -+ if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { -+ ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); - } - -- ChunkBiomeContainer biomestorage = new ChunkBiomeContainer(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), pos, worldchunkmanager, nbttagcompound1.contains("Biomes", 11) ? nbttagcompound1.getIntArray("Biomes") : null); -+ ChunkBiomeContainer biomestorage = new ChunkBiomeContainer(worldserver.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunkcoordintpair, worldchunkmanager, nbttagcompound1.contains("Biomes", 11) ? nbttagcompound1.getIntArray("Biomes") : null); - UpgradeData chunkconverter = nbttagcompound1.contains("UpgradeData", 10) ? new UpgradeData(nbttagcompound1.getCompound("UpgradeData")) : UpgradeData.EMPTY; - ProtoTickList protochunkticklist = new ProtoTickList<>((block) -> { - return block == null || block.defaultBlockState().isAir(); -- }, pos, nbttagcompound1.getList("ToBeTicked", 9)); -+ }, chunkcoordintpair, nbttagcompound1.getList("ToBeTicked", 9)); - ProtoTickList protochunkticklist1 = new ProtoTickList<>((fluidtype) -> { - return fluidtype == null || fluidtype == Fluids.EMPTY; -- }, pos, nbttagcompound1.getList("LiquidsToBeTicked", 9)); -+ }, chunkcoordintpair, nbttagcompound1.getList("LiquidsToBeTicked", 9)); - boolean flag = nbttagcompound1.getBoolean("isLightOn"); - ListTag nbttaglist = nbttagcompound1.getList("Sections", 10); - boolean flag1 = true; - LevelChunkSection[] achunksection = new LevelChunkSection[16]; -- boolean flag2 = world.dimensionType().hasSkyLight(); -- ServerChunkCache chunkproviderserver = world.getChunkSource(); -+ boolean flag2 = worldserver.dimensionType().hasSkyLight(); -+ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); + CompoundTag nbttagcompound1 = nbt.getCompound("Level"); +@@ -96,7 +119,9 @@ public class ChunkSerializer { LevelLightEngine lightengine = chunkproviderserver.getLightEngine(); if (flag) { -- lightengine.retainData(pos, true); + tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main -+ lightengine.retainData(chunkcoordintpair, true); + lightengine.retainData(pos, true); + }); // Paper - delay this task since we're executing off-main } - for (int i = 0; i < nbttaglist.size(); ++i) { -@@ -101,7 +126,7 @@ public class ChunkSerializer { - byte b0 = nbttagcompound2.getByte("Y"); - - if (nbttagcompound2.contains("Palette", 9) && nbttagcompound2.contains("BlockStates", 12)) { -- LevelChunkSection chunksection = new LevelChunkSection(b0 << 4, null, world, false); // Paper - Anti-Xray - Add parameters -+ LevelChunkSection chunksection = new LevelChunkSection(b0 << 4, null, worldserver, false); // Paper - Anti-Xray - Add parameters - - chunksection.getStates().read(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); - chunksection.recalcBlockCounts(); -@@ -109,22 +134,34 @@ public class ChunkSerializer { - achunksection[b0] = chunksection; + for (int j = 0; j < nbttaglist.size(); ++j) { +@@ -112,16 +137,28 @@ public class ChunkSerializer { + achunksection[world.getSectionIndexFromSectionY(b0)] = chunksection; } -- poiStorage.checkConsistencyWithBlocks(pos, chunksection); + tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main -+ villageplace.checkConsistencyWithBlocks(chunkcoordintpair, chunksection); + poiStorage.checkConsistencyWithBlocks(pos, chunksection); + }); // Paper - delay this task since we're executing off-main } @@ -3522,68 +3154,23 @@ index 8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2..be67dc16bf70e4517efd213ca9002f11 + // Paper start - delay this task since we're executing off-main + DataLayer blockLight = new DataLayer(nbttagcompound2.getByteArray("BlockLight")); + tasksToExecuteOnMain.add(() -> { -+ lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair, b0), blockLight, true); ++ lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair1, b0), blockLight, true); + }); + // Paper end - delay this task since we're executing off-main } - if (flag2 && nbttagcompound2.contains("SkyLight", 7)) { + if (flag1 && nbttagcompound2.contains("SkyLight", 7)) { - lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("SkyLight")), true); + // Paper start - delay this task since we're executing off-main + DataLayer skyLight = new DataLayer(nbttagcompound2.getByteArray("SkyLight")); + tasksToExecuteOnMain.add(() -> { -+ lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkcoordintpair, b0), skyLight, true); ++ lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkcoordintpair1, b0), skyLight, true); + }); + // Paper end - delay this task since we're executing off-main } } } - - long j = nbttagcompound1.getLong("InhabitedTime"); -- ChunkStatus.ChunkType chunkstatus_type = getChunkTypeFromTag(tag); -+ ChunkStatus.ChunkType chunkstatus_type = getChunkTypeFromTag(nbttagcompound); - Object object; - - if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) { -@@ -155,7 +192,7 @@ public class ChunkSerializer { - object2 = protochunkticklist1; - } - -- object = new LevelChunk(world.getLevel(), pos, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { -+ object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { - postLoadChunk(nbttagcompound1, chunk); - // CraftBukkit start - load chunk persistent data from nbt - net.minecraft.nbt.Tag persistentBase = nbttagcompound1.get("ChunkBukkitValues"); -@@ -165,7 +202,7 @@ public class ChunkSerializer { - // CraftBukkit end - }); - } else { -- ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world); // Paper - Anti-Xray - Add parameter -+ ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter - - protochunk.setBiomes(biomestorage); - object = protochunk; -@@ -176,7 +213,7 @@ public class ChunkSerializer { - } - - if (!flag && protochunk.getStatus().isOrAfter(ChunkStatus.LIGHT)) { -- Iterator iterator = BlockPos.betweenClosed(pos.getMinBlockX(), 0, pos.getMinBlockZ(), pos.getMaxBlockX(), 255, pos.getMaxBlockZ()).iterator(); -+ Iterator iterator = BlockPos.betweenClosed(chunkcoordintpair.getMinBlockX(), 0, chunkcoordintpair.getMinBlockZ(), chunkcoordintpair.getMaxBlockX(), 255, chunkcoordintpair.getMaxBlockZ()).iterator(); - - while (iterator.hasNext()) { - BlockPos blockposition = (BlockPos) iterator.next(); -@@ -207,8 +244,8 @@ public class ChunkSerializer { - Heightmap.primeHeightmaps((ChunkAccess) object, enumset); - CompoundTag nbttagcompound4 = nbttagcompound1.getCompound("Structures"); - -- ((ChunkAccess) object).setAllStarts(unpackStructureStart(structureManager, nbttagcompound4, world.getSeed())); -- ((ChunkAccess) object).setAllReferences(unpackStructureReferences(pos, nbttagcompound4)); -+ ((ChunkAccess) object).setAllStarts(unpackStructureStart(definedstructuremanager, nbttagcompound4, worldserver.getSeed())); -+ ((ChunkAccess) object).setAllReferences(unpackStructureReferences(chunkcoordintpair, nbttagcompound4)); - if (nbttagcompound1.getBoolean("shouldSave")) { - ((ChunkAccess) object).setUnsaved(true); - } -@@ -227,7 +264,7 @@ public class ChunkSerializer { +@@ -235,7 +272,7 @@ public class ChunkSerializer { } if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) { @@ -3592,7 +3179,7 @@ index 8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2..be67dc16bf70e4517efd213ca9002f11 } else { ProtoChunk protochunk1 = (ProtoChunk) object; -@@ -266,12 +303,84 @@ public class ChunkSerializer { +@@ -274,11 +311,83 @@ public class ChunkSerializer { protochunk1.setCarvingMask(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1))); } @@ -3670,47 +3257,25 @@ index 8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2..be67dc16bf70e4517efd213ca9002f11 + } + public static CompoundTag write(ServerLevel world, ChunkAccess chunk) { -- ChunkPos chunkcoordintpair = chunk.getPos(); + return saveChunk(world, chunk, null); + } -+ public static CompoundTag saveChunk(ServerLevel worldserver, ChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { ++ public static CompoundTag saveChunk(ServerLevel world, ChunkAccess chunk, AsyncSaveData asyncsavedata) { + // Paper end -+ ChunkPos chunkcoordintpair = ichunkaccess.getPos(); + ChunkPos chunkcoordintpair = chunk.getPos(); CompoundTag nbttagcompound = new CompoundTag(); CompoundTag nbttagcompound1 = new CompoundTag(); - -@@ -279,30 +388,38 @@ public class ChunkSerializer { +@@ -287,7 +396,7 @@ public class ChunkSerializer { nbttagcompound.put("Level", nbttagcompound1); nbttagcompound1.putInt("xPos", chunkcoordintpair.x); nbttagcompound1.putInt("zPos", chunkcoordintpair.z); - nbttagcompound1.putLong("LastUpdate", world.getGameTime()); -- nbttagcompound1.putLong("InhabitedTime", chunk.getInhabitedTime()); -- nbttagcompound1.putString("Status", chunk.getStatus().getName()); -- UpgradeData chunkconverter = chunk.getUpgradeData(); -+ nbttagcompound1.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getGameTime()); // Paper - async chunk unloading -+ nbttagcompound1.putLong("InhabitedTime", ichunkaccess.getInhabitedTime()); -+ nbttagcompound1.putString("Status", ichunkaccess.getStatus().getName()); -+ UpgradeData chunkconverter = ichunkaccess.getUpgradeData(); - - if (!chunkconverter.isEmpty()) { - nbttagcompound1.put("UpgradeData", chunkconverter.write()); - } - -- LevelChunkSection[] achunksection = chunk.getSections(); -+ LevelChunkSection[] achunksection = ichunkaccess.getSections(); - ListTag nbttaglist = new ListTag(); -- ThreadedLevelLightEngine lightenginethreaded = world.getChunkSource().getLightEngine(); -- boolean flag = chunk.isLightCorrect(); -+ ThreadedLevelLightEngine lightenginethreaded = worldserver.getChunkSource().getLightEngine(); -+ boolean flag = ichunkaccess.isLightCorrect(); - - CompoundTag nbttagcompound2; - -- for (int i = -1; i < 17; ++i) { -+ for (int i = -1; i < 17; ++i) { // Paper - conflict on loop parameter change - int finalI = i; // CraftBukkit - decompile errors ++ nbttagcompound1.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : world.getGameTime()); // Paper - async chunk unloading + nbttagcompound1.putLong("InhabitedTime", chunk.getInhabitedTime()); + nbttagcompound1.putString("Status", chunk.getStatus().getName()); + UpgradeData chunkconverter = chunk.getUpgradeData(); +@@ -306,9 +415,17 @@ public class ChunkSerializer { LevelChunkSection chunksection = (LevelChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { - return chunksection1 != null && chunksection1.bottomBlockY() >> 4 == finalI; // CraftBukkit - decompile errors + return chunksection1 != null && SectionPos.blockToSectionCoord(chunksection1.bottomBlockY()) == finalI; // CraftBukkit - decompile errors }).findFirst().orElse(LevelChunk.EMPTY_SECTION); - DataLayer nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); - DataLayer nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); @@ -3727,99 +3292,9 @@ index 8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2..be67dc16bf70e4517efd213ca9002f11 + } + // Paper end if (chunksection != LevelChunk.EMPTY_SECTION || nibblearray != null || nibblearray1 != null) { - nbttagcompound2 = new CompoundTag(); - nbttagcompound2.putByte("Y", (byte) (i & 255)); -@@ -327,21 +444,21 @@ public class ChunkSerializer { - nbttagcompound1.putBoolean("isLightOn", true); - } + CompoundTag nbttagcompound2 = new CompoundTag(); -- ChunkBiomeContainer biomestorage = chunk.getBiomes(); -+ ChunkBiomeContainer biomestorage = ichunkaccess.getBiomes(); - - if (biomestorage != null) { - nbttagcompound1.putIntArray("Biomes", biomestorage.writeBiomes()); - } - - ListTag nbttaglist1 = new ListTag(); -- Iterator iterator = chunk.getBlockEntitiesPos().iterator(); -+ Iterator iterator = ichunkaccess.getBlockEntitiesPos().iterator(); - - CompoundTag nbttagcompound3; - - while (iterator.hasNext()) { - BlockPos blockposition = (BlockPos) iterator.next(); - -- nbttagcompound3 = chunk.getBlockEntityNbtForSaving(blockposition); -+ nbttagcompound3 = ichunkaccess.getBlockEntityNbtForSaving(blockposition); - if (nbttagcompound3 != null) { - nbttaglist1.add(nbttagcompound3); - } -@@ -351,25 +468,25 @@ public class ChunkSerializer { - ListTag nbttaglist2 = new ListTag(); - - java.util.List toUpdate = new java.util.ArrayList<>(); // Paper -- if (chunk.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { -- LevelChunk chunk1 = (LevelChunk) chunk; -+ if (ichunkaccess.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { -+ LevelChunk chunk = (LevelChunk) ichunkaccess; - - // CraftBukkit start - store chunk persistent data in nbt -- if (!chunk1.persistentDataContainer.isEmpty()) { -- nbttagcompound1.put("ChunkBukkitValues", chunk1.persistentDataContainer.toTagCompound()); -+ if (!chunk.persistentDataContainer.isEmpty()) { -+ nbttagcompound1.put("ChunkBukkitValues", chunk.persistentDataContainer.toTagCompound()); - } - // CraftBukkit end - -- chunk1.setLastSaveHadEntities(false); -+ chunk.setLastSaveHadEntities(false); - -- for (int j = 0; j < chunk1.getEntitySlices().length; ++j) { -- Iterator iterator1 = chunk1.getEntitySlices()[j].iterator(); -+ for (int j = 0; j < chunk.getEntitySlices().length; ++j) { -+ Iterator iterator1 = chunk.getEntitySlices()[j].iterator(); - - while (iterator1.hasNext()) { - Entity entity = (Entity) iterator1.next(); - CompoundTag nbttagcompound4 = new CompoundTag(); - // Paper start -- if ((int) Math.floor(entity.getX()) >> 4 != chunk1.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk1.getPos().z) { -+ if (asyncsavedata == null && !entity.removed && (int) Math.floor(entity.getX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk.getPos().z) { - toUpdate.add(entity); - continue; - } -@@ -378,7 +495,7 @@ public class ChunkSerializer { - } - // Paper end - if (entity.save(nbttagcompound4)) { -- chunk1.setLastSaveHadEntities(true); -+ chunk.setLastSaveHadEntities(true); - nbttaglist2.add(nbttagcompound4); - } - } -@@ -386,12 +503,12 @@ public class ChunkSerializer { - - // Paper start - move entities to the correct chunk - for (Entity entity : toUpdate) { -- world.updateChunkPos(entity); -+ worldserver.updateChunkPos(entity); - } - // Paper end - - } else { -- ProtoChunk protochunk = (ProtoChunk) chunk; -+ ProtoChunk protochunk = (ProtoChunk) ichunkaccess; - - nbttaglist2.addAll(protochunk.getEntities()); - nbttagcompound1.put("Lights", packOffsets(protochunk.getPackedLights())); -@@ -412,40 +529,48 @@ public class ChunkSerializer { - } - - nbttagcompound1.put("Entities", nbttaglist2); -- TickList ticklist = chunk.getBlockTicks(); -+ TickList ticklist = ichunkaccess.getBlockTicks(); // Paper - diff on method change (see getAsyncSaveData) - - if (ticklist instanceof ProtoTickList) { +@@ -384,6 +501,10 @@ public class ChunkSerializer { nbttagcompound1.put("ToBeTicked", ((ProtoTickList) ticklist).save()); } else if (ticklist instanceof ChunkTickList) { nbttagcompound1.put("TileTicks", ((ChunkTickList) ticklist).save()); @@ -3828,14 +3303,9 @@ index 8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2..be67dc16bf70e4517efd213ca9002f11 + nbttagcompound1.put("TileTicks", asyncsavedata.blockTickList); + // Paper end } else { -- nbttagcompound1.put("TileTicks", world.getBlockTicks().save(chunkcoordintpair)); -+ nbttagcompound1.put("TileTicks", worldserver.getBlockTicks().save(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) + nbttagcompound1.put("TileTicks", world.getBlockTicks().save(chunkcoordintpair)); } - -- TickList ticklist1 = chunk.getLiquidTicks(); -+ TickList ticklist1 = ichunkaccess.getLiquidTicks(); // Paper - diff on method change (see getAsyncSaveData) - - if (ticklist1 instanceof ProtoTickList) { +@@ -394,6 +515,10 @@ public class ChunkSerializer { nbttagcompound1.put("LiquidsToBeTicked", ((ProtoTickList) ticklist1).save()); } else if (ticklist1 instanceof ChunkTickList) { nbttagcompound1.put("LiquidTicks", ((ChunkTickList) ticklist1).save()); @@ -3844,65 +3314,34 @@ index 8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2..be67dc16bf70e4517efd213ca9002f11 + nbttagcompound1.put("LiquidTicks", asyncsavedata.fluidTickList); + // Paper end } else { -- nbttagcompound1.put("LiquidTicks", world.getLiquidTicks().save(chunkcoordintpair)); -+ nbttagcompound1.put("LiquidTicks", worldserver.getLiquidTicks().save(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) + nbttagcompound1.put("LiquidTicks", world.getLiquidTicks().save(chunkcoordintpair)); } - -- nbttagcompound1.put("PostProcessing", packOffsets(chunk.getPostProcessing())); -+ nbttagcompound1.put("PostProcessing", packOffsets(ichunkaccess.getPostProcessing())); - nbttagcompound2 = new CompoundTag(); -- Iterator iterator2 = chunk.getHeightmaps().iterator(); -+ Iterator iterator2 = ichunkaccess.getHeightmaps().iterator(); - - while (iterator2.hasNext()) { - Entry entry = (Entry) iterator2.next(); - -- if (chunk.getStatus().heightmapsAfter().contains(entry.getKey())) { -+ if (ichunkaccess.getStatus().heightmapsAfter().contains(entry.getKey())) { - nbttagcompound2.put(((Heightmap.Types) entry.getKey()).getSerializationKey(), new LongArrayTag(((Heightmap) entry.getValue()).getRawData())); - } - } - - nbttagcompound1.put("Heightmaps", nbttagcompound2); -- nbttagcompound1.put("Structures", packStructureData(chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences())); -+ nbttagcompound1.put("Structures", packStructureData(chunkcoordintpair, ichunkaccess.getAllStarts(), ichunkaccess.getAllReferences())); - return nbttagcompound; - } - // Paper start - this is saved with the player diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -index 9cffef2098fbfba89ddd88a45bde33c07660497a..684442b7175e30b6d4cafb2f7d2d4c10517cc33d 100644 +index 00470d96be2500a0516125771304e76dfd4268a4..6f13c7adce7d4b3d170045ea5ef2a841d34ae7b0 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -@@ -3,6 +3,10 @@ package net.minecraft.world.level.chunk.storage; - import com.mojang.datafixers.DataFixer; - import java.io.File; - import java.io.IOException; -+// Paper start -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.CompletionException; -+// Paper end - import java.util.function.Supplier; - import javax.annotation.Nullable; - import net.minecraft.SharedConstants; -@@ -21,32 +25,41 @@ import net.minecraft.world.level.storage.DimensionDataStorage; +@@ -21,27 +21,38 @@ import net.minecraft.world.level.storage.DimensionDataStorage; public class ChunkStorage implements AutoCloseable { -- private final IOWorker worker; public IOWorker getIOWorker() { return worker; } // Paper - OBFHELPER -+ // Paper - OBFHELPER - nuke IOWorker +- private final IOWorker worker; ++ // Paper - nuke IO worker protected final DataFixer fixerUpper; @Nullable - private LegacyStructureDataHandler legacyStructureHandler; -+ private volatile LegacyStructureDataHandler legacyStructureHandler; // Paper - async chunk loading -+ ++ // Paper start - async chunk loading ++ private volatile LegacyStructureDataHandler legacyStructureHandler; + private final Object persistentDataLock = new Object(); // Paper + public final RegionFileStorage regionFileCache; ++ // Paper end - async chunk loading - public ChunkStorage(File file, DataFixer datafixer, boolean flag) { -+ this.regionFileCache = new RegionFileStorage(file, flag); // Paper - nuke IOWorker - this.fixerUpper = datafixer; -- this.worker = new IOWorker(file, flag, "chunk"); -+ // Paper - nuke IOWorker + public ChunkStorage(File directory, DataFixer dataFixer, boolean dsync) { + this.fixerUpper = dataFixer; +- this.worker = new IOWorker(directory, dsync, "chunk"); ++ // Paper start - async chunk io ++ // remove IO worker ++ this.regionFileCache = new RegionFileStorage(directory, dsync); // Paper - nuke IOWorker ++ // Paper end - async chunk io } // CraftBukkit start @@ -3917,27 +3356,16 @@ index 9cffef2098fbfba89ddd88a45bde33c07660497a..684442b7175e30b6d4cafb2f7d2d4c10 } } -- CompoundTag nbt = read(pos); -- if (nbt != null) { -- CompoundTag level = nbt.getCompound("Level"); -- if (level.getBoolean("TerrainPopulated")) { -- return true; -- } -+ -+ // Paper start - prioritize -+ CompoundTag nbt = cps == null ? read(pos) : -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.loadChunkData((ServerLevel)cps.getLevel(), x, z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHER_PRIORITY, false, true).chunkData; -+ // Paper end -+ if (nbt != null) { -+ CompoundTag level = nbt.getCompound("Level"); -+ if (level.getBoolean("TerrainPopulated")) { -+ return true; -+ } - - ChunkStatus status = ChunkStatus.byName(level.getString("Status")); - if (status != null && status.isOrAfter(ChunkStatus.FEATURES)) { -@@ -77,11 +90,13 @@ public class ChunkStorage implements AutoCloseable { +- CompoundTag nbt = this.read(pos); ++ // Paper start - prioritize ++ CompoundTag nbt = cps == null ? read(pos) : ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.loadChunkData((ServerLevel)cps.getLevel(), x, z, ++ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHER_PRIORITY, false, true).chunkData; ++ // Paper end + if (nbt != null) { + CompoundTag level = nbt.getCompound("Level"); + if (level.getBoolean("TerrainPopulated")) { +@@ -77,11 +88,13 @@ public class ChunkStorage implements AutoCloseable { if (i < 1493) { nbttagcompound = NbtUtils.update(this.fixerUpper, DataFixTypes.CHUNK, nbttagcompound, i, 1493); if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { @@ -3951,50 +3379,51 @@ index 9cffef2098fbfba89ddd88a45bde33c07660497a..684442b7175e30b6d4cafb2f7d2d4c10 } } -@@ -99,22 +114,20 @@ public class ChunkStorage implements AutoCloseable { +@@ -99,22 +112,26 @@ public class ChunkStorage implements AutoCloseable { @Nullable - public CompoundTag read(ChunkPos chunkcoordintpair) throws IOException { -- return this.worker.load(chunkcoordintpair); -+ return this.regionFileCache.read(chunkcoordintpair); + public CompoundTag read(ChunkPos chunkPos) throws IOException { +- return this.worker.load(chunkPos); ++ return this.regionFileCache.read(chunkPos); // Paper - async chunk io } -- public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) { -- this.worker.store(chunkcoordintpair, nbttagcompound); -+ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER -+ public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) -+ this.regionFileCache.write(chunkcoordintpair, nbttagcompound); +- public void write(ChunkPos chunkPos, CompoundTag nbt) { +- this.worker.store(chunkPos, nbt); ++ // Paper start - async chunk io ++ public void write(ChunkPos chunkPos, CompoundTag nbt) throws IOException { ++ this.regionFileCache.write(chunkPos, nbt); ++ // Paper end - Async chunk loading if (this.legacyStructureHandler != null) { + synchronized (this.persistentDataLock) { // Paper - Async chunk loading - this.legacyStructureHandler.removeIndex(chunkcoordintpair.toLong()); -+ } // Paper - Async chunk loading} + this.legacyStructureHandler.removeIndex(chunkPos.toLong()); ++ } // Paper - Async chunk loading } -- -- } -- -- public void flushWorker() { + + } + + public void flushWorker() { - this.worker.synchronize().join(); ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.flush(); // Paper - nuke IO worker } public void close() throws IOException { - this.worker.close(); -+ this.regionFileCache.close(); ++ this.regionFileCache.close(); // Paper - nuke IO worker } } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 4d96e5ed28c910387c0a4238c9036c7a12458f57..7ecde2cb15fa0b1b5195fc560c559f2c367e336f 100644 +index 1a35ef48c487c92f55fcbbfc19a708ededc6a32d..357da4846344d1182ab7149c4d352d5019384715 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -45,6 +45,8 @@ public class RegionFile implements AutoCloseable { +@@ -47,6 +47,7 @@ public class RegionFile implements AutoCloseable { + private final IntBuffer timestamps; + @VisibleForTesting protected final RegionBitmap usedSectors; - public final File file; // Paper - + public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper -+ - // Paper start - Cache chunk status - private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; -@@ -251,7 +253,7 @@ public class RegionFile implements AutoCloseable { + public RegionFile(File file, File directory, boolean dsync) throws IOException { + this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); +@@ -232,7 +233,7 @@ public class RegionFile implements AutoCloseable { return (byteCount + 4096 - 1) / 4096; } @@ -4003,7 +3432,7 @@ index 4d96e5ed28c910387c0a4238c9036c7a12458f57..7ecde2cb15fa0b1b5195fc560c559f2c int i = this.getOffset(pos); if (i == 0) { -@@ -411,6 +413,11 @@ public class RegionFile implements AutoCloseable { +@@ -399,6 +400,11 @@ public class RegionFile implements AutoCloseable { } public void close() throws IOException { @@ -4012,10 +3441,10 @@ index 4d96e5ed28c910387c0a4238c9036c7a12458f57..7ecde2cb15fa0b1b5195fc560c559f2c + synchronized (this) { + try { + // Paper end - this.closed = true; // Paper try { this.padToFullSector(); -@@ -421,6 +428,10 @@ public class RegionFile implements AutoCloseable { + } finally { +@@ -408,6 +414,10 @@ public class RegionFile implements AutoCloseable { this.file.close(); } } @@ -4027,31 +3456,35 @@ index 4d96e5ed28c910387c0a4238c9036c7a12458f57..7ecde2cb15fa0b1b5195fc560c559f2c } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 6f1c96e4325caf6b4762700ad2286d9ea41515c9..0498982ac14f20145d68dbf64a46bcaacf5516ef 100644 +index 3c82f98a34a5911fdb9e3ba66c54d25f6944fd07..211ab6cffe78c61fcff12ef7ffba904c4cae57b2 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -17,7 +17,7 @@ import net.minecraft.server.MinecraftServer; +@@ -15,7 +15,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.util.ExceptionCollector; import net.minecraft.world.level.ChunkPos; -public final class RegionFileStorage implements AutoCloseable { +public class RegionFileStorage implements AutoCloseable { // Paper - no final - public final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap(); - private final File folder; -@@ -30,16 +30,27 @@ public final class RegionFileStorage implements AutoCloseable { - - - // Paper start -- public RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { -+ public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { // Paper - synchronize for async io - return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); + public static final String ANVIL_EXTENSION = ".mca"; + private static final int MAX_CACHE_SIZE = 256; +@@ -28,11 +28,32 @@ public final class RegionFileStorage implements AutoCloseable { + this.sync = dsync; } - // Paper end -- public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public -+ public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public, synchronize -+ // Paper start - add lock parameter +- private RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit ++ // Paper start ++ public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { ++ return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); ++ } ++ ++ public synchronized boolean chunkExists(ChunkPos pos) throws IOException { ++ RegionFile regionfile = getFile(pos, true); ++ ++ return regionfile != null ? regionfile.hasChunk(pos) : false; ++ } ++ ++ public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - public + return this.getFile(chunkcoordintpair, existingOnly, false); + } + public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly, boolean lock) throws IOException { @@ -4069,8 +3502,8 @@ index 6f1c96e4325caf6b4762700ad2286d9ea41515c9..0498982ac14f20145d68dbf64a46bcaa return regionfile; } else { if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable -@@ -55,6 +66,12 @@ public final class RegionFileStorage implements AutoCloseable { - RegionFile regionfile1 = new RegionFile(file, this.folder, this.sync); +@@ -50,6 +71,12 @@ public final class RegionFileStorage implements AutoCloseable { + RegionFile regionfile1 = new RegionFile(file1, this.folder, this.sync); this.regionCache.putAndMoveToFirst(i, regionfile1); + // Paper start @@ -4082,7 +3515,7 @@ index 6f1c96e4325caf6b4762700ad2286d9ea41515c9..0498982ac14f20145d68dbf64a46bcaa return regionfile1; } } -@@ -130,11 +147,12 @@ public final class RegionFileStorage implements AutoCloseable { +@@ -57,11 +84,12 @@ public final class RegionFileStorage implements AutoCloseable { @Nullable public CompoundTag read(ChunkPos pos) throws IOException { // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing @@ -4094,9 +3527,9 @@ index 6f1c96e4325caf6b4762700ad2286d9ea41515c9..0498982ac14f20145d68dbf64a46bcaa // CraftBukkit end + try { // Paper DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); - // Paper start - if (regionfile.isOversized(pos.x, pos.z)) { -@@ -172,10 +190,14 @@ public final class RegionFileStorage implements AutoCloseable { + + CompoundTag nbttagcompound; +@@ -98,10 +126,14 @@ public final class RegionFileStorage implements AutoCloseable { } return nbttagcompound; @@ -4105,14 +3538,14 @@ index 6f1c96e4325caf6b4762700ad2286d9ea41515c9..0498982ac14f20145d68dbf64a46bcaa + } // Paper end } - protected void write(ChunkPos pos, CompoundTag tag) throws IOException { + protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException { - RegionFile regionfile = this.getFile(pos, false); // CraftBukkit + RegionFile regionfile = this.getFile(pos, false, true); // CraftBukkit // Paper + try { // Paper int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper - DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(pos); - Throwable throwable = null; -@@ -214,9 +236,12 @@ public final class RegionFileStorage implements AutoCloseable { + + if (nbt == null) { +@@ -140,9 +172,12 @@ public final class RegionFileStorage implements AutoCloseable { MinecraftServer.LOGGER.error("Failed to save chunk", laste); } // Paper end @@ -4126,69 +3559,61 @@ index 6f1c96e4325caf6b4762700ad2286d9ea41515c9..0498982ac14f20145d68dbf64a46bcaa ExceptionCollector exceptionsuppressor = new ExceptionCollector<>(); ObjectIterator objectiterator = this.regionCache.values().iterator(); -@@ -243,4 +268,12 @@ public final class RegionFileStorage implements AutoCloseable { - } - +@@ -159,7 +194,7 @@ public final class RegionFileStorage implements AutoCloseable { + exceptionsuppressor.throwIfPresent(); } -+ -+ // CraftBukkit start -+ public synchronized boolean chunkExists(ChunkPos pos) throws IOException { // Paper - synchronize -+ RegionFile regionfile = getFile(pos, true); -+ -+ return regionfile != null ? regionfile.hasChunk(pos) : false; -+ } -+ // CraftBukkit end - } + +- public void flush() throws IOException { ++ public synchronized void flush() throws IOException { // Paper - synchronize + ObjectIterator objectiterator = this.regionCache.values().iterator(); + + while (objectiterator.hasNext()) { diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java -index 059a658aa87d19025daa66d98f78112d5f5be4e3..bb30fb085a6c5edb717ad006c0ab481723ca1b6b 100644 +index 844d65612d9c4c19d02a2b0a5b90cd44de9f17c9..cfd4c38ca99b183f23716f82c972c14be33ca13d 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java -@@ -30,28 +30,29 @@ import net.minecraft.world.level.Level; +@@ -30,12 +30,12 @@ import net.minecraft.world.level.LevelHeightAccessor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -public class SectionStorage implements AutoCloseable { +public class SectionStorage extends RegionFileStorage implements AutoCloseable { // Paper - nuke IOWorker - private static final Logger LOGGER = LogManager.getLogger(); + private static final String SECTIONS_TAG = "Sections"; - private final IOWorker worker; -+ // Paper - nuke IOWorker - private final Long2ObjectMap> storage = new Long2ObjectOpenHashMap(); ++ // Paper - remove mojang I/O thread + private final Long2ObjectMap> storage = new Long2ObjectOpenHashMap<>(); - private final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet(); + public final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet(); // Paper - private -> public private final Function> codec; private final Function factory; private final DataFixer fixerUpper; - private final DataFixTypes type; +@@ -43,12 +43,13 @@ public class SectionStorage implements AutoCloseable { + protected final LevelHeightAccessor levelHeightAccessor; - public SectionStorage(File directory, Function> codecFactory, Function factory, DataFixer datafixer, DataFixTypes datafixtypes, boolean flag) { -+ super(directory, flag); // Paper - nuke IOWorker + public SectionStorage(File directory, Function> codecFactory, Function factory, DataFixer dataFixer, DataFixTypes dataFixTypes, boolean dsync, LevelHeightAccessor world) { ++ super(directory, dsync); // Paper - nuke IOWorker this.codec = codecFactory; this.factory = factory; - this.fixerUpper = datafixer; - this.type = datafixtypes; -- this.worker = new IOWorker(directory, flag, directory.getName()); -+ //this.b = new IOWorker(file, flag, file.getName()); // Paper - nuke IOWorker + this.fixerUpper = dataFixer; + this.type = dataFixTypes; + this.levelHeightAccessor = world; +- this.worker = new IOWorker(directory, dsync, directory.getName()); ++ // Paper - remove mojang I/O thread } protected void tick(BooleanSupplier shouldKeepTicking) { - while (!this.dirty.isEmpty() && shouldKeepTicking.getAsBoolean()) { -- ChunkPos chunkcoordintpair = SectionPos.of(this.dirty.firstLong()).chunk(); -+ ChunkPos chunkcoordintpair = SectionPos.of(this.dirty.firstLong()).chunk(); // Paper - conflict here to avoid obfhelpers - - this.writeColumn(chunkcoordintpair); - } -@@ -105,13 +106,18 @@ public class SectionStorage implements AutoCloseable { +@@ -106,13 +107,18 @@ public class SectionStorage implements AutoCloseable { } - private void readColumn(ChunkPos chunkcoordintpair) { -- this.readColumn(chunkcoordintpair, NbtOps.INSTANCE, this.tryRead(chunkcoordintpair)); -+ // Paper start - load data in function -+ this.loadInData(chunkcoordintpair, this.tryRead(chunkcoordintpair)); + private void readColumn(ChunkPos chunkPos) { +- this.readColumn(chunkPos, NbtOps.INSTANCE, this.tryRead(chunkPos)); ++ // Paper start - expose function to load in data ++ this.loadInData(chunkPos, this.tryRead(chunkPos)); + } + public void loadInData(ChunkPos chunkPos, CompoundTag compound) { + this.readColumn(chunkPos, NbtOps.INSTANCE, compound); -+ // Paper end ++ // Paper end - expose function to load in data } @Nullable @@ -4196,22 +3621,17 @@ index 059a658aa87d19025daa66d98f78112d5f5be4e3..bb30fb085a6c5edb717ad006c0ab4817 try { - return this.worker.load(pos); + return this.read(pos); // Paper - nuke IOWorker - } catch (IOException ioexception) { - SectionStorage.LOGGER.error("Error reading chunk {} data from disk", pos, ioexception); + } catch (IOException var3) { + LOGGER.error("Error reading chunk {} data from disk", pos, var3); return null; -@@ -157,17 +163,31 @@ public class SectionStorage implements AutoCloseable { - } - - private void writeColumn(ChunkPos chunkcoordintpair) { -- Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); -+ Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); // Paper - conflict here to avoid adding obfhelpers :) - Tag nbtbase = (Tag) dynamic.getValue(); - - if (nbtbase instanceof CompoundTag) { -- this.worker.store(chunkcoordintpair, (CompoundTag) nbtbase); -+ try { this.write(chunkcoordintpair, (CompoundTag) nbtbase); } catch (IOException ioexception) { SectionStorage.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker // TODO make this write async +@@ -156,13 +162,26 @@ public class SectionStorage implements AutoCloseable { + Dynamic dynamic = this.writeColumn(chunkPos, NbtOps.INSTANCE); + Tag tag = dynamic.getValue(); + if (tag instanceof CompoundTag) { +- this.worker.store(chunkPos, (CompoundTag)tag); ++ try { this.write(chunkPos, (CompoundTag)tag); } catch (IOException ioexception) { SectionStorage.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker } else { - SectionStorage.LOGGER.error("Expected compound tag, got {}", nbtbase); + LOGGER.error("Expected compound tag, got {}", (Object)tag); } } @@ -4229,40 +3649,23 @@ index 059a658aa87d19025daa66d98f78112d5f5be4e3..bb30fb085a6c5edb717ad006c0ab4817 + return null; + } + // Paper end -+ - private Dynamic writeColumn(ChunkPos chunkcoordintpair, DynamicOps dynamicops) { + private Dynamic writeColumn(ChunkPos chunkPos, DynamicOps dynamicOps) { Map map = Maps.newHashMap(); -@@ -213,9 +233,9 @@ public class SectionStorage implements AutoCloseable { - public void flush(ChunkPos chunkcoordintpair) { - if (!this.dirty.isEmpty()) { - for (int i = 0; i < 16; ++i) { -- long j = SectionPos.of(chunkcoordintpair, i).asLong(); -+ long j = SectionPos.of(chunkcoordintpair, i).asLong(); // Paper - conflict here to avoid obfhelpers +@@ -219,6 +238,23 @@ public class SectionStorage implements AutoCloseable { -- if (this.dirty.contains(j)) { -+ if (this.dirty.contains(j)) { // Paper - conflict here to avoid obfhelpers - this.writeColumn(chunkcoordintpair); - return; - } -@@ -224,7 +244,26 @@ public class SectionStorage implements AutoCloseable { - - } - -- public void close() throws IOException { + @Override + public void close() throws IOException { - this.worker.close(); -+// Paper start - nuke IOWorker -+// public void close() throws IOException { -+// this.b.close(); -+// } -+// Paper end ++ //this.worker.close(); // Paper - nuke I/O worker ++ } + + // Paper start - get data function + public CompoundTag getData(ChunkPos chunkcoordintpair) { + // Note: Copied from above -+ // This is checking if the data exists, then it builds it later in getDataInternal(ChunkCoordIntPair) ++ // This is checking if the data needs to be written, then it builds it later in getDataInternal(ChunkCoordIntPair) + if (!this.dirty.isEmpty()) { -+ for (int i = 0; i < 16; ++i) { ++ for (int i = this.levelHeightAccessor.getMinSection(); i < this.levelHeightAccessor.getMaxSection(); ++i) { + long j = SectionPos.of(chunkcoordintpair, i).asLong(); + + if (this.dirty.contains(j)) { @@ -4275,55 +3678,23 @@ index 059a658aa87d19025daa66d98f78112d5f5be4e3..bb30fb085a6c5edb717ad006c0ab4817 + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index a0615e4ba015cca4fe074de63b87d0bff84b1a14..52444619a4bae80a12bf296fbe07fa811adf806e 100644 +index 2a9a57263ff116c1a7f51eac127292559de48b11..84666742e0082f8fb853f255a8ec27832a75d4b0 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -545,22 +545,23 @@ public class CraftWorld implements World { - return true; - } - -- net.minecraft.world.level.chunk.storage.RegionFile file; -- try { -- file = world.getChunkSource().chunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -- } catch (IOException ex) { -- throw new RuntimeException(ex); -- } -+ ChunkStatus status = world.getChunkSource().chunkMap.getStatusOnDiskNoLoad(x, z); // Paper - async io - move to own method - -- ChunkStatus status = file.getStatusIfCached(x, z); -- if (!file.hasChunk(chunkPos) || (status != null && status != ChunkStatus.FULL)) { -+ // Paper start - async io -+ if (status == ChunkStatus.EMPTY) { -+ // does not exist on disk - return false; - } - -+ if (status == null) { // at this stage we don't know what it is on disk - ChunkAccess chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.EMPTY, true); - if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof net.minecraft.world.level.chunk.LevelChunk)) { - return false; - } -+ } else if (status != ChunkStatus.FULL) { -+ return false; // not full status on disk -+ } -+ // Paper end - - // fall through to load - // we do this so we do not re-read the chunk data on disk -@@ -2483,6 +2484,34 @@ public class CraftWorld implements World { +@@ -2422,6 +2422,34 @@ public class CraftWorld implements World { public DragonBattle getEnderDragonBattle() { - return (getHandle().dragonFight() == null) ? null : new CraftDragonBattle(getHandle().dragonFight()); + return (this.getHandle().dragonFight() == null) ? null : new CraftDragonBattle(this.getHandle().dragonFight()); } + // Paper start + @Override -+ public CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { ++ public java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { + if (Bukkit.isPrimaryThread()) { + net.minecraft.world.level.chunk.LevelChunk immediate = this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); + if (immediate != null) { -+ return CompletableFuture.completedFuture(immediate.getBukkitChunk()); ++ return java.util.concurrent.CompletableFuture.completedFuture(immediate.getBukkitChunk()); + } + } else { -+ CompletableFuture future = new CompletableFuture(); ++ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture(); + world.getServer().execute(() -> { + getChunkAtAsync(x, z, gen, urgent).whenComplete((chunk, err) -> { + if (err != null) { @@ -4338,7 +3709,7 @@ index a0615e4ba015cca4fe074de63b87d0bff84b1a14..52444619a4bae80a12bf296fbe07fa81 + + return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { + net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); -+ return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); ++ return java.util.concurrent.CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + }, net.minecraft.server.MinecraftServer.getServer()); + } + // Paper end @@ -4346,32 +3717,30 @@ index a0615e4ba015cca4fe074de63b87d0bff84b1a14..52444619a4bae80a12bf296fbe07fa81 // Spigot start @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 7ad4fb57af32cc1b8278688381e1b058ed8437db..76d652386806fd11961611486a1d0a12fe9616a4 100644 +index 0bc816407157264bf3e736da678535d08b4d85f2..ead2b25042af2622f75f7be1fdfad9b4250ac0cc 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -11,7 +11,9 @@ import net.minecraft.core.BlockPos; - import net.minecraft.nbt.CompoundTag; +@@ -12,6 +12,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; -+import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.level.TicketType; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.AreaEffectCloud; import net.minecraft.world.entity.Entity; -@@ -508,6 +510,28 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - entity.setYHeadRot(yaw); +@@ -514,6 +515,28 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + this.entity.setYHeadRot(yaw); } + @Override// Paper start + public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { -+ ChunkMap playerChunkMap = ((CraftWorld) loc.getWorld()).getHandle().getChunkSource().chunkMap; ++ net.minecraft.server.level.ChunkMap playerChunkMap = ((CraftWorld) loc.getWorld()).getHandle().getChunkSource().chunkMap; + java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); + + loc.getWorld().getChunkAtAsyncUrgently(loc).thenCompose(chunk -> { -+ ChunkCoordIntPair pair = new ChunkCoordIntPair(chunk.getX(), chunk.getZ()); -+ ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().addTicketAtLevel(TicketType.POST_TELEPORT, pair, 31, 0); -+ PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pair.pair()); ++ net.minecraft.world.level.ChunkPos pair = new net.minecraft.world.level.ChunkPos(chunk.getX(), chunk.getZ()); ++ ((CraftWorld) loc.getWorld()).getHandle().getChunkSource().addTicketAtLevel(TicketType.POST_TELEPORT, pair, 31, 0); ++ net.minecraft.server.level.ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pair.toLong()); + if (updatingChunk != null) { + return updatingChunk.getEntityTickingFuture(); + } else { @@ -4387,24 +3756,16 @@ index 7ad4fb57af32cc1b8278688381e1b058ed8437db..76d652386806fd11961611486a1d0a12 + @Override public boolean teleport(Location location) { - return teleport(location, TeleportCause.PLUGIN); + return this.teleport(location, TeleportCause.PLUGIN); diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 16f6163bb53e73aa4ab6e22365342613b6b38118..33a66322d253c7562ae5acbdbc6cc87f7d72a9af 100644 +index a01a266a25e3267c94c20f8597b4b596efe20faa..1ffb208094f521883ef0e23baf5fb29380b14273 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -6,6 +6,7 @@ import java.lang.management.ThreadInfo; - import java.util.logging.Level; - import java.util.logging.Logger; - import com.destroystokyo.paper.PaperConfig; -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; // Paper - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; - -@@ -116,6 +117,7 @@ public class WatchdogThread extends Thread +@@ -117,6 +117,7 @@ public class WatchdogThread extends Thread // Paper end - Different message for short timeout log.log( Level.SEVERE, "------------------------------" ); log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper -+ ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper + WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); log.log( Level.SEVERE, "------------------------------" ); // From 75b99eb454494983ff7c0b91dc58de82eef35d4d Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 12 Jun 2021 19:18:24 -0700 Subject: [PATCH 058/226] Add `runWorkDir` property for setting a custom run task working directory --- patches/server/0001-Setup-Gradle-project.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/patches/server/0001-Setup-Gradle-project.patch b/patches/server/0001-Setup-Gradle-project.patch index cd9ca86451..161db84a2a 100644 --- a/patches/server/0001-Setup-Gradle-project.patch +++ b/patches/server/0001-Setup-Gradle-project.patch @@ -17,7 +17,7 @@ index 67fb370cad6924895a6b27052dbd5c1767e3f0c9..3e05459f27c4c5697ae65da504d67a6a /.project diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 -index 0000000000000000000000000000000000000000..ccb67fe90e25010f7c8ca168d60d096ef95c4429 +index 0000000000000000000000000000000000000000..eed3e6de0224a03b5ca9dd914b96e2fe4b94793e --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,121 @@ @@ -109,9 +109,9 @@ index 0000000000000000000000000000000000000000..ccb67fe90e25010f7c8ca168d60d096e +fun TaskContainer.registerRunTask(name: String, block: JavaExec.() -> Unit): TaskProvider = + register(name) { + group = "Paper" -+ workingDir = rootProject.projectDir.resolve("run") ++ workingDir = layout.projectDirectory.dir(providers.gradleProperty("runWorkDir").orElse("run")).get().asFile + doFirst { -+ if (!workingDir.exists()) workingDir.mkdir() ++ workingDir.mkdirs() + } + standardInput = System.`in` + args("--nogui") From 24e9620d14461cb73af5786c306359403c00bf31 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 12 Jun 2021 19:23:21 -0700 Subject: [PATCH 059/226] Use `mergeServiceFiles()` instead of AppendingTransformer --- patches/server/0001-Setup-Gradle-project.patch | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/patches/server/0001-Setup-Gradle-project.patch b/patches/server/0001-Setup-Gradle-project.patch index 161db84a2a..4eb6e8fba2 100644 --- a/patches/server/0001-Setup-Gradle-project.patch +++ b/patches/server/0001-Setup-Gradle-project.patch @@ -17,10 +17,10 @@ index 67fb370cad6924895a6b27052dbd5c1767e3f0c9..3e05459f27c4c5697ae65da504d67a6a /.project diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 -index 0000000000000000000000000000000000000000..eed3e6de0224a03b5ca9dd914b96e2fe4b94793e +index 0000000000000000000000000000000000000000..492e3b592d17bd3d5fb4a36ff123f2bd2d13051e --- /dev/null +++ b/build.gradle.kts -@@ -0,0 +1,121 @@ +@@ -0,0 +1,119 @@ +import com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer +import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer +import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer @@ -96,9 +96,7 @@ index 0000000000000000000000000000000000000000..eed3e6de0224a03b5ca9dd914b96e2fe + relocate("org.bukkit.craftbukkit", "org.bukkit.craftbukkit.v$packageVersion") { + exclude("org.bukkit.craftbukkit.Main*") + } -+ transform(AppendingTransformer::class.java) { -+ resource = "META-INF/services/java.sql.Driver" -+ } ++ mergeServiceFiles() + transform(ModifiedLog4j2PluginsCacheFileTransformer::class.java) +} + From 152994d950649dcce587067c139e43fcc41155d2 Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Sat, 12 Jun 2021 22:18:50 -0500 Subject: [PATCH 060/226] Bump tiny-remapper to 0.4.1 --- build.gradle.kts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9c49ca8942..407f27e9d2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -38,8 +38,7 @@ subprojects { } repositories { - mavenLocal() - + mavenCentral() maven("https://wav.jfrog.io/artifactory/repo/") { content { onlyForConfigurations("paperclip") @@ -59,7 +58,7 @@ repositories { dependencies { paramMappings("org.quiltmc:yarn:1.17+build.2:mergedv2") - remapper("org.quiltmc:tiny-remapper:0.3.2:fat@jar") + remapper("org.quiltmc:tiny-remapper:0.4.1") decompiler("net.minecraftforge:forgeflower:1.5.498.12@jar") paperclip("io.papermc:paperclip:2.0.0-SNAPSHOT@jar") } From 06f41a48851b249847037300670595f48108cefd Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 12 Jun 2021 20:21:59 -0700 Subject: [PATCH 061/226] Use `forUseAtConfigurationTime()` for run directory property --- patches/server/0001-Setup-Gradle-project.patch | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/patches/server/0001-Setup-Gradle-project.patch b/patches/server/0001-Setup-Gradle-project.patch index 4eb6e8fba2..2bfeb3af87 100644 --- a/patches/server/0001-Setup-Gradle-project.patch +++ b/patches/server/0001-Setup-Gradle-project.patch @@ -17,10 +17,10 @@ index 67fb370cad6924895a6b27052dbd5c1767e3f0c9..3e05459f27c4c5697ae65da504d67a6a /.project diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 -index 0000000000000000000000000000000000000000..492e3b592d17bd3d5fb4a36ff123f2bd2d13051e +index 0000000000000000000000000000000000000000..29564703bd1502269c04cd5fb3070b687ca51af5 --- /dev/null +++ b/build.gradle.kts -@@ -0,0 +1,119 @@ +@@ -0,0 +1,121 @@ +import com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer +import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer +import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer @@ -107,7 +107,9 @@ index 0000000000000000000000000000000000000000..492e3b592d17bd3d5fb4a36ff123f2bd +fun TaskContainer.registerRunTask(name: String, block: JavaExec.() -> Unit): TaskProvider = + register(name) { + group = "Paper" -+ workingDir = layout.projectDirectory.dir(providers.gradleProperty("runWorkDir").orElse("run")).get().asFile ++ workingDir = layout.projectDirectory.dir( ++ providers.gradleProperty("runWorkDir").forUseAtConfigurationTime().orElse("run") ++ ).get().asFile + doFirst { + workingDir.mkdirs() + } From 2a3f1fa30cf9b513685dbe7c2f6606bcd76c2e27 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 12 Jun 2021 20:35:03 -0700 Subject: [PATCH 062/226] Resolve run working directory from rootProject --- patches/server/0001-Setup-Gradle-project.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/server/0001-Setup-Gradle-project.patch b/patches/server/0001-Setup-Gradle-project.patch index 2bfeb3af87..b2c3b3a0e8 100644 --- a/patches/server/0001-Setup-Gradle-project.patch +++ b/patches/server/0001-Setup-Gradle-project.patch @@ -17,7 +17,7 @@ index 67fb370cad6924895a6b27052dbd5c1767e3f0c9..3e05459f27c4c5697ae65da504d67a6a /.project diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 -index 0000000000000000000000000000000000000000..29564703bd1502269c04cd5fb3070b687ca51af5 +index 0000000000000000000000000000000000000000..21b97f37a4c4d35d80bc1c1b98f55bcfb8d21f20 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,121 @@ @@ -107,7 +107,7 @@ index 0000000000000000000000000000000000000000..29564703bd1502269c04cd5fb3070b68 +fun TaskContainer.registerRunTask(name: String, block: JavaExec.() -> Unit): TaskProvider = + register(name) { + group = "Paper" -+ workingDir = layout.projectDirectory.dir( ++ workingDir = rootProject.layout.projectDirectory.dir( + providers.gradleProperty("runWorkDir").forUseAtConfigurationTime().orElse("run") + ).get().asFile + doFirst { From ca621e6280a576506bd61e2ba8b3a85f0a2cf26b Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sat, 12 Jun 2021 21:03:02 -0700 Subject: [PATCH 063/226] even even even even more work --- ...ray-tracing-methods-to-LivingEntity.patch} | 2 +- ...e-attack-cooldown-methods-for-Player.patch | 0 .../0148-Improve-death-events.patch} | 0 .../0149-Mob-Pathfinding-API.patch} | 0 ...anPlaceOn-and-CanDestroy-NBT-values.patch} | 0 ...-ray-tracing-methods-to-LivingEntity.patch | 99 -------- ...ent-Mob-AI-Rules-from-Loading-Chunks.patch | 83 ------- ...-ray-tracing-methods-to-LivingEntity.patch | 90 +++++++ ...-attack-cooldown-methods-for-Player.patch} | 21 +- .../0260-Improve-death-events.patch} | 230 ++++++------------ ...w-chests-to-be-placed-with-NBT-data.patch} | 8 +- .../0262-Mob-Pathfinding-API.patch} | 55 ++--- ...nt-chunk-loading-from-Fluid-Flowing.patch} | 14 +- ...for-CanPlaceOn-and-CanDestroy-NBT-v.patch} | 102 +++----- ...ent-Mob-AI-Rules-from-Loading-Chunks.patch | 40 +++ ...ning-from-loading-generating-chunks.patch} | 14 +- 16 files changed, 292 insertions(+), 466 deletions(-) rename patches/{api-unmapped/0144-Add-ray-tracing-methods-to-LivingEntity.patch => api/0146-Add-ray-tracing-methods-to-LivingEntity.patch} (98%) rename patches/{api-unmapped => api}/0147-Expose-attack-cooldown-methods-for-Player.patch (100%) rename patches/{api-unmapped/0145-Improve-death-events.patch => api/0148-Improve-death-events.patch} (100%) rename patches/{api-unmapped/0146-Mob-Pathfinding-API.patch => api/0149-Mob-Pathfinding-API.patch} (100%) rename patches/{api-unmapped/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch => api/0150-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch} (100%) delete mode 100644 patches/server-remapped/0279-Add-ray-tracing-methods-to-LivingEntity.patch delete mode 100644 patches/server-remapped/0286-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch create mode 100644 patches/server/0258-Add-ray-tracing-methods-to-LivingEntity.patch rename patches/{server-remapped/0280-Expose-attack-cooldown-methods-for-Player.patch => server/0259-Expose-attack-cooldown-methods-for-Player.patch} (53%) rename patches/{server-remapped/0281-Improve-death-events.patch => server/0260-Improve-death-events.patch} (60%) rename patches/{server-remapped/0282-Allow-chests-to-be-placed-with-NBT-data.patch => server/0261-Allow-chests-to-be-placed-with-NBT-data.patch} (81%) rename patches/{server-remapped/0283-Mob-Pathfinding-API.patch => server/0262-Mob-Pathfinding-API.patch} (85%) rename patches/{server-remapped/0284-Prevent-chunk-loading-from-Fluid-Flowing.patch => server/0263-Prevent-chunk-loading-from-Fluid-Flowing.patch} (88%) rename patches/{server-remapped/0285-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch => server/0264-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch} (79%) create mode 100644 patches/server/0265-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch rename patches/{server-remapped/0287-Prevent-mob-spawning-from-loading-generating-chunks.patch => server/0266-Prevent-mob-spawning-from-loading-generating-chunks.patch} (63%) diff --git a/patches/api-unmapped/0144-Add-ray-tracing-methods-to-LivingEntity.patch b/patches/api/0146-Add-ray-tracing-methods-to-LivingEntity.patch similarity index 98% rename from patches/api-unmapped/0144-Add-ray-tracing-methods-to-LivingEntity.patch rename to patches/api/0146-Add-ray-tracing-methods-to-LivingEntity.patch index 96c37c9d46..8b636c8548 100644 --- a/patches/api-unmapped/0144-Add-ray-tracing-methods-to-LivingEntity.patch +++ b/patches/api/0146-Add-ray-tracing-methods-to-LivingEntity.patch @@ -65,7 +65,7 @@ index 0000000000000000000000000000000000000000..18a96dbb01d3b34476652264b2d6be37 + } +} diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 8b89c0701dd557bcab0c05c1593354ee704b9fe4..8fe7ccf12339355554835542cc1068d9f6c3a435 100644 +index 4f62a49e7b0538f0ce9cecd2c1b645f40ce17b3d..05992ade1bca42a6233373b44513b89986d89c5a 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -82,6 +82,77 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api-unmapped/0147-Expose-attack-cooldown-methods-for-Player.patch b/patches/api/0147-Expose-attack-cooldown-methods-for-Player.patch similarity index 100% rename from patches/api-unmapped/0147-Expose-attack-cooldown-methods-for-Player.patch rename to patches/api/0147-Expose-attack-cooldown-methods-for-Player.patch diff --git a/patches/api-unmapped/0145-Improve-death-events.patch b/patches/api/0148-Improve-death-events.patch similarity index 100% rename from patches/api-unmapped/0145-Improve-death-events.patch rename to patches/api/0148-Improve-death-events.patch diff --git a/patches/api-unmapped/0146-Mob-Pathfinding-API.patch b/patches/api/0149-Mob-Pathfinding-API.patch similarity index 100% rename from patches/api-unmapped/0146-Mob-Pathfinding-API.patch rename to patches/api/0149-Mob-Pathfinding-API.patch diff --git a/patches/api-unmapped/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/patches/api/0150-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch similarity index 100% rename from patches/api-unmapped/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch rename to patches/api/0150-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch diff --git a/patches/server-remapped/0279-Add-ray-tracing-methods-to-LivingEntity.patch b/patches/server-remapped/0279-Add-ray-tracing-methods-to-LivingEntity.patch deleted file mode 100644 index f1edc62517..0000000000 --- a/patches/server-remapped/0279-Add-ray-tracing-methods-to-LivingEntity.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 3 Sep 2018 18:20:03 -0500 -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 205c639d26652befebae925fc6e40976c370710f..2e25cb2a04d150d3154bf0d7f0eccb97e65ff53e 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3605,6 +3605,23 @@ public abstract class LivingEntity extends Entity { - this.broadcastBreakEvent(hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); - } - // Paper start -+ public HitResult getRayTrace(int maxDistance) { -+ return getRayTrace(maxDistance, ClipContext.Fluid.NONE); -+ } -+ -+ public HitResult getRayTrace(int maxDistance, ClipContext.Fluid fluidCollisionOption) { -+ if (maxDistance < 1 || maxDistance > 120) { -+ throw new IllegalArgumentException("maxDistance must be between 1-120"); -+ } -+ -+ Vec3 start = new Vec3(getX(), getY() + getEyeHeight(), getZ()); -+ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance); -+ Vec3 end = new Vec3(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ()); -+ ClipContext raytrace = new ClipContext(start, end, ClipContext.Block.OUTLINE, fluidCollisionOption, this); -+ -+ return level.clip(raytrace); -+ } -+ - public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; - - public int getShieldBlockingDelay() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 6dd7a722e10a2727f68318b880f2726bb816f198..7e3a215f1592bed9f35e22076d9e35a5a49a430e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.block.TargetBlockInfo; - import com.google.common.base.Preconditions; - import com.google.common.collect.Sets; - import java.util.ArrayList; -@@ -8,6 +9,7 @@ import java.util.Iterator; - import java.util.List; - import java.util.Set; - import java.util.UUID; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.InteractionHand; - import net.minecraft.world.damagesource.DamageSource; -@@ -28,6 +30,8 @@ import net.minecraft.world.entity.projectile.ThrownEgg; - import net.minecraft.world.entity.projectile.ThrownEnderpearl; - import net.minecraft.world.entity.projectile.ThrownExperienceBottle; - import net.minecraft.world.entity.projectile.ThrownTrident; -+import net.minecraft.world.phys.BlockHitResult; -+import net.minecraft.world.phys.HitResult; - import org.apache.commons.lang.Validate; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -37,6 +41,7 @@ import org.bukkit.attribute.AttributeInstance; - import org.bukkit.block.Block; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.entity.memory.CraftMemoryKey; - import org.bukkit.craftbukkit.entity.memory.CraftMemoryMapper; - import org.bukkit.craftbukkit.inventory.CraftEntityEquipment; -@@ -190,6 +195,28 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return blocks.get(0); - } - -+ // Paper start -+ @Override -+ public Block getTargetBlock(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ HitResult rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof BlockHitResult) ? null : CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()); -+ } -+ -+ @Override -+ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ HitResult rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof BlockHitResult) ? null : MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection()); -+ } -+ -+ @Override -+ public TargetBlockInfo getTargetBlockInfo(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ HitResult rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof BlockHitResult) ? null : -+ new TargetBlockInfo(CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()), -+ MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection())); -+ } -+ // Paper end -+ - @Override - public List getLastTwoTargetBlocks(Set transparent, int maxDistance) { - return getLineOfSight(transparent, maxDistance, 2); diff --git a/patches/server-remapped/0286-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/patches/server-remapped/0286-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch deleted file mode 100644 index dff6bf782c..0000000000 --- a/patches/server-remapped/0286-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 10 Sep 2018 23:56:36 -0400 -Subject: [PATCH] Prevent Mob AI Rules from Loading Chunks - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java -index 415661c61eb85ac57dd2ba81fb62f8d9df54153f..c9825bc1894904fab34bec8223adf8e343bb6623 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java -@@ -29,11 +29,13 @@ public class RemoveBlockGoal extends MoveToBlockGoal { - private final Block blockToRemove; - private final Mob removerMob; - private int ticksSinceReachedGoal; -+ private Level world; // Paper - - public RemoveBlockGoal(Block targetBlock, PathfinderMob mob, double speed, int maxYDifference) { - super(mob, speed, 24, maxYDifference); - this.blockToRemove = targetBlock; - this.removerMob = mob; -+ this.world = mob.level; // Paper - } - - @Override -@@ -131,7 +133,9 @@ public class RemoveBlockGoal extends MoveToBlockGoal { - - @Nullable - private BlockPos getPosWithBlock(BlockPos pos, BlockGetter world) { -- if (world.getBlockState(pos).is(this.blockToRemove)) { -+ Block block = world.getBlockIfLoaded(pos); // Paper -+ if (block == null) return null; // Paper -+ if (block.is(this.blockToRemove)) { // Paper - return pos; - } else { - BlockPos[] ablockposition = new BlockPos[]{pos.below(), pos.west(), pos.east(), pos.north(), pos.south(), pos.below().below()}; -@@ -141,7 +145,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal { - for (int j = 0; j < i; ++j) { - BlockPos blockposition1 = ablockposition1[j]; - -- if (world.getBlockState(blockposition1).is(this.blockToRemove)) { -+ if (world.getBlockIfLoaded(blockposition1).is(this.blockToRemove)) { // Paper - return blockposition1; - } - } -@@ -152,7 +156,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal { - - @Override - protected boolean isValidTarget(LevelReader world, BlockPos pos) { -- ChunkAccess ichunkaccess = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, false); -+ ChunkAccess ichunkaccess = world.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4); // Paper - - return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).is(this.blockToRemove) && ichunkaccess.getBlockState(pos.above()).isAir() && ichunkaccess.getBlockState(pos.above(2)).isAir(); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java b/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java -index 246cbddb23781e323d022db2fbeef72c9eeaad2b..55d484fd4774cfad8f8ba3263b387243540e31b1 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java -+++ b/src/main/java/net/minecraft/world/entity/ai/util/RandomPos.java -@@ -13,6 +13,7 @@ import net.minecraft.util.Mth; - import net.minecraft.world.entity.PathfinderMob; - import net.minecraft.world.entity.ai.navigation.PathNavigation; - import net.minecraft.world.level.BlockGetter; -+import net.minecraft.world.level.material.FluidState; - import net.minecraft.world.level.pathfinder.BlockPathTypes; - import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; - import net.minecraft.world.phys.Vec3; -@@ -128,6 +129,7 @@ public class RandomPos { - } - - blockposition2 = new BlockPos((double) k1 + mob.getX(), (double) l1 + mob.getY(), (double) i2 + mob.getZ()); -+ if (!mob.level.hasChunkAt(blockposition2)) continue; // Paper - if (blockposition2.getY() >= 0 && blockposition2.getY() <= mob.level.getMaxBuildHeight() && (!flag3 || mob.isWithinRestriction(blockposition2)) && (!validPositionsOnly || navigationabstract.isStableDestination(blockposition2))) { - if (aboveGround) { - blockposition2 = moveUpToAboveSolid(blockposition2, random.nextInt(distanceAboveGroundRange + 1) + minDistanceAboveGround, mob.level.getMaxBuildHeight(), (blockposition3) -> { -@@ -135,7 +137,8 @@ public class RandomPos { - }); - } - -- if (notInWater || !mob.level.getFluidState(blockposition2).is((Tag) FluidTags.WATER)) { -+ FluidState fluid = mob.level.getFluidIfLoaded(blockposition2); // Paper -+ if (notInWater || (fluid != null && !fluid.is((Tag) FluidTags.WATER))) { // Paper - BlockPathTypes pathtype = WalkNodeEvaluator.getBlockPathTypeStatic((BlockGetter) mob.level, blockposition2.mutable()); - - if (mob.getPathfindingMalus(pathtype) == 0.0F) { diff --git a/patches/server/0258-Add-ray-tracing-methods-to-LivingEntity.patch b/patches/server/0258-Add-ray-tracing-methods-to-LivingEntity.patch new file mode 100644 index 0000000000..bdc08913cd --- /dev/null +++ b/patches/server/0258-Add-ray-tracing-methods-to-LivingEntity.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Mon, 3 Sep 2018 18:20:03 -0500 +Subject: [PATCH] Add ray tracing methods to LivingEntity + + +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index 49fd3486a6c595749f33bbe1c1bec0454e4725c5..5c290f263fc2b643987c96ea75729bf1ff493760 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -482,6 +482,18 @@ public final class MCUtil { + return getNMSWorld(entity.getWorld()); + } + ++ public static ClipContext.Fluid getNMSFluidCollisionOption(com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) { ++ switch (fluidMode) { ++ case NEVER: ++ return ClipContext.Fluid.NONE; ++ case SOURCE_ONLY: ++ return ClipContext.Fluid.SOURCE_ONLY; ++ case ALWAYS: ++ return ClipContext.Fluid.ANY; ++ } ++ return null; ++ } ++ + public static BlockFace toBukkitBlockFace(Direction enumDirection) { + switch (enumDirection) { + case DOWN: +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index acf6f04fa229fb0850217ff3d50bf3b8c16cafdf..773c1e0ed3e10157c968d84b19947d99bb01371a 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3686,6 +3686,23 @@ public abstract class LivingEntity extends Entity { + } + + // Paper start ++ public HitResult getRayTrace(int maxDistance) { ++ return getRayTrace(maxDistance, ClipContext.Fluid.NONE); ++ } ++ ++ public HitResult getRayTrace(int maxDistance, ClipContext.Fluid fluidCollisionOption) { ++ if (maxDistance < 1 || maxDistance > 120) { ++ throw new IllegalArgumentException("maxDistance must be between 1-120"); ++ } ++ ++ Vec3 start = new Vec3(getX(), getY() + getEyeHeight(), getZ()); ++ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance); ++ Vec3 end = new Vec3(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ()); ++ ClipContext raytrace = new ClipContext(start, end, ClipContext.Block.OUTLINE, fluidCollisionOption, this); ++ ++ return level.clip(raytrace); ++ } ++ + public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; + + public int getShieldBlockingDelay() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 5194da5a141718390a317d75b31205f951cec7a2..cb4c15d17ea3f22e6baa73ba6ce2a18e34ac4b00 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -190,6 +190,28 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return blocks.get(0); + } + ++ // Paper start ++ @Override ++ public Block getTargetBlock(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) { ++ net.minecraft.world.phys.HitResult rayTrace = getHandle().getRayTrace(maxDistance, net.minecraft.server.MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof net.minecraft.world.phys.BlockHitResult) ? null : org.bukkit.craftbukkit.block.CraftBlock.at(getHandle().level, ((net.minecraft.world.phys.BlockHitResult)rayTrace).getBlockPos()); ++ } ++ ++ @Override ++ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) { ++ net.minecraft.world.phys.HitResult rayTrace = getHandle().getRayTrace(maxDistance, net.minecraft.server.MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof net.minecraft.world.phys.BlockHitResult) ? null : net.minecraft.server.MCUtil.toBukkitBlockFace(((net.minecraft.world.phys.BlockHitResult)rayTrace).getDirection()); ++ } ++ ++ @Override ++ public com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) { ++ net.minecraft.world.phys.HitResult rayTrace = getHandle().getRayTrace(maxDistance, net.minecraft.server.MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof net.minecraft.world.phys.BlockHitResult) ? null : ++ new com.destroystokyo.paper.block.TargetBlockInfo(org.bukkit.craftbukkit.block.CraftBlock.at(getHandle().level, ((net.minecraft.world.phys.BlockHitResult)rayTrace).getBlockPos()), ++ net.minecraft.server.MCUtil.toBukkitBlockFace(((net.minecraft.world.phys.BlockHitResult)rayTrace).getDirection())); ++ } ++ // Paper end ++ + @Override + public List getLastTwoTargetBlocks(Set transparent, int maxDistance) { + return this.getLineOfSight(transparent, maxDistance, 2); diff --git a/patches/server-remapped/0280-Expose-attack-cooldown-methods-for-Player.patch b/patches/server/0259-Expose-attack-cooldown-methods-for-Player.patch similarity index 53% rename from patches/server-remapped/0280-Expose-attack-cooldown-methods-for-Player.patch rename to patches/server/0259-Expose-attack-cooldown-methods-for-Player.patch index bfe6717c67..f01641a4ef 100644 --- a/patches/server-remapped/0280-Expose-attack-cooldown-methods-for-Player.patch +++ b/patches/server/0259-Expose-attack-cooldown-methods-for-Player.patch @@ -4,35 +4,26 @@ Date: Tue, 4 Sep 2018 15:02:00 -0500 Subject: [PATCH] Expose attack cooldown methods for Player -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 709e930eef7bae5694238ed8c4d0ef59316bb715..14d5acff198338c68162e33d4a90f74be77cb15f 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -2100,6 +2100,7 @@ public abstract class Player extends LivingEntity { - this.entityData.set(Player.DATA_SHOULDER_RIGHT, entityTag); - } - -+ public float getCooldownPeriod() { return this.getCurrentItemAttackStrengthDelay(); } // Paper - OBFHELPER - public float getCurrentItemAttackStrengthDelay() { - return (float) (1.0D / this.getAttributeValue(Attributes.ATTACK_SPEED) * 20.0D); - } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index c7f66dddf0a0850ca4048dd47cd2ded114caa07e..ee823c4ed5b9fcfaa900b470c582435f0b909ebc 100644 +index f8155d7edb4e13c2ec5ed832231f02ee6eff3f35..91dc9e3b02462211a6964204f5409fbae98027e6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2186,6 +2186,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2199,6 +2199,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND)); connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, inventory.getSelected())); } + ++ @Override + public float getCooldownPeriod() { -+ return getHandle().getCooldownPeriod(); ++ return getHandle().getCurrentItemAttackStrengthDelay(); + } + ++ @Override + public float getCooledAttackStrength(float adjustTicks) { + return getHandle().getAttackStrengthScale(adjustTicks); + } + ++ @Override + public void resetCooldown() { + getHandle().resetAttackStrengthTicker(); + } diff --git a/patches/server-remapped/0281-Improve-death-events.patch b/patches/server/0260-Improve-death-events.patch similarity index 60% rename from patches/server-remapped/0281-Improve-death-events.patch rename to patches/server/0260-Improve-death-events.patch index 15db46e30d..3928b674e5 100644 --- a/patches/server-remapped/0281-Improve-death-events.patch +++ b/patches/server/0260-Improve-death-events.patch @@ -14,11 +14,15 @@ to cancel the death which has the benefit of also receiving the dropped items and experience which is otherwise only properly possible by using internal code. +TODO 1.17: this needs to be checked (actually get off your lazy ass and cancel the events) for the following entities, +maybe more (please check patch overrides for drops for more): +- players, armor stands, foxes, chested donkeys/llamas + diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 5664e292046d4fcdb81340df8cee8d04aa27ca55..75419c866641ab654349cde6ca3fbdef701dd8d9 100644 +index 171500918c8ee248689909ae97230eb18adc33e5..44385d07b2deedffd95bcc428d9d8d3f785143db 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -211,6 +211,10 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -218,6 +218,10 @@ public class ServerPlayer extends Player { public int latency; public boolean wonGame; private int containerUpdateDelay; // Paper @@ -29,7 +33,7 @@ index 5664e292046d4fcdb81340df8cee8d04aa27ca55..75419c866641ab654349cde6ca3fbdef // CraftBukkit start public String displayName; -@@ -714,6 +718,15 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -751,6 +755,15 @@ public class ServerPlayer extends Player { Component defaultMessage = this.getCombatTracker().getDeathMessage(); org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure @@ -45,14 +49,14 @@ index 5664e292046d4fcdb81340df8cee8d04aa27ca55..75419c866641ab654349cde6ca3fbdef // SPIGOT-943 - only call if they have an inventory open if (this.containerMenu != this.inventoryMenu) { -@@ -860,8 +873,17 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -898,8 +911,17 @@ public class ServerPlayer extends Player { } } } - - return super.hurt(source, amount); + // Paper start - cancellable death events -+ //return super.damageEntity(damagesource, f); ++ //return super.hurt(source, amount); + this.queueHealthUpdatePacket = true; + boolean damaged = super.hurt(source, amount); + this.queueHealthUpdatePacket = false; @@ -65,73 +69,28 @@ index 5664e292046d4fcdb81340df8cee8d04aa27ca55..75419c866641ab654349cde6ca3fbdef } } } -diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -index 8a0863a695bb33698fb3fe6e06599f6f6f47011f..36e665009418d5177016a744eb920fbf99f534fc 100644 ---- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -+++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -@@ -203,6 +203,7 @@ public class CombatTracker { - this.nextLocation = null; - } - -+ public final void reset() { this.recheckStatus(); } // Paper - OBFHELPER - public void recheckStatus() { - int i = this.inCombat ? 300 : 100; - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 4503bd65b3454bad94bb7b869f4e72e3121d8a3d..e7fed1f8bb8ffb164ddcdab51f41c369d6e3103d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1537,6 +1537,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - // CraftBukkit end - -+ public final void runKillTrigger(Entity entity, int kills, DamageSource damageSource) { this.awardKillScore(entity, kills, damageSource); } // Paper - OBFHELPER - public void awardKillScore(Entity killer, int score, DamageSource damageSource) { - if (killer instanceof ServerPlayer) { - CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer) killer, this, damageSource); -@@ -2441,6 +2442,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.fallDistance = 0.0F; - } - -+ public final void onKill(ServerLevel worldserver, net.minecraft.world.entity.LivingEntity entityLiving) { this.killed(worldserver, entityLiving); } // Paper - OBFHELPER - public void killed(ServerLevel worldserver, net.minecraft.world.entity.LivingEntity entityliving) {} - - protected void moveTowardsClosestSpace(double x, double y, double z) { diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 2e25cb2a04d150d3154bf0d7f0eccb97e65ff53e..7a2292e6907a2ae2026bd7243e864bd8300ecafa 100644 +index 773c1e0ed3e10157c968d84b19947d99bb01371a..fd0c307a4b340661ba9aff9ae4e0055c139a1ebd 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -186,7 +186,7 @@ public abstract class LivingEntity extends Entity { - protected float animStep; - protected float animStepO; - protected float rotOffs; -- protected int deathScore; -+ protected int deathScore;protected int getKillCount() { return this.deathScore; } // Paper - OBFHELPER - public float lastHurt; - protected boolean jumping; - public float xxa; -@@ -230,6 +230,7 @@ public abstract class LivingEntity extends Entity { +@@ -261,6 +261,7 @@ public abstract class LivingEntity extends Entity { public Set collidableExemptions = new HashSet<>(); - public boolean canPickUpLoot; + public boolean bukkitPickUpLoot; public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper + public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event @Override public float getBukkitYaw() { -@@ -1345,13 +1346,17 @@ public abstract class LivingEntity extends Entity { +@@ -1446,13 +1447,12 @@ public abstract class LivingEntity extends Entity { if (knockbackCancelled) this.level.broadcastEntityEvent(this, (byte) 2); // Paper - Disable explosion knockback if (this.isDeadOrDying()) { if (!this.checkTotemDeathProtection(source)) { - SoundEvent soundeffect = this.getDeathSound(); -+ // Paper start - moved into CraftEventFactory event caller for cancellable death event -+ //SoundEffect soundeffect = this.getSoundDeath(); - +- - if (flag1 && soundeffect != null) { - this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); - } -+// if (flag1 && soundeffect != null) { -+// this.playSound(soundeffect, this.getSoundVolume(), this.dH()); -+// } ++ // Paper start - moved into CraftEventFactory event caller for cancellable death event + this.silentDeath = !flag1; // mark entity as dying silently + // Paper end @@ -140,45 +99,46 @@ index 2e25cb2a04d150d3154bf0d7f0eccb97e65ff53e..7a2292e6907a2ae2026bd7243e864bd8 } } else if (flag1) { this.playHurtSound(source); -@@ -1490,27 +1495,48 @@ public abstract class LivingEntity extends Entity { +@@ -1601,7 +1601,7 @@ public abstract class LivingEntity extends Entity { + if (!this.isRemoved() && !this.dead) { Entity entity = source.getEntity(); LivingEntity entityliving = this.getKillCredit(); - -- if (this.deathScore >= 0 && entityliving != null) { -- entityliving.awardKillScore(this, this.deathScore, source); +- + /* // Paper - move down to make death event cancellable - this is the runKillTrigger below -+ if (this.aO >= 0 && entityliving != null) { -+ entityliving.a(this, this.aO, damagesource); + if (this.deathScore >= 0 && entityliving != null) { + entityliving.awardKillScore(this, this.deathScore, source); } - +@@ -1609,20 +1609,43 @@ public abstract class LivingEntity extends Entity { if (this.isSleeping()) { -- this.stopSleeping(); -+ this.entityWakeup(); + this.stopSleeping(); } -+ */ // Paper ++ */ // Paper - move down to make death event cancellable - this is the runKillTrigger below ++ this.dead = true; - this.getCombatTracker().recheckStatus(); -+ // this.getCombatTracker().g(); // Paper - moved into if below as .reset() ++ // Paper - moved into if below if (this.level instanceof ServerLevel) { if (entity != null) { - entity.killed((ServerLevel) this.level, this); -+ // entity.a((WorldServer) this.world, this); // Paper - move below into if for onKill ++ // Paper - move below into if for onKill } - this.dropAllDeathLoot(source); + // Paper start -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.d(source); ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.dropAllDeathLoot(source); + if (deathEvent == null || !deathEvent.isCancelled()) { -+ if (this.getKillCount() >= 0 && entityliving != null) { -+ entityliving.runKillTrigger(this, this.getKillCount(), source); ++ if (this.deathScore >= 0 && entityliving != null) { ++ entityliving.awardKillScore(this, this.deathScore, source); + } ++ + if (this.isSleeping()) { + this.stopSleeping(); + } -+ this.getCombatTracker().reset(); ++ ++ this.getCombatTracker().recheckStatus(); + if (entity != null) { -+ entity.onKill((ServerLevel) this.level, this); ++ entity.killed((ServerLevel) this.level, this); + } + } else { + this.dead = false; @@ -195,7 +155,7 @@ index 2e25cb2a04d150d3154bf0d7f0eccb97e65ff53e..7a2292e6907a2ae2026bd7243e864bd8 } } -@@ -1518,7 +1544,7 @@ public abstract class LivingEntity extends Entity { +@@ -1630,7 +1653,7 @@ public abstract class LivingEntity extends Entity { if (!this.level.isClientSide) { boolean flag = false; @@ -204,26 +164,17 @@ index 2e25cb2a04d150d3154bf0d7f0eccb97e65ff53e..7a2292e6907a2ae2026bd7243e864bd8 if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { BlockPos blockposition = this.blockPosition(); BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState(); -@@ -1546,8 +1572,9 @@ public abstract class LivingEntity extends Entity { +@@ -1658,7 +1681,7 @@ public abstract class LivingEntity extends Entity { } } - protected void dropAllDeathLoot(DamageSource source) { -- Entity entity = source.getEntity(); -+ protected org.bukkit.event.entity.EntityDeathEvent processDeath(DamageSource damagesource) { return d(damagesource); } // Paper - OBFHELPER -+ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper -+ Entity entity = damagesource.getEntity(); ++ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) { // Paper + Entity entity = source.getEntity(); int i; - if (entity instanceof net.minecraft.world.entity.player.Player) { -@@ -1560,19 +1587,22 @@ public abstract class LivingEntity extends Entity { - - this.dropEquipment(); // CraftBukkit - from below - if (this.shouldDropLoot() && this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { -- this.dropFromLootTable(source, flag); -- this.dropCustomDeathLoot(source, i, flag); -+ this.dropFromLootTable(damagesource, flag); -+ this.dropCustomDeathLoot(damagesource, i, flag); +@@ -1676,15 +1699,18 @@ public abstract class LivingEntity extends Entity { + this.dropCustomDeathLoot(source, i, flag); } // CraftBukkit start - Call death event - CraftEventFactory.callEntityDeathEvent(this, this.drops); @@ -242,42 +193,41 @@ index 2e25cb2a04d150d3154bf0d7f0eccb97e65ff53e..7a2292e6907a2ae2026bd7243e864bd8 // CraftBukkit start public int getExpReward() { -@@ -1657,6 +1687,7 @@ public abstract class LivingEntity extends Entity { +@@ -1762,8 +1788,9 @@ public abstract class LivingEntity extends Entity { return SoundEvents.GENERIC_HURT; } -+ public final SoundEvent getDeathSoundEffect() { return this.getDeathSound(); } // Paper - OBFHELPER ++ @Nullable - protected SoundEvent getDeathSound() { +- protected SoundEvent getDeathSound() { ++ public final SoundEvent getDeathSoundPublic() { return this.getDeathSound(); } protected SoundEvent getDeathSound() { // Paper - provide PUBLIC accessor, overrides are hell to deal with return SoundEvents.GENERIC_DEATH; -@@ -2193,10 +2224,12 @@ public abstract class LivingEntity extends Entity { + } + +@@ -2477,7 +2504,7 @@ public abstract class LivingEntity extends Entity { } -+ public final float getDeathSoundVolume() { return this.getSoundVolume(); } // Paper - OBFHELPER - protected float getSoundVolume() { +- protected float getSoundVolume() { ++ public final float getSoundVolumePublic() { return this.getSoundVolume(); } protected float getSoundVolume() { // Paper - provide PUBLIC accessor, overrides are hell return 1.0F; } -+ public float getSoundPitch() { return getVoicePitch();} // Paper - OBFHELPER - protected float getVoicePitch() { - return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.5F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; - } diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java -index c2d98222f575d7383e4c040730f6d531bdb0d7b6..46792914f574800c893eb197fa7b3b87ce7e500b 100644 +index c1cdb1905536bda76f34ad3fc796996443839767..31f4e4a93ea5fd3ffe7e60dff2e2a9642b51daa2 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Fox.java +++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java -@@ -647,15 +647,25 @@ public class Fox extends Animal { +@@ -691,15 +691,25 @@ public class Fox extends Animal { } @Override - protected void dropAllDeathLoot(DamageSource source) { - ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND); -+ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper -+ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND).copy(); // Paper ++ // Paper start - Cancellable death event ++ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) { ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND).copy(); // Paper - modified by supercall + -+ // Paper start - Cancellable death event -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.d(damagesource); ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.dropAllDeathLoot(source); + + // Below is code to drop + @@ -297,11 +247,11 @@ index c2d98222f575d7383e4c040730f6d531bdb0d7b6..46792914f574800c893eb197fa7b3b87 public static boolean isPathClear(Fox fox, LivingEntity chasedEntity) { diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java -index 34a9843267ef739e5889791fb4899fabe1f864bc..63723044ae6c607e6d36bc0b0c6b525037df34b2 100644 +index 224eca7d20cf4b890a6bc1b314d566e02e716762..7281eb294ddd178ba742088d3c61bf3d529ff0c4 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java @@ -68,11 +68,19 @@ public abstract class AbstractChestedHorse extends AbstractHorse { - this.spawnAtLocation((ItemLike) Blocks.CHEST); + this.spawnAtLocation(Blocks.CHEST); } - this.setChest(false); @@ -319,56 +269,33 @@ index 34a9843267ef739e5889791fb4899fabe1f864bc..63723044ae6c607e6d36bc0b0c6b5250 + // Paper end + @Override - public void addAdditionalSaveData(CompoundTag tag) { - super.addAdditionalSaveData(tag); + public void addAdditionalSaveData(CompoundTag nbt) { + super.addAdditionalSaveData(nbt); diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 2994eee1d381af2c9ff3649dd48a2ae14c38c9d7..33d51852ed6fe3f5adcdecf8f405a23689f4265a 100644 +index 4adde11daa5ca97a2bf9c164c43c5c011a89b33d..cb9969d768b13863722aad3dc5daad3c10bb264a 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -610,7 +610,7 @@ public class ArmorStand extends LivingEntity { - this.armorItems.set(i, ItemStack.EMPTY); - } - } -- this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above -+ this.d(damageSource); // CraftBukkit - moved from above - - } - -@@ -742,7 +742,8 @@ public class ArmorStand extends LivingEntity { +@@ -755,7 +755,8 @@ public class ArmorStand extends LivingEntity { @Override public void kill() { - org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event + org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event // Paper - make cancellable + if (event.isCancelled()) return; // Paper - make cancellable - this.remove(); + this.remove(Entity.RemovalReason.KILLED); } -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 14d5acff198338c68162e33d4a90f74be77cb15f..3aadc4ab5fe7b2ee9e20e0789ddcfe750599972f 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -581,7 +581,7 @@ public abstract class Player extends LivingEntity { - super.die(source); - this.reapplyPosition(); - if (!this.isSpectator()) { -- this.dropAllDeathLoot(source); -+ this.d(source); - } - - if (source != null) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ee823c4ed5b9fcfaa900b470c582435f0b909ebc..a3e65028d3e0c09a65cd9c28b037fe01a2ed1d76 100644 +index 91dc9e3b02462211a6964204f5409fbae98027e6..22032108fdaed14663a9d7e0b6757eef5237c4dd 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1836,7 +1836,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1849,7 +1849,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void sendHealthUpdate() { -- getHandle().connection.send(new ClientboundSetHealthPacket(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); +- this.getHandle().connection.send(new ClientboundSetHealthPacket(this.getScaledHealth(), this.getHandle().getFoodData().getFoodLevel(), this.getHandle().getFoodData().getSaturationLevel())); + // Paper start - cancellable death event -+ //getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); -+ ClientboundSetHealthPacket packet = new ClientboundSetHealthPacket(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel()); ++ ClientboundSetHealthPacket packet = new ClientboundSetHealthPacket(this.getScaledHealth(), this.getHandle().getFoodData().getFoodLevel(), this.getHandle().getFoodData().getSaturationLevel()); + if (this.getHandle().queueHealthUpdatePacket) { + this.getHandle().queuedHealthUpdatePacket = packet; + } else { @@ -379,19 +306,10 @@ index ee823c4ed5b9fcfaa900b470c582435f0b909ebc..a3e65028d3e0c09a65cd9c28b037fe01 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 1877267344df1ff5b4de6a4e0c239f488cd52c1f..e696d2e52532df25d74a1f559e2c9ca0f3d5058d 100644 +index a81fc5212648056766824113b372a7c772c19e5a..f0c3255e0b4e1ecf4a54213c6458c92a7389b134 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -18,6 +18,8 @@ import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.sounds.SoundEvent; -+import net.minecraft.sounds.SoundSource; - import net.minecraft.util.Unit; - import net.minecraft.world.Container; - import net.minecraft.world.InteractionHand; -@@ -793,9 +795,16 @@ public class CraftEventFactory { +@@ -770,9 +770,16 @@ public class CraftEventFactory { public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, List drops) { CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward()); @@ -408,7 +326,7 @@ index 1877267344df1ff5b4de6a4e0c239f488cd52c1f..e696d2e52532df25d74a1f559e2c9ca0 victim.expToDrop = event.getDroppedExp(); for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { -@@ -811,8 +820,15 @@ public class CraftEventFactory { +@@ -788,8 +795,15 @@ public class CraftEventFactory { CraftPlayer entity = victim.getBukkitEntity(); PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure event.setKeepInventory(keepInventory); @@ -424,7 +342,7 @@ index 1877267344df1ff5b4de6a4e0c239f488cd52c1f..e696d2e52532df25d74a1f559e2c9ca0 victim.keepLevel = event.getKeepLevel(); victim.newLevel = event.getNewLevel(); -@@ -829,6 +845,31 @@ public class CraftEventFactory { +@@ -806,6 +820,31 @@ public class CraftEventFactory { return event; } @@ -433,11 +351,11 @@ index 1877267344df1ff5b4de6a4e0c239f488cd52c1f..e696d2e52532df25d74a1f559e2c9ca0 + private static void populateFields(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) { + event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue()); + event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent()); -+ SoundEvent soundEffect = victim.getDeathSoundEffect(); ++ net.minecraft.sounds.SoundEvent soundEffect = victim.getDeathSoundPublic(); + event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null); + event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundSource().name())); -+ event.setDeathSoundVolume(victim.getDeathSoundVolume()); -+ event.setDeathSoundPitch(victim.getSoundPitch()); ++ event.setDeathSoundVolume(victim.getSoundVolumePublic()); ++ event.setDeathSoundPitch(victim.getVoicePitch()); + } + + // Play death sound manually @@ -447,8 +365,8 @@ index 1877267344df1ff5b4de6a4e0c239f488cd52c1f..e696d2e52532df25d74a1f559e2c9ca0 + double x = event.getEntity().getLocation().getX(); + double y = event.getEntity().getLocation().getY(); + double z = event.getEntity().getLocation().getZ(); -+ SoundEvent soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound()); -+ SoundSource soundCategory = SoundSource.valueOf(event.getDeathSoundCategory().name()); ++ net.minecraft.sounds.SoundEvent soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound()); ++ net.minecraft.sounds.SoundSource soundCategory = net.minecraft.sounds.SoundSource.valueOf(event.getDeathSoundCategory().name()); + victim.level.playSound(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch()); + } + } diff --git a/patches/server-remapped/0282-Allow-chests-to-be-placed-with-NBT-data.patch b/patches/server/0261-Allow-chests-to-be-placed-with-NBT-data.patch similarity index 81% rename from patches/server-remapped/0282-Allow-chests-to-be-placed-with-NBT-data.patch rename to patches/server/0261-Allow-chests-to-be-placed-with-NBT-data.patch index 59c2f88e09..83f45fc478 100644 --- a/patches/server-remapped/0282-Allow-chests-to-be-placed-with-NBT-data.patch +++ b/patches/server/0261-Allow-chests-to-be-placed-with-NBT-data.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow chests to be placed with NBT data diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 79a7c37f15840dbd97510874ac12437d2b854999..02bfa4fb8055e60a84e878ffbf18303c0ee25b1d 100644 +index 8b3cf3b882ea6c0d48df8b551f4b85b87b889c58..dd4deb08eb3ed15a156269a11d3d43abfd61fe5b 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -296,6 +296,7 @@ public final class ItemStack { +@@ -339,6 +339,7 @@ public final class ItemStack { enuminteractionresult = InteractionResult.FAIL; // cancel placement // PAIL: Remove this when MC-99075 fixed placeEvent.getPlayer().updateInventory(); @@ -17,10 +17,10 @@ index 79a7c37f15840dbd97510874ac12437d2b854999..02bfa4fb8055e60a84e878ffbf18303c for (BlockState blockstate : blocks) { blockstate.update(true, false); diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java -index 17289d28b6d0023279a573715ee3d182988dd651..ab11c7a5a397047a35245b149d77bf035e718a0c 100644 +index f2c9755c2b55bee2a0b981313e1fcd1f8ab5e3d8..52de9852f87d346714a950b60a0004d386ac10f0 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java -@@ -326,7 +326,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity { // Pape +@@ -239,7 +239,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement // CraftBukkit start @Override public boolean onlyOpCanSetNbt() { diff --git a/patches/server-remapped/0283-Mob-Pathfinding-API.patch b/patches/server/0262-Mob-Pathfinding-API.patch similarity index 85% rename from patches/server-remapped/0283-Mob-Pathfinding-API.patch rename to patches/server/0262-Mob-Pathfinding-API.patch index 8ae73987bc..5a0a31dccc 100644 --- a/patches/server-remapped/0283-Mob-Pathfinding-API.patch +++ b/patches/server/0262-Mob-Pathfinding-API.patch @@ -7,10 +7,10 @@ Implements Pathfinding API for mobs diff --git a/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java new file mode 100644 -index 0000000000000000000000000000000000000000..3e7971b7ca5be0442378c9e7482775e05918d0ac +index 0000000000000000000000000000000000000000..92d1bb8b9cdb9eb0c04574c0b6ba5acdca9fb377 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java -@@ -0,0 +1,141 @@ +@@ -0,0 +1,139 @@ +package com.destroystokyo.paper.entity; + +import org.apache.commons.lang.Validate; @@ -18,12 +18,10 @@ index 0000000000000000000000000000000000000000..3e7971b7ca5be0442378c9e7482775e0 +import org.bukkit.craftbukkit.entity.CraftLivingEntity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Mob; -+ +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.world.level.pathfinder.Node; +import net.minecraft.world.level.pathfinder.Path; -+import PathResult; +import java.util.ArrayList; +import java.util.List; + @@ -153,10 +151,10 @@ index 0000000000000000000000000000000000000000..3e7971b7ca5be0442378c9e7482775e0 + } +} diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index c3082f5dd64413a47421cb01538bec846bf21d2c..a362506f38e8d30543b6cd6d215db561290dac76 100644 +index 8212aab2884c2a894bc981850e483ce31814c708..69edca1ef95c37b11fe3f793e6a8f8a674bd7f6f 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -100,7 +100,7 @@ public abstract class PathNavigation { +@@ -93,7 +93,7 @@ public abstract class PathNavigation { } @Nullable @@ -165,24 +163,24 @@ index c3082f5dd64413a47421cb01538bec846bf21d2c..a362506f38e8d30543b6cd6d215db561 return this.createPath(new BlockPos(x, y, z), distance); } -@@ -125,7 +125,7 @@ public abstract class PathNavigation { +@@ -123,7 +123,7 @@ public abstract class PathNavigation { } @Nullable - public Path createPath(Entity entity, int distance) { + public final Path calculateDestination(Entity entity) { return createPath(entity, 0); } public Path createPath(Entity entity, int distance) { - return this.a(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper + return this.createPath(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper } -@@ -190,6 +190,7 @@ public abstract class PathNavigation { - return pathentity != null && this.moveTo(pathentity, speed); +@@ -195,6 +195,7 @@ public abstract class PathNavigation { + return path != null && this.moveTo(path, speed); } + public boolean setDestination(@Nullable Path pathentity, double speed) { return moveTo(pathentity, speed); } // Paper - OBFHELPER public boolean moveTo(@Nullable Path path, double speed) { if (path == null) { this.path = null; -@@ -217,7 +218,7 @@ public abstract class PathNavigation { +@@ -221,7 +222,7 @@ public abstract class PathNavigation { } } @@ -191,7 +189,7 @@ index c3082f5dd64413a47421cb01538bec846bf21d2c..a362506f38e8d30543b6cd6d215db561 public Path getPath() { return this.path; } -@@ -341,6 +342,7 @@ public abstract class PathNavigation { +@@ -335,6 +336,7 @@ public abstract class PathNavigation { return !this.isDone(); } @@ -200,13 +198,13 @@ index c3082f5dd64413a47421cb01538bec846bf21d2c..a362506f38e8d30543b6cd6d215db561 this.path = null; } diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Node.java b/src/main/java/net/minecraft/world/level/pathfinder/Node.java -index c1ac95d784935f5d3d827e2e390162f594991d2c..27b5d3d02d1f3aa048fefc3ef2222c8031e7661f 100644 +index d7a86444d0e76154319c409317fc5ac9c54403a8..328f050ae68e0b42690f05e5995fb2711b8cf46d 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/Node.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/Node.java -@@ -5,9 +5,9 @@ import net.minecraft.util.Mth; +@@ -6,9 +6,9 @@ import net.minecraft.util.Mth; + import net.minecraft.world.phys.Vec3; public class Node { - - public final int x; - public final int y; - public final int z; @@ -217,10 +215,10 @@ index c1ac95d784935f5d3d827e2e390162f594991d2c..27b5d3d02d1f3aa048fefc3ef2222c80 public int heapIdx = -1; public float g; diff --git a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java -index 0941bd177f65abfed3991267448df7df259d7f04..ddc9a9ececf44ce5524fd98a872e8a53cd7cc4f5 100644 +index 72ca8adb9fa65588c6b1e19be2dc27a36c0146a6..e5bfd9ade1a49e11afd4a49784a0874654945709 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java -@@ -16,9 +16,9 @@ public abstract class NodeEvaluator { +@@ -15,9 +15,9 @@ public abstract class NodeEvaluator { protected int entityWidth; protected int entityHeight; protected int entityDepth; @@ -231,20 +229,21 @@ index 0941bd177f65abfed3991267448df7df259d7f04..ddc9a9ececf44ce5524fd98a872e8a53 + protected boolean canOpenDoors; public boolean shouldOpenDoors() { return canOpenDoors; } public void setShouldOpenDoors(boolean b) { canOpenDoors = b; } // Paper - obfhelper + protected boolean canFloat; public boolean shouldFloat() { return canFloat; } public void setShouldFloat(boolean b) { canFloat = b; } // Paper - obfhelper - public NodeEvaluator() {} - + public void prepare(PathNavigationRegion cachedWorld, Mob entity) { + this.level = cachedWorld; diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Path.java b/src/main/java/net/minecraft/world/level/pathfinder/Path.java -index 7bc0787634e3c5a6f76181b166793fb7591767e4..fd5b369b59669b893aaaec17aef1a526fd23d8c0 100644 +index 6928c415e328dd7cff2e9ec553bc4faa1ff8facf..e95312e5b0f0200178cbe1a61b3629dfeac55b4a 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/Path.java -@@ -8,13 +8,14 @@ import net.minecraft.world.phys.Vec3; +@@ -12,14 +12,15 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.phys.Vec3; public class Path { - - private final List nodes; + private final List nodes; public List getPoints() { return nodes; } // Paper - OBFHELPER private Node[] openSet = new Node[0]; private Node[] closedSet = new Node[0]; + private Set targetNodes; - private int nextNodeIndex; + private int nextNodeIndex; public int getNextIndex() { return this.nextNodeIndex; } // Paper - OBFHELPER private final BlockPos target; @@ -254,26 +253,26 @@ index 7bc0787634e3c5a6f76181b166793fb7591767e4..fd5b369b59669b893aaaec17aef1a526 public Path(List nodes, BlockPos target, boolean reachesTarget) { this.nodes = nodes; -@@ -36,7 +37,7 @@ public class Path { +@@ -41,7 +42,7 @@ public class Path { } @Nullable - public Node getEndNode() { + public Node getFinalPoint() { return getEndNode(); } @Nullable public Node getEndNode() { // Paper - OBFHELPER - return !this.nodes.isEmpty() ? (Node) this.nodes.get(this.nodes.size() - 1) : null; + return !this.nodes.isEmpty() ? this.nodes.get(this.nodes.size() - 1) : null; } -@@ -84,7 +85,7 @@ public class Path { +@@ -88,7 +89,7 @@ public class Path { return this.getEntityPosAtNode(entity, this.nextNodeIndex); } - public BlockPos getNextNodePos() { + public BlockPos getNext() { return getNextNodePos(); } public BlockPos getNextNodePos() { // Paper - OBFHELPER - return ((Node) this.nodes.get(this.nextNodeIndex)).asBlockPos(); + return this.nodes.get(this.nextNodeIndex).asBlockPos(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index fd2c5a4e245647f51c1191991dc315b773ff73d4..b5fe55a77c8558cf2ea32689ff57911530df75f9 100644 +index 71872fdfafca82cf745eecee4bf984726d49f5a4..9c9fa83615cd06539ce5e4e3d4feaa69f65b7931 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java @@ -11,8 +11,11 @@ import org.bukkit.loot.LootTable; @@ -287,4 +286,4 @@ index fd2c5a4e245647f51c1191991dc315b773ff73d4..b5fe55a77c8558cf2ea32689ff579115 + @Override public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { return paperPathfinder; } // Paper @Override public void setTarget(LivingEntity target) { - net.minecraft.world.entity.Mob entity = getHandle(); + net.minecraft.world.entity.Mob entity = this.getHandle(); diff --git a/patches/server-remapped/0284-Prevent-chunk-loading-from-Fluid-Flowing.patch b/patches/server/0263-Prevent-chunk-loading-from-Fluid-Flowing.patch similarity index 88% rename from patches/server-remapped/0284-Prevent-chunk-loading-from-Fluid-Flowing.patch rename to patches/server/0263-Prevent-chunk-loading-from-Fluid-Flowing.patch index 9234ee7b61..0a3719ca71 100644 --- a/patches/server-remapped/0284-Prevent-chunk-loading-from-Fluid-Flowing.patch +++ b/patches/server/0263-Prevent-chunk-loading-from-Fluid-Flowing.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Prevent chunk loading from Fluid Flowing diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -index 967123992ee86f13f4ca6e336eaf8cebed086a1a..7544bf227b1dded0f854cc1b30d246d120f65b20 100644 +index 21e2ffc105b7b573b19c826a5877ed726156e692..6e3e873efa1f50f53cb6503bde8a981f9cefd006 100644 --- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java +++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -@@ -175,7 +175,8 @@ public abstract class FlowingFluid extends Fluid { +@@ -176,7 +176,8 @@ public abstract class FlowingFluid extends Fluid { Direction enumdirection = (Direction) entry.getKey(); FluidState fluid1 = (FluidState) entry.getValue(); BlockPos blockposition1 = pos.relative(enumdirection); @@ -18,7 +18,7 @@ index 967123992ee86f13f4ca6e336eaf8cebed086a1a..7544bf227b1dded0f854cc1b30d246d1 if (this.canSpreadTo(world, pos, blockState, enumdirection, blockposition1, iblockdata1, world.getFluidState(blockposition1), fluid1.getType())) { // CraftBukkit start -@@ -202,7 +203,8 @@ public abstract class FlowingFluid extends Fluid { +@@ -203,7 +204,8 @@ public abstract class FlowingFluid extends Fluid { while (iterator.hasNext()) { Direction enumdirection = (Direction) iterator.next(); BlockPos blockposition1 = pos.relative(enumdirection); @@ -28,10 +28,10 @@ index 967123992ee86f13f4ca6e336eaf8cebed086a1a..7544bf227b1dded0f854cc1b30d246d1 FluidState fluid = iblockdata1.getFluidState(); if (fluid.getType().isSame((Fluid) this) && this.canPassThroughWall(enumdirection, (BlockGetter) world, pos, state, blockposition1, iblockdata1)) { -@@ -319,11 +321,18 @@ public abstract class FlowingFluid extends Fluid { +@@ -320,11 +322,18 @@ public abstract class FlowingFluid extends Fluid { if (enumdirection1 != enumdirection) { BlockPos blockposition2 = blockposition.relative(enumdirection1); - short short0 = getCacheKey(blockposition1, blockposition2); + short short0 = FlowingFluid.getCacheKey(blockposition1, blockposition2); - Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (k) -> { - BlockState iblockdata1 = world.getBlockState(blockposition2); + // Paper start - avoid loading chunks @@ -51,10 +51,10 @@ index 967123992ee86f13f4ca6e336eaf8cebed086a1a..7544bf227b1dded0f854cc1b30d246d1 BlockState iblockdata1 = (BlockState) pair.getFirst(); FluidState fluid = (FluidState) pair.getSecond(); -@@ -395,11 +404,16 @@ public abstract class FlowingFluid extends Fluid { +@@ -396,11 +405,16 @@ public abstract class FlowingFluid extends Fluid { Direction enumdirection = (Direction) iterator.next(); BlockPos blockposition1 = pos.relative(enumdirection); - short short0 = getCacheKey(pos, blockposition1); + short short0 = FlowingFluid.getCacheKey(pos, blockposition1); - Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (j) -> { - BlockState iblockdata1 = world.getBlockState(blockposition1); - diff --git a/patches/server-remapped/0285-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/patches/server/0264-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch similarity index 79% rename from patches/server-remapped/0285-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch rename to patches/server/0264-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch index 30b7b72f6c..27cd5aa1c7 100644 --- a/patches/server-remapped/0285-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch +++ b/patches/server/0264-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Implement an API for CanPlaceOn and CanDestroy NBT values diff --git a/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java b/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java -index 9175c74c2119e7052d744db77badcae6be05f3b4..52f8ad848a22ddca856f6f256276ea59416f9664 100644 +index 30c3b24af7efebecc21d190ab89817468bdbee22..147fc3f7648a519441eec7ef1048fd18ea595d98 100644 --- a/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java +++ b/src/main/java/net/minecraft/commands/arguments/blocks/BlockStateParser.java -@@ -57,7 +57,7 @@ public class BlockStateParser { +@@ -63,7 +63,7 @@ public class BlockStateParser { private final boolean forTesting; private final Map, Comparable> properties = Maps.newLinkedHashMap(); // CraftBukkit - stable private final Map vagueProperties = Maps.newHashMap(); @@ -17,40 +17,11 @@ index 9175c74c2119e7052d744db77badcae6be05f3b4..52f8ad848a22ddca856f6f256276ea59 private StateDefinition definition; private BlockState state; @Nullable -@@ -86,11 +86,13 @@ public class BlockStateParser { - return this.nbt; - } - -+ public final @Nullable ResourceLocation getTagKey() { return getTag(); } // Paper - OBFHELPER - @Nullable - public ResourceLocation getTag() { - return this.tag; - } - -+ public final BlockStateParser parse(boolean parseTile) throws CommandSyntaxException { return this.parse(parseTile); } // Paper - OBFHELPER - public BlockStateParser parse(boolean allowNbt) throws CommandSyntaxException { - this.suggestions = this::suggestBlockIdOrTag; - if (this.reader.canRead() && this.reader.peek() == '#') { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba918f044e51 100644 +index 4ad6fd7e110f949f0bd859331ed6a5109ade3008..6252c3934d72b0d5e6809842bdd26d344cab98c6 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -39,12 +39,14 @@ import java.util.logging.Level; - import java.util.logging.Logger; - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -+import net.minecraft.commands.arguments.blocks.BlockStateParser; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.nbt.NbtIo; - import net.minecraft.nbt.StringTag; - import net.minecraft.nbt.Tag; - import net.minecraft.network.chat.TextComponent; -+import net.minecraft.resources.ResourceLocation; - import net.minecraft.world.item.BlockItem; - import org.apache.commons.codec.binary.Base64; - import org.apache.commons.lang.Validate; -@@ -83,6 +85,12 @@ import org.bukkit.persistence.PersistentDataContainer; +@@ -83,6 +83,12 @@ import org.bukkit.persistence.PersistentDataContainer; import static org.spigotmc.ValidateUtils.*; // Spigot end @@ -63,7 +34,7 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 /** * Children must include the following: * -@@ -266,6 +274,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -267,6 +273,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { @Specific(Specific.To.NBT) static final ItemMetaKey BLOCK_DATA = new ItemMetaKey("BlockStateTag"); static final ItemMetaKey BUKKIT_CUSTOM_TAG = new ItemMetaKey("PublicBukkitValues"); @@ -74,7 +45,7 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 // We store the raw original JSON representation of all text data. See SPIGOT-5063, SPIGOT-5656, SPIGOT-5304 private String displayName; -@@ -279,6 +291,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -280,6 +290,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { private int hideFlag; private boolean unbreakable; private int damage; @@ -85,7 +56,7 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 private static final Set HANDLED_TAGS = Sets.newHashSet(); private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); -@@ -316,6 +332,15 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -317,6 +331,15 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { this.hideFlag = meta.hideFlag; this.unbreakable = meta.unbreakable; this.damage = meta.damage; @@ -101,8 +72,8 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 this.unhandledTags.putAll(meta.unhandledTags); this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw()); -@@ -379,6 +404,31 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - persistentDataContainer.put(key, compound.get(key)); +@@ -380,6 +403,31 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + this.persistentDataContainer.put(key, compound.get(key)); } } + // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values @@ -133,8 +104,8 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 Set keys = tag.getAllKeys(); for (String key : keys) { -@@ -517,6 +567,34 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - setDamage(damage); +@@ -518,6 +566,34 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + this.setDamage(damage); } + // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values @@ -168,8 +139,8 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 String internal = SerializableMeta.getString(map, "internal", true); if (internal != null) { ByteArrayInputStream buf = new ByteArrayInputStream(Base64.decodeBase64(internal)); -@@ -645,6 +723,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - if (hasDamage()) { +@@ -646,6 +722,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + if (this.hasDamage()) { itemTag.putInt(DAMAGE.NBT, damage); } + // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values @@ -190,9 +161,9 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 + } + // Paper end - for (Map.Entry e : unhandledTags.entrySet()) { + for (Map.Entry e : this.unhandledTags.entrySet()) { itemTag.put(e.getKey(), e.getValue()); -@@ -661,6 +756,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -662,6 +755,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { } } @@ -214,16 +185,16 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 ListTag createStringList(List list) { if (list == null) { return null; -@@ -744,7 +854,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -745,7 +853,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { @Overridden boolean isEmpty() { -- return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); -+ return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers() || hasPlaceableKeys() || hasDestroyableKeys()); // Paper - Implement an API for CanPlaceOn and CanDestroy NBT values +- return !(this.hasDisplayName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isUnbreakable() || this.hasDamage() || this.hasAttributeModifiers()); ++ return !(this.hasDisplayName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isUnbreakable() || this.hasDamage() || this.hasAttributeModifiers() || this.hasPlaceableKeys() || this.hasDestroyableKeys()); // Paper - Implement an API for CanPlaceOn and CanDestroy NBT values } // Paper start -@@ -1168,7 +1278,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -1169,7 +1277,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { && (this.hideFlag == that.hideFlag) && (this.isUnbreakable() == that.isUnbreakable()) && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) @@ -236,18 +207,18 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 } /** -@@ -1203,6 +1317,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - hash = 61 * hash + (hasDamage() ? this.damage : 0); - hash = 61 * hash + (hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); - hash = 61 * hash + version; +@@ -1204,6 +1316,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + hash = 61 * hash + (this.hasDamage() ? this.damage : 0); + hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); + hash = 61 * hash + this.version; + // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ hash = 61 * hash + (hasPlaceableKeys() ? this.placeableKeys.hashCode() : 0); -+ hash = 61 * hash + (hasDestroyableKeys() ? this.destroyableKeys.hashCode() : 0); ++ hash = 61 * hash + (this.hasPlaceableKeys() ? this.placeableKeys.hashCode() : 0); ++ hash = 61 * hash + (this.hasDestroyableKeys() ? this.destroyableKeys.hashCode() : 0); + // Paper end return hash; } -@@ -1227,6 +1345,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -1228,6 +1344,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { clone.unbreakable = this.unbreakable; clone.damage = this.damage; clone.version = this.version; @@ -262,12 +233,12 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 return clone; } catch (CloneNotSupportedException e) { throw new Error(e); -@@ -1284,6 +1410,24 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -1285,6 +1409,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { builder.put(DAMAGE.BUKKIT, damage); } + // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (hasPlaceableKeys()) { ++ if (this.hasPlaceableKeys()) { + List cerealPlaceable = this.placeableKeys.stream() + .map(this::serializeNamespaced) + .collect(java.util.stream.Collectors.toList()); @@ -275,7 +246,7 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 + builder.put(CAN_PLACE_ON.BUKKIT, cerealPlaceable); + } + -+ if (hasDestroyableKeys()) { ++ if (this.hasDestroyableKeys()) { + List cerealDestroyable = this.destroyableKeys.stream() + .map(this::serializeNamespaced) + .collect(java.util.stream.Collectors.toList()); @@ -283,11 +254,10 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 + builder.put(CAN_DESTROY.BUKKIT, cerealDestroyable); + } + // Paper end -+ - final Map internalTags = new HashMap(unhandledTags); - serializeInternal(internalTags); + final Map internalTags = new HashMap(this.unhandledTags); + this.serializeInternal(internalTags); if (!internalTags.isEmpty()) { -@@ -1448,6 +1592,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -1449,6 +1590,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { CraftMetaArmorStand.SHOW_ARMS.NBT, CraftMetaArmorStand.SMALL.NBT, CraftMetaArmorStand.MARKER.NBT, @@ -296,7 +266,7 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 // Paper end CraftMetaCompass.LODESTONE_DIMENSION.NBT, CraftMetaCompass.LODESTONE_POS.NBT, -@@ -1475,4 +1621,147 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -1477,4 +1620,147 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { } // Paper end @@ -392,7 +362,7 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 + + private @Nullable Namespaced deserializeNamespaced(String raw) { + boolean isTag = raw.length() > 0 && raw.codePointAt(0) == '#'; -+ BlockStateParser blockParser = new BlockStateParser(new com.mojang.brigadier.StringReader(raw), true); ++ net.minecraft.commands.arguments.blocks.BlockStateParser blockParser = new net.minecraft.commands.arguments.blocks.BlockStateParser(new com.mojang.brigadier.StringReader(raw), true); + try { + blockParser = blockParser.parse(false); + } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) { @@ -400,9 +370,9 @@ index 64f166fa93e998a58a895d785ff8c9e62dacb1bb..45abfebf3f947dcbd2e7b1d95be8ba91 + return null; + } + -+ ResourceLocation key; ++ net.minecraft.resources.ResourceLocation key; + if (isTag) { -+ key = blockParser.getTagKey(); ++ key = blockParser.getTag(); + } else { + key = blockParser.getBlockKey(); + } diff --git a/patches/server/0265-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/patches/server/0265-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch new file mode 100644 index 0000000000..6165cd6338 --- /dev/null +++ b/patches/server/0265-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 10 Sep 2018 23:56:36 -0400 +Subject: [PATCH] Prevent Mob AI Rules from Loading Chunks + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +index b255eed15cfc7282167a9bed01653b34bb8d13f1..ac5779319081a6894373877067edf958da8a9cf5 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +@@ -133,7 +133,9 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + + @Nullable + private BlockPos getPosWithBlock(BlockPos pos, BlockGetter world) { +- if (world.getBlockState(pos).is(this.blockToRemove)) { ++ net.minecraft.world.level.block.state.BlockState block = world.getTypeIfLoaded(pos); // Paper ++ if (block == null) return null; // Paper ++ if (block.is(this.blockToRemove)) { // Paper + return pos; + } else { + BlockPos[] ablockposition = new BlockPos[]{pos.below(), pos.west(), pos.east(), pos.north(), pos.south(), pos.below().below()}; +@@ -143,7 +145,8 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + for (int j = 0; j < i; ++j) { + BlockPos blockposition1 = ablockposition1[j]; + +- if (world.getBlockState(blockposition1).is(this.blockToRemove)) { ++ net.minecraft.world.level.block.state.BlockState block2 = world.getTypeIfLoaded(blockposition1); // Paper ++ if (block2 != null && block2.is(this.blockToRemove)) { // Paper + return blockposition1; + } + } +@@ -154,7 +157,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + + @Override + protected boolean isValidTarget(LevelReader world, BlockPos pos) { +- ChunkAccess ichunkaccess = world.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false); ++ ChunkAccess ichunkaccess = world.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4); // Paper + + return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).is(this.blockToRemove) && ichunkaccess.getBlockState(pos.above()).isAir() && ichunkaccess.getBlockState(pos.above(2)).isAir(); + } diff --git a/patches/server-remapped/0287-Prevent-mob-spawning-from-loading-generating-chunks.patch b/patches/server/0266-Prevent-mob-spawning-from-loading-generating-chunks.patch similarity index 63% rename from patches/server-remapped/0287-Prevent-mob-spawning-from-loading-generating-chunks.patch rename to patches/server/0266-Prevent-mob-spawning-from-loading-generating-chunks.patch index 759560db06..169635a71f 100644 --- a/patches/server-remapped/0287-Prevent-mob-spawning-from-loading-generating-chunks.patch +++ b/patches/server/0266-Prevent-mob-spawning-from-loading-generating-chunks.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Prevent mob spawning from loading/generating chunks also prevents if out of world border bounds diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index b90a275a0dc2913809ce16659eed445501e486de..e23875ae07c23fed1161ea070e63bbc3a30168a0 100644 +index 9c079d32e81cabfa7b8b28e3e8d5741d8d951d79..30ba1e3cb75d994770b006b9dfd6669000a9c1a4 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -174,9 +174,9 @@ public final class NaturalSpawner { +@@ -188,9 +188,9 @@ public final class NaturalSpawner { StructureFeatureManager structuremanager = world.structureFeatureManager(); ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); int i = pos.getY(); @@ -21,12 +21,12 @@ index b90a275a0dc2913809ce16659eed445501e486de..e23875ae07c23fed1161ea070e63bbc3 BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); int j = 0; int k = 0; -@@ -205,7 +205,7 @@ public final class NaturalSpawner { +@@ -219,7 +219,7 @@ public final class NaturalSpawner { if (entityhuman != null) { double d2 = entityhuman.distanceToSqr(d0, (double) i, d1); -- if (isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2)) { -+ if (isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2) && world.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn +- if (NaturalSpawner.isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2)) { ++ if (world.isLoadedAndInBounds(blockposition_mutableblockposition) && NaturalSpawner.isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2)) { // Paper - don't load chunks for mob spawn if (biomesettingsmobs_c == null) { - biomesettingsmobs_c = getRandomSpawnMobAt(world, structuremanager, chunkgenerator, group, world.random, (BlockPos) blockposition_mutableblockposition); - if (biomesettingsmobs_c == null) { + Optional optional = NaturalSpawner.getRandomSpawnMobAt(world, structuremanager, chunkgenerator, group, world.random, (BlockPos) blockposition_mutableblockposition); + From cef692bcc643994c47cfb21549778fe5b326e8f5 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sat, 12 Jun 2021 21:25:07 -0700 Subject: [PATCH 064/226] wor --- .../0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch | 2 ++ 1 file changed, 2 insertions(+) rename patches/{server-remapped => removed/1.17}/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch (99%) diff --git a/patches/server-remapped/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/removed/1.17/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch similarity index 99% rename from patches/server-remapped/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch rename to patches/removed/1.17/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch index db7b1e6312..5fe08a22a2 100644 --- a/patches/server-remapped/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch +++ b/patches/removed/1.17/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch @@ -5,6 +5,8 @@ Subject: [PATCH] Optimize Biome Mob Lookups for Mob Spawning Uses an EnumMap as well as a Set paired List for O(1) contains calls. + +TODO 1.17: Does not look relevant now diff --git a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java index 58ee27a994b4cd845b8bb28e80cc2102c860f097..528f42c63a1186b8827bfe7cf6193e14da938cb3 100644 --- a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java From 52f28953be3eb1cf641b5a296703f0bca2ed252e Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 12 Jun 2021 22:09:48 -0700 Subject: [PATCH 065/226] patches --- ...urrency-Improvements-to-Permissions.patch} | 0 ...Add-ItemStackRecipeChoice-Draft-API.patch} | 0 ...t-furnace-cook-speed-multiplier-API.patch} | 0 ...nt-furnace-cook-speed-multiplier-API.patch | 102 ----------------- ...nt-furnace-cook-speed-multiplier-API.patch | 106 ++++++++++++++++++ 5 files changed, 106 insertions(+), 102 deletions(-) rename patches/{api-unmapped/0149-Performance-Concurrency-Improvements-to-Permissions.patch => api/0151-Performance-Concurrency-Improvements-to-Permissions.patch} (100%) rename patches/{api-unmapped/0150-Add-ItemStackRecipeChoice-Draft-API.patch => api/0152-Add-ItemStackRecipeChoice-Draft-API.patch} (100%) rename patches/{api-unmapped/0151-Implement-furnace-cook-speed-multiplier-API.patch => api/0153-Implement-furnace-cook-speed-multiplier-API.patch} (100%) delete mode 100644 patches/server-remapped/0289-Implement-furnace-cook-speed-multiplier-API.patch create mode 100644 patches/server/0267-Implement-furnace-cook-speed-multiplier-API.patch diff --git a/patches/api-unmapped/0149-Performance-Concurrency-Improvements-to-Permissions.patch b/patches/api/0151-Performance-Concurrency-Improvements-to-Permissions.patch similarity index 100% rename from patches/api-unmapped/0149-Performance-Concurrency-Improvements-to-Permissions.patch rename to patches/api/0151-Performance-Concurrency-Improvements-to-Permissions.patch diff --git a/patches/api-unmapped/0150-Add-ItemStackRecipeChoice-Draft-API.patch b/patches/api/0152-Add-ItemStackRecipeChoice-Draft-API.patch similarity index 100% rename from patches/api-unmapped/0150-Add-ItemStackRecipeChoice-Draft-API.patch rename to patches/api/0152-Add-ItemStackRecipeChoice-Draft-API.patch diff --git a/patches/api-unmapped/0151-Implement-furnace-cook-speed-multiplier-API.patch b/patches/api/0153-Implement-furnace-cook-speed-multiplier-API.patch similarity index 100% rename from patches/api-unmapped/0151-Implement-furnace-cook-speed-multiplier-API.patch rename to patches/api/0153-Implement-furnace-cook-speed-multiplier-API.patch diff --git a/patches/server-remapped/0289-Implement-furnace-cook-speed-multiplier-API.patch b/patches/server-remapped/0289-Implement-furnace-cook-speed-multiplier-API.patch deleted file mode 100644 index 4b104b38ec..0000000000 --- a/patches/server-remapped/0289-Implement-furnace-cook-speed-multiplier-API.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tassu -Date: Thu, 13 Sep 2018 08:45:21 +0300 -Subject: [PATCH] Implement furnace cook speed multiplier API - -Signed-off-by: Tassu - -Fixed an issue where a furnace's cook-speed multiplier rounds down -to the nearest Integer when updating its current cook time. - -Modified by: Eric Su - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 8c55c1d88ef2e20e82bcdae0b9b3d381e562051f..4126a36dbc7750108a883f0be14dcb0d2e6d7ae8 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -38,6 +38,7 @@ import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.phys.Vec3; - // CraftBukkit start -+import java.util.List; - import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.entity.CraftHumanEntity; - import org.bukkit.craftbukkit.inventory.CraftItemStack; -@@ -56,6 +57,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - protected NonNullList items; - public int litTime; - private int litDuration; -+ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API - public int cookingProgress; - public int cookingTotalTime; - protected final ContainerData dataAccess; -@@ -256,6 +258,11 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - this.recipesUsed.put(new ResourceLocation(s), nbttagcompound1.getInt(s)); - } - -+ // Paper start - cook speed API -+ if (tag.contains("Paper.CookSpeedMultiplier")) { -+ this.cookSpeedMultiplier = tag.getDouble("Paper.CookSpeedMultiplier"); -+ } -+ // Paper end - } - - @Override -@@ -264,6 +271,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - tag.putShort("BurnTime", (short) this.litTime); - tag.putShort("CookTime", (short) this.cookingProgress); - tag.putShort("CookTimeTotal", (short) this.cookingTotalTime); -+ tag.putDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API - ContainerHelper.saveAllItems(tag, this.items); - CompoundTag nbttagcompound1 = new CompoundTag(); - -@@ -324,7 +332,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - - if (this.isLit() && this.canBurn(irecipe)) { - ++this.cookingProgress; -- if (this.cookingProgress == this.cookingTotalTime) { -+ if (this.cookingProgress >= this.cookingTotalTime) { // Paper - cook speed multiplier API - this.cookingProgress = 0; - this.cookingTotalTime = this.getTotalCookTime(); - this.burn(irecipe); -@@ -424,9 +432,13 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - } - } - -- protected int getTotalCookTime() { -- return (this.hasLevel()) ? (Integer) this.level.getRecipeManager().getRecipeFor((RecipeType) this.recipeType, this, this.level).map(AbstractCookingRecipe::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail -+ // Paper begin - Expose this function so CraftFurnace can correctly scale the total cooking time to a new multiplier -+ public int getTotalCookTime() { -+ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */ -+ int cookTime = (this.hasLevel()) ? (Integer) this.level.getRecipeManager().getRecipeFor((RecipeType) this.recipeType, this, this.level).map(AbstractCookingRecipe::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail -+ return (int) Math.ceil (cookTime / this.cookSpeedMultiplier); - } -+ // Paper end - - public static boolean isFuel(ItemStack stack) { - return getFuel().containsKey(stack.getItem()); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -index 5028a6388f95a14df8d1590cddd7414d8de5bf78..a69785c331c6cee34ba4e93f47865ab8e29ec9b8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -@@ -63,4 +63,20 @@ public abstract class CraftFurnace extends - public void setCookTimeTotal(int cookTimeTotal) { - this.getSnapshot().cookingTotalTime = cookTimeTotal; - } -+ -+ // Paper start - cook speed multiplier API -+ @Override -+ public double getCookSpeedMultiplier() { -+ return this.getSnapshot().cookSpeedMultiplier; -+ } -+ -+ @Override -+ public void setCookSpeedMultiplier(double multiplier) { -+ com.google.common.base.Preconditions.checkArgument(multiplier >= 0, "Furnace speed multiplier cannot be negative"); -+ com.google.common.base.Preconditions.checkArgument(multiplier <= 200, "Furnace speed multiplier cannot more than 200"); -+ T snapshot = this.getSnapshot(); -+ snapshot.cookSpeedMultiplier = multiplier; -+ snapshot.cookingTotalTime = snapshot.getTotalCookTime(); // Update the snapshot's current total cook time to scale with the newly set multiplier -+ } -+ // Paper end - } diff --git a/patches/server/0267-Implement-furnace-cook-speed-multiplier-API.patch b/patches/server/0267-Implement-furnace-cook-speed-multiplier-API.patch new file mode 100644 index 0000000000..4462635aa6 --- /dev/null +++ b/patches/server/0267-Implement-furnace-cook-speed-multiplier-API.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tassu +Date: Thu, 13 Sep 2018 08:45:21 +0300 +Subject: [PATCH] Implement furnace cook speed multiplier API + +Signed-off-by: Tassu + +Fixed an issue where a furnace's cook-speed multiplier rounds down +to the nearest Integer when updating its current cook time. + +Modified by: Eric Su + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 52b2b27f8f8b542a930d649ed6904b4bf808906c..627551db52a0ac1aff9f65f9fce7b9e3c07ad475 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -70,6 +70,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + protected NonNullList items; + public int litTime; + int litDuration; ++ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API + public int cookingProgress; + public int cookingTotalTime; + protected final ContainerData dataAccess; +@@ -272,6 +273,11 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + this.recipesUsed.put(new ResourceLocation(s), nbttagcompound1.getInt(s)); + } + ++ // Paper start - cook speed API ++ if (nbt.contains("Paper.CookSpeedMultiplier")) { ++ this.cookSpeedMultiplier = nbt.getDouble("Paper.CookSpeedMultiplier"); ++ } ++ // Paper end + } + + @Override +@@ -280,6 +286,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + nbt.putShort("BurnTime", (short) this.litTime); + nbt.putShort("CookTime", (short) this.cookingProgress); + nbt.putShort("CookTimeTotal", (short) this.cookingTotalTime); ++ nbt.putDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API + ContainerHelper.saveAllItems(nbt, this.items); + CompoundTag nbttagcompound1 = new CompoundTag(); + +@@ -339,9 +346,9 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + + if (blockEntity.isLit() && AbstractFurnaceBlockEntity.canBurn(irecipe, blockEntity.items, i)) { + ++blockEntity.cookingProgress; +- if (blockEntity.cookingProgress == blockEntity.cookingTotalTime) { ++ if (blockEntity.cookingProgress >= blockEntity.cookingTotalTime) { // Paper - cook speed multiplier API + blockEntity.cookingProgress = 0; +- blockEntity.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity.recipeType, blockEntity); ++ blockEntity.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity.recipeType, blockEntity, blockEntity.cookSpeedMultiplier); + if (AbstractFurnaceBlockEntity.burn(blockEntity.level, blockEntity.worldPosition, irecipe, blockEntity.items, i)) { // CraftBukkit + blockEntity.setRecipeUsed(irecipe); + } +@@ -441,9 +448,13 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + } + } + +- private static int getTotalCookTime(Level world, RecipeType recipeType, Container inventory) { +- return (world != null) ? (Integer) world.getRecipeManager().getRecipeFor((RecipeType) recipeType, inventory, world).map(AbstractCookingRecipe::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail ++ // Paper begin - Expose this function so CraftFurnace can correctly scale the total cooking time to a new multiplier ++ public static int getTotalCookTime(Level world, RecipeType recipeType, Container inventory, final double cookSpeedMultiplier) { ++ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */ ++ int cookTime = world != null ? world.getRecipeManager().getRecipeFor((RecipeType) recipeType, inventory, world).map(AbstractCookingRecipe::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail ++ return (int) Math.ceil (cookTime / cookSpeedMultiplier); + } ++ // Paper end + + public static boolean isFuel(ItemStack stack) { + return AbstractFurnaceBlockEntity.getFuel().containsKey(stack.getItem()); +@@ -512,7 +523,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + } + + if (slot == 0 && !flag) { +- this.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.level, this.recipeType, this); ++ this.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.level, this.recipeType, this, this.cookSpeedMultiplier); + this.cookingProgress = 0; + this.setChanged(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java +index 5028a6388f95a14df8d1590cddd7414d8de5bf78..a05704665f7718b189f0c60ae42c615fce408b0c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java +@@ -63,4 +63,20 @@ public abstract class CraftFurnace extends + public void setCookTimeTotal(int cookTimeTotal) { + this.getSnapshot().cookingTotalTime = cookTimeTotal; + } ++ ++ // Paper start - cook speed multiplier API ++ @Override ++ public double getCookSpeedMultiplier() { ++ return this.getSnapshot().cookSpeedMultiplier; ++ } ++ ++ @Override ++ public void setCookSpeedMultiplier(double multiplier) { ++ com.google.common.base.Preconditions.checkArgument(multiplier >= 0, "Furnace speed multiplier cannot be negative"); ++ com.google.common.base.Preconditions.checkArgument(multiplier <= 200, "Furnace speed multiplier cannot more than 200"); ++ T snapshot = this.getSnapshot(); ++ snapshot.cookSpeedMultiplier = multiplier; ++ snapshot.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.world.getHandle(), snapshot.getCurrentRecipe().getType(), ((CraftInventoryFurnace) this.getInventory()).getInventory(), snapshot.cookSpeedMultiplier); // Update the snapshot's current total cook time to scale with the newly set multiplier ++ } ++ // Paper end + } From 0fa2a949ae2fc87c2704fd89fcc49d700cd0b390 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 12 Jun 2021 22:13:07 -0700 Subject: [PATCH 066/226] 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: 8503c3c9 #621: Add HumanEntity#getItemInUse and Material#getSlipperiness 248deb09 #622: Add methods to check if item is the breed item for an entity 2ce691d8 Clarify Player#breakBlock only works for blocks in the same world 5dcdd48e SPIGOT-6514: Small Dripleaf block data is missing half property cc9610b7 #619: Add Player#breakBlock() 862bc475 Fix bad merge of SPIGOT-6502 fix 989bb0c1 Downgrade SnakeYAML due to issues with comments parsing 1dff62ae Fix inverted visual fire docs CraftBukkit Changes: 40caacc8 SPIGOT-6526: World entities are not populated when plugin onEnable is called c9a92ad0 SPIGOT-6536: Marker position not set on spawn 20d3e57c #855: Add HumanEntity#getItemInUse and Material#getSlipperiness d9c69b44 SPIGOT-6529: Fix BundleMeta#setItems 8bd43be5 SPIGOT-6535: PlayerGameModeChangeEvent event incorrectly reports old gamemode 4ece3ff3 #856: Add methods to check if item is the breed item for an entity dd4bec5f Add additional validation to Player#breakBlock bc835ae6 SPIGOT-6532: Fix Entity#setGlowing 384e116e Restore 1.16.5 behaviour of InventoryDragEvent being called even when a single item is 'dragged' to its own slot b42e708c Fix new map colors rendering as transparent cfe7fecf SPIGOT-6524: Inventory desync when InventoryClickEvent is cancelled eeae1b19 SPIGOT-6522: ItemStack on cursor is always AIR 7490724d Fix missing PlayerEditBookEvent 06875f76 SPIGOT-6513: Placing ItemStack in Inventory causes InventoryAction.NOTHING 27835bde SPIGOT-6519: Fix end gateway teleports 4ac634ad SPIGOT-6515: "Un-waterlogging" throws UnsupportedOperationException in some cases da425fa2 SPIGOT-6518: Anvils falling onto dripstone can sometimes crash server 50530da9 SPIGOT-6514: Small Dripleaf block data is missing half property 6fdecf20 #853: Implement Player#breakBlock() 4db9c49f SPIGOT-6510: Bukkit#createMap throws NullPointerException 89e2b127 SPIGOT-6517: Spider jockey crash on dripstone cbf2f678 SPIGOT-6508: Rename conflicted getServer 74575d48 SPIGOT-6506: Fix crash with custom inventories a3df386f Fix NPE with Entity.getNearbyEntities d747f8ed Fix NPE with World.getNearbyEntities 4d2c7800 Fix second usage of worldGenSettings just in case 5182f923 SPIGOT-6504: Fix generating fresh worlds Spigot Changes: 66f9d3c1 Rebuild patches 191e4971 Rebuild patches a09c0bb6 Restore Spigot experience merging --- patches/api/0005-Timings-v2.patch | 6 +- patches/api/0006-Adventure.patch | 44 +++++++------- .../0007-Player-affects-spawning-API.patch | 4 +- .../0012-Add-player-view-distance-API.patch | 4 +- ...cord-chat-API-from-spigot-subclasses.patch | 4 +- .../0019-Player-Tab-List-and-Title-APIs.patch | 4 +- .../api/0023-Complete-resource-pack-API.patch | 6 +- ...0043-Add-String-based-Action-Bar-API.patch | 10 ++-- ...upstream-javadoc-warnings-and-errors.patch | 4 +- .../0058-Shoulder-Entities-Release-API.patch | 4 +- ...or-plugins-modifying-the-parent-of-t.patch | 4 +- ...nt-protocol-version-and-virtual-host.patch | 4 +- ...8-Ability-to-apply-mending-to-XP-API.patch | 4 +- .../0089-Player.setPlayerProfile-API.patch | 4 +- ...d-method-to-open-already-placed-sign.patch | 4 +- ...93-Add-Ban-Methods-to-Player-Objects.patch | 4 +- ...e-attack-cooldown-methods-for-Player.patch | 4 +- patches/server/0002-Decompile-fixes.patch | 4 +- patches/server/0004-Paper-config-files.patch | 4 +- patches/server/0005-MC-Dev-fixes.patch | 6 +- patches/server/0006-MC-Utils.patch | 18 +++--- patches/server/0009-Timings-v2.patch | 42 +++++++------- patches/server/0010-Adventure.patch | 58 +++++++++---------- ...ient-crashes-server-lists-and-Mojang.patch | 6 +- .../0021-Player-affects-spawning-API.patch | 6 +- ...023-Further-improve-server-tick-loop.patch | 12 ++-- ...024-Only-refresh-abilities-if-needed.patch | 4 +- patches/server/0025-Entity-Origin-API.patch | 8 +-- patches/server/0032-Optimize-explosions.patch | 4 +- ...layer-View-Distance-API-placeholders.patch | 6 +- ...44-Ensure-commands-are-not-ran-async.patch | 6 +- .../0046-Expose-server-CommandMap.patch | 4 +- .../0048-Player-Tab-List-and-Title-APIs.patch | 4 +- .../server/0051-Add-velocity-warnings.patch | 6 +- ...ble-inter-world-teleportation-safety.patch | 4 +- .../0057-Complete-resource-pack-API.patch | 10 ++-- ...llow-Reloading-of-Custom-Permissions.patch | 4 +- ...th-absorb-values-and-repair-bad-data.patch | 4 +- ...ckPhysicsEvent-if-a-plugin-has-a-lis.patch | 6 +- ...0076-Add-PlayerUseUnknownEntityEvent.patch | 4 +- ...nd-for-setting-passengers-on-players.patch | 4 +- .../0083-Configurable-Player-Collision.patch | 4 +- ...86-Implement-PlayerLocaleChangeEvent.patch | 10 ++-- ...-possibility-for-getServer-singleton.patch | 4 +- .../0094-Optimize-UserCache-Thread-Safe.patch | 4 +- ...setting-for-proxy-online-mode-status.patch | 4 +- ...onfigurable-packet-in-spam-threshold.patch | 4 +- patches/server/0108-Add-EntityZapEvent.patch | 4 +- ...1-Allow-Reloading-of-Command-Aliases.patch | 4 +- ...2-Add-source-to-PlayerExpChangeEvent.patch | 8 +-- .../0114-Add-ProjectileCollideEvent.patch | 4 +- .../0121-String-based-Action-Bar-API.patch | 4 +- ...22-Properly-fix-item-duplication-bug.patch | 6 +- ...rovide-E-TE-Chunk-count-stat-methods.patch | 4 +- ...PI-for-Reason-Source-Triggering-play.patch | 14 ++--- ...le-async-calls-to-restart-the-server.patch | 6 +- ...ke-parrots-stay-on-shoulders-despite.patch | 4 +- ...n-option-to-prevent-player-names-fro.patch | 4 +- ...oleAppender-for-console-improvements.patch | 12 ++-- .../server/0143-Basic-PlayerProfile-API.patch | 4 +- .../0144-Shoulder-Entities-Release-API.patch | 4 +- .../server/0147-Entity-fromMobSpawner.patch | 6 +- patches/server/0159-Add-PlayerJumpEvent.patch | 4 +- ...nt-protocol-version-and-virtual-host.patch | 4 +- .../server/0168-AsyncTabCompleteEvent.patch | 6 +- .../0169-PlayerPickupExperienceEvent.patch | 4 +- ...0-Ability-to-apply-mending-to-XP-API.patch | 8 +-- ...-Extend-Player-Interact-cancellation.patch | 6 +- ...nt-extended-PaperServerListPingEvent.patch | 4 +- .../0184-Player.setPlayerProfile-API.patch | 8 +-- .../server/0185-getPlayerUniqueId-API.patch | 4 +- ...89-Flag-to-disable-the-channel-limit.patch | 6 +- ...d-method-to-open-already-placed-sign.patch | 4 +- ...ld.spawnParticle-API-and-add-Builder.patch | 6 +- ...Item-entities-with-World.spawnEntity.patch | 4 +- .../0206-Fix-CraftEntity-hashCode.patch | 4 +- .../server/0213-Expand-Explosions-API.patch | 4 +- ...7-Implement-World.getEntity-UUID-API.patch | 4 +- .../0218-InventoryCloseEvent-Reason-API.patch | 20 +++---- ...nventory-when-cancelling-PlayerInter.patch | 4 +- ...1-Vanished-players-don-t-have-rights.patch | 4 +- ...6-Experience-should-save-as-Integers.patch | 6 +- ...dd-Early-Warning-Feature-to-WatchDog.patch | 6 +- ...loadChunk-int-int-false-load-unconve.patch | 4 +- ...57-Asynchronous-chunk-IO-and-loading.patch | 18 +++--- ...e-attack-cooldown-methods-for-Player.patch | 4 +- .../server/0260-Improve-death-events.patch | 14 ++--- work/Bukkit | 2 +- work/CraftBukkit | 2 +- work/Spigot | 2 +- 90 files changed, 318 insertions(+), 318 deletions(-) diff --git a/patches/api/0005-Timings-v2.patch b/patches/api/0005-Timings-v2.patch index 9d4a3c6e40..a79549bfa0 100644 --- a/patches/api/0005-Timings-v2.patch +++ b/patches/api/0005-Timings-v2.patch @@ -3377,10 +3377,10 @@ index 2a145d851ce30360aa39549745bd87590c034584..00000000000000000000000000000000 - // Spigot end -} diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index da1b5b5253c0ac0abe1019096166e6c76a50e699..586fd9ebd02039ebd2c071cbbbf60f24879f96b9 100644 +index 7d2e96fa96f5c4c5dbe97113a5e1b9cb59e09ac6..edf4623a831442e1f06daabc402a3f32610dd519 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1368,7 +1368,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1395,7 +1395,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM */ public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { throw new UnsupportedOperationException("Not supported yet."); @@ -3499,7 +3499,7 @@ index a09c3f71ca563b6f40a118ce1344d0eb273bed40..cf2f517765d8f2a23cc4a17d9ee2dcd8 eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); } else { diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index b0a347ab4be868ca92a1a0a8318da658e7194069..13100c688bfccb826b3072aaa92901f8634cf9ab 100644 +index 993a8c02af014a46cf03eaa4b67b09c0c16bd78a..e77c616977a3dcaa72bb22c35f6092c1f00b2b85 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java @@ -29,7 +29,8 @@ import org.jetbrains.annotations.Nullable; diff --git a/patches/api/0006-Adventure.patch b/patches/api/0006-Adventure.patch index 1037cf46f7..107340f64e 100644 --- a/patches/api/0006-Adventure.patch +++ b/patches/api/0006-Adventure.patch @@ -23,7 +23,7 @@ index 218e9c682e7b91dc27f2caf46316ba7a7982e5f3..50c3a01826f0ff939e3ee935d5a4e446 compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/pom.xml b/pom.xml -index 1ebc4c096638128194cea9c2a4131f901e7d6896..cae43ce5c1287a4cd117fd069d34ebc1b64b7fdb 100644 +index 7b44549b508862b207324a6003fcdfa623f40f07..f2238314b948be036d9e7054d7af5bfdac8ebbf6 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,7 @@ @@ -1667,7 +1667,7 @@ index 9566e4306ada5e82dede0f002aa06da12c44996b..4d5f0837bd0e02a30c943d8969fb6b13 + // Paper end } diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 0831f2519a32cf1c5c7d5b72864bcb1c22c52eda..03e12de470f983e89a473c4e42c21941085b1d37 100644 +index 25a6f9313a1953def7470e411b53016f2ca14bef..d7a4cfed4f46b34f83fb2c07bdab5a71215d26bb 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java @@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable; @@ -1693,10 +1693,10 @@ index 0831f2519a32cf1c5c7d5b72864bcb1c22c52eda..03e12de470f983e89a473c4e42c21941 + // Paper end } diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5a2f8469c 100644 +index edf4623a831442e1f06daabc402a3f32610dd519..d026c791ee86cb45feadcad7a48dea41287e3da7 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -30,7 +30,28 @@ import org.jetbrains.annotations.Nullable; +@@ -33,7 +33,28 @@ import org.jetbrains.annotations.Nullable; /** * Represents a player, connected or not */ @@ -1726,7 +1726,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 /** * Gets the "friendly" name to display of this player. This may include -@@ -40,7 +61,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -43,7 +64,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * places defined by plugins. * * @return the friendly name @@ -1736,7 +1736,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 @NotNull public String getDisplayName(); -@@ -52,15 +75,50 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -55,15 +78,50 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * places defined by plugins. * * @param name The new display name. @@ -1787,7 +1787,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 public String getPlayerListName(); /** -@@ -69,14 +127,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -72,14 +130,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * If the value is null, the name will be identical to {@link #getName()}. * * @param name new player list name @@ -1806,7 +1806,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 @Nullable public String getPlayerListHeader(); -@@ -84,7 +146,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -87,7 +149,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * Gets the currently displayed player list footer for this player. * * @return player list header or null @@ -1816,7 +1816,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 @Nullable public String getPlayerListFooter(); -@@ -92,14 +156,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -95,14 +159,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * Sets the currently displayed player list header for this player. * * @param header player list header, null for empty @@ -1835,7 +1835,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 public void setPlayerListFooter(@Nullable String footer); /** -@@ -108,7 +176,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -111,7 +179,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * * @param header player list header, null for empty * @param footer player list footer, null for empty @@ -1845,7 +1845,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 public void setPlayerListHeaderFooter(@Nullable String header, @Nullable String footer); /** -@@ -146,9 +216,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -149,9 +219,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * Kicks player with custom kick message. * * @param message kick message @@ -1866,7 +1866,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 /** * Says a message (or runs a command). * -@@ -448,6 +529,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -475,6 +556,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM @Deprecated public boolean sendChunkChange(@NotNull Location loc, int sx, int sy, int sz, @NotNull byte[] data); @@ -1874,7 +1874,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 /** * Send a sign change. This fakes a sign change packet for a user at * a certain location. This will not actually change the world in any way. -@@ -463,6 +545,43 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -490,6 +572,43 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * @throws IllegalArgumentException if location is null * @throws IllegalArgumentException if lines is non-null and has a length less than 4 */ @@ -1918,7 +1918,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 public void sendSignChange(@NotNull Location loc, @Nullable String[] lines) throws IllegalArgumentException; -@@ -482,7 +601,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -509,7 +628,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * @throws IllegalArgumentException if location is null * @throws IllegalArgumentException if dyeColor is null * @throws IllegalArgumentException if lines is non-null and has a length less than 4 @@ -1928,7 +1928,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 public void sendSignChange(@NotNull Location loc, @Nullable String[] lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException; /** -@@ -1220,6 +1341,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1247,6 +1368,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM */ public int getClientViewDistance(); @@ -1943,7 +1943,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 /** * Gets the player's estimated ping in milliseconds. * -@@ -1245,8 +1374,10 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1272,8 +1401,10 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * they wish. * * @return the player's locale @@ -1954,7 +1954,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 public String getLocale(); /** -@@ -1264,6 +1395,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1291,6 +1422,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM */ public void openBook(@NotNull ItemStack book); @@ -1969,7 +1969,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 // Spigot start public class Spigot extends Entity.Spigot { -@@ -1318,11 +1457,13 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1345,11 +1484,13 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM throw new UnsupportedOperationException("Not supported yet."); } @@ -1983,7 +1983,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 @Override public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { throw new UnsupportedOperationException("Not supported yet."); -@@ -1333,7 +1474,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1360,7 +1501,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * * @param position the screen position * @param component the components to send @@ -1993,7 +1993,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { throw new UnsupportedOperationException("Not supported yet."); } -@@ -1343,7 +1486,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1370,7 +1513,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * * @param position the screen position * @param components the components to send @@ -2003,7 +2003,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { throw new UnsupportedOperationException("Not supported yet."); } -@@ -1354,7 +1499,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1381,7 +1526,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * @param position the screen position * @param sender the sender of the message * @param component the components to send @@ -2013,7 +2013,7 @@ index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5 public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { throw new UnsupportedOperationException("Not supported yet."); } -@@ -1365,7 +1512,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1392,7 +1539,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * @param position the screen position * @param sender the sender of the message * @param components the components to send diff --git a/patches/api/0007-Player-affects-spawning-API.patch b/patches/api/0007-Player-affects-spawning-API.patch index f923a3d19b..6d27ffd3e8 100644 --- a/patches/api/0007-Player-affects-spawning-API.patch +++ b/patches/api/0007-Player-affects-spawning-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Player affects spawning API diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 171e2663301f654258dbd772a57688b5a2f8469c..76ac0b20842002ce1b593e338bea98483e7080ac 100644 +index d026c791ee86cb45feadcad7a48dea41287e3da7..58f3a5ada8f081b0a84d7e332f40d259df7e750b 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1380,6 +1380,22 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1407,6 +1407,22 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM @Deprecated // Paper public String getLocale(); diff --git a/patches/api/0012-Add-player-view-distance-API.patch b/patches/api/0012-Add-player-view-distance-API.patch index 8b5561ac14..51f138cb33 100644 --- a/patches/api/0012-Add-player-view-distance-API.patch +++ b/patches/api/0012-Add-player-view-distance-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add player view distance API diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 76ac0b20842002ce1b593e338bea98483e7080ac..f34601480a3b3069c30c52d258a35a2a79c981fb 100644 +index 58f3a5ada8f081b0a84d7e332f40d259df7e750b..11667e04df85c72205bec0b8c34ef4ec5998b404 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1394,6 +1394,28 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1421,6 +1421,28 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * @param affects Whether the player can affect mob spawning */ public void setAffectsSpawning(boolean affects); diff --git a/patches/api/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch b/patches/api/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch index 84e54e9f5e..979adae1a2 100644 --- a/patches/api/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch +++ b/patches/api/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch @@ -76,10 +76,10 @@ index 8fc591b16da774d60e85e3f13e44e9b5be671a3b..599347ef656acad9a40be15fc5030e5d * Gets the name of the update folder. The update folder is used to safely * update plugins at the right moment on a plugin load. diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index f34601480a3b3069c30c52d258a35a2a79c981fb..4686212255e8de3e5a6f43d86f28fad595f687ed 100644 +index 11667e04df85c72205bec0b8c34ef4ec5998b404..c5b41ebfd94a4969ce998b7ad539d11a1164168a 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -614,6 +614,42 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -641,6 +641,42 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM */ public void sendMap(@NotNull MapView map); diff --git a/patches/api/0019-Player-Tab-List-and-Title-APIs.patch b/patches/api/0019-Player-Tab-List-and-Title-APIs.patch index e808ed413d..201a65b955 100644 --- a/patches/api/0019-Player-Tab-List-and-Title-APIs.patch +++ b/patches/api/0019-Player-Tab-List-and-Title-APIs.patch @@ -432,7 +432,7 @@ index 0000000000000000000000000000000000000000..9e90c3df567a65b48a0b9341f784eb90 + } +} diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 4686212255e8de3e5a6f43d86f28fad595f687ed..769ad98fd7a6a866b320e1ccffd7962228d564cf 100644 +index c5b41ebfd94a4969ce998b7ad539d11a1164168a..9e4ef22c04b335d81baba2904c5571d17138092b 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -2,6 +2,7 @@ package org.bukkit.entity; @@ -443,7 +443,7 @@ index 4686212255e8de3e5a6f43d86f28fad595f687ed..769ad98fd7a6a866b320e1ccffd79622 import org.bukkit.DyeColor; import org.bukkit.Effect; import org.bukkit.GameMode; -@@ -648,6 +649,131 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -675,6 +676,131 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { spigot().sendMessage(position, components); } diff --git a/patches/api/0023-Complete-resource-pack-API.patch b/patches/api/0023-Complete-resource-pack-API.patch index ff78c17d14..71526451a2 100644 --- a/patches/api/0023-Complete-resource-pack-API.patch +++ b/patches/api/0023-Complete-resource-pack-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Complete resource pack API diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 769ad98fd7a6a866b320e1ccffd7962228d564cf..ddbe5734ac0f905b0c388e30f17a281530b82262 100644 +index 9e4ef22c04b335d81baba2904c5571d17138092b..e72e3adc5783a268e74c09c689be57db8b7df7e2 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1124,7 +1124,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1151,7 +1151,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * @throws IllegalArgumentException Thrown if the URL is null. * @throws IllegalArgumentException Thrown if the URL is too long. The * length restriction is an implementation specific arbitrary value. @@ -18,7 +18,7 @@ index 769ad98fd7a6a866b320e1ccffd7962228d564cf..ddbe5734ac0f905b0c388e30f17a2815 public void setResourcePack(@NotNull String url); /** -@@ -1601,6 +1603,60 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1628,6 +1630,60 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.displayName()))); } diff --git a/patches/api/0043-Add-String-based-Action-Bar-API.patch b/patches/api/0043-Add-String-based-Action-Bar-API.patch index ae3f76e08c..21d38f4153 100644 --- a/patches/api/0043-Add-String-based-Action-Bar-API.patch +++ b/patches/api/0043-Add-String-based-Action-Bar-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add String based Action Bar API diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index ddbe5734ac0f905b0c388e30f17a281530b82262..6bb0bb8052c12c5a215abf4bd9602fbefc769523 100644 +index e72e3adc5783a268e74c09c689be57db8b7df7e2..88cfc75a7b55dd09c4577d61ac40c3e241fc9e6c 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -3,6 +3,7 @@ package org.bukkit.entity; @@ -16,7 +16,7 @@ index ddbe5734ac0f905b0c388e30f17a281530b82262..6bb0bb8052c12c5a215abf4bd9602fbe import org.bukkit.DyeColor; import org.bukkit.Effect; import org.bukkit.GameMode; -@@ -616,6 +617,39 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -643,6 +644,39 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM public void sendMap(@NotNull MapView map); // Paper start @@ -56,7 +56,7 @@ index ddbe5734ac0f905b0c388e30f17a281530b82262..6bb0bb8052c12c5a215abf4bd9602fbe /** * Sends the component to the player * -@@ -643,9 +677,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -670,9 +704,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM /** * Sends an array of components as a single message to the specified screen position of this player * @@ -68,7 +68,7 @@ index ddbe5734ac0f905b0c388e30f17a281530b82262..6bb0bb8052c12c5a215abf4bd9602fbe public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { spigot().sendMessage(position, components); } -@@ -1728,6 +1764,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1755,6 +1791,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM /** * Sends the component to the specified screen position of this player * @@ -76,7 +76,7 @@ index ddbe5734ac0f905b0c388e30f17a281530b82262..6bb0bb8052c12c5a215abf4bd9602fbe * @param position the screen position * @param component the components to send * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} -@@ -1740,6 +1777,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1767,6 +1804,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM /** * Sends an array of components as a single message to the specified screen position of this player * diff --git a/patches/api/0052-Fix-upstream-javadoc-warnings-and-errors.patch b/patches/api/0052-Fix-upstream-javadoc-warnings-and-errors.patch index ad9ec8b241..922cd6a288 100644 --- a/patches/api/0052-Fix-upstream-javadoc-warnings-and-errors.patch +++ b/patches/api/0052-Fix-upstream-javadoc-warnings-and-errors.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix upstream javadoc warnings and errors Upstream still refuses to use Java 8 with the API so they are likely unaware these are even issues. diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 6bb0bb8052c12c5a215abf4bd9602fbefc769523..22cfa703e4f543c26151b33fe9ee1ab445d1c4fe 100644 +index 88cfc75a7b55dd09c4577d61ac40c3e241fc9e6c..c4e166311234cbe1e91fa26e74eae1d9fc82f72f 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -634,7 +634,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -661,7 +661,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * * Use supplied alternative character to the section symbol to represent legacy color codes. * diff --git a/patches/api/0058-Shoulder-Entities-Release-API.patch b/patches/api/0058-Shoulder-Entities-Release-API.patch index 54cea09655..0cb4374499 100644 --- a/patches/api/0058-Shoulder-Entities-Release-API.patch +++ b/patches/api/0058-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 b64e1f5e5aa4ec9bdd5f6976bf9dfdb83398e305..8ba6a59066234b834aedb0fb414ee7391aa2ac18 100644 +index db4ba67618d29f72d695c66c27d771795565a1d0..f748e3d3836df4da76fa883a51b9582bc31a4f8c 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -300,6 +300,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder +@@ -310,6 +310,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder */ public int getExpToLevel(); diff --git a/patches/api/0070-Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/patches/api/0070-Add-workaround-for-plugins-modifying-the-parent-of-t.patch index 47b6099ab7..c4f874c6ed 100644 --- a/patches/api/0070-Add-workaround-for-plugins-modifying-the-parent-of-t.patch +++ b/patches/api/0070-Add-workaround-for-plugins-modifying-the-parent-of-t.patch @@ -87,7 +87,7 @@ index bb2e55e97bf887a28cac7d4f9a0a23960d22cf56..04fa3991f6ce4e9dad804f28fc6c9476 /** diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 13100c688bfccb826b3072aaa92901f8634cf9ab..b9766b9b47547c400ed075f1635bb1461cb5e860 100644 +index e77c616977a3dcaa72bb22c35f6092c1f00b2b85..550225f168160298f4b1bf6c361207a59cf23122 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java @@ -44,6 +44,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot @@ -107,7 +107,7 @@ index 13100c688bfccb826b3072aaa92901f8634cf9ab..b9766b9b47547c400ed075f1635bb146 try { Class jarClass; try { -@@ -222,6 +225,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot +@@ -224,6 +227,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot pluginState = new IllegalStateException("Initial initialization"); this.pluginInit = javaPlugin; diff --git a/patches/api/0074-Expose-client-protocol-version-and-virtual-host.patch b/patches/api/0074-Expose-client-protocol-version-and-virtual-host.patch index 755988a174..cb2d2ad985 100644 --- a/patches/api/0074-Expose-client-protocol-version-and-virtual-host.patch +++ b/patches/api/0074-Expose-client-protocol-version-and-virtual-host.patch @@ -57,10 +57,10 @@ index 0000000000000000000000000000000000000000..7b2af1bd72dfbcf4e962a982940fc49b + +} diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 22cfa703e4f543c26151b33fe9ee1ab445d1c4fe..a32c4bd276de797f518771460083050fcddc4c5b 100644 +index c4e166311234cbe1e91fa26e74eae1d9fc82f72f..fe0238c0b7c001b69ba6f5f50faf535df59a2351 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable; +@@ -35,7 +35,7 @@ import org.jetbrains.annotations.Nullable; /** * Represents a player, connected or not */ diff --git a/patches/api/0078-Ability-to-apply-mending-to-XP-API.patch b/patches/api/0078-Ability-to-apply-mending-to-XP-API.patch index 977d682512..61434cd97c 100644 --- a/patches/api/0078-Ability-to-apply-mending-to-XP-API.patch +++ b/patches/api/0078-Ability-to-apply-mending-to-XP-API.patch @@ -10,10 +10,10 @@ of giving the player experience points. Both an API To standalone mend, and apply mending logic to .giveExp has been added. diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index a32c4bd276de797f518771460083050fcddc4c5b..9a262d412b2762a33a60b1e8762a7d9c9c3f933d 100644 +index fe0238c0b7c001b69ba6f5f50faf535df59a2351..4fa6080c151c3c2c0a7d95a2dc95692bd8bbee57 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -892,12 +892,33 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -919,12 +919,33 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM */ public void resetPlayerWeather(); diff --git a/patches/api/0089-Player.setPlayerProfile-API.patch b/patches/api/0089-Player.setPlayerProfile-API.patch index 5a914436ae..a4de465dce 100644 --- a/patches/api/0089-Player.setPlayerProfile-API.patch +++ b/patches/api/0089-Player.setPlayerProfile-API.patch @@ -6,7 +6,7 @@ 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/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 9a262d412b2762a33a60b1e8762a7d9c9c3f933d..3ae4d670059f80bd057870a37f4025261e397dfa 100644 +index 4fa6080c151c3c2c0a7d95a2dc95692bd8bbee57..ea4bad15720ce0a31d09999efa6df3988a67be20 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -4,6 +4,7 @@ import java.net.InetSocketAddress; @@ -17,7 +17,7 @@ index 9a262d412b2762a33a60b1e8762a7d9c9c3f933d..3ae4d670059f80bd057870a37f402526 import org.bukkit.DyeColor; import org.bukkit.Effect; import org.bukkit.GameMode; -@@ -1714,6 +1715,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1741,6 +1742,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * was {@link org.bukkit.event.player.PlayerResourcePackStatusEvent.Status#SUCCESSFULLY_LOADED} */ boolean hasResourcePack(); diff --git a/patches/api/0092-Add-method-to-open-already-placed-sign.patch b/patches/api/0092-Add-method-to-open-already-placed-sign.patch index c2a5530280..bd472de2f2 100644 --- a/patches/api/0092-Add-method-to-open-already-placed-sign.patch +++ b/patches/api/0092-Add-method-to-open-already-placed-sign.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add method to open already placed sign diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index 8ba6a59066234b834aedb0fb414ee7391aa2ac18..2e86d4c9ee85cf0f9096472b8c3d131522181215 100644 +index f748e3d3836df4da76fa883a51b9582bc31a4f8c..a46cefbb0508c192fdfefd685c7ad3973bb9c0c9 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -461,6 +461,14 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder +@@ -471,6 +471,14 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder */ @Deprecated public void setShoulderEntityRight(@Nullable Entity entity); diff --git a/patches/api/0093-Add-Ban-Methods-to-Player-Objects.patch b/patches/api/0093-Add-Ban-Methods-to-Player-Objects.patch index 772bc38bed..126f47aac8 100644 --- a/patches/api/0093-Add-Ban-Methods-to-Player-Objects.patch +++ b/patches/api/0093-Add-Ban-Methods-to-Player-Objects.patch @@ -74,7 +74,7 @@ index 58313929f81509030216a0e5e3869da63e11108e..6cf05fed701c67a2c797a4e0839c7958 /** * Checks if this player is whitelisted or not diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 3ae4d670059f80bd057870a37f4025261e397dfa..257bf4a75393d1e25839bcae0ca5551ee832c627 100644 +index ea4bad15720ce0a31d09999efa6df3988a67be20..b7bda78eab3a8146b2c361735a19b2a159af215e 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -5,6 +5,10 @@ import java.util.UUID; @@ -88,7 +88,7 @@ index 3ae4d670059f80bd057870a37f4025261e397dfa..257bf4a75393d1e25839bcae0ca5551e import org.bukkit.DyeColor; import org.bukkit.Effect; import org.bukkit.GameMode; -@@ -618,6 +622,162 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -645,6 +649,162 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM public void sendMap(@NotNull MapView map); // Paper start diff --git a/patches/api/0147-Expose-attack-cooldown-methods-for-Player.patch b/patches/api/0147-Expose-attack-cooldown-methods-for-Player.patch index e67693668d..8611f83c05 100644 --- a/patches/api/0147-Expose-attack-cooldown-methods-for-Player.patch +++ b/patches/api/0147-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/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 257bf4a75393d1e25839bcae0ca5551ee832c627..ec87c78d0f9379511467b6d13b9cdfa4c19d15ca 100644 +index b7bda78eab3a8146b2c361735a19b2a159af215e..685975e7bb8938ce0b2d80855c4c5549f50b262d 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1889,6 +1889,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1916,6 +1916,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * @param profile The new profile to use */ void setPlayerProfile(@NotNull PlayerProfile profile); diff --git a/patches/server/0002-Decompile-fixes.patch b/patches/server/0002-Decompile-fixes.patch index ce714be18b..deb8f3303f 100644 --- a/patches/server/0002-Decompile-fixes.patch +++ b/patches/server/0002-Decompile-fixes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Decompile fixes diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 3aecce56bdac0a316742a55e340c522bea737321..6b4d84faba50d9f3f87e48251cf1294479d4a3a0 100644 +index 0000a0057ec4ee2db72e4ea1bf421f95d9d9fdc6..729e55535d833f8f6ff65bf226aac5ecdec44990 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1138,7 +1138,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= 5000000000L) { -@@ -1213,14 +1234,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % this.autosavePeriod == 0) { // CraftBukkit @@ -874,7 +874,7 @@ index 2c13b8565b606a26b305fd44cfc0bd339df8f6be..6a6249ad58cc90782d526d89c899f30a } this.profiler.push("snooper"); -@@ -1233,6 +1252,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop chunkConsumer) { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index d7bf5d3bb3524410e49bd54372ddd7613ec0dd4b..c89c983e6f64718dabb2893996f7eb4a111c97c9 100644 +index b6eb04733611b63916453f36abf2ae615786845c..2db7c62d25791bc7856d007e9197f8c8041f8dfa 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1,6 +1,8 @@ @@ -1378,7 +1378,7 @@ index d7bf5d3bb3524410e49bd54372ddd7613ec0dd4b..c89c983e6f64718dabb2893996f7eb4a this.entityManager.saveAll(); } else { diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ef8e601412933c7065ce1968b45381b02b14275a..4ada0aaca513cbac51b93b298f4e2587de46f0d8 100644 +index 73f6e956afd2a679ffda2e7e21485e0b1791ecdf..47195235a0aafeb7c5af090777b323a2685bcd5f 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -209,6 +209,7 @@ import org.bukkit.inventory.EquipmentSlot; @@ -1405,7 +1405,7 @@ index ef8e601412933c7065ce1968b45381b02b14275a..4ada0aaca513cbac51b93b298f4e2587 } -@@ -1921,7 +1920,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -1922,7 +1921,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // CraftBukkit end private void handleCommand(String input) { @@ -1414,7 +1414,7 @@ index ef8e601412933c7065ce1968b45381b02b14275a..4ada0aaca513cbac51b93b298f4e2587 // CraftBukkit start - whole method if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + input); -@@ -1932,7 +1931,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -1933,7 +1932,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.cserver.getPluginManager().callEvent(event); if (event.isCancelled()) { @@ -1423,7 +1423,7 @@ index ef8e601412933c7065ce1968b45381b02b14275a..4ada0aaca513cbac51b93b298f4e2587 return; } -@@ -1945,7 +1944,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -1946,7 +1945,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); return; } finally { @@ -1457,7 +1457,7 @@ index 01f3267c086837cbbc311d62974ecb034e429c23..34e386efda7ea52fb6f53333eda0f015 public UserWhiteList getWhiteList() { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b494980b4a3303b2f19002d44f81a2707e6916a5..c8ebce55b4e3838bf70b115ffb0b634b3548a7dd 100644 +index 2ad8e9ada3ba68c107931793846b4e8284b1ab06..2bfafeec6f8a605a7826091314992e61a49e4c51 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -126,7 +126,6 @@ import org.bukkit.craftbukkit.event.CraftPortalEvent; @@ -1762,7 +1762,7 @@ index 198c1092e7db6e0023df77e4707c376696fdbafd..c27e755f93a2b2e203b305e0cae2c782 private String descriptionId; @Nullable diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index e4601134598e509a158ceacec6099a78bbabe89d..0e70d9df226e0843a943b3a57d1319ce1bca2543 100644 +index 92b042080f06fb95958ff5e824830a84f2d1f2a6..7b333e2d6884b272abefbc820bcce8026a4cdf7e 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java @@ -19,10 +19,12 @@ import org.bukkit.inventory.InventoryHolder; @@ -1838,10 +1838,10 @@ index 468b67babc628f7ff7c6fa138ed7944a8d77f0a6..22d5c4cc3aea19cbf53ea320765ecceb private static CompoundTag packStructureData(ServerLevel world, ChunkPos chunkcoordintpair, Map, StructureStart> map, Map, LongSet> map1) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 743c9f11dbbb66db97bcb3b8fecd97290a7c9f61..c85f69cc6ef8a61ca1b07beb5f2b2159fbaa887d 100644 +index 6345774687d4158d58be067e968c055f0c4a01bb..b1b44efbe0ad16619a32991f594b928a82d53278 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2076,12 +2076,31 @@ public final class CraftServer implements Server { +@@ -2078,12 +2078,31 @@ public final class CraftServer implements Server { private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() { @@ -2043,10 +2043,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 06d071d43337f2b919144a8db28684f4a3c826cf..457506210f041291be6bcdef7286d0860cb85946 100644 +index 5b58118308225010f16aa46676ef6b82886ffd31..969d5071dbf3356b80da38526351d488ab936c08 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1810,6 +1810,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1819,6 +1819,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { packet.components = components; CraftPlayer.this.getHandle().connection.send(packet); } diff --git a/patches/server/0010-Adventure.patch b/patches/server/0010-Adventure.patch index 1b8b859d8f..4f747860da 100644 --- a/patches/server/0010-Adventure.patch +++ b/patches/server/0010-Adventure.patch @@ -1140,7 +1140,7 @@ index 762a9392ffac3042356709dddd15bb3516048bed..3544e2dc2522e9d6305d727d56e73490 buf.writeComponent(this.footer); } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 52e536c3497a3145f8fdf47e2b6cb0b6295cd1b5..ae04883b57d44fdfb748f1aad0b7a2e24120ebeb 100644 +index 59e58647e0650997b523a683aa52cb922a1d9c51..ab62111ebafad77c3dc739185f907a19e9f911db 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -145,6 +145,7 @@ import net.minecraft.world.scores.Score; @@ -1195,7 +1195,7 @@ index 52e536c3497a3145f8fdf47e2b6cb0b6295cd1b5..ae04883b57d44fdfb748f1aad0b7a2e2 this.connection.send((Packet) (new ClientboundPlayerCombatKillPacket(this.getCombatTracker(), ichatbasecomponent)), (future) -> { if (!future.isSuccess()) { -@@ -1709,6 +1706,7 @@ public class ServerPlayer extends Player { +@@ -1702,6 +1699,7 @@ public class ServerPlayer extends Player { } public String locale = "en_us"; // CraftBukkit - add, lowercase @@ -1203,7 +1203,7 @@ index 52e536c3497a3145f8fdf47e2b6cb0b6295cd1b5..ae04883b57d44fdfb748f1aad0b7a2e2 public void updateOptions(ServerboundClientInformationPacket packet) { // CraftBukkit start if (getMainArm() != packet.getMainHand()) { -@@ -1720,6 +1718,10 @@ public class ServerPlayer extends Player { +@@ -1713,6 +1711,10 @@ public class ServerPlayer extends Player { this.server.server.getPluginManager().callEvent(event); } this.locale = packet.language; @@ -1215,7 +1215,7 @@ index 52e536c3497a3145f8fdf47e2b6cb0b6295cd1b5..ae04883b57d44fdfb748f1aad0b7a2e2 // CraftBukkit end this.chatVisibility = packet.getChatVisibility(); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 4ada0aaca513cbac51b93b298f4e2587de46f0d8..94ebbcb7731c01fcb93f053eea109f544132139a 100644 +index 47195235a0aafeb7c5af090777b323a2685bcd5f..c58f8cf20822439098648265917801509dda1a72 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -162,6 +162,8 @@ import org.apache.logging.log4j.LogManager; @@ -1270,7 +1270,7 @@ index 4ada0aaca513cbac51b93b298f4e2587de46f0d8..94ebbcb7731c01fcb93f053eea109f54 // CraftBukkit end this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> { -@@ -1671,9 +1675,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -1672,9 +1676,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser */ this.player.disconnect(); @@ -1285,7 +1285,7 @@ index 4ada0aaca513cbac51b93b298f4e2587de46f0d8..94ebbcb7731c01fcb93f053eea109f54 } // CraftBukkit end this.player.getTextFilter().leave(); -@@ -1855,7 +1861,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -1856,7 +1862,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.handleCommand(s); } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { // Do nothing, this is coming from a plugin @@ -1575,7 +1575,7 @@ index 7a0e7961df1e62b311ea2ecc76d7343a8646723b..6859fafa42527d45366018f737c19e6c } collection = icons; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c85f69cc6ef8a61ca1b07beb5f2b2159fbaa887d..ea8d5d95d9aa2d0036f82eca782cb5a633cbc388 100644 +index b1b44efbe0ad16619a32991f594b928a82d53278..d2e2e0cab3035a6a458fde75e9fcf72b2d1e77dd 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -564,8 +564,10 @@ public final class CraftServer implements Server { @@ -1589,7 +1589,7 @@ index c85f69cc6ef8a61ca1b07beb5f2b2159fbaa887d..ea8d5d95d9aa2d0036f82eca782cb5a6 } public Player getPlayer(final ServerPlayer entity) { -@@ -1309,7 +1311,15 @@ public final class CraftServer implements Server { +@@ -1310,7 +1312,15 @@ public final class CraftServer implements Server { return this.configuration.getInt("settings.spawn-radius", -1); } @@ -1605,7 +1605,7 @@ index c85f69cc6ef8a61ca1b07beb5f2b2159fbaa887d..ea8d5d95d9aa2d0036f82eca782cb5a6 public String getShutdownMessage() { return this.configuration.getString("settings.shutdown-message"); } -@@ -1425,7 +1435,20 @@ public final class CraftServer implements Server { +@@ -1427,7 +1437,20 @@ public final class CraftServer implements Server { } @Override @@ -1626,7 +1626,7 @@ index c85f69cc6ef8a61ca1b07beb5f2b2159fbaa887d..ea8d5d95d9aa2d0036f82eca782cb5a6 Set recipients = new HashSet<>(); for (Permissible permissible : this.getPluginManager().getPermissionSubscriptions(permission)) { if (permissible instanceof CommandSender && permissible.hasPermission(permission)) { -@@ -1433,14 +1456,14 @@ public final class CraftServer implements Server { +@@ -1435,14 +1458,14 @@ public final class CraftServer implements Server { } } @@ -1643,7 +1643,7 @@ index c85f69cc6ef8a61ca1b07beb5f2b2159fbaa887d..ea8d5d95d9aa2d0036f82eca782cb5a6 for (CommandSender recipient : recipients) { recipient.sendMessage(message); -@@ -1666,6 +1689,14 @@ public final class CraftServer implements Server { +@@ -1668,6 +1691,14 @@ public final class CraftServer implements Server { return CraftInventoryCreator.INSTANCE.createInventory(owner, type); } @@ -1658,7 +1658,7 @@ index c85f69cc6ef8a61ca1b07beb5f2b2159fbaa887d..ea8d5d95d9aa2d0036f82eca782cb5a6 @Override public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); -@@ -1678,13 +1709,28 @@ public final class CraftServer implements Server { +@@ -1680,13 +1711,28 @@ public final class CraftServer implements Server { return CraftInventoryCreator.INSTANCE.createInventory(owner, size); } @@ -1687,7 +1687,7 @@ index c85f69cc6ef8a61ca1b07beb5f2b2159fbaa887d..ea8d5d95d9aa2d0036f82eca782cb5a6 public Merchant createMerchant(String title) { return new CraftMerchantCustom(title == null ? InventoryType.MERCHANT.getDefaultTitle() : title); } -@@ -1728,6 +1774,12 @@ public final class CraftServer implements Server { +@@ -1730,6 +1776,12 @@ public final class CraftServer implements Server { return Thread.currentThread().equals(console.serverThread) || this.console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog) } @@ -1700,7 +1700,7 @@ index c85f69cc6ef8a61ca1b07beb5f2b2159fbaa887d..ea8d5d95d9aa2d0036f82eca782cb5a6 @Override public String getMotd() { return this.console.getMotd(); -@@ -2156,5 +2208,15 @@ public final class CraftServer implements Server { +@@ -2158,5 +2210,15 @@ public final class CraftServer implements Server { return null; } } @@ -1956,10 +1956,10 @@ index cf69a45f038c2b8336010f5fe277313fd0513b5b..a7966aa0846637efdc43df1ca97cbc5d public net.minecraft.world.item.enchantment.Enchantment getHandle() { return this.target; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index fdd3a7990cd63d44a154698449a472969ed9efdc..f4bcf48060bc704e0b6c690f78faaecfe90d8db3 100644 +index 98407b26cb94088fd931c445d4ed65eae5b7ecce..408e5a68986a91183d08ce06d385867b947ac04e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -806,6 +806,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -807,6 +807,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return this.getHandle().getVehicle().getBukkitEntity(); } @@ -1980,7 +1980,7 @@ index fdd3a7990cd63d44a154698449a472969ed9efdc..f4bcf48060bc704e0b6c690f78faaecf public void setCustomName(String name) { // sane limit for name length diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 450eea6e518de0493d4af4ad384d24217a3c7acf..d27a7ac64d1daf85319ab0069b9196f1958f6f46 100644 +index d4ea706d5456e709b95e34be8220a0d39be2c8f4..2db149bf57c561d7f8f49341fbefafb5d3ecab54 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -317,9 +317,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @@ -2014,10 +2014,10 @@ index 450eea6e518de0493d4af4ad384d24217a3c7acf..d27a7ac64d1daf85319ab0069b9196f1 player.initMenu(container); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 457506210f041291be6bcdef7286d0860cb85946..f4dff38b0f9e33be3495433559935765f77d662e 100644 +index 969d5071dbf3356b80da38526351d488ab936c08..f1f35eeff46f6573b79f1190265a908e5f8855eb 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -243,14 +243,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -244,14 +244,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public String getDisplayName() { @@ -2057,7 +2057,7 @@ index 457506210f041291be6bcdef7286d0860cb85946..f4dff38b0f9e33be3495433559935765 @Override public String getPlayerListName() { return this.getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(this.getHandle().listName); -@@ -269,42 +294,42 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -270,42 +295,42 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } } @@ -2109,7 +2109,7 @@ index 457506210f041291be6bcdef7286d0860cb85946..f4dff38b0f9e33be3495433559935765 this.getHandle().connection.send(packet); } -@@ -336,6 +361,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -337,6 +362,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.getHandle().connection.disconnect(message == null ? "" : message); } @@ -2127,7 +2127,7 @@ index 457506210f041291be6bcdef7286d0860cb85946..f4dff38b0f9e33be3495433559935765 @Override public void setCompassTarget(Location loc) { if (this.getHandle().connection == null) return; -@@ -562,6 +598,36 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -571,6 +607,36 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.getHandle().connection.send(packet); } @@ -2164,7 +2164,7 @@ index 457506210f041291be6bcdef7286d0860cb85946..f4dff38b0f9e33be3495433559935765 @Override public void sendSignChange(Location loc, String[] lines) { this.sendSignChange(loc, lines, DyeColor.BLACK); -@@ -584,13 +650,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -593,13 +659,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } Component[] components = CraftSign.sanitizeLines(lines); @@ -2183,7 +2183,7 @@ index 457506210f041291be6bcdef7286d0860cb85946..f4dff38b0f9e33be3495433559935765 } @Override -@@ -1690,6 +1755,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1699,6 +1764,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return (this.getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : this.getHandle().clientViewDistance; } @@ -2196,7 +2196,7 @@ index 457506210f041291be6bcdef7286d0860cb85946..f4dff38b0f9e33be3495433559935765 @Override public int getPing() { return this.getHandle().latency; -@@ -1718,6 +1789,138 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1727,6 +1798,138 @@ public class CraftPlayer extends CraftHumanEntity implements Player { getInventory().setItemInMainHand(hand); } @@ -2336,10 +2336,10 @@ index 457506210f041291be6bcdef7286d0860cb85946..f4dff38b0f9e33be3495433559935765 private final Player.Spigot spigot = new Player.Spigot() { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index cd54ba211070d34581068d6c1f3cceb858411415..fdb97878a6e73b729dbf09292d214e42c57d720a 100644 +index ad68b85f5aec00b5fc266a97880fc38c93073af3..e96ce62978e2cca454f797c4ce1ab1d306f9d7e4 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -770,9 +770,9 @@ public class CraftEventFactory { +@@ -787,9 +787,9 @@ public class CraftEventFactory { return event; } @@ -2351,7 +2351,7 @@ index cd54ba211070d34581068d6c1f3cceb858411415..fdb97878a6e73b729dbf09292d214e42 event.setKeepInventory(keepInventory); org.bukkit.World world = entity.getWorld(); Bukkit.getServer().getPluginManager().callEvent(event); -@@ -796,7 +796,7 @@ public class CraftEventFactory { +@@ -813,7 +813,7 @@ public class CraftEventFactory { * Server methods */ public static ServerListPingEvent callServerListPingEvent(Server craftServer, InetAddress address, String motd, int numPlayers, int maxPlayers) { @@ -2361,7 +2361,7 @@ index cd54ba211070d34581068d6c1f3cceb858411415..fdb97878a6e73b729dbf09292d214e42 return event; } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -index 25826a4f019a3084517f84cd3e5a7810c7958f0e..dfca1161da8009e508c5c5ef788422441145cfdf 100644 +index ceada296118643c79dfb94f08288ddbeca50c9dd..99d52dc4a3619200e8eb864e8ed8f4a6e469b443 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java @@ -69,6 +69,13 @@ public class CraftContainer extends AbstractContainerMenu { diff --git a/patches/server/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/patches/server/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch index a6742d2967..b7fa971c0d 100644 --- a/patches/server/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch +++ b/patches/server/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch @@ -19,10 +19,10 @@ index 2c53a400611c78236c5a1c1270d27c02e94251bf..a1d5c0f8fe2adb2ee56f3217e089211e if (outputStream != null) { try { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 6a6249ad58cc90782d526d89c899f30a59b980b2..e8d732933ddd2b670ff0b9c8d9be84a332f06482 100644 +index 9f7b60c74ccc46b7677ccfe487367cd4793b8287..3a9d77a190ef96c06717ee00bcfba52b8f984c14 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1417,7 +1417,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= 0 && index < this.list.size()) { Tag tag = this.list.get(index); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index c89c983e6f64718dabb2893996f7eb4a111c97c9..d26e8803222276fb7bb1bedd9fd13a8861ce671c 100644 +index 2db7c62d25791bc7856d007e9197f8c8041f8dfa..461b376987d3bc7c786fe6d29c5a07a5129c3355 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1110,6 +1110,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl @@ -33,7 +33,7 @@ index c89c983e6f64718dabb2893996f7eb4a111c97c9..d26e8803222276fb7bb1bedd9fd13a88 } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 568ce924efcad6ab6b986f1a450eb56c80e89b02..84c2a14d7336d57d5db66d01c75e31a58860d96c 100644 +index a5e3f27a471bf2396db640685edfc93f77fe2c0c..864724d962d536c1a4402a8da1e0b378e9d7efd5 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -280,6 +280,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @@ -114,10 +114,10 @@ index 394164f50256ad9a167e15531a9202875abb6cb6..abc62c560816d945642d830a020deb28 @Nullable diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index f4bcf48060bc704e0b6c690f78faaecfe90d8db3..bac39ee51f36ad86d6a4978306b6612d9376adbf 100644 +index 408e5a68986a91183d08ce06d385867b947ac04e..e5549f33a472133a8ce8533b5b827560a550f7ae 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1096,4 +1096,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1097,4 +1097,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return this.spigot; } // Spigot end diff --git a/patches/server/0032-Optimize-explosions.patch b/patches/server/0032-Optimize-explosions.patch index d6ac9e859f..f70d7af74f 100644 --- a/patches/server/0032-Optimize-explosions.patch +++ b/patches/server/0032-Optimize-explosions.patch @@ -25,10 +25,10 @@ index e6e18f309dc09ea9416ea37dcc697ddc2b571a96..4881b03d470646843bad1bc343eb6a6a + } } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 400aac6a37c63f34bf0038780e2137d82bc3416d..c6a59fa4b30d54baa638c931f045b2d546da021a 100644 +index ca439ac2a09a2ce4e019282c0b75f2f5d41a2208..3b4e679cc3c711635e6e2f3906a0afd2142c7849 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1396,6 +1396,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { return worldserver + " " + worldserver.dimension().location(); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 69b52097eede1a5c408aa7f34442e42255386436..9394dd781bb27b273c442972c5923615ac406507 100644 +index 07c9a4438a940e85625e715ceb4e01821dc9cc4b..f97df3dcc1dac794591dceea0fe41bcd0843e2ce 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -201,6 +201,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0076-Add-PlayerUseUnknownEntityEvent.patch b/patches/server/0076-Add-PlayerUseUnknownEntityEvent.patch index cb09c9b1c8..88703e3fdd 100644 --- a/patches/server/0076-Add-PlayerUseUnknownEntityEvent.patch +++ b/patches/server/0076-Add-PlayerUseUnknownEntityEvent.patch @@ -29,10 +29,10 @@ index 1b316ecf2d8725b9c91a4869e6c2362c1443160d..70d309ddb215c62805b6ee13be50d8f9 ATTACK((friendlyByteBuf) -> { return ServerboundInteractPacket.ATTACK_ACTION; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 714fb0d766b654ad05134dea9b1e1b628a939993..6cd0fd57503723a58b30a7c33b1c863afc2401e2 100644 +index dfab012166354af6233ee1fdab1b0fba6fcbe940..fa6d414387950d522243370714d5425f09e351e8 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2202,8 +2202,37 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -2203,8 +2203,37 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser }); } } diff --git a/patches/server/0082-Workaround-for-setting-passengers-on-players.patch b/patches/server/0082-Workaround-for-setting-passengers-on-players.patch index 1a1869f691..0892d11ff7 100644 --- a/patches/server/0082-Workaround-for-setting-passengers-on-players.patch +++ b/patches/server/0082-Workaround-for-setting-passengers-on-players.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Workaround for setting passengers on players SPIGOT-1915 & GH-114 diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 836692160077935c45b25f7002079111ebb91a6e..2605f2b34206f8eaffcb0e5ae0b928261ab366d2 100644 +index af9e79e1995ed8c1d5160a7b8ba7eec993e82263..d20b4d4cb52e37356b553e5197d650472e03e5b2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -883,6 +883,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -892,6 +892,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return true; } diff --git a/patches/server/0083-Configurable-Player-Collision.patch b/patches/server/0083-Configurable-Player-Collision.patch index 655a296152..b89f00d481 100644 --- a/patches/server/0083-Configurable-Player-Collision.patch +++ b/patches/server/0083-Configurable-Player-Collision.patch @@ -32,7 +32,7 @@ index 8885220e4813b34627b42523834bbec995d8950d..4c9660176e783999301565790b8cf6f4 buf.writeComponent(this.playerPrefix); buf.writeComponent(this.playerSuffix); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 591f7452005cbfb567b611b3ba71c16596f9edfa..f1868ef9111f25a1d4232587c0c5145c7cd50ef4 100644 +index 9e936078b388459bed7da3c6edfd0e65f3b1b1bf..15e26dbc38e23c5284246ef55d038eb011759ee2 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -163,6 +163,7 @@ import net.minecraft.world.level.storage.loot.LootTables; @@ -43,7 +43,7 @@ index 591f7452005cbfb567b611b3ba71c16596f9edfa..f1868ef9111f25a1d4232587c0c5145c import org.apache.commons.lang3.Validate; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -@@ -602,6 +603,20 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -@@ -2232,7 +2234,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { @@ -18,10 +18,10 @@ index 7df6946dcb2a7fbc625681dfbae1e15be625875b..1953739fd2ead7680273ef63d8506e54 --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 cb3f1f71cc5c5a18c0af818679b72583a7edec7c..c981bb0e1e7c4c8b7603e2ac8e483ad5b4a2c742 100644 +index 68a3cc357a7f2a837d434a4defc0eeb9a2dc7c31..f32a2a96da71c1cbcf0d153d882ff60ca66ffd2a 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1041,6 +1041,17 @@ public class CraftEventFactory { +@@ -1057,6 +1057,17 @@ public class CraftEventFactory { return event; } diff --git a/patches/server/0114-Add-ProjectileCollideEvent.patch b/patches/server/0114-Add-ProjectileCollideEvent.patch index 96765a5d30..67389db8d6 100644 --- a/patches/server/0114-Add-ProjectileCollideEvent.patch +++ b/patches/server/0114-Add-ProjectileCollideEvent.patch @@ -87,10 +87,10 @@ index f81be1c6a5efc5090fbb8832f44dbb2ae6aa2f4a..8e81b19706a14c21b5ffdc4f12818fe7 this.checkInsideBlocks(); diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index c981bb0e1e7c4c8b7603e2ac8e483ad5b4a2c742..56900b5810db623a49559ad218a5385c110bf479 100644 +index f32a2a96da71c1cbcf0d153d882ff60ca66ffd2a..1fce91a05a6b04a8d93d2707637c5b96c318a641 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1185,6 +1185,16 @@ public class CraftEventFactory { +@@ -1201,6 +1201,16 @@ public class CraftEventFactory { return CraftItemStack.asNMSCopy(bitem); } diff --git a/patches/server/0121-String-based-Action-Bar-API.patch b/patches/server/0121-String-based-Action-Bar-API.patch index 0ef38a7816..35057a0292 100644 --- a/patches/server/0121-String-based-Action-Bar-API.patch +++ b/patches/server/0121-String-based-Action-Bar-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] String based Action Bar API diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index d50ce7fc675fcc57f591e90eb0bbb99a4ab21b02..1da034d28732a5f5b9bd9b31966da21830efdc9f 100644 +index 3c8cc16ecf277390db3dbe112d0be6adf44e5b0c..4f21d578a65778ab9022b09bee3b84af341ddbdd 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -247,6 +247,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -248,6 +248,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } // Paper start diff --git a/patches/server/0122-Properly-fix-item-duplication-bug.patch b/patches/server/0122-Properly-fix-item-duplication-bug.patch index 8262c3fe06..220ce9ab61 100644 --- a/patches/server/0122-Properly-fix-item-duplication-bug.patch +++ b/patches/server/0122-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 c60d42c835ed9a1bcc938aa1647c5266b87a05c5..1c4f3a1cfe808d59333e45c170caf0d760a709c9 100644 +index 4ea1e8b1442c9dc9d282b8cb51c2e588fe4b19a7..ce77dc9e046be1e22d2a6d485d8f17a5fd11949e 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2124,7 +2124,7 @@ public class ServerPlayer extends Player { +@@ -2117,7 +2117,7 @@ public class ServerPlayer extends Player { @Override public boolean isImmobile() { @@ -19,7 +19,7 @@ index c60d42c835ed9a1bcc938aa1647c5266b87a05c5..1c4f3a1cfe808d59333e45c170caf0d7 @Override diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index b33ef48a4372dd8ac4a86bdd386a5a7d42583c72..624776a85a3e3268665571635f0b837cb810a62e 100644 +index 35aa8b40a26a5941d07421f96b424b975a32224e..55cd070c2dbf4cf4d8d0fc62067e9bde69ac7e84 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -2822,7 +2822,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch index b9b48eb821..84141dee36 100644 --- a/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch +++ b/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch @@ -20,10 +20,10 @@ index 52d80086deff664fcfd8952b7cabbfa1f48ad131..a86b5272c0ac4dd64f796f7fd025c7a3 private boolean tickingBlockEntities; public final Thread thread; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 5133febf4b3a83b2870fee2f9e45b1d12894df54..10b046ed843acac205608fa2fa3ffd4e4a277b5c 100644 +index 26f89f747eba69caaee3cbca71a1d48f2378b4cc..c9f11030ff928d3dca5cfbe48af057eb0480f898 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -270,6 +270,57 @@ public class CraftWorld implements World { +@@ -271,6 +271,57 @@ public class CraftWorld implements World { private int waterAmbientSpawn = -1; private int ambientSpawn = -1; diff --git a/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch index d3d79693ea..443029cb4a 100644 --- a/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch +++ b/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch @@ -8,10 +8,10 @@ Adds lots of information about why this orb exists. Replaces isFromBottle() with logic that persists entity reloads too. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index f0462770e5e56b28d734f5d097d95de8faee8bbf..9d303a962950c7464d1d4a2a0ce3f658628cc785 100644 +index f772924217c0531b09662a145d8ee5d22dd5ca51..ecfb88b4d9727ad20a2c33475cc6b1ec88821a19 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -406,7 +406,7 @@ public class ServerPlayerGameMode { +@@ -415,7 +415,7 @@ public class ServerPlayerGameMode { // Drop event experience if (flag && event != null) { @@ -21,7 +21,7 @@ index f0462770e5e56b28d734f5d097d95de8faee8bbf..9d303a962950c7464d1d4a2a0ce3f658 return true; diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index 1953739fd2ead7680273ef63d8506e546758dc9b..337e861a8b1a89b73560601b704c18dcf446a144 100644 +index 919fbe73f46238a1846c969bf64c309f3b9ad9d6..9662104a85faff2cdafd8cf001a8222182b56073 100644 --- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java @@ -38,13 +38,63 @@ public class ExperienceOrb extends Entity { @@ -112,7 +112,7 @@ index 1953739fd2ead7680273ef63d8506e546758dc9b..337e861a8b1a89b73560601b704c18dc } } -@@ -230,6 +288,7 @@ public class ExperienceOrb extends Entity { +@@ -227,6 +285,7 @@ public class ExperienceOrb extends Entity { nbt.putShort("Age", (short) this.age); nbt.putShort("Value", (short) this.value); nbt.putInt("Count", this.count); @@ -120,7 +120,7 @@ index 1953739fd2ead7680273ef63d8506e546758dc9b..337e861a8b1a89b73560601b704c18dc } @Override -@@ -238,6 +297,7 @@ public class ExperienceOrb extends Entity { +@@ -235,6 +294,7 @@ public class ExperienceOrb extends Entity { this.age = nbt.getShort("Age"); this.value = nbt.getShort("Value"); this.count = Math.max(nbt.getInt("Count"), 1); @@ -314,10 +314,10 @@ index 11ed01b3ebe4c71e3d3c767887a5dca6033fdf3c..52b2b27f8f8b542a930d649ed6904b4b @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index e11a1a21bff1fc5e730d6c63c5b0c623b3b2e037..e396450366ebee663dd5ad5f59e5d6bccece0679 100644 +index c9f11030ff928d3dca5cfbe48af057eb0480f898..9925d1f68c35a29156a152a8cc4b653ba280374b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1836,7 +1836,7 @@ public class CraftWorld implements World { +@@ -1837,7 +1837,7 @@ public class CraftWorld implements World { } else if (TNTPrimed.class.isAssignableFrom(clazz)) { entity = new PrimedTnt(this.world, x, y, z, null); } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { diff --git a/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch b/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch index 71da2cb2bf..d3bde1b9bc 100644 --- a/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch +++ b/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch @@ -30,7 +30,7 @@ will have plugins and worlds saving to the disk has a high potential to result in corruption/dataloss. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 74073d3f8c9dda6f10e9fb34071dae079b73fb24..1617c59bf689e5f67c2af5c3a22ce5791d47b408 100644 +index 3e2955013ce75034170b5eeae60482e1c174769d..220ead6455587a07375b6e86913865c6b590a87d 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -233,6 +233,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0.0D; if (this.player.isOnGround() && !packet.isOnGround() && flag) { diff --git a/patches/server/0161-Expose-client-protocol-version-and-virtual-host.patch b/patches/server/0161-Expose-client-protocol-version-and-virtual-host.patch index ca799c2b52..d9c30bace1 100644 --- a/patches/server/0161-Expose-client-protocol-version-and-virtual-host.patch +++ b/patches/server/0161-Expose-client-protocol-version-and-virtual-host.patch @@ -90,10 +90,10 @@ index c4ba069f5124ec151e05813beddf293fddc3b804..484221e5a9c246aa91e0eacef3911b0e @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 1da034d28732a5f5b9bd9b31966da21830efdc9f..ed1c57f22adc8b96012eca426ed1e7b409e7d663 100644 +index 4f21d578a65778ab9022b09bee3b84af341ddbdd..1af5e3f3389d5f4e391f05b3f8e7df9d3c799981 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -191,6 +191,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -192,6 +192,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } } diff --git a/patches/server/0168-AsyncTabCompleteEvent.patch b/patches/server/0168-AsyncTabCompleteEvent.patch index 22bff78e55..c0a87f996b 100644 --- a/patches/server/0168-AsyncTabCompleteEvent.patch +++ b/patches/server/0168-AsyncTabCompleteEvent.patch @@ -14,7 +14,7 @@ completion, such as offline players. Also adds isCommand and getLocation to the sync TabCompleteEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index b2bbd25e5572f59add71579b676d5a4c719be239..205e4ef25f49edc11a408c302d9ba68a59c68a5a 100644 +index 985736fc4e3d702a1fd787336db8ab18ee2a4783..5b426265d62063544f0104c8c9f8061d002bc56c 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -703,10 +703,10 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @@ -72,10 +72,10 @@ index b2bbd25e5572f59add71579b676d5a4c719be239..205e4ef25f49edc11a408c302d9ba68a @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0be8b1727ce57ec0905315922e1d83104a936cd0..cb09b6170a74984628f2c3dbacad2ddc9fe56faf 100644 +index 754e10be4f62ee3efac34bea3c72e23b1b06053c..8e93f6398a5974676a479e17f31a8e77c461fb41 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1849,7 +1849,7 @@ public final class CraftServer implements Server { +@@ -1851,7 +1851,7 @@ public final class CraftServer implements Server { offers = this.tabCompleteChat(player, message); } diff --git a/patches/server/0169-PlayerPickupExperienceEvent.patch b/patches/server/0169-PlayerPickupExperienceEvent.patch index f668dc331a..6787576f71 100644 --- a/patches/server/0169-PlayerPickupExperienceEvent.patch +++ b/patches/server/0169-PlayerPickupExperienceEvent.patch @@ -6,10 +6,10 @@ Subject: [PATCH] PlayerPickupExperienceEvent Allows plugins to cancel a player picking up an experience orb diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index 337e861a8b1a89b73560601b704c18dcf446a144..8203c93dcb56646df2614f2233aaf3a36f745d1c 100644 +index 9662104a85faff2cdafd8cf001a8222182b56073..4a6a588eeeee3aa7d33d4b4545e9b8bdf043e567 100644 --- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -303,7 +303,7 @@ public class ExperienceOrb extends Entity { +@@ -300,7 +300,7 @@ public class ExperienceOrb extends Entity { @Override public void playerTouch(Player player) { if (!this.level.isClientSide) { diff --git a/patches/server/0170-Ability-to-apply-mending-to-XP-API.patch b/patches/server/0170-Ability-to-apply-mending-to-XP-API.patch index 24489b2e5c..d0492a8afa 100644 --- a/patches/server/0170-Ability-to-apply-mending-to-XP-API.patch +++ b/patches/server/0170-Ability-to-apply-mending-to-XP-API.patch @@ -10,10 +10,10 @@ of giving the player experience points. Both an API To standalone mend, and apply mending logic to .giveExp has been added. diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index 8203c93dcb56646df2614f2233aaf3a36f745d1c..71fb831ed3359e7986e279c987211f39c581ab23 100644 +index 4a6a588eeeee3aa7d33d4b4545e9b8bdf043e567..30a3facc1b23ccb508b30c5affa9ea1c527dd48b 100644 --- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -344,10 +344,12 @@ public class ExperienceOrb extends Entity { +@@ -341,10 +341,12 @@ public class ExperienceOrb extends Entity { } } @@ -45,7 +45,7 @@ index 27cdfbeb6cb2159075b35dd4f9e9557ec0eac7c2..069ce59faab5184ab9da8ca3fe1cebf7 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 ed1c57f22adc8b96012eca426ed1e7b409e7d663..75963a28b39f8835f1daba3d1b44655603124bf3 100644 +index 1af5e3f3389d5f4e391f05b3f8e7df9d3c799981..7c6e1348cc26c38a844b7324a8372266579e048e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -61,11 +61,14 @@ import net.minecraft.server.level.ServerPlayer; @@ -63,7 +63,7 @@ index ed1c57f22adc8b96012eca426ed1e7b409e7d663..75963a28b39f8835f1daba3d1b446556 import net.minecraft.world.level.GameType; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.SignBlockEntity; -@@ -1189,8 +1192,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1198,8 +1201,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return GameMode.getByValue(this.getHandle().gameMode.getGameModeForPlayer().getId()); } diff --git a/patches/server/0177-Extend-Player-Interact-cancellation.patch b/patches/server/0177-Extend-Player-Interact-cancellation.patch index 670211c9b7..ab571f3eba 100644 --- a/patches/server/0177-Extend-Player-Interact-cancellation.patch +++ b/patches/server/0177-Extend-Player-Interact-cancellation.patch @@ -13,10 +13,10 @@ Update adjacent blocks of doors, double plants, pistons and beds when cancelling interaction. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index 9d303a962950c7464d1d4a2a0ce3f658628cc785..a67b7c82236d448bf10c257ab0a10476372ce89c 100644 +index ecfb88b4d9727ad20a2c33475cc6b1ec88821a19..315dad4789f5f2582ee9b4fc176affd1f57537ef 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -178,6 +178,11 @@ public class ServerPlayerGameMode { +@@ -187,6 +187,11 @@ public class ServerPlayerGameMode { PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, direction, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND); if (event.isCancelled()) { // Let the client know the block still exists @@ -28,7 +28,7 @@ index 9d303a962950c7464d1d4a2a0ce3f658628cc785..a67b7c82236d448bf10c257ab0a10476 this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); // Update any tile entity data for this block BlockEntity tileentity = this.level.getBlockEntity(pos); -@@ -493,7 +498,13 @@ public class ServerPlayerGameMode { +@@ -502,7 +507,13 @@ public class ServerPlayerGameMode { // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.above())); diff --git a/patches/server/0181-Implement-extended-PaperServerListPingEvent.patch b/patches/server/0181-Implement-extended-PaperServerListPingEvent.patch index 31680c41fc..ff5a86f8ca 100644 --- a/patches/server/0181-Implement-extended-PaperServerListPingEvent.patch +++ b/patches/server/0181-Implement-extended-PaperServerListPingEvent.patch @@ -190,7 +190,7 @@ index 67455a5ba75c9b816213e44d6872c5ddf8e27e98..23efad80934930beadf15e65781551d4 public ClientboundStatusResponsePacket(ServerStatus metadata) { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index fb4385333ef8dd4fa22275753606df3020000539..a0c436fd5e7e03a0a01e59c046e65ebdcd88021a 100644 +index d86c5cb6fa9c31db90c6392cd8baf5823b6c32b4..050b27be1c25764d65e5340149718e858b3aeb2e 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -2,6 +2,9 @@ package net.minecraft.server; @@ -203,7 +203,7 @@ index fb4385333ef8dd4fa22275753606df3020000539..a0c436fd5e7e03a0a01e59c046e65ebd import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -@@ -1310,7 +1313,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= 5000000000L) { this.lastServerStatus = i; this.status.setPlayers(new ServerStatus.Players(this.getMaxPlayers(), this.getPlayerCount())); diff --git a/patches/server/0184-Player.setPlayerProfile-API.patch b/patches/server/0184-Player.setPlayerProfile-API.patch index 7ebc1c188e..1fdec002ba 100644 --- a/patches/server/0184-Player.setPlayerProfile-API.patch +++ b/patches/server/0184-Player.setPlayerProfile-API.patch @@ -39,7 +39,7 @@ index 4e8d38a6379d3dc1b7167b27479e6a27ea19ea19..3c0aca2b90521da83cf494d9fff953a1 private ItemStack lastItemInMainHand; private final ItemCooldowns cooldowns; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 75963a28b39f8835f1daba3d1b44655603124bf3..8bf0c74ee32e8cb7c0f48bc964552811ad6ee468 100644 +index 7c6e1348cc26c38a844b7324a8372266579e048e..c40b96a88ec6c33364cd7a04e5354900cba72f05 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -71,6 +71,7 @@ import net.minecraft.world.item.enchantment.EnchantmentHelper; @@ -50,7 +50,7 @@ index 75963a28b39f8835f1daba3d1b44655603124bf3..8bf0c74ee32e8cb7c0f48bc964552811 import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.saveddata.maps.MapDecoration; import net.minecraft.world.level.saveddata.maps.MapItemSavedData; -@@ -1320,8 +1321,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1329,8 +1330,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.hiddenPlayers.put(player.getUniqueId(), hidingPlugins); // Remove this player from the hidden player's EntityTrackerEntry @@ -65,7 +65,7 @@ index 75963a28b39f8835f1daba3d1b44655603124bf3..8bf0c74ee32e8cb7c0f48bc964552811 ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId()); if (entry != null) { entry.removePlayer(this.getHandle()); -@@ -1362,8 +1368,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1371,8 +1377,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } this.hiddenPlayers.remove(player.getUniqueId()); @@ -80,7 +80,7 @@ index 75963a28b39f8835f1daba3d1b44655603124bf3..8bf0c74ee32e8cb7c0f48bc964552811 this.getHandle().connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, other)); -@@ -1372,6 +1383,50 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1381,6 +1392,50 @@ public class CraftPlayer extends CraftHumanEntity implements Player { entry.updatePlayer(this.getHandle()); } } diff --git a/patches/server/0185-getPlayerUniqueId-API.patch b/patches/server/0185-getPlayerUniqueId-API.patch index bdb836561a..0db33e015e 100644 --- a/patches/server/0185-getPlayerUniqueId-API.patch +++ b/patches/server/0185-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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index cb09b6170a74984628f2c3dbacad2ddc9fe56faf..df94ac3f5319cd990f5592d57d2e319c84f51524 100644 +index 8e93f6398a5974676a479e17f31a8e77c461fb41..b12fb31d9a601c1781b0cb0a24bdd9cbcc4f382b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1517,6 +1517,25 @@ public final class CraftServer implements Server { +@@ -1519,6 +1519,25 @@ public final class CraftServer implements Server { return recipients.size(); } diff --git a/patches/server/0189-Flag-to-disable-the-channel-limit.patch b/patches/server/0189-Flag-to-disable-the-channel-limit.patch index c2ee900d0d..20cb1ffb92 100644 --- a/patches/server/0189-Flag-to-disable-the-channel-limit.patch +++ b/patches/server/0189-Flag-to-disable-the-channel-limit.patch @@ -9,10 +9,10 @@ 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 8bf0c74ee32e8cb7c0f48bc964552811ad6ee468..8df1894df3583840412ccc7ccdc4b23db6dd6265 100644 +index c40b96a88ec6c33364cd7a04e5354900cba72f05..87f48b648d7523ccd573fa673666fdaaadbb9eda 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -148,6 +148,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -149,6 +149,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Paper start private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; private String resourcePackHash; @@ -20,7 +20,7 @@ index 8bf0c74ee32e8cb7c0f48bc964552811ad6ee468..8df1894df3583840412ccc7ccdc4b23d // Paper end public CraftPlayer(CraftServer server, ServerPlayer entity) { -@@ -1589,7 +1590,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1598,7 +1599,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void addChannel(String channel) { diff --git a/patches/server/0190-Add-method-to-open-already-placed-sign.patch b/patches/server/0190-Add-method-to-open-already-placed-sign.patch index 01f8ae7ef7..94cbbbf03a 100644 --- a/patches/server/0190-Add-method-to-open-already-placed-sign.patch +++ b/patches/server/0190-Add-method-to-open-already-placed-sign.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add method to open already placed sign diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 6c404878e58f68c9ac86a1771c23e528f3817e32..7f7322b5174a7580675b0607b0f282f7bf75a3e2 100644 +index bddfc12e8cf896bee5fb518ddacdca434456c6bb..c839ea0b68fbdccfb7ed667c705a3f0f347fd89c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -604,6 +604,17 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -610,6 +610,17 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { } } diff --git a/patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch index 45e96cfdf8..719bc3db58 100644 --- a/patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch +++ b/patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch @@ -10,7 +10,7 @@ Adds an option to control the force mode of the particle. This adds a new Builder API which is much friendlier to use. diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 8323ddb363f49d266dd95f11241a30a9a27250aa..cf074ef0cb01bc2cbd8c529e7233ceb9443f764d 100644 +index 18ab943ea2a959f012c3f75957fcb05dbe4ee6ff..c7ac5b323c731e5a7929f87d59e62796e8d4a107 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1287,12 +1287,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl @@ -34,10 +34,10 @@ index 8323ddb363f49d266dd95f11241a30a9a27250aa..cf074ef0cb01bc2cbd8c529e7233ceb9 if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index bc80e0062ef679e7cb147bd1a6da52bf95da52b8..ab59b0e9dc827e7ebe0c4dea633680908dcb5874 100644 +index 9925d1f68c35a29156a152a8cc4b653ba280374b..fbc82598a2f7ea439bb371ecf074b486ae09c355 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2355,11 +2355,17 @@ public class CraftWorld implements World { +@@ -2357,11 +2357,17 @@ public class CraftWorld implements World { @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/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch index 7c6dcd87e2..5f114f6efd 100644 --- a/patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch +++ b/patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch @@ -8,10 +8,10 @@ This API has more capabilities than .dropItem with the Consumer function Item can be set inside of the Consumer pre spawn function. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index ab59b0e9dc827e7ebe0c4dea633680908dcb5874..058346b89c07d44a5425a61abedcfc440cb9ee21 100644 +index fbc82598a2f7ea439bb371ecf074b486ae09c355..e744a793062acce339c4914eb2eff2a8c2ff6f1b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1505,6 +1505,10 @@ public class CraftWorld implements World { +@@ -1506,6 +1506,10 @@ public class CraftWorld implements World { if (Boat.class.isAssignableFrom(clazz)) { entity = new net.minecraft.world.entity.vehicle.Boat(this.world, x, y, z); entity.moveTo(x, y, z, yaw, pitch); diff --git a/patches/server/0206-Fix-CraftEntity-hashCode.patch b/patches/server/0206-Fix-CraftEntity-hashCode.patch index 35cf02c08d..9c66bc30b3 100644 --- a/patches/server/0206-Fix-CraftEntity-hashCode.patch +++ b/patches/server/0206-Fix-CraftEntity-hashCode.patch @@ -21,10 +21,10 @@ check is essentially the same as this.getHandle() == other.getHandle() However, replaced it too to make it clearer of intent. diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 1fd891b53c54153c28d636b2679b4a083510ba3c..0bc816407157264bf3e736da678535d08b4d85f2 100644 +index af8552f21f598f99151e59fe44df40f13caa3ead..b9089ba658d38397cf07245e31e6d40b3a2a5f2b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -782,14 +782,15 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -783,14 +783,15 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return false; } final CraftEntity other = (CraftEntity) obj; diff --git a/patches/server/0213-Expand-Explosions-API.patch b/patches/server/0213-Expand-Explosions-API.patch index 00de92415e..211ac6f053 100644 --- a/patches/server/0213-Expand-Explosions-API.patch +++ b/patches/server/0213-Expand-Explosions-API.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Expand Explosions API Add Entity as a Source capability, and add more API choices, and on Location. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 058346b89c07d44a5425a61abedcfc440cb9ee21..df6b4f65dd84621b8477b42a504f9e62c633a6b5 100644 +index e744a793062acce339c4914eb2eff2a8c2ff6f1b..c3a57510cd17203c65c15de0544d5656eb7a0b7b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -889,6 +889,12 @@ public class CraftWorld implements World { +@@ -890,6 +890,12 @@ public class CraftWorld implements World { public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) { return !this.world.explode(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; } diff --git a/patches/server/0217-Implement-World.getEntity-UUID-API.patch b/patches/server/0217-Implement-World.getEntity-UUID-API.patch index 1024259266..db3675e02f 100644 --- a/patches/server/0217-Implement-World.getEntity-UUID-API.patch +++ b/patches/server/0217-Implement-World.getEntity-UUID-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Implement World.getEntity(UUID) API diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index df6b4f65dd84621b8477b42a504f9e62c633a6b5..e7f5cd35869790baf616e6c65f49169aa5349e89 100644 +index c3a57510cd17203c65c15de0544d5656eb7a0b7b..e819031a4176a54a06c5a09ee29eda4db4f6cc08 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1295,6 +1295,15 @@ public class CraftWorld implements World { +@@ -1296,6 +1296,15 @@ public class CraftWorld implements World { return list; } diff --git a/patches/server/0218-InventoryCloseEvent-Reason-API.patch b/patches/server/0218-InventoryCloseEvent-Reason-API.patch index b7296c49de..b2754a7e77 100644 --- a/patches/server/0218-InventoryCloseEvent-Reason-API.patch +++ b/patches/server/0218-InventoryCloseEvent-Reason-API.patch @@ -7,7 +7,7 @@ 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/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index cf074ef0cb01bc2cbd8c529e7233ceb9443f764d..ca0907601c6262d27c3406cea806a40421bc4ace 100644 +index c7ac5b323c731e5a7929f87d59e62796e8d4a107..5a5733124bd8395bb996e9d5426c4a260fbeb1d3 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1055,7 +1055,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl @@ -29,7 +29,7 @@ index cf074ef0cb01bc2cbd8c529e7233ceb9443f764d..ca0907601c6262d27c3406cea806a404 } // 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 7159a433e9a264d2151dddc84a74689d0bc7635b..171500918c8ee248689909ae97230eb18adc33e5 100644 +index aeea85ce319c8583c70dee632ff68d430c2cae02..c8652e3bf325d3c557257ad88fe195f7a31683d6 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -602,7 +602,7 @@ public class ServerPlayer extends Player { @@ -84,7 +84,7 @@ index 7159a433e9a264d2151dddc84a74689d0bc7635b..171500918c8ee248689909ae97230eb1 this.doCloseContainer(); } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 35a00a622ff0c3582e08dbbefb1d34a84e590a81..ce88f701f296e67afc67d7e3882406e86147408e 100644 +index d5c3c97e5205ef94578bc2d9d39f1a4c2600db94..ec473952e9f35db15cbb743a3c77c45c26d40ac5 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -188,6 +188,7 @@ import org.bukkit.event.inventory.ClickType; @@ -95,7 +95,7 @@ index 35a00a622ff0c3582e08dbbefb1d34a84e590a81..ce88f701f296e67afc67d7e3882406e8 import org.bukkit.event.inventory.InventoryCreativeEvent; import org.bukkit.event.inventory.InventoryType.SlotType; import org.bukkit.event.inventory.SmithItemEvent; -@@ -2332,10 +2333,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -2333,10 +2334,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @Override public void handleContainerClose(ServerboundContainerClosePacket packet) { @@ -154,7 +154,7 @@ index 0d6e024208182d5779be3d84cff193ce904ad541..e0e33dd92b686939f622f0a7da0d5a97 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 7f7322b5174a7580675b0607b0f282f7bf75a3e2..662a4cec1d292428f06ec5a1f862a1f8d8834c09 100644 +index c839ea0b68fbdccfb7ed667c705a3f0f347fd89c..43cee8b0b2b94d6db6303a1631731ed515eb806d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -373,7 +373,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @@ -185,10 +185,10 @@ index 7f7322b5174a7580675b0607b0f282f7bf75a3e2..662a4cec1d292428f06ec5a1f862a1f8 @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 8df1894df3583840412ccc7ccdc4b23db6dd6265..f8155d7edb4e13c2ec5ed832231f02ee6eff3f35 100644 +index 87f48b648d7523ccd573fa673666fdaaadbb9eda..b0a6ef41f5065e02c0eada4f2fb6cc9335307bde 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -908,7 +908,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -917,7 +917,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Close any foreign inventory if (this.getHandle().containerMenu != this.getHandle().inventoryMenu) { @@ -198,10 +198,10 @@ index 8df1894df3583840412ccc7ccdc4b23db6dd6265..f8155d7edb4e13c2ec5ed832231f02ee // 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 56900b5810db623a49559ad218a5385c110bf479..375e9e45331d5be237c67f11af94c6998409418b 100644 +index 1fce91a05a6b04a8d93d2707637c5b96c318a641..5d0bbdd342eda5660b461b99fed7e80afaefbff9 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1154,7 +1154,7 @@ public class CraftEventFactory { +@@ -1170,7 +1170,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 @@ -210,7 +210,7 @@ index 56900b5810db623a49559ad218a5385c110bf479..375e9e45331d5be237c67f11af94c699 } CraftServer server = player.level.getCraftServer(); -@@ -1320,8 +1320,18 @@ public class CraftEventFactory { +@@ -1336,8 +1336,18 @@ public class CraftEventFactory { return event; } diff --git a/patches/server/0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/patches/server/0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch index c21462446e..c4c078ca9f 100644 --- a/patches/server/0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch +++ b/patches/server/0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch @@ -16,10 +16,10 @@ Refresh the player inventory when PlayerInteractEntityEvent is cancelled to avoid this problem. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ce88f701f296e67afc67d7e3882406e86147408e..902eab82912b9a7002485f73df7ae25e370b7e25 100644 +index ec473952e9f35db15cbb743a3c77c45c26d40ac5..28f4c456936c378628336d4a36f1975476f7913f 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2217,6 +2217,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -2218,6 +2218,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } if (event.isCancelled()) { diff --git a/patches/server/0231-Vanished-players-don-t-have-rights.patch b/patches/server/0231-Vanished-players-don-t-have-rights.patch index 8e9dcb152a..4ccf5980c8 100644 --- a/patches/server/0231-Vanished-players-don-t-have-rights.patch +++ b/patches/server/0231-Vanished-players-don-t-have-rights.patch @@ -99,10 +99,10 @@ index 2c86a5ae8bbf7d80e7ce8cd08319ed6a17b86dbb..c1cf7f5bff2878281d4a9787ea7160e9 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 375e9e45331d5be237c67f11af94c6998409418b..966d06e2da7e6f9b4e78ca8ed02f3a6472bc8c05 100644 +index 5d0bbdd342eda5660b461b99fed7e80afaefbff9..c09c2c8ec2a4dd2e1eec5ecf97cbd8456b5ec3c9 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1190,6 +1190,14 @@ public class CraftEventFactory { +@@ -1206,6 +1206,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/0240-MC-135506-Experience-should-save-as-Integers.patch b/patches/server/0240-MC-135506-Experience-should-save-as-Integers.patch index 0136141c94..e0997fb33e 100644 --- a/patches/server/0240-MC-135506-Experience-should-save-as-Integers.patch +++ b/patches/server/0240-MC-135506-Experience-should-save-as-Integers.patch @@ -5,10 +5,10 @@ Subject: [PATCH] MC-135506: Experience should save as Integers diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index 71fb831ed3359e7986e279c987211f39c581ab23..9c91d8453c6a1ad020ecab45775bd81302b817d3 100644 +index 30a3facc1b23ccb508b30c5affa9ea1c527dd48b..a30f9d57257e1de1641f4af1fa7afaea3f0fd37c 100644 --- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -286,7 +286,7 @@ public class ExperienceOrb extends Entity { +@@ -283,7 +283,7 @@ public class ExperienceOrb extends Entity { public void addAdditionalSaveData(CompoundTag nbt) { nbt.putShort("Health", (short) this.health); nbt.putShort("Age", (short) this.age); @@ -17,7 +17,7 @@ index 71fb831ed3359e7986e279c987211f39c581ab23..9c91d8453c6a1ad020ecab45775bd813 nbt.putInt("Count", this.count); this.savePaperNBT(nbt); // Paper } -@@ -295,7 +295,7 @@ public class ExperienceOrb extends Entity { +@@ -292,7 +292,7 @@ public class ExperienceOrb extends Entity { public void readAdditionalSaveData(CompoundTag nbt) { this.health = nbt.getShort("Health"); this.age = nbt.getShort("Age"); diff --git a/patches/server/0242-Add-Early-Warning-Feature-to-WatchDog.patch b/patches/server/0242-Add-Early-Warning-Feature-to-WatchDog.patch index 35278841db..2656d34b76 100644 --- a/patches/server/0242-Add-Early-Warning-Feature-to-WatchDog.patch +++ b/patches/server/0242-Add-Early-Warning-Feature-to-WatchDog.patch @@ -36,10 +36,10 @@ index bd508025b771424c942fd856c31d520b6f548082..62621562137cba4804f0465c58d25ca2 public static int tabSpamLimit = 500; private static void tabSpamLimiters() { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index a0c436fd5e7e03a0a01e59c046e65ebdcd88021a..cf92c3275869e4a0209fd4b07ad723e11717dc86 100644 +index 050b27be1c25764d65e5340149718e858b3aeb2e..880fc4e346549a5d7ed627244bdfd284705ad2fc 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1075,6 +1075,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop comparator; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 6ea367295d07c444d7cce0366261a884d299185a..65a40c912ec20b06e5da01faebf3798c4b613faa 100644 +index b65fcc7519589c3bc5c5f5b5ec1db53a520ec39f..a29b8c83be940e4b3db06d881b59b03120e931ab 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -712,6 +712,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @@ -3678,10 +3678,10 @@ index 844d65612d9c4c19d02a2b0a5b90cd44de9f17c9..cfd4c38ca99b183f23716f82c972c14b + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 2a9a57263ff116c1a7f51eac127292559de48b11..84666742e0082f8fb853f255a8ec27832a75d4b0 100644 +index 43e47c345a0d2e00f13f0112d26d93b004009ac9..b8565aa86b478adb6fca6d433637ddb342ce6dcb 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2422,6 +2422,34 @@ public class CraftWorld implements World { +@@ -2424,6 +2424,34 @@ public class CraftWorld implements World { public DragonBattle getEnderDragonBattle() { return (this.getHandle().dragonFight() == null) ? null : new CraftDragonBattle(this.getHandle().dragonFight()); } @@ -3717,10 +3717,10 @@ index 2a9a57263ff116c1a7f51eac127292559de48b11..84666742e0082f8fb853f255a8ec2783 // Spigot start @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 0bc816407157264bf3e736da678535d08b4d85f2..ead2b25042af2622f75f7be1fdfad9b4250ac0cc 100644 +index b9089ba658d38397cf07245e31e6d40b3a2a5f2b..c381ea321b0fb3498e3f101ee059ac7d42aa029a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -12,6 +12,7 @@ import net.minecraft.nbt.CompoundTag; +@@ -13,6 +13,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; @@ -3728,7 +3728,7 @@ index 0bc816407157264bf3e736da678535d08b4d85f2..ead2b25042af2622f75f7be1fdfad9b4 import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.AreaEffectCloud; import net.minecraft.world.entity.Entity; -@@ -514,6 +515,28 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -515,6 +516,28 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { this.entity.setYHeadRot(yaw); } diff --git a/patches/server/0259-Expose-attack-cooldown-methods-for-Player.patch b/patches/server/0259-Expose-attack-cooldown-methods-for-Player.patch index f01641a4ef..ec4b2815fa 100644 --- a/patches/server/0259-Expose-attack-cooldown-methods-for-Player.patch +++ b/patches/server/0259-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 f8155d7edb4e13c2ec5ed832231f02ee6eff3f35..91dc9e3b02462211a6964204f5409fbae98027e6 100644 +index b0a6ef41f5065e02c0eada4f2fb6cc9335307bde..9683b5e7045050ee0a6f279749dd159ff4366a7d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2199,6 +2199,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2208,6 +2208,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND)); connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, inventory.getSelected())); } diff --git a/patches/server/0260-Improve-death-events.patch b/patches/server/0260-Improve-death-events.patch index 3928b674e5..095ae72b8a 100644 --- a/patches/server/0260-Improve-death-events.patch +++ b/patches/server/0260-Improve-death-events.patch @@ -19,7 +19,7 @@ maybe more (please check patch overrides for drops for more): - players, armor stands, foxes, chested donkeys/llamas diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 171500918c8ee248689909ae97230eb18adc33e5..44385d07b2deedffd95bcc428d9d8d3f785143db 100644 +index c8652e3bf325d3c557257ad88fe195f7a31683d6..bea1461ee3bd65f02bf6add6ed967555092fd675 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -218,6 +218,10 @@ public class ServerPlayer extends Player { @@ -286,10 +286,10 @@ index 4adde11daa5ca97a2bf9c164c43c5c011a89b33d..cb9969d768b13863722aad3dc5daad3c } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 91dc9e3b02462211a6964204f5409fbae98027e6..22032108fdaed14663a9d7e0b6757eef5237c4dd 100644 +index 9683b5e7045050ee0a6f279749dd159ff4366a7d..686dc5859c081d3b86d8e58a63abee49258208d7 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1849,7 +1849,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1858,7 +1858,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void sendHealthUpdate() { @@ -306,10 +306,10 @@ index 91dc9e3b02462211a6964204f5409fbae98027e6..22032108fdaed14663a9d7e0b6757eef 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 a81fc5212648056766824113b372a7c772c19e5a..f0c3255e0b4e1ecf4a54213c6458c92a7389b134 100644 +index bb006e6c703e5c4cfa16ca4ee4cf8463215c38b0..c3341d1c4e9cda85b0b236461b0a00cbebc9a856 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -770,9 +770,16 @@ public class CraftEventFactory { +@@ -787,9 +787,16 @@ public class CraftEventFactory { public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, List drops) { CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward()); @@ -326,7 +326,7 @@ index a81fc5212648056766824113b372a7c772c19e5a..f0c3255e0b4e1ecf4a54213c6458c92a victim.expToDrop = event.getDroppedExp(); for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { -@@ -788,8 +795,15 @@ public class CraftEventFactory { +@@ -805,8 +812,15 @@ public class CraftEventFactory { CraftPlayer entity = victim.getBukkitEntity(); PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure event.setKeepInventory(keepInventory); @@ -342,7 +342,7 @@ index a81fc5212648056766824113b372a7c772c19e5a..f0c3255e0b4e1ecf4a54213c6458c92a victim.keepLevel = event.getKeepLevel(); victim.newLevel = event.getNewLevel(); -@@ -806,6 +820,31 @@ public class CraftEventFactory { +@@ -823,6 +837,31 @@ public class CraftEventFactory { return event; } diff --git a/work/Bukkit b/work/Bukkit index 5b94881a0b..8503c3c9e3 160000 --- a/work/Bukkit +++ b/work/Bukkit @@ -1 +1 @@ -Subproject commit 5b94881a0b4383f901c1c65db10767e42446760e +Subproject commit 8503c3c9e3dca76b2ae10796d8c288b3f3101737 diff --git a/work/CraftBukkit b/work/CraftBukkit index e2f5ea34e9..40caacc846 160000 --- a/work/CraftBukkit +++ b/work/CraftBukkit @@ -1 +1 @@ -Subproject commit e2f5ea34e9c7f9eb3eb2be422b169679922b2770 +Subproject commit 40caacc846a6349cd555d9d89cf9cf729c0b75b7 diff --git a/work/Spigot b/work/Spigot index c9cea60004..66f9d3c17b 160000 --- a/work/Spigot +++ b/work/Spigot @@ -1 +1 @@ -Subproject commit c9cea600043b1dc6fa306b4baee307d064c65eac +Subproject commit 66f9d3c17bd578dacbb87702cc0347148696e105 From 79f1d1a07830c14bd8cd75a56c8714c1a9dc4bfd Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sat, 12 Jun 2021 23:48:25 -0700 Subject: [PATCH 067/226] patches fix --- .../0154-Material-API-additions.patch} | 6 +- .../0155-Add-Material-Tags.patch} | 2 +- ...156-Add-LivingEntity-getTargetEntity.patch | 2 +- .../0157-Add-sun-related-API.patch | 2 +- .../0158-Here-s-Johnny.patch | 0 .../0159-Turtle-API.patch | 0 .../0160-Add-spectator-target-events.patch | 0 .../0161-Add-more-Witch-API.patch | 0 .../1.17/0153-PreSpawnerSpawnEvent.patch} | 2 + .../1.17}/0290-PreSpawnerSpawnEvent.patch | 2 + .../0292-Honor-EntityAgeable.ageLock.patch | 18 -- ...ther-worlds-for-shooter-of-projectil.patch | 36 ---- ...336-Add-LivingEntity-getTargetEntity.patch | 187 ------------------ ...rseException-in-Entity-and-TE-names.patch} | 64 +++--- .../0269-Honor-EntityAgeable.ageLock.patch | 18 ++ ...le-connection-throttle-kick-message.patch} | 12 +- .../0271-Hook-into-CB-plugin-rewrites.patch} | 4 +- .../0272-Add-sun-related-API.patch} | 19 +- ...273-Add-LivingEntity-getTargetEntity.patch | 114 +++++++++++ .../0274-Turtle-API.patch} | 52 +++-- ...ther-worlds-for-shooter-of-projectil.patch | 35 ++++ ...ator-target-events-and-improve-impl.patch} | 29 ++- ...-Add-Velocity-IP-Forwarding-Support.patch} | 140 ++++--------- .../0278-Add-more-Witch-API.patch} | 19 +- ...wned-for-Villager-Aggression-Config.patch} | 10 +- .../0280-Here-s-Johnny.patch} | 10 +- ...vent-players-from-moving-into-unloa.patch} | 38 ++-- 27 files changed, 340 insertions(+), 481 deletions(-) rename patches/{api-unmapped/0153-Material-API-additions.patch => api/0154-Material-API-additions.patch} (82%) rename patches/{api-unmapped/0154-Add-Material-Tags.patch => api/0155-Add-Material-Tags.patch} (99%) rename patches/{api-unmapped => api}/0156-Add-LivingEntity-getTargetEntity.patch (97%) rename patches/{api-unmapped => api}/0157-Add-sun-related-API.patch (93%) rename patches/{api-unmapped => api}/0158-Here-s-Johnny.patch (100%) rename patches/{api-unmapped => api}/0159-Turtle-API.patch (100%) rename patches/{api-unmapped => api}/0160-Add-spectator-target-events.patch (100%) rename patches/{api-unmapped => api}/0161-Add-more-Witch-API.patch (100%) rename patches/{api-unmapped/0152-PreSpawnerSpawnEvent.patch => removed/1.17/0153-PreSpawnerSpawnEvent.patch} (95%) rename patches/{server-remapped => removed/1.17}/0290-PreSpawnerSpawnEvent.patch (94%) delete mode 100644 patches/server-remapped/0292-Honor-EntityAgeable.ageLock.patch delete mode 100644 patches/server-remapped/0298-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch delete mode 100644 patches/server-remapped/0336-Add-LivingEntity-getTargetEntity.patch rename patches/{server-remapped/0291-Catch-JsonParseException-in-Entity-and-TE-names.patch => server/0268-Catch-JsonParseException-in-Entity-and-TE-names.patch} (68%) create mode 100644 patches/server/0269-Honor-EntityAgeable.ageLock.patch rename patches/{server-remapped/0293-Configurable-connection-throttle-kick-message.patch => server/0270-Configurable-connection-throttle-kick-message.patch} (75%) rename patches/{server-remapped/0294-Hook-into-CB-plugin-rewrites.patch => server/0271-Hook-into-CB-plugin-rewrites.patch} (98%) rename patches/{server-remapped/0296-Add-sun-related-API.patch => server/0272-Add-sun-related-API.patch} (68%) create mode 100644 patches/server/0273-Add-LivingEntity-getTargetEntity.patch rename patches/{server-remapped/0297-Turtle-API.patch => server/0274-Turtle-API.patch} (74%) create mode 100644 patches/server/0275-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch rename patches/{server-remapped/0299-Call-player-spectator-target-events-and-improve-impl.patch => server/0276-Call-player-spectator-target-events-and-improve-impl.patch} (73%) rename patches/{server-remapped/0300-Add-Velocity-IP-Forwarding-Support.patch => server/0277-Add-Velocity-IP-Forwarding-Support.patch} (63%) rename patches/{server-remapped/0301-Add-more-Witch-API.patch => server/0278-Add-more-Witch-API.patch} (90%) rename patches/{server-remapped/0302-Check-Drowned-for-Villager-Aggression-Config.patch => server/0279-Check-Drowned-for-Villager-Aggression-Config.patch} (69%) rename patches/{server-remapped/0303-Here-s-Johnny.patch => server/0280-Here-s-Johnny.patch} (78%) rename patches/{server-remapped/0304-Add-option-to-prevent-players-from-moving-into-unloa.patch => server/0281-Add-option-to-prevent-players-from-moving-into-unloa.patch} (66%) diff --git a/patches/api-unmapped/0153-Material-API-additions.patch b/patches/api/0154-Material-API-additions.patch similarity index 82% rename from patches/api-unmapped/0153-Material-API-additions.patch rename to patches/api/0154-Material-API-additions.patch index 629bed4425..c740ab3a44 100644 --- a/patches/api-unmapped/0153-Material-API-additions.patch +++ b/patches/api/0154-Material-API-additions.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Material API additions diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index a9769ae0bad61d200c70331eba0b655da4ba03b2..9c28351c7c3f60c6a3b4020329344f91efeedae1 100644 +index da9f91d0a1d20839cfbc4e564f4987cda440f2ac..52290c43d1c02785c4cae4a73494a75cdc369e02 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java -@@ -98,6 +98,7 @@ import org.jetbrains.annotations.Nullable; +@@ -99,6 +99,7 @@ import org.jetbrains.annotations.Nullable; /** * An enum of all material IDs accepted by the official server and client */ @@ -16,7 +16,7 @@ index a9769ae0bad61d200c70331eba0b655da4ba03b2..9c28351c7c3f60c6a3b4020329344f91 public enum Material implements Keyed { // AIR(9648, 0), -@@ -3976,6 +3977,22 @@ public enum Material implements Keyed { +@@ -3977,6 +3978,22 @@ public enum Material implements Keyed { } } diff --git a/patches/api-unmapped/0154-Add-Material-Tags.patch b/patches/api/0155-Add-Material-Tags.patch similarity index 99% rename from patches/api-unmapped/0154-Add-Material-Tags.patch rename to patches/api/0155-Add-Material-Tags.patch index 7fa999bf70..895bee224a 100644 --- a/patches/api-unmapped/0154-Add-Material-Tags.patch +++ b/patches/api/0155-Add-Material-Tags.patch @@ -946,7 +946,7 @@ index 0000000000000000000000000000000000000000..9266c9d77e2eef7cd717dc729834a190 + .ensureSize("WATER_BASED", 9); +} diff --git a/src/main/java/org/bukkit/Tag.java b/src/main/java/org/bukkit/Tag.java -index aacbfadc91f580cc667603c8165eacbadee38cca..3c2a6a2167eab43097f5d6ccf1550e12795fc0b6 100644 +index 53b66c28f0fed97664d0886683731e94ca59bdd2..88ea8b6c5c2c4d2116f646341de62590718bc28c 100644 --- a/src/main/java/org/bukkit/Tag.java +++ b/src/main/java/org/bukkit/Tag.java @@ -10,6 +10,10 @@ import org.jetbrains.annotations.NotNull; diff --git a/patches/api-unmapped/0156-Add-LivingEntity-getTargetEntity.patch b/patches/api/0156-Add-LivingEntity-getTargetEntity.patch similarity index 97% rename from patches/api-unmapped/0156-Add-LivingEntity-getTargetEntity.patch rename to patches/api/0156-Add-LivingEntity-getTargetEntity.patch index cc02ae973f..43c223a636 100644 --- a/patches/api-unmapped/0156-Add-LivingEntity-getTargetEntity.patch +++ b/patches/api/0156-Add-LivingEntity-getTargetEntity.patch @@ -49,7 +49,7 @@ index 0000000000000000000000000000000000000000..f52644fab1522bdf83ff4f489e9805b2 + } +} diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 8fe7ccf12339355554835542cc1068d9f6c3a435..561db9d594633e3909fd6d69dad1dc2976928d58 100644 +index 05992ade1bca42a6233373b44513b89986d89c5a..ac6921093457cee6d01fd27690c8bb6034b4af53 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -151,6 +151,50 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api-unmapped/0157-Add-sun-related-API.patch b/patches/api/0157-Add-sun-related-API.patch similarity index 93% rename from patches/api-unmapped/0157-Add-sun-related-API.patch rename to patches/api/0157-Add-sun-related-API.patch index 85efb56e43..d276f4329a 100644 --- a/patches/api-unmapped/0157-Add-sun-related-API.patch +++ b/patches/api/0157-Add-sun-related-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add sun related API diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index ec8e3a949a869545a8e0cb8c2f59f1a6dd8f5485..ce1a3de1d03e10b18c0098ee2778361cc9a4cb01 100644 +index 1264c65235e622f648d71ef10d804ef5193da973..b80a2fe9eb6824d986126e451900a62244d3a8e7 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -1812,6 +1812,16 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad diff --git a/patches/api-unmapped/0158-Here-s-Johnny.patch b/patches/api/0158-Here-s-Johnny.patch similarity index 100% rename from patches/api-unmapped/0158-Here-s-Johnny.patch rename to patches/api/0158-Here-s-Johnny.patch diff --git a/patches/api-unmapped/0159-Turtle-API.patch b/patches/api/0159-Turtle-API.patch similarity index 100% rename from patches/api-unmapped/0159-Turtle-API.patch rename to patches/api/0159-Turtle-API.patch diff --git a/patches/api-unmapped/0160-Add-spectator-target-events.patch b/patches/api/0160-Add-spectator-target-events.patch similarity index 100% rename from patches/api-unmapped/0160-Add-spectator-target-events.patch rename to patches/api/0160-Add-spectator-target-events.patch diff --git a/patches/api-unmapped/0161-Add-more-Witch-API.patch b/patches/api/0161-Add-more-Witch-API.patch similarity index 100% rename from patches/api-unmapped/0161-Add-more-Witch-API.patch rename to patches/api/0161-Add-more-Witch-API.patch diff --git a/patches/api-unmapped/0152-PreSpawnerSpawnEvent.patch b/patches/removed/1.17/0153-PreSpawnerSpawnEvent.patch similarity index 95% rename from patches/api-unmapped/0152-PreSpawnerSpawnEvent.patch rename to patches/removed/1.17/0153-PreSpawnerSpawnEvent.patch index 70ec0d47bd..dcb362d8bc 100644 --- a/patches/api-unmapped/0152-PreSpawnerSpawnEvent.patch +++ b/patches/removed/1.17/0153-PreSpawnerSpawnEvent.patch @@ -8,6 +8,8 @@ which contains the location of the spawner too similarly to how the SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for spawners. +Dropped as it does not apply due to the earlier PreCreatureSpawnEvent patch not being applied + diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..48cff063594840a07aeaf35513780e28ea019a76 diff --git a/patches/server-remapped/0290-PreSpawnerSpawnEvent.patch b/patches/removed/1.17/0290-PreSpawnerSpawnEvent.patch similarity index 94% rename from patches/server-remapped/0290-PreSpawnerSpawnEvent.patch rename to patches/removed/1.17/0290-PreSpawnerSpawnEvent.patch index cb777e4c22..592cfbd22d 100644 --- a/patches/server-remapped/0290-PreSpawnerSpawnEvent.patch +++ b/patches/removed/1.17/0290-PreSpawnerSpawnEvent.patch @@ -8,6 +8,8 @@ which contains the location of the spawner too similarly to how the SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for spawners. +Dropped as it does not apply due to the earlier PreCreatureSpawnEvent patch not being applied + diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java index ac572eba10a7239d71dfae060f623b076d4252ce..1ce675d0d24ceb5724f5ac2d8f671e38f2735f74 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java diff --git a/patches/server-remapped/0292-Honor-EntityAgeable.ageLock.patch b/patches/server-remapped/0292-Honor-EntityAgeable.ageLock.patch deleted file mode 100644 index a2b0c4fa76..0000000000 --- a/patches/server-remapped/0292-Honor-EntityAgeable.ageLock.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Sep 2018 20:59:53 -0500 -Subject: [PATCH] Honor EntityAgeable.ageLock - - -diff --git a/src/main/java/net/minecraft/world/entity/AgableMob.java b/src/main/java/net/minecraft/world/entity/AgableMob.java -index d7c19e5607bcf92c874b3656c2742f4c84dceb12..354311dc541588212a2eacba38e60c7e34aa4c2b 100644 ---- a/src/main/java/net/minecraft/world/entity/AgableMob.java -+++ b/src/main/java/net/minecraft/world/entity/AgableMob.java -@@ -82,6 +82,7 @@ public abstract class AgableMob extends PathfinderMob { - } - - public void ageUp(int age, boolean overGrow) { -+ if (ageLocked) return; // Paper - GH-1459 - int j = this.getAge(); - int k = j; - diff --git a/patches/server-remapped/0298-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/patches/server-remapped/0298-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch deleted file mode 100644 index 685d458bbb..0000000000 --- a/patches/server-remapped/0298-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 17 Oct 2018 19:17:27 -0400 -Subject: [PATCH] MC-50319: Check other worlds for shooter of projectiles - -Say a player shoots an arrow through a nether portal, the game -would lose the shooter for determining things such as Player Kills, -because the entity is in another world. - -If the projectile fails to find the shooter in the current world, check -other worlds. - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index d1dd173c11d751b15c3afd4309e386931fd9cf8d..d385fb6eee5000951c350b6ced5669dc3dcce725 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -44,7 +44,18 @@ public abstract class Projectile extends Entity { - - @Nullable - public Entity getOwner() { -- return this.ownerUUID != null && this.level instanceof ServerLevel ? ((ServerLevel) this.level).getEntity(this.ownerUUID) : (this.ownerNetworkId != 0 ? this.level.getEntity(this.ownerNetworkId) : null); -+ // Paper start - MC-50319 - shooter might be in another world (arrows through portals) -+ Entity entity = this.ownerUUID != null && this.level instanceof ServerLevel ? ((ServerLevel) this.level).getEntity(this.ownerUUID) : (this.ownerNetworkId != 0 ? this.level.getEntity(this.ownerNetworkId) : null); -+ if (entity == null) { -+ for (ServerLevel world : level.getServer().getAllLevels()) { -+ entity = world.getEntity(this.ownerUUID); -+ if (entity != null) { -+ break; -+ } -+ } -+ } -+ return entity; -+ // Paper end - } - - @Override diff --git a/patches/server-remapped/0336-Add-LivingEntity-getTargetEntity.patch b/patches/server-remapped/0336-Add-LivingEntity-getTargetEntity.patch deleted file mode 100644 index d02aab104b..0000000000 --- a/patches/server-remapped/0336-Add-LivingEntity-getTargetEntity.patch +++ /dev/null @@ -1,187 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 22 Sep 2018 00:33:08 -0500 -Subject: [PATCH] Add LivingEntity#getTargetEntity - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c5d6235a132818dfc78105e9d03d0687f697bb00..d106118dbf4fb270f8526e40a767dd4c563a333f 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1503,6 +1503,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.calculateViewVector(pitch - 90.0F, yaw); - } - -+ public final Vec3 getEyePosition(float partialTicks) { return getEyePosition(partialTicks); } // Paper - OBFHELPER - public final Vec3 getEyePosition(float tickDelta) { - if (tickDelta == 1.0F) { - return new Vec3(this.getX(), this.getEyeY(), this.getZ()); -@@ -2153,6 +2154,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.getPassengers().size() < 1; - } - -+ public final float getCollisionBorderSize() { return getPickRadius(); } // Paper - OBFHELPER - public float getPickRadius() { - return 0.0F; - } -diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index e92a8c4c49c452e1f3f0c06398f2a74e3432262f..d3640975c5a33b4911428760691215905b987385 100644 ---- a/src/main/java/net/minecraft/world/entity/EntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -22,6 +22,7 @@ public final class EntitySelector { - public static final Predicate NO_CREATIVE_OR_SPECTATOR = (entity) -> { - return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative(); - }; -+ public static Predicate canAITarget() { return ATTACK_ALLOWED; } // Paper - OBFHELPER - public static final Predicate ATTACK_ALLOWED = (entity) -> { - return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative() && entity.level.getDifficulty() != Difficulty.PEACEFUL; - }; -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 29d4ed42e5d763639a50d849ef274c4d848bc9c9..046a05925739005080af35c4be984303b575bf68 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -108,6 +108,7 @@ import net.minecraft.world.level.storage.loot.LootTable; - import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; - import net.minecraft.world.level.storage.loot.parameters.LootContextParams; - import net.minecraft.world.phys.AABB; -+import net.minecraft.world.phys.EntityHitResult; - import net.minecraft.world.phys.HitResult; - import net.minecraft.world.phys.Vec3; - import net.minecraft.world.scores.PlayerTeam; -@@ -3657,6 +3658,37 @@ public abstract class LivingEntity extends Entity { - return level.clip(raytrace); - } - -+ public EntityHitResult getTargetEntity(int maxDistance) { -+ if (maxDistance < 1 || maxDistance > 120) { -+ throw new IllegalArgumentException("maxDistance must be between 1-120"); -+ } -+ -+ Vec3 start = this.getEyePosition(1.0F); -+ Vec3 direction = this.getLookAngle(); -+ Vec3 end = start.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance); -+ -+ List entityList = level.getEntities(this, getBoundingBox().expand(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance).inflate(1.0D, 1.0D, 1.0D), EntitySelector.canAITarget().and(Entity::isPickable)); -+ -+ double distance = 0.0D; -+ EntityHitResult result = null; -+ -+ for (Entity entity : entityList) { -+ AABB aabb = entity.getBoundingBox().grow((double) entity.getCollisionBorderSize()); -+ Optional rayTraceResult = aabb.calculateIntercept(start, end); -+ -+ if (rayTraceResult.isPresent()) { -+ Vec3 rayTrace = rayTraceResult.get(); -+ double distanceTo = start.distanceToSqr(rayTrace); -+ if (distanceTo < distance || distance == 0.0D) { -+ result = new EntityHitResult(entity, rayTrace); -+ distance = distanceTo; -+ } -+ } -+ } -+ -+ return result; -+ } -+ - public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; - - public int getShieldBlockingDelay() { -diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java -index 983d0495ec35128ca3ef68566ada065bc4b21efc..143a160a7577e9e34d34a9f3b900db03d3f297af 100644 ---- a/src/main/java/net/minecraft/world/phys/AABB.java -+++ b/src/main/java/net/minecraft/world/phys/AABB.java -@@ -116,6 +116,7 @@ public class AABB { - return this.expandTowards(scale.x, scale.y, scale.z); - } - -+ public final AABB expand(double x, double y, double z) { return expandTowards(x, y, z); } // Paper - OBFHELPER - public AABB expandTowards(double x, double y, double z) { - double d3 = this.minX; - double d4 = this.minY; -@@ -145,6 +146,12 @@ public class AABB { - return new AABB(d3, d4, d5, d6, d7, d8); - } - -+ // Paper start -+ public AABB grow(double d0) { -+ return inflate(d0, d0, d0); -+ } -+ // Paper end -+ - public AABB inflate(double x, double y, double z) { - double d3 = this.minX - x; - double d4 = this.minY - y; -@@ -204,6 +211,7 @@ public class AABB { - return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ; - } - -+ public final boolean contains(Vec3 vec3d) { return contains(vec3d); } // Paper - OBFHELPER - public boolean contains(Vec3 vec) { - return this.contains(vec.x, vec.y, vec.z); - } -@@ -237,6 +245,7 @@ public class AABB { - return this.inflate(-value); - } - -+ public final Optional calculateIntercept(Vec3 vec3d, Vec3 vec3d1) { return clip(vec3d, vec3d1); } // Paper - OBFHELPER - public Optional clip(Vec3 min, Vec3 max) { - double[] adouble = new double[]{1.0D}; - double d0 = max.x - min.x; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 7e3a215f1592bed9f35e22076d9e35a5a49a430e..a01bd035846df0e2e28dc55e2ef2f5f35b83f905 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -1,6 +1,7 @@ - package org.bukkit.craftbukkit.entity; - - import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.destroystokyo.paper.entity.TargetEntityInfo; - import com.google.common.base.Preconditions; - import com.google.common.collect.Sets; - import java.util.ArrayList; -@@ -30,8 +31,11 @@ import net.minecraft.world.entity.projectile.ThrownEgg; - import net.minecraft.world.entity.projectile.ThrownEnderpearl; - import net.minecraft.world.entity.projectile.ThrownExperienceBottle; - import net.minecraft.world.entity.projectile.ThrownTrident; -+import net.minecraft.world.level.ClipContext; - import net.minecraft.world.phys.BlockHitResult; -+import net.minecraft.world.phys.EntityHitResult; - import net.minecraft.world.phys.HitResult; -+import net.minecraft.world.phys.Vec3; - import org.apache.commons.lang.Validate; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -215,6 +219,33 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - new TargetBlockInfo(CraftBlock.at(getHandle().level, ((BlockHitResult)rayTrace).getBlockPos()), - MCUtil.toBukkitBlockFace(((BlockHitResult)rayTrace).getDirection())); - } -+ -+ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks) { -+ EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); -+ return rayTrace == null ? null : rayTrace.getEntity().getBukkitEntity(); -+ } -+ -+ public TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks) { -+ EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); -+ return rayTrace == null ? null : new TargetEntityInfo(rayTrace.getEntity().getBukkitEntity(), new org.bukkit.util.Vector(rayTrace.getLocation().x, rayTrace.getLocation().y, rayTrace.getLocation().z)); -+ } -+ -+ public EntityHitResult rayTraceEntity(int maxDistance, boolean ignoreBlocks) { -+ EntityHitResult rayTrace = getHandle().getTargetEntity(maxDistance); -+ if (rayTrace == null) { -+ return null; -+ } -+ if (!ignoreBlocks) { -+ HitResult rayTraceBlocks = getHandle().getRayTrace(maxDistance, ClipContext.Fluid.NONE); -+ if (rayTraceBlocks != null) { -+ Vec3 eye = getHandle().getEyePosition(1.0F); -+ if (eye.distanceToSqr(rayTraceBlocks.getLocation()) <= eye.distanceToSqr(rayTrace.getLocation())) { -+ return null; -+ } -+ } -+ } -+ return rayTrace; -+ } - // Paper end - - @Override diff --git a/patches/server-remapped/0291-Catch-JsonParseException-in-Entity-and-TE-names.patch b/patches/server/0268-Catch-JsonParseException-in-Entity-and-TE-names.patch similarity index 68% rename from patches/server-remapped/0291-Catch-JsonParseException-in-Entity-and-TE-names.patch rename to patches/server/0268-Catch-JsonParseException-in-Entity-and-TE-names.patch index a418dc54d3..0493d912d5 100644 --- a/patches/server-remapped/0291-Catch-JsonParseException-in-Entity-and-TE-names.patch +++ b/patches/server/0268-Catch-JsonParseException-in-Entity-and-TE-names.patch @@ -13,10 +13,10 @@ Shulkers) may need to be changed in order for it to re-save properly No more crashing though. diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 68c3f069f8f832ab3d146748348aded69b5ad823..1fecc81b25109592907623741225a6222a8c5ccc 100644 +index 5c290f263fc2b643987c96ea75729bf1ff493760..0df3961919f04f27eb265ab316aa5a0f15a70854 100644 --- a/src/main/java/net/minecraft/server/MCUtil.java +++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -7,6 +7,8 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; +@@ -6,6 +6,8 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -25,11 +25,10 @@ index 68c3f069f8f832ab3d146748348aded69b5ad823..1fecc81b25109592907623741225a622 import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.ChunkPos; -@@ -514,4 +516,19 @@ public final class MCUtil { - return null; +@@ -513,6 +515,21 @@ public final class MCUtil { } } -+ + + @Nullable + public static Component getBaseComponentFromNbt(String key, CompoundTag compound) { + if (!compound.contains(key)) { @@ -44,9 +43,12 @@ index 68c3f069f8f832ab3d146748348aded69b5ad823..1fecc81b25109592907623741225a622 + + return null; + } - } ++ + public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) { + return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status); + } diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java -index 9ad077259563a3d960d32a59d4b6fc3cfbe3440c..00dc4cd436023b946d7005f17a7ba983a4bbdfb6 100644 +index 04a3627667498b841fbff547d1874d99cc708af4..2e6172930526efc536a214e420e690a5ea42ac3e 100644 --- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java @@ -12,6 +12,7 @@ import net.minecraft.commands.CommandSourceStack; @@ -57,20 +59,20 @@ index 9ad077259563a3d960d32a59d4b6fc3cfbe3440c..00dc4cd436023b946d7005f17a7ba983 import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.StringUtil; -@@ -72,7 +73,7 @@ public abstract class BaseCommandBlock implements CommandSource { - this.command = tag.getString("Command"); - this.successCount = tag.getInt("SuccessCount"); - if (tag.contains("CustomName", 8)) { -- this.setName(Component.Serializer.fromJson(tag.getString("CustomName"))); -+ this.setName(MCUtil.getBaseComponentFromNbt("CustomName", tag)); // Paper - Catch ParseException +@@ -73,7 +74,7 @@ public abstract class BaseCommandBlock implements CommandSource { + this.command = nbt.getString("Command"); + this.successCount = nbt.getInt("SuccessCount"); + if (nbt.contains("CustomName", 8)) { +- this.setName(Component.Serializer.fromJson(nbt.getString("CustomName"))); ++ this.setName(MCUtil.getBaseComponentFromNbt("CustomName", nbt)); // Paper - Catch ParseException } - if (tag.contains("TrackOutput", 1)) { + if (nbt.contains("TrackOutput", 1)) { diff --git a/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java -index 2e3ec85e7bd1c375db0662dba2617d8924dbd2a6..2c885be67b9c992b96f5caf78130d46abb455ceb 100644 +index e07c9e7e37a2c6aa3fc4b7fdc2d547d9c8a2177e..83f27ede626fc7e263acf2c9417a2c2699e4c79a 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java -@@ -9,6 +9,7 @@ import net.minecraft.nbt.ListTag; +@@ -10,6 +10,7 @@ import net.minecraft.nbt.ListTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; @@ -78,20 +80,20 @@ index 2e3ec85e7bd1c375db0662dba2617d8924dbd2a6..2c885be67b9c992b96f5caf78130d46a import net.minecraft.world.Nameable; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; -@@ -70,7 +71,7 @@ public class BannerBlockEntity extends BlockEntity implements Nameable { - public void load(BlockState state, CompoundTag tag) { - super.load(state, tag); - if (tag.contains("CustomName", 8)) { -- this.name = Component.Serializer.fromJson(tag.getString("CustomName")); -+ this.name = MCUtil.getBaseComponentFromNbt("CustomName", tag); // Paper - Catch ParseException +@@ -95,7 +96,7 @@ public class BannerBlockEntity extends BlockEntity implements Nameable { + public void load(CompoundTag nbt) { + super.load(nbt); + if (nbt.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(nbt.getString("CustomName")); ++ this.name = MCUtil.getBaseComponentFromNbt("CustomName", nbt); // Paper - Catch ParseException } - if (this.hasLevel()) { + this.itemPatterns = nbt.getList("Patterns", 10); diff --git a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -index a7358274fe367a113b304a5ce332b8dcf721b7af..2b420109e9bed184aaa4ffbcee666b4c325c5a28 100644 +index 16fd9b356fee79b56893fe0a7c71721ae81664ab..67e39ebc7984d47bdf9081c24cb26845d70b83bb 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -@@ -4,6 +4,7 @@ import javax.annotation.Nullable; +@@ -5,6 +5,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TranslatableComponent; @@ -99,12 +101,12 @@ index a7358274fe367a113b304a5ce332b8dcf721b7af..2b420109e9bed184aaa4ffbcee666b4c import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.world.Container; -@@ -30,7 +31,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co - super.load(state, tag); - this.lockKey = LockCode.fromTag(tag); - if (tag.contains("CustomName", 8)) { -- this.name = Component.Serializer.fromJson(tag.getString("CustomName")); -+ this.name = MCUtil.getBaseComponentFromNbt("CustomName", tag); // Paper - Catch ParseException +@@ -31,7 +32,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co + super.load(nbt); + this.lockKey = LockCode.fromTag(nbt); + if (nbt.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(nbt.getString("CustomName")); ++ this.name = MCUtil.getBaseComponentFromNbt("CustomName", nbt); // Paper - Catch ParseException } } diff --git a/patches/server/0269-Honor-EntityAgeable.ageLock.patch b/patches/server/0269-Honor-EntityAgeable.ageLock.patch new file mode 100644 index 0000000000..369899cfee --- /dev/null +++ b/patches/server/0269-Honor-EntityAgeable.ageLock.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Sep 2018 20:59:53 -0500 +Subject: [PATCH] Honor EntityAgeable.ageLock + + +diff --git a/src/main/java/net/minecraft/world/entity/AgeableMob.java b/src/main/java/net/minecraft/world/entity/AgeableMob.java +index 123b125a3576903767983c93135086ca7a8ea813..c0780a8714808498390282b7fa1da1f3aacf8e2a 100644 +--- a/src/main/java/net/minecraft/world/entity/AgeableMob.java ++++ b/src/main/java/net/minecraft/world/entity/AgeableMob.java +@@ -84,6 +84,7 @@ public abstract class AgeableMob extends PathfinderMob { + } + + public void ageUp(int age, boolean overGrow) { ++ if (ageLocked) return; // Paper - GH-1459 + int j = this.getAge(); + int k = j; + diff --git a/patches/server-remapped/0293-Configurable-connection-throttle-kick-message.patch b/patches/server/0270-Configurable-connection-throttle-kick-message.patch similarity index 75% rename from patches/server-remapped/0293-Configurable-connection-throttle-kick-message.patch rename to patches/server/0270-Configurable-connection-throttle-kick-message.patch index 354aa4e66c..a475aa02f5 100644 --- a/patches/server-remapped/0293-Configurable-connection-throttle-kick-message.patch +++ b/patches/server/0270-Configurable-connection-throttle-kick-message.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable connection throttle kick message diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 62621562137cba4804f0465c58d25ca2786328e5..7178b37f7978c7e9031a22726005c5099fd78fe0 100644 +index ee8ead249d89bc81f87bfff6a1f594a9aeb21250..585be2fcbd63a59f911df69136eae07ce665053c 100644 --- a/src/main/java/com/destroystokyo/paper/PaperConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -281,6 +281,11 @@ public class PaperConfig { +@@ -282,6 +282,11 @@ public class PaperConfig { authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); } @@ -21,13 +21,13 @@ index 62621562137cba4804f0465c58d25ca2786328e5..7178b37f7978c7e9031a22726005c509 Object val = config.get("settings.save-player-data"); if (val instanceof Boolean) { diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -index 45c9dc9c2a580a5cd57fd4e891fbaa2b1336f5c5..6f98be2b9b00f71dd041e7511c70166fdecf0749 100644 +index 484221e5a9c246aa91e0eacef3911b0e9ecff401..c09d3cdb3acb04b6a833c30a619ff2af5e8b6b18 100644 --- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java @@ -50,7 +50,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - synchronized (throttleTracker) { - if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { - throttleTracker.put(address, currentTime); + synchronized (ServerHandshakePacketListenerImpl.throttleTracker) { + if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) { + ServerHandshakePacketListenerImpl.throttleTracker.put(address, currentTime); - TranslatableComponent chatmessage = new TranslatableComponent("Connection throttled! Please wait before reconnecting."); + TranslatableComponent chatmessage = new TranslatableComponent(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); diff --git a/patches/server-remapped/0294-Hook-into-CB-plugin-rewrites.patch b/patches/server/0271-Hook-into-CB-plugin-rewrites.patch similarity index 98% rename from patches/server-remapped/0294-Hook-into-CB-plugin-rewrites.patch rename to patches/server/0271-Hook-into-CB-plugin-rewrites.patch index 06025aa8c5..3f5cb35595 100644 --- a/patches/server-remapped/0294-Hook-into-CB-plugin-rewrites.patch +++ b/patches/server/0271-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 45cbdcfc131bbc0e2bf23cc30a572df72eecd51c..49e5a86c223f1b28ce7da6ced276b2f880777856 100644 +index a79c62e1c3ee49ada505c07b1171b439beeb4bdf..cbf630243410f97c21b14f654e81dc96b0323b70 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java +++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java @@ -6,7 +6,9 @@ import java.io.FileOutputStream; @@ -167,7 +167,7 @@ index 45cbdcfc131bbc0e2bf23cc30a572df72eecd51c..49e5a86c223f1b28ce7da6ced276b2f8 if ( owner.equals( "org/bukkit/block/Biome" ) ) { switch ( name ) -@@ -270,6 +384,14 @@ public class Commodore +@@ -273,6 +387,14 @@ public class Commodore return; } diff --git a/patches/server-remapped/0296-Add-sun-related-API.patch b/patches/server/0272-Add-sun-related-API.patch similarity index 68% rename from patches/server-remapped/0296-Add-sun-related-API.patch rename to patches/server/0272-Add-sun-related-API.patch index 32037c620c..f3352dd107 100644 --- a/patches/server-remapped/0296-Add-sun-related-API.patch +++ b/patches/server/0272-Add-sun-related-API.patch @@ -5,22 +5,23 @@ Subject: [PATCH] Add sun related API diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index f3690ea49cf90c816b8b3554b47d6f2d9dfbe016..29a2eeee9f2011ed6fcc44f19041f616decfdb38 100644 +index 8451baff82cb7ec7615ab50a409724897ccf4d95..32e8ae0d2a0f78af671a632c4d1be58a0b38a392 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -1595,6 +1595,7 @@ public abstract class Mob extends LivingEntity { +@@ -1561,7 +1561,7 @@ public abstract class Mob extends LivingEntity { } -+ public boolean isInDaylight() { return this.isSunBurnTick(); } // Paper - OBFHELPER - protected boolean isSunBurnTick() { +- protected boolean isSunBurnTick() { ++ public boolean isSunBurnTick() { // Paper - protected -> public if (this.level.isDay() && !this.level.isClientSide) { float f = this.getBrightness(); + BlockPos blockposition = new BlockPos(this.getX(), this.getEyeY(), this.getZ()); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 57a2af56b53567371fdb6d0a55866e1e4e37cf3b..7b5abccac9793811bd56340c8f9d23806e832365 100644 +index b8565aa86b478adb6fca6d433637ddb342ce6dcb..fda8858375a08e0aac15ca00751df5a34ed6a0f2 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -847,6 +847,13 @@ public class CraftWorld implements World { +@@ -866,6 +866,13 @@ public class CraftWorld implements World { } } @@ -35,18 +36,18 @@ index 57a2af56b53567371fdb6d0a55866e1e4e37cf3b..7b5abccac9793811bd56340c8f9d2380 public long getGameTime() { return world.levelData.getGameTime(); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index b5fe55a77c8558cf2ea32689ff57911530df75f9..1e3a0851c75d8067d2699f00bb3f6621d1d739d8 100644 +index 9c9fa83615cd06539ce5e4e3d4feaa69f65b7931..317b6abd2764cf34ef5c42bdbf48ab0bc5a03d27 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java @@ -77,4 +77,11 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { public long getSeed() { - return getHandle().lootTableSeed; + return this.getHandle().lootTableSeed; } + + // Paper start + @Override + public boolean isInDaylight() { -+ return getHandle().isInDaylight(); ++ return getHandle().isSunBurnTick(); + } + // Paper end } diff --git a/patches/server/0273-Add-LivingEntity-getTargetEntity.patch b/patches/server/0273-Add-LivingEntity-getTargetEntity.patch new file mode 100644 index 0000000000..3b34a48c14 --- /dev/null +++ b/patches/server/0273-Add-LivingEntity-getTargetEntity.patch @@ -0,0 +1,114 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sat, 22 Sep 2018 00:33:08 -0500 +Subject: [PATCH] Add LivingEntity#getTargetEntity + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 960c3e75a60ef33141e615bd8b256528eeaf399c..0974781e2f7fc541eaf397de033fb12b87dbf8ba 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2339,6 +2339,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + this.setYHeadRot(yaw); + } + ++ public final float getCollisionBorderSize() { return getPickRadius(); } // Paper - OBFHELPER + public float getPickRadius() { + return 0.0F; + } +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index fd0c307a4b340661ba9aff9ae4e0055c139a1ebd..8333d604fce05349455bf1779f3e5b0a980c4c16 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -116,6 +116,7 @@ import net.minecraft.world.level.storage.loot.LootTable; + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.PlayerTeam; +@@ -3730,6 +3731,38 @@ public abstract class LivingEntity extends Entity { + return level.clip(raytrace); + } + ++ public EntityHitResult getTargetEntity(int maxDistance) { ++ if (maxDistance < 1 || maxDistance > 120) { ++ throw new IllegalArgumentException("maxDistance must be between 1-120"); ++ } ++ ++ Vec3 start = this.getEyePosition(1.0F); ++ Vec3 direction = this.getLookAngle(); ++ Vec3 end = start.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance); ++ ++ List entityList = level.getEntities(this, getBoundingBox().expandTowards(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance).inflate(1.0D, 1.0D, 1.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR.and(Entity::isPickable)); ++ ++ double distance = 0.0D; ++ EntityHitResult result = null; ++ ++ for (Entity entity : entityList) { ++ final double inflationAmount = (double) entity.getCollisionBorderSize(); ++ AABB aabb = entity.getBoundingBox().inflate(inflationAmount, inflationAmount, inflationAmount); ++ Optional rayTraceResult = aabb.clip(start, end); ++ ++ if (rayTraceResult.isPresent()) { ++ Vec3 rayTrace = rayTraceResult.get(); ++ double distanceTo = start.distanceToSqr(rayTrace); ++ if (distanceTo < distance || distance == 0.0D) { ++ result = new EntityHitResult(entity, rayTrace); ++ distance = distanceTo; ++ } ++ } ++ } ++ ++ return result; ++ } ++ + public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; + + public int getShieldBlockingDelay() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index cb4c15d17ea3f22e6baa73ba6ce2a18e34ac4b00..5477f288db57d63051f4579b8cd3c19e3af430ee 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import com.destroystokyo.paper.entity.TargetEntityInfo; + import com.google.common.base.Preconditions; + import com.google.common.collect.Sets; + import java.util.ArrayList; +@@ -210,6 +211,33 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + new com.destroystokyo.paper.block.TargetBlockInfo(org.bukkit.craftbukkit.block.CraftBlock.at(getHandle().level, ((net.minecraft.world.phys.BlockHitResult)rayTrace).getBlockPos()), + net.minecraft.server.MCUtil.toBukkitBlockFace(((net.minecraft.world.phys.BlockHitResult)rayTrace).getDirection())); + } ++ ++ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks) { ++ net.minecraft.world.phys.EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); ++ return rayTrace == null ? null : rayTrace.getEntity().getBukkitEntity(); ++ } ++ ++ public TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks) { ++ net.minecraft.world.phys.EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); ++ return rayTrace == null ? null : new TargetEntityInfo(rayTrace.getEntity().getBukkitEntity(), new org.bukkit.util.Vector(rayTrace.getLocation().x, rayTrace.getLocation().y, rayTrace.getLocation().z)); ++ } ++ ++ public net.minecraft.world.phys.EntityHitResult rayTraceEntity(int maxDistance, boolean ignoreBlocks) { ++ net.minecraft.world.phys.EntityHitResult rayTrace = getHandle().getTargetEntity(maxDistance); ++ if (rayTrace == null) { ++ return null; ++ } ++ if (!ignoreBlocks) { ++ net.minecraft.world.phys.HitResult rayTraceBlocks = getHandle().getRayTrace(maxDistance, net.minecraft.world.level.ClipContext.Fluid.NONE); ++ if (rayTraceBlocks != null) { ++ net.minecraft.world.phys.Vec3 eye = getHandle().getEyePosition(1.0F); ++ if (eye.distanceToSqr(rayTraceBlocks.getLocation()) <= eye.distanceToSqr(rayTrace.getLocation())) { ++ return null; ++ } ++ } ++ } ++ return rayTrace; ++ } + // Paper end + + @Override diff --git a/patches/server-remapped/0297-Turtle-API.patch b/patches/server/0274-Turtle-API.patch similarity index 74% rename from patches/server-remapped/0297-Turtle-API.patch rename to patches/server/0274-Turtle-API.patch index 042449088a..4a809a1352 100644 --- a/patches/server-remapped/0297-Turtle-API.patch +++ b/patches/server/0274-Turtle-API.patch @@ -5,23 +5,23 @@ Subject: [PATCH] Turtle API diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -index 4584fad16a65f06e77e97a0804d88dbe83f7c5c1..c8680e795deeb68e0662eac7c760a103d1c767b4 100644 +index 70a51ba19fb34f652858b18f24554261787d97e2..065d0752db0e3ae2a89d707aaa2145807f50ecad 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java @@ -14,7 +14,7 @@ public abstract class MoveToBlockGoal extends Goal { protected int nextStartTick; protected int tryTicks; private int maxStayTicks; -- protected BlockPos blockPos; -+ protected BlockPos blockPos;public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER +- protected BlockPos blockPos = BlockPos.ZERO; ++ protected BlockPos blockPos = BlockPos.ZERO; public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER private boolean reachedTarget; private final int searchRange; private final int verticalSearchRange; diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index c54f4b83b9f2fdb15ddb363be0a179a05eb3693b..42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3 100644 +index b782d278463a72b8514719e9b14986f268828772..e638d982b4bd1d261a7282cad6dab98ad0b55213 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java +++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -@@ -14,6 +14,7 @@ import net.minecraft.nbt.CompoundTag; +@@ -11,6 +11,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; @@ -33,56 +33,50 @@ index c54f4b83b9f2fdb15ddb363be0a179a05eb3693b..42b636c4ebb6eb83c8a9f3f5f9a766d3 this.entityData.set(Turtle.HOME_POS, pos); } -- private BlockPos getHomePos() { +- BlockPos getHomePos() { + public BlockPos getHomePos() { // Paper - public return (BlockPos) this.entityData.get(Turtle.HOME_POS); } -@@ -109,31 +110,37 @@ public class Turtle extends Animal { +@@ -109,7 +110,7 @@ public class Turtle extends Animal { return (Boolean) this.entityData.get(Turtle.HAS_EGG); } -- private void setHasEgg(boolean hasEgg) { +- void setHasEgg(boolean hasEgg) { + public void setHasEgg(boolean hasEgg) { // Paper this.entityData.set(Turtle.HAS_EGG, hasEgg); } -+ public final boolean isDigging() { return this.isLayingEgg(); } // Paper - OBFHELPER - public boolean isLayingEgg() { - return (Boolean) this.entityData.get(Turtle.LAYING_EGG); - } - -+ public final void setDigging(boolean digging) { this.setLayingEgg(digging); } // Paper - OBFHELPER - private void setLayingEgg(boolean diggingSand) { - this.layEggCounter = diggingSand ? 1 : 0; +@@ -122,19 +123,19 @@ public class Turtle extends Animal { this.entityData.set(Turtle.LAYING_EGG, diggingSand); } -+ public final boolean isGoingHome() { return this.isGoingHome(); } // Paper - OBFHELPER - private boolean isGoingHome() { +- boolean isGoingHome() { ++ public boolean isGoingHome() { // Paper - public return (Boolean) this.entityData.get(Turtle.GOING_HOME); } -+ public final void setGoingHome(boolean goingHome) { this.setGoingHome(goingHome); } // Paper - OBFHELPER - private void setGoingHome(boolean landBound) { +- void setGoingHome(boolean landBound) { ++ public void setGoingHome(boolean landBound) { // Paper - public this.entityData.set(Turtle.GOING_HOME, landBound); } -+ public final boolean isTravelling() { return this.isTravelling(); } // Paper - OBFHELPER - private boolean isTravelling() { +- boolean isTravelling() { ++ public boolean isTravelling() { // Paper - public return (Boolean) this.entityData.get(Turtle.TRAVELLING); } -+ public final void setTravelling(boolean travelling) { this.setTravelling(travelling); } // Paper - OBFHELPER - private void setTravelling(boolean travelling) { +- void setTravelling(boolean travelling) { ++ public void setTravelling(boolean travelling) { // Paper - public this.entityData.set(Turtle.TRAVELLING, travelling); } -@@ -500,14 +507,17 @@ public class Turtle extends Animal { + +@@ -487,14 +488,17 @@ public class Turtle extends Animal { if (!this.turtle.isInWater() && this.isReachedTarget()) { if (this.turtle.layEggCounter < 1) { - this.turtle.setLayingEgg(true); -+ this.turtle.setDigging(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), MCUtil.toLocation(this.turtle.level, this.getTargetPosition())).callEvent()); // Paper ++ this.turtle.setLayingEgg(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), MCUtil.toLocation(this.turtle.level, this.getTargetPosition())).callEvent()); // Paper } else if (this.turtle.layEggCounter > 200) { Level world = this.turtle.level; @@ -98,7 +92,7 @@ index c54f4b83b9f2fdb15ddb363be0a179a05eb3693b..42b636c4ebb6eb83c8a9f3f5f9a766d3 } // CraftBukkit end this.turtle.setHasEgg(false); -@@ -636,7 +646,7 @@ public class Turtle extends Animal { +@@ -562,7 +566,7 @@ public class Turtle extends Animal { @Override public boolean canUse() { @@ -108,7 +102,7 @@ index c54f4b83b9f2fdb15ddb363be0a179a05eb3693b..42b636c4ebb6eb83c8a9f3f5f9a766d3 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -index ed08089f21c8958fc9fc7e6e73a2b6ff9108242c..e50f6051baf34981707adce56ab2d3e1f341fb4c 100644 +index ed08089f21c8958fc9fc7e6e73a2b6ff9108242c..a3849ebba14b47b33f1af57c47f94c02aebea232 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java @@ -24,4 +24,36 @@ public class CraftTurtle extends CraftAnimals implements Turtle { @@ -134,7 +128,7 @@ index ed08089f21c8958fc9fc7e6e73a2b6ff9108242c..e50f6051baf34981707adce56ab2d3e1 + + @Override + public boolean isDigging() { -+ return getHandle().isDigging(); ++ return getHandle().isLayingEgg(); + } + + @Override diff --git a/patches/server/0275-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/patches/server/0275-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch new file mode 100644 index 0000000000..ec2c3e732c --- /dev/null +++ b/patches/server/0275-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 17 Oct 2018 19:17:27 -0400 +Subject: [PATCH] MC-50319: Check other worlds for shooter of projectiles + +Say a player shoots an arrow through a nether portal, the game +would lose the shooter for determining things such as Player Kills, +because the entity is in another world. + +If the projectile fails to find the shooter in the current world, check +other worlds. + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index 30118ff975da9491fa41db2133d217c2a797a8e3..7311923d36ee872b4331d84f80709bb6cee61086 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -57,6 +57,18 @@ public abstract class Projectile extends Entity { + return this.cachedOwner; + } else if (this.ownerUUID != null && this.level instanceof ServerLevel) { + this.cachedOwner = ((ServerLevel) this.level).getEntity(this.ownerUUID); ++ // Paper start - check all worlds ++ if (this.cachedOwner == null) { ++ for (final ServerLevel level : this.level.getServer().getAllLevels()) { ++ if (level == this.level) continue; ++ final Entity entity = level.getEntity(this.ownerUUID); ++ if (entity != null) { ++ this.cachedOwner = entity; ++ break; ++ } ++ } ++ } ++ // Paper end + return this.cachedOwner; + } else { + return null; diff --git a/patches/server-remapped/0299-Call-player-spectator-target-events-and-improve-impl.patch b/patches/server/0276-Call-player-spectator-target-events-and-improve-impl.patch similarity index 73% rename from patches/server-remapped/0299-Call-player-spectator-target-events-and-improve-impl.patch rename to patches/server/0276-Call-player-spectator-target-events-and-improve-impl.patch index 4b6ccafcaa..3775abd05d 100644 --- a/patches/server-remapped/0299-Call-player-spectator-target-events-and-improve-impl.patch +++ b/patches/server/0276-Call-player-spectator-target-events-and-improve-impl.patch @@ -19,10 +19,10 @@ spectate the target entity. Co-authored-by: Spottedleaf diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 75419c866641ab654349cde6ca3fbdef701dd8d9..92139b271eb6c305787662ef8c7d221fb42296f7 100644 +index bea1461ee3bd65f02bf6add6ed967555092fd675..b2324b53b3cec3e577a8ec8c45b113c232d220a6 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1818,14 +1818,58 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1822,14 +1822,58 @@ public class ServerPlayer extends Player { } public void setCamera(Entity entity) { @@ -32,7 +32,7 @@ index 75419c866641ab654349cde6ca3fbdef701dd8d9..92139b271eb6c305787662ef8c7d221f - this.camera = (Entity) (entity == null ? this : entity); - if (entity1 != this.camera) { - this.connection.send(new ClientboundSetCameraPacket(this.camera)); -- this.connection.a(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.yRot, this.xRot, TeleportCause.SPECTATE); // CraftBukkit +- this.connection.b(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.getYRot(), this.getXRot(), TeleportCause.SPECTATE); // CraftBukkit + if (entity == null) { + entity = this; } @@ -54,7 +54,7 @@ index 75419c866641ab654349cde6ca3fbdef701dd8d9..92139b271eb6c305787662ef8c7d221f + } + // Validate + if (entity != this) { -+ if (entity.removed || entity.shouldBeRemoved || !entity.valid || entity.level == null) { ++ if (entity.isRemoved() || !entity.valid || entity.level == null) { + MinecraftServer.LOGGER.info("Blocking player " + this.toString() + " from spectating invalid entity " + entity.toString()); + return; + } @@ -70,7 +70,7 @@ index 75419c866641ab654349cde6ca3fbdef701dd8d9..92139b271eb6c305787662ef8c7d221f + if (entity != this) { + // Make sure we're in the right place + this.ejectPassengers(); // teleport can fail if we have passengers... -+ this.getBukkitEntity().teleport(new Location(entity.getCommandSenderWorld().getWorld(), entity.getX(), entity.getY(), entity.getZ(), this.yRot, this.xRot), TeleportCause.SPECTATE); // Correctly handle cross-world entities from api calls by using CB teleport ++ this.getBukkitEntity().teleport(new Location(entity.getCommandSenderWorld().getWorld(), entity.getX(), entity.getY(), entity.getZ(), this.getYRot(), this.getXRot()), TeleportCause.SPECTATE); // Correctly handle cross-world entities from api calls by using CB teleport + + // Make sure we're tracking the entity before sending + ChunkMap.TrackedEntity tracker = ((ServerLevel)entity.level).getChunkSource().chunkMap.entityMap.get(entity.getId()); @@ -78,7 +78,7 @@ index 75419c866641ab654349cde6ca3fbdef701dd8d9..92139b271eb6c305787662ef8c7d221f + tracker.updatePlayer(this); + } + } else { -+ this.connection.teleport(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.yRot, this.xRot, TeleportCause.SPECTATE); // CraftBukkit ++ this.connection.teleport(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.getYRot(), this.getXRot(), TeleportCause.SPECTATE); // CraftBukkit + } + this.connection.send(new ClientboundSetCameraPacket(entity)); + // Paper end @@ -86,14 +86,23 @@ index 75419c866641ab654349cde6ca3fbdef701dd8d9..92139b271eb6c305787662ef8c7d221f @Override diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 900c9b1106a153bc386f6c3d9c11226f8ac69f86..4fd8d775790c037e82f9b0d29ed0eccf03c2dc66 100644 +index a29b8c83be940e4b3db06d881b59b03120e931ab..06922b26ca1f2e31f7c8a527f1a8fdda4a8554c0 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1353,6 +1353,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1068,7 +1068,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } + } + +- private void a(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack old) { // CraftBukkit ++ public void a(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack old) { // CraftBukkit // Paper - make public + ListTag nbttaglist = new ListTag(); + + if (this.player.isTextFilteringEnabled()) { +@@ -1381,6 +1381,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + this.a(x, y, z, yaw, pitch, PlayerTeleportEvent.TeleportCause.UNKNOWN); } - // CraftBukkit start - Delegate to teleport(Location) + public final void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { this.a(d0, d1, d2, f, f1, cause); } // Paper - OBFHELPER public void a(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { - this.a(d0, d1, d2, f, f1, Collections.emptySet(), cause); + this.a(d0, d1, d2, f, f1, Collections.emptySet(), true, cause); } diff --git a/patches/server-remapped/0300-Add-Velocity-IP-Forwarding-Support.patch b/patches/server/0277-Add-Velocity-IP-Forwarding-Support.patch similarity index 63% rename from patches/server-remapped/0300-Add-Velocity-IP-Forwarding-Support.patch rename to patches/server/0277-Add-Velocity-IP-Forwarding-Support.patch index f1b44575c0..1fa12ab51f 100644 --- a/patches/server-remapped/0300-Add-Velocity-IP-Forwarding-Support.patch +++ b/patches/server/0277-Add-Velocity-IP-Forwarding-Support.patch @@ -14,10 +14,10 @@ forwarding, and is integrated into the Minecraft login process by using the 1.13 login plugin message packet. diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 7178b37f7978c7e9031a22726005c5099fd78fe0..3139c194f9b1bc3510d51a81f13ae43d00a3dc29 100644 +index 585be2fcbd63a59f911df69136eae07ce665053c..9768c591e72ce2ef5fdb43e2fc63378c57773216 100644 --- a/src/main/java/com/destroystokyo/paper/PaperConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -8,6 +8,7 @@ import java.io.IOException; +@@ -9,6 +9,7 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -25,7 +25,7 @@ index 7178b37f7978c7e9031a22726005c5099fd78fe0..3139c194f9b1bc3510d51a81f13ae43d import java.util.HashMap; import java.util.List; import java.util.Map; -@@ -252,7 +253,7 @@ public class PaperConfig { +@@ -253,7 +254,7 @@ public class PaperConfig { } public static boolean isProxyOnlineMode() { @@ -34,11 +34,10 @@ index 7178b37f7978c7e9031a22726005c5099fd78fe0..3139c194f9b1bc3510d51a81f13ae43d } public static int packetInSpamThreshold = 300; -@@ -324,4 +325,18 @@ public class PaperConfig { - } +@@ -326,6 +327,20 @@ public class PaperConfig { tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); } -+ + + public static boolean velocitySupport; + public static boolean velocityOnlineMode; + public static byte[] velocitySecretKey; @@ -52,10 +51,13 @@ index 7178b37f7978c7e9031a22726005c5099fd78fe0..3139c194f9b1bc3510d51a81f13ae43d + velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); + } + } - } ++ + public static boolean asyncChunks = false; + private static void asyncChunks() { + ConfigurationSection section; diff --git a/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java new file mode 100644 -index 0000000000000000000000000000000000000000..5490ddb9f2ff1fc3e6088e703c246a06594076bc +index 0000000000000000000000000000000000000000..41d73aa91fb401612e087aa1b7278ba61d28bf3a --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java @@ -0,0 +1,66 @@ @@ -106,11 +108,11 @@ index 0000000000000000000000000000000000000000..5490ddb9f2ff1fc3e6088e703c246a06 + } + + public static InetAddress readAddress(final FriendlyByteBuf buf) { -+ return InetAddresses.forString(buf.readUTF(Short.MAX_VALUE)); ++ return InetAddresses.forString(buf.readUtf(Short.MAX_VALUE)); + } + + public static GameProfile createProfile(final FriendlyByteBuf buf) { -+ final GameProfile profile = new GameProfile(buf.readUUID(), buf.readUTF(16)); ++ final GameProfile profile = new GameProfile(buf.readUUID(), buf.readUtf(16)); + readProperties(buf, profile); + return profile; + } @@ -118,80 +120,18 @@ index 0000000000000000000000000000000000000000..5490ddb9f2ff1fc3e6088e703c246a06 + private static void readProperties(final FriendlyByteBuf buf, final GameProfile profile) { + final int properties = buf.readVarInt(); + for (int i1 = 0; i1 < properties; i1++) { -+ final String name = buf.readUTF(Short.MAX_VALUE); -+ final String value = buf.readUTF(Short.MAX_VALUE); -+ final String signature = buf.readBoolean() ? buf.readUTF(Short.MAX_VALUE) : null; ++ final String name = buf.readUtf(Short.MAX_VALUE); ++ final String value = buf.readUtf(Short.MAX_VALUE); ++ final String signature = buf.readBoolean() ? buf.readUtf(Short.MAX_VALUE) : null; + profile.getProperties().put(name, new Property(name, value, signature)); + } + } +} -diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -index 10f1e3d761af83507bf71a00092641e22d0c8049..a295845409824b930992426451ef26856d6e7c36 100644 ---- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java -+++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java -@@ -191,6 +191,7 @@ public class FriendlyByteBuf extends ByteBuf { - return this.writeVarInt(oenum.ordinal()); - } - -+ public int readVarInt() { return readVarInt(); } // Paper - OBFHELPER - public int readVarInt() { - int i = 0; - int j = 0; -@@ -231,6 +232,7 @@ public class FriendlyByteBuf extends ByteBuf { - return this; - } - -+ public UUID readUUID() { return readUUID(); } // Paper - OBFHELPER - public UUID readUUID() { - return new UUID(this.readLong(), this.readLong()); - } -@@ -358,6 +360,7 @@ public class FriendlyByteBuf extends ByteBuf { - } - } - -+ public String readUTF(int maxLength) { return this.readUtf(maxLength); } // Paper - OBFHELPER - public String readUtf(int i) { - int j = this.readVarInt(); - -diff --git a/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java b/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java -index 8a0301cc4a411c4f9384331d68794ca73b797f5f..88a63635d73983afe58406c66f4ea81cd823c627 100644 ---- a/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/login/ClientboundCustomQueryPacket.java -@@ -13,6 +13,14 @@ public class ClientboundCustomQueryPacket implements Packet { - -- private int transactionId; -- private FriendlyByteBuf data; -+ private int transactionId; public int getId() { return transactionId; } // Paper - OBFHELPER -+ private FriendlyByteBuf data; public FriendlyByteBuf getBuf() { return data; } // Paper - OBFHELPER - - public ServerboundCustomQueryPacket() {} - diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 0aa3a154d68f00edcc09b947a24b2b59b1e135e6..22d6f41001977917ec75046252cbf7157b92396d 100644 +index 1d05725374bdffad6a8ab1502ee732775345024d..a196ab2510a1c302ef1c946400c1a7c07619994a 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -18,9 +18,11 @@ import javax.crypto.Cipher; +@@ -18,6 +18,7 @@ import javax.crypto.Cipher; import javax.crypto.SecretKey; import net.minecraft.DefaultUncaughtExceptionHandler; import net.minecraft.network.Connection; @@ -199,11 +139,7 @@ index 0aa3a154d68f00edcc09b947a24b2b59b1e135e6..22d6f41001977917ec75046252cbf715 import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TranslatableComponent; -+import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; - import net.minecraft.network.protocol.login.ClientboundGameProfilePacket; - import net.minecraft.network.protocol.login.ClientboundHelloPacket; - import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; -@@ -43,6 +45,7 @@ import org.bukkit.craftbukkit.util.Waitable; +@@ -44,6 +45,7 @@ import org.bukkit.craftbukkit.util.Waitable; import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.PlayerPreLoginEvent; // CraftBukkit end @@ -211,22 +147,22 @@ index 0aa3a154d68f00edcc09b947a24b2b59b1e135e6..22d6f41001977917ec75046252cbf715 public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener { -@@ -59,6 +62,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - private SecretKey secretKey; +@@ -62,6 +64,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + @Nullable private ServerPlayer delayedAcceptPlayer; public String hostname = ""; // CraftBukkit - add field + private int velocityLoginMessageId = -1; // Paper - Velocity support public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection) { this.state = ServerLoginPacketListenerImpl.State.HELLO; -@@ -211,6 +215,14 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -233,6 +236,14 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener this.state = ServerLoginPacketListenerImpl.State.KEY; this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce)); } else { + // Paper start - Velocity support + if (com.destroystokyo.paper.PaperConfig.velocitySupport) { + this.velocityLoginMessageId = java.util.concurrent.ThreadLocalRandom.current().nextInt(); -+ ClientboundCustomQueryPacket packet1 = new ClientboundCustomQueryPacket(this.velocityLoginMessageId, com.destroystokyo.paper.proxy.VelocityProxy.PLAYER_INFO_CHANNEL, new FriendlyByteBuf(Unpooled.EMPTY_BUFFER)); ++ net.minecraft.network.protocol.login.ClientboundCustomQueryPacket packet1 = new net.minecraft.network.protocol.login.ClientboundCustomQueryPacket(this.velocityLoginMessageId, com.destroystokyo.paper.proxy.VelocityProxy.PLAYER_INFO_CHANNEL, new FriendlyByteBuf(Unpooled.EMPTY_BUFFER)); + this.connection.send(packet1); + return; + } @@ -234,26 +170,26 @@ index 0aa3a154d68f00edcc09b947a24b2b59b1e135e6..22d6f41001977917ec75046252cbf715 // Spigot start // Paper start - Cache authenticator threads authenticatorPool.execute(new Runnable() { -@@ -312,6 +324,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -334,6 +345,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener public class LoginHandler { public void fireEvents() throws Exception { -+ // Paper start - Velocity support -+ if (ServerLoginPacketListenerImpl.this.velocityLoginMessageId == -1 && com.destroystokyo.paper.PaperConfig.velocitySupport) { -+ disconnect("This server requires you to connect with Velocity."); -+ return; -+ } -+ // Paper end - String playerName = gameProfile.getName(); - java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); - java.util.UUID uniqueId = gameProfile.getId(); -@@ -359,6 +377,40 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener ++ // Paper start - Velocity support ++ if (ServerLoginPacketListenerImpl.this.velocityLoginMessageId == -1 && com.destroystokyo.paper.PaperConfig.velocitySupport) { ++ disconnect("This server requires you to connect with Velocity."); ++ return; ++ } ++ // Paper end + String playerName = ServerLoginPacketListenerImpl.this.gameProfile.getName(); + java.net.InetAddress address = ((java.net.InetSocketAddress) ServerLoginPacketListenerImpl.this.connection.getRemoteAddress()).getAddress(); + java.util.UUID uniqueId = ServerLoginPacketListenerImpl.this.gameProfile.getId(); +@@ -381,6 +398,40 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener // Spigot end public void handleCustomQueryPacket(ServerboundCustomQueryPacket packet) { + // Paper start - Velocity support -+ if (com.destroystokyo.paper.PaperConfig.velocitySupport && packet.getId() == this.velocityLoginMessageId) { -+ FriendlyByteBuf buf = packet.getBuf(); ++ if (com.destroystokyo.paper.PaperConfig.velocitySupport && packet.getTransactionId() == this.velocityLoginMessageId) { ++ FriendlyByteBuf buf = packet.getData(); + if (buf == null) { + this.disconnect("This server requires you to connect with Velocity."); + return; @@ -271,7 +207,7 @@ index 0aa3a154d68f00edcc09b947a24b2b59b1e135e6..22d6f41001977917ec75046252cbf715 + } + this.connection.address = new java.net.InetSocketAddress(com.destroystokyo.paper.proxy.VelocityProxy.readAddress(buf), port); + -+ this.setGameProfile(com.destroystokyo.paper.proxy.VelocityProxy.createProfile(buf)); ++ this.gameProfile = com.destroystokyo.paper.proxy.VelocityProxy.createProfile(buf); + + // Proceed with login + authenticatorPool.execute(() -> { @@ -289,10 +225,10 @@ index 0aa3a154d68f00edcc09b947a24b2b59b1e135e6..22d6f41001977917ec75046252cbf715 } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 5e36d705c56384f507fd85f704eae634379a27f1..c06b35f114a8d243198b66c44ef57d8c2b201361 100644 +index 16645b4c096936c4d5c00f335e5cdb7dd4a4e2bd..717ad1c24bbc882db8f76cfef7bf847c58914e5a 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -680,7 +680,7 @@ public final class CraftServer implements Server { +@@ -683,7 +683,7 @@ public final class CraftServer implements Server { @Override public long getConnectionThrottle() { // Spigot Start - Automatically set connection throttle for bungee configurations diff --git a/patches/server-remapped/0301-Add-more-Witch-API.patch b/patches/server/0278-Add-more-Witch-API.patch similarity index 90% rename from patches/server-remapped/0301-Add-more-Witch-API.patch rename to patches/server/0278-Add-more-Witch-API.patch index 099a0f9cff..8c1a40d946 100644 --- a/patches/server-remapped/0301-Add-more-Witch-API.patch +++ b/patches/server/0278-Add-more-Witch-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add more Witch API diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java -index a37ee32b46aa87be6e3eeca2892b4e7294fd1aef..bc9380782c2afba359852542837e7154c4c6cf8b 100644 +index 5e2e8cb5eba4ba36065f07abed954b2aad022321..ee32917c9852a97c27779ea969131e6c28bbb3ac 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Witch.java +++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java @@ -1,5 +1,8 @@ @@ -26,20 +26,7 @@ index a37ee32b46aa87be6e3eeca2892b4e7294fd1aef..bc9380782c2afba359852542837e7154 private NearestHealableRaiderTargetGoal healRaidersGoal; private NearestAttackableWitchTargetGoal attackPlayersGoal; -@@ -95,10 +98,12 @@ public class Witch extends Raider implements RangedAttackMob { - return SoundEvents.WITCH_DEATH; - } - -+ public void setDrinkingPotion(boolean drinkingPotion) { setUsingItem(drinkingPotion); } // Paper - OBFHELPER - public void setUsingItem(boolean drinking) { - this.getEntityData().set(Witch.DATA_USING_ITEM, drinking); - } - -+ public boolean isDrinkingPotion() { return isDrinkingPotion(); } // Paper - OBFHELPER - public boolean isDrinkingPotion() { - return (Boolean) this.getEntityData().get(Witch.DATA_USING_ITEM); - } -@@ -157,21 +162,24 @@ public class Witch extends Raider implements RangedAttackMob { +@@ -157,21 +160,24 @@ public class Witch extends Raider implements RangedAttackMob { } if (potionregistry != null) { @@ -76,7 +63,7 @@ index a37ee32b46aa87be6e3eeca2892b4e7294fd1aef..bc9380782c2afba359852542837e7154 } } -@@ -183,6 +191,24 @@ public class Witch extends Raider implements RangedAttackMob { +@@ -183,6 +189,24 @@ public class Witch extends Raider implements RangedAttackMob { super.aiStep(); } diff --git a/patches/server-remapped/0302-Check-Drowned-for-Villager-Aggression-Config.patch b/patches/server/0279-Check-Drowned-for-Villager-Aggression-Config.patch similarity index 69% rename from patches/server-remapped/0302-Check-Drowned-for-Villager-Aggression-Config.patch rename to patches/server/0279-Check-Drowned-for-Villager-Aggression-Config.patch index cbace85cba..32fbb8a772 100644 --- a/patches/server-remapped/0302-Check-Drowned-for-Villager-Aggression-Config.patch +++ b/patches/server/0279-Check-Drowned-for-Villager-Aggression-Config.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Check Drowned for Villager Aggression Config diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -index cc9cd34f77e1f568572f312655fb2fe8e83bd733..0addfd6a1421fc99840d9229bad3ba04e524317b 100644 +index bacc065a9ce619fb0ac15b61cc5032c6bec00019..50228e59d629e75e97d23bd3ec92088f75480827 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java +++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -@@ -82,7 +82,7 @@ public class Drowned extends Zombie implements RangedAttackMob { +@@ -79,7 +79,7 @@ public class Drowned extends Zombie implements RangedAttackMob { this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D)); - this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Drowned.class})).setAlertOthers(ZombifiedPiglin.class)); + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, Drowned.class)).setAlertOthers(ZombifiedPiglin.class)); this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::okTarget)); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); -+ if ( level.spigotConfig.zombieAggressiveTowardsVillager ) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Paper ++ if (this.level.spigotConfig.zombieAggressiveTowardsVillager) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Paper this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Axolotl.class, true, false)); this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); - } diff --git a/patches/server-remapped/0303-Here-s-Johnny.patch b/patches/server/0280-Here-s-Johnny.patch similarity index 78% rename from patches/server-remapped/0303-Here-s-Johnny.patch rename to patches/server/0280-Here-s-Johnny.patch index e6a6846d1e..9bd412b6e3 100644 --- a/patches/server-remapped/0303-Here-s-Johnny.patch +++ b/patches/server/0280-Here-s-Johnny.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Here's Johnny! diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -index a41f61daf6cbbb13d0b86cdbad8a4cae00368653..623de661f3b56062792e3a7dbc508637aa58aca5 100644 +index aaeb82575ce0a3dac7c4e413fb782925573894d7..dcaec42b0756cf36da813815b4a54e4d6c4e293a 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java @@ -51,7 +51,7 @@ public class Vindicator extends AbstractIllager { - private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { - return enumdifficulty == Difficulty.NORMAL || enumdifficulty == Difficulty.HARD; + static final Predicate DOOR_BREAKING_PREDICATE = (difficulty) -> { + return difficulty == Difficulty.NORMAL || difficulty == Difficulty.HARD; }; -- private boolean isJohnny; -+ private boolean isJohnny; public boolean isJohnny() { return isJohnny; } public void setJohnny(boolean johnny) { isJohnny = johnny; } // Paper - OBFHELPER +- boolean isJohnny; ++ private boolean isJohnny; public boolean isJohnny() { return this.isJohnny; } public void setJohnny(boolean johnny) { this.isJohnny = johnny; } // Paper - OBFHELPER public Vindicator(EntityType type, Level world) { super(type, world); diff --git a/patches/server-remapped/0304-Add-option-to-prevent-players-from-moving-into-unloa.patch b/patches/server/0281-Add-option-to-prevent-players-from-moving-into-unloa.patch similarity index 66% rename from patches/server-remapped/0304-Add-option-to-prevent-players-from-moving-into-unloa.patch rename to patches/server/0281-Add-option-to-prevent-players-from-moving-into-unloa.patch index 565724bd30..08f65404d0 100644 --- a/patches/server-remapped/0304-Add-option-to-prevent-players-from-moving-into-unloa.patch +++ b/patches/server/0281-Add-option-to-prevent-players-from-moving-into-unloa.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add option to prevent players from moving into unloaded diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index f280dbff4a09bc611a9ca565c6d697d08801f53b..fbf3ccfb347a5ba6e895339e9576629d940d1aa4 100644 +index c17c504acdc12b6ef37d6643eb98a57fa5ca40c9..13e730b18c346934c061fb570048623ad66e7344 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -396,4 +396,9 @@ public class PaperWorldConfig { +@@ -390,4 +390,9 @@ public class PaperWorldConfig { waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); log("Water over lava flow speed: " + waterOverLavaFlowSpeed); } @@ -20,10 +20,10 @@ index f280dbff4a09bc611a9ca565c6d697d08801f53b..fbf3ccfb347a5ba6e895339e9576629d + } } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 4fd8d775790c037e82f9b0d29ed0eccf03c2dc66..b5593300516fad767f603084aca4abcda4424db3 100644 +index 06922b26ca1f2e31f7c8a527f1a8fdda4a8554c0..5f4718fa42be0ade1a40c0472efbbd0c65f061a7 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -541,6 +541,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -532,6 +532,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } speed *= 2f; // TODO: Get the speed of the vehicle instead of the player @@ -37,25 +37,25 @@ index 4fd8d775790c037e82f9b0d29ed0eccf03c2dc66..b5593300516fad767f603084aca4abcd if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { // CraftBukkit end ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getName().getString(), this.player.getName().getString(), d6, d7, d8); -@@ -1139,9 +1146,9 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - double d1 = this.player.getY(); - double d2 = this.player.getZ(); - double d3 = this.player.getY(); -- double d4 = packet.getX(this.player.getX()); -+ double d4 = packet.getX(this.player.getX());double toX = d4; // Paper - OBFHELPER - double d5 = packet.getY(this.player.getY()); -- double d6 = packet.getZ(this.player.getZ()); -+ double d6 = packet.getZ(this.player.getZ());double toZ = d6; // Paper - OBFHELPER - float f = packet.getYRot(this.player.yRot); - float f1 = packet.getXRot(this.player.xRot); - double d7 = d4 - this.firstGoodX; -@@ -1180,6 +1187,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1168,9 +1175,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + float prevYaw = this.player.getYRot(); + float prevPitch = this.player.getXRot(); + // CraftBukkit end +- double d3 = this.player.getX(); ++ double d3 = this.player.getX(); final double toX = d3; // Paper - OBFHELPER + double d4 = this.player.getY(); +- double d5 = this.player.getZ(); ++ double d5 = this.player.getZ(); final double toZ = d5; // Paper - OBFHELPER + double d6 = this.player.getY(); + double d7 = d0 - this.firstGoodX; + double d8 = d1 - this.firstGoodY; +@@ -1208,6 +1215,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } else { - speed = player.abilities.walkingSpeed * 10f; + speed = this.player.getAbilities().walkingSpeed * 10f; } + // Paper start - Prevent moving into unloaded chunks + if (player.level.paperConfig.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.hasChunk((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { -+ this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.yRot, this.player.xRot, Collections.emptySet()); ++ this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot(), Collections.emptySet(), true); + return; + } + // Paper end From 41a5f14f9ed600bcaf2cdcd8fa285ca0ac02594a Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 01:26:58 -0700 Subject: [PATCH 068/226] patches and patches --- ...ault-permission-message-configurable.patch | 4 +- ...tion-supression-of-EntityDismount-Ve.patch | 0 .../0164-Add-more-Zombie-API.patch | 0 ...eserved-channel-check-to-be-sensible.patch | 0 .../0166-Add-PlayerConnectionCloseEvent.patch | 0 ...-replace-OfflinePlayer-getLastPlayed.patch | 0 .../0168-BlockDestroyEvent.patch | 0 ...-ItemStack-Recipe-API-helper-methods.patch | 0 .../0170-Add-WhitelistToggleEvent.patch | 0 .../0327-Fix-sign-edit-memory-leak.patch | 2 + .../0311-Fix-SpongeAbsortEvent-handling.patch | 37 --------- ...2-Reset-players-airTicks-on-respawn.patch} | 8 +- ...after-profile-lookups-if-not-needed.patch} | 0 ...r-Thread-Pool-and-Thread-Priorities.patch} | 76 ++++++++----------- .../0285-Optimize-World-Time-Updates.patch} | 4 +- ...tore-custom-InventoryHolder-support.patch} | 8 +- .../0287-Use-Vanilla-Minecart-Speeds.patch} | 4 +- .../0288-Fix-SpongeAbsortEvent-handling.patch | 25 ++++++ ...-allow-digging-into-unloaded-chunks.patch} | 16 ++-- ...ult-permission-message-configurable.patch} | 10 +-- ...revent-rayTrace-from-loading-chunks.patch} | 4 +- ...-Large-Packets-disconnecting-client.patch} | 69 +++++++---------- ...ntity-dismount-during-teleportation.patch} | 26 +++---- .../0294-Add-more-Zombie-API.patch} | 46 +++++------ .../0295-Book-Size-Limits.patch} | 18 +++-- ...0296-Add-PlayerConnectionCloseEvent.patch} | 23 +++--- ...revent-Enderman-from-loading-chunks.patch} | 24 +++--- ...replace-OfflinePlayer-getLastPlayed.patch} | 28 +++---- ...ehicle-tracking-issue-on-disconnect.patch} | 4 +- ...nRetractEvent-for-all-empty-pistons.patch} | 6 +- ...remove-from-being-called-on-Players.patch} | 4 +- .../0302-BlockDestroyEvent.patch} | 8 +- ...m-Shapeless-Custom-Crafting-Recipes.patch} | 10 +-- .../0304-Limit-Client-Sign-length-more.patch} | 28 ++++--- 34 files changed, 231 insertions(+), 261 deletions(-) rename patches/{api-unmapped => api}/0162-Make-the-default-permission-message-configurable.patch (92%) rename patches/{api-unmapped => api}/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch (100%) rename patches/{api-unmapped => api}/0164-Add-more-Zombie-API.patch (100%) rename patches/{api-unmapped => api}/0165-Change-the-reserved-channel-check-to-be-sensible.patch (100%) rename patches/{api-unmapped => api}/0166-Add-PlayerConnectionCloseEvent.patch (100%) rename patches/{api-unmapped => api}/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch (100%) rename patches/{api-unmapped => api}/0168-BlockDestroyEvent.patch (100%) rename patches/{api-unmapped => api}/0169-Add-ItemStack-Recipe-API-helper-methods.patch (100%) rename patches/{api-unmapped => api}/0170-Add-WhitelistToggleEvent.patch (100%) rename patches/{server-remapped => removed/1.17}/0327-Fix-sign-edit-memory-leak.patch (97%) delete mode 100644 patches/server-remapped/0311-Fix-SpongeAbsortEvent-handling.patch rename patches/{server-remapped/0305-Reset-players-airTicks-on-respawn.patch => server/0282-Reset-players-airTicks-on-respawn.patch} (73%) rename patches/{server-remapped/0306-Don-t-sleep-after-profile-lookups-if-not-needed.patch => server/0283-Don-t-sleep-after-profile-lookups-if-not-needed.patch} (100%) rename patches/{server-remapped/0307-Improve-Server-Thread-Pool-and-Thread-Priorities.patch => server/0284-Improve-Server-Thread-Pool-and-Thread-Priorities.patch} (55%) rename patches/{server-remapped/0308-Optimize-World-Time-Updates.patch => server/0285-Optimize-World-Time-Updates.patch} (94%) rename patches/{server-remapped/0309-Restore-custom-InventoryHolder-support.patch => server/0286-Restore-custom-InventoryHolder-support.patch} (84%) rename patches/{server-remapped/0310-Use-Vanilla-Minecart-Speeds.patch => server/0287-Use-Vanilla-Minecart-Speeds.patch} (86%) create mode 100644 patches/server/0288-Fix-SpongeAbsortEvent-handling.patch rename patches/{server-remapped/0312-Don-t-allow-digging-into-unloaded-chunks.patch => server/0289-Don-t-allow-digging-into-unloaded-chunks.patch} (86%) rename patches/{server-remapped/0314-Make-the-default-permission-message-configurable.patch => server/0290-Make-the-default-permission-message-configurable.patch} (85%) rename patches/{server-remapped/0315-Prevent-rayTrace-from-loading-chunks.patch => server/0291-Prevent-rayTrace-from-loading-chunks.patch} (89%) rename patches/{server-remapped/0316-Handle-Large-Packets-disconnecting-client.patch => server/0292-Handle-Large-Packets-disconnecting-client.patch} (63%) rename patches/{server-remapped/0317-force-entity-dismount-during-teleportation.patch => server/0293-force-entity-dismount-during-teleportation.patch} (82%) rename patches/{server-remapped/0318-Add-more-Zombie-API.patch => server/0294-Add-more-Zombie-API.patch} (71%) rename patches/{server-remapped/0313-Book-Size-Limits.patch => server/0295-Book-Size-Limits.patch} (86%) rename patches/{server-remapped/0319-Add-PlayerConnectionCloseEvent.patch => server/0296-Add-PlayerConnectionCloseEvent.patch} (77%) rename patches/{server-remapped/0320-Prevent-Enderman-from-loading-chunks.patch => server/0297-Prevent-Enderman-from-loading-chunks.patch} (76%) rename patches/{server-remapped/0321-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch => server/0298-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch} (86%) rename patches/{server-remapped/0322-Workaround-for-vehicle-tracking-issue-on-disconnect.patch => server/0299-Workaround-for-vehicle-tracking-issue-on-disconnect.patch} (83%) rename patches/{server-remapped/0323-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch => server/0300-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch} (91%) rename patches/{server-remapped/0324-Block-Entity-remove-from-being-called-on-Players.patch => server/0301-Block-Entity-remove-from-being-called-on-Players.patch} (89%) rename patches/{server-remapped/0325-BlockDestroyEvent.patch => server/0302-BlockDestroyEvent.patch} (88%) rename patches/{server-remapped/0326-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch => server/0303-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch} (89%) rename patches/{server-remapped/0328-Limit-Client-Sign-length-more.patch => server/0304-Limit-Client-Sign-length-more.patch} (54%) diff --git a/patches/api-unmapped/0162-Make-the-default-permission-message-configurable.patch b/patches/api/0162-Make-the-default-permission-message-configurable.patch similarity index 92% rename from patches/api-unmapped/0162-Make-the-default-permission-message-configurable.patch rename to patches/api/0162-Make-the-default-permission-message-configurable.patch index 06ba70ae7d..7bc89dfab9 100644 --- a/patches/api-unmapped/0162-Make-the-default-permission-message-configurable.patch +++ b/patches/api/0162-Make-the-default-permission-message-configurable.patch @@ -5,7 +5,7 @@ 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 6b619b85fee86ccc599cb46d789e39b81af3201c..dcaefdaf5a0de8486f59115c8c4d4c211b7d64cd 100644 +index 1f4532e60abe62b88472a9bb0ef8d1af1f921220..a69e0b0c9f515256c6406ef8ff55f72c98dabe0d 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1793,6 +1793,15 @@ public final class Bukkit { @@ -25,7 +25,7 @@ index 6b619b85fee86ccc599cb46d789e39b81af3201c..dcaefdaf5a0de8486f59115c8c4d4c21 * Creates a PlayerProfile for the specified uuid, with name as null * @param uuid UUID to create profile for diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index c642fe9cfae6407404f5cf17264f42ef83a01280..9b8e6b7bbbed44e2659379c8046acaa35aaa8910 100644 +index ca4e2d3b27f629e0d5e672fc915a5d03f0c0581d..17f8dd9870a47227a7c9bb09cceedb94f7190ead 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1575,6 +1575,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api-unmapped/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch b/patches/api/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch similarity index 100% rename from patches/api-unmapped/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch rename to patches/api/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch diff --git a/patches/api-unmapped/0164-Add-more-Zombie-API.patch b/patches/api/0164-Add-more-Zombie-API.patch similarity index 100% rename from patches/api-unmapped/0164-Add-more-Zombie-API.patch rename to patches/api/0164-Add-more-Zombie-API.patch diff --git a/patches/api-unmapped/0165-Change-the-reserved-channel-check-to-be-sensible.patch b/patches/api/0165-Change-the-reserved-channel-check-to-be-sensible.patch similarity index 100% rename from patches/api-unmapped/0165-Change-the-reserved-channel-check-to-be-sensible.patch rename to patches/api/0165-Change-the-reserved-channel-check-to-be-sensible.patch diff --git a/patches/api-unmapped/0166-Add-PlayerConnectionCloseEvent.patch b/patches/api/0166-Add-PlayerConnectionCloseEvent.patch similarity index 100% rename from patches/api-unmapped/0166-Add-PlayerConnectionCloseEvent.patch rename to patches/api/0166-Add-PlayerConnectionCloseEvent.patch diff --git a/patches/api-unmapped/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/patches/api/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 100% rename from patches/api-unmapped/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to patches/api/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch diff --git a/patches/api-unmapped/0168-BlockDestroyEvent.patch b/patches/api/0168-BlockDestroyEvent.patch similarity index 100% rename from patches/api-unmapped/0168-BlockDestroyEvent.patch rename to patches/api/0168-BlockDestroyEvent.patch diff --git a/patches/api-unmapped/0169-Add-ItemStack-Recipe-API-helper-methods.patch b/patches/api/0169-Add-ItemStack-Recipe-API-helper-methods.patch similarity index 100% rename from patches/api-unmapped/0169-Add-ItemStack-Recipe-API-helper-methods.patch rename to patches/api/0169-Add-ItemStack-Recipe-API-helper-methods.patch diff --git a/patches/api-unmapped/0170-Add-WhitelistToggleEvent.patch b/patches/api/0170-Add-WhitelistToggleEvent.patch similarity index 100% rename from patches/api-unmapped/0170-Add-WhitelistToggleEvent.patch rename to patches/api/0170-Add-WhitelistToggleEvent.patch diff --git a/patches/server-remapped/0327-Fix-sign-edit-memory-leak.patch b/patches/removed/1.17/0327-Fix-sign-edit-memory-leak.patch similarity index 97% rename from patches/server-remapped/0327-Fix-sign-edit-memory-leak.patch rename to patches/removed/1.17/0327-Fix-sign-edit-memory-leak.patch index cdc4ad71f6..1c8d3052c4 100644 --- a/patches/server-remapped/0327-Fix-sign-edit-memory-leak.patch +++ b/patches/removed/1.17/0327-Fix-sign-edit-memory-leak.patch @@ -5,6 +5,8 @@ Subject: [PATCH] Fix sign edit memory leak when a player edits a sign, a reference to their Entity is never cleand up. +removed 1.17 - mojang uses a UUID instead of a player field now + diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java index b1c505d3fdcc2fb3496f80bee85e4895b9069dcb..276773e17149f57038cd21485fd9d9061670ff2d 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java diff --git a/patches/server-remapped/0311-Fix-SpongeAbsortEvent-handling.patch b/patches/server-remapped/0311-Fix-SpongeAbsortEvent-handling.patch deleted file mode 100644 index 169c739faa..0000000000 --- a/patches/server-remapped/0311-Fix-SpongeAbsortEvent-handling.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 10 Nov 2018 05:15:21 +0000 -Subject: [PATCH] Fix SpongeAbsortEvent handling - -Only process drops when the block is actually going to be removed - -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 9d2e4adddae481735053c64eec0ee7259c61f1a4..fca5d175cbef24fb0ee2d0bbedc8d1c0af3eb528 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -228,6 +228,7 @@ public class Block extends BlockBehaviour implements ItemLike { - - } - -+ public static void dropNaturally(BlockState iblockdata, LevelAccessor generatoraccess, BlockPos blockposition, @Nullable BlockEntity tileentity) { dropResources(iblockdata, generatoraccess, blockposition, tileentity); } - public static void dropResources(BlockState state, LevelAccessor world, BlockPos pos, @Nullable BlockEntity blockEntity) { - if (world instanceof ServerLevel) { - getDrops(state, (ServerLevel) world, pos, blockEntity).forEach((itemstack) -> { -diff --git a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java -index c453963ec90cd4eeec845fd0c2137e60dfdd6225..1895c75deee8da40624ba3abbd08ba7cd4f0f503 100644 ---- a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java -@@ -128,8 +128,11 @@ public class SpongeBlock extends Block { - // NOP - } else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) { - BlockEntity tileentity = iblockdata.getBlock().isEntityBlock() ? world.getBlockEntity(blockposition2) : null; -- -- dropResources(iblockdata, world, blockposition2, tileentity); -+ // Paper start -+ if (block.getHandle().getMaterial() == Material.AIR) { -+ dropNaturally(iblockdata, world, blockposition2, tileentity); -+ } -+ // Paper end - } - } - world.setBlock(blockposition2, block.getHandle(), block.getFlag()); diff --git a/patches/server-remapped/0305-Reset-players-airTicks-on-respawn.patch b/patches/server/0282-Reset-players-airTicks-on-respawn.patch similarity index 73% rename from patches/server-remapped/0305-Reset-players-airTicks-on-respawn.patch rename to patches/server/0282-Reset-players-airTicks-on-respawn.patch index b3525e04cd..562a2e2343 100644 --- a/patches/server-remapped/0305-Reset-players-airTicks-on-respawn.patch +++ b/patches/server/0282-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 92139b271eb6c305787662ef8c7d221fb42296f7..b68acf219fc61e2ea811d0c732393824fa44db2d 100644 +index b2324b53b3cec3e577a8ec8c45b113c232d220a6..5eb37fb1ae861940839fe6815b57111812d6b3ec 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2159,6 +2159,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -2210,6 +2210,7 @@ public class ServerPlayer extends Player { } this.setHealth(this.getMaxHealth()); @@ -17,10 +17,10 @@ index 92139b271eb6c305787662ef8c7d221fb42296f7..b68acf219fc61e2ea811d0c732393824 this.fallDistance = 0; this.foodData = new FoodData(this); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index e7fed1f8bb8ffb164ddcdab51f41c369d6e3103d..460c6fd61bb45247715d99445821e15e98e4c465 100644 +index 0974781e2f7fc541eaf397de033fb12b87dbf8ba..c3bbe8429ee792b881953c5894a55505cdba63d3 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2354,6 +2354,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2585,6 +2585,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } diff --git a/patches/server-remapped/0306-Don-t-sleep-after-profile-lookups-if-not-needed.patch b/patches/server/0283-Don-t-sleep-after-profile-lookups-if-not-needed.patch similarity index 100% rename from patches/server-remapped/0306-Don-t-sleep-after-profile-lookups-if-not-needed.patch rename to patches/server/0283-Don-t-sleep-after-profile-lookups-if-not-needed.patch diff --git a/patches/server-remapped/0307-Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/patches/server/0284-Improve-Server-Thread-Pool-and-Thread-Priorities.patch similarity index 55% rename from patches/server-remapped/0307-Improve-Server-Thread-Pool-and-Thread-Priorities.patch rename to patches/server/0284-Improve-Server-Thread-Pool-and-Thread-Priorities.patch index 04594148fc..33c9c97915 100644 --- a/patches/server-remapped/0307-Improve-Server-Thread-Pool-and-Thread-Priorities.patch +++ b/patches/server/0284-Improve-Server-Thread-Pool-and-Thread-Priorities.patch @@ -12,10 +12,10 @@ server threads Allow usage of a single thread executor by not using ForkJoin so single core CPU's. diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index 7b36274718b7cce24ac00530697f145648d52590..cec5ad5052c8cf6059e9b117117846bdb217748f 100644 +index 6f29d1fc437764a75d592ccb0c0ddc0593a89967..99d52a9643efe38b449b59b6aac81c5b20ed9477 100644 --- a/src/main/java/net/minecraft/Util.java +++ b/src/main/java/net/minecraft/Util.java -@@ -45,7 +45,7 @@ import java.util.stream.Stream; +@@ -56,7 +56,7 @@ import java.util.stream.Stream; import javax.annotation.Nullable; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.Bootstrap; @@ -23,75 +23,63 @@ index 7b36274718b7cce24ac00530697f145648d52590..cec5ad5052c8cf6059e9b117117846bd +import net.minecraft.server.ServerWorkerThread; import net.minecraft.util.datafix.DataFixers; import net.minecraft.world.level.block.state.properties.Property; - import org.apache.logging.log4j.LogManager; -@@ -54,8 +54,8 @@ import org.apache.logging.log4j.Logger; - public class Util { + import org.apache.commons.io.IOUtils; +@@ -65,8 +65,8 @@ import org.apache.logging.log4j.Logger; + public class Util { private static final AtomicInteger WORKER_COUNT = new AtomicInteger(1); - private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap"); - private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main"); -+ private static final ExecutorService BOOTSTRAP_EXECUTOR = a("Bootstrap", -2); // Paper - add -2 priority -+ private static final ExecutorService BACKGROUND_EXECUTOR = a("Main", -1); // Paper - add -1 priority ++ private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap", -2); // Paper - add -2 priority ++ private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main", -1); // Paper - add -1 priority private static final ExecutorService IO_POOL = makeIoExecutor(); public static LongSupplier timeSource = System::nanoTime; - public static final UUID NIL_UUID = new UUID(0L, 0L); public static final UUID getNullUUID() {return NIL_UUID;} // Paper OBFHELPER -@@ -85,30 +85,34 @@ public class Util { + public static final UUID NIL_UUID = new UUID(0L, 0L); +@@ -101,14 +101,18 @@ public class Util { return Instant.now().toEpochMilli(); } - private static ExecutorService makeExecutor(String name) { - int i = Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, 7); -- Object object; -+ private static ExecutorService a(String s, int priorityModifier) { // Paper - add priority ++ private static ExecutorService makeExecutor(String s, int priorityModifier) { // Paper - add priority + // Paper start - use simpler thread pool that allows 1 thread + int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1)); + i = Integer.getInteger("Paper.WorkerThreadCount", i); -+ ExecutorService object; - + ExecutorService executorService; ++ if (i <= 0) { - object = MoreExecutors.newDirectExecutorService(); + executorService = MoreExecutors.newDirectExecutorService(); } else { -- object = new ForkJoinPool(i, (forkjoinpool) -> { -- ForkJoinWorkerThread forkjoinworkerthread = new ForkJoinWorkerThread(forkjoinpool) { -+ object = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue(), target -> new ServerWorkerThread(target, s, priorityModifier)); +- executorService = new ForkJoinPool(i, (forkJoinPool) -> { +- ForkJoinWorkerThread forkJoinWorkerThread = new ForkJoinWorkerThread(forkJoinPool) { ++ executorService = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue(), target -> new ServerWorkerThread(target, s, priorityModifier)); + } + /* + @Override protected void onTermination(Throwable throwable) { if (throwable != null) { -- Util.LOGGER.warn("{} died", this.getName(), throwable); -+ SystemUtils.LOGGER.warn("{} died", this.getName(), throwable); - } else { -- Util.LOGGER.debug("{} shutdown", this.getName()); -+ SystemUtils.LOGGER.debug("{} shutdown", this.getName()); - } - - super.onTermination(throwable); - } - }; - -- forkjoinworkerthread.setName("Worker-" + name + "-" + Util.WORKER_COUNT.getAndIncrement()); -+ forkjoinworkerthread.setName("Worker-" + s + "-" + SystemUtils.c.getAndIncrement()); - return forkjoinworkerthread; -- }, Util::onThreadException, true); -+ }, SystemUtils::a, true); +@@ -124,6 +128,7 @@ public class Util { + return forkJoinWorkerThread; + }, Util::onThreadException, true); } + }*/ // Paper end - return (ExecutorService) object; + return executorService; } -@@ -157,6 +161,7 @@ public class Util { - }); +@@ -180,7 +185,7 @@ public class Util { + throw t instanceof RuntimeException ? (RuntimeException)t : new RuntimeException(t); } -+ public static void onThreadError(Thread thread, Throwable throwable) { onThreadException(thread, throwable); } // Paper - OBFHELPER - private static void onThreadException(Thread thread, Throwable throwable) { - pauseInIde(throwable); - if (throwable instanceof CompletionException) { +- private static void onThreadException(Thread thread, Throwable t) { ++ public static void onThreadException(Thread thread, Throwable t) { // Paper - make public + pauseInIde(t); + if (t instanceof CompletionException) { + t = t.getCause(); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 5a76ca77b974ff6fe862c9e05a88b507a34b44be..5faa8f3cc251b6687e33e40009db98d2aee48f2c 100644 +index 24fc2eb3ee067a4164db166aa3e07ecbb426bbba..a302d232da3fbaa2cb3e1903cfd096d404847c54 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -284,6 +284,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Sat, 10 Nov 2018 05:15:21 +0000 +Subject: [PATCH] Fix SpongeAbsortEvent handling + +Only process drops when the block is actually going to be removed + +diff --git a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java +index b8ae2000a44469245c6ba3cda0c0e87b07156b06..1ef8eadd4e59f2e5d2bbd84f6f9bcf37b59db5bd 100644 +--- a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java +@@ -130,8 +130,11 @@ public class SpongeBlock extends Block { + // NOP + } else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) { + BlockEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition2) : null; +- +- dropResources(iblockdata, world, blockposition2, tileentity); ++ // Paper start ++ if (block.getHandle().getMaterial() == Material.AIR) { ++ dropResources(iblockdata, world, blockposition2, tileentity); ++ } ++ // Paper end + } + } + world.setBlock(blockposition2, block.getHandle(), block.getFlag()); diff --git a/patches/server-remapped/0312-Don-t-allow-digging-into-unloaded-chunks.patch b/patches/server/0289-Don-t-allow-digging-into-unloaded-chunks.patch similarity index 86% rename from patches/server-remapped/0312-Don-t-allow-digging-into-unloaded-chunks.patch rename to patches/server/0289-Don-t-allow-digging-into-unloaded-chunks.patch index f5420a15fd..c74abe7bd4 100644 --- a/patches/server-remapped/0312-Don-t-allow-digging-into-unloaded-chunks.patch +++ b/patches/server/0289-Don-t-allow-digging-into-unloaded-chunks.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Don't allow digging into unloaded chunks diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index b1a53093eb5b5f359eedb6c252cf6d0d1ae8e409..d97607f2ded4977b253d3afa3bafcbe6d7f98837 100644 +index 315dad4789f5f2582ee9b4fc176affd1f57537ef..f4a056185990181e486f452960159a5287947382 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -113,8 +113,8 @@ public class ServerPlayerGameMode { +@@ -119,8 +119,8 @@ public class ServerPlayerGameMode { BlockState iblockdata; if (this.hasDelayedDestroy) { @@ -19,7 +19,7 @@ index b1a53093eb5b5f359eedb6c252cf6d0d1ae8e409..d97607f2ded4977b253d3afa3bafcbe6 this.hasDelayedDestroy = false; } else { float f = this.incrementDestroyProgress(iblockdata, this.delayedDestroyPos, this.delayedTickStart); -@@ -125,7 +125,13 @@ public class ServerPlayerGameMode { +@@ -131,7 +131,13 @@ public class ServerPlayerGameMode { } } } else if (this.isDestroyingBlock) { @@ -34,13 +34,13 @@ index b1a53093eb5b5f359eedb6c252cf6d0d1ae8e409..d97607f2ded4977b253d3afa3bafcbe6 if (iblockdata.isAir()) { this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); this.lastSentState = -1; -@@ -289,10 +295,12 @@ public class ServerPlayerGameMode { +@@ -295,10 +301,12 @@ public class ServerPlayerGameMode { this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, "stopped destroying")); } else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) { this.isDestroyingBlock = false; - if (!Objects.equals(this.destroyPos, pos)) { + if (!Objects.equals(this.destroyPos, pos) && !BlockPos.ZERO.equals(this.destroyPos)) { - ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: " + this.destroyPos + " " + pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled + ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: {} {}", this.destroyPos, pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled - this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); - this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, this.level.getBlockState(this.destroyPos), action, true, "aborted mismatched destroying")); + BlockState type = this.level.getTypeIfLoaded(this.destroyPos); // Paper - don't load unloaded chunks for stale records here @@ -51,10 +51,10 @@ index b1a53093eb5b5f359eedb6c252cf6d0d1ae8e409..d97607f2ded4977b253d3afa3bafcbe6 this.level.destroyBlockProgress(this.player.getId(), pos, -1); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index b5593300516fad767f603084aca4abcda4424db3..a6ad7747396f94def688b4d2783137180dc2bb84 100644 +index 5f4718fa42be0ade1a40c0472efbbd0c65f061a7..8b716c625c363d7143fe6fbc26d3d674d62a5833 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1518,6 +1518,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1558,6 +1558,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser case START_DESTROY_BLOCK: case ABORT_DESTROY_BLOCK: case STOP_DESTROY_BLOCK: @@ -63,6 +63,6 @@ index b5593300516fad767f603084aca4abcda4424db3..a6ad7747396f94def688b4d278313718 + return; + } + // Paper end - Don't allow digging in unloaded chunks - this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packet.getDirection(), this.server.getMaxBuildHeight()); + this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packet.getDirection(), this.player.level.getMaxBuildHeight()); return; default: diff --git a/patches/server-remapped/0314-Make-the-default-permission-message-configurable.patch b/patches/server/0290-Make-the-default-permission-message-configurable.patch similarity index 85% rename from patches/server-remapped/0314-Make-the-default-permission-message-configurable.patch rename to patches/server/0290-Make-the-default-permission-message-configurable.patch index f6e041b266..16f546dd5d 100644 --- a/patches/server-remapped/0314-Make-the-default-permission-message-configurable.patch +++ b/patches/server/0290-Make-the-default-permission-message-configurable.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Make the default permission message configurable TODO: Change the message in PaperCommand diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 13edb435b3fa65b4980bd7472aa5a5196f4d5b2b..469f78775b03cf363d88e35c69c0dc185c22547c 100644 +index 9768c591e72ce2ef5fdb43e2fc63378c57773216..11d628869a9a6eda8bf21a4f213ff23ad753b18e 100644 --- a/src/main/java/com/destroystokyo/paper/PaperConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -19,6 +19,7 @@ import java.util.regex.Pattern; +@@ -20,6 +20,7 @@ import java.util.regex.Pattern; import com.google.common.collect.Lists; import net.minecraft.server.MinecraftServer; import org.bukkit.Bukkit; @@ -17,7 +17,7 @@ index 13edb435b3fa65b4980bd7472aa5a5196f4d5b2b..469f78775b03cf363d88e35c69c0dc18 import org.bukkit.command.Command; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.InvalidConfigurationException; -@@ -287,6 +288,11 @@ public class PaperConfig { +@@ -288,6 +289,11 @@ public class PaperConfig { connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); } @@ -30,10 +30,10 @@ index 13edb435b3fa65b4980bd7472aa5a5196f4d5b2b..469f78775b03cf363d88e35c69c0dc18 Object val = config.get("settings.save-player-data"); if (val instanceof Boolean) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c06b35f114a8d243198b66c44ef57d8c2b201361..590687d5941cbed3a330bcd749f8d52cd4b5e3ae 100644 +index 717ad1c24bbc882db8f76cfef7bf847c58914e5a..0448e6b4c512f512bda13f41f1feb58de02fc9d4 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2340,6 +2340,11 @@ public final class CraftServer implements Server { +@@ -2341,6 +2341,11 @@ public final class CraftServer implements Server { return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; } diff --git a/patches/server-remapped/0315-Prevent-rayTrace-from-loading-chunks.patch b/patches/server/0291-Prevent-rayTrace-from-loading-chunks.patch similarity index 89% rename from patches/server-remapped/0315-Prevent-rayTrace-from-loading-chunks.patch rename to patches/server/0291-Prevent-rayTrace-from-loading-chunks.patch index d300ff7c9e..7043bbb004 100644 --- a/patches/server-remapped/0315-Prevent-rayTrace-from-loading-chunks.patch +++ b/patches/server/0291-Prevent-rayTrace-from-loading-chunks.patch @@ -7,10 +7,10 @@ ray tracing into an unloaded chunk should be treated as a miss this saves a ton of lag for when AI tries to raytrace near unloaded chunks. diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java -index 2feb187f62be5cf5d354a1e806087417cc189ab1..07fe8e72a7ff01d872dd5b04ccbc435e82ebe990 100644 +index e85e4a2dfceb0aa40e73b43a5e122a5906cac585..fe4dba491b586757a16aa36e62682f364daa2602 100644 --- a/src/main/java/net/minecraft/world/level/BlockGetter.java +++ b/src/main/java/net/minecraft/world/level/BlockGetter.java -@@ -58,7 +58,15 @@ public interface BlockGetter { +@@ -75,7 +75,15 @@ public interface BlockGetter extends LevelHeightAccessor { // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace default BlockHitResult rayTraceBlock(ClipContext raytrace1, BlockPos blockposition) { diff --git a/patches/server-remapped/0316-Handle-Large-Packets-disconnecting-client.patch b/patches/server/0292-Handle-Large-Packets-disconnecting-client.patch similarity index 63% rename from patches/server-remapped/0316-Handle-Large-Packets-disconnecting-client.patch rename to patches/server/0292-Handle-Large-Packets-disconnecting-client.patch index 3b9703f204..f9ec0723c2 100644 --- a/patches/server-remapped/0316-Handle-Large-Packets-disconnecting-client.patch +++ b/patches/server/0292-Handle-Large-Packets-disconnecting-client.patch @@ -7,23 +7,15 @@ If a players inventory is too big to send in a single packet, split the inventory set into multiple packets instead. diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 7f4681910751047a26fdfc6b59bc460449c02001..35191d968fd30db16213540ef7121f4dede68e68 100644 +index 0c5c62be83223e20f216df84413b8c2438db81ff..8bbf13a7aea1142b3154a1c76837a98aa5ed431d 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java -@@ -12,6 +12,7 @@ import io.netty.channel.epoll.EpollEventLoopGroup; - import io.netty.channel.local.LocalChannel; - import io.netty.channel.local.LocalServerChannel; - import io.netty.channel.nio.NioEventLoopGroup; -+import io.netty.handler.codec.EncoderException; // Paper - import io.netty.handler.timeout.TimeoutException; - import io.netty.util.AttributeKey; - import io.netty.util.concurrent.Future; -@@ -107,6 +108,15 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -120,6 +120,15 @@ public class Connection extends SimpleChannelInboundHandler> { } public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { + // Paper start -+ if (throwable instanceof EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) { ++ if (throwable instanceof io.netty.handler.codec.EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) { + if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) { + return; + } else { @@ -35,16 +27,16 @@ index 7f4681910751047a26fdfc6b59bc460449c02001..35191d968fd30db16213540ef7121f4d Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause()); } else { diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index d36d0424bcd4811af892f5f76fdcefda2af1ad33..a58c4fa8be7193b8acae5ea18a9780866312d768 100644 +index b8a0c0411fd2caab21672de7f3e721645b61a8ba..c0df136c408d7f001395291d8c80da5b4b54d462 100644 --- a/src/main/java/net/minecraft/network/PacketEncoder.java +++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -53,7 +53,31 @@ public class PacketEncoder extends MessageToByteEncoder> { - throw throwable; +@@ -54,7 +54,31 @@ public class PacketEncoder extends MessageToByteEncoder> { + throw var9; } } + + // Paper start -+ int packetLength = bytebuf.readableBytes(); ++ int packetLength = friendlyByteBuf.readableBytes(); + if (packetLength > MAX_PACKET_SIZE) { + throw new PacketTooLargeException(packet, packetLength); + } @@ -71,15 +63,15 @@ index d36d0424bcd4811af892f5f76fdcefda2af1ad33..a58c4fa8be7193b8acae5ea18a978086 + // Paper end } diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index 29f10af7feabe2765f576586db4e3dba320dceda..9914a82ba0ec146ab13fe94c4dbf0ebf64926536 100644 +index 10c1f2d8a92f848c3f2be9d1d06fd254978e6dcc..74bfe0d3942259c45702b099efdc4e101a4e3022 100644 --- a/src/main/java/net/minecraft/network/protocol/Packet.java +++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -12,6 +12,12 @@ public interface Packet { +@@ -8,6 +8,12 @@ public interface Packet { void handle(T listener); + // Paper start -+ default boolean packetTooLarge(NetworkManager manager) { ++ default boolean packetTooLarge(net.minecraft.network.Connection manager) { + return false; + } + // Paper end @@ -88,43 +80,36 @@ index 29f10af7feabe2765f576586db4e3dba320dceda..9914a82ba0ec146ab13fe94c4dbf0ebf return false; } diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java -index 70684318c562a9c3ce566b16cd0e68cfe95cbd50..64a15dcaef40c4e16458ab71d648f9fff169a3b2 100644 +index a27d46e90ad04c624d41f6cbededcd3121dfeee8..d5ca796408f975f4f002a5b385574d3516915507 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java -@@ -4,6 +4,7 @@ import java.io.IOException; - import java.util.Iterator; - import java.util.List; - import net.minecraft.core.NonNullList; -+import net.minecraft.network.Connection; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.protocol.Packet; - import net.minecraft.world.item.ItemStack; -@@ -13,6 +14,15 @@ public class ClientboundContainerSetContentPacket implements Packet items; +@@ -10,6 +10,16 @@ public class ClientboundContainerSetContentPacket implements Packet items; + //Paper start + @Override -+ public boolean packetTooLarge(Connection manager) { ++ public boolean packetTooLarge(net.minecraft.network.Connection manager) { + for (int i = 0 ; i < this.items.size() ; i++) { + manager.send(new ClientboundContainerSetSlotPacket(this.containerId, i, this.items.get(i))); + } + return true; + } + // Paper end - public ClientboundContainerSetContentPacket() {} - ++ public ClientboundContainerSetContentPacket(int syncId, NonNullList contents) { + this.containerId = syncId; + this.items = NonNullList.withSize(contents.size(), ItemStack.EMPTY); diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -index 4fe15aa331ca18319ca46d1b426f0d6fd24341f0..b7d303b5f51a35504888933efef74564fa01e59d 100644 +index 1451a98d69b185dd15a2d1d7681bcecb6a4f99c1..96626835fee3c0fdb452acacdc9f737ad90c08de 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -@@ -91,7 +91,7 @@ public class ClientboundLevelChunkPacket implements Packet 2097152) { -+ if (i > 2097152) { // Paper - if this changes, update PacketEncoder - throw new RuntimeException("Chunk Packet trying to allocate too much memory on read."); +@@ -64,7 +64,7 @@ public class ClientboundLevelChunkPacket implements Packet 2097152) { ++ if (i > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder + throw new RuntimeException("Chunk Packet trying to allocate too much memory on read."); + } else { + this.buffer = new byte[i]; diff --git a/patches/server-remapped/0317-force-entity-dismount-during-teleportation.patch b/patches/server/0293-force-entity-dismount-during-teleportation.patch similarity index 82% rename from patches/server-remapped/0317-force-entity-dismount-during-teleportation.patch rename to patches/server/0293-force-entity-dismount-during-teleportation.patch index abee5b71e8..a3e4049fb0 100644 --- a/patches/server-remapped/0317-force-entity-dismount-during-teleportation.patch +++ b/patches/server/0293-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 b68acf219fc61e2ea811d0c732393824fa44db2d..416c21f0a6be8d71a654e18f7ea0fa074f8fc5ff 100644 +index 5eb37fb1ae861940839fe6815b57111812d6b3ec..963a3c159e912a39b98dfcb3fdb8c384765990d7 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1258,11 +1258,13 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1299,11 +1299,13 @@ public class ServerPlayer extends Player { } } @@ -41,10 +41,10 @@ index b68acf219fc61e2ea811d0c732393824fa44db2d..416c21f0a6be8d71a654e18f7ea0fa07 if (entity1 != entity && this.connection != null) { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 460c6fd61bb45247715d99445821e15e98e4c465..c5d6235a132818dfc78105e9d03d0687f697bb00 100644 +index c3bbe8429ee792b881953c5894a55505cdba63d3..8df9bd656374d0b43af378c61c1df7b951085b58 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2044,12 +2044,15 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2212,12 +2212,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } @@ -62,7 +62,7 @@ index 460c6fd61bb45247715d99445821e15e98e4c465..c5d6235a132818dfc78105e9d03d0687 } } -@@ -2104,7 +2107,10 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2280,7 +2283,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n return true; // CraftBukkit } @@ -74,16 +74,16 @@ index 460c6fd61bb45247715d99445821e15e98e4c465..c5d6235a132818dfc78105e9d03d0687 if (entity.getVehicle() == this) { throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); } else { -@@ -2114,7 +2120,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { +@@ -2290,7 +2296,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + if (this.getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { VehicleExitEvent event = new VehicleExitEvent( - (Vehicle) getBukkitEntity(), + (Vehicle) this.getBukkitEntity(), - (LivingEntity) entity.getBukkitEntity() + (LivingEntity) entity.getBukkitEntity(), !suppressCancellation // Paper ); // Suppress during worldgen if (this.valid) { -@@ -2128,7 +2134,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2304,7 +2310,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } // CraftBukkit end // Spigot start @@ -93,10 +93,10 @@ index 460c6fd61bb45247715d99445821e15e98e4c465..c5d6235a132818dfc78105e9d03d0687 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 7a2292e6907a2ae2026bd7243e864bd8300ecafa..29d4ed42e5d763639a50d849ef274c4d848bc9c9 100644 +index 8333d604fce05349455bf1779f3e5b0a980c4c16..1dabdba428c10e65b634b6e2036f993c4be186a7 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3012,11 +3012,13 @@ public abstract class LivingEntity extends Entity { +@@ -3329,11 +3329,13 @@ public abstract class LivingEntity extends Entity { return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 4) != 0; } @@ -114,10 +114,10 @@ index 7a2292e6907a2ae2026bd7243e864bd8300ecafa..29d4ed42e5d763639a50d849ef274c4d this.dismountVehicle(entity); } 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 3aadc4ab5fe7b2ee9e20e0789ddcfe750599972f..0685920073a6a2b2c6a80018d0c9009b2ef860c4 100644 +index e0e33dd92b686939f622f0a7da0d5a971f43d0d6..4c9261c68518ab7429325f0366dfb2930663288c 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1036,9 +1036,11 @@ public abstract class Player extends LivingEntity { +@@ -1096,9 +1096,11 @@ public abstract class Player extends LivingEntity { return -0.35D; } diff --git a/patches/server-remapped/0318-Add-more-Zombie-API.patch b/patches/server/0294-Add-more-Zombie-API.patch similarity index 71% rename from patches/server-remapped/0318-Add-more-Zombie-API.patch rename to patches/server/0294-Add-more-Zombie-API.patch index 324b101062..9f2c58776e 100644 --- a/patches/server-remapped/0318-Add-more-Zombie-API.patch +++ b/patches/server/0294-Add-more-Zombie-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add more Zombie API diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 94e2a8f74e74d68d4a9b82b667fbff24b7e9e629..ad4eeb15771750193a28116117992270c72a3644 100644 +index 017d8de4d09f524aed2ee03af7ef79468503edf0..c60d9775230b2ff554eeb38136f8e7c32c47d8cf 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -91,6 +91,7 @@ public class Zombie extends Monster { +@@ -96,6 +96,7 @@ public class Zombie extends Monster { private int inWaterTime; public int conversionTime; private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field @@ -16,7 +16,7 @@ index 94e2a8f74e74d68d4a9b82b667fbff24b7e9e629..ad4eeb15771750193a28116117992270 public Zombie(EntityType type, Level world) { super(type, world); -@@ -259,6 +260,12 @@ public class Zombie extends Monster { +@@ -264,6 +265,12 @@ public class Zombie extends Monster { super.aiStep(); } @@ -29,47 +29,47 @@ index 94e2a8f74e74d68d4a9b82b667fbff24b7e9e629..ad4eeb15771750193a28116117992270 public void startUnderWaterConversion(int ticksUntilWaterConversion) { this.lastTick = MinecraftServer.currentTick; // CraftBukkit this.conversionTime = ticksUntilWaterConversion; -@@ -287,9 +294,16 @@ public class Zombie extends Monster { +@@ -292,10 +299,17 @@ public class Zombie extends Monster { } -+ public boolean shouldBurnInDay() { return isSunSensitive(); } // Paper - OBFHELPER ++ public boolean isSunSensitivePublic() { return this.isSunSensitive(); } // Paper - public getter protected boolean isSunSensitive() { - return true; + return this.shouldBurnInDay; // Paper - use api value instead -+ } -+ + } + + // Paper start + public void setShouldBurnInDay(boolean shouldBurnInDay) { + this.shouldBurnInDay = shouldBurnInDay; - } ++ } + // Paper end - ++ @Override public boolean hurt(DamageSource source, float amount) { -@@ -410,6 +424,7 @@ public class Zombie extends Monster { - tag.putBoolean("CanBreakDoors", this.canBreakDoors()); - tag.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1); - tag.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1); -+ tag.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); // Paper + if (!super.hurt(source, amount)) { +@@ -415,6 +429,7 @@ public class Zombie extends Monster { + nbt.putBoolean("CanBreakDoors", this.canBreakDoors()); + nbt.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1); + nbt.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1); ++ nbt.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Paper } @Override -@@ -421,7 +436,11 @@ public class Zombie extends Monster { - if (tag.contains("DrownedConversionTime", 99) && tag.getInt("DrownedConversionTime") > -1) { - this.startUnderWaterConversion(tag.getInt("DrownedConversionTime")); +@@ -426,6 +441,11 @@ public class Zombie extends Monster { + if (nbt.contains("DrownedConversionTime", 99) && nbt.getInt("DrownedConversionTime") > -1) { + this.startUnderWaterConversion(nbt.getInt("DrownedConversionTime")); } -- + // Paper start -+ if (tag.contains("Paper.ShouldBurnInDay")) { -+ shouldBurnInDay = tag.getBoolean("Paper.ShouldBurnInDay"); ++ if (nbt.contains("Paper.ShouldBurnInDay")) { ++ this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay"); + } + // Paper end + } - @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 038793987338c2e4b73784a10836f85c7061175a..86f65c07806a118c49e900c59be86c2bd2eb124c 100644 +index 2e643e92569512ac4e75c0ef2ee7aa4b688e7356..41b5059f6fde8a1afa8c70b983750854ac0207a6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java @@ -93,6 +93,42 @@ public class CraftZombie extends CraftMonster implements Zombie { @@ -94,7 +94,7 @@ index 038793987338c2e4b73784a10836f85c7061175a..86f65c07806a118c49e900c59be86c2b + + @Override + public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); ++ return getHandle().isSunSensitivePublic(); + } + + @Override diff --git a/patches/server-remapped/0313-Book-Size-Limits.patch b/patches/server/0295-Book-Size-Limits.patch similarity index 86% rename from patches/server-remapped/0313-Book-Size-Limits.patch rename to patches/server/0295-Book-Size-Limits.patch index ef45bdd8d0..0ac81c635d 100644 --- a/patches/server-remapped/0313-Book-Size-Limits.patch +++ b/patches/server/0295-Book-Size-Limits.patch @@ -6,32 +6,34 @@ Subject: [PATCH] Book Size Limits Puts some limits on the size of books. diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 3139c194f9b1bc3510d51a81f13ae43d00a3dc29..13edb435b3fa65b4980bd7472aa5a5196f4d5b2b 100644 +index 11d628869a9a6eda8bf21a4f213ff23ad753b18e..8bf4d2b8c38c02d6a5b2fea37113689a252f1571 100644 --- a/src/main/java/com/destroystokyo/paper/PaperConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -339,4 +339,11 @@ public class PaperConfig { - velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); +@@ -347,6 +347,13 @@ public class PaperConfig { } } -+ + + public static int maxBookPageSize = 2560; + public static double maxBookTotalSizeMultiplier = 0.98D; + private static void maxBookSize() { + maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); + maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); + } - } ++ + public static boolean asyncChunks = false; + private static void asyncChunks() { + ConfigurationSection section; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index a6ad7747396f94def688b4d2783137180dc2bb84..b1c505d3fdcc2fb3496f80bee85e4895b9069dcb 100644 +index 8b716c625c363d7143fe6fbc26d3d674d62a5833..f1a8470d0b314c8fa5eade198cffc1f8cd5e6832 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -999,6 +999,52 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1002,6 +1002,52 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @Override public void handleEditBook(ServerboundEditBookPacket packet) { + // Paper start + ItemStack testStack = packet.getBook(); -+ if (!craftServer.isPrimaryThread() && !testStack.isEmpty() && testStack.getTag() != null) { ++ if (!this.cserver.isPrimaryThread() && !testStack.isEmpty() && testStack.getTag() != null) { + ListTag pageList = testStack.getTag().getList("pages", 8); + if (pageList.size() > 100) { + ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with too many pages"); diff --git a/patches/server-remapped/0319-Add-PlayerConnectionCloseEvent.patch b/patches/server/0296-Add-PlayerConnectionCloseEvent.patch similarity index 77% rename from patches/server-remapped/0319-Add-PlayerConnectionCloseEvent.patch rename to patches/server/0296-Add-PlayerConnectionCloseEvent.patch index 12d0a9084e..602d72fd60 100644 --- a/patches/server-remapped/0319-Add-PlayerConnectionCloseEvent.patch +++ b/patches/server/0296-Add-PlayerConnectionCloseEvent.patch @@ -34,11 +34,11 @@ how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent is undefined. diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 35191d968fd30db16213540ef7121f4dede68e68..3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4 100644 +index 8bbf13a7aea1142b3154a1c76837a98aa5ed431d..9f0537799a3cae43fb120056b8fe805a4883cc4d 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java -@@ -350,6 +350,26 @@ public class Connection extends SimpleChannelInboundHandler> { - this.getPacketListener().a(new TranslatableComponent("multiplayer.disconnect.generic")); +@@ -418,6 +418,26 @@ public class Connection extends SimpleChannelInboundHandler> { + this.getPacketListener().onDisconnect(new TranslatableComponent("multiplayer.disconnect.generic")); } this.queue.clear(); // Free up packet queue. + // Paper start - Add PlayerConnectionCloseEvent @@ -65,18 +65,19 @@ index 35191d968fd30db16213540ef7121f4dede68e68..3247ec5d6cf329ba0b7e6d5a6c3294de } diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 22d6f41001977917ec75046252cbf7157b92396d..9631fa93b821c7f6bc6dc707c2c82cce2ae8291e 100644 +index a196ab2510a1c302ef1c946400c1a7c07619994a..abbd1926107b49f9b7c8097419ba19baf6f6b7d3 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -55,9 +55,9 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -56,10 +56,10 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener private final byte[] nonce = new byte[4]; - private final MinecraftServer server; + final MinecraftServer server; public final Connection connection; -- private ServerLoginPacketListenerImpl.State state; -+ private ServerLoginPacketListenerImpl.State state; public final ServerLoginPacketListenerImpl.State getLoginState() { return this.state; }; // Paper - OBFHELPER +- ServerLoginPacketListenerImpl.State state; ++ ServerLoginPacketListenerImpl.State state; public final ServerLoginPacketListenerImpl.State getLoginState() { return this.state; }; // Paper - OBFHELPER private int tick; -- private GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } private GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER -+ private GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } public GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER + @Nullable +- GameProfile gameProfile; ++ GameProfile gameProfile; private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } public GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER private final String serverId; - private SecretKey secretKey; + @Nullable private ServerPlayer delayedAcceptPlayer; diff --git a/patches/server-remapped/0320-Prevent-Enderman-from-loading-chunks.patch b/patches/server/0297-Prevent-Enderman-from-loading-chunks.patch similarity index 76% rename from patches/server-remapped/0320-Prevent-Enderman-from-loading-chunks.patch rename to patches/server/0297-Prevent-Enderman-from-loading-chunks.patch index b1074d223b..98c1b48303 100644 --- a/patches/server-remapped/0320-Prevent-Enderman-from-loading-chunks.patch +++ b/patches/server/0297-Prevent-Enderman-from-loading-chunks.patch @@ -5,20 +5,10 @@ Subject: [PATCH] Prevent Enderman from loading chunks diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -index d190b58bea310f4006ea3deaf0d42c502d441284..dae35d3f758e40c1edf31b11c6e11f1b7bb2dfae 100644 +index abd1130529dd74780054e26bac89cf757ba9cdc1..a39f4a1585ba888d27588a86130f6dae24f5a71b 100644 --- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -@@ -434,7 +434,8 @@ public class EnderMan extends Monster implements NeutralMob { - int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 3.0D); - int k = Mth.floor(this.enderman.getZ() - 2.0D + random.nextDouble() * 4.0D); - BlockPos blockposition = new BlockPos(i, j, k); -- BlockState iblockdata = world.getBlockState(blockposition); -+ BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return; // Paper - Block block = iblockdata.getBlock(); - Vec3 vec3d = new Vec3((double) Mth.floor(this.enderman.getX()) + 0.5D, (double) j + 0.5D, (double) Mth.floor(this.enderman.getZ()) + 0.5D); - Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); -@@ -474,7 +475,8 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -465,7 +465,8 @@ public class EnderMan extends Monster implements NeutralMob { int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 2.0D); int k = Mth.floor(this.enderman.getZ() - 1.0D + random.nextDouble() * 2.0D); BlockPos blockposition = new BlockPos(i, j, k); @@ -28,3 +18,13 @@ index d190b58bea310f4006ea3deaf0d42c502d441284..dae35d3f758e40c1edf31b11c6e11f1b BlockPos blockposition1 = blockposition.below(); BlockState iblockdata1 = world.getBlockState(blockposition1); BlockState iblockdata2 = this.enderman.getCarriedBlock(); +@@ -511,7 +512,8 @@ public class EnderMan extends Monster implements NeutralMob { + int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 3.0D); + int k = Mth.floor(this.enderman.getZ() - 2.0D + random.nextDouble() * 4.0D); + BlockPos blockposition = new BlockPos(i, j, k); +- BlockState iblockdata = world.getBlockState(blockposition); ++ BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper ++ if (iblockdata == null) return; // Paper + Vec3 vec3d = new Vec3((double) this.enderman.getBlockX() + 0.5D, (double) j + 0.5D, (double) this.enderman.getBlockZ() + 0.5D); + Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); + BlockHitResult movingobjectpositionblock = world.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman)); diff --git a/patches/server-remapped/0321-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/patches/server/0298-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 86% rename from patches/server-remapped/0321-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to patches/server/0298-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch index 491b5bd0f8..0cd88c9770 100644 --- a/patches/server-remapped/0321-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch +++ b/patches/server/0298-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch @@ -16,10 +16,10 @@ 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 416c21f0a6be8d71a654e18f7ea0fa074f8fc5ff..1fa4f58658ff98396eb5abfc27e19e5832d56f5a 100644 +index 963a3c159e912a39b98dfcb3fdb8c384765990d7..44da4efc23a3273449431845308ba889615ac425 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -211,6 +211,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -218,6 +218,7 @@ public class ServerPlayer extends Player { public int latency; public boolean wonGame; private int containerUpdateDelay; // Paper @@ -28,10 +28,10 @@ index 416c21f0a6be8d71a654e18f7ea0fa074f8fc5ff..1fa4f58658ff98396eb5abfc27e19e58 public boolean queueHealthUpdatePacket = false; public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7c307a16ca3962db65be09a0ddd058a4ce81c7be..5b71b487836cdd2ddc75b2039f4dc0177719d345 100644 +index b62aa9f934c33b4d22b985b5e56937baa8454677..0df68991eb2ef3dabe779f42c2bf44846ac0d862 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -164,6 +164,7 @@ public abstract class PlayerList { +@@ -169,6 +169,7 @@ public abstract class PlayerList { } public void placeNewPlayer(Connection connection, ServerPlayer player) { @@ -40,11 +40,11 @@ index 7c307a16ca3962db65be09a0ddd058a4ce81c7be..5b71b487836cdd2ddc75b2039f4dc017 GameProfileCache usercache = this.server.getProfileCache(); GameProfile gameprofile1 = usercache.get(gameprofile.getId()); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -index 1eeb1d1fe54eba68652be8dba52dce8ca91d948d..19aee8c6d0989bcf263e27adab42b3e6e411b66f 100644 +index 93de44b05a698515457052c9c684c4ef44c5cc40..b20bfe5ab165bf86985e5ff2f93f415d9710e0e4 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java @@ -244,6 +244,61 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa - return getData() != null; + return this.getData() != null; } + // Paper start @@ -104,12 +104,12 @@ index 1eeb1d1fe54eba68652be8dba52dce8ca91d948d..19aee8c6d0989bcf263e27adab42b3e6 + @Override public Location getBedSpawnLocation() { - CompoundTag data = getData(); + CompoundTag data = this.getData(); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index a3e65028d3e0c09a65cd9c28b037fe01a2ed1d76..ba03a1cdac68dc08ed878e311adeebc531e8f2f1 100644 +index 686dc5859c081d3b86d8e58a63abee49258208d7..f0bdf17d86458da3678945aeb23fdb5bceabc366 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -144,6 +144,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -150,6 +150,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; private String resourcePackHash; private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit @@ -117,7 +117,7 @@ index a3e65028d3e0c09a65cd9c28b037fe01a2ed1d76..ba03a1cdac68dc08ed878e311adeebc5 // Paper end public CraftPlayer(CraftServer server, ServerPlayer entity) { -@@ -1480,6 +1481,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1502,6 +1503,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.firstPlayed = firstPlayed; } @@ -134,9 +134,9 @@ index a3e65028d3e0c09a65cd9c28b037fe01a2ed1d76..ba03a1cdac68dc08ed878e311adeebc5 + // Paper end + public void readExtraData(CompoundTag nbttagcompound) { - hasPlayedBefore = true; + this.hasPlayedBefore = true; if (nbttagcompound.contains("bukkit")) { -@@ -1502,6 +1515,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1524,6 +1537,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void setExtraData(CompoundTag nbttagcompound) { @@ -145,8 +145,8 @@ index a3e65028d3e0c09a65cd9c28b037fe01a2ed1d76..ba03a1cdac68dc08ed878e311adeebc5 if (!nbttagcompound.contains("bukkit")) { nbttagcompound.put("bukkit", new CompoundTag()); } -@@ -1516,6 +1531,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - data.putLong("firstPlayed", getFirstPlayed()); +@@ -1538,6 +1553,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-remapped/0322-Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/patches/server/0299-Workaround-for-vehicle-tracking-issue-on-disconnect.patch similarity index 83% rename from patches/server-remapped/0322-Workaround-for-vehicle-tracking-issue-on-disconnect.patch rename to patches/server/0299-Workaround-for-vehicle-tracking-issue-on-disconnect.patch index 4645205240..f822adc555 100644 --- a/patches/server-remapped/0322-Workaround-for-vehicle-tracking-issue-on-disconnect.patch +++ b/patches/server/0299-Workaround-for-vehicle-tracking-issue-on-disconnect.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Workaround for vehicle tracking issue on disconnect diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 1fa4f58658ff98396eb5abfc27e19e5832d56f5a..fd2717a00a85f91ee23a1c0f929f856972892a9b 100644 +index 44da4efc23a3273449431845308ba889615ac425..955a7fcd80a57f920e402a5533f5029b9683104c 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1524,6 +1524,13 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1538,6 +1538,13 @@ public class ServerPlayer extends Player { public void disconnect() { this.disconnected = true; this.ejectPassengers(); diff --git a/patches/server-remapped/0323-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/patches/server/0300-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch similarity index 91% rename from patches/server-remapped/0323-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch rename to patches/server/0300-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch index 7b22e86252..e6dd1bd4fb 100644 --- a/patches/server-remapped/0323-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch +++ b/patches/server/0300-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch @@ -24,10 +24,10 @@ Instead we opt to remove the check entirely so that the event fires for all piston types. diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -index 878cec21b52fb62369310c2f85001e859a270dd8..dc9584a30c18d964afd9cc118c81c24a80beba63 100644 +index ca9e94b92d26eb6cd3ca6ff4b8cb1cd98aabf4e0..c345bd7542f3ffa09719864887e1516f1182e7e3 100644 --- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -@@ -140,7 +140,7 @@ public class PistonBaseBlock extends DirectionalBlock { +@@ -147,7 +147,7 @@ public class PistonBaseBlock extends DirectionalBlock { } // CraftBukkit start @@ -36,7 +36,7 @@ index 878cec21b52fb62369310c2f85001e859a270dd8..dc9584a30c18d964afd9cc118c81c24a org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); world.getCraftServer().getPluginManager().callEvent(event); -@@ -148,7 +148,7 @@ public class PistonBaseBlock extends DirectionalBlock { +@@ -155,7 +155,7 @@ public class PistonBaseBlock extends DirectionalBlock { if (event.isCancelled()) { return; } diff --git a/patches/server-remapped/0324-Block-Entity-remove-from-being-called-on-Players.patch b/patches/server/0301-Block-Entity-remove-from-being-called-on-Players.patch similarity index 89% rename from patches/server-remapped/0324-Block-Entity-remove-from-being-called-on-Players.patch rename to patches/server/0301-Block-Entity-remove-from-being-called-on-Players.patch index 8ac3978e9f..6980a2b26a 100644 --- a/patches/server-remapped/0324-Block-Entity-remove-from-being-called-on-Players.patch +++ b/patches/server/0301-Block-Entity-remove-from-being-called-on-Players.patch @@ -12,10 +12,10 @@ Player we will look at limiting the scope of this change. It appears to be unintentional in the few cases we've seen so far. diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ba03a1cdac68dc08ed878e311adeebc531e8f2f1..c2c6eb54096ef85b01c0b700cbe6a8054b62729f 100644 +index f0bdf17d86458da3678945aeb23fdb5bceabc366..2ed7920b0e046bc9d581878a10b04ad784bb8655 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2231,6 +2231,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2255,6 +2255,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public void resetCooldown() { getHandle().resetAttackStrengthTicker(); } diff --git a/patches/server-remapped/0325-BlockDestroyEvent.patch b/patches/server/0302-BlockDestroyEvent.patch similarity index 88% rename from patches/server-remapped/0325-BlockDestroyEvent.patch rename to patches/server/0302-BlockDestroyEvent.patch index 497abbdeb1..1f3060877f 100644 --- a/patches/server-remapped/0325-BlockDestroyEvent.patch +++ b/patches/server/0302-BlockDestroyEvent.patch @@ -11,18 +11,18 @@ floating in the air. This can replace many uses of BlockPhysicsEvent diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index b75ffafb6840b6acab6e5b0ef5e222c4fa130977..c8542636e89748699d608eb29569cacb6321d334 100644 +index 8d4f8719b30a66fbb68c9407ee8484312f05b3fb..a1b713391c2445967c3b5a645304f193c013d551 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -27,6 +27,7 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.ClientboundSetBorderPacket; +@@ -28,6 +28,7 @@ import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.protocol.Packet; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MCUtil; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ServerLevel; -@@ -559,8 +560,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -567,8 +568,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable { return false; } else { FluidState fluid = this.getFluidState(pos); diff --git a/patches/server-remapped/0326-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/patches/server/0303-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch similarity index 89% rename from patches/server-remapped/0326-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch rename to patches/server/0303-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch index 941fce8c3e..408be3ab4b 100644 --- a/patches/server-remapped/0326-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch +++ b/patches/server/0303-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch @@ -10,10 +10,10 @@ This made the Bukkit RecipeChoice API not work for Shapeless. This reimplements vanilla logic using the same test logic as Shaped diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java -index 7bd62f598f3fff7520c276bdc45e538bd3260bc9..a8d0a90d36d58515bb6f6128de1ef15b72c20c17 100644 +index 4e1159b3188d39c998e6887c2846209c10b701f9..6b960f0a31175bcfd8d477ee5b3c4d783303cdd5 100644 --- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java +++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java -@@ -71,16 +71,49 @@ public class ShapelessRecipe implements CraftingRecipe { +@@ -76,16 +76,49 @@ public class ShapelessRecipe implements CraftingRecipe { StackedContents autorecipestackmanager = new StackedContents(); int i = 0; @@ -22,8 +22,8 @@ index 7bd62f598f3fff7520c276bdc45e538bd3260bc9..a8d0a90d36d58515bb6f6128de1ef15b + co.aikar.util.Counter matchedProvided = new co.aikar.util.Counter<>(); + co.aikar.util.Counter matchedIngredients = new co.aikar.util.Counter<>(); + // Paper end - for (int j = 0; j < inv.getContainerSize(); ++j) { - ItemStack itemstack = inv.getItem(j); + for (int j = 0; j < inventory.getContainerSize(); ++j) { + ItemStack itemstack = inventory.getItem(j); if (!itemstack.isEmpty()) { - ++i; @@ -65,4 +65,4 @@ index 7bd62f598f3fff7520c276bdc45e538bd3260bc9..a8d0a90d36d58515bb6f6128de1ef15b + // Paper end } - public ItemStack assemble(CraftingContainer inv) { + public ItemStack assemble(CraftingContainer inventory) { diff --git a/patches/server-remapped/0328-Limit-Client-Sign-length-more.patch b/patches/server/0304-Limit-Client-Sign-length-more.patch similarity index 54% rename from patches/server-remapped/0328-Limit-Client-Sign-length-more.patch rename to patches/server/0304-Limit-Client-Sign-length-more.patch index da033509aa..877afd37b9 100644 --- a/patches/server-remapped/0328-Limit-Client-Sign-length-more.patch +++ b/patches/server/0304-Limit-Client-Sign-length-more.patch @@ -22,10 +22,10 @@ it only impacts data sent from the client. Set -DPaper.maxSignLength=XX to change limit or -1 to disable diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 276773e17149f57038cd21485fd9d9061670ff2d..d6d8d83bc16572474d56a278dd119eacc2c52476 100644 +index f1a8470d0b314c8fa5eade198cffc1f8cd5e6832..defebf7b45e4f006fa7e575b5dbd01ac1e231d5a 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -254,6 +254,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -255,6 +255,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser private int aboveGroundVehicleTickCount; private int receivedMovePacketCount; private int knownMovePacketCount; @@ -33,22 +33,26 @@ index 276773e17149f57038cd21485fd9d9061670ff2d..d6d8d83bc16572474d56a278dd119eac private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { -@@ -2860,7 +2861,17 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2867,10 +2868,20 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser List lines = new java.util.ArrayList<>(); for (int i = 0; i < list.size(); ++i) { -- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. + // Paper start - cap line length - modified clients can send longer data than normal -+ String currentLine = list.get(i); -+ if (MAX_SIGN_LINE_LENGTH > 0 && currentLine.length() > MAX_SIGN_LINE_LENGTH) { ++ net.minecraft.server.network.TextFilter.FilteredText currentLine = list.get(i); ++ if (MAX_SIGN_LINE_LENGTH > 0 && currentLine.getRaw().length() > MAX_SIGN_LINE_LENGTH) { + // This handles multibyte characters as 1 -+ int offset = currentLine.codePoints().limit(MAX_SIGN_LINE_LENGTH).map(Character::charCount).sum(); -+ if (offset < currentLine.length()) { -+ list.set(i, currentLine = currentLine.substring(0, offset)); ++ int offset = currentLine.getRaw().codePoints().limit(MAX_SIGN_LINE_LENGTH).map(Character::charCount).sum(); ++ if (offset < currentLine.getRaw().length()) { ++ list.set(i, currentLine = net.minecraft.server.network.TextFilter.FilteredText.passThrough(currentLine.getRaw().substring(0, offset))); // this will break any filtering, but filtering is NYI as of 1.17 + } + } + // Paper end -+ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(currentLine))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. + if (this.player.isTextFilteringEnabled()) { +- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(list.get(i).getFiltered()))); ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(currentLine.getFiltered()))); + } else { +- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(list.get(i).getRaw()))); ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(currentLine.getRaw()))); + } } - SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.craftServer.getPluginManager().callEvent(event); + SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.cserver.getPlayer(this.player), lines); From b8b3c400230a78cd550c89a5ca21aae0d2fdee80 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 01:40:50 -0700 Subject: [PATCH 069/226] patch --- ...k-ConvertSigns-boolean-every-sign-save.patch} | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) rename patches/{server-remapped/0329-Don-t-check-ConvertSigns-boolean-every-sign-save.patch => server/0305-Don-t-check-ConvertSigns-boolean-every-sign-save.patch} (64%) diff --git a/patches/server-remapped/0329-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/patches/server/0305-Don-t-check-ConvertSigns-boolean-every-sign-save.patch similarity index 64% rename from patches/server-remapped/0329-Don-t-check-ConvertSigns-boolean-every-sign-save.patch rename to patches/server/0305-Don-t-check-ConvertSigns-boolean-every-sign-save.patch index e847f69596..4ca9291478 100644 --- a/patches/server-remapped/0329-Don-t-check-ConvertSigns-boolean-every-sign-save.patch +++ b/patches/server/0305-Don-t-check-ConvertSigns-boolean-every-sign-save.patch @@ -7,23 +7,21 @@ property lookups arent super cheap. they synchronize, validate and check security managers. diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -index 0b26d3ab2db66d6baaa95d1d5f6c756595d31495..8d619e0bf8bcf7d6d4e7f23f11d648ccfb65cac4 100644 +index 589fbdd5c86655244aa92a42e5f45747b5c5026e..bc0e5df6c7e4a5784c3194c716dd2bb033aea9e5 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -@@ -31,6 +31,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C - private final FormattedCharSequence[] renderMessages; - private DyeColor color; - public java.util.UUID signEditor; // Paper +@@ -1,4 +1,5 @@ + package net.minecraft.world.level.block.entity; + private static final boolean CONVERT_LEGACY_SIGNS = Boolean.getBoolean("convertLegacySigns"); // Paper - public SignBlockEntity() { - super(BlockEntityType.SIGN); -@@ -51,7 +52,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import java.util.UUID; +@@ -66,7 +67,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C } // CraftBukkit start - if (Boolean.getBoolean("convertLegacySigns")) { + if (CONVERT_LEGACY_SIGNS) { // Paper - tag.putBoolean("Bukkit.isConverted", true); + nbt.putBoolean("Bukkit.isConverted", true); } // CraftBukkit end From 76a75fc35ad59bf0eab753a8c0f149376368cfaa Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 01:45:29 -0700 Subject: [PATCH 070/226] fix compile --- .../server/0296-Add-PlayerConnectionCloseEvent.patch | 11 ++++++++++- ...-check-ConvertSigns-boolean-every-sign-save.patch | 12 +++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/patches/server/0296-Add-PlayerConnectionCloseEvent.patch b/patches/server/0296-Add-PlayerConnectionCloseEvent.patch index 602d72fd60..ef06807c6c 100644 --- a/patches/server/0296-Add-PlayerConnectionCloseEvent.patch +++ b/patches/server/0296-Add-PlayerConnectionCloseEvent.patch @@ -65,7 +65,7 @@ index 8bbf13a7aea1142b3154a1c76837a98aa5ed431d..9f0537799a3cae43fb120056b8fe805a } diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index a196ab2510a1c302ef1c946400c1a7c07619994a..abbd1926107b49f9b7c8097419ba19baf6f6b7d3 100644 +index a196ab2510a1c302ef1c946400c1a7c07619994a..46432534fddbbf78e3bf46385b9638d2f92c951f 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -56,10 +56,10 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener @@ -81,3 +81,12 @@ index a196ab2510a1c302ef1c946400c1a7c07619994a..abbd1926107b49f9b7c8097419ba19ba private final String serverId; @Nullable private ServerPlayer delayedAcceptPlayer; +@@ -441,7 +441,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + return new GameProfile(uuid, profile.getName()); + } + +- private static enum State { ++ public static enum State { // Paper - make public + + HELLO, KEY, AUTHENTICATING, NEGOTIATING, READY_TO_ACCEPT, DELAY_ACCEPT, ACCEPTED; + diff --git a/patches/server/0305-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/patches/server/0305-Don-t-check-ConvertSigns-boolean-every-sign-save.patch index 4ca9291478..5032a2a1f6 100644 --- a/patches/server/0305-Don-t-check-ConvertSigns-boolean-every-sign-save.patch +++ b/patches/server/0305-Don-t-check-ConvertSigns-boolean-every-sign-save.patch @@ -7,15 +7,17 @@ property lookups arent super cheap. they synchronize, validate and check security managers. diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -index 589fbdd5c86655244aa92a42e5f45747b5c5026e..bc0e5df6c7e4a5784c3194c716dd2bb033aea9e5 100644 +index 589fbdd5c86655244aa92a42e5f45747b5c5026e..9b5d11ece006d7aa893360a84ba652c666517ac1 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -@@ -1,4 +1,5 @@ - package net.minecraft.world.level.block.entity; +@@ -26,6 +26,7 @@ import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + + public class SignBlockEntity extends BlockEntity implements CommandSource { // CraftBukkit - implements + private static final boolean CONVERT_LEGACY_SIGNS = Boolean.getBoolean("convertLegacySigns"); // Paper - import com.mojang.brigadier.exceptions.CommandSyntaxException; - import java.util.UUID; + public static final int LINES = 4; + private static final String[] RAW_TEXT_FIELD_NAMES = new String[]{"Text1", "Text2", "Text3", "Text4"}; @@ -66,7 +67,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C } From d42140148f655a3a3d70c69979ecc03ca34b8af1 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Sun, 13 Jun 2021 11:41:07 +0200 Subject: [PATCH 071/226] Work --- build.gradle.kts | 2 +- .../0171-Annotation-Test-changes.patch | 0 .../0172-Entity-getEntitySpawnReason.patch | 10 +- .../0173-Add-GS4-Query-event.patch | 0 .../0174-Add-PlayerPostRespawnEvent.patch | 0 ...334-Allow-Saving-of-Oversized-Chunks.patch | 2 + ...le-Oversized-Tile-Entities-in-chunks.patch | 54 ---- ...ity-Metadata-for-all-tracked-players.patch | 43 --- .../0640-Fire-event-on-GS4-query.patch | 265 ------------------ ...Manager-and-add-advanced-packet-sup.patch} | 233 +++++---------- ...le-Oversized-Tile-Entities-in-chunks.patch | 50 ++++ ...-Fix-Whitelist-On-Off-inconsistency.patch} | 21 +- ...t-tick-at-start-of-drowning-process.patch} | 4 +- ...ggleEvent-when-whitelist-is-toggled.patch} | 4 +- ...ngth-when-serialising-BungeeCord-te.patch} | 14 +- .../0312-Entity-getEntitySpawnReason.patch} | 62 ++-- ...ity-Metadata-for-all-tracked-players.patch | 76 +++++ .../server/0314-Fire-event-on-GS4-query.patch | 209 ++++++++++++++ ...15-Implement-PlayerPostRespawnEvent.patch} | 10 +- settings.gradle.kts | 1 + 20 files changed, 466 insertions(+), 594 deletions(-) rename patches/{api-unmapped => api}/0171-Annotation-Test-changes.patch (100%) rename patches/{api-unmapped => api}/0172-Entity-getEntitySpawnReason.patch (78%) rename patches/{api-unmapped => api}/0173-Add-GS4-Query-event.patch (100%) rename patches/{api-unmapped => api}/0174-Add-PlayerPostRespawnEvent.patch (100%) rename patches/{server-remapped => removed/1.17}/0334-Allow-Saving-of-Oversized-Chunks.patch (98%) delete mode 100644 patches/server-remapped/0331-Handle-Oversized-Tile-Entities-in-chunks.patch delete mode 100644 patches/server-remapped/0339-Update-entity-Metadata-for-all-tracked-players.patch delete mode 100644 patches/server-remapped/0640-Fire-event-on-GS4-query.patch rename patches/{server-remapped/0330-Optimize-Network-Manager-and-add-advanced-packet-sup.patch => server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch} (51%) create mode 100644 patches/server/0307-Handle-Oversized-Tile-Entities-in-chunks.patch rename patches/{server-remapped/0332-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch => server/0308-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch} (62%) rename patches/{server-remapped/0333-Set-Zombie-last-tick-at-start-of-drowning-process.patch => server/0309-Set-Zombie-last-tick-at-start-of-drowning-process.patch} (85%) rename patches/{server-remapped/0335-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch => server/0310-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch} (82%) rename patches/{server-remapped/0337-Use-proper-max-length-when-serialising-BungeeCord-te.patch => server/0311-Use-proper-max-length-when-serialising-BungeeCord-te.patch} (70%) rename patches/{server-remapped/0338-Entity-getEntitySpawnReason.patch => server/0312-Entity-getEntitySpawnReason.patch} (67%) create mode 100644 patches/server/0313-Update-entity-Metadata-for-all-tracked-players.patch create mode 100644 patches/server/0314-Fire-event-on-GS4-query.patch rename patches/{server-remapped/0340-Implement-PlayerPostRespawnEvent.patch => server/0315-Implement-PlayerPostRespawnEvent.patch} (82%) diff --git a/build.gradle.kts b/build.gradle.kts index 407f27e9d2..101bc900a8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight.core") version "1.0.0-SNAPSHOT" + id("io.papermc.paperweight.core") version "1.0.0-LOCAL-SNAPSHOT" } val mcVersion = providers.gradleProperty("mcVersion") diff --git a/patches/api-unmapped/0171-Annotation-Test-changes.patch b/patches/api/0171-Annotation-Test-changes.patch similarity index 100% rename from patches/api-unmapped/0171-Annotation-Test-changes.patch rename to patches/api/0171-Annotation-Test-changes.patch diff --git a/patches/api-unmapped/0172-Entity-getEntitySpawnReason.patch b/patches/api/0172-Entity-getEntitySpawnReason.patch similarity index 78% rename from patches/api-unmapped/0172-Entity-getEntitySpawnReason.patch rename to patches/api/0172-Entity-getEntitySpawnReason.patch index 080a5c3186..0a38cac838 100644 --- a/patches/api-unmapped/0172-Entity-getEntitySpawnReason.patch +++ b/patches/api/0172-Entity-getEntitySpawnReason.patch @@ -10,13 +10,13 @@ persistenting Living Entity, SPAWNER for spawners, or DEFAULT since data was not stored. diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 4b1f9b0ad5dc9ad6f33fddafc376b6f983a556ef..5b382091b1466b25ad42325d5808785a8e948552 100644 +index 92927b9a90b2a4497dd572f6f752c40cf35dd8b8..4a6d58ef68b782291b4d26a8515be326481f5209 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -708,5 +708,11 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - */ - @NotNull - Chunk getChunk(); +@@ -711,5 +711,11 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + // TODO remove impl here + return getLocation().getChunk(); + } + + /** + * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity. diff --git a/patches/api-unmapped/0173-Add-GS4-Query-event.patch b/patches/api/0173-Add-GS4-Query-event.patch similarity index 100% rename from patches/api-unmapped/0173-Add-GS4-Query-event.patch rename to patches/api/0173-Add-GS4-Query-event.patch diff --git a/patches/api-unmapped/0174-Add-PlayerPostRespawnEvent.patch b/patches/api/0174-Add-PlayerPostRespawnEvent.patch similarity index 100% rename from patches/api-unmapped/0174-Add-PlayerPostRespawnEvent.patch rename to patches/api/0174-Add-PlayerPostRespawnEvent.patch diff --git a/patches/server-remapped/0334-Allow-Saving-of-Oversized-Chunks.patch b/patches/removed/1.17/0334-Allow-Saving-of-Oversized-Chunks.patch similarity index 98% rename from patches/server-remapped/0334-Allow-Saving-of-Oversized-Chunks.patch rename to patches/removed/1.17/0334-Allow-Saving-of-Oversized-Chunks.patch index c23cb450e8..2c2f7bdb5a 100644 --- a/patches/server-remapped/0334-Allow-Saving-of-Oversized-Chunks.patch +++ b/patches/removed/1.17/0334-Allow-Saving-of-Oversized-Chunks.patch @@ -3,6 +3,8 @@ From: Aikar Date: Fri, 15 Feb 2019 01:08:19 -0500 Subject: [PATCH] Allow Saving of Oversized Chunks +Note 1.17 update: With 1.17, Entities are no longer stored in chunk slices, so this needs updating!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + The Minecraft World Region File format has a hard cap of 1MB per chunk. This is due to the fact that the header of the file format only allocates a single byte for sector count, meaning a maximum of 256 sectors, at 4k per sector. diff --git a/patches/server-remapped/0331-Handle-Oversized-Tile-Entities-in-chunks.patch b/patches/server-remapped/0331-Handle-Oversized-Tile-Entities-in-chunks.patch deleted file mode 100644 index 83303e9b30..0000000000 --- a/patches/server-remapped/0331-Handle-Oversized-Tile-Entities-in-chunks.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 05:00:57 -0400 -Subject: [PATCH] Handle Oversized Tile Entities in chunks - -Splits out Extra Packets if too many TE's are encountered to prevent -creating too large of a packet to sed. - -Co authored by Spottedleaf - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -index b7d303b5f51a35504888933efef74564fa01e59d..b587f774c8f88f2a1c3ea489f7e4fe0bbdeb5a41 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -@@ -34,7 +34,15 @@ public class ClientboundLevelChunkPacket implements Packet extraPackets = new java.util.ArrayList<>(); -+ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); - -+ @Override -+ public java.util.List getExtraPackets() { -+ return extraPackets; -+ } -+ // Paper end - public ClientboundLevelChunkPacket(LevelChunk chunk, int includedSectionsMask) { - ChunkPos chunkcoordintpair = chunk.getPos(); - -@@ -61,6 +69,7 @@ public class ClientboundLevelChunkPacket implements Packet> 4; - - if (this.isFullChunk() || (includedSectionsMask & 1 << j) != 0) { -+ // Paper start - improve oversized chunk data packet handling -+ if (++totalTileEntities > TE_LIMIT) { -+ ClientboundBlockEntityDataPacket updatePacket = tileentity.getUpdatePacket(); -+ if (updatePacket != null) { -+ this.extraPackets.add(updatePacket); -+ continue; -+ } -+ } -+ // Paper end - CompoundTag nbttagcompound = tileentity.getUpdateTag(); - if (tileentity instanceof SkullBlockEntity) { SkullBlockEntity.sanitizeTileEntityUUID(nbttagcompound); } // Paper - diff --git a/patches/server-remapped/0339-Update-entity-Metadata-for-all-tracked-players.patch b/patches/server-remapped/0339-Update-entity-Metadata-for-all-tracked-players.patch deleted file mode 100644 index 8f0ddb740c..0000000000 --- a/patches/server-remapped/0339-Update-entity-Metadata-for-all-tracked-players.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AgentTroll -Date: Fri, 22 Mar 2019 22:24:03 -0700 -Subject: [PATCH] Update entity Metadata for all tracked players - - -diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index 49c71b21b6b88bc41ca6ddf4c76186ce522ee456..1609ab94c86e964421f996d4d46aef30f8b8e696 100644 ---- a/src/main/java/net/minecraft/server/level/ServerEntity.java -+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -420,6 +420,12 @@ public class ServerEntity { - return ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp); - } - -+ // Paper start - Add broadcast method -+ void broadcast(Packet packet) { -+ this.getPacketConsumer().accept(packet); -+ } -+ // Paper end -+ - private void broadcastAndSend(Packet packet) { - this.broadcast.accept(packet); - if (this.entity instanceof ServerPlayer) { -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index d6d8d83bc16572474d56a278dd119eacc2c52476..ed4129a51351aff16455960d71a0add1b8209c02 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2286,7 +2286,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - if (event.isCancelled() || this.player.inventory.getSelected() == null || this.player.inventory.getSelected().getItem() != origItem) { - // Refresh the current entity metadata -- this.send(new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true)); -+ // Paper start - update entity for all players -+ ClientboundSetEntityDataPacket packet1 = new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true); -+ if (entity.tracker != null) { -+ entity.tracker.broadcast(packet1); -+ } else { -+ this.send(packet1); -+ } -+ // Paper end - } - - if (event.isCancelled()) { diff --git a/patches/server-remapped/0640-Fire-event-on-GS4-query.patch b/patches/server-remapped/0640-Fire-event-on-GS4-query.patch deleted file mode 100644 index a893ed5f5c..0000000000 --- a/patches/server-remapped/0640-Fire-event-on-GS4-query.patch +++ /dev/null @@ -1,265 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 17 Mar 2019 21:46:56 +0200 -Subject: [PATCH] Fire event on GS4 query - - -diff --git a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java -index d10de580430d754204b36de809376538a14591e6..f6f0539a8e6edbeb1c412cee753a282b24a38046 100644 ---- a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java -+++ b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java -@@ -18,15 +18,27 @@ public class NetworkDataOutputStream { - this.dataOutputStream.write(abyte, 0, abyte.length); - } - -+ public void writeString(String string) throws IOException { this.writeString(string); } // Paper - OBFHELPER - public void writeString(String s) throws IOException { - this.dataOutputStream.writeBytes(s); - this.dataOutputStream.write(0); - } -+ // Paper start - unchecked exception variant to use in Stream API -+ public void writeStringUnchecked(String string) { -+ try { -+ writeString(string); -+ } catch (IOException e) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(e); -+ } -+ } -+ // Paper end - -+ public void writeInt(int i) throws IOException { this.write(i); } // Paper - OBFHELPER - public void write(int i) throws IOException { - this.dataOutputStream.write(i); - } - -+ public void writeShort(short i) throws IOException { this.writeShort(i); } // Paper - OBFHELPER - public void writeShort(short short0) throws IOException { - this.dataOutputStream.writeShort(Short.reverseBytes(short0)); - } -diff --git a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java -index 170d047463154bd6851199f06fe343ccb1896213..5562a3caff328bb08857b4f06a79b1e52f390fdd 100644 ---- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java -+++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java -@@ -16,6 +16,7 @@ import java.util.Random; - import javax.annotation.Nullable; - import net.minecraft.Util; - import net.minecraft.server.ServerInterface; -+import net.minecraft.server.dedicated.DedicatedServer; - import net.minecraft.server.rcon.NetworkDataOutputStream; - import net.minecraft.server.rcon.PktUtils; - import org.apache.logging.log4j.LogManager; -@@ -26,18 +27,18 @@ public class QueryThreadGs4 extends GenericThread { - private static final Logger LOGGER = LogManager.getLogger(); - private long lastChallengeCheck; - private final int port; -- private final int serverPort; -- private final int maxPlayers; -- private final String serverName; -- private final String worldName; -+ private final int serverPort; private final int getServerPort() { return this.serverPort; } // Paper - OBFHELPER -+ private final int maxPlayers; private final int getMaxPlayers() { return this.maxPlayers; } // Paper - OBFHELPER -+ private final String serverName; private final String getMotd() { return this.serverName; } // Paper - OBFHELPER -+ private final String worldName; private final String getWorldName() { return this.worldName; } // Paper - OBFHELPER - private DatagramSocket socket; - private final byte[] buffer = new byte[1460]; -- private String hostIp; -+ private String hostIp; public final String getServerHost() { return this.hostIp; } // Paper - OBFHELPER - private String serverIp; - private final Map validChallenges; -- private final NetworkDataOutputStream rulesResponse; -+ private final NetworkDataOutputStream rulesResponse; private final NetworkDataOutputStream getCachedFullResponse() { return this.rulesResponse; } // Paper - OBFHELPER - private long lastRulesResponse; -- private final ServerInterface serverInterface; -+ private final ServerInterface serverInterface; private final ServerInterface getServer() { return this.serverInterface; } // Paper - OBFHELPER - - private QueryThreadGs4(ServerInterface server, int queryPort) { - super("Query Listener"); -@@ -107,13 +108,39 @@ public class QueryThreadGs4 extends GenericThread { - - remotestatusreply.write((int) 0); - remotestatusreply.writeBytes(this.getIdentBytes(packet.getSocketAddress())); -- remotestatusreply.writeString(this.serverName); -+ /* Paper start - GS4 Query event -+ remotestatusreply.a(this.i); -+ remotestatusreply.a("SMP"); -+ remotestatusreply.a(this.j); -+ remotestatusreply.a(Integer.toString(this.r.getPlayerCount())); -+ remotestatusreply.a(Integer.toString(this.h)); -+ remotestatusreply.a((short) this.g); -+ remotestatusreply.a(this.m); -+ */ -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.BASIC; -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() -+ .motd(this.getMotd()) -+ .map(this.getWorldName()) -+ .currentPlayers(this.getServer().getPlayerCount()) -+ .maxPlayers(this.getMaxPlayers()) -+ .port(this.getServerPort()) -+ .hostname(this.getServerHost()) -+ .gameVersion(this.getServer().getServerVersion()) -+ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) -+ .build(); -+ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = -+ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, packet.getAddress(), queryResponse); -+ queryEvent.callEvent(); -+ queryResponse = queryEvent.getResponse(); -+ remotestatusreply.writeString(queryResponse.getMotd()); - remotestatusreply.writeString("SMP"); -- remotestatusreply.writeString(this.worldName); -- remotestatusreply.writeString(Integer.toString(this.serverInterface.getPlayerCount())); -- remotestatusreply.writeString(Integer.toString(this.maxPlayers)); -- remotestatusreply.writeShort((short) this.serverPort); -- remotestatusreply.writeString(this.hostIp); -+ remotestatusreply.writeString(queryResponse.getMap()); -+ remotestatusreply.writeString(Integer.toString(queryResponse.getCurrentPlayers())); -+ remotestatusreply.writeString(Integer.toString(queryResponse.getMaxPlayers())); -+ remotestatusreply.writeShort((short) queryResponse.getPort()); -+ remotestatusreply.writeString(queryResponse.getHostname()); -+ // Paper end - this.sendTo(remotestatusreply.toByteArray(), packet); - QueryThreadGs4.LOGGER.debug("Status [{}]", socketaddress); - } -@@ -150,41 +177,115 @@ public class QueryThreadGs4 extends GenericThread { - this.rulesResponse.writeString("splitnum"); - this.rulesResponse.write((int) 128); - this.rulesResponse.write((int) 0); -- this.rulesResponse.writeString("hostname"); -- this.rulesResponse.writeString(this.serverName); -- this.rulesResponse.writeString("gametype"); -- this.rulesResponse.writeString("SMP"); -- this.rulesResponse.writeString("game_id"); -- this.rulesResponse.writeString("MINECRAFT"); -- this.rulesResponse.writeString("version"); -- this.rulesResponse.writeString(this.serverInterface.getServerVersion()); -- this.rulesResponse.writeString("plugins"); -- this.rulesResponse.writeString(this.serverInterface.getPluginNames()); -- this.rulesResponse.writeString("map"); -- this.rulesResponse.writeString(this.worldName); -- this.rulesResponse.writeString("numplayers"); -- this.rulesResponse.writeString("" + this.serverInterface.getPlayerCount()); -- this.rulesResponse.writeString("maxplayers"); -- this.rulesResponse.writeString("" + this.maxPlayers); -- this.rulesResponse.writeString("hostport"); -- this.rulesResponse.writeString("" + this.serverPort); -- this.rulesResponse.writeString("hostip"); -- this.rulesResponse.writeString(this.hostIp); -- this.rulesResponse.write((int) 0); -- this.rulesResponse.write((int) 1); -- this.rulesResponse.writeString("player_"); -- this.rulesResponse.write((int) 0); -- String[] astring = this.serverInterface.getPlayerNames(); -+ /* Paper start - GS4 Query event -+ this.p.a("hostname"); -+ this.p.a(this.i); -+ this.p.a("gametype"); -+ this.p.a("SMP"); -+ this.p.a("game_id"); -+ this.p.a("MINECRAFT"); -+ this.p.a("version"); -+ this.p.a(this.r.getVersion()); -+ this.p.a("plugins"); -+ this.p.a(this.r.getPlugins()); -+ this.p.a("map"); -+ this.p.a(this.j); -+ this.p.a("numplayers"); -+ this.p.a("" + this.r.getPlayerCount()); -+ this.p.a("maxplayers"); -+ this.p.a("" + this.h); -+ this.p.a("hostport"); -+ this.p.a("" + this.g); -+ this.p.a("hostip"); -+ this.p.a(this.m); -+ this.p.a((int) 0); -+ this.p.a((int) 1); -+ this.p.a("player_"); -+ this.p.a((int) 0); -+ String[] astring = this.r.getPlayers(); - String[] astring1 = astring; - int j = astring.length; - - for (int k = 0; k < j; ++k) { - String s = astring1[k]; - -- this.rulesResponse.writeString(s); -+ this.p.a(s); - } - -- this.rulesResponse.write((int) 0); -+ this.p.a((int) 0); -+ */ -+ // Pack plugins -+ java.util.List plugins = java.util.Collections.emptyList(); -+ org.bukkit.plugin.Plugin[] bukkitPlugins; -+ if (((DedicatedServer) this.getServer()).server.getQueryPlugins() && (bukkitPlugins = org.bukkit.Bukkit.getPluginManager().getPlugins()).length > 0) { -+ plugins = java.util.stream.Stream.of(bukkitPlugins) -+ .map(plugin -> com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation.of(plugin.getName(), plugin.getDescription().getVersion())) -+ .collect(java.util.stream.Collectors.toList()); -+ } -+ -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() -+ .motd(this.getMotd()) -+ .map(this.getWorldName()) -+ .currentPlayers(this.getServer().getPlayerCount()) -+ .maxPlayers(this.getMaxPlayers()) -+ .port(this.getServerPort()) -+ .hostname(this.getServerHost()) -+ .plugins(plugins) -+ .players(this.getServer().getPlayerNames()) -+ .gameVersion(this.getServer().getServerVersion()) -+ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) -+ .build(); -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.FULL; -+ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = -+ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, packet.getAddress(), queryResponse); -+ queryEvent.callEvent(); -+ queryResponse = queryEvent.getResponse(); -+ this.getCachedFullResponse().writeString("hostname"); -+ this.getCachedFullResponse().writeString(queryResponse.getMotd()); -+ this.getCachedFullResponse().writeString("gametype"); -+ this.getCachedFullResponse().writeString("SMP"); -+ this.getCachedFullResponse().writeString("game_id"); -+ this.getCachedFullResponse().writeString("MINECRAFT"); -+ this.getCachedFullResponse().writeString("version"); -+ this.getCachedFullResponse().writeString(queryResponse.getGameVersion()); -+ this.getCachedFullResponse().writeString("plugins"); -+ java.lang.StringBuilder pluginsString = new java.lang.StringBuilder(); -+ pluginsString.append(queryResponse.getServerVersion()); -+ if (!queryResponse.getPlugins().isEmpty()) { -+ pluginsString.append(": "); -+ java.util.Iterator iter = queryResponse.getPlugins().iterator(); -+ while (iter.hasNext()) { -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation info = iter.next(); -+ pluginsString.append(info.getName()); -+ if (info.getVersion() != null) { -+ pluginsString.append(' ').append(info.getVersion().replace(";", ",")); -+ } -+ if (iter.hasNext()) { -+ pluginsString.append(';').append(' '); -+ } -+ } -+ } -+ this.getCachedFullResponse().writeString(pluginsString.toString()); -+ this.getCachedFullResponse().writeString("map"); -+ this.getCachedFullResponse().writeString(queryResponse.getMap()); -+ this.getCachedFullResponse().writeString("numplayers"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getCurrentPlayers())); -+ this.getCachedFullResponse().writeString("maxplayers"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getMaxPlayers())); -+ this.getCachedFullResponse().writeString("hostport"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getPort())); -+ this.getCachedFullResponse().writeString("hostip"); -+ this.getCachedFullResponse().writeString(queryResponse.getHostname()); -+ // The "meaningless data" start, copied from above -+ this.getCachedFullResponse().writeInt(0); -+ this.getCachedFullResponse().writeInt(1); -+ this.getCachedFullResponse().writeString("player_"); -+ this.getCachedFullResponse().writeInt(0); -+ // "Meaningless data" end -+ queryResponse.getPlayers().forEach(this.getCachedFullResponse()::writeStringUnchecked); -+ this.getCachedFullResponse().writeInt(0); -+ // Paper end - return this.rulesResponse.toByteArray(); - } - } diff --git a/patches/server-remapped/0330-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch similarity index 51% rename from patches/server-remapped/0330-Optimize-Network-Manager-and-add-advanced-packet-sup.patch rename to patches/server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch index 0dc4b2e085..a50c8d9c54 100644 --- a/patches/server-remapped/0330-Optimize-Network-Manager-and-add-advanced-packet-sup.patch +++ b/patches/server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch @@ -28,26 +28,10 @@ and then catch exceptions and close if they fire. Part of this commit was authored by: Spottedleaf diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed0b562c1b 100644 +index 9f0537799a3cae43fb120056b8fe805a4883cc4d..5897bdb4d1372fa3d7bdc482d02f0a54d8767bda 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java -@@ -25,8 +25,15 @@ import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.PacketFlow; -+import net.minecraft.network.protocol.game.ClientboundBossEventPacket; -+import net.minecraft.network.protocol.game.ClientboundChatPacket; -+import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket; - import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; -+import net.minecraft.network.protocol.game.ClientboundKeepAlivePacket; -+import net.minecraft.network.protocol.game.ClientboundSetTitlesPacket; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.RunningOnDifferentThreadException; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.network.ServerGamePacketListenerImpl; - import net.minecraft.server.network.ServerLoginPacketListenerImpl; - import net.minecraft.util.LazyLoadedValue; -@@ -75,6 +82,10 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -87,6 +87,10 @@ public class Connection extends SimpleChannelInboundHandler> { public int protocolVersion; public java.net.InetSocketAddress virtualHost; private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); @@ -58,7 +42,7 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed // Paper end public Connection(PacketFlow side) { -@@ -98,6 +109,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -110,6 +114,7 @@ public class Connection extends SimpleChannelInboundHandler> { } public void setProtocol(ConnectionProtocol state) { @@ -66,12 +50,12 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).set(state); this.channel.config().setAutoRead(true); Connection.LOGGER.debug("Enabled auto read"); -@@ -168,19 +180,84 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -186,19 +191,87 @@ public class Connection extends SimpleChannelInboundHandler> { Validate.notNull(listener, "packetListener", new Object[0]); this.packetListener = listener; } + // Paper start -+ public ServerPlayer getPlayer() { ++ public net.minecraft.server.level.ServerPlayer getPlayer() { + if (packetListener instanceof ServerGamePacketListenerImpl) { + return ((ServerGamePacketListenerImpl) packetListener).player; + } else { @@ -101,11 +85,15 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed + // Paper start + private static boolean canSendImmediate(Connection networkManager, Packet packet) { + return networkManager.isPending || networkManager.protocol != ConnectionProtocol.PLAY || -+ packet instanceof ClientboundKeepAlivePacket || -+ packet instanceof ClientboundChatPacket || -+ packet instanceof ClientboundCommandSuggestionsPacket || -+ packet instanceof ClientboundSetTitlesPacket || -+ packet instanceof ClientboundBossEventPacket; ++ packet instanceof net.minecraft.network.protocol.game.ClientboundKeepAlivePacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundChatPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundClearTitlesPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundBossEventPacket; + } + // Paper end + } @@ -128,10 +116,10 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed + } + packet.onPacketDispatch(getPlayer()); + if (connected && (InnerUtil.canSendImmediate(this, packet) || ( -+ MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() && ++ net.minecraft.server.MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() && + (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) + ))) { -+ this.dispatchPacket(packet, callback); ++ this.send(packet, callback); + return; } + // write the packets to the queue, then flush - antixray hooks there already @@ -142,106 +130,67 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed + } else { + java.util.List packets = new java.util.ArrayList<>(1 + extraPackets.size()); + packets.add(new Connection.PacketHolder(packet, null)); // delay the future listener until the end of the extra packets -+ + + for (int i = 0, len = extraPackets.size(); i < len;) { + Packet extra = extraPackets.get(i); + boolean end = ++i == len; + packets.add(new Connection.PacketHolder(extra, end ? callback : null)); // append listener to the end + } - + this.queue.addAll(packets); // atomic + } -+ this.sendPacketQueue(); ++ this.flushQueue(); + // Paper end } - private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.sendPacket(packet, genericFutureListener); } // Paper - OBFHELPER -@@ -194,54 +271,119 @@ public class Connection extends SimpleChannelInboundHandler> { - this.channel.config().setAutoRead(false); + private void sendPacket(Packet packet, @Nullable GenericFutureListener> callback) { +@@ -226,33 +299,79 @@ public class Connection extends SimpleChannelInboundHandler> { + this.setProtocol(enumprotocol); } -+ ServerPlayer player = getPlayer(); // Paper - if (this.channel.eventLoop().inEventLoop()) { - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end - - ChannelFuture channelfuture = this.channel.writeAndFlush(packet); - - if (callback != null) { - channelfuture.addListener(callback); - } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end - - channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ disconnect(new TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end - } else { - this.channel.eventLoop().execute(() -> { - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } - -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end - ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet); - ++ // Paper start ++ net.minecraft.server.level.ServerPlayer player = getPlayer(); ++ if (!isConnected()) { ++ packet.onPacketDispatchFinish(player, null); ++ return; ++ } + - if (callback != null) { - channelfuture1.addListener(callback); - } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end ++ try { ++ // Paper end + ChannelFuture channelfuture = this.channel.writeAndFlush(packet); - channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ disconnect(new TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end - }); + if (genericfuturelistener != null) { + channelfuture.addListener(genericfuturelistener); } ++ // Paper start ++ if (packet.hasFinishListener()) { ++ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); ++ } ++ // Paper end + channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); ++ // Paper start ++ } catch (Exception e) { ++ LOGGER.error("NetworkException: " + player, e); ++ disconnect(new net.minecraft.network.chat.TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage())); ++ packet.onPacketDispatchFinish(player, null); ++ } ++ // Paper end + } + + private ConnectionProtocol getCurrentProtocol() { + return (ConnectionProtocol) this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).get(); } -- private void sendPacketQueue() { this.flushQueue(); } // Paper - OBFHELPER - private void flushQueue() { - if (this.channel != null && this.channel.isOpen()) { - Queue queue = this.queue; - + // Paper start - rewrite this to be safer if ran off main thread -+ private boolean sendPacketQueue() { return this.p(); } // OBFHELPER // void -> boolean -+ private boolean p() { // void -> boolean ++ private boolean flushQueue() { // void -> boolean + if (!isConnected()) { + return true; + } -+ if (MCUtil.isMainThread()) { ++ if (net.minecraft.server.MCUtil.isMainThread()) { + return processQueue(); + } else if (isPending) { + // Should only happen during login/status stages @@ -262,19 +211,19 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed + // But if we are not on main due to login/status, the parent is synchronized on packetQueue + java.util.Iterator iterator = this.queue.iterator(); + while (iterator.hasNext()) { -+ Connection.PacketHolder queued = iterator.next(); // poll -> peek ++ PacketHolder queued = iterator.next(); // poll -> peek + + // Fix NPE (Spigot bug caused by handleDisconnection()) + if (queued == null) { + return true; + } -+ Packet packet = queued.getPacket(); ++ Packet packet = queued.packet; + if (!packet.isReady()) { + return false; + } else { + iterator.remove(); -+ this.dispatchPacket(packet, queued.getGenericFutureListener()); ++ this.sendPacket(packet, queued.listener); } } + return true; @@ -282,26 +231,23 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed + // Paper end public void tick() { -- this.flushQueue(); -+ this.p(); - if (this.packetListener instanceof ServerLoginPacketListenerImpl) { - ((ServerLoginPacketListenerImpl) this.packetListener).tick(); - } -@@ -271,9 +413,21 @@ public class Connection extends SimpleChannelInboundHandler> { + this.flushQueue(); +@@ -289,9 +408,22 @@ public class Connection extends SimpleChannelInboundHandler> { return this.address; } + // Paper start + public void clearPacketQueue() { -+ ServerPlayer player = getPlayer(); ++ net.minecraft.server.level.ServerPlayer player = getPlayer(); + queue.forEach(queuedPacket -> { -+ Packet packet = queuedPacket.getPacket(); ++ Packet packet = queuedPacket.packet; + if (packet.hasFinishListener()) { + packet.onPacketDispatchFinish(player, null); + } + }); + queue.clear(); -+ } // Paper end ++ } ++ // Paper end public void disconnect(Component disconnectReason) { // Spigot Start this.preparing = false; @@ -309,18 +255,18 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed // Spigot End if (this.channel.isOpen()) { this.channel.close(); // We can't wait as this may be called from an event loop. -@@ -341,7 +495,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -409,7 +541,7 @@ public class Connection extends SimpleChannelInboundHandler> { public void handleDisconnection() { if (this.channel != null && !this.channel.isOpen()) { if (this.disconnectionHandled) { - Connection.LOGGER.warn("handleDisconnection() called twice"); -+ //NetworkManager.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message ++ //Connection.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message } else { this.disconnectionHandled = true; if (this.getDisconnectedReason() != null) { -@@ -349,7 +503,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -417,7 +549,7 @@ public class Connection extends SimpleChannelInboundHandler> { } else if (this.getPacketListener() != null) { - this.getPacketListener().a(new TranslatableComponent("multiplayer.disconnect.generic")); + this.getPacketListener().onDisconnect(new TranslatableComponent("multiplayer.disconnect.generic")); } - this.queue.clear(); // Free up packet queue. + clearPacketQueue(); // Paper @@ -328,67 +274,26 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed final PacketListener packetListener = this.getPacketListener(); if (packetListener instanceof ServerGamePacketListenerImpl) { diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index 9914a82ba0ec146ab13fe94c4dbf0ebf64926536..22db5d0d2cc33498ca40162c66aa3b5fbf2f569f 100644 +index 74bfe0d3942259c45702b099efdc4e101a4e3022..e8fcd56906d26f6dc87959e32c4c7c78cfea9658 100644 --- a/src/main/java/net/minecraft/network/protocol/Packet.java +++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -1,5 +1,6 @@ - package net.minecraft.network.protocol; - -+import io.netty.channel.ChannelFuture; // Paper - import java.io.IOException; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.PacketListener; -@@ -13,6 +14,20 @@ public interface Packet { +@@ -9,6 +9,19 @@ public interface Packet { void handle(T listener); // Paper start -+ + /** + * @param player Null if not at PLAY stage yet + */ -+ default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} ++ default void onPacketDispatch(@javax.annotation.Nullable net.minecraft.server.level.ServerPlayer player) {} + + /** + * @param player Null if not at PLAY stage yet + * @param future Can be null if packet was cancelled + */ -+ default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} ++ default void onPacketDispatchFinish(@javax.annotation.Nullable net.minecraft.server.level.ServerPlayer player, @javax.annotation.Nullable io.netty.channel.ChannelFuture future) {} + default boolean hasFinishListener() { return false; } + default boolean isReady() { return true; } + default java.util.List getExtraPackets() { return null; } - default boolean packetTooLarge(NetworkManager manager) { + default boolean packetTooLarge(net.minecraft.network.Connection manager) { return false; } -diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -index 6cb51a4fe3c11f53fbb556ce6b0d64b735254d51..d46910cfdc0aef046a0c79731a85d381953c328a 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -@@ -16,6 +16,7 @@ import io.netty.channel.epoll.EpollServerSocketChannel; - import io.netty.channel.nio.NioEventLoopGroup; - import io.netty.channel.socket.ServerSocketChannel; - import io.netty.channel.socket.nio.NioServerSocketChannel; -+import io.netty.handler.flush.FlushConsolidationHandler; // Paper - import io.netty.handler.timeout.ReadTimeoutHandler; - import java.io.IOException; - import java.net.InetAddress; -@@ -54,10 +55,12 @@ public class ServerConnectionListener { - private final List connections = Collections.synchronizedList(Lists.newArrayList()); - // Paper start - prevent blocking on adding a new network manager while the server is ticking - private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private static final boolean disableFlushConsolidation = Boolean.getBoolean("Paper.disableFlushConsolidate"); // Paper - private void addPending() { - Connection manager = null; - while ((manager = pending.poll()) != null) { - connections.add(manager); -+ manager.isPending = false; - } - } - // Paper end -@@ -92,6 +95,7 @@ public class ServerConnectionListener { - ; - } - -+ if (!disableFlushConsolidation) channel.pipeline().addFirst(new FlushConsolidationHandler()); // Paper - channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyQueryHandler(ServerConnectionListener.this)).addLast("splitter", new Varint21FrameDecoder()).addLast("decoder", new PacketDecoder(PacketFlow.SERVERBOUND)).addLast("prepender", new Varint21LengthFieldPrepender()).addLast("encoder", new PacketEncoder(PacketFlow.CLIENTBOUND)); - int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); - Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); diff --git a/patches/server/0307-Handle-Oversized-Tile-Entities-in-chunks.patch b/patches/server/0307-Handle-Oversized-Tile-Entities-in-chunks.patch new file mode 100644 index 0000000000..f02716ec0e --- /dev/null +++ b/patches/server/0307-Handle-Oversized-Tile-Entities-in-chunks.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 May 2020 05:00:57 -0400 +Subject: [PATCH] Handle Oversized Tile Entities in chunks + +Splits out Extra Packets if too many TE's are encountered to prevent +creating too large of a packet to sed. + +Co authored by Spottedleaf + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index 96626835fee3c0fdb452acacdc9f737ad90c08de..c28879f32b004f36ff746ea2274f91ddd9501e71 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -27,6 +27,15 @@ public class ClientboundLevelChunkPacket implements Packet blockEntitiesTags; ++ // Paper start ++ private final java.util.List extraPackets = new java.util.ArrayList<>(); ++ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); ++ ++ @Override ++ public java.util.List getExtraPackets() { ++ return extraPackets; ++ } ++ // Paper end + + public ClientboundLevelChunkPacket(LevelChunk chunk) { + ChunkPos chunkPos = chunk.getPos(); +@@ -44,9 +53,19 @@ public class ClientboundLevelChunkPacket implements Packet entry2 : chunk.getBlockEntities().entrySet()) { + BlockEntity blockEntity = entry2.getValue(); ++ // Paper start - improve oversized chunk data packet handling ++ if (++totalTileEntities > TE_LIMIT) { ++ ClientboundBlockEntityDataPacket updatePacket = blockEntity.getUpdatePacket(); ++ if (updatePacket != null) { ++ this.extraPackets.add(updatePacket); ++ continue; ++ } ++ } ++ // Paper end + CompoundTag compoundTag = blockEntity.getUpdateTag(); + if (blockEntity instanceof net.minecraft.world.level.block.entity.SkullBlockEntity) { net.minecraft.world.level.block.entity.SkullBlockEntity.sanitizeTileEntityUUID(compoundTag); } // Paper + this.blockEntitiesTags.add(compoundTag); diff --git a/patches/server-remapped/0332-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/patches/server/0308-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch similarity index 62% rename from patches/server-remapped/0332-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch rename to patches/server/0308-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch index 1209aa99ea..5e2db52029 100644 --- a/patches/server-remapped/0332-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch +++ b/patches/server/0308-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch @@ -11,10 +11,10 @@ everything to the Whitelist object. https://github.com/PaperMC/Paper/issues/1880 diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 5b71b487836cdd2ddc75b2039f4dc0177719d345..8d133d3c825f7747081de99ee67d4556e5c19cdd 100644 +index 0df68991eb2ef3dabe779f42c2bf44846ac0d862..4ae234a107d16bc71425af5f2729c428f79e3db7 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -55,6 +55,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; +@@ -62,6 +62,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket; import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket; import net.minecraft.resources.ResourceKey; @@ -22,24 +22,15 @@ index 5b71b487836cdd2ddc75b2039f4dc0177719d345..8d133d3c825f7747081de99ee67d4556 import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerAdvancements; import net.minecraft.server.ServerScoreboard; -@@ -1012,9 +1013,9 @@ public abstract class PlayerList { +@@ -996,9 +997,9 @@ public abstract class PlayerList { } public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { boolean isOp = this.ops.contains(gameprofile); - boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile); -+ boolean isWhitelisted = !this.isUsingWhitelist() || isOp || this.whitelist.contains(gameprofile); ++ boolean isWhitelisted = !this.isUsingWhitelist() || isOp || this.whitelist.contains(gameprofile); // Paper - use isUsingWhitelist() final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; -- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); -+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.isUsingWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); +- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(net.minecraft.server.MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); ++ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(net.minecraft.server.MCUtil.toBukkit(gameprofile), this.isUsingWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); // Paper - use isUsingWhitelist() event.callEvent(); if (!event.isWhitelisted()) { if (loginEvent != null) { -@@ -1062,7 +1063,7 @@ public abstract class PlayerList { - MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { -- this.savePlayerFile((EntityPlayer) this.players.get(i)); -+ this.save((ServerPlayer) this.players.get(i)); - } - MinecraftTimings.savePlayers.stopTiming(); // Paper - return null; }); // Paper - ensure main diff --git a/patches/server-remapped/0333-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/patches/server/0309-Set-Zombie-last-tick-at-start-of-drowning-process.patch similarity index 85% rename from patches/server-remapped/0333-Set-Zombie-last-tick-at-start-of-drowning-process.patch rename to patches/server/0309-Set-Zombie-last-tick-at-start-of-drowning-process.patch index eb4f5ff56c..2a8b7a4ce1 100644 --- a/patches/server-remapped/0333-Set-Zombie-last-tick-at-start-of-drowning-process.patch +++ b/patches/server/0309-Set-Zombie-last-tick-at-start-of-drowning-process.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Set Zombie last tick at start of drowning process Fixes GH-1887 diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index ad4eeb15771750193a28116117992270c72a3644..6fecf4188fc0247143edc688c03e645376960687 100644 +index c60d9775230b2ff554eeb38136f8e7c32c47d8cf..ee17cba501e0cc4822bd1278d18b561c77fe9674 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -220,6 +220,7 @@ public class Zombie extends Monster { +@@ -225,6 +225,7 @@ public class Zombie extends Monster { ++this.inWaterTime; if (this.inWaterTime >= 600) { this.startUnderWaterConversion(300); diff --git a/patches/server-remapped/0335-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/patches/server/0310-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch similarity index 82% rename from patches/server-remapped/0335-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch rename to patches/server/0310-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch index 5fcbc4df8c..d925e9aaa3 100644 --- a/patches/server-remapped/0335-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch +++ b/patches/server/0310-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Call WhitelistToggleEvent when whitelist is toggled diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8d133d3c825f7747081de99ee67d4556e5c19cdd..728eaadd3dc619e414ec30feb38c7d4a84b2e539 100644 +index 4ae234a107d16bc71425af5f2729c428f79e3db7..ea336bdf2f15aabe74de82ef6c29b93573254e31 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1131,6 +1131,7 @@ public abstract class PlayerList { +@@ -1115,6 +1115,7 @@ public abstract class PlayerList { } public void setUsingWhiteList(boolean whitelistEnabled) { diff --git a/patches/server-remapped/0337-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/patches/server/0311-Use-proper-max-length-when-serialising-BungeeCord-te.patch similarity index 70% rename from patches/server-remapped/0337-Use-proper-max-length-when-serialising-BungeeCord-te.patch rename to patches/server/0311-Use-proper-max-length-when-serialising-BungeeCord-te.patch index c6e42c264d..bb182f5de4 100644 --- a/patches/server-remapped/0337-Use-proper-max-length-when-serialising-BungeeCord-te.patch +++ b/patches/server/0311-Use-proper-max-length-when-serialising-BungeeCord-te.patch @@ -6,26 +6,26 @@ Subject: [PATCH] Use proper max length when serialising BungeeCord text diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -index f13da9e7d014bc00fbabf0a495b548bba2f59468..002a6c7933f64405707d7d34d3e5c17584539623 100644 +index a64780b4b49d01322d8f755ff540a9622c89e983..26a229f7aa3f4425ed572e2d50730b4e978bf33e 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -@@ -9,7 +9,7 @@ import net.minecraft.network.chat.Component; +@@ -8,7 +8,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.Packet; public class ClientboundChatPacket implements Packet { - + private static final int MAX_LENGTH = Short.MAX_VALUE * 8 + 8; // Paper - private Component message; + private final Component message; public net.kyori.adventure.text.Component adventure$message; // Paper public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot -@@ -43,9 +43,9 @@ public class ClientboundChatPacket implements Packet { - //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below +@@ -39,9 +39,9 @@ public class ClientboundChatPacket implements Packet { + // buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below // Paper start - don't nest if we don't need to so that we can preserve formatting if (this.components.length == 1) { -- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); +- buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); + buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]), MAX_LENGTH); // Paper - use proper max length } else { -- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); +- buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); + buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components), MAX_LENGTH); // Paper - use proper max length } // Paper end diff --git a/patches/server-remapped/0338-Entity-getEntitySpawnReason.patch b/patches/server/0312-Entity-getEntitySpawnReason.patch similarity index 67% rename from patches/server-remapped/0338-Entity-getEntitySpawnReason.patch rename to patches/server/0312-Entity-getEntitySpawnReason.patch index 18095e343f..90d47b684f 100644 --- a/patches/server-remapped/0338-Entity-getEntitySpawnReason.patch +++ b/patches/server/0312-Entity-getEntitySpawnReason.patch @@ -10,22 +10,22 @@ persistenting Living Entity, SPAWNER for spawners, or DEFAULT since data was not stored. diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 2ab221e5315dde4e556ee49a6962ae0091ccf616..d03b4f97102dfb88927a94ee5a5d397ac493eaa1 100644 +index 731c8e38c8daf04fee40a5ccfb0715b20f4d890f..940e6587125df1f203cdeeefc31658635badea81 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1035,6 +1035,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1093,6 +1093,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl // CraftBukkit start private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot + if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper - // Paper start - if (entity.valid) { - MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); + if (entity.isRemoved()) { + // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit + return false; diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 728eaadd3dc619e414ec30feb38c7d4a84b2e539..4d813b6556030354f51c1ee5f18eac2166b44576 100644 +index ea336bdf2f15aabe74de82ef6c29b93573254e31..da3100d6577166e222164c174b28020541dd8e3a 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -331,7 +331,7 @@ public abstract class PlayerList { +@@ -335,7 +335,7 @@ public abstract class PlayerList { // CraftBukkit start ServerLevel finalWorldServer = worldserver1; Entity entity = EntityType.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { @@ -35,10 +35,10 @@ index 728eaadd3dc619e414ec30feb38c7d4a84b2e539..4d813b6556030354f51c1ee5f18eac21 }); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f311e197f6e 100644 +index 8df9bd656374d0b43af378c61c1df7b951085b58..fcd3e6bfb4b1d0aefcb34eaec1212b08498dd5af 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -63,6 +63,8 @@ import net.minecraft.world.InteractionHand; +@@ -67,6 +67,8 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.Nameable; import net.minecraft.world.damagesource.DamageSource; @@ -47,30 +47,30 @@ index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f31 import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.vehicle.Boat; -@@ -157,6 +159,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -166,6 +168,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + } } }; - public List entitySlice = null; + public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper end public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper -@@ -1673,6 +1676,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); - tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); +@@ -1841,6 +1844,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + nbt.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); + nbt.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ())); } + if (spawnReason != null) { -+ tag.putString("Paper.SpawnReason", spawnReason.name()); ++ nbt.putString("Paper.SpawnReason", spawnReason.name()); + } // Save entity's from mob spawner status if (spawnedViaMobSpawner) { - tag.putBoolean("Paper.FromMobSpawner", true); -@@ -1811,6 +1817,26 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + nbt.putBoolean("Paper.FromMobSpawner", true); +@@ -1983,6 +1989,26 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } - spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ if (tag.contains("Paper.SpawnReason")) { -+ String spawnReasonName = tag.getString("Paper.SpawnReason"); + spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ if (nbt.contains("Paper.SpawnReason")) { ++ String spawnReasonName = nbt.getString("Paper.SpawnReason"); + try { + spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName); + } catch (Exception ignored) { @@ -81,7 +81,7 @@ index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f31 + if (spawnedViaMobSpawner) { + spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; + } else if (this instanceof Mob && (this instanceof Animal || this instanceof AbstractFish) && !((Mob) this).removeWhenFarAway(0.0)) { -+ if (!tag.getBoolean("PersistenceRequired")) { ++ if (!nbt.getBoolean("PersistenceRequired")) { + spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL; + } + } @@ -93,22 +93,22 @@ index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f31 } catch (Throwable throwable) { diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 1ce675d0d24ceb5724f5ac2d8f671e38f2735f74..3a7aec9bd2f3fd1b4a1981fb6a8c64b69e4875f8 100644 +index 12a78685848b7fd945a472902d8200ea1d50b9ec..3aadcb472ab808ee981065ddfa86be6cbf38c8d9 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -183,6 +183,7 @@ public abstract class BaseSpawner { - // Spigot End - } +@@ -167,6 +167,7 @@ public abstract class BaseSpawner { + // Spigot End + } entity.spawnedViaMobSpawner = true; // Paper -+ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper - flag = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { ++ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper + flag = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index e1bbaf620f3ed2a6cb9ce8007a78c4cee47b653e..7ad4fb57af32cc1b8278688381e1b058ed8437db 100644 +index c381ea321b0fb3498e3f101ee059ac7d42aa029a..33bc56eba4229d844e3af6ff4662d96450e929af 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1106,5 +1106,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1163,5 +1163,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { public boolean fromMobSpawner() { return getHandle().spawnedViaMobSpawner; } diff --git a/patches/server/0313-Update-entity-Metadata-for-all-tracked-players.patch b/patches/server/0313-Update-entity-Metadata-for-all-tracked-players.patch new file mode 100644 index 0000000000..5b0902aa33 --- /dev/null +++ b/patches/server/0313-Update-entity-Metadata-for-all-tracked-players.patch @@ -0,0 +1,76 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AgentTroll +Date: Fri, 22 Mar 2019 22:24:03 -0700 +Subject: [PATCH] Update entity Metadata for all tracked players + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 8311d921ded1c81a1f561dc13db2010d2b7ce5d6..95ac30f56a9268f14d2518974c5a52e08f40ea18 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1281,6 +1281,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } else { + ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas()); + ++ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker + this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); + playerchunkmap_entitytracker.updatePlayers(this.level.players()); + if (entity instanceof ServerPlayer) { +@@ -1323,7 +1324,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (playerchunkmap_entitytracker1 != null) { + playerchunkmap_entitytracker1.broadcastRemoved(); + } +- ++ entity.tracker = null; // Paper - We're no longer tracked + } + + protected void tick() { +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index ad9bbda31a4cdb306ca40f2b99e4b815c4f136bd..28afe2f238ded241acf77c3272a44068646b9133 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -392,6 +392,12 @@ public class ServerEntity { + return ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp); + } + ++ // Paper start - Add broadcast method ++ void broadcast(Packet packet) { ++ this.broadcast.accept(packet); ++ } ++ // Paper end ++ + private void broadcastAndSend(Packet packet) { + this.broadcast.accept(packet); + if (this.entity instanceof ServerPlayer) { +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index defebf7b45e4f006fa7e575b5dbd01ac1e231d5a..6c4266d847b1181a055fa425d5734032dadabf93 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2289,7 +2289,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + if (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem) { + // Refresh the current entity metadata +- ServerGamePacketListenerImpl.this.send(new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true)); ++ // Paper start - update entity for all players ++ ClientboundSetEntityDataPacket packet1 = new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true); ++ if (entity.tracker != null) { ++ entity.tracker.broadcast(packet1); ++ } else { ++ ServerGamePacketListenerImpl.this.send(packet1); ++ } ++ // Paper end + } + + if (event.isCancelled()) { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index fcd3e6bfb4b1d0aefcb34eaec1212b08498dd5af..a5159198003e43ce272ae73941d2be47d50eedc9 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -300,6 +300,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + public boolean forceExplosionKnockback; // SPIGOT-949 + public boolean persistentInvisibility = false; + public org.bukkit.Location origin; // Paper ++ public net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper - fast access to tracker + // Spigot start + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; diff --git a/patches/server/0314-Fire-event-on-GS4-query.patch b/patches/server/0314-Fire-event-on-GS4-query.patch new file mode 100644 index 0000000000..7e02bbbb33 --- /dev/null +++ b/patches/server/0314-Fire-event-on-GS4-query.patch @@ -0,0 +1,209 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 17 Mar 2019 21:46:56 +0200 +Subject: [PATCH] Fire event on GS4 query + + +diff --git a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java +index 51cb2644aa516a59e19fecb308d519dbc7e5fb11..e548aa0ca4e1e94ab628614b44fc11568ca3beff 100644 +--- a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java ++++ b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java +@@ -22,6 +22,16 @@ public class NetworkDataOutputStream { + this.dataOutputStream.write(0); + } + ++ // Paper start - unchecked exception variant to use in Stream API ++ public void writeStringUnchecked(String string) { ++ try { ++ writeString(string); ++ } catch (IOException e) { ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(e); ++ } ++ } ++ // Paper end ++ + public void write(int value) throws IOException { + this.dataOutputStream.write(value); + } +diff --git a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java +index 02bb0b2df37ead741adfef38d7479ba6f691dc2d..4632e8f0d27057bf3c47057124b347237ab58111 100644 +--- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java ++++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java +@@ -94,33 +94,52 @@ public class QueryThreadGs4 extends GenericThread { + if (3 <= i && -2 == bs[0] && -3 == bs[1]) { + LOGGER.debug("Packet '{}' [{}]", PktUtils.toHexString(bs[2]), socketAddress); + switch(bs[2]) { +- case 0: +- if (!this.validChallenge(packet)) { +- LOGGER.debug("Invalid challenge [{}]", (Object)socketAddress); +- return false; +- } else if (15 == i) { +- this.sendTo(this.buildRuleResponse(packet), packet); +- LOGGER.debug("Rules [{}]", (Object)socketAddress); +- } else { +- NetworkDataOutputStream networkDataOutputStream = new NetworkDataOutputStream(1460); +- networkDataOutputStream.write(0); +- networkDataOutputStream.writeBytes(this.getIdentBytes(packet.getSocketAddress())); +- networkDataOutputStream.writeString(this.serverName); +- networkDataOutputStream.writeString("SMP"); +- networkDataOutputStream.writeString(this.worldName); +- networkDataOutputStream.writeString(Integer.toString(this.serverInterface.getPlayerCount())); +- networkDataOutputStream.writeString(Integer.toString(this.maxPlayers)); +- networkDataOutputStream.writeShort((short)this.serverPort); +- networkDataOutputStream.writeString(this.hostIp); +- this.sendTo(networkDataOutputStream.toByteArray(), packet); +- LOGGER.debug("Status [{}]", (Object)socketAddress); +- } +- default: +- return true; +- case 9: +- this.sendChallenge(packet); +- LOGGER.debug("Challenge [{}]", (Object)socketAddress); +- return true; ++ case 0: ++ if (!this.validChallenge(packet)) { ++ LOGGER.debug("Invalid challenge [{}]", (Object)socketAddress); ++ return false; ++ } else if (15 == i) { ++ this.sendTo(this.buildRuleResponse(packet), packet); ++ LOGGER.debug("Rules [{}]", (Object)socketAddress); ++ } else { ++ NetworkDataOutputStream networkDataOutputStream = new NetworkDataOutputStream(1460); ++ networkDataOutputStream.write(0); ++ networkDataOutputStream.writeBytes(this.getIdentBytes(packet.getSocketAddress())); ++ ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.BASIC; ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() ++ .motd(this.serverName) ++ .map(this.worldName) ++ .currentPlayers(this.serverInterface.getPlayerCount()) ++ .maxPlayers(this.maxPlayers) ++ .port(this.serverPort) ++ .hostname(this.hostIp) ++ .gameVersion(this.serverInterface.getServerVersion()) ++ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) ++ .build(); ++ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = ++ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, packet.getAddress(), queryResponse); ++ queryEvent.callEvent(); ++ queryResponse = queryEvent.getResponse(); ++ ++ networkDataOutputStream.writeString(queryResponse.getMotd()); ++ networkDataOutputStream.writeString("SMP"); ++ networkDataOutputStream.writeString(queryResponse.getMap()); ++ networkDataOutputStream.writeString(Integer.toString(queryResponse.getCurrentPlayers())); ++ networkDataOutputStream.writeString(Integer.toString(queryResponse.getMaxPlayers())); ++ networkDataOutputStream.writeShort((short) queryResponse.getPort()); ++ networkDataOutputStream.writeString(queryResponse.getHostname()); ++ // Paper end ++ this.sendTo(networkDataOutputStream.toByteArray(), packet); ++ LOGGER.debug("Status [{}]", (Object)socketAddress); ++ } ++ default: ++ return true; ++ case 9: ++ this.sendChallenge(packet); ++ LOGGER.debug("Challenge [{}]", (Object)socketAddress); ++ return true; + } + } else { + LOGGER.debug("Invalid packet [{}]", (Object)socketAddress); +@@ -146,37 +165,79 @@ public class QueryThreadGs4 extends GenericThread { + this.rulesResponse.writeString("splitnum"); + this.rulesResponse.write(128); + this.rulesResponse.write(0); ++ // Paper start ++ // Pack plugins ++ java.util.List plugins = java.util.Collections.emptyList(); ++ org.bukkit.plugin.Plugin[] bukkitPlugins; ++ if (((net.minecraft.server.dedicated.DedicatedServer) this.serverInterface).server.getQueryPlugins() && (bukkitPlugins = org.bukkit.Bukkit.getPluginManager().getPlugins()).length > 0) { ++ plugins = java.util.stream.Stream.of(bukkitPlugins) ++ .map(plugin -> com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation.of(plugin.getName(), plugin.getDescription().getVersion())) ++ .collect(java.util.stream.Collectors.toList()); ++ } ++ ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() ++ .motd(this.serverName) ++ .map(this.worldName) ++ .currentPlayers(this.serverInterface.getPlayerCount()) ++ .maxPlayers(this.maxPlayers) ++ .port(this.serverPort) ++ .hostname(this.hostIp) ++ .plugins(plugins) ++ .players(this.serverInterface.getPlayerNames()) ++ .gameVersion(this.serverInterface.getServerVersion()) ++ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) ++ .build(); ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.FULL; ++ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = ++ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, packet.getAddress(), queryResponse); ++ queryEvent.callEvent(); ++ queryResponse = queryEvent.getResponse(); + this.rulesResponse.writeString("hostname"); +- this.rulesResponse.writeString(this.serverName); ++ this.rulesResponse.writeString(queryResponse.getMotd()); + this.rulesResponse.writeString("gametype"); + this.rulesResponse.writeString("SMP"); + this.rulesResponse.writeString("game_id"); + this.rulesResponse.writeString("MINECRAFT"); + this.rulesResponse.writeString("version"); +- this.rulesResponse.writeString(this.serverInterface.getServerVersion()); ++ this.rulesResponse.writeString(queryResponse.getGameVersion()); + this.rulesResponse.writeString("plugins"); +- this.rulesResponse.writeString(this.serverInterface.getPluginNames()); ++ java.lang.StringBuilder pluginsString = new java.lang.StringBuilder(); ++ pluginsString.append(queryResponse.getServerVersion()); ++ if (!queryResponse.getPlugins().isEmpty()) { ++ pluginsString.append(": "); ++ java.util.Iterator iter = queryResponse.getPlugins().iterator(); ++ while (iter.hasNext()) { ++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation info = iter.next(); ++ pluginsString.append(info.getName()); ++ if (info.getVersion() != null) { ++ pluginsString.append(' ').append(info.getVersion().replace(";", ",")); ++ } ++ if (iter.hasNext()) { ++ pluginsString.append(';').append(' '); ++ } ++ } ++ } ++ this.rulesResponse.writeString(pluginsString.toString()); + this.rulesResponse.writeString("map"); +- this.rulesResponse.writeString(this.worldName); ++ this.rulesResponse.writeString(queryResponse.getMap()); + this.rulesResponse.writeString("numplayers"); +- this.rulesResponse.writeString("" + this.serverInterface.getPlayerCount()); ++ this.rulesResponse.writeString(Integer.toString(queryResponse.getCurrentPlayers())); + this.rulesResponse.writeString("maxplayers"); +- this.rulesResponse.writeString("" + this.maxPlayers); ++ this.rulesResponse.writeString(Integer.toString(queryResponse.getMaxPlayers())); + this.rulesResponse.writeString("hostport"); +- this.rulesResponse.writeString("" + this.serverPort); ++ this.rulesResponse.writeString(Integer.toString(queryResponse.getPort())); + this.rulesResponse.writeString("hostip"); +- this.rulesResponse.writeString(this.hostIp); +- this.rulesResponse.write(0); +- this.rulesResponse.write(1); ++ this.rulesResponse.writeString(queryResponse.getHostname()); ++ // The "meaningless data" start, copied from above ++ this.rulesResponse.writeInt(0); ++ this.rulesResponse.writeInt(1); + this.rulesResponse.writeString("player_"); +- this.rulesResponse.write(0); +- String[] strings = this.serverInterface.getPlayerNames(); +- +- for(String string : strings) { +- this.rulesResponse.writeString(string); +- } +- +- this.rulesResponse.write(0); ++ this.rulesResponse.writeInt(0); ++ // "Meaningless data" end ++ queryResponse.getPlayers().forEach(this.rulesResponse::writeStringUnchecked); ++ this.rulesResponse.writeInt(0); ++ // Paper end + return this.rulesResponse.toByteArray(); + } + } diff --git a/patches/server-remapped/0340-Implement-PlayerPostRespawnEvent.patch b/patches/server/0315-Implement-PlayerPostRespawnEvent.patch similarity index 82% rename from patches/server-remapped/0340-Implement-PlayerPostRespawnEvent.patch rename to patches/server/0315-Implement-PlayerPostRespawnEvent.patch index dbfcbf2e3f..f1e3ff7b6c 100644 --- a/patches/server-remapped/0340-Implement-PlayerPostRespawnEvent.patch +++ b/patches/server/0315-Implement-PlayerPostRespawnEvent.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Implement PlayerPostRespawnEvent diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 4d813b6556030354f51c1ee5f18eac2166b44576..7412765020854caabd32fb6f4fffcf7f4bf6dba7 100644 +index da3100d6577166e222164c174b28020541dd8e3a..c7956664427ca97544d1b47992a62c95d2fc9690 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -737,9 +737,14 @@ public abstract class PlayerList { - // this.a(entityplayer1, entityplayer, worldserver1); // CraftBukkit - removed +@@ -715,9 +715,14 @@ public abstract class PlayerList { + boolean flag2 = false; + // Paper start @@ -24,7 +24,7 @@ index 4d813b6556030354f51c1ee5f18eac2166b44576..7412765020854caabd32fb6f4fffcf7f ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); if (worldserver1 != null) { Optional optional; -@@ -790,6 +795,7 @@ public abstract class PlayerList { +@@ -768,6 +773,7 @@ public abstract class PlayerList { location = respawnEvent.getRespawnLocation(); if (!flag) entityplayer.reset(); // SPIGOT-4785 @@ -32,7 +32,7 @@ index 4d813b6556030354f51c1ee5f18eac2166b44576..7412765020854caabd32fb6f4fffcf7f } else { location.setWorld(worldserver.getWorld()); } -@@ -847,6 +853,13 @@ public abstract class PlayerList { +@@ -825,6 +831,13 @@ public abstract class PlayerList { if (entityplayer.connection.isDisconnected()) { this.save(entityplayer); } diff --git a/settings.gradle.kts b/settings.gradle.kts index 54bb957497..302bcb31ab 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,6 @@ pluginManagement { repositories { + mavenLocal() gradlePluginPortal() maven("https://wav.jfrog.io/artifactory/repo/") } From 19da14ee00f93cc6b3e234162062a818df1f97d2 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Sun, 13 Jun 2021 13:40:34 +0200 Subject: [PATCH 072/226] More work --- ...rivate-methods-for-nullability-annot.patch | 0 ...lip-some-Spigot-API-null-annotations.patch | 6 +- .../0177-Server-Tick-Events.patch | 0 ...0178-PlayerDeathEvent-getItemsToKeep.patch | 0 .../0179-Add-Heightmap-API.patch | 2 +- .../0180-Mob-Spawner-API-Enhancements.patch | 0 ...ityAreaEffectCloud-from-going-negat.patch} | 7 +- ...h-entity-loss-due-to-unloaded-chunks.patch | 0 .../0352-Duplicate-UUID-Resolve-Option.patch | 0 ...-Optimize-Captured-TileEntity-Lookup.patch | 32 ---- .../0345-Add-Heightmap-API.patch | 55 ------- .../0346-Mob-Spawner-API-Enhancements.patch | 139 ------------------ ...for-pickupDelay-breaks-picking-up-i.patch} | 6 +- .../0317-Server-Tick-Events.patch} | 6 +- ...318-PlayerDeathEvent-getItemsToKeep.patch} | 15 +- ...-Optimize-Captured-TileEntity-Lookup.patch | 30 ++++ patches/server/0320-Add-Heightmap-API.patch | 40 +++++ .../0321-Mob-Spawner-API-Enhancements.patch | 129 ++++++++++++++++ ...-to-changed-postToMainThread-method.patch} | 8 +- ...-item-frames-are-modified-MC-123450.patch} | 6 +- ...sPrimaryThread-and-MinecraftServer-.patch} | 10 +- ...25-improve-CraftWorld-isChunkLoaded.patch} | 12 +- ...e-Keep-Spawn-Loaded-range-per-world.patch} | 80 +++++----- 23 files changed, 276 insertions(+), 307 deletions(-) rename patches/{api-unmapped => api}/0175-Ignore-package-private-methods-for-nullability-annot.patch (100%) rename patches/{api-unmapped => api}/0176-Flip-some-Spigot-API-null-annotations.patch (95%) rename patches/{api-unmapped => api}/0177-Server-Tick-Events.patch (100%) rename patches/{api-unmapped => api}/0178-PlayerDeathEvent-getItemsToKeep.patch (100%) rename patches/{api-unmapped => api}/0179-Add-Heightmap-API.patch (99%) rename patches/{api-unmapped => api}/0180-Mob-Spawner-API-Enhancements.patch (100%) rename patches/{server-remapped/0355-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch => removed/1.17/0327-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch} (76%) rename patches/{server-remapped => removed/1.17}/0351-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch (100%) rename patches/{server-remapped => removed/1.17}/0352-Duplicate-UUID-Resolve-Option.patch (100%) delete mode 100644 patches/server-remapped/0344-Optimize-Captured-TileEntity-Lookup.patch delete mode 100644 patches/server-remapped/0345-Add-Heightmap-API.patch delete mode 100644 patches/server-remapped/0346-Mob-Spawner-API-Enhancements.patch rename patches/{server-remapped/0341-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch => server/0316-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch} (86%) rename patches/{server-remapped/0342-Server-Tick-Events.patch => server/0317-Server-Tick-Events.patch} (85%) rename patches/{server-remapped/0343-PlayerDeathEvent-getItemsToKeep.patch => server/0318-PlayerDeathEvent-getItemsToKeep.patch} (83%) create mode 100644 patches/server/0319-Optimize-Captured-TileEntity-Lookup.patch create mode 100644 patches/server/0320-Add-Heightmap-API.patch create mode 100644 patches/server/0321-Mob-Spawner-API-Enhancements.patch rename patches/{server-remapped/0348-Fix-CB-call-to-changed-postToMainThread-method.patch => server/0322-Fix-CB-call-to-changed-postToMainThread-method.patch} (66%) rename patches/{server-remapped/0349-Fix-sounds-when-item-frames-are-modified-MC-123450.patch => server/0323-Fix-sounds-when-item-frames-are-modified-MC-123450.patch} (78%) rename patches/{server-remapped/0350-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch => server/0324-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch} (80%) rename patches/{server-remapped/0353-improve-CraftWorld-isChunkLoaded.patch => server/0325-improve-CraftWorld-isChunkLoaded.patch} (59%) rename patches/{server-remapped/0354-Configurable-Keep-Spawn-Loaded-range-per-world.patch => server/0326-Configurable-Keep-Spawn-Loaded-range-per-world.patch} (81%) diff --git a/patches/api-unmapped/0175-Ignore-package-private-methods-for-nullability-annot.patch b/patches/api/0175-Ignore-package-private-methods-for-nullability-annot.patch similarity index 100% rename from patches/api-unmapped/0175-Ignore-package-private-methods-for-nullability-annot.patch rename to patches/api/0175-Ignore-package-private-methods-for-nullability-annot.patch diff --git a/patches/api-unmapped/0176-Flip-some-Spigot-API-null-annotations.patch b/patches/api/0176-Flip-some-Spigot-API-null-annotations.patch similarity index 95% rename from patches/api-unmapped/0176-Flip-some-Spigot-API-null-annotations.patch rename to patches/api/0176-Flip-some-Spigot-API-null-annotations.patch index 44f9bcdbe3..ceb58db8e0 100644 --- a/patches/api-unmapped/0176-Flip-some-Spigot-API-null-annotations.patch +++ b/patches/api/0176-Flip-some-Spigot-API-null-annotations.patch @@ -9,7 +9,7 @@ a ton of noise to plugin developers. These do not help plugin developers if they bring moise noise than value. diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index dcaefdaf5a0de8486f59115c8c4d4c211b7d64cd..e3304fcc8c4fd176abd3fb7d4b47e5ccb7bdd37f 100644 +index a69e0b0c9f515256c6406ef8ff55f72c98dabe0d..7dd3fc9301de9a88313179088f6b5ce4c1362f06 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1389,7 +1389,7 @@ public final class Bukkit { @@ -62,7 +62,7 @@ index 9c91c49ed7302c12fcb1d8e9bc58712efc199954..d5d67b3d84cd88ed0f858497e68535ec if (this.world == null) { return null; diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 9b8e6b7bbbed44e2659379c8046acaa35aaa8910..989a732e5ef2053deede245d65fbf99cdf117c5e 100644 +index 17f8dd9870a47227a7c9bb09cceedb94f7190ead..139a96d01e3a7e2e298592ce5d485dfc21c9c6c7 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1171,7 +1171,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @@ -84,7 +84,7 @@ index 9b8e6b7bbbed44e2659379c8046acaa35aaa8910..989a732e5ef2053deede245d65fbf99c /** diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index 591e095dabd4cb72881abf206b1d7f0c8818cef3..ecf509a970ed4f0052d5d2c756406bf96052a680 100644 +index 71e5ee496a947fbd8e3ec579833b157c76b51833..d773e8594f91017bddd7ea8aada3a1ff2781d05b 100644 --- a/src/main/java/org/bukkit/inventory/ItemFactory.java +++ b/src/main/java/org/bukkit/inventory/ItemFactory.java @@ -3,6 +3,7 @@ package org.bukkit.inventory; diff --git a/patches/api-unmapped/0177-Server-Tick-Events.patch b/patches/api/0177-Server-Tick-Events.patch similarity index 100% rename from patches/api-unmapped/0177-Server-Tick-Events.patch rename to patches/api/0177-Server-Tick-Events.patch diff --git a/patches/api-unmapped/0178-PlayerDeathEvent-getItemsToKeep.patch b/patches/api/0178-PlayerDeathEvent-getItemsToKeep.patch similarity index 100% rename from patches/api-unmapped/0178-PlayerDeathEvent-getItemsToKeep.patch rename to patches/api/0178-PlayerDeathEvent-getItemsToKeep.patch diff --git a/patches/api-unmapped/0179-Add-Heightmap-API.patch b/patches/api/0179-Add-Heightmap-API.patch similarity index 99% rename from patches/api-unmapped/0179-Add-Heightmap-API.patch rename to patches/api/0179-Add-Heightmap-API.patch index 73e1e8d46f..cb8917e375 100644 --- a/patches/api-unmapped/0179-Add-Heightmap-API.patch +++ b/patches/api/0179-Add-Heightmap-API.patch @@ -103,7 +103,7 @@ index d5d67b3d84cd88ed0f858497e68535ec0162c700..432d5711b7ec34eafeb27df82d367612 * Creates explosion at this location with given power * diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 19060c7d9c74b9b2808103f3d5627444aece6ccb..f8e104d5e61e52c5fe658d7cda373f62424c7bea 100644 +index b80a2fe9eb6824d986126e451900a62244d3a8e7..6fe2875f95bb600606d66e2f7113d325d10a9b9c 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -160,6 +160,87 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad diff --git a/patches/api-unmapped/0180-Mob-Spawner-API-Enhancements.patch b/patches/api/0180-Mob-Spawner-API-Enhancements.patch similarity index 100% rename from patches/api-unmapped/0180-Mob-Spawner-API-Enhancements.patch rename to patches/api/0180-Mob-Spawner-API-Enhancements.patch diff --git a/patches/server-remapped/0355-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch b/patches/removed/1.17/0327-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch similarity index 76% rename from patches/server-remapped/0355-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch rename to patches/removed/1.17/0327-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch index 3475c01271..2d90ba443c 100644 --- a/patches/server-remapped/0355-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch +++ b/patches/removed/1.17/0327-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch @@ -4,12 +4,13 @@ Date: Mon, 27 May 2019 17:35:39 -0500 Subject: [PATCH] MC-114618 - Fix EntityAreaEffectCloud from going negative size +1.17 update note: Likely fixed in 1.17 diff --git a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java -index 949553229a55f8c8b9a5c0141409d1520eff22c7..fe4312a58b0b2ffd63db14068d99c5391e0eb0a0 100644 +index 4733f74ff028c03a60b73280caf9e4d1e2f0ca30..882c216b508a8623c2393b668cff6d702fe738b9 100644 --- a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java +++ b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java -@@ -194,6 +194,12 @@ public class AreaEffectCloud extends Entity { +@@ -197,6 +197,12 @@ public class AreaEffectCloud extends Entity { super.tick(); boolean flag = this.isWaiting(); float f = this.getRadius(); @@ -21,4 +22,4 @@ index 949553229a55f8c8b9a5c0141409d1520eff22c7..fe4312a58b0b2ffd63db14068d99c539 + // Paper end if (this.level.isClientSide) { - ParticleOptions particleparam = this.getParticle(); + if (flag && this.random.nextBoolean()) { diff --git a/patches/server-remapped/0351-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch b/patches/removed/1.17/0351-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch similarity index 100% rename from patches/server-remapped/0351-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch rename to patches/removed/1.17/0351-Fix-issues-with-entity-loss-due-to-unloaded-chunks.patch diff --git a/patches/server-remapped/0352-Duplicate-UUID-Resolve-Option.patch b/patches/removed/1.17/0352-Duplicate-UUID-Resolve-Option.patch similarity index 100% rename from patches/server-remapped/0352-Duplicate-UUID-Resolve-Option.patch rename to patches/removed/1.17/0352-Duplicate-UUID-Resolve-Option.patch diff --git a/patches/server-remapped/0344-Optimize-Captured-TileEntity-Lookup.patch b/patches/server-remapped/0344-Optimize-Captured-TileEntity-Lookup.patch deleted file mode 100644 index 5c22ff496a..0000000000 --- a/patches/server-remapped/0344-Optimize-Captured-TileEntity-Lookup.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 6 Apr 2019 10:16:48 -0400 -Subject: [PATCH] Optimize Captured TileEntity Lookup - -upstream was doing a containsKey/get pattern, and always doing it at that. -that scenario is only even valid if were in the middle of a block place. - -Optimize to check if the captured list even has values in it, and also to -just do a get call since the value can never be null. - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index c8542636e89748699d608eb29569cacb6321d334..5193271bc257248e0d2bc9d9a477e999a97deada 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -968,12 +968,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return null; - } else { - // CraftBukkit start -- if (capturedTileEntities.containsKey(blockposition)) { -- return capturedTileEntities.get(blockposition); -+ BlockEntity tileentity = null; // Paper -+ if (!capturedTileEntities.isEmpty() && (tileentity = capturedTileEntities.get(blockposition)) != null) { // Paper -+ return tileentity; // Paper - } - // CraftBukkit end - -- BlockEntity tileentity = null; -+ //TileEntity tileentity = null; // Paper - move up - - if (this.updatingBlockEntities) { - tileentity = this.getPendingBlockEntityAt(blockposition); diff --git a/patches/server-remapped/0345-Add-Heightmap-API.patch b/patches/server-remapped/0345-Add-Heightmap-API.patch deleted file mode 100644 index 2926bb8ee6..0000000000 --- a/patches/server-remapped/0345-Add-Heightmap-API.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 1 Jan 2019 02:22:01 -0800 -Subject: [PATCH] Add Heightmap API - - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 5193271bc257248e0d2bc9d9a477e999a97deada..eb88d830fb45a6b8c990e8bdc1943d80f63c8b93 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -670,8 +670,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - } - -- @Override -- public int getHeight(Heightmap.Types heightmap, int x, int z) { -+ public final int getHighestBlockY(final Heightmap.Types heightmap, final int x, final int z) { return this.getHeight(heightmap, x, z); } // Paper - OBFHELPER -+ @Override public int getHeight(Heightmap.Types heightmap, int x, int z) { // Paper - OBFHELPER - int k; - - if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 7b5abccac9793811bd56340c8f9d23806e832365..a4231e1c3d468355c0b55ac9d2c239f1b4c54594 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -325,6 +325,29 @@ public class CraftWorld implements World { - return getHighestBlockYAt(x, z, org.bukkit.HeightMap.MOTION_BLOCKING); - } - -+ // Paper start - Implement heightmap api -+ @Override -+ public int getHighestBlockYAt(final int x, final int z, final com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { -+ this.getChunkAt(x >> 4, z >> 4); // heightmap will ret 0 on unloaded areas -+ -+ switch (heightmap) { -+ case LIGHT_BLOCKING: -+ throw new UnsupportedOperationException(); // TODO -+ //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z); -+ case ANY: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE, x, z); -+ case SOLID: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR, x, z); -+ case SOLID_OR_LIQUID: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING, x, z); -+ case SOLID_OR_LIQUID_NO_LEAVES: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z); -+ default: -+ throw new UnsupportedOperationException(); -+ } -+ } -+ // Paper end -+ - @Override - public Location getSpawnLocation() { - BlockPos spawn = world.getSpawn(); diff --git a/patches/server-remapped/0346-Mob-Spawner-API-Enhancements.patch b/patches/server-remapped/0346-Mob-Spawner-API-Enhancements.patch deleted file mode 100644 index b3ee864737..0000000000 --- a/patches/server-remapped/0346-Mob-Spawner-API-Enhancements.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 19 Apr 2019 12:41:13 -0500 -Subject: [PATCH] Mob Spawner API Enhancements - - -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 3a7aec9bd2f3fd1b4a1981fb6a8c64b69e4875f8..6ca378ec7868b855d46c749910c656f82ddb009f 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -65,6 +65,7 @@ public abstract class BaseSpawner { - this.spawnPotentials.clear(); // CraftBukkit - SPIGOT-3496, MC-92282 - } - -+ public boolean isActivated() { return isNearPlayer(); } // Paper - OBFHELPER - private boolean isNearPlayer() { - BlockPos blockposition = this.getPos(); - -@@ -221,6 +222,7 @@ public abstract class BaseSpawner { - } - } - -+ public void resetTimer() { delay(); } // Paper - OBFHELPER - private void delay() { - if (this.maxSpawnDelay <= this.minSpawnDelay) { - this.spawnDelay = this.minSpawnDelay; -@@ -238,7 +240,13 @@ public abstract class BaseSpawner { - } - - public void load(CompoundTag tag) { -+ // Paper start - use larger int if set -+ if (tag.contains("Paper.Delay")) { -+ this.spawnDelay = tag.getInt("Paper.Delay"); -+ } else { - this.spawnDelay = tag.getShort("Delay"); -+ } -+ // Paper end - this.spawnPotentials.clear(); - if (tag.contains("SpawnPotentials", 9)) { - ListTag nbttaglist = tag.getList("SpawnPotentials", 10); -@@ -253,10 +261,15 @@ public abstract class BaseSpawner { - } else if (!this.spawnPotentials.isEmpty()) { - this.setNextSpawnData((SpawnData) WeighedRandom.getRandomItem(this.getLevel().random, this.spawnPotentials)); - } -- -+ // Paper start - use ints if set -+ if (tag.contains("Paper.MinSpawnDelay", 99)) { -+ this.minSpawnDelay = tag.getInt("Paper.MinSpawnDelay"); -+ this.maxSpawnDelay = tag.getInt("Paper.MaxSpawnDelay"); -+ this.spawnCount = tag.getShort("SpawnCount"); -+ } else // Paper end - if (tag.contains("MinSpawnDelay", 99)) { -- this.minSpawnDelay = tag.getShort("MinSpawnDelay"); -- this.maxSpawnDelay = tag.getShort("MaxSpawnDelay"); -+ this.minSpawnDelay = tag.getInt("MinSpawnDelay"); -+ this.maxSpawnDelay = tag.getInt("MaxSpawnDelay"); - this.spawnCount = tag.getShort("SpawnCount"); - } - -@@ -281,9 +294,20 @@ public abstract class BaseSpawner { - if (minecraftkey == null) { - return tag; - } else { -- tag.putShort("Delay", (short) this.spawnDelay); -- tag.putShort("MinSpawnDelay", (short) this.minSpawnDelay); -- tag.putShort("MaxSpawnDelay", (short) this.maxSpawnDelay); -+ // Paper start -+ if (spawnDelay > Short.MAX_VALUE) { -+ tag.putInt("Paper.Delay", this.spawnDelay); -+ } -+ tag.putShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay)); -+ -+ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) { -+ tag.putInt("Paper.MinSpawnDelay", this.minSpawnDelay); -+ tag.putInt("Paper.MaxSpawnDelay", this.maxSpawnDelay); -+ } -+ -+ tag.putShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay)); -+ tag.putShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay)); -+ // Paper end - tag.putShort("SpawnCount", (short) this.spawnCount); - tag.putShort("MaxNearbyEntities", (short) this.maxNearbyEntities); - tag.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 daaf861041cf7c8f59c85535ecb99e402ab4f658..a5b88b545e08eaabf894305a9bee31c55c5b1b87 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -@@ -1,12 +1,20 @@ - package org.bukkit.craftbukkit.block; - - import com.google.common.base.Preconditions; -+import net.minecraft.core.Registry; -+import net.minecraft.nbt.CompoundTag; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.world.level.SpawnData; - import net.minecraft.world.level.block.entity.SpawnerBlockEntity; - import org.bukkit.Material; - import org.bukkit.block.Block; - import org.bukkit.block.CreatureSpawner; - import org.bukkit.entity.EntityType; -+// Paper start -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.inventory.ItemStack; -+// Paper end - - public class CraftCreatureSpawner extends CraftBlockEntityState implements CreatureSpawner { - -@@ -120,4 +128,30 @@ public class CraftCreatureSpawner extends CraftBlockEntityState inv : this.inventory.getComponents()) { ++ for (NonNullList inv : this.getInventory().getComponents()) { + processKeep(event, inv); + } + processKeep(event, null); diff --git a/patches/server/0319-Optimize-Captured-TileEntity-Lookup.patch b/patches/server/0319-Optimize-Captured-TileEntity-Lookup.patch new file mode 100644 index 0000000000..12b5730d51 --- /dev/null +++ b/patches/server/0319-Optimize-Captured-TileEntity-Lookup.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 6 Apr 2019 10:16:48 -0400 +Subject: [PATCH] Optimize Captured TileEntity Lookup + +upstream was doing a containsKey/get pattern, and always doing it at that. +that scenario is only even valid if were in the middle of a block place. + +Optimize to check if the captured list even has values in it, and also to +just do a get call since the value can never be null. + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index a1b713391c2445967c3b5a645304f193c013d551..9891e40972c1dc6bebe8ccec2bf82123dcdd7e94 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -869,9 +869,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + @Nullable + public BlockEntity getTileEntity(BlockPos blockposition, boolean validate) { +- if (this.capturedTileEntities.containsKey(blockposition)) { +- return this.capturedTileEntities.get(blockposition); ++ // Paper start - Optimize capturedTileEntities lookup ++ net.minecraft.world.level.block.entity.BlockEntity blockEntity; ++ if (!this.capturedTileEntities.isEmpty() && (blockEntity = this.capturedTileEntities.get(blockposition)) != null) { ++ return blockEntity; + } ++ // Paper end + // CraftBukkit end + return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE)); + } diff --git a/patches/server/0320-Add-Heightmap-API.patch b/patches/server/0320-Add-Heightmap-API.patch new file mode 100644 index 0000000000..4c7380555f --- /dev/null +++ b/patches/server/0320-Add-Heightmap-API.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 1 Jan 2019 02:22:01 -0800 +Subject: [PATCH] Add Heightmap API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index fda8858375a08e0aac15ca00751df5a34ed6a0f2..5f93589106bcf29eabd4544951fa3ad36e00c5a6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -341,6 +341,29 @@ public class CraftWorld implements World { + return this.getHighestBlockYAt(x, z, org.bukkit.HeightMap.MOTION_BLOCKING); + } + ++ // Paper start - Implement heightmap api ++ @Override ++ public int getHighestBlockYAt(final int x, final int z, final com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { ++ this.getChunkAt(x >> 4, z >> 4); // heightmap will ret 0 on unloaded areas ++ ++ switch (heightmap) { ++ case LIGHT_BLOCKING: ++ throw new UnsupportedOperationException(); // TODO ++ //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z); ++ case ANY: ++ return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE, x, z); ++ case SOLID: ++ return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR, x, z); ++ case SOLID_OR_LIQUID: ++ return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING, x, z); ++ case SOLID_OR_LIQUID_NO_LEAVES: ++ return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z); ++ default: ++ throw new UnsupportedOperationException(); ++ } ++ } ++ // Paper end ++ + @Override + public Location getSpawnLocation() { + BlockPos spawn = this.world.getSharedSpawnPos(); diff --git a/patches/server/0321-Mob-Spawner-API-Enhancements.patch b/patches/server/0321-Mob-Spawner-API-Enhancements.patch new file mode 100644 index 0000000000..d24f3a6b40 --- /dev/null +++ b/patches/server/0321-Mob-Spawner-API-Enhancements.patch @@ -0,0 +1,129 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 19 Apr 2019 12:41:13 -0500 +Subject: [PATCH] Mob Spawner API Enhancements + + +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 3aadcb472ab808ee981065ddfa86be6cbf38c8d9..c6298b12e4e0c20be20e7e493be728f028f9eb31 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -31,7 +31,7 @@ public abstract class BaseSpawner { + + private static final Logger LOGGER = LogManager.getLogger(); + private static final int EVENT_SPAWN = 1; +- private static WeightedRandomList EMPTY_POTENTIALS = WeightedRandomList.create(); ++ public static WeightedRandomList EMPTY_POTENTIALS = WeightedRandomList.create(); // Paper - private->public + public int spawnDelay = 20; + public WeightedRandomList spawnPotentials; + public SpawnData nextSpawnData; +@@ -77,7 +77,7 @@ public abstract class BaseSpawner { + this.spawnPotentials = BaseSpawner.EMPTY_POTENTIALS; // CraftBukkit - SPIGOT-3496, MC-92282 + } + +- private boolean isNearPlayer(Level world, BlockPos pos) { ++ public boolean isNearPlayer(Level world, BlockPos pos) { // Paper private->public + return world.isAffectsSpawningPlayerNearby((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper + } + +@@ -204,7 +204,7 @@ public abstract class BaseSpawner { + } + } + +- private void delay(Level world, BlockPos pos) { ++ public void delay(Level world, BlockPos pos) { // Paper private->public + if (this.maxSpawnDelay <= this.minSpawnDelay) { + this.spawnDelay = this.minSpawnDelay; + } else { +@@ -218,7 +218,13 @@ public abstract class BaseSpawner { + } + + public void load(@Nullable Level world, BlockPos pos, CompoundTag nbt) { ++ // Paper start - use larger int if set ++ if (nbt.contains("Paper.Delay")) { ++ this.spawnDelay = nbt.getInt("Paper.Delay"); ++ } else { + this.spawnDelay = nbt.getShort("Delay"); ++ } ++ // Paper end + List list = Lists.newArrayList(); + + if (nbt.contains("SpawnPotentials", 9)) { +@@ -237,10 +243,15 @@ public abstract class BaseSpawner { + this.setSpawnData(world, pos, mobspawnerdata); + }); + } +- ++ // Paper start - use ints if set ++ if (nbt.contains("Paper.MinSpawnDelay", 99)) { ++ this.minSpawnDelay = nbt.getInt("Paper.MinSpawnDelay"); ++ this.maxSpawnDelay = nbt.getInt("Paper.MaxSpawnDelay"); ++ this.spawnCount = nbt.getShort("SpawnCount"); ++ } else // Paper end + if (nbt.contains("MinSpawnDelay", 99)) { +- this.minSpawnDelay = nbt.getShort("MinSpawnDelay"); +- this.maxSpawnDelay = nbt.getShort("MaxSpawnDelay"); ++ this.minSpawnDelay = nbt.getInt("MinSpawnDelay"); // Paper - short->int ++ this.maxSpawnDelay = nbt.getInt("MaxSpawnDelay"); // Paper - short->int + this.spawnCount = nbt.getShort("SpawnCount"); + } + +@@ -262,9 +273,20 @@ public abstract class BaseSpawner { + if (minecraftkey == null) { + return nbt; + } else { +- nbt.putShort("Delay", (short) this.spawnDelay); +- nbt.putShort("MinSpawnDelay", (short) this.minSpawnDelay); +- nbt.putShort("MaxSpawnDelay", (short) this.maxSpawnDelay); ++ // Paper start ++ if (spawnDelay > Short.MAX_VALUE) { ++ nbt.putInt("Paper.Delay", this.spawnDelay); ++ } ++ nbt.putShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay)); ++ ++ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) { ++ nbt.putInt("Paper.MinSpawnDelay", this.minSpawnDelay); ++ nbt.putInt("Paper.MaxSpawnDelay", this.maxSpawnDelay); ++ } ++ ++ nbt.putShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay)); ++ nbt.putShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay)); ++ // Paper end + nbt.putShort("SpawnCount", (short) this.spawnCount); + 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 ff8eba31e6169b5a1debe47f17a40e6d0be67897..75575b24aa0291c26d65de9787bc9d2f88c867e4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java +@@ -121,4 +121,30 @@ public class CraftCreatureSpawner extends CraftBlockEntityState void filterTextPacket(T text, Consumer consumer, BiFunction>> backingFilterer) { + private void filterTextPacket(T text, Consumer consumer, BiFunction> backingFilterer) { diff --git a/patches/server-remapped/0349-Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/patches/server/0323-Fix-sounds-when-item-frames-are-modified-MC-123450.patch similarity index 78% rename from patches/server-remapped/0349-Fix-sounds-when-item-frames-are-modified-MC-123450.patch rename to patches/server/0323-Fix-sounds-when-item-frames-are-modified-MC-123450.patch index 262820c228..25c0eca233 100644 --- a/patches/server-remapped/0349-Fix-sounds-when-item-frames-are-modified-MC-123450.patch +++ b/patches/server/0323-Fix-sounds-when-item-frames-are-modified-MC-123450.patch @@ -6,15 +6,15 @@ Subject: [PATCH] Fix sounds when item frames are modified (MC-123450) This also fixes the adding sound playing when the item frame direction is changed. diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java -index d6e6846a12a889222ced67937c09d184a64c60b9..429d8a50a35f07bfc16dbedf28560fa6df817644 100644 +index 5fab5f74f7ef2ba94d7dae1679653201d7ccb30f..b829efdb40051a41b3bf1cabb8bf7d7c952797b5 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java -@@ -277,7 +277,7 @@ public class ItemFrame extends HangingEntity { +@@ -307,7 +307,7 @@ public class ItemFrame extends HangingEntity { } this.getEntityData().set(ItemFrame.DATA_ITEM, itemstack); - if (!itemstack.isEmpty() && playSound) { // CraftBukkit + if (!itemstack.isEmpty() && flag && playSound) { // CraftBukkit // Paper - only play sound when update flag is set - this.playSound(SoundEvents.ITEM_FRAME_ADD_ITEM, 1.0F, 1.0F); + this.playSound(this.getAddItemSound(), 1.0F, 1.0F); } diff --git a/patches/server-remapped/0350-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/patches/server/0324-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch similarity index 80% rename from patches/server-remapped/0350-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch rename to patches/server/0324-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch index 367d2e18c9..92eb435a4a 100644 --- a/patches/server-remapped/0350-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch +++ b/patches/server/0324-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch @@ -16,10 +16,10 @@ handling that should have been handled synchronously will be handled synchronously when the server gets shut down. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 35984c7e994570a909ed4ffaabe64ae941b15e71..9beda5e429b5c520a41d9c7f536dc48dbb6f6f9e 100644 +index eb103c15218c334b9f85a57e30582e9efb188704..c8a59de4673d430fc8ec2e53315f107293122e7e 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2190,7 +2190,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop Date: Sun, 13 Jun 2021 14:43:56 +0200 Subject: [PATCH 073/226] More more work --- .../0181-Add-BlockSoundGroup-interface.patch | 0 ...ractAtEntityEvent-javadoc-for-ArmorS.patch | 0 ...-custom-payload-channel-message-size.patch | 0 ...eptions-from-dispenser-entity-spawns.patch | 0 ...le-Keep-Spawn-Loaded-range-per-world.patch | 4 +- .../0327-ChunkMapDistance-CME.patch} | 45 +++++++----------- ...0328-Implement-CraftBlockSoundGroup.patch} | 12 ++--- .../0329-Chunk-debug-command.patch} | 47 +++++++------------ ...360-Fix-World-isChunkGenerated-calls.patch | 0 9 files changed, 44 insertions(+), 64 deletions(-) rename patches/{api-unmapped => api}/0181-Add-BlockSoundGroup-interface.patch (100%) rename patches/{api-unmapped => api}/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch (100%) rename patches/{api-unmapped => api}/0183-Increase-custom-payload-channel-message-size.patch (100%) rename patches/{server-remapped => removed/1.17/No longer needed}/0359-Catch-exceptions-from-dispenser-entity-spawns.patch (100%) rename patches/{server-remapped/0356-ChunkMapDistance-CME.patch => server/0327-ChunkMapDistance-CME.patch} (56%) rename patches/{server-remapped/0357-Implement-CraftBlockSoundGroup.patch => server/0328-Implement-CraftBlockSoundGroup.patch} (81%) rename patches/{server-remapped/0358-Chunk-debug-command.patch => server/0329-Chunk-debug-command.patch} (92%) rename patches/{server-remapped => server}/0360-Fix-World-isChunkGenerated-calls.patch (100%) diff --git a/patches/api-unmapped/0181-Add-BlockSoundGroup-interface.patch b/patches/api/0181-Add-BlockSoundGroup-interface.patch similarity index 100% rename from patches/api-unmapped/0181-Add-BlockSoundGroup-interface.patch rename to patches/api/0181-Add-BlockSoundGroup-interface.patch diff --git a/patches/api-unmapped/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch b/patches/api/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch similarity index 100% rename from patches/api-unmapped/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch rename to patches/api/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch diff --git a/patches/api-unmapped/0183-Increase-custom-payload-channel-message-size.patch b/patches/api/0183-Increase-custom-payload-channel-message-size.patch similarity index 100% rename from patches/api-unmapped/0183-Increase-custom-payload-channel-message-size.patch rename to patches/api/0183-Increase-custom-payload-channel-message-size.patch diff --git a/patches/server-remapped/0359-Catch-exceptions-from-dispenser-entity-spawns.patch b/patches/removed/1.17/No longer needed/0359-Catch-exceptions-from-dispenser-entity-spawns.patch similarity index 100% rename from patches/server-remapped/0359-Catch-exceptions-from-dispenser-entity-spawns.patch rename to patches/removed/1.17/No longer needed/0359-Catch-exceptions-from-dispenser-entity-spawns.patch diff --git a/patches/server/0326-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server/0326-Configurable-Keep-Spawn-Loaded-range-per-world.patch index 5163975193..9d6f848e88 100644 --- a/patches/server/0326-Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ b/patches/server/0326-Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -85,7 +85,7 @@ index c8a59de4673d430fc8ec2e53315f107293122e7e..40e48c3f1199b127066732e3c8a6d40c // CraftBukkit start // this.updateSpawnFlags(); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 940e6587125df1f203cdeeefc31658635badea81..420ecc61be194486d335c44fc743894023d3f115 100644 +index 940e6587125df1f203cdeeefc31658635badea81..74a5dcde184c20129cb5fdcfb34ef1c3aecb1842 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -61,6 +61,7 @@ import net.minecraft.network.protocol.game.ClientboundSoundEntityPacket; @@ -174,7 +174,7 @@ index 940e6587125df1f203cdeeefc31658635badea81..420ecc61be194486d335c44fc7438940 public void setDefaultSpawnPos(BlockPos pos, float angle) { - ChunkPos chunkcoordintpair = new ChunkPos(new BlockPos(this.levelData.getXSpawn(), 0, this.levelData.getZSpawn())); + // Paper - configurable spawn radius -+ BlockPos prevSpawn = this.getSpawn(); ++ BlockPos prevSpawn = this.getSharedSpawnPos(); + //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); this.levelData.setSpawn(pos, angle); diff --git a/patches/server-remapped/0356-ChunkMapDistance-CME.patch b/patches/server/0327-ChunkMapDistance-CME.patch similarity index 56% rename from patches/server-remapped/0356-ChunkMapDistance-CME.patch rename to patches/server/0327-ChunkMapDistance-CME.patch index 09a7ae7ee7..a124ceb879 100644 --- a/patches/server-remapped/0356-ChunkMapDistance-CME.patch +++ b/patches/server/0327-ChunkMapDistance-CME.patch @@ -5,26 +5,26 @@ Subject: [PATCH] ChunkMapDistance CME diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 0b8cbf75ff01b9825141be00d63679f7bcc58a9f..89e90806b78d94d5c1d781113da420dafa47930a 100644 +index 00f5cd29170e3594fe2ac194e04e403cef685912..84831fc611589c19320b5e3af107080596b1fbdc 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -44,6 +44,7 @@ public class ChunkHolder { - private static final CompletableFuture> UNLOADED_LEVEL_CHUNK_FUTURE = CompletableFuture.completedFuture(ChunkHolder.UNLOADED_LEVEL_CHUNK); - private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); - private static final ChunkHolder.FullChunkStatus[] FULL_CHUNK_STATUSES = ChunkHolder.FullChunkStatus.values(); +@@ -73,6 +73,7 @@ public class ChunkHolder { + private boolean resendLight; + private CompletableFuture pendingFullStateConfirmation; + + boolean isUpdateQueued = false; // Paper - private final AtomicReferenceArray>> futures; - private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage - private volatile CompletableFuture> tickingChunkFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage + private final ChunkMap chunkMap; // Paper + + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index 8f993f15ae02c2e4af9cc732cd1b040cce0a67e8..71a51cc99e26579e765f88340588e23956888929 100644 +index 48bb57d3a431ea466425eb7da821c0aea900bd4c..45c7ebe67019cdbe88b6617a95d5c40d3a68286c 100644 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java +++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -39,7 +39,16 @@ public abstract class DistanceManager { +@@ -47,7 +47,16 @@ public abstract class DistanceManager { private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); -- private final Set chunksToUpdateFutures = Sets.newHashSet(); +- final Set chunksToUpdateFutures = Sets.newHashSet(); + // Paper start use a queue, but still keep unique requirement + public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { + @Override @@ -35,10 +35,10 @@ index 8f993f15ae02c2e4af9cc732cd1b040cce0a67e8..71a51cc99e26579e765f88340588e239 + } + }; + // Paper end - private final ChunkTaskPriorityQueueSorter ticketThrottler; - private final ProcessorHandle> ticketThrottlerInput; - private final ProcessorHandle ticketThrottlerReleaser; -@@ -100,26 +109,14 @@ public abstract class DistanceManager { + final ChunkTaskPriorityQueueSorter ticketThrottler; + final ProcessorHandle> ticketThrottlerInput; + final ProcessorHandle ticketThrottlerReleaser; +@@ -108,26 +117,14 @@ public abstract class DistanceManager { ; } @@ -52,7 +52,7 @@ index 8f993f15ae02c2e4af9cc732cd1b040cce0a67e8..71a51cc99e26579e765f88340588e239 - iter.remove(); - expectedSize--; - -- playerchunk.updateFutures(chunkStorage); +- playerchunk.updateFutures(playerchunkmap, this.mainThreadExecutor); - - // Reset iterator if set was modified using add() - if (this.chunksToUpdateFutures.size() != expectedSize) { @@ -67,13 +67,13 @@ index 8f993f15ae02c2e4af9cc732cd1b040cce0a67e8..71a51cc99e26579e765f88340588e239 + while(!this.pendingChunkUpdates.isEmpty()) { + ChunkHolder remove = this.pendingChunkUpdates.remove(); + remove.isUpdateQueued = false; -+ remove.updateFutures(chunkStorage); ++ remove.updateFutures(playerchunkmap, this.mainThreadExecutor); + } + // Paper end return true; } else { if (!this.ticketsToRelease.isEmpty()) { -@@ -342,7 +339,7 @@ public abstract class DistanceManager { +@@ -385,7 +382,7 @@ public abstract class DistanceManager { if (k != level) { playerchunk = DistanceManager.this.updateChunkScheduling(id, level, playerchunk, k); if (playerchunk != null) { @@ -82,12 +82,3 @@ index 8f993f15ae02c2e4af9cc732cd1b040cce0a67e8..71a51cc99e26579e765f88340588e239 } } -@@ -373,7 +370,7 @@ public abstract class DistanceManager { - ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); -+ Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix - byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); - long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); - diff --git a/patches/server-remapped/0357-Implement-CraftBlockSoundGroup.patch b/patches/server/0328-Implement-CraftBlockSoundGroup.patch similarity index 81% rename from patches/server-remapped/0357-Implement-CraftBlockSoundGroup.patch rename to patches/server/0328-Implement-CraftBlockSoundGroup.patch index 0fd2f20b1d..af7bd8930d 100644 --- a/patches/server-remapped/0357-Implement-CraftBlockSoundGroup.patch +++ b/patches/server/0328-Implement-CraftBlockSoundGroup.patch @@ -49,11 +49,11 @@ index 0000000000000000000000000000000000000000..9a516520d975f52169e346adc4ec6d9d + } +} diff --git a/src/main/java/net/minecraft/world/level/block/SoundType.java b/src/main/java/net/minecraft/world/level/block/SoundType.java -index 1d3acbbc80a38998fb38e0ce37af52103f677721..44394adbe60b5e9c4654ee2f437d465bef5909a8 100644 +index 46042087ef1e01cb9ca1f00137c436c6afa15599..74149f372b50e50fd735801324247787ad55d8b8 100644 --- a/src/main/java/net/minecraft/world/level/block/SoundType.java +++ b/src/main/java/net/minecraft/world/level/block/SoundType.java -@@ -54,10 +54,10 @@ public class SoundType { - public static final SoundType GILDED_BLACKSTONE = new SoundType(1.0F, 1.0F, SoundEvents.GILDED_BLACKSTONE_BREAK, SoundEvents.GILDED_BLACKSTONE_STEP, SoundEvents.GILDED_BLACKSTONE_PLACE, SoundEvents.GILDED_BLACKSTONE_HIT, SoundEvents.GILDED_BLACKSTONE_FALL); +@@ -82,10 +82,10 @@ public class SoundType { + public static final SoundType POLISHED_DEEPSLATE = new SoundType(1.0F, 1.0F, SoundEvents.POLISHED_DEEPSLATE_BREAK, SoundEvents.POLISHED_DEEPSLATE_STEP, SoundEvents.POLISHED_DEEPSLATE_PLACE, SoundEvents.POLISHED_DEEPSLATE_HIT, SoundEvents.POLISHED_DEEPSLATE_FALL); public final float volume; public final float pitch; - public final SoundEvent breakSound; @@ -66,12 +66,12 @@ index 1d3acbbc80a38998fb38e0ce37af52103f677721..44394adbe60b5e9c4654ee2f437d465b public SoundType(float volume, float pitch, SoundEvent breakSound, SoundEvent stepSound, SoundEvent placeSound, SoundEvent hitSound, SoundEvent fallSound) { diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index d73086970db19531db66c2e8af52da91d0b1ea28..5bff313dbbb3049105874846d995883e827fbc00 100644 +index ca03ed4b1581df2b7db272d6f330174a9d277153..0a9ed9992a2fc97472a06591a5d129a767ce21af 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -747,4 +747,11 @@ public class CraftBlock implements Block { +@@ -749,4 +749,11 @@ public class CraftBlock implements Block { AABB aabb = shape.bounds(); - return new BoundingBox(getX() + aabb.minX, getY() + aabb.minY, getZ() + aabb.minZ, getX() + aabb.maxX, getY() + aabb.maxY, getZ() + aabb.maxZ); + return new BoundingBox(this.getX() + aabb.minX, this.getY() + aabb.minY, this.getZ() + aabb.minZ, this.getX() + aabb.maxX, this.getY() + aabb.maxY, this.getZ() + aabb.maxZ); } + + // Paper start diff --git a/patches/server-remapped/0358-Chunk-debug-command.patch b/patches/server/0329-Chunk-debug-command.patch similarity index 92% rename from patches/server-remapped/0358-Chunk-debug-command.patch rename to patches/server/0329-Chunk-debug-command.patch index a8a34d2b86..23269b110d 100644 --- a/patches/server-remapped/0358-Chunk-debug-command.patch +++ b/patches/server/0329-Chunk-debug-command.patch @@ -32,7 +32,7 @@ https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528273&page=com.atlass https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528577&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528577 diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 8fd716bf2e1402694798b8be03fd85821153be44..53dd6c18de8e80378852bbb141016d9574d42162 100644 +index 1fa190e098079522e0fe3593fa261c1b7ad4e24b..71ffa66973d8994e2a480435ac1ada3fe61600a4 100644 --- a/src/main/java/com/destroystokyo/paper/PaperCommand.java +++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java @@ -6,13 +6,15 @@ import com.google.common.collect.ImmutableSet; @@ -212,10 +212,10 @@ index 8fd716bf2e1402694798b8be03fd85821153be44..53dd6c18de8e80378852bbb141016d95 * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 */ diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 1fecc81b25109592907623741225a6222a8c5ccc..a16551c81a444685f6337a65b6d7862b8c0dc684 100644 +index 0df3961919f04f27eb265ab316aa5a0f15a70854..e31dbb1346ba6755bc367a3eab6f87574b4eb3c4 100644 --- a/src/main/java/net/minecraft/server/MCUtil.java +++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -9,13 +9,27 @@ import net.minecraft.core.BlockPos; +@@ -8,13 +8,27 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -243,7 +243,7 @@ index 1fecc81b25109592907623741225a6222a8c5ccc..a16551c81a444685f6337a65b6d7862b import org.bukkit.Location; import org.bukkit.block.BlockFace; import org.bukkit.craftbukkit.CraftWorld; -@@ -24,8 +38,11 @@ import org.spigotmc.AsyncCatcher; +@@ -23,8 +37,11 @@ import org.spigotmc.AsyncCatcher; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -255,11 +255,10 @@ index 1fecc81b25109592907623741225a6222a8c5ccc..a16551c81a444685f6337a65b6d7862b import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.LinkedBlockingQueue; -@@ -531,4 +548,170 @@ public final class MCUtil { - +@@ -530,6 +547,172 @@ public final class MCUtil { return null; } -+ + + public static ChunkStatus getChunkStatus(ChunkHolder chunk) { + List statuses = ServerChunkCache.getPossibleChunkStatuses(); + for (int i = statuses.size() - 1; i >= 0; --i) { @@ -425,25 +424,15 @@ index 1fecc81b25109592907623741225a6222a8c5ccc..a16551c81a444685f6337a65b6d7862b + out.print(fileData); + } + } - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 89e90806b78d94d5c1d781113da420dafa47930a..a89b9dab043ad4536014141d5a942670b4152a95 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -53,7 +53,7 @@ public class ChunkHolder { - public int oldTicketLevel; - private int ticketLevel; - private int queueLevel; -- private final ChunkPos pos; -+ final ChunkPos pos; // Paper - private -> package - private boolean hasChangedSections; - private final ShortSet[] changedBlocksPerSection; - private int blockChangedLightSectionFilter; ++ + public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) { + return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status); + } diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 5d87a282042d7112415b7d7175031f734219f2c9..7585b6f87b72f53deccbcb8627a13503921fc682 100644 +index 95ac30f56a9268f14d2518974c5a52e08f40ea18..25826b41812f2d9ac29806ad7a9242e5674376fc 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -104,7 +104,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -110,7 +110,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; private final Long2ObjectLinkedOpenHashMap pendingUnloads; @@ -453,10 +442,10 @@ index 5d87a282042d7112415b7d7175031f734219f2c9..7585b6f87b72f53deccbcb8627a13503 private final ThreadedLevelLightEngine lightEngine; private final BlockableEventLoop mainThreadExecutor; diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index a7122a0411f4a8656efd4facde3403c8093bc8a6..6d33c1ee44bc732b58d18a8f6b0fd4bbdcb2dcd6 100644 +index 71ac5cf0fdedcfe422bf6f5e6ffb15ce4138aa04..77bb2fb280293da4a38f9acc6503e84997ecb399 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -46,7 +46,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper +@@ -49,7 +49,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper public class ServerChunkCache extends ChunkSource { @@ -464,13 +453,13 @@ index a7122a0411f4a8656efd4facde3403c8093bc8a6..6d33c1ee44bc732b58d18a8f6b0fd4bb + private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); public static final List getPossibleChunkStatuses() { return ServerChunkCache.CHUNK_STATUSES; } // Paper - OBFHELPER private final DistanceManager distanceManager; public final ChunkGenerator generator; - private final ServerLevel level; + final ServerLevel level; diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 0c118d482e304c567fe7fe778c6ff386f960bdde..c6b5f32153b63ac92df9c4b31b8de168481f79f2 100644 +index b346fa94b23d81da7da073f71dd12e672e0f079c..95f5050518109c4ae0b6846be65204cc29afc723 100644 --- a/src/main/java/net/minecraft/server/level/Ticket.java +++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -6,8 +6,8 @@ public final class Ticket implements Comparable> { - +@@ -5,8 +5,8 @@ import java.util.Objects; + public final class Ticket implements Comparable> { private final TicketType type; private final int ticketLevel; - public final T key; diff --git a/patches/server-remapped/0360-Fix-World-isChunkGenerated-calls.patch b/patches/server/0360-Fix-World-isChunkGenerated-calls.patch similarity index 100% rename from patches/server-remapped/0360-Fix-World-isChunkGenerated-calls.patch rename to patches/server/0360-Fix-World-isChunkGenerated-calls.patch From 2bf9070a52d6610152b3d223293149837b233df2 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Sun, 13 Jun 2021 14:44:31 +0200 Subject: [PATCH 074/226] Move this back --- .../0360-Fix-World-isChunkGenerated-calls.patch | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename patches/{server => server-remapped}/0360-Fix-World-isChunkGenerated-calls.patch (100%) diff --git a/patches/server/0360-Fix-World-isChunkGenerated-calls.patch b/patches/server-remapped/0360-Fix-World-isChunkGenerated-calls.patch similarity index 100% rename from patches/server/0360-Fix-World-isChunkGenerated-calls.patch rename to patches/server-remapped/0360-Fix-World-isChunkGenerated-calls.patch From fd645b456c6e5f0db18c1a3c28051346dd87d21d Mon Sep 17 00:00:00 2001 From: KennyTV Date: Sun, 13 Jun 2021 14:54:37 +0200 Subject: [PATCH 075/226] Fix compile --- .../0328-Implement-CraftBlockSoundGroup.patch | 17 ------ patches/server/0329-Chunk-debug-command.patch | 52 +++++++++++++------ 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/patches/server/0328-Implement-CraftBlockSoundGroup.patch b/patches/server/0328-Implement-CraftBlockSoundGroup.patch index af7bd8930d..76559b8fc1 100644 --- a/patches/server/0328-Implement-CraftBlockSoundGroup.patch +++ b/patches/server/0328-Implement-CraftBlockSoundGroup.patch @@ -48,23 +48,6 @@ index 0000000000000000000000000000000000000000..9a516520d975f52169e346adc4ec6d9d + return CraftSound.getBukkit(soundEffectType.getFallSound()); + } +} -diff --git a/src/main/java/net/minecraft/world/level/block/SoundType.java b/src/main/java/net/minecraft/world/level/block/SoundType.java -index 46042087ef1e01cb9ca1f00137c436c6afa15599..74149f372b50e50fd735801324247787ad55d8b8 100644 ---- a/src/main/java/net/minecraft/world/level/block/SoundType.java -+++ b/src/main/java/net/minecraft/world/level/block/SoundType.java -@@ -82,10 +82,10 @@ public class SoundType { - public static final SoundType POLISHED_DEEPSLATE = new SoundType(1.0F, 1.0F, SoundEvents.POLISHED_DEEPSLATE_BREAK, SoundEvents.POLISHED_DEEPSLATE_STEP, SoundEvents.POLISHED_DEEPSLATE_PLACE, SoundEvents.POLISHED_DEEPSLATE_HIT, SoundEvents.POLISHED_DEEPSLATE_FALL); - public final float volume; - public final float pitch; -- public final SoundEvent breakSound; -+ public final SoundEvent breakSound; public final SoundEvent getBreakSound() { return this.breakSound; } // Paper - OBFHELPER // PAIL private -> public, rename breakSound - private final SoundEvent stepSound; - private final SoundEvent placeSound; -- public final SoundEvent hitSound; -+ public final SoundEvent hitSound; public final SoundEvent getHitSound() { return this.hitSound; } // Paper - OBFHELPER // PAIL private -> public, rename hitSound - private final SoundEvent fallSound; - - public SoundType(float volume, float pitch, SoundEvent breakSound, SoundEvent stepSound, SoundEvent placeSound, SoundEvent hitSound, SoundEvent fallSound) { diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java index ca03ed4b1581df2b7db272d6f330174a9d277153..0a9ed9992a2fc97472a06591a5d129a767ce21af 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java diff --git a/patches/server/0329-Chunk-debug-command.patch b/patches/server/0329-Chunk-debug-command.patch index 23269b110d..5e3097224e 100644 --- a/patches/server/0329-Chunk-debug-command.patch +++ b/patches/server/0329-Chunk-debug-command.patch @@ -212,7 +212,7 @@ index 1fa190e098079522e0fe3593fa261c1b7ad4e24b..71ffa66973d8994e2a480435ac1ada3f * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 */ diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 0df3961919f04f27eb265ab316aa5a0f15a70854..e31dbb1346ba6755bc367a3eab6f87574b4eb3c4 100644 +index 0df3961919f04f27eb265ab316aa5a0f15a70854..bb0a07a280c7d4885165e9d6488e7741aaa7b47c 100644 --- a/src/main/java/net/minecraft/server/MCUtil.java +++ b/src/main/java/net/minecraft/server/MCUtil.java @@ -8,13 +8,27 @@ import net.minecraft.core.BlockPos; @@ -341,10 +341,10 @@ index 0df3961919f04f27eb265ab316aa5a0f15a70854..e31dbb1346ba6755bc367a3eab6f8757 + + // sorting by coordinate makes the log easier to read + allChunks.sort((ChunkHolder v1, ChunkHolder v2) -> { -+ if (v1.location.x != v2.location.x) { -+ return Integer.compare(v1.location.x, v2.location.x); ++ if (v1.pos.x != v2.pos.x) { ++ return Integer.compare(v1.pos.x, v2.pos.x); + } -+ return Integer.compare(v1.location.z, v2.location.z); ++ return Integer.compare(v1.pos.z, v2.pos.z); + }); + + worldData.addProperty("name", world.getWorld().getName()); @@ -376,14 +376,14 @@ index 0df3961919f04f27eb265ab316aa5a0f15a70854..e31dbb1346ba6755bc367a3eab6f8757 + for (ChunkHolder playerChunk : allChunks) { + JsonObject chunkData = new JsonObject(); + -+ Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.pair()); ++ Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.longKey); + ChunkStatus status = getChunkStatus(playerChunk); + -+ chunkData.addProperty("x", playerChunk.location.x); -+ chunkData.addProperty("z", playerChunk.location.z); ++ chunkData.addProperty("x", playerChunk.pos.x); ++ chunkData.addProperty("z", playerChunk.pos.z); + chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); + chunkData.addProperty("state", ChunkHolder.getFullChunkStatus(playerChunk.getTicketLevel()).toString()); -+ chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.pair())); ++ chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.longKey)); + chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); + + JsonArray ticketsData = new JsonArray(); @@ -428,6 +428,19 @@ index 0df3961919f04f27eb265ab316aa5a0f15a70854..e31dbb1346ba6755bc367a3eab6f8757 public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) { return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status); } +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 84831fc611589c19320b5e3af107080596b1fbdc..fa6d91886d433c0b7d77c1d059a23ee194ae14a4 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -61,7 +61,7 @@ public class ChunkHolder { + public int oldTicketLevel; + private int ticketLevel; + private int queueLevel; +- final ChunkPos pos; ++ public final ChunkPos pos; // Paper - package->public + private boolean hasChangedSections; + private final ShortSet[] changedBlocksPerSection; + private final BitSet blockChangedLightSectionFilter; diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java index 95ac30f56a9268f14d2518974c5a52e08f40ea18..25826b41812f2d9ac29806ad7a9242e5674376fc 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -454,8 +467,21 @@ index 71ac5cf0fdedcfe422bf6f5e6ffb15ce4138aa04..77bb2fb280293da4a38f9acc6503e849 private final DistanceManager distanceManager; public final ChunkGenerator generator; final ServerLevel level; +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 74a5dcde184c20129cb5fdcfb34ef1c3aecb1842..736521c0925339dc74c2648641932104a947708e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -174,7 +174,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public static final BlockPos END_SPAWN_POINT = new BlockPos(100, 50, 0); + private static final Logger LOGGER = LogManager.getLogger(); + private static final int EMPTY_TIME_NO_TICK = 300; +- final List players; ++ public final List players; // Paper - package->public + public final ServerChunkCache chunkSource; // Paper - public + private final MinecraftServer server; + public final PrimaryLevelData serverLevelData; // CraftBukkit - type diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index b346fa94b23d81da7da073f71dd12e672e0f079c..95f5050518109c4ae0b6846be65204cc29afc723 100644 +index b346fa94b23d81da7da073f71dd12e672e0f079c..8b0c6e1a649400908dbb674dfb4cdd1aa0ce1d38 100644 --- a/src/main/java/net/minecraft/server/level/Ticket.java +++ b/src/main/java/net/minecraft/server/level/Ticket.java @@ -5,8 +5,8 @@ import java.util.Objects; @@ -469,11 +495,3 @@ index b346fa94b23d81da7da073f71dd12e672e0f079c..95f5050518109c4ae0b6846be65204cc protected Ticket(TicketType type, int level, T argument) { this.type = type; -@@ -51,6 +51,7 @@ public final class Ticket implements Comparable> { - return this.type; - } - -+ public final int getTicketLevel() { return this.getTicketLevel(); } // Paper - OBFHELPER - public int getTicketLevel() { - return this.ticketLevel; - } From b804730254a69b703f2532abb71500a680db5d73 Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 13 Jun 2021 15:46:28 +0200 Subject: [PATCH 076/226] more work --- ...30-Fix-World-isChunkGenerated-calls.patch} | 202 ++++++++---------- 1 file changed, 90 insertions(+), 112 deletions(-) rename patches/{server-remapped/0360-Fix-World-isChunkGenerated-calls.patch => server/0330-Fix-World-isChunkGenerated-calls.patch} (67%) diff --git a/patches/server-remapped/0360-Fix-World-isChunkGenerated-calls.patch b/patches/server/0330-Fix-World-isChunkGenerated-calls.patch similarity index 67% rename from patches/server-remapped/0360-Fix-World-isChunkGenerated-calls.patch rename to patches/server/0330-Fix-World-isChunkGenerated-calls.patch index 6f00b2b7ac..953566fa39 100644 --- a/patches/server-remapped/0360-Fix-World-isChunkGenerated-calls.patch +++ b/patches/server/0330-Fix-World-isChunkGenerated-calls.patch @@ -8,12 +8,12 @@ This patch also adds a chunk status cache on region files (note that its only purpose is to cache the status on DISK) diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index a89b9dab043ad4536014141d5a942670b4152a95..7010e0a970462d2b2e1b5696a1a49dba9ea60935 100644 +index fa6d91886d433c0b7d77c1d059a23ee194ae14a4..56e292e6550b19d0cae9ebad369da730ca1cabd8 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -141,6 +141,19 @@ public class ChunkHolder { +@@ -111,6 +111,19 @@ public class ChunkHolder { Either either = (Either) statusFuture.getNow(null); - return either == null ? null : (LevelChunk) either.left().orElse(null); + return (either == null) ? null : (LevelChunk) either.left().orElse(null); } + + public ChunkAccess getAvailableChunkNow() { @@ -28,15 +28,23 @@ index a89b9dab043ad4536014141d5a942670b4152a95..7010e0a970462d2b2e1b5696a1a49dba + } + return null; + } - // Paper end + // CraftBukkit end public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 7585b6f87b72f53deccbcb8627a13503921fc682..0aac29de933c84c34cb24e204e8fcc7010060d8f 100644 +index 25826b41812f2d9ac29806ad7a9242e5674376fc..dd7de2c3db10d9d606d47c52eba40e71034fc11a 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -991,12 +991,61 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } +@@ -84,6 +84,7 @@ import net.minecraft.world.level.chunk.ProtoChunk; + import net.minecraft.world.level.chunk.UpgradeData; + import net.minecraft.world.level.chunk.storage.ChunkSerializer; + import net.minecraft.world.level.chunk.storage.ChunkStorage; ++import net.minecraft.world.level.chunk.storage.RegionFile; + import net.minecraft.world.level.entity.ChunkStatusUpdateListener; + import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; +@@ -1083,12 +1084,61 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end @Nullable - private CompoundTag readChunk(ChunkPos pos) throws IOException { @@ -60,15 +68,16 @@ index 7585b6f87b72f53deccbcb8627a13503921fc682..0aac29de933c84c34cb24e204e8fcc70 + + // Paper start - chunk status cache "api" + public ChunkStatus getChunkStatusOnDiskIfCached(ChunkPos chunkPos) { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); -+ ++ RegionFile regionFile = regionFileCache.getRegionFileIfLoaded(chunkPos); + +- return nbttagcompound == null ? null : this.getChunkData(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, pos, level); // CraftBukkit + return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } -+ + } + + public ChunkStatus getChunkStatusOnDisk(ChunkPos chunkPos) throws IOException { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); ++ RegionFile regionFile = regionFileCache.getFile(chunkPos, true); + -+ if (regionFile == null || !regionFile.chunkExists(chunkPos)) { ++ if (regionFile == null || !regionFileCache.chunkExists(chunkPos)) { + return null; + } + @@ -79,13 +88,12 @@ index 7585b6f87b72f53deccbcb8627a13503921fc682..0aac29de933c84c34cb24e204e8fcc70 + } + + this.readChunk(chunkPos); - -- return nbttagcompound == null ? null : this.getChunkData(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, pos, level); // CraftBukkit ++ + return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); - } - ++ } ++ + public void updateChunkStatusOnDisk(ChunkPos chunkPos, @Nullable CompoundTag compound) throws IOException { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); ++ RegionFile regionFile = regionFileCache.getFile(chunkPos, false); + + regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); + } @@ -96,58 +104,50 @@ index 7585b6f87b72f53deccbcb8627a13503921fc682..0aac29de933c84c34cb24e204e8fcc70 + } + // Paper end + - boolean noPlayersCloseForSpawning(ChunkPos chunkcoordintpair) { + boolean noPlayersCloseForSpawning(ChunkPos chunkPos) { // Spigot start - return isOutsideOfRange(chunkcoordintpair, false); + return this.isOutsideOfRange(chunkPos, false); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 6d33c1ee44bc732b58d18a8f6b0fd4bbdcb2dcd6..1e8ac0110badbf2d1c2336168c3e11991667c782 100644 +index 77bb2fb280293da4a38f9acc6503e84997ecb399..c47d1772044913475a60292162ef4be594bed4c6 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -52,7 +52,7 @@ public class ServerChunkCache extends ChunkSource { - private final ServerLevel level; - public final Thread mainThread; // Paper - private -> public - private final ThreadedLevelLightEngine lightEngine; -- private final ServerChunkCache.MainThreadExecutor mainThreadProcessor; +@@ -52,10 +52,10 @@ public class ServerChunkCache extends ChunkSource { + private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); public static final List getPossibleChunkStatuses() { return ServerChunkCache.CHUNK_STATUSES; } // Paper - OBFHELPER + private final DistanceManager distanceManager; + public final ChunkGenerator generator; +- final ServerLevel level; +- public final Thread mainThread; // Paper - package-private -> public +- final ThreadedLevelLightEngine lightEngine; +- public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; // Paper - private -> public ++ private final ServerLevel level; ++ public final Thread mainThread; // Paper - private -> public ++ private final ThreadedLevelLightEngine lightEngine; + public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; // Paper private -> public public final ChunkMap chunkMap; private final DimensionDataStorage dataStorage; private long lastInhabitedUpdate; -@@ -317,6 +317,21 @@ public class ServerChunkCache extends ChunkSource { - - return ret; +@@ -324,6 +324,7 @@ public class ServerChunkCache extends ChunkSource { } -+ -+ @Nullable -+ public ChunkAccess getChunkAtImmediately(int x, int z) { -+ long k = ChunkPos.asLong(x, z); -+ -+ // Note: Bypass cache to make this MT-Safe -+ -+ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(k); -+ if (playerChunk == null) { -+ return null; -+ } -+ -+ return playerChunk.getAvailableChunkNow(); -+ -+ } // Paper end - - @Nullable -@@ -771,7 +786,7 @@ public class ServerChunkCache extends ChunkSource { + // Paper start - async chunk io ++ @Nullable + public ChunkAccess getChunkAtImmediately(int x, int z) { + ChunkHolder holder = this.chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); + if (holder == null) { +@@ -922,7 +923,7 @@ public class ServerChunkCache extends ChunkSource { return this.lastSpawnState; } -- final class MainThreadExecutor extends BlockableEventLoop { +- private final class MainThreadExecutor extends BlockableEventLoop { + public final class MainThreadExecutor extends BlockableEventLoop { // Paper - package -> public - private MainThreadExecutor(Level world) { + MainThreadExecutor(Level world) { super("Chunk source main thread executor for " + world.dimension().location()); diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -index ae84dc310c076e3212d3cdbca77a1ab06a11d479..46d5a24332c1fd3c164b760ec2a2d5bf859b1ab6 100644 +index 6e0cf8ee76143301c939fc4af5eeb091abdcbc5c..066f03ee7b4feda9ec2b0984ee7cf63fa0b9e4fc 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -@@ -193,6 +193,7 @@ public class ChunkStatus { +@@ -204,6 +204,7 @@ public class ChunkStatus { return this.name; } @@ -155,7 +155,7 @@ index ae84dc310c076e3212d3cdbca77a1ab06a11d479..46d5a24332c1fd3c164b760ec2a2d5bf public ChunkStatus getParent() { return this.parent; } -@@ -213,6 +214,17 @@ public class ChunkStatus { +@@ -224,6 +225,17 @@ public class ChunkStatus { return this.chunkType; } @@ -174,12 +174,12 @@ index ae84dc310c076e3212d3cdbca77a1ab06a11d479..46d5a24332c1fd3c164b760ec2a2d5bf return (ChunkStatus) Registry.CHUNK_STATUS.get(ResourceLocation.tryParse(id)); } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 542d6f322df5f44ad9f504c8e14c88e3fa540657..969130442b529eaac6f708107ff129f89cc0af90 100644 +index 2621739b8dd11860084ea574c243cb8ba167ac40..fc320450878279a6aa48019fbde35bb183f5f06e 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -462,6 +462,17 @@ public class ChunkSerializer { +@@ -545,6 +545,17 @@ public class ChunkSerializer { + return nbttagcompound; } - // Paper end + // Paper start + public static ChunkStatus getStatus(CompoundTag compound) { @@ -192,37 +192,24 @@ index 542d6f322df5f44ad9f504c8e14c88e3fa540657..969130442b529eaac6f708107ff129f8 + } + // Paper end + - public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag tag) { - if (tag != null) { - ChunkStatus chunkstatus = ChunkStatus.byName(tag.getCompound("Level").getString("Status")); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -index 637274532b01bb7b4cdb7d7b1b58181b98ac7e98..9cffef2098fbfba89ddd88a45bde33c07660497a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -@@ -21,7 +21,7 @@ import net.minecraft.world.level.storage.DimensionDataStorage; - - public class ChunkStorage implements AutoCloseable { - -- private final IOWorker worker; -+ private final IOWorker worker; public IOWorker getIOWorker() { return worker; } // Paper - OBFHELPER - protected final DataFixer fixerUpper; - @Nullable - private LegacyStructureDataHandler legacyStructureHandler; + public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag nbt) { + if (nbt != null) { + ChunkStatus chunkstatus = ChunkStatus.byName(nbt.getCompound("Level").getString("Status")); diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 424628c9588c02454558bc7e7c5bad3a3e75ec9f..4d96e5ed28c910387c0a4238c9036c7a12458f57 100644 +index 357da4846344d1182ab7149c4d352d5019384715..832392cc2adc94e1fcb1055d91eb465529da1e92 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -27,6 +27,7 @@ import net.minecraft.Util; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.NbtIo; +@@ -23,6 +23,7 @@ import java.nio.file.StandardOpenOption; + import javax.annotation.Nullable; + import net.minecraft.Util; import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.ChunkStatus; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -@@ -44,6 +45,30 @@ public class RegionFile implements AutoCloseable { +@@ -49,6 +50,30 @@ public class RegionFile implements AutoCloseable { protected final RegionBitmap usedSectors; - public final File file; // Paper + public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper + // Paper start - Cache chunk status + private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; @@ -251,7 +238,7 @@ index 424628c9588c02454558bc7e7c5bad3a3e75ec9f..4d96e5ed28c910387c0a4238c9036c7a public RegionFile(File file, File directory, boolean dsync) throws IOException { this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); } -@@ -380,11 +405,13 @@ public class RegionFile implements AutoCloseable { +@@ -395,6 +420,7 @@ public class RegionFile implements AutoCloseable { return this.getOffset(pos) != 0; } @@ -259,45 +246,36 @@ index 424628c9588c02454558bc7e7c5bad3a3e75ec9f..4d96e5ed28c910387c0a4238c9036c7a private static int getOffsetIndex(ChunkPos pos) { return pos.getRegionLocalX() + pos.getRegionLocalZ() * 32; } - - public void close() throws IOException { +@@ -405,6 +431,7 @@ public class RegionFile implements AutoCloseable { + synchronized (this) { + try { + // Paper end + this.closed = true; // Paper try { this.padToFullSector(); } finally { diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 6d3e1bb20d1ab8ce5c9ea613322042d80550761a..6f1c96e4325caf6b4762700ad2286d9ea41515c9 100644 +index 211ab6cffe78c61fcff12ef7ffba904c4cae57b2..1bee455235ece8aa299a2baeede027d251e6ff57 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -28,7 +28,14 @@ public final class RegionFileStorage implements AutoCloseable { - this.sync = dsync; +@@ -143,6 +143,7 @@ public class RegionFileStorage implements AutoCloseable { // Paper - no final + + try { + NbtIo.write(nbt, (DataOutput) dataoutputstream); ++ regionfile.setStatus(pos.x, pos.z, ChunkSerializer.getStatus(nbt)); // Paper - cache status on disk + } catch (Throwable throwable) { + if (dataoutputstream != null) { + try { +@@ -205,3 +206,4 @@ public class RegionFileStorage implements AutoCloseable { // Paper - no final + } - -- private RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit + } + -+ // Paper start -+ public RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { -+ return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); -+ } -+ -+ // Paper end -+ public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public - long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); - RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); - -@@ -175,6 +182,7 @@ public final class RegionFileStorage implements AutoCloseable { - - try { - NbtIo.write(tag, (DataOutput) dataoutputstream); -+ regionfile.setStatus(pos.x, pos.z, ChunkSerializer.getStatus(tag)); // Paper - cache status on disk - regionfile.setOversized(pos.x, pos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone - } catch (Throwable throwable1) { - throwable = throwable1; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0cb0021fac211996c5bdbb2cfc8f54addc3b49f6..a0615e4ba015cca4fe074de63b87d0bff84b1a14 100644 +index 30305736b7dc023ad5eb3a177914560b3fec64ee..4841591539fdd5a01f9ded0ee510991602c266a4 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -19,6 +19,7 @@ import java.util.Objects; +@@ -20,6 +20,7 @@ import java.util.Objects; import java.util.Random; import java.util.Set; import java.util.UUID; @@ -305,7 +283,7 @@ index 0cb0021fac211996c5bdbb2cfc8f54addc3b49f6..a0615e4ba015cca4fe074de63b87d0bf import java.util.function.Predicate; import java.util.stream.Collectors; import net.minecraft.core.BlockPos; -@@ -401,8 +402,22 @@ public class CraftWorld implements World { +@@ -417,8 +418,22 @@ public class CraftWorld implements World { @Override public boolean isChunkGenerated(int x, int z) { @@ -323,24 +301,24 @@ index 0cb0021fac211996c5bdbb2cfc8f54addc3b49f6..a0615e4ba015cca4fe074de63b87d0bf + return chunk instanceof ImposterProtoChunk || chunk instanceof net.minecraft.world.level.chunk.LevelChunk; + } try { -- return world.getChunkSource().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; // Paper (TODO check if the first part can be removed) +- return this.world.getChunkSource().getChunkAtIfCachedImmediately(x, z) != null || this.world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; // Paper (TODO check if the first part can be removed) + return world.getChunkSource().chunkMap.getChunkStatusOnDisk(new ChunkPos(x, z)) == ChunkStatus.FULL; + // Paper end } catch (IOException ex) { throw new RuntimeException(ex); } -@@ -513,20 +528,48 @@ public class CraftWorld implements World { +@@ -529,20 +544,48 @@ public class CraftWorld implements World { @Override public boolean loadChunk(int x, int z, boolean generate) { org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -- ChunkAccess chunk = world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper +- ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper + // Paper start - Optimize this method + ChunkPos chunkPos = new ChunkPos(x, z); - // If generate = false, but the chunk already exists, we will get this back. - if (chunk instanceof ImposterProtoChunk) { - // We then cycle through again to get the full chunk immediately, rather than after the ticket addition -- chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); +- chunk = this.world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); - } + if (!generate) { + ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z); @@ -357,11 +335,11 @@ index 0cb0021fac211996c5bdbb2cfc8f54addc3b49f6..a0615e4ba015cca4fe074de63b87d0bf + } - if (chunk instanceof net.minecraft.world.level.chunk.LevelChunk) { -- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); +- this.world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); - return true; + net.minecraft.world.level.chunk.storage.RegionFile file; + try { -+ file = world.getChunkSource().chunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); ++ file = world.getChunkSource().chunkMap.regionFileCache.getFile(chunkPos, false); + } catch (IOException ex) { + throw new RuntimeException(ex); + } From 0ea382b41d440644c103961fd9373574b6e12772 Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 13 Jun 2021 15:46:49 +0200 Subject: [PATCH 077/226] fix kneny dumb --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 101bc900a8..407f27e9d2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight.core") version "1.0.0-LOCAL-SNAPSHOT" + id("io.papermc.paperweight.core") version "1.0.0-SNAPSHOT" } val mcVersion = providers.gradleProperty("mcVersion") From 8af12b17c10fd45518f96fcbc740f97993237fa3 Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 13 Jun 2021 16:14:18 +0200 Subject: [PATCH 078/226] even more work --- ...PaletteBlock-instead-of-ReentrantLoc.patch | 2 +- .../1.17}/0363-incremental-chunk-saving.patch | 2 +- .../1.17}/0364-Anti-Xray.patch | 4 +++- ...-being-ticked-when-notifying-navigat.patch | 2 +- ...opper-searches-if-there-are-no-items.patch | 2 +- ...etChunkIfLoadedImmediately-in-places.patch | 2 +- .../1.17}/0372-Reduce-sync-loads.patch | 2 +- ...lement-alternative-item-despawn-rate.patch | 2 +- ...ement-optional-per-player-mob-spawns.patch | 2 +- ...te-location-if-we-failed-to-read-it.patch} | 2 +- ...l-Spawned-mobs-towards-natural-spaw.patch} | 19 +++++++++---------- ...urable-projectile-relative-velocity.patch} | 11 ++++++----- .../0334-offset-item-frame-ticking.patch} | 2 +- ...f-we-have-a-custom-Bukkit-generator.patch} | 10 +++++----- .../0336-Fix-MC-158900.patch} | 6 +++--- ...event-consuming-the-wrong-itemstack.patch} | 8 ++++---- 16 files changed, 40 insertions(+), 38 deletions(-) rename patches/{server-remapped => removed/1.17}/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch (99%) rename patches/{server-remapped => removed/1.17}/0363-incremental-chunk-saving.patch (99%) rename patches/{server-remapped => removed/1.17}/0364-Anti-Xray.patch (99%) rename patches/{server-remapped => removed/1.17}/0367-Mark-entities-as-being-ticked-when-notifying-navigat.patch (96%) rename patches/{server-remapped => removed/1.17}/0369-Avoid-hopper-searches-if-there-are-no-items.patch (99%) rename patches/{server-remapped => removed/1.17}/0371-Use-getChunkIfLoadedImmediately-in-places.patch (99%) rename patches/{server-remapped => removed/1.17}/0372-Reduce-sync-loads.patch (99%) rename patches/{server-remapped => removed/1.17}/0373-Implement-alternative-item-despawn-rate.patch (99%) rename patches/{server-remapped => removed/1.17}/0376-implement-optional-per-player-mob-spawns.patch (99%) rename patches/{server-remapped/0361-Show-blockstate-location-if-we-failed-to-read-it.patch => server/0331-Show-blockstate-location-if-we-failed-to-read-it.patch} (94%) rename patches/{server-remapped/0365-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch => server/0332-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch} (79%) rename patches/{server-remapped/0366-Configurable-projectile-relative-velocity.patch => server/0333-Configurable-projectile-relative-velocity.patch} (85%) rename patches/{server-remapped/0368-offset-item-frame-ticking.patch => server/0334-offset-item-frame-ticking.patch} (90%) rename patches/{server-remapped/0374-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch => server/0335-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch} (85%) rename patches/{server-remapped/0375-Fix-MC-158900.patch => server/0336-Fix-MC-158900.patch} (84%) rename patches/{server-remapped/0377-Prevent-consuming-the-wrong-itemstack.patch => server/0337-Prevent-consuming-the-wrong-itemstack.patch} (89%) diff --git a/patches/server-remapped/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch b/patches/removed/1.17/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch similarity index 99% rename from patches/server-remapped/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch rename to patches/removed/1.17/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch index 9769725fb1..f172c356ec 100644 --- a/patches/server-remapped/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch +++ b/patches/removed/1.17/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Fri, 29 May 2020 20:29:02 -0400 Subject: [PATCH] Synchronize DataPaletteBlock instead of ReentrantLock - +1.17: Mini have fun I don't want to die Mojang has flaws in their logic about chunks being concurrently wrote to. So we constantly see crashes around multiple threads writing. diff --git a/patches/server-remapped/0363-incremental-chunk-saving.patch b/patches/removed/1.17/0363-incremental-chunk-saving.patch similarity index 99% rename from patches/server-remapped/0363-incremental-chunk-saving.patch rename to patches/removed/1.17/0363-incremental-chunk-saving.patch index 1600ad9506..70420b4593 100644 --- a/patches/server-remapped/0363-incremental-chunk-saving.patch +++ b/patches/removed/1.17/0363-incremental-chunk-saving.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Sun, 9 Jun 2019 03:53:22 +0100 Subject: [PATCH] incremental chunk saving - +1.17: saved for MM diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java index ffe9b1a63d78925e1d77b9e730aef42fed6d58fa..1278d09f70c1e97607ef20d87a178dc252c7f723 100644 diff --git a/patches/server-remapped/0364-Anti-Xray.patch b/patches/removed/1.17/0364-Anti-Xray.patch similarity index 99% rename from patches/server-remapped/0364-Anti-Xray.patch rename to patches/removed/1.17/0364-Anti-Xray.patch index 95ed9fdc2a..250195a551 100644 --- a/patches/server-remapped/0364-Anti-Xray.patch +++ b/patches/removed/1.17/0364-Anti-Xray.patch @@ -2,7 +2,9 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: stonar96 Date: Mon, 20 Aug 2018 03:03:58 +0200 Subject: [PATCH] Anti-Xray - +stonar96 — Today at 15:49 +I'm just here to watch you suffer :smile: +You can skip it if you want and I can do it later. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java index 1278d09f70c1e97607ef20d87a178dc252c7f723..c45493e88bf7e8811be2759ff9ac19e3fe9d938a 100644 diff --git a/patches/server-remapped/0367-Mark-entities-as-being-ticked-when-notifying-navigat.patch b/patches/removed/1.17/0367-Mark-entities-as-being-ticked-when-notifying-navigat.patch similarity index 96% rename from patches/server-remapped/0367-Mark-entities-as-being-ticked-when-notifying-navigat.patch rename to patches/removed/1.17/0367-Mark-entities-as-being-ticked-when-notifying-navigat.patch index 17630cf486..a5be725dd8 100644 --- a/patches/server-remapped/0367-Mark-entities-as-being-ticked-when-notifying-navigat.patch +++ b/patches/removed/1.17/0367-Mark-entities-as-being-ticked-when-notifying-navigat.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Sun, 28 Jul 2019 00:51:11 +0100 Subject: [PATCH] Mark entities as being ticked when notifying navigation - +1.17: Check how this is done after rework diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 7a09bc921827958f58290bd3d6f19984bb34a8f6..a811ced17721b70bb51837f47e466c2261db2466 100644 diff --git a/patches/server-remapped/0369-Avoid-hopper-searches-if-there-are-no-items.patch b/patches/removed/1.17/0369-Avoid-hopper-searches-if-there-are-no-items.patch similarity index 99% rename from patches/server-remapped/0369-Avoid-hopper-searches-if-there-are-no-items.patch rename to patches/removed/1.17/0369-Avoid-hopper-searches-if-there-are-no-items.patch index ee50904042..f4d9a785b8 100644 --- a/patches/server-remapped/0369-Avoid-hopper-searches-if-there-are-no-items.patch +++ b/patches/removed/1.17/0369-Avoid-hopper-searches-if-there-are-no-items.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: CullanP Date: Thu, 3 Mar 2016 02:13:38 -0600 Subject: [PATCH] Avoid hopper searches if there are no items - +1.17: figure this out after methods got moved Hoppers searching for items and minecarts is the most expensive part of hopper ticking. We keep track of the number of minecarts and items in a chunk. If there are no items in the chunk, we skip searching for items. diff --git a/patches/server-remapped/0371-Use-getChunkIfLoadedImmediately-in-places.patch b/patches/removed/1.17/0371-Use-getChunkIfLoadedImmediately-in-places.patch similarity index 99% rename from patches/server-remapped/0371-Use-getChunkIfLoadedImmediately-in-places.patch rename to patches/removed/1.17/0371-Use-getChunkIfLoadedImmediately-in-places.patch index 3becb4b6e9..cc0346dfaf 100644 --- a/patches/server-remapped/0371-Use-getChunkIfLoadedImmediately-in-places.patch +++ b/patches/removed/1.17/0371-Use-getChunkIfLoadedImmediately-in-places.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Mon, 8 Jul 2019 00:13:36 -0700 Subject: [PATCH] Use getChunkIfLoadedImmediately in places - +1.17: figure out moved entitiy stuff again This prevents us from hitting chunk loads for chunks at or less-than ticket level 33 (yes getChunkIfLoaded will actually perform a chunk load in that case). diff --git a/patches/server-remapped/0372-Reduce-sync-loads.patch b/patches/removed/1.17/0372-Reduce-sync-loads.patch similarity index 99% rename from patches/server-remapped/0372-Reduce-sync-loads.patch rename to patches/removed/1.17/0372-Reduce-sync-loads.patch index 5349d43158..b8467f22af 100644 --- a/patches/server-remapped/0372-Reduce-sync-loads.patch +++ b/patches/removed/1.17/0372-Reduce-sync-loads.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Fri, 19 Jul 2019 03:29:14 -0700 Subject: [PATCH] Reduce sync loads - +1.17: more entity stuff that someone has to figure out! This reduces calls to getChunkAt which would load chunks. This patch also adds a tool to find calls which are doing this, however diff --git a/patches/server-remapped/0373-Implement-alternative-item-despawn-rate.patch b/patches/removed/1.17/0373-Implement-alternative-item-despawn-rate.patch similarity index 99% rename from patches/server-remapped/0373-Implement-alternative-item-despawn-rate.patch rename to patches/removed/1.17/0373-Implement-alternative-item-despawn-rate.patch index 21aa2f962b..dde0e838a6 100644 --- a/patches/server-remapped/0373-Implement-alternative-item-despawn-rate.patch +++ b/patches/removed/1.17/0373-Implement-alternative-item-despawn-rate.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: kickash32 Date: Mon, 3 Jun 2019 02:02:39 -0400 Subject: [PATCH] Implement alternative item-despawn-rate - +1.17: kickash32 want's to do that later diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java index 1ee2cced100626e48eb36ee14f84b9257c79a2f8..b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920 100644 diff --git a/patches/server-remapped/0376-implement-optional-per-player-mob-spawns.patch b/patches/removed/1.17/0376-implement-optional-per-player-mob-spawns.patch similarity index 99% rename from patches/server-remapped/0376-implement-optional-per-player-mob-spawns.patch rename to patches/removed/1.17/0376-implement-optional-per-player-mob-spawns.patch index 70bcd1b1bd..ad609e6f05 100644 --- a/patches/server-remapped/0376-implement-optional-per-player-mob-spawns.patch +++ b/patches/removed/1.17/0376-implement-optional-per-player-mob-spawns.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: kickash32 Date: Mon, 19 Aug 2019 01:27:58 +0500 Subject: [PATCH] implement optional per player mob spawns - +1.17: kickash will take a look at this; has to be figured out again because of changes diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java index 24eac9400fbf971742e89bbf47b0ba52b587c4eb..b818a7451d45d2ab7d4678f0065ada9017d8a631 100644 diff --git a/patches/server-remapped/0361-Show-blockstate-location-if-we-failed-to-read-it.patch b/patches/server/0331-Show-blockstate-location-if-we-failed-to-read-it.patch similarity index 94% rename from patches/server-remapped/0361-Show-blockstate-location-if-we-failed-to-read-it.patch rename to patches/server/0331-Show-blockstate-location-if-we-failed-to-read-it.patch index 873d34715d..f19e042336 100644 --- a/patches/server-remapped/0361-Show-blockstate-location-if-we-failed-to-read-it.patch +++ b/patches/server/0331-Show-blockstate-location-if-we-failed-to-read-it.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Show blockstate location if we failed to read it diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 730fda7f0bf02400d349959e9cc2aafaed000b21..66aee7635cd9260d97ae9dd2e9a2a0590fe3c433 100644 +index 9a30770a2f68e1253afe3ca8ecdae19c988248f9..2b2c9e58eabe148c994152d2596e29a313be921b 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java @@ -19,6 +19,8 @@ public class CraftBlockEntityState extends CraftBlockStat diff --git a/patches/server-remapped/0365-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/patches/server/0332-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch similarity index 79% rename from patches/server-remapped/0365-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch rename to patches/server/0332-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch index 0d019759ff..fbf0003ead 100644 --- a/patches/server-remapped/0365-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch +++ b/patches/server/0332-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch @@ -17,13 +17,14 @@ This should fully solve all of the issues around it so that only natural influences natural spawns. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c45493e88bf7e8811be2759ff9ac19e3fe9d938a..384cb363eed794551bee6b0ec11ba1be92a3d7ac 100644 +index 090958a30ce20ff01ae77d4cd821a167474f0214..baf33659b021c89cbd02560cbfd9b0ddf205f0e2 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -464,6 +464,16 @@ public class PaperWorldConfig { - maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); +@@ -401,4 +401,15 @@ public class PaperWorldConfig { + private void preventMovingIntoUnloadedChunks() { + preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); } - ++ + public boolean countAllMobsForSpawning = false; + private void countAllMobsForSpawning() { + countAllMobsForSpawning = getBoolean("count-all-mobs-for-spawning", false); @@ -33,15 +34,13 @@ index c45493e88bf7e8811be2759ff9ac19e3fe9d938a..384cb363eed794551bee6b0ec11ba1be + log("Using improved mob spawn limits (Only Natural Spawns impact spawn limits for more natural spawns)"); + } + } + } + - public boolean antiXray; - public EngineMode engineMode; - public int maxChunkSectionIndex; diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index e23875ae07c23fed1161ea070e63bbc3a30168a0..0fb69f9194078e5e05e36ed909eb48424b6465b4 100644 +index 30ba1e3cb75d994770b006b9dfd6669000a9c1a4..e20a645e28a2e503c02b2bd89424e95506a2e6df 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -79,6 +79,13 @@ public final class NaturalSpawner { +@@ -85,6 +85,13 @@ public final class NaturalSpawner { MobCategory enumcreaturetype = entity.getType().getCategory(); if (enumcreaturetype != MobCategory.MISC) { @@ -53,5 +52,5 @@ index e23875ae07c23fed1161ea070e63bbc3a30168a0..0fb69f9194078e5e05e36ed909eb4842 + } + // Paper end BlockPos blockposition = entity.blockPosition(); - long j = ChunkPos.asLong(blockposition.getX() >> 4, blockposition.getZ() >> 4); + long j = ChunkPos.asLong(SectionPos.blockToSectionCoord(blockposition.getX()), SectionPos.blockToSectionCoord(blockposition.getZ())); diff --git a/patches/server-remapped/0366-Configurable-projectile-relative-velocity.patch b/patches/server/0333-Configurable-projectile-relative-velocity.patch similarity index 85% rename from patches/server-remapped/0366-Configurable-projectile-relative-velocity.patch rename to patches/server/0333-Configurable-projectile-relative-velocity.patch index 111827bdd8..48d891fe8a 100644 --- a/patches/server-remapped/0366-Configurable-projectile-relative-velocity.patch +++ b/patches/server/0333-Configurable-projectile-relative-velocity.patch @@ -25,11 +25,11 @@ P3) Solutions for 1) and especially 2) might not be future-proof, while this server-internal fix makes this change future-proof. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 384cb363eed794551bee6b0ec11ba1be92a3d7ac..1ee2cced100626e48eb36ee14f84b9257c79a2f8 100644 +index baf33659b021c89cbd02560cbfd9b0ddf205f0e2..4c177a383b277debe8a7c02a70d029d862e6b048 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -507,4 +507,9 @@ public class PaperWorldConfig { - Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); +@@ -411,5 +411,10 @@ public class PaperWorldConfig { + log("Using improved mob spawn limits (Only Natural Spawns impact spawn limits for more natural spawns)"); } } + @@ -38,11 +38,12 @@ index 384cb363eed794551bee6b0ec11ba1be92a3d7ac..1ee2cced100626e48eb36ee14f84b925 + disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); + } } + diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index d385fb6eee5000951c350b6ced5669dc3dcce725..ca3d936433cd47caa4e0335e41246b1c4ce0eb99 100644 +index 7311923d36ee872b4331d84f80709bb6cee61086..69f439851fe1ff07d827eaed274940a5783d5f6c 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -129,7 +129,7 @@ public abstract class Projectile extends Entity { +@@ -161,7 +161,7 @@ public abstract class Projectile extends Entity { this.shoot((double) f5, (double) f6, (double) f7, modifierZ, modifierXYZ); Vec3 vec3d = user.getDeltaMovement(); diff --git a/patches/server-remapped/0368-offset-item-frame-ticking.patch b/patches/server/0334-offset-item-frame-ticking.patch similarity index 90% rename from patches/server-remapped/0368-offset-item-frame-ticking.patch rename to patches/server/0334-offset-item-frame-ticking.patch index 32966f397f..5c65f244d8 100644 --- a/patches/server-remapped/0368-offset-item-frame-ticking.patch +++ b/patches/server/0334-offset-item-frame-ticking.patch @@ -5,7 +5,7 @@ Subject: [PATCH] offset item frame ticking diff --git a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java -index e0bf8c6c838b18a0c55b6f3317033e892b631f5c..3277a56bcf3831f8d3c9fa9168c608b369eed7e4 100644 +index acea1c03afb5b3e522edb072fd1c3f9b5c3edccc..ca9decf85dd1af0baf0d34a48aa67cbb9f4eb586 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java +++ b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java @@ -35,7 +35,7 @@ public abstract class HangingEntity extends Entity { diff --git a/patches/server-remapped/0374-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/patches/server/0335-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch similarity index 85% rename from patches/server-remapped/0374-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch rename to patches/server/0335-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch index eab9bd3397..eb3a0b6db9 100644 --- a/patches/server-remapped/0374-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch +++ b/patches/server/0335-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch @@ -7,13 +7,13 @@ If the Bukkit generator already has a spawn, use it immediately instead of spending time generating one that we won't use diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 643d75b999c3da006eaaab11f4acd77e807683d4..753e6f609189c589514739bea80007bace3c89d2 100644 +index 40e48c3f1199b127066732e3c8a6d40c232215b2..f00839eab02277bf10b742c88fadc4aa9e89e7e0 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -628,12 +628,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { @@ -24,7 +24,7 @@ index 643d75b999c3da006eaaab11f4acd77e807683d4..753e6f609189c589514739bea80007ba // CraftBukkit start if (world.generator != null) { Random rand = new Random(world.getSeed()); -@@ -649,6 +644,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop Date: Sun, 13 Jun 2021 18:25:59 +0200 Subject: [PATCH 079/226] Fix recursive connection call causing StackOverflowException This was probably caused by the rename sendPacket->send and dispatchPacket->sendPacket --- ...ize-Network-Manager-and-add-advanced-packet-sup.patch | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/patches/server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch index a50c8d9c54..4a73f0aa96 100644 --- a/patches/server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch +++ b/patches/server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch @@ -28,7 +28,7 @@ and then catch exceptions and close if they fire. Part of this commit was authored by: Spottedleaf diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 9f0537799a3cae43fb120056b8fe805a4883cc4d..5897bdb4d1372fa3d7bdc482d02f0a54d8767bda 100644 +index 9f0537799a3cae43fb120056b8fe805a4883cc4d..7607bf75968cc32d616e2b44e89901b3681b1131 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java @@ -87,6 +87,10 @@ public class Connection extends SimpleChannelInboundHandler> { @@ -106,9 +106,6 @@ index 9f0537799a3cae43fb120056b8fe805a4883cc4d..5897bdb4d1372fa3d7bdc482d02f0a54 public void send(Packet packet, @Nullable GenericFutureListener> callback) { - if (this.isConnected()) { - this.flushQueue(); -- this.sendPacket(packet, callback); -- } else { -- this.queue.add(new Connection.PacketHolder(packet, callback)); + // Paper start - handle oversized packets better + boolean connected = this.isConnected(); + if (!connected && !preparing) { @@ -119,7 +116,9 @@ index 9f0537799a3cae43fb120056b8fe805a4883cc4d..5897bdb4d1372fa3d7bdc482d02f0a54 + net.minecraft.server.MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() && + (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) + ))) { -+ this.send(packet, callback); + this.sendPacket(packet, callback); +- } else { +- this.queue.add(new Connection.PacketHolder(packet, callback)); + return; } + // write the packets to the queue, then flush - antixray hooks there already From 123a41d1325e6361e547af7c29327fa319e06fb3 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Sun, 13 Jun 2021 20:34:14 +0200 Subject: [PATCH 080/226] adjust material set tag sizes MC added a buuuunch of stuff --- patches/api/0155-Add-Material-Tags.patch | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/patches/api/0155-Add-Material-Tags.patch b/patches/api/0155-Add-Material-Tags.patch index 895bee224a..5f99eea69c 100644 --- a/patches/api/0155-Add-Material-Tags.patch +++ b/patches/api/0155-Add-Material-Tags.patch @@ -113,7 +113,7 @@ index 0000000000000000000000000000000000000000..a02a02aa0c87e0f0ed9e509e4dcab015 +} diff --git a/src/main/java/com/destroystokyo/paper/MaterialTags.java b/src/main/java/com/destroystokyo/paper/MaterialTags.java new file mode 100644 -index 0000000000000000000000000000000000000000..2b5a61a8afa8f73006676cdcb8a34640b43de1c3 +index 0000000000000000000000000000000000000000..e8e6b2156b72bc5c115ac522a36efeeff8acd557 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/MaterialTags.java @@ -0,0 +1,558 @@ @@ -173,7 +173,7 @@ index 0000000000000000000000000000000000000000..2b5a61a8afa8f73006676cdcb8a34640 + */ + public static final MaterialSetTag BUCKETS = new MaterialSetTag(keyFor("buckets")) + .endsWith("BUCKET") -+ .ensureSize("BUCKETS", 8); ++ .ensureSize("BUCKETS", 10); + + /** + * Covers coal and charcoal. @@ -254,7 +254,7 @@ index 0000000000000000000000000000000000000000..2b5a61a8afa8f73006676cdcb8a34640 + public static final MaterialSetTag GLASS = new MaterialSetTag(keyFor("glass")) + .endsWith("_GLASS") + .add(Material.GLASS) -+ .ensureSize("GLASS", 17); ++ .ensureSize("GLASS", 18); + + /** + * Covers the non-colored glass panes and stained glass panes (panes only). @@ -305,7 +305,7 @@ index 0000000000000000000000000000000000000000..2b5a61a8afa8f73006676cdcb8a34640 + */ + public static final MaterialSetTag INFESTED_BLOCKS = new MaterialSetTag(keyFor("infested_blocks")) + .startsWith("INFESTED_") -+ .ensureSize("INFESTED_BLOCKS", 6); ++ .ensureSize("INFESTED_BLOCKS", 7); + + /** + * Covers the variants of mushroom blocks. @@ -333,7 +333,7 @@ index 0000000000000000000000000000000000000000..2b5a61a8afa8f73006676cdcb8a34640 + public static final MaterialSetTag ORES = new MaterialSetTag(keyFor("ores")) + .add(Material.ANCIENT_DEBRIS) + .endsWith("_ORE") -+ .ensureSize("ORES", 10); ++ .ensureSize("ORES", 19); + + /** + * Covers all piston typed items and blocks including the piston head and moving piston. @@ -433,7 +433,7 @@ index 0000000000000000000000000000000000000000..2b5a61a8afa8f73006676cdcb8a34640 + */ + public static final MaterialSetTag SPAWN_EGGS = new MaterialSetTag(keyFor("spawn_eggs")) + .endsWith("_SPAWN_EGG") -+ .ensureSize("SPAWN_EGGS", 64); ++ .ensureSize("SPAWN_EGGS", 67); + + /** + * Covers all colors of stained glass. From 27a8d6da9a74a6b6b26568ba768538f16fa5f584 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sun, 13 Jun 2021 12:29:58 -0700 Subject: [PATCH 081/226] more patches --- ...184-Expose-the-internal-current-tick.patch | 4 +- ...layerDeathEvent-shouldDropExperience.patch | 2 +- ...-Add-effect-to-block-break-naturally.patch | 2 +- .../0187-World-view-distance-api.patch} | 2 +- ...ce-improvement-for-Chunk.getEntities.patch | 2 + .../0378-Generator-Settings.patch | 89 --- ...nk-loads-when-villagers-try-to-find-.patch | 20 - ...rializing-mismatching-chunk-coordina.patch | 62 --- patches/server/0338-Generator-Settings.patch | 165 ++++++ .../0339-Fix-MC-161754.patch} | 10 +- ...anging-entities-that-are-not-ItemFr.patch} | 6 +- ...41-Expose-the-internal-current-tick.patch} | 4 +- ...sneak-when-changing-worlds-MC-10657.patch} | 10 +- ...-option-to-disable-pillager-patrols.patch} | 7 +- ...r-when-player-hand-set-to-empty-typ.patch} | 16 +- ...nk-loads-when-villagers-try-to-find-.patch | 20 + ...656-Fix-Follow-Range-Initial-Target.patch} | 38 +- .../0347-Optimize-Hoppers.patch} | 373 +++++-------- ...ayerDeathEvent-shouldDropExperience.patch} | 6 +- ...ading-chunks-checking-hive-position.patch} | 4 +- ...hunks-from-Hoppers-and-other-things.patch} | 22 +- ...rializing-mismatching-chunk-coordina.patch | 54 ++ ...imise-IEntityAccess-getPlayerByUUID.patch} | 28 +- ...353-Fix-items-not-falling-correctly.patch} | 8 +- .../0354-Lag-compensate-eating.patch} | 46 +- ...ize-call-to-getFluid-for-explosions.patch} | 8 +- ...-in-stack-not-having-effects-when-d.patch} | 4 +- ...Add-effect-to-block-break-naturally.patch} | 8 +- .../0358-Entity-Activation-Range-2.0.patch} | 514 +++++++----------- .../0359-Increase-Light-Queue-Size.patch} | 13 +- .../0360-Fix-Light-Command.patch} | 97 ++-- ...o-Tick-view-distance-implementation.patch} | 349 ++++-------- 32 files changed, 825 insertions(+), 1168 deletions(-) rename patches/{api-unmapped => api}/0184-Expose-the-internal-current-tick.patch (87%) rename patches/{api-unmapped => api}/0185-PlayerDeathEvent-shouldDropExperience.patch (97%) rename patches/{api-unmapped => api}/0186-Add-effect-to-block-break-naturally.patch (91%) rename patches/{api-unmapped/0201-World-view-distance-api.patch => api/0187-World-view-distance-api.patch} (94%) rename patches/{server-remapped => removed/1.17}/0380-Performance-improvement-for-Chunk.getEntities.patch (96%) delete mode 100644 patches/server-remapped/0378-Generator-Settings.patch delete mode 100644 patches/server-remapped/0388-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch delete mode 100644 patches/server-remapped/0394-Guard-against-serializing-mismatching-chunk-coordina.patch create mode 100644 patches/server/0338-Generator-Settings.patch rename patches/{server-remapped/0379-Fix-MC-161754.patch => server/0339-Fix-MC-161754.patch} (54%) rename patches/{server-remapped/0381-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch => server/0340-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch} (85%) rename patches/{server-remapped/0382-Expose-the-internal-current-tick.patch => server/0341-Expose-the-internal-current-tick.patch} (81%) rename patches/{server-remapped/0383-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch => server/0342-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch} (78%) rename patches/{server-remapped/0384-Add-option-to-disable-pillager-patrols.patch => server/0343-Add-option-to-disable-pillager-patrols.patch} (86%) rename patches/{server-remapped/0385-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch => server/0344-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch} (52%) create mode 100644 patches/server/0345-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch rename patches/{server-remapped/0389-MC-145656-Fix-Follow-Range-Initial-Target.patch => server/0346-MC-145656-Fix-Follow-Range-Initial-Target.patch} (62%) rename patches/{server-remapped/0390-Optimize-Hoppers.patch => server/0347-Optimize-Hoppers.patch} (51%) rename patches/{server-remapped/0391-PlayerDeathEvent-shouldDropExperience.patch => server/0348-PlayerDeathEvent-shouldDropExperience.patch} (79%) rename patches/{server-remapped/0392-Prevent-bees-loading-chunks-checking-hive-position.patch => server/0349-Prevent-bees-loading-chunks-checking-hive-position.patch} (85%) rename patches/{server-remapped/0393-Don-t-load-Chunks-from-Hoppers-and-other-things.patch => server/0350-Don-t-load-Chunks-from-Hoppers-and-other-things.patch} (58%) create mode 100644 patches/server/0351-Guard-against-serializing-mismatching-chunk-coordina.patch rename patches/{server-remapped/0395-Optimise-IEntityAccess-getPlayerByUUID.patch => server/0352-Optimise-IEntityAccess-getPlayerByUUID.patch} (51%) rename patches/{server-remapped/0396-Fix-items-not-falling-correctly.patch => server/0353-Fix-items-not-falling-correctly.patch} (66%) rename patches/{server-remapped/0397-Lag-compensate-eating.patch => server/0354-Lag-compensate-eating.patch} (57%) rename patches/{server-remapped/0398-Optimize-call-to-getFluid-for-explosions.patch => server/0355-Optimize-call-to-getFluid-for-explosions.patch} (72%) rename patches/{server-remapped/0399-Fix-last-firework-in-stack-not-having-effects-when-d.patch => server/0356-Fix-last-firework-in-stack-not-having-effects-when-d.patch} (90%) rename patches/{server-remapped/0400-Add-effect-to-block-break-naturally.patch => server/0357-Add-effect-to-block-break-naturally.patch} (81%) rename patches/{server-remapped/0402-Entity-Activation-Range-2.0.patch => server/0358-Entity-Activation-Range-2.0.patch} (58%) rename patches/{server-remapped/0429-Increase-Light-Queue-Size.patch => server/0359-Increase-Light-Queue-Size.patch} (78%) rename patches/{server-remapped/0472-Fix-Light-Command.patch => server/0360-Fix-Light-Command.patch} (68%) rename patches/{server-remapped/0470-No-Tick-view-distance-implementation.patch => server/0361-No-Tick-view-distance-implementation.patch} (68%) diff --git a/patches/api-unmapped/0184-Expose-the-internal-current-tick.patch b/patches/api/0184-Expose-the-internal-current-tick.patch similarity index 87% rename from patches/api-unmapped/0184-Expose-the-internal-current-tick.patch rename to patches/api/0184-Expose-the-internal-current-tick.patch index b127872bfe..b83fdf74f7 100644 --- a/patches/api-unmapped/0184-Expose-the-internal-current-tick.patch +++ b/patches/api/0184-Expose-the-internal-current-tick.patch @@ -5,7 +5,7 @@ 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 e3304fcc8c4fd176abd3fb7d4b47e5ccb7bdd37f..49bf621a2c0e5e9641b334a42b2769944c991d5d 100644 +index 7dd3fc9301de9a88313179088f6b5ce4c1362f06..02f91b446697b1c637fda3b65b48ec8cf38de66d 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1835,6 +1835,10 @@ public final class Bukkit { @@ -20,7 +20,7 @@ index e3304fcc8c4fd176abd3fb7d4b47e5ccb7bdd37f..49bf621a2c0e5e9641b334a42b276994 @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 989a732e5ef2053deede245d65fbf99cdf117c5e..e448ae78304974f7664b7ef18568a547833ece9f 100644 +index 139a96d01e3a7e2e298592ce5d485dfc21c9c6c7..b038a82ffc298abb5129b6ec20538df5d0b6f595 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1609,5 +1609,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api-unmapped/0185-PlayerDeathEvent-shouldDropExperience.patch b/patches/api/0185-PlayerDeathEvent-shouldDropExperience.patch similarity index 97% rename from patches/api-unmapped/0185-PlayerDeathEvent-shouldDropExperience.patch rename to patches/api/0185-PlayerDeathEvent-shouldDropExperience.patch index f19bdcd569..cc31e67473 100644 --- a/patches/api-unmapped/0185-PlayerDeathEvent-shouldDropExperience.patch +++ b/patches/api/0185-PlayerDeathEvent-shouldDropExperience.patch @@ -5,7 +5,7 @@ Subject: [PATCH] PlayerDeathEvent#shouldDropExperience diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -index 7b78afe9281681cb9262fa044c1069a6121358eb..46917615ac4734bf5fa4ddea497132466eb5cc35 100644 +index 8c46eaebf004823c1c31eb2c7304181487cb1332..3d45d2e41aad6992b40a22030f2a63baeec78757 100644 --- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java @@ -1,6 +1,8 @@ diff --git a/patches/api-unmapped/0186-Add-effect-to-block-break-naturally.patch b/patches/api/0186-Add-effect-to-block-break-naturally.patch similarity index 91% rename from patches/api-unmapped/0186-Add-effect-to-block-break-naturally.patch rename to patches/api/0186-Add-effect-to-block-break-naturally.patch index 7c52aaa446..5ccd8c2548 100644 --- a/patches/api-unmapped/0186-Add-effect-to-block-break-naturally.patch +++ b/patches/api/0186-Add-effect-to-block-break-naturally.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add effect to block break naturally diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index d4ba9c2b858204825d47fd6e91dab8c003df085a..f8c599718143fe638de422fd4625f353ee6c54ae 100644 +index 5e2aa4fb8cf8130df21d3172dd94e857317f7653..e1cc36fbe808973227c0e8ca7166453235c90279 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java @@ -469,6 +469,18 @@ public interface Block extends Metadatable { diff --git a/patches/api-unmapped/0201-World-view-distance-api.patch b/patches/api/0187-World-view-distance-api.patch similarity index 94% rename from patches/api-unmapped/0201-World-view-distance-api.patch rename to patches/api/0187-World-view-distance-api.patch index 17a9a94f12..64845bcaf8 100644 --- a/patches/api-unmapped/0201-World-view-distance-api.patch +++ b/patches/api/0187-World-view-distance-api.patch @@ -5,7 +5,7 @@ Subject: [PATCH] World view distance api diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 7bf85151efddcbd561afb0fb2d423aa97ac176c1..61dfb057d94d89477d11b9e8d4be7c16032e25a9 100644 +index 6fe2875f95bb600606d66e2f7113d325d10a9b9c..cd96c851d00185e7ee3ec6682b166fc1d06b6a73 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -3447,6 +3447,34 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad diff --git a/patches/server-remapped/0380-Performance-improvement-for-Chunk.getEntities.patch b/patches/removed/1.17/0380-Performance-improvement-for-Chunk.getEntities.patch similarity index 96% rename from patches/server-remapped/0380-Performance-improvement-for-Chunk.getEntities.patch rename to patches/removed/1.17/0380-Performance-improvement-for-Chunk.getEntities.patch index 439bca032a..508f96a2bd 100644 --- a/patches/server-remapped/0380-Performance-improvement-for-Chunk.getEntities.patch +++ b/patches/removed/1.17/0380-Performance-improvement-for-Chunk.getEntities.patch @@ -9,6 +9,8 @@ extra array with List.toArray() with is a costly and unneccessary operation. This patch will reduce the load of plugins which for example implement custom moblimits and depend on Chunk.getEntities(). +1.17: needs to be reworked, entities not in chunk anymore? + diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java index 74bad15034d9d55fb70931f38868f812160c6305..0f45f4b2486e910d11fd94b260bcd68e49eae31e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java diff --git a/patches/server-remapped/0378-Generator-Settings.patch b/patches/server-remapped/0378-Generator-Settings.patch deleted file mode 100644 index fe0b780b55..0000000000 --- a/patches/server-remapped/0378-Generator-Settings.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 02:17:54 -0600 -Subject: [PATCH] Generator Settings - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6aec502eb529d4090306e12e837117cde7e114eb..290e49cf0077909ad7ab8127c01ef93cf7b70b51 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -570,4 +570,9 @@ public class PaperWorldConfig { - private void perPlayerMobSpawns() { - perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); - } -+ -+ public boolean generateFlatBedrock; -+ private void generatorSettings() { -+ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -index e6303cdb433ee2b6782e2a0bd6b03e4f6ecb18ba..36c7ab3919d8818af96d50170aeb431051c5aabf 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -@@ -25,6 +25,18 @@ import org.apache.logging.log4j.LogManager; - - public interface ChunkAccess extends BlockGetter, FeatureAccess { - -+ // Paper start -+ default boolean generateFlatBedrock() { -+ if (this instanceof ProtoChunk) { -+ return ((ProtoChunk)this).world.paperConfig.generateFlatBedrock; -+ } else if (this instanceof LevelChunk) { -+ return ((LevelChunk)this).world.paperConfig.generateFlatBedrock; -+ } else { -+ return false; -+ } -+ } -+ // Paper end -+ - BlockState getType(final int x, final int y, final int z); // Paper - @Nullable - BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 87fd585141ad9818fca0b697cb4c87248fe7ce11..5a94464b9628b74eefa1c1d8514cf267f4c8a11d 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -64,7 +64,7 @@ public class ProtoChunk implements ChunkAccess { - private long inhabitedTime; - private final Map carvingMasks; - private volatile boolean isLightCorrect; -- private final Level world; // Paper - Anti-Xray - Add world -+ final Level world; // Paper - Anti-Xray - Add world // Paper - private -> default - - // Paper start - Anti-Xray - Add world - @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { this(pos, upgradeData, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -index b38a9c87fc996bd3107c38f6446a687fd093c617..04adec255e4650ead8d80bee32a681c98686fb95 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -@@ -408,8 +408,8 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - int i = chunk.getPos().getMinBlockX(); - int j = chunk.getPos().getMinBlockZ(); - NoiseGeneratorSettings generatorsettingbase = (NoiseGeneratorSettings) this.settings.get(); -- int k = generatorsettingbase.getBedrockFloorPosition(); -- int l = this.height - 1 - generatorsettingbase.getBedrockRoofPosition(); -+ int k = generatorsettingbase.getBedrockFloorPosition(); final int floorHeight = k; // Paper -+ int l = this.height - 1 - generatorsettingbase.getBedrockRoofPosition(); final int roofHeight = l; // Paper - boolean flag = true; - boolean flag1 = l + 4 >= 0 && l < this.height; - boolean flag2 = k + 4 >= 0 && k < this.height; -@@ -423,7 +423,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - - if (flag1) { - for (i1 = 0; i1 < 5; ++i1) { -- if (i1 <= random.nextInt(5)) { -+ if (i1 <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof - chunk.setBlockState(blockposition_mutableblockposition.set(blockposition.getX(), l - i1, blockposition.getZ()), Blocks.BEDROCK.defaultBlockState(), false); - } - } -@@ -431,7 +431,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - - if (flag2) { - for (i1 = 4; i1 >= 0; --i1) { -- if (i1 <= random.nextInt(5)) { -+ if (i1 <= (chunk.generateFlatBedrock() ? floorHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor - chunk.setBlockState(blockposition_mutableblockposition.set(blockposition.getX(), k + i1, blockposition.getZ()), Blocks.BEDROCK.defaultBlockState(), false); - } - } diff --git a/patches/server-remapped/0388-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/patches/server-remapped/0388-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch deleted file mode 100644 index 32b045db49..0000000000 --- a/patches/server-remapped/0388-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Callahan -Date: Mon, 13 Jan 2020 23:47:28 -0600 -Subject: [PATCH] Prevent sync chunk loads when villagers try to find beds - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java -index 5151c794985a135d3bd794bbafdf524ab9f670de..9a582fb4b96b2d0406cc86e473e8bf8c4e488e37 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java -@@ -46,7 +46,8 @@ public class SleepInBed extends Behavior { - } - } - -- BlockState iblockdata = world.getBlockState(globalpos.getBlockPosition()); -+ BlockState iblockdata = world.getTypeIfLoaded(globalpos.getBlockPosition()); // Paper -+ if (iblockdata == null) { return false; } // Paper - - return globalpos.getBlockPosition().a((Position) entity.position(), 2.0D) && iblockdata.getBlock().is((Tag) BlockTags.BEDS) && !(Boolean) iblockdata.getValue(BedBlock.OCCUPIED); - } diff --git a/patches/server-remapped/0394-Guard-against-serializing-mismatching-chunk-coordina.patch b/patches/server-remapped/0394-Guard-against-serializing-mismatching-chunk-coordina.patch deleted file mode 100644 index 37dc33fc4a..0000000000 --- a/patches/server-remapped/0394-Guard-against-serializing-mismatching-chunk-coordina.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 27 Dec 2019 09:42:26 -0800 -Subject: [PATCH] Guard against serializing mismatching chunk coordinate - -Should help if something dumb happens - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index be67dc16bf70e4517efd213ca9002f116f60b57c..6c28a611b9b79c3322ab07883972c07b3bfc3073 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -67,6 +67,13 @@ public class ChunkSerializer { - - private static final Logger LOGGER = LogManager.getLogger(); - -+ // Paper start - guard against serializing mismatching coordinates -+ // TODO Note: This needs to be re-checked each update -+ public static ChunkPos getChunkCoordinate(CompoundTag chunkData) { -+ CompoundTag levelData = chunkData.getCompound("Level"); -+ return new ChunkPos(levelData.getInt("xPos"), levelData.getInt("zPos")); -+ } -+ // Paper end - // Paper start - public static final class InProgressChunkHolder { - -@@ -92,8 +99,8 @@ public class ChunkSerializer { - // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); - BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); -- CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); -- ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); -+ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate -+ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate - - if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { - ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -index 684442b7175e30b6d4cafb2f7d2d4c10517cc33d..1af804c5c6fb2b20ea3f020610763c1d7dcee110 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -@@ -13,6 +13,7 @@ import net.minecraft.SharedConstants; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.NbtUtils; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.datafix.DataFixTypes; -@@ -119,6 +120,13 @@ public class ChunkStorage implements AutoCloseable { - - public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER - public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) -+ // Paper start -+ if (!chunkcoordintpair.equals(ChunkSerializer.getChunkCoordinate(nbttagcompound))) { -+ String world = (this instanceof ChunkMap) ? ((ChunkMap)this).level.getWorld().getName() : null; -+ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkcoordintpair.toString() -+ + " but compound says coordinate is " + ChunkSerializer.getChunkCoordinate(nbttagcompound).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); -+ } -+ // Paper end - this.regionFileCache.write(chunkcoordintpair, nbttagcompound); - if (this.legacyStructureHandler != null) { - synchronized (this.persistentDataLock) { // Paper - Async chunk loading diff --git a/patches/server/0338-Generator-Settings.patch b/patches/server/0338-Generator-Settings.patch new file mode 100644 index 0000000000..590c2cd9f0 --- /dev/null +++ b/patches/server/0338-Generator-Settings.patch @@ -0,0 +1,165 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 2 Mar 2016 02:17:54 -0600 +Subject: [PATCH] Generator Settings + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 4c177a383b277debe8a7c02a70d029d862e6b048..0c336a794d21d5084b9ea39308379b2ffb4a4330 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -416,5 +416,10 @@ public class PaperWorldConfig { + private void disableRelativeProjectileVelocity() { + disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); + } ++ ++ public boolean generateFlatBedrock; ++ private void generatorSettings() { ++ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); ++ } + } + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index dd7de2c3db10d9d606d47c52eba40e71034fc11a..5473b22d21ea981f245f4826c4d47295890f88ef 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -678,7 +678,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + this.markPositionReplaceable(pos); +- return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level)); ++ return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level, this.level)); // Paper - add level + // Paper start - Async chunk io + }; + CompletableFuture> ret = new CompletableFuture<>(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index 974ab04b08bbd3c27a394b37c1af112be5f28f43..c0075d226331f32e470dae5bf1ce8d79e8b263dc 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -29,6 +29,18 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { + return GameEventDispatcher.NOOP; + } + ++ // Paper start ++ default boolean generateFlatBedrock() { ++ if (this instanceof ProtoChunk) { ++ return ((ProtoChunk)this).level.paperConfig.generateFlatBedrock; ++ } else if (this instanceof LevelChunk) { ++ return ((LevelChunk)this).level.paperConfig.generateFlatBedrock; ++ } else { ++ return false; ++ } ++ } ++ // Paper end ++ + BlockState getType(final int x, final int y, final int z); // Paper + @Nullable + BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +index 452b513e8b89d865a396066adaf4feb1140e1c62..8245c5834ec69beb8e3b95fb3900601009a9273f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +@@ -25,7 +25,7 @@ public class ImposterProtoChunk extends ProtoChunk { + private final LevelChunk wrapped; + + public ImposterProtoChunk(LevelChunk wrapped) { +- super(wrapped.getPos(), UpgradeData.EMPTY, wrapped); ++ super(wrapped.getPos(), UpgradeData.EMPTY, wrapped, wrapped.level); // Paper - add level + this.wrapped = wrapped; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index da36e6d40ad3e8b7cdbe09ef911d1e5b8c28670f..245998e2cea32cf15ee2659639c647f449704ec0 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -63,16 +63,24 @@ public class ProtoChunk implements ChunkAccess { + private long inhabitedTime; + private final Map carvingMasks = new Object2ObjectArrayMap<>(); + private volatile boolean isLightCorrect; ++ final net.minecraft.world.level.Level level; // Paper - Add level + +- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) { ++ // Paper start - add level ++ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) { this(pos, upgradeData, world, null); } ++ public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world, net.minecraft.server.level.ServerLevel level) { ++ // Paper end + this(pos, upgradeData, (LevelChunkSection[])null, new ProtoTickList<>((block) -> { + return block == null || block.defaultBlockState().isAir(); + }, pos, world), new ProtoTickList<>((fluid) -> { + return fluid == null || fluid == Fluids.EMPTY; +- }, pos, world), world); ++ }, pos, world), world, level); // Paper - add level + } + +- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler, LevelHeightAccessor world) { ++ // Paper start - add level ++ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler, LevelHeightAccessor world) { this(pos, upgradeData, levelChunkSections, blockTickScheduler, fluidTickScheduler, world, null); } ++ public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler, LevelHeightAccessor world, net.minecraft.server.level.ServerLevel level) { ++ this.level = level; ++ // Paper end + this.chunkPos = pos; + this.upgradeData = upgradeData; + this.blockTicks = blockTickScheduler; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index fc320450878279a6aa48019fbde35bb183f5f06e..3cb35f2f47ba841915ac2825d30cc4c3274ce3c4 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -210,7 +210,7 @@ public class ChunkSerializer { + // CraftBukkit end + }); + } else { +- ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world); ++ ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world, world); // Paper - add level + + protochunk.setBiomes(biomestorage); + object = protochunk; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +index a0a3cf7655eca5c2b181476b0842d9e8c19dbffd..db0abd275be2df7a4fdeb1d7179bff4d61bab052 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +@@ -270,8 +270,8 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + int j = chunk.getPos().getMinBlockZ(); + NoiseGeneratorSettings noiseGeneratorSettings = this.settings.get(); + int k = noiseGeneratorSettings.noiseSettings().minY(); +- int l = k + noiseGeneratorSettings.getBedrockFloorPosition(); +- int m = this.height - 1 + k - noiseGeneratorSettings.getBedrockRoofPosition(); ++ int l = k + noiseGeneratorSettings.getBedrockFloorPosition(); final int floorHeight = k; // Paper ++ int m = this.height - 1 + k - noiseGeneratorSettings.getBedrockRoofPosition(); final int roofHeight = l; // Paper + int n = 5; + int o = chunk.getMinBuildHeight(); + int p = chunk.getMaxBuildHeight(); +@@ -281,7 +281,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + for(BlockPos blockPos : BlockPos.betweenClosed(i, 0, j, i + 15, 0, j + 15)) { + if (bl) { + for(int q = 0; q < 5; ++q) { +- if (q <= random.nextInt(5)) { ++ if (q <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof + chunk.setBlockState(mutableBlockPos.set(blockPos.getX(), m - q, blockPos.getZ()), Blocks.BEDROCK.defaultBlockState(), false); + } + } +@@ -289,7 +289,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + + if (bl2) { + for(int r = 4; r >= 0; --r) { +- if (r <= random.nextInt(5)) { ++ if (r <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor + chunk.setBlockState(mutableBlockPos.set(blockPos.getX(), l + r, blockPos.getZ()), Blocks.BEDROCK.defaultBlockState(), false); + } + } +@@ -309,14 +309,14 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + if (l <= 0) { + return CompletableFuture.completedFuture(chunk); + } else { +- int m = chunk.getSectionIndex(l * this.cellHeight - 1 + i); ++ int mStart = chunk.getSectionIndex(l * this.cellHeight - 1 + i); // Paper - decompile fix + int n = chunk.getSectionIndex(i); + return CompletableFuture.supplyAsync(() -> { + Set set = Sets.newHashSet(); + + ChunkAccess var16; + try { +- for(int m = m; m >= n; --m) { ++ for(int m = mStart; m >= n; --m) { // Paper - decompile fix + LevelChunkSection levelChunkSection = chunk.getOrCreateSection(m); + levelChunkSection.acquire(); + set.add(levelChunkSection); diff --git a/patches/server-remapped/0379-Fix-MC-161754.patch b/patches/server/0339-Fix-MC-161754.patch similarity index 54% rename from patches/server-remapped/0379-Fix-MC-161754.patch rename to patches/server/0339-Fix-MC-161754.patch index c50817dd4f..5dcb7f8ca0 100644 --- a/patches/server-remapped/0379-Fix-MC-161754.patch +++ b/patches/server/0339-Fix-MC-161754.patch @@ -9,15 +9,15 @@ We can use an entity valid check since this method is invoked for each inventory iteraction (thanks to CB) and on player tick (vanilla). diff --git a/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java b/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java -index 7246b3a84415e303591adb08d81362201deebfce..e0237e821b2c31ba68168fddf1c1a4ebfcf10ca7 100644 +index 9da2f9334ea98ecba328c7b0d022321d6194529b..0d145f075798dde27beef80022cd7c0f582f8253 100644 --- a/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java +++ b/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java -@@ -85,7 +85,7 @@ public class HorseInventoryMenu extends AbstractContainerMenu { +@@ -95,7 +95,7 @@ public class HorseInventoryMenu extends AbstractContainerMenu { @Override public boolean stillValid(Player player) { -- return this.horseContainer.stillValid(player) && this.horse.isAlive() && this.horse.distanceTo((Entity) player) < 8.0F; -+ return this.horseContainer.stillValid(player) && (this.horse.isAlive() && this.horse.valid) && this.horse.distanceTo((Entity) player) < 8.0F; // Paper - Fix MC-161754 +- return !this.horse.hasInventoryChanged(this.horseContainer) && this.horseContainer.stillValid(player) && this.horse.isAlive() && this.horse.distanceTo((Entity) player) < 8.0F; ++ return !this.horse.hasInventoryChanged(this.horseContainer) && this.horseContainer.stillValid(player) && (this.horse.isAlive() && this.horse.valid) && this.horse.distanceTo((Entity) player) < 8.0F; // Paper - Fix MC-161754 } - @Override + private boolean hasChest(AbstractHorse entityhorseabstract) { diff --git a/patches/server-remapped/0381-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/patches/server/0340-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch similarity index 85% rename from patches/server-remapped/0381-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch rename to patches/server/0340-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch index 548deb2cdf..8a4a109b18 100644 --- a/patches/server-remapped/0381-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch +++ b/patches/server/0340-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix spawning of hanging entities that are not ItemFrames and diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 52444619a4bae80a12bf296fbe07fa811adf806e..fb74bdcf4c2935b56e92717cc5a1504fbc853d0a 100644 +index 4841591539fdd5a01f9ded0ee510991602c266a4..f1cbcdb1e409f8544125dde5f24bff5b07cb5082 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1868,7 +1868,12 @@ public class CraftWorld implements World { +@@ -1881,7 +1881,12 @@ public class CraftWorld implements World { height = 9; } @@ -22,4 +22,4 @@ index 52444619a4bae80a12bf296fbe07fa811adf806e..fb74bdcf4c2935b56e92717cc5a1504f + // Paper end final BlockPos pos = new BlockPos(x, y, z); for (BlockFace dir : faces) { - net.minecraft.world.level.block.state.BlockState nmsBlock = world.getBlockState(pos.relative(CraftBlock.blockFaceToNotch(dir))); + net.minecraft.world.level.block.state.BlockState nmsBlock = this.world.getBlockState(pos.relative(CraftBlock.blockFaceToNotch(dir))); diff --git a/patches/server-remapped/0382-Expose-the-internal-current-tick.patch b/patches/server/0341-Expose-the-internal-current-tick.patch similarity index 81% rename from patches/server-remapped/0382-Expose-the-internal-current-tick.patch rename to patches/server/0341-Expose-the-internal-current-tick.patch index 9cf110529d..0382311058 100644 --- a/patches/server-remapped/0382-Expose-the-internal-current-tick.patch +++ b/patches/server/0341-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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 96a3a4d89df858d4e46a36f110dd9ad3a2061433..3c0ba80bbba19f3725013e118cecdbac5612deec 100644 +index 58d7fec472dd8c8d7775eb6d931be29871102054..9730c701b734eb3491bc1fa5d9bb81ddfefc910a 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2363,5 +2363,10 @@ public final class CraftServer implements Server { +@@ -2364,5 +2364,10 @@ public final class CraftServer implements Server { } return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); } diff --git a/patches/server-remapped/0383-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/patches/server/0342-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch similarity index 78% rename from patches/server-remapped/0383-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch rename to patches/server/0342-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch index 169ff964a9..559cc6317a 100644 --- a/patches/server-remapped/0383-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch +++ b/patches/server/0342-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch @@ -5,23 +5,23 @@ Subject: [PATCH] Fix stuck in sneak when changing worlds (MC-10657) diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index b0eed4e18fc183856613c05f378576eb19985c46..2ef273e3b917803f3e2ac3c6a22d92a15b9eb71a 100644 +index 679f1e3ef4c19ab466cf2d06c47b1018aabaa7bf..8da35a7dde494b059e542d049d7ee039deb5833d 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1070,6 +1070,8 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1101,6 +1101,8 @@ public class ServerPlayer extends Player { this.lastSentHealth = -1.0F; this.lastSentFood = -1; -+ setShiftKeyDown(false); // Paper - fix MC-10657 ++ setShiftKeyDown(false); // Paper - fix MC-10657 + // CraftBukkit start PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); this.level.getCraftServer().getPluginManager().callEvent(changeEvent); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index e6eebb8f6f48cc55fc8fb114c959b8fbec4b8472..dfdde9722bc0d83916779014b7718eef2c01b3db 100644 +index 6f9bd5da1504af296e7ee2a69d8afdd3bc4cfd5e..bcc946d2747443c34ee8ac2485a5ab41773c93af 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -842,6 +842,8 @@ public abstract class PlayerList { +@@ -820,6 +820,8 @@ public abstract class PlayerList { entityplayer.connection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobEffect)); } diff --git a/patches/server-remapped/0384-Add-option-to-disable-pillager-patrols.patch b/patches/server/0343-Add-option-to-disable-pillager-patrols.patch similarity index 86% rename from patches/server-remapped/0384-Add-option-to-disable-pillager-patrols.patch rename to patches/server/0343-Add-option-to-disable-pillager-patrols.patch index 2e772d88a3..12f2a06084 100644 --- a/patches/server-remapped/0384-Add-option-to-disable-pillager-patrols.patch +++ b/patches/server/0343-Add-option-to-disable-pillager-patrols.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to disable pillager patrols diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 290e49cf0077909ad7ab8127c01ef93cf7b70b51..e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5 100644 +index 0c336a794d21d5084b9ea39308379b2ffb4a4330..f46731897f4234b27dafa49a5f652535a99d2992 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -575,4 +575,9 @@ public class PaperWorldConfig { +@@ -421,5 +421,10 @@ public class PaperWorldConfig { private void generatorSettings() { generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); } @@ -18,8 +18,9 @@ index 290e49cf0077909ad7ab8127c01ef93cf7b70b51..e726b6213cf2e8f5b326f05c0438b8f1 + disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); + } } + diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java -index caadd1a0fa6c4c446f84629088890a09e29622d9..48efe133d294bb1b17e8ac8b44eea8a29f15845f 100644 +index e0a376617f6b6232591942da0bc9d7b1ee58c2e7..744b58d59a5f34ed3bd6f2d4a0f876acfa6a7135 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java @@ -26,6 +26,7 @@ public class PatrolSpawner implements CustomSpawner { diff --git a/patches/server-remapped/0385-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/patches/server/0344-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch similarity index 52% rename from patches/server-remapped/0385-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch rename to patches/server/0344-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch index 3d4d87429f..fcb6434230 100644 --- a/patches/server-remapped/0385-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch +++ b/patches/server/0344-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch @@ -7,10 +7,10 @@ Fixes an AssertionError when setting the player's item in hand to null or a new Fixes GH-2718 diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index e45690b6197335ed1c07fa04c39b311b401724d7..2b79413bb8a592a7b7093e11d3a0cce895286c8f 100644 +index 377e224acb06bfd5f769b5f75b7f52129394b494..9240064a17e7ac2492fe157b759d1f724105cd0e 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1706,6 +1706,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1741,6 +1741,10 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 return; } @@ -21,15 +21,3 @@ index e45690b6197335ed1c07fa04c39b311b401724d7..2b79413bb8a592a7b7093e11d3a0cce8 InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); if (enuminteractionresult.shouldSwing()) { -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index f8917123547615dd624e3e428ec1bf6450c7b7d8..b49d4772932a58852b3195f5f56ff93dbcabf766 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2153,6 +2153,7 @@ public abstract class LivingEntity extends Entity { - return predicate.test(this.getMainHandItem().getItem()) || predicate.test(this.getOffhandItem().getItem()); - } - -+ public final ItemStack getItemInHand(InteractionHand enumhand) { return this.getItemInHand(enumhand); } // Paper - OBFHELPER - public ItemStack getItemInHand(InteractionHand hand) { - if (hand == InteractionHand.MAIN_HAND) { - return this.getItemBySlot(EquipmentSlot.MAINHAND); diff --git a/patches/server/0345-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/patches/server/0345-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch new file mode 100644 index 0000000000..7409939936 --- /dev/null +++ b/patches/server/0345-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Callahan +Date: Mon, 13 Jan 2020 23:47:28 -0600 +Subject: [PATCH] Prevent sync chunk loads when villagers try to find beds + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java +index 455774a211c679367c6e7845a11159ad84ca07e2..673b6e60731d440cc02b1e86bfba50e6ebeb0da9 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java +@@ -41,7 +41,8 @@ public class SleepInBed extends Behavior { + } + } + +- BlockState blockState = world.getBlockState(globalPos.pos()); ++ BlockState blockState = world.getTypeIfLoaded(globalPos.pos()); // Paper ++ if (blockState == null) { return false; } // Paper + return globalPos.pos().closerThan(entity.position(), 2.0D) && blockState.is(BlockTags.BEDS) && !blockState.getValue(BedBlock.OCCUPIED); + } + } diff --git a/patches/server-remapped/0389-MC-145656-Fix-Follow-Range-Initial-Target.patch b/patches/server/0346-MC-145656-Fix-Follow-Range-Initial-Target.patch similarity index 62% rename from patches/server-remapped/0389-MC-145656-Fix-Follow-Range-Initial-Target.patch rename to patches/server/0346-MC-145656-Fix-Follow-Range-Initial-Target.patch index 27d343fa11..e7218a0ce8 100644 --- a/patches/server-remapped/0389-MC-145656-Fix-Follow-Range-Initial-Target.patch +++ b/patches/server/0346-MC-145656-Fix-Follow-Range-Initial-Target.patch @@ -5,10 +5,10 @@ Subject: [PATCH] MC-145656 Fix Follow Range Initial Target diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5..edda2121f8c1046478beaa77030ebb36d403b334 100644 +index f46731897f4234b27dafa49a5f652535a99d2992..8190c30346c0fd2d86fb7cbcfc7ce17333e05146 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -580,4 +580,9 @@ public class PaperWorldConfig { +@@ -426,5 +426,10 @@ public class PaperWorldConfig { private void pillagerSettings() { disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); } @@ -18,41 +18,33 @@ index e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5..edda2121f8c1046478beaa77030ebb36 + entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); + } } + diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java -index 7bba2ac71a3cd34a06ec865a3c1828b10decd644..93845edab0e1b0e2ad300cad051b0182cadd46e5 100644 +index 6cbd2fc4a7041f957966e5b09616e70aae63c0d4..b5bbcb9fa6de4c919e4d4fabbab483054d81574e 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java @@ -32,6 +32,7 @@ public class NearestAttackableTargetGoal extends TargetG this.randomInterval = reciprocalChance; this.setFlags(EnumSet.of(Goal.Flag.TARGET)); - this.targetConditions = (new TargetingConditions()).range(this.getFollowDistance()).selector(targetPredicate); + this.targetConditions = TargetingConditions.forCombat().range(this.getFollowDistance()).selector(targetPredicate); + if (mob.level.paperConfig.entitiesTargetWithFollowRange) this.targetConditions.useFollowRange(); // Paper } @Override diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -index 1714507fa744b2767e8a66cdb5db7f43c21f5c56..e1a0104a3b52990a83e7732491029d8a20976dc3 100644 +index e45434b844c98c322e1432c2382c1ccb8c3e57a7..3ee691d4caccbc1b3e0f52decb41d436ac0d08ec 100644 --- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java +++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -@@ -4,6 +4,8 @@ import java.util.function.Predicate; - import javax.annotation.Nullable; - import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.Mob; -+import net.minecraft.world.entity.ai.attributes.AttributeInstance; -+import net.minecraft.world.entity.ai.attributes.Attributes; - - public class TargetingConditions { - -@@ -82,7 +84,7 @@ public class TargetingConditions { +@@ -75,7 +75,7 @@ public class TargetingConditions { if (this.range > 0.0D) { - double d0 = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D; -- double d1 = Math.max(this.range * d0, 2.0D); -+ double d1 = Math.max((useFollowRange ? getFollowRange(baseEntity) : this.range) * d0, 2.0D); // Paper - double d2 = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); - - if (d2 > d1 * d1) { -@@ -98,4 +100,18 @@ public class TargetingConditions { + double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D; +- double e = Math.max(this.range * d, 2.0D); ++ double e = Math.max((this.useFollowRange ? this.getFollowRange(baseEntity) : this.range) * d, 2.0D); // Paper + double f = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); + if (f > e * e) { + return false; +@@ -90,4 +90,18 @@ public class TargetingConditions { return true; } } @@ -66,7 +58,7 @@ index 1714507fa744b2767e8a66cdb5db7f43c21f5c56..e1a0104a3b52990a83e7732491029d8a + } + + private double getFollowRange(LivingEntity entityliving) { -+ AttributeInstance attributeinstance = entityliving.getAttribute(Attributes.FOLLOW_RANGE); ++ net.minecraft.world.entity.ai.attributes.AttributeInstance attributeinstance = entityliving.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.FOLLOW_RANGE); + return attributeinstance == null ? 16.0D : attributeinstance.getValue(); + } + // Paper end diff --git a/patches/server-remapped/0390-Optimize-Hoppers.patch b/patches/server/0347-Optimize-Hoppers.patch similarity index 51% rename from patches/server-remapped/0390-Optimize-Hoppers.patch rename to patches/server/0347-Optimize-Hoppers.patch index 5d342ad554..d68d9a0355 100644 --- a/patches/server-remapped/0390-Optimize-Hoppers.patch +++ b/patches/server/0347-Optimize-Hoppers.patch @@ -13,10 +13,10 @@ Subject: [PATCH] Optimize Hoppers * Remove Streams from Item Suck In and restore restore 1.12 AABB checks which is simpler and no voxel allocations (was doing TWO Item Suck ins) diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index edda2121f8c1046478beaa77030ebb36d403b334..7fbd501d70dccf869a4454e2789a5d68f2e15754 100644 +index 8190c30346c0fd2d86fb7cbcfc7ce17333e05146..041efecbfcd54384d15ebf771cdfa0e711483997 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -585,4 +585,13 @@ public class PaperWorldConfig { +@@ -431,5 +431,14 @@ public class PaperWorldConfig { private void entitiesTargetWithFollowRange() { entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); } @@ -30,31 +30,24 @@ index edda2121f8c1046478beaa77030ebb36d403b334..7fbd501d70dccf869a4454e2789a5d68 + log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); + } } + diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 753e6f609189c589514739bea80007bace3c89d2..7038897b8fb4c18ca97b95a3b24c30b40b62b005 100644 +index f00839eab02277bf10b742c88fadc4aa9e89e7e0..312be2221e1acc44aaf6936533b0eb968f796dc6 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -131,6 +131,7 @@ import net.minecraft.world.level.LevelSettings; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.biome.BiomeSource; - import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.HopperBlockEntity; - import net.minecraft.world.level.border.WorldBorder; - import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.dimension.DimensionType; -@@ -1360,6 +1361,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper -+ HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper ++ net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper this.profiler.push(() -> { return worldserver + " " + worldserver.dimension().location(); diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 02bfa4fb8055e60a84e878ffbf18303c0ee25b1d..ac996d581925c8f92832009945c766962e5b51c5 100644 +index dd4deb08eb3ed15a156269a11d3d43abfd61fe5b..10f55ba189d12c46e0ef38b0b96a29894b4fba93 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -538,11 +538,12 @@ public final class ItemStack { +@@ -601,11 +601,12 @@ public final class ItemStack { return this.getItem().interactLivingEntity(this, user, entity, hand); } @@ -70,89 +63,75 @@ index 02bfa4fb8055e60a84e878ffbf18303c0ee25b1d..ac996d581925c8f92832009945c76696 itemstack.setPopTime(this.getPopTime()); if (this.tag != null) { -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 3e2cd6c7a34c1a792d7346019a8b039d1f4a7c04..6b79f8cd9258af47afa6efa7b1f97c3780be58b0 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1162,8 +1162,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return list; - } - -- @Override -- public List getEntitiesOfClass(Class entityClass, AABB box, @Nullable Predicate predicate) { -+ public List getEntities(Class oclass, AABB axisalignedbb, @Nullable Predicate predicate) { return getEntitiesOfClass(oclass, axisalignedbb, predicate); } // Paper - OBFHELPER -+ @Override public List getEntitiesOfClass(Class entityClass, AABB box, @Nullable Predicate predicate) { - this.getProfiler().incrementCounter("getEntities"); - int i = Mth.floor((box.minX - 2.0D) / 16.0D); - int j = Mth.ceil((box.maxX + 2.0D) / 16.0D); diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 84012c2d12817e657b046bc168cc8eddebcd3831..05fa76c02ce61e26891ad995fe89e925ea086557 100644 +index 8a079ee3ed243fd19b1dd7eed2de1dd33785faa1..c3a07ccccd5cc38552363c82398f432c8d624288 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -77,6 +77,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - public void setCurrentChunk(LevelChunk chunk) { - this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; +@@ -63,6 +63,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + getMinecraftKey(); // Try to load if it doesn't exists. + return tileEntityKeyString; } + static boolean IGNORE_TILE_UPDATES = false; // Paper end @Nullable -@@ -155,6 +156,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { +@@ -145,6 +146,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { public void setChanged() { if (this.level != null) { + if (IGNORE_TILE_UPDATES) return; // Paper - this.blockState = this.level.getBlockState(this.worldPosition); - this.level.blockEntityChanged(this.worldPosition, this); - if (!this.blockState.isAir()) { + BlockEntity.setChanged(this.level, this.worldPosition, this.blockState); + } + diff --git a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java -index f8e4a42bed265822666141683e36e6696694925b..fc8bb72f7d677f65db505016ad6a4cd6146de29f 100644 +index a05acf709735b40ca86f978508c63a86065fd405..c1754df6a60ff93d75a28145b9dc4e9174241a21 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java +++ b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java -@@ -1,6 +1,7 @@ - package net.minecraft.world.level.block.entity; - - import javax.annotation.Nullable; -+import net.minecraft.core.BlockPos; - import net.minecraft.world.Container; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.block.Block; -@@ -17,12 +18,13 @@ public interface Hopper extends Container { - return Hopper.SUCK; +@@ -14,6 +14,10 @@ public interface Hopper extends Container { + return SUCK; } -- @Nullable -+ //@Nullable // Paper - it's annoying - Level getLevel(); -+ default BlockPos getBlockPosition() { return new BlockPos(getX(), getY(), getZ()); } // Paper ++ net.minecraft.world.level.Level getLevel(); ++ ++ default net.minecraft.core.BlockPos getBlockPosition() { return new net.minecraft.core.BlockPos(getLevelX(), getLevelY(), getLevelZ()); } // Paper ++ + double getLevelX(); -- double getLevelX(); -+ double getLevelX(); default double getX() { return this.getLevelX(); } // Paper - OBFHELPER - -- double getLevelY(); -+ double getLevelY(); default double getY() { return this.getLevelY(); } // Paper - OBFHELPER - -- double getLevelZ(); -+ double getLevelZ(); default double getZ() { return this.getLevelZ(); } // Paper - OBFHELPER - } + double getLevelY(); 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 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f7639dab54b 100644 +index 0ec16d554c2b51a64614c73783505c7b06ff02c7..86c0a477883102e4aebdab7ac28bf9f2ab2f7c48 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 -@@ -193,6 +193,160 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -3,7 +3,6 @@ package net.minecraft.world.level.block.entity; + import java.util.Iterator; + import java.util.List; + import java.util.function.BooleanSupplier; +-import java.util.stream.Collectors; + import java.util.stream.IntStream; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -33,7 +32,6 @@ import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.Shapes; +-import org.bukkit.Bukkit; + import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.entity.HumanEntity; +@@ -192,6 +190,159 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + return false; } - + // Paper start - Optimize Hoppers + private static boolean skipPullModeEventFire = false; + private static boolean skipPushModeEventFire = false; + public static boolean skipHopperEvents = false; + -+ private boolean hopperPush(Container iinventory, Direction enumdirection) { ++ private static boolean hopperPush(Level level, BlockPos pos, Container iinventory, Direction enumdirection, HopperBlockEntity hopper) { + skipPushModeEventFire = skipHopperEvents; + boolean foundItem = false; -+ for (int i = 0; i < this.getContainerSize(); ++i) { -+ ItemStack item = this.getItem(i); ++ for (int i = 0; i < iinventory.getContainerSize(); ++i) { ++ ItemStack item = iinventory.getItem(i); + if (!item.isEmpty()) { + foundItem = true; + ItemStack origItemStack = item; @@ -165,13 +144,13 @@ index 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f76 + // We only need to fire the event once to give protection plugins a chance to cancel this event + // Because nothing uses getItem, every event call should end up the same result. + if (!skipPushModeEventFire) { -+ itemstack = callPushMoveEvent(iinventory, itemstack); ++ itemstack = callPushMoveEvent(iinventory, itemstack, hopper); + if (itemstack == null) { // cancelled + origItemStack.setCount(origCount); + return false; + } + } -+ final ItemStack itemstack2 = addItem(this, iinventory, itemstack, enumdirection); ++ final ItemStack itemstack2 = addItem(hopper, iinventory, itemstack, enumdirection); + final int remaining = itemstack2.getCount(); + if (remaining != moved) { + origItemStack = origItemStack.cloneItemStack(true); @@ -179,7 +158,7 @@ index 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f76 + if (!origItemStack.isEmpty()) { + origItemStack.setCount(origCount - moved + remaining); + } -+ this.setItem(i, origItemStack); ++ hopper.setItem(i, origItemStack); + iinventory.setChanged(); + return true; + } @@ -187,7 +166,7 @@ index 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f76 + } + } + if (foundItem && level.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown -+ this.setCooldown(level.spigotConfig.hopperTransfer); ++ hopper.setCooldown(level.spigotConfig.hopperTransfer); + } + return false; + } @@ -233,16 +212,16 @@ index 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f76 + return false; + } + -+ private ItemStack callPushMoveEvent(Container iinventory, ItemStack itemstack) { ++ private static ItemStack callPushMoveEvent(Container iinventory, ItemStack itemstack, HopperBlockEntity hopper) { + Inventory destinationInventory = getInventory(iinventory); -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner(false).getInventory(), ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(hopper.getOwner(false).getInventory(), + CraftItemStack.asCraftMirror(itemstack), destinationInventory, true); + boolean result = event.callEvent(); + if (!event.calledGetItem && !event.calledSetItem) { + skipPushModeEventFire = true; + } + if (!result) { -+ cooldownHopper(this); ++ cooldownHopper(hopper); + return null; + } + @@ -296,58 +275,18 @@ index 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f76 + } + } + // Paper end -+ - private boolean ejectItems() { - Container iinventory = this.getAttachedContainer(); -@@ -204,27 +358,28 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - if (this.isFullContainer(iinventory, enumdirection)) { + private static boolean a(Level world, BlockPos blockposition, BlockState iblockdata, Container iinventory, HopperBlockEntity hopper) { // CraftBukkit + Container iinventory1 = HopperBlockEntity.getAttachedContainer(world, blockposition, iblockdata); +@@ -204,6 +355,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + if (HopperBlockEntity.isFullContainer(iinventory1, enumdirection)) { return false; } else { -- for (int i = 0; i < this.getContainerSize(); ++i) { -+ return hopperPush(iinventory, enumdirection); /* // Paper - disable rest -+ for (int i = 0; i < this.getSize(); ++i) { - if (!this.getItem(i).isEmpty()) { -- ItemStack itemstack = this.getItem(i).copy(); -+ ItemStack itemstack = this.getItem(i).cloneItemStack(); - // ItemStack itemstack1 = addItem(this, iinventory, this.splitStack(i, 1), enumdirection); - - // CraftBukkit start - Call event when pushing items into other inventories -- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.removeItem(i, level.spigotConfig.hopperAmount)); // Spigot -+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.splitStack(i, world.spigotConfig.hopperAmount)); // Spigot - - Inventory destinationInventory; - // Have to special case large chests as they work oddly -- if (iinventory instanceof CompoundContainer) { -- destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); -+ if (iinventory instanceof InventoryLargeChest) { -+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); - } else { - destinationInventory = iinventory.getOwner().getInventory(); - } - - InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); -- this.getLevel().getCraftServer().getPluginManager().callEvent(event); -+ this.getWorld().getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - this.setItem(i, itemstack); -- this.setCooldown(level.spigotConfig.hopperTransfer); // Spigot -+ this.setCooldown(world.spigotConfig.hopperTransfer); // Spigot - return false; - } - int origCount = event.getItem().getAmount(); // Spigot -@@ -232,16 +387,16 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - // CraftBukkit end - - if (itemstack1.isEmpty()) { -- iinventory.setChanged(); -+ iinventory.update(); - return true; - } - -- itemstack.shrink(origCount - itemstack1.getCount()); // Spigot -+ itemstack.subtract(origCount - itemstack1.getCount()); // Spigot - this.setItem(i, itemstack); ++ return hopperPush(world, blockposition, iinventory, enumdirection, hopper); /* // Paper - disable rest + for (int i = 0; i < iinventory.getContainerSize(); ++i) { + if (!iinventory.getItem(i).isEmpty()) { + ItemStack itemstack = iinventory.getItem(i).copy(); +@@ -241,7 +393,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } } @@ -356,13 +295,25 @@ index 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f76 } } } -@@ -250,18 +405,54 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - return inventory instanceof WorldlyContainer ? IntStream.of(((WorldlyContainer) inventory).getSlotsForFace(side)) : IntStream.range(0, inventory.getContainerSize()); +@@ -251,27 +403,68 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } -- private boolean isFullContainer(Container inv, Direction enumdirection) { -- return getSlots(inv, enumdirection).allMatch((i) -> { -- ItemStack itemstack = inv.getItem(i); + private static boolean isFullContainer(Container inventory, Direction direction) { +- return HopperBlockEntity.getSlots(inventory, direction).allMatch((i) -> { +- ItemStack itemstack = inventory.getItem(i); +- +- return itemstack.getCount() >= itemstack.getMaxStackSize(); +- }); ++ return allMatch(inventory, direction, STACK_SIZE_TEST); // Paper - no streams + } + + private static boolean isEmptyContainer(Container inv, Direction facing) { +- return HopperBlockEntity.getSlots(inv, facing).allMatch((i) -> { +- return inv.getItem(i).isEmpty(); +- }); ++ // Paper start ++ return allMatch(inv, facing, IS_EMPTY_TEST); ++ } + private static boolean allMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate test) { + if (iinventory instanceof WorldlyContainer) { + for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) { @@ -379,10 +330,8 @@ index 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f76 + } + } + return true; -+ } + } -- return itemstack.getCount() >= itemstack.getMaxStackSize(); -- }); + private static boolean anyMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate test) { + if (iinventory instanceof WorldlyContainer) { + for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) { @@ -402,111 +351,53 @@ index 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f76 + } + private static final java.util.function.BiPredicate STACK_SIZE_TEST = (itemstack, i) -> itemstack.getCount() >= itemstack.getMaxStackSize(); + private static final java.util.function.BiPredicate IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty(); -+ + // Paper end + -+ private boolean isFullContainer(Container inv, Direction enumdirection) { -+ // Paper start - no streams -+ return allMatch(inv, enumdirection, STACK_SIZE_TEST); -+ // Paper end - } + public static boolean suckInItems(Level world, Hopper hopper) { + Container iinventory = HopperBlockEntity.getSourceContainer(world, hopper); - private static boolean isEmptyContainer(Container inv, Direction facing) { -- return getSlots(inv, facing).allMatch((i) -> { -- return inv.getItem(i).isEmpty(); -- }); -+ return allMatch(inv, facing, IS_EMPTY_TEST); - } - - public static boolean suckInItems(Hopper hopper) { -@@ -270,9 +461,17 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen if (iinventory != null) { Direction enumdirection = Direction.DOWN; -- return isEmptyContainer(iinventory, enumdirection) ? false : getSlots(iinventory, enumdirection).anyMatch((i) -> { -- return tryTakeInItemFromSlot(hopper, iinventory, i, enumdirection); +- return HopperBlockEntity.isEmptyContainer(iinventory, enumdirection) ? false : HopperBlockEntity.getSlots(iinventory, enumdirection).anyMatch((i) -> { +- return HopperBlockEntity.a(hopper, iinventory, i, enumdirection, world); // Spigot + // Paper start - optimize hoppers and remove streams + skipPullModeEventFire = skipHopperEvents; -+ return !isEmptyContainer(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { ++ return !HopperBlockEntity.isEmptyContainer(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { + // Logic copied from below to avoid extra getItem calls -+ if (!item.isEmpty() && canTakeItem(iinventory, item, i, enumdirection)) { ++ if (!item.isEmpty() && canTakeItemFromContainer(iinventory, item, i, enumdirection)) { + return hopperPull(hopper, iinventory, item, i); + } else { + return false; + } ++ // Paper end }); -+ // Paper end } else { - Iterator iterator = getItemsAtAndAbove(hopper).iterator(); - -@@ -290,47 +489,48 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + Iterator iterator = HopperBlockEntity.getItemsAtAndAbove(world, hopper).iterator(); +@@ -290,10 +483,12 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } } -- private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) { -+ private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) {// Paper - method unused as logic is inlined above - ItemStack itemstack = inventory.getItem(slot); ++ // Paper - method unused as logic is inlined above + private static boolean a(Hopper ihopper, Container iinventory, int i, Direction enumdirection, Level world) { // Spigot + ItemStack itemstack = iinventory.getItem(i); -- if (!itemstack.isEmpty() && canTakeItemFromContainer(inventory, itemstack, slot, side)) { -- ItemStack itemstack1 = itemstack.copy(); -+ if (!itemstack.isEmpty() && canTakeItemFromContainer(inventory, itemstack, slot, side)) { // If this logic changes, update above. this is left inused incase reflective plugins -+ return hopperPull(hopper, inventory, itemstack, slot); /* // Paper - disable rest -+ ItemStack itemstack1 = itemstack.cloneItemStack(); +- if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(iinventory, itemstack, i, enumdirection)) { ++ if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(iinventory, itemstack, i, enumdirection)) { // If this logic changes, update above. this is left inused incase reflective plugins ++ return hopperPull(ihopper, iinventory, itemstack, i); /* // Paper - disable rest + ItemStack itemstack1 = itemstack.copy(); // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null); // CraftBukkit start - Call event on collection of items from inventories into the hopper -- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(inventory.removeItem(slot, hopper.getLevel().spigotConfig.hopperAmount)); // Spigot -+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.splitStack(i, ihopper.getWorld().spigotConfig.hopperAmount)); // Spigot - - Inventory sourceInventory; - // Have to special case large chests as they work oddly -- if (inventory instanceof CompoundContainer) { -- sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) inventory); -+ if (iinventory instanceof InventoryLargeChest) { -+ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); - } else { -- sourceInventory = inventory.getOwner().getInventory(); -+ sourceInventory = iinventory.getOwner().getInventory(); +@@ -330,7 +525,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } -- InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), hopper.getOwner().getInventory(), false); -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), ihopper.getOwner().getInventory(), false); - -- hopper.getLevel().getCraftServer().getPluginManager().callEvent(event); -+ ihopper.getWorld().getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { -- inventory.setItem(slot, itemstack1); -+ iinventory.setItem(i, itemstack1); - -- if (hopper instanceof HopperBlockEntity) { -- ((HopperBlockEntity) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer); // Spigot -- } else if (hopper instanceof MinecartHopper) { -- ((MinecartHopper) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer / 2); // Spigot -+ if (ihopper instanceof TileEntityHopper) { -+ ((TileEntityHopper) ihopper).setCooldown(ihopper.getWorld().spigotConfig.hopperTransfer); // Spigot -+ } else if (ihopper instanceof EntityMinecartHopper) { -+ ((EntityMinecartHopper) ihopper).setCooldown(ihopper.getWorld().spigotConfig.hopperTransfer / 2); // Spigot - } - return false; - } - int origCount = event.getItem().getAmount(); // Spigot -- ItemStack itemstack2 = addItem(inventory, hopper, CraftItemStack.asNMSCopy(event.getItem()), null); -+ ItemStack itemstack2 = addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null); - // CraftBukkit end - - if (itemstack2.isEmpty()) { -- inventory.setChanged(); -+ iinventory.update(); - return true; - } - -- itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot -- inventory.setItem(slot, itemstack1); -+ itemstack1.subtract(origCount - itemstack2.getCount()); // Spigot + itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot +- iinventory.setItem(i, itemstack1); + iinventory.setItem(i, itemstack1);*/ // Paper - end commenting out replaced block for Hopper Optimizations } return false; -@@ -339,7 +539,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -339,7 +534,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen public static boolean addItem(Container inventory, ItemEntity itemEntity) { boolean flag = false; // CraftBukkit start @@ -515,15 +406,7 @@ index 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f76 itemEntity.level.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return false; -@@ -381,6 +581,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - return !inventory.canPlaceItem(slot, stack) ? false : !(inventory instanceof WorldlyContainer) || ((WorldlyContainer) inventory).canPlaceItemThroughFace(slot, stack, side); - } - -+ private static boolean canTakeItem(Container iinventory, ItemStack itemstack, int i, Direction enumdirection) { return canTakeItemFromContainer(iinventory, itemstack, i, enumdirection); } // Paper - OBFHELPER - private static boolean canTakeItemFromContainer(Container inv, ItemStack stack, int slot, Direction facing) { - return !(inv instanceof WorldlyContainer) || ((WorldlyContainer) inv).canTakeItemThroughFace(slot, stack, facing); - } -@@ -393,7 +594,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -393,7 +588,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen boolean flag1 = to.isEmpty(); if (itemstack1.isEmpty()) { @@ -532,59 +415,53 @@ index 04b0f0de43dfd95e82d402068da8a97bdb86f758..70718fcbaa6f671061479957b7608f76 + IGNORE_TILE_UPDATES = false; // Paper stack = ItemStack.EMPTY; flag = true; - } else if (canMergeItems(itemstack1, stack)) { -@@ -444,20 +647,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) { +@@ -444,18 +641,23 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } - public static List getItemsAtAndAbove(Hopper ihopper) { -- return (List) ihopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> { -- return ihopper.getLevel().getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(ihopper.getLevelX() - 0.5D, ihopper.getLevelY() - 0.5D, ihopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream(); + public static List getItemsAtAndAbove(Level world, Hopper hopper) { +- return (List) hopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> { +- return world.getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(hopper.getLevelX() - 0.5D, hopper.getLevelY() - 0.5D, hopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream(); - }).collect(Collectors.toList()); + // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?! -+ Level world = ihopper.getLevel(); -+ double d0 = ihopper.getX(); -+ double d1 = ihopper.getY(); -+ double d2 = ihopper.getZ(); ++ double d0 = hopper.getLevelX(); ++ double d1 = hopper.getLevelY(); ++ double d2 = hopper.getLevelZ(); + AABB bb = new AABB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); -+ return world.getEntities(ItemEntity.class, bb, Entity::isAlive); ++ return world.getEntitiesOfClass(ItemEntity.class, bb, Entity::isAlive); + // Paper end } @Nullable - public static Container getContainerAt(Level world, BlockPos blockposition) { -- return getContainerAt(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); -+ return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, true); // Paper + public static Container getContainerAt(Level world, BlockPos pos) { +- return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D); ++ return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, true); // Paper } ++ public static Container getContainerAt(Level world, double x, double y, double z) { return getContainerAt(world, x, y, z, false); } // Paper - overload to default false @Nullable -- public static Container getContainerAt(Level world, double x, double y, double z) { -+ public static Container getContainerAt(Level world, double x, double y, double z) { return a(world, x, y, z, false); } // Paper - overload to default false -+ public static Container a(Level world, double d0, double d1, double d2, boolean optimizeEntities) { // Paper +- private static Container getContainerAt(Level world, double x, double y, double z) { ++ private static Container getContainerAt(Level world, double x, double y, double z, boolean optimizeEntities) { Object object = null; -- BlockPos blockposition = new BlockPos(x, y, z); -+ BlockPos blockposition = new BlockPos(d0, d1, d2); + BlockPos blockposition = new BlockPos(x, y, z); if ( !world.hasChunkAt( blockposition ) ) return null; // Spigot - BlockState iblockdata = world.getBlockState(blockposition); - Block block = iblockdata.getBlock(); -@@ -475,8 +684,8 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -475,7 +677,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } } - if (object == null) { -- List list = world.getEntities((Entity) null, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); + if (object == null && (!optimizeEntities || !org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(block).isOccluding())) { // Paper -+ List list = world.getEntities((Entity) null, new AABB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); + List list = world.getEntities((Entity) null, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); if (!list.isEmpty()) { - object = (Container) list.get(world.random.nextInt(list.size())); diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java -index 5ad419941ff1113ef29b9a4593f44d8f35ba8424..4525032232b5a89de13c6a46dc489a07428e3f21 100644 +index f23fff80d07ac7d06715efe67cb49ebbe704967b..ed3518fe7c841d9e1a9c97626acaa3d765a6d76f 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java -@@ -97,12 +97,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc +@@ -95,12 +95,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc @Override public boolean isEmpty() { - this.unpackLootTable((Player) null); + this.unpackLootTable((Player)null); - return this.getItems().stream().allMatch(ItemStack::isEmpty); + // Paper start + for (ItemStack itemStack : this.getItems()) { @@ -598,8 +475,8 @@ index 5ad419941ff1113ef29b9a4593f44d8f35ba8424..4525032232b5a89de13c6a46dc489a07 @Override public ItemStack getItem(int slot) { -- this.unpackLootTable((Player) null); +- this.unpackLootTable((Player)null); + if (slot == 0) this.unpackLootTable((Player) null); // Paper - return (ItemStack) this.getItems().get(slot); + return this.getItems().get(slot); } diff --git a/patches/server-remapped/0391-PlayerDeathEvent-shouldDropExperience.patch b/patches/server/0348-PlayerDeathEvent-shouldDropExperience.patch similarity index 79% rename from patches/server-remapped/0391-PlayerDeathEvent-shouldDropExperience.patch rename to patches/server/0348-PlayerDeathEvent-shouldDropExperience.patch index 4f453dc689..40e04c2c40 100644 --- a/patches/server-remapped/0391-PlayerDeathEvent-shouldDropExperience.patch +++ b/patches/server/0348-PlayerDeathEvent-shouldDropExperience.patch @@ -5,10 +5,10 @@ Subject: [PATCH] PlayerDeathEvent#shouldDropExperience diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 2ef273e3b917803f3e2ac3c6a22d92a15b9eb71a..7f4e81ee3339e90b8525541dccf6dea187853cf7 100644 +index 8da35a7dde494b059e542d049d7ee039deb5833d..4fef4c0240be90ddcb9640f5719e292d2d5dbdf8 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -819,7 +819,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -849,7 +849,7 @@ public class ServerPlayer extends Player { this.tellNeutralMobsThatIDied(); } // SPIGOT-5478 must be called manually now @@ -16,4 +16,4 @@ index 2ef273e3b917803f3e2ac3c6a22d92a15b9eb71a..7f4e81ee3339e90b8525541dccf6dea1 + if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. if (!event.getKeepInventory()) { - // Paper start - replace logic + this.getInventory().clearContent(); diff --git a/patches/server-remapped/0392-Prevent-bees-loading-chunks-checking-hive-position.patch b/patches/server/0349-Prevent-bees-loading-chunks-checking-hive-position.patch similarity index 85% rename from patches/server-remapped/0392-Prevent-bees-loading-chunks-checking-hive-position.patch rename to patches/server/0349-Prevent-bees-loading-chunks-checking-hive-position.patch index 9a427d5aa2..6c74d7945e 100644 --- a/patches/server-remapped/0392-Prevent-bees-loading-chunks-checking-hive-position.patch +++ b/patches/server/0349-Prevent-bees-loading-chunks-checking-hive-position.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Prevent bees loading chunks checking hive position diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index 32ee38142a3053091ab7b3fb3d608d268b07d4e3..edd6d63f715acef1a77eba0cf46ff8267228f4c6 100644 +index 488dd4693dbbc303f0fc6d98667b822304b06c9f..f3ba4b26553915917c79f013ed9dd7c87d9f65a4 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -442,6 +442,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -495,6 +495,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { if (!this.hasHive()) { return false; } else { diff --git a/patches/server-remapped/0393-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/patches/server/0350-Don-t-load-Chunks-from-Hoppers-and-other-things.patch similarity index 58% rename from patches/server-remapped/0393-Don-t-load-Chunks-from-Hoppers-and-other-things.patch rename to patches/server/0350-Don-t-load-Chunks-from-Hoppers-and-other-things.patch index f6952f6250..d646992d77 100644 --- a/patches/server-remapped/0393-Don-t-load-Chunks-from-Hoppers-and-other-things.patch +++ b/patches/server/0350-Don-t-load-Chunks-from-Hoppers-and-other-things.patch @@ -13,20 +13,20 @@ This of course is undesirable, so just return the loaded side as "primary" and treat it as a single chest if the other sides are unloaded diff --git a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java -index a4f16b2093c867e9fd1c2e07b67c49c3c5ec7506..df20b3616929657d2e8061159ed97f500b33d192 100644 +index ff2a7b08fe70adaecdaa508baadcfe40416519e0..7082bb0b28b6a046e3925f69e18b7c319871128f 100644 --- a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java +++ b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java -@@ -29,7 +29,12 @@ public class DoubleBlockCombiner { - return new DoubleBlockCombiner.NeighborCombineResult.Single<>(s0); +@@ -25,7 +25,12 @@ public class DoubleBlockCombiner { + return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity); } else { - BlockPos blockposition1 = pos.relative((Direction) function1.apply(state)); -- BlockState iblockdata1 = world.getBlockState(blockposition1); + BlockPos blockPos = pos.relative(function.apply(state)); +- BlockState blockState = world.getBlockState(blockPos); + // Paper start -+ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); -+ if (iblockdata1 == null) { -+ return new DoubleBlockCombiner.NeighborCombineResult.Single<>(s0); ++ BlockState blockState = world.getTypeIfLoaded(blockPos); ++ if (blockState == null) { ++ return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity); + } + // Paper end - - if (iblockdata1.is(state.getBlock())) { - DoubleBlockCombiner.BlockType doubleblockfinder_blocktype1 = (DoubleBlockCombiner.BlockType) typeMapper.apply(iblockdata1); + if (blockState.is(state.getBlock())) { + DoubleBlockCombiner.BlockType blockType2 = typeMapper.apply(blockState); + if (blockType2 != DoubleBlockCombiner.BlockType.SINGLE && blockType != blockType2 && blockState.getValue(directionProperty) == state.getValue(directionProperty)) { diff --git a/patches/server/0351-Guard-against-serializing-mismatching-chunk-coordina.patch b/patches/server/0351-Guard-against-serializing-mismatching-chunk-coordina.patch new file mode 100644 index 0000000000..5d846e842b --- /dev/null +++ b/patches/server/0351-Guard-against-serializing-mismatching-chunk-coordina.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Fri, 27 Dec 2019 09:42:26 -0800 +Subject: [PATCH] Guard against serializing mismatching chunk coordinate + +Should help if something dumb happens + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 3cb35f2f47ba841915ac2825d30cc4c3274ce3c4..7c04aef3eac54981ca1e34cb87d97104c3c9685b 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -69,6 +69,13 @@ public class ChunkSerializer { + + public ChunkSerializer() {} + ++ // Paper start - guard against serializing mismatching coordinates ++ // TODO Note: This needs to be re-checked each update ++ public static ChunkPos getChunkCoordinate(CompoundTag chunkData) { ++ CompoundTag levelData = chunkData.getCompound("Level"); ++ return new ChunkPos(levelData.getInt("xPos"), levelData.getInt("zPos")); ++ } ++ // Paper end + // Paper start + public static final class InProgressChunkHolder { + +@@ -95,8 +102,8 @@ public class ChunkSerializer { + // Paper end + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); + BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); +- CompoundTag nbttagcompound1 = nbt.getCompound("Level"); +- ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); ++ CompoundTag nbttagcompound1 = nbt.getCompound("Level"); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate ++ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate + + if (!Objects.equals(pos, chunkcoordintpair1)) { + ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", pos, pos, chunkcoordintpair1); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +index 6f13c7adce7d4b3d170045ea5ef2a841d34ae7b0..176610b31f66b890afe61f4de46c412382bb8d22 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -117,6 +117,13 @@ public class ChunkStorage implements AutoCloseable { + + // Paper start - async chunk io + public void write(ChunkPos chunkPos, CompoundTag nbt) throws IOException { ++ // Paper start ++ if (!chunkPos.equals(ChunkSerializer.getChunkCoordinate(nbt))) { ++ String world = (this instanceof net.minecraft.server.level.ChunkMap) ? ((net.minecraft.server.level.ChunkMap)this).level.getWorld().getName() : null; ++ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkPos.toString() ++ + " but compound says coordinate is " + ChunkSerializer.getChunkCoordinate(nbt).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); ++ } ++ // Paper end + this.regionFileCache.write(chunkPos, nbt); + // Paper end - Async chunk loading + if (this.legacyStructureHandler != null) { diff --git a/patches/server-remapped/0395-Optimise-IEntityAccess-getPlayerByUUID.patch b/patches/server/0352-Optimise-IEntityAccess-getPlayerByUUID.patch similarity index 51% rename from patches/server-remapped/0395-Optimise-IEntityAccess-getPlayerByUUID.patch rename to patches/server/0352-Optimise-IEntityAccess-getPlayerByUUID.patch index e478c7d039..7ec8915584 100644 --- a/patches/server-remapped/0395-Optimise-IEntityAccess-getPlayerByUUID.patch +++ b/patches/server/0352-Optimise-IEntityAccess-getPlayerByUUID.patch @@ -6,39 +6,21 @@ Subject: [PATCH] Optimise IEntityAccess#getPlayerByUUID Use the world entity map instead of iterating over all players diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 01f879a8dd0e1ffec380e02072567330152eaceb..40d7dbc4f1deda88d4a539b89d84b595217051b6 100644 +index 736521c0925339dc74c2648641932104a947708e..eabf8fa6e8802ebea8dbe124363bb085849af5d9 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -283,6 +283,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } +@@ -281,6 +281,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; // Paper end + // Paper start - optimise getPlayerByUUID + @Nullable + @Override + public Player getPlayerByUUID(UUID uuid) { -+ Entity player = this.entitiesByUuid.get(uuid); -+ return (player instanceof Player) ? (Player)player : null; ++ return this.getServer().getPlayerList().getPlayer(uuid); + } + // Paper end + // Add env and gen to constructor, WorldData -> WorldDataServer public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor -diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index 6a5430fe54a5c8ad119a0f3842961825a54d8d7a..b9606465ace8b320eafbbad3d60c01b87a859c44 100644 ---- a/src/main/java/net/minecraft/world/level/EntityGetter.java -+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -277,6 +277,12 @@ public interface EntityGetter { - - @Nullable - default Player getPlayerByUUID(UUID uuid) { -+ // Paper start - allow WorldServer to override -+ return this.getPlayerByUUID(uuid); -+ } -+ @Nullable -+ default Player getPlayerByUUID(UUID uuid) { -+ // Paper end - for (int i = 0; i < this.players().size(); ++i) { - Player entityhuman = (Player) this.players().get(i); - + // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error diff --git a/patches/server-remapped/0396-Fix-items-not-falling-correctly.patch b/patches/server/0353-Fix-items-not-falling-correctly.patch similarity index 66% rename from patches/server-remapped/0396-Fix-items-not-falling-correctly.patch rename to patches/server/0353-Fix-items-not-falling-correctly.patch index f1ecdfe628..8eba5c8d55 100644 --- a/patches/server-remapped/0396-Fix-items-not-falling-correctly.patch +++ b/patches/server/0353-Fix-items-not-falling-correctly.patch @@ -15,15 +15,15 @@ This patch resolves the conflict by offsetting checking an item's move method from Spigot's entity activation range check. diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 96b8102773cbee2c3fe2711008ba1487084d67b0..9311f9f411d09d4460f0be8235957fab9e195b7a 100644 +index 82ffe3624943d2e931e2cc2f85ede94f369bd06b..9ee1dc89dd4c6b9453e1f6f92208d454877d23c9 100644 --- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -115,7 +115,7 @@ public class ItemEntity extends Entity { +@@ -135,7 +135,7 @@ public class ItemEntity extends Entity { } } -- if (!this.onGround || getHorizontalDistanceSqr(this.getDeltaMovement()) > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) { -+ if (!this.onGround || getHorizontalDistanceSqr(this.getDeltaMovement()) > 9.999999747378752E-6D || this.tickCount % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check +- if (!this.onGround || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) { ++ if (!this.onGround || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || this.tickCount % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check this.move(MoverType.SELF, this.getDeltaMovement()); float f1 = 0.98F; diff --git a/patches/server-remapped/0397-Lag-compensate-eating.patch b/patches/server/0354-Lag-compensate-eating.patch similarity index 57% rename from patches/server-remapped/0397-Lag-compensate-eating.patch rename to patches/server/0354-Lag-compensate-eating.patch index cc90ba9655..9941db915c 100644 --- a/patches/server-remapped/0397-Lag-compensate-eating.patch +++ b/patches/server/0354-Lag-compensate-eating.patch @@ -7,19 +7,10 @@ When the server is lagging, players will wait longer when eating. Change to also use a time check instead if it passes. diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index b49d4772932a58852b3195f5f56ff93dbcabf766..016fcc4ae20e1e48728a848be28633e624ae49a7 100644 +index 5def2e0379373b126a1b2281b0859b39443fc4ac..f48435dc344fb48feb48e2a141b394829058c5c4 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -211,7 +211,7 @@ public abstract class LivingEntity extends Entity { - private int noJumpDelay; - private float absorptionAmount; - public ItemStack useItem; // Paper - public -- protected int useItemRemaining; -+ protected int useItemRemaining; protected final int getEatTimeTicks() { return this.useItemRemaining; } protected final void setEatTimeTicks(int value) { this.useItemRemaining = value; } // Paper - OBFHELPER - protected int fallFlyTicks; - private BlockPos lastPos; - private Optional lastClimbablePos; -@@ -3148,6 +3148,11 @@ public abstract class LivingEntity extends Entity { +@@ -3492,6 +3492,11 @@ public abstract class LivingEntity extends Entity { return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; } @@ -31,21 +22,22 @@ index b49d4772932a58852b3195f5f56ff93dbcabf766..016fcc4ae20e1e48728a848be28633e6 private void updatingUsingItem() { if (this.isUsingItem()) { if (ItemStack.isSameIgnoreDurability(this.getItemInHand(this.getUsedItemHand()), this.useItem)) { -@@ -3157,7 +3162,12 @@ public abstract class LivingEntity extends Entity { - this.triggerItemUseEffects(this.useItem, 5); - } +@@ -3509,8 +3514,12 @@ public abstract class LivingEntity extends Entity { + if (this.shouldTriggerItemUseEffects()) { + this.triggerItemUseEffects(stack, 5); + } +- +- if (--this.useItemRemaining == 0 && !this.level.isClientSide && !stack.useOnRelease()) { ++ // Paper start - lag compensate eating ++ // we add 1 to the expected time to avoid lag compensating when we should not ++ boolean shouldLagCompensate = this.useItem.getItem().isEdible() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); ++ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level.isClientSide && !this.useItem.useOnRelease()) { ++ this.useItemRemaining = 0; ++ // Paper end + this.completeUsingItem(); + } -- if (--this.useItemRemaining == 0 && !this.level.isClientSide && !this.useItem.useOnRelease()) { -+ // Paper start - lag compensate eating -+ // we add 1 to the expected time to avoid lag compensating when we should not -+ boolean shouldLagCompensate = this.useItem.getItem().isEdible() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); -+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level.isClientSide && !this.useItem.useOnRelease()) { -+ this.setEatTimeTicks(0); -+ // Paper end - this.completeUsingItem(); - } - } else { -@@ -3207,7 +3217,10 @@ public abstract class LivingEntity extends Entity { +@@ -3556,7 +3565,10 @@ public abstract class LivingEntity extends Entity { if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag this.useItem = itemstack; @@ -57,7 +49,7 @@ index b49d4772932a58852b3195f5f56ff93dbcabf766..016fcc4ae20e1e48728a848be28633e6 if (!this.level.isClientSide) { this.setLivingEntityFlag(1, true); this.setLivingEntityFlag(2, enumhand == InteractionHand.OFF_HAND); -@@ -3231,7 +3244,10 @@ public abstract class LivingEntity extends Entity { +@@ -3580,7 +3592,10 @@ public abstract class LivingEntity extends Entity { } } else if (!this.isUsingItem() && !this.useItem.isEmpty()) { this.useItem = ItemStack.EMPTY; @@ -69,7 +61,7 @@ index b49d4772932a58852b3195f5f56ff93dbcabf766..016fcc4ae20e1e48728a848be28633e6 } } -@@ -3359,7 +3375,10 @@ public abstract class LivingEntity extends Entity { +@@ -3706,7 +3721,10 @@ public abstract class LivingEntity extends Entity { } this.useItem = ItemStack.EMPTY; diff --git a/patches/server-remapped/0398-Optimize-call-to-getFluid-for-explosions.patch b/patches/server/0355-Optimize-call-to-getFluid-for-explosions.patch similarity index 72% rename from patches/server-remapped/0398-Optimize-call-to-getFluid-for-explosions.patch rename to patches/server/0355-Optimize-call-to-getFluid-for-explosions.patch index 9e3f2b3479..43ce56104d 100644 --- a/patches/server-remapped/0398-Optimize-call-to-getFluid-for-explosions.patch +++ b/patches/server/0355-Optimize-call-to-getFluid-for-explosions.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Optimize call to getFluid for explosions diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 45a75f7be308678336e192828becf6cf5c9047bc..667a6d645034c67639c01b8221591877bcb87b35 100644 +index edc0845ae735a9cf3e0f1a3a2b7eabf726d62744..cdf214fca3b0055efa56702470d9d2f890a8aead 100644 --- a/src/main/java/net/minecraft/world/level/Explosion.java +++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -151,7 +151,7 @@ public class Explosion { +@@ -174,7 +174,7 @@ public class Explosion { for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { BlockPos blockposition = new BlockPos(d4, d5, d6); BlockState iblockdata = this.level.getBlockState(blockposition); - FluidState fluid = this.level.getFluidState(blockposition); + FluidState fluid = iblockdata.getFluidState(); // Paper - Optional optional = this.damageCalculator.a(this, this.level, blockposition, iblockdata, fluid); - if (optional.isPresent()) { + if (!this.level.isInWorldBounds(blockposition)) { + break; diff --git a/patches/server-remapped/0399-Fix-last-firework-in-stack-not-having-effects-when-d.patch b/patches/server/0356-Fix-last-firework-in-stack-not-having-effects-when-d.patch similarity index 90% rename from patches/server-remapped/0399-Fix-last-firework-in-stack-not-having-effects-when-d.patch rename to patches/server/0356-Fix-last-firework-in-stack-not-having-effects-when-d.patch index 63271d423f..fbe63db8cd 100644 --- a/patches/server-remapped/0399-Fix-last-firework-in-stack-not-having-effects-when-d.patch +++ b/patches/server/0356-Fix-last-firework-in-stack-not-having-effects-when-d.patch @@ -9,10 +9,10 @@ dispensed. The resulting item would have size == 0 and therefore be convertered to air, hence why the effects disappeared. diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -index 67a894a185a3d4a53b3c7f90174b2604dff18257..67d140dff483bfc654a0390e0cdcd13aa658a62d 100644 +index b665d4293b746b221d469a7b029c1c7f17df6188..92623ae25249d63efb92be8bd6c95228f9155ad2 100644 --- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -@@ -425,7 +425,7 @@ public interface DispenseItemBehavior { +@@ -431,7 +431,7 @@ public interface DispenseItemBehavior { } itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); diff --git a/patches/server-remapped/0400-Add-effect-to-block-break-naturally.patch b/patches/server/0357-Add-effect-to-block-break-naturally.patch similarity index 81% rename from patches/server-remapped/0400-Add-effect-to-block-break-naturally.patch rename to patches/server/0357-Add-effect-to-block-break-naturally.patch index e51ec69f45..f0c758d801 100644 --- a/patches/server-remapped/0400-Add-effect-to-block-break-naturally.patch +++ b/patches/server/0357-Add-effect-to-block-break-naturally.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add effect to block break naturally diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 5bff313dbbb3049105874846d995883e827fbc00..05f0833f762436bf8f5f5875c7e3cfed1da11e1c 100644 +index 0a9ed9992a2fc97472a06591a5d129a767ce21af..ca95a6b1b156b37f839c6479733e5184691af66c 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -630,6 +630,13 @@ public class CraftBlock implements Block { +@@ -632,6 +632,13 @@ public class CraftBlock implements Block { @Override public boolean breakNaturally(ItemStack item) { @@ -22,10 +22,10 @@ index 5bff313dbbb3049105874846d995883e827fbc00..05f0833f762436bf8f5f5875c7e3cfed // Order matters here, need to drop before setting to air so skulls can get their data net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS(); net.minecraft.world.level.block.Block block = iblockdata.getBlock(); -@@ -639,6 +646,7 @@ public class CraftBlock implements Block { +@@ -641,6 +648,7 @@ public class CraftBlock implements Block { // Modelled off EntityHuman#hasBlock if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) { - net.minecraft.world.level.block.Block.dropResources(iblockdata, world.getLevel(), position, world.getBlockEntity(position), null, nmsItem); + net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), position, this.world.getBlockEntity(position), null, nmsItem); + if (triggerEffect) world.levelEvent(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.world.level.block.Block.getId(block.defaultBlockState())); // Paper result = true; } diff --git a/patches/server-remapped/0402-Entity-Activation-Range-2.0.patch b/patches/server/0358-Entity-Activation-Range-2.0.patch similarity index 58% rename from patches/server-remapped/0402-Entity-Activation-Range-2.0.patch rename to patches/server/0358-Entity-Activation-Range-2.0.patch index ad4d829921..35cc61b42d 100644 --- a/patches/server-remapped/0402-Entity-Activation-Range-2.0.patch +++ b/patches/server/0358-Entity-Activation-Range-2.0.patch @@ -14,111 +14,120 @@ Adds flying monsters to control ghast and phantoms Adds villagers as separate config diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 40d7dbc4f1deda88d4a539b89d84b595217051b6..bf1bb1530037ebcacc8d5a491789909bddb8b697 100644 +index eabf8fa6e8802ebea8dbe124363bb085849af5d9..67b9daee8d7e55fdf2015e6616f393f176b1ca96 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -855,17 +855,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - ++TimingHistory.entityTicks; // Paper - timings - // Spigot start - co.aikar.timings.Timing timer; // Paper -- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { -- entity.tickCount++; -- timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings -+ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below -+ entity.ticksLived++; -+ timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings - entity.inactiveTick(); - } finally { timer.stopTiming(); } // Paper - return; -- } -+ }*/ // Paper - comment out EAR 2 - // Spigot end - // Paper start- timings -- TimingHistory.activatedEntityTicks++; -- timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); -+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); -+ timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper - try { - // Paper end - timings - entity.setPosAndOldPos(entity.getX(), entity.getY(), entity.getZ()); -@@ -879,12 +879,16 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return Registry.ENTITY_TYPE.getKey(entity.getType()).toString(); - }); - gameprofilerfiller.incrementCounter("tickNonPassenger"); -+ if (isActive) { // Paper - EAR 2 -+ TimingHistory.activatedEntityTicks++; // Paper - entity.tick(); - entity.postTick(); // CraftBukkit -+ } else { entity.inactiveTick(); } // Paper - EAR 2 - gameprofilerfiller.pop(); - } +@@ -2,7 +2,6 @@ package net.minecraft.server.level; - this.updateChunkPos(entity); -+ } finally { timer.stopTiming(); } // Paper - timings - if (entity.inChunk) { - Iterator iterator = entity.getPassengers().iterator(); - -@@ -894,7 +898,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.tickPassenger(entity, entity1); - } - } -- } finally { timer.stopTiming(); } // Paper - timings -+ //} finally { timer.stopTiming(); } // Paper - timings - move up + import com.google.common.annotations.VisibleForTesting; + import co.aikar.timings.TimingHistory; // Paper +-import co.aikar.timings.Timings; // Paper + import com.google.common.collect.Lists; + import com.mojang.datafixers.DataFixer; + import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +@@ -11,7 +10,6 @@ import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.longs.LongSets; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +-import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; + import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +@@ -123,7 +121,6 @@ import net.minecraft.world.level.chunk.LevelChunkSection; + import net.minecraft.world.level.chunk.storage.EntityStorage; + import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.level.dimension.end.EndDragonFight; +-import net.minecraft.world.level.entity.EntityAccess; + import net.minecraft.world.level.entity.EntityPersistentStorage; + import net.minecraft.world.level.entity.EntityTickList; + import net.minecraft.world.level.entity.EntityTypeTest; +@@ -888,17 +885,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + ++TimingHistory.entityTicks; // Paper - timings + // Spigot start + co.aikar.timings.Timing timer; // Paper +- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { ++ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below + entity.tickCount++; + timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings + entity.inactiveTick(); + } finally { timer.stopTiming(); } // Paper + return; +- } ++ }*/ // Paper - comment out EAR 2 + // Spigot end + // Paper start- timings +- TimingHistory.activatedEntityTicks++; +- timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); ++ timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper + try { + // Paper end - timings + entity.isInLava(); +@@ -909,9 +906,13 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return Registry.ENTITY_TYPE.getKey(entity.getType()).toString(); + }); + gameprofilerfiller.incrementCounter("tickNonPassenger"); ++ if (isActive) { // Paper - EAR 2 ++ TimingHistory.activatedEntityTicks++; + entity.tick(); + entity.postTick(); // CraftBukkit ++ } else { entity.inactiveTick(); } // Paper - EAR 2 + this.getProfiler().pop(); ++ } finally { timer.stopTiming(); } // Paper - timings + Iterator iterator = entity.getPassengers().iterator(); + while (iterator.hasNext()) { +@@ -920,13 +921,18 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.tickPassenger(entity, entity1); } + +- } finally { timer.stopTiming(); } // Paper - timings ++ // } finally { timer.stopTiming(); } // Paper - timings - move up + } -@@ -902,6 +906,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - public void tickPassenger(Entity vehicle, Entity passenger) { - if (!passenger.removed && passenger.getVehicle() == vehicle) { - if (passenger instanceof Player || this.getChunkSource().isEntityTickingChunk(passenger)) { + + private void tickPassenger(Entity vehicle, Entity passenger) { + if (!passenger.isRemoved() && passenger.getVehicle() == vehicle) { + if (passenger instanceof Player || this.entityTickList.contains(passenger)) { + // Paper - EAR 2 + final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); + co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper + try { + // Paper end - passenger.setPosAndOldPos(passenger.getX(), passenger.getY(), passenger.getZ()); - passenger.yRotO = passenger.yRot; - passenger.xRotO = passenger.xRot; -@@ -913,8 +922,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return Registry.ENTITY_TYPE.getKey(passenger.getType()).toString(); - }); - gameprofilerfiller.incrementCounter("tickPassenger"); -+ // Paper start - EAR 2 -+ if (isActive) { - passenger.rideTick(); - passenger.postTick(); // CraftBukkit -+ } else { -+ passenger.setDeltaMovement(Vec3.ZERO); -+ passenger.inactiveTick(); -+ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary -+ vehicle.syncPositionOf(passenger); -+ } -+ // Paper end - EAR 2 - gameprofilerfiller.pop(); + passenger.setOldPosAndRot(); + ++passenger.tickCount; + ProfilerFiller gameprofilerfiller = this.getProfiler(); +@@ -935,8 +941,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return Registry.ENTITY_TYPE.getKey(passenger.getType()).toString(); + }); + gameprofilerfiller.incrementCounter("tickPassenger"); ++ // Paper start - EAR 2 ++ if (isActive) { + passenger.rideTick(); + passenger.postTick(); // CraftBukkit ++ } else { ++ passenger.setDeltaMovement(Vec3.ZERO); ++ passenger.inactiveTick(); ++ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary ++ vehicle.positionRider(passenger); ++ } ++ // Paper end - EAR 2 + gameprofilerfiller.pop(); + Iterator iterator = passenger.getPassengers().iterator(); + +@@ -946,6 +961,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.tickPassenger(passenger, entity2); } -@@ -927,7 +945,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - - this.tickPassenger(passenger, entity2); - } -- } -+ } } finally { timer.stopTiming(); } // Paper - EAR2 timings - ++ } finally { timer.stopTiming(); }// Paper - EAR2 timings } } else { + passenger.stopRiding(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index af86c370c6f834514115a8e40659f5e1aaabec75..c6881a9a5da2caed77dea30e4906d2dd99a624c1 100644 +index a5159198003e43ce272ae73941d2be47d50eedc9..fffeba61e9af5c69876921b48241edb881af2a64 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -67,6 +67,7 @@ import net.minecraft.world.entity.animal.AbstractFish; - import net.minecraft.world.entity.animal.Animal; - import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.entity.player.Player; -+import net.minecraft.world.entity.vehicle.AbstractMinecart; - import net.minecraft.world.entity.vehicle.Boat; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.enchantment.EnchantmentHelper; -@@ -250,7 +251,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -275,7 +275,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public boolean noCulling; public boolean hasImpulse; public int portalCooldown; @@ -127,7 +136,7 @@ index af86c370c6f834514115a8e40659f5e1aaabec75..c6881a9a5da2caed77dea30e4906d2dd protected int portalTime; protected BlockPos portalEntrancePos; private boolean invulnerable; -@@ -274,6 +275,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -305,6 +305,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); public final boolean defaultActivationState; public long activatedTick = Integer.MIN_VALUE; @@ -135,51 +144,35 @@ index af86c370c6f834514115a8e40659f5e1aaabec75..c6881a9a5da2caed77dea30e4906d2dd public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one protected int numCollisions = 0; // Paper public void inactiveTick() { } -@@ -664,6 +666,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.setLocationFromBoundingbox(); +@@ -746,6 +747,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } else { - if (type == MoverType.PISTON) { + this.wasOnFire = this.isOnFire(); + if (movementType == MoverType.PISTON) { + this.activatedTick = MinecraftServer.currentTick + 20; // Paper movement = this.limitPistonMovement(movement); if (movement.equals(Vec3.ZERO)) { return; -@@ -676,6 +679,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -758,6 +760,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n this.stuckSpeedMultiplier = Vec3.ZERO; this.setDeltaMovement(Vec3.ZERO); } + // Paper start - ignore movement changes while inactive. -+ if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof AbstractMinecart) && movement == getDeltaMovement() && type == MoverType.SELF) { ++ if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof net.minecraft.world.entity.vehicle.AbstractMinecart) && movement == getDeltaMovement() && movementType == MoverType.SELF) { + setDeltaMovement(Vec3.ZERO); + this.level.getProfiler().pop(); + return; + } + // Paper end - movement = this.maybeBackOffFromEdge(movement, type); + movement = this.maybeBackOffFromEdge(movement, movementType); Vec3 vec3d1 = this.collide(movement); -@@ -2011,6 +2021,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - } - -+ public void syncPositionOf(Entity entity) { positionRider(entity); } // Paper - OBFHELPER - public void positionRider(Entity passenger) { - this.positionRider(passenger, Entity::setPos); - } -@@ -2821,6 +2832,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.stringUUID; - } - -+ public final boolean isPushedByWater() { return this.isPushedByFluid(); } // Paper - OBFHELPER - the below is not an obfhelper, don't use it! - public boolean isPushedByFluid() { - // Paper start - return this.pushedByWater(); diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 016fcc4ae20e1e48728a848be28633e624ae49a7..b84dab1043c56e2deb58aec8639226f98db165d1 100644 +index f48435dc344fb48feb48e2a141b394829058c5c4..bd1cc5e6fea4b9a171718c1249f652782b7ce13e 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -189,7 +189,7 @@ public abstract class LivingEntity extends Entity { +@@ -219,7 +219,7 @@ public abstract class LivingEntity extends Entity { protected float rotOffs; - protected int deathScore;protected int getKillCount() { return this.deathScore; } // Paper - OBFHELPER + protected int deathScore; public float lastHurt; - protected boolean jumping; + public boolean jumping; // Paper protected -> public @@ -187,10 +180,10 @@ index 016fcc4ae20e1e48728a848be28633e624ae49a7..b84dab1043c56e2deb58aec8639226f9 public float yya; public float zza; diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 29a2eeee9f2011ed6fcc44f19041f616decfdb38..40ab66f888f30a5506e3aa96a4b32485452e8978 100644 +index 32e8ae0d2a0f78af671a632c4d1be58a0b38a392..79e10f41b2993a02c4218551b06673f1848325a3 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -113,7 +113,7 @@ public abstract class Mob extends LivingEntity { +@@ -117,7 +117,7 @@ public abstract class Mob extends LivingEntity { public ResourceLocation lootTable; public long lootTableSeed; @Nullable @@ -199,7 +192,7 @@ index 29a2eeee9f2011ed6fcc44f19041f616decfdb38..40ab66f888f30a5506e3aa96a4b32485 private int delayedLeashHolderId; @Nullable private CompoundTag leashInfoTag; -@@ -194,6 +194,19 @@ public abstract class Mob extends LivingEntity { +@@ -198,6 +198,19 @@ public abstract class Mob extends LivingEntity { return this.lookControl; } @@ -231,51 +224,29 @@ index 920ae9af8985705a0ada7da5b7085a1ed8ca7f27..7c82d453388a27b69207d051dec316fc protected PathfinderMob(EntityType type, Level world) { super(type, world); -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -index d44a5b7f6cf62d5e9acacad25d47cb0d44761cfa..558dd72c47930f6993952467f83b5a54ead95d92 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -@@ -20,7 +20,10 @@ public abstract class Goal { - - public void start() {} - -- public void stop() {} -+ public void stop() { -+ onTaskReset(); // Paper -+ } -+ public void onTaskReset() {} // Paper - - public void tick() {} - diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -index 9066db5c9a76cfb9665bef77b36172f1ea6ba931..9bd2ee05a0de6678ad8933a8ffbe0ae66bd073b4 100644 +index 70e5b4446a8485b5995a0ba26af3a86d9b79bcc7..f29ace7b6a27a602102d37d43a6dd0571f218dfe 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -@@ -26,10 +26,11 @@ public class GoalSelector { - } - }; - private final Map lockedFlags = new EnumMap(Goal.Flag.class); -- private final Set availableGoals = Sets.newLinkedHashSet(); -+ private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER - private final Supplier profiler; +@@ -31,6 +31,7 @@ public class GoalSelector { private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); -- private int newGoalRate = 3; -+ private int newGoalRate = 3;private int getTickRate() { return newGoalRate; } // Paper - OBFHELPER -+ private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO + private int tickCount; + private int newGoalRate = 3; ++ private int curRate; public GoalSelector(Supplier profiler) { this.profiler = profiler; -@@ -39,6 +40,21 @@ public class GoalSelector { - this.availableGoals.add(new WrappedGoal(priority, goal)); +@@ -45,6 +46,20 @@ public class GoalSelector { + this.availableGoals.clear(); } + // Paper start + public boolean inactiveTick() { -+ incRate(); -+ return getCurRate() % getTickRate() == 0; ++ this.curRate++; ++ return this.curRate % this.newGoalRate == 0; + } + public boolean hasTasks() { -+ for (WrappedGoal task : getTasks()) { ++ for (WrappedGoal task : this.availableGoals) { + if (task.isRunning()) { + return true; + } @@ -283,26 +254,19 @@ index 9066db5c9a76cfb9665bef77b36172f1ea6ba931..9bd2ee05a0de6678ad8933a8ffbe0ae6 + return false; + } + // Paper end -+ public void removeGoal(Goal goal) { - this.availableGoals.stream().filter((pathfindergoalwrapped) -> { - return pathfindergoalwrapped.getGoal() == goal; + this.availableGoals.stream().filter((wrappedGoal) -> { + return wrappedGoal.getGoal() == goal; diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -index c8680e795deeb68e0662eac7c760a103d1c767b4..e83cb412d8549b86d0348a2aa37c79201a5930be 100644 +index 065d0752db0e3ae2a89d707aaa2145807f50ecad..c93805ae832d049ea13ca495b778ed52381b1f78 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -@@ -9,12 +9,12 @@ import net.minecraft.world.level.LevelReader; - - public abstract class MoveToBlockGoal extends Goal { - -- protected final PathfinderMob mob; -+ protected final PathfinderMob mob;public PathfinderMob getEntity() { return mob; } // Paper - OBFHELPER - public final double speedModifier; +@@ -14,7 +14,7 @@ public abstract class MoveToBlockGoal extends Goal { protected int nextStartTick; protected int tryTicks; private int maxStayTicks; -- protected BlockPos blockPos;public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER -+ protected BlockPos blockPos; public final BlockPos getTargetPosition() { return this.blockPos; } public void setTargetPosition(BlockPos pos) { this.blockPos = pos; getEntity().movingTarget = pos != BlockPos.ZERO ? pos : null; } // Paper - OBFHELPER +- protected BlockPos blockPos = BlockPos.ZERO; public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER ++ protected BlockPos blockPos = BlockPos.ZERO; public final BlockPos getTargetPosition() { return this.blockPos; } public void setTargetPosition(BlockPos pos) { this.blockPos = pos; mob.movingTarget = pos != BlockPos.ZERO ? pos : null; } // Paper - OBFHELPER private boolean reachedTarget; private final int searchRange; private final int verticalSearchRange; @@ -312,85 +276,44 @@ index c8680e795deeb68e0662eac7c760a103d1c767b4..e83cb412d8549b86d0348a2aa37c7920 } + // Paper start - activation range improvements + @Override -+ public void onTaskReset() { -+ super.onTaskReset(); ++ public void stop() { ++ super.stop(); + setTargetPosition(BlockPos.ZERO); + } + // Paper end public MoveToBlockGoal(PathfinderMob mob, double speed, int range, int maxYDifference) { - this.blockPos = BlockPos.ZERO; -@@ -111,6 +118,7 @@ public abstract class MoveToBlockGoal extends Goal { - blockposition_mutableblockposition.setWithOffset((Vec3i) blockposition, i1, k - 1, j1); - if (this.mob.isWithinRestriction((BlockPos) blockposition_mutableblockposition) && this.isValidTarget(this.mob.level, blockposition_mutableblockposition)) { - this.blockPos = blockposition_mutableblockposition; -+ setTargetPosition(blockposition_mutableblockposition.immutable()); // Paper + this.mob = mob; +@@ -109,6 +116,7 @@ public abstract class MoveToBlockGoal extends Goal { + mutableBlockPos.setWithOffset(blockPos, m, k - 1, n); + if (this.mob.isWithinRestriction(mutableBlockPos) && this.isValidTarget(this.mob.level, mutableBlockPos)) { + this.blockPos = mutableBlockPos; ++ setTargetPosition(mutableBlockPos.immutable()); // Paper return true; } } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -index 9921adf9292e0eff77515841d1b109a07b489367..81b4618a7979ee8dd25e1749c084de9262318ef4 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -@@ -64,6 +64,7 @@ public class WrappedGoal extends Goal { - return this.goal.getFlags(); - } - -+ public boolean isRunning() { return this.isRunning(); } // Paper - OBFHELPER - public boolean isRunning() { - return this.isRunning; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -index 5a7310bb48c1b8a72ad3c5d82c44fff8800995a2..a24af0600ad3e7d189581aa06a8e998f6a12e0fc 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -@@ -454,6 +454,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { - return this.caravanTail != null; - } - -+ public final boolean inCaravan() { return this.inCaravan(); } // Paper - OBFHELPER - public boolean inCaravan() { - return this.caravanHead != null; - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -index ae8f850baa14a4f4277da5b6fdb1e5ccb44c4f35..9eee68a5a84e121698d26bd54212a72c75e16251 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -70,10 +70,12 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan - return super.finalizeSpawn(world, difficulty, spawnReason, (SpawnGroupData) entityData, entityTag); - } - -+ public final int getUnhappy() { return getUnhappyCounter(); } // Paper - OBFHELPER - public int getUnhappyCounter() { - return (Integer) this.entityData.get(AbstractVillager.DATA_UNHAPPY_COUNTER); - } - -+ public final void setUnhappy(int i) { setUnhappyCounter(i); } // Paper - OBFHELPER - public void setUnhappyCounter(int ticks) { - this.entityData.set(AbstractVillager.DATA_UNHAPPY_COUNTER, ticks); - } diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index eed6265dc8275921a18fc5f4970ba131ba782132..4aa34320ef7d6c62ccb17734bfa61d406190b919 100644 +index 6a9e2105b2d9a4ee83c0a2516d5ef26dc3b99053..a35ce224b11b44567814207c3821d0cd4cdd9ec1 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -212,17 +212,29 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -227,17 +227,29 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @Override public void inactiveTick() { // SPIGOT-3874, SPIGOT-3894, SPIGOT-3846, SPIGOT-5286 :( - if (level.spigotConfig.tickInactiveVillagers && this.isEffectiveAi()) { - this.customServerAiStep(); + // Paper start -+ if (this.getUnhappy() > 0) { -+ this.setUnhappy(this.getUnhappy() - 1); - } ++ if (this.getUnhappyCounter() > 0) { ++ this.setUnhappyCounter(this.getUnhappyCounter() - 1); ++ } + if (this.isEffectiveAi()) { + if (level.spigotConfig.tickInactiveVillagers) { + this.customServerAiStep(); + } else { + this.mobTick(true); + } -+ } -+ doReputationTick(); + } ++ maybeDecayGossip(); + // Paper end + super.inactiveTick(); @@ -407,7 +330,7 @@ index eed6265dc8275921a18fc5f4970ba131ba782132..4aa34320ef7d6c62ccb17734bfa61d40 this.level.getProfiler().pop(); if (this.assignProfessionWhenSpawned) { this.assignProfessionWhenSpawned = false; -@@ -246,7 +258,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -261,7 +273,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler this.lastTradedPlayer = null; } @@ -416,7 +339,7 @@ index eed6265dc8275921a18fc5f4970ba131ba782132..4aa34320ef7d6c62ccb17734bfa61d40 Raid raid = ((ServerLevel) this.level).getRaidAt(this.blockPosition()); if (raid != null && raid.isActive() && !raid.isOver()) { -@@ -257,6 +269,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -272,6 +284,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.isTrading()) { this.stopTrading(); } @@ -424,19 +347,11 @@ index eed6265dc8275921a18fc5f4970ba131ba782132..4aa34320ef7d6c62ccb17734bfa61d40 super.customServerAiStep(); } -@@ -900,6 +913,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - } - } - -+ private void doReputationTick() { maybeDecayGossip(); } // Paper - OBFHELPER - private void maybeDecayGossip() { - long i = this.level.getGameTime(); - diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 6b79f8cd9258af47afa6efa7b1f97c3780be58b0..1d536d77518a70bdc1a23924aea99df1042b3cd5 100644 +index 9891e40972c1dc6bebe8ccec2bf82123dcdd7e94..ddcde88a8c8b748b4dc2583b4dfd0fb8ea9e201e 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -142,6 +142,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -153,6 +153,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public long ticksPerWaterSpawns; public long ticksPerWaterAmbientSpawns; public long ticksPerAmbientSpawns; @@ -450,17 +365,16 @@ index 6b79f8cd9258af47afa6efa7b1f97c3780be58b0..1d536d77518a70bdc1a23924aea99df1 public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3e4ac3eaf 100644 +index 84ce3d38d5decb4a2f9fae78e0ef5d715860dc7d..2ab585a018290996e7fa9ca6f3ad7d734cd7beaa 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -1,41 +1,55 @@ +@@ -1,39 +1,51 @@ package org.spigotmc; - import java.util.Collection; +-import java.util.Collection; +import net.minecraft.core.BlockPos; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.FlyingMob; import net.minecraft.world.entity.LightningBolt; @@ -478,7 +392,6 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 import net.minecraft.world.entity.boss.enderdragon.EndCrystal; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; import net.minecraft.world.entity.boss.wither.WitherBoss; -+import net.minecraft.world.entity.item.FallingBlockEntity; import net.minecraft.world.entity.item.PrimedTnt; import net.minecraft.world.entity.monster.Creeper; -import net.minecraft.world.entity.monster.Monster; @@ -497,7 +410,6 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 +import co.aikar.timings.MinecraftTimings; +import net.minecraft.world.entity.schedule.Activity; import net.minecraft.world.level.Level; - import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.phys.AABB; -import co.aikar.timings.MinecraftTimings; @@ -512,7 +424,7 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 MONSTER, ANIMAL, RAIDER, -@@ -43,6 +57,43 @@ public class ActivationRange +@@ -41,6 +53,43 @@ public class ActivationRange AABB boundingBox = new AABB( 0, 0, 0, 0, 0, 0 ); } @@ -556,7 +468,7 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 static AABB maxBB = new AABB( 0, 0, 0, 0, 0, 0 ); -@@ -55,10 +106,13 @@ public class ActivationRange +@@ -53,10 +102,13 @@ public class ActivationRange */ public static ActivationType initializeEntityActivationType(Entity entity) { @@ -571,7 +483,7 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 { return ActivationType.MONSTER; } else if ( entity instanceof PathfinderMob || entity instanceof AmbientCreature ) -@@ -79,10 +133,14 @@ public class ActivationRange +@@ -77,10 +129,14 @@ public class ActivationRange */ public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) { @@ -590,16 +502,7 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 || entity instanceof Player || entity instanceof ThrowableProjectile || entity instanceof EnderDragon -@@ -91,7 +149,7 @@ public class ActivationRange - || entity instanceof AbstractHurtingProjectile - || entity instanceof LightningBolt - || entity instanceof PrimedTnt -- || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks -+ || entity instanceof FallingBlockEntity // Paper - Always tick falling blocks - || entity instanceof EndCrystal - || entity instanceof FireworkRocketEntity - || entity instanceof ThrownTrident ) -@@ -115,10 +173,25 @@ public class ActivationRange +@@ -113,10 +169,25 @@ public class ActivationRange final int raiderActivationRange = world.spigotConfig.raiderActivationRange; final int animalActivationRange = world.spigotConfig.animalActivationRange; final int monsterActivationRange = world.spigotConfig.monsterActivationRange; @@ -625,7 +528,7 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); for ( Player player : world.players() ) -@@ -130,6 +203,11 @@ public class ActivationRange +@@ -128,6 +199,11 @@ public class ActivationRange ActivationType.RAIDER.boundingBox = player.getBoundingBox().inflate( raiderActivationRange, 256, raiderActivationRange ); ActivationType.ANIMAL.boundingBox = player.getBoundingBox().inflate( animalActivationRange, 256, animalActivationRange ); ActivationType.MONSTER.boundingBox = player.getBoundingBox().inflate( monsterActivationRange, 256, monsterActivationRange ); @@ -635,46 +538,9 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 + ActivationType.VILLAGER.boundingBox = player.getBoundingBox().inflate( villagerActivationRange, 256, waterActivationRange ); + // Paper end - int i = Mth.floor( maxBB.minX / 16.0D ); - int j = Mth.floor( maxBB.maxX / 16.0D ); -@@ -140,7 +218,7 @@ public class ActivationRange - { - for ( int j1 = k; j1 <= l; ++j1 ) - { -- LevelChunk chunk = (LevelChunk) world.getChunkIfLoadedImmediately( i1, j1 ); -+ LevelChunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper - if ( chunk != null ) - { - activateChunkEntities( chunk ); -@@ -158,19 +236,15 @@ public class ActivationRange - */ - private static void activateChunkEntities(LevelChunk chunk) - { -- for ( java.util.List slice : chunk.entitySlices ) -- { -- for ( Entity entity : (Collection) slice ) -+ // Paper start -+ Entity[] rawData = chunk.entities.getRawData(); -+ for (int i = 0; i < chunk.entities.size(); i++) { -+ Entity entity = rawData[i]; -+ //for ( Entity entity : (Collection) slice ) -+ // Paper end - { -- if ( MinecraftServer.currentTick > entity.activatedTick ) -- { -- if ( entity.defaultActivationState ) -- { -- entity.activatedTick = MinecraftServer.currentTick; -- continue; -- } -- if ( entity.activationType.boundingBox.intersects( entity.getBoundingBox() ) ) -- { -+ if (MinecraftServer.currentTick > entity.activatedTick) { -+ if (entity.defaultActivationState || entity.activationType.boundingBox.intersects(entity.getBoundingBox())) { // Paper - entity.activatedTick = MinecraftServer.currentTick; - } - } -@@ -185,56 +259,105 @@ public class ActivationRange + world.getEntities().get(maxBB, ActivationRange::activateEntity); + } +@@ -162,56 +238,105 @@ public class ActivationRange * @param entity * @return */ @@ -694,7 +560,7 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 + // Paper end // quick checks. - if ( entity.wasTouchingWater || entity.remainingFireTicks > 0 ) -+ if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByWater()) ) // Paper ++ if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByFluid()) ) // Paper { - return true; + return 100; // Paper @@ -780,7 +646,7 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 if (entity instanceof Creeper && ((Creeper) entity).isIgnited()) { // isExplosive - return true; + return 20; // Paper - } ++ } + // Paper start + if (entity instanceof Mob && ((Mob) entity).targetSelector.hasTasks() ) { + return 0; @@ -788,7 +654,7 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 + if (entity instanceof Pillager) { + Pillager pillager = (Pillager) entity; + // TODO:? -+ } + } + // Paper end } - return false; @@ -796,8 +662,8 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 } /** -@@ -249,8 +372,19 @@ public class ActivationRange - if ( !entity.inChunk || entity instanceof FireworkRocketEntity ) { +@@ -226,8 +351,19 @@ public class ActivationRange + if ( entity instanceof FireworkRocketEntity ) { return true; } + // Paper start - special case always immunities @@ -817,11 +683,11 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 // Should this entity tick? if ( !isActive ) -@@ -258,15 +392,19 @@ public class ActivationRange +@@ -235,15 +371,19 @@ public class ActivationRange if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) { // Check immunities every 20 ticks. -- if ( checkEntityImmunities( entity ) ) +- if ( ActivationRange.checkEntityImmunities( entity ) ) - { - // Triggered some sort of immunity, give 20 full ticks before we check again. - entity.activatedTick = MinecraftServer.currentTick + 20; @@ -837,13 +703,13 @@ index 61f180a7c95d83bb88c7df4910c498d9bdf6785a..8cbafad53d20366a36493f22160c4fa3 + } // Add a little performance juice to active entities. Skip 1/4 if not immune. -- } else if ( !entity.defaultActivationState && entity.tickCount % 4 == 0 && !checkEntityImmunities( entity ) ) -+ } else if (entity.tickCount % 4 == 0 && checkEntityImmunities( entity) < 0 ) // Paper +- } else if ( !entity.defaultActivationState && entity.tickCount % 4 == 0 && !ActivationRange.checkEntityImmunities( entity ) ) ++ } else if ( entity.tickCount % 4 == 0 && ActivationRange.checkEntityImmunities( entity ) < 0 ) // Paper { isActive = false; } diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 34ee684901906fc2ef5f0d09680d2686b813e52b..6b015c1f26facb4e82d75b252164dec05731ca6c 100644 +index 8e6eae7cc27f66faede9a3dc74571e1814df3652..308de0757c219c1e5fa8bde182343c4095301cde 100644 --- a/src/main/java/org/spigotmc/SpigotWorldConfig.java +++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java @@ -180,13 +180,59 @@ public class SpigotWorldConfig @@ -873,36 +739,36 @@ index 34ee684901906fc2ef5f0d09680d2686b813e52b..6b015c1f26facb4e82d75b252164dec0 public boolean tickInactiveVillagers = true; private void activationRange() { -+ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", animalActivationRange) != animalActivationRange; // Paper - animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange ); - monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange ); - raiderActivationRange = getInt( "entity-activation-range.raiders", raiderActivationRange ); - miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange ); ++ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", this.animalActivationRange) != this.animalActivationRange; // Paper + this.animalActivationRange = this.getInt( "entity-activation-range.animals", this.animalActivationRange ); + this.monsterActivationRange = this.getInt( "entity-activation-range.monsters", this.monsterActivationRange ); + this.raiderActivationRange = this.getInt( "entity-activation-range.raiders", this.raiderActivationRange ); + this.miscActivationRange = this.getInt( "entity-activation-range.misc", this.miscActivationRange ); + // Paper start -+ waterActivationRange = getInt( "entity-activation-range.water", waterActivationRange ); -+ villagerActivationRange = getInt( "entity-activation-range.villagers", hasAnimalsConfig ? animalActivationRange : villagerActivationRange ); -+ flyingMonsterActivationRange = getInt( "entity-activation-range.flying-monsters", flyingMonsterActivationRange ); ++ this.waterActivationRange = this.getInt( "entity-activation-range.water", this.waterActivationRange ); ++ this.villagerActivationRange = this.getInt( "entity-activation-range.villagers", hasAnimalsConfig ? this.animalActivationRange : this.villagerActivationRange ); ++ this.flyingMonsterActivationRange = this.getInt( "entity-activation-range.flying-monsters", this.flyingMonsterActivationRange ); + -+ wakeUpInactiveAnimals = getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", wakeUpInactiveAnimals); -+ wakeUpInactiveAnimalsEvery = getInt("entity-activation-range.wake-up-inactive.animals-every", wakeUpInactiveAnimalsEvery); -+ wakeUpInactiveAnimalsFor = getInt("entity-activation-range.wake-up-inactive.animals-for", wakeUpInactiveAnimalsFor); ++ this.wakeUpInactiveAnimals = this.getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", this.wakeUpInactiveAnimals); ++ this.wakeUpInactiveAnimalsEvery = this.getInt("entity-activation-range.wake-up-inactive.animals-every", this.wakeUpInactiveAnimalsEvery); ++ this.wakeUpInactiveAnimalsFor = this.getInt("entity-activation-range.wake-up-inactive.animals-for", this.wakeUpInactiveAnimalsFor); + -+ wakeUpInactiveMonsters = getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", wakeUpInactiveMonsters); -+ wakeUpInactiveMonstersEvery = getInt("entity-activation-range.wake-up-inactive.monsters-every", wakeUpInactiveMonstersEvery); -+ wakeUpInactiveMonstersFor = getInt("entity-activation-range.wake-up-inactive.monsters-for", wakeUpInactiveMonstersFor); ++ this.wakeUpInactiveMonsters = this.getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", this.wakeUpInactiveMonsters); ++ this.wakeUpInactiveMonstersEvery = this.getInt("entity-activation-range.wake-up-inactive.monsters-every", this.wakeUpInactiveMonstersEvery); ++ this.wakeUpInactiveMonstersFor = this.getInt("entity-activation-range.wake-up-inactive.monsters-for", this.wakeUpInactiveMonstersFor); + -+ wakeUpInactiveVillagers = getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", wakeUpInactiveVillagers); -+ wakeUpInactiveVillagersEvery = getInt("entity-activation-range.wake-up-inactive.villagers-every", wakeUpInactiveVillagersEvery); -+ wakeUpInactiveVillagersFor = getInt("entity-activation-range.wake-up-inactive.villagers-for", wakeUpInactiveVillagersFor); ++ this.wakeUpInactiveVillagers = this.getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", this.wakeUpInactiveVillagers); ++ this.wakeUpInactiveVillagersEvery = this.getInt("entity-activation-range.wake-up-inactive.villagers-every", this.wakeUpInactiveVillagersEvery); ++ this.wakeUpInactiveVillagersFor = this.getInt("entity-activation-range.wake-up-inactive.villagers-for", this.wakeUpInactiveVillagersFor); + -+ wakeUpInactiveFlying = getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", wakeUpInactiveFlying); -+ wakeUpInactiveFlyingEvery = getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", wakeUpInactiveFlyingEvery); -+ wakeUpInactiveFlyingFor = getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", wakeUpInactiveFlyingFor); ++ this.wakeUpInactiveFlying = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", this.wakeUpInactiveFlying); ++ this.wakeUpInactiveFlyingEvery = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", this.wakeUpInactiveFlyingEvery); ++ this.wakeUpInactiveFlyingFor = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", this.wakeUpInactiveFlyingFor); + -+ villagersWorkImmunityAfter = getInt( "entity-activation-range.villagers-work-immunity-after", villagersWorkImmunityAfter ); -+ villagersWorkImmunityFor = getInt( "entity-activation-range.villagers-work-immunity-for", villagersWorkImmunityFor ); -+ villagersActiveForPanic = getBoolean( "entity-activation-range.villagers-active-for-panic", villagersActiveForPanic ); ++ this.villagersWorkImmunityAfter = this.getInt( "entity-activation-range.villagers-work-immunity-after", this.villagersWorkImmunityAfter ); ++ this.villagersWorkImmunityFor = this.getInt( "entity-activation-range.villagers-work-immunity-for", this.villagersWorkImmunityFor ); ++ this.villagersActiveForPanic = this.getBoolean( "entity-activation-range.villagers-active-for-panic", this.villagersActiveForPanic ); + // Paper end - tickInactiveVillagers = getBoolean( "entity-activation-range.tick-inactive-villagers", tickInactiveVillagers ); - log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Ra " + raiderActivationRange + " / Mi " + miscActivationRange + " / Tiv " + tickInactiveVillagers ); + this.tickInactiveVillagers = this.getBoolean( "entity-activation-range.tick-inactive-villagers", this.tickInactiveVillagers ); + this.log( "Entity Activation Range: An " + this.animalActivationRange + " / Mo " + this.monsterActivationRange + " / Ra " + this.raiderActivationRange + " / Mi " + this.miscActivationRange + " / Tiv " + this.tickInactiveVillagers ); } diff --git a/patches/server-remapped/0429-Increase-Light-Queue-Size.patch b/patches/server/0359-Increase-Light-Queue-Size.patch similarity index 78% rename from patches/server-remapped/0429-Increase-Light-Queue-Size.patch rename to patches/server/0359-Increase-Light-Queue-Size.patch index f5ba659507..980579a32c 100644 --- a/patches/server-remapped/0429-Increase-Light-Queue-Size.patch +++ b/patches/server/0359-Increase-Light-Queue-Size.patch @@ -14,12 +14,12 @@ light engine on shutdown... The queue size only puts a cap on max loss, doesn't solve that problem. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1..cd248eb6be663e8be33f2c3c6b06b77b6d5753a4 100644 +index 041efecbfcd54384d15ebf771cdfa0e711483997..e29566cad2647da4d9288e912188b57f00e8dd0c 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -620,4 +620,9 @@ public class PaperWorldConfig { - private void zombieVillagerInfectionChance() { - zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); +@@ -440,5 +440,10 @@ public class PaperWorldConfig { + disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); + log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); } + + public int lightQueueSize = 20; @@ -27,11 +27,12 @@ index 6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1..cd248eb6be663e8be33f2c3c6b06b77b + lightQueueSize = getInt("light-queue-size", lightQueueSize); + } } + diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e33189dc8375a3034910087654607fb531061636..11c6e8ce10c53dcb639145fbda32c5426eb6b3d9 100644 +index 312be2221e1acc44aaf6936533b0eb968f796dc6..494a3afaaa0e3496d30e8d97edbab62b21610dfe 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -775,7 +775,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop (max 5) to automatically fix all light data in the chunks. diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index ff718bc7f521575e6a670e17fcf59a2d30841705..528c860fc0c04431e0ebb2ae6bc96bf9c2d04789 100644 +index 71ffa66973d8994e2a480435ac1ada3fe61600a4..7b5afc5d34b78e6404c1a5c6bb823d9589471f13 100644 --- a/src/main/java/com/destroystokyo/paper/PaperCommand.java +++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -11,16 +11,20 @@ import com.google.common.collect.Maps; - import com.google.gson.JsonObject; - import com.google.gson.internal.Streams; - import com.google.gson.stream.JsonWriter; -+import net.minecraft.core.BlockPos; -+import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; +@@ -10,7 +10,8 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; +-import net.minecraft.world.entity.Entity; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.level.ThreadedLevelLightEngine; - import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.ChunkPos; --import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.chunk.LevelChunk; - import org.apache.commons.lang3.tuple.MutablePair; - import org.apache.commons.lang3.tuple.Pair; - import org.bukkit.Bukkit; -@@ -31,6 +35,7 @@ import org.bukkit.command.Command; + import net.minecraft.resources.ResourceLocation; +@@ -25,15 +26,18 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftWorld; @@ -40,8 +28,6 @@ index ff718bc7f521575e6a670e17fcf59a2d30841705..528c860fc0c04431e0ebb2ae6bc96bf9 import org.bukkit.entity.Player; import java.io.File; -@@ -39,10 +44,12 @@ import java.io.PrintStream; - import java.io.StringWriter; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.ArrayDeque; @@ -53,18 +39,18 @@ index ff718bc7f521575e6a670e17fcf59a2d30841705..528c860fc0c04431e0ebb2ae6bc96bf9 import java.util.Iterator; import java.util.List; import java.util.Locale; -@@ -52,7 +59,7 @@ import java.util.stream.Collectors; +@@ -43,7 +47,7 @@ import java.util.stream.Collectors; public class PaperCommand extends Command { private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "fixlight").build(); public PaperCommand(String name) { super(name); -@@ -173,6 +180,9 @@ public class PaperCommand extends Command { - case "syncloadinfo": - this.doSyncLoadInfo(sender, args); +@@ -158,6 +162,9 @@ public class PaperCommand extends Command { + case "chunkinfo": + doChunkInfo(sender, args); break; + case "fixlight": + this.doFixLight(sender, args); @@ -72,10 +58,10 @@ index ff718bc7f521575e6a670e17fcf59a2d30841705..528c860fc0c04431e0ebb2ae6bc96bf9 case "ver": if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) case "version": -@@ -190,6 +200,77 @@ public class PaperCommand extends Command { - return true; - } +@@ -413,4 +420,74 @@ public class PaperCommand extends Command { + Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete."); + } + private void doFixLight(CommandSender sender, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage("Only players can use this command"); @@ -97,7 +83,7 @@ index ff718bc7f521575e6a670e17fcf59a2d30841705..528c860fc0c04431e0ebb2ae6bc96bf9 + ServerLevel world = (ServerLevel) handle.level; + ThreadedLevelLightEngine lightengine = world.getChunkSource().getLightEngine(); + -+ BlockPos center = MCUtil.toBlockPosition(player.getLocation()); ++ net.minecraft.core.BlockPos center = MCUtil.toBlockPosition(player.getLocation()); + Deque queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius)); + updateLight(sender, world, lightengine, queue); + } @@ -114,7 +100,7 @@ index ff718bc7f521575e6a670e17fcf59a2d30841705..528c860fc0c04431e0ebb2ae6bc96bf9 + updateLight(sender, world, lightengine, queue); + return; + } -+ LevelChunk chunk = (LevelChunk) either.left().orElse(null); ++ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); + if (chunk == null) { + updateLight(sender, world, lightengine, queue); + return; @@ -126,7 +112,7 @@ index ff718bc7f521575e6a670e17fcf59a2d30841705..528c860fc0c04431e0ebb2ae6bc96bf9 + for (int y = 0; y < world.getHeight(); y++) { + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { -+ BlockPos pos = new BlockPos(cx + x, y, cz + z); ++ net.minecraft.core.BlockPos pos = new net.minecraft.core.BlockPos(cx + x, y, cz + z); + lightengine.checkBlock(pos); + } + } @@ -136,7 +122,7 @@ index ff718bc7f521575e6a670e17fcf59a2d30841705..528c860fc0c04431e0ebb2ae6bc96bf9 + if (visibleChunk != null) { + world.getChunkSource().chunkMap.addLightTask(visibleChunk, () -> { + MinecraftServer.getServer().processQueue.add(() -> { -+ visibleChunk.sendPacketToTrackedPlayers(new ClientboundLightUpdatePacket(chunk.getPos(), lightengine, true), false); ++ visibleChunk.broadcast(new net.minecraft.network.protocol.game.ClientboundLightUpdatePacket(chunk.getPos(), lightengine, null, null, true), false); + updateLight(sender, world, lightengine, queue); + }); + }); @@ -146,37 +132,48 @@ index ff718bc7f521575e6a670e17fcf59a2d30841705..528c860fc0c04431e0ebb2ae6bc96bf9 + lightengine.setTaskPerBatch(world.paperConfig.lightQueueSize); + }, MinecraftServer.getServer()); + } -+ - private void doSyncLoadInfo(CommandSender sender, String[] args) { - if (!SyncLoadFinder.ENABLED) { - sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); + } diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 9ebcfca10071cc42d4f1df02c25de5042c065f38..d907872d80f840b343419f49a6708082da6f921b 100644 +index 56e292e6550b19d0cae9ebad369da730ca1cabd8..3653ec6f93d627092e63cede51f4db2e12b10613 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -349,6 +349,7 @@ public class ChunkHolder { +@@ -312,7 +312,7 @@ public class ChunkHolder { } -+ public void sendPacketToTrackedPlayers(Packet packet, boolean flag) { broadcast(packet, flag); } // Paper - OBFHELPER - private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { - // Paper start - per player view distance - // there can be potential desync with player's last mapped section and the view distance map, so use the +- private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { ++ public void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { // Paper - private -> public + this.playerProvider.getPlayers(this.pos, onlyOnWatchDistanceEdge).forEach((entityplayer) -> { + entityplayer.connection.send(packet); + }); diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 6b51a082cf42bc3ffc550614e385d3956c5f2efb..67f748d5955453ba4873b0c9bb741b5bfe52d655 100644 +index 5473b22d21ea981f245f4826c4d47295890f88ef..480c361c919bbfbebacf9ac94418eac5ed38e233 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -344,11 +344,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - ProcessorHandle mailbox = ProcessorHandle.of("main", mainThreadExecutor::tell); +@@ -123,6 +123,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private final ChunkTaskPriorityQueueSorter queueSorter; + private final ProcessorHandle> worldgenMailbox; + private final ProcessorHandle> mainThreadMailbox; ++ // Paper start ++ final ProcessorHandle> mailboxLight; ++ public void addLightTask(ChunkHolder playerchunk, Runnable run) { ++ this.mailboxLight.tell(ChunkTaskPriorityQueueSorter.message(playerchunk, run)); ++ } ++ // Paper end + public final ChunkProgressListener progressListener; + private final ChunkStatusUpdateListener chunkStatusListener; + public final ChunkMap.ChunkDistanceManager distanceManager; +@@ -199,11 +205,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.progressListener = worldGenerationProgressListener; -- ProcessorMailbox threadedmailbox1 = ProcessorMailbox.create(workerExecutor, "light"); -+ ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(workerExecutor, "light"); // Paper + this.chunkStatusListener = chunkStatusChangeListener; +- ProcessorMailbox threadedmailbox1 = ProcessorMailbox.create(executor, "light"); ++ ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(executor, "light"); // Paper - this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), workerExecutor, Integer.MAX_VALUE); + this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE); this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); + this.mailboxLight = this.queueSorter.getProcessor(lightthreaded, false);// Paper this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); - this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper - this.overworldDataStorage = supplier; + this.distanceManager = new ChunkMap.ChunkDistanceManager(executor, mainThreadExecutor); + this.overworldDataStorage = persistentStateManagerFactory; diff --git a/patches/server-remapped/0470-No-Tick-view-distance-implementation.patch b/patches/server/0361-No-Tick-view-distance-implementation.patch similarity index 68% rename from patches/server-remapped/0470-No-Tick-view-distance-implementation.patch rename to patches/server/0361-No-Tick-view-distance-implementation.patch index 9fee42c2d0..6fdb3036eb 100644 --- a/patches/server-remapped/0470-No-Tick-view-distance-implementation.patch +++ b/patches/server/0361-No-Tick-view-distance-implementation.patch @@ -9,26 +9,26 @@ Per-Player is absent due to difficulty of maintaining the diff required to make it happen. diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index 5bcf9cefc29eb20e2cfbfb49e2b2662ec394a87e..a696474b4bd0e32a26dadfbc1257580ee596f0c0 100644 +index f27fadc15cb7f5c782e45885ec6a5a69963beade..2ff4d4921e2076abf415bd3c8f5173ecd6222168 100644 --- a/src/main/java/co/aikar/timings/TimingsExport.java +++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -156,7 +156,8 @@ public class TimingsExport extends Thread { +@@ -152,7 +152,8 @@ public class TimingsExport extends Thread { pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { return pair(rule, world.getWorld().getGameRuleValue(rule)); })), -- pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) -+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()), -+ pair("notick-viewdistance", world.getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance()) +- pair("ticking-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance()) ++ pair("ticking-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance()), ++ pair("notick-viewdistance", world.getChunkSource().chunkMap.getEffectiveNoTickViewDistance()) )); })); diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 46ac6d91422423f1e03b86d3efa3241f2599000d..6463d3e4837d032a35654a035f42b8a805e0e286 100644 +index e29566cad2647da4d9288e912188b57f00e8dd0c..3cd8895adecd345c3bdfb8b5e3e9fdf0ef9097db 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -632,4 +632,9 @@ public class PaperWorldConfig { - phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); - phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); +@@ -445,5 +445,10 @@ public class PaperWorldConfig { + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); } + + public int noTickViewDistance; @@ -36,11 +36,12 @@ index 46ac6d91422423f1e03b86d3efa3241f2599000d..6463d3e4837d032a35654a035f42b8a8 + this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); + } } + diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 9abef8550a89df5e15ac28de1a5549d064f29122..d18497a33dc53f6b465e659967bf8c98731c46c0 100644 +index bb0a07a280c7d4885165e9d6488e7741aaa7b47c..9c88426ab1275ee5fb6e28be8b213533dc4ab859 100644 --- a/src/main/java/net/minecraft/server/MCUtil.java +++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -638,7 +638,8 @@ public final class MCUtil { +@@ -636,7 +636,8 @@ public final class MCUtil { }); worldData.addProperty("name", world.getWorld().getName()); @@ -51,13 +52,13 @@ index 9abef8550a89df5e15ac28de1a5549d064f29122..d18497a33dc53f6b465e659967bf8c98 worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); worldData.addProperty("visible-chunk-count", visibleChunks.size()); diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 0147798c0285f64b8d767dfb2709d92f66ac72ef..9ebcfca10071cc42d4f1df02c25de5042c065f38 100644 +index 3653ec6f93d627092e63cede51f4db2e12b10613..995d7977233f0d7683c00a75c3833f9a1eba7f92 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -81,6 +81,18 @@ public class ChunkHolder { - } - // Paper end - optimise isOutsideOfRange +@@ -75,6 +75,17 @@ public class ChunkHolder { + boolean isUpdateQueued = false; // Paper + private final ChunkMap chunkMap; // Paper + // Paper start - no-tick view distance + public final LevelChunk getSendingChunk() { + // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used @@ -69,32 +70,31 @@ index 0147798c0285f64b8d767dfb2709d92f66ac72ef..9ebcfca10071cc42d4f1df02c25de504 + return null; + } + // Paper end - no-tick view distance -+ - public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); - this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; -@@ -240,7 +252,7 @@ public class ChunkHolder { +@@ -207,7 +218,7 @@ public class ChunkHolder { } - public void blockChanged(BlockPos blockposition) { + public void blockChanged(BlockPos pos) { - LevelChunk chunk = this.getTickingChunk(); + LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance if (chunk != null) { - byte b0 = (byte) SectionPos.blockToSectionCoord(blockposition.getY()); -@@ -256,7 +268,7 @@ public class ChunkHolder { + int i = this.levelHeightAccessor.getSectionIndex(pos.getY()); +@@ -223,7 +234,7 @@ public class ChunkHolder { } - public void sectionLightChanged(LightLayer type, int y) { + public void sectionLightChanged(LightLayer lightType, int y) { - LevelChunk chunk = this.getTickingChunk(); + LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance if (chunk != null) { chunk.setUnsaved(true); -@@ -338,9 +350,48 @@ public class ChunkHolder { +@@ -313,9 +324,48 @@ public class ChunkHolder { } - private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { + public void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { // Paper - private -> public - this.playerProvider.getPlayers(this.pos, onlyOnWatchDistanceEdge).forEach((entityplayer) -> { - entityplayer.connection.send(packet); - }); @@ -119,8 +119,8 @@ index 0147798c0285f64b8d767dfb2709d92f66ac72ef..9ebcfca10071cc42d4f1df02c25de504 + int viewDistance = viewDistanceMap.getLastViewDistance(player); + long lastPosition = viewDistanceMap.getLastCoordinate(player); + -+ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - this.pos.x); -+ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - this.pos.z); ++ int distX = Math.abs(net.minecraft.server.MCUtil.getCoordinateX(lastPosition) - this.pos.x); ++ int distZ = Math.abs(net.minecraft.server.MCUtil.getCoordinateZ(lastPosition) - this.pos.z); + + if (Math.max(distX, distZ) == viewDistance) { + player.connection.send(packet); @@ -144,43 +144,22 @@ index 0147798c0285f64b8d767dfb2709d92f66ac72ef..9ebcfca10071cc42d4f1df02c25de504 public CompletableFuture> getOrScheduleFuture(ChunkStatus targetStatus, ChunkMap chunkStorage) { diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d3956c5f2efb 100644 +index 480c361c919bbfbebacf9ac94418eac5ed38e233..fdf5d8ede4b01e399272ddebfbd49258b166f00b 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -57,12 +57,14 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; - import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; - import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; -+import net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket; - import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; - import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; - import net.minecraft.network.protocol.game.DebugPackets; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.progress.ChunkProgressListener; -+import net.minecraft.server.network.ServerGamePacketListenerImpl; - import net.minecraft.util.CsvOutput; - import net.minecraft.util.Mth; - import net.minecraft.util.profiling.ProfilerFiller; -@@ -144,7 +146,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -122,7 +122,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider private boolean modified; private final ChunkTaskPriorityQueueSorter queueSorter; private final ProcessorHandle> worldgenMailbox; - private final ProcessorHandle> mainThreadMailbox; + public final ProcessorHandle> mainThreadMailbox; // Paper - private -> public -+ // Paper start -+ final ProcessorHandle> mailboxLight; -+ public void addLightTask(ChunkHolder playerchunk, Runnable run) { -+ this.mailboxLight.tell(ChunkTaskPriorityQueueSorter.message(playerchunk, run)); -+ } -+ // Paper end - public final ChunkProgressListener progressListener; - public final ChunkMap.ChunkDistanceManager distanceManager; public final DistanceManager getChunkDistanceManager() { return this.distanceManager; } // Paper - OBFHELPER - private final AtomicInteger tickingGenerated; -@@ -219,6 +227,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick - public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; - // Paper end - optimise PlayerChunkMap#isOutsideRange + // Paper start + final ProcessorHandle> mailboxLight; + public void addLightTask(ChunkHolder playerchunk, Runnable run) { +@@ -164,21 +164,68 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + // Paper start - distance maps + private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); + // Paper start - no-tick view distance + int noTickViewDistance; + public final int getRawNoTickViewDistance() { @@ -200,15 +179,13 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 void addPlayerToDistanceMaps(ServerPlayer player) { int chunkX = MCUtil.getChunkCoordinate(player.getX()); -@@ -235,6 +259,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper start - optimise PlayerChunkMap#isOutsideRange - this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); - // Paper end - optimise PlayerChunkMap#isOutsideRange + int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); + // Note: players need to be explicitly added to distance maps before they can be updated + // Paper start - no-tick view distance + int effectiveTickViewDistance = this.getEffectiveViewDistance(); + int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); + -+ if (!this.cannotLoadChunks(player)) { ++ if (!this.skipPlayer(player)) { + this.playerViewDistanceTickMap.add(player, chunkX, chunkZ, effectiveTickViewDistance); + this.playerViewDistanceNoTickMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) + } @@ -220,10 +197,7 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 } void removePlayerFromDistanceMaps(ServerPlayer player) { -@@ -247,6 +284,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.playerMobSpawnMap.remove(player); - this.playerChunkTickRangeMap.remove(player); - // Paper end - optimise PlayerChunkMap#isOutsideRange + + // Paper start - no-tick view distance + this.playerViewDistanceBroadcastMap.remove(player); + this.playerViewDistanceTickMap.remove(player); @@ -232,15 +206,14 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 } void updateMaps(ServerPlayer player) { -@@ -264,6 +306,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper start - optimise PlayerChunkMap#isOutsideRange - this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); - // Paper end - optimise PlayerChunkMap#isOutsideRange + int chunkX = MCUtil.getChunkCoordinate(player.getX()); + int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); + // Note: players need to be explicitly added to distance maps before they can be updated + // Paper start - no-tick view distance + int effectiveTickViewDistance = this.getEffectiveViewDistance(); + int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); + -+ if (!this.cannotLoadChunks(player)) { ++ if (!this.skipPlayer(player)) { + this.playerViewDistanceTickMap.update(player, chunkX, chunkZ, effectiveTickViewDistance); + this.playerViewDistanceNoTickMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) + } @@ -252,10 +225,10 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 } // Paper end -@@ -371,6 +426,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - }); - // Paper end - optimise PlayerChunkMap#isOutsideRange +@@ -216,6 +263,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.overworldDataStorage = persistentStateManagerFactory; + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world); + this.setViewDistance(viewDistance); + // Paper start - no-tick view distance + this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); + this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, @@ -297,10 +270,10 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 + // Paper end - no-tick view distance } - public void updatePlayerMobTypeMap(Entity entity) { -@@ -1199,15 +1293,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { +@@ -863,14 +949,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider completablefuture1.thenAcceptAsync((either) -> { - either.mapLeft((chunk) -> { + either.ifLeft((chunk) -> { this.tickingGenerated.getAndIncrement(); - Packet[] apacket = new Packet[2]; - @@ -308,7 +281,6 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 - this.playerLoadedChunk(entityplayer, apacket, chunk); - }); + // Paper - no-tick view distance - moved to Chunk neighbour update - return Either.left(chunk); }); }, (runnable) -> { - this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); @@ -316,7 +288,7 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 }); return completablefuture1; } -@@ -1302,32 +1392,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -962,28 +1044,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } } @@ -341,7 +313,7 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 + } - this.getPlayers(chunkcoordintpair, false).forEach((entityplayer) -> { -- int l = checkerboardDistance(chunkcoordintpair, entityplayer, true); +- int l = ChunkMap.checkerboardDistance(chunkcoordintpair, entityplayer, true); - boolean flag = l <= k; - boolean flag1 = l <= this.viewDistance; + // Paper start - no-tick view distance @@ -356,21 +328,17 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 + + if (this.level != null && this.level.players != null) { // this can be called from constructor, where these aren't set + for (ServerPlayer player : this.level.players) { -+ ServerGamePacketListenerImpl connection = player.connection; ++ net.minecraft.server.network.ServerGamePacketListenerImpl connection = player.connection; + if (connection != null) { + // moved in from PlayerList -+ connection.send(new ClientboundSetChunkCacheRadiusPacket(loadViewDistance)); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket(loadViewDistance)); + } + this.updateMaps(player); ++ // Paper end - no-tick view distance } } -- - } -+ // Paper end - no-tick view distance - protected void updateChunkTracking(ServerPlayer player, ChunkPos pos, Packet[] packets, boolean withinMaxWatchDistance, boolean withinViewDistance) { - if (player.level == this.level) { -@@ -1335,7 +1431,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -995,7 +1084,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.toLong()); if (playerchunk != null) { @@ -379,15 +347,7 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 if (chunk != null) { this.playerLoadedChunk(player, packets, chunk); -@@ -1596,6 +1692,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - // Paper end - optimise isOutsideOfRange - -+ private boolean cannotLoadChunks(ServerPlayer entityplayer) { return this.skipPlayer(entityplayer); } // Paper - OBFHELPER - private boolean skipPlayer(ServerPlayer player) { - return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); - } -@@ -1623,13 +1720,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1202,13 +1291,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.removePlayerFromDistanceMaps(player); // Paper - distance maps } @@ -402,16 +362,16 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 } -@@ -1637,7 +1728,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - SectionPos sectionposition = SectionPos.of((Entity) entityplayer); +@@ -1216,7 +1299,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + SectionPos sectionposition = SectionPos.of((Entity) player); - entityplayer.setLastSectionPos(sectionposition); -- entityplayer.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); -+ // Paper - distance map handles this now + player.setLastSectionPos(sectionposition); +- player.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); ++ // player.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); // Paper - distance map handles this now return sectionposition; } -@@ -1682,6 +1773,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1271,6 +1354,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider int k1; int l1; @@ -419,65 +379,26 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 if (Math.abs(i1 - i) <= this.viewDistance * 2 && Math.abs(j1 - j) <= this.viewDistance * 2) { k1 = Math.min(i, i1) - this.viewDistance; l1 = Math.min(j, j1) - this.viewDistance; -@@ -1690,36 +1782,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - for (int k2 = k1; k2 <= i2; ++k2) { - for (int l2 = l1; l2 <= j2; ++l2) { -- ChunkPos chunkcoordintpair = new ChunkPos(k2, l2); -- boolean flag3 = checkerboardDistance(chunkcoordintpair, i1, j1) <= this.viewDistance; -- boolean flag4 = checkerboardDistance(chunkcoordintpair, i, j) <= this.viewDistance; -+ ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k2, l2); -+ boolean flag3 = a(chunkcoordintpair, i1, j1) <= this.viewDistance; -+ boolean flag4 = a(chunkcoordintpair, i, j) <= this.viewDistance; - -- this.updateChunkTracking(player, chunkcoordintpair, new Packet[2], flag3, flag4); -+ this.sendChunk(entityplayer, chunkcoordintpair, new Packet[2], flag3, flag4); +@@ -1309,6 +1393,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } } - } else { -- ChunkPos chunkcoordintpair1; -+ ChunkCoordIntPair chunkcoordintpair1; - boolean flag5; - boolean flag6; - - for (k1 = i1 - this.viewDistance; k1 <= i1 + this.viewDistance; ++k1) { - for (l1 = j1 - this.viewDistance; l1 <= j1 + this.viewDistance; ++l1) { -- chunkcoordintpair1 = new ChunkPos(k1, l1); -+ chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1); - flag5 = true; - flag6 = false; -- this.updateChunkTracking(player, chunkcoordintpair1, new Packet[2], true, false); -+ this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], true, false); - } - } - - for (k1 = i - this.viewDistance; k1 <= i + this.viewDistance; ++k1) { - for (l1 = j - this.viewDistance; l1 <= j + this.viewDistance; ++l1) { -- chunkcoordintpair1 = new ChunkPos(k1, l1); -+ chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1); - flag5 = false; - flag6 = true; -- this.updateChunkTracking(player, chunkcoordintpair1, new Packet[2], false, true); -+ this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], false, true); - } - } -- } -+ }*/ // Paper end - replaced by distance map + } ++ */ // Paper end - replaced by distance map this.updateMaps(player); // Paper - distance maps -@@ -1727,11 +1819,46 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1316,11 +1401,46 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @Override public Stream getPlayers(ChunkPos chunkPos, boolean onlyOnWatchDistanceEdge) { -- return this.playerMap.a(chunkPos.toLong()).filter((entityplayer) -> { -- int i = b(chunkcoordintpair, entityplayer, true); +- return this.playerMap.getPlayers(chunkPos.toLong()).filter((entityplayer) -> { +- int i = ChunkMap.checkerboardDistance(chunkPos, entityplayer, true); + // Paper start - per player view distance + // there can be potential desync with player's last mapped section and the view distance map, so use the + // view distance map here. + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = this.playerViewDistanceBroadcastMap.getObjectsInRange(chunkPos); -- return i > this.viewDistance ? false : !flag || i == this.viewDistance; +- return i > this.viewDistance ? false : !onlyOnWatchDistanceEdge || i == this.viewDistance; - }); + if (inRange == null) { + return Stream.empty(); @@ -516,15 +437,15 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 + // Paper end - per player view distance } - public void addEntity(Entity entity) { // Paper - protected -> public -@@ -1889,7 +2016,48 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + protected void addEntity(Entity entity) { +@@ -1442,7 +1562,48 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } -- private final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER +- private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { + // Paper start + private static int getLightMask(final LevelChunk chunk) { -+ final ChunkSection[] chunkSections = chunk.getSections(); ++ final net.minecraft.world.level.chunk.LevelChunkSection[] chunkSections = chunk.getSections(); + int mask = 0; + + for (int i = 0; i < chunkSections.length; ++i) { @@ -535,7 +456,7 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 +Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. + + */ -+ mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; ++ mask |= (net.minecraft.world.level.chunk.LevelChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; + } + + return mask; @@ -563,24 +484,15 @@ index 56ca469bf930bcced88efdafc78f464c756a5be9..6b51a082cf42bc3ffc550614e385d395 + } + // Paper end + -+ public final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { ++ public void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { // Paper - private -> public if (packets[0] == null) { - packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass -@@ -2075,7 +2243,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - ChunkPos chunkcoordintpair = new ChunkPos(this.entity.xChunk, this.entity.zChunk); - ChunkHolder playerchunk = ChunkMap.this.getVisibleChunkIfPresent(chunkcoordintpair.toLong()); - -- if (playerchunk != null && playerchunk.getTickingChunk() != null) { -+ if (playerchunk != null && playerchunk.getSendingChunk() != null) { // Paper - no-tick view distance - flag1 = ChunkMap.checkerboardDistance(chunkcoordintpair, player, false) <= ChunkMap.this.viewDistance; - } - } + packets[0] = new ClientboundLevelChunkPacket(chunk); + packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, (BitSet) null, (BitSet) null, true); diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index 91c672531087430c47365657a3219ab5980d3467..c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e 100644 +index 45c7ebe67019cdbe88b6617a95d5c40d3a68286c..38eebda226e007c8910e04f502ce218cdfe1d456 100644 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java +++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -269,8 +269,8 @@ public abstract class DistanceManager { +@@ -275,8 +275,8 @@ public abstract class DistanceManager { return s; } @@ -591,7 +503,7 @@ index 91c672531087430c47365657a3219ab5980d3467..c9b4025f6c3d1be7bca2ff7337dd86e3 } public int getNaturalSpawnChunkCount() { -@@ -388,7 +388,7 @@ public abstract class DistanceManager { +@@ -503,7 +503,7 @@ public abstract class DistanceManager { private void onLevelChange(long pos, int distance, boolean oldWithinViewDistance, boolean withinViewDistance) { if (oldWithinViewDistance != withinViewDistance) { @@ -601,23 +513,22 @@ index 91c672531087430c47365657a3219ab5980d3467..c9b4025f6c3d1be7bca2ff7337dd86e3 if (withinViewDistance) { DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 95f1f4727a8e2000931e6f36b862e3ad28334a69..8e4cef60b760be385df81a74834d026f856a78c5 100644 +index 4fef4c0240be90ddcb9640f5719e292d2d5dbdf8..bffc897cb88a54c36432c98264f3416051aeab17 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -249,6 +249,8 @@ public class ServerPlayer extends Player implements ContainerListener { - - double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks +@@ -241,6 +241,7 @@ public class ServerPlayer extends Player { + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + boolean needsChunkCenterUpdate; // Paper - no-tick view distance -+ - public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { - super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); - this.respawnDimension = Level.OVERWORLD; + + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) { + super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index ffc8c9ee8b1768dd809189858ee45658fb9bf1c5..8e00747c1a717836d12a43aa48d667bf801167b0 100644 +index bcc946d2747443c34ee8ac2485a5ab41773c93af..2730923bd0bf3b0f928765b9e09e2299fa9a393d 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -250,7 +250,7 @@ public abstract class PlayerList { +@@ -241,7 +241,7 @@ public abstract class PlayerList { boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); // Spigot - view distance @@ -626,16 +537,16 @@ index ffc8c9ee8b1768dd809189858ee45658fb9bf1c5..8e00747c1a717836d12a43aa48d667bf player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit playerconnection.send(new ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.BRAND, (new FriendlyByteBuf(Unpooled.buffer())).writeUtf(this.getServer().getServerModName()))); playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); -@@ -904,7 +904,7 @@ public abstract class PlayerList { +@@ -789,7 +789,7 @@ public abstract class PlayerList { // CraftBukkit start LevelData worlddata = worldserver1.getLevelData(); entityplayer1.connection.send(new ClientboundRespawnPacket(worldserver1.dimensionType(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), entityplayer1.gameMode.getGameModeForPlayer(), entityplayer1.gameMode.getPreviousGameModeForPlayer(), worldserver1.isDebug(), worldserver1.isFlat(), flag)); - entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.spigotConfig.viewDistance)); // Spigot + entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.getChunkSource().chunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance entityplayer1.setLevel(worldserver1); - entityplayer1.removed = false; - entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.yRot, entityplayer1.xRot)); -@@ -1372,7 +1372,7 @@ public abstract class PlayerList { + entityplayer1.unsetRemoved(); + entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.getYRot(), entityplayer1.getXRot())); +@@ -1273,7 +1273,7 @@ public abstract class PlayerList { public void setViewDistance(int viewDistance) { this.viewDistance = viewDistance; @@ -645,10 +556,10 @@ index ffc8c9ee8b1768dd809189858ee45658fb9bf1c5..8e00747c1a717836d12a43aa48d667bf while (iterator.hasNext()) { diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 5860e7866724abd35bde2a5710d9c92799e5de67..67ab681a9c9157a420de5fd872bde1fc0de24561 100644 +index ddcde88a8c8b748b4dc2583b4dfd0fb8ea9e201e..07e81fa1119bba4981e34e70b9e67f43280f8071 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -525,8 +525,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -521,8 +521,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); } @@ -664,30 +575,26 @@ index 5860e7866724abd35bde2a5710d9c92799e5de67..67ab681a9c9157a420de5fd872bde1fc if ((i & 1) != 0) { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 8a14bdda4a408ec1e2b51efeb35467835f62b42c..dbea2a4370ccf24a5084cdabeecbc81f206e910a 100644 +index 521f199e495f3bec232cc9ca36e51e0392afe737..922026da8c234427e0322443004d3c32993adfce 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -27,9 +27,14 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Registry; +@@ -33,7 +33,10 @@ import net.minecraft.core.Registry; + import net.minecraft.core.SectionPos; import net.minecraft.nbt.CompoundTag; - import net.minecraft.server.MinecraftServer; + import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.Packet; import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkTaskPriorityQueueSorter; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.TicketType; - import net.minecraft.util.Mth; - import net.minecraft.world.Container; - import net.minecraft.world.entity.Entity; -@@ -242,7 +247,51 @@ public class LevelChunk implements ChunkAccess { + import net.minecraft.util.profiling.ProfilerFiller; +@@ -227,7 +230,51 @@ public class LevelChunk implements ChunkAccess { } protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { + // Paper start - no-tick view distance -+ ServerChunkCache chunkProviderServer = ((ServerLevel)this.world).getChunkSource(); ++ ServerChunkCache chunkProviderServer = ((ServerLevel)this.level).getChunkSource(); + ChunkMap chunkMap = chunkProviderServer.chunkMap; + // this code handles the addition of ticking tickets - the distance map handles the removal + if (!areNeighboursLoaded(bitsetBefore, 2) && areNeighboursLoaded(bitsetAfter, 2)) { @@ -696,7 +603,7 @@ index 8a14bdda4a408ec1e2b51efeb35467835f62b42c..dbea2a4370ccf24a5084cdabeecbc81f + chunkProviderServer.mainThreadProcessor.execute(() -> { + // double check that this condition still holds. + if (LevelChunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(LevelChunk.this.coordinateKey) != null) { -+ chunkProviderServer.addTicketAtLevel(TicketType.PLAYER, LevelChunk.this.chunkPos, 31, LevelChunk.this.chunkPos); // 31 -> entity ticking, TODO check on update ++ chunkProviderServer.addTicketAtLevel(net.minecraft.server.level.TicketType.PLAYER, LevelChunk.this.chunkPos, 31, LevelChunk.this.chunkPos); // 31 -> entity ticking, TODO check on update + } + }); + } @@ -711,7 +618,7 @@ index 8a14bdda4a408ec1e2b51efeb35467835f62b42c..dbea2a4370ccf24a5084cdabeecbc81f + if (!LevelChunk.this.areNeighboursLoaded(1)) { + return; + } -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(LevelChunk.this.coordinateKey); ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(LevelChunk.this.coordinateKey); + if (inRange == null) { + return; + } @@ -721,11 +628,11 @@ index 8a14bdda4a408ec1e2b51efeb35467835f62b42c..dbea2a4370ccf24a5084cdabeecbc81f + Packet[] chunkPackets = new Packet[2]; + for (int index = 0, len = backingSet.length; index < len; ++index) { + Object temp = backingSet[index]; -+ if (!(temp instanceof ServerPlayer)) { ++ if (!(temp instanceof net.minecraft.server.level.ServerPlayer)) { + continue; + } -+ ServerPlayer player = (ServerPlayer)temp; -+ chunkMap.sendChunk(player, chunkPackets, LevelChunk.this); ++ net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer)temp; ++ chunkMap.playerLoadedChunk(player, chunkPackets, LevelChunk.this); + } + }))); + } @@ -734,28 +641,20 @@ index 8a14bdda4a408ec1e2b51efeb35467835f62b42c..dbea2a4370ccf24a5084cdabeecbc81f } public final boolean isAnyNeighborsLoaded() { -@@ -1131,7 +1180,7 @@ public class LevelChunk implements ChunkAccess { +@@ -1005,7 +1052,7 @@ public class LevelChunk implements ChunkAccess { BlockState iblockdata = this.getBlockState(blockposition); - BlockState iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, (LevelAccessor) this.world, blockposition); + BlockState iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, (LevelAccessor) this.level, blockposition); -- this.world.setBlock(blockposition, iblockdata1, 20); -+ this.world.setBlock(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here +- this.level.setBlock(blockposition, iblockdata1, 20); ++ this.level.setBlock(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here } this.postProcessing[i].clear(); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 1a839242e359fa32f32d0e571c6e918ac39642e9..4fc44390f432ef13c9952aa22bbb29bc8bf47975 100644 +index f1cbcdb1e409f8544125dde5f24bff5b07cb5082..1d22119b962840dff789a0619fd2188958f924d0 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -31,6 +31,7 @@ import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; - import net.minecraft.network.protocol.game.ClientboundSetTimePacket; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.level.ChunkHolder; -+import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.DistanceManager; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.Ticket; -@@ -2532,10 +2533,39 @@ public class CraftWorld implements World { +@@ -2540,10 +2540,39 @@ public class CraftWorld implements World { // Spigot start @Override public int getViewDistance() { @@ -770,7 +669,7 @@ index 1a839242e359fa32f32d0e571c6e918ac39642e9..4fc44390f432ef13c9952aa22bbb29bc + if (viewDistance < 2 || viewDistance > 32) { + throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); + } -+ ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; ++ net.minecraft.server.level.ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; + if (viewDistance != chunkMap.getEffectiveViewDistance()) { + chunkMap.setViewDistance(viewDistance); + } @@ -786,7 +685,7 @@ index 1a839242e359fa32f32d0e571c6e918ac39642e9..4fc44390f432ef13c9952aa22bbb29bc + if ((viewDistance < 2 || viewDistance > 32) && viewDistance != -1) { + throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); + } -+ ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; ++ net.minecraft.server.level.ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; + if (viewDistance != chunkMap.getRawNoTickViewDistance()) { + chunkMap.setNoTickViewDistance(viewDistance); + } @@ -797,23 +696,15 @@ index 1a839242e359fa32f32d0e571c6e918ac39642e9..4fc44390f432ef13c9952aa22bbb29bc private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot() { diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 8cbafad53d20366a36493f22160c4fa3e4ac3eaf..20d5da61fc0594e86c68ea8fb5ebe5517f27f126 100644 +index 2ab585a018290996e7fa9ca6f3ad7d734cd7beaa..a08583863f9fa08016bdfc7949a273eaa4429927 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -4,6 +4,7 @@ import java.util.Collection; - import net.minecraft.core.BlockPos; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerChunkCache; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.FlyingMob; -@@ -192,7 +193,7 @@ public class ActivationRange +@@ -188,7 +188,7 @@ public class ActivationRange maxRange = Math.max( maxRange, waterActivationRange ); maxRange = Math.max( maxRange, villagerActivationRange ); // Paper end - maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); -+ maxRange = Math.min( ( ((ServerLevel)world).getChunkSource().chunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance ++ maxRange = Math.min( ( ((net.minecraft.server.level.ServerLevel)world).getChunkSource().chunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance for ( Player player : world.players() ) { From f55b6e04b1af431994aa7879cf0eef86ccf2acbe Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sun, 13 Jun 2021 15:05:18 -0700 Subject: [PATCH 082/226] MOAR PATCHES --- .../0188-Add-ThrownEggHatchEvent.patch} | 0 .../0189-Entity-Jump-API.patch} | 0 ...90-add-hand-to-BlockMultiPlaceEvent.patch} | 0 ...re-Entity-is-never-double-registered.patch | 2 + ...ering-entities-from-unloading-chunks.patch | 2 + ...get-gravity-in-void.-Fixes-MC-167279.patch | 55 -- ...ptimize-Collision-to-not-load-chunks.patch | 185 ------- .../0362-Tracking-Range-Improvements.patch} | 8 +- ...-items-vanishing-through-end-portal.patch} | 8 +- ...get-gravity-in-void.-Fixes-MC-167279.patch | 29 ++ ...-getChunkAt-calls-for-loaded-chunks.patch} | 6 +- ...w-overriding-the-java-version-check.patch} | 6 +- .../0367-Add-ThrownEggHatchEvent.patch} | 8 +- .../0368-Optimise-random-block-ticking.patch} | 170 +++--- .../0369-Entity-Jump-API.patch} | 10 +- ...-to-nerf-pigmen-from-nether-portals.patch} | 48 +- .../0371-Make-the-GUI-graph-fancier.patch} | 59 +-- ...72-add-hand-to-BlockMultiPlaceEvent.patch} | 4 +- ...3-Prevent-teleporting-dead-entities.patch} | 10 +- ...ipwire-hook-placement-before-update.patch} | 4 +- ...o-allow-iron-golems-to-spawn-in-air.patch} | 8 +- ...chance-of-villager-zombie-infection.patch} | 31 +- .../0377-Optimise-Chunk-getFluid.patch} | 38 +- ...mise-TickListServer-by-rewriting-it.patch} | 493 ++++++------------ ...pawn-settings-and-per-player-option.patch} | 24 +- ...nections-shouldn-t-hold-up-shutdown.patch} | 4 +- ...ow-bees-to-load-chunks-for-beehives.patch} | 10 +- ...PlayerChunkMap-adds-crashing-server.patch} | 34 +- ...ptimize-Collision-to-not-load-chunks.patch | 133 +++++ .../0384-Don-t-tick-dead-players.patch} | 8 +- ...-Player-s-shouldn-t-be-able-to-move.patch} | 6 +- ...unkMap-memory-use-for-visibleChunks.patch} | 73 +-- ...sks-Speed-up-processing-of-chunk-lo.patch} | 87 ++-- ...ove-existing-players-to-world-spawn.patch} | 27 +- 34 files changed, 623 insertions(+), 967 deletions(-) rename patches/{api-unmapped/0187-Add-ThrownEggHatchEvent.patch => api/0188-Add-ThrownEggHatchEvent.patch} (100%) rename patches/{api-unmapped/0188-Entity-Jump-API.patch => api/0189-Entity-Jump-API.patch} (100%) rename patches/{api-unmapped/0189-add-hand-to-BlockMultiPlaceEvent.patch => api/0190-add-hand-to-BlockMultiPlaceEvent.patch} (100%) rename patches/{server-remapped => removed/1.17}/0420-Ensure-Entity-is-never-double-registered.patch (99%) rename patches/{server-remapped => removed/1.17}/0421-Fix-unregistering-entities-from-unloading-chunks.patch (98%) delete mode 100644 patches/server-remapped/0404-Bees-get-gravity-in-void.-Fixes-MC-167279.patch delete mode 100644 patches/server-remapped/0425-Optimize-Collision-to-not-load-chunks.patch rename patches/{server-remapped/0401-Tracking-Range-Improvements.patch => server/0362-Tracking-Range-Improvements.patch} (90%) rename patches/{server-remapped/0403-Fix-items-vanishing-through-end-portal.patch => server/0363-Fix-items-vanishing-through-end-portal.patch} (77%) create mode 100644 patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch rename patches/{server-remapped/0405-Optimise-getChunkAt-calls-for-loaded-chunks.patch => server/0365-Optimise-getChunkAt-calls-for-loaded-chunks.patch} (92%) rename patches/{server-remapped/0406-Allow-overriding-the-java-version-check.patch => server/0366-Allow-overriding-the-java-version-check.patch} (76%) rename patches/{server-remapped/0407-Add-ThrownEggHatchEvent.patch => server/0367-Add-ThrownEggHatchEvent.patch} (85%) rename patches/{server-remapped/0408-Optimise-random-block-ticking.patch => server/0368-Optimise-random-block-ticking.patch} (74%) rename patches/{server-remapped/0409-Entity-Jump-API.patch => server/0369-Entity-Jump-API.patch} (87%) rename patches/{server-remapped/0410-Add-option-to-nerf-pigmen-from-nether-portals.patch => server/0370-Add-option-to-nerf-pigmen-from-nether-portals.patch} (58%) rename patches/{server-remapped/0411-Make-the-GUI-graph-fancier.patch => server/0371-Make-the-GUI-graph-fancier.patch} (80%) rename patches/{server-remapped/0412-add-hand-to-BlockMultiPlaceEvent.patch => server/0372-add-hand-to-BlockMultiPlaceEvent.patch} (89%) rename patches/{server-remapped/0413-Prevent-teleporting-dead-entities.patch => server/0373-Prevent-teleporting-dead-entities.patch} (67%) rename patches/{server-remapped/0414-Validate-tripwire-hook-placement-before-update.patch => server/0374-Validate-tripwire-hook-placement-before-update.patch} (85%) rename patches/{server-remapped/0415-Add-option-to-allow-iron-golems-to-spawn-in-air.patch => server/0375-Add-option-to-allow-iron-golems-to-spawn-in-air.patch} (85%) rename patches/{server-remapped/0416-Configurable-chance-of-villager-zombie-infection.patch => server/0376-Configurable-chance-of-villager-zombie-infection.patch} (63%) rename patches/{server-remapped/0417-Optimise-Chunk-getFluid.patch => server/0377-Optimise-Chunk-getFluid.patch} (58%) rename patches/{server-remapped/0418-Optimise-TickListServer-by-rewriting-it.patch => server/0378-Optimise-TickListServer-by-rewriting-it.patch} (66%) rename patches/{server-remapped/0419-Pillager-patrol-spawn-settings-and-per-player-option.patch => server/0379-Pillager-patrol-spawn-settings-and-per-player-option.patch} (85%) rename patches/{server-remapped/0422-Remote-Connections-shouldn-t-hold-up-shutdown.patch => server/0380-Remote-Connections-shouldn-t-hold-up-shutdown.patch} (86%) rename patches/{server-remapped/0423-Do-not-allow-bees-to-load-chunks-for-beehives.patch => server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch} (85%) rename patches/{server-remapped/0424-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch => server/0382-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch} (62%) create mode 100644 patches/server/0383-Optimize-Collision-to-not-load-chunks.patch rename patches/{server-remapped/0426-Don-t-tick-dead-players.patch => server/0384-Don-t-tick-dead-players.patch} (59%) rename patches/{server-remapped/0427-Dead-Player-s-shouldn-t-be-able-to-move.patch => server/0385-Dead-Player-s-shouldn-t-be-able-to-move.patch} (70%) rename patches/{server-remapped/0428-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch => server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch} (84%) rename patches/{server-remapped/0430-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch => server/0387-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch} (79%) rename patches/{server-remapped/0431-Don-t-move-existing-players-to-world-spawn.patch => server/0388-Don-t-move-existing-players-to-world-spawn.patch} (65%) diff --git a/patches/api-unmapped/0187-Add-ThrownEggHatchEvent.patch b/patches/api/0188-Add-ThrownEggHatchEvent.patch similarity index 100% rename from patches/api-unmapped/0187-Add-ThrownEggHatchEvent.patch rename to patches/api/0188-Add-ThrownEggHatchEvent.patch diff --git a/patches/api-unmapped/0188-Entity-Jump-API.patch b/patches/api/0189-Entity-Jump-API.patch similarity index 100% rename from patches/api-unmapped/0188-Entity-Jump-API.patch rename to patches/api/0189-Entity-Jump-API.patch diff --git a/patches/api-unmapped/0189-add-hand-to-BlockMultiPlaceEvent.patch b/patches/api/0190-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from patches/api-unmapped/0189-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/api/0190-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/patches/server-remapped/0420-Ensure-Entity-is-never-double-registered.patch b/patches/removed/1.17/0420-Ensure-Entity-is-never-double-registered.patch similarity index 99% rename from patches/server-remapped/0420-Ensure-Entity-is-never-double-registered.patch rename to patches/removed/1.17/0420-Ensure-Entity-is-never-double-registered.patch index 0c956bdb77..a10ff17d78 100644 --- a/patches/server-remapped/0420-Ensure-Entity-is-never-double-registered.patch +++ b/patches/removed/1.17/0420-Ensure-Entity-is-never-double-registered.patch @@ -10,6 +10,8 @@ Vs behavior of non ticking of just overwriting state. We will now simply log a warning when this happens instead of crashing the server. +1.17: Probably not needed? + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 9da0d98bc2ed7876a00a734690ed42f01b9a9a9b..9898d5c8fab63c576831bd416ccf1854ed077b0d 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/server-remapped/0421-Fix-unregistering-entities-from-unloading-chunks.patch b/patches/removed/1.17/0421-Fix-unregistering-entities-from-unloading-chunks.patch similarity index 98% rename from patches/server-remapped/0421-Fix-unregistering-entities-from-unloading-chunks.patch rename to patches/removed/1.17/0421-Fix-unregistering-entities-from-unloading-chunks.patch index 110790b17f..8d30f4e4f1 100644 --- a/patches/server-remapped/0421-Fix-unregistering-entities-from-unloading-chunks.patch +++ b/patches/removed/1.17/0421-Fix-unregistering-entities-from-unloading-chunks.patch @@ -14,6 +14,8 @@ This then results in dead entities lingering in the Chunk. Combine that with a buggy detail of the previous implementation of the Dupe UUID patch, then this was the likely source of the "Ghost entities" +1.17: Probably not needed? + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 9898d5c8fab63c576831bd416ccf1854ed077b0d..c5dc41a3cf499038bd33451a189913cd3978b230 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/server-remapped/0404-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server-remapped/0404-Bees-get-gravity-in-void.-Fixes-MC-167279.patch deleted file mode 100644 index f19be75b52..0000000000 --- a/patches/server-remapped/0404-Bees-get-gravity-in-void.-Fixes-MC-167279.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 26 Jan 2020 16:30:19 -0600 -Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java -index 2c9e3dd1b9dd7bb8825a2eb9fecc2b2be348d055..868e9cdeb3c7effb398cef6f6f9c1e4fffa2db8c 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java -@@ -16,7 +16,7 @@ public class FlyingMoveControl extends MoveControl { - } - - @Override -- public void tick() { -+ public void tick() { tick(); } public void tick() { // Paper - OBFHELPER - if (this.operation == MoveControl.Operation.MOVE_TO) { - this.operation = MoveControl.Operation.WAIT; - this.mob.setNoGravity(true); -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java -index ab65f0327766463a5e53fdd723e243464319fdbe..f4984d601d14c684e75f887f5f5d2f5a29326b15 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java -@@ -16,7 +16,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; - - public class MoveControl { - -- protected final Mob mob; -+ protected final Mob mob; public final Mob getEntity() { return mob; } // Paper - OBFHELPER - protected double wantedX; - protected double wantedY; - protected double wantedZ; -diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index edd6d63f715acef1a77eba0cf46ff8267228f4c6..9b68809b91910d2bbb82cafe23d1de5dfff4221c 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Bee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -111,7 +111,17 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - - public Bee(EntityType type, Level world) { - super(type, world); -- this.moveControl = new FlyingMoveControl(this, 20, true); -+ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 -+ this.moveControl = new FlyingMoveControl(this, 20, true) { -+ @Override -+ public void tick() { -+ if (getEntity().getY() <= 0) { -+ getEntity().setNoGravity(false); -+ } -+ super.tick(); -+ } -+ }; -+ // Paper end - this.lookControl = new Bee.BeeLookControl(this); - this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); - this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); diff --git a/patches/server-remapped/0425-Optimize-Collision-to-not-load-chunks.patch b/patches/server-remapped/0425-Optimize-Collision-to-not-load-chunks.patch deleted file mode 100644 index 58edb5460d..0000000000 --- a/patches/server-remapped/0425-Optimize-Collision-to-not-load-chunks.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 02:37:57 -0400 -Subject: [PATCH] Optimize Collision to not load chunks - -The collision code takes an AABB and generates a cuboid of checks rather -than a cylinder, so at high velocity this can generate a lot of chunk checks. - -Treat an unloaded chunk as a collision for entities, and also for players if -the "prevent moving into unloaded chunks" setting is enabled. - -If that serting is not enabled, collisions will be ignored for players, since -movement will load only the chunk the player enters anyways and avoids loading -massive amounts of surrounding chunks due to large AABB lookups. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index dfdde9722bc0d83916779014b7718eef2c01b3db..86c5549196a4e9011c5240e7918b466c299be4a3 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -59,12 +59,23 @@ import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.PlayerAdvancements; - import net.minecraft.server.ServerScoreboard; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.ServerPlayerGameMode; -+import net.minecraft.server.level.TicketType; -+import net.minecraft.server.network.ServerGamePacketListenerImpl; -+import net.minecraft.server.network.ServerLoginPacketListenerImpl; -+import net.minecraft.sounds.SoundEvents; -+import net.minecraft.sounds.SoundSource; -+import net.minecraft.stats.ServerStatsCounter; -+import net.minecraft.stats.Stats; - import net.minecraft.tags.BlockTags; - import net.minecraft.tags.Tag; - import net.minecraft.util.Mth; - import net.minecraft.world.effect.MobEffectInstance; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.GameType; - import net.minecraft.world.level.Level; -@@ -90,15 +101,6 @@ import io.papermc.paper.adventure.PaperAdventure; // Paper - import com.google.common.base.Predicate; - import com.google.common.collect.Iterables; - import net.minecraft.server.dedicated.DedicatedServer; --import net.minecraft.server.level.ServerLevel; --import net.minecraft.server.level.ServerPlayer; --import net.minecraft.server.level.ServerPlayerGameMode; --import net.minecraft.server.network.ServerGamePacketListenerImpl; --import net.minecraft.server.network.ServerLoginPacketListenerImpl; --import net.minecraft.sounds.SoundEvents; --import net.minecraft.sounds.SoundSource; --import net.minecraft.stats.ServerStatsCounter; --import net.minecraft.stats.Stats; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - -@@ -805,6 +807,7 @@ public abstract class PlayerList { - entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - // CraftBukkit end - -+ worldserver1.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, new ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper - while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < 256.0D) { - entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 7e198b94f349d4c4d61502f5ad8c60686800d88f..b8dcc91a191f25ca578e0858abf6c1b874fee15d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -168,6 +168,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - private CraftEntity bukkitEntity; - - ChunkMap.TrackedEntity tracker; // Paper -+ public boolean collisionLoadChunks = false; // Paper - public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { -diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java -index d9e69195ee0af4dfb90bf0e8f4cc65e63f7ecf5b..1b52f2a0ce9cb847d7d57b38f4b8b6bed8de2cd9 100644 ---- a/src/main/java/net/minecraft/world/level/CollisionGetter.java -+++ b/src/main/java/net/minecraft/world/level/CollisionGetter.java -@@ -54,7 +54,9 @@ public interface CollisionGetter extends BlockGetter { - } - - default boolean noCollision(@Nullable Entity entity, AABB axisalignedbb, Predicate predicate) { -+ try { if (entity != null) entity.collisionLoadChunks = true; // Paper - return this.getCollisions(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty); -+ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper - } - - Stream getEntityCollisions(@Nullable Entity entity, AABB axisalignedbb, Predicate predicate); -diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -index 7208c61da48ce5e735810b6268490584e1d5c260..feca9ff34936686c0665ae0dbc926869087df3a7 100644 ---- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -+++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -@@ -7,6 +7,9 @@ import java.util.function.Consumer; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Cursor3D; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.WorldGenRegion; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.block.Blocks; -@@ -21,13 +24,13 @@ import net.minecraft.world.phys.shapes.VoxelShape; - public class CollisionSpliterator extends AbstractSpliterator { - - @Nullable -- private final Entity source; -+ private final Entity source; final Entity getEntity() { return this.source; } // Paper - OBFHELPER - private final AABB box; - private final CollisionContext context; - private final Cursor3D cursor; -- private final BlockPos.MutableBlockPos pos; -+ private final BlockPos.MutableBlockPos pos; final BlockPos.MutableBlockPos getMutablePos() { return this.pos; } // Paper - OBFHELPER - private final VoxelShape entityShape; -- private final CollisionGetter collisionGetter; -+ private final CollisionGetter collisionGetter; final CollisionGetter getCollisionAccess() { return this.collisionGetter; } // Paper - OBFHELPER - private boolean needsBorderCheck; - private final BiPredicate predicate; - -@@ -64,23 +67,37 @@ public class CollisionSpliterator extends AbstractSpliterator { - boolean collisionCheck(Consumer consumer) { - while (true) { - if (this.cursor.advance()) { -- int i = this.cursor.nextX(); -- int j = this.cursor.nextY(); -- int k = this.cursor.nextZ(); -+ int i = this.cursor.nextX(); final int x = i; -+ int j = this.cursor.nextY(); final int y = j; -+ int k = this.cursor.nextZ(); final int z = k; - int l = this.cursor.getNextType(); - - if (l == 3) { - continue; - } - -- BlockGetter iblockaccess = this.getChunk(i, k); -- -- if (iblockaccess == null) { -+ // Paper start - ensure we don't load chunks -+ Entity entity = this.getEntity(); -+ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getMutablePos(); -+ boolean far = entity != null && MCUtil.distanceSq(entity.getX(), y, entity.getZ(), x, y, z) > 14; -+ blockposition_mutableblockposition.setValues(x, y, z); -+ -+ boolean isRegionLimited = this.getCollisionAccess() instanceof WorldGenRegion; -+ BlockState iblockdata = isRegionLimited ? Blocks.VOID_AIR.defaultBlockState() : ((!far && entity instanceof ServerPlayer) || (entity != null && entity.collisionLoadChunks) -+ ? this.getCollisionAccess().getBlockState(blockposition_mutableblockposition) -+ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition) -+ ); -+ -+ if (iblockdata == null) { -+ if (!(entity instanceof ServerPlayer) || entity.level.paperConfig.preventMovingIntoUnloadedChunks) { -+ VoxelShape voxelshape3 = Shapes.of(far ? entity.getBoundingBox() : new AABB(new BlockPos(x, y, z))); -+ consumer.accept(voxelshape3); -+ return true; -+ } - continue; - } -- -- this.pos.set(i, j, k); -- BlockState iblockdata = iblockaccess.getBlockState(this.pos); -+ // Paper - moved up -+ // Paper end - - if (!this.predicate.test(iblockdata, this.pos) || l == 1 && !iblockdata.hasLargeCollisionShape() || l == 2 && !iblockdata.is(Blocks.MOVING_PISTON)) { - continue; -diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -index fa2942d0b0424390daee2121f8959034c5352e0b..c14d5ebe16a693834ed218af8f737714065b2e17 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -@@ -249,7 +249,8 @@ public final class Shapes { - - if (k2 < 3) { - blockposition_mutableblockposition.set(enumaxiscycle1, i2, j2, l1); -- BlockState iblockdata = world.getBlockState(blockposition_mutableblockposition); -+ BlockState iblockdata = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper -+ if (iblockdata == null) return 0.0D; // Paper - - if ((k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { - initial = iblockdata.getCollisionShape((BlockGetter) world, blockposition_mutableblockposition, context).collide(enumdirection_enumaxis2, box.move((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), initial); diff --git a/patches/server-remapped/0401-Tracking-Range-Improvements.patch b/patches/server/0362-Tracking-Range-Improvements.patch similarity index 90% rename from patches/server-remapped/0401-Tracking-Range-Improvements.patch rename to patches/server/0362-Tracking-Range-Improvements.patch index ec1d0a178d..b4d6875ed4 100644 --- a/patches/server-remapped/0401-Tracking-Range-Improvements.patch +++ b/patches/server/0362-Tracking-Range-Improvements.patch @@ -8,10 +8,10 @@ Sets tracking range of watermobs to animals instead of misc and simplifies code Also ignores Enderdragon, defaulting it to Mojang's setting diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 190ddd4d9ef3472c33d46c2ead72fa0dc918054a..6da406c8403797a1cd9276ac06577c3c080a8a22 100644 +index fdf5d8ede4b01e399272ddebfbd49258b166f00b..273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1795,6 +1795,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1791,6 +1791,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially while (iterator.hasNext()) { Entity entity = (Entity) iterator.next(); int j = entity.getType().clientTrackingRange() * 16; @@ -20,7 +20,7 @@ index 190ddd4d9ef3472c33d46c2ead72fa0dc918054a..6da406c8403797a1cd9276ac06577c3c if (j > i) { i = j; diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java -index 8e3e36a8739a7dea1feb3785e96b7b9f19720446..b03fa9024c7f0238e1379f6ae4486db5300a70e9 100644 +index 2d5cb8991e368372f1ab227735aac0c060deb199..24b1dfcf91d36947c87e9e5c2524317f8775ba95 100644 --- a/src/main/java/org/spigotmc/TrackingRange.java +++ b/src/main/java/org/spigotmc/TrackingRange.java @@ -6,7 +6,6 @@ import net.minecraft.world.entity.ExperienceOrb; @@ -31,7 +31,7 @@ index 8e3e36a8739a7dea1feb3785e96b7b9f19720446..b03fa9024c7f0238e1379f6ae4486db5 public class TrackingRange { -@@ -25,26 +24,26 @@ public class TrackingRange +@@ -29,26 +28,26 @@ public class TrackingRange if ( entity instanceof ServerPlayer ) { return config.playerTrackingRange; diff --git a/patches/server-remapped/0403-Fix-items-vanishing-through-end-portal.patch b/patches/server/0363-Fix-items-vanishing-through-end-portal.patch similarity index 77% rename from patches/server-remapped/0403-Fix-items-vanishing-through-end-portal.patch rename to patches/server/0363-Fix-items-vanishing-through-end-portal.patch index 283ad7000c..e32fc1978b 100644 --- a/patches/server-remapped/0403-Fix-items-vanishing-through-end-portal.patch +++ b/patches/server/0363-Fix-items-vanishing-through-end-portal.patch @@ -13,16 +13,16 @@ Quickly loading the exact world spawn chunk before searching the heightmap resolves the issue without having to load all spawn chunks. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c6881a9a5da2caed77dea30e4906d2dd99a624c1..efc9cb6def2f4ee327329dc090d2918ff60d8e19 100644 +index fffeba61e9af5c69876921b48241edb881af2a64..3d3286070c9c4db6d6487e119070794dadf493bd 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2734,6 +2734,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2983,6 +2983,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n BlockPos blockposition1; if (flag1) { + // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate -+ this.level.getChunkAt(this.level.getSpawn()); ++ this.level.getChunkAt(this.level.getSharedSpawnPos()); + // Paper end blockposition1 = ServerLevel.END_SPAWN_POINT; } else { - blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSpawn()); + blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos()); diff --git a/patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch new file mode 100644 index 0000000000..adb34b3de2 --- /dev/null +++ b/patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 26 Jan 2020 16:30:19 -0600 +Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java +index f3ba4b26553915917c79f013ed9dd7c87d9f65a4..b4cd490a1b2a2a118dc5f49bcb0fb755fbad853b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -143,7 +143,17 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + public Bee(EntityType type, Level world) { + super(type, world); + this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60); +- this.moveControl = new FlyingMoveControl(this, 20, true); ++ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 ++ this.moveControl = new FlyingMoveControl(this, 20, true) { ++ @Override ++ public void tick() { ++ if (this.mob.getY() <= 0) { ++ this.mob.setNoGravity(false); ++ } ++ super.tick(); ++ } ++ }; ++ // Paper end + this.lookControl = new Bee.BeeLookControl(this); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); diff --git a/patches/server-remapped/0405-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server/0365-Optimise-getChunkAt-calls-for-loaded-chunks.patch similarity index 92% rename from patches/server-remapped/0405-Optimise-getChunkAt-calls-for-loaded-chunks.patch rename to patches/server/0365-Optimise-getChunkAt-calls-for-loaded-chunks.patch index 009a0fad66..5eea71802d 100644 --- a/patches/server-remapped/0405-Optimise-getChunkAt-calls-for-loaded-chunks.patch +++ b/patches/server/0365-Optimise-getChunkAt-calls-for-loaded-chunks.patch @@ -7,10 +7,10 @@ bypass the need to get a player chunk, then get the either, then unwrap it... diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index eac5e799c4d26e53286a27c54b56899ba0b9ffb2..3aeb8426b0461ec572c1499116be80f968bb4104 100644 +index c47d1772044913475a60292162ef4be594bed4c6..7cbd3db81c73d466a6e6012c1c91698b53a0cb86 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -470,6 +470,12 @@ public class ServerChunkCache extends ChunkSource { +@@ -451,6 +451,12 @@ public class ServerChunkCache extends ChunkSource { return this.getChunk(x, z, leastStatus, create); }, this.mainThreadProcessor).join(); } else { @@ -23,7 +23,7 @@ index eac5e799c4d26e53286a27c54b56899ba0b9ffb2..3aeb8426b0461ec572c1499116be80f9 ProfilerFiller gameprofilerfiller = this.level.getProfiler(); gameprofilerfiller.incrementCounter("getChunk"); -@@ -520,39 +526,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -502,39 +508,7 @@ public class ServerChunkCache extends ChunkSource { if (Thread.currentThread() != this.mainThread) { return null; } else { diff --git a/patches/server-remapped/0406-Allow-overriding-the-java-version-check.patch b/patches/server/0366-Allow-overriding-the-java-version-check.patch similarity index 76% rename from patches/server-remapped/0406-Allow-overriding-the-java-version-check.patch rename to patches/server/0366-Allow-overriding-the-java-version-check.patch index 04082e9a36..983fc278c8 100644 --- a/patches/server-remapped/0406-Allow-overriding-the-java-version-check.patch +++ b/patches/server/0366-Allow-overriding-the-java-version-check.patch @@ -6,11 +6,11 @@ Subject: [PATCH] Allow overriding the java version check -DPaper.IgnoreJavaVersion=true diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 808a7688ed81bdfef623ee0a151ff8f94df2a3d7..c519ceca6f7788ca7c5d74ad1001dbc09f62681c 100644 +index f68d44721c91c20a7e4abffe26dabff8b5d2c3ce..fd48cfe3dfaf7c867becfbf90246af2f33a74612 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -181,7 +181,7 @@ public class Main { - float javaVersion = Float.parseFloat(System.getProperty("java.class.version")); +@@ -185,7 +185,7 @@ public class Main { + } if (javaVersion > 60.0) { System.err.println("Unsupported Java detected (" + javaVersion + "). Only up to Java 16 is supported."); - return; diff --git a/patches/server-remapped/0407-Add-ThrownEggHatchEvent.patch b/patches/server/0367-Add-ThrownEggHatchEvent.patch similarity index 85% rename from patches/server-remapped/0407-Add-ThrownEggHatchEvent.patch rename to patches/server/0367-Add-ThrownEggHatchEvent.patch index 5bc9d2e683..c026427598 100644 --- a/patches/server-remapped/0407-Add-ThrownEggHatchEvent.patch +++ b/patches/server/0367-Add-ThrownEggHatchEvent.patch @@ -7,10 +7,10 @@ Adds a new event similar to PlayerEggThrowEvent, but without the Player requirem (dispensers can throw eggs to hatch them, too). diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java -index f3808a5e9155e1bf6c6219fc494864bb7dc61117..520eace73b569c2c77e76e0dfd18eb9c7188ec30 100644 +index 4e083dcd07e5975c7379035e72ac2f3469e919fd..77941e3981e49cf5662b3e3c86a9c419080b17c8 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java +++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java -@@ -63,6 +63,16 @@ public class ThrownEgg extends ThrowableItemProjectile { +@@ -77,6 +77,14 @@ public class ThrownEgg extends ThrowableItemProjectile { hatchingType = event.getHatchingType(); } @@ -22,8 +22,6 @@ index f3808a5e9155e1bf6c6219fc494864bb7dc61117..520eace73b569c2c77e76e0dfd18eb9c + hatching = event.isHatching(); + hatchingType = event.getHatchingType(); + // Paper end -+ -+ if (hatching) { for (int i = 0; i < b0; ++i) { - Entity entity = level.getWorld().createEntity(new org.bukkit.Location(level.getWorld(), this.getX(), this.getY(), this.getZ(), this.yRot, 0.0F), hatchingType.getEntityClass()); + Entity entity = level.getWorld().createEntity(new org.bukkit.Location(level.getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F), hatchingType.getEntityClass()); diff --git a/patches/server-remapped/0408-Optimise-random-block-ticking.patch b/patches/server/0368-Optimise-random-block-ticking.patch similarity index 74% rename from patches/server-remapped/0408-Optimise-random-block-ticking.patch rename to patches/server/0368-Optimise-random-block-ticking.patch index 881f7be3f4..e6d451fad9 100644 --- a/patches/server-remapped/0408-Optimise-random-block-ticking.patch +++ b/patches/server/0368-Optimise-random-block-ticking.patch @@ -70,23 +70,11 @@ index 0000000000000000000000000000000000000000..3edc8e52e06a62ce9f8cc734fd7458b3 + return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound); + } +} -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index b13e5d05d862ea8c6031b8071f525f00bc48f7e7..3db77d9eda98eacb099135643aff5e94751f4c7c 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -468,6 +468,7 @@ public class BlockPos extends Vec3i { - return this.set(Mth.floor(x), Mth.floor(y), Mth.floor(z)); - } - -+ public final BlockPos.MutableBlockPos setValues(final Vec3i baseblockposition) { return this.set(baseblockposition); } // Paper - OBFHELPER - public BlockPos.MutableBlockPos set(Vec3i pos) { - return this.set(pos.getX(), pos.getY(), pos.getZ()); - } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027ea23b400b 100644 +index 67b9daee8d7e55fdf2015e6616f393f176b1ca96..ecb9c5a1958c89494417bdb3e6c6363f3fc84534 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -669,7 +669,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -664,7 +664,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl }); } @@ -100,7 +88,7 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e ChunkPos chunkcoordintpair = chunk.getPos(); boolean flag = this.isRaining(); int j = chunkcoordintpair.getMinBlockX(); -@@ -677,10 +682,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -672,10 +677,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl ProfilerFiller gameprofilerfiller = this.getProfiler(); gameprofilerfiller.push("thunder"); @@ -108,12 +96,12 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e + final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change if (!this.paperConfig.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder -- blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); -+ blockposition.setValues(this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper +- blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15)); ++ blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper if (this.isRainingAt(blockposition)) { DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); - boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance; // Paper -@@ -703,59 +708,77 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper +@@ -698,66 +703,81 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } gameprofilerfiller.popPush("iceandsnow"); @@ -129,7 +117,7 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e + // Paper end Biome biomebase = this.getBiome(blockposition); -- if (biomebase.shouldFreeze(this, blockposition1)) { +- if (biomebase.shouldFreeze((LevelReader) this, blockposition1)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.defaultBlockState(), null); // CraftBukkit + // Paper start - optimise chunk ticking + blockposition.setY(downY); @@ -138,18 +126,24 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e + // Paper end } -+ blockposition.setY(normalY); // Paper - if (flag && biomebase.shouldSnow(this, blockposition)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit - } + if (flag) { ++ blockposition.setY(normalY); // Paper + if (biomebase.shouldSnow(this, blockposition)) { + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit + } -- if (flag && this.getBiome(blockposition1).getPrecipitation() == Biome.Precipitation.RAIN) { -- this.getBlockState(blockposition1).getBlock().handleRain((net.minecraft.world.level.Level) this, blockposition1); -+ // Paper start - optimise chunk ticking -+ blockposition.setY(downY); -+ if (flag && this.getBiome(blockposition).getPrecipitation() == Biome.Precipitation.RAIN) { -+ chunk.getBlockState(blockposition).getBlock().handleRain((net.minecraft.world.level.Level) this, blockposition); -+ // Paper end +- BlockState iblockdata = this.getBlockState(blockposition1); ++ blockposition.setY(downY); // Paper ++ BlockState iblockdata = this.getBlockState(blockposition); // Paper + Biome.Precipitation biomebase_precipitation = this.getBiome(blockposition).getPrecipitation(); + +- if (biomebase_precipitation == Biome.Precipitation.RAIN && biomebase.isColdEnoughToSnow(blockposition1)) { ++ if (biomebase_precipitation == Biome.Precipitation.RAIN && biomebase.isColdEnoughToSnow(blockposition)) { // Paper + biomebase_precipitation = Biome.Precipitation.SNOW; + } + +- iblockdata.getBlock().handlePrecipitation(iblockdata, (net.minecraft.world.level.Level) this, blockposition1, biomebase_precipitation); ++ iblockdata.getBlock().handlePrecipitation(iblockdata, (net.minecraft.world.level.Level) this, blockposition, biomebase_precipitation); // Paper } } @@ -160,27 +154,27 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e if (randomTickSpeed > 0) { - LevelChunkSection[] achunksection = chunk.getSections(); - int l = achunksection.length; +- +- for (int i1 = 0; i1 < l; ++i1) { +- LevelChunkSection chunksection = achunksection[i1]; + gameprofilerfiller.push("randomTick"); + timings.chunkTicksBlocks.startTiming(); // Paper -- for (int i1 = 0; i1 < l; ++i1) { -- LevelChunkSection chunksection = achunksection[i1]; -+ LevelChunkSection[] sections = chunk.getSections(); - - if (chunksection != LevelChunk.EMPTY_SECTION && chunksection.isRandomlyTicking()) { - int j1 = chunksection.bottomBlockY(); ++ LevelChunkSection[] sections = chunk.getSections(); + +- for (int k1 = 0; k1 < randomTickSpeed; ++k1) { +- BlockPos blockposition2 = this.getBlockRandomPos(j, j1, k, 15); + for (int sectionIndex = 0; sectionIndex < 16; ++sectionIndex) { + LevelChunkSection section = sections[sectionIndex]; + if (section == null || section.tickingList.size() == 0) { + continue; + } -- for (int k1 = 0; k1 < randomTickSpeed; ++k1) { -- BlockPos blockposition2 = this.getBlockRandomPos(j, j1, k, 15); -+ int yPos = sectionIndex << 4; - - gameprofilerfiller.push("randomTick"); -- BlockState iblockdata = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); +- BlockState iblockdata1 = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); ++ int yPos = sectionIndex << 4; + for (int a = 0; a < randomTickSpeed1; ++a) { + int tickingBlocks = section.tickingList.size(); + int index = this.randomTickRandom.nextInt(16 * 16 * 16); @@ -188,8 +182,8 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e + continue; + } -- if (iblockdata.isRandomlyTicking()) { -- iblockdata.randomTick(this, blockposition2, this.random); +- if (iblockdata1.isRandomlyTicking()) { +- iblockdata1.randomTick(this, blockposition2, this.random); - } + long raw = section.tickingList.getRaw(index); + int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); @@ -197,7 +191,7 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e + int randomY = ((location >>> (4 + 4)) & 255) | yPos; + int randomZ = (location >>> 4) & 15; -- FluidState fluid = iblockdata.getFluidState(); +- FluidState fluid = iblockdata1.getFluidState(); + BlockPos blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ); + BlockState iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); @@ -220,12 +214,12 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e - gameprofilerfiller.pop(); } - protected BlockPos findLightingTargetAround(BlockPos pos) { + private Optional findLightningRod(BlockPos pos) { diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java -index dd84984f28484cf7129c294222696784e128221a..9ea72751354e893cd3820befaa5df3e5e503de6e 100644 +index 9b955a027bd2c3cbcfa659a41a6687221c5fea63..6c036335b28258cd8c268173d73707af00d12bf9 100644 --- a/src/main/java/net/minecraft/util/BitStorage.java +++ b/src/main/java/net/minecraft/util/BitStorage.java -@@ -112,4 +112,32 @@ public class BitStorage { +@@ -105,4 +105,32 @@ public class BitStorage { } } @@ -259,7 +253,7 @@ index dd84984f28484cf7129c294222696784e128221a..9ea72751354e893cd3820befaa5df3e5 + // Paper end } diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index 42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3..0e15ca2fb9cd1aeb4a075b8d50350dd7fd463c72 100644 +index e638d982b4bd1d261a7282cad6dab98ad0b55213..e305173fd1652a8b88ae8a9b94d0fae083e2da95 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java +++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java @@ -91,7 +91,7 @@ public class Turtle extends Animal { @@ -272,10 +266,10 @@ index 42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3..0e15ca2fb9cd1aeb4a075b8d50350dd7 public BlockPos getHomePos() { // Paper - public diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 1d536d77518a70bdc1a23924aea99df1042b3cd5..632f32405053fbcff2fd26fa99f98c6add9f9dc7 100644 +index 07e81fa1119bba4981e34e70b9e67f43280f8071..5fccec12c0325dd9873905c5c3559128c3b4d9ad 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1472,10 +1472,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1299,10 +1299,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public abstract TagContainer getTagManager(); public BlockPos getBlockRandomPos(int x, int y, int z, int l) { @@ -296,27 +290,24 @@ index 1d536d77518a70bdc1a23924aea99df1042b3cd5..632f32405053fbcff2fd26fa99f98c6a public boolean noSave() { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 4fef3abe4b416cbebe1b456468b5c3e162de18f1..87d7a87a2925f2c062658e960bb5128738828d9f 100644 +index 922026da8c234427e0322443004d3c32993adfce..88b053d8181d2a5abdb2c5527529a81855e1de7c 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -639,8 +639,8 @@ public class LevelChunk implements ChunkAccess { - this.entities.remove(entity); // Paper - } +@@ -568,6 +568,7 @@ public class LevelChunk implements ChunkAccess { + @Override + public void addEntity(Entity entity) {} -- @Override -- public int getHeight(Heightmap.Types type, int x, int z) { + public final int getHighestBlockY(Heightmap.Types heightmap_type, int i, int j) { return this.getHeight(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1 -+ @Override public int getHeight(Heightmap.Types type, int x, int z) { // Paper + @Override + public int getHeight(Heightmap.Types type, int x, int z) { return ((Heightmap) this.heightmaps.get(type)).getFirstAvailable(x & 15, z & 15) - 1; - } - diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a71ad031d9 100644 +index 5fd66020a937b641e2a060cf38df731a43f3bf55..b5497272bc03a290298b5a829bdf653ac986866b 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -14,12 +14,14 @@ import net.minecraft.world.level.material.FluidState; - public class LevelChunkSection { - +@@ -14,11 +14,12 @@ public class LevelChunkSection { + public static final int SECTION_HEIGHT = 16; + public static final int SECTION_SIZE = 4096; public static final Palette GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState()); - private final int bottomBlockY; + final int bottomBlockY; // Paper - private -> package-private @@ -325,15 +316,13 @@ index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a7 + short tickingBlockCount; // Paper - private -> package-private private short tickingFluidCount; final PalettedContainer states; // Paper - package-private - + public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper -+ - // Paper start - Anti-Xray - Add parameters - @Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere - public LevelChunkSection(int i, ChunkAccess chunk, Level world, boolean initializeBlocks) { -@@ -74,6 +76,9 @@ public class LevelChunkSection { + + public LevelChunkSection(int yOffset) { + this(yOffset, (short)0, (short)0, (short)0); +@@ -70,6 +71,9 @@ public class LevelChunkSection { --this.nonEmptyBlockCount; - if (iblockdata1.isRandomlyTicking()) { + if (blockState.isRandomlyTicking()) { --this.tickingBlockCount; + // Paper start + this.tickingList.remove(x, y, z); @@ -341,7 +330,7 @@ index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a7 } } -@@ -85,6 +90,9 @@ public class LevelChunkSection { +@@ -81,6 +85,9 @@ public class LevelChunkSection { ++this.nonEmptyBlockCount; if (state.isRandomlyTicking()) { ++this.tickingBlockCount; @@ -351,7 +340,7 @@ index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a7 } } -@@ -120,23 +128,29 @@ public class LevelChunkSection { +@@ -116,22 +123,28 @@ public class LevelChunkSection { } public void recalcBlockCounts() { @@ -361,36 +350,35 @@ index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a7 this.nonEmptyBlockCount = 0; this.tickingBlockCount = 0; this.tickingFluidCount = 0; -- this.states.count((iblockdata, i) -> { -+ this.states.forEachLocation((iblockdata, location) -> { // Paper - FluidState fluid = iblockdata.getFluidState(); - - if (!iblockdata.isAir()) { -- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); - if (iblockdata.isRandomlyTicking()) { -- this.tickingBlockCount = (short) (this.tickingBlockCount + i); -+ this.tickingBlockCount = (short) (this.tickingBlockCount + 1); +- this.states.count((state, count) -> { ++ this.states.forEachLocation((state, location) -> { // Paper + FluidState fluidState = state.getFluidState(); + if (!state.isAir()) { +- this.nonEmptyBlockCount = (short)(this.nonEmptyBlockCount + count); ++ this.nonEmptyBlockCount = (short)(this.nonEmptyBlockCount + 1); // Paper + if (state.isRandomlyTicking()) { +- this.tickingBlockCount = (short)(this.tickingBlockCount + count); + // Paper start -+ this.tickingList.add(location, iblockdata); ++ this.tickingBlockCount = (short)(this.tickingBlockCount + 1); ++ this.tickingList.add(location, state); + // Paper end } } - if (!fluid.isEmpty()) { -- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); - if (fluid.isRandomlyTicking()) { -- this.tickingFluidCount = (short) (this.tickingFluidCount + i); -+ this.tickingFluidCount = (short) (this.tickingFluidCount + 1); + if (!fluidState.isEmpty()) { +- this.nonEmptyBlockCount = (short)(this.nonEmptyBlockCount + count); ++ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); // Paper + if (fluidState.isRandomlyTicking()) { +- this.tickingFluidCount = (short)(this.tickingFluidCount + count); ++ this.tickingFluidCount = (short) (this.tickingFluidCount + 1); // Paper } } diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index dd252372e1e380674b1191e9ea265cbb10de437b..f93316b3ae5cd5fb960fa24f8c921b5b9276d9f3 100644 +index 5ea60bbb56450502f1ceb41959239ab579458ac2..5ac948b5b82f3144cdf402af440251cb8c7369d7 100644 --- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -285,6 +285,14 @@ public class PalettedContainer implements PaletteResize { +@@ -259,6 +259,14 @@ public class PalettedContainer implements PaletteResize { }); } @@ -404,4 +392,4 @@ index dd252372e1e380674b1191e9ea265cbb10de437b..f93316b3ae5cd5fb960fa24f8c921b5b + @FunctionalInterface public interface CountConsumer { - + void accept(T object, int count); diff --git a/patches/server-remapped/0409-Entity-Jump-API.patch b/patches/server/0369-Entity-Jump-API.patch similarity index 87% rename from patches/server-remapped/0409-Entity-Jump-API.patch rename to patches/server/0369-Entity-Jump-API.patch index 15c22b27a5..9a22507440 100644 --- a/patches/server-remapped/0409-Entity-Jump-API.patch +++ b/patches/server/0369-Entity-Jump-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Entity Jump API diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index b84dab1043c56e2deb58aec8639226f98db165d1..43fbe7d220f61802ae0cb0620ad078c5df7b69bc 100644 +index bd1cc5e6fea4b9a171718c1249f652782b7ce13e..6cc2d26403aa5074218b4b76e2d8ed9e8409a0ae 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2873,8 +2873,10 @@ public abstract class LivingEntity extends Entity { +@@ -3159,8 +3159,10 @@ public abstract class LivingEntity extends Entity { } else if (this.isInLava() && (!this.onGround || d7 > d8)) { this.jumpInLiquid((Tag) FluidTags.LAVA); } else if ((this.onGround || flag && d7 <= d8) && this.noJumpDelay == 0) { @@ -20,10 +20,10 @@ index b84dab1043c56e2deb58aec8639226f98db165d1..43fbe7d220f61802ae0cb0620ad078c5 } else { this.noJumpDelay = 0; diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java -index 1621d8748e96c6e1abb33b699a1273bb698f67d2..423bdbe25b6f2261cb5092378b0564a82faeecb4 100644 +index 2d59eab846db2c0a624cf6d06a570b2313aa6b13..851ee58e52c6003d6ae7b58c9b6b9a9a9795fa85 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Panda.java +++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java -@@ -489,7 +489,9 @@ public class Panda extends Animal { +@@ -514,7 +514,9 @@ public class Panda extends Animal { Panda entitypanda = (Panda) iterator.next(); if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.canPerformAction()) { @@ -34,7 +34,7 @@ index 1621d8748e96c6e1abb33b699a1273bb698f67d2..423bdbe25b6f2261cb5092378b0564a8 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index a01bd035846df0e2e28dc55e2ef2f5f35b83f905..5dac3bf5a117bfbf57798238f0614558deafcd1b 100644 +index 5477f288db57d63051f4579b8cd3c19e3af430ee..76e9977f7b2f7fb50631fc56f3318d59d04b1398 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -792,5 +792,19 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { diff --git a/patches/server-remapped/0410-Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/0370-Add-option-to-nerf-pigmen-from-nether-portals.patch similarity index 58% rename from patches/server-remapped/0410-Add-option-to-nerf-pigmen-from-nether-portals.patch rename to patches/server/0370-Add-option-to-nerf-pigmen-from-nether-portals.patch index d66918d012..ede8b0de95 100644 --- a/patches/server-remapped/0410-Add-option-to-nerf-pigmen-from-nether-portals.patch +++ b/patches/server/0370-Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -5,24 +5,26 @@ Subject: [PATCH] Add option to nerf pigmen from nether portals diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7fbd501d70dccf869a4454e2789a5d68f2e15754..9e4591ddc4b755f4ff5a6f1078b51cb13db80480 100644 +index 3cd8895adecd345c3bdfb8b5e3e9fdf0ef9097db..e70e0b1115422b9b901c2879138433da2d4f94d8 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -594,4 +594,9 @@ public class PaperWorldConfig { - disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); +@@ -441,6 +441,11 @@ public class PaperWorldConfig { log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); } -+ + + public boolean nerfNetherPortalPigmen = false; + private void nerfNetherPortalPigmen() { + nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); + } - } ++ + public int lightQueueSize = 20; + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index efc9cb6def2f4ee327329dc090d2918ff60d8e19..43f77d01fceab107d3502d282205aa579d64cc4b 100644 +index 3d3286070c9c4db6d6487e119070794dadf493bd..facb09e49d92d22dbcde7d187d4ba1c9a04202a9 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -277,6 +277,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -307,6 +307,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public long activatedTick = Integer.MIN_VALUE; public boolean isTemporarilyActive = false; // Paper public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one @@ -30,42 +32,34 @@ index efc9cb6def2f4ee327329dc090d2918ff60d8e19..43f77d01fceab107d3502d282205aa57 protected int numCollisions = 0; // Paper public void inactiveTick() { } // Spigot end -@@ -1693,6 +1694,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1861,6 +1862,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n if (spawnedViaMobSpawner) { - tag.putBoolean("Paper.FromMobSpawner", true); + nbt.putBoolean("Paper.FromMobSpawner", true); } + if (fromNetherPortal) { -+ tag.putBoolean("Paper.FromNetherPortal", true); ++ nbt.putBoolean("Paper.FromNetherPortal", true); + } // Paper end - return tag; + return nbt; } catch (Throwable throwable) { -@@ -1827,6 +1831,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1999,6 +2003,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } - spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ fromNetherPortal = tag.getBoolean("Paper.FromNetherPortal"); - if (tag.contains("Paper.SpawnReason")) { - String spawnReasonName = tag.getString("Paper.SpawnReason"); + spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ fromNetherPortal = nbt.getBoolean("Paper.FromNetherPortal"); + if (nbt.contains("Paper.SpawnReason")) { + String spawnReasonName = nbt.getString("Paper.SpawnReason"); try { diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -index 805d83a93bce20910d17c3f419bc085251b6cfc1..ae58929886921d0714bf811de92f99dc0dc120dc 100644 +index e34716f2a19eb578fef3f19182c124d359deb88f..cfea29f5bf1c5e74a0292c1344baaaa49c2f4403 100644 --- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -@@ -8,6 +8,7 @@ import net.minecraft.network.chat.Component; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.entity.Mob; - import net.minecraft.world.entity.MobSpawnType; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.level.BlockGetter; -@@ -61,6 +62,8 @@ public class NetherPortalBlock extends Block { +@@ -66,6 +66,8 @@ public class NetherPortalBlock extends Block { if (entity != null) { entity.setPortalCooldown(); + entity.fromNetherPortal = true; // Paper -+ if (world.paperConfig.nerfNetherPortalPigmen) ((Mob) entity).aware = false; // Paper ++ if (world.paperConfig.nerfNetherPortalPigmen) ((net.minecraft.world.entity.Mob) entity).aware = false; // Paper } } } diff --git a/patches/server-remapped/0411-Make-the-GUI-graph-fancier.patch b/patches/server/0371-Make-the-GUI-graph-fancier.patch similarity index 80% rename from patches/server-remapped/0411-Make-the-GUI-graph-fancier.patch rename to patches/server/0371-Make-the-GUI-graph-fancier.patch index c98d2918e6..202d52ab06 100644 --- a/patches/server-remapped/0411-Make-the-GUI-graph-fancier.patch +++ b/patches/server/0371-Make-the-GUI-graph-fancier.patch @@ -109,7 +109,7 @@ index 0000000000000000000000000000000000000000..186fc722965e403f76b1480e1c2381fc +} diff --git a/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java new file mode 100644 -index 0000000000000000000000000000000000000000..0f29ad583e798c09b2fe3f568ed50cbc719e40e2 +index 0000000000000000000000000000000000000000..537bc6213545e8ff1b7b51bc4b27fd5b2a740883 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java @@ -0,0 +1,41 @@ @@ -149,14 +149,14 @@ index 0000000000000000000000000000000000000000..0f29ad583e798c09b2fe3f568ed50cbc + return new Dimension(350, 200); + } + -+ public void stop() { a(); } public void a() { ++ public void close() { + timer.stop(); + ramGraph.stop(); + } +} diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java new file mode 100644 -index 0000000000000000000000000000000000000000..c0923ec75ecced2e0a1c0d3ec2c046d69af3e9a9 +index 0000000000000000000000000000000000000000..23239679d6584f1088b2b94c46eb9a5c1f9ad91d --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java @@ -0,0 +1,73 @@ @@ -176,7 +176,7 @@ index 0000000000000000000000000000000000000000..c0923ec75ecced2e0a1c0d3ec2c046d6 +import java.util.Vector; + +public class RAMDetails extends JList { -+ public static final DecimalFormat DECIMAL_FORMAT = Util.peek(new DecimalFormat("########0.000"), (format) ++ public static final DecimalFormat DECIMAL_FORMAT = Util.make(new DecimalFormat("########0.000"), (format) + -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT))); + + private final MinecraftServer server; @@ -221,7 +221,7 @@ index 0000000000000000000000000000000000000000..c0923ec75ecced2e0a1c0d3ec2c046d6 + Vector vector = new Vector<>(); + vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); + vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); -+ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); ++ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.tickTimes)) + " ms"); + setListData(vector); + } + @@ -383,57 +383,16 @@ index 0000000000000000000000000000000000000000..c3e54da4ab6440811aab2f9dd1e21880 + timer.stop(); + } +} -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index cec5ad5052c8cf6059e9b117117846bdb217748f..c2f747226f10479c826849af898538610a2dd659 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -259,6 +259,7 @@ public class Util { - return factory.get(); - } - -+ public static T peek(T t0, Consumer consumer) { return make(t0, consumer); } // Paper - OBFHELPER - public static T make(T object, Consumer initializer) { - initializer.accept(object); - return object; -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 7038897b8fb4c18ca97b95a3b24c30b40b62b005..e33189dc8375a3034910087654607fb531061636 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -216,7 +216,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop collection = this.finalizers; // CraftBukkit - decompile error -- this.finalizers.add(guistatscomponent::close); -+ this.finalizers.add(guistatscomponent::a); - jpanel.add(guistatscomponent, "North"); - jpanel.add(this.buildPlayerPanel(), "Center"); - jpanel.setBorder(new TitledBorder(new EtchedBorder(), "Stats")); -diff --git a/src/main/java/net/minecraft/server/gui/StatsComponent.java b/src/main/java/net/minecraft/server/gui/StatsComponent.java -index 30960738de03edf7aa8745a176b3a2be86eaf282..09414d04208a843f8d337569b53f61b34e64ed92 100644 ---- a/src/main/java/net/minecraft/server/gui/StatsComponent.java -+++ b/src/main/java/net/minecraft/server/gui/StatsComponent.java -@@ -13,7 +13,7 @@ import net.minecraft.server.MinecraftServer; - - public class StatsComponent extends JComponent { - -- private static final DecimalFormat DECIMAL_FORMAT = (DecimalFormat) Util.make((Object) (new DecimalFormat("########0.000")), (decimalformat) -> { -+ private static final DecimalFormat DECIMAL_FORMAT = (DecimalFormat) Util.make(new DecimalFormat("########0.000"), (decimalformat) -> { // Paper - decompile error - decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); - }); - private final int[] values = new int[256]; + Objects.requireNonNull(guistatscomponent); diff --git a/patches/server-remapped/0412-add-hand-to-BlockMultiPlaceEvent.patch b/patches/server/0372-add-hand-to-BlockMultiPlaceEvent.patch similarity index 89% rename from patches/server-remapped/0412-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/server/0372-add-hand-to-BlockMultiPlaceEvent.patch index e93352bf03..02e47511bf 100644 --- a/patches/server-remapped/0412-add-hand-to-BlockMultiPlaceEvent.patch +++ b/patches/server/0372-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 e696d2e52532df25d74a1f559e2c9ca0f3d5058d..7d9a3b65b2d6b294d3a11414289e64fac88665f0 100644 +index c3341d1c4e9cda85b0b236461b0a00cbebc9a856..98bec353d6dbd85c7b329f75e09f4d0bfcfdaa6c 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -337,13 +337,18 @@ public class CraftEventFactory { +@@ -339,13 +339,18 @@ public class CraftEventFactory { } org.bukkit.inventory.ItemStack item; diff --git a/patches/server-remapped/0413-Prevent-teleporting-dead-entities.patch b/patches/server/0373-Prevent-teleporting-dead-entities.patch similarity index 67% rename from patches/server-remapped/0413-Prevent-teleporting-dead-entities.patch rename to patches/server/0373-Prevent-teleporting-dead-entities.patch index ef6164bd27..59a60c41af 100644 --- a/patches/server-remapped/0413-Prevent-teleporting-dead-entities.patch +++ b/patches/server/0373-Prevent-teleporting-dead-entities.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Prevent teleporting dead entities diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 2b79413bb8a592a7b7093e11d3a0cce895286c8f..09a663cc53cdf8ae45352b280200c8170dbbcdfc 100644 +index 9240064a17e7ac2492fe157b759d1f724105cd0e..fcfd57fd7af655aafb330986e8f6f9cc55819165 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1468,6 +1468,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1501,6 +1501,10 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } - private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { -+ if (player.removed) { -+ LOGGER.info("Attempt to teleport dead player {} restricted", player.getScoreboardName()); + private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set, boolean flag) { ++ if (player.isRemoved()) { ++ LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName()); + return; + } // CraftBukkit start diff --git a/patches/server-remapped/0414-Validate-tripwire-hook-placement-before-update.patch b/patches/server/0374-Validate-tripwire-hook-placement-before-update.patch similarity index 85% rename from patches/server-remapped/0414-Validate-tripwire-hook-placement-before-update.patch rename to patches/server/0374-Validate-tripwire-hook-placement-before-update.patch index 8fbefb7aec..37fe80e7fc 100644 --- a/patches/server-remapped/0414-Validate-tripwire-hook-placement-before-update.patch +++ b/patches/server/0374-Validate-tripwire-hook-placement-before-update.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Validate tripwire hook placement before update diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java -index f44d4809fe87c832e4d3bda429af2254e8c746d6..20428aff54527b664d988a6a0f54236b693fda89 100644 +index 3a5252afa9681fb1956493bead27e6cdb13679ca..0cfa1abca2c5744a4147b05905983ae4acaa569a 100644 --- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java +++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java -@@ -169,6 +169,7 @@ public class TripWireHookBlock extends Block { +@@ -174,6 +174,7 @@ public class TripWireHookBlock extends Block { this.playSound(world, pos, flag4, flag5, flag2, flag3); if (!beingRemoved) { diff --git a/patches/server-remapped/0415-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server/0375-Add-option-to-allow-iron-golems-to-spawn-in-air.patch similarity index 85% rename from patches/server-remapped/0415-Add-option-to-allow-iron-golems-to-spawn-in-air.patch rename to patches/server/0375-Add-option-to-allow-iron-golems-to-spawn-in-air.patch index 163f5b9240..35a64d65e2 100644 --- a/patches/server-remapped/0415-Add-option-to-allow-iron-golems-to-spawn-in-air.patch +++ b/patches/server/0375-Add-option-to-allow-iron-golems-to-spawn-in-air.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to allow iron golems to spawn in air diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9e4591ddc4b755f4ff5a6f1078b51cb13db80480..fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f 100644 +index e70e0b1115422b9b901c2879138433da2d4f94d8..19e0532ea296d6862ab6508658726e96e05346c9 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -387,6 +387,11 @@ public class PaperWorldConfig { +@@ -380,6 +380,11 @@ public class PaperWorldConfig { scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); } @@ -21,10 +21,10 @@ index 9e4591ddc4b755f4ff5a6f1078b51cb13db80480..fe1c9dd8258ec8c3fdf343d4a44de2be private void armorStandEntityLookups() { armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -index 9cedac83304847bdc92c2e97c4e6e119664c3bd0..59f0224b6a743408a03b642dd7cbe545f406c57e 100644 +index b5481299f551b7150425a4a1b1c21b43d8a1d382..ec00c2dd8f969eb99ec6a014e3bcd09c7484b237 100644 --- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -@@ -297,7 +297,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { +@@ -322,7 +322,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { BlockPos blockposition1 = blockposition.below(); BlockState iblockdata = world.getBlockState(blockposition1); diff --git a/patches/server-remapped/0416-Configurable-chance-of-villager-zombie-infection.patch b/patches/server/0376-Configurable-chance-of-villager-zombie-infection.patch similarity index 63% rename from patches/server-remapped/0416-Configurable-chance-of-villager-zombie-infection.patch rename to patches/server/0376-Configurable-chance-of-villager-zombie-infection.patch index 1bf93843e4..7c01b2f514 100644 --- a/patches/server-remapped/0416-Configurable-chance-of-villager-zombie-infection.patch +++ b/patches/server/0376-Configurable-chance-of-villager-zombie-infection.patch @@ -8,37 +8,38 @@ This allows you to solve an issue in vanilla behavior where: * On normal difficulty they will have a 50% of getting infected or dying. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f..525d702d78a609af987ebd2c32169b873e5c05ed 100644 +index 19e0532ea296d6862ab6508658726e96e05346c9..b57d9c84db5685b86cb077e3b42db7a8578d6f62 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -604,4 +604,9 @@ public class PaperWorldConfig { - private void nerfNetherPortalPigmen() { +@@ -451,6 +451,11 @@ public class PaperWorldConfig { nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); } -+ + + public double zombieVillagerInfectionChance = -1.0; + private void zombieVillagerInfectionChance() { + zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); + } - } ++ + public int lightQueueSize = 20; + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 6fecf4188fc0247143edc688c03e645376960687..1e7c2c603b967c8c606efd94ce95a17c856f78d7 100644 +index ee17cba501e0cc4822bd1278d18b561c77fe9674..b036cbb9a1b6bcac91ffc8ee659fc95d6e04d5d4 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -447,10 +447,14 @@ public class Zombie extends Monster { +@@ -453,10 +453,13 @@ public class Zombie extends Monster { @Override - public void killed(ServerLevel worldserver, LivingEntity entityliving) { - super.killed(worldserver, entityliving); -- if ((worldserver.getDifficulty() == Difficulty.NORMAL || worldserver.getDifficulty() == Difficulty.HARD) && entityliving instanceof Villager) { -- if (worldserver.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { -+ // Paper start -+ if (level.paperConfig.zombieVillagerInfectionChance != 0.0 && (level.paperConfig.zombieVillagerInfectionChance != -1.0 || worldserver.getDifficulty() == Difficulty.NORMAL || worldserver.getDifficulty() == Difficulty.HARD) && entityliving instanceof Villager) { -+ if (level.paperConfig.zombieVillagerInfectionChance == -1.0 && worldserver.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { + public void killed(ServerLevel world, LivingEntity other) { + super.killed(world, other); +- if ((world.getDifficulty() == Difficulty.NORMAL || world.getDifficulty() == Difficulty.HARD) && other instanceof Villager) { +- if (world.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { ++ if (level.paperConfig.zombieVillagerInfectionChance != 0.0 && (level.paperConfig.zombieVillagerInfectionChance != -1.0 || world.getDifficulty() == Difficulty.NORMAL || world.getDifficulty() == Difficulty.HARD) && other instanceof Villager) { ++ if (level.paperConfig.zombieVillagerInfectionChance == -1.0 && world.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { return; } + if (level.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > level.paperConfig.zombieVillagerInfectionChance) { + return; + } // Paper end - Villager entityvillager = (Villager) entityliving; + Villager entityvillager = (Villager) other; // CraftBukkit start diff --git a/patches/server-remapped/0417-Optimise-Chunk-getFluid.patch b/patches/server/0377-Optimise-Chunk-getFluid.patch similarity index 58% rename from patches/server-remapped/0417-Optimise-Chunk-getFluid.patch rename to patches/server/0377-Optimise-Chunk-getFluid.patch index 2ba043c076..13d8263759 100644 --- a/patches/server-remapped/0417-Optimise-Chunk-getFluid.patch +++ b/patches/server/0377-Optimise-Chunk-getFluid.patch @@ -8,22 +8,24 @@ faster on its own, however removing the try catch makes it easier to inline due to code size diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 87d7a87a2925f2c062658e960bb5128738828d9f..8a14bdda4a408ec1e2b51efeb35467835f62b42c 100644 +index 88b053d8181d2a5abdb2c5527529a81855e1de7c..59a77541bbda880ae8f84e3535a2b6112caa78fb 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -430,25 +430,29 @@ public class LevelChunk implements ChunkAccess { +@@ -461,18 +461,20 @@ public class LevelChunk implements ChunkAccess { } public FluidState getFluidState(int x, int y, int z) { - try { -- if (y >= 0 && y >> 4 < this.sections.length) { -- LevelChunkSection chunksection = this.sections[y >> 4]; +- int l = this.getSectionIndex(y); +- +- if (l >= 0 && l < this.sections.length) { +- LevelChunkSection chunksection = this.sections[l]; - - if (!LevelChunkSection.isEmpty(chunksection)) { - return chunksection.getFluidState(x & 15, y & 15, z & 15); -+ //try { // Paper - remove try catch ++ // try { // Paper - remove try catch + // Paper start - reduce the number of ops in this call -+ int index = y >> 4; ++ int index = this.getSectionIndex(y); + if (index >= 0 && index < this.sections.length) { + LevelChunkSection chunksection = this.sections[index]; + @@ -34,17 +36,11 @@ index 87d7a87a2925f2c062658e960bb5128738828d9f..8a14bdda4a408ec1e2b51efeb3546783 } return Fluids.EMPTY.defaultFluidState(); -- } catch (Throwable throwable) { -- CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state"); -- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got"); -+ /*} catch (Throwable throwable) { // Paper - remove try catch -+ CrashReport crashreport = CrashReport.a(throwable, "Getting fluid state"); -+ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being got"); - -- crashreportsystemdetails.setDetail("Location", () -> { -- return CrashReportCategory.formatLocation(x, y, z); -+ crashreportsystemdetails.a("Location", () -> { -+ return CrashReportSystemDetails.a(i, j, k); ++ /* // Paper - remove try catch + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got"); +@@ -482,6 +484,7 @@ public class LevelChunk implements ChunkAccess { }); throw new ReportedException(crashreport); } @@ -53,15 +49,15 @@ index 87d7a87a2925f2c062658e960bb5128738828d9f..8a14bdda4a408ec1e2b51efeb3546783 // CraftBukkit start diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index c44d32f966c61497b4a8892eb51da3a71ad031d9..5e7f6000df129100ef306703f325af9f60da8ae6 100644 +index b5497272bc03a290298b5a829bdf653ac986866b..fa350db3f4ada07a385d9f57b46aa799effb6039 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -45,7 +45,7 @@ public class LevelChunkSection { +@@ -42,7 +42,7 @@ public class LevelChunkSection { } public FluidState getFluidState(int x, int y, int z) { -- return ((BlockState) this.states.get(x, y, z)).getFluidState(); -+ return ((BlockState) this.states.get(x, y, z)).getFluidState(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid. +- return this.states.get(x, y, z).getFluidState(); ++ return this.states.get(x, y, z).getFluidState(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid. } public void acquire() { diff --git a/patches/server-remapped/0418-Optimise-TickListServer-by-rewriting-it.patch b/patches/server/0378-Optimise-TickListServer-by-rewriting-it.patch similarity index 66% rename from patches/server-remapped/0418-Optimise-TickListServer-by-rewriting-it.patch rename to patches/server/0378-Optimise-TickListServer-by-rewriting-it.patch index 6cf945010b..b5d38ff419 100644 --- a/patches/server-remapped/0418-Optimise-TickListServer-by-rewriting-it.patch +++ b/patches/server/0378-Optimise-TickListServer-by-rewriting-it.patch @@ -61,7 +61,7 @@ index 8bf4d2b8c38c02d6a5b2fea37113689a252f1571..da93d38fe63035e4ff198ada84a4431f ConfigurationSection section; diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java new file mode 100644 -index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2d579909b +index 0000000000000000000000000000000000000000..da13ff17609b7bc8076d9297edf8decf01a2ed88 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java @@ -0,0 +1,628 @@ @@ -168,7 +168,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + + private void queueEntryForTick(final TickNextTickData entry, final ServerChunkCache chunkProvider) { + if (entry.tickState == STATE_SCHEDULED) { -+ if (chunkProvider.isTickingReadyMainThread(entry.getPosition())) { ++ if (chunkProvider.isTickingReadyMainThread(entry.pos)) { + this.toTickThisTick.add(entry); + entry.tickState = STATE_PENDING_TICK; + } else { @@ -179,13 +179,13 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + + private void addToNotTickingReady(final TickNextTickData entry) { -+ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (long keyInMap) -> { ++ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.pos), (long keyInMap) -> { + return new ArrayList<>(); + }).add(entry); + } + + private void addToSchedule(final TickNextTickData entry) { -+ long delay = entry.getTargetTick() - (this.currentTick + 1); ++ long delay = entry.triggerTick - (this.currentTick + 1); + if (delay < SHORT_SCHEDULE_TICK_THRESHOLD) { + if (delay < 0) { + // longScheduled orders by tick time, short scheduled does not @@ -202,7 +202,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + entry.tickState = STATE_CANCELLED_TICK; + // short/long scheduled will skip the entry + -+ final BlockPos pos = entry.getPosition(); ++ final BlockPos pos = entry.pos; + final long blockKey = MCUtil.getBlockKey(pos); + + final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); @@ -221,7 +221,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + } + -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ final long chunkKey = MCUtil.getCoordinateKey(entry.pos); + + ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); + @@ -246,7 +246,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + } + -+ long delay = entry.getTargetTick() - (this.currentTick + 1); ++ long delay = entry.triggerTick - (this.currentTick + 1); + if (delay >= SHORT_SCHEDULE_TICK_THRESHOLD) { + this.longScheduled.remove(entry); + } @@ -274,7 +274,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + + // we don't remove items from shortScheduled (but do from longScheduled) because they're cleared at the end of + // this tick -+ if (this.longScheduled.isEmpty() || this.longScheduled.first().getTargetTick() > currentTick) { ++ if (this.longScheduled.isEmpty() || this.longScheduled.first().triggerTick > currentTick) { + // nothing in longScheduled to worry about + final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; + for (int i = 0, len = interval.byPriority.length; i < len; ++i) { @@ -300,7 +300,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + longScheduledIterator.remove(); + if (longScheduledIterator.hasNext()) { + longCurrent = longScheduledIterator.next(); -+ if (longCurrent.getTargetTick() > currentTick) { ++ if (longCurrent.triggerTick > currentTick) { + longCurrent = null; + break; + } @@ -316,7 +316,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + + // add remaining from long scheduled + for (;;) { -+ if (longCurrent == null || longCurrent.getTargetTick() > currentTick) { ++ if (longCurrent == null || longCurrent.triggerTick > currentTick) { + break; + } + longScheduledIterator.remove(); @@ -368,7 +368,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + continue; + } + try { -+ if (chunkProvider.isTickingReadyMainThread(toTick.getPosition())) { ++ if (chunkProvider.isTickingReadyMainThread(toTick.pos)) { + toTick.tickState = STATE_TICKING; + this.tickFunction.accept(toTick); + if (toTick.tickState == STATE_TICKING) { @@ -384,7 +384,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + CrashReport crashreport = CrashReport.forThrowable(thr, "Exception while ticking"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being ticked"); + -+ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, toTick.getPosition(), (BlockState) null); ++ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.world, toTick.pos, (BlockState) null); + throw new ReportedException(crashreport); + // end copy from TickListServer + } @@ -413,7 +413,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + entry.tickState = STATE_UNSCHEDULED; + -+ final BlockPos pos = entry.getPosition(); ++ final BlockPos pos = entry.pos; + final long blockKey = MCUtil.getBlockKey(pos); + + final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); @@ -432,7 +432,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + } + -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ final long chunkKey = MCUtil.getCoordinateKey(entry.pos); + + ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); + @@ -446,7 +446,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + + @Override -+ public boolean isPendingTickThisTick(final BlockPos blockposition, final T data) { ++ public boolean willTickThisTick(final BlockPos blockposition, final T data) { + final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); + + if (entries == null) { @@ -455,7 +455,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + + for (int i = 0, size = entries.size(); i < size; ++i) { + final TickNextTickData entry = entries.get(i); -+ if (entry.getData() == data && entry.tickState == STATE_PENDING_TICK) { ++ if (entry.getType() == data && entry.tickState == STATE_PENDING_TICK) { + return true; + } + } @@ -464,7 +464,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + + @Override -+ public boolean isScheduledForTick(final BlockPos blockposition, final T data) { ++ public boolean hasScheduledTick(final BlockPos blockposition, final T data) { + final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); + + if (entries == null) { @@ -473,7 +473,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + + for (int i = 0, size = entries.size(); i < size; ++i) { + final TickNextTickData entry = entries.get(i); -+ if (entry.getData() == data && entry.tickState == STATE_SCHEDULED) { ++ if (entry.getType() == data && entry.tickState == STATE_SCHEDULED) { + return true; + } + } @@ -482,22 +482,22 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + + @Override -+ public void schedule(BlockPos blockPosition, T t, int i, TickPriority tickListPriority) { ++ public void scheduleTick(BlockPos blockPosition, T t, int i, TickPriority tickListPriority) { + this.schedule(blockPosition, t, i + this.currentTick, tickListPriority); + } + + public void schedule(final TickNextTickData entry) { -+ this.schedule(entry.getPosition(), entry.getData(), entry.getTargetTick(), entry.getPriority()); ++ this.schedule(entry.pos, entry.getType(), entry.triggerTick, entry.priority); + } + + public void schedule(final BlockPos pos, final T data, final long targetTick, final TickPriority priority) { + final TickNextTickData entry = new TickNextTickData<>(pos, data, targetTick, priority); -+ if (this.excludeFromScheduling.test(entry.getData())) { ++ if (this.excludeFromScheduling.test(entry.getType())) { + return; + } + + if (WARN_ON_EXCESSIVE_DELAY) { -+ final long delay = entry.getTargetTick() - this.currentTick; ++ final long delay = entry.triggerTick - this.currentTick; + if (delay >= EXCESSIVE_DELAY_THRESHOLD) { + MinecraftServer.LOGGER.warn("Entry " + entry.toString() + " has been scheduled with an excessive delay of: " + delay, new Throwable()); + } @@ -514,7 +514,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + final TickNextTickData currentEntry = currentEntries.get(i); + + // entries are only blocked from scheduling if currentEntry.equals(toSchedule) && currentEntry is scheduled to tick (NOT including pending) -+ if (currentEntry.getData() == entry.getData() && currentEntry.tickState == STATE_SCHEDULED) { ++ if (currentEntry.getType() == entry.getType() && currentEntry.tickState == STATE_SCHEDULED) { + // can't add + return; + } @@ -524,7 +524,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + + entry.tickState = STATE_SCHEDULED; + -+ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (final long keyInMap) -> { ++ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.pos), (final long keyInMap) -> { + return new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); + }).add(entry); + @@ -541,19 +541,19 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + // i.e the y value is ignored? the x, z calc isn't correct? + // however for the copy op they use the correct intersection, after using this one of course... + private static boolean isBlockInSortof(final BoundingBox boundingBox, final BlockPos pos) { -+ return pos.getX() >= boundingBox.getMinX() && pos.getX() < boundingBox.getMaxX() && pos.getZ() >= boundingBox.getMinZ() && pos.getZ() < boundingBox.getMaxZ(); ++ return pos.getX() >= boundingBox.minX() && pos.getX() < boundingBox.maxX() && pos.getZ() >= boundingBox.minZ() && pos.getZ() < boundingBox.maxZ(); + } + + @Override -+ public List> getEntriesInBoundingBox(final BoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { -+ if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) { ++ public List> fetchTicksInArea(final BoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { ++ if (structureboundingbox.minX() == structureboundingbox.maxX() || structureboundingbox.minZ() == structureboundingbox.maxZ()) { + return Collections.emptyList(); // vanilla behaviour, check isBlockInSortof above + } + -+ final int lowerChunkX = structureboundingbox.getMinX() >> 4; -+ final int upperChunkX = (structureboundingbox.getMaxX() - 1) >> 4; // subtract 1 since maxX is exclusive -+ final int lowerChunkZ = structureboundingbox.getMinZ() >> 4; -+ final int upperChunkZ = (structureboundingbox.getMaxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive ++ final int lowerChunkX = structureboundingbox.minX() >> 4; ++ final int upperChunkX = (structureboundingbox.maxX() - 1) >> 4; // subtract 1 since maxX is exclusive ++ final int lowerChunkZ = structureboundingbox.minZ() >> 4; ++ final int upperChunkZ = (structureboundingbox.maxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive + + final int xChunksLength = (upperChunkX - lowerChunkX + 1); + final int zChunksLength = (upperChunkZ - lowerChunkZ + 1); @@ -579,7 +579,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); + + MCUtil.mergeSortedSets((TickNextTickData entry) -> { -+ if (!isBlockInSortof(structureboundingbox, entry.getPosition())) { ++ if (!isBlockInSortof(structureboundingbox, entry.pos)) { + return; + } + final int tickState = entry.tickState; @@ -603,24 +603,24 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + @Override + public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { + // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInBoundingBox(structureboundingbox, false, false); ++ List> list = this.fetchTicksInArea(structureboundingbox, false, false); + Iterator> iterator = list.iterator(); + + while (iterator.hasNext()) { + TickNextTickData nextticklistentry = iterator.next(); + -+ if (structureboundingbox.hasPoint( nextticklistentry.getPosition())) { -+ BlockPos blockposition1 = nextticklistentry.getPosition().add(blockposition); -+ T t0 = nextticklistentry.getData(); ++ if (structureboundingbox.isInside( nextticklistentry.pos)) { ++ BlockPos blockposition1 = nextticklistentry.pos.offset(blockposition); ++ T t0 = nextticklistentry.getType(); + -+ this.schedule(new TickNextTickData<>(blockposition1, t0, nextticklistentry.getTargetTick(), nextticklistentry.getPriority())); ++ this.schedule(new TickNextTickData<>(blockposition1, t0, nextticklistentry.triggerTick, nextticklistentry.priority)); + } + } + // end copy from TickListServer + } + + @Override -+ public List> getEntriesInChunk(ChunkPos chunkPos, boolean removeReturned, boolean excludeTicked) { ++ public List> fetchTicksInChunk(ChunkPos chunkPos, boolean removeReturned, boolean excludeTicked) { + // Vanilla DOES get the entries 2 blocks out of the chunk too, but that doesn't matter since we ignore chunks + // not at ticking status, and ticking status requires neighbours loaded + // so with this method we will reduce scheduler churning @@ -651,16 +651,16 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + + @Override -+ public ListTag serialize(ChunkPos chunkcoordintpair) { ++ public ListTag save(ChunkPos chunkcoordintpair) { + // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInChunk(chunkcoordintpair, false, true); ++ List> list = this.fetchTicksInChunk(chunkcoordintpair, false, true); + -+ return ServerTickList.serialize(this.getMinecraftKeyFrom, list, this.currentTick); ++ return ServerTickList.saveTickList(this.getMinecraftKeyFrom, list, this.currentTick); + // end copy from TickListServer + } + + @Override -+ public int getTotalScheduledEntries() { ++ public int size() { + // good thing this is only used in debug reports // TODO check on update + int ret = 0; + @@ -695,7 +695,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 +} diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java new file mode 100644 -index 0000000000000000000000000000000000000000..d40a7aff6c27883f3ae8ba878a94c97242619f2c +index 0000000000000000000000000000000000000000..a1e6f49274a7ae8057a9112e0dd6597a8e58e6da --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java @@ -0,0 +1,41 @@ @@ -713,7 +713,7 @@ index 0000000000000000000000000000000000000000..d40a7aff6c27883f3ae8ba878a94c972 + public static final Comparator> ENTRY_COMPARATOR_BY_ID = (entry1, entry2) -> { + return Long.compare(entry1.getId(), entry2.getId()); + }; -+ public static final Comparator> ENTRY_COMPARATOR = (Comparator)TickNextTickData.comparator(); ++ public static final Comparator> ENTRY_COMPARATOR = (Comparator)TickNextTickData.createTimeComparator(); + + // we do not record the interval, this class is meant to be used on a ring buffer + @@ -727,11 +727,11 @@ index 0000000000000000000000000000000000000000..d40a7aff6c27883f3ae8ba878a94c972 + } + + public void addEntryLast(final TickNextTickData entry) { -+ this.byPriority[entry.getPriority().ordinal()].addLast(entry); ++ this.byPriority[entry.priority.ordinal()].addLast(entry); + } + + public void addEntryFirst(final TickNextTickData entry) { -+ this.byPriority[entry.getPriority().ordinal()].addFirst(entry); ++ this.byPriority[entry.priority.ordinal()].addFirst(entry); + } + + public void clear() { @@ -888,64 +888,63 @@ index 0000000000000000000000000000000000000000..118988c39e58f28e8a2851792b9c014f + } + } +} -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 3db77d9eda98eacb099135643aff5e94751f4c7c..595abf528a7862478100770987906af1b13439fe 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -111,6 +111,7 @@ public class BlockPos extends Vec3i { - return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.getX() + x, this.getY() + y, this.getZ() + z); - } - -+ public final BlockPos add(Vec3i baseblockposition) { return this.offset(baseblockposition); } // Paper - OBFHELPER - public BlockPos offset(Vec3i pos) { - return this.offset(pos.getX(), pos.getY(), pos.getZ()); - } diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 77d3969200ac6f88f3af9add05def0b627ce6db3..d12d5459c847d3f0d655c85e31d81c27b7a2face 100644 +index 995d7977233f0d7683c00a75c3833f9a1eba7f92..58369d70bcd8b2c25609b6f101d9cbe2031df352 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -495,7 +495,9 @@ public class ChunkHolder { +@@ -86,6 +86,19 @@ public class ChunkHolder { + return null; + } + // Paper end - no-tick view distance ++ // Paper start ++ public final boolean isEntityTickingReady() { ++ return this.isEntityTickingReady; ++ } ++ ++ public final boolean isTickingReady() { ++ return this.isTickingReady; ++ } ++ ++ public final boolean isFullChunkReady() { ++ return this.isFullChunkReady; ++ } ++ // Paper end + + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); +@@ -547,6 +560,10 @@ public class ChunkHolder { + either.ifLeft(chunk -> { + // note: Here is a very good place to add callbacks to logic waiting on this. ChunkHolder.this.isTickingReady = true; - - -- ++ + // Paper start - rewrite ticklistserver + ChunkHolder.this.chunkMap.level.onChunkSetTicking(ChunkHolder.this.pos.x, ChunkHolder.this.pos.z); + // Paper end - rewrite ticklistserver - - } + }); }); + // Paper end diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 3aeb8426b0461ec572c1499116be80f968bb4104..e2b1541042bceac965411e3176d08c61f217c07f 100644 +index 7cbd3db81c73d466a6e6012c1c91698b53a0cb86..382a68c76e8946840de62f05483870689de80278 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -21,6 +21,7 @@ import net.minecraft.Util; - import net.minecraft.core.BlockPos; - import net.minecraft.core.SectionPos; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.progress.ChunkProgressListener; - import net.minecraft.util.Mth; - import net.minecraft.util.profiling.ProfilerFiller; -@@ -217,6 +218,13 @@ public class ServerChunkCache extends ChunkSource { +@@ -220,6 +220,12 @@ public class ServerChunkCache extends ChunkSource { + }, this.mainThreadProcessor); } // Paper end - + // Paper start - rewrite ticklistserver + public final boolean isTickingReadyMainThread(BlockPos pos) { -+ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(pos)); ++ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(net.minecraft.server.MCUtil.getCoordinateKey(pos)); + return chunk != null && chunk.isTickingReady(); + } + // Paper end - rewrite ticklistserver -+ - public ServerChunkCache(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldloadlistener, Supplier supplier) { - this.level = worldserver; - this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(worldserver); + + public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier supplier) { + this.level = world; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 5d85895456b5d65954889cadf932027ea23b400b..9da0d98bc2ed7876a00a734690ed42f01b9a9a9b 100644 +index ecb9c5a1958c89494417bdb3e6c6363f3fc84534..385b8e707406173ea5258aff87af719ce93aecf3 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -292,6 +292,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -286,6 +286,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } // Paper end @@ -960,273 +959,127 @@ index 5d85895456b5d65954889cadf932027ea23b400b..9da0d98bc2ed7876a00a734690ed42f0 + // Add env and gen to constructor, WorldData -> WorldDataServer public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor -@@ -299,12 +308,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - convertable = convertable_conversionsession; - uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile()); - // CraftBukkit end -- this.blockTicks = new ServerTickList<>(this, (block) -> { -- return block == null || block.defaultBlockState().isAir(); -- }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings -- this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { -- return fluidtype == null || fluidtype == Fluids.EMPTY; -- }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings + // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error +@@ -302,13 +311,19 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + DefaultedRegistry registryblocks = Registry.BLOCK; + + Objects.requireNonNull(registryblocks); +- this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings ++ // this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings // Paper - copied down + Predicate predicate2 = (fluidtype) -> { // CraftBukkit - decompile error + return fluidtype == null || fluidtype == Fluids.EMPTY; + }; + registryblocks = Registry.FLUID; + Objects.requireNonNull(registryblocks); + if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { -+ this.blockTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> { -+ return block == null || block.defaultBlockState().isAir(); -+ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings -+ this.liquidTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (fluidtype) -> { -+ return fluidtype == null || fluidtype == Fluids.EMPTY; -+ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings ++ this.blockTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings ++ this.liquidTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, predicate2, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper timings + } else { -+ this.blockTicks = new ServerTickList<>(this, (block) -> { -+ return block == null || block.defaultBlockState().isAir(); -+ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings -+ this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { -+ return fluidtype == null || fluidtype == Fluids.EMPTY; -+ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings ++ this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings & copied from above + this.liquidTicks = new ServerTickList<>(this, predicate2, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // CraftBukkit - decompile error // Paper - Timings + } - this.navigations = Sets.newHashSet(); + this.navigatingMobs = new ObjectOpenHashSet(); this.blockEvents = new ObjectLinkedOpenHashSet(); - this.tickTime = flag1; -@@ -639,7 +657,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.dragonParts = new Int2ObjectOpenHashMap(); +@@ -629,7 +644,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl if (this.tickTime) { long i = this.levelData.getGameTime() + 1L; -- this.worldDataServer.setGameTime(i); -+ this.worldDataServer.setGameTime(i); // Paper - diff on change, we want the below to be ran right after this +- this.serverLevelData.setGameTime(i); ++ this.serverLevelData.setGameTime(i); ; // Paper - diff on change, we want the below to be ran right after this + this.blockTicks.nextTick(); // Paper + this.liquidTicks.nextTick(); // Paper - this.worldDataServer.getScheduledEvents().tick(this.server, i); + this.serverLevelData.getScheduledEvents().tick(this.server, i); if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { this.setDayTime(this.levelData.getDayTime() + 1L); diff --git a/src/main/java/net/minecraft/world/level/ChunkTickList.java b/src/main/java/net/minecraft/world/level/ChunkTickList.java -index 16757eb9c03c0dab51a7a1b569daff81cf9654f3..3008e0c42efe908e45dba1a1437928d4d4378f24 100644 +index 1a05edf041cf4aeee7c165fec564ce45adbdd5c7..febc837d324cbe2cd83aea6c1e0d298c70f45f78 100644 --- a/src/main/java/net/minecraft/world/level/ChunkTickList.java +++ b/src/main/java/net/minecraft/world/level/ChunkTickList.java -@@ -9,6 +9,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MinecraftServer; +@@ -15,7 +15,7 @@ public class ChunkTickList implements TickList { - public class ChunkTickList implements TickList { + public ChunkTickList(Function identifierProvider, List> scheduledTicks, long startTime) { + this(identifierProvider, scheduledTicks.stream().map((tickNextTickData) -> { +- return new ChunkTickList.ScheduledTick(tickNextTickData.getType(), tickNextTickData.pos, (int)(tickNextTickData.triggerTick - startTime), tickNextTickData.priority); ++ return new ChunkTickList.ScheduledTick<>(tickNextTickData.getType(), tickNextTickData.pos, (int)(tickNextTickData.triggerTick - startTime), tickNextTickData.priority); // Paper - decompile error + }).collect(Collectors.toList())); + } -@@ -61,6 +62,8 @@ public class ChunkTickList implements TickList { - return nbttaglist; +@@ -56,6 +56,7 @@ public class ChunkTickList implements TickList { + return listTag; } + private static final int MAX_TICK_DELAY = Integer.getInteger("paper.ticklist-max-tick-delay", -1).intValue(); // Paper - clean up broken entries -+ - public static ChunkTickList create(ListTag ticks, Function function, Function function1) { + public static ChunkTickList create(ListTag ticks, Function function, Function function2) { List> list = Lists.newArrayList(); -@@ -71,7 +74,14 @@ public class ChunkTickList implements TickList { - if (t0 != null) { - BlockPos blockposition = new BlockPos(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); - -- list.add(new ChunkTickList.ScheduledTick<>(t0, blockposition, nbttagcompound.getInt("t"), TickPriority.byValue(nbttagcompound.getInt("p")))); +@@ -64,7 +65,14 @@ public class ChunkTickList implements TickList { + T object = function2.apply(new ResourceLocation(compoundTag.getString("i"))); + if (object != null) { + BlockPos blockPos = new BlockPos(compoundTag.getInt("x"), compoundTag.getInt("y"), compoundTag.getInt("z")); +- list.add(new ChunkTickList.ScheduledTick<>(object, blockPos, compoundTag.getInt("t"), TickPriority.byValue(compoundTag.getInt("p")))); + // Paper start - clean up broken entries -+ int delay = nbttagcompound.getInt("t"); ++ int delay = compoundTag.getInt("t"); + if (MAX_TICK_DELAY > 0 && delay > MAX_TICK_DELAY) { -+ MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockposition + ", tick delay " + delay); ++ net.minecraft.server.MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockPos + ", tick delay " + delay); + continue; + } -+ list.add(new ChunkTickList.ScheduledTick<>(t0, blockposition, delay, TickPriority.byValue(nbttagcompound.getInt("p")))); + // Paper end - clean up broken entries ++ list.add(new ChunkTickList.ScheduledTick<>(object, blockPos, delay, TickPriority.byValue(compoundTag.getInt("p")))); } } diff --git a/src/main/java/net/minecraft/world/level/ServerTickList.java b/src/main/java/net/minecraft/world/level/ServerTickList.java -index 10ac1ba0a3d192486f22c2127d5bc30353f0edb6..65b3a16f40a295c2916be2a9fd019b452fb65e4f 100644 +index 702203f4a4fa4fc03c35ec974a97e08ed0f3c67c..609c8ece9e9f151875bf8191cc671206ee1e5f68 100644 --- a/src/main/java/net/minecraft/world/level/ServerTickList.java +++ b/src/main/java/net/minecraft/world/level/ServerTickList.java -@@ -50,7 +50,16 @@ public class ServerTickList implements TickList { +@@ -49,6 +49,9 @@ public class ServerTickList implements TickList { private final co.aikar.timings.Timing timingTicking; // Paper // Paper end + // Paper start + public void nextTick() {} + // Paper end -+ -+ public void tick() { -+ // Paper start - allow overriding -+ this.tick(); -+ } public void tick() { -+ // Paper end int i = this.tickNextTickList.size(); - if (false) { // CraftBukkit -@@ -118,28 +127,43 @@ public class ServerTickList implements TickList { - - @Override - public boolean willTickThisTick(BlockPos pos, T object) { -- return this.currentlyTicking.contains(new TickNextTickData<>(pos, object)); -+ // Paper start - allow overriding -+ return this.isPendingTickThisTick(pos, object); -+ } -+ public boolean isPendingTickThisTick(BlockPos blockposition, T t0) { -+ // Paper end -+ return this.currentlyTicking.contains(new TickNextTickData<>(blockposition, t0)); +@@ -190,7 +193,7 @@ public class ServerTickList implements TickList { + return ServerTickList.saveTickList(this.toId, list, this.level.getGameTime()); } - public List> fetchTicksInChunk(ChunkPos chunkcoordintpair, boolean updateState, boolean getStaleTicks) { -+ // Paper start - allow overriding -+ return this.getEntriesInChunk(chunkcoordintpair, updateState, getStaleTicks); -+ } -+ public List> getEntriesInChunk(ChunkPos chunkcoordintpair, boolean flag, boolean flag1) { -+ // Paper end - int i = (chunkcoordintpair.x << 4) - 2; - int j = i + 16 + 2; - int k = (chunkcoordintpair.z << 4) - 2; - int l = k + 16 + 2; - -- return this.fetchTicksInArea(new BoundingBox(i, 0, k, j, 256, l), updateState, getStaleTicks); -+ return this.fetchTicksInArea(new BoundingBox(i, 0, k, j, 256, l), flag, flag1); - } - - public List> fetchTicksInArea(BoundingBox bounds, boolean updateState, boolean getStaleTicks) { -- List> list = this.fetchTicksInArea((List) null, this.tickNextTickList, bounds, updateState); -+ // Paper start - allow overriding -+ return this.getEntriesInBoundingBox(bounds, updateState, getStaleTicks); -+ } -+ public List> getEntriesInBoundingBox(BoundingBox structureboundingbox, boolean flag, boolean flag1) { -+ // Paper end -+ List> list = this.fetchTicksInArea((List) null, this.tickNextTickList, structureboundingbox, flag); - -- if (updateState && list != null) { -+ if (flag && list != null) { - this.tickNextTickSet.removeAll(list); - } - -- list = this.fetchTicksInArea(list, this.currentlyTicking, bounds, updateState); -- if (!getStaleTicks) { -- list = this.fetchTicksInArea(list, this.alreadyTicked, bounds, updateState); -+ list = this.fetchTicksInArea(list, this.currentlyTicking, structureboundingbox, flag); -+ if (!flag1) { -+ list = this.fetchTicksInArea(list, this.alreadyTicked, structureboundingbox, flag); - } - - return list == null ? Collections.emptyList() : list; -@@ -170,14 +194,19 @@ public class ServerTickList implements TickList { - } - - public void copy(BoundingBox box, BlockPos offset) { -- List> list = this.fetchTicksInArea(box, false, false); -+ // Paper start - allow overriding -+ this.copy(box, offset); -+ } -+ public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { -+ // Paper end -+ List> list = this.fetchTicksInArea(structureboundingbox, false, false); - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) { - TickNextTickData nextticklistentry = (TickNextTickData) iterator.next(); - -- if (box.isInside((Vec3i) nextticklistentry.pos)) { -- BlockPos blockposition1 = nextticklistentry.pos.offset((Vec3i) offset); -+ if (structureboundingbox.isInside((Vec3i) nextticklistentry.pos)) { -+ BlockPos blockposition1 = nextticklistentry.pos.offset((Vec3i) blockposition); - T t0 = nextticklistentry.getType(); - - this.addTickData(new TickNextTickData<>(blockposition1, t0, nextticklistentry.triggerTick, nextticklistentry.priority)); -@@ -187,11 +216,17 @@ public class ServerTickList implements TickList { - } - - public ListTag save(ChunkPos chunkcoordintpair) { -+ // Paper start - allow overriding -+ return this.serialize(chunkcoordintpair); -+ } -+ public ListTag serialize(ChunkPos chunkcoordintpair) { -+ // Paper end - List> list = this.fetchTicksInChunk(chunkcoordintpair, false, true); - - return saveTickList(this.toId, list, this.level.getGameTime()); - } - -+ public static ListTag serialize(Function function, Iterable> iterable, long i) { return ServerTickList.saveTickList(function, iterable, i); } // Paper - OBFHELPER - private static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { +- private static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { ++ public static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { // Paper - private -> public ListTag nbttaglist = new ListTag(); Iterator iterator = scheduledTicks.iterator(); -@@ -214,13 +249,23 @@ public class ServerTickList implements TickList { - @Override - public boolean hasScheduledTick(BlockPos pos, T object) { -- return this.tickNextTickSet.contains(new TickNextTickData<>(pos, object)); -+ // Paper start - allow overriding -+ return this.isScheduledForTick(pos, object); -+ } -+ public boolean isScheduledForTick(BlockPos blockposition, T t0) { -+ // Paper end -+ return this.tickNextTickSet.contains(new TickNextTickData<>(blockposition, t0)); - } - - @Override - public void scheduleTick(BlockPos pos, T object, int delay, TickPriority priority) { -- if (!this.ignore.test(object)) { -- this.addTickData(new TickNextTickData<>(pos, object, (long) delay + this.level.getGameTime(), priority)); -+ // Paper start - allow overriding -+ this.schedule(pos, object, delay, priority); -+ } -+ public void schedule(BlockPos blockposition, T t0, int i, TickPriority ticklistpriority) { -+ // Paper end -+ if (!this.ignore.test(t0)) { -+ this.addTickData(new TickNextTickData<>(blockposition, t0, (long) i + this.level.getGameTime(), ticklistpriority)); - } - - } -@@ -234,6 +279,11 @@ public class ServerTickList implements TickList { - } - - public int size() { -+ // Paper start - allow overriding -+ return this.getTotalScheduledEntries(); -+ } -+ public int getTotalScheduledEntries() { -+ // Paper end - return this.tickNextTickSet.size(); - } - } diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java -index 90833389022d7412bdda8868a356b84f62a00e03..61cdaf45368dcc40f3311e8b7f8637a6c93a2d76 100644 +index 3b8c04f6ffd7e6c197465aa1caf633ba92529472..6b4b7c290b623a9821734ef74a2e566343e3c5bd 100644 --- a/src/main/java/net/minecraft/world/level/TickNextTickData.java +++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java -@@ -6,11 +6,13 @@ import net.minecraft.core.BlockPos; - public class TickNextTickData { - - private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading -- private final T type; -- public final BlockPos pos; -- public final long triggerTick; -- public final TickPriority priority; +@@ -9,7 +9,9 @@ public class TickNextTickData { + public final BlockPos pos; + public final long triggerTick; + public final TickPriority priority; - private final long c; -+ private final T type; public final T getData() { return this.type; } // Paper - OBFHELPER -+ public final BlockPos pos; public final BlockPos getPosition() { return this.pos; } // Paper - OBFHELPER -+ public final long triggerTick; public final long getTargetTick() { return this.triggerTick; } // Paper - OBFHELPER -+ public final TickPriority priority; public final TickPriority getPriority() { return this.priority; } // Paper - OBFHELPER + private final long c; public final long getId() { return this.c; } // Paper - OBFHELPER + private final int hash; // Paper + public int tickState; // Paper public TickNextTickData(BlockPos pos, T t) { this(pos, t, 0L, TickPriority.NORMAL); -@@ -22,6 +24,7 @@ public class TickNextTickData { +@@ -21,6 +23,7 @@ public class TickNextTickData { this.type = t; this.triggerTick = time; this.priority = priority; + this.hash = this.computeHash(); // Paper } - public boolean equals(Object object) { -@@ -34,19 +37,31 @@ public class TickNextTickData { - } - } + @Override +@@ -35,17 +38,27 @@ public class TickNextTickData { -+ // Paper start - optimize hashcode -+ @Override + @Override public int hashCode() { ++ // Paper start - optimize hashcode + return this.hash; + } + public final int computeHash() { @@ -1234,68 +1087,26 @@ index 90833389022d7412bdda8868a356b84f62a00e03..61cdaf45368dcc40f3311e8b7f8637a6 return this.pos.hashCode(); } -- public static Comparator createTimeComparator() { // Paper - decompile fix -- return Comparator.comparingLong((nextticklistentry) -> { -- return ((TickNextTickData) nextticklistentry).triggerTick; // Paper - decompile fix -- }).thenComparing((nextticklistentry) -> { -- return ((TickNextTickData) nextticklistentry).priority; // Paper - decompile fix -- }).thenComparingLong((nextticklistentry) -> { -- return ((TickNextTickData) nextticklistentry).c; // Paper - decompile fix + public static Comparator> createTimeComparator() { +- return Comparator.>comparingLong((tickNextTickData) -> { // Paper - decompile fix +- return tickNextTickData.triggerTick; +- }).thenComparing((tickNextTickData) -> { +- return tickNextTickData.priority; +- }).thenComparingLong((tickNextTickData) -> { +- return tickNextTickData.c; - }); -+ // Paper start - let's not use more functional code for no reason. -+ public static Comparator comparator() { return TickNextTickData.createTimeComparator(); } // Paper - OBFHELPER -+ public static Comparator createTimeComparator() { -+ return (Comparator)(Comparator)(TickNextTickData nextticklistentry, TickNextTickData nextticklistentry1) -> { -+ int i = Long.compare(nextticklistentry.getTargetTick(), nextticklistentry1.getTargetTick()); ++ // Paper start - let's not use more functional code for no reason. ++ return (Comparator) (Comparator) (TickNextTickData nextticklistentry, TickNextTickData nextticklistentry1) -> { ++ int i = Long.compare(nextticklistentry.triggerTick, nextticklistentry1.triggerTick); + + if (i != 0) { + return i; + } else { -+ i = nextticklistentry.getPriority().compareTo(nextticklistentry1.getPriority()); ++ i = nextticklistentry.priority.compareTo(nextticklistentry1.priority); + return i != 0 ? i : Long.compare(nextticklistentry.getId(), nextticklistentry1.getId()); + } + }; - } -+ // Paper end - let's not use more functional code for no reason. - - public String toString() { - return this.type + ": " + this.pos + ", " + this.triggerTick + ", " + this.priority + ", " + this.c; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java b/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java -index 76bea58d35d352ee6f3d4bd0d10af3b6d615ae2c..4288fa253668196e6c32a876f18ec496fb3abad6 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java -@@ -8,12 +8,12 @@ import net.minecraft.nbt.IntArrayTag; - - public class BoundingBox { - -- public int x0; -- public int y0; -- public int z0; -- public int x1; -- public int y1; -- public int z1; -+ public int x0; public final int getMinX() { return this.x0; } // Paper - OBFHELPER -+ public int y0; public final int getMinY() { return this.y0; } // Paper - OBFHELPER -+ public int z0; public final int getMinZ() { return this.z0; } // Paper - OBFHELPER -+ public int x1; public final int getMaxX() { return this.x1; } // Paper - OBFHELPER -+ public int y1; public final int getMaxY() { return this.y1; } // Paper - OBFHELPER -+ public int z1; public final int getMaxZ() { return this.z1; } // Paper - OBFHELPER - - public BoundingBox() {} - -@@ -92,6 +92,7 @@ public class BoundingBox { - this.y1 = 512; ++ // Paper end - let's not use more functional code for no reason. } -+ public final boolean intersects(BoundingBox boundingBox) { return this.intersects(boundingBox); } // Paper - OBFHELPER - public boolean intersects(BoundingBox other) { - return this.x1 >= other.x0 && this.x0 <= other.x1 && this.z1 >= other.z0 && this.z0 <= other.z1 && this.y1 >= other.y0 && this.y0 <= other.y1; - } -@@ -126,6 +127,7 @@ public class BoundingBox { - this.move(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } - -+ public final boolean hasPoint(Vec3i baseblockposition) { return this.isInside(baseblockposition); } // Paper - OBFHELPER - public boolean isInside(Vec3i vec) { - return vec.getX() >= this.x0 && vec.getX() <= this.x1 && vec.getZ() >= this.z0 && vec.getZ() <= this.z1 && vec.getY() >= this.y0 && vec.getY() <= this.y1; - } + @Override diff --git a/patches/server-remapped/0419-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/0379-Pillager-patrol-spawn-settings-and-per-player-option.patch similarity index 85% rename from patches/server-remapped/0419-Pillager-patrol-spawn-settings-and-per-player-option.patch rename to patches/server/0379-Pillager-patrol-spawn-settings-and-per-player-option.patch index 6e0269c7f2..ff68539cdb 100644 --- a/patches/server-remapped/0419-Pillager-patrol-spawn-settings-and-per-player-option.patch +++ b/patches/server/0379-Pillager-patrol-spawn-settings-and-per-player-option.patch @@ -10,10 +10,10 @@ When not per player it will use the Vanilla mechanic of one delay per world and the world age for the start day. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 525d702d78a609af987ebd2c32169b873e5c05ed..6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1 100644 +index b57d9c84db5685b86cb077e3b42db7a8578d6f62..9664786d471b949880030f5c6271bf9c12529326 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -582,10 +582,21 @@ public class PaperWorldConfig { +@@ -428,10 +428,21 @@ public class PaperWorldConfig { } public boolean disablePillagerPatrols = false; @@ -36,10 +36,10 @@ index 525d702d78a609af987ebd2c32169b873e5c05ed..6c8e9d498c9a30a1aa88494ba09c3cae private void entitiesTargetWithFollowRange() { entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 7f4e81ee3339e90b8525541dccf6dea187853cf7..a469016c43251f16913a365c4131b2448eaa4c48 100644 +index bffc897cb88a54c36432c98264f3416051aeab17..5b5a0c0db79452ee07c40bf7693b6701dbe0b615 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -213,6 +213,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -219,6 +219,7 @@ public class ServerPlayer extends Player { public boolean wonGame; private int containerUpdateDelay; // Paper public long loginTime; // Paper @@ -47,20 +47,8 @@ index 7f4e81ee3339e90b8525541dccf6dea187853cf7..a469016c43251f16913a365c4131b244 // Paper start - cancellable death event public boolean queueHealthUpdatePacket = false; public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; -diff --git a/src/main/java/net/minecraft/stats/StatType.java b/src/main/java/net/minecraft/stats/StatType.java -index ba48795a7b7cbf4622e64273ab488e26d7a862e2..b85987910cf80b1d1a04a7b772e19200f4ce4372 100644 ---- a/src/main/java/net/minecraft/stats/StatType.java -+++ b/src/main/java/net/minecraft/stats/StatType.java -@@ -28,6 +28,7 @@ public class StatType implements Iterable> { - return this.map.values().iterator(); - } - -+ public final Stat get(T t) { return this.get(t); }; // Paper - OBFHELPER - public Stat get(T key) { - return this.get(key, StatFormatter.DEFAULT); - } diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java -index 48efe133d294bb1b17e8ac8b44eea8a29f15845f..dcbe74bdb1b6e07f7b8845182576ef544493d377 100644 +index 744b58d59a5f34ed3bd6f2d4a0f876acfa6a7135..d75a04e7a70b7fb2527fdd7d1a45a101d064824f 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java @@ -4,11 +4,12 @@ import java.util.Random; @@ -127,7 +115,7 @@ index 48efe133d294bb1b17e8ac8b44eea8a29f15845f..dcbe74bdb1b6e07f7b8845182576ef54 + } else { + long days; + if (world.paperConfig.patrolPerPlayerStart) { -+ days = entityhuman.getStats().getValue(Stats.CUSTOM.get(Stats.PLAY_ONE_MINUTE)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang ++ days = entityhuman.getStats().getValue(Stats.CUSTOM.get(Stats.PLAY_TIME)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang + } else { + days = world.getDayTime() / 24000L; + } diff --git a/patches/server-remapped/0422-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server/0380-Remote-Connections-shouldn-t-hold-up-shutdown.patch similarity index 86% rename from patches/server-remapped/0422-Remote-Connections-shouldn-t-hold-up-shutdown.patch rename to patches/server/0380-Remote-Connections-shouldn-t-hold-up-shutdown.patch index a83d559354..64931753ef 100644 --- a/patches/server-remapped/0422-Remote-Connections-shouldn-t-hold-up-shutdown.patch +++ b/patches/server/0380-Remote-Connections-shouldn-t-hold-up-shutdown.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Remote Connections shouldn't hold up shutdown Bugs in the connection logic appears to leave stale connections even, preventing shutdown diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 4862a9519d4ba5f05b634a0335837bea9812edee..f8ddc0aa98874c7879a51e76d1a629cbdaf58812 100644 +index 6f9b7c3cf22d0c44f31b81bcbfa3cb1f8c065083..0511f1921193b78cbf4d8426136bf1f79746f955 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -397,11 +397,11 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -439,11 +439,11 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } if (this.rconThread != null) { diff --git a/patches/server-remapped/0423-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch similarity index 85% rename from patches/server-remapped/0423-Do-not-allow-bees-to-load-chunks-for-beehives.patch rename to patches/server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch index 044507e1b4..bbc752cdd0 100644 --- a/patches/server-remapped/0423-Do-not-allow-bees-to-load-chunks-for-beehives.patch +++ b/patches/server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Do not allow bees to load chunks for beehives diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e99b45d887 100644 +index b4cd490a1b2a2a118dc5f49bcb0fb755fbad853b..4aeffd9efe6f845007f35a3fd23fdfda2d1f20aa 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -358,6 +358,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -404,6 +404,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { if (this.hivePos == null) { return false; } else { @@ -16,7 +16,7 @@ index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e9 BlockEntity tileentity = this.level.getBlockEntity(this.hivePos); return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby(); -@@ -390,6 +391,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -436,6 +437,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { } private boolean doesHiveHaveSpace(BlockPos pos) { @@ -24,7 +24,7 @@ index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e9 BlockEntity tileentity = this.level.getBlockEntity(pos); return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false; -@@ -632,6 +634,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -909,6 +911,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override public boolean canBeeUse() { if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerThan((Position) Bee.this.position(), 2.0D)) { @@ -32,7 +32,7 @@ index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e9 BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos); if (tileentity instanceof BeehiveBlockEntity) { -@@ -655,6 +658,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -932,6 +935,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override public void start() { diff --git a/patches/server-remapped/0424-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server/0382-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch similarity index 62% rename from patches/server-remapped/0424-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch rename to patches/server/0382-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch index 720e9dcff9..60f46ed4f2 100644 --- a/patches/server-remapped/0424-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ b/patches/server/0382-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -7,10 +7,10 @@ Suspected case would be around the technique used in .stopRiding Stack will identify any causer of this and warn instead of crashing. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 6da406c8403797a1cd9276ac06577c3c080a8a22..e6eeca5834a164d87f5b0e564fe6237902edaa6a 100644 +index 273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c..d06c6828180b7864bf4d3736a65ea0a2dc7804e2 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1501,6 +1501,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1445,6 +1445,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider protected void addEntity(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot @@ -26,23 +26,23 @@ index 6da406c8403797a1cd9276ac06577c3c080a8a22..e6eeca5834a164d87f5b0e564fe62379 EntityType entitytypes = entity.getType(); int i = entitytypes.clientTrackingRange() * 16; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index c5dc41a3cf499038bd33451a189913cd3978b230..5127bce423a83711cea94e387b3ae7866215ded5 100644 +index 385b8e707406173ea5258aff87af719ce93aecf3..5944c44eadca550671d7740af5756985afede39d 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1525,7 +1525,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } +@@ -2100,7 +2100,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + public void onTrackingStart(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot +- ServerLevel.this.getChunkSource().addEntity(entity); ++ // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - moved down below valid=true + if (entity instanceof ServerPlayer) { + ServerLevel.this.players.add((ServerPlayer) entity); + ServerLevel.this.updateSleepingPlayerList(); +@@ -2122,6 +2122,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } -- this.getChunkSource().addEntity(entity); -+ // this.getChunkProvider().addEntity(entity); // Paper - moved down below valid=true - // CraftBukkit start - SPIGOT-5278 - if (entity instanceof Drowned) { - this.navigations.add(((Drowned) entity).waterNavigation); -@@ -1536,6 +1536,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.navigations.add(((Mob) entity).getNavigation()); - } entity.valid = true; // CraftBukkit -+ this.getChunkSource().addEntity(entity); // Paper - from above to be below valid=true - // Paper start - Set origin location when the entity is being added to the world - if (entity.origin == null) { - entity.origin = entity.getBukkitEntity().getLocation(); ++ ServerLevel.this.getChunkSource().addEntity(entity); + } + + public void onTrackingEnd(Entity entity) { diff --git a/patches/server/0383-Optimize-Collision-to-not-load-chunks.patch b/patches/server/0383-Optimize-Collision-to-not-load-chunks.patch new file mode 100644 index 0000000000..d2e15c6828 --- /dev/null +++ b/patches/server/0383-Optimize-Collision-to-not-load-chunks.patch @@ -0,0 +1,133 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 02:37:57 -0400 +Subject: [PATCH] Optimize Collision to not load chunks + +The collision code takes an AABB and generates a cuboid of checks rather +than a cylinder, so at high velocity this can generate a lot of chunk checks. + +Treat an unloaded chunk as a collision for entities, and also for players if +the "prevent moving into unloaded chunks" setting is enabled. + +If that serting is not enabled, collisions will be ignored for players, since +movement will load only the chunk the player enters anyways and avoids loading +massive amounts of surrounding chunks due to large AABB lookups. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 2730923bd0bf3b0f928765b9e09e2299fa9a393d..f98a1c32e0c209473cf7268cbd8245ab9c134d28 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -783,6 +783,7 @@ public abstract class PlayerList { + entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + // CraftBukkit end + ++ worldserver1.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper + while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { + entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index facb09e49d92d22dbcde7d187d4ba1c9a04202a9..85c0656ee8c91cab1e269daea631977c4284295f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -172,6 +172,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + // Paper end + + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper ++ public boolean collisionLoadChunks = false; // Paper + private CraftEntity bukkitEntity; + + public CraftEntity getBukkitEntity() { +diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java +index b980c26ab5cac02e03525177a9dc4fb0b6a2f9f6..2a784a8342e708e0813c7076a2ca8e429446ffd3 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionGetter.java ++++ b/src/main/java/net/minecraft/world/level/CollisionGetter.java +@@ -55,7 +55,9 @@ public interface CollisionGetter extends BlockGetter { + } + + default boolean noCollision(@Nullable Entity entity, AABB box, Predicate filter) { ++ try { if (entity != null) entity.collisionLoadChunks = true; // Paper + return this.getCollisions(entity, box, filter).allMatch(VoxelShape::isEmpty); ++ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper + } + + Stream getEntityCollisions(@Nullable Entity entity, AABB box, Predicate predicate); +diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +index e6190bfb893de12e87e1da49001ebd963b3d6318..90039d01ef481ba206f2e952c99a755e94201ea3 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java ++++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +@@ -21,13 +21,13 @@ import net.minecraft.world.phys.shapes.VoxelShape; + + public class CollisionSpliterator extends AbstractSpliterator { + @Nullable +- private final Entity source; ++ private final Entity source; final Entity getEntity() { return this.source; } // Paper - OBFHELPER + private final AABB box; + private final CollisionContext context; + private final Cursor3D cursor; +- private final BlockPos.MutableBlockPos pos; ++ private final BlockPos.MutableBlockPos pos; final BlockPos.MutableBlockPos getMutablePos() { return this.pos; } // Paper - OBFHELPER + private final VoxelShape entityShape; +- private final CollisionGetter collisionGetter; ++ private final CollisionGetter collisionGetter; final CollisionGetter getCollisionAccess() { return this.collisionGetter; } // Paper - OBFHELPER + private boolean needsBorderCheck; + private final BiPredicate predicate; + +@@ -64,21 +64,37 @@ public class CollisionSpliterator extends AbstractSpliterator { + boolean collisionCheck(Consumer action) { + while(true) { + if (this.cursor.advance()) { +- int i = this.cursor.nextX(); +- int j = this.cursor.nextY(); +- int k = this.cursor.nextZ(); ++ int i = this.cursor.nextX(); final int x = i; ++ int j = this.cursor.nextY(); final int y = j; ++ int k = this.cursor.nextZ(); final int z = k; + int l = this.cursor.getNextType(); + if (l == 3) { + continue; + } + +- BlockGetter blockGetter = this.getChunk(i, k); +- if (blockGetter == null) { ++ // Paper start - ensure we don't load chunks ++ Entity entity = this.getEntity(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getMutablePos(); ++ boolean far = entity != null && net.minecraft.server.MCUtil.distanceSq(entity.getX(), y, entity.getZ(), x, y, z) > 14; ++ blockposition_mutableblockposition.setValues(x, y, z); ++ ++ boolean isRegionLimited = this.getCollisionAccess() instanceof net.minecraft.server.level.WorldGenRegion; ++ BlockState blockState = isRegionLimited ? Blocks.VOID_AIR.defaultBlockState() : ((!far && entity instanceof net.minecraft.server.level.ServerPlayer) || (entity != null && entity.collisionLoadChunks) ++ ? this.getCollisionAccess().getBlockState(blockposition_mutableblockposition) ++ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition) ++ ); ++ ++ if (blockState == null) { ++ if (!(entity instanceof net.minecraft.server.level.ServerPlayer) || entity.level.paperConfig.preventMovingIntoUnloadedChunks) { ++ VoxelShape voxelshape3 = Shapes.create(far ? entity.getBoundingBox() : new AABB(new BlockPos(x, y, z))); ++ action.accept(voxelshape3); ++ return true; ++ } + continue; + } ++ // Paper - moved up ++ // Paper end + +- this.pos.set(i, j, k); +- BlockState blockState = blockGetter.getBlockState(this.pos); + if (!this.predicate.test(blockState, this.pos) || l == 1 && !blockState.hasLargeCollisionShape() || l == 2 && !blockState.is(Blocks.MOVING_PISTON)) { + continue; + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index 5d4d953f197afc402248ab73daeb6ef59134f48f..95428f13dae909bb7de552aa65e4256bd4049c65 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -238,7 +238,8 @@ public final class Shapes { + + if (s < 3) { + mutableBlockPos.set(axisCycle, q, r, p); +- BlockState blockState = world.getBlockState(mutableBlockPos); ++ BlockState blockState = world.getTypeIfLoaded(mutableBlockPos); // Paper ++ if (blockState == null) return 0.0D; // Paper + if ((s != 1 || blockState.hasLargeCollisionShape()) && (s != 2 || blockState.is(Blocks.MOVING_PISTON))) { + initial = blockState.getCollisionShape(world, mutableBlockPos, context).collide(axis3, box.move((double)(-mutableBlockPos.getX()), (double)(-mutableBlockPos.getY()), (double)(-mutableBlockPos.getZ())), initial); + if (Math.abs(initial) < 1.0E-7D) { diff --git a/patches/server-remapped/0426-Don-t-tick-dead-players.patch b/patches/server/0384-Don-t-tick-dead-players.patch similarity index 59% rename from patches/server-remapped/0426-Don-t-tick-dead-players.patch rename to patches/server/0384-Don-t-tick-dead-players.patch index b748ace1a1..d831e3b2b6 100644 --- a/patches/server-remapped/0426-Don-t-tick-dead-players.patch +++ b/patches/server/0384-Don-t-tick-dead-players.patch @@ -7,15 +7,15 @@ Causes sync chunk loads and who knows what all else. This is safe because Spectators are skipped in unloaded chunks too in vanilla. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index a469016c43251f16913a365c4131b2448eaa4c48..286b75a27103a084a9f9d79a90716ebcad65d813 100644 +index 5b5a0c0db79452ee07c40bf7693b6701dbe0b615..2822d493500dcd01c26ff5b205da83d8d356e119 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -606,7 +606,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -637,7 +637,7 @@ public class ServerPlayer extends Player { public void doTick() { try { -- if (!this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { -+ if (valid && !this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) +- if (!this.isSpectator() || !this.touchingUnloadedChunk()) { ++ if (valid && !this.isSpectator() || !this.touchingUnloadedChunk()) { // Paper - don't tick dead players that are not in the world currently (pending respawn) super.tick(); } diff --git a/patches/server-remapped/0427-Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server/0385-Dead-Player-s-shouldn-t-be-able-to-move.patch similarity index 70% rename from patches/server-remapped/0427-Dead-Player-s-shouldn-t-be-able-to-move.patch rename to patches/server/0385-Dead-Player-s-shouldn-t-be-able-to-move.patch index 3e2b8e5352..51a1431c6c 100644 --- a/patches/server-remapped/0427-Dead-Player-s-shouldn-t-be-able-to-move.patch +++ b/patches/server/0385-Dead-Player-s-shouldn-t-be-able-to-move.patch @@ -7,15 +7,15 @@ 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 0685920073a6a2b2c6a80018d0c9009b2ef860c4..32f1b180e82f41f3ce1b49ea7d67b7d55d2b9ca7 100644 +index 4c9261c68518ab7429325f0366dfb2930663288c..a3d31cec6d1b8de700b6cd2f7f51398debef5b6d 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1046,7 +1046,7 @@ public abstract class Player extends LivingEntity { +@@ -1106,7 +1106,7 @@ public abstract class Player extends LivingEntity { @Override protected boolean isImmobile() { - return super.isImmobile() || this.isSleeping(); -+ return super.isImmobile() || this.isSleeping() || removed || !valid; // Paper - player's who are dead or not in a world shouldn't move... ++ return super.isImmobile() || this.isSleeping() || this.isRemoved() || !valid; // Paper - player's who are dead or not in a world shouldn't move... } @Override diff --git a/patches/server-remapped/0428-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch similarity index 84% rename from patches/server-remapped/0428-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch rename to patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch index a211d40a2c..71138d1089 100644 --- a/patches/server-remapped/0428-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch +++ b/patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch @@ -57,10 +57,10 @@ index 0000000000000000000000000000000000000000..f6ff4d8132a95895680f5bc81f8f873e + } +} diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 99c3337eec552ba47d3b8b2d8feaaa80acf2a86f..9abef8550a89df5e15ac28de1a5549d064f29122 100644 +index 9c88426ab1275ee5fb6e28be8b213533dc4ab859..87c9a5c1b43f6010898d72136b5eb9973299b723 100644 --- a/src/main/java/net/minecraft/server/MCUtil.java +++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -616,7 +616,7 @@ public final class MCUtil { +@@ -614,7 +614,7 @@ public final class MCUtil { ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); ChunkMap chunkMap = world.getChunkSource().chunkMap; @@ -70,15 +70,13 @@ index 99c3337eec552ba47d3b8b2d8feaaa80acf2a86f..9abef8550a89df5e15ac28de1a5549d0 List allChunks = new ArrayList<>(visibleChunks.values()); List players = world.players; diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc08174003f4a 100644 +index d06c6828180b7864bf4d3736a65ea0a2dc7804e2..c304c57a572b7e154362b39065ab8cb30a7e112e 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -104,8 +104,33 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - private static final Logger LOGGER = LogManager.getLogger(); +@@ -107,9 +107,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private static final int MIN_VIEW_DISTANCE = 3; + public static final int MAX_VIEW_DISTANCE = 33; public static final int MAX_CHUNK_DISTANCE = 33 + ChunkStatus.maxDistance(); -- public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); -- public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; + // Paper start - faster copying + public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<>(); // Paper - faster copying + public final Long2ObjectLinkedOpenHashMap visibleChunkMap = new ProtectedVisibleChunksMap(); // Paper - faster copying @@ -106,19 +104,24 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 + // Paper end + public final com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy pendingVisibleChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy(); // Paper - this is used if the visible chunks is updated while iterating only + public transient com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy visibleChunksClone; // Paper - used for async access of visible chunks, clone and cache only when needed + public static final int FORCED_TICKET_LEVEL = 31; +- public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); +- public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; ++ // public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); // Paper - moved up ++ // public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; // Paper - moved up private final Long2ObjectLinkedOpenHashMap pendingUnloads; public final LongSet entitiesInLevel; // Paper - private -> public public final ServerLevel level; -@@ -178,7 +203,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -231,7 +258,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag); + public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { + super(new File(session.getDimensionPath(world.dimension()), "region"), dataFixer, dsync); - this.visibleChunkMap = this.updatingChunkMap.clone(); + //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning this.pendingUnloads = new Long2ObjectLinkedOpenHashMap(); this.entitiesInLevel = new LongOpenHashSet(); this.toDrop = new LongOpenHashSet(); -@@ -270,9 +295,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -350,9 +377,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return (ChunkHolder) this.updatingChunkMap.get(pos); } @@ -159,7 +162,7 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 + // Paper end + @Nullable - public ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public + public final ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public - return (ChunkHolder) this.visibleChunkMap.get(pos); + // Paper start - mt safe get + if (Thread.currentThread() != this.level.thread) { @@ -172,8 +175,8 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 } protected IntSupplier getChunkQueueLevel(long pos) { -@@ -460,8 +528,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper end +@@ -509,8 +579,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } protected void saveAllChunks(boolean flush) { + Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) @@ -183,7 +186,7 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 MutableBoolean mutableboolean = new MutableBoolean(); do { -@@ -489,7 +558,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -541,7 +612,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // this.i(); // Paper - nuke IOWorker ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); } else { @@ -192,7 +195,7 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error if (ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk) { -@@ -660,7 +729,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -701,7 +772,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (!this.modified) { return false; } else { @@ -214,7 +217,7 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 this.modified = false; return true; } -@@ -1139,12 +1221,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1110,12 +1194,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } protected Iterable getChunks() { @@ -223,17 +226,17 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 } void dumpChunks(Writer writer) throws IOException { - CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("entity_count").addColumn("block_entity_count").build(writer); + CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("block_entity_count").build(writer); - ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunkMap.long2ObjectEntrySet().iterator(); + ObjectBidirectionalIterator objectbidirectionaliterator = this.getVisibleChunks().long2ObjectEntrySet().iterator(); // Paper while (objectbidirectionaliterator.hasNext()) { Entry entry = (Entry) objectbidirectionaliterator.next(); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index e2b1541042bceac965411e3176d08c61f217c07f..f5de878020be9465739fba07fd7dea46b0a3ae34 100644 +index 382a68c76e8946840de62f05483870689de80278..8523fbd66ed42cd5b959d57cab515fa4a774a575 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -782,7 +782,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -751,7 +751,7 @@ public class ServerChunkCache extends ChunkSource { }; // Paper end this.level.timings.chunkTicks.startTiming(); // Paper @@ -243,41 +246,43 @@ index e2b1541042bceac965411e3176d08c61f217c07f..f5de878020be9465739fba07fd7dea46 if (optional.isPresent()) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index fb74bdcf4c2935b56e92717cc5a1504fbc853d0a..1a839242e359fa32f32d0e571c6e918ac39642e9 100644 +index 1d22119b962840dff789a0619fd2188958f924d0..1023a0d5d1699b28d380e017b386a9b3986f1250 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -276,6 +276,7 @@ public class CraftWorld implements World { - return ret; - } +@@ -286,6 +286,7 @@ public class CraftWorld implements World { + + @Override public int getTileEntityCount() { + return net.minecraft.server.MCUtil.ensureMain(() -> { // We don't use the full world tile entity list, so we must iterate chunks Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; int size = 0; -@@ -287,11 +288,13 @@ public class CraftWorld implements World { +@@ -297,6 +298,7 @@ public class CraftWorld implements World { size += chunk.blockEntities.size(); } return size; + }); } - public int getTickableTileEntityCount() { - return world.tickableBlockEntities.size(); - } + + @Override +@@ -306,6 +308,7 @@ public class CraftWorld implements World { + + @Override public int getChunkCount() { + return net.minecraft.server.MCUtil.ensureMain(() -> { int ret = 0; for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { -@@ -300,7 +303,7 @@ public class CraftWorld implements World { +@@ -314,7 +317,7 @@ public class CraftWorld implements World { } } - return ret; + return ret; }); } - public int getPlayerCount() { - return world.players.size(); -@@ -425,6 +428,14 @@ public class CraftWorld implements World { + + @Override +@@ -441,6 +444,14 @@ public class CraftWorld implements World { @Override public Chunk[] getLoadedChunks() { @@ -289,6 +294,6 @@ index fb74bdcf4c2935b56e92717cc5a1504fbc853d0a..1a839242e359fa32f32d0e571c6e918a + } + } + // Paper end - Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; + Long2ObjectLinkedOpenHashMap chunks = this.world.getChunkSource().chunkMap.visibleChunkMap; return chunks.values().stream().map(ChunkHolder::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new); } diff --git a/patches/server-remapped/0430-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/patches/server/0387-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch similarity index 79% rename from patches/server-remapped/0430-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch rename to patches/server/0387-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch index b0f42e94cc..395f0c27cf 100644 --- a/patches/server-remapped/0430-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch +++ b/patches/server/0387-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch @@ -30,10 +30,10 @@ In a view distance of 15, chunk loading performance was visually faster on the c Flying at high speed in spectator mode was able to keep up with chunk loading (as long as they are already generated) diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -index be3a62f543a5fec4739c14821fe5a443c1fa3f5b..6bff5317939635b925bb41eb7a67d1fd95715078 100644 +index 72f9e1978394afb6e5cc1c0d085d41586d69b84e..aa0698508de8fba6e84c20ac4d3aebb99a075c25 100644 --- a/src/main/java/co/aikar/timings/MinecraftTimings.java +++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -17,6 +17,7 @@ import java.util.Map; +@@ -16,6 +16,7 @@ import java.util.Map; public final class MinecraftTimings { public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); @@ -56,18 +56,18 @@ index da93d38fe63035e4ff198ada84a4431f52d97c01..ddbc8cb712c50038922eded75dd6ca85 + } } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b174dee62 100644 +index 494a3afaaa0e3496d30e8d97edbab62b21610dfe..fa3a9d763f7072c68b126ce95fee191aab576e43 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1055,6 +1055,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { @@ -108,10 +108,10 @@ index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b return !this.canOversleep(); }); isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -@@ -1318,13 +1337,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); if (optional.isPresent()) { -@@ -806,6 +809,7 @@ public class ServerChunkCache extends ChunkSource { - //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper - this.level.tickChunk(chunk, k); - //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper +@@ -768,6 +770,7 @@ public class ServerChunkCache extends ChunkSource { + chunk.setInhabitedTime(chunk.getInhabitedTime() + j); + if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot + NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); + if (chunksTicked[0]++ % 10 == 0) this.level.getServer().midTickLoadChunks(); // Paper } - } - } -@@ -963,6 +967,41 @@ public class ServerChunkCache extends ChunkSource { + + // this.level.timings.doTickTiles.startTiming(); // Spigot // Paper +@@ -935,6 +938,41 @@ public class ServerChunkCache extends ChunkSource { super.doRunTask(task); } @@ -210,7 +202,7 @@ index f5de878020be9465739fba07fd7dea46b0a3ae34..3744cce8611ac01b1b6c76cd3c489079 + return false; + } + public void midTickLoadChunks() { -+ MinecraftServer server = ServerChunkCache.this.level.getServer(); ++ net.minecraft.server.MinecraftServer server = ServerChunkCache.this.level.getServer(); + // always try to load chunks, restrain generation/other updates only. don't count these towards tick count + //noinspection StatementWithEmptyBody + while (pollChunkLoadTasks()) {} @@ -231,13 +223,13 @@ index f5de878020be9465739fba07fd7dea46b0a3ae34..3744cce8611ac01b1b6c76cd3c489079 + // Paper end + @Override - protected boolean pollTask() { // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task + public boolean pollTask() { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 5127bce423a83711cea94e387b3ae7866215ded5..4e75cc5e52a5295e32ccadb371702a405bb518bb 100644 +index 5944c44eadca550671d7740af5756985afede39d..fd3159f7767faaa55ed49eba237e30a2dbd4fa92 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -565,6 +565,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -578,6 +578,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } timings.scheduledBlocks.stopTiming(); // Paper @@ -245,27 +237,24 @@ index 5127bce423a83711cea94e387b3ae7866215ded5..4e75cc5e52a5295e32ccadb371702a40 gameprofilerfiller.popPush("raid"); this.timings.raids.startTiming(); // Paper - timings this.raids.tick(); -@@ -573,6 +574,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -586,6 +587,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl timings.doSounds.startTiming(); // Spigot this.runBlockEvents(); timings.doSounds.stopTiming(); // Spigot + this.getServer().midTickLoadChunks(); // Paper this.handlingTick = false; - gameprofilerfiller.popPush("entities"); + gameprofilerfiller.pop(); boolean flag3 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players -@@ -639,6 +641,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -632,10 +634,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl timings.entityTick.stopTiming(); // Spigot - - this.tickingEntities = false; -+ this.getServer().midTickLoadChunks(); // Paper - - Entity entity2; - -@@ -648,6 +651,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - timings.tickEntities.stopTiming(); // Spigot + gameprofilerfiller.pop(); + this.getServer().midTickLoadChunks(); // Paper this.tickBlockEntities(); } + gameprofilerfiller.push("entityManagement"); ++ this.getServer().midTickLoadChunks(); // Paper + this.entityManager.tick(); + gameprofilerfiller.pop(); + } diff --git a/patches/server-remapped/0431-Don-t-move-existing-players-to-world-spawn.patch b/patches/server/0388-Don-t-move-existing-players-to-world-spawn.patch similarity index 65% rename from patches/server-remapped/0431-Don-t-move-existing-players-to-world-spawn.patch rename to patches/server/0388-Don-t-move-existing-players-to-world-spawn.patch index 02f8b575b0..6b5d0a25e6 100644 --- a/patches/server-remapped/0431-Don-t-move-existing-players-to-world-spawn.patch +++ b/patches/server/0388-Don-t-move-existing-players-to-world-spawn.patch @@ -10,28 +10,29 @@ larger than the keep loaded range. By skipping this, we avoid potential for a large spike on server start. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 286b75a27103a084a9f9d79a90716ebcad65d813..162b1a8c6ab57aafa4f6deefc842755a8e14208e 100644 +index 2822d493500dcd01c26ff5b205da83d8d356e119..bfa91166c18110877f751a5325e59623a05325d0 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -251,7 +251,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -309,7 +309,7 @@ public class ServerPlayer extends Player { this.stats = server.getPlayerList().getStatisticManager(this); this.advancements = server.getPlayerList().getPlayerAdvancements(this); this.maxUpStep = 1.0F; - this.fudgeSpawnLocation(world); + //this.c(worldserver); // Paper - don't move to spawn on login, only first join - this.textFilter = server.createTextFilterForPlayer(this); this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -@@ -303,6 +303,7 @@ public class ServerPlayer extends Player implements ContainerListener { + +@@ -359,7 +359,7 @@ public class ServerPlayer extends Player { } // CraftBukkit end -+ public final void moveToSpawn(ServerLevel worldserver) { fudgeSpawnLocation(worldserver); } // Paper - OBFHELPER - private void fudgeSpawnLocation(ServerLevel world) { - BlockPos blockposition = world.getSpawn(); +- private void fudgeSpawnLocation(ServerLevel world) { ++ public void fudgeSpawnLocation(ServerLevel world) { // Paper - private -> public + BlockPos blockposition = world.getSharedSpawnPos(); -@@ -480,7 +481,7 @@ public class ServerPlayer extends Player implements ContainerListener { - position = Vec3.atCenterOf(((ServerLevel) world).getSpawn()); + if (world.dimensionType().hasSkyLight() && world.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit +@@ -527,7 +527,7 @@ public class ServerPlayer extends Player { + position = Vec3.atCenterOf(((ServerLevel) world).getSharedSpawnPos()); } this.level = world; - this.setPos(position.x(), position.y(), position.z()); @@ -40,15 +41,15 @@ index 286b75a27103a084a9f9d79a90716ebcad65d813..162b1a8c6ab57aafa4f6deefc842755a this.gameMode.setLevel((ServerLevel) world); } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 86c5549196a4e9011c5240e7918b466c299be4a3..30666fca36b683158ff60302684b5093f5536e24 100644 +index f98a1c32e0c209473cf7268cbd8245ab9c134d28..18485689bcbf7818c3ca5b82086acef51888603b 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -204,6 +204,8 @@ public abstract class PlayerList { +@@ -207,6 +207,8 @@ public abstract class PlayerList { worldserver1 = worldserver; } -+ if (nbttagcompound == null) player.moveToSpawn(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are.... ++ if (nbttagcompound == null) player.fudgeSpawnLocation(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are.... + player.setLevel(worldserver1); - player.gameMode.setLevel((ServerLevel) player.level); String s1 = "local"; + From ab709d8405c353583c6efe7e16b92c484edaec95 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Mon, 14 Jun 2021 00:44:48 +0200 Subject: [PATCH 083/226] update github action to the new setup --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 407f27e9d2..101bc900a8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight.core") version "1.0.0-SNAPSHOT" + id("io.papermc.paperweight.core") version "1.0.0-LOCAL-SNAPSHOT" } val mcVersion = providers.gradleProperty("mcVersion") From 5cdbd0064bd460534c265fc41c1d6133e839d77a Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Mon, 14 Jun 2021 00:45:42 +0200 Subject: [PATCH 084/226] update github action to the new setup --- .github/workflows/build.yml | 12 ++++++------ build.gradle.kts | 2 +- settings.gradle.kts | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0da3c7e06f..b8ae06caf6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,14 +26,14 @@ jobs: uses: actions/cache@v2 with: path: | - ~/.m2/repository/ - work/Minecraft - key: ${{ runner.os }}-paper-2-${{ hashFiles('**/pom.xml') }} + ~/.gradle/caches + ~/.gradle/jdks + ~/.gradle/native + ~/.gradle/wrapper + key: ${{ runner.os }}-paper-2-${{ hashFiles('**/*.gradle*', 'gradle/**', 'gradle.properties') }} restore-keys: ${{ runner.os }}-paper-2 - name: Patch and build run: | git config --global user.email "no-reply@github.com" git config --global user.name "Github Actions" - ./paper build - - name: Build javadocs - run: mvn -pl Paper-API,Paper-MojangAPI -am javadoc:javadoc + ./gradlew applyPatches build diff --git a/build.gradle.kts b/build.gradle.kts index 101bc900a8..407f27e9d2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight.core") version "1.0.0-LOCAL-SNAPSHOT" + id("io.papermc.paperweight.core") version "1.0.0-SNAPSHOT" } val mcVersion = providers.gradleProperty("mcVersion") diff --git a/settings.gradle.kts b/settings.gradle.kts index 302bcb31ab..54bb957497 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,5 @@ pluginManagement { repositories { - mavenLocal() gradlePluginPortal() maven("https://wav.jfrog.io/artifactory/repo/") } From 69e6160294fd41f8015bc87278225c4c0220082a Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Mon, 14 Jun 2021 00:56:05 +0200 Subject: [PATCH 085/226] separate out the CI tasks --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b8ae06caf6..2d414ee7de 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,4 +36,5 @@ jobs: run: | git config --global user.email "no-reply@github.com" git config --global user.name "Github Actions" - ./gradlew applyPatches build + ./gradlew applyPatches + ./gradlew build From 2372198eb43de83893d096f4b744520b60280727 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Mon, 14 Jun 2021 01:19:51 +0200 Subject: [PATCH 086/226] use local class for movecontrol stuff to prevent reobf mapping issue --- ...-Bees-get-gravity-in-void.-Fixes-MC-167279.patch | 13 +++++++++---- ...not-allow-bees-to-load-chunks-for-beehives.patch | 10 +++++----- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch index adb34b3de2..d42a9033b2 100644 --- a/patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch +++ b/patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch @@ -5,16 +5,20 @@ Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index f3ba4b26553915917c79f013ed9dd7c87d9f65a4..b4cd490a1b2a2a118dc5f49bcb0fb755fbad853b 100644 +index f3ba4b26553915917c79f013ed9dd7c87d9f65a4..3d049e43c8ea85597e98e9dad61c8d4c49b01b1c 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -143,7 +143,17 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -143,7 +143,22 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { public Bee(EntityType type, Level world) { super(type, world); this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60); - this.moveControl = new FlyingMoveControl(this, 20, true); + // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 -+ this.moveControl = new FlyingMoveControl(this, 20, true) { ++ class BeeFlyingMoveControl extends FlyingMoveControl { ++ public BeeFlyingMoveControl(final Mob entity, final int maxPitchChange, final boolean noGravity) { ++ super(entity, maxPitchChange, noGravity); ++ } ++ + @Override + public void tick() { + if (this.mob.getY() <= 0) { @@ -22,7 +26,8 @@ index f3ba4b26553915917c79f013ed9dd7c87d9f65a4..b4cd490a1b2a2a118dc5f49bcb0fb755 + } + super.tick(); + } -+ }; ++ } ++ this.moveControl = new BeeFlyingMoveControl(this, 20, true); + // Paper end this.lookControl = new Bee.BeeLookControl(this); this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); diff --git a/patches/server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch index bbc752cdd0..5e703d1985 100644 --- a/patches/server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch +++ b/patches/server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Do not allow bees to load chunks for beehives diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index b4cd490a1b2a2a118dc5f49bcb0fb755fbad853b..4aeffd9efe6f845007f35a3fd23fdfda2d1f20aa 100644 +index 3d049e43c8ea85597e98e9dad61c8d4c49b01b1c..207e6f411491d01f9ca5b49aa65a66e16255ff3e 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -404,6 +404,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -409,6 +409,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { if (this.hivePos == null) { return false; } else { @@ -16,7 +16,7 @@ index b4cd490a1b2a2a118dc5f49bcb0fb755fbad853b..4aeffd9efe6f845007f35a3fd23fdfda BlockEntity tileentity = this.level.getBlockEntity(this.hivePos); return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby(); -@@ -436,6 +437,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -441,6 +442,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { } private boolean doesHiveHaveSpace(BlockPos pos) { @@ -24,7 +24,7 @@ index b4cd490a1b2a2a118dc5f49bcb0fb755fbad853b..4aeffd9efe6f845007f35a3fd23fdfda BlockEntity tileentity = this.level.getBlockEntity(pos); return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false; -@@ -909,6 +911,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -914,6 +916,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override public boolean canBeeUse() { if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerThan((Position) Bee.this.position(), 2.0D)) { @@ -32,7 +32,7 @@ index b4cd490a1b2a2a118dc5f49bcb0fb755fbad853b..4aeffd9efe6f845007f35a3fd23fdfda BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos); if (tileentity instanceof BeehiveBlockEntity) { -@@ -932,6 +935,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -937,6 +940,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override public void start() { From 2d176a6083cadf2294d258181f9c2fd93c669188 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Mon, 14 Jun 2021 01:33:04 +0200 Subject: [PATCH 087/226] eeeeww, maven --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2d414ee7de..2e65ad9613 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,7 @@ jobs: with: java-version: ${{ matrix.java }} distribution: 'adopt' - - name: Cache maven + - name: Cache gradle uses: actions/cache@v2 with: path: | From b75a22c4b1f9a0cf75d77fcf065b83eec8c20f04 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Mon, 14 Jun 2021 01:48:04 +0200 Subject: [PATCH 088/226] not even checkstyle can help us now --- patches/api/0001-Convert-project-to-Gradle.patch | 12 ++---------- patches/api/0002-POM-changes.patch | 6 +++--- patches/api/0003-Add-FastUtil-to-Bukkit.patch | 6 +++--- patches/api/0006-Adventure.patch | 4 ++-- patches/api/0024-Use-ASM-for-event-executors.patch | 6 +++--- ...0067-Allow-plugins-to-use-SLF4J-for-logging.patch | 4 ++-- 6 files changed, 15 insertions(+), 23 deletions(-) diff --git a/patches/api/0001-Convert-project-to-Gradle.patch b/patches/api/0001-Convert-project-to-Gradle.patch index 1fb1db17ac..64567fb6dd 100644 --- a/patches/api/0001-Convert-project-to-Gradle.patch +++ b/patches/api/0001-Convert-project-to-Gradle.patch @@ -16,15 +16,14 @@ index e431e3435737e28394d81b56568a08b3c3148b9b..c484aff2c192bf42059b5689327909e4 /.project diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 -index 0000000000000000000000000000000000000000..f3dd92e136a71aa39e422de7b2c5f2f3fdec554e +index 0000000000000000000000000000000000000000..35b57f52fcfd91cff04dc60c3a8a16b31f775fc0 --- /dev/null +++ b/build.gradle.kts -@@ -0,0 +1,67 @@ +@@ -0,0 +1,59 @@ +import java.util.Locale + +plugins { + `java-library` -+ checkstyle +} + +java { @@ -51,8 +50,6 @@ index 0000000000000000000000000000000000000000..f3dd92e136a71aa39e422de7b2c5f2f3 + testImplementation("junit:junit:4.13.1") + testImplementation("org.hamcrest:hamcrest-library:1.3") + testImplementation("org.ow2.asm:asm-tree:9.1") -+ -+ checkstyle("com.puppycrawl.tools:checkstyle:8.39") +} + +val generateApiVersioningFile by tasks.registering { @@ -82,8 +79,3 @@ index 0000000000000000000000000000000000000000..f3dd92e136a71aa39e422de7b2c5f2f3 + "https://javadoc.io/doc/net.md-5/bungeecord-chat/1.16-R0.4/" + ) +} -+ -+checkstyle { -+ configFile = file("checkstyle.xml") -+ sourceSets = listOf(project.sourceSets.main.get(), project.sourceSets.test.get()) -+} diff --git a/patches/api/0002-POM-changes.patch b/patches/api/0002-POM-changes.patch index 1422974313..6eff19161e 100644 --- a/patches/api/0002-POM-changes.patch +++ b/patches/api/0002-POM-changes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] POM changes diff --git a/build.gradle.kts b/build.gradle.kts -index f3dd92e136a71aa39e422de7b2c5f2f3fdec554e..b75ac1f11c3171a3f0c8edb30be3555216f51b0a 100644 +index 35b57f52fcfd91cff04dc60c3a8a16b31f775fc0..20c8a34b299ba455c29b4e31d311de0b3a063288 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -17,10 +17,12 @@ dependencies { +@@ -16,10 +16,12 @@ dependencies { api("com.google.code.gson:gson:2.8.0") api("net.md-5:bungeecord-chat:1.16-R0.4") api("org.yaml:snakeyaml:1.29") @@ -22,7 +22,7 @@ index f3dd92e136a71aa39e422de7b2c5f2f3fdec554e..b75ac1f11c3171a3f0c8edb30be35552 val annotations = "org.jetbrains:annotations-java5:21.0.1" compileOnly(annotations) diff --git a/pom.xml b/pom.xml -index debe5bd7adb1f41e8a6878a8545de4bfcad1a590..d7cf64f05d0a2f5b186ca13b2b88e390abe84226 100644 +index 10eeaef61be733e63f6680f1675e0b527eb30fd9..e5802bcb6fc2376cff2ee8b3069150127312b154 100644 --- a/pom.xml +++ b/pom.xml @@ -2,33 +2,34 @@ diff --git a/patches/api/0003-Add-FastUtil-to-Bukkit.patch b/patches/api/0003-Add-FastUtil-to-Bukkit.patch index 8e8ee65d9e..a315769d11 100644 --- a/patches/api/0003-Add-FastUtil-to-Bukkit.patch +++ b/patches/api/0003-Add-FastUtil-to-Bukkit.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add FastUtil to Bukkit Doesn't expose to plugins, just allows Paper-API to use it for optimization diff --git a/build.gradle.kts b/build.gradle.kts -index b75ac1f11c3171a3f0c8edb30be3555216f51b0a..218e9c682e7b91dc27f2caf46316ba7a7982e5f3 100644 +index 20c8a34b299ba455c29b4e31d311de0b3a063288..6243c2fc2021e6c4fe0f036892bc83983364f360 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -18,6 +18,7 @@ dependencies { +@@ -17,6 +17,7 @@ dependencies { api("net.md-5:bungeecord-chat:1.16-R0.4") api("org.yaml:snakeyaml:1.29") api("com.googlecode.json-simple:json-simple:1.1.1") // Paper @@ -18,7 +18,7 @@ index b75ac1f11c3171a3f0c8edb30be3555216f51b0a..218e9c682e7b91dc27f2caf46316ba7a compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/pom.xml b/pom.xml -index d7cf64f05d0a2f5b186ca13b2b88e390abe84226..1ebc4c096638128194cea9c2a4131f901e7d6896 100644 +index e5802bcb6fc2376cff2ee8b3069150127312b154..7b44549b508862b207324a6003fcdfa623f40f07 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,12 @@ diff --git a/patches/api/0006-Adventure.patch b/patches/api/0006-Adventure.patch index 107340f64e..ca041f6d3b 100644 --- a/patches/api/0006-Adventure.patch +++ b/patches/api/0006-Adventure.patch @@ -7,10 +7,10 @@ Co-authored-by: zml Co-authored-by: Jake Potrebic diff --git a/build.gradle.kts b/build.gradle.kts -index 218e9c682e7b91dc27f2caf46316ba7a7982e5f3..50c3a01826f0ff939e3ee935d5a4e446f46c8cce 100644 +index 6243c2fc2021e6c4fe0f036892bc83983364f360..d22f6ce80583f4a12e61b5ca89033deeeebde5d5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -19,6 +19,11 @@ dependencies { +@@ -18,6 +18,11 @@ dependencies { api("org.yaml:snakeyaml:1.29") api("com.googlecode.json-simple:json-simple:1.1.1") // Paper api("it.unimi.dsi:fastutil:8.2.2") diff --git a/patches/api/0024-Use-ASM-for-event-executors.patch b/patches/api/0024-Use-ASM-for-event-executors.patch index 2cb4f1f832..ba94a254e2 100644 --- a/patches/api/0024-Use-ASM-for-event-executors.patch +++ b/patches/api/0024-Use-ASM-for-event-executors.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Use ASM for event executors. Uses method handles for private or static methods. diff --git a/build.gradle.kts b/build.gradle.kts -index 50c3a01826f0ff939e3ee935d5a4e446f46c8cce..c976d4458886603feeb05b7c854a5c1e54fcb287 100644 +index d22f6ce80583f4a12e61b5ca89033deeeebde5d5..a5f7258a543c8a9e2ce55c6f8f1b6f3435ef608e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -24,6 +24,8 @@ dependencies { +@@ -23,6 +23,8 @@ dependencies { api("net.kyori:adventure-text-serializer-gson") api("net.kyori:adventure-text-serializer-legacy") api("net.kyori:adventure-text-serializer-plain") @@ -19,7 +19,7 @@ index 50c3a01826f0ff939e3ee935d5a4e446f46c8cce..c976d4458886603feeb05b7c854a5c1e compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/pom.xml b/pom.xml -index cae43ce5c1287a4cd117fd069d34ebc1b64b7fdb..2c757ffb2253748c6a81f9b373290108209b6ff2 100644 +index f2238314b948be036d9e7054d7af5bfdac8ebbf6..aefaeec678b2f6b5ba1c15e43c4886eb9af6b143 100644 --- a/pom.xml +++ b/pom.xml @@ -163,6 +163,17 @@ diff --git a/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch b/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch index b59af7a1bd..2196884838 100644 --- a/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch +++ b/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch @@ -14,10 +14,10 @@ it without having to shade it in the plugin and going through several layers of logging abstraction. diff --git a/build.gradle.kts b/build.gradle.kts -index c976d4458886603feeb05b7c854a5c1e54fcb287..9633529a71556a453edae71b09a573a957d65c60 100644 +index a5f7258a543c8a9e2ce55c6f8f1b6f3435ef608e..12c4f278d52bd6fb626fc7cd9414e8869c49fcd2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -26,6 +26,7 @@ dependencies { +@@ -25,6 +25,7 @@ dependencies { api("net.kyori:adventure-text-serializer-plain") api("org.ow2.asm:asm:9.0") api("org.ow2.asm:asm-commons:9.0") From 9085da6e602fda8de3b03fece8e4d31278274b8c Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Mon, 14 Jun 2021 02:19:51 +0200 Subject: [PATCH 089/226] fix tests --- patches/server/0002-Decompile-fixes.patch | 95 +++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/patches/server/0002-Decompile-fixes.patch b/patches/server/0002-Decompile-fixes.patch index deb8f3303f..fea43707a9 100644 --- a/patches/server/0002-Decompile-fixes.patch +++ b/patches/server/0002-Decompile-fixes.patch @@ -75,3 +75,98 @@ index b4a5709b03e400d00504f33a9b34019d2b7bf115..2d79d4014770081fcd58a929e5fe0a26 return new Object2ObjectLinkedOpenHashMap<>(); // CraftBukkit }); Recipe irecipe1 = (Recipe) map1.put(irecipe.getId(), irecipe); +diff --git a/src/test/java/org/bukkit/DyeColorsTest.java b/src/test/java/org/bukkit/DyeColorsTest.java +index ad52c3fc6210939a39ef77a382c640a24ee44838..5d811797ce8e14195a23fc71c8a3afbdca7691eb 100644 +--- a/src/test/java/org/bukkit/DyeColorsTest.java ++++ b/src/test/java/org/bukkit/DyeColorsTest.java +@@ -4,7 +4,6 @@ import static org.hamcrest.Matchers.*; + import static org.junit.Assert.*; + import java.util.ArrayList; + import java.util.List; +-import net.minecraft.world.item.DyeColor; + import org.bukkit.support.AbstractTestingBase; + import org.junit.Test; + import org.junit.runner.RunWith; +@@ -29,7 +28,7 @@ public class DyeColorsTest extends AbstractTestingBase { + @Test + public void checkColor() { + Color color = this.dye.getColor(); +- float[] nmsColorArray = DyeColor.byId(this.dye.getWoolData()).getTextureDiffuseColors(); ++ float[] nmsColorArray = net.minecraft.world.item.DyeColor.byId(this.dye.getWoolData()).getTextureDiffuseColors(); + Color nmsColor = Color.fromRGB((int) (nmsColorArray[0] * 255), (int) (nmsColorArray[1] * 255), (int) (nmsColorArray[2] * 255)); + assertThat(color, is(nmsColor)); + } +@@ -37,7 +36,7 @@ public class DyeColorsTest extends AbstractTestingBase { + @Test + public void checkFireworkColor() { + Color color = this.dye.getFireworkColor(); +- int nmsColor = DyeColor.byId(this.dye.getWoolData()).getFireworkColor(); ++ int nmsColor = net.minecraft.world.item.DyeColor.byId(this.dye.getWoolData()).getFireworkColor(); + assertThat(color, is(Color.fromRGB(nmsColor))); + } + } +diff --git a/src/test/java/org/bukkit/PerMaterialTest.java b/src/test/java/org/bukkit/PerMaterialTest.java +index 90baf6e3329d64495da9edd580d5fbc80df8c165..185fa8bf7308bb2980a0feecf0d7696a59e507ac 100644 +--- a/src/test/java/org/bukkit/PerMaterialTest.java ++++ b/src/test/java/org/bukkit/PerMaterialTest.java +@@ -221,7 +221,7 @@ public class PerMaterialTest extends AbstractTestingBase { + if (this.material.isBlock()) { + assertThat(this.material.isInteractable(), + is(!CraftMagicNumbers.getBlock(material).getClass() +- .getMethod("interact", BlockState.class, net.minecraft.world.level.Level.class, BlockPos.class, Player.class, InteractionHand.class, BlockHitResult.class) ++ .getMethod("use", BlockState.class, net.minecraft.world.level.Level.class, BlockPos.class, Player.class, InteractionHand.class, BlockHitResult.class) + .getDeclaringClass().equals(BlockBehaviour.class))); + } else { + assertFalse(this.material.isInteractable()); +diff --git a/src/test/java/org/bukkit/entity/EntityTypesTest.java b/src/test/java/org/bukkit/entity/EntityTypesTest.java +index 8c4ad718e113f24a30fd11b345d34d6ca1ef73b0..085b0c17fb54fd8229838fee666120d9e59d942b 100644 +--- a/src/test/java/org/bukkit/entity/EntityTypesTest.java ++++ b/src/test/java/org/bukkit/entity/EntityTypesTest.java +@@ -5,7 +5,6 @@ import java.util.Set; + import java.util.stream.Collectors; + import net.minecraft.core.Registry; + import net.minecraft.resources.ResourceLocation; +-import net.minecraft.world.entity.EntityType; + import org.bukkit.support.AbstractTestingBase; + import org.junit.Assert; + import org.junit.Test; +@@ -16,8 +15,8 @@ public class EntityTypesTest extends AbstractTestingBase { + public void testMaps() { + Set allBukkit = Arrays.stream(EntityType.values()).filter((b) -> b.getName() != null).collect(Collectors.toSet()); + +- for (EntityType nms : Registry.ENTITY_TYPE) { +- ResourceLocation key = EntityType.getKey(nms); ++ for (net.minecraft.world.entity.EntityType nms : Registry.ENTITY_TYPE) { ++ ResourceLocation key = net.minecraft.world.entity.EntityType.getKey(nms); + + org.bukkit.entity.EntityType bukkit = org.bukkit.entity.EntityType.fromName(key.getPath()); + Assert.assertNotNull("Missing nms->bukkit " + key, bukkit); +diff --git a/src/test/java/org/bukkit/entity/PandaGeneTest.java b/src/test/java/org/bukkit/entity/PandaGeneTest.java +index 76e2ad676ae68846bdff3c3ef711751445fb0f3c..bee1bd015f161a00df1311b6ef272739fcff6834 100644 +--- a/src/test/java/org/bukkit/entity/PandaGeneTest.java ++++ b/src/test/java/org/bukkit/entity/PandaGeneTest.java +@@ -1,6 +1,5 @@ + package org.bukkit.entity; + +-import net.minecraft.world.entity.animal.Panda; + import org.bukkit.craftbukkit.entity.CraftPanda; + import org.junit.Assert; + import org.junit.Test; +@@ -10,7 +9,7 @@ public class PandaGeneTest { + @Test + public void testBukkit() { + for (Panda.Gene gene : Panda.Gene.values()) { +- Panda.Gene nms = CraftPanda.toNms(gene); ++ net.minecraft.world.entity.animal.Panda.Gene nms = CraftPanda.toNms(gene); + + Assert.assertNotNull("NMS gene null for " + gene, nms); + Assert.assertEquals("Recessive status did not match " + gene, gene.isRecessive(), nms.isRecessive()); +@@ -20,7 +19,7 @@ public class PandaGeneTest { + + @Test + public void testNMS() { +- for (Panda.Gene gene : Panda.Gene.values()) { ++ for (net.minecraft.world.entity.animal.Panda.Gene gene : net.minecraft.world.entity.animal.Panda.Gene.values()) { + org.bukkit.entity.Panda.Gene bukkit = CraftPanda.fromNms(gene); + + Assert.assertNotNull("Bukkit gene null for " + gene, bukkit); From 2a46c72164697a80f7b257dcc26b980c48b505ff Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Sun, 13 Jun 2021 18:06:38 -0700 Subject: [PATCH 090/226] EVEN MOOOOOAAAAAAARRRRRRR patches :) (#5820) --- Paper-MojangAPI/build.gradle.kts | 26 ++ ...-get-a-BlockState-without-a-snapshot.patch | 4 +- patches/api/0116-RangedEntity-API.patch | 19 +- ...Blocks-to-be-accessed-via-a-long-key.patch | 4 +- .../0181-Add-BlockSoundGroup-interface.patch | 14 +- ...-Add-effect-to-block-break-naturally.patch | 4 +- .../0191-Add-tick-times-API.patch} | 4 +- ...92-Expose-MinecraftServer-isRunning.patch} | 4 +- ...dd-Raw-Byte-ItemStack-Serialization.patch} | 2 +- ...ts-firing-Async-errors-during-shutd.patch} | 2 +- ...5-Make-JavaPluginLoader-thread-safe.patch} | 0 .../0196-Add-Player-Client-Options-API.patch} | 4 +- ...layerAttackEntityCooldownResetEvent.patch} | 0 ...Stack-swapping-the-extended-and-upg.patch} | 0 .../0199-Villager-Restocks-API.patch} | 0 .../0200-Expose-game-version.patch} | 4 +- ...ions-until-after-entity-ticking-is-d.patch | 2 + ...oviderServer-s-chunk-level-checking-.patch | 2 + ...Add-Raw-Byte-ItemStack-Serialization.patch | 102 ----- ...0441-Remove-streams-from-PairedQueue.patch | 79 ---- ...Load-Chunks-for-Login-Asynchronously.patch | 416 ------------------ .../0464-Optimize-Voxel-Shape-Merging.patch | 175 -------- patches/server/0010-Adventure.patch | 4 +- patches/server/0025-Entity-Origin-API.patch | 4 +- .../server/0051-Add-velocity-warnings.patch | 4 +- ...rovide-E-TE-Chunk-count-stat-methods.patch | 4 +- ...PI-for-Reason-Source-Triggering-play.patch | 4 +- .../server/0147-Entity-fromMobSpawner.patch | 4 +- ...-get-a-BlockState-without-a-snapshot.patch | 4 +- ...ld.spawnParticle-API-and-add-Builder.patch | 4 +- ...Item-entities-with-World.spawnEntity.patch | 4 +- .../0206-Fix-CraftEntity-hashCode.patch | 4 +- .../server/0213-Expand-Explosions-API.patch | 4 +- patches/server/0215-RangedEntity-API.patch | 12 +- ...7-Implement-World.getEntity-UUID-API.patch | 4 +- ...loadChunk-int-int-false-load-unconve.patch | 4 +- ...57-Asynchronous-chunk-IO-and-loading.patch | 8 +- patches/server/0272-Add-sun-related-API.patch | 4 +- .../0312-Entity-getEntitySpawnReason.patch | 4 +- patches/server/0320-Add-Heightmap-API.patch | 4 +- ...325-improve-CraftWorld-isChunkLoaded.patch | 4 +- ...le-Keep-Spawn-Loaded-range-per-world.patch | 4 +- .../0328-Implement-CraftBlockSoundGroup.patch | 9 +- ...330-Fix-World-isChunkGenerated-calls.patch | 6 +- ...hanging-entities-that-are-not-ItemFr.patch | 4 +- ...-Add-effect-to-block-break-naturally.patch | 6 +- ...No-Tick-view-distance-implementation.patch | 4 +- ...hunkMap-memory-use-for-visibleChunks.patch | 12 +- ...Add-tick-times-API-and-mspt-command.patch} | 21 +- ...90-Expose-MinecraftServer-isRunning.patch} | 4 +- ...Add-Raw-Byte-ItemStack-Serialization.patch | 58 +++ ...2-Remove-streams-from-Mob-AI-System.patch} | 169 +++---- .../0393-Async-command-map-building.patch} | 6 +- .../0394-Improved-Watchdog-Support.patch} | 169 +++---- .../0395-Optimize-Pathfinding.patch} | 32 +- ...6-Reduce-Either-Optional-allocation.patch} | 2 +- ...0397-Remove-streams-from-PairedQueue.patch | 46 ++ ...-memory-footprint-of-NBTTagCompound.patch} | 35 +- ...ent-opening-inventories-when-frozen.patch} | 29 +- ...00-Optimise-ArraySetSorted-removeIf.patch} | 30 +- ...entity-collision-code-if-not-needed.patch} | 8 +- ...teleport-command-to-valid-locations.patch} | 4 +- ...Implement-Player-Client-Options-API.patch} | 90 +--- ...Chunk-Post-Processing-deadlock-risk.patch} | 13 +- ...ayer-is-attempted-to-be-removed-fro.patch} | 4 +- ...6-Broadcast-join-message-to-console.patch} | 8 +- ...-Broken-behavior-of-PlayerJoinEvent.patch} | 72 +-- ...Load-Chunks-for-Login-Asynchronously.patch | 277 ++++++++++++ ...awn-point-if-spawn-in-unloaded-worl.patch} | 6 +- ...layerAttackEntityCooldownResetEvent.patch} | 4 +- ...llbacks-to-schedule-for-Callback-Ex.patch} | 38 +- ...-fire-BlockFade-on-worldgen-threads.patch} | 8 +- ...tom-creative-and-insomniac-controls.patch} | 39 +- ...-duplication-issues-and-teleport-is.patch} | 24 +- ...0415-Implement-Brigadier-Mojang-API.patch} | 34 +- .../0416-Villager-Restocks-API.patch} | 10 +- ...ickItem-Packet-and-kick-for-invalid.patch} | 16 +- .../0418-Expose-game-version.patch} | 6 +- .../0419-Optimize-Voxel-Shape-Merging.patch | 121 +++++ settings.gradle.kts | 2 +- work/Bukkit | 2 +- work/CraftBukkit | 2 +- 82 files changed, 971 insertions(+), 1418 deletions(-) create mode 100644 Paper-MojangAPI/build.gradle.kts rename patches/{api-unmapped/0190-Add-tick-times-API.patch => api/0191-Add-tick-times-API.patch} (90%) rename patches/{api-unmapped/0191-Expose-MinecraftServer-isRunning.patch => api/0192-Expose-MinecraftServer-isRunning.patch} (88%) rename patches/{api-unmapped/0206-Add-Raw-Byte-ItemStack-Serialization.patch => api/0193-Add-Raw-Byte-ItemStack-Serialization.patch} (96%) rename patches/{api-unmapped/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch => api/0194-Disable-Sync-Events-firing-Async-errors-during-shutd.patch} (93%) rename patches/{api-unmapped/0193-Make-JavaPluginLoader-thread-safe.patch => api/0195-Make-JavaPluginLoader-thread-safe.patch} (100%) rename patches/{api-unmapped/0194-Add-Player-Client-Options-API.patch => api/0196-Add-Player-Client-Options-API.patch} (97%) rename patches/{api-unmapped/0195-Add-PlayerAttackEntityCooldownResetEvent.patch => api/0197-Add-PlayerAttackEntityCooldownResetEvent.patch} (100%) rename patches/{api-unmapped/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch => api/0198-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch} (100%) rename patches/{api-unmapped/0197-Villager-Restocks-API.patch => api/0199-Villager-Restocks-API.patch} (100%) rename patches/{api-unmapped/0198-Expose-game-version.patch => api/0200-Expose-game-version.patch} (89%) rename patches/{server-remapped => removed/1.17}/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch (95%) rename patches/{server-remapped => removed/1.17}/0446-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch (99%) delete mode 100644 patches/server-remapped/0434-Add-Raw-Byte-ItemStack-Serialization.patch delete mode 100644 patches/server-remapped/0441-Remove-streams-from-PairedQueue.patch delete mode 100644 patches/server-remapped/0453-Load-Chunks-for-Login-Asynchronously.patch delete mode 100644 patches/server-remapped/0464-Optimize-Voxel-Shape-Merging.patch rename patches/{server-remapped/0432-Add-tick-times-API-and-mspt-command.patch => server/0389-Add-tick-times-API-and-mspt-command.patch} (89%) rename patches/{server-remapped/0433-Expose-MinecraftServer-isRunning.patch => server/0390-Expose-MinecraftServer-isRunning.patch} (83%) create mode 100644 patches/server/0391-Add-Raw-Byte-ItemStack-Serialization.patch rename patches/{server-remapped/0435-Remove-streams-from-Mob-AI-System.patch => server/0392-Remove-streams-from-Mob-AI-System.patch} (58%) rename patches/{server-remapped/0437-Async-command-map-building.patch => server/0393-Async-command-map-building.patch} (95%) rename patches/{server-remapped/0438-Improved-Watchdog-Support.patch => server/0394-Improved-Watchdog-Support.patch} (81%) rename patches/{server-remapped/0439-Optimize-Pathfinding.patch => server/0395-Optimize-Pathfinding.patch} (51%) rename patches/{server-remapped/0440-Reduce-Either-Optional-allocation.patch => server/0396-Reduce-Either-Optional-allocation.patch} (95%) create mode 100644 patches/server/0397-Remove-streams-from-PairedQueue.patch rename patches/{server-remapped/0442-Reduce-memory-footprint-of-NBTTagCompound.patch => server/0398-Reduce-memory-footprint-of-NBTTagCompound.patch} (50%) rename patches/{server-remapped/0443-Prevent-opening-inventories-when-frozen.patch => server/0399-Prevent-opening-inventories-when-frozen.patch} (76%) rename patches/{server-remapped/0444-Optimise-ArraySetSorted-removeIf.patch => server/0400-Optimise-ArraySetSorted-removeIf.patch} (60%) rename patches/{server-remapped/0445-Don-t-run-entity-collision-code-if-not-needed.patch => server/0401-Don-t-run-entity-collision-code-if-not-needed.patch} (81%) rename patches/{server-remapped/0447-Restrict-vanilla-teleport-command-to-valid-locations.patch => server/0402-Restrict-vanilla-teleport-command-to-valid-locations.patch} (90%) rename patches/{server-remapped/0448-Implement-Player-Client-Options-API.patch => server/0403-Implement-Player-Client-Options-API.patch} (50%) rename patches/{server-remapped/0449-Fix-Chunk-Post-Processing-deadlock-risk.patch => server/0404-Fix-Chunk-Post-Processing-deadlock-risk.patch} (87%) rename patches/{server-remapped/0450-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch => server/0405-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch} (88%) rename patches/{server-remapped/0451-Broadcast-join-message-to-console.patch => server/0406-Broadcast-join-message-to-console.patch} (65%) rename patches/{server-remapped/0452-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch => server/0407-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch} (61%) create mode 100644 patches/server/0408-Load-Chunks-for-Login-Asynchronously.patch rename patches/{server-remapped/0454-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch => server/0409-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch} (79%) rename patches/{server-remapped/0455-Add-PlayerAttackEntityCooldownResetEvent.patch => server/0410-Add-PlayerAttackEntityCooldownResetEvent.patch} (92%) rename patches/{server-remapped/0456-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch => server/0411-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch} (63%) rename patches/{server-remapped/0457-Don-t-fire-BlockFade-on-worldgen-threads.patch => server/0412-Don-t-fire-BlockFade-on-worldgen-threads.patch} (80%) rename patches/{server-remapped/0458-Add-phantom-creative-and-insomniac-controls.patch => server/0413-Add-phantom-creative-and-insomniac-controls.patch} (68%) rename patches/{server-remapped/0459-Fix-numerous-item-duplication-issues-and-teleport-is.patch => server/0414-Fix-numerous-item-duplication-issues-and-teleport-is.patch} (85%) rename patches/{server-remapped/0460-Implement-Brigadier-Mojang-API.patch => server/0415-Implement-Brigadier-Mojang-API.patch} (86%) rename patches/{server-remapped/0461-Villager-Restocks-API.patch => server/0416-Villager-Restocks-API.patch} (60%) rename patches/{server-remapped/0462-Validate-PickItem-Packet-and-kick-for-invalid.patch => server/0417-Validate-PickItem-Packet-and-kick-for-invalid.patch} (65%) rename patches/{server-remapped/0463-Expose-game-version.patch => server/0418-Expose-game-version.patch} (78%) create mode 100644 patches/server/0419-Optimize-Voxel-Shape-Merging.patch diff --git a/Paper-MojangAPI/build.gradle.kts b/Paper-MojangAPI/build.gradle.kts new file mode 100644 index 0000000000..e0ef6532b9 --- /dev/null +++ b/Paper-MojangAPI/build.gradle.kts @@ -0,0 +1,26 @@ +plugins { + `java-library` + checkstyle +} + +java { + withSourcesJar() + withJavadocJar() +} + +repositories { + mavenCentral() + maven("https://libraries.minecraft.net") +} + +dependencies { + implementation(project(":Paper-API")) + api("com.mojang:brigadier:1.0.18") + + compileOnly("it.unimi.dsi:fastutil") + compileOnly("org.jetbrains:annotations:18.0.0") + + testImplementation("junit:junit:4.13.1") + testImplementation("org.hamcrest:hamcrest-library:1.3") + testImplementation("org.ow2.asm:asm-tree:7.3.1") +} \ No newline at end of file diff --git a/patches/api/0072-API-to-get-a-BlockState-without-a-snapshot.patch b/patches/api/0072-API-to-get-a-BlockState-without-a-snapshot.patch index 17364528bc..26c4c4cc18 100644 --- a/patches/api/0072-API-to-get-a-BlockState-without-a-snapshot.patch +++ b/patches/api/0072-API-to-get-a-BlockState-without-a-snapshot.patch @@ -9,10 +9,10 @@ on the real tile entity. This is useful for where performance is needed diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index d4c69573f250309adc442c7cf67ea6fc2f2e3ace..969a6cf404d99c186e73321659240195b8650ffc 100644 +index da0964b1b6555ad50cb2ee47f13a7b9dfb1ab6aa..3ca05a6e86a5329cf452041eac476e3636eec34a 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java -@@ -269,6 +269,16 @@ public interface Block extends Metadatable { +@@ -271,6 +271,16 @@ public interface Block extends Metadatable { @NotNull BlockState getState(); diff --git a/patches/api/0116-RangedEntity-API.patch b/patches/api/0116-RangedEntity-API.patch index f609bc2f0e..c86139036d 100644 --- a/patches/api/0116-RangedEntity-API.patch +++ b/patches/api/0116-RangedEntity-API.patch @@ -122,23 +122,18 @@ index 9a2252fef56be1ed3ae2169aea46cb567e965c6c..11f38187fca830d974be01fea2966a31 -public interface Pillager extends Illager, InventoryHolder { } +public interface Pillager extends Illager, InventoryHolder, RangedEntity { } // Paper diff --git a/src/main/java/org/bukkit/entity/Skeleton.java b/src/main/java/org/bukkit/entity/Skeleton.java -index 16b1293887cee2bc5267f3da771fb5a6ece1b4e9..1c367f78eadf24850061a84ce63b950b79d3c435 100644 +index 01d838a60d056bf4b4a8ef9d0ac18c6f91f412e6..b7e424ea8a282f45fb8b91c919e4e4526c00be8b 100644 --- a/src/main/java/org/bukkit/entity/Skeleton.java +++ b/src/main/java/org/bukkit/entity/Skeleton.java -@@ -2,11 +2,12 @@ package org.bukkit.entity; - - import org.jetbrains.annotations.Contract; - import org.jetbrains.annotations.NotNull; -+import com.destroystokyo.paper.entity.RangedEntity; - - /** - * Represents a Skeleton. +@@ -7,7 +7,7 @@ package org.bukkit.entity; + * Other skeleton-like entities, such as the {@link WitherSkeleton} or the + * {@link Stray} are not related to this type. */ --public interface Skeleton extends Monster { -+public interface Skeleton extends Monster, RangedEntity { // Paper +-public interface Skeleton extends AbstractSkeleton { ++public interface Skeleton extends AbstractSkeleton, com.destroystokyo.paper.entity.RangedEntity { // Paper /** - * Gets the current type of this skeleton. + * Computes whether or not this skeleton is currently in the process of diff --git a/src/main/java/org/bukkit/entity/Snowman.java b/src/main/java/org/bukkit/entity/Snowman.java index 818efe2a4d1ac0c4d8dca6c757850d99cdc2cb4b..10f8f6d45ae9280651c3ebddd1f90acbd7d6ff29 100644 --- a/src/main/java/org/bukkit/entity/Snowman.java diff --git a/patches/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch b/patches/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch index 7014671c66..6591a86aed 100644 --- a/patches/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch +++ b/patches/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch @@ -91,10 +91,10 @@ index f45bea24a350c3700bdbf4c44aeb1c0562e57d9e..a653a09968123724f9ec5501760257b3 * Gets the highest non-empty (impassable) coordinate at the given * coordinates. diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 969a6cf404d99c186e73321659240195b8650ffc..b090938f883c486e703cb7c036c47925f3016704 100644 +index 3ca05a6e86a5329cf452041eac476e3636eec34a..18ab5cca036522df2d245f755d6c67904e6398e8 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java -@@ -153,6 +153,72 @@ public interface Block extends Metadatable { +@@ -155,6 +155,72 @@ public interface Block extends Metadatable { */ int getZ(); diff --git a/patches/api/0181-Add-BlockSoundGroup-interface.patch b/patches/api/0181-Add-BlockSoundGroup-interface.patch index 428810f1d8..566c91565a 100644 --- a/patches/api/0181-Add-BlockSoundGroup-interface.patch +++ b/patches/api/0181-Add-BlockSoundGroup-interface.patch @@ -64,21 +64,13 @@ index 0000000000000000000000000000000000000000..8cf87d228a7006658d52ce0da16c2d74 + Sound getFallSound(); +} diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index b090938f883c486e703cb7c036c47925f3016704..5e2aa4fb8cf8130df21d3172dd94e857317f7653 100644 +index 18ab5cca036522df2d245f755d6c67904e6398e8..5ac36e0f90d0889853736390877aa92ec0ca181b 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java -@@ -1,6 +1,7 @@ - package org.bukkit.block; - - import java.util.Collection; -+ - import org.bukkit.Chunk; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -560,4 +561,16 @@ public interface Block extends Metadatable { +@@ -587,4 +587,16 @@ public interface Block extends Metadatable { */ @NotNull - BoundingBox getBoundingBox(); + VoxelShape getCollisionShape(); + + // Paper start + /** diff --git a/patches/api/0186-Add-effect-to-block-break-naturally.patch b/patches/api/0186-Add-effect-to-block-break-naturally.patch index 5ccd8c2548..ce1785047a 100644 --- a/patches/api/0186-Add-effect-to-block-break-naturally.patch +++ b/patches/api/0186-Add-effect-to-block-break-naturally.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add effect to block break naturally diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 5e2aa4fb8cf8130df21d3172dd94e857317f7653..e1cc36fbe808973227c0e8ca7166453235c90279 100644 +index 5ac36e0f90d0889853736390877aa92ec0ca181b..786b8011e98b2fe93cc2418d624f6350ede62d90 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java -@@ -469,6 +469,18 @@ public interface Block extends Metadatable { +@@ -470,6 +470,18 @@ public interface Block extends Metadatable { */ boolean breakNaturally(@Nullable ItemStack tool); diff --git a/patches/api-unmapped/0190-Add-tick-times-API.patch b/patches/api/0191-Add-tick-times-API.patch similarity index 90% rename from patches/api-unmapped/0190-Add-tick-times-API.patch rename to patches/api/0191-Add-tick-times-API.patch index a4ae8d485c..b4d7379b4b 100644 --- a/patches/api-unmapped/0190-Add-tick-times-API.patch +++ b/patches/api/0191-Add-tick-times-API.patch @@ -5,7 +5,7 @@ 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 49bf621a2c0e5e9641b334a42b2769944c991d5d..4bae8a4387b86c868149f06b490ef6dfced2ff41 100644 +index 02f91b446697b1c637fda3b65b48ec8cf38de66d..1eeb1257888ef2e2d92598e2b1a80286a087dfa5 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1590,6 +1590,25 @@ public final class Bukkit { @@ -35,7 +35,7 @@ index 49bf621a2c0e5e9641b334a42b2769944c991d5d..4bae8a4387b86c868149f06b490ef6df /** diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index e448ae78304974f7664b7ef18568a547833ece9f..bea7ffdb00e6de1391e9143901c62f0aceaaf727 100644 +index b038a82ffc298abb5129b6ec20538df5d0b6f595..3c9890ce33231070836ee471206b20cec74e00b4 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1345,6 +1345,21 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api-unmapped/0191-Expose-MinecraftServer-isRunning.patch b/patches/api/0192-Expose-MinecraftServer-isRunning.patch similarity index 88% rename from patches/api-unmapped/0191-Expose-MinecraftServer-isRunning.patch rename to patches/api/0192-Expose-MinecraftServer-isRunning.patch index 33f2570121..4a5c20868f 100644 --- a/patches/api-unmapped/0191-Expose-MinecraftServer-isRunning.patch +++ b/patches/api/0192-Expose-MinecraftServer-isRunning.patch @@ -6,7 +6,7 @@ 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 4bae8a4387b86c868149f06b490ef6dfced2ff41..4dadea432c8d79b15fa126b4f0c810e9a72b4029 100644 +index 1eeb1257888ef2e2d92598e2b1a80286a087dfa5..847ba5143660d5c56ff8f2cae2169a51b8927757 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1858,6 +1858,15 @@ public final class Bukkit { @@ -26,7 +26,7 @@ index 4bae8a4387b86c868149f06b490ef6dfced2ff41..4dadea432c8d79b15fa126b4f0c810e9 @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index bea7ffdb00e6de1391e9143901c62f0aceaaf727..b92261e09790e89788560bf7c9784c8399504810 100644 +index 3c9890ce33231070836ee471206b20cec74e00b4..e6b62ba32e089e2fd8563ec8430b72196f6680e0 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1631,5 +1631,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api-unmapped/0206-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/api/0193-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 96% rename from patches/api-unmapped/0206-Add-Raw-Byte-ItemStack-Serialization.patch rename to patches/api/0193-Add-Raw-Byte-ItemStack-Serialization.patch index 8ffb283fa6..e88adb86e7 100644 --- a/patches/api-unmapped/0206-Add-Raw-Byte-ItemStack-Serialization.patch +++ b/patches/api/0193-Add-Raw-Byte-ItemStack-Serialization.patch @@ -20,7 +20,7 @@ index d6897f43a0692e031bed8a212d9a637ef548cc60..e348034288c74ab80360086d71f0b7f6 // Paper end } diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index bf39989dbe08c93120d75bed6281ae75c460afca..15b48ad1ba5bcf7394fb3f52ce2cc6baa6632f66 100644 +index 290c3f0fd6e8c3407d421b697e0ee01584f4cebd..9a878e4fde31c015e2f3fdf365d5d16c30198685 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -628,6 +628,30 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor diff --git a/patches/api-unmapped/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch b/patches/api/0194-Disable-Sync-Events-firing-Async-errors-during-shutd.patch similarity index 93% rename from patches/api-unmapped/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch rename to patches/api/0194-Disable-Sync-Events-firing-Async-errors-during-shutd.patch index 5ca0264ed8..32392efc4e 100644 --- a/patches/api-unmapped/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch +++ b/patches/api/0194-Disable-Sync-Events-firing-Async-errors-during-shutd.patch @@ -11,7 +11,7 @@ errors. This isn't an issue on Spigot diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index a1a805004941d67abb0b9aa1721e0370c45b5289..26685f59b235ea5b4c4fb7ae21acb5149edaa2b3 100644 +index b83637f872be5fc73500b10c917d71802976b340..49e5d49eb09bb966e47d6a03ac08a527c963b43d 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -591,7 +591,7 @@ public final class SimplePluginManager implements PluginManager { diff --git a/patches/api-unmapped/0193-Make-JavaPluginLoader-thread-safe.patch b/patches/api/0195-Make-JavaPluginLoader-thread-safe.patch similarity index 100% rename from patches/api-unmapped/0193-Make-JavaPluginLoader-thread-safe.patch rename to patches/api/0195-Make-JavaPluginLoader-thread-safe.patch diff --git a/patches/api-unmapped/0194-Add-Player-Client-Options-API.patch b/patches/api/0196-Add-Player-Client-Options-API.patch similarity index 97% rename from patches/api-unmapped/0194-Add-Player-Client-Options-API.patch rename to patches/api/0196-Add-Player-Client-Options-API.patch index c156119b15..a271a07324 100644 --- a/patches/api-unmapped/0194-Add-Player-Client-Options-API.patch +++ b/patches/api/0196-Add-Player-Client-Options-API.patch @@ -176,7 +176,7 @@ index 0000000000000000000000000000000000000000..f7f171c4ee0b8339b2f8fbe82442d65f + } +} diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index ec87c78d0f9379511467b6d13b9cdfa4c19d15ca..2530c811f52f51d6338900221b4681c952c1c752 100644 +index 685975e7bb8938ce0b2d80855c4c5549f50b262d..e53f641e11dc74c99e656e985caa7c5943fb53a4 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -2,6 +2,7 @@ package org.bukkit.entity; @@ -187,7 +187,7 @@ index ec87c78d0f9379511467b6d13b9cdfa4c19d15ca..2530c811f52f51d6338900221b4681c9 import com.destroystokyo.paper.Title; // Paper import net.kyori.adventure.text.Component; import com.destroystokyo.paper.profile.PlayerProfile; // Paper -@@ -1909,6 +1910,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1936,6 +1937,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * Reset the cooldown counter to 0, effectively starting the cooldown period. */ void resetCooldown(); diff --git a/patches/api-unmapped/0195-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/api/0197-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from patches/api-unmapped/0195-Add-PlayerAttackEntityCooldownResetEvent.patch rename to patches/api/0197-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/patches/api-unmapped/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch b/patches/api/0198-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch similarity index 100% rename from patches/api-unmapped/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch rename to patches/api/0198-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch diff --git a/patches/api-unmapped/0197-Villager-Restocks-API.patch b/patches/api/0199-Villager-Restocks-API.patch similarity index 100% rename from patches/api-unmapped/0197-Villager-Restocks-API.patch rename to patches/api/0199-Villager-Restocks-API.patch diff --git a/patches/api-unmapped/0198-Expose-game-version.patch b/patches/api/0200-Expose-game-version.patch similarity index 89% rename from patches/api-unmapped/0198-Expose-game-version.patch rename to patches/api/0200-Expose-game-version.patch index 560d2370a1..987427e030 100644 --- a/patches/api-unmapped/0198-Expose-game-version.patch +++ b/patches/api/0200-Expose-game-version.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Expose game version diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 86ac6702b3aeab1126b2b2879b87ef3883793d44..12214ce2af7363d40cf44652e46f05c5c1f2fe5a 100644 +index 847ba5143660d5c56ff8f2cae2169a51b8927757..2c9d2739e78d5c422574f5ddda078ca395c0fa6d 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -118,6 +118,18 @@ public final class Bukkit { @@ -28,7 +28,7 @@ index 86ac6702b3aeab1126b2b2879b87ef3883793d44..12214ce2af7363d40cf44652e46f05c5 * 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 16a74b834c4d4b907f9b11ccf9ef9804514df224..360decea2eb6de4c567fa4cceea8f19bceff6823 100644 +index e6b62ba32e089e2fd8563ec8430b72196f6680e0..46d1086bd7d7f91b4337c8463974d4b9d501cbf0 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -97,6 +97,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/server-remapped/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch b/patches/removed/1.17/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch similarity index 95% rename from patches/server-remapped/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch rename to patches/removed/1.17/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch index 9fb51d1e35..2c856fd185 100644 --- a/patches/server-remapped/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch +++ b/patches/removed/1.17/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch @@ -5,6 +5,8 @@ Subject: [PATCH] Delay unsafe actions until after entity ticking is done This will help prevent many cases of unregistering entities during entity ticking +1.17: Not used anywhere in 1.16.5 server, and no more tickingEntities bool on ServerLevel + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 4e75cc5e52a5295e32ccadb371702a405bb518bb..b9978d296b83e73d3395b8254c0e8ccd9b36d0fa 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/server-remapped/0446-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch b/patches/removed/1.17/0446-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch similarity index 99% rename from patches/server-remapped/0446-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch rename to patches/removed/1.17/0446-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch index e6f6255656..083f25a75d 100644 --- a/patches/server-remapped/0446-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch +++ b/patches/removed/1.17/0446-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch @@ -8,6 +8,8 @@ These can be hot functions (i.e entity ticking and block ticking), so inline where possible, and avoid the abstraction of the Either class. +1.17: needs to be looked at again + diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java index 3744cce8611ac01b1b6c76cd3c4890795c1f06a2..531fe1259a1d60ff69321c3fefbf97f7141e6475 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java diff --git a/patches/server-remapped/0434-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server-remapped/0434-Add-Raw-Byte-ItemStack-Serialization.patch deleted file mode 100644 index 4f867cd88c..0000000000 --- a/patches/server-remapped/0434-Add-Raw-Byte-ItemStack-Serialization.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Thu, 30 Apr 2020 16:56:54 +0200 -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/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java -index b3838e709c1581c25da7738c9a03a827761845b1..05ace1d046e32a261e67bff5afc18c2d32e1a8aa 100644 ---- a/src/main/java/net/minecraft/nbt/NbtIo.java -+++ b/src/main/java/net/minecraft/nbt/NbtIo.java -@@ -51,6 +51,7 @@ public class NbtIo { - return nbttagcompound; - } - -+ public static CompoundTag readNBT(InputStream inputstream) throws IOException { return readCompressed(inputstream); } // Paper - OBFHELPER - public static CompoundTag readCompressed(InputStream stream) throws IOException { - DataInputStream datainputstream = new DataInputStream(new BufferedInputStream(new GZIPInputStream(stream))); - Throwable throwable = null; -@@ -106,6 +107,7 @@ public class NbtIo { - - } - -+ public static void writeNBT(CompoundTag nbttagcompound, OutputStream outputstream) throws IOException { writeCompressed(nbttagcompound, outputstream); } // Paper - OBFHELPER - public static void writeCompressed(CompoundTag tag, OutputStream stream) throws IOException { - DataOutputStream dataoutputstream = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(stream))); - Throwable throwable = null; -diff --git a/src/main/java/net/minecraft/util/datafix/DataFixers.java b/src/main/java/net/minecraft/util/datafix/DataFixers.java -index 950a4b67f9091af551ec1036ebeb943e3b335e91..dc4e2fc26e1bc2c545f955d30c052bb86e3ef614 100644 ---- a/src/main/java/net/minecraft/util/datafix/DataFixers.java -+++ b/src/main/java/net/minecraft/util/datafix/DataFixers.java -@@ -78,6 +78,7 @@ public class DataFixers { - return datafixerbuilder.build(Util.bootstrapExecutor()); - } - -+ public static DataFixer getDataFixer() { return getDataFixer(); } // Paper - OBFHELPER - public static DataFixer getDataFixer() { - return DataFixers.DATA_FIXER; - } -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index ac996d581925c8f92832009945c766962e5b51c5..458cdfbeac9d757c9721acd4557a548affa0ede1 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -196,6 +196,7 @@ public final class ItemStack { - this.updateEmptyCacheFlag(); - } - -+ public static ItemStack fromCompound(CompoundTag nbttagcompound) { return of(nbttagcompound); } // Paper - OBFHELPER - public static ItemStack of(CompoundTag tag) { - try { - return new ItemStack(tag); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 86b319337fc41a09dd45df466df60cadaed1343f..a5a5038a84434e69fda8f6b41d2f00b4989e25ae 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -378,6 +378,46 @@ public final class CraftMagicNumbers implements UnsafeValues { - public boolean isSupportedApiVersion(String apiVersion) { - return apiVersion != null && SUPPORTED_API.contains(apiVersion); - } -+ -+ @Override -+ public byte[] serializeItem(ItemStack item) { -+ Preconditions.checkNotNull(item, "null cannot be serialized"); -+ Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized"); -+ -+ java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); -+ CompoundTag compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).getHandle() : CraftItemStack.asNMSCopy(item)).save(new CompoundTag()); -+ compound.putInt("DataVersion", getDataVersion()); -+ try { -+ net.minecraft.nbt.NbtIo.writeNBT( -+ compound, -+ outputStream -+ ); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return outputStream.toByteArray(); -+ } -+ -+ @Override -+ public ItemStack deserializeItem(byte[] data) { -+ Preconditions.checkNotNull(data, "null cannot be deserialized"); -+ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing"); -+ -+ try { -+ CompoundTag compound = net.minecraft.nbt.NbtIo.readNBT( -+ new java.io.ByteArrayInputStream(data) -+ ); -+ int dataVersion = compound.getInt("DataVersion"); -+ -+ Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); -+ Dynamic converted = DataFixers.getDataFixer().update(References.ITEM_STACK, new Dynamic(NbtOps.INSTANCE, compound), dataVersion, getDataVersion()); -+ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.fromCompound((CompoundTag) converted.getValue())); -+ } catch (IOException ex) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ex); -+ throw new RuntimeException(); -+ } -+ } - // Paper end - - /** diff --git a/patches/server-remapped/0441-Remove-streams-from-PairedQueue.patch b/patches/server-remapped/0441-Remove-streams-from-PairedQueue.patch deleted file mode 100644 index 935abedc0d..0000000000 --- a/patches/server-remapped/0441-Remove-streams-from-PairedQueue.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 18:10:43 -0700 -Subject: [PATCH] Remove streams from PairedQueue - -We shouldn't be doing stream calls just to see if the queue is -empty. This creates loads of garbage thanks to how often it's called. - -diff --git a/src/main/java/net/minecraft/util/thread/StrictQueue.java b/src/main/java/net/minecraft/util/thread/StrictQueue.java -index cdc572b0261034248960fa13b8412e874fd20db5..07938519b699a31a280f3f419b34fb7cf6cf6883 100644 ---- a/src/main/java/net/minecraft/util/thread/StrictQueue.java -+++ b/src/main/java/net/minecraft/util/thread/StrictQueue.java -@@ -20,32 +20,30 @@ public interface StrictQueue { - - public static final class FixedPriorityQueue implements StrictQueue { - -- private final List> queueList; -+ private final List> queueList; private final List> getQueues() { return this.queueList; } // Paper - OBFHELPER - - public FixedPriorityQueue(int priorityCount) { -- this.queueList = (List) IntStream.range(0, priorityCount).mapToObj((j) -> { -- return Queues.newConcurrentLinkedQueue(); -- }).collect(Collectors.toList()); -+ // Paper start - remove streams -+ this.queueList = new java.util.ArrayList<>(priorityCount); // queues -+ for (int j = 0; j < priorityCount; ++j) { -+ this.getQueues().add(Queues.newConcurrentLinkedQueue()); -+ } -+ // Paper end - remove streams - } - - @Nullable - @Override - public Runnable pop() { -- Iterator iterator = this.queueList.iterator(); -- -- Runnable runnable; -- -- do { -- if (!iterator.hasNext()) { -- return null; -+ // Paper start - remove iterator creation -+ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { -+ Queue queue = this.getQueues().get(i); -+ Runnable ret = queue.poll(); -+ if (ret != null) { -+ return ret; - } -- -- Queue queue = (Queue) iterator.next(); -- -- runnable = (Runnable) queue.poll(); -- } while (runnable == null); -- -- return runnable; -+ } -+ return null; -+ // Paper end - remove iterator creation - } - - public boolean push(StrictQueue.IntRunnable message) { -@@ -57,7 +55,16 @@ public interface StrictQueue { - - @Override - public boolean isEmpty() { -- return this.queueList.stream().allMatch(Collection::isEmpty); -+ // Paper start - remove streams -+ // why are we doing streams every time we might want to execute a task? -+ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { -+ Queue queue = this.getQueues().get(i); -+ if (!queue.isEmpty()) { -+ return false; -+ } -+ } -+ return true; -+ // Paper end - remove streams - } - } - diff --git a/patches/server-remapped/0453-Load-Chunks-for-Login-Asynchronously.patch b/patches/server-remapped/0453-Load-Chunks-for-Login-Asynchronously.patch deleted file mode 100644 index f02494b2a2..0000000000 --- a/patches/server-remapped/0453-Load-Chunks-for-Login-Asynchronously.patch +++ /dev/null @@ -1,416 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 04:28:29 -0400 -Subject: [PATCH] Load Chunks for Login Asynchronously - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index b3ca4300b280a24f3ed2acaffdd6ae2cdffd140d..97a582614ad28f9fa864ae9be4860658e5979214 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -145,7 +145,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private final ProcessorHandle> worldgenMailbox; - private final ProcessorHandle> mainThreadMailbox; - public final ChunkProgressListener progressListener; -- public final ChunkMap.ChunkDistanceManager distanceManager; -+ public final ChunkMap.ChunkDistanceManager distanceManager; public final DistanceManager getChunkDistanceManager() { return this.distanceManager; } // Paper - OBFHELPER - private final AtomicInteger tickingGenerated; - public final StructureManager structureManager; // Paper - private -> public - private final File storageFolder; -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index b45fe750c8ca838e1beebff4077e5819eec2836c..79fb63c40dd0543a6f629e78f390f23f34992ba1 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -629,7 +629,7 @@ public class ServerChunkCache extends ChunkSource { - return this.mainThreadProcessor.pollTask(); - } - -- private boolean runDistanceManagerUpdates() { -+ public boolean runDistanceManagerUpdates() { // Paper - private -> public - boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); - boolean flag1 = this.chunkMap.promoteChunkMap(); - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 75a095e0c2177dc1b46b080597ff8f12f1480acc..24c508ade61a6ad90b0ef73cdc995f531ef18263 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -32,6 +32,7 @@ import net.minecraft.core.Vec3i; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.NbtOps; - import net.minecraft.nbt.Tag; -+import net.minecraft.network.Connection; - import net.minecraft.network.chat.ChatType; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.HoverEvent; -@@ -172,6 +173,7 @@ public class ServerPlayer extends Player implements ContainerListener { - - private static final Logger LOGGER = LogManager.getLogger(); - public ServerGamePacketListenerImpl connection; -+ public Connection networkManager; // Paper - public final MinecraftServer server; - public final ServerPlayerGameMode gameMode; - public final Deque removeQueue = new ArrayDeque<>(); // Paper -@@ -238,6 +240,7 @@ public class ServerPlayer extends Player implements ContainerListener { - public boolean joining = true; - public boolean sentListPacket = false; - public boolean supressTrackerForLogin = false; // Paper -+ public boolean didPlayerJoinEvent = false; // Paper - public Integer clientViewDistance; - // CraftBukkit end - public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index d09e4857b6c40410d134fa81b48e95919a7373bd..583587457790df826a8a3239a4bd1d0f1dcab1da 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -21,6 +21,7 @@ public class TicketType { - public static final TicketType FORCED = create("forced", Comparator.comparingLong(ChunkPos::toLong)); - public static final TicketType LIGHT = create("light", Comparator.comparingLong(ChunkPos::toLong)); - public static final TicketType PORTAL = create("portal", Vec3i::compareTo, 300); -+ public static final TicketType LOGIN = create("login", Long::compareTo, 100); // Paper - public static final TicketType POST_TELEPORT = create("post_teleport", Integer::compareTo, 5); - public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); - public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 09a663cc53cdf8ae45352b280200c8170dbbcdfc..1bed6e69bf3cc1ab9b0c1259de4f643bf58371aa 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -220,6 +220,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - private static final Logger LOGGER = LogManager.getLogger(); - public final Connection connection; - private final MinecraftServer server; -+ public Runnable playerJoinReady; // Paper - public ServerPlayer player; - private int tickCount; - private long keepAliveTime = Util.getMillis(); private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER -@@ -298,6 +299,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // CraftBukkit end - - public void tick() { -+ // Paper start - login async -+ Runnable playerJoinReady = this.playerJoinReady; -+ if (playerJoinReady != null) { -+ this.playerJoinReady = null; -+ playerJoinReady.run(); -+ } -+ // Don't tick if not valid (dead), otherwise we load chunks below -+ if (this.player.valid) { -+ // Paper end - this.resetPosition(); - this.player.xo = this.player.getX(); - this.player.yo = this.player.getY(); -@@ -339,7 +349,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - this.lastVehicle = null; - this.clientVehicleIsFloating = false; - this.aboveGroundVehicleTickCount = 0; -- } -+ }} // Paper - end if (valid) - - this.server.getProfiler().push("keepAlive"); - // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 9631fa93b821c7f6bc6dc707c2c82cce2ae8291e..e229c7735ba88be3d8721440104958408a2a075e 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -86,7 +86,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - } - // Paper end - } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { -- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); -+ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper - - if (entityplayer == null) { - this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT; -@@ -186,7 +186,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - } - - this.connection.send(new ClientboundGameProfilePacket(this.gameProfile)); -- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); -+ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper - - if (entityplayer != null) { - this.state = ServerLoginPacketListenerImpl.State.DELAY_ACCEPT; -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 454d60566743e02e7e55868c7bb45e30583dfa8f..ffc8c9ee8b1768dd809189858ee45658fb9bf1c5 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -36,6 +36,7 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; - import net.minecraft.network.protocol.game.ClientboundChatPacket; - import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; -+import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; - import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; - import net.minecraft.network.protocol.game.ClientboundGameEventPacket; - import net.minecraft.network.protocol.game.ClientboundLoginPacket; -@@ -59,6 +60,8 @@ import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.PlayerAdvancements; - import net.minecraft.server.ServerScoreboard; -+import net.minecraft.server.level.ChunkHolder; -+import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.level.ServerPlayerGameMode; -@@ -124,11 +127,12 @@ public abstract class PlayerList { - private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); - private final MinecraftServer server; - public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety -- private final Map playersByUUID = Maps.newHashMap(); -+ private final Map playersByUUID = Maps.newHashMap();Map getUUIDMap() { return playersByUUID; } // Paper - OBFHELPER - private final UserBanList bans; - private final IpBanList ipBans; - private final ServerOpList ops; - private final UserWhiteList whitelist; -+ private final Map pendingPlayers = Maps.newHashMap(); // Paper - // CraftBukkit start - // private final Map o; - // private final Map p; -@@ -167,6 +171,11 @@ public abstract class PlayerList { - } - - public void placeNewPlayer(Connection connection, ServerPlayer player) { -+ ServerPlayer prev = pendingPlayers.put(player.getUUID(), player);// Paper -+ if (prev != null) { -+ disconnectPendingPlayer(prev); -+ } -+ player.networkManager = connection; // Paper - player.loginTime = System.currentTimeMillis(); // Paper - GameProfile gameprofile = player.getGameProfile(); - GameProfileCache usercache = this.server.getProfileCache(); -@@ -180,7 +189,7 @@ public abstract class PlayerList { - if (nbttagcompound != null && nbttagcompound.contains("bukkit")) { - CompoundTag bukkit = nbttagcompound.getCompound("bukkit"); - s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; -- } -+ }String lastKnownName = s; // Paper - // CraftBukkit end - - if (nbttagcompound != null) { -@@ -255,34 +264,79 @@ public abstract class PlayerList { - player.getRecipeBook().sendInitialRecipeBook(player); - this.updateEntireScoreboard(worldserver1.getScoreboard(), player); - this.server.invalidateStatus(); -+ // Paper start - async load spawn in chunk -+ ServerLevel finalWorldserver = worldserver1; -+ int chunkX = loc.getBlockX() >> 4; -+ int chunkZ = loc.getBlockZ() >> 4; -+ final ChunkPos pos = new ChunkPos(chunkX, chunkZ); -+ ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; -+ playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.toLong()); -+ worldserver1.getChunkSource().runDistanceManagerUpdates(); -+ worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { -+ ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); -+ if (updatingChunk != null) { -+ return updatingChunk.getEntityTickingFuture(); -+ } else { -+ return java.util.concurrent.CompletableFuture.completedFuture(chunk); -+ } -+ }).thenAccept(chunk -> { -+ playerconnection.playerJoinReady = () -> { -+ postChunkLoadJoin( -+ player, finalWorldserver, connection, playerconnection, -+ nbttagcompound, connection.getRemoteAddress().toString(), lastKnownName -+ ); -+ }; -+ }); -+ } -+ -+ public ServerPlayer getActivePlayer(UUID uuid) { -+ ServerPlayer player = this.getUUIDMap().get(uuid); -+ return player != null ? player : pendingPlayers.get(uuid); -+ } -+ -+ void disconnectPendingPlayer(ServerPlayer entityplayer) { -+ TranslatableComponent msg = new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0]); -+ entityplayer.networkManager.send(new ClientboundDisconnectPacket(msg), (future) -> { -+ entityplayer.networkManager.disconnect(msg); -+ entityplayer.networkManager = null; -+ }); -+ } -+ -+ private void postChunkLoadJoin(ServerPlayer entityplayer, ServerLevel worldserver1, Connection networkmanager, ServerGamePacketListenerImpl playerconnection, CompoundTag nbttagcompound, String s1, String s) { -+ pendingPlayers.remove(entityplayer.getUUID(), entityplayer); -+ if (!networkmanager.isConnected()) { -+ return; -+ } -+ entityplayer.didPlayerJoinEvent = true; -+ // Paper end - TranslatableComponent chatmessage; - -- if (player.getGameProfile().getName().equalsIgnoreCase(s)) { -- chatmessage = new TranslatableComponent("multiplayer.player.joined", new Object[]{player.getDisplayName()}); -+ if (entityplayer.getGameProfile().getName().equalsIgnoreCase(s)) { -+ chatmessage = new TranslatableComponent("multiplayer.player.joined", new Object[]{entityplayer.getDisplayName()}); - } else { -- chatmessage = new TranslatableComponent("multiplayer.player.joined.renamed", new Object[]{player.getDisplayName(), s}); -+ chatmessage = new TranslatableComponent("multiplayer.player.joined.renamed", new Object[]{entityplayer.getDisplayName(), s}); - } - // CraftBukkit start - chatmessage.withStyle(ChatFormatting.YELLOW); - Component joinMessage = chatmessage; // Paper - Adventure - -- playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.yRot, player.xRot); -- this.players.add(player); -- this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot -- this.playersByUUID.put(player.getUUID(), player); -+ playerconnection.teleport(entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), entityplayer.yRot, entityplayer.xRot); -+ this.players.add(entityplayer); -+ this.playersByName.put(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT), entityplayer); // Spigot -+ this.playersByUUID.put(entityplayer.getUUID(), entityplayer); - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below - - // Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks -- player.supressTrackerForLogin = true; -- worldserver1.addNewPlayer(player); -- this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below worldserver.addPlayerJoin(entityplayer); -- mountSavedVehicle(player, worldserver1, nbttagcompound); -+ entityplayer.supressTrackerForLogin = true; -+ worldserver1.addNewPlayer(entityplayer); -+ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); // see commented out section below worldserver.addPlayerJoin(entityplayer); -+ mountSavedVehicle(entityplayer, worldserver1, nbttagcompound); - // Paper end - // CraftBukkit start -- PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure -+ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - cserver.getPluginManager().callEvent(playerJoinEvent); - -- if (!player.connection.connection.isConnected()) { -+ if (!entityplayer.connection.connection.isConnected()) { - return; - } - -@@ -297,51 +351,51 @@ public abstract class PlayerList { - // CraftBukkit end - - // CraftBukkit start - sendAll above replaced with this loop -- ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, player); -+ ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, entityplayer); - - for (int i = 0; i < this.players.size(); ++i) { - ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i); - -- if (entityplayer1.getBukkitEntity().canSee(player.getBukkitEntity())) { -+ if (entityplayer1.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { - entityplayer1.connection.send(packet); - } - -- if (!player.getBukkitEntity().canSee(entityplayer1.getBukkitEntity())) { -+ if (!entityplayer.getBukkitEntity().canSee(entityplayer1.getBukkitEntity())) { - continue; - } - -- player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); -+ entityplayer.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); - } -- player.sentListPacket = true; -- player.supressTrackerForLogin = false; // Paper -- ((ServerLevel)player.level).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now -+ entityplayer.sentListPacket = true; -+ entityplayer.supressTrackerForLogin = false; // Paper -+ ((ServerLevel)entityplayer.level).getChunkSource().chunkMap.addEntity(entityplayer); // Paper - track entity now - // CraftBukkit end - -- player.connection.send(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn -+ entityplayer.connection.send(new ClientboundSetEntityDataPacket(entityplayer.getId(), entityplayer.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn - - // CraftBukkit start - Only add if the player wasn't moved in the event -- if (player.level == worldserver1 && !worldserver1.players().contains(player)) { -- worldserver1.addNewPlayer(player); -- this.server.getCustomBossEvents().onPlayerConnect(player); -+ if (entityplayer.level == worldserver1 && !worldserver1.players().contains(entityplayer)) { -+ worldserver1.addNewPlayer(entityplayer); -+ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); - } - -- worldserver1 = player.getLevel(); // CraftBukkit - Update in case join event changed it -+ worldserver1 = entityplayer.getLevel(); // CraftBukkit - Update in case join event changed it - // CraftBukkit end -- this.sendLevelInfo(player, worldserver1); -+ this.sendLevelInfo(entityplayer, worldserver1); - if (!this.server.getResourcePack().isEmpty()) { -- player.sendTexturePack(this.server.getResourcePack(), this.server.getResourcePackHash()); -+ entityplayer.sendTexturePack(this.server.getResourcePack(), this.server.getResourcePackHash()); - } - -- Iterator iterator = player.getActiveEffects().iterator(); -+ Iterator iterator = entityplayer.getActiveEffects().iterator(); - - while (iterator.hasNext()) { - MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); - -- playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect)); -+ playerconnection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobeffect)); - } - - // Paper start - move vehicle into method so it can be called above - short circuit around that code -- onPlayerJoinFinish(player, worldserver1, s1); -+ onPlayerJoinFinish(entityplayer, worldserver1, s1); - } - private void mountSavedVehicle(ServerPlayer entityplayer, ServerLevel worldserver1, CompoundTag nbttagcompound) { - // Paper end -@@ -492,6 +546,7 @@ public abstract class PlayerList { - - protected void save(ServerPlayer player) { - if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit -+ if (!player.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) - this.playerIo.save(player); - ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit - -@@ -519,7 +574,7 @@ public abstract class PlayerList { - } - - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); -- cserver.getPluginManager().callEvent(playerQuitEvent); -+ if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - - if (server.isSameThread()) entityplayer.doTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) -@@ -572,6 +627,13 @@ public abstract class PlayerList { - // this.p.remove(uuid); - // CraftBukkit end - } -+ // Paper start -+ entityplayer1 = pendingPlayers.get(uuid); -+ if (entityplayer1 == entityplayer) { -+ pendingPlayers.remove(uuid); -+ } -+ entityplayer.networkManager = null; -+ // Paper end - - // CraftBukkit start - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[]{entityplayer})); -@@ -589,7 +651,7 @@ public abstract class PlayerList { - cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); - // CraftBukkit end - -- return playerQuitEvent.quitMessage(); // Paper - Adventure -+ return entityplayer.didPlayerJoinEvent ? playerQuitEvent.quitMessage() : null; // CraftBukkit // Paper - Adventure // Paper - don't print quit if we never printed join - } - - // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer -@@ -608,6 +670,13 @@ public abstract class PlayerList { - list.add(entityplayer); - } - } -+ // Paper start - check pending players too -+ entityplayer = pendingPlayers.get(uuid); -+ if (entityplayer != null) { -+ this.pendingPlayers.remove(uuid); -+ disconnectPendingPlayer(entityplayer); -+ } -+ // Paper end - - Iterator iterator = list.iterator(); - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b8dcc91a191f25ca578e0858abf6c1b874fee15d..9f0371282f5829d26dc9618c3d466bccaa4cd3af 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1371,7 +1371,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.yo = y; - this.zo = d4; - this.setPos(d3, y, d4); -- level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit -+ if (valid) level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit // Paper - } - - public void moveTo(Vec3 vec3d) { diff --git a/patches/server-remapped/0464-Optimize-Voxel-Shape-Merging.patch b/patches/server-remapped/0464-Optimize-Voxel-Shape-Merging.patch deleted file mode 100644 index 935b12df1e..0000000000 --- a/patches/server-remapped/0464-Optimize-Voxel-Shape-Merging.patch +++ /dev/null @@ -1,175 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 May 2020 22:35:09 -0400 -Subject: [PATCH] Optimize Voxel Shape Merging - -This method shows up as super hot in profiler, and also a high "self" time. - -Upon analyzing, it appears most usages of this method fall down to the final -else statement of the nasty ternary. - -Upon even further analyzation, it appears then the majority of those have a -consistent list 1.... One with Infinity head and Tails. - -First optimization is to detect these infinite states and immediately return that -VoxelShapeMergerList so we can avoid testing the rest for most cases. - -Break the method into 2 to help the JVM promote inlining of this fast path. - -Then it was also noticed that VoxelShapeMergerList constructor is also a hotspot -with a high self time... - -Well, knowing that in most cases our list 1 is actualy the same value, it allows -us to know that with an infinite list1, the result on the merger is essentially -list2 as the final values. - -This let us analyze the 2 potential states (Infinite with 2 sources or 4 sources) -and compute a deterministic result for the MergerList values. - -Additionally, this lets us avoid even allocating new objects for this too, further -reducing memory usage. - -diff --git a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java -index f0e74daa5bb9e88c028225e7c71deb04c481a7ac..abbe05b07831423eccf8779e854251dec5fbc2ae 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java -@@ -6,10 +6,16 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; - - public final class IndirectMerger implements IndexMerger { - -- private final DoubleArrayList result; -+ private final DoubleList a; // Paper - private final IntArrayList firstIndices; - private final IntArrayList secondIndices; - -+ // Paper start -+ private static final IntArrayList INFINITE_B_1 = new IntArrayList(new int[]{1, 1}); -+ private static final IntArrayList INFINITE_B_0 = new IntArrayList(new int[]{0, 0}); -+ private static final IntArrayList INFINITE_C = new IntArrayList(new int[]{0, 1}); -+ // Paper end -+ - protected IndirectMerger(DoubleList first, DoubleList second, boolean includeFirstOnly, boolean includeSecondOnly) { - int i = 0; - int j = 0; -@@ -18,7 +24,23 @@ public final class IndirectMerger implements IndexMerger { - int l = second.size(); - int i1 = k + l; - -- this.result = new DoubleArrayList(i1); -+ // Paper start - optimize common path of infinity doublelist -+ int size = first.size(); -+ double tail = first.getDouble(size - 1); -+ double head = first.getDouble(0); -+ if (head == Double.NEGATIVE_INFINITY && tail == Double.POSITIVE_INFINITY && !includeFirstOnly && !includeSecondOnly && (size == 2 || size == 4)) { -+ this.a = second; -+ if (size == 2) { -+ this.firstIndices = INFINITE_B_0; -+ } else { -+ this.firstIndices = INFINITE_B_1; -+ } -+ this.secondIndices = INFINITE_C; -+ return; -+ } -+ // Paper end -+ -+ this.a = new DoubleArrayList(i1); - this.firstIndices = new IntArrayList(i1); - this.secondIndices = new IntArrayList(i1); - -@@ -27,8 +49,8 @@ public final class IndirectMerger implements IndexMerger { - boolean flag3 = j < l; - - if (!flag2 && !flag3) { -- if (this.result.isEmpty()) { -- this.result.add(Math.min(first.getDouble(k - 1), second.getDouble(l - 1))); -+ if (this.a.isEmpty()) { -+ this.a.add(Math.min(first.getDouble(k - 1), second.getDouble(l - 1))); - } - - return; -@@ -41,9 +63,9 @@ public final class IndirectMerger implements IndexMerger { - if (!(d0 >= d1 - 1.0E-7D)) { // Paper - decompile error - welcome to hell - this.firstIndices.add(i - 1); - this.secondIndices.add(j - 1); -- this.result.add(d1); -+ this.a.add(d1); - d0 = d1; -- } else if (!this.result.isEmpty()) { -+ } else if (!this.a.isEmpty()) { - this.firstIndices.set(this.firstIndices.size() - 1, i - 1); - this.secondIndices.set(this.secondIndices.size() - 1, j - 1); - } -@@ -53,7 +75,7 @@ public final class IndirectMerger implements IndexMerger { - - @Override - public boolean forMergedIndexes(IndexMerger.IndexConsumer predicate) { -- for (int i = 0; i < this.result.size() - 1; ++i) { -+ for (int i = 0; i < this.a.size() - 1; ++i) { - if (!predicate.merge(this.firstIndices.getInt(i), this.secondIndices.getInt(i), i)) { - return false; - } -@@ -64,6 +86,6 @@ public final class IndirectMerger implements IndexMerger { - - @Override - public DoubleList getList() { -- return this.result; -+ return this.a; - } - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -index c14d5ebe16a693834ed218af8f737714065b2e17..1603eb3f7d90a4b3a028b20776566db77d09c123 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -@@ -329,19 +329,46 @@ public final class Shapes { - } - - @VisibleForTesting -- protected static IndexMerger createIndexMerger(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { -- int j = first.size() - 1; -- int k = second.size() - 1; -+ private static IndexMerger createIndexMerger(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { // Paper - private -+ // Paper start - fast track the most common scenario -+ // doublelist is usually a DoubleArrayList with Infinite head/tails that falls to the final else clause -+ // This is actually the most common path, so jump to it straight away -+ if (first.getDouble(0) == Double.NEGATIVE_INFINITY && first.getDouble(first.size() - 1) == Double.POSITIVE_INFINITY) { -+ return new IndirectMerger(first, second, includeFirst, includeSecond); -+ } -+ // Split out rest to hopefully inline the above -+ return lessCommonMerge(size, first, second, includeFirst, includeSecond); -+ } -+ -+ private static IndexMerger lessCommonMerge(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { -+ int j = doublelist.size() - 1; -+ int k = doublelist1.size() - 1; -+ // Paper note - Rewrite below as optimized order if instead of nasty ternary - -- if (first instanceof CubePointRange && second instanceof CubePointRange) { -+ if (doublelist instanceof CubePointRange && doublelist1 instanceof CubePointRange) { - long l = lcm(j, k); - -- if ((long) size * l <= 256L) { -+ if ((long) i * l <= 256L) { - return new DiscreteCubeMerger(j, k); - } - } - -- return (IndexMerger) (first.getDouble(j) < second.getDouble(0) - 1.0E-7D ? new NonOverlappingMerger(first, second, false) : (second.getDouble(k) < first.getDouble(0) - 1.0E-7D ? new NonOverlappingMerger(second, first, true) : (j == k && Objects.equals(first, second) ? (first instanceof IdenticalMerger ? (IndexMerger) first : (second instanceof IdenticalMerger ? (IndexMerger) second : new IdenticalMerger(first))) : new IndirectMerger(first, second, includeFirst, includeSecond)))); -+ // Identical happens more often than Disjoint -+ if (j == k && Objects.equals(doublelist, doublelist1)) { -+ if (doublelist instanceof IdenticalMerger) { -+ return (IndexMerger) doublelist; -+ } else if (doublelist1 instanceof IdenticalMerger) { -+ return (IndexMerger) doublelist1; -+ } -+ return new IdenticalMerger(doublelist); -+ } else if (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-07) { -+ return new NonOverlappingMerger(doublelist, doublelist1, false); -+ } else if (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-07) { -+ return new NonOverlappingMerger(doublelist1, doublelist, true); -+ } else { -+ return new IndirectMerger(doublelist, doublelist1, flag, flag1); -+ } -+ // Paper end - } - - public interface DoubleLineConsumer { diff --git a/patches/server/0010-Adventure.patch b/patches/server/0010-Adventure.patch index 4f747860da..1da3dba942 100644 --- a/patches/server/0010-Adventure.patch +++ b/patches/server/0010-Adventure.patch @@ -1956,10 +1956,10 @@ index cf69a45f038c2b8336010f5fe277313fd0513b5b..a7966aa0846637efdc43df1ca97cbc5d public net.minecraft.world.item.enchantment.Enchantment getHandle() { return this.target; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 98407b26cb94088fd931c445d4ed65eae5b7ecce..408e5a68986a91183d08ce06d385867b947ac04e 100644 +index 78d1621c1b5f1870829d92720e2151e9f9d9a8b5..6722d97d498fb2951b7dd8af3b68dd771ce8f5c1 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -807,6 +807,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -808,6 +808,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return this.getHandle().getVehicle().getBukkitEntity(); } diff --git a/patches/server/0025-Entity-Origin-API.patch b/patches/server/0025-Entity-Origin-API.patch index cdae1bf4b3..1029b368c6 100644 --- a/patches/server/0025-Entity-Origin-API.patch +++ b/patches/server/0025-Entity-Origin-API.patch @@ -114,10 +114,10 @@ index 394164f50256ad9a167e15531a9202875abb6cb6..abc62c560816d945642d830a020deb28 @Nullable diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 408e5a68986a91183d08ce06d385867b947ac04e..e5549f33a472133a8ce8533b5b827560a550f7ae 100644 +index 6722d97d498fb2951b7dd8af3b68dd771ce8f5c1..417357f6a187747a5e27fa60a57cee3fb91f3d2e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1097,4 +1097,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1098,4 +1098,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return this.spigot; } // Spigot end diff --git a/patches/server/0051-Add-velocity-warnings.patch b/patches/server/0051-Add-velocity-warnings.patch index 2a5b77ca91..0039fad826 100644 --- a/patches/server/0051-Add-velocity-warnings.patch +++ b/patches/server/0051-Add-velocity-warnings.patch @@ -17,10 +17,10 @@ index 4b6e6f120edc0e2c3dd3f81c5b9fb96980e41a33..6dab7f65401d5f01e094454b392042cc static { ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index e5549f33a472133a8ce8533b5b827560a550f7ae..380cd00e55bbdc8851483a5f469e01a5ba48e955 100644 +index 417357f6a187747a5e27fa60a57cee3fb91f3d2e..808169e6d78b9e3647763239bbd05fcfba6449a6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -432,10 +432,40 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -433,10 +433,40 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { public void setVelocity(Vector velocity) { Preconditions.checkArgument(velocity != null, "velocity"); velocity.checkFinite(); diff --git a/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch index 84141dee36..b2f4bbed01 100644 --- a/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch +++ b/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch @@ -20,10 +20,10 @@ index 52d80086deff664fcfd8952b7cabbfa1f48ad131..a86b5272c0ac4dd64f796f7fd025c7a3 private boolean tickingBlockEntities; public final Thread thread; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 26f89f747eba69caaee3cbca71a1d48f2378b4cc..c9f11030ff928d3dca5cfbe48af057eb0480f898 100644 +index 1de08dd42366c9988fdcde265b92823e25e48b99..7b1f853913a3d858718a6067b3927946c7e50114 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -271,6 +271,57 @@ public class CraftWorld implements World { +@@ -272,6 +272,57 @@ public class CraftWorld implements World { private int waterAmbientSpawn = -1; private int ambientSpawn = -1; diff --git a/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch index 443029cb4a..26eef0feb7 100644 --- a/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch +++ b/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch @@ -314,10 +314,10 @@ index 11ed01b3ebe4c71e3d3c767887a5dca6033fdf3c..52b2b27f8f8b542a930d649ed6904b4b @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index c9f11030ff928d3dca5cfbe48af057eb0480f898..9925d1f68c35a29156a152a8cc4b653ba280374b 100644 +index 7b1f853913a3d858718a6067b3927946c7e50114..efff3e9590e3fd66d9ab56173c986f5b51bbe559 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1837,7 +1837,7 @@ public class CraftWorld implements World { +@@ -1838,7 +1838,7 @@ public class CraftWorld implements World { } else if (TNTPrimed.class.isAssignableFrom(clazz)) { entity = new PrimedTnt(this.world, x, y, z, null); } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { diff --git a/patches/server/0147-Entity-fromMobSpawner.patch b/patches/server/0147-Entity-fromMobSpawner.patch index 34ebf1b310..c8b928e2bd 100644 --- a/patches/server/0147-Entity-fromMobSpawner.patch +++ b/patches/server/0147-Entity-fromMobSpawner.patch @@ -49,10 +49,10 @@ index 037dafb59e54047d1d54474c44897d35b8f46c98..e310c1eb1108780bcff4d7ba9d49cefa if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { Entity vehicle = entity.getVehicle(); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 380cd00e55bbdc8851483a5f469e01a5ba48e955..af8552f21f598f99151e59fe44df40f13caa3ead 100644 +index 808169e6d78b9e3647763239bbd05fcfba6449a6..a2a7b6a62ea1292fce37581863bee931d1497223 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1134,5 +1134,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1135,5 +1135,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { Location origin = getHandle().origin; return origin == null ? null : origin.clone(); } diff --git a/patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch b/patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch index c5483d657a..0ad07b41da 100644 --- a/patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch +++ b/patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch @@ -58,10 +58,10 @@ index 77645019c88d61dde28b7598d8a29b7d0c23c209..8a079ee3ed243fd19b1dd7eed2de1dd3 return null; } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 6128eb5a793365822d9b00a86629ad4d86c61da9..ca03ed4b1581df2b7db272d6f330174a9d277153 100644 +index 923948e7fc63a778ca126c99e1189357bb490dee..bf12cb6a1f991372206e462e46f2686decff11a6 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -313,7 +313,21 @@ public class CraftBlock implements Block { +@@ -316,7 +316,21 @@ public class CraftBlock implements Block { @Override public BlockState getState() { diff --git a/patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch index 719bc3db58..c403b862a0 100644 --- a/patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch +++ b/patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch @@ -34,10 +34,10 @@ index 18ab943ea2a959f012c3f75957fcb05dbe4ee6ff..c7ac5b323c731e5a7929f87d59e62796 if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 9925d1f68c35a29156a152a8cc4b653ba280374b..fbc82598a2f7ea439bb371ecf074b486ae09c355 100644 +index efff3e9590e3fd66d9ab56173c986f5b51bbe559..8574cca2582d5eaf3720df1c42fda38957d18230 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2357,11 +2357,17 @@ public class CraftWorld implements World { +@@ -2358,11 +2358,17 @@ public class CraftWorld implements World { @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/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch index 5f114f6efd..110d6d75ee 100644 --- a/patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch +++ b/patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch @@ -8,10 +8,10 @@ This API has more capabilities than .dropItem with the Consumer function Item can be set inside of the Consumer pre spawn function. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index fbc82598a2f7ea439bb371ecf074b486ae09c355..e744a793062acce339c4914eb2eff2a8c2ff6f1b 100644 +index 8574cca2582d5eaf3720df1c42fda38957d18230..082ca9db7e925dfb36998135bea7be298a691b86 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1506,6 +1506,10 @@ public class CraftWorld implements World { +@@ -1507,6 +1507,10 @@ public class CraftWorld implements World { if (Boat.class.isAssignableFrom(clazz)) { entity = new net.minecraft.world.entity.vehicle.Boat(this.world, x, y, z); entity.moveTo(x, y, z, yaw, pitch); diff --git a/patches/server/0206-Fix-CraftEntity-hashCode.patch b/patches/server/0206-Fix-CraftEntity-hashCode.patch index 9c66bc30b3..b260b94401 100644 --- a/patches/server/0206-Fix-CraftEntity-hashCode.patch +++ b/patches/server/0206-Fix-CraftEntity-hashCode.patch @@ -21,10 +21,10 @@ check is essentially the same as this.getHandle() == other.getHandle() However, replaced it too to make it clearer of intent. diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index af8552f21f598f99151e59fe44df40f13caa3ead..b9089ba658d38397cf07245e31e6d40b3a2a5f2b 100644 +index a2a7b6a62ea1292fce37581863bee931d1497223..e57fef24ee5159142ec4f05a9e76a34c6e153386 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -783,14 +783,15 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -784,14 +784,15 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return false; } final CraftEntity other = (CraftEntity) obj; diff --git a/patches/server/0213-Expand-Explosions-API.patch b/patches/server/0213-Expand-Explosions-API.patch index 211ac6f053..b9c8b6499f 100644 --- a/patches/server/0213-Expand-Explosions-API.patch +++ b/patches/server/0213-Expand-Explosions-API.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Expand Explosions API Add Entity as a Source capability, and add more API choices, and on Location. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index e744a793062acce339c4914eb2eff2a8c2ff6f1b..c3a57510cd17203c65c15de0544d5656eb7a0b7b 100644 +index 082ca9db7e925dfb36998135bea7be298a691b86..20269c9084dd2a4f941e98e25c40bd3f3af43bcc 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -890,6 +890,12 @@ public class CraftWorld implements World { +@@ -891,6 +891,12 @@ public class CraftWorld implements World { public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) { return !this.world.explode(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; } diff --git a/patches/server/0215-RangedEntity-API.patch b/patches/server/0215-RangedEntity-API.patch index 96a8f6424a..1cfaceeec1 100644 --- a/patches/server/0215-RangedEntity-API.patch +++ b/patches/server/0215-RangedEntity-API.patch @@ -111,17 +111,17 @@ index 06786fba1fef36e8fc3d0f5650160123f728a6d1..beea227855f0b978e655efc298024120 public CraftPillager(CraftServer server, net.minecraft.world.entity.monster.Pillager entity) { super(server, entity); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -index 4cd3dfd3466f384aab06dacd388e8053b045b046..b2d3244cca4d9d108159f3537d8a9aace3f8e77f 100644 +index 7a73ada3d8b8085591308275ece4a9ce617314d3..3b19cd5a232f38d373359072925be12f6c075d4a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -@@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; +@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; import org.bukkit.entity.Skeleton; - import org.bukkit.entity.Skeleton.SkeletonType; --public class CraftSkeleton extends CraftMonster implements Skeleton { -+public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper +-public class CraftSkeleton extends CraftAbstractSkeleton implements Skeleton { ++public class CraftSkeleton extends CraftAbstractSkeleton implements Skeleton, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftSkeleton(CraftServer server, AbstractSkeleton entity) { + public CraftSkeleton(CraftServer server, net.minecraft.world.entity.monster.Skeleton entity) { super(server, entity); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java index 6a82d567d96a42bfea0e38afb4e8de13eb3ad5a2..659e2959c5330e4764ea1edc7f8de9f464f9ff52 100644 diff --git a/patches/server/0217-Implement-World.getEntity-UUID-API.patch b/patches/server/0217-Implement-World.getEntity-UUID-API.patch index db3675e02f..0e8d1dd597 100644 --- a/patches/server/0217-Implement-World.getEntity-UUID-API.patch +++ b/patches/server/0217-Implement-World.getEntity-UUID-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Implement World.getEntity(UUID) API diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index c3a57510cd17203c65c15de0544d5656eb7a0b7b..e819031a4176a54a06c5a09ee29eda4db4f6cc08 100644 +index 20269c9084dd2a4f941e98e25c40bd3f3af43bcc..951445d5dba92ada70ce239098c702dd7b8ce0f1 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1296,6 +1296,15 @@ public class CraftWorld implements World { +@@ -1297,6 +1297,15 @@ public class CraftWorld implements World { return list; } diff --git a/patches/server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/patches/server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch index a54b182f75..d3469898d1 100644 --- a/patches/server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch +++ b/patches/server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Make CraftWorld#loadChunk(int, int, false) load unconverted diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index e819031a4176a54a06c5a09ee29eda4db4f6cc08..43e47c345a0d2e00f13f0112d26d93b004009ac9 100644 +index 951445d5dba92ada70ce239098c702dd7b8ce0f1..ad9a4d4a9363741cc47f142c24fa6f4858dd947f 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -506,7 +506,7 @@ public class CraftWorld implements World { +@@ -507,7 +507,7 @@ public class CraftWorld implements World { @Override public boolean loadChunk(int x, int z, boolean generate) { org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot diff --git a/patches/server/0257-Asynchronous-chunk-IO-and-loading.patch b/patches/server/0257-Asynchronous-chunk-IO-and-loading.patch index dda7a3dcd0..ea7e8e8faa 100644 --- a/patches/server/0257-Asynchronous-chunk-IO-and-loading.patch +++ b/patches/server/0257-Asynchronous-chunk-IO-and-loading.patch @@ -3678,10 +3678,10 @@ index 844d65612d9c4c19d02a2b0a5b90cd44de9f17c9..cfd4c38ca99b183f23716f82c972c14b + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 43e47c345a0d2e00f13f0112d26d93b004009ac9..b8565aa86b478adb6fca6d433637ddb342ce6dcb 100644 +index ad9a4d4a9363741cc47f142c24fa6f4858dd947f..a19de8405de8ee29afc112556e4684b042c6f4ab 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2424,6 +2424,34 @@ public class CraftWorld implements World { +@@ -2425,6 +2425,34 @@ public class CraftWorld implements World { public DragonBattle getEnderDragonBattle() { return (this.getHandle().dragonFight() == null) ? null : new CraftDragonBattle(this.getHandle().dragonFight()); } @@ -3717,7 +3717,7 @@ index 43e47c345a0d2e00f13f0112d26d93b004009ac9..b8565aa86b478adb6fca6d433637ddb3 // Spigot start @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index b9089ba658d38397cf07245e31e6d40b3a2a5f2b..c381ea321b0fb3498e3f101ee059ac7d42aa029a 100644 +index e57fef24ee5159142ec4f05a9e76a34c6e153386..d0774636b151e8dbd778f2e2f2e3de154ff18494 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -13,6 +13,7 @@ import net.minecraft.nbt.CompoundTag; @@ -3728,7 +3728,7 @@ index b9089ba658d38397cf07245e31e6d40b3a2a5f2b..c381ea321b0fb3498e3f101ee059ac7d import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.AreaEffectCloud; import net.minecraft.world.entity.Entity; -@@ -515,6 +516,28 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -516,6 +517,28 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { this.entity.setYHeadRot(yaw); } diff --git a/patches/server/0272-Add-sun-related-API.patch b/patches/server/0272-Add-sun-related-API.patch index f3352dd107..52e76a976f 100644 --- a/patches/server/0272-Add-sun-related-API.patch +++ b/patches/server/0272-Add-sun-related-API.patch @@ -18,10 +18,10 @@ index 8451baff82cb7ec7615ab50a409724897ccf4d95..32e8ae0d2a0f78af671a632c4d1be58a float f = this.getBrightness(); BlockPos blockposition = new BlockPos(this.getX(), this.getEyeY(), this.getZ()); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index b8565aa86b478adb6fca6d433637ddb342ce6dcb..fda8858375a08e0aac15ca00751df5a34ed6a0f2 100644 +index a19de8405de8ee29afc112556e4684b042c6f4ab..be4c05259f176e9ef5c25db2b1745df5ea4d5789 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -866,6 +866,13 @@ public class CraftWorld implements World { +@@ -867,6 +867,13 @@ public class CraftWorld implements World { } } diff --git a/patches/server/0312-Entity-getEntitySpawnReason.patch b/patches/server/0312-Entity-getEntitySpawnReason.patch index 90d47b684f..fbcb73d40c 100644 --- a/patches/server/0312-Entity-getEntitySpawnReason.patch +++ b/patches/server/0312-Entity-getEntitySpawnReason.patch @@ -105,10 +105,10 @@ index 12a78685848b7fd945a472902d8200ea1d50b9ec..3aadcb472ab808ee981065ddfa86be6c // Spigot Start if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index c381ea321b0fb3498e3f101ee059ac7d42aa029a..33bc56eba4229d844e3af6ff4662d96450e929af 100644 +index d0774636b151e8dbd778f2e2f2e3de154ff18494..98d3818d38f487fc7e1302ee4af9e4898efec809 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1163,5 +1163,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1164,5 +1164,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { public boolean fromMobSpawner() { return getHandle().spawnedViaMobSpawner; } diff --git a/patches/server/0320-Add-Heightmap-API.patch b/patches/server/0320-Add-Heightmap-API.patch index 4c7380555f..59f0009d95 100644 --- a/patches/server/0320-Add-Heightmap-API.patch +++ b/patches/server/0320-Add-Heightmap-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add Heightmap API diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index fda8858375a08e0aac15ca00751df5a34ed6a0f2..5f93589106bcf29eabd4544951fa3ad36e00c5a6 100644 +index be4c05259f176e9ef5c25db2b1745df5ea4d5789..ea587597bfb205531c03eb0c0c9bde31ea6ab53b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -341,6 +341,29 @@ public class CraftWorld implements World { +@@ -342,6 +342,29 @@ public class CraftWorld implements World { return this.getHighestBlockYAt(x, z, org.bukkit.HeightMap.MOTION_BLOCKING); } diff --git a/patches/server/0325-improve-CraftWorld-isChunkLoaded.patch b/patches/server/0325-improve-CraftWorld-isChunkLoaded.patch index cb95e90f06..4eb97bfd19 100644 --- a/patches/server/0325-improve-CraftWorld-isChunkLoaded.patch +++ b/patches/server/0325-improve-CraftWorld-isChunkLoaded.patch @@ -9,10 +9,10 @@ waiting for the execution queue to get to our request; We can just query the chunk status and get a response now, vs having to wait diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 5f93589106bcf29eabd4544951fa3ad36e00c5a6..a7eb8f69b49bb0229de9e5a4400a4424555ac1dd 100644 +index ea587597bfb205531c03eb0c0c9bde31ea6ab53b..a112daf93daeab6d34416bc7c8a69acfc207c98b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -412,13 +412,13 @@ public class CraftWorld implements World { +@@ -413,13 +413,13 @@ public class CraftWorld implements World { @Override public boolean isChunkLoaded(int x, int z) { diff --git a/patches/server/0326-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server/0326-Configurable-Keep-Spawn-Loaded-range-per-world.patch index 9d6f848e88..82b32a8df4 100644 --- a/patches/server/0326-Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ b/patches/server/0326-Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -225,10 +225,10 @@ index 4185e6bcf9b2bb65b2a0fa5fcbeb5684615169a7..dbc29442f2b2ad3ea451910f4944e901 this.maxCount = i * i; } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index a7eb8f69b49bb0229de9e5a4400a4424555ac1dd..30305736b7dc023ad5eb3a177914560b3fec64ee 100644 +index a112daf93daeab6d34416bc7c8a69acfc207c98b..98b2d054b6436e3fdb8fadd03369a65cf4156843 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1974,15 +1974,21 @@ public class CraftWorld implements World { +@@ -1975,15 +1975,21 @@ public class CraftWorld implements World { @Override public void setKeepSpawnInMemory(boolean keepLoaded) { diff --git a/patches/server/0328-Implement-CraftBlockSoundGroup.patch b/patches/server/0328-Implement-CraftBlockSoundGroup.patch index 76559b8fc1..6cb5b06325 100644 --- a/patches/server/0328-Implement-CraftBlockSoundGroup.patch +++ b/patches/server/0328-Implement-CraftBlockSoundGroup.patch @@ -49,14 +49,13 @@ index 0000000000000000000000000000000000000000..9a516520d975f52169e346adc4ec6d9d + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index ca03ed4b1581df2b7db272d6f330174a9d277153..0a9ed9992a2fc97472a06591a5d129a767ce21af 100644 +index bf12cb6a1f991372206e462e46f2686decff11a6..75dd8cbadae9a2d18931dd49f49f8f1e14b50da5 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -749,4 +749,11 @@ public class CraftBlock implements Block { - AABB aabb = shape.bounds(); - return new BoundingBox(this.getX() + aabb.minX, this.getY() + aabb.minY, this.getZ() + aabb.minZ, this.getX() + aabb.maxX, this.getY() + aabb.maxY, this.getZ() + aabb.maxZ); +@@ -764,4 +764,10 @@ public class CraftBlock implements Block { + VoxelShape shape = this.getNMS().getCollisionShape(world, position); + return new CraftVoxelShape(shape); } -+ + // Paper start + @Override + public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { diff --git a/patches/server/0330-Fix-World-isChunkGenerated-calls.patch b/patches/server/0330-Fix-World-isChunkGenerated-calls.patch index 953566fa39..8cfc74e92c 100644 --- a/patches/server/0330-Fix-World-isChunkGenerated-calls.patch +++ b/patches/server/0330-Fix-World-isChunkGenerated-calls.patch @@ -272,7 +272,7 @@ index 211ab6cffe78c61fcff12ef7ffba904c4cae57b2..1bee455235ece8aa299a2baeede027d2 } + diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 30305736b7dc023ad5eb3a177914560b3fec64ee..4841591539fdd5a01f9ded0ee510991602c266a4 100644 +index 98b2d054b6436e3fdb8fadd03369a65cf4156843..f9c58de7fa8b3c2ab5ac78cf0b366df69e0b40df 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -20,6 +20,7 @@ import java.util.Objects; @@ -283,7 +283,7 @@ index 30305736b7dc023ad5eb3a177914560b3fec64ee..4841591539fdd5a01f9ded0ee5109916 import java.util.function.Predicate; import java.util.stream.Collectors; import net.minecraft.core.BlockPos; -@@ -417,8 +418,22 @@ public class CraftWorld implements World { +@@ -418,8 +419,22 @@ public class CraftWorld implements World { @Override public boolean isChunkGenerated(int x, int z) { @@ -307,7 +307,7 @@ index 30305736b7dc023ad5eb3a177914560b3fec64ee..4841591539fdd5a01f9ded0ee5109916 } catch (IOException ex) { throw new RuntimeException(ex); } -@@ -529,20 +544,48 @@ public class CraftWorld implements World { +@@ -530,20 +545,48 @@ public class CraftWorld implements World { @Override public boolean loadChunk(int x, int z, boolean generate) { org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot diff --git a/patches/server/0340-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/patches/server/0340-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch index 8a4a109b18..019515ccee 100644 --- a/patches/server/0340-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch +++ b/patches/server/0340-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix spawning of hanging entities that are not ItemFrames and diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 4841591539fdd5a01f9ded0ee510991602c266a4..f1cbcdb1e409f8544125dde5f24bff5b07cb5082 100644 +index f9c58de7fa8b3c2ab5ac78cf0b366df69e0b40df..053878ce00b77367b403a8c52f0d81f485022c59 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1881,7 +1881,12 @@ public class CraftWorld implements World { +@@ -1882,7 +1882,12 @@ public class CraftWorld implements World { height = 9; } diff --git a/patches/server/0357-Add-effect-to-block-break-naturally.patch b/patches/server/0357-Add-effect-to-block-break-naturally.patch index f0c758d801..1f77985ef9 100644 --- a/patches/server/0357-Add-effect-to-block-break-naturally.patch +++ b/patches/server/0357-Add-effect-to-block-break-naturally.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add effect to block break naturally diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 0a9ed9992a2fc97472a06591a5d129a767ce21af..ca95a6b1b156b37f839c6479733e5184691af66c 100644 +index 75dd8cbadae9a2d18931dd49f49f8f1e14b50da5..64c304cab8c7c4c9c29f73465f99c11f224a72bd 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -632,6 +632,13 @@ public class CraftBlock implements Block { +@@ -635,6 +635,13 @@ public class CraftBlock implements Block { @Override public boolean breakNaturally(ItemStack item) { @@ -22,7 +22,7 @@ index 0a9ed9992a2fc97472a06591a5d129a767ce21af..ca95a6b1b156b37f839c6479733e5184 // Order matters here, need to drop before setting to air so skulls can get their data net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS(); net.minecraft.world.level.block.Block block = iblockdata.getBlock(); -@@ -641,6 +648,7 @@ public class CraftBlock implements Block { +@@ -644,6 +651,7 @@ public class CraftBlock implements Block { // Modelled off EntityHuman#hasBlock if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) { net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), position, this.world.getBlockEntity(position), null, nmsItem); diff --git a/patches/server/0361-No-Tick-view-distance-implementation.patch b/patches/server/0361-No-Tick-view-distance-implementation.patch index 6fdb3036eb..3087bd1eca 100644 --- a/patches/server/0361-No-Tick-view-distance-implementation.patch +++ b/patches/server/0361-No-Tick-view-distance-implementation.patch @@ -651,10 +651,10 @@ index 521f199e495f3bec232cc9ca36e51e0392afe737..922026da8c234427e0322443004d3c32 this.postProcessing[i].clear(); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index f1cbcdb1e409f8544125dde5f24bff5b07cb5082..1d22119b962840dff789a0619fd2188958f924d0 100644 +index 053878ce00b77367b403a8c52f0d81f485022c59..b6134895d1b04d3ea7340e77f70efa23cff8b568 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2540,10 +2540,39 @@ public class CraftWorld implements World { +@@ -2541,10 +2541,39 @@ public class CraftWorld implements World { // Spigot start @Override public int getViewDistance() { diff --git a/patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch index 71138d1089..8118c956ed 100644 --- a/patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch +++ b/patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch @@ -246,10 +246,10 @@ index 382a68c76e8946840de62f05483870689de80278..8523fbd66ed42cd5b959d57cab515fa4 if (optional.isPresent()) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 1d22119b962840dff789a0619fd2188958f924d0..1023a0d5d1699b28d380e017b386a9b3986f1250 100644 +index b6134895d1b04d3ea7340e77f70efa23cff8b568..72c9ad9f75c20d6c1a6d54e2913e2f9918c11ffd 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -286,6 +286,7 @@ public class CraftWorld implements World { +@@ -287,6 +287,7 @@ public class CraftWorld implements World { @Override public int getTileEntityCount() { @@ -257,7 +257,7 @@ index 1d22119b962840dff789a0619fd2188958f924d0..1023a0d5d1699b28d380e017b386a9b3 // We don't use the full world tile entity list, so we must iterate chunks Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; int size = 0; -@@ -297,6 +298,7 @@ public class CraftWorld implements World { +@@ -298,6 +299,7 @@ public class CraftWorld implements World { size += chunk.blockEntities.size(); } return size; @@ -265,7 +265,7 @@ index 1d22119b962840dff789a0619fd2188958f924d0..1023a0d5d1699b28d380e017b386a9b3 } @Override -@@ -306,6 +308,7 @@ public class CraftWorld implements World { +@@ -307,6 +309,7 @@ public class CraftWorld implements World { @Override public int getChunkCount() { @@ -273,7 +273,7 @@ index 1d22119b962840dff789a0619fd2188958f924d0..1023a0d5d1699b28d380e017b386a9b3 int ret = 0; for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { -@@ -314,7 +317,7 @@ public class CraftWorld implements World { +@@ -315,7 +318,7 @@ public class CraftWorld implements World { } } @@ -282,7 +282,7 @@ index 1d22119b962840dff789a0619fd2188958f924d0..1023a0d5d1699b28d380e017b386a9b3 } @Override -@@ -441,6 +444,14 @@ public class CraftWorld implements World { +@@ -442,6 +445,14 @@ public class CraftWorld implements World { @Override public Chunk[] getLoadedChunks() { diff --git a/patches/server-remapped/0432-Add-tick-times-API-and-mspt-command.patch b/patches/server/0389-Add-tick-times-API-and-mspt-command.patch similarity index 89% rename from patches/server-remapped/0432-Add-tick-times-API-and-mspt-command.patch rename to patches/server/0389-Add-tick-times-API-and-mspt-command.patch index 0f2cf4005e..81685ed79c 100644 --- a/patches/server-remapped/0432-Add-tick-times-API-and-mspt-command.patch +++ b/patches/server/0389-Add-tick-times-API-and-mspt-command.patch @@ -87,13 +87,13 @@ index ddbc8cb712c50038922eded75dd6ca85fe851078..78271b400c79578d043b20a5389a37b1 version = getInt("config-version", 20); set("config-version", 20); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 087f31ac0cc7816b1cbeffc45be6927b174dee62..99ee9de92264381a064066bc22bb66b4b2852a2e 100644 +index fa3a9d763f7072c68b126ce95fee191aab576e43..91ae80ee1020dc017faef7c8be8487132c547fe4 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -217,6 +217,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Thu, 30 Apr 2020 16:56:54 +0200 +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 ad8d6a84e1a66e03ae15269e36bc787148f12396..88d5c7a0d7de2e896433d85fbd5425351f51b64d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -378,6 +378,46 @@ public final class CraftMagicNumbers implements UnsafeValues { + public boolean isSupportedApiVersion(String apiVersion) { + return apiVersion != null && SUPPORTED_API.contains(apiVersion); + } ++ ++ @Override ++ public byte[] serializeItem(ItemStack item) { ++ Preconditions.checkNotNull(item, "null cannot be serialized"); ++ Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized"); ++ ++ java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); ++ CompoundTag compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).getHandle() : CraftItemStack.asNMSCopy(item)).save(new CompoundTag()); ++ compound.putInt("DataVersion", getDataVersion()); ++ try { ++ net.minecraft.nbt.NbtIo.writeCompressed( ++ compound, ++ outputStream ++ ); ++ } catch (IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ return outputStream.toByteArray(); ++ } ++ ++ @Override ++ public ItemStack deserializeItem(byte[] data) { ++ Preconditions.checkNotNull(data, "null cannot be deserialized"); ++ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing"); ++ ++ try { ++ CompoundTag compound = net.minecraft.nbt.NbtIo.readCompressed( ++ new java.io.ByteArrayInputStream(data) ++ ); ++ int dataVersion = compound.getInt("DataVersion"); ++ ++ Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); ++ Dynamic converted = DataFixers.getDataFixer().update(References.ITEM_STACK, new Dynamic(NbtOps.INSTANCE, compound), dataVersion, getDataVersion()); ++ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of((CompoundTag) converted.getValue())); ++ } catch (IOException ex) { ++ com.destroystokyo.paper.util.SneakyThrow.sneaky(ex); ++ throw new RuntimeException(); ++ } ++ } + // Paper end + + /** diff --git a/patches/server-remapped/0435-Remove-streams-from-Mob-AI-System.patch b/patches/server/0392-Remove-streams-from-Mob-AI-System.patch similarity index 58% rename from patches/server-remapped/0435-Remove-streams-from-Mob-AI-System.patch rename to patches/server/0392-Remove-streams-from-Mob-AI-System.patch index 019eef698e..12d3a671c6 100644 --- a/patches/server-remapped/0435-Remove-streams-from-Mob-AI-System.patch +++ b/patches/server/0392-Remove-streams-from-Mob-AI-System.patch @@ -10,25 +10,21 @@ Also optimise the stream.anyMatch statement to move to a bitset where we can replace the call with a single bitwise operation. diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -index 558dd72c47930f6993952467f83b5a54ead95d92..acc6306d659cd65a043d12cd42dcbaf55aaf5250 100644 +index d92ddc8a4c0f5249b7ff4f97af1ea3db413b2983..8c2ec30a35e86f2b30863045b586a67e485c624b 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -@@ -1,10 +1,12 @@ - package net.minecraft.world.entity.ai.goal; - -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector +@@ -3,7 +3,8 @@ package net.minecraft.world.entity.ai.goal; import java.util.EnumSet; public abstract class Goal { - - private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); + private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. -+ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector ++ private final com.destroystokyo.paper.util.set.OptimizedSmallEnumSet goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector - public Goal() {} + public abstract boolean canUse(); -@@ -28,16 +30,20 @@ public abstract class Goal { - public void tick() {} +@@ -25,8 +26,10 @@ public abstract class Goal { + } public void setFlags(EnumSet controls) { - this.flags.clear(); @@ -39,7 +35,8 @@ index 558dd72c47930f6993952467f83b5a54ead95d92..acc6306d659cd65a043d12cd42dcbaf5 + // Paper end - remove streams from pathfindergoalselector } - public String toString() { + @Override +@@ -34,8 +37,10 @@ public abstract class Goal { return this.getClass().getSimpleName(); } @@ -53,42 +50,35 @@ index 558dd72c47930f6993952467f83b5a54ead95d92..acc6306d659cd65a043d12cd42dcbaf5 public static enum Flag { diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -index 9bd2ee05a0de6678ad8933a8ffbe0ae66bd073b4..5da2d780c17522e07c733a5e23b17ec760c7b342 100644 +index f29ace7b6a27a602102d37d43a6dd0571f218dfe..bcb2c5480872eef6f21746003380f71b8d44f5c8 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -@@ -1,8 +1,10 @@ - package net.minecraft.world.entity.ai.goal; - -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector - import com.google.common.collect.Sets; - import java.util.EnumMap; - import java.util.EnumSet; -+import java.util.Iterator; // Paper - remove streams from pathfindergoalselector - import java.util.Map; - import java.util.Set; - import java.util.function.Supplier; -@@ -28,7 +30,8 @@ public class GoalSelector { - private final Map lockedFlags = new EnumMap(Goal.Flag.class); - private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER +@@ -28,10 +28,12 @@ public class GoalSelector { + private final Map lockedFlags = new EnumMap<>(Goal.Flag.class); + private final Set availableGoals = Sets.newLinkedHashSet(); private final Supplier profiler; - private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); + private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. -+ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector - private int newGoalRate = 3;private int getTickRate() { return newGoalRate; } // Paper - OBFHELPER - private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO ++ private final com.destroystokyo.paper.util.set.OptimizedSmallEnumSet goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector + private int tickCount; + private int newGoalRate = 3; + private int curRate; ++ private static final Goal.Flag[] PATHFINDER_GOAL_TYPES = Goal.Flag.values(); // Paper - remove streams from pathfindergoalselector -@@ -56,35 +59,38 @@ public class GoalSelector { + public GoalSelector(Supplier profiler) { + this.profiler = profiler; +@@ -61,47 +63,95 @@ public class GoalSelector { + } // Paper end - public void removeGoal(Goal goal) { -- this.availableGoals.stream().filter((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.getGoal() == goal; +- this.availableGoals.stream().filter((wrappedGoal) -> { +- return wrappedGoal.getGoal() == goal; - }).filter(WrappedGoal::isRunning).forEach(WrappedGoal::stop); -- this.availableGoals.removeIf((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.getGoal() == goal; +- this.availableGoals.removeIf((wrappedGoal) -> { +- return wrappedGoal.getGoal() == goal; - }); + // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ for (java.util.Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { + WrappedGoal goalWrapped = iterator.next(); + if (goalWrapped.getGoal() != goal) { + continue; @@ -101,76 +91,57 @@ index 9bd2ee05a0de6678ad8933a8ffbe0ae66bd073b4..5da2d780c17522e07c733a5e23b17ec7 + // Paper end - remove streams from pathfindergoalselector } -+ private static final Goal.Flag[] PATHFINDER_GOAL_TYPES = Goal.Flag.values(); // Paper - remove streams from pathfindergoalselector -+ public void tick() { - ProfilerFiller gameprofilerfiller = (ProfilerFiller) this.profiler.get(); - - gameprofilerfiller.push("goalCleanup"); -- this.getRunningGoals().filter((pathfindergoalwrapped) -> { -- boolean flag; -- -- if (pathfindergoalwrapped.isRunning()) { -- Stream stream = pathfindergoalwrapped.getFlags().stream(); -- EnumSet enumset = this.disabledFlags; -- -- this.disabledFlags.getClass(); -- if (!stream.anyMatch(enumset::contains) && pathfindergoalwrapped.canContinueToUse()) { -- flag = false; -- return flag; -- } -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { -+ WrappedGoal wrappedGoal = iterator.next(); -+ if (!wrappedGoal.isRunning()) { -+ continue; - } -- -- flag = true; -- return flag; + ProfilerFiller profilerFiller = this.profiler.get(); + profilerFiller.push("goalCleanup"); +- this.getRunningGoals().filter((wrappedGoal) -> { +- return !wrappedGoal.isRunning() || wrappedGoal.getFlags().stream().anyMatch(this.disabledFlags::contains) || !wrappedGoal.canContinueToUse(); - }).forEach(Goal::stop); +- this.lockedFlags.forEach((flag, wrappedGoal) -> { ++ // Paper start - remove streams from pathfindergoalselector ++ for (java.util.Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal wrappedGoal = iterator.next(); + if (!wrappedGoal.isRunning()) { +- this.lockedFlags.remove(flag); ++ continue; ++ } + if (!this.goalTypes.hasCommonElements(wrappedGoal.getGoalTypes()) && wrappedGoal.canContinueToUse()) { + continue; + } + wrappedGoal.stop(); + } + // Paper end - remove streams from pathfindergoalselector - this.lockedFlags.forEach((pathfindergoal_type, pathfindergoalwrapped) -> { - if (!pathfindergoalwrapped.isRunning()) { - this.lockedFlags.remove(pathfindergoal_type); -@@ -93,30 +99,58 @@ public class GoalSelector { ++ this.lockedFlags.forEach((pathfindergoal_type, pathfindergoalwrapped) -> { ++ if (!pathfindergoalwrapped.isRunning()) { ++ this.lockedFlags.remove(pathfindergoal_type); + } + }); - gameprofilerfiller.pop(); - gameprofilerfiller.push("goalUpdate"); -- this.availableGoals.stream().filter((pathfindergoalwrapped) -> { -- return !pathfindergoalwrapped.isRunning(); -- }).filter((pathfindergoalwrapped) -> { -- Stream stream = pathfindergoalwrapped.getFlags().stream(); -- EnumSet enumset = this.disabledFlags; -- -- this.disabledFlags.getClass(); -- return stream.noneMatch(enumset::contains); -- }).filter((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.getFlags().stream().allMatch((pathfindergoal_type) -> { -- return ((WrappedGoal) this.lockedFlags.getOrDefault(pathfindergoal_type, GoalSelector.NO_GOAL)).canBeReplacedBy(pathfindergoalwrapped); + profilerFiller.pop(); + profilerFiller.push("goalUpdate"); +- this.availableGoals.stream().filter((wrappedGoal) -> { +- return !wrappedGoal.isRunning(); +- }).filter((wrappedGoal) -> { +- return wrappedGoal.getFlags().stream().noneMatch(this.disabledFlags::contains); +- }).filter((wrappedGoal) -> { +- return wrappedGoal.getFlags().stream().allMatch((flag) -> { +- return this.lockedFlags.getOrDefault(flag, NO_GOAL).canBeReplacedBy(wrappedGoal); - }); -- }).filter(WrappedGoal::canUse).forEach((pathfindergoalwrapped) -> { -- pathfindergoalwrapped.getFlags().forEach((pathfindergoal_type) -> { -- WrappedGoal pathfindergoalwrapped1 = (WrappedGoal) this.lockedFlags.getOrDefault(pathfindergoal_type, GoalSelector.NO_GOAL); -- -- pathfindergoalwrapped1.stop(); -- this.lockedFlags.put(pathfindergoal_type, pathfindergoalwrapped); +- }).filter(WrappedGoal::canUse).forEach((wrappedGoal) -> { +- wrappedGoal.getFlags().forEach((flag) -> { +- WrappedGoal wrappedGoal2 = this.lockedFlags.getOrDefault(flag, NO_GOAL); +- wrappedGoal2.stop(); +- this.lockedFlags.put(flag, wrappedGoal); - }); -- pathfindergoalwrapped.start(); -- }); ++ + // Paper start - remove streams from pathfindergoalselector -+ goal_update_loop: for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ goal_update_loop: for (java.util.Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { + WrappedGoal wrappedGoal = iterator.next(); + if (wrappedGoal.isRunning()) { + continue; + } + -+ OptimizedSmallEnumSet wrappedGoalSet = wrappedGoal.getGoalTypes(); ++ com.destroystokyo.paper.util.set.OptimizedSmallEnumSet wrappedGoalSet = wrappedGoal.getGoalTypes(); + + if (this.goalTypes.hasCommonElements(wrappedGoalSet)) { + continue; @@ -201,25 +172,25 @@ index 9bd2ee05a0de6678ad8933a8ffbe0ae66bd073b4..5da2d780c17522e07c733a5e23b17ec7 + wrapped.stop(); + this.lockedFlags.put(type, wrappedGoal); + } -+ -+ wrappedGoal.start(); + wrappedGoal.start(); +- }); + } + // Paper end - remove streams from pathfindergoalselector - gameprofilerfiller.pop(); - gameprofilerfiller.push("goalTick"); + profilerFiller.pop(); + profilerFiller.push("goalTick"); - this.getRunningGoals().forEach(WrappedGoal::tick); + // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ for (java.util.Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { + WrappedGoal wrappedGoal = iterator.next(); + if (wrappedGoal.isRunning()) { + wrappedGoal.tick(); + } + } + // Paper end - remove streams from pathfindergoalselector - gameprofilerfiller.pop(); + profilerFiller.pop(); } -@@ -125,11 +159,11 @@ public class GoalSelector { +@@ -118,11 +168,11 @@ public class GoalSelector { } public void disableControlFlag(Goal.Flag control) { @@ -234,10 +205,10 @@ index 9bd2ee05a0de6678ad8933a8ffbe0ae66bd073b4..5da2d780c17522e07c733a5e23b17ec7 public void setControlFlag(Goal.Flag control, boolean enabled) { diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -index 81b4618a7979ee8dd25e1749c084de9262318ef4..984146b2b6eb3e498433b1c4971397848166d9c9 100644 +index 1e915b999f4261fb27846a0e559ea22e4b09b4db..037cc5d2b41161e040fc9b264a0dd04827c29681 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -@@ -59,9 +59,10 @@ public class WrappedGoal extends Goal { +@@ -58,9 +58,10 @@ public class WrappedGoal extends Goal { this.goal.setFlags(controls); } @@ -250,4 +221,4 @@ index 81b4618a7979ee8dd25e1749c084de9262318ef4..984146b2b6eb3e498433b1c497139784 + // Paper end - remove streams from pathfindergoalselector } - public boolean isRunning() { return this.isRunning(); } // Paper - OBFHELPER + public boolean isRunning() { diff --git a/patches/server-remapped/0437-Async-command-map-building.patch b/patches/server/0393-Async-command-map-building.patch similarity index 95% rename from patches/server-remapped/0437-Async-command-map-building.patch rename to patches/server/0393-Async-command-map-building.patch index 87f32eb782..12df4c5c75 100644 --- a/patches/server-remapped/0437-Async-command-map-building.patch +++ b/patches/server/0393-Async-command-map-building.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Async command map building diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java -index 44f2e8a3741afc0e3c3bca3b0864e37ecf83e5d4..8154d9327c5411bbfea3bfa4d99d57feab764664 100644 +index 7ca6a1a3f10cb19d759f6d4dc9d5458ac0fc05d3..13e358e0eac3bfd426d924b6f745e001df76c64a 100644 --- a/src/main/java/net/minecraft/commands/Commands.java +++ b/src/main/java/net/minecraft/commands/Commands.java @@ -29,6 +29,7 @@ import net.minecraft.network.chat.MutableComponent; @@ -16,7 +16,7 @@ index 44f2e8a3741afc0e3c3bca3b0864e37ecf83e5d4..8154d9327c5411bbfea3bfa4d99d57fe import net.minecraft.server.commands.AdvancementCommands; import net.minecraft.server.commands.AttributeCommand; import net.minecraft.server.commands.BanIpCommands; -@@ -328,25 +329,40 @@ public class Commands { +@@ -335,25 +336,40 @@ public class Commands { if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot // CraftBukkit start // Register Vanilla commands into builtRoot as before @@ -61,7 +61,7 @@ index 44f2e8a3741afc0e3c3bca3b0864e37ecf83e5d4..8154d9327c5411bbfea3bfa4d99d57fe event.getPlayer().getServer().getPluginManager().callEvent(event); // Remove labels that were removed during the event -@@ -356,7 +372,7 @@ public class Commands { +@@ -363,7 +379,7 @@ public class Commands { } } // CraftBukkit end diff --git a/patches/server-remapped/0438-Improved-Watchdog-Support.patch b/patches/server/0394-Improved-Watchdog-Support.patch similarity index 81% rename from patches/server-remapped/0438-Improved-Watchdog-Support.patch rename to patches/server/0394-Improved-Watchdog-Support.patch index 928b62d524..be6786aadf 100644 --- a/patches/server-remapped/0438-Improved-Watchdog-Support.patch +++ b/patches/server/0394-Improved-Watchdog-Support.patch @@ -41,7 +41,7 @@ This also moves all plugins who register "delayed init" tasks to occur just befo are properly accounted for and wont trip watchdog on init. diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index 0b9e689d57705965721b5c55bc45d36657f360e4..dee00aac05f1acf050f05d4db557a08dd0f301c8 100644 +index e3b74dbdf8e14219a56fab939f3174e0c2f66de6..218f5bafeed8551b55b91c7fccaf6935c8b631ca 100644 --- a/src/main/java/com/destroystokyo/paper/Metrics.java +++ b/src/main/java/com/destroystokyo/paper/Metrics.java @@ -92,7 +92,12 @@ public class Metrics { @@ -59,10 +59,10 @@ index 0b9e689d57705965721b5c55bc45d36657f360e4..dee00aac05f1acf050f05d4db557a08d // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java -index 4008fbe506e74f2c463dc7b12f5dd0f3b6fc342d..766ab2fe536a2acccaec28e922ccf8993b0790dc 100644 +index bda7137b3435c9b7610be258cefb6b4ac2c1d47a..09f56e49383d3f5413ad4c28f3a7664e4d9570bd 100644 --- a/src/main/java/net/minecraft/CrashReport.java +++ b/src/main/java/net/minecraft/CrashReport.java -@@ -257,6 +257,7 @@ public class CrashReport { +@@ -231,6 +231,7 @@ public class CrashReport { } public static CrashReport forThrowable(Throwable cause, String title) { @@ -70,32 +70,20 @@ index 4008fbe506e74f2c463dc7b12f5dd0f3b6fc342d..766ab2fe536a2acccaec28e922ccf899 while (cause instanceof CompletionException && cause.getCause() != null) { cause = cause.getCause(); } -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index c2f747226f10479c826849af898538610a2dd659..83f9f97586f8c0e9d228923e4fec6f121a6702e2 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -129,6 +129,7 @@ public class Util { - return Util.IO_POOL; - } - -+ public static void shutdownServerThreadPool() { shutdownExecutors(); } // Paper - OBFHELPER - public static void shutdownExecutors() { - shutdownExecutor(Util.BACKGROUND_EXECUTOR); - shutdownExecutor(Util.IO_POOL); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 99ee9de92264381a064066bc22bb66b4b2852a2e..e5ad635a480d32e7a10ee92c65cfc18a98beafad 100644 +index 91ae80ee1020dc017faef7c8be8487132c547fe4..11fd6d24ed0612e4df1a0493907178fb9c455d1c 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -269,7 +269,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; - public boolean serverAutoSave = false; // Paper public Commands vanillaCommandDispatcher; - private boolean forceTicks; + public boolean forceTicks; // Paper // CraftBukkit end // Spigot start public static final int TPS = 20; -@@ -279,6 +279,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); Thread thread = new Thread(() -> { -@@ -851,6 +854,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -+ world.tickingEntities = false; -+ }); + } + // Paper end // CraftBukkit end MinecraftServer.LOGGER.info("Stopping server"); MinecraftTimings.stopServer(); // Paper -@@ -930,7 +951,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { CompletableFuture completablefuture; -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index b9978d296b83e73d3395b8254c0e8ccd9b36d0fa..bf4e50cd1d561456c033cda2d5c5487c5e3fe1eb 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -171,7 +171,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - private final Queue toAddAfterTick = Queues.newArrayDeque(); - public final List players = Lists.newArrayList(); // Paper - private -> public - public final ServerChunkCache chunkSource; // Paper - public -- boolean tickingEntities; -+ public boolean tickingEntities; // Paper - expose for watchdog - // Paper start - List afterEntityTickingTasks = Lists.newArrayList(); - public void doIfNotEntityTicking(java.lang.Runnable run) { diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 30666fca36b683158ff60302684b5093f5536e24..984ac19dcab446531c816e365c7c149e2c49d567 100644 +index 18485689bcbf7818c3ca5b82086acef51888603b..3431d28fd69c634ee0a941796308b88bb51bdaac 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -503,7 +503,7 @@ public abstract class PlayerList { - cserver.getPluginManager().callEvent(playerQuitEvent); +@@ -505,7 +505,7 @@ public abstract class PlayerList { + this.cserver.getPluginManager().callEvent(playerQuitEvent); entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - entityplayer.doTick(); // SPIGOT-924 @@ -316,30 +287,22 @@ index 30666fca36b683158ff60302684b5093f5536e24..984ac19dcab446531c816e365c7c149e // Paper start - Remove from collideRule team if needed diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -index a5ce61be7d6e85ac289730d9671e66a7190529f9..add18ba4833686ff51fbb280b0a5759f142b3f91 100644 +index 0ef3c4982df88a7991a56d983ac733daa8adc507..cdd797c6fc7507a0e6376f7d9c521be8f1d6decc 100644 --- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -@@ -135,6 +135,7 @@ public abstract class BlockableEventLoop implements Processo +@@ -148,6 +148,7 @@ public abstract class BlockableEventLoop implements Profiler try { task.run(); - } catch (Exception exception) { -+ if (exception.getCause() instanceof ThreadDeath) throw exception; // Paper - BlockableEventLoop.LOGGER.fatal("Error executing task on {}", this.name(), exception); + } catch (Exception var3) { ++ if (var3.getCause() instanceof ThreadDeath) throw var3; // Paper + LOGGER.fatal("Error executing task on {}", this.name(), var3); } diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 632f32405053fbcff2fd26fa99f98c6add9f9dc7..5860e7866724abd35bde2a5710d9c92799e5de67 100644 +index 5fccec12c0325dd9873905c5c3559128c3b4d9ad..03271675b4997588bd8f6774856aef25cdd4fa05 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -858,6 +858,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - gameprofilerfiller.pop(); - } catch (Throwable throwable) { -+ if (throwable instanceof ThreadDeath) throw throwable; // Paper - // Paper start - Prevent tile entity and entity crashes - String msg = "TileEntity threw exception at " + tileentity.getLevel().getWorld().getName() + ":" + tileentity.getBlockPos().getX() + "," + tileentity.getBlockPos().getY() + "," + tileentity.getBlockPos().getZ(); - System.err.println(msg); -@@ -932,6 +933,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -836,6 +836,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { try { tickConsumer.accept(entity); } catch (Throwable throwable) { @@ -347,11 +310,23 @@ index 632f32405053fbcff2fd26fa99f98c6add9f9dc7..5860e7866724abd35bde2a5710d9c927 // Paper start - Prevent tile entity and entity crashes String msg = "Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ(); System.err.println(msg); +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 59a77541bbda880ae8f84e3535a2b6112caa78fb..a63dc77db41dab79f03ef7384da55c1cdeca5d98 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -1320,6 +1320,7 @@ public class LevelChunk implements ChunkAccess { + + gameprofilerfiller.pop(); + } catch (Throwable throwable) { ++ if (throwable instanceof ThreadDeath) throw throwable; // Paper + // Paper start - Prevent tile entity and entity crashes + String msg = "TileEntity threw exception at " + LevelChunk.this.getLevel().getWorld().getName() + ":" + this.getPos().getX() + "," + this.getPos().getY() + "," + this.getPos().getZ(); + System.err.println(msg); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 3f35e93b42efd03ff1002f09962fe3da51fb4c3f..43c37e660a8a7f9d326ad38e66f9aa7c53c7b87c 100644 +index 3423de396e0fadfa29714f5fcac4b579a8ff0967..4c0b94a56fab161fca92b594f55e1c846524d5e8 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1839,7 +1839,7 @@ public final class CraftServer implements Server { +@@ -1840,7 +1840,7 @@ public final class CraftServer implements Server { @Override public boolean isPrimaryThread() { @@ -361,7 +336,7 @@ index 3f35e93b42efd03ff1002f09962fe3da51fb4c3f..43c37e660a8a7f9d326ad38e66f9aa7c // Paper start diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index c519ceca6f7788ca7c5d74ad1001dbc09f62681c..c288b89bf5a22269823ba1d18af217032d7c6a36 100644 +index fd48cfe3dfaf7c867becfbf90246af2f33a74612..2904cbda94a8fb986d94022c11061f98938237dd 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -12,6 +12,8 @@ import java.util.logging.Level; @@ -410,7 +385,7 @@ index c519ceca6f7788ca7c5d74ad1001dbc09f62681c..c288b89bf5a22269823ba1d18af21703 try { options = parser.parse(args); } catch (joptsimple.OptionException ex) { -@@ -251,8 +283,64 @@ public class Main { +@@ -255,8 +287,64 @@ public class Main { } catch (Throwable t) { t.printStackTrace(); } @@ -476,7 +451,7 @@ index c519ceca6f7788ca7c5d74ad1001dbc09f62681c..c288b89bf5a22269823ba1d18af21703 private static List asList(String... params) { return Arrays.asList(params); diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index 449e99d1b673870ed6892f6ab2c715a2db35c35d..c7ed6e0f8a989cec97700df2b15198c9c481c549 100644 +index b4a19d80bbf71591f25729fd0e98590350cb31d0..d752720f2f234b9dbd2117333fee1bfad663ec02 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java @@ -12,12 +12,27 @@ public class ServerShutdownThread extends Thread { @@ -496,7 +471,7 @@ index 449e99d1b673870ed6892f6ab2c715a2db35c35d..c7ed6e0f8a989cec97700df2b15198c9 org.spigotmc.AsyncCatcher.enabled = false; // Spigot org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper + server.forceTicks = true; - server.close(); + this.server.close(); + while (!server.hasFullyShutdown) Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); @@ -509,7 +484,7 @@ index 449e99d1b673870ed6892f6ab2c715a2db35c35d..c7ed6e0f8a989cec97700df2b15198c9 } } diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index 6dab105cd7cc4340c031c395c0346d4731355d79..6498dc4c6630bfef1a52edf74d8574e5e4876720 100644 +index a142a56a920e153ed84c08cece993f10d76f7793..92d97a5810a379b427a99b4c63fb9844d823a84f 100644 --- a/src/main/java/org/spigotmc/RestartCommand.java +++ b/src/main/java/org/spigotmc/RestartCommand.java @@ -139,7 +139,7 @@ public class RestartCommand extends Command @@ -522,10 +497,10 @@ index 6dab105cd7cc4340c031c395c0346d4731355d79..6498dc4c6630bfef1a52edf74d8574e5 String[] split = restartScript.split( " " ); if ( split.length > 0 && new File( split[0] ).isFile() ) diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 33a66322d253c7562ae5acbdbc6cc87f7d72a9af..26c9adf7af4328ce2d8e08568019c5b438e28b05 100644 +index 1ffb208094f521883ef0e23baf5fb29380b14273..4d271cae88c16ed2419f896c728fdff612540500 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -13,6 +13,7 @@ import org.bukkit.Bukkit; +@@ -12,6 +12,7 @@ import org.bukkit.Bukkit; public class WatchdogThread extends Thread { @@ -533,21 +508,21 @@ index 33a66322d253c7562ae5acbdbc6cc87f7d72a9af..26c9adf7af4328ce2d8e08568019c5b4 private static WatchdogThread instance; private long timeoutTime; private boolean restart; -@@ -41,6 +42,7 @@ public class WatchdogThread extends Thread +@@ -40,6 +41,7 @@ public class WatchdogThread extends Thread { - if ( instance == null ) + if ( WatchdogThread.instance == null ) { + if (timeoutTime <= 0) timeoutTime = 300; // Paper - instance = new WatchdogThread( timeoutTime * 1000L, restart ); - instance.start(); + WatchdogThread.instance = new WatchdogThread( timeoutTime * 1000L, restart ); + WatchdogThread.instance.start(); } else @@ -71,12 +73,13 @@ public class WatchdogThread extends Thread // Paper start Logger log = Bukkit.getServer().getLogger(); - long currentTime = monotonicMillis(); -- if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) + long currentTime = WatchdogThread.monotonicMillis(); +- if ( this.lastTick != 0 && this.timeoutTime > 0 && currentTime > this.lastTick + this.earlyWarningEvery && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable + MinecraftServer server = MinecraftServer.getServer(); -+ if (lastTick != 0 && timeoutTime > 0 && hasStarted && (!server.isRunning() || (currentTime > lastTick + earlyWarningEvery && !DISABLE_WATCHDOG) )) ++ if ( this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.hasStarted && (!server.isRunning() || (currentTime > this.lastTick + this.earlyWarningEvery && !DISABLE_WATCHDOG) )) // Paper - add property to disable { - boolean isLongTimeout = currentTime > lastTick + timeoutTime; + boolean isLongTimeout = currentTime > lastTick + timeoutTime || (!server.isRunning() && !server.hasStopped() && currentTime > lastTick + 1000); @@ -561,17 +536,17 @@ index 33a66322d253c7562ae5acbdbc6cc87f7d72a9af..26c9adf7af4328ce2d8e08568019c5b4 @@ -118,7 +121,7 @@ public class WatchdogThread extends Thread log.log( Level.SEVERE, "------------------------------" ); log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper -- dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); -+ dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log ); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper +- WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); ++ WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log ); log.log( Level.SEVERE, "------------------------------" ); // // Paper start - Only print full dump on long timeouts -@@ -139,9 +142,25 @@ public class WatchdogThread extends Thread +@@ -138,9 +141,25 @@ public class WatchdogThread extends Thread if ( isLongTimeout ) { -- if ( restart && !MinecraftServer.getServer().hasStopped() ) +- if ( this.restart && !MinecraftServer.getServer().hasStopped() ) + if ( !server.hasStopped() ) { - RestartCommand.restart(); diff --git a/patches/server-remapped/0439-Optimize-Pathfinding.patch b/patches/server/0395-Optimize-Pathfinding.patch similarity index 51% rename from patches/server-remapped/0439-Optimize-Pathfinding.patch rename to patches/server/0395-Optimize-Pathfinding.patch index 9f2777798e..4e073805ba 100644 --- a/patches/server-remapped/0439-Optimize-Pathfinding.patch +++ b/patches/server/0395-Optimize-Pathfinding.patch @@ -7,27 +7,10 @@ Prevents pathfinding from spamming failures for things such as arrow attacks. diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index a362506f38e8d30543b6cd6d215db561290dac76..c501e42b6fef4af065807182dc5b4c444e74e310 100644 +index 69edca1ef95c37b11fe3f793e6a8f8a674bd7f6f..3f4d7552e7f219aec043f0cc06a816758e5a3f66 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -11,6 +11,7 @@ import net.minecraft.core.Position; - import net.minecraft.core.Vec3i; - import net.minecraft.network.protocol.game.DebugPackets; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.Mob; -@@ -32,7 +33,7 @@ public abstract class PathNavigation { - protected final Mob mob; public Entity getEntity() { return mob; } // Paper - OBFHELPER - protected final Level level; - @Nullable -- protected Path path; -+ protected Path path; protected final Path getCurrentPath() { return this.path; } // Paper - OBFHELPER - protected double speedModifier; - protected int tick; - protected int lastStuckCheck; -@@ -184,10 +185,30 @@ public abstract class PathNavigation { +@@ -190,9 +190,29 @@ public abstract class PathNavigation { return this.moveTo(this.createPath(x, y, z, 1), speed); } @@ -38,21 +21,20 @@ index a362506f38e8d30543b6cd6d215db561290dac76..c501e42b6fef4af065807182dc5b4c44 + public boolean moveTo(Entity entity, double speed) { + // Paper start - Pathfinding optimizations -+ if (this.pathfindFailures > 10 && this.getCurrentPath() == null && MinecraftServer.currentTick < this.lastFailure + 40) { ++ if (this.pathfindFailures > 10 && this.path == null && net.minecraft.server.MinecraftServer.currentTick < this.lastFailure + 40) { + return false; + } + // Paper end - Path pathentity = this.createPath(entity, 1); - -- return pathentity != null && this.moveTo(pathentity, speed); + Path path = this.createPath(entity, 1); +- return path != null && this.moveTo(path, speed); + // Paper start - Pathfinding optimizations -+ if (pathentity != null && this.moveTo(pathentity, speed)) { ++ if (path != null && this.moveTo(path, speed)) { + this.lastFailure = 0; + this.pathfindFailures = 0; + return true; + } else { + this.pathfindFailures++; -+ this.lastFailure = MinecraftServer.currentTick; ++ this.lastFailure = net.minecraft.server.MinecraftServer.currentTick; + return false; + } + // Paper end diff --git a/patches/server-remapped/0440-Reduce-Either-Optional-allocation.patch b/patches/server/0396-Reduce-Either-Optional-allocation.patch similarity index 95% rename from patches/server-remapped/0440-Reduce-Either-Optional-allocation.patch rename to patches/server/0396-Reduce-Either-Optional-allocation.patch index 991b0f903b..0f4641263b 100644 --- a/patches/server-remapped/0440-Reduce-Either-Optional-allocation.patch +++ b/patches/server/0396-Reduce-Either-Optional-allocation.patch @@ -7,7 +7,7 @@ In order to get chunk values, we shouldn't need to create an optional each time. diff --git a/src/main/java/com/mojang/datafixers/util/Either.java b/src/main/java/com/mojang/datafixers/util/Either.java -index fc8dbdf43833d76d8dc5f4e92575ca2965afa93a..ab71cdb3a8c2bec036ece630a0e0f088653e928f 100644 +index a90adac7bd7ebd423f480e9ae0f44cb9d521fa4f..3f65fe71024928e35111fc6719a290aab9a6859e 100644 --- a/src/main/java/com/mojang/datafixers/util/Either.java +++ b/src/main/java/com/mojang/datafixers/util/Either.java @@ -22,7 +22,7 @@ public abstract class Either implements App, L> { diff --git a/patches/server/0397-Remove-streams-from-PairedQueue.patch b/patches/server/0397-Remove-streams-from-PairedQueue.patch new file mode 100644 index 0000000000..91f6f25ab6 --- /dev/null +++ b/patches/server/0397-Remove-streams-from-PairedQueue.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 6 Apr 2020 18:10:43 -0700 +Subject: [PATCH] Remove streams from PairedQueue + +We shouldn't be doing stream calls just to see if the queue is +empty. This creates loads of garbage thanks to how often it's called. + +diff --git a/src/main/java/net/minecraft/util/thread/StrictQueue.java b/src/main/java/net/minecraft/util/thread/StrictQueue.java +index 66591e23bc9e0df968fb6b291a3ad3773debdf29..c4a20df21e1fe5556fddac64b52d542579758e2c 100644 +--- a/src/main/java/net/minecraft/util/thread/StrictQueue.java ++++ b/src/main/java/net/minecraft/util/thread/StrictQueue.java +@@ -22,9 +22,12 @@ public interface StrictQueue { + private final List> queueList; + + public FixedPriorityQueue(int priorityCount) { +- this.queueList = IntStream.range(0, priorityCount).mapToObj((i) -> { +- return Queues.newConcurrentLinkedQueue(); +- }).collect(Collectors.toList()); ++ // Paper start - remove streams ++ this.queueList = new java.util.ArrayList<>(priorityCount); // queues ++ for (int j = 0; j < priorityCount; ++j) { ++ this.queueList.add(Queues.newConcurrentLinkedQueue()); ++ } ++ // Paper end - remove streams + } + + @Nullable +@@ -49,7 +52,16 @@ public interface StrictQueue { + + @Override + public boolean isEmpty() { +- return this.queueList.stream().allMatch(Collection::isEmpty); ++ // Paper start - remove streams ++ // why are we doing streams every time we might want to execute a task? ++ for (int i = 0, len = this.queueList.size(); i < len; ++i) { ++ Queue queue = this.queueList.get(i); ++ if (!queue.isEmpty()) { ++ return false; ++ } ++ } ++ return true; ++ // Paper end - remove streams + } + + @Override diff --git a/patches/server-remapped/0442-Reduce-memory-footprint-of-NBTTagCompound.patch b/patches/server/0398-Reduce-memory-footprint-of-NBTTagCompound.patch similarity index 50% rename from patches/server-remapped/0442-Reduce-memory-footprint-of-NBTTagCompound.patch rename to patches/server/0398-Reduce-memory-footprint-of-NBTTagCompound.patch index dcba632a31..cea824d101 100644 --- a/patches/server-remapped/0442-Reduce-memory-footprint-of-NBTTagCompound.patch +++ b/patches/server/0398-Reduce-memory-footprint-of-NBTTagCompound.patch @@ -8,45 +8,36 @@ is important because we clone chunk data after reading it for safety. So, reduce the impact of the clone on GC. diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java -index a91bf94ed9f2f353a685194fc91c4b101ccc1232..c856ca720a9329a94bb07eaa3060c034f95718b3 100644 +index 750df4ab2fbfdcf759f4d3451340e66b6764391d..1aa3af8c7714b2c850fb4264c863db8e639e6284 100644 --- a/src/main/java/net/minecraft/nbt/CompoundTag.java +++ b/src/main/java/net/minecraft/nbt/CompoundTag.java -@@ -26,6 +26,7 @@ import net.minecraft.ReportedException; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.MutableComponent; - import net.minecraft.network.chat.TextComponent; -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -47,7 +48,7 @@ public class CompoundTag implements Tag { +@@ -34,7 +34,7 @@ public class CompoundTag implements Tag { if (i > 512) { throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512"); } else { -- HashMap hashmap = Maps.newHashMap(); -+ Object2ObjectOpenHashMap hashmap = new Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound +- Map map = Maps.newHashMap(); ++ it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap map = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound - byte b0; - -@@ -83,7 +84,7 @@ public class CompoundTag implements Tag { + byte b; + while((b = CompoundTag.readNamedTagType(dataInput, nbtAccounter)) != 0) { +@@ -67,7 +67,7 @@ public class CompoundTag implements Tag { } public CompoundTag() { - this(Maps.newHashMap()); -+ this(new Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - reduce memory footprint of NBTTagCompound ++ this(new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - reduce memory footprint of NBTTagCompound } @Override -@@ -417,9 +418,17 @@ public class CompoundTag implements Tag { +@@ -374,8 +374,16 @@ public class CompoundTag implements Tag { @Override public CompoundTag copy() { - Map map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy)); -+ // Paper start - reduce memory footprint of NBTTagCompound -+ Object2ObjectOpenHashMap ret = new Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f); - - return new CompoundTag(map); -+ Iterator> iterator = (this.tags instanceof Object2ObjectOpenHashMap) ? ((Object2ObjectOpenHashMap)this.tags).object2ObjectEntrySet().fastIterator() : this.tags.entrySet().iterator(); ++ // Paper start - reduce memory footprint of NBTTagCompound ++ it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap ret = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f); ++ java.util.Iterator> iterator = (this.tags instanceof it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap) ? ((it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap)this.tags).object2ObjectEntrySet().fastIterator() : this.tags.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + ret.put(entry.getKey(), entry.getValue().copy()); @@ -56,4 +47,4 @@ index a91bf94ed9f2f353a685194fc91c4b101ccc1232..c856ca720a9329a94bb07eaa3060c034 + // Paper end - reduce memory footprint of NBTTagCompound } - public boolean equals(Object object) { + @Override diff --git a/patches/server-remapped/0443-Prevent-opening-inventories-when-frozen.patch b/patches/server/0399-Prevent-opening-inventories-when-frozen.patch similarity index 76% rename from patches/server-remapped/0443-Prevent-opening-inventories-when-frozen.patch rename to patches/server/0399-Prevent-opening-inventories-when-frozen.patch index 7b2a22a56b..29b12f74db 100644 --- a/patches/server-remapped/0443-Prevent-opening-inventories-when-frozen.patch +++ b/patches/server/0399-Prevent-opening-inventories-when-frozen.patch @@ -5,10 +5,10 @@ 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 162b1a8c6ab57aafa4f6deefc842755a8e14208e..efacfcaab444270b985f3a7fe0ef97e33c18a9de 100644 +index bfa91166c18110877f751a5325e59623a05325d0..42c2862530cff79a9b09850faccb683df1f2a5c8 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -557,7 +557,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -608,7 +608,7 @@ public class ServerPlayer extends Player { containerUpdateDelay = level.paperConfig.containerUpdateTickRate; } // Paper end @@ -17,43 +17,34 @@ index 162b1a8c6ab57aafa4f6deefc842755a8e14208e..efacfcaab444270b985f3a7fe0ef97e3 this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper this.containerMenu = this.inventoryMenu; } -@@ -1404,7 +1404,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1449,7 +1449,7 @@ public class ServerPlayer extends Player { } else { // CraftBukkit start this.containerMenu = container; - this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); + if (!isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper // CraftBukkit end - container.addSlotListener(this); + this.initMenu(container); return OptionalInt.of(this.containerCounter); -@@ -2206,7 +2206,7 @@ public class ServerPlayer extends Player implements ContainerListener { - } - - @Override -- protected boolean isImmobile() { -+ public boolean isImmobile() { // Paper - protected > public - return super.isImmobile() || (this.connection != null && this.connection.isDisconnected()); // Paper - } - diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index a73c6ddd6bf66cc21ae5b25daacdece8cbfeeeac..ae6faa331fcbefd99ee1cd92c88926d767fc50ee 100644 +index 43cee8b0b2b94d6db6303a1631731ed515eb806d..31b62dc1ee06b254c398cbfe157283fb199ef0fe 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -323,7 +323,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -322,7 +322,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment - player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - getHandle().containerMenu = container; - getHandle().containerMenu.addSlotListener(player); + player.containerMenu = container; + player.initMenu(container); } -@@ -397,7 +397,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -396,7 +396,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment - player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper player.containerMenu = container; - player.containerMenu.addSlotListener(player); + player.initMenu(container); } diff --git a/patches/server-remapped/0444-Optimise-ArraySetSorted-removeIf.patch b/patches/server/0400-Optimise-ArraySetSorted-removeIf.patch similarity index 60% rename from patches/server-remapped/0444-Optimise-ArraySetSorted-removeIf.patch rename to patches/server/0400-Optimise-ArraySetSorted-removeIf.patch index dad03aa170..1f9f1e2e4e 100644 --- a/patches/server-remapped/0444-Optimise-ArraySetSorted-removeIf.patch +++ b/patches/server/0400-Optimise-ArraySetSorted-removeIf.patch @@ -6,30 +6,19 @@ Subject: [PATCH] Optimise ArraySetSorted#removeIf Remove iterator allocation and ensure the call is always O(n) diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java -index 93813a508be1e1e600a8211f9822f2087328de70..8f03847eeb95ccdb69ad181b38b8724c9c72a76b 100644 +index d1b2ba24ef54e01c6249c3b2ca16e80f03c001a6..5f1c4c6b9e36f2d6ec43b82cc0e2cae24b800dc4 100644 --- a/src/main/java/net/minecraft/util/SortedArraySet.java +++ b/src/main/java/net/minecraft/util/SortedArraySet.java -@@ -10,8 +10,8 @@ import java.util.NoSuchElementException; - public class SortedArraySet extends AbstractSet { - - private final Comparator comparator; -- private T[] contents; -- private int size; -+ private T[] contents; private final T[] getBackingArray() { return this.contents; } // Paper - OBFHELPER -+ private int size; private final int getSize() { return this.size; } private final void setSize(int value) { this.size = value; } // Paper - OBFHELPER - - private SortedArraySet(int initialCapacity, Comparator comparator) { - this.comparator = comparator; -@@ -22,6 +22,42 @@ public class SortedArraySet extends AbstractSet { +@@ -22,6 +22,41 @@ public class SortedArraySet extends AbstractSet { + this.contents = (T[])castRawArray(new Object[initialCapacity]); } } - + // Paper start - optimise removeIf + @Override + public boolean removeIf(java.util.function.Predicate filter) { + // prev. impl used an iterator, which could be n^2 and creates garbage -+ int i = 0, len = this.getSize(); -+ T[] backingArray = this.getBackingArray(); ++ int i = 0, len = this.size; ++ T[] backingArray = this.contents; + + for (;;) { + if (i >= len) { @@ -55,11 +44,10 @@ index 93813a508be1e1e600a8211f9822f2087328de70..8f03847eeb95ccdb69ad181b38b8724c + + // cleanup end + Arrays.fill(backingArray, lastIndex, len, null); -+ this.setSize(lastIndex); ++ this.size = lastIndex; + return true; + } + // Paper end - optimise removeIf -+ - public static > SortedArraySet create(int initialCapacity) { - return new SortedArraySet<>(initialCapacity, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix - } + + public static > SortedArraySet create() { + return create(10); diff --git a/patches/server-remapped/0445-Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server/0401-Don-t-run-entity-collision-code-if-not-needed.patch similarity index 81% rename from patches/server-remapped/0445-Don-t-run-entity-collision-code-if-not-needed.patch rename to patches/server/0401-Don-t-run-entity-collision-code-if-not-needed.patch index 474688a9b3..ce4b9003ba 100644 --- a/patches/server-remapped/0445-Don-t-run-entity-collision-code-if-not-needed.patch +++ b/patches/server/0401-Don-t-run-entity-collision-code-if-not-needed.patch @@ -7,19 +7,19 @@ Will not run if max entity craming is disabled and the max collisions per entity is less than or equal to 0 diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 43fbe7d220f61802ae0cb0620ad078c5df7b69bc..46b962183e2e27ed93054ad9fb6d8ecbf70bc5f9 100644 +index 6cc2d26403aa5074218b4b76e2d8ed9e8409a0ae..0fd79c399e723b5a9db04c8f2fe7b6ec66c0cf44 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2941,10 +2941,16 @@ public abstract class LivingEntity extends Entity { +@@ -3256,10 +3256,16 @@ public abstract class LivingEntity extends Entity { protected void serverAiStep() {} protected void pushEntities() { -+ // Paper - start don't run getEntities if we're not going to use its result ++ // Paper start - don't run getEntities if we're not going to use its result + int i = this.level.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); + if (i <= 0 && level.paperConfig.maxCollisionsPerEntity <= 0) { + return; + } -+ // Paper - end don't run getEntities if we're not going to use its result ++ // Paper end - don't run getEntities if we're not going to use its result List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); if (!list.isEmpty()) { diff --git a/patches/server-remapped/0447-Restrict-vanilla-teleport-command-to-valid-locations.patch b/patches/server/0402-Restrict-vanilla-teleport-command-to-valid-locations.patch similarity index 90% rename from patches/server-remapped/0447-Restrict-vanilla-teleport-command-to-valid-locations.patch rename to patches/server/0402-Restrict-vanilla-teleport-command-to-valid-locations.patch index bc23f71417..b0ce748234 100644 --- a/patches/server-remapped/0447-Restrict-vanilla-teleport-command-to-valid-locations.patch +++ b/patches/server/0402-Restrict-vanilla-teleport-command-to-valid-locations.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Restrict vanilla teleport command to valid locations Fixes GH-3165, GH-3575 diff --git a/src/main/java/net/minecraft/server/commands/TeleportCommand.java b/src/main/java/net/minecraft/server/commands/TeleportCommand.java -index 774180d9e450199309fee65b1d10e1592f84548a..d04ce9a323b079b4556b8c341fb11186e8d3e05d 100644 +index 85ae18b7f8a26f83ea0cf1ae17cfa88b796fcc77..d0109df7fad51fc0444459f5d367254c8f4c355e 100644 --- a/src/main/java/net/minecraft/server/commands/TeleportCommand.java +++ b/src/main/java/net/minecraft/server/commands/TeleportCommand.java -@@ -141,6 +141,12 @@ public class TeleportCommand { +@@ -148,6 +148,12 @@ public class TeleportCommand { private static void performTeleport(CommandSourceStack source, Entity target, ServerLevel world, double x, double y, double z, Set movementFlags, float yaw, float pitch, @Nullable TeleportCommand.LookAt facingLocation) throws CommandSyntaxException { BlockPos blockposition = new BlockPos(x, y, z); diff --git a/patches/server-remapped/0448-Implement-Player-Client-Options-API.patch b/patches/server/0403-Implement-Player-Client-Options-API.patch similarity index 50% rename from patches/server-remapped/0448-Implement-Player-Client-Options-API.patch rename to patches/server/0403-Implement-Player-Client-Options-API.patch index dcdbea5496..0f85780783 100644 --- a/patches/server-remapped/0448-Implement-Player-Client-Options-API.patch +++ b/patches/server/0403-Implement-Player-Client-Options-API.patch @@ -84,105 +84,57 @@ index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabb + .toString(); + } +} -diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java -index 1f486cfd77b49568540398b1b3fa6127b17ba6aa..4b43740f9ff4feab4f1cd2f8e91d55be3cf8eb50 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundClientInformationPacket.java -@@ -41,14 +41,17 @@ public class ServerboundClientInformationPacket implements Packet POSES = ImmutableMap.builder().put(Pose.STANDING, Player.STANDING_DIMENSIONS).put(Pose.SLEEPING, Player.SLEEPING_DIMENSIONS).put(Pose.FALL_FLYING, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.SWIMMING, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.SPIN_ATTACK, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.CROUCHING, EntityDimensions.scalable(0.6F, 1.5F)).put(Pose.DYING, EntityDimensions.fixed(0.2F, 0.2F)).build(); +@@ -144,7 +144,7 @@ public abstract class Player extends LivingEntity { + private static final int FLY_ACHIEVEMENT_SPEED = 25; private static final EntityDataAccessor DATA_PLAYER_ABSORPTION_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.FLOAT); private static final EntityDataAccessor DATA_SCORE_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.INT); - protected static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); -+ protected static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); public static EntityDataAccessor getSkinPartsWatcher() { return DATA_PLAYER_MODE_CUSTOMISATION; } // Paper - OBFHELPER ++ public static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); // Paper - protected -> public protected static final EntityDataAccessor DATA_PLAYER_MAIN_HAND = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); protected static final EntityDataAccessor DATA_SHOULDER_LEFT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); protected static final EntityDataAccessor DATA_SHOULDER_RIGHT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 20de8e358789d05bb5ac15e4cdd7dda85b61b7f8..eb366396820c9b6731469df4198e0884a431a77c 100644 +index 2ed7920b0e046bc9d581878a10b04ad784bb8655..0a6d6ea67eaf8b2a59ec45fb3ffb85096f509997 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1,5 +1,8 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.ClientOption.ChatVisibility; -+import com.destroystokyo.paper.PaperSkinParts; -+import com.destroystokyo.paper.ClientOption; - import com.destroystokyo.paper.Title; - import com.google.common.base.Preconditions; - import com.google.common.collect.ImmutableSet; -@@ -2250,6 +2253,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -516,6 +516,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public void setViewDistance(int viewDistance) { throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO } + + @Override -+ public T getClientOption(ClientOption type) { -+ if(ClientOption.SKIN_PARTS.equals(type)) { -+ return type.getType().cast(new PaperSkinParts(getHandle().getEntityData().get(net.minecraft.world.entity.player.Player.getSkinPartsWatcher()))); -+ } else if(ClientOption.CHAT_COLORS_ENABLED.equals(type)) { -+ return type.getType().cast(getHandle().hasChatColorsEnabled()); -+ } else if(ClientOption.CHAT_VISIBILITY.equals(type)) { -+ return type.getType().cast(getHandle().getChatVisibility() == null ? ChatVisibility.UNKNOWN : ChatVisibility.valueOf(getHandle().getChatVisibility().name())); -+ } else if(ClientOption.LOCALE.equals(type)) { ++ public T getClientOption(com.destroystokyo.paper.ClientOption type) { ++ if(com.destroystokyo.paper.ClientOption.SKIN_PARTS.equals(type)) { ++ return type.getType().cast(new com.destroystokyo.paper.PaperSkinParts(getHandle().getEntityData().get(net.minecraft.world.entity.player.Player.DATA_PLAYER_MODE_CUSTOMISATION))); ++ } else if(com.destroystokyo.paper.ClientOption.CHAT_COLORS_ENABLED.equals(type)) { ++ return type.getType().cast(getHandle().canChatInColor()); ++ } else if(com.destroystokyo.paper.ClientOption.CHAT_VISIBILITY.equals(type)) { ++ return type.getType().cast(getHandle().getChatVisibility() == null ? com.destroystokyo.paper.ClientOption.ChatVisibility.UNKNOWN : com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(getHandle().getChatVisibility().name())); ++ } else if(com.destroystokyo.paper.ClientOption.LOCALE.equals(type)) { + return type.getType().cast(getLocale()); -+ } else if(ClientOption.MAIN_HAND.equals(type)) { ++ } else if(com.destroystokyo.paper.ClientOption.MAIN_HAND.equals(type)) { + return type.getType().cast(getMainHand()); -+ } else if(ClientOption.VIEW_DISTANCE.equals(type)) { ++ } else if(com.destroystokyo.paper.ClientOption.VIEW_DISTANCE.equals(type)) { + return type.getType().cast(getClientViewDistance()); + } + throw new RuntimeException("Unknown settings type"); + } // Paper end - // Spigot start + @Override diff --git a/patches/server-remapped/0449-Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server/0404-Fix-Chunk-Post-Processing-deadlock-risk.patch similarity index 87% rename from patches/server-remapped/0449-Fix-Chunk-Post-Processing-deadlock-risk.patch rename to patches/server/0404-Fix-Chunk-Post-Processing-deadlock-risk.patch index 1d32694a1d..eff3a55349 100644 --- a/patches/server-remapped/0449-Fix-Chunk-Post-Processing-deadlock-risk.patch +++ b/patches/server/0404-Fix-Chunk-Post-Processing-deadlock-risk.patch @@ -25,19 +25,18 @@ This successfully fixed a reoccurring and highly reproduceable crash for heightmaps. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 49728aab7512ea8486d277d34e80d3c6a4727aac..dbe60f5d24fb39be52c3cb8f933371b1626951df 100644 +index c82345c74e0e6246f304283c2e06e2d1fcfe53ca..d3094c8a6a906737d4ca56a76ff40b3586961680 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -181,6 +181,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -189,6 +189,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider }; // CraftBukkit end + final CallbackExecutor chunkLoadConversionCallbackExecutor = new CallbackExecutor(); // Paper -+ // Paper start - distance maps private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); - -@@ -1054,7 +1056,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper start - no-tick view distance +@@ -1028,7 +1029,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return Either.left(chunk); }); }, (runnable) -> { @@ -47,10 +46,10 @@ index 49728aab7512ea8486d277d34e80d3c6a4727aac..dbe60f5d24fb39be52c3cb8f933371b1 completablefuture1.thenAcceptAsync((either) -> { diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 531fe1259a1d60ff69321c3fefbf97f7141e6475..b45fe750c8ca838e1beebff4077e5819eec2836c 100644 +index 751454ad5a2c374c01ff360535428db36c0aa1b3..e4f5f564892836a2e925f419e8fcb60c70b21a47 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -1021,6 +1021,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -985,6 +985,7 @@ public class ServerChunkCache extends ChunkSource { return super.pollTask() || execChunkTask; // Paper } } finally { diff --git a/patches/server-remapped/0450-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/patches/server/0405-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch similarity index 88% rename from patches/server-remapped/0450-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch rename to patches/server/0405-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch index 1469edc105..324693d286 100644 --- a/patches/server-remapped/0450-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch +++ b/patches/server/0405-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch @@ -7,10 +7,10 @@ Subject: [PATCH] Don't crash if player is attempted to be removed from I suspect it deals with teleporting as it uses players current x/y/z diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index 71a51cc99e26579e765f88340588e23956888929..90429d3f5c5b725098cfb001d54c70608f3df7bb 100644 +index 38eebda226e007c8910e04f502ce218cdfe1d456..b49d380ef088aed3204ec71abc437c348ef004fa 100644 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java +++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -245,8 +245,8 @@ public abstract class DistanceManager { +@@ -253,8 +253,8 @@ public abstract class DistanceManager { ObjectSet objectset = (ObjectSet) this.playersPerChunk.get(i); if (objectset == null) return; // CraftBukkit - SPIGOT-6208 diff --git a/patches/server-remapped/0451-Broadcast-join-message-to-console.patch b/patches/server/0406-Broadcast-join-message-to-console.patch similarity index 65% rename from patches/server-remapped/0451-Broadcast-join-message-to-console.patch rename to patches/server/0406-Broadcast-join-message-to-console.patch index de365413d4..255cb81628 100644 --- a/patches/server-remapped/0451-Broadcast-join-message-to-console.patch +++ b/patches/server/0406-Broadcast-join-message-to-console.patch @@ -5,16 +5,16 @@ Subject: [PATCH] Broadcast join message to console diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 984ac19dcab446531c816e365c7c149e2c49d567..e043722436492140162940770c22be47690fb47f 100644 +index 3431d28fd69c634ee0a941796308b88bb51bdaac..5432ce5b86b7731fe5d06d334e4e191f2eb2f429 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -284,7 +284,9 @@ public abstract class PlayerList { +@@ -286,7 +286,9 @@ public abstract class PlayerList { if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure -- server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure +- this.server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure + // Paper start - Removed sendAll for loop and broadcasted to console also -+ server.getPlayerList().sendMessage(joinMessage); // Paper - Adventure ++ this.server.getPlayerList().broadcastMessage(joinMessage, ChatType.SYSTEM, Util.NIL_UUID); // Paper - Adventure + // Paper end } // CraftBukkit end diff --git a/patches/server-remapped/0452-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/patches/server/0407-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch similarity index 61% rename from patches/server-remapped/0452-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch rename to patches/server/0407-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch index e4ac02eb91..c85247b418 100644 --- a/patches/server-remapped/0452-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch +++ b/patches/server/0407-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch @@ -28,11 +28,11 @@ receives a deterministic result, and should no longer require 1 tick delays anymore. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index dbe60f5d24fb39be52c3cb8f933371b1626951df..b3ca4300b280a24f3ed2acaffdd6ae2cdffd140d 100644 +index d3094c8a6a906737d4ca56a76ff40b3586961680..2cb807f7095648948527b5b9151770193970cc00 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1584,7 +1584,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - }); +@@ -1529,7 +1529,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end - per player view distance } - protected void addEntity(Entity entity) { @@ -40,7 +40,7 @@ index dbe60f5d24fb39be52c3cb8f933371b1626951df..b3ca4300b280a24f3ed2acaffdd6ae2c org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot // Paper start - ignore and warn about illegal addEntity calls instead of crashing server if (!entity.valid || entity.level != this.level || this.entityMap.containsKey(entity.getId())) { -@@ -1593,6 +1593,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1538,6 +1538,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider .printStackTrace(); return; } @@ -49,10 +49,10 @@ index dbe60f5d24fb39be52c3cb8f933371b1626951df..b3ca4300b280a24f3ed2acaffdd6ae2c if (!(entity instanceof EnderDragonPart)) { EntityType entitytypes = entity.getType(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index aa979d17c264840ebd528708df3d6118e69fec68..75a095e0c2177dc1b46b080597ff8f12f1480acc 100644 +index aec3ded7f65e4a97796afc01b71eeb89c2b3fb70..a30840b74bc2574725c42735f633630d9b471d54 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -237,6 +237,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -237,6 +237,7 @@ public class ServerPlayer extends Player { public double maxHealthCache; public boolean joining = true; public boolean sentListPacket = false; @@ -61,10 +61,10 @@ index aa979d17c264840ebd528708df3d6118e69fec68..75a095e0c2177dc1b46b080597ff8f12 // CraftBukkit end public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index e043722436492140162940770c22be47690fb47f..454d60566743e02e7e55868c7bb45e30583dfa8f 100644 +index 5432ce5b86b7731fe5d06d334e4e191f2eb2f429..3a13c151066c8784fdc844e1d6310f77ff32e7f1 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -272,6 +272,12 @@ public abstract class PlayerList { +@@ -274,6 +274,12 @@ public abstract class PlayerList { this.playersByUUID.put(player.getUUID(), player); // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below @@ -75,9 +75,9 @@ index e043722436492140162940770c22be47690fb47f..454d60566743e02e7e55868c7bb45e30 + mountSavedVehicle(player, worldserver1, nbttagcompound); + // Paper end // CraftBukkit start - PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - cserver.getPluginManager().callEvent(playerJoinEvent); -@@ -307,6 +313,8 @@ public abstract class PlayerList { + PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(this.cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + this.cserver.getPluginManager().callEvent(playerJoinEvent); +@@ -309,6 +315,8 @@ public abstract class PlayerList { player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); } player.sentListPacket = true; @@ -86,64 +86,34 @@ index e043722436492140162940770c22be47690fb47f..454d60566743e02e7e55868c7bb45e30 // CraftBukkit end player.connection.send(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn -@@ -332,6 +340,11 @@ public abstract class PlayerList { +@@ -334,6 +342,11 @@ public abstract class PlayerList { playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect)); } + // Paper start - move vehicle into method so it can be called above - short circuit around that code + onPlayerJoinFinish(player, worldserver1, s1); + } -+ private void mountSavedVehicle(ServerPlayer entityplayer, ServerLevel worldserver1, CompoundTag nbttagcompound) { ++ private void mountSavedVehicle(ServerPlayer player, ServerLevel worldserver1, CompoundTag nbttagcompound) { + // Paper end if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) { CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); // CraftBukkit start -@@ -354,20 +367,20 @@ public abstract class PlayerList { - Entity entity1; - - if (entity.getUUID().equals(uuid)) { -- player.startRiding(entity, true); -+ entityplayer.startRiding(entity, true); - } else { - iterator1 = entity.getIndirectPassengers().iterator(); - - while (iterator1.hasNext()) { - entity1 = (Entity) iterator1.next(); - if (entity1.getUUID().equals(uuid)) { -- player.startRiding(entity1, true); -+ entityplayer.startRiding(entity1, true); - break; - } - } - } - -- if (!player.isPassenger()) { -+ if (!entityplayer.isPassenger()) { - PlayerList.LOGGER.warn("Couldn't reattach entity to player"); - worldserver1.despawn(entity); - iterator1 = entity.getIndirectPassengers().iterator(); -@@ -380,16 +393,20 @@ public abstract class PlayerList { +@@ -382,6 +395,10 @@ public abstract class PlayerList { } } -- player.initMenu(); + // Paper start + } -+ public void onPlayerJoinFinish(ServerPlayer entityplayer, ServerLevel worldserver1, String s1) { ++ public void onPlayerJoinFinish(ServerPlayer player, ServerLevel worldserver1, String s1) { + // Paper end -+ entityplayer.initMenu(); + player.initInventoryMenu(); + // CraftBukkit - Moved from above, added world // Paper start - Add to collideRule team if needed - final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); - final PlayerTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName); -- if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) { -- scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); -+ if (this.collideRuleTeamName != null && collideRuleTeam != null && entityplayer.getTeam() == null) { -+ scoreboard.addPlayerToTeam(entityplayer.getScoreboardName(), collideRuleTeam); +@@ -391,6 +408,7 @@ public abstract class PlayerList { + scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); } // Paper end - // CraftBukkit - Moved from above, added world -- PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.worldDataServer.getLevelName(), player.getX(), player.getY(), player.getZ()); -+ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getName().getString(), s1, entityplayer.getId(), worldserver1.worldDataServer.getLevelName(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()); ++ // CraftBukkit - Moved from above, added world + PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ()); } - public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) { diff --git a/patches/server/0408-Load-Chunks-for-Login-Asynchronously.patch b/patches/server/0408-Load-Chunks-for-Login-Asynchronously.patch new file mode 100644 index 0000000000..399eeca8a3 --- /dev/null +++ b/patches/server/0408-Load-Chunks-for-Login-Asynchronously.patch @@ -0,0 +1,277 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 19 Apr 2020 04:28:29 -0400 +Subject: [PATCH] Load Chunks for Login Asynchronously + + +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index e4f5f564892836a2e925f419e8fcb60c70b21a47..afc9431b61f2953229765ef90005b7968fbed591 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -630,7 +630,7 @@ public class ServerChunkCache extends ChunkSource { + return this.mainThreadProcessor.pollTask(); + } + +- boolean runDistanceManagerUpdates() { ++ public boolean runDistanceManagerUpdates() { // Paper - packate-private -> public + boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); + boolean flag1 = this.chunkMap.promoteChunkMap(); + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index a30840b74bc2574725c42735f633630d9b471d54..d4ec913a96c5f8f9780d78f6f340d844718a5849 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -177,6 +177,7 @@ public class ServerPlayer extends Player { + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; + public ServerGamePacketListenerImpl connection; ++ public net.minecraft.network.Connection networkManager; // Paper + public final MinecraftServer server; + public final ServerPlayerGameMode gameMode; + private final PlayerAdvancements advancements; +@@ -238,6 +239,7 @@ public class ServerPlayer extends Player { + public boolean joining = true; + public boolean sentListPacket = false; + public boolean supressTrackerForLogin = false; // Paper ++ public boolean didPlayerJoinEvent = false; // Paper + public Integer clientViewDistance; + // CraftBukkit end + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper +diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java +index be677d437d17b74c6188ce1bd5fc6fdc228fd92f..78fbb4c3e52e900956ae0811aaf934c81ee5ea48 100644 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -23,6 +23,7 @@ public class TicketType { + public static final TicketType FORCED = TicketType.create("forced", Comparator.comparingLong(ChunkPos::toLong)); + public static final TicketType LIGHT = TicketType.create("light", Comparator.comparingLong(ChunkPos::toLong)); + public static final TicketType PORTAL = TicketType.create("portal", Vec3i::compareTo, 300); ++ public static final TicketType LOGIN = create("login", Long::compareTo, 100); // Paper + public static final TicketType POST_TELEPORT = TicketType.create("post_teleport", Integer::compareTo, 5); + public static final TicketType UNKNOWN = TicketType.create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); + public static final TicketType PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index fcfd57fd7af655aafb330986e8f6f9cc55819165..1263e845a56e96920c71a7ef636ad3437a70c06f 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -221,6 +221,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + private static final int LATENCY_CHECK_INTERVAL = 15000; + public final Connection connection; + private final MinecraftServer server; ++ public Runnable playerJoinReady; // Paper + public ServerPlayer player; + private int tickCount; + private long keepAliveTime = Util.getMillis(); +@@ -295,6 +296,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + // CraftBukkit end + + public void tick() { ++ // Paper start - login async ++ Runnable playerJoinReady = this.playerJoinReady; ++ if (playerJoinReady != null) { ++ this.playerJoinReady = null; ++ playerJoinReady.run(); ++ } ++ // Don't tick if not valid (dead), otherwise we load chunks below ++ if (this.player.valid) { ++ // Paper end + this.resetPosition(); + this.player.xo = this.player.getX(); + this.player.yo = this.player.getY(); +@@ -336,7 +346,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + this.lastVehicle = null; + this.clientVehicleIsFloating = false; + this.aboveGroundVehicleTickCount = 0; +- } ++ }} // Paper - end if (valid) + + this.server.getProfiler().push("keepAlive"); + // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 46432534fddbbf78e3bf46385b9638d2f92c951f..49308829885a473906d58fb17797127faabfcf31 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -88,7 +88,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + // Paper end + } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { +- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); ++ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper + + if (entityplayer == null) { + this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT; +@@ -194,7 +194,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + + this.connection.send(new ClientboundGameProfilePacket(this.gameProfile)); +- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); ++ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper + + try { + ServerPlayer entityplayer1 = this.server.getPlayerList().processLogin(this.gameProfile, s); // CraftBukkit - add player reference +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 3a13c151066c8784fdc844e1d6310f77ff32e7f1..c4242a1602bbb02541c330bc02016f15c8644358 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -38,6 +38,7 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; + import net.minecraft.network.protocol.game.ClientboundChatPacket; + import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; ++import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; + import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; + import net.minecraft.network.protocol.game.ClientboundGameEventPacket; + import net.minecraft.network.protocol.game.ClientboundInitializeBorderPacket; +@@ -127,11 +128,12 @@ public abstract class PlayerList { + private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); + private final MinecraftServer server; + public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety +- private final Map playersByUUID = Maps.newHashMap(); ++ private final Map playersByUUID = Maps.newHashMap();Map getUUIDMap() { return playersByUUID; } // Paper - OBFHELPER + private final UserBanList bans; + private final IpBanList ipBans; + private final ServerOpList ops; + private final UserWhiteList whitelist; ++ private final Map pendingPlayers = Maps.newHashMap(); // Paper + // CraftBukkit start + // private final Map o; + // private final Map p; +@@ -170,6 +172,11 @@ public abstract class PlayerList { + } + + public void placeNewPlayer(Connection connection, ServerPlayer player) { ++ ServerPlayer prev = pendingPlayers.put(player.getUUID(), player);// Paper ++ if (prev != null) { ++ disconnectPendingPlayer(prev); ++ } ++ player.networkManager = connection; // Paper + player.loginTime = System.currentTimeMillis(); // Paper + GameProfile gameprofile = player.getGameProfile(); + GameProfileCache usercache = this.server.getProfileCache(); +@@ -183,7 +190,7 @@ public abstract class PlayerList { + if (nbttagcompound != null && nbttagcompound.contains("bukkit")) { + CompoundTag bukkit = nbttagcompound.getCompound("bukkit"); + s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; +- } ++ }String lastKnownName = s; // Paper + // CraftBukkit end + + if (nbttagcompound != null) { +@@ -257,6 +264,52 @@ public abstract class PlayerList { + player.getRecipeBook().sendInitialRecipeBook(player); + this.updateEntireScoreboard(worldserver1.getScoreboard(), player); + this.server.invalidateStatus(); ++ // Paper start - async load spawn in chunk ++ ServerLevel finalWorldserver = worldserver1; ++ int chunkX = loc.getBlockX() >> 4; ++ int chunkZ = loc.getBlockZ() >> 4; ++ final net.minecraft.world.level.ChunkPos pos = new net.minecraft.world.level.ChunkPos(chunkX, chunkZ); ++ net.minecraft.server.level.ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; ++ net.minecraft.server.level.DistanceManager distanceManager = playerChunkMap.distanceManager; ++ distanceManager.addTicketAtLevel(net.minecraft.server.level.TicketType.LOGIN, pos, 31, pos.toLong()); ++ worldserver1.getChunkSource().runDistanceManagerUpdates(); ++ worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { ++ net.minecraft.server.level.ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); ++ if (updatingChunk != null) { ++ return updatingChunk.getEntityTickingFuture(); ++ } else { ++ return java.util.concurrent.CompletableFuture.completedFuture(chunk); ++ } ++ }).thenAccept(chunk -> { ++ playerconnection.playerJoinReady = () -> { ++ postChunkLoadJoin( ++ player, finalWorldserver, connection, playerconnection, ++ nbttagcompound, connection.getRemoteAddress().toString(), lastKnownName ++ ); ++ }; ++ }); ++ } ++ ++ public ServerPlayer getActivePlayer(UUID uuid) { ++ ServerPlayer player = this.getUUIDMap().get(uuid); ++ return player != null ? player : pendingPlayers.get(uuid); ++ } ++ ++ void disconnectPendingPlayer(ServerPlayer entityplayer) { ++ TranslatableComponent msg = new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0]); ++ entityplayer.networkManager.send(new ClientboundDisconnectPacket(msg), (future) -> { ++ entityplayer.networkManager.disconnect(msg); ++ entityplayer.networkManager = null; ++ }); ++ } ++ ++ private void postChunkLoadJoin(ServerPlayer player, ServerLevel worldserver1, Connection networkmanager, ServerGamePacketListenerImpl playerconnection, CompoundTag nbttagcompound, String s1, String s) { ++ pendingPlayers.remove(player.getUUID(), player); ++ if (!networkmanager.isConnected()) { ++ return; ++ } ++ player.didPlayerJoinEvent = true; ++ // Paper end + TranslatableComponent chatmessage; + + if (player.getGameProfile().getName().equalsIgnoreCase(s)) { +@@ -495,6 +548,7 @@ public abstract class PlayerList { + + protected void save(ServerPlayer player) { + if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit ++ if (!player.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) + this.playerIo.save(player); + ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit + +@@ -522,7 +576,7 @@ public abstract class PlayerList { + } + + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(this.cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); +- this.cserver.getPluginManager().callEvent(playerQuitEvent); ++ if (entityplayer.didPlayerJoinEvent) this.cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + + if (server.isSameThread()) entityplayer.doTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) +@@ -567,6 +621,13 @@ public abstract class PlayerList { + // this.p.remove(uuid); + // CraftBukkit end + } ++ // Paper start ++ entityplayer1 = pendingPlayers.get(uuid); ++ if (entityplayer1 == entityplayer) { ++ pendingPlayers.remove(uuid); ++ } ++ entityplayer.networkManager = null; ++ // Paper end + + // CraftBukkit start + // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[]{entityplayer})); +@@ -584,7 +645,7 @@ public abstract class PlayerList { + this.cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); + // CraftBukkit end + +- return playerQuitEvent.quitMessage(); // Paper - Adventure ++ return entityplayer.didPlayerJoinEvent ? playerQuitEvent.quitMessage() : null; // CraftBukkit // Paper - Adventure // Paper - don't print quit if we never printed join + } + + // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer +@@ -603,6 +664,13 @@ public abstract class PlayerList { + list.add(entityplayer); + } + } ++ // Paper start - check pending players too ++ entityplayer = pendingPlayers.get(uuid); ++ if (entityplayer != null) { ++ this.pendingPlayers.remove(uuid); ++ disconnectPendingPlayer(entityplayer); ++ } ++ // Paper end + + Iterator iterator = list.iterator(); + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 85c0656ee8c91cab1e269daea631977c4284295f..ac5f0bf573cbb5aa19dd3326f412010286de4378 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1490,7 +1490,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + this.yo = y; + this.zo = d4; + this.setPos(d3, y, d4); +- this.level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit ++ if (valid) this.level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit // Paper + } + + public void moveTo(Vec3 pos) { diff --git a/patches/server-remapped/0454-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/patches/server/0409-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch similarity index 79% rename from patches/server-remapped/0454-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch rename to patches/server/0409-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch index eeaa3a49f4..ed5d792bee 100644 --- a/patches/server-remapped/0454-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch +++ b/patches/server/0409-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch @@ -7,10 +7,10 @@ The code following this has better support for null worlds to move them back to the world spawn. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 9f0371282f5829d26dc9618c3d466bccaa4cd3af..34226102c50a4353c42e68917d41c44d251e602f 100644 +index ac5f0bf573cbb5aa19dd3326f412010286de4378..1ab073aaacbf6af35f97a7d3b0d8ae078335f9a6 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1808,9 +1808,11 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1979,9 +1979,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n bworld = server.getWorld(worldName); } @@ -23,5 +23,5 @@ index 9f0371282f5829d26dc9618c3d466bccaa4cd3af..34226102c50a4353c42e68917d41c44d +// } + // Paper end - Move player to spawn point if spawn in unloaded world - setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle()); + ((ServerPlayer) this).setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle()); } diff --git a/patches/server-remapped/0455-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server/0410-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 92% rename from patches/server-remapped/0455-Add-PlayerAttackEntityCooldownResetEvent.patch rename to patches/server/0410-Add-PlayerAttackEntityCooldownResetEvent.patch index f1eab97e33..8ef5ac518f 100644 --- a/patches/server-remapped/0455-Add-PlayerAttackEntityCooldownResetEvent.patch +++ b/patches/server/0410-Add-PlayerAttackEntityCooldownResetEvent.patch @@ -5,10 +5,10 @@ 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 46b962183e2e27ed93054ad9fb6d8ecbf70bc5f9..cec1e6105b8c2ac3d1482c00482d53d6be0d38d1 100644 +index 0fd79c399e723b5a9db04c8f2fe7b6ec66c0cf44..3a83cbe8fb1a5bfc7e7b699686b92561bf0cdba0 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1928,7 +1928,16 @@ public abstract class LivingEntity extends Entity { +@@ -2033,7 +2033,16 @@ public abstract class LivingEntity extends Entity { 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) { diff --git a/patches/server-remapped/0456-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/patches/server/0411-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch similarity index 63% rename from patches/server-remapped/0456-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch rename to patches/server/0411-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch index 025b5a9d8e..1ad36331ec 100644 --- a/patches/server-remapped/0456-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch +++ b/patches/server/0411-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch @@ -14,45 +14,35 @@ Use an ArrayDeque to store this Queue We make sure to also implement a pattern that is recursion safe too. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 97a582614ad28f9fa864ae9be4860658e5979214..6c7af93cead523830d32b007cc69b313e59abef1 100644 +index 2cb807f7095648948527b5b9151770193970cc00..7fa35cba408d036e649e6d63bace88e6047c02b4 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -160,24 +160,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -172,15 +172,27 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public final CallbackExecutor callbackExecutor = new CallbackExecutor(); public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { -- private Runnable queued; +- private final java.util.Queue queue = new java.util.ArrayDeque<>(); + // Paper start - replace impl with recursive safe multi entry queue + // it's possible to schedule multiple tasks currently, so it's vital we change this impl + // If we recurse into the executor again, we will append to another queue, ensuring task order consistency -+ private java.util.ArrayDeque queued = new java.util.ArrayDeque<>(); ++ private java.util.Queue queue = new java.util.ArrayDeque<>(); // Paper - remove final @Override public void execute(Runnable runnable) { -- if (queued != null) { -- throw new IllegalStateException("Already queued"); -+ if (queued == null) { -+ queued = new java.util.ArrayDeque<>(); - } -- queued = runnable; -+ queued.add(runnable); ++ if (this.queue == null) { ++ this.queue = new java.util.ArrayDeque<>(); ++ } + this.queue.add(runnable); } @Override public void run() { -- Runnable task = queued; -+ if (queued == null) { ++ if (this.queue == null) { + return; + } -+ java.util.ArrayDeque queue = queued; - queued = null; -- if (task != null) { -+ Runnable task; -+ while ((task = queue.pollFirst()) != null) { ++ java.util.Queue queue = this.queue; ++ this.queue = null; ++ // Paper end + Runnable task; + while ((task = this.queue.poll()) != null) { task.run(); - } - } -+ // Paper end - }; - // CraftBukkit end - diff --git a/patches/server-remapped/0457-Don-t-fire-BlockFade-on-worldgen-threads.patch b/patches/server/0412-Don-t-fire-BlockFade-on-worldgen-threads.patch similarity index 80% rename from patches/server-remapped/0457-Don-t-fire-BlockFade-on-worldgen-threads.patch rename to patches/server/0412-Don-t-fire-BlockFade-on-worldgen-threads.patch index 8997a0897d..fe13efc946 100644 --- a/patches/server-remapped/0457-Don-t-fire-BlockFade-on-worldgen-threads.patch +++ b/patches/server/0412-Don-t-fire-BlockFade-on-worldgen-threads.patch @@ -6,18 +6,18 @@ Subject: [PATCH] Don't fire BlockFade on worldgen threads Caused a deadlock diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java -index 31b6c1333c7d0af28385e804e94348cef398748b..ac63c5bef5b35b158e57835d765bbdd15fc60664 100644 +index ad0b485dbc77717f16191d6950a2e91faaede94a..c86bf175853197dceaa91a2287ef51de87b9d5f9 100644 --- a/src/main/java/net/minecraft/world/level/block/FireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java -@@ -93,6 +93,7 @@ public class FireBlock extends BaseFireBlock { +@@ -100,6 +100,7 @@ public class FireBlock extends BaseFireBlock { @Override - public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { + public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { // CraftBukkit start + if (!(world instanceof ServerLevel)) return this.canSurvive(state, world, pos) ? (BlockState) this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)) : Blocks.AIR.defaultBlockState(); // Paper - don't fire events in world generation if (!this.canSurvive(state, world, pos)) { // Suppress during worldgen if (!(world instanceof Level)) { -@@ -108,7 +109,7 @@ public class FireBlock extends BaseFireBlock { +@@ -115,7 +116,7 @@ public class FireBlock extends BaseFireBlock { return blockState.getHandle(); } } diff --git a/patches/server-remapped/0458-Add-phantom-creative-and-insomniac-controls.patch b/patches/server/0413-Add-phantom-creative-and-insomniac-controls.patch similarity index 68% rename from patches/server-remapped/0458-Add-phantom-creative-and-insomniac-controls.patch rename to patches/server/0413-Add-phantom-creative-and-insomniac-controls.patch index 9a052de409..6b22ec66cb 100644 --- a/patches/server-remapped/0458-Add-phantom-creative-and-insomniac-controls.patch +++ b/patches/server/0413-Add-phantom-creative-and-insomniac-controls.patch @@ -5,53 +5,40 @@ Subject: [PATCH] Add phantom creative and insomniac controls diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index cd248eb6be663e8be33f2c3c6b06b77b6d5753a4..46ac6d91422423f1e03b86d3efa3241f2599000d 100644 +index 9664786d471b949880030f5c6271bf9c12529326..45058c715152e3ffa5ec1c79a472e32d63d69e02 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -625,4 +625,11 @@ public class PaperWorldConfig { - private void lightQueueSize() { +@@ -472,6 +472,13 @@ public class PaperWorldConfig { lightQueueSize = getInt("light-queue-size", lightQueueSize); } -+ + + public boolean phantomIgnoreCreative = true; + public boolean phantomOnlyAttackInsomniacs = true; + private void phantomSettings() { + phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); + phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); + } - } ++ + public int noTickViewDistance; + private void viewDistance() { + this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index e7facd849e3511c64b4ae44b34382f4a4985f2a4..8ce62148ebaeac9988e7c9d4b2f7ee57f58d883e 100644 +index d17b75ad13bbc8a38cdc2f2d77ee5d88438cec31..8fb89326395a7e70982c0d757b506565e98b12a4 100644 --- a/src/main/java/net/minecraft/world/entity/EntitySelector.java +++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -3,6 +3,9 @@ package net.minecraft.world.entity; - import com.google.common.base.Predicates; - import java.util.function.Predicate; - import javax.annotation.Nullable; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.stats.Stats; -+import net.minecraft.util.Mth; - import net.minecraft.world.Container; - import net.minecraft.world.Difficulty; - import net.minecraft.world.entity.player.Player; -@@ -31,10 +34,11 @@ public final class EntitySelector { +@@ -26,6 +26,7 @@ public final class EntitySelector { public static final Predicate NO_SPECTATORS = (entity) -> { return !entity.isSpectator(); }; -+ public static Predicate isInsomniac = (player) -> Mth.clamp(((ServerPlayer) player).getStats().getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper ++ public static Predicate isInsomniac = (player) -> net.minecraft.util.Mth.clamp(((net.minecraft.server.level.ServerPlayer) player).getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper + private EntitySelector() {} // Paper start - public static final Predicate affectsSpawning = (entity) -> { -- return !entity.isSpectator() && entity.isAlive() && (entity instanceof EntityPlayer) && ((EntityPlayer) entity).affectsSpawning; -+ return !entity.isSpectator() && entity.isAlive() && (entity instanceof ServerPlayer) && ((ServerPlayer) entity).affectsSpawning; - }; - // Paper end - diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index e37137a2890330b92e05d6f76c46ffc99a527803..a40c23e824652cff59633b7c314e27ec9a515c07 100644 +index 2ddb7b4c0a75c6f41910c84c8b9341f56fcb1116..941f86b04fedaf1e3f5d04c9aa8c1cd74da9b7a2 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java +++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -@@ -262,6 +262,7 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -547,6 +547,7 @@ public class Phantom extends FlyingMob implements Enemy { Player entityhuman = (Player) iterator.next(); if (Phantom.this.canAttack((LivingEntity) entityhuman, TargetingConditions.DEFAULT)) { diff --git a/patches/server-remapped/0459-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/patches/server/0414-Fix-numerous-item-duplication-issues-and-teleport-is.patch similarity index 85% rename from patches/server-remapped/0459-Fix-numerous-item-duplication-issues-and-teleport-is.patch rename to patches/server/0414-Fix-numerous-item-duplication-issues-and-teleport-is.patch index 9e378d1d32..b1c5df36ef 100644 --- a/patches/server-remapped/0459-Fix-numerous-item-duplication-issues-and-teleport-is.patch +++ b/patches/server/0414-Fix-numerous-item-duplication-issues-and-teleport-is.patch @@ -16,10 +16,10 @@ So even if something NEW comes up, it would be impossible to drop the same item twice because the source was destroyed. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 34226102c50a4353c42e68917d41c44d251e602f..2b48c4a2b512c42bed2c767db90a28898c74286a 100644 +index 1ab073aaacbf6af35f97a7d3b0d8ae078335f9a6..9897a0ac66dd788b0b22a88b20ca86a386e397e4 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1973,11 +1973,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2125,11 +2125,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } else { // CraftBukkit start - Capture drops for death event if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) { @@ -34,7 +34,7 @@ index 34226102c50a4353c42e68917d41c44d251e602f..2b48c4a2b512c42bed2c767db90a2889 entityitem.setDefaultPickUpDelay(); // CraftBukkit start -@@ -2625,6 +2626,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2873,6 +2874,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @Nullable public Entity teleportTo(ServerLevel worldserver, BlockPos location) { // CraftBukkit end @@ -44,10 +44,10 @@ index 34226102c50a4353c42e68917d41c44d251e602f..2b48c4a2b512c42bed2c767db90a2889 + return null; + } + // Paper end - if (this.level instanceof ServerLevel && !this.removed) { + if (this.level instanceof ServerLevel && !this.isRemoved()) { this.level.getProfiler().push("changeDimension"); // CraftBukkit start -@@ -2645,6 +2652,11 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2893,6 +2900,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n // CraftBukkit end this.level.getProfiler().popPush("reloading"); @@ -59,7 +59,7 @@ index 34226102c50a4353c42e68917d41c44d251e602f..2b48c4a2b512c42bed2c767db90a2889 Entity entity = this.getType().create((Level) worldserver); if (entity != null) { -@@ -2658,10 +2670,6 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2906,10 +2918,6 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n // CraftBukkit start - Forward the CraftEntity to the new entity this.getBukkitEntity().setHandle(entity); entity.bukkitEntity = this.getBukkitEntity(); @@ -70,7 +70,7 @@ index 34226102c50a4353c42e68917d41c44d251e602f..2b48c4a2b512c42bed2c767db90a2889 // CraftBukkit end } -@@ -2786,7 +2794,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -3034,7 +3042,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } public boolean canChangeDimensions() { @@ -80,10 +80,10 @@ index 34226102c50a4353c42e68917d41c44d251e602f..2b48c4a2b512c42bed2c767db90a2889 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/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 33d51852ed6fe3f5adcdecf8f405a23689f4265a..5714aa450ac09788bcf1c2790d4f1581c9a7c28b 100644 +index cb9969d768b13863722aad3dc5daad3c10bb264a..5bfec185e15a54ee5fe6eab1aa59d1963d046262 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -598,7 +598,7 @@ public class ArmorStand extends LivingEntity { +@@ -611,7 +611,7 @@ public class ArmorStand extends LivingEntity { for (i = 0; i < this.handItems.size(); ++i) { itemstack = (ItemStack) this.handItems.get(i); if (!itemstack.isEmpty()) { @@ -92,7 +92,7 @@ index 33d51852ed6fe3f5adcdecf8f405a23689f4265a..5714aa450ac09788bcf1c2790d4f1581 this.handItems.set(i, ItemStack.EMPTY); } } -@@ -606,7 +606,7 @@ public class ArmorStand extends LivingEntity { +@@ -619,7 +619,7 @@ public class ArmorStand extends LivingEntity { for (i = 0; i < this.armorItems.size(); ++i) { itemstack = (ItemStack) this.armorItems.get(i); if (!itemstack.isEmpty()) { @@ -102,10 +102,10 @@ index 33d51852ed6fe3f5adcdecf8f405a23689f4265a..5714aa450ac09788bcf1c2790d4f1581 } } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 7d9a3b65b2d6b294d3a11414289e64fac88665f0..87fe7f4f5ed70bf1b3dc1e2a392ba42a1f8f568b 100644 +index 98bec353d6dbd85c7b329f75e09f4d0bfcfdaa6c..7d43439a13bd109399691ddec60ee99c818db198 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -815,7 +815,8 @@ public class CraftEventFactory { +@@ -807,7 +807,8 @@ public class CraftEventFactory { for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { if (stack == null || stack.getType() == Material.AIR || stack.getAmount() == 0) continue; diff --git a/patches/server-remapped/0460-Implement-Brigadier-Mojang-API.patch b/patches/server/0415-Implement-Brigadier-Mojang-API.patch similarity index 86% rename from patches/server-remapped/0460-Implement-Brigadier-Mojang-API.patch rename to patches/server/0415-Implement-Brigadier-Mojang-API.patch index 5504aee900..c73a8699ba 100644 --- a/patches/server-remapped/0460-Implement-Brigadier-Mojang-API.patch +++ b/patches/server/0415-Implement-Brigadier-Mojang-API.patch @@ -9,8 +9,20 @@ Adds AsyncPlayerSendCommandsEvent Adds CommandRegisteredEvent - Allows manipulating the CommandNode to add more children/metadata for the client +diff --git a/build.gradle.kts b/build.gradle.kts +index f0256fe4aea16c9e0d6f5eee360eeec36cfdeebd..2543a4cf2bb58c2265cfc427c427b683d2ff70ca 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -21,6 +21,7 @@ repositories { + + dependencies { + implementation(project(":Paper-API")) ++ implementation(project(":Paper-MojangAPI")) + // Paper start + implementation("org.jline:jline-terminal-jansi:3.12.1") + implementation("net.minecrell:terminalconsoleappender:1.2.0") diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java -index f74765f31bc7272724ee7fac0cc5a8c852550006..e1f4ffaa36bfffb7741c74b7a094e26a03a9a1e6 100644 +index 60b503dd85706bd2593a5e9d3314540ff1012652..42d97bc67c8f4e5b65a81159179c43dc6edc804c 100644 --- a/src/main/java/net/minecraft/commands/CommandSourceStack.java +++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java @@ -37,7 +37,7 @@ import net.minecraft.world.phys.Vec2; @@ -22,7 +34,7 @@ index f74765f31bc7272724ee7fac0cc5a8c852550006..e1f4ffaa36bfffb7741c74b7a094e26a public static final SimpleCommandExceptionType ERROR_NOT_PLAYER = new SimpleCommandExceptionType(new TranslatableComponent("permissions.requires.player")); public static final SimpleCommandExceptionType ERROR_NOT_ENTITY = new SimpleCommandExceptionType(new TranslatableComponent("permissions.requires.entity")); -@@ -149,6 +149,25 @@ public class CommandSourceStack implements SharedSuggestionProvider { +@@ -153,6 +153,25 @@ public class CommandSourceStack implements SharedSuggestionProvider { return this.textName; } @@ -49,10 +61,10 @@ index f74765f31bc7272724ee7fac0cc5a8c852550006..e1f4ffaa36bfffb7741c74b7a094e26a public boolean hasPermission(int level) { // CraftBukkit start diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java -index 8154d9327c5411bbfea3bfa4d99d57feab764664..c63033e3eb50423a7c32acfc0e705623cc4bec68 100644 +index 13e358e0eac3bfd426d924b6f745e001df76c64a..7156dea53be828acd01734fa1f9f7b9accf30ff6 100644 --- a/src/main/java/net/minecraft/commands/Commands.java +++ b/src/main/java/net/minecraft/commands/Commands.java -@@ -355,6 +355,7 @@ public class Commands { +@@ -362,6 +362,7 @@ public class Commands { bukkit.add(node.getName()); } // Paper start - Async command map building @@ -60,7 +72,7 @@ index 8154d9327c5411bbfea3bfa4d99d57feab764664..c63033e3eb50423a7c32acfc0e705623 MinecraftServer.getServer().execute(() -> { runSync(entityplayer, bukkit, rootcommandnode); }); -@@ -362,6 +363,7 @@ public class Commands { +@@ -369,6 +370,7 @@ public class Commands { private void runSync(ServerPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { // Paper end - Async command map building @@ -69,17 +81,17 @@ index 8154d9327c5411bbfea3bfa4d99d57feab764664..c63033e3eb50423a7c32acfc0e705623 event.getPlayer().getServer().getPluginManager().callEvent(event); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 1bed6e69bf3cc1ab9b0c1259de4f643bf58371aa..5f12987b93f1578624626c4e911d1757dee3d45f 100644 +index 1263e845a56e96920c71a7ef636ad3437a70c06f..fbb33cfa62723ac1fd6f426969e747e49abc8ea6 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -768,8 +768,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -760,8 +760,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { - if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer - this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); + // Paper start -+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); ++ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getCraftPlayer(), suggestions, buffer); + suggestEvent.setCancelled(suggestions.isEmpty()); + if (!suggestEvent.callEvent()) return; + this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), (com.mojang.brigadier.suggestion.Suggestions) suggestEvent.getSuggestions())); // CraftBukkit - decompile error // Paper @@ -87,13 +99,13 @@ index 1bed6e69bf3cc1ab9b0c1259de4f643bf58371aa..5f12987b93f1578624626c4e911d1757 }); }); } -@@ -778,7 +782,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -770,7 +774,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); completions.forEach(builder::suggest); - player.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), builder.buildFuture().join())); + com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); -+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); ++ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getCraftPlayer(), suggestions, buffer); + suggestEvent.setCancelled(suggestions.isEmpty()); + if (!suggestEvent.callEvent()) return; + this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestEvent.getSuggestions())); @@ -101,7 +113,7 @@ index 1bed6e69bf3cc1ab9b0c1259de4f643bf58371aa..5f12987b93f1578624626c4e911d1757 // Paper end - async tab completion } diff --git a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -index f9a245503c8982d1756503a6179f3715d919d910..b17002abdb43e74da4eb61e65e45c5e0e1dc0f95 100644 +index 21971d52fa8ed92c946c519ba93a39aceae10f5f..0bba36d18d56a4dc2d6c6fb7969e5e6f0e1da404 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java +++ b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java @@ -17,7 +17,7 @@ import net.minecraft.commands.CommandSourceStack; diff --git a/patches/server-remapped/0461-Villager-Restocks-API.patch b/patches/server/0416-Villager-Restocks-API.patch similarity index 60% rename from patches/server-remapped/0461-Villager-Restocks-API.patch rename to patches/server/0416-Villager-Restocks-API.patch index 49b6ff50fa..3f24c8fdfe 100644 --- a/patches/server-remapped/0461-Villager-Restocks-API.patch +++ b/patches/server/0416-Villager-Restocks-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Villager Restocks API diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 4aa34320ef7d6c62ccb17734bfa61d406190b919..a83a7d37f3d769535161fda46fca6f71dcc4d515 100644 +index a35ce224b11b44567814207c3821d0cd4cdd9ec1..e99cdbb1d050288b5f1177737b242c331a989471 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -112,7 +112,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -127,7 +127,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler private long lastGossipDecayTime; private int villagerXp; private long lastRestockGameTime; @@ -16,13 +16,13 @@ index 4aa34320ef7d6c62ccb17734bfa61d406190b919..a83a7d37f3d769535161fda46fca6f71 + private int numberOfRestocksToday; public int getRestocksToday(){ return this.numberOfRestocksToday; } public void setRestocksToday(int restocksToday){ this.numberOfRestocksToday = restocksToday; } // Paper OBFHELPER private long lastRestockCheckDayTime; private boolean assignProfessionWhenSpawned; - private static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.MOBS, MemoryModuleType.VISIBLE_MOBS, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.WALK_TARGET, new MemoryModuleType[]{MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); + private static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.WALK_TARGET, new MemoryModuleType[]{MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index 5a21e9447c3e0225b07144eec83c277dd101bfd5..d0b933cfd02b237bfe85011831dab6e8e966496e 100644 +index 40815c2500a1b4946c502b8ae7f80c4e93e556ae..115f107ac100524ef0fcf8de0fc528d164c845f7 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java @@ -83,6 +83,18 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { - getHandle().setVillagerXp(experience); + this.getHandle().setVillagerXp(experience); } + // Paper start diff --git a/patches/server-remapped/0462-Validate-PickItem-Packet-and-kick-for-invalid.patch b/patches/server/0417-Validate-PickItem-Packet-and-kick-for-invalid.patch similarity index 65% rename from patches/server-remapped/0462-Validate-PickItem-Packet-and-kick-for-invalid.patch rename to patches/server/0417-Validate-PickItem-Packet-and-kick-for-invalid.patch index 34909e54c5..348bbe236c 100644 --- a/patches/server-remapped/0462-Validate-PickItem-Packet-and-kick-for-invalid.patch +++ b/patches/server/0417-Validate-PickItem-Packet-and-kick-for-invalid.patch @@ -5,22 +5,22 @@ Subject: [PATCH] Validate PickItem Packet and kick for invalid diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 5f12987b93f1578624626c4e911d1757dee3d45f..3f416479e23c60ec5b4b779cce9ab62c74865ac8 100644 +index fbb33cfa62723ac1fd6f426969e747e49abc8ea6..b5325f19458467b307db629a00359af41004124a 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -881,7 +881,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -877,7 +877,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @Override public void handlePickItem(ServerboundPickItemPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); -- this.player.inventory.pickSlot(packet.getSlot()); +- this.player.getInventory().pickSlot(packet.getSlot()); + // Paper start - validate pick item position -+ if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.inventory.items.size())) { ++ if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.getInventory().items.size())) { + ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); + this.disconnect("Invalid hotbar selection (Hacking?)"); + return; + } -+ this.player.inventory.pickSlot(packet.getSlot()); // Paper - Diff above if changed ++ this.player.getInventory().pickSlot(packet.getSlot()); // Paper - Diff above if changed + // Paper end - this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, this.player.inventory.selected, this.player.inventory.getItem(this.player.inventory.selected))); - this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, packet.getSlot(), this.player.inventory.getItem(packet.getSlot()))); - this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.inventory.selected)); + this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, this.player.getInventory().selected, this.player.getInventory().getItem(this.player.getInventory().selected))); + this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, packet.getSlot(), this.player.getInventory().getItem(packet.getSlot()))); + this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected)); diff --git a/patches/server-remapped/0463-Expose-game-version.patch b/patches/server/0418-Expose-game-version.patch similarity index 78% rename from patches/server-remapped/0463-Expose-game-version.patch rename to patches/server/0418-Expose-game-version.patch index 9e0cf63bd9..9c79c20af1 100644 --- a/patches/server-remapped/0463-Expose-game-version.patch +++ b/patches/server/0418-Expose-game-version.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Expose game version diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 43c37e660a8a7f9d326ad38e66f9aa7c53c7b87c..1bfe96443877e460d22513d59ebc3b5988e8eb43 100644 +index 4c0b94a56fab161fca92b594f55e1c846524d5e8..479b4eb8efeeca432bcb21925db18d5c0750f001 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -514,6 +514,13 @@ public final class CraftServer implements Server { - return bukkitVersion; +@@ -517,6 +517,13 @@ public final class CraftServer implements Server { + return this.bukkitVersion; } + // Paper start - expose game version diff --git a/patches/server/0419-Optimize-Voxel-Shape-Merging.patch b/patches/server/0419-Optimize-Voxel-Shape-Merging.patch new file mode 100644 index 0000000000..4227b67cdc --- /dev/null +++ b/patches/server/0419-Optimize-Voxel-Shape-Merging.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 May 2020 22:35:09 -0400 +Subject: [PATCH] Optimize Voxel Shape Merging + +This method shows up as super hot in profiler, and also a high "self" time. + +Upon analyzing, it appears most usages of this method fall down to the final +else statement of the nasty ternary. + +Upon even further analyzation, it appears then the majority of those have a +consistent list 1.... One with Infinity head and Tails. + +First optimization is to detect these infinite states and immediately return that +VoxelShapeMergerList so we can avoid testing the rest for most cases. + +Break the method into 2 to help the JVM promote inlining of this fast path. + +Then it was also noticed that VoxelShapeMergerList constructor is also a hotspot +with a high self time... + +Well, knowing that in most cases our list 1 is actualy the same value, it allows +us to know that with an infinite list1, the result on the merger is essentially +list2 as the final values. + +This let us analyze the 2 potential states (Infinite with 2 sources or 4 sources) +and compute a deterministic result for the MergerList values. + +Additionally, this lets us avoid even allocating new objects for this too, further +reducing memory usage. + +diff --git a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java +index 9e0afab2329e560c4b2512548dd4b02dd1a2e69f..06662dbff8180751a8684841aa35f709007078ae 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java +@@ -10,12 +10,33 @@ public class IndirectMerger implements IndexMerger { + private final int[] firstIndices; + private final int[] secondIndices; + private final int resultLength; ++ // Paper start ++ private static final int[] INFINITE_B_1 = new int[]{1, 1}; ++ private static final int[] INFINITE_B_0 = new int[]{0, 0}; ++ private static final int[] INFINITE_C = new int[]{0, 1}; ++ // Paper end + + public IndirectMerger(DoubleList first, DoubleList second, boolean includeFirstOnly, boolean includeSecondOnly) { + double d = Double.NaN; + int i = first.size(); + int j = second.size(); + int k = i + j; ++ // Paper start - optimize common path of infinity doublelist ++ int size = first.size(); ++ double tail = first.getDouble(size - 1); ++ double head = first.getDouble(0); ++ if (head == Double.NEGATIVE_INFINITY && tail == Double.POSITIVE_INFINITY && !includeFirstOnly && !includeSecondOnly && (size == 2 || size == 4)) { ++ this.result = second.toDoubleArray(); ++ this.resultLength = second.size(); ++ if (size == 2) { ++ this.firstIndices = INFINITE_B_0; ++ } else { ++ this.firstIndices = INFINITE_B_1; ++ } ++ this.secondIndices = INFINITE_C; ++ return; ++ } ++ // Paper end + this.result = new double[k]; + this.firstIndices = new int[k]; + this.secondIndices = new int[k]; +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index 95428f13dae909bb7de552aa65e4256bd4049c65..94f58332bb1408971fe65e5fd0401457ab986441 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -337,9 +337,21 @@ public final class Shapes { + } + + @VisibleForTesting +- protected static IndexMerger createIndexMerger(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { ++ private static IndexMerger createIndexMerger(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { // Paper - private ++ // Paper start - fast track the most common scenario ++ // doublelist is usually a DoubleArrayList with Infinite head/tails that falls to the final else clause ++ // This is actually the most common path, so jump to it straight away ++ if (first.getDouble(0) == Double.NEGATIVE_INFINITY && first.getDouble(first.size() - 1) == Double.POSITIVE_INFINITY) { ++ return new IndirectMerger(first, second, includeFirst, includeSecond); ++ } ++ // Split out rest to hopefully inline the above ++ return lessCommonMerge(size, first, second, includeFirst, includeSecond); ++ } ++ ++ private static IndexMerger lessCommonMerge(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { + int i = first.size() - 1; + int j = second.size() - 1; ++ // Paper note - Rewrite below as optimized order if instead of nasty ternary + if (first instanceof CubePointRange && second instanceof CubePointRange) { + long l = lcm(i, j); + if ((long)size * l <= 256L) { +@@ -347,13 +359,22 @@ public final class Shapes { + } + } + +- if (first.getDouble(i) < second.getDouble(0) - 1.0E-7D) { ++ // Paper start - Identical happens more often than Disjoint ++ if (i == j && Objects.equals(first, second)) { ++ if (first instanceof IdenticalMerger) { ++ return (IndexMerger) first; ++ } else if (second instanceof IdenticalMerger) { ++ return (IndexMerger) second; ++ } ++ return new IdenticalMerger(first); ++ } else if (first.getDouble(i) < second.getDouble(0) - 1.0E-7D) { + return new NonOverlappingMerger(first, second, false); + } else if (second.getDouble(j) < first.getDouble(0) - 1.0E-7D) { + return new NonOverlappingMerger(second, first, true); + } else { +- return (IndexMerger)(i == j && Objects.equals(first, second) ? new IdenticalMerger(first) : new IndirectMerger(first, second, includeFirst, includeSecond)); ++ return new IndirectMerger(first, second, includeFirst, includeSecond); + } ++ // Paper end + } + + public interface DoubleLineConsumer { diff --git a/settings.gradle.kts b/settings.gradle.kts index 54bb957497..a9d4e7b2c7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,4 +7,4 @@ pluginManagement { rootProject.name = "Paper" -include("Paper-API", "Paper-Server") +include("Paper-API", "Paper-Server", "Paper-MojangAPI") diff --git a/work/Bukkit b/work/Bukkit index 8503c3c9e3..a791f93de2 160000 --- a/work/Bukkit +++ b/work/Bukkit @@ -1 +1 @@ -Subproject commit 8503c3c9e3dca76b2ae10796d8c288b3f3101737 +Subproject commit a791f93de242bf89d116fed843b889e38433e094 diff --git a/work/CraftBukkit b/work/CraftBukkit index 40caacc846..85b8c1fda6 160000 --- a/work/CraftBukkit +++ b/work/CraftBukkit @@ -1 +1 @@ -Subproject commit 40caacc846a6349cd555d9d89cf9cf729c0b75b7 +Subproject commit 85b8c1fda69f6f80e45ddd19590846c249e5b6bc From 6c309496100484350c5b01dc5575861ecff5aac3 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 18:48:31 -0700 Subject: [PATCH 091/226] Use correct jetbrains annotations --- ...-changes.patch => 0002-Build-system-changes.patch} | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) rename patches/api/{0002-POM-changes.patch => 0002-Build-system-changes.patch} (92%) diff --git a/patches/api/0002-POM-changes.patch b/patches/api/0002-Build-system-changes.patch similarity index 92% rename from patches/api/0002-POM-changes.patch rename to patches/api/0002-Build-system-changes.patch index 6eff19161e..012a45883a 100644 --- a/patches/api/0002-POM-changes.patch +++ b/patches/api/0002-Build-system-changes.patch @@ -1,14 +1,14 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Tue, 1 Mar 2016 00:16:08 +0100 -Subject: [PATCH] POM changes +Subject: [PATCH] Build system changes diff --git a/build.gradle.kts b/build.gradle.kts -index 35b57f52fcfd91cff04dc60c3a8a16b31f775fc0..20c8a34b299ba455c29b4e31d311de0b3a063288 100644 +index 35b57f52fcfd91cff04dc60c3a8a16b31f775fc0..328fe3d7708b0e93dad080c7689d0d7cde138288 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -16,10 +16,12 @@ dependencies { +@@ -16,12 +16,14 @@ dependencies { api("com.google.code.gson:gson:2.8.0") api("net.md-5:bungeecord-chat:1.16-R0.4") api("org.yaml:snakeyaml:1.29") @@ -19,8 +19,11 @@ index 35b57f52fcfd91cff04dc60c3a8a16b31f775fc0..20c8a34b299ba455c29b4e31d311de0b compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") + compileOnly("com.google.code.findbugs:jsr305:1.3.9") // Paper - val annotations = "org.jetbrains:annotations-java5:21.0.1" +- val annotations = "org.jetbrains:annotations-java5:21.0.1" ++ val annotations = "org.jetbrains:annotations:21.0.1" // Paper - we don't want Java 5 annotations... compileOnly(annotations) + testCompileOnly(annotations) + diff --git a/pom.xml b/pom.xml index 10eeaef61be733e63f6680f1675e0b527eb30fd9..e5802bcb6fc2376cff2ee8b3069150127312b154 100644 --- a/pom.xml From 3e552cc54c48376f361b9fc908c789ed9cee824a Mon Sep 17 00:00:00 2001 From: Omer Uddin Date: Sun, 13 Jun 2021 22:41:44 -0400 Subject: [PATCH 092/226] work work (#5821) --- ...ement-alternative-item-despawn-rate.patch} | 41 +-- ...ment-optional-per-player-mob-spawns.patch} | 324 ++++++------------ 2 files changed, 124 insertions(+), 241 deletions(-) rename patches/{removed/1.17/0373-Implement-alternative-item-despawn-rate.patch => server/0362-Implement-alternative-item-despawn-rate.patch} (76%) rename patches/{removed/1.17/0376-implement-optional-per-player-mob-spawns.patch => server/0363-implement-optional-per-player-mob-spawns.patch} (66%) diff --git a/patches/removed/1.17/0373-Implement-alternative-item-despawn-rate.patch b/patches/server/0362-Implement-alternative-item-despawn-rate.patch similarity index 76% rename from patches/removed/1.17/0373-Implement-alternative-item-despawn-rate.patch rename to patches/server/0362-Implement-alternative-item-despawn-rate.patch index dde0e838a6..5db80421d3 100644 --- a/patches/removed/1.17/0373-Implement-alternative-item-despawn-rate.patch +++ b/patches/server/0362-Implement-alternative-item-despawn-rate.patch @@ -2,31 +2,29 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: kickash32 Date: Mon, 3 Jun 2019 02:02:39 -0400 Subject: [PATCH] Implement alternative item-despawn-rate -1.17: kickash32 want's to do that later + diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1ee2cced100626e48eb36ee14f84b9257c79a2f8..b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920 100644 +index 3cd8895adecd345c3bdfb8b5e3e9fdf0ef9097db..be4a36df28d4f16727daad1270d5c3a84ae94613 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -1,10 +1,15 @@ +@@ -1,8 +1,13 @@ package com.destroystokyo.paper; - import java.util.Arrays; +import java.util.EnumMap; +import java.util.HashMap; import java.util.List; +import java.util.Map; - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.spigotmc.SpigotWorldConfig; -@@ -512,4 +517,52 @@ public class PaperWorldConfig { - private void disableRelativeProjectileVelocity() { - disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); +@@ -450,5 +455,53 @@ public class PaperWorldConfig { + private void viewDistance() { + this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); } + + public boolean altItemDespawnRateEnabled; @@ -77,19 +75,12 @@ index 1ee2cced100626e48eb36ee14f84b9257c79a2f8..b913cd2dd0cd1b369b3f7b5a9d8b1be7 + } + } } + diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 281f5646980afc70890bdafd358ff9b20d32420d..96b8102773cbee2c3fe2711008ba1487084d67b0 100644 +index 9ee1dc89dd4c6b9453e1f6f92208d454877d23c9..e0c13a112c95eed9867d4608e18dc797b0c9c9cf 100644 --- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -32,6 +32,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.stats.Stats; -+import org.bukkit.Material; // Paper - import org.bukkit.event.entity.EntityPickupItemEvent; - import org.bukkit.event.player.PlayerPickupItemEvent; - // CraftBukkit end -@@ -160,7 +161,7 @@ public class ItemEntity extends Entity { +@@ -175,7 +175,7 @@ public class ItemEntity extends Entity { } } @@ -98,7 +89,7 @@ index 281f5646980afc70890bdafd358ff9b20d32420d..96b8102773cbee2c3fe2711008ba1487 // CraftBukkit start - fire ItemDespawnEvent if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { this.age = 0; -@@ -184,7 +185,7 @@ public class ItemEntity extends Entity { +@@ -199,7 +199,7 @@ public class ItemEntity extends Entity { this.lastTick = MinecraftServer.currentTick; // CraftBukkit end @@ -107,21 +98,21 @@ index 281f5646980afc70890bdafd358ff9b20d32420d..96b8102773cbee2c3fe2711008ba1487 // CraftBukkit start - fire ItemDespawnEvent if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { this.age = 0; -@@ -534,9 +535,16 @@ public class ItemEntity extends Entity { +@@ -559,9 +559,16 @@ public class ItemEntity extends Entity { public void makeFakeItem() { this.setNeverPickUp(); - this.age = level.spigotConfig.itemDespawnRate - 1; // Spigot -+ this.age = this.getDespawnRate() - 1; // Spigot // Paper ++ this.age = this.getDespawnRate() - 1; // Spigot } + // Paper start + public int getDespawnRate(){ -+ Material material = this.getItem().getBukkitStack().getType(); ++ org.bukkit.Material material = this.getItem().getBukkitStack().getType(); + return level.paperConfig.altItemDespawnRateMap.getOrDefault(material, level.spigotConfig.itemDespawnRate); + } + // Paper end + - @Override - public Packet getAddEntityPacket() { - return new ClientboundAddEntityPacket(this); + public float getSpin(float tickDelta) { + return ((float) this.getAge() + tickDelta) / 20.0F + this.bobOffs; + } diff --git a/patches/removed/1.17/0376-implement-optional-per-player-mob-spawns.patch b/patches/server/0363-implement-optional-per-player-mob-spawns.patch similarity index 66% rename from patches/removed/1.17/0376-implement-optional-per-player-mob-spawns.patch rename to patches/server/0363-implement-optional-per-player-mob-spawns.patch index ad609e6f05..c62f193d01 100644 --- a/patches/removed/1.17/0376-implement-optional-per-player-mob-spawns.patch +++ b/patches/server/0363-implement-optional-per-player-mob-spawns.patch @@ -2,13 +2,13 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: kickash32 Date: Mon, 19 Aug 2019 01:27:58 +0500 Subject: [PATCH] implement optional per player mob spawns -1.17: kickash will take a look at this; has to be figured out again because of changes + diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -index 24eac9400fbf971742e89bbf47b0ba52b587c4eb..b818a7451d45d2ab7d4678f0065ada9017d8a631 100644 +index fe79c0add4f7cb18d487c5bb9415c40c5b551ea2..8d9ddad1879e7616d980ca70de8aecacaa86db35 100644 --- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java +++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -58,6 +58,7 @@ public class WorldTimingsHandler { +@@ -57,6 +57,7 @@ public class WorldTimingsHandler { public final Timing miscMobSpawning; @@ -16,7 +16,7 @@ index 24eac9400fbf971742e89bbf47b0ba52b587c4eb..b818a7451d45d2ab7d4678f0065ada90 public final Timing poiUnload; public final Timing chunkUnload; -@@ -123,6 +124,7 @@ public class WorldTimingsHandler { +@@ -121,6 +122,7 @@ public class WorldTimingsHandler { miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); @@ -25,10 +25,10 @@ index 24eac9400fbf971742e89bbf47b0ba52b587c4eb..b818a7451d45d2ab7d4678f0065ada90 poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920..6aec502eb529d4090306e12e837117cde7e114eb 100644 +index be4a36df28d4f16727daad1270d5c3a84ae94613..16f013ffe992a934e9d0b32e764a14a8fd204449 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -565,4 +565,9 @@ public class PaperWorldConfig { +@@ -503,5 +503,10 @@ public class PaperWorldConfig { } } } @@ -38,6 +38,7 @@ index b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920..6aec502eb529d4090306e12e837117cd + perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); + } } + diff --git a/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java new file mode 100644 index 0000000000000000000000000000000000000000..2a87599922d7075a9f888f48a2deb35ed3eb7c54 @@ -296,6 +297,7 @@ index 0000000000000000000000000000000000000000..2a87599922d7075a9f888f48a2deb35e + } + } +} + diff --git a/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java new file mode 100644 index 0000000000000000000000000000000000000000..4f13d3ff8391793a99f067189f854078334499c6 @@ -542,12 +544,12 @@ index 0000000000000000000000000000000000000000..4f13d3ff8391793a99f067189f854078 + this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); + } + } -+} ++} diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index c00f7c60ce7b497d697d1abdf230f91f327e2113..190ddd4d9ef3472c33d46c2ead72fa0dc918054a 100644 +index fdf5d8ede4b01e399272ddebfbd49258b166f00b..bd4133466eb8ad2f5f69fdf5b04bc45734cec9a4 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -71,6 +71,7 @@ import net.minecraft.util.thread.ProcessorMailbox; +@@ -69,6 +69,7 @@ import net.minecraft.util.thread.ProcessorMailbox; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; @@ -555,30 +557,34 @@ index c00f7c60ce7b497d697d1abdf230f91f327e2113..190ddd4d9ef3472c33d46c2ead72fa0d import net.minecraft.world.entity.ai.village.poi.PoiManager; import net.minecraft.world.entity.boss.EnderDragonPart; import net.minecraft.world.level.ChunkPos; -@@ -127,7 +128,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public final Int2ObjectMap entityMap; +@@ -140,6 +141,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider private final Long2ByteMap chunkTypeCache; - private final Queue unloadQueue; private final Queue getUnloadQueueTasks() { return this.unloadQueue; } // Paper - OBFHELPER -- private int viewDistance; -+ int viewDistance; // Paper - private -> package private + private final Queue unloadQueue; + int viewDistance; + public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() public final CallbackExecutor callbackExecutor = new CallbackExecutor(); -@@ -206,6 +208,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.overworldDataStorage = supplier; - this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper - this.setViewDistance(i); +@@ -263,6 +265,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.overworldDataStorage = persistentStateManagerFactory; + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world); + this.setViewDistance(viewDistance); + this.playerMobDistanceMap = this.level.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper -+ } -+ + // Paper start - no-tick view distance + this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); + this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, +@@ -304,6 +307,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end - no-tick view distance + } + ++ // Paper start + public void updatePlayerMobTypeMap(Entity entity) { + if (!this.level.paperConfig.perPlayerMobSpawns) { + return; + } + int chunkX = (int)Math.floor(entity.getX()) >> 4; + int chunkZ = (int)Math.floor(entity.getZ()) >> 4; -+ int index = entity.getType().getEnumCreatureType().ordinal(); ++ int index = entity.getType().getCategory().ordinal(); + + for (ServerPlayer player : this.playerMobDistanceMap.getPlayersInRange(chunkX, chunkZ)) { + ++player.mobCounts[index]; @@ -587,14 +593,17 @@ index c00f7c60ce7b497d697d1abdf230f91f327e2113..190ddd4d9ef3472c33d46c2ead72fa0d + + public int getMobCountNear(ServerPlayer entityPlayer, MobCategory enumCreatureType) { + return entityPlayer.mobCounts[enumCreatureType.ordinal()]; - } - ++ } ++ // Paper end ++ private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { + double d0 = (double) SectionPos.sectionToBlockCoord(pos.x, 8); + double d1 = (double) SectionPos.sectionToBlockCoord(pos.z, 8); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 5e0d55c3821b1769d20514a8a6c5c74477019778..eac5e799c4d26e53286a27c54b56899ba0b9ffb2 100644 +index c47d1772044913475a60292162ef4be594bed4c6..78143fe566fef13604c46029d4184ba39ed4aefc 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -768,7 +768,22 @@ public class ServerChunkCache extends ChunkSource { +@@ -754,7 +754,22 @@ public class ServerChunkCache extends ChunkSource { this.level.getProfiler().push("naturalSpawnCount"); this.level.timings.countNaturalMobs.startTiming(); // Paper - timings int l = this.distanceManager.getNaturalSpawnChunkCount(); @@ -610,27 +619,33 @@ index 5e0d55c3821b1769d20514a8a6c5c74477019778..eac5e799c4d26e53286a27c54b56899b + for (ServerPlayer player : this.level.players) { + Arrays.fill(player.mobCounts, 0); + } -+ spawnercreature_d = NaturalSpawner.countMobs(l, this.level.getAllEntities(), this::getFullChunk, true); ++ spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, true); + } else { -+ spawnercreature_d = NaturalSpawner.countMobs(l, this.level.getAllEntities(), this::getFullChunk, false); ++ spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, false); + } + // Paper end this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings this.lastSpawnState = spawnercreature_d; diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index d6cfe68be1a944ff5d5780666467f5fd8e2794e3..b0eed4e18fc183856613c05f378576eb19985c46 100644 +index bffc897cb88a54c36432c98264f3416051aeab17..14a0190ea5e9a387582736bb130c16a3bc94151e 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -93,6 +93,7 @@ import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.HumanoidArm; - import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.Mob; -+import net.minecraft.world.entity.MobCategory; - import net.minecraft.world.entity.NeutralMob; +@@ -90,12 +90,7 @@ import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.damagesource.EntityDamageSource; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; +-import net.minecraft.world.entity.Entity; +-import net.minecraft.world.entity.EntitySelector; +-import net.minecraft.world.entity.HumanoidArm; +-import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.NeutralMob; ++import net.minecraft.world.entity.*; import net.minecraft.world.entity.animal.horse.AbstractHorse; import net.minecraft.world.entity.item.ItemEntity; -@@ -216,6 +217,11 @@ public class ServerPlayer extends Player implements ContainerListener { + import net.minecraft.world.entity.monster.Monster; +@@ -223,6 +218,11 @@ public class ServerPlayer extends Player { public boolean queueHealthUpdatePacket = false; public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; // Paper end @@ -642,97 +657,59 @@ index d6cfe68be1a944ff5d5780666467f5fd8e2794e3..b0eed4e18fc183856613c05f378576eb // CraftBukkit start public String displayName; -@@ -254,6 +260,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -317,6 +317,7 @@ public class ServerPlayer extends Player { this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper - this.canPickUpLoot = true; + this.bukkitPickUpLoot = true; this.maxHealthCache = this.getMaxHealth(); + this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper } // Yes, this doesn't match Vanilla, but it's the best we can do for now. -@@ -2058,6 +2065,7 @@ public class ServerPlayer extends Player implements ContainerListener { - - } - -+ public final SectionPos getPlayerMapSection() { return this.getLastSectionPos(); } // Paper - OBFHELPER - public SectionPos getLastSectionPos() { - return this.lastSectionPos; - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index e39d950783599b01271bdb7e67fe68b46af0c49c..ae50030df7512c56c552e800b74ef4c69ec6d6d2 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -426,6 +426,7 @@ public class EntityType { - return this.canSpawnFarFromPlayer; - } - -+ public final MobCategory getEnumCreatureType() { return this.getCategory(); } // Paper - OBFHELPER - public MobCategory getCategory() { - return this.category; - } diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 0fb69f9194078e5e05e36ed909eb48424b6465b4..df271598f6036c8cab8a8811151a376dda46e44d 100644 +index e20a645e28a2e503c02b2bd89424e95506a2e6df..18a28659a72a761f53ca226bbf9866b4f30c2e4c 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java @@ -17,6 +17,7 @@ import net.minecraft.core.Registry; + import net.minecraft.core.SectionPos; import net.minecraft.nbt.CompoundTag; - import net.minecraft.server.MCUtil; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.BlockTags; import net.minecraft.tags.FluidTags; import net.minecraft.tags.Tag; -@@ -60,9 +61,14 @@ public final class NaturalSpawner { - }); +@@ -65,7 +66,12 @@ public final class NaturalSpawner { + private NaturalSpawner() {} + ++ // Paper start - add countMobs parameter public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkSource) { -+ // Paper start - add countMobs parameter -+ return countMobs(spawningChunkCount, entities, chunkSource, false); ++ return createState(spawningChunkCount, entities, chunkSource, false); + } -+ public static NaturalSpawner.SpawnState countMobs(int i, Iterable iterable, NaturalSpawner.ChunkGetter spawnercreature_b, boolean countMobs) { -+ // Paper end - add countMobs parameter ++ public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkSource, boolean countMobs) { ++ // Paper end - add countMobs parameter PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator(); Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); -- Iterator iterator = entities.iterator(); -+ Iterator iterator = iterable.iterator(); - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); -@@ -89,7 +95,7 @@ public final class NaturalSpawner { - BlockPos blockposition = entity.blockPosition(); - long j = ChunkPos.asLong(blockposition.getX() >> 4, blockposition.getZ() >> 4); - -- chunkSource.query(j, (chunk) -> { -+ spawnercreature_b.query(j, (chunk) -> { - MobSpawnSettings.MobSpawnCost biomesettingsmobs_b = getRoughBiome(blockposition, chunk).getMobSettings().getMobSpawnCost(entity.getType()); - - if (biomesettingsmobs_b != null) { -@@ -97,11 +103,16 @@ public final class NaturalSpawner { + Iterator iterator = entities.iterator(); +@@ -103,6 +109,11 @@ public final class NaturalSpawner { } object2intopenhashmap.addTo(enumcreaturetype, 1); + // Paper start + if (countMobs) { -+ ((ServerLevel)chunk.world).getChunkSource().chunkMap.updatePlayerMobTypeMap(entity); ++ chunk.level.getChunkSource().chunkMap.updatePlayerMobTypeMap(entity); + } + // Paper end }); } } - -- return new NaturalSpawner.SpawnState(spawningChunkCount, object2intopenhashmap, spawnercreatureprobabilities); -+ return new NaturalSpawner.SpawnState(i, object2intopenhashmap, spawnercreatureprobabilities); - } - - private static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) { -@@ -155,13 +166,31 @@ public final class NaturalSpawner { +@@ -161,13 +172,31 @@ public final class NaturalSpawner { continue; } -- if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (shouldSpawnAnimals || !enumcreaturetype.isPersistent()) && info.a(enumcreaturetype, limit)) { +- if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (rareSpawn || !enumcreaturetype.isPersistent()) && info.a(enumcreaturetype, limit)) { + // Paper start - only allow spawns upto the limit per chunk and update count afterwards -+ int currEntityCount = info.getEntityCountsByType().getInt(enumcreaturetype); -+ int k1 = limit * info.getSpawnerChunks() / NaturalSpawner.MAGIC_NUMBER; ++ int currEntityCount = info.getMobCategoryCounts().getInt(enumcreaturetype); ++ int k1 = limit * info.getSpawnableChunkCount() / NaturalSpawner.MAGIC_NUMBER; + int difference = k1 - currEntityCount; + + if (world.paperConfig.perPlayerMobSpawns) { @@ -745,141 +722,76 @@ index 0fb69f9194078e5e05e36ed909eb48424b6465b4..df271598f6036c8cab8a8811151a376d + // Paper end + + // Paper start - per player mob spawning -+ if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (shouldSpawnAnimals || !enumcreaturetype.isPersistent()) && difference > 0) { ++ if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (spawnAnimals || !enumcreaturetype.isPersistent()) && info.a(enumcreaturetype, limit) && difference > 0) { // CraftBukkit end -- spawnCategoryForChunk(enumcreaturetype, world, chunk, (entitytypes, blockposition, ichunkaccess) -> { -+ int spawnCount = spawnMobs(enumcreaturetype, world, chunk, (entitytypes, blockposition, ichunkaccess) -> { - return info.canSpawn(entitytypes, blockposition, ichunkaccess); - }, (entityinsentient, ichunkaccess) -> { - info.afterSpawn(entityinsentient, ichunkaccess); -- }); -+ }, -+ difference, world.paperConfig.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null); -+ info.getEntityCountsByType().mergeInt(enumcreaturetype, spawnCount, Integer::sum); + Objects.requireNonNull(info); + NaturalSpawner.SpawnPredicate spawnercreature_c = info::canSpawn; + + Objects.requireNonNull(info); +- NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn); ++ int spawnCount = NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn, ++ difference, world.paperConfig.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null); ++ info.getMobCategoryCounts().mergeInt(enumcreaturetype, spawnCount, Integer::sum); + // Paper end - per player mob spawning } } -@@ -170,31 +199,43 @@ public final class NaturalSpawner { +@@ -175,12 +204,18 @@ public final class NaturalSpawner { + world.getProfiler().pop(); } ++ // Paper start - add parameters and int ret type public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { -- BlockPos blockposition = getRandomPosWithin(world, chunk); -+ // Paper start - add parameters and int ret type -+ spawnMobs(group, world, chunk, checker, runner, Integer.MAX_VALUE, null); ++ spawnCategoryForChunk(group, world, chunk, checker, runner); + } -+ public static int spawnMobs(MobCategory enumcreaturetype, ServerLevel worldserver, LevelChunk chunk, NaturalSpawner.SpawnPredicate spawnercreature_c, NaturalSpawner.AfterSpawnCallback spawnercreature_a, int maxSpawns, Consumer trackEntity) { ++ public static int spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer trackEntity) { + // Paper end - add parameters and int ret type -+ BlockPos blockposition = getRandomPosWithin(worldserver, chunk); + BlockPos blockposition = NaturalSpawner.getRandomPosWithin(world, chunk); - if (blockposition.getY() >= 1) { -- spawnCategoryForPosition(group, world, (ChunkAccess) chunk, blockposition, checker, runner); -+ return spawnMobsInternal(enumcreaturetype, worldserver, (ChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a, maxSpawns, trackEntity); + if (blockposition.getY() >= world.getMinBuildHeight() + 1) { +- NaturalSpawner.spawnCategoryForPosition(group, world, (ChunkAccess) chunk, blockposition, checker, runner); ++ return NaturalSpawner.spawnCategoryForPosition(group, world, (ChunkAccess) chunk, blockposition, checker, runner, maxSpawns, trackEntity); // Paper } + return 0; // Paper } + @VisibleForDebug +@@ -191,15 +226,21 @@ public final class NaturalSpawner { + }); + } + ++ // Paper start - add maxSpawns parameter and return spawned mobs public static void spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { -- StructureFeatureManager structuremanager = world.structureFeatureManager(); -- ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); -- int i = pos.getY(); -- BlockState iblockdata = world.getTypeIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn -- -- if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn -+ // Paper start - add maxSpawns parameter and return spawned mobs -+ spawnMobsInternal(group, world, chunk, pos, checker, runner, Integer.MAX_VALUE, null); ++ spawnCategoryForPosition(group, world,chunk, pos, checker, runner); + } -+ public static int spawnMobsInternal(MobCategory enumcreaturetype, ServerLevel worldserver, ChunkAccess ichunkaccess, BlockPos blockposition, NaturalSpawner.SpawnPredicate spawnercreature_c, NaturalSpawner.AfterSpawnCallback spawnercreature_a, int maxSpawns, Consumer trackEntity) { -+ // Paper end - add maxSpawns parameter and return spawned mobs -+ StructureFeatureManager structuremanager = worldserver.structureFeatureManager(); -+ ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); -+ int i = blockposition.getY(); -+ BlockState iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn ++ public static int spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer trackEntity) { ++ // Paper end - add maxSpawns parameter and return spawned mobs + StructureFeatureManager structuremanager = world.structureFeatureManager(); + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); + int i = pos.getY(); + BlockState iblockdata = world.getTypeIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn + int j = 0; // Paper - moved up -+ -+ if (iblockdata != null && !iblockdata.isRedstoneConductor(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn + + if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); - int j = 0; + // Paper - moved up int k = 0; while (k < 3) { -- int l = pos.getX(); -- int i1 = pos.getZ(); -+ int l = blockposition.getX(); -+ int i1 = blockposition.getZ(); - boolean flag = true; - MobSpawnSettings.SpawnerData biomesettingsmobs_c = null; - SpawnGroupData groupdataentity = null; -- int j1 = Mth.ceil(world.random.nextFloat() * 4.0F); -+ int j1 = Mth.ceil(worldserver.random.nextFloat() * 4.0F); - int k1 = 0; - int l1 = 0; - -@@ -202,53 +243,58 @@ public final class NaturalSpawner { - if (l1 < j1) { - label53: - { -- l += world.random.nextInt(6) - world.random.nextInt(6); -- i1 += world.random.nextInt(6) - world.random.nextInt(6); -+ l += worldserver.random.nextInt(6) - worldserver.random.nextInt(6); -+ i1 += worldserver.random.nextInt(6) - worldserver.random.nextInt(6); - blockposition_mutableblockposition.set(l, i, i1); - double d0 = (double) l + 0.5D; - double d1 = (double) i1 + 0.5D; -- Player entityhuman = world.getNearestPlayer(d0, (double) i, d1, -1.0D, false); -+ Player entityhuman = worldserver.getNearestPlayer(d0, (double) i, d1, -1.0D, false); - - if (entityhuman != null) { - double d2 = entityhuman.distanceToSqr(d0, (double) i, d1); - -- if (isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2) && world.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn -+ if (isRightDistanceToPlayerAndSpawnPoint(worldserver, ichunkaccess, blockposition_mutableblockposition, d2) && worldserver.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn - if (biomesettingsmobs_c == null) { -- biomesettingsmobs_c = getRandomSpawnMobAt(world, structuremanager, chunkgenerator, group, world.random, (BlockPos) blockposition_mutableblockposition); -+ biomesettingsmobs_c = getRandomSpawnMobAt(worldserver, structuremanager, chunkgenerator, enumcreaturetype, worldserver.random, (BlockPos) blockposition_mutableblockposition); - if (biomesettingsmobs_c == null) { - break label53; - } - -- j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); -+ j1 = biomesettingsmobs_c.minCount + worldserver.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); - } - - // Paper start -- Boolean doSpawning = a(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); -+ Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); - if (doSpawning == null) { -- return; -+ return j; // Paper - } -- if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { -+ if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, ichunkaccess)) { - // Paper end -- Mob entityinsentient = getMobForSpawn(world, biomesettingsmobs_c.type); -+ Mob entityinsentient = getMobForSpawn(worldserver, biomesettingsmobs_c.type); - +@@ -242,7 +283,7 @@ public final class NaturalSpawner { + Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type); if (entityinsentient == null) { - return; + return j; // Paper } -- entityinsentient.moveTo(d0, (double) i, d1, world.random.nextFloat() * 360.0F, 0.0F); -- if (isValidPositionForMob(world, entityinsentient, d2)) { -- groupdataentity = entityinsentient.finalizeSpawn(world, world.getCurrentDifficultyAt(entityinsentient.blockPosition()), MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); -+ entityinsentient.moveTo(d0, (double) i, d1, worldserver.random.nextFloat() * 360.0F, 0.0F); -+ if (isValidPositionForMob(worldserver, entityinsentient, d2)) { -+ groupdataentity = entityinsentient.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(entityinsentient.blockPosition()), MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); - // CraftBukkit start -- world.addAllEntities(entityinsentient, SpawnReason.NATURAL); -+ worldserver.addAllEntities(entityinsentient, SpawnReason.NATURAL); - if (!entityinsentient.removed) { -- ++j; -+ ++j; // Paper - force diff on name change - we expect this to be the total amount spawned + entityinsentient.moveTo(d0, (double) i, d1, world.random.nextFloat() * 360.0F, 0.0F); +@@ -254,10 +295,15 @@ public final class NaturalSpawner { + ++j; ++k1; -- runner.run(entityinsentient, chunk); -+ spawnercreature_a.run(entityinsentient, ichunkaccess); + runner.run(entityinsentient, chunk); + // Paper start + if (trackEntity != null) { + trackEntity.accept(entityinsentient); @@ -894,7 +806,7 @@ index 0fb69f9194078e5e05e36ed909eb48424b6465b4..df271598f6036c8cab8a8811151a376d } if (entityinsentient.isMaxGroupSizeReached(k1)) { -@@ -270,6 +316,7 @@ public final class NaturalSpawner { +@@ -279,6 +325,7 @@ public final class NaturalSpawner { } } @@ -902,23 +814,3 @@ index 0fb69f9194078e5e05e36ed909eb48424b6465b4..df271598f6036c8cab8a8811151a376d } private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) { -@@ -510,8 +557,8 @@ public final class NaturalSpawner { - - public static class SpawnState { - -- private final int spawnableChunkCount; -- private final Object2IntOpenHashMap mobCategoryCounts; -+ private final int spawnableChunkCount; final int getSpawnerChunks() { return this.spawnableChunkCount; } // Paper - OBFHELPER -+ private final Object2IntOpenHashMap mobCategoryCounts; final Object2IntMap getEntityCountsByType() { return this.mobCategoryCounts; } // Paper - OBFHELPER - private final PotentialCalculator spawnPotential; - private final Object2IntMap unmodifiableMobCategoryCounts; - @Nullable -@@ -572,7 +619,7 @@ public final class NaturalSpawner { - - // CraftBukkit start - private boolean a(MobCategory enumcreaturetype, int limit) { -- int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; -+ int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; // Paper - diff on change, needed in the spawn method - // CraftBukkit end - - return this.mobCategoryCounts.getInt(enumcreaturetype) < i; From f67dc7a35be82fd4053e5f908d1ca07b33067e2d Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 19:40:12 -0700 Subject: [PATCH 093/226] patches --- ...99-Add-item-slot-convenience-methods.patch | 0 ...patch => 0200-Villager-Restocks-API.patch} | 0 .../0201-Add-Mob-Goal-API.patch} | 8 +- ...n.patch => 0202-Expose-game-version.patch} | 4 +- ...per-thread-native-byte-buffer-cache.patch} | 4 +- .../0421-Implement-Mob-Goal-API.patch} | 191 +++++++----------- 6 files changed, 82 insertions(+), 125 deletions(-) rename patches/{api-unmapped => api}/0199-Add-item-slot-convenience-methods.patch (100%) rename patches/api/{0199-Villager-Restocks-API.patch => 0200-Villager-Restocks-API.patch} (100%) rename patches/{api-unmapped/0200-Add-Mob-Goal-API.patch => api/0201-Add-Mob-Goal-API.patch} (98%) rename patches/api/{0200-Expose-game-version.patch => 0202-Expose-game-version.patch} (89%) rename patches/{server-remapped/0465-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch => server/0420-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch} (88%) rename patches/{server-remapped/0466-Implement-Mob-Goal-API.patch => server/0421-Implement-Mob-Goal-API.patch} (88%) diff --git a/patches/api-unmapped/0199-Add-item-slot-convenience-methods.patch b/patches/api/0199-Add-item-slot-convenience-methods.patch similarity index 100% rename from patches/api-unmapped/0199-Add-item-slot-convenience-methods.patch rename to patches/api/0199-Add-item-slot-convenience-methods.patch diff --git a/patches/api/0199-Villager-Restocks-API.patch b/patches/api/0200-Villager-Restocks-API.patch similarity index 100% rename from patches/api/0199-Villager-Restocks-API.patch rename to patches/api/0200-Villager-Restocks-API.patch diff --git a/patches/api-unmapped/0200-Add-Mob-Goal-API.patch b/patches/api/0201-Add-Mob-Goal-API.patch similarity index 98% rename from patches/api-unmapped/0200-Add-Mob-Goal-API.patch rename to patches/api/0201-Add-Mob-Goal-API.patch index 24855e7426..5c3c26fbaf 100644 --- a/patches/api-unmapped/0200-Add-Mob-Goal-API.patch +++ b/patches/api/0201-Add-Mob-Goal-API.patch @@ -441,10 +441,10 @@ index 0000000000000000000000000000000000000000..b42091752981a1f309ab350e9a394092 + GoalKey UNIVERSAL_ANGER_RESET = GoalKey.of(Mob.class, NamespacedKey.minecraft("universal_anger_reset")); +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index bbf15311a48ba96e14ffa2ab9d59613e79f06618..4cffbc4f665e267371e99094e8b7de975fffc223 100644 +index 847ba5143660d5c56ff8f2cae2169a51b8927757..17553703d6dcb0c7852cc35b08da05075af435f2 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1879,6 +1879,16 @@ public final class Bukkit { +@@ -1867,6 +1867,16 @@ public final class Bukkit { public static boolean isStopping() { return server.isStopping(); } @@ -462,10 +462,10 @@ index bbf15311a48ba96e14ffa2ab9d59613e79f06618..4cffbc4f665e267371e99094e8b7de97 @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 21ebe1e70a4b9df54a5c730cee6d024cc1358b88..969cba46ba2790dde32724111ad77332c5872e0b 100644 +index e6b62ba32e089e2fd8563ec8430b72196f6680e0..0a109e9157d9a9f15f71d2fa96d31b7f8eb3fde2 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1648,5 +1648,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1638,5 +1638,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/0200-Expose-game-version.patch b/patches/api/0202-Expose-game-version.patch similarity index 89% rename from patches/api/0200-Expose-game-version.patch rename to patches/api/0202-Expose-game-version.patch index 987427e030..cdc766fcf1 100644 --- a/patches/api/0200-Expose-game-version.patch +++ b/patches/api/0202-Expose-game-version.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Expose game version diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 847ba5143660d5c56ff8f2cae2169a51b8927757..2c9d2739e78d5c422574f5ddda078ca395c0fa6d 100644 +index 17553703d6dcb0c7852cc35b08da05075af435f2..4eb60f2772c80f9917e88c40ed2214993709e443 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -118,6 +118,18 @@ public final class Bukkit { @@ -28,7 +28,7 @@ index 847ba5143660d5c56ff8f2cae2169a51b8927757..2c9d2739e78d5c422574f5ddda078ca3 * 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 e6b62ba32e089e2fd8563ec8430b72196f6680e0..46d1086bd7d7f91b4337c8463974d4b9d501cbf0 100644 +index 0a109e9157d9a9f15f71d2fa96d31b7f8eb3fde2..22495f576b05e3f0161bfd2c4ea5e5622fdb6302 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -97,6 +97,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/server-remapped/0465-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/patches/server/0420-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch similarity index 88% rename from patches/server-remapped/0465-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch rename to patches/server/0420-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch index d35e663567..dba06499e6 100644 --- a/patches/server-remapped/0465-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch +++ b/patches/server/0420-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch @@ -17,7 +17,7 @@ keeping long lived large direct buffers in cache. Set system properly at server startup if not set already to help protect from this. diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index c288b89bf5a22269823ba1d18af217032d7c6a36..bd10345cb90f98b8af1519afd603a5244f3a5ca2 100644 +index 2904cbda94a8fb986d94022c11061f98938237dd..6ebd0f6053929beb246993b5a1b682b9971baf0b 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -28,6 +28,7 @@ public class Main { @@ -27,4 +27,4 @@ index c288b89bf5a22269823ba1d18af217032d7c6a36..bd10345cb90f98b8af1519afd603a524 + if (System.getProperty("jdk.nio.maxCachedBufferSize") == null) System.setProperty("jdk.nio.maxCachedBufferSize", "262144"); // Paper - cap per-thread NIO cache size OptionParser parser = new OptionParser() { { - acceptsAll(asList("?", "help"), "Show the help"); + acceptsAll(Main.asList("?", "help"), "Show the help"); diff --git a/patches/server-remapped/0466-Implement-Mob-Goal-API.patch b/patches/server/0421-Implement-Mob-Goal-API.patch similarity index 88% rename from patches/server-remapped/0466-Implement-Mob-Goal-API.patch rename to patches/server/0421-Implement-Mob-Goal-API.patch index 0aaed21f24..dd073b39fe 100644 --- a/patches/server-remapped/0466-Implement-Mob-Goal-API.patch +++ b/patches/server/0421-Implement-Mob-Goal-API.patch @@ -4,11 +4,23 @@ Date: Fri, 3 Jan 2020 16:26:19 +0100 Subject: [PATCH] Implement Mob Goal API +diff --git a/build.gradle.kts b/build.gradle.kts +index 2543a4cf2bb58c2265cfc427c427b683d2ff70ca..5c885454c729467e29fd3784058fff6a7379c9dc 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -52,6 +52,7 @@ dependencies { + implementation("co.aikar:cleaner:1.0-SNAPSHOT") // Paper + implementation("io.netty:netty-all:4.1.65.Final") // Paper + ++ testImplementation("io.github.classgraph:classgraph:4.8.47") // Paper - mob goal test + testImplementation("junit:junit:4.13.1") + testImplementation("org.hamcrest:hamcrest-library:1.3") + } diff --git a/pom.xml b/pom.xml -index 4c8a057e790c96b0ab5123549d0566371acacb46..1a9204c869dd36e80932b1366352db15ebd70723 100644 +index 86cce7143abd317326cc755118bf61435e82e479..4233698d499b520dfc07c4184cefca633a95d15b 100644 --- a/pom.xml +++ b/pom.xml -@@ -176,6 +176,13 @@ +@@ -121,6 +121,13 @@ 1.3 test @@ -24,14 +36,12 @@ index 4c8a057e790c96b0ab5123549d0566371acacb46..1a9204c869dd36e80932b1366352db15 diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java new file mode 100644 -index 0000000000000000000000000000000000000000..6ddb198f86ccf3bc2471752d5fb2f59d9a7ab4df +index 0000000000000000000000000000000000000000..9efe7e29faf09901e8cde8713db80ceb31453412 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -@@ -0,0 +1,462 @@ +@@ -0,0 +1,463 @@ +package com.destroystokyo.paper.entity.ai; + -+import GoalKey; -+import GoalType; +import com.destroystokyo.paper.entity.RangedEntity; +import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; +import com.google.common.collect.BiMap; @@ -42,7 +52,6 @@ index 0000000000000000000000000000000000000000..6ddb198f86ccf3bc2471752d5fb2f59d +import java.util.HashSet; +import java.util.Map; +import java.util.Set; -+import net.minecraft.world.entity.AgableMob; +import net.minecraft.world.entity.FlyingMob; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.TamableAnimal; @@ -247,7 +256,7 @@ index 0000000000000000000000000000000000000000..6ddb198f86ccf3bc2471752d5fb2f59d + deobfuscationMap.put("shulker_d", "shulker_nearest"); + deobfuscationMap.put("shulker_e", "shulker_peek"); + deobfuscationMap.put("squid_a", "squid_flee"); -+ deobfuscationMap.put("skeleton_abstract_1", "skeleton_melee"); ++ deobfuscationMap.put("abstract_skeleton_1", "skeleton_melee"); + deobfuscationMap.put("strider_a", "strider_go_to_lava"); + deobfuscationMap.put("turtle_a", "turtle_breed"); + deobfuscationMap.put("turtle_b", "turtle_go_home"); @@ -268,12 +277,12 @@ index 0000000000000000000000000000000000000000..6ddb198f86ccf3bc2471752d5fb2f59d + deobfuscationMap.put("wolf_a", "wolf_avoid_entity"); + deobfuscationMap.put("zombie_a", "zombie_attack_turtle_egg"); + -+ ignored.add("selector_1"); -+ ignored.add("selector_2"); ++ ignored.add("goal_selector_1"); ++ ignored.add("goal_selector_2"); + ignored.add("wrapped"); + + bukkitMap.put(net.minecraft.world.entity.Mob.class, Mob.class); -+ bukkitMap.put(AgableMob.class, Ageable.class); ++ bukkitMap.put(net.minecraft.world.entity.AgeableMob.class, Ageable.class); + bukkitMap.put(AmbientCreature.class, Ambient.class); + bukkitMap.put(Animal.class, Animals.class); + bukkitMap.put(net.minecraft.world.entity.ambient.Bat.class, Bat.class); @@ -364,8 +373,12 @@ index 0000000000000000000000000000000000000000..6ddb198f86ccf3bc2471752d5fb2f59d + bukkitMap.put(net.minecraft.world.entity.monster.piglin.PiglinBrute.class, PiglinBrute.class); + bukkitMap.put(net.minecraft.world.entity.monster.Strider.class, Strider.class); + bukkitMap.put(net.minecraft.world.entity.monster.Zoglin.class, Zoglin.class); ++ bukkitMap.put(net.minecraft.world.entity.GlowSquid.class, org.bukkit.entity.GlowSquid.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.axolotl.Axolotl.class, org.bukkit.entity.Axolotl.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.goat.Goat.class, org.bukkit.entity.Goat.class); + } + ++ // TODO: FIX THIS + public static String getUsableName(Class clazz) { + String name = clazz.getName(); + name = name.substring(name.lastIndexOf(".") + 1); @@ -492,20 +505,19 @@ index 0000000000000000000000000000000000000000..6ddb198f86ccf3bc2471752d5fb2f59d +} diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java new file mode 100644 -index 0000000000000000000000000000000000000000..14ddf844be10c04522aa3ec125fa7a0f540b10c2 +index 0000000000000000000000000000000000000000..ee500489fca34c339175b5209ebcf3417640b166 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java -@@ -0,0 +1,55 @@ +@@ -0,0 +1,54 @@ +package com.destroystokyo.paper.entity.ai; + -+import GoalKey; -+import net.minecraft.world.entity.ai.goal.Goal; +import org.bukkit.entity.Mob; ++import com.destroystokyo.paper.entity.ai.Goal; + +/** + * Wraps api in vanilla + */ -+public class PaperCustomGoal extends Goal { ++public class PaperCustomGoal extends net.minecraft.world.entity.ai.goal.Goal { + + private final Goal handle; + @@ -534,7 +546,7 @@ index 0000000000000000000000000000000000000000..14ddf844be10c04522aa3ec125fa7a0f + } + + @Override -+ public void onTaskReset() { ++ public void stop() { + handle.stop(); + } + @@ -553,10 +565,10 @@ index 0000000000000000000000000000000000000000..14ddf844be10c04522aa3ec125fa7a0f +} diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java new file mode 100644 -index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959e82e4ab1 +index 0000000000000000000000000000000000000000..a17a8d8ced942e6e3f9072f199c75391dd57dc6a --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java -@@ -0,0 +1,222 @@ +@@ -0,0 +1,221 @@ +package com.destroystokyo.paper.entity.ai; + +import java.util.Collection; @@ -567,7 +579,6 @@ index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959 +import java.util.List; +import java.util.Map; +import java.util.Set; -+import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.ai.goal.GoalSelector; +import net.minecraft.world.entity.ai.goal.WrappedGoal; +import org.bukkit.craftbukkit.entity.CraftMob; @@ -575,7 +586,7 @@ index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959 + +public class PaperMobGoals implements MobGoals { + -+ private final Map> instanceCache = new HashMap<>(); ++ private final Map> instanceCache = new HashMap<>(); + + @Override + public void addGoal(T mob, int priority, Goal goal) { @@ -587,12 +598,12 @@ index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959 + public void removeGoal(T mob, Goal goal) { + CraftMob craftMob = (CraftMob) mob; + if (goal instanceof PaperCustomGoal) { -+ getHandle(craftMob, goal.getTypes()).removeGoal((Goal) goal); ++ getHandle(craftMob, goal.getTypes()).removeGoal((net.minecraft.world.entity.ai.goal.Goal) goal); + } else if (goal instanceof PaperVanillaGoal) { + getHandle(craftMob, goal.getTypes()).removeGoal(((PaperVanillaGoal) goal).getHandle()); + } else { -+ List toRemove = new LinkedList<>(); -+ for (WrappedGoal item : getHandle(craftMob, goal.getTypes()).getTasks()) { ++ List toRemove = new LinkedList<>(); ++ for (WrappedGoal item : getHandle(craftMob, goal.getTypes()).availableGoals()) { + if (item.getGoal() instanceof PaperCustomGoal) { + //noinspection unchecked + if (((PaperCustomGoal) item.getGoal()).getHandle() == goal) { @@ -601,7 +612,7 @@ index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959 + } + } + -+ for (Goal g : toRemove) { ++ for (net.minecraft.world.entity.ai.goal.Goal g : toRemove) { + getHandle(craftMob, goal.getTypes()).removeGoal(g); + } + } @@ -672,7 +683,7 @@ index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959 + public Collection> getAllGoals(T mob, GoalType type) { + CraftMob craftMob = (CraftMob) mob; + Set> goals = new HashSet<>(); -+ for (WrappedGoal item : getHandle(craftMob, type).getTasks()) { ++ for (WrappedGoal item : getHandle(craftMob, type).availableGoals()) { + if (!item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { + continue; + } @@ -696,7 +707,7 @@ index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959 + if (internalType == type) { + continue; + } -+ for (WrappedGoal item : getHandle(craftMob, internalType).getTasks()) { ++ for (WrappedGoal item : getHandle(craftMob, internalType).availableGoals()) { + if (item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { + continue; + } @@ -726,7 +737,7 @@ index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959 + public Collection> getRunningGoals(T mob, GoalType type) { + CraftMob craftMob = (CraftMob) mob; + Set> goals = new HashSet<>(); -+ getHandle(craftMob, type).getExecutingGoals() ++ getHandle(craftMob, type).getRunningGoals() + .filter(item -> item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) + .forEach(item -> { + if (item.getGoal() instanceof PaperCustomGoal) { @@ -748,7 +759,7 @@ index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959 + if (internalType == type) { + continue; + } -+ getHandle(craftMob, internalType).getExecutingGoals() ++ getHandle(craftMob, internalType).getRunningGoals() + .filter(item -> !item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) + .forEach(item -> { + if (item.getGoal() instanceof PaperCustomGoal) { @@ -781,13 +792,12 @@ index 0000000000000000000000000000000000000000..615f571b08da27b0da7c53e3be172959 +} diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java new file mode 100644 -index 0000000000000000000000000000000000000000..d4fe9d517a05f99c715ab73d5baf1deb6a732068 +index 0000000000000000000000000000000000000000..bb06eb216a3f19af06abef3b84dd4191f5728256 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java -@@ -0,0 +1,62 @@ +@@ -0,0 +1,61 @@ +package com.destroystokyo.paper.entity.ai; + -+import GoalKey; +import java.util.EnumSet; +import net.minecraft.world.entity.ai.goal.Goal; +import org.bukkit.entity.Mob; @@ -829,7 +839,7 @@ index 0000000000000000000000000000000000000000..d4fe9d517a05f99c715ab73d5baf1deb + + @Override + public void stop() { -+ handle.onTaskReset(); ++ handle.stop(); + } + + @Override @@ -861,23 +871,22 @@ index 9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f..b3329c6fcd6758a781a51f5ba8f5052a + } } diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -index acc6306d659cd65a043d12cd42dcbaf55aaf5250..f85dfd8b57cf81ad7c6b12753fdd42e93f772f9e 100644 +index 8c2ec30a35e86f2b30863045b586a67e485c624b..a20faf55488baa31d7f8bf8231e3e8258b91cdc8 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -@@ -8,11 +8,17 @@ public abstract class Goal { +@@ -6,9 +6,17 @@ public abstract class Goal { private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. - private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector + private final com.destroystokyo.paper.util.set.OptimizedSmallEnumSet goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector -- public Goal() {} +- public abstract boolean canUse(); + // Paper start make sure goaltypes is never empty + public Goal() { + if (this.goalTypes.size() == 0) { + this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR); + } + } -+ // paper end - -- public abstract boolean canUse(); ++ // Paper end ++ + public boolean canUse() { return this.shouldActivate(); } public boolean shouldActivate() { return false;} public boolean shouldActivate2() { return canUse(); } // Paper - OBFHELPER, for both directions... - public boolean canContinueToUse() { @@ -885,21 +894,10 @@ index acc6306d659cd65a043d12cd42dcbaf55aaf5250..f85dfd8b57cf81ad7c6b12753fdd42e9 return this.canUse(); } -@@ -20,19 +26,23 @@ public abstract class Goal { - return true; +@@ -25,10 +33,14 @@ public abstract class Goal { + public void tick() { } -- public void start() {} -+ public void start() { this.start(); } public void start() {} // Paper - OBFHELPER - - public void stop() { - onTaskReset(); // Paper - } - public void onTaskReset() {} // Paper - -- public void tick() {} -+ public void tick() { this.tick(); } public void tick() {} // Paper OBFHELPER - - public void setFlags(EnumSet controls) { + public void setFlags(EnumSet controls) { this.setTypes(controls); } public void setTypes(EnumSet enumset) { // Paper - OBFHELPER // Paper start - remove streams from pathfindergoalselector @@ -913,74 +911,32 @@ index acc6306d659cd65a043d12cd42dcbaf55aaf5250..f85dfd8b57cf81ad7c6b12753fdd42e9 // Paper end - remove streams from pathfindergoalselector } -@@ -48,7 +58,7 @@ public abstract class Goal { +@@ -44,6 +56,7 @@ public abstract class Goal { + } public static enum Flag { - -- MOVE, LOOK, JUMP, TARGET; -+ MOVE, LOOK, JUMP, TARGET, UNKNOWN_BEHAVIOR; // Paper - add unknown - - private Flag() {} - } ++ UNKNOWN_BEHAVIOR, // Paper - add UNKNOWN_BEHAVIOR + MOVE, + LOOK, + JUMP, diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -index 5da2d780c17522e07c733a5e23b17ec760c7b342..a03f72f67948efab3b000dfa1d48061abf7cc02f 100644 +index bcb2c5480872eef6f21746003380f71b8d44f5c8..bcd0da029edd9b1d6f3617ee20dac00c9890ae82 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -@@ -28,7 +28,7 @@ public class GoalSelector { +@@ -26,7 +26,7 @@ public class GoalSelector { } }; - private final Map lockedFlags = new EnumMap(Goal.Flag.class); -- private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER -+ private final Set availableGoals = Sets.newLinkedHashSet(); public final Set getTasks() { return availableGoals; }// Paper - OBFHELPER // Paper - private -> public + private final Map lockedFlags = new EnumMap<>(Goal.Flag.class); +- private final Set availableGoals = Sets.newLinkedHashSet(); ++ private final Set availableGoals = Sets.newLinkedHashSet(); public final Set availableGoals() { return this.availableGoals; } // Paper - public getter private final Supplier profiler; private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. - private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector -@@ -39,7 +39,7 @@ public class GoalSelector { - this.profiler = profiler; - } - -- public void addGoal(int priority, Goal goal) { -+ public void addGoal(int priority, Goal goal) {addGoal(priority, goal);} public void addGoal(int priority, Goal goal) { // Paper - OBFHELPER - this.availableGoals.add(new WrappedGoal(priority, goal)); - } - -@@ -58,7 +58,7 @@ public class GoalSelector { - } - // Paper end - -- public void removeGoal(Goal goal) { -+ public void removeGoal(Goal goal) {removeGoal(goal);} public void removeGoal(Goal goal) { // Paper - OBFHELPER - // Paper start - remove streams from pathfindergoalselector - for (Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { - WrappedGoal goalWrapped = iterator.next(); -@@ -154,6 +154,7 @@ public class GoalSelector { - gameprofilerfiller.pop(); - } - -+ public final Stream getExecutingGoals() { return getRunningGoals(); } // Paper - OBFHELPER - public Stream getRunningGoals() { - return this.availableGoals.stream().filter(WrappedGoal::isRunning); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -index 984146b2b6eb3e498433b1c4971397848166d9c9..06fe2248a52c180ffabe0a6fe0cf155b78d4752d 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -@@ -5,8 +5,8 @@ import javax.annotation.Nullable; - - public class WrappedGoal extends Goal { - -- private final Goal goal; -- private final int priority; -+ private final Goal goal; public Goal getGoal() {return goal;} // Paper - OBFHELPER -+ private final int priority; public int getPriority() {return priority;} // Paper - OBFHELPER - private boolean isRunning; - - public WrappedGoal(int priority, Goal goal) { + private final com.destroystokyo.paper.util.set.OptimizedSmallEnumSet goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 1bfe96443877e460d22513d59ebc3b5988e8eb43..c6dc314a1735bf849ee1572e01335909bed9b455 100644 +index 479b4eb8efeeca432bcb21925db18d5c0750f001..4d6a6583af73a25b5f2783ba56a63b8c9987c0a4 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2390,5 +2390,11 @@ public final class CraftServer implements Server { +@@ -2391,5 +2391,11 @@ public final class CraftServer implements Server { public boolean isStopping() { return net.minecraft.server.MinecraftServer.getServer().hasStopped(); } @@ -994,14 +950,12 @@ index 1bfe96443877e460d22513d59ebc3b5988e8eb43..c6dc314a1735bf849ee1572e01335909 } diff --git a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java new file mode 100644 -index 0000000000000000000000000000000000000000..c0525216a8469613c3e0d4b5774a82f69e70fb16 +index 0000000000000000000000000000000000000000..33597ba747c10bc9e2a89e6920f64ce5a737967e --- /dev/null +++ b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java -@@ -0,0 +1,104 @@ +@@ -0,0 +1,105 @@ +package com.destroystokyo.paper.entity.ai; + -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; +import org.junit.Assert; +import org.junit.Test; + @@ -1019,6 +973,7 @@ index 0000000000000000000000000000000000000000..c0525216a8469613c3e0d4b5774a82f6 + +public class VanillaMobGoalTest { + ++ /* TODO: FIX THIS + @Test + public void testKeys() { + List> deprecated = new ArrayList<>(); @@ -1040,13 +995,14 @@ index 0000000000000000000000000000000000000000..c0525216a8469613c3e0d4b5774a82f6 + + List> classes; + try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) { -+ classes = scanResult.getSubclasses(PathfinderGoal.class.getName()).loadClasses(); ++ classes = scanResult.getSubclasses(net.minecraft.world.entity.ai.goal.Goal.class.getName()).loadClasses(); + } + + List> vanillaNames = classes.stream() + .filter(VanillaMobGoalTest::hasNoEnclosingClass) + .filter(clazz -> !Modifier.isAbstract(clazz.getModifiers())) -+ .map(goalClass -> MobGoalHelper.getKey((Class) goalClass)) ++ .filter(clazz -> !net.minecraft.world.entity.ai.goal.WrappedGoal.class.equals(clazz)) // TODO - properly fix ++ .map(goalClass -> MobGoalHelper.getKey((Class) goalClass)) + .collect(Collectors.toList()); + + List> missingFromAPI = new ArrayList<>(vanillaNames); @@ -1077,6 +1033,7 @@ index 0000000000000000000000000000000000000000..c0525216a8469613c3e0d4b5774a82f6 + + if (shouldFail) Assert.fail("See above"); + } ++ */ + + private static boolean hasNoEnclosingClass(Class clazz) { + return clazz.getEnclosingClass() == null || hasNoEnclosingClass(clazz.getSuperclass()); @@ -1086,13 +1043,13 @@ index 0000000000000000000000000000000000000000..c0525216a8469613c3e0d4b5774a82f6 + public void testBukkitMap() { + List> classes; + try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft.world.entity").scan()) { -+ classes = scanResult.getSubclasses("net.minecraft.world.entity.EntityInsentient").loadClasses(); ++ classes = scanResult.getSubclasses("net.minecraft.world.entity.Mob").loadClasses(); + } + Assert.assertNotEquals("There are supposed to be more than 0 entity types!", Collections.emptyList(), classes); + + boolean shouldFail = false; + for (Class nmsClass : classes) { -+ Class bukkitClass = MobGoalHelper.toBukkitClass((Class) nmsClass); ++ Class bukkitClass = MobGoalHelper.toBukkitClass((Class) nmsClass); + if (bukkitClass == null) { + shouldFail = true; + System.out.println("Missing bukkitMap.put(" + nmsClass.getSimpleName() + ".class, " + nmsClass.getSimpleName().replace("Entity", "") + ".class);"); From 3d7b0490c0e7fdfded2206f4a2949ce471316057 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 19:43:29 -0700 Subject: [PATCH 094/226] reorder patches after merge --- ...=> 0363-Tracking-Range-Improvements.patch} | 0 ...-items-vanishing-through-end-portal.patch} | 0 ...ment-optional-per-player-mob-spawns.patch} | 7 +++---- ...et-gravity-in-void.-Fixes-MC-167279.patch} | 0 ...-getChunkAt-calls-for-loaded-chunks.patch} | 2 +- ...w-overriding-the-java-version-check.patch} | 0 ...tch => 0369-Add-ThrownEggHatchEvent.patch} | 0 ... 0370-Optimise-random-block-ticking.patch} | 0 ...p-API.patch => 0371-Entity-Jump-API.patch} | 0 ...-to-nerf-pigmen-from-nether-portals.patch} | 4 ++-- ... => 0373-Make-the-GUI-graph-fancier.patch} | 0 ...74-add-hand-to-BlockMultiPlaceEvent.patch} | 0 ...5-Prevent-teleporting-dead-entities.patch} | 0 ...ipwire-hook-placement-before-update.patch} | 0 ...o-allow-iron-golems-to-spawn-in-air.patch} | 4 ++-- ...chance-of-villager-zombie-infection.patch} | 4 ++-- ...tch => 0379-Optimise-Chunk-getFluid.patch} | 0 ...mise-TickListServer-by-rewriting-it.patch} | 2 +- ...pawn-settings-and-per-player-option.patch} | 8 ++++---- ...nections-shouldn-t-hold-up-shutdown.patch} | 0 ...ow-bees-to-load-chunks-for-beehives.patch} | 0 ...PlayerChunkMap-adds-crashing-server.patch} | 4 ++-- ...timize-Collision-to-not-load-chunks.patch} | 0 ...tch => 0386-Don-t-tick-dead-players.patch} | 4 ++-- ...-Player-s-shouldn-t-be-able-to-move.patch} | 0 ...unkMap-memory-use-for-visibleChunks.patch} | 20 +++++++++---------- ...sks-Speed-up-processing-of-chunk-lo.patch} | 8 ++++---- ...ove-existing-players-to-world-spawn.patch} | 6 +++--- ...Add-tick-times-API-and-mspt-command.patch} | 0 ...92-Expose-MinecraftServer-isRunning.patch} | 0 ...dd-Raw-Byte-ItemStack-Serialization.patch} | 0 ...4-Remove-streams-from-Mob-AI-System.patch} | 0 ... => 0395-Async-command-map-building.patch} | 0 ...h => 0396-Improved-Watchdog-Support.patch} | 4 ++-- ....patch => 0397-Optimize-Pathfinding.patch} | 0 ...8-Reduce-Either-Optional-allocation.patch} | 0 ...399-Remove-streams-from-PairedQueue.patch} | 0 ...-memory-footprint-of-NBTTagCompound.patch} | 0 ...ent-opening-inventories-when-frozen.patch} | 6 +++--- ...02-Optimise-ArraySetSorted-removeIf.patch} | 0 ...entity-collision-code-if-not-needed.patch} | 0 ...teleport-command-to-valid-locations.patch} | 0 ...Implement-Player-Client-Options-API.patch} | 4 ++-- ...Chunk-Post-Processing-deadlock-risk.patch} | 10 +++++----- ...ayer-is-attempted-to-be-removed-fro.patch} | 0 ...8-Broadcast-join-message-to-console.patch} | 0 ...-Broken-behavior-of-PlayerJoinEvent.patch} | 8 ++++---- ...oad-Chunks-for-Login-Asynchronously.patch} | 6 +++--- ...awn-point-if-spawn-in-unloaded-worl.patch} | 0 ...layerAttackEntityCooldownResetEvent.patch} | 0 ...llbacks-to-schedule-for-Callback-Ex.patch} | 4 ++-- ...-fire-BlockFade-on-worldgen-threads.patch} | 0 ...tom-creative-and-insomniac-controls.patch} | 4 ++-- ...-duplication-issues-and-teleport-is.patch} | 0 ...0417-Implement-Brigadier-Mojang-API.patch} | 0 ...patch => 0418-Villager-Restocks-API.patch} | 0 ...ickItem-Packet-and-kick-for-invalid.patch} | 0 ...n.patch => 0420-Expose-game-version.patch} | 0 ...> 0421-Optimize-Voxel-Shape-Merging.patch} | 0 ...per-thread-native-byte-buffer-cache.patch} | 0 ...atch => 0423-Implement-Mob-Goal-API.patch} | 0 61 files changed, 59 insertions(+), 60 deletions(-) rename patches/server/{0362-Tracking-Range-Improvements.patch => 0363-Tracking-Range-Improvements.patch} (100%) rename patches/server/{0363-Fix-items-vanishing-through-end-portal.patch => 0364-Fix-items-vanishing-through-end-portal.patch} (100%) rename patches/server/{0363-implement-optional-per-player-mob-spawns.patch => 0365-implement-optional-per-player-mob-spawns.patch} (99%) rename patches/server/{0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch => 0366-Bees-get-gravity-in-void.-Fixes-MC-167279.patch} (100%) rename patches/server/{0365-Optimise-getChunkAt-calls-for-loaded-chunks.patch => 0367-Optimise-getChunkAt-calls-for-loaded-chunks.patch} (96%) rename patches/server/{0366-Allow-overriding-the-java-version-check.patch => 0368-Allow-overriding-the-java-version-check.patch} (100%) rename patches/server/{0367-Add-ThrownEggHatchEvent.patch => 0369-Add-ThrownEggHatchEvent.patch} (100%) rename patches/server/{0368-Optimise-random-block-ticking.patch => 0370-Optimise-random-block-ticking.patch} (100%) rename patches/server/{0369-Entity-Jump-API.patch => 0371-Entity-Jump-API.patch} (100%) rename patches/server/{0370-Add-option-to-nerf-pigmen-from-nether-portals.patch => 0372-Add-option-to-nerf-pigmen-from-nether-portals.patch} (95%) rename patches/server/{0371-Make-the-GUI-graph-fancier.patch => 0373-Make-the-GUI-graph-fancier.patch} (100%) rename patches/server/{0372-add-hand-to-BlockMultiPlaceEvent.patch => 0374-add-hand-to-BlockMultiPlaceEvent.patch} (100%) rename patches/server/{0373-Prevent-teleporting-dead-entities.patch => 0375-Prevent-teleporting-dead-entities.patch} (100%) rename patches/server/{0374-Validate-tripwire-hook-placement-before-update.patch => 0376-Validate-tripwire-hook-placement-before-update.patch} (100%) rename patches/server/{0375-Add-option-to-allow-iron-golems-to-spawn-in-air.patch => 0377-Add-option-to-allow-iron-golems-to-spawn-in-air.patch} (92%) rename patches/server/{0376-Configurable-chance-of-villager-zombie-infection.patch => 0378-Configurable-chance-of-villager-zombie-infection.patch} (94%) rename patches/server/{0377-Optimise-Chunk-getFluid.patch => 0379-Optimise-Chunk-getFluid.patch} (100%) rename patches/server/{0378-Optimise-TickListServer-by-rewriting-it.patch => 0380-Optimise-TickListServer-by-rewriting-it.patch} (99%) rename patches/server/{0379-Pillager-patrol-spawn-settings-and-per-player-option.patch => 0381-Pillager-patrol-spawn-settings-and-per-player-option.patch} (95%) rename patches/server/{0380-Remote-Connections-shouldn-t-hold-up-shutdown.patch => 0382-Remote-Connections-shouldn-t-hold-up-shutdown.patch} (100%) rename patches/server/{0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch => 0383-Do-not-allow-bees-to-load-chunks-for-beehives.patch} (100%) rename patches/server/{0382-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch => 0384-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch} (94%) rename patches/server/{0383-Optimize-Collision-to-not-load-chunks.patch => 0385-Optimize-Collision-to-not-load-chunks.patch} (100%) rename patches/server/{0384-Don-t-tick-dead-players.patch => 0386-Don-t-tick-dead-players.patch} (85%) rename patches/server/{0385-Dead-Player-s-shouldn-t-be-able-to-move.patch => 0387-Dead-Player-s-shouldn-t-be-able-to-move.patch} (100%) rename patches/server/{0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch => 0388-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch} (95%) rename patches/server/{0387-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch => 0389-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch} (97%) rename patches/server/{0388-Don-t-move-existing-players-to-world-spawn.patch => 0390-Don-t-move-existing-players-to-world-spawn.patch} (92%) rename patches/server/{0389-Add-tick-times-API-and-mspt-command.patch => 0391-Add-tick-times-API-and-mspt-command.patch} (100%) rename patches/server/{0390-Expose-MinecraftServer-isRunning.patch => 0392-Expose-MinecraftServer-isRunning.patch} (100%) rename patches/server/{0391-Add-Raw-Byte-ItemStack-Serialization.patch => 0393-Add-Raw-Byte-ItemStack-Serialization.patch} (100%) rename patches/server/{0392-Remove-streams-from-Mob-AI-System.patch => 0394-Remove-streams-from-Mob-AI-System.patch} (100%) rename patches/server/{0393-Async-command-map-building.patch => 0395-Async-command-map-building.patch} (100%) rename patches/server/{0394-Improved-Watchdog-Support.patch => 0396-Improved-Watchdog-Support.patch} (99%) rename patches/server/{0395-Optimize-Pathfinding.patch => 0397-Optimize-Pathfinding.patch} (100%) rename patches/server/{0396-Reduce-Either-Optional-allocation.patch => 0398-Reduce-Either-Optional-allocation.patch} (100%) rename patches/server/{0397-Remove-streams-from-PairedQueue.patch => 0399-Remove-streams-from-PairedQueue.patch} (100%) rename patches/server/{0398-Reduce-memory-footprint-of-NBTTagCompound.patch => 0400-Reduce-memory-footprint-of-NBTTagCompound.patch} (100%) rename patches/server/{0399-Prevent-opening-inventories-when-frozen.patch => 0401-Prevent-opening-inventories-when-frozen.patch} (94%) rename patches/server/{0400-Optimise-ArraySetSorted-removeIf.patch => 0402-Optimise-ArraySetSorted-removeIf.patch} (100%) rename patches/server/{0401-Don-t-run-entity-collision-code-if-not-needed.patch => 0403-Don-t-run-entity-collision-code-if-not-needed.patch} (100%) rename patches/server/{0402-Restrict-vanilla-teleport-command-to-valid-locations.patch => 0404-Restrict-vanilla-teleport-command-to-valid-locations.patch} (100%) rename patches/server/{0403-Implement-Player-Client-Options-API.patch => 0405-Implement-Player-Client-Options-API.patch} (97%) rename patches/server/{0404-Fix-Chunk-Post-Processing-deadlock-risk.patch => 0406-Fix-Chunk-Post-Processing-deadlock-risk.patch} (88%) rename patches/server/{0405-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch => 0407-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch} (100%) rename patches/server/{0406-Broadcast-join-message-to-console.patch => 0408-Broadcast-join-message-to-console.patch} (100%) rename patches/server/{0407-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch => 0409-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch} (95%) rename patches/server/{0408-Load-Chunks-for-Login-Asynchronously.patch => 0410-Load-Chunks-for-Login-Asynchronously.patch} (98%) rename patches/server/{0409-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch => 0411-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch} (100%) rename patches/server/{0410-Add-PlayerAttackEntityCooldownResetEvent.patch => 0412-Add-PlayerAttackEntityCooldownResetEvent.patch} (100%) rename patches/server/{0411-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch => 0413-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch} (92%) rename patches/server/{0412-Don-t-fire-BlockFade-on-worldgen-threads.patch => 0414-Don-t-fire-BlockFade-on-worldgen-threads.patch} (100%) rename patches/server/{0413-Add-phantom-creative-and-insomniac-controls.patch => 0415-Add-phantom-creative-and-insomniac-controls.patch} (96%) rename patches/server/{0414-Fix-numerous-item-duplication-issues-and-teleport-is.patch => 0416-Fix-numerous-item-duplication-issues-and-teleport-is.patch} (100%) rename patches/server/{0415-Implement-Brigadier-Mojang-API.patch => 0417-Implement-Brigadier-Mojang-API.patch} (100%) rename patches/server/{0416-Villager-Restocks-API.patch => 0418-Villager-Restocks-API.patch} (100%) rename patches/server/{0417-Validate-PickItem-Packet-and-kick-for-invalid.patch => 0419-Validate-PickItem-Packet-and-kick-for-invalid.patch} (100%) rename patches/server/{0418-Expose-game-version.patch => 0420-Expose-game-version.patch} (100%) rename patches/server/{0419-Optimize-Voxel-Shape-Merging.patch => 0421-Optimize-Voxel-Shape-Merging.patch} (100%) rename patches/server/{0420-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch => 0422-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch} (100%) rename patches/server/{0421-Implement-Mob-Goal-API.patch => 0423-Implement-Mob-Goal-API.patch} (100%) diff --git a/patches/server/0362-Tracking-Range-Improvements.patch b/patches/server/0363-Tracking-Range-Improvements.patch similarity index 100% rename from patches/server/0362-Tracking-Range-Improvements.patch rename to patches/server/0363-Tracking-Range-Improvements.patch diff --git a/patches/server/0363-Fix-items-vanishing-through-end-portal.patch b/patches/server/0364-Fix-items-vanishing-through-end-portal.patch similarity index 100% rename from patches/server/0363-Fix-items-vanishing-through-end-portal.patch rename to patches/server/0364-Fix-items-vanishing-through-end-portal.patch diff --git a/patches/server/0363-implement-optional-per-player-mob-spawns.patch b/patches/server/0365-implement-optional-per-player-mob-spawns.patch similarity index 99% rename from patches/server/0363-implement-optional-per-player-mob-spawns.patch rename to patches/server/0365-implement-optional-per-player-mob-spawns.patch index c62f193d01..8d1082349a 100644 --- a/patches/server/0363-implement-optional-per-player-mob-spawns.patch +++ b/patches/server/0365-implement-optional-per-player-mob-spawns.patch @@ -38,7 +38,7 @@ index be4a36df28d4f16727daad1270d5c3a84ae94613..16f013ffe992a934e9d0b32e764a14a8 + perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); + } } - + diff --git a/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java new file mode 100644 index 0000000000000000000000000000000000000000..2a87599922d7075a9f888f48a2deb35ed3eb7c54 @@ -297,10 +297,9 @@ index 0000000000000000000000000000000000000000..2a87599922d7075a9f888f48a2deb35e + } + } +} - diff --git a/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java new file mode 100644 -index 0000000000000000000000000000000000000000..4f13d3ff8391793a99f067189f854078334499c6 +index 0000000000000000000000000000000000000000..11de56afaf059b00fa5bec293516bcdce7c4b2b9 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java @@ -0,0 +1,241 @@ @@ -546,7 +545,7 @@ index 0000000000000000000000000000000000000000..4f13d3ff8391793a99f067189f854078 + } +} diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index fdf5d8ede4b01e399272ddebfbd49258b166f00b..bd4133466eb8ad2f5f69fdf5b04bc45734cec9a4 100644 +index 273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c..e1498a5a8e664b922c77a8524ed2ea38c91834ce 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -69,6 +69,7 @@ import net.minecraft.util.thread.ProcessorMailbox; diff --git a/patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/0366-Bees-get-gravity-in-void.-Fixes-MC-167279.patch similarity index 100% rename from patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch rename to patches/server/0366-Bees-get-gravity-in-void.-Fixes-MC-167279.patch diff --git a/patches/server/0365-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server/0367-Optimise-getChunkAt-calls-for-loaded-chunks.patch similarity index 96% rename from patches/server/0365-Optimise-getChunkAt-calls-for-loaded-chunks.patch rename to patches/server/0367-Optimise-getChunkAt-calls-for-loaded-chunks.patch index 5eea71802d..8a08a84198 100644 --- a/patches/server/0365-Optimise-getChunkAt-calls-for-loaded-chunks.patch +++ b/patches/server/0367-Optimise-getChunkAt-calls-for-loaded-chunks.patch @@ -7,7 +7,7 @@ bypass the need to get a player chunk, then get the either, then unwrap it... diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index c47d1772044913475a60292162ef4be594bed4c6..7cbd3db81c73d466a6e6012c1c91698b53a0cb86 100644 +index 78143fe566fef13604c46029d4184ba39ed4aefc..56aa640eb0096e5c5f1a34d6f11a4dd9ac8770df 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -451,6 +451,12 @@ public class ServerChunkCache extends ChunkSource { diff --git a/patches/server/0366-Allow-overriding-the-java-version-check.patch b/patches/server/0368-Allow-overriding-the-java-version-check.patch similarity index 100% rename from patches/server/0366-Allow-overriding-the-java-version-check.patch rename to patches/server/0368-Allow-overriding-the-java-version-check.patch diff --git a/patches/server/0367-Add-ThrownEggHatchEvent.patch b/patches/server/0369-Add-ThrownEggHatchEvent.patch similarity index 100% rename from patches/server/0367-Add-ThrownEggHatchEvent.patch rename to patches/server/0369-Add-ThrownEggHatchEvent.patch diff --git a/patches/server/0368-Optimise-random-block-ticking.patch b/patches/server/0370-Optimise-random-block-ticking.patch similarity index 100% rename from patches/server/0368-Optimise-random-block-ticking.patch rename to patches/server/0370-Optimise-random-block-ticking.patch diff --git a/patches/server/0369-Entity-Jump-API.patch b/patches/server/0371-Entity-Jump-API.patch similarity index 100% rename from patches/server/0369-Entity-Jump-API.patch rename to patches/server/0371-Entity-Jump-API.patch diff --git a/patches/server/0370-Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/0372-Add-option-to-nerf-pigmen-from-nether-portals.patch similarity index 95% rename from patches/server/0370-Add-option-to-nerf-pigmen-from-nether-portals.patch rename to patches/server/0372-Add-option-to-nerf-pigmen-from-nether-portals.patch index ede8b0de95..bd3b08c4c3 100644 --- a/patches/server/0370-Add-option-to-nerf-pigmen-from-nether-portals.patch +++ b/patches/server/0372-Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to nerf pigmen from nether portals diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3cd8895adecd345c3bdfb8b5e3e9fdf0ef9097db..e70e0b1115422b9b901c2879138433da2d4f94d8 100644 +index 16f013ffe992a934e9d0b32e764a14a8fd204449..6c7e90f9939d42fdf8d40dd7ec0a6a86d5437451 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -441,6 +441,11 @@ public class PaperWorldConfig { +@@ -446,6 +446,11 @@ public class PaperWorldConfig { log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); } diff --git a/patches/server/0371-Make-the-GUI-graph-fancier.patch b/patches/server/0373-Make-the-GUI-graph-fancier.patch similarity index 100% rename from patches/server/0371-Make-the-GUI-graph-fancier.patch rename to patches/server/0373-Make-the-GUI-graph-fancier.patch diff --git a/patches/server/0372-add-hand-to-BlockMultiPlaceEvent.patch b/patches/server/0374-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from patches/server/0372-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/server/0374-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/patches/server/0373-Prevent-teleporting-dead-entities.patch b/patches/server/0375-Prevent-teleporting-dead-entities.patch similarity index 100% rename from patches/server/0373-Prevent-teleporting-dead-entities.patch rename to patches/server/0375-Prevent-teleporting-dead-entities.patch diff --git a/patches/server/0374-Validate-tripwire-hook-placement-before-update.patch b/patches/server/0376-Validate-tripwire-hook-placement-before-update.patch similarity index 100% rename from patches/server/0374-Validate-tripwire-hook-placement-before-update.patch rename to patches/server/0376-Validate-tripwire-hook-placement-before-update.patch diff --git a/patches/server/0375-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server/0377-Add-option-to-allow-iron-golems-to-spawn-in-air.patch similarity index 92% rename from patches/server/0375-Add-option-to-allow-iron-golems-to-spawn-in-air.patch rename to patches/server/0377-Add-option-to-allow-iron-golems-to-spawn-in-air.patch index 35a64d65e2..3f7ba7afc5 100644 --- a/patches/server/0375-Add-option-to-allow-iron-golems-to-spawn-in-air.patch +++ b/patches/server/0377-Add-option-to-allow-iron-golems-to-spawn-in-air.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to allow iron golems to spawn in air diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e70e0b1115422b9b901c2879138433da2d4f94d8..19e0532ea296d6862ab6508658726e96e05346c9 100644 +index 6c7e90f9939d42fdf8d40dd7ec0a6a86d5437451..3ac4fe247dd12e039396da5276b83709957823c7 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -380,6 +380,11 @@ public class PaperWorldConfig { +@@ -385,6 +385,11 @@ public class PaperWorldConfig { scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); } diff --git a/patches/server/0376-Configurable-chance-of-villager-zombie-infection.patch b/patches/server/0378-Configurable-chance-of-villager-zombie-infection.patch similarity index 94% rename from patches/server/0376-Configurable-chance-of-villager-zombie-infection.patch rename to patches/server/0378-Configurable-chance-of-villager-zombie-infection.patch index 7c01b2f514..2e4e196e34 100644 --- a/patches/server/0376-Configurable-chance-of-villager-zombie-infection.patch +++ b/patches/server/0378-Configurable-chance-of-villager-zombie-infection.patch @@ -8,10 +8,10 @@ This allows you to solve an issue in vanilla behavior where: * On normal difficulty they will have a 50% of getting infected or dying. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 19e0532ea296d6862ab6508658726e96e05346c9..b57d9c84db5685b86cb077e3b42db7a8578d6f62 100644 +index 3ac4fe247dd12e039396da5276b83709957823c7..0863bdab8322b80a3df52c238b55c14401bafe6d 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -451,6 +451,11 @@ public class PaperWorldConfig { +@@ -456,6 +456,11 @@ public class PaperWorldConfig { nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); } diff --git a/patches/server/0377-Optimise-Chunk-getFluid.patch b/patches/server/0379-Optimise-Chunk-getFluid.patch similarity index 100% rename from patches/server/0377-Optimise-Chunk-getFluid.patch rename to patches/server/0379-Optimise-Chunk-getFluid.patch diff --git a/patches/server/0378-Optimise-TickListServer-by-rewriting-it.patch b/patches/server/0380-Optimise-TickListServer-by-rewriting-it.patch similarity index 99% rename from patches/server/0378-Optimise-TickListServer-by-rewriting-it.patch rename to patches/server/0380-Optimise-TickListServer-by-rewriting-it.patch index b5d38ff419..20aa3203b6 100644 --- a/patches/server/0378-Optimise-TickListServer-by-rewriting-it.patch +++ b/patches/server/0380-Optimise-TickListServer-by-rewriting-it.patch @@ -924,7 +924,7 @@ index 995d7977233f0d7683c00a75c3833f9a1eba7f92..58369d70bcd8b2c25609b6f101d9cbe2 }); // Paper end diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 7cbd3db81c73d466a6e6012c1c91698b53a0cb86..382a68c76e8946840de62f05483870689de80278 100644 +index 56aa640eb0096e5c5f1a34d6f11a4dd9ac8770df..a81c773cc281ba390d3ce44c52c43710b43829a5 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -220,6 +220,12 @@ public class ServerChunkCache extends ChunkSource { diff --git a/patches/server/0379-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/0381-Pillager-patrol-spawn-settings-and-per-player-option.patch similarity index 95% rename from patches/server/0379-Pillager-patrol-spawn-settings-and-per-player-option.patch rename to patches/server/0381-Pillager-patrol-spawn-settings-and-per-player-option.patch index ff68539cdb..150228e975 100644 --- a/patches/server/0379-Pillager-patrol-spawn-settings-and-per-player-option.patch +++ b/patches/server/0381-Pillager-patrol-spawn-settings-and-per-player-option.patch @@ -10,10 +10,10 @@ When not per player it will use the Vanilla mechanic of one delay per world and the world age for the start day. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b57d9c84db5685b86cb077e3b42db7a8578d6f62..9664786d471b949880030f5c6271bf9c12529326 100644 +index 0863bdab8322b80a3df52c238b55c14401bafe6d..4a2b52b5f5c0453c204765ec77e35524ee7e77c1 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -428,10 +428,21 @@ public class PaperWorldConfig { +@@ -433,10 +433,21 @@ public class PaperWorldConfig { } public boolean disablePillagerPatrols = false; @@ -36,10 +36,10 @@ index b57d9c84db5685b86cb077e3b42db7a8578d6f62..9664786d471b949880030f5c6271bf9c private void entitiesTargetWithFollowRange() { entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index bffc897cb88a54c36432c98264f3416051aeab17..5b5a0c0db79452ee07c40bf7693b6701dbe0b615 100644 +index 14a0190ea5e9a387582736bb130c16a3bc94151e..c3ed4358b0cb6f252f9e3f71abe4ec9624cb7694 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -219,6 +219,7 @@ public class ServerPlayer extends Player { +@@ -214,6 +214,7 @@ public class ServerPlayer extends Player { public boolean wonGame; private int containerUpdateDelay; // Paper public long loginTime; // Paper diff --git a/patches/server/0380-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server/0382-Remote-Connections-shouldn-t-hold-up-shutdown.patch similarity index 100% rename from patches/server/0380-Remote-Connections-shouldn-t-hold-up-shutdown.patch rename to patches/server/0382-Remote-Connections-shouldn-t-hold-up-shutdown.patch diff --git a/patches/server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/0383-Do-not-allow-bees-to-load-chunks-for-beehives.patch similarity index 100% rename from patches/server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch rename to patches/server/0383-Do-not-allow-bees-to-load-chunks-for-beehives.patch diff --git a/patches/server/0382-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server/0384-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch similarity index 94% rename from patches/server/0382-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch rename to patches/server/0384-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch index 60f46ed4f2..9f991f3e0d 100644 --- a/patches/server/0382-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ b/patches/server/0384-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -7,10 +7,10 @@ Suspected case would be around the technique used in .stopRiding Stack will identify any causer of this and warn instead of crashing. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c..d06c6828180b7864bf4d3736a65ea0a2dc7804e2 100644 +index e1498a5a8e664b922c77a8524ed2ea38c91834ce..71d5c298e14869d9d44226aeb6ffe3f051827d1a 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1445,6 +1445,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1467,6 +1467,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider protected void addEntity(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot diff --git a/patches/server/0383-Optimize-Collision-to-not-load-chunks.patch b/patches/server/0385-Optimize-Collision-to-not-load-chunks.patch similarity index 100% rename from patches/server/0383-Optimize-Collision-to-not-load-chunks.patch rename to patches/server/0385-Optimize-Collision-to-not-load-chunks.patch diff --git a/patches/server/0384-Don-t-tick-dead-players.patch b/patches/server/0386-Don-t-tick-dead-players.patch similarity index 85% rename from patches/server/0384-Don-t-tick-dead-players.patch rename to patches/server/0386-Don-t-tick-dead-players.patch index d831e3b2b6..95d2e787e5 100644 --- a/patches/server/0384-Don-t-tick-dead-players.patch +++ b/patches/server/0386-Don-t-tick-dead-players.patch @@ -7,10 +7,10 @@ Causes sync chunk loads and who knows what all else. This is safe because Spectators are skipped in unloaded chunks too in vanilla. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 5b5a0c0db79452ee07c40bf7693b6701dbe0b615..2822d493500dcd01c26ff5b205da83d8d356e119 100644 +index c3ed4358b0cb6f252f9e3f71abe4ec9624cb7694..791aa76cd09b3597f6f1e0d7e302fe9a446ea8e5 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -637,7 +637,7 @@ public class ServerPlayer extends Player { +@@ -638,7 +638,7 @@ public class ServerPlayer extends Player { public void doTick() { try { diff --git a/patches/server/0385-Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server/0387-Dead-Player-s-shouldn-t-be-able-to-move.patch similarity index 100% rename from patches/server/0385-Dead-Player-s-shouldn-t-be-able-to-move.patch rename to patches/server/0387-Dead-Player-s-shouldn-t-be-able-to-move.patch diff --git a/patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/0388-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch similarity index 95% rename from patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch rename to patches/server/0388-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch index 8118c956ed..66741a4086 100644 --- a/patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch +++ b/patches/server/0388-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch @@ -70,10 +70,10 @@ index 9c88426ab1275ee5fb6e28be8b213533dc4ab859..87c9a5c1b43f6010898d72136b5eb997 List allChunks = new ArrayList<>(visibleChunks.values()); List players = world.players; diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index d06c6828180b7864bf4d3736a65ea0a2dc7804e2..c304c57a572b7e154362b39065ab8cb30a7e112e 100644 +index 71d5c298e14869d9d44226aeb6ffe3f051827d1a..a75de538835522f92e889452fddd5a3d8fc25f07 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -107,9 +107,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -108,9 +108,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider private static final int MIN_VIEW_DISTANCE = 3; public static final int MAX_VIEW_DISTANCE = 33; public static final int MAX_CHUNK_DISTANCE = 33 + ChunkStatus.maxDistance(); @@ -112,7 +112,7 @@ index d06c6828180b7864bf4d3736a65ea0a2dc7804e2..c304c57a572b7e154362b39065ab8cb3 private final Long2ObjectLinkedOpenHashMap pendingUnloads; public final LongSet entitiesInLevel; // Paper - private -> public public final ServerLevel level; -@@ -231,7 +258,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -233,7 +260,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { super(new File(session.getDimensionPath(world.dimension()), "region"), dataFixer, dsync); @@ -121,7 +121,7 @@ index d06c6828180b7864bf4d3736a65ea0a2dc7804e2..c304c57a572b7e154362b39065ab8cb3 this.pendingUnloads = new Long2ObjectLinkedOpenHashMap(); this.entitiesInLevel = new LongOpenHashSet(); this.toDrop = new LongOpenHashSet(); -@@ -350,9 +377,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -372,9 +399,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return (ChunkHolder) this.updatingChunkMap.get(pos); } @@ -175,7 +175,7 @@ index d06c6828180b7864bf4d3736a65ea0a2dc7804e2..c304c57a572b7e154362b39065ab8cb3 } protected IntSupplier getChunkQueueLevel(long pos) { -@@ -509,8 +579,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -531,8 +601,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } protected void saveAllChunks(boolean flush) { @@ -186,7 +186,7 @@ index d06c6828180b7864bf4d3736a65ea0a2dc7804e2..c304c57a572b7e154362b39065ab8cb3 MutableBoolean mutableboolean = new MutableBoolean(); do { -@@ -541,7 +612,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -563,7 +634,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // this.i(); // Paper - nuke IOWorker ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); } else { @@ -195,7 +195,7 @@ index d06c6828180b7864bf4d3736a65ea0a2dc7804e2..c304c57a572b7e154362b39065ab8cb3 ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error if (ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk) { -@@ -701,7 +772,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -723,7 +794,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (!this.modified) { return false; } else { @@ -217,7 +217,7 @@ index d06c6828180b7864bf4d3736a65ea0a2dc7804e2..c304c57a572b7e154362b39065ab8cb3 this.modified = false; return true; } -@@ -1110,12 +1194,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1132,12 +1216,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } protected Iterable getChunks() { @@ -233,10 +233,10 @@ index d06c6828180b7864bf4d3736a65ea0a2dc7804e2..c304c57a572b7e154362b39065ab8cb3 while (objectbidirectionaliterator.hasNext()) { Entry entry = (Entry) objectbidirectionaliterator.next(); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 382a68c76e8946840de62f05483870689de80278..8523fbd66ed42cd5b959d57cab515fa4a774a575 100644 +index a81c773cc281ba390d3ce44c52c43710b43829a5..34183527a23650706a9249ffac0182cb77b18086 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -751,7 +751,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -766,7 +766,7 @@ public class ServerChunkCache extends ChunkSource { }; // Paper end this.level.timings.chunkTicks.startTiming(); // Paper diff --git a/patches/server/0387-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/patches/server/0389-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch similarity index 97% rename from patches/server/0387-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch rename to patches/server/0389-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch index 395f0c27cf..6f6470fd04 100644 --- a/patches/server/0387-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch +++ b/patches/server/0389-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch @@ -147,7 +147,7 @@ index 494a3afaaa0e3496d30e8d97edbab62b21610dfe..fa3a9d763f7072c68b126ce95fee191a // Spigot Start CrashReport crashreport; diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 8523fbd66ed42cd5b959d57cab515fa4a774a575..751454ad5a2c374c01ff360535428db36c0aa1b3 100644 +index 34183527a23650706a9249ffac0182cb77b18086..90decfade57b2f17cdcc9188962c2d2140a16b1e 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -703,6 +703,7 @@ public class ServerChunkCache extends ChunkSource { @@ -166,7 +166,7 @@ index 8523fbd66ed42cd5b959d57cab515fa4a774a575..751454ad5a2c374c01ff360535428db3 this.level.timings.doChunkUnload.stopTiming(); // Spigot this.level.getProfiler().pop(); this.clearCache(); -@@ -751,7 +753,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -766,7 +768,7 @@ public class ServerChunkCache extends ChunkSource { }; // Paper end this.level.timings.chunkTicks.startTiming(); // Paper @@ -175,7 +175,7 @@ index 8523fbd66ed42cd5b959d57cab515fa4a774a575..751454ad5a2c374c01ff360535428db3 Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); if (optional.isPresent()) { -@@ -768,6 +770,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -783,6 +785,7 @@ public class ServerChunkCache extends ChunkSource { chunk.setInhabitedTime(chunk.getInhabitedTime() + j); if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); @@ -183,7 +183,7 @@ index 8523fbd66ed42cd5b959d57cab515fa4a774a575..751454ad5a2c374c01ff360535428db3 } // this.level.timings.doTickTiles.startTiming(); // Spigot // Paper -@@ -935,6 +938,41 @@ public class ServerChunkCache extends ChunkSource { +@@ -950,6 +953,41 @@ public class ServerChunkCache extends ChunkSource { super.doRunTask(task); } diff --git a/patches/server/0388-Don-t-move-existing-players-to-world-spawn.patch b/patches/server/0390-Don-t-move-existing-players-to-world-spawn.patch similarity index 92% rename from patches/server/0388-Don-t-move-existing-players-to-world-spawn.patch rename to patches/server/0390-Don-t-move-existing-players-to-world-spawn.patch index 6b5d0a25e6..2ca582d971 100644 --- a/patches/server/0388-Don-t-move-existing-players-to-world-spawn.patch +++ b/patches/server/0390-Don-t-move-existing-players-to-world-spawn.patch @@ -10,7 +10,7 @@ larger than the keep loaded range. By skipping this, we avoid potential for a large spike on server start. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 2822d493500dcd01c26ff5b205da83d8d356e119..bfa91166c18110877f751a5325e59623a05325d0 100644 +index 791aa76cd09b3597f6f1e0d7e302fe9a446ea8e5..a2103ba85e012bbeaf5ecf91db8d5203f576e285 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -309,7 +309,7 @@ public class ServerPlayer extends Player { @@ -22,7 +22,7 @@ index 2822d493500dcd01c26ff5b205da83d8d356e119..bfa91166c18110877f751a5325e59623 this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -@@ -359,7 +359,7 @@ public class ServerPlayer extends Player { +@@ -360,7 +360,7 @@ public class ServerPlayer extends Player { } // CraftBukkit end @@ -31,7 +31,7 @@ index 2822d493500dcd01c26ff5b205da83d8d356e119..bfa91166c18110877f751a5325e59623 BlockPos blockposition = world.getSharedSpawnPos(); if (world.dimensionType().hasSkyLight() && world.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit -@@ -527,7 +527,7 @@ public class ServerPlayer extends Player { +@@ -528,7 +528,7 @@ public class ServerPlayer extends Player { position = Vec3.atCenterOf(((ServerLevel) world).getSharedSpawnPos()); } this.level = world; diff --git a/patches/server/0389-Add-tick-times-API-and-mspt-command.patch b/patches/server/0391-Add-tick-times-API-and-mspt-command.patch similarity index 100% rename from patches/server/0389-Add-tick-times-API-and-mspt-command.patch rename to patches/server/0391-Add-tick-times-API-and-mspt-command.patch diff --git a/patches/server/0390-Expose-MinecraftServer-isRunning.patch b/patches/server/0392-Expose-MinecraftServer-isRunning.patch similarity index 100% rename from patches/server/0390-Expose-MinecraftServer-isRunning.patch rename to patches/server/0392-Expose-MinecraftServer-isRunning.patch diff --git a/patches/server/0391-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/0393-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 100% rename from patches/server/0391-Add-Raw-Byte-ItemStack-Serialization.patch rename to patches/server/0393-Add-Raw-Byte-ItemStack-Serialization.patch diff --git a/patches/server/0392-Remove-streams-from-Mob-AI-System.patch b/patches/server/0394-Remove-streams-from-Mob-AI-System.patch similarity index 100% rename from patches/server/0392-Remove-streams-from-Mob-AI-System.patch rename to patches/server/0394-Remove-streams-from-Mob-AI-System.patch diff --git a/patches/server/0393-Async-command-map-building.patch b/patches/server/0395-Async-command-map-building.patch similarity index 100% rename from patches/server/0393-Async-command-map-building.patch rename to patches/server/0395-Async-command-map-building.patch diff --git a/patches/server/0394-Improved-Watchdog-Support.patch b/patches/server/0396-Improved-Watchdog-Support.patch similarity index 99% rename from patches/server/0394-Improved-Watchdog-Support.patch rename to patches/server/0396-Improved-Watchdog-Support.patch index be6786aadf..52408524a3 100644 --- a/patches/server/0394-Improved-Watchdog-Support.patch +++ b/patches/server/0396-Improved-Watchdog-Support.patch @@ -262,10 +262,10 @@ index 0511f1921193b78cbf4d8426136bf1f79746f955..e5f7f043cbdb28d85b8aa0eea7cbaeb5 @Override diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index c304c57a572b7e154362b39065ab8cb30a7e112e..c82345c74e0e6246f304283c2e06e2d1fcfe53ca 100644 +index a75de538835522f92e889452fddd5a3d8fc25f07..ccf50500b53f7336db1d3d287ec6f2a0da3d4183 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -585,6 +585,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -607,6 +607,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider MutableBoolean mutableboolean = new MutableBoolean(); do { diff --git a/patches/server/0395-Optimize-Pathfinding.patch b/patches/server/0397-Optimize-Pathfinding.patch similarity index 100% rename from patches/server/0395-Optimize-Pathfinding.patch rename to patches/server/0397-Optimize-Pathfinding.patch diff --git a/patches/server/0396-Reduce-Either-Optional-allocation.patch b/patches/server/0398-Reduce-Either-Optional-allocation.patch similarity index 100% rename from patches/server/0396-Reduce-Either-Optional-allocation.patch rename to patches/server/0398-Reduce-Either-Optional-allocation.patch diff --git a/patches/server/0397-Remove-streams-from-PairedQueue.patch b/patches/server/0399-Remove-streams-from-PairedQueue.patch similarity index 100% rename from patches/server/0397-Remove-streams-from-PairedQueue.patch rename to patches/server/0399-Remove-streams-from-PairedQueue.patch diff --git a/patches/server/0398-Reduce-memory-footprint-of-NBTTagCompound.patch b/patches/server/0400-Reduce-memory-footprint-of-NBTTagCompound.patch similarity index 100% rename from patches/server/0398-Reduce-memory-footprint-of-NBTTagCompound.patch rename to patches/server/0400-Reduce-memory-footprint-of-NBTTagCompound.patch diff --git a/patches/server/0399-Prevent-opening-inventories-when-frozen.patch b/patches/server/0401-Prevent-opening-inventories-when-frozen.patch similarity index 94% rename from patches/server/0399-Prevent-opening-inventories-when-frozen.patch rename to patches/server/0401-Prevent-opening-inventories-when-frozen.patch index 29b12f74db..2c7b34bab9 100644 --- a/patches/server/0399-Prevent-opening-inventories-when-frozen.patch +++ b/patches/server/0401-Prevent-opening-inventories-when-frozen.patch @@ -5,10 +5,10 @@ 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 bfa91166c18110877f751a5325e59623a05325d0..42c2862530cff79a9b09850faccb683df1f2a5c8 100644 +index a2103ba85e012bbeaf5ecf91db8d5203f576e285..d9db660db873bade362ef40aa776293a001564a9 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -608,7 +608,7 @@ public class ServerPlayer extends Player { +@@ -609,7 +609,7 @@ public class ServerPlayer extends Player { containerUpdateDelay = level.paperConfig.containerUpdateTickRate; } // Paper end @@ -17,7 +17,7 @@ index bfa91166c18110877f751a5325e59623a05325d0..42c2862530cff79a9b09850faccb683d this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper this.containerMenu = this.inventoryMenu; } -@@ -1449,7 +1449,7 @@ public class ServerPlayer extends Player { +@@ -1450,7 +1450,7 @@ public class ServerPlayer extends Player { } else { // CraftBukkit start this.containerMenu = container; diff --git a/patches/server/0400-Optimise-ArraySetSorted-removeIf.patch b/patches/server/0402-Optimise-ArraySetSorted-removeIf.patch similarity index 100% rename from patches/server/0400-Optimise-ArraySetSorted-removeIf.patch rename to patches/server/0402-Optimise-ArraySetSorted-removeIf.patch diff --git a/patches/server/0401-Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server/0403-Don-t-run-entity-collision-code-if-not-needed.patch similarity index 100% rename from patches/server/0401-Don-t-run-entity-collision-code-if-not-needed.patch rename to patches/server/0403-Don-t-run-entity-collision-code-if-not-needed.patch diff --git a/patches/server/0402-Restrict-vanilla-teleport-command-to-valid-locations.patch b/patches/server/0404-Restrict-vanilla-teleport-command-to-valid-locations.patch similarity index 100% rename from patches/server/0402-Restrict-vanilla-teleport-command-to-valid-locations.patch rename to patches/server/0404-Restrict-vanilla-teleport-command-to-valid-locations.patch diff --git a/patches/server/0403-Implement-Player-Client-Options-API.patch b/patches/server/0405-Implement-Player-Client-Options-API.patch similarity index 97% rename from patches/server/0403-Implement-Player-Client-Options-API.patch rename to patches/server/0405-Implement-Player-Client-Options-API.patch index 0f85780783..ef5eadd098 100644 --- a/patches/server/0403-Implement-Player-Client-Options-API.patch +++ b/patches/server/0405-Implement-Player-Client-Options-API.patch @@ -85,10 +85,10 @@ index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabb + } +} diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 42c2862530cff79a9b09850faccb683df1f2a5c8..aec3ded7f65e4a97796afc01b71eeb89c2b3fb70 100644 +index d9db660db873bade362ef40aa776293a001564a9..c3aae7bc629b08b8bc1b40973adebfd6aa1edbfd 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1801,6 +1801,7 @@ public class ServerPlayer extends Player { +@@ -1802,6 +1802,7 @@ public class ServerPlayer extends Player { public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null public java.util.Locale adventure$locale = java.util.Locale.US; // Paper public void updateOptions(ServerboundClientInformationPacket packet) { diff --git a/patches/server/0404-Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server/0406-Fix-Chunk-Post-Processing-deadlock-risk.patch similarity index 88% rename from patches/server/0404-Fix-Chunk-Post-Processing-deadlock-risk.patch rename to patches/server/0406-Fix-Chunk-Post-Processing-deadlock-risk.patch index eff3a55349..0818f079c0 100644 --- a/patches/server/0404-Fix-Chunk-Post-Processing-deadlock-risk.patch +++ b/patches/server/0406-Fix-Chunk-Post-Processing-deadlock-risk.patch @@ -25,10 +25,10 @@ This successfully fixed a reoccurring and highly reproduceable crash for heightmaps. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index c82345c74e0e6246f304283c2e06e2d1fcfe53ca..d3094c8a6a906737d4ca56a76ff40b3586961680 100644 +index ccf50500b53f7336db1d3d287ec6f2a0da3d4183..f651b7d2bbc2fc883bc73ef892de62624d1285e7 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -189,6 +189,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -191,6 +191,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider }; // CraftBukkit end @@ -36,7 +36,7 @@ index c82345c74e0e6246f304283c2e06e2d1fcfe53ca..d3094c8a6a906737d4ca56a76ff40b35 // Paper start - distance maps private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); // Paper start - no-tick view distance -@@ -1028,7 +1029,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1050,7 +1051,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return Either.left(chunk); }); }, (runnable) -> { @@ -46,10 +46,10 @@ index c82345c74e0e6246f304283c2e06e2d1fcfe53ca..d3094c8a6a906737d4ca56a76ff40b35 completablefuture1.thenAcceptAsync((either) -> { diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 751454ad5a2c374c01ff360535428db36c0aa1b3..e4f5f564892836a2e925f419e8fcb60c70b21a47 100644 +index 90decfade57b2f17cdcc9188962c2d2140a16b1e..60cdb1f5c3f329b417f340f1d2651d89c244e439 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -985,6 +985,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -1000,6 +1000,7 @@ public class ServerChunkCache extends ChunkSource { return super.pollTask() || execChunkTask; // Paper } } finally { diff --git a/patches/server/0405-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/patches/server/0407-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch similarity index 100% rename from patches/server/0405-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch rename to patches/server/0407-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch diff --git a/patches/server/0406-Broadcast-join-message-to-console.patch b/patches/server/0408-Broadcast-join-message-to-console.patch similarity index 100% rename from patches/server/0406-Broadcast-join-message-to-console.patch rename to patches/server/0408-Broadcast-join-message-to-console.patch diff --git a/patches/server/0407-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/patches/server/0409-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch similarity index 95% rename from patches/server/0407-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch rename to patches/server/0409-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch index c85247b418..3f471ab0a6 100644 --- a/patches/server/0407-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch +++ b/patches/server/0409-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch @@ -28,10 +28,10 @@ receives a deterministic result, and should no longer require 1 tick delays anymore. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index d3094c8a6a906737d4ca56a76ff40b3586961680..2cb807f7095648948527b5b9151770193970cc00 100644 +index f651b7d2bbc2fc883bc73ef892de62624d1285e7..6c763b5407425b764839b921f4dc9e18d76442cd 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1529,7 +1529,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1551,7 +1551,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // Paper end - per player view distance } @@ -40,7 +40,7 @@ index d3094c8a6a906737d4ca56a76ff40b3586961680..2cb807f7095648948527b5b915177019 org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot // Paper start - ignore and warn about illegal addEntity calls instead of crashing server if (!entity.valid || entity.level != this.level || this.entityMap.containsKey(entity.getId())) { -@@ -1538,6 +1538,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1560,6 +1560,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider .printStackTrace(); return; } @@ -49,7 +49,7 @@ index d3094c8a6a906737d4ca56a76ff40b3586961680..2cb807f7095648948527b5b915177019 if (!(entity instanceof EnderDragonPart)) { EntityType entitytypes = entity.getType(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index aec3ded7f65e4a97796afc01b71eeb89c2b3fb70..a30840b74bc2574725c42735f633630d9b471d54 100644 +index c3aae7bc629b08b8bc1b40973adebfd6aa1edbfd..48f089040dd21342d001b91135ec9128ad5e1027 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -237,6 +237,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0408-Load-Chunks-for-Login-Asynchronously.patch b/patches/server/0410-Load-Chunks-for-Login-Asynchronously.patch similarity index 98% rename from patches/server/0408-Load-Chunks-for-Login-Asynchronously.patch rename to patches/server/0410-Load-Chunks-for-Login-Asynchronously.patch index 399eeca8a3..22009dda6e 100644 --- a/patches/server/0408-Load-Chunks-for-Login-Asynchronously.patch +++ b/patches/server/0410-Load-Chunks-for-Login-Asynchronously.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Load Chunks for Login Asynchronously diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index e4f5f564892836a2e925f419e8fcb60c70b21a47..afc9431b61f2953229765ef90005b7968fbed591 100644 +index 60cdb1f5c3f329b417f340f1d2651d89c244e439..3d1c4f8e0db37c6dabece657a17595e7bf1e3dc2 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -630,7 +630,7 @@ public class ServerChunkCache extends ChunkSource { @@ -18,10 +18,10 @@ index e4f5f564892836a2e925f419e8fcb60c70b21a47..afc9431b61f2953229765ef90005b796 boolean flag1 = this.chunkMap.promoteChunkMap(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index a30840b74bc2574725c42735f633630d9b471d54..d4ec913a96c5f8f9780d78f6f340d844718a5849 100644 +index 48f089040dd21342d001b91135ec9128ad5e1027..c083ee1322f86809300fce1552eacd663aaa650d 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -177,6 +177,7 @@ public class ServerPlayer extends Player { +@@ -172,6 +172,7 @@ public class ServerPlayer extends Player { private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; public ServerGamePacketListenerImpl connection; diff --git a/patches/server/0409-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/patches/server/0411-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch similarity index 100% rename from patches/server/0409-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch rename to patches/server/0411-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch diff --git a/patches/server/0410-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server/0412-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from patches/server/0410-Add-PlayerAttackEntityCooldownResetEvent.patch rename to patches/server/0412-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/patches/server/0411-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/patches/server/0413-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch similarity index 92% rename from patches/server/0411-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch rename to patches/server/0413-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch index 1ad36331ec..2dc86442f7 100644 --- a/patches/server/0411-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch +++ b/patches/server/0413-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch @@ -14,10 +14,10 @@ Use an ArrayDeque to store this Queue We make sure to also implement a pattern that is recursion safe too. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 2cb807f7095648948527b5b9151770193970cc00..7fa35cba408d036e649e6d63bace88e6047c02b4 100644 +index 6c763b5407425b764839b921f4dc9e18d76442cd..f81c7a6bf2ba1564874a7865cde3c4f36e28055a 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -172,15 +172,27 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -174,15 +174,27 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public final CallbackExecutor callbackExecutor = new CallbackExecutor(); public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { diff --git a/patches/server/0412-Don-t-fire-BlockFade-on-worldgen-threads.patch b/patches/server/0414-Don-t-fire-BlockFade-on-worldgen-threads.patch similarity index 100% rename from patches/server/0412-Don-t-fire-BlockFade-on-worldgen-threads.patch rename to patches/server/0414-Don-t-fire-BlockFade-on-worldgen-threads.patch diff --git a/patches/server/0413-Add-phantom-creative-and-insomniac-controls.patch b/patches/server/0415-Add-phantom-creative-and-insomniac-controls.patch similarity index 96% rename from patches/server/0413-Add-phantom-creative-and-insomniac-controls.patch rename to patches/server/0415-Add-phantom-creative-and-insomniac-controls.patch index 6b22ec66cb..ae7582ec64 100644 --- a/patches/server/0413-Add-phantom-creative-and-insomniac-controls.patch +++ b/patches/server/0415-Add-phantom-creative-and-insomniac-controls.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add phantom creative and insomniac controls diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9664786d471b949880030f5c6271bf9c12529326..45058c715152e3ffa5ec1c79a472e32d63d69e02 100644 +index 4a2b52b5f5c0453c204765ec77e35524ee7e77c1..16cf7d116e3ffd44ffc4f060b4014b52389cff77 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -472,6 +472,13 @@ public class PaperWorldConfig { +@@ -477,6 +477,13 @@ public class PaperWorldConfig { lightQueueSize = getInt("light-queue-size", lightQueueSize); } diff --git a/patches/server/0414-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/patches/server/0416-Fix-numerous-item-duplication-issues-and-teleport-is.patch similarity index 100% rename from patches/server/0414-Fix-numerous-item-duplication-issues-and-teleport-is.patch rename to patches/server/0416-Fix-numerous-item-duplication-issues-and-teleport-is.patch diff --git a/patches/server/0415-Implement-Brigadier-Mojang-API.patch b/patches/server/0417-Implement-Brigadier-Mojang-API.patch similarity index 100% rename from patches/server/0415-Implement-Brigadier-Mojang-API.patch rename to patches/server/0417-Implement-Brigadier-Mojang-API.patch diff --git a/patches/server/0416-Villager-Restocks-API.patch b/patches/server/0418-Villager-Restocks-API.patch similarity index 100% rename from patches/server/0416-Villager-Restocks-API.patch rename to patches/server/0418-Villager-Restocks-API.patch diff --git a/patches/server/0417-Validate-PickItem-Packet-and-kick-for-invalid.patch b/patches/server/0419-Validate-PickItem-Packet-and-kick-for-invalid.patch similarity index 100% rename from patches/server/0417-Validate-PickItem-Packet-and-kick-for-invalid.patch rename to patches/server/0419-Validate-PickItem-Packet-and-kick-for-invalid.patch diff --git a/patches/server/0418-Expose-game-version.patch b/patches/server/0420-Expose-game-version.patch similarity index 100% rename from patches/server/0418-Expose-game-version.patch rename to patches/server/0420-Expose-game-version.patch diff --git a/patches/server/0419-Optimize-Voxel-Shape-Merging.patch b/patches/server/0421-Optimize-Voxel-Shape-Merging.patch similarity index 100% rename from patches/server/0419-Optimize-Voxel-Shape-Merging.patch rename to patches/server/0421-Optimize-Voxel-Shape-Merging.patch diff --git a/patches/server/0420-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/patches/server/0422-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch similarity index 100% rename from patches/server/0420-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch rename to patches/server/0422-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch diff --git a/patches/server/0421-Implement-Mob-Goal-API.patch b/patches/server/0423-Implement-Mob-Goal-API.patch similarity index 100% rename from patches/server/0421-Implement-Mob-Goal-API.patch rename to patches/server/0423-Implement-Mob-Goal-API.patch From 5e62aca6c99dfd4e2f60d7e8b047c1df9912e656 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 20:06:11 -0700 Subject: [PATCH 095/226] small fixes --- .../0365-implement-optional-per-player-mob-spawns.patch | 6 +++--- ...-multiple-callbacks-to-schedule-for-Callback-Ex.patch | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/patches/server/0365-implement-optional-per-player-mob-spawns.patch b/patches/server/0365-implement-optional-per-player-mob-spawns.patch index 8d1082349a..1ca06b50fd 100644 --- a/patches/server/0365-implement-optional-per-player-mob-spawns.patch +++ b/patches/server/0365-implement-optional-per-player-mob-spawns.patch @@ -41,7 +41,7 @@ index be4a36df28d4f16727daad1270d5c3a84ae94613..16f013ffe992a934e9d0b32e764a14a8 diff --git a/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java new file mode 100644 -index 0000000000000000000000000000000000000000..2a87599922d7075a9f888f48a2deb35ed3eb7c54 +index 0000000000000000000000000000000000000000..72063ba7fb0d04594043cb07034590d597c3d77e --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java @@ -0,0 +1,252 @@ @@ -92,7 +92,7 @@ index 0000000000000000000000000000000000000000..2a87599922d7075a9f888f48a2deb35e + + gone.remove(player); + -+ final SectionPos newPosition = player.getPlayerMapSection(); ++ final SectionPos newPosition = player.getLastSectionPos(); + final SectionPos oldPosition = this.players.put(player, newPosition); + + if (oldPosition == null) { @@ -117,7 +117,7 @@ index 0000000000000000000000000000000000000000..2a87599922d7075a9f888f48a2deb35e + int expectedEntries = (2 * viewDistance + 1); + expectedEntries *= expectedEntries; + -+ final SectionPos currPosition = player.getPlayerMapSection(); ++ final SectionPos currPosition = player.getLastSectionPos(); + + final int centerX = currPosition.getX(); + final int centerZ = currPosition.getZ(); diff --git a/patches/server/0413-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/patches/server/0413-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch index 2dc86442f7..9ced634f50 100644 --- a/patches/server/0413-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch +++ b/patches/server/0413-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch @@ -14,10 +14,10 @@ Use an ArrayDeque to store this Queue We make sure to also implement a pattern that is recursion safe too. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 6c763b5407425b764839b921f4dc9e18d76442cd..f81c7a6bf2ba1564874a7865cde3c4f36e28055a 100644 +index 6c763b5407425b764839b921f4dc9e18d76442cd..f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -174,15 +174,27 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -174,17 +174,29 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public final CallbackExecutor callbackExecutor = new CallbackExecutor(); public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { @@ -44,5 +44,8 @@ index 6c763b5407425b764839b921f4dc9e18d76442cd..f81c7a6bf2ba1564874a7865cde3c4f3 + this.queue = null; + // Paper end Runnable task; - while ((task = this.queue.poll()) != null) { +- while ((task = this.queue.poll()) != null) { ++ while ((task = queue.poll()) != null) { // Paper task.run(); + } + } From 961f297963d2ad43f3fbf4868523b738c473c9a0 Mon Sep 17 00:00:00 2001 From: Omer Uddin Date: Mon, 14 Jun 2021 00:29:25 -0400 Subject: [PATCH 096/226] fix exception (#5822) --- .../0365-implement-optional-per-player-mob-spawns.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/server/0365-implement-optional-per-player-mob-spawns.patch b/patches/server/0365-implement-optional-per-player-mob-spawns.patch index 1ca06b50fd..225d30ce9d 100644 --- a/patches/server/0365-implement-optional-per-player-mob-spawns.patch +++ b/patches/server/0365-implement-optional-per-player-mob-spawns.patch @@ -707,7 +707,7 @@ index e20a645e28a2e503c02b2bd89424e95506a2e6df..18a28659a72a761f53ca226bbf9866b4 - if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (rareSpawn || !enumcreaturetype.isPersistent()) && info.a(enumcreaturetype, limit)) { + // Paper start - only allow spawns upto the limit per chunk and update count afterwards -+ int currEntityCount = info.getMobCategoryCounts().getInt(enumcreaturetype); ++ int currEntityCount = info.mobCategoryCounts.getInt(enumcreaturetype); + int k1 = limit * info.getSpawnableChunkCount() / NaturalSpawner.MAGIC_NUMBER; + int difference = k1 - currEntityCount; + @@ -730,7 +730,7 @@ index e20a645e28a2e503c02b2bd89424e95506a2e6df..18a28659a72a761f53ca226bbf9866b4 - NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn); + int spawnCount = NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn, + difference, world.paperConfig.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null); -+ info.getMobCategoryCounts().mergeInt(enumcreaturetype, spawnCount, Integer::sum); ++ info.mobCategoryCounts.mergeInt(enumcreaturetype, spawnCount, Integer::sum); + // Paper end - per player mob spawning } } From d001eefd7e3266f535d306c7a747f9f20176b2a8 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 21:27:51 -0700 Subject: [PATCH 097/226] 2 patch --- ...ance-map-to-optimise-entity-tracker.patch} | 118 ++++++----- ...isOutsideRange-to-use-distance-maps.patch} | 185 +++++++++--------- 2 files changed, 145 insertions(+), 158 deletions(-) rename patches/{server-remapped/0467-Use-distance-map-to-optimise-entity-tracker.patch => server/0424-Use-distance-map-to-optimise-entity-tracker.patch} (80%) rename patches/{server-remapped/0468-Optimize-isOutsideRange-to-use-distance-maps.patch => server/0425-Optimize-isOutsideRange-to-use-distance-maps.patch} (75%) diff --git a/patches/server-remapped/0467-Use-distance-map-to-optimise-entity-tracker.patch b/patches/server/0424-Use-distance-map-to-optimise-entity-tracker.patch similarity index 80% rename from patches/server-remapped/0467-Use-distance-map-to-optimise-entity-tracker.patch rename to patches/server/0424-Use-distance-map-to-optimise-entity-tracker.patch index 16a647e328..9c57b25122 100644 --- a/patches/server-remapped/0467-Use-distance-map-to-optimise-entity-tracker.patch +++ b/patches/server/0424-Use-distance-map-to-optimise-entity-tracker.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Use distance map to optimise entity tracker Use the distance map to find candidate players for tracking. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e5ad635a480d32e7a10ee92c65cfc18a98beafad..74f393ffa2ae2d0e25b3f0b674cef7a987e985d3 100644 +index 11fd6d24ed0612e4df1a0493907178fb9c455d1c..d7023cb0974f6c28a0fb8a0a6e5a6600fe30d3e3 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1652,6 +1652,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); +@@ -222,11 +223,33 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap; + public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap; + // Paper end - no-tick view distance + // Paper start - use distance map to optimise tracker + public static boolean isLegacyTrackingEntity(Entity entity) { + return entity.isLegacyTrackingEntity; @@ -60,6 +60,10 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f + trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); + } + // Paper end - use distance map to optimise entity tracker + // Paper start - no-tick view distance + int effectiveTickViewDistance = this.getEffectiveViewDistance(); + int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); +@@ -243,7 +266,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } void removePlayerFromDistanceMaps(ServerPlayer player) { @@ -69,9 +73,10 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f + this.playerEntityTrackerTrackMaps[i].remove(player); + } + // Paper end - use distance map to optimise tracker - } - - void updateMaps(ServerPlayer player) { + // Paper start - no-tick view distance + this.playerViewDistanceBroadcastMap.remove(player); + this.playerViewDistanceTickMap.remove(player); +@@ -255,6 +282,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider int chunkX = MCUtil.getChunkCoordinate(player.getX()); int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); // Note: players need to be explicitly added to distance maps before they can be updated @@ -83,12 +88,12 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f + trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); + } + // Paper end - use distance map to optimise entity tracker - } - // Paper end - -@@ -244,6 +279,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper - this.setViewDistance(i); + // Paper start - no-tick view distance + int effectiveTickViewDistance = this.getEffectiveViewDistance(); + int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); +@@ -306,6 +341,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world); + this.setViewDistance(viewDistance); this.playerMobDistanceMap = this.level.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper + // Paper start - use distance map to optimise entity tracker + this.playerEntityTrackerTrackMaps = new com.destroystokyo.paper.util.misc.PlayerAreaMap[TRACKING_RANGE_TYPES.length]; @@ -129,10 +134,10 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f + this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); + } + // Paper end - use distance map to optimise entity tracker - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -1490,17 +1564,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper start - no-tick view distance + this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); + this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, +@@ -1424,17 +1498,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } public void move(ServerPlayer player) { @@ -149,18 +154,18 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f - } + // Paper - delay this logic for the entity tracker tick, no need to duplicate it - int i = Mth.floor(player.getX()) >> 4; - int j = Mth.floor(player.getZ()) >> 4; -@@ -1616,7 +1680,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + int i = SectionPos.blockToSectionCoord(player.getBlockX()); + int j = SectionPos.blockToSectionCoord(player.getBlockZ()); +@@ -1589,7 +1653,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker - this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); -- playerchunkmap_entitytracker.updatePlayers(this.level.players()); -+ playerchunkmap_entitytracker.updatePlayers(entity.getPlayersInTrackRange()); // Paper - don't search all players - if (entity instanceof ServerPlayer) { - ServerPlayer entityplayer = (ServerPlayer) entity; + entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker + this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); +- playerchunkmap_entitytracker.updatePlayers(this.level.players()); ++ playerchunkmap_entitytracker.updatePlayers(entity.getPlayersInTrackRange()); // Paper - don't search all players + if (entity instanceof ServerPlayer) { + ServerPlayer entityplayer = (ServerPlayer) entity; -@@ -1659,7 +1723,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1633,7 +1697,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider entity.tracker = null; // Paper - We're no longer tracked } @@ -198,7 +203,7 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f List list = Lists.newArrayList(); List list1 = this.level.players(); -@@ -1728,23 +1822,31 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1742,23 +1836,31 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos()); List list = Lists.newArrayList(); List list1 = Lists.newArrayList(); @@ -222,7 +227,7 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f + // keep the vanilla logic here - this is REQUIRED or else passengers and their vehicles disappear! + // (and god knows what the leash thing is) -- if (entity != player && entity.xChunk == chunk.getPos().x && entity.zChunk == chunk.getPos().z) { +- if (entity != player && entity.chunkPosition().equals(chunk.getPos())) { - playerchunkmap_entitytracker.updatePlayer(player); - if (entity instanceof Mob && ((Mob) entity).getLeashHolder() != null) { - list.add(entity); @@ -242,16 +247,7 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f Iterator iterator; Entity entity1; -@@ -1782,7 +1884,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - public class TrackedEntity { - -- private final ServerEntity serverEntity; -+ final ServerEntity serverEntity; // Paper - private -> package private - private final Entity entity; - private final int range; - private SectionPos lastSectionPos; -@@ -1799,6 +1901,42 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1837,6 +1939,42 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially this.lastSectionPos = SectionPos.of(entity); } @@ -283,9 +279,9 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f + // stuff could have been removed, so we need to check the trackedPlayers set + // for players that were removed + -+ for (ServerPlayer player : this.seenBy.toArray(new ServerPlayer[0])) { // avoid CME -+ if (newTrackerCandidates == null || !newTrackerCandidates.contains(player)) { -+ this.updatePlayer(player); ++ for (ServerPlayerConnection conn : this.seenBy.toArray(new ServerPlayerConnection[0])) { // avoid CME ++ if (newTrackerCandidates == null || !newTrackerCandidates.contains(conn)) { ++ this.updatePlayer(conn.getPlayer()); + } + } + } @@ -294,7 +290,7 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f public boolean equals(Object object) { return object instanceof ChunkMap.TrackedEntity ? ((ChunkMap.TrackedEntity) object).entity.getId() == this.entity.getId() : false; } -@@ -1899,7 +2037,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1922,7 +2060,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially int j = entity.getType().clientTrackingRange() * 16; j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper @@ -304,10 +300,10 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f } } diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index 1609ab94c86e964421f996d4d46aef30f8b8e696..d797873db52ba265ac4478f9f3c6344badd4739e 100644 +index 28afe2f238ded241acf77c3272a44068646b9133..6b492b72b177e3c58580561585609b176876acf1 100644 --- a/src/main/java/net/minecraft/server/level/ServerEntity.java +++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -100,6 +100,7 @@ public class ServerEntity { +@@ -87,6 +87,7 @@ public class ServerEntity { this.wasOnGround = entity.isOnGround(); } @@ -316,18 +312,18 @@ index 1609ab94c86e964421f996d4d46aef30f8b8e696..d797873db52ba265ac4478f9f3c6344b List list = this.entity.getPassengers(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 2b48c4a2b512c42bed2c767db90a28898c74286a..d9bb00752ac81b2171d3ad25fd84904467a18e3b 100644 +index 9897a0ac66dd788b0b22a88b20ca86a386e397e4..dec5690bd90830bace704b553dbcd1d2633ab668 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -46,6 +46,7 @@ import net.minecraft.network.syncher.EntityDataSerializers; +@@ -50,6 +50,7 @@ import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MCUtil; import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; -@@ -294,6 +295,21 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + import net.minecraft.server.level.ServerPlayer; +@@ -322,6 +323,21 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } // CraftBukkit end @@ -348,20 +344,20 @@ index 2b48c4a2b512c42bed2c767db90a28898c74286a..d9bb00752ac81b2171d3ad25fd849044 + public Entity(EntityType type, Level world) { this.id = Entity.ENTITY_COUNTER.incrementAndGet(); - this.passengers = Lists.newArrayList(); + this.passengers = ImmutableList.of(); diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java -index b03fa9024c7f0238e1379f6ae4486db5300a70e9..7b6011be849ecffdd791d439f70ae5dffc96f264 100644 +index 24b1dfcf91d36947c87e9e5c2524317f8775ba95..e5bcbfe175a697e04886d04543e1278b7e83a184 100644 --- a/src/main/java/org/spigotmc/TrackingRange.java +++ b/src/main/java/org/spigotmc/TrackingRange.java -@@ -20,6 +20,7 @@ public class TrackingRange - */ - public static int getEntityTrackingRange(Entity entity, int defaultRange) - { +@@ -24,6 +24,7 @@ public class TrackingRange + { + return defaultRange; + } + if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return defaultRange; // Paper - enderdragon is exempt SpigotWorldConfig config = entity.level.spigotConfig; if ( entity instanceof ServerPlayer ) { -@@ -43,8 +44,48 @@ public class TrackingRange +@@ -47,8 +48,48 @@ public class TrackingRange return config.miscTrackingRange; } else { diff --git a/patches/server-remapped/0468-Optimize-isOutsideRange-to-use-distance-maps.patch b/patches/server/0425-Optimize-isOutsideRange-to-use-distance-maps.patch similarity index 75% rename from patches/server-remapped/0468-Optimize-isOutsideRange-to-use-distance-maps.patch rename to patches/server/0425-Optimize-isOutsideRange-to-use-distance-maps.patch index adc6c14065..2971066550 100644 --- a/patches/server-remapped/0468-Optimize-isOutsideRange-to-use-distance-maps.patch +++ b/patches/server/0425-Optimize-isOutsideRange-to-use-distance-maps.patch @@ -6,12 +6,12 @@ Subject: [PATCH] Optimize isOutsideRange to use distance maps Use a distance map to find the players in range quickly diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index d12d5459c847d3f0d655c85e31d81c27b7a2face..0147798c0285f64b8d767dfb2709d92f66ac72ef 100644 +index 58369d70bcd8b2c25609b6f101d9cbe2031df352..969b0c9cf6d7eb2055d3b804f25a3cbc161ceaea 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -69,6 +69,18 @@ public class ChunkHolder { - long lastAutoSaveTime; // Paper - incremental autosave - long inactiveTimeStart; // Paper - incremental autosave +@@ -100,6 +100,18 @@ public class ChunkHolder { + } + // Paper end + // Paper start - optimise isOutsideOfRange + // cached here to avoid a map lookup @@ -25,22 +25,22 @@ index d12d5459c847d3f0d655c85e31d81c27b7a2face..0147798c0285f64b8d767dfb2709d92f + } + // Paper end - optimise isOutsideOfRange + - public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; -@@ -85,6 +97,7 @@ public class ChunkHolder { - this.queueLevel = this.oldTicketLevel; +@@ -121,6 +133,7 @@ public class ChunkHolder { this.setTicketLevel(level); + this.changedBlocksPerSection = new ShortSet[world.getSectionsCount()]; this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper + this.updateRanges(); // Paper - optimise isOutsideOfRange } - // Paper start + // CraftBukkit start diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c756a5be9 100644 +index f7032e1d64afa6707756bb5a2af9d43a808c9736..18335e2c5c9e50a8ed31a3d2b585835bcc28bbe6 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -208,6 +208,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -237,6 +237,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); } // Paper end - use distance map to optimise tracker @@ -58,17 +58,20 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c void addPlayerToDistanceMaps(ServerPlayer player) { int chunkX = MCUtil.getChunkCoordinate(player.getX()); -@@ -221,6 +232,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -250,6 +261,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); } // Paper end - use distance map to optimise entity tracker + // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - optimise PlayerChunkMap#isOutsideRange + this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); + // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - void removePlayerFromDistanceMaps(ServerPlayer player) { -@@ -229,6 +243,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper start - no-tick view distance + int effectiveTickViewDistance = this.getEffectiveViewDistance(); + int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); +@@ -271,6 +288,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.playerEntityTrackerTrackMaps[i].remove(player); } // Paper end - use distance map to optimise tracker @@ -76,29 +79,29 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c + this.playerMobSpawnMap.remove(player); + this.playerChunkTickRangeMap.remove(player); + // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - void updateMaps(ServerPlayer player) { -@@ -243,6 +261,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper start - no-tick view distance + this.playerViewDistanceBroadcastMap.remove(player); + this.playerViewDistanceTickMap.remove(player); +@@ -290,6 +311,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); } // Paper end - use distance map to optimise entity tracker + // Paper start - optimise PlayerChunkMap#isOutsideRange + this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); + // Paper end - optimise PlayerChunkMap#isOutsideRange - } - // Paper end - -@@ -274,7 +295,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); + // Paper start - no-tick view distance + int effectiveTickViewDistance = this.getEffectiveViewDistance(); + int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); +@@ -336,7 +360,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); + this.mailboxLight = this.queueSorter.getProcessor(lightthreaded, false);// Paper this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); -- this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); -+ this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper - this.overworldDataStorage = supplier; - this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper - this.setViewDistance(i); -@@ -318,6 +339,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +- this.distanceManager = new ChunkMap.ChunkDistanceManager(executor, mainThreadExecutor); ++ this.distanceManager = new ChunkMap.ChunkDistanceManager(executor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper + this.overworldDataStorage = persistentStateManagerFactory; + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world); + this.setViewDistance(viewDistance); +@@ -380,6 +404,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); } // Paper end - use distance map to optimise entity tracker @@ -134,18 +137,10 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c + } + }); + // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -337,6 +390,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return entityPlayer.mobCounts[enumCreatureType.ordinal()]; - } - -+ private static double getDistanceSquaredFromChunk(ChunkPos chunkPos, Entity entity) { return euclideanDistanceSquared(chunkPos, entity); } // Paper - OBFHELPER - private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { - double d0 = (double) (pos.x * 16 + 8); - double d1 = (double) (pos.z * 16 + 8); -@@ -515,6 +569,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper start - no-tick view distance + this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); + this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, +@@ -649,6 +705,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } else { if (holder != null) { holder.setTicketLevel(level); @@ -153,46 +148,40 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c } if (holder != null) { -@@ -1493,30 +1548,53 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return isOutsideOfRange(chunkcoordintpair, false); +@@ -1434,29 +1491,50 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return this.isOutsideOfRange(chunkPos, false); } - boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) { - int chunkRange = level.spigotConfig.mobSpawnRange; - chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; - chunkRange = (chunkRange > 8) ? 8 : chunkRange; -+ // Paper start - optimise isOutsideOfRange -+ final boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) { -+ return this.isOutsideOfRange(this.getUpdatingChunkIfPresent(chunkcoordintpair.toLong()), chunkcoordintpair, reducedRange); -+ } - +- - final int finalChunkRange = chunkRange; // Paper for lambda below - //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event - // Spigot end - long i = chunkcoordintpair.toLong(); ++ // Paper start - optimise isOutsideOfRange ++ final boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) { ++ return this.isOutsideOfRange(this.getUpdatingChunkIfPresent(chunkcoordintpair.toLong()), chunkcoordintpair, reducedRange); ++ } + final boolean isOutsideOfRange(ChunkHolder playerchunk, ChunkPos chunkcoordintpair, boolean reducedRange) { + // this function is so hot that removing the map lookup call can have an order of magnitude impact on its performance + // tested and confirmed via System.nanoTime() + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInRange = reducedRange ? playerchunk.playersInMobSpawnRange : playerchunk.playersInChunkTickRange; ++ if (playersInRange == null) { ++ return true; ++ } ++ Object[] backingSet = playersInRange.getBackingSet(); -- return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { -- // Paper start - +- return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.getPlayers(i).noneMatch((entityplayer) -> { +- // Paper start - add PlayerNaturallySpawnCreaturesEvent - com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; - double blockRange = 16384.0D; - if (reducedRange) { - event = entityplayer.playerNaturallySpawnedEvent; - if (event == null || event.isCancelled()) return false; - blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); -- } -+ if (playersInRange == null) { -+ return true; -+ } - -- return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot -- // Paper end -- }); -+ Object[] backingSet = playersInRange.getBackingSet(); -+ + if (reducedRange) { + for (int i = 0, len = backingSet.length; i < len; ++i) { + Object raw = backingSet[i]; @@ -201,10 +190,13 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c + } + ServerPlayer player = (ServerPlayer) raw; + // don't check spectator and whatnot, already handled by mob spawn map update -+ if (player.lastEntitySpawnRadiusSquared > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { ++ if (player.lastEntitySpawnRadiusSquared > euclideanDistanceSquared(chunkcoordintpair, player)) { + return false; // in range + } -+ } + } +- // Paper end +- return !entityplayer.isSpectator() && ChunkMap.euclideanDistanceSquared(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot +- }); + } else { + final double range = (DistanceManager.MOB_SPAWN_RANGE * 16) * (DistanceManager.MOB_SPAWN_RANGE * 16); + // before spigot, mob spawn range was actually mob spawn range + tick range, but it was split @@ -215,7 +207,7 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c + } + ServerPlayer player = (ServerPlayer) raw; + // don't check spectator and whatnot, already handled by mob spawn map update -+ if (range > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { ++ if (range > euclideanDistanceSquared(chunkcoordintpair, player)) { + return false; // in range + } + } @@ -228,11 +220,11 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c private boolean skipPlayer(ServerPlayer player) { return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5980d3467 100644 +index b49d380ef088aed3204ec71abc437c348ef004fa..577b391dcba1db712c1e2c83296e1c87b3e34ab2 100644 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java +++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -37,7 +37,7 @@ public abstract class DistanceManager { - private final Long2ObjectMap> playersPerChunk = new Long2ObjectOpenHashMap(); +@@ -45,7 +45,7 @@ public abstract class DistanceManager { + final Long2ObjectMap> playersPerChunk = new Long2ObjectOpenHashMap(); public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); - private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); @@ -240,25 +232,25 @@ index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5 private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); // Paper start use a queue, but still keep unique requirement public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { -@@ -56,6 +56,8 @@ public abstract class DistanceManager { - private final Executor mainThreadExecutor; +@@ -64,6 +64,8 @@ public abstract class DistanceManager { + final Executor mainThreadExecutor; private long ticketTickCounter; + ChunkMap chunkMap; // Paper + protected DistanceManager(Executor workerExecutor, Executor mainThreadExecutor) { - mainThreadExecutor.getClass(); + Objects.requireNonNull(mainThreadExecutor); ProcessorHandle mailbox = ProcessorHandle.of("player ticket throttler", mainThreadExecutor::execute); -@@ -100,7 +102,7 @@ public abstract class DistanceManager { +@@ -108,7 +110,7 @@ public abstract class DistanceManager { protected abstract ChunkHolder updateChunkScheduling(long pos, int level, @Nullable ChunkHolder holder, int k); - public boolean runAllUpdates(ChunkMap chunkStorage) { + public boolean runAllUpdates(ChunkMap playerchunkmap) { - this.naturalSpawnChunkCounter.runAllUpdates(); + //this.f.a(); // Paper - no longer used this.playerTicketManager.runAllUpdates(); int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE); boolean flag = i != 0; -@@ -236,7 +238,7 @@ public abstract class DistanceManager { +@@ -244,7 +246,7 @@ public abstract class DistanceManager { ((ObjectSet) this.playersPerChunk.computeIfAbsent(i, (j) -> { return new ObjectOpenHashSet(); })).add(player); @@ -267,7 +259,7 @@ index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5 this.playerTicketManager.update(i, 0, true); } -@@ -248,7 +250,7 @@ public abstract class DistanceManager { +@@ -256,7 +258,7 @@ public abstract class DistanceManager { if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully. if (objectset == null || objectset.isEmpty()) { // Paper this.playersPerChunk.remove(i); @@ -276,7 +268,7 @@ index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5 this.playerTicketManager.update(i, Integer.MAX_VALUE, false); } -@@ -272,13 +274,17 @@ public abstract class DistanceManager { +@@ -280,13 +282,17 @@ public abstract class DistanceManager { } public int getNaturalSpawnChunkCount() { @@ -299,11 +291,11 @@ index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5 public String getDebugStatus() { diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 79fb63c40dd0543a6f629e78f390f23f34992ba1..52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd 100644 +index 3d1c4f8e0db37c6dabece657a17595e7bf1e3dc2..3faa808f41f057a9956c697ec1323330f5920b86 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -753,6 +753,37 @@ public class ServerChunkCache extends ChunkSource { - boolean flag1 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !level.players().isEmpty(); // CraftBukkit +@@ -729,6 +729,37 @@ public class ServerChunkCache extends ChunkSource { + boolean flag1 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit if (!flag) { + // Paper start - optimize isOutisdeRange @@ -340,7 +332,7 @@ index 79fb63c40dd0543a6f629e78f390f23f34992ba1..52c2e81f2e2bcd74d4e9aac3ecb5ab61 this.level.getProfiler().push("pollingChunks"); int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); boolean flag2 = level.ticksPerAnimalSpawns != 0L && worlddata.getGameTime() % level.ticksPerAnimalSpawns == 0L; // CraftBukkit -@@ -782,15 +813,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -758,15 +789,7 @@ public class ServerChunkCache extends ChunkSource { this.level.getProfiler().pop(); //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper //Collections.shuffle(list); // Paper @@ -357,28 +349,27 @@ index 79fb63c40dd0543a6f629e78f390f23f34992ba1..52c2e81f2e2bcd74d4e9aac3ecb5ab61 this.level.timings.chunkTicks.startTiming(); // Paper final int[] chunksTicked = {0}; this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); -@@ -807,9 +830,9 @@ public class ServerChunkCache extends ChunkSource { - LevelChunk chunk = (LevelChunk) optional1.get(); - ChunkPos chunkcoordintpair = playerchunk.getPos(); - -- if (!this.chunkMap.noPlayersCloseForSpawning(chunkcoordintpair)) { -+ if (!this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange - chunk.setInhabitedTime(chunk.getInhabitedTime() + j); -- if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot -+ if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange - NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); - } +@@ -781,9 +804,9 @@ public class ServerChunkCache extends ChunkSource { + this.level.getProfiler().pop(); + ChunkPos chunkcoordintpair = chunk.getPos(); +- if (this.level.isPositionEntityTicking(chunkcoordintpair) && !this.chunkMap.noPlayersCloseForSpawning(chunkcoordintpair)) { ++ if (this.level.isPositionEntityTicking(chunkcoordintpair) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange + chunk.setInhabitedTime(chunk.getInhabitedTime() + j); +- if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot ++ if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange + NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); + if (chunksTicked[0]++ % 10 == 0) this.level.getServer().midTickLoadChunks(); // Paper + } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 24c508ade61a6ad90b0ef73cdc995f531ef18263..95f1f4727a8e2000931e6f36b862e3ad28334a69 100644 +index c083ee1322f86809300fce1552eacd663aaa650d..cd34b5aa61c78d8138500a93f0a9714bedd7ed86 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -247,6 +247,8 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -244,6 +244,7 @@ public class ServerPlayer extends Player { + // CraftBukkit end + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper ++ public double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + boolean needsChunkCenterUpdate; // Paper - no-tick view distance -+ double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks -+ - public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { - super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); - this.respawnDimension = Level.OVERWORLD; From 3c02c90f3e4c9e86d1690b5ba3ac3b9ffb80ec1d Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 22:32:56 -0700 Subject: [PATCH 098/226] progress --- .../0202-Add-villager-reputation-API.patch | 0 ...n.patch => 0203-Expose-game-version.patch} | 0 .../0204-Spawn-Reason-API.patch} | 2 +- .../0205-Potential-bed-API.patch} | 2 +- ...ioritise-own-classes-where-possible.patch} | 6 +- ...-a-useful-PluginClassLoader-toString.patch | 4 +- ...und-for-Client-Lag-Spikes-MC-162253.patch} | 58 ++++--------------- ...te-operations-for-updating-light-dat.patch | 2 + ...ze-NibbleArray-to-use-pooled-buffers.patch | 2 + ...3-Fix-PotionEffect-ignores-icon-flag.patch | 19 ------ .../0482-Ensure-safe-gateway-teleport.patch | 27 --------- .../0426-Add-villager-reputation-API.patch} | 37 +++++------- ...7-Fix-PotionEffect-ignores-icon-flag.patch | 19 ++++++ ...brigadier-child-sorting-performance.patch} | 11 ++-- .../0429-Potential-bed-API.patch} | 6 +- ...ait-for-Async-Tasks-during-shutdown.patch} | 6 +- ...er-respects-game-and-entity-rules-f.patch} | 6 +- ...nd-End-Portal-Frames-from-being-des.patch} | 42 +++++++------- ...leInt-allocations-from-light-engine.patch} | 38 ++++++------ ...location-of-Vec3D-by-entity-tracker.patch} | 26 +++------ .../0435-Ensure-safe-gateway-teleport.patch | 26 +++++++++ ...-for-console-having-all-permissions.patch} | 17 +----- ...n-Full-Status-Chunk-NBT-Memory-Leak.patch} | 20 +++---- 23 files changed, 157 insertions(+), 219 deletions(-) rename patches/{api-unmapped => api}/0202-Add-villager-reputation-API.patch (100%) rename patches/api/{0202-Expose-game-version.patch => 0203-Expose-game-version.patch} (100%) rename patches/{api-unmapped/0203-Spawn-Reason-API.patch => api/0204-Spawn-Reason-API.patch} (96%) rename patches/{api-unmapped/0204-Potential-bed-API.patch => api/0205-Potential-bed-API.patch} (93%) rename patches/{api-unmapped/0205-Prioritise-own-classes-where-possible.patch => api/0206-Prioritise-own-classes-where-possible.patch} (92%) rename patches/{api-unmapped => api}/0207-Provide-a-useful-PluginClassLoader-toString.patch (89%) rename patches/{server-remapped/0485-Workaround-for-Client-Lag-Spikes-MC-162253.patch => removed/1.17/0438-Workaround-for-Client-Lag-Spikes-MC-162253.patch} (56%) rename patches/{server-remapped => removed/1.17}/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch (99%) rename patches/{server-remapped => removed/1.17}/0479-Optimize-NibbleArray-to-use-pooled-buffers.patch (99%) delete mode 100644 patches/server-remapped/0473-Fix-PotionEffect-ignores-icon-flag.patch delete mode 100644 patches/server-remapped/0482-Ensure-safe-gateway-teleport.patch rename patches/{server-remapped/0471-Add-villager-reputation-API.patch => server/0426-Add-villager-reputation-API.patch} (87%) create mode 100644 patches/server/0427-Fix-PotionEffect-ignores-icon-flag.patch rename patches/{server-remapped/0474-Optimize-brigadier-child-sorting-performance.patch => server/0428-Optimize-brigadier-child-sorting-performance.patch} (70%) rename patches/{server-remapped/0475-Potential-bed-API.patch => server/0429-Potential-bed-API.patch} (90%) rename patches/{server-remapped/0476-Wait-for-Async-Tasks-during-shutdown.patch => server/0430-Wait-for-Async-Tasks-during-shutdown.patch} (91%) rename patches/{server-remapped/0477-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch => server/0431-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch} (85%) rename patches/{server-remapped/0478-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch => server/0432-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch} (81%) rename patches/{server-remapped/0480-Reduce-MutableInt-allocations-from-light-engine.patch => server/0433-Reduce-MutableInt-allocations-from-light-engine.patch} (59%) rename patches/{server-remapped/0481-Reduce-allocation-of-Vec3D-by-entity-tracker.patch => server/0434-Reduce-allocation-of-Vec3D-by-entity-tracker.patch} (78%) create mode 100644 patches/server/0435-Ensure-safe-gateway-teleport.patch rename patches/{server-remapped/0483-Add-option-for-console-having-all-permissions.patch => server/0436-Add-option-for-console-having-all-permissions.patch} (76%) rename patches/{server-remapped/0484-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch => server/0437-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch} (77%) diff --git a/patches/api-unmapped/0202-Add-villager-reputation-API.patch b/patches/api/0202-Add-villager-reputation-API.patch similarity index 100% rename from patches/api-unmapped/0202-Add-villager-reputation-API.patch rename to patches/api/0202-Add-villager-reputation-API.patch diff --git a/patches/api/0202-Expose-game-version.patch b/patches/api/0203-Expose-game-version.patch similarity index 100% rename from patches/api/0202-Expose-game-version.patch rename to patches/api/0203-Expose-game-version.patch diff --git a/patches/api-unmapped/0203-Spawn-Reason-API.patch b/patches/api/0204-Spawn-Reason-API.patch similarity index 96% rename from patches/api-unmapped/0203-Spawn-Reason-API.patch rename to patches/api/0204-Spawn-Reason-API.patch index 0ee08ee996..78038ce509 100644 --- a/patches/api-unmapped/0203-Spawn-Reason-API.patch +++ b/patches/api/0204-Spawn-Reason-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Spawn Reason API diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 476184db904d8a2e1347e1219e8ba196bf4da5cb..c1010e314144a65e12eaf5514d639a87f45891a9 100644 +index cd96c851d00185e7ee3ec6682b166fc1d06b6a73..10c22809535b6151b45aa18a02b80b8f2e3e6dff 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -1,6 +1,8 @@ diff --git a/patches/api-unmapped/0204-Potential-bed-API.patch b/patches/api/0205-Potential-bed-API.patch similarity index 93% rename from patches/api-unmapped/0204-Potential-bed-API.patch rename to patches/api/0205-Potential-bed-API.patch index b8b1e2519a..1e630dff90 100644 --- a/patches/api-unmapped/0204-Potential-bed-API.patch +++ b/patches/api/0205-Potential-bed-API.patch @@ -8,7 +8,7 @@ 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 3418133d07250a7fd50caad8d97924b86fb30bad..b09d12390d5f77330ac84452e0fee63a169bd01f 100644 +index 66f11e9670770e05a164922cc0f2aa863c066203..c307a58b17324d6df8c21fa45f0f1e34810f1828 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java @@ -240,6 +240,19 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder diff --git a/patches/api-unmapped/0205-Prioritise-own-classes-where-possible.patch b/patches/api/0206-Prioritise-own-classes-where-possible.patch similarity index 92% rename from patches/api-unmapped/0205-Prioritise-own-classes-where-possible.patch rename to patches/api/0206-Prioritise-own-classes-where-possible.patch index be1c895ad7..275d1ff4b8 100644 --- a/patches/api-unmapped/0205-Prioritise-own-classes-where-possible.patch +++ b/patches/api/0206-Prioritise-own-classes-where-possible.patch @@ -63,7 +63,7 @@ index ce751577623eaad0f31e2eb7bf0842d1ab73e845..31793f46e5623729dfb4048e901f2740 for (PluginClassLoader loader : loaders) { try { diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index b9766b9b47547c400ed075f1635bb1461cb5e860..87016d01640d8ea86b93cf2f7ead4c88b6d9d778 100644 +index 550225f168160298f4b1bf6c361207a59cf23122..9c2bde2820b92d17bc2241957390f3fb3cc50d98 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java @@ -33,7 +33,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot @@ -82,5 +82,5 @@ index b9766b9b47547c400ed075f1635bb1461cb5e860..87016d01640d8ea86b93cf2f7ead4c88 - Class result = loader.getClassByName(name, resolve, description); + Class result = loader.getClassByName(name, resolve, description, this); // Paper - prioritize self - // If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check. - if (result != null && result.getClassLoader() instanceof PluginClassLoader) { + if (result != null) { + // If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check. diff --git a/patches/api-unmapped/0207-Provide-a-useful-PluginClassLoader-toString.patch b/patches/api/0207-Provide-a-useful-PluginClassLoader-toString.patch similarity index 89% rename from patches/api-unmapped/0207-Provide-a-useful-PluginClassLoader-toString.patch rename to patches/api/0207-Provide-a-useful-PluginClassLoader-toString.patch index f993bdc2b7..b81a6dacb4 100644 --- a/patches/api-unmapped/0207-Provide-a-useful-PluginClassLoader-toString.patch +++ b/patches/api/0207-Provide-a-useful-PluginClassLoader-toString.patch @@ -8,10 +8,10 @@ however, this provides no indication of the owner of the classloader, making these messages effectively useless, this patch rectifies this diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 87016d01640d8ea86b93cf2f7ead4c88b6d9d778..cb62666d14a8eeb6338ecef75d57a1946cfa99a4 100644 +index 9c2bde2820b92d17bc2241957390f3fb3cc50d98..6b5d7c350c216b7a234d96ecacae1d39a1acd814 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -228,4 +228,16 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot +@@ -230,4 +230,16 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot javaPlugin.logger = this.logger; // Paper - set logger javaPlugin.init(loader, loader.server, description, dataFolder, file, this); } diff --git a/patches/server-remapped/0485-Workaround-for-Client-Lag-Spikes-MC-162253.patch b/patches/removed/1.17/0438-Workaround-for-Client-Lag-Spikes-MC-162253.patch similarity index 56% rename from patches/server-remapped/0485-Workaround-for-Client-Lag-Spikes-MC-162253.patch rename to patches/removed/1.17/0438-Workaround-for-Client-Lag-Spikes-MC-162253.patch index 7918002d5e..bacdd2ea36 100644 --- a/patches/server-remapped/0485-Workaround-for-Client-Lag-Spikes-MC-162253.patch +++ b/patches/removed/1.17/0438-Workaround-for-Client-Lag-Spikes-MC-162253.patch @@ -11,47 +11,23 @@ This patch basically serves as a workaround by sending light maps to the client, so that it doesn't attempt to calculate them. This mitigates the frametime impact to a minimum (but it's still there). +1.17 update note: Line sending the light update packet needs updating, rest seems to be mostly fine + diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 738f1183ce663db7c67d2f0289823390a7f06a0e..8070acde38c47c364c1d26ec3b7d65da037554a5 100644 +index d8f99f7f5ca0e1dbbb9b760af3a4b4f9c52ef6c7..f700ac973ebc3037a5a44eac3c9d505b98adce41 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -85,6 +85,7 @@ import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.ImposterProtoChunk; - import net.minecraft.world.level.chunk.LevelChunk; -+import net.minecraft.world.level.chunk.LevelChunkSection; - import net.minecraft.world.level.chunk.LightChunkGetter; - import net.minecraft.world.level.chunk.ProtoChunk; - import net.minecraft.world.level.chunk.UpgradeData; -@@ -2018,7 +2019,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1906,9 +1906,68 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - // Paper start - private static int getLightMask(final LevelChunk chunk) { -- final ChunkSection[] chunkSections = chunk.getSections(); -+ final LevelChunkSection[] chunkSections = chunk.getSections(); - int mask = 0; - - for (int i = 0; i < chunkSections.length; ++i) { -@@ -2029,7 +2030,7 @@ Lightmasks have 18 bits, from the -1 (void) section until the 17th (air) section - Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. - - */ -- mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; -+ mask |= (LevelChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; - } - - return mask; -@@ -2060,9 +2061,68 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - public final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { + public void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { // Paper - private -> public if (packets[0] == null) { + // Paper start - add 8 for light fix workaround + if (packets.length != 10) { // in case Plugins call sendChunk, resize + packets = new Packet[10]; + } + // Paper end - packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass - packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, true); + packets[0] = new ClientboundLevelChunkPacket(chunk); + packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, (BitSet) null, (BitSet) null, true); + + // Paper start - Fix MC-162253 + final int lightMask = getLightMask(chunk); @@ -75,7 +51,7 @@ index 738f1183ce663db7c67d2f0289823390a7f06a0e..8070acde38c47c364c1d26ec3b7d65da + continue; + } + -+ packets[i] = new ClientboundLightUpdatePacket(new ChunkPos(chunk.getPos().x + x, chunk.getPos().z + z), lightEngine, updateLightMask, 0, true); ++ packets[i] = new ClientboundLightUpdatePacket(new ChunkPos(chunk.getPos().x + x, chunk.getPos().z + z), lightEngine, null, null, updateLightMask, 0, true); // TODO: This line needs updating + } + } + } @@ -111,10 +87,10 @@ index 738f1183ce663db7c67d2f0289823390a7f06a0e..8070acde38c47c364c1d26ec3b7d65da player.trackChunk(chunk.getPos(), packets[0], packets[1]); DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos()); diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index dbea2a4370ccf24a5084cdabeecbc81f206e910a..9b76dc15417eef420804e5184a6d684e1137a746 100644 +index a63dc77db41dab79f03ef7384da55c1cdeca5d98..7cced5d06f296fcdc1209a43e7b3d1d9b47c0b26 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -279,7 +279,7 @@ public class LevelChunk implements ChunkAccess { +@@ -262,7 +262,7 @@ public class LevelChunk implements ChunkAccess { // broadcast Object[] backingSet = inRange.getBackingSet(); @@ -122,16 +98,4 @@ index dbea2a4370ccf24a5084cdabeecbc81f206e910a..9b76dc15417eef420804e5184a6d684e + Packet[] chunkPackets = new Packet[10]; for (int index = 0, len = backingSet.length; index < len; ++index) { Object temp = backingSet[index]; - if (!(temp instanceof ServerPlayer)) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index 5e7f6000df129100ef306703f325af9f60da8ae6..cc7d930c1fcd7157efc181d766e1639669f6eab9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -107,6 +107,7 @@ public class LevelChunkSection { - return this.nonEmptyBlockCount == 0; - } - -+ public static boolean isEmpty(@Nullable LevelChunkSection chunksection) { return isEmpty(chunksection) ; } // Paper - OBFHELPER - public static boolean isEmpty(@Nullable LevelChunkSection section) { - return section == LevelChunk.EMPTY_SECTION || section.isEmpty(); - } + if (!(temp instanceof net.minecraft.server.level.ServerPlayer)) { diff --git a/patches/server-remapped/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch b/patches/removed/1.17/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch similarity index 99% rename from patches/server-remapped/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch rename to patches/removed/1.17/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch index e9e6a043fc..d2b1599c09 100644 --- a/patches/server-remapped/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch +++ b/patches/removed/1.17/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch @@ -5,6 +5,8 @@ Subject: [PATCH] Stop copy-on-write operations for updating light data Causes huge memory allocations + gc issues +1.17 update note: Needs updating, temp skipped + diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java index 9f33fa8f84d10f8f4089030074ad6c0d81269ce8..a1ad4d73ddaf6afe97a1f1ff7e0622b52fac8761 100644 --- a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java diff --git a/patches/server-remapped/0479-Optimize-NibbleArray-to-use-pooled-buffers.patch b/patches/removed/1.17/0479-Optimize-NibbleArray-to-use-pooled-buffers.patch similarity index 99% rename from patches/server-remapped/0479-Optimize-NibbleArray-to-use-pooled-buffers.patch rename to patches/removed/1.17/0479-Optimize-NibbleArray-to-use-pooled-buffers.patch index 9cdcec0403..4fa0fd6f02 100644 --- a/patches/server-remapped/0479-Optimize-NibbleArray-to-use-pooled-buffers.patch +++ b/patches/removed/1.17/0479-Optimize-NibbleArray-to-use-pooled-buffers.patch @@ -8,6 +8,8 @@ an object pool for these. Uses lots of advanced new capabilities of the Paper codebase :) +1.17 update note: ClientboundLightUpdatePacket has has made changes which necessitate updating this patch + diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java index bc1b4cc2e0a4181bde5ac05ce0a20a651cb0c4c3..902f14e2e5ac5aa11b545a68ac69e9b0282df7f4 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java diff --git a/patches/server-remapped/0473-Fix-PotionEffect-ignores-icon-flag.patch b/patches/server-remapped/0473-Fix-PotionEffect-ignores-icon-flag.patch deleted file mode 100644 index 5968f9b0c8..0000000000 --- a/patches/server-remapped/0473-Fix-PotionEffect-ignores-icon-flag.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Fri, 8 May 2020 00:49:18 -0400 -Subject: [PATCH] Fix PotionEffect ignores icon flag - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 5dac3bf5a117bfbf57798238f0614558deafcd1b..067eaf1e05ced344eb168431403f3fe786eafddf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -408,7 +408,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - - @Override - public boolean addPotionEffect(PotionEffect effect, boolean force) { -- getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN); -+ getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon - return true; - } - diff --git a/patches/server-remapped/0482-Ensure-safe-gateway-teleport.patch b/patches/server-remapped/0482-Ensure-safe-gateway-teleport.patch deleted file mode 100644 index 3ca91f50a5..0000000000 --- a/patches/server-remapped/0482-Ensure-safe-gateway-teleport.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Fri, 15 May 2020 01:10:03 -0400 -Subject: [PATCH] Ensure safe gateway teleport - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -index b70e0633435a272ae1e9fbd12d7f18862de0b951..3491956cb09b825bbfc99667b058d67cef127332 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -@@ -86,9 +86,14 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements - } else if (!this.level.isClientSide) { - List list = this.level.getEntitiesOfClass(Entity.class, new AABB(this.getBlockPos()), TheEndGatewayBlockEntity::canEntityTeleport); - -- if (!list.isEmpty()) { -- this.teleportEntity((Entity) list.get(this.level.random.nextInt(list.size()))); -+ // Paper start -+ for (Entity entity : list) { -+ if (entity.canChangeDimensions()) { -+ this.teleportEntity(entity); -+ break; -+ } - } -+ // Paper end - - if (this.age % 2400L == 0L) { - this.triggerCooldown(); diff --git a/patches/server-remapped/0471-Add-villager-reputation-API.patch b/patches/server/0426-Add-villager-reputation-API.patch similarity index 87% rename from patches/server-remapped/0471-Add-villager-reputation-API.patch rename to patches/server/0426-Add-villager-reputation-API.patch index 771a37b8cf..3679ce0494 100644 --- a/patches/server-remapped/0471-Add-villager-reputation-API.patch +++ b/patches/server/0426-Add-villager-reputation-API.patch @@ -6,15 +6,13 @@ Subject: [PATCH] Add villager reputation API diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java new file mode 100644 -index 0000000000000000000000000000000000000000..c6072615e95bf51c83b2f728fc3288a7043a89af +index 0000000000000000000000000000000000000000..0f10c333d88f2e1c56a6c7f22d421084adfd3789 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java -@@ -0,0 +1,11 @@ +@@ -0,0 +1,9 @@ +package com.destroystokyo.paper.entity.villager; +// Must have own package due to package-level constructor. + -+import Reputation; -+ +public final class ReputationConstructor { + // Abuse the package-level constructor. + public static Reputation construct(int[] values) { @@ -22,33 +20,28 @@ index 0000000000000000000000000000000000000000..c6072615e95bf51c83b2f728fc3288a7 + } +} diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -index c4ece3ac4863067b12c10772debd1b1454bec5b4..0204f05d989d45c0848f810d1953adf0992ce3c2 100644 +index 07ecb01d02f64e85d478995062a33b58c211ed7e..e316f83a7adc7bba06a6a3fdab55cc9c004cb835 100644 --- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -@@ -27,7 +27,7 @@ import net.minecraft.core.SerializableUUID; +@@ -29,7 +29,7 @@ import net.minecraft.util.VisibleForDebug; public class GossipContainer { - + public static final int DISCARD_THRESHOLD = 2; - private final Map gossips = Maps.newHashMap(); + private final Map gossips = Maps.newHashMap(); public Map getReputations() { return this.gossips; } // Paper - add getter for reputations - public GossipContainer() {} - -@@ -142,11 +142,11 @@ public class GossipContainer { - return k > type.max ? Math.max(type.max, left) : k; + @VisibleForDebug + public Map> getGossipEntries() { +@@ -177,7 +177,7 @@ public class GossipContainer { + return i > type.max ? Math.max(type.max, left) : i; } - static class EntityGossips { + public static class EntityGossips { // Paper - make public + final Object2IntMap entries = new Object2IntOpenHashMap<>(); - private final Object2IntMap entries; - -- private EntityGossips() { -+ public EntityGossips() { // Paper - make public - update CraftVillager setReputation on change - this.entries = new Object2IntOpenHashMap(); - } - -@@ -200,6 +200,28 @@ public class GossipContainer { + public int weightedValue(Predicate gossipTypeFilter) { +@@ -228,6 +228,28 @@ public class GossipContainer { public void remove(GossipType gossipType) { this.entries.removeInt(gossipType); } @@ -78,10 +71,10 @@ index c4ece3ac4863067b12c10772debd1b1454bec5b4..0204f05d989d45c0848f810d1953adf0 static class GossipEntry { diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index a83a7d37f3d769535161fda46fca6f71dcc4d515..e9912551e6a19d6ad3b20fad1b716577b9d28f99 100644 +index e99cdbb1d050288b5f1177737b242c331a989471..8508a3864fc3f8919f823d96f27061a6b3706713 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -1037,6 +1037,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -1065,6 +1065,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler this.numberOfRestocksToday = 0; } @@ -90,7 +83,7 @@ index a83a7d37f3d769535161fda46fca6f71dcc4d515..e9912551e6a19d6ad3b20fad1b716577 return this.gossips; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index d0b933cfd02b237bfe85011831dab6e8e966496e..e3d4214ef6360b4a9949a73ba3d665ad08733b43 100644 +index 115f107ac100524ef0fcf8de0fc528d164c845f7..b15db2bf0a0bbe39b8067559fbf2b6bdadf56ca4 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java @@ -16,6 +16,13 @@ import org.bukkit.entity.Villager; diff --git a/patches/server/0427-Fix-PotionEffect-ignores-icon-flag.patch b/patches/server/0427-Fix-PotionEffect-ignores-icon-flag.patch new file mode 100644 index 0000000000..5ed01958b2 --- /dev/null +++ b/patches/server/0427-Fix-PotionEffect-ignores-icon-flag.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Fri, 8 May 2020 00:49:18 -0400 +Subject: [PATCH] Fix PotionEffect ignores icon flag + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 76e9977f7b2f7fb50631fc56f3318d59d04b1398..a7a6757b83c94a0c0926097021015815f8f18b8e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -400,7 +400,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + + @Override + public boolean addPotionEffect(PotionEffect effect, boolean force) { +- this.getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN); ++ this.getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon + return true; + } + diff --git a/patches/server-remapped/0474-Optimize-brigadier-child-sorting-performance.patch b/patches/server/0428-Optimize-brigadier-child-sorting-performance.patch similarity index 70% rename from patches/server-remapped/0474-Optimize-brigadier-child-sorting-performance.patch rename to patches/server/0428-Optimize-brigadier-child-sorting-performance.patch index d213e040be..42f1eb780d 100644 --- a/patches/server-remapped/0474-Optimize-brigadier-child-sorting-performance.patch +++ b/patches/server/0428-Optimize-brigadier-child-sorting-performance.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Optimize brigadier child sorting performance diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -index 120234605433165d1c78986b5f0f130e64c5a20a..5c35cef42af4053332c02b4960c227fe95d4c197 100644 +index b8d646864a24bba376661cfd87901012416c669d..aa3a1795850a419f624f14bd7c4daab0020779d0 100644 --- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java +++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java @@ -26,7 +26,7 @@ import java.util.stream.Collectors; @@ -17,13 +17,12 @@ index 120234605433165d1c78986b5f0f130e64c5a20a..5c35cef42af4053332c02b4960c227fe private Map> literals = Maps.newLinkedHashMap(); private Map> arguments = Maps.newLinkedHashMap(); private final Predicate requirement; -@@ -106,8 +106,7 @@ public abstract class CommandNode implements Comparable> { - arguments.put(node.getName(), (ArgumentCommandNode) node); +@@ -107,7 +107,7 @@ public abstract class CommandNode implements Comparable> { } } -- -- children = children.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); -+ //Paper - Remove manual sorting, it is no longer needed + +- this.children = this.children.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); ++ // Paper - Remove manual sorting, it is no longer needed } public void findAmbiguities(final AmbiguityConsumer consumer) { diff --git a/patches/server-remapped/0475-Potential-bed-API.patch b/patches/server/0429-Potential-bed-API.patch similarity index 90% rename from patches/server-remapped/0475-Potential-bed-API.patch rename to patches/server/0429-Potential-bed-API.patch index efd1703506..a655522abf 100644 --- a/patches/server-remapped/0475-Potential-bed-API.patch +++ b/patches/server/0429-Potential-bed-API.patch @@ -8,7 +8,7 @@ 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/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index ae6faa331fcbefd99ee1cd92c88926d767fc50ee..878a62e04962aafeaf192075fbe08e319298a800 100644 +index 31b62dc1ee06b254c398cbfe157283fb199ef0fe..36ea76bfe0bd96ead82ed1ad34f25de10b7fa30e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -12,6 +12,7 @@ import net.minecraft.nbt.CompoundTag; @@ -19,8 +19,8 @@ index ae6faa331fcbefd99ee1cd92c88926d767fc50ee..878a62e04962aafeaf192075fbe08e31 import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.Entity; -@@ -126,6 +127,22 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - return getHandle().sleepCounter; +@@ -125,6 +126,22 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + return this.getHandle().sleepCounter; } + // Paper start - Potential bed api diff --git a/patches/server-remapped/0476-Wait-for-Async-Tasks-during-shutdown.patch b/patches/server/0430-Wait-for-Async-Tasks-during-shutdown.patch similarity index 91% rename from patches/server-remapped/0476-Wait-for-Async-Tasks-during-shutdown.patch rename to patches/server/0430-Wait-for-Async-Tasks-during-shutdown.patch index dea3aa2ef9..cc6436b194 100644 --- a/patches/server-remapped/0476-Wait-for-Async-Tasks-during-shutdown.patch +++ b/patches/server/0430-Wait-for-Async-Tasks-during-shutdown.patch @@ -10,10 +10,10 @@ Adds a 5 second grace period for any async tasks to finish and warns if any are still running after that delay just as reload does. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 74f393ffa2ae2d0e25b3f0b674cef7a987e985d3..f530c739b6aee3718eb5d0e0e6a09d882d817c68 100644 +index d7023cb0974f6c28a0fb8a0a6e5a6600fe30d3e3..11dbe48c8a8c29cd28d725c43505e326a6e626ff 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -892,6 +892,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop extends Goal { @@ -18,7 +18,7 @@ index 6406b0a03b67ea61083b704cd24b9b25a0f33c87..5502615be430d9eba0c1c68e3f10826d public ObtainRaidLeaderBannerGoal(T entityraider) { // CraftBukkit - decompile error this.mob = entityraider; -@@ -532,6 +532,7 @@ public abstract class Raider extends PatrollingMonster { +@@ -314,6 +314,7 @@ public abstract class Raider extends PatrollingMonster { @Override public boolean canUse() { diff --git a/patches/server-remapped/0478-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server/0432-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch similarity index 81% rename from patches/server-remapped/0478-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch rename to patches/server/0432-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch index 99a5355669..5a8eb18dfb 100644 --- a/patches/server-remapped/0478-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch +++ b/patches/server/0432-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch @@ -35,18 +35,18 @@ index 78271b400c79578d043b20a5389a37b1bef9a70d..5f3b0d95cc7e6a0434d78ea7305a7068 + } diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 667a6d645034c67639c01b8221591877bcb87b35..0f0a5fa2be5a7c69291b593a04cad83e069ba5b1 100644 +index cdf214fca3b0055efa56702470d9d2f890a8aead..a12af10e28f2d023ba6f916b5e7a53539416713f 100644 --- a/src/main/java/net/minecraft/world/level/Explosion.java +++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -151,6 +151,7 @@ public class Explosion { +@@ -174,6 +174,7 @@ public class Explosion { for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { BlockPos blockposition = new BlockPos(d4, d5, d6); BlockState iblockdata = this.level.getBlockState(blockposition); + if (!iblockdata.isDestroyable()) continue; // Paper FluidState fluid = iblockdata.getFluidState(); // Paper - Optional optional = this.damageCalculator.a(this, this.level, blockposition, iblockdata, fluid); -@@ -304,7 +305,7 @@ public class Explosion { + if (!this.level.isInWorldBounds(blockposition)) { +@@ -332,7 +333,7 @@ public class Explosion { BlockState iblockdata = this.level.getBlockState(blockposition); Block block = iblockdata.getBlock(); @@ -56,10 +56,10 @@ index 667a6d645034c67639c01b8221591877bcb87b35..0f0a5fa2be5a7c69291b593a04cad83e this.level.getProfiler().push("explosion_blocks"); diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 67ab681a9c9157a420de5fd872bde1fc0de24561..9b50b8030174338c04b60d441b980131e1d593e4 100644 +index 03271675b4997588bd8f6774856aef25cdd4fa05..581e7975c4bfcc902e262003843fe54212bc5b61 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -422,6 +422,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -419,6 +419,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { // CraftBukkit start - tree generation if (this.captureTreeGeneration) { @@ -67,14 +67,14 @@ index 67ab681a9c9157a420de5fd872bde1fc0de24561..9b50b8030174338c04b60d441b980131 + BlockState type = getBlockState(pos); + if (!type.isDestroyable()) return false; + // Paper end - CraftBlockState blockstate = capturedBlockStates.get(pos); + CraftBlockState blockstate = this.capturedBlockStates.get(pos); if (blockstate == null) { blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index fca5d175cbef24fb0ee2d0bbedc8d1c0af3eb528..5b84ee4091e354c4b6500f58a31931f2a6827ffc 100644 +index 27016f964d2f6458298a9052d031a44b3d9f5f4b..878cdfc49253e7916d038495f79fec7cce75aa50 100644 --- a/src/main/java/net/minecraft/world/level/block/Block.java +++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -62,6 +62,19 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -91,6 +91,19 @@ public class Block extends BlockBehaviour implements ItemLike { protected final StateDefinition stateDefinition; private BlockState defaultBlockState; // Paper start @@ -95,10 +95,10 @@ index fca5d175cbef24fb0ee2d0bbedc8d1c0af3eb528..5b84ee4091e354c4b6500f58a31931f2 public co.aikar.timings.Timing getTiming() { if (timing == null) { diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -index dc9584a30c18d964afd9cc118c81c24a80beba63..40a18302dd682e5ade4ec77ac7f316b6c0f8c112 100644 +index c345bd7542f3ffa09719864887e1516f1182e7e3..44cc09006eac6315d167a2628857f9942eb1fc13 100644 --- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -@@ -193,6 +193,12 @@ public class PistonBaseBlock extends DirectionalBlock { +@@ -200,6 +200,12 @@ public class PistonBaseBlock extends DirectionalBlock { @Override public boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) { Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING); @@ -111,16 +111,16 @@ index dc9584a30c18d964afd9cc118c81c24a80beba63..40a18302dd682e5ade4ec77ac7f316b6 if (!world.isClientSide) { boolean flag = this.getNeighborSignal(world, pos, enumdirection); -@@ -224,7 +230,7 @@ public class PistonBaseBlock extends DirectionalBlock { +@@ -232,7 +238,7 @@ public class PistonBaseBlock extends DirectionalBlock { BlockState iblockdata1 = (BlockState) ((BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, enumdirection)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); world.setBlock(pos, iblockdata1, 20); -- world.setBlockEntity(pos, MovingPistonBlock.newMovingBlockEntity((BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); -+ world.setBlockEntity(pos, MovingPistonBlock.newMovingBlockEntity((BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - diff on change, j is facing direction - copy this above +- world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata1, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); ++ world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata1, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - diff on change world.blockUpdated(pos, iblockdata1.getBlock()); iblockdata1.updateNeighbourShapes(world, pos, 2); if (this.isSticky) { -@@ -253,7 +259,14 @@ public class PistonBaseBlock extends DirectionalBlock { +@@ -261,7 +267,14 @@ public class PistonBaseBlock extends DirectionalBlock { } } } else { @@ -137,19 +137,19 @@ index dc9584a30c18d964afd9cc118c81c24a80beba63..40a18302dd682e5ade4ec77ac7f316b6 world.playSound((Player) null, pos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F); diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index 57eedaeedaa24bd274fb55c6e4521f1305382645..df2836b071158729728411f5b228cc38dddd4d4e 100644 +index d99ca942f5885b4d9af054547832c05ddb5634eb..6d4ef15842c6bd230543de19dd1053a4fe6ad270 100644 --- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -189,7 +189,7 @@ public abstract class BlockBehaviour { +@@ -206,7 +206,7 @@ public abstract class BlockBehaviour { @Deprecated public boolean canBeReplaced(BlockState state, BlockPlaceContext context) { -- return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || context.getItemInHand().getItem() != this.asItem()); -+ return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || context.getItemInHand().getItem() != this.asItem()) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().abilities.instabuild)); // Paper +- return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())); ++ return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().getAbilities().instabuild)); // Paper } @Deprecated -@@ -393,7 +393,11 @@ public abstract class BlockBehaviour { +@@ -656,7 +656,11 @@ public abstract class BlockBehaviour { public Block getBlock() { return (Block) this.owner; } @@ -162,7 +162,7 @@ index 57eedaeedaa24bd274fb55c6e4521f1305382645..df2836b071158729728411f5b228cc38 public Material getMaterial() { return this.material; } -@@ -483,7 +487,7 @@ public abstract class BlockBehaviour { +@@ -754,7 +758,7 @@ public abstract class BlockBehaviour { } public PushReaction getPistonPushReaction() { diff --git a/patches/server-remapped/0480-Reduce-MutableInt-allocations-from-light-engine.patch b/patches/server/0433-Reduce-MutableInt-allocations-from-light-engine.patch similarity index 59% rename from patches/server-remapped/0480-Reduce-MutableInt-allocations-from-light-engine.patch rename to patches/server/0433-Reduce-MutableInt-allocations-from-light-engine.patch index 932a889a98..881c2f0231 100644 --- a/patches/server-remapped/0480-Reduce-MutableInt-allocations-from-light-engine.patch +++ b/patches/server/0433-Reduce-MutableInt-allocations-from-light-engine.patch @@ -7,44 +7,44 @@ We can abuse the fact light is single threaded and share an instance per light engine instance diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java -index 8979101a52537f4ec03a5f43030264b8e72fcea4..709fc42057f8a0282c3c942067e63abb874d9042 100644 +index 729c4b1763a24bac3c0764bea505555a32e54f57..37d7165dfd17da03428f8dbbbf95aa8005be289c 100644 --- a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java +++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java -@@ -16,6 +16,7 @@ public final class BlockLightEngine extends LayerLightEngine { private static final Direction[] DIRECTIONS = Direction.values(); private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); -+ private final MutableInt mutableint = new MutableInt(); // Paper ++ private final MutableInt mutableInt = new MutableInt(); // Paper public BlockLightEngine(LightChunkGetter chunkProvider) { super(chunkProvider, LightLayer.BLOCK, new BlockLightSectionStorage(chunkProvider)); -@@ -47,7 +48,7 @@ public final class BlockLightEngine extends LayerLightEngine= 15) { + BlockState blockState = this.getStateAndOpacity(targetId, mutableInt); + if (mutableInt.getValue() >= 15) { + return 15; diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java -index d99890121bdf1e499e364bdc953e628c04d69b95..ff1fbc46776b26ca56c3293e40ed55028230ec46 100644 +index 4252247acd5c71e46d90f454663a9737e22e2a61..d122475c1a9d340046c478087d3ff5bf1ff8932c 100644 --- a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java +++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java -@@ -15,6 +15,7 @@ public final class SkyLightEngine extends LayerLightEngine { private static final Direction[] DIRECTIONS = Direction.values(); private static final Direction[] HORIZONTALS = new Direction[]{Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST}; -+ private final MutableInt mutableint = new MutableInt(); // Paper ++ private final MutableInt mutableInt = new MutableInt(); // Paper public SkyLightEngine(LightChunkGetter chunkProvider) { super(chunkProvider, LightLayer.SKY, new SkyLightSectionStorage(chunkProvider)); -@@ -36,7 +37,7 @@ public final class SkyLightEngine extends LayerLightEngine= 15) { return level; } else { -- MutableInt mutableint = new MutableInt(); +- MutableInt mutableInt = new MutableInt(); + //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded - BlockState iblockdata = this.getStateAndOpacity(targetId, mutableint); - - if (mutableint.getValue() >= 15) { + BlockState blockState = this.getStateAndOpacity(targetId, mutableInt); + if (mutableInt.getValue() >= 15) { + return 15; diff --git a/patches/server-remapped/0481-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/patches/server/0434-Reduce-allocation-of-Vec3D-by-entity-tracker.patch similarity index 78% rename from patches/server-remapped/0481-Reduce-allocation-of-Vec3D-by-entity-tracker.patch rename to patches/server/0434-Reduce-allocation-of-Vec3D-by-entity-tracker.patch index 6751467281..b91add5e6e 100644 --- a/patches/server-remapped/0481-Reduce-allocation-of-Vec3D-by-entity-tracker.patch +++ b/patches/server/0434-Reduce-allocation-of-Vec3D-by-entity-tracker.patch @@ -5,18 +5,10 @@ Subject: [PATCH] Reduce allocation of Vec3D by entity tracker diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 67f748d5955453ba4873b0c9bb741b5bfe52d655..738f1183ce663db7c67d2f0289823390a7f06a0e 100644 +index 18335e2c5c9e50a8ed31a3d2b585835bcc28bbe6..d8f99f7f5ca0e1dbbb9b760af3a4b4f9c52ef6c7 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -95,7 +95,6 @@ import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; - import net.minecraft.world.level.storage.DimensionDataStorage; - import net.minecraft.world.level.storage.LevelStorageSource; --import net.minecraft.world.phys.Vec3; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper - import org.apache.commons.lang3.mutable.MutableBoolean; - import org.apache.logging.log4j.LogManager; -@@ -2233,9 +2232,14 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially +@@ -2102,9 +2102,14 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially public void updatePlayer(ServerPlayer player) { org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot if (player != this.entity) { @@ -31,16 +23,16 @@ index 67f748d5955453ba4873b0c9bb741b5bfe52d655..738f1183ce663db7c67d2f0289823390 - boolean flag = vec3d.x >= (double) (-i) && vec3d.x <= (double) i && vec3d.z >= (double) (-i) && vec3d.z <= (double) i && this.entity.broadcastToPlayer(player); + boolean flag = vec3d_dx >= (double) (-i) && vec3d_dx <= (double) i && vec3d_dz >= (double) (-i) && vec3d_dz <= (double) i && this.entity.broadcastToPlayer(player); // Paper - remove allocation of Vec3D here - if (flag) { - boolean flag1 = this.entity.forcedLoading; + // CraftBukkit start - respect vanish API + if (this.entity instanceof ServerPlayer) { diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index d797873db52ba265ac4478f9f3c6344badd4739e..75e2274578c2c28de3d786372df0b4102337a2cc 100644 +index 6b492b72b177e3c58580561585609b176876acf1..8ea4209400489116823eced292d8cd9654a1c809 100644 --- a/src/main/java/net/minecraft/server/level/ServerEntity.java +++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -154,8 +154,12 @@ public class ServerEntity { +@@ -145,8 +145,12 @@ public class ServerEntity { ++this.teleportDelay; - i = Mth.floor(this.entity.yRot * 256.0F / 360.0F); - j = Mth.floor(this.entity.xRot * 256.0F / 360.0F); + i = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F); + j = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F); - Vec3 vec3d = this.entity.position().subtract(ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp)); - boolean flag1 = vec3d.lengthSqr() >= 7.62939453125E-6D; + // Paper start - reduce allocation of Vec3D here @@ -52,7 +44,7 @@ index d797873db52ba265ac4478f9f3c6344badd4739e..75e2274578c2c28de3d786372df0b410 Packet packet1 = null; boolean flag2 = flag1 || this.tickCount % 60 == 0; boolean flag3 = Math.abs(i - this.yRotp) >= 1 || Math.abs(j - this.xRotp) >= 1; -@@ -172,9 +176,11 @@ public class ServerEntity { +@@ -163,9 +167,11 @@ public class ServerEntity { // CraftBukkit end if (this.tickCount > 0 || this.entity instanceof AbstractArrow) { diff --git a/patches/server/0435-Ensure-safe-gateway-teleport.patch b/patches/server/0435-Ensure-safe-gateway-teleport.patch new file mode 100644 index 0000000000..3b939b0472 --- /dev/null +++ b/patches/server/0435-Ensure-safe-gateway-teleport.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kickash32 +Date: Fri, 15 May 2020 01:10:03 -0400 +Subject: [PATCH] Ensure safe gateway teleport + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +index 370ec4cd08a50ad0b8154db9afcaa76ec741dcb2..782becb96b6300f14deee360b653dc99c57fdc12 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -105,7 +105,14 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { + List list = world.getEntitiesOfClass(Entity.class, new AABB(pos), TheEndGatewayBlockEntity::canEntityTeleport); + + if (!list.isEmpty()) { +- TheEndGatewayBlockEntity.teleportEntity(world, pos, state, (Entity) list.get(world.random.nextInt(list.size())), blockEntity); ++ // Paper start ++ for (Entity entity : list) { ++ if (entity.canChangeDimensions()) { ++ TheEndGatewayBlockEntity.teleportEntity(world, pos, state, entity, blockEntity); ++ break; ++ } ++ } ++ // Paper end + } + + if (blockEntity.age % 2400L == 0L) { diff --git a/patches/server-remapped/0483-Add-option-for-console-having-all-permissions.patch b/patches/server/0436-Add-option-for-console-having-all-permissions.patch similarity index 76% rename from patches/server-remapped/0483-Add-option-for-console-having-all-permissions.patch rename to patches/server/0436-Add-option-for-console-having-all-permissions.patch index 61d650c223..17c0476f85 100644 --- a/patches/server-remapped/0483-Add-option-for-console-having-all-permissions.patch +++ b/patches/server/0436-Add-option-for-console-having-all-permissions.patch @@ -18,21 +18,8 @@ index 5f3b0d95cc7e6a0434d78ea7305a70689c41c71c..7f140333c2e62012fa572c1a061d8443 + } + } -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 525cd44411b344bc4b5d43c087094fea88fa41a6..4817b8ab259d348b48bc325d34ba9351ffe951df 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1886,7 +1886,7 @@ public abstract class Player extends LivingEntity { - } - } - -- protected void removeEntitiesOnShoulder() { -+ public void removeEntitiesOnShoulder() { // Paper - protected -> public - if (this.timeEntitySatOnShoulder + 20L < this.level.getGameTime()) { - // CraftBukkit start - if (this.spawnEntityFromShoulder(this.getShoulderEntityLeft())) { diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -index af986adfdb547cb61fbd52f0f89858f1a9e52cc3..80a67deaeaae3b3f0ceb9a298de5bb38b8ee707b 100644 +index a885eb537d6475eefe7d06f8312ecf0a278c5a00..4d95d4f4b354fc22c29c55bb70010282a4d3c5d9 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java +++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java @@ -86,5 +86,15 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co @@ -52,7 +39,7 @@ index af986adfdb547cb61fbd52f0f89858f1a9e52cc3..80a67deaeaae3b3f0ceb9a298de5bb38 // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -index d0757d116ee689041c0e64e622d2c36e0b0bcaf1..7b53b5a0857fc0ce0463db319f86a1f79833ab93 100644 +index c2d163c078b569e3e97ee01d149c5c3e87f55513..d1ce98ca68690542c6864c189bc114f1f715b2b5 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java +++ b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java @@ -39,4 +39,16 @@ public class CraftRemoteConsoleCommandSender extends ServerCommandSender impleme diff --git a/patches/server-remapped/0484-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/patches/server/0437-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch similarity index 77% rename from patches/server-remapped/0484-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch rename to patches/server/0437-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch index 1346418468..9a51437a68 100644 --- a/patches/server-remapped/0484-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch +++ b/patches/server/0437-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch @@ -16,23 +16,23 @@ We further improve it by making a copy of the nbt tag with only the memory it needs, so that we dont have to hold a copy to the entire compound. diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 1e58958c3d7b10da5a5f22fc9591d9183e53e3cc..0adf14af9841cd3a20a8b2c0c320eb06794ef261 100644 +index 7c04aef3eac54981ca1e34cb87d97104c3c9685b..b4246524dd11ad1e1dc94c56eee966c5a54d9ecc 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -26,6 +26,7 @@ import net.minecraft.nbt.CompoundTag; +@@ -27,6 +27,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.LongArrayTag; import net.minecraft.nbt.ShortTag; +import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; -@@ -199,15 +200,9 @@ public class ChunkSerializer { + import net.minecraft.server.level.ThreadedLevelLightEngine; +@@ -207,15 +208,9 @@ public class ChunkSerializer { object2 = protochunkticklist1; } -- object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { -- postLoadChunk(nbttagcompound1, chunk); +- object = new LevelChunk(world.getLevel(), pos, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, k, achunksection, (chunk) -> { +- ChunkSerializer.postLoadChunk(world, nbttagcompound1, chunk); - // CraftBukkit start - load chunk persistent data from nbt - net.minecraft.nbt.Tag persistentBase = nbttagcompound1.get("ChunkBukkitValues"); - if (persistentBase instanceof CompoundTag) { @@ -40,13 +40,13 @@ index 1e58958c3d7b10da5a5f22fc9591d9183e53e3cc..0adf14af9841cd3a20a8b2c0c320eb06 - } - // CraftBukkit end - }); -+ object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. ++ object = new LevelChunk(world.getLevel(), pos, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, k, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. + createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities", "ChunkBukkitValues")) // Paper - move CB Chunk PDC into here + );// Paper end } else { - ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter + ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world, world); // Paper - add level -@@ -313,6 +308,50 @@ public class ChunkSerializer { +@@ -321,6 +316,50 @@ public class ChunkSerializer { return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading } } @@ -84,7 +84,7 @@ index 1e58958c3d7b10da5a5f22fc9591d9183e53e3cc..0adf14af9841cd3a20a8b2c0c320eb06 + } + private static java.util.function.Consumer createLoadEntitiesConsumer(CompoundTag nbt) { + return (chunk) -> { -+ postLoadChunk(nbt, chunk); ++ postLoadChunk(chunk.level, nbt, chunk); + // CraftBukkit start - load chunk persistent data from nbt + Tag persistentBase = nbt.get("ChunkBukkitValues"); + if (persistentBase instanceof CompoundTag) { From 9c95d0481df235634eb7dbd2359d607a480bd045 Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Sun, 13 Jun 2021 22:37:57 -0700 Subject: [PATCH 099/226] Re-add xp orb merging patches (#5823) --- ...maximum-exp-value-when-merging-orbs.patch} | 30 +++++++++---------- .../0427-ExperienceOrbMergeEvent.patch} | 9 +++--- 2 files changed, 19 insertions(+), 20 deletions(-) rename patches/{removed/1.17/0176-Option-for-maximum-exp-value-when-merging-orbs.patch => server/0426-Option-for-maximum-exp-value-when-merging-orbs.patch} (76%) rename patches/{removed/1.17/0184-ExperienceOrbMergeEvent.patch => server/0427-ExperienceOrbMergeEvent.patch} (67%) diff --git a/patches/removed/1.17/0176-Option-for-maximum-exp-value-when-merging-orbs.patch b/patches/server/0426-Option-for-maximum-exp-value-when-merging-orbs.patch similarity index 76% rename from patches/removed/1.17/0176-Option-for-maximum-exp-value-when-merging-orbs.patch rename to patches/server/0426-Option-for-maximum-exp-value-when-merging-orbs.patch index c2626fdee4..329975a609 100644 --- a/patches/removed/1.17/0176-Option-for-maximum-exp-value-when-merging-orbs.patch +++ b/patches/server/0426-Option-for-maximum-exp-value-when-merging-orbs.patch @@ -5,25 +5,27 @@ Subject: [PATCH] Option for maximum exp value when merging orbs diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 90ca51dfdbb3045dd528450225cba96f5834166e..6c692e58cde22003ecbf6dc5695799147c39905a 100644 +index 16cf7d116e3ffd44ffc4f060b4014b52389cff77..3bc6329d3ea48966cb99e792f9b35e2d2d71a34b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -342,4 +342,10 @@ public class PaperWorldConfig { - disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); +@@ -359,6 +359,12 @@ public class PaperWorldConfig { log("Creeper lingering effect: " + disableCreeperLingeringEffect); } -+ + + public int expMergeMaxValue; + private void expMergeMaxValue() { + expMergeMaxValue = getInt("experience-merge-max-value", -1); + log("Experience Merge Max Value: " + expMergeMaxValue); + } - } ++ + public double squidMaxSpawnHeight; + private void squidMaxSpawnHeight() { + squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 3f082b7fd50752728917a7da28cba4cb396a9fdf..7d6834796259e364196280ffa468b5bf999ec7b9 100644 +index 7d43439a13bd109399691ddec60ee99c818db198..36b2faebca20ef152e4fc88ecfa660ecbbb11384 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -587,16 +587,32 @@ public class CraftEventFactory { +@@ -610,16 +610,30 @@ public class CraftEventFactory { net.minecraft.world.entity.ExperienceOrb xp = (net.minecraft.world.entity.ExperienceOrb) entity; double radius = world.spigotConfig.expMerge; if (radius > 0) { @@ -36,25 +38,21 @@ index 3f082b7fd50752728917a7da28cba4cb396a9fdf..7d6834796259e364196280ffa468b5bf for (Entity e : entities) { if (e instanceof net.minecraft.world.entity.ExperienceOrb) { net.minecraft.world.entity.ExperienceOrb loopItem = (net.minecraft.world.entity.ExperienceOrb) e; -- if (!loopItem.removed) { -- xp.value += loopItem.value; -- loopItem.remove(); +- if (!loopItem.isRemoved()) { + // Paper start -+ if (!loopItem.removed && !(maxValue > 0 && loopItem.value >= maxValue)) { ++ if (!loopItem.isRemoved() && !(maxValue > 0 && loopItem.value >= maxValue)) { + long newTotal = (long)xp.value + (long)loopItem.value; + if ((int) newTotal < 0) continue; // Overflow + if (maxValue > 0 && newTotal > (long)maxValue) { + loopItem.value = (int) (newTotal - maxValue); + xp.value = maxValue; + } else { -+ xp.value += loopItem.value; -+ loopItem.remove(); -+ } -+ // Paper end + xp.value += loopItem.value; + loopItem.discard(); ++ } // Paper end } } } -+ + } // Paper end - End iteration skip check - All tweaking ends here } // Spigot end diff --git a/patches/removed/1.17/0184-ExperienceOrbMergeEvent.patch b/patches/server/0427-ExperienceOrbMergeEvent.patch similarity index 67% rename from patches/removed/1.17/0184-ExperienceOrbMergeEvent.patch rename to patches/server/0427-ExperienceOrbMergeEvent.patch index aef031bd77..5a91c0f475 100644 --- a/patches/removed/1.17/0184-ExperienceOrbMergeEvent.patch +++ b/patches/server/0427-ExperienceOrbMergeEvent.patch @@ -2,21 +2,22 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Tue, 19 Dec 2017 22:57:26 -0500 Subject: [PATCH] ExperienceOrbMergeEvent + Has to be reimplemented at one point maybe Fired when the server is about to merge 2 experience orbs Plugins can cancel this if they want to ensure experience orbs do not lose important metadata such as spawn reason, or conditionally move data from source to target. diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 7d6834796259e364196280ffa468b5bf999ec7b9..5e8ff18f98b03741ccbb927f87499ae36d775a86 100644 +index 36b2faebca20ef152e4fc88ecfa660ecbbb11384..d4b8035160332d98c37918f62ee9e0d630e23ee8 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -597,7 +597,7 @@ public class CraftEventFactory { +@@ -620,7 +620,7 @@ public class CraftEventFactory { if (e instanceof net.minecraft.world.entity.ExperienceOrb) { net.minecraft.world.entity.ExperienceOrb loopItem = (net.minecraft.world.entity.ExperienceOrb) e; // Paper start -- if (!loopItem.removed && !(maxValue > 0 && loopItem.value >= maxValue)) { -+ if (!loopItem.removed && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper +- if (!loopItem.isRemoved() && !(maxValue > 0 && loopItem.value >= maxValue)) { ++ if (!loopItem.isRemoved() && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper - ExperienceOrbMergeEvent long newTotal = (long)xp.value + (long)loopItem.value; if ((int) newTotal < 0) continue; // Overflow if (maxValue > 0 && newTotal > (long)maxValue) { From dcbb16316d86d5de5a1338f911046ad2c28d62dc Mon Sep 17 00:00:00 2001 From: mechoriet Date: Mon, 14 Jun 2021 07:40:21 +0200 Subject: [PATCH 100/226] ReAdded PreCreatureSpawnEvent from removed (#5814) --- .../1.17/0187-PreCreatureSpawnEvent.patch | 215 ------------------ .../server/0330-PreCreatureSpawnEvent.patch | 150 ++++++++++++ 2 files changed, 150 insertions(+), 215 deletions(-) delete mode 100644 patches/removed/1.17/0187-PreCreatureSpawnEvent.patch create mode 100644 patches/server/0330-PreCreatureSpawnEvent.patch diff --git a/patches/removed/1.17/0187-PreCreatureSpawnEvent.patch b/patches/removed/1.17/0187-PreCreatureSpawnEvent.patch deleted file mode 100644 index c3206f4317..0000000000 --- a/patches/removed/1.17/0187-PreCreatureSpawnEvent.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 17:01:31 -0500 -Subject: [PATCH] PreCreatureSpawnEvent -1.17: Has to be looked into more -Adds an event to fire before an Entity is created, so that plugins that need to cancel -CreatureSpawnEvent can do so from this event instead. - -Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste -as it's done after the Entity object has been fully created. - -Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event -instead and save a lot of server resources. - -See: https://github.com/PaperMC/Paper/issues/917 - -diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index e3d92d1d35911b2960a7ca82bd4f324d285d0533..e39d950783599b01271bdb7e67fe68b46af0c49c 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -17,6 +17,7 @@ import net.minecraft.nbt.ListTag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.tags.BlockTags; -@@ -317,6 +318,20 @@ public class EntityType { - - @Nullable - public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ // Paper start - Call PreCreatureSpawnEvent -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath()); -+ if (type != null) { -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(worldserver, blockposition), -+ type, -+ spawnReason -+ ); -+ if (!event.callEvent()) { -+ return null; -+ } -+ } -+ // Paper end - T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); - - if (t0 != null) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java -index f3a7807a20b279056d5640ab02aa77f7b1dabc2a..880d69bad933294a2cfdea9adb3e648e29eb42be 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java -@@ -33,8 +33,8 @@ public class GolemSensor extends Sensor { - Optional> optional = entityliving.getBrain().getMemory(MemoryModuleType.MOBS); - - if (optional.isPresent()) { -- boolean flag = ((List) optional.get()).stream().anyMatch((entityliving1) -> { -- return entityliving1.getEntityType().equals(EntityType.IRON_GOLEM); -+ boolean flag = optional.get().stream().anyMatch((entityliving1) -> { // Paper - decompile fixes -+ return entityliving1.getType().equals(EntityType.IRON_GOLEM); - }); - - if (flag) { -@@ -44,6 +44,7 @@ public class GolemSensor extends Sensor { - } - } - -+ public static void setDetectedRecently(LivingEntity entityLiving) { golemDetected(entityLiving); } // Paper - OBFHELPER - public static void golemDetected(LivingEntity entityliving) { - entityliving.getBrain().setMemoryWithExpiry(MemoryModuleType.GOLEM_DETECTED_RECENTLY, true, 600L); - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index a66fab2e04a5d87ced139ed15d2434c5ffcec695..eed6265dc8275921a18fc5f4970ba131ba782132 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/Villager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.DebugPackets; - import net.minecraft.network.syncher.EntityDataAccessor; - import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.sounds.SoundEvent; -@@ -942,6 +943,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - BlockPos blockposition1 = this.findSpawnPositionForGolemInColumn(blockposition, d0, d1); - - if (blockposition1 != null) { -+ // Paper start - Call PreCreatureSpawnEvent -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(level, blockposition1), -+ org.bukkit.entity.EntityType.IRON_GOLEM, -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE -+ ); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ GolemSensor.golemDetected(this); // Set Golem Last Seen to stop it from spawning another one -+ return null; -+ } -+ break; -+ } -+ // Paper end - IronGolem entityirongolem = (IronGolem) EntityType.IRON_GOLEM.create(world, (CompoundTag) null, (Component) null, (Player) null, blockposition1, MobSpawnType.MOB_SUMMONED, false, false); - - if (entityirongolem != null) { -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 4582fc1bb767214241568fbc22b0ee2cbf3322e0..ac572eba10a7239d71dfae060f623b076d4252ce 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -12,6 +12,7 @@ import net.minecraft.core.particles.ParticleTypes; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.StringUtil; - import net.minecraft.util.WeighedRandom; -@@ -125,6 +126,27 @@ public abstract class BaseSpawner { - ServerLevel worldserver = (ServerLevel) world; - - if (SpawnPlacements.checkSpawnRules((EntityType) optional.get(), worldserver, MobSpawnType.SPAWNER, new BlockPos(d3, d4, d5), world.getRandom())) { -+ // Paper start -+ EntityType entityType = optional.get(); -+ String key = EntityType.getKey(entityType).getPath(); -+ -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); -+ if (type != null) { -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(world, d3, d4, d5), -+ type, -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER -+ ); -+ if (!event.callEvent()) { -+ flag = true; -+ if (event.shouldAbortSpawn()) { -+ break; -+ } -+ continue; -+ } -+ } -+ // Paper end - Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> { - entity1.moveTo(d3, d4, d5, entity1.yRot, entity1.xRot); - return entity1; -diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index a19ac1cb7e4d8d478648a048b2bfa0daf85a80c9..8a71eaf2855be0d415d1f7b18dbec98353fe5b47 100644 ---- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java -+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -15,6 +15,7 @@ import net.minecraft.core.Direction; - import net.minecraft.core.Position; - import net.minecraft.core.Registry; - import net.minecraft.nbt.CompoundTag; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.tags.BlockTags; - import net.minecraft.tags.FluidTags; -@@ -214,9 +215,16 @@ public final class NaturalSpawner { - j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); - } - -- if (isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { -+ // Paper start -+ Boolean doSpawning = a(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); -+ if (doSpawning == null) { -+ return; -+ } -+ if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { -+ // Paper end - Mob entityinsentient = getMobForSpawn(world, biomesettingsmobs_c.type); - -+ - if (entityinsentient == null) { - return; - } -@@ -269,17 +277,33 @@ public final class NaturalSpawner { - } - } - -- private static boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { -- EntityType entitytypes = spawnEntry.type; -+ private static Boolean a(ServerLevel worldserver, MobCategory enumcreaturetype, StructureFeatureManager structuremanager, ChunkGenerator chunkgenerator, MobSpawnSettings.SpawnerData biomesettingsmobs_c, BlockPos.MutableBlockPos blockposition_mutableblockposition, double d0) { // Paper -+ EntityType entitytypes = biomesettingsmobs_c.type; -+ // Paper start -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(entitytypes).getPath()); -+ if (type != null) { -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(worldserver, blockposition_mutableblockposition), -+ type, SpawnReason.NATURAL -+ ); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ return null; -+ } -+ return false; -+ } -+ } -+ // Paper end - - if (entitytypes.getCategory() == MobCategory.MISC) { - return false; -- } else if (!entitytypes.canSpawnFarFromPlayer() && squaredDistance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { -+ } else if (!entitytypes.canSpawnFarFromPlayer() && d0 > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { - return false; -- } else if (entitytypes.canSummon() && canSpawnMobAt(world, structureAccessor, chunkGenerator, group, spawnEntry, (BlockPos) pos)) { -+ } else if (entitytypes.canSummon() && canSpawnMobAt(worldserver, structuremanager, chunkgenerator, enumcreaturetype, biomesettingsmobs_c, (BlockPos) blockposition_mutableblockposition)) { - SpawnPlacements.Type entitypositiontypes_surface = SpawnPlacements.getPlacementType(entitytypes); - -- return !isSpawnPositionOk(entitypositiontypes_surface, (LevelReader) world, pos, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, world, MobSpawnType.NATURAL, pos, world.random) ? false : world.noCollision(entitytypes.getAABB((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D))); -+ return !isSpawnPositionOk(entitypositiontypes_surface, (LevelReader) worldserver, blockposition_mutableblockposition, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, worldserver, MobSpawnType.NATURAL, blockposition_mutableblockposition, worldserver.random) ? false : worldserver.noCollision(entitytypes.getAABB((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D))); - } else { - return false; - } diff --git a/patches/server/0330-PreCreatureSpawnEvent.patch b/patches/server/0330-PreCreatureSpawnEvent.patch new file mode 100644 index 0000000000..f15e5b7e00 --- /dev/null +++ b/patches/server/0330-PreCreatureSpawnEvent.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 14 Jan 2018 17:01:31 -0500 +Subject: [PATCH] PreCreatureSpawnEvent + +Adds an event to fire before an Entity is created, so that plugins that need to cancel +CreatureSpawnEvent can do so from this event instead. + +Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste +as it's done after the Entity object has been fully created. + +Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event +instead and save a lot of server resources. + +See: https://github.com/PaperMC/Paper/issues/917 + +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index 9f5f2bd9bdfce14da030b09f56c821ec1989e12f..872f92ac1a6bc86ce54700dbf555ceea4fab2057 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -333,6 +333,20 @@ public class EntityType implements EntityTypeTest { + + @Nullable + public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // Paper start - Call PreCreatureSpawnEvent ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath()); ++ if (type != null) { ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ net.minecraft.server.MCUtil.toLocation(worldserver, blockposition), ++ type, ++ spawnReason ++ ); ++ if (!event.callEvent()) { ++ return null; ++ } ++ } ++ // Paper end + T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); + + if (t0 != null) { +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 6a9e2105b2d9a4ee83c0a2516d5ef26dc3b99053..aec77679584a2acab5818e26e2586b5316118e84 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -987,6 +987,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + BlockPos blockposition1 = this.findSpawnPositionForGolemInColumn(blockposition, d0, d1); + + if (blockposition1 != null) { ++ // Paper start - Call PreCreatureSpawnEvent ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ net.minecraft.server.MCUtil.toLocation(level, blockposition1), ++ org.bukkit.entity.EntityType.IRON_GOLEM, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE ++ ); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ GolemSensor.golemDetected(this); // Set Golem Last Seen to stop it from spawning another one ++ return null; ++ } ++ break; ++ } ++ // Paper end + IronGolem entityirongolem = (IronGolem) EntityType.IRON_GOLEM.create(world, (CompoundTag) null, (Component) null, (Player) null, blockposition1, MobSpawnType.MOB_SUMMONED, false, false); + + if (entityirongolem != null) { +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index c6298b12e4e0c20be20e7e493be728f028f9eb31..68ce2732dfdc25ddadc15c43c30a609f9b1eba86 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -132,6 +132,27 @@ public abstract class BaseSpawner { + double d2 = j >= 3 ? nbttaglist.getDouble(2) : (double) pos.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) this.spawnRange + 0.5D; + + if (world.noCollision(((EntityType) optional.get()).getAABB(d0, d1, d2)) && SpawnPlacements.checkSpawnRules((EntityType) optional.get(), world, MobSpawnType.SPAWNER, new BlockPos(d0, d1, d2), world.getRandom())) { ++ // Paper start ++ EntityType entityType = optional.get(); ++ String key = EntityType.getKey(entityType).getPath(); ++ ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); ++ if (type != null) { ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ net.minecraft.server.MCUtil.toLocation(world, d0, d1, d2), ++ type, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER ++ ); ++ if (!event.callEvent()) { ++ flag = true; ++ if (event.shouldAbortSpawn()) { ++ break; ++ } ++ continue; ++ } ++ } ++ // Paper end + Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> { + entity1.moveTo(d0, d1, d2, entity1.getYRot(), entity1.getXRot()); + return entity1; +@@ -349,3 +370,4 @@ public abstract class BaseSpawner { + return this.oSpin; + } + } ++ +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index 30ba1e3cb75d994770b006b9dfd6669000a9c1a4..6204bf41d410df9784b32f993b46d7adb2af5f13 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -231,7 +231,13 @@ public final class NaturalSpawner { + j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); + } + +- if (NaturalSpawner.isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ // Paper start ++ Boolean doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); ++ if (doSpawning == null) { ++ return; ++ } ++ if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ // Paper end + Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type); + + if (entityinsentient == null) { +@@ -278,9 +284,25 @@ public final class NaturalSpawner { + return squaredDistance <= 576.0D ? false : (world.getSharedSpawnPos().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D) ? false : Objects.equals(new ChunkPos(pos), chunk.getPos()) || world.isPositionEntityTicking((BlockPos) pos)); + } + +- private static boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { ++ private static Boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { // Paper + EntityType entitytypes = spawnEntry.type; + ++ // Paper start ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(entitytypes).getPath()); ++ if (type != null) { ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ net.minecraft.server.MCUtil.toLocation(world, pos), ++ type, SpawnReason.NATURAL ++ ); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ return null; ++ } ++ return false; ++ } ++ } ++ // Paper end + if (entitytypes.getCategory() == MobCategory.MISC) { + return false; + } else if (!entitytypes.canSpawnFarFromPlayer() && squaredDistance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { From ba374d24858bb68eb466daa8b920c8e5a0919b19 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 22:38:49 -0700 Subject: [PATCH 101/226] reorder --- ...awnEvent.patch => 0173-PreCreatureSpawnEvent.patch} | 6 +++--- ... => 0174-Add-setPlayerProfile-API-for-Skulls.patch} | 0 ...s.patch => 0175-Fill-Profile-Property-Events.patch} | 0 ...=> 0176-PlayerAdvancementCriterionGrantEvent.patch} | 0 ...-Meta.patch => 0177-Add-ArmorStand-Item-Meta.patch} | 0 ... => 0178-Extend-Player-Interact-cancellation.patch} | 0 ....patch => 0179-Tameable-getOwnerUniqueId-API.patch} | 0 ...le-player-crits-helps-mitigate-hacked-client.patch} | 0 ...81-Disable-Explicit-Network-Manager-Flushing.patch} | 0 ...-Implement-extended-PaperServerListPingEvent.patch} | 0 ....patch => 0183-Improved-Async-Task-Scheduler.patch} | 0 ...to-change-PlayerProfile-in-AsyncPreLoginEven.patch} | 0 ...PI.patch => 0185-Player.setPlayerProfile-API.patch} | 0 ...ueId-API.patch => 0186-getPlayerUniqueId-API.patch} | 0 ...=> 0187-Make-player-data-saving-configurable.patch} | 0 ... 0188-Make-legacy-ping-handler-more-reliable.patch} | 0 ...ll-PaperServerListPingEvent-for-legacy-pings.patch} | 0 ...ch => 0190-Flag-to-disable-the-channel-limit.patch} | 0 ... 0191-Add-method-to-open-already-placed-sign.patch} | 0 ...2-Configurable-sprint-interruption-on-attack.patch} | 0 ...oit-that-allowed-colored-signs-to-be-created.patch} | 2 +- ...scapeEvent.patch => 0194-EndermanEscapeEvent.patch} | 0 ...omly.patch => 0195-Enderman.teleportRandomly.patch} | 0 ...atch => 0196-Block-Enderpearl-Travel-Exploit.patch} | 0 ...pand-World.spawnParticle-API-and-add-Builder.patch} | 0 ...vent-Frosted-Ice-from-loading-holding-chunks.patch} | 0 ...vent.patch => 0199-EndermanAttackPlayerEvent.patch} | 0 ...nEvent.patch => 0200-WitchConsumePotionEvent.patch} | 0 ...ionEvent.patch => 0201-WitchThrowPotionEvent.patch} | 0 ...pawning-Item-entities-with-World.spawnEntity.patch} | 0 ...ionEvent.patch => 0203-WitchReadyPotionEvent.patch} | 0 ...atch => 0204-ItemStack-getMaxItemUseDuration.patch} | 0 ...0205-Implement-EntityTeleportEndGatewayEvent.patch} | 2 +- ...et-Ignited-flag-on-cancel-of-Explosion-Event.patch} | 0 ...hCode.patch => 0207-Fix-CraftEntity-hashCode.patch} | 0 ...nfigurable-Alternative-LootPool-Luck-Formula.patch} | 0 ...ror-details-when-failing-to-save-player-data.patch} | 0 ...0210-Make-shield-blocking-delay-configurable.patch} | 0 ...nt.patch => 0211-Improve-EntityShootBowEvent.patch} | 0 ...rowEvent.patch => 0212-PlayerReadyArrowEvent.patch} | 0 ... 0213-Implement-EntityKnockbackByEntityEvent.patch} | 0 ...ions-API.patch => 0214-Expand-Explosions-API.patch} | 0 ...> 0215-LivingEntity-Hand-Raised-Item-Use-API.patch} | 0 ...gedEntity-API.patch => 0216-RangedEntity-API.patch} | 0 ...-config-to-disable-ender-dragon-legacy-check.patch} | 0 ...h => 0218-Implement-World.getEntity-UUID-API.patch} | 0 ...patch => 0219-InventoryCloseEvent-Reason-API.patch} | 0 ...er-API.patch => 0220-Vex-get-setSummoner-API.patch} | 0 ...player-inventory-when-cancelling-PlayerInter.patch} | 0 ...tem-merge-if-stack-size-above-max-stack-size.patch} | 0 ...tch => 0223-Use-asynchronous-Log4j-2-loggers.patch} | 2 +- ...0224-add-more-information-to-Entity.toString.patch} | 0 ...-Add-CraftMagicNumbers.isSupportedApiVersion.patch} | 0 ...agon-Events.patch => 0226-EnderDragon-Events.patch} | 0 ...stEvent.patch => 0227-PlayerElytraBoostEvent.patch} | 0 ...nt.patch => 0228-PlayerLaunchProjectileEvent.patch} | 0 ...patch => 0229-Improve-BlockPosition-inlining.patch} | 0 ...> 0230-Optimize-IntIdentityHashBiMiap-nextId.patch} | 0 ...o-prevent-armor-stands-from-doing-entity-loo.patch} | 0 ...h => 0232-Vanished-players-don-t-have-rights.patch} | 0 ...=> 0233-Allow-disabling-armour-stand-ticking.patch} | 0 ...itions.patch => 0234-SkeletonHorse-Additions.patch} | 0 ...> 0235-Don-t-call-getItemMeta-on-hasItemMeta.patch} | 0 ...ch => 0236-Implement-Expanded-ArmorStand-API.patch} | 0 ...ilDamageEvent.patch => 0237-AnvilDamageEvent.patch} | 0 ...ents.patch => 0238-Add-hand-to-bucket-events.patch} | 8 ++++---- ...NTPrimeEvent.patch => 0239-Add-TNTPrimeEvent.patch} | 0 ...eak-up-and-make-tab-spam-limits-configurable.patch} | 2 +- ...MC-135506-Experience-should-save-as-Integers.patch} | 0 ...2-Fix-client-rendering-skulls-from-same-user.patch} | 0 ...> 0243-Add-Early-Warning-Feature-to-WatchDog.patch} | 0 ...patch => 0244-Make-EnderDragon-implement-Mob.patch} | 0 ...ch => 0245-Use-ConcurrentHashMap-in-JsonList.patch} | 0 ...ch => 0246-Use-a-Queue-for-Queueing-Commands.patch} | 0 ...to-get-Tile-Entities-from-a-chunk-without-sn.patch} | 0 ...> 0248-Optimize-BlockPosition-helper-methods.patch} | 0 ...vanlla-default-mob-spawn-range-and-water-ani.patch} | 0 ...Events.patch => 0250-Slime-Pathfinder-Events.patch} | 0 ...nfigurable-speed-for-water-flowing-over-lava.patch} | 0 ...tch => 0252-Optimize-CraftBlockData-Creation.patch} | 0 ...gistry.patch => 0253-Optimize-MappedRegistry.patch} | 0 ...Event.patch => 0254-Add-PhantomPreSpawnEvent.patch} | 0 ...eeper-API.patch => 0255-Add-More-Creeper-API.patch} | 0 ...ot.patch => 0256-Inventory-removeItemAnySlot.patch} | 0 ...ftWorld-loadChunk-int-int-false-load-unconve.patch} | 0 ...ch => 0258-Asynchronous-chunk-IO-and-loading.patch} | 0 ...0259-Add-ray-tracing-methods-to-LivingEntity.patch} | 0 ...60-Expose-attack-cooldown-methods-for-Player.patch} | 0 ...th-events.patch => 0261-Improve-death-events.patch} | 0 ...0262-Allow-chests-to-be-placed-with-NBT-data.patch} | 0 ...inding-API.patch => 0263-Mob-Pathfinding-API.patch} | 0 ...264-Prevent-chunk-loading-from-Fluid-Flowing.patch} | 0 ...t-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch} | 0 ...266-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch} | 0 ...-mob-spawning-from-loading-generating-chunks.patch} | 2 +- ...-Implement-furnace-cook-speed-multiplier-API.patch} | 0 ...ch-JsonParseException-in-Entity-and-TE-names.patch} | 0 ...ck.patch => 0270-Honor-EntityAgeable.ageLock.patch} | 0 ...onfigurable-connection-throttle-kick-message.patch} | 0 ...s.patch => 0272-Hook-into-CB-plugin-rewrites.patch} | 0 ...elated-API.patch => 0273-Add-sun-related-API.patch} | 0 ...tch => 0274-Add-LivingEntity-getTargetEntity.patch} | 0 .../{0274-Turtle-API.patch => 0275-Turtle-API.patch} | 0 ...-Check-other-worlds-for-shooter-of-projectil.patch} | 0 ...yer-spectator-target-events-and-improve-impl.patch} | 0 ...h => 0278-Add-Velocity-IP-Forwarding-Support.patch} | 0 ...e-Witch-API.patch => 0279-Add-more-Witch-API.patch} | 0 ...Check-Drowned-for-Villager-Aggression-Config.patch} | 0 ...80-Here-s-Johnny.patch => 0281-Here-s-Johnny.patch} | 0 ...on-to-prevent-players-from-moving-into-unloa.patch} | 0 ...ch => 0283-Reset-players-airTicks-on-respawn.patch} | 0 ...-t-sleep-after-profile-lookups-if-not-needed.patch} | 0 ...ove-Server-Thread-Pool-and-Thread-Priorities.patch} | 0 ...es.patch => 0286-Optimize-World-Time-Updates.patch} | 0 ... 0287-Restore-custom-InventoryHolder-support.patch} | 0 ...ds.patch => 0288-Use-Vanilla-Minecart-Speeds.patch} | 0 ...patch => 0289-Fix-SpongeAbsortEvent-handling.patch} | 0 ...290-Don-t-allow-digging-into-unloaded-chunks.patch} | 0 ...-the-default-permission-message-configurable.patch} | 0 ...=> 0292-Prevent-rayTrace-from-loading-chunks.patch} | 0 ...93-Handle-Large-Packets-disconnecting-client.patch} | 0 ...4-force-entity-dismount-during-teleportation.patch} | 0 ...Zombie-API.patch => 0295-Add-more-Zombie-API.patch} | 0 ...k-Size-Limits.patch => 0296-Book-Size-Limits.patch} | 0 ...patch => 0297-Add-PlayerConnectionCloseEvent.patch} | 0 ...=> 0298-Prevent-Enderman-from-loading-chunks.patch} | 0 ...-APIs-to-replace-OfflinePlayer-getLastPlayed.patch} | 0 ...und-for-vehicle-tracking-issue-on-disconnect.patch} | 0 ...lockPistonRetractEvent-for-all-empty-pistons.patch} | 0 ...k-Entity-remove-from-being-called-on-Players.patch} | 0 ...DestroyEvent.patch => 0303-BlockDestroyEvent.patch} | 0 ...Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch} | 0 ....patch => 0305-Limit-Client-Sign-length-more.patch} | 0 ...t-check-ConvertSigns-boolean-every-sign-save.patch} | 0 ...-Network-Manager-and-add-advanced-packet-sup.patch} | 0 ...308-Handle-Oversized-Tile-Entities-in-chunks.patch} | 0 ...MC-145260-Fix-Whitelist-On-Off-inconsistency.patch} | 0 ...ombie-last-tick-at-start-of-drowning-process.patch} | 0 ...itelistToggleEvent-when-whitelist-is-toggled.patch} | 0 ...er-max-length-when-serialising-BungeeCord-te.patch} | 0 ...on.patch => 0313-Entity-getEntitySpawnReason.patch} | 4 ++-- ...date-entity-Metadata-for-all-tracked-players.patch} | 0 ...-query.patch => 0315-Fire-event-on-GS4-query.patch} | 0 ...tch => 0316-Implement-PlayerPostRespawnEvent.patch} | 0 ...-below-0-for-pickupDelay-breaks-picking-up-i.patch} | 0 ...Tick-Events.patch => 0318-Server-Tick-Events.patch} | 0 ...atch => 0319-PlayerDeathEvent-getItemsToKeep.patch} | 0 ... => 0320-Optimize-Captured-TileEntity-Lookup.patch} | 0 ...eightmap-API.patch => 0321-Add-Heightmap-API.patch} | 0 ...s.patch => 0322-Mob-Spawner-API-Enhancements.patch} | 10 +++++----- ...x-CB-call-to-changed-postToMainThread-method.patch} | 0 ...unds-when-item-frames-are-modified-MC-123450.patch} | 0 ...tServer-isPrimaryThread-and-MinecraftServer-.patch} | 0 ...tch => 0326-improve-CraftWorld-isChunkLoaded.patch} | 0 ...nfigurable-Keep-Spawn-Loaded-range-per-world.patch} | 0 ...tance-CME.patch => 0328-ChunkMapDistance-CME.patch} | 0 ...patch => 0329-Implement-CraftBlockSoundGroup.patch} | 0 ...ug-command.patch => 0330-Chunk-debug-command.patch} | 0 ...tch => 0331-Fix-World-isChunkGenerated-calls.patch} | 0 ...-blockstate-location-if-we-failed-to-read-it.patch} | 0 ...nt-Natural-Spawned-mobs-towards-natural-spaw.patch} | 2 +- ...34-Configurable-projectile-relative-velocity.patch} | 0 ...king.patch => 0335-offset-item-frame-ticking.patch} | 0 ...ss-work-if-we-have-a-custom-Bukkit-generator.patch} | 0 ...36-Fix-MC-158900.patch => 0337-Fix-MC-158900.patch} | 0 ...> 0338-Prevent-consuming-the-wrong-itemstack.patch} | 0 ...or-Settings.patch => 0339-Generator-Settings.patch} | 0 ...39-Fix-MC-161754.patch => 0340-Fix-MC-161754.patch} | 0 ...ning-of-hanging-entities-that-are-not-ItemFr.patch} | 0 ...tch => 0342-Expose-the-internal-current-tick.patch} | 0 ...stuck-in-sneak-when-changing-worlds-MC-10657.patch} | 0 ... 0344-Add-option-to-disable-pillager-patrols.patch} | 0 ...rtionError-when-player-hand-set-to-empty-typ.patch} | 0 ...sync-chunk-loads-when-villagers-try-to-find-.patch} | 0 ...47-MC-145656-Fix-Follow-Range-Initial-Target.patch} | 0 ...imize-Hoppers.patch => 0348-Optimize-Hoppers.patch} | 0 ...> 0349-PlayerDeathEvent-shouldDropExperience.patch} | 0 ...t-bees-loading-chunks-checking-hive-position.patch} | 0 ...-t-load-Chunks-from-Hoppers-and-other-things.patch} | 0 ...ainst-serializing-mismatching-chunk-coordina.patch} | 0 ... 0353-Optimise-IEntityAccess-getPlayerByUUID.patch} | 0 ...atch => 0354-Fix-items-not-falling-correctly.patch} | 0 ...e-eating.patch => 0355-Lag-compensate-eating.patch} | 0 ...356-Optimize-call-to-getFluid-for-explosions.patch} | 0 ...-firework-in-stack-not-having-effects-when-d.patch} | 0 ... => 0358-Add-effect-to-block-break-naturally.patch} | 0 ....0.patch => 0359-Entity-Activation-Range-2.0.patch} | 2 +- ...Size.patch => 0360-Increase-Light-Queue-Size.patch} | 0 ...ight-Command.patch => 0361-Fix-Light-Command.patch} | 0 ...=> 0362-No-Tick-view-distance-implementation.patch} | 0 ...0363-Implement-alternative-item-despawn-rate.patch} | 0 ...ts.patch => 0364-Tracking-Range-Improvements.patch} | 0 ... 0365-Fix-items-vanishing-through-end-portal.patch} | 0 ...366-implement-optional-per-player-mob-spawns.patch} | 8 ++++---- ...67-Bees-get-gravity-in-void.-Fixes-MC-167279.patch} | 0 ...-Optimise-getChunkAt-calls-for-loaded-chunks.patch} | 0 ...0369-Allow-overriding-the-java-version-check.patch} | 0 ...hEvent.patch => 0370-Add-ThrownEggHatchEvent.patch} | 0 ....patch => 0371-Optimise-random-block-ticking.patch} | 0 ...ntity-Jump-API.patch => 0372-Entity-Jump-API.patch} | 0 ...dd-option-to-nerf-pigmen-from-nether-portals.patch} | 0 ...ier.patch => 0374-Make-the-GUI-graph-fancier.patch} | 0 ...tch => 0375-add-hand-to-BlockMultiPlaceEvent.patch} | 0 ...ch => 0376-Prevent-teleporting-dead-entities.patch} | 0 ...lidate-tripwire-hook-placement-before-update.patch} | 0 ...-option-to-allow-iron-golems-to-spawn-in-air.patch} | 0 ...igurable-chance-of-villager-zombie-infection.patch} | 0 ...tFluid.patch => 0380-Optimise-Chunk-getFluid.patch} | 0 ...0381-Optimise-TickListServer-by-rewriting-it.patch} | 0 ...-patrol-spawn-settings-and-per-player-option.patch} | 0 ...emote-Connections-shouldn-t-hold-up-shutdown.patch} | 0 ...o-not-allow-bees-to-load-chunks-for-beehives.patch} | 0 ...t-Double-PlayerChunkMap-adds-crashing-server.patch} | 0 ...> 0386-Optimize-Collision-to-not-load-chunks.patch} | 0 ...layers.patch => 0387-Don-t-tick-dead-players.patch} | 0 ...0388-Dead-Player-s-shouldn-t-be-able-to-move.patch} | 0 ...-PlayerChunkMap-memory-use-for-visibleChunks.patch} | 0 ...-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch} | 0 ...1-Don-t-move-existing-players-to-world-spawn.patch} | 0 ... => 0392-Add-tick-times-API-and-mspt-command.patch} | 0 ...tch => 0393-Expose-MinecraftServer-isRunning.patch} | 0 ...=> 0394-Add-Raw-Byte-ItemStack-Serialization.patch} | 0 ...ch => 0395-Remove-streams-from-Mob-AI-System.patch} | 0 ...ing.patch => 0396-Async-command-map-building.patch} | 0 ...port.patch => 0397-Improved-Watchdog-Support.patch} | 0 ...thfinding.patch => 0398-Optimize-Pathfinding.patch} | 0 ...ch => 0399-Reduce-Either-Optional-allocation.patch} | 0 ...atch => 0400-Remove-streams-from-PairedQueue.patch} | 0 ...01-Reduce-memory-footprint-of-NBTTagCompound.patch} | 0 ...0402-Prevent-opening-inventories-when-frozen.patch} | 0 ...tch => 0403-Optimise-ArraySetSorted-removeIf.patch} | 0 ...on-t-run-entity-collision-code-if-not-needed.patch} | 0 ...-vanilla-teleport-command-to-valid-locations.patch} | 0 ... => 0406-Implement-Player-Client-Options-API.patch} | 0 ...0407-Fix-Chunk-Post-Processing-deadlock-risk.patch} | 0 ...ash-if-player-is-attempted-to-be-removed-fro.patch} | 0 ...ch => 0409-Broadcast-join-message-to-console.patch} | 0 ...gstanding-Broken-behavior-of-PlayerJoinEvent.patch} | 0 ...=> 0411-Load-Chunks-for-Login-Asynchronously.patch} | 0 ...yer-to-spawn-point-if-spawn-in-unloaded-worl.patch} | 0 ...413-Add-PlayerAttackEntityCooldownResetEvent.patch} | 0 ...ltiple-callbacks-to-schedule-for-Callback-Ex.patch} | 0 ...415-Don-t-fire-BlockFade-on-worldgen-threads.patch} | 0 ...-Add-phantom-creative-and-insomniac-controls.patch} | 0 ...rous-item-duplication-issues-and-teleport-is.patch} | 0 ...patch => 0418-Implement-Brigadier-Mojang-API.patch} | 0 ...ocks-API.patch => 0419-Villager-Restocks-API.patch} | 2 +- ...alidate-PickItem-Packet-and-kick-for-invalid.patch} | 0 ...me-version.patch => 0421-Expose-game-version.patch} | 0 ...g.patch => 0422-Optimize-Voxel-Shape-Merging.patch} | 0 ...p-on-JDK-per-thread-native-byte-buffer-cache.patch} | 0 ...oal-API.patch => 0424-Implement-Mob-Goal-API.patch} | 0 ...-Use-distance-map-to-optimise-entity-tracker.patch} | 0 ...Optimize-isOutsideRange-to-use-distance-maps.patch} | 0 ...PI.patch => 0427-Add-villager-reputation-API.patch} | 4 ++-- ...tion-for-maximum-exp-value-when-merging-orbs.patch} | 0 ...eEvent.patch => 0429-ExperienceOrbMergeEvent.patch} | 0 ...h => 0430-Fix-PotionEffect-ignores-icon-flag.patch} | 0 ...Optimize-brigadier-child-sorting-performance.patch} | 0 ...tial-bed-API.patch => 0432-Potential-bed-API.patch} | 0 ...=> 0433-Wait-for-Async-Tasks-during-shutdown.patch} | 0 ...ntityRaider-respects-game-and-entity-rules-f.patch} | 0 ...Bedrock-and-End-Portal-Frames-from-being-des.patch} | 0 ...uce-MutableInt-allocations-from-light-engine.patch} | 0 ...Reduce-allocation-of-Vec3D-by-entity-tracker.patch} | 0 ...t.patch => 0438-Ensure-safe-gateway-teleport.patch} | 0 ...dd-option-for-console-having-all-permissions.patch} | 0 ...40-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch} | 0 268 files changed, 28 insertions(+), 28 deletions(-) rename patches/server/{0330-PreCreatureSpawnEvent.patch => 0173-PreCreatureSpawnEvent.patch} (97%) rename patches/server/{0173-Add-setPlayerProfile-API-for-Skulls.patch => 0174-Add-setPlayerProfile-API-for-Skulls.patch} (100%) rename patches/server/{0174-Fill-Profile-Property-Events.patch => 0175-Fill-Profile-Property-Events.patch} (100%) rename patches/server/{0175-PlayerAdvancementCriterionGrantEvent.patch => 0176-PlayerAdvancementCriterionGrantEvent.patch} (100%) rename patches/server/{0176-Add-ArmorStand-Item-Meta.patch => 0177-Add-ArmorStand-Item-Meta.patch} (100%) rename patches/server/{0177-Extend-Player-Interact-cancellation.patch => 0178-Extend-Player-Interact-cancellation.patch} (100%) rename patches/server/{0178-Tameable-getOwnerUniqueId-API.patch => 0179-Tameable-getOwnerUniqueId-API.patch} (100%) rename patches/server/{0179-Toggleable-player-crits-helps-mitigate-hacked-client.patch => 0180-Toggleable-player-crits-helps-mitigate-hacked-client.patch} (100%) rename patches/server/{0180-Disable-Explicit-Network-Manager-Flushing.patch => 0181-Disable-Explicit-Network-Manager-Flushing.patch} (100%) rename patches/server/{0181-Implement-extended-PaperServerListPingEvent.patch => 0182-Implement-extended-PaperServerListPingEvent.patch} (100%) rename patches/server/{0182-Improved-Async-Task-Scheduler.patch => 0183-Improved-Async-Task-Scheduler.patch} (100%) rename patches/server/{0183-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch => 0184-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch} (100%) rename patches/server/{0184-Player.setPlayerProfile-API.patch => 0185-Player.setPlayerProfile-API.patch} (100%) rename patches/server/{0185-getPlayerUniqueId-API.patch => 0186-getPlayerUniqueId-API.patch} (100%) rename patches/server/{0186-Make-player-data-saving-configurable.patch => 0187-Make-player-data-saving-configurable.patch} (100%) rename patches/server/{0187-Make-legacy-ping-handler-more-reliable.patch => 0188-Make-legacy-ping-handler-more-reliable.patch} (100%) rename patches/server/{0188-Call-PaperServerListPingEvent-for-legacy-pings.patch => 0189-Call-PaperServerListPingEvent-for-legacy-pings.patch} (100%) rename patches/server/{0189-Flag-to-disable-the-channel-limit.patch => 0190-Flag-to-disable-the-channel-limit.patch} (100%) rename patches/server/{0190-Add-method-to-open-already-placed-sign.patch => 0191-Add-method-to-open-already-placed-sign.patch} (100%) rename patches/server/{0191-Configurable-sprint-interruption-on-attack.patch => 0192-Configurable-sprint-interruption-on-attack.patch} (100%) rename patches/server/{0192-Fix-exploit-that-allowed-colored-signs-to-be-created.patch => 0193-Fix-exploit-that-allowed-colored-signs-to-be-created.patch} (93%) rename patches/server/{0193-EndermanEscapeEvent.patch => 0194-EndermanEscapeEvent.patch} (100%) rename patches/server/{0194-Enderman.teleportRandomly.patch => 0195-Enderman.teleportRandomly.patch} (100%) rename patches/server/{0195-Block-Enderpearl-Travel-Exploit.patch => 0196-Block-Enderpearl-Travel-Exploit.patch} (100%) rename patches/server/{0196-Expand-World.spawnParticle-API-and-add-Builder.patch => 0197-Expand-World.spawnParticle-API-and-add-Builder.patch} (100%) rename patches/server/{0197-Prevent-Frosted-Ice-from-loading-holding-chunks.patch => 0198-Prevent-Frosted-Ice-from-loading-holding-chunks.patch} (100%) rename patches/server/{0198-EndermanAttackPlayerEvent.patch => 0199-EndermanAttackPlayerEvent.patch} (100%) rename patches/server/{0199-WitchConsumePotionEvent.patch => 0200-WitchConsumePotionEvent.patch} (100%) rename patches/server/{0200-WitchThrowPotionEvent.patch => 0201-WitchThrowPotionEvent.patch} (100%) rename patches/server/{0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch => 0202-Allow-spawning-Item-entities-with-World.spawnEntity.patch} (100%) rename patches/server/{0202-WitchReadyPotionEvent.patch => 0203-WitchReadyPotionEvent.patch} (100%) rename patches/server/{0203-ItemStack-getMaxItemUseDuration.patch => 0204-ItemStack-getMaxItemUseDuration.patch} (100%) rename patches/server/{0204-Implement-EntityTeleportEndGatewayEvent.patch => 0205-Implement-EntityTeleportEndGatewayEvent.patch} (95%) rename patches/server/{0205-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch => 0206-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch} (100%) rename patches/server/{0206-Fix-CraftEntity-hashCode.patch => 0207-Fix-CraftEntity-hashCode.patch} (100%) rename patches/server/{0207-Configurable-Alternative-LootPool-Luck-Formula.patch => 0208-Configurable-Alternative-LootPool-Luck-Formula.patch} (100%) rename patches/server/{0208-Print-Error-details-when-failing-to-save-player-data.patch => 0209-Print-Error-details-when-failing-to-save-player-data.patch} (100%) rename patches/server/{0209-Make-shield-blocking-delay-configurable.patch => 0210-Make-shield-blocking-delay-configurable.patch} (100%) rename patches/server/{0210-Improve-EntityShootBowEvent.patch => 0211-Improve-EntityShootBowEvent.patch} (100%) rename patches/server/{0211-PlayerReadyArrowEvent.patch => 0212-PlayerReadyArrowEvent.patch} (100%) rename patches/server/{0212-Implement-EntityKnockbackByEntityEvent.patch => 0213-Implement-EntityKnockbackByEntityEvent.patch} (100%) rename patches/server/{0213-Expand-Explosions-API.patch => 0214-Expand-Explosions-API.patch} (100%) rename patches/server/{0214-LivingEntity-Hand-Raised-Item-Use-API.patch => 0215-LivingEntity-Hand-Raised-Item-Use-API.patch} (100%) rename patches/server/{0215-RangedEntity-API.patch => 0216-RangedEntity-API.patch} (100%) rename patches/server/{0216-Add-config-to-disable-ender-dragon-legacy-check.patch => 0217-Add-config-to-disable-ender-dragon-legacy-check.patch} (100%) rename patches/server/{0217-Implement-World.getEntity-UUID-API.patch => 0218-Implement-World.getEntity-UUID-API.patch} (100%) rename patches/server/{0218-InventoryCloseEvent-Reason-API.patch => 0219-InventoryCloseEvent-Reason-API.patch} (100%) rename patches/server/{0219-Vex-get-setSummoner-API.patch => 0220-Vex-get-setSummoner-API.patch} (100%) rename patches/server/{0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch => 0221-Refresh-player-inventory-when-cancelling-PlayerInter.patch} (100%) rename patches/server/{0221-Avoid-item-merge-if-stack-size-above-max-stack-size.patch => 0222-Avoid-item-merge-if-stack-size-above-max-stack-size.patch} (100%) rename patches/server/{0222-Use-asynchronous-Log4j-2-loggers.patch => 0223-Use-asynchronous-Log4j-2-loggers.patch} (96%) rename patches/server/{0223-add-more-information-to-Entity.toString.patch => 0224-add-more-information-to-Entity.toString.patch} (100%) rename patches/server/{0224-Add-CraftMagicNumbers.isSupportedApiVersion.patch => 0225-Add-CraftMagicNumbers.isSupportedApiVersion.patch} (100%) rename patches/server/{0225-EnderDragon-Events.patch => 0226-EnderDragon-Events.patch} (100%) rename patches/server/{0226-PlayerElytraBoostEvent.patch => 0227-PlayerElytraBoostEvent.patch} (100%) rename patches/server/{0227-PlayerLaunchProjectileEvent.patch => 0228-PlayerLaunchProjectileEvent.patch} (100%) rename patches/server/{0228-Improve-BlockPosition-inlining.patch => 0229-Improve-BlockPosition-inlining.patch} (100%) rename patches/server/{0229-Optimize-IntIdentityHashBiMiap-nextId.patch => 0230-Optimize-IntIdentityHashBiMiap-nextId.patch} (100%) rename patches/server/{0230-Option-to-prevent-armor-stands-from-doing-entity-loo.patch => 0231-Option-to-prevent-armor-stands-from-doing-entity-loo.patch} (100%) rename patches/server/{0231-Vanished-players-don-t-have-rights.patch => 0232-Vanished-players-don-t-have-rights.patch} (100%) rename patches/server/{0232-Allow-disabling-armour-stand-ticking.patch => 0233-Allow-disabling-armour-stand-ticking.patch} (100%) rename patches/server/{0233-SkeletonHorse-Additions.patch => 0234-SkeletonHorse-Additions.patch} (100%) rename patches/server/{0234-Don-t-call-getItemMeta-on-hasItemMeta.patch => 0235-Don-t-call-getItemMeta-on-hasItemMeta.patch} (100%) rename patches/server/{0235-Implement-Expanded-ArmorStand-API.patch => 0236-Implement-Expanded-ArmorStand-API.patch} (100%) rename patches/server/{0236-AnvilDamageEvent.patch => 0237-AnvilDamageEvent.patch} (100%) rename patches/server/{0237-Add-hand-to-bucket-events.patch => 0238-Add-hand-to-bucket-events.patch} (97%) rename patches/server/{0238-Add-TNTPrimeEvent.patch => 0239-Add-TNTPrimeEvent.patch} (100%) rename patches/server/{0239-Break-up-and-make-tab-spam-limits-configurable.patch => 0240-Break-up-and-make-tab-spam-limits-configurable.patch} (98%) rename patches/server/{0240-MC-135506-Experience-should-save-as-Integers.patch => 0241-MC-135506-Experience-should-save-as-Integers.patch} (100%) rename patches/server/{0241-Fix-client-rendering-skulls-from-same-user.patch => 0242-Fix-client-rendering-skulls-from-same-user.patch} (100%) rename patches/server/{0242-Add-Early-Warning-Feature-to-WatchDog.patch => 0243-Add-Early-Warning-Feature-to-WatchDog.patch} (100%) rename patches/server/{0243-Make-EnderDragon-implement-Mob.patch => 0244-Make-EnderDragon-implement-Mob.patch} (100%) rename patches/server/{0244-Use-ConcurrentHashMap-in-JsonList.patch => 0245-Use-ConcurrentHashMap-in-JsonList.patch} (100%) rename patches/server/{0245-Use-a-Queue-for-Queueing-Commands.patch => 0246-Use-a-Queue-for-Queueing-Commands.patch} (100%) rename patches/server/{0246-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch => 0247-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch} (100%) rename patches/server/{0247-Optimize-BlockPosition-helper-methods.patch => 0248-Optimize-BlockPosition-helper-methods.patch} (100%) rename patches/server/{0248-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch => 0249-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch} (100%) rename patches/server/{0249-Slime-Pathfinder-Events.patch => 0250-Slime-Pathfinder-Events.patch} (100%) rename patches/server/{0250-Configurable-speed-for-water-flowing-over-lava.patch => 0251-Configurable-speed-for-water-flowing-over-lava.patch} (100%) rename patches/server/{0251-Optimize-CraftBlockData-Creation.patch => 0252-Optimize-CraftBlockData-Creation.patch} (100%) rename patches/server/{0252-Optimize-MappedRegistry.patch => 0253-Optimize-MappedRegistry.patch} (100%) rename patches/server/{0253-Add-PhantomPreSpawnEvent.patch => 0254-Add-PhantomPreSpawnEvent.patch} (100%) rename patches/server/{0254-Add-More-Creeper-API.patch => 0255-Add-More-Creeper-API.patch} (100%) rename patches/server/{0255-Inventory-removeItemAnySlot.patch => 0256-Inventory-removeItemAnySlot.patch} (100%) rename patches/server/{0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch => 0257-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch} (100%) rename patches/server/{0257-Asynchronous-chunk-IO-and-loading.patch => 0258-Asynchronous-chunk-IO-and-loading.patch} (100%) rename patches/server/{0258-Add-ray-tracing-methods-to-LivingEntity.patch => 0259-Add-ray-tracing-methods-to-LivingEntity.patch} (100%) rename patches/server/{0259-Expose-attack-cooldown-methods-for-Player.patch => 0260-Expose-attack-cooldown-methods-for-Player.patch} (100%) rename patches/server/{0260-Improve-death-events.patch => 0261-Improve-death-events.patch} (100%) rename patches/server/{0261-Allow-chests-to-be-placed-with-NBT-data.patch => 0262-Allow-chests-to-be-placed-with-NBT-data.patch} (100%) rename patches/server/{0262-Mob-Pathfinding-API.patch => 0263-Mob-Pathfinding-API.patch} (100%) rename patches/server/{0263-Prevent-chunk-loading-from-Fluid-Flowing.patch => 0264-Prevent-chunk-loading-from-Fluid-Flowing.patch} (100%) rename patches/server/{0264-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch => 0265-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch} (100%) rename patches/server/{0265-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch => 0266-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch} (100%) rename patches/server/{0266-Prevent-mob-spawning-from-loading-generating-chunks.patch => 0267-Prevent-mob-spawning-from-loading-generating-chunks.patch} (95%) rename patches/server/{0267-Implement-furnace-cook-speed-multiplier-API.patch => 0268-Implement-furnace-cook-speed-multiplier-API.patch} (100%) rename patches/server/{0268-Catch-JsonParseException-in-Entity-and-TE-names.patch => 0269-Catch-JsonParseException-in-Entity-and-TE-names.patch} (100%) rename patches/server/{0269-Honor-EntityAgeable.ageLock.patch => 0270-Honor-EntityAgeable.ageLock.patch} (100%) rename patches/server/{0270-Configurable-connection-throttle-kick-message.patch => 0271-Configurable-connection-throttle-kick-message.patch} (100%) rename patches/server/{0271-Hook-into-CB-plugin-rewrites.patch => 0272-Hook-into-CB-plugin-rewrites.patch} (100%) rename patches/server/{0272-Add-sun-related-API.patch => 0273-Add-sun-related-API.patch} (100%) rename patches/server/{0273-Add-LivingEntity-getTargetEntity.patch => 0274-Add-LivingEntity-getTargetEntity.patch} (100%) rename patches/server/{0274-Turtle-API.patch => 0275-Turtle-API.patch} (100%) rename patches/server/{0275-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch => 0276-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch} (100%) rename patches/server/{0276-Call-player-spectator-target-events-and-improve-impl.patch => 0277-Call-player-spectator-target-events-and-improve-impl.patch} (100%) rename patches/server/{0277-Add-Velocity-IP-Forwarding-Support.patch => 0278-Add-Velocity-IP-Forwarding-Support.patch} (100%) rename patches/server/{0278-Add-more-Witch-API.patch => 0279-Add-more-Witch-API.patch} (100%) rename patches/server/{0279-Check-Drowned-for-Villager-Aggression-Config.patch => 0280-Check-Drowned-for-Villager-Aggression-Config.patch} (100%) rename patches/server/{0280-Here-s-Johnny.patch => 0281-Here-s-Johnny.patch} (100%) rename patches/server/{0281-Add-option-to-prevent-players-from-moving-into-unloa.patch => 0282-Add-option-to-prevent-players-from-moving-into-unloa.patch} (100%) rename patches/server/{0282-Reset-players-airTicks-on-respawn.patch => 0283-Reset-players-airTicks-on-respawn.patch} (100%) rename patches/server/{0283-Don-t-sleep-after-profile-lookups-if-not-needed.patch => 0284-Don-t-sleep-after-profile-lookups-if-not-needed.patch} (100%) rename patches/server/{0284-Improve-Server-Thread-Pool-and-Thread-Priorities.patch => 0285-Improve-Server-Thread-Pool-and-Thread-Priorities.patch} (100%) rename patches/server/{0285-Optimize-World-Time-Updates.patch => 0286-Optimize-World-Time-Updates.patch} (100%) rename patches/server/{0286-Restore-custom-InventoryHolder-support.patch => 0287-Restore-custom-InventoryHolder-support.patch} (100%) rename patches/server/{0287-Use-Vanilla-Minecart-Speeds.patch => 0288-Use-Vanilla-Minecart-Speeds.patch} (100%) rename patches/server/{0288-Fix-SpongeAbsortEvent-handling.patch => 0289-Fix-SpongeAbsortEvent-handling.patch} (100%) rename patches/server/{0289-Don-t-allow-digging-into-unloaded-chunks.patch => 0290-Don-t-allow-digging-into-unloaded-chunks.patch} (100%) rename patches/server/{0290-Make-the-default-permission-message-configurable.patch => 0291-Make-the-default-permission-message-configurable.patch} (100%) rename patches/server/{0291-Prevent-rayTrace-from-loading-chunks.patch => 0292-Prevent-rayTrace-from-loading-chunks.patch} (100%) rename patches/server/{0292-Handle-Large-Packets-disconnecting-client.patch => 0293-Handle-Large-Packets-disconnecting-client.patch} (100%) rename patches/server/{0293-force-entity-dismount-during-teleportation.patch => 0294-force-entity-dismount-during-teleportation.patch} (100%) rename patches/server/{0294-Add-more-Zombie-API.patch => 0295-Add-more-Zombie-API.patch} (100%) rename patches/server/{0295-Book-Size-Limits.patch => 0296-Book-Size-Limits.patch} (100%) rename patches/server/{0296-Add-PlayerConnectionCloseEvent.patch => 0297-Add-PlayerConnectionCloseEvent.patch} (100%) rename patches/server/{0297-Prevent-Enderman-from-loading-chunks.patch => 0298-Prevent-Enderman-from-loading-chunks.patch} (100%) rename patches/server/{0298-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch => 0299-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch} (100%) rename patches/server/{0299-Workaround-for-vehicle-tracking-issue-on-disconnect.patch => 0300-Workaround-for-vehicle-tracking-issue-on-disconnect.patch} (100%) rename patches/server/{0300-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch => 0301-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch} (100%) rename patches/server/{0301-Block-Entity-remove-from-being-called-on-Players.patch => 0302-Block-Entity-remove-from-being-called-on-Players.patch} (100%) rename patches/server/{0302-BlockDestroyEvent.patch => 0303-BlockDestroyEvent.patch} (100%) rename patches/server/{0303-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch => 0304-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch} (100%) rename patches/server/{0304-Limit-Client-Sign-length-more.patch => 0305-Limit-Client-Sign-length-more.patch} (100%) rename patches/server/{0305-Don-t-check-ConvertSigns-boolean-every-sign-save.patch => 0306-Don-t-check-ConvertSigns-boolean-every-sign-save.patch} (100%) rename patches/server/{0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch => 0307-Optimize-Network-Manager-and-add-advanced-packet-sup.patch} (100%) rename patches/server/{0307-Handle-Oversized-Tile-Entities-in-chunks.patch => 0308-Handle-Oversized-Tile-Entities-in-chunks.patch} (100%) rename patches/server/{0308-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch => 0309-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch} (100%) rename patches/server/{0309-Set-Zombie-last-tick-at-start-of-drowning-process.patch => 0310-Set-Zombie-last-tick-at-start-of-drowning-process.patch} (100%) rename patches/server/{0310-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch => 0311-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch} (100%) rename patches/server/{0311-Use-proper-max-length-when-serialising-BungeeCord-te.patch => 0312-Use-proper-max-length-when-serialising-BungeeCord-te.patch} (100%) rename patches/server/{0312-Entity-getEntitySpawnReason.patch => 0313-Entity-getEntitySpawnReason.patch} (97%) rename patches/server/{0313-Update-entity-Metadata-for-all-tracked-players.patch => 0314-Update-entity-Metadata-for-all-tracked-players.patch} (100%) rename patches/server/{0314-Fire-event-on-GS4-query.patch => 0315-Fire-event-on-GS4-query.patch} (100%) rename patches/server/{0315-Implement-PlayerPostRespawnEvent.patch => 0316-Implement-PlayerPostRespawnEvent.patch} (100%) rename patches/server/{0316-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch => 0317-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch} (100%) rename patches/server/{0317-Server-Tick-Events.patch => 0318-Server-Tick-Events.patch} (100%) rename patches/server/{0318-PlayerDeathEvent-getItemsToKeep.patch => 0319-PlayerDeathEvent-getItemsToKeep.patch} (100%) rename patches/server/{0319-Optimize-Captured-TileEntity-Lookup.patch => 0320-Optimize-Captured-TileEntity-Lookup.patch} (100%) rename patches/server/{0320-Add-Heightmap-API.patch => 0321-Add-Heightmap-API.patch} (100%) rename patches/server/{0321-Mob-Spawner-API-Enhancements.patch => 0322-Mob-Spawner-API-Enhancements.patch} (95%) rename patches/server/{0322-Fix-CB-call-to-changed-postToMainThread-method.patch => 0323-Fix-CB-call-to-changed-postToMainThread-method.patch} (100%) rename patches/server/{0323-Fix-sounds-when-item-frames-are-modified-MC-123450.patch => 0324-Fix-sounds-when-item-frames-are-modified-MC-123450.patch} (100%) rename patches/server/{0324-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch => 0325-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch} (100%) rename patches/server/{0325-improve-CraftWorld-isChunkLoaded.patch => 0326-improve-CraftWorld-isChunkLoaded.patch} (100%) rename patches/server/{0326-Configurable-Keep-Spawn-Loaded-range-per-world.patch => 0327-Configurable-Keep-Spawn-Loaded-range-per-world.patch} (100%) rename patches/server/{0327-ChunkMapDistance-CME.patch => 0328-ChunkMapDistance-CME.patch} (100%) rename patches/server/{0328-Implement-CraftBlockSoundGroup.patch => 0329-Implement-CraftBlockSoundGroup.patch} (100%) rename patches/server/{0329-Chunk-debug-command.patch => 0330-Chunk-debug-command.patch} (100%) rename patches/server/{0330-Fix-World-isChunkGenerated-calls.patch => 0331-Fix-World-isChunkGenerated-calls.patch} (100%) rename patches/server/{0331-Show-blockstate-location-if-we-failed-to-read-it.patch => 0332-Show-blockstate-location-if-we-failed-to-read-it.patch} (100%) rename patches/server/{0332-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch => 0333-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch} (96%) rename patches/server/{0333-Configurable-projectile-relative-velocity.patch => 0334-Configurable-projectile-relative-velocity.patch} (100%) rename patches/server/{0334-offset-item-frame-ticking.patch => 0335-offset-item-frame-ticking.patch} (100%) rename patches/server/{0335-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch => 0336-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch} (100%) rename patches/server/{0336-Fix-MC-158900.patch => 0337-Fix-MC-158900.patch} (100%) rename patches/server/{0337-Prevent-consuming-the-wrong-itemstack.patch => 0338-Prevent-consuming-the-wrong-itemstack.patch} (100%) rename patches/server/{0338-Generator-Settings.patch => 0339-Generator-Settings.patch} (100%) rename patches/server/{0339-Fix-MC-161754.patch => 0340-Fix-MC-161754.patch} (100%) rename patches/server/{0340-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch => 0341-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch} (100%) rename patches/server/{0341-Expose-the-internal-current-tick.patch => 0342-Expose-the-internal-current-tick.patch} (100%) rename patches/server/{0342-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch => 0343-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch} (100%) rename patches/server/{0343-Add-option-to-disable-pillager-patrols.patch => 0344-Add-option-to-disable-pillager-patrols.patch} (100%) rename patches/server/{0344-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch => 0345-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch} (100%) rename patches/server/{0345-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch => 0346-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch} (100%) rename patches/server/{0346-MC-145656-Fix-Follow-Range-Initial-Target.patch => 0347-MC-145656-Fix-Follow-Range-Initial-Target.patch} (100%) rename patches/server/{0347-Optimize-Hoppers.patch => 0348-Optimize-Hoppers.patch} (100%) rename patches/server/{0348-PlayerDeathEvent-shouldDropExperience.patch => 0349-PlayerDeathEvent-shouldDropExperience.patch} (100%) rename patches/server/{0349-Prevent-bees-loading-chunks-checking-hive-position.patch => 0350-Prevent-bees-loading-chunks-checking-hive-position.patch} (100%) rename patches/server/{0350-Don-t-load-Chunks-from-Hoppers-and-other-things.patch => 0351-Don-t-load-Chunks-from-Hoppers-and-other-things.patch} (100%) rename patches/server/{0351-Guard-against-serializing-mismatching-chunk-coordina.patch => 0352-Guard-against-serializing-mismatching-chunk-coordina.patch} (100%) rename patches/server/{0352-Optimise-IEntityAccess-getPlayerByUUID.patch => 0353-Optimise-IEntityAccess-getPlayerByUUID.patch} (100%) rename patches/server/{0353-Fix-items-not-falling-correctly.patch => 0354-Fix-items-not-falling-correctly.patch} (100%) rename patches/server/{0354-Lag-compensate-eating.patch => 0355-Lag-compensate-eating.patch} (100%) rename patches/server/{0355-Optimize-call-to-getFluid-for-explosions.patch => 0356-Optimize-call-to-getFluid-for-explosions.patch} (100%) rename patches/server/{0356-Fix-last-firework-in-stack-not-having-effects-when-d.patch => 0357-Fix-last-firework-in-stack-not-having-effects-when-d.patch} (100%) rename patches/server/{0357-Add-effect-to-block-break-naturally.patch => 0358-Add-effect-to-block-break-naturally.patch} (100%) rename patches/server/{0358-Entity-Activation-Range-2.0.patch => 0359-Entity-Activation-Range-2.0.patch} (99%) rename patches/server/{0359-Increase-Light-Queue-Size.patch => 0360-Increase-Light-Queue-Size.patch} (100%) rename patches/server/{0360-Fix-Light-Command.patch => 0361-Fix-Light-Command.patch} (100%) rename patches/server/{0361-No-Tick-view-distance-implementation.patch => 0362-No-Tick-view-distance-implementation.patch} (100%) rename patches/server/{0362-Implement-alternative-item-despawn-rate.patch => 0363-Implement-alternative-item-despawn-rate.patch} (100%) rename patches/server/{0363-Tracking-Range-Improvements.patch => 0364-Tracking-Range-Improvements.patch} (100%) rename patches/server/{0364-Fix-items-vanishing-through-end-portal.patch => 0365-Fix-items-vanishing-through-end-portal.patch} (100%) rename patches/server/{0365-implement-optional-per-player-mob-spawns.patch => 0366-implement-optional-per-player-mob-spawns.patch} (99%) rename patches/server/{0366-Bees-get-gravity-in-void.-Fixes-MC-167279.patch => 0367-Bees-get-gravity-in-void.-Fixes-MC-167279.patch} (100%) rename patches/server/{0367-Optimise-getChunkAt-calls-for-loaded-chunks.patch => 0368-Optimise-getChunkAt-calls-for-loaded-chunks.patch} (100%) rename patches/server/{0368-Allow-overriding-the-java-version-check.patch => 0369-Allow-overriding-the-java-version-check.patch} (100%) rename patches/server/{0369-Add-ThrownEggHatchEvent.patch => 0370-Add-ThrownEggHatchEvent.patch} (100%) rename patches/server/{0370-Optimise-random-block-ticking.patch => 0371-Optimise-random-block-ticking.patch} (100%) rename patches/server/{0371-Entity-Jump-API.patch => 0372-Entity-Jump-API.patch} (100%) rename patches/server/{0372-Add-option-to-nerf-pigmen-from-nether-portals.patch => 0373-Add-option-to-nerf-pigmen-from-nether-portals.patch} (100%) rename patches/server/{0373-Make-the-GUI-graph-fancier.patch => 0374-Make-the-GUI-graph-fancier.patch} (100%) rename patches/server/{0374-add-hand-to-BlockMultiPlaceEvent.patch => 0375-add-hand-to-BlockMultiPlaceEvent.patch} (100%) rename patches/server/{0375-Prevent-teleporting-dead-entities.patch => 0376-Prevent-teleporting-dead-entities.patch} (100%) rename patches/server/{0376-Validate-tripwire-hook-placement-before-update.patch => 0377-Validate-tripwire-hook-placement-before-update.patch} (100%) rename patches/server/{0377-Add-option-to-allow-iron-golems-to-spawn-in-air.patch => 0378-Add-option-to-allow-iron-golems-to-spawn-in-air.patch} (100%) rename patches/server/{0378-Configurable-chance-of-villager-zombie-infection.patch => 0379-Configurable-chance-of-villager-zombie-infection.patch} (100%) rename patches/server/{0379-Optimise-Chunk-getFluid.patch => 0380-Optimise-Chunk-getFluid.patch} (100%) rename patches/server/{0380-Optimise-TickListServer-by-rewriting-it.patch => 0381-Optimise-TickListServer-by-rewriting-it.patch} (100%) rename patches/server/{0381-Pillager-patrol-spawn-settings-and-per-player-option.patch => 0382-Pillager-patrol-spawn-settings-and-per-player-option.patch} (100%) rename patches/server/{0382-Remote-Connections-shouldn-t-hold-up-shutdown.patch => 0383-Remote-Connections-shouldn-t-hold-up-shutdown.patch} (100%) rename patches/server/{0383-Do-not-allow-bees-to-load-chunks-for-beehives.patch => 0384-Do-not-allow-bees-to-load-chunks-for-beehives.patch} (100%) rename patches/server/{0384-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch => 0385-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch} (100%) rename patches/server/{0385-Optimize-Collision-to-not-load-chunks.patch => 0386-Optimize-Collision-to-not-load-chunks.patch} (100%) rename patches/server/{0386-Don-t-tick-dead-players.patch => 0387-Don-t-tick-dead-players.patch} (100%) rename patches/server/{0387-Dead-Player-s-shouldn-t-be-able-to-move.patch => 0388-Dead-Player-s-shouldn-t-be-able-to-move.patch} (100%) rename patches/server/{0388-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch => 0389-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch} (100%) rename patches/server/{0389-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch => 0390-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch} (100%) rename patches/server/{0390-Don-t-move-existing-players-to-world-spawn.patch => 0391-Don-t-move-existing-players-to-world-spawn.patch} (100%) rename patches/server/{0391-Add-tick-times-API-and-mspt-command.patch => 0392-Add-tick-times-API-and-mspt-command.patch} (100%) rename patches/server/{0392-Expose-MinecraftServer-isRunning.patch => 0393-Expose-MinecraftServer-isRunning.patch} (100%) rename patches/server/{0393-Add-Raw-Byte-ItemStack-Serialization.patch => 0394-Add-Raw-Byte-ItemStack-Serialization.patch} (100%) rename patches/server/{0394-Remove-streams-from-Mob-AI-System.patch => 0395-Remove-streams-from-Mob-AI-System.patch} (100%) rename patches/server/{0395-Async-command-map-building.patch => 0396-Async-command-map-building.patch} (100%) rename patches/server/{0396-Improved-Watchdog-Support.patch => 0397-Improved-Watchdog-Support.patch} (100%) rename patches/server/{0397-Optimize-Pathfinding.patch => 0398-Optimize-Pathfinding.patch} (100%) rename patches/server/{0398-Reduce-Either-Optional-allocation.patch => 0399-Reduce-Either-Optional-allocation.patch} (100%) rename patches/server/{0399-Remove-streams-from-PairedQueue.patch => 0400-Remove-streams-from-PairedQueue.patch} (100%) rename patches/server/{0400-Reduce-memory-footprint-of-NBTTagCompound.patch => 0401-Reduce-memory-footprint-of-NBTTagCompound.patch} (100%) rename patches/server/{0401-Prevent-opening-inventories-when-frozen.patch => 0402-Prevent-opening-inventories-when-frozen.patch} (100%) rename patches/server/{0402-Optimise-ArraySetSorted-removeIf.patch => 0403-Optimise-ArraySetSorted-removeIf.patch} (100%) rename patches/server/{0403-Don-t-run-entity-collision-code-if-not-needed.patch => 0404-Don-t-run-entity-collision-code-if-not-needed.patch} (100%) rename patches/server/{0404-Restrict-vanilla-teleport-command-to-valid-locations.patch => 0405-Restrict-vanilla-teleport-command-to-valid-locations.patch} (100%) rename patches/server/{0405-Implement-Player-Client-Options-API.patch => 0406-Implement-Player-Client-Options-API.patch} (100%) rename patches/server/{0406-Fix-Chunk-Post-Processing-deadlock-risk.patch => 0407-Fix-Chunk-Post-Processing-deadlock-risk.patch} (100%) rename patches/server/{0407-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch => 0408-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch} (100%) rename patches/server/{0408-Broadcast-join-message-to-console.patch => 0409-Broadcast-join-message-to-console.patch} (100%) rename patches/server/{0409-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch => 0410-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch} (100%) rename patches/server/{0410-Load-Chunks-for-Login-Asynchronously.patch => 0411-Load-Chunks-for-Login-Asynchronously.patch} (100%) rename patches/server/{0411-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch => 0412-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch} (100%) rename patches/server/{0412-Add-PlayerAttackEntityCooldownResetEvent.patch => 0413-Add-PlayerAttackEntityCooldownResetEvent.patch} (100%) rename patches/server/{0413-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch => 0414-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch} (100%) rename patches/server/{0414-Don-t-fire-BlockFade-on-worldgen-threads.patch => 0415-Don-t-fire-BlockFade-on-worldgen-threads.patch} (100%) rename patches/server/{0415-Add-phantom-creative-and-insomniac-controls.patch => 0416-Add-phantom-creative-and-insomniac-controls.patch} (100%) rename patches/server/{0416-Fix-numerous-item-duplication-issues-and-teleport-is.patch => 0417-Fix-numerous-item-duplication-issues-and-teleport-is.patch} (100%) rename patches/server/{0417-Implement-Brigadier-Mojang-API.patch => 0418-Implement-Brigadier-Mojang-API.patch} (100%) rename patches/server/{0418-Villager-Restocks-API.patch => 0419-Villager-Restocks-API.patch} (97%) rename patches/server/{0419-Validate-PickItem-Packet-and-kick-for-invalid.patch => 0420-Validate-PickItem-Packet-and-kick-for-invalid.patch} (100%) rename patches/server/{0420-Expose-game-version.patch => 0421-Expose-game-version.patch} (100%) rename patches/server/{0421-Optimize-Voxel-Shape-Merging.patch => 0422-Optimize-Voxel-Shape-Merging.patch} (100%) rename patches/server/{0422-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch => 0423-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch} (100%) rename patches/server/{0423-Implement-Mob-Goal-API.patch => 0424-Implement-Mob-Goal-API.patch} (100%) rename patches/server/{0424-Use-distance-map-to-optimise-entity-tracker.patch => 0425-Use-distance-map-to-optimise-entity-tracker.patch} (100%) rename patches/server/{0425-Optimize-isOutsideRange-to-use-distance-maps.patch => 0426-Optimize-isOutsideRange-to-use-distance-maps.patch} (100%) rename patches/server/{0426-Add-villager-reputation-API.patch => 0427-Add-villager-reputation-API.patch} (98%) rename patches/server/{0426-Option-for-maximum-exp-value-when-merging-orbs.patch => 0428-Option-for-maximum-exp-value-when-merging-orbs.patch} (100%) rename patches/server/{0427-ExperienceOrbMergeEvent.patch => 0429-ExperienceOrbMergeEvent.patch} (100%) rename patches/server/{0427-Fix-PotionEffect-ignores-icon-flag.patch => 0430-Fix-PotionEffect-ignores-icon-flag.patch} (100%) rename patches/server/{0428-Optimize-brigadier-child-sorting-performance.patch => 0431-Optimize-brigadier-child-sorting-performance.patch} (100%) rename patches/server/{0429-Potential-bed-API.patch => 0432-Potential-bed-API.patch} (100%) rename patches/server/{0430-Wait-for-Async-Tasks-during-shutdown.patch => 0433-Wait-for-Async-Tasks-during-shutdown.patch} (100%) rename patches/server/{0431-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch => 0434-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch} (100%) rename patches/server/{0432-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch => 0435-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch} (100%) rename patches/server/{0433-Reduce-MutableInt-allocations-from-light-engine.patch => 0436-Reduce-MutableInt-allocations-from-light-engine.patch} (100%) rename patches/server/{0434-Reduce-allocation-of-Vec3D-by-entity-tracker.patch => 0437-Reduce-allocation-of-Vec3D-by-entity-tracker.patch} (100%) rename patches/server/{0435-Ensure-safe-gateway-teleport.patch => 0438-Ensure-safe-gateway-teleport.patch} (100%) rename patches/server/{0436-Add-option-for-console-having-all-permissions.patch => 0439-Add-option-for-console-having-all-permissions.patch} (100%) rename patches/server/{0437-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch => 0440-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch} (100%) diff --git a/patches/server/0330-PreCreatureSpawnEvent.patch b/patches/server/0173-PreCreatureSpawnEvent.patch similarity index 97% rename from patches/server/0330-PreCreatureSpawnEvent.patch rename to patches/server/0173-PreCreatureSpawnEvent.patch index f15e5b7e00..d68ee45bdb 100644 --- a/patches/server/0330-PreCreatureSpawnEvent.patch +++ b/patches/server/0173-PreCreatureSpawnEvent.patch @@ -66,7 +66,7 @@ index 6a9e2105b2d9a4ee83c0a2516d5ef26dc3b99053..aec77679584a2acab5818e26e2586b53 if (entityirongolem != null) { diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index c6298b12e4e0c20be20e7e493be728f028f9eb31..68ce2732dfdc25ddadc15c43c30a609f9b1eba86 100644 +index 12a78685848b7fd945a472902d8200ea1d50b9ec..cfb820636f819a7da56d0302d49f39cea1b5a93d 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java @@ -132,6 +132,27 @@ public abstract class BaseSpawner { @@ -97,13 +97,13 @@ index c6298b12e4e0c20be20e7e493be728f028f9eb31..68ce2732dfdc25ddadc15c43c30a609f Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> { entity1.moveTo(d0, d1, d2, entity1.getYRot(), entity1.getXRot()); return entity1; -@@ -349,3 +370,4 @@ public abstract class BaseSpawner { +@@ -326,3 +347,4 @@ public abstract class BaseSpawner { return this.oSpin; } } + diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 30ba1e3cb75d994770b006b9dfd6669000a9c1a4..6204bf41d410df9784b32f993b46d7adb2af5f13 100644 +index 59fae60116167baf989e85596334824e9004e6fb..be667bb12e1ee186b8d9ad1d7ac4534454d0e787 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java @@ -231,7 +231,13 @@ public final class NaturalSpawner { diff --git a/patches/server/0173-Add-setPlayerProfile-API-for-Skulls.patch b/patches/server/0174-Add-setPlayerProfile-API-for-Skulls.patch similarity index 100% rename from patches/server/0173-Add-setPlayerProfile-API-for-Skulls.patch rename to patches/server/0174-Add-setPlayerProfile-API-for-Skulls.patch diff --git a/patches/server/0174-Fill-Profile-Property-Events.patch b/patches/server/0175-Fill-Profile-Property-Events.patch similarity index 100% rename from patches/server/0174-Fill-Profile-Property-Events.patch rename to patches/server/0175-Fill-Profile-Property-Events.patch diff --git a/patches/server/0175-PlayerAdvancementCriterionGrantEvent.patch b/patches/server/0176-PlayerAdvancementCriterionGrantEvent.patch similarity index 100% rename from patches/server/0175-PlayerAdvancementCriterionGrantEvent.patch rename to patches/server/0176-PlayerAdvancementCriterionGrantEvent.patch diff --git a/patches/server/0176-Add-ArmorStand-Item-Meta.patch b/patches/server/0177-Add-ArmorStand-Item-Meta.patch similarity index 100% rename from patches/server/0176-Add-ArmorStand-Item-Meta.patch rename to patches/server/0177-Add-ArmorStand-Item-Meta.patch diff --git a/patches/server/0177-Extend-Player-Interact-cancellation.patch b/patches/server/0178-Extend-Player-Interact-cancellation.patch similarity index 100% rename from patches/server/0177-Extend-Player-Interact-cancellation.patch rename to patches/server/0178-Extend-Player-Interact-cancellation.patch diff --git a/patches/server/0178-Tameable-getOwnerUniqueId-API.patch b/patches/server/0179-Tameable-getOwnerUniqueId-API.patch similarity index 100% rename from patches/server/0178-Tameable-getOwnerUniqueId-API.patch rename to patches/server/0179-Tameable-getOwnerUniqueId-API.patch diff --git a/patches/server/0179-Toggleable-player-crits-helps-mitigate-hacked-client.patch b/patches/server/0180-Toggleable-player-crits-helps-mitigate-hacked-client.patch similarity index 100% rename from patches/server/0179-Toggleable-player-crits-helps-mitigate-hacked-client.patch rename to patches/server/0180-Toggleable-player-crits-helps-mitigate-hacked-client.patch diff --git a/patches/server/0180-Disable-Explicit-Network-Manager-Flushing.patch b/patches/server/0181-Disable-Explicit-Network-Manager-Flushing.patch similarity index 100% rename from patches/server/0180-Disable-Explicit-Network-Manager-Flushing.patch rename to patches/server/0181-Disable-Explicit-Network-Manager-Flushing.patch diff --git a/patches/server/0181-Implement-extended-PaperServerListPingEvent.patch b/patches/server/0182-Implement-extended-PaperServerListPingEvent.patch similarity index 100% rename from patches/server/0181-Implement-extended-PaperServerListPingEvent.patch rename to patches/server/0182-Implement-extended-PaperServerListPingEvent.patch diff --git a/patches/server/0182-Improved-Async-Task-Scheduler.patch b/patches/server/0183-Improved-Async-Task-Scheduler.patch similarity index 100% rename from patches/server/0182-Improved-Async-Task-Scheduler.patch rename to patches/server/0183-Improved-Async-Task-Scheduler.patch diff --git a/patches/server/0183-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/patches/server/0184-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch similarity index 100% rename from patches/server/0183-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch rename to patches/server/0184-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch diff --git a/patches/server/0184-Player.setPlayerProfile-API.patch b/patches/server/0185-Player.setPlayerProfile-API.patch similarity index 100% rename from patches/server/0184-Player.setPlayerProfile-API.patch rename to patches/server/0185-Player.setPlayerProfile-API.patch diff --git a/patches/server/0185-getPlayerUniqueId-API.patch b/patches/server/0186-getPlayerUniqueId-API.patch similarity index 100% rename from patches/server/0185-getPlayerUniqueId-API.patch rename to patches/server/0186-getPlayerUniqueId-API.patch diff --git a/patches/server/0186-Make-player-data-saving-configurable.patch b/patches/server/0187-Make-player-data-saving-configurable.patch similarity index 100% rename from patches/server/0186-Make-player-data-saving-configurable.patch rename to patches/server/0187-Make-player-data-saving-configurable.patch diff --git a/patches/server/0187-Make-legacy-ping-handler-more-reliable.patch b/patches/server/0188-Make-legacy-ping-handler-more-reliable.patch similarity index 100% rename from patches/server/0187-Make-legacy-ping-handler-more-reliable.patch rename to patches/server/0188-Make-legacy-ping-handler-more-reliable.patch diff --git a/patches/server/0188-Call-PaperServerListPingEvent-for-legacy-pings.patch b/patches/server/0189-Call-PaperServerListPingEvent-for-legacy-pings.patch similarity index 100% rename from patches/server/0188-Call-PaperServerListPingEvent-for-legacy-pings.patch rename to patches/server/0189-Call-PaperServerListPingEvent-for-legacy-pings.patch diff --git a/patches/server/0189-Flag-to-disable-the-channel-limit.patch b/patches/server/0190-Flag-to-disable-the-channel-limit.patch similarity index 100% rename from patches/server/0189-Flag-to-disable-the-channel-limit.patch rename to patches/server/0190-Flag-to-disable-the-channel-limit.patch diff --git a/patches/server/0190-Add-method-to-open-already-placed-sign.patch b/patches/server/0191-Add-method-to-open-already-placed-sign.patch similarity index 100% rename from patches/server/0190-Add-method-to-open-already-placed-sign.patch rename to patches/server/0191-Add-method-to-open-already-placed-sign.patch diff --git a/patches/server/0191-Configurable-sprint-interruption-on-attack.patch b/patches/server/0192-Configurable-sprint-interruption-on-attack.patch similarity index 100% rename from patches/server/0191-Configurable-sprint-interruption-on-attack.patch rename to patches/server/0192-Configurable-sprint-interruption-on-attack.patch diff --git a/patches/server/0192-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/patches/server/0193-Fix-exploit-that-allowed-colored-signs-to-be-created.patch similarity index 93% rename from patches/server/0192-Fix-exploit-that-allowed-colored-signs-to-be-created.patch rename to patches/server/0193-Fix-exploit-that-allowed-colored-signs-to-be-created.patch index a1458e6d99..b08e171906 100644 --- a/patches/server/0192-Fix-exploit-that-allowed-colored-signs-to-be-created.patch +++ b/patches/server/0193-Fix-exploit-that-allowed-colored-signs-to-be-created.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix exploit that allowed colored signs to be created diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 205e4ef25f49edc11a408c302d9ba68a59c68a5a..35a00a622ff0c3582e08dbbefb1d34a84e590a81 100644 +index 5b426265d62063544f0104c8c9f8061d002bc56c..d5c3c97e5205ef94578bc2d9d39f1a4c2600db94 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -2787,9 +2787,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0193-EndermanEscapeEvent.patch b/patches/server/0194-EndermanEscapeEvent.patch similarity index 100% rename from patches/server/0193-EndermanEscapeEvent.patch rename to patches/server/0194-EndermanEscapeEvent.patch diff --git a/patches/server/0194-Enderman.teleportRandomly.patch b/patches/server/0195-Enderman.teleportRandomly.patch similarity index 100% rename from patches/server/0194-Enderman.teleportRandomly.patch rename to patches/server/0195-Enderman.teleportRandomly.patch diff --git a/patches/server/0195-Block-Enderpearl-Travel-Exploit.patch b/patches/server/0196-Block-Enderpearl-Travel-Exploit.patch similarity index 100% rename from patches/server/0195-Block-Enderpearl-Travel-Exploit.patch rename to patches/server/0196-Block-Enderpearl-Travel-Exploit.patch diff --git a/patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/server/0197-Expand-World.spawnParticle-API-and-add-Builder.patch similarity index 100% rename from patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch rename to patches/server/0197-Expand-World.spawnParticle-API-and-add-Builder.patch diff --git a/patches/server/0197-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/patches/server/0198-Prevent-Frosted-Ice-from-loading-holding-chunks.patch similarity index 100% rename from patches/server/0197-Prevent-Frosted-Ice-from-loading-holding-chunks.patch rename to patches/server/0198-Prevent-Frosted-Ice-from-loading-holding-chunks.patch diff --git a/patches/server/0198-EndermanAttackPlayerEvent.patch b/patches/server/0199-EndermanAttackPlayerEvent.patch similarity index 100% rename from patches/server/0198-EndermanAttackPlayerEvent.patch rename to patches/server/0199-EndermanAttackPlayerEvent.patch diff --git a/patches/server/0199-WitchConsumePotionEvent.patch b/patches/server/0200-WitchConsumePotionEvent.patch similarity index 100% rename from patches/server/0199-WitchConsumePotionEvent.patch rename to patches/server/0200-WitchConsumePotionEvent.patch diff --git a/patches/server/0200-WitchThrowPotionEvent.patch b/patches/server/0201-WitchThrowPotionEvent.patch similarity index 100% rename from patches/server/0200-WitchThrowPotionEvent.patch rename to patches/server/0201-WitchThrowPotionEvent.patch diff --git a/patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/patches/server/0202-Allow-spawning-Item-entities-with-World.spawnEntity.patch similarity index 100% rename from patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch rename to patches/server/0202-Allow-spawning-Item-entities-with-World.spawnEntity.patch diff --git a/patches/server/0202-WitchReadyPotionEvent.patch b/patches/server/0203-WitchReadyPotionEvent.patch similarity index 100% rename from patches/server/0202-WitchReadyPotionEvent.patch rename to patches/server/0203-WitchReadyPotionEvent.patch diff --git a/patches/server/0203-ItemStack-getMaxItemUseDuration.patch b/patches/server/0204-ItemStack-getMaxItemUseDuration.patch similarity index 100% rename from patches/server/0203-ItemStack-getMaxItemUseDuration.patch rename to patches/server/0204-ItemStack-getMaxItemUseDuration.patch diff --git a/patches/server/0204-Implement-EntityTeleportEndGatewayEvent.patch b/patches/server/0205-Implement-EntityTeleportEndGatewayEvent.patch similarity index 95% rename from patches/server/0204-Implement-EntityTeleportEndGatewayEvent.patch rename to patches/server/0205-Implement-EntityTeleportEndGatewayEvent.patch index 3c1584cc23..0fdb872e98 100644 --- a/patches/server/0204-Implement-EntityTeleportEndGatewayEvent.patch +++ b/patches/server/0205-Implement-EntityTeleportEndGatewayEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Implement EntityTeleportEndGatewayEvent diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -index 2bf65c8da827c6bdbfb74a9d8ee5754584c40c53..f9cd4c28db815205e548ac59515cd80989741bab 100644 +index 07c786b3988a2cc3a7bd3910dd909b887395a194..370ec4cd08a50ad0b8154db9afcaa76ec741dcb2 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java @@ -225,9 +225,20 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { diff --git a/patches/server/0205-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/patches/server/0206-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch similarity index 100% rename from patches/server/0205-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch rename to patches/server/0206-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch diff --git a/patches/server/0206-Fix-CraftEntity-hashCode.patch b/patches/server/0207-Fix-CraftEntity-hashCode.patch similarity index 100% rename from patches/server/0206-Fix-CraftEntity-hashCode.patch rename to patches/server/0207-Fix-CraftEntity-hashCode.patch diff --git a/patches/server/0207-Configurable-Alternative-LootPool-Luck-Formula.patch b/patches/server/0208-Configurable-Alternative-LootPool-Luck-Formula.patch similarity index 100% rename from patches/server/0207-Configurable-Alternative-LootPool-Luck-Formula.patch rename to patches/server/0208-Configurable-Alternative-LootPool-Luck-Formula.patch diff --git a/patches/server/0208-Print-Error-details-when-failing-to-save-player-data.patch b/patches/server/0209-Print-Error-details-when-failing-to-save-player-data.patch similarity index 100% rename from patches/server/0208-Print-Error-details-when-failing-to-save-player-data.patch rename to patches/server/0209-Print-Error-details-when-failing-to-save-player-data.patch diff --git a/patches/server/0209-Make-shield-blocking-delay-configurable.patch b/patches/server/0210-Make-shield-blocking-delay-configurable.patch similarity index 100% rename from patches/server/0209-Make-shield-blocking-delay-configurable.patch rename to patches/server/0210-Make-shield-blocking-delay-configurable.patch diff --git a/patches/server/0210-Improve-EntityShootBowEvent.patch b/patches/server/0211-Improve-EntityShootBowEvent.patch similarity index 100% rename from patches/server/0210-Improve-EntityShootBowEvent.patch rename to patches/server/0211-Improve-EntityShootBowEvent.patch diff --git a/patches/server/0211-PlayerReadyArrowEvent.patch b/patches/server/0212-PlayerReadyArrowEvent.patch similarity index 100% rename from patches/server/0211-PlayerReadyArrowEvent.patch rename to patches/server/0212-PlayerReadyArrowEvent.patch diff --git a/patches/server/0212-Implement-EntityKnockbackByEntityEvent.patch b/patches/server/0213-Implement-EntityKnockbackByEntityEvent.patch similarity index 100% rename from patches/server/0212-Implement-EntityKnockbackByEntityEvent.patch rename to patches/server/0213-Implement-EntityKnockbackByEntityEvent.patch diff --git a/patches/server/0213-Expand-Explosions-API.patch b/patches/server/0214-Expand-Explosions-API.patch similarity index 100% rename from patches/server/0213-Expand-Explosions-API.patch rename to patches/server/0214-Expand-Explosions-API.patch diff --git a/patches/server/0214-LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/server/0215-LivingEntity-Hand-Raised-Item-Use-API.patch similarity index 100% rename from patches/server/0214-LivingEntity-Hand-Raised-Item-Use-API.patch rename to patches/server/0215-LivingEntity-Hand-Raised-Item-Use-API.patch diff --git a/patches/server/0215-RangedEntity-API.patch b/patches/server/0216-RangedEntity-API.patch similarity index 100% rename from patches/server/0215-RangedEntity-API.patch rename to patches/server/0216-RangedEntity-API.patch diff --git a/patches/server/0216-Add-config-to-disable-ender-dragon-legacy-check.patch b/patches/server/0217-Add-config-to-disable-ender-dragon-legacy-check.patch similarity index 100% rename from patches/server/0216-Add-config-to-disable-ender-dragon-legacy-check.patch rename to patches/server/0217-Add-config-to-disable-ender-dragon-legacy-check.patch diff --git a/patches/server/0217-Implement-World.getEntity-UUID-API.patch b/patches/server/0218-Implement-World.getEntity-UUID-API.patch similarity index 100% rename from patches/server/0217-Implement-World.getEntity-UUID-API.patch rename to patches/server/0218-Implement-World.getEntity-UUID-API.patch diff --git a/patches/server/0218-InventoryCloseEvent-Reason-API.patch b/patches/server/0219-InventoryCloseEvent-Reason-API.patch similarity index 100% rename from patches/server/0218-InventoryCloseEvent-Reason-API.patch rename to patches/server/0219-InventoryCloseEvent-Reason-API.patch diff --git a/patches/server/0219-Vex-get-setSummoner-API.patch b/patches/server/0220-Vex-get-setSummoner-API.patch similarity index 100% rename from patches/server/0219-Vex-get-setSummoner-API.patch rename to patches/server/0220-Vex-get-setSummoner-API.patch diff --git a/patches/server/0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/patches/server/0221-Refresh-player-inventory-when-cancelling-PlayerInter.patch similarity index 100% rename from patches/server/0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch rename to patches/server/0221-Refresh-player-inventory-when-cancelling-PlayerInter.patch diff --git a/patches/server/0221-Avoid-item-merge-if-stack-size-above-max-stack-size.patch b/patches/server/0222-Avoid-item-merge-if-stack-size-above-max-stack-size.patch similarity index 100% rename from patches/server/0221-Avoid-item-merge-if-stack-size-above-max-stack-size.patch rename to patches/server/0222-Avoid-item-merge-if-stack-size-above-max-stack-size.patch diff --git a/patches/server/0222-Use-asynchronous-Log4j-2-loggers.patch b/patches/server/0223-Use-asynchronous-Log4j-2-loggers.patch similarity index 96% rename from patches/server/0222-Use-asynchronous-Log4j-2-loggers.patch rename to patches/server/0223-Use-asynchronous-Log4j-2-loggers.patch index 8c37425010..15fd44e4bd 100644 --- a/patches/server/0222-Use-asynchronous-Log4j-2-loggers.patch +++ b/patches/server/0223-Use-asynchronous-Log4j-2-loggers.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Use asynchronous Log4j 2 loggers diff --git a/build.gradle.kts b/build.gradle.kts -index ac607a3be84bc02dedb95cab9a5eace40e33b511..b967ab10155bbf26e864bedadb8ae2ab5fdd38c1 100644 +index daf0455eeb2ef3d2bf88b1177315133b571569bb..f0256fe4aea16c9e0d6f5eee360eeec36cfdeebd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -42,6 +42,7 @@ dependencies { diff --git a/patches/server/0223-add-more-information-to-Entity.toString.patch b/patches/server/0224-add-more-information-to-Entity.toString.patch similarity index 100% rename from patches/server/0223-add-more-information-to-Entity.toString.patch rename to patches/server/0224-add-more-information-to-Entity.toString.patch diff --git a/patches/server/0224-Add-CraftMagicNumbers.isSupportedApiVersion.patch b/patches/server/0225-Add-CraftMagicNumbers.isSupportedApiVersion.patch similarity index 100% rename from patches/server/0224-Add-CraftMagicNumbers.isSupportedApiVersion.patch rename to patches/server/0225-Add-CraftMagicNumbers.isSupportedApiVersion.patch diff --git a/patches/server/0225-EnderDragon-Events.patch b/patches/server/0226-EnderDragon-Events.patch similarity index 100% rename from patches/server/0225-EnderDragon-Events.patch rename to patches/server/0226-EnderDragon-Events.patch diff --git a/patches/server/0226-PlayerElytraBoostEvent.patch b/patches/server/0227-PlayerElytraBoostEvent.patch similarity index 100% rename from patches/server/0226-PlayerElytraBoostEvent.patch rename to patches/server/0227-PlayerElytraBoostEvent.patch diff --git a/patches/server/0227-PlayerLaunchProjectileEvent.patch b/patches/server/0228-PlayerLaunchProjectileEvent.patch similarity index 100% rename from patches/server/0227-PlayerLaunchProjectileEvent.patch rename to patches/server/0228-PlayerLaunchProjectileEvent.patch diff --git a/patches/server/0228-Improve-BlockPosition-inlining.patch b/patches/server/0229-Improve-BlockPosition-inlining.patch similarity index 100% rename from patches/server/0228-Improve-BlockPosition-inlining.patch rename to patches/server/0229-Improve-BlockPosition-inlining.patch diff --git a/patches/server/0229-Optimize-IntIdentityHashBiMiap-nextId.patch b/patches/server/0230-Optimize-IntIdentityHashBiMiap-nextId.patch similarity index 100% rename from patches/server/0229-Optimize-IntIdentityHashBiMiap-nextId.patch rename to patches/server/0230-Optimize-IntIdentityHashBiMiap-nextId.patch diff --git a/patches/server/0230-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/patches/server/0231-Option-to-prevent-armor-stands-from-doing-entity-loo.patch similarity index 100% rename from patches/server/0230-Option-to-prevent-armor-stands-from-doing-entity-loo.patch rename to patches/server/0231-Option-to-prevent-armor-stands-from-doing-entity-loo.patch diff --git a/patches/server/0231-Vanished-players-don-t-have-rights.patch b/patches/server/0232-Vanished-players-don-t-have-rights.patch similarity index 100% rename from patches/server/0231-Vanished-players-don-t-have-rights.patch rename to patches/server/0232-Vanished-players-don-t-have-rights.patch diff --git a/patches/server/0232-Allow-disabling-armour-stand-ticking.patch b/patches/server/0233-Allow-disabling-armour-stand-ticking.patch similarity index 100% rename from patches/server/0232-Allow-disabling-armour-stand-ticking.patch rename to patches/server/0233-Allow-disabling-armour-stand-ticking.patch diff --git a/patches/server/0233-SkeletonHorse-Additions.patch b/patches/server/0234-SkeletonHorse-Additions.patch similarity index 100% rename from patches/server/0233-SkeletonHorse-Additions.patch rename to patches/server/0234-SkeletonHorse-Additions.patch diff --git a/patches/server/0234-Don-t-call-getItemMeta-on-hasItemMeta.patch b/patches/server/0235-Don-t-call-getItemMeta-on-hasItemMeta.patch similarity index 100% rename from patches/server/0234-Don-t-call-getItemMeta-on-hasItemMeta.patch rename to patches/server/0235-Don-t-call-getItemMeta-on-hasItemMeta.patch diff --git a/patches/server/0235-Implement-Expanded-ArmorStand-API.patch b/patches/server/0236-Implement-Expanded-ArmorStand-API.patch similarity index 100% rename from patches/server/0235-Implement-Expanded-ArmorStand-API.patch rename to patches/server/0236-Implement-Expanded-ArmorStand-API.patch diff --git a/patches/server/0236-AnvilDamageEvent.patch b/patches/server/0237-AnvilDamageEvent.patch similarity index 100% rename from patches/server/0236-AnvilDamageEvent.patch rename to patches/server/0237-AnvilDamageEvent.patch diff --git a/patches/server/0237-Add-hand-to-bucket-events.patch b/patches/server/0238-Add-hand-to-bucket-events.patch similarity index 97% rename from patches/server/0237-Add-hand-to-bucket-events.patch rename to patches/server/0238-Add-hand-to-bucket-events.patch index 6bd9341130..b18f266565 100644 --- a/patches/server/0237-Add-hand-to-bucket-events.patch +++ b/patches/server/0238-Add-hand-to-bucket-events.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add hand to bucket events diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 5751a9318867df781568dd92ad4f51d1f40bc23c..dae19715582d75d24744d44a87f94dd86f90c1c7 100644 +index 5a5733124bd8395bb996e9d5426c4a260fbeb1d3..8989b3153b0c849e189a8ff4ac4de6085e3a3db2 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1419,15 +1419,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl @@ -139,16 +139,16 @@ index c1cf7f5bff2878281d4a9787ea7160e984268352..8d4f8719b30a66fbb68c9407ee848431 public boolean isClientSide() { return this.isClientSide; diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 59fae60116167baf989e85596334824e9004e6fb..9c079d32e81cabfa7b8b28e3e8d5741d8d951d79 100644 +index be667bb12e1ee186b8d9ad1d7ac4534454d0e787..cf6bcbe7d75a52fe509e3b6c6c24b64bf9d460ad 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -558,3 +558,4 @@ public final class NaturalSpawner { +@@ -580,3 +580,4 @@ public final class NaturalSpawner { void run(Mob entity, ChunkAccess chunk); } } + diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 966d06e2da7e6f9b4e78ca8ed02f3a6472bc8c05..a81fc5212648056766824113b372a7c772c19e5a 100644 +index c09c2c8ec2a4dd2e1eec5ecf97cbd8456b5ec3c9..bb006e6c703e5c4cfa16ca4ee4cf8463215c38b0 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -222,7 +222,7 @@ public class CraftEventFactory { diff --git a/patches/server/0238-Add-TNTPrimeEvent.patch b/patches/server/0239-Add-TNTPrimeEvent.patch similarity index 100% rename from patches/server/0238-Add-TNTPrimeEvent.patch rename to patches/server/0239-Add-TNTPrimeEvent.patch diff --git a/patches/server/0239-Break-up-and-make-tab-spam-limits-configurable.patch b/patches/server/0240-Break-up-and-make-tab-spam-limits-configurable.patch similarity index 98% rename from patches/server/0239-Break-up-and-make-tab-spam-limits-configurable.patch rename to patches/server/0240-Break-up-and-make-tab-spam-limits-configurable.patch index c88867bf3a..eb1d793af7 100644 --- a/patches/server/0239-Break-up-and-make-tab-spam-limits-configurable.patch +++ b/patches/server/0240-Break-up-and-make-tab-spam-limits-configurable.patch @@ -45,7 +45,7 @@ index 77a03abd59db4a43f6f2d59d4c7ef176e782f205..bd508025b771424c942fd856c31d520b + } } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 902eab82912b9a7002485f73df7ae25e370b7e25..6ea367295d07c444d7cce0366261a884d299185a 100644 +index 28f4c456936c378628336d4a36f1975476f7913f..b65fcc7519589c3bc5c5f5b5ec1db53a520ec39f 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -228,6 +228,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0240-MC-135506-Experience-should-save-as-Integers.patch b/patches/server/0241-MC-135506-Experience-should-save-as-Integers.patch similarity index 100% rename from patches/server/0240-MC-135506-Experience-should-save-as-Integers.patch rename to patches/server/0241-MC-135506-Experience-should-save-as-Integers.patch diff --git a/patches/server/0241-Fix-client-rendering-skulls-from-same-user.patch b/patches/server/0242-Fix-client-rendering-skulls-from-same-user.patch similarity index 100% rename from patches/server/0241-Fix-client-rendering-skulls-from-same-user.patch rename to patches/server/0242-Fix-client-rendering-skulls-from-same-user.patch diff --git a/patches/server/0242-Add-Early-Warning-Feature-to-WatchDog.patch b/patches/server/0243-Add-Early-Warning-Feature-to-WatchDog.patch similarity index 100% rename from patches/server/0242-Add-Early-Warning-Feature-to-WatchDog.patch rename to patches/server/0243-Add-Early-Warning-Feature-to-WatchDog.patch diff --git a/patches/server/0243-Make-EnderDragon-implement-Mob.patch b/patches/server/0244-Make-EnderDragon-implement-Mob.patch similarity index 100% rename from patches/server/0243-Make-EnderDragon-implement-Mob.patch rename to patches/server/0244-Make-EnderDragon-implement-Mob.patch diff --git a/patches/server/0244-Use-ConcurrentHashMap-in-JsonList.patch b/patches/server/0245-Use-ConcurrentHashMap-in-JsonList.patch similarity index 100% rename from patches/server/0244-Use-ConcurrentHashMap-in-JsonList.patch rename to patches/server/0245-Use-ConcurrentHashMap-in-JsonList.patch diff --git a/patches/server/0245-Use-a-Queue-for-Queueing-Commands.patch b/patches/server/0246-Use-a-Queue-for-Queueing-Commands.patch similarity index 100% rename from patches/server/0245-Use-a-Queue-for-Queueing-Commands.patch rename to patches/server/0246-Use-a-Queue-for-Queueing-Commands.patch diff --git a/patches/server/0246-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/patches/server/0247-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch similarity index 100% rename from patches/server/0246-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch rename to patches/server/0247-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch diff --git a/patches/server/0247-Optimize-BlockPosition-helper-methods.patch b/patches/server/0248-Optimize-BlockPosition-helper-methods.patch similarity index 100% rename from patches/server/0247-Optimize-BlockPosition-helper-methods.patch rename to patches/server/0248-Optimize-BlockPosition-helper-methods.patch diff --git a/patches/server/0248-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/patches/server/0249-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch similarity index 100% rename from patches/server/0248-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch rename to patches/server/0249-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch diff --git a/patches/server/0249-Slime-Pathfinder-Events.patch b/patches/server/0250-Slime-Pathfinder-Events.patch similarity index 100% rename from patches/server/0249-Slime-Pathfinder-Events.patch rename to patches/server/0250-Slime-Pathfinder-Events.patch diff --git a/patches/server/0250-Configurable-speed-for-water-flowing-over-lava.patch b/patches/server/0251-Configurable-speed-for-water-flowing-over-lava.patch similarity index 100% rename from patches/server/0250-Configurable-speed-for-water-flowing-over-lava.patch rename to patches/server/0251-Configurable-speed-for-water-flowing-over-lava.patch diff --git a/patches/server/0251-Optimize-CraftBlockData-Creation.patch b/patches/server/0252-Optimize-CraftBlockData-Creation.patch similarity index 100% rename from patches/server/0251-Optimize-CraftBlockData-Creation.patch rename to patches/server/0252-Optimize-CraftBlockData-Creation.patch diff --git a/patches/server/0252-Optimize-MappedRegistry.patch b/patches/server/0253-Optimize-MappedRegistry.patch similarity index 100% rename from patches/server/0252-Optimize-MappedRegistry.patch rename to patches/server/0253-Optimize-MappedRegistry.patch diff --git a/patches/server/0253-Add-PhantomPreSpawnEvent.patch b/patches/server/0254-Add-PhantomPreSpawnEvent.patch similarity index 100% rename from patches/server/0253-Add-PhantomPreSpawnEvent.patch rename to patches/server/0254-Add-PhantomPreSpawnEvent.patch diff --git a/patches/server/0254-Add-More-Creeper-API.patch b/patches/server/0255-Add-More-Creeper-API.patch similarity index 100% rename from patches/server/0254-Add-More-Creeper-API.patch rename to patches/server/0255-Add-More-Creeper-API.patch diff --git a/patches/server/0255-Inventory-removeItemAnySlot.patch b/patches/server/0256-Inventory-removeItemAnySlot.patch similarity index 100% rename from patches/server/0255-Inventory-removeItemAnySlot.patch rename to patches/server/0256-Inventory-removeItemAnySlot.patch diff --git a/patches/server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/patches/server/0257-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch similarity index 100% rename from patches/server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch rename to patches/server/0257-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch diff --git a/patches/server/0257-Asynchronous-chunk-IO-and-loading.patch b/patches/server/0258-Asynchronous-chunk-IO-and-loading.patch similarity index 100% rename from patches/server/0257-Asynchronous-chunk-IO-and-loading.patch rename to patches/server/0258-Asynchronous-chunk-IO-and-loading.patch diff --git a/patches/server/0258-Add-ray-tracing-methods-to-LivingEntity.patch b/patches/server/0259-Add-ray-tracing-methods-to-LivingEntity.patch similarity index 100% rename from patches/server/0258-Add-ray-tracing-methods-to-LivingEntity.patch rename to patches/server/0259-Add-ray-tracing-methods-to-LivingEntity.patch diff --git a/patches/server/0259-Expose-attack-cooldown-methods-for-Player.patch b/patches/server/0260-Expose-attack-cooldown-methods-for-Player.patch similarity index 100% rename from patches/server/0259-Expose-attack-cooldown-methods-for-Player.patch rename to patches/server/0260-Expose-attack-cooldown-methods-for-Player.patch diff --git a/patches/server/0260-Improve-death-events.patch b/patches/server/0261-Improve-death-events.patch similarity index 100% rename from patches/server/0260-Improve-death-events.patch rename to patches/server/0261-Improve-death-events.patch diff --git a/patches/server/0261-Allow-chests-to-be-placed-with-NBT-data.patch b/patches/server/0262-Allow-chests-to-be-placed-with-NBT-data.patch similarity index 100% rename from patches/server/0261-Allow-chests-to-be-placed-with-NBT-data.patch rename to patches/server/0262-Allow-chests-to-be-placed-with-NBT-data.patch diff --git a/patches/server/0262-Mob-Pathfinding-API.patch b/patches/server/0263-Mob-Pathfinding-API.patch similarity index 100% rename from patches/server/0262-Mob-Pathfinding-API.patch rename to patches/server/0263-Mob-Pathfinding-API.patch diff --git a/patches/server/0263-Prevent-chunk-loading-from-Fluid-Flowing.patch b/patches/server/0264-Prevent-chunk-loading-from-Fluid-Flowing.patch similarity index 100% rename from patches/server/0263-Prevent-chunk-loading-from-Fluid-Flowing.patch rename to patches/server/0264-Prevent-chunk-loading-from-Fluid-Flowing.patch diff --git a/patches/server/0264-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/patches/server/0265-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch similarity index 100% rename from patches/server/0264-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch rename to patches/server/0265-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch diff --git a/patches/server/0265-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/patches/server/0266-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch similarity index 100% rename from patches/server/0265-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch rename to patches/server/0266-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch diff --git a/patches/server/0266-Prevent-mob-spawning-from-loading-generating-chunks.patch b/patches/server/0267-Prevent-mob-spawning-from-loading-generating-chunks.patch similarity index 95% rename from patches/server/0266-Prevent-mob-spawning-from-loading-generating-chunks.patch rename to patches/server/0267-Prevent-mob-spawning-from-loading-generating-chunks.patch index 169635a71f..b1f9c57bd9 100644 --- a/patches/server/0266-Prevent-mob-spawning-from-loading-generating-chunks.patch +++ b/patches/server/0267-Prevent-mob-spawning-from-loading-generating-chunks.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Prevent mob spawning from loading/generating chunks also prevents if out of world border bounds diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 9c079d32e81cabfa7b8b28e3e8d5741d8d951d79..30ba1e3cb75d994770b006b9dfd6669000a9c1a4 100644 +index cf6bcbe7d75a52fe509e3b6c6c24b64bf9d460ad..6204bf41d410df9784b32f993b46d7adb2af5f13 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java @@ -188,9 +188,9 @@ public final class NaturalSpawner { diff --git a/patches/server/0267-Implement-furnace-cook-speed-multiplier-API.patch b/patches/server/0268-Implement-furnace-cook-speed-multiplier-API.patch similarity index 100% rename from patches/server/0267-Implement-furnace-cook-speed-multiplier-API.patch rename to patches/server/0268-Implement-furnace-cook-speed-multiplier-API.patch diff --git a/patches/server/0268-Catch-JsonParseException-in-Entity-and-TE-names.patch b/patches/server/0269-Catch-JsonParseException-in-Entity-and-TE-names.patch similarity index 100% rename from patches/server/0268-Catch-JsonParseException-in-Entity-and-TE-names.patch rename to patches/server/0269-Catch-JsonParseException-in-Entity-and-TE-names.patch diff --git a/patches/server/0269-Honor-EntityAgeable.ageLock.patch b/patches/server/0270-Honor-EntityAgeable.ageLock.patch similarity index 100% rename from patches/server/0269-Honor-EntityAgeable.ageLock.patch rename to patches/server/0270-Honor-EntityAgeable.ageLock.patch diff --git a/patches/server/0270-Configurable-connection-throttle-kick-message.patch b/patches/server/0271-Configurable-connection-throttle-kick-message.patch similarity index 100% rename from patches/server/0270-Configurable-connection-throttle-kick-message.patch rename to patches/server/0271-Configurable-connection-throttle-kick-message.patch diff --git a/patches/server/0271-Hook-into-CB-plugin-rewrites.patch b/patches/server/0272-Hook-into-CB-plugin-rewrites.patch similarity index 100% rename from patches/server/0271-Hook-into-CB-plugin-rewrites.patch rename to patches/server/0272-Hook-into-CB-plugin-rewrites.patch diff --git a/patches/server/0272-Add-sun-related-API.patch b/patches/server/0273-Add-sun-related-API.patch similarity index 100% rename from patches/server/0272-Add-sun-related-API.patch rename to patches/server/0273-Add-sun-related-API.patch diff --git a/patches/server/0273-Add-LivingEntity-getTargetEntity.patch b/patches/server/0274-Add-LivingEntity-getTargetEntity.patch similarity index 100% rename from patches/server/0273-Add-LivingEntity-getTargetEntity.patch rename to patches/server/0274-Add-LivingEntity-getTargetEntity.patch diff --git a/patches/server/0274-Turtle-API.patch b/patches/server/0275-Turtle-API.patch similarity index 100% rename from patches/server/0274-Turtle-API.patch rename to patches/server/0275-Turtle-API.patch diff --git a/patches/server/0275-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/patches/server/0276-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch similarity index 100% rename from patches/server/0275-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch rename to patches/server/0276-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch diff --git a/patches/server/0276-Call-player-spectator-target-events-and-improve-impl.patch b/patches/server/0277-Call-player-spectator-target-events-and-improve-impl.patch similarity index 100% rename from patches/server/0276-Call-player-spectator-target-events-and-improve-impl.patch rename to patches/server/0277-Call-player-spectator-target-events-and-improve-impl.patch diff --git a/patches/server/0277-Add-Velocity-IP-Forwarding-Support.patch b/patches/server/0278-Add-Velocity-IP-Forwarding-Support.patch similarity index 100% rename from patches/server/0277-Add-Velocity-IP-Forwarding-Support.patch rename to patches/server/0278-Add-Velocity-IP-Forwarding-Support.patch diff --git a/patches/server/0278-Add-more-Witch-API.patch b/patches/server/0279-Add-more-Witch-API.patch similarity index 100% rename from patches/server/0278-Add-more-Witch-API.patch rename to patches/server/0279-Add-more-Witch-API.patch diff --git a/patches/server/0279-Check-Drowned-for-Villager-Aggression-Config.patch b/patches/server/0280-Check-Drowned-for-Villager-Aggression-Config.patch similarity index 100% rename from patches/server/0279-Check-Drowned-for-Villager-Aggression-Config.patch rename to patches/server/0280-Check-Drowned-for-Villager-Aggression-Config.patch diff --git a/patches/server/0280-Here-s-Johnny.patch b/patches/server/0281-Here-s-Johnny.patch similarity index 100% rename from patches/server/0280-Here-s-Johnny.patch rename to patches/server/0281-Here-s-Johnny.patch diff --git a/patches/server/0281-Add-option-to-prevent-players-from-moving-into-unloa.patch b/patches/server/0282-Add-option-to-prevent-players-from-moving-into-unloa.patch similarity index 100% rename from patches/server/0281-Add-option-to-prevent-players-from-moving-into-unloa.patch rename to patches/server/0282-Add-option-to-prevent-players-from-moving-into-unloa.patch diff --git a/patches/server/0282-Reset-players-airTicks-on-respawn.patch b/patches/server/0283-Reset-players-airTicks-on-respawn.patch similarity index 100% rename from patches/server/0282-Reset-players-airTicks-on-respawn.patch rename to patches/server/0283-Reset-players-airTicks-on-respawn.patch diff --git a/patches/server/0283-Don-t-sleep-after-profile-lookups-if-not-needed.patch b/patches/server/0284-Don-t-sleep-after-profile-lookups-if-not-needed.patch similarity index 100% rename from patches/server/0283-Don-t-sleep-after-profile-lookups-if-not-needed.patch rename to patches/server/0284-Don-t-sleep-after-profile-lookups-if-not-needed.patch diff --git a/patches/server/0284-Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/patches/server/0285-Improve-Server-Thread-Pool-and-Thread-Priorities.patch similarity index 100% rename from patches/server/0284-Improve-Server-Thread-Pool-and-Thread-Priorities.patch rename to patches/server/0285-Improve-Server-Thread-Pool-and-Thread-Priorities.patch diff --git a/patches/server/0285-Optimize-World-Time-Updates.patch b/patches/server/0286-Optimize-World-Time-Updates.patch similarity index 100% rename from patches/server/0285-Optimize-World-Time-Updates.patch rename to patches/server/0286-Optimize-World-Time-Updates.patch diff --git a/patches/server/0286-Restore-custom-InventoryHolder-support.patch b/patches/server/0287-Restore-custom-InventoryHolder-support.patch similarity index 100% rename from patches/server/0286-Restore-custom-InventoryHolder-support.patch rename to patches/server/0287-Restore-custom-InventoryHolder-support.patch diff --git a/patches/server/0287-Use-Vanilla-Minecart-Speeds.patch b/patches/server/0288-Use-Vanilla-Minecart-Speeds.patch similarity index 100% rename from patches/server/0287-Use-Vanilla-Minecart-Speeds.patch rename to patches/server/0288-Use-Vanilla-Minecart-Speeds.patch diff --git a/patches/server/0288-Fix-SpongeAbsortEvent-handling.patch b/patches/server/0289-Fix-SpongeAbsortEvent-handling.patch similarity index 100% rename from patches/server/0288-Fix-SpongeAbsortEvent-handling.patch rename to patches/server/0289-Fix-SpongeAbsortEvent-handling.patch diff --git a/patches/server/0289-Don-t-allow-digging-into-unloaded-chunks.patch b/patches/server/0290-Don-t-allow-digging-into-unloaded-chunks.patch similarity index 100% rename from patches/server/0289-Don-t-allow-digging-into-unloaded-chunks.patch rename to patches/server/0290-Don-t-allow-digging-into-unloaded-chunks.patch diff --git a/patches/server/0290-Make-the-default-permission-message-configurable.patch b/patches/server/0291-Make-the-default-permission-message-configurable.patch similarity index 100% rename from patches/server/0290-Make-the-default-permission-message-configurable.patch rename to patches/server/0291-Make-the-default-permission-message-configurable.patch diff --git a/patches/server/0291-Prevent-rayTrace-from-loading-chunks.patch b/patches/server/0292-Prevent-rayTrace-from-loading-chunks.patch similarity index 100% rename from patches/server/0291-Prevent-rayTrace-from-loading-chunks.patch rename to patches/server/0292-Prevent-rayTrace-from-loading-chunks.patch diff --git a/patches/server/0292-Handle-Large-Packets-disconnecting-client.patch b/patches/server/0293-Handle-Large-Packets-disconnecting-client.patch similarity index 100% rename from patches/server/0292-Handle-Large-Packets-disconnecting-client.patch rename to patches/server/0293-Handle-Large-Packets-disconnecting-client.patch diff --git a/patches/server/0293-force-entity-dismount-during-teleportation.patch b/patches/server/0294-force-entity-dismount-during-teleportation.patch similarity index 100% rename from patches/server/0293-force-entity-dismount-during-teleportation.patch rename to patches/server/0294-force-entity-dismount-during-teleportation.patch diff --git a/patches/server/0294-Add-more-Zombie-API.patch b/patches/server/0295-Add-more-Zombie-API.patch similarity index 100% rename from patches/server/0294-Add-more-Zombie-API.patch rename to patches/server/0295-Add-more-Zombie-API.patch diff --git a/patches/server/0295-Book-Size-Limits.patch b/patches/server/0296-Book-Size-Limits.patch similarity index 100% rename from patches/server/0295-Book-Size-Limits.patch rename to patches/server/0296-Book-Size-Limits.patch diff --git a/patches/server/0296-Add-PlayerConnectionCloseEvent.patch b/patches/server/0297-Add-PlayerConnectionCloseEvent.patch similarity index 100% rename from patches/server/0296-Add-PlayerConnectionCloseEvent.patch rename to patches/server/0297-Add-PlayerConnectionCloseEvent.patch diff --git a/patches/server/0297-Prevent-Enderman-from-loading-chunks.patch b/patches/server/0298-Prevent-Enderman-from-loading-chunks.patch similarity index 100% rename from patches/server/0297-Prevent-Enderman-from-loading-chunks.patch rename to patches/server/0298-Prevent-Enderman-from-loading-chunks.patch diff --git a/patches/server/0298-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/patches/server/0299-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 100% rename from patches/server/0298-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to patches/server/0299-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch diff --git a/patches/server/0299-Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/patches/server/0300-Workaround-for-vehicle-tracking-issue-on-disconnect.patch similarity index 100% rename from patches/server/0299-Workaround-for-vehicle-tracking-issue-on-disconnect.patch rename to patches/server/0300-Workaround-for-vehicle-tracking-issue-on-disconnect.patch diff --git a/patches/server/0300-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/patches/server/0301-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch similarity index 100% rename from patches/server/0300-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch rename to patches/server/0301-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch diff --git a/patches/server/0301-Block-Entity-remove-from-being-called-on-Players.patch b/patches/server/0302-Block-Entity-remove-from-being-called-on-Players.patch similarity index 100% rename from patches/server/0301-Block-Entity-remove-from-being-called-on-Players.patch rename to patches/server/0302-Block-Entity-remove-from-being-called-on-Players.patch diff --git a/patches/server/0302-BlockDestroyEvent.patch b/patches/server/0303-BlockDestroyEvent.patch similarity index 100% rename from patches/server/0302-BlockDestroyEvent.patch rename to patches/server/0303-BlockDestroyEvent.patch diff --git a/patches/server/0303-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/patches/server/0304-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch similarity index 100% rename from patches/server/0303-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch rename to patches/server/0304-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch diff --git a/patches/server/0304-Limit-Client-Sign-length-more.patch b/patches/server/0305-Limit-Client-Sign-length-more.patch similarity index 100% rename from patches/server/0304-Limit-Client-Sign-length-more.patch rename to patches/server/0305-Limit-Client-Sign-length-more.patch diff --git a/patches/server/0305-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/patches/server/0306-Don-t-check-ConvertSigns-boolean-every-sign-save.patch similarity index 100% rename from patches/server/0305-Don-t-check-ConvertSigns-boolean-every-sign-save.patch rename to patches/server/0306-Don-t-check-ConvertSigns-boolean-every-sign-save.patch diff --git a/patches/server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server/0307-Optimize-Network-Manager-and-add-advanced-packet-sup.patch similarity index 100% rename from patches/server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch rename to patches/server/0307-Optimize-Network-Manager-and-add-advanced-packet-sup.patch diff --git a/patches/server/0307-Handle-Oversized-Tile-Entities-in-chunks.patch b/patches/server/0308-Handle-Oversized-Tile-Entities-in-chunks.patch similarity index 100% rename from patches/server/0307-Handle-Oversized-Tile-Entities-in-chunks.patch rename to patches/server/0308-Handle-Oversized-Tile-Entities-in-chunks.patch diff --git a/patches/server/0308-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/patches/server/0309-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch similarity index 100% rename from patches/server/0308-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch rename to patches/server/0309-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch diff --git a/patches/server/0309-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/patches/server/0310-Set-Zombie-last-tick-at-start-of-drowning-process.patch similarity index 100% rename from patches/server/0309-Set-Zombie-last-tick-at-start-of-drowning-process.patch rename to patches/server/0310-Set-Zombie-last-tick-at-start-of-drowning-process.patch diff --git a/patches/server/0310-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/patches/server/0311-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch similarity index 100% rename from patches/server/0310-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch rename to patches/server/0311-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch diff --git a/patches/server/0311-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/patches/server/0312-Use-proper-max-length-when-serialising-BungeeCord-te.patch similarity index 100% rename from patches/server/0311-Use-proper-max-length-when-serialising-BungeeCord-te.patch rename to patches/server/0312-Use-proper-max-length-when-serialising-BungeeCord-te.patch diff --git a/patches/server/0312-Entity-getEntitySpawnReason.patch b/patches/server/0313-Entity-getEntitySpawnReason.patch similarity index 97% rename from patches/server/0312-Entity-getEntitySpawnReason.patch rename to patches/server/0313-Entity-getEntitySpawnReason.patch index fbcb73d40c..20c369e137 100644 --- a/patches/server/0312-Entity-getEntitySpawnReason.patch +++ b/patches/server/0313-Entity-getEntitySpawnReason.patch @@ -93,10 +93,10 @@ index 8df9bd656374d0b43af378c61c1df7b951085b58..fcd3e6bfb4b1d0aefcb34eaec1212b08 } catch (Throwable throwable) { diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 12a78685848b7fd945a472902d8200ea1d50b9ec..3aadcb472ab808ee981065ddfa86be6cbf38c8d9 100644 +index cfb820636f819a7da56d0302d49f39cea1b5a93d..9a8af1867315840518533381e594fc50542cd72d 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -167,6 +167,7 @@ public abstract class BaseSpawner { +@@ -188,6 +188,7 @@ public abstract class BaseSpawner { // Spigot End } entity.spawnedViaMobSpawner = true; // Paper diff --git a/patches/server/0313-Update-entity-Metadata-for-all-tracked-players.patch b/patches/server/0314-Update-entity-Metadata-for-all-tracked-players.patch similarity index 100% rename from patches/server/0313-Update-entity-Metadata-for-all-tracked-players.patch rename to patches/server/0314-Update-entity-Metadata-for-all-tracked-players.patch diff --git a/patches/server/0314-Fire-event-on-GS4-query.patch b/patches/server/0315-Fire-event-on-GS4-query.patch similarity index 100% rename from patches/server/0314-Fire-event-on-GS4-query.patch rename to patches/server/0315-Fire-event-on-GS4-query.patch diff --git a/patches/server/0315-Implement-PlayerPostRespawnEvent.patch b/patches/server/0316-Implement-PlayerPostRespawnEvent.patch similarity index 100% rename from patches/server/0315-Implement-PlayerPostRespawnEvent.patch rename to patches/server/0316-Implement-PlayerPostRespawnEvent.patch diff --git a/patches/server/0316-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/patches/server/0317-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch similarity index 100% rename from patches/server/0316-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch rename to patches/server/0317-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch diff --git a/patches/server/0317-Server-Tick-Events.patch b/patches/server/0318-Server-Tick-Events.patch similarity index 100% rename from patches/server/0317-Server-Tick-Events.patch rename to patches/server/0318-Server-Tick-Events.patch diff --git a/patches/server/0318-PlayerDeathEvent-getItemsToKeep.patch b/patches/server/0319-PlayerDeathEvent-getItemsToKeep.patch similarity index 100% rename from patches/server/0318-PlayerDeathEvent-getItemsToKeep.patch rename to patches/server/0319-PlayerDeathEvent-getItemsToKeep.patch diff --git a/patches/server/0319-Optimize-Captured-TileEntity-Lookup.patch b/patches/server/0320-Optimize-Captured-TileEntity-Lookup.patch similarity index 100% rename from patches/server/0319-Optimize-Captured-TileEntity-Lookup.patch rename to patches/server/0320-Optimize-Captured-TileEntity-Lookup.patch diff --git a/patches/server/0320-Add-Heightmap-API.patch b/patches/server/0321-Add-Heightmap-API.patch similarity index 100% rename from patches/server/0320-Add-Heightmap-API.patch rename to patches/server/0321-Add-Heightmap-API.patch diff --git a/patches/server/0321-Mob-Spawner-API-Enhancements.patch b/patches/server/0322-Mob-Spawner-API-Enhancements.patch similarity index 95% rename from patches/server/0321-Mob-Spawner-API-Enhancements.patch rename to patches/server/0322-Mob-Spawner-API-Enhancements.patch index d24f3a6b40..c19c118528 100644 --- a/patches/server/0321-Mob-Spawner-API-Enhancements.patch +++ b/patches/server/0322-Mob-Spawner-API-Enhancements.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Mob Spawner API Enhancements diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 3aadcb472ab808ee981065ddfa86be6cbf38c8d9..c6298b12e4e0c20be20e7e493be728f028f9eb31 100644 +index 9a8af1867315840518533381e594fc50542cd72d..68ce2732dfdc25ddadc15c43c30a609f9b1eba86 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java @@ -31,7 +31,7 @@ public abstract class BaseSpawner { @@ -26,7 +26,7 @@ index 3aadcb472ab808ee981065ddfa86be6cbf38c8d9..c6298b12e4e0c20be20e7e493be728f0 return world.isAffectsSpawningPlayerNearby((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper } -@@ -204,7 +204,7 @@ public abstract class BaseSpawner { +@@ -225,7 +225,7 @@ public abstract class BaseSpawner { } } @@ -35,7 +35,7 @@ index 3aadcb472ab808ee981065ddfa86be6cbf38c8d9..c6298b12e4e0c20be20e7e493be728f0 if (this.maxSpawnDelay <= this.minSpawnDelay) { this.spawnDelay = this.minSpawnDelay; } else { -@@ -218,7 +218,13 @@ public abstract class BaseSpawner { +@@ -239,7 +239,13 @@ public abstract class BaseSpawner { } public void load(@Nullable Level world, BlockPos pos, CompoundTag nbt) { @@ -49,7 +49,7 @@ index 3aadcb472ab808ee981065ddfa86be6cbf38c8d9..c6298b12e4e0c20be20e7e493be728f0 List list = Lists.newArrayList(); if (nbt.contains("SpawnPotentials", 9)) { -@@ -237,10 +243,15 @@ public abstract class BaseSpawner { +@@ -258,10 +264,15 @@ public abstract class BaseSpawner { this.setSpawnData(world, pos, mobspawnerdata); }); } @@ -68,7 +68,7 @@ index 3aadcb472ab808ee981065ddfa86be6cbf38c8d9..c6298b12e4e0c20be20e7e493be728f0 this.spawnCount = nbt.getShort("SpawnCount"); } -@@ -262,9 +273,20 @@ public abstract class BaseSpawner { +@@ -283,9 +294,20 @@ public abstract class BaseSpawner { if (minecraftkey == null) { return nbt; } else { diff --git a/patches/server/0322-Fix-CB-call-to-changed-postToMainThread-method.patch b/patches/server/0323-Fix-CB-call-to-changed-postToMainThread-method.patch similarity index 100% rename from patches/server/0322-Fix-CB-call-to-changed-postToMainThread-method.patch rename to patches/server/0323-Fix-CB-call-to-changed-postToMainThread-method.patch diff --git a/patches/server/0323-Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/patches/server/0324-Fix-sounds-when-item-frames-are-modified-MC-123450.patch similarity index 100% rename from patches/server/0323-Fix-sounds-when-item-frames-are-modified-MC-123450.patch rename to patches/server/0324-Fix-sounds-when-item-frames-are-modified-MC-123450.patch diff --git a/patches/server/0324-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/patches/server/0325-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch similarity index 100% rename from patches/server/0324-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch rename to patches/server/0325-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch diff --git a/patches/server/0325-improve-CraftWorld-isChunkLoaded.patch b/patches/server/0326-improve-CraftWorld-isChunkLoaded.patch similarity index 100% rename from patches/server/0325-improve-CraftWorld-isChunkLoaded.patch rename to patches/server/0326-improve-CraftWorld-isChunkLoaded.patch diff --git a/patches/server/0326-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server/0327-Configurable-Keep-Spawn-Loaded-range-per-world.patch similarity index 100% rename from patches/server/0326-Configurable-Keep-Spawn-Loaded-range-per-world.patch rename to patches/server/0327-Configurable-Keep-Spawn-Loaded-range-per-world.patch diff --git a/patches/server/0327-ChunkMapDistance-CME.patch b/patches/server/0328-ChunkMapDistance-CME.patch similarity index 100% rename from patches/server/0327-ChunkMapDistance-CME.patch rename to patches/server/0328-ChunkMapDistance-CME.patch diff --git a/patches/server/0328-Implement-CraftBlockSoundGroup.patch b/patches/server/0329-Implement-CraftBlockSoundGroup.patch similarity index 100% rename from patches/server/0328-Implement-CraftBlockSoundGroup.patch rename to patches/server/0329-Implement-CraftBlockSoundGroup.patch diff --git a/patches/server/0329-Chunk-debug-command.patch b/patches/server/0330-Chunk-debug-command.patch similarity index 100% rename from patches/server/0329-Chunk-debug-command.patch rename to patches/server/0330-Chunk-debug-command.patch diff --git a/patches/server/0330-Fix-World-isChunkGenerated-calls.patch b/patches/server/0331-Fix-World-isChunkGenerated-calls.patch similarity index 100% rename from patches/server/0330-Fix-World-isChunkGenerated-calls.patch rename to patches/server/0331-Fix-World-isChunkGenerated-calls.patch diff --git a/patches/server/0331-Show-blockstate-location-if-we-failed-to-read-it.patch b/patches/server/0332-Show-blockstate-location-if-we-failed-to-read-it.patch similarity index 100% rename from patches/server/0331-Show-blockstate-location-if-we-failed-to-read-it.patch rename to patches/server/0332-Show-blockstate-location-if-we-failed-to-read-it.patch diff --git a/patches/server/0332-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/patches/server/0333-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch similarity index 96% rename from patches/server/0332-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch rename to patches/server/0333-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch index fbf0003ead..6ea6b89385 100644 --- a/patches/server/0332-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch +++ b/patches/server/0333-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch @@ -37,7 +37,7 @@ index 090958a30ce20ff01ae77d4cd821a167474f0214..baf33659b021c89cbd02560cbfd9b0dd } + diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 30ba1e3cb75d994770b006b9dfd6669000a9c1a4..e20a645e28a2e503c02b2bd89424e95506a2e6df 100644 +index 6204bf41d410df9784b32f993b46d7adb2af5f13..19d0ed5ff8569b0280117750f9ce05095afd9f70 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java @@ -85,6 +85,13 @@ public final class NaturalSpawner { diff --git a/patches/server/0333-Configurable-projectile-relative-velocity.patch b/patches/server/0334-Configurable-projectile-relative-velocity.patch similarity index 100% rename from patches/server/0333-Configurable-projectile-relative-velocity.patch rename to patches/server/0334-Configurable-projectile-relative-velocity.patch diff --git a/patches/server/0334-offset-item-frame-ticking.patch b/patches/server/0335-offset-item-frame-ticking.patch similarity index 100% rename from patches/server/0334-offset-item-frame-ticking.patch rename to patches/server/0335-offset-item-frame-ticking.patch diff --git a/patches/server/0335-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/patches/server/0336-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch similarity index 100% rename from patches/server/0335-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch rename to patches/server/0336-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch diff --git a/patches/server/0336-Fix-MC-158900.patch b/patches/server/0337-Fix-MC-158900.patch similarity index 100% rename from patches/server/0336-Fix-MC-158900.patch rename to patches/server/0337-Fix-MC-158900.patch diff --git a/patches/server/0337-Prevent-consuming-the-wrong-itemstack.patch b/patches/server/0338-Prevent-consuming-the-wrong-itemstack.patch similarity index 100% rename from patches/server/0337-Prevent-consuming-the-wrong-itemstack.patch rename to patches/server/0338-Prevent-consuming-the-wrong-itemstack.patch diff --git a/patches/server/0338-Generator-Settings.patch b/patches/server/0339-Generator-Settings.patch similarity index 100% rename from patches/server/0338-Generator-Settings.patch rename to patches/server/0339-Generator-Settings.patch diff --git a/patches/server/0339-Fix-MC-161754.patch b/patches/server/0340-Fix-MC-161754.patch similarity index 100% rename from patches/server/0339-Fix-MC-161754.patch rename to patches/server/0340-Fix-MC-161754.patch diff --git a/patches/server/0340-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/patches/server/0341-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch similarity index 100% rename from patches/server/0340-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch rename to patches/server/0341-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch diff --git a/patches/server/0341-Expose-the-internal-current-tick.patch b/patches/server/0342-Expose-the-internal-current-tick.patch similarity index 100% rename from patches/server/0341-Expose-the-internal-current-tick.patch rename to patches/server/0342-Expose-the-internal-current-tick.patch diff --git a/patches/server/0342-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/patches/server/0343-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch similarity index 100% rename from patches/server/0342-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch rename to patches/server/0343-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch diff --git a/patches/server/0343-Add-option-to-disable-pillager-patrols.patch b/patches/server/0344-Add-option-to-disable-pillager-patrols.patch similarity index 100% rename from patches/server/0343-Add-option-to-disable-pillager-patrols.patch rename to patches/server/0344-Add-option-to-disable-pillager-patrols.patch diff --git a/patches/server/0344-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/patches/server/0345-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch similarity index 100% rename from patches/server/0344-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch rename to patches/server/0345-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch diff --git a/patches/server/0345-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/patches/server/0346-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch similarity index 100% rename from patches/server/0345-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch rename to patches/server/0346-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch diff --git a/patches/server/0346-MC-145656-Fix-Follow-Range-Initial-Target.patch b/patches/server/0347-MC-145656-Fix-Follow-Range-Initial-Target.patch similarity index 100% rename from patches/server/0346-MC-145656-Fix-Follow-Range-Initial-Target.patch rename to patches/server/0347-MC-145656-Fix-Follow-Range-Initial-Target.patch diff --git a/patches/server/0347-Optimize-Hoppers.patch b/patches/server/0348-Optimize-Hoppers.patch similarity index 100% rename from patches/server/0347-Optimize-Hoppers.patch rename to patches/server/0348-Optimize-Hoppers.patch diff --git a/patches/server/0348-PlayerDeathEvent-shouldDropExperience.patch b/patches/server/0349-PlayerDeathEvent-shouldDropExperience.patch similarity index 100% rename from patches/server/0348-PlayerDeathEvent-shouldDropExperience.patch rename to patches/server/0349-PlayerDeathEvent-shouldDropExperience.patch diff --git a/patches/server/0349-Prevent-bees-loading-chunks-checking-hive-position.patch b/patches/server/0350-Prevent-bees-loading-chunks-checking-hive-position.patch similarity index 100% rename from patches/server/0349-Prevent-bees-loading-chunks-checking-hive-position.patch rename to patches/server/0350-Prevent-bees-loading-chunks-checking-hive-position.patch diff --git a/patches/server/0350-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/patches/server/0351-Don-t-load-Chunks-from-Hoppers-and-other-things.patch similarity index 100% rename from patches/server/0350-Don-t-load-Chunks-from-Hoppers-and-other-things.patch rename to patches/server/0351-Don-t-load-Chunks-from-Hoppers-and-other-things.patch diff --git a/patches/server/0351-Guard-against-serializing-mismatching-chunk-coordina.patch b/patches/server/0352-Guard-against-serializing-mismatching-chunk-coordina.patch similarity index 100% rename from patches/server/0351-Guard-against-serializing-mismatching-chunk-coordina.patch rename to patches/server/0352-Guard-against-serializing-mismatching-chunk-coordina.patch diff --git a/patches/server/0352-Optimise-IEntityAccess-getPlayerByUUID.patch b/patches/server/0353-Optimise-IEntityAccess-getPlayerByUUID.patch similarity index 100% rename from patches/server/0352-Optimise-IEntityAccess-getPlayerByUUID.patch rename to patches/server/0353-Optimise-IEntityAccess-getPlayerByUUID.patch diff --git a/patches/server/0353-Fix-items-not-falling-correctly.patch b/patches/server/0354-Fix-items-not-falling-correctly.patch similarity index 100% rename from patches/server/0353-Fix-items-not-falling-correctly.patch rename to patches/server/0354-Fix-items-not-falling-correctly.patch diff --git a/patches/server/0354-Lag-compensate-eating.patch b/patches/server/0355-Lag-compensate-eating.patch similarity index 100% rename from patches/server/0354-Lag-compensate-eating.patch rename to patches/server/0355-Lag-compensate-eating.patch diff --git a/patches/server/0355-Optimize-call-to-getFluid-for-explosions.patch b/patches/server/0356-Optimize-call-to-getFluid-for-explosions.patch similarity index 100% rename from patches/server/0355-Optimize-call-to-getFluid-for-explosions.patch rename to patches/server/0356-Optimize-call-to-getFluid-for-explosions.patch diff --git a/patches/server/0356-Fix-last-firework-in-stack-not-having-effects-when-d.patch b/patches/server/0357-Fix-last-firework-in-stack-not-having-effects-when-d.patch similarity index 100% rename from patches/server/0356-Fix-last-firework-in-stack-not-having-effects-when-d.patch rename to patches/server/0357-Fix-last-firework-in-stack-not-having-effects-when-d.patch diff --git a/patches/server/0357-Add-effect-to-block-break-naturally.patch b/patches/server/0358-Add-effect-to-block-break-naturally.patch similarity index 100% rename from patches/server/0357-Add-effect-to-block-break-naturally.patch rename to patches/server/0358-Add-effect-to-block-break-naturally.patch diff --git a/patches/server/0358-Entity-Activation-Range-2.0.patch b/patches/server/0359-Entity-Activation-Range-2.0.patch similarity index 99% rename from patches/server/0358-Entity-Activation-Range-2.0.patch rename to patches/server/0359-Entity-Activation-Range-2.0.patch index 35cc61b42d..426f54cefb 100644 --- a/patches/server/0358-Entity-Activation-Range-2.0.patch +++ b/patches/server/0359-Entity-Activation-Range-2.0.patch @@ -293,7 +293,7 @@ index 065d0752db0e3ae2a89d707aaa2145807f50ecad..c93805ae832d049ea13ca495b778ed52 } } diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 6a9e2105b2d9a4ee83c0a2516d5ef26dc3b99053..a35ce224b11b44567814207c3821d0cd4cdd9ec1 100644 +index aec77679584a2acab5818e26e2586b5316118e84..9c7cb4f11c429ca5006cf5e178326ead1658581d 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -227,17 +227,29 @@ public class Villager extends AbstractVillager implements ReputationEventHandler diff --git a/patches/server/0359-Increase-Light-Queue-Size.patch b/patches/server/0360-Increase-Light-Queue-Size.patch similarity index 100% rename from patches/server/0359-Increase-Light-Queue-Size.patch rename to patches/server/0360-Increase-Light-Queue-Size.patch diff --git a/patches/server/0360-Fix-Light-Command.patch b/patches/server/0361-Fix-Light-Command.patch similarity index 100% rename from patches/server/0360-Fix-Light-Command.patch rename to patches/server/0361-Fix-Light-Command.patch diff --git a/patches/server/0361-No-Tick-view-distance-implementation.patch b/patches/server/0362-No-Tick-view-distance-implementation.patch similarity index 100% rename from patches/server/0361-No-Tick-view-distance-implementation.patch rename to patches/server/0362-No-Tick-view-distance-implementation.patch diff --git a/patches/server/0362-Implement-alternative-item-despawn-rate.patch b/patches/server/0363-Implement-alternative-item-despawn-rate.patch similarity index 100% rename from patches/server/0362-Implement-alternative-item-despawn-rate.patch rename to patches/server/0363-Implement-alternative-item-despawn-rate.patch diff --git a/patches/server/0363-Tracking-Range-Improvements.patch b/patches/server/0364-Tracking-Range-Improvements.patch similarity index 100% rename from patches/server/0363-Tracking-Range-Improvements.patch rename to patches/server/0364-Tracking-Range-Improvements.patch diff --git a/patches/server/0364-Fix-items-vanishing-through-end-portal.patch b/patches/server/0365-Fix-items-vanishing-through-end-portal.patch similarity index 100% rename from patches/server/0364-Fix-items-vanishing-through-end-portal.patch rename to patches/server/0365-Fix-items-vanishing-through-end-portal.patch diff --git a/patches/server/0365-implement-optional-per-player-mob-spawns.patch b/patches/server/0366-implement-optional-per-player-mob-spawns.patch similarity index 99% rename from patches/server/0365-implement-optional-per-player-mob-spawns.patch rename to patches/server/0366-implement-optional-per-player-mob-spawns.patch index 225d30ce9d..5b3eeae286 100644 --- a/patches/server/0365-implement-optional-per-player-mob-spawns.patch +++ b/patches/server/0366-implement-optional-per-player-mob-spawns.patch @@ -665,7 +665,7 @@ index bffc897cb88a54c36432c98264f3416051aeab17..14a0190ea5e9a387582736bb130c16a3 // Yes, this doesn't match Vanilla, but it's the best we can do for now. diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index e20a645e28a2e503c02b2bd89424e95506a2e6df..18a28659a72a761f53ca226bbf9866b4f30c2e4c 100644 +index 19d0ed5ff8569b0280117750f9ce05095afd9f70..490ff09c3c4f93dcafc1703b1df3fb2f7333add2 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java @@ -17,6 +17,7 @@ import net.minecraft.core.Registry; @@ -778,7 +778,7 @@ index e20a645e28a2e503c02b2bd89424e95506a2e6df..18a28659a72a761f53ca226bbf9866b4 int k = 0; while (k < 3) { -@@ -242,7 +283,7 @@ public final class NaturalSpawner { +@@ -248,7 +289,7 @@ public final class NaturalSpawner { Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type); if (entityinsentient == null) { @@ -787,7 +787,7 @@ index e20a645e28a2e503c02b2bd89424e95506a2e6df..18a28659a72a761f53ca226bbf9866b4 } entityinsentient.moveTo(d0, (double) i, d1, world.random.nextFloat() * 360.0F, 0.0F); -@@ -254,10 +295,15 @@ public final class NaturalSpawner { +@@ -260,10 +301,15 @@ public final class NaturalSpawner { ++j; ++k1; runner.run(entityinsentient, chunk); @@ -805,7 +805,7 @@ index e20a645e28a2e503c02b2bd89424e95506a2e6df..18a28659a72a761f53ca226bbf9866b4 } if (entityinsentient.isMaxGroupSizeReached(k1)) { -@@ -279,6 +325,7 @@ public final class NaturalSpawner { +@@ -285,6 +331,7 @@ public final class NaturalSpawner { } } diff --git a/patches/server/0366-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/0367-Bees-get-gravity-in-void.-Fixes-MC-167279.patch similarity index 100% rename from patches/server/0366-Bees-get-gravity-in-void.-Fixes-MC-167279.patch rename to patches/server/0367-Bees-get-gravity-in-void.-Fixes-MC-167279.patch diff --git a/patches/server/0367-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server/0368-Optimise-getChunkAt-calls-for-loaded-chunks.patch similarity index 100% rename from patches/server/0367-Optimise-getChunkAt-calls-for-loaded-chunks.patch rename to patches/server/0368-Optimise-getChunkAt-calls-for-loaded-chunks.patch diff --git a/patches/server/0368-Allow-overriding-the-java-version-check.patch b/patches/server/0369-Allow-overriding-the-java-version-check.patch similarity index 100% rename from patches/server/0368-Allow-overriding-the-java-version-check.patch rename to patches/server/0369-Allow-overriding-the-java-version-check.patch diff --git a/patches/server/0369-Add-ThrownEggHatchEvent.patch b/patches/server/0370-Add-ThrownEggHatchEvent.patch similarity index 100% rename from patches/server/0369-Add-ThrownEggHatchEvent.patch rename to patches/server/0370-Add-ThrownEggHatchEvent.patch diff --git a/patches/server/0370-Optimise-random-block-ticking.patch b/patches/server/0371-Optimise-random-block-ticking.patch similarity index 100% rename from patches/server/0370-Optimise-random-block-ticking.patch rename to patches/server/0371-Optimise-random-block-ticking.patch diff --git a/patches/server/0371-Entity-Jump-API.patch b/patches/server/0372-Entity-Jump-API.patch similarity index 100% rename from patches/server/0371-Entity-Jump-API.patch rename to patches/server/0372-Entity-Jump-API.patch diff --git a/patches/server/0372-Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/0373-Add-option-to-nerf-pigmen-from-nether-portals.patch similarity index 100% rename from patches/server/0372-Add-option-to-nerf-pigmen-from-nether-portals.patch rename to patches/server/0373-Add-option-to-nerf-pigmen-from-nether-portals.patch diff --git a/patches/server/0373-Make-the-GUI-graph-fancier.patch b/patches/server/0374-Make-the-GUI-graph-fancier.patch similarity index 100% rename from patches/server/0373-Make-the-GUI-graph-fancier.patch rename to patches/server/0374-Make-the-GUI-graph-fancier.patch diff --git a/patches/server/0374-add-hand-to-BlockMultiPlaceEvent.patch b/patches/server/0375-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from patches/server/0374-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/server/0375-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/patches/server/0375-Prevent-teleporting-dead-entities.patch b/patches/server/0376-Prevent-teleporting-dead-entities.patch similarity index 100% rename from patches/server/0375-Prevent-teleporting-dead-entities.patch rename to patches/server/0376-Prevent-teleporting-dead-entities.patch diff --git a/patches/server/0376-Validate-tripwire-hook-placement-before-update.patch b/patches/server/0377-Validate-tripwire-hook-placement-before-update.patch similarity index 100% rename from patches/server/0376-Validate-tripwire-hook-placement-before-update.patch rename to patches/server/0377-Validate-tripwire-hook-placement-before-update.patch diff --git a/patches/server/0377-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server/0378-Add-option-to-allow-iron-golems-to-spawn-in-air.patch similarity index 100% rename from patches/server/0377-Add-option-to-allow-iron-golems-to-spawn-in-air.patch rename to patches/server/0378-Add-option-to-allow-iron-golems-to-spawn-in-air.patch diff --git a/patches/server/0378-Configurable-chance-of-villager-zombie-infection.patch b/patches/server/0379-Configurable-chance-of-villager-zombie-infection.patch similarity index 100% rename from patches/server/0378-Configurable-chance-of-villager-zombie-infection.patch rename to patches/server/0379-Configurable-chance-of-villager-zombie-infection.patch diff --git a/patches/server/0379-Optimise-Chunk-getFluid.patch b/patches/server/0380-Optimise-Chunk-getFluid.patch similarity index 100% rename from patches/server/0379-Optimise-Chunk-getFluid.patch rename to patches/server/0380-Optimise-Chunk-getFluid.patch diff --git a/patches/server/0380-Optimise-TickListServer-by-rewriting-it.patch b/patches/server/0381-Optimise-TickListServer-by-rewriting-it.patch similarity index 100% rename from patches/server/0380-Optimise-TickListServer-by-rewriting-it.patch rename to patches/server/0381-Optimise-TickListServer-by-rewriting-it.patch diff --git a/patches/server/0381-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/0382-Pillager-patrol-spawn-settings-and-per-player-option.patch similarity index 100% rename from patches/server/0381-Pillager-patrol-spawn-settings-and-per-player-option.patch rename to patches/server/0382-Pillager-patrol-spawn-settings-and-per-player-option.patch diff --git a/patches/server/0382-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server/0383-Remote-Connections-shouldn-t-hold-up-shutdown.patch similarity index 100% rename from patches/server/0382-Remote-Connections-shouldn-t-hold-up-shutdown.patch rename to patches/server/0383-Remote-Connections-shouldn-t-hold-up-shutdown.patch diff --git a/patches/server/0383-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/0384-Do-not-allow-bees-to-load-chunks-for-beehives.patch similarity index 100% rename from patches/server/0383-Do-not-allow-bees-to-load-chunks-for-beehives.patch rename to patches/server/0384-Do-not-allow-bees-to-load-chunks-for-beehives.patch diff --git a/patches/server/0384-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server/0385-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch similarity index 100% rename from patches/server/0384-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch rename to patches/server/0385-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch diff --git a/patches/server/0385-Optimize-Collision-to-not-load-chunks.patch b/patches/server/0386-Optimize-Collision-to-not-load-chunks.patch similarity index 100% rename from patches/server/0385-Optimize-Collision-to-not-load-chunks.patch rename to patches/server/0386-Optimize-Collision-to-not-load-chunks.patch diff --git a/patches/server/0386-Don-t-tick-dead-players.patch b/patches/server/0387-Don-t-tick-dead-players.patch similarity index 100% rename from patches/server/0386-Don-t-tick-dead-players.patch rename to patches/server/0387-Don-t-tick-dead-players.patch diff --git a/patches/server/0387-Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server/0388-Dead-Player-s-shouldn-t-be-able-to-move.patch similarity index 100% rename from patches/server/0387-Dead-Player-s-shouldn-t-be-able-to-move.patch rename to patches/server/0388-Dead-Player-s-shouldn-t-be-able-to-move.patch diff --git a/patches/server/0388-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/0389-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch similarity index 100% rename from patches/server/0388-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch rename to patches/server/0389-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch diff --git a/patches/server/0389-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/patches/server/0390-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch similarity index 100% rename from patches/server/0389-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch rename to patches/server/0390-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch diff --git a/patches/server/0390-Don-t-move-existing-players-to-world-spawn.patch b/patches/server/0391-Don-t-move-existing-players-to-world-spawn.patch similarity index 100% rename from patches/server/0390-Don-t-move-existing-players-to-world-spawn.patch rename to patches/server/0391-Don-t-move-existing-players-to-world-spawn.patch diff --git a/patches/server/0391-Add-tick-times-API-and-mspt-command.patch b/patches/server/0392-Add-tick-times-API-and-mspt-command.patch similarity index 100% rename from patches/server/0391-Add-tick-times-API-and-mspt-command.patch rename to patches/server/0392-Add-tick-times-API-and-mspt-command.patch diff --git a/patches/server/0392-Expose-MinecraftServer-isRunning.patch b/patches/server/0393-Expose-MinecraftServer-isRunning.patch similarity index 100% rename from patches/server/0392-Expose-MinecraftServer-isRunning.patch rename to patches/server/0393-Expose-MinecraftServer-isRunning.patch diff --git a/patches/server/0393-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/0394-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 100% rename from patches/server/0393-Add-Raw-Byte-ItemStack-Serialization.patch rename to patches/server/0394-Add-Raw-Byte-ItemStack-Serialization.patch diff --git a/patches/server/0394-Remove-streams-from-Mob-AI-System.patch b/patches/server/0395-Remove-streams-from-Mob-AI-System.patch similarity index 100% rename from patches/server/0394-Remove-streams-from-Mob-AI-System.patch rename to patches/server/0395-Remove-streams-from-Mob-AI-System.patch diff --git a/patches/server/0395-Async-command-map-building.patch b/patches/server/0396-Async-command-map-building.patch similarity index 100% rename from patches/server/0395-Async-command-map-building.patch rename to patches/server/0396-Async-command-map-building.patch diff --git a/patches/server/0396-Improved-Watchdog-Support.patch b/patches/server/0397-Improved-Watchdog-Support.patch similarity index 100% rename from patches/server/0396-Improved-Watchdog-Support.patch rename to patches/server/0397-Improved-Watchdog-Support.patch diff --git a/patches/server/0397-Optimize-Pathfinding.patch b/patches/server/0398-Optimize-Pathfinding.patch similarity index 100% rename from patches/server/0397-Optimize-Pathfinding.patch rename to patches/server/0398-Optimize-Pathfinding.patch diff --git a/patches/server/0398-Reduce-Either-Optional-allocation.patch b/patches/server/0399-Reduce-Either-Optional-allocation.patch similarity index 100% rename from patches/server/0398-Reduce-Either-Optional-allocation.patch rename to patches/server/0399-Reduce-Either-Optional-allocation.patch diff --git a/patches/server/0399-Remove-streams-from-PairedQueue.patch b/patches/server/0400-Remove-streams-from-PairedQueue.patch similarity index 100% rename from patches/server/0399-Remove-streams-from-PairedQueue.patch rename to patches/server/0400-Remove-streams-from-PairedQueue.patch diff --git a/patches/server/0400-Reduce-memory-footprint-of-NBTTagCompound.patch b/patches/server/0401-Reduce-memory-footprint-of-NBTTagCompound.patch similarity index 100% rename from patches/server/0400-Reduce-memory-footprint-of-NBTTagCompound.patch rename to patches/server/0401-Reduce-memory-footprint-of-NBTTagCompound.patch diff --git a/patches/server/0401-Prevent-opening-inventories-when-frozen.patch b/patches/server/0402-Prevent-opening-inventories-when-frozen.patch similarity index 100% rename from patches/server/0401-Prevent-opening-inventories-when-frozen.patch rename to patches/server/0402-Prevent-opening-inventories-when-frozen.patch diff --git a/patches/server/0402-Optimise-ArraySetSorted-removeIf.patch b/patches/server/0403-Optimise-ArraySetSorted-removeIf.patch similarity index 100% rename from patches/server/0402-Optimise-ArraySetSorted-removeIf.patch rename to patches/server/0403-Optimise-ArraySetSorted-removeIf.patch diff --git a/patches/server/0403-Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server/0404-Don-t-run-entity-collision-code-if-not-needed.patch similarity index 100% rename from patches/server/0403-Don-t-run-entity-collision-code-if-not-needed.patch rename to patches/server/0404-Don-t-run-entity-collision-code-if-not-needed.patch diff --git a/patches/server/0404-Restrict-vanilla-teleport-command-to-valid-locations.patch b/patches/server/0405-Restrict-vanilla-teleport-command-to-valid-locations.patch similarity index 100% rename from patches/server/0404-Restrict-vanilla-teleport-command-to-valid-locations.patch rename to patches/server/0405-Restrict-vanilla-teleport-command-to-valid-locations.patch diff --git a/patches/server/0405-Implement-Player-Client-Options-API.patch b/patches/server/0406-Implement-Player-Client-Options-API.patch similarity index 100% rename from patches/server/0405-Implement-Player-Client-Options-API.patch rename to patches/server/0406-Implement-Player-Client-Options-API.patch diff --git a/patches/server/0406-Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server/0407-Fix-Chunk-Post-Processing-deadlock-risk.patch similarity index 100% rename from patches/server/0406-Fix-Chunk-Post-Processing-deadlock-risk.patch rename to patches/server/0407-Fix-Chunk-Post-Processing-deadlock-risk.patch diff --git a/patches/server/0407-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/patches/server/0408-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch similarity index 100% rename from patches/server/0407-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch rename to patches/server/0408-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch diff --git a/patches/server/0408-Broadcast-join-message-to-console.patch b/patches/server/0409-Broadcast-join-message-to-console.patch similarity index 100% rename from patches/server/0408-Broadcast-join-message-to-console.patch rename to patches/server/0409-Broadcast-join-message-to-console.patch diff --git a/patches/server/0409-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/patches/server/0410-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch similarity index 100% rename from patches/server/0409-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch rename to patches/server/0410-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch diff --git a/patches/server/0410-Load-Chunks-for-Login-Asynchronously.patch b/patches/server/0411-Load-Chunks-for-Login-Asynchronously.patch similarity index 100% rename from patches/server/0410-Load-Chunks-for-Login-Asynchronously.patch rename to patches/server/0411-Load-Chunks-for-Login-Asynchronously.patch diff --git a/patches/server/0411-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/patches/server/0412-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch similarity index 100% rename from patches/server/0411-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch rename to patches/server/0412-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch diff --git a/patches/server/0412-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server/0413-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from patches/server/0412-Add-PlayerAttackEntityCooldownResetEvent.patch rename to patches/server/0413-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/patches/server/0413-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/patches/server/0414-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch similarity index 100% rename from patches/server/0413-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch rename to patches/server/0414-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch diff --git a/patches/server/0414-Don-t-fire-BlockFade-on-worldgen-threads.patch b/patches/server/0415-Don-t-fire-BlockFade-on-worldgen-threads.patch similarity index 100% rename from patches/server/0414-Don-t-fire-BlockFade-on-worldgen-threads.patch rename to patches/server/0415-Don-t-fire-BlockFade-on-worldgen-threads.patch diff --git a/patches/server/0415-Add-phantom-creative-and-insomniac-controls.patch b/patches/server/0416-Add-phantom-creative-and-insomniac-controls.patch similarity index 100% rename from patches/server/0415-Add-phantom-creative-and-insomniac-controls.patch rename to patches/server/0416-Add-phantom-creative-and-insomniac-controls.patch diff --git a/patches/server/0416-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/patches/server/0417-Fix-numerous-item-duplication-issues-and-teleport-is.patch similarity index 100% rename from patches/server/0416-Fix-numerous-item-duplication-issues-and-teleport-is.patch rename to patches/server/0417-Fix-numerous-item-duplication-issues-and-teleport-is.patch diff --git a/patches/server/0417-Implement-Brigadier-Mojang-API.patch b/patches/server/0418-Implement-Brigadier-Mojang-API.patch similarity index 100% rename from patches/server/0417-Implement-Brigadier-Mojang-API.patch rename to patches/server/0418-Implement-Brigadier-Mojang-API.patch diff --git a/patches/server/0418-Villager-Restocks-API.patch b/patches/server/0419-Villager-Restocks-API.patch similarity index 97% rename from patches/server/0418-Villager-Restocks-API.patch rename to patches/server/0419-Villager-Restocks-API.patch index 3f24c8fdfe..1445794bf4 100644 --- a/patches/server/0418-Villager-Restocks-API.patch +++ b/patches/server/0419-Villager-Restocks-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Villager Restocks API diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index a35ce224b11b44567814207c3821d0cd4cdd9ec1..e99cdbb1d050288b5f1177737b242c331a989471 100644 +index 9c7cb4f11c429ca5006cf5e178326ead1658581d..fd2a2493fd7c935ab0b2fcd0f5d2b87ef3413af2 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -127,7 +127,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler diff --git a/patches/server/0419-Validate-PickItem-Packet-and-kick-for-invalid.patch b/patches/server/0420-Validate-PickItem-Packet-and-kick-for-invalid.patch similarity index 100% rename from patches/server/0419-Validate-PickItem-Packet-and-kick-for-invalid.patch rename to patches/server/0420-Validate-PickItem-Packet-and-kick-for-invalid.patch diff --git a/patches/server/0420-Expose-game-version.patch b/patches/server/0421-Expose-game-version.patch similarity index 100% rename from patches/server/0420-Expose-game-version.patch rename to patches/server/0421-Expose-game-version.patch diff --git a/patches/server/0421-Optimize-Voxel-Shape-Merging.patch b/patches/server/0422-Optimize-Voxel-Shape-Merging.patch similarity index 100% rename from patches/server/0421-Optimize-Voxel-Shape-Merging.patch rename to patches/server/0422-Optimize-Voxel-Shape-Merging.patch diff --git a/patches/server/0422-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/patches/server/0423-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch similarity index 100% rename from patches/server/0422-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch rename to patches/server/0423-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch diff --git a/patches/server/0423-Implement-Mob-Goal-API.patch b/patches/server/0424-Implement-Mob-Goal-API.patch similarity index 100% rename from patches/server/0423-Implement-Mob-Goal-API.patch rename to patches/server/0424-Implement-Mob-Goal-API.patch diff --git a/patches/server/0424-Use-distance-map-to-optimise-entity-tracker.patch b/patches/server/0425-Use-distance-map-to-optimise-entity-tracker.patch similarity index 100% rename from patches/server/0424-Use-distance-map-to-optimise-entity-tracker.patch rename to patches/server/0425-Use-distance-map-to-optimise-entity-tracker.patch diff --git a/patches/server/0425-Optimize-isOutsideRange-to-use-distance-maps.patch b/patches/server/0426-Optimize-isOutsideRange-to-use-distance-maps.patch similarity index 100% rename from patches/server/0425-Optimize-isOutsideRange-to-use-distance-maps.patch rename to patches/server/0426-Optimize-isOutsideRange-to-use-distance-maps.patch diff --git a/patches/server/0426-Add-villager-reputation-API.patch b/patches/server/0427-Add-villager-reputation-API.patch similarity index 98% rename from patches/server/0426-Add-villager-reputation-API.patch rename to patches/server/0427-Add-villager-reputation-API.patch index 3679ce0494..851d9cc053 100644 --- a/patches/server/0426-Add-villager-reputation-API.patch +++ b/patches/server/0427-Add-villager-reputation-API.patch @@ -71,10 +71,10 @@ index 07ecb01d02f64e85d478995062a33b58c211ed7e..e316f83a7adc7bba06a6a3fdab55cc9c static class GossipEntry { diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index e99cdbb1d050288b5f1177737b242c331a989471..8508a3864fc3f8919f823d96f27061a6b3706713 100644 +index fd2a2493fd7c935ab0b2fcd0f5d2b87ef3413af2..94e742856244b99236ba458fa38801abb5acf286 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -1065,6 +1065,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -1080,6 +1080,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler this.numberOfRestocksToday = 0; } diff --git a/patches/server/0426-Option-for-maximum-exp-value-when-merging-orbs.patch b/patches/server/0428-Option-for-maximum-exp-value-when-merging-orbs.patch similarity index 100% rename from patches/server/0426-Option-for-maximum-exp-value-when-merging-orbs.patch rename to patches/server/0428-Option-for-maximum-exp-value-when-merging-orbs.patch diff --git a/patches/server/0427-ExperienceOrbMergeEvent.patch b/patches/server/0429-ExperienceOrbMergeEvent.patch similarity index 100% rename from patches/server/0427-ExperienceOrbMergeEvent.patch rename to patches/server/0429-ExperienceOrbMergeEvent.patch diff --git a/patches/server/0427-Fix-PotionEffect-ignores-icon-flag.patch b/patches/server/0430-Fix-PotionEffect-ignores-icon-flag.patch similarity index 100% rename from patches/server/0427-Fix-PotionEffect-ignores-icon-flag.patch rename to patches/server/0430-Fix-PotionEffect-ignores-icon-flag.patch diff --git a/patches/server/0428-Optimize-brigadier-child-sorting-performance.patch b/patches/server/0431-Optimize-brigadier-child-sorting-performance.patch similarity index 100% rename from patches/server/0428-Optimize-brigadier-child-sorting-performance.patch rename to patches/server/0431-Optimize-brigadier-child-sorting-performance.patch diff --git a/patches/server/0429-Potential-bed-API.patch b/patches/server/0432-Potential-bed-API.patch similarity index 100% rename from patches/server/0429-Potential-bed-API.patch rename to patches/server/0432-Potential-bed-API.patch diff --git a/patches/server/0430-Wait-for-Async-Tasks-during-shutdown.patch b/patches/server/0433-Wait-for-Async-Tasks-during-shutdown.patch similarity index 100% rename from patches/server/0430-Wait-for-Async-Tasks-during-shutdown.patch rename to patches/server/0433-Wait-for-Async-Tasks-during-shutdown.patch diff --git a/patches/server/0431-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/patches/server/0434-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch similarity index 100% rename from patches/server/0431-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch rename to patches/server/0434-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch diff --git a/patches/server/0432-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server/0435-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch similarity index 100% rename from patches/server/0432-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch rename to patches/server/0435-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch diff --git a/patches/server/0433-Reduce-MutableInt-allocations-from-light-engine.patch b/patches/server/0436-Reduce-MutableInt-allocations-from-light-engine.patch similarity index 100% rename from patches/server/0433-Reduce-MutableInt-allocations-from-light-engine.patch rename to patches/server/0436-Reduce-MutableInt-allocations-from-light-engine.patch diff --git a/patches/server/0434-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/patches/server/0437-Reduce-allocation-of-Vec3D-by-entity-tracker.patch similarity index 100% rename from patches/server/0434-Reduce-allocation-of-Vec3D-by-entity-tracker.patch rename to patches/server/0437-Reduce-allocation-of-Vec3D-by-entity-tracker.patch diff --git a/patches/server/0435-Ensure-safe-gateway-teleport.patch b/patches/server/0438-Ensure-safe-gateway-teleport.patch similarity index 100% rename from patches/server/0435-Ensure-safe-gateway-teleport.patch rename to patches/server/0438-Ensure-safe-gateway-teleport.patch diff --git a/patches/server/0436-Add-option-for-console-having-all-permissions.patch b/patches/server/0439-Add-option-for-console-having-all-permissions.patch similarity index 100% rename from patches/server/0436-Add-option-for-console-having-all-permissions.patch rename to patches/server/0439-Add-option-for-console-having-all-permissions.patch diff --git a/patches/server/0437-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/patches/server/0440-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch similarity index 100% rename from patches/server/0437-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch rename to patches/server/0440-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch From 45c6df964850569f44fa22f16f29a5f0d86d9f42 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 23:45:29 -0700 Subject: [PATCH 102/226] patches --- ...k-Priority-Urgency-System-for-Chunks.patch | 2 + ...mprove-Chunk-Status-Transition-Speed.patch | 4 + ...ookup-for-Treasure-Maps-Fixes-lag-fr.patch | 35 ------ ...ement-optional-per-player-mob-spawns.patch | 12 +- ...packets-to-nearby-locations-sounds-.patch} | 6 +- ...x-villager-trading-demand-MC-163962.patch} | 2 +- .../0443-Maps-shouldn-t-load-chunks.patch} | 4 +- ...ookup-for-Treasure-Maps-Fixes-lag-fr.patch | 20 +++ ...Optimize-Bit-Operations-by-inlining.patch} | 119 +++++++++--------- 9 files changed, 98 insertions(+), 106 deletions(-) rename patches/{server-remapped => removed/1.17}/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch (99%) rename patches/{server-remapped => removed/1.17}/0488-Improve-Chunk-Status-Transition-Speed.patch (98%) delete mode 100644 patches/server-remapped/0491-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch rename patches/{server-remapped/0487-Optimize-sending-packets-to-nearby-locations-sounds-.patch => server/0441-Optimize-sending-packets-to-nearby-locations-sounds-.patch} (92%) rename patches/{server-remapped/0489-Fix-villager-trading-demand-MC-163962.patch => server/0442-Fix-villager-trading-demand-MC-163962.patch} (90%) rename patches/{server-remapped/0490-Maps-shouldn-t-load-chunks.patch => server/0443-Maps-shouldn-t-load-chunks.patch} (91%) create mode 100644 patches/server/0444-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch rename patches/{server-remapped/0492-Optimize-Bit-Operations-by-inlining.patch => server/0445-Optimize-Bit-Operations-by-inlining.patch} (67%) diff --git a/patches/server-remapped/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/removed/1.17/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch similarity index 99% rename from patches/server-remapped/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch rename to patches/removed/1.17/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch index c64155c42a..2ebcfe75f1 100644 --- a/patches/server-remapped/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch +++ b/patches/removed/1.17/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch @@ -22,6 +22,8 @@ view distance holds on you. Chunks in front of the player have higher priority, to help with fast traveling players keep up with their movement. +1.17 update note: very big diff skipping for now, still needs to be updated + diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java index 499aff1f1e1ffc01ba8f9de43ca17899525a306f..97b85587525ddb62af9bfc8785b48727a6135599 100644 --- a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java diff --git a/patches/server-remapped/0488-Improve-Chunk-Status-Transition-Speed.patch b/patches/removed/1.17/0488-Improve-Chunk-Status-Transition-Speed.patch similarity index 98% rename from patches/server-remapped/0488-Improve-Chunk-Status-Transition-Speed.patch rename to patches/removed/1.17/0488-Improve-Chunk-Status-Transition-Speed.patch index 38e09f9701..56552887af 100644 --- a/patches/server-remapped/0488-Improve-Chunk-Status-Transition-Speed.patch +++ b/patches/removed/1.17/0488-Improve-Chunk-Status-Transition-Speed.patch @@ -3,6 +3,10 @@ From: Aikar Date: Fri, 29 May 2020 23:32:14 -0400 Subject: [PATCH] Improve Chunk Status Transition Speed + +1.17 Update note: Depends on not yet applied patch: Implement Chunk Priority / Urgency System for Chunks + + When a chunk is loaded from disk that has already been generated, the server has to promote the chunk through the system to reach it's current desired status level. diff --git a/patches/server-remapped/0491-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/patches/server-remapped/0491-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch deleted file mode 100644 index 356dcc464b..0000000000 --- a/patches/server-remapped/0491-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 7 Jun 2020 19:25:13 -0400 -Subject: [PATCH] Use seed based lookup for Treasure Maps - Fixes lag from - carto/sunken maps - - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index bf4e50cd1d561456c033cda2d5c5487c5e3fe1eb..61aee2c109614a014149ae5a15ad2a28c796cb9d 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -415,8 +415,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.worldDataServer.setThundering(thundering); - } - -- @Override -- public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { -+ public Biome getBiomeBySeed(int i, int j, int k) { return getUncachedNoiseBiome(i, j, k); } // Paper - OBFHELPER -+ @Override public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { - return this.getChunkSource().getGenerator().getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ); - } - -diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java -index 05759dc6edaa790a5e3f2ca2e0ae27e53cfa4397..550892bc769a58991583b16295a72a162ceea788 100644 ---- a/src/main/java/net/minecraft/world/item/MapItem.java -+++ b/src/main/java/net/minecraft/world/item/MapItem.java -@@ -252,7 +252,7 @@ public class MapItem extends ComplexItem { - - for (l = 0; l < 128 * i; ++l) { - for (i1 = 0; i1 < 128 * i; ++i1) { -- abiomebase[l * 128 * i + i1] = worldserver.getBiome(new BlockPos((j / i - 64) * i + i1, 0, (k / i - 64) * i + l)); -+ abiomebase[l * 128 * i + i1] = worldserver.getBiomeBySeed((j / i - 64) * i + i1, 0, (k / i - 64) * i + l); // Paper - } - } - diff --git a/patches/server/0366-implement-optional-per-player-mob-spawns.patch b/patches/server/0366-implement-optional-per-player-mob-spawns.patch index 5b3eeae286..c999eb08be 100644 --- a/patches/server/0366-implement-optional-per-player-mob-spawns.patch +++ b/patches/server/0366-implement-optional-per-player-mob-spawns.patch @@ -665,7 +665,7 @@ index bffc897cb88a54c36432c98264f3416051aeab17..14a0190ea5e9a387582736bb130c16a3 // Yes, this doesn't match Vanilla, but it's the best we can do for now. diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 19d0ed5ff8569b0280117750f9ce05095afd9f70..490ff09c3c4f93dcafc1703b1df3fb2f7333add2 100644 +index 19d0ed5ff8569b0280117750f9ce05095afd9f70..55b937f802ee7066cb13b9a497932038b2905ff0 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java @@ -17,6 +17,7 @@ import net.minecraft.core.Registry; @@ -778,7 +778,15 @@ index 19d0ed5ff8569b0280117750f9ce05095afd9f70..490ff09c3c4f93dcafc1703b1df3fb2f int k = 0; while (k < 3) { -@@ -248,7 +289,7 @@ public final class NaturalSpawner { +@@ -241,14 +282,14 @@ public final class NaturalSpawner { + // Paper start + Boolean doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); + if (doSpawning == null) { +- return; ++ return j; // Paper + } + if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { + // Paper end Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type); if (entityinsentient == null) { diff --git a/patches/server-remapped/0487-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/patches/server/0441-Optimize-sending-packets-to-nearby-locations-sounds-.patch similarity index 92% rename from patches/server-remapped/0487-Optimize-sending-packets-to-nearby-locations-sounds-.patch rename to patches/server/0441-Optimize-sending-packets-to-nearby-locations-sounds-.patch index e8add9864d..ec9d2a1f08 100644 --- a/patches/server-remapped/0487-Optimize-sending-packets-to-nearby-locations-sounds-.patch +++ b/patches/server/0441-Optimize-sending-packets-to-nearby-locations-sounds-.patch @@ -11,10 +11,10 @@ This will drastically cut down on packet sending cost for worlds with lots of players in them. diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 168895dab31a0d5356eb96f2642399a1c99fccab..713cc88dd067c0d918f253b1845f42c0d9eb920f 100644 +index c4242a1602bbb02541c330bc02016f15c8644358..7eb3088d47ff78198e01a3a12b0ce6abe9d6ca6b 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1149,16 +1149,40 @@ public abstract class PlayerList { +@@ -1129,16 +1129,40 @@ public abstract class PlayerList { } public void broadcast(@Nullable net.minecraft.world.entity.player.Player player, double x, double y, double z, double distance, ResourceKey worldKey, Packet packet) { @@ -32,7 +32,7 @@ index 168895dab31a0d5356eb96f2642399a1c99fccab..713cc88dd067c0d918f253b1845f42c0 + if (world == null) { + world = server.getLevel(worldKey); + } -+ ChunkMap chunkMap = world != null ? world.getChunkSource().chunkMap : null; ++ net.minecraft.server.level.ChunkMap chunkMap = world != null ? world.getChunkSource().chunkMap : null; + Object[] backingSet; + if (chunkMap == null) { + // Really shouldn't happen... diff --git a/patches/server-remapped/0489-Fix-villager-trading-demand-MC-163962.patch b/patches/server/0442-Fix-villager-trading-demand-MC-163962.patch similarity index 90% rename from patches/server-remapped/0489-Fix-villager-trading-demand-MC-163962.patch rename to patches/server/0442-Fix-villager-trading-demand-MC-163962.patch index 65b79cf458..6e2a6230a6 100644 --- a/patches/server-remapped/0489-Fix-villager-trading-demand-MC-163962.patch +++ b/patches/server/0442-Fix-villager-trading-demand-MC-163962.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Fix villager trading demand - MC-163962 Prevent demand from going negative and tending to negative infinity diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java -index 9ce1c1092970618a204f87c673144152afbade99..fa74813e0fe76612023830b2fc41d41aa0b4f10e 100644 +index 3a59f610145504a096ccf4793ea4140120b00f48..75827fcad36a551d832f4be094167936092b6caf 100644 --- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java +++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java @@ -109,7 +109,7 @@ public class MerchantOffer { diff --git a/patches/server-remapped/0490-Maps-shouldn-t-load-chunks.patch b/patches/server/0443-Maps-shouldn-t-load-chunks.patch similarity index 91% rename from patches/server-remapped/0490-Maps-shouldn-t-load-chunks.patch rename to patches/server/0443-Maps-shouldn-t-load-chunks.patch index 186fc75fa9..9b2e431c37 100644 --- a/patches/server-remapped/0490-Maps-shouldn-t-load-chunks.patch +++ b/patches/server/0443-Maps-shouldn-t-load-chunks.patch @@ -15,10 +15,10 @@ Previously maps would load all chunks in a certain radius depending on five ticks that movement occur in anyways. diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java -index 1736d2eb33e5f2221210a0a4f3ceb8905555a162..05759dc6edaa790a5e3f2ca2e0ae27e53cfa4397 100644 +index 044111a5ea88d3f938c08b027ac6836355eff7c2..994a3c0253c7298fef1471736b74bd34ec87738a 100644 --- a/src/main/java/net/minecraft/world/item/MapItem.java +++ b/src/main/java/net/minecraft/world/item/MapItem.java -@@ -119,9 +119,9 @@ public class MapItem extends ComplexItem { +@@ -132,9 +132,9 @@ public class MapItem extends ComplexItem { int k2 = (j / i + k1 - 64) * i; int l2 = (k / i + l1 - 64) * i; Multiset multiset = LinkedHashMultiset.create(); diff --git a/patches/server/0444-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/patches/server/0444-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch new file mode 100644 index 0000000000..dc402ab882 --- /dev/null +++ b/patches/server/0444-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 7 Jun 2020 19:25:13 -0400 +Subject: [PATCH] Use seed based lookup for Treasure Maps - Fixes lag from + carto/sunken maps + + +diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java +index 994a3c0253c7298fef1471736b74bd34ec87738a..305c0b0ca23eea6b8b32778a4bbe8a2eacc78107 100644 +--- a/src/main/java/net/minecraft/world/item/MapItem.java ++++ b/src/main/java/net/minecraft/world/item/MapItem.java +@@ -258,7 +258,7 @@ public class MapItem extends ComplexItem { + + for (l = 0; l < 128 * i; ++l) { + for (i1 = 0; i1 < 128 * i; ++i1) { +- abiomebase[l * 128 * i + i1] = world.getBiome(new BlockPos((j / i - 64) * i + i1, 0, (k / i - 64) * i + l)); ++ abiomebase[l * 128 * i + i1] = world.getUncachedNoiseBiome((j / i - 64) * i + i1, 0, (k / i - 64) * i + l); // Paper + } + } + diff --git a/patches/server-remapped/0492-Optimize-Bit-Operations-by-inlining.patch b/patches/server/0445-Optimize-Bit-Operations-by-inlining.patch similarity index 67% rename from patches/server-remapped/0492-Optimize-Bit-Operations-by-inlining.patch rename to patches/server/0445-Optimize-Bit-Operations-by-inlining.patch index f1615b3c0b..0dcb98cfb4 100644 --- a/patches/server-remapped/0492-Optimize-Bit-Operations-by-inlining.patch +++ b/patches/server/0445-Optimize-Bit-Operations-by-inlining.patch @@ -7,25 +7,26 @@ Inline bit operations and reduce instruction count to make these hot operations faster diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 595abf528a7862478100770987906af1b13439fe..727af6ac84075db87615ebac51a024e6376fa3cb 100644 +index dd1d76867ac3832ad515f304925c595c9a021c8f..fd5c22a3d281d8d913c353c8a668ec51b885066a 100644 --- a/src/main/java/net/minecraft/core/BlockPos.java +++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -31,14 +31,16 @@ public class BlockPos extends Vec3i { +@@ -30,15 +30,16 @@ public class BlockPos extends Vec3i { }).stable(); private static final Logger LOGGER = LogManager.getLogger(); public static final BlockPos ZERO = new BlockPos(0, 0, 0); - private static final int PACKED_X_LENGTH = 1 + Mth.log2(Mth.smallestEncompassingPowerOfTwo(30000000)); -- private static final int PACKED_Z_LENGTH = BlockPos.PACKED_X_LENGTH; -- private static final int PACKED_Y_LENGTH = 64 - BlockPos.PACKED_X_LENGTH - BlockPos.PACKED_Z_LENGTH; -- private static final long PACKED_X_MASK = (1L << BlockPos.PACKED_X_LENGTH) - 1L; -- private static final long PACKED_Y_MASK = (1L << BlockPos.PACKED_Y_LENGTH) - 1L; -- private static final long PACKED_Z_MASK = (1L << BlockPos.PACKED_Z_LENGTH) - 1L; -- private static final int Z_OFFSET = BlockPos.PACKED_Y_LENGTH; -- private static final int X_OFFSET = BlockPos.PACKED_Y_LENGTH + BlockPos.PACKED_Z_LENGTH; +- private static final int PACKED_Z_LENGTH = PACKED_X_LENGTH; +- public static final int PACKED_Y_LENGTH = 64 - PACKED_X_LENGTH - PACKED_Z_LENGTH; +- private static final long PACKED_X_MASK = (1L << PACKED_X_LENGTH) - 1L; +- private static final long PACKED_Y_MASK = (1L << PACKED_Y_LENGTH) - 1L; +- private static final long PACKED_Z_MASK = (1L << PACKED_Z_LENGTH) - 1L; +- private static final int Y_OFFSET = 0; +- private static final int Z_OFFSET = PACKED_Y_LENGTH; +- private static final int X_OFFSET = PACKED_Y_LENGTH + PACKED_Z_LENGTH; + // Paper start - static constants + private static final int PACKED_X_LENGTH = 26; + private static final int PACKED_Z_LENGTH = 26; -+ private static final int PACKED_Y_LENGTH = 12; ++ public static final int PACKED_Y_LENGTH = 12; + private static final long PACKED_X_MASK = 67108863; + private static final long PACKED_Y_MASK = 4095; + private static final long PACKED_Z_MASK = 67108863; @@ -35,7 +36,7 @@ index 595abf528a7862478100770987906af1b13439fe..727af6ac84075db87615ebac51a024e6 public BlockPos(int x, int y, int z) { super(x, y, z); -@@ -60,28 +62,29 @@ public class BlockPos extends Vec3i { +@@ -60,28 +61,29 @@ public class BlockPos extends Vec3i { this(pos.getX(), pos.getY(), pos.getZ()); } @@ -50,17 +51,17 @@ index 595abf528a7862478100770987906af1b13439fe..727af6ac84075db87615ebac51a024e6 } public static int getX(long packedPos) { -- return (int) (packedPos << 64 - BlockPos.X_OFFSET - BlockPos.PACKED_X_LENGTH >> 64 - BlockPos.PACKED_X_LENGTH); +- return (int)(packedPos << 64 - X_OFFSET - PACKED_X_LENGTH >> 64 - PACKED_X_LENGTH); + return (int) (packedPos >> 38); // Paper - simplify/inline } public static int getY(long packedPos) { -- return (int) (packedPos << 64 - BlockPos.PACKED_Y_LENGTH >> 64 - BlockPos.PACKED_Y_LENGTH); +- return (int)(packedPos << 64 - PACKED_Y_LENGTH >> 64 - PACKED_Y_LENGTH); + return (int) ((packedPos << 52) >> 52); // Paper - simplify/inline } public static int getZ(long packedPos) { -- return (int) (packedPos << 64 - BlockPos.Z_OFFSET - BlockPos.PACKED_Z_LENGTH >> 64 - BlockPos.PACKED_Z_LENGTH); +- return (int)(packedPos << 64 - Z_OFFSET - PACKED_Z_LENGTH >> 64 - PACKED_Z_LENGTH); + return (int) ((packedPos << 26) >> 38); // Paper - simplify/inline } @@ -70,25 +71,23 @@ index 595abf528a7862478100770987906af1b13439fe..727af6ac84075db87615ebac51a024e6 } public long asLong() { -@@ -90,12 +93,7 @@ public class BlockPos extends Vec3i { +@@ -89,10 +91,7 @@ public class BlockPos extends Vec3i { + } - public static long asLong(int x, int y, int z) { return asLong(x, y, z); } // Paper - OBFHELPER public static long asLong(int x, int y, int z) { - long l = 0L; -- -- l |= ((long) x & BlockPos.PACKED_X_MASK) << BlockPos.X_OFFSET; -- l |= ((long) y & BlockPos.PACKED_Y_MASK) << 0; -- l |= ((long) z & BlockPos.PACKED_Z_MASK) << BlockPos.Z_OFFSET; -- return l; +- l = l | ((long)x & PACKED_X_MASK) << X_OFFSET; +- l = l | ((long)y & PACKED_Y_MASK) << 0; +- return l | ((long)z & PACKED_Z_MASK) << Z_OFFSET; + return (((long) x & (long) 67108863) << 38) | (((long) y & (long) 4095)) | (((long) z & (long) 67108863) << 12); // Paper - inline constants and simplify } public static long getFlatIndex(long y) { diff --git a/src/main/java/net/minecraft/core/SectionPos.java b/src/main/java/net/minecraft/core/SectionPos.java -index 700e0d7b132242bd65d13ec61c1f7036905b2767..c4bf1bc383fbdfb8ec997883aececde38206c7dd 100644 +index 4ea92289304bdad469e67164442bc0b837183e8a..b0c39895e10fab5acc609128d34aafdebc5520f9 100644 --- a/src/main/java/net/minecraft/core/SectionPos.java +++ b/src/main/java/net/minecraft/core/SectionPos.java -@@ -19,7 +19,7 @@ public class SectionPos extends Vec3i { +@@ -37,7 +37,7 @@ public class SectionPos extends Vec3i { } public static SectionPos of(BlockPos pos) { @@ -97,7 +96,7 @@ index 700e0d7b132242bd65d13ec61c1f7036905b2767..c4bf1bc383fbdfb8ec997883aececde3 } public static SectionPos of(ChunkPos chunkPos, int y) { -@@ -31,15 +31,23 @@ public class SectionPos extends Vec3i { +@@ -49,7 +49,7 @@ public class SectionPos extends Vec3i { } public static SectionPos of(long packed) { @@ -105,7 +104,8 @@ index 700e0d7b132242bd65d13ec61c1f7036905b2767..c4bf1bc383fbdfb8ec997883aececde3 + return new SectionPos((int) (packed >> 42), (int) (packed << 44 >> 44), (int) (packed << 22 >> 42)); // Paper } - public static long offset(long packed, Direction direction) { + public static SectionPos bottomOf(ChunkAccess chunk) { +@@ -60,8 +60,16 @@ public class SectionPos extends Vec3i { return offset(packed, direction.getStepX(), direction.getStepY(), direction.getStepZ()); } @@ -122,48 +122,45 @@ index 700e0d7b132242bd65d13ec61c1f7036905b2767..c4bf1bc383fbdfb8ec997883aececde3 + return (((long) ((int) (packed >> 42) + x) & 4194303L) << 42) | (((long) ((int) (packed << 44 >> 44) + y) & 1048575L)) | (((long) ((int) (packed << 22 >> 42) + z) & 4194303L) << 20); // Simplify to reduce instruction count } - public static int blockToSectionCoord(int coord) { -@@ -51,11 +59,7 @@ public class SectionPos extends Vec3i { + public static int posToSectionCoord(double coord) { +@@ -77,10 +85,7 @@ public class SectionPos extends Vec3i { } public static short sectionRelativePos(BlockPos pos) { - int i = sectionRelative(pos.getX()); - int j = sectionRelative(pos.getY()); - int k = sectionRelative(pos.getZ()); -- -- return (short) (i << 8 | k << 4 | j << 0); +- return (short)(i << 8 | k << 4 | j << 0); + return (short) ((pos.getX() & 15) << 8 | (pos.getZ() & 15) << 4 | pos.getY() & 15); // Paper - simplify/inline } public static int sectionRelativeX(short packedLocalPos) { -@@ -114,16 +118,16 @@ public class SectionPos extends Vec3i { +@@ -143,16 +148,16 @@ public class SectionPos extends Vec3i { return this.getZ(); } - public int minBlockX() { -- return this.x() << 4; -+ public final int minBlockX() { // Paper -+ return this.getX() << 4; // Paper +- return sectionToBlockCoord(this.x()); ++ public final int minBlockX() { // Paper - make final ++ return this.getX() << 4; // Paper - inline } - public int minBlockY() { -- return this.y() << 4; -+ public final int minBlockY() { // Paper -+ return this.getY() << 4; // Paper +- return sectionToBlockCoord(this.y()); ++ public final int minBlockY() { // Paper - make final ++ return this.getY() << 4; // Paper - inline } - public int minBlockZ() { -- return this.z() << 4; -+ public final int minBlockZ() { // Paper -+ return this.getZ() << 4; // Paper +- return sectionToBlockCoord(this.z()); ++ public int minBlockZ() { // Paper - make final ++ return this.getZ() << 4; // Paper - inline } public int maxBlockX() { -@@ -138,8 +142,10 @@ public class SectionPos extends Vec3i { - return (this.z() << 4) + 15; +@@ -168,7 +173,8 @@ public class SectionPos extends Vec3i { } -+ public static long blockToSection(long i) { return blockToSection(i); } // Paper - OBFHELPER public static long blockToSection(long blockPos) { - return asLong(blockToSectionCoord(BlockPos.getX(blockPos)), blockToSectionCoord(BlockPos.getY(blockPos)), blockToSectionCoord(BlockPos.getZ(blockPos))); + // b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); @@ -171,8 +168,8 @@ index 700e0d7b132242bd65d13ec61c1f7036905b2767..c4bf1bc383fbdfb8ec997883aececde3 } public static long getZeroNode(long pos) { -@@ -160,17 +166,18 @@ public class SectionPos extends Vec3i { - return new ChunkPos(this.x(), this.z()); +@@ -192,15 +198,18 @@ public class SectionPos extends Vec3i { + return asLong(blockToSectionCoord(pos.getX()), blockToSectionCoord(pos.getY()), blockToSectionCoord(pos.getZ())); } + // Paper start @@ -180,14 +177,12 @@ index 700e0d7b132242bd65d13ec61c1f7036905b2767..c4bf1bc383fbdfb8ec997883aececde3 + return (((long) (i >> 4) & 4194303L) << 42) | (((long) (j >> 4) & 1048575L)) | (((long) (k >> 4) & 4194303L) << 20); + } + // Paper end -+ public static long asLong(int i, int j, int k) { return asLong(i, j, k); } // Paper - OBFHELPER ++ public static long asLong(int x, int y, int z) { - long l = 0L; -- -- l |= ((long) x & 4194303L) << 42; -- l |= ((long) y & 1048575L) << 0; -- l |= ((long) z & 4194303L) << 20; -- return l; +- l = l | ((long)x & 4194303L) << 42; +- l = l | ((long)y & 1048575L) << 0; +- return l | ((long)z & 4194303L) << 20; + return (((long) x & 4194303L) << 42) | (((long) y & 1048575L)) | (((long) z & 4194303L) << 20); // Paper - Simplify to reduce instruction count } @@ -196,25 +191,23 @@ index 700e0d7b132242bd65d13ec61c1f7036905b2767..c4bf1bc383fbdfb8ec997883aececde3 + return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count } - public Stream blocksInside() { -@@ -178,18 +185,11 @@ public class SectionPos extends Vec3i { + @Override +@@ -213,16 +222,11 @@ public class SectionPos extends Vec3i { } public static Stream cube(SectionPos center, int radius) { -- int j = center.x(); -- int k = center.y(); -- int l = center.z(); -- -- return betweenClosedStream(j - radius, k - radius, l - radius, j + radius, k + radius, l + radius); +- int i = center.x(); +- int j = center.y(); +- int k = center.z(); +- return betweenClosedStream(i - radius, j - radius, k - radius, i + radius, j + radius, k + radius); + return betweenClosedStream(center.getX() - radius, center.getY() - radius, center.getZ() - radius, center.getX() + radius, center.getY() + radius, center.getZ() + radius); // Paper - simplify/inline } - public static Stream aroundChunk(ChunkPos center, int radius) { -- int j = center.x; -- int k = center.z; -- -- return betweenClosedStream(j - radius, 0, k - radius, j + radius, 15, k + radius); + public static Stream aroundChunk(ChunkPos center, int radius, int minY, int maxY) { +- int i = center.x; +- int j = center.z; +- return betweenClosedStream(i - radius, minY, j - radius, i + radius, maxY - 1, j + radius); + return betweenClosedStream(center.x - radius, 0, center.z - radius, center.x + radius, 15, center.z + radius); // Paper - simplify/inline } - public static Stream betweenClosedStream(final int minX, final int minY, final int minZ, final int maxX, final int maxY, final int maxZ) { + public static Stream betweenClosedStream(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { From 956fcad4eae4634de1177624743e758429be389e Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 23:56:15 -0700 Subject: [PATCH 103/226] Fix mojangapi build --- Paper-MojangAPI/build.gradle.kts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Paper-MojangAPI/build.gradle.kts b/Paper-MojangAPI/build.gradle.kts index e0ef6532b9..536b4577cf 100644 --- a/Paper-MojangAPI/build.gradle.kts +++ b/Paper-MojangAPI/build.gradle.kts @@ -1,6 +1,5 @@ plugins { `java-library` - checkstyle } java { @@ -17,10 +16,10 @@ dependencies { implementation(project(":Paper-API")) api("com.mojang:brigadier:1.0.18") - compileOnly("it.unimi.dsi:fastutil") + compileOnly("it.unimi.dsi:fastutil:8.2.2") compileOnly("org.jetbrains:annotations:18.0.0") testImplementation("junit:junit:4.13.1") testImplementation("org.hamcrest:hamcrest-library:1.3") testImplementation("org.ow2.asm:asm-tree:7.3.1") -} \ No newline at end of file +} From 4b2f4cbebbb06bcaf775f8b7a21930dad30cf1ab Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sun, 13 Jun 2021 22:34:40 -0700 Subject: [PATCH 104/226] Add back incremental chunk saving patch --- .../0446-incremental-chunk-saving.patch} | 185 ++++++++++-------- 1 file changed, 101 insertions(+), 84 deletions(-) rename patches/{removed/1.17/0363-incremental-chunk-saving.patch => server/0446-incremental-chunk-saving.patch} (64%) diff --git a/patches/removed/1.17/0363-incremental-chunk-saving.patch b/patches/server/0446-incremental-chunk-saving.patch similarity index 64% rename from patches/removed/1.17/0363-incremental-chunk-saving.patch rename to patches/server/0446-incremental-chunk-saving.patch index 70420b4593..8856801d1f 100644 --- a/patches/removed/1.17/0363-incremental-chunk-saving.patch +++ b/patches/server/0446-incremental-chunk-saving.patch @@ -2,17 +2,16 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Sun, 9 Jun 2019 03:53:22 +0100 Subject: [PATCH] incremental chunk saving -1.17: saved for MM + diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index ffe9b1a63d78925e1d77b9e730aef42fed6d58fa..1278d09f70c1e97607ef20d87a178dc252c7f723 100644 +index 3bc6329d3ea48966cb99e792f9b35e2d2d71a34b..ec51a9e19670888584e5324a57a47aa9c676d423 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -446,4 +446,19 @@ public class PaperWorldConfig { - keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); +@@ -47,6 +47,21 @@ public class PaperWorldConfig { log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); } -+ + + public int autoSavePeriod = -1; + private void autoSavePeriod() { + autoSavePeriod = getInt("auto-save-interval", -1); @@ -27,64 +26,65 @@ index ffe9b1a63d78925e1d77b9e730aef42fed6d58fa..1278d09f70c1e97607ef20d87a178dc2 + private void maxAutoSaveChunksPerTick() { + maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); + } - } ++ + private boolean getBoolean(String path, boolean def) { + config.addDefault("world-settings.default." + path, def); + return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path)); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0efe7024493f96bb54e7d8c1ea7b233a1b481a04..aab1a055c065d1f1a92461e4442ec2cdd8e0b347 100644 +index 11dbe48c8a8c29cd28d725c43505e326a6e626ff..363dcebb3b2d5a2512776a191f6716ed3d0e8aff 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -261,6 +261,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; + public boolean serverAutoSave = false; // Paper public Commands vanillaCommandDispatcher; - private boolean forceTicks; + public boolean forceTicks; // Paper // CraftBukkit end -@@ -1256,14 +1257,24 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % autosavePeriod == 0) { // CraftBukkit +- if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // CraftBukkit - MinecraftServer.LOGGER.debug("Autosave started"); -+ //if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down -+ //MinecraftServer.LOGGER.debug("Autosave started"); // Paper -+ serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper ++ // if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // CraftBukkit // Paper - move down ++ // MinecraftServer.LOGGER.debug("Autosave started"); // Paper ++ serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper this.profiler.push("save"); -+ if (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0) { // Paper ++ if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // Paper - moved from above this.playerList.saveAll(); - this.saveAllChunks(true, false, false); -+ }// Paper -+ // Paper start -+ for (ServerLevel world : getAllLevels()) { -+ if (world.paperConfig.autoSavePeriod > 0) { -+ world.saveIncrementally(serverAutoSave); -+ } -+ } -+ // Paper end -+ - this.profiler.pop(); +- this.profiler.pop(); - MinecraftServer.LOGGER.debug("Autosave finished"); -- } -+ //MinecraftServer.LOGGER.debug("Autosave finished"); // Paper ++ // this.saveAllChunks(true, false, false); // Paper - saved incrementally below ++ } // Paper start ++ for (ServerLevel level : this.getAllLevels()) { ++ if (level.paperConfig.autoSavePeriod > 0) { ++ level.saveIncrementally(this.serverAutoSave); ++ } + } ++ // Paper end ++ this.profiler.pop(); ++ // MinecraftServer.LOGGER.debug("Autosave finished"); // Paper + //} // Paper this.profiler.push("snooper"); if (((DedicatedServer) this).getProperties().snooperEnabled && !this.snooper.isStarted() && this.tickCount > 100) { // Spigot diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 7010e0a970462d2b2e1b5696a1a49dba9ea60935..491a9e78fdcec8c211499e8f48cceb829f1e5c8b 100644 +index 969b0c9cf6d7eb2055d3b804f25a3cbc161ceaea..1f67c9c5f7161ea687983e7ae0ec7d259da9acd3 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -66,6 +66,9 @@ public class ChunkHolder { - - private final ChunkMap chunkMap; // Paper - +@@ -111,6 +111,8 @@ public class ChunkHolder { + this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); + } + // Paper end - optimise isOutsideOfRange + long lastAutoSaveTime; // Paper - incremental autosave + long inactiveTimeStart; // Paper - incremental autosave -+ - public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); - this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; -@@ -421,7 +424,19 @@ public class ChunkHolder { +@@ -533,7 +535,19 @@ public class ChunkHolder { boolean flag2 = playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER); boolean flag3 = playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER); @@ -102,14 +102,14 @@ index 7010e0a970462d2b2e1b5696a1a49dba9ea60935..491a9e78fdcec8c211499e8f48cceb82 + } + // Paper end if (!flag2 && flag3) { - // Paper start - cache ticking ready status - int expectCreateCount = ++this.fullChunkCreateCount; -@@ -541,8 +556,32 @@ public class ChunkHolder { + int expectCreateCount = ++this.fullChunkCreateCount; // Paper + this.fullChunkFuture = chunkStorage.prepareAccessibleChunk(this); +@@ -654,9 +668,33 @@ public class ChunkHolder { } public void refreshAccessibility() { + boolean prev = this.wasAccessibleSinceLastSave; // Paper -+ this.wasAccessibleSinceLastSave = getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER); + this.wasAccessibleSinceLastSave = ChunkHolder.getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER); + // Paper start - incremental autosave + if (prev != this.wasAccessibleSinceLastSave) { + if (this.wasAccessibleSinceLastSave) { @@ -126,22 +126,23 @@ index 7010e0a970462d2b2e1b5696a1a49dba9ea60935..491a9e78fdcec8c211499e8f48cceb82 + } + } + // Paper end -+ } -+ + } + + // Paper start - incremental autosave + public boolean setHasBeenLoaded() { - this.wasAccessibleSinceLastSave = getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER); ++ this.wasAccessibleSinceLastSave = getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER); + return this.wasAccessibleSinceLastSave; - } ++ } + // Paper end - - public void replaceProtoChunk(ImposterProtoChunk protochunkextension) { ++ + public void replaceProtoChunk(ImposterProtoChunk chunk) { for (int i = 0; i < this.futures.length(); ++i) { + CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 0aac29de933c84c34cb24e204e8fcc7010060d8f..cfec04e12dfaeb8852dc129a6a7e68c61dac54b6 100644 +index d8f99f7f5ca0e1dbbb9b760af3a4b4f9c52ef6c7..5a5e9188f55405c8a2646891c348d544d33eb940 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -91,6 +91,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana +@@ -93,6 +93,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana import net.minecraft.world.level.storage.DimensionDataStorage; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.phys.Vec3; @@ -149,7 +150,7 @@ index 0aac29de933c84c34cb24e204e8fcc7010060d8f..cfec04e12dfaeb8852dc129a6a7e68c6 import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -@@ -378,6 +379,64 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -744,6 +745,64 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } @@ -212,30 +213,37 @@ index 0aac29de933c84c34cb24e204e8fcc7010060d8f..cfec04e12dfaeb8852dc129a6a7e68c6 + // Paper end + protected void saveAllChunks(boolean flush) { + Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) if (flush) { - List list = (List) this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); -@@ -488,6 +547,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -883,6 +942,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + asyncSaveData, chunk); + + chunk.setUnsaved(false); ++ chunk.setLastSaved(this.level.getGameTime()); // Paper - track last saved time + } + // Paper end + +@@ -905,6 +965,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.level.unload(chunk); } -+ this.autoSaveQueue.remove(playerchunk); // Paper ++ this.autoSaveQueue.remove(holder); // Paper - this.lightEngine.updateChunkStatus(ichunkaccess.getPos()); - this.lightEngine.tryScheduleUpdate(); -@@ -680,6 +740,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - playerchunk.replaceProtoChunk(new ImposterProtoChunk(chunk)); - } + // Paper start - async chunk saving + try { +@@ -1231,6 +1292,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (!chunk.isUnsaved()) { + return false; + } else { ++ chunk.setLastSaved(this.level.getGameTime()); // Paper - track save time + chunk.setUnsaved(false); + ChunkPos chunkcoordintpair = chunk.getPos(); -+ chunk.setLastSaveTime(this.level.getGameTime() - 1); // Paper - avoid autosaving newly generated/loaded chunks -+ - chunk.setFullStatus(() -> { - return ChunkHolder.getFullChunkStatus(playerchunk.getTicketLevel()); - }); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 1e8ac0110badbf2d1c2336168c3e11991667c782..c1aa40c01a80a8870478193b8cd7354b0d71045c 100644 +index 3faa808f41f057a9956c697ec1323330f5920b86..7ab28e9bd3f785838b7fa4ac5811c0e71cddcb61 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -558,6 +558,15 @@ public class ServerChunkCache extends ChunkSource { +@@ -671,6 +671,15 @@ public class ServerChunkCache extends ChunkSource { } // Paper - Timings } @@ -252,10 +260,10 @@ index 1e8ac0110badbf2d1c2336168c3e11991667c782..c1aa40c01a80a8870478193b8cd7354b public void close() throws IOException { // CraftBukkit start diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index b2ddf145ae9f581ec6820deb9cb6a98be87658d7..fd7ee4badb383ffb4347d62c00ea2dfa3d76fd12 100644 +index fd3159f7767faaa55ed49eba237e30a2dbd4fa92..9fb7345a8c3985aa3e0f4575d680b82379d2cc5a 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -882,6 +882,38 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1014,6 +1014,38 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos); } @@ -267,14 +275,14 @@ index b2ddf145ae9f581ec6820deb9cb6a98be87658d7..fd7ee4badb383ffb4347d62c00ea2dfa + org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); + } + -+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { ++ try (co.aikar.timings.Timing ignored = this.timings.worldSave.startTiming()) { + if (doFull) { -+ this.saveData(); ++ this.saveLevelData(); + } + -+ timings.worldSaveChunks.startTiming(); // Paper ++ this.timings.worldSaveChunks.startTiming(); // Paper + if (!this.noSave()) chunkproviderserver.saveIncrementally(); -+ timings.worldSaveChunks.stopTiming(); // Paper ++ this.timings.worldSaveChunks.stopTiming(); // Paper + + + // Copied from save() @@ -282,9 +290,9 @@ index b2ddf145ae9f581ec6820deb9cb6a98be87658d7..fd7ee4badb383ffb4347d62c00ea2dfa + if (doFull) { // Paper + ServerLevel worldserver1 = this; + -+ worldDataServer.setWorldBorder(worldserver1.getWorldBorder().createSettings()); -+ worldDataServer.setCustomBossEvents(this.server.getCustomBossEvents().save()); -+ convertable.saveDataTag(this.server.registryHolder, this.worldDataServer, this.server.getPlayerList().getSingleplayerData()); ++ this.serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings()); ++ this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save()); ++ this.convertable.saveDataTag(this.server.registryHolder, this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); + } + // CraftBukkit end + } @@ -294,24 +302,33 @@ index b2ddf145ae9f581ec6820deb9cb6a98be87658d7..fd7ee4badb383ffb4347d62c00ea2dfa public void save(@Nullable ProgressListener progressListener, boolean flush, boolean flag1) { ServerChunkCache chunkproviderserver = this.getChunkSource(); -@@ -912,6 +944,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index c0075d226331f32e470dae5bf1ce8d79e8b263dc..8ba782511b0a6c7859cbcf910ad742cbb9f599e5 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -29,6 +29,7 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { + return GameEventDispatcher.NOOP; } -+ private void saveData() { this.saveLevelData(); } // Paper - OBFHELPER - private void saveLevelData() { - if (this.dragonFight != null) { - this.worldDataServer.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit ++ default void setLastSaved(long ticks) {} + // Paper start + default boolean generateFlatBedrock() { + if (this instanceof ProtoChunk) { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 55872a17060a35b727a597bc414fecec3ada3515..419b4bf0549d798d52d73fbbd9de59313fc05eb1 100644 +index a63dc77db41dab79f03ef7384da55c1cdeca5d98..efb9c6fef915b43c9dd4468ead52aa36ea9e7ef3 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -80,7 +80,7 @@ public class LevelChunk implements ChunkAccess { +@@ -108,6 +108,13 @@ public class LevelChunk implements ChunkAccess { + private final ShortList[] postProcessing; private TickList blockTicks; private TickList liquidTicks; - private boolean lastSaveHadEntities; -- private long lastSaveTime; -+ public long lastSaveTime; // Paper ++ // Paper start - track last save time ++ public long lastSaveTime; ++ @Override ++ public void setLastSaved(long ticks) { ++ this.lastSaveTime = ticks; ++ } ++ // Paper end private volatile boolean unsaved; private long inhabitedTime; @Nullable From 405ab6388e4e0825d21438494cf7ca293618a572 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sun, 13 Jun 2021 23:41:01 -0700 Subject: [PATCH 105/226] add entity debug info patch back --- ...ies-option-to-debug-dupe-uuid-issues.patch | 133 ----------------- ...ies-option-to-debug-dupe-uuid-issues.patch | 139 ++++++++++++++++++ ...d-Early-Warning-Feature-to-WatchDog.patch} | 0 ...0245-Make-EnderDragon-implement-Mob.patch} | 0 ...6-Use-ConcurrentHashMap-in-JsonList.patch} | 0 ...7-Use-a-Queue-for-Queueing-Commands.patch} | 0 ...le-Entities-from-a-chunk-without-sn.patch} | 0 ...timize-BlockPosition-helper-methods.patch} | 0 ...fault-mob-spawn-range-and-water-ani.patch} | 0 ...tch => 0251-Slime-Pathfinder-Events.patch} | 0 ...e-speed-for-water-flowing-over-lava.patch} | 0 ...53-Optimize-CraftBlockData-Creation.patch} | 0 ...tch => 0254-Optimize-MappedRegistry.patch} | 0 ...ch => 0255-Add-PhantomPreSpawnEvent.patch} | 0 ....patch => 0256-Add-More-Creeper-API.patch} | 0 ...=> 0257-Inventory-removeItemAnySlot.patch} | 0 ...oadChunk-int-int-false-load-unconve.patch} | 0 ...9-Asynchronous-chunk-IO-and-loading.patch} | 10 +- ...ray-tracing-methods-to-LivingEntity.patch} | 0 ...-attack-cooldown-methods-for-Player.patch} | 0 ....patch => 0262-Improve-death-events.patch} | 0 ...w-chests-to-be-placed-with-NBT-data.patch} | 0 ...I.patch => 0264-Mob-Pathfinding-API.patch} | 0 ...nt-chunk-loading-from-Fluid-Flowing.patch} | 0 ...for-CanPlaceOn-and-CanDestroy-NBT-v.patch} | 0 ...nt-Mob-AI-Rules-from-Loading-Chunks.patch} | 0 ...ning-from-loading-generating-chunks.patch} | 0 ...t-furnace-cook-speed-multiplier-API.patch} | 0 ...rseException-in-Entity-and-TE-names.patch} | 0 ...=> 0271-Honor-EntityAgeable.ageLock.patch} | 0 ...le-connection-throttle-kick-message.patch} | 0 ...> 0273-Hook-into-CB-plugin-rewrites.patch} | 0 ...I.patch => 0274-Add-sun-related-API.patch} | 0 ...75-Add-LivingEntity-getTargetEntity.patch} | 4 +- ...Turtle-API.patch => 0276-Turtle-API.patch} | 0 ...her-worlds-for-shooter-of-projectil.patch} | 0 ...ator-target-events-and-improve-impl.patch} | 0 ...-Add-Velocity-IP-Forwarding-Support.patch} | 0 ...PI.patch => 0280-Add-more-Witch-API.patch} | 0 ...wned-for-Villager-Aggression-Config.patch} | 0 ...-Johnny.patch => 0282-Here-s-Johnny.patch} | 0 ...vent-players-from-moving-into-unloa.patch} | 0 ...4-Reset-players-airTicks-on-respawn.patch} | 4 +- ...after-profile-lookups-if-not-needed.patch} | 0 ...r-Thread-Pool-and-Thread-Priorities.patch} | 0 ...=> 0287-Optimize-World-Time-Updates.patch} | 0 ...tore-custom-InventoryHolder-support.patch} | 0 ...=> 0289-Use-Vanilla-Minecart-Speeds.patch} | 0 ...0290-Fix-SpongeAbsortEvent-handling.patch} | 0 ...-allow-digging-into-unloaded-chunks.patch} | 0 ...ult-permission-message-configurable.patch} | 0 ...revent-rayTrace-from-loading-chunks.patch} | 0 ...-Large-Packets-disconnecting-client.patch} | 0 ...ntity-dismount-during-teleportation.patch} | 10 +- ...I.patch => 0296-Add-more-Zombie-API.patch} | 0 ...mits.patch => 0297-Book-Size-Limits.patch} | 0 ...0298-Add-PlayerConnectionCloseEvent.patch} | 0 ...revent-Enderman-from-loading-chunks.patch} | 0 ...replace-OfflinePlayer-getLastPlayed.patch} | 0 ...ehicle-tracking-issue-on-disconnect.patch} | 0 ...nRetractEvent-for-all-empty-pistons.patch} | 0 ...remove-from-being-called-on-Players.patch} | 0 ...ent.patch => 0304-BlockDestroyEvent.patch} | 4 +- ...m-Shapeless-Custom-Crafting-Recipes.patch} | 0 ... 0306-Limit-Client-Sign-length-more.patch} | 0 ...onvertSigns-boolean-every-sign-save.patch} | 0 ...Manager-and-add-advanced-packet-sup.patch} | 0 ...e-Oversized-Tile-Entities-in-chunks.patch} | 0 ...-Fix-Whitelist-On-Off-inconsistency.patch} | 0 ...t-tick-at-start-of-drowning-process.patch} | 0 ...ggleEvent-when-whitelist-is-toggled.patch} | 0 ...ngth-when-serialising-BungeeCord-te.patch} | 0 ...=> 0314-Entity-getEntitySpawnReason.patch} | 20 +-- ...ty-Metadata-for-all-tracked-players.patch} | 33 ----- ...tch => 0316-Fire-event-on-GS4-query.patch} | 0 ...17-Implement-PlayerPostRespawnEvent.patch} | 0 ...for-pickupDelay-breaks-picking-up-i.patch} | 0 ...ts.patch => 0319-Server-Tick-Events.patch} | 0 ...320-PlayerDeathEvent-getItemsToKeep.patch} | 0 ...Optimize-Captured-TileEntity-Lookup.patch} | 4 +- ...API.patch => 0322-Add-Heightmap-API.patch} | 0 ...> 0323-Mob-Spawner-API-Enhancements.patch} | 0 ...-to-changed-postToMainThread-method.patch} | 0 ...-item-frames-are-modified-MC-123450.patch} | 0 ...sPrimaryThread-and-MinecraftServer-.patch} | 0 ...27-improve-CraftWorld-isChunkLoaded.patch} | 0 ...e-Keep-Spawn-Loaded-range-per-world.patch} | 4 +- ....patch => 0329-ChunkMapDistance-CME.patch} | 0 ...0330-Implement-CraftBlockSoundGroup.patch} | 0 ...d.patch => 0331-Chunk-debug-command.patch} | 2 +- ...32-Fix-World-isChunkGenerated-calls.patch} | 0 ...te-location-if-we-failed-to-read-it.patch} | 0 ...l-Spawned-mobs-towards-natural-spaw.patch} | 0 ...urable-projectile-relative-velocity.patch} | 0 ...h => 0336-offset-item-frame-ticking.patch} | 0 ...f-we-have-a-custom-Bukkit-generator.patch} | 0 ...-158900.patch => 0338-Fix-MC-158900.patch} | 0 ...event-consuming-the-wrong-itemstack.patch} | 0 ...gs.patch => 0340-Generator-Settings.patch} | 0 ...-161754.patch => 0341-Fix-MC-161754.patch} | 0 ...anging-entities-that-are-not-ItemFr.patch} | 0 ...43-Expose-the-internal-current-tick.patch} | 0 ...sneak-when-changing-worlds-MC-10657.patch} | 0 ...-option-to-disable-pillager-patrols.patch} | 0 ...r-when-player-hand-set-to-empty-typ.patch} | 0 ...k-loads-when-villagers-try-to-find-.patch} | 0 ...656-Fix-Follow-Range-Initial-Target.patch} | 0 ...pers.patch => 0349-Optimize-Hoppers.patch} | 0 ...ayerDeathEvent-shouldDropExperience.patch} | 0 ...ading-chunks-checking-hive-position.patch} | 0 ...hunks-from-Hoppers-and-other-things.patch} | 0 ...ializing-mismatching-chunk-coordina.patch} | 0 ...imise-IEntityAccess-getPlayerByUUID.patch} | 4 +- ...355-Fix-items-not-falling-correctly.patch} | 0 ...patch => 0356-Lag-compensate-eating.patch} | 0 ...ize-call-to-getFluid-for-explosions.patch} | 0 ...-in-stack-not-having-effects-when-d.patch} | 0 ...Add-effect-to-block-break-naturally.patch} | 0 ...=> 0360-Entity-Activation-Range-2.0.patch} | 26 ++-- ...h => 0361-Increase-Light-Queue-Size.patch} | 0 ...and.patch => 0362-Fix-Light-Command.patch} | 0 ...o-Tick-view-distance-implementation.patch} | 4 +- ...ement-alternative-item-despawn-rate.patch} | 0 ...=> 0365-Tracking-Range-Improvements.patch} | 0 ...-items-vanishing-through-end-portal.patch} | 4 +- ...ment-optional-per-player-mob-spawns.patch} | 0 ...et-gravity-in-void.-Fixes-MC-167279.patch} | 0 ...-getChunkAt-calls-for-loaded-chunks.patch} | 0 ...w-overriding-the-java-version-check.patch} | 0 ...tch => 0371-Add-ThrownEggHatchEvent.patch} | 0 ... 0372-Optimise-random-block-ticking.patch} | 12 +- ...p-API.patch => 0373-Entity-Jump-API.patch} | 0 ...-to-nerf-pigmen-from-nether-portals.patch} | 8 +- ... => 0375-Make-the-GUI-graph-fancier.patch} | 0 ...76-add-hand-to-BlockMultiPlaceEvent.patch} | 0 ...7-Prevent-teleporting-dead-entities.patch} | 0 ...ipwire-hook-placement-before-update.patch} | 0 ...o-allow-iron-golems-to-spawn-in-air.patch} | 0 ...chance-of-villager-zombie-infection.patch} | 0 ...tch => 0381-Optimise-Chunk-getFluid.patch} | 0 ...mise-TickListServer-by-rewriting-it.patch} | 8 +- ...pawn-settings-and-per-player-option.patch} | 0 ...nections-shouldn-t-hold-up-shutdown.patch} | 0 ...ow-bees-to-load-chunks-for-beehives.patch} | 0 ...PlayerChunkMap-adds-crashing-server.patch} | 6 +- ...timize-Collision-to-not-load-chunks.patch} | 4 +- ...tch => 0388-Don-t-tick-dead-players.patch} | 0 ...-Player-s-shouldn-t-be-able-to-move.patch} | 0 ...unkMap-memory-use-for-visibleChunks.patch} | 0 ...sks-Speed-up-processing-of-chunk-lo.patch} | 8 +- ...ove-existing-players-to-world-spawn.patch} | 0 ...Add-tick-times-API-and-mspt-command.patch} | 0 ...94-Expose-MinecraftServer-isRunning.patch} | 0 ...dd-Raw-Byte-ItemStack-Serialization.patch} | 0 ...6-Remove-streams-from-Mob-AI-System.patch} | 0 ... => 0397-Async-command-map-building.patch} | 0 ...h => 0398-Improved-Watchdog-Support.patch} | 4 +- ....patch => 0399-Optimize-Pathfinding.patch} | 0 ...0-Reduce-Either-Optional-allocation.patch} | 0 ...401-Remove-streams-from-PairedQueue.patch} | 0 ...-memory-footprint-of-NBTTagCompound.patch} | 0 ...ent-opening-inventories-when-frozen.patch} | 0 ...04-Optimise-ArraySetSorted-removeIf.patch} | 0 ...entity-collision-code-if-not-needed.patch} | 0 ...teleport-command-to-valid-locations.patch} | 0 ...Implement-Player-Client-Options-API.patch} | 0 ...Chunk-Post-Processing-deadlock-risk.patch} | 0 ...ayer-is-attempted-to-be-removed-fro.patch} | 0 ...0-Broadcast-join-message-to-console.patch} | 0 ...-Broken-behavior-of-PlayerJoinEvent.patch} | 0 ...oad-Chunks-for-Login-Asynchronously.patch} | 4 +- ...awn-point-if-spawn-in-unloaded-worl.patch} | 4 +- ...layerAttackEntityCooldownResetEvent.patch} | 0 ...llbacks-to-schedule-for-Callback-Ex.patch} | 0 ...-fire-BlockFade-on-worldgen-threads.patch} | 0 ...tom-creative-and-insomniac-controls.patch} | 0 ...-duplication-issues-and-teleport-is.patch} | 12 +- ...0419-Implement-Brigadier-Mojang-API.patch} | 0 ...patch => 0420-Villager-Restocks-API.patch} | 0 ...ickItem-Packet-and-kick-for-invalid.patch} | 0 ...n.patch => 0422-Expose-game-version.patch} | 0 ...> 0423-Optimize-Voxel-Shape-Merging.patch} | 0 ...per-thread-native-byte-buffer-cache.patch} | 0 ...atch => 0425-Implement-Mob-Goal-API.patch} | 0 ...ance-map-to-optimise-entity-tracker.patch} | 4 +- ...isOutsideRange-to-use-distance-maps.patch} | 0 ...=> 0428-Add-villager-reputation-API.patch} | 0 ...maximum-exp-value-when-merging-orbs.patch} | 0 ...tch => 0430-ExperienceOrbMergeEvent.patch} | 0 ...-Fix-PotionEffect-ignores-icon-flag.patch} | 0 ...brigadier-child-sorting-performance.patch} | 0 ...API.patch => 0433-Potential-bed-API.patch} | 0 ...ait-for-Async-Tasks-during-shutdown.patch} | 0 ...er-respects-game-and-entity-rules-f.patch} | 0 ...nd-End-Portal-Frames-from-being-des.patch} | 4 +- ...leInt-allocations-from-light-engine.patch} | 0 ...location-of-Vec3D-by-entity-tracker.patch} | 0 ...> 0439-Ensure-safe-gateway-teleport.patch} | 0 ...-for-console-having-all-permissions.patch} | 0 ...n-Full-Status-Chunk-NBT-Memory-Leak.patch} | 0 ...packets-to-nearby-locations-sounds-.patch} | 0 ...x-villager-trading-demand-MC-163962.patch} | 0 ... => 0444-Maps-shouldn-t-load-chunks.patch} | 0 ...okup-for-Treasure-Maps-Fixes-lag-fr.patch} | 0 ...Optimize-Bit-Operations-by-inlining.patch} | 0 ...ch => 0447-incremental-chunk-saving.patch} | 4 +- 206 files changed, 230 insertions(+), 257 deletions(-) delete mode 100644 patches/removed/1.17/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch create mode 100644 patches/server/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch rename patches/server/{0243-Add-Early-Warning-Feature-to-WatchDog.patch => 0244-Add-Early-Warning-Feature-to-WatchDog.patch} (100%) rename patches/server/{0244-Make-EnderDragon-implement-Mob.patch => 0245-Make-EnderDragon-implement-Mob.patch} (100%) rename patches/server/{0245-Use-ConcurrentHashMap-in-JsonList.patch => 0246-Use-ConcurrentHashMap-in-JsonList.patch} (100%) rename patches/server/{0246-Use-a-Queue-for-Queueing-Commands.patch => 0247-Use-a-Queue-for-Queueing-Commands.patch} (100%) rename patches/server/{0247-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch => 0248-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch} (100%) rename patches/server/{0248-Optimize-BlockPosition-helper-methods.patch => 0249-Optimize-BlockPosition-helper-methods.patch} (100%) rename patches/server/{0249-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch => 0250-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch} (100%) rename patches/server/{0250-Slime-Pathfinder-Events.patch => 0251-Slime-Pathfinder-Events.patch} (100%) rename patches/server/{0251-Configurable-speed-for-water-flowing-over-lava.patch => 0252-Configurable-speed-for-water-flowing-over-lava.patch} (100%) rename patches/server/{0252-Optimize-CraftBlockData-Creation.patch => 0253-Optimize-CraftBlockData-Creation.patch} (100%) rename patches/server/{0253-Optimize-MappedRegistry.patch => 0254-Optimize-MappedRegistry.patch} (100%) rename patches/server/{0254-Add-PhantomPreSpawnEvent.patch => 0255-Add-PhantomPreSpawnEvent.patch} (100%) rename patches/server/{0255-Add-More-Creeper-API.patch => 0256-Add-More-Creeper-API.patch} (100%) rename patches/server/{0256-Inventory-removeItemAnySlot.patch => 0257-Inventory-removeItemAnySlot.patch} (100%) rename patches/server/{0257-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch => 0258-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch} (100%) rename patches/server/{0258-Asynchronous-chunk-IO-and-loading.patch => 0259-Asynchronous-chunk-IO-and-loading.patch} (99%) rename patches/server/{0259-Add-ray-tracing-methods-to-LivingEntity.patch => 0260-Add-ray-tracing-methods-to-LivingEntity.patch} (100%) rename patches/server/{0260-Expose-attack-cooldown-methods-for-Player.patch => 0261-Expose-attack-cooldown-methods-for-Player.patch} (100%) rename patches/server/{0261-Improve-death-events.patch => 0262-Improve-death-events.patch} (100%) rename patches/server/{0262-Allow-chests-to-be-placed-with-NBT-data.patch => 0263-Allow-chests-to-be-placed-with-NBT-data.patch} (100%) rename patches/server/{0263-Mob-Pathfinding-API.patch => 0264-Mob-Pathfinding-API.patch} (100%) rename patches/server/{0264-Prevent-chunk-loading-from-Fluid-Flowing.patch => 0265-Prevent-chunk-loading-from-Fluid-Flowing.patch} (100%) rename patches/server/{0265-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch => 0266-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch} (100%) rename patches/server/{0266-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch => 0267-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch} (100%) rename patches/server/{0267-Prevent-mob-spawning-from-loading-generating-chunks.patch => 0268-Prevent-mob-spawning-from-loading-generating-chunks.patch} (100%) rename patches/server/{0268-Implement-furnace-cook-speed-multiplier-API.patch => 0269-Implement-furnace-cook-speed-multiplier-API.patch} (100%) rename patches/server/{0269-Catch-JsonParseException-in-Entity-and-TE-names.patch => 0270-Catch-JsonParseException-in-Entity-and-TE-names.patch} (100%) rename patches/server/{0270-Honor-EntityAgeable.ageLock.patch => 0271-Honor-EntityAgeable.ageLock.patch} (100%) rename patches/server/{0271-Configurable-connection-throttle-kick-message.patch => 0272-Configurable-connection-throttle-kick-message.patch} (100%) rename patches/server/{0272-Hook-into-CB-plugin-rewrites.patch => 0273-Hook-into-CB-plugin-rewrites.patch} (100%) rename patches/server/{0273-Add-sun-related-API.patch => 0274-Add-sun-related-API.patch} (100%) rename patches/server/{0274-Add-LivingEntity-getTargetEntity.patch => 0275-Add-LivingEntity-getTargetEntity.patch} (97%) rename patches/server/{0275-Turtle-API.patch => 0276-Turtle-API.patch} (100%) rename patches/server/{0276-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch => 0277-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch} (100%) rename patches/server/{0277-Call-player-spectator-target-events-and-improve-impl.patch => 0278-Call-player-spectator-target-events-and-improve-impl.patch} (100%) rename patches/server/{0278-Add-Velocity-IP-Forwarding-Support.patch => 0279-Add-Velocity-IP-Forwarding-Support.patch} (100%) rename patches/server/{0279-Add-more-Witch-API.patch => 0280-Add-more-Witch-API.patch} (100%) rename patches/server/{0280-Check-Drowned-for-Villager-Aggression-Config.patch => 0281-Check-Drowned-for-Villager-Aggression-Config.patch} (100%) rename patches/server/{0281-Here-s-Johnny.patch => 0282-Here-s-Johnny.patch} (100%) rename patches/server/{0282-Add-option-to-prevent-players-from-moving-into-unloa.patch => 0283-Add-option-to-prevent-players-from-moving-into-unloa.patch} (100%) rename patches/server/{0283-Reset-players-airTicks-on-respawn.patch => 0284-Reset-players-airTicks-on-respawn.patch} (89%) rename patches/server/{0284-Don-t-sleep-after-profile-lookups-if-not-needed.patch => 0285-Don-t-sleep-after-profile-lookups-if-not-needed.patch} (100%) rename patches/server/{0285-Improve-Server-Thread-Pool-and-Thread-Priorities.patch => 0286-Improve-Server-Thread-Pool-and-Thread-Priorities.patch} (100%) rename patches/server/{0286-Optimize-World-Time-Updates.patch => 0287-Optimize-World-Time-Updates.patch} (100%) rename patches/server/{0287-Restore-custom-InventoryHolder-support.patch => 0288-Restore-custom-InventoryHolder-support.patch} (100%) rename patches/server/{0288-Use-Vanilla-Minecart-Speeds.patch => 0289-Use-Vanilla-Minecart-Speeds.patch} (100%) rename patches/server/{0289-Fix-SpongeAbsortEvent-handling.patch => 0290-Fix-SpongeAbsortEvent-handling.patch} (100%) rename patches/server/{0290-Don-t-allow-digging-into-unloaded-chunks.patch => 0291-Don-t-allow-digging-into-unloaded-chunks.patch} (100%) rename patches/server/{0291-Make-the-default-permission-message-configurable.patch => 0292-Make-the-default-permission-message-configurable.patch} (100%) rename patches/server/{0292-Prevent-rayTrace-from-loading-chunks.patch => 0293-Prevent-rayTrace-from-loading-chunks.patch} (100%) rename patches/server/{0293-Handle-Large-Packets-disconnecting-client.patch => 0294-Handle-Large-Packets-disconnecting-client.patch} (100%) rename patches/server/{0294-force-entity-dismount-during-teleportation.patch => 0295-force-entity-dismount-during-teleportation.patch} (94%) rename patches/server/{0295-Add-more-Zombie-API.patch => 0296-Add-more-Zombie-API.patch} (100%) rename patches/server/{0296-Book-Size-Limits.patch => 0297-Book-Size-Limits.patch} (100%) rename patches/server/{0297-Add-PlayerConnectionCloseEvent.patch => 0298-Add-PlayerConnectionCloseEvent.patch} (100%) rename patches/server/{0298-Prevent-Enderman-from-loading-chunks.patch => 0299-Prevent-Enderman-from-loading-chunks.patch} (100%) rename patches/server/{0299-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch => 0300-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch} (100%) rename patches/server/{0300-Workaround-for-vehicle-tracking-issue-on-disconnect.patch => 0301-Workaround-for-vehicle-tracking-issue-on-disconnect.patch} (100%) rename patches/server/{0301-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch => 0302-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch} (100%) rename patches/server/{0302-Block-Entity-remove-from-being-called-on-Players.patch => 0303-Block-Entity-remove-from-being-called-on-Players.patch} (100%) rename patches/server/{0303-BlockDestroyEvent.patch => 0304-BlockDestroyEvent.patch} (93%) rename patches/server/{0304-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch => 0305-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch} (100%) rename patches/server/{0305-Limit-Client-Sign-length-more.patch => 0306-Limit-Client-Sign-length-more.patch} (100%) rename patches/server/{0306-Don-t-check-ConvertSigns-boolean-every-sign-save.patch => 0307-Don-t-check-ConvertSigns-boolean-every-sign-save.patch} (100%) rename patches/server/{0307-Optimize-Network-Manager-and-add-advanced-packet-sup.patch => 0308-Optimize-Network-Manager-and-add-advanced-packet-sup.patch} (100%) rename patches/server/{0308-Handle-Oversized-Tile-Entities-in-chunks.patch => 0309-Handle-Oversized-Tile-Entities-in-chunks.patch} (100%) rename patches/server/{0309-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch => 0310-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch} (100%) rename patches/server/{0310-Set-Zombie-last-tick-at-start-of-drowning-process.patch => 0311-Set-Zombie-last-tick-at-start-of-drowning-process.patch} (100%) rename patches/server/{0311-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch => 0312-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch} (100%) rename patches/server/{0312-Use-proper-max-length-when-serialising-BungeeCord-te.patch => 0313-Use-proper-max-length-when-serialising-BungeeCord-te.patch} (100%) rename patches/server/{0313-Entity-getEntitySpawnReason.patch => 0314-Entity-getEntitySpawnReason.patch} (89%) rename patches/server/{0314-Update-entity-Metadata-for-all-tracked-players.patch => 0315-Update-entity-Metadata-for-all-tracked-players.patch} (54%) rename patches/server/{0315-Fire-event-on-GS4-query.patch => 0316-Fire-event-on-GS4-query.patch} (100%) rename patches/server/{0316-Implement-PlayerPostRespawnEvent.patch => 0317-Implement-PlayerPostRespawnEvent.patch} (100%) rename patches/server/{0317-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch => 0318-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch} (100%) rename patches/server/{0318-Server-Tick-Events.patch => 0319-Server-Tick-Events.patch} (100%) rename patches/server/{0319-PlayerDeathEvent-getItemsToKeep.patch => 0320-PlayerDeathEvent-getItemsToKeep.patch} (100%) rename patches/server/{0320-Optimize-Captured-TileEntity-Lookup.patch => 0321-Optimize-Captured-TileEntity-Lookup.patch} (90%) rename patches/server/{0321-Add-Heightmap-API.patch => 0322-Add-Heightmap-API.patch} (100%) rename patches/server/{0322-Mob-Spawner-API-Enhancements.patch => 0323-Mob-Spawner-API-Enhancements.patch} (100%) rename patches/server/{0323-Fix-CB-call-to-changed-postToMainThread-method.patch => 0324-Fix-CB-call-to-changed-postToMainThread-method.patch} (100%) rename patches/server/{0324-Fix-sounds-when-item-frames-are-modified-MC-123450.patch => 0325-Fix-sounds-when-item-frames-are-modified-MC-123450.patch} (100%) rename patches/server/{0325-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch => 0326-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch} (100%) rename patches/server/{0326-improve-CraftWorld-isChunkLoaded.patch => 0327-improve-CraftWorld-isChunkLoaded.patch} (100%) rename patches/server/{0327-Configurable-Keep-Spawn-Loaded-range-per-world.patch => 0328-Configurable-Keep-Spawn-Loaded-range-per-world.patch} (98%) rename patches/server/{0328-ChunkMapDistance-CME.patch => 0329-ChunkMapDistance-CME.patch} (100%) rename patches/server/{0329-Implement-CraftBlockSoundGroup.patch => 0330-Implement-CraftBlockSoundGroup.patch} (100%) rename patches/server/{0330-Chunk-debug-command.patch => 0331-Chunk-debug-command.patch} (99%) rename patches/server/{0331-Fix-World-isChunkGenerated-calls.patch => 0332-Fix-World-isChunkGenerated-calls.patch} (100%) rename patches/server/{0332-Show-blockstate-location-if-we-failed-to-read-it.patch => 0333-Show-blockstate-location-if-we-failed-to-read-it.patch} (100%) rename patches/server/{0333-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch => 0334-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch} (100%) rename patches/server/{0334-Configurable-projectile-relative-velocity.patch => 0335-Configurable-projectile-relative-velocity.patch} (100%) rename patches/server/{0335-offset-item-frame-ticking.patch => 0336-offset-item-frame-ticking.patch} (100%) rename patches/server/{0336-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch => 0337-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch} (100%) rename patches/server/{0337-Fix-MC-158900.patch => 0338-Fix-MC-158900.patch} (100%) rename patches/server/{0338-Prevent-consuming-the-wrong-itemstack.patch => 0339-Prevent-consuming-the-wrong-itemstack.patch} (100%) rename patches/server/{0339-Generator-Settings.patch => 0340-Generator-Settings.patch} (100%) rename patches/server/{0340-Fix-MC-161754.patch => 0341-Fix-MC-161754.patch} (100%) rename patches/server/{0341-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch => 0342-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch} (100%) rename patches/server/{0342-Expose-the-internal-current-tick.patch => 0343-Expose-the-internal-current-tick.patch} (100%) rename patches/server/{0343-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch => 0344-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch} (100%) rename patches/server/{0344-Add-option-to-disable-pillager-patrols.patch => 0345-Add-option-to-disable-pillager-patrols.patch} (100%) rename patches/server/{0345-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch => 0346-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch} (100%) rename patches/server/{0346-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch => 0347-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch} (100%) rename patches/server/{0347-MC-145656-Fix-Follow-Range-Initial-Target.patch => 0348-MC-145656-Fix-Follow-Range-Initial-Target.patch} (100%) rename patches/server/{0348-Optimize-Hoppers.patch => 0349-Optimize-Hoppers.patch} (100%) rename patches/server/{0349-PlayerDeathEvent-shouldDropExperience.patch => 0350-PlayerDeathEvent-shouldDropExperience.patch} (100%) rename patches/server/{0350-Prevent-bees-loading-chunks-checking-hive-position.patch => 0351-Prevent-bees-loading-chunks-checking-hive-position.patch} (100%) rename patches/server/{0351-Don-t-load-Chunks-from-Hoppers-and-other-things.patch => 0352-Don-t-load-Chunks-from-Hoppers-and-other-things.patch} (100%) rename patches/server/{0352-Guard-against-serializing-mismatching-chunk-coordina.patch => 0353-Guard-against-serializing-mismatching-chunk-coordina.patch} (100%) rename patches/server/{0353-Optimise-IEntityAccess-getPlayerByUUID.patch => 0354-Optimise-IEntityAccess-getPlayerByUUID.patch} (90%) rename patches/server/{0354-Fix-items-not-falling-correctly.patch => 0355-Fix-items-not-falling-correctly.patch} (100%) rename patches/server/{0355-Lag-compensate-eating.patch => 0356-Lag-compensate-eating.patch} (100%) rename patches/server/{0356-Optimize-call-to-getFluid-for-explosions.patch => 0357-Optimize-call-to-getFluid-for-explosions.patch} (100%) rename patches/server/{0357-Fix-last-firework-in-stack-not-having-effects-when-d.patch => 0358-Fix-last-firework-in-stack-not-having-effects-when-d.patch} (100%) rename patches/server/{0358-Add-effect-to-block-break-naturally.patch => 0359-Add-effect-to-block-break-naturally.patch} (100%) rename patches/server/{0359-Entity-Activation-Range-2.0.patch => 0360-Entity-Activation-Range-2.0.patch} (97%) rename patches/server/{0360-Increase-Light-Queue-Size.patch => 0361-Increase-Light-Queue-Size.patch} (100%) rename patches/server/{0361-Fix-Light-Command.patch => 0362-Fix-Light-Command.patch} (100%) rename patches/server/{0362-No-Tick-view-distance-implementation.patch => 0363-No-Tick-view-distance-implementation.patch} (99%) rename patches/server/{0363-Implement-alternative-item-despawn-rate.patch => 0364-Implement-alternative-item-despawn-rate.patch} (100%) rename patches/server/{0364-Tracking-Range-Improvements.patch => 0365-Tracking-Range-Improvements.patch} (100%) rename patches/server/{0365-Fix-items-vanishing-through-end-portal.patch => 0366-Fix-items-vanishing-through-end-portal.patch} (89%) rename patches/server/{0366-implement-optional-per-player-mob-spawns.patch => 0367-implement-optional-per-player-mob-spawns.patch} (100%) rename patches/server/{0367-Bees-get-gravity-in-void.-Fixes-MC-167279.patch => 0368-Bees-get-gravity-in-void.-Fixes-MC-167279.patch} (100%) rename patches/server/{0368-Optimise-getChunkAt-calls-for-loaded-chunks.patch => 0369-Optimise-getChunkAt-calls-for-loaded-chunks.patch} (100%) rename patches/server/{0369-Allow-overriding-the-java-version-check.patch => 0370-Allow-overriding-the-java-version-check.patch} (100%) rename patches/server/{0370-Add-ThrownEggHatchEvent.patch => 0371-Add-ThrownEggHatchEvent.patch} (100%) rename patches/server/{0371-Optimise-random-block-ticking.patch => 0372-Optimise-random-block-ticking.patch} (97%) rename patches/server/{0372-Entity-Jump-API.patch => 0373-Entity-Jump-API.patch} (100%) rename patches/server/{0373-Add-option-to-nerf-pigmen-from-nether-portals.patch => 0374-Add-option-to-nerf-pigmen-from-nether-portals.patch} (92%) rename patches/server/{0374-Make-the-GUI-graph-fancier.patch => 0375-Make-the-GUI-graph-fancier.patch} (100%) rename patches/server/{0375-add-hand-to-BlockMultiPlaceEvent.patch => 0376-add-hand-to-BlockMultiPlaceEvent.patch} (100%) rename patches/server/{0376-Prevent-teleporting-dead-entities.patch => 0377-Prevent-teleporting-dead-entities.patch} (100%) rename patches/server/{0377-Validate-tripwire-hook-placement-before-update.patch => 0378-Validate-tripwire-hook-placement-before-update.patch} (100%) rename patches/server/{0378-Add-option-to-allow-iron-golems-to-spawn-in-air.patch => 0379-Add-option-to-allow-iron-golems-to-spawn-in-air.patch} (100%) rename patches/server/{0379-Configurable-chance-of-villager-zombie-infection.patch => 0380-Configurable-chance-of-villager-zombie-infection.patch} (100%) rename patches/server/{0380-Optimise-Chunk-getFluid.patch => 0381-Optimise-Chunk-getFluid.patch} (100%) rename patches/server/{0381-Optimise-TickListServer-by-rewriting-it.patch => 0382-Optimise-TickListServer-by-rewriting-it.patch} (99%) rename patches/server/{0382-Pillager-patrol-spawn-settings-and-per-player-option.patch => 0383-Pillager-patrol-spawn-settings-and-per-player-option.patch} (100%) rename patches/server/{0383-Remote-Connections-shouldn-t-hold-up-shutdown.patch => 0384-Remote-Connections-shouldn-t-hold-up-shutdown.patch} (100%) rename patches/server/{0384-Do-not-allow-bees-to-load-chunks-for-beehives.patch => 0385-Do-not-allow-bees-to-load-chunks-for-beehives.patch} (100%) rename patches/server/{0385-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch => 0386-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch} (92%) rename patches/server/{0386-Optimize-Collision-to-not-load-chunks.patch => 0387-Optimize-Collision-to-not-load-chunks.patch} (97%) rename patches/server/{0387-Don-t-tick-dead-players.patch => 0388-Don-t-tick-dead-players.patch} (100%) rename patches/server/{0388-Dead-Player-s-shouldn-t-be-able-to-move.patch => 0389-Dead-Player-s-shouldn-t-be-able-to-move.patch} (100%) rename patches/server/{0389-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch => 0390-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch} (100%) rename patches/server/{0390-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch => 0391-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch} (97%) rename patches/server/{0391-Don-t-move-existing-players-to-world-spawn.patch => 0392-Don-t-move-existing-players-to-world-spawn.patch} (100%) rename patches/server/{0392-Add-tick-times-API-and-mspt-command.patch => 0393-Add-tick-times-API-and-mspt-command.patch} (100%) rename patches/server/{0393-Expose-MinecraftServer-isRunning.patch => 0394-Expose-MinecraftServer-isRunning.patch} (100%) rename patches/server/{0394-Add-Raw-Byte-ItemStack-Serialization.patch => 0395-Add-Raw-Byte-ItemStack-Serialization.patch} (100%) rename patches/server/{0395-Remove-streams-from-Mob-AI-System.patch => 0396-Remove-streams-from-Mob-AI-System.patch} (100%) rename patches/server/{0396-Async-command-map-building.patch => 0397-Async-command-map-building.patch} (100%) rename patches/server/{0397-Improved-Watchdog-Support.patch => 0398-Improved-Watchdog-Support.patch} (99%) rename patches/server/{0398-Optimize-Pathfinding.patch => 0399-Optimize-Pathfinding.patch} (100%) rename patches/server/{0399-Reduce-Either-Optional-allocation.patch => 0400-Reduce-Either-Optional-allocation.patch} (100%) rename patches/server/{0400-Remove-streams-from-PairedQueue.patch => 0401-Remove-streams-from-PairedQueue.patch} (100%) rename patches/server/{0401-Reduce-memory-footprint-of-NBTTagCompound.patch => 0402-Reduce-memory-footprint-of-NBTTagCompound.patch} (100%) rename patches/server/{0402-Prevent-opening-inventories-when-frozen.patch => 0403-Prevent-opening-inventories-when-frozen.patch} (100%) rename patches/server/{0403-Optimise-ArraySetSorted-removeIf.patch => 0404-Optimise-ArraySetSorted-removeIf.patch} (100%) rename patches/server/{0404-Don-t-run-entity-collision-code-if-not-needed.patch => 0405-Don-t-run-entity-collision-code-if-not-needed.patch} (100%) rename patches/server/{0405-Restrict-vanilla-teleport-command-to-valid-locations.patch => 0406-Restrict-vanilla-teleport-command-to-valid-locations.patch} (100%) rename patches/server/{0406-Implement-Player-Client-Options-API.patch => 0407-Implement-Player-Client-Options-API.patch} (100%) rename patches/server/{0407-Fix-Chunk-Post-Processing-deadlock-risk.patch => 0408-Fix-Chunk-Post-Processing-deadlock-risk.patch} (100%) rename patches/server/{0408-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch => 0409-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch} (100%) rename patches/server/{0409-Broadcast-join-message-to-console.patch => 0410-Broadcast-join-message-to-console.patch} (100%) rename patches/server/{0410-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch => 0411-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch} (100%) rename patches/server/{0411-Load-Chunks-for-Login-Asynchronously.patch => 0412-Load-Chunks-for-Login-Asynchronously.patch} (99%) rename patches/server/{0412-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch => 0413-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch} (89%) rename patches/server/{0413-Add-PlayerAttackEntityCooldownResetEvent.patch => 0414-Add-PlayerAttackEntityCooldownResetEvent.patch} (100%) rename patches/server/{0414-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch => 0415-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch} (100%) rename patches/server/{0415-Don-t-fire-BlockFade-on-worldgen-threads.patch => 0416-Don-t-fire-BlockFade-on-worldgen-threads.patch} (100%) rename patches/server/{0416-Add-phantom-creative-and-insomniac-controls.patch => 0417-Add-phantom-creative-and-insomniac-controls.patch} (100%) rename patches/server/{0417-Fix-numerous-item-duplication-issues-and-teleport-is.patch => 0418-Fix-numerous-item-duplication-issues-and-teleport-is.patch} (94%) rename patches/server/{0418-Implement-Brigadier-Mojang-API.patch => 0419-Implement-Brigadier-Mojang-API.patch} (100%) rename patches/server/{0419-Villager-Restocks-API.patch => 0420-Villager-Restocks-API.patch} (100%) rename patches/server/{0420-Validate-PickItem-Packet-and-kick-for-invalid.patch => 0421-Validate-PickItem-Packet-and-kick-for-invalid.patch} (100%) rename patches/server/{0421-Expose-game-version.patch => 0422-Expose-game-version.patch} (100%) rename patches/server/{0422-Optimize-Voxel-Shape-Merging.patch => 0423-Optimize-Voxel-Shape-Merging.patch} (100%) rename patches/server/{0423-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch => 0424-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch} (100%) rename patches/server/{0424-Implement-Mob-Goal-API.patch => 0425-Implement-Mob-Goal-API.patch} (100%) rename patches/server/{0425-Use-distance-map-to-optimise-entity-tracker.patch => 0426-Use-distance-map-to-optimise-entity-tracker.patch} (99%) rename patches/server/{0426-Optimize-isOutsideRange-to-use-distance-maps.patch => 0427-Optimize-isOutsideRange-to-use-distance-maps.patch} (100%) rename patches/server/{0427-Add-villager-reputation-API.patch => 0428-Add-villager-reputation-API.patch} (100%) rename patches/server/{0428-Option-for-maximum-exp-value-when-merging-orbs.patch => 0429-Option-for-maximum-exp-value-when-merging-orbs.patch} (100%) rename patches/server/{0429-ExperienceOrbMergeEvent.patch => 0430-ExperienceOrbMergeEvent.patch} (100%) rename patches/server/{0430-Fix-PotionEffect-ignores-icon-flag.patch => 0431-Fix-PotionEffect-ignores-icon-flag.patch} (100%) rename patches/server/{0431-Optimize-brigadier-child-sorting-performance.patch => 0432-Optimize-brigadier-child-sorting-performance.patch} (100%) rename patches/server/{0432-Potential-bed-API.patch => 0433-Potential-bed-API.patch} (100%) rename patches/server/{0433-Wait-for-Async-Tasks-during-shutdown.patch => 0434-Wait-for-Async-Tasks-during-shutdown.patch} (100%) rename patches/server/{0434-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch => 0435-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch} (100%) rename patches/server/{0435-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch => 0436-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch} (98%) rename patches/server/{0436-Reduce-MutableInt-allocations-from-light-engine.patch => 0437-Reduce-MutableInt-allocations-from-light-engine.patch} (100%) rename patches/server/{0437-Reduce-allocation-of-Vec3D-by-entity-tracker.patch => 0438-Reduce-allocation-of-Vec3D-by-entity-tracker.patch} (100%) rename patches/server/{0438-Ensure-safe-gateway-teleport.patch => 0439-Ensure-safe-gateway-teleport.patch} (100%) rename patches/server/{0439-Add-option-for-console-having-all-permissions.patch => 0440-Add-option-for-console-having-all-permissions.patch} (100%) rename patches/server/{0440-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch => 0441-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch} (100%) rename patches/server/{0441-Optimize-sending-packets-to-nearby-locations-sounds-.patch => 0442-Optimize-sending-packets-to-nearby-locations-sounds-.patch} (100%) rename patches/server/{0442-Fix-villager-trading-demand-MC-163962.patch => 0443-Fix-villager-trading-demand-MC-163962.patch} (100%) rename patches/server/{0443-Maps-shouldn-t-load-chunks.patch => 0444-Maps-shouldn-t-load-chunks.patch} (100%) rename patches/server/{0444-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch => 0445-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch} (100%) rename patches/server/{0445-Optimize-Bit-Operations-by-inlining.patch => 0446-Optimize-Bit-Operations-by-inlining.patch} (100%) rename patches/server/{0446-incremental-chunk-saving.patch => 0447-incremental-chunk-saving.patch} (99%) diff --git a/patches/removed/1.17/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/patches/removed/1.17/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch deleted file mode 100644 index 4f79f9fe1b..0000000000 --- a/patches/removed/1.17/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 21 Jul 2018 08:25:40 -0400 -Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues - -Add -Ddebug.entities=true to your JVM flags to gain more information - -1.17: Needs to be reworked for new entity storage system - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 97d5437df10a6d0124e944404e88650547b7d8a8..083db6c1899b5391231b6d5d5044a334212f148c 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1145,6 +1145,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } else { - ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas()); - -+ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker - this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); - playerchunkmap_entitytracker.updatePlayers(this.level.players()); - if (entity instanceof ServerPlayer) { -@@ -1186,7 +1187,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - if (playerchunkmap_entitytracker1 != null) { - playerchunkmap_entitytracker1.broadcastRemoved(); - } -- -+ entity.tracker = null; // Paper - We're no longer tracked - } - - protected void tick() { -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 914241a57c304fde220bc546261d6e959445772a..a5d7781b13a6d61238d026f064512f7162e1e868 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -191,6 +191,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - public final LevelStorageSource.LevelStorageAccess convertable; - public final UUID uuid; - public boolean hasPhysicsEvent = true; // Paper -+ private static Throwable getAddToWorldStackTrace(Entity entity) { -+ return new Throwable(entity + " Added to world at " + new java.util.Date()); -+ } - - @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkSource.getChunk(x, z, false); -@@ -1032,8 +1035,28 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -- if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper -+ // Paper start -+ if (entity.valid) { -+ MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); -+ -+ if (DEBUG_ENTITIES) { -+ Throwable thr = entity.addedToWorldStack; -+ if (thr == null) { -+ MinecraftServer.LOGGER.error("Double add entity has no add stacktrace"); -+ } else { -+ MinecraftServer.LOGGER.error("Double add stacktrace: ", thr); -+ } -+ } -+ return true; -+ } -+ // Paper end - if (entity.removed) { -+ // Paper start -+ if (DEBUG_ENTITIES) { -+ new Throwable("Tried to add entity " + entity + " but it was marked as removed already").printStackTrace(); // CraftBukkit -+ getAddToWorldStackTrace(entity).printStackTrace(); -+ } -+ // Paper end - // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit - return false; - } else if (this.isUUIDUsed(entity)) { -@@ -1231,7 +1254,24 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - } - -- this.entitiesByUuid.put(entity.getUUID(), entity); -+ if (DEBUG_ENTITIES) { -+ entity.addedToWorldStack = getAddToWorldStackTrace(entity); -+ } -+ -+ Entity old = this.entitiesByUuid.put(entity.getUUID(), entity); -+ if (old != null && old.getId() != entity.getId() && old.valid) { -+ Logger logger = LogManager.getLogger(); -+ logger.error("Overwrote an existing entity " + old + " with " + entity); -+ if (DEBUG_ENTITIES) { -+ if (old.addedToWorldStack != null) { -+ old.addedToWorldStack.printStackTrace(); -+ } else { -+ logger.error("Oddly, the old entity was not added to the world in the normal way. Plugins?"); -+ } -+ entity.addedToWorldStack.printStackTrace(); -+ } -+ } -+ - this.getChunkSource().addEntity(entity); - // CraftBukkit start - SPIGOT-5278 - if (entity instanceof Drowned) { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index e49fe2de6a53bdd16f0cd09b691f01f1866ffb4f..9d8682d367522bd85894947ad2f2a53cf0aa123a 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -47,6 +47,7 @@ import net.minecraft.network.syncher.SynchedEntityData; - import net.minecraft.resources.ResourceKey; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.level.TicketType; -@@ -160,6 +161,8 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - -+ ChunkMap.TrackedEntity tracker; // Paper -+ public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { - bukkitEntity = CraftEntity.getEntity(level.getCraftServer(), this); -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index b4248d46ccb1a95e21601bca1198512287edcabf..0c6c3b211b05eda8f9ab47ef0a01cc520ae28201 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -121,6 +121,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public boolean pvpMode; - public boolean keepSpawnInMemory = true; - public org.bukkit.generator.ChunkGenerator generator; -+ public static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper - - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; diff --git a/patches/server/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/patches/server/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch new file mode 100644 index 0000000000..f59488baee --- /dev/null +++ b/patches/server/0243-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch @@ -0,0 +1,139 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 21 Jul 2018 08:25:40 -0400 +Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues + +Add -Ddebug.entities=true to your JVM flags to gain more information + +1.17: Needs to be reworked for new entity storage system + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 4b349960daaacd87c042b055adf36c0a66748f7f..a0f8f341e0cd6a2ac28e12d0824b694ac4fbc7ae 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1156,6 +1156,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } else { + ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas()); + ++ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker + this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); + playerchunkmap_entitytracker.updatePlayers(this.level.players()); + if (entity instanceof ServerPlayer) { +@@ -1198,7 +1199,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (playerchunkmap_entitytracker1 != null) { + playerchunkmap_entitytracker1.broadcastRemoved(); + } +- ++ entity.tracker = null; // Paper - We're no longer tracked + } + + protected void tick() { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 8989b3153b0c849e189a8ff4ac4de6085e3a3db2..73da340ab8782efc7d97c3a3e29ea9cd9a830799 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -202,6 +202,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper ++ public static Throwable getAddToWorldStackTrace(Entity entity) { ++ return new Throwable(entity + " Added to world at " + new java.util.Date()); ++ } + + @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkSource.getChunk(x, z, false); +@@ -1018,7 +1021,28 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // CraftBukkit start + private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot ++ // Paper start ++ if (entity.valid) { ++ MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); ++ ++ if (DEBUG_ENTITIES) { ++ Throwable thr = entity.addedToWorldStack; ++ if (thr == null) { ++ MinecraftServer.LOGGER.error("Double add entity has no add stacktrace"); ++ } else { ++ MinecraftServer.LOGGER.error("Double add stacktrace: ", thr); ++ } ++ } ++ return true; ++ } ++ // Paper end + if (entity.isRemoved()) { ++ // Paper start ++ if (DEBUG_ENTITIES) { ++ new Throwable("Tried to add entity " + entity + " but it was marked as removed already").printStackTrace(); // CraftBukkit ++ getAddToWorldStackTrace(entity).printStackTrace(); ++ } ++ // Paper end + // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit + return false; + } else { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 960c3e75a60ef33141e615bd8b256528eeaf399c..0d4ab7a469b2ce643b80e7912e20d126a251960a 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -171,6 +171,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper + private CraftEntity bukkitEntity; + ++ public net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper ++ public Throwable addedToWorldStack; // Paper - entity debug + public CraftEntity getBukkitEntity() { + if (this.bukkitEntity == null) { + this.bukkitEntity = CraftEntity.getEntity(this.level.getCraftServer(), this); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 8d4f8719b30a66fbb68c9407ee8484312f05b3fb..b978a6d44416ce89addaafb54a71fcb06e635b30 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -141,6 +141,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean pvpMode; + public boolean keepSpawnInMemory = true; + public org.bukkit.generator.ChunkGenerator generator; ++ public static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper + + public boolean captureBlockStates = false; + public boolean captureTreeGeneration = false; +diff --git a/src/main/java/net/minecraft/world/level/entity/EntityLookup.java b/src/main/java/net/minecraft/world/level/entity/EntityLookup.java +index c8cf7da4224dccd9b9e8a73bcfc3ff5babfb8f8c..1d04f35b6755b3a7ee77f93c1a30513a5af7d6cf 100644 +--- a/src/main/java/net/minecraft/world/level/entity/EntityLookup.java ++++ b/src/main/java/net/minecraft/world/level/entity/EntityLookup.java +@@ -20,7 +20,7 @@ public class EntityLookup { + for(T entityAccess : this.byId.values()) { + U entityAccess2 = (U)((EntityAccess)filter.tryCast(entityAccess)); + if (entityAccess2 != null) { +- action.accept((T)entityAccess2); ++ action.accept(entityAccess2); // Paper - decompile fix + } + } + +@@ -34,6 +34,27 @@ public class EntityLookup { + UUID uUID = entity.getUUID(); + if (this.byUuid.containsKey(uUID)) { + LOGGER.warn("Duplicate entity UUID {}: {}", uUID, entity); ++ // Paper start - extra debug info ++ if (entity instanceof net.minecraft.world.entity.Entity) { ++ if (net.minecraft.server.level.ServerLevel.DEBUG_ENTITIES) { ++ ((net.minecraft.world.entity.Entity) entity).addedToWorldStack = net.minecraft.server.level.ServerLevel.getAddToWorldStackTrace((net.minecraft.world.entity.Entity) entity); ++ } ++ ++ T old = this.byUuid.get(entity.getUUID()); ++ if (old instanceof net.minecraft.world.entity.Entity && old != null && old.getId() != entity.getId() && ((net.minecraft.world.entity.Entity) old).valid) { ++ Logger logger = LogManager.getLogger(); ++ logger.error("Overwrote an existing entity " + old + " with " + entity); ++ if (net.minecraft.server.level.ServerLevel.DEBUG_ENTITIES) { ++ if (((net.minecraft.world.entity.Entity) old).addedToWorldStack != null) { ++ ((net.minecraft.world.entity.Entity) old).addedToWorldStack.printStackTrace(); ++ } else { ++ logger.error("Oddly, the old entity was not added to the world in the normal way. Plugins?"); ++ } ++ ((net.minecraft.world.entity.Entity) entity).addedToWorldStack.printStackTrace(); ++ } ++ } ++ } ++ // Paper end + } else { + this.byUuid.put(uUID, entity); + this.byId.put(entity.getId(), entity); diff --git a/patches/server/0243-Add-Early-Warning-Feature-to-WatchDog.patch b/patches/server/0244-Add-Early-Warning-Feature-to-WatchDog.patch similarity index 100% rename from patches/server/0243-Add-Early-Warning-Feature-to-WatchDog.patch rename to patches/server/0244-Add-Early-Warning-Feature-to-WatchDog.patch diff --git a/patches/server/0244-Make-EnderDragon-implement-Mob.patch b/patches/server/0245-Make-EnderDragon-implement-Mob.patch similarity index 100% rename from patches/server/0244-Make-EnderDragon-implement-Mob.patch rename to patches/server/0245-Make-EnderDragon-implement-Mob.patch diff --git a/patches/server/0245-Use-ConcurrentHashMap-in-JsonList.patch b/patches/server/0246-Use-ConcurrentHashMap-in-JsonList.patch similarity index 100% rename from patches/server/0245-Use-ConcurrentHashMap-in-JsonList.patch rename to patches/server/0246-Use-ConcurrentHashMap-in-JsonList.patch diff --git a/patches/server/0246-Use-a-Queue-for-Queueing-Commands.patch b/patches/server/0247-Use-a-Queue-for-Queueing-Commands.patch similarity index 100% rename from patches/server/0246-Use-a-Queue-for-Queueing-Commands.patch rename to patches/server/0247-Use-a-Queue-for-Queueing-Commands.patch diff --git a/patches/server/0247-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/patches/server/0248-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch similarity index 100% rename from patches/server/0247-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch rename to patches/server/0248-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch diff --git a/patches/server/0248-Optimize-BlockPosition-helper-methods.patch b/patches/server/0249-Optimize-BlockPosition-helper-methods.patch similarity index 100% rename from patches/server/0248-Optimize-BlockPosition-helper-methods.patch rename to patches/server/0249-Optimize-BlockPosition-helper-methods.patch diff --git a/patches/server/0249-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/patches/server/0250-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch similarity index 100% rename from patches/server/0249-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch rename to patches/server/0250-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch diff --git a/patches/server/0250-Slime-Pathfinder-Events.patch b/patches/server/0251-Slime-Pathfinder-Events.patch similarity index 100% rename from patches/server/0250-Slime-Pathfinder-Events.patch rename to patches/server/0251-Slime-Pathfinder-Events.patch diff --git a/patches/server/0251-Configurable-speed-for-water-flowing-over-lava.patch b/patches/server/0252-Configurable-speed-for-water-flowing-over-lava.patch similarity index 100% rename from patches/server/0251-Configurable-speed-for-water-flowing-over-lava.patch rename to patches/server/0252-Configurable-speed-for-water-flowing-over-lava.patch diff --git a/patches/server/0252-Optimize-CraftBlockData-Creation.patch b/patches/server/0253-Optimize-CraftBlockData-Creation.patch similarity index 100% rename from patches/server/0252-Optimize-CraftBlockData-Creation.patch rename to patches/server/0253-Optimize-CraftBlockData-Creation.patch diff --git a/patches/server/0253-Optimize-MappedRegistry.patch b/patches/server/0254-Optimize-MappedRegistry.patch similarity index 100% rename from patches/server/0253-Optimize-MappedRegistry.patch rename to patches/server/0254-Optimize-MappedRegistry.patch diff --git a/patches/server/0254-Add-PhantomPreSpawnEvent.patch b/patches/server/0255-Add-PhantomPreSpawnEvent.patch similarity index 100% rename from patches/server/0254-Add-PhantomPreSpawnEvent.patch rename to patches/server/0255-Add-PhantomPreSpawnEvent.patch diff --git a/patches/server/0255-Add-More-Creeper-API.patch b/patches/server/0256-Add-More-Creeper-API.patch similarity index 100% rename from patches/server/0255-Add-More-Creeper-API.patch rename to patches/server/0256-Add-More-Creeper-API.patch diff --git a/patches/server/0256-Inventory-removeItemAnySlot.patch b/patches/server/0257-Inventory-removeItemAnySlot.patch similarity index 100% rename from patches/server/0256-Inventory-removeItemAnySlot.patch rename to patches/server/0257-Inventory-removeItemAnySlot.patch diff --git a/patches/server/0257-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/patches/server/0258-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch similarity index 100% rename from patches/server/0257-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch rename to patches/server/0258-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch diff --git a/patches/server/0258-Asynchronous-chunk-IO-and-loading.patch b/patches/server/0259-Asynchronous-chunk-IO-and-loading.patch similarity index 99% rename from patches/server/0258-Asynchronous-chunk-IO-and-loading.patch rename to patches/server/0259-Asynchronous-chunk-IO-and-loading.patch index ea7e8e8faa..f362446c4e 100644 --- a/patches/server/0258-Asynchronous-chunk-IO-and-loading.patch +++ b/patches/server/0259-Asynchronous-chunk-IO-and-loading.patch @@ -2357,7 +2357,7 @@ index ce4296ab7e6f1ccc735d619eacabdf2ef2f4e361..00f5cd29170e3594fe2ac194e04e403c completablefuture = (CompletableFuture) this.futures.get(i); if (completablefuture == null) { diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 4b349960daaacd87c042b055adf36c0a66748f7f..8311d921ded1c81a1f561dc13db2010d2b7ce5d6 100644 +index a0f8f341e0cd6a2ac28e12d0824b694ac4fbc7ae..95ac30f56a9268f14d2518974c5a52e08f40ea18 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -115,7 +115,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -2668,7 +2668,7 @@ index 4b349960daaacd87c042b055adf36c0a66748f7f..8311d921ded1c81a1f561dc13db2010d @Nullable private CompoundTag readChunk(ChunkPos pos) throws IOException { CompoundTag nbttagcompound = this.read(pos); -@@ -1310,6 +1435,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1311,6 +1436,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } @@ -2865,10 +2865,10 @@ index 4a343fa19566f468aca17228379f4d75f3f56f28..71ac5cf0fdedcfe422bf6f5e6ffb15ce } finally { chunkMap.callbackExecutor.run(); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 8989b3153b0c849e189a8ff4ac4de6085e3a3db2..731c8e38c8daf04fee40a5ccfb0715b20f4d890f 100644 +index 73da340ab8782efc7d97c3a3e29ea9cd9a830799..043869948201c728bf168855d260b0dca42a0b3a 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -207,6 +207,79 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -210,6 +210,79 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl return this.chunkSource.getChunk(x, z, false); } @@ -2948,7 +2948,7 @@ index 8989b3153b0c849e189a8ff4ac4de6085e3a3db2..731c8e38c8daf04fee40a5ccfb0715b2 // Add env and gen to constructor, WorldData -> WorldDataServer public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error -@@ -278,6 +351,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -281,6 +354,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl this.sleepStatus = new SleepStatus(); this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit diff --git a/patches/server/0259-Add-ray-tracing-methods-to-LivingEntity.patch b/patches/server/0260-Add-ray-tracing-methods-to-LivingEntity.patch similarity index 100% rename from patches/server/0259-Add-ray-tracing-methods-to-LivingEntity.patch rename to patches/server/0260-Add-ray-tracing-methods-to-LivingEntity.patch diff --git a/patches/server/0260-Expose-attack-cooldown-methods-for-Player.patch b/patches/server/0261-Expose-attack-cooldown-methods-for-Player.patch similarity index 100% rename from patches/server/0260-Expose-attack-cooldown-methods-for-Player.patch rename to patches/server/0261-Expose-attack-cooldown-methods-for-Player.patch diff --git a/patches/server/0261-Improve-death-events.patch b/patches/server/0262-Improve-death-events.patch similarity index 100% rename from patches/server/0261-Improve-death-events.patch rename to patches/server/0262-Improve-death-events.patch diff --git a/patches/server/0262-Allow-chests-to-be-placed-with-NBT-data.patch b/patches/server/0263-Allow-chests-to-be-placed-with-NBT-data.patch similarity index 100% rename from patches/server/0262-Allow-chests-to-be-placed-with-NBT-data.patch rename to patches/server/0263-Allow-chests-to-be-placed-with-NBT-data.patch diff --git a/patches/server/0263-Mob-Pathfinding-API.patch b/patches/server/0264-Mob-Pathfinding-API.patch similarity index 100% rename from patches/server/0263-Mob-Pathfinding-API.patch rename to patches/server/0264-Mob-Pathfinding-API.patch diff --git a/patches/server/0264-Prevent-chunk-loading-from-Fluid-Flowing.patch b/patches/server/0265-Prevent-chunk-loading-from-Fluid-Flowing.patch similarity index 100% rename from patches/server/0264-Prevent-chunk-loading-from-Fluid-Flowing.patch rename to patches/server/0265-Prevent-chunk-loading-from-Fluid-Flowing.patch diff --git a/patches/server/0265-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/patches/server/0266-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch similarity index 100% rename from patches/server/0265-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch rename to patches/server/0266-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch diff --git a/patches/server/0266-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/patches/server/0267-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch similarity index 100% rename from patches/server/0266-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch rename to patches/server/0267-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch diff --git a/patches/server/0267-Prevent-mob-spawning-from-loading-generating-chunks.patch b/patches/server/0268-Prevent-mob-spawning-from-loading-generating-chunks.patch similarity index 100% rename from patches/server/0267-Prevent-mob-spawning-from-loading-generating-chunks.patch rename to patches/server/0268-Prevent-mob-spawning-from-loading-generating-chunks.patch diff --git a/patches/server/0268-Implement-furnace-cook-speed-multiplier-API.patch b/patches/server/0269-Implement-furnace-cook-speed-multiplier-API.patch similarity index 100% rename from patches/server/0268-Implement-furnace-cook-speed-multiplier-API.patch rename to patches/server/0269-Implement-furnace-cook-speed-multiplier-API.patch diff --git a/patches/server/0269-Catch-JsonParseException-in-Entity-and-TE-names.patch b/patches/server/0270-Catch-JsonParseException-in-Entity-and-TE-names.patch similarity index 100% rename from patches/server/0269-Catch-JsonParseException-in-Entity-and-TE-names.patch rename to patches/server/0270-Catch-JsonParseException-in-Entity-and-TE-names.patch diff --git a/patches/server/0270-Honor-EntityAgeable.ageLock.patch b/patches/server/0271-Honor-EntityAgeable.ageLock.patch similarity index 100% rename from patches/server/0270-Honor-EntityAgeable.ageLock.patch rename to patches/server/0271-Honor-EntityAgeable.ageLock.patch diff --git a/patches/server/0271-Configurable-connection-throttle-kick-message.patch b/patches/server/0272-Configurable-connection-throttle-kick-message.patch similarity index 100% rename from patches/server/0271-Configurable-connection-throttle-kick-message.patch rename to patches/server/0272-Configurable-connection-throttle-kick-message.patch diff --git a/patches/server/0272-Hook-into-CB-plugin-rewrites.patch b/patches/server/0273-Hook-into-CB-plugin-rewrites.patch similarity index 100% rename from patches/server/0272-Hook-into-CB-plugin-rewrites.patch rename to patches/server/0273-Hook-into-CB-plugin-rewrites.patch diff --git a/patches/server/0273-Add-sun-related-API.patch b/patches/server/0274-Add-sun-related-API.patch similarity index 100% rename from patches/server/0273-Add-sun-related-API.patch rename to patches/server/0274-Add-sun-related-API.patch diff --git a/patches/server/0274-Add-LivingEntity-getTargetEntity.patch b/patches/server/0275-Add-LivingEntity-getTargetEntity.patch similarity index 97% rename from patches/server/0274-Add-LivingEntity-getTargetEntity.patch rename to patches/server/0275-Add-LivingEntity-getTargetEntity.patch index 3b34a48c14..e2cacd1761 100644 --- a/patches/server/0274-Add-LivingEntity-getTargetEntity.patch +++ b/patches/server/0275-Add-LivingEntity-getTargetEntity.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add LivingEntity#getTargetEntity diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 960c3e75a60ef33141e615bd8b256528eeaf399c..0974781e2f7fc541eaf397de033fb12b87dbf8ba 100644 +index 0d4ab7a469b2ce643b80e7912e20d126a251960a..b75a7f702ca6166c1f869a138ac4b93ba3870c62 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2339,6 +2339,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -2341,6 +2341,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n this.setYHeadRot(yaw); } diff --git a/patches/server/0275-Turtle-API.patch b/patches/server/0276-Turtle-API.patch similarity index 100% rename from patches/server/0275-Turtle-API.patch rename to patches/server/0276-Turtle-API.patch diff --git a/patches/server/0276-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/patches/server/0277-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch similarity index 100% rename from patches/server/0276-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch rename to patches/server/0277-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch diff --git a/patches/server/0277-Call-player-spectator-target-events-and-improve-impl.patch b/patches/server/0278-Call-player-spectator-target-events-and-improve-impl.patch similarity index 100% rename from patches/server/0277-Call-player-spectator-target-events-and-improve-impl.patch rename to patches/server/0278-Call-player-spectator-target-events-and-improve-impl.patch diff --git a/patches/server/0278-Add-Velocity-IP-Forwarding-Support.patch b/patches/server/0279-Add-Velocity-IP-Forwarding-Support.patch similarity index 100% rename from patches/server/0278-Add-Velocity-IP-Forwarding-Support.patch rename to patches/server/0279-Add-Velocity-IP-Forwarding-Support.patch diff --git a/patches/server/0279-Add-more-Witch-API.patch b/patches/server/0280-Add-more-Witch-API.patch similarity index 100% rename from patches/server/0279-Add-more-Witch-API.patch rename to patches/server/0280-Add-more-Witch-API.patch diff --git a/patches/server/0280-Check-Drowned-for-Villager-Aggression-Config.patch b/patches/server/0281-Check-Drowned-for-Villager-Aggression-Config.patch similarity index 100% rename from patches/server/0280-Check-Drowned-for-Villager-Aggression-Config.patch rename to patches/server/0281-Check-Drowned-for-Villager-Aggression-Config.patch diff --git a/patches/server/0281-Here-s-Johnny.patch b/patches/server/0282-Here-s-Johnny.patch similarity index 100% rename from patches/server/0281-Here-s-Johnny.patch rename to patches/server/0282-Here-s-Johnny.patch diff --git a/patches/server/0282-Add-option-to-prevent-players-from-moving-into-unloa.patch b/patches/server/0283-Add-option-to-prevent-players-from-moving-into-unloa.patch similarity index 100% rename from patches/server/0282-Add-option-to-prevent-players-from-moving-into-unloa.patch rename to patches/server/0283-Add-option-to-prevent-players-from-moving-into-unloa.patch diff --git a/patches/server/0283-Reset-players-airTicks-on-respawn.patch b/patches/server/0284-Reset-players-airTicks-on-respawn.patch similarity index 89% rename from patches/server/0283-Reset-players-airTicks-on-respawn.patch rename to patches/server/0284-Reset-players-airTicks-on-respawn.patch index 562a2e2343..5ce220ca22 100644 --- a/patches/server/0283-Reset-players-airTicks-on-respawn.patch +++ b/patches/server/0284-Reset-players-airTicks-on-respawn.patch @@ -17,10 +17,10 @@ index b2324b53b3cec3e577a8ec8c45b113c232d220a6..5eb37fb1ae861940839fe6815b571118 this.fallDistance = 0; this.foodData = new FoodData(this); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0974781e2f7fc541eaf397de033fb12b87dbf8ba..c3bbe8429ee792b881953c5894a55505cdba63d3 100644 +index b75a7f702ca6166c1f869a138ac4b93ba3870c62..f9f51b84036f522cdfc4ca6d47c074d51c14bf08 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2585,6 +2585,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -2587,6 +2587,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } diff --git a/patches/server/0284-Don-t-sleep-after-profile-lookups-if-not-needed.patch b/patches/server/0285-Don-t-sleep-after-profile-lookups-if-not-needed.patch similarity index 100% rename from patches/server/0284-Don-t-sleep-after-profile-lookups-if-not-needed.patch rename to patches/server/0285-Don-t-sleep-after-profile-lookups-if-not-needed.patch diff --git a/patches/server/0285-Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/patches/server/0286-Improve-Server-Thread-Pool-and-Thread-Priorities.patch similarity index 100% rename from patches/server/0285-Improve-Server-Thread-Pool-and-Thread-Priorities.patch rename to patches/server/0286-Improve-Server-Thread-Pool-and-Thread-Priorities.patch diff --git a/patches/server/0286-Optimize-World-Time-Updates.patch b/patches/server/0287-Optimize-World-Time-Updates.patch similarity index 100% rename from patches/server/0286-Optimize-World-Time-Updates.patch rename to patches/server/0287-Optimize-World-Time-Updates.patch diff --git a/patches/server/0287-Restore-custom-InventoryHolder-support.patch b/patches/server/0288-Restore-custom-InventoryHolder-support.patch similarity index 100% rename from patches/server/0287-Restore-custom-InventoryHolder-support.patch rename to patches/server/0288-Restore-custom-InventoryHolder-support.patch diff --git a/patches/server/0288-Use-Vanilla-Minecart-Speeds.patch b/patches/server/0289-Use-Vanilla-Minecart-Speeds.patch similarity index 100% rename from patches/server/0288-Use-Vanilla-Minecart-Speeds.patch rename to patches/server/0289-Use-Vanilla-Minecart-Speeds.patch diff --git a/patches/server/0289-Fix-SpongeAbsortEvent-handling.patch b/patches/server/0290-Fix-SpongeAbsortEvent-handling.patch similarity index 100% rename from patches/server/0289-Fix-SpongeAbsortEvent-handling.patch rename to patches/server/0290-Fix-SpongeAbsortEvent-handling.patch diff --git a/patches/server/0290-Don-t-allow-digging-into-unloaded-chunks.patch b/patches/server/0291-Don-t-allow-digging-into-unloaded-chunks.patch similarity index 100% rename from patches/server/0290-Don-t-allow-digging-into-unloaded-chunks.patch rename to patches/server/0291-Don-t-allow-digging-into-unloaded-chunks.patch diff --git a/patches/server/0291-Make-the-default-permission-message-configurable.patch b/patches/server/0292-Make-the-default-permission-message-configurable.patch similarity index 100% rename from patches/server/0291-Make-the-default-permission-message-configurable.patch rename to patches/server/0292-Make-the-default-permission-message-configurable.patch diff --git a/patches/server/0292-Prevent-rayTrace-from-loading-chunks.patch b/patches/server/0293-Prevent-rayTrace-from-loading-chunks.patch similarity index 100% rename from patches/server/0292-Prevent-rayTrace-from-loading-chunks.patch rename to patches/server/0293-Prevent-rayTrace-from-loading-chunks.patch diff --git a/patches/server/0293-Handle-Large-Packets-disconnecting-client.patch b/patches/server/0294-Handle-Large-Packets-disconnecting-client.patch similarity index 100% rename from patches/server/0293-Handle-Large-Packets-disconnecting-client.patch rename to patches/server/0294-Handle-Large-Packets-disconnecting-client.patch diff --git a/patches/server/0294-force-entity-dismount-during-teleportation.patch b/patches/server/0295-force-entity-dismount-during-teleportation.patch similarity index 94% rename from patches/server/0294-force-entity-dismount-during-teleportation.patch rename to patches/server/0295-force-entity-dismount-during-teleportation.patch index a3e4049fb0..73280109bd 100644 --- a/patches/server/0294-force-entity-dismount-during-teleportation.patch +++ b/patches/server/0295-force-entity-dismount-during-teleportation.patch @@ -41,10 +41,10 @@ index 5eb37fb1ae861940839fe6815b57111812d6b3ec..963a3c159e912a39b98dfcb3fdb8c384 if (entity1 != entity && this.connection != null) { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c3bbe8429ee792b881953c5894a55505cdba63d3..8df9bd656374d0b43af378c61c1df7b951085b58 100644 +index f9f51b84036f522cdfc4ca6d47c074d51c14bf08..fcfee0f2b2b073b0c642684fddfb8d3c4eacf4f9 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2212,12 +2212,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -2214,12 +2214,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } @@ -62,7 +62,7 @@ index c3bbe8429ee792b881953c5894a55505cdba63d3..8df9bd656374d0b43af378c61c1df7b9 } } -@@ -2280,7 +2283,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -2282,7 +2285,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n return true; // CraftBukkit } @@ -74,7 +74,7 @@ index c3bbe8429ee792b881953c5894a55505cdba63d3..8df9bd656374d0b43af378c61c1df7b9 if (entity.getVehicle() == this) { throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); } else { -@@ -2290,7 +2296,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -2292,7 +2298,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n if (this.getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { VehicleExitEvent event = new VehicleExitEvent( (Vehicle) this.getBukkitEntity(), @@ -83,7 +83,7 @@ index c3bbe8429ee792b881953c5894a55505cdba63d3..8df9bd656374d0b43af378c61c1df7b9 ); // Suppress during worldgen if (this.valid) { -@@ -2304,7 +2310,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -2306,7 +2312,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } // CraftBukkit end // Spigot start diff --git a/patches/server/0295-Add-more-Zombie-API.patch b/patches/server/0296-Add-more-Zombie-API.patch similarity index 100% rename from patches/server/0295-Add-more-Zombie-API.patch rename to patches/server/0296-Add-more-Zombie-API.patch diff --git a/patches/server/0296-Book-Size-Limits.patch b/patches/server/0297-Book-Size-Limits.patch similarity index 100% rename from patches/server/0296-Book-Size-Limits.patch rename to patches/server/0297-Book-Size-Limits.patch diff --git a/patches/server/0297-Add-PlayerConnectionCloseEvent.patch b/patches/server/0298-Add-PlayerConnectionCloseEvent.patch similarity index 100% rename from patches/server/0297-Add-PlayerConnectionCloseEvent.patch rename to patches/server/0298-Add-PlayerConnectionCloseEvent.patch diff --git a/patches/server/0298-Prevent-Enderman-from-loading-chunks.patch b/patches/server/0299-Prevent-Enderman-from-loading-chunks.patch similarity index 100% rename from patches/server/0298-Prevent-Enderman-from-loading-chunks.patch rename to patches/server/0299-Prevent-Enderman-from-loading-chunks.patch diff --git a/patches/server/0299-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/patches/server/0300-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 100% rename from patches/server/0299-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to patches/server/0300-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch diff --git a/patches/server/0300-Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/patches/server/0301-Workaround-for-vehicle-tracking-issue-on-disconnect.patch similarity index 100% rename from patches/server/0300-Workaround-for-vehicle-tracking-issue-on-disconnect.patch rename to patches/server/0301-Workaround-for-vehicle-tracking-issue-on-disconnect.patch diff --git a/patches/server/0301-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/patches/server/0302-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch similarity index 100% rename from patches/server/0301-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch rename to patches/server/0302-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch diff --git a/patches/server/0302-Block-Entity-remove-from-being-called-on-Players.patch b/patches/server/0303-Block-Entity-remove-from-being-called-on-Players.patch similarity index 100% rename from patches/server/0302-Block-Entity-remove-from-being-called-on-Players.patch rename to patches/server/0303-Block-Entity-remove-from-being-called-on-Players.patch diff --git a/patches/server/0303-BlockDestroyEvent.patch b/patches/server/0304-BlockDestroyEvent.patch similarity index 93% rename from patches/server/0303-BlockDestroyEvent.patch rename to patches/server/0304-BlockDestroyEvent.patch index 1f3060877f..ba8f2e39cf 100644 --- a/patches/server/0303-BlockDestroyEvent.patch +++ b/patches/server/0304-BlockDestroyEvent.patch @@ -11,7 +11,7 @@ floating in the air. This can replace many uses of BlockPhysicsEvent diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 8d4f8719b30a66fbb68c9407ee8484312f05b3fb..a1b713391c2445967c3b5a645304f193c013d551 100644 +index b978a6d44416ce89addaafb54a71fcb06e635b30..834bbd63b4e45e8c89b4ece4eaf357f3cbe8e8ca 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -28,6 +28,7 @@ import net.minecraft.nbt.CompoundTag; @@ -22,7 +22,7 @@ index 8d4f8719b30a66fbb68c9407ee8484312f05b3fb..a1b713391c2445967c3b5a645304f193 import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ServerLevel; -@@ -567,8 +568,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -568,8 +569,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable { return false; } else { FluidState fluid = this.getFluidState(pos); diff --git a/patches/server/0304-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/patches/server/0305-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch similarity index 100% rename from patches/server/0304-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch rename to patches/server/0305-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch diff --git a/patches/server/0305-Limit-Client-Sign-length-more.patch b/patches/server/0306-Limit-Client-Sign-length-more.patch similarity index 100% rename from patches/server/0305-Limit-Client-Sign-length-more.patch rename to patches/server/0306-Limit-Client-Sign-length-more.patch diff --git a/patches/server/0306-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/patches/server/0307-Don-t-check-ConvertSigns-boolean-every-sign-save.patch similarity index 100% rename from patches/server/0306-Don-t-check-ConvertSigns-boolean-every-sign-save.patch rename to patches/server/0307-Don-t-check-ConvertSigns-boolean-every-sign-save.patch diff --git a/patches/server/0307-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server/0308-Optimize-Network-Manager-and-add-advanced-packet-sup.patch similarity index 100% rename from patches/server/0307-Optimize-Network-Manager-and-add-advanced-packet-sup.patch rename to patches/server/0308-Optimize-Network-Manager-and-add-advanced-packet-sup.patch diff --git a/patches/server/0308-Handle-Oversized-Tile-Entities-in-chunks.patch b/patches/server/0309-Handle-Oversized-Tile-Entities-in-chunks.patch similarity index 100% rename from patches/server/0308-Handle-Oversized-Tile-Entities-in-chunks.patch rename to patches/server/0309-Handle-Oversized-Tile-Entities-in-chunks.patch diff --git a/patches/server/0309-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/patches/server/0310-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch similarity index 100% rename from patches/server/0309-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch rename to patches/server/0310-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch diff --git a/patches/server/0310-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/patches/server/0311-Set-Zombie-last-tick-at-start-of-drowning-process.patch similarity index 100% rename from patches/server/0310-Set-Zombie-last-tick-at-start-of-drowning-process.patch rename to patches/server/0311-Set-Zombie-last-tick-at-start-of-drowning-process.patch diff --git a/patches/server/0311-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/patches/server/0312-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch similarity index 100% rename from patches/server/0311-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch rename to patches/server/0312-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch diff --git a/patches/server/0312-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/patches/server/0313-Use-proper-max-length-when-serialising-BungeeCord-te.patch similarity index 100% rename from patches/server/0312-Use-proper-max-length-when-serialising-BungeeCord-te.patch rename to patches/server/0313-Use-proper-max-length-when-serialising-BungeeCord-te.patch diff --git a/patches/server/0313-Entity-getEntitySpawnReason.patch b/patches/server/0314-Entity-getEntitySpawnReason.patch similarity index 89% rename from patches/server/0313-Entity-getEntitySpawnReason.patch rename to patches/server/0314-Entity-getEntitySpawnReason.patch index 20c369e137..33f056c7fe 100644 --- a/patches/server/0313-Entity-getEntitySpawnReason.patch +++ b/patches/server/0314-Entity-getEntitySpawnReason.patch @@ -10,17 +10,17 @@ persistenting Living Entity, SPAWNER for spawners, or DEFAULT since data was not stored. diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 731c8e38c8daf04fee40a5ccfb0715b20f4d890f..940e6587125df1f203cdeeefc31658635badea81 100644 +index 043869948201c728bf168855d260b0dca42a0b3a..c64557c70122bff6ea0c8d0b34f62daf680e4334 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1093,6 +1093,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot +@@ -1111,6 +1111,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return true; + } + // Paper end + if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper if (entity.isRemoved()) { - // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit - return false; + // Paper start + if (DEBUG_ENTITIES) { diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java index ea336bdf2f15aabe74de82ef6c29b93573254e31..da3100d6577166e222164c174b28020541dd8e3a 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java @@ -35,7 +35,7 @@ index ea336bdf2f15aabe74de82ef6c29b93573254e31..da3100d6577166e222164c174b280205 }); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 8df9bd656374d0b43af378c61c1df7b951085b58..fcd3e6bfb4b1d0aefcb34eaec1212b08498dd5af 100644 +index fcfee0f2b2b073b0c642684fddfb8d3c4eacf4f9..47503fa2feabf6615f250d13f25f080d19c2f560 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -67,6 +67,8 @@ import net.minecraft.world.InteractionHand; @@ -55,7 +55,7 @@ index 8df9bd656374d0b43af378c61c1df7b951085b58..fcd3e6bfb4b1d0aefcb34eaec1212b08 // Paper end public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper -@@ -1841,6 +1844,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -1843,6 +1846,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n nbt.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); nbt.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ())); } @@ -65,7 +65,7 @@ index 8df9bd656374d0b43af378c61c1df7b951085b58..fcd3e6bfb4b1d0aefcb34eaec1212b08 // Save entity's from mob spawner status if (spawnedViaMobSpawner) { nbt.putBoolean("Paper.FromMobSpawner", true); -@@ -1983,6 +1989,26 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -1985,6 +1991,26 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status diff --git a/patches/server/0314-Update-entity-Metadata-for-all-tracked-players.patch b/patches/server/0315-Update-entity-Metadata-for-all-tracked-players.patch similarity index 54% rename from patches/server/0314-Update-entity-Metadata-for-all-tracked-players.patch rename to patches/server/0315-Update-entity-Metadata-for-all-tracked-players.patch index 5b0902aa33..8804fcd546 100644 --- a/patches/server/0314-Update-entity-Metadata-for-all-tracked-players.patch +++ b/patches/server/0315-Update-entity-Metadata-for-all-tracked-players.patch @@ -4,27 +4,6 @@ Date: Fri, 22 Mar 2019 22:24:03 -0700 Subject: [PATCH] Update entity Metadata for all tracked players -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 8311d921ded1c81a1f561dc13db2010d2b7ce5d6..95ac30f56a9268f14d2518974c5a52e08f40ea18 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1281,6 +1281,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } else { - ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas()); - -+ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker - this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); - playerchunkmap_entitytracker.updatePlayers(this.level.players()); - if (entity instanceof ServerPlayer) { -@@ -1323,7 +1324,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - if (playerchunkmap_entitytracker1 != null) { - playerchunkmap_entitytracker1.broadcastRemoved(); - } -- -+ entity.tracker = null; // Paper - We're no longer tracked - } - - protected void tick() { diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java index ad9bbda31a4cdb306ca40f2b99e4b815c4f136bd..28afe2f238ded241acf77c3272a44068646b9133 100644 --- a/src/main/java/net/minecraft/server/level/ServerEntity.java @@ -62,15 +41,3 @@ index defebf7b45e4f006fa7e575b5dbd01ac1e231d5a..6c4266d847b1181a055fa425d5734032 } if (event.isCancelled()) { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index fcd3e6bfb4b1d0aefcb34eaec1212b08498dd5af..a5159198003e43ce272ae73941d2be47d50eedc9 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -300,6 +300,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n - public boolean forceExplosionKnockback; // SPIGOT-949 - public boolean persistentInvisibility = false; - public org.bukkit.Location origin; // Paper -+ public net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper - fast access to tracker - // Spigot start - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; diff --git a/patches/server/0315-Fire-event-on-GS4-query.patch b/patches/server/0316-Fire-event-on-GS4-query.patch similarity index 100% rename from patches/server/0315-Fire-event-on-GS4-query.patch rename to patches/server/0316-Fire-event-on-GS4-query.patch diff --git a/patches/server/0316-Implement-PlayerPostRespawnEvent.patch b/patches/server/0317-Implement-PlayerPostRespawnEvent.patch similarity index 100% rename from patches/server/0316-Implement-PlayerPostRespawnEvent.patch rename to patches/server/0317-Implement-PlayerPostRespawnEvent.patch diff --git a/patches/server/0317-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/patches/server/0318-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch similarity index 100% rename from patches/server/0317-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch rename to patches/server/0318-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch diff --git a/patches/server/0318-Server-Tick-Events.patch b/patches/server/0319-Server-Tick-Events.patch similarity index 100% rename from patches/server/0318-Server-Tick-Events.patch rename to patches/server/0319-Server-Tick-Events.patch diff --git a/patches/server/0319-PlayerDeathEvent-getItemsToKeep.patch b/patches/server/0320-PlayerDeathEvent-getItemsToKeep.patch similarity index 100% rename from patches/server/0319-PlayerDeathEvent-getItemsToKeep.patch rename to patches/server/0320-PlayerDeathEvent-getItemsToKeep.patch diff --git a/patches/server/0320-Optimize-Captured-TileEntity-Lookup.patch b/patches/server/0321-Optimize-Captured-TileEntity-Lookup.patch similarity index 90% rename from patches/server/0320-Optimize-Captured-TileEntity-Lookup.patch rename to patches/server/0321-Optimize-Captured-TileEntity-Lookup.patch index 12b5730d51..222154acf8 100644 --- a/patches/server/0320-Optimize-Captured-TileEntity-Lookup.patch +++ b/patches/server/0321-Optimize-Captured-TileEntity-Lookup.patch @@ -10,10 +10,10 @@ Optimize to check if the captured list even has values in it, and also to just do a get call since the value can never be null. diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index a1b713391c2445967c3b5a645304f193c013d551..9891e40972c1dc6bebe8ccec2bf82123dcdd7e94 100644 +index 834bbd63b4e45e8c89b4ece4eaf357f3cbe8e8ca..982029f2927b034835e95f45bb2937fff28f1cdf 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -869,9 +869,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -870,9 +870,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @Nullable public BlockEntity getTileEntity(BlockPos blockposition, boolean validate) { diff --git a/patches/server/0321-Add-Heightmap-API.patch b/patches/server/0322-Add-Heightmap-API.patch similarity index 100% rename from patches/server/0321-Add-Heightmap-API.patch rename to patches/server/0322-Add-Heightmap-API.patch diff --git a/patches/server/0322-Mob-Spawner-API-Enhancements.patch b/patches/server/0323-Mob-Spawner-API-Enhancements.patch similarity index 100% rename from patches/server/0322-Mob-Spawner-API-Enhancements.patch rename to patches/server/0323-Mob-Spawner-API-Enhancements.patch diff --git a/patches/server/0323-Fix-CB-call-to-changed-postToMainThread-method.patch b/patches/server/0324-Fix-CB-call-to-changed-postToMainThread-method.patch similarity index 100% rename from patches/server/0323-Fix-CB-call-to-changed-postToMainThread-method.patch rename to patches/server/0324-Fix-CB-call-to-changed-postToMainThread-method.patch diff --git a/patches/server/0324-Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/patches/server/0325-Fix-sounds-when-item-frames-are-modified-MC-123450.patch similarity index 100% rename from patches/server/0324-Fix-sounds-when-item-frames-are-modified-MC-123450.patch rename to patches/server/0325-Fix-sounds-when-item-frames-are-modified-MC-123450.patch diff --git a/patches/server/0325-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/patches/server/0326-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch similarity index 100% rename from patches/server/0325-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch rename to patches/server/0326-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch diff --git a/patches/server/0326-improve-CraftWorld-isChunkLoaded.patch b/patches/server/0327-improve-CraftWorld-isChunkLoaded.patch similarity index 100% rename from patches/server/0326-improve-CraftWorld-isChunkLoaded.patch rename to patches/server/0327-improve-CraftWorld-isChunkLoaded.patch diff --git a/patches/server/0327-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server/0328-Configurable-Keep-Spawn-Loaded-range-per-world.patch similarity index 98% rename from patches/server/0327-Configurable-Keep-Spawn-Loaded-range-per-world.patch rename to patches/server/0328-Configurable-Keep-Spawn-Loaded-range-per-world.patch index 82b32a8df4..bbd5eacb22 100644 --- a/patches/server/0327-Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ b/patches/server/0328-Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -85,7 +85,7 @@ index c8a59de4673d430fc8ec2e53315f107293122e7e..40e48c3f1199b127066732e3c8a6d40c // CraftBukkit start // this.updateSpawnFlags(); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 940e6587125df1f203cdeeefc31658635badea81..74a5dcde184c20129cb5fdcfb34ef1c3aecb1842 100644 +index c64557c70122bff6ea0c8d0b34f62daf680e4334..c778ce951c1ca648faa5d6c02b331d34ffc71156 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -61,6 +61,7 @@ import net.minecraft.network.protocol.game.ClientboundSoundEntityPacket; @@ -96,7 +96,7 @@ index 940e6587125df1f203cdeeefc31658635badea81..74a5dcde184c20129cb5fdcfb34ef1c3 import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerScoreboard; import net.minecraft.server.level.progress.ChunkProgressListener; -@@ -1486,12 +1487,88 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1510,12 +1511,88 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl return ((MapIndex) this.getServer().overworld().getDataStorage().computeIfAbsent(MapIndex::load, MapIndex::new, "idcounts")).getFreeAuxValueForMap(); } diff --git a/patches/server/0328-ChunkMapDistance-CME.patch b/patches/server/0329-ChunkMapDistance-CME.patch similarity index 100% rename from patches/server/0328-ChunkMapDistance-CME.patch rename to patches/server/0329-ChunkMapDistance-CME.patch diff --git a/patches/server/0329-Implement-CraftBlockSoundGroup.patch b/patches/server/0330-Implement-CraftBlockSoundGroup.patch similarity index 100% rename from patches/server/0329-Implement-CraftBlockSoundGroup.patch rename to patches/server/0330-Implement-CraftBlockSoundGroup.patch diff --git a/patches/server/0330-Chunk-debug-command.patch b/patches/server/0331-Chunk-debug-command.patch similarity index 99% rename from patches/server/0330-Chunk-debug-command.patch rename to patches/server/0331-Chunk-debug-command.patch index 5e3097224e..fc2006bbbd 100644 --- a/patches/server/0330-Chunk-debug-command.patch +++ b/patches/server/0331-Chunk-debug-command.patch @@ -468,7 +468,7 @@ index 71ac5cf0fdedcfe422bf6f5e6ffb15ce4138aa04..77bb2fb280293da4a38f9acc6503e849 public final ChunkGenerator generator; final ServerLevel level; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 74a5dcde184c20129cb5fdcfb34ef1c3aecb1842..736521c0925339dc74c2648641932104a947708e 100644 +index c778ce951c1ca648faa5d6c02b331d34ffc71156..1e09fdfbc1a8f1014ad0f7c5db7c709fc454270e 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -174,7 +174,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0331-Fix-World-isChunkGenerated-calls.patch b/patches/server/0332-Fix-World-isChunkGenerated-calls.patch similarity index 100% rename from patches/server/0331-Fix-World-isChunkGenerated-calls.patch rename to patches/server/0332-Fix-World-isChunkGenerated-calls.patch diff --git a/patches/server/0332-Show-blockstate-location-if-we-failed-to-read-it.patch b/patches/server/0333-Show-blockstate-location-if-we-failed-to-read-it.patch similarity index 100% rename from patches/server/0332-Show-blockstate-location-if-we-failed-to-read-it.patch rename to patches/server/0333-Show-blockstate-location-if-we-failed-to-read-it.patch diff --git a/patches/server/0333-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/patches/server/0334-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch similarity index 100% rename from patches/server/0333-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch rename to patches/server/0334-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch diff --git a/patches/server/0334-Configurable-projectile-relative-velocity.patch b/patches/server/0335-Configurable-projectile-relative-velocity.patch similarity index 100% rename from patches/server/0334-Configurable-projectile-relative-velocity.patch rename to patches/server/0335-Configurable-projectile-relative-velocity.patch diff --git a/patches/server/0335-offset-item-frame-ticking.patch b/patches/server/0336-offset-item-frame-ticking.patch similarity index 100% rename from patches/server/0335-offset-item-frame-ticking.patch rename to patches/server/0336-offset-item-frame-ticking.patch diff --git a/patches/server/0336-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/patches/server/0337-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch similarity index 100% rename from patches/server/0336-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch rename to patches/server/0337-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch diff --git a/patches/server/0337-Fix-MC-158900.patch b/patches/server/0338-Fix-MC-158900.patch similarity index 100% rename from patches/server/0337-Fix-MC-158900.patch rename to patches/server/0338-Fix-MC-158900.patch diff --git a/patches/server/0338-Prevent-consuming-the-wrong-itemstack.patch b/patches/server/0339-Prevent-consuming-the-wrong-itemstack.patch similarity index 100% rename from patches/server/0338-Prevent-consuming-the-wrong-itemstack.patch rename to patches/server/0339-Prevent-consuming-the-wrong-itemstack.patch diff --git a/patches/server/0339-Generator-Settings.patch b/patches/server/0340-Generator-Settings.patch similarity index 100% rename from patches/server/0339-Generator-Settings.patch rename to patches/server/0340-Generator-Settings.patch diff --git a/patches/server/0340-Fix-MC-161754.patch b/patches/server/0341-Fix-MC-161754.patch similarity index 100% rename from patches/server/0340-Fix-MC-161754.patch rename to patches/server/0341-Fix-MC-161754.patch diff --git a/patches/server/0341-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/patches/server/0342-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch similarity index 100% rename from patches/server/0341-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch rename to patches/server/0342-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch diff --git a/patches/server/0342-Expose-the-internal-current-tick.patch b/patches/server/0343-Expose-the-internal-current-tick.patch similarity index 100% rename from patches/server/0342-Expose-the-internal-current-tick.patch rename to patches/server/0343-Expose-the-internal-current-tick.patch diff --git a/patches/server/0343-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/patches/server/0344-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch similarity index 100% rename from patches/server/0343-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch rename to patches/server/0344-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch diff --git a/patches/server/0344-Add-option-to-disable-pillager-patrols.patch b/patches/server/0345-Add-option-to-disable-pillager-patrols.patch similarity index 100% rename from patches/server/0344-Add-option-to-disable-pillager-patrols.patch rename to patches/server/0345-Add-option-to-disable-pillager-patrols.patch diff --git a/patches/server/0345-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/patches/server/0346-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch similarity index 100% rename from patches/server/0345-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch rename to patches/server/0346-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch diff --git a/patches/server/0346-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/patches/server/0347-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch similarity index 100% rename from patches/server/0346-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch rename to patches/server/0347-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch diff --git a/patches/server/0347-MC-145656-Fix-Follow-Range-Initial-Target.patch b/patches/server/0348-MC-145656-Fix-Follow-Range-Initial-Target.patch similarity index 100% rename from patches/server/0347-MC-145656-Fix-Follow-Range-Initial-Target.patch rename to patches/server/0348-MC-145656-Fix-Follow-Range-Initial-Target.patch diff --git a/patches/server/0348-Optimize-Hoppers.patch b/patches/server/0349-Optimize-Hoppers.patch similarity index 100% rename from patches/server/0348-Optimize-Hoppers.patch rename to patches/server/0349-Optimize-Hoppers.patch diff --git a/patches/server/0349-PlayerDeathEvent-shouldDropExperience.patch b/patches/server/0350-PlayerDeathEvent-shouldDropExperience.patch similarity index 100% rename from patches/server/0349-PlayerDeathEvent-shouldDropExperience.patch rename to patches/server/0350-PlayerDeathEvent-shouldDropExperience.patch diff --git a/patches/server/0350-Prevent-bees-loading-chunks-checking-hive-position.patch b/patches/server/0351-Prevent-bees-loading-chunks-checking-hive-position.patch similarity index 100% rename from patches/server/0350-Prevent-bees-loading-chunks-checking-hive-position.patch rename to patches/server/0351-Prevent-bees-loading-chunks-checking-hive-position.patch diff --git a/patches/server/0351-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/patches/server/0352-Don-t-load-Chunks-from-Hoppers-and-other-things.patch similarity index 100% rename from patches/server/0351-Don-t-load-Chunks-from-Hoppers-and-other-things.patch rename to patches/server/0352-Don-t-load-Chunks-from-Hoppers-and-other-things.patch diff --git a/patches/server/0352-Guard-against-serializing-mismatching-chunk-coordina.patch b/patches/server/0353-Guard-against-serializing-mismatching-chunk-coordina.patch similarity index 100% rename from patches/server/0352-Guard-against-serializing-mismatching-chunk-coordina.patch rename to patches/server/0353-Guard-against-serializing-mismatching-chunk-coordina.patch diff --git a/patches/server/0353-Optimise-IEntityAccess-getPlayerByUUID.patch b/patches/server/0354-Optimise-IEntityAccess-getPlayerByUUID.patch similarity index 90% rename from patches/server/0353-Optimise-IEntityAccess-getPlayerByUUID.patch rename to patches/server/0354-Optimise-IEntityAccess-getPlayerByUUID.patch index 7ec8915584..9b8cfb93e6 100644 --- a/patches/server/0353-Optimise-IEntityAccess-getPlayerByUUID.patch +++ b/patches/server/0354-Optimise-IEntityAccess-getPlayerByUUID.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Optimise IEntityAccess#getPlayerByUUID Use the world entity map instead of iterating over all players diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 736521c0925339dc74c2648641932104a947708e..eabf8fa6e8802ebea8dbe124363bb085849af5d9 100644 +index 1e09fdfbc1a8f1014ad0f7c5db7c709fc454270e..fe98fa03548922903e4fb352fbdfeeaac87450df 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -281,6 +281,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -284,6 +284,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; // Paper end diff --git a/patches/server/0354-Fix-items-not-falling-correctly.patch b/patches/server/0355-Fix-items-not-falling-correctly.patch similarity index 100% rename from patches/server/0354-Fix-items-not-falling-correctly.patch rename to patches/server/0355-Fix-items-not-falling-correctly.patch diff --git a/patches/server/0355-Lag-compensate-eating.patch b/patches/server/0356-Lag-compensate-eating.patch similarity index 100% rename from patches/server/0355-Lag-compensate-eating.patch rename to patches/server/0356-Lag-compensate-eating.patch diff --git a/patches/server/0356-Optimize-call-to-getFluid-for-explosions.patch b/patches/server/0357-Optimize-call-to-getFluid-for-explosions.patch similarity index 100% rename from patches/server/0356-Optimize-call-to-getFluid-for-explosions.patch rename to patches/server/0357-Optimize-call-to-getFluid-for-explosions.patch diff --git a/patches/server/0357-Fix-last-firework-in-stack-not-having-effects-when-d.patch b/patches/server/0358-Fix-last-firework-in-stack-not-having-effects-when-d.patch similarity index 100% rename from patches/server/0357-Fix-last-firework-in-stack-not-having-effects-when-d.patch rename to patches/server/0358-Fix-last-firework-in-stack-not-having-effects-when-d.patch diff --git a/patches/server/0358-Add-effect-to-block-break-naturally.patch b/patches/server/0359-Add-effect-to-block-break-naturally.patch similarity index 100% rename from patches/server/0358-Add-effect-to-block-break-naturally.patch rename to patches/server/0359-Add-effect-to-block-break-naturally.patch diff --git a/patches/server/0359-Entity-Activation-Range-2.0.patch b/patches/server/0360-Entity-Activation-Range-2.0.patch similarity index 97% rename from patches/server/0359-Entity-Activation-Range-2.0.patch rename to patches/server/0360-Entity-Activation-Range-2.0.patch index 426f54cefb..8496b9c17e 100644 --- a/patches/server/0359-Entity-Activation-Range-2.0.patch +++ b/patches/server/0360-Entity-Activation-Range-2.0.patch @@ -14,7 +14,7 @@ Adds flying monsters to control ghast and phantoms Adds villagers as separate config diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index eabf8fa6e8802ebea8dbe124363bb085849af5d9..67b9daee8d7e55fdf2015e6616f393f176b1ca96 100644 +index fe98fa03548922903e4fb352fbdfeeaac87450df..8d72e68fe8f7d0a770264f54c539ea11f5e1d8da 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -2,7 +2,6 @@ package net.minecraft.server.level; @@ -41,7 +41,7 @@ index eabf8fa6e8802ebea8dbe124363bb085849af5d9..67b9daee8d7e55fdf2015e6616f393f1 import net.minecraft.world.level.entity.EntityPersistentStorage; import net.minecraft.world.level.entity.EntityTickList; import net.minecraft.world.level.entity.EntityTypeTest; -@@ -888,17 +885,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -891,17 +888,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl ++TimingHistory.entityTicks; // Paper - timings // Spigot start co.aikar.timings.Timing timer; // Paper @@ -63,7 +63,7 @@ index eabf8fa6e8802ebea8dbe124363bb085849af5d9..67b9daee8d7e55fdf2015e6616f393f1 try { // Paper end - timings entity.isInLava(); -@@ -909,9 +906,13 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -912,9 +909,13 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl return Registry.ENTITY_TYPE.getKey(entity.getType()).toString(); }); gameprofilerfiller.incrementCounter("tickNonPassenger"); @@ -77,7 +77,7 @@ index eabf8fa6e8802ebea8dbe124363bb085849af5d9..67b9daee8d7e55fdf2015e6616f393f1 Iterator iterator = entity.getPassengers().iterator(); while (iterator.hasNext()) { -@@ -920,13 +921,18 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -923,13 +924,18 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl this.tickPassenger(entity, entity1); } @@ -97,7 +97,7 @@ index eabf8fa6e8802ebea8dbe124363bb085849af5d9..67b9daee8d7e55fdf2015e6616f393f1 passenger.setOldPosAndRot(); ++passenger.tickCount; ProfilerFiller gameprofilerfiller = this.getProfiler(); -@@ -935,8 +941,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -938,8 +944,17 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl return Registry.ENTITY_TYPE.getKey(passenger.getType()).toString(); }); gameprofilerfiller.incrementCounter("tickPassenger"); @@ -115,7 +115,7 @@ index eabf8fa6e8802ebea8dbe124363bb085849af5d9..67b9daee8d7e55fdf2015e6616f393f1 gameprofilerfiller.pop(); Iterator iterator = passenger.getPassengers().iterator(); -@@ -946,6 +961,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -949,6 +964,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl this.tickPassenger(passenger, entity2); } @@ -124,10 +124,10 @@ index eabf8fa6e8802ebea8dbe124363bb085849af5d9..67b9daee8d7e55fdf2015e6616f393f1 } else { passenger.stopRiding(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a5159198003e43ce272ae73941d2be47d50eedc9..fffeba61e9af5c69876921b48241edb881af2a64 100644 +index 47503fa2feabf6615f250d13f25f080d19c2f560..6b93b4e7717efbe68de3f1afe4843023e22c06bb 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -275,7 +275,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -277,7 +277,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public boolean noCulling; public boolean hasImpulse; public int portalCooldown; @@ -136,7 +136,7 @@ index a5159198003e43ce272ae73941d2be47d50eedc9..fffeba61e9af5c69876921b48241edb8 protected int portalTime; protected BlockPos portalEntrancePos; private boolean invulnerable; -@@ -305,6 +305,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -306,6 +306,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); public final boolean defaultActivationState; public long activatedTick = Integer.MIN_VALUE; @@ -144,7 +144,7 @@ index a5159198003e43ce272ae73941d2be47d50eedc9..fffeba61e9af5c69876921b48241edb8 public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one protected int numCollisions = 0; // Paper public void inactiveTick() { } -@@ -746,6 +747,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -747,6 +748,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } else { this.wasOnFire = this.isOnFire(); if (movementType == MoverType.PISTON) { @@ -152,7 +152,7 @@ index a5159198003e43ce272ae73941d2be47d50eedc9..fffeba61e9af5c69876921b48241edb8 movement = this.limitPistonMovement(movement); if (movement.equals(Vec3.ZERO)) { return; -@@ -758,6 +760,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -759,6 +761,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n this.stuckSpeedMultiplier = Vec3.ZERO; this.setDeltaMovement(Vec3.ZERO); } @@ -348,10 +348,10 @@ index aec77679584a2acab5818e26e2586b5316118e84..9c7cb4f11c429ca5006cf5e178326ead super.customServerAiStep(); } diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 9891e40972c1dc6bebe8ccec2bf82123dcdd7e94..ddcde88a8c8b748b4dc2583b4dfd0fb8ea9e201e 100644 +index 982029f2927b034835e95f45bb2937fff28f1cdf..aa198e9f2755734eac591bd3f94679518e9d7270 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -153,6 +153,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -154,6 +154,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public long ticksPerWaterSpawns; public long ticksPerWaterAmbientSpawns; public long ticksPerAmbientSpawns; diff --git a/patches/server/0360-Increase-Light-Queue-Size.patch b/patches/server/0361-Increase-Light-Queue-Size.patch similarity index 100% rename from patches/server/0360-Increase-Light-Queue-Size.patch rename to patches/server/0361-Increase-Light-Queue-Size.patch diff --git a/patches/server/0361-Fix-Light-Command.patch b/patches/server/0362-Fix-Light-Command.patch similarity index 100% rename from patches/server/0361-Fix-Light-Command.patch rename to patches/server/0362-Fix-Light-Command.patch diff --git a/patches/server/0362-No-Tick-view-distance-implementation.patch b/patches/server/0363-No-Tick-view-distance-implementation.patch similarity index 99% rename from patches/server/0362-No-Tick-view-distance-implementation.patch rename to patches/server/0363-No-Tick-view-distance-implementation.patch index 3087bd1eca..50391a3d4f 100644 --- a/patches/server/0362-No-Tick-view-distance-implementation.patch +++ b/patches/server/0363-No-Tick-view-distance-implementation.patch @@ -556,10 +556,10 @@ index bcc946d2747443c34ee8ac2485a5ab41773c93af..2730923bd0bf3b0f928765b9e09e2299 while (iterator.hasNext()) { diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index ddcde88a8c8b748b4dc2583b4dfd0fb8ea9e201e..07e81fa1119bba4981e34e70b9e67f43280f8071 100644 +index aa198e9f2755734eac591bd3f94679518e9d7270..507a70521a97c463d6fd22b788c39e9f458971c3 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -521,8 +521,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -522,8 +522,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); } diff --git a/patches/server/0363-Implement-alternative-item-despawn-rate.patch b/patches/server/0364-Implement-alternative-item-despawn-rate.patch similarity index 100% rename from patches/server/0363-Implement-alternative-item-despawn-rate.patch rename to patches/server/0364-Implement-alternative-item-despawn-rate.patch diff --git a/patches/server/0364-Tracking-Range-Improvements.patch b/patches/server/0365-Tracking-Range-Improvements.patch similarity index 100% rename from patches/server/0364-Tracking-Range-Improvements.patch rename to patches/server/0365-Tracking-Range-Improvements.patch diff --git a/patches/server/0365-Fix-items-vanishing-through-end-portal.patch b/patches/server/0366-Fix-items-vanishing-through-end-portal.patch similarity index 89% rename from patches/server/0365-Fix-items-vanishing-through-end-portal.patch rename to patches/server/0366-Fix-items-vanishing-through-end-portal.patch index e32fc1978b..d64b934744 100644 --- a/patches/server/0365-Fix-items-vanishing-through-end-portal.patch +++ b/patches/server/0366-Fix-items-vanishing-through-end-portal.patch @@ -13,10 +13,10 @@ Quickly loading the exact world spawn chunk before searching the heightmap resolves the issue without having to load all spawn chunks. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index fffeba61e9af5c69876921b48241edb881af2a64..3d3286070c9c4db6d6487e119070794dadf493bd 100644 +index 6b93b4e7717efbe68de3f1afe4843023e22c06bb..999cf6f54133fb70bff56f93347e9916b58e1e3a 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2983,6 +2983,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -2984,6 +2984,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n BlockPos blockposition1; if (flag1) { diff --git a/patches/server/0366-implement-optional-per-player-mob-spawns.patch b/patches/server/0367-implement-optional-per-player-mob-spawns.patch similarity index 100% rename from patches/server/0366-implement-optional-per-player-mob-spawns.patch rename to patches/server/0367-implement-optional-per-player-mob-spawns.patch diff --git a/patches/server/0367-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/0368-Bees-get-gravity-in-void.-Fixes-MC-167279.patch similarity index 100% rename from patches/server/0367-Bees-get-gravity-in-void.-Fixes-MC-167279.patch rename to patches/server/0368-Bees-get-gravity-in-void.-Fixes-MC-167279.patch diff --git a/patches/server/0368-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server/0369-Optimise-getChunkAt-calls-for-loaded-chunks.patch similarity index 100% rename from patches/server/0368-Optimise-getChunkAt-calls-for-loaded-chunks.patch rename to patches/server/0369-Optimise-getChunkAt-calls-for-loaded-chunks.patch diff --git a/patches/server/0369-Allow-overriding-the-java-version-check.patch b/patches/server/0370-Allow-overriding-the-java-version-check.patch similarity index 100% rename from patches/server/0369-Allow-overriding-the-java-version-check.patch rename to patches/server/0370-Allow-overriding-the-java-version-check.patch diff --git a/patches/server/0370-Add-ThrownEggHatchEvent.patch b/patches/server/0371-Add-ThrownEggHatchEvent.patch similarity index 100% rename from patches/server/0370-Add-ThrownEggHatchEvent.patch rename to patches/server/0371-Add-ThrownEggHatchEvent.patch diff --git a/patches/server/0371-Optimise-random-block-ticking.patch b/patches/server/0372-Optimise-random-block-ticking.patch similarity index 97% rename from patches/server/0371-Optimise-random-block-ticking.patch rename to patches/server/0372-Optimise-random-block-ticking.patch index e6d451fad9..d8b3340523 100644 --- a/patches/server/0371-Optimise-random-block-ticking.patch +++ b/patches/server/0372-Optimise-random-block-ticking.patch @@ -71,10 +71,10 @@ index 0000000000000000000000000000000000000000..3edc8e52e06a62ce9f8cc734fd7458b3 + } +} diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 67b9daee8d7e55fdf2015e6616f393f176b1ca96..ecb9c5a1958c89494417bdb3e6c6363f3fc84534 100644 +index 8d72e68fe8f7d0a770264f54c539ea11f5e1d8da..50efe1bd6a62b71007bf3274f323704be1477ce7 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -664,7 +664,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -667,7 +667,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl }); } @@ -88,7 +88,7 @@ index 67b9daee8d7e55fdf2015e6616f393f176b1ca96..ecb9c5a1958c89494417bdb3e6c6363f ChunkPos chunkcoordintpair = chunk.getPos(); boolean flag = this.isRaining(); int j = chunkcoordintpair.getMinBlockX(); -@@ -672,10 +677,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -675,10 +680,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl ProfilerFiller gameprofilerfiller = this.getProfiler(); gameprofilerfiller.push("thunder"); @@ -101,7 +101,7 @@ index 67b9daee8d7e55fdf2015e6616f393f176b1ca96..ecb9c5a1958c89494417bdb3e6c6363f if (this.isRainingAt(blockposition)) { DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper -@@ -698,66 +703,81 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -701,66 +706,81 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } gameprofilerfiller.popPush("iceandsnow"); @@ -266,10 +266,10 @@ index e638d982b4bd1d261a7282cad6dab98ad0b55213..e305173fd1652a8b88ae8a9b94d0fae0 public BlockPos getHomePos() { // Paper - public diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 07e81fa1119bba4981e34e70b9e67f43280f8071..5fccec12c0325dd9873905c5c3559128c3b4d9ad 100644 +index 507a70521a97c463d6fd22b788c39e9f458971c3..ea455e8aa7db5e9c397875e1fc8716cd52044c05 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1299,10 +1299,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1300,10 +1300,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public abstract TagContainer getTagManager(); public BlockPos getBlockRandomPos(int x, int y, int z, int l) { diff --git a/patches/server/0372-Entity-Jump-API.patch b/patches/server/0373-Entity-Jump-API.patch similarity index 100% rename from patches/server/0372-Entity-Jump-API.patch rename to patches/server/0373-Entity-Jump-API.patch diff --git a/patches/server/0373-Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/0374-Add-option-to-nerf-pigmen-from-nether-portals.patch similarity index 92% rename from patches/server/0373-Add-option-to-nerf-pigmen-from-nether-portals.patch rename to patches/server/0374-Add-option-to-nerf-pigmen-from-nether-portals.patch index bd3b08c4c3..f33d6ed44f 100644 --- a/patches/server/0373-Add-option-to-nerf-pigmen-from-nether-portals.patch +++ b/patches/server/0374-Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -21,10 +21,10 @@ index 16f013ffe992a934e9d0b32e764a14a8fd204449..6c7e90f9939d42fdf8d40dd7ec0a6a86 private void lightQueueSize() { lightQueueSize = getInt("light-queue-size", lightQueueSize); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 3d3286070c9c4db6d6487e119070794dadf493bd..facb09e49d92d22dbcde7d187d4ba1c9a04202a9 100644 +index 999cf6f54133fb70bff56f93347e9916b58e1e3a..d97319136d6cded2a12cb9ae4f9aa921ff59882c 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -307,6 +307,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -308,6 +308,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public long activatedTick = Integer.MIN_VALUE; public boolean isTemporarilyActive = false; // Paper public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one @@ -32,7 +32,7 @@ index 3d3286070c9c4db6d6487e119070794dadf493bd..facb09e49d92d22dbcde7d187d4ba1c9 protected int numCollisions = 0; // Paper public void inactiveTick() { } // Spigot end -@@ -1861,6 +1862,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -1862,6 +1863,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n if (spawnedViaMobSpawner) { nbt.putBoolean("Paper.FromMobSpawner", true); } @@ -42,7 +42,7 @@ index 3d3286070c9c4db6d6487e119070794dadf493bd..facb09e49d92d22dbcde7d187d4ba1c9 // Paper end return nbt; } catch (Throwable throwable) { -@@ -1999,6 +2003,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -2000,6 +2004,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status diff --git a/patches/server/0374-Make-the-GUI-graph-fancier.patch b/patches/server/0375-Make-the-GUI-graph-fancier.patch similarity index 100% rename from patches/server/0374-Make-the-GUI-graph-fancier.patch rename to patches/server/0375-Make-the-GUI-graph-fancier.patch diff --git a/patches/server/0375-add-hand-to-BlockMultiPlaceEvent.patch b/patches/server/0376-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from patches/server/0375-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/server/0376-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/patches/server/0376-Prevent-teleporting-dead-entities.patch b/patches/server/0377-Prevent-teleporting-dead-entities.patch similarity index 100% rename from patches/server/0376-Prevent-teleporting-dead-entities.patch rename to patches/server/0377-Prevent-teleporting-dead-entities.patch diff --git a/patches/server/0377-Validate-tripwire-hook-placement-before-update.patch b/patches/server/0378-Validate-tripwire-hook-placement-before-update.patch similarity index 100% rename from patches/server/0377-Validate-tripwire-hook-placement-before-update.patch rename to patches/server/0378-Validate-tripwire-hook-placement-before-update.patch diff --git a/patches/server/0378-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server/0379-Add-option-to-allow-iron-golems-to-spawn-in-air.patch similarity index 100% rename from patches/server/0378-Add-option-to-allow-iron-golems-to-spawn-in-air.patch rename to patches/server/0379-Add-option-to-allow-iron-golems-to-spawn-in-air.patch diff --git a/patches/server/0379-Configurable-chance-of-villager-zombie-infection.patch b/patches/server/0380-Configurable-chance-of-villager-zombie-infection.patch similarity index 100% rename from patches/server/0379-Configurable-chance-of-villager-zombie-infection.patch rename to patches/server/0380-Configurable-chance-of-villager-zombie-infection.patch diff --git a/patches/server/0380-Optimise-Chunk-getFluid.patch b/patches/server/0381-Optimise-Chunk-getFluid.patch similarity index 100% rename from patches/server/0380-Optimise-Chunk-getFluid.patch rename to patches/server/0381-Optimise-Chunk-getFluid.patch diff --git a/patches/server/0381-Optimise-TickListServer-by-rewriting-it.patch b/patches/server/0382-Optimise-TickListServer-by-rewriting-it.patch similarity index 99% rename from patches/server/0381-Optimise-TickListServer-by-rewriting-it.patch rename to patches/server/0382-Optimise-TickListServer-by-rewriting-it.patch index 20aa3203b6..40dbc4fec4 100644 --- a/patches/server/0381-Optimise-TickListServer-by-rewriting-it.patch +++ b/patches/server/0382-Optimise-TickListServer-by-rewriting-it.patch @@ -941,10 +941,10 @@ index 56aa640eb0096e5c5f1a34d6f11a4dd9ac8770df..a81c773cc281ba390d3ce44c52c43710 public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier supplier) { this.level = world; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index ecb9c5a1958c89494417bdb3e6c6363f3fc84534..385b8e707406173ea5258aff87af719ce93aecf3 100644 +index 50efe1bd6a62b71007bf3274f323704be1477ce7..a43839ddd468d7b61d5609f22fb1e9fcd873590a 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -286,6 +286,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -289,6 +289,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } // Paper end @@ -960,7 +960,7 @@ index ecb9c5a1958c89494417bdb3e6c6363f3fc84534..385b8e707406173ea5258aff87af719c // Add env and gen to constructor, WorldData -> WorldDataServer public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error -@@ -302,13 +311,19 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -305,13 +314,19 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl DefaultedRegistry registryblocks = Registry.BLOCK; Objects.requireNonNull(registryblocks); @@ -981,7 +981,7 @@ index ecb9c5a1958c89494417bdb3e6c6363f3fc84534..385b8e707406173ea5258aff87af719c this.navigatingMobs = new ObjectOpenHashSet(); this.blockEvents = new ObjectLinkedOpenHashSet(); this.dragonParts = new Int2ObjectOpenHashMap(); -@@ -629,7 +644,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -632,7 +647,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl if (this.tickTime) { long i = this.levelData.getGameTime() + 1L; diff --git a/patches/server/0382-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/0383-Pillager-patrol-spawn-settings-and-per-player-option.patch similarity index 100% rename from patches/server/0382-Pillager-patrol-spawn-settings-and-per-player-option.patch rename to patches/server/0383-Pillager-patrol-spawn-settings-and-per-player-option.patch diff --git a/patches/server/0383-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server/0384-Remote-Connections-shouldn-t-hold-up-shutdown.patch similarity index 100% rename from patches/server/0383-Remote-Connections-shouldn-t-hold-up-shutdown.patch rename to patches/server/0384-Remote-Connections-shouldn-t-hold-up-shutdown.patch diff --git a/patches/server/0384-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/0385-Do-not-allow-bees-to-load-chunks-for-beehives.patch similarity index 100% rename from patches/server/0384-Do-not-allow-bees-to-load-chunks-for-beehives.patch rename to patches/server/0385-Do-not-allow-bees-to-load-chunks-for-beehives.patch diff --git a/patches/server/0385-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server/0386-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch similarity index 92% rename from patches/server/0385-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch rename to patches/server/0386-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch index 9f991f3e0d..6a201d9358 100644 --- a/patches/server/0385-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ b/patches/server/0386-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -26,10 +26,10 @@ index e1498a5a8e664b922c77a8524ed2ea38c91834ce..71d5c298e14869d9d44226aeb6ffe3f0 EntityType entitytypes = entity.getType(); int i = entitytypes.clientTrackingRange() * 16; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 385b8e707406173ea5258aff87af719ce93aecf3..5944c44eadca550671d7740af5756985afede39d 100644 +index a43839ddd468d7b61d5609f22fb1e9fcd873590a..da85bfe5de9dcd6d51605ce9b023265b5a5f2936 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -2100,7 +2100,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -2124,7 +2124,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl public void onTrackingStart(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot @@ -38,7 +38,7 @@ index 385b8e707406173ea5258aff87af719ce93aecf3..5944c44eadca550671d7740af5756985 if (entity instanceof ServerPlayer) { ServerLevel.this.players.add((ServerPlayer) entity); ServerLevel.this.updateSleepingPlayerList(); -@@ -2122,6 +2122,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -2146,6 +2146,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } entity.valid = true; // CraftBukkit diff --git a/patches/server/0386-Optimize-Collision-to-not-load-chunks.patch b/patches/server/0387-Optimize-Collision-to-not-load-chunks.patch similarity index 97% rename from patches/server/0386-Optimize-Collision-to-not-load-chunks.patch rename to patches/server/0387-Optimize-Collision-to-not-load-chunks.patch index d2e15c6828..2387b545f1 100644 --- a/patches/server/0386-Optimize-Collision-to-not-load-chunks.patch +++ b/patches/server/0387-Optimize-Collision-to-not-load-chunks.patch @@ -26,7 +26,7 @@ index 2730923bd0bf3b0f928765b9e09e2299fa9a393d..f98a1c32e0c209473cf7268cbd8245ab entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index facb09e49d92d22dbcde7d187d4ba1c9a04202a9..85c0656ee8c91cab1e269daea631977c4284295f 100644 +index d97319136d6cded2a12cb9ae4f9aa921ff59882c..21bcb811eb002714db7a9be70133bda7a722ba65 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -172,6 +172,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @@ -36,7 +36,7 @@ index facb09e49d92d22dbcde7d187d4ba1c9a04202a9..85c0656ee8c91cab1e269daea631977c + public boolean collisionLoadChunks = false; // Paper private CraftEntity bukkitEntity; - public CraftEntity getBukkitEntity() { + public net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java index b980c26ab5cac02e03525177a9dc4fb0b6a2f9f6..2a784a8342e708e0813c7076a2ca8e429446ffd3 100644 --- a/src/main/java/net/minecraft/world/level/CollisionGetter.java diff --git a/patches/server/0387-Don-t-tick-dead-players.patch b/patches/server/0388-Don-t-tick-dead-players.patch similarity index 100% rename from patches/server/0387-Don-t-tick-dead-players.patch rename to patches/server/0388-Don-t-tick-dead-players.patch diff --git a/patches/server/0388-Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server/0389-Dead-Player-s-shouldn-t-be-able-to-move.patch similarity index 100% rename from patches/server/0388-Dead-Player-s-shouldn-t-be-able-to-move.patch rename to patches/server/0389-Dead-Player-s-shouldn-t-be-able-to-move.patch diff --git a/patches/server/0389-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/0390-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch similarity index 100% rename from patches/server/0389-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch rename to patches/server/0390-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch diff --git a/patches/server/0390-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/patches/server/0391-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch similarity index 97% rename from patches/server/0390-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch rename to patches/server/0391-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch index 6f6470fd04..7f241bc382 100644 --- a/patches/server/0390-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch +++ b/patches/server/0391-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch @@ -226,10 +226,10 @@ index 34183527a23650706a9249ffac0182cb77b18086..90decfade57b2f17cdcc9188962c2d21 // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task public boolean pollTask() { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 5944c44eadca550671d7740af5756985afede39d..fd3159f7767faaa55ed49eba237e30a2dbd4fa92 100644 +index da85bfe5de9dcd6d51605ce9b023265b5a5f2936..f10fad84e4f36f9158383b327170593f273cecd9 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -578,6 +578,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -581,6 +581,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } timings.scheduledBlocks.stopTiming(); // Paper @@ -237,7 +237,7 @@ index 5944c44eadca550671d7740af5756985afede39d..fd3159f7767faaa55ed49eba237e30a2 gameprofilerfiller.popPush("raid"); this.timings.raids.startTiming(); // Paper - timings this.raids.tick(); -@@ -586,6 +587,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -589,6 +590,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl timings.doSounds.startTiming(); // Spigot this.runBlockEvents(); timings.doSounds.stopTiming(); // Spigot @@ -245,7 +245,7 @@ index 5944c44eadca550671d7740af5756985afede39d..fd3159f7767faaa55ed49eba237e30a2 this.handlingTick = false; gameprofilerfiller.pop(); boolean flag3 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players -@@ -632,10 +634,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -635,10 +637,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl timings.entityTick.stopTiming(); // Spigot timings.tickEntities.stopTiming(); // Spigot gameprofilerfiller.pop(); diff --git a/patches/server/0391-Don-t-move-existing-players-to-world-spawn.patch b/patches/server/0392-Don-t-move-existing-players-to-world-spawn.patch similarity index 100% rename from patches/server/0391-Don-t-move-existing-players-to-world-spawn.patch rename to patches/server/0392-Don-t-move-existing-players-to-world-spawn.patch diff --git a/patches/server/0392-Add-tick-times-API-and-mspt-command.patch b/patches/server/0393-Add-tick-times-API-and-mspt-command.patch similarity index 100% rename from patches/server/0392-Add-tick-times-API-and-mspt-command.patch rename to patches/server/0393-Add-tick-times-API-and-mspt-command.patch diff --git a/patches/server/0393-Expose-MinecraftServer-isRunning.patch b/patches/server/0394-Expose-MinecraftServer-isRunning.patch similarity index 100% rename from patches/server/0393-Expose-MinecraftServer-isRunning.patch rename to patches/server/0394-Expose-MinecraftServer-isRunning.patch diff --git a/patches/server/0394-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/0395-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 100% rename from patches/server/0394-Add-Raw-Byte-ItemStack-Serialization.patch rename to patches/server/0395-Add-Raw-Byte-ItemStack-Serialization.patch diff --git a/patches/server/0395-Remove-streams-from-Mob-AI-System.patch b/patches/server/0396-Remove-streams-from-Mob-AI-System.patch similarity index 100% rename from patches/server/0395-Remove-streams-from-Mob-AI-System.patch rename to patches/server/0396-Remove-streams-from-Mob-AI-System.patch diff --git a/patches/server/0396-Async-command-map-building.patch b/patches/server/0397-Async-command-map-building.patch similarity index 100% rename from patches/server/0396-Async-command-map-building.patch rename to patches/server/0397-Async-command-map-building.patch diff --git a/patches/server/0397-Improved-Watchdog-Support.patch b/patches/server/0398-Improved-Watchdog-Support.patch similarity index 99% rename from patches/server/0397-Improved-Watchdog-Support.patch rename to patches/server/0398-Improved-Watchdog-Support.patch index 52408524a3..77f803c039 100644 --- a/patches/server/0397-Improved-Watchdog-Support.patch +++ b/patches/server/0398-Improved-Watchdog-Support.patch @@ -299,10 +299,10 @@ index 0ef3c4982df88a7991a56d983ac733daa8adc507..cdd797c6fc7507a0e6376f7d9c521be8 } diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 5fccec12c0325dd9873905c5c3559128c3b4d9ad..03271675b4997588bd8f6774856aef25cdd4fa05 100644 +index ea455e8aa7db5e9c397875e1fc8716cd52044c05..6aeb3ff79f08ade7ddd0d328d1a01514a91f671a 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -836,6 +836,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -837,6 +837,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { try { tickConsumer.accept(entity); } catch (Throwable throwable) { diff --git a/patches/server/0398-Optimize-Pathfinding.patch b/patches/server/0399-Optimize-Pathfinding.patch similarity index 100% rename from patches/server/0398-Optimize-Pathfinding.patch rename to patches/server/0399-Optimize-Pathfinding.patch diff --git a/patches/server/0399-Reduce-Either-Optional-allocation.patch b/patches/server/0400-Reduce-Either-Optional-allocation.patch similarity index 100% rename from patches/server/0399-Reduce-Either-Optional-allocation.patch rename to patches/server/0400-Reduce-Either-Optional-allocation.patch diff --git a/patches/server/0400-Remove-streams-from-PairedQueue.patch b/patches/server/0401-Remove-streams-from-PairedQueue.patch similarity index 100% rename from patches/server/0400-Remove-streams-from-PairedQueue.patch rename to patches/server/0401-Remove-streams-from-PairedQueue.patch diff --git a/patches/server/0401-Reduce-memory-footprint-of-NBTTagCompound.patch b/patches/server/0402-Reduce-memory-footprint-of-NBTTagCompound.patch similarity index 100% rename from patches/server/0401-Reduce-memory-footprint-of-NBTTagCompound.patch rename to patches/server/0402-Reduce-memory-footprint-of-NBTTagCompound.patch diff --git a/patches/server/0402-Prevent-opening-inventories-when-frozen.patch b/patches/server/0403-Prevent-opening-inventories-when-frozen.patch similarity index 100% rename from patches/server/0402-Prevent-opening-inventories-when-frozen.patch rename to patches/server/0403-Prevent-opening-inventories-when-frozen.patch diff --git a/patches/server/0403-Optimise-ArraySetSorted-removeIf.patch b/patches/server/0404-Optimise-ArraySetSorted-removeIf.patch similarity index 100% rename from patches/server/0403-Optimise-ArraySetSorted-removeIf.patch rename to patches/server/0404-Optimise-ArraySetSorted-removeIf.patch diff --git a/patches/server/0404-Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server/0405-Don-t-run-entity-collision-code-if-not-needed.patch similarity index 100% rename from patches/server/0404-Don-t-run-entity-collision-code-if-not-needed.patch rename to patches/server/0405-Don-t-run-entity-collision-code-if-not-needed.patch diff --git a/patches/server/0405-Restrict-vanilla-teleport-command-to-valid-locations.patch b/patches/server/0406-Restrict-vanilla-teleport-command-to-valid-locations.patch similarity index 100% rename from patches/server/0405-Restrict-vanilla-teleport-command-to-valid-locations.patch rename to patches/server/0406-Restrict-vanilla-teleport-command-to-valid-locations.patch diff --git a/patches/server/0406-Implement-Player-Client-Options-API.patch b/patches/server/0407-Implement-Player-Client-Options-API.patch similarity index 100% rename from patches/server/0406-Implement-Player-Client-Options-API.patch rename to patches/server/0407-Implement-Player-Client-Options-API.patch diff --git a/patches/server/0407-Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server/0408-Fix-Chunk-Post-Processing-deadlock-risk.patch similarity index 100% rename from patches/server/0407-Fix-Chunk-Post-Processing-deadlock-risk.patch rename to patches/server/0408-Fix-Chunk-Post-Processing-deadlock-risk.patch diff --git a/patches/server/0408-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/patches/server/0409-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch similarity index 100% rename from patches/server/0408-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch rename to patches/server/0409-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch diff --git a/patches/server/0409-Broadcast-join-message-to-console.patch b/patches/server/0410-Broadcast-join-message-to-console.patch similarity index 100% rename from patches/server/0409-Broadcast-join-message-to-console.patch rename to patches/server/0410-Broadcast-join-message-to-console.patch diff --git a/patches/server/0410-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/patches/server/0411-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch similarity index 100% rename from patches/server/0410-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch rename to patches/server/0411-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch diff --git a/patches/server/0411-Load-Chunks-for-Login-Asynchronously.patch b/patches/server/0412-Load-Chunks-for-Login-Asynchronously.patch similarity index 99% rename from patches/server/0411-Load-Chunks-for-Login-Asynchronously.patch rename to patches/server/0412-Load-Chunks-for-Login-Asynchronously.patch index 22009dda6e..e5ea651270 100644 --- a/patches/server/0411-Load-Chunks-for-Login-Asynchronously.patch +++ b/patches/server/0412-Load-Chunks-for-Login-Asynchronously.patch @@ -263,10 +263,10 @@ index 3a13c151066c8784fdc844e1d6310f77ff32e7f1..c4242a1602bbb02541c330bc02016f15 Iterator iterator = list.iterator(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 85c0656ee8c91cab1e269daea631977c4284295f..ac5f0bf573cbb5aa19dd3326f412010286de4378 100644 +index 21bcb811eb002714db7a9be70133bda7a722ba65..326241a4669aa771db9d91ddd205576599110c2d 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1490,7 +1490,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -1491,7 +1491,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n this.yo = y; this.zo = d4; this.setPos(d3, y, d4); diff --git a/patches/server/0412-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/patches/server/0413-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch similarity index 89% rename from patches/server/0412-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch rename to patches/server/0413-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch index ed5d792bee..dd8d0f9858 100644 --- a/patches/server/0412-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch +++ b/patches/server/0413-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch @@ -7,10 +7,10 @@ The code following this has better support for null worlds to move them back to the world spawn. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index ac5f0bf573cbb5aa19dd3326f412010286de4378..1ab073aaacbf6af35f97a7d3b0d8ae078335f9a6 100644 +index 326241a4669aa771db9d91ddd205576599110c2d..62b16f0cedc90af6842c981cf0d8390675fc7201 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1979,9 +1979,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -1980,9 +1980,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n bworld = server.getWorld(worldName); } diff --git a/patches/server/0413-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server/0414-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from patches/server/0413-Add-PlayerAttackEntityCooldownResetEvent.patch rename to patches/server/0414-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/patches/server/0414-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/patches/server/0415-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch similarity index 100% rename from patches/server/0414-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch rename to patches/server/0415-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch diff --git a/patches/server/0415-Don-t-fire-BlockFade-on-worldgen-threads.patch b/patches/server/0416-Don-t-fire-BlockFade-on-worldgen-threads.patch similarity index 100% rename from patches/server/0415-Don-t-fire-BlockFade-on-worldgen-threads.patch rename to patches/server/0416-Don-t-fire-BlockFade-on-worldgen-threads.patch diff --git a/patches/server/0416-Add-phantom-creative-and-insomniac-controls.patch b/patches/server/0417-Add-phantom-creative-and-insomniac-controls.patch similarity index 100% rename from patches/server/0416-Add-phantom-creative-and-insomniac-controls.patch rename to patches/server/0417-Add-phantom-creative-and-insomniac-controls.patch diff --git a/patches/server/0417-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/patches/server/0418-Fix-numerous-item-duplication-issues-and-teleport-is.patch similarity index 94% rename from patches/server/0417-Fix-numerous-item-duplication-issues-and-teleport-is.patch rename to patches/server/0418-Fix-numerous-item-duplication-issues-and-teleport-is.patch index b1c5df36ef..98d85e37e6 100644 --- a/patches/server/0417-Fix-numerous-item-duplication-issues-and-teleport-is.patch +++ b/patches/server/0418-Fix-numerous-item-duplication-issues-and-teleport-is.patch @@ -16,10 +16,10 @@ So even if something NEW comes up, it would be impossible to drop the same item twice because the source was destroyed. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 1ab073aaacbf6af35f97a7d3b0d8ae078335f9a6..9897a0ac66dd788b0b22a88b20ca86a386e397e4 100644 +index 62b16f0cedc90af6842c981cf0d8390675fc7201..a80a1a54a66de45aaf4974be56aecbafeb477825 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2125,11 +2125,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -2126,11 +2126,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } else { // CraftBukkit start - Capture drops for death event if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) { @@ -34,7 +34,7 @@ index 1ab073aaacbf6af35f97a7d3b0d8ae078335f9a6..9897a0ac66dd788b0b22a88b20ca86a3 entityitem.setDefaultPickUpDelay(); // CraftBukkit start -@@ -2873,6 +2874,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -2874,6 +2875,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @Nullable public Entity teleportTo(ServerLevel worldserver, BlockPos location) { // CraftBukkit end @@ -47,7 +47,7 @@ index 1ab073aaacbf6af35f97a7d3b0d8ae078335f9a6..9897a0ac66dd788b0b22a88b20ca86a3 if (this.level instanceof ServerLevel && !this.isRemoved()) { this.level.getProfiler().push("changeDimension"); // CraftBukkit start -@@ -2893,6 +2900,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -2894,6 +2901,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n // CraftBukkit end this.level.getProfiler().popPush("reloading"); @@ -59,7 +59,7 @@ index 1ab073aaacbf6af35f97a7d3b0d8ae078335f9a6..9897a0ac66dd788b0b22a88b20ca86a3 Entity entity = this.getType().create((Level) worldserver); if (entity != null) { -@@ -2906,10 +2918,6 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -2907,10 +2919,6 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n // CraftBukkit start - Forward the CraftEntity to the new entity this.getBukkitEntity().setHandle(entity); entity.bukkitEntity = this.getBukkitEntity(); @@ -70,7 +70,7 @@ index 1ab073aaacbf6af35f97a7d3b0d8ae078335f9a6..9897a0ac66dd788b0b22a88b20ca86a3 // CraftBukkit end } -@@ -3034,7 +3042,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -3035,7 +3043,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } public boolean canChangeDimensions() { diff --git a/patches/server/0418-Implement-Brigadier-Mojang-API.patch b/patches/server/0419-Implement-Brigadier-Mojang-API.patch similarity index 100% rename from patches/server/0418-Implement-Brigadier-Mojang-API.patch rename to patches/server/0419-Implement-Brigadier-Mojang-API.patch diff --git a/patches/server/0419-Villager-Restocks-API.patch b/patches/server/0420-Villager-Restocks-API.patch similarity index 100% rename from patches/server/0419-Villager-Restocks-API.patch rename to patches/server/0420-Villager-Restocks-API.patch diff --git a/patches/server/0420-Validate-PickItem-Packet-and-kick-for-invalid.patch b/patches/server/0421-Validate-PickItem-Packet-and-kick-for-invalid.patch similarity index 100% rename from patches/server/0420-Validate-PickItem-Packet-and-kick-for-invalid.patch rename to patches/server/0421-Validate-PickItem-Packet-and-kick-for-invalid.patch diff --git a/patches/server/0421-Expose-game-version.patch b/patches/server/0422-Expose-game-version.patch similarity index 100% rename from patches/server/0421-Expose-game-version.patch rename to patches/server/0422-Expose-game-version.patch diff --git a/patches/server/0422-Optimize-Voxel-Shape-Merging.patch b/patches/server/0423-Optimize-Voxel-Shape-Merging.patch similarity index 100% rename from patches/server/0422-Optimize-Voxel-Shape-Merging.patch rename to patches/server/0423-Optimize-Voxel-Shape-Merging.patch diff --git a/patches/server/0423-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/patches/server/0424-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch similarity index 100% rename from patches/server/0423-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch rename to patches/server/0424-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch diff --git a/patches/server/0424-Implement-Mob-Goal-API.patch b/patches/server/0425-Implement-Mob-Goal-API.patch similarity index 100% rename from patches/server/0424-Implement-Mob-Goal-API.patch rename to patches/server/0425-Implement-Mob-Goal-API.patch diff --git a/patches/server/0425-Use-distance-map-to-optimise-entity-tracker.patch b/patches/server/0426-Use-distance-map-to-optimise-entity-tracker.patch similarity index 99% rename from patches/server/0425-Use-distance-map-to-optimise-entity-tracker.patch rename to patches/server/0426-Use-distance-map-to-optimise-entity-tracker.patch index 9c57b25122..0312a52281 100644 --- a/patches/server/0425-Use-distance-map-to-optimise-entity-tracker.patch +++ b/patches/server/0426-Use-distance-map-to-optimise-entity-tracker.patch @@ -312,7 +312,7 @@ index 28afe2f238ded241acf77c3272a44068646b9133..6b492b72b177e3c58580561585609b17 List list = this.entity.getPassengers(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 9897a0ac66dd788b0b22a88b20ca86a386e397e4..dec5690bd90830bace704b553dbcd1d2633ab668 100644 +index a80a1a54a66de45aaf4974be56aecbafeb477825..11ae525a5d2bd29bfe658d683c53a0ab2626616a 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -50,6 +50,7 @@ import net.minecraft.network.syncher.EntityDataSerializers; @@ -323,7 +323,7 @@ index 9897a0ac66dd788b0b22a88b20ca86a386e397e4..dec5690bd90830bace704b553dbcd1d2 import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -@@ -322,6 +323,21 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -323,6 +324,21 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } // CraftBukkit end diff --git a/patches/server/0426-Optimize-isOutsideRange-to-use-distance-maps.patch b/patches/server/0427-Optimize-isOutsideRange-to-use-distance-maps.patch similarity index 100% rename from patches/server/0426-Optimize-isOutsideRange-to-use-distance-maps.patch rename to patches/server/0427-Optimize-isOutsideRange-to-use-distance-maps.patch diff --git a/patches/server/0427-Add-villager-reputation-API.patch b/patches/server/0428-Add-villager-reputation-API.patch similarity index 100% rename from patches/server/0427-Add-villager-reputation-API.patch rename to patches/server/0428-Add-villager-reputation-API.patch diff --git a/patches/server/0428-Option-for-maximum-exp-value-when-merging-orbs.patch b/patches/server/0429-Option-for-maximum-exp-value-when-merging-orbs.patch similarity index 100% rename from patches/server/0428-Option-for-maximum-exp-value-when-merging-orbs.patch rename to patches/server/0429-Option-for-maximum-exp-value-when-merging-orbs.patch diff --git a/patches/server/0429-ExperienceOrbMergeEvent.patch b/patches/server/0430-ExperienceOrbMergeEvent.patch similarity index 100% rename from patches/server/0429-ExperienceOrbMergeEvent.patch rename to patches/server/0430-ExperienceOrbMergeEvent.patch diff --git a/patches/server/0430-Fix-PotionEffect-ignores-icon-flag.patch b/patches/server/0431-Fix-PotionEffect-ignores-icon-flag.patch similarity index 100% rename from patches/server/0430-Fix-PotionEffect-ignores-icon-flag.patch rename to patches/server/0431-Fix-PotionEffect-ignores-icon-flag.patch diff --git a/patches/server/0431-Optimize-brigadier-child-sorting-performance.patch b/patches/server/0432-Optimize-brigadier-child-sorting-performance.patch similarity index 100% rename from patches/server/0431-Optimize-brigadier-child-sorting-performance.patch rename to patches/server/0432-Optimize-brigadier-child-sorting-performance.patch diff --git a/patches/server/0432-Potential-bed-API.patch b/patches/server/0433-Potential-bed-API.patch similarity index 100% rename from patches/server/0432-Potential-bed-API.patch rename to patches/server/0433-Potential-bed-API.patch diff --git a/patches/server/0433-Wait-for-Async-Tasks-during-shutdown.patch b/patches/server/0434-Wait-for-Async-Tasks-during-shutdown.patch similarity index 100% rename from patches/server/0433-Wait-for-Async-Tasks-during-shutdown.patch rename to patches/server/0434-Wait-for-Async-Tasks-during-shutdown.patch diff --git a/patches/server/0434-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/patches/server/0435-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch similarity index 100% rename from patches/server/0434-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch rename to patches/server/0435-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch diff --git a/patches/server/0435-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server/0436-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch similarity index 98% rename from patches/server/0435-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch rename to patches/server/0436-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch index 5a8eb18dfb..2c13e4ac2d 100644 --- a/patches/server/0435-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch +++ b/patches/server/0436-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch @@ -56,10 +56,10 @@ index cdf214fca3b0055efa56702470d9d2f890a8aead..a12af10e28f2d023ba6f916b5e7a5353 this.level.getProfiler().push("explosion_blocks"); diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 03271675b4997588bd8f6774856aef25cdd4fa05..581e7975c4bfcc902e262003843fe54212bc5b61 100644 +index 6aeb3ff79f08ade7ddd0d328d1a01514a91f671a..b969e7f2087aed5b1f97ce8593a25ada737daec9 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -419,6 +419,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -420,6 +420,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { // CraftBukkit start - tree generation if (this.captureTreeGeneration) { diff --git a/patches/server/0436-Reduce-MutableInt-allocations-from-light-engine.patch b/patches/server/0437-Reduce-MutableInt-allocations-from-light-engine.patch similarity index 100% rename from patches/server/0436-Reduce-MutableInt-allocations-from-light-engine.patch rename to patches/server/0437-Reduce-MutableInt-allocations-from-light-engine.patch diff --git a/patches/server/0437-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/patches/server/0438-Reduce-allocation-of-Vec3D-by-entity-tracker.patch similarity index 100% rename from patches/server/0437-Reduce-allocation-of-Vec3D-by-entity-tracker.patch rename to patches/server/0438-Reduce-allocation-of-Vec3D-by-entity-tracker.patch diff --git a/patches/server/0438-Ensure-safe-gateway-teleport.patch b/patches/server/0439-Ensure-safe-gateway-teleport.patch similarity index 100% rename from patches/server/0438-Ensure-safe-gateway-teleport.patch rename to patches/server/0439-Ensure-safe-gateway-teleport.patch diff --git a/patches/server/0439-Add-option-for-console-having-all-permissions.patch b/patches/server/0440-Add-option-for-console-having-all-permissions.patch similarity index 100% rename from patches/server/0439-Add-option-for-console-having-all-permissions.patch rename to patches/server/0440-Add-option-for-console-having-all-permissions.patch diff --git a/patches/server/0440-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/patches/server/0441-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch similarity index 100% rename from patches/server/0440-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch rename to patches/server/0441-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch diff --git a/patches/server/0441-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/patches/server/0442-Optimize-sending-packets-to-nearby-locations-sounds-.patch similarity index 100% rename from patches/server/0441-Optimize-sending-packets-to-nearby-locations-sounds-.patch rename to patches/server/0442-Optimize-sending-packets-to-nearby-locations-sounds-.patch diff --git a/patches/server/0442-Fix-villager-trading-demand-MC-163962.patch b/patches/server/0443-Fix-villager-trading-demand-MC-163962.patch similarity index 100% rename from patches/server/0442-Fix-villager-trading-demand-MC-163962.patch rename to patches/server/0443-Fix-villager-trading-demand-MC-163962.patch diff --git a/patches/server/0443-Maps-shouldn-t-load-chunks.patch b/patches/server/0444-Maps-shouldn-t-load-chunks.patch similarity index 100% rename from patches/server/0443-Maps-shouldn-t-load-chunks.patch rename to patches/server/0444-Maps-shouldn-t-load-chunks.patch diff --git a/patches/server/0444-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/patches/server/0445-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch similarity index 100% rename from patches/server/0444-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch rename to patches/server/0445-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch diff --git a/patches/server/0445-Optimize-Bit-Operations-by-inlining.patch b/patches/server/0446-Optimize-Bit-Operations-by-inlining.patch similarity index 100% rename from patches/server/0445-Optimize-Bit-Operations-by-inlining.patch rename to patches/server/0446-Optimize-Bit-Operations-by-inlining.patch diff --git a/patches/server/0446-incremental-chunk-saving.patch b/patches/server/0447-incremental-chunk-saving.patch similarity index 99% rename from patches/server/0446-incremental-chunk-saving.patch rename to patches/server/0447-incremental-chunk-saving.patch index 8856801d1f..36c5663041 100644 --- a/patches/server/0446-incremental-chunk-saving.patch +++ b/patches/server/0447-incremental-chunk-saving.patch @@ -260,10 +260,10 @@ index 3faa808f41f057a9956c697ec1323330f5920b86..7ab28e9bd3f785838b7fa4ac5811c0e7 public void close() throws IOException { // CraftBukkit start diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index fd3159f7767faaa55ed49eba237e30a2dbd4fa92..9fb7345a8c3985aa3e0f4575d680b82379d2cc5a 100644 +index f10fad84e4f36f9158383b327170593f273cecd9..bdabcdb60dbfb803ead13c42c8dd5e100b37dc00 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1014,6 +1014,38 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1017,6 +1017,38 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos); } From 7fe98bd520978d3017828cbfde8eff8709278110 Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Mon, 14 Jun 2021 01:37:14 -0700 Subject: [PATCH 106/226] more patches (#5827) * more patches * even moar patches --- ...Holder-method-without-block-snapshot.patch | 0 .../0209-Expose-Arrow-getItemStack.patch | 0 ...implement-PlayerRecipeBookClickEvent.patch | 0 .../1.17}/0493-Optimize-Light-Engine.patch | 2 + .../1.17}/0501-Fix-enderdragon-exp-dupe.patch | 2 + ...mit-lightning-strike-effect-distance.patch | 1 + .../0503-Expose-Arrow-getItemStack.patch | 36 ---------- ...sure-Entity-AABB-s-are-never-invalid.patch | 48 ------------- ...WorldBorder-collision-checks-and-air.patch | 71 ------------------- ...up-duplicated-GameProfile-Properties.patch | 68 ------------------ ...nk-Unloads-based-on-Player-Movement.patch} | 50 ++++++------- ...Optimize-Bit-Operations-by-inlining.patch} | 0 ...ch => 0448-incremental-chunk-saving.patch} | 2 +- ...Plugin-Tickets-to-API-Chunk-Methods.patch} | 68 ++++++++---------- ...sing-chunks-due-to-integer-overflow.patch} | 16 ++--- ...r-runTaskTimerAsynchronously-Plugin.patch} | 6 +- ...ton-physics-inconsistency-MC-188840.patch} | 30 ++++---- .../0453-Fix-sand-duping.patch} | 12 ++-- ...desync-in-playerconnection-causing-.patch} | 6 +- ...older-method-without-block-snapshot.patch} | 22 ++---- .../0456-Expose-Arrow-getItemStack.patch | 24 +++++++ ...mplement-PlayerRecipeBookClickEvent.patch} | 14 ++-- ...-Hide-sync-chunk-writes-behind-flag.patch} | 2 +- ...9-Add-permission-for-command-blocks.patch} | 32 ++++----- ...sure-Entity-AABB-s-are-never-invalid.patch | 32 +++++++++ ...WorldBorder-collision-checks-and-air.patch | 50 +++++++++++++ ...d-Difficulty-Remembering-Difficulty.patch} | 59 +++++++-------- .../0463-Paper-dumpitem-command.patch} | 52 ++++++-------- ...64-Don-t-allow-null-UUID-s-for-chat.patch} | 20 ++---- ...Legacy-Component-serialization-size.patch} | 14 ++-- ...466-Support-old-UUID-format-for-NBT.patch} | 46 ++++++++---- ...up-duplicated-GameProfile-Properties.patch | 47 ++++++++++++ 32 files changed, 369 insertions(+), 463 deletions(-) rename patches/{api-unmapped => api}/0208-Inventory-getHolder-method-without-block-snapshot.patch (100%) rename patches/{api-unmapped => api}/0209-Expose-Arrow-getItemStack.patch (100%) rename patches/{api-unmapped => api}/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch (100%) rename patches/{server-remapped => removed/1.17}/0493-Optimize-Light-Engine.patch (99%) rename patches/{server-remapped => removed/1.17}/0501-Fix-enderdragon-exp-dupe.patch (96%) rename patches/{server-remapped => removed/1.17}/0506-Limit-lightning-strike-effect-distance.patch (98%) delete mode 100644 patches/server-remapped/0503-Expose-Arrow-getItemStack.patch delete mode 100644 patches/server-remapped/0508-Ensure-Entity-AABB-s-are-never-invalid.patch delete mode 100644 patches/server-remapped/0509-Optimize-WorldBorder-collision-checks-and-air.patch delete mode 100644 patches/server-remapped/0515-Clean-up-duplicated-GameProfile-Properties.patch rename patches/{server-remapped/0494-Delay-Chunk-Unloads-based-on-Player-Movement.patch => server/0446-Delay-Chunk-Unloads-based-on-Player-Movement.patch} (73%) rename patches/server/{0446-Optimize-Bit-Operations-by-inlining.patch => 0447-Optimize-Bit-Operations-by-inlining.patch} (100%) rename patches/server/{0447-incremental-chunk-saving.patch => 0448-incremental-chunk-saving.patch} (99%) rename patches/{server-remapped/0495-Add-Plugin-Tickets-to-API-Chunk-Methods.patch => server/0449-Add-Plugin-Tickets-to-API-Chunk-Methods.patch} (62%) rename patches/{server-remapped/0496-Fix-missing-chunks-due-to-integer-overflow.patch => server/0450-Fix-missing-chunks-due-to-integer-overflow.patch} (75%) rename patches/{server-remapped/0497-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch => server/0451-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch} (76%) rename patches/{server-remapped/0498-Fix-piston-physics-inconsistency-MC-188840.patch => server/0452-Fix-piston-physics-inconsistency-MC-188840.patch} (72%) rename patches/{server-remapped/0499-Fix-sand-duping.patch => server/0453-Fix-sand-duping.patch} (81%) rename patches/{server-remapped/0500-Prevent-position-desync-in-playerconnection-causing-.patch => server/0454-Prevent-position-desync-in-playerconnection-causing-.patch} (86%) rename patches/{server-remapped/0502-Inventory-getHolder-method-without-block-snapshot.patch => server/0455-Inventory-getHolder-method-without-block-snapshot.patch} (56%) create mode 100644 patches/server/0456-Expose-Arrow-getItemStack.patch rename patches/{server-remapped/0504-Add-and-implement-PlayerRecipeBookClickEvent.patch => server/0457-Add-and-implement-PlayerRecipeBookClickEvent.patch} (76%) rename patches/{server-remapped/0505-Hide-sync-chunk-writes-behind-flag.patch => server/0458-Hide-sync-chunk-writes-behind-flag.patch} (93%) rename patches/{server-remapped/0507-Add-permission-for-command-blocks.patch => server/0459-Add-permission-for-command-blocks.patch} (68%) create mode 100644 patches/server/0460-Ensure-Entity-AABB-s-are-never-invalid.patch create mode 100644 patches/server/0461-Optimize-WorldBorder-collision-checks-and-air.patch rename patches/{server-remapped/0510-Fix-Per-World-Difficulty-Remembering-Difficulty.patch => server/0462-Fix-Per-World-Difficulty-Remembering-Difficulty.patch} (57%) rename patches/{server-remapped/0511-Paper-dumpitem-command.patch => server/0463-Paper-dumpitem-command.patch} (55%) rename patches/{server-remapped/0512-Don-t-allow-null-UUID-s-for-chat.patch => server/0464-Don-t-allow-null-UUID-s-for-chat.patch} (53%) rename patches/{server-remapped/0513-Improve-Legacy-Component-serialization-size.patch => server/0465-Improve-Legacy-Component-serialization-size.patch} (81%) rename patches/{server-remapped/0514-Support-old-UUID-format-for-NBT.patch => server/0466-Support-old-UUID-format-for-NBT.patch} (51%) create mode 100644 patches/server/0467-Clean-up-duplicated-GameProfile-Properties.patch diff --git a/patches/api-unmapped/0208-Inventory-getHolder-method-without-block-snapshot.patch b/patches/api/0208-Inventory-getHolder-method-without-block-snapshot.patch similarity index 100% rename from patches/api-unmapped/0208-Inventory-getHolder-method-without-block-snapshot.patch rename to patches/api/0208-Inventory-getHolder-method-without-block-snapshot.patch diff --git a/patches/api-unmapped/0209-Expose-Arrow-getItemStack.patch b/patches/api/0209-Expose-Arrow-getItemStack.patch similarity index 100% rename from patches/api-unmapped/0209-Expose-Arrow-getItemStack.patch rename to patches/api/0209-Expose-Arrow-getItemStack.patch diff --git a/patches/api-unmapped/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/api/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch similarity index 100% rename from patches/api-unmapped/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch rename to patches/api/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch diff --git a/patches/server-remapped/0493-Optimize-Light-Engine.patch b/patches/removed/1.17/0493-Optimize-Light-Engine.patch similarity index 99% rename from patches/server-remapped/0493-Optimize-Light-Engine.patch rename to patches/removed/1.17/0493-Optimize-Light-Engine.patch index 53f26fe554..6b16fce1cd 100644 --- a/patches/server-remapped/0493-Optimize-Light-Engine.patch +++ b/patches/removed/1.17/0493-Optimize-Light-Engine.patch @@ -24,6 +24,8 @@ Massive update to light to improve performance and chunk loading/generation. 7) Buffer non urgent tasks even if queueUpdate is called multiple times to improve efficiency. 8) Fix NPE risk that crashes server in getting nibble data +1.17: Depends on chunk urgency patch as well + diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java index 8260636da673ef095728c208db2d6237bab2db19..9e3629884709126574a52ad44fe7523f01dbcce9 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java diff --git a/patches/server-remapped/0501-Fix-enderdragon-exp-dupe.patch b/patches/removed/1.17/0501-Fix-enderdragon-exp-dupe.patch similarity index 96% rename from patches/server-remapped/0501-Fix-enderdragon-exp-dupe.patch rename to patches/removed/1.17/0501-Fix-enderdragon-exp-dupe.patch index 38690afc49..ccc32f2cc8 100644 --- a/patches/server-remapped/0501-Fix-enderdragon-exp-dupe.patch +++ b/patches/removed/1.17/0501-Fix-enderdragon-exp-dupe.patch @@ -6,6 +6,8 @@ Subject: [PATCH] Fix enderdragon exp dupe Properly track death stage when unloading/loading in the dragon +1.17: Mojang fixed in 1.17(maybe before, idk) + diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java index ec9436005a3a6fdfb4783d1092bb361224eb6414..b224a630f8adb1fa357c838e6b32c784aed0b15b 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java diff --git a/patches/server-remapped/0506-Limit-lightning-strike-effect-distance.patch b/patches/removed/1.17/0506-Limit-lightning-strike-effect-distance.patch similarity index 98% rename from patches/server-remapped/0506-Limit-lightning-strike-effect-distance.patch rename to patches/removed/1.17/0506-Limit-lightning-strike-effect-distance.patch index 1f74c2ced9..f29d1e4440 100644 --- a/patches/server-remapped/0506-Limit-lightning-strike-effect-distance.patch +++ b/patches/removed/1.17/0506-Limit-lightning-strike-effect-distance.patch @@ -3,6 +3,7 @@ From: Trigary Date: Fri, 14 Sep 2018 17:42:08 +0200 Subject: [PATCH] Limit lightning strike effect distance +Doesnt seem to apply anymore as spigot isn't using relative distance for lightning diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java index 1655bca0502e7b871de4addaa163536d86547a02..978062774c1db286bfb9b0ffdef19d880b1f249b 100644 diff --git a/patches/server-remapped/0503-Expose-Arrow-getItemStack.patch b/patches/server-remapped/0503-Expose-Arrow-getItemStack.patch deleted file mode 100644 index cafd641bc1..0000000000 --- a/patches/server-remapped/0503-Expose-Arrow-getItemStack.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nesaak <52047222+Nesaak@users.noreply.github.com> -Date: Sat, 23 May 2020 10:31:11 -0400 -Subject: [PATCH] Expose Arrow getItemStack - - -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 3ce431c1fdf1f5bd62b49f26cca188e939e98efa..6225f390b51733217a809910182f58acea1055e2 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -556,6 +556,7 @@ public abstract class AbstractArrow extends Projectile { - } - } - -+ public final ItemStack getOriginalItemStack() { return getPickupItem(); } // Paper - OBFHELPER - exists purely due to overrides all as protected and dont want to change them all - protected abstract ItemStack getPickupItem(); - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -index 5b898118a46007a85254931c7b5bd18d7cda99be..91d32aff07e81608a2f8ecb1301ef3c08533494b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -@@ -102,6 +102,13 @@ public class CraftArrow extends AbstractProjectile implements AbstractArrow { - getHandle().pickup = net.minecraft.world.entity.projectile.AbstractArrow.Pickup.byOrdinal(status.ordinal()); - } - -+ // Paper start -+ @Override -+ public org.bukkit.craftbukkit.inventory.CraftItemStack getItemStack() { -+ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(getHandle().getOriginalItemStack()); -+ } -+ //Paper end -+ - @Override - public void setTicksLived(int value) { - super.setTicksLived(value); diff --git a/patches/server-remapped/0508-Ensure-Entity-AABB-s-are-never-invalid.patch b/patches/server-remapped/0508-Ensure-Entity-AABB-s-are-never-invalid.patch deleted file mode 100644 index f77fef5ea0..0000000000 --- a/patches/server-remapped/0508-Ensure-Entity-AABB-s-are-never-invalid.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 May 2020 22:12:46 -0400 -Subject: [PATCH] Ensure Entity AABB's are never invalid - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d9bb00752ac81b2171d3ad25fd84904467a18e3b..728379292728cf58f5512feae3cdc74392980f68 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -66,6 +66,7 @@ import net.minecraft.world.Nameable; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.animal.AbstractFish; - import net.minecraft.world.entity.animal.Animal; -+import net.minecraft.world.entity.decoration.HangingEntity; - import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.vehicle.AbstractMinecart; -@@ -478,7 +479,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - - public void setPos(double x, double y, double z) { - this.setPosRaw(x, y, z); -- this.setBoundingBox(this.dimensions.makeBoundingBox(x, y, z)); -+ //this.a(this.size.a(d0, d1, d2)); // Paper - move into setPositionRaw - if (valid) ((ServerLevel) level).updateChunkPos(this); // CraftBukkit - } - -@@ -2998,6 +2999,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return new AABB(vec3d, vec3d1); - } - -+ public final void setBoundingBox(AABB axisalignedbb) { setBoundingBox(axisalignedbb); } // Paper - OBFHELPER - public void setBoundingBox(AABB boundingBox) { - // CraftBukkit start - block invalid bounding boxes - double minX = boundingBox.minX, -@@ -3436,6 +3438,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public void setPosRaw(double x, double y, double z) { -+ // Paper start - never allow AABB to become desynced from position -+ // hanging has its own special logic -+ if (!(this instanceof HangingEntity) && (this.position.x != x || this.position.y != y || this.position.z != z)) { -+ this.setBoundingBox(this.dimensions.makeBoundingBox(x, y, z)); -+ } -+ // Paper end - if (this.position.x != x || this.position.y != y || this.position.z != z) { - this.position = new Vec3(x, y, z); - int i = Mth.floor(x); diff --git a/patches/server-remapped/0509-Optimize-WorldBorder-collision-checks-and-air.patch b/patches/server-remapped/0509-Optimize-WorldBorder-collision-checks-and-air.patch deleted file mode 100644 index bc82f5847c..0000000000 --- a/patches/server-remapped/0509-Optimize-WorldBorder-collision-checks-and-air.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 10 May 2020 22:49:05 -0400 -Subject: [PATCH] Optimize WorldBorder collision checks and air - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 728379292728cf58f5512feae3cdc74392980f68..e9a658b11e2b6683831dc3f5bd20be9a7840ed69 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -102,7 +102,6 @@ import net.minecraft.world.phys.AABB; - import net.minecraft.world.phys.HitResult; - import net.minecraft.world.phys.Vec2; - import net.minecraft.world.phys.Vec3; --import net.minecraft.world.phys.shapes.BooleanOp; - import net.minecraft.world.phys.shapes.CollisionContext; - import net.minecraft.world.phys.shapes.Shapes; - import net.minecraft.world.phys.shapes.VoxelShape; -@@ -908,7 +907,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - AABB axisalignedbb = this.getBoundingBox(); - CollisionContext voxelshapecollision = CollisionContext.of(this); - VoxelShape voxelshape = this.level.getWorldBorder().getCollisionShape(); -- Stream stream = Shapes.joinIsNotEmpty(voxelshape, Shapes.create(axisalignedbb.deflate(1.0E-7D)), BooleanOp.AND) ? Stream.empty() : Stream.of(voxelshape); -+ Stream stream = !this.level.getWorldBorder().isInBounds(axisalignedbb) ? Stream.empty() : Stream.of(voxelshape); // Paper - Stream stream1 = this.level.getEntityCollisions(this, axisalignedbb.expandTowards(movement), (entity) -> { - return true; - }); -diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -index feca9ff34936686c0665ae0dbc926869087df3a7..60f8585a736af5b654b8aaed89a39a8bf5e91301 100644 ---- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -+++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -@@ -143,10 +143,10 @@ public class CollisionSpliterator extends AbstractSpliterator { - AABB axisalignedbb = this.source.getBoundingBox(); - - if (!isBoxFullyWithinWorldBorder(worldborder, axisalignedbb)) { -- VoxelShape voxelshape = worldborder.getCollisionShape(); -- -- if (!isOutsideBorder(voxelshape, axisalignedbb) && isCloseToBorder(voxelshape, axisalignedbb)) { -- consumer.accept(voxelshape); -+ // Paper start -+ if (worldborder.isInBounds(axisalignedbb.deflate(1.0E-7D)) && !worldborder.isInBounds(axisalignedbb.grow(1.0E-7D))) { -+ consumer.accept(worldborder.asVoxelShape()); -+ // Paper end - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 7a728ca96ee2eaf776c391ba8351196a526e18ec..aaa6251838483de5c46913534413151b5cb1d3fe 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -52,6 +52,7 @@ public class WorldBorder { - return (double) pos.getMaxBlockX() > this.getMinX() && (double) pos.getMinBlockX() < this.getMaxX() && (double) pos.getMaxBlockZ() > this.getMinZ() && (double) pos.getMinBlockZ() < this.getMaxZ(); - } - -+ public final boolean isInBounds(AABB aabb) { return this.isWithinBounds(aabb); } // Paper - OBFHELPER - public boolean isWithinBounds(AABB box) { - return box.maxX > this.getMinX() && box.minX < this.getMaxX() && box.maxZ > this.getMinZ() && box.minZ < this.getMaxZ(); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -index 1603eb3f7d90a4b3a028b20776566db77d09c123..f28d2126bc29fad3971a32cf85a7a7c4803b36ab 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -@@ -252,7 +252,7 @@ public final class Shapes { - BlockState iblockdata = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper - if (iblockdata == null) return 0.0D; // Paper - -- if ((k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { -+ if (!iblockdata.isAir() && (k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { // Paper - initial = iblockdata.getCollisionShape((BlockGetter) world, blockposition_mutableblockposition, context).collide(enumdirection_enumaxis2, box.move((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), initial); - if (Math.abs(initial) < 1.0E-7D) { - return 0.0D; diff --git a/patches/server-remapped/0515-Clean-up-duplicated-GameProfile-Properties.patch b/patches/server-remapped/0515-Clean-up-duplicated-GameProfile-Properties.patch deleted file mode 100644 index 40c9060216..0000000000 --- a/patches/server-remapped/0515-Clean-up-duplicated-GameProfile-Properties.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 1 Jul 2020 03:12:06 -0400 -Subject: [PATCH] Clean up duplicated GameProfile Properties - -We had a bug where we accidently cloned properties resulting in skulls -growing to large sizes and preventing login. - -This now automatically cleans up the extra properties. - -diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java -index f57c5e441045a81072a2edfed0f199d90e6d7fde..3abfd21ea84c54aec6256008b3b9e6bbc7ae694c 100644 ---- a/src/main/java/net/minecraft/nbt/NbtUtils.java -+++ b/src/main/java/net/minecraft/nbt/NbtUtils.java -@@ -59,8 +59,8 @@ public final class NbtUtils { - while (iterator.hasNext()) { - String s1 = (String) iterator.next(); - ListTag nbttaglist = nbttagcompound1.getList(s1, 10); -- -- for (int i = 0; i < nbttaglist.size(); ++i) { -+ if (nbttaglist.size() == 0) continue; // Paper - remove duplicate properties -+ for (int i = nbttaglist.size() - 1; i < nbttaglist.size(); ++i) { // Paper - remove duplicate properties - CompoundTag nbttagcompound2 = nbttaglist.getCompound(i); - String s2 = nbttagcompound2.getString("Value"); - -@@ -246,7 +246,7 @@ public final class NbtUtils { - Optional optional = property.getValue(propertiesTag.getString(key)); - - if (optional.isPresent()) { -- return (StateHolder) state.setValue(property, (Comparable) optional.get()); -+ return state.setValue(property, optional.get()); // Paper - decompile error - } else { - NbtUtils.LOGGER.warn("Unable to read property: {} with value: {} for blockstate: {}", key, propertiesTag.getString(key), mainTag.toString()); - return state; -@@ -276,8 +276,8 @@ public final class NbtUtils { - return nbttagcompound; - } - -- private static > String getName(net.minecraft.world.level.block.state.properties.Property property, Comparable value) { -- return property.value(value); -+ private static > String getName(net.minecraft.world.level.block.state.properties.Property property, Comparable value) {// Paper - decompile error -+ return property.getName((T) value);// Paper - decompile error - } - - public static CompoundTag update(DataFixer fixer, DataFixTypes fixTypes, CompoundTag tag, int oldVersion) { -diff --git a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java -index 1cb67832a849db96f1cce95c32b41574e990e5b7..d97be7a1dfa7ad413afb8ff7668189fd37baf264 100644 ---- a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java -+++ b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java -@@ -59,6 +59,18 @@ public class PlayerHeadItem extends StandingAndWallBlockItem { - return true; - } else { - // CraftBukkit start -+ // Paper start - clean up old duplicated properties -+ CompoundTag properties = tag.getCompound("SkullOwner").getCompound("Properties"); -+ for (String key : properties.getAllKeys()) { -+ net.minecraft.nbt.ListTag values = properties.getList(key, 10); -+ if (values.size() > 1) { -+ net.minecraft.nbt.Tag texture = values.get(values.size() - 1); -+ values = new net.minecraft.nbt.ListTag(); -+ values.add(texture); -+ properties.put(key, values); -+ } -+ } -+ // Paper end - net.minecraft.nbt.ListTag textures = tag.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts - for (int i = 0; i < textures.size(); i++) { - if (textures.get(i) instanceof CompoundTag && !((CompoundTag) textures.get(i)).contains("Signature", 8) && ((CompoundTag) textures.get(i)).getString("Value").trim().isEmpty()) { diff --git a/patches/server-remapped/0494-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/patches/server/0446-Delay-Chunk-Unloads-based-on-Player-Movement.patch similarity index 73% rename from patches/server-remapped/0494-Delay-Chunk-Unloads-based-on-Player-Movement.patch rename to patches/server/0446-Delay-Chunk-Unloads-based-on-Player-Movement.patch index a8c890b13a..a7a809be4c 100644 --- a/patches/server-remapped/0494-Delay-Chunk-Unloads-based-on-Player-Movement.patch +++ b/patches/server/0446-Delay-Chunk-Unloads-based-on-Player-Movement.patch @@ -17,14 +17,13 @@ This allows servers with smaller worlds who do less long distance exploring to s wasting cpu cycles on saving/unloading/reloading chunks repeatedly. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6463d3e4837d032a35654a035f42b8a805e0e286..1655bca0502e7b871de4addaa163536d86547a02 100644 +index 3bc6329d3ea48966cb99e792f9b35e2d2d71a34b..1f4d0d3493e748f52eb3b679c0a8a1306c0cc8b4 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -637,4 +637,13 @@ public class PaperWorldConfig { - private void viewDistance() { +@@ -495,6 +495,15 @@ public class PaperWorldConfig { this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); } -+ + + public long delayChunkUnloadsBy; + private void delayChunkUnloadsBy() { + delayChunkUnloadsBy = PaperConfig.getSeconds(getString("delay-chunk-unloads-by", "10s")); @@ -33,12 +32,15 @@ index 6463d3e4837d032a35654a035f42b8a805e0e286..1655bca0502e7b871de4addaa163536d + delayChunkUnloadsBy *= 20; + } + } - } ++ + public boolean altItemDespawnRateEnabled; + public Map altItemDespawnRateMap; + private void altItemDespawnRate() { diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index e41f388e8350010a471410436adf15a906f07e97..e0241b9d60cd2b72f8fb774f1ab4753dfd615184 100644 +index 577b391dcba1db712c1e2c83296e1c87b3e34ab2..d94241bcca4f2fd5e464a860bd356af504dc68b7 100644 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java +++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -185,6 +185,27 @@ public abstract class DistanceManager { +@@ -181,6 +181,27 @@ public abstract class DistanceManager { boolean removed = false; // CraftBukkit if (arraysetsorted.remove(ticket)) { removed = true; // CraftBukkit @@ -56,7 +58,7 @@ index e41f388e8350010a471410436adf15a906f07e97..e0241b9d60cd2b72f8fb774f1ab4753d + if (!hasPlayer && playerChunk != null && playerChunk.isFullChunkReady()) { + Ticket delayUnload = new Ticket(TicketType.DELAY_UNLOAD, 33, i); + delayUnload.delayUnloadBy = delayChunkUnloadsBy; -+ delayUnload.setCurrentTick(this.ticketTickCounter); ++ delayUnload.setCreatedTick(this.ticketTickCounter); + arraysetsorted.remove(delayUnload); + // refresh ticket + arraysetsorted.add(delayUnload); @@ -67,13 +69,13 @@ index e41f388e8350010a471410436adf15a906f07e97..e0241b9d60cd2b72f8fb774f1ab4753d if (arraysetsorted.isEmpty()) { diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index c0bfe136ccb9ad4fc0f8ccdd703254205213ec8e..f7898bd7806684d2c068898cecbf835d834df461 100644 +index 8b0c6e1a649400908dbb674dfb4cdd1aa0ce1d38..a7aa7a9038d4812a9d1e4e72c4dbbbe10df15820 100644 --- a/src/main/java/net/minecraft/server/level/Ticket.java +++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -9,11 +9,13 @@ public final class Ticket implements Comparable> { +@@ -7,11 +7,13 @@ public final class Ticket implements Comparable> { + private final int ticketLevel; public final T key; public final T getObjectReason() { return this.key; } // Paper - OBFHELPER private long createdTick; public final long getCreationTick() { return this.createdTick; } // Paper - OBFHELPER - public int priority = 0; // Paper + public long delayUnloadBy; // Paper protected Ticket(TicketType type, int level, T argument) { @@ -83,25 +85,25 @@ index c0bfe136ccb9ad4fc0f8ccdd703254205213ec8e..f7898bd7806684d2c068898cecbf835d + this.delayUnloadBy = type.timeout; // Paper } - public int compareTo(Ticket ticket) { -@@ -63,7 +65,7 @@ public final class Ticket implements Comparable> { + @Override +@@ -60,7 +62,7 @@ public final class Ticket implements Comparable> { } protected boolean timedOut(long currentTick) { -- long j = this.type.timeout(); -+ long j = delayUnloadBy; // Paper - - return j != 0L && currentTick - this.createdTick > j; +- long l = this.type.timeout(); ++ long l = delayUnloadBy; // Paper + return l != 0L && currentTick - this.createdTick > l; } + } diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 2444f6f676db543509b14e8c882491dc3f41b264..531ebf1bafec2b295af9f6dfec8f4b6466688287 100644 +index 78fbb4c3e52e900956ae0811aaf934c81ee5ea48..8770fe0db46b01e8b608637df4f1a669a3f4cdde 100644 --- a/src/main/java/net/minecraft/server/level/TicketType.java +++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -30,6 +30,7 @@ public class TicketType { - public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper - public static final TicketType PRIORITY = create("priority", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper - public static final TicketType URGENT = create("urgent", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper +@@ -28,6 +28,7 @@ public class TicketType { + public static final TicketType UNKNOWN = TicketType.create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); + public static final TicketType PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit + public static final TicketType PLUGIN_TICKET = TicketType.create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + public static final TicketType DELAY_UNLOAD = create("delay_unload", Long::compareTo, 300); // Paper - public static TicketType create(String name, Comparator comparator) { - return new TicketType<>(name, comparator, 0L); + public static TicketType create(String name, Comparator argumentComparator) { + return new TicketType<>(name, argumentComparator, 0L); diff --git a/patches/server/0446-Optimize-Bit-Operations-by-inlining.patch b/patches/server/0447-Optimize-Bit-Operations-by-inlining.patch similarity index 100% rename from patches/server/0446-Optimize-Bit-Operations-by-inlining.patch rename to patches/server/0447-Optimize-Bit-Operations-by-inlining.patch diff --git a/patches/server/0447-incremental-chunk-saving.patch b/patches/server/0448-incremental-chunk-saving.patch similarity index 99% rename from patches/server/0447-incremental-chunk-saving.patch rename to patches/server/0448-incremental-chunk-saving.patch index 36c5663041..ece4224cd0 100644 --- a/patches/server/0447-incremental-chunk-saving.patch +++ b/patches/server/0448-incremental-chunk-saving.patch @@ -5,7 +5,7 @@ Subject: [PATCH] incremental chunk saving diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3bc6329d3ea48966cb99e792f9b35e2d2d71a34b..ec51a9e19670888584e5324a57a47aa9c676d423 100644 +index 1f4d0d3493e748f52eb3b679c0a8a1306c0cc8b4..91917b11163c0740d5e5effc5e93d494e2b2d73e 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -47,6 +47,21 @@ public class PaperWorldConfig { diff --git a/patches/server-remapped/0495-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/patches/server/0449-Add-Plugin-Tickets-to-API-Chunk-Methods.patch similarity index 62% rename from patches/server-remapped/0495-Add-Plugin-Tickets-to-API-Chunk-Methods.patch rename to patches/server/0449-Add-Plugin-Tickets-to-API-Chunk-Methods.patch index 2d4cc183be..ab4ec662b0 100644 --- a/patches/server-remapped/0495-Add-Plugin-Tickets-to-API-Chunk-Methods.patch +++ b/patches/server/0449-Add-Plugin-Tickets-to-API-Chunk-Methods.patch @@ -22,40 +22,32 @@ wants it to collect even faster, they can restore that setting back to 1 instead Not adding it to .getType() though to keep behavior consistent with vanilla for performance reasons. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 92f1a6d32a96fee682342e86c3ffd3c65292150b..2ec41cb87cec97780f1fa8abfbb756fca4dba1bf 100644 +index 94670ec4de01341822f6affe0fa1c9774dd6131b..6bc5ba51c90723c7138b1b5d2381cb215f1e5271 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -342,7 +342,7 @@ public final class CraftServer implements Server { - ambientSpawn = configuration.getInt("spawn-limits.ambient"); - console.autosavePeriod = configuration.getInt("ticks-per.autosave"); - warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); -- TicketType.PLUGIN.timeout = configuration.getInt("chunk-gc.period-in-ticks"); -+ TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - loadIcon(); +@@ -346,7 +346,7 @@ public final class CraftServer implements Server { + this.ambientSpawn = this.configuration.getInt("spawn-limits.ambient"); + console.autosavePeriod = this.configuration.getInt("ticks-per.autosave"); + this.warningState = WarningState.value(this.configuration.getString("settings.deprecated-verbose")); +- TicketType.PLUGIN.timeout = this.configuration.getInt("chunk-gc.period-in-ticks"); ++ TicketType.PLUGIN.timeout = Math.min(20, this.configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + this.minimumAPI = this.configuration.getString("settings.minimum-api"); + this.loadIcon(); } -@@ -832,7 +832,7 @@ public final class CraftServer implements Server { - waterAmbientSpawn = configuration.getInt("spawn-limits.water-ambient"); - ambientSpawn = configuration.getInt("spawn-limits.ambient"); - warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); -- TicketType.PLUGIN.timeout = configuration.getInt("chunk-gc.period-in-ticks"); +@@ -834,7 +834,7 @@ public final class CraftServer implements Server { + this.waterAmbientSpawn = this.configuration.getInt("spawn-limits.water-ambient"); + this.ambientSpawn = this.configuration.getInt("spawn-limits.ambient"); + this.warningState = WarningState.value(this.configuration.getString("settings.deprecated-verbose")); +- TicketType.PLUGIN.timeout = this.configuration.getInt("chunk-gc.period-in-ticks"); + TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - printSaveWarning = false; - console.autosavePeriod = configuration.getInt("ticks-per.autosave"); + this.minimumAPI = this.configuration.getString("settings.minimum-api"); + this.printSaveWarning = false; + console.autosavePeriod = this.configuration.getInt("ticks-per.autosave"); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 7261e22a71d219efe0949a08c5d3f10747759469..4436b3d23dc8f33925da1ec539ea16307e0785b9 100644 +index 72c9ad9f75c20d6c1a6d54e2913e2f9918c11ffd..f72471ac82907a0d5112598b3289689495285944 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.ClientboundCustomSoundPacket; - import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; - import net.minecraft.network.protocol.game.ClientboundSetTimePacket; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ChunkHolder; - import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.DistanceManager; -@@ -389,8 +390,21 @@ public class CraftWorld implements World { +@@ -405,8 +405,21 @@ public class CraftWorld implements World { @Override public Chunk getChunkAt(int x, int z) { @@ -72,22 +64,22 @@ index 7261e22a71d219efe0949a08c5d3f10747759469..4436b3d23dc8f33925da1ec539ea1630 + + // Paper start + private void addTicket(int x, int z) { -+ MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE)); // Paper ++ net.minecraft.server.MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE)); // Paper } + // Paper end @Override public Chunk getChunkAt(Block block) { -@@ -465,7 +479,7 @@ public class CraftWorld implements World { +@@ -481,7 +494,7 @@ public class CraftWorld implements World { public boolean unloadChunkRequest(int x, int z) { org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot - if (isChunkLoaded(x, z)) { -- world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); -+ world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE); // Paper + if (this.isChunkLoaded(x, z)) { +- this.world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); ++ this.world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE); // Paper } return true; -@@ -542,9 +556,12 @@ public class CraftWorld implements World { +@@ -558,9 +571,12 @@ public class CraftWorld implements World { org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot // Paper start - Optimize this method ChunkPos chunkPos = new ChunkPos(x, z); @@ -101,7 +93,7 @@ index 7261e22a71d219efe0949a08c5d3f10747759469..4436b3d23dc8f33925da1ec539ea1630 if (immediate == null) { immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); } -@@ -552,7 +569,7 @@ public class CraftWorld implements World { +@@ -568,7 +584,7 @@ public class CraftWorld implements World { if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) { return false; // not full status } @@ -110,7 +102,7 @@ index 7261e22a71d219efe0949a08c5d3f10747759469..4436b3d23dc8f33925da1ec539ea1630 world.getChunk(x, z); // make sure we're at ticket level 32 or lower return true; } -@@ -579,7 +596,7 @@ public class CraftWorld implements World { +@@ -594,7 +610,7 @@ public class CraftWorld implements World { // we do this so we do not re-read the chunk data on disk } @@ -119,11 +111,11 @@ index 7261e22a71d219efe0949a08c5d3f10747759469..4436b3d23dc8f33925da1ec539ea1630 world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); return true; // Paper end -@@ -2529,6 +2546,7 @@ public class CraftWorld implements World { - } +@@ -2544,6 +2560,7 @@ public class CraftWorld implements World { + return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); + if (chunk != null) addTicket(x, z); // Paper - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + return java.util.concurrent.CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); }, net.minecraft.server.MinecraftServer.getServer()); } diff --git a/patches/server-remapped/0496-Fix-missing-chunks-due-to-integer-overflow.patch b/patches/server/0450-Fix-missing-chunks-due-to-integer-overflow.patch similarity index 75% rename from patches/server-remapped/0496-Fix-missing-chunks-due-to-integer-overflow.patch rename to patches/server/0450-Fix-missing-chunks-due-to-integer-overflow.patch index f86c4c1c6b..0cfdc16188 100644 --- a/patches/server-remapped/0496-Fix-missing-chunks-due-to-integer-overflow.patch +++ b/patches/server/0450-Fix-missing-chunks-due-to-integer-overflow.patch @@ -13,17 +13,15 @@ The fix for the issue is quite simple, casting chunk coordinates to longs allows the distance calculation to avoid overflow and work as intended. diff --git a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java -index af006c2e45e0a14367a0bc850c319024c6b82024..063369d3a64b4afc9cc6e1d20360900595e1a05f 100644 +index 7f7b0c961a76119b6004da03fe01ff4e2ae41628..9a64ab092ac8616ed8b9ea5c1e8677dda5c4333c 100644 --- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java -@@ -75,7 +75,9 @@ public class TheEndBiomeSource extends BiomeSource { +@@ -84,7 +84,7 @@ public class TheEndBiomeSource extends BiomeSource { int l = j / 2; - int i1 = i % 2; - int j1 = j % 2; -- float f = 100.0F - Mth.sqrt((float) (i * i + j * j)) * 8.0F; -+ // Paper start - cast ints to long to avoid integer overflow -+ float f = 100.0F - Mth.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; -+ // Paper end - + int m = i % 2; + int n = j % 2; +- float f = 100.0F - Mth.sqrt((float)(i * i + j * j)) * 8.0F; ++ float f = 100.0F - Mth.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; // Paper - cast ints to long to avoid integer overflow f = Mth.clamp(f, -100.0F, 80.0F); + for(int o = -12; o <= 12; ++o) { diff --git a/patches/server-remapped/0497-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/patches/server/0451-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch similarity index 76% rename from patches/server-remapped/0497-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch rename to patches/server/0451-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch index 423af0ebf9..1e146b3ec8 100644 --- a/patches/server-remapped/0497-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch +++ b/patches/server/0451-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch @@ -7,15 +7,15 @@ Subject: [PATCH] Fix CraftScheduler#runTaskTimerAsynchronously(Plugin, diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index ca90237a53c9a026919d28adaedf483ca3c7c2a8..13e461ffb2ee2e7d0440c0f60809ea99629b843c 100644 +index dd1e8b170e87bff2089f642f41dcf7442a8ccd16..33480893ddee34a1983c5f1c4b14db98ff438528 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java @@ -184,7 +184,7 @@ public class CraftScheduler implements BukkitScheduler { @Override public void runTaskTimerAsynchronously(Plugin plugin, Consumer task, long delay, long period) throws IllegalArgumentException { -- runTaskTimerAsynchronously(plugin, (Object) task, delay, CraftTask.NO_REPEATING); -+ runTaskTimerAsynchronously(plugin, (Object) task, delay, period); +- this.runTaskTimerAsynchronously(plugin, (Object) task, delay, CraftTask.NO_REPEATING); ++ this.runTaskTimerAsynchronously(plugin, (Object) task, delay, period); } @Override diff --git a/patches/server-remapped/0498-Fix-piston-physics-inconsistency-MC-188840.patch b/patches/server/0452-Fix-piston-physics-inconsistency-MC-188840.patch similarity index 72% rename from patches/server-remapped/0498-Fix-piston-physics-inconsistency-MC-188840.patch rename to patches/server/0452-Fix-piston-physics-inconsistency-MC-188840.patch index 1d54c7bad6..8910512100 100644 --- a/patches/server-remapped/0498-Fix-piston-physics-inconsistency-MC-188840.patch +++ b/patches/server/0452-Fix-piston-physics-inconsistency-MC-188840.patch @@ -47,10 +47,10 @@ index 7f140333c2e62012fa572c1a061d84432426997f..b67ba8f75e4a3358d7c2462918b85b0b + } } diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -index 40a18302dd682e5ade4ec77ac7f316b6c0f8c112..44876557515eaa6bbe33344b3d3ba03aee58409f 100644 +index 44cc09006eac6315d167a2628857f9942eb1fc13..aea9a2dc4164f5728e711efb3009bde8862c7345 100644 --- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -@@ -398,12 +398,24 @@ public class PistonBaseBlock extends DirectionalBlock { +@@ -411,14 +411,26 @@ public class PistonBaseBlock extends DirectionalBlock { } for (k = list.size() - 1; k >= 0; --k) { @@ -63,14 +63,16 @@ index 40a18302dd682e5ade4ec77ac7f316b6c0f8c112..44876557515eaa6bbe33344b3d3ba03a + // Paper end - fix a variety of piston desync dupes blockposition3 = blockposition3.relative(enumdirection1); map.remove(blockposition3); - world.setBlock(blockposition3, (BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, dir), 68); -- world.setBlockEntity(blockposition3, MovingPistonBlock.newMovingBlockEntity((BlockState) list1.get(k), dir, retract, false)); + BlockState iblockdata2 = (BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, dir); + + world.setBlock(blockposition3, iblockdata2, 68); +- world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockposition3, iblockdata2, (BlockState) list1.get(k), dir, retract, false)); + // Paper start - fix a variety of piston desync dupes + if (!allowDesync) { + iblockdata1 = world.getBlockState(oldPos); + map.replace(oldPos, iblockdata1); + } -+ world.setBlockEntity(blockposition3, MovingPistonBlock.newMovingBlockEntity(allowDesync ? list1.get(k) : iblockdata1, dir, retract, false)); ++ world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockposition3, iblockdata2, allowDesync ? list1.get(k) : iblockdata1, dir, retract, false)); + if (!allowDesync) { + world.setBlock(oldPos, Blocks.AIR.defaultBlockState(), 2 | 4 | 16 | 1024); // set air to prevent later physics updates from seeing this block + } @@ -79,15 +81,15 @@ index 40a18302dd682e5ade4ec77ac7f316b6c0f8c112..44876557515eaa6bbe33344b3d3ba03a } diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -index 73888713746e7ddd72ba9ac9d33d8e616eb3bd25..001e90da8b09e16b6df4849a5bac4f4821000c94 100644 +index 9b631698d1c736f61e07a5a1253127f4081dc90d..87bedba9ab495edcce289c6665271d92b7165944 100644 --- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -@@ -279,7 +279,7 @@ public class PistonMovingBlockEntity extends BlockEntity implements TickableBloc - BlockState iblockdata = Block.updateFromNeighbourShapes(this.movedState, (LevelAccessor) this.level, this.worldPosition); - - if (iblockdata.isAir()) { -- this.level.setBlock(this.worldPosition, this.movedState, 84); -+ this.level.setBlock(this.worldPosition, this.movedState, com.destroystokyo.paper.PaperConfig.allowPistonDuplication ? 84 : (84 | 2)); // Paper - force notify (flag 2), it's possible the set type by the piston block (which doesn't notify) set this block to air - Block.updateOrDestroy(this.movedState, iblockdata, this.level, this.worldPosition, 3); +@@ -281,7 +281,7 @@ public class PistonMovingBlockEntity extends BlockEntity { + if (blockEntity.movedState != null && world.getBlockState(pos).is(Blocks.MOVING_PISTON)) { + BlockState blockState = Block.updateFromNeighbourShapes(blockEntity.movedState, world, pos); + if (blockState.isAir()) { +- world.setBlock(pos, blockEntity.movedState, 84); ++ world.setBlock(pos, blockEntity.movedState, com.destroystokyo.paper.PaperConfig.allowPistonDuplication ? 84 : (84 | 2)); // Paper - force notify (flag 2), it's possible the set type by the piston block (which doesn't notify) set this block to air + Block.updateOrDestroy(blockEntity.movedState, blockState, world, pos, 3); } else { - if (iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) iblockdata.getValue(BlockStateProperties.WATERLOGGED)) { + if (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED)) { diff --git a/patches/server-remapped/0499-Fix-sand-duping.patch b/patches/server/0453-Fix-sand-duping.patch similarity index 81% rename from patches/server-remapped/0499-Fix-sand-duping.patch rename to patches/server/0453-Fix-sand-duping.patch index d06a661655..dd88074406 100644 --- a/patches/server-remapped/0499-Fix-sand-duping.patch +++ b/patches/server/0453-Fix-sand-duping.patch @@ -7,27 +7,27 @@ If the falling block dies during teleportation (entity#move), then we need to detect that by placing a check after the move. diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -index ff8f7e4569a889ead1512b7c9908f9c5cad9eed5..2ba81e7179c7f9e2e1add1ad6bd6b96ee12c5da1 100644 +index 2332a00780edcf054ec63a60a42962033d0cc74a..2fad050547242028d4ff2deb613e074190f51341 100644 --- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -101,6 +101,11 @@ public class FallingBlockEntity extends Entity { +@@ -106,6 +106,11 @@ public class FallingBlockEntity extends Entity { @Override public void tick() { + // Paper start - fix sand duping -+ if (this.removed) { ++ if (this.isRemoved()) { + return; + } + // Paper end - fix sand duping if (this.blockState.isAir()) { - this.remove(); + this.discard(); } else { -@@ -123,6 +128,12 @@ public class FallingBlockEntity extends Entity { +@@ -128,6 +133,12 @@ public class FallingBlockEntity extends Entity { this.move(MoverType.SELF, this.getDeltaMovement()); + // Paper start - fix sand duping -+ if (this.removed) { ++ if (this.isRemoved()) { + return; + } + // Paper end - fix sand duping diff --git a/patches/server-remapped/0500-Prevent-position-desync-in-playerconnection-causing-.patch b/patches/server/0454-Prevent-position-desync-in-playerconnection-causing-.patch similarity index 86% rename from patches/server-remapped/0500-Prevent-position-desync-in-playerconnection-causing-.patch rename to patches/server/0454-Prevent-position-desync-in-playerconnection-causing-.patch index 9994f830fa..032768e519 100644 --- a/patches/server-remapped/0500-Prevent-position-desync-in-playerconnection-causing-.patch +++ b/patches/server/0454-Prevent-position-desync-in-playerconnection-causing-.patch @@ -14,10 +14,10 @@ behaviour, we need to move all of this dangerous logic outside of the move call and into an appropriate place in the tick method. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 0625bc7ffd07b66b27176fe62ae3061aa7c67df2..fbafb89cc63744d942933546026e272122bd9fba 100644 +index b5325f19458467b307db629a00359af41004124a..7c9ac85431f8c5a325c94c0e7d1db0315b2d62c1 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1324,6 +1324,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1345,6 +1345,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9)); this.player.setOnGround(packet.isOnGround()); // CraftBukkit - SPIGOT-5810, SPIGOT-5835: reset by this.player.move @@ -28,4 +28,4 @@ index 0625bc7ffd07b66b27176fe62ae3061aa7c67df2..fbafb89cc63744d942933546026e2721 + // Paper end - prevent position desync double d12 = d8; - d7 = d4 - this.player.getX(); + d7 = d0 - this.player.getX(); diff --git a/patches/server-remapped/0502-Inventory-getHolder-method-without-block-snapshot.patch b/patches/server/0455-Inventory-getHolder-method-without-block-snapshot.patch similarity index 56% rename from patches/server-remapped/0502-Inventory-getHolder-method-without-block-snapshot.patch rename to patches/server/0455-Inventory-getHolder-method-without-block-snapshot.patch index d25c9ffc5a..888e64518b 100644 --- a/patches/server-remapped/0502-Inventory-getHolder-method-without-block-snapshot.patch +++ b/patches/server/0455-Inventory-getHolder-method-without-block-snapshot.patch @@ -5,33 +5,25 @@ Subject: [PATCH] Inventory getHolder method without block snapshot diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index ef2d18d19a86b3701855aa1ac126462e663f8fcd..7ccc085228f373e6eba55d809bed480d43d5c211 100644 +index 56bd3290fdf011590594d68128eb3fe9ca71506c..7850dfa9130761905030856786a97a008c700687 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -10,6 +10,7 @@ import net.minecraft.world.inventory.PlayerEnderChestContainer; - import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; - import net.minecraft.world.level.block.entity.BarrelBlockEntity; - import net.minecraft.world.level.block.entity.BlastFurnaceBlockEntity; -+import net.minecraft.world.level.block.entity.BlockEntity; - import net.minecraft.world.level.block.entity.BrewingStandBlockEntity; - import net.minecraft.world.level.block.entity.DispenserBlockEntity; - import net.minecraft.world.level.block.entity.DropperBlockEntity; -@@ -525,6 +526,13 @@ public class CraftInventory implements Inventory { - return inventory.getOwner(); +@@ -525,6 +525,13 @@ public class CraftInventory implements Inventory { + return this.inventory.getOwner(); } + // Paper start - getHolder without snapshot + @Override + public InventoryHolder getHolder(boolean useSnapshot) { -+ return inventory instanceof BlockEntity ? ((BlockEntity) inventory).getOwner(useSnapshot) : getHolder(); ++ return inventory instanceof net.minecraft.world.level.block.entity.BlockEntity ? ((net.minecraft.world.level.block.entity.BlockEntity) inventory).getOwner(useSnapshot) : getHolder(); + } + // Paper end + @Override public int getMaxStackSize() { - return inventory.getMaxStackSize(); + return this.inventory.getMaxStackSize(); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -index 3245dfa94410d319e53543c862c990e80ed3c72d..23dcf6e9332bd2b42ebb851497483e41948355d8 100644 +index 01d425d359f2d6d87b6c01b435a9cfcfe11caa20..4707a651dc80086efa852bcfba38a534e7f1f3d0 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java @@ -64,6 +64,13 @@ public class CraftInventoryDoubleChest extends CraftInventory implements DoubleC @@ -47,4 +39,4 @@ index 3245dfa94410d319e53543c862c990e80ed3c72d..23dcf6e9332bd2b42ebb851497483e41 + @Override public Location getLocation() { - return getLeftSide().getLocation().add(getRightSide().getLocation()).multiply(0.5); + return this.getLeftSide().getLocation().add(this.getRightSide().getLocation()).multiply(0.5); diff --git a/patches/server/0456-Expose-Arrow-getItemStack.patch b/patches/server/0456-Expose-Arrow-getItemStack.patch new file mode 100644 index 0000000000..3529a49750 --- /dev/null +++ b/patches/server/0456-Expose-Arrow-getItemStack.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nesaak <52047222+Nesaak@users.noreply.github.com> +Date: Sat, 23 May 2020 10:31:11 -0400 +Subject: [PATCH] Expose Arrow getItemStack + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +index 376885c8148da619a3b203145d315ebaf44994fb..88defdc48c72580bbf029910f159dedccf67dc1e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +@@ -102,6 +102,13 @@ public class CraftArrow extends AbstractProjectile implements AbstractArrow { + this.getHandle().pickup = net.minecraft.world.entity.projectile.AbstractArrow.Pickup.byOrdinal(status.ordinal()); + } + ++ // Paper start ++ @Override ++ public org.bukkit.craftbukkit.inventory.CraftItemStack getItemStack() { ++ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(getHandle().getPickupItem()); ++ } ++ //Paper end ++ + @Override + public void setTicksLived(int value) { + super.setTicksLived(value); diff --git a/patches/server-remapped/0504-Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/server/0457-Add-and-implement-PlayerRecipeBookClickEvent.patch similarity index 76% rename from patches/server-remapped/0504-Add-and-implement-PlayerRecipeBookClickEvent.patch rename to patches/server/0457-Add-and-implement-PlayerRecipeBookClickEvent.patch index 412fc1c8ad..dd62e3c0fe 100644 --- a/patches/server-remapped/0504-Add-and-implement-PlayerRecipeBookClickEvent.patch +++ b/patches/server/0457-Add-and-implement-PlayerRecipeBookClickEvent.patch @@ -5,25 +5,23 @@ Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index fbafb89cc63744d942933546026e272122bd9fba..a0b2fc3fe59d97b9282a9451f35542b39df774e7 100644 +index 7c9ac85431f8c5a325c94c0e7d1db0315b2d62c1..c65f6eda0cff66ae9007e92002075e1f6fd631cd 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2770,9 +2770,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2778,9 +2778,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); this.player.resetLastActionTime(); - if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu.isSynched(this.player) && this.player.containerMenu instanceof RecipeBookMenu) { + if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu instanceof RecipeBookMenu) { - this.server.getRecipeManager().byKey(packet.getRecipe()).ifPresent((irecipe) -> { - ((RecipeBookMenu) this.player.containerMenu).handlePlacement(packet.isShiftDown(), irecipe, this.player); -- }); + // Paper start - fire event for clicking recipes in the recipe book + com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent event = new com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent( + player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(packet.getRecipe()), packet.isShiftDown()); + if (event.callEvent()) { + this.server.getRecipeManager().byKey(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getRecipe())).ifPresent((irecipe) -> { -+ ((ContainerRecipeBook) this.player.activeContainer).a(event.isMakeAll(), irecipe, this.player); -+ }); -+ } -+ // Paper end ++ ((RecipeBookMenu) this.player.containerMenu).handlePlacement(event.isMakeAll(), irecipe, this.player); + }); ++ } // Paper end } } diff --git a/patches/server-remapped/0505-Hide-sync-chunk-writes-behind-flag.patch b/patches/server/0458-Hide-sync-chunk-writes-behind-flag.patch similarity index 93% rename from patches/server-remapped/0505-Hide-sync-chunk-writes-behind-flag.patch rename to patches/server/0458-Hide-sync-chunk-writes-behind-flag.patch index 43a0839a47..f00dbd43a0 100644 --- a/patches/server-remapped/0505-Hide-sync-chunk-writes-behind-flag.patch +++ b/patches/server/0458-Hide-sync-chunk-writes-behind-flag.patch @@ -9,7 +9,7 @@ on harddrives. -DPaper.enable-sync-chunk-writes=true to enable diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index 545096d9ba403396b6aaa7bb6d912f2de08a967e..3450a58fc02a472eb710aa1a31f6fecefc982b6f 100644 +index e3409d5f4ddcaa4edecfa4b3c638a12624b09f1b..c9d80a5430cc66d6189bf337770af43121a5bfd5 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java @@ -108,7 +108,7 @@ public class DedicatedServerProperties extends Settings +Date: Sun, 10 May 2020 22:12:46 -0400 +Subject: [PATCH] Ensure Entity AABB's are never invalid + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 11ae525a5d2bd29bfe658d683c53a0ab2626616a..fd0cef886761e71fe331aa60806c186c23ed19bc 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -540,7 +540,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + + public void setPos(double x, double y, double z) { + this.setPosRaw(x, y, z); +- this.setBoundingBox(this.makeBoundingBox()); ++ // this.setBoundingBox(this.makeBoundingBox()); // Paper - move into setPositionRaw + } + + protected AABB makeBoundingBox() { +@@ -3717,6 +3717,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + } + + public final void setPosRaw(double x, double y, double z) { ++ // Paper start - never allow AABB to become desynced from position ++ // hanging has its own special logic ++ if (!(this instanceof net.minecraft.world.entity.decoration.HangingEntity) && (this.position.x != x || this.position.y != y || this.position.z != z)) { ++ this.setBoundingBox(this.dimensions.makeBoundingBox(x, y, z)); ++ } ++ // Paper end + if (this.position.x != x || this.position.y != y || this.position.z != z) { + this.position = new Vec3(x, y, z); + int i = Mth.floor(x); diff --git a/patches/server/0461-Optimize-WorldBorder-collision-checks-and-air.patch b/patches/server/0461-Optimize-WorldBorder-collision-checks-and-air.patch new file mode 100644 index 0000000000..01936bbbf9 --- /dev/null +++ b/patches/server/0461-Optimize-WorldBorder-collision-checks-and-air.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 10 May 2020 22:49:05 -0400 +Subject: [PATCH] Optimize WorldBorder collision checks and air + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index fd0cef886761e71fe331aa60806c186c23ed19bc..96da70f1077f70c4bd5ba1196292a856deb25286 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1024,7 +1024,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + AABB axisalignedbb = this.getBoundingBox(); + CollisionContext voxelshapecollision = CollisionContext.of(this); + VoxelShape voxelshape = this.level.getWorldBorder().getCollisionShape(); +- Stream stream = Shapes.joinIsNotEmpty(voxelshape, Shapes.create(axisalignedbb.deflate(1.0E-7D)), BooleanOp.AND) ? Stream.empty() : Stream.of(voxelshape); ++ Stream stream = !this.level.getWorldBorder().isWithinBounds(axisalignedbb) ? Stream.empty() : Stream.of(voxelshape); // Paper + Stream stream1 = this.level.getEntityCollisions(this, axisalignedbb.expandTowards(movement), (entity) -> { + return true; + }); +diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +index 90039d01ef481ba206f2e952c99a755e94201ea3..2e93f33d6c9074c246c2289523b1fda20a2cf0dd 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java ++++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +@@ -135,9 +135,10 @@ public class CollisionSpliterator extends AbstractSpliterator { + WorldBorder worldBorder = this.collisionGetter.getWorldBorder(); + AABB aABB = this.source.getBoundingBox(); + if (!isBoxFullyWithinWorldBorder(worldBorder, aABB)) { +- VoxelShape voxelShape = worldBorder.getCollisionShape(); +- if (!isOutsideBorder(voxelShape, aABB) && isCloseToBorder(voxelShape, aABB)) { +- action.accept(voxelShape); ++ // Paper start ++ if (worldBorder.isWithinBounds(aABB.deflate(1.0E-7D)) && !worldBorder.isWithinBounds(aABB.inflate(1.0E-7D))) { ++ action.accept(worldBorder.asVoxelShape()); ++ // Paper end + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index 94f58332bb1408971fe65e5fd0401457ab986441..ceeec68fba8dacdc5b023c8817a6863b28c0e132 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -240,7 +240,7 @@ public final class Shapes { + mutableBlockPos.set(axisCycle, q, r, p); + BlockState blockState = world.getTypeIfLoaded(mutableBlockPos); // Paper + if (blockState == null) return 0.0D; // Paper +- if ((s != 1 || blockState.hasLargeCollisionShape()) && (s != 2 || blockState.is(Blocks.MOVING_PISTON))) { ++ if (!blockState.isAir() && (s != 1 || blockState.hasLargeCollisionShape()) && (s != 2 || blockState.is(Blocks.MOVING_PISTON))) { // Paper + initial = blockState.getCollisionShape(world, mutableBlockPos, context).collide(axis3, box.move((double)(-mutableBlockPos.getX()), (double)(-mutableBlockPos.getY()), (double)(-mutableBlockPos.getZ())), initial); + if (Math.abs(initial) < 1.0E-7D) { + return 0.0D; diff --git a/patches/server-remapped/0510-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/patches/server/0462-Fix-Per-World-Difficulty-Remembering-Difficulty.patch similarity index 57% rename from patches/server-remapped/0510-Fix-Per-World-Difficulty-Remembering-Difficulty.patch rename to patches/server/0462-Fix-Per-World-Difficulty-Remembering-Difficulty.patch index 568d1c34e6..eec5efcc02 100644 --- a/patches/server-remapped/0510-Fix-Per-World-Difficulty-Remembering-Difficulty.patch +++ b/patches/server/0462-Fix-Per-World-Difficulty-Remembering-Difficulty.patch @@ -8,61 +8,52 @@ makes it so that the server keeps the last difficulty used instead of restoring the server.properties every single load. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f530c739b6aee3718eb5d0e0e6a09d882d817c68..19544b794b5a46c129016172798ff7294fcfed33 100644 +index 363dcebb3b2d5a2512776a191f6716ed3d0e8aff..1feda8b44364c748497174944b26abc4f058f354 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1645,11 +1645,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight", "dumpitem").build(); +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "fixlight").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "fixlight", "dumpitem").build(); public PaperCommand(String name) { super(name); -@@ -168,6 +171,9 @@ public class PaperCommand extends Command { +@@ -156,6 +159,9 @@ public class PaperCommand extends Command { case "reload": doReload(sender); break; @@ -46,18 +46,18 @@ index 528c860fc0c04431e0ebb2ae6bc96bf9c2d04789..6fad9329213e4e8a3ef9ce7fb568ad22 case "debug": doDebug(sender, args); break; -@@ -200,6 +206,19 @@ public class PaperCommand extends Command { - return true; - } +@@ -420,6 +426,19 @@ public class PaperCommand extends Command { + Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete."); + } + private void doDumpItem(CommandSender sender) { + ItemStack itemInHand = ((CraftPlayer) sender).getItemInHand(); + net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(itemInHand); -+ CompoundTag tag = itemStack.getTag(); ++ net.minecraft.nbt.CompoundTag tag = itemStack.getTag(); + if (tag != null) { -+ String nbt = org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(tag.getNbtPrettyComponent()); -+ Bukkit.getConsoleSender().sendMessage(nbt); -+ sender.sendMessage(nbt); ++ net.kyori.adventure.text.Component nbtComponent = io.papermc.paper.adventure.PaperAdventure.asAdventure(net.minecraft.nbt.NbtUtils.toPrettyComponent(tag)); ++ Bukkit.getConsoleSender().sendMessage(nbtComponent); ++ sender.sendMessage(nbtComponent); + } else { + sender.sendMessage("Item does not have NBT"); + } @@ -66,15 +66,3 @@ index 528c860fc0c04431e0ebb2ae6bc96bf9c2d04789..6fad9329213e4e8a3ef9ce7fb568ad22 private void doFixLight(CommandSender sender, String[] args) { if (!(sender instanceof Player)) { sender.sendMessage("Only players can use this command"); -diff --git a/src/main/java/net/minecraft/nbt/Tag.java b/src/main/java/net/minecraft/nbt/Tag.java -index 85e9c5f4620fcf48cb3655fbb2db58b3fb31aa74..ba204cf135be333d4ac1c06ee6c2e961faadf8cb 100644 ---- a/src/main/java/net/minecraft/nbt/Tag.java -+++ b/src/main/java/net/minecraft/nbt/Tag.java -@@ -26,6 +26,7 @@ public interface Tag { - return this.toString(); - } - -+ default Component getNbtPrettyComponent() { return this.getPrettyDisplay(); } // Paper - OBFHELPER - default Component getPrettyDisplay() { - return this.getPrettyDisplay("", 0); - } diff --git a/patches/server-remapped/0512-Don-t-allow-null-UUID-s-for-chat.patch b/patches/server/0464-Don-t-allow-null-UUID-s-for-chat.patch similarity index 53% rename from patches/server-remapped/0512-Don-t-allow-null-UUID-s-for-chat.patch rename to patches/server/0464-Don-t-allow-null-UUID-s-for-chat.patch index dfc52a21c5..1117d64336 100644 --- a/patches/server-remapped/0512-Don-t-allow-null-UUID-s-for-chat.patch +++ b/patches/server/0464-Don-t-allow-null-UUID-s-for-chat.patch @@ -5,23 +5,15 @@ Subject: [PATCH] Don't allow null UUID's for chat diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -index 002a6c7933f64405707d7d34d3e5c17584539623..a983785bf3bc43f65bd0809870c14a9fd30a3fc1 100644 +index 26a229f7aa3f4425ed572e2d50730b4e978bf33e..a9fdfa7ec2a022e8adaa62721fb56748884686f5 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -@@ -3,6 +3,7 @@ package net.minecraft.network.protocol.game; - - import java.io.IOException; - import java.util.UUID; -+import net.minecraft.Util; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.chat.ChatType; - import net.minecraft.network.chat.Component; -@@ -21,7 +22,7 @@ public class ClientboundChatPacket implements Packet { - public ClientboundChatPacket(Component message, ChatType location, UUID senderUuid) { +@@ -18,7 +18,7 @@ public class ClientboundChatPacket implements Packet { + public ClientboundChatPacket(Component message, ChatType location, UUID sender) { this.message = message; this.type = location; -- this.sender = senderUuid; -+ this.sender = senderUuid != null ? senderUuid : Util.getNullUUID(); // Paper +- this.sender = sender; ++ this.sender = sender != null ? sender : net.minecraft.Util.NIL_UUID; } - @Override + public ClientboundChatPacket(FriendlyByteBuf buf) { diff --git a/patches/server-remapped/0513-Improve-Legacy-Component-serialization-size.patch b/patches/server/0465-Improve-Legacy-Component-serialization-size.patch similarity index 81% rename from patches/server-remapped/0513-Improve-Legacy-Component-serialization-size.patch rename to patches/server/0465-Improve-Legacy-Component-serialization-size.patch index 2f031e9064..8d30b49c6b 100644 --- a/patches/server-remapped/0513-Improve-Legacy-Component-serialization-size.patch +++ b/patches/server/0465-Improve-Legacy-Component-serialization-size.patch @@ -7,7 +7,7 @@ Don't constantly send format: false for all formatting options when parent alrea has it false diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -index b27af66795d902a2e95d692fa0ff18eccbef8a75..b89660244ffad484e3fbf69ccb9cdc1bc178d2ad 100644 +index 0de5a46423ae0403dcbfca630dfd7c5ac1e1761d..26d43c229caf9f8504af7071c3a61ec6da7e27ec 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java @@ -46,6 +46,7 @@ public final class CraftChatMessage { @@ -15,11 +15,11 @@ index b27af66795d902a2e95d692fa0ff18eccbef8a75..b89660244ffad484e3fbf69ccb9cdc1b private static final Pattern INCREMENTAL_PATTERN_KEEP_NEWLINES = Pattern.compile("(" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + "[0-9a-fk-orx])|((?:(?:https?):\\/\\/)?(?:[-\\w_\\.]{2,}\\.[a-z]{2,4}.*?(?=[\\.\\?!,;:]?(?:[" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + " ]|$))))", Pattern.CASE_INSENSITIVE); // ChatColor.b does not explicitly reset, its more of empty + private static final Style EMPTY = Style.EMPTY.withItalic(false); // Paper - OBFHELPER - private static final Style RESET = Style.EMPTY.withBold(false).withItalic(false).setUnderline(false).setStrikethrough(false).setRandom(false); + private static final Style RESET = Style.EMPTY.withBold(false).withItalic(false).withUnderlined(false).withStrikethrough(false).withObfuscated(false); private final List list = new ArrayList(); @@ -67,6 +68,7 @@ public final class CraftChatMessage { - Matcher matcher = (keepNewlines ? INCREMENTAL_PATTERN_KEEP_NEWLINES : INCREMENTAL_PATTERN).matcher(message); + Matcher matcher = (keepNewlines ? StringMessage.INCREMENTAL_PATTERN_KEEP_NEWLINES : StringMessage.INCREMENTAL_PATTERN).matcher(message); String match = null; boolean needsAdd = false; + boolean hasReset = false; // Paper @@ -30,7 +30,7 @@ index b27af66795d902a2e95d692fa0ff18eccbef8a75..b89660244ffad484e3fbf69ccb9cdc1b throw new AssertionError("Unexpected message format"); } } else { // Color resets formatting -- modifier = RESET.withColor(format); +- this.modifier = StringMessage.RESET.withColor(format); + // Paper start - improve legacy formatting + Style previous = modifier; + modifier = (!hasReset ? RESET : EMPTY).withColor(format); @@ -42,13 +42,13 @@ index b27af66795d902a2e95d692fa0ff18eccbef8a75..b89660244ffad484e3fbf69ccb9cdc1b + modifier = modifier.withItalic(false); + } + if (previous.isObfuscated()) { -+ modifier = modifier.setRandom(false); ++ modifier = modifier.withObfuscated(false); + } + if (previous.isStrikethrough()) { -+ modifier = modifier.setStrikethrough(false); ++ modifier = modifier.withStrikethrough(false); + } + if (previous.isUnderlined()) { -+ modifier = modifier.setUnderline(false); ++ modifier = modifier.withUnderlined(false); + } + // Paper end } diff --git a/patches/server-remapped/0514-Support-old-UUID-format-for-NBT.patch b/patches/server/0466-Support-old-UUID-format-for-NBT.patch similarity index 51% rename from patches/server-remapped/0514-Support-old-UUID-format-for-NBT.patch rename to patches/server/0466-Support-old-UUID-format-for-NBT.patch index ffba727ac3..0418f312a1 100644 --- a/patches/server-remapped/0514-Support-old-UUID-format-for-NBT.patch +++ b/patches/server/0466-Support-old-UUID-format-for-NBT.patch @@ -8,10 +8,10 @@ We have stored UUID in plenty of places that did not get DFU'd So just look for old format and load it if it exists. diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java -index c856ca720a9329a94bb07eaa3060c034f95718b3..0b739b5f040697049893d311c99456dbc5470e93 100644 +index 1aa3af8c7714b2c850fb4264c863db8e639e6284..2a805d6bbeede50898d36258976ff25ee0aea165 100644 --- a/src/main/java/net/minecraft/nbt/CompoundTag.java +++ b/src/main/java/net/minecraft/nbt/CompoundTag.java -@@ -142,6 +142,12 @@ public class CompoundTag implements Tag { +@@ -121,6 +121,12 @@ public class CompoundTag implements Tag { public void setUUID(String prefix, UUID uuid) { putUUID(prefix, uuid); } // Paper - OBFHELPER public void putUUID(String key, UUID value) { @@ -24,9 +24,9 @@ index c856ca720a9329a94bb07eaa3060c034f95718b3..0b739b5f040697049893d311c99456db this.tags.put(key, NbtUtils.createUUID(value)); } -@@ -151,11 +157,21 @@ public class CompoundTag implements Tag { +@@ -129,10 +135,20 @@ public class CompoundTag implements Tag { + * You must use {@link #hasUUID(String)} before or else it will throw an NPE. */ - public UUID getUUID(String prefix) { return getUUID(prefix); } // Paper - OBFHELPER public UUID getUUID(String key) { + // Paper start - support old format + if (!contains(key, 11) && this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { @@ -36,29 +36,45 @@ index c856ca720a9329a94bb07eaa3060c034f95718b3..0b739b5f040697049893d311c99456db return NbtUtils.loadUUID(this.get(key)); } - public final boolean hasUUID(String s) { return this.hasUUID(s); } // Paper - OBFHELPER public boolean hasUUID(String key) { + // Paper start - support old format + if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { + return true; + } + // Paper end - Tag nbtbase = this.get(key); - - return nbtbase != null && nbtbase.getType() == IntArrayTag.TYPE && ((IntArrayTag) nbtbase).getAsIntArray().length == 4; + Tag tag = this.get(key); + return tag != null && tag.getType() == IntArrayTag.TYPE && ((IntArrayTag)tag).getAsIntArray().length == 4; + } diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java -index bf0da04ec9db3ec8313bddb06c278c13073819d1..f57c5e441045a81072a2edfed0f199d90e6d7fde 100644 +index 57c9575a9714acb95d9dced672955a96d71dfd1e..dc136cd4d5d4ba1e0e53a7187b3a2e836e185c19 100644 --- a/src/main/java/net/minecraft/nbt/NbtUtils.java +++ b/src/main/java/net/minecraft/nbt/NbtUtils.java -@@ -40,6 +40,11 @@ public final class NbtUtils { - s = tag.getString("Name"); +@@ -40,14 +40,14 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + public final class NbtUtils { +- private static final Comparator YXZ_LISTTAG_INT_COMPARATOR = Comparator.comparingInt((listTag) -> { ++ private static final Comparator YXZ_LISTTAG_INT_COMPARATOR = Comparator.comparingInt((listTag) -> { // Paper - decompile fix + return listTag.getInt(1); + }).thenComparingInt((listTag) -> { + return listTag.getInt(0); + }).thenComparingInt((listTag) -> { + return listTag.getInt(2); + }); +- private static final Comparator YXZ_LISTTAG_DOUBLE_COMPARATOR = Comparator.comparingDouble((listTag) -> { ++ private static final Comparator YXZ_LISTTAG_DOUBLE_COMPARATOR = Comparator.comparingDouble((listTag) -> { // Paper - decompile fix + return listTag.getDouble(1); + }).thenComparingDouble((listTag) -> { + return listTag.getDouble(0); +@@ -76,6 +76,11 @@ public final class NbtUtils { + string = compound.getString("Name"); } + // Paper start - support string UUID's -+ if (tag.contains("Id", 8)) { -+ uuid = UUID.fromString(tag.getString("Id")); ++ if (compound.contains("Id", 8)) { ++ uUID = UUID.fromString(compound.getString("Id")); + } + // Paper end - if (tag.hasUUID("Id")) { - uuid = tag.getUUID("Id"); + if (compound.hasUUID("Id")) { + uUID = compound.getUUID("Id"); } diff --git a/patches/server/0467-Clean-up-duplicated-GameProfile-Properties.patch b/patches/server/0467-Clean-up-duplicated-GameProfile-Properties.patch new file mode 100644 index 0000000000..495144b4fb --- /dev/null +++ b/patches/server/0467-Clean-up-duplicated-GameProfile-Properties.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 1 Jul 2020 03:12:06 -0400 +Subject: [PATCH] Clean up duplicated GameProfile Properties + +We had a bug where we accidently cloned properties resulting in skulls +growing to large sizes and preventing login. + +This now automatically cleans up the extra properties. + +diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java +index dc136cd4d5d4ba1e0e53a7187b3a2e836e185c19..1a9435a55e20170244497be70d86d989a4e0f78f 100644 +--- a/src/main/java/net/minecraft/nbt/NbtUtils.java ++++ b/src/main/java/net/minecraft/nbt/NbtUtils.java +@@ -93,7 +93,8 @@ public final class NbtUtils { + for(String string2 : compoundTag.getAllKeys()) { + ListTag listTag = compoundTag.getList(string2, 10); + +- for(int i = 0; i < listTag.size(); ++i) { ++ if (listTag.size() == 0) continue; // Paper - remove duplicate properties ++ for (int i = listTag.size() - 1; i < listTag.size(); ++i) { // Paper - remove duplicate properties + CompoundTag compoundTag2 = listTag.getCompound(i); + String string3 = compoundTag2.getString("Value"); + if (compoundTag2.contains("Signature", 8)) { +diff --git a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java +index 7fb2cc8d49a2d8f256f625cb99b66ef8efc3fc0e..f9980110a4614bb0206dce3dc796d9459069b750 100644 +--- a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java ++++ b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java +@@ -53,6 +53,18 @@ public class PlayerHeadItem extends StandingAndWallBlockItem { + }); + // CraftBukkit start + } else { ++ // Paper start - clean up old duplicated properties ++ CompoundTag properties = nbt.getCompound("SkullOwner").getCompound("Properties"); ++ for (String key : properties.getAllKeys()) { ++ net.minecraft.nbt.ListTag values = properties.getList(key, 10); ++ if (values.size() > 1) { ++ net.minecraft.nbt.Tag texture = values.get(values.size() - 1); ++ values = new net.minecraft.nbt.ListTag(); ++ values.add(texture); ++ properties.put(key, values); ++ } ++ } ++ // Paper end + net.minecraft.nbt.ListTag textures = nbt.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts + for (int i = 0; i < textures.size(); i++) { + if (textures.get(i) instanceof CompoundTag && !((CompoundTag) textures.get(i)).contains("Signature", 8) && ((CompoundTag) textures.get(i)).getString("Value").trim().isEmpty()) { From f7bc64123028cd4357713241bad0faf9f419fc2a Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 02:06:46 -0700 Subject: [PATCH 107/226] Add missing getLevel implementation to Hopper Minecart, add mapping to fix reobf --- .../additional-spigot-member-mappings.csrg | 5 +++++ patches/server/0349-Optimize-Hoppers.patch | 22 +++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/build-data/additional-spigot-member-mappings.csrg b/build-data/additional-spigot-member-mappings.csrg index 962d83c9a2..33f15ea1ca 100644 --- a/build-data/additional-spigot-member-mappings.csrg +++ b/build-data/additional-spigot-member-mappings.csrg @@ -20,3 +20,8 @@ net/minecraft/world/entity/npc/EntityVillagerAbstract fD ()Lnet/minecraft/world/ # BehaviorWorkComposter -> BehaviorWork net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter a (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/npc/EntityVillager;)V doWork + +# We add getLevel to the Hopper interface (implemented by Hoppers and Hopper Minecarts), but this also exists on BlockEntity, +# which Hoppers also extend. We need to map the method we add to the Hopper interface to the same name used for the method on BlockEntity +# to avoid remap causing issues +net/minecraft/world/level/block/entity/IHopper getWorld ()Lnet/minecraft/world/level/World; getLevel diff --git a/patches/server/0349-Optimize-Hoppers.patch b/patches/server/0349-Optimize-Hoppers.patch index d68d9a0355..1ec55ab1c3 100644 --- a/patches/server/0349-Optimize-Hoppers.patch +++ b/patches/server/0349-Optimize-Hoppers.patch @@ -43,6 +43,24 @@ index f00839eab02277bf10b742c88fadc4aa9e89e7e0..312be2221e1acc44aaf6936533b0eb96 this.profiler.push(() -> { return worldserver + " " + worldserver.dimension().location(); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java +index 449d2e7b18608ca36282f1a29e69457fc525307e..c738cb0433ea4a86d82372bf66e29c01f991d2c6 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java +@@ -68,6 +68,13 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper + this.enabled = enabled; + } + ++ // Paper start - add back getLevel ++ @Override ++ public net.minecraft.world.level.Level getLevel() { ++ return this.level; ++ } ++ // Paper end ++ + @Override + public double getLevelX() { + return this.getX(); diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java index dd4deb08eb3ed15a156269a11d3d43abfd61fe5b..10f55ba189d12c46e0ef38b0b96a29894b4fba93 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java @@ -84,14 +102,14 @@ index 8a079ee3ed243fd19b1dd7eed2de1dd33785faa1..c3a07ccccd5cc38552363c82398f432c } diff --git a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java -index a05acf709735b40ca86f978508c63a86065fd405..c1754df6a60ff93d75a28145b9dc4e9174241a21 100644 +index a05acf709735b40ca86f978508c63a86065fd405..71dd26ca6626631b94d53818cd06b93f61485369 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java +++ b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java @@ -14,6 +14,10 @@ public interface Hopper extends Container { return SUCK; } -+ net.minecraft.world.level.Level getLevel(); ++ net.minecraft.world.level.Level getLevel(); // Paper + + default net.minecraft.core.BlockPos getBlockPosition() { return new net.minecraft.core.BlockPos(getLevelX(), getLevelY(), getLevelZ()); } // Paper + From eddf0f40dc9022cf233295eba7fe7132a61b8141 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 02:15:37 -0700 Subject: [PATCH 108/226] decomp fixes --- ...0466-Support-old-UUID-format-for-NBT.patch | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/patches/server/0466-Support-old-UUID-format-for-NBT.patch b/patches/server/0466-Support-old-UUID-format-for-NBT.patch index 0418f312a1..9fd9265bf0 100644 --- a/patches/server/0466-Support-old-UUID-format-for-NBT.patch +++ b/patches/server/0466-Support-old-UUID-format-for-NBT.patch @@ -46,7 +46,7 @@ index 1aa3af8c7714b2c850fb4264c863db8e639e6284..2a805d6bbeede50898d36258976ff25e return tag != null && tag.getType() == IntArrayTag.TYPE && ((IntArrayTag)tag).getAsIntArray().length == 4; } diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java -index 57c9575a9714acb95d9dced672955a96d71dfd1e..dc136cd4d5d4ba1e0e53a7187b3a2e836e185c19 100644 +index 57c9575a9714acb95d9dced672955a96d71dfd1e..06fe97e05608fc21f90c9884d745d910beb6883d 100644 --- a/src/main/java/net/minecraft/nbt/NbtUtils.java +++ b/src/main/java/net/minecraft/nbt/NbtUtils.java @@ -40,14 +40,14 @@ import org.apache.logging.log4j.LogManager; @@ -78,3 +78,23 @@ index 57c9575a9714acb95d9dced672955a96d71dfd1e..dc136cd4d5d4ba1e0e53a7187b3a2e83 if (compound.hasUUID("Id")) { uUID = compound.getUUID("Id"); } +@@ -495,7 +500,7 @@ public final class NbtUtils { + } + + public static CompoundTag update(DataFixer fixer, DataFixTypes fixTypes, CompoundTag compound, int oldVersion, int targetVersion) { +- return fixer.update(fixTypes.getType(), new Dynamic<>(NbtOps.INSTANCE, compound), oldVersion, targetVersion).getValue(); ++ return (CompoundTag) fixer.update(fixTypes.getType(), new com.mojang.serialization.Dynamic<>(NbtOps.INSTANCE, compound), oldVersion, targetVersion).getValue(); // Paper - decompile fix + } + + public static Component toPrettyComponent(Tag element) { +@@ -620,8 +625,8 @@ public final class NbtUtils { + CompoundTag compoundTag2 = new CompoundTag(); + if (i + 2 <= string.length()) { + String string3 = string.substring(i + 1, string.indexOf(125, i)); +- COMMA_SPLITTER.split(string3).forEach((string2) -> { +- List list = COLON_SPLITTER.splitToList(string2); ++ COMMA_SPLITTER.split(string3).forEach(it -> { // Paper - decompile fix ++ List list = COLON_SPLITTER.splitToList(it); // Paper - decompile fix + if (list.size() == 2) { + compoundTag2.putString(list.get(0), list.get(1)); + } else { From ba3ce754a9abf1eba3671039bf1763b923a674de Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 14 Jun 2021 11:46:59 +0200 Subject: [PATCH 109/226] more work uwu --- .../0211-Support-components-in-ItemMeta.patch | 0 ...-TargetReasons-for-1.16-mob-behavior.patch | 0 .../0213-Add-entity-liquid-API.patch | 4 +- ...reResultEvent-PrepareGrindstoneEvent.patch | 0 ...llow-delegation-to-vanilla-chunk-gen.patch | 6 +- ...-Remove-some-streams-from-structures.patch | 1 + ...ix-Concurrency-issue-in-WeightedList.patch | 2 +- ...vert-legacy-attributes-in-Item-Meta.patch} | 6 +- ...rom-classes-related-villager-gossip.patch} | 50 ++++++------ ...0470-Support-components-in-ItemMeta.patch} | 14 ++-- ...rgetLivingEntityEvent-for-1.16-mobs.patch} | 31 ++++---- .../0472-Add-entity-liquid-API.patch} | 14 ++-- ...date-itemstack-legacy-name-and-lore.patch} | 32 +++----- ...wn-player-in-correct-world-on-login.patch} | 4 +- .../0475-Add-PrepareResultEvent.patch} | 40 +++++----- ...low-delegation-to-vanilla-chunk-gen.patch} | 44 +++-------- ...-for-portal-on-world-gen-entity-add.patch} | 4 +- ...e-NetworkManager-Exception-Handling.patch} | 78 +++++-------------- ...ncement-data-player-iteration-to-be.patch} | 6 +- ...x-arrows-never-despawning-MC-125757.patch} | 6 +- ...Vanilla-Command-permission-checking.patch} | 10 +-- ...ve-range-check-for-block-placing-up.patch} | 16 ++-- 22 files changed, 150 insertions(+), 218 deletions(-) rename patches/{api-unmapped => api}/0211-Support-components-in-ItemMeta.patch (100%) rename patches/{api-unmapped => api}/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch (100%) rename patches/{api-unmapped => api}/0213-Add-entity-liquid-API.patch (88%) rename patches/{api-unmapped => api}/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch (100%) rename patches/{api-unmapped => api}/0215-Allow-delegation-to-vanilla-chunk-gen.patch (91%) rename patches/{server-remapped => removed/1.17}/0517-Remove-some-streams-from-structures.patch (98%) rename patches/{server-remapped => removed/1.17}/0528-Fix-Concurrency-issue-in-WeightedList.patch (98%) rename patches/{server-remapped/0516-Convert-legacy-attributes-in-Item-Meta.patch => server/0468-Convert-legacy-attributes-in-Item-Meta.patch} (92%) rename patches/{server-remapped/0518-Remove-streams-from-classes-related-villager-gossip.patch => server/0469-Remove-streams-from-classes-related-villager-gossip.patch} (66%) rename patches/{server-remapped/0519-Support-components-in-ItemMeta.patch => server/0470-Support-components-in-ItemMeta.patch} (87%) rename patches/{server-remapped/0520-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch => server/0471-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch} (66%) rename patches/{server-remapped/0521-Add-entity-liquid-API.patch => server/0472-Add-entity-liquid-API.patch} (81%) rename patches/{server-remapped/0522-Update-itemstack-legacy-name-and-lore.patch => server/0473-Update-itemstack-legacy-name-and-lore.patch} (70%) rename patches/{server-remapped/0523-Spawn-player-in-correct-world-on-login.patch => server/0474-Spawn-player-in-correct-world-on-login.patch} (90%) rename patches/{server-remapped/0524-Add-PrepareResultEvent.patch => server/0475-Add-PrepareResultEvent.patch} (83%) rename patches/{server-remapped/0525-Allow-delegation-to-vanilla-chunk-gen.patch => server/0476-Allow-delegation-to-vanilla-chunk-gen.patch} (64%) rename patches/{server-remapped/0526-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch => server/0477-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch} (84%) rename patches/{server-remapped/0527-Optimize-NetworkManager-Exception-Handling.patch => server/0478-Optimize-NetworkManager-Exception-Handling.patch} (51%) rename patches/{server-remapped/0529-Optimize-the-advancement-data-player-iteration-to-be.patch => server/0479-Optimize-the-advancement-data-player-iteration-to-be.patch} (91%) rename patches/{server-remapped/0530-Fix-arrows-never-despawning-MC-125757.patch => server/0480-Fix-arrows-never-despawning-MC-125757.patch} (87%) rename patches/{server-remapped/0531-Thread-Safe-Vanilla-Command-permission-checking.patch => server/0481-Thread-Safe-Vanilla-Command-permission-checking.patch} (85%) rename patches/{server-remapped/0532-Move-range-check-for-block-placing-up.patch => server/0482-Move-range-check-for-block-placing-up.patch} (71%) diff --git a/patches/api-unmapped/0211-Support-components-in-ItemMeta.patch b/patches/api/0211-Support-components-in-ItemMeta.patch similarity index 100% rename from patches/api-unmapped/0211-Support-components-in-ItemMeta.patch rename to patches/api/0211-Support-components-in-ItemMeta.patch diff --git a/patches/api-unmapped/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch b/patches/api/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch similarity index 100% rename from patches/api-unmapped/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch rename to patches/api/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch diff --git a/patches/api-unmapped/0213-Add-entity-liquid-API.patch b/patches/api/0213-Add-entity-liquid-API.patch similarity index 88% rename from patches/api-unmapped/0213-Add-entity-liquid-API.patch rename to patches/api/0213-Add-entity-liquid-API.patch index c38113b716..2bf531eba3 100644 --- a/patches/api-unmapped/0213-Add-entity-liquid-API.patch +++ b/patches/api/0213-Add-entity-liquid-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add entity liquid API diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 5b382091b1466b25ad42325d5808785a8e948552..ecb5595332ab493224d06a75904e142ab541aad9 100644 +index 4a6d58ef68b782291b4d26a8515be326481f5209..09dc74b0e10d075190009631c84a3710cc1f9177 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -714,5 +714,35 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent +@@ -717,5 +717,35 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent */ @NotNull org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason(); diff --git a/patches/api-unmapped/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch b/patches/api/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch similarity index 100% rename from patches/api-unmapped/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch rename to patches/api/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch diff --git a/patches/api-unmapped/0215-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/api/0215-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 91% rename from patches/api-unmapped/0215-Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/api/0215-Allow-delegation-to-vanilla-chunk-gen.patch index c270243b46..87622a4f16 100644 --- a/patches/api-unmapped/0215-Allow-delegation-to-vanilla-chunk-gen.patch +++ b/patches/api/0215-Allow-delegation-to-vanilla-chunk-gen.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Allow delegation to vanilla chunk gen diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 4cffbc4f665e267371e99094e8b7de975fffc223..a1e211653e05f3c9bc2ddf5aa1b69dea1c4bb61b 100644 +index 4eb60f2772c80f9917e88c40ed2214993709e443..26099f95d68540d4e6c54c32fd9699ff01660236 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1490,6 +1490,22 @@ public final class Bukkit { @@ -32,7 +32,7 @@ index 4cffbc4f665e267371e99094e8b7de975fffc223..a1e211653e05f3c9bc2ddf5aa1b69dea * Creates a boss bar instance to display to players. The progress * defaults to 1.0 diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 969cba46ba2790dde32724111ad77332c5872e0b..71538dfce294776b8f98046cbddde21dc9ae89e7 100644 +index 22495f576b05e3f0161bfd2c4ea5e5622fdb6302..864211431ebfe9bb333943c31892dfcbdeb33037 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1256,6 +1256,20 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @@ -57,7 +57,7 @@ index 969cba46ba2790dde32724111ad77332c5872e0b..71538dfce294776b8f98046cbddde21d * Creates a boss bar instance to display to players. The progress * defaults to 1.0 diff --git a/src/main/java/org/bukkit/generator/ChunkGenerator.java b/src/main/java/org/bukkit/generator/ChunkGenerator.java -index 7caef27682f22a77de283dd6f391ec8bc0b0312b..5ba77d40a38e5e592ee265e4fbd510043a0b4345 100644 +index 9d7592988a2fbcc70f889b0622adbef014054d00..244a8a93c35d5a84e17672ff745051587bca384c 100644 --- a/src/main/java/org/bukkit/generator/ChunkGenerator.java +++ b/src/main/java/org/bukkit/generator/ChunkGenerator.java @@ -227,6 +227,22 @@ public abstract class ChunkGenerator { diff --git a/patches/server-remapped/0517-Remove-some-streams-from-structures.patch b/patches/removed/1.17/0517-Remove-some-streams-from-structures.patch similarity index 98% rename from patches/server-remapped/0517-Remove-some-streams-from-structures.patch rename to patches/removed/1.17/0517-Remove-some-streams-from-structures.patch index 26f90fc29a..6587728a2f 100644 --- a/patches/server-remapped/0517-Remove-some-streams-from-structures.patch +++ b/patches/removed/1.17/0517-Remove-some-streams-from-structures.patch @@ -5,6 +5,7 @@ Subject: [PATCH] Remove some streams from structures This showed up a lot in the spark profiler, should have a low-medium performance improvement. +Update 1.17: looks like some things in here have been moved to some weird beardifier - has to be investigated further diff --git a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java index e842dbc586234799a05b6df213b686e17b8ed1ac..2f88e015708cadb43a348ba2b144c3dd92bb95a5 100644 --- a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java diff --git a/patches/server-remapped/0528-Fix-Concurrency-issue-in-WeightedList.patch b/patches/removed/1.17/0528-Fix-Concurrency-issue-in-WeightedList.patch similarity index 98% rename from patches/server-remapped/0528-Fix-Concurrency-issue-in-WeightedList.patch rename to patches/removed/1.17/0528-Fix-Concurrency-issue-in-WeightedList.patch index 7c0af04ac0..684716359f 100644 --- a/patches/server-remapped/0528-Fix-Concurrency-issue-in-WeightedList.patch +++ b/patches/removed/1.17/0528-Fix-Concurrency-issue-in-WeightedList.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 6 Jul 2020 18:36:41 -0400 Subject: [PATCH] Fix Concurrency issue in WeightedList - +1.17 Update: Looks like whatever this patch is trying to fix might be already fixed upstream, needs to be investigated if multiple threads from worldgen sort at same time, it will crash. So make a copy of the list for sorting purposes. diff --git a/patches/server-remapped/0516-Convert-legacy-attributes-in-Item-Meta.patch b/patches/server/0468-Convert-legacy-attributes-in-Item-Meta.patch similarity index 92% rename from patches/server-remapped/0516-Convert-legacy-attributes-in-Item-Meta.patch rename to patches/server/0468-Convert-legacy-attributes-in-Item-Meta.patch index 9306e47d2d..cf24e3253b 100644 --- a/patches/server-remapped/0516-Convert-legacy-attributes-in-Item-Meta.patch +++ b/patches/server/0468-Convert-legacy-attributes-in-Item-Meta.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Convert legacy attributes in Item Meta diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -index 2d547810125f00680ef7e60dd791d0bddd9ebd3e..320fd6780af2fa99e4e4f4193cbc9338d492dc6d 100644 +index 0520c45197629cbdc2777d9ae11eef572e793160..46c313d581b9af6aa0a48f97ae3cc800a88535f2 100644 --- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java @@ -11,6 +11,20 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; @@ -30,10 +30,10 @@ index 2d547810125f00680ef7e60dd791d0bddd9ebd3e..320fd6780af2fa99e4e4f4193cbc9338 public CraftAttributeMap(AttributeMap handle) { this.handle = handle; diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 45abfebf3f947dcbd2e7b1d95be8ba918f044e51..cb66998dbaa9d93e92ef4045b83efbb0fd486234 100644 +index 6252c3934d72b0d5e6809842bdd26d344cab98c6..daca454b375ab1d5900b6c3c9b6575463e47a3a9 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -480,7 +480,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -479,7 +479,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); diff --git a/patches/server-remapped/0518-Remove-streams-from-classes-related-villager-gossip.patch b/patches/server/0469-Remove-streams-from-classes-related-villager-gossip.patch similarity index 66% rename from patches/server-remapped/0518-Remove-streams-from-classes-related-villager-gossip.patch rename to patches/server/0469-Remove-streams-from-classes-related-villager-gossip.patch index a3582192b3..d24c65f437 100644 --- a/patches/server-remapped/0518-Remove-streams-from-classes-related-villager-gossip.patch +++ b/patches/server/0469-Remove-streams-from-classes-related-villager-gossip.patch @@ -5,18 +5,18 @@ Subject: [PATCH] Remove streams from classes related villager gossip diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -index 0204f05d989d45c0848f810d1953adf0992ce3c2..57832c392910d22aa81ac2b4816d043dd7ac867a 100644 +index e316f83a7adc7bba06a6a3fdab55cc9c004cb835..bd661bcaf5eb65a4f34eec268ced84894d7d0898 100644 --- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -@@ -9,6 +9,7 @@ import com.mojang.serialization.DynamicOps; +@@ -8,6 +8,7 @@ import com.mojang.serialization.Dynamic; + import com.mojang.serialization.DynamicOps; import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper import it.unimi.dsi.fastutil.objects.ObjectIterator; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; import java.util.Arrays; - import java.util.Collection; -@@ -51,8 +52,21 @@ public class GossipContainer { +@@ -60,8 +61,21 @@ public class GossipContainer { }); } @@ -34,40 +34,36 @@ index 0204f05d989d45c0848f810d1953adf0992ce3c2..57832c392910d22aa81ac2b4816d043d + // Paper end + private Collection selectGossipsForTransfer(Random random, int count) { -- List list = (List) this.unpack().collect(Collectors.toList()); +- List list = this.unpack().collect(Collectors.toList()); + List list = decompress(); // Paper - Remove streams from reputation - if (list.isEmpty()) { return Collections.emptyList(); -@@ -119,7 +133,7 @@ public class GossipContainer { + } else { +@@ -154,9 +168,9 @@ public class GossipContainer { + } - public Dynamic store(DynamicOps dynamicops) { -- return new Dynamic(dynamicops, dynamicops.createList(this.unpack().map((reputation_b) -> { +- public Dynamic store(DynamicOps dynamicOps) { +- return new Dynamic<>(dynamicOps, dynamicOps.createList(this.unpack().map((gossipEntry) -> { +- return gossipEntry.store(dynamicOps); ++ public Dynamic store(DynamicOps dynamicops) { + return new Dynamic(dynamicops, dynamicops.createList(this.decompress().stream().map((reputation_b) -> { - return reputation_b.store(dynamicops); ++ return reputation_b.store(dynamicops); }).map(Dynamic::getValue))); } -@@ -144,18 +158,30 @@ public class GossipContainer { - public static class EntityGossips { // Paper - make public - -- private final Object2IntMap entries; -+ private final Object2IntMap entries; private Object2IntMap getEntries() { return entries; } // Paper - OBFHELPER - - public EntityGossips() { // Paper - make public - update CraftVillager setReputation on change - this.entries = new Object2IntOpenHashMap(); - } +@@ -181,11 +195,23 @@ public class GossipContainer { + final Object2IntMap entries = new Object2IntOpenHashMap<>(); public int weightedValue(Predicate gossipTypeFilter) { - return this.entries.object2IntEntrySet().stream().filter((entry) -> { - return gossipTypeFilter.test(entry.getKey()); - }).mapToInt((entry) -> { -- return entry.getIntValue() * ((GossipType) entry.getKey()).weight; +- return entry.getIntValue() * (entry.getKey()).weight; - }).sum(); + // Paper start - Remove streams from reputation + int weight = 0; -+ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { ++ for (Object2IntMap.Entry entry : entries.object2IntEntrySet()) { + if (gossipTypeFilter.test(entry.getKey())) { + weight += entry.getIntValue() * entry.getKey().getWeight(); + } @@ -77,7 +73,7 @@ index 0204f05d989d45c0848f810d1953adf0992ce3c2..57832c392910d22aa81ac2b4816d043d + + public List decompress(UUID uuid) { + List list = new ObjectArrayList<>(); -+ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { ++ for (Object2IntMap.Entry entry : entries.object2IntEntrySet()) { + list.add(new GossipContainer.GossipEntry(uuid, entry.getKey(), entry.getIntValue())); + } + return list; @@ -86,12 +82,12 @@ index 0204f05d989d45c0848f810d1953adf0992ce3c2..57832c392910d22aa81ac2b4816d043d public Stream unpack(UUID target) { diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java -index 808eaaae5d534427d197c90c8e53494f4c3bfd82..c775d0df2a8f8a0fd32a8ffc26d6ea6978cbb595 100644 +index c82b26dd4a16d77b7ed06c2919082edd62a3dffc..ad1b49cfa201fe6e80b3cd0204f8ffaf6115c081 100644 --- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java +++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipType.java -@@ -11,7 +11,7 @@ public enum GossipType { - MAJOR_NEGATIVE("major_negative", -5, 100, 10, 10), MINOR_NEGATIVE("minor_negative", -1, 200, 20, 20), MINOR_POSITIVE("minor_positive", 1, 200, 1, 5), MAJOR_POSITIVE("major_positive", 5, 100, 0, 100), TRADING("trading", 1, 25, 2, 20); - +@@ -17,7 +17,7 @@ public enum GossipType { + public static final int REPUTATION_CHANGE_PER_EVERLASTING_MEMORY = 20; + public static final int REPUTATION_CHANGE_PER_TRADE = 2; public final String id; - public final int weight; + public final int weight; public int getWeight() { return weight; } // Paper - OBFHELPER diff --git a/patches/server-remapped/0519-Support-components-in-ItemMeta.patch b/patches/server/0470-Support-components-in-ItemMeta.patch similarity index 87% rename from patches/server-remapped/0519-Support-components-in-ItemMeta.patch rename to patches/server/0470-Support-components-in-ItemMeta.patch index 66bda208cc..e512d7a848 100644 --- a/patches/server-remapped/0519-Support-components-in-ItemMeta.patch +++ b/patches/server/0470-Support-components-in-ItemMeta.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Support components in ItemMeta diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index cb66998dbaa9d93e92ef4045b83efbb0fd486234..20e008277d1188fc7b31bfb2522ef9f6429cc3fb 100644 +index daca454b375ab1d5900b6c3c9b6575463e47a3a9..81738dac125a7247fff5e51fa595667ef25ba0a1 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -874,11 +874,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -873,11 +873,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { return CraftChatMessage.fromJSONComponent(displayName); } @@ -31,8 +31,8 @@ index cb66998dbaa9d93e92ef4045b83efbb0fd486234..20e008277d1188fc7b31bfb2522ef9f6 + // Paper end @Override public boolean hasDisplayName() { - return displayName != null; -@@ -1021,6 +1033,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return this.displayName != null; +@@ -1020,6 +1032,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { return this.lore == null ? null : new ArrayList(Lists.transform(this.lore, CraftChatMessage::fromJSONComponent)); } @@ -47,7 +47,7 @@ index cb66998dbaa9d93e92ef4045b83efbb0fd486234..20e008277d1188fc7b31bfb2522ef9f6 @Override public void setLore(List lore) { if (lore == null || lore.isEmpty()) { -@@ -1035,6 +1055,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -1034,6 +1054,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { } } @@ -68,8 +68,8 @@ index cb66998dbaa9d93e92ef4045b83efbb0fd486234..20e008277d1188fc7b31bfb2522ef9f6 + // Paper end @Override public boolean hasCustomModelData() { - return customModelData != null; -@@ -1496,6 +1531,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + return this.customModelData != null; +@@ -1494,6 +1529,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { } for (Object object : addFrom) { diff --git a/patches/server-remapped/0520-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/patches/server/0471-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch similarity index 66% rename from patches/server-remapped/0520-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch rename to patches/server/0471-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch index 52cd27053f..3130394c90 100644 --- a/patches/server-remapped/0520-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch +++ b/patches/server/0471-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch @@ -7,36 +7,36 @@ CraftBukkit has a bug in their implementation and is incorrectly handling forget Also adds more target reasons for why it forgot target. 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 738162a55eb186f66df4d31e017c9b9a7cc604c2..1b6f34c2a185368aac973e8a5316a03950e4314b 100644 +index 6ee0098de2b55a437f914869643adbd1ddbe7faf..00e0babb051b4fd2b9bc4a4129204c08f8ce5af0 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 -@@ -33,15 +33,15 @@ public class StopAttackingIfTargetInvalid extends Behavior { +@@ -50,15 +50,15 @@ public class StopAttackingIfTargetInvalid extends Behavior { + LivingEntity entityliving = this.getAttackTarget(entity); - protected void start(ServerLevel world, E entity, long time) { - if (isTiredOfTryingToReachTarget((LivingEntity) entity)) { + if (!entity.canAttack(entityliving)) { - this.clearAttackTarget(entity); -+ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // Paper ++ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper + } else if (StopAttackingIfTargetInvalid.isTiredOfTryingToReachTarget((LivingEntity) entity)) { +- this.clearAttackTarget(entity); ++ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // Paper } else if (this.isCurrentTargetDeadOrRemoved(entity)) { - this.clearAttackTarget(entity); -+ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_DIED); // Paper ++ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_DIED); // Paper } else if (this.isCurrentTargetInDifferentLevel(entity)) { - this.clearAttackTarget(entity); -+ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_OTHER_LEVEL); // Paper - } else if (!EntitySelector.ATTACK_ALLOWED.test(this.getAttackTarget(entity))) { -- this.clearAttackTarget(entity); -+ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper ++ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_OTHER_LEVEL); // Paper } else if (this.stopAttackingWhen.test(this.getAttackTarget(entity))) { - this.clearAttackTarget(entity); -+ this.d(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper ++ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper } } -@@ -65,18 +65,21 @@ public class StopAttackingIfTargetInvalid extends Behavior { +@@ -82,19 +82,21 @@ public class StopAttackingIfTargetInvalid extends Behavior { return optional.isPresent() && !((LivingEntity) optional.get()).isAlive(); } -- private void clearAttackTarget(E entity) { -+ private void d(E e0, EntityTargetEvent.TargetReason reason) { +- protected void clearAttackTarget(E entity) { ++ protected void clearAttackTarget(E e0, EntityTargetEvent.TargetReason reason) { // CraftBukkit start - LivingEntity old = entity.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); - EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); @@ -56,7 +56,8 @@ index 738162a55eb186f66df4d31e017c9b9a7cc604c2..1b6f34c2a185368aac973e8a5316a039 + }*/ + // Paper end // CraftBukkit end +- this.onTargetErased.accept(entity); - entity.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); -+ e0.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); ++ this.onTargetErased.accept(e0); } } diff --git a/patches/server-remapped/0521-Add-entity-liquid-API.patch b/patches/server/0472-Add-entity-liquid-API.patch similarity index 81% rename from patches/server-remapped/0521-Add-entity-liquid-API.patch rename to patches/server/0472-Add-entity-liquid-API.patch index 87da8f1dcb..572e26f912 100644 --- a/patches/server-remapped/0521-Add-entity-liquid-API.patch +++ b/patches/server/0472-Add-entity-liquid-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add entity liquid API diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index e9a658b11e2b6683831dc3f5bd20be9a7840ed69..aea2457510c75214bbb925307155611e981f115f 100644 +index 96da70f1077f70c4bd5ba1196292a856deb25286..8531f1deea95aa8e73e75b714426c915a52a74af 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1164,12 +1164,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1305,12 +1305,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n return this.wasTouchingWater; } @@ -23,7 +23,7 @@ index e9a658b11e2b6683831dc3f5bd20be9a7840ed69..aea2457510c75214bbb925307155611e private boolean isInBubbleColumn() { return this.level.getBlockState(this.blockPosition()).is(Blocks.BUBBLE_COLUMN); } -@@ -1183,6 +1184,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1324,6 +1325,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n return this.isInWater() || this.isInRain() || this.isInBubbleColumn(); } @@ -31,8 +31,8 @@ index e9a658b11e2b6683831dc3f5bd20be9a7840ed69..aea2457510c75214bbb925307155611e public boolean isInWaterOrBubble() { return this.isInWater() || this.isInBubbleColumn(); } -@@ -1325,6 +1327,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.fluidOnEyes == tag; +@@ -1463,6 +1465,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + return this.fluidOnEyes == fluidTag; } + public final boolean isInLava() { return isInLava(); } // Paper - OBFHELPER @@ -40,10 +40,10 @@ index e9a658b11e2b6683831dc3f5bd20be9a7840ed69..aea2457510c75214bbb925307155611e return !this.firstTick && this.fluidHeight.getDouble(FluidTags.LAVA) > 0.0D; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 76d652386806fd11961611486a1d0a12fe9616a4..deeae62e9926f9435907c68e7d35e7420f5e79dd 100644 +index 98d3818d38f487fc7e1302ee4af9e4898efec809..26bfbab1e8332f91c4d2814cd0056ca2ea7ddab7 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1135,5 +1135,29 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1169,5 +1169,29 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { return getHandle().spawnReason; } diff --git a/patches/server-remapped/0522-Update-itemstack-legacy-name-and-lore.patch b/patches/server/0473-Update-itemstack-legacy-name-and-lore.patch similarity index 70% rename from patches/server-remapped/0522-Update-itemstack-legacy-name-and-lore.patch rename to patches/server/0473-Update-itemstack-legacy-name-and-lore.patch index 1b999bcc30..02b04dfbf2 100644 --- a/patches/server-remapped/0522-Update-itemstack-legacy-name-and-lore.patch +++ b/patches/server/0473-Update-itemstack-legacy-name-and-lore.patch @@ -5,19 +5,11 @@ Subject: [PATCH] Update itemstack legacy name and lore diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 458cdfbeac9d757c9721acd4557a548affa0ede1..04b717326524f400da3562655c25db59e72814ec 100644 +index 10f55ba189d12c46e0ef38b0b96a29894b4fba93..c1667fa43194a17eeeb2ac9c5d57daf5cb131958 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -49,6 +49,7 @@ import net.minecraft.core.Registry; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.nbt.NbtOps; -+import net.minecraft.nbt.StringTag; - import net.minecraft.nbt.Tag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.ComponentUtils; -@@ -135,6 +136,44 @@ public final class ItemStack { - list.sort((Comparator) enchantSorter); // Paper +@@ -170,6 +170,44 @@ public final class ItemStack { + list.sort((Comparator) enchantSorter); // Paper } catch (Exception ignored) {} } + @@ -42,7 +34,7 @@ index 458cdfbeac9d757c9721acd4557a548affa0ede1..04b717326524f400da3562655c25db59 + try { + list.set(index, convert(json)); + } catch (JsonParseException e) { -+ list.set(index, StringTag.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(new TextComponent("")))); ++ list.set(index, net.minecraft.nbt.StringTag.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(new TextComponent("")))); + } + } + } @@ -50,26 +42,26 @@ index 458cdfbeac9d757c9721acd4557a548affa0ede1..04b717326524f400da3562655c25db59 + } + } + -+ private StringTag convert(String json) { ++ private net.minecraft.nbt.StringTag convert(String json) { + Component component = Component.Serializer.jsonToComponent(json); + if (component instanceof TextComponent && component.getContents().contains("\u00A7") && component.getSiblings().isEmpty()) { + // Only convert if the root component is a single comp with legacy in it, don't convert already normal components + component = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(component.getContents())[0]; + } -+ return StringTag.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(component)); ++ return net.minecraft.nbt.StringTag.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(component)); + } // Paper end public ItemStack(ItemLike item) { -@@ -180,6 +219,7 @@ public final class ItemStack { - // CraftBukkit start - make defensive copy as this data may be coming from the save thread +@@ -216,6 +254,7 @@ public final class ItemStack { this.tag = (CompoundTag) nbttagcompound.getCompound("tag").copy(); - processEnchantOrder(this.tag); // Paper -+ processText(); // Paper - this.getItem().verifyTagAfterLoad(this.tag); // CraftBukkit end + this.processEnchantOrder(this.tag); // Paper ++ this.processText(); // Paper + this.getItem().verifyTagAfterLoad(this.tag); } -@@ -663,6 +703,7 @@ public final class ItemStack { + +@@ -728,6 +767,7 @@ public final class ItemStack { } } diff --git a/patches/server-remapped/0523-Spawn-player-in-correct-world-on-login.patch b/patches/server/0474-Spawn-player-in-correct-world-on-login.patch similarity index 90% rename from patches/server-remapped/0523-Spawn-player-in-correct-world-on-login.patch rename to patches/server/0474-Spawn-player-in-correct-world-on-login.patch index 5ec61b9dae..2de440c5aa 100644 --- a/patches/server-remapped/0523-Spawn-player-in-correct-world-on-login.patch +++ b/patches/server/0474-Spawn-player-in-correct-world-on-login.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Spawn player in correct world on login diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 713cc88dd067c0d918f253b1845f42c0d9eb920f..f36c92e42300c2056075610caf63f8bef0e7edda 100644 +index 7eb3088d47ff78198e01a3a12b0ce6abe9d6ca6b..66735bbc2528c5812c9df14ef7cd91cb69d903b2 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -192,7 +192,18 @@ public abstract class PlayerList { +@@ -193,7 +193,18 @@ public abstract class PlayerList { }String lastKnownName = s; // Paper // CraftBukkit end diff --git a/patches/server-remapped/0524-Add-PrepareResultEvent.patch b/patches/server/0475-Add-PrepareResultEvent.patch similarity index 83% rename from patches/server-remapped/0524-Add-PrepareResultEvent.patch rename to patches/server/0475-Add-PrepareResultEvent.patch index be0c76ca05..53d3c6585c 100644 --- a/patches/server-remapped/0524-Add-PrepareResultEvent.patch +++ b/patches/server/0475-Add-PrepareResultEvent.patch @@ -8,10 +8,10 @@ Adds a new event for all crafting stations that generate a result slot item Anvil, Grindstone and Smithing now extend this event diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -index 72b0cfcc5aab03e14e63440c734436e9c1432111..bc39e7464646d712b085251dc0277a5b1ec0a393 100644 +index 92681e56cea92a4600ef268b21c1b56e15fe3a03..766c907f92ca8cb19b22cd19185cc92603aeca03 100644 --- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -141,6 +141,7 @@ public abstract class AbstractContainerMenu { +@@ -214,6 +214,7 @@ public abstract class AbstractContainerMenu { return nonnulllist; } @@ -20,22 +20,22 @@ index 72b0cfcc5aab03e14e63440c734436e9c1432111..bc39e7464646d712b085251dc0277a5b int i; diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java -index 3d53edae7e3d5bb00913384ad0eb67551a65750e..492a42ad5dc460717de8179d522d042cee11db60 100644 +index 1dad9577370bb58b27b32b997a505ce5145a6769..56d3ed1cdafd7904c35be5db568b9975a97418a7 100644 --- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java -@@ -307,6 +307,7 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -317,6 +317,7 @@ public class AnvilMenu extends ItemCombinerMenu { } this.createResult(); + org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper } - // CraftBukkit start + public int getCost() { diff --git a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java -index 6183e33237a231be388a8ace0ca3b56720db13ee..464f27d3f0cc694257a550cf873a0ee4534e2189 100644 +index 528fc4ee870303c6c42c603a9869f7e47825fd40..c96abb8945fe5dc2f963f548ccdd87272a445a7a 100644 --- a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java +++ b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java -@@ -146,6 +146,7 @@ public class CartographyTableMenu extends AbstractContainerMenu { +@@ -150,6 +150,7 @@ public class CartographyTableMenu extends AbstractContainerMenu { this.setupResultSlot(itemstack, itemstack1, itemstack2); } @@ -44,10 +44,10 @@ index 6183e33237a231be388a8ace0ca3b56720db13ee..464f27d3f0cc694257a550cf873a0ee4 private void setupResultSlot(ItemStack map, ItemStack item, ItemStack oldResult) { diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -index e9e830117fe3e4e02a51eef8671a3d3b48c2858e..329a6d70d53c13cd554c64996f2ddc489bdc1e94 100644 +index 34574f3945d2a7b4ab6a71adb2408b9811a3cb0d..b260216460b0bbf75edc631bb69e3e4fc94d459a 100644 --- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -@@ -156,6 +156,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { +@@ -160,6 +160,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { super.slotsChanged(inventory); if (inventory == this.repairSlots) { this.createResult(); @@ -56,10 +56,10 @@ index e9e830117fe3e4e02a51eef8671a3d3b48c2858e..329a6d70d53c13cd554c64996f2ddc48 } diff --git a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java -index d944cbcdf4d886d3b8b171edd8e2ac8a54dc19b9..8704c4dbead1ff661d84b751479babac5ebc5839 100644 +index 982b7ac02335bfa2b752d900a5d0392c6660745b..eb1a0c6ce8ceab4955a5ac3d2fdf4d869a2a34ae 100644 --- a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java +++ b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java -@@ -71,6 +71,7 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu { +@@ -78,6 +78,7 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu { super.slotsChanged(inventory); if (inventory == this.inputSlots) { this.createResult(); @@ -68,10 +68,10 @@ index d944cbcdf4d886d3b8b171edd8e2ac8a54dc19b9..8704c4dbead1ff661d84b751479babac } diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java -index b33daf92752841e46f2fd9fa20dc1cfa79aa423a..3460fb2bb1451b8456a7fe42449ec4dbce641f40 100644 +index 6d40ef2459e0ba5927ee723495cd6f5fd3101859..7e8b6e0e69876cb7bfd444a8dd72edf8289e6dd1 100644 --- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java +++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java -@@ -188,7 +188,8 @@ public class LoomMenu extends AbstractContainerMenu { +@@ -196,7 +196,8 @@ public class LoomMenu extends AbstractContainerMenu { } this.setupResultSlot(); @@ -80,12 +80,12 @@ index b33daf92752841e46f2fd9fa20dc1cfa79aa423a..3460fb2bb1451b8456a7fe42449ec4db + org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 3); // Paper } - @Override + public void registerUpdateListener(Runnable inventoryChangeListener) { diff --git a/src/main/java/net/minecraft/world/inventory/SmithingMenu.java b/src/main/java/net/minecraft/world/inventory/SmithingMenu.java -index befb2e6294c3d0a16ae4766c3804d04fd4e1bba5..44aa1f4f91ae9f84fc7ed38cc6b3c11f07d55ba1 100644 +index edb88d59a7b81b9d8b0328ce54ff1fbcf47323ae..c2b997bff39c8bf51c5f8f788696c92920b04868 100644 --- a/src/main/java/net/minecraft/world/inventory/SmithingMenu.java +++ b/src/main/java/net/minecraft/world/inventory/SmithingMenu.java -@@ -78,6 +78,7 @@ public class SmithingMenu extends ItemCombinerMenu { +@@ -76,6 +76,7 @@ public class SmithingMenu extends ItemCombinerMenu { // CraftBukkit end } @@ -94,10 +94,10 @@ index befb2e6294c3d0a16ae4766c3804d04fd4e1bba5..44aa1f4f91ae9f84fc7ed38cc6b3c11f @Override diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java -index febf7fa112c470888af171e585ab6a052abb46ca..072bac443e7c54ac2b92e1d93b757bdacf230fbb 100644 +index ddd34b07f7cf39a8b5ad51bdefb6e9d7cbf8f393..eac9765ecf0b33cab8b04204591de8d56c6f75c7 100644 --- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java -@@ -155,6 +155,7 @@ public class StonecutterMenu extends AbstractContainerMenu { +@@ -176,6 +176,7 @@ public class StonecutterMenu extends AbstractContainerMenu { this.setupRecipeList(inventory, itemstack); } @@ -106,10 +106,10 @@ index febf7fa112c470888af171e585ab6a052abb46ca..072bac443e7c54ac2b92e1d93b757bda private void setupRecipeList(Container input, ItemStack stack) { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 87fe7f4f5ed70bf1b3dc1e2a392ba42a1f8f568b..64cfa14aa4e32430a6970fd4f3654a56146ba807 100644 +index d4b8035160332d98c37918f62ee9e0d630e23ee8..fc9c63b73211d05321776648d6ba9c54f14ba83d 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1522,19 +1522,44 @@ public class CraftEventFactory { +@@ -1529,19 +1529,44 @@ public class CraftEventFactory { return event; } diff --git a/patches/server-remapped/0525-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/0476-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 64% rename from patches/server-remapped/0525-Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/server/0476-Allow-delegation-to-vanilla-chunk-gen.patch index 183e23a96c..3719bedef5 100644 --- a/patches/server-remapped/0525-Allow-delegation-to-vanilla-chunk-gen.patch +++ b/patches/server/0476-Allow-delegation-to-vanilla-chunk-gen.patch @@ -4,33 +4,11 @@ Date: Wed, 29 Apr 2020 02:10:32 +0200 Subject: [PATCH] Allow delegation to vanilla chunk gen -diff --git a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java -index aaa8d78b131c4095b36c6db6078f57f927c15374..54e560348836498f16dde017c6e7e3fcc263eeea 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java -+++ b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java -@@ -36,7 +36,7 @@ import org.apache.logging.log4j.Logger; - public class UpgradeData { - - private static final Logger LOGGER = LogManager.getLogger(); -- public static final UpgradeData EMPTY = new UpgradeData(); -+ public static final UpgradeData EMPTY = new UpgradeData(); public static UpgradeData getEmptyConverter() { return EMPTY; } // Paper - obfhelper - private static final Direction8[] DIRECTIONS = Direction8.values(); - private final EnumSet sides; - private final int[][] index; -@@ -322,7 +322,7 @@ public class UpgradeData { - if ((Integer) iblockdata.getValue(BlockStateProperties.DISTANCE) >= j) { - world.setBlock(blockposition, (BlockState) iblockdata.setValue(BlockStateProperties.DISTANCE, j), 18); - if (i != 7) { -- Direction[] aenumdirection = null.f; -+ Direction[] aenumdirection = DIRECTIONS; // Paper - decomp fix - int k = aenumdirection.length; - - for (int l = 0; l < k; ++l) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 2ec41cb87cec97780f1fa8abfbb756fca4dba1bf..e301aee53b19fc3f93a36d0ed03a649741123bfa 100644 +index 6bc5ba51c90723c7138b1b5d2381cb215f1e5271..df2c41d18377d8519d5537186d529ecc1901f58a 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2032,6 +2032,32 @@ public final class CraftServer implements Server { +@@ -2033,6 +2033,32 @@ public final class CraftServer implements Server { return new CraftChunkData(world); } @@ -64,20 +42,20 @@ index 2ec41cb87cec97780f1fa8abfbb756fca4dba1bf..e301aee53b19fc3f93a36d0ed03a6497 public BossBar createBossBar(String title, BarColor color, BarStyle style, BarFlag... flags) { return new CraftBossBar(title, color, style, flags); diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index 8d72cd6a44cf462cfe3adac9bf99a16883a587df..fd2cb2a584fea360fcf8180338708f35c4e3dc1f 100644 +index 7f8d9e82c1fadc0621f6e94adbc31f7774f9568f..2f0849dd05605e693dcc12c3d0842e8dfa53a869 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -19,7 +19,7 @@ import org.bukkit.material.MaterialData; - */ +@@ -20,7 +20,7 @@ import org.bukkit.material.MaterialData; public final class CraftChunkData implements ChunkGenerator.ChunkData { + private final int minHeight; private final int maxHeight; - private final LevelChunkSection[] sections; + private LevelChunkSection[] sections; // Paper - remove final private Set tiles; - private World world; // Paper - Anti-Xray - Add world -@@ -168,6 +168,12 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - return sections; + public CraftChunkData(World world) { +@@ -171,6 +171,12 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + return this.sections; } + // Paper start @@ -87,13 +65,13 @@ index 8d72cd6a44cf462cfe3adac9bf99a16883a587df..fd2cb2a584fea360fcf8180338708f35 + // Paper end + Set getTiles() { - return tiles; + return this.tiles; } diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -index eba3a6a2467116d93945ab2d5dc0a6f41d76f547..e25dc1c87752fcf73181cb02ddaf84b258ac4e9d 100644 +index e9502acf47b94e529f3ce273add9b7e0f4fe6d72..a4c3e307e861e6c220425d35fe228dcb9dc7ef31 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java +++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -@@ -32,7 +32,7 @@ import org.bukkit.generator.ChunkGenerator.ChunkData; +@@ -34,7 +34,7 @@ import org.bukkit.generator.ChunkGenerator.ChunkData; public class CustomChunkGenerator extends InternalChunkGenerator { diff --git a/patches/server-remapped/0526-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server/0477-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch similarity index 84% rename from patches/server-remapped/0526-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch rename to patches/server/0477-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch index 253148a7ee..f3eb70e20f 100644 --- a/patches/server-remapped/0526-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch +++ b/patches/server/0477-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 cec1e6105b8c2ac3d1482c00482d53d6be0d38d1..9724d4222311345a44aa101ec47523a1909fbe8f 100644 +index 3a83cbe8fb1a5bfc7e7b699686b92561bf0cdba0..8781b3ac40f214974ebb3e06c789f1717735d3a6 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3038,7 +3038,7 @@ public abstract class LivingEntity extends Entity { +@@ -3353,7 +3353,7 @@ public abstract class LivingEntity extends Entity { Entity entity = this.getVehicle(); super.stopRiding(suppressCancellation); // Paper - suppress diff --git a/patches/server-remapped/0527-Optimize-NetworkManager-Exception-Handling.patch b/patches/server/0478-Optimize-NetworkManager-Exception-Handling.patch similarity index 51% rename from patches/server-remapped/0527-Optimize-NetworkManager-Exception-Handling.patch rename to patches/server/0478-Optimize-NetworkManager-Exception-Handling.patch index dc51ae715d..7e00ab11c3 100644 --- a/patches/server-remapped/0527-Optimize-NetworkManager-Exception-Handling.patch +++ b/patches/server/0478-Optimize-NetworkManager-Exception-Handling.patch @@ -5,82 +5,44 @@ Subject: [PATCH] Optimize NetworkManager Exception Handling diff --git a/src/main/java/net/minecraft/network/ConnectionProtocol.java b/src/main/java/net/minecraft/network/ConnectionProtocol.java -index fca778d131aa10e88d5f7ed8d57eda6803318184..47a5ee9db64184f173af5984765e9b6d1a8ec367 100644 +index e722cf3a8e816b0c7405e6282591d9fa8d5bfa61..22d1758e52f56b39a2c110f123bdbf80898c4d92 100644 --- a/src/main/java/net/minecraft/network/ConnectionProtocol.java +++ b/src/main/java/net/minecraft/network/ConnectionProtocol.java -@@ -151,6 +151,7 @@ public enum ConnectionProtocol { +@@ -275,6 +275,7 @@ public enum ConnectionProtocol { @Nullable - public Packet createPacket(int id) { -+ if (id < 0 || id >= this.idToConstructor.size()) return null; // Paper - Supplier> supplier = (Supplier) this.idToConstructor.get(id); - - return supplier != null ? (Packet) supplier.get() : null; + public Packet createPacket(int id, FriendlyByteBuf buf) { ++ if (id < 0 || id >= this.idToDeserializer.size()) return null; // Paper + Function> function = this.idToDeserializer.get(id); + return function != null ? function.apply(buf) : null; + } diff --git a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java -index 8363b63f8dbd16948eeba3f912dc43605ad8db6a..fbebef6525a0872fecc081c7f63f27c1a04e11dc 100644 +index 5356f6484751e4b4740720aecac90bdfe044283b..ed54479b14dcfc736ac90749106557f0ff537550 100644 --- a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java +++ b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java -@@ -9,11 +9,21 @@ import java.util.List; +@@ -8,9 +8,20 @@ import io.netty.handler.codec.CorruptedFrameException; + import java.util.List; public class Varint21FrameDecoder extends ByteToMessageDecoder { - + private final byte[] lenBuf = new byte[3]; // Paper - public Varint21FrameDecoder() {} - - protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) { + // Paper start - if channel is not active just discard the packet -+ if (!channelhandlercontext.channel().isActive()) { -+ bytebuf.skipBytes(bytebuf.readableBytes()); ++ if (!channelHandlerContext.channel().isActive()) { ++ byteBuf.skipBytes(byteBuf.readableBytes()); + return; + } + // Paper end - bytebuf.markReaderIndex(); -- byte[] abyte = new byte[3]; + byteBuf.markReaderIndex(); + // Paper start - reuse temporary length buffer + byte[] abyte = lenBuf; + java.util.Arrays.fill(abyte, (byte) 0); + // Paper end + byte[] bs = new byte[3]; - for (int i = 0; i < abyte.length; ++i) { - if (!bytebuf.isReadable()) { -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index 22db5d0d2cc33498ca40162c66aa3b5fbf2f569f..3163502cb9bbbb5a00e7f06cf0032b1ad93c354d 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -2,8 +2,10 @@ package net.minecraft.network.protocol; - - import io.netty.channel.ChannelFuture; // Paper - import java.io.IOException; -+import net.minecraft.network.Connection; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.PacketListener; -+import net.minecraft.server.level.ServerPlayer; - - public interface Packet { - -@@ -18,17 +20,17 @@ public interface Packet { - /** - * @param player Null if not at PLAY stage yet - */ -- default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} -+ default void onPacketDispatch(@javax.annotation.Nullable ServerPlayer player) {} - - /** - * @param player Null if not at PLAY stage yet - * @param future Can be null if packet was cancelled - */ -- default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} -+ default void onPacketDispatchFinish(@javax.annotation.Nullable ServerPlayer player, @javax.annotation.Nullable ChannelFuture future) {} - default boolean hasFinishListener() { return false; } - default boolean isReady() { return true; } - default java.util.List getExtraPackets() { return null; } -- default boolean packetTooLarge(NetworkManager manager) { -+ default boolean packetTooLarge(Connection manager) { - return false; - } - // Paper end + for(int i = 0; i < bs.length; ++i) { diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -index 4ae8201d7dcffeb3298a4e593f978e15ffc5ac15..5812e518222e419da141ab0f70d1e7a3939a0df0 100644 +index 449f1b2f5dca350dc0912e14c8c2bf3eb4652b92..9e944aa41c184ebde1179399def662b2f08eef62 100644 --- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java +++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java @@ -1,6 +1,9 @@ @@ -93,7 +55,7 @@ index 4ae8201d7dcffeb3298a4e593f978e15ffc5ac15..5812e518222e419da141ab0f70d1e7a3 import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import co.aikar.timings.MinecraftTimings; // Paper -@@ -30,6 +33,21 @@ public class PacketUtils { +@@ -32,6 +35,21 @@ public class PacketUtils { try (Timing ignored = timing.startTiming()) { // Paper - timings packet.handle(listener); } // Paper - timings @@ -113,5 +75,5 @@ index 4ae8201d7dcffeb3298a4e593f978e15ffc5ac15..5812e518222e419da141ab0f70d1e7a3 + } + // Paper end } else { - PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); + PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: {}", packet); } diff --git a/patches/server-remapped/0529-Optimize-the-advancement-data-player-iteration-to-be.patch b/patches/server/0479-Optimize-the-advancement-data-player-iteration-to-be.patch similarity index 91% rename from patches/server-remapped/0529-Optimize-the-advancement-data-player-iteration-to-be.patch rename to patches/server/0479-Optimize-the-advancement-data-player-iteration-to-be.patch index a23f3a28c9..74142c996a 100644 --- a/patches/server-remapped/0529-Optimize-the-advancement-data-player-iteration-to-be.patch +++ b/patches/server/0479-Optimize-the-advancement-data-player-iteration-to-be.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Optimize the advancement data player iteration to be O(N) diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java -index 5ab62fc74085bbbb0c81b2f4d16a35c9345cd1f1..af8553f1b22e24fbeb732937fbbffc95cb9dfe90 100644 +index 3d82f984648605d58fae3c57f145d0da8a2ae225..ce02a467c1c3434f2cdb112ceb9794196069a820 100644 --- a/src/main/java/net/minecraft/server/PlayerAdvancements.java +++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java -@@ -457,6 +457,16 @@ public class PlayerAdvancements { +@@ -437,6 +437,16 @@ public class PlayerAdvancements { } private void ensureVisibility(Advancement advancement) { @@ -26,7 +26,7 @@ index 5ab62fc74085bbbb0c81b2f4d16a35c9345cd1f1..af8553f1b22e24fbeb732937fbbffc95 boolean flag = this.shouldBeVisible(advancement); boolean flag1 = this.visible.contains(advancement); -@@ -472,15 +482,23 @@ public class PlayerAdvancements { +@@ -452,15 +462,23 @@ public class PlayerAdvancements { } if (flag != flag1 && advancement.getParent() != null) { diff --git a/patches/server-remapped/0530-Fix-arrows-never-despawning-MC-125757.patch b/patches/server/0480-Fix-arrows-never-despawning-MC-125757.patch similarity index 87% rename from patches/server-remapped/0530-Fix-arrows-never-despawning-MC-125757.patch rename to patches/server/0480-Fix-arrows-never-despawning-MC-125757.patch index 677615b010..33bedb131a 100644 --- a/patches/server-remapped/0530-Fix-arrows-never-despawning-MC-125757.patch +++ b/patches/server/0480-Fix-arrows-never-despawning-MC-125757.patch @@ -9,10 +9,10 @@ instead of getting stuck in a never despawn state (bubble columns, etc). 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 6225f390b51733217a809910182f58acea1055e2..73df844610530bbfb133bd59d00015117b59b215 100644 +index 988986d549dae93cfcb8147126c84f263efe3452..b6b729424dfade696cdf7117fc2bdf0dba03485f 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -169,6 +169,7 @@ public abstract class AbstractArrow extends Projectile { +@@ -198,6 +198,7 @@ public abstract class AbstractArrow extends Projectile { ++this.inGroundTime; } else { @@ -20,7 +20,7 @@ index 6225f390b51733217a809910182f58acea1055e2..73df844610530bbfb133bd59d0001511 this.inGroundTime = 0; Vec3 vec3d2 = this.position(); -@@ -290,6 +291,7 @@ public abstract class AbstractArrow extends Projectile { +@@ -319,6 +320,7 @@ public abstract class AbstractArrow extends Projectile { } diff --git a/patches/server-remapped/0531-Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server/0481-Thread-Safe-Vanilla-Command-permission-checking.patch similarity index 85% rename from patches/server-remapped/0531-Thread-Safe-Vanilla-Command-permission-checking.patch rename to patches/server/0481-Thread-Safe-Vanilla-Command-permission-checking.patch index 41cf790265..a297a9a47f 100644 --- a/patches/server-remapped/0531-Thread-Safe-Vanilla-Command-permission-checking.patch +++ b/patches/server/0481-Thread-Safe-Vanilla-Command-permission-checking.patch @@ -9,7 +9,7 @@ to race conditions. Plus, .canUse we want to be safe for async anyways. diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -index 5c35cef42af4053332c02b4960c227fe95d4c197..757ed7a0887f4bdb187ca7c757db5c188362f1a0 100644 +index aa3a1795850a419f624f14bd7c4daab0020779d0..39708be1b445791b053023dec16ad7d4efcc9048 100644 --- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java +++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java @@ -74,10 +74,10 @@ public abstract class CommandNode implements Comparable> { @@ -18,7 +18,7 @@ index 5c35cef42af4053332c02b4960c227fe95d4c197..757ed7a0887f4bdb187ca7c757db5c18 try { - ((CommandSourceStack) source).currentCommand = this; + ((CommandSourceStack) source).currentCommand.set(this); // Paper - return requirement.test(source); + return this.requirement.test(source); } finally { - ((CommandSourceStack) source).currentCommand = null; + ((CommandSourceStack) source).currentCommand.set(null); // Paper @@ -26,7 +26,7 @@ index 5c35cef42af4053332c02b4960c227fe95d4c197..757ed7a0887f4bdb187ca7c757db5c18 } // CraftBukkit end diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java -index e1f4ffaa36bfffb7741c74b7a094e26a03a9a1e6..2c024f8f8b949dc8cebd29a10415eeac6d50902e 100644 +index 42d97bc67c8f4e5b65a81159179c43dc6edc804c..6a330170ec1ea9d06593a1bbd1bdb8d98c0904fb 100644 --- a/src/main/java/net/minecraft/commands/CommandSourceStack.java +++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java @@ -54,7 +54,7 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy @@ -38,7 +38,7 @@ index e1f4ffaa36bfffb7741c74b7a094e26a03a9a1e6..2c024f8f8b949dc8cebd29a10415eeac public CommandSourceStack(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String simpleName, Component name, MinecraftServer server, @Nullable Entity entity) { this(output, pos, rot, world, level, simpleName, name, server, entity, false, (commandcontext, flag, j) -> { -@@ -171,9 +171,11 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy +@@ -175,9 +175,11 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy @Override public boolean hasPermission(int level) { // CraftBukkit start @@ -46,7 +46,7 @@ index e1f4ffaa36bfffb7741c74b7a094e26a03a9a1e6..2c024f8f8b949dc8cebd29a10415eeac + // Paper start - fix concurrency issue + CommandNode currentCommand = this.currentCommand.get(); if (currentCommand != null) { - return hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); + return this.hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); + // Paper end } // CraftBukkit end diff --git a/patches/server-remapped/0532-Move-range-check-for-block-placing-up.patch b/patches/server/0482-Move-range-check-for-block-placing-up.patch similarity index 71% rename from patches/server-remapped/0532-Move-range-check-for-block-placing-up.patch rename to patches/server/0482-Move-range-check-for-block-placing-up.patch index 7fba765097..344b1912e1 100644 --- a/patches/server-remapped/0532-Move-range-check-for-block-placing-up.patch +++ b/patches/server/0482-Move-range-check-for-block-placing-up.patch @@ -5,28 +5,30 @@ Subject: [PATCH] Move range check for block placing up diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 773f2589c14e16d2f5b01a6dbd48e09d17d19c7e..d264fca2737f83a0860394f7bb6b269ffe669594 100644 +index 39777c2b1bbb12ce3e5be3724235ea0a8072cef8..99a16a2f0c2dc227dd45db1964c2d47ffdcda73e 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1661,15 +1661,19 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1693,17 +1693,21 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser BlockPos blockposition = movingobjectpositionblock.getBlockPos(); Direction enumdirection = movingobjectpositionblock.getDirection(); + // Paper start - move check up -+ Location eyeLoc = this.getPlayer().getEyeLocation(); ++ Location eyeLoc = this.getCraftPlayer().getEyeLocation(); + double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); -+ if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { ++ if (reachDistance > (this.getCraftPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { + return; + } + // Paper end - move check up + this.player.resetLastActionTime(); - if (blockposition.getY() < this.server.getMaxBuildHeight()) { + int i = this.player.level.getMaxBuildHeight(); + + if (blockposition.getY() < i) { if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition)) { // CraftBukkit start - Check if we can actually do something over this large a distance -- Location eyeLoc = this.getPlayer().getEyeLocation(); +- Location eyeLoc = this.getCraftPlayer().getEyeLocation(); - double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); -- if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { +- if (reachDistance > (this.getCraftPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? ServerGamePacketListenerImpl.CREATIVE_PLACE_DISTANCE_SQUARED : ServerGamePacketListenerImpl.SURVIVAL_PLACE_DISTANCE_SQUARED)) { - return; - } + // Paper - move check up From b7cdb5d6c4dc166497c84cbabd8e550c058c8a3b Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 03:18:42 -0700 Subject: [PATCH 110/226] fix issue in hopper patch --- patches/server/0349-Optimize-Hoppers.patch | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/patches/server/0349-Optimize-Hoppers.patch b/patches/server/0349-Optimize-Hoppers.patch index 1ec55ab1c3..e8c6dade14 100644 --- a/patches/server/0349-Optimize-Hoppers.patch +++ b/patches/server/0349-Optimize-Hoppers.patch @@ -117,7 +117,7 @@ index a05acf709735b40ca86f978508c63a86065fd405..71dd26ca6626631b94d53818cd06b93f double getLevelY(); 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 0ec16d554c2b51a64614c73783505c7b06ff02c7..86c0a477883102e4aebdab7ac28bf9f2ab2f7c48 100644 +index 0ec16d554c2b51a64614c73783505c7b06ff02c7..3b1442bf4c83650369e925d76f07dc67c6cbbc83 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 @@ -3,7 +3,6 @@ package net.minecraft.world.level.block.entity; @@ -145,11 +145,11 @@ index 0ec16d554c2b51a64614c73783505c7b06ff02c7..86c0a477883102e4aebdab7ac28bf9f2 + private static boolean skipPushModeEventFire = false; + public static boolean skipHopperEvents = false; + -+ private static boolean hopperPush(Level level, BlockPos pos, Container iinventory, Direction enumdirection, HopperBlockEntity hopper) { ++ private static boolean hopperPush(Level level, BlockPos pos, Container destination, Direction enumdirection, HopperBlockEntity hopper) { + skipPushModeEventFire = skipHopperEvents; + boolean foundItem = false; -+ for (int i = 0; i < iinventory.getContainerSize(); ++i) { -+ ItemStack item = iinventory.getItem(i); ++ for (int i = 0; i < hopper.getContainerSize(); ++i) { ++ ItemStack item = hopper.getItem(i); + if (!item.isEmpty()) { + foundItem = true; + ItemStack origItemStack = item; @@ -162,13 +162,13 @@ index 0ec16d554c2b51a64614c73783505c7b06ff02c7..86c0a477883102e4aebdab7ac28bf9f2 + // We only need to fire the event once to give protection plugins a chance to cancel this event + // Because nothing uses getItem, every event call should end up the same result. + if (!skipPushModeEventFire) { -+ itemstack = callPushMoveEvent(iinventory, itemstack, hopper); ++ itemstack = callPushMoveEvent(destination, itemstack, hopper); + if (itemstack == null) { // cancelled + origItemStack.setCount(origCount); + return false; + } + } -+ final ItemStack itemstack2 = addItem(hopper, iinventory, itemstack, enumdirection); ++ final ItemStack itemstack2 = addItem(hopper, destination, itemstack, enumdirection); + final int remaining = itemstack2.getCount(); + if (remaining != moved) { + origItemStack = origItemStack.cloneItemStack(true); @@ -177,7 +177,7 @@ index 0ec16d554c2b51a64614c73783505c7b06ff02c7..86c0a477883102e4aebdab7ac28bf9f2 + origItemStack.setCount(origCount - moved + remaining); + } + hopper.setItem(i, origItemStack); -+ iinventory.setChanged(); ++ destination.setChanged(); + return true; + } + origItemStack.setCount(origCount); @@ -300,7 +300,7 @@ index 0ec16d554c2b51a64614c73783505c7b06ff02c7..86c0a477883102e4aebdab7ac28bf9f2 if (HopperBlockEntity.isFullContainer(iinventory1, enumdirection)) { return false; } else { -+ return hopperPush(world, blockposition, iinventory, enumdirection, hopper); /* // Paper - disable rest ++ return hopperPush(world, blockposition, iinventory1, enumdirection, hopper); /* // Paper - disable rest for (int i = 0; i < iinventory.getContainerSize(); ++i) { if (!iinventory.getItem(i).isEmpty()) { ItemStack itemstack = iinventory.getItem(i).copy(); From 8ca5a642eff3a60b9cce8e991d8bfdfca4ed7b9d Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 14 Jun 2021 12:42:08 +0200 Subject: [PATCH 111/226] more work work work --- ...-Support-hex-colors-in-getLastColors.patch | 0 .../0217-Add-setMaxPlayers-API.patch | 4 +- .../0218-Add-moon-phase-API.patch | 2 +- ...yPickupItemAnimation-to-LivingEntity.patch | 0 .../0220-Add-BellRingEvent.patch | 0 .../0221-Brand-support.patch | 4 +- ...der-Remove-Streams-Optimized-collect.patch | 2 +- .../1.17}/0541-Import-fastutil-classes.patch | 2 +- ...ove-armour-stand-double-add-to-world.patch | 2 +- ...her-Boss-Bar-doesn-t-update-until-in.patch | 1 + .../1.17}/0549-Fix-MC-197271.patch | 2 +- .../0550-MC-197883-Bandaid-decode-issue.patch | 2 +- ...ataPlayer-leak-due-from-quitting-ear.patch | 94 ------------------- ...-Fix-MC-187716-Use-configured-height.patch | 45 --------- .../0483-Fix-SPIGOT-5989.patch} | 14 +-- ...-Bukkit-world-container-is-not-used.patch} | 6 +- ...5885-Unable-to-disable-advancements.patch} | 4 +- ...ataPlayer-leak-due-from-quitting-ear.patch | 82 ++++++++++++++++ ...eLighting-call-to-World-spigot-stri.patch} | 4 +- ...ix-some-rails-connecting-improperly.patch} | 41 ++++---- .../0489-Incremental-player-saving.patch} | 63 +++++++------ ...ll-chunk-sections-for-block-updates.patch} | 8 +- ...-Fix-MC-187716-Use-configured-height.patch | 51 ++++++++++ ...stake-in-CB-NBT-int-deserialization.patch} | 2 +- ...rver-load-chunks-from-newer-version.patch} | 21 +++-- .../0494-Brand-support.patch} | 27 +++--- .../0495-Add-setMaxPlayers-API.patch} | 12 +-- ...PickupItemAnimation-to-LivingEntity.patch} | 2 +- .../0497-Don-t-require-FACING-data.patch} | 2 +- ...eEvent-not-firing-for-all-use-cases.patch} | 14 +-- .../0499-Add-moon-phase-API.patch} | 6 +- ...headless-pistons-from-being-created.patch} | 12 +-- 32 files changed, 267 insertions(+), 264 deletions(-) rename patches/{api-unmapped => api}/0216-Support-hex-colors-in-getLastColors.patch (100%) rename patches/{api-unmapped => api}/0217-Add-setMaxPlayers-API.patch (88%) rename patches/{api-unmapped => api}/0218-Add-moon-phase-API.patch (94%) rename patches/{api-unmapped => api}/0219-Add-playPickupItemAnimation-to-LivingEntity.patch (100%) rename patches/{api-unmapped => api}/0220-Add-BellRingEvent.patch (100%) rename patches/{api-unmapped => api}/0221-Brand-support.patch (85%) rename patches/{server-remapped => removed/1.17}/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch (99%) rename patches/{server-remapped => removed/1.17}/0541-Import-fastutil-classes.patch (99%) rename patches/{server-remapped => removed/1.17}/0543-Remove-armour-stand-double-add-to-world.patch (98%) rename patches/{server-remapped => removed/1.17}/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch (95%) rename patches/{server-remapped => removed/1.17}/0549-Fix-MC-197271.patch (98%) rename patches/{server-remapped => removed/1.17}/0550-MC-197883-Bandaid-decode-issue.patch (96%) delete mode 100644 patches/server-remapped/0536-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch delete mode 100644 patches/server-remapped/0544-Fix-MC-187716-Use-configured-height.patch rename patches/{server-remapped/0533-Fix-SPIGOT-5989.patch => server/0483-Fix-SPIGOT-5989.patch} (87%) rename patches/{server-remapped/0534-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch => server/0484-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch} (87%) rename patches/{server-remapped/0535-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch => server/0485-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch} (85%) create mode 100644 patches/server/0486-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch rename patches/{server-remapped/0537-Add-missing-strikeLighting-call-to-World-spigot-stri.patch => server/0487-Add-missing-strikeLighting-call-to-World-spigot-stri.patch} (82%) rename patches/{server-remapped/0538-Fix-some-rails-connecting-improperly.patch => server/0488-Fix-some-rails-connecting-improperly.patch} (71%) rename patches/{server-remapped/0540-Incremental-player-saving.patch => server/0489-Incremental-player-saving.patch} (63%) rename patches/{server-remapped/0542-Don-t-mark-null-chunk-sections-for-block-updates.patch => server/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch} (79%) create mode 100644 patches/server/0491-Fix-MC-187716-Use-configured-height.patch rename patches/{server-remapped/0545-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch => server/0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch} (94%) rename patches/{server-remapped/0546-Do-not-let-the-server-load-chunks-from-newer-version.patch => server/0493-Do-not-let-the-server-load-chunks-from-newer-version.patch} (68%) rename patches/{server-remapped/0547-Brand-support.patch => server/0494-Brand-support.patch} (77%) rename patches/{server-remapped/0551-Add-setMaxPlayers-API.patch => server/0495-Add-setMaxPlayers-API.patch} (77%) rename patches/{server-remapped/0552-Add-playPickupItemAnimation-to-LivingEntity.patch => server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch} (90%) rename patches/{server-remapped/0553-Don-t-require-FACING-data.patch => server/0497-Don-t-require-FACING-data.patch} (94%) rename patches/{server-remapped/0554-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch => server/0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch} (81%) rename patches/{server-remapped/0555-Add-moon-phase-API.patch => server/0499-Add-moon-phase-API.patch} (78%) rename patches/{server-remapped/0556-Prevent-headless-pistons-from-being-created.patch => server/0500-Prevent-headless-pistons-from-being-created.patch} (87%) diff --git a/patches/api-unmapped/0216-Support-hex-colors-in-getLastColors.patch b/patches/api/0216-Support-hex-colors-in-getLastColors.patch similarity index 100% rename from patches/api-unmapped/0216-Support-hex-colors-in-getLastColors.patch rename to patches/api/0216-Support-hex-colors-in-getLastColors.patch diff --git a/patches/api-unmapped/0217-Add-setMaxPlayers-API.patch b/patches/api/0217-Add-setMaxPlayers-API.patch similarity index 88% rename from patches/api-unmapped/0217-Add-setMaxPlayers-API.patch rename to patches/api/0217-Add-setMaxPlayers-API.patch index 17b9d923f2..41c6954954 100644 --- a/patches/api-unmapped/0217-Add-setMaxPlayers-API.patch +++ b/patches/api/0217-Add-setMaxPlayers-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add #setMaxPlayers API diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 1eaf6aae1e13c48a7f911e523015cb9b8cca8638..6228d7eca85fba52296c8d63d32804f32af1b421 100644 +index 26099f95d68540d4e6c54c32fd9699ff01660236..af0cf1fe3db1efd39bc06a89216413fc4415b007 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -171,6 +171,17 @@ public final class Bukkit { @@ -27,7 +27,7 @@ index 1eaf6aae1e13c48a7f911e523015cb9b8cca8638..6228d7eca85fba52296c8d63d32804f3 * Get the game port that the server runs on. * diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 8ee02c3d6cc8751704e5993fecd05293714e492f..6237578b373002c009efde4fb4c1864f0bf4f19e 100644 +index 864211431ebfe9bb333943c31892dfcbdeb33037..64316a3bcba881f9366d9bf9e16b205e2b817707 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -144,6 +144,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api-unmapped/0218-Add-moon-phase-API.patch b/patches/api/0218-Add-moon-phase-API.patch similarity index 94% rename from patches/api-unmapped/0218-Add-moon-phase-API.patch rename to patches/api/0218-Add-moon-phase-API.patch index c9e9827954..364b9c106b 100644 --- a/patches/api-unmapped/0218-Add-moon-phase-API.patch +++ b/patches/api/0218-Add-moon-phase-API.patch @@ -47,7 +47,7 @@ index 0000000000000000000000000000000000000000..df05153397b42930cd53d37b30824c7e + } +} diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 6441d4e45e5d5f008f95233cdc34048b8be38592..e20d863d1308b470a294cb7ab022aac4b9a91f71 100644 +index 10c22809535b6151b45aa18a02b80b8f2e3e6dff..27d97cde0fb5f6d727656c291e34dc468200f0c0 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -70,6 +70,12 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad diff --git a/patches/api-unmapped/0219-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/api/0219-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from patches/api-unmapped/0219-Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/api/0219-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/patches/api-unmapped/0220-Add-BellRingEvent.patch b/patches/api/0220-Add-BellRingEvent.patch similarity index 100% rename from patches/api-unmapped/0220-Add-BellRingEvent.patch rename to patches/api/0220-Add-BellRingEvent.patch diff --git a/patches/api-unmapped/0221-Brand-support.patch b/patches/api/0221-Brand-support.patch similarity index 85% rename from patches/api-unmapped/0221-Brand-support.patch rename to patches/api/0221-Brand-support.patch index 2c6d0a6ab9..4e255c4f7b 100644 --- a/patches/api-unmapped/0221-Brand-support.patch +++ b/patches/api/0221-Brand-support.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Brand support diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 2530c811f52f51d6338900221b4681c952c1c752..828b2b0538d4f936bee57d9fca55774723e13970 100644 +index e53f641e11dc74c99e656e985caa7c5943fb53a4..6bc4f12e4ef35979c9d99273d14d7b31833d3f75 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -2044,6 +2044,16 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -2071,6 +2071,16 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM // Paper end } diff --git a/patches/server-remapped/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/patches/removed/1.17/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch similarity index 99% rename from patches/server-remapped/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch rename to patches/removed/1.17/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch index 7f15a77054..4d8b1d0357 100644 --- a/patches/server-remapped/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch +++ b/patches/removed/1.17/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Tue, 4 Aug 2020 22:24:15 +0200 Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections - +1.17 Update: Please do this k thx bb I utilized the IDE to convert streams to non streams code, so shouldn't be any risk of behavior change. Only did minor optimization of the generated code set to remove unnecessary things. diff --git a/patches/server-remapped/0541-Import-fastutil-classes.patch b/patches/removed/1.17/0541-Import-fastutil-classes.patch similarity index 99% rename from patches/server-remapped/0541-Import-fastutil-classes.patch rename to patches/removed/1.17/0541-Import-fastutil-classes.patch index 706c8236e3..0fd44a3e61 100644 --- a/patches/server-remapped/0541-Import-fastutil-classes.patch +++ b/patches/removed/1.17/0541-Import-fastutil-classes.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Wed, 12 Aug 2020 11:33:04 +0200 Subject: [PATCH] Import fastutil classes - +1.17: YEET diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java index 95e166aa63f42c675df645a56e313bdffc2e8663..05f7d4a3835536f26f741d54a0884bd43fc82967 100644 diff --git a/patches/server-remapped/0543-Remove-armour-stand-double-add-to-world.patch b/patches/removed/1.17/0543-Remove-armour-stand-double-add-to-world.patch similarity index 98% rename from patches/server-remapped/0543-Remove-armour-stand-double-add-to-world.patch rename to patches/removed/1.17/0543-Remove-armour-stand-double-add-to-world.patch index 8e11c05922..12731c058d 100644 --- a/patches/server-remapped/0543-Remove-armour-stand-double-add-to-world.patch +++ b/patches/removed/1.17/0543-Remove-armour-stand-double-add-to-world.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Fri, 14 Aug 2020 23:59:26 +0200 Subject: [PATCH] Remove armour stand double add to world - +1.17 Update: YEET (?) diff --git a/src/main/java/net/minecraft/world/item/ArmorStandItem.java b/src/main/java/net/minecraft/world/item/ArmorStandItem.java index a2dfcaac8a2a4a69e703de43be76d4fe369fd647..bed063497bb593683ea384605ae1a71a68f4fc1b 100644 diff --git a/patches/server-remapped/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch b/patches/removed/1.17/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch similarity index 95% rename from patches/server-remapped/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch rename to patches/removed/1.17/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch index d3257fe8be..aed77697a6 100644 --- a/patches/server-remapped/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch +++ b/patches/removed/1.17/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch @@ -2,6 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: jmp Date: Thu, 20 Aug 2020 19:24:13 -0700 Subject: [PATCH] Fix MC-99259 Wither Boss Bar doesn't update until +1.17 Update: This issue is marked as fixed on 1.17 - yeet! invulnerability period is over diff --git a/patches/server-remapped/0549-Fix-MC-197271.patch b/patches/removed/1.17/0549-Fix-MC-197271.patch similarity index 98% rename from patches/server-remapped/0549-Fix-MC-197271.patch rename to patches/removed/1.17/0549-Fix-MC-197271.patch index 14ad3b04d2..65a6ccce8d 100644 --- a/patches/server-remapped/0549-Fix-MC-197271.patch +++ b/patches/removed/1.17/0549-Fix-MC-197271.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: ishland Date: Sun, 23 Aug 2020 10:57:44 +0200 Subject: [PATCH] Fix MC-197271 - +Update 1.17: Fixed in openj9-0.23.0-m2 release This patch only fixes an issue for servers running OpenJ9. diff --git a/src/main/java/net/minecraft/data/BuiltinRegistries.java b/src/main/java/net/minecraft/data/BuiltinRegistries.java diff --git a/patches/server-remapped/0550-MC-197883-Bandaid-decode-issue.patch b/patches/removed/1.17/0550-MC-197883-Bandaid-decode-issue.patch similarity index 96% rename from patches/server-remapped/0550-MC-197883-Bandaid-decode-issue.patch rename to patches/removed/1.17/0550-MC-197883-Bandaid-decode-issue.patch index fd35ea34e4..b05b52883d 100644 --- a/patches/server-remapped/0550-MC-197883-Bandaid-decode-issue.patch +++ b/patches/removed/1.17/0550-MC-197883-Bandaid-decode-issue.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Fri, 21 Aug 2020 21:05:28 -0400 Subject: [PATCH] MC-197883: Bandaid decode issue - +1.17 Update: Marked as fixed in 1.17 on mojira, yeet Mojang has a mix of type and name in the data sets, but you can only use one. diff --git a/patches/server-remapped/0536-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/patches/server-remapped/0536-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch deleted file mode 100644 index 8ec38751cb..0000000000 --- a/patches/server-remapped/0536-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 13 Jul 2020 06:22:54 -0700 -Subject: [PATCH] Fix AdvancementDataPlayer leak due from quitting early in - login - -Move the criterion storage to the AdvancementDataPlayer object -itself, so the criterion object stores no references - and thus -needs no cleanup. - -diff --git a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java -index 31650e41b37e322d2e8a4d4a3deec95851e72675..a645c79af856d2484a4ce7aa2885a32358b9a480 100644 ---- a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java -+++ b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java -@@ -16,25 +16,25 @@ import net.minecraft.world.level.storage.loot.LootContext; - - public abstract class SimpleCriterionTrigger implements CriterionTrigger { - -- private final Map>> a = Maps.newIdentityHashMap(); -+ //private final Map>> a = Maps.newIdentityHashMap(); // Paper - moved into AdvancementDataPlayer to fix memory leak - - public SimpleCriterionTrigger() {} - - @Override - public final void a(PlayerAdvancements advancementdataplayer, CriterionTrigger.Listener criteriontrigger_a) { -- ((Set) this.a.computeIfAbsent(advancementdataplayer, (advancementdataplayer1) -> { -+ (advancementdataplayer.criterionData.computeIfAbsent(this, (advancementdataplayer1) -> { // Paper - fix AdvancementDataPlayer leak - return Sets.newHashSet(); - })).add(criteriontrigger_a); - } - - @Override - public final void b(PlayerAdvancements advancementdataplayer, CriterionTrigger.Listener criteriontrigger_a) { -- Set> set = (Set) this.a.get(advancementdataplayer); -+ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak - - if (set != null) { - set.remove(criteriontrigger_a); - if (set.isEmpty()) { -- this.a.remove(advancementdataplayer); -+ advancementdataplayer.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak - } - } - -@@ -42,7 +42,7 @@ public abstract class SimpleCriterionTrigger tester) { - PlayerAdvancements advancementdataplayer = player.getAdvancements(); -- Set> set = (Set) this.a.get(advancementdataplayer); -+ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak - - if (set != null && !set.isEmpty()) { - LootContext loottableinfo = EntityPredicate.createContext(player, player); -@@ -67,7 +67,7 @@ public abstract class SimpleCriterionTrigger> criterionData = Maps.newIdentityHashMap(); -+ // Paper end - fix advancement data player leakage -+ - public PlayerAdvancements(DataFixer datafixer, PlayerList playerlist, ServerAdvancementManager advancementdataworld, File file, ServerPlayer entityplayer) { - this.dataFixer = datafixer; - this.playerList = playerlist; diff --git a/patches/server-remapped/0544-Fix-MC-187716-Use-configured-height.patch b/patches/server-remapped/0544-Fix-MC-187716-Use-configured-height.patch deleted file mode 100644 index 1e2cd52d5b..0000000000 --- a/patches/server-remapped/0544-Fix-MC-187716-Use-configured-height.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 15 Aug 2020 08:04:49 -0500 -Subject: [PATCH] Fix MC-187716 Use configured height - - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java -index 3f297ef7bde4159c77681574966446a0eba03f25..ff17c76f341028dd6d17f4c1f13f442c2e404532 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java -@@ -44,7 +44,7 @@ public abstract class NetherCappedSurfaceBuilder extends SurfaceBuilder= 0; --k2) { -+ for (int k2 = height; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.set(k1, k2, l1); - BlockState iblockdata5 = chunk.getBlockState(blockposition_mutableblockposition); - int l2; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java -index 4d6c03048022442dea467e1d9d018f150adc62c7..f64671b7359fb71e8af578d48d0a3c211e315057 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java -@@ -34,7 +34,7 @@ public class NetherForestSurfaceBuilder extends SurfaceBuilder= 0; --k2) { -+ for (int k2 = height; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.set(k1, k2, l1); - BlockState iblockdata3 = surfaceBlocks.getTopMaterial(); - BlockState iblockdata4 = chunk.getBlockState(blockposition_mutableblockposition); -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java -index c1e0fd7813786bf1cc03b08b204007711575f144..b222890e7bdff2c1470841677a99d4423f9c9d7f 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java -@@ -36,7 +36,7 @@ public class NetherSurfaceBuilder extends SurfaceBuilder= 0; --k2) { -+ for (int k2 = height; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.set(k1, k2, l1); - BlockState iblockdata4 = chunk.getBlockState(blockposition_mutableblockposition); - diff --git a/patches/server-remapped/0533-Fix-SPIGOT-5989.patch b/patches/server/0483-Fix-SPIGOT-5989.patch similarity index 87% rename from patches/server-remapped/0533-Fix-SPIGOT-5989.patch rename to patches/server/0483-Fix-SPIGOT-5989.patch index 84a6a9da90..a31cd6ebb9 100644 --- a/patches/server-remapped/0533-Fix-SPIGOT-5989.patch +++ b/patches/server/0483-Fix-SPIGOT-5989.patch @@ -10,10 +10,10 @@ This fixes that by checking if the modified spawn location is still at a respawn anchor. diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index f36c92e42300c2056075610caf63f8bef0e7edda..882cd25c9610f0b995c27291aa62846922ab531f 100644 +index 66735bbc2528c5812c9df14ef7cd91cb69d903b2..9c594c0f142ca10b7c1df50faf45ccb3f7468ba9 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -84,6 +84,7 @@ import net.minecraft.world.level.GameType; +@@ -77,6 +77,7 @@ import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.BiomeManager; import net.minecraft.world.level.block.Blocks; @@ -21,7 +21,7 @@ index f36c92e42300c2056075610caf63f8bef0e7edda..882cd25c9610f0b995c27291aa628469 import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.border.BorderChangeListener; import net.minecraft.world.level.border.WorldBorder; -@@ -846,6 +847,7 @@ public abstract class PlayerList { +@@ -821,6 +822,7 @@ public abstract class PlayerList { // Paper start boolean isBedSpawn = false; boolean isRespawn = false; @@ -29,7 +29,7 @@ index f36c92e42300c2056075610caf63f8bef0e7edda..882cd25c9610f0b995c27291aa628469 // Paper end // CraftBukkit start - fire PlayerRespawnEvent -@@ -856,7 +858,7 @@ public abstract class PlayerList { +@@ -831,7 +833,7 @@ public abstract class PlayerList { Optional optional; if (blockposition != null) { @@ -38,7 +38,7 @@ index f36c92e42300c2056075610caf63f8bef0e7edda..882cd25c9610f0b995c27291aa628469 } else { optional = Optional.empty(); } -@@ -899,7 +901,12 @@ public abstract class PlayerList { +@@ -874,7 +876,12 @@ public abstract class PlayerList { } // Spigot End @@ -52,7 +52,7 @@ index f36c92e42300c2056075610caf63f8bef0e7edda..882cd25c9610f0b995c27291aa628469 if (!flag) entityplayer.reset(); // SPIGOT-4785 isRespawn = true; // Paper } else { -@@ -937,8 +944,12 @@ public abstract class PlayerList { +@@ -911,8 +918,12 @@ public abstract class PlayerList { } // entityplayer1.syncInventory(); entityplayer1.setHealth(entityplayer1.getHealth()); @@ -66,4 +66,4 @@ index f36c92e42300c2056075610caf63f8bef0e7edda..882cd25c9610f0b995c27291aa628469 + // Paper end } // Added from changeDimension - sendAllPlayerInfo(entityplayer); // Update health, etc... + this.sendAllPlayerInfo(entityplayer); // Update health, etc... diff --git a/patches/server-remapped/0534-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/patches/server/0484-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch similarity index 87% rename from patches/server-remapped/0534-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch rename to patches/server/0484-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch index 52bb1345ae..057ecc45bd 100644 --- a/patches/server-remapped/0534-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch +++ b/patches/server/0484-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix SPIGOT-5824 Bukkit world-container is not used diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 855b3b4c90d84d4efa8395a76010b4b194591cbc..4e353432281a6dbbb49eaa4a6cb4eb051d1a08c5 100644 +index 7ce854edba32ffcafaa5268d4bb2822a5233e40b..3d6e09a3f028e50c08cbbb6b426f5b044c7b9e67 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java -@@ -124,11 +124,20 @@ public class Main { +@@ -129,11 +129,20 @@ public class Main { return; } @@ -29,5 +29,5 @@ index 855b3b4c90d84d4efa8395a76010b4b194591cbc..4e353432281a6dbbb49eaa4a6cb4eb05 - GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName())); + GameProfileCache usercache = new GameProfileCache(gameprofilerepository, userCacheFile); // Paper - only move usercache.json into folder if --universe is used, not world-container // CraftBukkit start - String s = (String) Optional.ofNullable(optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); + String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath()); diff --git a/patches/server-remapped/0535-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/patches/server/0485-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch similarity index 85% rename from patches/server-remapped/0535-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch rename to patches/server/0485-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch index fb2e14a9d3..6de50899f7 100644 --- a/patches/server-remapped/0535-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch +++ b/patches/server/0485-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix SPIGOT-5885 Unable to disable advancements diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 4e353432281a6dbbb49eaa4a6cb4eb051d1a08c5..9dc9a5e6ad7f23c8bf3553c765ceeecd67a49ac1 100644 +index 3d6e09a3f028e50c08cbbb6b426f5b044c7b9e67..ea136b9ad3a2a07076e12b8656c68f63aa4718c8 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java -@@ -124,6 +124,7 @@ public class Main { +@@ -129,6 +129,7 @@ public class Main { return; } diff --git a/patches/server/0486-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/patches/server/0486-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch new file mode 100644 index 0000000000..0711bd7fa0 --- /dev/null +++ b/patches/server/0486-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 13 Jul 2020 06:22:54 -0700 +Subject: [PATCH] Fix AdvancementDataPlayer leak due from quitting early in + login + +Move the criterion storage to the AdvancementDataPlayer object +itself, so the criterion object stores no references - and thus +needs no cleanup. + +diff --git a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java +index 584f48aba7bfec07a75b5a37da4ba7439610543c..c25c1cfca010ed625b6faf310be2edeccd6667bc 100644 +--- a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java ++++ b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java +@@ -14,22 +14,24 @@ import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.level.storage.loot.LootContext; + + public abstract class SimpleCriterionTrigger implements CriterionTrigger { +- private final Map>> players = Maps.newIdentityHashMap(); ++ //private final Map>> players = Maps.newIdentityHashMap(); // Paper - moved into AdvancementDataPlayer to fix memory leak ++ ++ public SimpleCriterionTrigger() {} + + @Override + public final void addPlayerListener(PlayerAdvancements manager, CriterionTrigger.Listener conditions) { +- this.players.computeIfAbsent(manager, (managerx) -> { ++ manager.criterionData.computeIfAbsent(this, (managerx) -> { // Paper - fix AdvancementDataPlayer leak + return Sets.newHashSet(); + }).add(conditions); + } + + @Override + public final void removePlayerListener(PlayerAdvancements manager, CriterionTrigger.Listener conditions) { +- Set> set = this.players.get(manager); ++ Set> set = (Set) manager.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak + if (set != null) { + set.remove(conditions); + if (set.isEmpty()) { +- this.players.remove(manager); ++ manager.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak + } + } + +@@ -37,7 +39,7 @@ public abstract class SimpleCriterionTrigger tester) { + PlayerAdvancements playerAdvancements = player.getAdvancements(); +- Set> set = this.players.get(playerAdvancements); ++ Set> set = (Set) playerAdvancements.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak + if (set != null && !set.isEmpty()) { + LootContext lootContext = EntityPredicate.createContext(player, player); + List> list = null; +diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index ce02a467c1c3434f2cdb112ceb9794196069a820..e05e5710c81b7dbb648afbfe16f843e7ae310752 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -39,6 +39,7 @@ import net.minecraft.advancements.Criterion; + import net.minecraft.advancements.CriterionProgress; + import net.minecraft.advancements.CriterionTrigger; + import net.minecraft.advancements.CriterionTriggerInstance; ++import net.minecraft.advancements.critereon.SimpleCriterionTrigger; + import net.minecraft.network.chat.ChatType; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.game.ClientboundSelectAdvancementsTabPacket; +@@ -70,6 +71,8 @@ public class PlayerAdvancements { + private Advancement lastSelectedTab; + private boolean isFirstPacket = true; + ++ public final Map> criterionData = Maps.newIdentityHashMap(); // Paper - fix advancement data player leakage ++ + public PlayerAdvancements(DataFixer dataFixer, PlayerList playerManager, ServerAdvancementManager advancementLoader, File advancementFile, ServerPlayer owner) { + this.dataFixer = dataFixer; + this.playerList = playerManager; diff --git a/patches/server-remapped/0537-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/patches/server/0487-Add-missing-strikeLighting-call-to-World-spigot-stri.patch similarity index 82% rename from patches/server-remapped/0537-Add-missing-strikeLighting-call-to-World-spigot-stri.patch rename to patches/server/0487-Add-missing-strikeLighting-call-to-World-spigot-stri.patch index 468888ab9b..9449b0adec 100644 --- a/patches/server-remapped/0537-Add-missing-strikeLighting-call-to-World-spigot-stri.patch +++ b/patches/server/0487-Add-missing-strikeLighting-call-to-World-spigot-stri.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add missing strikeLighting call to diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 4436b3d23dc8f33925da1ec539ea16307e0785b9..793b1309528671ce822d5a484ff9e40d6eba4e9d 100644 +index f72471ac82907a0d5112598b3289689495285944..d79a711d4080ad8acb2c240870be9d99a0b84cea 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2609,6 +2609,7 @@ public class CraftWorld implements World { +@@ -2623,6 +2623,7 @@ public class CraftWorld implements World { lightning.moveTo( loc.getX(), loc.getY(), loc.getZ() ); lightning.visualOnly = true; lightning.isSilent = isSilent; diff --git a/patches/server-remapped/0538-Fix-some-rails-connecting-improperly.patch b/patches/server/0488-Fix-some-rails-connecting-improperly.patch similarity index 71% rename from patches/server-remapped/0538-Fix-some-rails-connecting-improperly.patch rename to patches/server/0488-Fix-some-rails-connecting-improperly.patch index a1593c3e27..39dfbdd227 100644 --- a/patches/server-remapped/0538-Fix-some-rails-connecting-improperly.patch +++ b/patches/server/0488-Fix-some-rails-connecting-improperly.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix some rails connecting improperly diff --git a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java -index 1a44c8b41928a83a22b53d1b6f45ce39b4caf2b2..7cef6d1fc2045c62d4e96a0fd0a311d089cb1406 100644 +index 41c23abf78c2ca95c26633860adb9360139b3ceb..1242eb55996bca8a63bd7b95d01d0299fb36d105 100644 --- a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java -@@ -62,6 +62,7 @@ public abstract class BaseRailBlock extends Block { +@@ -65,6 +65,7 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl state = this.updateDir(world, pos, state, true); if (this.isStraight) { state.neighborChanged(world, pos, this, pos, notify); @@ -17,7 +17,7 @@ index 1a44c8b41928a83a22b53d1b6f45ce39b4caf2b2..7cef6d1fc2045c62d4e96a0fd0a311d0 return state; diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java -index 0ab1e15d8575c3e90a10b80b94030e15a01faac9..1854809e045300e84a713dc7c3a8264f53ec6c0f 100644 +index 2335e7af6bc16a0d65c7818c316f3194c680c69d..63c7f2cf530ac9562960ae5a3cbc6e511a009377 100644 --- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java @@ -70,6 +70,7 @@ public class DetectorRailBlock extends BaseRailBlock { @@ -27,15 +27,15 @@ index 0ab1e15d8575c3e90a10b80b94030e15a01faac9..1854809e045300e84a713dc7c3a8264f + if (state.getBlock() != this) { return; } // Paper - not our block, don't do anything boolean flag = (Boolean) state.getValue(DetectorRailBlock.POWERED); boolean flag1 = false; - List list = this.getInteractingMinecartOfType(world, pos, AbstractMinecart.class, (Predicate) null); + List list = this.getInteractingMinecartOfType(world, pos, AbstractMinecart.class, (entity) -> { diff --git a/src/main/java/net/minecraft/world/level/block/RailState.java b/src/main/java/net/minecraft/world/level/block/RailState.java -index 0d824ab98dcdd6ea9dac025c37970fb4ec464131..4c17bec369fb19f47760e30b391b2128cee6b276 100644 +index a205e04bce8706302e4a077646749d05dee98251..0f24187dc3f1340d142f88cbac64c4f5c333e5b8 100644 --- a/src/main/java/net/minecraft/world/level/block/RailState.java +++ b/src/main/java/net/minecraft/world/level/block/RailState.java -@@ -12,13 +12,19 @@ import net.minecraft.world.level.block.state.properties.RailShape; +@@ -10,13 +10,19 @@ import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.block.state.properties.RailShape; public class RailState { - - private final Level level; - private final BlockPos pos; + private final Level level; public final Level getWorld() { return this.level; } // Paper - OBFHELPER @@ -55,7 +55,7 @@ index 0d824ab98dcdd6ea9dac025c37970fb4ec464131..4c17bec369fb19f47760e30b391b2128 public RailState(Level world, BlockPos pos, BlockState state) { this.level = world; this.pos = pos; -@@ -153,6 +159,11 @@ public class RailState { +@@ -143,6 +149,11 @@ public class RailState { } private void connectTo(RailState placementHelper) { @@ -65,10 +65,10 @@ index 0d824ab98dcdd6ea9dac025c37970fb4ec464131..4c17bec369fb19f47760e30b391b2128 + } + // Paper end - prevent desync this.connections.add(placementHelper.pos); - BlockPos blockposition = this.pos.north(); - BlockPos blockposition1 = this.pos.south(); -@@ -347,11 +358,16 @@ public class RailState { - this.state = (BlockState) this.state.setValue(this.block.getShapeProperty(), blockpropertytrackposition1); + BlockPos blockPos = this.pos.north(); + BlockPos blockPos2 = this.pos.south(); +@@ -333,10 +344,15 @@ public class RailState { + this.state = this.state.setValue(this.block.getShapeProperty(), railShape2); if (forceUpdate || this.level.getBlockState(this.pos) != this.state) { this.level.setBlock(this.pos, this.state, 3); + // Paper start - prevent desync @@ -77,15 +77,14 @@ index 0d824ab98dcdd6ea9dac025c37970fb4ec464131..4c17bec369fb19f47760e30b391b2128 + } + // Paper end - prevent desync - for (int i = 0; i < this.connections.size(); ++i) { - RailState minecarttracklogic = this.getRail((BlockPos) this.connections.get(i)); - -- if (minecarttracklogic != null) { -+ if (minecarttracklogic != null && minecarttracklogic.isValid()) { // Paper - prevent desync - minecarttracklogic.removeSoftConnections(); - if (minecarttracklogic.canConnectTo(this)) { - minecarttracklogic.connectTo(this); -@@ -364,6 +380,6 @@ public class RailState { + for(int i = 0; i < this.connections.size(); ++i) { + RailState railState = this.getRail(this.connections.get(i)); +- if (railState != null) { ++ if (railState != null && railState.isValid()) { // Paper - prevent desync + railState.removeSoftConnections(); + if (railState.canConnectTo(this)) { + railState.connectTo(this); +@@ -349,6 +365,6 @@ public class RailState { } public BlockState getState() { diff --git a/patches/server-remapped/0540-Incremental-player-saving.patch b/patches/server/0489-Incremental-player-saving.patch similarity index 63% rename from patches/server-remapped/0540-Incremental-player-saving.patch rename to patches/server/0489-Incremental-player-saving.patch index cd7713a510..dae7e913d7 100644 --- a/patches/server-remapped/0540-Incremental-player-saving.patch +++ b/patches/server/0489-Incremental-player-saving.patch @@ -25,44 +25,52 @@ index b67ba8f75e4a3358d7c2462918b85b0bf9b5a922..fdbd8b89bb8bf3b61f60b812b90483c9 + } } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 19544b794b5a46c129016172798ff7294fcfed33..735c3c983e96e4e6f36de0975909fc48cb042081 100644 +index 1feda8b44364c748497174944b26abc4f058f354..1889de77a5e3d9371005b6bd451e2c0e57e96a93 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1347,9 +1347,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down - //MinecraftServer.LOGGER.debug("Autosave started"); // Paper - serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper -+ // Paper start -+ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate; -+ if (playerSaveInterval < 0) { -+ playerSaveInterval = autosavePeriod; -+ } -+ // Paper end - this.profiler.push("save"); -- if (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0) { // Paper +@@ -955,7 +955,6 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { // Paper + this.playerList.removeAll(this.isRestarting); // Paper + try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets + } +@@ -1415,9 +1414,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % this.autosavePeriod == 0) { // CraftBukkit // Paper - move down + // MinecraftServer.LOGGER.debug("Autosave started"); // Paper + serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper ++ // Paper start ++ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate; ++ if (playerSaveInterval < 0) { ++ playerSaveInterval = autosavePeriod; ++ } ++ // Paper end + this.profiler.push("save"); +- if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // Paper - moved from above +- this.playerList.saveAll(); ++ if (playerSaveInterval > 0) { // Paper + this.playerList.savePlayers(playerSaveInterval); // Paper - }// Paper - // Paper start - for (ServerLevel world : getAllLevels()) { + // this.saveAllChunks(true, false, false); // Paper - saved incrementally below + } // Paper start + for (ServerLevel level : this.getAllLevels()) { diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index c5717f45a0110492aad41f21cc06fb8cbeb1f791..bd4d4ace35e966e819aa461d3962fe06ff402be7 100644 +index cd34b5aa61c78d8138500a93f0a9714bedd7ed86..b49fa995973f860a95d937c98e2821435262ce25 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -173,6 +173,7 @@ import org.bukkit.inventory.MainHand; - public class ServerPlayer extends Player implements ContainerListener { +@@ -169,6 +169,7 @@ public class ServerPlayer extends Player { + public final int getViewDistance() { return this.getLevel().getChunkSource().chunkMap.viewDistance - 1; } // Paper - placeholder private static final Logger LOGGER = LogManager.getLogger(); + public long lastSave = MinecraftServer.currentTick; // Paper + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; public ServerGamePacketListenerImpl connection; - public Connection networkManager; // Paper - public final MinecraftServer server; diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 882cd25c9610f0b995c27291aa62846922ab531f..b76735531ef96f9d4c870a5107feea01524a7670 100644 +index 9c594c0f142ca10b7c1df50faf45ccb3f7468ba9..8c62367888af566dd9be4bb5cd301c26e0248e46 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -559,6 +559,7 @@ public abstract class PlayerList { +@@ -561,6 +561,7 @@ public abstract class PlayerList { protected void save(ServerPlayer player) { if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit if (!player.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) @@ -70,20 +78,21 @@ index 882cd25c9610f0b995c27291aa62846922ab531f..b76735531ef96f9d4c870a5107feea01 this.playerIo.save(player); ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit -@@ -1218,10 +1219,21 @@ public abstract class PlayerList { +@@ -1198,10 +1199,21 @@ public abstract class PlayerList { } public void saveAll() { +- net.minecraft.server.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main + // Paper start - incremental player saving + savePlayers(null); + } + public void savePlayers(Integer interval) { - MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main ++ MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main MinecraftTimings.savePlayers.startTiming(); // Paper + int numSaved = 0; + long now = MinecraftServer.currentTick; for (int i = 0; i < this.players.size(); ++i) { -- this.save((ServerPlayer) this.players.get(i)); +- this.save(this.players.get(i)); + ServerPlayer entityplayer = this.players.get(i); + if (interval == null || now - entityplayer.lastSave >= interval) { + this.save(entityplayer); diff --git a/patches/server-remapped/0542-Don-t-mark-null-chunk-sections-for-block-updates.patch b/patches/server/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch similarity index 79% rename from patches/server-remapped/0542-Don-t-mark-null-chunk-sections-for-block-updates.patch rename to patches/server/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch index 3a19fd93b1..0d7df8df12 100644 --- a/patches/server-remapped/0542-Don-t-mark-null-chunk-sections-for-block-updates.patch +++ b/patches/server/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch @@ -5,13 +5,13 @@ Subject: [PATCH] Don't mark null chunk sections for block updates diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 9e3629884709126574a52ad44fe7523f01dbcce9..82205ad13ef0e987bd83979d06331545efe0a60a 100644 +index 1f67c9c5f7161ea687983e7ae0ec7d259da9acd3..32bcc55ce15d832e2182d89acecd715947b1667d 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -449,6 +449,7 @@ public class ChunkHolder { - this.broadcastBlockEntityIfNeeded(world, blockposition, iblockdata); +@@ -315,6 +315,7 @@ public class ChunkHolder { + this.a(world, blockposition, iblockdata); } else { - LevelChunkSection chunksection = chunk.getSections()[sectionposition.getY()]; + LevelChunkSection chunksection = chunk.getSections()[j]; + if (chunksection == null) chunksection = new LevelChunkSection(sectionposition.getY(), chunk, world, true); // Paper - make a new chunk section if none was found ClientboundSectionBlocksUpdatePacket packetplayoutmultiblockchange = new ClientboundSectionBlocksUpdatePacket(sectionposition, shortset, chunksection, this.resendLight); diff --git a/patches/server/0491-Fix-MC-187716-Use-configured-height.patch b/patches/server/0491-Fix-MC-187716-Use-configured-height.patch new file mode 100644 index 0000000000..678b0ee0bc --- /dev/null +++ b/patches/server/0491-Fix-MC-187716-Use-configured-height.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 15 Aug 2020 08:04:49 -0500 +Subject: [PATCH] Fix MC-187716 Use configured height + + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java +index 5ad6e0ef718a1775a2310925b8273120687230b1..88fbd8a925d84184116051082514ef4d45c98acf 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java +@@ -1,4 +1,5 @@ + package net.minecraft.world.level.levelgen.surfacebuilders; ++<<<<<<< found + + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableMap; +@@ -42,7 +43,7 @@ public abstract class NetherCappedSurfaceBuilder extends SurfaceBuilder= i; --p) { ++ for(int p = height; p >= i; --p) { // Paper - fix MC-187716 - use configured height + mutableBlockPos.set(k, p, m); + BlockState blockState4 = chunk.getBlockState(mutableBlockPos); + if (blockState3.is(defaultBlock.getBlock()) && (blockState4.isAir() || blockState4 == defaultFluid)) { +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java +index fbb756504609285d96e01c4079be06561f75331e..aa6be90ac272c7e1186d177768230b7f52371e68 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherForestSurfaceBuilder.java +@@ -34,7 +34,7 @@ public class NetherForestSurfaceBuilder extends SurfaceBuilder= i; --p) { ++ for(int p = height; p >= i; --p) { // Paper - fix MC-187716 - use configured height + mutableBlockPos.set(k, p, m); + BlockState blockState2 = surfaceBuilderBaseConfiguration.getTopMaterial(); + BlockState blockState3 = chunk.getBlockState(mutableBlockPos); +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java +index 0cdb3a1ca76375fc69d1709cdd34d4176a99a617..206f74305a01604892ff98ece0c8344cc5582d14 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java +@@ -36,7 +36,7 @@ public class NetherSurfaceBuilder extends SurfaceBuilder= i; --p) { ++ for(int p = height; p >= i; --p) { // Paper - fix MC-187716 - use configured height + mutableBlockPos.set(k, p, m); + BlockState blockState3 = chunk.getBlockState(mutableBlockPos); + if (blockState3.isAir()) { diff --git a/patches/server-remapped/0545-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/patches/server/0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch similarity index 94% rename from patches/server-remapped/0545-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch rename to patches/server/0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch index c7a761474b..be48fd5ae2 100644 --- a/patches/server-remapped/0545-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch +++ b/patches/server/0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch @@ -13,7 +13,7 @@ This commit forces numbers to be present prior to the ending "i" letter. diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -index 94d46bc56b3bc4c4750fcfb1732eea0e49a04195..8ec09ff3b5aae4267b753bd715f0a9d4ef0381bd 100644 +index a7f4054002bd176fccf8357e9a23de66dd9e0dc5..207e4302161b3abe2ade56c9dc9c31820010fa42 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java @@ -19,7 +19,7 @@ import net.minecraft.nbt.TagParser; diff --git a/patches/server-remapped/0546-Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server/0493-Do-not-let-the-server-load-chunks-from-newer-version.patch similarity index 68% rename from patches/server-remapped/0546-Do-not-let-the-server-load-chunks-from-newer-version.patch rename to patches/server/0493-Do-not-let-the-server-load-chunks-from-newer-version.patch index d47ebc8c6e..f0ecafa556 100644 --- a/patches/server-remapped/0546-Do-not-let-the-server-load-chunks-from-newer-version.patch +++ b/patches/server/0493-Do-not-let-the-server-load-chunks-from-newer-version.patch @@ -9,25 +9,26 @@ the game, immediately stop the server to prevent data corruption. You can override this functionality at your own peril. diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 0adf14af9841cd3a20a8b2c0c320eb06794ef261..f6a814f9305813eaafa56baa0327e0111cd4e38c 100644 +index b4246524dd11ad1e1dc94c56eee966c5a54d9ecc..fad795c67829f89b21d78e822c7b15f2ea560184 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -95,10 +95,24 @@ public class ChunkSerializer { +@@ -98,10 +98,25 @@ public class ChunkSerializer { + holder.tasks.forEach(Runnable::run); return holder.protoChunk; } - ++ + // Paper start + private static final int CURRENT_DATA_VERSION = SharedConstants.getCurrentVersion().getWorldVersion(); + private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion"); + // Paper end + - public static InProgressChunkHolder loadChunk(ServerLevel worldserver, StructureManager definedstructuremanager, PoiManager villageplace, ChunkPos chunkcoordintpair, CompoundTag nbttagcompound, boolean distinguish) { - ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); + public static InProgressChunkHolder loadChunk(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt, boolean distinguish) { + java.util.ArrayDeque tasksToExecuteOnMain = new java.util.ArrayDeque<>(); // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); + // Paper start - Do NOT attempt to load chunks saved with newer versions -+ if (nbttagcompound.contains("DataVersion", 99)) { -+ int dataVersion = nbttagcompound.getInt("DataVersion"); ++ if (nbt.contains("DataVersion", 99)) { ++ int dataVersion = nbt.getInt("DataVersion"); + if (!JUST_CORRUPT_IT && dataVersion > CURRENT_DATA_VERSION) { + new RuntimeException("Server attempted to load chunk saved with newer version of minecraft! " + dataVersion + " > " + CURRENT_DATA_VERSION).printStackTrace(); + System.exit(1); @@ -35,5 +36,5 @@ index 0adf14af9841cd3a20a8b2c0c320eb06794ef261..f6a814f9305813eaafa56baa0327e011 + } + // Paper end BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); - CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate - ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate + CompoundTag nbttagcompound1 = nbt.getCompound("Level"); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate + ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate diff --git a/patches/server-remapped/0547-Brand-support.patch b/patches/server/0494-Brand-support.patch similarity index 77% rename from patches/server-remapped/0547-Brand-support.patch rename to patches/server/0494-Brand-support.patch index e134b27182..4ce0bb26ce 100644 --- a/patches/server-remapped/0547-Brand-support.patch +++ b/patches/server/0494-Brand-support.patch @@ -5,18 +5,18 @@ Subject: [PATCH] Brand support diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index d264fca2737f83a0860394f7bb6b269ffe669594..ab6494f5a872bba5398bef0367b4d9257786f61e 100644 +index 99a16a2f0c2dc227dd45db1964c2d47ffdcda73e..0176b85a031b33cb2a12bb75079f5e3111f4f2b7 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -5,6 +5,7 @@ import com.google.common.primitives.Doubles; +@@ -4,6 +4,7 @@ import com.google.common.collect.Lists; import com.google.common.primitives.Floats; import com.mojang.brigadier.ParseResults; import com.mojang.brigadier.StringReader; +import io.netty.buffer.Unpooled; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; - import it.unimi.dsi.fastutil.ints.Int2ShortMap; -@@ -37,6 +38,7 @@ import net.minecraft.nbt.ListTag; + import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry; +@@ -38,6 +39,7 @@ import net.minecraft.nbt.ListTag; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; import net.minecraft.network.Connection; @@ -24,7 +24,7 @@ index d264fca2737f83a0860394f7bb6b269ffe669594..ab6494f5a872bba5398bef0367b4d925 import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; -@@ -258,6 +260,8 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -259,6 +261,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit @@ -33,7 +33,7 @@ index d264fca2737f83a0860394f7bb6b269ffe669594..ab6494f5a872bba5398bef0367b4d925 public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { this.server = server; this.connection = connection; -@@ -2998,6 +3002,8 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -3000,6 +3004,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register"); private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister"); @@ -42,24 +42,23 @@ index d264fca2737f83a0860394f7bb6b269ffe669594..ab6494f5a872bba5398bef0367b4d925 @Override public void handleCustomPayload(ServerboundCustomPayloadPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); -@@ -3025,6 +3031,16 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -3027,6 +3033,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser try { byte[] data = new byte[packet.data.readableBytes()]; packet.data.readBytes(data); -+ + // Paper start - Brand support + if (packet.identifier.equals(MINECRAFT_BRAND)) { + try { -+ this.clientBrandName = new FriendlyByteBuf(Unpooled.copiedBuffer(data)).readUTF(256); ++ this.clientBrandName = new FriendlyByteBuf(Unpooled.copiedBuffer(data)).readUtf(256); + } catch (StringIndexOutOfBoundsException ex) { + this.clientBrandName = "illegal"; + } + } + // Paper end - craftServer.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packet.identifier.toString(), data); + this.cserver.getMessenger().dispatchIncomingMessage(this.player.getBukkitEntity(), packet.identifier.toString(), data); } catch (Exception ex) { ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); -@@ -3034,6 +3050,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -3036,6 +3051,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } @@ -73,10 +72,10 @@ index d264fca2737f83a0860394f7bb6b269ffe669594..ab6494f5a872bba5398bef0367b4d925 return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 610eabd2e93f9efccee810c3b5a314bc3cc649d8..7aae63d22167dc1b3ec7e8bc8672855c2038007e 100644 +index 0a6d6ea67eaf8b2a59ec45fb3ffb85096f509997..b277c87c0834ddcefcfaebd85c9e69d8d389b59e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2385,6 +2385,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2386,6 +2386,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Paper end }; @@ -89,4 +88,4 @@ index 610eabd2e93f9efccee810c3b5a314bc3cc649d8..7aae63d22167dc1b3ec7e8bc8672855c + public Player.Spigot spigot() { - return spigot; + return this.spigot; diff --git a/patches/server-remapped/0551-Add-setMaxPlayers-API.patch b/patches/server/0495-Add-setMaxPlayers-API.patch similarity index 77% rename from patches/server-remapped/0551-Add-setMaxPlayers-API.patch rename to patches/server/0495-Add-setMaxPlayers-API.patch index bfd99ce60a..92e26244b5 100644 --- a/patches/server-remapped/0551-Add-setMaxPlayers-API.patch +++ b/patches/server/0495-Add-setMaxPlayers-API.patch @@ -5,24 +5,24 @@ Subject: [PATCH] Add #setMaxPlayers API diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index b76735531ef96f9d4c870a5107feea01524a7670..7e44c911f4abc5c7d0e89513bf2cfc3516f13492 100644 +index 8c62367888af566dd9be4bb5cd301c26e0248e46..2f73f1f770e5e1fa422bec9c27e5bd10e86b7538 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -141,7 +141,7 @@ public abstract class PlayerList { +@@ -142,7 +142,7 @@ public abstract class PlayerList { public final PlayerDataStorage playerIo; private boolean doWhiteList; private final RegistryAccess.RegistryHolder registryHolder; - protected final int maxPlayers; + protected int maxPlayers; public final void setMaxPlayers(int maxPlayers) { this.maxPlayers = maxPlayers; } // Paper - remove final and add setter private int viewDistance; - private GameType overrideGameMode; private boolean allowCheatsForAllPlayers; + private static final boolean ALLOW_LOGOUTIVATOR = false; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e301aee53b19fc3f93a36d0ed03a649741123bfa..e599be15af17e5e45d2b694c30140cc4a787a7f5 100644 +index df2c41d18377d8519d5537186d529ecc1901f58a..74de169828d7e1e55d15546eb637a87268610700 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -613,6 +613,13 @@ public final class CraftServer implements Server { - return playerList.getMaxPlayers(); +@@ -616,6 +616,13 @@ public final class CraftServer implements Server { + return this.playerList.getMaxPlayers(); } + // Paper start diff --git a/patches/server-remapped/0552-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 90% rename from patches/server-remapped/0552-Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch index e3089f12ce..59a5584131 100644 --- a/patches/server-remapped/0552-Add-playPickupItemAnimation-to-LivingEntity.patch +++ b/patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add playPickupItemAnimation to LivingEntity diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 067eaf1e05ced344eb168431403f3fe786eafddf..eb136af0f99f5d7520ceabb98cefd5a01122872c 100644 +index a7a6757b83c94a0c0926097021015815f8f18b8e..c01eae70fe12970e9f617bf14e542b33572bcf4c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -806,5 +806,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { diff --git a/patches/server-remapped/0553-Don-t-require-FACING-data.patch b/patches/server/0497-Don-t-require-FACING-data.patch similarity index 94% rename from patches/server-remapped/0553-Don-t-require-FACING-data.patch rename to patches/server/0497-Don-t-require-FACING-data.patch index 5ecdef5062..ca355d45a1 100644 --- a/patches/server-remapped/0553-Don-t-require-FACING-data.patch +++ b/patches/server/0497-Don-t-require-FACING-data.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Don't require FACING data diff --git a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -index f7e60cdfa0b3f5970a897b5d52aaa72210f2fa57..ab8e69f9fc38012844ce01bd0cc5be8de2fcf4ab 100644 +index 0c286d7254f653bc855b1cb329fa76e3c1669b3c..05c0f0049421bc897f8e722331e30a6756ebbeea 100644 --- a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java @@ -14,20 +14,22 @@ import org.bukkit.event.block.BlockDispenseEvent; diff --git a/patches/server-remapped/0554-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server/0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch similarity index 81% rename from patches/server-remapped/0554-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch rename to patches/server/0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch index 7947c73149..f5f54e1c8c 100644 --- a/patches/server-remapped/0554-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch +++ b/patches/server/0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch @@ -5,17 +5,17 @@ Subject: [PATCH] Fix SpawnChangeEvent not firing for all use-cases diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 61aee2c109614a014149ae5a15ad2a28c796cb9d..22266fda4de9b5fbace3b8e55ce390b8d7e75a65 100644 +index bdabcdb60dbfb803ead13c42c8dd5e100b37dc00..4ae56444d258cdf44a02256315d6aae84e2f53be 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1981,12 +1981,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1679,12 +1679,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } // Paper end + public final void setSpawn(BlockPos blockposition, float f) { this.setDefaultSpawnPos(blockposition, f); } // Paper - OBFHELPER public void setDefaultSpawnPos(BlockPos pos, float angle) { // Paper - configurable spawn radius - BlockPos prevSpawn = this.getSpawn(); + BlockPos prevSpawn = this.getSharedSpawnPos(); //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); this.levelData.setSpawn(pos, angle); @@ -24,20 +24,20 @@ index 61aee2c109614a014149ae5a15ad2a28c796cb9d..22266fda4de9b5fbace3b8e55ce390b8 // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 793b1309528671ce822d5a484ff9e40d6eba4e9d..37513a1774f5a6611338c1b90018b974238ddbf6 100644 +index d79a711d4080ad8acb2c240870be9d99a0b84cea..4ca674fac0e1ed354a0c49284c21ca2b117dd852 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -371,11 +371,13 @@ public class CraftWorld implements World { +@@ -386,11 +386,13 @@ public class CraftWorld implements World { public boolean setSpawnLocation(int x, int y, int z, float angle) { try { - Location previousLocation = getSpawnLocation(); + Location previousLocation = this.getSpawnLocation(); - world.levelData.setSpawn(new BlockPos(x, y, z), angle); + world.setSpawn(new BlockPos(x, y, z), angle); // Paper - use WorldServer#setSpawn + // Paper start - move to nms.World // Notify anyone who's listening. - SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); -- server.getPluginManager().callEvent(event); +- this.server.getPluginManager().callEvent(event); + // SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); + // server.getPluginManager().callEvent(event); + // Paper end diff --git a/patches/server-remapped/0555-Add-moon-phase-API.patch b/patches/server/0499-Add-moon-phase-API.patch similarity index 78% rename from patches/server-remapped/0555-Add-moon-phase-API.patch rename to patches/server/0499-Add-moon-phase-API.patch index bd3ee0c1e2..e6c06c4be3 100644 --- a/patches/server-remapped/0555-Add-moon-phase-API.patch +++ b/patches/server/0499-Add-moon-phase-API.patch @@ -5,12 +5,12 @@ Subject: [PATCH] Add moon phase API diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 37513a1774f5a6611338c1b90018b974238ddbf6..28bf53bc9fca21f57cd4851adf508d833ecdd33b 100644 +index 4ca674fac0e1ed354a0c49284c21ca2b117dd852..d0b2de0f0a37554eb812aa8c7c20f1067807dc40 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -310,6 +310,11 @@ public class CraftWorld implements World { +@@ -325,6 +325,11 @@ public class CraftWorld implements World { public int getPlayerCount() { - return world.players.size(); + return world.players().size(); } + + @Override diff --git a/patches/server-remapped/0556-Prevent-headless-pistons-from-being-created.patch b/patches/server/0500-Prevent-headless-pistons-from-being-created.patch similarity index 87% rename from patches/server-remapped/0556-Prevent-headless-pistons-from-being-created.patch rename to patches/server/0500-Prevent-headless-pistons-from-being-created.patch index 15edeb8af6..a8508e9361 100644 --- a/patches/server-remapped/0556-Prevent-headless-pistons-from-being-created.patch +++ b/patches/server/0500-Prevent-headless-pistons-from-being-created.patch @@ -23,7 +23,7 @@ index fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb..faa1b775e45563b93ac1d5b904938b1f public static int maxPlayerAutoSavePerTick = 10; private static void playerAutoSaveRate() { diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 0f0a5fa2be5a7c69291b593a04cad83e069ba5b1..f7ca5294fe571770e3b0036e92563c5a099f76b1 100644 +index a12af10e28f2d023ba6f916b5e7a53539416713f..822a8dbfaea0a312c4eb2849f2386ecd401b13e9 100644 --- a/src/main/java/net/minecraft/world/level/Explosion.java +++ b/src/main/java/net/minecraft/world/level/Explosion.java @@ -15,6 +15,7 @@ import java.util.Random; @@ -41,11 +41,11 @@ index 0f0a5fa2be5a7c69291b593a04cad83e069ba5b1..f7ca5294fe571770e3b0036e92563c5a +import net.minecraft.world.level.block.piston.PistonHeadBlock; +import net.minecraft.world.level.block.piston.PistonMovingBlockEntity; import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.material.FluidState; - import net.minecraft.world.level.storage.loot.LootContext; -@@ -161,6 +164,15 @@ public class Explosion { +@@ -189,6 +192,15 @@ public class Explosion { - if (f > 0.0F && this.damageCalculator.a(this, this.level, blockposition, iblockdata, f) && blockposition.getY() < 256 && blockposition.getY() >= 0) { // CraftBukkit - don't wrap explosions + if (f > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, blockposition, iblockdata, f) && blockposition.getY() < 256 && blockposition.getY() >= 0) { // CraftBukkit - don't wrap explosions set.add(blockposition); + // Paper start - prevent headless pistons from forming + if (!com.destroystokyo.paper.PaperConfig.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) { @@ -60,10 +60,10 @@ index 0f0a5fa2be5a7c69291b593a04cad83e069ba5b1..f7ca5294fe571770e3b0036e92563c5a d4 += d0 * 0.30000001192092896D; diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -index 001e90da8b09e16b6df4849a5bac4f4821000c94..81f3c6fb7bab9de364537d3f3b2ea0f32795e5f1 100644 +index 87bedba9ab495edcce289c6665271d92b7165944..985f1112963c3b644a88788a6b4f8a9bd5f5c11a 100644 --- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -@@ -65,6 +65,8 @@ public class PistonMovingBlockEntity extends BlockEntity implements TickableBloc +@@ -66,6 +66,8 @@ public class PistonMovingBlockEntity extends BlockEntity { return this.direction; } From cfb17666fff3c983da846604682847f891ceb84a Mon Sep 17 00:00:00 2001 From: Josh Roy <10731363+JRoy@users.noreply.github.com> Date: Mon, 14 Jun 2021 06:45:16 -0700 Subject: [PATCH 112/226] even MOAR progress --- .../0222-Add-more-Evoker-API.patch | 0 ...-translation-keys-for-blocks-entitie.patch | 10 +-- ...ate-HoverEvent-from-ItemStack-Entity.patch | 6 +- .../0557-Add-BellRingEvent.patch | 58 ---------------- .../0564-Add-more-Evoker-API.patch | 57 --------------- patches/server/0501-Add-BellRingEvent.patch | 28 ++++++++ ...dd-zombie-targets-turtle-egg-config.patch} | 16 +++-- .../0503-Buffer-joins-to-world.patch} | 29 +++----- .../0504-Optimize-redstone-algorithm.patch} | 69 +++++++------------ ...s-not-working-in-some-kick-messages.patch} | 18 ++--- ...reateEvent-needs-to-know-its-entity.patch} | 47 +++++++------ .../0507-Fix-CraftTeam-null-check.patch} | 4 +- patches/server/0508-Add-more-Evoker-API.patch | 35 ++++++++++ ...translation-keys-for-blocks-entitie.patch} | 47 +++---------- 14 files changed, 156 insertions(+), 268 deletions(-) rename patches/{api-unmapped => api}/0222-Add-more-Evoker-API.patch (100%) rename patches/{api-unmapped => api}/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch (92%) rename patches/{api-unmapped => api}/0224-Create-HoverEvent-from-ItemStack-Entity.patch (95%) delete mode 100644 patches/server-remapped/0557-Add-BellRingEvent.patch delete mode 100644 patches/server-remapped/0564-Add-more-Evoker-API.patch create mode 100644 patches/server/0501-Add-BellRingEvent.patch rename patches/{server-remapped/0558-Add-zombie-targets-turtle-egg-config.patch => server/0502-Add-zombie-targets-turtle-egg-config.patch} (74%) rename patches/{server-remapped/0559-Buffer-joins-to-world.patch => server/0503-Buffer-joins-to-world.patch} (66%) rename patches/{server-remapped/0560-Optimize-redstone-algorithm.patch => server/0504-Optimize-redstone-algorithm.patch} (94%) rename patches/{server-remapped/0561-Fix-hex-colors-not-working-in-some-kick-messages.patch => server/0505-Fix-hex-colors-not-working-in-some-kick-messages.patch} (82%) rename patches/{server-remapped/0562-PortalCreateEvent-needs-to-know-its-entity.patch => server/0506-PortalCreateEvent-needs-to-know-its-entity.patch} (80%) rename patches/{server-remapped/0563-Fix-CraftTeam-null-check.patch => server/0507-Fix-CraftTeam-null-check.patch} (84%) create mode 100644 patches/server/0508-Add-more-Evoker-API.patch rename patches/{server-remapped/0565-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch => server/0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch} (65%) diff --git a/patches/api-unmapped/0222-Add-more-Evoker-API.patch b/patches/api/0222-Add-more-Evoker-API.patch similarity index 100% rename from patches/api-unmapped/0222-Add-more-Evoker-API.patch rename to patches/api/0222-Add-more-Evoker-API.patch diff --git a/patches/api-unmapped/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/api/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 92% rename from patches/api-unmapped/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to patches/api/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch index bfa151e84b..5e9876ef43 100644 --- a/patches/api-unmapped/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch +++ b/patches/api/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 0000000000000000000000>>>>>>> replacement000000000000000000 Mon Sep 17 00:00:00 2001 From: MeFisto94 Date: Tue, 11 Aug 2020 19:17:46 +0200 Subject: [PATCH] Add a way to get translation keys for blocks, entities and @@ -6,10 +6,10 @@ Subject: [PATCH] Add a way to get translation keys for blocks, entities and diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 9c28351c7c3f60c6a3b4020329344f91efeedae1..69c85c3a1f45476f7de0a9399852d82eeb4f9c86 100644 +index 52290c43d1c02785c4cae4a73494a75cdc369e02..1efc97d88c38863bcd6cd4c11c8b88a18ee06b25 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java -@@ -3991,6 +3991,16 @@ public enum Material implements Keyed { +@@ -3992,6 +3992,16 @@ public enum Material implements Keyed { } return false; } @@ -66,10 +66,10 @@ index e348034288c74ab80360086d71f0b7f61551df24..2d9264ffe0fee863f1b814952ef063da // Paper end } diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index e1cc36fbe808973227c0e8ca7166453235c90279..e6647c45f65bae916759cd899256f8130790d242 100644 +index 786b8011e98b2fe93cc2418d624f6350ede62d90..024deba760c41787190d20e4ac5c541920bb4991 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java -@@ -584,5 +584,13 @@ public interface Block extends Metadatable { +@@ -610,5 +610,13 @@ public interface Block extends Metadatable { */ @NotNull com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup(); diff --git a/patches/api-unmapped/0224-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/api/0224-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 95% rename from patches/api-unmapped/0224-Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/api/0224-Create-HoverEvent-from-ItemStack-Entity.patch index 9a15253cfd..982d892402 100644 --- a/patches/api-unmapped/0224-Create-HoverEvent-from-ItemStack-Entity.patch +++ b/patches/api/0224-Create-HoverEvent-from-ItemStack-Entity.patch @@ -5,13 +5,13 @@ Subject: [PATCH] Create HoverEvent from ItemStack Entity diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index e2bcc96ad067e2abfe9108b3a2235fe5da7ab3eb..3cbe5afc3548d4b7d0c6e625d9029506133676ff 100644 +index d773e8594f91017bddd7ea8aada3a1ff2781d05b..0a4466c6ca519c3a5da76ff870fb2a4e3a06effd 100644 --- a/src/main/java/org/bukkit/inventory/ItemFactory.java +++ b/src/main/java/org/bukkit/inventory/ItemFactory.java @@ -184,5 +184,62 @@ public interface ItemFactory { */ - @Nullable - String getI18NDisplayName(@Nullable ItemStack item); + @NotNull + ItemStack ensureServerConversions(@NotNull ItemStack item); + + /** + * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that ItemStack for displaying. diff --git a/patches/server-remapped/0557-Add-BellRingEvent.patch b/patches/server-remapped/0557-Add-BellRingEvent.patch deleted file mode 100644 index 05dfb6c0bb..0000000000 --- a/patches/server-remapped/0557-Add-BellRingEvent.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Eearslya Sleiarion -Date: Sun, 23 Aug 2020 13:04:02 +0200 -Subject: [PATCH] Add BellRingEvent - -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/net/minecraft/world/level/block/BellBlock.java b/src/main/java/net/minecraft/world/level/block/BellBlock.java -index affae471e50354bfa9594e188e6dcea183b9b5c9..dc5dc9e533c71908b7a9a3cc9e614bd4a0dcde98 100644 ---- a/src/main/java/net/minecraft/world/level/block/BellBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/BellBlock.java -@@ -1,8 +1,11 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.BellRingEvent; -+ - import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.stats.Stats; -@@ -89,7 +92,7 @@ public class BellBlock extends BaseEntityBlock { - boolean flag1 = !flag || this.isProperHit(state, enumdirection, movingobjectpositionblock.getLocation().y - (double) blockposition.getY()); - - if (flag1) { -- boolean flag2 = this.attemptToRing(world, blockposition, enumdirection); -+ boolean flag2 = this.handleBellRing(world, blockposition, enumdirection, entityhuman); // Paper - - if (flag2 && entityhuman != null) { - entityhuman.awardStat(Stats.BELL_RING); -@@ -123,15 +126,21 @@ public class BellBlock extends BaseEntityBlock { - } - - public boolean attemptToRing(Level world, BlockPos pos, @Nullable Direction enumdirection) { -- BlockEntity tileentity = world.getBlockEntity(pos); -+ // Paper start - add ringer param -+ return this.handleBellRing(world, pos, enumdirection, null); -+ } -+ public boolean handleBellRing(Level world, BlockPos blockposition, @Nullable Direction enumdirection, @Nullable Entity ringer) { -+ // Paper end -+ BlockEntity tileentity = world.getBlockEntity(blockposition); - - if (!world.isClientSide && tileentity instanceof BellBlockEntity) { - if (enumdirection == null) { -- enumdirection = (Direction) world.getBlockState(pos).getValue(BellBlock.FACING); -+ enumdirection = (Direction) world.getBlockState(blockposition).getValue(BellBlock.FACING); - } - -+ if (!new BellRingEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, blockposition)), ringer == null ? null : ringer.getBukkitEntity()).callEvent()) return false; // Paper - BellRingEvent - ((BellBlockEntity) tileentity).onHit(enumdirection); -- world.playSound((Player) null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); -+ world.playSound((Player) null, blockposition, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); - return true; - } else { - return false; diff --git a/patches/server-remapped/0564-Add-more-Evoker-API.patch b/patches/server-remapped/0564-Add-more-Evoker-API.patch deleted file mode 100644 index af8a4c5513..0000000000 --- a/patches/server-remapped/0564-Add-more-Evoker-API.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 15:28:35 +0200 -Subject: [PATCH] Add more Evoker API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Evoker.java b/src/main/java/net/minecraft/world/entity/monster/Evoker.java -index c0a5b0074480aad717177c92b28fa27b8a1d707d..617075955506500dc2d9c734398c48b8fc10b69d 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Evoker.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Evoker.java -@@ -40,7 +40,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; - - public class Evoker extends SpellcasterIllager { - -- private Sheep wololoTarget; -+ private Sheep wololoTarget; public final Sheep getWololoTarget() { return this.wololoTarget; } public final void setWololoTarget(Sheep sheep) { this.wololoTarget = sheep; } // Paper - OBFHELPER - - public Evoker(EntityType type, Level world) { - super(type, world); -@@ -59,7 +59,7 @@ public class Evoker extends SpellcasterIllager { - this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); - this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); - this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); -- this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).canUse()); -+ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers(new Class[0])); // Paper - decompile fix - this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); - this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, false)); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -index 29fec87c938c4252cf5c9473ce9e5c1908ea9063..950e35f67f88138cc2ce923be1ea7976bd317d1f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import net.minecraft.world.entity.animal.Sheep; - import net.minecraft.world.entity.monster.SpellcasterIllager; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; -@@ -35,4 +36,17 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { - public void setCurrentSpell(Evoker.Spell spell) { - getHandle().setIsCastingSpell(spell == null ? SpellcasterIllager.IllagerSpell.NONE : SpellcasterIllager.IllagerSpell.byId(spell.ordinal())); - } -+ -+ // Paper start -+ @Override -+ public org.bukkit.entity.Sheep getWololoTarget() { -+ Sheep sheep = getHandle().getWololoTarget(); -+ return sheep == null ? null : (org.bukkit.entity.Sheep) sheep.getBukkitEntity(); -+ } -+ -+ @Override -+ public void setWololoTarget(org.bukkit.entity.Sheep sheep) { -+ getHandle().setWololoTarget(sheep == null ? null : ((org.bukkit.craftbukkit.entity.CraftSheep) sheep).getHandle()); -+ } -+ // Paper end - } diff --git a/patches/server/0501-Add-BellRingEvent.patch b/patches/server/0501-Add-BellRingEvent.patch new file mode 100644 index 0000000000..e101aa373c --- /dev/null +++ b/patches/server/0501-Add-BellRingEvent.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Eearslya Sleiarion +Date: Sun, 23 Aug 2020 13:04:02 +0200 +Subject: [PATCH] Add BellRingEvent + +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/net/minecraft/world/level/block/BellBlock.java b/src/main/java/net/minecraft/world/level/block/BellBlock.java +index 3392d9b45d4bfba7ad3e3a84cdd4f2a29b58e4ff..1864984197a6b28cccb3a57b6856f61766d6a467 100644 +--- a/src/main/java/net/minecraft/world/level/block/BellBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BellBlock.java +@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +@@ -131,6 +132,7 @@ public class BellBlock extends BaseEntityBlock { + direction = world.getBlockState(pos).getValue(FACING); + } + ++ if (!new io.papermc.paper.event.block.BellRingEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, pos)), entity == null ? null : entity.getBukkitEntity()).callEvent()) return false; // Paper - BellRingEvent + ((BellBlockEntity)blockEntity).onHit(direction); + world.playSound((Player)null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); + world.gameEvent(entity, GameEvent.RING_BELL, pos); diff --git a/patches/server-remapped/0558-Add-zombie-targets-turtle-egg-config.patch b/patches/server/0502-Add-zombie-targets-turtle-egg-config.patch similarity index 74% rename from patches/server-remapped/0558-Add-zombie-targets-turtle-egg-config.patch rename to patches/server/0502-Add-zombie-targets-turtle-egg-config.patch index d46a54fd32..7704727c56 100644 --- a/patches/server-remapped/0558-Add-zombie-targets-turtle-egg-config.patch +++ b/patches/server/0502-Add-zombie-targets-turtle-egg-config.patch @@ -5,24 +5,26 @@ Subject: [PATCH] Add zombie targets turtle egg config diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 978062774c1db286bfb9b0ffdef19d880b1f249b..36ecdfce84141ac731b827e469ac842f5c666259 100644 +index 91917b11163c0740d5e5effc5e93d494e2b2d73e..caac3c9936c764e411799cb6a702b590f49d9955 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -668,4 +668,9 @@ public class PaperWorldConfig { - maxLightningFlashDistance = 512; // Vanilla value +@@ -41,6 +41,11 @@ public class PaperWorldConfig { } } -+ + + public boolean zombiesTargetTurtleEggs = true; + private void zombiesTargetTurtleEggs() { + zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); + } - } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 1e7c2c603b967c8c606efd94ce95a17c856f78d7..4105c1763d25824aac35d305a793823c1604eee8 100644 +index b036cbb9a1b6bcac91ffc8ee659fc95d6e04d5d4..3125aad3b14a185bbd563827f07c15bbb1ef0895 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -104,7 +104,7 @@ public class Zombie extends Monster { +@@ -109,7 +109,7 @@ public class Zombie extends Monster { @Override protected void registerGoals() { diff --git a/patches/server-remapped/0559-Buffer-joins-to-world.patch b/patches/server/0503-Buffer-joins-to-world.patch similarity index 66% rename from patches/server-remapped/0559-Buffer-joins-to-world.patch rename to patches/server/0503-Buffer-joins-to-world.patch index b9f930aa4e..139ee8a613 100644 --- a/patches/server-remapped/0559-Buffer-joins-to-world.patch +++ b/patches/server/0503-Buffer-joins-to-world.patch @@ -22,18 +22,18 @@ index faa1b775e45563b93ac1d5b904938b1f5ad8d80c..545948f20efd6c8dd42140b565af94cd + } } diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index fc63df21aecd4721efdb45d4744666ed0b562c1b..6f7cbce5a049d87d4a0ed7cc4517cb4e8694efb5 100644 +index 7607bf75968cc32d616e2b44e89901b3681b1131..d32b96a5f51d745869cfc40c01c54de58e1eb843 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java -@@ -32,6 +32,7 @@ import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; - import net.minecraft.network.protocol.game.ClientboundKeepAlivePacket; - import net.minecraft.network.protocol.game.ClientboundSetTitlesPacket; - import net.minecraft.server.MCUtil; +@@ -37,6 +37,7 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketFlow; + import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; + import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.RunningOnDifferentThreadException; - import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; -@@ -382,10 +383,22 @@ public class Connection extends SimpleChannelInboundHandler> { + import net.minecraft.server.network.ServerLoginPacketListenerImpl; +@@ -373,10 +374,22 @@ public class Connection extends SimpleChannelInboundHandler> { } // Paper end @@ -41,7 +41,7 @@ index fc63df21aecd4721efdb45d4744666ed0b562c1b..6f7cbce5a049d87d4a0ed7cc4517cb4e + private static int joinAttemptsThisTick; // Paper + private static int currTick; // Paper public void tick() { - this.p(); + this.flushQueue(); + // Paper start + if (currTick != MinecraftServer.currentTick) { + currTick = MinecraftServer.currentTick; @@ -56,16 +56,3 @@ index fc63df21aecd4721efdb45d4744666ed0b562c1b..6f7cbce5a049d87d4a0ed7cc4517cb4e } if (this.packetListener instanceof ServerGamePacketListenerImpl) { -diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index e229c7735ba88be3d8721440104958408a2a075e..659bf14cf3c949b896d0333f893a3d5e16ab9c92 100644 ---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -420,7 +420,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - return new GameProfile(uuid, profile.getName()); - } - -- static enum State { -+ public enum State { // Paper - package private -> public - - HELLO, KEY, AUTHENTICATING, NEGOTIATING, READY_TO_ACCEPT, DELAY_ACCEPT, ACCEPTED; - diff --git a/patches/server-remapped/0560-Optimize-redstone-algorithm.patch b/patches/server/0504-Optimize-redstone-algorithm.patch similarity index 94% rename from patches/server-remapped/0560-Optimize-redstone-algorithm.patch rename to patches/server/0504-Optimize-redstone-algorithm.patch index 002eed1eeb..1c103119e7 100644 --- a/patches/server-remapped/0560-Optimize-redstone-algorithm.patch +++ b/patches/server/0504-Optimize-redstone-algorithm.patch @@ -19,14 +19,13 @@ Aside from making the obvious class/function renames and obfhelpers I didn't nee Just added Bukkit's event system and took a few liberties with dead code and comment misspellings. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 36ecdfce84141ac731b827e469ac842f5c666259..02bb85364560784adea47c877c13291c3d016b86 100644 +index caac3c9936c764e411799cb6a702b590f49d9955..a88ef43adcf4ba36964f02e3fd363d3e018147cd 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -673,4 +673,14 @@ public class PaperWorldConfig { - private void zombiesTargetTurtleEggs() { +@@ -46,6 +46,16 @@ public class PaperWorldConfig { zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); } -+ + + public boolean useEigencraftRedstone = false; + private void useEigencraftRedstone() { + useEigencraftRedstone = this.getBoolean("use-faster-eigencraft-redstone", false); @@ -36,10 +35,13 @@ index 36ecdfce84141ac731b827e469ac842f5c666259..02bb85364560784adea47c877c13291c + log("Using vanilla redstone algorithm."); + } + } - } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); diff --git a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java new file mode 100644 -index 0000000000000000000000000000000000000000..19604f4d2d0cdf65cb9f164258c4435a5a3450bc +index 0000000000000000000000000000000000000000..3728979e290ab031c9fe9eeb19a0f98d2ce566db --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java @@ -0,0 +1,913 @@ @@ -863,14 +865,14 @@ index 0000000000000000000000000000000000000000..19604f4d2d0cdf65cb9f164258c4435a + j = getMaxCurrentStrength(upd, j); + int l = 0; + -+ wire.setCanProvidePower(false); ++ wire.shouldSignal = false; + // Unfortunately, World.isBlockIndirectlyGettingPowered is complicated, + // and I'm not ready to try to replicate even more functionality from + // elsewhere in Minecraft into this accelerator. So sadly, we must + // suffer the performance hit of this very expensive call. If there + // is consistency to what this call returns, we may be able to cache it. -+ final int k = worldIn.isBlockIndirectlyGettingPowered(upd.self); -+ wire.setCanProvidePower(true); ++ final int k = worldIn.getBestNeighborSignal(upd.self); ++ wire.shouldSignal = true; + + // The variable 'k' holds the maximum redstone power value of any adjacent blocks. + // If 'k' has the highest level of all neighbors, then the power level of this @@ -956,28 +958,8 @@ index 0000000000000000000000000000000000000000..19604f4d2d0cdf65cb9f164258c4435a + return i > strength ? i : strength; + } +} -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 9b50b8030174338c04b60d441b980131e1d593e4..ebb92f88e0402681c47834bcf45e6b236748289a 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -659,6 +659,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - } - -+ public void neighborChanged(BlockPos pos, Block blockIn, BlockPos fromPos) { neighborChanged(pos, blockIn, fromPos); } // Paper - OBFHELPER - public void neighborChanged(BlockPos sourcePos, Block sourceBlock, BlockPos neighborPos) { - if (!this.isClientSide) { - BlockState iblockdata = this.getBlockState(sourcePos); -@@ -1287,6 +1288,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return this.getSignal(pos.below(), Direction.DOWN) > 0 ? true : (this.getSignal(pos.above(), Direction.UP) > 0 ? true : (this.getSignal(pos.north(), Direction.NORTH) > 0 ? true : (this.getSignal(pos.south(), Direction.SOUTH) > 0 ? true : (this.getSignal(pos.west(), Direction.WEST) > 0 ? true : this.getSignal(pos.east(), Direction.EAST) > 0)))); - } - -+ public int isBlockIndirectlyGettingPowered(BlockPos pos) { return this.getBestNeighborSignal(pos); } // Paper - OBFHELPER - public int getBestNeighborSignal(BlockPos pos) { - int i = 0; - Direction[] aenumdirection = Level.DIRECTIONS; diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java -index 7318536fe89cddda305007a9ab115970bf18f65d..e5558b73c6159e4c1901d286535a7875924434e9 100644 +index 2f7a34853fb52c840264ae9f01b3c598f1f92e96..881417b16c377572718fb3ed7c3db832ca7bf865 100644 --- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java @@ -1,5 +1,7 @@ @@ -988,16 +970,16 @@ index 7318536fe89cddda305007a9ab115970bf18f65d..e5558b73c6159e4c1901d286535a7875 import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -@@ -49,7 +51,7 @@ public class RedStoneWireBlock extends Block { - private final Map SHAPES_CACHE = Maps.newHashMap(); - private static final Vector3f[] COLORS = new Vector3f[16]; +@@ -69,7 +71,7 @@ public class RedStoneWireBlock extends Block { + }); + private static final float PARTICLE_DENSITY = 0.2F; private final BlockState crossState; - private boolean shouldSignal = true; -+ private boolean shouldSignal = true; public final boolean canProvidePower() { return this.shouldSignal; } public final void setCanProvidePower(boolean value) { this.shouldSignal = value; } // Paper - OBFHELPER ++ public boolean shouldSignal = true; // Paper private -> public public RedStoneWireBlock(BlockBehaviour.Properties settings) { super(settings); -@@ -236,6 +238,121 @@ public class RedStoneWireBlock extends Block { +@@ -256,6 +258,121 @@ public class RedStoneWireBlock extends Block { return floor.isFaceSturdy(world, pos, Direction.UP) || floor.is(Blocks.HOPPER); } @@ -1031,9 +1013,9 @@ index 7318536fe89cddda305007a9ab115970bf18f65d..e5558b73c6159e4c1901d286535a7875 + int i = state.getValue(POWER); + int j = 0; + j = this.getPower(j, worldIn.getBlockState(pos2)); -+ this.setCanProvidePower(false); -+ int k = worldIn.isBlockIndirectlyGettingPowered(pos1); -+ this.setCanProvidePower(true); ++ this.shouldSignal = false; ++ int k = worldIn.getBestNeighborSignal(pos1); ++ this.shouldSignal = true; + + if (!worldIn.paperConfig.useEigencraftRedstone) { + // This code is totally redundant to if statements just below the loop. @@ -1119,16 +1101,15 @@ index 7318536fe89cddda305007a9ab115970bf18f65d..e5558b73c6159e4c1901d286535a7875 private void updatePowerStrength(Level world, BlockPos pos, BlockState state) { int i = this.calculateTargetStrength(world, pos); -@@ -305,6 +422,8 @@ public class RedStoneWireBlock extends Block { +@@ -325,6 +442,7 @@ public class RedStoneWireBlock extends Block { return Math.max(i, j - 1); } -+ private int getPower(int min, BlockState iblockdata) { return Math.max(min, getPower(iblockdata)); } // Paper - Optimize redstone -+ private int getPower(BlockState iblockdata) { return this.getWireSignal(iblockdata); } // Paper - OBFHELPER ++ private int getPower(int min, BlockState iblockdata) { return Math.max(min, getWireSignal(iblockdata)); } // Paper - Optimize redstone private int getWireSignal(BlockState state) { return state.is((Block) this) ? (Integer) state.getValue(RedStoneWireBlock.POWER) : 0; } -@@ -327,7 +446,7 @@ public class RedStoneWireBlock extends Block { +@@ -347,7 +465,7 @@ public class RedStoneWireBlock extends Block { @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { if (!oldState.is(state.getBlock()) && !world.isClientSide) { @@ -1137,7 +1118,7 @@ index 7318536fe89cddda305007a9ab115970bf18f65d..e5558b73c6159e4c1901d286535a7875 Iterator iterator = Direction.Plane.VERTICAL.iterator(); while (iterator.hasNext()) { -@@ -354,7 +473,7 @@ public class RedStoneWireBlock extends Block { +@@ -374,7 +492,7 @@ public class RedStoneWireBlock extends Block { world.updateNeighborsAt(pos.relative(enumdirection), this); } @@ -1146,7 +1127,7 @@ index 7318536fe89cddda305007a9ab115970bf18f65d..e5558b73c6159e4c1901d286535a7875 this.updateNeighborsOfNeighboringWires(world, pos); } } -@@ -389,7 +508,7 @@ public class RedStoneWireBlock extends Block { +@@ -409,7 +527,7 @@ public class RedStoneWireBlock extends Block { public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { if (!world.isClientSide) { if (state.canSurvive(world, pos)) { diff --git a/patches/server-remapped/0561-Fix-hex-colors-not-working-in-some-kick-messages.patch b/patches/server/0505-Fix-hex-colors-not-working-in-some-kick-messages.patch similarity index 82% rename from patches/server-remapped/0561-Fix-hex-colors-not-working-in-some-kick-messages.patch rename to patches/server/0505-Fix-hex-colors-not-working-in-some-kick-messages.patch index dfda54388f..b6d9c1b713 100644 --- a/patches/server-remapped/0561-Fix-hex-colors-not-working-in-some-kick-messages.patch +++ b/patches/server/0505-Fix-hex-colors-not-working-in-some-kick-messages.patch @@ -5,13 +5,13 @@ Subject: [PATCH] Fix hex colors not working in some kick messages diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -index 6f98be2b9b00f71dd041e7511c70166fdecf0749..c648b73a4c478f9d8020274205d6684f7c7c416f 100644 +index c09d3cdb3acb04b6a833c30a619ff2af5e8b6b18..2384ae5082afd01c4f28fe2f3f782cdce15ff3f2 100644 --- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java @@ -50,7 +50,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL - synchronized (throttleTracker) { - if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { - throttleTracker.put(address, currentTime); + synchronized (ServerHandshakePacketListenerImpl.throttleTracker) { + if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) { + ServerHandshakePacketListenerImpl.throttleTracker.put(address, currentTime); - TranslatableComponent chatmessage = new TranslatableComponent(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message + Component chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage, true)[0]; // Paper - Configurable connection throttle kick message // Paper - Fix hex colors not working in some kick messages this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); @@ -37,16 +37,16 @@ index 6f98be2b9b00f71dd041e7511c70166fdecf0749..c648b73a4c478f9d8020274205d6684f if (event.callEvent()) { // If we've failed somehow, let the client know so and go no further. if (event.isFailed()) { -- chatmessage = new TranslatableComponent(event.getFailMessage()); +- TranslatableComponent chatmessage = new TranslatableComponent(event.getFailMessage()); + Component chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(event.getFailMessage(), true)[0]; // Paper - Fix hex colors not working in some kick messages - this.getNetworkManager().send(new ClientboundLoginDisconnectPacket(chatmessage)); - this.getNetworkManager().disconnect(chatmessage); + this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); + this.connection.disconnect(chatmessage); return; diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 659bf14cf3c949b896d0333f893a3d5e16ab9c92..573963a09f15046cfcaab83aef906801ce70d75a 100644 +index 49308829885a473906d58fb17797127faabfcf31..21ed58d746cb0734cc45574888ed03886e7c411a 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -104,14 +104,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener +@@ -106,14 +106,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener // CraftBukkit start @Deprecated public void disconnect(String s) { diff --git a/patches/server-remapped/0562-PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server/0506-PortalCreateEvent-needs-to-know-its-entity.patch similarity index 80% rename from patches/server-remapped/0562-PortalCreateEvent-needs-to-know-its-entity.patch rename to patches/server/0506-PortalCreateEvent-needs-to-know-its-entity.patch index 0287c9ed0f..2f93746b8b 100644 --- a/patches/server-remapped/0562-PortalCreateEvent-needs-to-know-its-entity.patch +++ b/patches/server/0506-PortalCreateEvent-needs-to-know-its-entity.patch @@ -5,10 +5,10 @@ Subject: [PATCH] PortalCreateEvent needs to know its entity diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 04b717326524f400da3562655c25db59e72814ec..a9256fc4a0bc3cd277cb372a9c090028e03482f5 100644 +index c1667fa43194a17eeeb2ac9c5d57daf5cb131958..a994dd9833ff66eef311b637c59f16a57ddcfe5f 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -366,7 +366,7 @@ public final class ItemStack { +@@ -407,7 +407,7 @@ public final class ItemStack { net.minecraft.world.level.block.state.BlockState block = world.getBlockState(newblockposition); if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically @@ -18,10 +18,10 @@ index 04b717326524f400da3562655c25db59e72814ec..a9256fc4a0bc3cd277cb372a9c090028 world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point diff --git a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java -index cd005f7dbfcaf3cebae3a92da36e0d40c93dbf79..ad37261e716b15d62fc2083d137cdac818308cdd 100644 +index a36d31caa5bfc82a5fd9b16dc42334955fe7511d..177d1da44c83da5f99ae91891dec41dc210bd31d 100644 --- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java -@@ -7,6 +7,7 @@ import net.minecraft.world.damagesource.DamageSource; +@@ -11,6 +11,7 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.context.BlockPlaceContext; @@ -29,7 +29,7 @@ index cd005f7dbfcaf3cebae3a92da36e0d40c93dbf79..ad37261e716b15d62fc2083d137cdac8 import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; -@@ -66,20 +67,23 @@ public abstract class BaseFireBlock extends Block { +@@ -141,20 +142,23 @@ public abstract class BaseFireBlock extends Block { super.entityInside(state, world, pos, entity); } @@ -41,7 +41,7 @@ index cd005f7dbfcaf3cebae3a92da36e0d40c93dbf79..ad37261e716b15d62fc2083d137cdac8 + public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { + // Paper end + if (!iblockdata1.is(iblockdata.getBlock())) { - if (inPortalDimension(world)) { + if (BaseFireBlock.inPortalDimension(world)) { - Optional optional = PortalShape.findEmptyPortalShape((LevelAccessor) world, pos, Direction.Axis.X); + Optional optional = PortalShape.findEmptyPortalShape((LevelAccessor) world, blockposition, Direction.Axis.X); @@ -53,41 +53,41 @@ index cd005f7dbfcaf3cebae3a92da36e0d40c93dbf79..ad37261e716b15d62fc2083d137cdac8 } - if (!state.canSurvive(world, pos)) { -- fireExtinguished(world, pos); // CraftBukkit - fuel block broke +- this.fireExtinguished(world, pos); // CraftBukkit - fuel block broke + if (!iblockdata.canSurvive(world, blockposition)) { + fireExtinguished(world, blockposition); // CraftBukkit - fuel block broke } } diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java -index ac63c5bef5b35b158e57835d765bbdd15fc60664..e690e7c366fc087d3b28d61323dcc78bb7154aed 100644 +index c86bf175853197dceaa91a2287ef51de87b9d5f9..48d9174f88beb759966bfca4c5861aa25cdb2942 100644 --- a/src/main/java/net/minecraft/world/level/block/FireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java -@@ -15,6 +15,7 @@ import net.minecraft.core.Vec3i; - import net.minecraft.server.MCUtil; +@@ -13,6 +13,7 @@ import net.minecraft.core.Direction; + import net.minecraft.core.Vec3i; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; -@@ -363,9 +364,11 @@ public class FireBlock extends BaseFireBlock { +@@ -358,9 +359,11 @@ public class FireBlock extends BaseFireBlock { } @Override - public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { - super.onPlace(state, world, pos, oldState, notify); -- world.getBlockTicks().a(pos, this, getFireTickDelay(world.random)); +- world.getBlockTicks().scheduleTick(pos, this, FireBlock.getFireTickDelay(world.random)); + // Paper start - ItemActionContext param + public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { + super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext); + // Paper end -+ world.getBlockTicks().a(blockposition, this, getFireTickDelay(world.random)); ++ world.getBlockTicks().scheduleTick(blockposition, this, getFireTickDelay(world.random)); } private static int getFireTickDelay(Random random) { diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index df2836b071158729728411f5b228cc38dddd4d4e..f2fefdad26057c722085e60ba837fe2c117f55f7 100644 +index 6d4ef15842c6bd230543de19dd1053a4fe6ad270..597bb3b9b638c59c6ddc21095e4fe4503ef36cb1 100644 --- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java @@ -32,6 +32,7 @@ import net.minecraft.world.item.DyeColor; @@ -98,7 +98,7 @@ index df2836b071158729728411f5b228cc38dddd4d4e..f2fefdad26057c722085e60ba837fe2c import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.world.level.Level; -@@ -119,6 +120,12 @@ public abstract class BlockBehaviour { +@@ -128,6 +129,12 @@ public abstract class BlockBehaviour { DebugPackets.sendNeighborsUpdatePacket(world, pos); } @@ -112,7 +112,7 @@ index df2836b071158729728411f5b228cc38dddd4d4e..f2fefdad26057c722085e60ba837fe2c public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot diff --git a/src/main/java/net/minecraft/world/level/portal/PortalShape.java b/src/main/java/net/minecraft/world/level/portal/PortalShape.java -index 7a99adbe39ca2566d42ed67dc9d6f609005f3d6f..500744b6383390266efed9e35a000511210cb5b9 100644 +index b68fa6cb68bb8fa078d4572bad338f43f20e8dc7..c07b5d1f1ef8b5e6026c7555d476880c8802d6c5 100644 --- a/src/main/java/net/minecraft/world/level/portal/PortalShape.java +++ b/src/main/java/net/minecraft/world/level/portal/PortalShape.java @@ -11,6 +11,7 @@ import net.minecraft.tags.BlockTags; @@ -123,7 +123,7 @@ index 7a99adbe39ca2566d42ed67dc9d6f609005f3d6f..500744b6383390266efed9e35a000511 import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.NetherPortalBlock; -@@ -181,7 +182,10 @@ public class PortalShape { +@@ -185,7 +186,10 @@ public class PortalShape { } // CraftBukkit start - return boolean @@ -132,16 +132,15 @@ index 7a99adbe39ca2566d42ed67dc9d6f609005f3d6f..500744b6383390266efed9e35a000511 + @Deprecated public boolean createPortal() { return this.createPortal(null); } + public boolean createPortal(UseOnContext itemActionContext) { + // Paper end - org.bukkit.World bworld = this.level.getLevel().getWorld(); + org.bukkit.World bworld = this.level.getMinecraftWorld().getWorld(); // Copy below for loop -@@ -190,8 +194,7 @@ public class PortalShape { - BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { - blocks.setBlock(blockposition, iblockdata, 18); +@@ -195,7 +199,7 @@ public class PortalShape { + this.blocks.setBlock(blockposition, iblockdata, 18); }); -- -- PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); + +- PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) this.blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); + PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, itemActionContext == null || itemActionContext.getPlayer() == null ? null : itemActionContext.getPlayer().getBukkitEntity(), PortalCreateEvent.CreateReason.FIRE); // Paper - pass entity param - this.level.getLevel().getServer().server.getPluginManager().callEvent(event); + this.level.getMinecraftWorld().getServer().server.getPluginManager().callEvent(event); if (event.isCancelled()) { diff --git a/patches/server-remapped/0563-Fix-CraftTeam-null-check.patch b/patches/server/0507-Fix-CraftTeam-null-check.patch similarity index 84% rename from patches/server-remapped/0563-Fix-CraftTeam-null-check.patch rename to patches/server/0507-Fix-CraftTeam-null-check.patch index d30a891285..72439c7b46 100644 --- a/patches/server-remapped/0563-Fix-CraftTeam-null-check.patch +++ b/patches/server/0507-Fix-CraftTeam-null-check.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix CraftTeam null check diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -index 7ebcba4ada42f5599d56cfdeb75dbf62f2a09b78..222e3d4e379fd5ca50c122f70e90ed11b2f5e1f7 100644 +index c2dc4d65170eba2d914cf2efdcc231254fec7c02..3d4d4ae34cfbe32a844c7a4bc6cd6fd32e252297 100644 --- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java @@ -253,7 +253,7 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { @@ -15,5 +15,5 @@ index 7ebcba4ada42f5599d56cfdeb75dbf62f2a09b78..222e3d4e379fd5ca50c122f70e90ed11 - Validate.notNull("Entry cannot be null"); + Validate.notNull(entry, "Entry cannot be null"); // Paper - CraftScoreboard scoreboard = checkState(); + CraftScoreboard scoreboard = this.checkState(); diff --git a/patches/server/0508-Add-more-Evoker-API.patch b/patches/server/0508-Add-more-Evoker-API.patch new file mode 100644 index 0000000000..367e900e25 --- /dev/null +++ b/patches/server/0508-Add-more-Evoker-API.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Sun, 23 Aug 2020 15:28:35 +0200 +Subject: [PATCH] Add more Evoker API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java +index 91d07e6996e315734689ea25336992b0ed21cf25..7e861636710aa44ed36e7f20c6320dabb809c35d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java +@@ -1,5 +1,6 @@ + package org.bukkit.craftbukkit.entity; + ++import net.minecraft.world.entity.animal.Sheep; + import net.minecraft.world.entity.monster.SpellcasterIllager; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; +@@ -35,4 +36,17 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { + public void setCurrentSpell(Evoker.Spell spell) { + this.getHandle().setIsCastingSpell(spell == null ? SpellcasterIllager.IllagerSpell.NONE : SpellcasterIllager.IllagerSpell.byId(spell.ordinal())); + } ++ ++ // Paper start ++ @Override ++ public org.bukkit.entity.Sheep getWololoTarget() { ++ Sheep sheep = getHandle().getWololoTarget(); ++ return sheep == null ? null : (org.bukkit.entity.Sheep) sheep.getBukkitEntity(); ++ } ++ ++ @Override ++ public void setWololoTarget(org.bukkit.entity.Sheep sheep) { ++ getHandle().setWololoTarget(sheep == null ? null : ((org.bukkit.craftbukkit.entity.CraftSheep) sheep).getHandle()); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0565-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/server/0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 65% rename from patches/server-remapped/0565-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to patches/server/0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch index 163eac24a0..33a500d610 100644 --- a/patches/server-remapped/0565-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch +++ b/patches/server/0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add a way to get translation keys for blocks, entities and diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index ae50030df7512c56c552e800b74ef4c69ec6d6d2..d38828485d6deb08036e11d8bf16b3d63a60fbae 100644 +index 872f92ac1a6bc86ce54700dbf555ceea4fab2057..4a663a70235609d2f801b8c6bcecbe59d0ea2e27 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -278,6 +278,7 @@ public class EntityType { +@@ -291,6 +291,7 @@ public class EntityType implements EntityTypeTest { return Registry.ENTITY_TYPE.getKey(type); } @@ -17,7 +17,7 @@ index ae50030df7512c56c552e800b74ef4c69ec6d6d2..d38828485d6deb08036e11d8bf16b3d6 public static Optional> byString(String id) { return Registry.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(id)); } -@@ -431,6 +432,7 @@ public class EntityType { +@@ -445,6 +446,7 @@ public class EntityType implements EntityTypeTest { return this.category; } @@ -25,41 +25,12 @@ index ae50030df7512c56c552e800b74ef4c69ec6d6d2..d38828485d6deb08036e11d8bf16b3d6 public String getDescriptionId() { if (this.descriptionId == null) { this.descriptionId = Util.makeDescriptionId("entity", Registry.ENTITY_TYPE.getKey(this)); -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 6fce16e89c5492654c891d5754714360a7649bca..58400e84830c93675b0a1fe632be5e217c19a932 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -56,7 +56,7 @@ public class Item implements ItemLike { - private final FoodProperties foodProperties; - - public static int getId(Item item) { -- return item == null ? 0 : Registry.ITEM.getId((Object) item); -+ return item == null ? 0 : Registry.ITEM.getId(item); // Paper - Fix Decompiler Issue - } - - public static Item byId(int id) { -@@ -152,6 +152,7 @@ public class Item implements ItemLike { - return Registry.ITEM.getKey(this).getPath(); - } - -+ public String getOrCreateDescriptionId() { return getOrCreateDescriptionId(); } // Paper - OBFHELPER - protected String getOrCreateDescriptionId() { - if (this.descriptionId == null) { - this.descriptionId = Util.makeDescriptionId("item", Registry.ITEM.getKey(this)); -@@ -164,6 +165,7 @@ public class Item implements ItemLike { - return this.getOrCreateDescriptionId(); - } - -+ public String getDescriptionId(ItemStack itemStack) { return getDescriptionId(itemStack); } // Paper - OBFHELPER - public String getDescriptionId(ItemStack stack) { - return this.getDescriptionId(); - } diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 5b84ee4091e354c4b6500f58a31931f2a6827ffc..baa587e73a71d6324bb7817fa4702a7c3a2db726 100644 +index 878cdfc49253e7916d038495f79fec7cce75aa50..85fa2b26863e2da8f4de93aa10ffd77f7076b682 100644 --- a/src/main/java/net/minecraft/world/level/block/Block.java +++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -318,6 +318,7 @@ public class Block extends BlockBehaviour implements ItemLike { - return !this.material.isBuildable() && !this.material.isLiquid(); +@@ -427,6 +427,7 @@ public class Block extends BlockBehaviour implements ItemLike { + return new TranslatableComponent(this.getDescriptionId()); } + public String getOrCreateDescriptionId() { return getDescriptionId(); } // Paper - OBFHELPER @@ -67,10 +38,10 @@ index 5b84ee4091e354c4b6500f58a31931f2a6827ffc..baa587e73a71d6324bb7817fa4702a7c if (this.descriptionId == null) { this.descriptionId = Util.makeDescriptionId("block", Registry.BLOCK.getKey(this)); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 05f0833f762436bf8f5f5875c7e3cfed1da11e1c..e09f65f0b06c8fb9a965b921c2c8e68ae2ac1e55 100644 +index 64c304cab8c7c4c9c29f73465f99c11f224a72bd..b31eaa1459690d7f54989ba7a01f96a3f0d8d3b9 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -761,5 +761,10 @@ public class CraftBlock implements Block { +@@ -777,5 +777,10 @@ public class CraftBlock implements Block { public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().defaultBlockState().getSoundType()); } @@ -82,7 +53,7 @@ index 05f0833f762436bf8f5f5875c7e3cfed1da11e1c..e09f65f0b06c8fb9a965b921c2c8e68a // 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 a5a5038a84434e69fda8f6b41d2f00b4989e25ae..de5d02a1345f9886200f0540ac08be0df5878708 100644 +index 88d5c7a0d7de2e896433d85fbd5425351f51b64d..1e387ba8552484b10ae276e1eea47d77d121e19d 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -43,6 +43,7 @@ import org.bukkit.Registry; From 3721b1466f57bebb9d4747802b028a00c36a8e51 Mon Sep 17 00:00:00 2001 From: Josh Roy <10731363+JRoy@users.noreply.github.com> Date: Mon, 14 Jun 2021 06:47:04 -0700 Subject: [PATCH 113/226] need to look at this later, fails rn --- ...3-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch | 2 +- .../0490-Don-t-mark-null-chunk-sections-for-block-updates.patch | 0 ...ght.patch => 0490-Fix-MC-187716-Use-configured-height.patch} | 0 ... 0491-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch} | 0 ...-Do-not-let-the-server-load-chunks-from-newer-version.patch} | 0 .../{0494-Brand-support.patch => 0493-Brand-support.patch} | 0 ...setMaxPlayers-API.patch => 0494-Add-setMaxPlayers-API.patch} | 0 ...h => 0495-Add-playPickupItemAnimation-to-LivingEntity.patch} | 0 ...e-FACING-data.patch => 0496-Don-t-require-FACING-data.patch} | 0 ...497-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch} | 0 ...9-Add-moon-phase-API.patch => 0498-Add-moon-phase-API.patch} | 0 ...h => 0499-Prevent-headless-pistons-from-being-created.patch} | 0 ...501-Add-BellRingEvent.patch => 0500-Add-BellRingEvent.patch} | 0 ...ig.patch => 0501-Add-zombie-targets-turtle-egg-config.patch} | 0 ...er-joins-to-world.patch => 0502-Buffer-joins-to-world.patch} | 0 ...e-algorithm.patch => 0503-Optimize-redstone-algorithm.patch} | 0 ...0504-Fix-hex-colors-not-working-in-some-kick-messages.patch} | 0 ...ch => 0505-PortalCreateEvent-needs-to-know-its-entity.patch} | 0 ...eam-null-check.patch => 0506-Fix-CraftTeam-null-check.patch} | 0 ...Add-more-Evoker-API.patch => 0507-Add-more-Evoker-API.patch} | 0 ...-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch} | 0 21 files changed, 1 insertion(+), 1 deletion(-) rename patches/{server => removed/1.17}/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch (100%) rename patches/server/{0491-Fix-MC-187716-Use-configured-height.patch => 0490-Fix-MC-187716-Use-configured-height.patch} (100%) rename patches/server/{0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch => 0491-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch} (100%) rename patches/server/{0493-Do-not-let-the-server-load-chunks-from-newer-version.patch => 0492-Do-not-let-the-server-load-chunks-from-newer-version.patch} (100%) rename patches/server/{0494-Brand-support.patch => 0493-Brand-support.patch} (100%) rename patches/server/{0495-Add-setMaxPlayers-API.patch => 0494-Add-setMaxPlayers-API.patch} (100%) rename patches/server/{0496-Add-playPickupItemAnimation-to-LivingEntity.patch => 0495-Add-playPickupItemAnimation-to-LivingEntity.patch} (100%) rename patches/server/{0497-Don-t-require-FACING-data.patch => 0496-Don-t-require-FACING-data.patch} (100%) rename patches/server/{0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch => 0497-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch} (100%) rename patches/server/{0499-Add-moon-phase-API.patch => 0498-Add-moon-phase-API.patch} (100%) rename patches/server/{0500-Prevent-headless-pistons-from-being-created.patch => 0499-Prevent-headless-pistons-from-being-created.patch} (100%) rename patches/server/{0501-Add-BellRingEvent.patch => 0500-Add-BellRingEvent.patch} (100%) rename patches/server/{0502-Add-zombie-targets-turtle-egg-config.patch => 0501-Add-zombie-targets-turtle-egg-config.patch} (100%) rename patches/server/{0503-Buffer-joins-to-world.patch => 0502-Buffer-joins-to-world.patch} (100%) rename patches/server/{0504-Optimize-redstone-algorithm.patch => 0503-Optimize-redstone-algorithm.patch} (100%) rename patches/server/{0505-Fix-hex-colors-not-working-in-some-kick-messages.patch => 0504-Fix-hex-colors-not-working-in-some-kick-messages.patch} (100%) rename patches/server/{0506-PortalCreateEvent-needs-to-know-its-entity.patch => 0505-PortalCreateEvent-needs-to-know-its-entity.patch} (100%) rename patches/server/{0507-Fix-CraftTeam-null-check.patch => 0506-Fix-CraftTeam-null-check.patch} (100%) rename patches/server/{0508-Add-more-Evoker-API.patch => 0507-Add-more-Evoker-API.patch} (100%) rename patches/server/{0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch => 0508-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch} (100%) diff --git a/patches/api/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/api/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch index 5e9876ef43..d9c9d2143a 100644 --- a/patches/api/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch +++ b/patches/api/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000>>>>>>> replacement000000000000000000 Mon Sep 17 00:00:00 2001 +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MeFisto94 Date: Tue, 11 Aug 2020 19:17:46 +0200 Subject: [PATCH] Add a way to get translation keys for blocks, entities and diff --git a/patches/server/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch b/patches/removed/1.17/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch similarity index 100% rename from patches/server/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch rename to patches/removed/1.17/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch diff --git a/patches/server/0491-Fix-MC-187716-Use-configured-height.patch b/patches/server/0490-Fix-MC-187716-Use-configured-height.patch similarity index 100% rename from patches/server/0491-Fix-MC-187716-Use-configured-height.patch rename to patches/server/0490-Fix-MC-187716-Use-configured-height.patch diff --git a/patches/server/0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/patches/server/0491-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch similarity index 100% rename from patches/server/0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch rename to patches/server/0491-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch diff --git a/patches/server/0493-Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server/0492-Do-not-let-the-server-load-chunks-from-newer-version.patch similarity index 100% rename from patches/server/0493-Do-not-let-the-server-load-chunks-from-newer-version.patch rename to patches/server/0492-Do-not-let-the-server-load-chunks-from-newer-version.patch diff --git a/patches/server/0494-Brand-support.patch b/patches/server/0493-Brand-support.patch similarity index 100% rename from patches/server/0494-Brand-support.patch rename to patches/server/0493-Brand-support.patch diff --git a/patches/server/0495-Add-setMaxPlayers-API.patch b/patches/server/0494-Add-setMaxPlayers-API.patch similarity index 100% rename from patches/server/0495-Add-setMaxPlayers-API.patch rename to patches/server/0494-Add-setMaxPlayers-API.patch diff --git a/patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server/0495-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/server/0495-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/patches/server/0497-Don-t-require-FACING-data.patch b/patches/server/0496-Don-t-require-FACING-data.patch similarity index 100% rename from patches/server/0497-Don-t-require-FACING-data.patch rename to patches/server/0496-Don-t-require-FACING-data.patch diff --git a/patches/server/0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server/0497-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch similarity index 100% rename from patches/server/0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch rename to patches/server/0497-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch diff --git a/patches/server/0499-Add-moon-phase-API.patch b/patches/server/0498-Add-moon-phase-API.patch similarity index 100% rename from patches/server/0499-Add-moon-phase-API.patch rename to patches/server/0498-Add-moon-phase-API.patch diff --git a/patches/server/0500-Prevent-headless-pistons-from-being-created.patch b/patches/server/0499-Prevent-headless-pistons-from-being-created.patch similarity index 100% rename from patches/server/0500-Prevent-headless-pistons-from-being-created.patch rename to patches/server/0499-Prevent-headless-pistons-from-being-created.patch diff --git a/patches/server/0501-Add-BellRingEvent.patch b/patches/server/0500-Add-BellRingEvent.patch similarity index 100% rename from patches/server/0501-Add-BellRingEvent.patch rename to patches/server/0500-Add-BellRingEvent.patch diff --git a/patches/server/0502-Add-zombie-targets-turtle-egg-config.patch b/patches/server/0501-Add-zombie-targets-turtle-egg-config.patch similarity index 100% rename from patches/server/0502-Add-zombie-targets-turtle-egg-config.patch rename to patches/server/0501-Add-zombie-targets-turtle-egg-config.patch diff --git a/patches/server/0503-Buffer-joins-to-world.patch b/patches/server/0502-Buffer-joins-to-world.patch similarity index 100% rename from patches/server/0503-Buffer-joins-to-world.patch rename to patches/server/0502-Buffer-joins-to-world.patch diff --git a/patches/server/0504-Optimize-redstone-algorithm.patch b/patches/server/0503-Optimize-redstone-algorithm.patch similarity index 100% rename from patches/server/0504-Optimize-redstone-algorithm.patch rename to patches/server/0503-Optimize-redstone-algorithm.patch diff --git a/patches/server/0505-Fix-hex-colors-not-working-in-some-kick-messages.patch b/patches/server/0504-Fix-hex-colors-not-working-in-some-kick-messages.patch similarity index 100% rename from patches/server/0505-Fix-hex-colors-not-working-in-some-kick-messages.patch rename to patches/server/0504-Fix-hex-colors-not-working-in-some-kick-messages.patch diff --git a/patches/server/0506-PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server/0505-PortalCreateEvent-needs-to-know-its-entity.patch similarity index 100% rename from patches/server/0506-PortalCreateEvent-needs-to-know-its-entity.patch rename to patches/server/0505-PortalCreateEvent-needs-to-know-its-entity.patch diff --git a/patches/server/0507-Fix-CraftTeam-null-check.patch b/patches/server/0506-Fix-CraftTeam-null-check.patch similarity index 100% rename from patches/server/0507-Fix-CraftTeam-null-check.patch rename to patches/server/0506-Fix-CraftTeam-null-check.patch diff --git a/patches/server/0508-Add-more-Evoker-API.patch b/patches/server/0507-Add-more-Evoker-API.patch similarity index 100% rename from patches/server/0508-Add-more-Evoker-API.patch rename to patches/server/0507-Add-more-Evoker-API.patch diff --git a/patches/server/0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/server/0508-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 100% rename from patches/server/0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to patches/server/0508-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch From 21effd6c48b49bd3aebd746d6a157bac9c798e60 Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 14 Jun 2021 16:41:34 +0200 Subject: [PATCH 114/226] even moar workkkkk --- ...al-open-container-api-to-HumanEntity.patch | 2 +- ...y-Counter-to-allow-plugins-to-use-va.patch | 0 .../0227-Entity-isTicking.patch | 4 +- ...Fix-Not-a-string-Map-Conversion-spam.patch | 2 +- ...d-mobs-to-jump-and-take-water-damage.patch | 6 +-- .../server/0472-Add-entity-liquid-API.patch | 35 +++++-------- ...llow-delegation-to-vanilla-chunk-gen.patch | 8 +-- ...ze-NetworkManager-Exception-Handling.patch | 4 +- ...-Fix-MC-187716-Use-configured-height.patch | 15 +++--- patches/server/0507-Add-more-Evoker-API.patch | 19 +++++++ ...-translation-keys-for-blocks-entitie.patch | 10 +--- ...te-HoverEvent-from-ItemStack-Entity.patch} | 6 +-- .../0510-Cache-block-data-strings.patch} | 10 ++-- ...rtation-and-cancel-velocity-if-tele.patch} | 52 +++++++++---------- ...l-open-container-api-to-HumanEntity.patch} | 6 +-- ...aFixerUpper-Rewrite-Rules-on-demand.patch} | 0 ...-capture-to-capture-all-items-added.patch} | 24 +++------ ...ty-in-invalid-locations-SPIGOT-6086.patch} | 6 +-- ...-Counter-to-allow-plugins-to-use-va.patch} | 6 +-- ...track-plugin-scoreboards-by-default.patch} | 23 ++++---- .../0518-Entity-isTicking.patch} | 12 ++--- ...non-whitelisted-player-when-white-l.patch} | 4 +- 22 files changed, 125 insertions(+), 129 deletions(-) rename patches/{api-unmapped => api}/0225-Add-additional-open-container-api-to-HumanEntity.patch (97%) rename patches/{api-unmapped => api}/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch (100%) rename patches/{api-unmapped => api}/0227-Entity-isTicking.patch (80%) rename patches/{server-remapped => removed/1.17}/0577-Fix-Not-a-string-Map-Conversion-spam.patch (97%) rename patches/{server-remapped/0566-Create-HoverEvent-from-ItemStack-Entity.patch => server/0509-Create-HoverEvent-from-ItemStack-Entity.patch} (91%) rename patches/{server-remapped/0567-Cache-block-data-strings.patch => server/0510-Cache-block-data-strings.patch} (87%) rename patches/{server-remapped/0568-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch => server/0511-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch} (64%) rename patches/{server-remapped/0569-Add-additional-open-container-api-to-HumanEntity.patch => server/0512-Add-additional-open-container-api-to-HumanEntity.patch} (92%) rename patches/{server-remapped/0570-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch => server/0513-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch} (100%) rename patches/{server-remapped/0571-Extend-block-drop-capture-to-capture-all-items-added.patch => server/0514-Extend-block-drop-capture-to-capture-all-items-added.patch} (70%) rename patches/{server-remapped/0572-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch => server/0515-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch} (78%) rename patches/{server-remapped/0573-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch => server/0516-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch} (82%) rename patches/{server-remapped/0574-Lazily-track-plugin-scoreboards-by-default.patch => server/0517-Lazily-track-plugin-scoreboards-by-default.patch} (84%) rename patches/{server-remapped/0575-Entity-isTicking.patch => server/0518-Entity-isTicking.patch} (75%) rename patches/{server-remapped/0576-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch => server/0519-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch} (86%) diff --git a/patches/api-unmapped/0225-Add-additional-open-container-api-to-HumanEntity.patch b/patches/api/0225-Add-additional-open-container-api-to-HumanEntity.patch similarity index 97% rename from patches/api-unmapped/0225-Add-additional-open-container-api-to-HumanEntity.patch rename to patches/api/0225-Add-additional-open-container-api-to-HumanEntity.patch index 53584ff633..52fe9f1bc3 100644 --- a/patches/api-unmapped/0225-Add-additional-open-container-api-to-HumanEntity.patch +++ b/patches/api/0225-Add-additional-open-container-api-to-HumanEntity.patch @@ -5,7 +5,7 @@ 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 b09d12390d5f77330ac84452e0fee63a169bd01f..77bff8fb6bfdf739e413084e13677a83e723c71e 100644 +index c307a58b17324d6df8c21fa45f0f1e34810f1828..112c891e54e8f30ac10e6865efc2a8ee8d172188 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java @@ -148,6 +148,92 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder diff --git a/patches/api-unmapped/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/api/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 100% rename from patches/api-unmapped/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to patches/api/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch diff --git a/patches/api-unmapped/0227-Entity-isTicking.patch b/patches/api/0227-Entity-isTicking.patch similarity index 80% rename from patches/api-unmapped/0227-Entity-isTicking.patch rename to patches/api/0227-Entity-isTicking.patch index 315c89bf3b..c4c93d0fdb 100644 --- a/patches/api-unmapped/0227-Entity-isTicking.patch +++ b/patches/api/0227-Entity-isTicking.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Entity#isTicking diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index ecb5595332ab493224d06a75904e142ab541aad9..4ed8c74f874dbd1017764d7592acfdafbc5d5fe1 100644 +index 09dc74b0e10d075190009631c84a3710cc1f9177..8cfe08cbc869e468edc0f0bdaa28d5bf1f6201a2 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -744,5 +744,10 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent +@@ -747,5 +747,10 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent * Check if entity is in lava */ public boolean isInLava(); diff --git a/patches/server-remapped/0577-Fix-Not-a-string-Map-Conversion-spam.patch b/patches/removed/1.17/0577-Fix-Not-a-string-Map-Conversion-spam.patch similarity index 97% rename from patches/server-remapped/0577-Fix-Not-a-string-Map-Conversion-spam.patch rename to patches/removed/1.17/0577-Fix-Not-a-string-Map-Conversion-spam.patch index 5b9dbf362f..6decec5b67 100644 --- a/patches/server-remapped/0577-Fix-Not-a-string-Map-Conversion-spam.patch +++ b/patches/removed/1.17/0577-Fix-Not-a-string-Map-Conversion-spam.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Thu, 8 Oct 2020 00:00:25 -0400 Subject: [PATCH] Fix "Not a string" Map Conversion spam - +1.17 Update: See if this is still needed, might be fixed upstream The maps did convert successfully, but had noisy logs due to Spigot implementing this logic incorrectly. diff --git a/patches/server/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/patches/server/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch index c8750f1179..ea21f6702a 100644 --- a/patches/server/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch +++ b/patches/server/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch @@ -19,7 +19,7 @@ index 78948c42b13194005bdbbbc69c2b7ae0732a78c5..b41e7922dd96c3358eb849ab39982a75 + } } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c8ebce55b4e3838bf70b115ffb0b634b3548a7dd..b82dd96147224057ea0e0dc92506b27ffbc9f034 100644 +index 2bfafeec6f8a605a7826091314992e61a49e4c51..6d7f2db63d586b96939cfc3643ebae3a952a4836 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1264,6 +1264,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @@ -31,7 +31,7 @@ index c8ebce55b4e3838bf70b115ffb0b634b3548a7dd..b82dd96147224057ea0e0dc92506b27f return this.isInWater() || this.isInRain() || this.isInBubbleColumn(); } diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index e4f3dbff2605243039f9f59f025c931b3fb309c5..a5d90af5275c9c8069932f711069a6d422303d05 100644 +index e4f3dbff2605243039f9f59f025c931b3fb309c5..3a444371e484defa3119d04b9fa7cf50ca5966ec 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java @@ -103,6 +103,7 @@ public abstract class Mob extends LivingEntity { @@ -52,7 +52,7 @@ index e4f3dbff2605243039f9f59f025c931b3fb309c5..a5d90af5275c9c8069932f711069a6d4 + if (goalFloat.validConditions()) goalFloat.update(); + this.getJumpControl().jumpIfSet(); + } -+ if ((this instanceof net.minecraft.world.entity.monster.Blaze || this instanceof net.minecraft.world.entity.monster.EnderMan) && isInWaterOrRainOrBubble()) { ++ if ((this instanceof net.minecraft.world.entity.monster.Blaze || this instanceof net.minecraft.world.entity.monster.EnderMan) && isInWaterRainOrBubble()) { + hurt(DamageSource.DROWN, 1.0F); + } + return; diff --git a/patches/server/0472-Add-entity-liquid-API.patch b/patches/server/0472-Add-entity-liquid-API.patch index 572e26f912..81e7a4809c 100644 --- a/patches/server/0472-Add-entity-liquid-API.patch +++ b/patches/server/0472-Add-entity-liquid-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add entity liquid API diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 96da70f1077f70c4bd5ba1196292a856deb25286..8531f1deea95aa8e73e75b714426c915a52a74af 100644 +index 96da70f1077f70c4bd5ba1196292a856deb25286..466de2bbdbf0c9e3ed28ec8fee5fcfeb75c54398 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1305,12 +1305,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -1305,13 +1305,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n return this.wasTouchingWater; } @@ -19,28 +19,21 @@ index 96da70f1077f70c4bd5ba1196292a856deb25286..8531f1deea95aa8e73e75b714426c915 return this.level.isRainingAt(blockposition) || this.level.isRainingAt(new BlockPos((double) blockposition.getX(), this.getBoundingBox().maxY, (double) blockposition.getZ())); } -+ public final boolean isInBubbleColumn() { return isInBubbleColumn(); } // Paper - OBFHELPER - private boolean isInBubbleColumn() { +- private boolean isInBubbleColumn() { ++ public boolean isInBubbleColumn() { // Paper - make public return this.level.getBlockState(this.blockPosition()).is(Blocks.BUBBLE_COLUMN); } -@@ -1324,6 +1325,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + +@@ -1319,7 +1319,6 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + return this.isInWater() || this.isInRain(); + } + +- public final boolean isInWaterOrRainOrBubble() { return isInWaterRainOrBubble(); } // Paper - OBFHELPER + public boolean isInWaterRainOrBubble() { return this.isInWater() || this.isInRain() || this.isInBubbleColumn(); } - -+ public final boolean isInWaterOrBubbleColumn() { return isInWaterOrBubble(); } // Paper - OBFHELPER - public boolean isInWaterOrBubble() { - return this.isInWater() || this.isInBubbleColumn(); - } -@@ -1463,6 +1465,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n - return this.fluidOnEyes == fluidTag; - } - -+ public final boolean isInLava() { return isInLava(); } // Paper - OBFHELPER - public boolean isInLava() { - return !this.firstTick && this.fluidHeight.getDouble(FluidTags.LAVA) > 0.0D; - } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 98d3818d38f487fc7e1302ee4af9e4898efec809..26bfbab1e8332f91c4d2814cd0056ca2ea7ddab7 100644 +index 98d3818d38f487fc7e1302ee4af9e4898efec809..a13042367ac284ce23d799eba1330aa2777173e7 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -1169,5 +1169,29 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -61,11 +54,11 @@ index 98d3818d38f487fc7e1302ee4af9e4898efec809..26bfbab1e8332f91c4d2814cd0056ca2 + } + + public boolean isInWaterOrBubbleColumn() { -+ return getHandle().isInWaterOrBubbleColumn(); ++ return getHandle().isInWaterOrBubble(); + } + + public boolean isInWaterOrRainOrBubbleColumn() { -+ return getHandle().isInWaterOrRainOrBubble(); ++ return getHandle().isInWaterRainOrBubble(); + } + + public boolean isInLava() { diff --git a/patches/server/0476-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/0476-Allow-delegation-to-vanilla-chunk-gen.patch index 3719bedef5..287d85372d 100644 --- a/patches/server/0476-Allow-delegation-to-vanilla-chunk-gen.patch +++ b/patches/server/0476-Allow-delegation-to-vanilla-chunk-gen.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Allow delegation to vanilla chunk gen diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6bc5ba51c90723c7138b1b5d2381cb215f1e5271..df2c41d18377d8519d5537186d529ecc1901f58a 100644 +index 6bc5ba51c90723c7138b1b5d2381cb215f1e5271..beb8b7d06ef47c80ede95c884598fedcc7126d67 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -2033,6 +2033,32 @@ public final class CraftServer implements Server { @@ -19,17 +19,17 @@ index 6bc5ba51c90723c7138b1b5d2381cb215f1e5271..df2c41d18377d8519d5537186d529ecc + CraftChunkData data = (CraftChunkData) createChunkData(world); + // do bunch of vanilla shit + net.minecraft.server.level.ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); -+ net.minecraft.world.level.chunk.ProtoChunk protoChunk = new net.minecraft.world.level.chunk.ProtoChunk(new net.minecraft.world.level.ChunkPos(x, z), net.minecraft.world.level.chunk.UpgradeData.getEmptyConverter(), nmsWorld); ++ net.minecraft.world.level.chunk.ProtoChunk protoChunk = new net.minecraft.world.level.chunk.ProtoChunk(new net.minecraft.world.level.ChunkPos(x, z), null, nmsWorld); + List list = new ArrayList<>(); + list.add(protoChunk); -+ net.minecraft.server.level.WorldGenRegion genRegion = new net.minecraft.server.level.WorldGenRegion(nmsWorld, list); ++ net.minecraft.server.level.WorldGenRegion genRegion = new net.minecraft.server.level.WorldGenRegion(nmsWorld, list, net.minecraft.world.level.chunk.ChunkStatus.EMPTY, -1); + // call vanilla generator, one feature after another. Order here is important! + net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator = nmsWorld.getChunkSource().generator; + if (chunkGenerator instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator) { + chunkGenerator = ((org.bukkit.craftbukkit.generator.CustomChunkGenerator) chunkGenerator).delegate; + } + chunkGenerator.createBiomes(nmsWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), protoChunk); -+ chunkGenerator.fillFromNoise(genRegion, nmsWorld.structureFeatureManager(), protoChunk); ++ chunkGenerator.fillFromNoise((runnable) -> {}, nmsWorld.structureFeatureManager(), protoChunk); + chunkGenerator.buildSurfaceAndBedrock(genRegion, protoChunk); + // copy over generated sections + data.setRawChunkData(protoChunk.getSections()); diff --git a/patches/server/0478-Optimize-NetworkManager-Exception-Handling.patch b/patches/server/0478-Optimize-NetworkManager-Exception-Handling.patch index 7e00ab11c3..5115fd3ccd 100644 --- a/patches/server/0478-Optimize-NetworkManager-Exception-Handling.patch +++ b/patches/server/0478-Optimize-NetworkManager-Exception-Handling.patch @@ -42,7 +42,7 @@ index 5356f6484751e4b4740720aecac90bdfe044283b..ed54479b14dcfc736ac90749106557f0 for(int i = 0; i < bs.length; ++i) { diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -index 449f1b2f5dca350dc0912e14c8c2bf3eb4652b92..9e944aa41c184ebde1179399def662b2f08eef62 100644 +index 449f1b2f5dca350dc0912e14c8c2bf3eb4652b92..bcf53ec07b8eeec7a88fb67e6fb908362e6f51b0 100644 --- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java +++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java @@ -1,6 +1,9 @@ @@ -61,7 +61,7 @@ index 449f1b2f5dca350dc0912e14c8c2bf3eb4652b92..9e944aa41c184ebde1179399def662b2 } // Paper - timings + // Paper start + catch (Exception e) { -+ Connection networkmanager = listener.a(); ++ Connection networkmanager = listener.getConnection(); + if (networkmanager.getPlayer() != null) { + LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), networkmanager.getRemoteAddress(), e); + } else { diff --git a/patches/server/0490-Fix-MC-187716-Use-configured-height.patch b/patches/server/0490-Fix-MC-187716-Use-configured-height.patch index 678b0ee0bc..204be7ceb0 100644 --- a/patches/server/0490-Fix-MC-187716-Use-configured-height.patch +++ b/patches/server/0490-Fix-MC-187716-Use-configured-height.patch @@ -5,16 +5,10 @@ Subject: [PATCH] Fix MC-187716 Use configured height diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java -index 5ad6e0ef718a1775a2310925b8273120687230b1..88fbd8a925d84184116051082514ef4d45c98acf 100644 +index 5ad6e0ef718a1775a2310925b8273120687230b1..7c3386b37aae7d10629e0a256102967f69b68a7e 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java +++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java -@@ -1,4 +1,5 @@ - package net.minecraft.world.level.levelgen.surfacebuilders; -+<<<<<<< found - - import com.google.common.collect.ImmutableList; - import com.google.common.collect.ImmutableMap; -@@ -42,7 +43,7 @@ public abstract class NetherCappedSurfaceBuilder extends SurfaceBuilder implements EntityTypeTest { @@ -17,14 +17,6 @@ index 872f92ac1a6bc86ce54700dbf555ceea4fab2057..4a663a70235609d2f801b8c6bcecbe59 public static Optional> byString(String id) { return Registry.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(id)); } -@@ -445,6 +446,7 @@ public class EntityType implements EntityTypeTest { - return this.category; - } - -+ public String getDescriptionId() { return getDescriptionId(); } // Paper - OBFHELPER - public String getDescriptionId() { - if (this.descriptionId == null) { - this.descriptionId = Util.makeDescriptionId("entity", Registry.ENTITY_TYPE.getKey(this)); diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java index 878cdfc49253e7916d038495f79fec7cce75aa50..85fa2b26863e2da8f4de93aa10ffd77f7076b682 100644 --- a/src/main/java/net/minecraft/world/level/block/Block.java diff --git a/patches/server-remapped/0566-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server/0509-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 91% rename from patches/server-remapped/0566-Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/server/0509-Create-HoverEvent-from-ItemStack-Entity.patch index a7252fed8a..b71640c7c6 100644 --- a/patches/server-remapped/0566-Create-HoverEvent-from-ItemStack-Entity.patch +++ b/patches/server/0509-Create-HoverEvent-from-ItemStack-Entity.patch @@ -5,12 +5,12 @@ Subject: [PATCH] Create HoverEvent from ItemStack Entity diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 746755f76ae177b2eeccf66f8cd95e6ffd5acad9..2e0be9771ca3511f5d9364c57235556b70f07ec6 100644 +index 6ec39de514ceed7e5ffe9a8dc94c2ffd2902cd98..9cde8ae979287d342574da066f65731324725dea 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -365,5 +365,40 @@ public final class CraftItemFactory implements ItemFactory { +@@ -368,5 +368,40 @@ public final class CraftItemFactory implements ItemFactory { - return nms != null ? net.minecraft.locale.Language.getInstance().translateKey(nms.getItem().getDescriptionId()) : null; + return nms != null ? net.minecraft.locale.Language.getInstance().getOrDefault(nms.getItem().getDescriptionId()) : null; } + + @Override diff --git a/patches/server-remapped/0567-Cache-block-data-strings.patch b/patches/server/0510-Cache-block-data-strings.patch similarity index 87% rename from patches/server-remapped/0567-Cache-block-data-strings.patch rename to patches/server/0510-Cache-block-data-strings.patch index b4924166cc..90aa71661d 100644 --- a/patches/server-remapped/0567-Cache-block-data-strings.patch +++ b/patches/server/0510-Cache-block-data-strings.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Cache block data strings diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 735c3c983e96e4e6f36de0975909fc48cb042081..5c5903867432894b47bc62d89989f78c36a84ca1 100644 +index 1889de77a5e3d9371005b6bd451e2c0e57e96a93..dd51341115450a38ea5b0ea34dbadc2a8e191f60 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1953,6 +1953,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop%s", nms, bukkit); +@@ -494,9 +495,39 @@ public class CraftBlockData implements BlockData { + Preconditions.checkState(CraftBlockData.MAP.put(nms, bukkit) == null, "Duplicate mapping %s->%s", nms, bukkit); } + // Paper start - cache block data strings diff --git a/patches/server-remapped/0568-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/patches/server/0511-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch similarity index 64% rename from patches/server-remapped/0568-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch rename to patches/server/0511-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch index 1e30590a64..403e8d2e60 100644 --- a/patches/server-remapped/0568-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch +++ b/patches/server/0511-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch @@ -9,32 +9,32 @@ as this is how Vanilla teleports entities. Cancel any pending motion when teleported. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ab6494f5a872bba5398bef0367b4d9257786f61e..ab45497e8f7720c9d60626b32e9c95779af676b0 100644 +index 0176b85a031b33cb2a12bb75079f5e3111f4f2b7..e3725db7e19fe3235ec25beffca26a7eede24394 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -691,7 +691,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -682,7 +682,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser public void handleAcceptTeleportPacket(ServerboundAcceptTeleportationPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); if (packet.getId() == this.awaitingTeleport && this.awaitingPositionFromClient != null) { // CraftBukkit -- this.player.absMoveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.yRot, this.player.xRot); -+ this.player.moveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.yRot, this.player.xRot); // Paper - use proper setPositionRotation for teleportation +- this.player.absMoveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); ++ this.player.moveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); // Paper - use proper setPositionRotation for teleportation this.lastGoodX = this.awaitingPositionFromClient.x; this.lastGoodY = this.awaitingPositionFromClient.y; this.lastGoodZ = this.awaitingPositionFromClient.z; -@@ -1536,7 +1536,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1569,7 +1569,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // CraftBukkit end this.awaitingTeleportTime = this.tickCount; - this.player.absMoveTo(d0, d1, d2, f, f1); + this.player.moveTo(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation - this.player.forceCheckHighPriority(); // Paper - this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); + this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport, flag)); } + diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index aea2457510c75214bbb925307155611e981f115f..d69981a1b5a40418c7d17de5f3bece30592ae586 100644 +index 466de2bbdbf0c9e3ed28ec8fee5fcfeb75c54398..a9c90e41af1cc67a88a639dc795dd8023a7acb89 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -143,6 +143,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -152,6 +152,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n // CraftBukkit start private static final int CURRENT_LEVEL = 2; @@ -42,7 +42,7 @@ index aea2457510c75214bbb925307155611e981f115f..d69981a1b5a40418c7d17de5f3bece30 static boolean isLevelAtLeast(CompoundTag tag, int level) { return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; } -@@ -1406,6 +1407,13 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1522,6 +1523,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } public void moveTo(double x, double y, double z, float yaw, float pitch) { @@ -53,31 +53,31 @@ index aea2457510c75214bbb925307155611e981f115f..d69981a1b5a40418c7d17de5f3bece30 + this.preserveMotion = false; + } + // Paper end - this.setPosAndOldPos(x, y, z); - this.yRot = yaw; - this.xRot = pitch; + this.setPosRaw(x, y, z); + this.setYRot(yaw); + this.setXRot(pitch); diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 6ca378ec7868b855d46c749910c656f82ddb009f..091e72474ac199c38fff979a5faf524e011d8d0a 100644 +index 68ce2732dfdc25ddadc15c43c30a609f9b1eba86..c741f8e4a4b67d1bfed2d1bac36856c5688bb161 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -165,6 +165,7 @@ public abstract class BaseSpawner { - return; - } +@@ -170,6 +170,7 @@ public abstract class BaseSpawner { + return; + } -+ entity.preserveMotion = true; // Paper - preserve entity motion from tag - entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), world.random.nextFloat() * 360.0F, 0.0F); - if (entity instanceof Mob) { - Mob entityinsentient = (Mob) entity; ++ entity.preserveMotion = true; // Paper - preserve entity motion from tag + entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), world.random.nextFloat() * 360.0F, 0.0F); + if (entity instanceof Mob) { + Mob entityinsentient = (Mob) entity; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index deeae62e9926f9435907c68e7d35e7420f5e79dd..1275768762884416fa3c68dab3a6671b24949976 100644 +index a13042367ac284ce23d799eba1330aa2777173e7..5d11d573a68bea7b341bb987b6cfb998bd1b74fb 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -556,7 +556,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -563,7 +563,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { } // entity.setLocation() throws no event, and so cannot be cancelled -- entity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); +- this.entity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + entity.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); // Paper - use proper setPosition, as per vanilla teleporting // SPIGOT-619: Force sync head rotation also - entity.setYHeadRot(location.getYaw()); - ((net.minecraft.server.level.ServerLevel) entity.level).updateChunkPos(entity); // Spigot - register to new chunk + this.entity.setYHeadRot(location.getYaw()); + diff --git a/patches/server-remapped/0569-Add-additional-open-container-api-to-HumanEntity.patch b/patches/server/0512-Add-additional-open-container-api-to-HumanEntity.patch similarity index 92% rename from patches/server-remapped/0569-Add-additional-open-container-api-to-HumanEntity.patch rename to patches/server/0512-Add-additional-open-container-api-to-HumanEntity.patch index 4f031f39de..bc89c1c9ea 100644 --- a/patches/server-remapped/0569-Add-additional-open-container-api-to-HumanEntity.patch +++ b/patches/server/0512-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/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 878a62e04962aafeaf192075fbe08e319298a800..aceb57c93c91730345f49f78838780c41ce2dcef 100644 +index 36ea76bfe0bd96ead82ed1ad34f25de10b7fa30e..021394a0e668d2cfccd8617d4aee79147181fa22 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -459,6 +459,70 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -458,6 +458,70 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { return this.getHandle().containerMenu.getBukkitView(); } @@ -78,4 +78,4 @@ index 878a62e04962aafeaf192075fbe08e319298a800..aceb57c93c91730345f49f78838780c4 + @Override public void closeInventory() { - // Paper start + this.getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); diff --git a/patches/server-remapped/0570-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/patches/server/0513-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch similarity index 100% rename from patches/server-remapped/0570-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch rename to patches/server/0513-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch diff --git a/patches/server-remapped/0571-Extend-block-drop-capture-to-capture-all-items-added.patch b/patches/server/0514-Extend-block-drop-capture-to-capture-all-items-added.patch similarity index 70% rename from patches/server-remapped/0571-Extend-block-drop-capture-to-capture-all-items-added.patch rename to patches/server/0514-Extend-block-drop-capture-to-capture-all-items-added.patch index 21f6d53f47..e32d13d264 100644 --- a/patches/server-remapped/0571-Extend-block-drop-capture-to-capture-all-items-added.patch +++ b/patches/server/0514-Extend-block-drop-capture-to-capture-all-items-added.patch @@ -6,24 +6,16 @@ Subject: [PATCH] Extend block drop capture to capture all items added to the diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 22266fda4de9b5fbace3b8e55ce390b8d7e75a65..fe7b71fbb3963beafe93a5d86bebdd629c7ec8f2 100644 +index 4ae56444d258cdf44a02256315d6aae84e2f53be..f1c02ae301da2a3b582d2ec1215c1a981e26ac47 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -95,6 +95,7 @@ import net.minecraft.world.entity.ai.village.poi.PoiType; - import net.minecraft.world.entity.animal.horse.SkeletonHorse; - import net.minecraft.world.entity.boss.EnderDragonPart; - import net.minecraft.world.entity.boss.enderdragon.EnderDragon; -+import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.entity.monster.Drowned; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.raid.Raid; -@@ -1284,6 +1285,13 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } else if (this.isUUIDUsed(entity)) { +@@ -1220,6 +1220,13 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit return false; } else { + // Paper start - capture all item additions to the world -+ if (captureDrops != null && entity instanceof ItemEntity) { -+ captureDrops.add((ItemEntity) entity); ++ if (captureDrops != null && entity instanceof net.minecraft.world.entity.item.ItemEntity) { ++ captureDrops.add((net.minecraft.world.entity.item.ItemEntity) entity); + return true; + } + // Paper end @@ -32,10 +24,10 @@ index 22266fda4de9b5fbace3b8e55ce390b8d7e75a65..fe7b71fbb3963beafe93a5d86bebdd62 return false; } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index 79f3e4176145c42debb9adc1e68175cf063c1f22..6269e37f2859417a80e6de16045f1c2325f9746f 100644 +index 6c55bd8b876d1d694e05ad6de6a9fd29a4d4d053..de4fdd46f23b2b17da752a8afc0faecc1ad8344f 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -6,6 +6,7 @@ import net.minecraft.world.InteractionResult; +@@ -7,6 +7,7 @@ import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.EquipmentSlot; @@ -43,7 +35,7 @@ index 79f3e4176145c42debb9adc1e68175cf063c1f22..6269e37f2859417a80e6de16045f1c23 import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.DoubleHighBlockItem; import net.minecraft.world.item.ItemStack; -@@ -418,10 +419,12 @@ public class ServerPlayerGameMode { +@@ -421,10 +422,12 @@ public class ServerPlayerGameMode { // return true; // CraftBukkit } // CraftBukkit start diff --git a/patches/server-remapped/0572-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server/0515-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch similarity index 78% rename from patches/server-remapped/0572-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch rename to patches/server/0515-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch index 07195903cb..50871e1554 100644 --- a/patches/server-remapped/0572-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch +++ b/patches/server/0515-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch @@ -5,13 +5,13 @@ Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086) diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 82205ad13ef0e987bd83979d06331545efe0a60a..50dc47e8c03ce274d558bc0dfa73ba3ab5fbae5c 100644 +index 1f67c9c5f7161ea687983e7ae0ec7d259da9acd3..0d8ddbc3f8aa22f16907613838ffb9a42f1e6de6 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -388,6 +388,7 @@ public class ChunkHolder { +@@ -246,6 +246,7 @@ public class ChunkHolder { } - public void blockChanged(BlockPos blockposition) { + public void blockChanged(BlockPos pos) { + if (!blockposition.isValidLocation()) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance diff --git a/patches/server-remapped/0573-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server/0516-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 82% rename from patches/server-remapped/0573-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to patches/server/0516-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch index 6eb1a44bc0..64a555e00d 100644 --- a/patches/server-remapped/0573-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ b/patches/server/0516-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/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d69981a1b5a40418c7d17de5f3bece30592ae586..fa22c0d7f676c96d34bf56d80181d6b047f2ff0b 100644 +index a9c90e41af1cc67a88a639dc795dd8023a7acb89..dac4585ba1bfc782b3e381dfba0a1b9abbb6a2d7 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -3476,4 +3476,10 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -3904,4 +3904,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n void accept(Entity entity, double x, double y, double z); } @@ -21,7 +21,7 @@ index d69981a1b5a40418c7d17de5f3bece30592ae586..fa22c0d7f676c96d34bf56d80181d6b0 + // 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 de5d02a1345f9886200f0540ac08be0df5878708..9a16882deee21faf78ea46e08b2f2ad3fbb6021b 100644 +index 1e387ba8552484b10ae276e1eea47d77d121e19d..2984f5fa036019bb35a603690c568fc5c7b855d6 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -443,6 +443,10 @@ public final class CraftMagicNumbers implements UnsafeValues { diff --git a/patches/server-remapped/0574-Lazily-track-plugin-scoreboards-by-default.patch b/patches/server/0517-Lazily-track-plugin-scoreboards-by-default.patch similarity index 84% rename from patches/server-remapped/0574-Lazily-track-plugin-scoreboards-by-default.patch rename to patches/server/0517-Lazily-track-plugin-scoreboards-by-default.patch index e06db589aa..76bcce754e 100644 --- a/patches/server-remapped/0574-Lazily-track-plugin-scoreboards-by-default.patch +++ b/patches/server/0517-Lazily-track-plugin-scoreboards-by-default.patch @@ -28,7 +28,7 @@ index 545948f20efd6c8dd42140b565af94cd6b52b661..7d50aded88f5b7dfebaea1aebc86231f + } } diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -index 4c93be31fd95d731327479519ecb34a08785c1ca..57537b8871dd5c54d97f3effe1802a3396644e46 100644 +index 68aa66c340b7a686a353e2a15084d811a3955a0a..b1fbbfeadb63d495b57f6c29b00de5327ca713cd 100644 --- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java +++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java @@ -18,6 +18,7 @@ import org.bukkit.scoreboard.Team; @@ -49,11 +49,11 @@ index 4c93be31fd95d731327479519ecb34a08785c1ca..57537b8871dd5c54d97f3effe1802a33 + registeredGlobally = true; + } + // Paper end - net.minecraft.world.scores.Objective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); + net.minecraft.world.scores.Objective objective = board.addObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); return new CraftObjective(this, objective); } -@@ -65,6 +72,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); +@@ -68,6 +75,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { + net.minecraft.world.scores.Objective objective = this.board.addObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); + // Paper start @@ -66,25 +66,26 @@ index 4c93be31fd95d731327479519ecb34a08785c1ca..57537b8871dd5c54d97f3effe1802a33 return new CraftObjective(this, objective);*/ // Paper return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -index 30b0d4986a7edcf324d94d9304d66d0567098855..8217e35f5a3093e63a165ee8c8b30bf3f28f3bd3 100644 +index ff090edcc85713083449cebb22bd1490123bc1ee..8ccfe9488db44d7d2cf4040a5b4cead33da1d5f4 100644 --- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java @@ -30,6 +30,7 @@ public final class CraftScoreboardManager implements ScoreboardManager { public CraftScoreboardManager(MinecraftServer minecraftserver, net.minecraft.world.scores.Scoreboard scoreboardServer) { - mainScoreboard = new CraftScoreboard(scoreboardServer); + this.mainScoreboard = new CraftScoreboard(scoreboardServer); + mainScoreboard.registeredGlobally = true; // Paper - server = minecraftserver; - scoreboards.add(mainScoreboard); + this.server = minecraftserver; + this.scoreboards.add(mainScoreboard); } @@ -43,10 +44,22 @@ public final class CraftScoreboardManager implements ScoreboardManager { public CraftScoreboard getNewScoreboard() { org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot - CraftScoreboard scoreboard = new CraftScoreboard(new ServerScoreboard(server)); + CraftScoreboard scoreboard = new CraftScoreboard(new ServerScoreboard(this.server)); +- this.scoreboards.add(scoreboard); + // Paper start + if (com.destroystokyo.paper.PaperConfig.trackPluginScoreboards) { + scoreboard.registeredGlobally = true; - scoreboards.add(scoreboard); ++ scoreboards.add(scoreboard); + } + // Paper end return scoreboard; @@ -99,4 +100,4 @@ index 30b0d4986a7edcf324d94d9304d66d0567098855..8217e35f5a3093e63a165ee8c8b30bf3 + // CraftBukkit method public CraftScoreboard getPlayerBoard(CraftPlayer player) { - CraftScoreboard board = playerBoards.get(player); + CraftScoreboard board = this.playerBoards.get(player); diff --git a/patches/server-remapped/0575-Entity-isTicking.patch b/patches/server/0518-Entity-isTicking.patch similarity index 75% rename from patches/server-remapped/0575-Entity-isTicking.patch rename to patches/server/0518-Entity-isTicking.patch index 22d5c7950d..544d8d71be 100644 --- a/patches/server-remapped/0575-Entity-isTicking.patch +++ b/patches/server/0518-Entity-isTicking.patch @@ -5,18 +5,18 @@ Subject: [PATCH] Entity#isTicking diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index fa22c0d7f676c96d34bf56d80181d6b047f2ff0b..a623c22cd03ad92657e661851fddc76a30986755 100644 +index dac4585ba1bfc782b3e381dfba0a1b9abbb6a2d7..7ecf78759ff7e3d64bb09306e55d54402a2d99a5 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -49,6 +49,7 @@ import net.minecraft.resources.ResourceLocation; +@@ -52,6 +52,7 @@ import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MCUtil; import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.TicketType; -@@ -3481,5 +3482,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -3909,5 +3910,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public static int nextEntityId() { return ENTITY_COUNTER.incrementAndGet(); } @@ -27,10 +27,10 @@ index fa22c0d7f676c96d34bf56d80181d6b047f2ff0b..a623c22cd03ad92657e661851fddc76a // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 1275768762884416fa3c68dab3a6671b24949976..502773ae60290125057fb342a3358ff55927d196 100644 +index 5d11d573a68bea7b341bb987b6cfb998bd1b74fb..b75a14a3af6c23128010f37f10cf78e477b72c4f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1159,5 +1159,9 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1193,5 +1193,9 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { public boolean isInLava() { return getHandle().isInLava(); } diff --git a/patches/server-remapped/0576-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/patches/server/0519-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch similarity index 86% rename from patches/server-remapped/0576-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch rename to patches/server/0519-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch index 2d6ec97910..79c9a69984 100644 --- a/patches/server-remapped/0576-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch +++ b/patches/server/0519-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix deop kicking non-whitelisted player when white list is diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 5c5903867432894b47bc62d89989f78c36a84ca1..954dce690852da87a37e7797c6f9f549242e511a 100644 +index dd51341115450a38ea5b0ea34dbadc2a8e191f60..9bd2255d31bcfd4574f8d1caf598f9141aa9e3c1 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2018,6 +2018,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop Date: Mon, 14 Jun 2021 17:10:25 +0200 Subject: [PATCH 115/226] fix compile issues --- ...isValidLocation-getType-and-getBlockData-fo.patch | 12 ++++++------ ...mark-dirty-in-invalid-locations-SPIGOT-6086.patch | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/patches/server/0069-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/patches/server/0069-Optimize-isValidLocation-getType-and-getBlockData-fo.patch index 6096bf4e20..19013eb221 100644 --- a/patches/server/0069-Optimize-isValidLocation-getType-and-getBlockData-fo.patch +++ b/patches/server/0069-Optimize-isValidLocation-getType-and-getBlockData-fo.patch @@ -13,7 +13,7 @@ Replace all calls to the new place to the unnecessary forward. Optimize getType and getBlockData to manually inline and optimize the calls diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java -index f4b5792e080d5181184eb661d005ce6cab649bf3..c66ae4d9eea993f3b7fcc6e253259db3346229d1 100644 +index f4b5792e080d5181184eb661d005ce6cab649bf3..35b26f4a4554541affbf76df38fed0f7e555c9b9 100644 --- a/src/main/java/net/minecraft/core/Vec3i.java +++ b/src/main/java/net/minecraft/core/Vec3i.java @@ -21,6 +21,15 @@ public class Vec3i implements Comparable { @@ -21,11 +21,11 @@ index f4b5792e080d5181184eb661d005ce6cab649bf3..c66ae4d9eea993f3b7fcc6e253259db3 private int z; + // Paper start -+ public boolean isValidLocation(net.minecraft.world.level.Level level) { -+ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && !level.isOutsideBuildHeight(getY()); ++ public boolean isValidLocation(net.minecraft.world.level.LevelHeightAccessor levelHeightAccessor) { ++ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && !levelHeightAccessor.isOutsideBuildHeight(getY()); + } -+ public boolean isInvalidYLocation(net.minecraft.world.level.Level level) { -+ return level.isOutsideBuildHeight(getY()); ++ public boolean isInvalidYLocation(net.minecraft.world.level.LevelHeightAccessor levelHeightAccessor) { ++ return levelHeightAccessor.isOutsideBuildHeight(getY()); + } + // Paper end + @@ -90,7 +90,7 @@ index c1beb6d5fc3cabfeacf0ffbf563e53ff7984c5d3..452b513e8b89d865a396066adaf4feb1 @Override public FluidState getFluidState(BlockPos pos) { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 9939c4c39549771afe971a6433dfd57e36050dd8..7e5e16fd61b39d2093459766e8aaa10bb05f6763 100644 +index b36a893ded952d1a5ed1a55eae9c3c406848e1f3..092f2cd5806e8609b952e7678c0c38b235c52264 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -337,12 +337,28 @@ public class LevelChunk implements ChunkAccess { diff --git a/patches/server/0515-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server/0515-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch index 50871e1554..6f969d64c5 100644 --- a/patches/server/0515-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch +++ b/patches/server/0515-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch @@ -5,14 +5,14 @@ Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086) diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 1f67c9c5f7161ea687983e7ae0ec7d259da9acd3..0d8ddbc3f8aa22f16907613838ffb9a42f1e6de6 100644 +index 1f67c9c5f7161ea687983e7ae0ec7d259da9acd3..1f5086a18b9c1c65dc2b09f44ed7c561ba96a847 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java @@ -246,6 +246,7 @@ public class ChunkHolder { } public void blockChanged(BlockPos pos) { -+ if (!blockposition.isValidLocation()) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks ++ if (!pos.isValidLocation(levelHeightAccessor)) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance if (chunk != null) { From 53081c6e5ff8078fdfd41276f6224da5f0dc303e Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 14 Jun 2021 17:17:08 +0200 Subject: [PATCH 116/226] even more compile fixes --- patches/server/0518-Entity-isTicking.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/server/0518-Entity-isTicking.patch b/patches/server/0518-Entity-isTicking.patch index 544d8d71be..cf77947417 100644 --- a/patches/server/0518-Entity-isTicking.patch +++ b/patches/server/0518-Entity-isTicking.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Entity#isTicking diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index dac4585ba1bfc782b3e381dfba0a1b9abbb6a2d7..7ecf78759ff7e3d64bb09306e55d54402a2d99a5 100644 +index dac4585ba1bfc782b3e381dfba0a1b9abbb6a2d7..d1199a166dfc88722e13dbdfeb86d9c89e7e8513 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -52,6 +52,7 @@ import net.minecraft.resources.ResourceKey; @@ -22,7 +22,7 @@ index dac4585ba1bfc782b3e381dfba0a1b9abbb6a2d7..7ecf78759ff7e3d64bb09306e55d5440 } + + public boolean isTicking() { -+ return ((ServerChunkCache) level.getChunkSource()).isInEntityTickingChunk(this); ++ return ((ServerChunkCache) level.getChunkSource()).isPositionTicking(this); + } // Paper end } From 18a839d265cfccddef565755e8763b3f4c903f4c Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Mon, 14 Jun 2021 08:19:29 -0700 Subject: [PATCH 117/226] fix no grav bee patch for world height changes --- .../0368-Bees-get-gravity-in-void.-Fixes-MC-167279.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/server/0368-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/0368-Bees-get-gravity-in-void.-Fixes-MC-167279.patch index d42a9033b2..aa3265d3af 100644 --- a/patches/server/0368-Bees-get-gravity-in-void.-Fixes-MC-167279.patch +++ b/patches/server/0368-Bees-get-gravity-in-void.-Fixes-MC-167279.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index f3ba4b26553915917c79f013ed9dd7c87d9f65a4..3d049e43c8ea85597e98e9dad61c8d4c49b01b1c 100644 +index f3ba4b26553915917c79f013ed9dd7c87d9f65a4..50724baf5eb207ce44be62509f9a024d9a0e10f3 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java @@ -143,7 +143,22 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @@ -21,7 +21,7 @@ index f3ba4b26553915917c79f013ed9dd7c87d9f65a4..3d049e43c8ea85597e98e9dad61c8d4c + + @Override + public void tick() { -+ if (this.mob.getY() <= 0) { ++ if (this.mob.getY() <= Bee.this.level.getMinBuildHeight()) { + this.mob.setNoGravity(false); + } + super.tick(); From 8cf470d6b193446ff695b4aed214c7944419e95f Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Mon, 14 Jun 2021 09:58:00 -0700 Subject: [PATCH 118/226] more patches --- ...docs-for-Entity.getEntitySpawnReason.patch | 6 +- .../0229-Villager-resetOffers.patch | 0 .../0230-Player-elytra-boost-API.patch | 4 +- ...-Add-getOfflinePlayerIfCached-String.patch | 4 +- .../0232-Add-ignore-discounts-API.patch | 0 .../0233-Item-no-age-no-player-pickup.patch | 0 ...0234-Beacon-API-custom-effect-ranges.patch | 0 .../0235-Add-API-for-quit-reason.patch | 0 .../0236-Add-Destroy-Speed-API.patch | 4 +- ...237-Add-LivingEntity-clearActiveItem.patch | 2 +- .../0238-Add-PlayerItemCooldownEvent.patch | 0 .../0239-More-lightning-API.patch | 0 ...tems-that-are-extra-from-a-crafting-.patch | 1 + ...ng-a-passenger-in-CreatureSpawnEvent.patch | 19 --- ...blockpos-allocation-from-pathfinding.patch | 28 ----- ...tem-locations-dropped-from-campfires.patch | 32 ----- ...589-Fixed-TileEntityBell-memory-leak.patch | 56 --------- ...0596-Beacon-API-custom-effect-ranges.patch | 90 -------------- .../0598-Seed-based-feature-search.patch | 115 ------------------ ...prove-performance-of-the-end-generat.patch | 77 ------------ ...ng-a-passenger-in-CreatureSpawnEvent.patch | 19 +++ ...eset-Ender-Crystals-on-Dragon-Spawn.patch} | 12 +- ...-large-move-vectors-crashing-server.patch} | 49 ++++---- .../0523-Optimise-getType-calls.patch} | 52 ++++---- .../0524-Villager-resetOffers.patch} | 16 +-- ...nig-for-some-hot-IBlockData-methods.patch} | 28 ++--- ...ce-order-when-capturing-blockstates.patch} | 4 +- ...blockpos-allocation-from-pathfinding.patch | 28 +++++ ...tem-locations-dropped-from-campfires.patch | 24 ++++ .../0529-Player-elytra-boost-API.patch} | 16 +-- ...530-Fixed-TileEntityBell-memory-leak.patch | 39 ++++++ ...ing-up-when-item-stack-is-empty-in-.patch} | 6 +- ...Add-getOfflinePlayerIfCached-String.patch} | 4 +- .../0533-Add-ignore-discounts-API.patch} | 38 +++--- ...Toggle-for-removing-existing-dragon.patch} | 28 +++-- ...x-client-lag-on-advancement-loading.patch} | 14 +-- .../0536-Item-no-age-no-player-pickup.patch} | 4 +- ...0537-Beacon-API-custom-effect-ranges.patch | 94 ++++++++++++++ .../0538-Add-API-for-quit-reason.patch} | 34 +++--- .../0539-Seed-based-feature-search.patch | 71 +++++++++++ ...ng-Trader-spawn-rate-config-options.patch} | 73 +++++------ ...prove-performance-of-the-end-generat.patch | 63 ++++++++++ .../0542-Expose-world-spawn-angle.patch} | 24 +--- .../0543-Add-Destroy-Speed-API.patch} | 4 +- ...-spawnParticle-x-y-z-precision-loss.patch} | 6 +- ...45-Add-LivingEntity-clearActiveItem.patch} | 6 +- .../0546-Add-PlayerItemCooldownEvent.patch} | 18 +-- .../0547-More-lightning-API.patch} | 42 +++---- ...should-not-bypass-cramming-gamerule.patch} | 66 +++++----- 49 files changed, 582 insertions(+), 738 deletions(-) rename patches/{api-unmapped => api}/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch (83%) rename patches/{api-unmapped => api}/0229-Villager-resetOffers.patch (100%) rename patches/{api-unmapped => api}/0230-Player-elytra-boost-API.patch (88%) rename patches/{api-unmapped => api}/0231-Add-getOfflinePlayerIfCached-String.patch (92%) rename patches/{api-unmapped => api}/0232-Add-ignore-discounts-API.patch (100%) rename patches/{api-unmapped => api}/0233-Item-no-age-no-player-pickup.patch (100%) rename patches/{api-unmapped => api}/0234-Beacon-API-custom-effect-ranges.patch (100%) rename patches/{api-unmapped => api}/0235-Add-API-for-quit-reason.patch (100%) rename patches/{api-unmapped => api}/0236-Add-Destroy-Speed-API.patch (90%) rename patches/{api-unmapped => api}/0237-Add-LivingEntity-clearActiveItem.patch (90%) rename patches/{api-unmapped => api}/0238-Add-PlayerItemCooldownEvent.patch (100%) rename patches/{api-unmapped => api}/0239-More-lightning-API.patch (100%) rename patches/{server-remapped => removed/1.17}/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch (95%) delete mode 100644 patches/server-remapped/0578-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch delete mode 100644 patches/server-remapped/0586-Reduce-blockpos-allocation-from-pathfinding.patch delete mode 100644 patches/server-remapped/0587-Fix-item-locations-dropped-from-campfires.patch delete mode 100644 patches/server-remapped/0589-Fixed-TileEntityBell-memory-leak.patch delete mode 100644 patches/server-remapped/0596-Beacon-API-custom-effect-ranges.patch delete mode 100644 patches/server-remapped/0598-Seed-based-feature-search.patch delete mode 100644 patches/server-remapped/0600-Significantly-improve-performance-of-the-end-generat.patch create mode 100644 patches/server/0520-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch rename patches/{server-remapped/0580-Reset-Ender-Crystals-on-Dragon-Spawn.patch => server/0521-Reset-Ender-Crystals-on-Dragon-Spawn.patch} (66%) rename patches/{server-remapped/0581-Fix-for-large-move-vectors-crashing-server.patch => server/0522-Fix-for-large-move-vectors-crashing-server.patch} (55%) rename patches/{server-remapped/0582-Optimise-getType-calls.patch => server/0523-Optimise-getType-calls.patch} (59%) rename patches/{server-remapped/0583-Villager-resetOffers.patch => server/0524-Villager-resetOffers.patch} (65%) rename patches/{server-remapped/0584-Improve-inlinig-for-some-hot-IBlockData-methods.patch => server/0525-Improve-inlinig-for-some-hot-IBlockData-methods.patch} (79%) rename patches/{server-remapped/0585-Retain-block-place-order-when-capturing-blockstates.patch => server/0526-Retain-block-place-order-when-capturing-blockstates.patch} (88%) create mode 100644 patches/server/0527-Reduce-blockpos-allocation-from-pathfinding.patch create mode 100644 patches/server/0528-Fix-item-locations-dropped-from-campfires.patch rename patches/{server-remapped/0588-Player-elytra-boost-API.patch => server/0529-Player-elytra-boost-API.patch} (60%) create mode 100644 patches/server/0530-Fixed-TileEntityBell-memory-leak.patch rename patches/{server-remapped/0590-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch => server/0531-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch} (93%) rename patches/{server-remapped/0591-Add-getOfflinePlayerIfCached-String.patch => server/0532-Add-getOfflinePlayerIfCached-String.patch} (88%) rename patches/{server-remapped/0592-Add-ignore-discounts-API.patch => server/0533-Add-ignore-discounts-API.patch} (78%) rename patches/{server-remapped/0593-Toggle-for-removing-existing-dragon.patch => server/0534-Toggle-for-removing-existing-dragon.patch} (59%) rename patches/{server-remapped/0594-Fix-client-lag-on-advancement-loading.patch => server/0535-Fix-client-lag-on-advancement-loading.patch} (81%) rename patches/{server-remapped/0595-Item-no-age-no-player-pickup.patch => server/0536-Item-no-age-no-player-pickup.patch} (90%) create mode 100644 patches/server/0537-Beacon-API-custom-effect-ranges.patch rename patches/{server-remapped/0597-Add-API-for-quit-reason.patch => server/0538-Add-API-for-quit-reason.patch} (58%) create mode 100644 patches/server/0539-Seed-based-feature-search.patch rename patches/{server-remapped/0599-Add-Wandering-Trader-spawn-rate-config-options.patch => server/0540-Add-Wandering-Trader-spawn-rate-config-options.patch} (56%) create mode 100644 patches/server/0541-Significantly-improve-performance-of-the-end-generat.patch rename patches/{server-remapped/0601-Expose-world-spawn-angle.patch => server/0542-Expose-world-spawn-angle.patch} (62%) rename patches/{server-remapped/0602-Add-Destroy-Speed-API.patch => server/0543-Add-Destroy-Speed-API.patch} (90%) rename patches/{server-remapped/0603-Fix-Player-spawnParticle-x-y-z-precision-loss.patch => server/0544-Fix-Player-spawnParticle-x-y-z-precision-loss.patch} (84%) rename patches/{server-remapped/0604-Add-LivingEntity-clearActiveItem.patch => server/0545-Add-LivingEntity-clearActiveItem.patch} (79%) rename patches/{server-remapped/0605-Add-PlayerItemCooldownEvent.patch => server/0546-Add-PlayerItemCooldownEvent.patch} (52%) rename patches/{server-remapped/0606-More-lightning-API.patch => server/0547-More-lightning-API.patch} (57%) rename patches/{server-remapped/0607-Climbing-should-not-bypass-cramming-gamerule.patch => server/0548-Climbing-should-not-bypass-cramming-gamerule.patch} (73%) diff --git a/patches/api-unmapped/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch b/patches/api/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch similarity index 83% rename from patches/api-unmapped/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch rename to patches/api/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch index 2947f78299..69ed86641c 100644 --- a/patches/api-unmapped/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch +++ b/patches/api/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Clarify the Javadocs for Entity.getEntitySpawnReason() diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 4ed8c74f874dbd1017764d7592acfdafbc5d5fe1..14470b23f7b4102cf2dca777bc832ebcbcd5edc6 100644 +index 8cfe08cbc869e468edc0f0bdaa28d5bf1f6201a2..a9e455c5b3bbe4edbdb71f86f5c6eebc2f605547 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -710,7 +710,7 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - Chunk getChunk(); +@@ -713,7 +713,7 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + } /** - * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity. diff --git a/patches/api-unmapped/0229-Villager-resetOffers.patch b/patches/api/0229-Villager-resetOffers.patch similarity index 100% rename from patches/api-unmapped/0229-Villager-resetOffers.patch rename to patches/api/0229-Villager-resetOffers.patch diff --git a/patches/api-unmapped/0230-Player-elytra-boost-API.patch b/patches/api/0230-Player-elytra-boost-API.patch similarity index 88% rename from patches/api-unmapped/0230-Player-elytra-boost-API.patch rename to patches/api/0230-Player-elytra-boost-API.patch index 1f9e683db7..f89408fba7 100644 --- a/patches/api-unmapped/0230-Player-elytra-boost-API.patch +++ b/patches/api/0230-Player-elytra-boost-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Player elytra boost API diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 828b2b0538d4f936bee57d9fca55774723e13970..7aa9fb852dce23c53fee80e97e0dcdb278ae82ba 100644 +index 6bc4f12e4ef35979c9d99273d14d7b31833d3f75..d281d270bba71da5a7d1326112e73d9cdb1ed57b 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1916,6 +1916,19 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1943,6 +1943,19 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM */ @NotNull T getClientOption(@NotNull ClientOption option); diff --git a/patches/api-unmapped/0231-Add-getOfflinePlayerIfCached-String.patch b/patches/api/0231-Add-getOfflinePlayerIfCached-String.patch similarity index 92% rename from patches/api-unmapped/0231-Add-getOfflinePlayerIfCached-String.patch rename to patches/api/0231-Add-getOfflinePlayerIfCached-String.patch index f39340e7f4..84d12a5906 100644 --- a/patches/api-unmapped/0231-Add-getOfflinePlayerIfCached-String.patch +++ b/patches/api/0231-Add-getOfflinePlayerIfCached-String.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add getOfflinePlayerIfCached(String) diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 3a930ee1b1dce3639d590a8646f68b4ab92207fb..a498c5267458767e1f7802ab3d3b7a22f987d985 100644 +index af0cf1fe3db1efd39bc06a89216413fc4415b007..bad4593447ca390b3e2f3bc71b4ea9f4dd673445 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -962,6 +962,27 @@ public final class Bukkit { @@ -37,7 +37,7 @@ index 3a930ee1b1dce3639d590a8646f68b4ab92207fb..a498c5267458767e1f7802ab3d3b7a22 * 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 9d8886526ae0cd31ec5771462f3cd57692b1cb53..bbc7a1a35da6c8c66c18779ba4fb1aca1a567e6f 100644 +index 64316a3bcba881f9366d9bf9e16b205e2b817707..48c6434a6a5b1659d4cc8ddf8fe23806628c3b7e 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -808,6 +808,25 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api-unmapped/0232-Add-ignore-discounts-API.patch b/patches/api/0232-Add-ignore-discounts-API.patch similarity index 100% rename from patches/api-unmapped/0232-Add-ignore-discounts-API.patch rename to patches/api/0232-Add-ignore-discounts-API.patch diff --git a/patches/api-unmapped/0233-Item-no-age-no-player-pickup.patch b/patches/api/0233-Item-no-age-no-player-pickup.patch similarity index 100% rename from patches/api-unmapped/0233-Item-no-age-no-player-pickup.patch rename to patches/api/0233-Item-no-age-no-player-pickup.patch diff --git a/patches/api-unmapped/0234-Beacon-API-custom-effect-ranges.patch b/patches/api/0234-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from patches/api-unmapped/0234-Beacon-API-custom-effect-ranges.patch rename to patches/api/0234-Beacon-API-custom-effect-ranges.patch diff --git a/patches/api-unmapped/0235-Add-API-for-quit-reason.patch b/patches/api/0235-Add-API-for-quit-reason.patch similarity index 100% rename from patches/api-unmapped/0235-Add-API-for-quit-reason.patch rename to patches/api/0235-Add-API-for-quit-reason.patch diff --git a/patches/api-unmapped/0236-Add-Destroy-Speed-API.patch b/patches/api/0236-Add-Destroy-Speed-API.patch similarity index 90% rename from patches/api-unmapped/0236-Add-Destroy-Speed-API.patch rename to patches/api/0236-Add-Destroy-Speed-API.patch index bdf3dd2bbe..1b87616b56 100644 --- a/patches/api-unmapped/0236-Add-Destroy-Speed-API.patch +++ b/patches/api/0236-Add-Destroy-Speed-API.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add Destroy Speed API Co-authored-by: Jake Potrebic diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index e6647c45f65bae916759cd899256f8130790d242..e4e3be0ee9c557e04d9ed1ab6f1569bd36a0e846 100644 +index 024deba760c41787190d20e4ac5c541920bb4991..e759a03ccf7b341db36f455879e0004a6d6d4d07 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java -@@ -592,5 +592,29 @@ public interface Block extends Metadatable { +@@ -618,5 +618,29 @@ public interface Block extends Metadatable { */ @NotNull String getTranslationKey(); diff --git a/patches/api-unmapped/0237-Add-LivingEntity-clearActiveItem.patch b/patches/api/0237-Add-LivingEntity-clearActiveItem.patch similarity index 90% rename from patches/api-unmapped/0237-Add-LivingEntity-clearActiveItem.patch rename to patches/api/0237-Add-LivingEntity-clearActiveItem.patch index bb5b5e0b5e..6f423cc936 100644 --- a/patches/api-unmapped/0237-Add-LivingEntity-clearActiveItem.patch +++ b/patches/api/0237-Add-LivingEntity-clearActiveItem.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add LivingEntity#clearActiveItem diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 9bf525b795ff1d88d2596b1f2bc787ce0df047bb..e535750d01a6c1bf4b1fe94df518166213da9b08 100644 +index c4fe44dce3bcb3502b26af7c76ec6b36c2a2bebe..b96b5f4f2fc754298e2223b2f449a0755469278c 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -766,6 +766,13 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api-unmapped/0238-Add-PlayerItemCooldownEvent.patch b/patches/api/0238-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from patches/api-unmapped/0238-Add-PlayerItemCooldownEvent.patch rename to patches/api/0238-Add-PlayerItemCooldownEvent.patch diff --git a/patches/api-unmapped/0239-More-lightning-API.patch b/patches/api/0239-More-lightning-API.patch similarity index 100% rename from patches/api-unmapped/0239-More-lightning-API.patch rename to patches/api/0239-More-lightning-API.patch diff --git a/patches/server-remapped/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch b/patches/removed/1.17/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch similarity index 95% rename from patches/server-remapped/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch rename to patches/removed/1.17/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch index 02442096a4..ed4a24b0df 100644 --- a/patches/server-remapped/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch +++ b/patches/removed/1.17/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch @@ -3,6 +3,7 @@ From: chickeneer Date: Wed, 18 Mar 2020 00:07:46 -0500 Subject: [PATCH] MC-147729: Drop items that are extra from a crafting recipe +1.17: Issue seems to be fixed (source: Mojira) diff --git a/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java b/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java index a18aa176850bef45afcaf5742e9afbfa39281e22..c6ba6aabf94c26cccbd14689ea32373c17bbccc4 100644 diff --git a/patches/server-remapped/0578-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/patches/server-remapped/0578-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch deleted file mode 100644 index d952b410f0..0000000000 --- a/patches/server-remapped/0578-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Sun, 4 Oct 2020 19:55:25 -0700 -Subject: [PATCH] Fix CME on adding a passenger in CreatureSpawnEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a623c22cd03ad92657e661851fddc76a30986755..90e9797cc1f3a4aa0a2bee28dca364e6f6dd0c0b 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -3180,7 +3180,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - public Stream getSelfAndPassengers() { -- return Stream.concat(Stream.of(this), this.passengers.stream().flatMap(Entity::getSelfAndPassengers)); -+ return Stream.concat(Stream.of(this), com.google.common.collect.ImmutableList.copyOf(this.passengers).stream().flatMap(Entity::getSelfAndPassengers)); // Paper - } - - public boolean hasOnePlayerPassenger() { diff --git a/patches/server-remapped/0586-Reduce-blockpos-allocation-from-pathfinding.patch b/patches/server-remapped/0586-Reduce-blockpos-allocation-from-pathfinding.patch deleted file mode 100644 index 9371d97aec..0000000000 --- a/patches/server-remapped/0586-Reduce-blockpos-allocation-from-pathfinding.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 25 Apr 2020 17:10:55 -0700 -Subject: [PATCH] Reduce blockpos allocation from pathfinding - - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java -index 7ae24381b91c282745b7fe5f6897865e74bc0acf..3c460682611969a5db136aa41ca0d230c6228d56 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java -@@ -498,7 +498,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { - return BlockPathTypes.DANGER_FIRE; - } - -- if (iblockaccess.getFluidState(blockposition_mutableblockposition).is((Tag) FluidTags.WATER)) { -+ if (iblockdata.getFluidState().is((Tag) FluidTags.WATER)) { // Paper - remove another getType call - return BlockPathTypes.WATER_BORDER; - } - } // Paper -@@ -528,7 +528,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { - } else if (iblockdata.is(Blocks.COCOA)) { - return BlockPathTypes.COCOA; - } else { -- FluidState fluid = iblockaccess.getFluidState(blockposition); -+ FluidState fluid = iblockdata.getFluidState(); // Paper - remove another get type call - - return fluid.is((Tag) FluidTags.WATER) ? BlockPathTypes.WATER : (fluid.is((Tag) FluidTags.LAVA) ? BlockPathTypes.LAVA : (isBurningBlock(iblockdata) ? BlockPathTypes.DAMAGE_FIRE : (DoorBlock.isWoodenDoor(iblockdata) && !(Boolean) iblockdata.getValue(DoorBlock.OPEN) ? BlockPathTypes.DOOR_WOOD_CLOSED : (block instanceof DoorBlock && material == Material.ORE && !(Boolean) iblockdata.getValue(DoorBlock.OPEN) ? BlockPathTypes.DOOR_IRON_CLOSED : (block instanceof DoorBlock && (Boolean) iblockdata.getValue(DoorBlock.OPEN) ? BlockPathTypes.DOOR_OPEN : (block instanceof BaseRailBlock ? BlockPathTypes.RAIL : (block instanceof LeavesBlock ? BlockPathTypes.LEAVES : (!block.is((Tag) BlockTags.FENCES) && !block.is((Tag) BlockTags.WALLS) && (!(block instanceof FenceGateBlock) || (Boolean) iblockdata.getValue(FenceGateBlock.OPEN)) ? (!iblockdata.isPathfindable(iblockaccess, blockposition, PathComputationType.LAND) ? BlockPathTypes.BLOCKED : BlockPathTypes.OPEN) : BlockPathTypes.FENCE)))))))); - } diff --git a/patches/server-remapped/0587-Fix-item-locations-dropped-from-campfires.patch b/patches/server-remapped/0587-Fix-item-locations-dropped-from-campfires.patch deleted file mode 100644 index 535e3ffd30..0000000000 --- a/patches/server-remapped/0587-Fix-item-locations-dropped-from-campfires.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 20:32:25 -0500 -Subject: [PATCH] Fix item locations dropped from campfires - -Fixes #4259 by not flooring the blockposition among other weirdness - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -index 0c90b1b13611843ba4402c8ccf0b15781b85e773..6c38361d744eae763b6c131ad314485f5a88fcfc 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -@@ -14,6 +14,7 @@ import net.minecraft.world.Clearable; - import net.minecraft.world.ContainerHelper; - import net.minecraft.world.Containers; - import net.minecraft.world.SimpleContainer; -+import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.crafting.CampfireCookingRecipe; - import net.minecraft.world.item.crafting.RecipeType; -@@ -91,7 +92,11 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable, Ticka - result = blockCookEvent.getResult(); - itemstack1 = CraftItemStack.asNMSCopy(result); - // CraftBukkit end -- Containers.dropItemStack(this.level, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack1); -+ // Paper start -+ ItemEntity droppedItem = new ItemEntity(this.level, blockposition.getX() + 0.5D, blockposition.getY() + 0.5D, blockposition.getZ() + 0.5D, itemstack1.split(this.level.random.nextInt(21) + 10)); -+ droppedItem.setDeltaMovement(this.level.random.nextGaussian() * 0.05D, this.level.random.nextGaussian() * 0.05D + 0.2D, this.level.random.nextGaussian() * 0.05D); -+ this.level.addFreshEntity(droppedItem); -+ // Paper end - this.items.set(i, ItemStack.EMPTY); - this.markUpdated(); - } diff --git a/patches/server-remapped/0589-Fixed-TileEntityBell-memory-leak.patch b/patches/server-remapped/0589-Fixed-TileEntityBell-memory-leak.patch deleted file mode 100644 index de814154fd..0000000000 --- a/patches/server-remapped/0589-Fixed-TileEntityBell-memory-leak.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: giacomo <32515303+giacomozama@users.noreply.github.com> -Date: Sat, 10 Oct 2020 12:15:33 +0200 -Subject: [PATCH] Fixed TileEntityBell memory leak - -TileEntityBell has a list of entities (entitiesAtRing) that was not being cleared at the right time, causing leaks whenever a bell would be rung near a crowd of entities. - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java -index aa45a142aa11acc9fd08b4877891741f3cbd936d..3f9179a7678091875161a34d13b6ec0e78025c4c 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java -@@ -27,8 +27,8 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity - public int ticks; - public boolean shaking; - public Direction clickDirection; -- private List nearbyEntities; -- private boolean resonating; -+ private List nearbyEntities; private List getEntitiesAtRing() { return this.nearbyEntities; } // Paper - OBFHELPER -+ private boolean resonating; private boolean getShouldReveal() { return this.resonating; } // Paper - OBFHELPER - private int resonationTicks; - - public BellBlockEntity() { -@@ -57,6 +57,11 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity - - if (this.ticks >= 50) { - this.shaking = false; -+ // Paper start -+ if (!this.getShouldReveal()) { -+ this.getEntitiesAtRing().clear(); -+ } -+ // Paper end - this.ticks = 0; - } - -@@ -71,6 +76,7 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity - } else { - this.makeRaidersGlow(this.level); - this.showBellParticles(this.level); -+ this.getEntitiesAtRing().clear(); // Paper - this.resonating = false; - } - } -@@ -111,11 +117,12 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity - LivingEntity entityliving = (LivingEntity) iterator.next(); - - if (entityliving.isAlive() && !entityliving.removed && blockposition.closerThan((Position) entityliving.position(), 32.0D)) { -- entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, (Object) this.level.getGameTime()); -+ entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.level.getGameTime()); // Paper - decompile fix - } - } - } - -+ this.getEntitiesAtRing().removeIf(e -> !e.isAlive()); // Paper - } - - private boolean areRaidersNearby() { diff --git a/patches/server-remapped/0596-Beacon-API-custom-effect-ranges.patch b/patches/server-remapped/0596-Beacon-API-custom-effect-ranges.patch deleted file mode 100644 index 78d729cb3e..0000000000 --- a/patches/server-remapped/0596-Beacon-API-custom-effect-ranges.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 12:39:08 -0600 -Subject: [PATCH] Beacon API - custom effect ranges - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -index 5f75c6d653a31f65fcf9c0e280d796e15d059c00..fed29e5707e2a7f64159d284c52647dd91e1948e 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -@@ -71,6 +71,26 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - return (hasSecondaryEffect()) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, getLevelCb(), getAmplification(), true, true)) : null; - } - // CraftBukkit end -+ // Paper start - add field/methods for custom range -+ private final String PAPER_RANGE_TAG = "Paper.Range"; -+ private double effectRange = -1; -+ -+ public double getEffectRange() { -+ if (this.effectRange < 0) { -+ return this.levels * 10 + 10; -+ } else { -+ return effectRange; -+ } -+ } -+ -+ public void setEffectRange(double range) { -+ this.effectRange = range; -+ } -+ -+ public void resetEffectRange() { -+ this.effectRange = -1; -+ } -+ // Paper end - - public BeaconBlockEntity() { - super(BlockEntityType.BEACON); -@@ -261,7 +281,8 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - - public List getHumansInRange() { - { -- double d0 = (double) (this.levels * 10 + 10); -+ // Paper - custom beacon ranges -+ double d0 = this.getEffectRange(); - - AABB axisalignedbb = (new AABB(this.worldPosition)).inflate(d0).expandTowards(0.0D, (double) this.level.getMaxBuildHeight(), 0.0D); - List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.player.Player.class, axisalignedbb); -@@ -361,6 +382,9 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - this.secondaryPower = MobEffect.byId(tag.getInt("Secondary")); - this.levels = tag.getInt("Levels"); // SPIGOT-5053, use where available - // CraftBukkit end -+ // Paper -+ this.effectRange = tag.contains(PAPER_RANGE_TAG, 6) ? tag.getDouble(PAPER_RANGE_TAG) : -1; -+ - if (tag.contains("CustomName", 8)) { - this.name = Component.Serializer.fromJson(tag.getString("CustomName")); - } -@@ -377,6 +401,8 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - if (this.name != null) { - tag.putString("CustomName", Component.Serializer.toJson(this.name)); - } -+ // Paper -+ tag.putDouble(PAPER_RANGE_TAG, this.effectRange); - - this.lockKey.addToTag(tag); - return tag; -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -index 940fef58f14e06213c7f305f67dcb8918976c03d..2a10a9352fdb52f5cb27eae2b6d3baa9ff95e486 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -@@ -108,4 +108,19 @@ public class CraftBeacon extends CraftBlockEntityState implem - public void setLock(String key) { - this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key); - } -+ -+ @Override -+ public double getEffectRange() { -+ return this.getSnapshot().getEffectRange(); -+ } -+ -+ @Override -+ public void setEffectRange(double range) { -+ this.getSnapshot().setEffectRange(range); -+ } -+ -+ @Override -+ public void resetEffectRange() { -+ this.getSnapshot().resetEffectRange(); -+ } - } diff --git a/patches/server-remapped/0598-Seed-based-feature-search.patch b/patches/server-remapped/0598-Seed-based-feature-search.patch deleted file mode 100644 index 40529ba82f..0000000000 --- a/patches/server-remapped/0598-Seed-based-feature-search.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Mon, 13 Jan 2020 15:40:32 +0100 -Subject: [PATCH] Seed based feature search - -This tries to work around the issue where the server will load -surrounding chunks up to a radius of 100 chunks in order to search for -features e.g. when running the /locate command or for treasure maps -(issue #2312). -This is done by backporting Mojang's change in 1.17 which makes it so -that the biome (generated by the seed) is checked first if the feature -can be generated before actually to load the chunk. - -Additionally to that the center location of the target chunk is simply -returned if the chunk is not loaded to avoid the sync chunk load. -As this can lead to less precise locations a toggle is provided to -enable the sync loading of the target chunk again. - -The main downside of this is that it breaks once the seed or generator -changes but this should usually not happen. A config option to disable -this completely is added though in case that should ever be necessary. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 424754a0183b071d20c86f0420cec784a8992e2b..97870622e41cca36d9c7493bfad796f35f3831f4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -337,6 +337,14 @@ public class PaperWorldConfig { - } - } - -+ public boolean seedBasedFeatureSearch = true; -+ public boolean seedBasedFeatureSearchLoadsChunks = false; -+ private void seedBasedFeatureSearch() { -+ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch); -+ seedBasedFeatureSearchLoadsChunks = getBoolean("seed-based-feature-search-loads-chunks", seedBasedFeatureSearchLoadsChunks); -+ log("Feature search is based on seed: " + seedBasedFeatureSearch + ", loads chunks:" + seedBasedFeatureSearchLoadsChunks); -+ } -+ - public int maxCollisionsPerEntity; - private void maxEntityCollision() { - maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); -diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java -index 4a5f318adf5bc2ca1c3fab5d173a99cddd77ab85..f61a3eda40328922b95f166be4dc604500e000be 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkPos.java -+++ b/src/main/java/net/minecraft/world/level/ChunkPos.java -@@ -68,10 +68,12 @@ public class ChunkPos { - } - } - -+ public int getBlockX() { return getMinBlockX(); } // Paper - OBFHELPER - public int getMinBlockX() { - return this.x << 4; - } - -+ public int getBlockZ() { return getMinBlockZ(); } // Paper - OBFHELPER - public int getMinBlockZ() { - return this.z << 4; - } -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 2ad8a4558aa812885adebee8c05dab45f2bf5f90..066d5f7ee93351bff67c0d39ee9d940ac51515d8 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1511,8 +1511,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return this.profiler; - } - -- @Override -- public BiomeManager getBiomeManager() { -+ public BiomeManager getBiomeManager() { return getBiomeManager(); } // Paper - OBFHELPER -+ @Override public BiomeManager getBiomeManager() { - return this.biomeManager; - } - -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -index d22ac114440d807a6cf5f286961bc63935fa7823..3a1909c0b198d89539f4351d70a39d16cfd84987 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -@@ -23,6 +23,7 @@ public class BiomeManager { - return new BiomeManager(source, this.biomeZoomSeed, this.zoomer); - } - -+ public Biome getBiome(BlockPos blockposition) { return getBiome(blockposition); } // Paper - OBFHELPER - public Biome getBiome(BlockPos pos) { - return this.zoomer.getBiome(this.biomeZoomSeed, pos.getX(), pos.getY(), pos.getZ(), this.noiseBiomeSource); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -index 0624b8270bc28c83c5479cd51fa4633ed5c36f44..6b24590a1ac460a7fd4bbc2c70d4a4981378e79c 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java -@@ -176,7 +176,24 @@ public abstract class StructureFeature { - int j2 = i1 + k * l1; - ChunkPos chunkcoordintpair = this.getPotentialFeatureChunk(config, worldSeed, seededrandom, i2, j2); - if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper -- ChunkAccess ichunkaccess = world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); -+ // Paper start - seed based feature search -+ ChunkAccess ichunkaccess = null; -+ if (structureAccessor.getWorld().paperConfig.seedBasedFeatureSearch) { -+ Biome biomeBase = structureAccessor.getWorld().getBiomeManager().getBiome(new BlockPos(chunkcoordintpair.getBlockX() + 9, 0, chunkcoordintpair.getBlockZ() + 9)); -+ if (!biomeBase.getGenerationSettings().isValidStart(this)) { -+ continue; -+ } -+ if (!structureAccessor.getWorld().paperConfig.seedBasedFeatureSearchLoadsChunks) { -+ ichunkaccess = structureAccessor.getWorld().getChunkIfLoaded(chunkcoordintpair.x, chunkcoordintpair.z); -+ if (ichunkaccess == null) { -+ return chunkcoordintpair.asPosition().add(8, searchStartPos.getY(), 8); -+ } -+ } -+ } -+ if (ichunkaccess == null) { -+ ichunkaccess = world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); -+ } -+ // Paper end - StructureStart structurestart = structureAccessor.getStartForFeature(SectionPos.of(ichunkaccess.getPos(), 0), this, ichunkaccess); - - if (structurestart != null && structurestart.e()) { diff --git a/patches/server-remapped/0600-Significantly-improve-performance-of-the-end-generat.patch b/patches/server-remapped/0600-Significantly-improve-performance-of-the-end-generat.patch deleted file mode 100644 index 22a13c79b6..0000000000 --- a/patches/server-remapped/0600-Significantly-improve-performance-of-the-end-generat.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com> -Date: Tue, 3 Nov 2020 23:48:05 -0600 -Subject: [PATCH] Significantly improve performance of the end generation - -This patch implements a noise cache for the end which significantly reduces the computation time of generation. This results in about a 3x improvement. - -Original code by SuperCoder7979 and Gegy in Lithium, licensed under LGPL-3.0 (Source: https://github.com/jellysquid3/lithium-fabric) - -Co-authored-by: Gegy -Co-authored-by: Dylan Xaldin -Co-authored-by: pop4959 - -diff --git a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java -index 063369d3a64b4afc9cc6e1d20360900595e1a05f..f01d1b01ebc31f0967a73871f278aac9e414fb67 100644 ---- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java -+++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java -@@ -3,10 +3,12 @@ package net.minecraft.world.level.biome; - import com.google.common.collect.ImmutableList; - import com.mojang.serialization.Codec; - import com.mojang.serialization.codecs.RecordCodecBuilder; -+import it.unimi.dsi.fastutil.HashCommon; // Paper - import java.util.List; - import net.minecraft.core.Registry; - import net.minecraft.resources.RegistryLookupCodec; - import net.minecraft.util.Mth; -+import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.levelgen.WorldgenRandom; - import net.minecraft.world.level.levelgen.synth.SimplexNoise; - -@@ -27,6 +29,16 @@ public class TheEndBiomeSource extends BiomeSource { - private final Biome midlands; - private final Biome islands; - private final Biome barrens; -+ // Paper start -+ private static final class NoiseCache { -+ public long[] keys = new long[8192]; -+ public float[] values = new float[8192]; -+ public NoiseCache() { -+ java.util.Arrays.fill(keys, Long.MIN_VALUE); -+ } -+ } -+ private static final ThreadLocal> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new); -+ // Paper end - - public TheEndBiomeSource(Registry biomeRegistry, long seed) { - this(biomeRegistry, seed, (Biome) biomeRegistry.lifecycle(Biomes.THE_END), (Biome) biomeRegistry.lifecycle(Biomes.END_HIGHLANDS), (Biome) biomeRegistry.lifecycle(Biomes.END_MIDLANDS), (Biome) biomeRegistry.lifecycle(Biomes.SMALL_END_ISLANDS), (Biome) biomeRegistry.lifecycle(Biomes.END_BARRENS)); -@@ -81,13 +93,27 @@ public class TheEndBiomeSource extends BiomeSource { - - f = Mth.clamp(f, -100.0F, 80.0F); - -+ NoiseCache cache = noiseCache.get().computeIfAbsent(noisegenerator3handler, m -> new NoiseCache()); // Paper - for (int k1 = -12; k1 <= 12; ++k1) { - for (int l1 = -12; l1 <= 12; ++l1) { - long i2 = (long) (k + k1); - long j2 = (long) (l + l1); - -- if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.getValue((double) i2, (double) j2) < -0.8999999761581421D) { -- float f1 = (Mth.abs((float) i2) * 3439.0F + Mth.abs((float) j2) * 147.0F) % 13.0F + 9.0F; -+ // Paper start - Significantly improve end generation performance by using a noise cache -+ long key = ChunkPos.asLong((int) i2, (int) j2); -+ int index = (int) HashCommon.mix(key) & 8191; -+ float f1 = Float.MIN_VALUE; -+ if (cache.keys[index] == key) { -+ f1 = cache.values[index]; -+ } else { -+ if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.getValue((double) i2, (double) j2) < -0.8999999761581421D) { -+ f1 = (Mth.abs((float) i2) * 3439.0F + Mth.abs((float) j2) * 147.0F) % 13.0F + 9.0F; -+ } -+ cache.keys[index] = key; -+ cache.values[index] = f1; -+ } -+ if (f1 != Float.MIN_VALUE) { -+ // Paper end - float f2 = (float) (i1 - k1 * 2); - float f3 = (float) (j1 - l1 * 2); - float f4 = 100.0F - Mth.sqrt(f2 * f2 + f3 * f3) * f1; diff --git a/patches/server/0520-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/patches/server/0520-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch new file mode 100644 index 0000000000..c2938746f9 --- /dev/null +++ b/patches/server/0520-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Sun, 4 Oct 2020 19:55:25 -0700 +Subject: [PATCH] Fix CME on adding a passenger in CreatureSpawnEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index d1199a166dfc88722e13dbdfeb86d9c89e7e8513..d64caca72a5302392df944d4c60ed2ba79a19ee7 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -3413,7 +3413,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + } + + private Stream getIndirectPassengersStream() { +- return this.passengers.stream().flatMap(Entity::getSelfAndPassengers); ++ return ImmutableList.copyOf(this.passengers).stream().flatMap(Entity::getSelfAndPassengers); // Paper + } + + @Override diff --git a/patches/server-remapped/0580-Reset-Ender-Crystals-on-Dragon-Spawn.patch b/patches/server/0521-Reset-Ender-Crystals-on-Dragon-Spawn.patch similarity index 66% rename from patches/server-remapped/0580-Reset-Ender-Crystals-on-Dragon-Spawn.patch rename to patches/server/0521-Reset-Ender-Crystals-on-Dragon-Spawn.patch index 0fa89bf211..c91bcad15a 100644 --- a/patches/server-remapped/0580-Reset-Ender-Crystals-on-Dragon-Spawn.patch +++ b/patches/server/0521-Reset-Ender-Crystals-on-Dragon-Spawn.patch @@ -11,14 +11,14 @@ This ensures the crystals/pillars are in expected state when the dragon spawns. See #3522 diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 4b18931225ef60dbcffd7fcc20d0e9ce62348a07..590df3b93b897613cad74f9920aec62b33a2f7f7 100644 +index 711be01abe9d47bdc9bfe8b09a2719d666b986fb..9899c70b88fc371963e33caccd7125ef8c333df4 100644 --- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -441,6 +441,7 @@ public class EndDragonFight { - entityenderdragon.moveTo(0.0D, 128.0D, 0.0D, this.level.random.nextFloat() * 360.0F, 0.0F); - this.level.addFreshEntity(entityenderdragon); - this.dragonUUID = entityenderdragon.getUUID(); +@@ -404,6 +404,7 @@ public class EndDragonFight { + enderDragon.moveTo(0.0D, 128.0D, 0.0D, this.level.random.nextFloat() * 360.0F, 0.0F); + this.level.addFreshEntity(enderDragon); + this.dragonUUID = enderDragon.getUUID(); + this.resetSpikeCrystals(); // Paper - return entityenderdragon; + return enderDragon; } diff --git a/patches/server-remapped/0581-Fix-for-large-move-vectors-crashing-server.patch b/patches/server/0522-Fix-for-large-move-vectors-crashing-server.patch similarity index 55% rename from patches/server-remapped/0581-Fix-for-large-move-vectors-crashing-server.patch rename to patches/server/0522-Fix-for-large-move-vectors-crashing-server.patch index 42d90f77ee..6aa61b9e81 100644 --- a/patches/server-remapped/0581-Fix-for-large-move-vectors-crashing-server.patch +++ b/patches/server/0522-Fix-for-large-move-vectors-crashing-server.patch @@ -6,27 +6,27 @@ Subject: [PATCH] Fix for large move vectors crashing server Check movement distance also based on current position. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ab45497e8f7720c9d60626b32e9c95779af676b0..3a114bec14fcc6c1e1045e2b99178a6adb25f387 100644 +index e3725db7e19fe3235ec25beffca26a7eede24394..0e0d6d298caa1bbb6fb0dd42fd00460f7609c431 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -516,19 +516,24 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -507,19 +507,24 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) { ServerLevel worldserver = this.player.getLevel(); - double d0 = entity.getX(); - double d1 = entity.getY(); - double d2 = entity.getZ(); -- double d3 = packet.getX(); -- double d4 = packet.getY(); -- double d5 = packet.getZ(); -+ double d0 = entity.getX();double fromX = d0; // Paper - OBFHELPER -+ double d1 = entity.getY();double fromY = d1; // Paper - OBFHELPER -+ double d2 = entity.getZ();double fromZ = d2; // Paper - OBFHELPER -+ double d3 = packet.getX();double toX = d3; // Paper - OBFHELPER -+ double d4 = packet.getY();double toY = d4; // Paper - OBFHELPER -+ double d5 = packet.getZ();double toZ = d5; // Paper - OBFHELPER - float f = packet.getYRot(); - float f1 = packet.getXRot(); +- double d3 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX()); +- double d4 = ServerGamePacketListenerImpl.clampVertical(packet.getY()); +- double d5 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ()); ++ double d0 = entity.getX();final double fromX = d0; // Paper - OBFHELPER ++ double d1 = entity.getY();final double fromY = d1; // Paper - OBFHELPER ++ double d2 = entity.getZ();final double fromZ = d2; // Paper - OBFHELPER ++ double d3 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX());final double toX = d3; // Paper - OBFHELPER ++ double d4 = ServerGamePacketListenerImpl.clampVertical(packet.getY());final double toY = d4; // Paper - OBFHELPER ++ double d5 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ());final double toZ = d5; // Paper - OBFHELPER + float f = Mth.wrapDegrees(packet.getYRot()); + float f1 = Mth.wrapDegrees(packet.getXRot()); double d6 = d3 - this.vehicleFirstGoodX; double d7 = d4 - this.vehicleFirstGoodY; double d8 = d5 - this.vehicleFirstGoodZ; @@ -41,18 +41,17 @@ index ab45497e8f7720c9d60626b32e9c95779af676b0..3a114bec14fcc6c1e1045e2b99178a6a // CraftBukkit start - handle custom speeds and skipped ticks -@@ -1230,7 +1235,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - double d2 = this.player.getZ(); - double d3 = this.player.getY(); - double d4 = packet.getX(this.player.getX());double toX = d4; // Paper - OBFHELPER -- double d5 = packet.getY(this.player.getY()); -+ double d5 = packet.getY(this.player.getY());double toY = d5; // Paper - OBFHELPER - double d6 = packet.getZ(this.player.getZ());double toZ = d6; // Paper - OBFHELPER - float f = packet.getYRot(this.player.yRot); - float f1 = packet.getXRot(this.player.xRot); -@@ -1238,7 +1243,12 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - double d8 = d5 - this.firstGoodY; - double d9 = d6 - this.firstGoodZ; +@@ -1252,14 +1257,19 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + float prevPitch = this.player.getXRot(); + // CraftBukkit end + double d3 = this.player.getX(); final double toX = d3; // Paper - OBFHELPER +- double d4 = this.player.getY(); ++ double d4 = this.player.getY(); final double toY = d4; // Paper - OBFHELPER + double d5 = this.player.getZ(); final double toZ = d5; // Paper - OBFHELPER + double d6 = this.player.getY(); + double d7 = d0 - this.firstGoodX; + double d8 = d1 - this.firstGoodY; + double d9 = d2 - this.firstGoodZ; double d10 = this.player.getDeltaMovement().lengthSqr(); - double d11 = d7 * d7 + d8 * d8 + d9 * d9; + // Paper start - fix large move vectors killing the server diff --git a/patches/server-remapped/0582-Optimise-getType-calls.patch b/patches/server/0523-Optimise-getType-calls.patch similarity index 59% rename from patches/server-remapped/0582-Optimise-getType-calls.patch rename to patches/server/0523-Optimise-getType-calls.patch index f1103a3993..714fa391ab 100644 --- a/patches/server-remapped/0582-Optimise-getType-calls.patch +++ b/patches/server/0523-Optimise-getType-calls.patch @@ -6,14 +6,13 @@ Subject: [PATCH] Optimise getType calls Remove the map lookup for converting from Block->Bukkit Material diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockState.java b/src/main/java/net/minecraft/world/level/block/state/BlockState.java -index 9958cdf55cef2177fafd0cdae48da9db064af9f1..4263ac345d57e36e010e3dd009130c02799b249c 100644 +index 3581aa7dcba934017896dc947adeb9d548d5f333..6158ef624ddbf02179afcc4aebc8284ae326ffb1 100644 --- a/src/main/java/net/minecraft/world/level/block/state/BlockState.java +++ b/src/main/java/net/minecraft/world/level/block/state/BlockState.java -@@ -11,6 +11,19 @@ public class BlockState extends BlockBehaviour.BlockStateBase { +@@ -10,6 +10,17 @@ import net.minecraft.world.level.block.state.properties.Property; + public class BlockState extends BlockBehaviour.BlockStateBase { + public static final Codec CODEC = codec(Registry.BLOCK, Block::defaultBlockState).stable(); - public static final Codec CODEC = codec((Codec) Registry.BLOCK, Block::defaultBlockState).stable(); - -+ + // Paper start - optimise getType calls + org.bukkit.Material cachedMaterial; + @@ -25,72 +24,71 @@ index 9958cdf55cef2177fafd0cdae48da9db064af9f1..4263ac345d57e36e010e3dd009130c02 + return this.cachedMaterial; + } + // Paper end - optimise getType calls -+ - public BlockState(Block block, ImmutableMap, Comparable> propertyMap, MapCodec mapcodec) { - super(block, propertyMap, mapcodec); + public BlockState(Block block, ImmutableMap, Comparable> propertyMap, MapCodec codec) { + super(block, propertyMap, codec); } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -index fe00c8fdacc28a68c732aac0b887ea107d87e979..227974a85a81c623311301e28e83e85424b05f3d 100644 +index e2e6652fc227173b69580dba74855c3ed8884a3b..2c23712aadfe32439ae014c62aa16f1b2a677439 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -@@ -78,7 +78,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot { +@@ -81,7 +81,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot { public Material getBlockType(int x, int y, int z) { - CraftChunk.validateChunkCoordinates(x, y, z); + this.validateChunkCoordinates(x, y, z); -- return CraftMagicNumbers.getMaterial(blockids[y >> 4].get(x, y & 0xF, z).getBlock()); -+ return blockids[y >> 4].get(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls +- return CraftMagicNumbers.getMaterial(this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBlock()); ++ return this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls } @Override diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index e09f65f0b06c8fb9a965b921c2c8e68ae2ac1e55..37eceaef1212e2ee13aa763a5ede24ec170e5391 100644 +index b31eaa1459690d7f54989ba7a01f96a3f0d8d3b9..aa81c0a4c02fd6f2ab900983fd8c9668fada802e 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -211,7 +211,7 @@ public class CraftBlock implements Block { +@@ -214,7 +214,7 @@ public class CraftBlock implements Block { @Override public Material getType() { -- return CraftMagicNumbers.getMaterial(world.getBlockState(position).getBlock()); -+ return world.getBlockState(position).getBukkitMaterial(); // Paper - optimise getType calls +- return CraftMagicNumbers.getMaterial(this.world.getBlockState(position).getBlock()); ++ return this.world.getBlockState(this.position).getBukkitMaterial(); // Paper - optimise getType calls } @Override diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -index 754559c9e47032845fdc94eedad0cece0e0ae4c7..7e4c522605cf04a38a7a0f54e7ac6ea0e372c98d 100644 +index efc6cbe905b982ab39a12bd137f1dc0515a7c46a..3c41d80b0ffca929abfcb45cd1dedbc0bf3f5954 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java @@ -134,7 +134,7 @@ public class CraftBlockState implements BlockState { @Override public Material getType() { -- return CraftMagicNumbers.getMaterial(data.getBlock()); -+ return data.getBukkitMaterial(); // Paper - optimise getType calls +- return CraftMagicNumbers.getMaterial(this.data.getBlock()); ++ return this.data.getBukkitMaterial(); // Paper - optimise getType calls } public void setFlag(int flag) { diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -index 03e065bf92cafd376ad0f878584cdac6fd196245..d93f2373f3127462aa2f9b69f7cc808b58d47b61 100644 +index 6dc8f9f269db6971b8b46819e017357899ccd118..7f49c7c7048b5778f20ddce1d844d4b389e6597f 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java @@ -45,7 +45,7 @@ public class CraftBlockData implements BlockData { @Override public Material getMaterial() { -- return CraftMagicNumbers.getMaterial(state.getBlock()); -+ return state.getBukkitMaterial(); // Paper - optimise getType calls +- return CraftMagicNumbers.getMaterial(this.state.getBlock()); ++ return this.state.getBukkitMaterial(); // Paper - optimise getType calls } public BlockState getState() { diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index fd2cb2a584fea360fcf8180338708f35c4e3dc1f..a463b89888460e5a894098c20eb4c4a78c04642c 100644 +index 2f0849dd05605e693dcc12c3d0842e8dfa53a869..612241ad511cb515fe28c69452c66efcfe62bd7e 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -73,7 +73,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { +@@ -75,7 +75,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { @Override public Material getType(int x, int y, int z) { -- return CraftMagicNumbers.getMaterial(getTypeId(x, y, z).getBlock()); -+ return getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls +- return CraftMagicNumbers.getMaterial(this.getTypeId(x, y, z).getBlock()); ++ return this.getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls } @Override diff --git a/patches/server-remapped/0583-Villager-resetOffers.patch b/patches/server/0524-Villager-resetOffers.patch similarity index 65% rename from patches/server-remapped/0583-Villager-resetOffers.patch rename to patches/server/0524-Villager-resetOffers.patch index 2d03e1410f..d82060745c 100644 --- a/patches/server-remapped/0583-Villager-resetOffers.patch +++ b/patches/server/0524-Villager-resetOffers.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Villager#resetOffers diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -index 9eee68a5a84e121698d26bd54212a72c75e16251..407a68edf6408400f1a6c5bb1a6cbbfae08ac2cd 100644 +index ab701d86b1181e30d74e0e03eef79c43f7fb2513..2610d9cd849aa38cc7a67aef21223707e85682ec 100644 --- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -111,6 +111,13 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan +@@ -115,6 +115,13 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa return this.tradingPlayer != null; } @@ -22,21 +22,13 @@ index 9eee68a5a84e121698d26bd54212a72c75e16251..407a68edf6408400f1a6c5bb1a6cbbfa @Override public MerchantOffers getOffers() { if (this.offers == null) { -@@ -232,6 +239,7 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan - return this.level; - } - -+ protected final void updateTrades() { updateTrades(); } // Paper - OBFHELPER - protected abstract void updateTrades(); - - protected void addOffersFromItemListings(MerchantOffers recipeList, VillagerTrades.ItemListing[] pool, int count) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -index 8ffdfe3e8229b556838eab18dcb6bfb0c05a6063..7f887e883a87f2df7ae428ffddb072724d602d62 100644 +index 1467232779541a9e38420caabf273662f380794c..762354681315e4c74e414bf7d677b5422385161e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java @@ -70,4 +70,11 @@ public class CraftAbstractVillager extends CraftAgeable implements AbstractVilla public HumanEntity getTrader() { - return getMerchant().getTrader(); + return this.getMerchant().getTrader(); } + + // Paper start diff --git a/patches/server-remapped/0584-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/patches/server/0525-Improve-inlinig-for-some-hot-IBlockData-methods.patch similarity index 79% rename from patches/server-remapped/0584-Improve-inlinig-for-some-hot-IBlockData-methods.patch rename to patches/server/0525-Improve-inlinig-for-some-hot-IBlockData-methods.patch index fc2f46516c..c21e66a43c 100644 --- a/patches/server-remapped/0584-Improve-inlinig-for-some-hot-IBlockData-methods.patch +++ b/patches/server/0525-Improve-inlinig-for-some-hot-IBlockData-methods.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Improve inlinig for some hot IBlockData methods diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index f2fefdad26057c722085e60ba837fe2c117f55f7..17baae6b11f191f4738a107c7e62ea5bdac17a3c 100644 +index 597bb3b9b638c59c6ddc21095e4fe4503ef36cb1..933448659367b5f0b323bd91992fc9b59314b8a1 100644 --- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -390,7 +390,14 @@ public abstract class BlockBehaviour { +@@ -653,7 +653,14 @@ public abstract class BlockBehaviour { } // Paper end @@ -23,7 +23,7 @@ index f2fefdad26057c722085e60ba837fe2c117f55f7..17baae6b11f191f4738a107c7e62ea5b if (!this.getBlock().hasDynamicShape()) { this.cache = new BlockBehaviour.BlockStateBase.Cache(this.asState()); } -@@ -429,19 +436,19 @@ public abstract class BlockBehaviour { +@@ -692,19 +699,19 @@ public abstract class BlockBehaviour { return this.getBlock().getOcclusionShape(this.asState(), world, pos); } @@ -47,7 +47,7 @@ index f2fefdad26057c722085e60ba837fe2c117f55f7..17baae6b11f191f4738a107c7e62ea5b return this.isAir; } -@@ -507,7 +514,7 @@ public abstract class BlockBehaviour { +@@ -778,7 +785,7 @@ public abstract class BlockBehaviour { } } @@ -56,8 +56,8 @@ index f2fefdad26057c722085e60ba837fe2c117f55f7..17baae6b11f191f4738a107c7e62ea5b return this.canOcclude; } -@@ -679,12 +686,12 @@ public abstract class BlockBehaviour { - return this.getBlock().is(block); +@@ -971,12 +978,12 @@ public abstract class BlockBehaviour { + return this.getBlock() == block; } - public FluidState getFluidState() { @@ -72,25 +72,25 @@ index f2fefdad26057c722085e60ba837fe2c117f55f7..17baae6b11f191f4738a107c7e62ea5b + return this.isTicking; // Paper - moved into init } - public SoundType getSoundType() { + public long getSeed(BlockPos pos) { diff --git a/src/main/java/net/minecraft/world/level/material/FluidState.java b/src/main/java/net/minecraft/world/level/material/FluidState.java -index c077e4a7ce6a484956206eaab9dfde057b7e429a..69cf9e149c207336c537a00f08251a2252752df6 100644 +index 65911334082f9d53fc930d7c6b0313e8acef0c5e..0ae876f0bbfac74a9d5f06fb73f9cfcf5991b02e 100644 --- a/src/main/java/net/minecraft/world/level/material/FluidState.java +++ b/src/main/java/net/minecraft/world/level/material/FluidState.java -@@ -20,8 +20,12 @@ public final class FluidState extends StateHolder { - - public static final Codec CODEC = codec((Codec) Registry.FLUID, Fluid::defaultFluidState).stable(); +@@ -23,8 +23,12 @@ public final class FluidState extends StateHolder { + public static final int AMOUNT_MAX = 9; + public static final int AMOUNT_FULL = 8; + // Paper start + protected final boolean isEmpty; + // Paper end - public FluidState(Fluid fluid, ImmutableMap, Comparable> propertiesMap, MapCodec mapcodec) { - super(fluid, propertiesMap, mapcodec); + public FluidState(Fluid fluid, ImmutableMap, Comparable> propertiesMap, MapCodec codec) { + super(fluid, propertiesMap, codec); + this.isEmpty = fluid.isEmpty(); // Paper - moved from isEmpty() } public Fluid getType() { -@@ -33,7 +37,7 @@ public final class FluidState extends StateHolder { +@@ -40,7 +44,7 @@ public final class FluidState extends StateHolder { } public boolean isEmpty() { diff --git a/patches/server-remapped/0585-Retain-block-place-order-when-capturing-blockstates.patch b/patches/server/0526-Retain-block-place-order-when-capturing-blockstates.patch similarity index 88% rename from patches/server-remapped/0585-Retain-block-place-order-when-capturing-blockstates.patch rename to patches/server/0526-Retain-block-place-order-when-capturing-blockstates.patch index 1d1bff4b34..60332ff843 100644 --- a/patches/server-remapped/0585-Retain-block-place-order-when-capturing-blockstates.patch +++ b/patches/server/0526-Retain-block-place-order-when-capturing-blockstates.patch @@ -10,10 +10,10 @@ In general, look at making this logic more robust (i.e properly handling cases where a captured entry is overriden) - but for now this will do. diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index ebb92f88e0402681c47834bcf45e6b236748289a..2ad8a4558aa812885adebee8c05dab45f2bf5f90 100644 +index b969e7f2087aed5b1f97ce8593a25ada737daec9..31aa0c682fddb0555c2ac47f563484cfa51f2669 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -135,7 +135,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -147,7 +147,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public boolean captureBlockStates = false; public boolean captureTreeGeneration = false; public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper diff --git a/patches/server/0527-Reduce-blockpos-allocation-from-pathfinding.patch b/patches/server/0527-Reduce-blockpos-allocation-from-pathfinding.patch new file mode 100644 index 0000000000..9fbe5ebecc --- /dev/null +++ b/patches/server/0527-Reduce-blockpos-allocation-from-pathfinding.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 25 Apr 2020 17:10:55 -0700 +Subject: [PATCH] Reduce blockpos allocation from pathfinding + + +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +index b37acb6e6e253529a38f44a518a02c7747d3145e..2ad5ff9a1d7de54e75436e99da8a73db9dc91bde 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +@@ -471,7 +471,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { + return BlockPathTypes.DANGER_FIRE; + } + +- if (world.getFluidState(pos).is(FluidTags.WATER)) { ++ if (blockState.getFluidState().is(FluidTags.WATER)) { + return BlockPathTypes.WATER_BORDER; + } + } // Paper +@@ -502,7 +502,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { + } else if (blockState.is(Blocks.COCOA)) { + return BlockPathTypes.COCOA; + } else { +- FluidState fluidState = world.getFluidState(pos); ++ FluidState fluidState = blockState.getFluidState(); // Paper - remove another get type call + if (fluidState.is(FluidTags.LAVA)) { + return BlockPathTypes.LAVA; + } else if (isBurningBlock(blockState)) { diff --git a/patches/server/0528-Fix-item-locations-dropped-from-campfires.patch b/patches/server/0528-Fix-item-locations-dropped-from-campfires.patch new file mode 100644 index 0000000000..30515883c1 --- /dev/null +++ b/patches/server/0528-Fix-item-locations-dropped-from-campfires.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 3 Oct 2020 20:32:25 -0500 +Subject: [PATCH] Fix item locations dropped from campfires + +Fixes #4259 by not flooring the blockposition among other weirdness + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +index 7a5f748f974429ce4faa8f64fae905994b5e59a9..ad35d82f03f7643507dde6adbb38c911d12ec6c1 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +@@ -71,7 +71,11 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { + result = blockCookEvent.getResult(); + itemstack1 = CraftItemStack.asNMSCopy(result); + // CraftBukkit end +- Containers.dropItemStack(world, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), itemstack1); ++ // Paper start ++ net.minecraft.world.entity.item.ItemEntity droppedItem = new net.minecraft.world.entity.item.ItemEntity(world, pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, itemstack1.split(world.random.nextInt(21) + 10)); ++ droppedItem.setDeltaMovement(world.random.nextGaussian() * 0.05D, world.random.nextGaussian() * 0.05D + 0.2D, world.random.nextGaussian() * 0.05D); ++ world.addFreshEntity(droppedItem); ++ // Paper end + campfire.items.set(i, ItemStack.EMPTY); + world.sendBlockUpdated(pos, state, state, 3); + } diff --git a/patches/server-remapped/0588-Player-elytra-boost-API.patch b/patches/server/0529-Player-elytra-boost-API.patch similarity index 60% rename from patches/server-remapped/0588-Player-elytra-boost-API.patch rename to patches/server/0529-Player-elytra-boost-API.patch index 92e087e79f..3bae46ddd3 100644 --- a/patches/server-remapped/0588-Player-elytra-boost-API.patch +++ b/patches/server/0529-Player-elytra-boost-API.patch @@ -5,18 +5,10 @@ Subject: [PATCH] Player elytra boost API diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 7aae63d22167dc1b3ec7e8bc8672855c2038007e..94240b70e245bdc3dda60420f5787f8d5dcc1958 100644 +index b277c87c0834ddcefcfaebd85c9e69d8d389b59e..41bb480e61ff98dd35b8e059356bf867406e9e5e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -67,6 +67,7 @@ import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.ai.attributes.AttributeInstance; - import net.minecraft.world.entity.ai.attributes.AttributeMap; - import net.minecraft.world.entity.ai.attributes.Attributes; -+import net.minecraft.world.entity.projectile.FireworkRocketEntity; - import net.minecraft.world.inventory.AbstractContainerMenu; - import net.minecraft.world.item.enchantment.EnchantmentHelper; - import net.minecraft.world.item.enchantment.Enchantments; -@@ -2281,6 +2282,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -534,6 +534,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } throw new RuntimeException("Unknown settings type"); } @@ -29,11 +21,11 @@ index 7aae63d22167dc1b3ec7e8bc8672855c2038007e..94240b70e245bdc3dda60420f5787f8d + + net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(firework); + net.minecraft.world.level.Level world = ((CraftWorld) getWorld()).getHandle(); -+ FireworkRocketEntity entity = new FireworkRocketEntity(world, item, getHandle()); ++ net.minecraft.world.entity.projectile.FireworkRocketEntity entity = new net.minecraft.world.entity.projectile.FireworkRocketEntity(world, item, getHandle()); + return world.addFreshEntity(entity) + ? (org.bukkit.entity.Firework) entity.getBukkitEntity() + : null; + } // Paper end - // Spigot start + @Override diff --git a/patches/server/0530-Fixed-TileEntityBell-memory-leak.patch b/patches/server/0530-Fixed-TileEntityBell-memory-leak.patch new file mode 100644 index 0000000000..673852d44b --- /dev/null +++ b/patches/server/0530-Fixed-TileEntityBell-memory-leak.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: giacomo <32515303+giacomozama@users.noreply.github.com> +Date: Sat, 10 Oct 2020 12:15:33 +0200 +Subject: [PATCH] Fixed TileEntityBell memory leak + +TileEntityBell has a list of entities (entitiesAtRing) that was not being cleared at the right time, causing leaks whenever a bell would be rung near a crowd of entities. + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +index 58ee348d0934a8d8743005b4b8e9114cfe1bc028..a71bf0802d04217dd11086901b7148957d32ca89 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -61,6 +61,11 @@ public class BellBlockEntity extends BlockEntity { + + if (blockEntity.ticks >= 50) { + blockEntity.shaking = false; ++ // Paper start ++ if (!blockEntity.resonating) { ++ blockEntity.nearbyEntities.clear(); ++ } ++ // Paper end + blockEntity.ticks = 0; + } + +@@ -74,6 +79,7 @@ public class BellBlockEntity extends BlockEntity { + ++blockEntity.resonationTicks; + } else { + bellEffect.run(world, pos, blockEntity.nearbyEntities); ++ blockEntity.nearbyEntities.clear(); // Paper + blockEntity.resonating = false; + } + } +@@ -116,6 +122,7 @@ public class BellBlockEntity extends BlockEntity { + } + } + ++ this.nearbyEntities.removeIf(e -> !e.isAlive()); // Paper + } + + private static boolean areRaidersNearby(BlockPos pos, List hearingEntities) { diff --git a/patches/server-remapped/0590-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/patches/server/0531-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch similarity index 93% rename from patches/server-remapped/0590-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch rename to patches/server/0531-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch index 6072b2edd8..a945afec8d 100644 --- a/patches/server-remapped/0590-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch +++ b/patches/server/0531-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch @@ -8,10 +8,10 @@ This can realistically only happen if there's custom loot active on fishing which can return 0 items. This would disconnect the player who's fishing. diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -index 7bff012f3cd4458673ee02e5f5f830fc0ef983a3..ef71cca9922ed134ec82fb2982d375bf16f47b17 100644 +index 0258d0699afe7ceec19154c669b10298e6e1bf95..852a4edde291bf368b2396e3c94ab402e3c66622 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -@@ -481,9 +481,15 @@ public class FishingHook extends Projectile { +@@ -497,9 +497,15 @@ public class FishingHook extends Projectile { while (iterator.hasNext()) { ItemStack itemstack1 = (ItemStack) iterator.next(); @@ -29,7 +29,7 @@ index 7bff012f3cd4458673ee02e5f5f830fc0ef983a3..ef71cca9922ed134ec82fb2982d375bf playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); this.level.getCraftServer().getPluginManager().callEvent(playerFishEvent); -@@ -496,8 +502,12 @@ public class FishingHook extends Projectile { +@@ -512,8 +518,12 @@ public class FishingHook extends Projectile { double d2 = entityhuman.getZ() - this.getZ(); double d3 = 0.1D; diff --git a/patches/server-remapped/0591-Add-getOfflinePlayerIfCached-String.patch b/patches/server/0532-Add-getOfflinePlayerIfCached-String.patch similarity index 88% rename from patches/server-remapped/0591-Add-getOfflinePlayerIfCached-String.patch rename to patches/server/0532-Add-getOfflinePlayerIfCached-String.patch index b581372702..9c08b509fc 100644 --- a/patches/server-remapped/0591-Add-getOfflinePlayerIfCached-String.patch +++ b/patches/server/0532-Add-getOfflinePlayerIfCached-String.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add getOfflinePlayerIfCached(String) diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e599be15af17e5e45d2b694c30140cc4a787a7f5..046fbc646d2818bb2c7e08ff22093523e8246523 100644 +index 7795735e5acc3b7b6b71b4e61bdc4bdcb722a7b3..ecae20bb39848cc0223df3c4804a68f4e0731e3b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1612,6 +1612,28 @@ public final class CraftServer implements Server { +@@ -1613,6 +1613,28 @@ public final class CraftServer implements Server { return result; } diff --git a/patches/server-remapped/0592-Add-ignore-discounts-API.patch b/patches/server/0533-Add-ignore-discounts-API.patch similarity index 78% rename from patches/server-remapped/0592-Add-ignore-discounts-API.patch rename to patches/server/0533-Add-ignore-discounts-API.patch index e20018337f..467e7a6641 100644 --- a/patches/server-remapped/0592-Add-ignore-discounts-API.patch +++ b/patches/server/0533-Add-ignore-discounts-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add ignore discounts API diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index e9912551e6a19d6ad3b20fad1b716577b9d28f99..415fa3591add1f1ab22dd5866e110dbfccd0ec93 100644 +index 94e742856244b99236ba458fa38801abb5acf286..f534d3afaa20abacfd9e6e15d31d592855667c57 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -459,6 +459,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -474,6 +474,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler while (iterator.hasNext()) { MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); @@ -16,7 +16,7 @@ index e9912551e6a19d6ad3b20fad1b716577b9d28f99..415fa3591add1f1ab22dd5866e110dbf // CraftBukkit start int bonus = -Mth.floor((float) i * merchantrecipe.getPriceMultiplier()); -@@ -478,6 +479,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -493,6 +494,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler while (iterator1.hasNext()) { MerchantOffer merchantrecipe1 = (MerchantOffer) iterator1.next(); @@ -25,7 +25,7 @@ index e9912551e6a19d6ad3b20fad1b716577b9d28f99..415fa3591add1f1ab22dd5866e110dbf int k = (int) Math.floor(d0 * (double) merchantrecipe1.getBaseCostA().getCount()); diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java -index fa74813e0fe76612023830b2fc41d41aa0b4f10e..25a0f180967911d5916eb71334a94baec84eafbf 100644 +index 75827fcad36a551d832f4be094167936092b6caf..70b703b920752e7301e4f19cdc07a1a4ceac5e0e 100644 --- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java +++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java @@ -19,6 +19,7 @@ public class MerchantOffer { @@ -45,40 +45,40 @@ index fa74813e0fe76612023830b2fc41d41aa0b4f10e..25a0f180967911d5916eb71334a94bae + this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, false, bukkit); + } + public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) { -+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, ignoreDiscounts); ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, 0, ignoreDiscounts); + // Paper end this.bukkitHandle = bukkit; } // CraftBukkit end @@ -59,6 +65,7 @@ public class MerchantOffer { - this.specialPriceDiff = nbttagcompound.getInt("specialPrice"); - this.demand = nbttagcompound.getInt("demand"); -+ this.ignoreDiscounts = nbttagcompound.getBoolean("Paper.IgnoreDiscounts"); // Paper + this.specialPriceDiff = nbt.getInt("specialPrice"); + this.demand = nbt.getInt("demand"); ++ this.ignoreDiscounts = nbt.getBoolean("Paper.IgnoreDiscounts"); // Paper } - public MerchantOffer(ItemStack buyItem, ItemStack sellItem, int maxUses, int rewardedExp, float priceMultiplier) { + public MerchantOffer(ItemStack buyItem, ItemStack sellItem, int maxUses, int merchantExperience, float priceMultiplier) { @@ -70,10 +77,19 @@ public class MerchantOffer { } - public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int rewardedExp, float priceMultiplier) { -- this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, rewardedExp, priceMultiplier, 0); + public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier) { +- this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, 0); + // Paper start - add ignoreDiscounts param -+ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, rewardedExp, priceMultiplier, false); ++ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, false); + } -+ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, boolean ignoreDiscounts) { -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, 0, ignoreDiscounts); ++ public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, boolean ignoreDiscounts) { ++ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, 0, ignoreDiscounts); } - public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l) { -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, l, false); + public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, int demandBonus) { ++ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, demandBonus, false); + } -+ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l, boolean ignoreDiscounts) { ++ public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, int demandBonus, boolean ignoreDiscounts) { + this.ignoreDiscounts = ignoreDiscounts; + // Paper end this.rewardExp = true; this.xp = 1; - this.baseCostA = itemstack; + this.baseCostA = firstBuyItem; @@ -189,6 +205,7 @@ public class MerchantOffer { nbttagcompound.putFloat("priceMultiplier", this.priceMultiplier); nbttagcompound.putInt("specialPrice", this.specialPriceDiff); @@ -88,7 +88,7 @@ index fa74813e0fe76612023830b2fc41d41aa0b4f10e..25a0f180967911d5916eb71334a94bae } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -index 212f9c7f3e73ffedf27b94abeac957b7d866a086..a6c8588f10c4c109833aea6a8b02c9048b6d9ea4 100644 +index 8dfbac01a7c88797bb7adfee6278d090da2bedc9..fc69347b03ce197584b310f99e14799046ed5b70 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java @@ -17,7 +17,12 @@ public class CraftMerchantRecipe extends MerchantRecipe { diff --git a/patches/server-remapped/0593-Toggle-for-removing-existing-dragon.patch b/patches/server/0534-Toggle-for-removing-existing-dragon.patch similarity index 59% rename from patches/server-remapped/0593-Toggle-for-removing-existing-dragon.patch rename to patches/server/0534-Toggle-for-removing-existing-dragon.patch index 184345a27e..3bb55320e8 100644 --- a/patches/server-remapped/0593-Toggle-for-removing-existing-dragon.patch +++ b/patches/server/0534-Toggle-for-removing-existing-dragon.patch @@ -5,14 +5,13 @@ Subject: [PATCH] Toggle for removing existing dragon diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 02bb85364560784adea47c877c13291c3d016b86..424754a0183b071d20c86f0420cec784a8992e2b 100644 +index a88ef43adcf4ba36964f02e3fd363d3e018147cd..1a2f62fae9ccf31764d8e10642ef38bdb955dc41 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -683,4 +683,12 @@ public class PaperWorldConfig { - log("Using vanilla redstone algorithm."); +@@ -56,6 +56,14 @@ public class PaperWorldConfig { } } -+ + + public boolean shouldRemoveDragon = false; + private void shouldRemoveDragon() { + shouldRemoveDragon = getBoolean("should-remove-dragon", shouldRemoveDragon); @@ -20,17 +19,20 @@ index 02bb85364560784adea47c877c13291c3d016b86..424754a0183b071d20c86f0420cec784 + log("The Ender Dragon will be removed if she already exists without a portal."); + } + } - } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 590df3b93b897613cad74f9920aec62b33a2f7f7..84447e9845edad2d228b94184b35b4afb453a14b 100644 +index 9899c70b88fc371963e33caccd7125ef8c333df4..e1d689aa65b8d993c7223d306363366f3adff62f 100644 --- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -210,7 +210,7 @@ public class EndDragonFight { - this.dragonUUID = entityenderdragon.getUUID(); - EndDragonFight.LOGGER.info("Found that there's a dragon still alive ({})", entityenderdragon); +@@ -212,7 +212,7 @@ public class EndDragonFight { + this.dragonUUID = enderDragon.getUUID(); + LOGGER.info("Found that there's a dragon still alive ({})", (Object)enderDragon); this.dragonKilled = false; -- if (!flag) { -+ if (!flag && this.level.paperConfig.shouldRemoveDragon) { // Paper - EndDragonFight.LOGGER.info("But we didn't have a portal, let's remove it."); - entityenderdragon.remove(); +- if (!bl) { ++ if (!bl && this.level.paperConfig.shouldRemoveDragon) { + LOGGER.info("But we didn't have a portal, let's remove it."); + enderDragon.discard(); this.dragonUUID = null; diff --git a/patches/server-remapped/0594-Fix-client-lag-on-advancement-loading.patch b/patches/server/0535-Fix-client-lag-on-advancement-loading.patch similarity index 81% rename from patches/server-remapped/0594-Fix-client-lag-on-advancement-loading.patch rename to patches/server/0535-Fix-client-lag-on-advancement-loading.patch index 2affffb90a..94e1148e05 100644 --- a/patches/server-remapped/0594-Fix-client-lag-on-advancement-loading.patch +++ b/patches/server/0535-Fix-client-lag-on-advancement-loading.patch @@ -15,18 +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/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java -index acb41cc3965154c5b515cd8e808bf2cf5dc850e4..b8d3f2c59199e245e2035d6205dd1a042aa93f77 100644 +index e05e5710c81b7dbb648afbfe16f843e7ae310752..77e262f2236318e053da136037332fbe6d8bf380 100644 --- a/src/main/java/net/minecraft/server/PlayerAdvancements.java +++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java -@@ -97,6 +97,7 @@ public class PlayerAdvancements { - - } - -+ public final void reload(ServerAdvancementManager advancementDataWorld) { this.reload(advancementDataWorld); } // Paper - OBFHELPER - public void reload(ServerAdvancementManager advancementLoader) { - this.stopListening(); - this.advancements.clear(); -@@ -393,6 +394,7 @@ public class PlayerAdvancements { +@@ -371,6 +371,7 @@ public class PlayerAdvancements { } @@ -35,7 +27,7 @@ index acb41cc3965154c5b515cd8e808bf2cf5dc850e4..b8d3f2c59199e245e2035d6205dd1a04 if (this.isFirstPacket || !this.visibilityChanged.isEmpty() || !this.progressChanged.isEmpty()) { Map map = Maps.newHashMap(); diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 9a16882deee21faf78ea46e08b2f2ad3fbb6021b..ac94fd569bd4c79e30adef148e09e395ba8c1812 100644 +index 2984f5fa036019bb35a603690c568fc5c7b855d6..3d5f9ac267943fe2487a5cc4f9f059b169b438a8 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -307,7 +307,13 @@ public final class CraftMagicNumbers implements UnsafeValues { diff --git a/patches/server-remapped/0595-Item-no-age-no-player-pickup.patch b/patches/server/0536-Item-no-age-no-player-pickup.patch similarity index 90% rename from patches/server-remapped/0595-Item-no-age-no-player-pickup.patch rename to patches/server/0536-Item-no-age-no-player-pickup.patch index 0c17d7553d..a121c378e3 100644 --- a/patches/server-remapped/0595-Item-no-age-no-player-pickup.patch +++ b/patches/server/0536-Item-no-age-no-player-pickup.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Item no age & no player pickup diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -index 9a410f557988d737c3b930a79ef2ccb2b5c8b406..aff17bb3bd22de492b9736d27b7f3e4bdb37134c 100644 +index 0d262c99c7e9ef06e297612b1802c493700f64ae..342345eb04d00efb58392ccf209e3c51c1064173 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java @@ -10,6 +10,12 @@ import org.bukkit.entity.Item; @@ -21,7 +21,7 @@ index 9a410f557988d737c3b930a79ef2ccb2b5c8b406..aff17bb3bd22de492b9736d27b7f3e4b private final ItemEntity item; public CraftItem(CraftServer server, Entity entity, ItemEntity item) { -@@ -57,6 +63,26 @@ public class CraftItem extends CraftEntity implements Item { +@@ -59,6 +65,26 @@ public class CraftItem extends CraftEntity implements Item { public void setCanMobPickup(boolean canMobPickup) { item.canMobPickup = canMobPickup; } diff --git a/patches/server/0537-Beacon-API-custom-effect-ranges.patch b/patches/server/0537-Beacon-API-custom-effect-ranges.patch new file mode 100644 index 0000000000..358189f049 --- /dev/null +++ b/patches/server/0537-Beacon-API-custom-effect-ranges.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 24 Jun 2020 12:39:08 -0600 +Subject: [PATCH] Beacon API - custom effect ranges + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +index 0fa01b98f4a2ce2a7d34437a71d8c1cc7e718fb1..1df7a4a937729fc402f80021434ddf3481facd94 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -79,6 +79,26 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + return (BeaconBlockEntity.hasSecondaryEffect(this.levels, this.primaryPower, this.secondaryPower)) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, BeaconBlockEntity.getLevel(this.levels), BeaconBlockEntity.getAmplification(this.levels, this.primaryPower, this.secondaryPower), true, true)) : null; + } + // CraftBukkit end ++ // Paper start - add field/methods for custom range ++ private final String PAPER_RANGE_TAG = "Paper.Range"; ++ private double effectRange = -1; ++ ++ public double getEffectRange() { ++ if (this.effectRange < 0) { ++ return this.levels * 10 + 10; ++ } else { ++ return effectRange; ++ } ++ } ++ ++ public void setEffectRange(double range) { ++ this.effectRange = range; ++ } ++ ++ public void resetEffectRange() { ++ this.effectRange = -1; ++ } ++ // Paper end + + public BeaconBlockEntity(BlockPos pos, BlockState state) { + super(BlockEntityType.BEACON, pos, state); +@@ -268,8 +288,13 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + } + + public static List getHumansInRange(Level world, BlockPos blockposition, int i) { ++ // Paper start ++ return BeaconBlockEntity.getHumansInRange(world, blockposition, i, null); ++ } ++ public static List getHumansInRange(Level world, BlockPos blockposition, int i, @Nullable BeaconBlockEntity blockEntity) { ++ // Paper end + { +- double d0 = (double) (i * 10 + 10); ++ double d0 = blockEntity != null ? blockEntity.getEffectRange() : (i * 10 + 10);// Paper - custom beacon ranges + + AABB axisalignedbb = (new AABB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D); + List list = world.getEntitiesOfClass(Player.class, axisalignedbb); +@@ -366,6 +391,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + } + + this.lockKey = LockCode.fromTag(nbt); ++ this.effectRange = nbt.contains(PAPER_RANGE_TAG, 6) ? nbt.getDouble(PAPER_RANGE_TAG) : -1; // Paper + } + + @Override +@@ -379,6 +405,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + } + + this.lockKey.addToTag(nbt); ++ nbt.putDouble(PAPER_RANGE_TAG, this.effectRange); // Paper + return nbt; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +index 5abf219e86c6b4cf0c6b2e8ea72d7ed7b4f612e3..e2b2625565a4ac39899de01a7fe660188f04c109 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +@@ -108,4 +108,21 @@ public class CraftBeacon extends CraftBlockEntityState implem + public void setLock(String key) { + this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key); + } ++ ++ // Paper start ++ @Override ++ public double getEffectRange() { ++ return this.getSnapshot().getEffectRange(); ++ } ++ ++ @Override ++ public void setEffectRange(double range) { ++ this.getSnapshot().setEffectRange(range); ++ } ++ ++ @Override ++ public void resetEffectRange() { ++ this.getSnapshot().resetEffectRange(); ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0597-Add-API-for-quit-reason.patch b/patches/server/0538-Add-API-for-quit-reason.patch similarity index 58% rename from patches/server-remapped/0597-Add-API-for-quit-reason.patch rename to patches/server/0538-Add-API-for-quit-reason.patch index 988b77b058..4e5d931b12 100644 --- a/patches/server-remapped/0597-Add-API-for-quit-reason.patch +++ b/patches/server/0538-Add-API-for-quit-reason.patch @@ -5,14 +5,14 @@ Subject: [PATCH] Add API for quit reason diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 6f7cbce5a049d87d4a0ed7cc4517cb4e8694efb5..3ba9c38fc44a8edba9b504112a383249052a0035 100644 +index d32b96a5f51d745869cfc40c01c54de58e1eb843..759e563d1ed13249fada8a8eab6b6a10e5ef0d37 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java -@@ -137,12 +137,15 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -142,12 +142,15 @@ public class Connection extends SimpleChannelInboundHandler> { this.handlingFault = true; if (this.channel.isOpen()) { -+ ServerPlayer player = this.getPlayer(); // Paper ++ net.minecraft.server.level.ServerPlayer player = this.getPlayer(); // Paper if (throwable instanceof TimeoutException) { Connection.LOGGER.debug("Timeout", throwable); + if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper @@ -23,24 +23,24 @@ index 6f7cbce5a049d87d4a0ed7cc4517cb4e8694efb5..3ba9c38fc44a8edba9b504112a383249 + if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper if (flag) { Connection.LOGGER.debug("Failed to sent packet", throwable); - this.send(new ClientboundDisconnectPacket(chatmessage), (future) -> { + ConnectionProtocol enumprotocol = this.getCurrentProtocol(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index bd4d4ace35e966e819aa461d3962fe06ff402be7..1b5f24920c46cd238a79f5a2857d26fa1c12b983 100644 +index b49fa995973f860a95d937c98e2821435262ce25..41e6164fc9f3aa54028e5db1331df743126e55e2 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -258,6 +258,7 @@ public class ServerPlayer extends Player implements ContainerListener { - double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks - +@@ -248,6 +248,7 @@ public class ServerPlayer extends Player { + public double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper boolean needsChunkCenterUpdate; // Paper - no-tick view distance + public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event - public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { - super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) { + super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 3a114bec14fcc6c1e1045e2b99178a6adb25f387..ccfe5a1ec1e9895f7462b7c676fee80903502a88 100644 +index 0e0d6d298caa1bbb6fb0dd42fd00460f7609c431..fa57095f0ddd5685f848ade5c0ec2e90e2a07e91 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -447,6 +447,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -444,6 +444,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser final Component ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure // CraftBukkit end @@ -49,15 +49,15 @@ index 3a114bec14fcc6c1e1045e2b99178a6adb25f387..ccfe5a1ec1e9895f7462b7c676fee809 this.connection.disconnect(ichatbasecomponent); }); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7e44c911f4abc5c7d0e89513bf2cfc3516f13492..cda21726f4929b03191e912550d4e4b1232b3b0b 100644 +index 2f73f1f770e5e1fa422bec9c27e5bd10e86b7538..fe548b8625a123798f8d966cb3bffd899971cb34 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -586,7 +586,7 @@ public abstract class PlayerList { +@@ -588,7 +588,7 @@ public abstract class PlayerList { entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper } -- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); -+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName())), entityplayer.quitReason); // Paper - quit reason - if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit +- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(this.cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName()))); ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(this.cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName())), entityplayer.quitReason); // Paper - quit reason + if (entityplayer.didPlayerJoinEvent) this.cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); diff --git a/patches/server/0539-Seed-based-feature-search.patch b/patches/server/0539-Seed-based-feature-search.patch new file mode 100644 index 0000000000..05c05fa386 --- /dev/null +++ b/patches/server/0539-Seed-based-feature-search.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Mon, 13 Jan 2020 15:40:32 +0100 +Subject: [PATCH] Seed based feature search + +This tries to work around the issue where the server will load +surrounding chunks up to a radius of 100 chunks in order to search for +features e.g. when running the /locate command or for treasure maps +(issue #2312). +This is done by backporting Mojang's change in 1.17 which makes it so +that the biome (generated by the seed) is checked first if the feature +can be generated before actually to load the chunk. + +Additionally to that the center location of the target chunk is simply +returned if the chunk is not loaded to avoid the sync chunk load. +As this can lead to less precise locations a toggle is provided to +enable the sync loading of the target chunk again. + +The main downside of this is that it breaks once the seed or generator +changes but this should usually not happen. A config option to disable +this completely is added though in case that should ever be necessary. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 1a2f62fae9ccf31764d8e10642ef38bdb955dc41..2097c579bda12c2d1d19d67a023ca94051509b51 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -379,6 +379,14 @@ public class PaperWorldConfig { + } + } + ++ public boolean seedBasedFeatureSearch = true; ++ public boolean seedBasedFeatureSearchLoadsChunks = false; ++ private void seedBasedFeatureSearch() { ++ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch); ++ seedBasedFeatureSearchLoadsChunks = getBoolean("seed-based-feature-search-loads-chunks", seedBasedFeatureSearchLoadsChunks); ++ log("Feature search is based on seed: " + seedBasedFeatureSearch + ", loads chunks:" + seedBasedFeatureSearchLoadsChunks); ++ } ++ + public int maxCollisionsPerEntity; + private void maxEntityCollision() { + maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +index 3878a7f6402a1dff1e019e16dd8772ec7303ebe7..ef77b7e54c9ce3379b3bd6991aebcb4889029907 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +@@ -171,7 +171,24 @@ public abstract class StructureFeature { + if (!world.getWorldBorder().isChunkInBounds(chunkPos.x, chunkPos.z)) { continue; } // Paper + boolean bl3 = world.getBiomeManager().getPrimaryBiomeAtChunk(chunkPos).getGenerationSettings().isValidStart(this); + if (bl3) { +- ChunkAccess chunkAccess = world.getChunk(chunkPos.x, chunkPos.z, ChunkStatus.STRUCTURE_STARTS); ++ // Paper start - seed based feature search ++ ChunkAccess chunkAccess = null; ++ if (structureAccessor.getWorld().paperConfig.seedBasedFeatureSearch) { ++ Biome biomeBase = structureAccessor.getWorld().getBiomeManager().getBiome(new BlockPos(chunkPos.getMinBlockX() + 9, 0, chunkPos.getMinBlockZ() + 9)); ++ if (!biomeBase.getGenerationSettings().isValidStart(this)) { ++ continue; ++ } ++ if (!structureAccessor.getWorld().paperConfig.seedBasedFeatureSearchLoadsChunks) { ++ chunkAccess = structureAccessor.getWorld().getChunkIfLoaded(chunkPos.x, chunkPos.z); ++ if (chunkAccess == null) { ++ return chunkPos.getWorldPosition().offset(8, searchStartPos.getY(), 8); ++ } ++ } ++ } ++ if (chunkAccess == null) { ++ chunkAccess = world.getChunk(chunkPos.x, chunkPos.z, ChunkStatus.STRUCTURE_STARTS); ++ } ++ // Paper end + StructureStart structureStart = structureAccessor.getStartForFeature(SectionPos.bottomOf(chunkAccess), this, chunkAccess); + if (structureStart != null && structureStart.isValid()) { + if (skipExistingChunks && structureStart.canBeReferenced()) { diff --git a/patches/server-remapped/0599-Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server/0540-Add-Wandering-Trader-spawn-rate-config-options.patch similarity index 56% rename from patches/server-remapped/0599-Add-Wandering-Trader-spawn-rate-config-options.patch rename to patches/server/0540-Add-Wandering-Trader-spawn-rate-config-options.patch index 2dbaff374a..d5e31e5fbb 100644 --- a/patches/server-remapped/0599-Add-Wandering-Trader-spawn-rate-config-options.patch +++ b/patches/server/0540-Add-Wandering-Trader-spawn-rate-config-options.patch @@ -11,14 +11,13 @@ in IWorldServerData are removed as they were only used in certain places, with h values used in other places. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 97870622e41cca36d9c7493bfad796f35f3831f4..5a451cc855de57f79a57670ba38e3af2343cb510 100644 +index 2097c579bda12c2d1d19d67a023ca94051509b51..afc637476380da272e61c10663dc77b30901c03a 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -699,4 +699,17 @@ public class PaperWorldConfig { - log("The Ender Dragon will be removed if she already exists without a portal."); +@@ -64,6 +64,19 @@ public class PaperWorldConfig { } } -+ + + public int wanderingTraderSpawnMinuteTicks = 1200; + public int wanderingTraderSpawnDayTicks = 24000; + public int wanderingTraderSpawnChanceFailureIncrement = 25; @@ -31,21 +30,15 @@ index 97870622e41cca36d9c7493bfad796f35f3831f4..5a451cc855de57f79a57670ba38e3af2 + wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); + wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); + } - } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -index c297051bc48ff20a6764496cbf11eef601761d13..9074d57e1576db2da3e4c76add4f7e07e5567879 100644 +index 12aa0fd5b6bada9820c3a08eee47c870f9c183cb..60f08ecd0034e8ef2965b54b3abccce582d0ca54 100644 --- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -@@ -30,49 +30,59 @@ public class WanderingTraderSpawner implements CustomSpawner { - - private final Random random = new Random(); - private final ServerLevelData serverLevelData; -- private int tickDelay; -- private int spawnDelay; -- private int spawnChance; -+ private int tickDelay; public final int getMinuteTimer() { return this.tickDelay; } public final void setMinuteTimer(int x) { this.tickDelay = x; } // Paper - OBFHELPER -+ private int spawnDelay; public final int getDayTimer() { return this.spawnDelay; } public final void setDayTimer(int x) { this.spawnDelay = x; } // Paper - OBFHELPER -+ private int spawnChance; public final int getSpawnChance() { return this.spawnChance; } public final void setSpawnChance(int x) { this.spawnChance = x; } // Paper - OBFHELPER +@@ -43,43 +43,53 @@ public class WanderingTraderSpawner implements CustomSpawner { public WanderingTraderSpawner(ServerLevelData properties) { this.serverLevelData = properties; @@ -59,14 +52,14 @@ index c297051bc48ff20a6764496cbf11eef601761d13..9074d57e1576db2da3e4c76add4f7e07 - properties.setWanderingTraderSpawnChance(this.spawnChance); - } + // Paper start -+ this.setMinuteTimer(Integer.MIN_VALUE); -+ //this.d = iworlddataserver.v(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value -+ //this.e = iworlddataserver.w(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value -+ //if (this.d == 0 && this.e == 0) { -+ // this.d = 24000; -+ // iworlddataserver.g(this.d); -+ // this.e = 25; -+ // iworlddataserver.h(this.e); ++ this.tickDelay = Integer.MIN_VALUE; ++ //this.spawnDelay = properties.getWanderingTraderSpawnDelay(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value ++ //this.spawnChance = properties.getWanderingTraderSpawnChance(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value ++ //if (this.spawnDelay == 0 && this.spawnChance == 0) { ++ // this.spawnDelay = 24000; ++ // properties.setWanderingTraderSpawnDelay(this.spawnDelay); ++ // this.spawnChance = 25; ++ // properties.setWanderingTraderSpawnChance(this.spawnChance); + //} + // Paper end @@ -75,45 +68,43 @@ index c297051bc48ff20a6764496cbf11eef601761d13..9074d57e1576db2da3e4c76add4f7e07 @Override public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { + // Paper start -+ if (this.getMinuteTimer() == Integer.MIN_VALUE) { -+ this.setMinuteTimer(world.paperConfig.wanderingTraderSpawnMinuteTicks); -+ this.setDayTimer(world.paperConfig.wanderingTraderSpawnDayTicks); -+ this.setSpawnChance(world.paperConfig.wanderingTraderSpawnChanceMin); ++ if (this.tickDelay == Integer.MIN_VALUE) { ++ this.tickDelay = world.paperConfig.wanderingTraderSpawnMinuteTicks; ++ this.spawnDelay = world.paperConfig.wanderingTraderSpawnDayTicks; ++ this.spawnChance = world.paperConfig.wanderingTraderSpawnChanceMin; + } if (!world.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) { return 0; - } else if (--this.tickDelay > 0) { -+ } else if (this.getMinuteTimer() - 1 > 0) { -+ this.setMinuteTimer(this.getMinuteTimer() - 1); ++ } else if (this.tickDelay - 1 > 0) { ++ this.tickDelay = this.tickDelay - 1; return 0; } else { - this.tickDelay = 1200; - this.spawnDelay -= 1200; - this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay); -- if (this.spawnDelay > 0) { -+ this.setMinuteTimer(world.paperConfig.wanderingTraderSpawnMinuteTicks); -+ this.setDayTimer(getDayTimer() - world.paperConfig.wanderingTraderSpawnMinuteTicks); -+ //this.b.g(this.d); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways -+ if (this.getDayTimer() > 0) { ++ this.tickDelay = world.paperConfig.wanderingTraderSpawnMinuteTicks; ++ this.spawnDelay = this.spawnDelay - world.paperConfig.wanderingTraderSpawnMinuteTicks; ++ //this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways + if (this.spawnDelay > 0) { return 0; } else { - this.spawnDelay = 24000; -+ this.setDayTimer(world.paperConfig.wanderingTraderSpawnDayTicks); ++ this.spawnDelay = world.paperConfig.wanderingTraderSpawnDayTicks; if (!world.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { return 0; } else { -- int i = this.spawnChance; -+ int i = this.getSpawnChance(); + int i = this.spawnChance; - this.spawnChance = Mth.clamp(this.spawnChance + 25, 25, 75); - this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); -+ this.setSpawnChance(Mth.clamp(i + world.paperConfig.wanderingTraderSpawnChanceFailureIncrement, world.paperConfig.wanderingTraderSpawnChanceMin, world.paperConfig.wanderingTraderSpawnChanceMax)); -+ //this.b.h(this.e); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways ++ this.spawnChance = Mth.clamp(i + world.paperConfig.wanderingTraderSpawnChanceFailureIncrement, world.paperConfig.wanderingTraderSpawnChanceMin, world.paperConfig.wanderingTraderSpawnChanceMax); ++ //this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways if (this.random.nextInt(100) > i) { return 0; } else if (this.spawn(world)) { - this.spawnChance = 25; -+ this.setSpawnChance(world.paperConfig.wanderingTraderSpawnChanceMin); ++ this.spawnChance = world.paperConfig.wanderingTraderSpawnChanceMin; + // Paper end return 1; } else { diff --git a/patches/server/0541-Significantly-improve-performance-of-the-end-generat.patch b/patches/server/0541-Significantly-improve-performance-of-the-end-generat.patch new file mode 100644 index 0000000000..3117923e3f --- /dev/null +++ b/patches/server/0541-Significantly-improve-performance-of-the-end-generat.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com> +Date: Tue, 3 Nov 2020 23:48:05 -0600 +Subject: [PATCH] Significantly improve performance of the end generation + +This patch implements a noise cache for the end which significantly reduces the computation time of generation. This results in about a 3x improvement. + +Original code by SuperCoder7979 and Gegy in Lithium, licensed under LGPL-3.0 (Source: https://github.com/jellysquid3/lithium-fabric) + +Co-authored-by: Gegy +Co-authored-by: Dylan Xaldin +Co-authored-by: pop4959 + +diff --git a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +index 9a64ab092ac8616ed8b9ea5c1e8677dda5c4333c..b4bc60b9251a141e9a276877a9be76a381ff351b 100644 +--- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java ++++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +@@ -28,6 +28,16 @@ public class TheEndBiomeSource extends BiomeSource { + private final Biome midlands; + private final Biome islands; + private final Biome barrens; ++ // Paper start ++ private static final class NoiseCache { ++ public long[] keys = new long[8192]; ++ public float[] values = new float[8192]; ++ public NoiseCache() { ++ java.util.Arrays.fill(keys, Long.MIN_VALUE); ++ } ++ } ++ private static final ThreadLocal> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new); ++ // Paper end + + public TheEndBiomeSource(Registry biomeRegistry, long seed) { + this(biomeRegistry, seed, biomeRegistry.getOrThrow(Biomes.THE_END), biomeRegistry.getOrThrow(Biomes.END_HIGHLANDS), biomeRegistry.getOrThrow(Biomes.END_MIDLANDS), biomeRegistry.getOrThrow(Biomes.SMALL_END_ISLANDS), biomeRegistry.getOrThrow(Biomes.END_BARRENS)); +@@ -87,12 +97,26 @@ public class TheEndBiomeSource extends BiomeSource { + float f = 100.0F - Mth.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; // Paper - cast ints to long to avoid integer overflow + f = Mth.clamp(f, -100.0F, 80.0F); + ++ NoiseCache cache = noiseCache.get().computeIfAbsent(simplexNoise, noiseKey -> new NoiseCache()); // Paper + for(int o = -12; o <= 12; ++o) { + for(int p = -12; p <= 12; ++p) { + long q = (long)(k + o); + long r = (long)(l + p); +- if (q * q + r * r > 4096L && simplexNoise.getValue((double)q, (double)r) < (double)-0.9F) { +- float g = (Mth.abs((float)q) * 3439.0F + Mth.abs((float)r) * 147.0F) % 13.0F + 9.0F; ++ // Paper start - Significantly improve end generation performance by using a noise cache ++ long key = net.minecraft.world.level.ChunkPos.asLong((int) q, (int) q); ++ int index = (int) it.unimi.dsi.fastutil.HashCommon.mix(key) & 8191; ++ float g = Float.MIN_VALUE; ++ if (cache.keys[index] == key) { ++ g = cache.values[index]; ++ } else { ++ if (q * q + r * r > 4096L && simplexNoise.getValue((double)q, (double)r) < (double)-0.9F) { ++ g = (Mth.abs((float) q) * 3439.0F + Mth.abs((float) r) * 147.0F) % 13.0F + 9.0F; ++ } ++ cache.keys[index] = key; ++ cache.values[index] = g; ++ } ++ if (g != Float.MIN_VALUE) { ++ // Paper end + float h = (float)(m - o * 2); + float s = (float)(n - p * 2); + float t = 100.0F - Mth.sqrt(h * h + s * s) * g; diff --git a/patches/server-remapped/0601-Expose-world-spawn-angle.patch b/patches/server/0542-Expose-world-spawn-angle.patch similarity index 62% rename from patches/server-remapped/0601-Expose-world-spawn-angle.patch rename to patches/server/0542-Expose-world-spawn-angle.patch index 0086ded8da..419b678486 100644 --- a/patches/server-remapped/0601-Expose-world-spawn-angle.patch +++ b/patches/server/0542-Expose-world-spawn-angle.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose world spawn angle diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index cda21726f4929b03191e912550d4e4b1232b3b0b..7e07fd0c8dec9f9cdeda65dfa0ccf42b4dde010e 100644 +index fe548b8625a123798f8d966cb3bffd899971cb34..ce6d9b460f0f55fc6d5544d5c8d2b78e5fcc3937 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -890,7 +890,7 @@ public abstract class PlayerList { +@@ -865,7 +865,7 @@ public abstract class PlayerList { if (location == null) { worldserver1 = this.server.getLevel(Level.OVERWORLD); blockposition = entityplayer1.getSpawnPoint(worldserver1); @@ -16,27 +16,15 @@ index cda21726f4929b03191e912550d4e4b1232b3b0b..7e07fd0c8dec9f9cdeda65dfa0ccf42b + location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F), worldserver1.levelData.getSpawnAngle(), 0.0F); // Paper - use world spawn angle } - Player respawnPlayer = cserver.getPlayer(entityplayer1); -diff --git a/src/main/java/net/minecraft/world/level/storage/LevelData.java b/src/main/java/net/minecraft/world/level/storage/LevelData.java -index 12a2371b15588ae84824d7a2d36a6d4c37e77013..078cee770a77b77d9b4a777754599d7b0b31f54b 100644 ---- a/src/main/java/net/minecraft/world/level/storage/LevelData.java -+++ b/src/main/java/net/minecraft/world/level/storage/LevelData.java -@@ -12,6 +12,7 @@ public interface LevelData { - - int getZSpawn(); - -+ default float getSpawnAngle() { return getSpawnAngle(); } // Paper - OBFHELPER - float getSpawnAngle(); - - long getGameTime(); + Player respawnPlayer = this.cserver.getPlayer(entityplayer1); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 28bf53bc9fca21f57cd4851adf508d833ecdd33b..aaf97c13babce3b0ffc639ef950d59d1eba1398a 100644 +index d0b2de0f0a37554eb812aa8c7c20f1067807dc40..ed8c8b7ff07a58dfaf7bbb1e630a1e68cc0c29f3 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -362,7 +362,7 @@ public class CraftWorld implements World { +@@ -377,7 +377,7 @@ public class CraftWorld implements World { @Override public Location getSpawnLocation() { - BlockPos spawn = world.getSpawn(); + BlockPos spawn = this.world.getSharedSpawnPos(); - return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); + return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ(), world.levelData.getSpawnAngle(), 0.0F); // Paper - expose world spawn angle } diff --git a/patches/server-remapped/0602-Add-Destroy-Speed-API.patch b/patches/server/0543-Add-Destroy-Speed-API.patch similarity index 90% rename from patches/server-remapped/0602-Add-Destroy-Speed-API.patch rename to patches/server/0543-Add-Destroy-Speed-API.patch index 53910619a5..bb9faa5da2 100644 --- a/patches/server-remapped/0602-Add-Destroy-Speed-API.patch +++ b/patches/server/0543-Add-Destroy-Speed-API.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add Destroy Speed API Co-authored-by: Jake Potrebic diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 37eceaef1212e2ee13aa763a5ede24ec170e5391..9defb202761296a825d035e27ddc51e17a311647 100644 +index aa81c0a4c02fd6f2ab900983fd8c9668fada802e..597ac36c6f6748ecfbf64920da172758814b8061 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -766,5 +766,23 @@ public class CraftBlock implements Block { +@@ -782,5 +782,23 @@ public class CraftBlock implements Block { public String getTranslationKey() { return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); } diff --git a/patches/server-remapped/0603-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/patches/server/0544-Fix-Player-spawnParticle-x-y-z-precision-loss.patch similarity index 84% rename from patches/server-remapped/0603-Fix-Player-spawnParticle-x-y-z-precision-loss.patch rename to patches/server/0544-Fix-Player-spawnParticle-x-y-z-precision-loss.patch index 95a480a03b..e4450be6cf 100644 --- a/patches/server-remapped/0603-Fix-Player-spawnParticle-x-y-z-precision-loss.patch +++ b/patches/server/0544-Fix-Player-spawnParticle-x-y-z-precision-loss.patch @@ -5,15 +5,15 @@ 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 94240b70e245bdc3dda60420f5787f8d5dcc1958..40380fff222cc1f3340cf6a6c4afbe60aaa5d3a6 100644 +index 41bb480e61ff98dd35b8e059356bf867406e9e5e..9236027beb13ae4f2e35c46f6c176fd5d7d20b4f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2008,7 +2008,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2047,7 +2047,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (data != null && !particle.getDataType().isInstance(data)) { throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); } - ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.toNMS(particle, data), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); + ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.toNMS(particle, data), true, x, y, z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); // Paper - Fix x/y/z coordinate precision loss - getHandle().connection.send(packetplayoutworldparticles); + this.getHandle().connection.send(packetplayoutworldparticles); } diff --git a/patches/server-remapped/0604-Add-LivingEntity-clearActiveItem.patch b/patches/server/0545-Add-LivingEntity-clearActiveItem.patch similarity index 79% rename from patches/server-remapped/0604-Add-LivingEntity-clearActiveItem.patch rename to patches/server/0545-Add-LivingEntity-clearActiveItem.patch index 308d4591ab..f67ede11d8 100644 --- a/patches/server-remapped/0604-Add-LivingEntity-clearActiveItem.patch +++ b/patches/server/0545-Add-LivingEntity-clearActiveItem.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Add LivingEntity#clearActiveItem diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index eb136af0f99f5d7520ceabb98cefd5a01122872c..170bb1124ee396a85dd64baed8110e39823ad849 100644 +index c01eae70fe12970e9f617bf14e542b33572bcf4c..18635227a39c96e350fbb8ee9918c41c7a645aa6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -773,6 +773,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().useItem.asBukkitMirror(); + return getHandle().getUseItem().asBukkitMirror(); } + // Paper start @@ -21,4 +21,4 @@ index eb136af0f99f5d7520ceabb98cefd5a01122872c..170bb1124ee396a85dd64baed8110e39 + @Override public int getItemUseRemainingTime() { - return getHandle().getItemUseRemainingTime(); + return getHandle().getUseItemRemainingTicks(); diff --git a/patches/server-remapped/0605-Add-PlayerItemCooldownEvent.patch b/patches/server/0546-Add-PlayerItemCooldownEvent.patch similarity index 52% rename from patches/server-remapped/0605-Add-PlayerItemCooldownEvent.patch rename to patches/server/0546-Add-PlayerItemCooldownEvent.patch index 4d8772cbb5..60c864d5cf 100644 --- a/patches/server-remapped/0605-Add-PlayerItemCooldownEvent.patch +++ b/patches/server/0546-Add-PlayerItemCooldownEvent.patch @@ -5,29 +5,17 @@ Subject: [PATCH] Add PlayerItemCooldownEvent diff --git a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java -index 93161583c215e1832570b39e72f7e7cfb94a700c..1983cdcefed60795e8c88737ae3459d5821cdcfa 100644 +index 47283d2a49209839002212e663a503a82ea86587..ce026600b3b5c846d991a0dfe599708caf2a2962 100644 --- a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java +++ b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java -@@ -1,16 +1,27 @@ - package net.minecraft.world.item; - -+import io.papermc.paper.event.player.PlayerItemCooldownEvent; // Paper - import net.minecraft.network.protocol.game.ClientboundCooldownPacket; - import net.minecraft.server.level.ServerPlayer; - - public class ServerItemCooldowns extends ItemCooldowns { - -- private final ServerPlayer player; -+ private final ServerPlayer player; public ServerPlayer getEntityPlayer() { return player; } // Paper - OBFHELPER - - public ServerItemCooldowns(ServerPlayer player) { +@@ -10,6 +10,16 @@ public class ServerItemCooldowns extends ItemCooldowns { this.player = player; } + // Paper start + @Override + public void addCooldown(Item item, int duration) { -+ PlayerItemCooldownEvent event = new PlayerItemCooldownEvent(getEntityPlayer().getBukkitEntity(), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(item), duration); ++ io.papermc.paper.event.player.PlayerItemCooldownEvent event = new io.papermc.paper.event.player.PlayerItemCooldownEvent(this.player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(item), duration); + if (event.callEvent()) { + super.addCooldown(item, event.getCooldown()); + } diff --git a/patches/server-remapped/0606-More-lightning-API.patch b/patches/server/0547-More-lightning-API.patch similarity index 57% rename from patches/server-remapped/0606-More-lightning-API.patch rename to patches/server/0547-More-lightning-API.patch index 6c4c8bac10..dae67c3aff 100644 --- a/patches/server-remapped/0606-More-lightning-API.patch +++ b/patches/server/0547-More-lightning-API.patch @@ -5,64 +5,50 @@ Subject: [PATCH] More lightning API diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java -index 4b0dbeded2b8a475d32f518957909d3495a4b6fc..3fdef4511e21e453b89e42a8f41e587fe300ba6b 100644 +index e476bc8013ac199713e3aaae787bb61fab736aeb..fff23f1cd9da385781547664f26b59255487e2b1 100644 --- a/src/main/java/net/minecraft/world/entity/LightningBolt.java +++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java -@@ -28,7 +28,7 @@ public class LightningBolt extends Entity { - - private int life; +@@ -39,9 +39,9 @@ public class LightningBolt extends Entity { + private static final int START_LIFE = 2; + private static final double DAMAGE_RADIUS = 3.0D; + private static final double DETECTION_RADIUS = 15.0D; +- private int life; ++ public int life; // Paper - private -> public public long seed; - private int flashes; -+ private int flashes; public int getFlashCount() { return flashes; } public void setFlashCount(int flashes) { this.flashes = flashes; } // Paper - OBFHELPER ++ public int flashes; // Paper - private -> public public boolean visualOnly; @Nullable private ServerPlayer cause; -@@ -46,6 +46,16 @@ public class LightningBolt extends Entity { - this.visualOnly = cosmetic; - } - -+ // Paper start -+ public int getLifeTicks() { -+ return life; -+ } -+ -+ public void setLifeTicks(int lifeTicks) { -+ this.life = lifeTicks; -+ } -+ // Paper end -+ - @Override - public SoundSource getSoundSource() { - return SoundSource.WEATHER; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -index 26506c22592b58b208487fb244985361d70988a8..c1593bb345b38deb4d8b28a73d8dc6246c17b873 100644 +index f7991ff14ef9cda0327b8621bf615b49cffd7ac5..db6b158f18ad7b9171a8c041802e3495d733bc16 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java @@ -45,4 +45,27 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike - return spigot; + return this.spigot; } // Spigot end + + // Paper start + @Override + public int getFlashCount() { -+ return getHandle().getFlashCount(); ++ return getHandle().flashes; + } + + @Override + public void setFlashCount(int flashes) { + com.google.common.base.Preconditions.checkArgument(flashes >= 0, "Flashes has to be a positive number!"); -+ getHandle().setFlashCount(flashes); ++ getHandle().flashes = flashes; + } + + @Override + public int getLifeTicks() { -+ return getHandle().getLifeTicks(); ++ return getHandle().life; + } + + @Override + public void setLifeTicks(int lifeTicks) { -+ getHandle().setLifeTicks(lifeTicks); ++ getHandle().life = lifeTicks; + } + // Paper end } diff --git a/patches/server-remapped/0607-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/0548-Climbing-should-not-bypass-cramming-gamerule.patch similarity index 73% rename from patches/server-remapped/0607-Climbing-should-not-bypass-cramming-gamerule.patch rename to patches/server/0548-Climbing-should-not-bypass-cramming-gamerule.patch index c25768004e..cb9304652a 100644 --- a/patches/server-remapped/0607-Climbing-should-not-bypass-cramming-gamerule.patch +++ b/patches/server/0548-Climbing-should-not-bypass-cramming-gamerule.patch @@ -5,24 +5,26 @@ Subject: [PATCH] Climbing should not bypass cramming gamerule diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5a451cc855de57f79a57670ba38e3af2343cb510..7d3207a9af8360ddad228281d6aa65e1a0d24157 100644 +index afc637476380da272e61c10663dc77b30901c03a..247b30b2b2edbb1043b6385039ba830dea877c55 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -712,4 +712,9 @@ public class PaperWorldConfig { - wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); +@@ -77,6 +77,11 @@ public class PaperWorldConfig { wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); } -+ + + public boolean fixClimbingBypassingCrammingRule = false; + private void fixClimbingBypassingCrammingRule() { + fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); + } - } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 90e9797cc1f3a4aa0a2bee28dca364e6f6dd0c0b..ec98f5f59ca2b4cb58eb00ed8cdfa364f8bacd88 100644 +index d64caca72a5302392df944d4c60ed2ba79a19ee7..785970057ceb7a58049f9d36ac0eaa122637430f 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1573,6 +1573,12 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1704,6 +1704,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } public boolean isPushable() { @@ -36,10 +38,10 @@ index 90e9797cc1f3a4aa0a2bee28dca364e6f6dd0c0b..ec98f5f59ca2b4cb58eb00ed8cdfa364 } diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index 8ce62148ebaeac9988e7c9d4b2f7ee57f58d883e..8d1e24c2fa844971908ae7ac918a8950026b40a6 100644 +index 8fb89326395a7e70982c0d757b506565e98b12a4..a060cca08631fb42041e3a79a9abc422fe7757af 100644 --- a/src/main/java/net/minecraft/world/entity/EntitySelector.java +++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -51,11 +51,17 @@ public final class EntitySelector { +@@ -44,11 +44,17 @@ public final class EntitySelector { } public static Predicate pushableBy(Entity entity) { @@ -53,34 +55,26 @@ index 8ce62148ebaeac9988e7c9d4b2f7ee57f58d883e..8d1e24c2fa844971908ae7ac918a8950 Team.CollisionRule scoreboardteambase_enumteampush = scoreboardteambase == null ? Team.CollisionRule.ALWAYS : scoreboardteambase.getCollisionRule(); return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> { -- if (!entity1.canCollideWithCb(entity) || !entity.canCollideWithCb(entity1)) { // CraftBukkit - collidable API -+ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWithCb(entity) || !entity.canCollideWithCb(entity1)) { // CraftBukkit - collidable API // Paper - isCollidable +- if (!entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API ++ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API // Paper - isCollidable return false; } 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 9724d4222311345a44aa101ec47523a1909fbe8f..57b933afdbb2136ed48170da6945eb2b92edb4db 100644 +index 8781b3ac40f214974ebb3e06c789f1717735d3a6..19ef1b2814270b9385ea15a89dac8c2613a672ee 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -134,7 +134,6 @@ import org.bukkit.event.entity.EntityTeleportEvent; - import org.bukkit.event.player.PlayerItemConsumeEvent; - // CraftBukkit end - --import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class LivingEntity extends Entity { - -@@ -2956,7 +2955,7 @@ public abstract class LivingEntity extends Entity { +@@ -3271,7 +3271,7 @@ public abstract class LivingEntity extends Entity { return; } - // Paper - end don't run getEntities if we're not going to use its result + // Paper end - don't run getEntities if we're not going to use its result - List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); + List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushable(this, level.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule if (!list.isEmpty()) { // Paper - move up -@@ -3094,9 +3093,16 @@ public abstract class LivingEntity extends Entity { - return !this.removed && this.collides; // CraftBukkit +@@ -3438,9 +3438,16 @@ public abstract class LivingEntity extends Entity { + return !this.isRemoved() && this.collides; // CraftBukkit } + // Paper start @@ -98,10 +92,10 @@ index 9724d4222311345a44aa101ec47523a1909fbe8f..57b933afdbb2136ed48170da6945eb2b // CraftBukkit start - collidable API diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java -index e56c575d744e1efe9a7512f337b781dc3715f6be..8e02e3a4464ab4096637fc69c03d083988bb426e 100644 +index 7a7b566d781560a85e184a0e67977ba75e6262c5..4716ece9bd1db50c87ccadc44d9ea3c43e741338 100644 --- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java +++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java -@@ -75,7 +75,7 @@ public class Bat extends AmbientCreature { +@@ -83,7 +83,7 @@ public class Bat extends AmbientCreature { } @Override @@ -111,10 +105,10 @@ index e56c575d744e1efe9a7512f337b781dc3715f6be..8e02e3a4464ab4096637fc69c03d0839 } diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java -index 918628c0ed8fb32d44c034fddf045f08659c10f8..d6a9d0e94d80f1924cedef913829d15762456537 100644 +index 23f87848b42d180c94b5659b184a768a756deed8..345fe87d5d6c3883c28d2c1b34d1020e18864d97 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java +++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java -@@ -368,8 +368,8 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { +@@ -380,8 +380,8 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { } @Override @@ -126,10 +120,10 @@ index 918628c0ed8fb32d44c034fddf045f08659c10f8..d6a9d0e94d80f1924cedef913829d157 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index d9bfc754d7544a54ff214b41b4f6c0a6bc66df28..b298bcfb665b1036cd21445cec1518069eb08f06 100644 +index c9e0d66443387f3f3e3999ee84d523550f48f573..d9699a422164c30a8386a8042202e1a8bc0ab2b0 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -@@ -226,7 +226,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, +@@ -240,7 +240,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, } @Override @@ -139,10 +133,10 @@ index d9bfc754d7544a54ff214b41b4f6c0a6bc66df28..b298bcfb665b1036cd21445cec151806 } diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 5714aa450ac09788bcf1c2790d4f1581c9a7c28b..a89573670f7dccfd8f0c81fcd95673b6faf3fc10 100644 +index 5bfec185e15a54ee5fe6eab1aa59d1963d046262..d098d9f9280d2e08596491264a46a8978aaeaca7 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -358,7 +358,7 @@ public class ArmorStand extends LivingEntity { +@@ -345,7 +345,7 @@ public class ArmorStand extends LivingEntity { } @Override @@ -152,10 +146,10 @@ index 5714aa450ac09788bcf1c2790d4f1581c9a7c28b..a89573670f7dccfd8f0c81fcd95673b6 } diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -index 1257a740a4ab79870fe89057782e8ffc6c658c14..9cbde70787d8044f0edeb3d459231dd7fbb79584 100644 +index fa889f93a5c6782957bdbf803915cb5e80e05f3e..9653b142c199c068e4d6175bcd3cbecb6465853f 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -@@ -144,7 +144,7 @@ public abstract class AbstractMinecart extends Entity { +@@ -149,7 +149,7 @@ public abstract class AbstractMinecart extends Entity { } @Override @@ -165,10 +159,10 @@ index 1257a740a4ab79870fe89057782e8ffc6c658c14..9cbde70787d8044f0edeb3d459231dd7 } diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -index bddc51c656f04f25744ec29cabab31d465cf8bce..4f82c6797fe9bbb1a29420ea15277be50e44808c 100644 +index 3f1059569da23bd02c00279050bf7bce7a160462..a1b93f2878e22fa1d0cad639416d2dc5b8339c73 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -@@ -149,7 +149,7 @@ public class Boat extends Entity { +@@ -158,7 +158,7 @@ public class Boat extends Entity { } @Override From ae5af5afcc9e2a68a10797fce661315d73c1af38 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Mon, 14 Jun 2021 21:02:30 +0200 Subject: [PATCH 119/226] resolve paperweight from paper repo --- build.gradle.kts | 2 +- settings.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 407f27e9d2..ec57e7a469 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -39,7 +39,7 @@ subprojects { repositories { mavenCentral() - maven("https://wav.jfrog.io/artifactory/repo/") { + maven("https://papermc.io/repo/repository/maven-public/") { content { onlyForConfigurations("paperclip") } diff --git a/settings.gradle.kts b/settings.gradle.kts index a9d4e7b2c7..4127fc6b8c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,7 +1,7 @@ pluginManagement { repositories { gradlePluginPortal() - maven("https://wav.jfrog.io/artifactory/repo/") + maven("https://papermc.io/repo/repository/maven-public/") } } From f72886c9a62de65a08f6eff434e8749c16680832 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Mon, 14 Jun 2021 21:12:21 +0200 Subject: [PATCH 120/226] run CI with --stacktrace --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2e65ad9613..63f28ac60f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,5 +36,5 @@ jobs: run: | git config --global user.email "no-reply@github.com" git config --global user.name "Github Actions" - ./gradlew applyPatches - ./gradlew build + ./gradlew applyPatches --stacktrace + ./gradlew build --stacktrace From 5dce4d9178a5a5922ae80ede5e7c7682361c9b15 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Mon, 14 Jun 2021 11:50:22 -0700 Subject: [PATCH 121/226] more patches --- .../0240-Add-PlayerShearBlockEvent.patch | 0 ...241-Enable-multi-release-plugin-jars.patch | 2 +- ...0242-Player-Chunk-Load-Unload-Events.patch | 0 ...3-Expose-LivingEntity-hurt-direction.patch | 0 ...OBSTRUCTED-reason-to-BedEnterResult.patch} | 0 .../0245-Added-PlayerTradeEvent.patch} | 0 .../0246-Add-TargetHitEvent-API.patch | 0 ...0247-Additional-Block-Material-API-s.patch | 4 +- ...et-Material-from-Boats-and-Minecarts.patch | 0 ...9-Add-PlayerFlowerPotManipulateEvent.patch | 0 .../0250-Zombie-API-breaking-doors.patch | 0 .../0251-Add-EntityLoadCrossbowEvent.patch | 0 .../0252-Added-WorldGameRuleChangeEvent.patch | 0 .../0626-Optimized-tick-ready-check.patch | 1 + ...d-missing-default-perms-for-commands.patch | 70 ----------- .../0609-Add-PlayerShearBlockEvent.patch | 116 ------------------ .../0615-MC-4-Fix-item-position-desync.patch | 84 ------------- ...0616-Player-Chunk-Load-Unload-Events.patch | 41 ------- ...8-Expose-LivingEntity-hurt-direction.patch | 39 ------ .../0621-added-PlayerTradeEvent.patch | 75 ----------- .../0622-Implement-TargetHitEvent.patch | 58 --------- .../0627-Cache-burn-durations.patch | 63 ---------- .../0631-Zombie-API-breaking-doors.patch | 44 ------- .../0633-Add-EntityLoadCrossbowEvent.patch | 60 --------- .../0634-Guardian-beam-workaround.patch | 30 ----- .../0635-Added-WorldGameRuleChangeEvent.patch | 110 ----------------- ...d-missing-default-perms-for-commands.patch | 70 +++++++++++ .../0550-Add-PlayerShearBlockEvent.patch | 70 +++++++++++ ...-for-servers-not-running-on-Java-16.patch} | 14 +-- ...rbose-world-setting-to-false-by-def.patch} | 8 +- ...ng-zombie-villager-discount-exploit.patch} | 32 ++--- .../0554-Limit-recipe-packets.patch} | 41 ++----- ...-CraftSound-backwards-compatibility.patch} | 0 .../0556-MC-4-Fix-item-position-desync.patch | 63 ++++++++++ ...0557-Player-Chunk-Load-Unload-Events.patch | 32 +++++ ...8-Optimize-Dynamic-get-Missing-Keys.patch} | 0 ...9-Expose-LivingEntity-hurt-direction.patch | 26 ++++ ...OBSTRUCTED-reason-to-BedEnterResult.patch} | 4 +- ...-invalid-ingredient-lists-in-Villag.patch} | 4 +- .../server/0562-added-PlayerTradeEvent.patch | 40 ++++++ .../0563-Implement-TargetHitEvent.patch | 42 +++++++ ...564-Additional-Block-Material-API-s.patch} | 12 +- .../0565-Fix-harming-potion-dupe.patch} | 32 ++--- ...get-Material-from-Boats-and-Minecar.patch} | 36 ++---- .../server/0567-Cache-burn-durations.patch | 36 ++++++ ...ob-spawner-spawn-egg-transformation.patch} | 16 +-- ...ment-PlayerFlowerPotManipulateEvent.patch} | 29 ++--- ...event-not-being-called-in-adventure.patch} | 14 +-- .../0571-Zombie-API-breaking-doors.patch | 27 ++++ ...572-Fix-nerfed-slime-when-splitting.patch} | 4 +- .../0573-Add-EntityLoadCrossbowEvent.patch | 39 ++++++ .../0574-Guardian-beam-workaround.patch | 20 +++ .../0575-Added-WorldGameRuleChangeEvent.patch | 98 +++++++++++++++ 53 files changed, 654 insertions(+), 952 deletions(-) rename patches/{api-unmapped => api}/0240-Add-PlayerShearBlockEvent.patch (100%) rename patches/{api-unmapped => api}/0241-Enable-multi-release-plugin-jars.patch (94%) rename patches/{api-unmapped => api}/0242-Player-Chunk-Load-Unload-Events.patch (100%) rename patches/{api-unmapped => api}/0243-Expose-LivingEntity-hurt-direction.patch (100%) rename patches/{api-unmapped/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch => api/0244-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} (100%) rename patches/{api-unmapped/0244-Added-PlayerTradeEvent.patch => api/0245-Added-PlayerTradeEvent.patch} (100%) rename patches/{api-unmapped => api}/0246-Add-TargetHitEvent-API.patch (100%) rename patches/{api-unmapped => api}/0247-Additional-Block-Material-API-s.patch (92%) rename patches/{api-unmapped => api}/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch (100%) rename patches/{api-unmapped => api}/0249-Add-PlayerFlowerPotManipulateEvent.patch (100%) rename patches/{api-unmapped => api}/0250-Zombie-API-breaking-doors.patch (100%) rename patches/{api-unmapped => api}/0251-Add-EntityLoadCrossbowEvent.patch (100%) rename patches/{api-unmapped => api}/0252-Added-WorldGameRuleChangeEvent.patch (100%) rename patches/{server-remapped => removed/1.17}/0626-Optimized-tick-ready-check.patch (99%) delete mode 100644 patches/server-remapped/0608-Added-missing-default-perms-for-commands.patch delete mode 100644 patches/server-remapped/0609-Add-PlayerShearBlockEvent.patch delete mode 100644 patches/server-remapped/0615-MC-4-Fix-item-position-desync.patch delete mode 100644 patches/server-remapped/0616-Player-Chunk-Load-Unload-Events.patch delete mode 100644 patches/server-remapped/0618-Expose-LivingEntity-hurt-direction.patch delete mode 100644 patches/server-remapped/0621-added-PlayerTradeEvent.patch delete mode 100644 patches/server-remapped/0622-Implement-TargetHitEvent.patch delete mode 100644 patches/server-remapped/0627-Cache-burn-durations.patch delete mode 100644 patches/server-remapped/0631-Zombie-API-breaking-doors.patch delete mode 100644 patches/server-remapped/0633-Add-EntityLoadCrossbowEvent.patch delete mode 100644 patches/server-remapped/0634-Guardian-beam-workaround.patch delete mode 100644 patches/server-remapped/0635-Added-WorldGameRuleChangeEvent.patch create mode 100644 patches/server/0549-Added-missing-default-perms-for-commands.patch create mode 100644 patches/server/0550-Add-PlayerShearBlockEvent.patch rename patches/{server-remapped/0610-Add-warning-for-servers-not-running-on-Java-16.patch => server/0551-Add-warning-for-servers-not-running-on-Java-16.patch} (84%) rename patches/{server-remapped/0611-Set-spigots-verbose-world-setting-to-false-by-def.patch => server/0552-Set-spigots-verbose-world-setting-to-false-by-def.patch} (65%) rename patches/{server-remapped/0612-Fix-curing-zombie-villager-discount-exploit.patch => server/0553-Fix-curing-zombie-villager-discount-exploit.patch} (62%) rename patches/{server-remapped/0613-Limit-recipe-packets.patch => server/0554-Limit-recipe-packets.patch} (60%) rename patches/{server-remapped/0614-Fix-CraftSound-backwards-compatibility.patch => server/0555-Fix-CraftSound-backwards-compatibility.patch} (100%) create mode 100644 patches/server/0556-MC-4-Fix-item-position-desync.patch create mode 100644 patches/server/0557-Player-Chunk-Load-Unload-Events.patch rename patches/{server-remapped/0617-Optimize-Dynamic-get-Missing-Keys.patch => server/0558-Optimize-Dynamic-get-Missing-Keys.patch} (100%) create mode 100644 patches/server/0559-Expose-LivingEntity-hurt-direction.patch rename patches/{server-remapped/0619-Add-OBSTRUCTED-reason-to-BedEnterResult.patch => server/0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} (86%) rename patches/{server-remapped/0620-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch => server/0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch} (85%) create mode 100644 patches/server/0562-added-PlayerTradeEvent.patch create mode 100644 patches/server/0563-Implement-TargetHitEvent.patch rename patches/{server-remapped/0623-Additional-Block-Material-API-s.patch => server/0564-Additional-Block-Material-API-s.patch} (68%) rename patches/{server-remapped/0624-Fix-harming-potion-dupe.patch => server/0565-Fix-harming-potion-dupe.patch} (66%) rename patches/{server-remapped/0625-Implement-API-to-get-Material-from-Boats-and-Minecar.patch => server/0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch} (66%) create mode 100644 patches/server/0567-Cache-burn-durations.patch rename patches/{server-remapped/0628-Allow-disabling-mob-spawner-spawn-egg-transformation.patch => server/0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch} (77%) rename patches/{server-remapped/0629-Implement-PlayerFlowerPotManipulateEvent.patch => server/0569-Implement-PlayerFlowerPotManipulateEvent.patch} (62%) rename patches/{server-remapped/0630-Fix-interact-event-not-being-called-in-adventure.patch => server/0570-Fix-interact-event-not-being-called-in-adventure.patch} (70%) create mode 100644 patches/server/0571-Zombie-API-breaking-doors.patch rename patches/{server-remapped/0632-Fix-nerfed-slime-when-splitting.patch => server/0572-Fix-nerfed-slime-when-splitting.patch} (83%) create mode 100644 patches/server/0573-Add-EntityLoadCrossbowEvent.patch create mode 100644 patches/server/0574-Guardian-beam-workaround.patch create mode 100644 patches/server/0575-Added-WorldGameRuleChangeEvent.patch diff --git a/patches/api-unmapped/0240-Add-PlayerShearBlockEvent.patch b/patches/api/0240-Add-PlayerShearBlockEvent.patch similarity index 100% rename from patches/api-unmapped/0240-Add-PlayerShearBlockEvent.patch rename to patches/api/0240-Add-PlayerShearBlockEvent.patch diff --git a/patches/api-unmapped/0241-Enable-multi-release-plugin-jars.patch b/patches/api/0241-Enable-multi-release-plugin-jars.patch similarity index 94% rename from patches/api-unmapped/0241-Enable-multi-release-plugin-jars.patch rename to patches/api/0241-Enable-multi-release-plugin-jars.patch index 9f71d1c074..215e2b9054 100644 --- a/patches/api-unmapped/0241-Enable-multi-release-plugin-jars.patch +++ b/patches/api/0241-Enable-multi-release-plugin-jars.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Enable multi-release plugin jars diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 11e5618ff66385574ba04db0942a75227cf8eb0f..c833cee9fddd12afdfe6bde1435559819b9ad656 100644 +index 6b5d7c350c216b7a234d96ecacae1d39a1acd814..18cf36020bca7c174a775de75241f149ef4e45e7 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java @@ -58,7 +58,18 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot diff --git a/patches/api-unmapped/0242-Player-Chunk-Load-Unload-Events.patch b/patches/api/0242-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from patches/api-unmapped/0242-Player-Chunk-Load-Unload-Events.patch rename to patches/api/0242-Player-Chunk-Load-Unload-Events.patch diff --git a/patches/api-unmapped/0243-Expose-LivingEntity-hurt-direction.patch b/patches/api/0243-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from patches/api-unmapped/0243-Expose-LivingEntity-hurt-direction.patch rename to patches/api/0243-Expose-LivingEntity-hurt-direction.patch diff --git a/patches/api-unmapped/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/api/0244-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from patches/api-unmapped/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/api/0244-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/patches/api-unmapped/0244-Added-PlayerTradeEvent.patch b/patches/api/0245-Added-PlayerTradeEvent.patch similarity index 100% rename from patches/api-unmapped/0244-Added-PlayerTradeEvent.patch rename to patches/api/0245-Added-PlayerTradeEvent.patch diff --git a/patches/api-unmapped/0246-Add-TargetHitEvent-API.patch b/patches/api/0246-Add-TargetHitEvent-API.patch similarity index 100% rename from patches/api-unmapped/0246-Add-TargetHitEvent-API.patch rename to patches/api/0246-Add-TargetHitEvent-API.patch diff --git a/patches/api-unmapped/0247-Additional-Block-Material-API-s.patch b/patches/api/0247-Additional-Block-Material-API-s.patch similarity index 92% rename from patches/api-unmapped/0247-Additional-Block-Material-API-s.patch rename to patches/api/0247-Additional-Block-Material-API-s.patch index 87283b0984..c16d0c6a64 100644 --- a/patches/api-unmapped/0247-Additional-Block-Material-API-s.patch +++ b/patches/api/0247-Additional-Block-Material-API-s.patch @@ -9,10 +9,10 @@ process to do this in the Bukkit API Adds API for buildable, replaceable, burnable too. diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 6933fd6ad353a2d008c4a64c52a64bf36bd8035c..0c72d00ad238ab69d7ae0941e3ecb6c86e71624d 100644 +index e759a03ccf7b341db36f455879e0004a6d6d4d07..b3c127a3d4c554c08e500497a54755e626342dd3 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java -@@ -427,6 +427,42 @@ public interface Block extends Metadatable { +@@ -428,6 +428,42 @@ public interface Block extends Metadatable { */ boolean isLiquid(); diff --git a/patches/api-unmapped/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch b/patches/api/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch similarity index 100% rename from patches/api-unmapped/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch rename to patches/api/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch diff --git a/patches/api-unmapped/0249-Add-PlayerFlowerPotManipulateEvent.patch b/patches/api/0249-Add-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from patches/api-unmapped/0249-Add-PlayerFlowerPotManipulateEvent.patch rename to patches/api/0249-Add-PlayerFlowerPotManipulateEvent.patch diff --git a/patches/api-unmapped/0250-Zombie-API-breaking-doors.patch b/patches/api/0250-Zombie-API-breaking-doors.patch similarity index 100% rename from patches/api-unmapped/0250-Zombie-API-breaking-doors.patch rename to patches/api/0250-Zombie-API-breaking-doors.patch diff --git a/patches/api-unmapped/0251-Add-EntityLoadCrossbowEvent.patch b/patches/api/0251-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from patches/api-unmapped/0251-Add-EntityLoadCrossbowEvent.patch rename to patches/api/0251-Add-EntityLoadCrossbowEvent.patch diff --git a/patches/api-unmapped/0252-Added-WorldGameRuleChangeEvent.patch b/patches/api/0252-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from patches/api-unmapped/0252-Added-WorldGameRuleChangeEvent.patch rename to patches/api/0252-Added-WorldGameRuleChangeEvent.patch diff --git a/patches/server-remapped/0626-Optimized-tick-ready-check.patch b/patches/removed/1.17/0626-Optimized-tick-ready-check.patch similarity index 99% rename from patches/server-remapped/0626-Optimized-tick-ready-check.patch rename to patches/removed/1.17/0626-Optimized-tick-ready-check.patch index 3dd32bb45a..a054be2fb3 100644 --- a/patches/server-remapped/0626-Optimized-tick-ready-check.patch +++ b/patches/removed/1.17/0626-Optimized-tick-ready-check.patch @@ -3,6 +3,7 @@ From: lukas Date: Sun, 27 Dec 2020 17:19:51 +0100 Subject: [PATCH] Optimized tick ready check +1.17: Needs to be reworked or dropped diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index 066d5f7ee93351bff67c0d39ee9d940ac51515d8..b89cefc8890774dbc64fd6bddeb038d2ee36d485 100644 diff --git a/patches/server-remapped/0608-Added-missing-default-perms-for-commands.patch b/patches/server-remapped/0608-Added-missing-default-perms-for-commands.patch deleted file mode 100644 index 25843d00d1..0000000000 --- a/patches/server-remapped/0608-Added-missing-default-perms-for-commands.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 16 Nov 2020 12:01:52 -0800 -Subject: [PATCH] Added missing default perms for commands - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -index d5f4ece060b61de9ca5292d1f2411c709de5ece2..f0a57d225b81a505ff12425155ba838d8fad990c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -@@ -31,6 +31,59 @@ public final class CommandPermissions { - DefaultPermissions.registerPermission(PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands); -+ // Paper start -+ DefaultPermissions.registerPermission(PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "ban", "Allows the user to add players to banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "ban-ip", "Allows the user to add ip address to banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "banlist", "Allows the user to display banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "pardon", "Allows the user to remove entries from the banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "replaceitem", "Allows the user to replace items in inventories", PermissionDefault.OP, commands); // Remove in 1.17 (replaced by /item) -+ DefaultPermissions.registerPermission(PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands); -+ DefaultPermissions.registerPermission(PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands); -+ // Paper end - - DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands); - diff --git a/patches/server-remapped/0609-Add-PlayerShearBlockEvent.patch b/patches/server-remapped/0609-Add-PlayerShearBlockEvent.patch deleted file mode 100644 index c9ae36d161..0000000000 --- a/patches/server-remapped/0609-Add-PlayerShearBlockEvent.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Thu, 27 Aug 2020 15:02:48 -0400 -Subject: [PATCH] Add PlayerShearBlockEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java -index 1a01937f5250f3a529932dc2fdd9e1ebd9ae896a..125e646b39ef4a59be3989df16b5625c5504aac1 100644 ---- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java -@@ -1,5 +1,7 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts -+ - import java.util.Iterator; - import java.util.List; - import java.util.Random; -@@ -10,6 +12,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.Tag; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; -@@ -116,8 +119,19 @@ public class BeehiveBlock extends BaseEntityBlock { - - if (i >= 5) { - if (itemstack.getItem() == Items.SHEARS) { -+ // Paper start - Add PlayerShearBlockEvent -+ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); -+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3))); -+ if (!event.callEvent()) { -+ return InteractionResult.PASS; -+ } -+ // Paper end - world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.NEUTRAL, 1.0F, 1.0F); -- dropHoneycomb(world, pos); -+ // Paper start - Add PlayerShearBlockEvent -+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { -+ dropItem(world, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); -+ } -+ // Paper end - itemstack.hurtAndBreak(1, player, (entityhuman1) -> { - entityhuman1.broadcastBreakEvent(hand); - }); -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index baa587e73a71d6324bb7817fa4702a7c3a2db726..5f1853c3f22661809437bdb49f002482da7195f2 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -262,13 +262,13 @@ public class Block extends BlockBehaviour implements ItemLike { - - } - -- public static void popResource(Level world, BlockPos pos, ItemStack stack) { -- if (!world.isClientSide && !stack.isEmpty() && world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { -+ public static void popResource(Level world, BlockPos pos, ItemStack stack) { dropItem(world, pos, stack); } public static void dropItem(Level world, BlockPos blockposition, ItemStack itemstack) { // Paper - OBFHELPER -+ if (!world.isClientSide && !itemstack.isEmpty() && world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { - float f = 0.5F; - double d0 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; - double d1 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; - double d2 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; -- ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + d0, (double) pos.getY() + d1, (double) pos.getZ() + d2, stack); -+ ItemEntity entityitem = new ItemEntity(world, (double) blockposition.getX() + d0, (double) blockposition.getY() + d1, (double) blockposition.getZ() + d2, itemstack); - - entityitem.setDefaultPickUpDelay(); - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java -index fe528f7dee693982285ce035abd9929cb4e0cbdf..7cac13ad06ee7acfc3bdcbf79318dbfbd2a31e02 100644 ---- a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; - - import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.world.InteractionHand; -@@ -14,6 +15,7 @@ import net.minecraft.world.level.Level; - import net.minecraft.world.level.block.state.BlockBehaviour; - import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.phys.BlockHitResult; -+import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts - - public class PumpkinBlock extends StemGrownBlock { - -@@ -27,15 +29,26 @@ public class PumpkinBlock extends StemGrownBlock { - - if (itemstack.getItem() == Items.SHEARS) { - if (!world.isClientSide) { -+ // Paper start - Add PlayerShearBlockEvent -+ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); -+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4))); -+ if (!event.callEvent()) { -+ return InteractionResult.PASS; -+ } -+ // Paper end - Direction enumdirection = hit.getDirection(); - Direction enumdirection1 = enumdirection.getAxis() == Direction.Axis.Y ? player.getDirection().getOpposite() : enumdirection; - - world.playSound((Player) null, pos, SoundEvents.PUMPKIN_CARVE, SoundSource.BLOCKS, 1.0F, 1.0F); - world.setBlock(pos, (BlockState) Blocks.CARVED_PUMPKIN.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, enumdirection1), 11); -- ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) enumdirection1.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) enumdirection1.getStepZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4)); -+ // Paper start - Add PlayerShearBlockEvent -+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { -+ ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) enumdirection1.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) enumdirection1.getStepZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); -+ // Paper end - - entityitem.setDeltaMovement(0.05D * (double) enumdirection1.getStepX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double) enumdirection1.getStepZ() + world.random.nextDouble() * 0.02D); - world.addFreshEntity(entityitem); -+ } // Paper - Add PlayerShearBlockEvent - itemstack.hurtAndBreak(1, player, (entityhuman1) -> { - entityhuman1.broadcastBreakEvent(hand); - }); diff --git a/patches/server-remapped/0615-MC-4-Fix-item-position-desync.patch b/patches/server-remapped/0615-MC-4-Fix-item-position-desync.patch deleted file mode 100644 index 3d3624adc8..0000000000 --- a/patches/server-remapped/0615-MC-4-Fix-item-position-desync.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 8 Dec 2020 20:24:52 -0600 -Subject: [PATCH] MC-4: Fix item position desync - -This fixes item position desync (MC-4) by running the item coordinates -through the encode/decode methods of the packet that causes the precision -loss, which forces the server to lose the same precision as the client -keeping them in sync. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 652d87fc5d566dba8018c81676329f0e0bca471b..c56e7fb18f9a56c8025eb70a524f028b5942da37 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -474,4 +474,9 @@ public class PaperConfig { - private static void trackPluginScoreboards() { - trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); - } -+ -+ public static boolean fixEntityPositionDesync = true; -+ private static void fixEntityPositionDesync() { -+ fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); -+ } - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java -index cb10c87728b5f9062c4bdd1fe5e4b2c7a558f323..6b97d60d923e772c7284e674bc3f2e9a5a0ddead 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java -@@ -19,11 +19,11 @@ public class ClientboundMoveEntityPacket implements Packet { -+ private static final float[] SIN = (float[]) Util.make((new float[65536]), (afloat) -> { // Paper - decompile error - for (int i = 0; i < afloat.length; ++i) { - afloat[i] = (float) Math.sin((double) i * 3.141592653589793D * 2.0D / 65536.0D); - } -@@ -49,6 +49,7 @@ public class Mth { - return d0 < (double) i ? i - 1 : i; - } - -+ public static long floorLong(double d0) { return lfloor(d0); } // Paper - OBFHELPER - public static long lfloor(double d0) { - long i = (long) d0; - -diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 9311f9f411d09d4460f0be8235957fab9e195b7a..7476ae301fb4ee503944d39022cb25ccb19f1232 100644 ---- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -549,4 +549,16 @@ public class ItemEntity extends Entity { - public Packet getAddEntityPacket() { - return new ClientboundAddEntityPacket(this); - } -+ -+ // Paper start - fix MC-4 -+ public void setPosRaw(double x, double y, double z) { -+ if (com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) { -+ // encode/decode from PacketPlayOutEntity -+ x = Mth.floorLong(x * 4096.0D) * (1 / 4096.0D); -+ y = Mth.floorLong(y * 4096.0D) * (1 / 4096.0D); -+ z = Mth.floorLong(z * 4096.0D) * (1 / 4096.0D); -+ } -+ super.setPosRaw(x, y, z); -+ } -+ // Paper end - fix MC-4 - } diff --git a/patches/server-remapped/0616-Player-Chunk-Load-Unload-Events.patch b/patches/server-remapped/0616-Player-Chunk-Load-Unload-Events.patch deleted file mode 100644 index d7abc567f0..0000000000 --- a/patches/server-remapped/0616-Player-Chunk-Load-Unload-Events.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 5 Oct 2020 21:25:16 +0200 -Subject: [PATCH] Player Chunk Load/Unload Events - - -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 1b5f24920c46cd238a79f5a2857d26fa1c12b983..ff831ca0cbc0cabbf78178c609ccf70d78da7980 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -136,6 +136,8 @@ import net.minecraft.world.level.dimension.DimensionType; - import net.minecraft.world.level.portal.PortalInfo; - import net.minecraft.world.phys.AABB; - import net.minecraft.world.phys.Vec3; -+import io.papermc.paper.event.packet.PlayerChunkLoadEvent; // Paper -+import io.papermc.paper.event.packet.PlayerChunkUnloadEvent; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - import net.minecraft.world.Container; -@@ -2095,11 +2097,21 @@ public class ServerPlayer extends Player implements ContainerListener { - public void trackChunk(ChunkPos chunkcoordintpair, Packet packet, Packet packet1) { - this.connection.send(packet1); - this.connection.send(packet); -+ // Paper start -+ if(PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0){ -+ new PlayerChunkLoadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); -+ } -+ // Paper end - } - - public void untrackChunk(ChunkPos chunkcoordintpair) { - if (this.isAlive()) { - this.connection.send(new ClientboundForgetLevelChunkPacket(chunkcoordintpair.x, chunkcoordintpair.z)); -+ // Paper start -+ if(PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0){ -+ new PlayerChunkUnloadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); -+ } -+ // Paper end - } - - } diff --git a/patches/server-remapped/0618-Expose-LivingEntity-hurt-direction.patch b/patches/server-remapped/0618-Expose-LivingEntity-hurt-direction.patch deleted file mode 100644 index d179506896..0000000000 --- a/patches/server-remapped/0618-Expose-LivingEntity-hurt-direction.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 13 Dec 2020 05:32:05 +0200 -Subject: [PATCH] Expose LivingEntity hurt direction - - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 57b933afdbb2136ed48170da6945eb2b92edb4db..02ddb84c563b3149c4f1b0e24899ce8a21ad61bb 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -160,7 +160,7 @@ public abstract class LivingEntity extends Entity { - public int removeStingerTime; - public int hurtTime; - public int hurtDuration; -- public float hurtDir; -+ public float hurtDir; public final float getHurtDirection() { return hurtDir; } public final void setHurtDirection(float hurtDirection) { this.hurtDir = hurtDirection; } // Paper - OBFHELPER - public int deathTime; - public float oAttackAnim; - public float attackAnim; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 170bb1124ee396a85dd64baed8110e39823ad849..a8d21382d5859edfd12e01a48924ce780790b4b7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -818,5 +818,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { - getHandle().take(((CraftItem) item).getHandle(), quantity); - } -+ -+ @Override -+ public float getHurtDirection() { -+ return getHandle().getHurtDirection(); -+ } -+ -+ @Override -+ public void setHurtDirection(float hurtDirection) { -+ getHandle().setHurtDirection(hurtDirection); -+ } - // Paper end - } diff --git a/patches/server-remapped/0621-added-PlayerTradeEvent.patch b/patches/server-remapped/0621-added-PlayerTradeEvent.patch deleted file mode 100644 index 3589365354..0000000000 --- a/patches/server-remapped/0621-added-PlayerTradeEvent.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 2 Jul 2020 16:12:10 -0700 -Subject: [PATCH] added PlayerTradeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 40ab66f888f30a5506e3aa96a4b32485452e8978..87dd6c012bf1ca6a1e8df44dc0957c4c67d02adc 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -91,7 +91,7 @@ import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; - public abstract class Mob extends LivingEntity { - - private static final EntityDataAccessor DATA_MOB_FLAGS_ID = SynchedEntityData.defineId(Mob.class, EntityDataSerializers.BYTE); -- public int ambientSoundTime; -+ public int ambientSoundTime;public void setAmbientSoundTime(int time) { this.ambientSoundTime = time; } // Paper - OBFHELPER - protected int xpReward; - protected LookControl lookControl; - protected MoveControl moveControl; -@@ -293,6 +293,7 @@ public abstract class Mob extends LivingEntity { - this.entityData.define(Mob.DATA_MOB_FLAGS_ID, (byte) 0); - } - -+ public int getAmbientSoundInterval() { return getAmbientSoundInterval(); } // Paper - OBFHELPER - public int getAmbientSoundInterval() { - return 80; - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -index 335000713279b7964c5172937483678c671bfed1..d31b773f8aff09c9f214662aa3aa0c904119e12c 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -37,6 +37,9 @@ import org.bukkit.craftbukkit.inventory.CraftMerchant; - import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; - import org.bukkit.event.entity.VillagerAcquireTradeEvent; - // CraftBukkit end -+// Paper start -+import io.papermc.paper.event.player.PlayerTradeEvent; -+// Paper end - - public abstract class AbstractVillager extends AgableMob implements Npc, Merchant { - -@@ -133,16 +136,27 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan - - @Override - public void notifyTrade(MerchantOffer offer) { -- offer.increaseUses(); -- this.ambientSoundTime = -this.getAmbientSoundInterval(); -- this.rewardTradeXp(offer); -+ // Paper - moved down -+ // Paper start - if (this.tradingPlayer instanceof ServerPlayer) { -- CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, offer.getResult()); -+ PlayerTradeEvent event = new PlayerTradeEvent(((ServerPlayer) this.tradingPlayer).getBukkitEntity(), (org.bukkit.entity.AbstractVillager) this.getBukkitEntity(), offer.asBukkit(), true, true); -+ event.callEvent(); -+ if (!event.isCancelled()) { -+ MerchantOffer recipe = CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft(); -+ if (event.willIncreaseTradeUses()) recipe.increaseUses(); -+ this.setAmbientSoundTime(-getAmbientSoundInterval()); -+ if (event.isRewardingExp()) this.rewardTradeXp(recipe); -+ CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, recipe.getResult()); -+ } -+ } else { -+ offer.increaseUses(); -+ this.setAmbientSoundTime(-getAmbientSoundInterval()); -+ this.rewardTradeXp(offer); - } -- -+ // Paper end - } - -- protected abstract void rewardTradeXp(MerchantOffer offer); -+ protected abstract void rewardTradeXp(MerchantOffer offer); public void rewardTradeXp(MerchantOffer merchantrecipe) { this.rewardTradeXp(merchantrecipe); } // Paper - OBFHELPER - - @Override - public boolean showProgressBar() { diff --git a/patches/server-remapped/0622-Implement-TargetHitEvent.patch b/patches/server-remapped/0622-Implement-TargetHitEvent.patch deleted file mode 100644 index bc8c6c48be..0000000000 --- a/patches/server-remapped/0622-Implement-TargetHitEvent.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Wed, 25 Nov 2020 23:20:44 -0800 -Subject: [PATCH] Implement TargetHitEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/TargetBlock.java b/src/main/java/net/minecraft/world/level/block/TargetBlock.java -index bbaf90b30b07c97321541b8fe15d47975a34161d..a7215c9b9f0f191bbfe95cb1185c99a8d21ff785 100644 ---- a/src/main/java/net/minecraft/world/level/block/TargetBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/TargetBlock.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.TargetHitEvent; // Paper - Need to import because 'io' class exists in nms - import java.util.Random; - import net.minecraft.advancements.CriteriaTriggers; - import net.minecraft.core.BlockPos; -@@ -34,13 +35,17 @@ public class TargetBlock extends Block { - @Override - public void onProjectileHit(Level world, BlockState state, BlockHitResult hit, Projectile projectile) { - int i = updateRedstoneOutput((LevelAccessor) world, state, hit, (Entity) projectile); -- Entity entity = projectile.getOwner(); -+ // Paper start -+ } -+ private static void awardTargetHitCriteria(Projectile iprojectile, BlockHitResult movingobjectpositionblock, int i) { -+ // Paper end -+ Entity entity = iprojectile.getOwner(); - - if (entity instanceof ServerPlayer) { - ServerPlayer entityplayer = (ServerPlayer) entity; - - entityplayer.awardStat(Stats.TARGET_HIT); -- CriteriaTriggers.TARGET_BLOCK_HIT.trigger(entityplayer, projectile, hit.getLocation(), i); -+ CriteriaTriggers.TARGET_BLOCK_HIT.trigger(entityplayer, iprojectile, movingobjectpositionblock.getLocation(), i); - } - - } -@@ -49,6 +54,20 @@ public class TargetBlock extends Block { - int i = getRedstoneStrength(movingobjectpositionblock, movingobjectpositionblock.getLocation()); - int j = entity instanceof AbstractArrow ? 20 : 8; - -+ // Paper start -+ if (entity instanceof Projectile) { -+ final Projectile projectile = (Projectile) entity; -+ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, movingobjectpositionblock.getBlockPos()); -+ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(movingobjectpositionblock.getDirection()); -+ final TargetHitEvent targetHitEvent = new TargetHitEvent((org.bukkit.entity.Projectile) projectile.getBukkitEntity(), craftBlock, blockFace, i); -+ if (targetHitEvent.callEvent()) { -+ i = targetHitEvent.getSignalStrength(); -+ awardTargetHitCriteria(projectile, movingobjectpositionblock, i); -+ } else { -+ return i; -+ } -+ } -+ // Paper end - if (!world.getBlockTicks().a(movingobjectpositionblock.getBlockPos(), state.getBlock())) { - setOutputPower(world, state, i, movingobjectpositionblock.getBlockPos(), j); - } diff --git a/patches/server-remapped/0627-Cache-burn-durations.patch b/patches/server-remapped/0627-Cache-burn-durations.patch deleted file mode 100644 index 4163e2cc84..0000000000 --- a/patches/server-remapped/0627-Cache-burn-durations.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas -Date: Sun, 27 Dec 2020 16:47:00 +0100 -Subject: [PATCH] Cache burn durations - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 4126a36dbc7750108a883f0be14dcb0d2e6d7ae8..f47b46cebd43faa509b8139d2a51cc8f87615893 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.block.entity; - -+import com.google.common.collect.ImmutableMap; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; -@@ -111,7 +112,15 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - this.recipeType = recipeType; - } - -+ private static Map cachedBurnDurations = null; // Paper - cache burn durations -+ -+ public static Map getBurnDurations() { return getFuel(); } // Paper - OBFHELPER - public static Map getFuel() { -+ // Paper start - cache burn durations -+ if(cachedBurnDurations != null) { -+ return cachedBurnDurations; -+ } -+ // Paper end - Map map = Maps.newLinkedHashMap(); - - add(map, (ItemLike) Items.LAVA_BUCKET, 20000); -@@ -174,7 +183,10 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - add(map, (ItemLike) Blocks.FLETCHING_TABLE, 300); - add(map, (ItemLike) Blocks.SMITHING_TABLE, 300); - add(map, (ItemLike) Blocks.COMPOSTER, 300); -- return map; -+ // Paper start - cache burn durations -+ cachedBurnDurations = ImmutableMap.copyOf(map); -+ return cachedBurnDurations; -+ // Paper end - } - - // CraftBukkit start - add fields and methods -@@ -428,7 +440,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - } else { - Item item = fuel.getItem(); - -- return (Integer) getFuel().getOrDefault(item, 0); -+ return getBurnDurations().getOrDefault(item, 0); // Paper - cache burn durations - } - } - -@@ -441,7 +453,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - // Paper end - - public static boolean isFuel(ItemStack stack) { -- return getFuel().containsKey(stack.getItem()); -+ return getBurnDurations().containsKey(stack.getItem()); // Paper - cache burn durations - } - - @Override diff --git a/patches/server-remapped/0631-Zombie-API-breaking-doors.patch b/patches/server-remapped/0631-Zombie-API-breaking-doors.patch deleted file mode 100644 index 63b6f1e733..0000000000 --- a/patches/server-remapped/0631-Zombie-API-breaking-doors.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 18 Nov 2020 11:32:46 -0800 -Subject: [PATCH] Zombie API - breaking doors - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 4105c1763d25824aac35d305a793823c1604eee8..77634a1e8e7539000f7db0b96f4548137af1a819 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -137,10 +137,12 @@ public class Zombie extends Monster { - return (Boolean) this.getEntityData().get(Zombie.DATA_DROWNED_CONVERSION_ID); - } - -+ public boolean canBreakDoors() { return this.canBreakDoors(); } // Paper - OBFHELPER - public boolean canBreakDoors() { - return this.canBreakDoors; - } - -+ public void setCanBreakDoors(boolean canBreakDoors) { this.setCanBreakDoors(canBreakDoors); } // Paper - OBFHELPER - public void setCanBreakDoors(boolean canBreakDoors) { - if (this.supportsBreakDoorGoal() && GoalUtils.hasGroundPathNavigation(this)) { - if (this.canBreakDoors != canBreakDoors) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 86f65c07806a118c49e900c59be86c2bd2eb124c..44f21b3b1c2f2fbc1f3f53931349b9a9426e97f8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -@@ -128,6 +128,16 @@ public class CraftZombie extends CraftMonster implements Zombie { - public void setShouldBurnInDay(boolean shouldBurnInDay) { - getHandle().setShouldBurnInDay(shouldBurnInDay); - } -+ -+ @Override -+ public boolean canBreakDoors() { -+ return getHandle().canBreakDoors(); -+ } -+ -+ @Override -+ public void setCanBreakDoors(boolean canBreakDoors) { -+ getHandle().setCanBreakDoors(canBreakDoors); -+ } - // Paper end - - @Override diff --git a/patches/server-remapped/0633-Add-EntityLoadCrossbowEvent.patch b/patches/server-remapped/0633-Add-EntityLoadCrossbowEvent.patch deleted file mode 100644 index 6eea724442..0000000000 --- a/patches/server-remapped/0633-Add-EntityLoadCrossbowEvent.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 7 Oct 2020 12:04:01 -0400 -Subject: [PATCH] Add EntityLoadCrossbowEvent - - -diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java -index e1e58b7035e6dbafdad0a04cc5333464fc4febb8..32e927375daeaf16f4ea763bc9f7c4a244797bba 100644 ---- a/src/main/java/net/minecraft/world/item/CrossbowItem.java -+++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java -@@ -3,6 +3,8 @@ package net.minecraft.world.item; - import com.google.common.collect.Lists; - import com.mojang.math.Quaternion; - import com.mojang.math.Vector3f; -+import org.bukkit.inventory.EquipmentSlot; // Paper -+import io.papermc.paper.event.entity.EntityLoadCrossbowEvent; // Paper - EntityLoadCrossbowEvent namespace conflicts - import java.util.List; - import java.util.Random; - import java.util.function.Predicate; -@@ -73,7 +75,11 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { - int j = this.getUseDuration(stack) - remainingUseTicks; - float f = getPowerForTime(j, stack); - -- if (f >= 1.0F && !isCharged(stack) && tryLoadProjectiles(user, stack)) { -+ // Paper start - EntityLoadCrossbowEvent -+ if (f >= 1.0F && !isCharged(stack) /*&& a(entityliving, itemstack)*/) { -+ final EntityLoadCrossbowEvent event = new EntityLoadCrossbowEvent(user.getBukkitLivingEntity(), stack.asBukkitMirror(), user.getUsedItemHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND); -+ if (!event.callEvent() || !attemptProjectileLoad(user, stack, event.shouldConsumeItem())) return; -+ // Paper end - setCharged(stack, true); - SoundSource soundcategory = user instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE; - -@@ -82,11 +88,14 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { - - } - -- private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack projectile) { -- int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, projectile); -+ private static boolean attemptProjectileLoad(LivingEntity ent, ItemStack bow) { return tryLoadProjectiles(ent, bow); } // Paper - EntityLoadCrossbowEvent - OBFHELPER -+ private static boolean attemptProjectileLoad(LivingEntity ent, ItemStack bow, boolean consume) { return a(ent, bow, consume); } // Paper - EntityLoadCrossbowEvent - OBFHELPER -+ private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack projectile) { return a(shooter, projectile, true); };// Paper - add consume -+ private static boolean a(LivingEntity entityliving, ItemStack itemstack, boolean consume) { // Paper - add consume -+ int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, itemstack); - int j = i == 0 ? 1 : 3; -- boolean flag = shooter instanceof Player && ((Player) shooter).abilities.instabuild; -- ItemStack itemstack1 = shooter.getProjectile(projectile); -+ boolean flag = !consume || entityliving instanceof Player && ((Player) entityliving).abilities.instabuild; // Paper - add consme -+ ItemStack itemstack1 = entityliving.getProjectile(itemstack); - ItemStack itemstack2 = itemstack1.copy(); - - for (int k = 0; k < j; ++k) { -@@ -103,7 +112,7 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { - // CraftBukkit end - } - -- if (!loadProjectile(shooter, projectile, itemstack1, k > 0, flag)) { -+ if (!loadProjectile(entityliving, itemstack, itemstack1, k > 0, flag)) { - return false; - } - } diff --git a/patches/server-remapped/0634-Guardian-beam-workaround.patch b/patches/server-remapped/0634-Guardian-beam-workaround.patch deleted file mode 100644 index c16b905697..0000000000 --- a/patches/server-remapped/0634-Guardian-beam-workaround.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabscap -Date: Sat, 19 Mar 2016 22:25:11 +0100 -Subject: [PATCH] Guardian beam workaround - -This patch is a workaround for MC-165595 - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java -index a02f492c279f4e859b44d52e150a2990cbe8275a..4f177e7396db00db56f2106068fc02b9c2618407 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java -@@ -6,7 +6,7 @@ import net.minecraft.network.protocol.Packet; - - public class ClientboundSetTimePacket implements Packet { - -- private long gameTime; -+ private long gameTime; private final void setWorldAge(final long age) { this.gameTime = age; } private final long getWorldAge() { return this.gameTime; } // Paper - OBFHELPER - private long dayTime; - - public ClientboundSetTimePacket() {} -@@ -21,6 +21,9 @@ public class ClientboundSetTimePacket implements Packet -Date: Sun, 20 Dec 2020 16:41:44 -0800 -Subject: [PATCH] Added WorldGameRuleChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java -index 87b968019fa10647522121c7b29094ed3e0dcf6d..7f124784dd7876cdb26f16e83deddf07dd9a198e 100644 ---- a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java -+++ b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java -@@ -31,7 +31,7 @@ public class GameRuleCommand { - CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); - T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(key); // CraftBukkit - -- t0.setFromArgument(context, "value"); -+ t0.setValue(context, "value", key); // Paper - commandlistenerwrapper.sendSuccess(new TranslatableComponent("commands.gamerule.set", new Object[]{key.getId(), t0.toString()}), true); - return t0.getCommandResult(); - } -diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java -index 6c996d34ef34879db1d65c39adf99ce2d64e5499..1e6f299571a25729dbf8c5b0cd115c1e842a8a3c 100644 ---- a/src/main/java/net/minecraft/world/level/GameRules.java -+++ b/src/main/java/net/minecraft/world/level/GameRules.java -@@ -25,6 +25,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerPlayer; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.event.world.WorldGameRuleChangeEvent; // Paper - - public class GameRules { - -@@ -177,8 +178,11 @@ public class GameRules { - } - - @Override -- protected void updateFromArgument(CommandContext context, String name) { -- this.value = BoolArgumentType.getBool(context, name); -+ protected void a(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { // Paper start -+ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(commandcontext, s))); -+ if (!event.callEvent()) return; -+ this.value = Boolean.parseBoolean(event.getValue()); -+ // Paper end - } - - public boolean get() { -@@ -237,8 +241,11 @@ public class GameRules { - } - - @Override -- protected void updateFromArgument(CommandContext context, String name) { -- this.value = IntegerArgumentType.getInteger(context, name); -+ protected void a(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { // Paper start -+ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(commandcontext, s))); -+ if (!event.callEvent()) return; -+ this.value = Integer.parseInt(event.getValue()); -+ // Paper end - } - - public int get() { -@@ -291,11 +298,13 @@ public class GameRules { - this.type = type; - } - -- protected abstract void updateFromArgument(CommandContext context, String name); -+ protected void updateValue(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { this.a(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER -+ protected abstract void a(CommandContext commandcontext, String s, GameRules.Key gameRuleKey); // Paper - -- public void setFromArgument(CommandContext context, String name) { -- this.updateFromArgument(context, name); -- this.onChanged(((CommandSourceStack) context.getSource()).getServer()); -+ public void setValue(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { this.b(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER -+ public void b(CommandContext commandcontext, String s, GameRules.Key gameRuleKey) { // Paper -+ this.updateValue(commandcontext, s, gameRuleKey); // Paper -+ this.onChanged(((CommandSourceStack) commandcontext.getSource()).getServer()); - } - - public void onChanged(@Nullable MinecraftServer server) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index aaf97c13babce3b0ffc639ef950d59d1eba1398a..f497b9e11a075a84ff0a2117eb79d0532e4a326f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2345,8 +2345,13 @@ public class CraftWorld implements World { - - if (!isGameRule(rule)) return false; - -+ // Paper start -+ GameRule gameRule = GameRule.getByName(rule); -+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, gameRule, value); -+ if (!event.callEvent()) return false; -+ // Paper end - GameRules.Value handle = getHandle().getGameRules().getRule(getGameRulesNMS().get(rule)); -- handle.deserialize(value); -+ handle.deserialize(event.getValue().toString()); // Paper - handle.onChanged(getHandle().getServer()); - return true; - } -@@ -2381,8 +2386,12 @@ public class CraftWorld implements World { - - if (!isGameRule(rule.getName())) return false; - -+ // Paper start -+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, rule, String.valueOf(newValue)); -+ if (!event.callEvent()) return false; -+ // Paper end - GameRules.Value handle = getHandle().getGameRules().getRule(getGameRulesNMS().get(rule.getName())); -- handle.deserialize(newValue.toString()); -+ handle.deserialize(event.getValue().toString()); // Paper - handle.onChanged(getHandle().getServer()); - return true; - } diff --git a/patches/server/0549-Added-missing-default-perms-for-commands.patch b/patches/server/0549-Added-missing-default-perms-for-commands.patch new file mode 100644 index 0000000000..e9e468da5e --- /dev/null +++ b/patches/server/0549-Added-missing-default-perms-for-commands.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 16 Nov 2020 12:01:52 -0800 +Subject: [PATCH] Added missing default perms for commands + + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java +index ca30f9c590f792caa8f1b76d7219e9121d932673..6cc517b394bafefce50d877761e5b2eee8e14c78 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java +@@ -31,6 +31,59 @@ public final class CommandPermissions { + DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands); ++ // Paper start ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban", "Allows the user to add players to banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban-ip", "Allows the user to add ip address to banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "banlist", "Allows the user to display banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "pardon", "Allows the user to remove entries from the banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "item", "Allows the user to replace items in inventories", PermissionDefault.OP, commands); // Remove in 1.17 (replaced by /item) ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands); ++ // Paper end + + DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands); + diff --git a/patches/server/0550-Add-PlayerShearBlockEvent.patch b/patches/server/0550-Add-PlayerShearBlockEvent.patch new file mode 100644 index 0000000000..0fde3c457f --- /dev/null +++ b/patches/server/0550-Add-PlayerShearBlockEvent.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Thu, 27 Aug 2020 15:02:48 -0400 +Subject: [PATCH] Add PlayerShearBlockEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java +index 96bc2cc1e3005a5273b8834569f5dee5c3a08293..d3b85a29662d33d458cfd4d7942b8e2d2264b750 100644 +--- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java +@@ -115,7 +115,7 @@ public class BeehiveBlock extends BaseEntityBlock { + } + + public static void dropHoneycomb(Level world, BlockPos pos) { +- popResource(world, pos, new ItemStack(Items.HONEYCOMB, 3)); ++ popResource(world, pos, new ItemStack(Items.HONEYCOMB, 3)); // Paper - conflict on change, item needs to be set below + } + + @Override +@@ -128,8 +128,19 @@ public class BeehiveBlock extends BaseEntityBlock { + Item item = itemstack.getItem(); + + if (itemstack.is(Items.SHEARS)) { ++ // Paper start - Add PlayerShearBlockEvent ++ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), net.minecraft.server.MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); ++ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3))); ++ if (!event.callEvent()) { ++ return InteractionResult.PASS; ++ } ++ // Paper end + world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.NEUTRAL, 1.0F, 1.0F); +- BeehiveBlock.dropHoneycomb(world, pos); ++ // Paper start - Add PlayerShearBlockEvent ++ for (org.bukkit.inventory.ItemStack itemDrop : event.getDrops()) { ++ popResource(world, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(itemDrop)); ++ } ++ // Paper end + itemstack.hurtAndBreak(1, player, (entityhuman1) -> { + entityhuman1.broadcastBreakEvent(hand); + }); +diff --git a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java +index 0e8cbe7a465edc31b78b7e47a928435f9c2b6bd9..f998598a34315389dd74b82e4b9c8448f0aae253 100644 +--- a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java +@@ -27,13 +27,24 @@ public class PumpkinBlock extends StemGrownBlock { + ItemStack itemStack = player.getItemInHand(hand); + if (itemStack.is(Items.SHEARS)) { + if (!world.isClientSide) { ++ // Paper start - Add PlayerShearBlockEvent ++ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), net.minecraft.server.MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); ++ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4))); ++ if (!event.callEvent()) { ++ return InteractionResult.PASS; ++ } ++ // Paper end + Direction direction = hit.getDirection(); + Direction direction2 = direction.getAxis() == Direction.Axis.Y ? player.getDirection().getOpposite() : direction; + world.playSound((Player)null, pos, SoundEvents.PUMPKIN_CARVE, SoundSource.BLOCKS, 1.0F, 1.0F); + world.setBlock(pos, Blocks.CARVED_PUMPKIN.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, direction2), 11); +- ItemEntity itemEntity = new ItemEntity(world, (double)pos.getX() + 0.5D + (double)direction2.getStepX() * 0.65D, (double)pos.getY() + 0.1D, (double)pos.getZ() + 0.5D + (double)direction2.getStepZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4)); ++ // Paper start - Add PlayerShearBlockEvent ++ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { ++ ItemEntity itemEntity = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) direction2.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) direction2.getStepZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); ++ // Paper end + itemEntity.setDeltaMovement(0.05D * (double)direction2.getStepX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double)direction2.getStepZ() + world.random.nextDouble() * 0.02D); + world.addFreshEntity(itemEntity); ++ } // Paper - Add PlayerShearBlockEvent + itemStack.hurtAndBreak(1, player, (playerx) -> { + playerx.broadcastBreakEvent(hand); + }); diff --git a/patches/server-remapped/0610-Add-warning-for-servers-not-running-on-Java-16.patch b/patches/server/0551-Add-warning-for-servers-not-running-on-Java-16.patch similarity index 84% rename from patches/server-remapped/0610-Add-warning-for-servers-not-running-on-Java-16.patch rename to patches/server/0551-Add-warning-for-servers-not-running-on-Java-16.patch index ce4786d7fc..81a48dfbbd 100644 --- a/patches/server-remapped/0610-Add-warning-for-servers-not-running-on-Java-16.patch +++ b/patches/server/0551-Add-warning-for-servers-not-running-on-Java-16.patch @@ -59,22 +59,14 @@ index 0000000000000000000000000000000000000000..fdf3ff8894e5e202229d1be52fe3c92e + } +} diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 954dce690852da87a37e7797c6f9f549242e511a..c83f2636ae93d92381e019d5b13ac82c5a1d30bf 100644 +index 9bd2255d31bcfd4574f8d1caf598f9141aa9e3c1..c7432ccffc024f171a2868b4eb0dca4860b7f8c4 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -180,6 +180,7 @@ import org.bukkit.event.server.ServerLoadEvent; - - import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot -+import io.papermc.paper.util.PaperJvmChecker; // Paper - - public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { - -@@ -1075,6 +1076,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; + for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !this.chatSpamTickCount.compareAndSet(spam, spam - 1); ) ; if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable + if (recipeSpamPackets.get() > 0) recipeSpamPackets.getAndDecrement(); // Paper /* Use thread-safe field access instead - if (this.chatThrottle > 0) { - --this.chatThrottle; -@@ -2786,6 +2790,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + if (this.chatSpamTickCount > 0) { + --this.chatSpamTickCount; +@@ -2794,6 +2796,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @Override public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) { + // Paper start -+ if (!Bukkit.isPrimaryThread()) { -+ if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { ++ if (!org.bukkit.Bukkit.isPrimaryThread()) { ++ if (recipeSpamPackets.addAndGet(com.destroystokyo.paper.PaperConfig.autoRecipeIncrement) > com.destroystokyo.paper.PaperConfig.autoRecipeLimit) { + server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper + return; + } @@ -71,4 +56,4 @@ index ccfe5a1ec1e9895f7462b7c676fee80903502a88..e50e42cce60c725cdd981d8927e379c5 + // Paper end PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); this.player.resetLastActionTime(); - if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu.isSynched(this.player) && this.player.containerMenu instanceof RecipeBookMenu) { + if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu instanceof RecipeBookMenu) { diff --git a/patches/server-remapped/0614-Fix-CraftSound-backwards-compatibility.patch b/patches/server/0555-Fix-CraftSound-backwards-compatibility.patch similarity index 100% rename from patches/server-remapped/0614-Fix-CraftSound-backwards-compatibility.patch rename to patches/server/0555-Fix-CraftSound-backwards-compatibility.patch diff --git a/patches/server/0556-MC-4-Fix-item-position-desync.patch b/patches/server/0556-MC-4-Fix-item-position-desync.patch new file mode 100644 index 0000000000..aaad2cd0d1 --- /dev/null +++ b/patches/server/0556-MC-4-Fix-item-position-desync.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 8 Dec 2020 20:24:52 -0600 +Subject: [PATCH] MC-4: Fix item position desync + +This fixes item position desync (MC-4) by running the item coordinates +through the encode/decode methods of the packet that causes the precision +loss, which forces the server to lose the same precision as the client +keeping them in sync. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index 652d87fc5d566dba8018c81676329f0e0bca471b..c56e7fb18f9a56c8025eb70a524f028b5942da37 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -474,4 +474,9 @@ public class PaperConfig { + private static void trackPluginScoreboards() { + trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); + } ++ ++ public static boolean fixEntityPositionDesync = true; ++ private static void fixEntityPositionDesync() { ++ fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); ++ } + } +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java +index b30c08bfb8c55161543a4ef09f2e462e0a1fe4ae..ec93f5300cc7d423ec0d292f0f8443f900d72dab 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java +@@ -21,11 +21,11 @@ public abstract class ClientboundMoveEntityPacket implements Packet +Date: Mon, 5 Oct 2020 21:25:16 +0200 +Subject: [PATCH] Player Chunk Load/Unload Events + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 41e6164fc9f3aa54028e5db1331df743126e55e2..5a87875b03740053d8cde6d81c57703d0b0ef57e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -2065,11 +2065,21 @@ public class ServerPlayer extends Player { + public void trackChunk(ChunkPos chunkcoordintpair, Packet packet, Packet packet1) { + this.connection.send(packet1); + this.connection.send(packet); ++ // Paper start ++ if(io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0){ ++ new io.papermc.paper.event.packet.PlayerChunkLoadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); ++ } ++ // Paper end + } + + public void untrackChunk(ChunkPos chunkPos) { + if (this.isAlive()) { + this.connection.send(new ClientboundForgetLevelChunkPacket(chunkPos.x, chunkPos.z)); ++ // Paper start ++ if(io.papermc.paper.event.packet.PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0){ ++ new io.papermc.paper.event.packet.PlayerChunkUnloadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkPos.longKey), this.getBukkitEntity()).callEvent(); ++ } ++ // Paper end + } + + } diff --git a/patches/server-remapped/0617-Optimize-Dynamic-get-Missing-Keys.patch b/patches/server/0558-Optimize-Dynamic-get-Missing-Keys.patch similarity index 100% rename from patches/server-remapped/0617-Optimize-Dynamic-get-Missing-Keys.patch rename to patches/server/0558-Optimize-Dynamic-get-Missing-Keys.patch diff --git a/patches/server/0559-Expose-LivingEntity-hurt-direction.patch b/patches/server/0559-Expose-LivingEntity-hurt-direction.patch new file mode 100644 index 0000000000..06745550e6 --- /dev/null +++ b/patches/server/0559-Expose-LivingEntity-hurt-direction.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa +Date: Sun, 13 Dec 2020 05:32:05 +0200 +Subject: [PATCH] Expose LivingEntity hurt direction + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 18635227a39c96e350fbb8ee9918c41c7a645aa6..2ca223324cc079e397852c30c969a05814585cde 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -818,5 +818,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { + getHandle().take(((CraftItem) item).getHandle(), quantity); + } ++ ++ @Override ++ public float getHurtDirection() { ++ return getHandle().hurtDir; ++ } ++ ++ @Override ++ public void setHurtDirection(float hurtDirection) { ++ getHandle().hurtDir = hurtDirection; ++ } + // Paper end + } diff --git a/patches/server-remapped/0619-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server/0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 86% rename from patches/server-remapped/0619-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/server/0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch index d2162d0415..56f636a0c1 100644 --- a/patches/server-remapped/0619-Add-OBSTRUCTED-reason-to-BedEnterResult.patch +++ b/patches/server/0560-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 64cfa14aa4e32430a6970fd4f3654a56146ba807..34c7b1213b3f83ff1a1f2d606a9c25e57fea8ef3 100644 +index fc9c63b73211d05321776648d6ba9c54f14ba83d..0f120d72816667ef8d50502b1e7e7dc3848f0ab4 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -259,6 +259,10 @@ public class CraftEventFactory { +@@ -257,6 +257,10 @@ public class CraftEventFactory { return BedEnterResult.TOO_FAR_AWAY; case NOT_SAFE: return BedEnterResult.NOT_SAFE; diff --git a/patches/server-remapped/0620-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server/0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch similarity index 85% rename from patches/server-remapped/0620-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch rename to patches/server/0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch index f57f5ee833..f8e8f443d3 100644 --- a/patches/server-remapped/0620-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch +++ b/patches/server/0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Do not crash from invalid ingredient lists in diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -index 407a68edf6408400f1a6c5bb1a6cbbfae08ac2cd..335000713279b7964c5172937483678c671bfed1 100644 +index 2610d9cd849aa38cc7a67aef21223707e85682ec..4a7b657265cbbc91ae85409abb3db29cfc555a2c 100644 --- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -270,7 +270,11 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan +@@ -279,7 +279,11 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa Bukkit.getPluginManager().callEvent(event); } if (!event.isCancelled()) { diff --git a/patches/server/0562-added-PlayerTradeEvent.patch b/patches/server/0562-added-PlayerTradeEvent.patch new file mode 100644 index 0000000000..c2539b44bd --- /dev/null +++ b/patches/server/0562-added-PlayerTradeEvent.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 2 Jul 2020 16:12:10 -0700 +Subject: [PATCH] added PlayerTradeEvent + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +index 4a7b657265cbbc91ae85409abb3db29cfc555a2c..e59a77c80a1bbe62aaa61bd4792d21b12c895a5c 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -140,13 +140,24 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa + + @Override + public void notifyTrade(MerchantOffer offer) { +- offer.increaseUses(); +- this.ambientSoundTime = -this.getAmbientSoundInterval(); +- this.rewardTradeXp(offer); ++ // Paper - moved down ++ // Paper start + if (this.tradingPlayer instanceof ServerPlayer) { +- CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, offer.getResult()); ++ io.papermc.paper.event.player.PlayerTradeEvent event = new io.papermc.paper.event.player.PlayerTradeEvent(((ServerPlayer) this.tradingPlayer).getBukkitEntity(), (org.bukkit.entity.AbstractVillager) this.getBukkitEntity(), offer.asBukkit(), true, true); ++ event.callEvent(); ++ if (!event.isCancelled()) { ++ MerchantOffer recipe = CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft(); ++ if (event.willIncreaseTradeUses()) recipe.increaseUses(); ++ this.ambientSoundTime = -this.getAmbientSoundInterval(); ++ if (event.isRewardingExp()) this.rewardTradeXp(recipe); ++ CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, recipe.getResult()); ++ } ++ } else { ++ offer.increaseUses(); ++ this.ambientSoundTime = -getAmbientSoundInterval(); ++ this.rewardTradeXp(offer); + } +- ++ // Paper end + } + + protected abstract void rewardTradeXp(MerchantOffer offer); diff --git a/patches/server/0563-Implement-TargetHitEvent.patch b/patches/server/0563-Implement-TargetHitEvent.patch new file mode 100644 index 0000000000..f746559a49 --- /dev/null +++ b/patches/server/0563-Implement-TargetHitEvent.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Wed, 25 Nov 2020 23:20:44 -0800 +Subject: [PATCH] Implement TargetHitEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/TargetBlock.java b/src/main/java/net/minecraft/world/level/block/TargetBlock.java +index 3f29d7dec834fda549db938cd7f3dc3b9ad67de3..18e8dbd7971e83a69953d203b02d8cd8d456e434 100644 +--- a/src/main/java/net/minecraft/world/level/block/TargetBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TargetBlock.java +@@ -35,6 +35,10 @@ public class TargetBlock extends Block { + @Override + public void onProjectileHit(Level world, BlockState state, BlockHitResult hit, Projectile projectile) { + int i = updateRedstoneOutput(world, state, hit, projectile); ++ // Paper start ++ } ++ private static void awardTargetHitCriteria(Projectile projectile, BlockHitResult hit, int i) { ++ // Paper end + Entity entity = projectile.getOwner(); + if (entity instanceof ServerPlayer) { + ServerPlayer serverPlayer = (ServerPlayer)entity; +@@ -47,6 +51,20 @@ public class TargetBlock extends Block { + private static int updateRedstoneOutput(LevelAccessor world, BlockState state, BlockHitResult hitResult, Entity entity) { + int i = getRedstoneStrength(hitResult, hitResult.getLocation()); + int j = entity instanceof AbstractArrow ? 20 : 8; ++ // Paper start ++ if (entity instanceof Projectile) { ++ final Projectile projectile = (Projectile) entity; ++ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, hitResult.getBlockPos()); ++ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(hitResult.getDirection()); ++ final io.papermc.paper.event.block.TargetHitEvent targetHitEvent = new io.papermc.paper.event.block.TargetHitEvent((org.bukkit.entity.Projectile) projectile.getBukkitEntity(), craftBlock, blockFace, i); ++ if (targetHitEvent.callEvent()) { ++ i = targetHitEvent.getSignalStrength(); ++ awardTargetHitCriteria(projectile, hitResult, i); ++ } else { ++ return i; ++ } ++ } ++ // Paper end + if (!world.getBlockTicks().hasScheduledTick(hitResult.getBlockPos(), state.getBlock())) { + setOutputPower(world, state, i, hitResult.getBlockPos(), j); + } diff --git a/patches/server-remapped/0623-Additional-Block-Material-API-s.patch b/patches/server/0564-Additional-Block-Material-API-s.patch similarity index 68% rename from patches/server-remapped/0623-Additional-Block-Material-API-s.patch rename to patches/server/0564-Additional-Block-Material-API-s.patch index 6aa789f4d3..eef88ca622 100644 --- a/patches/server-remapped/0623-Additional-Block-Material-API-s.patch +++ b/patches/server/0564-Additional-Block-Material-API-s.patch @@ -9,21 +9,21 @@ process to do this in the Bukkit API Adds API for buildable, replaceable, burnable too. diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 9defb202761296a825d035e27ddc51e17a311647..376b0497c28a35d7ea615397c87b2558b95c596a 100644 +index 597ac36c6f6748ecfbf64920da172758814b8061..f69ad3ccfe885f3acde930ea844d3bc471ce661b 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -618,6 +618,25 @@ public class CraftBlock implements Block { - return getNMS().getMaterial().isLiquid(); +@@ -623,6 +623,25 @@ public class CraftBlock implements Block { + return this.getNMS().getMaterial().isLiquid(); } + // Paper start + @Override + public boolean isBuildable() { -+ return getNMS().getMaterial().isBuildable(); ++ return getNMS().getMaterial().isSolid(); // This is in fact isSolid, despite the fact that isSolid below returns blocksMotion + } + @Override + public boolean isBurnable() { -+ return getNMS().getMaterial().isBurnable(); ++ return getNMS().getMaterial().isFlammable(); + } + @Override + public boolean isReplaceable() { @@ -37,4 +37,4 @@ index 9defb202761296a825d035e27ddc51e17a311647..376b0497c28a35d7ea615397c87b2558 + @Override public PistonMoveReaction getPistonMoveReaction() { - return PistonMoveReaction.getById(getNMS().getPistonPushReaction().ordinal()); + return PistonMoveReaction.getById(this.getNMS().getPistonPushReaction().ordinal()); diff --git a/patches/server-remapped/0624-Fix-harming-potion-dupe.patch b/patches/server/0565-Fix-harming-potion-dupe.patch similarity index 66% rename from patches/server-remapped/0624-Fix-harming-potion-dupe.patch rename to patches/server/0565-Fix-harming-potion-dupe.patch index e5c11d28d2..c8bd7c539a 100644 --- a/patches/server-remapped/0624-Fix-harming-potion-dupe.patch +++ b/patches/server/0565-Fix-harming-potion-dupe.patch @@ -8,18 +8,10 @@ Before this patch, instant effects would be applied before the potion ItemStack This patch makes it so that instant effects are applied after the potion ItemStack is removed, and the glass bottle is only put into the player's inventory if the player is not dead. Otherwise, the glass bottle is dropped on the ground. diff --git a/src/main/java/net/minecraft/world/item/PotionItem.java b/src/main/java/net/minecraft/world/item/PotionItem.java -index 36ccec8ad2f605d5bceae476e26c2fbfbdae39d8..ba2bc044b259b0a5ba590d4ae6fd36e5c415ddff 100644 +index 9014bf545205504bee2d727399d39090ebe3d210..12a29323d99dcc7880fe3c7c9709a755d9cbf43e 100644 --- a/src/main/java/net/minecraft/world/item/PotionItem.java +++ b/src/main/java/net/minecraft/world/item/PotionItem.java -@@ -15,6 +15,7 @@ import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.alchemy.Potion; - import net.minecraft.world.item.alchemy.PotionUtils; - import net.minecraft.world.item.alchemy.Potions; -+import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.Level; - - public class PotionItem extends Item { -@@ -36,6 +37,7 @@ public class PotionItem extends Item { +@@ -42,6 +42,7 @@ public class PotionItem extends Item { CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) entityhuman, stack); } @@ -27,33 +19,31 @@ index 36ccec8ad2f605d5bceae476e26c2fbfbdae39d8..ba2bc044b259b0a5ba590d4ae6fd36e5 if (!world.isClientSide) { List list = PotionUtils.getMobEffects(stack); Iterator iterator = list.iterator(); -@@ -44,7 +46,7 @@ public class PotionItem extends Item { +@@ -50,7 +51,7 @@ public class PotionItem extends Item { MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); - if (mobeffect.getMobEffect().isInstant()) { -- mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D); + if (mobeffect.getEffect().isInstantenous()) { +- mobeffect.getEffect().applyInstantenousEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D); + instantLater.add(mobeffect); // Paper - Fix harming potion dupe } else { user.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit } -@@ -58,7 +60,20 @@ public class PotionItem extends Item { +@@ -64,7 +65,18 @@ public class PotionItem extends Item { } } + // Paper start - Fix harming potion dupe + for (MobEffectInstance mobeffect : instantLater) { -+ mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D); ++ mobeffect.getEffect().applyInstantenousEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D); + } + // Paper end -+ - if (entityhuman == null || !entityhuman.abilities.instabuild) { + if (entityhuman == null || !entityhuman.getAbilities().instabuild) { + // Paper start - Fix harming potion dupe -+ if (user.getHealth() <= 0 && !user.level.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY)) { -+ user.dropItem(new ItemStack(Items.GLASS_BOTTLE), 0); -+ return ItemStack.NULL_ITEM; ++ if (user.getHealth() <= 0 && !user.level.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_KEEPINVENTORY)) { ++ user.spawnAtLocation(new ItemStack(Items.GLASS_BOTTLE), 0); ++ return ItemStack.EMPTY; + } + // Paper end -+ if (stack.isEmpty()) { return new ItemStack(Items.GLASS_BOTTLE); } diff --git a/patches/server-remapped/0625-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/patches/server/0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch similarity index 66% rename from patches/server-remapped/0625-Implement-API-to-get-Material-from-Boats-and-Minecar.patch rename to patches/server/0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch index f956ace9fd..fffb32a201 100644 --- a/patches/server-remapped/0625-Implement-API-to-get-Material-from-Boats-and-Minecar.patch +++ b/patches/server/0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch @@ -4,40 +4,18 @@ Date: Thu, 31 Dec 2020 12:48:19 +1000 Subject: [PATCH] Implement API to get Material from Boats and Minecarts -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -index 4f82c6797fe9bbb1a29420ea15277be50e44808c..6a9c18540886979b2212bf7917a21753c9a9db3c 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -@@ -259,6 +259,7 @@ public class Boat extends Entity { - - } - -+ public final Item getBoatItem() { return this.getDropItem(); } // Paper - OBFHELPER - public Item getDropItem() { - switch (this.getBoatType()) { - case OAK: diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -index de8e9e8d18fb9cc6f49d98ab0c57faffec61e5b5..5928ab97b91062963e5cca0a8ec50f2bc3a7ff96 100644 +index 47f95fb26793fbf6c5c37187d4958ee5ba93f060..39e7aeb409a39bd8cd8200b18dd3da1e427519ab 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -@@ -1,7 +1,9 @@ - package org.bukkit.craftbukkit.entity; - -+import org.bukkit.Material; // Paper - import org.bukkit.TreeSpecies; - import org.bukkit.craftbukkit.CraftServer; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper - import org.bukkit.entity.Boat; - import org.bukkit.entity.EntityType; - -@@ -65,6 +67,13 @@ public class CraftBoat extends CraftVehicle implements Boat { - getHandle().landBoats = workOnLand; +@@ -65,6 +65,13 @@ public class CraftBoat extends CraftVehicle implements Boat { + this.getHandle().landBoats = workOnLand; } + // Paper start + @Override -+ public Material getBoatMaterial() { -+ return CraftMagicNumbers.getMaterial(getHandle().getBoatItem()); ++ public org.bukkit.Material getBoatMaterial() { ++ return org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(getHandle().getDropItem()); + } + // Paper end + @@ -45,7 +23,7 @@ index de8e9e8d18fb9cc6f49d98ab0c57faffec61e5b5..5928ab97b91062963e5cca0a8ec50f2b public net.minecraft.world.entity.vehicle.Boat getHandle() { return (net.minecraft.world.entity.vehicle.Boat) entity; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -index 55df92a4661e13a9085f325db0572a265a89948c..fb26b6125ad4090d87b2326add94ffaded82c8ef 100644 +index 053112d7411caa6f439bd344e74aff8c844d93ac..5b8a83b250987fe5c939ab06b1021621820ad56e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java @@ -1,8 +1,10 @@ @@ -60,7 +38,7 @@ index 55df92a4661e13a9085f325db0572a265a89948c..fb26b6125ad4090d87b2326add94ffad import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.block.data.CraftBlockData; @@ -68,6 +70,38 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart { - getHandle().setDerailedVelocityMod(derailed); + this.getHandle().setDerailedVelocityMod(derailed); } + // Paper start diff --git a/patches/server/0567-Cache-burn-durations.patch b/patches/server/0567-Cache-burn-durations.patch new file mode 100644 index 0000000000..d90289aac5 --- /dev/null +++ b/patches/server/0567-Cache-burn-durations.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lukas +Date: Sun, 27 Dec 2020 16:47:00 +0100 +Subject: [PATCH] Cache burn durations + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 627551db52a0ac1aff9f65f9fce7b9e3c07ad475..f1e44b57f8c77ee279b4be0853923dcd95f71f0a 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -124,7 +124,13 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + this.recipeType = recipeType; + } + ++ private static Map cachedBurnDurations = null; // Paper - cache burn durations + public static Map getFuel() { ++ // Paper start - cache burn durations ++ if(cachedBurnDurations != null) { ++ return cachedBurnDurations; ++ } ++ // Paper end + Map map = Maps.newLinkedHashMap(); + + AbstractFurnaceBlockEntity.add(map, (ItemLike) Items.LAVA_BUCKET, 20000); +@@ -189,7 +195,10 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + AbstractFurnaceBlockEntity.add(map, (ItemLike) Blocks.COMPOSTER, 300); + AbstractFurnaceBlockEntity.add(map, (ItemLike) Blocks.AZALEA, 100); + AbstractFurnaceBlockEntity.add(map, (ItemLike) Blocks.FLOWERING_AZALEA, 100); +- return map; ++ // Paper start - cache burn durations ++ cachedBurnDurations = com.google.common.collect.ImmutableMap.copyOf(map); ++ return cachedBurnDurations; ++ // Paper end + } + + // CraftBukkit start - add fields and methods diff --git a/patches/server-remapped/0628-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server/0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch similarity index 77% rename from patches/server-remapped/0628-Allow-disabling-mob-spawner-spawn-egg-transformation.patch rename to patches/server/0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch index efb245db2f..25231c3e9e 100644 --- a/patches/server-remapped/0628-Allow-disabling-mob-spawner-spawn-egg-transformation.patch +++ b/patches/server/0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch @@ -5,24 +5,26 @@ Subject: [PATCH] Allow disabling mob spawner spawn egg transformation diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a3b3e3e04b7a5e3a351992e06870cc91fbd8adc8..b48067c71f9de18ba40e970e2832f6245984a218 100644 +index 618f47567ca9d4704f4686d7ca789286866f080a..bedadfc8835fa0c834494eb10cef13fa1cdc5cf5 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -722,4 +722,9 @@ public class PaperWorldConfig { - private void fixCuringExploit() { +@@ -87,6 +87,11 @@ public class PaperWorldConfig { fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); } -+ + + public boolean disableMobSpawnerSpawnEggTransformation = false; + private void disableMobSpawnerSpawnEggTransformation() { + disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); + } - } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); diff --git a/src/main/java/net/minecraft/world/item/SpawnEggItem.java b/src/main/java/net/minecraft/world/item/SpawnEggItem.java -index 9aae1435a271bb17d6355e4c75ccbce78cb9d449..7904a2176253eaf48b47e06dd2e19758a673873c 100644 +index dd69c9b132fb52c60c44b3e029924412ecc28133..32a9a752e1afdcdaffa5198f3577856f742c9136 100644 --- a/src/main/java/net/minecraft/world/item/SpawnEggItem.java +++ b/src/main/java/net/minecraft/world/item/SpawnEggItem.java -@@ -60,7 +60,7 @@ public class SpawnEggItem extends Item { +@@ -61,7 +61,7 @@ public class SpawnEggItem extends Item { Direction enumdirection = context.getClickedFace(); BlockState iblockdata = world.getBlockState(blockposition); diff --git a/patches/server-remapped/0629-Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server/0569-Implement-PlayerFlowerPotManipulateEvent.patch similarity index 62% rename from patches/server-remapped/0629-Implement-PlayerFlowerPotManipulateEvent.patch rename to patches/server/0569-Implement-PlayerFlowerPotManipulateEvent.patch index 2c81edd9ad..8f512f54d6 100644 --- a/patches/server-remapped/0629-Implement-PlayerFlowerPotManipulateEvent.patch +++ b/patches/server/0569-Implement-PlayerFlowerPotManipulateEvent.patch @@ -5,31 +5,23 @@ Subject: [PATCH] Implement PlayerFlowerPotManipulateEvent diff --git a/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java b/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java -index ae74e70457f8f46ee71bf0902ade3468da272e81..a1d1f3416df8e313688fedad47dd264444d7c465 100644 +index 9a8fc69de43fcfeebcb31c895fa4b5868952fa0a..db05c1ea847d60ad45d33cd798cb34ad3f5cfd75 100644 --- a/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java +++ b/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java -@@ -20,6 +20,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType; - import net.minecraft.world.phys.BlockHitResult; - import net.minecraft.world.phys.shapes.CollisionContext; - import net.minecraft.world.phys.shapes.VoxelShape; -+import io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent; // Paper - - public class FlowerPotBlock extends Block { - -@@ -52,6 +53,27 @@ public class FlowerPotBlock extends Block { - boolean flag1 = this.content == Blocks.AIR; - - if (flag != flag1) { +@@ -52,6 +52,26 @@ public class FlowerPotBlock extends Block { + boolean bl = blockState.is(Blocks.AIR); + boolean bl2 = this.isEmpty(); + if (bl != bl2) { + // Paper start + org.bukkit.entity.Player player1 = (org.bukkit.entity.Player) player.getBukkitEntity(); -+ boolean placing = flag1; ++ boolean placing = bl2; + org.bukkit.block.Block bukkitblock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos); -+ org.bukkit.inventory.ItemStack bukkititemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack); ++ org.bukkit.inventory.ItemStack bukkititemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemStack); + org.bukkit.Material mat = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(content); + org.bukkit.inventory.ItemStack bukkititemstack1 = new org.bukkit.inventory.ItemStack(mat, 1); + org.bukkit.inventory.ItemStack whichitem = placing ? bukkititemstack : bukkititemstack1; + -+ PlayerFlowerPotManipulateEvent event = new PlayerFlowerPotManipulateEvent(player1, bukkitblock, whichitem, placing); ++ io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent event = new io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent(player1, bukkitblock, whichitem, placing); + player1.getServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { @@ -40,7 +32,6 @@ index ae74e70457f8f46ee71bf0902ade3468da272e81..a1d1f3416df8e313688fedad47dd2644 + return InteractionResult.PASS; + } + // Paper end -+ - if (flag1) { - world.setBlock(pos, block.defaultBlockState(), 3); + if (bl2) { + world.setBlock(pos, blockState, 3); player.awardStat(Stats.POT_FLOWER); diff --git a/patches/server-remapped/0630-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server/0570-Fix-interact-event-not-being-called-in-adventure.patch similarity index 70% rename from patches/server-remapped/0630-Fix-interact-event-not-being-called-in-adventure.patch rename to patches/server/0570-Fix-interact-event-not-being-called-in-adventure.patch index 5e69fe3a87..cc7e10b0fd 100644 --- a/patches/server-remapped/0630-Fix-interact-event-not-being-called-in-adventure.patch +++ b/patches/server/0570-Fix-interact-event-not-being-called-in-adventure.patch @@ -6,24 +6,24 @@ Subject: [PATCH] Fix interact event not being called in adventure Call PlayerInteractEvent when left-clicking on a block in adventure mode diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index e50e42cce60c725cdd981d8927e379c5760d9200..cb6568b622abeb939a1195f4656accc8a1c3f1fc 100644 +index 309b8e193ec67df0379d65ce77a2a095702fd024..df80023e43e7872e32e7b958ea0a5e82d86d43f7 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1701,7 +1701,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - MutableComponent ichatmutablecomponent = (new TranslatableComponent("build.tooHigh", new Object[]{this.server.getMaxBuildHeight()})).withStyle(ChatFormatting.RED); +@@ -1733,7 +1733,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + MutableComponent ichatmutablecomponent = (new TranslatableComponent("build.tooHigh", new Object[]{i - 1})).withStyle(ChatFormatting.RED); - this.player.connection.send(new ClientboundChatPacket(ichatmutablecomponent, ChatType.GAME_INFO, Util.NIL_UUID)); + this.player.sendMessage((Component) ichatmutablecomponent, ChatType.GAME_INFO, Util.NIL_UUID); - } else if (enuminteractionresult.shouldSwing()) { + } else if (enuminteractionresult.shouldSwing() && !this.player.gameMode.interactResult) { this.player.swing(enumhand, true); } } -@@ -2202,7 +2202,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2205,7 +2205,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser Vec3 vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); - HitResult movingobjectposition = this.player.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)); + HitResult movingobjectposition = this.player.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.player)); - if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK) { + if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK || this.player.gameMode.getGameModeForPlayer() == GameType.ADVENTURE) { // Paper - call PlayerInteractEvent when left-clicking on a block in adventure mode - CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.inventory.getSelected(), InteractionHand.MAIN_HAND); + CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND); } diff --git a/patches/server/0571-Zombie-API-breaking-doors.patch b/patches/server/0571-Zombie-API-breaking-doors.patch new file mode 100644 index 0000000000..0d301fa1a9 --- /dev/null +++ b/patches/server/0571-Zombie-API-breaking-doors.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 18 Nov 2020 11:32:46 -0800 +Subject: [PATCH] Zombie API - breaking doors + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +index 41b5059f6fde8a1afa8c70b983750854ac0207a6..0f6e26030807f5f3011a4bb0bcd598c4674fa772 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +@@ -128,6 +128,16 @@ public class CraftZombie extends CraftMonster implements Zombie { + public void setShouldBurnInDay(boolean shouldBurnInDay) { + getHandle().setShouldBurnInDay(shouldBurnInDay); + } ++ ++ @Override ++ public boolean canBreakDoors() { ++ return getHandle().canBreakDoors(); ++ } ++ ++ @Override ++ public void setCanBreakDoors(boolean canBreakDoors) { ++ getHandle().setCanBreakDoors(canBreakDoors); ++ } + // Paper end + + @Override diff --git a/patches/server-remapped/0632-Fix-nerfed-slime-when-splitting.patch b/patches/server/0572-Fix-nerfed-slime-when-splitting.patch similarity index 83% rename from patches/server-remapped/0632-Fix-nerfed-slime-when-splitting.patch rename to patches/server/0572-Fix-nerfed-slime-when-splitting.patch index 85d8576628..4ad2437b32 100644 --- a/patches/server-remapped/0632-Fix-nerfed-slime-when-splitting.patch +++ b/patches/server/0572-Fix-nerfed-slime-when-splitting.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix nerfed slime when splitting diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java -index 120ceb28ee3aee8a09cf67b45ac95d3d6613c133..2f04543c1c0a197f22fb26b2a38c7c79e6b4a63a 100644 +index 6a199e148929d8df9b1f39733dd821c503380973..31ca6e693acb7f2db9ea75a38ec6286ea1ed2bd4 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Slime.java +++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java -@@ -242,6 +242,7 @@ public class Slime extends Mob implements Enemy { +@@ -241,6 +241,7 @@ public class Slime extends Mob implements Enemy { entityslime.setPersistenceRequired(); } diff --git a/patches/server/0573-Add-EntityLoadCrossbowEvent.patch b/patches/server/0573-Add-EntityLoadCrossbowEvent.patch new file mode 100644 index 0000000000..8b93410c0d --- /dev/null +++ b/patches/server/0573-Add-EntityLoadCrossbowEvent.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Wed, 7 Oct 2020 12:04:01 -0400 +Subject: [PATCH] Add EntityLoadCrossbowEvent + + +diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java +index 35f3f3887c0696b757553af9a5997506c97b24c0..d670ac2b57ecbdd6ff5426c233e23e634d4f665d 100644 +--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java ++++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java +@@ -90,7 +90,11 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + int j = this.getUseDuration(stack) - remainingUseTicks; + float f = CrossbowItem.getPowerForTime(j, stack); + +- if (f >= 1.0F && !CrossbowItem.isCharged(stack) && CrossbowItem.tryLoadProjectiles(user, stack)) { ++ // Paper start - EntityLoadCrossbowEvent ++ if (f >= 1.0F && !CrossbowItem.isCharged(stack) /*&& CrossbowItem.tryLoadProjectiles(entityliving, itemstack)*/) { ++ final io.papermc.paper.event.entity.EntityLoadCrossbowEvent event = new io.papermc.paper.event.entity.EntityLoadCrossbowEvent(user.getBukkitLivingEntity(), stack.asBukkitMirror(), user.getUsedItemHand() == InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND); ++ if (!event.callEvent() || !tryLoadProjectiles(user, stack, event.shouldConsumeItem())) return; ++ // Paper end + CrossbowItem.setCharged(stack, true); + SoundSource soundcategory = user instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE; + +@@ -100,9 +104,14 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + } + + private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack projectile) { ++ // Paper start ++ return CrossbowItem.tryLoadProjectiles(shooter, projectile, true); ++ } ++ private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack projectile, boolean consume) { ++ // Paper end + int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, projectile); + int j = i == 0 ? 1 : 3; +- boolean flag = shooter instanceof Player && ((Player) shooter).getAbilities().instabuild; ++ boolean flag = !consume || shooter instanceof Player && ((Player) shooter).getAbilities().instabuild; // Paper - add consme + ItemStack itemstack1 = shooter.getProjectile(projectile); + ItemStack itemstack2 = itemstack1.copy(); + diff --git a/patches/server/0574-Guardian-beam-workaround.patch b/patches/server/0574-Guardian-beam-workaround.patch new file mode 100644 index 0000000000..5369300252 --- /dev/null +++ b/patches/server/0574-Guardian-beam-workaround.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gabscap +Date: Sat, 19 Mar 2016 22:25:11 +0100 +Subject: [PATCH] Guardian beam workaround + +This patch is a workaround for MC-165595 + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java +index 9ec6145fe04ec64bbee8ec6a837719caebdbc6f5..c96b63355b38053b0f7ede313fb4bdf0e1089796 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java +@@ -8,7 +8,7 @@ public class ClientboundSetTimePacket implements Packet +Date: Sun, 20 Dec 2020 16:41:44 -0800 +Subject: [PATCH] Added WorldGameRuleChangeEvent + + +diff --git a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java +index f2e53fbb067a3909f386386eb3b89dfe090ee096..6f6292e7945cec1bdc69632dbfb950d6af53df42 100644 +--- a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java +@@ -33,7 +33,7 @@ public class GameRuleCommand { + CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); + T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(key); // CraftBukkit + +- t0.setFromArgument(context, "value"); ++ t0.setFromArgument(context, "value", key); // Paper + commandlistenerwrapper.sendSuccess(new TranslatableComponent("commands.gamerule.set", new Object[]{key.getId(), t0.toString()}), true); + return t0.getCommandResult(); + } +diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java +index 888d812118c15c212284687ae5842a94f5715d52..e7ca5d6fb8922e7e8065864f736b06056be080a0 100644 +--- a/src/main/java/net/minecraft/world/level/GameRules.java ++++ b/src/main/java/net/minecraft/world/level/GameRules.java +@@ -261,10 +261,10 @@ public class GameRules { + this.type = type; + } + +- protected abstract void updateFromArgument(CommandContext context, String name); ++ protected abstract void updateFromArgument(CommandContext context, String name, GameRules.Key gameRuleKey); // Paper + +- public void setFromArgument(CommandContext context, String name) { +- this.updateFromArgument(context, name); ++ public void setFromArgument(CommandContext context, String name, GameRules.Key gameRuleKey) { // Paper ++ this.updateFromArgument(context, name, gameRuleKey); // Paper + this.onChanged(((CommandSourceStack) context.getSource()).getServer()); + } + +@@ -322,8 +322,11 @@ public class GameRules { + } + + @Override +- protected void updateFromArgument(CommandContext context, String name) { +- this.value = BoolArgumentType.getBool(context, name); ++ protected void updateFromArgument(CommandContext context, String name, GameRules.Key gameRuleKey) { // Paper start ++ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(context.getSource().getBukkitWorld(), context.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(context, name))); ++ if (!event.callEvent()) return; ++ this.value = Boolean.parseBoolean(event.getValue()); ++ // Paper end + } + + public boolean get() { +@@ -387,8 +390,11 @@ public class GameRules { + } + + @Override +- protected void updateFromArgument(CommandContext context, String name) { +- this.value = IntegerArgumentType.getInteger(context, name); ++ protected void updateFromArgument(CommandContext context, String name, GameRules.Key gameRuleKey) { // Paper start ++ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(context.getSource().getBukkitWorld(), context.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(context, name))); ++ if (!event.callEvent()) return; ++ this.value = Integer.parseInt(event.getValue()); ++ // Paper end + } + + public int get() { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index ed8c8b7ff07a58dfaf7bbb1e630a1e68cc0c29f3..fd01fc9708a62df9483c88ffeec6a0304f3708ca 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2363,8 +2363,13 @@ public class CraftWorld implements World { + + if (!this.isGameRule(rule)) return false; + ++ // Paper start ++ GameRule gameRule = GameRule.getByName(rule); ++ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, gameRule, value); ++ if (!event.callEvent()) return false; ++ // Paper end + GameRules.Value handle = this.getHandle().getGameRules().getRule(CraftWorld.getGameRulesNMS().get(rule)); +- handle.deserialize(value); ++ handle.deserialize(event.getValue()); // Paper + handle.onChanged(this.getHandle().getServer()); + return true; + } +@@ -2399,8 +2404,12 @@ public class CraftWorld implements World { + + if (!this.isGameRule(rule.getName())) return false; + ++ // Paper start ++ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, rule, String.valueOf(newValue)); ++ if (!event.callEvent()) return false; ++ // Paper end + GameRules.Value handle = this.getHandle().getGameRules().getRule(CraftWorld.getGameRulesNMS().get(rule.getName())); +- handle.deserialize(newValue.toString()); ++ handle.deserialize(event.getValue()); // Paper + handle.onChanged(this.getHandle().getServer()); + return true; + } From f777faa8c12ee62987d5e2927c4ecfd4a747374d Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Mon, 14 Jun 2021 12:17:47 -0700 Subject: [PATCH 122/226] more patches & fixes to existing patches --- ...3-Added-ServerResourcesReloadedEvent.patch | 0 .../0254-Add-BlockFailedDispenseEvent.patch | 0 ...5-Added-PlayerLecternPageChangeEvent.patch | 0 ...6-Added-PlayerLoomPatternSelectEvent.patch | 0 .../0257-Better-AnnotationTest-printout.patch | 4 +- ...xact-interaction-point-in-PlayerInte.patch | 0 ...g-for-servers-not-running-on-Java-16.patch | 1 + ...6-Added-ServerResourcesReloadedEvent.patch | 90 ------------------ ...9-Added-PlayerLecternPageChangeEvent.patch | 66 ------------- ...1-Added-PlayerLoomPatternSelectEvent.patch | 63 ------------- .../0645-Remove-stale-POIs.patch | 50 ---------- ...rbose-world-setting-to-false-by-def.patch} | 0 ...ng-zombie-villager-discount-exploit.patch} | 0 ....patch => 0553-Limit-recipe-packets.patch} | 0 ...-CraftSound-backwards-compatibility.patch} | 0 ... 0555-MC-4-Fix-item-position-desync.patch} | 0 ...556-Player-Chunk-Load-Unload-Events.patch} | 0 ...7-Optimize-Dynamic-get-Missing-Keys.patch} | 0 ...-Expose-LivingEntity-hurt-direction.patch} | 0 ...OBSTRUCTED-reason-to-BedEnterResult.patch} | 0 ...-invalid-ingredient-lists-in-Villag.patch} | 0 ...atch => 0561-added-PlayerTradeEvent.patch} | 0 ...ch => 0562-Implement-TargetHitEvent.patch} | 0 ...563-Additional-Block-Material-API-s.patch} | 0 ...tch => 0564-Fix-harming-potion-dupe.patch} | 0 ...get-Material-from-Boats-and-Minecar.patch} | 0 ....patch => 0566-Cache-burn-durations.patch} | 0 ...ob-spawner-spawn-egg-transformation.patch} | 0 ...ment-PlayerFlowerPotManipulateEvent.patch} | 0 ...event-not-being-called-in-adventure.patch} | 0 ...h => 0570-Zombie-API-breaking-doors.patch} | 0 ...571-Fix-nerfed-slime-when-splitting.patch} | 0 ...=> 0572-Add-EntityLoadCrossbowEvent.patch} | 0 ...ch => 0573-Guardian-beam-workaround.patch} | 4 +- ...0574-Added-WorldGameRuleChangeEvent.patch} | 0 ...5-Added-ServerResourcesReloadedEvent.patch | 54 +++++++++++ ...d-settings-for-mobs-picking-up-loot.patch} | 16 ++-- ...mplemented-BlockFailedDispenseEvent.patch} | 43 +++------ ...8-Added-PlayerLecternPageChangeEvent.patch | 46 ++++++++++ ...9-Added-PlayerLoomPatternSelectEvent.patch | 34 +++++++ ...nfigurable-door-breaking-difficulty.patch} | 92 ++++++++++--------- ...ty-commands-shall-not-be-dispatched.patch} | 4 +- ...I-to-expose-exact-interaction-point.patch} | 20 ++-- patches/server/0583-Remove-stale-POIs.patch | 22 +++++ 44 files changed, 244 insertions(+), 365 deletions(-) rename patches/{api-unmapped => api}/0253-Added-ServerResourcesReloadedEvent.patch (100%) rename patches/{api-unmapped => api}/0254-Add-BlockFailedDispenseEvent.patch (100%) rename patches/{api-unmapped => api}/0255-Added-PlayerLecternPageChangeEvent.patch (100%) rename patches/{api-unmapped => api}/0256-Added-PlayerLoomPatternSelectEvent.patch (100%) rename patches/{api-unmapped => api}/0257-Better-AnnotationTest-printout.patch (95%) rename patches/{api-unmapped => api}/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch (100%) rename patches/{server => removed/1.17}/0551-Add-warning-for-servers-not-running-on-Java-16.patch (99%) delete mode 100644 patches/server-remapped/0636-Added-ServerResourcesReloadedEvent.patch delete mode 100644 patches/server-remapped/0639-Added-PlayerLecternPageChangeEvent.patch delete mode 100644 patches/server-remapped/0641-Added-PlayerLoomPatternSelectEvent.patch delete mode 100644 patches/server-remapped/0645-Remove-stale-POIs.patch rename patches/server/{0552-Set-spigots-verbose-world-setting-to-false-by-def.patch => 0551-Set-spigots-verbose-world-setting-to-false-by-def.patch} (100%) rename patches/server/{0553-Fix-curing-zombie-villager-discount-exploit.patch => 0552-Fix-curing-zombie-villager-discount-exploit.patch} (100%) rename patches/server/{0554-Limit-recipe-packets.patch => 0553-Limit-recipe-packets.patch} (100%) rename patches/server/{0555-Fix-CraftSound-backwards-compatibility.patch => 0554-Fix-CraftSound-backwards-compatibility.patch} (100%) rename patches/server/{0556-MC-4-Fix-item-position-desync.patch => 0555-MC-4-Fix-item-position-desync.patch} (100%) rename patches/server/{0557-Player-Chunk-Load-Unload-Events.patch => 0556-Player-Chunk-Load-Unload-Events.patch} (100%) rename patches/server/{0558-Optimize-Dynamic-get-Missing-Keys.patch => 0557-Optimize-Dynamic-get-Missing-Keys.patch} (100%) rename patches/server/{0559-Expose-LivingEntity-hurt-direction.patch => 0558-Expose-LivingEntity-hurt-direction.patch} (100%) rename patches/server/{0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch => 0559-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} (100%) rename patches/server/{0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch => 0560-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch} (100%) rename patches/server/{0562-added-PlayerTradeEvent.patch => 0561-added-PlayerTradeEvent.patch} (100%) rename patches/server/{0563-Implement-TargetHitEvent.patch => 0562-Implement-TargetHitEvent.patch} (100%) rename patches/server/{0564-Additional-Block-Material-API-s.patch => 0563-Additional-Block-Material-API-s.patch} (100%) rename patches/server/{0565-Fix-harming-potion-dupe.patch => 0564-Fix-harming-potion-dupe.patch} (100%) rename patches/server/{0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch => 0565-Implement-API-to-get-Material-from-Boats-and-Minecar.patch} (100%) rename patches/server/{0567-Cache-burn-durations.patch => 0566-Cache-burn-durations.patch} (100%) rename patches/server/{0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch => 0567-Allow-disabling-mob-spawner-spawn-egg-transformation.patch} (100%) rename patches/server/{0569-Implement-PlayerFlowerPotManipulateEvent.patch => 0568-Implement-PlayerFlowerPotManipulateEvent.patch} (100%) rename patches/server/{0570-Fix-interact-event-not-being-called-in-adventure.patch => 0569-Fix-interact-event-not-being-called-in-adventure.patch} (100%) rename patches/server/{0571-Zombie-API-breaking-doors.patch => 0570-Zombie-API-breaking-doors.patch} (100%) rename patches/server/{0572-Fix-nerfed-slime-when-splitting.patch => 0571-Fix-nerfed-slime-when-splitting.patch} (100%) rename patches/server/{0573-Add-EntityLoadCrossbowEvent.patch => 0572-Add-EntityLoadCrossbowEvent.patch} (100%) rename patches/server/{0574-Guardian-beam-workaround.patch => 0573-Guardian-beam-workaround.patch} (90%) rename patches/server/{0575-Added-WorldGameRuleChangeEvent.patch => 0574-Added-WorldGameRuleChangeEvent.patch} (100%) create mode 100644 patches/server/0575-Added-ServerResourcesReloadedEvent.patch rename patches/{server-remapped/0637-Added-world-settings-for-mobs-picking-up-loot.patch => server/0576-Added-world-settings-for-mobs-picking-up-loot.patch} (82%) rename patches/{server-remapped/0638-Implemented-BlockFailedDispenseEvent.patch => server/0577-Implemented-BlockFailedDispenseEvent.patch} (55%) create mode 100644 patches/server/0578-Added-PlayerLecternPageChangeEvent.patch create mode 100644 patches/server/0579-Added-PlayerLoomPatternSelectEvent.patch rename patches/{server-remapped/0642-Configurable-door-breaking-difficulty.patch => server/0580-Configurable-door-breaking-difficulty.patch} (63%) rename patches/{server-remapped/0643-Empty-commands-shall-not-be-dispatched.patch => server/0581-Empty-commands-shall-not-be-dispatched.patch} (84%) rename patches/{server-remapped/0644-Implement-API-to-expose-exact-interaction-point.patch => server/0582-Implement-API-to-expose-exact-interaction-point.patch} (82%) create mode 100644 patches/server/0583-Remove-stale-POIs.patch diff --git a/patches/api-unmapped/0253-Added-ServerResourcesReloadedEvent.patch b/patches/api/0253-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from patches/api-unmapped/0253-Added-ServerResourcesReloadedEvent.patch rename to patches/api/0253-Added-ServerResourcesReloadedEvent.patch diff --git a/patches/api-unmapped/0254-Add-BlockFailedDispenseEvent.patch b/patches/api/0254-Add-BlockFailedDispenseEvent.patch similarity index 100% rename from patches/api-unmapped/0254-Add-BlockFailedDispenseEvent.patch rename to patches/api/0254-Add-BlockFailedDispenseEvent.patch diff --git a/patches/api-unmapped/0255-Added-PlayerLecternPageChangeEvent.patch b/patches/api/0255-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from patches/api-unmapped/0255-Added-PlayerLecternPageChangeEvent.patch rename to patches/api/0255-Added-PlayerLecternPageChangeEvent.patch diff --git a/patches/api-unmapped/0256-Added-PlayerLoomPatternSelectEvent.patch b/patches/api/0256-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from patches/api-unmapped/0256-Added-PlayerLoomPatternSelectEvent.patch rename to patches/api/0256-Added-PlayerLoomPatternSelectEvent.patch diff --git a/patches/api-unmapped/0257-Better-AnnotationTest-printout.patch b/patches/api/0257-Better-AnnotationTest-printout.patch similarity index 95% rename from patches/api-unmapped/0257-Better-AnnotationTest-printout.patch rename to patches/api/0257-Better-AnnotationTest-printout.patch index 2a40d2b44f..557bf7adf4 100644 --- a/patches/api-unmapped/0257-Better-AnnotationTest-printout.patch +++ b/patches/api/0257-Better-AnnotationTest-printout.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Better AnnotationTest printout diff --git a/pom.xml b/pom.xml -index 6b71d9a397dd5b72320402a47b8e7197d24e061c..73fbd5d5a591871a3a386fb5c455cd96a3992e7a 100644 +index aefaeec678b2f6b5ba1c15e43c4886eb9af6b143..33771618d2fd7591db020af57df358c891b11d6d 100644 --- a/pom.xml +++ b/pom.xml -@@ -257,6 +257,19 @@ +@@ -250,6 +250,19 @@ true diff --git a/patches/api-unmapped/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch b/patches/api/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch similarity index 100% rename from patches/api-unmapped/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch rename to patches/api/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch diff --git a/patches/server/0551-Add-warning-for-servers-not-running-on-Java-16.patch b/patches/removed/1.17/0551-Add-warning-for-servers-not-running-on-Java-16.patch similarity index 99% rename from patches/server/0551-Add-warning-for-servers-not-running-on-Java-16.patch rename to patches/removed/1.17/0551-Add-warning-for-servers-not-running-on-Java-16.patch index 81a48dfbbd..eba2d26c5e 100644 --- a/patches/server/0551-Add-warning-for-servers-not-running-on-Java-16.patch +++ b/patches/removed/1.17/0551-Add-warning-for-servers-not-running-on-Java-16.patch @@ -3,6 +3,7 @@ From: Kyle Wood Date: Wed, 2 Dec 2020 21:58:45 -0800 Subject: [PATCH] Add warning for servers not running on Java 16 +1.17: game requires java 16 diff --git a/src/main/java/io/papermc/paper/util/PaperJvmChecker.java b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java new file mode 100644 diff --git a/patches/server-remapped/0636-Added-ServerResourcesReloadedEvent.patch b/patches/server-remapped/0636-Added-ServerResourcesReloadedEvent.patch deleted file mode 100644 index 02aef6be64..0000000000 --- a/patches/server-remapped/0636-Added-ServerResourcesReloadedEvent.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Dec 2020 20:04:01 -0800 -Subject: [PATCH] Added ServerResourcesReloadedEvent - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index c83f2636ae93d92381e019d5b13ac82c5a1d30bf..892ca65d258b0745be95d7ef4886c49899b24d92 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2,9 +2,6 @@ package net.minecraft.server; - - import com.google.common.base.Splitter; - import com.google.common.collect.ImmutableList; --import co.aikar.timings.Timings; --import com.destroystokyo.paper.event.server.PaperServerListPingEvent; --import com.google.common.base.Stopwatch; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -181,6 +178,7 @@ import org.bukkit.event.server.ServerLoadEvent; - import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot - import io.papermc.paper.util.PaperJvmChecker; // Paper -+import io.papermc.paper.event.server.ServerResourcesReloadedEvent; // Paper - - public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { - -@@ -1934,9 +1932,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop reloadResources(Collection datapacks) { -+ return this.reloadServerResources(datapacks, ServerResourcesReloadedEvent.Cause.PLUGIN); -+ } -+ public CompletableFuture reloadServerResources(Collection collection, ServerResourcesReloadedEvent.Cause cause) { -+ // Paper end - CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { -- Stream stream = datapacks.stream(); // CraftBukkit - decompile error -+ Stream stream = collection.stream(); // CraftBukkit - decompile error - PackRepository resourcepackrepository = this.packRepository; - - this.packRepository.getClass(); -@@ -1947,9 +1951,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop collection, CommandSourceStack commandlistenerwrapper) { -- commandlistenerwrapper.getServer().reloadResources(collection).exceptionally((throwable) -> { -- ReloadCommand.LOGGER.warn("Failed to execute reload", throwable); -- commandlistenerwrapper.sendFailure(new TranslatableComponent("commands.reload.failure")); -+ commandlistenerwrapper.getServer().reloadServerResources(collection, ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally((throwable) -> { // Paper -+ CommandReload.LOGGER.warn("Failed to execute reload", throwable); -+ commandlistenerwrapper.sendFailureMessage(new ChatMessage("commands.reload.failure")); - return null; - }); - } -@@ -48,7 +49,7 @@ public class ReloadCommand { - WorldData savedata = minecraftserver.getWorldData(); - Collection collection = resourcepackrepository.getSelectedIds(); - Collection collection1 = discoverNewPacks(resourcepackrepository, savedata, collection); -- minecraftserver.reloadResources(collection1); -+ minecraftserver.reloadServerResources(collection1, ServerResourcesReloadedEvent.Cause.PLUGIN); // Paper - } - // CraftBukkit end - diff --git a/patches/server-remapped/0639-Added-PlayerLecternPageChangeEvent.patch b/patches/server-remapped/0639-Added-PlayerLecternPageChangeEvent.patch deleted file mode 100644 index b4eacbfa37..0000000000 --- a/patches/server-remapped/0639-Added-PlayerLecternPageChangeEvent.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 23 Nov 2020 12:58:51 -0800 -Subject: [PATCH] Added PlayerLecternPageChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -index bc39e7464646d712b085251dc0277a5b1ec0a393..b5d79635cd8b0eb6b17962450b347010aeb52654 100644 ---- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -561,6 +561,7 @@ public abstract class AbstractContainerMenu { - this.getSlot(slot).set(stack); - } - -+ public void setData(int index, int value) { this.setData(index, value); } // Paper - OBFHELPER - public void setData(int id, int value) { - ((DataSlot) this.dataSlots.get(id)).set(value); - } -diff --git a/src/main/java/net/minecraft/world/inventory/LecternMenu.java b/src/main/java/net/minecraft/world/inventory/LecternMenu.java -index 29e8dbc6be57faf50a8ca68eed6bf2e203b7e87a..a7be91a9336065899c409526a890e55f37b98751 100644 ---- a/src/main/java/net/minecraft/world/inventory/LecternMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/LecternMenu.java -@@ -11,6 +11,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - import org.bukkit.event.player.PlayerTakeLecternBookEvent; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerLecternPageChangeEvent; // Paper - - public class LecternMenu extends AbstractContainerMenu { - -@@ -58,6 +59,7 @@ public class LecternMenu extends AbstractContainerMenu { - @Override - public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { - int j; -+ PlayerLecternPageChangeEvent playerLecternPageChangeEvent; CraftInventoryLectern bukkitView; // Paper - - if (id >= 100) { - j = id - 100; -@@ -67,11 +69,25 @@ public class LecternMenu extends AbstractContainerMenu { - switch (id) { - case 1: - j = this.lecternData.get(0); -- this.setData(0, j - 1); -+ // Paper start -+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); -+ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, j, j - 1); -+ if (!playerLecternPageChangeEvent.callEvent()) { -+ return false; -+ } -+ this.setData(0, playerLecternPageChangeEvent.getNewPage()); -+ // Paper end - return true; - case 2: - j = this.lecternData.get(0); -- this.setData(0, j + 1); -+ // Paper start -+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); -+ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, j, j + 1); -+ if (!playerLecternPageChangeEvent.callEvent()) { -+ return false; -+ } -+ this.setData(0, playerLecternPageChangeEvent.getNewPage()); -+ // Paper end - return true; - case 3: - if (!player.mayBuild()) { diff --git a/patches/server-remapped/0641-Added-PlayerLoomPatternSelectEvent.patch b/patches/server-remapped/0641-Added-PlayerLoomPatternSelectEvent.patch deleted file mode 100644 index 3c2cf5afe6..0000000000 --- a/patches/server-remapped/0641-Added-PlayerLoomPatternSelectEvent.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 25 Nov 2020 16:33:27 -0800 -Subject: [PATCH] Added PlayerLoomPatternSelectEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java -index 3460fb2bb1451b8456a7fe42449ec4dbce641f40..0dc1b0b7181c0f93dcf6213c63baffcd4694d70c 100644 ---- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java -@@ -20,6 +20,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerLoomPatternSelectEvent; // Paper - - public class LoomMenu extends AbstractContainerMenu { - -@@ -39,7 +40,7 @@ public class LoomMenu extends AbstractContainerMenu { - } - // CraftBukkit end - private final ContainerLevelAccess access; -- private final DataSlot selectedBannerPatternIndex; -+ private final DataSlot selectedBannerPatternIndex; public final DataSlot getSelectedBannerPattern() { return this.selectedBannerPatternIndex; }; // Paper - OBFHELPER - private Runnable slotUpdateListener; - private final Slot bannerSlot; - private final Slot dyeSlot; -@@ -158,7 +159,22 @@ public class LoomMenu extends AbstractContainerMenu { - @Override - public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { - if (id > 0 && id <= BannerPattern.AVAILABLE_PATTERNS) { -- this.selectedBannerPatternIndex.set(id); -+ // Paper start -+ int enumBannerPatternTypeOrdinal = id; -+ PlayerLoomPatternSelectEvent event = new PlayerLoomPatternSelectEvent((Player) player.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.block.banner.PatternType.getByIdentifier(BannerPattern.values()[id].getIdentifier())); -+ if (!event.callEvent()) { -+ ((Player) player.getBukkitEntity()).updateInventory(); -+ return false; -+ } -+ for (BannerPattern nms : BannerPattern.values()) { -+ if (event.getPatternType().getIdentifier().equals(nms.getIdentifier())) { -+ enumBannerPatternTypeOrdinal = nms.ordinal(); -+ break; -+ } -+ } -+ ((Player) player.getBukkitEntity()).updateInventory(); -+ this.getSelectedBannerPattern().set(enumBannerPatternTypeOrdinal); -+ // Paper end - this.setupResultSlot(); - return true; - } else { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java b/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java -index 9ea01d5888a21b0dedb555d118a4dc07af2b50fd..9ee3f8bb2294fc552735a64efbddf661d39602c7 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BannerPattern.java -@@ -33,6 +33,7 @@ public enum BannerPattern { - this.hasPatternItem = flag; - } - -+ public String getIdentifier() { return this.getHashname(); } // Paper - OBFHELPER - public String getHashname() { - return this.hashname; - } diff --git a/patches/server-remapped/0645-Remove-stale-POIs.patch b/patches/server-remapped/0645-Remove-stale-POIs.patch deleted file mode 100644 index 561ae57f81..0000000000 --- a/patches/server-remapped/0645-Remove-stale-POIs.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 9 Jan 2021 14:17:07 +0100 -Subject: [PATCH] Remove stale POIs - - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index fe7b71fbb3963beafe93a5d86bebdd629c7ec8f2..9f1838d12b13d64f10871eb672ed2aec78d9936e 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -2071,6 +2071,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - }); - optional1.ifPresent((villageplacetype) -> { - this.getServer().execute(() -> { -+ // Paper start -+ if (!optional.isPresent() && this.getPoiStorage().test(blockposition1, com.google.common.base.Predicates.alwaysTrue())) { -+ this.getPoiStorage().remove(blockposition1); -+ } -+ // Paper end - this.getPoiManager().add(blockposition1, villageplacetype); - DebugPackets.sendPoiAddedPacket(this, blockposition1); - }); -@@ -2078,6 +2083,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - } - -+ public final PoiManager getPoiStorage() { return this.getPoiManager(); } // Paper - OBFHELPER - public PoiManager getPoiManager() { - return this.getChunkSource().getPoiManager(); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -index b9d32e3322c2cce1aca2a90df71b6175a6f8c548..25b26a78a55f98687ed22e986b54d5e9d47a16ea 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -@@ -54,6 +54,7 @@ public class PoiManager extends SectionStorage { - ((PoiSection) this.getOrCreate(SectionPos.of(pos).asLong())).add(pos, type); - } - -+ public void remove(BlockPos blockposition) { this.remove(blockposition); } // Paper - OBFHELPER - public void remove(BlockPos pos) { - ((PoiSection) this.getOrCreate(SectionPos.of(pos).asLong())).remove(pos); - } -@@ -138,6 +139,7 @@ public class PoiManager extends SectionStorage { - return ((PoiSection) this.getOrCreate(SectionPos.of(pos).asLong())).release(pos); - } - -+ public final boolean test(BlockPos blockposition, Predicate predicate) { return this.exists(blockposition, predicate); } // Paper - OBFHELPER - public boolean exists(BlockPos pos, Predicate predicate) { - return (Boolean) this.getOrLoad(SectionPos.of(pos).asLong()).map((villageplacesection) -> { - return villageplacesection.exists(pos, predicate); diff --git a/patches/server/0552-Set-spigots-verbose-world-setting-to-false-by-def.patch b/patches/server/0551-Set-spigots-verbose-world-setting-to-false-by-def.patch similarity index 100% rename from patches/server/0552-Set-spigots-verbose-world-setting-to-false-by-def.patch rename to patches/server/0551-Set-spigots-verbose-world-setting-to-false-by-def.patch diff --git a/patches/server/0553-Fix-curing-zombie-villager-discount-exploit.patch b/patches/server/0552-Fix-curing-zombie-villager-discount-exploit.patch similarity index 100% rename from patches/server/0553-Fix-curing-zombie-villager-discount-exploit.patch rename to patches/server/0552-Fix-curing-zombie-villager-discount-exploit.patch diff --git a/patches/server/0554-Limit-recipe-packets.patch b/patches/server/0553-Limit-recipe-packets.patch similarity index 100% rename from patches/server/0554-Limit-recipe-packets.patch rename to patches/server/0553-Limit-recipe-packets.patch diff --git a/patches/server/0555-Fix-CraftSound-backwards-compatibility.patch b/patches/server/0554-Fix-CraftSound-backwards-compatibility.patch similarity index 100% rename from patches/server/0555-Fix-CraftSound-backwards-compatibility.patch rename to patches/server/0554-Fix-CraftSound-backwards-compatibility.patch diff --git a/patches/server/0556-MC-4-Fix-item-position-desync.patch b/patches/server/0555-MC-4-Fix-item-position-desync.patch similarity index 100% rename from patches/server/0556-MC-4-Fix-item-position-desync.patch rename to patches/server/0555-MC-4-Fix-item-position-desync.patch diff --git a/patches/server/0557-Player-Chunk-Load-Unload-Events.patch b/patches/server/0556-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from patches/server/0557-Player-Chunk-Load-Unload-Events.patch rename to patches/server/0556-Player-Chunk-Load-Unload-Events.patch diff --git a/patches/server/0558-Optimize-Dynamic-get-Missing-Keys.patch b/patches/server/0557-Optimize-Dynamic-get-Missing-Keys.patch similarity index 100% rename from patches/server/0558-Optimize-Dynamic-get-Missing-Keys.patch rename to patches/server/0557-Optimize-Dynamic-get-Missing-Keys.patch diff --git a/patches/server/0559-Expose-LivingEntity-hurt-direction.patch b/patches/server/0558-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from patches/server/0559-Expose-LivingEntity-hurt-direction.patch rename to patches/server/0558-Expose-LivingEntity-hurt-direction.patch diff --git a/patches/server/0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server/0559-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from patches/server/0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/server/0559-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/patches/server/0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server/0560-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch similarity index 100% rename from patches/server/0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch rename to patches/server/0560-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch diff --git a/patches/server/0562-added-PlayerTradeEvent.patch b/patches/server/0561-added-PlayerTradeEvent.patch similarity index 100% rename from patches/server/0562-added-PlayerTradeEvent.patch rename to patches/server/0561-added-PlayerTradeEvent.patch diff --git a/patches/server/0563-Implement-TargetHitEvent.patch b/patches/server/0562-Implement-TargetHitEvent.patch similarity index 100% rename from patches/server/0563-Implement-TargetHitEvent.patch rename to patches/server/0562-Implement-TargetHitEvent.patch diff --git a/patches/server/0564-Additional-Block-Material-API-s.patch b/patches/server/0563-Additional-Block-Material-API-s.patch similarity index 100% rename from patches/server/0564-Additional-Block-Material-API-s.patch rename to patches/server/0563-Additional-Block-Material-API-s.patch diff --git a/patches/server/0565-Fix-harming-potion-dupe.patch b/patches/server/0564-Fix-harming-potion-dupe.patch similarity index 100% rename from patches/server/0565-Fix-harming-potion-dupe.patch rename to patches/server/0564-Fix-harming-potion-dupe.patch diff --git a/patches/server/0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/patches/server/0565-Implement-API-to-get-Material-from-Boats-and-Minecar.patch similarity index 100% rename from patches/server/0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch rename to patches/server/0565-Implement-API-to-get-Material-from-Boats-and-Minecar.patch diff --git a/patches/server/0567-Cache-burn-durations.patch b/patches/server/0566-Cache-burn-durations.patch similarity index 100% rename from patches/server/0567-Cache-burn-durations.patch rename to patches/server/0566-Cache-burn-durations.patch diff --git a/patches/server/0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server/0567-Allow-disabling-mob-spawner-spawn-egg-transformation.patch similarity index 100% rename from patches/server/0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch rename to patches/server/0567-Allow-disabling-mob-spawner-spawn-egg-transformation.patch diff --git a/patches/server/0569-Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server/0568-Implement-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from patches/server/0569-Implement-PlayerFlowerPotManipulateEvent.patch rename to patches/server/0568-Implement-PlayerFlowerPotManipulateEvent.patch diff --git a/patches/server/0570-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server/0569-Fix-interact-event-not-being-called-in-adventure.patch similarity index 100% rename from patches/server/0570-Fix-interact-event-not-being-called-in-adventure.patch rename to patches/server/0569-Fix-interact-event-not-being-called-in-adventure.patch diff --git a/patches/server/0571-Zombie-API-breaking-doors.patch b/patches/server/0570-Zombie-API-breaking-doors.patch similarity index 100% rename from patches/server/0571-Zombie-API-breaking-doors.patch rename to patches/server/0570-Zombie-API-breaking-doors.patch diff --git a/patches/server/0572-Fix-nerfed-slime-when-splitting.patch b/patches/server/0571-Fix-nerfed-slime-when-splitting.patch similarity index 100% rename from patches/server/0572-Fix-nerfed-slime-when-splitting.patch rename to patches/server/0571-Fix-nerfed-slime-when-splitting.patch diff --git a/patches/server/0573-Add-EntityLoadCrossbowEvent.patch b/patches/server/0572-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from patches/server/0573-Add-EntityLoadCrossbowEvent.patch rename to patches/server/0572-Add-EntityLoadCrossbowEvent.patch diff --git a/patches/server/0574-Guardian-beam-workaround.patch b/patches/server/0573-Guardian-beam-workaround.patch similarity index 90% rename from patches/server/0574-Guardian-beam-workaround.patch rename to patches/server/0573-Guardian-beam-workaround.patch index 5369300252..fa66573d2b 100644 --- a/patches/server/0574-Guardian-beam-workaround.patch +++ b/patches/server/0573-Guardian-beam-workaround.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Guardian beam workaround This patch is a workaround for MC-165595 diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java -index 9ec6145fe04ec64bbee8ec6a837719caebdbc6f5..c96b63355b38053b0f7ede313fb4bdf0e1089796 100644 +index 9ec6145fe04ec64bbee8ec6a837719caebdbc6f5..689ad22925b2561f7c8db961743eb1f821dbb25f 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java @@ -8,7 +8,7 @@ public class ClientboundSetTimePacket implements Packet +Date: Wed, 2 Dec 2020 20:04:01 -0800 +Subject: [PATCH] Added ServerResourcesReloadedEvent + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 9bd2255d31bcfd4574f8d1caf598f9141aa9e3c1..51bbb11ff8d3da95fa6d9890be3135a34b3eafac 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2017,7 +2017,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop reloadResources(Collection datapacks) { ++ return this.reloadResources(datapacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN); ++ } ++ public CompletableFuture reloadResources(Collection datapacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) { ++ // Paper end + CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { + Stream stream = datapacks.stream(); // CraftBukkit - decompile error + PackRepository resourcepackrepository = this.packRepository; +@@ -2033,6 +2039,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop dataPacks, CommandSourceStack source) { +- source.getServer().reloadResources(dataPacks).exceptionally((throwable) -> { ++ source.getServer().reloadResources(dataPacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally((throwable) -> { + ReloadCommand.LOGGER.warn("Failed to execute reload", throwable); + source.sendFailure(new TranslatableComponent("commands.reload.failure")); + return null; +@@ -50,7 +50,7 @@ public class ReloadCommand { + WorldData savedata = minecraftserver.getWorldData(); + Collection collection = resourcepackrepository.getSelectedIds(); + Collection collection1 = ReloadCommand.discoverNewPacks(resourcepackrepository, savedata, collection); +- minecraftserver.reloadResources(collection1); ++ minecraftserver.reloadResources(collection1, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN); // Paper + } + // CraftBukkit end + diff --git a/patches/server-remapped/0637-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server/0576-Added-world-settings-for-mobs-picking-up-loot.patch similarity index 82% rename from patches/server-remapped/0637-Added-world-settings-for-mobs-picking-up-loot.patch rename to patches/server/0576-Added-world-settings-for-mobs-picking-up-loot.patch index ead34bbc60..78f99e2245 100644 --- a/patches/server-remapped/0637-Added-world-settings-for-mobs-picking-up-loot.patch +++ b/patches/server/0576-Added-world-settings-for-mobs-picking-up-loot.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Added world settings for mobs picking up loot diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b48067c71f9de18ba40e970e2832f6245984a218..23a23e2ea133ce81d3dedc4ffd17435a995497ef 100644 +index bedadfc8835fa0c834494eb10cef13fa1cdc5cf5..b0b414a31192a2b0e5c69d00b982f883b66e77fd 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -363,6 +363,14 @@ public class PaperWorldConfig { +@@ -433,6 +433,14 @@ public class PaperWorldConfig { log("Creeper lingering effect: " + disableCreeperLingeringEffect); } @@ -24,10 +24,10 @@ index b48067c71f9de18ba40e970e2832f6245984a218..23a23e2ea133ce81d3dedc4ffd17435a private void expMergeMaxValue() { expMergeMaxValue = getInt("experience-merge-max-value", -1); diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -index 76027a7c9615495af64102744e264d7ba7c9b87e..68e52e3a31e70569d1a92602aff4b7b81c594757 100644 +index 3d8f3e22223e4effeaf52cb18c14c60276d4689c..6b4163f5601a0961055c8451ec7ef2204938cf69 100644 --- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -@@ -149,7 +149,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo +@@ -148,7 +148,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo this.populateDefaultEquipmentSlots(difficulty); this.populateDefaultEquipmentEnchantments(difficulty); this.reassessWeaponGoal(); @@ -37,15 +37,15 @@ index 76027a7c9615495af64102744e264d7ba7c9b87e..68e52e3a31e70569d1a92602aff4b7b8 LocalDate localdate = LocalDate.now(); int i = localdate.get(ChronoField.DAY_OF_MONTH); diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 77634a1e8e7539000f7db0b96f4548137af1a819..74fd175c4dc2d0d9832ee41efaf065b75a43f4b8 100644 +index 3125aad3b14a185bbd563827f07c15bbb1ef0895..03acacd30b84452733aa2bdeed515455a1f271f8 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -494,7 +494,7 @@ public class Zombie extends Monster { - Object object = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag); +@@ -497,7 +497,7 @@ public class Zombie extends Monster { + Object object = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityNbt); float f = difficulty.getSpecialMultiplier(); - this.setCanPickUpLoot(this.random.nextFloat() < 0.55F * f); + this.setCanPickUpLoot(this.level.paperConfig.zombiesAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * f); // Paper if (object == null) { - object = new Zombie.ZombieGroupData(getSpawnAsBabyOdds(world.getRandom()), true); + object = new Zombie.ZombieGroupData(Zombie.getSpawnAsBabyOdds(world.getRandom()), true); } diff --git a/patches/server-remapped/0638-Implemented-BlockFailedDispenseEvent.patch b/patches/server/0577-Implemented-BlockFailedDispenseEvent.patch similarity index 55% rename from patches/server-remapped/0638-Implemented-BlockFailedDispenseEvent.patch rename to patches/server/0577-Implemented-BlockFailedDispenseEvent.patch index a7a4e49910..3199535c18 100644 --- a/patches/server-remapped/0638-Implemented-BlockFailedDispenseEvent.patch +++ b/patches/server/0577-Implemented-BlockFailedDispenseEvent.patch @@ -5,58 +5,45 @@ Subject: [PATCH] Implemented BlockFailedDispenseEvent diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -index bfb2e21ccbcc67d6c9b4b329db1949d7d938bd2e..2a4cb76bdfcf55ba222b4976359c1b8efb165009 100644 +index 5812a6d601ab3552bd42dbf6e1071eff29dacc75..501a5483160dba050261bb3448317a097cdb7ef2 100644 --- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -@@ -81,6 +81,7 @@ public class DispenserBlock extends BaseEntityBlock { +@@ -82,8 +82,10 @@ public class DispenserBlock extends BaseEntityBlock { int i = tileentitydispenser.getRandomSlot(); if (i < 0) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, pos)) // Paper - BlockFailedDispenseEvent is called here - worldserver.levelEvent(1001, pos, 0); ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(world, pos)) {// Paper - BlockFailedDispenseEvent is called here + world.levelEvent(1001, pos, 0); + world.gameEvent(GameEvent.DISPENSE_FAIL, pos); ++ } // Paper } else { ItemStack itemstack = tileentitydispenser.getItem(i); + DispenseItemBehavior idispensebehavior = this.getDispenseMethod(itemstack); diff --git a/src/main/java/net/minecraft/world/level/block/DropperBlock.java b/src/main/java/net/minecraft/world/level/block/DropperBlock.java -index 154ec671e9d741e536464b794783da859e8447c1..492b19b94e2e2439f72ed9478d75641b0f50451a 100644 +index 51723c8f740c7b0bbd15acc0f1c848790c2ff299..5a95b550c767284563c124df1ff45322b37d4b4c 100644 --- a/src/main/java/net/minecraft/world/level/block/DropperBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DropperBlock.java @@ -45,6 +45,7 @@ public class DropperBlock extends DispenserBlock { int i = tileentitydispenser.getRandomSlot(); if (i < 0) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, pos)) // Paper - BlockFailedDispenseEvent is called here - worldserver.levelEvent(1001, pos, 0); ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(world, pos)) // Paper - BlockFailedDispenseEvent is called here + world.levelEvent(1001, pos, 0); } 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 34c7b1213b3f83ff1a1f2d606a9c25e57fea8ef3..8829ef03d0be16d8317aaf05bcd286b74f20656a 100644 +index 0f120d72816667ef8d50502b1e7e7dc3848f0ab4..263aaf312efcc8c8bda57448710ef6eb36a3a5bd 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -4,6 +4,7 @@ import com.google.common.base.Function; - import com.google.common.base.Functions; - import com.google.common.collect.Lists; - import com.mojang.datafixers.util.Either; -+import io.papermc.paper.event.block.BlockFailedDispenseEvent; - import java.net.InetAddress; - import java.util.ArrayList; - import java.util.Collections; -@@ -111,7 +112,6 @@ import org.bukkit.entity.ThrownPotion; - import org.bukkit.entity.Vehicle; - import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; --import org.bukkit.entity.ExperienceOrb; // Paper - import org.bukkit.event.Cancellable; - import org.bukkit.event.Event; - import org.bukkit.event.Event.Result; -@@ -1784,4 +1784,12 @@ public class CraftEventFactory { +@@ -1791,4 +1791,12 @@ public class CraftEventFactory { Bukkit.getPluginManager().callEvent(event); return event; } + + // Paper start -+ public static boolean handleBlockFailedDispenseEvent(ServerLevel worldserver, BlockPos blockposition) { -+ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); ++ public static boolean handleBlockFailedDispenseEvent(ServerLevel serverLevel, BlockPos blockposition) { ++ org.bukkit.block.Block block = serverLevel.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ io.papermc.paper.event.block.BlockFailedDispenseEvent event = new io.papermc.paper.event.block.BlockFailedDispenseEvent(block); + return event.callEvent(); + } + // Paper end diff --git a/patches/server/0578-Added-PlayerLecternPageChangeEvent.patch b/patches/server/0578-Added-PlayerLecternPageChangeEvent.patch new file mode 100644 index 0000000000..cd550d08ad --- /dev/null +++ b/patches/server/0578-Added-PlayerLecternPageChangeEvent.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 23 Nov 2020 12:58:51 -0800 +Subject: [PATCH] Added PlayerLecternPageChangeEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/LecternMenu.java b/src/main/java/net/minecraft/world/inventory/LecternMenu.java +index 0149b958a3bdeb529a8b7e64f4ca458d0be88998..ff79925bc6437222f9ceb133e21bbc0600cc74ed 100644 +--- a/src/main/java/net/minecraft/world/inventory/LecternMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/LecternMenu.java +@@ -64,6 +64,7 @@ public class LecternMenu extends AbstractContainerMenu { + @Override + public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + int j; ++ io.papermc.paper.event.player.PlayerLecternPageChangeEvent playerLecternPageChangeEvent; CraftInventoryLectern bukkitView; // Paper + + if (id >= 100) { + j = id - 100; +@@ -73,11 +74,25 @@ public class LecternMenu extends AbstractContainerMenu { + switch (id) { + case 1: + j = this.lecternData.get(0); +- this.setData(0, j - 1); ++ // Paper start ++ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); ++ playerLecternPageChangeEvent = new io.papermc.paper.event.player.PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), io.papermc.paper.event.player.PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, j, j - 1); ++ if (!playerLecternPageChangeEvent.callEvent()) { ++ return false; ++ } ++ this.setData(0, playerLecternPageChangeEvent.getNewPage()); ++ // Paper end + return true; + case 2: + j = this.lecternData.get(0); +- this.setData(0, j + 1); ++ // Paper start ++ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); ++ playerLecternPageChangeEvent = new io.papermc.paper.event.player.PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), io.papermc.paper.event.player.PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, j, j + 1); ++ if (!playerLecternPageChangeEvent.callEvent()) { ++ return false; ++ } ++ this.setData(0, playerLecternPageChangeEvent.getNewPage()); ++ // Paper end + return true; + case 3: + if (!player.mayBuild()) { diff --git a/patches/server/0579-Added-PlayerLoomPatternSelectEvent.patch b/patches/server/0579-Added-PlayerLoomPatternSelectEvent.patch new file mode 100644 index 0000000000..9847995136 --- /dev/null +++ b/patches/server/0579-Added-PlayerLoomPatternSelectEvent.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 25 Nov 2020 16:33:27 -0800 +Subject: [PATCH] Added PlayerLoomPatternSelectEvent + + +diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +index 7e8b6e0e69876cb7bfd444a8dd72edf8289e6dd1..51579f642859fc99c715dfcd286482995012d84a 100644 +--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +@@ -166,7 +166,22 @@ public class LoomMenu extends AbstractContainerMenu { + @Override + public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + if (id > 0 && id <= BannerPattern.AVAILABLE_PATTERNS) { +- this.selectedBannerPatternIndex.set(id); ++ // Paper start ++ int enumBannerPatternTypeOrdinal = id; ++ io.papermc.paper.event.player.PlayerLoomPatternSelectEvent event = new io.papermc.paper.event.player.PlayerLoomPatternSelectEvent((Player) player.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.block.banner.PatternType.getByIdentifier(BannerPattern.values()[id].getHashname())); ++ if (!event.callEvent()) { ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ return false; ++ } ++ for (BannerPattern nms : BannerPattern.values()) { ++ if (event.getPatternType().getIdentifier().equals(nms.getHashname())) { ++ enumBannerPatternTypeOrdinal = nms.ordinal(); ++ break; ++ } ++ } ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ this.selectedBannerPatternIndex.set(enumBannerPatternTypeOrdinal); ++ // Paper end + this.setupResultSlot(); + return true; + } else { diff --git a/patches/server-remapped/0642-Configurable-door-breaking-difficulty.patch b/patches/server/0580-Configurable-door-breaking-difficulty.patch similarity index 63% rename from patches/server-remapped/0642-Configurable-door-breaking-difficulty.patch rename to patches/server/0580-Configurable-door-breaking-difficulty.patch index c1c84edf4d..8b84a411c3 100644 --- a/patches/server-remapped/0642-Configurable-door-breaking-difficulty.patch +++ b/patches/server/0580-Configurable-door-breaking-difficulty.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable door breaking difficulty diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 23a23e2ea133ce81d3dedc4ffd17435a995497ef..7ebc85264a2cbfb601dfe5472b561cac1a7cf8bf 100644 +index b0b414a31192a2b0e5c69d00b982f883b66e77fd..dd5c092a035a30c477fe828b58bc918fc48daa03 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -5,7 +5,10 @@ import java.util.EnumMap; +@@ -4,7 +4,10 @@ import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -17,10 +17,36 @@ index 23a23e2ea133ce81d3dedc4ffd17435a995497ef..7ebc85264a2cbfb601dfe5472b561cac +import net.minecraft.world.Difficulty; +import net.minecraft.world.entity.monster.Vindicator; +import net.minecraft.world.entity.monster.Zombie; - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; import org.bukkit.Bukkit; import org.bukkit.Material; -@@ -73,6 +76,11 @@ public class PaperWorldConfig { + import org.bukkit.configuration.ConfigurationSection; +@@ -92,6 +95,25 @@ public class PaperWorldConfig { + disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); + } + ++ public List zombieBreakDoors; ++ public List vindicatorBreakDoors; ++ private void setupEntityBreakingDoors() { ++ zombieBreakDoors = getEnumList( ++ "door-breaking-difficulty.zombie", ++ java.util.Arrays.stream(Difficulty.values()) ++ .filter(Zombie.DOOR_BREAKING_PREDICATE) ++ .collect(Collectors.toList()), ++ Difficulty.class ++ ); ++ vindicatorBreakDoors = getEnumList( ++ "door-breaking-difficulty.vindicator", ++ java.util.Arrays.stream(Difficulty.values()) ++ .filter(Vindicator.DOOR_BREAKING_PREDICATE) ++ .collect(Collectors.toList()), ++ Difficulty.class ++ ); ++ } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); +@@ -143,6 +165,11 @@ public class PaperWorldConfig { return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); } @@ -32,45 +58,22 @@ index 23a23e2ea133ce81d3dedc4ffd17435a995497ef..7ebc85264a2cbfb601dfe5472b561cac public int cactusMaxHeight; public int reedMaxHeight; public int bambooMaxHeight; -@@ -735,4 +743,23 @@ public class PaperWorldConfig { - private void disableMobSpawnerSpawnEggTransformation() { - disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); - } -+ -+ public List zombieBreakDoors; -+ public List vindicatorBreakDoors; -+ private void setupEntityBreakingDoors() { -+ zombieBreakDoors = getEnumList( -+ "door-breaking-difficulty.zombie", -+ Arrays.stream(Difficulty.values()) -+ .filter(Zombie.getDoorBreakingPredicate()) -+ .collect(Collectors.toList()), -+ Difficulty.class -+ ); -+ vindicatorBreakDoors = getEnumList( -+ "door-breaking-difficulty.vindicator", -+ Arrays.stream(Difficulty.values()) -+ .filter(Vindicator.getDoorBreakingPredicate()) -+ .collect(Collectors.toList()), -+ Difficulty.class -+ ); -+ } - } diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -index 623de661f3b56062792e3a7dbc508637aa58aca5..48700094da6e97610ccc652593a9e229ba7b1003 100644 +index dcaec42b0756cf36da813815b4a54e4d6c4e293a..53a9e4b0fda9f5a3b23a874c53d93fbe931b0cfb 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -@@ -48,6 +48,7 @@ import net.minecraft.world.level.ServerLevelAccessor; +@@ -48,7 +48,7 @@ import net.minecraft.world.level.ServerLevelAccessor; public class Vindicator extends AbstractIllager { - -+ public static final Predicate getDoorBreakingPredicate() { return DOOR_BREAKING_PREDICATE; } // Paper - OBFHELPER - private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { - return enumdifficulty == Difficulty.NORMAL || enumdifficulty == Difficulty.HARD; + private static final String TAG_JOHNNY = "Johnny"; +- static final Predicate DOOR_BREAKING_PREDICATE = (difficulty) -> { ++ public static final Predicate DOOR_BREAKING_PREDICATE = (difficulty) -> { // Paper - package private -> public + return difficulty == Difficulty.NORMAL || difficulty == Difficulty.HARD; }; -@@ -204,7 +205,7 @@ public class Vindicator extends AbstractIllager { - static class VindicatorBreakDoorGoal extends BreakDoorGoal { + private boolean isJohnny; public boolean isJohnny() { return this.isJohnny; } public void setJohnny(boolean johnny) { this.isJohnny = johnny; } // Paper - OBFHELPER +@@ -195,7 +195,7 @@ public class Vindicator extends AbstractIllager { + static class VindicatorBreakDoorGoal extends BreakDoorGoal { public VindicatorBreakDoorGoal(Mob mob) { - super(mob, 6, Vindicator.DOOR_BREAKING_PREDICATE); + super(mob, 6, com.google.common.base.Predicates.in(mob.level.paperConfig.vindicatorBreakDoors)); // Paper @@ -78,18 +81,19 @@ index 623de661f3b56062792e3a7dbc508637aa58aca5..48700094da6e97610ccc652593a9e229 } diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 74fd175c4dc2d0d9832ee41efaf065b75a43f4b8..caa99a2737598bd74ede54f1c35ce4b99ce1e6d3 100644 +index 03acacd30b84452733aa2bdeed515455a1f271f8..9e535cf3293cf624b1e2e1b7fb40a446b888b099 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -83,6 +83,7 @@ public class Zombie extends Monster { - private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); - private static final EntityDataAccessor DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT); - public static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); -+ public static final Predicate getDoorBreakingPredicate() { return DOOR_BREAKING_PREDICATE; } // Paper - OBFHELPER - private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { +@@ -88,7 +88,7 @@ public class Zombie extends Monster { + public static final int REINFORCEMENT_RANGE_MAX = 40; + public static final int REINFORCEMENT_RANGE_MIN = 7; + private static final float BREAK_DOOR_CHANCE = 0.1F; +- private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { ++ public static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { // Paper - private -> public return enumdifficulty == Difficulty.HARD; }; -@@ -95,7 +96,7 @@ public class Zombie extends Monster { + private final BreakDoorGoal breakDoorGoal; +@@ -100,7 +100,7 @@ public class Zombie extends Monster { public Zombie(EntityType type, Level world) { super(type, world); diff --git a/patches/server-remapped/0643-Empty-commands-shall-not-be-dispatched.patch b/patches/server/0581-Empty-commands-shall-not-be-dispatched.patch similarity index 84% rename from patches/server-remapped/0643-Empty-commands-shall-not-be-dispatched.patch rename to patches/server/0581-Empty-commands-shall-not-be-dispatched.patch index a9abc78c3f..23f3b5516e 100644 --- a/patches/server-remapped/0643-Empty-commands-shall-not-be-dispatched.patch +++ b/patches/server/0581-Empty-commands-shall-not-be-dispatched.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Empty commands shall not be dispatched diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java -index c63033e3eb50423a7c32acfc0e705623cc4bec68..5ed78383ce247ceb24cda0335dbeae293958055c 100644 +index 7156dea53be828acd01734fa1f9f7b9accf30ff6..dc5d21693237ebb0b2a1ee45e92d0f191c547637 100644 --- a/src/main/java/net/minecraft/commands/Commands.java +++ b/src/main/java/net/minecraft/commands/Commands.java -@@ -223,6 +223,7 @@ public class Commands { +@@ -230,6 +230,7 @@ public class Commands { command = event.getCommand(); String[] args = command.split(" "); diff --git a/patches/server-remapped/0644-Implement-API-to-expose-exact-interaction-point.patch b/patches/server/0582-Implement-API-to-expose-exact-interaction-point.patch similarity index 82% rename from patches/server-remapped/0644-Implement-API-to-expose-exact-interaction-point.patch rename to patches/server/0582-Implement-API-to-expose-exact-interaction-point.patch index 4f115620e4..fcb5a17e21 100644 --- a/patches/server-remapped/0644-Implement-API-to-expose-exact-interaction-point.patch +++ b/patches/server/0582-Implement-API-to-expose-exact-interaction-point.patch @@ -5,23 +5,23 @@ Subject: [PATCH] Implement API to expose exact interaction point diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index 6269e37f2859417a80e6de16045f1c2325f9746f..37761176861027d0ee06f50d60584687fdac669b 100644 +index de4fdd46f23b2b17da752a8afc0faecc1ad8344f..2a0f313365a25c1780027f1536dbb88ccdab61e2 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -495,7 +495,7 @@ public class ServerPlayerGameMode { +@@ -498,7 +498,7 @@ public class ServerPlayerGameMode { cancelledBlock = true; } - PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand); + PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand, hitResult.getLocation()); // Paper - firedInteract = true; - interactResult = event.useItemInHand() == Event.Result.DENY; - interactPosition = blockposition.immutable(); + this.firedInteract = true; + 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 8829ef03d0be16d8317aaf05bcd286b74f20656a..586d21eed8189adf696ca6d3642afebbe752d1b5 100644 +index 263aaf312efcc8c8bda57448710ef6eb36a3a5bd..f6f2856c407abe195f1dfee7f4a7e30baea585f7 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -58,7 +58,9 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +@@ -55,7 +55,9 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; @@ -31,8 +31,8 @@ index 8829ef03d0be16d8317aaf05bcd286b74f20656a..586d21eed8189adf696ca6d3642afebb import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.Server; -@@ -475,7 +477,13 @@ public class CraftEventFactory { - return callPlayerInteractEvent(who, action, position, direction, itemstack, false, hand); +@@ -477,7 +479,13 @@ public class CraftEventFactory { + return CraftEventFactory.callPlayerInteractEvent(who, action, position, direction, itemstack, false, hand); } + // Paper start - Add interactionPoint @@ -45,7 +45,7 @@ index 8829ef03d0be16d8317aaf05bcd286b74f20656a..586d21eed8189adf696ca6d3642afebb Player player = (who == null) ? null : (Player) who.getBukkitEntity(); CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack); -@@ -501,7 +509,10 @@ public class CraftEventFactory { +@@ -503,7 +511,10 @@ public class CraftEventFactory { itemInHand = null; } diff --git a/patches/server/0583-Remove-stale-POIs.patch b/patches/server/0583-Remove-stale-POIs.patch new file mode 100644 index 0000000000..0683532986 --- /dev/null +++ b/patches/server/0583-Remove-stale-POIs.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 9 Jan 2021 14:17:07 +0100 +Subject: [PATCH] Remove stale POIs + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index f1c02ae301da2a3b582d2ec1215c1a981e26ac47..0e14946284738b751790b2763bfe197c0148a54a 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1768,6 +1768,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + }); + optional1.ifPresent((villageplacetype) -> { + this.getServer().execute(() -> { ++ // Paper start ++ if (!optional.isPresent() && this.getPoiManager().exists(blockposition1, com.google.common.base.Predicates.alwaysTrue())) { ++ this.getPoiManager().remove(blockposition1); ++ } ++ // Paper end + this.getPoiManager().add(blockposition1, villageplacetype); + DebugPackets.sendPoiAddedPacket(this, blockposition1); + }); From 23a9df76fde1d48cb8eaedba6462193853f2dc02 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Mon, 14 Jun 2021 22:15:09 +0200 Subject: [PATCH 123/226] add access transforming capabilities --- build-data/paper.at | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 build-data/paper.at diff --git a/build-data/paper.at b/build-data/paper.at new file mode 100644 index 0000000000..ced8ae8dfd --- /dev/null +++ b/build-data/paper.at @@ -0,0 +1,6 @@ +# You can use this file to change the access modifiers on a member +# This line would make the field rollAmount public in Bee +#public net.minecraft.world.entity.animal.Bee rollAmount +# This line would make the field public and remove the final modifier +#public-f net.minecraft.network.protocol.game.ClientboundChatPacket sender +# Leave out the member and it will apply to the class itself From b2a63428c891f8c0dc130ebe1cf51d5c77a019b8 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Mon, 14 Jun 2021 22:29:55 +0200 Subject: [PATCH 124/226] continue to load paperclip from jfrog for now --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index ec57e7a469..c8e36de76b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -39,7 +39,7 @@ subprojects { repositories { mavenCentral() - maven("https://papermc.io/repo/repository/maven-public/") { + maven("https://wav.jfrog.io/artifactory/repo/") { // TODO replace with "https://papermc.io/repo/repository/maven-public/" once paperclip is deplyoed there content { onlyForConfigurations("paperclip") } From 09ead8b04372e515c7f415ddbbf471b5fd0636d2 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Mon, 14 Jun 2021 12:58:32 -0700 Subject: [PATCH 125/226] more patches --- build-data/mappings-patch.tiny | 4 + .../0259-Add-sendOpLevel-API.patch | 4 +- .../0260-Add-StructureLocateEvent.patch | 0 ...onent-with-empty-text-instead-of-thr.patch | 0 .../0262-Add-BlockPreDispenseEvent.patch | 0 .../0263-Added-Vanilla-Entity-Tags.patch | 0 .../0264-added-Wither-API.patch | 0 ...-Added-PlayerChangeBeaconEffectEvent.patch | 0 ...-PlayerStonecutterRecipeSelectEvent.patch} | 0 ...eash-variable-to-EntityUnleashEvent.patch} | 0 .../0268-EntityMoveEvent.patch | 0 .../0269-add-DragonEggFormEvent.patch | 0 ...647-Entity-load-save-limit-per-chunk.patch | 2 + .../0646-Fix-villager-boat-exploit.patch | 34 ----- ...0653-Make-schedule-command-per-world.patch | 37 ------ ...0655-Implement-BlockPreDispenseEvent.patch | 42 ------- ...d-PlayerStonecutterRecipeSelectEvent.patch | 109 ---------------- .../0665-add-DragonEggFormEvent.patch | 117 ------------------ .../0584-Fix-villager-boat-exploit.patch | 26 ++++ .../0585-Add-sendOpLevel-API.patch} | 10 +- .../0586-Add-StructureLocateEvent.patch} | 4 +- ...-for-requiring-a-player-participant.patch} | 18 +-- ...leHitEvent-call-when-fireballs-dead.patch} | 6 +- ...nent-with-empty-text-instead-of-thr.patch} | 6 +- ...0590-Make-schedule-command-per-world.patch | 37 ++++++ ...591-Configurable-max-leash-distance.patch} | 4 +- ...0592-Implement-BlockPreDispenseEvent.patch | 34 +++++ .../0593-Added-Vanilla-Entity-Tags.patch} | 16 +-- .../0594-added-Wither-API.patch} | 20 +-- ...ng-of-PlayerChangeBeaconEffectEvent.patch} | 19 +-- ...-spam-when-removing-chests-in-water.patch} | 4 +- ...e-for-always-placing-the-dragon-egg.patch} | 13 +- ...d-PlayerStonecutterRecipeSelectEvent.patch | 51 ++++++++ ...eash-variable-to-EntityUnleashEvent.patch} | 48 +++---- ...e-map-update-when-spawning-disabled.patch} | 4 +- ...shield-blocking-on-dimension-change.patch} | 4 +- .../server/0602-add-DragonEggFormEvent.patch | 36 ++++++ .../0603-EntityMoveEvent.patch} | 44 +++---- 38 files changed, 277 insertions(+), 476 deletions(-) rename patches/{api-unmapped => api}/0259-Add-sendOpLevel-API.patch (87%) rename patches/{api-unmapped => api}/0260-Add-StructureLocateEvent.patch (100%) rename patches/{api-unmapped => api}/0261-Return-chat-component-with-empty-text-instead-of-thr.patch (100%) rename patches/{api-unmapped => api}/0262-Add-BlockPreDispenseEvent.patch (100%) rename patches/{api-unmapped => api}/0263-Added-Vanilla-Entity-Tags.patch (100%) rename patches/{api-unmapped => api}/0264-added-Wither-API.patch (100%) rename patches/{api-unmapped => api}/0265-Added-PlayerChangeBeaconEffectEvent.patch (100%) rename patches/{api-unmapped/0267-Added-PlayerStonecutterRecipeSelectEvent.patch => api/0266-Added-PlayerStonecutterRecipeSelectEvent.patch} (100%) rename patches/{api-unmapped/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch => api/0267-Add-dropLeash-variable-to-EntityUnleashEvent.patch} (100%) rename patches/{api-unmapped => api}/0268-EntityMoveEvent.patch (100%) rename patches/{api-unmapped => api}/0269-add-DragonEggFormEvent.patch (100%) rename patches/{server-remapped => removed/1.17}/0647-Entity-load-save-limit-per-chunk.patch (99%) delete mode 100644 patches/server-remapped/0646-Fix-villager-boat-exploit.patch delete mode 100644 patches/server-remapped/0653-Make-schedule-command-per-world.patch delete mode 100644 patches/server-remapped/0655-Implement-BlockPreDispenseEvent.patch delete mode 100644 patches/server-remapped/0661-Added-PlayerStonecutterRecipeSelectEvent.patch delete mode 100644 patches/server-remapped/0665-add-DragonEggFormEvent.patch create mode 100644 patches/server/0584-Fix-villager-boat-exploit.patch rename patches/{server-remapped/0648-Add-sendOpLevel-API.patch => server/0585-Add-sendOpLevel-API.patch} (87%) rename patches/{server-remapped/0649-Add-StructureLocateEvent.patch => server/0586-Add-StructureLocateEvent.patch} (93%) rename patches/{server-remapped/0650-Collision-option-for-requiring-a-player-participant.patch => server/0587-Collision-option-for-requiring-a-player-participant.patch} (85%) rename patches/{server-remapped/0651-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch => server/0588-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch} (84%) rename patches/{server-remapped/0652-Return-chat-component-with-empty-text-instead-of-thr.patch => server/0589-Return-chat-component-with-empty-text-instead-of-thr.patch} (86%) create mode 100644 patches/server/0590-Make-schedule-command-per-world.patch rename patches/{server-remapped/0654-Configurable-max-leash-distance.patch => server/0591-Configurable-max-leash-distance.patch} (94%) create mode 100644 patches/server/0592-Implement-BlockPreDispenseEvent.patch rename patches/{server-remapped/0656-Added-Vanilla-Entity-Tags.patch => server/0593-Added-Vanilla-Entity-Tags.patch} (86%) rename patches/{server-remapped/0657-added-Wither-API.patch => server/0594-added-Wither-API.patch} (71%) rename patches/{server-remapped/0658-Added-firing-of-PlayerChangeBeaconEffectEvent.patch => server/0595-Added-firing-of-PlayerChangeBeaconEffectEvent.patch} (56%) rename patches/{server-remapped/0659-Fix-console-spam-when-removing-chests-in-water.patch => server/0596-Fix-console-spam-when-removing-chests-in-water.patch} (86%) rename patches/{server-remapped/0660-Add-toggle-for-always-placing-the-dragon-egg.patch => server/0597-Add-toggle-for-always-placing-the-dragon-egg.patch} (79%) create mode 100644 patches/server/0598-Added-PlayerStonecutterRecipeSelectEvent.patch rename patches/{server-remapped/0662-Add-dropLeash-variable-to-EntityUnleashEvent.patch => server/0599-Add-dropLeash-variable-to-EntityUnleashEvent.patch} (81%) rename patches/{server-remapped/0663-Skip-distance-map-update-when-spawning-disabled.patch => server/0600-Skip-distance-map-update-when-spawning-disabled.patch} (87%) rename patches/{server-remapped/0664-Reset-shield-blocking-on-dimension-change.patch => server/0601-Reset-shield-blocking-on-dimension-change.patch} (80%) create mode 100644 patches/server/0602-add-DragonEggFormEvent.patch rename patches/{server-remapped/0666-EntityMoveEvent.patch => server/0603-EntityMoveEvent.patch} (53%) diff --git a/build-data/mappings-patch.tiny b/build-data/mappings-patch.tiny index b592b1991b..42978d9d06 100644 --- a/build-data/mappings-patch.tiny +++ b/build-data/mappings-patch.tiny @@ -83,3 +83,7 @@ c net/minecraft/world/level/block/MultifaceBlock net/minecraft/world/level/block c net/minecraft/server/players/UserCache net/minecraft/server/players/GameProfileCache m (Ljava/lang/String;)Lcom/mojang/authlib/GameProfile; getProfile get p 0 name + +# change dimension in ServerPlayer TODO (not sure what's wrong here) +#c net/minecraft/server/level/EntityPlayer net/minecraft/server/level/ServerPlayer +# m (Lnet/minecraft/server/level/ServerLevel;Lorg/bukkit/event/player/PlayerTeleportEvent$TeleportCause)Lnet/minecraft/world/entity/Entity; b changeDimension diff --git a/patches/api-unmapped/0259-Add-sendOpLevel-API.patch b/patches/api/0259-Add-sendOpLevel-API.patch similarity index 87% rename from patches/api-unmapped/0259-Add-sendOpLevel-API.patch rename to patches/api/0259-Add-sendOpLevel-API.patch index d1a8696b2d..3271c9ce3e 100644 --- a/patches/api-unmapped/0259-Add-sendOpLevel-API.patch +++ b/patches/api/0259-Add-sendOpLevel-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add sendOpLevel API diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 7aa9fb852dce23c53fee80e97e0dcdb278ae82ba..68a03821a5f06308a9c51fdf107d3924c44886c8 100644 +index d281d270bba71da5a7d1326112e73d9cdb1ed57b..9c7960f56733ff18b949cffe15f082c4cde28317 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1929,6 +1929,17 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1956,6 +1956,17 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM */ @Nullable Firework boostElytra(@NotNull ItemStack firework); diff --git a/patches/api-unmapped/0260-Add-StructureLocateEvent.patch b/patches/api/0260-Add-StructureLocateEvent.patch similarity index 100% rename from patches/api-unmapped/0260-Add-StructureLocateEvent.patch rename to patches/api/0260-Add-StructureLocateEvent.patch diff --git a/patches/api-unmapped/0261-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/api/0261-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from patches/api-unmapped/0261-Return-chat-component-with-empty-text-instead-of-thr.patch rename to patches/api/0261-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/patches/api-unmapped/0262-Add-BlockPreDispenseEvent.patch b/patches/api/0262-Add-BlockPreDispenseEvent.patch similarity index 100% rename from patches/api-unmapped/0262-Add-BlockPreDispenseEvent.patch rename to patches/api/0262-Add-BlockPreDispenseEvent.patch diff --git a/patches/api-unmapped/0263-Added-Vanilla-Entity-Tags.patch b/patches/api/0263-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from patches/api-unmapped/0263-Added-Vanilla-Entity-Tags.patch rename to patches/api/0263-Added-Vanilla-Entity-Tags.patch diff --git a/patches/api-unmapped/0264-added-Wither-API.patch b/patches/api/0264-added-Wither-API.patch similarity index 100% rename from patches/api-unmapped/0264-added-Wither-API.patch rename to patches/api/0264-added-Wither-API.patch diff --git a/patches/api-unmapped/0265-Added-PlayerChangeBeaconEffectEvent.patch b/patches/api/0265-Added-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from patches/api-unmapped/0265-Added-PlayerChangeBeaconEffectEvent.patch rename to patches/api/0265-Added-PlayerChangeBeaconEffectEvent.patch diff --git a/patches/api-unmapped/0267-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/api/0266-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from patches/api-unmapped/0267-Added-PlayerStonecutterRecipeSelectEvent.patch rename to patches/api/0266-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/patches/api-unmapped/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/api/0267-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from patches/api-unmapped/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/api/0267-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/patches/api-unmapped/0268-EntityMoveEvent.patch b/patches/api/0268-EntityMoveEvent.patch similarity index 100% rename from patches/api-unmapped/0268-EntityMoveEvent.patch rename to patches/api/0268-EntityMoveEvent.patch diff --git a/patches/api-unmapped/0269-add-DragonEggFormEvent.patch b/patches/api/0269-add-DragonEggFormEvent.patch similarity index 100% rename from patches/api-unmapped/0269-add-DragonEggFormEvent.patch rename to patches/api/0269-add-DragonEggFormEvent.patch diff --git a/patches/server-remapped/0647-Entity-load-save-limit-per-chunk.patch b/patches/removed/1.17/0647-Entity-load-save-limit-per-chunk.patch similarity index 99% rename from patches/server-remapped/0647-Entity-load-save-limit-per-chunk.patch rename to patches/removed/1.17/0647-Entity-load-save-limit-per-chunk.patch index a9cb53ca69..6ee87e0f50 100644 --- a/patches/server-remapped/0647-Entity-load-save-limit-per-chunk.patch +++ b/patches/removed/1.17/0647-Entity-load-save-limit-per-chunk.patch @@ -8,6 +8,8 @@ to a chunk. The default values of -1 disable the limit. Although defaults are only included for certain entites, this allows setting limits for any entity type. +1.17: entities not in chunks anymore + diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java index 7ebc85264a2cbfb601dfe5472b561cac1a7cf8bf..486e5438254348db68017228af131cba7defd637 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java diff --git a/patches/server-remapped/0646-Fix-villager-boat-exploit.patch b/patches/server-remapped/0646-Fix-villager-boat-exploit.patch deleted file mode 100644 index bc4c9d15d6..0000000000 --- a/patches/server-remapped/0646-Fix-villager-boat-exploit.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Mon, 11 Jan 2021 12:43:51 -0800 -Subject: [PATCH] Fix villager boat exploit - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7e07fd0c8dec9f9cdeda65dfa0ccf42b4dde010e..9d1116f601b79dabf7a0d9e5ecf5c2a0306f9aa4 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -78,6 +78,7 @@ import net.minecraft.util.Mth; - import net.minecraft.world.effect.MobEffectInstance; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.entity.npc.AbstractVillager; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.GameType; -@@ -617,6 +618,15 @@ public abstract class PlayerList { - - for (Iterator iterator = entity.getIndirectPassengers().iterator(); iterator.hasNext(); entity1.removed = true) { - entity1 = (Entity) iterator.next(); -+ // Paper start -+ if (entity1 instanceof AbstractVillager) { -+ final AbstractVillager villager = (AbstractVillager) entity1; -+ final net.minecraft.world.entity.player.Player human = villager.getTradingPlayer(); -+ if (human != null) { -+ villager.setTradingPlayer(null); -+ } -+ } -+ // Paper end - worldserver.despawn(entity1); - } - diff --git a/patches/server-remapped/0653-Make-schedule-command-per-world.patch b/patches/server-remapped/0653-Make-schedule-command-per-world.patch deleted file mode 100644 index 24fcb77734..0000000000 --- a/patches/server-remapped/0653-Make-schedule-command-per-world.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 19:52:44 -0800 -Subject: [PATCH] Make schedule command per-world - - -diff --git a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java -index 122a790285734ecd95fe6817043a84cf1752dbe8..173ab97b01b2191d9d731a28f2690eb4f539880b 100644 ---- a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java -+++ b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java -@@ -32,7 +32,7 @@ public class ScheduleCommand { - return new TranslatableComponent("commands.schedule.cleared.failure", new Object[]{object}); - }); - private static final SuggestionProvider SUGGEST_SCHEDULE = (commandcontext, suggestionsbuilder) -> { -- return SharedSuggestionProvider.suggest((Iterable) ((CommandSourceStack) commandcontext.getSource()).getServer().getWorldData().overworldData().getScheduledEvents().getEventsIds(), suggestionsbuilder); -+ return SharedSuggestionProvider.suggest((Iterable) ((CommandSourceStack) commandcontext.getSource()).getLevel().worldDataServer.overworldData().getScheduledEvents().getEventsIds(), suggestionsbuilder); // Paper - }; - - public static void register(CommandDispatcher dispatcher) { -@@ -55,7 +55,7 @@ public class ScheduleCommand { - } else { - long j = source.getLevel().getGameTime() + (long) i; - ResourceLocation minecraftkey = (ResourceLocation) pair.getFirst(); -- TimerQueue customfunctioncallbacktimerqueue = source.getServer().getWorldData().overworldData().getScheduledEvents(); -+ TimerQueue customfunctioncallbacktimerqueue = source.getLevel().worldDataServer.overworldData().getScheduledEvents(); // Paper - - ((Either) pair.getSecond()).ifLeft((customfunction) -> { - String s = minecraftkey.toString(); -@@ -81,7 +81,7 @@ public class ScheduleCommand { - } - - private static int remove(CommandSourceStack commandlistenerwrapper, String s) throws CommandSyntaxException { -- int i = commandlistenerwrapper.getServer().getWorldData().overworldData().getScheduledEvents().remove(s); -+ int i = commandlistenerwrapper.getLevel().worldDataServer.overworldData().getScheduledEvents().remove(s); // Paper - - if (i == 0) { - throw ScheduleCommand.ERROR_CANT_REMOVE.create(s); diff --git a/patches/server-remapped/0655-Implement-BlockPreDispenseEvent.patch b/patches/server-remapped/0655-Implement-BlockPreDispenseEvent.patch deleted file mode 100644 index fea75084e5..0000000000 --- a/patches/server-remapped/0655-Implement-BlockPreDispenseEvent.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Sun, 17 Jan 2021 13:16:09 +1000 -Subject: [PATCH] Implement BlockPreDispenseEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -index 2a4cb76bdfcf55ba222b4976359c1b8efb165009..08ce586f8d024b57a20031868ca2a3058bc500ee 100644 ---- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -@@ -88,6 +88,7 @@ public class DispenserBlock extends BaseEntityBlock { - DispenseItemBehavior idispensebehavior = this.getDispenseMethod(itemstack); - - if (idispensebehavior != DispenseItemBehavior.NOOP) { -+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(worldserver, pos, itemstack, i)) return; // Paper - BlockPreDispenseEvent is called here - eventFired = false; // CraftBukkit - reset event status - tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 586d21eed8189adf696ca6d3642afebbe752d1b5..34c0216baa69206aca51821aec421484b18cb04c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -59,6 +59,7 @@ import net.minecraft.world.phys.BlockHitResult; - import net.minecraft.world.phys.EntityHitResult; - import net.minecraft.world.phys.HitResult; - import net.minecraft.world.phys.Vec3; -+import io.papermc.paper.event.block.BlockPreDispenseEvent; // Paper - import org.bukkit.Bukkit; - import org.bukkit.Location; // Paper - import org.bukkit.Material; -@@ -1802,5 +1803,11 @@ public class CraftEventFactory { - BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); - return event.callEvent(); - } -+ -+ public static boolean handleBlockPreDispenseEvent(ServerLevel worldserver, BlockPos blockposition, ItemStack itemStack, int slot) { -+ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ BlockPreDispenseEvent event = new BlockPreDispenseEvent(block, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), slot); -+ return event.callEvent(); -+ } - // Paper end - } diff --git a/patches/server-remapped/0661-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server-remapped/0661-Added-PlayerStonecutterRecipeSelectEvent.patch deleted file mode 100644 index aab6a1ebc8..0000000000 --- a/patches/server-remapped/0661-Added-PlayerStonecutterRecipeSelectEvent.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 27 Nov 2020 17:14:27 -0800 -Subject: [PATCH] Added PlayerStonecutterRecipeSelectEvent - -Co-Authored-By: MiniDigger - -diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -index d2f762371f82d54bcec8b1a0a02d0866e55fd174..b5eeb2749237d589eafdfbea073bfe90e609600b 100644 ---- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -117,7 +117,7 @@ public abstract class AbstractContainerMenu { - return slot; - } - -- protected DataSlot addDataSlot(DataSlot containerproperty) { -+ protected DataSlot addDataSlot(DataSlot containerproperty) { return addDataSlot(containerproperty); } protected DataSlot addDataSlot(DataSlot containerproperty) { // Paper - OBFHELPER - this.dataSlots.add(containerproperty); - return containerproperty; - } -diff --git a/src/main/java/net/minecraft/world/inventory/DataSlot.java b/src/main/java/net/minecraft/world/inventory/DataSlot.java -index 56d99e39f8cfe46a780bd17a0f99c3cbbe01c719..e851d6c8e5ad58091a58d489a48cd3ec379ce0da 100644 ---- a/src/main/java/net/minecraft/world/inventory/DataSlot.java -+++ b/src/main/java/net/minecraft/world/inventory/DataSlot.java -@@ -20,7 +20,7 @@ public abstract class DataSlot { - }; - } - -- public static DataSlot shared(final int[] array, final int index) { -+ public static DataSlot shared(final int[] aint, final int i) { return shared(aint, i); } public static DataSlot shared(final int[] array, final int index) { // Paper - OBFHELPER - return new DataSlot() { - @Override - public int get() { -@@ -54,7 +54,7 @@ public abstract class DataSlot { - - public abstract void set(int value); - -- public boolean checkAndClearUpdateFlag() { -+ public boolean checkAndClearUpdateFlag() { return checkAndClearUpdateFlag(); } public boolean checkAndClearUpdateFlag() { // Paper - OBFHELPER - int i = this.get(); - boolean flag = i != this.prevValue; - -diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java -index 072bac443e7c54ac2b92e1d93b757bdacf230fbb..beb02f953719170d1668ada1c09d073d84bb7baf 100644 ---- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java -+++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java -@@ -21,13 +21,14 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent; // Paper - - public class StonecutterMenu extends AbstractContainerMenu { - - private final ContainerLevelAccess access; - private final DataSlot selectedRecipeIndex; - private final Level level; -- private List recipes; -+ private List recipes; public final List getRecipes() { return this.recipes; } // Paper - OBFHELPER - private ItemStack input; - private long lastSoundTime; - final Slot inputSlot; -@@ -57,7 +58,7 @@ public class StonecutterMenu extends AbstractContainerMenu { - - public StonecutterMenu(int syncId, Inventory playerInventory, final ContainerLevelAccess context) { - super(MenuType.STONECUTTER, syncId); -- this.selectedRecipeIndex = DataSlot.standalone(); -+ this.selectedRecipeIndex = addDataSlot(DataSlot.shared(new int[1], 0)); // Paper - allow replication - this.recipes = Lists.newArrayList(); - this.input = ItemStack.EMPTY; - this.slotUpdateListener = () -> { -@@ -135,13 +136,36 @@ public class StonecutterMenu extends AbstractContainerMenu { - @Override - public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { - if (this.isValidRecipeIndex(id)) { -- this.selectedRecipeIndex.set(id); -+ // Paper start -+ int recipeIndex = id; -+ this.selectedRecipeIndex.set(recipeIndex); -+ this.selectedRecipeIndex.checkAndClearUpdateFlag(); // mark as changed -+ if (this.isValidRecipeIndex(id)) { -+ PlayerStonecutterRecipeSelectEvent event = new PlayerStonecutterRecipeSelectEvent((Player) player.getBukkitEntity(), (org.bukkit.inventory.StonecutterInventory) getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) this.getRecipes().get(id).toBukkitRecipe()); -+ if (!event.callEvent()) { -+ ((Player) player.getBukkitEntity()).updateInventory(); -+ return false; -+ } -+ int newRecipeIndex; -+ if (!this.getRecipes().get(recipeIndex).getId().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { // If the recipe did NOT stay the same -+ for (newRecipeIndex = 0; newRecipeIndex < this.getRecipes().size(); newRecipeIndex++) { -+ if (this.getRecipes().get(newRecipeIndex).getId().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { -+ recipeIndex = newRecipeIndex; -+ break; -+ } -+ } -+ } -+ } -+ ((Player) player.getBukkitEntity()).updateInventory(); -+ this.selectedRecipeIndex.set(recipeIndex); // set new index, so that listeners can read it -+ // Paper end - this.setupResultSlot(); - } - - return true; - } - -+ private boolean isValidRecipeIndex(int index) { return this.isValidRecipeIndex(index); } // Paper - OBFHELPER - private boolean isValidRecipeIndex(int i) { - return i >= 0 && i < this.recipes.size(); - } diff --git a/patches/server-remapped/0665-add-DragonEggFormEvent.patch b/patches/server-remapped/0665-add-DragonEggFormEvent.patch deleted file mode 100644 index 17cbf7f9ae..0000000000 --- a/patches/server-remapped/0665-add-DragonEggFormEvent.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Mon, 25 Jan 2021 14:53:57 +0100 -Subject: [PATCH] add DragonEggFormEvent - - -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index e2f784b771b12bd646d519938c33b1c86cc2686d..f32e2c71929a73258e4eb521c160c247690744d2 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -57,6 +57,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfigur - import net.minecraft.world.phys.AABB; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.event.block.DragonEggFormEvent; // Paper - DragonEggFormEvent - - public class EndDragonFight { - -@@ -396,9 +397,24 @@ public class EndDragonFight { - this.dragonEvent.setVisible(false); - this.spawnExitPortal(true); - this.spawnNewGateway(); -+ // Paper start - DragonEggFormEvent -+ BlockPos eggPosition = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getPosition()); -+ org.bukkit.craftbukkit.block.CraftBlock eggBlock = org.bukkit.craftbukkit.block.CraftBlock.at(this.level, eggPosition); -+ org.bukkit.craftbukkit.block.CraftBlockState eggState = new org.bukkit.craftbukkit.block.CraftBlockState(eggBlock); -+ eggState.setData(Blocks.DRAGON_EGG.defaultBlockState()); -+ DragonEggFormEvent eggEvent = new DragonEggFormEvent(eggBlock, eggState, -+ new org.bukkit.craftbukkit.boss.CraftDragonBattle(this)); -+ // Paper end - DragonEggFormEvent - if (this.level.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg -- this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.END_PODIUM_LOCATION), Blocks.DRAGON_EGG.defaultBlockState()); -+ // Paper start - DragonEggFormEvent -+ //this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); -+ } else { -+ eggEvent.setCancelled(true); -+ } -+ if (eggEvent.callEvent()) { -+ eggEvent.getNewState().update(true); - } -+ // Paper end - DragonEggFormEvent - - this.previouslyKilled = true; - this.dragonKilled = true; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java -index cd24e9db1e9a490117716d4883376bb6b59c7c67..e085607f4033476e80b7dcd7b026449c12a47cf6 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java -@@ -14,7 +14,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConf - - public class EndPodiumFeature extends Feature { - -- public static final BlockPos END_PODIUM_LOCATION = BlockPos.ZERO; -+ public static final BlockPos END_PODIUM_LOCATION = BlockPos.ZERO; public static BlockPos getPosition() { return END_PODIUM_LOCATION; } // Paper - OBFHELPER - private final boolean active; - - public EndPodiumFeature(boolean open) { -@@ -22,43 +22,43 @@ public class EndPodiumFeature extends Feature { - this.active = open; - } - -- public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, NoneFeatureConfiguration config) { -- Iterator iterator = BlockPos.betweenClosed(new BlockPos(pos.getX() - 4, pos.getY() - 1, pos.getZ() - 4), new BlockPos(pos.getX() + 4, pos.getY() + 32, pos.getZ() + 4)).iterator(); -+ public boolean generate(WorldGenLevel generatoraccessseed, ChunkGenerator chunkgenerator, Random random, BlockPos blockposition, NoneFeatureConfiguration worldgenfeatureemptyconfiguration) { // Paper - decompile fix -+ Iterator iterator = BlockPos.betweenClosed(new BlockPos(blockposition.getX() - 4, blockposition.getY() - 1, blockposition.getZ() - 4), new BlockPos(blockposition.getX() + 4, blockposition.getY() + 32, blockposition.getZ() + 4)).iterator(); - - while (iterator.hasNext()) { - BlockPos blockposition1 = (BlockPos) iterator.next(); -- boolean flag = blockposition1.closerThan((Vec3i) pos, 2.5D); -+ boolean flag = blockposition1.closerThan((Vec3i) blockposition, 2.5D); - -- if (flag || blockposition1.closerThan((Vec3i) pos, 3.5D)) { -- if (blockposition1.getY() < pos.getY()) { -+ if (flag || blockposition1.closerThan((Vec3i) blockposition, 3.5D)) { -+ if (blockposition1.getY() < blockposition.getY()) { - if (flag) { -- this.setBlock(world, blockposition1, Blocks.BEDROCK.defaultBlockState()); -- } else if (blockposition1.getY() < pos.getY()) { -- this.setBlock(world, blockposition1, Blocks.END_STONE.defaultBlockState()); -+ this.setBlock(generatoraccessseed, blockposition1, Blocks.BEDROCK.defaultBlockState()); -+ } else if (blockposition1.getY() < blockposition.getY()) { -+ this.setBlock(generatoraccessseed, blockposition1, Blocks.END_STONE.defaultBlockState()); - } -- } else if (blockposition1.getY() > pos.getY()) { -- this.setBlock(world, blockposition1, Blocks.AIR.defaultBlockState()); -+ } else if (blockposition1.getY() > blockposition.getY()) { -+ this.setBlock(generatoraccessseed, blockposition1, Blocks.AIR.defaultBlockState()); - } else if (!flag) { -- this.setBlock(world, blockposition1, Blocks.BEDROCK.defaultBlockState()); -+ this.setBlock(generatoraccessseed, blockposition1, Blocks.BEDROCK.defaultBlockState()); - } else if (this.active) { -- this.setBlock(world, new BlockPos(blockposition1), Blocks.END_PORTAL.defaultBlockState()); -+ this.setBlock(generatoraccessseed, new BlockPos(blockposition1), Blocks.END_PORTAL.defaultBlockState()); - } else { -- this.setBlock(world, new BlockPos(blockposition1), Blocks.AIR.defaultBlockState()); -+ this.setBlock(generatoraccessseed, new BlockPos(blockposition1), Blocks.AIR.defaultBlockState()); - } - } - } - - for (int i = 0; i < 4; ++i) { -- this.setBlock(world, pos.above(i), Blocks.BEDROCK.defaultBlockState()); -+ this.setBlock(generatoraccessseed, blockposition.above(i), Blocks.BEDROCK.defaultBlockState()); - } - -- BlockPos blockposition2 = pos.above(2); -+ BlockPos blockposition2 = blockposition.above(2); - Iterator iterator1 = Direction.Plane.HORIZONTAL.iterator(); - - while (iterator1.hasNext()) { - Direction enumdirection = (Direction) iterator1.next(); - -- this.setBlock(world, blockposition2.relative(enumdirection), (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, enumdirection)); -+ this.setBlock(generatoraccessseed, blockposition2.relative(enumdirection), (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, enumdirection)); - } - - return true; diff --git a/patches/server/0584-Fix-villager-boat-exploit.patch b/patches/server/0584-Fix-villager-boat-exploit.patch new file mode 100644 index 0000000000..edc990c633 --- /dev/null +++ b/patches/server/0584-Fix-villager-boat-exploit.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Mon, 11 Jan 2021 12:43:51 -0800 +Subject: [PATCH] Fix villager boat exploit + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index ce6d9b460f0f55fc6d5544d5c8d2b78e5fcc3937..9a37a962b141e9faecc9f6f4906a9d727d20c20a 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -613,6 +613,15 @@ public abstract class PlayerList { + PlayerList.LOGGER.debug("Removing player mount"); + entityplayer.stopRiding(); + entity.getPassengersAndSelf().forEach((entity1) -> { ++ // Paper start ++ if (entity1 instanceof net.minecraft.world.entity.npc.AbstractVillager) { ++ final net.minecraft.world.entity.npc.AbstractVillager villager = (net.minecraft.world.entity.npc.AbstractVillager) entity1; ++ final net.minecraft.world.entity.player.Player human = villager.getTradingPlayer(); ++ if (human != null) { ++ villager.setTradingPlayer(null); ++ } ++ } ++ // Paper end + entity1.setRemoved(Entity.RemovalReason.UNLOADED_WITH_PLAYER); + }); + } diff --git a/patches/server-remapped/0648-Add-sendOpLevel-API.patch b/patches/server/0585-Add-sendOpLevel-API.patch similarity index 87% rename from patches/server-remapped/0648-Add-sendOpLevel-API.patch rename to patches/server/0585-Add-sendOpLevel-API.patch index 82ff3e57c1..804eeb2787 100644 --- a/patches/server-remapped/0648-Add-sendOpLevel-API.patch +++ b/patches/server/0585-Add-sendOpLevel-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add sendOpLevel API diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 9d1116f601b79dabf7a0d9e5ecf5c2a0306f9aa4..c962b6fc0c65dc5e2ea636220727bca63bf4b740 100644 +index 9a37a962b141e9faecc9f6f4906a9d727d20c20a..d01712cad42c078a726d6f757a4d8f0e3f186274 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1134,22 +1134,29 @@ public abstract class PlayerList { +@@ -1113,22 +1113,29 @@ public abstract class PlayerList { } private void sendPlayerPermissionLevel(ServerPlayer player, int permissionLevel) { @@ -46,10 +46,10 @@ index 9d1116f601b79dabf7a0d9e5ecf5c2a0306f9aa4..c962b6fc0c65dc5e2ea636220727bca6 // Paper start diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 40380fff222cc1f3340cf6a6c4afbe60aaa5d3a6..d2d179cdef8129653983b01d94928ba83f64f644 100644 +index 9236027beb13ae4f2e35c46f6c176fd5d7d20b4f..a9fdf153a9442830c7ce9e8fb6147b2c7b33db55 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2296,6 +2296,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -548,6 +548,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { ? (org.bukkit.entity.Firework) entity.getBukkitEntity() : null; } @@ -62,4 +62,4 @@ index 40380fff222cc1f3340cf6a6c4afbe60aaa5d3a6..d2d179cdef8129653983b01d94928ba8 + } // Paper end - // Spigot start + @Override diff --git a/patches/server-remapped/0649-Add-StructureLocateEvent.patch b/patches/server/0586-Add-StructureLocateEvent.patch similarity index 93% rename from patches/server-remapped/0649-Add-StructureLocateEvent.patch rename to patches/server/0586-Add-StructureLocateEvent.patch index 6aaa2cdea9..928a6fc6bc 100644 --- a/patches/server-remapped/0649-Add-StructureLocateEvent.patch +++ b/patches/server/0586-Add-StructureLocateEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add StructureLocateEvent diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -index 860af116dbc7dd9d691ff27d28a2d10dbec83df4..29310d96eb562ead1e568a97b6f3019e43ca0a88 100644 +index 6a93d3b3798b15fd75ca797665b442dcc634b89a..c2b0b1adcff5baf169901710d492317d44b93846 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java @@ -2,6 +2,7 @@ package net.minecraft.world.level.chunk; @@ -16,7 +16,7 @@ index 860af116dbc7dd9d691ff27d28a2d10dbec83df4..29310d96eb562ead1e568a97b6f3019e import java.util.BitSet; import java.util.Iterator; import java.util.List; -@@ -160,6 +161,22 @@ public abstract class ChunkGenerator { +@@ -185,6 +186,22 @@ public abstract class ChunkGenerator { @Nullable public BlockPos findNearestMapFeature(ServerLevel world, StructureFeature feature, BlockPos center, int radius, boolean skipExistingChunks) { diff --git a/patches/server-remapped/0650-Collision-option-for-requiring-a-player-participant.patch b/patches/server/0587-Collision-option-for-requiring-a-player-participant.patch similarity index 85% rename from patches/server-remapped/0650-Collision-option-for-requiring-a-player-participant.patch rename to patches/server/0587-Collision-option-for-requiring-a-player-participant.patch index 33e77f9b2e..f3649e1149 100644 --- a/patches/server-remapped/0650-Collision-option-for-requiring-a-player-participant.patch +++ b/patches/server/0587-Collision-option-for-requiring-a-player-participant.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Collision option for requiring a player participant diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 486e5438254348db68017228af131cba7defd637..3dd228ae8071a747f2cd7b2b46a2215183f72cd0 100644 +index dd5c092a035a30c477fe828b58bc918fc48daa03..16b80fe4c55c51d3afaefba7eef97d1e3e4a3248 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -717,6 +717,18 @@ public class PaperWorldConfig { +@@ -67,6 +67,18 @@ public class PaperWorldConfig { } } @@ -28,10 +28,10 @@ index 486e5438254348db68017228af131cba7defd637..3dd228ae8071a747f2cd7b2b46a22151 public int wanderingTraderSpawnDayTicks = 24000; public int wanderingTraderSpawnChanceFailureIncrement = 25; diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index ec98f5f59ca2b4cb58eb00ed8cdfa364f8bacd88..87c719caf796f54296ff7e412548062e02af270e 100644 +index fec2a44c4a110407d33002a955fe5dacbccc840c..9023cee63d77886683840f8d5650a8e07426b4c6 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1465,6 +1465,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1587,6 +1587,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public void push(Entity entity) { if (!this.isPassengerOfSameVehicle(entity)) { if (!entity.noPhysics && !this.noPhysics) { @@ -40,7 +40,7 @@ index ec98f5f59ca2b4cb58eb00ed8cdfa364f8bacd88..87c719caf796f54296ff7e412548062e double d1 = entity.getZ() - this.getZ(); double d2 = Mth.absMax(d0, d1); diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -index 9cbde70787d8044f0edeb3d459231dd7fbb79584..25df3ef6b96bec39847a732394af8eccdb4d5d45 100644 +index 9653b142c199c068e4d6175bcd3cbecb6465853f..309bafd257d4932cfd69c2c212b32306938cd234 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java @@ -21,6 +21,7 @@ import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; @@ -51,7 +51,7 @@ index 9cbde70787d8044f0edeb3d459231dd7fbb79584..25df3ef6b96bec39847a732394af8ecc import net.minecraft.tags.BlockTags; import net.minecraft.tags.Tag; import net.minecraft.util.Mth; -@@ -766,6 +767,7 @@ public abstract class AbstractMinecart extends Entity { +@@ -833,6 +834,7 @@ public abstract class AbstractMinecart extends Entity { public void push(Entity entity) { if (!this.level.isClientSide) { if (!entity.noPhysics && !this.noPhysics) { @@ -60,10 +60,10 @@ index 9cbde70787d8044f0edeb3d459231dd7fbb79584..25df3ef6b96bec39847a732394af8ecc // CraftBukkit start VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -index 6a9c18540886979b2212bf7917a21753c9a9db3c..e7ac3bff190c899397d6576fabbf4966878ea7e5 100644 +index a1b93f2878e22fa1d0cad639416d2dc5b8339c73..aa7c022c4faade23bd9061311d4152cf845d3331 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -@@ -14,6 +14,7 @@ import net.minecraft.network.protocol.game.ServerboundPaddleBoatPacket; +@@ -16,6 +16,7 @@ import net.minecraft.network.protocol.game.ServerboundPaddleBoatPacket; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; @@ -71,7 +71,7 @@ index 6a9c18540886979b2212bf7917a21753c9a9db3c..e7ac3bff190c899397d6576fabbf4966 import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.FluidTags; -@@ -229,6 +230,7 @@ public class Boat extends Entity { +@@ -240,6 +241,7 @@ public class Boat extends Entity { @Override public void push(Entity entity) { diff --git a/patches/server-remapped/0651-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/patches/server/0588-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch similarity index 84% rename from patches/server-remapped/0651-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch rename to patches/server/0588-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch index ed43990f0e..8ce2f9276b 100644 --- a/patches/server-remapped/0651-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch +++ b/patches/server/0588-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch @@ -7,13 +7,13 @@ The duplicate ProjectileHitEvent in EntityFireball was removed. The event was always called before the duplicate call. diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -index 872ff430547276e2a41a48aa07ae63b87ab39e5d..cba1b361162456cf297d88439f76586a2f61fc45 100644 +index dd5209ab2e5b59312349e709392689f25da162c0..3a088afd8269606543ebc9fb2074eb70431fcd39 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -@@ -86,7 +86,7 @@ public abstract class AbstractHurtingProjectile extends Projectile { +@@ -97,7 +97,7 @@ public abstract class AbstractHurtingProjectile extends Projectile { // CraftBukkit start - Fire ProjectileHitEvent - if (this.removed) { + if (this.isRemoved()) { - CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); + // CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); // Paper - this is an undesired duplicate event } diff --git a/patches/server-remapped/0652-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/server/0589-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 86% rename from patches/server-remapped/0652-Return-chat-component-with-empty-text-instead-of-thr.patch rename to patches/server/0589-Return-chat-component-with-empty-text-instead-of-thr.patch index 8f0e61039a..7b391807e5 100644 --- a/patches/server-remapped/0652-Return-chat-component-with-empty-text-instead-of-thr.patch +++ b/patches/server/0589-Return-chat-component-with-empty-text-instead-of-thr.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Return chat component with empty text instead of throwing diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -index b5d79635cd8b0eb6b17962450b347010aeb52654..d2f762371f82d54bcec8b1a0a02d0866e55fd174 100644 +index 766c907f92ca8cb19b22cd19185cc92603aeca03..311ace44ba65d6dd24941b56e78e148134ceb6f9 100644 --- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -12,6 +12,7 @@ import net.minecraft.ReportedException; +@@ -20,6 +20,7 @@ import net.minecraft.ReportedException; import net.minecraft.core.NonNullList; import net.minecraft.core.Registry; import net.minecraft.network.chat.Component; @@ -17,7 +17,7 @@ index b5d79635cd8b0eb6b17962450b347010aeb52654..d2f762371f82d54bcec8b1a0a02d0866 import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; -@@ -60,7 +61,12 @@ public abstract class AbstractContainerMenu { +@@ -82,7 +83,12 @@ public abstract class AbstractContainerMenu { } private Component title; public final Component getTitle() { diff --git a/patches/server/0590-Make-schedule-command-per-world.patch b/patches/server/0590-Make-schedule-command-per-world.patch new file mode 100644 index 0000000000..121eda3867 --- /dev/null +++ b/patches/server/0590-Make-schedule-command-per-world.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 4 Jan 2021 19:52:44 -0800 +Subject: [PATCH] Make schedule command per-world + + +diff --git a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java +index 018923e519544561747240618bce5df60475cdc6..7f5d249502e9b2fb9e5811cfeb43122b47f7b111 100644 +--- a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java ++++ b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java +@@ -29,7 +29,7 @@ public class ScheduleCommand { + return new TranslatableComponent("commands.schedule.cleared.failure", eventName); + }); + private static final SuggestionProvider SUGGEST_SCHEDULE = (context, builder) -> { +- return SharedSuggestionProvider.suggest(context.getSource().getServer().getWorldData().overworldData().getScheduledEvents().getEventsIds(), builder); ++ return SharedSuggestionProvider.suggest(context.getSource().getLevel().serverLevelData.overworldData().getScheduledEvents().getEventsIds(), builder); // Paper + }; + + public static void register(CommandDispatcher dispatcher) { +@@ -52,7 +52,7 @@ public class ScheduleCommand { + } else { + long l = source.getLevel().getGameTime() + (long)time; + ResourceLocation resourceLocation = function.getFirst(); +- TimerQueue timerQueue = source.getServer().getWorldData().overworldData().getScheduledEvents(); ++ TimerQueue timerQueue = source.getLevel().serverLevelData.getScheduledEvents(); // Paper + function.getSecond().ifLeft((functionx) -> { + String string = resourceLocation.toString(); + if (replace) { +@@ -75,7 +75,7 @@ public class ScheduleCommand { + } + + private static int remove(CommandSourceStack source, String eventName) throws CommandSyntaxException { +- int i = source.getServer().getWorldData().overworldData().getScheduledEvents().remove(eventName); ++ int i = source.getLevel().serverLevelData.getScheduledEvents().remove(eventName); // Paper + if (i == 0) { + throw ERROR_CANT_REMOVE.create(eventName); + } else { diff --git a/patches/server-remapped/0654-Configurable-max-leash-distance.patch b/patches/server/0591-Configurable-max-leash-distance.patch similarity index 94% rename from patches/server-remapped/0654-Configurable-max-leash-distance.patch rename to patches/server/0591-Configurable-max-leash-distance.patch index 42d46d7655..de244acf73 100644 --- a/patches/server-remapped/0654-Configurable-max-leash-distance.patch +++ b/patches/server/0591-Configurable-max-leash-distance.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable max leash distance diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3dd228ae8071a747f2cd7b2b46a2215183f72cd0..c4ca7ed5b251a2a3d64297351ef32541a4243c35 100644 +index 16b80fe4c55c51d3afaefba7eef97d1e3e4a3248..4ceb6b048889c62edb69c88422abddd1aee0bcf7 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -166,6 +166,12 @@ public class PaperWorldConfig { +@@ -266,6 +266,12 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0592-Implement-BlockPreDispenseEvent.patch b/patches/server/0592-Implement-BlockPreDispenseEvent.patch new file mode 100644 index 0000000000..7dd8f1e5f5 --- /dev/null +++ b/patches/server/0592-Implement-BlockPreDispenseEvent.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Miller +Date: Sun, 17 Jan 2021 13:16:09 +1000 +Subject: [PATCH] Implement BlockPreDispenseEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +index 501a5483160dba050261bb3448317a097cdb7ef2..2dcac4b638073aa1748f26f61219dbf95fd1ced6 100644 +--- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +@@ -91,6 +91,7 @@ public class DispenserBlock extends BaseEntityBlock { + DispenseItemBehavior idispensebehavior = this.getDispenseMethod(itemstack); + + if (idispensebehavior != DispenseItemBehavior.NOOP) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(world, pos, itemstack, i)) return; // Paper - BlockPreDispenseEvent is called here + DispenserBlock.eventFired = false; // CraftBukkit - reset event status + tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index f6f2856c407abe195f1dfee7f4a7e30baea585f7..ea7082ab595f7bce572eec66ce7790a0afa8dae1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1809,5 +1809,11 @@ public class CraftEventFactory { + io.papermc.paper.event.block.BlockFailedDispenseEvent event = new io.papermc.paper.event.block.BlockFailedDispenseEvent(block); + return event.callEvent(); + } ++ ++ public static boolean handleBlockPreDispenseEvent(ServerLevel serverLevel, BlockPos pos, ItemStack itemStack, int slot) { ++ org.bukkit.block.Block block = serverLevel.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ io.papermc.paper.event.block.BlockPreDispenseEvent event = new io.papermc.paper.event.block.BlockPreDispenseEvent(block, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), slot); ++ return event.callEvent(); ++ } + // Paper end + } diff --git a/patches/server-remapped/0656-Added-Vanilla-Entity-Tags.patch b/patches/server/0593-Added-Vanilla-Entity-Tags.patch similarity index 86% rename from patches/server-remapped/0656-Added-Vanilla-Entity-Tags.patch rename to patches/server/0593-Added-Vanilla-Entity-Tags.patch index fcf1ba26d8..25885466ab 100644 --- a/patches/server-remapped/0656-Added-Vanilla-Entity-Tags.patch +++ b/patches/server/0593-Added-Vanilla-Entity-Tags.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Added Vanilla Entity Tags diff --git a/src/main/java/io/papermc/paper/CraftEntityTag.java b/src/main/java/io/papermc/paper/CraftEntityTag.java new file mode 100644 -index 0000000000000000000000000000000000000000..687edf189871fc989174248dbf070bcba161f1a8 +index 0000000000000000000000000000000000000000..6271586368c65250c887739d04c5fccf95fdb2d8 --- /dev/null +++ b/src/main/java/io/papermc/paper/CraftEntityTag.java @@ -0,0 +1,28 @@ @@ -30,32 +30,32 @@ index 0000000000000000000000000000000000000000..687edf189871fc989174248dbf070bcb + + @Override + public boolean isTagged(EntityType item) { -+ return getHandle().isTagged(CraftMagicNumbers.getEntityTypes(item)); ++ return getHandle().contains(CraftMagicNumbers.getEntityTypes(item)); + } + + @Override + public Set getValues() { -+ return Collections.unmodifiableSet(getHandle().getTagged().stream().map(CraftMagicNumbers::getEntityType).collect(Collectors.toSet())); ++ return Collections.unmodifiableSet(getHandle().getValues().stream().map(CraftMagicNumbers::getEntityType).collect(Collectors.toSet())); + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 046fbc646d2818bb2c7e08ff22093523e8246523..3d7cc98710bb925743e6fe8de1f154096334d46c 100644 +index ecae20bb39848cc0223df3c4804a68f4e0731e3b..726db110f27ce46b8ed9c78dad14542bba1622a8 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2221,6 +2221,11 @@ public final class CraftServer implements Server { +@@ -2222,6 +2222,11 @@ public final class CraftServer implements Server { Preconditions.checkArgument(clazz == org.bukkit.Fluid.class, "Fluid namespace must have fluid type"); - return (org.bukkit.Tag) new CraftFluidTag(console.getTags().getFluids(), key); + return (org.bukkit.Tag) new CraftFluidTag(FluidTags.getAllTags(), key); + // Paper start + case org.bukkit.Tag.REGISTRY_ENTITIES: + Preconditions.checkArgument(clazz == org.bukkit.entity.EntityType.class, "Entity namespace must have entitytype type"); -+ return (org.bukkit.Tag) new io.papermc.paper.CraftEntityTag(console.getTags().getEntityTypes(), key); ++ return (org.bukkit.Tag) new io.papermc.paper.CraftEntityTag(net.minecraft.tags.EntityTypeTags.getAllTags(), key); + // Paper end default: throw new IllegalArgumentException(); } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index ac94fd569bd4c79e30adef148e09e395ba8c1812..25a29d997f163ce2b11330d66a691601f514a9cb 100644 +index 3d5f9ac267943fe2487a5cc4f9f059b169b438a8..f70d7b1c9b10f59b4d9c8575b9cc35409fec11e4 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -116,8 +116,17 @@ public final class CraftMagicNumbers implements UnsafeValues { diff --git a/patches/server-remapped/0657-added-Wither-API.patch b/patches/server/0594-added-Wither-API.patch similarity index 71% rename from patches/server-remapped/0657-added-Wither-API.patch rename to patches/server/0594-added-Wither-API.patch index 175023cea0..acd4657b80 100644 --- a/patches/server-remapped/0657-added-Wither-API.patch +++ b/patches/server/0594-added-Wither-API.patch @@ -5,13 +5,13 @@ Subject: [PATCH] added Wither API diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index 1f330d852eb9b3a36570542e10a88ae065798714..fd91c80cd6337b5fa41d6060ecdb44b8fa68a16a 100644 +index 03263689479d0f163fceb834bda07e7be13b798d..1e479853ec239b5e970b478adb3419e400d2f1d6 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -80,6 +80,11 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -83,6 +83,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob return entityliving.getMobType() != MobType.UNDEAD && entityliving.attackable(); }; - private static final TargetingConditions TARGETING_CONDITIONS = (new TargetingConditions()).range(20.0D).selector(WitherBoss.LIVING_ENTITY_SELECTOR); + private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0D).selector(WitherBoss.LIVING_ENTITY_SELECTOR); + // Paper start + private boolean canPortal = false; + @@ -20,15 +20,7 @@ index 1f330d852eb9b3a36570542e10a88ae065798714..fd91c80cd6337b5fa41d6060ecdb44b8 public WitherBoss(EntityType type, Level world) { super(type, world); -@@ -578,6 +583,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { - this.entityData.set((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(headIndex), id); - } - -+ public final boolean isPowered() { return this.isPowered(); } // Paper - OBFHELPER - public boolean isPowered() { - return this.getHealth() <= this.getMaxHealth() / 2.0F; - } -@@ -594,7 +600,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -591,7 +596,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob @Override public boolean canChangeDimensions() { @@ -38,12 +30,12 @@ index 1f330d852eb9b3a36570542e10a88ae065798714..fd91c80cd6337b5fa41d6060ecdb44b8 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -index fdcd680b972da54f9cdb41dff5563e42bd12d8e3..a09f46c586416b77dda40067fe1639a9250af3f0 100644 +index 640b0860fbe3412da32d03187e6f355ba8f099ea..299d5e47489cfe489ac130a33a08cdb29ba76d72 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java @@ -38,4 +38,31 @@ public class CraftWither extends CraftMonster implements Wither, com.destroystok public BossBar getBossBar() { - return bossBar; + return this.bossBar; } + + // Paper start diff --git a/patches/server-remapped/0658-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/patches/server/0595-Added-firing-of-PlayerChangeBeaconEffectEvent.patch similarity index 56% rename from patches/server-remapped/0658-Added-firing-of-PlayerChangeBeaconEffectEvent.patch rename to patches/server/0595-Added-firing-of-PlayerChangeBeaconEffectEvent.patch index e2d21ff095..c1aa4158a8 100644 --- a/patches/server-remapped/0658-Added-firing-of-PlayerChangeBeaconEffectEvent.patch +++ b/patches/server/0595-Added-firing-of-PlayerChangeBeaconEffectEvent.patch @@ -5,33 +5,22 @@ Subject: [PATCH] Added firing of PlayerChangeBeaconEffectEvent diff --git a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java -index 1371bfe4a4b5bb065de4d2118b2b32f4ee0b78d9..20069eeece4e03827ed4b3b4e2b713c43b23a366 100644 +index 4c76ef8ac18c538f97fd33cf5de47441c17b9181..91118c5d7d1414cacb80aad753c44c90f5812cf2 100644 --- a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java +++ b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java -@@ -11,6 +11,10 @@ import net.minecraft.world.level.block.Blocks; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - // CraftBukkit end - -+// Paper start -+import io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent; -+// Paper end -+ - public class BeaconMenu extends AbstractContainerMenu { - - private final Container beacon; -@@ -137,9 +141,15 @@ public class BeaconMenu extends AbstractContainerMenu { +@@ -160,9 +160,15 @@ public class BeaconMenu extends AbstractContainerMenu { public void updateEffects(int primaryEffectId, int secondaryEffectId) { if (this.paymentSlot.hasItem()) { - this.beaconData.set(1, primaryEffectId); - this.beaconData.set(2, secondaryEffectId); + // Paper start -+ PlayerChangeBeaconEffectEvent event = new PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), org.bukkit.potion.PotionEffectType.getById(primaryEffectId), org.bukkit.potion.PotionEffectType.getById(secondaryEffectId), this.access.getLocation().getBlock()); ++ io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent event = new io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), org.bukkit.potion.PotionEffectType.getById(primaryEffectId), org.bukkit.potion.PotionEffectType.getById(secondaryEffectId), this.access.getLocation().getBlock()); + if (event.callEvent()) { + this.beaconData.set(1, event.getPrimary() == null ? 0 : event.getPrimary().getId()); + this.beaconData.set(2, event.getSecondary() == null ? 0 : event.getSecondary().getId()); + if (!event.willConsumeItem()) return; - this.paymentSlot.a(1); + this.paymentSlot.remove(1); + } + // Paper end } diff --git a/patches/server-remapped/0659-Fix-console-spam-when-removing-chests-in-water.patch b/patches/server/0596-Fix-console-spam-when-removing-chests-in-water.patch similarity index 86% rename from patches/server-remapped/0659-Fix-console-spam-when-removing-chests-in-water.patch rename to patches/server/0596-Fix-console-spam-when-removing-chests-in-water.patch index 239c089fb6..717ceaeacc 100644 --- a/patches/server-remapped/0659-Fix-console-spam-when-removing-chests-in-water.patch +++ b/patches/server/0596-Fix-console-spam-when-removing-chests-in-water.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix console spam when removing chests in water diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java -index 6b95cd2e2af66eef324dfcc8f7642da2f9e39d4e..d061548b5490f441b91a2dd90e7668a05f7f2112 100644 +index eecb8c089b5f426b1395b47f714af32c210555ef..d980a556785b52fe827310b83638139df0816b11 100644 --- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java +++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java -@@ -239,7 +239,7 @@ public class ChestBlock extends AbstractChestBlock implements +@@ -248,7 +248,7 @@ public class ChestBlock extends AbstractChestBlock implements @Override public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) { if (!state.is(newState.getBlock())) { diff --git a/patches/server-remapped/0660-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server/0597-Add-toggle-for-always-placing-the-dragon-egg.patch similarity index 79% rename from patches/server-remapped/0660-Add-toggle-for-always-placing-the-dragon-egg.patch rename to patches/server/0597-Add-toggle-for-always-placing-the-dragon-egg.patch index 2dafd06172..1ca09dd0b5 100644 --- a/patches/server-remapped/0660-Add-toggle-for-always-placing-the-dragon-egg.patch +++ b/patches/server/0597-Add-toggle-for-always-placing-the-dragon-egg.patch @@ -5,12 +5,12 @@ Subject: [PATCH] Add toggle for always placing the dragon egg diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c4ca7ed5b251a2a3d64297351ef32541a4243c35..40939de88b1a8169dbfc7a0cd288c2fe9b706426 100644 +index 4ceb6b048889c62edb69c88422abddd1aee0bcf7..7738b5959f347cb369646852e7174aa580546400 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -795,4 +795,9 @@ public class PaperWorldConfig { - if (value != -1) entityPerChunkSaveLimits.put(type, value); - }); +@@ -683,5 +683,10 @@ public class PaperWorldConfig { + private void perPlayerMobSpawns() { + perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); } + + public boolean enderDragonsDeathAlwaysPlacesDragonEgg = false; @@ -18,11 +18,12 @@ index c4ca7ed5b251a2a3d64297351ef32541a4243c35..40939de88b1a8169dbfc7a0cd288c2fe + enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); + } } + diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 84447e9845edad2d228b94184b35b4afb453a14b..e2f784b771b12bd646d519938c33b1c86cc2686d 100644 +index e1d689aa65b8d993c7223d306363366f3adff62f..f88719dede80c064f6210e078c435ffda32ecc1a 100644 --- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -396,7 +396,7 @@ public class EndDragonFight { +@@ -363,7 +363,7 @@ public class EndDragonFight { this.dragonEvent.setVisible(false); this.spawnExitPortal(true); this.spawnNewGateway(); diff --git a/patches/server/0598-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server/0598-Added-PlayerStonecutterRecipeSelectEvent.patch new file mode 100644 index 0000000000..b48d754a11 --- /dev/null +++ b/patches/server/0598-Added-PlayerStonecutterRecipeSelectEvent.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 27 Nov 2020 17:14:27 -0800 +Subject: [PATCH] Added PlayerStonecutterRecipeSelectEvent + +Co-Authored-By: MiniDigger + +diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +index eac9765ecf0b33cab8b04204591de8d56c6f75c7..72d1d7722691ff411cb481ac8be6afba0c3b989c 100644 +--- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +@@ -62,7 +62,7 @@ public class StonecutterMenu extends AbstractContainerMenu { + + public StonecutterMenu(int syncId, Inventory playerInventory, final ContainerLevelAccess context) { + super(MenuType.STONECUTTER, syncId); +- this.selectedRecipeIndex = DataSlot.standalone(); ++ this.selectedRecipeIndex = addDataSlot(DataSlot.shared(new int[1], 0)); // Paper - allow replication + this.recipes = Lists.newArrayList(); + this.input = ItemStack.EMPTY; + this.slotUpdateListener = () -> { +@@ -156,7 +156,29 @@ public class StonecutterMenu extends AbstractContainerMenu { + @Override + public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + if (this.isValidRecipeIndex(id)) { +- this.selectedRecipeIndex.set(id); ++ // Paper start ++ int recipeIndex = id; ++ this.selectedRecipeIndex.set(recipeIndex); ++ this.selectedRecipeIndex.checkAndClearUpdateFlag(); // mark as changed ++ if (this.isValidRecipeIndex(id)) { ++ io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent event = new io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent((Player) player.getBukkitEntity(), (org.bukkit.inventory.StonecutterInventory) getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) this.getRecipes().get(id).toBukkitRecipe()); ++ if (!event.callEvent()) { ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ return false; ++ } ++ int newRecipeIndex; ++ if (!this.getRecipes().get(recipeIndex).getId().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { // If the recipe did NOT stay the same ++ for (newRecipeIndex = 0; newRecipeIndex < this.getRecipes().size(); newRecipeIndex++) { ++ if (this.getRecipes().get(newRecipeIndex).getId().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { ++ recipeIndex = newRecipeIndex; ++ break; ++ } ++ } ++ } ++ } ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ this.selectedRecipeIndex.set(recipeIndex); // set new index, so that listeners can read it ++ // Paper end + this.setupResultSlot(); + } + diff --git a/patches/server-remapped/0662-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/server/0599-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 81% rename from patches/server-remapped/0662-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/server/0599-Add-dropLeash-variable-to-EntityUnleashEvent.patch index 33a094ba1f..fbf737e2d8 100644 --- a/patches/server-remapped/0662-Add-dropLeash-variable-to-EntityUnleashEvent.patch +++ b/patches/server/0599-Add-dropLeash-variable-to-EntityUnleashEvent.patch @@ -5,36 +5,28 @@ Subject: [PATCH] Add dropLeash variable to EntityUnleashEvent diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 87dd6c012bf1ca6a1e8df44dc0957c4c67d02adc..ea34306858116e5626383af408529091836c2752 100644 +index c9324245d18f8268191c0a89b465ef3054dd014d..c25f80baea8857c35a3faaa82d80e2e358449a83 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -86,6 +86,7 @@ import org.bukkit.event.entity.EntityTargetEvent; - import org.bukkit.event.entity.EntityTransformEvent; - import org.bukkit.event.entity.EntityUnleashEvent; - import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; -+import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper - // CraftBukkit end - - public abstract class Mob extends LivingEntity { -@@ -1205,12 +1206,15 @@ public abstract class Mob extends LivingEntity { +@@ -1208,12 +1208,15 @@ public abstract class Mob extends LivingEntity { return InteractionResult.PASS; } else if (this.getLeashHolder() == player) { // CraftBukkit start - fire PlayerUnleashEntityEvent - if (CraftEventFactory.callPlayerUnleashEntityEvent(this, player).isCancelled()) { + // Paper start - drop leash variable -+ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, player, !player.abilities.instabuild); ++ org.bukkit.event.player.PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, player, !player.getAbilities().instabuild); + if (event.isCancelled()) { + // Paper end ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); return InteractionResult.PASS; } // CraftBukkit end -- this.dropLeash(true, !player.abilities.instabuild); +- this.dropLeash(true, !player.getAbilities().instabuild); + this.dropLeash(true, event.isDropLeash()); // Paper - drop leash variable return InteractionResult.sidedSuccess(this.level.isClientSide); } else { InteractionResult enuminteractionresult = this.checkAndHandleImportantInteractions(player, hand); -@@ -1364,8 +1368,11 @@ public abstract class Mob extends LivingEntity { +@@ -1371,8 +1374,11 @@ public abstract class Mob extends LivingEntity { if (this.leashHolder != null) { if (!this.isAlive() || !this.leashHolder.isAlive()) { @@ -48,7 +40,7 @@ index 87dd6c012bf1ca6a1e8df44dc0957c4c67d02adc..ea34306858116e5626383af408529091 } } -@@ -1433,8 +1440,11 @@ public abstract class Mob extends LivingEntity { +@@ -1435,8 +1441,11 @@ public abstract class Mob extends LivingEntity { boolean flag1 = super.startRiding(entity, force); if (flag1 && this.isLeashed()) { @@ -62,7 +54,7 @@ index 87dd6c012bf1ca6a1e8df44dc0957c4c67d02adc..ea34306858116e5626383af408529091 } return flag1; -@@ -1636,7 +1646,10 @@ public abstract class Mob extends LivingEntity { +@@ -1606,8 +1615,11 @@ public abstract class Mob extends LivingEntity { @Override protected void removeAfterChangingDimensions() { super.removeAfterChangingDimensions(); @@ -73,8 +65,9 @@ index 87dd6c012bf1ca6a1e8df44dc0957c4c67d02adc..ea34306858116e5626383af408529091 + this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit + this.dropLeash(true, event.isDropLeash()); + // Paper end - } - } + this.getAllSlots().forEach((itemstack) -> { + if (!itemstack.isEmpty()) itemstack.setCount(0); // CraftBukkit + }); diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java index a884940cc576704951d42c6b0d00f5a319297c29..d16a7bab5495d58ea9e6811d4b507667cfa3d264 100644 --- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java @@ -108,40 +101,31 @@ index a884940cc576704951d42c6b0d00f5a319297c29..d16a7bab5495d58ea9e6811d4b507667 } else if (f > 6.0F) { double d0 = (entity.getX() - this.getX()) / (double) f; diff --git a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java -index 465548de7e32028a2aed4b6e9543e1bd9b73700b..1f54c020cc2b1928b2e7edda9ddf7b9d61e6424b 100644 +index b9b67134f02fd7484ed19905c9ae1f9b8a26ce26..c05f173b7642380900fdd77ce5d2c020468b5fc0 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java +++ b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java -@@ -28,6 +28,8 @@ import net.minecraft.world.phys.AABB; - import org.bukkit.craftbukkit.event.CraftEventFactory; - // CraftBukkit end - -+import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper -+ - public class LeashFenceKnotEntity extends HangingEntity { - - public LeashFenceKnotEntity(EntityType type, Level world) { -@@ -123,11 +125,14 @@ public class LeashFenceKnotEntity extends HangingEntity { +@@ -123,11 +123,14 @@ public class LeashFenceKnotEntity extends HangingEntity { entityinsentient = (Mob) iterator.next(); if (entityinsentient.isLeashed() && entityinsentient.getLeashHolder() == this) { // CraftBukkit start - if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, player).isCancelled()) { + // Paper start - drop leash variable -+ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, player, !player.abilities.instabuild); ++ org.bukkit.event.player.PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, player, !player.getAbilities().instabuild); + if (event.isCancelled()) { + // Paper end die = false; continue; } -- entityinsentient.dropLeash(true, !player.abilities.instabuild); // false -> survival mode boolean +- entityinsentient.dropLeash(true, !player.getAbilities().instabuild); // false -> survival mode boolean + entityinsentient.dropLeash(true, event.isDropLeash()); // false -> survival mode boolean // Paper - drop leash variable // CraftBukkit end } } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 34c0216baa69206aca51821aec421484b18cb04c..ea7c30ef17fc66c1fb55d5909f94651c98b181be 100644 +index ea7082ab595f7bce572eec66ce7790a0afa8dae1..2b5f63c3f0ff3039fbef9afdfa46e0e715d347bc 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1460,8 +1460,10 @@ public class CraftEventFactory { +@@ -1466,8 +1466,10 @@ public class CraftEventFactory { return itemInHand; } diff --git a/patches/server-remapped/0663-Skip-distance-map-update-when-spawning-disabled.patch b/patches/server/0600-Skip-distance-map-update-when-spawning-disabled.patch similarity index 87% rename from patches/server-remapped/0663-Skip-distance-map-update-when-spawning-disabled.patch rename to patches/server/0600-Skip-distance-map-update-when-spawning-disabled.patch index fac284074d..40fde190b3 100644 --- a/patches/server-remapped/0663-Skip-distance-map-update-when-spawning-disabled.patch +++ b/patches/server/0600-Skip-distance-map-update-when-spawning-disabled.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Skip distance map update when spawning disabled. diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 7a615a18f1f297adfe7e046407a019d8933e9ed9..8e27559a12ada05e0530c7fe5b0bfbc4422ccbd6 100644 +index 7ab28e9bd3f785838b7fa4ac5811c0e71cddcb61..b609740fb95ccd4c9d7a2a95fad3dfbff630db5f 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -825,7 +825,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -778,7 +778,7 @@ public class ServerChunkCache extends ChunkSource { int l = this.distanceManager.getNaturalSpawnChunkCount(); // Paper start - per player mob spawning NaturalSpawner.SpawnState spawnercreature_d; // moved down diff --git a/patches/server-remapped/0664-Reset-shield-blocking-on-dimension-change.patch b/patches/server/0601-Reset-shield-blocking-on-dimension-change.patch similarity index 80% rename from patches/server-remapped/0664-Reset-shield-blocking-on-dimension-change.patch rename to patches/server/0601-Reset-shield-blocking-on-dimension-change.patch index 4349f8f4d8..dac062f779 100644 --- a/patches/server-remapped/0664-Reset-shield-blocking-on-dimension-change.patch +++ b/patches/server/0601-Reset-shield-blocking-on-dimension-change.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Reset shield blocking on dimension change diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index ff831ca0cbc0cabbf78178c609ccf70d78da7980..314f168c9d17ab3654c9dda07e48839570f0d332 100644 +index 5a87875b03740053d8cde6d81c57703d0b0ef57e..f9cf0c088f4c3de0a1a7b92beb6ee0c57a0b1326 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1115,6 +1115,11 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1117,6 +1117,11 @@ public class ServerPlayer extends Player { this.level.getCraftServer().getPluginManager().callEvent(changeEvent); // CraftBukkit end } diff --git a/patches/server/0602-add-DragonEggFormEvent.patch b/patches/server/0602-add-DragonEggFormEvent.patch new file mode 100644 index 0000000000..c7e3745a3b --- /dev/null +++ b/patches/server/0602-add-DragonEggFormEvent.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Mon, 25 Jan 2021 14:53:57 +0100 +Subject: [PATCH] add DragonEggFormEvent + + +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index f88719dede80c064f6210e078c435ffda32ecc1a..93dd5a2d0b550b0373cbf59376a04e9fd6146e92 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -363,9 +363,24 @@ public class EndDragonFight { + this.dragonEvent.setVisible(false); + this.spawnExitPortal(true); + this.spawnNewGateway(); ++ // Paper start - DragonEggFormEvent ++ BlockPos eggPosition = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.END_PODIUM_LOCATION); ++ org.bukkit.craftbukkit.block.CraftBlock eggBlock = org.bukkit.craftbukkit.block.CraftBlock.at(this.level, eggPosition); ++ org.bukkit.craftbukkit.block.CraftBlockState eggState = new org.bukkit.craftbukkit.block.CraftBlockState(eggBlock); ++ eggState.setData(Blocks.DRAGON_EGG.defaultBlockState()); ++ io.papermc.paper.event.block.DragonEggFormEvent eggEvent = new io.papermc.paper.event.block.DragonEggFormEvent(eggBlock, eggState, ++ new org.bukkit.craftbukkit.boss.CraftDragonBattle(this)); ++ // Paper end - DragonEggFormEvent + if (this.level.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg +- this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.END_PODIUM_LOCATION), Blocks.DRAGON_EGG.defaultBlockState()); ++ // Paper start - DragonEggFormEvent ++ //this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); ++ } else { ++ eggEvent.setCancelled(true); ++ } ++ if (eggEvent.callEvent()) { ++ eggEvent.getNewState().update(true); + } ++ // Paper end - DragonEggFormEvent + + this.previouslyKilled = true; + this.dragonKilled = true; diff --git a/patches/server-remapped/0666-EntityMoveEvent.patch b/patches/server/0603-EntityMoveEvent.patch similarity index 53% rename from patches/server-remapped/0666-EntityMoveEvent.patch rename to patches/server/0603-EntityMoveEvent.patch index eec865bf53..b6b9cba0ed 100644 --- a/patches/server-remapped/0666-EntityMoveEvent.patch +++ b/patches/server/0603-EntityMoveEvent.patch @@ -5,59 +5,43 @@ Subject: [PATCH] EntityMoveEvent diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 892ca65d258b0745be95d7ef4886c49899b24d92..bc44811f26076871848ba8f5c582ab26b1fd7170 100644 +index 51bbb11ff8d3da95fa6d9890be3135a34b3eafac..c8213692e658f6eb82d3bd843b9525ff6565cc81 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -13,6 +13,7 @@ import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; - import io.papermc.paper.adventure.PaperAdventure; // Paper -+import io.papermc.paper.event.entity.EntityMoveEvent; - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -1458,6 +1459,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper -+ worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper ++ worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper + net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper this.profiler.push(() -> { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 9f1838d12b13d64f10871eb672ed2aec78d9936e..338b4c382fb8ea349ce81f2009e96de1df7ac5e2 100644 +index 0e14946284738b751790b2763bfe197c0148a54a..5cd1fe3506b1009de9fce64c3f4f44a29f13c359 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -207,6 +207,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -200,6 +200,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl public final LevelStorageSource.LevelStorageAccess convertable; public final UUID uuid; public boolean hasPhysicsEvent = true; // Paper + public boolean hasEntityMoveEvent = false; // Paper - private static Throwable getAddToWorldStackTrace(Entity entity) { + public static Throwable getAddToWorldStackTrace(Entity entity) { return new Throwable(entity + " Added to world at " + new java.util.Date()); } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 02ddb84c563b3149c4f1b0e24899ce8a21ad61bb..8bc74878919ab7cf6a50d425da61f1b8a8b0ee44 100644 +index 19ef1b2814270b9385ea15a89dac8c2613a672ee..8c3fb37c511ada39dafdd19fa85e21a1b458386b 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -10,6 +10,7 @@ import com.mojang.datafixers.util.Pair; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import com.mojang.serialization.DynamicOps; -+import io.papermc.paper.event.entity.EntityMoveEvent; - import java.util.Collection; - import java.util.ConcurrentModificationException; - import java.util.Iterator; -@@ -2909,6 +2910,20 @@ public abstract class LivingEntity extends Entity { +@@ -3217,6 +3217,20 @@ public abstract class LivingEntity extends Entity { this.pushEntities(); this.level.getProfiler().pop(); + // Paper start -+ if (((ServerLevel) level).hasEntityMoveEvent) { -+ if (xo != getX() || yo != getY() || zo != getZ() || yRotO != yRot || xRotO != xRot) { -+ Location from = new Location(level.getWorld(), xo, yo, zo, yRotO, xRotO); -+ Location to = new Location (level.getWorld(), getX(), getY(), getZ(), yRot, xRot); -+ EntityMoveEvent event = new EntityMoveEvent(getBukkitLivingEntity(), from, to.clone()); ++ if (((ServerLevel) this.level).hasEntityMoveEvent) { ++ if (this.xo != getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) { ++ Location from = new Location(this.level.getWorld(), this.xo, this.yo, this.zo, this.yRotO, this.xRotO); ++ Location to = new Location (this.level.getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ io.papermc.paper.event.entity.EntityMoveEvent event = new io.papermc.paper.event.entity.EntityMoveEvent(this.getBukkitLivingEntity(), from, to.clone()); + if (!event.callEvent()) { + absMoveTo(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); + } else if (!to.equals(event.getTo())) { From 0c732e2ef50c83414929fc9d3421d376e822ce42 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 18:50:13 -0700 Subject: [PATCH 126/226] Put pom in correct location for Paperclip install to maven local feature --- Paper-MojangAPI/build.gradle.kts | 7 +++++++ patches/api/0001-Convert-project-to-Gradle.patch | 11 +++++++++-- patches/api/0002-Build-system-changes.patch | 4 ++-- patches/api/0003-Add-FastUtil-to-Bukkit.patch | 4 ++-- patches/api/0006-Adventure.patch | 4 ++-- .../api/0024-Use-ASM-for-event-executors.patch | 4 ++-- ...-Allow-plugins-to-use-SLF4J-for-logging.patch | 4 ++-- patches/server/0001-Setup-Gradle-project.patch | 16 +++++++++++++--- patches/server/0003-Build-system-changes.patch | 14 ++++++++++++-- 9 files changed, 51 insertions(+), 17 deletions(-) diff --git a/Paper-MojangAPI/build.gradle.kts b/Paper-MojangAPI/build.gradle.kts index 536b4577cf..0fdb8a028b 100644 --- a/Paper-MojangAPI/build.gradle.kts +++ b/Paper-MojangAPI/build.gradle.kts @@ -1,5 +1,6 @@ plugins { `java-library` + `maven-publish` } java { @@ -23,3 +24,9 @@ dependencies { testImplementation("org.hamcrest:hamcrest-library:1.3") testImplementation("org.ow2.asm:asm-tree:7.3.1") } + +configure { + publications.create("maven") { + from(components["java"]) + } +} diff --git a/patches/api/0001-Convert-project-to-Gradle.patch b/patches/api/0001-Convert-project-to-Gradle.patch index 64567fb6dd..c152ea3140 100644 --- a/patches/api/0001-Convert-project-to-Gradle.patch +++ b/patches/api/0001-Convert-project-to-Gradle.patch @@ -16,14 +16,15 @@ index e431e3435737e28394d81b56568a08b3c3148b9b..c484aff2c192bf42059b5689327909e4 /.project diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 -index 0000000000000000000000000000000000000000..35b57f52fcfd91cff04dc60c3a8a16b31f775fc0 +index 0000000000000000000000000000000000000000..271a6672e7fe9ce51bf96c8c18f5579fc47b2414 --- /dev/null +++ b/build.gradle.kts -@@ -0,0 +1,59 @@ +@@ -0,0 +1,66 @@ +import java.util.Locale + +plugins { + `java-library` ++ `maven-publish` +} + +java { @@ -52,6 +53,12 @@ index 0000000000000000000000000000000000000000..35b57f52fcfd91cff04dc60c3a8a16b3 + testImplementation("org.ow2.asm:asm-tree:9.1") +} + ++configure { ++ publications.create("maven") { ++ from(components["java"]) ++ } ++} ++ +val generateApiVersioningFile by tasks.registering { + val pomProps = layout.buildDirectory.file("pom.properties") + outputs.file(pomProps) diff --git a/patches/api/0002-Build-system-changes.patch b/patches/api/0002-Build-system-changes.patch index 012a45883a..3ca987e846 100644 --- a/patches/api/0002-Build-system-changes.patch +++ b/patches/api/0002-Build-system-changes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Build system changes diff --git a/build.gradle.kts b/build.gradle.kts -index 35b57f52fcfd91cff04dc60c3a8a16b31f775fc0..328fe3d7708b0e93dad080c7689d0d7cde138288 100644 +index 271a6672e7fe9ce51bf96c8c18f5579fc47b2414..125fee17f7ab37fb2b4deb096f37a43cb9519e96 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -16,12 +16,14 @@ dependencies { +@@ -17,12 +17,14 @@ dependencies { api("com.google.code.gson:gson:2.8.0") api("net.md-5:bungeecord-chat:1.16-R0.4") api("org.yaml:snakeyaml:1.29") diff --git a/patches/api/0003-Add-FastUtil-to-Bukkit.patch b/patches/api/0003-Add-FastUtil-to-Bukkit.patch index a315769d11..c5c0470aa7 100644 --- a/patches/api/0003-Add-FastUtil-to-Bukkit.patch +++ b/patches/api/0003-Add-FastUtil-to-Bukkit.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add FastUtil to Bukkit Doesn't expose to plugins, just allows Paper-API to use it for optimization diff --git a/build.gradle.kts b/build.gradle.kts -index 20c8a34b299ba455c29b4e31d311de0b3a063288..6243c2fc2021e6c4fe0f036892bc83983364f360 100644 +index 125fee17f7ab37fb2b4deb096f37a43cb9519e96..e4123d5f918a5f21b7f6fddba7084643f86ad5aa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -17,6 +17,7 @@ dependencies { +@@ -18,6 +18,7 @@ dependencies { api("net.md-5:bungeecord-chat:1.16-R0.4") api("org.yaml:snakeyaml:1.29") api("com.googlecode.json-simple:json-simple:1.1.1") // Paper diff --git a/patches/api/0006-Adventure.patch b/patches/api/0006-Adventure.patch index ca041f6d3b..5d255c4fc0 100644 --- a/patches/api/0006-Adventure.patch +++ b/patches/api/0006-Adventure.patch @@ -7,10 +7,10 @@ Co-authored-by: zml Co-authored-by: Jake Potrebic diff --git a/build.gradle.kts b/build.gradle.kts -index 6243c2fc2021e6c4fe0f036892bc83983364f360..d22f6ce80583f4a12e61b5ca89033deeeebde5d5 100644 +index e4123d5f918a5f21b7f6fddba7084643f86ad5aa..176180570bf2705d975cf349faf08b5ba32cdab3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -18,6 +18,11 @@ dependencies { +@@ -19,6 +19,11 @@ dependencies { api("org.yaml:snakeyaml:1.29") api("com.googlecode.json-simple:json-simple:1.1.1") // Paper api("it.unimi.dsi:fastutil:8.2.2") diff --git a/patches/api/0024-Use-ASM-for-event-executors.patch b/patches/api/0024-Use-ASM-for-event-executors.patch index ba94a254e2..303673fd3d 100644 --- a/patches/api/0024-Use-ASM-for-event-executors.patch +++ b/patches/api/0024-Use-ASM-for-event-executors.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Use ASM for event executors. Uses method handles for private or static methods. diff --git a/build.gradle.kts b/build.gradle.kts -index d22f6ce80583f4a12e61b5ca89033deeeebde5d5..a5f7258a543c8a9e2ce55c6f8f1b6f3435ef608e 100644 +index 176180570bf2705d975cf349faf08b5ba32cdab3..c10c9f86db276b42d8b7c21c353970691990f125 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -23,6 +23,8 @@ dependencies { +@@ -24,6 +24,8 @@ dependencies { api("net.kyori:adventure-text-serializer-gson") api("net.kyori:adventure-text-serializer-legacy") api("net.kyori:adventure-text-serializer-plain") diff --git a/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch b/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch index 2196884838..0ee190ea33 100644 --- a/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch +++ b/patches/api/0067-Allow-plugins-to-use-SLF4J-for-logging.patch @@ -14,10 +14,10 @@ it without having to shade it in the plugin and going through several layers of logging abstraction. diff --git a/build.gradle.kts b/build.gradle.kts -index a5f7258a543c8a9e2ce55c6f8f1b6f3435ef608e..12c4f278d52bd6fb626fc7cd9414e8869c49fcd2 100644 +index c10c9f86db276b42d8b7c21c353970691990f125..6d04816e22f44a33c001d2b7e080402fba6af86c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -25,6 +25,7 @@ dependencies { +@@ -26,6 +26,7 @@ dependencies { api("net.kyori:adventure-text-serializer-plain") api("org.ow2.asm:asm:9.0") api("org.ow2.asm:asm-commons:9.0") diff --git a/patches/server/0001-Setup-Gradle-project.patch b/patches/server/0001-Setup-Gradle-project.patch index b2c3b3a0e8..8672be8dda 100644 --- a/patches/server/0001-Setup-Gradle-project.patch +++ b/patches/server/0001-Setup-Gradle-project.patch @@ -17,11 +17,10 @@ index 67fb370cad6924895a6b27052dbd5c1767e3f0c9..3e05459f27c4c5697ae65da504d67a6a /.project diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 -index 0000000000000000000000000000000000000000..21b97f37a4c4d35d80bc1c1b98f55bcfb8d21f20 +index 0000000000000000000000000000000000000000..80fab4621582aed02cc029900999ceff72e027ef --- /dev/null +++ b/build.gradle.kts -@@ -0,0 +1,121 @@ -+import com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer +@@ -0,0 +1,131 @@ +import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer +import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer +import io.papermc.paperweight.util.Git @@ -33,6 +32,7 @@ index 0000000000000000000000000000000000000000..21b97f37a4c4d35d80bc1c1b98f55bcf + +plugins { + java ++ `maven-publish` + id("com.github.johnrengelman.shadow") +} + @@ -86,6 +86,16 @@ index 0000000000000000000000000000000000000000..21b97f37a4c4d35d80bc1c1b98f55bcf + } +} + ++configure { ++ publications.create("maven") { ++ // todo: confirm this is correct ++ from(components["java"]) ++ artifact(tasks.reobfJar) { ++ classifier = "reobf" ++ } ++ } ++} ++ +tasks.shadowJar { + listOf( + "jline", "it.unimi", "org.apache.commons.codec", "org.apache.commons.io", diff --git a/patches/server/0003-Build-system-changes.patch b/patches/server/0003-Build-system-changes.patch index 29cd18e973..37c7c0d01e 100644 --- a/patches/server/0003-Build-system-changes.patch +++ b/patches/server/0003-Build-system-changes.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Build system changes diff --git a/build.gradle.kts b/build.gradle.kts -index ccb67fe90e25010f7c8ca168d60d096ef95c4429..f353524ada2caa05824b1e7ded17a1c00473d906 100644 +index 80fab4621582aed02cc029900999ceff72e027ef..07be9eb1dd7f0f85e8a36cc4e8df807bae989372 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,21 +22,24 @@ repositories { @@ -47,9 +47,19 @@ index ccb67fe90e25010f7c8ca168d60d096ef95c4429..f353524ada2caa05824b1e7ded17a1c0 )) for (tld in listOf("net", "com", "org")) { attributes(mapOf( -@@ -65,7 +69,7 @@ tasks.jar { +@@ -73,9 +77,17 @@ configure { + } + } ++val generatePom = tasks.named("generatePomFileForMavenPublication") ++ tasks.shadowJar { ++ // Needed for Paperclip's install to maven local feature ++ from(generatePom) { ++ into("META-INF/maven/io.papermc.paper/paper") ++ rename { "pom.xml" } ++ } ++ listOf( - "jline", "it.unimi", "org.apache.commons.codec", "org.apache.commons.io", + "jline", "org.apache.commons.codec", "org.apache.commons.io", // Paper - don't relocate fastutil From 24b7da65eed610c18d1c7a66578b57ca71428a00 Mon Sep 17 00:00:00 2001 From: mechoriet Date: Tue, 15 Jun 2021 04:41:12 +0200 Subject: [PATCH 127/226] Re-add Chunk Priority/Urgency System (#5829) --- ...-Priority-Urgency-System-for-Chunks.patch} | 556 +++++++----------- 1 file changed, 197 insertions(+), 359 deletions(-) rename patches/{removed/1.17/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch => server/0468-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch} (70%) diff --git a/patches/removed/1.17/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server/0468-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch similarity index 70% rename from patches/removed/1.17/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch rename to patches/server/0468-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch index 2ebcfe75f1..619abec3da 100644 --- a/patches/removed/1.17/0486-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch +++ b/patches/server/0468-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch @@ -25,7 +25,7 @@ fast traveling players keep up with their movement. 1.17 update note: very big diff skipping for now, still needs to be updated diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -index 499aff1f1e1ffc01ba8f9de43ca17899525a306f..97b85587525ddb62af9bfc8785b48727a6135599 100644 +index 18ae2e2b339d357fbe0f6f2b18bc14c0dfe4c222..782301661f739192798ca6ef501b184bea990c5a 100644 --- a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java +++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java @@ -108,7 +108,7 @@ public final class ChunkTaskManager { @@ -41,7 +41,7 @@ index 499aff1f1e1ffc01ba8f9de43ca17899525a306f..97b85587525ddb62af9bfc8785b48727 PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Priority - " + chunkHolder.getCurrentPriority()); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Priority - " + chunkHolder.getQueueLevel()); + + if (!chunkHolder.neighbors.isEmpty()) { + if (indent >= maxDepth) { @@ -51,7 +51,7 @@ index 499aff1f1e1ffc01ba8f9de43ca17899525a306f..97b85587525ddb62af9bfc8785b48727 + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: "); + for (ChunkHolder neighbor : chunkHolder.neighbors.keySet()) { + ChunkStatus status = neighbor.getChunkHolderStatus(); -+ if (status != null && status.isAtLeastStatus(ChunkHolder.getStatus(neighbor.getTicketLevel()))) { ++ if (status != null && status.isOrAfter(ChunkHolder.getStatus(neighbor.getTicketLevel()))) { + continue; + } + int nx = neighbor.pos.x; @@ -68,92 +68,43 @@ index 499aff1f1e1ffc01ba8f9de43ca17899525a306f..97b85587525ddb62af9bfc8785b48727 } } -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index d18497a33dc53f6b465e659967bf8c98731c46c0..9a5737caf250dd2cc7f244248226f69117b27bad 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -631,10 +631,10 @@ public final class MCUtil { - - // sorting by coordinate makes the log easier to read - allChunks.sort((ChunkHolder v1, ChunkHolder v2) -> { -- if (v1.location.x != v2.location.x) { -- return Integer.compare(v1.location.x, v2.location.x); -+ if (v1.pos.x != v2.pos.x) { -+ return Integer.compare(v1.pos.x, v2.pos.x); - } -- return Integer.compare(v1.location.z, v2.location.z); -+ return Integer.compare(v1.pos.z, v2.pos.z); - }); - - worldData.addProperty("name", world.getWorld().getName()); -@@ -667,14 +667,15 @@ public final class MCUtil { - for (ChunkHolder playerChunk : allChunks) { - JsonObject chunkData = new JsonObject(); - -- Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.pair()); -+ Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.toLong()); - ChunkStatus status = getChunkStatus(playerChunk); - -- chunkData.addProperty("x", playerChunk.location.x); -- chunkData.addProperty("z", playerChunk.location.z); -+ chunkData.addProperty("x", playerChunk.pos.x); -+ chunkData.addProperty("z", playerChunk.pos.z); - chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); -+ chunkData.addProperty("priority", playerChunk.getCurrentPriority()); - chunkData.addProperty("state", ChunkHolder.getFullChunkStatus(playerChunk.getTicketLevel()).toString()); -- chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.pair())); -+ chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.toLong())); - chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); - - JsonArray ticketsData = new JsonArray(); diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index d907872d80f840b343419f49a6708082da6f921b..ce320672d7602c94dd75ad857435dca6ac3bab56 100644 +index 1f67c9c5f7161ea687983e7ae0ec7d259da9acd3..6a1c000d693031f0c537112963cfa52e22463f1d 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -1,6 +1,7 @@ +@@ -1,5 +1,6 @@ package net.minecraft.server.level; ++import com.destroystokyo.paper.io.PrioritizedTaskQueue; import com.mojang.datafixers.util.Either; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper import it.unimi.dsi.fastutil.shorts.ShortArraySet; import it.unimi.dsi.fastutil.shorts.ShortSet; - import java.util.List; -@@ -19,6 +20,7 @@ import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; - import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; - import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; - import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; -+import net.minecraft.server.MCUtil; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.LightLayer; -@@ -52,8 +54,8 @@ public class ChunkHolder { - private CompletableFuture chunkToSave; +@@ -60,7 +61,7 @@ public class ChunkHolder { + private final DebugBuffer chunkToSaveHistory; public int oldTicketLevel; private int ticketLevel; - private int queueLevel; -- final ChunkPos pos; // Paper - private -> package -+ volatile int queueLevel; public final int getCurrentPriority() { return queueLevel; } // Paper - OBFHELPER - make volatile since this is concurrently accessed -+ public final ChunkPos pos; // Paper - private -> public ++ volatile int queueLevel; // Paper - make volatile since this is concurrently accessed + public final ChunkPos pos; // Paper - package->public private boolean hasChangedSections; private final ShortSet[] changedBlocksPerSection; - private int blockChangedLightSectionFilter; -@@ -65,6 +67,7 @@ public class ChunkHolder { - private boolean resendLight; +@@ -75,6 +76,7 @@ public class ChunkHolder { + boolean isUpdateQueued = false; // Paper private final ChunkMap chunkMap; // Paper + public ServerLevel getWorld() { return chunkMap.level; } // Paper - + // Paper start - no-tick view distance + public final LevelChunk getSendingChunk() { + // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used +@@ -113,7 +115,120 @@ public class ChunkHolder { + // Paper end - optimise isOutsideOfRange long lastAutoSaveTime; // Paper - incremental autosave long inactiveTimeStart; // Paper - incremental autosave -@@ -92,6 +95,120 @@ public class ChunkHolder { - return null; - } - // Paper end - no-tick view distance + // Paper start - Chunk gen/load priority system + volatile int neighborPriority = -1; + volatile int priorityBoost = 0; + public final java.util.concurrent.ConcurrentHashMap neighbors = new java.util.concurrent.ConcurrentHashMap<>(); -+ public final Long2ObjectOpenHashMap neighborPriorities = new Long2ObjectOpenHashMap<>(); ++ public final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap neighborPriorities = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(); + + private int getDemandedPriority() { + int priority = neighborPriority; // if we have a neighbor priority, use it @@ -180,7 +131,7 @@ index d907872d80f840b343419f49a6708082da6f921b..ce320672d7602c94dd75ad857435dca6 + public void onNeighborRequest(ChunkHolder neighbor, ChunkStatus status) { + neighbor.setNeighborPriority(this, getNeighborsPriority()); + this.neighbors.compute(neighbor, (playerChunk, currentWantedStatus) -> { -+ if (currentWantedStatus == null || !currentWantedStatus.isAtLeastStatus(status)) { ++ if (currentWantedStatus == null || !currentWantedStatus.isOrAfter(status)) { + //System.out.println(this + " request " + neighbor + " at " + status + " currently " + currentWantedStatus); + return status; + } else { @@ -193,7 +144,7 @@ index d907872d80f840b343419f49a6708082da6f921b..ce320672d7602c94dd75ad857435dca6 + + public void onNeighborDone(ChunkHolder neighbor, ChunkStatus chunkstatus, ChunkAccess chunk) { + this.neighbors.compute(neighbor, (playerChunk, wantedStatus) -> { -+ if (wantedStatus != null && chunkstatus.isAtLeastStatus(wantedStatus)) { ++ if (wantedStatus != null && chunkstatus.isOrAfter(wantedStatus)) { + //System.out.println(this + " neighbor done at " + neighbor + " for status " + chunkstatus + " wanted " + wantedStatus); + neighbor.removeNeighborPriority(this); + return null; @@ -220,7 +171,7 @@ index d907872d80f840b343419f49a6708082da6f921b..ce320672d7602c94dd75ad857435dca6 + } + checkPriority(); + } -+ + + private void recalcNeighborPriority() { + neighborPriority = -1; + if (!neighborPriorities.isEmpty()) { @@ -234,15 +185,15 @@ index d907872d80f840b343419f49a6708082da6f921b..ce320672d7602c94dd75ad857435dca6 + } + } + private void checkPriority() { -+ if (getCurrentPriority() != getDemandedPriority()) this.chunkMap.queueHolderUpdate(this); ++ if (getQueueLevel() != getDemandedPriority()) this.chunkMap.queueHolderUpdate(this); + } + + public final double getDistance(ServerPlayer player) { + return getDistance(player.getX(), player.getZ()); + } + public final double getDistance(double blockX, double blockZ) { -+ int cx = MCUtil.fastFloor(blockX) >> 4; -+ int cz = MCUtil.fastFloor(blockZ) >> 4; ++ int cx = net.minecraft.server.MCUtil.fastFloor(blockX) >> 4; ++ int cz = net.minecraft.server.MCUtil.fastFloor(blockZ) >> 4; + final double x = pos.x - cx; + final double z = pos.z - cz; + return (x * x) + (z * z); @@ -259,41 +210,34 @@ index d907872d80f840b343419f49a6708082da6f921b..ce320672d7602c94dd75ad857435dca6 + ", ticketLevel=" + ticketLevel + "/" + getStatus(this.ticketLevel) + + ", chunkHolderStatus=" + getChunkHolderStatus() + + ", neighborPriority=" + getNeighborsPriority() + -+ ", priority=(" + ticketLevel + " - " + priorityBoost +" vs N " + neighborPriority + ") = " + getDemandedPriority() + " A " + getCurrentPriority() + ++ ", priority=(" + ticketLevel + " - " + priorityBoost +" vs N " + neighborPriority + ") = " + getDemandedPriority() + " A " + getQueueLevel() + + '}'; + } + // Paper end - - public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); -@@ -194,6 +311,18 @@ public class ChunkHolder { - } + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +@@ -164,7 +279,18 @@ public class ChunkHolder { return null; } + // CraftBukkit end +- + public static ChunkStatus getNextStatus(ChunkStatus status) { + if (status == ChunkStatus.FULL) { -+ return status; -+ } -+ return CHUNK_STATUSES.get(status.getStatusIndex() + 1); ++ return status; ++ } ++ return CHUNK_STATUSES.get(status.getIndex() + 1); + } + public CompletableFuture> getStatusFutureUncheckedMain(ChunkStatus chunkstatus) { -+ return ensureMain(getFutureIfPresentUnchecked(chunkstatus)); -+ } ++ return ensureMain(getFutureIfPresentUnchecked(chunkstatus)); ++ } + public CompletableFuture ensureMain(CompletableFuture future) { + return future.thenApplyAsync(r -> r, chunkMap.mainInvokingExecutor); + } - // Paper end - public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { -@@ -440,6 +569,7 @@ public class ChunkHolder { - return this.queueLevel; - } + CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(leastStatus.getIndex()); -+ private void setPriority(int i) { setQueueLevel(i); } // Paper - OBFHELPER - private void setQueueLevel(int level) { - this.queueLevel = level; - } -@@ -458,7 +588,7 @@ public class ChunkHolder { +@@ -488,7 +614,7 @@ public class ChunkHolder { // CraftBukkit start // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. if (playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { @@ -302,58 +246,65 @@ index d907872d80f840b343419f49a6708082da6f921b..ce320672d7602c94dd75ad857435dca6 LevelChunk chunk = (LevelChunk)either.left().orElse(null); if (chunk != null) { chunkStorage.callbackExecutor.execute(() -> { -@@ -523,12 +653,13 @@ public class ChunkHolder { - if (!flag2 && flag3) { +@@ -553,13 +679,14 @@ public class ChunkHolder { + this.fullChunkFuture = chunkStorage.prepareAccessibleChunk(this); + this.scheduleFullChunkPromotion(chunkStorage, this.fullChunkFuture, executor, ChunkHolder.FullChunkStatus.BORDER); // Paper start - cache ticking ready status - int expectCreateCount = ++this.fullChunkCreateCount; -- this.fullChunkFuture = chunkStorage.unpackTicks(this); this.fullChunkFuture.thenAccept((either) -> { -+ this.fullChunkFuture = chunkStorage.unpackTicks(this); ensureMain(this.fullChunkFuture).thenAccept((either) -> { // Paper - ensure main - if (either.left().isPresent() && ChunkHolder.this.fullChunkCreateCount == expectCreateCount) { +- this.fullChunkFuture.thenAccept(either -> { ++ ensureMain(this.fullChunkFuture).thenAccept(either -> { // Paper ensureMain + final Optional left = either.left(); + if (left.isPresent() && ChunkHolder.this.fullChunkCreateCount == expectCreateCount) { // note: Here is a very good place to add callbacks to logic waiting on this. LevelChunk fullChunk = either.left().get(); ChunkHolder.this.isFullChunkReady = true; fullChunk.playerChunk = ChunkHolder.this; -+ this.chunkMap.distanceManager.clearPriorityTickets(pos); - - ++ this.chunkMap.getDistanceManager().clearPriorityTickets(pos); } -@@ -553,7 +684,7 @@ public class ChunkHolder { - - if (!flag4 && flag5) { + }); + this.updateChunkToSave(this.fullChunkFuture, "full"); +@@ -583,11 +710,12 @@ public class ChunkHolder { + this.tickingChunkFuture = chunkStorage.prepareTickingChunk(this); + this.scheduleFullChunkPromotion(chunkStorage, this.tickingChunkFuture, executor, ChunkHolder.FullChunkStatus.TICKING); // Paper start - cache ticking ready status -- this.tickingChunkFuture = chunkStorage.postProcess(this); this.tickingChunkFuture.thenAccept((either) -> { -+ this.tickingChunkFuture = chunkStorage.postProcess(this); ensureMain(this.tickingChunkFuture).thenAccept((either) -> { // Paper - ensure main - if (either.left().isPresent()) { +- this.tickingChunkFuture.thenAccept(either -> { ++ ensureMain(this.tickingChunkFuture).thenAccept(either -> {// Paper - ensureMain + either.ifLeft(chunk -> { // note: Here is a very good place to add callbacks to logic waiting on this. - LevelChunk tickingChunk = either.left().get(); -@@ -584,7 +715,7 @@ public class ChunkHolder { - } - +- ChunkHolder.this.isTickingReady = true; +- ++ LevelChunk fullChunk = either.left().get(); ++ ChunkHolder.this.isFullChunkReady = true; ++ fullChunk.playerChunk = ChunkHolder.this; + // Paper start - rewrite ticklistserver + ChunkHolder.this.chunkMap.level.onChunkSetTicking(ChunkHolder.this.pos.x, ChunkHolder.this.pos.z); + // Paper end - rewrite ticklistserver +@@ -613,7 +741,7 @@ public class ChunkHolder { + this.entityTickingChunkFuture = chunkStorage.prepareEntityTickingChunk(this.pos); + this.scheduleFullChunkPromotion(chunkStorage, this.entityTickingChunkFuture, executor, ChunkHolder.FullChunkStatus.ENTITY_TICKING); // Paper start - cache ticking ready status -- this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); this.entityTickingChunkFuture.thenAccept((either) -> { -+ this.entityTickingChunkFuture = chunkStorage.getEntityTickingRangeFuture(this.pos); ensureMain(this.entityTickingChunkFuture).thenAccept((either) -> { // Paper ensureMain - if (either.left().isPresent()) { - // note: Here is a very good place to add callbacks to logic waiting on this. - LevelChunk entityTickingChunk = either.left().get(); -@@ -604,12 +735,29 @@ public class ChunkHolder { - this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +- this.entityTickingChunkFuture.thenAccept(either -> { ++ ensureMain(this.entityTickingChunkFuture).thenAccept(either -> {// Paper - ensureMain + either.ifLeft(chunk -> { + ChunkHolder.this.isEntityTickingReady = true; + }); +@@ -632,11 +760,29 @@ public class ChunkHolder { } -- this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); + this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); + // Paper start - raise IO/load priority if priority changes, use our preferred priority -+ priorityBoost = chunkMap.distanceManager.getChunkPriority(pos); ++ priorityBoost = this.chunkMap.getDistanceManager().getChunkPriority(pos); + int priority = getDemandedPriority(); -+ if (getCurrentPriority() > priority) { -+ int ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; ++ if (getQueueLevel() > priority) { ++ int ioPriority = PrioritizedTaskQueue.NORMAL_PRIORITY; + if (priority <= 10) { -+ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; ++ ioPriority = PrioritizedTaskQueue.HIGHEST_PRIORITY; + } else if (priority <= 20) { -+ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; ++ ioPriority = PrioritizedTaskQueue.HIGH_PRIORITY; + } + chunkMap.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, ioPriority); + } -+ if (getCurrentPriority() != priority) { -+ this.onLevelChange.onLevelChange(this.pos, this::getCurrentPriority, priority, this::setPriority); // use preferred priority ++ if (getQueueLevel() != priority) { ++ this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, priority, this::setQueueLevel); // use preferred priority + int neighborsPriority = getNeighborsPriority(); + this.neighbors.forEach((neighbor, neighborDesired) -> neighbor.setNeighborPriority(this, neighborsPriority)); + } @@ -363,12 +314,12 @@ index d907872d80f840b343419f49a6708082da6f921b..ce320672d7602c94dd75ad857435dca6 // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. if (!playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { - this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { -+ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main ++ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> {// Paper - ensure main LevelChunk chunk = (LevelChunk)either.left().orElse(null); if (chunk != null) { chunkStorage.callbackExecutor.execute(() -> { -@@ -691,6 +839,7 @@ public class ChunkHolder { - +@@ -714,6 +860,7 @@ public class ChunkHolder { + @FunctionalInterface public interface LevelChangeListener { + default void changePriority(ChunkPos chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer) { onLevelChange(chunkcoordintpair, intsupplier, i, intconsumer); } // Paper - OBFHELPER @@ -376,34 +327,10 @@ index d907872d80f840b343419f49a6708082da6f921b..ce320672d7602c94dd75ad857435dca6 } diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c06720820 100644 +index 5a5e9188f55405c8a2646891c348d544d33eb940..b86ff17cdfa613a03bd75eeaab194de03a597b29 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -14,6 +14,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; - import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - import it.unimi.dsi.fastutil.longs.Long2ByteMap; - import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; // Paper - import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; - import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; - import it.unimi.dsi.fastutil.longs.LongIterator; -@@ -51,6 +52,7 @@ import net.minecraft.CrashReport; - import net.minecraft.CrashReportCategory; - import net.minecraft.ReportedException; - import net.minecraft.Util; -+import net.minecraft.core.BlockPos; - import net.minecraft.core.SectionPos; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.network.protocol.Packet; -@@ -102,6 +104,7 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - import org.bukkit.entity.Player; // CraftBukkit -+import org.spigotmc.AsyncCatcher; - - public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider { - -@@ -139,6 +142,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -145,6 +145,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public final ServerLevel level; private final ThreadedLevelLightEngine lightEngine; private final BlockableEventLoop mainThreadExecutor; @@ -411,24 +338,24 @@ index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c public final ChunkGenerator generator; private final Supplier overworldDataStorage; public final Supplier getWorldPersistentDataSupplier() { return this.overworldDataStorage; } // Paper - OBFHELPER private final PoiManager poiManager; -@@ -176,6 +180,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -183,6 +184,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @Override public void execute(Runnable runnable) { -+ AsyncCatcher.catchOp("Callback Executor execute"); - if (queued == null) { - queued = new java.util.ArrayDeque<>(); ++ org.spigotmc.AsyncCatcher.catchOp("Callback Executor execute"); // Paper + if (this.queue == null) { + this.queue = new java.util.ArrayDeque<>(); } -@@ -184,6 +189,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -191,6 +193,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @Override public void run() { -+ AsyncCatcher.catchOp("Callback Executor run"); - if (queued == null) { ++ org.spigotmc.AsyncCatcher.catchOp("Callback Executor run"); // Paper + if (this.queue == null) { return; } -@@ -338,6 +344,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.level = worldserver; +@@ -347,6 +350,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.level = world; this.generator = chunkGenerator; this.mainThreadExecutor = mainThreadExecutor; + // Paper start @@ -440,10 +367,10 @@ index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c + } + }; + // Paper end - ProcessorMailbox threadedmailbox = ProcessorMailbox.create(workerExecutor, "worldgen"); + ProcessorMailbox threadedmailbox = ProcessorMailbox.create(executor, "worldgen"); - mainThreadExecutor.getClass(); -@@ -432,6 +447,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + Objects.requireNonNull(mainThreadExecutor); +@@ -442,6 +454,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { @@ -451,7 +378,7 @@ index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c if (newState.size() != 1) { return; } -@@ -450,7 +466,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -460,7 +473,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); ChunkMap.this.level.getChunkSource().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update @@ -464,7 +391,7 @@ index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -@@ -467,6 +487,115 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -477,8 +494,116 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider }); // Paper end - no-tick view distance } @@ -486,12 +413,13 @@ index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c + mainThreadExecutor.execute(runnable); + } + } -+ + + // Paper start + private boolean isUnloading(ChunkHolder playerchunk) { + return playerchunk == null || toDrop.contains(playerchunk.pos.toLong()); + } + -+ private void updateChunkPriorityMap(Long2IntOpenHashMap map, long chunk, int level) { ++ private void updateChunkPriorityMap(it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap map, long chunk, int level) { + int prev = map.getOrDefault(chunk, -1); + if (level > prev) { + map.put(chunk, level); @@ -504,10 +432,10 @@ index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c + return; + } + player.lastHighPriorityChecked = currentTick; -+ Long2IntOpenHashMap priorities = new Long2IntOpenHashMap(); ++ it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap priorities = new it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap(); + + int viewDistance = getEffectiveNoTickViewDistance(); -+ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); ++ net.minecraft.core.BlockPos.MutableBlockPos pos = new net.minecraft.core.BlockPos.MutableBlockPos(); + + // Prioritize circular near + double playerChunkX = Mth.floor(player.getX()) >> 4; @@ -577,10 +505,10 @@ index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c + return chunk != null && (chunk.isFullChunkReady()); + } + // Paper end - public void updatePlayerMobTypeMap(Entity entity) { if (!this.level.paperConfig.perPlayerMobSpawns) { -@@ -596,6 +725,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return; +@@ -636,6 +761,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider List>> list = Lists.newArrayList(); int j = centerChunk.x; int k = centerChunk.z; @@ -588,7 +516,7 @@ index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c for (int l = -margin; l <= margin; ++l) { for (int i1 = -margin; i1 <= margin; ++i1) { -@@ -614,6 +744,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -654,6 +780,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider ChunkStatus chunkstatus = (ChunkStatus) distanceToStatus.apply(j1); CompletableFuture> completablefuture = playerchunk.getOrScheduleFuture(chunkstatus, this); @@ -603,12 +531,12 @@ index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c list.add(completablefuture); } -@@ -1081,14 +1219,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1100,14 +1234,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider }; CompletableFuture chunkSaveFuture = this.level.asyncChunkTaskManager.getChunkSaveFuture(pos.x, pos.z); + ChunkHolder playerChunk = getUpdatingChunkIfPresent(pos.toLong()); -+ int chunkPriority = playerChunk != null ? playerChunk.getCurrentPriority() : 33; ++ int chunkPriority = playerChunk != null ? playerChunk.getQueueLevel() : 33; + int priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; + + if (chunkPriority <= 10) { @@ -631,64 +559,36 @@ index 8070acde38c47c364c1d26ec3b7d65da037554a5..7a1f6d1807757a43a7aa471db651404c return ret; // Paper end } -@@ -1233,7 +1379,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1238,7 +1380,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider long i = playerchunk.getPos().toLong(); - playerchunk.getClass(); + Objects.requireNonNull(playerchunk); - mailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, playerchunk::getTicketLevel)); + mailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, () -> 1)); // Paper - final loads are always urgent! }); } diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a906f07e97 100644 +index d94241bcca4f2fd5e464a860bd356af504dc68b7..864c78ae0f0b3b50b8ea22b709c1f16bea0ecfea 100644 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java +++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -21,7 +21,10 @@ import java.util.Set; - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.Executor; - import javax.annotation.Nullable; -+import net.minecraft.core.BlockPos; - import net.minecraft.core.SectionPos; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.SortedArraySet; - import net.minecraft.util.thread.ProcessorHandle; - import net.minecraft.world.level.ChunkPos; -@@ -29,6 +32,7 @@ import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.LevelChunk; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import org.spigotmc.AsyncCatcher; // Paper - - public abstract class DistanceManager { - -@@ -52,7 +56,7 @@ public abstract class DistanceManager { - private final ChunkTaskPriorityQueueSorter ticketThrottler; - private final ProcessorHandle> ticketThrottlerInput; - private final ProcessorHandle ticketThrottlerReleaser; -- private final LongSet ticketsToRelease = new LongOpenHashSet(); -+ private final LongSet ticketsToRelease = new LongOpenHashSet(); public final LongSet getOnPlayerTicketAddQueue() { return ticketsToRelease; } // Paper - OBFHELPER - private final Executor mainThreadExecutor; - private long ticketTickCounter; - -@@ -90,6 +94,7 @@ public abstract class DistanceManager { +@@ -98,6 +98,7 @@ public abstract class DistanceManager { } private static int getTicketLevelAt(SortedArraySet> arraysetsorted) { -+ AsyncCatcher.catchOp("ChunkMapDistance::getLowestTicketLevel"); // Paper ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::getLowestTicketLevel"); // Paper return !arraysetsorted.isEmpty() ? ((Ticket) arraysetsorted.first()).getTicketLevel() : ChunkMap.MAX_CHUNK_DISTANCE + 1; } -@@ -103,6 +108,7 @@ public abstract class DistanceManager { +@@ -111,6 +112,7 @@ public abstract class DistanceManager { - public boolean runAllUpdates(ChunkMap chunkStorage) { + public boolean runAllUpdates(ChunkMap playerchunkmap) { //this.f.a(); // Paper - no longer used -+ AsyncCatcher.catchOp("DistanceManagerTick"); // Paper ++ org.spigotmc.AsyncCatcher.catchOp("DistanceManagerTick"); // Paper this.playerTicketManager.runAllUpdates(); int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE); boolean flag = i != 0; -@@ -113,11 +119,13 @@ public abstract class DistanceManager { +@@ -121,11 +123,13 @@ public abstract class DistanceManager { // Paper start if (!this.pendingChunkUpdates.isEmpty()) { @@ -696,44 +596,44 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 while(!this.pendingChunkUpdates.isEmpty()) { ChunkHolder remove = this.pendingChunkUpdates.remove(); remove.isUpdateQueued = false; - remove.updateFutures(chunkStorage); + remove.updateFutures(playerchunkmap, this.mainThreadExecutor); } + } finally { this.pollingPendingChunkUpdates = false; } // Paper end return true; } else { -@@ -153,8 +161,10 @@ public abstract class DistanceManager { +@@ -161,8 +165,10 @@ public abstract class DistanceManager { return flag; } } + boolean pollingPendingChunkUpdates = false; // Paper - private boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean -+ AsyncCatcher.catchOp("ChunkMapDistance::addTicket"); // Paper + boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::addTicket"); // Paper SortedArraySet> arraysetsorted = this.getTickets(i); - int j = getTicketLevelAt(arraysetsorted); + int j = DistanceManager.getTicketLevelAt(arraysetsorted); Ticket ticket1 = (Ticket) arraysetsorted.addOrGet(ticket); // CraftBukkit - decompile error -@@ -168,7 +178,9 @@ public abstract class DistanceManager { +@@ -176,7 +182,9 @@ public abstract class DistanceManager { } - private boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean -+ AsyncCatcher.catchOp("ChunkMapDistance::removeTicket"); // Paper + boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::removeTicket"); // Paper SortedArraySet> arraysetsorted = this.getTickets(i); + int oldLevel = getTicketLevelAt(arraysetsorted); // Paper boolean removed = false; // CraftBukkit if (arraysetsorted.remove(ticket)) { -@@ -179,7 +191,8 @@ public abstract class DistanceManager { +@@ -208,7 +216,8 @@ public abstract class DistanceManager { this.tickets.remove(i); } -- this.ticketTracker.update(i, getTicketLevelAt(arraysetsorted), false); +- this.ticketTracker.update(i, DistanceManager.getTicketLevelAt(arraysetsorted), false); + int newLevel = getTicketLevelAt(arraysetsorted); // Paper + if (newLevel > oldLevel) this.ticketTracker.update(i, newLevel, false); // Paper return removed; // CraftBukkit } -@@ -188,6 +201,135 @@ public abstract class DistanceManager { +@@ -217,6 +226,135 @@ public abstract class DistanceManager { this.addTicketAtLevel(type, pos, level, argument); } @@ -753,7 +653,7 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 + delayDistanceManagerTick = true; + priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); + int finalPriority = priority; -+ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { ++ net.minecraft.server.MCUtil.getSpiralOutChunks(center.getWorldPosition(), radius).forEach(coords -> { + addPriorityTicket(coords, TicketType.PRIORITY, finalPriority); + }); + delayDistanceManagerTick = false; @@ -762,7 +662,7 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 + + public void clearAreaPriorityTickets(ChunkPos center, int radius) { + delayDistanceManagerTick = true; -+ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { ++ net.minecraft.server.MCUtil.getSpiralOutChunks(center.getWorldPosition(), radius).forEach(coords -> { + this.removeTicket(coords.toLong(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); + }); + delayDistanceManagerTick = false; @@ -784,14 +684,14 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 + } + + private boolean addPriorityTicket(ChunkPos coords, TicketType ticketType, int priority) { -+ AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket"); ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket"); + long pair = coords.toLong(); + ChunkHolder chunk = chunkMap.getUpdatingChunkIfPresent(pair); + boolean needsTicket = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(pair) != null && !hasPlayerTicket(coords, 33); + + if (needsTicket) { + Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); -+ getOnPlayerTicketAddQueue().add(pair); ++ ticketsToRelease.add(pair); + addTicket(pair, ticket); + } + if ((chunk != null && chunk.isFullChunkReady())) { @@ -838,7 +738,7 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 + } + + public int getChunkPriority(ChunkPos coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::getChunkPriority"); ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::getChunkPriority"); + SortedArraySet> tickets = this.tickets.get(coords.toLong()); + if (tickets == null) { + return 0; @@ -857,38 +757,29 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 + } + + public void clearPriorityTickets(ChunkPos coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::clearPriority"); ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::clearPriority"); + this.removeTicket(coords.toLong(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); + } + + public void clearUrgent(ChunkPos coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::clearUrgent"); ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::clearUrgent"); + this.removeTicket(coords.toLong(), new Ticket(TicketType.URGENT, PRIORITY_TICKET_LEVEL, coords)); + } + // Paper end public boolean addTicketAtLevel(TicketType ticketType, ChunkPos chunkcoordintpair, int level, T identifier) { return this.addTicket(chunkcoordintpair.toLong(), new Ticket<>(ticketType, level, identifier)); // CraftBukkit end -@@ -358,7 +500,7 @@ public abstract class DistanceManager { - - class PlayerTicketTracker extends DistanceManager.FixedPlayerDistanceChunkTracker { - -- private int viewDistance = 0; -+ private int viewDistance = 0; private int getViewDistance() { return viewDistance; } private void setViewDistance(int value) { this.viewDistance = value; } // Paper - OBFHELPER - private final Long2IntMap queueLevels = Long2IntMaps.synchronize(new Long2IntOpenHashMap()); - private final LongSet toUpdate = new LongOpenHashSet(); - -@@ -374,41 +516,68 @@ public abstract class DistanceManager { +@@ -516,41 +654,68 @@ public abstract class DistanceManager { public void updateViewDistance(int watchDistance) { ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); + // Paper start - set the view distance before scheduling chunk loads/unloads -+ int lastViewDistance = getViewDistance(); -+ setViewDistance(watchDistance); ++ int lastViewDistance = viewDistance; ++ this.viewDistance = watchDistance; + // Paper end while (objectiterator.hasNext()) { - Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix + it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); @@ -908,7 +799,7 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 if (withinViewDistance) { - DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { -+ scheduleChunkLoad(pos, MinecraftServer.currentTick, distance, (priority) -> { // Paper - smarter ticket delay based on frustum and distance ++ scheduleChunkLoad(pos, net.minecraft.server.MinecraftServer.currentTick, distance, (priority) -> { // Paper - smarter ticket delay based on frustum and distance + // Paper start - recheck its still valid if not cancel + if (!isChunkInRange(pos)) { + DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { @@ -955,16 +846,16 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 }); }, pos, true)); } -@@ -416,6 +585,101 @@ public abstract class DistanceManager { +@@ -558,6 +723,101 @@ public abstract class DistanceManager { } + // Paper start - smart scheduling of player tickets + private boolean isChunkInRange(long i) { -+ return this.isLoadedChunkLevel(this.getChunkLevel(i)); ++ return this.haveTicketFor(this.getLevel(i)); + } + public void scheduleChunkLoad(long i, long startTick, int initialDistance, java.util.function.Consumer task) { -+ long elapsed = MinecraftServer.currentTick - startTick; ++ long elapsed = net.minecraft.server.MinecraftServer.currentTick - startTick; + ChunkPos chunkPos = new ChunkPos(i); + ChunkHolder updatingChunk = chunkMap.getUpdatingChunkIfPresent(i); + if ((updatingChunk != null && updatingChunk.isFullChunkReady()) || !isChunkInRange(i) || getChunkPriority(chunkPos) > 0) { // Copied from above @@ -982,10 +873,10 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 + } else if (players != null) { + Object[] backingSet = players.getBackingSet(); + -+ BlockPos blockPos = chunkPos.asPosition(); ++ net.minecraft.core.BlockPos blockPos = chunkPos.getWorldPosition(); + + boolean isFront = false; -+ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); ++ net.minecraft.core.BlockPos.MutableBlockPos pos = new net.minecraft.core.BlockPos.MutableBlockPos(); + for (int index = 0, len = backingSet.length; index < len; ++index) { + if (!(backingSet[index] instanceof ServerPlayer)) { + continue; @@ -994,16 +885,16 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 + + ChunkPos pointInFront = player.getChunkInFront(5); + pos.setValues(pointInFront.x << 4, 0, pointInFront.z << 4); -+ double frontDist = MCUtil.distanceSq(pos, blockPos); ++ double frontDist = net.minecraft.server.MCUtil.distanceSq(pos, blockPos); + + pos.setValues(player.getX(), 0, player.getZ()); -+ double center = MCUtil.distanceSq(pos, blockPos); ++ double center = net.minecraft.server.MCUtil.distanceSq(pos, blockPos); + + double dist = Math.min(frontDist, center); + if (!isFront) { + ChunkPos pointInBack = player.getChunkInFront(-7); + pos.setValues(pointInBack.x << 4, 0, pointInBack.z << 4); -+ double backDist = MCUtil.distanceSq(pos, blockPos); ++ double backDist = net.minecraft.server.MCUtil.distanceSq(pos, blockPos); + if (frontDist < backDist) { + isFront = true; + } @@ -1036,7 +927,7 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 + long pair = ChunkPos.asLong(chunkPos.x + x, chunkPos.z + z); + ChunkHolder neighbor = chunkMap.getUpdatingChunkIfPresent(pair); + ChunkStatus current = neighbor != null ? neighbor.getChunkHolderStatus() : null; -+ if (current != null && current.isAtLeastStatus(ChunkStatus.LIGHT)) { ++ if (current != null && current.isOrAfter(ChunkStatus.LIGHT)) { + hasAnyNeighbor = true; + } + } @@ -1049,7 +940,7 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 + task.accept((int) minDist); + } else { + int taskDelay = (int) Math.min(delay, minDist >= 10 ? 40 : (minDist < 6 ? 5 : 20)); -+ MCUtil.scheduleTask(taskDelay, () -> scheduleChunkLoad(i, startTick, initialDistance, task), "Player Ticket Delayer"); ++ net.minecraft.server.MCUtil.scheduleTask(taskDelay, () -> scheduleChunkLoad(i, startTick, initialDistance, task), "Player Ticket Delayer"); + } + } + // Paper end @@ -1057,27 +948,11 @@ index c9b4025f6c3d1be7bca2ff7337dd86e37d21b53e..e41f388e8350010a471410436adf15a9 @Override public void runAllUpdates() { super.runAllUpdates(); -@@ -447,6 +711,7 @@ public abstract class DistanceManager { - - } - -+ private boolean isLoadedChunkLevel(int i) { return haveTicketFor(i); } // Paper - OBFHELPER - private boolean haveTicketFor(int distance) { - return distance <= this.viewDistance - 2; - } -@@ -463,6 +728,7 @@ public abstract class DistanceManager { - this.chunks.defaultReturnValue((byte) (i + 2)); - } - -+ protected final int getChunkLevel(long i) { return getLevel(i); } // Paper - OBFHELPER - @Override - protected int getLevel(long id) { - return this.chunks.get(id); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd..f36badcafbad7fb4537ffdf54d9e266ae3d72459 100644 +index 7ab28e9bd3f785838b7fa4ac5811c0e71cddcb61..d13abec908dbb756272888e9ccdedbefff719012 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -467,6 +467,26 @@ public class ServerChunkCache extends ChunkSource { +@@ -446,6 +446,26 @@ public class ServerChunkCache extends ChunkSource { public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { this.distanceManager.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); } @@ -1101,11 +976,11 @@ index 52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd..f36badcafbad7fb4537ffdf54d9e266a + public void clearPriorityTickets(ChunkPos coords) { + this.distanceManager.clearPriorityTickets(coords); + } - // Paper end + // Paper end - async chunk io @Nullable -@@ -505,6 +525,8 @@ public class ServerChunkCache extends ChunkSource { - +@@ -486,6 +506,8 @@ public class ServerChunkCache extends ChunkSource { + Objects.requireNonNull(completablefuture); if (!completablefuture.isDone()) { // Paper // Paper start - async chunk io/loading + ChunkPos pair = new ChunkPos(x1, z1); @@ -1113,8 +988,8 @@ index 52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd..f36badcafbad7fb4537ffdf54d9e266a this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); // Paper end -@@ -513,6 +535,8 @@ public class ServerChunkCache extends ChunkSource { - this.mainThreadProcessor.managedBlock(completablefuture::isDone); +@@ -493,6 +515,8 @@ public class ServerChunkCache extends ChunkSource { + chunkproviderserver_a.managedBlock(completablefuture::isDone); com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug this.level.timings.syncChunkLoad.stopTiming(); // Paper + this.distanceManager.clearPriorityTickets(pair); // Paper @@ -1122,7 +997,7 @@ index 52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd..f36badcafbad7fb4537ffdf54d9e266a } // Paper ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { return ichunkaccess1; -@@ -565,10 +589,12 @@ public class ServerChunkCache extends ChunkSource { +@@ -566,10 +590,12 @@ public class ServerChunkCache extends ChunkSource { if (flag && !currentlyUnloading) { // CraftBukkit end this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); @@ -1135,7 +1010,7 @@ index 52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd..f36badcafbad7fb4537ffdf54d9e266a this.runDistanceManagerUpdates(); playerchunk = this.getVisibleChunkIfPresent(k); gameprofilerfiller.pop(); -@@ -577,8 +603,13 @@ public class ServerChunkCache extends ChunkSource { +@@ -578,8 +604,13 @@ public class ServerChunkCache extends ChunkSource { } } } @@ -1151,27 +1026,19 @@ index 52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd..f36badcafbad7fb4537ffdf54d9e266a } private boolean chunkAbsent(@Nullable ChunkHolder holder, int maxLevel) { -@@ -630,6 +661,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -631,6 +662,7 @@ public class ServerChunkCache extends ChunkSource { } - public boolean runDistanceManagerUpdates() { // Paper - private -> public + public boolean runDistanceManagerUpdates() { // Paper - packate-private -> public + if (distanceManager.delayDistanceManagerTick) return false; // Paper boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); boolean flag1 = this.chunkMap.promoteChunkMap(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 8e4cef60b760be385df81a74834d026f856a78c5..c5717f45a0110492aad41f21cc06fb8cbeb1f791 100644 +index cd34b5aa61c78d8138500a93f0a9714bedd7ed86..b106a972a76e856d6cdab78dec5daef77b135f98 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -73,6 +73,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; - import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; - import net.minecraft.resources.ResourceKey; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.PlayerAdvancements; - import net.minecraft.server.network.ServerGamePacketListenerImpl; -@@ -185,6 +186,12 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -183,6 +183,12 @@ public class ServerPlayer extends Player { private int lastRecordedArmor = Integer.MIN_VALUE; private int lastRecordedLevel = Integer.MIN_VALUE; private int lastRecordedExperience = Integer.MIN_VALUE; @@ -1184,20 +1051,20 @@ index 8e4cef60b760be385df81a74834d026f856a78c5..c5717f45a0110492aad41f21cc06fb8c private float lastSentHealth = -1.0E8F; private int lastSentFood = -99999999; private boolean lastFoodSaturationZero = true; -@@ -272,6 +279,21 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -324,6 +330,21 @@ public class ServerPlayer extends Player { this.maxHealthCache = this.getMaxHealth(); this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper } + // Paper start + public BlockPos getPointInFront(double inFront) { -+ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yRot+90)); // MC rotates yaw 90 for some odd reason ++ double rads = Math.toRadians(net.minecraft.server.MCUtil.normalizeYaw(this.getYRot()+90)); // MC rotates yaw 90 for some odd reason + final double x = getX() + inFront * Math.cos(rads); + final double z = getZ() + inFront * Math.sin(rads); + return new BlockPos(x, getY(), z); + } + + public ChunkPos getChunkInFront(double inFront) { -+ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yRot+90)); // MC rotates yaw 90 for some odd reason ++ double rads = Math.toRadians(net.minecraft.server.MCUtil.normalizeYaw(this.getYRot()+90)); // MC rotates yaw 90 for some odd reason + final double x = getX() + (inFront * 16) * Math.cos(rads); + final double z = getZ() + (inFront * 16) * Math.sin(rads); + return new ChunkPos(Mth.floor(x) >> 4, Mth.floor(z) >> 4); @@ -1206,27 +1073,27 @@ index 8e4cef60b760be385df81a74834d026f856a78c5..c5717f45a0110492aad41f21cc06fb8c // Yes, this doesn't match Vanilla, but it's the best we can do for now. // If this is an issue, PRs are welcome -@@ -619,6 +641,7 @@ public class ServerPlayer extends Player implements ContainerListener { - if (valid && !this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) +@@ -645,6 +666,7 @@ public class ServerPlayer extends Player { + if (valid && !this.isSpectator() || !this.touchingUnloadedChunk()) { // Paper - don't tick dead players that are not in the world currently (pending respawn) super.tick(); } + if (valid && isAlive() && connection != null) ((ServerLevel)level).getChunkSource().chunkMap.checkHighPriorityChunks(this); // Paper - for (int i = 0; i < this.inventory.getContainerSize(); ++i) { - ItemStack itemstack = this.inventory.getItem(i); + for (int i = 0; i < this.getInventory().getContainerSize(); ++i) { + ItemStack itemstack = this.getInventory().getItem(i); diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index c6b5f32153b63ac92df9c4b31b8de168481f79f2..c0bfe136ccb9ad4fc0f8ccdd703254205213ec8e 100644 +index a7aa7a9038d4812a9d1e4e72c4dbbbe10df15820..5c03bae6d34aae4752438650414460102a043a4b 100644 --- a/src/main/java/net/minecraft/server/level/Ticket.java +++ b/src/main/java/net/minecraft/server/level/Ticket.java @@ -8,6 +8,7 @@ public final class Ticket implements Comparable> { - private final int ticketLevel; public final T key; public final T getObjectReason() { return this.key; } // Paper - OBFHELPER private long createdTick; public final long getCreationTick() { return this.createdTick; } // Paper - OBFHELPER + public long delayUnloadBy; // Paper + public int priority = 0; // Paper protected Ticket(TicketType type, int level, T argument) { this.type = type; -@@ -56,6 +57,7 @@ public final class Ticket implements Comparable> { +@@ -57,6 +58,7 @@ public final class Ticket implements Comparable> { return this.ticketLevel; } @@ -1235,78 +1102,66 @@ index c6b5f32153b63ac92df9c4b31b8de168481f79f2..c0bfe136ccb9ad4fc0f8ccdd70325420 this.createdTick = tickCreated; } diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 583587457790df826a8a3239a4bd1d0f1dcab1da..2444f6f676db543509b14e8c882491dc3f41b264 100644 +index 8770fe0db46b01e8b608637df4f1a669a3f4cdde..3c1698ba0d3bc412ab957777d9b5211dbc555208 100644 --- a/src/main/java/net/minecraft/server/level/TicketType.java +++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -28,6 +28,8 @@ public class TicketType { - public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit +@@ -9,6 +9,8 @@ import net.minecraft.world.level.ChunkPos; + public class TicketType { public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper + public static final TicketType PRIORITY = create("priority", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper + public static final TicketType URGENT = create("urgent", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper - public static TicketType create(String name, Comparator comparator) { - return new TicketType<>(name, comparator, 0L); + private final String name; + private final Comparator comparator; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 3f416479e23c60ec5b4b779cce9ab62c74865ac8..0625bc7ffd07b66b27176fe62ae3061aa7c67df2 100644 +index 39777c2b1bbb12ce3e5be3724235ea0a8072cef8..2b8a9d16add3ac81ede029a909a40feaa07c51d3 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1528,6 +1528,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1566,6 +1566,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.awaitingTeleportTime = this.tickCount; this.player.absMoveTo(d0, d1, d2, f, f1); + this.player.forceCheckHighPriority(); // Paper - this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); + this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport, flag)); } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8e00747c1a717836d12a43aa48d667bf801167b0..168895dab31a0d5356eb96f2642399a1c99fccab 100644 +index 7eb3088d47ff78198e01a3a12b0ce6abe9d6ca6b..9c13479d2a508728c10803dee719ed7ad097e019 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -271,8 +271,8 @@ public abstract class PlayerList { - final ChunkPos pos = new ChunkPos(chunkX, chunkZ); - ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; - playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.toLong()); +@@ -272,8 +272,8 @@ public abstract class PlayerList { + net.minecraft.server.level.ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; + net.minecraft.server.level.DistanceManager distanceManager = playerChunkMap.distanceManager; + distanceManager.addTicketAtLevel(net.minecraft.server.level.TicketType.LOGIN, pos, 31, pos.toLong()); - worldserver1.getChunkSource().runDistanceManagerUpdates(); - worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { + worldserver1.getChunkSource().markAreaHighPriority(pos, 28, 3); + worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, false).thenApply(chunk -> { - ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); + net.minecraft.server.level.ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); if (updatingChunk != null) { return updatingChunk.getEntityTickingFuture(); -@@ -692,6 +692,7 @@ public abstract class PlayerList { +@@ -686,6 +686,7 @@ public abstract class PlayerList { SocketAddress socketaddress = loginlistener.connection.getRemoteAddress(); - ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameprofile, new ServerPlayerGameMode(this.server.getLevel(Level.OVERWORLD))); + ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameprofile); + entity.isRealPlayer = true; // Paper Player player = entity.getBukkitEntity(); PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.connection.getRawAddress()).getAddress()); -@@ -898,6 +899,7 @@ public abstract class PlayerList { +@@ -874,6 +875,7 @@ public abstract class PlayerList { // CraftBukkit end - worldserver1.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, new ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper + worldserver1.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper + entityplayer1.forceCheckHighPriority(); // Player - while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < 256.0D) { + while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); } -diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java -index 7ccf830146c252cff8e22553d293e02d4b53dad8..4a5f318adf5bc2ca1c3fab5d173a99cddd77ab85 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkPos.java -+++ b/src/main/java/net/minecraft/world/level/ChunkPos.java -@@ -104,6 +104,7 @@ public class ChunkPos { - return "[" + this.x + ", " + this.z + "]"; - } - -+ public final BlockPos asPosition() { return getWorldPosition(); } // Paper - OBFHELPER - public BlockPos getWorldPosition() { - return new BlockPos(this.getMinBlockX(), 0, this.getMinBlockZ()); - } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 4fc44390f432ef13c9952aa22bbb29bc8bf47975..7261e22a71d219efe0949a08c5d3f10747759469 100644 +index f72471ac82907a0d5112598b3289689495285944..29b2f5d3e6fd4859fbe94ad1cd5c355be7f9d4f3 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2523,6 +2523,10 @@ public class CraftWorld implements World { +@@ -2558,6 +2558,10 @@ public class CraftWorld implements World { return future; } @@ -1316,39 +1171,22 @@ index 4fc44390f432ef13c9952aa22bbb29bc8bf47975..7261e22a71d219efe0949a08c5d3f107 + } return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + if (chunk != null) addTicket(x, z); // Paper diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index eb366396820c9b6731469df4198e0884a431a77c..610eabd2e93f9efccee810c3b5a314bc3cc649d8 100644 +index 0a6d6ea67eaf8b2a59ec45fb3ffb85096f509997..e4386cf8bc6170f0c144560905ab285e44ebd5bb 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -60,6 +60,7 @@ import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.network.ServerGamePacketListenerImpl; - import net.minecraft.server.players.UserWhiteListEntry; -+import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.ExperienceOrb; - import net.minecraft.world.entity.LivingEntity; -@@ -69,6 +70,7 @@ import net.minecraft.world.entity.ai.attributes.Attributes; - import net.minecraft.world.inventory.AbstractContainerMenu; - import net.minecraft.world.item.enchantment.EnchantmentHelper; - import net.minecraft.world.item.enchantment.Enchantments; -+import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.GameType; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.entity.SignBlockEntity; -@@ -848,6 +850,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -885,6 +885,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { throw new UnsupportedOperationException("Cannot set rotation of players. Consider teleporting instead."); } + // Paper start + @Override + public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull PlayerTeleportEvent.TeleportCause cause) { -+ ((CraftWorld)loc.getWorld()).getHandle().getChunkSource().markAreaHighPriority(new ChunkPos(Mth.floor(loc.getX()) >> 4, Mth.floor(loc.getZ()) >> 4), 28, 3); // Paper - load area high priority ++ ((CraftWorld)loc.getWorld()).getHandle().getChunkSource().markAreaHighPriority(new net.minecraft.world.level.ChunkPos(net.minecraft.util.Mth.floor(loc.getX()) >> 4, net.minecraft.util.Mth.floor(loc.getZ()) >> 4), 28, 3); // Paper - load area high priority + return super.teleportAsync(loc, cause); + } + // Paper end -+ @Override public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) { Preconditions.checkArgument(location != null, "location"); From 38e4dc305075a44ba7accbcf233127273df9e604 Mon Sep 17 00:00:00 2001 From: Omer Uddin Date: Mon, 14 Jun 2021 22:54:17 -0400 Subject: [PATCH 128/226] Organize removed patches (#5836) --- .../1.17/0087-Remove-unused-World-Tile-Entity-List.patch | 1 + ...Delay-unsafe-actions-until-after-entity-ticking-is-d.patch | 2 +- .../0025-Optimize-TileEntity-Ticking.patch | 0 ...Send-absolute-position-the-first-time-an-entity-is-s.patch | 0 ...53-Change-implementation-of-tile-entity-removal-list.patch | 0 .../0088-Don-t-tick-Skulls-unused-code.patch | 0 ...0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch | 0 .../0107-Fix-Double-World-Add-issues.patch | 2 ++ .../0114-Chunk-registration-fixes.patch | 0 .../0120-Cache-user-authenticator-threads.patch | 3 +++ .../0182-Avoid-NPE-in-PathfinderGoalTempt.patch | 1 + .../0185-Fix-Dragon-Server-Crashes.patch | 0 .../0238-Don-t-change-the-Entity-Random-seed-for-squids.patch | 0 .../0239-Re-add-vanilla-entity-warnings-for-duplicates.patch | 0 ...Mark-chunk-dirty-anytime-entities-change-to-guarante.patch | 0 .../0251-Add-some-Debug-to-Chunk-Entity-slices.patch | 0 .../0253-Prevent-Saving-Bad-entities-to-chunks.patch | 0 .../0255-Ignore-Dead-Entities-in-entityList-iteration.patch | 0 .../0327-Fix-sign-edit-memory-leak.patch | 0 ...MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch | 2 ++ .../0359-Catch-exceptions-from-dispenser-entity-spawns.patch | 2 +- .../0380-Performance-improvement-for-Chunk.getEntities.patch | 4 +++- ...421-Fix-unregistering-entities-from-unloading-chunks.patch | 2 ++ ...490-Don-t-mark-null-chunk-sections-for-block-updates.patch | 1 + .../0501-Fix-enderdragon-exp-dupe.patch | 2 ++ .../0543-Remove-armour-stand-double-add-to-world.patch | 2 ++ ...Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch | 1 + .../1.17/{ => No longer needed}/0549-Fix-MC-197271.patch | 2 ++ .../0550-MC-197883-Bandaid-decode-issue.patch | 2 ++ .../0551-Add-warning-for-servers-not-running-on-Java-16.patch | 0 ...MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch | 2 +- 31 files changed, 27 insertions(+), 4 deletions(-) rename patches/removed/1.17/{ => No longer needed}/0025-Optimize-TileEntity-Ticking.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0053-Change-implementation-of-tile-entity-removal-list.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0088-Don-t-tick-Skulls-unused-code.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0107-Fix-Double-World-Add-issues.patch (97%) rename patches/removed/1.17/{ => No longer needed}/0114-Chunk-registration-fixes.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0120-Cache-user-authenticator-threads.patch (99%) rename patches/removed/1.17/{ => No longer needed}/0182-Avoid-NPE-in-PathfinderGoalTempt.patch (97%) rename patches/removed/1.17/{ => No longer needed}/0185-Fix-Dragon-Server-Crashes.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0251-Add-some-Debug-to-Chunk-Entity-slices.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0253-Prevent-Saving-Bad-entities-to-chunks.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0255-Ignore-Dead-Entities-in-entityList-iteration.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0327-Fix-sign-edit-memory-leak.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0327-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch (95%) rename patches/removed/1.17/{ => No longer needed}/0380-Performance-improvement-for-Chunk.getEntities.patch (92%) rename patches/removed/1.17/{ => No longer needed}/0421-Fix-unregistering-entities-from-unloading-chunks.patch (97%) rename patches/removed/1.17/{ => No longer needed}/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch (94%) rename patches/removed/1.17/{ => No longer needed}/0501-Fix-enderdragon-exp-dupe.patch (95%) rename patches/removed/1.17/{ => No longer needed}/0543-Remove-armour-stand-double-add-to-world.patch (98%) rename patches/removed/1.17/{ => No longer needed}/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch (96%) rename patches/removed/1.17/{ => No longer needed}/0549-Fix-MC-197271.patch (98%) rename patches/removed/1.17/{ => No longer needed}/0550-MC-197883-Bandaid-decode-issue.patch (96%) rename patches/removed/1.17/{ => No longer needed}/0551-Add-warning-for-servers-not-running-on-Java-16.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch (92%) diff --git a/patches/removed/1.17/0087-Remove-unused-World-Tile-Entity-List.patch b/patches/removed/1.17/0087-Remove-unused-World-Tile-Entity-List.patch index 46f6aa73e4..69e6d9076a 100644 --- a/patches/removed/1.17/0087-Remove-unused-World-Tile-Entity-List.patch +++ b/patches/removed/1.17/0087-Remove-unused-World-Tile-Entity-List.patch @@ -6,6 +6,7 @@ Subject: [PATCH] Remove unused World Tile Entity List Massive hit to performance and it is completely unnecessary. Removed during 1.17 update - no longer logically applies +not true? blockEntityTickers and pendingBlockEntityTickers have similar logic applied to them diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index f7eddb39985072afeb79ec0cbfc084d7e84638e6..bb99d9fe5e274318d8480a6de2c45b0a57351f77 100644 diff --git a/patches/removed/1.17/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch b/patches/removed/1.17/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch index 2c856fd185..4dfb0ddf1d 100644 --- a/patches/removed/1.17/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch +++ b/patches/removed/1.17/0436-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Delay unsafe actions until after entity ticking is done This will help prevent many cases of unregistering entities during entity ticking -1.17: Not used anywhere in 1.16.5 server, and no more tickingEntities bool on ServerLevel +1.17: Not used anywhere in 1.16.5 server, and no more tickingEntities bool on ServerLevel (moved to Level?) diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 4e75cc5e52a5295e32ccadb371702a405bb518bb..b9978d296b83e73d3395b8254c0e8ccd9b36d0fa 100644 diff --git a/patches/removed/1.17/0025-Optimize-TileEntity-Ticking.patch b/patches/removed/1.17/No longer needed/0025-Optimize-TileEntity-Ticking.patch similarity index 100% rename from patches/removed/1.17/0025-Optimize-TileEntity-Ticking.patch rename to patches/removed/1.17/No longer needed/0025-Optimize-TileEntity-Ticking.patch diff --git a/patches/removed/1.17/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch b/patches/removed/1.17/No longer needed/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch similarity index 100% rename from patches/removed/1.17/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch rename to patches/removed/1.17/No longer needed/0040-Send-absolute-position-the-first-time-an-entity-is-s.patch diff --git a/patches/removed/1.17/0053-Change-implementation-of-tile-entity-removal-list.patch b/patches/removed/1.17/No longer needed/0053-Change-implementation-of-tile-entity-removal-list.patch similarity index 100% rename from patches/removed/1.17/0053-Change-implementation-of-tile-entity-removal-list.patch rename to patches/removed/1.17/No longer needed/0053-Change-implementation-of-tile-entity-removal-list.patch diff --git a/patches/removed/1.17/0088-Don-t-tick-Skulls-unused-code.patch b/patches/removed/1.17/No longer needed/0088-Don-t-tick-Skulls-unused-code.patch similarity index 100% rename from patches/removed/1.17/0088-Don-t-tick-Skulls-unused-code.patch rename to patches/removed/1.17/No longer needed/0088-Don-t-tick-Skulls-unused-code.patch diff --git a/patches/removed/1.17/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch b/patches/removed/1.17/No longer needed/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch similarity index 100% rename from patches/removed/1.17/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch rename to patches/removed/1.17/No longer needed/0092-Prevent-Fire-from-loading-chunks-wrongly-spread.patch diff --git a/patches/removed/1.17/0107-Fix-Double-World-Add-issues.patch b/patches/removed/1.17/No longer needed/0107-Fix-Double-World-Add-issues.patch similarity index 97% rename from patches/removed/1.17/0107-Fix-Double-World-Add-issues.patch rename to patches/removed/1.17/No longer needed/0107-Fix-Double-World-Add-issues.patch index 707d235e76..aa8370e2b0 100644 --- a/patches/removed/1.17/0107-Fix-Double-World-Add-issues.patch +++ b/patches/removed/1.17/No longer needed/0107-Fix-Double-World-Add-issues.patch @@ -10,6 +10,8 @@ Also add debug if something else tries to, and abort before world gets bad state In 1.17 the entire entity state manager was rewritten. no longer applies, needs further information on new state manager +similar check added by mojang + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 0a613f94d1c796267636e1a343aeee65a49ffed5..335928d60dbfc07644ffeab366900c5e77e99d56 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/removed/1.17/0114-Chunk-registration-fixes.patch b/patches/removed/1.17/No longer needed/0114-Chunk-registration-fixes.patch similarity index 100% rename from patches/removed/1.17/0114-Chunk-registration-fixes.patch rename to patches/removed/1.17/No longer needed/0114-Chunk-registration-fixes.patch diff --git a/patches/removed/1.17/0120-Cache-user-authenticator-threads.patch b/patches/removed/1.17/No longer needed/0120-Cache-user-authenticator-threads.patch similarity index 99% rename from patches/removed/1.17/0120-Cache-user-authenticator-threads.patch rename to patches/removed/1.17/No longer needed/0120-Cache-user-authenticator-threads.patch index fbc0443e78..8b7ea21b92 100644 --- a/patches/removed/1.17/0120-Cache-user-authenticator-threads.patch +++ b/patches/removed/1.17/No longer needed/0120-Cache-user-authenticator-threads.patch @@ -6,6 +6,9 @@ Subject: [PATCH] Cache user authenticator threads TODO it looks like someone royally messed this one up, patch name doesn't remotely describe contents. Good thing this patch is no longer relevant at all + +no remove queue anymore + diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java index 0597c0c3e881dd43cf91bd3088ed30dfecfe8098..175bf535066afc42de8a3f0d11c46af66f3e3e52 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java diff --git a/patches/removed/1.17/0182-Avoid-NPE-in-PathfinderGoalTempt.patch b/patches/removed/1.17/No longer needed/0182-Avoid-NPE-in-PathfinderGoalTempt.patch similarity index 97% rename from patches/removed/1.17/0182-Avoid-NPE-in-PathfinderGoalTempt.patch rename to patches/removed/1.17/No longer needed/0182-Avoid-NPE-in-PathfinderGoalTempt.patch index 15a2d9eab1..54268b11fc 100644 --- a/patches/removed/1.17/0182-Avoid-NPE-in-PathfinderGoalTempt.patch +++ b/patches/removed/1.17/No longer needed/0182-Avoid-NPE-in-PathfinderGoalTempt.patch @@ -3,6 +3,7 @@ From: Aikar Date: Wed, 29 Nov 2017 22:18:54 -0500 Subject: [PATCH] Avoid NPE in PathfinderGoalTempt Not needed anymore +similar check added by Mojang diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java index 186025458e923d153e9e47c2be147a9bb53db517..11ca6a752bac4ba4bc683bef844d204b739fab63 100644 diff --git a/patches/removed/1.17/0185-Fix-Dragon-Server-Crashes.patch b/patches/removed/1.17/No longer needed/0185-Fix-Dragon-Server-Crashes.patch similarity index 100% rename from patches/removed/1.17/0185-Fix-Dragon-Server-Crashes.patch rename to patches/removed/1.17/No longer needed/0185-Fix-Dragon-Server-Crashes.patch diff --git a/patches/removed/1.17/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch b/patches/removed/1.17/No longer needed/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch similarity index 100% rename from patches/removed/1.17/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch rename to patches/removed/1.17/No longer needed/0238-Don-t-change-the-Entity-Random-seed-for-squids.patch diff --git a/patches/removed/1.17/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch b/patches/removed/1.17/No longer needed/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch similarity index 100% rename from patches/removed/1.17/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch rename to patches/removed/1.17/No longer needed/0239-Re-add-vanilla-entity-warnings-for-duplicates.patch diff --git a/patches/removed/1.17/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch b/patches/removed/1.17/No longer needed/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch similarity index 100% rename from patches/removed/1.17/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch rename to patches/removed/1.17/No longer needed/0250-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch diff --git a/patches/removed/1.17/0251-Add-some-Debug-to-Chunk-Entity-slices.patch b/patches/removed/1.17/No longer needed/0251-Add-some-Debug-to-Chunk-Entity-slices.patch similarity index 100% rename from patches/removed/1.17/0251-Add-some-Debug-to-Chunk-Entity-slices.patch rename to patches/removed/1.17/No longer needed/0251-Add-some-Debug-to-Chunk-Entity-slices.patch diff --git a/patches/removed/1.17/0253-Prevent-Saving-Bad-entities-to-chunks.patch b/patches/removed/1.17/No longer needed/0253-Prevent-Saving-Bad-entities-to-chunks.patch similarity index 100% rename from patches/removed/1.17/0253-Prevent-Saving-Bad-entities-to-chunks.patch rename to patches/removed/1.17/No longer needed/0253-Prevent-Saving-Bad-entities-to-chunks.patch diff --git a/patches/removed/1.17/0255-Ignore-Dead-Entities-in-entityList-iteration.patch b/patches/removed/1.17/No longer needed/0255-Ignore-Dead-Entities-in-entityList-iteration.patch similarity index 100% rename from patches/removed/1.17/0255-Ignore-Dead-Entities-in-entityList-iteration.patch rename to patches/removed/1.17/No longer needed/0255-Ignore-Dead-Entities-in-entityList-iteration.patch diff --git a/patches/removed/1.17/0327-Fix-sign-edit-memory-leak.patch b/patches/removed/1.17/No longer needed/0327-Fix-sign-edit-memory-leak.patch similarity index 100% rename from patches/removed/1.17/0327-Fix-sign-edit-memory-leak.patch rename to patches/removed/1.17/No longer needed/0327-Fix-sign-edit-memory-leak.patch diff --git a/patches/removed/1.17/0327-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch b/patches/removed/1.17/No longer needed/0327-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch similarity index 95% rename from patches/removed/1.17/0327-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch rename to patches/removed/1.17/No longer needed/0327-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch index 2d90ba443c..3781130845 100644 --- a/patches/removed/1.17/0327-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch +++ b/patches/removed/1.17/No longer needed/0327-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch @@ -6,6 +6,8 @@ Subject: [PATCH] MC-114618 - Fix EntityAreaEffectCloud from going negative 1.17 update note: Likely fixed in 1.17 +fixed https://bugs.mojang.com/browse/MC-114618 + diff --git a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java index 4733f74ff028c03a60b73280caf9e4d1e2f0ca30..882c216b508a8623c2393b668cff6d702fe738b9 100644 --- a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java diff --git a/patches/removed/1.17/No longer needed/0359-Catch-exceptions-from-dispenser-entity-spawns.patch b/patches/removed/1.17/No longer needed/0359-Catch-exceptions-from-dispenser-entity-spawns.patch index 0a15b5e432..a560a1fd92 100644 --- a/patches/removed/1.17/No longer needed/0359-Catch-exceptions-from-dispenser-entity-spawns.patch +++ b/patches/removed/1.17/No longer needed/0359-Catch-exceptions-from-dispenser-entity-spawns.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Mon, 10 Jun 2019 09:36:40 +0100 Subject: [PATCH] Catch exceptions from dispenser entity spawns - +mojang(?) added similar warning diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java index dccf689d17bb5a77abf97779663413d01e840c23..67a894a185a3d4a53b3c7f90174b2604dff18257 100644 diff --git a/patches/removed/1.17/0380-Performance-improvement-for-Chunk.getEntities.patch b/patches/removed/1.17/No longer needed/0380-Performance-improvement-for-Chunk.getEntities.patch similarity index 92% rename from patches/removed/1.17/0380-Performance-improvement-for-Chunk.getEntities.patch rename to patches/removed/1.17/No longer needed/0380-Performance-improvement-for-Chunk.getEntities.patch index 508f96a2bd..45306b4541 100644 --- a/patches/removed/1.17/0380-Performance-improvement-for-Chunk.getEntities.patch +++ b/patches/removed/1.17/No longer needed/0380-Performance-improvement-for-Chunk.getEntities.patch @@ -9,7 +9,9 @@ extra array with List.toArray() with is a costly and unneccessary operation. This patch will reduce the load of plugins which for example implement custom moblimits and depend on Chunk.getEntities(). -1.17: needs to be reworked, entities not in chunk anymore? +1.17: needs to be reworked, entities not in chunk anymore + +no longer needed as no toArray is called during getEntities due to rewrite of entity system diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java index 74bad15034d9d55fb70931f38868f812160c6305..0f45f4b2486e910d11fd94b260bcd68e49eae31e 100644 diff --git a/patches/removed/1.17/0421-Fix-unregistering-entities-from-unloading-chunks.patch b/patches/removed/1.17/No longer needed/0421-Fix-unregistering-entities-from-unloading-chunks.patch similarity index 97% rename from patches/removed/1.17/0421-Fix-unregistering-entities-from-unloading-chunks.patch rename to patches/removed/1.17/No longer needed/0421-Fix-unregistering-entities-from-unloading-chunks.patch index 8d30f4e4f1..0f7af54c0b 100644 --- a/patches/removed/1.17/0421-Fix-unregistering-entities-from-unloading-chunks.patch +++ b/patches/removed/1.17/No longer needed/0421-Fix-unregistering-entities-from-unloading-chunks.patch @@ -16,6 +16,8 @@ the Dupe UUID patch, then this was the likely source of the "Ghost entities" 1.17: Probably not needed? +no longer applies as entities not stored in chunks + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 9898d5c8fab63c576831bd416ccf1854ed077b0d..c5dc41a3cf499038bd33451a189913cd3978b230 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/removed/1.17/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch b/patches/removed/1.17/No longer needed/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch similarity index 94% rename from patches/removed/1.17/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch rename to patches/removed/1.17/No longer needed/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch index 0d7df8df12..167b17c93f 100644 --- a/patches/removed/1.17/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch +++ b/patches/removed/1.17/No longer needed/0490-Don-t-mark-null-chunk-sections-for-block-updates.patch @@ -3,6 +3,7 @@ From: Mariell Hoversholm Date: Fri, 14 Aug 2020 23:41:19 +0200 Subject: [PATCH] Don't mark null chunk sections for block updates +no longer needed as the accessor to get chunksection handles null chunk sections diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java index 1f67c9c5f7161ea687983e7ae0ec7d259da9acd3..32bcc55ce15d832e2182d89acecd715947b1667d 100644 diff --git a/patches/removed/1.17/0501-Fix-enderdragon-exp-dupe.patch b/patches/removed/1.17/No longer needed/0501-Fix-enderdragon-exp-dupe.patch similarity index 95% rename from patches/removed/1.17/0501-Fix-enderdragon-exp-dupe.patch rename to patches/removed/1.17/No longer needed/0501-Fix-enderdragon-exp-dupe.patch index ccc32f2cc8..33515365ec 100644 --- a/patches/removed/1.17/0501-Fix-enderdragon-exp-dupe.patch +++ b/patches/removed/1.17/No longer needed/0501-Fix-enderdragon-exp-dupe.patch @@ -8,6 +8,8 @@ dragon 1.17: Mojang fixed in 1.17(maybe before, idk) +resolved by Mojang https://bugs.mojang.com/browse/MCPE-64818 + diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java index ec9436005a3a6fdfb4783d1092bb361224eb6414..b224a630f8adb1fa357c838e6b32c784aed0b15b 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java diff --git a/patches/removed/1.17/0543-Remove-armour-stand-double-add-to-world.patch b/patches/removed/1.17/No longer needed/0543-Remove-armour-stand-double-add-to-world.patch similarity index 98% rename from patches/removed/1.17/0543-Remove-armour-stand-double-add-to-world.patch rename to patches/removed/1.17/No longer needed/0543-Remove-armour-stand-double-add-to-world.patch index 12731c058d..1516cc83cb 100644 --- a/patches/removed/1.17/0543-Remove-armour-stand-double-add-to-world.patch +++ b/patches/removed/1.17/No longer needed/0543-Remove-armour-stand-double-add-to-world.patch @@ -4,6 +4,8 @@ Date: Fri, 14 Aug 2020 23:59:26 +0200 Subject: [PATCH] Remove armour stand double add to world 1.17 Update: YEET (?) +Applied by Mojang + diff --git a/src/main/java/net/minecraft/world/item/ArmorStandItem.java b/src/main/java/net/minecraft/world/item/ArmorStandItem.java index a2dfcaac8a2a4a69e703de43be76d4fe369fd647..bed063497bb593683ea384605ae1a71a68f4fc1b 100644 --- a/src/main/java/net/minecraft/world/item/ArmorStandItem.java diff --git a/patches/removed/1.17/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch b/patches/removed/1.17/No longer needed/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch similarity index 96% rename from patches/removed/1.17/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch rename to patches/removed/1.17/No longer needed/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch index aed77697a6..0e1b50e0cf 100644 --- a/patches/removed/1.17/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch +++ b/patches/removed/1.17/No longer needed/0548-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch @@ -5,6 +5,7 @@ Subject: [PATCH] Fix MC-99259 Wither Boss Bar doesn't update until 1.17 Update: This issue is marked as fixed on 1.17 - yeet! invulnerability period is over +Resolved https://bugs.mojang.com/browse/MC-99259 diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java index edd231568b75330d0cffbecb03a7e9dbc55d5f94..1f330d852eb9b3a36570542e10a88ae065798714 100644 diff --git a/patches/removed/1.17/0549-Fix-MC-197271.patch b/patches/removed/1.17/No longer needed/0549-Fix-MC-197271.patch similarity index 98% rename from patches/removed/1.17/0549-Fix-MC-197271.patch rename to patches/removed/1.17/No longer needed/0549-Fix-MC-197271.patch index 65a6ccce8d..c82b3a6ca3 100644 --- a/patches/removed/1.17/0549-Fix-MC-197271.patch +++ b/patches/removed/1.17/No longer needed/0549-Fix-MC-197271.patch @@ -5,6 +5,8 @@ Subject: [PATCH] Fix MC-197271 Update 1.17: Fixed in openj9-0.23.0-m2 release This patch only fixes an issue for servers running OpenJ9. +resolved https://bugs.mojang.com/browse/MC-197271 + diff --git a/src/main/java/net/minecraft/data/BuiltinRegistries.java b/src/main/java/net/minecraft/data/BuiltinRegistries.java index d64cebb4431664762a14670c7d9d782dd7894ed5..0c403ea85f7ea20f2f978e06313f8675abf204b6 100644 --- a/src/main/java/net/minecraft/data/BuiltinRegistries.java diff --git a/patches/removed/1.17/0550-MC-197883-Bandaid-decode-issue.patch b/patches/removed/1.17/No longer needed/0550-MC-197883-Bandaid-decode-issue.patch similarity index 96% rename from patches/removed/1.17/0550-MC-197883-Bandaid-decode-issue.patch rename to patches/removed/1.17/No longer needed/0550-MC-197883-Bandaid-decode-issue.patch index b05b52883d..be32d8a82f 100644 --- a/patches/removed/1.17/0550-MC-197883-Bandaid-decode-issue.patch +++ b/patches/removed/1.17/No longer needed/0550-MC-197883-Bandaid-decode-issue.patch @@ -8,6 +8,8 @@ use one. This will retry as name if type is asked for and not found. +resolved https://bugs.mojang.com/browse/MC-197883 + diff --git a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java index de7d1e5e0319c65775d932144c268c2d55bb7dc7..bd6a0e1b5454e880a4f2a16be7dc8da64b73e11d 100644 --- a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java diff --git a/patches/removed/1.17/0551-Add-warning-for-servers-not-running-on-Java-16.patch b/patches/removed/1.17/No longer needed/0551-Add-warning-for-servers-not-running-on-Java-16.patch similarity index 100% rename from patches/removed/1.17/0551-Add-warning-for-servers-not-running-on-Java-16.patch rename to patches/removed/1.17/No longer needed/0551-Add-warning-for-servers-not-running-on-Java-16.patch diff --git a/patches/removed/1.17/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch b/patches/removed/1.17/No longer needed/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch similarity index 92% rename from patches/removed/1.17/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch rename to patches/removed/1.17/No longer needed/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch index ed4a24b0df..d54558fb30 100644 --- a/patches/removed/1.17/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch +++ b/patches/removed/1.17/No longer needed/0579-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch @@ -3,7 +3,7 @@ From: chickeneer Date: Wed, 18 Mar 2020 00:07:46 -0500 Subject: [PATCH] MC-147729: Drop items that are extra from a crafting recipe -1.17: Issue seems to be fixed (source: Mojira) +1.17: Issue seems to be fixed (source: Mojira) https://bugs.mojang.com/browse/MC-147729 diff --git a/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java b/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java index a18aa176850bef45afcaf5742e9afbfa39281e22..c6ba6aabf94c26cccbd14689ea32373c17bbccc4 100644 From d3424f4a8a860ff1e1793af84a861bd5b956ad53 Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Mon, 14 Jun 2021 19:59:31 -0700 Subject: [PATCH 129/226] tons of patches (#5835) --- build-data/paper.at | 12 ++ ...w-adding-items-to-BlockDropItemEvent.patch | 0 ...ainThreadExecutor-to-BukkitScheduler.patch | 0 ...-entity-allow-attribute-registration.patch | 0 .../0273-Add-missing-effects.patch | 0 .../0274-Expose-Tracked-Players.patch | 4 +- ...Cache-the-result-of-Material-isBlock.patch | 8 +- .../0276-Add-worldborder-events.patch | 0 .../0277-added-PlayerNameEntityEvent.patch | 0 .../0278-Add-recipe-to-cook-events.patch | 0 .../0279-Add-Block-isValidTool.patch | 4 +- .../0280-Implement-Keyed-on-World.patch | 8 +- ...ventory-getContents-null-annotations.patch | 0 .../0282-Item-Rarity-API.patch | 4 +- .../0283-Expose-protocol-version.patch | 0 ...nt-suggestion-tooltips-in-AsyncTabC.patch} | 0 ...add-isDeeplySleeping-to-HumanEntity.patch} | 2 +- ...add-consumeFuel-to-FurnaceBurnEvent.patch} | 0 ...-set-drop-chance-to-EntityEquipment.patch} | 0 .../0288-Added-PlayerDeepSleepEvent.patch} | 0 .../0289-More-World-API.patch} | 2 +- .../0290-Added-PlayerBedFailEnterEvent.patch} | 0 ...acon-activation-deactivation-events.patch} | 0 .../0292-PlayerMoveEvent-Improvements.patch} | 0 ...-RespawnFlags-to-PlayerRespawnEvent.patch} | 0 .../0294-Add-more-WanderingTrader-API.patch} | 0 ...Add-EntityBlockStorage-clearEntities.patch | 0 ...essage-to-PlayerAdvancementDoneEvent.patch | 0 ...-address-to-AsyncPlayerPreLoginEvent.patch | 0 .../0298-Inventory-close.patch | 0 ...n-in-sunlight-API-for-Phantoms-and-S.patch | 4 +- .../0300-Add-basic-Datapack-API.patch | 4 +- ...ditions-to-PlayerGameModeChangeEvent.patch | 0 .../0302-ItemStack-repair-check-API.patch | 2 +- .../0303-More-Enchantment-API.patch | 0 ...-option-to-load-extra-plugin-jars-no.patch | 2 +- ...-missing-hard-depends-not-just-first.patch | 2 +- .../0306-Add-Mob-lookAt-API.patch | 0 .../0307-ItemStack-editMeta.patch | 0 .../0308-Add-EntityInsideBlockEvent.patch | 0 ...309-Attributes-API-for-item-defaults.patch | 4 +- ...cause-to-Weather-ThunderChangeEvents.patch | 0 .../0311-More-Lidded-Block-API.patch | 0 ...0312-Add-PufferFishStateChangeEvent.patch} | 0 .../1.17}/0676-Clear-SyncLoadInfo.patch | 2 + ...-to-remove-correct-TE-during-TE-tick.patch | 2 + ...atus-dataconverter-for-pre-1.13-chun.patch | 2 + ...crease-structure-block-data-length-t.patch | 1 + ...unnecessary-copies-of-passenger-list.patch | 1 + ...don-t-throw-when-loading-invalid-TEs.patch | 1 + .../0677-Expose-Tracked-Players.patch | 53 ------ ...78-Remove-streams-from-SensorNearest.patch | 120 ------------ .../0691-Implement-Keyed-on-World.patch | 110 ----------- .../0693-Item-Rarity-API.patch | 52 ------ ...ignore-result-of-PlayerEditBookEvent.patch | 19 -- ...-block-falling-causing-client-desync.patch | 59 ------ ...ating-give-items-on-item-drop-cancel.patch | 113 ------------ ...fix-PlayerItemHeldEvent-firing-twice.patch | 30 --- .../server-remapped/0716-More-World-API.patch | 146 --------------- ...essage-to-PlayerAdvancementDoneEvent.patch | 89 --------- .../0732-Add-basic-Datapack-API.patch | 174 ------------------ ...ditions-to-PlayerGameModeChangeEvent.patch | 138 -------------- .../0741-Add-Mob-lookAt-API.patch | 127 ------------- ...-Priority-Urgency-System-for-Chunks.patch} | 0 ...rom-classes-related-villager-gossip.patch} | 0 ...0471-Support-components-in-ItemMeta.patch} | 0 ...rgetLivingEntityEvent-for-1.16-mobs.patch} | 0 ...patch => 0473-Add-entity-liquid-API.patch} | 0 ...date-itemstack-legacy-name-and-lore.patch} | 0 ...wn-player-in-correct-world-on-login.patch} | 2 +- ...atch => 0476-Add-PrepareResultEvent.patch} | 0 ...low-delegation-to-vanilla-chunk-gen.patch} | 0 ...-for-portal-on-world-gen-entity-add.patch} | 0 ...e-NetworkManager-Exception-Handling.patch} | 0 ...ncement-data-player-iteration-to-be.patch} | 0 ...x-arrows-never-despawning-MC-125757.patch} | 0 ...Vanilla-Command-permission-checking.patch} | 0 ...ve-range-check-for-block-placing-up.patch} | 4 +- ...-5989.patch => 0484-Fix-SPIGOT-5989.patch} | 10 +- ...-Bukkit-world-container-is-not-used.patch} | 0 ...5885-Unable-to-disable-advancements.patch} | 0 ...taPlayer-leak-due-from-quitting-ear.patch} | 0 ...eLighting-call-to-World-spigot-stri.patch} | 4 +- ...ix-some-rails-connecting-improperly.patch} | 0 ...h => 0490-Incremental-player-saving.patch} | 6 +- ...Fix-MC-187716-Use-configured-height.patch} | 0 ...stake-in-CB-NBT-int-deserialization.patch} | 0 ...rver-load-chunks-from-newer-version.patch} | 0 ...support.patch => 0494-Brand-support.patch} | 12 +- ...patch => 0495-Add-setMaxPlayers-API.patch} | 4 +- ...PickupItemAnimation-to-LivingEntity.patch} | 0 ...h => 0497-Don-t-require-FACING-data.patch} | 0 ...eEvent-not-firing-for-all-use-cases.patch} | 2 +- ...PI.patch => 0499-Add-moon-phase-API.patch} | 2 +- ...headless-pistons-from-being-created.patch} | 0 ...ent.patch => 0501-Add-BellRingEvent.patch} | 0 ...dd-zombie-targets-turtle-egg-config.patch} | 0 ...patch => 0503-Buffer-joins-to-world.patch} | 0 ...=> 0504-Optimize-redstone-algorithm.patch} | 0 ...s-not-working-in-some-kick-messages.patch} | 0 ...reateEvent-needs-to-know-its-entity.patch} | 0 ...ch => 0507-Fix-CraftTeam-null-check.patch} | 0 ...I.patch => 0508-Add-more-Evoker-API.patch} | 0 ...translation-keys-for-blocks-entitie.patch} | 0 ...te-HoverEvent-from-ItemStack-Entity.patch} | 0 ...ch => 0511-Cache-block-data-strings.patch} | 0 ...rtation-and-cancel-velocity-if-tele.patch} | 4 +- ...l-open-container-api-to-HumanEntity.patch} | 0 ...aFixerUpper-Rewrite-Rules-on-demand.patch} | 0 ...-capture-to-capture-all-items-added.patch} | 0 ...ty-in-invalid-locations-SPIGOT-6086.patch} | 4 +- ...-Counter-to-allow-plugins-to-use-va.patch} | 0 ...track-plugin-scoreboards-by-default.patch} | 0 ...king.patch => 0519-Entity-isTicking.patch} | 0 ...non-whitelisted-player-when-white-l.patch} | 0 ...g-a-passenger-in-CreatureSpawnEvent.patch} | 0 ...eset-Ender-Crystals-on-Dragon-Spawn.patch} | 0 ...-large-move-vectors-crashing-server.patch} | 2 +- ...atch => 0524-Optimise-getType-calls.patch} | 0 ....patch => 0525-Villager-resetOffers.patch} | 0 ...nig-for-some-hot-IBlockData-methods.patch} | 0 ...ce-order-when-capturing-blockstates.patch} | 0 ...lockpos-allocation-from-pathfinding.patch} | 0 ...em-locations-dropped-from-campfires.patch} | 0 ...tch => 0530-Player-elytra-boost-API.patch} | 2 +- ...31-Fixed-TileEntityBell-memory-leak.patch} | 0 ...ing-up-when-item-stack-is-empty-in-.patch} | 0 ...Add-getOfflinePlayerIfCached-String.patch} | 0 ...ch => 0534-Add-ignore-discounts-API.patch} | 0 ...Toggle-for-removing-existing-dragon.patch} | 0 ...x-client-lag-on-advancement-loading.patch} | 0 ...> 0537-Item-no-age-no-player-pickup.patch} | 0 ...538-Beacon-API-custom-effect-ranges.patch} | 0 ...tch => 0539-Add-API-for-quit-reason.patch} | 8 +- ...h => 0540-Seed-based-feature-search.patch} | 0 ...ng-Trader-spawn-rate-config-options.patch} | 0 ...rove-performance-of-the-end-generat.patch} | 4 +- ...ch => 0543-Expose-world-spawn-angle.patch} | 6 +- ...patch => 0544-Add-Destroy-Speed-API.patch} | 0 ...-spawnParticle-x-y-z-precision-loss.patch} | 4 +- ...46-Add-LivingEntity-clearActiveItem.patch} | 0 ...=> 0547-Add-PlayerItemCooldownEvent.patch} | 0 ...PI.patch => 0548-More-lightning-API.patch} | 0 ...should-not-bypass-cramming-gamerule.patch} | 0 ...-missing-default-perms-for-commands.patch} | 0 ...h => 0551-Add-PlayerShearBlockEvent.patch} | 0 ...rbose-world-setting-to-false-by-def.patch} | 0 ...ng-zombie-villager-discount-exploit.patch} | 0 ....patch => 0554-Limit-recipe-packets.patch} | 4 +- ...-CraftSound-backwards-compatibility.patch} | 0 ... 0556-MC-4-Fix-item-position-desync.patch} | 0 ...557-Player-Chunk-Load-Unload-Events.patch} | 4 +- ...8-Optimize-Dynamic-get-Missing-Keys.patch} | 0 ...-Expose-LivingEntity-hurt-direction.patch} | 0 ...OBSTRUCTED-reason-to-BedEnterResult.patch} | 0 ...-invalid-ingredient-lists-in-Villag.patch} | 0 ...atch => 0562-added-PlayerTradeEvent.patch} | 0 ...ch => 0563-Implement-TargetHitEvent.patch} | 0 ...564-Additional-Block-Material-API-s.patch} | 0 ...tch => 0565-Fix-harming-potion-dupe.patch} | 0 ...get-Material-from-Boats-and-Minecar.patch} | 0 ....patch => 0567-Cache-burn-durations.patch} | 0 ...ob-spawner-spawn-egg-transformation.patch} | 0 ...ment-PlayerFlowerPotManipulateEvent.patch} | 0 ...event-not-being-called-in-adventure.patch} | 6 +- ...h => 0571-Zombie-API-breaking-doors.patch} | 0 ...572-Fix-nerfed-slime-when-splitting.patch} | 0 ...=> 0573-Add-EntityLoadCrossbowEvent.patch} | 0 ...ch => 0574-Guardian-beam-workaround.patch} | 0 ...0575-Added-WorldGameRuleChangeEvent.patch} | 2 +- ...-Added-ServerResourcesReloadedEvent.patch} | 0 ...d-settings-for-mobs-picking-up-loot.patch} | 0 ...mplemented-BlockFailedDispenseEvent.patch} | 0 ...-Added-PlayerLecternPageChangeEvent.patch} | 0 ...-Added-PlayerLoomPatternSelectEvent.patch} | 0 ...nfigurable-door-breaking-difficulty.patch} | 0 ...ty-commands-shall-not-be-dispatched.patch} | 0 ...I-to-expose-exact-interaction-point.patch} | 0 ...OIs.patch => 0584-Remove-stale-POIs.patch} | 0 ...h => 0585-Fix-villager-boat-exploit.patch} | 2 +- ...I.patch => 0586-Add-sendOpLevel-API.patch} | 6 +- ...ch => 0587-Add-StructureLocateEvent.patch} | 0 ...-for-requiring-a-player-participant.patch} | 0 ...leHitEvent-call-when-fireballs-dead.patch} | 0 ...nent-with-empty-text-instead-of-thr.patch} | 0 ...591-Make-schedule-command-per-world.patch} | 0 ...592-Configurable-max-leash-distance.patch} | 0 ...593-Implement-BlockPreDispenseEvent.patch} | 0 ...h => 0594-Added-Vanilla-Entity-Tags.patch} | 0 ...-API.patch => 0595-added-Wither-API.patch} | 0 ...ng-of-PlayerChangeBeaconEffectEvent.patch} | 0 ...-spam-when-removing-chests-in-water.patch} | 0 ...e-for-always-placing-the-dragon-egg.patch} | 0 ...-PlayerStonecutterRecipeSelectEvent.patch} | 0 ...eash-variable-to-EntityUnleashEvent.patch} | 0 ...e-map-update-when-spawning-disabled.patch} | 4 +- ...shield-blocking-on-dimension-change.patch} | 4 +- ...atch => 0603-add-DragonEggFormEvent.patch} | 0 ...Event.patch => 0604-EntityMoveEvent.patch} | 0 ...isable-pathfinding-updates-on-block.patch} | 13 +- .../0606-Inline-shift-direction-fields.patch} | 28 +-- ...-adding-items-to-BlockDropItemEvent.patch} | 4 +- ...inThreadExecutor-to-BukkitScheduler.patch} | 2 +- ...entity-allow-attribute-registration.patch} | 21 +-- ...ix-dead-slime-setSize-invincibility.patch} | 6 +- ...pes-should-return-an-immutable-list.patch} | 6 +- .../0612-misc-debugging-dumps.patch} | 50 ++--- ...port-for-hex-color-codes-in-console.patch} | 12 ++ .../server/0614-Expose-Tracked-Players.patch | 32 ++++ ...15-Remove-streams-from-SensorNearest.patch | 107 +++++++++++ ...ix-Wither-hostility-towards-players.patch} | 9 +- ...er-exception-on-empty-JsonList-file.patch} | 2 +- .../0618-Improve-ServerGUI.patch} | 43 ++--- ...ure-plate-EntityInteractEvent-for-i.patch} | 0 ...620-fix-converting-txt-to-json-file.patch} | 35 ++-- .../0621-Add-worldborder-events.patch} | 57 ++---- .../0622-added-PlayerNameEntityEvent.patch} | 17 +- ...grindstones-from-overstacking-items.patch} | 4 +- .../0624-Add-recipe-to-cook-events.patch} | 30 +-- .../0625-Add-Block-isValidTool.patch} | 4 +- ...using-signs-inside-spawn-protection.patch} | 23 +-- .../0627-Implement-Keyed-on-World.patch | 51 +++++ ...ternative-constructor-for-Rotations.patch} | 8 +- patches/server/0629-Item-Rarity-API.patch | 31 ++++ ...imer-for-Wandering-Traders-spawned-.patch} | 20 +- ...py-TESign-isEditable-from-snapshots.patch} | 4 +- ...d-item-when-player-has-disconnected.patch} | 18 +- ...elist-use-configurable-kick-message.patch} | 6 +- ...ignore-result-of-PlayerEditBookEvent.patch | 19 ++ ...-block-falling-causing-client-desync.patch | 31 ++++ .../0636-Expose-protocol-version.patch} | 4 +- ...nt-suggestion-tooltips-in-AsyncTabC.patch} | 14 +- ...ab-completions-for-brigadier-comman.patch} | 61 +----- ...temConsumeEvent-cancelling-properly.patch} | 4 +- .../0640-Add-bypass-host-check.patch} | 10 +- ...0641-Set-area-affect-cloud-rotation.patch} | 10 +- ...add-isDeeplySleeping-to-HumanEntity.patch} | 6 +- ...ating-give-items-on-item-drop-cancel.patch | 70 +++++++ ...add-consumeFuel-to-FurnaceBurnEvent.patch} | 18 +- ...-set-drop-chance-to-EntityEquipment.patch} | 6 +- ...ix-PigZombieAngerEvent-cancellation.patch} | 26 +-- ...-checkReach-check-for-Shulker-boxes.patch} | 4 +- ...fix-PlayerItemHeldEvent-firing-twice.patch | 18 ++ .../0649-Added-PlayerDeepSleepEvent.patch} | 4 +- patches/server/0650-More-World-API.patch | 86 +++++++++ .../0651-Added-PlayerBedFailEnterEvent.patch} | 29 +-- ...-to-convert-between-Component-and-B.patch} | 4 +- ...n-acting-as-a-bed-respawn-from-the-.patch} | 12 +- ...acon-activation-deactivation-events.patch} | 22 +-- ...-RespawnFlags-to-PlayerRespawnEvent.patch} | 17 +- ...dd-Channel-initialization-listeners.patch} | 6 +- ...mands-if-tab-completion-is-disabled.patch} | 4 +- .../0658-Add-more-WanderingTrader-API.patch} | 12 +- ...dd-EntityBlockStorage-clearEntities.patch} | 4 +- ...essage-to-PlayerAdvancementDoneEvent.patch | 32 ++++ ...address-to-AsyncPlayerPreLoginEvent.patch} | 14 +- .../0662-Inventory-close.patch} | 6 +- ...reateEvent-players-and-end-platform.patch} | 10 +- ...-in-sunlight-API-for-Phantoms-and-S.patch} | 52 +++--- .../0665-Fix-CraftPotionBrewer-cache.patch} | 18 +- .../server/0666-Add-basic-Datapack-API.patch | 125 +++++++++++++ ...ment-variable-to-disable-server-gui.patch} | 4 +- ...ditions-to-PlayerGameModeChangeEvent.patch | 150 +++++++++++++++ .../0669-ItemStack-repair-check-API.patch} | 18 +- .../0670-More-Enchantment-API.patch} | 88 ++------- ...option-to-load-extra-plugin-jars-no.patch} | 14 +- ...-and-optimise-world-force-upgrading.patch} | 70 +++---- patches/server/0673-Add-Mob-lookAt-API.patch | 64 +++++++ ...0674-Add-Unix-domain-socket-support.patch} | 26 +-- .../0675-Add-EntityInsideBlockEvent.patch} | 122 +++++++----- ...76-Attributes-API-for-item-defaults.patch} | 20 +- ...hantCustom-emit-PlayerPurchaseEvent.patch} | 15 +- ...ause-to-Weather-ThunderChangeEvents.patch} | 97 +++++----- .../0679-More-Lidded-Block-API.patch} | 56 ++---- ...80-Limit-item-frame-cursors-on-maps.patch} | 9 +- ...0681-Add-PufferFishStateChangeEvent.patch} | 4 +- 276 files changed, 1441 insertions(+), 2130 deletions(-) rename patches/{api-unmapped => api}/0270-Allow-adding-items-to-BlockDropItemEvent.patch (100%) rename patches/{api-unmapped => api}/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch (100%) rename patches/{api-unmapped => api}/0272-living-entity-allow-attribute-registration.patch (100%) rename patches/{api-unmapped => api}/0273-Add-missing-effects.patch (100%) rename patches/{api-unmapped => api}/0274-Expose-Tracked-Players.patch (86%) rename patches/{api-unmapped => api}/0275-Cache-the-result-of-Material-isBlock.patch (79%) rename patches/{api-unmapped => api}/0276-Add-worldborder-events.patch (100%) rename patches/{api-unmapped => api}/0277-added-PlayerNameEntityEvent.patch (100%) rename patches/{api-unmapped => api}/0278-Add-recipe-to-cook-events.patch (100%) rename patches/{api-unmapped => api}/0279-Add-Block-isValidTool.patch (83%) rename patches/{api-unmapped => api}/0280-Implement-Keyed-on-World.patch (93%) rename patches/{api-unmapped => api}/0281-fix-Inventory-getContents-null-annotations.patch (100%) rename patches/{api-unmapped => api}/0282-Item-Rarity-API.patch (96%) rename patches/{api-unmapped => api}/0283-Expose-protocol-version.patch (100%) rename patches/{api-unmapped/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch => api/0284-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} (100%) rename patches/{api-unmapped/0284-add-isDeeplySleeping-to-HumanEntity.patch => api/0285-add-isDeeplySleeping-to-HumanEntity.patch} (90%) rename patches/{api-unmapped/0285-add-consumeFuel-to-FurnaceBurnEvent.patch => api/0286-add-consumeFuel-to-FurnaceBurnEvent.patch} (100%) rename patches/{api-unmapped/0286-add-get-set-drop-chance-to-EntityEquipment.patch => api/0287-add-get-set-drop-chance-to-EntityEquipment.patch} (100%) rename patches/{api-unmapped/0287-Added-PlayerDeepSleepEvent.patch => api/0288-Added-PlayerDeepSleepEvent.patch} (100%) rename patches/{api-unmapped/0288-More-World-API.patch => api/0289-More-World-API.patch} (97%) rename patches/{api-unmapped/0289-Added-PlayerBedFailEnterEvent.patch => api/0290-Added-PlayerBedFailEnterEvent.patch} (100%) rename patches/{api-unmapped/0290-Introduce-beacon-activation-deactivation-events.patch => api/0291-Introduce-beacon-activation-deactivation-events.patch} (100%) rename patches/{api-unmapped/0291-PlayerMoveEvent-Improvements.patch => api/0292-PlayerMoveEvent-Improvements.patch} (100%) rename patches/{api-unmapped/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch => api/0293-add-RespawnFlags-to-PlayerRespawnEvent.patch} (100%) rename patches/{api-unmapped/0293-Add-more-WanderingTrader-API.patch => api/0294-Add-more-WanderingTrader-API.patch} (100%) rename patches/{api-unmapped => api}/0295-Add-EntityBlockStorage-clearEntities.patch (100%) rename patches/{api-unmapped => api}/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch (100%) rename patches/{api-unmapped => api}/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch (100%) rename patches/{api-unmapped => api}/0298-Inventory-close.patch (100%) rename patches/{api-unmapped => api}/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch (89%) rename patches/{api-unmapped => api}/0300-Add-basic-Datapack-API.patch (93%) rename patches/{api-unmapped => api}/0301-additions-to-PlayerGameModeChangeEvent.patch (100%) rename patches/{api-unmapped => api}/0302-ItemStack-repair-check-API.patch (96%) rename patches/{api-unmapped => api}/0303-More-Enchantment-API.patch (100%) rename patches/{api-unmapped => api}/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch (99%) rename patches/{api-unmapped => api}/0305-List-all-missing-hard-depends-not-just-first.patch (98%) rename patches/{api-unmapped => api}/0306-Add-Mob-lookAt-API.patch (100%) rename patches/{api-unmapped => api}/0307-ItemStack-editMeta.patch (100%) rename patches/{api-unmapped => api}/0308-Add-EntityInsideBlockEvent.patch (100%) rename patches/{api-unmapped => api}/0309-Attributes-API-for-item-defaults.patch (93%) rename patches/{api-unmapped => api}/0310-Add-cause-to-Weather-ThunderChangeEvents.patch (100%) rename patches/{api-unmapped => api}/0311-More-Lidded-Block-API.patch (100%) rename patches/{api-unmapped/0313-Add-PufferFishStateChangeEvent.patch => api/0312-Add-PufferFishStateChangeEvent.patch} (100%) rename patches/{server-remapped => removed/1.17}/0676-Clear-SyncLoadInfo.patch (98%) rename patches/{server-remapped => removed/1.17}/0698-Make-sure-to-remove-correct-TE-during-TE-tick.patch (98%) rename patches/{server-remapped => removed/1.17}/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch (99%) rename patches/{server-remapped => removed/1.17}/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch (98%) rename patches/{server-remapped => removed/1.17/No longer needed}/0679-do-not-create-unnecessary-copies-of-passenger-list.patch (99%) rename patches/{server-remapped => removed/1.17/No longer needed}/0706-don-t-throw-when-loading-invalid-TEs.patch (97%) delete mode 100644 patches/server-remapped/0677-Expose-Tracked-Players.patch delete mode 100644 patches/server-remapped/0678-Remove-streams-from-SensorNearest.patch delete mode 100644 patches/server-remapped/0691-Implement-Keyed-on-World.patch delete mode 100644 patches/server-remapped/0693-Item-Rarity-API.patch delete mode 100644 patches/server-remapped/0699-Don-t-ignore-result-of-PlayerEditBookEvent.patch delete mode 100644 patches/server-remapped/0700-fix-cancelling-block-falling-causing-client-desync.patch delete mode 100644 patches/server-remapped/0709-Fix-duplicating-give-items-on-item-drop-cancel.patch delete mode 100644 patches/server-remapped/0714-fix-PlayerItemHeldEvent-firing-twice.patch delete mode 100644 patches/server-remapped/0716-More-World-API.patch delete mode 100644 patches/server-remapped/0726-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch delete mode 100644 patches/server-remapped/0732-Add-basic-Datapack-API.patch delete mode 100644 patches/server-remapped/0734-additions-to-PlayerGameModeChangeEvent.patch delete mode 100644 patches/server-remapped/0741-Add-Mob-lookAt-API.patch rename patches/server/{0468-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch => 0469-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch} (100%) rename patches/server/{0469-Remove-streams-from-classes-related-villager-gossip.patch => 0470-Remove-streams-from-classes-related-villager-gossip.patch} (100%) rename patches/server/{0470-Support-components-in-ItemMeta.patch => 0471-Support-components-in-ItemMeta.patch} (100%) rename patches/server/{0471-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch => 0472-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch} (100%) rename patches/server/{0472-Add-entity-liquid-API.patch => 0473-Add-entity-liquid-API.patch} (100%) rename patches/server/{0473-Update-itemstack-legacy-name-and-lore.patch => 0474-Update-itemstack-legacy-name-and-lore.patch} (100%) rename patches/server/{0474-Spawn-player-in-correct-world-on-login.patch => 0475-Spawn-player-in-correct-world-on-login.patch} (94%) rename patches/server/{0475-Add-PrepareResultEvent.patch => 0476-Add-PrepareResultEvent.patch} (100%) rename patches/server/{0476-Allow-delegation-to-vanilla-chunk-gen.patch => 0477-Allow-delegation-to-vanilla-chunk-gen.patch} (100%) rename patches/server/{0477-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch => 0478-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch} (100%) rename patches/server/{0478-Optimize-NetworkManager-Exception-Handling.patch => 0479-Optimize-NetworkManager-Exception-Handling.patch} (100%) rename patches/server/{0479-Optimize-the-advancement-data-player-iteration-to-be.patch => 0480-Optimize-the-advancement-data-player-iteration-to-be.patch} (100%) rename patches/server/{0480-Fix-arrows-never-despawning-MC-125757.patch => 0481-Fix-arrows-never-despawning-MC-125757.patch} (100%) rename patches/server/{0481-Thread-Safe-Vanilla-Command-permission-checking.patch => 0482-Thread-Safe-Vanilla-Command-permission-checking.patch} (100%) rename patches/server/{0482-Move-range-check-for-block-placing-up.patch => 0483-Move-range-check-for-block-placing-up.patch} (94%) rename patches/server/{0483-Fix-SPIGOT-5989.patch => 0484-Fix-SPIGOT-5989.patch} (91%) rename patches/server/{0484-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch => 0485-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch} (100%) rename patches/server/{0485-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch => 0486-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch} (100%) rename patches/server/{0486-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch => 0487-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch} (100%) rename patches/server/{0487-Add-missing-strikeLighting-call-to-World-spigot-stri.patch => 0488-Add-missing-strikeLighting-call-to-World-spigot-stri.patch} (82%) rename patches/server/{0488-Fix-some-rails-connecting-improperly.patch => 0489-Fix-some-rails-connecting-improperly.patch} (100%) rename patches/server/{0489-Incremental-player-saving.patch => 0490-Incremental-player-saving.patch} (96%) rename patches/server/{0490-Fix-MC-187716-Use-configured-height.patch => 0491-Fix-MC-187716-Use-configured-height.patch} (100%) rename patches/server/{0491-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch => 0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch} (100%) rename patches/server/{0492-Do-not-let-the-server-load-chunks-from-newer-version.patch => 0493-Do-not-let-the-server-load-chunks-from-newer-version.patch} (100%) rename patches/server/{0493-Brand-support.patch => 0494-Brand-support.patch} (90%) rename patches/server/{0494-Add-setMaxPlayers-API.patch => 0495-Add-setMaxPlayers-API.patch} (89%) rename patches/server/{0495-Add-playPickupItemAnimation-to-LivingEntity.patch => 0496-Add-playPickupItemAnimation-to-LivingEntity.patch} (100%) rename patches/server/{0496-Don-t-require-FACING-data.patch => 0497-Don-t-require-FACING-data.patch} (100%) rename patches/server/{0497-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch => 0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch} (96%) rename patches/server/{0498-Add-moon-phase-API.patch => 0499-Add-moon-phase-API.patch} (89%) rename patches/server/{0499-Prevent-headless-pistons-from-being-created.patch => 0500-Prevent-headless-pistons-from-being-created.patch} (100%) rename patches/server/{0500-Add-BellRingEvent.patch => 0501-Add-BellRingEvent.patch} (100%) rename patches/server/{0501-Add-zombie-targets-turtle-egg-config.patch => 0502-Add-zombie-targets-turtle-egg-config.patch} (100%) rename patches/server/{0502-Buffer-joins-to-world.patch => 0503-Buffer-joins-to-world.patch} (100%) rename patches/server/{0503-Optimize-redstone-algorithm.patch => 0504-Optimize-redstone-algorithm.patch} (100%) rename patches/server/{0504-Fix-hex-colors-not-working-in-some-kick-messages.patch => 0505-Fix-hex-colors-not-working-in-some-kick-messages.patch} (100%) rename patches/server/{0505-PortalCreateEvent-needs-to-know-its-entity.patch => 0506-PortalCreateEvent-needs-to-know-its-entity.patch} (100%) rename patches/server/{0506-Fix-CraftTeam-null-check.patch => 0507-Fix-CraftTeam-null-check.patch} (100%) rename patches/server/{0507-Add-more-Evoker-API.patch => 0508-Add-more-Evoker-API.patch} (100%) rename patches/server/{0508-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch => 0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch} (100%) rename patches/server/{0509-Create-HoverEvent-from-ItemStack-Entity.patch => 0510-Create-HoverEvent-from-ItemStack-Entity.patch} (100%) rename patches/server/{0510-Cache-block-data-strings.patch => 0511-Cache-block-data-strings.patch} (100%) rename patches/server/{0511-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch => 0512-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch} (97%) rename patches/server/{0512-Add-additional-open-container-api-to-HumanEntity.patch => 0513-Add-additional-open-container-api-to-HumanEntity.patch} (100%) rename patches/server/{0513-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch => 0514-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch} (100%) rename patches/server/{0514-Extend-block-drop-capture-to-capture-all-items-added.patch => 0515-Extend-block-drop-capture-to-capture-all-items-added.patch} (100%) rename patches/server/{0515-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch => 0516-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch} (84%) rename patches/server/{0516-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch => 0517-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch} (100%) rename patches/server/{0517-Lazily-track-plugin-scoreboards-by-default.patch => 0518-Lazily-track-plugin-scoreboards-by-default.patch} (100%) rename patches/server/{0518-Entity-isTicking.patch => 0519-Entity-isTicking.patch} (100%) rename patches/server/{0519-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch => 0520-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch} (100%) rename patches/server/{0520-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch => 0521-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch} (100%) rename patches/server/{0521-Reset-Ender-Crystals-on-Dragon-Spawn.patch => 0522-Reset-Ender-Crystals-on-Dragon-Spawn.patch} (100%) rename patches/server/{0522-Fix-for-large-move-vectors-crashing-server.patch => 0523-Fix-for-large-move-vectors-crashing-server.patch} (97%) rename patches/server/{0523-Optimise-getType-calls.patch => 0524-Optimise-getType-calls.patch} (100%) rename patches/server/{0524-Villager-resetOffers.patch => 0525-Villager-resetOffers.patch} (100%) rename patches/server/{0525-Improve-inlinig-for-some-hot-IBlockData-methods.patch => 0526-Improve-inlinig-for-some-hot-IBlockData-methods.patch} (100%) rename patches/server/{0526-Retain-block-place-order-when-capturing-blockstates.patch => 0527-Retain-block-place-order-when-capturing-blockstates.patch} (100%) rename patches/server/{0527-Reduce-blockpos-allocation-from-pathfinding.patch => 0528-Reduce-blockpos-allocation-from-pathfinding.patch} (100%) rename patches/server/{0528-Fix-item-locations-dropped-from-campfires.patch => 0529-Fix-item-locations-dropped-from-campfires.patch} (100%) rename patches/server/{0529-Player-elytra-boost-API.patch => 0530-Player-elytra-boost-API.patch} (94%) rename patches/server/{0530-Fixed-TileEntityBell-memory-leak.patch => 0531-Fixed-TileEntityBell-memory-leak.patch} (100%) rename patches/server/{0531-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch => 0532-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch} (100%) rename patches/server/{0532-Add-getOfflinePlayerIfCached-String.patch => 0533-Add-getOfflinePlayerIfCached-String.patch} (100%) rename patches/server/{0533-Add-ignore-discounts-API.patch => 0534-Add-ignore-discounts-API.patch} (100%) rename patches/server/{0534-Toggle-for-removing-existing-dragon.patch => 0535-Toggle-for-removing-existing-dragon.patch} (100%) rename patches/server/{0535-Fix-client-lag-on-advancement-loading.patch => 0536-Fix-client-lag-on-advancement-loading.patch} (100%) rename patches/server/{0536-Item-no-age-no-player-pickup.patch => 0537-Item-no-age-no-player-pickup.patch} (100%) rename patches/server/{0537-Beacon-API-custom-effect-ranges.patch => 0538-Beacon-API-custom-effect-ranges.patch} (100%) rename patches/server/{0538-Add-API-for-quit-reason.patch => 0539-Add-API-for-quit-reason.patch} (93%) rename patches/server/{0539-Seed-based-feature-search.patch => 0540-Seed-based-feature-search.patch} (100%) rename patches/server/{0540-Add-Wandering-Trader-spawn-rate-config-options.patch => 0541-Add-Wandering-Trader-spawn-rate-config-options.patch} (100%) rename patches/server/{0541-Significantly-improve-performance-of-the-end-generat.patch => 0542-Significantly-improve-performance-of-the-end-generat.patch} (96%) rename patches/server/{0542-Expose-world-spawn-angle.patch => 0543-Expose-world-spawn-angle.patch} (88%) rename patches/server/{0543-Add-Destroy-Speed-API.patch => 0544-Add-Destroy-Speed-API.patch} (100%) rename patches/server/{0544-Fix-Player-spawnParticle-x-y-z-precision-loss.patch => 0545-Fix-Player-spawnParticle-x-y-z-precision-loss.patch} (89%) rename patches/server/{0545-Add-LivingEntity-clearActiveItem.patch => 0546-Add-LivingEntity-clearActiveItem.patch} (100%) rename patches/server/{0546-Add-PlayerItemCooldownEvent.patch => 0547-Add-PlayerItemCooldownEvent.patch} (100%) rename patches/server/{0547-More-lightning-API.patch => 0548-More-lightning-API.patch} (100%) rename patches/server/{0548-Climbing-should-not-bypass-cramming-gamerule.patch => 0549-Climbing-should-not-bypass-cramming-gamerule.patch} (100%) rename patches/server/{0549-Added-missing-default-perms-for-commands.patch => 0550-Added-missing-default-perms-for-commands.patch} (100%) rename patches/server/{0550-Add-PlayerShearBlockEvent.patch => 0551-Add-PlayerShearBlockEvent.patch} (100%) rename patches/server/{0551-Set-spigots-verbose-world-setting-to-false-by-def.patch => 0552-Set-spigots-verbose-world-setting-to-false-by-def.patch} (100%) rename patches/server/{0552-Fix-curing-zombie-villager-discount-exploit.patch => 0553-Fix-curing-zombie-villager-discount-exploit.patch} (100%) rename patches/server/{0553-Limit-recipe-packets.patch => 0554-Limit-recipe-packets.patch} (95%) rename patches/server/{0554-Fix-CraftSound-backwards-compatibility.patch => 0555-Fix-CraftSound-backwards-compatibility.patch} (100%) rename patches/server/{0555-MC-4-Fix-item-position-desync.patch => 0556-MC-4-Fix-item-position-desync.patch} (100%) rename patches/server/{0556-Player-Chunk-Load-Unload-Events.patch => 0557-Player-Chunk-Load-Unload-Events.patch} (90%) rename patches/server/{0557-Optimize-Dynamic-get-Missing-Keys.patch => 0558-Optimize-Dynamic-get-Missing-Keys.patch} (100%) rename patches/server/{0558-Expose-LivingEntity-hurt-direction.patch => 0559-Expose-LivingEntity-hurt-direction.patch} (100%) rename patches/server/{0559-Add-OBSTRUCTED-reason-to-BedEnterResult.patch => 0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} (100%) rename patches/server/{0560-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch => 0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch} (100%) rename patches/server/{0561-added-PlayerTradeEvent.patch => 0562-added-PlayerTradeEvent.patch} (100%) rename patches/server/{0562-Implement-TargetHitEvent.patch => 0563-Implement-TargetHitEvent.patch} (100%) rename patches/server/{0563-Additional-Block-Material-API-s.patch => 0564-Additional-Block-Material-API-s.patch} (100%) rename patches/server/{0564-Fix-harming-potion-dupe.patch => 0565-Fix-harming-potion-dupe.patch} (100%) rename patches/server/{0565-Implement-API-to-get-Material-from-Boats-and-Minecar.patch => 0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch} (100%) rename patches/server/{0566-Cache-burn-durations.patch => 0567-Cache-burn-durations.patch} (100%) rename patches/server/{0567-Allow-disabling-mob-spawner-spawn-egg-transformation.patch => 0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch} (100%) rename patches/server/{0568-Implement-PlayerFlowerPotManipulateEvent.patch => 0569-Implement-PlayerFlowerPotManipulateEvent.patch} (100%) rename patches/server/{0569-Fix-interact-event-not-being-called-in-adventure.patch => 0570-Fix-interact-event-not-being-called-in-adventure.patch} (90%) rename patches/server/{0570-Zombie-API-breaking-doors.patch => 0571-Zombie-API-breaking-doors.patch} (100%) rename patches/server/{0571-Fix-nerfed-slime-when-splitting.patch => 0572-Fix-nerfed-slime-when-splitting.patch} (100%) rename patches/server/{0572-Add-EntityLoadCrossbowEvent.patch => 0573-Add-EntityLoadCrossbowEvent.patch} (100%) rename patches/server/{0573-Guardian-beam-workaround.patch => 0574-Guardian-beam-workaround.patch} (100%) rename patches/server/{0574-Added-WorldGameRuleChangeEvent.patch => 0575-Added-WorldGameRuleChangeEvent.patch} (98%) rename patches/server/{0575-Added-ServerResourcesReloadedEvent.patch => 0576-Added-ServerResourcesReloadedEvent.patch} (100%) rename patches/server/{0576-Added-world-settings-for-mobs-picking-up-loot.patch => 0577-Added-world-settings-for-mobs-picking-up-loot.patch} (100%) rename patches/server/{0577-Implemented-BlockFailedDispenseEvent.patch => 0578-Implemented-BlockFailedDispenseEvent.patch} (100%) rename patches/server/{0578-Added-PlayerLecternPageChangeEvent.patch => 0579-Added-PlayerLecternPageChangeEvent.patch} (100%) rename patches/server/{0579-Added-PlayerLoomPatternSelectEvent.patch => 0580-Added-PlayerLoomPatternSelectEvent.patch} (100%) rename patches/server/{0580-Configurable-door-breaking-difficulty.patch => 0581-Configurable-door-breaking-difficulty.patch} (100%) rename patches/server/{0581-Empty-commands-shall-not-be-dispatched.patch => 0582-Empty-commands-shall-not-be-dispatched.patch} (100%) rename patches/server/{0582-Implement-API-to-expose-exact-interaction-point.patch => 0583-Implement-API-to-expose-exact-interaction-point.patch} (100%) rename patches/server/{0583-Remove-stale-POIs.patch => 0584-Remove-stale-POIs.patch} (100%) rename patches/server/{0584-Fix-villager-boat-exploit.patch => 0585-Fix-villager-boat-exploit.patch} (93%) rename patches/server/{0585-Add-sendOpLevel-API.patch => 0586-Add-sendOpLevel-API.patch} (91%) rename patches/server/{0586-Add-StructureLocateEvent.patch => 0587-Add-StructureLocateEvent.patch} (100%) rename patches/server/{0587-Collision-option-for-requiring-a-player-participant.patch => 0588-Collision-option-for-requiring-a-player-participant.patch} (100%) rename patches/server/{0588-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch => 0589-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch} (100%) rename patches/server/{0589-Return-chat-component-with-empty-text-instead-of-thr.patch => 0590-Return-chat-component-with-empty-text-instead-of-thr.patch} (100%) rename patches/server/{0590-Make-schedule-command-per-world.patch => 0591-Make-schedule-command-per-world.patch} (100%) rename patches/server/{0591-Configurable-max-leash-distance.patch => 0592-Configurable-max-leash-distance.patch} (100%) rename patches/server/{0592-Implement-BlockPreDispenseEvent.patch => 0593-Implement-BlockPreDispenseEvent.patch} (100%) rename patches/server/{0593-Added-Vanilla-Entity-Tags.patch => 0594-Added-Vanilla-Entity-Tags.patch} (100%) rename patches/server/{0594-added-Wither-API.patch => 0595-added-Wither-API.patch} (100%) rename patches/server/{0595-Added-firing-of-PlayerChangeBeaconEffectEvent.patch => 0596-Added-firing-of-PlayerChangeBeaconEffectEvent.patch} (100%) rename patches/server/{0596-Fix-console-spam-when-removing-chests-in-water.patch => 0597-Fix-console-spam-when-removing-chests-in-water.patch} (100%) rename patches/server/{0597-Add-toggle-for-always-placing-the-dragon-egg.patch => 0598-Add-toggle-for-always-placing-the-dragon-egg.patch} (100%) rename patches/server/{0598-Added-PlayerStonecutterRecipeSelectEvent.patch => 0599-Added-PlayerStonecutterRecipeSelectEvent.patch} (100%) rename patches/server/{0599-Add-dropLeash-variable-to-EntityUnleashEvent.patch => 0600-Add-dropLeash-variable-to-EntityUnleashEvent.patch} (100%) rename patches/server/{0600-Skip-distance-map-update-when-spawning-disabled.patch => 0601-Skip-distance-map-update-when-spawning-disabled.patch} (87%) rename patches/server/{0601-Reset-shield-blocking-on-dimension-change.patch => 0602-Reset-shield-blocking-on-dimension-change.patch} (83%) rename patches/server/{0602-add-DragonEggFormEvent.patch => 0603-add-DragonEggFormEvent.patch} (100%) rename patches/server/{0603-EntityMoveEvent.patch => 0604-EntityMoveEvent.patch} (100%) rename patches/{server-remapped/0667-added-option-to-disable-pathfinding-updates-on-block.patch => server/0605-added-option-to-disable-pathfinding-updates-on-block.patch} (80%) rename patches/{server-remapped/0668-Inline-shift-direction-fields.patch => server/0606-Inline-shift-direction-fields.patch} (60%) rename patches/{server-remapped/0669-Allow-adding-items-to-BlockDropItemEvent.patch => server/0607-Allow-adding-items-to-BlockDropItemEvent.patch} (92%) rename patches/{server-remapped/0670-Add-getMainThreadExecutor-to-BukkitScheduler.patch => server/0608-Add-getMainThreadExecutor-to-BukkitScheduler.patch} (92%) rename patches/{server-remapped/0671-living-entity-allow-attribute-registration.patch => server/0609-living-entity-allow-attribute-registration.patch} (70%) rename patches/{server-remapped/0672-fix-dead-slime-setSize-invincibility.patch => server/0610-fix-dead-slime-setSize-invincibility.patch} (70%) rename patches/{server-remapped/0673-Merchant-getRecipes-should-return-an-immutable-list.patch => server/0611-Merchant-getRecipes-should-return-an-immutable-list.patch} (61%) rename patches/{server-remapped/0674-misc-debugging-dumps.patch => server/0612-misc-debugging-dumps.patch} (59%) rename patches/{server-remapped/0675-Add-support-for-hex-color-codes-in-console.patch => server/0613-Add-support-for-hex-color-codes-in-console.patch} (93%) create mode 100644 patches/server/0614-Expose-Tracked-Players.patch create mode 100644 patches/server/0615-Remove-streams-from-SensorNearest.patch rename patches/{server-remapped/0680-MC-29274-Fix-Wither-hostility-towards-players.patch => server/0616-MC-29274-Fix-Wither-hostility-towards-players.patch} (84%) rename patches/{server-remapped/0681-Throw-proper-exception-on-empty-JsonList-file.patch => server/0617-Throw-proper-exception-on-empty-JsonList-file.patch} (91%) rename patches/{server-remapped/0682-Improve-ServerGUI.patch => server/0618-Improve-ServerGUI.patch} (92%) rename patches/{server-remapped/0683-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch => server/0619-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch} (100%) rename patches/{server-remapped/0684-fix-converting-txt-to-json-file.patch => server/0620-fix-converting-txt-to-json-file.patch} (64%) rename patches/{server-remapped/0685-Add-worldborder-events.patch => server/0621-Add-worldborder-events.patch} (52%) rename patches/{server-remapped/0686-added-PlayerNameEntityEvent.patch => server/0622-added-PlayerNameEntityEvent.patch} (80%) rename patches/{server-remapped/0687-Prevent-grindstones-from-overstacking-items.patch => server/0623-Prevent-grindstones-from-overstacking-items.patch} (89%) rename patches/{server-remapped/0688-Add-recipe-to-cook-events.patch => server/0624-Add-recipe-to-cook-events.patch} (55%) rename patches/{server-remapped/0689-Add-Block-isValidTool.patch => server/0625-Add-Block-isValidTool.patch} (79%) rename patches/{server-remapped/0690-Allow-using-signs-inside-spawn-protection.patch => server/0626-Allow-using-signs-inside-spawn-protection.patch} (68%) create mode 100644 patches/server/0627-Implement-Keyed-on-World.patch rename patches/{server-remapped/0692-Add-fast-alternative-constructor-for-Vector3f.patch => server/0628-Add-fast-alternative-constructor-for-Rotations.patch} (79%) create mode 100644 patches/server/0629-Item-Rarity-API.patch rename patches/{server-remapped/0694-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch => server/0630-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch} (74%) rename patches/{server-remapped/0695-copy-TESign-isEditable-from-snapshots.patch => server/0631-copy-TESign-isEditable-from-snapshots.patch} (80%) rename patches/{server-remapped/0696-Drop-carried-item-when-player-has-disconnected.patch => server/0632-Drop-carried-item-when-player-has-disconnected.patch} (55%) rename patches/{server-remapped/0697-forced-whitelist-use-configurable-kick-message.patch => server/0633-forced-whitelist-use-configurable-kick-message.patch} (86%) create mode 100644 patches/server/0634-Don-t-ignore-result-of-PlayerEditBookEvent.patch create mode 100644 patches/server/0635-fix-cancelling-block-falling-causing-client-desync.patch rename patches/{server-remapped/0701-Expose-protocol-version.patch => server/0636-Expose-protocol-version.patch} (82%) rename patches/{server-remapped/0702-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch => server/0637-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} (93%) rename patches/{server-remapped/0703-Enhance-console-tab-completions-for-brigadier-comman.patch => server/0638-Enhance-console-tab-completions-for-brigadier-comman.patch} (79%) rename patches/{server-remapped/0704-Fix-PlayerItemConsumeEvent-cancelling-properly.patch => server/0639-Fix-PlayerItemConsumeEvent-cancelling-properly.patch} (87%) rename patches/{server-remapped/0705-Add-bypass-host-check.patch => server/0640-Add-bypass-host-check.patch} (77%) rename patches/{server-remapped/0707-Set-area-affect-cloud-rotation.patch => server/0641-Set-area-affect-cloud-rotation.patch} (73%) rename patches/{server-remapped/0708-add-isDeeplySleeping-to-HumanEntity.patch => server/0642-add-isDeeplySleeping-to-HumanEntity.patch} (78%) create mode 100644 patches/server/0643-Fix-duplicating-give-items-on-item-drop-cancel.patch rename patches/{server-remapped/0710-add-consumeFuel-to-FurnaceBurnEvent.patch => server/0644-add-consumeFuel-to-FurnaceBurnEvent.patch} (51%) rename patches/{server-remapped/0711-add-get-set-drop-chance-to-EntityEquipment.patch => server/0645-add-get-set-drop-chance-to-EntityEquipment.patch} (88%) rename patches/{server-remapped/0712-fix-PigZombieAngerEvent-cancellation.patch => server/0646-fix-PigZombieAngerEvent-cancellation.patch} (60%) rename patches/{server-remapped/0713-Fix-checkReach-check-for-Shulker-boxes.patch => server/0647-Fix-checkReach-check-for-Shulker-boxes.patch} (82%) create mode 100644 patches/server/0648-fix-PlayerItemHeldEvent-firing-twice.patch rename patches/{server-remapped/0715-Added-PlayerDeepSleepEvent.patch => server/0649-Added-PlayerDeepSleepEvent.patch} (85%) create mode 100644 patches/server/0650-More-World-API.patch rename patches/{server-remapped/0717-Added-PlayerBedFailEnterEvent.patch => server/0651-Added-PlayerBedFailEnterEvent.patch} (50%) rename patches/{server-remapped/0718-Implement-methods-to-convert-between-Component-and-B.patch => server/0652-Implement-methods-to-convert-between-Component-and-B.patch} (93%) rename patches/{server-remapped/0719-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch => server/0653-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch} (79%) rename patches/{server-remapped/0721-Introduce-beacon-activation-deactivation-events.patch => server/0654-Introduce-beacon-activation-deactivation-events.patch} (63%) rename patches/{server-remapped/0720-add-RespawnFlags-to-PlayerRespawnEvent.patch => server/0655-add-RespawnFlags-to-PlayerRespawnEvent.patch} (81%) rename patches/{server-remapped/0722-Add-Channel-initialization-listeners.patch => server/0656-Add-Channel-initialization-listeners.patch} (94%) rename patches/{server-remapped/0723-Send-empty-commands-if-tab-completion-is-disabled.patch => server/0657-Send-empty-commands-if-tab-completion-is-disabled.patch} (88%) rename patches/{server-remapped/0724-Add-more-WanderingTrader-API.patch => server/0658-Add-more-WanderingTrader-API.patch} (84%) rename patches/{server-remapped/0725-Add-EntityBlockStorage-clearEntities.patch => server/0659-Add-EntityBlockStorage-clearEntities.patch} (89%) create mode 100644 patches/server/0660-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename patches/{server-remapped/0727-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch => server/0661-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch} (72%) rename patches/{server-remapped/0728-Inventory-close.patch => server/0662-Inventory-close.patch} (82%) rename patches/{server-remapped/0729-call-PortalCreateEvent-players-and-end-platform.patch => server/0663-call-PortalCreateEvent-players-and-end-platform.patch} (84%) rename patches/{server-remapped/0730-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch => server/0664-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch} (68%) rename patches/{server-remapped/0731-Fix-CraftPotionBrewer-cache.patch => server/0665-Fix-CraftPotionBrewer-cache.patch} (72%) create mode 100644 patches/server/0666-Add-basic-Datapack-API.patch rename patches/{server-remapped/0733-Add-environment-variable-to-disable-server-gui.patch => server/0667-Add-environment-variable-to-disable-server-gui.patch} (85%) create mode 100644 patches/server/0668-additions-to-PlayerGameModeChangeEvent.patch rename patches/{server-remapped/0735-ItemStack-repair-check-API.patch => server/0669-ItemStack-repair-check-API.patch} (74%) rename patches/{server-remapped/0736-More-Enchantment-API.patch => server/0670-More-Enchantment-API.patch} (59%) rename patches/{server-remapped/0737-Add-command-line-option-to-load-extra-plugin-jars-no.patch => server/0671-Add-command-line-option-to-load-extra-plugin-jars-no.patch} (82%) rename patches/{server-remapped/0740-Fix-and-optimise-world-force-upgrading.patch => server/0672-Fix-and-optimise-world-force-upgrading.patch} (83%) create mode 100644 patches/server/0673-Add-Mob-lookAt-API.patch rename patches/{server-remapped/0742-Add-Unix-domain-socket-support.patch => server/0674-Add-Unix-domain-socket-support.patch} (87%) rename patches/{server-remapped/0743-Add-EntityInsideBlockEvent.patch => server/0675-Add-EntityInsideBlockEvent.patch} (72%) rename patches/{server-remapped/0744-Attributes-API-for-item-defaults.patch => server/0676-Attributes-API-for-item-defaults.patch} (58%) rename patches/{server-remapped/0745-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch => server/0677-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch} (76%) rename patches/{server-remapped/0746-Add-cause-to-Weather-ThunderChangeEvents.patch => server/0678-Add-cause-to-Weather-ThunderChangeEvents.patch} (57%) rename patches/{server-remapped/0747-More-Lidded-Block-API.patch => server/0679-More-Lidded-Block-API.patch} (64%) rename patches/{server-remapped/0749-Limit-item-frame-cursors-on-maps.patch => server/0680-Limit-item-frame-cursors-on-maps.patch} (86%) rename patches/{server-remapped/0750-Add-PufferFishStateChangeEvent.patch => server/0681-Add-PufferFishStateChangeEvent.patch} (95%) diff --git a/build-data/paper.at b/build-data/paper.at index ced8ae8dfd..1afeccf82a 100644 --- a/build-data/paper.at +++ b/build-data/paper.at @@ -4,3 +4,15 @@ # This line would make the field public and remove the final modifier #public-f net.minecraft.network.protocol.game.ClientboundChatPacket sender # Leave out the member and it will apply to the class itself + +# Item Rarity API +public net.minecraft.world.item.Item rarity + +# More Enchantment API +public net.minecraft.world.item.enchantment.Enchantment slots; + +# Fix and optimise world force upgrading +public net.minecraft.util.worldupdate.WorldUpgrader REGEX; + +# More Lidded Block API +public net.minecraft.world.level.block.entity.EnderChestBlockEntity openersCounter \ No newline at end of file diff --git a/patches/api-unmapped/0270-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/api/0270-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from patches/api-unmapped/0270-Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/api/0270-Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/patches/api-unmapped/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/api/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from patches/api-unmapped/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/api/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/patches/api-unmapped/0272-living-entity-allow-attribute-registration.patch b/patches/api/0272-living-entity-allow-attribute-registration.patch similarity index 100% rename from patches/api-unmapped/0272-living-entity-allow-attribute-registration.patch rename to patches/api/0272-living-entity-allow-attribute-registration.patch diff --git a/patches/api-unmapped/0273-Add-missing-effects.patch b/patches/api/0273-Add-missing-effects.patch similarity index 100% rename from patches/api-unmapped/0273-Add-missing-effects.patch rename to patches/api/0273-Add-missing-effects.patch diff --git a/patches/api-unmapped/0274-Expose-Tracked-Players.patch b/patches/api/0274-Expose-Tracked-Players.patch similarity index 86% rename from patches/api-unmapped/0274-Expose-Tracked-Players.patch rename to patches/api/0274-Expose-Tracked-Players.patch index 1c4214897c..625e7bd3b7 100644 --- a/patches/api-unmapped/0274-Expose-Tracked-Players.patch +++ b/patches/api/0274-Expose-Tracked-Players.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Expose Tracked Players diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 68a03821a5f06308a9c51fdf107d3924c44886c8..34b51466ffb281b05f531b3f7deda245ae7fd96a 100644 +index 9c7960f56733ff18b949cffe15f082c4cde28317..38003de85a8098fc78fc947dd975990d478ee908 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1,6 +1,7 @@ @@ -16,7 +16,7 @@ index 68a03821a5f06308a9c51fdf107d3924c44886c8..34b51466ffb281b05f531b3f7deda245 import java.util.UUID; import com.destroystokyo.paper.ClientOption; // Paper import com.destroystokyo.paper.Title; // Paper -@@ -1942,6 +1943,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1969,6 +1970,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM void sendOpLevel(byte level); // Paper end diff --git a/patches/api-unmapped/0275-Cache-the-result-of-Material-isBlock.patch b/patches/api/0275-Cache-the-result-of-Material-isBlock.patch similarity index 79% rename from patches/api-unmapped/0275-Cache-the-result-of-Material-isBlock.patch rename to patches/api/0275-Cache-the-result-of-Material-isBlock.patch index 7eca03bdf5..164998f1ec 100644 --- a/patches/api-unmapped/0275-Cache-the-result-of-Material-isBlock.patch +++ b/patches/api/0275-Cache-the-result-of-Material-isBlock.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Cache the result of Material#isBlock diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 69c85c3a1f45476f7de0a9399852d82eeb4f9c86..0f081835c0484e15fca4fadaa27e90cadd394276 100644 +index 1efc97d88c38863bcd6cd4c11c8b88a18ee06b25..5ff032f73d88dd91163ff3e6c89dcd0d1507228c 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java -@@ -3935,6 +3935,7 @@ public enum Material implements Keyed { +@@ -3936,6 +3936,7 @@ public enum Material implements Keyed { public final Class data; private final boolean legacy; private final NamespacedKey key; @@ -16,7 +16,7 @@ index 69c85c3a1f45476f7de0a9399852d82eeb4f9c86..0f081835c0484e15fca4fadaa27e90ca private Material(final int id) { this(id, 64); -@@ -4132,6 +4133,11 @@ public enum Material implements Keyed { +@@ -4133,6 +4134,11 @@ public enum Material implements Keyed { * @return true if this material is a block */ public boolean isBlock() { @@ -28,7 +28,7 @@ index 69c85c3a1f45476f7de0a9399852d82eeb4f9c86..0f081835c0484e15fca4fadaa27e90ca switch (this) { // case ACACIA_BUTTON: -@@ -5213,6 +5219,7 @@ public enum Material implements Keyed { +@@ -5214,6 +5220,7 @@ public enum Material implements Keyed { static { for (Material material : values()) { BY_NAME.put(material.name(), material); diff --git a/patches/api-unmapped/0276-Add-worldborder-events.patch b/patches/api/0276-Add-worldborder-events.patch similarity index 100% rename from patches/api-unmapped/0276-Add-worldborder-events.patch rename to patches/api/0276-Add-worldborder-events.patch diff --git a/patches/api-unmapped/0277-added-PlayerNameEntityEvent.patch b/patches/api/0277-added-PlayerNameEntityEvent.patch similarity index 100% rename from patches/api-unmapped/0277-added-PlayerNameEntityEvent.patch rename to patches/api/0277-added-PlayerNameEntityEvent.patch diff --git a/patches/api-unmapped/0278-Add-recipe-to-cook-events.patch b/patches/api/0278-Add-recipe-to-cook-events.patch similarity index 100% rename from patches/api-unmapped/0278-Add-recipe-to-cook-events.patch rename to patches/api/0278-Add-recipe-to-cook-events.patch diff --git a/patches/api-unmapped/0279-Add-Block-isValidTool.patch b/patches/api/0279-Add-Block-isValidTool.patch similarity index 83% rename from patches/api-unmapped/0279-Add-Block-isValidTool.patch rename to patches/api/0279-Add-Block-isValidTool.patch index f037cf8c32..257cf003a8 100644 --- a/patches/api-unmapped/0279-Add-Block-isValidTool.patch +++ b/patches/api/0279-Add-Block-isValidTool.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add Block#isValidTool diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 181658c679d306ffc4ad45259494571ee224ef47..08e6f1741685f54506c8a4ff29bbd30f62cf8e45 100644 +index b3c127a3d4c554c08e500497a54755e626342dd3..ca488173a20bcf3427906f0a6548f06a97c9dc36 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java -@@ -218,6 +218,15 @@ public interface Block extends Metadatable { +@@ -219,6 +219,15 @@ public interface Block extends Metadatable { public static int getBlockKeyZ(long packed) { return (int) ((packed << 10) >> 37); } diff --git a/patches/api-unmapped/0280-Implement-Keyed-on-World.patch b/patches/api/0280-Implement-Keyed-on-World.patch similarity index 93% rename from patches/api-unmapped/0280-Implement-Keyed-on-World.patch rename to patches/api/0280-Implement-Keyed-on-World.patch index 75f66d5848..b8287b7ba8 100644 --- a/patches/api-unmapped/0280-Implement-Keyed-on-World.patch +++ b/patches/api/0280-Implement-Keyed-on-World.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Implement Keyed on World diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 68101a322ffab8ec28843386b79b8079576fa720..5f7208196684d9c8373df28b7cfb5f9e21baa41e 100644 +index bad4593447ca390b3e2f3bc71b4ea9f4dd673445..142050887ac02e36ae20e73a43ec698b6bab1947 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -639,6 +639,18 @@ public final class Bukkit { @@ -28,7 +28,7 @@ index 68101a322ffab8ec28843386b79b8079576fa720..5f7208196684d9c8373df28b7cfb5f9e /** * Gets the map from the given item ID. diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index a79fa08b9e6fb924b2da933eb6e4b365d14d938d..f3e27d2d02a9407bb1b091b8c1125ad5abf99e55 100644 +index 48c6434a6a5b1659d4cc8ddf8fe23806628c3b7e..0b3de184f7267543d693c45379bf5989303cf56a 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -541,6 +541,17 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @@ -50,7 +50,7 @@ index a79fa08b9e6fb924b2da933eb6e4b365d14d938d..f3e27d2d02a9407bb1b091b8c1125ad5 * Gets the map from the given item ID. * diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index ced33fc6de6bfa2767123131d532e7ae9ef3a5be..98512bddbb0c8bd6a3f487c60b1ec77b274b991e 100644 +index 27d97cde0fb5f6d727656c291e34dc468200f0c0..178a0853bd8136c6a7408f5d49604ceb2479f138 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -43,7 +43,7 @@ import org.jetbrains.annotations.Nullable; @@ -62,7 +62,7 @@ index ced33fc6de6bfa2767123131d532e7ae9ef3a5be..98512bddbb0c8bd6a3f487c60b1ec77b // Paper start /** -@@ -829,6 +829,15 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad +@@ -1534,6 +1534,15 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad @NotNull java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent); diff --git a/patches/api-unmapped/0281-fix-Inventory-getContents-null-annotations.patch b/patches/api/0281-fix-Inventory-getContents-null-annotations.patch similarity index 100% rename from patches/api-unmapped/0281-fix-Inventory-getContents-null-annotations.patch rename to patches/api/0281-fix-Inventory-getContents-null-annotations.patch diff --git a/patches/api-unmapped/0282-Item-Rarity-API.patch b/patches/api/0282-Item-Rarity-API.patch similarity index 96% rename from patches/api-unmapped/0282-Item-Rarity-API.patch rename to patches/api/0282-Item-Rarity-API.patch index 8f0f4fc977..4a41972380 100644 --- a/patches/api-unmapped/0282-Item-Rarity-API.patch +++ b/patches/api/0282-Item-Rarity-API.patch @@ -39,10 +39,10 @@ index 0000000000000000000000000000000000000000..74ef8395cc040ce488c2acaa416db202 + } +} diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 0f081835c0484e15fca4fadaa27e90cadd394276..07b8b913434bb575df8670230d693b2d4cec2571 100644 +index 5ff032f73d88dd91163ff3e6c89dcd0d1507228c..a9bcb123526da0881728070d36aea37612db8cf2 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java -@@ -4002,6 +4002,17 @@ public enum Material implements Keyed { +@@ -4003,6 +4003,17 @@ public enum Material implements Keyed { public String getTranslationKey() { return Bukkit.getUnsafe().getTranslationKey(this); } diff --git a/patches/api-unmapped/0283-Expose-protocol-version.patch b/patches/api/0283-Expose-protocol-version.patch similarity index 100% rename from patches/api-unmapped/0283-Expose-protocol-version.patch rename to patches/api/0283-Expose-protocol-version.patch diff --git a/patches/api-unmapped/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/api/0284-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 100% rename from patches/api-unmapped/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to patches/api/0284-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch diff --git a/patches/api-unmapped/0284-add-isDeeplySleeping-to-HumanEntity.patch b/patches/api/0285-add-isDeeplySleeping-to-HumanEntity.patch similarity index 90% rename from patches/api-unmapped/0284-add-isDeeplySleeping-to-HumanEntity.patch rename to patches/api/0285-add-isDeeplySleeping-to-HumanEntity.patch index b0f198f0e1..cc4e80e8a0 100644 --- a/patches/api-unmapped/0284-add-isDeeplySleeping-to-HumanEntity.patch +++ b/patches/api/0285-add-isDeeplySleeping-to-HumanEntity.patch @@ -5,7 +5,7 @@ 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 f0e0710fef5a3e0b722ece7ccf89c3d0f88f8f0f..2ce774c81a93260a1464183d435b4c418ed61648 100644 +index 112c891e54e8f30ac10e6865efc2a8ee8d172188..0ad7a3d4d40d58eb950e34668f9554bb73f934fb 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java @@ -319,6 +319,15 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder diff --git a/patches/api-unmapped/0285-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/api/0286-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from patches/api-unmapped/0285-add-consumeFuel-to-FurnaceBurnEvent.patch rename to patches/api/0286-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/patches/api-unmapped/0286-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/api/0287-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from patches/api-unmapped/0286-add-get-set-drop-chance-to-EntityEquipment.patch rename to patches/api/0287-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/patches/api-unmapped/0287-Added-PlayerDeepSleepEvent.patch b/patches/api/0288-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from patches/api-unmapped/0287-Added-PlayerDeepSleepEvent.patch rename to patches/api/0288-Added-PlayerDeepSleepEvent.patch diff --git a/patches/api-unmapped/0288-More-World-API.patch b/patches/api/0289-More-World-API.patch similarity index 97% rename from patches/api-unmapped/0288-More-World-API.patch rename to patches/api/0289-More-World-API.patch index 1a3c73561c..0852f78c91 100644 --- a/patches/api-unmapped/0288-More-World-API.patch +++ b/patches/api/0289-More-World-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] More World API diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 98512bddbb0c8bd6a3f487c60b1ec77b274b991e..a1496fe00a2d5ba6c1af054d4327f868b2cd7344 100644 +index 178a0853bd8136c6a7408f5d49604ceb2479f138..244bb359492ae486f0610f5aea6b75997dbc4bdc 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -3482,6 +3482,120 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad diff --git a/patches/api-unmapped/0289-Added-PlayerBedFailEnterEvent.patch b/patches/api/0290-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from patches/api-unmapped/0289-Added-PlayerBedFailEnterEvent.patch rename to patches/api/0290-Added-PlayerBedFailEnterEvent.patch diff --git a/patches/api-unmapped/0290-Introduce-beacon-activation-deactivation-events.patch b/patches/api/0291-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from patches/api-unmapped/0290-Introduce-beacon-activation-deactivation-events.patch rename to patches/api/0291-Introduce-beacon-activation-deactivation-events.patch diff --git a/patches/api-unmapped/0291-PlayerMoveEvent-Improvements.patch b/patches/api/0292-PlayerMoveEvent-Improvements.patch similarity index 100% rename from patches/api-unmapped/0291-PlayerMoveEvent-Improvements.patch rename to patches/api/0292-PlayerMoveEvent-Improvements.patch diff --git a/patches/api-unmapped/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/api/0293-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from patches/api-unmapped/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/api/0293-add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/patches/api-unmapped/0293-Add-more-WanderingTrader-API.patch b/patches/api/0294-Add-more-WanderingTrader-API.patch similarity index 100% rename from patches/api-unmapped/0293-Add-more-WanderingTrader-API.patch rename to patches/api/0294-Add-more-WanderingTrader-API.patch diff --git a/patches/api-unmapped/0295-Add-EntityBlockStorage-clearEntities.patch b/patches/api/0295-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from patches/api-unmapped/0295-Add-EntityBlockStorage-clearEntities.patch rename to patches/api/0295-Add-EntityBlockStorage-clearEntities.patch diff --git a/patches/api-unmapped/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/api/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from patches/api-unmapped/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to patches/api/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/patches/api-unmapped/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/api/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from patches/api-unmapped/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/api/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/patches/api-unmapped/0298-Inventory-close.patch b/patches/api/0298-Inventory-close.patch similarity index 100% rename from patches/api-unmapped/0298-Inventory-close.patch rename to patches/api/0298-Inventory-close.patch diff --git a/patches/api-unmapped/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/api/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 89% rename from patches/api-unmapped/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/api/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch index 9b01b30676..1f4bc96b56 100644 --- a/patches/api-unmapped/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch +++ b/patches/api/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch @@ -30,10 +30,10 @@ index ed4d417c2deefb78807cb61b01df5afcd334d754..a40b045f08b85e22e75459b547e7e7c0 // Paper end } diff --git a/src/main/java/org/bukkit/entity/Skeleton.java b/src/main/java/org/bukkit/entity/Skeleton.java -index 1c367f78eadf24850061a84ce63b950b79d3c435..684477b894e52ff33f9fce2edf76e58c292dd75e 100644 +index b7e424ea8a282f45fb8b91c919e4e4526c00be8b..2ca7c040270fa1b0fe623a0a779879783201a2f1 100644 --- a/src/main/java/org/bukkit/entity/Skeleton.java +++ b/src/main/java/org/bukkit/entity/Skeleton.java -@@ -46,4 +46,19 @@ public interface Skeleton extends Monster, RangedEntity { // Paper +@@ -64,4 +64,19 @@ public interface Skeleton extends AbstractSkeleton, com.destroystokyo.paper.enti */ STRAY; } diff --git a/patches/api-unmapped/0300-Add-basic-Datapack-API.patch b/patches/api/0300-Add-basic-Datapack-API.patch similarity index 93% rename from patches/api-unmapped/0300-Add-basic-Datapack-API.patch rename to patches/api/0300-Add-basic-Datapack-API.patch index ae9149d2f3..9b119b0963 100644 --- a/patches/api-unmapped/0300-Add-basic-Datapack-API.patch +++ b/patches/api/0300-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 050ee6a6fd0b74d9bfdd9dfe88cd4cd3d17da868..a8b6cc350e85d4f1a31f30dee42feafd0edb6009 100644 +index 142050887ac02e36ae20e73a43ec698b6bab1947..e8414592b3afeb1e5db2b817b8fb7c13e073b9aa 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -1949,6 +1949,14 @@ public final class Bukkit { @@ -89,7 +89,7 @@ index 050ee6a6fd0b74d9bfdd9dfe88cd4cd3d17da868..a8b6cc350e85d4f1a31f30dee42feafd @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index eb7f604600839618eaf27e0e5444b4830716eb07..2b400079559abd6b847782ae8480f2ae1948e22a 100644 +index 0b3de184f7267543d693c45379bf5989303cf56a..e88b47a838dc472ad64271a518ee1789f7be19fa 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1709,5 +1709,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api-unmapped/0301-additions-to-PlayerGameModeChangeEvent.patch b/patches/api/0301-additions-to-PlayerGameModeChangeEvent.patch similarity index 100% rename from patches/api-unmapped/0301-additions-to-PlayerGameModeChangeEvent.patch rename to patches/api/0301-additions-to-PlayerGameModeChangeEvent.patch diff --git a/patches/api-unmapped/0302-ItemStack-repair-check-API.patch b/patches/api/0302-ItemStack-repair-check-API.patch similarity index 96% rename from patches/api-unmapped/0302-ItemStack-repair-check-API.patch rename to patches/api/0302-ItemStack-repair-check-API.patch index 2281b38541..d90207b8e3 100644 --- a/patches/api-unmapped/0302-ItemStack-repair-check-API.patch +++ b/patches/api/0302-ItemStack-repair-check-API.patch @@ -26,7 +26,7 @@ index 6dbd520182b1e7713a68baad09b7f613424ef619..e504567cf755557be8511f2c93c17157 * Returns the server's protocol version. * diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index fccfae41f53a175e1a6a670c793e464456de6b60..0f8c593ae9bca46081f0b22c2d763a2699175398 100644 +index f72d3d62d61755bbaf1950ebcb228ce95d1faf58..1bd9f7582bb907ff178fd110fdc92834885d1d78 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -873,5 +873,27 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor diff --git a/patches/api-unmapped/0303-More-Enchantment-API.patch b/patches/api/0303-More-Enchantment-API.patch similarity index 100% rename from patches/api-unmapped/0303-More-Enchantment-API.patch rename to patches/api/0303-More-Enchantment-API.patch diff --git a/patches/api-unmapped/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/api/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 99% rename from patches/api-unmapped/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to patches/api/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch index c4cd74cdbe..79e5efee21 100644 --- a/patches/api-unmapped/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch +++ b/patches/api/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch @@ -7,7 +7,7 @@ Subject: [PATCH] Add command line option to load extra plugin jars not in the ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 26685f59b235ea5b4c4fb7ae21acb5149edaa2b3..ca866876f2f35a1c41eb009064412423fa09e441 100644 +index 49e5d49eb09bb966e47d6a03ac08a527c963b43d..f988705a3cd3943b2f6f952b4f8b5ec014722978 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -60,6 +60,7 @@ public final class SimplePluginManager implements PluginManager { diff --git a/patches/api-unmapped/0305-List-all-missing-hard-depends-not-just-first.patch b/patches/api/0305-List-all-missing-hard-depends-not-just-first.patch similarity index 98% rename from patches/api-unmapped/0305-List-all-missing-hard-depends-not-just-first.patch rename to patches/api/0305-List-all-missing-hard-depends-not-just-first.patch index bbbab43d60..4d1ba6ef20 100644 --- a/patches/api-unmapped/0305-List-all-missing-hard-depends-not-just-first.patch +++ b/patches/api/0305-List-all-missing-hard-depends-not-just-first.patch @@ -5,7 +5,7 @@ Subject: [PATCH] List all missing hard depends not just first diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index ca866876f2f35a1c41eb009064412423fa09e441..d1c35e4cf778070f8d18bbe0af8d423334c6dfbf 100644 +index f988705a3cd3943b2f6f952b4f8b5ec014722978..0e25119564dfa9cb12f3c5dc5f653d7f2c147a9d 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -264,6 +264,7 @@ public final class SimplePluginManager implements PluginManager { diff --git a/patches/api-unmapped/0306-Add-Mob-lookAt-API.patch b/patches/api/0306-Add-Mob-lookAt-API.patch similarity index 100% rename from patches/api-unmapped/0306-Add-Mob-lookAt-API.patch rename to patches/api/0306-Add-Mob-lookAt-API.patch diff --git a/patches/api-unmapped/0307-ItemStack-editMeta.patch b/patches/api/0307-ItemStack-editMeta.patch similarity index 100% rename from patches/api-unmapped/0307-ItemStack-editMeta.patch rename to patches/api/0307-ItemStack-editMeta.patch diff --git a/patches/api-unmapped/0308-Add-EntityInsideBlockEvent.patch b/patches/api/0308-Add-EntityInsideBlockEvent.patch similarity index 100% rename from patches/api-unmapped/0308-Add-EntityInsideBlockEvent.patch rename to patches/api/0308-Add-EntityInsideBlockEvent.patch diff --git a/patches/api-unmapped/0309-Attributes-API-for-item-defaults.patch b/patches/api/0309-Attributes-API-for-item-defaults.patch similarity index 93% rename from patches/api-unmapped/0309-Attributes-API-for-item-defaults.patch rename to patches/api/0309-Attributes-API-for-item-defaults.patch index fa1b8ce93a..f3107ae522 100644 --- a/patches/api-unmapped/0309-Attributes-API-for-item-defaults.patch +++ b/patches/api/0309-Attributes-API-for-item-defaults.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Attributes API for item defaults diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 07b8b913434bb575df8670230d693b2d4cec2571..397591da25fbb0e4d3012431df70d661d9bc9188 100644 +index a9bcb123526da0881728070d36aea37612db8cf2..d635c4fb85d3eeea3853037b2da5881c4853b193 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java -@@ -4013,6 +4013,19 @@ public enum Material implements Keyed { +@@ -4014,6 +4014,19 @@ public enum Material implements Keyed { public io.papermc.paper.inventory.ItemRarity getItemRarity() { return Bukkit.getUnsafe().getItemRarity(this); } diff --git a/patches/api-unmapped/0310-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/api/0310-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from patches/api-unmapped/0310-Add-cause-to-Weather-ThunderChangeEvents.patch rename to patches/api/0310-Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/patches/api-unmapped/0311-More-Lidded-Block-API.patch b/patches/api/0311-More-Lidded-Block-API.patch similarity index 100% rename from patches/api-unmapped/0311-More-Lidded-Block-API.patch rename to patches/api/0311-More-Lidded-Block-API.patch diff --git a/patches/api-unmapped/0313-Add-PufferFishStateChangeEvent.patch b/patches/api/0312-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from patches/api-unmapped/0313-Add-PufferFishStateChangeEvent.patch rename to patches/api/0312-Add-PufferFishStateChangeEvent.patch diff --git a/patches/server-remapped/0676-Clear-SyncLoadInfo.patch b/patches/removed/1.17/0676-Clear-SyncLoadInfo.patch similarity index 98% rename from patches/server-remapped/0676-Clear-SyncLoadInfo.patch rename to patches/removed/1.17/0676-Clear-SyncLoadInfo.patch index 08d7212876..14947b5139 100644 --- a/patches/server-remapped/0676-Clear-SyncLoadInfo.patch +++ b/patches/removed/1.17/0676-Clear-SyncLoadInfo.patch @@ -5,6 +5,8 @@ Subject: [PATCH] Clear SyncLoadInfo This patch merely adds the extra argument "clear" after /paper syncloadinfo to clear currently stored syncload info. +Relies on other not-applied patches + diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java index 6fad9329213e4e8a3ef9ce7fb568ad22484a11f3..a6b2b69a5a79fb8cea81e55018ee7f57c8820e56 100644 --- a/src/main/java/com/destroystokyo/paper/PaperCommand.java diff --git a/patches/server-remapped/0698-Make-sure-to-remove-correct-TE-during-TE-tick.patch b/patches/removed/1.17/0698-Make-sure-to-remove-correct-TE-during-TE-tick.patch similarity index 98% rename from patches/server-remapped/0698-Make-sure-to-remove-correct-TE-during-TE-tick.patch rename to patches/removed/1.17/0698-Make-sure-to-remove-correct-TE-during-TE-tick.patch index 7fbf9ba181..1998d6b9d6 100644 --- a/patches/server-remapped/0698-Make-sure-to-remove-correct-TE-during-TE-tick.patch +++ b/patches/removed/1.17/0698-Make-sure-to-remove-correct-TE-during-TE-tick.patch @@ -5,6 +5,8 @@ Subject: [PATCH] Make sure to remove correct TE during TE tick This looks like it can cause premature TE removal. +1.17: doesnt apply anymore? + diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index b89cefc8890774dbc64fd6bddeb038d2ee36d485..4523bc1f49e7be248a47eeb599fa7b6550dbb08d 100644 --- a/src/main/java/net/minecraft/world/level/Level.java diff --git a/patches/server-remapped/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/patches/removed/1.17/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch similarity index 99% rename from patches/server-remapped/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch rename to patches/removed/1.17/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch index 7f7be61f7b..51967306ba 100644 --- a/patches/server-remapped/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch +++ b/patches/removed/1.17/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch @@ -34,6 +34,8 @@ This should fix some problems converting old data, as the changes here are going to prevent the chunk from being regenerated incorrectly. +SPOTTEDLEAF!!!!!!!!!!! + diff --git a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java index 16f6aa39385e2d278d4883a32c11ddd119d0d85d..3d262dcf6db0e395d2fa457f7197f24013037ac1 100644 --- a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java diff --git a/patches/server-remapped/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch b/patches/removed/1.17/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch similarity index 98% rename from patches/server-remapped/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch rename to patches/removed/1.17/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch index 885e2d6ca3..ba83517560 100644 --- a/patches/server-remapped/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch +++ b/patches/removed/1.17/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch @@ -3,6 +3,7 @@ From: SamB440 Date: Fri, 21 May 2021 00:22:09 +0100 Subject: [PATCH] Fix MC-148809: Increase structure block data length to 128 +Fixed in 1.17 diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java index 4c797dd82bb1989861e350a7e628eb847b58bbd8..4792aafd8d992cd64d05f8bbef5cbf30988949ed 100644 diff --git a/patches/server-remapped/0679-do-not-create-unnecessary-copies-of-passenger-list.patch b/patches/removed/1.17/No longer needed/0679-do-not-create-unnecessary-copies-of-passenger-list.patch similarity index 99% rename from patches/server-remapped/0679-do-not-create-unnecessary-copies-of-passenger-list.patch rename to patches/removed/1.17/No longer needed/0679-do-not-create-unnecessary-copies-of-passenger-list.patch index e8d0daacfc..cb84c8997d 100644 --- a/patches/server-remapped/0679-do-not-create-unnecessary-copies-of-passenger-list.patch +++ b/patches/removed/1.17/No longer needed/0679-do-not-create-unnecessary-copies-of-passenger-list.patch @@ -3,6 +3,7 @@ From: lukas81298 Date: Sun, 13 Dec 2020 13:42:55 +0100 Subject: [PATCH] do not create unnecessary copies of passenger list +1.17: Mojang removed the copy of the passenger list from getPassengers, no longer needed diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPassengersPacket.java index a6ecb82d14ccab5d8229689a2a6cb67c579b1f71..cded79352dff0978e0d633eae9d9020b4dec1d4b 100644 diff --git a/patches/server-remapped/0706-don-t-throw-when-loading-invalid-TEs.patch b/patches/removed/1.17/No longer needed/0706-don-t-throw-when-loading-invalid-TEs.patch similarity index 97% rename from patches/server-remapped/0706-don-t-throw-when-loading-invalid-TEs.patch rename to patches/removed/1.17/No longer needed/0706-don-t-throw-when-loading-invalid-TEs.patch index 487cbc3ff9..da8d3dfaa5 100644 --- a/patches/server-remapped/0706-don-t-throw-when-loading-invalid-TEs.patch +++ b/patches/removed/1.17/No longer needed/0706-don-t-throw-when-loading-invalid-TEs.patch @@ -3,6 +3,7 @@ From: Shane Freeder Date: Tue, 20 Apr 2021 01:15:04 +0100 Subject: [PATCH] don't throw when loading invalid TEs +1.17: Mojang catches the exception diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java index 05fa76c02ce61e26891ad995fe89e925ea086557..b7ebb213efd759253f0042f77e11f2a8102ea6ca 100644 diff --git a/patches/server-remapped/0677-Expose-Tracked-Players.patch b/patches/server-remapped/0677-Expose-Tracked-Players.patch deleted file mode 100644 index 7997af8fee..0000000000 --- a/patches/server-remapped/0677-Expose-Tracked-Players.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tom -Date: Fri, 26 Feb 2021 16:24:25 -0600 -Subject: [PATCH] Expose Tracked Players - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 87c719caf796f54296ff7e412548062e02af270e..ec30f886585d407fbd122e05107ebca44895c585 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -170,7 +170,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - -- ChunkMap.TrackedEntity tracker; // Paper -+ public ChunkMap.TrackedEntity tracker; // Paper package private -> public - public boolean collisionLoadChunks = false; // Paper - public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index d2d179cdef8129653983b01d94928ba83f64f644..ec8c7499662c0a810f1337ebc0fa24d2f3ca79e7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -16,6 +16,7 @@ import java.net.InetSocketAddress; - import java.net.SocketAddress; - import java.util.ArrayList; - import java.util.Collection; -+import java.util.Collections; // Paper - import java.util.HashMap; - import java.util.HashSet; - import java.util.LinkedHashMap; -@@ -2305,6 +2306,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - // Paper end - -+ // Paper start -+ @Override -+ public Set getTrackedPlayers() { -+ if (entity.tracker == null) { -+ return Collections.emptySet(); -+ } -+ -+ Set set = new HashSet<>(entity.tracker.seenBy.size()); -+ for (ServerPlayer entityPlayer : entity.tracker.seenBy) { -+ set.add(entityPlayer.getBukkitEntity().getPlayer()); -+ } -+ return set; -+ } -+ // Paper end -+ - // Spigot start - private final Player.Spigot spigot = new Player.Spigot() - { diff --git a/patches/server-remapped/0678-Remove-streams-from-SensorNearest.patch b/patches/server-remapped/0678-Remove-streams-from-SensorNearest.patch deleted file mode 100644 index f305e85937..0000000000 --- a/patches/server-remapped/0678-Remove-streams-from-SensorNearest.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Bjarne Koll -Date: Wed, 3 Mar 2021 12:48:48 +0100 -Subject: [PATCH] Remove streams from SensorNearest - -The behavioural nearby sensors are validated every tick on the entities -that registered the respective sensors and are therefore a good subject -to performance improvements. - -More specifically this commit replaces the Stream#filter usage with -ArrayList#removeIf as the removeIf method on an array list is heavily -optimized towards a single internal array re-allocation without any -further overhead on the removeIf call. - -The only negative of this change is the rather agressive diff these -patches introduce as the methods are basically being reimplemented -compared to the previous stream-based implementation. - -See: https://nipafx.dev/java-stream-performance/ - -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -index 91295b8501b1e9d60bf9a7e954ea7fbce9cdea7f..0cd5a19beeb6103dec454b9071cc2e40adf2d006 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -@@ -27,18 +27,16 @@ public class NearestItemSensor extends Sensor { - List list = world.getEntitiesOfClass(ItemEntity.class, entity.getBoundingBox().inflate(8.0D, 4.0D, 8.0D), (entityitem) -> { - return true; - }); -- -- entity.getClass(); -+ // Paper start - remove streams in favour of lists - list.sort(Comparator.comparingDouble(entity::distanceToSqr)); -- Stream stream = list.stream().filter((entityitem) -> { -- return entity.wantsToPickUp(entityitem.getItem()); -- }).filter((entityitem) -> { -- return entityitem.closerThan((Entity) entity, 9.0D); -- }); -- -- entity.getClass(); -- Optional optional = stream.filter(entity::hasLineOfSight).findFirst(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); -+ ItemEntity nearest = null; -+ for (ItemEntity entityItem : list) { -+ if (entity.wantsToPickUp(entityItem.getItem()) && entityItem.closerThan(entity, 9.0D) && entity.canSee(entityItem)) { -+ nearest = entityItem; -+ break; -+ } -+ } -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java -index bf38e8b465ae0f50e34b94e0d7830dfdc1be1d59..fa827377ef0ef7cb280d1d54e156e45579899e6c 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java -@@ -26,10 +26,12 @@ public class NearestLivingEntitySensor extends Sensor { - list.sort(Comparator.comparingDouble(entity::distanceToSqr)); - Brain behaviorcontroller = entity.getBrain(); - -- behaviorcontroller.setMemory(MemoryModuleType.MOBS, (Object) list); -- behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, list.stream().filter((entityliving1) -> { -- return doTick(entity, entityliving1); -- }).collect(Collectors.toList())); -+ behaviorcontroller.setMemory(MemoryModuleType.MOBS, list); // Paper - decompile error -+ // Paper start - remove streams in favour of lists -+ List visibleMobs = new java.util.ArrayList<>(list); -+ visibleMobs.removeIf(otherEntityLiving -> !Sensor.a(entity, otherEntityLiving)); -+ behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, visibleMobs); -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -index 41a9db2cc4af26baa7072b3c4cebc5357ff43301..fe7414293f144656a938de42524841592c9f40d4 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -@@ -26,22 +26,26 @@ public class PlayerSensor extends Sensor { - - @Override - protected void doTick(ServerLevel world, LivingEntity entity) { -- Stream stream = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((entityplayer) -> { -- return entity.closerThan((Entity) entityplayer, 16.0D); -- }); -+ // Paper start - remove streams in favour of lists -+ List players = new java.util.ArrayList<>(world.players()); -+ players.removeIf(player -> !EntitySelector.notSpectator().test(player) || !entity.closerThan(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator -+ players.sort(Comparator.comparingDouble(entity::distanceToSqr)); - -- entity.getClass(); -- List list = (List) stream.sorted(Comparator.comparingDouble(entity::h)).collect(Collectors.toList()); - Brain behaviorcontroller = entity.getBrain(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, (Object) list); -- List list1 = (List) list.stream().filter((entityhuman) -> { -- return doTick(entity, (LivingEntity) entityhuman); -- }).collect(Collectors.toList()); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, (Object) (list1.isEmpty() ? null : (Player) list1.get(0))); -- Optional optional = list1.stream().filter(EntitySelector.ATTACK_ALLOWED).findFirst(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, optional); -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); -+ -+ Player nearest = null, nearestTargetable = null; -+ for (Player player : players) { -+ if (Sensor.a(entity, player)) { -+ if (nearest == null) nearest = player; -+ if (EntitySelector.canAITarget().test(player)) { -+ nearestTargetable = player; -+ break; // Both variables are assigned, no reason to loop further -+ } -+ } -+ } -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, nearestTargetable); -+ // Paper end - } - } diff --git a/patches/server-remapped/0691-Implement-Keyed-on-World.patch b/patches/server-remapped/0691-Implement-Keyed-on-World.patch deleted file mode 100644 index 94fd5a3703..0000000000 --- a/patches/server-remapped/0691-Implement-Keyed-on-World.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 6 Jan 2021 00:34:04 -0800 -Subject: [PATCH] Implement Keyed on World - - -diff --git a/src/main/java/net/minecraft/core/Registry.java b/src/main/java/net/minecraft/core/Registry.java -index 5a98bc1522c2035487ce0a048c236903dbfa816e..4924d8cd3004a6e1ce76cd5cf7520556c23fe20a 100644 ---- a/src/main/java/net/minecraft/core/Registry.java -+++ b/src/main/java/net/minecraft/core/Registry.java -@@ -130,7 +130,7 @@ public abstract class Registry implements Codec, Keyable, IdMap { - public static final ResourceKey> LOOT_FUNCTION_REGISTRY = createRegistryKey("loot_function_type"); - public static final ResourceKey> LOOT_ITEM_REGISTRY = createRegistryKey("loot_condition_type"); - public static final ResourceKey> DIMENSION_TYPE_REGISTRY = createRegistryKey("dimension_type"); -- public static final ResourceKey> DIMENSION_REGISTRY = createRegistryKey("dimension"); -+ public static final ResourceKey> DIMENSION_REGISTRY = createRegistryKey("dimension"); public static final ResourceKey> getWorldRegistry() { return DIMENSION_REGISTRY; } // Paper - OBFHELPER - public static final ResourceKey> LEVEL_STEM_REGISTRY = createRegistryKey("dimension"); - public static final Registry SOUND_EVENT = registerSimple(Registry.SOUND_EVENT_REGISTRY, () -> { - return SoundEvents.ITEM_PICKUP; -@@ -339,9 +339,9 @@ public abstract class Registry implements Codec, Keyable, IdMap { - ResourceLocation minecraftkey = resourcekey.location(); - - Registry.LOADERS.put(minecraftkey, defaultEntry); -- WritableRegistry iregistrywritable = Registry.WRITABLE_REGISTRY; -+ WritableRegistry iregistrywritable = Registry.WRITABLE_REGISTRY; // Paper - decompile fix - -- return (WritableRegistry) iregistrywritable.register(resourcekey, (Object) registry, lifecycle); -+ return (R) iregistrywritable.register(resourcekey, (Object) registry, lifecycle); // Paper - decompile fix - } - - protected Registry(ResourceKey> key, Lifecycle lifecycle) { -@@ -428,11 +428,11 @@ public abstract class Registry implements Codec, Keyable, IdMap { - } - - public static T register(Registry registry, ResourceLocation id, T entry) { -- return ((WritableRegistry) registry).register(ResourceKey.create(registry.key, id), entry, Lifecycle.stable()); -+ return ((WritableRegistry) registry).register(ResourceKey.create(registry.key, id), entry, Lifecycle.stable()); // Paper - decompile fix - } - - public static T registerMapping(Registry registry, int rawId, String id, T entry) { -- return ((WritableRegistry) registry).registerMapping(rawId, ResourceKey.create(registry.key, new ResourceLocation(id)), entry, Lifecycle.stable()); -+ return ((WritableRegistry) registry).registerMapping(rawId, ResourceKey.create(registry.key, new ResourceLocation(id)), entry, Lifecycle.stable()); // Paper - decompile fix - } - - static { -diff --git a/src/main/java/net/minecraft/resources/ResourceKey.java b/src/main/java/net/minecraft/resources/ResourceKey.java -index 2f39438ee9b23706efb2fd877fe223777b6968c7..3085ec1f20f4c945242697b809188a8c828cfb75 100644 ---- a/src/main/java/net/minecraft/resources/ResourceKey.java -+++ b/src/main/java/net/minecraft/resources/ResourceKey.java -@@ -12,6 +12,7 @@ public class ResourceKey { - private final ResourceLocation registryName; - private final ResourceLocation location; - -+ public static ResourceKey newResourceKey(ResourceKey> registryKey, ResourceLocation minecraftKey) { return create(registryKey, minecraftKey); } // Paper - OBFHELPER - public static ResourceKey create(ResourceKey> registry, ResourceLocation value) { - return create(registry.location, value); - } -@@ -41,6 +42,7 @@ public class ResourceKey { - return this.registryName.equals(registry.location()); - } - -+ public ResourceLocation getLocation() { return location(); } // Paper - OBFHELPER - public ResourceLocation location() { - return this.location; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 794b894ed24636aec60de9a28ba7613d7a917324..6905256147d9bd79e5f52bf86bdb21c89b8411a7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1156,7 +1156,7 @@ public final class CraftServer implements Server { - } else if (name.equals(levelName + "_the_end")) { - worldKey = net.minecraft.world.level.Level.END; - } else { -- worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(name.toLowerCase(java.util.Locale.ENGLISH))); -+ worldKey = ResourceKey.newResourceKey(Registry.getWorldRegistry(), new net.minecraft.resources.ResourceLocation(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper - } - - ServerLevel internal = (ServerLevel) new ServerLevel(console, console.executor, worldSession, worlddata, worldKey, dimensionmanager, getServer().progressListenerFactory.create(11), -@@ -1246,6 +1246,15 @@ public final class CraftServer implements Server { - return null; - } - -+ // Paper start -+ @Override -+ public World getWorld(NamespacedKey worldKey) { -+ ServerLevel worldServer = console.getLevel(ResourceKey.newResourceKey(Registry.getWorldRegistry(), CraftNamespacedKey.toMinecraft(worldKey))); -+ if (worldServer == null) return null; -+ return worldServer.getWorld(); -+ } -+ // Paper end -+ - public void addWorld(World world) { - // Check if a World already exists with the UID. - if (getWorld(world.getUID()) != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index f497b9e11a075a84ff0a2117eb79d0532e4a326f..b0212b2043ee5fd77c8876ef0b51ef91488712f0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2566,6 +2566,11 @@ public class CraftWorld implements World { - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); - }, net.minecraft.server.MinecraftServer.getServer()); - } -+ -+ @Override -+ public org.bukkit.NamespacedKey getKey() { -+ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(world.dimension().getLocation()); -+ } - // Paper end - - // Spigot start diff --git a/patches/server-remapped/0693-Item-Rarity-API.patch b/patches/server-remapped/0693-Item-Rarity-API.patch deleted file mode 100644 index 51a841f551..0000000000 --- a/patches/server-remapped/0693-Item-Rarity-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 12 Mar 2021 17:09:42 -0800 -Subject: [PATCH] Item Rarity API - - -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 58400e84830c93675b0a1fe632be5e217c19a932..cb079bfd5339b96ad372b0a3b483d02cd0636bfd 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -45,7 +45,7 @@ public class Item implements ItemLike { - protected static final UUID BASE_ATTACK_SPEED_UUID = UUID.fromString("FA233E1C-4180-4865-B01B-BCCE9785ACA3"); - protected static final Random random = new Random(); - protected final CreativeModeTab category; -- private final Rarity rarity; -+ private final Rarity rarity; public final Rarity getItemRarity() { return rarity; } // Paper - OBFHELPER - private final int maxStackSize; - private final int maxDamage; - private final boolean isFireResistant; -@@ -209,6 +209,7 @@ public class Item implements ItemLike { - return stack.isEnchanted(); - } - -+ public Rarity getItemStackRarity(ItemStack itemStack) { return getRarity(itemStack); } // Paper - OBFHELPER - public Rarity getRarity(ItemStack stack) { - if (!stack.isEnchanted()) { - return this.rarity; -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 25a29d997f163ce2b11330d66a691601f514a9cb..472b0615dcdc3c0c52bd377fd69752716f354262 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -470,6 +470,20 @@ public final class CraftMagicNumbers implements UnsafeValues { - public int nextEntityId() { - return net.minecraft.world.entity.Entity.nextEntityId(); - } -+ -+ @Override -+ public io.papermc.paper.inventory.ItemRarity getItemRarity(org.bukkit.Material material) { -+ Item item = getItem(material); -+ if (item == null) { -+ throw new IllegalArgumentException(material + " is not an item, and rarity does not apply to blocks"); -+ } -+ return io.papermc.paper.inventory.ItemRarity.values()[item.getItemRarity().ordinal()]; -+ } -+ -+ @Override -+ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { -+ return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; -+ } - // Paper end - - /** diff --git a/patches/server-remapped/0699-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/patches/server-remapped/0699-Don-t-ignore-result-of-PlayerEditBookEvent.patch deleted file mode 100644 index 930a7a71e6..0000000000 --- a/patches/server-remapped/0699-Don-t-ignore-result-of-PlayerEditBookEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Mon, 5 Apr 2021 18:35:15 -0700 -Subject: [PATCH] Don't ignore result of PlayerEditBookEvent - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 1add53082ab9382cb2e90dc8305b8c71ef1c6a46..65afc23f4791aca19bff78ed86b3b0d31fa81977 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1144,7 +1144,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - list.stream().map(StringTag::valueOf).forEach(nbttaglist::add); - ItemStack old = itemstack.copy(); // CraftBukkit - itemstack.addTagElement("pages", (Tag) nbttaglist); -- CraftEventFactory.handleEditBookEvent(player, i, old, itemstack); // CraftBukkit -+ this.player.inventory.setItem(i, CraftEventFactory.handleEditBookEvent(player, i, old, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) - } - } - diff --git a/patches/server-remapped/0700-fix-cancelling-block-falling-causing-client-desync.patch b/patches/server-remapped/0700-fix-cancelling-block-falling-causing-client-desync.patch deleted file mode 100644 index 00cd7e5d6c..0000000000 --- a/patches/server-remapped/0700-fix-cancelling-block-falling-causing-client-desync.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sat, 27 Mar 2021 11:13:30 +0100 -Subject: [PATCH] fix cancelling block falling causing client desync - - -diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -index 2ba81e7179c7f9e2e1add1ad6bd6b96ee12c5da1..718e20f83a9b510c095d7e12241616cdce33d2d6 100644 ---- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -13,6 +13,7 @@ import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; - import net.minecraft.network.syncher.EntityDataAccessor; - import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.tags.BlockTags; - import net.minecraft.tags.FluidTags; - import net.minecraft.tags.Tag; -@@ -41,6 +42,7 @@ import net.minecraft.world.level.material.Fluids; - import net.minecraft.world.phys.BlockHitResult; - import net.minecraft.world.phys.HitResult; - import net.minecraft.world.phys.Vec3; -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit - - public class FallingBlockEntity extends Entity { -@@ -114,8 +116,18 @@ public class FallingBlockEntity extends Entity { - - if (this.time++ == 0) { - blockposition = this.blockPosition(); -- if (this.level.getBlockState(blockposition).is(block) && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { -- this.level.removeBlock(blockposition, false); -+ // Paper start - fix cancelling block falling causing client desync -+ if (this.level.getBlockState(blockposition).isSameInstance(block)) { -+ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { -+ if (this.level.getBlockState(blockposition).isSameInstance(block)) { //if listener didn't update the block -+ ((ServerLevel) level).getChunkSource().blockChanged(blockposition); -+ } -+ this.remove(); -+ return; -+ } else { -+ this.level.setAir(blockposition, false); -+ } -+ // Paper end - fix cancelling block falling causing client desync - } else if (!this.level.isClientSide) { - this.remove(); - return; -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index 17baae6b11f191f4738a107c7e62ea5bdac17a3c..32cda8c2e14cf8b218cb006a9b25330f0dab849a 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -682,6 +682,7 @@ public abstract class BlockBehaviour { - return this.getBlock().is(tag) && predicate.test(this); - } - -+ public final boolean isSameInstance(Block block) { return is(block); } // Paper - OBFHELPER - public boolean is(Block block) { - return this.getBlock().is(block); - } diff --git a/patches/server-remapped/0709-Fix-duplicating-give-items-on-item-drop-cancel.patch b/patches/server-remapped/0709-Fix-duplicating-give-items-on-item-drop-cancel.patch deleted file mode 100644 index 0672393254..0000000000 --- a/patches/server-remapped/0709-Fix-duplicating-give-items-on-item-drop-cancel.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alphaesia -Date: Fri, 23 Apr 2021 09:57:56 +1200 -Subject: [PATCH] Fix duplicating /give items on item drop cancel - -Fixes SPIGOT-2942 (Give command fires PlayerDropItemEvent, cancelling it causes item duplication). - -For every stack of items to give, /give puts the item stack straight -into the player's inventory. However, it also summons a "fake item" -at the player's location. When the PlayerDropItemEvent for this fake -item is cancelled, the server attempts to put the item back into the -player's inventory. The result is that the fake item, which is never -meant to be obtained, is combined with the real items injected directly -into the player's inventory. This means more items than the amount -specified in /give are given to the player - one for every stack of -items given. (e.g. /give @s dirt 1 gives you 2 dirt). - -While this isn't a big issue for general building usage, it can affect -e.g. adventure maps where the number of items the player receives is -important (and you want to restrict the player from throwing items). - -If there are any overflow items that didn't make it into the inventory -(insufficient space), those items are dropped as a real item instead -of a fake one. While cancelling this drop would also result in the -server attempting to put those items into the inventory, since it is -full this has no effect. - -Just ignoring cancellation of the PlayerDropItemEvent seems like the -cleanest and least intrusive way to fix it. - -diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java -index a6259e9160f291cf527a4ea5533a2e5530471874..3b8a7b9bdd2445afa93e4f2dc971a1d252c1463a 100644 ---- a/src/main/java/net/minecraft/server/commands/GiveCommand.java -+++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java -@@ -49,7 +49,7 @@ public class GiveCommand { - - if (flag && itemstack.isEmpty()) { - itemstack.setCount(1); -- entityitem = entityplayer.drop(itemstack, false); -+ entityitem = entityplayer.drop(itemstack, false, false, true); // Paper - Fix duplicating /give items on item drop cancel - if (entityitem != null) { - entityitem.makeFakeItem(); - } -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 4817b8ab259d348b48bc325d34ba9351ffe951df..cfb9bd6b9863a0f6f0f50181b7553adce90cfebe 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -639,7 +639,14 @@ public abstract class Player extends LivingEntity { - - @Nullable - public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership) { -- if (stack.isEmpty()) { -+ // Paper start - Fix duplicating /give items on item drop cancel -+ return this.drop(stack, throwRandomly, retainOwnership, false); -+ } -+ -+ @Nullable -+ public ItemEntity drop(ItemStack itemstack, boolean flag, boolean flag1, boolean alwaysSucceed) { -+ // Paper end -+ if (itemstack.isEmpty()) { - return null; - } else { - if (this.level.isClientSide) { -@@ -647,17 +654,17 @@ public abstract class Player extends LivingEntity { - } - - double d0 = this.getEyeY() - 0.30000001192092896D; -- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), d0, this.getZ(), stack); -+ ItemEntity entityitem = new ItemEntity(this.level, this.getX(), d0, this.getZ(), itemstack); - - entityitem.setPickUpDelay(40); -- if (retainOwnership) { -+ if (flag1) { - entityitem.setThrower(this.getUUID()); - } - - float f; - float f1; - -- if (throwRandomly) { -+ if (flag) { - f = this.random.nextFloat() * 0.5F; - f1 = this.random.nextFloat() * 6.2831855F; - entityitem.setDeltaMovement((double) (-Mth.sin(f1) * f), 0.20000000298023224D, (double) (Mth.cos(f1) * f)); -@@ -680,12 +687,12 @@ public abstract class Player extends LivingEntity { - PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); - this.level.getCraftServer().getPluginManager().callEvent(event); - -- if (event.isCancelled()) { -+ if (event.isCancelled() && !alwaysSucceed) { // Paper - Fix duplicating /give items on item drop cancel - org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); -- if (retainOwnership && (cur == null || cur.getAmount() == 0)) { -+ if (flag1 && (cur == null || cur.getAmount() == 0)) { - // The complete stack was dropped - player.getInventory().setItemInHand(drop.getItemStack()); -- } else if (retainOwnership && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { -+ } else if (flag1 && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { - // Only one item is dropped - cur.setAmount(cur.getAmount() + 1); - player.getInventory().setItemInHand(cur); -@@ -697,9 +704,9 @@ public abstract class Player extends LivingEntity { - } - // CraftBukkit end - // Paper start - remove player from map on drop -- if (stack.getItem() == Items.FILLED_MAP) { -- MapItemSavedData worldmap = MapItem.getOrCreateSavedData(stack, this.level); -- worldmap.updateSeenPlayers(this, stack); -+ if (itemstack.getItem() == Items.FILLED_MAP) { -+ MapItemSavedData worldmap = MapItem.getOrCreateSavedData(itemstack, this.level); -+ worldmap.updateSeenPlayers(this, itemstack); - } - // Paper end - diff --git a/patches/server-remapped/0714-fix-PlayerItemHeldEvent-firing-twice.patch b/patches/server-remapped/0714-fix-PlayerItemHeldEvent-firing-twice.patch deleted file mode 100644 index 094351a8ff..0000000000 --- a/patches/server-remapped/0714-fix-PlayerItemHeldEvent-firing-twice.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Thu, 22 Apr 2021 19:02:07 -0700 -Subject: [PATCH] fix PlayerItemHeldEvent firing twice - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java -index 68026536cfc26f07ca99ee9e76fd74b4ed4a995c..848fb02988b0fb319655f790112274ac2a437d25 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCarriedItemPacket.java -@@ -24,6 +24,7 @@ public class ServerboundSetCarriedItemPacket implements Packet= 0 && packet.getSlot() < Inventory.getSelectionSize()) { -+ if (packet.getItemInHandIndex() == this.player.inventory.selected) { return; } // Paper - don't fire itemheldevent when there wasn't a slot change - PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.selected, packet.getSlot()); - this.craftServer.getPluginManager().callEvent(event); - if (event.isCancelled()) { diff --git a/patches/server-remapped/0716-More-World-API.patch b/patches/server-remapped/0716-More-World-API.patch deleted file mode 100644 index 37cb7379d4..0000000000 --- a/patches/server-remapped/0716-More-World-API.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 7 Jul 2020 10:52:34 -0700 -Subject: [PATCH] More World API - - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index a7553a856b9c99bee8f75d514b97cfab952bfd33..511e6a941d441c55a4b38660f0f7f8c47fa689dd 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1863,6 +1863,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return !this.worldDataServer.worldGenSettings().generateFeatures() ? null : this.getChunkSource().getGenerator().findNearestMapFeature(this, feature, pos, radius, skipExistingChunks); // CraftBukkit - } - -+ public BlockPos getNearestBiome(Biome biomeBase, BlockPos blockPosition, int radius, int step) { return this.findNearestBiome(biomeBase, blockPosition, radius, step); } // Paper - OBFHELPER - @Nullable - public BlockPos findNearestBiome(Biome biome, BlockPos pos, int radius, int j) { - return this.getChunkSource().getGenerator().getBiomeSource().findBiomeHorizontal(pos.getX(), pos.getY(), pos.getZ(), radius, j, (biomebase1) -> { -@@ -1885,6 +1886,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return this.noSave; - } - -+ public RegistryAccess getWorldCustomRegistry() { return registryAccess(); } // Paper - OBFHELPER - @Override - public RegistryAccess registryAccess() { - return this.server.registryAccess(); -diff --git a/src/main/java/net/minecraft/world/level/dimension/DimensionType.java b/src/main/java/net/minecraft/world/level/dimension/DimensionType.java -index 7dead90a0d77e936816c2a54fe70c87d92dc8e5b..fb2bdfbeb44de6ce967af2deb4738972b44dcf44 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/DimensionType.java -+++ b/src/main/java/net/minecraft/world/level/dimension/DimensionType.java -@@ -142,10 +142,10 @@ public class DimensionType { - public static RegistryAccess.RegistryHolder registerBuiltin(RegistryAccess.RegistryHolder registryManager) { - WritableRegistry iregistrywritable = registryManager.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); - -- iregistrywritable.register(DimensionType.OVERWORLD_LOCATION, (Object) DimensionType.DEFAULT_OVERWORLD, Lifecycle.stable()); -- iregistrywritable.register(DimensionType.OVERWORLD_CAVES_LOCATION, (Object) DimensionType.DEFAULT_OVERWORLD_CAVES, Lifecycle.stable()); -- iregistrywritable.register(DimensionType.NETHER_LOCATION, (Object) DimensionType.DEFAULT_NETHER, Lifecycle.stable()); -- iregistrywritable.register(DimensionType.END_LOCATION, (Object) DimensionType.DEFAULT_END, Lifecycle.stable()); -+ iregistrywritable.register(DimensionType.OVERWORLD_LOCATION, DimensionType.DEFAULT_OVERWORLD, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.register(DimensionType.OVERWORLD_CAVES_LOCATION, DimensionType.DEFAULT_OVERWORLD_CAVES, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.register(DimensionType.NETHER_LOCATION, DimensionType.DEFAULT_NETHER, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.register(DimensionType.END_LOCATION, DimensionType.DEFAULT_END, Lifecycle.stable()); // Paper - decompile fix - return registryManager; - } - -@@ -164,10 +164,10 @@ public class DimensionType { - public static MappedRegistry defaultDimensions(Registry dimensionRegistry, Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed) { - MappedRegistry registrymaterials = new MappedRegistry<>(Registry.LEVEL_STEM_REGISTRY, Lifecycle.experimental()); - -- registrymaterials.register(LevelStem.NETHER, (Object) (new LevelStem(() -> { -+ registrymaterials.register(LevelStem.NETHER, (new LevelStem(() -> { // Paper - decompile fix - return (DimensionType) dimensionRegistry.getOrThrow(DimensionType.NETHER_LOCATION); - }, defaultNetherGenerator(biomeRegistry, chunkGeneratorSettingsRegistry, seed))), Lifecycle.stable()); -- registrymaterials.register(LevelStem.END, (Object) (new LevelStem(() -> { -+ registrymaterials.register(LevelStem.END, (new LevelStem(() -> { // Paper - decompile fix - return (DimensionType) dimensionRegistry.getOrThrow(DimensionType.END_LOCATION); - }, defaultEndGenerator(biomeRegistry, chunkGeneratorSettingsRegistry, seed))), Lifecycle.stable()); - return registrymaterials; -@@ -256,6 +256,7 @@ public class DimensionType { - return this.brightnessRamp[i]; - } - -+ public Tag getInfiniburnTag() { return infiniburn(); } // Paper - OBFHELPER - public Tag infiniburn() { - Tag tag = BlockTags.getAllTags().getTag(this.infiniburn); - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index b44e83d93bba579e439b93e5093350675137b070..a1fa2d5e00bd125abd38a00e0bc3936f2fb8186f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2515,6 +2515,75 @@ public class CraftWorld implements World { - return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); - } - -+ // Paper start -+ @Override -+ public Location locateNearestBiome(Location origin, Biome biome, int radius) { -+ return this.locateNearestBiome(origin, biome, radius, 8); -+ } -+ -+ @Override -+ public Location locateNearestBiome(Location origin, Biome biome, int radius, int step) { -+ BlockPos originPos = new BlockPos(origin.getX(), origin.getY(), origin.getZ()); -+ BlockPos nearest = getHandle().getNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().getWorldCustomRegistry().registryOrThrow(Registry.BIOME_REGISTRY), biome), originPos, radius, step); -+ return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); -+ } -+ -+ @Override -+ public boolean isUltrawarm() { -+ return getHandle().dimensionType().ultraWarm(); -+ } -+ -+ @Override -+ public boolean isNatural() { -+ return getHandle().dimensionType().natural(); -+ } -+ -+ @Override -+ public double getCoordinateScale() { -+ return getHandle().dimensionType().coordinateScale(); -+ } -+ -+ @Override -+ public boolean hasSkylight() { -+ return getHandle().dimensionType().hasSkyLight(); -+ } -+ -+ @Override -+ public boolean hasBedrockCeiling() { -+ return getHandle().dimensionType().hasSkyLight(); -+ } -+ -+ @Override -+ public boolean isPiglinSafe() { -+ return getHandle().dimensionType().piglinSafe(); -+ } -+ -+ @Override -+ public boolean doesBedWork() { -+ return getHandle().dimensionType().bedWorks(); -+ } -+ -+ @Override -+ public boolean doesRespawnAnchorWork() { -+ return getHandle().dimensionType().respawnAnchorWorks(); -+ } -+ -+ @Override -+ public boolean hasRaids() { -+ return getHandle().dimensionType().hasRaids(); -+ } -+ -+ @Override -+ public boolean isFixedTime() { -+ return getHandle().dimensionType().hasFixedTime(); -+ } -+ -+ @Override -+ public Collection getInfiniburn() { -+ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().dimensionType().getInfiniburnTag().getTagged().iterator(), CraftMagicNumbers::getMaterial)); -+ } -+ // Paper end -+ - @Override - public Raid locateNearestRaid(Location location, int radius) { - Validate.notNull(location, "Location cannot be null"); diff --git a/patches/server-remapped/0726-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/server-remapped/0726-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch deleted file mode 100644 index 9006bd8edb..0000000000 --- a/patches/server-remapped/0726-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alvinn8 <42838560+Alvinn8@users.noreply.github.com> -Date: Fri, 8 Jan 2021 20:31:13 +0100 -Subject: [PATCH] Add Adventure message to PlayerAdvancementDoneEvent - - -diff --git a/src/main/java/net/minecraft/advancements/Advancement.java b/src/main/java/net/minecraft/advancements/Advancement.java -index 9d27b658d32297337fb367bae628a1cc3a78712a..4abbe45237667c08753c040ef1281af1b2f34f88 100644 ---- a/src/main/java/net/minecraft/advancements/Advancement.java -+++ b/src/main/java/net/minecraft/advancements/Advancement.java -@@ -76,6 +76,7 @@ public class Advancement { - return this.parent; - } - -+ public final @Nullable DisplayInfo getAdvancementDisplay() { return this.getDisplay(); } // Paper - OBFHELPER - @Nullable - public DisplayInfo getDisplay() { - return this.display; -@@ -125,6 +126,7 @@ public class Advancement { - return this.requirements; - } - -+ public final Component getChatComponent() { return this.getChatComponent(); } // Paper - OBFHELPER - public Component getChatComponent() { - return this.chatComponent; - } -diff --git a/src/main/java/net/minecraft/advancements/DisplayInfo.java b/src/main/java/net/minecraft/advancements/DisplayInfo.java -index 2bcf14826ec1c6a1654246844d03184ceae55d79..1b41578fed1da6d15a806a7200e53954f608b625 100644 ---- a/src/main/java/net/minecraft/advancements/DisplayInfo.java -+++ b/src/main/java/net/minecraft/advancements/DisplayInfo.java -@@ -54,10 +54,12 @@ public class DisplayInfo { - return this.description; - } - -+ public final FrameType getFrameType() { return this.getFrame(); } // Paper - OBFHELPER - public FrameType getFrame() { - return this.frame; - } - -+ public final boolean shouldAnnounceToChat() { return this.shouldAnnounceChat(); } // Paper - OBFHELPER - public boolean shouldAnnounceChat() { - return this.announceChat; - } -diff --git a/src/main/java/net/minecraft/advancements/FrameType.java b/src/main/java/net/minecraft/advancements/FrameType.java -index 0ccac480a760259412b525e66c43de3a209543f5..f6d4b876bdd25942763780f17c8bb69ac3d56031 100644 ---- a/src/main/java/net/minecraft/advancements/FrameType.java -+++ b/src/main/java/net/minecraft/advancements/FrameType.java -@@ -20,6 +20,7 @@ public enum FrameType { - this.displayName = new TranslatableComponent("advancements.toast." + s); - } - -+ public final String getId() { return this.getName(); } // Paper - OBFHELPER - public String getName() { - return this.name; - } -diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java -index b8d3f2c59199e245e2035d6205dd1a042aa93f77..fcb59f6538e66fa43d11d4998e6eeac2e33b0393 100644 ---- a/src/main/java/net/minecraft/server/PlayerAdvancements.java -+++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java -@@ -51,6 +51,7 @@ import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.GameRules; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - - public class PlayerAdvancements { - -@@ -313,10 +314,18 @@ public class PlayerAdvancements { - this.progressChanged.add(advancement); - flag = true; - if (!flag1 && advancementprogress.isDone()) { -- this.player.level.getCraftServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit)); // CraftBukkit -+ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent -+ boolean announceToChat = advancement.getAdvancementDisplay() != null && advancement.getAdvancementDisplay().shouldAnnounceToChat(); -+ net.kyori.adventure.text.Component message = announceToChat ? PaperAdventure.asAdventure(new TranslatableComponent("chat.type.advancement." + advancement.getAdvancementDisplay().getFrameType().getId(), this.player.getDisplayName(), advancement.getChatComponent())) : null; -+ org.bukkit.event.player.PlayerAdvancementDoneEvent event = new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit, message); -+ this.player.level.getCraftServer().getPluginManager().callEvent(event); -+ message = event.message(); -+ // Paper end - advancement.getRewards().a(this.player); -- if (advancement.getDisplay() != null && advancement.getDisplay().shouldAnnounceChat() && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { -- this.playerList.broadcastMessage(new TranslatableComponent("chat.type.advancement." + advancement.getDisplay().getFrame().getName(), new Object[]{this.player.getDisplayName(), advancement.getChatComponent()}), ChatType.SYSTEM, Util.NIL_UUID); -+ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent -+ if (message != null && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { -+ this.playerList.broadcastMessage(PaperAdventure.asVanilla(message), ChatType.SYSTEM, Util.getNullUUID()); -+ // Paper end - } - } - } diff --git a/patches/server-remapped/0732-Add-basic-Datapack-API.patch b/patches/server-remapped/0732-Add-basic-Datapack-API.patch deleted file mode 100644 index 547e7cb557..0000000000 --- a/patches/server-remapped/0732-Add-basic-Datapack-API.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Sun, 16 May 2021 15:07:34 +0100 -Subject: [PATCH] Add basic Datapack API - - -diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java -new file mode 100644 -index 0000000000000000000000000000000000000000..66debefcd474e4dcc2a8889a82af6c1809c93f46 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java -@@ -0,0 +1,51 @@ -+package io.papermc.paper.datapack; -+ -+import Compatibility; -+import io.papermc.paper.event.server.ServerResourcesReloadedEvent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.packs.repository.Pack; -+import java.util.List; -+import java.util.stream.Collectors; -+ -+public class PaperDatapack implements Datapack { -+ private final String name; -+ private final Compatibility compatibility; -+ private final boolean enabled; -+ -+ PaperDatapack(Pack loader, boolean enabled) { -+ this.name = loader.getName(); -+ this.compatibility = Compatibility.valueOf(loader.getVersion().name()); -+ this.enabled = enabled; -+ } -+ -+ @Override -+ public String getName() { -+ return name; -+ } -+ -+ @Override -+ public Compatibility getCompatibility() { -+ return compatibility; -+ } -+ -+ @Override -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @Override -+ public void setEnabled(boolean enabled) { -+ if (enabled == this.enabled) { -+ return; -+ } -+ -+ MinecraftServer server = MinecraftServer.getServer(); -+ List enabledKeys = server.getPackRepository().getEnabledPacks().stream().map(Pack::getName).collect(Collectors.toList()); -+ if (enabled) { -+ enabledKeys.add(this.name); -+ } else { -+ enabledKeys.remove(this.name); -+ } -+ server.reloadServerResources(enabledKeys, ServerResourcesReloadedEvent.Cause.PLUGIN); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ec221183bef1065bda0a37e1025958df0d1f6318 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java -@@ -0,0 +1,25 @@ -+package io.papermc.paper.datapack; -+ -+import java.util.Collection; -+import java.util.stream.Collectors; -+import net.minecraft.server.packs.repository.Pack; -+import net.minecraft.server.packs.repository.PackRepository; -+ -+public class PaperDatapackManager implements DatapackManager { -+ private final PackRepository repository; -+ -+ public PaperDatapackManager(PackRepository repository) { -+ this.repository = repository; -+ } -+ -+ @Override -+ public Collection getPacks() { -+ Collection enabledPacks = repository.getEnabledPacks(); -+ return repository.getPacks().stream().map(loader -> new PaperDatapack(loader, enabledPacks.contains(loader))).collect(Collectors.toList()); -+ } -+ -+ @Override -+ public Collection getEnabledPacks() { -+ return repository.getEnabledPacks().stream().map(loader -> new PaperDatapack(loader, true)).collect(Collectors.toList()); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/packs/repository/Pack.java b/src/main/java/net/minecraft/server/packs/repository/Pack.java -index df5d258b80e37077fa236e4190ad934853c88619..4120326e0d047347e5d7ab9521babe7bb6b6a7db 100644 ---- a/src/main/java/net/minecraft/server/packs/repository/Pack.java -+++ b/src/main/java/net/minecraft/server/packs/repository/Pack.java -@@ -101,6 +101,7 @@ public class Pack implements AutoCloseable { - }); - } - -+ public final PackCompatibility getVersion() { return this.getCompatibility(); } // Paper - OBFHELPER - public PackCompatibility getCompatibility() { - return this.compatibility; - } -@@ -109,6 +110,7 @@ public class Pack implements AutoCloseable { - return (PackResources) this.supplier.get(); - } - -+ public final String getName() { return this.getId(); } // Paper - OBFHELPER - public String getId() { - return this.id; - } -diff --git a/src/main/java/net/minecraft/server/packs/repository/PackRepository.java b/src/main/java/net/minecraft/server/packs/repository/PackRepository.java -index bce2fd67048bd1fd53865eef81bac262dbda2865..8d0ef3bdf9fa283f54628800768717181df28aa5 100644 ---- a/src/main/java/net/minecraft/server/packs/repository/PackRepository.java -+++ b/src/main/java/net/minecraft/server/packs/repository/PackRepository.java -@@ -88,6 +88,7 @@ public class PackRepository implements AutoCloseable { - return this.available.keySet(); - } - -+ public final Collection getPacks() { return this.getAvailablePacks(); } // Paper - OBFHELPER - public Collection getAvailablePacks() { - return this.available.values(); - } -@@ -96,6 +97,7 @@ public class PackRepository implements AutoCloseable { - return (Collection) this.selected.stream().map(Pack::getId).collect(ImmutableSet.toImmutableSet()); - } - -+ public final Collection getEnabledPacks() { return this.getSelectedPacks(); } // Paper - OBFHELPER - public Collection getSelectedPacks() { - return this.selected; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6905256147d9bd79e5f52bf86bdb21c89b8411a7..63639923f7875d76f569b8c6e958782c6462d906 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -18,6 +18,7 @@ import com.mojang.serialization.Lifecycle; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.datapack.PaperDatapackManager; // Paper - import io.papermc.paper.util.TraceUtil; - import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; - import java.awt.image.BufferedImage; -@@ -264,6 +265,7 @@ public final class CraftServer implements Server { - public boolean ignoreVanillaPermissions = false; - private final List playerView; - public int reloadCount; -+ private final PaperDatapackManager datapackManager; // Paper - public static Exception excessiveVelEx; // Paper - Velocity warnings - - static { -@@ -346,6 +348,7 @@ public final class CraftServer implements Server { - TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - loadIcon(); -+ datapackManager = new PaperDatapackManager(console.getPackRepository()); // Paper - } - - public boolean getCommandBlockOverride(String command) { -@@ -2496,5 +2499,11 @@ public final class CraftServer implements Server { - public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { - return mobGoals; - } -+ -+ @Override -+ public PaperDatapackManager getDatapackManager() { -+ return datapackManager; -+ } -+ - // Paper end - } diff --git a/patches/server-remapped/0734-additions-to-PlayerGameModeChangeEvent.patch b/patches/server-remapped/0734-additions-to-PlayerGameModeChangeEvent.patch deleted file mode 100644 index 31a8669378..0000000000 --- a/patches/server-remapped/0734-additions-to-PlayerGameModeChangeEvent.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 10:04:43 -0700 -Subject: [PATCH] additions to PlayerGameModeChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java -index c0098a8f8a9fa2671ff66cbcf50ac74b057d1446..ebbd6f2b0e7236b33d136ab2218c8eca4c5df03e 100644 ---- a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java -+++ b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java -@@ -43,7 +43,13 @@ public class DefaultGameModeCommands { - ServerPlayer entityplayer = (ServerPlayer) iterator.next(); - - if (entityplayer.gameMode.getGameModeForPlayer() != defaultGameMode) { -- entityplayer.setGameMode(defaultGameMode); -+ // Paper start - handle event cancelling the change -+ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(defaultGameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getScoreboardName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); -+ if (event != null && event.isCancelled()) { -+ source.sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); -+ continue; -+ } -+ // Paper end - ++i; - } - } -diff --git a/src/main/java/net/minecraft/server/commands/GameModeCommand.java b/src/main/java/net/minecraft/server/commands/GameModeCommand.java -index 3e999090fb3b03b996a9790c53e5b4618c8891f7..3b17c81167f8e011e7f9c09bf42eb632f5a3c2f2 100644 ---- a/src/main/java/net/minecraft/server/commands/GameModeCommand.java -+++ b/src/main/java/net/minecraft/server/commands/GameModeCommand.java -@@ -62,13 +62,13 @@ public class GameModeCommand { - ServerPlayer entityplayer = (ServerPlayer) iterator.next(); - - if (entityplayer.gameMode.getGameModeForPlayer() != gameMode) { -- entityplayer.setGameMode(gameMode); -- // CraftBukkit start - handle event cancelling the change -- if (entityplayer.gameMode.getGameModeForPlayer() != gameMode) { -- context.getSource().sendFailure(new net.minecraft.network.chat.TextComponent("Failed to set the gamemode of '" + entityplayer.getScoreboardName() + "'")); -+ // Paper start - handle event cancelling the change -+ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getScoreboardName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); -+ if (event != null && event.isCancelled()) { -+ context.getSource().sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); - continue; - } -- // CraftBukkit end -+ // Paper end - logGamemodeChange((CommandSourceStack) context.getSource(), entityplayer, gameMode); - ++i; - } -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 5d710a1f4e0c61d4be6efe8cebd9b80789868338..779b926921fd435620cbbc69ed6f9931a422b652 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -393,7 +393,16 @@ public class ServerPlayer extends Player implements ContainerListener { - if (this.getY() > 300) this.setPosRaw(getX(), 257, getZ()); // Paper - bring down to a saner Y level if out of world - if (tag.contains("playerGameType", 99)) { - if (this.getServer().getForceGameType()) { -+ // Paper start - call PlayerGameModeChangeEvent on join for players that do not have the correct gamemode -+ if (this.getServer().getDefaultGameType() != GameType.byId(tag.getInt("playerGameType"))) { -+ if (new org.bukkit.event.player.PlayerGameModeChangeEvent(this.getBukkitEntity(), GameMode.getByValue(this.getServer().getDefaultGameType().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) { - this.gameMode.setGameModeForPlayer(this.getServer().getDefaultGameType(), GameType.NOT_SET); -+ } else { -+ this.gameMode.setGameModeForPlayer(GameType.byId(tag.getInt("playerGameType")), tag.contains("previousPlayerGameType", 3) ? GameType.byId(tag.getInt("previousPlayerGameType")) : GameType.NOT_SET); // copied from below; if cancelled, set gamemode normally -+ } -+ } else { -+ this.gameMode.setGameModeForPlayer(GameType.byId(tag.getInt("playerGameType")), tag.contains("previousPlayerGameType", 3) ? GameType.byId(tag.getInt("previousPlayerGameType")) : GameType.NOT_SET); // copied from below; if no change needed, set gamemode normally -+ } // Paper end - } else { - this.gameMode.setGameModeForPlayer(GameType.byId(tag.getInt("playerGameType")), tag.contains("previousPlayerGameType", 3) ? GameType.byId(tag.getInt("previousPlayerGameType")) : GameType.NOT_SET); - } -@@ -1789,21 +1798,27 @@ public class ServerPlayer extends Player implements ContainerListener { - - @Override - public void setGameMode(GameType gameMode) { -+ // Paper start - Add cause and nullable message to event -+ setGamemode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null); -+ } -+ -+ public PlayerGameModeChangeEvent setGamemode(GameType enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component message) { -+ // Paper end - // CraftBukkit start -- if (gameMode == this.gameMode.getGameModeForPlayer()) { -- return; -+ if (enumgamemode == this.gameMode.getGameModeForPlayer()) { -+ return null; // Paper - } - -- PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(gameMode.getId())); -+ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(enumgamemode.getId()), cause, message); // Paper - level.getCraftServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { -- return; -+ return event; // Paper - } - // CraftBukkit end - -- this.gameMode.setGameModeForPlayer(gameMode); -- this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) gameMode.getId())); -- if (gameMode == GameType.SPECTATOR) { -+ this.gameMode.setGameModeForPlayer(enumgamemode); -+ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) enumgamemode.getId())); -+ if (enumgamemode == GameType.SPECTATOR) { - this.removeEntitiesOnShoulder(); - this.stopRiding(); - } else { -@@ -1812,6 +1827,7 @@ public class ServerPlayer extends Player implements ContainerListener { - - this.onUpdateAbilities(); - this.updateEffectVisibility(); -+ return event; // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index a0e69cac7699ddc318057c8016e329850d3baa26..c454908f23a436f66f8e64fc346186f113b6eefb 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2449,7 +2449,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - this.player = this.server.getPlayerList().respawn(this.player, false); - if (this.server.isHardcore()) { -- this.player.setGameMode(GameType.SPECTATOR); -+ this.player.setGamemode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper - ((GameRules.BooleanValue) this.player.getLevel().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, this.server); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ec8c7499662c0a810f1337ebc0fa24d2f3ca79e7..3dbe94d9b9647f5cc1e27335b36042e50c652cea 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1189,7 +1189,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - throw new IllegalArgumentException("Mode cannot be null"); - } - -- getHandle().setGameMode(GameType.byId(mode.getValue())); -+ getHandle().setGamemode(GameType.byId(mode.getValue()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.PLUGIN, null); // Paper - } - - @Override diff --git a/patches/server-remapped/0741-Add-Mob-lookAt-API.patch b/patches/server-remapped/0741-Add-Mob-lookAt-API.patch deleted file mode 100644 index ce42177784..0000000000 --- a/patches/server-remapped/0741-Add-Mob-lookAt-API.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 14 May 2021 13:42:17 -0500 -Subject: [PATCH] Add Mob#lookAt API - - -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index ea34306858116e5626383af408529091836c2752..5692b497875ba2ee455859bc8a88d7888afd86fc 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -850,14 +850,17 @@ public abstract class Mob extends LivingEntity { - - protected void customServerAiStep() {} - -+ public int getMaxHeadXRot() { return getMaxHeadXRot(); } // Paper - OBFHELPER - public int getMaxHeadXRot() { - return 40; - } - -+ public int getMaxHeadYRot() { return getMaxHeadYRot(); } // Paper - OBFHELPER - public int getMaxHeadYRot() { - return 75; - } - -+ public int getHeadRotSpeed() { return getHeadRotSpeed(); } // Paper - OBFHELPER - public int getHeadRotSpeed() { - return 10; - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java b/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java -index faba4a95883bb0fcfd4f65c3f62bd6f476ded249..3fe159c4bdc3ad3e95354e18e2921305af121725 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/LookControl.java -@@ -20,18 +20,28 @@ public class LookControl { - this.mob = entity; - } - -+ public void lookAt(Vec3 vec3d) { setLookAt(vec3d); } // Paper - OBFHELPER - public void setLookAt(Vec3 direction) { - this.setLookAt(direction.x, direction.y, direction.z); - } - -+ // Paper start -+ public void lookAt(Entity entity) { -+ this.lookAt(entity.getX(), getWantedY(entity), entity.getZ()); -+ } -+ // Paper end -+ -+ public void lookAt(Entity entity, float f, float f1) { setLookAt(entity, f, f1); } // Paper - OBFHELPER - public void setLookAt(Entity entity, float yawSpeed, float pitchSpeed) { - this.setLookAt(entity.getX(), getWantedY(entity), entity.getZ(), yawSpeed, pitchSpeed); - } - -+ public void lookAt(double d0, double d1, double d2) { setLookAt(d0, d1, d2); } // Paper - OBFHELPER - public void setLookAt(double x, double y, double z) { - this.setLookAt(x, y, z, (float) this.mob.getHeadRotSpeed(), (float) this.mob.getMaxHeadXRot()); - } - -+ public void lookAt(double d0, double d1, double d2, float f, float f1) { setLookAt(d0, d1, d2, f, f1); } // Paper - OBFHELPER - public void setLookAt(double x, double y, double z, float yawSpeed, float pitchSpeed) { - this.wantedX = x; - this.wantedY = y; -@@ -103,6 +113,7 @@ public class LookControl { - return from + f4; - } - -+ public static double getWantedY(Entity entity) { return getWantedY(entity); } // Paper - OBFHELPER - private static double getWantedY(Entity entity) { - return entity instanceof LivingEntity ? entity.getEyeY() : (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0D; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index 1e3a0851c75d8067d2699f00bb3f6621d1d739d8..f597cf70779fde265cc45868aba3ae9db898fb6e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -83,5 +83,53 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { - public boolean isInDaylight() { - return getHandle().isInDaylight(); - } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location) { -+ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); -+ getHandle().getLookControl().lookAt(location.getX(), location.getY(), location.getZ()); -+ } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location, float headRotationSpeed, float maxHeadPitch) { -+ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); -+ getHandle().getLookControl().lookAt(location.getX(), location.getY(), location.getZ(), headRotationSpeed, maxHeadPitch); -+ } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity) { -+ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); -+ getHandle().getLookControl().lookAt(((CraftEntity) entity).getHandle()); -+ } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity, float headRotationSpeed, float maxHeadPitch) { -+ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); -+ getHandle().getLookControl().lookAt(((CraftEntity) entity).getHandle(), headRotationSpeed, maxHeadPitch); -+ } -+ -+ @Override -+ public void lookAt(double x, double y, double z) { -+ getHandle().getLookControl().lookAt(x, y, z); -+ } -+ -+ @Override -+ public void lookAt(double x, double y, double z, float headRotationSpeed, float maxHeadPitch) { -+ getHandle().getLookControl().lookAt(x, y, z, headRotationSpeed, maxHeadPitch); -+ } -+ -+ @Override -+ public int getHeadRotationSpeed() { -+ return getHandle().getHeadRotSpeed(); -+ } -+ -+ @Override -+ public int getMaxHeadPitch() { -+ return getHandle().getMaxHeadXRot(); -+ } - // Paper end - } diff --git a/patches/server/0468-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server/0469-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch similarity index 100% rename from patches/server/0468-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch rename to patches/server/0469-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch diff --git a/patches/server/0469-Remove-streams-from-classes-related-villager-gossip.patch b/patches/server/0470-Remove-streams-from-classes-related-villager-gossip.patch similarity index 100% rename from patches/server/0469-Remove-streams-from-classes-related-villager-gossip.patch rename to patches/server/0470-Remove-streams-from-classes-related-villager-gossip.patch diff --git a/patches/server/0470-Support-components-in-ItemMeta.patch b/patches/server/0471-Support-components-in-ItemMeta.patch similarity index 100% rename from patches/server/0470-Support-components-in-ItemMeta.patch rename to patches/server/0471-Support-components-in-ItemMeta.patch diff --git a/patches/server/0471-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/patches/server/0472-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch similarity index 100% rename from patches/server/0471-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch rename to patches/server/0472-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch diff --git a/patches/server/0472-Add-entity-liquid-API.patch b/patches/server/0473-Add-entity-liquid-API.patch similarity index 100% rename from patches/server/0472-Add-entity-liquid-API.patch rename to patches/server/0473-Add-entity-liquid-API.patch diff --git a/patches/server/0473-Update-itemstack-legacy-name-and-lore.patch b/patches/server/0474-Update-itemstack-legacy-name-and-lore.patch similarity index 100% rename from patches/server/0473-Update-itemstack-legacy-name-and-lore.patch rename to patches/server/0474-Update-itemstack-legacy-name-and-lore.patch diff --git a/patches/server/0474-Spawn-player-in-correct-world-on-login.patch b/patches/server/0475-Spawn-player-in-correct-world-on-login.patch similarity index 94% rename from patches/server/0474-Spawn-player-in-correct-world-on-login.patch rename to patches/server/0475-Spawn-player-in-correct-world-on-login.patch index 2de440c5aa..dbde21b12c 100644 --- a/patches/server/0474-Spawn-player-in-correct-world-on-login.patch +++ b/patches/server/0475-Spawn-player-in-correct-world-on-login.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Spawn player in correct world on login diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7eb3088d47ff78198e01a3a12b0ce6abe9d6ca6b..66735bbc2528c5812c9df14ef7cd91cb69d903b2 100644 +index 9c13479d2a508728c10803dee719ed7ad097e019..56b33bcd93cd4e8b448271edee497b7c3c9b246a 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -193,7 +193,18 @@ public abstract class PlayerList { diff --git a/patches/server/0475-Add-PrepareResultEvent.patch b/patches/server/0476-Add-PrepareResultEvent.patch similarity index 100% rename from patches/server/0475-Add-PrepareResultEvent.patch rename to patches/server/0476-Add-PrepareResultEvent.patch diff --git a/patches/server/0476-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/0477-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 100% rename from patches/server/0476-Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/server/0477-Allow-delegation-to-vanilla-chunk-gen.patch diff --git a/patches/server/0477-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server/0478-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch similarity index 100% rename from patches/server/0477-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch rename to patches/server/0478-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch diff --git a/patches/server/0478-Optimize-NetworkManager-Exception-Handling.patch b/patches/server/0479-Optimize-NetworkManager-Exception-Handling.patch similarity index 100% rename from patches/server/0478-Optimize-NetworkManager-Exception-Handling.patch rename to patches/server/0479-Optimize-NetworkManager-Exception-Handling.patch diff --git a/patches/server/0479-Optimize-the-advancement-data-player-iteration-to-be.patch b/patches/server/0480-Optimize-the-advancement-data-player-iteration-to-be.patch similarity index 100% rename from patches/server/0479-Optimize-the-advancement-data-player-iteration-to-be.patch rename to patches/server/0480-Optimize-the-advancement-data-player-iteration-to-be.patch diff --git a/patches/server/0480-Fix-arrows-never-despawning-MC-125757.patch b/patches/server/0481-Fix-arrows-never-despawning-MC-125757.patch similarity index 100% rename from patches/server/0480-Fix-arrows-never-despawning-MC-125757.patch rename to patches/server/0481-Fix-arrows-never-despawning-MC-125757.patch diff --git a/patches/server/0481-Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server/0482-Thread-Safe-Vanilla-Command-permission-checking.patch similarity index 100% rename from patches/server/0481-Thread-Safe-Vanilla-Command-permission-checking.patch rename to patches/server/0482-Thread-Safe-Vanilla-Command-permission-checking.patch diff --git a/patches/server/0482-Move-range-check-for-block-placing-up.patch b/patches/server/0483-Move-range-check-for-block-placing-up.patch similarity index 94% rename from patches/server/0482-Move-range-check-for-block-placing-up.patch rename to patches/server/0483-Move-range-check-for-block-placing-up.patch index 344b1912e1..4614ed8f8f 100644 --- a/patches/server/0482-Move-range-check-for-block-placing-up.patch +++ b/patches/server/0483-Move-range-check-for-block-placing-up.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Move range check for block placing up diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 39777c2b1bbb12ce3e5be3724235ea0a8072cef8..99a16a2f0c2dc227dd45db1964c2d47ffdcda73e 100644 +index 2b8a9d16add3ac81ede029a909a40feaa07c51d3..afd5f5efdd6b47811fdbc23adeacace594602046 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1693,17 +1693,21 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -1694,17 +1694,21 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser BlockPos blockposition = movingobjectpositionblock.getBlockPos(); Direction enumdirection = movingobjectpositionblock.getDirection(); diff --git a/patches/server/0483-Fix-SPIGOT-5989.patch b/patches/server/0484-Fix-SPIGOT-5989.patch similarity index 91% rename from patches/server/0483-Fix-SPIGOT-5989.patch rename to patches/server/0484-Fix-SPIGOT-5989.patch index a31cd6ebb9..22c038b591 100644 --- a/patches/server/0483-Fix-SPIGOT-5989.patch +++ b/patches/server/0484-Fix-SPIGOT-5989.patch @@ -10,7 +10,7 @@ This fixes that by checking if the modified spawn location is still at a respawn anchor. diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 66735bbc2528c5812c9df14ef7cd91cb69d903b2..9c594c0f142ca10b7c1df50faf45ccb3f7468ba9 100644 +index 56b33bcd93cd4e8b448271edee497b7c3c9b246a..0528099611eca136722507cacbd8ba6a668778b8 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -77,6 +77,7 @@ import net.minecraft.world.level.GameRules; @@ -21,7 +21,7 @@ index 66735bbc2528c5812c9df14ef7cd91cb69d903b2..9c594c0f142ca10b7c1df50faf45ccb3 import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.border.BorderChangeListener; import net.minecraft.world.level.border.WorldBorder; -@@ -821,6 +822,7 @@ public abstract class PlayerList { +@@ -822,6 +823,7 @@ public abstract class PlayerList { // Paper start boolean isBedSpawn = false; boolean isRespawn = false; @@ -29,7 +29,7 @@ index 66735bbc2528c5812c9df14ef7cd91cb69d903b2..9c594c0f142ca10b7c1df50faf45ccb3 // Paper end // CraftBukkit start - fire PlayerRespawnEvent -@@ -831,7 +833,7 @@ public abstract class PlayerList { +@@ -832,7 +834,7 @@ public abstract class PlayerList { Optional optional; if (blockposition != null) { @@ -38,7 +38,7 @@ index 66735bbc2528c5812c9df14ef7cd91cb69d903b2..9c594c0f142ca10b7c1df50faf45ccb3 } else { optional = Optional.empty(); } -@@ -874,7 +876,12 @@ public abstract class PlayerList { +@@ -875,7 +877,12 @@ public abstract class PlayerList { } // Spigot End @@ -52,7 +52,7 @@ index 66735bbc2528c5812c9df14ef7cd91cb69d903b2..9c594c0f142ca10b7c1df50faf45ccb3 if (!flag) entityplayer.reset(); // SPIGOT-4785 isRespawn = true; // Paper } else { -@@ -911,8 +918,12 @@ public abstract class PlayerList { +@@ -913,8 +920,12 @@ public abstract class PlayerList { } // entityplayer1.syncInventory(); entityplayer1.setHealth(entityplayer1.getHealth()); diff --git a/patches/server/0484-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/patches/server/0485-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch similarity index 100% rename from patches/server/0484-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch rename to patches/server/0485-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch diff --git a/patches/server/0485-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/patches/server/0486-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch similarity index 100% rename from patches/server/0485-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch rename to patches/server/0486-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch diff --git a/patches/server/0486-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/patches/server/0487-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch similarity index 100% rename from patches/server/0486-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch rename to patches/server/0487-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch diff --git a/patches/server/0487-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/patches/server/0488-Add-missing-strikeLighting-call-to-World-spigot-stri.patch similarity index 82% rename from patches/server/0487-Add-missing-strikeLighting-call-to-World-spigot-stri.patch rename to patches/server/0488-Add-missing-strikeLighting-call-to-World-spigot-stri.patch index 9449b0adec..b1f6784ef3 100644 --- a/patches/server/0487-Add-missing-strikeLighting-call-to-World-spigot-stri.patch +++ b/patches/server/0488-Add-missing-strikeLighting-call-to-World-spigot-stri.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add missing strikeLighting call to diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index f72471ac82907a0d5112598b3289689495285944..d79a711d4080ad8acb2c240870be9d99a0b84cea 100644 +index 29b2f5d3e6fd4859fbe94ad1cd5c355be7f9d4f3..babe877022156adc224643c3d487793bfa43d5ff 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2623,6 +2623,7 @@ public class CraftWorld implements World { +@@ -2627,6 +2627,7 @@ public class CraftWorld implements World { lightning.moveTo( loc.getX(), loc.getY(), loc.getZ() ); lightning.visualOnly = true; lightning.isSilent = isSilent; diff --git a/patches/server/0488-Fix-some-rails-connecting-improperly.patch b/patches/server/0489-Fix-some-rails-connecting-improperly.patch similarity index 100% rename from patches/server/0488-Fix-some-rails-connecting-improperly.patch rename to patches/server/0489-Fix-some-rails-connecting-improperly.patch diff --git a/patches/server/0489-Incremental-player-saving.patch b/patches/server/0490-Incremental-player-saving.patch similarity index 96% rename from patches/server/0489-Incremental-player-saving.patch rename to patches/server/0490-Incremental-player-saving.patch index dae7e913d7..cc01e08383 100644 --- a/patches/server/0489-Incremental-player-saving.patch +++ b/patches/server/0490-Incremental-player-saving.patch @@ -55,7 +55,7 @@ index 1feda8b44364c748497174944b26abc4f058f354..1889de77a5e3d9371005b6bd451e2c0e } // Paper start for (ServerLevel level : this.getAllLevels()) { diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index cd34b5aa61c78d8138500a93f0a9714bedd7ed86..b49fa995973f860a95d937c98e2821435262ce25 100644 +index b106a972a76e856d6cdab78dec5daef77b135f98..de50d3de98490b5620a085c1af7fb100b8b8ad99 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -169,6 +169,7 @@ public class ServerPlayer extends Player { @@ -67,7 +67,7 @@ index cd34b5aa61c78d8138500a93f0a9714bedd7ed86..b49fa995973f860a95d937c98e282143 private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; public ServerGamePacketListenerImpl connection; diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 9c594c0f142ca10b7c1df50faf45ccb3f7468ba9..8c62367888af566dd9be4bb5cd301c26e0248e46 100644 +index 0528099611eca136722507cacbd8ba6a668778b8..554da65376a1513af64fee6a958ceaa63c88b552 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -561,6 +561,7 @@ public abstract class PlayerList { @@ -78,7 +78,7 @@ index 9c594c0f142ca10b7c1df50faf45ccb3f7468ba9..8c62367888af566dd9be4bb5cd301c26 this.playerIo.save(player); ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit -@@ -1198,10 +1199,21 @@ public abstract class PlayerList { +@@ -1200,10 +1201,21 @@ public abstract class PlayerList { } public void saveAll() { diff --git a/patches/server/0490-Fix-MC-187716-Use-configured-height.patch b/patches/server/0491-Fix-MC-187716-Use-configured-height.patch similarity index 100% rename from patches/server/0490-Fix-MC-187716-Use-configured-height.patch rename to patches/server/0491-Fix-MC-187716-Use-configured-height.patch diff --git a/patches/server/0491-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/patches/server/0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch similarity index 100% rename from patches/server/0491-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch rename to patches/server/0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch diff --git a/patches/server/0492-Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server/0493-Do-not-let-the-server-load-chunks-from-newer-version.patch similarity index 100% rename from patches/server/0492-Do-not-let-the-server-load-chunks-from-newer-version.patch rename to patches/server/0493-Do-not-let-the-server-load-chunks-from-newer-version.patch diff --git a/patches/server/0493-Brand-support.patch b/patches/server/0494-Brand-support.patch similarity index 90% rename from patches/server/0493-Brand-support.patch rename to patches/server/0494-Brand-support.patch index 4ce0bb26ce..148208218a 100644 --- a/patches/server/0493-Brand-support.patch +++ b/patches/server/0494-Brand-support.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Brand support diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 99a16a2f0c2dc227dd45db1964c2d47ffdcda73e..0176b85a031b33cb2a12bb75079f5e3111f4f2b7 100644 +index afd5f5efdd6b47811fdbc23adeacace594602046..30cdacbefb07c7b3e7d64cbb78ff821a5f6c7567 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -4,6 +4,7 @@ import com.google.common.collect.Lists; @@ -33,7 +33,7 @@ index 99a16a2f0c2dc227dd45db1964c2d47ffdcda73e..0176b85a031b33cb2a12bb75079f5e31 public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { this.server = server; this.connection = connection; -@@ -3000,6 +3004,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -3001,6 +3005,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register"); private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister"); @@ -42,7 +42,7 @@ index 99a16a2f0c2dc227dd45db1964c2d47ffdcda73e..0176b85a031b33cb2a12bb75079f5e31 @Override public void handleCustomPayload(ServerboundCustomPayloadPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); -@@ -3027,6 +3033,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -3028,6 +3034,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser try { byte[] data = new byte[packet.data.readableBytes()]; packet.data.readBytes(data); @@ -58,7 +58,7 @@ index 99a16a2f0c2dc227dd45db1964c2d47ffdcda73e..0176b85a031b33cb2a12bb75079f5e31 this.cserver.getMessenger().dispatchIncomingMessage(this.player.getBukkitEntity(), packet.identifier.toString(), data); } catch (Exception ex) { ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); -@@ -3036,6 +3051,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -3037,6 +3052,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } @@ -72,10 +72,10 @@ index 99a16a2f0c2dc227dd45db1964c2d47ffdcda73e..0176b85a031b33cb2a12bb75079f5e31 return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0a6d6ea67eaf8b2a59ec45fb3ffb85096f509997..b277c87c0834ddcefcfaebd85c9e69d8d389b59e 100644 +index e4386cf8bc6170f0c144560905ab285e44ebd5bb..a574848e34a391650efd09e5a5ec010ea5eb769e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2386,6 +2386,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2393,6 +2393,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Paper end }; diff --git a/patches/server/0494-Add-setMaxPlayers-API.patch b/patches/server/0495-Add-setMaxPlayers-API.patch similarity index 89% rename from patches/server/0494-Add-setMaxPlayers-API.patch rename to patches/server/0495-Add-setMaxPlayers-API.patch index 92e26244b5..1249b8a981 100644 --- a/patches/server/0494-Add-setMaxPlayers-API.patch +++ b/patches/server/0495-Add-setMaxPlayers-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add #setMaxPlayers API diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8c62367888af566dd9be4bb5cd301c26e0248e46..2f73f1f770e5e1fa422bec9c27e5bd10e86b7538 100644 +index 554da65376a1513af64fee6a958ceaa63c88b552..c61a4e8e03996487ed3f7f39187d96a866191a41 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -142,7 +142,7 @@ public abstract class PlayerList { @@ -18,7 +18,7 @@ index 8c62367888af566dd9be4bb5cd301c26e0248e46..2f73f1f770e5e1fa422bec9c27e5bd10 private boolean allowCheatsForAllPlayers; private static final boolean ALLOW_LOGOUTIVATOR = false; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index df2c41d18377d8519d5537186d529ecc1901f58a..74de169828d7e1e55d15546eb637a87268610700 100644 +index beb8b7d06ef47c80ede95c884598fedcc7126d67..7795735e5acc3b7b6b71b4e61bdc4bdcb722a7b3 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -616,6 +616,13 @@ public final class CraftServer implements Server { diff --git a/patches/server/0495-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from patches/server/0495-Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/patches/server/0496-Don-t-require-FACING-data.patch b/patches/server/0497-Don-t-require-FACING-data.patch similarity index 100% rename from patches/server/0496-Don-t-require-FACING-data.patch rename to patches/server/0497-Don-t-require-FACING-data.patch diff --git a/patches/server/0497-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server/0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch similarity index 96% rename from patches/server/0497-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch rename to patches/server/0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch index f5f54e1c8c..744c5321fa 100644 --- a/patches/server/0497-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch +++ b/patches/server/0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch @@ -24,7 +24,7 @@ index bdabcdb60dbfb803ead13c42c8dd5e100b37dc00..4ae56444d258cdf44a02256315d6aae8 // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index d79a711d4080ad8acb2c240870be9d99a0b84cea..4ca674fac0e1ed354a0c49284c21ca2b117dd852 100644 +index babe877022156adc224643c3d487793bfa43d5ff..b24395160c1ea84ed44a1db07b4f024a540ca80b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -386,11 +386,13 @@ public class CraftWorld implements World { diff --git a/patches/server/0498-Add-moon-phase-API.patch b/patches/server/0499-Add-moon-phase-API.patch similarity index 89% rename from patches/server/0498-Add-moon-phase-API.patch rename to patches/server/0499-Add-moon-phase-API.patch index e6c06c4be3..884806ab13 100644 --- a/patches/server/0498-Add-moon-phase-API.patch +++ b/patches/server/0499-Add-moon-phase-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add moon phase API diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 4ca674fac0e1ed354a0c49284c21ca2b117dd852..d0b2de0f0a37554eb812aa8c7c20f1067807dc40 100644 +index b24395160c1ea84ed44a1db07b4f024a540ca80b..b373e72237cc33a628648de515b163d8ce2980fb 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -325,6 +325,11 @@ public class CraftWorld implements World { diff --git a/patches/server/0499-Prevent-headless-pistons-from-being-created.patch b/patches/server/0500-Prevent-headless-pistons-from-being-created.patch similarity index 100% rename from patches/server/0499-Prevent-headless-pistons-from-being-created.patch rename to patches/server/0500-Prevent-headless-pistons-from-being-created.patch diff --git a/patches/server/0500-Add-BellRingEvent.patch b/patches/server/0501-Add-BellRingEvent.patch similarity index 100% rename from patches/server/0500-Add-BellRingEvent.patch rename to patches/server/0501-Add-BellRingEvent.patch diff --git a/patches/server/0501-Add-zombie-targets-turtle-egg-config.patch b/patches/server/0502-Add-zombie-targets-turtle-egg-config.patch similarity index 100% rename from patches/server/0501-Add-zombie-targets-turtle-egg-config.patch rename to patches/server/0502-Add-zombie-targets-turtle-egg-config.patch diff --git a/patches/server/0502-Buffer-joins-to-world.patch b/patches/server/0503-Buffer-joins-to-world.patch similarity index 100% rename from patches/server/0502-Buffer-joins-to-world.patch rename to patches/server/0503-Buffer-joins-to-world.patch diff --git a/patches/server/0503-Optimize-redstone-algorithm.patch b/patches/server/0504-Optimize-redstone-algorithm.patch similarity index 100% rename from patches/server/0503-Optimize-redstone-algorithm.patch rename to patches/server/0504-Optimize-redstone-algorithm.patch diff --git a/patches/server/0504-Fix-hex-colors-not-working-in-some-kick-messages.patch b/patches/server/0505-Fix-hex-colors-not-working-in-some-kick-messages.patch similarity index 100% rename from patches/server/0504-Fix-hex-colors-not-working-in-some-kick-messages.patch rename to patches/server/0505-Fix-hex-colors-not-working-in-some-kick-messages.patch diff --git a/patches/server/0505-PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server/0506-PortalCreateEvent-needs-to-know-its-entity.patch similarity index 100% rename from patches/server/0505-PortalCreateEvent-needs-to-know-its-entity.patch rename to patches/server/0506-PortalCreateEvent-needs-to-know-its-entity.patch diff --git a/patches/server/0506-Fix-CraftTeam-null-check.patch b/patches/server/0507-Fix-CraftTeam-null-check.patch similarity index 100% rename from patches/server/0506-Fix-CraftTeam-null-check.patch rename to patches/server/0507-Fix-CraftTeam-null-check.patch diff --git a/patches/server/0507-Add-more-Evoker-API.patch b/patches/server/0508-Add-more-Evoker-API.patch similarity index 100% rename from patches/server/0507-Add-more-Evoker-API.patch rename to patches/server/0508-Add-more-Evoker-API.patch diff --git a/patches/server/0508-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/server/0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 100% rename from patches/server/0508-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to patches/server/0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch diff --git a/patches/server/0509-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server/0510-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 100% rename from patches/server/0509-Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/server/0510-Create-HoverEvent-from-ItemStack-Entity.patch diff --git a/patches/server/0510-Cache-block-data-strings.patch b/patches/server/0511-Cache-block-data-strings.patch similarity index 100% rename from patches/server/0510-Cache-block-data-strings.patch rename to patches/server/0511-Cache-block-data-strings.patch diff --git a/patches/server/0511-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/patches/server/0512-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch similarity index 97% rename from patches/server/0511-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch rename to patches/server/0512-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch index 403e8d2e60..dd9aef6436 100644 --- a/patches/server/0511-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch +++ b/patches/server/0512-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch @@ -9,7 +9,7 @@ as this is how Vanilla teleports entities. Cancel any pending motion when teleported. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 0176b85a031b33cb2a12bb75079f5e3111f4f2b7..e3725db7e19fe3235ec25beffca26a7eede24394 100644 +index 30cdacbefb07c7b3e7d64cbb78ff821a5f6c7567..1a085522026d6a7d549ca9975e02336bcd495aa4 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -682,7 +682,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @@ -27,9 +27,9 @@ index 0176b85a031b33cb2a12bb75079f5e3111f4f2b7..e3725db7e19fe3235ec25beffca26a7e this.awaitingTeleportTime = this.tickCount; - this.player.absMoveTo(d0, d1, d2, f, f1); + this.player.moveTo(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation + this.player.forceCheckHighPriority(); // Paper this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport, flag)); } - diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index 466de2bbdbf0c9e3ed28ec8fee5fcfeb75c54398..a9c90e41af1cc67a88a639dc795dd8023a7acb89 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java diff --git a/patches/server/0512-Add-additional-open-container-api-to-HumanEntity.patch b/patches/server/0513-Add-additional-open-container-api-to-HumanEntity.patch similarity index 100% rename from patches/server/0512-Add-additional-open-container-api-to-HumanEntity.patch rename to patches/server/0513-Add-additional-open-container-api-to-HumanEntity.patch diff --git a/patches/server/0513-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/patches/server/0514-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch similarity index 100% rename from patches/server/0513-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch rename to patches/server/0514-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch diff --git a/patches/server/0514-Extend-block-drop-capture-to-capture-all-items-added.patch b/patches/server/0515-Extend-block-drop-capture-to-capture-all-items-added.patch similarity index 100% rename from patches/server/0514-Extend-block-drop-capture-to-capture-all-items-added.patch rename to patches/server/0515-Extend-block-drop-capture-to-capture-all-items-added.patch diff --git a/patches/server/0515-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server/0516-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch similarity index 84% rename from patches/server/0515-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch rename to patches/server/0516-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch index 6f969d64c5..f2b384b6a9 100644 --- a/patches/server/0515-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch +++ b/patches/server/0516-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086) diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 1f67c9c5f7161ea687983e7ae0ec7d259da9acd3..1f5086a18b9c1c65dc2b09f44ed7c561ba96a847 100644 +index 6a1c000d693031f0c537112963cfa52e22463f1d..506b1b9d09a0e5a26fdac0192405e8b325ce97c9 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -246,6 +246,7 @@ public class ChunkHolder { +@@ -372,6 +372,7 @@ public class ChunkHolder { } public void blockChanged(BlockPos pos) { diff --git a/patches/server/0516-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server/0517-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 100% rename from patches/server/0516-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to patches/server/0517-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch diff --git a/patches/server/0517-Lazily-track-plugin-scoreboards-by-default.patch b/patches/server/0518-Lazily-track-plugin-scoreboards-by-default.patch similarity index 100% rename from patches/server/0517-Lazily-track-plugin-scoreboards-by-default.patch rename to patches/server/0518-Lazily-track-plugin-scoreboards-by-default.patch diff --git a/patches/server/0518-Entity-isTicking.patch b/patches/server/0519-Entity-isTicking.patch similarity index 100% rename from patches/server/0518-Entity-isTicking.patch rename to patches/server/0519-Entity-isTicking.patch diff --git a/patches/server/0519-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/patches/server/0520-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch similarity index 100% rename from patches/server/0519-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch rename to patches/server/0520-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch diff --git a/patches/server/0520-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/patches/server/0521-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch similarity index 100% rename from patches/server/0520-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch rename to patches/server/0521-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch diff --git a/patches/server/0521-Reset-Ender-Crystals-on-Dragon-Spawn.patch b/patches/server/0522-Reset-Ender-Crystals-on-Dragon-Spawn.patch similarity index 100% rename from patches/server/0521-Reset-Ender-Crystals-on-Dragon-Spawn.patch rename to patches/server/0522-Reset-Ender-Crystals-on-Dragon-Spawn.patch diff --git a/patches/server/0522-Fix-for-large-move-vectors-crashing-server.patch b/patches/server/0523-Fix-for-large-move-vectors-crashing-server.patch similarity index 97% rename from patches/server/0522-Fix-for-large-move-vectors-crashing-server.patch rename to patches/server/0523-Fix-for-large-move-vectors-crashing-server.patch index 6aa61b9e81..a1a4688c67 100644 --- a/patches/server/0522-Fix-for-large-move-vectors-crashing-server.patch +++ b/patches/server/0523-Fix-for-large-move-vectors-crashing-server.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Fix for large move vectors crashing server Check movement distance also based on current position. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index e3725db7e19fe3235ec25beffca26a7eede24394..0e0d6d298caa1bbb6fb0dd42fd00460f7609c431 100644 +index 1a085522026d6a7d549ca9975e02336bcd495aa4..1fffa32bd193fa122c7f7b5381f57975c2e895fe 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -507,19 +507,24 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0523-Optimise-getType-calls.patch b/patches/server/0524-Optimise-getType-calls.patch similarity index 100% rename from patches/server/0523-Optimise-getType-calls.patch rename to patches/server/0524-Optimise-getType-calls.patch diff --git a/patches/server/0524-Villager-resetOffers.patch b/patches/server/0525-Villager-resetOffers.patch similarity index 100% rename from patches/server/0524-Villager-resetOffers.patch rename to patches/server/0525-Villager-resetOffers.patch diff --git a/patches/server/0525-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/patches/server/0526-Improve-inlinig-for-some-hot-IBlockData-methods.patch similarity index 100% rename from patches/server/0525-Improve-inlinig-for-some-hot-IBlockData-methods.patch rename to patches/server/0526-Improve-inlinig-for-some-hot-IBlockData-methods.patch diff --git a/patches/server/0526-Retain-block-place-order-when-capturing-blockstates.patch b/patches/server/0527-Retain-block-place-order-when-capturing-blockstates.patch similarity index 100% rename from patches/server/0526-Retain-block-place-order-when-capturing-blockstates.patch rename to patches/server/0527-Retain-block-place-order-when-capturing-blockstates.patch diff --git a/patches/server/0527-Reduce-blockpos-allocation-from-pathfinding.patch b/patches/server/0528-Reduce-blockpos-allocation-from-pathfinding.patch similarity index 100% rename from patches/server/0527-Reduce-blockpos-allocation-from-pathfinding.patch rename to patches/server/0528-Reduce-blockpos-allocation-from-pathfinding.patch diff --git a/patches/server/0528-Fix-item-locations-dropped-from-campfires.patch b/patches/server/0529-Fix-item-locations-dropped-from-campfires.patch similarity index 100% rename from patches/server/0528-Fix-item-locations-dropped-from-campfires.patch rename to patches/server/0529-Fix-item-locations-dropped-from-campfires.patch diff --git a/patches/server/0529-Player-elytra-boost-API.patch b/patches/server/0530-Player-elytra-boost-API.patch similarity index 94% rename from patches/server/0529-Player-elytra-boost-API.patch rename to patches/server/0530-Player-elytra-boost-API.patch index 3bae46ddd3..5882c85691 100644 --- a/patches/server/0529-Player-elytra-boost-API.patch +++ b/patches/server/0530-Player-elytra-boost-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Player elytra boost API diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b277c87c0834ddcefcfaebd85c9e69d8d389b59e..41bb480e61ff98dd35b8e059356bf867406e9e5e 100644 +index a574848e34a391650efd09e5a5ec010ea5eb769e..776c79ff21ddd1e3a3644104ae91f15c119acd29 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -534,6 +534,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0530-Fixed-TileEntityBell-memory-leak.patch b/patches/server/0531-Fixed-TileEntityBell-memory-leak.patch similarity index 100% rename from patches/server/0530-Fixed-TileEntityBell-memory-leak.patch rename to patches/server/0531-Fixed-TileEntityBell-memory-leak.patch diff --git a/patches/server/0531-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/patches/server/0532-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch similarity index 100% rename from patches/server/0531-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch rename to patches/server/0532-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch diff --git a/patches/server/0532-Add-getOfflinePlayerIfCached-String.patch b/patches/server/0533-Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from patches/server/0532-Add-getOfflinePlayerIfCached-String.patch rename to patches/server/0533-Add-getOfflinePlayerIfCached-String.patch diff --git a/patches/server/0533-Add-ignore-discounts-API.patch b/patches/server/0534-Add-ignore-discounts-API.patch similarity index 100% rename from patches/server/0533-Add-ignore-discounts-API.patch rename to patches/server/0534-Add-ignore-discounts-API.patch diff --git a/patches/server/0534-Toggle-for-removing-existing-dragon.patch b/patches/server/0535-Toggle-for-removing-existing-dragon.patch similarity index 100% rename from patches/server/0534-Toggle-for-removing-existing-dragon.patch rename to patches/server/0535-Toggle-for-removing-existing-dragon.patch diff --git a/patches/server/0535-Fix-client-lag-on-advancement-loading.patch b/patches/server/0536-Fix-client-lag-on-advancement-loading.patch similarity index 100% rename from patches/server/0535-Fix-client-lag-on-advancement-loading.patch rename to patches/server/0536-Fix-client-lag-on-advancement-loading.patch diff --git a/patches/server/0536-Item-no-age-no-player-pickup.patch b/patches/server/0537-Item-no-age-no-player-pickup.patch similarity index 100% rename from patches/server/0536-Item-no-age-no-player-pickup.patch rename to patches/server/0537-Item-no-age-no-player-pickup.patch diff --git a/patches/server/0537-Beacon-API-custom-effect-ranges.patch b/patches/server/0538-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from patches/server/0537-Beacon-API-custom-effect-ranges.patch rename to patches/server/0538-Beacon-API-custom-effect-ranges.patch diff --git a/patches/server/0538-Add-API-for-quit-reason.patch b/patches/server/0539-Add-API-for-quit-reason.patch similarity index 93% rename from patches/server/0538-Add-API-for-quit-reason.patch rename to patches/server/0539-Add-API-for-quit-reason.patch index 4e5d931b12..dd04749f87 100644 --- a/patches/server/0538-Add-API-for-quit-reason.patch +++ b/patches/server/0539-Add-API-for-quit-reason.patch @@ -25,10 +25,10 @@ index d32b96a5f51d745869cfc40c01c54de58e1eb843..759e563d1ed13249fada8a8eab6b6a10 Connection.LOGGER.debug("Failed to sent packet", throwable); ConnectionProtocol enumprotocol = this.getCurrentProtocol(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index b49fa995973f860a95d937c98e2821435262ce25..41e6164fc9f3aa54028e5db1331df743126e55e2 100644 +index de50d3de98490b5620a085c1af7fb100b8b8ad99..2be97d1024b15691fb2aaa8516d6447f47da4937 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -248,6 +248,7 @@ public class ServerPlayer extends Player { +@@ -254,6 +254,7 @@ public class ServerPlayer extends Player { public double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper boolean needsChunkCenterUpdate; // Paper - no-tick view distance @@ -37,7 +37,7 @@ index b49fa995973f860a95d937c98e2821435262ce25..41e6164fc9f3aa54028e5db1331df743 public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) { super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 0e0d6d298caa1bbb6fb0dd42fd00460f7609c431..fa57095f0ddd5685f848ade5c0ec2e90e2a07e91 100644 +index 1fffa32bd193fa122c7f7b5381f57975c2e895fe..c495525da3dda12977d70ea85c87701988aa5929 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -444,6 +444,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @@ -49,7 +49,7 @@ index 0e0d6d298caa1bbb6fb0dd42fd00460f7609c431..fa57095f0ddd5685f848ade5c0ec2e90 this.connection.disconnect(ichatbasecomponent); }); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 2f73f1f770e5e1fa422bec9c27e5bd10e86b7538..fe548b8625a123798f8d966cb3bffd899971cb34 100644 +index c61a4e8e03996487ed3f7f39187d96a866191a41..1c61fd2c2c5cf5344f8c6dc14ae01353810de9eb 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -588,7 +588,7 @@ public abstract class PlayerList { diff --git a/patches/server/0539-Seed-based-feature-search.patch b/patches/server/0540-Seed-based-feature-search.patch similarity index 100% rename from patches/server/0539-Seed-based-feature-search.patch rename to patches/server/0540-Seed-based-feature-search.patch diff --git a/patches/server/0540-Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server/0541-Add-Wandering-Trader-spawn-rate-config-options.patch similarity index 100% rename from patches/server/0540-Add-Wandering-Trader-spawn-rate-config-options.patch rename to patches/server/0541-Add-Wandering-Trader-spawn-rate-config-options.patch diff --git a/patches/server/0541-Significantly-improve-performance-of-the-end-generat.patch b/patches/server/0542-Significantly-improve-performance-of-the-end-generat.patch similarity index 96% rename from patches/server/0541-Significantly-improve-performance-of-the-end-generat.patch rename to patches/server/0542-Significantly-improve-performance-of-the-end-generat.patch index 3117923e3f..a6386a6a1c 100644 --- a/patches/server/0541-Significantly-improve-performance-of-the-end-generat.patch +++ b/patches/server/0542-Significantly-improve-performance-of-the-end-generat.patch @@ -12,7 +12,7 @@ Co-authored-by: Dylan Xaldin Co-authored-by: pop4959 diff --git a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java -index 9a64ab092ac8616ed8b9ea5c1e8677dda5c4333c..b4bc60b9251a141e9a276877a9be76a381ff351b 100644 +index 9a64ab092ac8616ed8b9ea5c1e8677dda5c4333c..3f7c4e0938933705ac1bcb8dd676d018088a831a 100644 --- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java @@ -28,6 +28,16 @@ public class TheEndBiomeSource extends BiomeSource { @@ -44,7 +44,7 @@ index 9a64ab092ac8616ed8b9ea5c1e8677dda5c4333c..b4bc60b9251a141e9a276877a9be76a3 - if (q * q + r * r > 4096L && simplexNoise.getValue((double)q, (double)r) < (double)-0.9F) { - float g = (Mth.abs((float)q) * 3439.0F + Mth.abs((float)r) * 147.0F) % 13.0F + 9.0F; + // Paper start - Significantly improve end generation performance by using a noise cache -+ long key = net.minecraft.world.level.ChunkPos.asLong((int) q, (int) q); ++ long key = net.minecraft.world.level.ChunkPos.asLong((int) q, (int) r); + int index = (int) it.unimi.dsi.fastutil.HashCommon.mix(key) & 8191; + float g = Float.MIN_VALUE; + if (cache.keys[index] == key) { diff --git a/patches/server/0542-Expose-world-spawn-angle.patch b/patches/server/0543-Expose-world-spawn-angle.patch similarity index 88% rename from patches/server/0542-Expose-world-spawn-angle.patch rename to patches/server/0543-Expose-world-spawn-angle.patch index 419b678486..38e827eec1 100644 --- a/patches/server/0542-Expose-world-spawn-angle.patch +++ b/patches/server/0543-Expose-world-spawn-angle.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose world spawn angle diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index fe548b8625a123798f8d966cb3bffd899971cb34..ce6d9b460f0f55fc6d5544d5c8d2b78e5fcc3937 100644 +index 1c61fd2c2c5cf5344f8c6dc14ae01353810de9eb..720fa2b74d3f9257a32e4bd5d21050626d136668 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -865,7 +865,7 @@ public abstract class PlayerList { +@@ -866,7 +866,7 @@ public abstract class PlayerList { if (location == null) { worldserver1 = this.server.getLevel(Level.OVERWORLD); blockposition = entityplayer1.getSpawnPoint(worldserver1); @@ -18,7 +18,7 @@ index fe548b8625a123798f8d966cb3bffd899971cb34..ce6d9b460f0f55fc6d5544d5c8d2b78e Player respawnPlayer = this.cserver.getPlayer(entityplayer1); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index d0b2de0f0a37554eb812aa8c7c20f1067807dc40..ed8c8b7ff07a58dfaf7bbb1e630a1e68cc0c29f3 100644 +index b373e72237cc33a628648de515b163d8ce2980fb..8257e5a648eebf8ac9fa1a15656643a448cf07b6 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -377,7 +377,7 @@ public class CraftWorld implements World { diff --git a/patches/server/0543-Add-Destroy-Speed-API.patch b/patches/server/0544-Add-Destroy-Speed-API.patch similarity index 100% rename from patches/server/0543-Add-Destroy-Speed-API.patch rename to patches/server/0544-Add-Destroy-Speed-API.patch diff --git a/patches/server/0544-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/patches/server/0545-Fix-Player-spawnParticle-x-y-z-precision-loss.patch similarity index 89% rename from patches/server/0544-Fix-Player-spawnParticle-x-y-z-precision-loss.patch rename to patches/server/0545-Fix-Player-spawnParticle-x-y-z-precision-loss.patch index e4450be6cf..693e824d57 100644 --- a/patches/server/0544-Fix-Player-spawnParticle-x-y-z-precision-loss.patch +++ b/patches/server/0545-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 41bb480e61ff98dd35b8e059356bf867406e9e5e..9236027beb13ae4f2e35c46f6c176fd5d7d20b4f 100644 +index 776c79ff21ddd1e3a3644104ae91f15c119acd29..0f832a1cec5dbe3f4fb8638af2ea1dc129ea5970 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2047,7 +2047,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2054,7 +2054,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (data != null && !particle.getDataType().isInstance(data)) { throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); } diff --git a/patches/server/0545-Add-LivingEntity-clearActiveItem.patch b/patches/server/0546-Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from patches/server/0545-Add-LivingEntity-clearActiveItem.patch rename to patches/server/0546-Add-LivingEntity-clearActiveItem.patch diff --git a/patches/server/0546-Add-PlayerItemCooldownEvent.patch b/patches/server/0547-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from patches/server/0546-Add-PlayerItemCooldownEvent.patch rename to patches/server/0547-Add-PlayerItemCooldownEvent.patch diff --git a/patches/server/0547-More-lightning-API.patch b/patches/server/0548-More-lightning-API.patch similarity index 100% rename from patches/server/0547-More-lightning-API.patch rename to patches/server/0548-More-lightning-API.patch diff --git a/patches/server/0548-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/0549-Climbing-should-not-bypass-cramming-gamerule.patch similarity index 100% rename from patches/server/0548-Climbing-should-not-bypass-cramming-gamerule.patch rename to patches/server/0549-Climbing-should-not-bypass-cramming-gamerule.patch diff --git a/patches/server/0549-Added-missing-default-perms-for-commands.patch b/patches/server/0550-Added-missing-default-perms-for-commands.patch similarity index 100% rename from patches/server/0549-Added-missing-default-perms-for-commands.patch rename to patches/server/0550-Added-missing-default-perms-for-commands.patch diff --git a/patches/server/0550-Add-PlayerShearBlockEvent.patch b/patches/server/0551-Add-PlayerShearBlockEvent.patch similarity index 100% rename from patches/server/0550-Add-PlayerShearBlockEvent.patch rename to patches/server/0551-Add-PlayerShearBlockEvent.patch diff --git a/patches/server/0551-Set-spigots-verbose-world-setting-to-false-by-def.patch b/patches/server/0552-Set-spigots-verbose-world-setting-to-false-by-def.patch similarity index 100% rename from patches/server/0551-Set-spigots-verbose-world-setting-to-false-by-def.patch rename to patches/server/0552-Set-spigots-verbose-world-setting-to-false-by-def.patch diff --git a/patches/server/0552-Fix-curing-zombie-villager-discount-exploit.patch b/patches/server/0553-Fix-curing-zombie-villager-discount-exploit.patch similarity index 100% rename from patches/server/0552-Fix-curing-zombie-villager-discount-exploit.patch rename to patches/server/0553-Fix-curing-zombie-villager-discount-exploit.patch diff --git a/patches/server/0553-Limit-recipe-packets.patch b/patches/server/0554-Limit-recipe-packets.patch similarity index 95% rename from patches/server/0553-Limit-recipe-packets.patch rename to patches/server/0554-Limit-recipe-packets.patch index 8f746a55f1..261cfcff49 100644 --- a/patches/server/0553-Limit-recipe-packets.patch +++ b/patches/server/0554-Limit-recipe-packets.patch @@ -23,7 +23,7 @@ index 7d50aded88f5b7dfebaea1aebc86231f7b5c4e25..652d87fc5d566dba8018c81676329f0e public static boolean velocityOnlineMode; public static byte[] velocitySecretKey; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index fa57095f0ddd5685f848ade5c0ec2e90e2a07e91..309b8e193ec67df0379d65ce77a2a095702fd024 100644 +index c495525da3dda12977d70ea85c87701988aa5929..2a1c524941e50d6a16076f57460d0cb05ed57f7c 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -232,6 +232,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @@ -42,7 +42,7 @@ index fa57095f0ddd5685f848ade5c0ec2e90e2a07e91..309b8e193ec67df0379d65ce77a2a095 /* Use thread-safe field access instead if (this.chatSpamTickCount > 0) { --this.chatSpamTickCount; -@@ -2794,6 +2796,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -2795,6 +2797,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @Override public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) { diff --git a/patches/server/0554-Fix-CraftSound-backwards-compatibility.patch b/patches/server/0555-Fix-CraftSound-backwards-compatibility.patch similarity index 100% rename from patches/server/0554-Fix-CraftSound-backwards-compatibility.patch rename to patches/server/0555-Fix-CraftSound-backwards-compatibility.patch diff --git a/patches/server/0555-MC-4-Fix-item-position-desync.patch b/patches/server/0556-MC-4-Fix-item-position-desync.patch similarity index 100% rename from patches/server/0555-MC-4-Fix-item-position-desync.patch rename to patches/server/0556-MC-4-Fix-item-position-desync.patch diff --git a/patches/server/0556-Player-Chunk-Load-Unload-Events.patch b/patches/server/0557-Player-Chunk-Load-Unload-Events.patch similarity index 90% rename from patches/server/0556-Player-Chunk-Load-Unload-Events.patch rename to patches/server/0557-Player-Chunk-Load-Unload-Events.patch index 9adb124224..54e121ece4 100644 --- a/patches/server/0556-Player-Chunk-Load-Unload-Events.patch +++ b/patches/server/0557-Player-Chunk-Load-Unload-Events.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Player Chunk Load/Unload Events diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 41e6164fc9f3aa54028e5db1331df743126e55e2..5a87875b03740053d8cde6d81c57703d0b0ef57e 100644 +index 2be97d1024b15691fb2aaa8516d6447f47da4937..f412f3b9f3af498b9ced4a808849442efad01b69 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2065,11 +2065,21 @@ public class ServerPlayer extends Player { +@@ -2087,11 +2087,21 @@ public class ServerPlayer extends Player { public void trackChunk(ChunkPos chunkcoordintpair, Packet packet, Packet packet1) { this.connection.send(packet1); this.connection.send(packet); diff --git a/patches/server/0557-Optimize-Dynamic-get-Missing-Keys.patch b/patches/server/0558-Optimize-Dynamic-get-Missing-Keys.patch similarity index 100% rename from patches/server/0557-Optimize-Dynamic-get-Missing-Keys.patch rename to patches/server/0558-Optimize-Dynamic-get-Missing-Keys.patch diff --git a/patches/server/0558-Expose-LivingEntity-hurt-direction.patch b/patches/server/0559-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from patches/server/0558-Expose-LivingEntity-hurt-direction.patch rename to patches/server/0559-Expose-LivingEntity-hurt-direction.patch diff --git a/patches/server/0559-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server/0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from patches/server/0559-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/server/0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/patches/server/0560-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server/0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch similarity index 100% rename from patches/server/0560-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch rename to patches/server/0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch diff --git a/patches/server/0561-added-PlayerTradeEvent.patch b/patches/server/0562-added-PlayerTradeEvent.patch similarity index 100% rename from patches/server/0561-added-PlayerTradeEvent.patch rename to patches/server/0562-added-PlayerTradeEvent.patch diff --git a/patches/server/0562-Implement-TargetHitEvent.patch b/patches/server/0563-Implement-TargetHitEvent.patch similarity index 100% rename from patches/server/0562-Implement-TargetHitEvent.patch rename to patches/server/0563-Implement-TargetHitEvent.patch diff --git a/patches/server/0563-Additional-Block-Material-API-s.patch b/patches/server/0564-Additional-Block-Material-API-s.patch similarity index 100% rename from patches/server/0563-Additional-Block-Material-API-s.patch rename to patches/server/0564-Additional-Block-Material-API-s.patch diff --git a/patches/server/0564-Fix-harming-potion-dupe.patch b/patches/server/0565-Fix-harming-potion-dupe.patch similarity index 100% rename from patches/server/0564-Fix-harming-potion-dupe.patch rename to patches/server/0565-Fix-harming-potion-dupe.patch diff --git a/patches/server/0565-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/patches/server/0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch similarity index 100% rename from patches/server/0565-Implement-API-to-get-Material-from-Boats-and-Minecar.patch rename to patches/server/0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch diff --git a/patches/server/0566-Cache-burn-durations.patch b/patches/server/0567-Cache-burn-durations.patch similarity index 100% rename from patches/server/0566-Cache-burn-durations.patch rename to patches/server/0567-Cache-burn-durations.patch diff --git a/patches/server/0567-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server/0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch similarity index 100% rename from patches/server/0567-Allow-disabling-mob-spawner-spawn-egg-transformation.patch rename to patches/server/0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch diff --git a/patches/server/0568-Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server/0569-Implement-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from patches/server/0568-Implement-PlayerFlowerPotManipulateEvent.patch rename to patches/server/0569-Implement-PlayerFlowerPotManipulateEvent.patch diff --git a/patches/server/0569-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server/0570-Fix-interact-event-not-being-called-in-adventure.patch similarity index 90% rename from patches/server/0569-Fix-interact-event-not-being-called-in-adventure.patch rename to patches/server/0570-Fix-interact-event-not-being-called-in-adventure.patch index cc7e10b0fd..df7ae51e70 100644 --- a/patches/server/0569-Fix-interact-event-not-being-called-in-adventure.patch +++ b/patches/server/0570-Fix-interact-event-not-being-called-in-adventure.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix interact event not being called in adventure Call PlayerInteractEvent when left-clicking on a block in adventure mode diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 309b8e193ec67df0379d65ce77a2a095702fd024..df80023e43e7872e32e7b958ea0a5e82d86d43f7 100644 +index 2a1c524941e50d6a16076f57460d0cb05ed57f7c..8051cc5950b71f284e7ad8be685977fd098fe022 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1733,7 +1733,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -1734,7 +1734,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser MutableComponent ichatmutablecomponent = (new TranslatableComponent("build.tooHigh", new Object[]{i - 1})).withStyle(ChatFormatting.RED); this.player.sendMessage((Component) ichatmutablecomponent, ChatType.GAME_INFO, Util.NIL_UUID); @@ -18,7 +18,7 @@ index 309b8e193ec67df0379d65ce77a2a095702fd024..df80023e43e7872e32e7b958ea0a5e82 this.player.swing(enumhand, true); } } -@@ -2205,7 +2205,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -2206,7 +2206,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser Vec3 vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); HitResult movingobjectposition = this.player.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.player)); diff --git a/patches/server/0570-Zombie-API-breaking-doors.patch b/patches/server/0571-Zombie-API-breaking-doors.patch similarity index 100% rename from patches/server/0570-Zombie-API-breaking-doors.patch rename to patches/server/0571-Zombie-API-breaking-doors.patch diff --git a/patches/server/0571-Fix-nerfed-slime-when-splitting.patch b/patches/server/0572-Fix-nerfed-slime-when-splitting.patch similarity index 100% rename from patches/server/0571-Fix-nerfed-slime-when-splitting.patch rename to patches/server/0572-Fix-nerfed-slime-when-splitting.patch diff --git a/patches/server/0572-Add-EntityLoadCrossbowEvent.patch b/patches/server/0573-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from patches/server/0572-Add-EntityLoadCrossbowEvent.patch rename to patches/server/0573-Add-EntityLoadCrossbowEvent.patch diff --git a/patches/server/0573-Guardian-beam-workaround.patch b/patches/server/0574-Guardian-beam-workaround.patch similarity index 100% rename from patches/server/0573-Guardian-beam-workaround.patch rename to patches/server/0574-Guardian-beam-workaround.patch diff --git a/patches/server/0574-Added-WorldGameRuleChangeEvent.patch b/patches/server/0575-Added-WorldGameRuleChangeEvent.patch similarity index 98% rename from patches/server/0574-Added-WorldGameRuleChangeEvent.patch rename to patches/server/0575-Added-WorldGameRuleChangeEvent.patch index ba44871043..5b055df691 100644 --- a/patches/server/0574-Added-WorldGameRuleChangeEvent.patch +++ b/patches/server/0575-Added-WorldGameRuleChangeEvent.patch @@ -64,7 +64,7 @@ index 888d812118c15c212284687ae5842a94f5715d52..e7ca5d6fb8922e7e8065864f736b0605 public int get() { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index ed8c8b7ff07a58dfaf7bbb1e630a1e68cc0c29f3..fd01fc9708a62df9483c88ffeec6a0304f3708ca 100644 +index 8257e5a648eebf8ac9fa1a15656643a448cf07b6..c36a9eedaa587d513a3be78054d15f4ad96d4d7c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -2363,8 +2363,13 @@ public class CraftWorld implements World { diff --git a/patches/server/0575-Added-ServerResourcesReloadedEvent.patch b/patches/server/0576-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from patches/server/0575-Added-ServerResourcesReloadedEvent.patch rename to patches/server/0576-Added-ServerResourcesReloadedEvent.patch diff --git a/patches/server/0576-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server/0577-Added-world-settings-for-mobs-picking-up-loot.patch similarity index 100% rename from patches/server/0576-Added-world-settings-for-mobs-picking-up-loot.patch rename to patches/server/0577-Added-world-settings-for-mobs-picking-up-loot.patch diff --git a/patches/server/0577-Implemented-BlockFailedDispenseEvent.patch b/patches/server/0578-Implemented-BlockFailedDispenseEvent.patch similarity index 100% rename from patches/server/0577-Implemented-BlockFailedDispenseEvent.patch rename to patches/server/0578-Implemented-BlockFailedDispenseEvent.patch diff --git a/patches/server/0578-Added-PlayerLecternPageChangeEvent.patch b/patches/server/0579-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from patches/server/0578-Added-PlayerLecternPageChangeEvent.patch rename to patches/server/0579-Added-PlayerLecternPageChangeEvent.patch diff --git a/patches/server/0579-Added-PlayerLoomPatternSelectEvent.patch b/patches/server/0580-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from patches/server/0579-Added-PlayerLoomPatternSelectEvent.patch rename to patches/server/0580-Added-PlayerLoomPatternSelectEvent.patch diff --git a/patches/server/0580-Configurable-door-breaking-difficulty.patch b/patches/server/0581-Configurable-door-breaking-difficulty.patch similarity index 100% rename from patches/server/0580-Configurable-door-breaking-difficulty.patch rename to patches/server/0581-Configurable-door-breaking-difficulty.patch diff --git a/patches/server/0581-Empty-commands-shall-not-be-dispatched.patch b/patches/server/0582-Empty-commands-shall-not-be-dispatched.patch similarity index 100% rename from patches/server/0581-Empty-commands-shall-not-be-dispatched.patch rename to patches/server/0582-Empty-commands-shall-not-be-dispatched.patch diff --git a/patches/server/0582-Implement-API-to-expose-exact-interaction-point.patch b/patches/server/0583-Implement-API-to-expose-exact-interaction-point.patch similarity index 100% rename from patches/server/0582-Implement-API-to-expose-exact-interaction-point.patch rename to patches/server/0583-Implement-API-to-expose-exact-interaction-point.patch diff --git a/patches/server/0583-Remove-stale-POIs.patch b/patches/server/0584-Remove-stale-POIs.patch similarity index 100% rename from patches/server/0583-Remove-stale-POIs.patch rename to patches/server/0584-Remove-stale-POIs.patch diff --git a/patches/server/0584-Fix-villager-boat-exploit.patch b/patches/server/0585-Fix-villager-boat-exploit.patch similarity index 93% rename from patches/server/0584-Fix-villager-boat-exploit.patch rename to patches/server/0585-Fix-villager-boat-exploit.patch index edc990c633..5eec001adb 100644 --- a/patches/server/0584-Fix-villager-boat-exploit.patch +++ b/patches/server/0585-Fix-villager-boat-exploit.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix villager boat exploit diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index ce6d9b460f0f55fc6d5544d5c8d2b78e5fcc3937..9a37a962b141e9faecc9f6f4906a9d727d20c20a 100644 +index 720fa2b74d3f9257a32e4bd5d21050626d136668..bbb2b5d96b35328e0b6041145a3d8234fd43dd03 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -613,6 +613,15 @@ public abstract class PlayerList { diff --git a/patches/server/0585-Add-sendOpLevel-API.patch b/patches/server/0586-Add-sendOpLevel-API.patch similarity index 91% rename from patches/server/0585-Add-sendOpLevel-API.patch rename to patches/server/0586-Add-sendOpLevel-API.patch index 804eeb2787..226d9fdddc 100644 --- a/patches/server/0585-Add-sendOpLevel-API.patch +++ b/patches/server/0586-Add-sendOpLevel-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add sendOpLevel API diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 9a37a962b141e9faecc9f6f4906a9d727d20c20a..d01712cad42c078a726d6f757a4d8f0e3f186274 100644 +index bbb2b5d96b35328e0b6041145a3d8234fd43dd03..213bfc7637b649a8e578d9a122fc4fce3c9fe9ea 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1113,22 +1113,29 @@ public abstract class PlayerList { +@@ -1115,22 +1115,29 @@ public abstract class PlayerList { } private void sendPlayerPermissionLevel(ServerPlayer player, int permissionLevel) { @@ -46,7 +46,7 @@ index 9a37a962b141e9faecc9f6f4906a9d727d20c20a..d01712cad42c078a726d6f757a4d8f0e // Paper start diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 9236027beb13ae4f2e35c46f6c176fd5d7d20b4f..a9fdf153a9442830c7ce9e8fb6147b2c7b33db55 100644 +index 0f832a1cec5dbe3f4fb8638af2ea1dc129ea5970..79527b4806c306b9811f6e93733836e658fea0fe 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -548,6 +548,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0586-Add-StructureLocateEvent.patch b/patches/server/0587-Add-StructureLocateEvent.patch similarity index 100% rename from patches/server/0586-Add-StructureLocateEvent.patch rename to patches/server/0587-Add-StructureLocateEvent.patch diff --git a/patches/server/0587-Collision-option-for-requiring-a-player-participant.patch b/patches/server/0588-Collision-option-for-requiring-a-player-participant.patch similarity index 100% rename from patches/server/0587-Collision-option-for-requiring-a-player-participant.patch rename to patches/server/0588-Collision-option-for-requiring-a-player-participant.patch diff --git a/patches/server/0588-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/patches/server/0589-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch similarity index 100% rename from patches/server/0588-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch rename to patches/server/0589-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch diff --git a/patches/server/0589-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/server/0590-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from patches/server/0589-Return-chat-component-with-empty-text-instead-of-thr.patch rename to patches/server/0590-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/patches/server/0590-Make-schedule-command-per-world.patch b/patches/server/0591-Make-schedule-command-per-world.patch similarity index 100% rename from patches/server/0590-Make-schedule-command-per-world.patch rename to patches/server/0591-Make-schedule-command-per-world.patch diff --git a/patches/server/0591-Configurable-max-leash-distance.patch b/patches/server/0592-Configurable-max-leash-distance.patch similarity index 100% rename from patches/server/0591-Configurable-max-leash-distance.patch rename to patches/server/0592-Configurable-max-leash-distance.patch diff --git a/patches/server/0592-Implement-BlockPreDispenseEvent.patch b/patches/server/0593-Implement-BlockPreDispenseEvent.patch similarity index 100% rename from patches/server/0592-Implement-BlockPreDispenseEvent.patch rename to patches/server/0593-Implement-BlockPreDispenseEvent.patch diff --git a/patches/server/0593-Added-Vanilla-Entity-Tags.patch b/patches/server/0594-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from patches/server/0593-Added-Vanilla-Entity-Tags.patch rename to patches/server/0594-Added-Vanilla-Entity-Tags.patch diff --git a/patches/server/0594-added-Wither-API.patch b/patches/server/0595-added-Wither-API.patch similarity index 100% rename from patches/server/0594-added-Wither-API.patch rename to patches/server/0595-added-Wither-API.patch diff --git a/patches/server/0595-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/patches/server/0596-Added-firing-of-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from patches/server/0595-Added-firing-of-PlayerChangeBeaconEffectEvent.patch rename to patches/server/0596-Added-firing-of-PlayerChangeBeaconEffectEvent.patch diff --git a/patches/server/0596-Fix-console-spam-when-removing-chests-in-water.patch b/patches/server/0597-Fix-console-spam-when-removing-chests-in-water.patch similarity index 100% rename from patches/server/0596-Fix-console-spam-when-removing-chests-in-water.patch rename to patches/server/0597-Fix-console-spam-when-removing-chests-in-water.patch diff --git a/patches/server/0597-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server/0598-Add-toggle-for-always-placing-the-dragon-egg.patch similarity index 100% rename from patches/server/0597-Add-toggle-for-always-placing-the-dragon-egg.patch rename to patches/server/0598-Add-toggle-for-always-placing-the-dragon-egg.patch diff --git a/patches/server/0598-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server/0599-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from patches/server/0598-Added-PlayerStonecutterRecipeSelectEvent.patch rename to patches/server/0599-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/patches/server/0599-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/server/0600-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from patches/server/0599-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/server/0600-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/patches/server/0600-Skip-distance-map-update-when-spawning-disabled.patch b/patches/server/0601-Skip-distance-map-update-when-spawning-disabled.patch similarity index 87% rename from patches/server/0600-Skip-distance-map-update-when-spawning-disabled.patch rename to patches/server/0601-Skip-distance-map-update-when-spawning-disabled.patch index 40fde190b3..f68ef8f362 100644 --- a/patches/server/0600-Skip-distance-map-update-when-spawning-disabled.patch +++ b/patches/server/0601-Skip-distance-map-update-when-spawning-disabled.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Skip distance map update when spawning disabled. diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 7ab28e9bd3f785838b7fa4ac5811c0e71cddcb61..b609740fb95ccd4c9d7a2a95fad3dfbff630db5f 100644 +index d13abec908dbb756272888e9ccdedbefff719012..d013d693a94369da6df00934b986b303160f5a07 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -778,7 +778,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -810,7 +810,7 @@ public class ServerChunkCache extends ChunkSource { int l = this.distanceManager.getNaturalSpawnChunkCount(); // Paper start - per player mob spawning NaturalSpawner.SpawnState spawnercreature_d; // moved down diff --git a/patches/server/0601-Reset-shield-blocking-on-dimension-change.patch b/patches/server/0602-Reset-shield-blocking-on-dimension-change.patch similarity index 83% rename from patches/server/0601-Reset-shield-blocking-on-dimension-change.patch rename to patches/server/0602-Reset-shield-blocking-on-dimension-change.patch index dac062f779..aa3eb4e6c1 100644 --- a/patches/server/0601-Reset-shield-blocking-on-dimension-change.patch +++ b/patches/server/0602-Reset-shield-blocking-on-dimension-change.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Reset shield blocking on dimension change diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 5a87875b03740053d8cde6d81c57703d0b0ef57e..f9cf0c088f4c3de0a1a7b92beb6ee0c57a0b1326 100644 +index f412f3b9f3af498b9ced4a808849442efad01b69..d0e9bbecb4b0cf980116c72b96ae8edd74f9bfd6 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1117,6 +1117,11 @@ public class ServerPlayer extends Player { +@@ -1139,6 +1139,11 @@ public class ServerPlayer extends Player { this.level.getCraftServer().getPluginManager().callEvent(changeEvent); // CraftBukkit end } diff --git a/patches/server/0602-add-DragonEggFormEvent.patch b/patches/server/0603-add-DragonEggFormEvent.patch similarity index 100% rename from patches/server/0602-add-DragonEggFormEvent.patch rename to patches/server/0603-add-DragonEggFormEvent.patch diff --git a/patches/server/0603-EntityMoveEvent.patch b/patches/server/0604-EntityMoveEvent.patch similarity index 100% rename from patches/server/0603-EntityMoveEvent.patch rename to patches/server/0604-EntityMoveEvent.patch diff --git a/patches/server-remapped/0667-added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server/0605-added-option-to-disable-pathfinding-updates-on-block.patch similarity index 80% rename from patches/server-remapped/0667-added-option-to-disable-pathfinding-updates-on-block.patch rename to patches/server/0605-added-option-to-disable-pathfinding-updates-on-block.patch index ca84c216d2..176d82a83b 100644 --- a/patches/server-remapped/0667-added-option-to-disable-pathfinding-updates-on-block.patch +++ b/patches/server/0605-added-option-to-disable-pathfinding-updates-on-block.patch @@ -5,10 +5,10 @@ Subject: [PATCH] added option to disable pathfinding updates on block changes diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 40939de88b1a8169dbfc7a0cd288c2fe9b706426..bbb1d0ed9e76f414dc7d73b4f7786891425f55cd 100644 +index 7738b5959f347cb369646852e7174aa580546400..c6cbc656f2cf6b253c3dfc87b8367f11102c7e41 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -800,4 +800,9 @@ public class PaperWorldConfig { +@@ -688,5 +688,10 @@ public class PaperWorldConfig { private void enderDragonsDeathAlwaysPlacesDragonEgg() { enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); } @@ -18,11 +18,12 @@ index 40939de88b1a8169dbfc7a0cd288c2fe9b706426..bbb1d0ed9e76f414dc7d73b4f7786891 + updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); + } } + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 338b4c382fb8ea349ce81f2009e96de1df7ac5e2..a7553a856b9c99bee8f75d514b97cfab952bfd33 100644 +index 5cd1fe3506b1009de9fce64c3f4f44a29f13c359..a2d9e093bf7b5ee947f1d7c3b94397cd93eedef7 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1678,6 +1678,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1360,6 +1360,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl @Override public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) { this.getChunkSource().blockChanged(pos); @@ -30,9 +31,9 @@ index 338b4c382fb8ea349ce81f2009e96de1df7ac5e2..a7553a856b9c99bee8f75d514b97cfab VoxelShape voxelshape = oldState.getCollisionShape(this, pos); VoxelShape voxelshape1 = newState.getCollisionShape(this, pos); -@@ -1706,6 +1707,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1387,6 +1388,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } - this.tickingEntities = wasTicking; // Paper } + } // Paper } diff --git a/patches/server-remapped/0668-Inline-shift-direction-fields.patch b/patches/server/0606-Inline-shift-direction-fields.patch similarity index 60% rename from patches/server-remapped/0668-Inline-shift-direction-fields.patch rename to patches/server/0606-Inline-shift-direction-fields.patch index bf3e677ed6..5be0e06548 100644 --- a/patches/server-remapped/0668-Inline-shift-direction-fields.patch +++ b/patches/server/0606-Inline-shift-direction-fields.patch @@ -7,11 +7,11 @@ Removes a layer of indirection for EnumDirection.getAdjacent(X|Y|Z)(), which is critical section for much of the server, including the lighting engine. diff --git a/src/main/java/net/minecraft/core/Direction.java b/src/main/java/net/minecraft/core/Direction.java -index 3ebc62fe93a0cd0048e07b0343fc724f2c056010..51217f7e5288162b8e76c8717506b393cd262537 100644 +index e8e9494f7f337ee91a56fbd299da015dcda4a81b..593d6251c75ec337175d08b85000239ba7da1af2 100644 --- a/src/main/java/net/minecraft/core/Direction.java +++ b/src/main/java/net/minecraft/core/Direction.java -@@ -53,6 +53,11 @@ public enum Direction implements StringRepresentable { - }, (enumdirection, enumdirection1) -> { +@@ -62,6 +62,11 @@ public enum Direction implements StringRepresentable { + }, (direction1, direction2) -> { throw new IllegalArgumentException("Duplicate keys"); }, Long2ObjectOpenHashMap::new)); + // Paper start @@ -20,21 +20,21 @@ index 3ebc62fe93a0cd0048e07b0343fc724f2c056010..51217f7e5288162b8e76c8717506b393 + private final int adjZ; + // Paper end - private Direction(int i, int j, int k, String s, Direction.AxisDirection enumdirection_enumaxisdirection, Direction.Axis enumdirection_enumaxis, Vec3i baseblockposition) { - this.data3d = i; -@@ -62,6 +67,11 @@ public enum Direction implements StringRepresentable { - this.axis = enumdirection_enumaxis; - this.axisDirection = enumdirection_enumaxisdirection; - this.normal = baseblockposition; + private Direction(int id, int idOpposite, int idHorizontal, String name, Direction.AxisDirection direction, Direction.Axis axis, Vec3i vector) { + this.data3d = id; +@@ -71,6 +76,11 @@ public enum Direction implements StringRepresentable { + this.axis = axis; + this.axisDirection = direction; + this.normal = vector; + // Paper start -+ this.adjX = baseblockposition.getX(); -+ this.adjY = baseblockposition.getY(); -+ this.adjZ = baseblockposition.getZ(); ++ this.adjX = vector.getX(); ++ this.adjY = vector.getY(); ++ this.adjZ = vector.getZ(); + // Paper end } public static Direction[] orderedByNearest(Entity entity) { -@@ -137,15 +147,15 @@ public enum Direction implements StringRepresentable { +@@ -310,15 +320,15 @@ public enum Direction implements StringRepresentable { } public int getStepX() { @@ -52,4 +52,4 @@ index 3ebc62fe93a0cd0048e07b0343fc724f2c056010..51217f7e5288162b8e76c8717506b393 + return this.adjZ; // Paper } - public String getName() { + public Vector3f step() { diff --git a/patches/server-remapped/0669-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server/0607-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 92% rename from patches/server-remapped/0669-Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/server/0607-Allow-adding-items-to-BlockDropItemEvent.patch index 973fb6de6c..169393cd20 100644 --- a/patches/server-remapped/0669-Allow-adding-items-to-BlockDropItemEvent.patch +++ b/patches/server/0607-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 ea7c30ef17fc66c1fb55d5909f94651c98b181be..5145968c9c6ccabfb15b91102f82e8a3a2d3cf82 100644 +index 2b5f63c3f0ff3039fbef9afdfa46e0e715d347bc..dcd59630c9e8870128859b9022827aeefebec963 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -389,13 +389,30 @@ public class CraftEventFactory { +@@ -390,13 +390,30 @@ public class CraftEventFactory { } public static void handleBlockDropItemEvent(Block block, BlockState state, ServerPlayer player, List items) { diff --git a/patches/server-remapped/0670-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/server/0608-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 92% rename from patches/server-remapped/0670-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/server/0608-Add-getMainThreadExecutor-to-BukkitScheduler.patch index f2acd9e212..63e7f01676 100644 --- a/patches/server-remapped/0670-Add-getMainThreadExecutor-to-BukkitScheduler.patch +++ b/patches/server/0608-Add-getMainThreadExecutor-to-BukkitScheduler.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add getMainThreadExecutor to BukkitScheduler diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 13e461ffb2ee2e7d0440c0f60809ea99629b843c..0be39dac4b9dd69d7d73d86d64cf1e33e4086e81 100644 +index 33480893ddee34a1983c5f1c4b14db98ff438528..d20438fcfc2baf7c826d1723738dbad3fdd123ee 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java @@ -635,4 +635,15 @@ public class CraftScheduler implements BukkitScheduler { diff --git a/patches/server-remapped/0671-living-entity-allow-attribute-registration.patch b/patches/server/0609-living-entity-allow-attribute-registration.patch similarity index 70% rename from patches/server-remapped/0671-living-entity-allow-attribute-registration.patch rename to patches/server/0609-living-entity-allow-attribute-registration.patch index 78a2270873..2782de61f6 100644 --- a/patches/server-remapped/0671-living-entity-allow-attribute-registration.patch +++ b/patches/server/0609-living-entity-allow-attribute-registration.patch @@ -5,19 +5,10 @@ Subject: [PATCH] living entity allow attribute registration diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java -index a501f334ce0bcc606dd2bb186cf7195102cd6c09..8acd102c0778e4e546e5191b6098eacbd15bd9f9 100644 +index cb9ed449ed96474d2115a3023ff0b7b298548071..9cbfda029782385d1a7987f5be46d450bd8a758e 100644 --- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java +++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java -@@ -21,7 +21,7 @@ import org.apache.logging.log4j.Logger; - public class AttributeMap { - - private static final Logger LOGGER = LogManager.getLogger(); -- private final Map attributes = Maps.newHashMap(); -+ private final Map attributes = Maps.newHashMap(); private final Map attributeMap = attributes; // Paper - OBFHELPER - private final Set dirtyAttributes = Sets.newHashSet(); - private final AttributeSupplier supplier; - -@@ -135,4 +135,12 @@ public class AttributeMap { +@@ -132,4 +132,12 @@ public class AttributeMap { } } @@ -25,13 +16,13 @@ index a501f334ce0bcc606dd2bb186cf7195102cd6c09..8acd102c0778e4e546e5191b6098eacb + // Paper - start + public void registerAttribute(Attribute attributeBase) { + AttributeInstance attributeModifiable = new AttributeInstance(attributeBase, AttributeInstance::getAttribute); -+ attributeMap.put(attributeBase, attributeModifiable); ++ attributes.put(attributeBase, attributeModifiable); + } + // Paper - end + } diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -index 320fd6780af2fa99e4e4f4193cbc9338d492dc6d..a57b16679889f5b20c74712651f94d6796b8c661 100644 +index 46c313d581b9af6aa0a48f97ae3cc800a88535f2..07d700382fc356837045c46d320b7b69ad13af68 100644 --- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java +++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java @@ -38,6 +38,14 @@ public class CraftAttributeMap implements Attributable { @@ -50,11 +41,11 @@ index 320fd6780af2fa99e4e4f4193cbc9338d492dc6d..a57b16679889f5b20c74712651f94d67 return net.minecraft.core.Registry.ATTRIBUTE.get(CraftNamespacedKey.toMinecraft(attribute.getKey())); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index a8d21382d5859edfd12e01a48924ce780790b4b7..eefb6bd580ea176c3a242695ab4af46e7c61b492 100644 +index 2ca223324cc079e397852c30c969a05814585cde..eed0fb2293cf1e19f2d4f4b66a9e2ef8b214141c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -663,6 +663,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().craftAttributes.getAttribute(attribute); + return this.getHandle().craftAttributes.getAttribute(attribute); } + // Paper start diff --git a/patches/server-remapped/0672-fix-dead-slime-setSize-invincibility.patch b/patches/server/0610-fix-dead-slime-setSize-invincibility.patch similarity index 70% rename from patches/server-remapped/0672-fix-dead-slime-setSize-invincibility.patch rename to patches/server/0610-fix-dead-slime-setSize-invincibility.patch index 72df11355c..33ce1b72f2 100644 --- a/patches/server-remapped/0672-fix-dead-slime-setSize-invincibility.patch +++ b/patches/server/0610-fix-dead-slime-setSize-invincibility.patch @@ -5,15 +5,15 @@ Subject: [PATCH] fix dead slime setSize invincibility diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -index 340036135588d06e43cbd229dd3a6613b04bb9ab..d1bb7e1f7f7837774512e0af0c8b855d34d5a85b 100644 +index 4d401403de2399919043651345eed91c11ac986f..3c5326b1b4b18365e06292eca447778442201176 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java @@ -17,7 +17,7 @@ public class CraftSlime extends CraftMob implements Slime { @Override public void setSize(int size) { -- getHandle().setSize(size, true); -+ getHandle().setSize(size, /* true */ getHandle().isAlive()); // Paper - fix dead slime setSize invincibility +- this.getHandle().setSize(size, true); ++ this.getHandle().setSize(size, /* true */ getHandle().isAlive()); // Paper - fix dead slime setSize invincibility } @Override diff --git a/patches/server-remapped/0673-Merchant-getRecipes-should-return-an-immutable-list.patch b/patches/server/0611-Merchant-getRecipes-should-return-an-immutable-list.patch similarity index 61% rename from patches/server-remapped/0673-Merchant-getRecipes-should-return-an-immutable-list.patch rename to patches/server/0611-Merchant-getRecipes-should-return-an-immutable-list.patch index c4baf4a043..f316582cb5 100644 --- a/patches/server-remapped/0673-Merchant-getRecipes-should-return-an-immutable-list.patch +++ b/patches/server/0611-Merchant-getRecipes-should-return-an-immutable-list.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Merchant#getRecipes should return an immutable list diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -index 3437ec2c7c1a84debb7d7b7c90283d7e25208604..b4bcbd6329c67ea3deeeb1bf38233ebd15e922b7 100644 +index 425c8de426cecc9919d03dc64325494104d1b294..fcd6574857f77d547fd8101c5ac097bc6306034c 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java @@ -24,7 +24,7 @@ public class CraftMerchant implements Merchant { @Override public List getRecipes() { -- return Collections.unmodifiableList(Lists.transform(merchant.getOffers(), new Function() { -+ return com.google.common.collect.ImmutableList.copyOf(Lists.transform(merchant.getOffers(), new Function() { // Paper - javadoc says 'an immutable list of trades' - not 'an unmodifiable view of a list of trades'. fixes issue with setRecipes(getRecipes()) +- return Collections.unmodifiableList(Lists.transform(this.merchant.getOffers(), new Function() { ++ return com.google.common.collect.ImmutableList.copyOf(Lists.transform(this.merchant.getOffers(), new Function() { // Paper - javadoc says 'an immutable list of trades' - not 'an unmodifiable view of a list of trades'. fixes issue with setRecipes(getRecipes()) @Override public MerchantRecipe apply(net.minecraft.world.item.trading.MerchantOffer recipe) { return recipe.asBukkit(); diff --git a/patches/server-remapped/0674-misc-debugging-dumps.patch b/patches/server/0612-misc-debugging-dumps.patch similarity index 59% rename from patches/server-remapped/0674-misc-debugging-dumps.patch rename to patches/server/0612-misc-debugging-dumps.patch index f56af1f8b5..3b8113783b 100644 --- a/patches/server-remapped/0674-misc-debugging-dumps.patch +++ b/patches/server/0612-misc-debugging-dumps.patch @@ -29,59 +29,43 @@ index 0000000000000000000000000000000000000000..2d5494d2813b773e60ddba6790b750a9 + } +} diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index bc44811f26076871848ba8f5c582ab26b1fd7170..9b654fed2a00740cef84cf72258abfc7aeafc0c2 100644 +index c8213692e658f6eb82d3bd843b9525ff6565cc81..f1c1d715d509aeb13e465cd57a82896db6c51838 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -14,6 +14,7 @@ import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; - import io.papermc.paper.adventure.PaperAdventure; // Paper - import io.papermc.paper.event.entity.EntityMoveEvent; -+import io.papermc.paper.util.TraceUtil; - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -855,6 +856,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Fri, 26 Feb 2021 16:24:25 -0600 +Subject: [PATCH] Expose Tracked Players + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 79527b4806c306b9811f6e93733836e658fea0fe..db920ef12e918b7dfdcc4612c4bec0b9961d9a3e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2312,6 +2312,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + // Paper end + ++ // Paper start ++ @Override ++ public Set getTrackedPlayers() { ++ if (entity.tracker == null) { ++ return java.util.Collections.emptySet(); ++ } ++ ++ Set set = new HashSet<>(entity.tracker.seenBy.size()); ++ for (net.minecraft.server.network.ServerPlayerConnection connection : entity.tracker.seenBy) { ++ set.add(connection.getPlayer().getBukkitEntity().getPlayer()); ++ } ++ return set; ++ } ++ // Paper end ++ + // Spigot start + private final Player.Spigot spigot = new Player.Spigot() + { diff --git a/patches/server/0615-Remove-streams-from-SensorNearest.patch b/patches/server/0615-Remove-streams-from-SensorNearest.patch new file mode 100644 index 0000000000..3ef5964d12 --- /dev/null +++ b/patches/server/0615-Remove-streams-from-SensorNearest.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Bjarne Koll +Date: Wed, 3 Mar 2021 12:48:48 +0100 +Subject: [PATCH] Remove streams from SensorNearest + +The behavioural nearby sensors are validated every tick on the entities +that registered the respective sensors and are therefore a good subject +to performance improvements. + +More specifically this commit replaces the Stream#filter usage with +ArrayList#removeIf as the removeIf method on an array list is heavily +optimized towards a single internal array re-allocation without any +further overhead on the removeIf call. + +The only negative of this change is the rather agressive diff these +patches introduce as the methods are basically being reimplemented +compared to the previous stream-based implementation. + +See: https://nipafx.dev/java-stream-performance/ + +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java +index 7680c269c2fe0cf2a51d0ebeb34624181826d578..49f3b25d28072b61f5cc97260df61df892a58714 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java +@@ -28,11 +28,15 @@ public class NearestItemSensor extends Sensor { + return true; + }); + list.sort(Comparator.comparingDouble(entity::distanceToSqr)); +- Optional optional = list.stream().filter((itemEntity) -> { +- return entity.wantsToPickUp(itemEntity.getItem()); +- }).filter((itemEntity) -> { +- return itemEntity.closerThan(entity, 9.0D); +- }).filter(entity::hasLineOfSight).findFirst(); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); ++ // Paper start - remove streams in favour of lists ++ ItemEntity nearest = null; ++ for (ItemEntity entityItem : list) { ++ if (entity.wantsToPickUp(entityItem.getItem()) && entityItem.closerThan(entity, 9.0D) && entity.hasLineOfSight(entityItem)) { ++ nearest = entityItem; ++ break; ++ } ++ } ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +index 66c90013e52170a657b1a5dbdb99748a19fe55e8..ffd83db0a419ab589e89feeddd3fb038d6ed5839 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +@@ -21,9 +21,11 @@ public class NearestLivingEntitySensor extends Sensor { + list.sort(Comparator.comparingDouble(entity::distanceToSqr)); + Brain brain = entity.getBrain(); + brain.setMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES, list); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, list.stream().filter((livingEntity2) -> { +- return isEntityTargetable(entity, livingEntity2); +- }).collect(Collectors.toList())); ++ // Paper start - remove streams in favour of lists ++ List visibleMobs = new java.util.ArrayList<>(list); ++ visibleMobs.removeIf(otherEntityLiving -> !Sensor.isEntityTargetable(entity, otherEntityLiving)); ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, visibleMobs); ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +index b51574548b370f8a86d27835e9888ce1cd1d18be..457ea75137b8b02dc32bf1769ae8d57c470da470 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +@@ -21,18 +21,25 @@ public class PlayerSensor extends Sensor { + + @Override + protected void doTick(ServerLevel world, LivingEntity entity) { +- List list = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((serverPlayer) -> { +- return entity.closerThan(serverPlayer, 16.0D); +- }).sorted(Comparator.comparingDouble(entity::distanceToSqr)).collect(Collectors.toList()); ++ // Paper start - remove streams in favour of lists ++ List players = new java.util.ArrayList<>(world.players()); ++ players.removeIf(player -> !EntitySelector.NO_SPECTATORS.test(player) || !entity.closerThan(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator + Brain brain = entity.getBrain(); +- brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, list); +- List list2 = list.stream().filter((player) -> { +- return isEntityTargetable(entity, player); +- }).collect(Collectors.toList()); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, list2.isEmpty() ? null : list2.get(0)); +- Optional optional = list2.stream().filter((player) -> { +- return isEntityAttackable(entity, player); +- }).findFirst(); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, optional); ++ ++ brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); ++ ++ Player nearest = null, nearestTargetable = null; ++ for (Player player : players) { ++ if (Sensor.isEntityTargetable(entity, player)) { ++ if (nearest == null) nearest = player; ++ if (Sensor.isEntityAttackable(entity, player)) { ++ nearestTargetable = player; ++ break; // Both variables are assigned, no reason to loop further ++ } ++ } ++ } ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, nearestTargetable); ++ // Paper end + } + } diff --git a/patches/server-remapped/0680-MC-29274-Fix-Wither-hostility-towards-players.patch b/patches/server/0616-MC-29274-Fix-Wither-hostility-towards-players.patch similarity index 84% rename from patches/server-remapped/0680-MC-29274-Fix-Wither-hostility-towards-players.patch rename to patches/server/0616-MC-29274-Fix-Wither-hostility-towards-players.patch index ec43d966cb..019deb51e8 100644 --- a/patches/server-remapped/0680-MC-29274-Fix-Wither-hostility-towards-players.patch +++ b/patches/server/0616-MC-29274-Fix-Wither-hostility-towards-players.patch @@ -5,10 +5,10 @@ Subject: [PATCH] MC-29274: Fix Wither hostility towards players diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index bbb1d0ed9e76f414dc7d73b4f7786891425f55cd..eb367b8feda8219a97a547c3ef6ab82d278d2f25 100644 +index c6cbc656f2cf6b253c3dfc87b8367f11102c7e41..caa15973d78e21725b5dd9e5fc91cede4cc0dac4 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -805,4 +805,10 @@ public class PaperWorldConfig { +@@ -693,5 +693,11 @@ public class PaperWorldConfig { private void setUpdatePathfindingOnBlockUpdate() { updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); } @@ -19,11 +19,12 @@ index bbb1d0ed9e76f414dc7d73b4f7786891425f55cd..eb367b8feda8219a97a547c3ef6ab82d + log("Withers properly target players: " + fixWitherTargetingBug); + } } + diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index fd91c80cd6337b5fa41d6060ecdb44b8fa68a16a..b364b442d4cb1f3351850140b85c62c30c888bed 100644 +index 1e479853ec239b5e970b478adb3419e400d2f1d6..1c8f6863b976cfcb559de9b3e3cf9292831166ee 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -102,6 +102,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -105,6 +105,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); diff --git a/patches/server-remapped/0681-Throw-proper-exception-on-empty-JsonList-file.patch b/patches/server/0617-Throw-proper-exception-on-empty-JsonList-file.patch similarity index 91% rename from patches/server-remapped/0681-Throw-proper-exception-on-empty-JsonList-file.patch rename to patches/server/0617-Throw-proper-exception-on-empty-JsonList-file.patch index cdc493b6d3..5350e561c4 100644 --- a/patches/server-remapped/0681-Throw-proper-exception-on-empty-JsonList-file.patch +++ b/patches/server/0617-Throw-proper-exception-on-empty-JsonList-file.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Throw proper exception on empty JsonList file diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java -index e2982a8ac5448110378bc92247952332bdffe12c..71de59cadcbd214b9e3a91a6051f918d9b421b16 100644 +index 4b85943a704e0a5ca6b95f9cfcbfd1f9505c3b68..bfac2eb1ad06e82fed92574c1dd07e33f1440db7 100644 --- a/src/main/java/net/minecraft/server/players/StoredUserList.java +++ b/src/main/java/net/minecraft/server/players/StoredUserList.java @@ -189,6 +189,7 @@ public abstract class StoredUserList> { diff --git a/patches/server-remapped/0682-Improve-ServerGUI.patch b/patches/server/0618-Improve-ServerGUI.patch similarity index 92% rename from patches/server-remapped/0682-Improve-ServerGUI.patch rename to patches/server/0618-Improve-ServerGUI.patch index 46ebed8c68..2ddf152c7a 100644 --- a/patches/server-remapped/0682-Improve-ServerGUI.patch +++ b/patches/server/0618-Improve-ServerGUI.patch @@ -7,7 +7,7 @@ Subject: [PATCH] Improve ServerGUI - Show tps in the server stats diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -index c0923ec75ecced2e0a1c0d3ec2c046d69af3e9a9..a3e17c1cb54938908d72d3e86e43f4655f1db194 100644 +index 23239679d6584f1088b2b94c46eb9a5c1f9ad91d..fa56cd09102a89692b42f1d14257990508c5c720 100644 --- a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java @@ -57,9 +57,18 @@ public class RAMDetails extends JList { @@ -23,27 +23,26 @@ index c0923ec75ecced2e0a1c0d3ec2c046d69af3e9a9..a3e17c1cb54938908d72d3e86e43f465 + } vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); - vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); + vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.tickTimes)) + " ms"); + vector.add("TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg)); + setListData(vector); } -@@ -70,4 +79,9 @@ public class RAMDetails extends JList { +@@ -70,4 +79,8 @@ public class RAMDetails extends JList { } return ((double) total / (double) tickTimes.length) * 1.0E-6D; } + -+ private static String format(double tps) -+ { ++ private static String format(double tps) { + return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); + } } diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java -index 2567c588a1dcf732800e6cf87352b020c7bb84d6..ad912fae191777256dd88f6c863ec92f8b6a9c13 100644 +index 703d2bb93d6ab76fc117a320f155570addcc543c..07f0c5f629741e4ecc1fcbc122ba7700174e5c9d 100644 --- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java +++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java -@@ -31,6 +31,11 @@ import net.minecraft.DefaultUncaughtExceptionHandler; +@@ -32,6 +32,11 @@ import net.minecraft.DefaultUncaughtExceptionHandler; import net.minecraft.server.dedicated.DedicatedServer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -55,7 +54,7 @@ index 2567c588a1dcf732800e6cf87352b020c7bb84d6..ad912fae191777256dd88f6c863ec92f public class MinecraftServerGui extends JComponent { -@@ -56,6 +61,15 @@ public class MinecraftServerGui extends JComponent { +@@ -59,6 +64,15 @@ public class MinecraftServerGui extends JComponent { jframe.pack(); jframe.setLocationRelativeTo((Component) null); jframe.setVisible(true); @@ -72,22 +71,13 @@ index 2567c588a1dcf732800e6cf87352b020c7bb84d6..ad912fae191777256dd88f6c863ec92f public void windowClosing(WindowEvent windowevent) { if (!servergui.isClosing.getAndSet(true)) { diff --git a/src/main/java/net/minecraft/server/gui/StatsComponent.java b/src/main/java/net/minecraft/server/gui/StatsComponent.java -index 09414d04208a843f8d337569b53f61b34e64ed92..d2583c762fe655dd1d7bed1061e41cd08ac0c092 100644 +index 4c5059805715bbca53196bcabd7eda550a46c34d..88f10d729aa1e0a01790521821d691a0ecd373a2 100644 --- a/src/main/java/net/minecraft/server/gui/StatsComponent.java +++ b/src/main/java/net/minecraft/server/gui/StatsComponent.java -@@ -18,7 +18,7 @@ public class StatsComponent extends JComponent { - }); - private final int[] values = new int[256]; - private int vp; -- private final String[] msgs = new String[11]; -+ private final String[] msgs = new String[12]; public String[] getStatEntries() { return this.msgs; } // Paper - change size, OBFHELPER - private final MinecraftServer server; - private final Timer timer; +@@ -35,8 +35,17 @@ public class StatsComponent extends JComponent { -@@ -37,8 +37,18 @@ public class StatsComponent extends JComponent { private void tick() { - long i = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - + long l = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + // Paper start - Add tps entry + double[] tps = org.bukkit.Bukkit.getTPS(); + String[] tpsAvg = new String[tps.length]; @@ -95,22 +85,21 @@ index 09414d04208a843f8d337569b53f61b34e64ed92..d2583c762fe655dd1d7bed1061e41cd0 + for ( int g = 0; g < tps.length; g++) { + tpsAvg[g] = format( tps[g] ); + } - this.msgs[0] = "Memory use: " + i / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)"; - this.msgs[1] = "Avg tick: " + StatsComponent.DECIMAL_FORMAT.format(this.getAverage(this.server.tickTimes) * 1.0E-6D) + " ms"; -+ getStatEntries()[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg); + this.msgs[0] = "Memory use: " + l / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)"; + this.msgs[1] = "Avg tick: " + DECIMAL_FORMAT.format(this.getAverage(this.server.tickTimes) * 1.0E-6D) + " ms"; ++ this.msgs[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg); + // Paper end -+ - this.values[this.vp++ & 255] = (int) (i * 100L / Runtime.getRuntime().maxMemory()); + this.values[this.vp++ & 255] = (int)(l * 100L / Runtime.getRuntime().maxMemory()); this.repaint(); } -@@ -85,4 +95,10 @@ public class StatsComponent extends JComponent { +@@ -76,4 +85,10 @@ public class StatsComponent extends JComponent { public void close() { this.timer.stop(); } + + // Paper - start Add tps entry + private static String format(double tps) { -+ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise ++ return (( tps > 21.0 ) ? "*" : "") + Math.min(Math.round(tps * 100.0) / 100.0, 20.0); // only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise + } + // Paper end } diff --git a/patches/server-remapped/0683-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/patches/server/0619-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch similarity index 100% rename from patches/server-remapped/0683-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch rename to patches/server/0619-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch diff --git a/patches/server-remapped/0684-fix-converting-txt-to-json-file.patch b/patches/server/0620-fix-converting-txt-to-json-file.patch similarity index 64% rename from patches/server-remapped/0684-fix-converting-txt-to-json-file.patch rename to patches/server/0620-fix-converting-txt-to-json-file.patch index 950227fe76..2d0213dc1f 100644 --- a/patches/server-remapped/0684-fix-converting-txt-to-json-file.patch +++ b/patches/server/0620-fix-converting-txt-to-json-file.patch @@ -5,13 +5,13 @@ Subject: [PATCH] fix converting txt to json file diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -index 603b4f841bcc276997d130f1545c4cf550dcac2d..2eafb7e27d06a975cee48cc18c7596d610483d16 100644 +index aeb91eefa0949b2a53d77f1e4a48a29b9d1bc3fe..918f5221e94cbc867349c69c83563e225d2fef1d 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -@@ -18,6 +18,11 @@ public class DedicatedPlayerList extends PlayerList { - - this.setViewDistance(dedicatedserverproperties.viewDistance); - super.setUsingWhiteList((Boolean) dedicatedserverproperties.whiteList.get()); +@@ -16,6 +16,11 @@ public class DedicatedPlayerList extends PlayerList { + DedicatedServerProperties dedicatedServerProperties = server.getProperties(); + this.setViewDistance(dedicatedServerProperties.viewDistance); + super.setUsingWhiteList(dedicatedServerProperties.whiteList.get()); + // Paper start - moved from constructor + } + @Override @@ -21,10 +21,10 @@ index 603b4f841bcc276997d130f1545c4cf550dcac2d..2eafb7e27d06a975cee48cc18c7596d6 this.saveUserBanList(); this.loadIpBanList(); diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 95f9863bbccaa23d08c409792314df4f2397a317..c2947313cc0eda3247fb4b20ddd1d0b86c37c50a 100644 +index a5c1114f9b323e8a49c84d0e68461e473bbcd690..eadacfa8449336c024f6154f46bb514d8e1230ec 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -195,6 +195,12 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -204,6 +204,12 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); org.spigotmc.SpigotConfig.registerCommands(); // Spigot end @@ -37,31 +37,18 @@ index 95f9863bbccaa23d08c409792314df4f2397a317..c2947313cc0eda3247fb4b20ddd1d0b8 // Paper start try { com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); -@@ -257,10 +263,6 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -265,9 +271,6 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface DedicatedServer.LOGGER.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file."); } - if (this.convertOldUsers()) { -- this.getProfileCache().b(false); // Paper +- this.getProfileCache().save(false); // Paper - } -- + if (!OldUsersConverter.serverReadyAfterUserconversion(this)) { return false; - } else { -diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index 941b7e356c377fd8ad4e27409cd74c0046878396..f23ca6bebf2c0b7e02dc6aa51e384cee4e3d12c3 100644 ---- a/src/main/java/net/minecraft/server/players/GameProfileCache.java -+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java -@@ -243,6 +243,7 @@ public class GameProfileCache { - return arraylist; - } - -+ public void save(boolean asyncSave) { b(asyncSave); } // Paper - OBFHELPER - public void b(boolean asyncSave) { // Paper - JsonArray jsonarray = new JsonArray(); - DateFormat dateformat = createDateFormat(); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index c962b6fc0c65dc5e2ea636220727bca63bf4b740..dd121ec8f779b3786eeb7fe85519cf9e472f5adf 100644 +index 213bfc7637b649a8e578d9a122fc4fce3c9fe9ea..12a10d6586b0b1d95e2b1a229f922286753f066c 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -171,6 +171,7 @@ public abstract class PlayerList { diff --git a/patches/server-remapped/0685-Add-worldborder-events.patch b/patches/server/0621-Add-worldborder-events.patch similarity index 52% rename from patches/server-remapped/0685-Add-worldborder-events.patch rename to patches/server/0621-Add-worldborder-events.patch index 33286aca0e..a78c112f12 100644 --- a/patches/server-remapped/0685-Add-worldborder-events.patch +++ b/patches/server/0621-Add-worldborder-events.patch @@ -5,27 +5,17 @@ Subject: [PATCH] Add worldborder events diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index aaa6251838483de5c46913534413151b5cb1d3fe..4ad686f4fcd3a23c4230faa03946db1f338bc904 100644 +index 4a61153eaf9cf4c8aa532f770c0e449325448107..a30cd5a649a3086b794f1cb03bc0e02846b2f558 100644 --- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java +++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -14,6 +14,9 @@ import net.minecraft.world.phys.AABB; - import net.minecraft.world.phys.shapes.BooleanOp; - import net.minecraft.world.phys.shapes.Shapes; - import net.minecraft.world.phys.shapes.VoxelShape; -+import io.papermc.paper.event.world.border.WorldBorderBoundsChangeFinishEvent; // Paper -+import io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent; // Paper -+import io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent; // Paper - - public class WorldBorder { - -@@ -102,15 +105,19 @@ public class WorldBorder { +@@ -110,15 +110,19 @@ public class WorldBorder { } public void setCenter(double x, double z) { - this.centerX = x; - this.centerZ = z; + // Paper start -+ WorldBorderCenterChangeEvent event = new WorldBorderCenterChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), new org.bukkit.Location(world.getWorld(), this.getCenterX(), 0, this.getCenterZ()), new org.bukkit.Location(world.getWorld(), x, 0, z)); ++ io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent event = new io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), new org.bukkit.Location(world.getWorld(), this.getCenterX(), 0, this.getCenterZ()), new org.bukkit.Location(world.getWorld(), x, 0, z)); + if (!event.callEvent()) return; + this.centerX = event.getNewCenter().getX(); + this.centerZ = event.getNewCenter().getZ(); @@ -41,15 +31,15 @@ index aaa6251838483de5c46913534413151b5cb1d3fe..4ad686f4fcd3a23c4230faa03946db1f } } -@@ -128,25 +135,43 @@ public class WorldBorder { +@@ -136,25 +140,43 @@ public class WorldBorder { } public void setSize(double size) { - this.extent = new WorldBorder.StaticBorderExtent(size); + // Paper start -+ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE, getSize(), size, 0); ++ io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent event = new io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE, getSize(), size, 0); + if (!event.callEvent()) return; -+ if (event.getType() == WorldBorderBoundsChangeEvent.Type.STARTED_MOVE && event.getDuration() > 0) { // If changed to a timed transition ++ if (event.getType() == io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type.STARTED_MOVE && event.getDuration() > 0) { // If changed to a timed transition + lerpSizeBetween(event.getOldSize(), event.getNewSize(), event.getDuration()); + return; + } @@ -69,13 +59,13 @@ index aaa6251838483de5c46913534413151b5cb1d3fe..4ad686f4fcd3a23c4230faa03946db1f public void lerpSizeBetween(double fromSize, double toSize, long time) { - this.extent = (WorldBorder.BorderExtent) (fromSize == toSize ? new WorldBorder.StaticBorderExtent(toSize) : new WorldBorder.MovingBorderExtent(fromSize, toSize, time)); + // Paper start -+ WorldBorderBoundsChangeEvent.Type type; ++ io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type type; + if (fromSize == toSize) { // new size = old size -+ type = WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE; // Use INSTANT_MOVE because below it creates a Static border if they are equal. ++ type = io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE; // Use INSTANT_MOVE because below it creates a Static border if they are equal. + } else { -+ type = WorldBorderBoundsChangeEvent.Type.STARTED_MOVE; ++ type = io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type.STARTED_MOVE; + } -+ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), type, fromSize, toSize, time); ++ io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent event = new io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), type, fromSize, toSize, time); + if (!event.callEvent()) return; + this.extent = (WorldBorder.BorderExtent) (fromSize == event.getNewSize() ? new WorldBorder.StaticBorderExtent(event.getNewSize()) : new WorldBorder.MovingBorderExtent(fromSize, event.getNewSize(), event.getDuration())); + // Paper end @@ -89,34 +79,11 @@ index aaa6251838483de5c46913534413151b5cb1d3fe..4ad686f4fcd3a23c4230faa03946db1f } } -@@ -434,11 +459,11 @@ public class WorldBorder { - - class MovingBorderExtent implements WorldBorder.BorderExtent { - -- private final double from; -- private final double to; -+ private final double from; public final double getOldSize() { return this.from; } // Paper - OBFHELPER -+ private final double to; public final double getNewSize() { return this.to; } // Paper - OBFHELPER - private final long lerpEnd; - private final long lerpBegin; -- private final double lerpDuration; -+ private final double lerpDuration; public final double getDuration() { return this.lerpDuration; } // Paper - OBFHELPER - - private MovingBorderExtent(double d0, double d1, long i) { - this.from = d0; -@@ -493,6 +518,7 @@ public class WorldBorder { +@@ -459,6 +481,7 @@ public class WorldBorder { @Override public WorldBorder.BorderExtent update() { -+ if (this.getLerpTimeRemaining() <= 0L) new WorldBorderBoundsChangeFinishEvent(world.getWorld(), world.getWorld().getWorldBorder(), getOldSize(), getNewSize(), getDuration()).callEvent(); // Paper ++ if (this.getLerpRemainingTime() <= 0L) new io.papermc.paper.event.world.border.WorldBorderBoundsChangeFinishEvent(world.getWorld(), world.getWorld().getWorldBorder(), this.from, this.to, this.lerpDuration).callEvent(); // Paper return (WorldBorder.BorderExtent) (this.getLerpRemainingTime() <= 0L ? WorldBorder.this.new StaticBorderExtent(this.to) : this); } -@@ -514,6 +540,7 @@ public class WorldBorder { - - double getSize(); - -+ default long getLerpTimeRemaining() { return getLerpRemainingTime(); } // Paper - OBFHELPER - long getLerpRemainingTime(); - - double getLerpTarget(); diff --git a/patches/server-remapped/0686-added-PlayerNameEntityEvent.patch b/patches/server/0622-added-PlayerNameEntityEvent.patch similarity index 80% rename from patches/server-remapped/0686-added-PlayerNameEntityEvent.patch rename to patches/server/0622-added-PlayerNameEntityEvent.patch index 64f85dbc14..c1df33b717 100644 --- a/patches/server-remapped/0686-added-PlayerNameEntityEvent.patch +++ b/patches/server/0622-added-PlayerNameEntityEvent.patch @@ -5,37 +5,34 @@ Subject: [PATCH] added PlayerNameEntityEvent diff --git a/src/main/java/net/minecraft/world/item/NameTagItem.java b/src/main/java/net/minecraft/world/item/NameTagItem.java -index 5e38077c3de0a40f3cfd856bf2e48f7061e39a9d..5c575798c20f15d28350f767ecf15bfc042ebc8c 100644 +index 13080fb2350d4ee2107063948dd2ef359dff8306..623f78c078fb3aa2665d7e8a37672438227bce6b 100644 --- a/src/main/java/net/minecraft/world/item/NameTagItem.java +++ b/src/main/java/net/minecraft/world/item/NameTagItem.java -@@ -1,5 +1,10 @@ +@@ -1,5 +1,9 @@ package net.minecraft.world.item; +// Paper start +import io.papermc.paper.adventure.PaperAdventure; +import io.papermc.paper.event.player.PlayerNameEntityEvent; +// Paper end -+import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; -@@ -16,11 +21,15 @@ public class NameTagItem extends Item { +@@ -15,9 +19,14 @@ public class NameTagItem extends Item { public InteractionResult interactLivingEntity(ItemStack stack, Player user, LivingEntity entity, InteractionHand hand) { if (stack.hasCustomHoverName() && !(entity instanceof Player)) { if (!user.level.isClientSide && entity.isAlive()) { - entity.setCustomName(stack.getHoverName()); - if (entity instanceof Mob) { -- ((Mob) entity).setPersistenceRequired(); +- ((Mob)entity).setPersistenceRequired(); + // Paper start -+ PlayerNameEntityEvent event = new PlayerNameEntityEvent(((ServerPlayer) user).getBukkitEntity(), entity.getBukkitLivingEntity(), PaperAdventure.asAdventure(stack.getHoverName()), true); ++ PlayerNameEntityEvent event = new PlayerNameEntityEvent(((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity(), entity.getBukkitLivingEntity(), PaperAdventure.asAdventure(stack.getHoverName()), true); + if (!event.callEvent()) return InteractionResult.PASS; + LivingEntity newEntityLiving = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle(); + newEntityLiving.setCustomName(event.getName() != null ? PaperAdventure.asVanilla(event.getName()) : null); + if (event.isPersistent() && newEntityLiving instanceof Mob) { + ((Mob) newEntityLiving).setPersistenceRequired(); - } -- + // Paper end - stack.shrink(1); - } + } + stack.shrink(1); diff --git a/patches/server-remapped/0687-Prevent-grindstones-from-overstacking-items.patch b/patches/server/0623-Prevent-grindstones-from-overstacking-items.patch similarity index 89% rename from patches/server-remapped/0687-Prevent-grindstones-from-overstacking-items.patch rename to patches/server/0623-Prevent-grindstones-from-overstacking-items.patch index 9f050a4e9b..1dc9e0fcf3 100644 --- a/patches/server-remapped/0687-Prevent-grindstones-from-overstacking-items.patch +++ b/patches/server/0623-Prevent-grindstones-from-overstacking-items.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Prevent grindstones from overstacking items diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -index 329a6d70d53c13cd554c64996f2ddc489bdc1e94..445d408963538fbc01d61902805b2e35c861e4ce 100644 +index b260216460b0bbf75edc631bb69e3e4fc94d459a..4414f59b17d3a5232dc2def1816964610fe03b68 100644 --- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -@@ -195,13 +195,13 @@ public class GrindstoneMenu extends AbstractContainerMenu { +@@ -199,13 +199,13 @@ public class GrindstoneMenu extends AbstractContainerMenu { i = Math.max(item.getMaxDamage() - l, 0); itemstack2 = this.mergeEnchants(itemstack, itemstack1); if (!itemstack2.isDamageableItem()) { diff --git a/patches/server-remapped/0688-Add-recipe-to-cook-events.patch b/patches/server/0624-Add-recipe-to-cook-events.patch similarity index 55% rename from patches/server-remapped/0688-Add-recipe-to-cook-events.patch rename to patches/server/0624-Add-recipe-to-cook-events.patch index e43e7804ac..d8aaa16e04 100644 --- a/patches/server-remapped/0688-Add-recipe-to-cook-events.patch +++ b/patches/server/0624-Add-recipe-to-cook-events.patch @@ -5,40 +5,40 @@ Subject: [PATCH] Add recipe to cook events diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index f47b46cebd43faa509b8139d2a51cc8f87615893..2dcabfc765cbf6341546a7e2c48156fd921fcc82 100644 +index f1e44b57f8c77ee279b4be0853923dcd95f71f0a..7b17cc405acab015d9fb1fe233875c6b17bf782d 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -393,7 +393,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -407,7 +407,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); -- FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()), source, result); -+ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()), source, result, (org.bukkit.inventory.CookingRecipe) recipe.toBukkitRecipe()); // Paper - this.level.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent); +- FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(world, blockposition), source, result); ++ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(world, blockposition), source, result, (org.bukkit.inventory.CookingRecipe) irecipe.toBukkitRecipe()); // Paper + world.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent); if (furnaceSmeltEvent.isCancelled()) { diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -index 6c38361d744eae763b6c131ad314485f5a88fcfc..39b4782df965c785be7946d6964e0b7a4381ff74 100644 +index ad35d82f03f7643507dde6adbb38c911d12ec6c1..9f00de75b6f206c11ce7d1c59ba98fafe02fa9ab 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -@@ -73,7 +73,10 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable, Ticka +@@ -53,7 +53,10 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { - if (this.cookingProgress[i] >= this.cookingTime[i]) { + if (campfire.cookingProgress[i] >= campfire.cookingTime[i]) { SimpleContainer inventorysubcontainer = new SimpleContainer(new ItemStack[]{itemstack}); -- ItemStack itemstack1 = (ItemStack) this.level.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, inventorysubcontainer, this.level).map((recipecampfire) -> { +- ItemStack itemstack1 = (ItemStack) world.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, inventorysubcontainer, world).map((recipecampfire) -> { + // Paper start -+ Optional recipe = this.level.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, inventorysubcontainer, this.level); ++ Optional recipe = world.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, inventorysubcontainer, world); + ItemStack itemstack1 = (ItemStack) recipe.map((recipecampfire) -> { + // Paper end return recipecampfire.assemble(inventorysubcontainer); }).orElse(itemstack); - BlockPos blockposition = this.getBlockPos(); -@@ -82,7 +85,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable, Ticka + +@@ -61,7 +64,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); -- BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.level, this.worldPosition), source, result); -+ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.level, this.worldPosition), source, result, (org.bukkit.inventory.CookingRecipe) recipe.map(CampfireCookingRecipe::toBukkitRecipe).orElse(null)); // Paper - this.level.getCraftServer().getPluginManager().callEvent(blockCookEvent); +- BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(world, pos), source, result); ++ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(world, pos), source, result, (org.bukkit.inventory.CookingRecipe) recipe.map(CampfireCookingRecipe::toBukkitRecipe).orElse(null)); // Paper + world.getCraftServer().getPluginManager().callEvent(blockCookEvent); if (blockCookEvent.isCancelled()) { diff --git a/patches/server-remapped/0689-Add-Block-isValidTool.patch b/patches/server/0625-Add-Block-isValidTool.patch similarity index 79% rename from patches/server-remapped/0689-Add-Block-isValidTool.patch rename to patches/server/0625-Add-Block-isValidTool.patch index a9fe23e278..7a3a143aeb 100644 --- a/patches/server-remapped/0689-Add-Block-isValidTool.patch +++ b/patches/server/0625-Add-Block-isValidTool.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add Block#isValidTool diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 376b0497c28a35d7ea615397c87b2558b95c596a..def19e23996b85e1e540cd5edc6821ae0ae37f91 100644 +index f69ad3ccfe885f3acde930ea844d3bc471ce661b..2f50a731216780ee6d592370c49f3a7a4d93948a 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -803,5 +803,9 @@ public class CraftBlock implements Block { +@@ -819,5 +819,9 @@ public class CraftBlock implements Block { } return speed; } diff --git a/patches/server-remapped/0690-Allow-using-signs-inside-spawn-protection.patch b/patches/server/0626-Allow-using-signs-inside-spawn-protection.patch similarity index 68% rename from patches/server-remapped/0690-Allow-using-signs-inside-spawn-protection.patch rename to patches/server/0626-Allow-using-signs-inside-spawn-protection.patch index fa0bc9f104..1c8a0a68b4 100644 --- a/patches/server-remapped/0690-Allow-using-signs-inside-spawn-protection.patch +++ b/patches/server/0626-Allow-using-signs-inside-spawn-protection.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow using signs inside spawn protection diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index eb367b8feda8219a97a547c3ef6ab82d278d2f25..108a005c296c4ed370de4af636163088971bed13 100644 +index caa15973d78e21725b5dd9e5fc91cede4cc0dac4..46601a98d9f06c6cfadc8120bcffab081ca7f557 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -811,4 +811,9 @@ public class PaperWorldConfig { +@@ -699,5 +699,10 @@ public class PaperWorldConfig { fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); log("Withers properly target players: " + fixWitherTargetingBug); } @@ -18,24 +18,17 @@ index eb367b8feda8219a97a547c3ef6ab82d278d2f25..108a005c296c4ed370de4af636163088 + allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); + } } + diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index cb6568b622abeb939a1195f4656accc8a1c3f1fc..1add53082ab9382cb2e90dc8305b8c71ef1c6a46 100644 +index 8051cc5950b71f284e7ad8be685977fd098fe022..f5de1e31b62a4e04b865ab041e122d33c7efd54e 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -152,6 +152,7 @@ import net.minecraft.world.level.Level; - import net.minecraft.world.level.LevelReader; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.CommandBlock; -+import net.minecraft.world.level.block.SignBlock; - import net.minecraft.world.level.block.entity.BlockEntity; - import net.minecraft.world.level.block.entity.CommandBlockEntity; - import net.minecraft.world.level.block.entity.JigsawBlockEntity; -@@ -1690,7 +1691,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1723,7 +1723,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + int i = this.player.level.getMaxBuildHeight(); - this.player.resetLastActionTime(); - if (blockposition.getY() < this.server.getMaxBuildHeight()) { + if (blockposition.getY() < i) { - if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition)) { -+ if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && (worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition) || (worldserver.paperConfig.allowUsingSignsInsideSpawnProtection && worldserver.getBlockState(blockposition).getBlock() instanceof SignBlock))) { // Paper ++ if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && (worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition) || (worldserver.paperConfig.allowUsingSignsInsideSpawnProtection && worldserver.getBlockState(blockposition).getBlock() instanceof net.minecraft.world.level.block.SignBlock))) { // Paper // CraftBukkit start - Check if we can actually do something over this large a distance // Paper - move check up this.player.stopUsingItem(); // SPIGOT-4706 diff --git a/patches/server/0627-Implement-Keyed-on-World.patch b/patches/server/0627-Implement-Keyed-on-World.patch new file mode 100644 index 0000000000..8b4d4dd266 --- /dev/null +++ b/patches/server/0627-Implement-Keyed-on-World.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 6 Jan 2021 00:34:04 -0800 +Subject: [PATCH] Implement Keyed on World + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 40496bc7b1ce71c898078f7713600ac05922dcf1..bd7db12503c3175c3bd71f8a0fe3a826eb043000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1155,7 +1155,7 @@ public final class CraftServer implements Server { + } else if (name.equals(levelName + "_the_end")) { + worldKey = net.minecraft.world.level.Level.END; + } else { +- worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(name.toLowerCase(java.util.Locale.ENGLISH))); ++ worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, new net.minecraft.resources.ResourceLocation(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper + } + + ServerLevel internal = (ServerLevel) new ServerLevel(this.console, console.executor, worldSession, worlddata, worldKey, dimensionmanager, this.getServer().progressListenerFactory.create(11), +@@ -1246,6 +1246,15 @@ public final class CraftServer implements Server { + return null; + } + ++ // Paper start ++ @Override ++ public World getWorld(NamespacedKey worldKey) { ++ ServerLevel worldServer = console.getLevel(ResourceKey.create(Registry.DIMENSION_REGISTRY, CraftNamespacedKey.toMinecraft(worldKey))); ++ if (worldServer == null) return null; ++ return worldServer.getWorld(); ++ } ++ // Paper end ++ + public void addWorld(World world) { + // Check if a World already exists with the UID. + if (this.getWorld(world.getUID()) != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index c36a9eedaa587d513a3be78054d15f4ad96d4d7c..c67cd478da70b4a6f97eed6e964d74dc57e07e71 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2584,6 +2584,11 @@ public class CraftWorld implements World { + return java.util.concurrent.CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + }, net.minecraft.server.MinecraftServer.getServer()); + } ++ ++ @Override ++ public org.bukkit.NamespacedKey getKey() { ++ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(world.dimension().location()); ++ } + // Paper end + + // Spigot start diff --git a/patches/server-remapped/0692-Add-fast-alternative-constructor-for-Vector3f.patch b/patches/server/0628-Add-fast-alternative-constructor-for-Rotations.patch similarity index 79% rename from patches/server-remapped/0692-Add-fast-alternative-constructor-for-Vector3f.patch rename to patches/server/0628-Add-fast-alternative-constructor-for-Rotations.patch index b395761137..d2a627b5b6 100644 --- a/patches/server-remapped/0692-Add-fast-alternative-constructor-for-Vector3f.patch +++ b/patches/server/0628-Add-fast-alternative-constructor-for-Rotations.patch @@ -1,12 +1,12 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Irmo van den Berge Date: Wed, 10 Mar 2021 21:26:31 +0100 -Subject: [PATCH] Add fast alternative constructor for Vector3f +Subject: [PATCH] Add fast alternative constructor for Rotations Signed-off-by: Irmo van den Berge diff --git a/src/main/java/net/minecraft/core/Rotations.java b/src/main/java/net/minecraft/core/Rotations.java -index e3c2affb5dfaf2d78139e98c9e8a40b37c92bf2f..4782cbd9d86d8246954db76993741a8a749a7fe0 100644 +index d6b192ffa208f2bfc16238933ab2af9c61607796..dd0f0a4567a7d1749e5265649e0fa816aadd6826 100644 --- a/src/main/java/net/minecraft/core/Rotations.java +++ b/src/main/java/net/minecraft/core/Rotations.java @@ -19,6 +19,18 @@ public class Rotations { @@ -26,5 +26,5 @@ index e3c2affb5dfaf2d78139e98c9e8a40b37c92bf2f..4782cbd9d86d8246954db76993741a8a + // Paper end + public ListTag save() { - ListTag nbttaglist = new ListTag(); - + ListTag listTag = new ListTag(); + listTag.add(FloatTag.valueOf(this.x)); diff --git a/patches/server/0629-Item-Rarity-API.patch b/patches/server/0629-Item-Rarity-API.patch new file mode 100644 index 0000000000..0fc250e89d --- /dev/null +++ b/patches/server/0629-Item-Rarity-API.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 12 Mar 2021 17:09:42 -0800 +Subject: [PATCH] Item Rarity API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index f70d7b1c9b10f59b4d9c8575b9cc35409fec11e4..6816c2a5487d96e65acacef438fa43a0e3808b99 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -470,6 +470,20 @@ public final class CraftMagicNumbers implements UnsafeValues { + public int nextEntityId() { + return net.minecraft.world.entity.Entity.nextEntityId(); + } ++ ++ @Override ++ public io.papermc.paper.inventory.ItemRarity getItemRarity(org.bukkit.Material material) { ++ Item item = getItem(material); ++ if (item == null) { ++ throw new IllegalArgumentException(material + " is not an item, and rarity does not apply to blocks"); ++ } ++ return io.papermc.paper.inventory.ItemRarity.values()[item.rarity.ordinal()]; ++ } ++ ++ @Override ++ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { ++ return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; ++ } + // Paper end + + /** diff --git a/patches/server-remapped/0694-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/patches/server/0630-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch similarity index 74% rename from patches/server-remapped/0694-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch rename to patches/server/0630-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch index c076df0076..dbdfe748f0 100644 --- a/patches/server-remapped/0694-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch +++ b/patches/server/0630-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Only set despawnTimer for Wandering Traders spawned by diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index d38828485d6deb08036e11d8bf16b3d63a60fbae..f6d2aca2fe3ee9b69a0b200c8b2ea35f222fb521 100644 +index b3c07e22d4e7107ca22242661fa9ecf2d81fc9e4..2b82859d4ac43036e346220333e676998742d56d 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -319,6 +319,12 @@ public class EntityType { +@@ -334,6 +334,12 @@ public class EntityType implements EntityTypeTest { @Nullable public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { @@ -22,7 +22,7 @@ index d38828485d6deb08036e11d8bf16b3d63a60fbae..f6d2aca2fe3ee9b69a0b200c8b2ea35f // Paper start - Call PreCreatureSpawnEvent org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath()); if (type != null) { -@@ -334,6 +340,7 @@ public class EntityType { +@@ -349,6 +355,7 @@ public class EntityType implements EntityTypeTest { } // Paper end T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); @@ -31,28 +31,28 @@ index d38828485d6deb08036e11d8bf16b3d63a60fbae..f6d2aca2fe3ee9b69a0b200c8b2ea35f if (t0 != null) { worldserver.addAllEntities(t0, spawnReason); diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -index 69d92590d265abe8a04d8bf48bbe9a6ae606ae50..04c4cca4be8886feb59f180915977b77f9c7dde8 100644 +index 59c4ab697ef0a336ffce19d215952f3a8ff0852b..9f9b48546fd1ae23a04cad060b6996e21354efbb 100644 --- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -@@ -61,7 +61,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -60,7 +60,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + public WanderingTrader(EntityType type, Level world) { super(type, world); - this.forcedLoading = true; - this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader + //this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set. } @Override diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -index 9074d57e1576db2da3e4c76add4f7e07e5567879..f861d83affbb0b5eaf7440a909ca3b5f7a604da7 100644 +index 60f08ecd0034e8ef2965b54b3abccce582d0ca54..f8ede3588bfda9a7d4d5807311a3e9c2651fd0a3 100644 --- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -@@ -114,7 +114,7 @@ public class WanderingTraderSpawner implements CustomSpawner { +@@ -121,7 +121,7 @@ public class WanderingTraderSpawner implements CustomSpawner { return false; } -- WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawnCreature(worldserver, (CompoundTag) null, (Component) null, (Player) null, blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit -+ WanderingTrader entityvillagertrader = EntityType.WANDERING_TRADER.spawnCreature(worldserver, null, null, null, blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, trader -> trader.setDespawnDelay(48000)); // CraftBukkit // Paper - set despawnTimer before spawn events called +- WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawnCreature(world, (CompoundTag) null, (Component) null, (Player) null, blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit ++ WanderingTrader entityvillagertrader = EntityType.WANDERING_TRADER.spawnCreature(world, null, null, null, blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, trader -> trader.setDespawnDelay(48000)); // CraftBukkit // Paper - set despawnTimer before spawn events called if (entityvillagertrader != null) { for (int i = 0; i < 2; ++i) { diff --git a/patches/server-remapped/0695-copy-TESign-isEditable-from-snapshots.patch b/patches/server/0631-copy-TESign-isEditable-from-snapshots.patch similarity index 80% rename from patches/server-remapped/0695-copy-TESign-isEditable-from-snapshots.patch rename to patches/server/0631-copy-TESign-isEditable-from-snapshots.patch index 862aed64d3..d45654d7c6 100644 --- a/patches/server-remapped/0695-copy-TESign-isEditable-from-snapshots.patch +++ b/patches/server/0631-copy-TESign-isEditable-from-snapshots.patch @@ -5,10 +5,10 @@ Subject: [PATCH] copy TESign#isEditable from snapshots diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -index 65e8a349c80a700f63dd27b11bb2099f65cbc069..eb0739c0927e821a5080d14e762225fd4936b82d 100644 +index 6e89b039479a034d98d1ec183b06d5418ab51733..924a8278ffc27f0db5f50c16ff06ddfc3042f333 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -@@ -109,6 +109,7 @@ public class CraftSign extends CraftBlockEntityState implements +@@ -118,6 +118,7 @@ public class CraftSign extends CraftBlockEntityState implements } // Paper end } diff --git a/patches/server-remapped/0696-Drop-carried-item-when-player-has-disconnected.patch b/patches/server/0632-Drop-carried-item-when-player-has-disconnected.patch similarity index 55% rename from patches/server-remapped/0696-Drop-carried-item-when-player-has-disconnected.patch rename to patches/server/0632-Drop-carried-item-when-player-has-disconnected.patch index 4e8128fd64..e74bd6d322 100644 --- a/patches/server-remapped/0696-Drop-carried-item-when-player-has-disconnected.patch +++ b/patches/server/0632-Drop-carried-item-when-player-has-disconnected.patch @@ -7,25 +7,17 @@ Fixes disappearance of held items, when a player gets disconnected and PlayerDro Closes #5036 diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index dd121ec8f779b3786eeb7fe85519cf9e472f5adf..23cfaf5c432221f2d1afe37ba657f723d6d21a73 100644 +index 12a10d6586b0b1d95e2b1a229f922286753f066c..b744653a7508ba2aea859709e7ea3c58fbb586cf 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -79,6 +79,7 @@ import net.minecraft.world.effect.MobEffectInstance; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; - import net.minecraft.world.entity.npc.AbstractVillager; -+import net.minecraft.world.item.ItemStack; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.GameType; -@@ -605,6 +606,14 @@ public abstract class PlayerList { +@@ -606,6 +606,14 @@ public abstract class PlayerList { } // Paper end + // Paper - Drop carried item when player has disconnected -+ if (!entityplayer.inventory.getCarried().isEmpty()) { -+ ItemStack carried = entityplayer.inventory.getCarried(); -+ entityplayer.inventory.setCarried(ItemStack.NULL_ITEM); ++ if (!entityplayer.containerMenu.getCarried().isEmpty()) { ++ net.minecraft.world.item.ItemStack carried = entityplayer.containerMenu.getCarried(); ++ entityplayer.containerMenu.setCarried(net.minecraft.world.item.ItemStack.EMPTY); + entityplayer.drop(carried, false); + } + // Paper end diff --git a/patches/server-remapped/0697-forced-whitelist-use-configurable-kick-message.patch b/patches/server/0633-forced-whitelist-use-configurable-kick-message.patch similarity index 86% rename from patches/server-remapped/0697-forced-whitelist-use-configurable-kick-message.patch rename to patches/server/0633-forced-whitelist-use-configurable-kick-message.patch index 4b433dc16c..a57d85fa8d 100644 --- a/patches/server-remapped/0697-forced-whitelist-use-configurable-kick-message.patch +++ b/patches/server/0633-forced-whitelist-use-configurable-kick-message.patch @@ -5,10 +5,10 @@ Subject: [PATCH] forced whitelist: use configurable kick message diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 9b654fed2a00740cef84cf72258abfc7aeafc0c2..fd76d776c7003585c9efef44c6d7da0f6c3f574e 100644 +index f1c1d715d509aeb13e465cd57a82896db6c51838..73ac55de9059a1d0f1da5bec0688dcd4bf5c8973 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -73,7 +73,6 @@ import net.minecraft.nbt.NbtOps; +@@ -77,7 +77,6 @@ import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TextComponent; @@ -16,7 +16,7 @@ index 9b654fed2a00740cef84cf72258abfc7aeafc0c2..fd76d776c7003585c9efef44c6d7da0f import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; import net.minecraft.network.protocol.game.ClientboundSetTimePacket; -@@ -2040,7 +2039,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Mon, 5 Apr 2021 18:35:15 -0700 +Subject: [PATCH] Don't ignore result of PlayerEditBookEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index f5de1e31b62a4e04b865ab041e122d33c7efd54e..95b229081a4d51d63f477ef7894a938584d87fd0 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1191,7 +1191,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } + + itemstack.addTagElement("pages", (Tag) nbttaglist); +- CraftEventFactory.handleEditBookEvent(player, slot, old, itemstack); // CraftBukkit ++ this.player.containerMenu.setItem(slot, CraftEventFactory.handleEditBookEvent(player, slot, old, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) + } + + @Override diff --git a/patches/server/0635-fix-cancelling-block-falling-causing-client-desync.patch b/patches/server/0635-fix-cancelling-block-falling-causing-client-desync.patch new file mode 100644 index 0000000000..b3b4cf1fcb --- /dev/null +++ b/patches/server/0635-fix-cancelling-block-falling-causing-client-desync.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trigary +Date: Sat, 27 Mar 2021 11:13:30 +0100 +Subject: [PATCH] fix cancelling block falling causing client desync + + +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 2fad050547242028d4ff2deb613e074190f51341..3989ed1bd5c666aa7759ebc2c57a0d5f70d85838 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -119,8 +119,18 @@ public class FallingBlockEntity extends Entity { + + if (this.time++ == 0) { + blockposition = this.blockPosition(); +- if (this.level.getBlockState(blockposition).is(block) && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { +- this.level.removeBlock(blockposition, false); ++ // Paper start - fix cancelling block falling causing client desync ++ if (this.level.getBlockState(blockposition).is(block)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ if (this.level.getBlockState(blockposition).is(block)) { //if listener didn't update the block ++ ((ServerLevel) level).getChunkSource().blockChanged(blockposition); ++ } ++ this.discard(); ++ return; ++ } else { ++ this.level.setAir(blockposition, false); ++ } ++ // Paper end - fix cancelling block falling causing client desync + } else if (!this.level.isClientSide) { + this.discard(); + return; diff --git a/patches/server-remapped/0701-Expose-protocol-version.patch b/patches/server/0636-Expose-protocol-version.patch similarity index 82% rename from patches/server-remapped/0701-Expose-protocol-version.patch rename to patches/server/0636-Expose-protocol-version.patch index 0e4392f5f9..065e44668c 100644 --- a/patches/server-remapped/0701-Expose-protocol-version.patch +++ b/patches/server/0636-Expose-protocol-version.patch @@ -5,12 +5,12 @@ 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 472b0615dcdc3c0c52bd377fd69752716f354262..402e5a98290a1701dd67d27c484c97e0a6067c4f 100644 +index 6816c2a5487d96e65acacef438fa43a0e3808b99..5c49c4e671b9d44c12f8d8efcf97305a41e5dbe1 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -484,6 +484,11 @@ public final class CraftMagicNumbers implements UnsafeValues { public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { - return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; + return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; } + + @Override diff --git a/patches/server-remapped/0702-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/server/0637-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 93% rename from patches/server-remapped/0702-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to patches/server/0637-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch index 036bfe3e5a..90d013302e 100644 --- a/patches/server-remapped/0702-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch +++ b/patches/server/0637-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch @@ -6,17 +6,17 @@ Subject: [PATCH] Allow for Component suggestion tooltips in diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 65afc23f4791aca19bff78ed86b3b0d31fa81977..67defaf71752ed29fde483e8232aa358ffa53675 100644 +index 95b229081a4d51d63f477ef7894a938584d87fd0..f5c79ec1293c72b738bb6bc1d0aa9d495eefe194 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -769,12 +769,11 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -758,12 +758,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // Paper start - async tab completion com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; - java.util.List completions = new java.util.ArrayList<>(); String buffer = packet.getCommand(); -- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), +- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getCraftPlayer(), completions, ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getCraftPlayer(), buffer, true, null); event.callEvent(); - completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); @@ -24,7 +24,7 @@ index 65afc23f4791aca19bff78ed86b3b0d31fa81977..67defaf71752ed29fde483e8232aa358 // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server if (!event.isHandled()) { if (!event.isCancelled()) { -@@ -793,10 +792,16 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -782,10 +781,16 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser }); } } else if (!completions.isEmpty()) { @@ -42,10 +42,10 @@ index 65afc23f4791aca19bff78ed86b3b0d31fa81977..67defaf71752ed29fde483e8232aa358 + } + }); com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); - com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); + com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getCraftPlayer(), suggestions, buffer); suggestEvent.setCancelled(suggestions.isEmpty()); diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index c5e00bd9e2790992202aadf8eec2002fc88c78f1..dd8e87ad192c19743577bb95253a127072ea196c 100644 +index e5af155d75f717d33c23e22ff8b96bb3ff87844d..14cd8ae69d9b25dc5edad4ff96ff4a9acb1f22cb 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java @@ -29,34 +29,56 @@ public class ConsoleCommandCompleter implements Completer { diff --git a/patches/server-remapped/0703-Enhance-console-tab-completions-for-brigadier-comman.patch b/patches/server/0638-Enhance-console-tab-completions-for-brigadier-comman.patch similarity index 79% rename from patches/server-remapped/0703-Enhance-console-tab-completions-for-brigadier-comman.patch rename to patches/server/0638-Enhance-console-tab-completions-for-brigadier-comman.patch index f6416177a9..0609bfa202 100644 --- a/patches/server-remapped/0703-Enhance-console-tab-completions-for-brigadier-comman.patch +++ b/patches/server/0638-Enhance-console-tab-completions-for-brigadier-comman.patch @@ -21,18 +21,10 @@ index c56e7fb18f9a56c8025eb70a524f028b5942da37..efc1e42d606e1c9feb1a4871c0714933 + } } diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -index a4070b59e261f0f1ac4beec47b11492f4724bf27..372a459bd08f79f10ffd1391ec492e37f1e8bb50 100644 +index a4070b59e261f0f1ac4beec47b11492f4724bf27..e0b1f0671d16ddddcb6725acd25a1d1d69e42701 100644 --- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -@@ -1,5 +1,7 @@ - package com.destroystokyo.paper.console; - -+import com.destroystokyo.paper.PaperConfig; -+import io.papermc.paper.console.BrigadierCommandHighlighter; - import net.minecraft.server.dedicated.DedicatedServer; - import net.minecrell.terminalconsole.SimpleTerminalConsole; - import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; -@@ -16,11 +18,15 @@ public final class PaperConsole extends SimpleTerminalConsole { +@@ -16,11 +16,15 @@ public final class PaperConsole extends SimpleTerminalConsole { @Override protected LineReader buildReader(LineReaderBuilder builder) { @@ -43,8 +35,8 @@ index a4070b59e261f0f1ac4beec47b11492f4724bf27..372a459bd08f79f10ffd1391ec492e37 .completer(new ConsoleCommandCompleter(this.server)) - ); + .option(LineReader.Option.COMPLETE_IN_WORD, true); -+ if (PaperConfig.enableBrigadierConsoleHighlighting) { -+ builder.highlighter(new BrigadierCommandHighlighter(this.server, this.server.createCommandSourceStack())); ++ if (com.destroystokyo.paper.PaperConfig.enableBrigadierConsoleHighlighting) { ++ builder.highlighter(new io.papermc.paper.console.BrigadierCommandHighlighter(this.server, this.server.createCommandSourceStack())); + } + return super.buildReader(builder); } @@ -52,7 +44,7 @@ index a4070b59e261f0f1ac4beec47b11492f4724bf27..372a459bd08f79f10ffd1391ec492e37 @Override diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java new file mode 100644 -index 0000000000000000000000000000000000000000..2768028750fb9a95b3f3b409d047be14bb0083d5 +index 0000000000000000000000000000000000000000..d3f80b5dcd366c5b8a48cb885d825d243b01ac4c --- /dev/null +++ b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java @@ -0,0 +1,95 @@ @@ -92,7 +84,7 @@ index 0000000000000000000000000000000000000000..2768028750fb9a95b3f3b409d047be14 + this.addCandidates(candidates, Collections.emptyList(), existing); + return; + } -+ final CommandDispatcher dispatcher = this.server.getCommands().dispatcher(); ++ final CommandDispatcher dispatcher = this.server.getCommands().getDispatcher(); + final ParseResults results = dispatcher.parse(prepareStringReader(line.line()), this.commandSourceStack); + this.addCandidates( + candidates, @@ -153,7 +145,7 @@ index 0000000000000000000000000000000000000000..2768028750fb9a95b3f3b409d047be14 +} diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java new file mode 100644 -index 0000000000000000000000000000000000000000..812027fb84e1b7825f2dd0fb6fa33831367c2dc0 +index 0000000000000000000000000000000000000000..f33e9376bd166ebdb3d9f8c7467cd923ea0aadeb --- /dev/null +++ b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java @@ -0,0 +1,57 @@ @@ -184,7 +176,7 @@ index 0000000000000000000000000000000000000000..812027fb84e1b7825f2dd0fb6fa33831 + @Override + public AttributedString highlight(final @NonNull LineReader reader, final @NonNull String buffer) { + final AttributedStringBuilder builder = new AttributedStringBuilder(); -+ final ParseResults results = this.server.getCommands().dispatcher().parse(BrigadierCommandCompleter.prepareStringReader(buffer), this.commandSourceStack); ++ final ParseResults results = this.server.getCommands().getDispatcher().parse(BrigadierCommandCompleter.prepareStringReader(buffer), this.commandSourceStack); + int pos = 0; + if (buffer.startsWith("/")) { + builder.append("/", AttributedStyle.DEFAULT); @@ -214,43 +206,8 @@ index 0000000000000000000000000000000000000000..812027fb84e1b7825f2dd0fb6fa33831 + return builder.toAttributedString(); + } +} -diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java -index 5ed78383ce247ceb24cda0335dbeae293958055c..e2f18b5bf1e091fe5fd868520a6d1bcc2669c24c 100644 ---- a/src/main/java/net/minecraft/commands/Commands.java -+++ b/src/main/java/net/minecraft/commands/Commands.java -@@ -440,7 +440,7 @@ public class Commands { - }; - } - -- public com.mojang.brigadier.CommandDispatcher getDispatcher() { -+ public com.mojang.brigadier.CommandDispatcher getDispatcher() { return this.dispatcher(); } public com.mojang.brigadier.CommandDispatcher dispatcher() { // Paper - OBFHELPER - return this.dispatcher; - } - -diff --git a/src/main/java/net/minecraft/network/chat/ComponentUtils.java b/src/main/java/net/minecraft/network/chat/ComponentUtils.java -index b5a59aed5d5cfbe0f75a8209b058b368b1f2b595..ed90c4348ca030d678251b0f9891d00153992f89 100644 ---- a/src/main/java/net/minecraft/network/chat/ComponentUtils.java -+++ b/src/main/java/net/minecraft/network/chat/ComponentUtils.java -@@ -90,7 +90,7 @@ public class ComponentUtils { - TextComponent chatcomponenttext = new TextComponent(""); - boolean flag = true; - -- for (Iterator iterator = elements.iterator(); iterator.hasNext(); flag = false) { -+ for (Iterator iterator = elements.iterator(); iterator.hasNext(); flag = false) { // Paper - decompile fix - T t0 = iterator.next(); - - if (!flag) { -@@ -108,7 +108,7 @@ public class ComponentUtils { - return new TranslatableComponent("chat.square_brackets", new Object[]{text}); - } - -- public static Component fromMessage(Message message) { -+ public static Component fromMessage(Message message) { return fromMessage(message); } public static Component fromMessage(final @org.checkerframework.checker.nullness.qual.NonNull Message message) { // Paper - OBFHELPER - return (Component) (message instanceof Component ? (Component) message : new TextComponent(message.getString())); - } - } diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index dd8e87ad192c19743577bb95253a127072ea196c..eaad328d0d15ef450bb5a305828ce413d1eab53b 100644 +index 14cd8ae69d9b25dc5edad4ff96ff4a9acb1f22cb..b3484487fa8baa4d1dd6c595586fb26a01a2153d 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java +++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java @@ -18,9 +18,11 @@ import org.bukkit.event.server.TabCompleteEvent; diff --git a/patches/server-remapped/0704-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/patches/server/0639-Fix-PlayerItemConsumeEvent-cancelling-properly.patch similarity index 87% rename from patches/server-remapped/0704-Fix-PlayerItemConsumeEvent-cancelling-properly.patch rename to patches/server/0639-Fix-PlayerItemConsumeEvent-cancelling-properly.patch index a86a2c1b40..a990ea2e7b 100644 --- a/patches/server-remapped/0704-Fix-PlayerItemConsumeEvent-cancelling-properly.patch +++ b/patches/server/0639-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 8bc74878919ab7cf6a50d425da61f1b8a8b0ee44..37787a725725d22b0870dcab0f3bec8b94cfd130 100644 +index 8c3fb37c511ada39dafdd19fa85e21a1b458386b..b954fcfcf3bd3c55ca856126670fa6967d525fe3 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3348,6 +3348,7 @@ public abstract class LivingEntity extends Entity { +@@ -3696,6 +3696,7 @@ public abstract class LivingEntity extends Entity { level.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { diff --git a/patches/server-remapped/0705-Add-bypass-host-check.patch b/patches/server/0640-Add-bypass-host-check.patch similarity index 77% rename from patches/server-remapped/0705-Add-bypass-host-check.patch rename to patches/server/0640-Add-bypass-host-check.patch index 88f6d3d8dc..80d7b918c3 100644 --- a/patches/server-remapped/0705-Add-bypass-host-check.patch +++ b/patches/server/0640-Add-bypass-host-check.patch @@ -8,13 +8,13 @@ Paper.bypassHostCheck Seriously, fix your firewalls. -.- diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -index c648b73a4c478f9d8020274205d6684f7c7c416f..4e055a41de3ee410682cc05a3b883ac8babeb290 100644 +index 2384ae5082afd01c4f28fe2f3f782cdce15ff3f2..4c44f06ba18cfa2d889d0dd57fdd7eb79971c8c6 100644 --- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java @@ -30,6 +30,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL private static final Component IGNORE_STATUS_REASON = new TextComponent("Ignoring status request"); private final MinecraftServer server; - private final Connection connection; final Connection getNetworkManager() { return this.connection; } // Paper - OBFHELPER + private final Connection connection; + private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper public ServerHandshakePacketListenerImpl(MinecraftServer server, Connection connection) { @@ -23,8 +23,8 @@ index c648b73a4c478f9d8020274205d6684f7c7c416f..4e055a41de3ee410682cc05a3b883ac8 // Spigot Start //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! String[] split = packet.hostName.split("\00"); -- if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { -+ if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper +- if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.HOST_PATTERN.matcher( split[1] ).matches() ) ) { ++ if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.BYPASS_HOSTCHECK || ServerHandshakePacketListenerImpl.HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper packet.hostName = split[0]; - connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort()); + connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getPort()); connection.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); diff --git a/patches/server-remapped/0707-Set-area-affect-cloud-rotation.patch b/patches/server/0641-Set-area-affect-cloud-rotation.patch similarity index 73% rename from patches/server-remapped/0707-Set-area-affect-cloud-rotation.patch rename to patches/server/0641-Set-area-affect-cloud-rotation.patch index f907ad7a6b..855fa94054 100644 --- a/patches/server-remapped/0707-Set-area-affect-cloud-rotation.patch +++ b/patches/server/0641-Set-area-affect-cloud-rotation.patch @@ -5,14 +5,14 @@ Subject: [PATCH] Set area affect cloud rotation diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index b0212b2043ee5fd77c8876ef0b51ef91488712f0..b44e83d93bba579e439b93e5093350675137b070 100644 +index c67cd478da70b4a6f97eed6e964d74dc57e07e71..4f07a3385930b2f18dc642261a9d5ebe036ec932 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1959,6 +1959,7 @@ public class CraftWorld implements World { +@@ -1974,6 +1974,7 @@ public class CraftWorld implements World { entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(world); } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { - entity = new net.minecraft.world.entity.AreaEffectCloud(world, x, y, z); + entity = new net.minecraft.world.entity.AreaEffectCloud(this.world, x, y, z); + entity.moveTo(x, y, z, yaw, pitch); // Paper - Set area effect cloud Rotation } else if (EvokerFangs.class.isAssignableFrom(clazz)) { - entity = new net.minecraft.world.entity.projectile.EvokerFangs(world, x, y, z, (float) Math.toRadians(yaw), 0, null); - } + entity = new net.minecraft.world.entity.projectile.EvokerFangs(this.world, x, y, z, (float) Math.toRadians(yaw), 0, null); + } else if (Marker.class.isAssignableFrom(clazz)) { diff --git a/patches/server-remapped/0708-add-isDeeplySleeping-to-HumanEntity.patch b/patches/server/0642-add-isDeeplySleeping-to-HumanEntity.patch similarity index 78% rename from patches/server-remapped/0708-add-isDeeplySleeping-to-HumanEntity.patch rename to patches/server/0642-add-isDeeplySleeping-to-HumanEntity.patch index 75f3e9118b..4a64a4a56c 100644 --- a/patches/server-remapped/0708-add-isDeeplySleeping-to-HumanEntity.patch +++ b/patches/server/0642-add-isDeeplySleeping-to-HumanEntity.patch @@ -5,10 +5,10 @@ Subject: [PATCH] add isDeeplySleeping 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 aceb57c93c91730345f49f78838780c41ce2dcef..0559f2cfab817e989c02ce2d13bcdabb8ad3b82b 100644 +index 021394a0e668d2cfccd8617d4aee79147181fa22..3ab8bd503a599a11c0d50017826cebf6765197f3 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -122,6 +122,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -121,6 +121,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { } } @@ -21,4 +21,4 @@ index aceb57c93c91730345f49f78838780c41ce2dcef..0559f2cfab817e989c02ce2d13bcdabb + @Override public int getSleepTicks() { - return getHandle().sleepCounter; + return this.getHandle().sleepCounter; diff --git a/patches/server/0643-Fix-duplicating-give-items-on-item-drop-cancel.patch b/patches/server/0643-Fix-duplicating-give-items-on-item-drop-cancel.patch new file mode 100644 index 0000000000..ee7bccc6af --- /dev/null +++ b/patches/server/0643-Fix-duplicating-give-items-on-item-drop-cancel.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alphaesia +Date: Fri, 23 Apr 2021 09:57:56 +1200 +Subject: [PATCH] Fix duplicating /give items on item drop cancel + +Fixes SPIGOT-2942 (Give command fires PlayerDropItemEvent, cancelling it causes item duplication). + +For every stack of items to give, /give puts the item stack straight +into the player's inventory. However, it also summons a "fake item" +at the player's location. When the PlayerDropItemEvent for this fake +item is cancelled, the server attempts to put the item back into the +player's inventory. The result is that the fake item, which is never +meant to be obtained, is combined with the real items injected directly +into the player's inventory. This means more items than the amount +specified in /give are given to the player - one for every stack of +items given. (e.g. /give @s dirt 1 gives you 2 dirt). + +While this isn't a big issue for general building usage, it can affect +e.g. adventure maps where the number of items the player receives is +important (and you want to restrict the player from throwing items). + +If there are any overflow items that didn't make it into the inventory +(insufficient space), those items are dropped as a real item instead +of a fake one. While cancelling this drop would also result in the +server attempting to put those items into the inventory, since it is +full this has no effect. + +Just ignoring cancellation of the PlayerDropItemEvent seems like the +cleanest and least intrusive way to fix it. + +diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java +index 58941830a4bd024fcdb97df47783c82062e9167f..a0dc380e90415de9068ea408d62a1605c82631df 100644 +--- a/src/main/java/net/minecraft/server/commands/GiveCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java +@@ -47,7 +47,7 @@ public class GiveCommand { + boolean bl = serverPlayer.getInventory().add(itemStack); + if (bl && itemStack.isEmpty()) { + itemStack.setCount(1); +- ItemEntity itemEntity2 = serverPlayer.drop(itemStack, false); ++ ItemEntity itemEntity2 = serverPlayer.drop(itemStack, false, false, true); // Paper - Fix duplicating /give items on item drop cancel + if (itemEntity2 != null) { + itemEntity2.makeFakeItem(); + } +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 b916f629c2a0fb018cba19aaa612cbbcbb597dc1..c0b18656637cdc1ee6938c70aa281a71551e75dd 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -689,6 +689,13 @@ public abstract class Player extends LivingEntity { + + @Nullable + public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership) { ++ // Paper start - Fix duplicating /give items on item drop cancel ++ return this.drop(stack, throwRandomly, retainOwnership, false); ++ } ++ ++ @Nullable ++ public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership, boolean alwaysSucceed) { ++ // Paper end + if (stack.isEmpty()) { + return null; + } else { +@@ -730,7 +737,7 @@ public abstract class Player extends LivingEntity { + PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); + this.level.getCraftServer().getPluginManager().callEvent(event); + +- if (event.isCancelled()) { ++ if (event.isCancelled() && !alwaysSucceed) { // Paper - Fix duplicating /give items on item drop cancel + org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); + if (retainOwnership && (cur == null || cur.getAmount() == 0)) { + // The complete stack was dropped diff --git a/patches/server-remapped/0710-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/server/0644-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 51% rename from patches/server-remapped/0710-add-consumeFuel-to-FurnaceBurnEvent.patch rename to patches/server/0644-add-consumeFuel-to-FurnaceBurnEvent.patch index f9cc308842..fe66bf1885 100644 --- a/patches/server-remapped/0710-add-consumeFuel-to-FurnaceBurnEvent.patch +++ b/patches/server/0644-add-consumeFuel-to-FurnaceBurnEvent.patch @@ -5,15 +5,15 @@ Subject: [PATCH] add consumeFuel to FurnaceBurnEvent diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 2dcabfc765cbf6341546a7e2c48156fd921fcc82..6e4feb2280021c26dbbfb92feb08c95165e126fe 100644 +index 7b17cc405acab015d9fb1fe233875c6b17bf782d..de53c9652fd6103c4ee5bdb9304979b675cb2bd7 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -329,7 +329,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - if (this.isLit() && furnaceBurnEvent.isBurning()) { - // CraftBukkit end - flag1 = true; -- if (!itemstack.isEmpty()) { -+ if (!itemstack.isEmpty() && furnaceBurnEvent.willConsumeFuel()) { // Paper - Item item = itemstack.getItem(); +@@ -340,7 +340,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + if (blockEntity.isLit() && furnaceBurnEvent.isBurning()) { + // CraftBukkit end + flag1 = true; +- if (!itemstack.isEmpty()) { ++ if (!itemstack.isEmpty() && furnaceBurnEvent.willConsumeFuel()) { // Paper + Item item = itemstack.getItem(); - itemstack.shrink(1); + itemstack.shrink(1); diff --git a/patches/server-remapped/0711-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/server/0645-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 88% rename from patches/server-remapped/0711-add-get-set-drop-chance-to-EntityEquipment.patch rename to patches/server/0645-add-get-set-drop-chance-to-EntityEquipment.patch index c18ac532d5..db1374a99b 100644 --- a/patches/server-remapped/0711-add-get-set-drop-chance-to-EntityEquipment.patch +++ b/patches/server/0645-add-get-set-drop-chance-to-EntityEquipment.patch @@ -5,12 +5,12 @@ Subject: [PATCH] add get-set drop chance to EntityEquipment diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -index e8d6e1abf29a5c50e1cafa01c602f36596d42ecf..9841b4ed648b95272feee45e6f1e8fd9399c322e 100644 +index cd882ef5c6b3e0e33c0caeda534928a7ee168c54..c9c85d7a7257c535e6360499893b3dd392608687 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java @@ -244,6 +244,17 @@ public class CraftEntityEquipment implements EntityEquipment { public void setBootsDropChance(float chance) { - setDropChance(net.minecraft.world.entity.EquipmentSlot.FEET, chance); + this.setDropChance(net.minecraft.world.entity.EquipmentSlot.FEET, chance); } + // Paper start + @Override @@ -27,7 +27,7 @@ index e8d6e1abf29a5c50e1cafa01c602f36596d42ecf..9841b4ed648b95272feee45e6f1e8fd9 private void setDropChance(net.minecraft.world.entity.EquipmentSlot slot, float chance) { if (slot == net.minecraft.world.entity.EquipmentSlot.MAINHAND || slot == net.minecraft.world.entity.EquipmentSlot.OFFHAND) { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -index 7a8181f559cc3c92c3b3aa2ff8eda515719eba08..c326a75728fffbab301654afd94b6839c009fe93 100644 +index 5ae4f2b6cfa4067a0589d6f909ac6a7d9b48fd6f..3354d13f657cecfc3cc756a99accd5d481e8b1dd 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java @@ -354,4 +354,15 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i diff --git a/patches/server-remapped/0712-fix-PigZombieAngerEvent-cancellation.patch b/patches/server/0646-fix-PigZombieAngerEvent-cancellation.patch similarity index 60% rename from patches/server-remapped/0712-fix-PigZombieAngerEvent-cancellation.patch rename to patches/server/0646-fix-PigZombieAngerEvent-cancellation.patch index 5d4feaac2c..20531d6207 100644 --- a/patches/server-remapped/0712-fix-PigZombieAngerEvent-cancellation.patch +++ b/patches/server/0646-fix-PigZombieAngerEvent-cancellation.patch @@ -4,31 +4,19 @@ Date: Thu, 18 Mar 2021 21:38:01 +0100 Subject: [PATCH] fix PigZombieAngerEvent cancellation -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -index f85dfd8b57cf81ad7c6b12753fdd42e93f772f9e..16f4dbfd21a287bad3e10c174fa77a1cac771afa 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -@@ -28,6 +28,7 @@ public abstract class Goal { - - public void start() { this.start(); } public void start() {} // Paper - OBFHELPER - -+ public final void onTaskResetObfHelper() { stop(); } // Paper - OBFHELPER - public void stop() { - onTaskReset(); // Paper - } diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java -index d1cbbfbf9d3c5e65785aad00c2292245a5de1422..d67a50740b1c6d4ecd49a5541d24d1e4bacb8887 100644 +index 7853fbad01bea710e06bdf3198895f2492bdbd10..233b390541acddcf815db4a8f299496eaea4f758 100644 --- a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +++ b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java -@@ -49,6 +49,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { - private UUID persistentAngerTarget; - private static final IntRange ALERT_INTERVAL = TimeUtil.rangeOfSeconds(4, 6); +@@ -51,6 +51,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + private static final int ALERT_RANGE_Y = 10; + private static final UniformInt ALERT_INTERVAL = TimeUtil.rangeOfSeconds(4, 6); private int ticksUntilNextAlert; + private HurtByTargetGoal pathfinderGoalHurtByTarget; // Paper public ZombifiedPiglin(EntityType type, Level world) { super(type, world); -@@ -69,7 +70,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { +@@ -71,7 +72,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { protected void addBehaviourGoals() { this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0D, false)); this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); @@ -37,11 +25,11 @@ index d1cbbfbf9d3c5e65785aad00c2292245a5de1422..d67a50740b1c6d4ecd49a5541d24d1e4 this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true)); } -@@ -172,6 +173,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { +@@ -174,6 +175,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { this.level.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { this.setPersistentAngerTarget(null); -+ pathfinderGoalHurtByTarget.onTaskResetObfHelper(); // Paper - clear goalTargets to fix cancellation ++ pathfinderGoalHurtByTarget.stop(); // Paper - clear goalTargets to fix cancellation return; } this.setRemainingPersistentAngerTime(event.getNewAnger()); diff --git a/patches/server-remapped/0713-Fix-checkReach-check-for-Shulker-boxes.patch b/patches/server/0647-Fix-checkReach-check-for-Shulker-boxes.patch similarity index 82% rename from patches/server-remapped/0713-Fix-checkReach-check-for-Shulker-boxes.patch rename to patches/server/0647-Fix-checkReach-check-for-Shulker-boxes.patch index 38d7d768a3..1449209449 100644 --- a/patches/server-remapped/0713-Fix-checkReach-check-for-Shulker-boxes.patch +++ b/patches/server/0647-Fix-checkReach-check-for-Shulker-boxes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix checkReach check for Shulker boxes diff --git a/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java b/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java -index c40518b0e4ad2b043a9acc858413648d6419f3a3..4b7814a31deeef31e877cee96f0d51b348e7a281 100644 +index b6235e4fe95ba5f19d5897010bf74245336d372d..4739515ca5c8d88283f24214c74ebf4fbd203677 100644 --- a/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java +++ b/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java -@@ -65,6 +65,7 @@ public class ShulkerBoxMenu extends AbstractContainerMenu { +@@ -66,6 +66,7 @@ public class ShulkerBoxMenu extends AbstractContainerMenu { @Override public boolean stillValid(Player player) { diff --git a/patches/server/0648-fix-PlayerItemHeldEvent-firing-twice.patch b/patches/server/0648-fix-PlayerItemHeldEvent-firing-twice.patch new file mode 100644 index 0000000000..21430d3a83 --- /dev/null +++ b/patches/server/0648-fix-PlayerItemHeldEvent-firing-twice.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chickeneer +Date: Thu, 22 Apr 2021 19:02:07 -0700 +Subject: [PATCH] fix PlayerItemHeldEvent firing twice + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index f5c79ec1293c72b738bb6bc1d0aa9d495eefe194..b154aa2d151babbe4341c6dbaec1753d1472215c 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1927,6 +1927,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (this.player.isImmobile()) return; // CraftBukkit + if (packet.getSlot() >= 0 && packet.getSlot() < Inventory.getSelectionSize()) { ++ if (packet.getSlot() == this.player.getInventory().selected) { return; } // Paper - don't fire itemheldevent when there wasn't a slot change + PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getCraftPlayer(), this.player.getInventory().selected, packet.getSlot()); + this.cserver.getPluginManager().callEvent(event); + if (event.isCancelled()) { diff --git a/patches/server-remapped/0715-Added-PlayerDeepSleepEvent.patch b/patches/server/0649-Added-PlayerDeepSleepEvent.patch similarity index 85% rename from patches/server-remapped/0715-Added-PlayerDeepSleepEvent.patch rename to patches/server/0649-Added-PlayerDeepSleepEvent.patch index 14d231bf04..70b0dcea3c 100644 --- a/patches/server-remapped/0715-Added-PlayerDeepSleepEvent.patch +++ b/patches/server/0649-Added-PlayerDeepSleepEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Added 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 cfb9bd6b9863a0f6f0f50181b7553adce90cfebe..c0d2ca1daca0c0c6f21334bc4d9d039440efc453 100644 +index c0b18656637cdc1ee6938c70aa281a71551e75dd..20b286fc905fa77f0d862305b73f3f74f73cfccd 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -232,6 +232,11 @@ public abstract class Player extends LivingEntity { +@@ -247,6 +247,11 @@ public abstract class Player extends LivingEntity { if (this.isSleeping()) { ++this.sleepCounter; diff --git a/patches/server/0650-More-World-API.patch b/patches/server/0650-More-World-API.patch new file mode 100644 index 0000000000..98c56ec734 --- /dev/null +++ b/patches/server/0650-More-World-API.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 7 Jul 2020 10:52:34 -0700 +Subject: [PATCH] More World API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 4f07a3385930b2f18dc642261a9d5ebe036ec932..8a9d367cfcf49f80f05633d16a7019798fc808ec 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2533,6 +2533,75 @@ public class CraftWorld implements World { + return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); + } + ++ // Paper start ++ @Override ++ public Location locateNearestBiome(Location origin, Biome biome, int radius) { ++ return this.locateNearestBiome(origin, biome, radius, 8); ++ } ++ ++ @Override ++ public Location locateNearestBiome(Location origin, Biome biome, int radius, int step) { ++ BlockPos originPos = new BlockPos(origin.getX(), origin.getY(), origin.getZ()); ++ BlockPos nearest = getHandle().findNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), biome), originPos, radius, step); ++ return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); ++ } ++ ++ @Override ++ public boolean isUltrawarm() { ++ return getHandle().dimensionType().ultraWarm(); ++ } ++ ++ @Override ++ public boolean isNatural() { ++ return getHandle().dimensionType().natural(); ++ } ++ ++ @Override ++ public double getCoordinateScale() { ++ return getHandle().dimensionType().coordinateScale(); ++ } ++ ++ @Override ++ public boolean hasSkylight() { ++ return getHandle().dimensionType().hasSkyLight(); ++ } ++ ++ @Override ++ public boolean hasBedrockCeiling() { ++ return getHandle().dimensionType().hasSkyLight(); ++ } ++ ++ @Override ++ public boolean isPiglinSafe() { ++ return getHandle().dimensionType().piglinSafe(); ++ } ++ ++ @Override ++ public boolean doesBedWork() { ++ return getHandle().dimensionType().bedWorks(); ++ } ++ ++ @Override ++ public boolean doesRespawnAnchorWork() { ++ return getHandle().dimensionType().respawnAnchorWorks(); ++ } ++ ++ @Override ++ public boolean hasRaids() { ++ return getHandle().dimensionType().hasRaids(); ++ } ++ ++ @Override ++ public boolean isFixedTime() { ++ return getHandle().dimensionType().hasFixedTime(); ++ } ++ ++ @Override ++ public Collection getInfiniburn() { ++ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().dimensionType().infiniburn().getValues().iterator(), CraftMagicNumbers::getMaterial)); ++ } ++ // Paper end ++ + @Override + public Raid locateNearestRaid(Location location, int radius) { + Validate.notNull(location, "Location cannot be null"); diff --git a/patches/server-remapped/0717-Added-PlayerBedFailEnterEvent.patch b/patches/server/0651-Added-PlayerBedFailEnterEvent.patch similarity index 50% rename from patches/server-remapped/0717-Added-PlayerBedFailEnterEvent.patch rename to patches/server/0651-Added-PlayerBedFailEnterEvent.patch index 87c355341c..7366cdda81 100644 --- a/patches/server-remapped/0717-Added-PlayerBedFailEnterEvent.patch +++ b/patches/server/0651-Added-PlayerBedFailEnterEvent.patch @@ -4,38 +4,17 @@ Date: Thu, 24 Dec 2020 12:27:41 -0800 Subject: [PATCH] Added PlayerBedFailEnterEvent -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 c0d2ca1daca0c0c6f21334bc4d9d039440efc453..007d9476943f5a9c75554927df941bda0f7dd6d5 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -2230,6 +2230,7 @@ public abstract class Player extends LivingEntity { - this.message = ichatbasecomponent; - } - -+ public @Nullable Component getChatComponent() { return this.getMessage(); }; // Paper - OBFHELPER - @Nullable - public Component getMessage() { - return this.message; diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java -index 9dcbc0f741f5980305ae031daac70c7933bc6862..9dcf145b6d1a93785150d268828bca4bb31984c8 100644 +index dd3a4a8527b9adc5daba7540661fb88f9fbf33b2..163a7861f987c3832aac51cc6df950c768546731 100644 --- a/src/main/java/net/minecraft/world/level/block/BedBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java -@@ -43,6 +43,8 @@ import net.minecraft.world.phys.shapes.CollisionContext; - import net.minecraft.world.phys.shapes.Shapes; - import net.minecraft.world.phys.shapes.VoxelShape; - import org.apache.commons.lang3.ArrayUtils; -+import io.papermc.paper.event.player.PlayerBedFailEnterEvent; // Paper -+import io.papermc.paper.adventure.PaperAdventure; // Paper - - public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock { - -@@ -101,14 +103,23 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock +@@ -111,14 +111,23 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock BlockPos finalblockposition = pos; // CraftBukkit end player.startSleepInBed(pos).ifLeft((entityhuman_enumbedresult) -> { + // Paper start - PlayerBedFailEnterEvent + if (entityhuman_enumbedresult != null) { -+ PlayerBedFailEnterEvent event = new PlayerBedFailEnterEvent((org.bukkit.entity.Player) player.getBukkitEntity(), PlayerBedFailEnterEvent.FailReason.VALUES[entityhuman_enumbedresult.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(world, finalblockposition), entityhuman_enumbedresult == Player.BedSleepingProblem.NOT_POSSIBLE_HERE, PaperAdventure.asAdventure(entityhuman_enumbedresult.getChatComponent())); ++ io.papermc.paper.event.player.PlayerBedFailEnterEvent event = new io.papermc.paper.event.player.PlayerBedFailEnterEvent((org.bukkit.entity.Player) player.getBukkitEntity(), io.papermc.paper.event.player.PlayerBedFailEnterEvent.FailReason.VALUES[entityhuman_enumbedresult.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(world, finalblockposition), entityhuman_enumbedresult == Player.BedSleepingProblem.NOT_POSSIBLE_HERE, io.papermc.paper.adventure.PaperAdventure.asAdventure(entityhuman_enumbedresult.getMessage())); + if (!event.callEvent()) { + return; + } @@ -49,7 +28,7 @@ index 9dcbc0f741f5980305ae031daac70c7933bc6862..9dcf145b6d1a93785150d268828bca4b if (entityhuman_enumbedresult != null) { - player.displayClientMessage(entityhuman_enumbedresult.getMessage(), true); + final net.kyori.adventure.text.Component message = event.getMessage(); // Paper -+ if(message != null) player.displayClientMessage(PaperAdventure.asVanilla(message), true); // Paper ++ if(message != null) player.displayClientMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message), true); // Paper } + } // Paper diff --git a/patches/server-remapped/0718-Implement-methods-to-convert-between-Component-and-B.patch b/patches/server/0652-Implement-methods-to-convert-between-Component-and-B.patch similarity index 93% rename from patches/server-remapped/0718-Implement-methods-to-convert-between-Component-and-B.patch rename to patches/server/0652-Implement-methods-to-convert-between-Component-and-B.patch index e796b62074..8f31720349 100644 --- a/patches/server-remapped/0718-Implement-methods-to-convert-between-Component-and-B.patch +++ b/patches/server/0652-Implement-methods-to-convert-between-Component-and-B.patch @@ -42,10 +42,10 @@ index 0000000000000000000000000000000000000000..dd6012b6a097575b2d1471be5069ecce + } +} diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index c2947313cc0eda3247fb4b20ddd1d0b86c37c50a..0198268bc614b190cd84f625a62f6c55247a01c8 100644 +index eadacfa8449336c024f6154f46bb514d8e1230ec..f5cb59aa72dfd22ec143360a131818bef4f1b701 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -210,6 +210,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -219,6 +219,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } com.destroystokyo.paper.PaperConfig.registerCommands(); com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now diff --git a/patches/server-remapped/0719-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/patches/server/0653-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch similarity index 79% rename from patches/server-remapped/0719-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch rename to patches/server/0653-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch index cf90fd18e8..3d432bc5f2 100644 --- a/patches/server-remapped/0719-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch +++ b/patches/server/0653-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix anchor respawn acting as a bed respawn from the end diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 23cfaf5c432221f2d1afe37ba657f723d6d21a73..a4e897171ce05736bcead319b7fda74d2b02fd2e 100644 +index b744653a7508ba2aea859709e7ea3c58fbb586cf..508fdb0b07bc4e45c630a2c4b731ffdaa3a5711a 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -867,6 +867,7 @@ public abstract class PlayerList { +@@ -841,6 +841,7 @@ public abstract class PlayerList { // Paper start boolean isBedSpawn = false; @@ -17,7 +17,7 @@ index 23cfaf5c432221f2d1afe37ba657f723d6d21a73..a4e897171ce05736bcead319b7fda74d boolean isRespawn = false; boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 // Paper end -@@ -887,6 +888,7 @@ public abstract class PlayerList { +@@ -861,6 +862,7 @@ public abstract class PlayerList { if (optional.isPresent()) { BlockState iblockdata = worldserver1.getBlockState(blockposition); boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); @@ -25,12 +25,12 @@ index 23cfaf5c432221f2d1afe37ba657f723d6d21a73..a4e897171ce05736bcead319b7fda74d Vec3 vec3d = (Vec3) optional.get(); float f1; -@@ -914,7 +916,7 @@ public abstract class PlayerList { +@@ -888,7 +890,7 @@ public abstract class PlayerList { } - Player respawnPlayer = cserver.getPlayer(entityplayer1); + Player respawnPlayer = this.cserver.getPlayer(entityplayer1); - PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag2, flag2); + PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal - cserver.getPluginManager().callEvent(respawnEvent); + this.cserver.getPluginManager().callEvent(respawnEvent); // Spigot Start if (entityplayer.connection.isDisconnected()) { diff --git a/patches/server-remapped/0721-Introduce-beacon-activation-deactivation-events.patch b/patches/server/0654-Introduce-beacon-activation-deactivation-events.patch similarity index 63% rename from patches/server-remapped/0721-Introduce-beacon-activation-deactivation-events.patch rename to patches/server/0654-Introduce-beacon-activation-deactivation-events.patch index 57b84d6df6..45f5b0e153 100644 --- a/patches/server-remapped/0721-Introduce-beacon-activation-deactivation-events.patch +++ b/patches/server/0654-Introduce-beacon-activation-deactivation-events.patch @@ -5,26 +5,26 @@ Subject: [PATCH] Introduce beacon activation/deactivation events diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -index fed29e5707e2a7f64159d284c52647dd91e1948e..7025a27c25f8640df06a3c65c2086059769870b5 100644 +index 1df7a4a937729fc402f80021434ddf3481facd94..c1a0b0d77b8783fd127b68449a209ec0e62e6005 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -@@ -199,6 +199,15 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick - this.playSound(SoundEvents.BEACON_AMBIENT); +@@ -206,6 +206,15 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + BeaconBlockEntity.playSound(world, pos, SoundEvents.BEACON_AMBIENT); } } + // Paper start - beacon activation/deactivation events -+ if (!(i1 > 0) && this.levels > 0) { -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); ++ if (i1 <= 0 && blockEntity.levels > 0) { ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos); + new io.papermc.paper.event.block.BeaconActivatedEvent(block).callEvent(); -+ } else if (i1 > 0 && !(this.levels > 0)) { -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); ++ } else if (i1 > 0 && blockEntity.levels <= 0) { ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos); + new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); + } + // Paper end - if (this.lastCheckY >= l) { - this.lastCheckY = -1; -@@ -255,6 +264,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Tick + if (blockEntity.lastCheckY >= l) { + blockEntity.lastCheckY = world.getMinBuildHeight() - 1; +@@ -263,6 +272,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { @Override public void setRemoved() { @@ -32,6 +32,6 @@ index fed29e5707e2a7f64159d284c52647dd91e1948e..7025a27c25f8640df06a3c65c2086059 + org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); + new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); + // Paper end - this.playSound(SoundEvents.BEACON_DEACTIVATE); + BeaconBlockEntity.playSound(this.level, this.worldPosition, SoundEvents.BEACON_DEACTIVATE); super.setRemoved(); } diff --git a/patches/server-remapped/0720-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/server/0655-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 81% rename from patches/server-remapped/0720-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/server/0655-add-RespawnFlags-to-PlayerRespawnEvent.patch index b0c5ab3263..6d960c9670 100644 --- a/patches/server-remapped/0720-add-RespawnFlags-to-PlayerRespawnEvent.patch +++ b/patches/server/0655-add-RespawnFlags-to-PlayerRespawnEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 5b0eb8744dba5df6f16bafd6d907cd1efd508fe6..a0e69cac7699ddc318057c8016e329850d3baa26 100644 +index b154aa2d151babbe4341c6dbaec1753d1472215c..e896057274434eea97d78777dcf303fd83e9cd79 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2440,7 +2440,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2461,7 +2461,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser case PERFORM_RESPAWN: if (this.player.wonGame) { this.player.wonGame = false; @@ -18,15 +18,14 @@ index 5b0eb8744dba5df6f16bafd6d907cd1efd508fe6..a0e69cac7699ddc318057c8016e32985 } else { if (this.player.getHealth() > 0.0F) { diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index a4e897171ce05736bcead319b7fda74d2b02fd2e..6011b43ae8a858f88b8fcf6dc0bf147024a4742c 100644 +index 508fdb0b07bc4e45c630a2c4b731ffdaa3a5711a..34de9e2b0e52eb7a7e993678fd54ac1b883be4aa 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -816,7 +816,13 @@ public abstract class PlayerList { - return this.moveToWorld(player, this.server.getLevel(player.getRespawnDimension()), alive, null, true); +@@ -800,6 +800,12 @@ public abstract class PlayerList { } -+ // Paper start public ServerPlayer moveToWorld(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation) { ++ // Paper start + return moveToWorld(entityplayer, worldserver, flag, location, avoidSuffocation, new org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag[0]); + } + @@ -35,12 +34,12 @@ index a4e897171ce05736bcead319b7fda74d2b02fd2e..6011b43ae8a858f88b8fcf6dc0bf1470 entityplayer.stopRiding(); // CraftBukkit this.players.remove(entityplayer); this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -916,7 +922,7 @@ public abstract class PlayerList { +@@ -890,7 +896,7 @@ public abstract class PlayerList { } - Player respawnPlayer = cserver.getPlayer(entityplayer1); + Player respawnPlayer = this.cserver.getPlayer(entityplayer1); - PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal + PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn, com.google.common.collect.ImmutableSet.builder().add(respawnFlags)); // Paper - Fix anchor respawn acting as a bed respawn from the end portal - cserver.getPluginManager().callEvent(respawnEvent); + this.cserver.getPluginManager().callEvent(respawnEvent); // Spigot Start if (entityplayer.connection.isDisconnected()) { diff --git a/patches/server-remapped/0722-Add-Channel-initialization-listeners.patch b/patches/server/0656-Add-Channel-initialization-listeners.patch similarity index 94% rename from patches/server-remapped/0722-Add-Channel-initialization-listeners.patch rename to patches/server/0656-Add-Channel-initialization-listeners.patch index 72cbb09b5a..0fb730c943 100644 --- a/patches/server-remapped/0722-Add-Channel-initialization-listeners.patch +++ b/patches/server/0656-Add-Channel-initialization-listeners.patch @@ -106,11 +106,11 @@ index 0000000000000000000000000000000000000000..30e62719e0a83525daa33cf41cb61df3 + } +} diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -index d46910cfdc0aef046a0c79731a85d381953c328a..bcc19d0a4b6c5f683dc416e27a13705b57213d21 100644 +index 8fffe354d40c5fac4daa03af87c2323e307bd3ea..9c9368628845f316e157f6ae15b89c24af082d97 100644 --- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -@@ -104,6 +104,7 @@ public class ServerConnectionListener { - pending.add((Connection) object); // Paper +@@ -99,6 +99,7 @@ public class ServerConnectionListener { + ServerConnectionListener.this.connections.add((Connection) object); // CraftBukkit - decompile error channel.pipeline().addLast("packet_handler", (ChannelHandler) object); ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); + io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper diff --git a/patches/server-remapped/0723-Send-empty-commands-if-tab-completion-is-disabled.patch b/patches/server/0657-Send-empty-commands-if-tab-completion-is-disabled.patch similarity index 88% rename from patches/server-remapped/0723-Send-empty-commands-if-tab-completion-is-disabled.patch rename to patches/server/0657-Send-empty-commands-if-tab-completion-is-disabled.patch index de0a65c719..c5a368ae15 100644 --- a/patches/server-remapped/0723-Send-empty-commands-if-tab-completion-is-disabled.patch +++ b/patches/server/0657-Send-empty-commands-if-tab-completion-is-disabled.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Send empty commands if tab completion is disabled diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java -index e2f18b5bf1e091fe5fd868520a6d1bcc2669c24c..1d880a80348527d036b6f8b04f7dd1c4a479fcfd 100644 +index dc5d21693237ebb0b2a1ee45e92d0f191c547637..ff4f48f6646060b398e8bf90a078e7fbf84beada 100644 --- a/src/main/java/net/minecraft/commands/Commands.java +++ b/src/main/java/net/minecraft/commands/Commands.java -@@ -327,7 +327,12 @@ public class Commands { +@@ -334,7 +334,12 @@ public class Commands { } public void sendCommands(ServerPlayer player) { diff --git a/patches/server-remapped/0724-Add-more-WanderingTrader-API.patch b/patches/server/0658-Add-more-WanderingTrader-API.patch similarity index 84% rename from patches/server-remapped/0724-Add-more-WanderingTrader-API.patch rename to patches/server/0658-Add-more-WanderingTrader-API.patch index b99c0c4512..f1883cfb2a 100644 --- a/patches/server-remapped/0724-Add-more-WanderingTrader-API.patch +++ b/patches/server/0658-Add-more-WanderingTrader-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add more WanderingTrader API diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -index 04c4cca4be8886feb59f180915977b77f9c7dde8..22a695ee3f6c60d484285f1b441b809da61f2436 100644 +index 9f9b48546fd1ae23a04cad060b6996e21354efbb..c4f7c94255e4631a3c0355f9260132ba28296f50 100644 --- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java @@ -57,6 +57,10 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill @@ -19,12 +19,12 @@ index 04c4cca4be8886feb59f180915977b77f9c7dde8..22a695ee3f6c60d484285f1b441b809d public WanderingTrader(EntityType type, Level world) { super(type, world); -@@ -68,10 +72,10 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -67,10 +71,10 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill protected void registerGoals() { this.goalSelector.addGoal(0, new FloatGoal(this)); this.goalSelector.addGoal(0, new UseItemGoal<>(this, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEvents.WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { -- return this.world.isNight() && !entityvillagertrader.isInvisible(); -+ return canDrinkPotion && this.world.isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API +- return this.level.isNight() && !entityvillagertrader.isInvisible(); ++ return this.canDrinkPotion && this.level.isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API })); this.goalSelector.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { - return this.level.isDay() && entityvillagertrader.isInvisible(); @@ -33,12 +33,12 @@ index 04c4cca4be8886feb59f180915977b77f9c7dde8..22a695ee3f6c60d484285f1b441b809d this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this)); this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zombie.class, 8.0F, 0.5D, 0.5D)); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -index a00b1ee5d80d3918ece2260dc1360aa90de16c8a..de58fc26bd811e87cd393bdecee796faf72e65e1 100644 +index 65b052567d1d855021d7273672b4354aba0a42a4..fa7107593b20e0151d8d67104e4a92dcc697d461 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java @@ -34,4 +34,26 @@ public class CraftWanderingTrader extends CraftAbstractVillager implements Wande public void setDespawnDelay(int despawnDelay) { - getHandle().setDespawnDelay(despawnDelay); + this.getHandle().setDespawnDelay(despawnDelay); } + + // Paper start - Add more WanderingTrader API diff --git a/patches/server-remapped/0725-Add-EntityBlockStorage-clearEntities.patch b/patches/server/0659-Add-EntityBlockStorage-clearEntities.patch similarity index 89% rename from patches/server-remapped/0725-Add-EntityBlockStorage-clearEntities.patch rename to patches/server/0659-Add-EntityBlockStorage-clearEntities.patch index 530ee44dcf..a25b644273 100644 --- a/patches/server-remapped/0725-Add-EntityBlockStorage-clearEntities.patch +++ b/patches/server/0659-Add-EntityBlockStorage-clearEntities.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add EntityBlockStorage#clearEntities() diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -index cbd0587eeecf14b1914bdb33f7a4584bd6b5c8d0..83e5367ee1126afe31e9f704a0daedd310339d15 100644 +index 61125c1c1a6efbb3ba13a29d5e4e6bbe67df8a4e..8484e80a70129fb0358d56efab6fd54798b54e6e 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -@@ -120,6 +120,11 @@ public class BeehiveBlockEntity extends BlockEntity implements TickableBlockEnti +@@ -135,6 +135,11 @@ public class BeehiveBlockEntity extends BlockEntity { return this.stored.size(); } diff --git a/patches/server/0660-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/server/0660-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch new file mode 100644 index 0000000000..b63b7cfcd1 --- /dev/null +++ b/patches/server/0660-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alvinn8 <42838560+Alvinn8@users.noreply.github.com> +Date: Fri, 8 Jan 2021 20:31:13 +0100 +Subject: [PATCH] Add Adventure message to PlayerAdvancementDoneEvent + + +diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index 77e262f2236318e053da136037332fbe6d8bf380..d1f85b092eba829b003e39c913a4afeffc140568 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -290,10 +290,18 @@ public class PlayerAdvancements { + this.progressChanged.add(advancement); + flag = true; + if (!flag1 && advancementprogress.isDone()) { +- this.player.level.getCraftServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit)); // CraftBukkit ++ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent ++ boolean announceToChat = advancement.getDisplay() != null && advancement.getDisplay().shouldAnnounceChat(); ++ net.kyori.adventure.text.Component message = announceToChat ? io.papermc.paper.adventure.PaperAdventure.asAdventure(new TranslatableComponent("chat.type.advancement." + advancement.getDisplay().getFrame().getName(), this.player.getDisplayName(), advancement.getChatComponent())) : null; ++ org.bukkit.event.player.PlayerAdvancementDoneEvent event = new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit, message); ++ this.player.level.getCraftServer().getPluginManager().callEvent(event); ++ message = event.message(); ++ // Paper end + advancement.getRewards().grant(this.player); +- if (advancement.getDisplay() != null && advancement.getDisplay().shouldAnnounceChat() && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { +- this.playerList.broadcastMessage(new TranslatableComponent("chat.type.advancement." + advancement.getDisplay().getFrame().getName(), new Object[]{this.player.getDisplayName(), advancement.getChatComponent()}), ChatType.SYSTEM, Util.NIL_UUID); ++ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent ++ if (message != null && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { ++ this.playerList.broadcastMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message), ChatType.SYSTEM, Util.NIL_UUID); ++ // Paper end + } + } + } diff --git a/patches/server-remapped/0727-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/server/0661-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 72% rename from patches/server-remapped/0727-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/server/0661-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch index a376cbbc19..ce5c6a07d5 100644 --- a/patches/server-remapped/0727-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch +++ b/patches/server/0661-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch @@ -5,19 +5,19 @@ Subject: [PATCH] Add raw address to AsyncPlayerPreLoginEvent diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 573963a09f15046cfcaab83aef906801ce70d75a..99275a8bc2e7bf242ff3c5b5c29924af5328327a 100644 +index 21ed58d746cb0734cc45574888ed03886e7c411a..8cc84be906fc8b50429af96c346f7114a2191535 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -325,12 +325,13 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - // Paper end - String playerName = gameProfile.getName(); - java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); +@@ -346,12 +346,13 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + // Paper end + String playerName = ServerLoginPacketListenerImpl.this.gameProfile.getName(); + java.net.InetAddress address = ((java.net.InetSocketAddress) ServerLoginPacketListenerImpl.this.connection.getRemoteAddress()).getAddress(); + java.net.InetAddress rawAddress = ((java.net.InetSocketAddress) connection.getRawAddress()).getAddress(); // Paper - java.util.UUID uniqueId = gameProfile.getId(); + java.util.UUID uniqueId = ServerLoginPacketListenerImpl.this.gameProfile.getId(); final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; // Paper start - PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); + PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile); - AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); + AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile); server.getPluginManager().callEvent(asyncEvent); diff --git a/patches/server-remapped/0728-Inventory-close.patch b/patches/server/0662-Inventory-close.patch similarity index 82% rename from patches/server-remapped/0728-Inventory-close.patch rename to patches/server/0662-Inventory-close.patch index f206ea0fbd..8bfd99aed9 100644 --- a/patches/server-remapped/0728-Inventory-close.patch +++ b/patches/server/0662-Inventory-close.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Inventory#close diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index 7ccc085228f373e6eba55d809bed480d43d5c211..16d34f44e92e26d13188417942f444952f98dfa1 100644 +index 7850dfa9130761905030856786a97a008c700687..01701e50dd0ce1c46dcc27ea7da8f51d45899a8c 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -448,6 +448,14 @@ public class CraftInventory implements Inventory { - clear(i); +@@ -447,6 +447,14 @@ public class CraftInventory implements Inventory { + this.clear(i); } } + // Paper start diff --git a/patches/server-remapped/0729-call-PortalCreateEvent-players-and-end-platform.patch b/patches/server/0663-call-PortalCreateEvent-players-and-end-platform.patch similarity index 84% rename from patches/server-remapped/0729-call-PortalCreateEvent-players-and-end-platform.patch rename to patches/server/0663-call-PortalCreateEvent-players-and-end-platform.patch index 4776fc7a79..2488018cba 100644 --- a/patches/server-remapped/0729-call-PortalCreateEvent-players-and-end-platform.patch +++ b/patches/server/0663-call-PortalCreateEvent-players-and-end-platform.patch @@ -5,10 +5,10 @@ Subject: [PATCH] call PortalCreateEvent players and end platform diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 727af6ac84075db87615ebac51a024e6376fa3cb..6e2a272075ead399004dabfb7d4f0ea5fd32ffc2 100644 +index fd5c22a3d281d8d913c353c8a668ec51b885066a..8c3b34b3d55af4aa8e3619a5bdf0eadb7baad029 100644 --- a/src/main/java/net/minecraft/core/BlockPos.java +++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -496,6 +496,7 @@ public class BlockPos extends Vec3i { +@@ -521,6 +521,7 @@ public class BlockPos extends Vec3i { return this.set(this.getX() + direction.getStepX() * distance, this.getY() + direction.getStepY() * distance, this.getZ() + direction.getStepZ() * distance); } @@ -17,10 +17,10 @@ index 727af6ac84075db87615ebac51a024e6376fa3cb..6e2a272075ead399004dabfb7d4f0ea5 return this.set(this.getX() + dx, this.getY() + dy, this.getZ() + dz); } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 314f168c9d17ab3654c9dda07e48839570f0d332..5d710a1f4e0c61d4be6efe8cebd9b80789868338 100644 +index d0e9bbecb4b0cf980116c72b96ae8edd74f9bfd6..3b5feea941eba2ee2c6d93fd5141f2f8f1dbae42 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1142,15 +1142,21 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -1166,15 +1166,21 @@ public class ServerPlayer extends Player { private void createEndPlatform(ServerLevel world, BlockPos centerPos) { BlockPos.MutableBlockPos blockposition_mutableblockposition = centerPos.mutable(); @@ -31,7 +31,7 @@ index 314f168c9d17ab3654c9dda07e48839570f0d332..5d710a1f4e0c61d4be6efe8cebd9b807 BlockState iblockdata = k == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); - world.setBlockAndUpdate(blockposition_mutableblockposition.set(centerPos).move(j, k, i), iblockdata); -+ blockList.setBlock(blockposition_mutableblockposition.setValues(centerPos).withOffset(j, k, i), iblockdata, 3); // Paper ++ blockList.setBlock(blockposition_mutableblockposition.set(centerPos).move(j, k, i), iblockdata, 3); // Paper } } } diff --git a/patches/server-remapped/0730-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/server/0664-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 68% rename from patches/server-remapped/0730-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/server/0664-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch index fb4c1ca38d..f553f149e6 100644 --- a/patches/server-remapped/0730-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch +++ b/patches/server/0664-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add a "should burn in sunlight" API for Phantoms and diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -index 68e52e3a31e70569d1a92602aff4b7b81c594757..a8a0dba43453b7ac73e8e0faf7728445d9bcc2cd 100644 +index 6b4163f5601a0961055c8451ec7ef2204938cf69..c54a37516ef1d8a76f7161917bf448127cd98603 100644 --- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -@@ -98,9 +98,15 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo +@@ -97,9 +97,15 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo return MobType.UNDEAD; } @@ -26,28 +26,28 @@ index 68e52e3a31e70569d1a92602aff4b7b81c594757..a8a0dba43453b7ac73e8e0faf7728445 if (flag) { ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); -@@ -224,7 +230,16 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo - public void readAdditionalSaveData(CompoundTag tag) { - super.readAdditionalSaveData(tag); +@@ -223,7 +229,16 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + public void readAdditionalSaveData(CompoundTag nbt) { + super.readAdditionalSaveData(nbt); this.reassessWeaponGoal(); -+ this.shouldBurnInDay = tag.getBoolean("Paper.ShouldBurnInDay"); // Paper ++ this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay"); // Paper + } + + // Paper start + @Override -+ public void addAdditionalSaveData(CompoundTag tag) { -+ super.addAdditionalSaveData(tag); -+ tag.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); ++ public void addAdditionalSaveData(CompoundTag nbt) { ++ super.addAdditionalSaveData(nbt); ++ nbt.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); } + // Paper end @Override public void setItemSlot(EquipmentSlot slot, ItemStack stack) { diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index a40c23e824652cff59633b7c314e27ec9a515c07..8f4dd4540330966689e71568e9e9ef77f82a786a 100644 +index 941f86b04fedaf1e3f5d04c9aa8c1cd74da9b7a2..11940597e0f9f87b5906f1d51a34e35046de1d1f 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java +++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -@@ -134,7 +134,7 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -145,7 +145,7 @@ public class Phantom extends FlyingMob implements Enemy { @Override public void aiStep() { @@ -56,23 +56,23 @@ index a40c23e824652cff59633b7c314e27ec9a515c07..8f4dd4540330966689e71568e9e9ef77 this.setSecondsOnFire(8); } -@@ -165,6 +165,7 @@ public class Phantom extends FlyingMob implements Enemy { - if (tag.hasUUID("Paper.SpawningEntity")) { - this.spawningEntity = tag.getUUID("Paper.SpawningEntity"); +@@ -176,6 +176,7 @@ public class Phantom extends FlyingMob implements Enemy { + if (nbt.hasUUID("Paper.SpawningEntity")) { + this.spawningEntity = nbt.getUUID("Paper.SpawningEntity"); } -+ this.shouldBurnInDay = tag.getBoolean("Paper.ShouldBurnInDay"); ++ this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay"); // Paper end } -@@ -179,6 +180,7 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -190,6 +191,7 @@ public class Phantom extends FlyingMob implements Enemy { if (this.spawningEntity != null) { - tag.setUUID("Paper.SpawningEntity", this.spawningEntity); + nbt.setUUID("Paper.SpawningEntity", this.spawningEntity); } -+ tag.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); ++ nbt.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); // Paper end } -@@ -233,6 +235,10 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -249,6 +251,10 @@ public class Phantom extends FlyingMob implements Enemy { return spawningEntity; } public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } @@ -81,13 +81,13 @@ index a40c23e824652cff59633b7c314e27ec9a515c07..8f4dd4540330966689e71568e9e9ef77 + public boolean shouldBurnInDay() { return shouldBurnInDay; } + public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } // Paper end + private static enum AttackPhase { - class PhantomAttackPlayerTargetGoal extends Goal { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -index 92162fa22f5e98b7837bde5830bd47c31b8b52d8..011ad2224a3a3a2d255b2498e406fbb047359240 100644 +index c9dab70b0b284fe1c1daafd3c1f5bd08b14fa35d..dce23f3878b1588c26b6116d80e597d08070edbc 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -@@ -39,5 +39,15 @@ public class CraftPhantom extends CraftFlying implements Phantom { +@@ -40,5 +40,15 @@ public class CraftPhantom extends CraftFlying implements Phantom { public java.util.UUID getSpawningEntity() { return getHandle().getSpawningEntity(); } @@ -104,12 +104,12 @@ index 92162fa22f5e98b7837bde5830bd47c31b8b52d8..011ad2224a3a3a2d255b2498e406fbb0 // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -index b2d3244cca4d9d108159f3537d8a9aace3f8e77f..28dda8beb1793fad47b2c9db815c0b6cf6ed781a 100644 +index 3b19cd5a232f38d373359072925be12f6c075d4a..a248774ead0afee576af291e70a9a05d12ca203b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -@@ -36,4 +36,16 @@ public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroy - public void setSkeletonType(SkeletonType type) { - throw new UnsupportedOperationException("Not supported."); +@@ -51,4 +51,16 @@ public class CraftSkeleton extends CraftAbstractSkeleton implements Skeleton, co + public SkeletonType getSkeletonType() { + return SkeletonType.NORMAL; } + + // Paper start diff --git a/patches/server-remapped/0731-Fix-CraftPotionBrewer-cache.patch b/patches/server/0665-Fix-CraftPotionBrewer-cache.patch similarity index 72% rename from patches/server-remapped/0731-Fix-CraftPotionBrewer-cache.patch rename to patches/server/0665-Fix-CraftPotionBrewer-cache.patch index 140b30b682..2d8295382f 100644 --- a/patches/server-remapped/0731-Fix-CraftPotionBrewer-cache.patch +++ b/patches/server/0665-Fix-CraftPotionBrewer-cache.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix CraftPotionBrewer cache diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -index e20d96ec67dcbe935357b4de7e0e9a6984dc3303..eb28a055ba60bb1da3412cf0dbbe5ce76a779f38 100644 +index 1e4bc0d9f9d2e45157929af685f116988cbb8c03..8fdc9a3bb2f1b6bdc6c2c96f8ade7e9cd88ea4e0 100644 --- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java +++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java @@ -15,12 +15,18 @@ import org.bukkit.potion.PotionEffectType; @@ -17,15 +17,15 @@ index e20d96ec67dcbe935357b4de7e0e9a6984dc3303..eb28a055ba60bb1da3412cf0dbbe5ce7 @Override public Collection getEffects(PotionType damage, boolean upgraded, boolean extended) { -- if (cache.containsKey(damage)) -- return cache.get(damage); +- if (CraftPotionBrewer.cache.containsKey(damage)) +- return CraftPotionBrewer.cache.get(damage); + // Paper start + int key = damage.ordinal() << 2; + key |= (upgraded ? 1 : 0) << 1; + key |= extended ? 1 : 0; + -+ if (cache.containsKey(key)) -+ return cache.get(key); ++ if (CraftPotionBrewer.cache.containsKey(key)) ++ return CraftPotionBrewer.cache.get(key); + // Paper end List mcEffects = Potion.byName(CraftPotionUtil.fromBukkit(new PotionData(damage, extended, upgraded))).getEffects(); @@ -34,11 +34,11 @@ index e20d96ec67dcbe935357b4de7e0e9a6984dc3303..eb28a055ba60bb1da3412cf0dbbe5ce7 builder.add(CraftPotionUtil.toBukkit(effect)); } -- cache.put(damage, builder.build()); -+ cache.put(key, builder.build()); // Paper +- CraftPotionBrewer.cache.put(damage, builder.build()); ++ CraftPotionBrewer.cache.put(key, builder.build()); // Paper -- return cache.get(damage); -+ return cache.get(key); // Paper +- return CraftPotionBrewer.cache.get(damage); ++ return CraftPotionBrewer.cache.get(key); // Paper } @Override diff --git a/patches/server/0666-Add-basic-Datapack-API.patch b/patches/server/0666-Add-basic-Datapack-API.patch new file mode 100644 index 0000000000..5ec36d4c3b --- /dev/null +++ b/patches/server/0666-Add-basic-Datapack-API.patch @@ -0,0 +1,125 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Connor Linfoot +Date: Sun, 16 May 2021 15:07:34 +0100 +Subject: [PATCH] Add basic Datapack API + + +diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9b7dd8a0fba4547f5268b3f99e21ddbe6b5bf566 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java +@@ -0,0 +1,50 @@ ++package io.papermc.paper.datapack; ++ ++import io.papermc.paper.event.server.ServerResourcesReloadedEvent; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.packs.repository.Pack; ++import java.util.List; ++import java.util.stream.Collectors; ++ ++public class PaperDatapack implements Datapack { ++ private final String name; ++ private final Compatibility compatibility; ++ private final boolean enabled; ++ ++ PaperDatapack(Pack loader, boolean enabled) { ++ this.name = loader.getId(); ++ this.compatibility = Compatibility.valueOf(loader.getCompatibility().name()); ++ this.enabled = enabled; ++ } ++ ++ @Override ++ public String getName() { ++ return name; ++ } ++ ++ @Override ++ public Compatibility getCompatibility() { ++ return compatibility; ++ } ++ ++ @Override ++ public boolean isEnabled() { ++ return enabled; ++ } ++ ++ @Override ++ public void setEnabled(boolean enabled) { ++ if (enabled == this.enabled) { ++ return; ++ } ++ ++ MinecraftServer server = MinecraftServer.getServer(); ++ List enabledKeys = server.getPackRepository().getSelectedPacks().stream().map(Pack::getId).collect(Collectors.toList()); ++ if (enabled) { ++ enabledKeys.add(this.name); ++ } else { ++ enabledKeys.remove(this.name); ++ } ++ server.reloadResources(enabledKeys, ServerResourcesReloadedEvent.Cause.PLUGIN); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..cf4374493c11057451a62a655514415cf6b298e0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java +@@ -0,0 +1,25 @@ ++package io.papermc.paper.datapack; ++ ++import java.util.Collection; ++import java.util.stream.Collectors; ++import net.minecraft.server.packs.repository.Pack; ++import net.minecraft.server.packs.repository.PackRepository; ++ ++public class PaperDatapackManager implements DatapackManager { ++ private final PackRepository repository; ++ ++ public PaperDatapackManager(PackRepository repository) { ++ this.repository = repository; ++ } ++ ++ @Override ++ public Collection getPacks() { ++ Collection enabledPacks = repository.getSelectedPacks(); ++ return repository.getAvailablePacks().stream().map(loader -> new PaperDatapack(loader, enabledPacks.contains(loader))).collect(Collectors.toList()); ++ } ++ ++ @Override ++ public Collection getEnabledPacks() { ++ return repository.getSelectedPacks().stream().map(loader -> new PaperDatapack(loader, true)).collect(Collectors.toList()); ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index bd7db12503c3175c3bd71f8a0fe3a826eb043000..2f914ebd18764fbfd3834c0a94cedb2184f8dbb0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -266,6 +266,7 @@ public final class CraftServer implements Server { + public boolean ignoreVanillaPermissions = false; + private final List playerView; + public int reloadCount; ++ private final io.papermc.paper.datapack.PaperDatapackManager datapackManager; // Paper + public static Exception excessiveVelEx; // Paper - Velocity warnings + + static { +@@ -349,6 +350,7 @@ public final class CraftServer implements Server { + TicketType.PLUGIN.timeout = Math.min(20, this.configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + this.minimumAPI = this.configuration.getString("settings.minimum-api"); + this.loadIcon(); ++ datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper + } + + public boolean getCommandBlockOverride(String command) { +@@ -2496,5 +2498,11 @@ public final class CraftServer implements Server { + public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { + return mobGoals; + } ++ ++ @Override ++ public io.papermc.paper.datapack.PaperDatapackManager getDatapackManager() { ++ return datapackManager; ++ } ++ + // Paper end + } diff --git a/patches/server-remapped/0733-Add-environment-variable-to-disable-server-gui.patch b/patches/server/0667-Add-environment-variable-to-disable-server-gui.patch similarity index 85% rename from patches/server-remapped/0733-Add-environment-variable-to-disable-server-gui.patch rename to patches/server/0667-Add-environment-variable-to-disable-server-gui.patch index a1f57cca90..875c5e6c83 100644 --- a/patches/server-remapped/0733-Add-environment-variable-to-disable-server-gui.patch +++ b/patches/server/0667-Add-environment-variable-to-disable-server-gui.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add environment variable to disable server gui diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 9dc9a5e6ad7f23c8bf3553c765ceeecd67a49ac1..ba6c17da4875c3a342da99e354c9f07cc7f17326 100644 +index ea136b9ad3a2a07076e12b8656c68f63aa4718c8..cf0a74b8a1c31d4bc493eb09a69ee2bd94cb6485 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java -@@ -225,6 +225,7 @@ public class Main { +@@ -239,6 +239,7 @@ public class Main { */ boolean flag1 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui"); diff --git a/patches/server/0668-additions-to-PlayerGameModeChangeEvent.patch b/patches/server/0668-additions-to-PlayerGameModeChangeEvent.patch new file mode 100644 index 0000000000..3fa2f12096 --- /dev/null +++ b/patches/server/0668-additions-to-PlayerGameModeChangeEvent.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 15 May 2021 10:04:43 -0700 +Subject: [PATCH] additions to PlayerGameModeChangeEvent + + +diff --git a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java +index d25a27f3a6775ca86092ea8bdeab4abdd8909d35..7d9ec435f3821f95d3bed893c4e46d5a2531cd58 100644 +--- a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java ++++ b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java +@@ -31,9 +31,13 @@ public class DefaultGameModeCommands { + GameType gameType = minecraftServer.getForcedGameType(); + if (gameType != null) { + for(ServerPlayer serverPlayer : minecraftServer.getPlayerList().getPlayers()) { +- if (serverPlayer.setGameMode(gameType)) { +- ++i; ++ // Paper start - extend PlayerGameModeChangeEvent ++ org.bukkit.event.player.PlayerGameModeChangeEvent event = serverPlayer.setGameMode(gameType, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.empty()); ++ if (event != null && event.isCancelled()) { ++ source.sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); + } ++ // Paper end ++ ++i; + } + } + +diff --git a/src/main/java/net/minecraft/server/commands/GameModeCommand.java b/src/main/java/net/minecraft/server/commands/GameModeCommand.java +index d75f78d2e3fb1376e8f6a8668c98a04a693c99e1..79f6089b934124c3309c6bee2e48b36b937252e0 100644 +--- a/src/main/java/net/minecraft/server/commands/GameModeCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GameModeCommand.java +@@ -52,9 +52,14 @@ public class GameModeCommand { + int i = 0; + + for(ServerPlayer serverPlayer : targets) { +- if (serverPlayer.setGameMode(gameMode)) { ++ // Paper start - extend PlayerGameModeChangeEvent ++ org.bukkit.event.player.PlayerGameModeChangeEvent event = serverPlayer.setGameMode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.empty()); ++ if (event != null && !event.isCancelled()) { + logGamemodeChange(context.getSource(), serverPlayer, gameMode); + ++i; ++ } else if (event != null && event.cancelMessage() != null) { ++ context.getSource().sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), true); ++ // Paper end + } + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 3b5feea941eba2ee2c6d93fd5141f2f8f1dbae42..8d39c5314c2566d0193e10ad7c91c314fa16385a 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -1783,8 +1783,15 @@ public class ServerPlayer extends Player { + } + + public boolean setGameMode(GameType gameMode) { +- if (!this.gameMode.changeGameModeForPlayer(gameMode)) { +- return false; ++ // Paper start - Add cause and nullable message to event ++ PlayerGameModeChangeEvent event = this.setGameMode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null); ++ return event == null ? false : event.isCancelled(); ++ } ++ public PlayerGameModeChangeEvent setGameMode(GameType gameMode, PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component message) { ++ PlayerGameModeChangeEvent event = this.gameMode.changeGameModeForPlayer(gameMode, cause, message); ++ if (event == null || event.isCancelled()) { ++ // Paper end ++ return null; + } else { + this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) gameMode.getId())); + if (gameMode == GameType.SPECTATOR) { +@@ -1796,7 +1803,7 @@ public class ServerPlayer extends Player { + + this.onUpdateAbilities(); + this.updateEffectVisibility(); +- return true; ++ return event; // Paper + } + } + +@@ -2178,6 +2185,14 @@ public class ServerPlayer extends Player { + } + + public void loadGameTypes(@Nullable CompoundTag nbt) { ++ if (this.server.getForcedGameType() != null && this.server.getForcedGameType() != ServerPlayer.readPlayerMode(nbt, "playerGameType")) { ++ if (new PlayerGameModeChangeEvent(this.getBukkitEntity(), GameMode.getByValue(this.server.getDefaultGameType().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) { ++ this.gameMode.setGameModeForPlayer(this.server.getForcedGameType(), GameType.DEFAULT_MODE); ++ } else { ++ this.gameMode.setGameModeForPlayer(ServerPlayer.readPlayerMode(nbt,"playerGameType"), ServerPlayer.readPlayerMode(nbt, "previousPlayerGameType")); ++ } ++ return; ++ } + this.gameMode.setGameModeForPlayer(this.calculateGameModeForNewPlayer(ServerPlayer.readPlayerMode(nbt, "playerGameType")), ServerPlayer.readPlayerMode(nbt, "previousPlayerGameType")); + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 2a0f313365a25c1780027f1536dbb88ccdab61e2..013ed10b8eca812309a2c9a10acd668ad51aac8e 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -74,18 +74,24 @@ public class ServerPlayerGameMode { + } + + public boolean changeGameModeForPlayer(GameType gameMode) { ++ // Paper end ++ PlayerGameModeChangeEvent event = this.changeGameModeForPlayer(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null); ++ return event == null ? false : event.isCancelled(); ++ } ++ public PlayerGameModeChangeEvent changeGameModeForPlayer(GameType gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component component) { ++ // Paper end + if (gameMode == this.gameModeForPlayer) { +- return false; ++ return null; // Paper + } else { + // CraftBukkit start + PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(this.player.getBukkitEntity(), GameMode.getByValue(gameMode.getId())); + this.level.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { +- return false; ++ return event; // Paper + } + // CraftBukkit end + this.setGameModeForPlayer(gameMode, this.gameModeForPlayer); +- return true; ++ return event; // Paper + } + } + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index e896057274434eea97d78777dcf303fd83e9cd79..b369d400e34fc8b6d161d79c57bcd26d57147ff8 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2470,7 +2470,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + this.player = this.server.getPlayerList().respawn(this.player, false); + if (this.server.isHardcore()) { +- this.player.setGameMode(GameType.SPECTATOR); ++ this.player.setGameMode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper + ((GameRules.BooleanValue) this.player.getLevel().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, this.server); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index db920ef12e918b7dfdcc4612c4bec0b9961d9a3e..d46c2e85c845c769391af98619b9c771f13f90f7 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1242,7 +1242,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + throw new IllegalArgumentException("Mode cannot be null"); + } + +- this.getHandle().setGameMode(GameType.byId(mode.getValue())); ++ this.getHandle().setGameMode(GameType.byId(mode.getValue()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.PLUGIN, null); // Paper + } + + @Override diff --git a/patches/server-remapped/0735-ItemStack-repair-check-API.patch b/patches/server/0669-ItemStack-repair-check-API.patch similarity index 74% rename from patches/server-remapped/0735-ItemStack-repair-check-API.patch rename to patches/server/0669-ItemStack-repair-check-API.patch index 74dbd3c778..b8be99842d 100644 --- a/patches/server-remapped/0735-ItemStack-repair-check-API.patch +++ b/patches/server/0669-ItemStack-repair-check-API.patch @@ -4,24 +4,12 @@ Date: Sat, 15 May 2021 22:11:11 -0700 Subject: [PATCH] ItemStack repair check API -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index cb079bfd5339b96ad372b0a3b483d02cd0636bfd..42085d3f4ae5c6ceecaffde79fb3187712a2af00 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -269,6 +269,7 @@ public class Item implements ItemLike { - return this.category; - } - -+ public boolean canRepair(ItemStack toBeRepaired, ItemStack repairMaterial) { return isValidRepairItem(toBeRepaired, repairMaterial); } // Paper - OBFHELPER - public boolean isValidRepairItem(ItemStack stack, ItemStack ingredient) { - return false; - } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 402e5a98290a1701dd67d27c484c97e0a6067c4f..34eed57c7ed884e0d634ca403e38d25c95b6a038 100644 +index 5c49c4e671b9d44c12f8d8efcf97305a41e5dbe1..e1b1c754c4ca38331cbb524358becd64957295d0 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -485,6 +485,14 @@ public final class CraftMagicNumbers implements UnsafeValues { - return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; + return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; } + @Override @@ -29,7 +17,7 @@ index 402e5a98290a1701dd67d27c484c97e0a6067c4f..34eed57c7ed884e0d634ca403e38d25c + if (!itemToBeRepaired.getType().isItem() || !repairMaterial.getType().isItem()) { + return false; + } -+ return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); ++ return CraftMagicNumbers.getItem(itemToBeRepaired.getType()).isValidRepairItem(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); + } + @Override diff --git a/patches/server-remapped/0736-More-Enchantment-API.patch b/patches/server/0670-More-Enchantment-API.patch similarity index 59% rename from patches/server-remapped/0736-More-Enchantment-API.patch rename to patches/server/0670-More-Enchantment-API.patch index 4bf44e22d8..a83275d8e7 100644 --- a/patches/server-remapped/0736-More-Enchantment-API.patch +++ b/patches/server/0670-More-Enchantment-API.patch @@ -4,76 +4,20 @@ Date: Thu, 6 May 2021 19:57:58 -0700 Subject: [PATCH] More Enchantment API -diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -index c23ec1b31950471905c65e46273ae105de853d9b..b994a7aca0ce01b5c0d44b9b126295ffcd2f795d 100644 ---- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -+++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -@@ -17,7 +17,7 @@ import net.minecraft.world.item.ItemStack; - - public abstract class Enchantment { - -- private final EquipmentSlot[] slots; -+ private final EquipmentSlot[] slots; public final EquipmentSlot[] getSlots() { return this.slots; } // Paper - OBFHELPER - private final Enchantment.Rarity rarity; - public final EnchantmentCategory category; - @Nullable -@@ -46,6 +46,7 @@ public abstract class Enchantment { - return map; - } - -+ public Enchantment.Rarity getRarity() { return getRarity(); } // Paper - OBFHELPER - public Enchantment.Rarity getRarity() { - return this.rarity; - } -@@ -70,6 +71,7 @@ public abstract class Enchantment { - return 0; - } - -+ public float getDamageIncrease(int level, MobType enumMonsterType) { return getDamageBonus(level, enumMonsterType); } // Paper - OBFHELPER - public float getDamageBonus(int level, MobType group) { - return 0.0F; - } -@@ -123,14 +125,17 @@ public abstract class Enchantment { - return false; - } - -+ public boolean isCursed() { return isCurse(); } // Paper - OBFHELPER - public boolean isCurse() { - return false; - } - -+ public boolean isTradeable() { return isTradeable(); } // Paper - OBFHELPER - public boolean isTradeable() { - return true; - } - -+ public boolean isDiscoverable() { return isDiscoverable(); } // Paper - OBFHELPER - public boolean isDiscoverable() { - return true; - } diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -index b1ffe6c7a5915f00a476e88f3a38349b740b4910..20858bb8463ff86c96b5fcdeca455c20c696870f 100644 +index a7966aa0846637efdc43df1ca97cbc5d29616953..aec59f469b77aa2184a2899e8e8d1c5b823d9263 100644 --- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -@@ -1,8 +1,6 @@ - package org.bukkit.craftbukkit.enchantments; - - import net.minecraft.core.Registry; --import net.minecraft.world.item.enchantment.BindingCurseEnchantment; --import net.minecraft.world.item.enchantment.VanishingCurseEnchantment; - import org.bukkit.craftbukkit.inventory.CraftItemStack; - import org.bukkit.craftbukkit.util.CraftNamespacedKey; - import org.bukkit.enchantments.Enchantment; -@@ -71,7 +69,7 @@ public class CraftEnchantment extends Enchantment { +@@ -71,7 +71,7 @@ public class CraftEnchantment extends Enchantment { @Override public boolean isCursed() { -- return target instanceof BindingCurseEnchantment || target instanceof VanishingCurseEnchantment; -+ return target.isCursed(); // Paper +- return this.target instanceof BindingCurseEnchantment || this.target instanceof VanishingCurseEnchantment; ++ return this.target.isCurse(); // Paper } @Override -@@ -192,6 +190,45 @@ public class CraftEnchantment extends Enchantment { +@@ -192,6 +192,45 @@ public class CraftEnchantment extends Enchantment { public net.kyori.adventure.text.Component displayName(int level) { return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); } @@ -95,12 +39,12 @@ index b1ffe6c7a5915f00a476e88f3a38349b740b4910..20858bb8463ff86c96b5fcdeca455c20 + + @Override + public float getDamageIncrease(int level, org.bukkit.entity.EntityCategory entityCategory) { -+ return target.getDamageIncrease(level, org.bukkit.craftbukkit.entity.CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); ++ return target.getDamageBonus(level, org.bukkit.craftbukkit.entity.CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); + } + + @Override + public java.util.Set getActiveSlots() { -+ return java.util.stream.Stream.of(target.getSlots()).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet()); ++ return java.util.stream.Stream.of(target.slots).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet()); + } + + public static io.papermc.paper.enchantments.EnchantmentRarity fromNMSRarity(net.minecraft.world.item.enchantment.Enchantment.Rarity nmsRarity) { @@ -120,12 +64,12 @@ index b1ffe6c7a5915f00a476e88f3a38349b740b4910..20858bb8463ff86c96b5fcdeca455c20 public net.minecraft.world.item.enchantment.Enchantment getHandle() { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index eefb6bd580ea176c3a242695ab4af46e7c61b492..25ba7a26c951fc5e4638bdb0db36e94d3e08fb2e 100644 +index eed0fb2293cf1e19f2d4f4b66a9e2ef8b214141c..965eb5345d83661809b8b4bc644d5d9af38cf371 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -835,5 +835,21 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { public void setHurtDirection(float hurtDirection) { - getHandle().setHurtDirection(hurtDirection); + getHandle().hurtDir = hurtDirection; } + + public static MobType fromBukkitEntityCategory(EntityCategory entityCategory) { @@ -171,7 +115,7 @@ index 0000000000000000000000000000000000000000..62b56b5b43696b03fc72cac59f986d00 +} diff --git a/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java new file mode 100644 -index 0000000000000000000000000000000000000000..adb0e5b4268fa115b814143cf29d9a3688e4bc17 +index 0000000000000000000000000000000000000000..b9824b1f9491304ceb91be18f4f3b3068526bb33 --- /dev/null +++ b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java @@ -0,0 +1,34 @@ @@ -180,7 +124,7 @@ index 0000000000000000000000000000000000000000..adb0e5b4268fa115b814143cf29d9a36 +import com.google.common.base.Joiner; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; -+import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.MobType; +import org.bukkit.craftbukkit.entity.CraftLivingEntity; +import org.bukkit.entity.EntityCategory; +import org.junit.Test; @@ -196,16 +140,16 @@ index 0000000000000000000000000000000000000000..adb0e5b4268fa115b814143cf29d9a36 + @Test + public void test() throws IllegalAccessException { + -+ Map enumMonsterTypeFieldMap = Maps.newHashMap(); -+ for (Field field : EnumMonsterType.class.getDeclaredFields()) { -+ if (field.getType() == EnumMonsterType.class) { -+ enumMonsterTypeFieldMap.put( (EnumMonsterType) field.get(null), field.getName()); ++ Map enumMonsterTypeFieldMap = Maps.newHashMap(); ++ for (Field field : MobType.class.getDeclaredFields()) { ++ if (field.getType() == MobType.class) { ++ enumMonsterTypeFieldMap.put( (MobType) field.get(null), field.getName()); + } + } + + for (EntityCategory entityCategory : EntityCategory.values()) { + enumMonsterTypeFieldMap.remove(CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); + } -+ assertTrue(EnumMonsterType.class.getName() + " instance(s): " + Joiner.on(", ").join(enumMonsterTypeFieldMap.values()) + " do not have bukkit equivalents", enumMonsterTypeFieldMap.size() == 0); ++ assertTrue(MobType.class.getName() + " instance(s): " + Joiner.on(", ").join(enumMonsterTypeFieldMap.values()) + " do not have bukkit equivalents", enumMonsterTypeFieldMap.size() == 0); + } +} diff --git a/patches/server-remapped/0737-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/server/0671-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 82% rename from patches/server-remapped/0737-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to patches/server/0671-Add-command-line-option-to-load-extra-plugin-jars-no.patch index 6c752cc24c..2299c257c0 100644 --- a/patches/server-remapped/0737-Add-command-line-option-to-load-extra-plugin-jars-no.patch +++ b/patches/server/0671-Add-command-line-option-to-load-extra-plugin-jars-no.patch @@ -7,26 +7,26 @@ Subject: [PATCH] Add command line option to load extra plugin jars not in the ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 63639923f7875d76f569b8c6e958782c6462d906..f1e6d0050092ad51bf233c80b6a51a121e961b07 100644 +index 2f914ebd18764fbfd3834c0a94cedb2184f8dbb0..59c352f9666ff9b828450a62f590ab637b4329b5 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -384,8 +384,13 @@ public final class CraftServer implements Server { +@@ -386,8 +386,13 @@ public final class CraftServer implements Server { File pluginFolder = (File) console.options.valueOf("plugins"); - if (pluginFolder.exists()) { -- Plugin[] plugins = pluginManager.loadPlugins(pluginFolder); +- Plugin[] plugins = this.pluginManager.loadPlugins(pluginFolder); + // Paper start + if (true || pluginFolder.exists()) { + if (!pluginFolder.exists()) { + pluginFolder.mkdirs(); + } -+ Plugin[] plugins = pluginManager.loadPlugins(pluginFolder, this.extraPluginJars()); ++ Plugin[] plugins = this.pluginManager.loadPlugins(pluginFolder, this.extraPluginJars()); + // Paper end for (Plugin plugin : plugins) { try { String message = String.format("Loading %s", plugin.getDescription().getFullName()); -@@ -400,6 +405,18 @@ public final class CraftServer implements Server { +@@ -402,6 +407,18 @@ public final class CraftServer implements Server { } } @@ -44,9 +44,9 @@ index 63639923f7875d76f569b8c6e958782c6462d906..f1e6d0050092ad51bf233c80b6a51a12 + public void enablePlugins(PluginLoadOrder type) { if (type == PluginLoadOrder.STARTUP) { - helpMap.clear(); + this.helpMap.clear(); diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index bd10345cb90f98b8af1519afd603a5244f3a5ca2..521542999b25b1da448fadb3fe6531e083f93e67 100644 +index 6ebd0f6053929beb246993b5a1b682b9971baf0b..ba01312f7615d0507c1bd1cd175588197f8d122e 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -153,6 +153,12 @@ public class Main { diff --git a/patches/server-remapped/0740-Fix-and-optimise-world-force-upgrading.patch b/patches/server/0672-Fix-and-optimise-world-force-upgrading.patch similarity index 83% rename from patches/server-remapped/0740-Fix-and-optimise-world-force-upgrading.patch rename to patches/server/0672-Fix-and-optimise-world-force-upgrading.patch index 2b1a725ed2..ac29e5ed6b 100644 --- a/patches/server-remapped/0740-Fix-and-optimise-world-force-upgrading.patch +++ b/patches/server/0672-Fix-and-optimise-world-force-upgrading.patch @@ -30,7 +30,7 @@ easy to add threading, so I did. diff --git a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java new file mode 100644 -index 0000000000000000000000000000000000000000..f476f21bcfd64d4eb2b690c9100275093c49c9d6 +index 0000000000000000000000000000000000000000..452934a7a037c8b1c5f9906c7af75ed8c449ebc0 --- /dev/null +++ b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java @@ -0,0 +1,200 @@ @@ -104,7 +104,7 @@ index 0000000000000000000000000000000000000000..f476f21bcfd64d4eb2b690c910027509 + LOGGER.info("Force upgrading " + this.worldName); + LOGGER.info("Counting regionfiles for " + this.worldName); + final File[] regionFiles = regionFolder.listFiles((final File dir, final String name) -> { -+ return WorldUpgrader.getRegionfileRegex().matcher(name).matches(); ++ return WorldUpgrader.REGEX.matcher(name).matches(); + }); + if (regionFiles == null) { + LOGGER.info("Found no regionfiles to convert for world " + this.worldName); @@ -235,7 +235,7 @@ index 0000000000000000000000000000000000000000..f476f21bcfd64d4eb2b690c910027509 + } +} diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index ba6c17da4875c3a342da99e354c9f07cc7f17326..d0105061c714af4403b3e14e96e54e17a82c172b 100644 +index cf0a74b8a1c31d4bc493eb09a69ee2bd94cb6485..6fa1a7da70896d0ff34d38698769195a98c06195 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java @@ -15,6 +15,7 @@ import java.nio.file.Paths; @@ -246,7 +246,7 @@ index ba6c17da4875c3a342da99e354c9f07cc7f17326..d0105061c714af4403b3e14e96e54e17 import joptsimple.NonOptionArgumentSpec; import joptsimple.OptionParser; import joptsimple.OptionSet; -@@ -269,6 +270,15 @@ public class Main { +@@ -283,6 +284,15 @@ public class Main { } // Paper end @@ -263,15 +263,15 @@ index ba6c17da4875c3a342da99e354c9f07cc7f17326..d0105061c714af4403b3e14e96e54e17 Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, worlds, eraseCache); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index fd76d776c7003585c9efef44c6d7da0f6c3f574e..9d7cebd703bd0171ca3e95d2985c1a52fdb59712 100644 +index 73ac55de9059a1d0f1da5bec0688dcd4bf5c8973..db2d6e7b2dc82c60d524dd2a018d28c2068552fa 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -512,13 +512,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +- if (this.options.has("forceUpgrade")) { +- net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), this.options.has("eraseCache"), () -> { - return true; - }, worlddata.worldGenSettings().dimensions().entrySet().stream().map((entry1) -> { - return ResourceKey.create(Registry.DIMENSION_TYPE_REGISTRY, ((ResourceKey) entry1.getKey()).location()); @@ -281,7 +281,7 @@ index fd76d776c7003585c9efef44c6d7da0f6c3f574e..9d7cebd703bd0171ca3e95d2985c1a52 ServerLevelData iworlddataserver = worlddata; WorldGenSettings generatorsettings = worlddata.worldGenSettings(); -@@ -538,6 +532,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, dimensionKey.location()); if (dimensionKey == LevelStem.OVERWORLD) { -diff --git a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java -index 79491c5081dbc0cc479d6bc0329ff9b374559c9b..29c0fe698e91e232bcebfafdd853d222c83d5af8 100644 ---- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java -+++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java -@@ -52,7 +52,7 @@ public class WorldUpgrader { - private volatile int skipped; - private final Object2FloatMap> progressMap = Object2FloatMaps.synchronize(new Object2FloatOpenCustomHashMap(Util.identityStrategy())); // CraftBukkit - private volatile Component status = new TranslatableComponent("optimizeWorld.stage.counting"); -- private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); -+ private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); public static final Pattern getRegionfileRegex() { return REGEX; } // Paper - OBFHELPER - private final DimensionDataStorage overworldDataStorage; - - public WorldUpgrader(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, ImmutableSet> worlds, boolean eraseCache) { // CraftBukkit diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 4523bc1f49e7be248a47eeb599fa7b6550dbb08d..d155d00abf8f423e64e6e6d80ddadbc1cfb58a64 100644 +index 31aa0c682fddb0555c2ac47f563484cfa51f2669..ad2d5b19ef23677dd6192b049fca42b9cec392a1 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -181,6 +181,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return typeKey; +@@ -185,6 +185,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return this.typeKey; } + // Paper start - fix and optimise world upgrading + // copied from below + public static ResourceKey getDimensionKey(DimensionType manager) { -+ return ((org.bukkit.craftbukkit.CraftServer)org.bukkit.Bukkit.getServer()).getHandle().getServer().registryHolder.dimensionTypes().getResourceKey(manager).orElseThrow(() -> { ++ return ((org.bukkit.craftbukkit.CraftServer)org.bukkit.Bukkit.getServer()).getHandle().getServer().registryHolder.ownedRegistryOrThrow(net.minecraft.core.Registry.DIMENSION_TYPE_REGISTRY).getResourceKey(manager).orElseThrow(() -> { + return new IllegalStateException("Unregistered dimension type: " + manager); + }); + } + // Paper end - fix and optimise world upgrading -+ - protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -index 1af804c5c6fb2b20ea3f020610763c1d7dcee110..0e38f2f31d167c417b707f00aa68cacaef3d9f6c 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -@@ -109,6 +109,7 @@ public class ChunkStorage implements AutoCloseable { - return nbttagcompound; - } - -+ public static int getVersion(CompoundTag nbttagcompound) { return getVersion(nbttagcompound); } // Paper - OBFHELPER - public static int getVersion(CompoundTag tag) { - return tag.contains("DataVersion", 99) ? tag.getInt("DataVersion") : -1; - } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 0498982ac14f20145d68dbf64a46bcaacf5516ef..7a01f2fbe459e36cee5416455a049b25963e257a 100644 +index 1bee455235ece8aa299a2baeede027d251e6ff57..60ae9395591c81aebaa4be1541380a8fe921ce68 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -30,6 +30,28 @@ public class RegionFileStorage implements AutoCloseable { // Paper - no final - +@@ -29,6 +29,28 @@ public class RegionFileStorage implements AutoCloseable { // Paper - no final + } // Paper start + public static ChunkPos getRegionFileCoordinates(File file) { @@ -371,17 +345,17 @@ index 0498982ac14f20145d68dbf64a46bcaacf5516ef..7a01f2fbe459e36cee5416455a049b25 + } + } + - public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { // Paper - synchronize for async io + public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f1e6d0050092ad51bf233c80b6a51a121e961b07..831f187cde88e815c9a859e52ab45fbbe054f83e 100644 +index 59c352f9666ff9b828450a62f590ab637b4329b5..e5135b5cffc39fa63cb9a78274c026a0b5fddaf8 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1145,14 +1145,7 @@ public final class CraftServer implements Server { +@@ -1143,14 +1143,7 @@ public final class CraftServer implements Server { } worlddata.checkName(name); - worlddata.setModdedInfo(console.getServerModName(), console.getModdedStatus().isPresent()); + worlddata.setModdedInfo(this.console.getServerModName(), this.console.getModdedStatus().isPresent()); - - if (console.options.has("forceUpgrade")) { - net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), console.options.has("eraseCache"), () -> { @@ -394,7 +368,7 @@ index f1e6d0050092ad51bf233c80b6a51a121e961b07..831f187cde88e815c9a859e52ab45fbb long j = BiomeManager.obfuscateSeed(creator.seed()); List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata)); -@@ -1169,6 +1162,14 @@ public final class CraftServer implements Server { +@@ -1167,6 +1160,14 @@ public final class CraftServer implements Server { chunkgenerator = worlddimension.generator(); } diff --git a/patches/server/0673-Add-Mob-lookAt-API.patch b/patches/server/0673-Add-Mob-lookAt-API.patch new file mode 100644 index 0000000000..b82033a43e --- /dev/null +++ b/patches/server/0673-Add-Mob-lookAt-API.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Fri, 14 May 2021 13:42:17 -0500 +Subject: [PATCH] Add Mob#lookAt API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +index 317b6abd2764cf34ef5c42bdbf48ab0bc5a03d27..6549d7c40d6a0ca307fdcb6fd3ca01d2ab732b59 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +@@ -83,5 +83,53 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { + public boolean isInDaylight() { + return getHandle().isSunBurnTick(); + } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location) { ++ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); ++ getHandle().getLookControl().setLookAt(location.getX(), location.getY(), location.getZ()); ++ } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location, float headRotationSpeed, float maxHeadPitch) { ++ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); ++ getHandle().getLookControl().setLookAt(location.getX(), location.getY(), location.getZ(), headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity) { ++ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); ++ getHandle().getLookControl().setLookAt(((CraftEntity) entity).getHandle()); ++ } ++ ++ @Override ++ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity, float headRotationSpeed, float maxHeadPitch) { ++ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); ++ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); ++ getHandle().getLookControl().setLookAt(((CraftEntity) entity).getHandle(), headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public void lookAt(double x, double y, double z) { ++ getHandle().getLookControl().setLookAt(x, y, z); ++ } ++ ++ @Override ++ public void lookAt(double x, double y, double z, float headRotationSpeed, float maxHeadPitch) { ++ getHandle().getLookControl().setLookAt(x, y, z, headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public int getHeadRotationSpeed() { ++ return getHandle().getHeadRotSpeed(); ++ } ++ ++ @Override ++ public int getMaxHeadPitch() { ++ return getHandle().getMaxHeadXRot(); ++ } + // Paper end + } diff --git a/patches/server-remapped/0742-Add-Unix-domain-socket-support.patch b/patches/server/0674-Add-Unix-domain-socket-support.patch similarity index 87% rename from patches/server-remapped/0742-Add-Unix-domain-socket-support.patch rename to patches/server/0674-Add-Unix-domain-socket-support.patch index 83c74f604e..8f002d50bd 100644 --- a/patches/server-remapped/0742-Add-Unix-domain-socket-support.patch +++ b/patches/server/0674-Add-Unix-domain-socket-support.patch @@ -11,10 +11,10 @@ Tested-by: Mariell Hoversholm Reviewed-by: Mariell Hoversholm diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 3ba9c38fc44a8edba9b504112a383249052a0035..cc823a1337bea3ad552687add46706128311f26d 100644 +index 759e563d1ed13249fada8a8eab6b6a10e5ef0d37..e1ecfe280f97985fadbe22db7e420f04c38dd672 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java -@@ -564,6 +564,11 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -614,6 +614,11 @@ public class Connection extends SimpleChannelInboundHandler> { // Spigot Start public SocketAddress getRawAddress() { @@ -27,12 +27,12 @@ index 3ba9c38fc44a8edba9b504112a383249052a0035..cc823a1337bea3ad552687add4670612 } // Spigot End diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 0198268bc614b190cd84f625a62f6c55247a01c8..2821fa9505d6b5adc8e776219df024713fc1a486 100644 +index f5cb59aa72dfd22ec143360a131818bef4f1b701..eeefbb86cb88bd1b132bb6e22b4a4572cfb5e22c 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -222,6 +222,20 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -230,6 +230,20 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist); - // this.saveData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading + // this.worldData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode); + // Paper start - Unix domain socket support + java.net.SocketAddress bindAddress; @@ -51,7 +51,7 @@ index 0198268bc614b190cd84f625a62f6c55247a01c8..2821fa9505d6b5adc8e776219df02471 InetAddress inetaddress = null; if (!this.getLocalIp().isEmpty()) { -@@ -231,12 +245,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -239,12 +253,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface if (this.getPort() < 0) { this.setPort(dedicatedserverproperties.serverPort); } @@ -69,10 +69,10 @@ index 0198268bc614b190cd84f625a62f6c55247a01c8..2821fa9505d6b5adc8e776219df02471 DedicatedServer.LOGGER.warn("**** FAILED TO BIND TO PORT!"); DedicatedServer.LOGGER.warn("The exception was: {}", ioexception.toString()); diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -index bcc19d0a4b6c5f683dc416e27a13705b57213d21..67a17ced9460bc83a6f564b38fdb43b1a7f1b8a0 100644 +index 9c9368628845f316e157f6ae15b89c24af082d97..158933a67beadd7f667351d9826ba56f6cc7d781 100644 --- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -@@ -70,7 +70,12 @@ public class ServerConnectionListener { +@@ -67,7 +67,12 @@ public class ServerConnectionListener { this.running = true; } @@ -85,7 +85,7 @@ index bcc19d0a4b6c5f683dc416e27a13705b57213d21..67a17ced9460bc83a6f564b38fdb43b1 List list = this.channels; synchronized (this.channels) { -@@ -78,7 +83,11 @@ public class ServerConnectionListener { +@@ -75,7 +80,11 @@ public class ServerConnectionListener { LazyLoadedValue lazyinitvar; if (Epoll.isAvailable() && this.server.isEpollEnabled()) { @@ -97,7 +97,7 @@ index bcc19d0a4b6c5f683dc416e27a13705b57213d21..67a17ced9460bc83a6f564b38fdb43b1 lazyinitvar = ServerConnectionListener.SERVER_EPOLL_EVENT_GROUP; ServerConnectionListener.LOGGER.info("Using epoll channel type"); } else { -@@ -106,7 +115,7 @@ public class ServerConnectionListener { +@@ -101,7 +110,7 @@ public class ServerConnectionListener { ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper } @@ -107,7 +107,7 @@ index bcc19d0a4b6c5f683dc416e27a13705b57213d21..67a17ced9460bc83a6f564b38fdb43b1 } diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java -index 4e055a41de3ee410682cc05a3b883ac8babeb290..e1fbb207d6921516c7423e9a3cded8efb5676d49 100644 +index 4c44f06ba18cfa2d889d0dd57fdd7eb79971c8c6..e0cd786f130e34b3401d40663e1548fc0076f74a 100644 --- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java @@ -44,6 +44,7 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL @@ -129,11 +129,11 @@ index 4e055a41de3ee410682cc05a3b883ac8babeb290..e1fbb207d6921516c7423e9a3cded8ef @@ -120,8 +122,11 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! String[] split = packet.hostName.split("\00"); - if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper + if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.BYPASS_HOSTCHECK || ServerHandshakePacketListenerImpl.HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper + // Paper start - Unix domain socket support + java.net.SocketAddress socketAddress = connection.getRemoteAddress(); packet.hostName = split[0]; -- connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort()); +- connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getPort()); + connection.address = new java.net.InetSocketAddress(split[1], socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); + // Paper end connection.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); diff --git a/patches/server-remapped/0743-Add-EntityInsideBlockEvent.patch b/patches/server/0675-Add-EntityInsideBlockEvent.patch similarity index 72% rename from patches/server-remapped/0743-Add-EntityInsideBlockEvent.patch rename to patches/server/0675-Add-EntityInsideBlockEvent.patch index 6380d78daa..31db266834 100644 --- a/patches/server-remapped/0743-Add-EntityInsideBlockEvent.patch +++ b/patches/server/0675-Add-EntityInsideBlockEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add EntityInsideBlockEvent diff --git a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java -index ad37261e716b15d62fc2083d137cdac818308cdd..58519e224a5005bf6468b99196acb7209b2e1398 100644 +index 177d1da44c83da5f99ae91891dec41dc210bd31d..d2fb4d5738919c1e7b9a7f08aad2e4b607414a53 100644 --- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java -@@ -48,6 +48,7 @@ public abstract class BaseFireBlock extends Block { +@@ -123,6 +123,7 @@ public abstract class BaseFireBlock extends Block { @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { @@ -17,10 +17,10 @@ index ad37261e716b15d62fc2083d137cdac818308cdd..58519e224a5005bf6468b99196acb720 entity.setRemainingFireTicks(entity.getRemainingFireTicks() + 1); if (entity.getRemainingFireTicks() == 0) { diff --git a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java -index 6acb24f96591d555e550d399d2ed38036a0220fe..8d8fd646c9527852bfe9a2d3cd0a6bf1bfa9e4a2 100644 +index 94c48393e467f61cb763e8c44baccdef446be474..14de86667e9c05da95e807177d8c44cdaa765f18 100644 --- a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java -@@ -65,6 +65,7 @@ public abstract class BasePressurePlateBlock extends Block { +@@ -67,6 +67,7 @@ public abstract class BasePressurePlateBlock extends Block { @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { @@ -29,22 +29,22 @@ index 6acb24f96591d555e550d399d2ed38036a0220fe..8d8fd646c9527852bfe9a2d3cd0a6bf1 int i = this.getSignalForState(state); diff --git a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java -index f741980d0e1759e3fefe322b654760dab35200d6..faa1070aaf3fcc40bf7e36a0dda8ec7879c89dd6 100644 +index 68135caecf506a5a2ad36def1a94a83eec3abe32..17cffb3bd362dc4a69535425f7289af7ccb640eb 100644 --- a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java -@@ -33,6 +33,7 @@ public class BubbleColumnBlock extends Block implements BucketPickup { +@@ -38,6 +38,7 @@ public class BubbleColumnBlock extends Block implements BucketPickup { @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { + if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - BlockState iblockdata1 = world.getBlockState(pos.above()); - - if (iblockdata1.isAir()) { + BlockState blockState = world.getBlockState(pos.above()); + if (blockState.isAir()) { + entity.onAboveBubbleCol(state.getValue(DRAG_DOWN)); diff --git a/src/main/java/net/minecraft/world/level/block/ButtonBlock.java b/src/main/java/net/minecraft/world/level/block/ButtonBlock.java -index 52ca5dad75674b81b997f8a1cf3f5d52bf4313c1..2c4c5fc6d45225cc9f7f1c2038bd4d0ae20c9daa 100644 +index 698a80029f4410045af486f926324b3fdb98bb64..af6730322a7cea0c4f9ca92c289698554bf86b3a 100644 --- a/src/main/java/net/minecraft/world/level/block/ButtonBlock.java +++ b/src/main/java/net/minecraft/world/level/block/ButtonBlock.java -@@ -179,6 +179,7 @@ public abstract class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock +@@ -186,6 +186,7 @@ public abstract class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { @@ -53,10 +53,10 @@ index 52ca5dad75674b81b997f8a1cf3f5d52bf4313c1..2c4c5fc6d45225cc9f7f1c2038bd4d0a this.checkPressed(state, world, pos); } diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java -index de61393e3f702554817d81ff10693ec3fb63d492..28b083a8220856723b6169b5b13677b965a4dab6 100644 +index 722f1816cd4130fa4b1e2310badedc77ab96eee6..2a02fdf58640d26b82e0ca22d0d8ff3326921b61 100644 --- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java +++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java -@@ -115,6 +115,7 @@ public class CactusBlock extends Block { +@@ -117,6 +117,7 @@ public class CactusBlock extends Block { @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { @@ -65,10 +65,10 @@ index de61393e3f702554817d81ff10693ec3fb63d492..28b083a8220856723b6169b5b13677b9 entity.hurt(DamageSource.CACTUS, 1.0F); CraftEventFactory.blockDamage = null; // CraftBukkit diff --git a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java -index 87f106ad9139157af69a0ae1602c32ed372a04be..b0c6ac74daea347f4acb5da95e6b0cb013827509 100644 +index f602ddb6fc5a9d026239c900ec800122663d6bfc..2519a0f511f0a6065459cd2fe2d9a3e68e55d222 100644 --- a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java -@@ -88,6 +88,7 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB +@@ -91,6 +91,7 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { @@ -76,23 +76,11 @@ index 87f106ad9139157af69a0ae1602c32ed372a04be..b0c6ac74daea347f4acb5da95e6b0cb0 if (!entity.fireImmune() && (Boolean) state.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { entity.hurt(DamageSource.IN_FIRE, (float) this.fireDamage); } -diff --git a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java -index 941061b50f7909278e962fb2aa080bb630862aa1..7d23adaa833c9c45708705294969fe268153b927 100644 ---- a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java -@@ -58,6 +58,7 @@ public class CauldronBlock extends Block { - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - int i = (Integer) state.getValue(CauldronBlock.LEVEL); - float f = (float) pos.getY() + (6.0F + (float) (3 * i)) / 16.0F; - diff --git a/src/main/java/net/minecraft/world/level/block/CropBlock.java b/src/main/java/net/minecraft/world/level/block/CropBlock.java -index 4cd6f18e0a2ee8d0495b3c822b227e212a13b11f..8368a5911690a9abb26c0f381bda7a0633197548 100644 +index ea8047d4509632c9bc8247356f6eb3d1289db672..6dda5eeca4e310eceb2598322803bfafc184e9c7 100644 --- a/src/main/java/net/minecraft/world/level/block/CropBlock.java +++ b/src/main/java/net/minecraft/world/level/block/CropBlock.java -@@ -159,6 +159,7 @@ public class CropBlock extends BushBlock implements BonemealableBlock { +@@ -163,6 +163,7 @@ public class CropBlock extends BushBlock implements BonemealableBlock { @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { @@ -101,7 +89,7 @@ index 4cd6f18e0a2ee8d0495b3c822b227e212a13b11f..8368a5911690a9abb26c0f381bda7a06 world.destroyBlock(pos, true, entity); } diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java -index 1854809e045300e84a713dc7c3a8264f53ec6c0f..d970fe7137f7dd37221b54e4025b98d15b950489 100644 +index 63c7f2cf530ac9562960ae5a3cbc6e511a009377..3705452f1b57d3bc1307411c7367529de0fa47e1 100644 --- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java @@ -44,6 +44,7 @@ public class DetectorRailBlock extends BaseRailBlock { @@ -113,10 +101,10 @@ index 1854809e045300e84a713dc7c3a8264f53ec6c0f..d970fe7137f7dd37221b54e4025b98d1 if (!(Boolean) state.getValue(DetectorRailBlock.POWERED)) { this.checkPressed(world, pos, state); diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -index a6d793478be8e2aab1f72b68a6a96c86642ad1fc..2231680140d0e3c4c10b6722fd13fe0ee55ce294 100644 +index cc76a17492a67c1d2b97a8b6cd991db893de4414..834be24478b801d75be96ada91a4f18ccc3ee7b4 100644 --- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -@@ -41,6 +41,7 @@ public class EndPortalBlock extends BaseEntityBlock { +@@ -44,6 +44,7 @@ public class EndPortalBlock extends BaseEntityBlock { @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { @@ -125,10 +113,10 @@ index a6d793478be8e2aab1f72b68a6a96c86642ad1fc..2231680140d0e3c4c10b6722fd13fe0e ResourceKey resourcekey = world.getTypeKey() == DimensionType.END_LOCATION ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends ServerLevel worldserver = ((ServerLevel) world).getServer().getLevel(resourcekey); diff --git a/src/main/java/net/minecraft/world/level/block/HoneyBlock.java b/src/main/java/net/minecraft/world/level/block/HoneyBlock.java -index 7d0206dc5ac46220970adad51863028840b4a9ad..ef74852a1677a4ec80149aa7eafca910fac5ee91 100644 +index 6f7bcf0ae17aec3e937ff52084f53681aacb9398..c6a988fdc92cd7329b4fd7c6b415fd2fe01aa8a3 100644 --- a/src/main/java/net/minecraft/world/level/block/HoneyBlock.java +++ b/src/main/java/net/minecraft/world/level/block/HoneyBlock.java -@@ -49,6 +49,7 @@ public class HoneyBlock extends HalfTransparentBlock { +@@ -55,6 +55,7 @@ public class HoneyBlock extends HalfTransparentBlock { @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { @@ -137,22 +125,46 @@ index 7d0206dc5ac46220970adad51863028840b4a9ad..ef74852a1677a4ec80149aa7eafca910 this.maybeDoSlideAchievement(entity, pos); this.doSlideMovement(entity); diff --git a/src/main/java/net/minecraft/world/level/block/HopperBlock.java b/src/main/java/net/minecraft/world/level/block/HopperBlock.java -index 1f50c2b4bebeb6a224eb0ac552d6ea693f7831a6..40b1bba69ae96e4cd652261e3f97850e2e7c51a3 100644 +index 9a58f017bbaa742cbb892c804011cc9396b8607c..386c3e458babc31ad3bf2b51c20d1cfde08647ac 100644 --- a/src/main/java/net/minecraft/world/level/block/HopperBlock.java +++ b/src/main/java/net/minecraft/world/level/block/HopperBlock.java -@@ -197,6 +197,7 @@ public class HopperBlock extends BaseEntityBlock { +@@ -200,6 +200,7 @@ public class HopperBlock extends BaseEntityBlock { @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { + if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - BlockEntity tileentity = world.getBlockEntity(pos); + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof HopperBlockEntity) { + HopperBlockEntity.entityInside(world, pos, state, entity, (HopperBlockEntity)blockEntity); +diff --git a/src/main/java/net/minecraft/world/level/block/LavaCauldronBlock.java b/src/main/java/net/minecraft/world/level/block/LavaCauldronBlock.java +index f0a3ef0529951e7732602d358ddea1782001db7e..6588b207d93d96934e72176874ba60c81e9a098c 100644 +--- a/src/main/java/net/minecraft/world/level/block/LavaCauldronBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/LavaCauldronBlock.java +@@ -24,6 +24,7 @@ public class LavaCauldronBlock extends AbstractCauldronBlock { - if (tileentity instanceof HopperBlockEntity) { + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (this.isEntityInsideContent(state, pos, entity)) { + entity.lavaHurt(); + } +diff --git a/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java b/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java +index 033b4e342d6c3978be084e65a2a7a3b23d6a7851..058f55c68ea788719b369efbe78a02dfadfcd960 100644 +--- a/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java +@@ -59,6 +59,7 @@ public class LayeredCauldronBlock extends AbstractCauldronBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide && entity.isOnFire() && this.isEntityInsideContent(state, pos, entity)) { + // CraftBukkit start + if (entity.mayInteract(world, pos)) { diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -index ae58929886921d0714bf811de92f99dc0dc120dc..53e7570cc2538e73f1cfe3d28ffc491f61cac372 100644 +index cfea29f5bf1c5e74a0292c1344baaaa49c2f4403..bc2f2c69d437e99cb965cede7dfd42228151b26c 100644 --- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -@@ -81,6 +81,7 @@ public class NetherPortalBlock extends Block { +@@ -85,6 +85,7 @@ public class NetherPortalBlock extends Block { @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { @@ -160,11 +172,23 @@ index ae58929886921d0714bf811de92f99dc0dc120dc..53e7570cc2538e73f1cfe3d28ffc491f if (!entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions()) { // CraftBukkit start - Entity in portal EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); +diff --git a/src/main/java/net/minecraft/world/level/block/PowderSnowBlock.java b/src/main/java/net/minecraft/world/level/block/PowderSnowBlock.java +index ceda744e9f7e48051e046eb3171e80bded739ba8..1187a7382b8849524f99bbd8d12b43677f1053cd 100644 +--- a/src/main/java/net/minecraft/world/level/block/PowderSnowBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/PowderSnowBlock.java +@@ -54,6 +54,7 @@ public class PowderSnowBlock extends Block implements BucketPickup { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!(entity instanceof LivingEntity) || entity.getFeetBlockState().is((Block) this)) { + entity.makeStuckInBlock(state, new Vec3(0.8999999761581421D, 1.5D, 0.8999999761581421D)); + if (world.isClientSide) { diff --git a/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java b/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java -index 09122e2031e9ddfae4544911f8c25b937b03933f..6b5e8654ddd2c268627d0244b01dadeaeb4a7de4 100644 +index 1a5590ff8e5122b5c7587347fcc38d73671c2747..71abf800e623336124bd9a955e07db4950286516 100644 --- a/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java +++ b/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java -@@ -66,6 +66,7 @@ public class SweetBerryBushBlock extends BushBlock implements BonemealableBlock +@@ -73,6 +73,7 @@ public class SweetBerryBushBlock extends BushBlock implements BonemealableBlock @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { @@ -173,10 +197,10 @@ index 09122e2031e9ddfae4544911f8c25b937b03933f..6b5e8654ddd2c268627d0244b01dadea entity.makeStuckInBlock(state, new Vec3(0.800000011920929D, 0.75D, 0.800000011920929D)); if (!world.isClientSide && (Integer) state.getValue(SweetBerryBushBlock.AGE) > 0 && (entity.xOld != entity.getX() || entity.zOld != entity.getZ())) { diff --git a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java -index eaee409bc8fbf8c5541afd10d24975535556a7f6..a488a2a589126df617564d9278eb0496915b6f88 100644 +index baa14c23016df6687984447d1a1f071b29aa7b49..9cafee5bd1e432ed5f114c73cf616798cd71a379 100644 --- a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java -@@ -118,6 +118,7 @@ public class TripWireBlock extends Block { +@@ -121,6 +121,7 @@ public class TripWireBlock extends Block { @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { @@ -197,22 +221,22 @@ index 2b2a28d0383ccc8c0e7debd90331570b02b5e65f..bd4295f8d24ca9fd8c3af31abcd13da2 world.destroyBlock(new BlockPos(pos), true, entity); } diff --git a/src/main/java/net/minecraft/world/level/block/WebBlock.java b/src/main/java/net/minecraft/world/level/block/WebBlock.java -index c368531420d464414de3661e1624e2a284976ab6..fc1c2e057e8b63048c919b5cbcc0a0e897f1dd01 100644 +index 6964308822ebf8a7027ce426062ba43a70c20c15..763fa221c562e96c2abd09c7055e91a86ac03d43 100644 --- a/src/main/java/net/minecraft/world/level/block/WebBlock.java +++ b/src/main/java/net/minecraft/world/level/block/WebBlock.java -@@ -15,6 +15,7 @@ public class WebBlock extends Block { +@@ -14,6 +14,7 @@ public class WebBlock extends Block { @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { + if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - entity.makeStuckInBlock(state, new Vec3(0.25D, 0.05000000074505806D, 0.25D)); + entity.makeStuckInBlock(state, new Vec3(0.25D, (double)0.05F, 0.25D)); } } diff --git a/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java b/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java -index c1648c28c761cdf31089d434f9cb896ddef41521..5cb4e1ec7ce3087163d2ecf26d043894310768d1 100644 +index adf1e71323ea84856ec2871b8e3227f29ff59c40..5b6fe6fa607c38e42a30d6c7c6f6fc93af93dd20 100644 --- a/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java +++ b/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java -@@ -26,6 +26,7 @@ public class WitherRoseBlock extends FlowerBlock { +@@ -46,6 +46,7 @@ public class WitherRoseBlock extends FlowerBlock { @Override public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { diff --git a/patches/server-remapped/0744-Attributes-API-for-item-defaults.patch b/patches/server/0676-Attributes-API-for-item-defaults.patch similarity index 58% rename from patches/server-remapped/0744-Attributes-API-for-item-defaults.patch rename to patches/server/0676-Attributes-API-for-item-defaults.patch index ce7b672b14..f6dd86b8a3 100644 --- a/patches/server-remapped/0744-Attributes-API-for-item-defaults.patch +++ b/patches/server/0676-Attributes-API-for-item-defaults.patch @@ -4,34 +4,22 @@ Date: Sat, 8 May 2021 15:01:54 -0700 Subject: [PATCH] Attributes API for item defaults -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 42085d3f4ae5c6ceecaffde79fb3187712a2af00..3043378c3addf959e0ccf323c1cde8b300b5f237 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -274,6 +274,7 @@ public class Item implements ItemLike { - return false; - } - -+ public Multimap getAttributesForSlot(EquipmentSlot enumItemSlot) { return getDefaultAttributeModifiers(enumItemSlot); } // Paper - OBFHELPER - public Multimap getDefaultAttributeModifiers(EquipmentSlot slot) { - return ImmutableMultimap.of(); - } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 34eed57c7ed884e0d634ca403e38d25c95b6a038..824111fc74bade75ce06b1f0b57498006d0a66cd 100644 +index e1b1c754c4ca38331cbb524358becd64957295d0..e5fc463e2d2e4a1b3c394ceb21e25f1c286aeb0a 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -493,6 +493,19 @@ public final class CraftMagicNumbers implements UnsafeValues { - return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); + return CraftMagicNumbers.getItem(itemToBeRepaired.getType()).isValidRepairItem(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); } + @Override + public com.google.common.collect.Multimap getItemAttributes(org.bukkit.Material material, org.bukkit.inventory.EquipmentSlot equipmentSlot) { -+ Item item = this.getItem(material); ++ Item item = CraftMagicNumbers.getItem(material); + if (item == null) { + throw new IllegalArgumentException(material + " is not an item and therefore does not have attributes"); + } + com.google.common.collect.ImmutableMultimap.Builder attributeMapBuilder = com.google.common.collect.ImmutableMultimap.builder(); -+ item.getAttributesForSlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(equipmentSlot)).forEach((attributeBase, attributeModifier) -> { ++ item.getDefaultAttributeModifiers(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(equipmentSlot)).forEach((attributeBase, attributeModifier) -> { + attributeMapBuilder.put(org.bukkit.Registry.ATTRIBUTE.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.Registry.ATTRIBUTE.getKey(attributeBase))), org.bukkit.craftbukkit.attribute.CraftAttributeInstance.convert(attributeModifier)); + }); + return attributeMapBuilder.build(); diff --git a/patches/server-remapped/0745-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/patches/server/0677-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch similarity index 76% rename from patches/server-remapped/0745-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch rename to patches/server/0677-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch index 339837dc3e..586065db50 100644 --- a/patches/server-remapped/0745-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch +++ b/patches/server/0677-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch @@ -4,21 +4,8 @@ Date: Thu, 6 May 2021 13:01:25 +0100 Subject: [PATCH] Have CraftMerchantCustom emit PlayerPurchaseEvent -diff --git a/src/main/java/net/minecraft/world/item/trading/Merchant.java b/src/main/java/net/minecraft/world/item/trading/Merchant.java -index 8298e667aa3a17d987bbc4cc2b63600af48beabc..334df355470bff98db63396b33c8db6a0abcc61a 100644 ---- a/src/main/java/net/minecraft/world/item/trading/Merchant.java -+++ b/src/main/java/net/minecraft/world/item/trading/Merchant.java -@@ -19,7 +19,7 @@ public interface Merchant { - - MerchantOffers getOffers(); - -- void notifyTrade(MerchantOffer offer); -+ void notifyTrade(MerchantOffer offer); default void handlePurchase(MerchantOffer merchantRecipe) { notifyTrade(merchantRecipe); } // Paper - OBFHELPER - - void notifyTradeUpdated(ItemStack stack); - diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -index 306c6483708ae1b41bd16f122d36beec1916a776..d52192545c39734be3c97c7978652a54d7b9f029 100644 +index f40d6a0048ad5b3f6e31d83894ee89f5ca64fb3a..56a04cfdedfbc34be686304fc2dde59f1707d282 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java @@ -81,6 +81,35 @@ public class CraftMerchantCustom extends CraftMerchant { diff --git a/patches/server-remapped/0746-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/server/0678-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 57% rename from patches/server-remapped/0746-Add-cause-to-Weather-ThunderChangeEvents.patch rename to patches/server/0678-Add-cause-to-Weather-ThunderChangeEvents.patch index fb889a4693..b94ca80e31 100644 --- a/patches/server-remapped/0746-Add-cause-to-Weather-ThunderChangeEvents.patch +++ b/patches/server/0678-Add-cause-to-Weather-ThunderChangeEvents.patch @@ -5,53 +5,53 @@ Subject: [PATCH] Add cause to Weather/ThunderChangeEvents diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 511e6a941d441c55a4b38660f0f7f8c47fa689dd..85e62e3c52950a517c4dbae739d21d879cb467a4 100644 +index a2d9e093bf7b5ee947f1d7c3b94397cd93eedef7..985b8b9da26aba43b84e9fe363507627c625e6d3 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -413,8 +413,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.worldDataServer.setClearWeatherTime(clearDuration); - this.worldDataServer.setRainTime(rainDuration); - this.worldDataServer.setThunderTime(rainDuration); -- this.worldDataServer.setRaining(raining); -- this.worldDataServer.setThundering(thundering); -+ this.worldDataServer.setRaining(raining, org.bukkit.event.weather.WeatherChangeEvent.Cause.COMMAND); // Paper -+ this.worldDataServer.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.COMMAND); // Paper +@@ -419,8 +419,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.serverLevelData.setClearWeatherTime(clearDuration); + this.serverLevelData.setRainTime(rainDuration); + this.serverLevelData.setThunderTime(rainDuration); +- this.serverLevelData.setRaining(raining); +- this.serverLevelData.setThundering(thundering); ++ this.serverLevelData.setRaining(raining, org.bukkit.event.weather.WeatherChangeEvent.Cause.COMMAND); // Paper ++ this.serverLevelData.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.COMMAND); // Paper } - public Biome getBiomeBySeed(int i, int j, int k) { return getUncachedNoiseBiome(i, j, k); } // Paper - OBFHELPER -@@ -476,8 +476,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.worldDataServer.setThunderTime(j); - this.worldDataServer.setRainTime(k); - this.worldDataServer.setClearWeatherTime(i); -- this.worldDataServer.setThundering(flag1); -- this.worldDataServer.setRaining(flag2); -+ this.worldDataServer.setThundering(flag1, org.bukkit.event.weather.ThunderChangeEvent.Cause.NATURAL); // Paper -+ this.worldDataServer.setRaining(flag2, org.bukkit.event.weather.WeatherChangeEvent.Cause.NATURAL); // Paper + @Override +@@ -483,8 +483,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.serverLevelData.setThunderTime(j); + this.serverLevelData.setRainTime(k); + this.serverLevelData.setClearWeatherTime(i); +- this.serverLevelData.setThundering(flag1); +- this.serverLevelData.setRaining(flag2); ++ this.serverLevelData.setThundering(flag1, org.bukkit.event.weather.ThunderChangeEvent.Cause.NATURAL); // Paper ++ this.serverLevelData.setRaining(flag2, org.bukkit.event.weather.WeatherChangeEvent.Cause.NATURAL); // Paper } this.oThunderLevel = this.thunderLevel; -@@ -879,14 +879,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -887,14 +887,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl private void stopWeather() { // CraftBukkit start -- this.worldDataServer.setRaining(false); -+ this.worldDataServer.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - when passing the night +- this.serverLevelData.setRaining(false); ++ this.serverLevelData.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - when passing the night // If we stop due to everyone sleeping we should reset the weather duration to some other random value. // Not that everyone ever manages to get the whole server to sleep at the same time.... - if (!this.worldDataServer.isRaining()) { - this.worldDataServer.setRainTime(0); + if (!this.serverLevelData.isRaining()) { + this.serverLevelData.setRainTime(0); } // CraftBukkit end -- this.worldDataServer.setThundering(false); -+ this.worldDataServer.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - when passing the night +- this.serverLevelData.setThundering(false); ++ this.serverLevelData.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - when passing the night // CraftBukkit start // If we stop due to everyone sleeping we should reset the weather duration to some other random value. // Not that everyone ever manages to get the whole server to sleep at the same time.... diff --git a/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java b/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java -index 83f2fdfa1ac2435f5199b5c33bfc409d2e94f4ed..e902534fd64f72e46feefa04f526e0dacd612627 100644 +index cd840dc4a8ca432868fb3e9c912ea928e5303e0d..4d0af984490b556a9911c3b8fdca1e168e6fe932 100644 --- a/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java +++ b/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java -@@ -325,21 +325,26 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { +@@ -330,21 +330,26 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { @Override public void setThundering(boolean thundering) { @@ -66,7 +66,7 @@ index 83f2fdfa1ac2435f5199b5c33bfc409d2e94f4ed..e902534fd64f72e46feefa04f526e0da return; } - org.bukkit.World world = Bukkit.getWorld(getLevelName()); + org.bukkit.World world = Bukkit.getWorld(this.getLevelName()); if (world != null) { - ThunderChangeEvent thunder = new ThunderChangeEvent(world, thundering); + ThunderChangeEvent thunder = new ThunderChangeEvent(world, flag, cause); // Paper @@ -81,7 +81,7 @@ index 83f2fdfa1ac2435f5199b5c33bfc409d2e94f4ed..e902534fd64f72e46feefa04f526e0da } @Override -@@ -359,21 +364,27 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { +@@ -364,6 +369,12 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { @Override public void setRaining(boolean raining) { @@ -89,48 +89,39 @@ index 83f2fdfa1ac2435f5199b5c33bfc409d2e94f4ed..e902534fd64f72e46feefa04f526e0da + this.setRaining(raining, org.bukkit.event.weather.WeatherChangeEvent.Cause.UNKNOWN); + } + -+ public void setStorm(boolean flag, org.bukkit.event.weather.WeatherChangeEvent.Cause cause) { ++ public void setRaining(boolean raining, org.bukkit.event.weather.WeatherChangeEvent.Cause cause) { + // Paper end // CraftBukkit start -- if (this.raining == raining) { -+ if (this.raining == flag) { + if (this.raining == raining) { return; - } +@@ -371,7 +382,7 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { - org.bukkit.World world = Bukkit.getWorld(getLevelName()); + org.bukkit.World world = Bukkit.getWorld(this.getLevelName()); if (world != null) { - WeatherChangeEvent weather = new WeatherChangeEvent(world, raining); -+ WeatherChangeEvent weather = new WeatherChangeEvent(world, flag, cause); // Paper ++ WeatherChangeEvent weather = new WeatherChangeEvent(world, raining, cause); // Paper Bukkit.getServer().getPluginManager().callEvent(weather); if (weather.isCancelled()) { return; - } - } - // CraftBukkit end -- this.raining = raining; -+ this.raining = flag; - } - - @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index a1fa2d5e00bd125abd38a00e0bc3936f2fb8186f..1c9321cef1a05c5e8a22dd52bc63a5103eaf7311 100644 +index 8a9d367cfcf49f80f05633d16a7019798fc808ec..fb90250f1b61c34a0a88bf50bc5b5bae09de9f0e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1452,7 +1452,7 @@ public class CraftWorld implements World { +@@ -1456,7 +1456,7 @@ public class CraftWorld implements World { @Override public void setStorm(boolean hasStorm) { - world.levelData.setRaining(hasStorm); -+ world.worldDataServer.setRaining(hasStorm, org.bukkit.event.weather.WeatherChangeEvent.Cause.PLUGIN); // Paper - setWeatherDuration(0); // Reset weather duration (legacy behaviour) - setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) ++ world.serverLevelData.setRaining(hasStorm, org.bukkit.event.weather.WeatherChangeEvent.Cause.PLUGIN); // Paper + this.setWeatherDuration(0); // Reset weather duration (legacy behaviour) + this.setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) } -@@ -1474,7 +1474,7 @@ public class CraftWorld implements World { +@@ -1478,7 +1478,7 @@ public class CraftWorld implements World { @Override public void setThundering(boolean thundering) { -- world.worldDataServer.setThundering(thundering); -+ world.worldDataServer.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.PLUGIN); // Paper - setThunderDuration(0); // Reset weather duration (legacy behaviour) - setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) +- world.serverLevelData.setThundering(thundering); ++ world.serverLevelData.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.PLUGIN); // Paper + this.setThunderDuration(0); // Reset weather duration (legacy behaviour) + this.setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) } diff --git a/patches/server-remapped/0747-More-Lidded-Block-API.patch b/patches/server/0679-More-Lidded-Block-API.patch similarity index 64% rename from patches/server-remapped/0747-More-Lidded-Block-API.patch rename to patches/server/0679-More-Lidded-Block-API.patch index 5a3dcda899..946581e92d 100644 --- a/patches/server-remapped/0747-More-Lidded-Block-API.patch +++ b/patches/server/0679-More-Lidded-Block-API.patch @@ -4,70 +4,40 @@ Date: Sun, 23 May 2021 17:49:51 +0900 Subject: [PATCH] More Lidded Block API -diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java -index 8f0477d9620ef71e10855bbca07f9b6984d5d794..70ca456fad052ca6eeaf8c4242c78d15d81084a5 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java -@@ -10,8 +10,9 @@ public class EnderChestBlockEntity extends BlockEntity { // Paper - Remove ITick - - public float openness; - public float oOpenness; -- public int openCount; -+ public int openCount; public int getViewerCount() { return openCount; } // Paper - OBFHELPER - private int tickInterval; -+ public boolean opened; // Paper - More Lidded Block API - - public EnderChestBlockEntity() { - super(BlockEntityType.ENDER_CHEST); -@@ -106,12 +107,14 @@ public class EnderChestBlockEntity extends BlockEntity { // Paper - Remove ITick - - public void startOpen() { - ++this.openCount; -+ if (opened) return; // Paper - More Lidded Block API - this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); - doOpenLogic(); // Paper - } - - public void stopOpen() { - --this.openCount; -+ if (opened) return; // Paper - More Lidded Block API - this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount); - doCloseLogic(); // Paper - } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java -index a0eadcbcb2575eb18f7b4951ae9eadfbc2e8af6f..fc4397a48425a23d64e0a679ace9e58fbf9b770b 100644 +index dcae26b698d31a8b0107b0f9757efa34f53b030a..c0e7ae7ae38d55088e1b6ae6c80b849fd740cb1a 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java @@ -59,4 +59,11 @@ public class CraftBarrel extends CraftLootable implements Bar } - getTileEntity().opened = false; + getTileEntity().openersCounter.opened = false; } + + // Paper start - More Lidded Block API + @Override + public boolean isOpen() { -+ return getTileEntity().opened; ++ return getTileEntity().openersCounter.opened; + } + // Paper end - More Lidded Block API } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -index a821df3e13e2ddc479dc5f55540671f43563cdac..9d7af8717085ba5c170a998aa863686d72840a40 100644 +index f48b830a9ae8160388cb0d0220a44b1ec9f0d214..5045507871db402305a43430194b4c5e965300ad 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -@@ -78,4 +78,11 @@ public class CraftChest extends CraftLootable implements Chest +@@ -79,4 +79,11 @@ public class CraftChest extends CraftLootable implements Chest } - getTileEntity().opened = false; + getTileEntity().openersCounter.opened = false; } + + // Paper start - More Lidded Block API + @Override + public boolean isOpen() { -+ return getTileEntity().opened; ++ return getTileEntity().openersCounter.opened; + } + // Paper end - More Lidded Block API } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java -index 25add8bee6ea35beeb205dd828759304346e4f48..fabcb2b8dc950fd074d65fed95d6b371dcfbf842 100644 +index 25add8bee6ea35beeb205dd828759304346e4f48..d4a5810111c81845c3b465468b470535f814889b 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java @@ -14,4 +14,33 @@ public class CraftEnderChest extends CraftBlockEntityState 0) { From cf885102cdee042107ae9495c5b60ffce301062e Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Mon, 14 Jun 2021 22:58:14 -0500 Subject: [PATCH 130/226] Fix AT format issue --- build-data/paper.at | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build-data/paper.at b/build-data/paper.at index 1afeccf82a..e1f52762aa 100644 --- a/build-data/paper.at +++ b/build-data/paper.at @@ -9,10 +9,10 @@ public net.minecraft.world.item.Item rarity # More Enchantment API -public net.minecraft.world.item.enchantment.Enchantment slots; +public net.minecraft.world.item.enchantment.Enchantment slots # Fix and optimise world force upgrading -public net.minecraft.util.worldupdate.WorldUpgrader REGEX; +public net.minecraft.util.worldupdate.WorldUpgrader REGEX # More Lidded Block API -public net.minecraft.world.level.block.entity.EnderChestBlockEntity openersCounter \ No newline at end of file +public net.minecraft.world.level.block.entity.EnderChestBlockEntity openersCounter From 2ac6b12fc870f6edaf6568b2012b853728e1667a Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 20:50:12 -0700 Subject: [PATCH 131/226] Update editorconfig --- .editorconfig | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 210d3ca851..aa4d12f5a8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,12 @@ -[*.java] +[*] charset=utf-8 end_of_line=lf insert_final_newline=true indent_style=space indent_size=4 + +[*.tiny] +indent_style=tab + +[*.bat] +end_of_line=crlf From 7271649af27ff745628637025113424b4f8120d6 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 20:50:26 -0700 Subject: [PATCH 132/226] patches --- .../0312-Add-PlayerKickEvent-causes.patch | 10 +- ...0313-Add-PufferFishStateChangeEvent.patch} | 0 .../0314-Add-BellRevealRaiderEvent.patch | 0 ...315-Add-ElderGuardianAppearanceEvent.patch | 0 .../0541-Import-fastutil-classes.patch | 1 + ...crease-structure-block-data-length-t.patch | 2 +- .../0753-Add-BellRevealRaiderEvent.patch | 26 --- .../0682-Add-PlayerKickEvent-causes.patch} | 204 +++++++++--------- ...erBucketEmptyEvent-result-itemstack.patch} | 31 +-- ...-to-fix-items-merging-through-walls.patch} | 11 +- .../0685-Add-BellRevealRaiderEvent.patch | 32 +++ .../0686-Fix-invulnerable-end-crystals.patch} | 62 ++---- ...87-Add-ElderGuardianAppearanceEvent.patch} | 6 +- ...inventory-on-cancelled-pickup-event.patch} | 18 +- ...0689-Fix-dangerous-end-portal-logic.patch} | 34 +-- 15 files changed, 195 insertions(+), 242 deletions(-) rename patches/{api-unmapped => api}/0312-Add-PlayerKickEvent-causes.patch (91%) rename patches/api/{0312-Add-PufferFishStateChangeEvent.patch => 0313-Add-PufferFishStateChangeEvent.patch} (100%) rename patches/{api-unmapped => api}/0314-Add-BellRevealRaiderEvent.patch (100%) rename patches/{api-unmapped => api}/0315-Add-ElderGuardianAppearanceEvent.patch (100%) rename patches/removed/1.17/{ => No longer needed}/0541-Import-fastutil-classes.patch (95%) rename patches/removed/1.17/{ => No longer needed}/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch (96%) delete mode 100644 patches/server-remapped/0753-Add-BellRevealRaiderEvent.patch rename patches/{server-remapped/0748-Add-PlayerKickEvent-causes.patch => server/0682-Add-PlayerKickEvent-causes.patch} (68%) rename patches/{server-remapped/0751-Fix-PlayerBucketEmptyEvent-result-itemstack.patch => server/0683-Fix-PlayerBucketEmptyEvent-result-itemstack.patch} (58%) rename patches/{server-remapped/0752-Add-option-to-fix-items-merging-through-walls.patch => server/0684-Add-option-to-fix-items-merging-through-walls.patch} (85%) create mode 100644 patches/server/0685-Add-BellRevealRaiderEvent.patch rename patches/{server-remapped/0754-Fix-invulnerable-end-crystals.patch => server/0686-Fix-invulnerable-end-crystals.patch} (56%) rename patches/{server-remapped/0755-Add-ElderGuardianAppearanceEvent.patch => server/0687-Add-ElderGuardianAppearanceEvent.patch} (83%) rename patches/{server-remapped/0756-Reset-villager-inventory-on-cancelled-pickup-event.patch => server/0688-Reset-villager-inventory-on-cancelled-pickup-event.patch} (77%) rename patches/{server-remapped/0757-Fix-dangerous-end-portal-logic.patch => server/0689-Fix-dangerous-end-portal-logic.patch} (66%) diff --git a/patches/api-unmapped/0312-Add-PlayerKickEvent-causes.patch b/patches/api/0312-Add-PlayerKickEvent-causes.patch similarity index 91% rename from patches/api-unmapped/0312-Add-PlayerKickEvent-causes.patch rename to patches/api/0312-Add-PlayerKickEvent-causes.patch index b3cfb136d3..d74f554747 100644 --- a/patches/api-unmapped/0312-Add-PlayerKickEvent-causes.patch +++ b/patches/api/0312-Add-PlayerKickEvent-causes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add PlayerKickEvent causes diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 34b51466ffb281b05f531b3f7deda245ae7fd96a..a4b236d75e77176a163094edd31f81725bbf4eca 100644 +index 38003de85a8098fc78fc947dd975990d478ee908..da83b4cbed0be6f693c7cbb1cc032356f12d7883 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -237,6 +237,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -240,6 +240,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * @param message kick message */ void kick(final @Nullable net.kyori.adventure.text.Component message); @@ -24,7 +24,7 @@ index 34b51466ffb281b05f531b3f7deda245ae7fd96a..a4b236d75e77176a163094edd31f8172 /** diff --git a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -index 5c0efe74237dbe6803ce023fde99682ff70d1a92..02914c0743852e9e4fd2c085fd4b735e74d8875b 100644 +index 5c0efe74237dbe6803ce023fde99682ff70d1a92..05ecfd8c133e72d198faeeded8c757c231c871cc 100644 --- a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java +++ b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java @@ -12,6 +12,7 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { @@ -61,7 +61,7 @@ index 5c0efe74237dbe6803ce023fde99682ff70d1a92..02914c0743852e9e4fd2c085fd4b735e } /** -@@ -132,4 +144,63 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { +@@ -132,4 +144,65 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { public static HandlerList getHandlerList() { return handlers; } @@ -114,6 +114,8 @@ index 5c0efe74237dbe6803ce023fde99682ff70d1a92..02914c0743852e9e4fd2c085fd4b735e + + DUPLICATE_LOGIN, + ++ RESOURCE_PACK_REJECTION, ++ + /** + * Spigot's restart command + */ diff --git a/patches/api/0312-Add-PufferFishStateChangeEvent.patch b/patches/api/0313-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from patches/api/0312-Add-PufferFishStateChangeEvent.patch rename to patches/api/0313-Add-PufferFishStateChangeEvent.patch diff --git a/patches/api-unmapped/0314-Add-BellRevealRaiderEvent.patch b/patches/api/0314-Add-BellRevealRaiderEvent.patch similarity index 100% rename from patches/api-unmapped/0314-Add-BellRevealRaiderEvent.patch rename to patches/api/0314-Add-BellRevealRaiderEvent.patch diff --git a/patches/api-unmapped/0315-Add-ElderGuardianAppearanceEvent.patch b/patches/api/0315-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from patches/api-unmapped/0315-Add-ElderGuardianAppearanceEvent.patch rename to patches/api/0315-Add-ElderGuardianAppearanceEvent.patch diff --git a/patches/removed/1.17/0541-Import-fastutil-classes.patch b/patches/removed/1.17/No longer needed/0541-Import-fastutil-classes.patch similarity index 95% rename from patches/removed/1.17/0541-Import-fastutil-classes.patch rename to patches/removed/1.17/No longer needed/0541-Import-fastutil-classes.patch index 0fd44a3e61..13fa459a56 100644 --- a/patches/removed/1.17/0541-Import-fastutil-classes.patch +++ b/patches/removed/1.17/No longer needed/0541-Import-fastutil-classes.patch @@ -3,6 +3,7 @@ From: Mariell Hoversholm Date: Wed, 12 Aug 2020 11:33:04 +0200 Subject: [PATCH] Import fastutil classes 1.17: YEET +we use real mappings now so a class called 'it' in nms is no longer a concern diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java index 95e166aa63f42c675df645a56e313bdffc2e8663..05f7d4a3835536f26f741d54a0884bd43fc82967 100644 diff --git a/patches/removed/1.17/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch b/patches/removed/1.17/No longer needed/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch similarity index 96% rename from patches/removed/1.17/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch rename to patches/removed/1.17/No longer needed/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch index ba83517560..58711e1c47 100644 --- a/patches/removed/1.17/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch +++ b/patches/removed/1.17/No longer needed/0739-Fix-MC-148809-Increase-structure-block-data-length-t.patch @@ -3,7 +3,7 @@ From: SamB440 Date: Fri, 21 May 2021 00:22:09 +0100 Subject: [PATCH] Fix MC-148809: Increase structure block data length to 128 -Fixed in 1.17 +Fixed in 1.17 - mojira issue marked as resolved diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetStructureBlockPacket.java index 4c797dd82bb1989861e350a7e628eb847b58bbd8..4792aafd8d992cd64d05f8bbef5cbf30988949ed 100644 diff --git a/patches/server-remapped/0753-Add-BellRevealRaiderEvent.patch b/patches/server-remapped/0753-Add-BellRevealRaiderEvent.patch deleted file mode 100644 index 78020871e6..0000000000 --- a/patches/server-remapped/0753-Add-BellRevealRaiderEvent.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Wed, 26 May 2021 17:09:07 -0400 -Subject: [PATCH] Add BellRevealRaiderEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java -index 3f9179a7678091875161a34d13b6ec0e78025c4c..03c2831a7c4f310936dad1ee72f402ed38f3c9e7 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java -@@ -6,6 +6,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Direction; - import net.minecraft.core.Position; - import net.minecraft.core.particles.ParticleTypes; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.tags.EntityTypeTags; -@@ -181,6 +182,7 @@ public class BellBlockEntity extends BlockEntity implements TickableBlockEntity - } - - private void glow(LivingEntity entity) { -+ if (!new io.papermc.paper.event.block.BellRevealRaiderEvent(level.getWorld().getBlockAt(MCUtil.toLocation(level, worldPosition)), entity.getBukkitEntity()).callEvent()) return; // Paper - BellRevealRaiderEvent - entity.addEffect(new MobEffectInstance(MobEffects.GLOWING, 60)); - } - } diff --git a/patches/server-remapped/0748-Add-PlayerKickEvent-causes.patch b/patches/server/0682-Add-PlayerKickEvent-causes.patch similarity index 68% rename from patches/server-remapped/0748-Add-PlayerKickEvent-causes.patch rename to patches/server/0682-Add-PlayerKickEvent-causes.patch index 82c7b23bb7..7959f099e4 100644 --- a/patches/server-remapped/0748-Add-PlayerKickEvent-causes.patch +++ b/patches/server/0682-Add-PlayerKickEvent-causes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add PlayerKickEvent causes diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 9d7cebd703bd0171ca3e95d2985c1a52fdb59712..9e3b8c7478d97bf65a875807a268d1c98389c1f8 100644 +index db2d6e7b2dc82c60d524dd2a018d28c2068552fa..c6747f49ae8ddc9fc1bad82ab480f85d0883da5d 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2041,7 +2041,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop targets, Component reason) { + for(ServerPlayer serverPlayer : targets) { +- serverPlayer.connection.disconnect(reason); ++ serverPlayer.connection.disconnect(reason, org.bukkit.event.player.PlayerKickEvent.Cause.KICK_COMMAND); // Paper - kick event cause + source.sendSuccess(new TranslatableComponent("commands.kick.success", serverPlayer.getDisplayName(), reason), true); } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560a9566399 100644 +index b369d400e34fc8b6d161d79c57bcd26d57147ff8..8e7a8e7b6d44255044a34ed374f106435cf1ba07 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -327,7 +327,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -321,7 +321,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser if (this.clientIsFloating && !this.player.isSleeping()) { if (++this.aboveGroundTickCount > 80) { ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); @@ -69,7 +69,7 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 return; } } else { -@@ -346,7 +346,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -340,7 +340,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) { if (++this.aboveGroundVehicleTickCount > 80) { ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); @@ -78,8 +78,8 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 return; } } else { -@@ -368,7 +368,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - if (this.isPendingPing()) { +@@ -362,7 +362,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + if (this.keepAlivePending) { if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info - this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0])); @@ -87,7 +87,7 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 } } else { if (elapsedTime >= 15000L) { // 15 seconds -@@ -398,7 +398,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -392,7 +392,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) (this.server.getPlayerIdleTimeout() * 1000 * 60)) { this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 @@ -96,7 +96,7 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 } } -@@ -423,14 +423,22 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -417,14 +417,22 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser public void disconnect(String s) { // Paper start @@ -122,28 +122,28 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 // Paper end // CraftBukkit start - fire PlayerKickEvent if (this.processedDisconnect) { -@@ -438,7 +446,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -432,7 +440,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure -- PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure -+ PlayerKickEvent event = new PlayerKickEvent(this.craftServer.getPlayer(this.player), reason, leaveMessage, cause); // Paper - Adventure & kick event reason +- PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), reason, leaveMessage); // Paper - Adventure ++ PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), reason, leaveMessage, cause); // Paper - Adventure & kick event reason - if (this.craftServer.getServer().isRunning()) { - this.craftServer.getPluginManager().callEvent(event); -@@ -516,7 +524,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + if (this.cserver.getServer().isRunning()) { + this.cserver.getPluginManager().callEvent(event); +@@ -504,7 +512,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser public void handleMoveVehicle(ServerboundMoveVehiclePacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); - if (containsInvalidValues(packet)) { + if (ServerGamePacketListenerImpl.containsInvalidValues(packet.getX(), packet.getY(), packet.getZ(), packet.getYRot(), packet.getXRot())) { - this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_vehicle_movement")); + this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_vehicle_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_VEHICLE_MOVEMENT); // Paper - kick event cause } else { Entity entity = this.player.getRootVehicle(); -@@ -750,13 +758,13 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -739,13 +747,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async // CraftBukkit start - if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable + if (this.chatSpamTickCount.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable - server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper + server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause return; @@ -156,16 +156,16 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 return; } // Paper end -@@ -904,7 +912,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -897,7 +905,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // Paper start - validate pick item position - if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.inventory.items.size())) { + if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.getInventory().items.size())) { ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); - this.disconnect("Invalid hotbar selection (Hacking?)"); + this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause return; } - this.player.inventory.pickSlot(packet.getSlot()); // Paper - Diff above if changed -@@ -1058,7 +1066,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { + this.player.getInventory().pickSlot(packet.getSlot()); // Paper - Diff above if changed +@@ -1051,7 +1059,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser ListTag pageList = testStack.getTag().getList("pages", 8); if (pageList.size() > 100) { ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with too many pages"); @@ -174,7 +174,7 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 return; } long byteTotal = 0; -@@ -1070,7 +1078,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1063,7 +1071,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; if (byteLength > 256 * 4) { ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!"); @@ -183,7 +183,7 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 return; } byteTotal += byteLength; -@@ -1093,14 +1101,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1086,14 +1094,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser if (byteTotal > byteAllowed) { ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); @@ -200,25 +200,34 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 return; } this.lastBookTick = MinecraftServer.currentTick; -@@ -1212,7 +1220,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1229,7 +1237,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser public void handleMovePlayer(ServerboundMovePlayerPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); - if (containsInvalidValues(packet)) { + if (ServerGamePacketListenerImpl.containsInvalidValues(packet.getX(0.0D), packet.getY(0.0D), packet.getZ(0.0D), packet.getYRot(0.0F), packet.getXRot(0.0F))) { - this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement")); + this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause } else { ServerLevel worldserver = this.player.getLevel(); -@@ -1611,7 +1619,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1641,7 +1649,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.dropCount++; if (this.dropCount >= 20) { - LOGGER.warn(this.player.getScoreboardName() + " dropped their items too quickly!"); + ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " dropped their items too quickly!"); - this.disconnect("You dropped your items too quickly (Hacking?)"); + this.disconnect("You dropped your items too quickly (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause return; } } -@@ -1924,7 +1932,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1839,7 +1847,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (packet.getAction() == ServerboundResourcePackPacket.Action.DECLINED && this.server.isResourcePackRequired()) { + ServerGamePacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack rejection", this.player.getName()); +- this.disconnect(new TranslatableComponent("multiplayer.requiredTexturePrompt.disconnect")); ++ this.disconnect(new TranslatableComponent("multiplayer.requiredTexturePrompt.disconnect"), org.bukkit.event.player.PlayerKickEvent.Cause.RESOURCE_PACK_REJECTION); // Paper - add cause + } + // Paper start + PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()]; +@@ -1944,7 +1952,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.player.resetLastActionTime(); } else { ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); @@ -227,25 +236,16 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 } } -@@ -1961,7 +1969,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - Waitable waitable = new Waitable() { - @Override - protected Object evaluate() { -- ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters")); -+ ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause - return null; - } - }; -@@ -1976,7 +1984,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - throw new RuntimeException(e); - } - } else { -- this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters")); -+ this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause - } - // CraftBukkit end - return; -@@ -2030,7 +2038,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1960,7 +1968,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + for (int i = 0; i < s.length(); ++i) { + if (!SharedConstants.isAllowedChatCharacter(s.charAt(i))) { +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - add cause + return; + } + } +@@ -2033,7 +2041,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser Waitable waitable = new Waitable() { @Override protected Object evaluate() { @@ -254,7 +254,7 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 return null; } }; -@@ -2045,7 +2053,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2048,7 +2056,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser throw new RuntimeException(e); } } else { @@ -263,43 +263,43 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 } // CraftBukkit end } -@@ -2318,7 +2326,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2321,7 +2329,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // Spigot Start - if ( entity == player && !player.isSpectator() ) + if ( entity == this.player && !this.player.isSpectator() ) { -- disconnect( "Cannot interact with self!" ); -+ disconnect( "Cannot interact with self!", org.bukkit.event.player.PlayerKickEvent.Cause.SELF_INTERACTION ); // Paper - kick event cause +- this.disconnect( "Cannot interact with self!" ); ++ this.disconnect( "Cannot interact with self!", org.bukkit.event.player.PlayerKickEvent.Cause.SELF_INTERACTION ); // Paper - add cause return; } // Spigot End -@@ -2395,7 +2403,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - // CraftBukkit end - } else if (packet.getAction() == ServerboundInteractPacket.Action.ATTACK) { - if (entity instanceof ItemEntity || entity instanceof ExperienceOrb || entity instanceof AbstractArrow || (entity == this.player && !player.isSpectator())) { // CraftBukkit -- this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked")); -+ this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_ENTITY_ATTACKED); // Paper - kick event cause - ServerGamePacketListenerImpl.LOGGER.warn("Player {} tried to attack an invalid entity", this.player.getName().getString()); - return; +@@ -2412,7 +2420,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } + // CraftBukkit end + } else { +- ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked")); ++ ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_ENTITY_ATTACKED); // Paper - add cause + ServerGamePacketListenerImpl.LOGGER.warn("Player {} tried to attack an invalid entity", ServerGamePacketListenerImpl.this.player.getName().getString()); + } } -@@ -2800,7 +2808,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2806,7 +2814,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // Paper start - if (!Bukkit.isPrimaryThread()) { - if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { + if (!org.bukkit.Bukkit.isPrimaryThread()) { + if (recipeSpamPackets.addAndGet(com.destroystokyo.paper.PaperConfig.autoRecipeIncrement) > com.destroystokyo.paper.PaperConfig.autoRecipeLimit) { - server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper + server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause return; } } -@@ -2999,7 +3007,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2999,7 +3007,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } else if (!this.isSingleplayerOwner()) { // Paper start - This needs to be handled on the main thread for plugins - server.scheduleOnMain(() -> { + server.submit(() -> { - this.disconnect(new TranslatableComponent("disconnect.timeout")); + this.disconnect(new TranslatableComponent("disconnect.timeout"), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause }); // Paper end } -@@ -3045,7 +3053,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -3045,7 +3053,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } } catch (Exception ex) { ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex); @@ -308,7 +308,7 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 } } else if (packet.identifier.equals(CUSTOM_UNREGISTER)) { try { -@@ -3055,7 +3063,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -3055,7 +3063,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } } catch (Exception ex) { ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t unregister custom payload", ex); @@ -317,8 +317,8 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 } } else { try { -@@ -3074,7 +3082,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - craftServer.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packet.identifier.toString(), data); +@@ -3073,7 +3081,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + this.cserver.getMessenger().dispatchIncomingMessage(this.player.getBukkitEntity(), packet.identifier.toString(), data); } catch (Exception ex) { ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); - this.disconnect("Invalid custom payload!"); @@ -327,20 +327,20 @@ index c454908f23a436f66f8e64fc346186f113b6eefb..3e257d2cf6bf5609247bd022ccc2f560 } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 6011b43ae8a858f88b8fcf6dc0bf147024a4742c..9e138bf9f9ee4efee462271d1a69a2126aa94946 100644 +index 34de9e2b0e52eb7a7e993678fd54ac1b883be4aa..bc3fe18dd32da2d381b9546aae675a475c073696 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -716,7 +716,7 @@ public abstract class PlayerList { +@@ -708,7 +708,7 @@ public abstract class PlayerList { while (iterator.hasNext()) { entityplayer = (ServerPlayer) iterator.next(); - save(entityplayer); // CraftBukkit - Force the player's inventory to be saved + this.save(entityplayer); // CraftBukkit - Force the player's inventory to be saved - entityplayer.connection.disconnect(new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0])); + entityplayer.connection.disconnect(new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause } // Instead of kicking then returning, we need to store the kick reason -@@ -1385,8 +1385,8 @@ public abstract class PlayerList { - public void shutdown(boolean isRestarting) { +@@ -1360,8 +1360,8 @@ public abstract class PlayerList { + // Paper end // CraftBukkit start - disconnect safely for (ServerPlayer player : this.players) { - if (isRestarting) player.connection.disconnect(org.spigotmc.SpigotConfig.restartMessage); else // Paper @@ -351,15 +351,15 @@ index 6011b43ae8a858f88b8fcf6dc0bf147024a4742c..9e138bf9f9ee4efee462271d1a69a212 // CraftBukkit end diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 3dbe94d9b9647f5cc1e27335b36042e50c652cea..97aec6370a8a24a13ae04443d03f250f8938b2e0 100644 +index d46c2e85c845c769391af98619b9c771f13f90f7..a210ce9438455e3bf15e189fb5aea8f23dc9aae0 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -495,16 +495,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -494,16 +494,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { org.spigotmc.AsyncCatcher.catchOp("player kick"); // Spigot - if (getHandle().connection == null) return; + if (this.getHandle().connection == null) return; -- getHandle().connection.disconnect(message == null ? "" : message); -+ getHandle().connection.disconnect(message == null ? "" : message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause +- this.getHandle().connection.disconnect(message == null ? "" : message); ++ this.getHandle().connection.disconnect(message == null ? "" : message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause } // Paper start @@ -377,9 +377,9 @@ index 3dbe94d9b9647f5cc1e27335b36042e50c652cea..97aec6370a8a24a13ae04443d03f250f + connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message, cause); } } - // Paper end + diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index 6498dc4c6630bfef1a52edf74d8574e5e4876720..ea1f088ac94616978af5e01a59c558cd2db4b619 100644 +index 92d97a5810a379b427a99b4c63fb9844d823a84f..160115bf8a153ff981ba308599d22c4c08026fb6 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 diff --git a/patches/server-remapped/0751-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/patches/server/0683-Fix-PlayerBucketEmptyEvent-result-itemstack.patch similarity index 58% rename from patches/server-remapped/0751-Fix-PlayerBucketEmptyEvent-result-itemstack.patch rename to patches/server/0683-Fix-PlayerBucketEmptyEvent-result-itemstack.patch index 85fe9b3b12..164f05c32a 100644 --- a/patches/server-remapped/0751-Fix-PlayerBucketEmptyEvent-result-itemstack.patch +++ b/patches/server/0683-Fix-PlayerBucketEmptyEvent-result-itemstack.patch @@ -6,32 +6,33 @@ Subject: [PATCH] Fix PlayerBucketEmptyEvent result itemstack Fixes SPIGOT-2560: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-2560 diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java -index d0e847e58483695d2af1c1410826bb25231cd6f6..08c00a084b2972420eae020e13480489b29aec64 100644 +index 7c3e94c6bf8337ef660473d8ed451606d56082a5..4fdb99240e6ebda946fd2e0a847654d92b7c56a1 100644 --- a/src/main/java/net/minecraft/world/item/BucketItem.java +++ b/src/main/java/net/minecraft/world/item/BucketItem.java -@@ -116,6 +116,13 @@ public class BucketItem extends Item { +@@ -41,6 +41,8 @@ import org.bukkit.event.player.PlayerBucketFillEvent; + + public class BucketItem extends Item implements DispensibleContainerItem { + ++ private static ItemStack itemLeftInHandAfterPlayerBucketEmptyEvent = null; // Paper ++ + public final Fluid content; + + public BucketItem(Fluid fluid, Item.Properties settings) { +@@ -121,6 +123,13 @@ public class BucketItem extends Item implements DispensibleContainerItem { } - protected ItemStack getEmptySuccessItem(ItemStack stack, Player player) { -+ // Paper + public static ItemStack getEmptySuccessItem(ItemStack stack, Player player) { ++ // Paper start + if (itemLeftInHandAfterPlayerBucketEmptyEvent != null) { + ItemStack itemInHand = itemLeftInHandAfterPlayerBucketEmptyEvent; + itemLeftInHandAfterPlayerBucketEmptyEvent = null; + return itemInHand; + } -+ // Paper - return !player.abilities.instabuild ? new ItemStack(Items.BUCKET) : stack; ++ // Paper end + return !player.getAbilities().instabuild ? new ItemStack(Items.BUCKET) : stack; } -@@ -126,6 +133,7 @@ public class BucketItem extends Item { - return a(player, world, pos, movingobjectpositionblock, null, null, null, null); - } - -+ private ItemStack itemLeftInHandAfterPlayerBucketEmptyEvent = null; // Paper - public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, InteractionHand enumhand) { - // Paper end - // CraftBukkit end -@@ -146,6 +154,9 @@ public class BucketItem extends Item { +@@ -153,6 +162,9 @@ public class BucketItem extends Item implements DispensibleContainerItem { ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 return false; } diff --git a/patches/server-remapped/0752-Add-option-to-fix-items-merging-through-walls.patch b/patches/server/0684-Add-option-to-fix-items-merging-through-walls.patch similarity index 85% rename from patches/server-remapped/0752-Add-option-to-fix-items-merging-through-walls.patch rename to patches/server/0684-Add-option-to-fix-items-merging-through-walls.patch index 3cd329efc6..3e34d24f12 100644 --- a/patches/server-remapped/0752-Add-option-to-fix-items-merging-through-walls.patch +++ b/patches/server/0684-Add-option-to-fix-items-merging-through-walls.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to fix items merging through walls diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9287dfcf29ce6f89a937f4e10b70be8faab9ab9e..74f2413773fbe30597314e02a5284172e0fc40b2 100644 +index b7b160ef6feded6b84faf9958599c761828fcf59..75a02252f398b3d16f8588693e71f779d7fa062a 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -821,4 +821,9 @@ public class PaperWorldConfig { +@@ -709,5 +709,10 @@ public class PaperWorldConfig { private void mapItemFrameCursorLimit() { mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); } @@ -18,11 +18,12 @@ index 9287dfcf29ce6f89a937f4e10b70be8faab9ab9e..74f2413773fbe30597314e02a5284172 + fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); + } } + diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 7476ae301fb4ee503944d39022cb25ccb19f1232..d937a74d2e822c8542286fb5bcdfcec7895d845c 100644 +index e0c13a112c95eed9867d4608e18dc797b0c9c9cf..158719d46c96bb733a00e08c8285f41a48406abf 100644 --- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -@@ -227,6 +227,14 @@ public class ItemEntity extends Entity { +@@ -241,6 +241,14 @@ public class ItemEntity extends Entity { ItemEntity entityitem = (ItemEntity) iterator.next(); if (entityitem.isMergable()) { @@ -35,5 +36,5 @@ index 7476ae301fb4ee503944d39022cb25ccb19f1232..d937a74d2e822c8542286fb5bcdfcec7 + } + // Paper End this.tryToMerge(entityitem); - if (this.removed) { + if (this.isRemoved()) { break; diff --git a/patches/server/0685-Add-BellRevealRaiderEvent.patch b/patches/server/0685-Add-BellRevealRaiderEvent.patch new file mode 100644 index 0000000000..c434ce8f0f --- /dev/null +++ b/patches/server/0685-Add-BellRevealRaiderEvent.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Wed, 26 May 2021 17:09:07 -0400 +Subject: [PATCH] Add BellRevealRaiderEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +index a71bf0802d04217dd11086901b7148957d32ca89..b4a5da7e2baecc856c75283cc776398042d17108 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -138,7 +138,7 @@ public class BellBlockEntity extends BlockEntity { + private static void makeRaidersGlow(Level world, BlockPos pos, List hearingEntities) { + hearingEntities.stream().filter((livingEntity) -> { + return isRaiderWithinRange(pos, livingEntity); +- }).forEach(BellBlockEntity::glow); ++ }).forEach(entity -> glow(entity, pos)); // Paper - pass BlockPos + } + + private static void showBellParticles(Level world, BlockPos pos, List hearingEntities) { +@@ -170,7 +170,11 @@ public class BellBlockEntity extends BlockEntity { + return entity.isAlive() && !entity.isRemoved() && pos.closerThan(entity.position(), 48.0D) && entity.getType().is(EntityTypeTags.RAIDERS); + } + +- private static void glow(LivingEntity entity) { ++ // Paper start ++ private static void glow(LivingEntity entity) { glow(entity, null); } ++ private static void glow(LivingEntity entity, BlockPos pos) { ++ if (pos != null && !new io.papermc.paper.event.block.BellRevealRaiderEvent(entity.level.getWorld().getBlockAt(net.minecraft.server.MCUtil.toLocation(entity.level, pos)), entity.getBukkitEntity()).callEvent()) return; ++ // Paper end + entity.addEffect(new MobEffectInstance(MobEffects.GLOWING, 60)); + } + diff --git a/patches/server-remapped/0754-Fix-invulnerable-end-crystals.patch b/patches/server/0686-Fix-invulnerable-end-crystals.patch similarity index 56% rename from patches/server-remapped/0754-Fix-invulnerable-end-crystals.patch rename to patches/server/0686-Fix-invulnerable-end-crystals.patch index d830a00fa4..39d58c730d 100644 --- a/patches/server-remapped/0754-Fix-invulnerable-end-crystals.patch +++ b/patches/server/0686-Fix-invulnerable-end-crystals.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix invulnerable end crystals MC-108513 diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 74f2413773fbe30597314e02a5284172e0fc40b2..dc5ebbb44238cb5928f385d2962c9057388575f8 100644 +index 75a02252f398b3d16f8588693e71f779d7fa062a..f2981aa82c26d7bdac08f45818813025b240b77e 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -826,4 +826,9 @@ public class PaperWorldConfig { +@@ -714,5 +714,10 @@ public class PaperWorldConfig { private void fixItemsMergingThroughWalls() { fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); } @@ -19,11 +19,12 @@ index 74f2413773fbe30597314e02a5284172e0fc40b2..dc5ebbb44238cb5928f385d2962c9057 + fixInvulnerableEndCrystalExploit = getBoolean("unsupported-settings.fix-invulnerable-end-crystal-exploit", fixInvulnerableEndCrystalExploit); + } } + diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java -index 6292d04464950ac52fcd6d69345db5125d3127eb..8583209750e4bb70e86d7243a47c525f1726ee42 100644 +index 2c4c1fc2a2afe88864b72d86708a3ddb6a1f50a0..5b9ba62ce37aabb268d76c23f5cb41a4a5c61a2f 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java -@@ -29,6 +29,7 @@ public class EndCrystal extends Entity { +@@ -31,6 +31,7 @@ public class EndCrystal extends Entity { private static final EntityDataAccessor> DATA_BEAM_TARGET = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.OPTIONAL_BLOCK_POS); private static final EntityDataAccessor DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN); public int time; @@ -31,7 +32,7 @@ index 6292d04464950ac52fcd6d69345db5125d3127eb..8583209750e4bb70e86d7243a47c525f public EndCrystal(EntityType type, Level world) { super(type, world); -@@ -65,6 +66,17 @@ public class EndCrystal extends Entity { +@@ -67,8 +68,20 @@ public class EndCrystal extends Entity { } // CraftBukkit end } @@ -48,58 +49,27 @@ index 6292d04464950ac52fcd6d69345db5125d3127eb..8583209750e4bb70e86d7243a47c525f + // Paper end } - } -@@ -76,6 +88,7 @@ public class EndCrystal extends Entity { - } - - tag.putBoolean("ShowBottom", this.showsBottom()); + if (this.generatedByDragonFight) tag.putBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals } @Override -@@ -87,6 +100,7 @@ public class EndCrystal extends Entity { - if (tag.contains("ShowBottom", 1)) { - this.setShowBottom(tag.getBoolean("ShowBottom")); +@@ -89,6 +102,7 @@ public class EndCrystal extends Entity { + if (nbt.contains("ShowBottom", 1)) { + this.setShowBottom(nbt.getBoolean("ShowBottom")); } + if (tag.contains("Paper.GeneratedByDragonFight", 1)) this.generatedByDragonFight = tag.getBoolean("Paper.GeneratedByDragonFight"); // Paper - Fix invulnerable end crystals } diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java -index b99576b524a65cc1a0de88c49324d929503d655f..d51d2fb6d24bfee63b04f32f2cb157fec9d8ee6c 100644 +index 1e53d4bef86349eaa1356444a80ae92d4311ccce..c03bf5bdb67b00c75f9fcfead882c4d944282244 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java +++ b/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java -@@ -42,11 +42,11 @@ public class SpikeFeature extends Feature { - return (List) SpikeFeature.SPIKE_CACHE.getUnchecked(i); - } - -- public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, SpikeConfiguration config) { -- List list = config.getSpikes(); -+ public boolean generate(WorldGenLevel generatoraccessseed, ChunkGenerator chunkgenerator, Random random, BlockPos blockposition, SpikeConfiguration worldgenfeatureendspikeconfiguration) { // Paper - decompile fix -+ List list = worldgenfeatureendspikeconfiguration.getSpikes(); - - if (list.isEmpty()) { -- list = getSpikesForLevel(world); -+ list = getSpikesForLevel(generatoraccessseed); - } - - Iterator iterator = list.iterator(); -@@ -54,8 +54,8 @@ public class SpikeFeature extends Feature { - while (iterator.hasNext()) { - SpikeFeature.EndSpike worldgenender_spike = (SpikeFeature.EndSpike) iterator.next(); - -- if (worldgenender_spike.isCenterWithinChunk(pos)) { -- this.placeSpike(world, random, config, worldgenender_spike); -+ if (worldgenender_spike.isCenterWithinChunk(blockposition)) { -+ this.placeSpike(generatoraccessseed, random, worldgenfeatureendspikeconfiguration, worldgenender_spike); - } - } - -@@ -106,6 +106,7 @@ public class SpikeFeature extends Feature { - entityendercrystal.setBeamTarget(config.getCrystalBeamTarget()); - entityendercrystal.setInvulnerable(config.isCrystalInvulnerable()); - entityendercrystal.moveTo((double) spike.getCenterX() + 0.5D, (double) (spike.getHeight() + 1), (double) spike.getCenterZ() + 0.5D, random.nextFloat() * 360.0F, 0.0F); -+ entityendercrystal.generatedByDragonFight = true; - world.addFreshEntity(entityendercrystal); +@@ -99,6 +99,7 @@ public class SpikeFeature extends Feature { + endCrystal.setBeamTarget(config.getCrystalBeamTarget()); + endCrystal.setInvulnerable(config.isCrystalInvulnerable()); + endCrystal.moveTo((double)spike.getCenterX() + 0.5D, (double)(spike.getHeight() + 1), (double)spike.getCenterZ() + 0.5D, random.nextFloat() * 360.0F, 0.0F); ++ endCrystal.generatedByDragonFight = true; // Paper + world.addFreshEntity(endCrystal); this.setBlock(world, new BlockPos(spike.getCenterX(), spike.getHeight(), spike.getCenterZ()), Blocks.BEDROCK.defaultBlockState()); } diff --git a/patches/server-remapped/0755-Add-ElderGuardianAppearanceEvent.patch b/patches/server/0687-Add-ElderGuardianAppearanceEvent.patch similarity index 83% rename from patches/server-remapped/0755-Add-ElderGuardianAppearanceEvent.patch rename to patches/server/0687-Add-ElderGuardianAppearanceEvent.patch index 2e0af7d211..6d3483fe35 100644 --- a/patches/server-remapped/0755-Add-ElderGuardianAppearanceEvent.patch +++ b/patches/server/0687-Add-ElderGuardianAppearanceEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add ElderGuardianAppearanceEvent diff --git a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java -index b6a842f9a24634ff84f2f4f94c0f2838f10cddb0..0cf6a06f8bddac0a2a1a00f3a4b266116f7ae594 100644 +index f4bfbce1fed066faebb44ea0880de5a8c7f902cd..ee2febe92309f277f1607c0ea024d6cd291490bc 100644 --- a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +++ b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java @@ -77,10 +77,12 @@ public class ElderGuardian extends Guardian { @@ -15,9 +15,9 @@ index b6a842f9a24634ff84f2f4f94c0f2838f10cddb0..0cf6a06f8bddac0a2a1a00f3a4b26611 + if (new io.papermc.paper.event.entity.ElderGuardianAppearanceEvent(getBukkitEntity(), entityplayer.getBukkitEntity()).callEvent()) { // Paper - Add Guardian Appearance Event if (!entityplayer.hasEffect(mobeffectlist) || entityplayer.getEffect(mobeffectlist).getAmplifier() < 2 || entityplayer.getEffect(mobeffectlist).getDuration() < 1200) { entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)); - entityplayer.addEffect(new MobEffectInstance(mobeffectlist, 6000, 2), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + entityplayer.addEffect(new MobEffectInstance(mobeffectlist, 6000, 2), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit } -+ } // Paper - Add Guardian Appearance Event ++ } // Paper - Add Guardian Appearance Event } } diff --git a/patches/server-remapped/0756-Reset-villager-inventory-on-cancelled-pickup-event.patch b/patches/server/0688-Reset-villager-inventory-on-cancelled-pickup-event.patch similarity index 77% rename from patches/server-remapped/0756-Reset-villager-inventory-on-cancelled-pickup-event.patch rename to patches/server/0688-Reset-villager-inventory-on-cancelled-pickup-event.patch index a6ef1d69fa..502eba8446 100644 --- a/patches/server-remapped/0756-Reset-villager-inventory-on-cancelled-pickup-event.patch +++ b/patches/server/0688-Reset-villager-inventory-on-cancelled-pickup-event.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Reset villager inventory on cancelled pickup event diff --git a/src/main/java/net/minecraft/world/SimpleContainer.java b/src/main/java/net/minecraft/world/SimpleContainer.java -index d6bb1d540e6dcbbad5e5bdf54803c495a4f3e771..3e639f5af83bea6760669696425dffd2d741cc16 100644 +index 502e29644504aabe3834351d3b479e21bd8f4be7..4e47ea7359ae56efeb2b74161dc9e7387589415b 100644 --- a/src/main/java/net/minecraft/world/SimpleContainer.java +++ b/src/main/java/net/minecraft/world/SimpleContainer.java @@ -34,6 +34,16 @@ public class SimpleContainer implements Container, StackedContentsCompatible { @@ -23,21 +23,13 @@ index d6bb1d540e6dcbbad5e5bdf54803c495a4f3e771..3e639f5af83bea6760669696425dffd2 + // Paper end + public void onOpen(CraftHumanEntity who) { - transaction.add(who); + this.transaction.add(who); } -@@ -148,6 +158,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible { - return itemstack; - } - -+ public ItemStack addItem(ItemStack itemstack) { return addItem(itemstack); } // Paper - OBFHELPER - public ItemStack addItem(ItemStack stack) { - ItemStack itemstack1 = stack.copy(); - diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 7817071b1964b962c8f4017d5bb39d74ca0ca3e4..1fbb7a2db5c362a5fc9e3f81382f729c962e377b 100644 +index ee23149411a49f08d2eb4808ef78cb5a50785977..4591054d5f106f2d630fc7bd3304a8ff7f426007 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -844,15 +844,19 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -888,15 +888,19 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } // CraftBukkit start @@ -59,4 +51,4 @@ index 7817071b1964b962c8f4017d5bb39d74ca0ca3e4..1fbb7a2db5c362a5fc9e3f81382f729c + // ItemStack itemstack1 = inventorysubcontainer.a(itemstack); // Paper - moved up if (itemstack1.isEmpty()) { - item.remove(); + item.discard(); diff --git a/patches/server-remapped/0757-Fix-dangerous-end-portal-logic.patch b/patches/server/0689-Fix-dangerous-end-portal-logic.patch similarity index 66% rename from patches/server-remapped/0757-Fix-dangerous-end-portal-logic.patch rename to patches/server/0689-Fix-dangerous-end-portal-logic.patch index a1fbfe0408..3eea2269ff 100644 --- a/patches/server-remapped/0757-Fix-dangerous-end-portal-logic.patch +++ b/patches/server/0689-Fix-dangerous-end-portal-logic.patch @@ -10,23 +10,11 @@ and will result in all kinds of dupes. Move the tick logic into the post tick, where portaling was designed to happen in the first place. -diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 779b926921fd435620cbbc69ed6f9931a422b652..25711ab723386db0f448c54e18ef069bfcd0dd99 100644 ---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java -+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1020,6 +1020,7 @@ public class ServerPlayer extends Player implements ContainerListener { - return b(destination, TeleportCause.UNKNOWN); - } - -+ @Nullable public final Entity changeDimension(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { return this.b(worldserver, cause); } // Paper - OBFHELPER - @Nullable - public Entity b(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { - // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d055b362459e5b4658aa220e16118ee6174c0de4..2462a78d976937cf4737f1ce0bfde2b2b7d5b1f7 100644 +index 5d4bee5470795bd9f362fff5ae653794223fa182..3e665504ff2138f8bc40cfac74b5af722d91f6e9 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -312,6 +312,37 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -341,6 +341,37 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } // Paper end - optimise entity tracking @@ -63,8 +51,8 @@ index d055b362459e5b4658aa220e16118ee6174c0de4..2462a78d976937cf4737f1ce0bfde2b2 + public Entity(EntityType type, Level world) { this.id = Entity.ENTITY_COUNTER.incrementAndGet(); - this.passengers = Lists.newArrayList(); -@@ -2297,6 +2328,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + this.passengers = ImmutableList.of(); +@@ -2487,6 +2518,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } this.processPortalCooldown(); @@ -73,18 +61,10 @@ index d055b362459e5b4658aa220e16118ee6174c0de4..2462a78d976937cf4737f1ce0bfde2b2 } diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -index 2231680140d0e3c4c10b6722fd13fe0ee55ce294..52884b87b25bef8abfa824f40d02efe3f947f330 100644 +index 739c9c3a49fd3893ac39962a02a5e3620dc4fe06..62c2f947a77570228dfdf4dae16c64eb97ee2f40 100644 --- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -@@ -3,7 +3,6 @@ package net.minecraft.world.level.block; - import net.minecraft.core.BlockPos; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.level.ServerLevel; --import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.BlockGetter; - import net.minecraft.world.level.Level; -@@ -50,16 +49,10 @@ public class EndPortalBlock extends BaseEntityBlock { +@@ -53,16 +53,10 @@ public class EndPortalBlock extends BaseEntityBlock { // return; // CraftBukkit - always fire event in case plugins wish to change it } @@ -93,7 +73,7 @@ index 2231680140d0e3c4c10b6722fd13fe0ee55ce294..52884b87b25bef8abfa824f40d02efe3 - world.getCraftServer().getPluginManager().callEvent(event); - - if (entity instanceof ServerPlayer) { -- ((ServerPlayer) entity).b(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); +- ((ServerPlayer) entity).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); - return; - } - // CraftBukkit end From 7929fdabaff685068324507548df8487608bc202 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 20:50:34 -0700 Subject: [PATCH 133/226] update mappings files --- build-data/mappings-patch.tiny | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build-data/mappings-patch.tiny b/build-data/mappings-patch.tiny index 42978d9d06..08728ac9e1 100644 --- a/build-data/mappings-patch.tiny +++ b/build-data/mappings-patch.tiny @@ -84,6 +84,6 @@ c net/minecraft/server/players/UserCache net/minecraft/server/players/GameProfil m (Ljava/lang/String;)Lcom/mojang/authlib/GameProfile; getProfile get p 0 name -# change dimension in ServerPlayer TODO (not sure what's wrong here) -#c net/minecraft/server/level/EntityPlayer net/minecraft/server/level/ServerPlayer -# m (Lnet/minecraft/server/level/ServerLevel;Lorg/bukkit/event/player/PlayerTeleportEvent$TeleportCause)Lnet/minecraft/world/entity/Entity; b changeDimension +# change dimension in ServerPlayer +c net/minecraft/server/level/EntityPlayer net/minecraft/server/level/ServerPlayer + m (Lnet/minecraft/server/level/WorldServer;Lorg/bukkit/event/player/PlayerTeleportEvent$TeleportCause;)Lnet/minecraft/world/entity/Entity; b changeDimension From f6636fca9e1179d7c28e8a3d8354986a13113884 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 21:01:27 -0700 Subject: [PATCH 134/226] Updated Upstream (Bukkit/CraftBukkit) 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: ebb0e28d #631: Add Villager#shakeHead 751469c6 #629: Add LivingEntity#isClimbing CraftBukkit Changes: 622cf611 SPIGOT-6555: Cannot access shield BlockStateMeta 8b2e78ec SPIGOT-6542: Fix counting players with fauxSleeping = true f66c437a SPIGOT-6561: Add events for dripleaf tilting 6ed40004 SPIGOT-6560: Crash when falling stalactite hits player 72a2901b SPIGOT-6557: PlayerEditBookEvent#setNewBookMeta does not update meta a07e783a #865: Implement Villager#shakeHead 3252ff18 #863: Add LivingEntity#isClimbing 77058c79 SPIGOT-6554: Worlds created with the bukkit ChunkGenerator cannot save --- ...methods-for-working-with-arrows-stuck-in-living-.patch | 4 ++-- .../0108-Make-shield-blocking-delay-configurable.patch | 4 ++-- .../api/0115-LivingEntity-Hand-Raised-Item-Use-API.patch | 4 ++-- patches/api/0189-Entity-Jump-API.patch | 4 ++-- patches/api/0202-Add-villager-reputation-API.patch | 4 ++-- ...0219-Add-playPickupItemAnimation-to-LivingEntity.patch | 4 ++-- patches/api/0237-Add-LivingEntity-clearActiveItem.patch | 4 ++-- patches/api/0243-Expose-LivingEntity-hurt-direction.patch | 4 ++-- ...methods-for-working-with-arrows-stuck-in-living-.patch | 4 ++-- .../0210-Make-shield-blocking-delay-configurable.patch | 4 ++-- .../0215-LivingEntity-Hand-Raised-Item-Use-API.patch | 4 ++-- ...-player-spectator-target-events-and-improve-impl.patch | 8 ++++---- patches/server/0373-Entity-Jump-API.patch | 4 ++-- patches/server/0428-Add-villager-reputation-API.patch | 6 +++--- ...0496-Add-playPickupItemAnimation-to-LivingEntity.patch | 4 ++-- .../server/0546-Add-LivingEntity-clearActiveItem.patch | 4 ++-- .../server/0559-Expose-LivingEntity-hurt-direction.patch | 4 ++-- .../0609-living-entity-allow-attribute-registration.patch | 4 ++-- .../0634-Don-t-ignore-result-of-PlayerEditBookEvent.patch | 6 +++--- patches/server/0670-More-Enchantment-API.patch | 4 ++-- work/Bukkit | 2 +- work/CraftBukkit | 2 +- 22 files changed, 46 insertions(+), 46 deletions(-) diff --git a/patches/api/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/api/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch index 515b56ff03..c2662ea313 100644 --- a/patches/api/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ b/patches/api/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add methods for working with arrows stuck in living entities diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 24c858182f25496cc7254f7cf9e996b3bea1f9ec..45e9f585c3e522ecf94a6bc42cdc190e1a191a5c 100644 +index 5077ec367a5cba88957c6115be27742974f7deec..b41133f23d25f90fc0993499056c4eeaf003a701 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -605,4 +605,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource +@@ -612,4 +612,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource * @return Whether the entity is invisible */ public boolean isInvisible(); diff --git a/patches/api/0108-Make-shield-blocking-delay-configurable.patch b/patches/api/0108-Make-shield-blocking-delay-configurable.patch index cec33b7a78..7b6e95c4e8 100644 --- a/patches/api/0108-Make-shield-blocking-delay-configurable.patch +++ b/patches/api/0108-Make-shield-blocking-delay-configurable.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make shield blocking delay configurable diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 33fffda7c8b05cde3c95623937e7eb6c8b628ec6..879dec59f202ee95043bd7317a672cd59ab3bbbe 100644 +index bfc90a3569abc717f37c064e3068c55ef323edab..588ad09a764236cf858a4e6689cf4ee5246e6f08 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -628,5 +628,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource +@@ -635,5 +635,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource * @param arrows Number of arrows to stick in this entity */ void setArrowsStuck(int arrows); diff --git a/patches/api/0115-LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/api/0115-LivingEntity-Hand-Raised-Item-Use-API.patch index 62fef67f7a..85f859eb81 100644 --- a/patches/api/0115-LivingEntity-Hand-Raised-Item-Use-API.patch +++ b/patches/api/0115-LivingEntity-Hand-Raised-Item-Use-API.patch @@ -6,7 +6,7 @@ Subject: [PATCH] LivingEntity Hand Raised/Item Use API How long an entity has raised hands to charge an attack or use an item diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 879dec59f202ee95043bd7317a672cd59ab3bbbe..4f62a49e7b0538f0ce9cecd2c1b645f40ce17b3d 100644 +index 588ad09a764236cf858a4e6689cf4ee5246e6f08..6d8d96976bcef4e176453fede81a529478f11234 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -12,6 +12,7 @@ import org.bukkit.attribute.Attributable; @@ -17,7 +17,7 @@ index 879dec59f202ee95043bd7317a672cd59ab3bbbe..4f62a49e7b0538f0ce9cecd2c1b645f4 import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.projectiles.ProjectileSource; -@@ -642,5 +643,42 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource +@@ -649,5 +650,42 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource * @param delay Delay in ticks */ void setShieldBlockingDelay(int delay); diff --git a/patches/api/0189-Entity-Jump-API.patch b/patches/api/0189-Entity-Jump-API.patch index dd4991158c..6e14c963f0 100644 --- a/patches/api/0189-Entity-Jump-API.patch +++ b/patches/api/0189-Entity-Jump-API.patch @@ -57,10 +57,10 @@ index 0000000000000000000000000000000000000000..f0067c2e953d18e1a33536980071ba3f + } +} diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index ac6921093457cee6d01fd27690c8bb6034b4af53..a46379b3a777a9071b0b13357bbd6af40dbfb569 100644 +index 93d20f67bf856d80226470ae2442d199d3e2f45b..5ab8db52160049e36464df4e20e374b8849ef29c 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -795,5 +795,25 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource +@@ -802,5 +802,25 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource */ @NotNull org.bukkit.inventory.EquipmentSlot getHandRaised(); diff --git a/patches/api/0202-Add-villager-reputation-API.patch b/patches/api/0202-Add-villager-reputation-API.patch index cef4ea6027..44b6a6f422 100644 --- a/patches/api/0202-Add-villager-reputation-API.patch +++ b/patches/api/0202-Add-villager-reputation-API.patch @@ -107,7 +107,7 @@ index 0000000000000000000000000000000000000000..5600fcdc9795a9f49091db48d73bbd49 + TRADING, +} diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java -index d1579153092c1b80350155110f1b9926b1a1ef57..c8777a476e38ef5e72b6709761990a339eb43d2b 100644 +index ef8a81c4857bd06be19264580bf3a7e087118f5c..511b96841f7342d0a6b38d7cff56252ea8ef9bfe 100644 --- a/src/main/java/org/bukkit/entity/Villager.java +++ b/src/main/java/org/bukkit/entity/Villager.java @@ -1,10 +1,13 @@ @@ -124,7 +124,7 @@ index d1579153092c1b80350155110f1b9926b1a1ef57..c8777a476e38ef5e72b6709761990a33 /** * Represents a villager NPC -@@ -224,4 +227,50 @@ public interface Villager extends AbstractVillager { +@@ -229,4 +232,50 @@ public interface Villager extends AbstractVillager { return key; } } diff --git a/patches/api/0219-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/api/0219-Add-playPickupItemAnimation-to-LivingEntity.patch index 561ec4779e..1416b1373a 100644 --- a/patches/api/0219-Add-playPickupItemAnimation-to-LivingEntity.patch +++ b/patches/api/0219-Add-playPickupItemAnimation-to-LivingEntity.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add playPickupItemAnimation to LivingEntity diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index a46379b3a777a9071b0b13357bbd6af40dbfb569..c4fe44dce3bcb3502b26af7c76ec6b36c2a2bebe 100644 +index 5ab8db52160049e36464df4e20e374b8849ef29c..1b6c2b2cfb910e7651e7f18ea407e31db685af8a 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -815,5 +815,28 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource +@@ -822,5 +822,28 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource * @param jumping entity jump state */ void setJumping(boolean jumping); diff --git a/patches/api/0237-Add-LivingEntity-clearActiveItem.patch b/patches/api/0237-Add-LivingEntity-clearActiveItem.patch index 6f423cc936..2855c9e780 100644 --- a/patches/api/0237-Add-LivingEntity-clearActiveItem.patch +++ b/patches/api/0237-Add-LivingEntity-clearActiveItem.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add LivingEntity#clearActiveItem diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index c4fe44dce3bcb3502b26af7c76ec6b36c2a2bebe..b96b5f4f2fc754298e2223b2f449a0755469278c 100644 +index 1b6c2b2cfb910e7651e7f18ea407e31db685af8a..751a7345b650e96bbfd3ca9d22c9623bd5444f67 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -766,6 +766,13 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource +@@ -773,6 +773,13 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource @Nullable ItemStack getActiveItem(); diff --git a/patches/api/0243-Expose-LivingEntity-hurt-direction.patch b/patches/api/0243-Expose-LivingEntity-hurt-direction.patch index 95b46eabc4..a6f7ce6054 100644 --- a/patches/api/0243-Expose-LivingEntity-hurt-direction.patch +++ b/patches/api/0243-Expose-LivingEntity-hurt-direction.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose LivingEntity hurt direction diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index b96b5f4f2fc754298e2223b2f449a0755469278c..b6de41e3e718fa5d1b82c6f68b153e60a81265e7 100644 +index 751a7345b650e96bbfd3ca9d22c9623bd5444f67..330eab77547ae059f716418f71ad1d3391a57a9b 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -845,5 +845,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource +@@ -852,5 +852,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource * @param quantity quantity of item */ void playPickupItemAnimation(@NotNull Item item, int quantity); diff --git a/patches/server/0056-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/server/0056-Add-methods-for-working-with-arrows-stuck-in-living-.patch index 2c5f3c5b06..eca15ea8fb 100644 --- a/patches/server/0056-Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ b/patches/server/0056-Add-methods-for-working-with-arrows-stuck-in-living-.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add methods for working with arrows stuck in living entities diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index b2a91fdff5960975787d4cd8f340f631275290fe..ea94dc9a3b8bd3da5f8ccbeb216384723db668aa 100644 +index 97dc4aa5dc3cb5cb21e9a2e316a3f729d6896b85..9e98e854b6b3f8dac3990abaa1c9f60fd1ff3836 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -685,4 +685,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -690,4 +690,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { this.getHandle().persistentInvisibility = invisible; this.getHandle().setSharedFlag(5, invisible); } diff --git a/patches/server/0210-Make-shield-blocking-delay-configurable.patch b/patches/server/0210-Make-shield-blocking-delay-configurable.patch index 44cc55e1d5..4762d6fb7e 100644 --- a/patches/server/0210-Make-shield-blocking-delay-configurable.patch +++ b/patches/server/0210-Make-shield-blocking-delay-configurable.patch @@ -49,10 +49,10 @@ index 28de49c8b5771491b168bba26e6033669c48e3c9..a3af689df12852ac47bd658f28c9f5b9 return this.isShiftKeyDown(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 4e9565def5a28a7391f8f541d066c2981d0bbc92..dea64f96139fbf4e1ff860b75f2005169a55c395 100644 +index 7beb84da34e58b18cd83a53eab2bcf703e8bf35e..d9f06a7ff7c6b4c60ddbc5d7131916fabd0fc4d2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -707,5 +707,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -712,5 +712,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { public void setArrowsStuck(int arrows) { getHandle().setArrowCount(arrows); } diff --git a/patches/server/0215-LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/server/0215-LivingEntity-Hand-Raised-Item-Use-API.patch index 0195a35046..bbfe9bd0fb 100644 --- a/patches/server/0215-LivingEntity-Hand-Raised-Item-Use-API.patch +++ b/patches/server/0215-LivingEntity-Hand-Raised-Item-Use-API.patch @@ -6,10 +6,10 @@ Subject: [PATCH] LivingEntity Hand Raised/Item Use API How long an entity has raised hands to charge an attack or use an item diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index dea64f96139fbf4e1ff860b75f2005169a55c395..5194da5a141718390a317d75b31205f951cec7a2 100644 +index d9f06a7ff7c6b4c60ddbc5d7131916fabd0fc4d2..0aec2e79d053b6cb845ffea393ad431b3d254b83 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -717,5 +717,30 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -722,5 +722,30 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { public void setShieldBlockingDelay(int delay) { getHandle().setShieldBlockingDelay(delay); } diff --git a/patches/server/0278-Call-player-spectator-target-events-and-improve-impl.patch b/patches/server/0278-Call-player-spectator-target-events-and-improve-impl.patch index 3775abd05d..537e2dbe3c 100644 --- a/patches/server/0278-Call-player-spectator-target-events-and-improve-impl.patch +++ b/patches/server/0278-Call-player-spectator-target-events-and-improve-impl.patch @@ -19,7 +19,7 @@ spectate the target entity. Co-authored-by: Spottedleaf diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index bea1461ee3bd65f02bf6add6ed967555092fd675..b2324b53b3cec3e577a8ec8c45b113c232d220a6 100644 +index 76be554b8266f1cb2b2eebb4db9777bda727f421..e6b64def52915114edb7a5e53fdc8816afd809a9 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1822,14 +1822,58 @@ public class ServerPlayer extends Player { @@ -86,15 +86,15 @@ index bea1461ee3bd65f02bf6add6ed967555092fd675..b2324b53b3cec3e577a8ec8c45b113c2 @Override diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index a29b8c83be940e4b3db06d881b59b03120e931ab..06922b26ca1f2e31f7c8a527f1a8fdda4a8554c0 100644 +index 2917632c5e974dbfb7d78c497ebd49e742b8ef3c..deb6352604b7cbda7de9df0d654410399f4ce159 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1068,7 +1068,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } } -- private void a(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack old) { // CraftBukkit -+ public void a(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack old) { // CraftBukkit // Paper - make public +- private void a(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack handItem) { // CraftBukkit ++ public void a(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack handItem) { // CraftBukkit // Paper - make public ListTag nbttaglist = new ListTag(); if (this.player.isTextFilteringEnabled()) { diff --git a/patches/server/0373-Entity-Jump-API.patch b/patches/server/0373-Entity-Jump-API.patch index 9a22507440..7bce87d91f 100644 --- a/patches/server/0373-Entity-Jump-API.patch +++ b/patches/server/0373-Entity-Jump-API.patch @@ -34,10 +34,10 @@ index 2d59eab846db2c0a624cf6d06a570b2313aa6b13..851ee58e52c6003d6ae7b58c9b6b9a9a } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 5477f288db57d63051f4579b8cd3c19e3af430ee..76e9977f7b2f7fb50631fc56f3318d59d04b1398 100644 +index e2e76c5de41666ef3a7132e376a3e4257bb13109..d2e1dbc33d25cd1132b74d50dd9dd746098a4ecc 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -792,5 +792,19 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -797,5 +797,19 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { public org.bukkit.inventory.EquipmentSlot getHandRaised() { return getHandle().getUsedItemHand() == net.minecraft.world.InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; } diff --git a/patches/server/0428-Add-villager-reputation-API.patch b/patches/server/0428-Add-villager-reputation-API.patch index 851d9cc053..4182694fcb 100644 --- a/patches/server/0428-Add-villager-reputation-API.patch +++ b/patches/server/0428-Add-villager-reputation-API.patch @@ -71,7 +71,7 @@ index 07ecb01d02f64e85d478995062a33b58c211ed7e..e316f83a7adc7bba06a6a3fdab55cc9c static class GossipEntry { diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index fd2a2493fd7c935ab0b2fcd0f5d2b87ef3413af2..94e742856244b99236ba458fa38801abb5acf286 100644 +index 124a8eb24bc9428011075925092e99f8159ee1c2..23ea91449a04e8457273db34c4a388bdf85d7dfc 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -1080,6 +1080,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @@ -83,7 +83,7 @@ index fd2a2493fd7c935ab0b2fcd0f5d2b87ef3413af2..94e742856244b99236ba458fa38801ab return this.gossips; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index 115f107ac100524ef0fcf8de0fc528d164c845f7..b15db2bf0a0bbe39b8067559fbf2b6bdadf56ca4 100644 +index 6b16bb1226515b8cbb477e62b617ee1a7f5ef8ed..f2cfce5cc18776c4dfd162b699661c9bee725f01 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java @@ -16,6 +16,13 @@ import org.bukkit.entity.Villager; @@ -100,7 +100,7 @@ index 115f107ac100524ef0fcf8de0fc528d164c845f7..b15db2bf0a0bbe39b8067559fbf2b6bd public class CraftVillager extends CraftAbstractVillager implements Villager { public CraftVillager(CraftServer server, net.minecraft.world.entity.npc.Villager entity) { -@@ -125,4 +132,45 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { +@@ -130,4 +137,45 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { public static VillagerProfession bukkitToNmsProfession(Profession bukkit) { return Registry.VILLAGER_PROFESSION.get(CraftNamespacedKey.toMinecraft(bukkit.getKey())); } diff --git a/patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch index 59a5584131..1149ce8813 100644 --- a/patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch +++ b/patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add playPickupItemAnimation to LivingEntity diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index a7a6757b83c94a0c0926097021015815f8f18b8e..c01eae70fe12970e9f617bf14e542b33572bcf4c 100644 +index 46fe4779bb894f3beb1f7814dbcc95a7f03b9e5a..bb4896eb52ae8031b7374dfdc408da6f2f3cf68e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -806,5 +806,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -811,5 +811,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { ((Mob) getHandle()).getJumpControl().jump(); } } diff --git a/patches/server/0546-Add-LivingEntity-clearActiveItem.patch b/patches/server/0546-Add-LivingEntity-clearActiveItem.patch index f67ede11d8..f84fc5a468 100644 --- a/patches/server/0546-Add-LivingEntity-clearActiveItem.patch +++ b/patches/server/0546-Add-LivingEntity-clearActiveItem.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add LivingEntity#clearActiveItem diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index c01eae70fe12970e9f617bf14e542b33572bcf4c..18635227a39c96e350fbb8ee9918c41c7a645aa6 100644 +index bb4896eb52ae8031b7374dfdc408da6f2f3cf68e..4b5b9b78356745f6218cd0eb7acebb5bd3879c6b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -773,6 +773,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -778,6 +778,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { return getHandle().getUseItem().asBukkitMirror(); } diff --git a/patches/server/0559-Expose-LivingEntity-hurt-direction.patch b/patches/server/0559-Expose-LivingEntity-hurt-direction.patch index 06745550e6..922b6e74f9 100644 --- a/patches/server/0559-Expose-LivingEntity-hurt-direction.patch +++ b/patches/server/0559-Expose-LivingEntity-hurt-direction.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose LivingEntity hurt direction diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 18635227a39c96e350fbb8ee9918c41c7a645aa6..2ca223324cc079e397852c30c969a05814585cde 100644 +index 4b5b9b78356745f6218cd0eb7acebb5bd3879c6b..df287dd43a01b7b2edd3c8ec510a1e7b802ce2ac 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -818,5 +818,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -823,5 +823,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { getHandle().take(((CraftItem) item).getHandle(), quantity); } diff --git a/patches/server/0609-living-entity-allow-attribute-registration.patch b/patches/server/0609-living-entity-allow-attribute-registration.patch index 2782de61f6..307b5b847b 100644 --- a/patches/server/0609-living-entity-allow-attribute-registration.patch +++ b/patches/server/0609-living-entity-allow-attribute-registration.patch @@ -41,10 +41,10 @@ index 46c313d581b9af6aa0a48f97ae3cc800a88535f2..07d700382fc356837045c46d320b7b69 return net.minecraft.core.Registry.ATTRIBUTE.get(CraftNamespacedKey.toMinecraft(attribute.getKey())); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 2ca223324cc079e397852c30c969a05814585cde..eed0fb2293cf1e19f2d4f4b66a9e2ef8b214141c 100644 +index df287dd43a01b7b2edd3c8ec510a1e7b802ce2ac..0afcc71de94e90eabf3a2efb88b311bf5d16187e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -663,6 +663,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -668,6 +668,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { return this.getHandle().craftAttributes.getAttribute(attribute); } diff --git a/patches/server/0634-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/patches/server/0634-Don-t-ignore-result-of-PlayerEditBookEvent.patch index f406ee6bd3..fa05aced0b 100644 --- a/patches/server/0634-Don-t-ignore-result-of-PlayerEditBookEvent.patch +++ b/patches/server/0634-Don-t-ignore-result-of-PlayerEditBookEvent.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Don't ignore result of PlayerEditBookEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index f5de1e31b62a4e04b865ab041e122d33c7efd54e..95b229081a4d51d63f477ef7894a938584d87fd0 100644 +index 7f7b34cc8a2c5fbf7dff8e785b067cb777808c52..11c2dac045e78b778a82246123ced159bfd2c1de 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1191,7 +1191,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } itemstack.addTagElement("pages", (Tag) nbttaglist); -- CraftEventFactory.handleEditBookEvent(player, slot, old, itemstack); // CraftBukkit -+ this.player.containerMenu.setItem(slot, CraftEventFactory.handleEditBookEvent(player, slot, old, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) +- CraftEventFactory.handleEditBookEvent(player, slot, handItem, itemstack); // CraftBukkit ++ this.player.containerMenu.setItem(slot, CraftEventFactory.handleEditBookEvent(player, slot, handItem, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) } @Override diff --git a/patches/server/0670-More-Enchantment-API.patch b/patches/server/0670-More-Enchantment-API.patch index a83275d8e7..8d82ae04ea 100644 --- a/patches/server/0670-More-Enchantment-API.patch +++ b/patches/server/0670-More-Enchantment-API.patch @@ -64,10 +64,10 @@ index a7966aa0846637efdc43df1ca97cbc5d29616953..aec59f469b77aa2184a2899e8e8d1c5b public net.minecraft.world.item.enchantment.Enchantment getHandle() { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index eed0fb2293cf1e19f2d4f4b66a9e2ef8b214141c..965eb5345d83661809b8b4bc644d5d9af38cf371 100644 +index 0afcc71de94e90eabf3a2efb88b311bf5d16187e..526beeac806d65c53c117be7702ce6cc3c6ec1c1 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -835,5 +835,21 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -840,5 +840,21 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { public void setHurtDirection(float hurtDirection) { getHandle().hurtDir = hurtDirection; } diff --git a/work/Bukkit b/work/Bukkit index a791f93de2..ebb0e28d11 160000 --- a/work/Bukkit +++ b/work/Bukkit @@ -1 +1 @@ -Subproject commit a791f93de242bf89d116fed843b889e38433e094 +Subproject commit ebb0e28d11747aa0bb4bb39fad8979ccfaa925b6 diff --git a/work/CraftBukkit b/work/CraftBukkit index 85b8c1fda6..622cf61119 160000 --- a/work/CraftBukkit +++ b/work/CraftBukkit @@ -1 +1 @@ -Subproject commit 85b8c1fda69f6f80e45ddd19590846c249e5b6bc +Subproject commit 622cf6111905e787add191b9a88d62656439ef31 From f5f80a4aed1251b7a7d8a58d034f54b83333beee Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 21:16:18 -0700 Subject: [PATCH 135/226] fixes --- patches/server/0679-More-Lidded-Block-API.patch | 4 ++-- .../server/0686-Fix-invulnerable-end-crystals.patch | 13 +++++++++---- .../0689-Fix-dangerous-end-portal-logic.patch | 4 ++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/patches/server/0679-More-Lidded-Block-API.patch b/patches/server/0679-More-Lidded-Block-API.patch index 946581e92d..646ca159b0 100644 --- a/patches/server/0679-More-Lidded-Block-API.patch +++ b/patches/server/0679-More-Lidded-Block-API.patch @@ -37,7 +37,7 @@ index f48b830a9ae8160388cb0d0220a44b1ec9f0d214..5045507871db402305a43430194b4c5e + // Paper end - More Lidded Block API } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java -index 25add8bee6ea35beeb205dd828759304346e4f48..d4a5810111c81845c3b465468b470535f814889b 100644 +index 25add8bee6ea35beeb205dd828759304346e4f48..599f6747dfa140e40fef26ed4d8244bfe87b7cdf 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java @@ -14,4 +14,33 @@ public class CraftEnderChest extends CraftBlockEntityState type, Level world) { super(type, world); -@@ -67,8 +68,20 @@ public class EndCrystal extends Entity { +@@ -67,6 +68,17 @@ public class EndCrystal extends Entity { } // CraftBukkit end } @@ -49,7 +49,12 @@ index 2c4c1fc2a2afe88864b72d86708a3ddb6a1f50a0..5b9ba62ce37aabb268d76c23f5cb41a4 + // Paper end } -+ if (this.generatedByDragonFight) tag.putBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals + } +@@ -78,6 +90,7 @@ public class EndCrystal extends Entity { + } + + nbt.putBoolean("ShowBottom", this.showsBottom()); ++ if (this.generatedByDragonFight) nbt.putBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals } @Override @@ -57,7 +62,7 @@ index 2c4c1fc2a2afe88864b72d86708a3ddb6a1f50a0..5b9ba62ce37aabb268d76c23f5cb41a4 if (nbt.contains("ShowBottom", 1)) { this.setShowBottom(nbt.getBoolean("ShowBottom")); } -+ if (tag.contains("Paper.GeneratedByDragonFight", 1)) this.generatedByDragonFight = tag.getBoolean("Paper.GeneratedByDragonFight"); // Paper - Fix invulnerable end crystals ++ if (nbt.contains("Paper.GeneratedByDragonFight", 1)) this.generatedByDragonFight = nbt.getBoolean("Paper.GeneratedByDragonFight"); // Paper - Fix invulnerable end crystals } diff --git a/patches/server/0689-Fix-dangerous-end-portal-logic.patch b/patches/server/0689-Fix-dangerous-end-portal-logic.patch index 3eea2269ff..d7b1eefe90 100644 --- a/patches/server/0689-Fix-dangerous-end-portal-logic.patch +++ b/patches/server/0689-Fix-dangerous-end-portal-logic.patch @@ -11,7 +11,7 @@ Move the tick logic into the post tick, where portaling was designed to happen in the first place. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 5d4bee5470795bd9f362fff5ae653794223fa182..3e665504ff2138f8bc40cfac74b5af722d91f6e9 100644 +index 5d4bee5470795bd9f362fff5ae653794223fa182..b2478c6aee858c362f92c292635bb14f812ccf0b 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -341,6 +341,37 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @@ -31,7 +31,7 @@ index 5d4bee5470795bd9f362fff5ae653794223fa182..3e665504ff2138f8bc40cfac74b5af72 + return; + } + -+ if (this.isPassenger() || this.isVehicle() || !this.canChangeDimensions() || this.removed || !this.valid || !this.isAlive()) { ++ if (this.isPassenger() || this.isVehicle() || !this.canChangeDimensions() || this.isRemoved() || !this.valid || !this.isAlive()) { + return; + } + From 5b49459c6410d48b6059d440f5954cc669a085f5 Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Mon, 14 Jun 2021 23:17:16 -0500 Subject: [PATCH 136/226] Gradle & Paperclip updates --- build.gradle.kts | 13 +++++-------- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index c8e36de76b..ada32f29a8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,9 +4,6 @@ plugins { id("io.papermc.paperweight.core") version "1.0.0-SNAPSHOT" } -val mcVersion = providers.gradleProperty("mcVersion") -val packageVersion = providers.gradleProperty("packageVersion") - subprojects { apply(plugin = "java") @@ -39,7 +36,7 @@ subprojects { repositories { mavenCentral() - maven("https://wav.jfrog.io/artifactory/repo/") { // TODO replace with "https://papermc.io/repo/repository/maven-public/" once paperclip is deplyoed there + maven("https://papermc.io/repo/repository/maven-public/") { content { onlyForConfigurations("paperclip") } @@ -59,13 +56,13 @@ repositories { dependencies { paramMappings("org.quiltmc:yarn:1.17+build.2:mergedv2") remapper("org.quiltmc:tiny-remapper:0.4.1") - decompiler("net.minecraftforge:forgeflower:1.5.498.12@jar") - paperclip("io.papermc:paperclip:2.0.0-SNAPSHOT@jar") + decompiler("net.minecraftforge:forgeflower:1.5.498.12") + paperclip("io.papermc:paperclip:2.0.0@jar") } paperweight { - minecraftVersion.set(mcVersion) - versionPackage.set(packageVersion) + minecraftVersion.set(providers.gradleProperty("mcVersion")) + versionPackage.set(providers.gradleProperty("packageVersion")) serverProject.set(project(":Paper-Server")) paper { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0f80bbf516..69a9715077 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From da99f8648f8433742ce93f5b915be86a3e7fae46 Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Mon, 14 Jun 2021 23:39:41 -0500 Subject: [PATCH 137/226] Fix mappings patches for Hopper getLevel issue --- .../additional-spigot-member-mappings.csrg | 1 - build-data/mappings-patch.tiny | 56 ++----------------- 2 files changed, 6 insertions(+), 51 deletions(-) diff --git a/build-data/additional-spigot-member-mappings.csrg b/build-data/additional-spigot-member-mappings.csrg index 33f15ea1ca..9452f6f5ca 100644 --- a/build-data/additional-spigot-member-mappings.csrg +++ b/build-data/additional-spigot-member-mappings.csrg @@ -1,6 +1,5 @@ # CraftBukkit maps all of (mojmap names): # Merchant.getLevel() -# Hopper.getLevel() # Entity.getCommandSenderWorld() # to getWorld(), which confuses our ability to map this method properly. This patch disambiguates it net/minecraft/world/item/trading/IMerchant fD ()Lnet/minecraft/world/level/World; getLevel diff --git a/build-data/mappings-patch.tiny b/build-data/mappings-patch.tiny index 08728ac9e1..11c99f9c66 100644 --- a/build-data/mappings-patch.tiny +++ b/build-data/mappings-patch.tiny @@ -12,10 +12,6 @@ c net/minecraft/world/level/World net/minecraft/world/level/Level c net/minecraft/server/network/PlayerConnection net/minecraft/server/network/ServerGamePacketListenerImpl m ()Lorg/bukkit/craftbukkit/entity/CraftPlayer; getPlayer getCraftPlayer -# CraftBukkit adds the player field, clashes with a Mojang field -#c net/minecraft/world/inventory/ContainerWorkbench net/minecraft/world/inventory/CraftingMenu -# f Lnet/minecraft/world/entity/player/PlayerInventory; player playerInventory - # CraftBukkit adds the getType() method, clashes with a Mojang method c net/minecraft/world/entity/EntityAreaEffectCloud net/minecraft/world/entity/AreaEffectCloud m ()Ljava/lang/String; getType getPotionType @@ -24,57 +20,11 @@ c net/minecraft/world/entity/EntityAreaEffectCloud net/minecraft/world/entity/Ar c net/minecraft/world/entity/projectile/EntityTippedArrow net/minecraft/world/entity/projectile/Arrow m ()Ljava/lang/String; getType getPotionType -# CraftBukkit adds the getLevel() method, clashes with original method -#c net/minecraft/world/level/block/entity/TileEntityBeacon net/minecraft/world/level/block/entity/BeaconBlockEntity -# m ()I getLevel getLevelCb - -# CraftBukkit adds the getLootTable() method, clashes with original method -#c net/minecraft/world/entity/EntityInsentient net/minecraft/world/entity/Mob -# m ()Lnet/minecraft/resources/MinecraftKey; getLootTable getLootTableCb - -# CraftBukkit adds the canCollideWith() method, clashes with original method -#c net/minecraft/world/entity/Entity net/minecraft/world/entity/Entity -# m (Lnet/minecraft/world/entity/Entity;)Z canCollideWith canCollideWithCb - # CraftBukkit adds a new `a` method which allows passing the Entity parameter # It uses `a` to match the original method (with just 1 param), so this patch makes them match c net/minecraft/server/level/WorldServer net/minecraft/server/level/ServerLevel m (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/Entity;)V a makeObsidianPlatform -# CraftBukkit adds `getMinecraftWorld()` to `GeneratorAccess`, which matches `WorldAccess.getMinecraftWorld()` -# But that method in `WorldAccess` is called `getLevel()` in Mojang mappings -#c net/minecraft/world/level/GeneratorAccess net/minecraft/world/level/LevelAccessor -# m ()Lnet/minecraft/server/level/WorldServer; getMinecraftWorld getLevel - -# SpecialSource2 automatically maps methods to the name of synthetic methods that point to it in an attempt to -# normalize method names with what is expected by the super class. This is _extremely_ stupid and flawed however -# because synthetic methods by definition have different descriptors than the base method, which means method -# signature clashes become possible, which is what happens here. -# -# LootEntryAbstract$Serializer has a synthetic method pointing to the base serialize() method with the following descriptor: -# -# (JsonObject,Object,JsonSerializationContext)V <-- ProGuard names this method `a` -# -# and this synthetic method points to another method with the specialized descriptor: -# -# (JsonObject,LootEntryAbstract,JsonSerializationContext)V <-- ProGuard names this method `b` -# -# SpecialSource2 automatically maps the second method name to the name of the first method, in this case `a`. -# -# LootEntryAbstract$Serializer also has another method with the same descriptor as serialize(), which Spigot calls -# serializeCustom(). Of course ProGuard strips the names and since this method is the first time it's seen this -# descriptor, it renamed that method also to `a`. -# -# This is allowed because the synthetic method for serialize() has a different descriptor, using Object as the second -# parameter. This breaks when SpecialSource2 does it's "magic" of course. This patch manually fixes this case by adding -# both correct mappings -#c net/minecraft/world/level/storage/loot/entries/LootEntryAbstract$Serializer net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer$Serializer -# m (Lcom/google/gson/JsonObject;Lnet/minecraft/world/level/storage/loot/entries/LootEntryAbstract;Lcom/google/gson/JsonSerializationContext;)V a serialize -# p 0 json -# p 1 entry -# p 2 context -# m (Lcom/google/gson/JsonObject;Lnet/minecraft/world/level/storage/loot/entries/LootEntryAbstract;Lcom/google/gson/JsonSerializationContext;)V serializeType serializeCustom - # missed mapping? c net/minecraft/world/level/block/MultifaceBlock net/minecraft/world/level/block/MultifaceBlock m (Lnet/minecraft/world/level/block/state/IBlockData;Lnet/minecraft/world/level/IBlockAccess;Lnet/minecraft/core/BlockPosition;Lnet/minecraft/core/EnumDirection;)Lnet/minecraft/world/level/block/state/IBlockData; c getStateForPlacement @@ -87,3 +37,9 @@ c net/minecraft/server/players/UserCache net/minecraft/server/players/GameProfil # change dimension in ServerPlayer c net/minecraft/server/level/EntityPlayer net/minecraft/server/level/ServerPlayer m (Lnet/minecraft/server/level/WorldServer;Lorg/bukkit/event/player/PlayerTeleportEvent$TeleportCause;)Lnet/minecraft/world/entity/Entity; b changeDimension + +# We add the getLevel method back to Hopper since mojang removed it - we need the method for hooper optimization +# We add the method with this name to match the mojmap method of the same name in BlockEntity +# Since we add the method we need to add the mapping for it so reobf works as expected +c net/minecraft/world/level/block/entity/IHopper net/minecraft/world/level/block/entity/Hopper + m ()Lnet/minecraft/world/level/World; getWorld getLevel From 5a86fba66828b2998bb36a9fa1018c29caab0462 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 21:55:46 -0700 Subject: [PATCH 138/226] final patches from remapped and unmapped keep in mind many patches in the removed folder still need to be updated --- .../0316-Add-more-line-of-sight-methods.patch | 4 +- ...-Make-item-validations-configurable.patch} | 24 ++++++------ ...0691-Add-more-line-of-sight-methods.patch} | 38 ++++++++++++------- .../0692-add-per-world-spawn-limits.patch} | 10 ++--- ...plashEvent-for-water-splash-potions.patch} | 25 ++++-------- 5 files changed, 51 insertions(+), 50 deletions(-) rename patches/{api-unmapped => api}/0316-Add-more-line-of-sight-methods.patch (90%) rename patches/{server-remapped/0758-Make-item-validations-configurable.patch => server/0690-Make-item-validations-configurable.patch} (80%) rename patches/{server-remapped/0759-Add-more-line-of-sight-methods.patch => server/0691-Add-more-line-of-sight-methods.patch} (58%) rename patches/{server-remapped/0760-add-per-world-spawn-limits.patch => server/0692-add-per-world-spawn-limits.patch} (86%) rename patches/{server-remapped/0761-Fix-PotionSplashEvent-for-water-splash-potions.patch => server/0693-Fix-PotionSplashEvent-for-water-splash-potions.patch} (65%) diff --git a/patches/api-unmapped/0316-Add-more-line-of-sight-methods.patch b/patches/api/0316-Add-more-line-of-sight-methods.patch similarity index 90% rename from patches/api-unmapped/0316-Add-more-line-of-sight-methods.patch rename to patches/api/0316-Add-more-line-of-sight-methods.patch index be49c1cc25..b0121b47ab 100644 --- a/patches/api-unmapped/0316-Add-more-line-of-sight-methods.patch +++ b/patches/api/0316-Add-more-line-of-sight-methods.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add more line of sight methods diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index a1496fe00a2d5ba6c1af054d4327f868b2cd7344..f66ec2dfdc64871f8b752bf44086954300804f08 100644 +index 244bb359492ae486f0610f5aea6b75997dbc4bdc..8ae9198ba7fdb006dc420504a984627add20dbb5 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -76,6 +76,14 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad @@ -24,7 +24,7 @@ index a1496fe00a2d5ba6c1af054d4327f868b2cd7344..f66ec2dfdc64871f8b752bf440869543 /** diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index b6de41e3e718fa5d1b82c6f68b153e60a81265e7..ccb81ceee74fff50ec3ed88ae0a41f790c40ae87 100644 +index 330eab77547ae059f716418f71ad1d3391a57a9b..cda05df6784dd4d6a09710a416dcb71c016dabfc 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -483,6 +483,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/server-remapped/0758-Make-item-validations-configurable.patch b/patches/server/0690-Make-item-validations-configurable.patch similarity index 80% rename from patches/server-remapped/0758-Make-item-validations-configurable.patch rename to patches/server/0690-Make-item-validations-configurable.patch index 964f15ad4b..53e2e160d3 100644 --- a/patches/server-remapped/0758-Make-item-validations-configurable.patch +++ b/patches/server/0690-Make-item-validations-configurable.patch @@ -29,10 +29,10 @@ index efc1e42d606e1c9feb1a4871c0714933ae92a1b2..7acf077bc131af718c7548cc29deef55 + } } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index 80397e223990f11c9aa413f3f4ebd7c1b8ce1cff..2ff1619e6898add074481c7ca43bfbf9a8d163ca 100644 +index 1d94d285951faa98ff1f70c3c5330dfaa77cb691..778936a5d1aecaaa20fe2c542466da33594a86ae 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -94,11 +94,11 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { +@@ -93,11 +93,11 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { super(tag); if (tag.contains(BOOK_TITLE.NBT)) { @@ -46,9 +46,9 @@ index 80397e223990f11c9aa413f3f4ebd7c1b8ce1cff..2ff1619e6898add074481c7ca43bfbf9 } if (tag.contains(RESOLVED.NBT)) { -@@ -126,7 +126,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { +@@ -125,7 +125,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { } else { - page = validatePage(page); + page = this.validatePage(page); } - this.pages.add( limit( page, 16384 ) ); // Spigot + this.pages.add( limit( page, com.destroystokyo.paper.PaperConfig.itemValidationBookPageLength ) ); // Spigot // Paper - make configurable @@ -56,28 +56,28 @@ index 80397e223990f11c9aa413f3f4ebd7c1b8ce1cff..2ff1619e6898add074481c7ca43bfbf9 } } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 20e008277d1188fc7b31bfb2522ef9f6429cc3fb..99e18748b3cc4168b1d15c030f992a128b666d84 100644 +index 81738dac125a7247fff5e51fa595667ef25ba0a1..d4a31ebc01656ac372ef597b31df93764dba6ec5 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -357,18 +357,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -356,18 +356,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { CompoundTag display = tag.getCompound(DISPLAY.NBT); if (display.contains(NAME.NBT)) { -- displayName = limit( display.getString(NAME.NBT), 8192 ); // Spigot -+ displayName = limit( display.getString(NAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationDisplayNameLength); // Spigot // Paper - make configurable +- this.displayName = limit( display.getString(NAME.NBT), 8192 ); // Spigot ++ this.displayName = limit( display.getString(NAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationDisplayNameLength ); // Spigot // Paper - make configurable } if (display.contains(LOCNAME.NBT)) { -- locName = limit( display.getString(LOCNAME.NBT), 8192 ); // Spigot -+ locName = limit( display.getString(LOCNAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationLocNameLength ); // Spigot // Paper - make configurable +- this.locName = limit( display.getString(LOCNAME.NBT), 8192 ); // Spigot ++ this.locName = limit( display.getString(LOCNAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationLocNameLength ); // Spigot // Paper - make configurable } if (display.contains(LORE.NBT)) { ListTag list = display.getList(LORE.NBT, CraftMagicNumbers.NBT.TAG_STRING); - lore = new ArrayList(list.size()); + this.lore = new ArrayList(list.size()); for (int index = 0; index < list.size(); index++) { - String line = limit( list.getString(index), 8192 ); // Spigot + String line = limit( list.getString(index), com.destroystokyo.paper.PaperConfig.itemValidationLoreLineLength ); // Spigot // Paper - make configurable - lore.add(line); + this.lore.add(line); } } diff --git a/patches/server-remapped/0759-Add-more-line-of-sight-methods.patch b/patches/server/0691-Add-more-line-of-sight-methods.patch similarity index 58% rename from patches/server-remapped/0759-Add-more-line-of-sight-methods.patch rename to patches/server/0691-Add-more-line-of-sight-methods.patch index 2961b16b07..9cf789500d 100644 --- a/patches/server-remapped/0759-Add-more-line-of-sight-methods.patch +++ b/patches/server/0691-Add-more-line-of-sight-methods.patch @@ -5,22 +5,22 @@ Subject: [PATCH] Add more line of sight methods diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 37787a725725d22b0870dcab0f3bec8b94cfd130..79b43b1b0f8e223f256c2aaec1925426931a9a54 100644 +index b954fcfcf3bd3c55ca856126670fa6967d525fe3..cf7588aa282709a7b8ce6caff4aa713d54280660 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3091,6 +3091,7 @@ public abstract class LivingEntity extends Entity { - Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); - Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); +@@ -3424,6 +3424,7 @@ public abstract class LivingEntity extends Entity { + Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); + Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); -+ // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists - return this.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; ++ // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists + return vec3d1.distanceTo(vec3d) > 128.0D ? false : this.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; + } } - diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 1c9321cef1a05c5e8a22dd52bc63a5103eaf7311..312ed9c693cc5108d51ad90e15d6be4bb21904e1 100644 +index fb90250f1b61c34a0a88bf50bc5b5bae09de9f0e..88635209d1c6598dc62804ad01e9ebbf039435f9 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -315,6 +315,17 @@ public class CraftWorld implements World { +@@ -330,6 +330,18 @@ public class CraftWorld implements World { public io.papermc.paper.world.MoonPhase getMoonPhase() { return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); } @@ -32,6 +32,7 @@ index 1c9321cef1a05c5e8a22dd52bc63a5103eaf7311..312ed9c693cc5108d51ad90e15d6be4b + if (from.getWorld() != to.getWorld()) return false; + Vec3 vec3d = new Vec3(from.getX(), from.getY(), from.getZ()); + Vec3 vec3d1 = new Vec3(to.getX(), to.getY(), to.getZ()); ++ if (vec3d1.distanceTo(vec3d) > 128.0D) return false; + + return this.getHandle().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, null)).getType() == HitResult.Type.MISS; + } @@ -39,11 +40,21 @@ index 1c9321cef1a05c5e8a22dd52bc63a5103eaf7311..312ed9c693cc5108d51ad90e15d6be4b private static final Random rand = new Random(); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 25ba7a26c951fc5e4638bdb0db36e94d3e08fb2e..cd42edd8f36cea3acad76974c39eb0cd1585f73d 100644 +index 526beeac806d65c53c117be7702ce6cc3c6ec1c1..53b61b609361c305fb8d1f1a8700e81ce139fde4 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -549,6 +549,17 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().canSee(((CraftEntity) other).getHandle()); +@@ -29,6 +29,9 @@ import net.minecraft.world.entity.projectile.ThrownEgg; + import net.minecraft.world.entity.projectile.ThrownEnderpearl; + import net.minecraft.world.entity.projectile.ThrownExperienceBottle; + import net.minecraft.world.entity.projectile.ThrownTrident; ++import net.minecraft.world.level.ClipContext; ++import net.minecraft.world.phys.HitResult; ++import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang.Validate; + import org.bukkit.FluidCollisionMode; + import org.bukkit.Location; +@@ -541,6 +544,18 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return this.getHandle().hasLineOfSight(((CraftEntity) other).getHandle()); } + // Paper start @@ -52,6 +63,7 @@ index 25ba7a26c951fc5e4638bdb0db36e94d3e08fb2e..cd42edd8f36cea3acad76974c39eb0cd + if (this.getHandle().level != ((CraftWorld) loc.getWorld()).getHandle()) return false; + Vec3 vec3d = new Vec3(this.getHandle().getX(), this.getHandle().getEyeY(), this.getHandle().getZ()); + Vec3 vec3d1 = new Vec3(loc.getX(), loc.getY(), loc.getZ()); ++ if (vec3d1.distanceTo(vec3d) > 128.0D) return false; + + return this.getHandle().level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this.getHandle())).getType() == HitResult.Type.MISS; + } @@ -59,4 +71,4 @@ index 25ba7a26c951fc5e4638bdb0db36e94d3e08fb2e..cd42edd8f36cea3acad76974c39eb0cd + @Override public boolean getRemoveWhenFarAway() { - return getHandle() instanceof Mob && !((Mob) getHandle()).persistenceRequired; + return this.getHandle() instanceof Mob && !((Mob) this.getHandle()).persistenceRequired; diff --git a/patches/server-remapped/0760-add-per-world-spawn-limits.patch b/patches/server/0692-add-per-world-spawn-limits.patch similarity index 86% rename from patches/server-remapped/0760-add-per-world-spawn-limits.patch rename to patches/server/0692-add-per-world-spawn-limits.patch index b4f5cd5335..a828305722 100644 --- a/patches/server-remapped/0760-add-per-world-spawn-limits.patch +++ b/patches/server/0692-add-per-world-spawn-limits.patch @@ -6,10 +6,10 @@ Subject: [PATCH] add per world spawn limits Taken from #2982. Credit to Chasewhip8 diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index dc5ebbb44238cb5928f385d2962c9057388575f8..f80186f663ff654ab6b69189941cd26815f65f09 100644 +index f2981aa82c26d7bdac08f45818813025b240b77e..974fba89648399919802dc4c11846601d2923712 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -652,6 +652,19 @@ public class PaperWorldConfig { +@@ -605,6 +605,19 @@ public class PaperWorldConfig { zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); } @@ -30,13 +30,13 @@ index dc5ebbb44238cb5928f385d2962c9057388575f8..f80186f663ff654ab6b69189941cd268 private void lightQueueSize() { lightQueueSize = getInt("light-queue-size", lightQueueSize); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 312ed9c693cc5108d51ad90e15d6be4bb21904e1..89aac4214084bd72a83eaaf043b7d47cc0b748f5 100644 +index 88635209d1c6598dc62804ad01e9ebbf039435f9..f2428723ac4a30f57baa0d31aba75a1a95547aa6 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -335,6 +335,13 @@ public class CraftWorld implements World { +@@ -351,6 +351,13 @@ public class CraftWorld implements World { this.generator = gen; - environment = env; + this.environment = env; + // Paper start - per world spawn limits + this.monsterSpawn = this.world.paperConfig.spawnLimitMonsters; + this.animalSpawn = this.world.paperConfig.spawnLimitAnimals; diff --git a/patches/server-remapped/0761-Fix-PotionSplashEvent-for-water-splash-potions.patch b/patches/server/0693-Fix-PotionSplashEvent-for-water-splash-potions.patch similarity index 65% rename from patches/server-remapped/0761-Fix-PotionSplashEvent-for-water-splash-potions.patch rename to patches/server/0693-Fix-PotionSplashEvent-for-water-splash-potions.patch index f351ce4533..56322b5744 100644 --- a/patches/server-remapped/0761-Fix-PotionSplashEvent-for-water-splash-potions.patch +++ b/patches/server/0693-Fix-PotionSplashEvent-for-water-splash-potions.patch @@ -5,23 +5,11 @@ Subject: [PATCH] Fix PotionSplashEvent for water splash potions Fixes SPIGOT-6221: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-6221 -diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -index ed81d2a306d28561370745bb3389c49012f677a7..fbdfab50af195d219f9745324c8924fc777f76ec 100644 ---- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java -+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -@@ -99,6 +99,7 @@ public class DamageSource { - return (new IndirectEntityDamageSource("thrown", projectile, attacker)).setProjectile(); - } - -+ public static DamageSource indirectMagic(Entity target, Entity cause) { return indirectMagic(target, cause); } // Paper - OBFHELPER - public static DamageSource indirectMagic(Entity magic, @Nullable Entity attacker) { - return (new IndirectEntityDamageSource("indirectMagic", magic, attacker)).bypassArmor().setMagic(); - } diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java -index 2ff7e8dfc0a520fb330177c140a1ae5c729f14c0..8bf095bce9dfec6479185b6e60c2e9d76e3363eb 100644 +index 4dc6ab94a50a1dca8603129b28405578d381a06e..8676796ff65cd0bd3f215dc7edcf3a5b2291ca27 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java +++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java -@@ -122,6 +122,7 @@ public class ThrownPotion extends ThrowableItemProjectile { +@@ -126,6 +126,7 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie private void applyWater() { AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb, ThrownPotion.WATER_SENSITIVE); @@ -29,7 +17,7 @@ index 2ff7e8dfc0a520fb330177c140a1ae5c729f14c0..8bf095bce9dfec6479185b6e60c2e9d7 if (!list.isEmpty()) { Iterator iterator = list.iterator(); -@@ -131,11 +132,22 @@ public class ThrownPotion extends ThrowableItemProjectile { +@@ -135,11 +136,23 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie double d0 = this.distanceToSqr(entityliving); if (d0 < 16.0D && entityliving.isSensitiveToWater()) { @@ -50,10 +38,11 @@ index 2ff7e8dfc0a520fb330177c140a1ae5c729f14c0..8bf095bce9dfec6479185b6e60c2e9d7 + } + } + // Paper end - } ++ + List list1 = this.level.getEntitiesOfClass(Axolotl.class, axisalignedbb); + Iterator iterator1 = list1.iterator(); - private void applySplash(List statusEffects, @Nullable Entity entity) { -@@ -153,6 +165,7 @@ public class ThrownPotion extends ThrowableItemProjectile { +@@ -167,6 +180,7 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie double d0 = this.distanceToSqr(entityliving); if (d0 < 16.0D) { From a5251b43755b547e0ccaa379a6b46d71fc46a2a3 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 22:12:50 -0700 Subject: [PATCH 139/226] update Fix incorrect status dataconverter for pre 1.13 chunks --- ...tus-dataconverter-for-pre-1.13-chun.patch} | 59 +++++++------------ 1 file changed, 20 insertions(+), 39 deletions(-) rename patches/{removed/1.17/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch => server/0694-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch} (60%) diff --git a/patches/removed/1.17/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/patches/server/0694-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch similarity index 60% rename from patches/removed/1.17/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch rename to patches/server/0694-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch index 51967306ba..a09b97be3d 100644 --- a/patches/removed/1.17/0738-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch +++ b/patches/server/0694-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch @@ -37,16 +37,23 @@ incorrectly. SPOTTEDLEAF!!!!!!!!!!! diff --git a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java -index 16f6aa39385e2d278d4883a32c11ddd119d0d85d..3d262dcf6db0e395d2fa457f7197f24013037ac1 100644 +index 081bcae48ae34d8354635ea57952f09f14f7fa7a..a4305f58f793e1577de5e13132381ce81304cae4 100644 --- a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java +++ b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java -@@ -43,13 +43,21 @@ public class ChunkToProtochunkFix extends DataFix { - return dynamic.asStreamOpt().result(); +@@ -36,17 +36,26 @@ public class ChunkToProtochunkFix extends DataFix { + OpticFinder opticFinder2 = DSL.fieldFinder("TileTicks", type5); + return TypeRewriteRule.seq(this.fixTypeEverywhereTyped("ChunkToProtoChunkFix", type, this.getOutputSchema().getType(References.CHUNK), (typed) -> { + return typed.updateTyped(opticFinder, type4, (typedx) -> { +- Optional>> optional = typedx.getOptionalTyped(opticFinder2).flatMap((typed) -> { +- return typed.write().result(); ++ Optional>> optional = typedx.getOptionalTyped(opticFinder2).flatMap((it) -> { // Paper - remap fix ++ return it.write().result(); // Paper - remap fix + }).flatMap((dynamicx) -> { + return dynamicx.asStreamOpt().result(); }); - Dynamic dynamic = (Dynamic) typed1.get(DSL.remainderFinder()); -- boolean flag = dynamic.get("TerrainPopulated").asBoolean(false) && (!dynamic.get("LightPopulated").asNumber().result().isPresent() || dynamic.get("LightPopulated").asBoolean(false)); -- -- dynamic = dynamic.set("Status", dynamic.createString(flag ? "mobs_spawned" : "empty")); + Dynamic dynamic = typedx.get(DSL.remainderFinder()); +- boolean bl = dynamic.get("TerrainPopulated").asBoolean(false) && (!dynamic.get("LightPopulated").asNumber().result().isPresent() || dynamic.get("LightPopulated").asBoolean(false)); +- dynamic = dynamic.set("Status", dynamic.createString(bl ? "mobs_spawned" : "empty")); + // Paper start - fix incorrect status conversion + // Vanilla is setting chunks to incorrect status here, they should be using at minimum carved. + // for populated chunks, it should be at minimum decorated @@ -57,37 +64,11 @@ index 16f6aa39385e2d278d4883a32c11ddd119d0d85d..3d262dcf6db0e395d2fa457f7197f240 + final String newStatus = !terrainPopulated ? "carved" : (lightPopulated ? "mobs_spawned" : "decorated"); + + dynamic = dynamic.set("Status", dynamic.createString(newStatus)); - dynamic = dynamic.set("hasLegacyStructureData", dynamic.createBoolean(true)); -- Dynamic dynamic1; + // Paper end - fix incorrect status conversion -+ Dynamic dynamic1; // Paper - decompile fix - -- if (flag) { + dynamic = dynamic.set("hasLegacyStructureData", dynamic.createBoolean(true)); + Dynamic dynamic3; +- if (bl) { + if (true) { // Paper - fix incorrect status conversion - Optional optional1 = dynamic.get("Biomes").asByteBufferOpt().result(); - - if (optional1.isPresent()) { -@@ -70,7 +78,7 @@ public class ChunkToProtochunkFix extends DataFix { - }).collect(Collectors.toList()); - - if (optional.isPresent()) { -- ((Stream) optional.get()).forEach((dynamic2) -> { -+ optional.get().forEach((dynamic2) -> { // Paper - decompile fix - int j = dynamic2.get("x").asInt(0); - int k = dynamic2.get("y").asInt(0); - int l = dynamic2.get("z").asInt(0); -@@ -78,11 +86,11 @@ public class ChunkToProtochunkFix extends DataFix { - - ((ShortList) list.get(k >> 4)).add(short0); - }); -+ Dynamic finalDynamic = dynamic; // Paper - decompile fix - dynamic = dynamic.set("ToBeTicked", dynamic.createList(list.stream().map((shortlist) -> { -- Stream stream = shortlist.stream(); -+ Stream stream = shortlist.stream(); // Paper - decompile fix - -- dynamic.getClass(); -- return dynamic.createList(stream.map(dynamic::createShort)); -+ return finalDynamic.createList(stream.map(finalDynamic::createShort)); - }))); - } - + Optional optional2 = dynamic.get("Biomes").asByteBufferOpt().result(); + if (optional2.isPresent()) { + ByteBuffer byteBuffer = optional2.get(); From 8755b391fb17a17e248d6831cbeef0429eb22ba2 Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Mon, 14 Jun 2021 22:38:36 -0700 Subject: [PATCH 140/226] Add back stream patch (#5838) --- ...-Remove-some-streams-from-structures.patch | 144 ------------------ ...-Remove-some-streams-from-structures.patch | 106 +++++++++++++ ...rom-classes-related-villager-gossip.patch} | 0 ...0472-Support-components-in-ItemMeta.patch} | 0 ...rgetLivingEntityEvent-for-1.16-mobs.patch} | 0 ...patch => 0474-Add-entity-liquid-API.patch} | 2 +- ...date-itemstack-legacy-name-and-lore.patch} | 0 ...wn-player-in-correct-world-on-login.patch} | 0 ...atch => 0477-Add-PrepareResultEvent.patch} | 2 +- ...low-delegation-to-vanilla-chunk-gen.patch} | 2 +- ...-for-portal-on-world-gen-entity-add.patch} | 0 ...e-NetworkManager-Exception-Handling.patch} | 0 ...ncement-data-player-iteration-to-be.patch} | 0 ...x-arrows-never-despawning-MC-125757.patch} | 0 ...Vanilla-Command-permission-checking.patch} | 0 ...ve-range-check-for-block-placing-up.patch} | 2 +- ...-5989.patch => 0485-Fix-SPIGOT-5989.patch} | 0 ...-Bukkit-world-container-is-not-used.patch} | 0 ...5885-Unable-to-disable-advancements.patch} | 0 ...taPlayer-leak-due-from-quitting-ear.patch} | 0 ...eLighting-call-to-World-spigot-stri.patch} | 0 ...ix-some-rails-connecting-improperly.patch} | 0 ...h => 0491-Incremental-player-saving.patch} | 2 +- ...Fix-MC-187716-Use-configured-height.patch} | 0 ...stake-in-CB-NBT-int-deserialization.patch} | 0 ...rver-load-chunks-from-newer-version.patch} | 0 ...support.patch => 0495-Brand-support.patch} | 2 +- ...patch => 0496-Add-setMaxPlayers-API.patch} | 0 ...PickupItemAnimation-to-LivingEntity.patch} | 0 ...h => 0498-Don-t-require-FACING-data.patch} | 0 ...eEvent-not-firing-for-all-use-cases.patch} | 0 ...PI.patch => 0500-Add-moon-phase-API.patch} | 0 ...headless-pistons-from-being-created.patch} | 0 ...ent.patch => 0502-Add-BellRingEvent.patch} | 0 ...dd-zombie-targets-turtle-egg-config.patch} | 0 ...patch => 0504-Buffer-joins-to-world.patch} | 0 ...=> 0505-Optimize-redstone-algorithm.patch} | 0 ...s-not-working-in-some-kick-messages.patch} | 0 ...reateEvent-needs-to-know-its-entity.patch} | 0 ...ch => 0508-Fix-CraftTeam-null-check.patch} | 0 ...I.patch => 0509-Add-more-Evoker-API.patch} | 0 ...translation-keys-for-blocks-entitie.patch} | 0 ...te-HoverEvent-from-ItemStack-Entity.patch} | 0 ...ch => 0512-Cache-block-data-strings.patch} | 0 ...rtation-and-cancel-velocity-if-tele.patch} | 4 +- ...l-open-container-api-to-HumanEntity.patch} | 0 ...aFixerUpper-Rewrite-Rules-on-demand.patch} | 0 ...-capture-to-capture-all-items-added.patch} | 0 ...ty-in-invalid-locations-SPIGOT-6086.patch} | 0 ...-Counter-to-allow-plugins-to-use-va.patch} | 2 +- ...track-plugin-scoreboards-by-default.patch} | 0 ...king.patch => 0520-Entity-isTicking.patch} | 2 +- ...non-whitelisted-player-when-white-l.patch} | 0 ...g-a-passenger-in-CreatureSpawnEvent.patch} | 2 +- ...eset-Ender-Crystals-on-Dragon-Spawn.patch} | 0 ...-large-move-vectors-crashing-server.patch} | 2 +- ...atch => 0525-Optimise-getType-calls.patch} | 2 +- ....patch => 0526-Villager-resetOffers.patch} | 0 ...nig-for-some-hot-IBlockData-methods.patch} | 0 ...ce-order-when-capturing-blockstates.patch} | 0 ...lockpos-allocation-from-pathfinding.patch} | 0 ...em-locations-dropped-from-campfires.patch} | 0 ...tch => 0531-Player-elytra-boost-API.patch} | 0 ...32-Fixed-TileEntityBell-memory-leak.patch} | 0 ...ing-up-when-item-stack-is-empty-in-.patch} | 0 ...Add-getOfflinePlayerIfCached-String.patch} | 0 ...ch => 0535-Add-ignore-discounts-API.patch} | 2 +- ...Toggle-for-removing-existing-dragon.patch} | 0 ...x-client-lag-on-advancement-loading.patch} | 0 ...> 0538-Item-no-age-no-player-pickup.patch} | 0 ...539-Beacon-API-custom-effect-ranges.patch} | 0 ...tch => 0540-Add-API-for-quit-reason.patch} | 4 +- ...h => 0541-Seed-based-feature-search.patch} | 0 ...ng-Trader-spawn-rate-config-options.patch} | 0 ...rove-performance-of-the-end-generat.patch} | 0 ...ch => 0544-Expose-world-spawn-angle.patch} | 0 ...patch => 0545-Add-Destroy-Speed-API.patch} | 0 ...-spawnParticle-x-y-z-precision-loss.patch} | 0 ...47-Add-LivingEntity-clearActiveItem.patch} | 0 ...=> 0548-Add-PlayerItemCooldownEvent.patch} | 0 ...PI.patch => 0549-More-lightning-API.patch} | 0 ...should-not-bypass-cramming-gamerule.patch} | 2 +- ...-missing-default-perms-for-commands.patch} | 0 ...h => 0552-Add-PlayerShearBlockEvent.patch} | 0 ...rbose-world-setting-to-false-by-def.patch} | 0 ...ng-zombie-villager-discount-exploit.patch} | 2 +- ....patch => 0555-Limit-recipe-packets.patch} | 2 +- ...-CraftSound-backwards-compatibility.patch} | 0 ... 0557-MC-4-Fix-item-position-desync.patch} | 2 +- ...558-Player-Chunk-Load-Unload-Events.patch} | 2 +- ...9-Optimize-Dynamic-get-Missing-Keys.patch} | 0 ...-Expose-LivingEntity-hurt-direction.patch} | 0 ...OBSTRUCTED-reason-to-BedEnterResult.patch} | 2 +- ...-invalid-ingredient-lists-in-Villag.patch} | 0 ...atch => 0563-added-PlayerTradeEvent.patch} | 0 ...ch => 0564-Implement-TargetHitEvent.patch} | 0 ...565-Additional-Block-Material-API-s.patch} | 0 ...tch => 0566-Fix-harming-potion-dupe.patch} | 0 ...get-Material-from-Boats-and-Minecar.patch} | 0 ....patch => 0568-Cache-burn-durations.patch} | 0 ...ob-spawner-spawn-egg-transformation.patch} | 0 ...ment-PlayerFlowerPotManipulateEvent.patch} | 0 ...event-not-being-called-in-adventure.patch} | 2 +- ...h => 0572-Zombie-API-breaking-doors.patch} | 0 ...573-Fix-nerfed-slime-when-splitting.patch} | 0 ...=> 0574-Add-EntityLoadCrossbowEvent.patch} | 0 ...ch => 0575-Guardian-beam-workaround.patch} | 0 ...0576-Added-WorldGameRuleChangeEvent.patch} | 0 ...-Added-ServerResourcesReloadedEvent.patch} | 0 ...d-settings-for-mobs-picking-up-loot.patch} | 0 ...mplemented-BlockFailedDispenseEvent.patch} | 2 +- ...-Added-PlayerLecternPageChangeEvent.patch} | 0 ...-Added-PlayerLoomPatternSelectEvent.patch} | 0 ...nfigurable-door-breaking-difficulty.patch} | 0 ...ty-commands-shall-not-be-dispatched.patch} | 0 ...I-to-expose-exact-interaction-point.patch} | 2 +- ...OIs.patch => 0585-Remove-stale-POIs.patch} | 0 ...h => 0586-Fix-villager-boat-exploit.patch} | 0 ...I.patch => 0587-Add-sendOpLevel-API.patch} | 0 ...ch => 0588-Add-StructureLocateEvent.patch} | 0 ...-for-requiring-a-player-participant.patch} | 2 +- ...leHitEvent-call-when-fireballs-dead.patch} | 0 ...nent-with-empty-text-instead-of-thr.patch} | 0 ...592-Make-schedule-command-per-world.patch} | 0 ...593-Configurable-max-leash-distance.patch} | 0 ...594-Implement-BlockPreDispenseEvent.patch} | 2 +- ...h => 0595-Added-Vanilla-Entity-Tags.patch} | 0 ...-API.patch => 0596-added-Wither-API.patch} | 0 ...ng-of-PlayerChangeBeaconEffectEvent.patch} | 0 ...-spam-when-removing-chests-in-water.patch} | 0 ...e-for-always-placing-the-dragon-egg.patch} | 0 ...-PlayerStonecutterRecipeSelectEvent.patch} | 0 ...eash-variable-to-EntityUnleashEvent.patch} | 2 +- ...e-map-update-when-spawning-disabled.patch} | 0 ...shield-blocking-on-dimension-change.patch} | 2 +- ...atch => 0604-add-DragonEggFormEvent.patch} | 0 ...Event.patch => 0605-EntityMoveEvent.patch} | 0 ...isable-pathfinding-updates-on-block.patch} | 0 ... 0607-Inline-shift-direction-fields.patch} | 0 ...-adding-items-to-BlockDropItemEvent.patch} | 2 +- ...inThreadExecutor-to-BukkitScheduler.patch} | 0 ...entity-allow-attribute-registration.patch} | 0 ...ix-dead-slime-setSize-invincibility.patch} | 0 ...pes-should-return-an-immutable-list.patch} | 0 ....patch => 0613-misc-debugging-dumps.patch} | 0 ...port-for-hex-color-codes-in-console.patch} | 0 ...atch => 0615-Expose-Tracked-Players.patch} | 0 ...6-Remove-streams-from-SensorNearest.patch} | 0 ...ix-Wither-hostility-towards-players.patch} | 0 ...er-exception-on-empty-JsonList-file.patch} | 0 ...GUI.patch => 0619-Improve-ServerGUI.patch} | 0 ...ure-plate-EntityInteractEvent-for-i.patch} | 0 ...621-fix-converting-txt-to-json-file.patch} | 0 ...atch => 0622-Add-worldborder-events.patch} | 0 ...=> 0623-added-PlayerNameEntityEvent.patch} | 0 ...grindstones-from-overstacking-items.patch} | 0 ...h => 0625-Add-recipe-to-cook-events.patch} | 0 ...patch => 0626-Add-Block-isValidTool.patch} | 0 ...using-signs-inside-spawn-protection.patch} | 2 +- ...ch => 0628-Implement-Keyed-on-World.patch} | 0 ...ternative-constructor-for-Rotations.patch} | 0 ...y-API.patch => 0630-Item-Rarity-API.patch} | 0 ...imer-for-Wandering-Traders-spawned-.patch} | 0 ...py-TESign-isEditable-from-snapshots.patch} | 0 ...d-item-when-player-has-disconnected.patch} | 0 ...elist-use-configurable-kick-message.patch} | 0 ...gnore-result-of-PlayerEditBookEvent.patch} | 0 ...block-falling-causing-client-desync.patch} | 0 ...tch => 0637-Expose-protocol-version.patch} | 0 ...nt-suggestion-tooltips-in-AsyncTabC.patch} | 2 +- ...ab-completions-for-brigadier-comman.patch} | 0 ...temConsumeEvent-cancelling-properly.patch} | 0 ...patch => 0641-Add-bypass-host-check.patch} | 0 ...0642-Set-area-affect-cloud-rotation.patch} | 0 ...add-isDeeplySleeping-to-HumanEntity.patch} | 0 ...ting-give-items-on-item-drop-cancel.patch} | 0 ...add-consumeFuel-to-FurnaceBurnEvent.patch} | 0 ...-set-drop-chance-to-EntityEquipment.patch} | 0 ...ix-PigZombieAngerEvent-cancellation.patch} | 0 ...-checkReach-check-for-Shulker-boxes.patch} | 0 ...ix-PlayerItemHeldEvent-firing-twice.patch} | 2 +- ... => 0650-Added-PlayerDeepSleepEvent.patch} | 0 ...ld-API.patch => 0651-More-World-API.patch} | 0 ... 0652-Added-PlayerBedFailEnterEvent.patch} | 0 ...-to-convert-between-Component-and-B.patch} | 0 ...n-acting-as-a-bed-respawn-from-the-.patch} | 0 ...acon-activation-deactivation-events.patch} | 0 ...-RespawnFlags-to-PlayerRespawnEvent.patch} | 2 +- ...dd-Channel-initialization-listeners.patch} | 0 ...mands-if-tab-completion-is-disabled.patch} | 0 ...> 0659-Add-more-WanderingTrader-API.patch} | 0 ...dd-EntityBlockStorage-clearEntities.patch} | 0 ...ssage-to-PlayerAdvancementDoneEvent.patch} | 0 ...address-to-AsyncPlayerPreLoginEvent.patch} | 0 ...close.patch => 0663-Inventory-close.patch} | 0 ...reateEvent-players-and-end-platform.patch} | 2 +- ...-in-sunlight-API-for-Phantoms-and-S.patch} | 0 ...=> 0666-Fix-CraftPotionBrewer-cache.patch} | 0 ...atch => 0667-Add-basic-Datapack-API.patch} | 0 ...ment-variable-to-disable-server-gui.patch} | 0 ...itions-to-PlayerGameModeChangeEvent.patch} | 4 +- ... => 0670-ItemStack-repair-check-API.patch} | 0 ....patch => 0671-More-Enchantment-API.patch} | 0 ...option-to-load-extra-plugin-jars-no.patch} | 0 ...-and-optimise-world-force-upgrading.patch} | 0 ...PI.patch => 0674-Add-Mob-lookAt-API.patch} | 0 ...0675-Add-Unix-domain-socket-support.patch} | 0 ... => 0676-Add-EntityInsideBlockEvent.patch} | 2 +- ...77-Attributes-API-for-item-defaults.patch} | 0 ...hantCustom-emit-PlayerPurchaseEvent.patch} | 0 ...ause-to-Weather-ThunderChangeEvents.patch} | 0 ...patch => 0680-More-Lidded-Block-API.patch} | 0 ...81-Limit-item-frame-cursors-on-maps.patch} | 0 ...0682-Add-PufferFishStateChangeEvent.patch} | 0 ... => 0683-Add-PlayerKickEvent-causes.patch} | 2 +- ...erBucketEmptyEvent-result-itemstack.patch} | 0 ...-to-fix-items-merging-through-walls.patch} | 0 ...h => 0686-Add-BellRevealRaiderEvent.patch} | 0 ... 0687-Fix-invulnerable-end-crystals.patch} | 0 ...88-Add-ElderGuardianAppearanceEvent.patch} | 0 ...inventory-on-cancelled-pickup-event.patch} | 2 +- ...0690-Fix-dangerous-end-portal-logic.patch} | 0 ...-Make-item-validations-configurable.patch} | 0 ...0692-Add-more-line-of-sight-methods.patch} | 0 ... => 0693-add-per-world-spawn-limits.patch} | 0 ...plashEvent-for-water-splash-potions.patch} | 0 226 files changed, 146 insertions(+), 184 deletions(-) delete mode 100644 patches/removed/1.17/0517-Remove-some-streams-from-structures.patch create mode 100644 patches/server/0470-Remove-some-streams-from-structures.patch rename patches/server/{0470-Remove-streams-from-classes-related-villager-gossip.patch => 0471-Remove-streams-from-classes-related-villager-gossip.patch} (100%) rename patches/server/{0471-Support-components-in-ItemMeta.patch => 0472-Support-components-in-ItemMeta.patch} (100%) rename patches/server/{0472-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch => 0473-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch} (100%) rename patches/server/{0473-Add-entity-liquid-API.patch => 0474-Add-entity-liquid-API.patch} (96%) rename patches/server/{0474-Update-itemstack-legacy-name-and-lore.patch => 0475-Update-itemstack-legacy-name-and-lore.patch} (100%) rename patches/server/{0475-Spawn-player-in-correct-world-on-login.patch => 0476-Spawn-player-in-correct-world-on-login.patch} (100%) rename patches/server/{0476-Add-PrepareResultEvent.patch => 0477-Add-PrepareResultEvent.patch} (98%) rename patches/server/{0477-Allow-delegation-to-vanilla-chunk-gen.patch => 0478-Allow-delegation-to-vanilla-chunk-gen.patch} (97%) rename patches/server/{0478-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch => 0479-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch} (100%) rename patches/server/{0479-Optimize-NetworkManager-Exception-Handling.patch => 0480-Optimize-NetworkManager-Exception-Handling.patch} (100%) rename patches/server/{0480-Optimize-the-advancement-data-player-iteration-to-be.patch => 0481-Optimize-the-advancement-data-player-iteration-to-be.patch} (100%) rename patches/server/{0481-Fix-arrows-never-despawning-MC-125757.patch => 0482-Fix-arrows-never-despawning-MC-125757.patch} (100%) rename patches/server/{0482-Thread-Safe-Vanilla-Command-permission-checking.patch => 0483-Thread-Safe-Vanilla-Command-permission-checking.patch} (100%) rename patches/server/{0483-Move-range-check-for-block-placing-up.patch => 0484-Move-range-check-for-block-placing-up.patch} (96%) rename patches/server/{0484-Fix-SPIGOT-5989.patch => 0485-Fix-SPIGOT-5989.patch} (100%) rename patches/server/{0485-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch => 0486-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch} (100%) rename patches/server/{0486-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch => 0487-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch} (100%) rename patches/server/{0487-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch => 0488-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch} (100%) rename patches/server/{0488-Add-missing-strikeLighting-call-to-World-spigot-stri.patch => 0489-Add-missing-strikeLighting-call-to-World-spigot-stri.patch} (100%) rename patches/server/{0489-Fix-some-rails-connecting-improperly.patch => 0490-Fix-some-rails-connecting-improperly.patch} (100%) rename patches/server/{0490-Incremental-player-saving.patch => 0491-Incremental-player-saving.patch} (98%) rename patches/server/{0491-Fix-MC-187716-Use-configured-height.patch => 0492-Fix-MC-187716-Use-configured-height.patch} (100%) rename patches/server/{0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch => 0493-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch} (100%) rename patches/server/{0493-Do-not-let-the-server-load-chunks-from-newer-version.patch => 0494-Do-not-let-the-server-load-chunks-from-newer-version.patch} (100%) rename patches/server/{0494-Brand-support.patch => 0495-Brand-support.patch} (97%) rename patches/server/{0495-Add-setMaxPlayers-API.patch => 0496-Add-setMaxPlayers-API.patch} (100%) rename patches/server/{0496-Add-playPickupItemAnimation-to-LivingEntity.patch => 0497-Add-playPickupItemAnimation-to-LivingEntity.patch} (100%) rename patches/server/{0497-Don-t-require-FACING-data.patch => 0498-Don-t-require-FACING-data.patch} (100%) rename patches/server/{0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch => 0499-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch} (100%) rename patches/server/{0499-Add-moon-phase-API.patch => 0500-Add-moon-phase-API.patch} (100%) rename patches/server/{0500-Prevent-headless-pistons-from-being-created.patch => 0501-Prevent-headless-pistons-from-being-created.patch} (100%) rename patches/server/{0501-Add-BellRingEvent.patch => 0502-Add-BellRingEvent.patch} (100%) rename patches/server/{0502-Add-zombie-targets-turtle-egg-config.patch => 0503-Add-zombie-targets-turtle-egg-config.patch} (100%) rename patches/server/{0503-Buffer-joins-to-world.patch => 0504-Buffer-joins-to-world.patch} (100%) rename patches/server/{0504-Optimize-redstone-algorithm.patch => 0505-Optimize-redstone-algorithm.patch} (100%) rename patches/server/{0505-Fix-hex-colors-not-working-in-some-kick-messages.patch => 0506-Fix-hex-colors-not-working-in-some-kick-messages.patch} (100%) rename patches/server/{0506-PortalCreateEvent-needs-to-know-its-entity.patch => 0507-PortalCreateEvent-needs-to-know-its-entity.patch} (100%) rename patches/server/{0507-Fix-CraftTeam-null-check.patch => 0508-Fix-CraftTeam-null-check.patch} (100%) rename patches/server/{0508-Add-more-Evoker-API.patch => 0509-Add-more-Evoker-API.patch} (100%) rename patches/server/{0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch => 0510-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch} (100%) rename patches/server/{0510-Create-HoverEvent-from-ItemStack-Entity.patch => 0511-Create-HoverEvent-from-ItemStack-Entity.patch} (100%) rename patches/server/{0511-Cache-block-data-strings.patch => 0512-Cache-block-data-strings.patch} (100%) rename patches/server/{0512-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch => 0513-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch} (96%) rename patches/server/{0513-Add-additional-open-container-api-to-HumanEntity.patch => 0514-Add-additional-open-container-api-to-HumanEntity.patch} (100%) rename patches/server/{0514-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch => 0515-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch} (100%) rename patches/server/{0515-Extend-block-drop-capture-to-capture-all-items-added.patch => 0516-Extend-block-drop-capture-to-capture-all-items-added.patch} (100%) rename patches/server/{0516-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch => 0517-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch} (100%) rename patches/server/{0517-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch => 0518-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch} (94%) rename patches/server/{0518-Lazily-track-plugin-scoreboards-by-default.patch => 0519-Lazily-track-plugin-scoreboards-by-default.patch} (100%) rename patches/server/{0519-Entity-isTicking.patch => 0520-Entity-isTicking.patch} (95%) rename patches/server/{0520-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch => 0521-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch} (100%) rename patches/server/{0521-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch => 0522-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch} (89%) rename patches/server/{0522-Reset-Ender-Crystals-on-Dragon-Spawn.patch => 0523-Reset-Ender-Crystals-on-Dragon-Spawn.patch} (100%) rename patches/server/{0523-Fix-for-large-move-vectors-crashing-server.patch => 0524-Fix-for-large-move-vectors-crashing-server.patch} (97%) rename patches/server/{0524-Optimise-getType-calls.patch => 0525-Optimise-getType-calls.patch} (98%) rename patches/server/{0525-Villager-resetOffers.patch => 0526-Villager-resetOffers.patch} (100%) rename patches/server/{0526-Improve-inlinig-for-some-hot-IBlockData-methods.patch => 0527-Improve-inlinig-for-some-hot-IBlockData-methods.patch} (100%) rename patches/server/{0527-Retain-block-place-order-when-capturing-blockstates.patch => 0528-Retain-block-place-order-when-capturing-blockstates.patch} (100%) rename patches/server/{0528-Reduce-blockpos-allocation-from-pathfinding.patch => 0529-Reduce-blockpos-allocation-from-pathfinding.patch} (100%) rename patches/server/{0529-Fix-item-locations-dropped-from-campfires.patch => 0530-Fix-item-locations-dropped-from-campfires.patch} (100%) rename patches/server/{0530-Player-elytra-boost-API.patch => 0531-Player-elytra-boost-API.patch} (100%) rename patches/server/{0531-Fixed-TileEntityBell-memory-leak.patch => 0532-Fixed-TileEntityBell-memory-leak.patch} (100%) rename patches/server/{0532-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch => 0533-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch} (100%) rename patches/server/{0533-Add-getOfflinePlayerIfCached-String.patch => 0534-Add-getOfflinePlayerIfCached-String.patch} (100%) rename patches/server/{0534-Add-ignore-discounts-API.patch => 0535-Add-ignore-discounts-API.patch} (98%) rename patches/server/{0535-Toggle-for-removing-existing-dragon.patch => 0536-Toggle-for-removing-existing-dragon.patch} (100%) rename patches/server/{0536-Fix-client-lag-on-advancement-loading.patch => 0537-Fix-client-lag-on-advancement-loading.patch} (100%) rename patches/server/{0537-Item-no-age-no-player-pickup.patch => 0538-Item-no-age-no-player-pickup.patch} (100%) rename patches/server/{0538-Beacon-API-custom-effect-ranges.patch => 0539-Beacon-API-custom-effect-ranges.patch} (100%) rename patches/server/{0539-Add-API-for-quit-reason.patch => 0540-Add-API-for-quit-reason.patch} (96%) rename patches/server/{0540-Seed-based-feature-search.patch => 0541-Seed-based-feature-search.patch} (100%) rename patches/server/{0541-Add-Wandering-Trader-spawn-rate-config-options.patch => 0542-Add-Wandering-Trader-spawn-rate-config-options.patch} (100%) rename patches/server/{0542-Significantly-improve-performance-of-the-end-generat.patch => 0543-Significantly-improve-performance-of-the-end-generat.patch} (100%) rename patches/server/{0543-Expose-world-spawn-angle.patch => 0544-Expose-world-spawn-angle.patch} (100%) rename patches/server/{0544-Add-Destroy-Speed-API.patch => 0545-Add-Destroy-Speed-API.patch} (100%) rename patches/server/{0545-Fix-Player-spawnParticle-x-y-z-precision-loss.patch => 0546-Fix-Player-spawnParticle-x-y-z-precision-loss.patch} (100%) rename patches/server/{0546-Add-LivingEntity-clearActiveItem.patch => 0547-Add-LivingEntity-clearActiveItem.patch} (100%) rename patches/server/{0547-Add-PlayerItemCooldownEvent.patch => 0548-Add-PlayerItemCooldownEvent.patch} (100%) rename patches/server/{0548-More-lightning-API.patch => 0549-More-lightning-API.patch} (100%) rename patches/server/{0549-Climbing-should-not-bypass-cramming-gamerule.patch => 0550-Climbing-should-not-bypass-cramming-gamerule.patch} (98%) rename patches/server/{0550-Added-missing-default-perms-for-commands.patch => 0551-Added-missing-default-perms-for-commands.patch} (100%) rename patches/server/{0551-Add-PlayerShearBlockEvent.patch => 0552-Add-PlayerShearBlockEvent.patch} (100%) rename patches/server/{0552-Set-spigots-verbose-world-setting-to-false-by-def.patch => 0553-Set-spigots-verbose-world-setting-to-false-by-def.patch} (100%) rename patches/server/{0553-Fix-curing-zombie-villager-discount-exploit.patch => 0554-Fix-curing-zombie-villager-discount-exploit.patch} (96%) rename patches/server/{0554-Limit-recipe-packets.patch => 0555-Limit-recipe-packets.patch} (97%) rename patches/server/{0555-Fix-CraftSound-backwards-compatibility.patch => 0556-Fix-CraftSound-backwards-compatibility.patch} (100%) rename patches/server/{0556-MC-4-Fix-item-position-desync.patch => 0557-MC-4-Fix-item-position-desync.patch} (97%) rename patches/server/{0557-Player-Chunk-Load-Unload-Events.patch => 0558-Player-Chunk-Load-Unload-Events.patch} (94%) rename patches/server/{0558-Optimize-Dynamic-get-Missing-Keys.patch => 0559-Optimize-Dynamic-get-Missing-Keys.patch} (100%) rename patches/server/{0559-Expose-LivingEntity-hurt-direction.patch => 0560-Expose-LivingEntity-hurt-direction.patch} (100%) rename patches/server/{0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch => 0561-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} (91%) rename patches/server/{0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch => 0562-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch} (100%) rename patches/server/{0562-added-PlayerTradeEvent.patch => 0563-added-PlayerTradeEvent.patch} (100%) rename patches/server/{0563-Implement-TargetHitEvent.patch => 0564-Implement-TargetHitEvent.patch} (100%) rename patches/server/{0564-Additional-Block-Material-API-s.patch => 0565-Additional-Block-Material-API-s.patch} (100%) rename patches/server/{0565-Fix-harming-potion-dupe.patch => 0566-Fix-harming-potion-dupe.patch} (100%) rename patches/server/{0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch => 0567-Implement-API-to-get-Material-from-Boats-and-Minecar.patch} (100%) rename patches/server/{0567-Cache-burn-durations.patch => 0568-Cache-burn-durations.patch} (100%) rename patches/server/{0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch => 0569-Allow-disabling-mob-spawner-spawn-egg-transformation.patch} (100%) rename patches/server/{0569-Implement-PlayerFlowerPotManipulateEvent.patch => 0570-Implement-PlayerFlowerPotManipulateEvent.patch} (100%) rename patches/server/{0570-Fix-interact-event-not-being-called-in-adventure.patch => 0571-Fix-interact-event-not-being-called-in-adventure.patch} (95%) rename patches/server/{0571-Zombie-API-breaking-doors.patch => 0572-Zombie-API-breaking-doors.patch} (100%) rename patches/server/{0572-Fix-nerfed-slime-when-splitting.patch => 0573-Fix-nerfed-slime-when-splitting.patch} (100%) rename patches/server/{0573-Add-EntityLoadCrossbowEvent.patch => 0574-Add-EntityLoadCrossbowEvent.patch} (100%) rename patches/server/{0574-Guardian-beam-workaround.patch => 0575-Guardian-beam-workaround.patch} (100%) rename patches/server/{0575-Added-WorldGameRuleChangeEvent.patch => 0576-Added-WorldGameRuleChangeEvent.patch} (100%) rename patches/server/{0576-Added-ServerResourcesReloadedEvent.patch => 0577-Added-ServerResourcesReloadedEvent.patch} (100%) rename patches/server/{0577-Added-world-settings-for-mobs-picking-up-loot.patch => 0578-Added-world-settings-for-mobs-picking-up-loot.patch} (100%) rename patches/server/{0578-Implemented-BlockFailedDispenseEvent.patch => 0579-Implemented-BlockFailedDispenseEvent.patch} (96%) rename patches/server/{0579-Added-PlayerLecternPageChangeEvent.patch => 0580-Added-PlayerLecternPageChangeEvent.patch} (100%) rename patches/server/{0580-Added-PlayerLoomPatternSelectEvent.patch => 0581-Added-PlayerLoomPatternSelectEvent.patch} (100%) rename patches/server/{0581-Configurable-door-breaking-difficulty.patch => 0582-Configurable-door-breaking-difficulty.patch} (100%) rename patches/server/{0582-Empty-commands-shall-not-be-dispatched.patch => 0583-Empty-commands-shall-not-be-dispatched.patch} (100%) rename patches/server/{0583-Implement-API-to-expose-exact-interaction-point.patch => 0584-Implement-API-to-expose-exact-interaction-point.patch} (97%) rename patches/server/{0584-Remove-stale-POIs.patch => 0585-Remove-stale-POIs.patch} (100%) rename patches/server/{0585-Fix-villager-boat-exploit.patch => 0586-Fix-villager-boat-exploit.patch} (100%) rename patches/server/{0586-Add-sendOpLevel-API.patch => 0587-Add-sendOpLevel-API.patch} (100%) rename patches/server/{0587-Add-StructureLocateEvent.patch => 0588-Add-StructureLocateEvent.patch} (100%) rename patches/server/{0588-Collision-option-for-requiring-a-player-participant.patch => 0589-Collision-option-for-requiring-a-player-participant.patch} (98%) rename patches/server/{0589-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch => 0590-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch} (100%) rename patches/server/{0590-Return-chat-component-with-empty-text-instead-of-thr.patch => 0591-Return-chat-component-with-empty-text-instead-of-thr.patch} (100%) rename patches/server/{0591-Make-schedule-command-per-world.patch => 0592-Make-schedule-command-per-world.patch} (100%) rename patches/server/{0592-Configurable-max-leash-distance.patch => 0593-Configurable-max-leash-distance.patch} (100%) rename patches/server/{0593-Implement-BlockPreDispenseEvent.patch => 0594-Implement-BlockPreDispenseEvent.patch} (95%) rename patches/server/{0594-Added-Vanilla-Entity-Tags.patch => 0595-Added-Vanilla-Entity-Tags.patch} (100%) rename patches/server/{0595-added-Wither-API.patch => 0596-added-Wither-API.patch} (100%) rename patches/server/{0596-Added-firing-of-PlayerChangeBeaconEffectEvent.patch => 0597-Added-firing-of-PlayerChangeBeaconEffectEvent.patch} (100%) rename patches/server/{0597-Fix-console-spam-when-removing-chests-in-water.patch => 0598-Fix-console-spam-when-removing-chests-in-water.patch} (100%) rename patches/server/{0598-Add-toggle-for-always-placing-the-dragon-egg.patch => 0599-Add-toggle-for-always-placing-the-dragon-egg.patch} (100%) rename patches/server/{0599-Added-PlayerStonecutterRecipeSelectEvent.patch => 0600-Added-PlayerStonecutterRecipeSelectEvent.patch} (100%) rename patches/server/{0600-Add-dropLeash-variable-to-EntityUnleashEvent.patch => 0601-Add-dropLeash-variable-to-EntityUnleashEvent.patch} (98%) rename patches/server/{0601-Skip-distance-map-update-when-spawning-disabled.patch => 0602-Skip-distance-map-update-when-spawning-disabled.patch} (100%) rename patches/server/{0602-Reset-shield-blocking-on-dimension-change.patch => 0603-Reset-shield-blocking-on-dimension-change.patch} (89%) rename patches/server/{0603-add-DragonEggFormEvent.patch => 0604-add-DragonEggFormEvent.patch} (100%) rename patches/server/{0604-EntityMoveEvent.patch => 0605-EntityMoveEvent.patch} (100%) rename patches/server/{0605-added-option-to-disable-pathfinding-updates-on-block.patch => 0606-added-option-to-disable-pathfinding-updates-on-block.patch} (100%) rename patches/server/{0606-Inline-shift-direction-fields.patch => 0607-Inline-shift-direction-fields.patch} (100%) rename patches/server/{0607-Allow-adding-items-to-BlockDropItemEvent.patch => 0608-Allow-adding-items-to-BlockDropItemEvent.patch} (95%) rename patches/server/{0608-Add-getMainThreadExecutor-to-BukkitScheduler.patch => 0609-Add-getMainThreadExecutor-to-BukkitScheduler.patch} (100%) rename patches/server/{0609-living-entity-allow-attribute-registration.patch => 0610-living-entity-allow-attribute-registration.patch} (100%) rename patches/server/{0610-fix-dead-slime-setSize-invincibility.patch => 0611-fix-dead-slime-setSize-invincibility.patch} (100%) rename patches/server/{0611-Merchant-getRecipes-should-return-an-immutable-list.patch => 0612-Merchant-getRecipes-should-return-an-immutable-list.patch} (100%) rename patches/server/{0612-misc-debugging-dumps.patch => 0613-misc-debugging-dumps.patch} (100%) rename patches/server/{0613-Add-support-for-hex-color-codes-in-console.patch => 0614-Add-support-for-hex-color-codes-in-console.patch} (100%) rename patches/server/{0614-Expose-Tracked-Players.patch => 0615-Expose-Tracked-Players.patch} (100%) rename patches/server/{0615-Remove-streams-from-SensorNearest.patch => 0616-Remove-streams-from-SensorNearest.patch} (100%) rename patches/server/{0616-MC-29274-Fix-Wither-hostility-towards-players.patch => 0617-MC-29274-Fix-Wither-hostility-towards-players.patch} (100%) rename patches/server/{0617-Throw-proper-exception-on-empty-JsonList-file.patch => 0618-Throw-proper-exception-on-empty-JsonList-file.patch} (100%) rename patches/server/{0618-Improve-ServerGUI.patch => 0619-Improve-ServerGUI.patch} (100%) rename patches/server/{0619-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch => 0620-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch} (100%) rename patches/server/{0620-fix-converting-txt-to-json-file.patch => 0621-fix-converting-txt-to-json-file.patch} (100%) rename patches/server/{0621-Add-worldborder-events.patch => 0622-Add-worldborder-events.patch} (100%) rename patches/server/{0622-added-PlayerNameEntityEvent.patch => 0623-added-PlayerNameEntityEvent.patch} (100%) rename patches/server/{0623-Prevent-grindstones-from-overstacking-items.patch => 0624-Prevent-grindstones-from-overstacking-items.patch} (100%) rename patches/server/{0624-Add-recipe-to-cook-events.patch => 0625-Add-recipe-to-cook-events.patch} (100%) rename patches/server/{0625-Add-Block-isValidTool.patch => 0626-Add-Block-isValidTool.patch} (100%) rename patches/server/{0626-Allow-using-signs-inside-spawn-protection.patch => 0627-Allow-using-signs-inside-spawn-protection.patch} (96%) rename patches/server/{0627-Implement-Keyed-on-World.patch => 0628-Implement-Keyed-on-World.patch} (100%) rename patches/server/{0628-Add-fast-alternative-constructor-for-Rotations.patch => 0629-Add-fast-alternative-constructor-for-Rotations.patch} (100%) rename patches/server/{0629-Item-Rarity-API.patch => 0630-Item-Rarity-API.patch} (100%) rename patches/server/{0630-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch => 0631-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch} (100%) rename patches/server/{0631-copy-TESign-isEditable-from-snapshots.patch => 0632-copy-TESign-isEditable-from-snapshots.patch} (100%) rename patches/server/{0632-Drop-carried-item-when-player-has-disconnected.patch => 0633-Drop-carried-item-when-player-has-disconnected.patch} (100%) rename patches/server/{0633-forced-whitelist-use-configurable-kick-message.patch => 0634-forced-whitelist-use-configurable-kick-message.patch} (100%) rename patches/server/{0634-Don-t-ignore-result-of-PlayerEditBookEvent.patch => 0635-Don-t-ignore-result-of-PlayerEditBookEvent.patch} (100%) rename patches/server/{0635-fix-cancelling-block-falling-causing-client-desync.patch => 0636-fix-cancelling-block-falling-causing-client-desync.patch} (100%) rename patches/server/{0636-Expose-protocol-version.patch => 0637-Expose-protocol-version.patch} (100%) rename patches/server/{0637-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch => 0638-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} (98%) rename patches/server/{0638-Enhance-console-tab-completions-for-brigadier-comman.patch => 0639-Enhance-console-tab-completions-for-brigadier-comman.patch} (100%) rename patches/server/{0639-Fix-PlayerItemConsumeEvent-cancelling-properly.patch => 0640-Fix-PlayerItemConsumeEvent-cancelling-properly.patch} (100%) rename patches/server/{0640-Add-bypass-host-check.patch => 0641-Add-bypass-host-check.patch} (100%) rename patches/server/{0641-Set-area-affect-cloud-rotation.patch => 0642-Set-area-affect-cloud-rotation.patch} (100%) rename patches/server/{0642-add-isDeeplySleeping-to-HumanEntity.patch => 0643-add-isDeeplySleeping-to-HumanEntity.patch} (100%) rename patches/server/{0643-Fix-duplicating-give-items-on-item-drop-cancel.patch => 0644-Fix-duplicating-give-items-on-item-drop-cancel.patch} (100%) rename patches/server/{0644-add-consumeFuel-to-FurnaceBurnEvent.patch => 0645-add-consumeFuel-to-FurnaceBurnEvent.patch} (100%) rename patches/server/{0645-add-get-set-drop-chance-to-EntityEquipment.patch => 0646-add-get-set-drop-chance-to-EntityEquipment.patch} (100%) rename patches/server/{0646-fix-PigZombieAngerEvent-cancellation.patch => 0647-fix-PigZombieAngerEvent-cancellation.patch} (100%) rename patches/server/{0647-Fix-checkReach-check-for-Shulker-boxes.patch => 0648-Fix-checkReach-check-for-Shulker-boxes.patch} (100%) rename patches/server/{0648-fix-PlayerItemHeldEvent-firing-twice.patch => 0649-fix-PlayerItemHeldEvent-firing-twice.patch} (93%) rename patches/server/{0649-Added-PlayerDeepSleepEvent.patch => 0650-Added-PlayerDeepSleepEvent.patch} (100%) rename patches/server/{0650-More-World-API.patch => 0651-More-World-API.patch} (100%) rename patches/server/{0651-Added-PlayerBedFailEnterEvent.patch => 0652-Added-PlayerBedFailEnterEvent.patch} (100%) rename patches/server/{0652-Implement-methods-to-convert-between-Component-and-B.patch => 0653-Implement-methods-to-convert-between-Component-and-B.patch} (100%) rename patches/server/{0653-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch => 0654-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch} (100%) rename patches/server/{0654-Introduce-beacon-activation-deactivation-events.patch => 0655-Introduce-beacon-activation-deactivation-events.patch} (100%) rename patches/server/{0655-add-RespawnFlags-to-PlayerRespawnEvent.patch => 0656-add-RespawnFlags-to-PlayerRespawnEvent.patch} (97%) rename patches/server/{0656-Add-Channel-initialization-listeners.patch => 0657-Add-Channel-initialization-listeners.patch} (100%) rename patches/server/{0657-Send-empty-commands-if-tab-completion-is-disabled.patch => 0658-Send-empty-commands-if-tab-completion-is-disabled.patch} (100%) rename patches/server/{0658-Add-more-WanderingTrader-API.patch => 0659-Add-more-WanderingTrader-API.patch} (100%) rename patches/server/{0659-Add-EntityBlockStorage-clearEntities.patch => 0660-Add-EntityBlockStorage-clearEntities.patch} (100%) rename patches/server/{0660-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch => 0661-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch} (100%) rename patches/server/{0661-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch => 0662-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch} (100%) rename patches/server/{0662-Inventory-close.patch => 0663-Inventory-close.patch} (100%) rename patches/server/{0663-call-PortalCreateEvent-players-and-end-platform.patch => 0664-call-PortalCreateEvent-players-and-end-platform.patch} (96%) rename patches/server/{0664-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch => 0665-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch} (100%) rename patches/server/{0665-Fix-CraftPotionBrewer-cache.patch => 0666-Fix-CraftPotionBrewer-cache.patch} (100%) rename patches/server/{0666-Add-basic-Datapack-API.patch => 0667-Add-basic-Datapack-API.patch} (100%) rename patches/server/{0667-Add-environment-variable-to-disable-server-gui.patch => 0668-Add-environment-variable-to-disable-server-gui.patch} (100%) rename patches/server/{0668-additions-to-PlayerGameModeChangeEvent.patch => 0669-additions-to-PlayerGameModeChangeEvent.patch} (97%) rename patches/server/{0669-ItemStack-repair-check-API.patch => 0670-ItemStack-repair-check-API.patch} (100%) rename patches/server/{0670-More-Enchantment-API.patch => 0671-More-Enchantment-API.patch} (100%) rename patches/server/{0671-Add-command-line-option-to-load-extra-plugin-jars-no.patch => 0672-Add-command-line-option-to-load-extra-plugin-jars-no.patch} (100%) rename patches/server/{0672-Fix-and-optimise-world-force-upgrading.patch => 0673-Fix-and-optimise-world-force-upgrading.patch} (100%) rename patches/server/{0673-Add-Mob-lookAt-API.patch => 0674-Add-Mob-lookAt-API.patch} (100%) rename patches/server/{0674-Add-Unix-domain-socket-support.patch => 0675-Add-Unix-domain-socket-support.patch} (100%) rename patches/server/{0675-Add-EntityInsideBlockEvent.patch => 0676-Add-EntityInsideBlockEvent.patch} (99%) rename patches/server/{0676-Attributes-API-for-item-defaults.patch => 0677-Attributes-API-for-item-defaults.patch} (100%) rename patches/server/{0677-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch => 0678-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch} (100%) rename patches/server/{0678-Add-cause-to-Weather-ThunderChangeEvents.patch => 0679-Add-cause-to-Weather-ThunderChangeEvents.patch} (100%) rename patches/server/{0679-More-Lidded-Block-API.patch => 0680-More-Lidded-Block-API.patch} (100%) rename patches/server/{0680-Limit-item-frame-cursors-on-maps.patch => 0681-Limit-item-frame-cursors-on-maps.patch} (100%) rename patches/server/{0681-Add-PufferFishStateChangeEvent.patch => 0682-Add-PufferFishStateChangeEvent.patch} (100%) rename patches/server/{0682-Add-PlayerKickEvent-causes.patch => 0683-Add-PlayerKickEvent-causes.patch} (99%) rename patches/server/{0683-Fix-PlayerBucketEmptyEvent-result-itemstack.patch => 0684-Fix-PlayerBucketEmptyEvent-result-itemstack.patch} (100%) rename patches/server/{0684-Add-option-to-fix-items-merging-through-walls.patch => 0685-Add-option-to-fix-items-merging-through-walls.patch} (100%) rename patches/server/{0685-Add-BellRevealRaiderEvent.patch => 0686-Add-BellRevealRaiderEvent.patch} (100%) rename patches/server/{0686-Fix-invulnerable-end-crystals.patch => 0687-Fix-invulnerable-end-crystals.patch} (100%) rename patches/server/{0687-Add-ElderGuardianAppearanceEvent.patch => 0688-Add-ElderGuardianAppearanceEvent.patch} (100%) rename patches/server/{0688-Reset-villager-inventory-on-cancelled-pickup-event.patch => 0689-Reset-villager-inventory-on-cancelled-pickup-event.patch} (96%) rename patches/server/{0689-Fix-dangerous-end-portal-logic.patch => 0690-Fix-dangerous-end-portal-logic.patch} (100%) rename patches/server/{0690-Make-item-validations-configurable.patch => 0691-Make-item-validations-configurable.patch} (100%) rename patches/server/{0691-Add-more-line-of-sight-methods.patch => 0692-Add-more-line-of-sight-methods.patch} (100%) rename patches/server/{0692-add-per-world-spawn-limits.patch => 0693-add-per-world-spawn-limits.patch} (100%) rename patches/server/{0693-Fix-PotionSplashEvent-for-water-splash-potions.patch => 0694-Fix-PotionSplashEvent-for-water-splash-potions.patch} (100%) diff --git a/patches/removed/1.17/0517-Remove-some-streams-from-structures.patch b/patches/removed/1.17/0517-Remove-some-streams-from-structures.patch deleted file mode 100644 index 6587728a2f..0000000000 --- a/patches/removed/1.17/0517-Remove-some-streams-from-structures.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Mon, 29 Jun 2020 17:03:06 -0400 -Subject: [PATCH] Remove some streams from structures - -This showed up a lot in the spark profiler, should have a low-medium performance improvement. - -Update 1.17: looks like some things in here have been moved to some weird beardifier - has to be investigated further -diff --git a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java -index e842dbc586234799a05b6df213b686e17b8ed1ac..2f88e015708cadb43a348ba2b144c3dd92bb95a5 100644 ---- a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java -+++ b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java -@@ -2,21 +2,22 @@ - package net.minecraft.world.level; - - import com.mojang.datafixers.DataFixUtils; -+import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper - import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; - import net.minecraft.core.SectionPos; --import net.minecraft.core.Vec3i; - import net.minecraft.server.level.WorldGenRegion; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.FeatureAccess; - import net.minecraft.world.level.levelgen.WorldGenSettings; - import net.minecraft.world.level.levelgen.feature.StructureFeature; -+import net.minecraft.world.level.levelgen.structure.StructurePiece; - import net.minecraft.world.level.levelgen.structure.StructureStart; - - public class StructureFeatureManager { - -- private final LevelAccessor level; -+ private final LevelAccessor level; public LevelAccessor getLevel() { return level; } // Paper - OBFHELPER - private final WorldGenSettings worldGenSettings; - - public StructureFeatureManager(LevelAccessor world, WorldGenSettings options) { -@@ -42,6 +43,20 @@ public class StructureFeatureManager { - }); - } - -+ // Paper start - remove structure streams -+ public java.util.List> getFeatureStarts(SectionPos sectionPosition, StructureFeature structureGenerator) { -+ java.util.List> list = new ObjectArrayList<>(); -+ for (Long curLong: getLevel().getChunk(sectionPosition.x(), sectionPosition.z(), ChunkStatus.STRUCTURE_REFERENCES).getReferencesForFeature(structureGenerator)) { -+ SectionPos sectionPosition1 = SectionPos.of(new ChunkPos(curLong), 0); -+ StructureStart structurestart = getStartForFeature(sectionPosition1, structureGenerator, getLevel().getChunk(sectionPosition1.x(), sectionPosition1.z(), ChunkStatus.STRUCTURE_STARTS)); -+ if (structurestart != null && structurestart.e()) { -+ list.add(structurestart); -+ } -+ } -+ return list; -+ } -+ // Paper end -+ - @Nullable - public StructureStart getStartForFeature(SectionPos pos, StructureFeature feature, FeatureAccess holder) { - return holder.getStartForFeature(feature); -@@ -60,13 +75,21 @@ public class StructureFeatureManager { - } - - public StructureStart getStructureAt(BlockPos pos, boolean matchChildren, StructureFeature feature) { -- return (StructureStart) DataFixUtils.orElse(this.startsForFeature(SectionPos.of(pos), feature).filter((structurestart) -> { -- return structurestart.c().b((Vec3i) pos); -- }).filter((structurestart) -> { -- return !matchChildren || structurestart.d().stream().anyMatch((structurepiece) -> { -- return structurepiece.g().b((BaseBlockPosition) blockposition); -- }); -- }).findFirst(), StructureStart.a); -+ // Paper start - remove structure streams -+ for (StructureStart structurestart : getFeatureStarts(SectionPos.of(pos), feature)) { -+ if (structurestart.c().b(pos)) { -+ if (!matchChildren) { -+ return structurestart; -+ } -+ for (StructurePiece structurepiece : structurestart.d()) { -+ if (structurepiece.g().b(pos)) { -+ return structurestart; -+ } -+ } -+ } -+ } -+ return StructureStart.a; -+ // Paper end - } - - // Spigot start -diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java -index ed83335175bb882741dfaef251ab30ce1590f74c..2422dbb8691b8c45401a68602a33d4d7f1718dfb 100644 ---- a/src/main/java/net/minecraft/world/level/biome/Biome.java -+++ b/src/main/java/net/minecraft/world/level/biome/Biome.java -@@ -39,6 +39,7 @@ import net.minecraft.world.level.levelgen.WorldgenRandom; - import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; - import net.minecraft.world.level.levelgen.feature.StructureFeature; - import net.minecraft.world.level.levelgen.structure.BoundingBox; -+import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder; - import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise; - import net.minecraft.world.level.material.FluidState; -@@ -238,9 +239,11 @@ public final class Biome { - int l1 = j1 << 4; - - try { -- structureAccessor.startsForFeature(SectionPos.of(pos), structuregenerator).forEach((structurestart) -> { -- structurestart.a(region, structureAccessor, chunkGenerator, random, new BoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkPos(i1, j1)); -- }); -+ // Paper start - remove structure streams -+ for (StructureStart structureStart : structureAccessor.getFeatureStarts(SectionPos.of(pos), structuregenerator)) { -+ structureStart.a(region, structureAccessor, chunkGenerator, random, new BoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkPos(i1, j1)); -+ } -+ // Paper end - } catch (Exception exception) { - CrashReport crashreport = CrashReport.forThrowable(exception, "Feature placement"); - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -index 04adec255e4650ead8d80bee32a681c98686fb95..20f3899b7e39033ebc0f833e75fbdba29777a168 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -@@ -41,6 +41,7 @@ import net.minecraft.world.level.levelgen.feature.structures.StructureTemplatePo - import net.minecraft.world.level.levelgen.structure.BoundingBox; - import net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece; - import net.minecraft.world.level.levelgen.structure.StructurePiece; -+import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.synth.ImprovedNoise; - import net.minecraft.world.level.levelgen.synth.PerlinNoise; - import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise; -@@ -455,7 +456,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - while (iterator.hasNext()) { - StructureFeature structuregenerator = (StructureFeature) iterator.next(); - -- accessor.startsForFeature(SectionPos.of(chunkcoordintpair, 0), structuregenerator).forEach((structurestart) -> { -+ for (StructureStart structurestart : accessor.getFeatureStarts(SectionPos.of(chunkcoordintpair, 0), structuregenerator)) { // Paper - remove structure streams - Iterator iterator1 = structurestart.d().iterator(); - - while (iterator1.hasNext()) { -@@ -487,7 +488,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - } - } - -- }); -+ } // Paper - remove structure streams - } - - double[][][] adouble = new double[2][this.chunkCountZ + 1][this.chunkCountY + 1]; diff --git a/patches/server/0470-Remove-some-streams-from-structures.patch b/patches/server/0470-Remove-some-streams-from-structures.patch new file mode 100644 index 0000000000..072f341f2a --- /dev/null +++ b/patches/server/0470-Remove-some-streams-from-structures.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JRoy +Date: Mon, 29 Jun 2020 17:03:06 -0400 +Subject: [PATCH] Remove some streams from structures + +This showed up a lot in the spark profiler, should have a low-medium performance improvement. + +diff --git a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java +index 21f67cf20dede30a056a7807a0e7338e858da142..9a8e44fb3b1cffec3f70c9812c80175bd07f10e2 100644 +--- a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java ++++ b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java +@@ -45,6 +45,20 @@ public class StructureFeatureManager { + }); + } + ++ // Paper start - remove structure streams - based on method above ++ public java.util.List> streamlessStartsForFeature(SectionPos sectionPosition, StructureFeature structureGenerator) { ++ java.util.List> list = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); ++ for (Long curLong : this.level.getChunk(sectionPosition.x(), sectionPosition.z(), ChunkStatus.STRUCTURE_REFERENCES).getReferencesForFeature(structureGenerator)) { ++ SectionPos sectionPosition1 = SectionPos.of(new ChunkPos(curLong), 0); ++ StructureStart structurestart = getStartForFeature(sectionPosition1, structureGenerator, this.level.getChunk(sectionPosition1.x(), sectionPosition1.z(), ChunkStatus.STRUCTURE_STARTS)); ++ if (structurestart != null && structurestart.isValid()) { ++ list.add(structurestart); ++ } ++ } ++ return list; ++ } ++ // Paper end ++ + @Nullable + public StructureStart getStartForFeature(SectionPos pos, StructureFeature feature, FeatureAccess holder) { + return holder.getStartForFeature(feature); +@@ -63,11 +77,20 @@ public class StructureFeatureManager { + } + + public StructureStart getStructureAt(BlockPos pos, boolean matchChildren, StructureFeature feature) { +- return (StructureStart) DataFixUtils.orElse(this.startsForFeature(SectionPos.of(pos), feature).filter((structurestart) -> { +- return matchChildren ? structurestart.getPieces().stream().anyMatch((structurepiece) -> { +- return structurepiece.getBoundingBox().isInside((Vec3i) pos); +- }) : structurestart.getBoundingBox().isInside((Vec3i) pos); +- }).findFirst(), StructureStart.INVALID_START); ++ // Paper start - remove structure streams ++ for (StructureStart structureStart : streamlessStartsForFeature(SectionPos.of(pos), feature)) { ++ if (matchChildren) { ++ for (net.minecraft.world.level.levelgen.structure.StructurePiece piece : structureStart.getPieces()) { ++ if (piece.getBoundingBox().isInside(pos)) { ++ return structureStart; ++ } ++ } ++ } else if (structureStart.getBoundingBox().isInside(pos)) { ++ return structureStart; ++ } ++ } ++ return StructureStart.INVALID_START; ++ // Paper end + } + + // Spigot start +diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java +index 3f3b4e4ea8231fdcc799bd9de3e20747a5634603..a7a7e6cd87270e64a92448f03f8b0b0c7e375ec7 100644 +--- a/src/main/java/net/minecraft/world/level/biome/Biome.java ++++ b/src/main/java/net/minecraft/world/level/biome/Biome.java +@@ -44,6 +44,7 @@ import net.minecraft.world.level.levelgen.WorldgenRandom; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.levelgen.feature.StructureFeature; + import net.minecraft.world.level.levelgen.structure.BoundingBox; ++import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder; + import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise; + import net.minecraft.world.level.material.FluidState; +@@ -241,9 +242,11 @@ public final class Biome { + int p = region.getMinBuildHeight() + 1; + int q = region.getMaxBuildHeight() - 1; + region.setCurrentlyGenerating(supplier); +- structureAccessor.startsForFeature(SectionPos.of(origin), structureFeature).forEach((structureStart) -> { ++ // Paper start - remove structure streams ++ for (StructureStart structureStart : structureAccessor.streamlessStartsForFeature(SectionPos.of(origin), structureFeature)) { + structureStart.placeInChunk(region, structureAccessor, chunkGenerator, random, new BoundingBox(n, p, o, n + 15, q, o + 15), new ChunkPos(l, m)); +- }); ++ } ++ // Paper end + } catch (Exception var24) { + CrashReport crashReport = CrashReport.forThrowable(var24, "Feature placement"); + crashReport.addCategory("Feature").setDetail("Description", supplier::get); +diff --git a/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java b/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java +index ed3bfe13d0e3835ce0dbe3ae5af8cd22a7ea25e6..c52d1a23a0f0bdde062f73a435bc6b9cef51c437 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java +@@ -44,7 +44,7 @@ public class Beardifier { + this.rigids = new ObjectArrayList<>(10); + + for(StructureFeature structureFeature : StructureFeature.NOISE_AFFECTING_FEATURES) { +- accessor.startsForFeature(SectionPos.bottomOf(chunk), structureFeature).forEach((start) -> { ++ for (net.minecraft.world.level.levelgen.structure.StructureStart start : accessor.streamlessStartsForFeature(SectionPos.of(chunkPos, 0), structureFeature)) { // Paper - remove structure streams + for(StructurePiece structurePiece : start.getPieces()) { + if (structurePiece.isCloseToChunk(chunkPos, 12)) { + if (structurePiece instanceof PoolElementStructurePiece) { +@@ -67,7 +67,7 @@ public class Beardifier { + } + } + +- }); ++ } // Paper - remove structure streams + } + + this.pieceIterator = this.rigids.iterator(); diff --git a/patches/server/0470-Remove-streams-from-classes-related-villager-gossip.patch b/patches/server/0471-Remove-streams-from-classes-related-villager-gossip.patch similarity index 100% rename from patches/server/0470-Remove-streams-from-classes-related-villager-gossip.patch rename to patches/server/0471-Remove-streams-from-classes-related-villager-gossip.patch diff --git a/patches/server/0471-Support-components-in-ItemMeta.patch b/patches/server/0472-Support-components-in-ItemMeta.patch similarity index 100% rename from patches/server/0471-Support-components-in-ItemMeta.patch rename to patches/server/0472-Support-components-in-ItemMeta.patch diff --git a/patches/server/0472-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/patches/server/0473-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch similarity index 100% rename from patches/server/0472-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch rename to patches/server/0473-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch diff --git a/patches/server/0473-Add-entity-liquid-API.patch b/patches/server/0474-Add-entity-liquid-API.patch similarity index 96% rename from patches/server/0473-Add-entity-liquid-API.patch rename to patches/server/0474-Add-entity-liquid-API.patch index 81e7a4809c..3600a0f8a8 100644 --- a/patches/server/0473-Add-entity-liquid-API.patch +++ b/patches/server/0474-Add-entity-liquid-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add entity liquid API diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 96da70f1077f70c4bd5ba1196292a856deb25286..466de2bbdbf0c9e3ed28ec8fee5fcfeb75c54398 100644 +index 28f9b58c379306138f1528d91f2112c21ae9cb0a..0f37c205fe401126a19191fb5382cc1b4d3f43b4 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1305,13 +1305,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0474-Update-itemstack-legacy-name-and-lore.patch b/patches/server/0475-Update-itemstack-legacy-name-and-lore.patch similarity index 100% rename from patches/server/0474-Update-itemstack-legacy-name-and-lore.patch rename to patches/server/0475-Update-itemstack-legacy-name-and-lore.patch diff --git a/patches/server/0475-Spawn-player-in-correct-world-on-login.patch b/patches/server/0476-Spawn-player-in-correct-world-on-login.patch similarity index 100% rename from patches/server/0475-Spawn-player-in-correct-world-on-login.patch rename to patches/server/0476-Spawn-player-in-correct-world-on-login.patch diff --git a/patches/server/0476-Add-PrepareResultEvent.patch b/patches/server/0477-Add-PrepareResultEvent.patch similarity index 98% rename from patches/server/0476-Add-PrepareResultEvent.patch rename to patches/server/0477-Add-PrepareResultEvent.patch index 53d3c6585c..77eb7d1ebf 100644 --- a/patches/server/0476-Add-PrepareResultEvent.patch +++ b/patches/server/0477-Add-PrepareResultEvent.patch @@ -106,7 +106,7 @@ index ddd34b07f7cf39a8b5ad51bdefb6e9d7cbf8f393..eac9765ecf0b33cab8b04204591de8d5 private void setupRecipeList(Container input, ItemStack stack) { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index d4b8035160332d98c37918f62ee9e0d630e23ee8..fc9c63b73211d05321776648d6ba9c54f14ba83d 100644 +index e508f75158423e8c4a59af18a094dfa36b9c180c..ff5d9baa5f961a6be7d5d73bfb78cb5de1b8cfe9 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -1529,19 +1529,44 @@ public class CraftEventFactory { diff --git a/patches/server/0477-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/0478-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 97% rename from patches/server/0477-Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/server/0478-Allow-delegation-to-vanilla-chunk-gen.patch index 287d85372d..840cdeb9ac 100644 --- a/patches/server/0477-Allow-delegation-to-vanilla-chunk-gen.patch +++ b/patches/server/0478-Allow-delegation-to-vanilla-chunk-gen.patch @@ -42,7 +42,7 @@ index 6bc5ba51c90723c7138b1b5d2381cb215f1e5271..beb8b7d06ef47c80ede95c884598fedc public BossBar createBossBar(String title, BarColor color, BarStyle style, BarFlag... flags) { return new CraftBossBar(title, color, style, flags); diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index 7f8d9e82c1fadc0621f6e94adbc31f7774f9568f..2f0849dd05605e693dcc12c3d0842e8dfa53a869 100644 +index 3d905c98704da64cefd009b2c796b24e729396a5..6e8018241664d2cc2a6a8d52d87946740ac8bb97 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java @@ -20,7 +20,7 @@ import org.bukkit.material.MaterialData; diff --git a/patches/server/0478-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server/0479-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch similarity index 100% rename from patches/server/0478-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch rename to patches/server/0479-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch diff --git a/patches/server/0479-Optimize-NetworkManager-Exception-Handling.patch b/patches/server/0480-Optimize-NetworkManager-Exception-Handling.patch similarity index 100% rename from patches/server/0479-Optimize-NetworkManager-Exception-Handling.patch rename to patches/server/0480-Optimize-NetworkManager-Exception-Handling.patch diff --git a/patches/server/0480-Optimize-the-advancement-data-player-iteration-to-be.patch b/patches/server/0481-Optimize-the-advancement-data-player-iteration-to-be.patch similarity index 100% rename from patches/server/0480-Optimize-the-advancement-data-player-iteration-to-be.patch rename to patches/server/0481-Optimize-the-advancement-data-player-iteration-to-be.patch diff --git a/patches/server/0481-Fix-arrows-never-despawning-MC-125757.patch b/patches/server/0482-Fix-arrows-never-despawning-MC-125757.patch similarity index 100% rename from patches/server/0481-Fix-arrows-never-despawning-MC-125757.patch rename to patches/server/0482-Fix-arrows-never-despawning-MC-125757.patch diff --git a/patches/server/0482-Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server/0483-Thread-Safe-Vanilla-Command-permission-checking.patch similarity index 100% rename from patches/server/0482-Thread-Safe-Vanilla-Command-permission-checking.patch rename to patches/server/0483-Thread-Safe-Vanilla-Command-permission-checking.patch diff --git a/patches/server/0483-Move-range-check-for-block-placing-up.patch b/patches/server/0484-Move-range-check-for-block-placing-up.patch similarity index 96% rename from patches/server/0483-Move-range-check-for-block-placing-up.patch rename to patches/server/0484-Move-range-check-for-block-placing-up.patch index 4614ed8f8f..dc297131fb 100644 --- a/patches/server/0483-Move-range-check-for-block-placing-up.patch +++ b/patches/server/0484-Move-range-check-for-block-placing-up.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Move range check for block placing up diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 2b8a9d16add3ac81ede029a909a40feaa07c51d3..afd5f5efdd6b47811fdbc23adeacace594602046 100644 +index 91a06e1ac325fe80aaadaf213d40495f4ce15e53..d1574bf0a326212898378b72b44c1b08e633dc27 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1694,17 +1694,21 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0484-Fix-SPIGOT-5989.patch b/patches/server/0485-Fix-SPIGOT-5989.patch similarity index 100% rename from patches/server/0484-Fix-SPIGOT-5989.patch rename to patches/server/0485-Fix-SPIGOT-5989.patch diff --git a/patches/server/0485-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/patches/server/0486-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch similarity index 100% rename from patches/server/0485-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch rename to patches/server/0486-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch diff --git a/patches/server/0486-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/patches/server/0487-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch similarity index 100% rename from patches/server/0486-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch rename to patches/server/0487-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch diff --git a/patches/server/0487-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/patches/server/0488-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch similarity index 100% rename from patches/server/0487-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch rename to patches/server/0488-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch diff --git a/patches/server/0488-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/patches/server/0489-Add-missing-strikeLighting-call-to-World-spigot-stri.patch similarity index 100% rename from patches/server/0488-Add-missing-strikeLighting-call-to-World-spigot-stri.patch rename to patches/server/0489-Add-missing-strikeLighting-call-to-World-spigot-stri.patch diff --git a/patches/server/0489-Fix-some-rails-connecting-improperly.patch b/patches/server/0490-Fix-some-rails-connecting-improperly.patch similarity index 100% rename from patches/server/0489-Fix-some-rails-connecting-improperly.patch rename to patches/server/0490-Fix-some-rails-connecting-improperly.patch diff --git a/patches/server/0490-Incremental-player-saving.patch b/patches/server/0491-Incremental-player-saving.patch similarity index 98% rename from patches/server/0490-Incremental-player-saving.patch rename to patches/server/0491-Incremental-player-saving.patch index cc01e08383..d2651f5fda 100644 --- a/patches/server/0490-Incremental-player-saving.patch +++ b/patches/server/0491-Incremental-player-saving.patch @@ -55,7 +55,7 @@ index 1feda8b44364c748497174944b26abc4f058f354..1889de77a5e3d9371005b6bd451e2c0e } // Paper start for (ServerLevel level : this.getAllLevels()) { diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index b106a972a76e856d6cdab78dec5daef77b135f98..de50d3de98490b5620a085c1af7fb100b8b8ad99 100644 +index 2bf25f90f760c1a5ee025a0ebaaccd9285a4db7f..fb56655df35c8a2cee8f5c4bb47a155054d850f8 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -169,6 +169,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0491-Fix-MC-187716-Use-configured-height.patch b/patches/server/0492-Fix-MC-187716-Use-configured-height.patch similarity index 100% rename from patches/server/0491-Fix-MC-187716-Use-configured-height.patch rename to patches/server/0492-Fix-MC-187716-Use-configured-height.patch diff --git a/patches/server/0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/patches/server/0493-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch similarity index 100% rename from patches/server/0492-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch rename to patches/server/0493-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch diff --git a/patches/server/0493-Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server/0494-Do-not-let-the-server-load-chunks-from-newer-version.patch similarity index 100% rename from patches/server/0493-Do-not-let-the-server-load-chunks-from-newer-version.patch rename to patches/server/0494-Do-not-let-the-server-load-chunks-from-newer-version.patch diff --git a/patches/server/0494-Brand-support.patch b/patches/server/0495-Brand-support.patch similarity index 97% rename from patches/server/0494-Brand-support.patch rename to patches/server/0495-Brand-support.patch index 148208218a..ea3f01793c 100644 --- a/patches/server/0494-Brand-support.patch +++ b/patches/server/0495-Brand-support.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Brand support diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index afd5f5efdd6b47811fdbc23adeacace594602046..30cdacbefb07c7b3e7d64cbb78ff821a5f6c7567 100644 +index d1574bf0a326212898378b72b44c1b08e633dc27..d7c0d82eecb6c601a0ef038ec970a3b657691107 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -4,6 +4,7 @@ import com.google.common.collect.Lists; diff --git a/patches/server/0495-Add-setMaxPlayers-API.patch b/patches/server/0496-Add-setMaxPlayers-API.patch similarity index 100% rename from patches/server/0495-Add-setMaxPlayers-API.patch rename to patches/server/0496-Add-setMaxPlayers-API.patch diff --git a/patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server/0497-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from patches/server/0496-Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/server/0497-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/patches/server/0497-Don-t-require-FACING-data.patch b/patches/server/0498-Don-t-require-FACING-data.patch similarity index 100% rename from patches/server/0497-Don-t-require-FACING-data.patch rename to patches/server/0498-Don-t-require-FACING-data.patch diff --git a/patches/server/0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server/0499-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch similarity index 100% rename from patches/server/0498-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch rename to patches/server/0499-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch diff --git a/patches/server/0499-Add-moon-phase-API.patch b/patches/server/0500-Add-moon-phase-API.patch similarity index 100% rename from patches/server/0499-Add-moon-phase-API.patch rename to patches/server/0500-Add-moon-phase-API.patch diff --git a/patches/server/0500-Prevent-headless-pistons-from-being-created.patch b/patches/server/0501-Prevent-headless-pistons-from-being-created.patch similarity index 100% rename from patches/server/0500-Prevent-headless-pistons-from-being-created.patch rename to patches/server/0501-Prevent-headless-pistons-from-being-created.patch diff --git a/patches/server/0501-Add-BellRingEvent.patch b/patches/server/0502-Add-BellRingEvent.patch similarity index 100% rename from patches/server/0501-Add-BellRingEvent.patch rename to patches/server/0502-Add-BellRingEvent.patch diff --git a/patches/server/0502-Add-zombie-targets-turtle-egg-config.patch b/patches/server/0503-Add-zombie-targets-turtle-egg-config.patch similarity index 100% rename from patches/server/0502-Add-zombie-targets-turtle-egg-config.patch rename to patches/server/0503-Add-zombie-targets-turtle-egg-config.patch diff --git a/patches/server/0503-Buffer-joins-to-world.patch b/patches/server/0504-Buffer-joins-to-world.patch similarity index 100% rename from patches/server/0503-Buffer-joins-to-world.patch rename to patches/server/0504-Buffer-joins-to-world.patch diff --git a/patches/server/0504-Optimize-redstone-algorithm.patch b/patches/server/0505-Optimize-redstone-algorithm.patch similarity index 100% rename from patches/server/0504-Optimize-redstone-algorithm.patch rename to patches/server/0505-Optimize-redstone-algorithm.patch diff --git a/patches/server/0505-Fix-hex-colors-not-working-in-some-kick-messages.patch b/patches/server/0506-Fix-hex-colors-not-working-in-some-kick-messages.patch similarity index 100% rename from patches/server/0505-Fix-hex-colors-not-working-in-some-kick-messages.patch rename to patches/server/0506-Fix-hex-colors-not-working-in-some-kick-messages.patch diff --git a/patches/server/0506-PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server/0507-PortalCreateEvent-needs-to-know-its-entity.patch similarity index 100% rename from patches/server/0506-PortalCreateEvent-needs-to-know-its-entity.patch rename to patches/server/0507-PortalCreateEvent-needs-to-know-its-entity.patch diff --git a/patches/server/0507-Fix-CraftTeam-null-check.patch b/patches/server/0508-Fix-CraftTeam-null-check.patch similarity index 100% rename from patches/server/0507-Fix-CraftTeam-null-check.patch rename to patches/server/0508-Fix-CraftTeam-null-check.patch diff --git a/patches/server/0508-Add-more-Evoker-API.patch b/patches/server/0509-Add-more-Evoker-API.patch similarity index 100% rename from patches/server/0508-Add-more-Evoker-API.patch rename to patches/server/0509-Add-more-Evoker-API.patch diff --git a/patches/server/0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/server/0510-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 100% rename from patches/server/0509-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to patches/server/0510-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch diff --git a/patches/server/0510-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server/0511-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 100% rename from patches/server/0510-Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/server/0511-Create-HoverEvent-from-ItemStack-Entity.patch diff --git a/patches/server/0511-Cache-block-data-strings.patch b/patches/server/0512-Cache-block-data-strings.patch similarity index 100% rename from patches/server/0511-Cache-block-data-strings.patch rename to patches/server/0512-Cache-block-data-strings.patch diff --git a/patches/server/0512-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/patches/server/0513-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch similarity index 96% rename from patches/server/0512-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch rename to patches/server/0513-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch index dd9aef6436..8599c641f4 100644 --- a/patches/server/0512-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch +++ b/patches/server/0513-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch @@ -9,7 +9,7 @@ as this is how Vanilla teleports entities. Cancel any pending motion when teleported. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 30cdacbefb07c7b3e7d64cbb78ff821a5f6c7567..1a085522026d6a7d549ca9975e02336bcd495aa4 100644 +index d7c0d82eecb6c601a0ef038ec970a3b657691107..5b923254ea7c8106e4ce9f7792c9c044ab06acc9 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -682,7 +682,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @@ -31,7 +31,7 @@ index 30cdacbefb07c7b3e7d64cbb78ff821a5f6c7567..1a085522026d6a7d549ca9975e02336b this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport, flag)); } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 466de2bbdbf0c9e3ed28ec8fee5fcfeb75c54398..a9c90e41af1cc67a88a639dc795dd8023a7acb89 100644 +index 0f37c205fe401126a19191fb5382cc1b4d3f43b4..b964efb6afb090ffec505493e9bbbb88ba3efd9d 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -152,6 +152,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0513-Add-additional-open-container-api-to-HumanEntity.patch b/patches/server/0514-Add-additional-open-container-api-to-HumanEntity.patch similarity index 100% rename from patches/server/0513-Add-additional-open-container-api-to-HumanEntity.patch rename to patches/server/0514-Add-additional-open-container-api-to-HumanEntity.patch diff --git a/patches/server/0514-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/patches/server/0515-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch similarity index 100% rename from patches/server/0514-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch rename to patches/server/0515-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch diff --git a/patches/server/0515-Extend-block-drop-capture-to-capture-all-items-added.patch b/patches/server/0516-Extend-block-drop-capture-to-capture-all-items-added.patch similarity index 100% rename from patches/server/0515-Extend-block-drop-capture-to-capture-all-items-added.patch rename to patches/server/0516-Extend-block-drop-capture-to-capture-all-items-added.patch diff --git a/patches/server/0516-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server/0517-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch similarity index 100% rename from patches/server/0516-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch rename to patches/server/0517-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch diff --git a/patches/server/0517-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server/0518-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 94% rename from patches/server/0517-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to patches/server/0518-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch index 64a555e00d..1500ec007e 100644 --- a/patches/server/0517-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ b/patches/server/0518-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a9c90e41af1cc67a88a639dc795dd8023a7acb89..dac4585ba1bfc782b3e381dfba0a1b9abbb6a2d7 100644 +index b964efb6afb090ffec505493e9bbbb88ba3efd9d..2de83f4f507c87347b58ba2102a87bbb2d7ceb7b 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -3904,4 +3904,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0518-Lazily-track-plugin-scoreboards-by-default.patch b/patches/server/0519-Lazily-track-plugin-scoreboards-by-default.patch similarity index 100% rename from patches/server/0518-Lazily-track-plugin-scoreboards-by-default.patch rename to patches/server/0519-Lazily-track-plugin-scoreboards-by-default.patch diff --git a/patches/server/0519-Entity-isTicking.patch b/patches/server/0520-Entity-isTicking.patch similarity index 95% rename from patches/server/0519-Entity-isTicking.patch rename to patches/server/0520-Entity-isTicking.patch index cf77947417..0ddc485993 100644 --- a/patches/server/0519-Entity-isTicking.patch +++ b/patches/server/0520-Entity-isTicking.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Entity#isTicking diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index dac4585ba1bfc782b3e381dfba0a1b9abbb6a2d7..d1199a166dfc88722e13dbdfeb86d9c89e7e8513 100644 +index 2de83f4f507c87347b58ba2102a87bbb2d7ceb7b..15b48d9e6caf8d28438e161dcf2c1499e938984c 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -52,6 +52,7 @@ import net.minecraft.resources.ResourceKey; diff --git a/patches/server/0520-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/patches/server/0521-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch similarity index 100% rename from patches/server/0520-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch rename to patches/server/0521-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch diff --git a/patches/server/0521-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/patches/server/0522-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch similarity index 89% rename from patches/server/0521-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch rename to patches/server/0522-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch index c2938746f9..d082581820 100644 --- a/patches/server/0521-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch +++ b/patches/server/0522-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix CME on adding a passenger in CreatureSpawnEvent diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d1199a166dfc88722e13dbdfeb86d9c89e7e8513..d64caca72a5302392df944d4c60ed2ba79a19ee7 100644 +index 15b48d9e6caf8d28438e161dcf2c1499e938984c..c3b05e73f9f42bdc2ab5d43fa905dd4cf5e39440 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -3413,7 +3413,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0522-Reset-Ender-Crystals-on-Dragon-Spawn.patch b/patches/server/0523-Reset-Ender-Crystals-on-Dragon-Spawn.patch similarity index 100% rename from patches/server/0522-Reset-Ender-Crystals-on-Dragon-Spawn.patch rename to patches/server/0523-Reset-Ender-Crystals-on-Dragon-Spawn.patch diff --git a/patches/server/0523-Fix-for-large-move-vectors-crashing-server.patch b/patches/server/0524-Fix-for-large-move-vectors-crashing-server.patch similarity index 97% rename from patches/server/0523-Fix-for-large-move-vectors-crashing-server.patch rename to patches/server/0524-Fix-for-large-move-vectors-crashing-server.patch index a1a4688c67..e95f85d441 100644 --- a/patches/server/0523-Fix-for-large-move-vectors-crashing-server.patch +++ b/patches/server/0524-Fix-for-large-move-vectors-crashing-server.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Fix for large move vectors crashing server Check movement distance also based on current position. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 1a085522026d6a7d549ca9975e02336bcd495aa4..1fffa32bd193fa122c7f7b5381f57975c2e895fe 100644 +index 5b923254ea7c8106e4ce9f7792c9c044ab06acc9..70f82d410dd12d4f162ff38f7222f9d099e11e1f 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -507,19 +507,24 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0524-Optimise-getType-calls.patch b/patches/server/0525-Optimise-getType-calls.patch similarity index 98% rename from patches/server/0524-Optimise-getType-calls.patch rename to patches/server/0525-Optimise-getType-calls.patch index 714fa391ab..e67e76e8d0 100644 --- a/patches/server/0524-Optimise-getType-calls.patch +++ b/patches/server/0525-Optimise-getType-calls.patch @@ -80,7 +80,7 @@ index 6dc8f9f269db6971b8b46819e017357899ccd118..7f49c7c7048b5778f20ddce1d844d4b3 public BlockState getState() { diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index 2f0849dd05605e693dcc12c3d0842e8dfa53a869..612241ad511cb515fe28c69452c66efcfe62bd7e 100644 +index 6e8018241664d2cc2a6a8d52d87946740ac8bb97..8038fe792533617023e9667fa2763ce98975318c 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java @@ -75,7 +75,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { diff --git a/patches/server/0525-Villager-resetOffers.patch b/patches/server/0526-Villager-resetOffers.patch similarity index 100% rename from patches/server/0525-Villager-resetOffers.patch rename to patches/server/0526-Villager-resetOffers.patch diff --git a/patches/server/0526-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/patches/server/0527-Improve-inlinig-for-some-hot-IBlockData-methods.patch similarity index 100% rename from patches/server/0526-Improve-inlinig-for-some-hot-IBlockData-methods.patch rename to patches/server/0527-Improve-inlinig-for-some-hot-IBlockData-methods.patch diff --git a/patches/server/0527-Retain-block-place-order-when-capturing-blockstates.patch b/patches/server/0528-Retain-block-place-order-when-capturing-blockstates.patch similarity index 100% rename from patches/server/0527-Retain-block-place-order-when-capturing-blockstates.patch rename to patches/server/0528-Retain-block-place-order-when-capturing-blockstates.patch diff --git a/patches/server/0528-Reduce-blockpos-allocation-from-pathfinding.patch b/patches/server/0529-Reduce-blockpos-allocation-from-pathfinding.patch similarity index 100% rename from patches/server/0528-Reduce-blockpos-allocation-from-pathfinding.patch rename to patches/server/0529-Reduce-blockpos-allocation-from-pathfinding.patch diff --git a/patches/server/0529-Fix-item-locations-dropped-from-campfires.patch b/patches/server/0530-Fix-item-locations-dropped-from-campfires.patch similarity index 100% rename from patches/server/0529-Fix-item-locations-dropped-from-campfires.patch rename to patches/server/0530-Fix-item-locations-dropped-from-campfires.patch diff --git a/patches/server/0530-Player-elytra-boost-API.patch b/patches/server/0531-Player-elytra-boost-API.patch similarity index 100% rename from patches/server/0530-Player-elytra-boost-API.patch rename to patches/server/0531-Player-elytra-boost-API.patch diff --git a/patches/server/0531-Fixed-TileEntityBell-memory-leak.patch b/patches/server/0532-Fixed-TileEntityBell-memory-leak.patch similarity index 100% rename from patches/server/0531-Fixed-TileEntityBell-memory-leak.patch rename to patches/server/0532-Fixed-TileEntityBell-memory-leak.patch diff --git a/patches/server/0532-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/patches/server/0533-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch similarity index 100% rename from patches/server/0532-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch rename to patches/server/0533-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch diff --git a/patches/server/0533-Add-getOfflinePlayerIfCached-String.patch b/patches/server/0534-Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from patches/server/0533-Add-getOfflinePlayerIfCached-String.patch rename to patches/server/0534-Add-getOfflinePlayerIfCached-String.patch diff --git a/patches/server/0534-Add-ignore-discounts-API.patch b/patches/server/0535-Add-ignore-discounts-API.patch similarity index 98% rename from patches/server/0534-Add-ignore-discounts-API.patch rename to patches/server/0535-Add-ignore-discounts-API.patch index 467e7a6641..a947fd725a 100644 --- a/patches/server/0534-Add-ignore-discounts-API.patch +++ b/patches/server/0535-Add-ignore-discounts-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add ignore discounts API diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 94e742856244b99236ba458fa38801abb5acf286..f534d3afaa20abacfd9e6e15d31d592855667c57 100644 +index 23ea91449a04e8457273db34c4a388bdf85d7dfc..fe9ee43bf0c49c0541bc4fb114e63b8a0fcf1967 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -474,6 +474,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler diff --git a/patches/server/0535-Toggle-for-removing-existing-dragon.patch b/patches/server/0536-Toggle-for-removing-existing-dragon.patch similarity index 100% rename from patches/server/0535-Toggle-for-removing-existing-dragon.patch rename to patches/server/0536-Toggle-for-removing-existing-dragon.patch diff --git a/patches/server/0536-Fix-client-lag-on-advancement-loading.patch b/patches/server/0537-Fix-client-lag-on-advancement-loading.patch similarity index 100% rename from patches/server/0536-Fix-client-lag-on-advancement-loading.patch rename to patches/server/0537-Fix-client-lag-on-advancement-loading.patch diff --git a/patches/server/0537-Item-no-age-no-player-pickup.patch b/patches/server/0538-Item-no-age-no-player-pickup.patch similarity index 100% rename from patches/server/0537-Item-no-age-no-player-pickup.patch rename to patches/server/0538-Item-no-age-no-player-pickup.patch diff --git a/patches/server/0538-Beacon-API-custom-effect-ranges.patch b/patches/server/0539-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from patches/server/0538-Beacon-API-custom-effect-ranges.patch rename to patches/server/0539-Beacon-API-custom-effect-ranges.patch diff --git a/patches/server/0539-Add-API-for-quit-reason.patch b/patches/server/0540-Add-API-for-quit-reason.patch similarity index 96% rename from patches/server/0539-Add-API-for-quit-reason.patch rename to patches/server/0540-Add-API-for-quit-reason.patch index dd04749f87..c43ced5243 100644 --- a/patches/server/0539-Add-API-for-quit-reason.patch +++ b/patches/server/0540-Add-API-for-quit-reason.patch @@ -25,7 +25,7 @@ index d32b96a5f51d745869cfc40c01c54de58e1eb843..759e563d1ed13249fada8a8eab6b6a10 Connection.LOGGER.debug("Failed to sent packet", throwable); ConnectionProtocol enumprotocol = this.getCurrentProtocol(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index de50d3de98490b5620a085c1af7fb100b8b8ad99..2be97d1024b15691fb2aaa8516d6447f47da4937 100644 +index fb56655df35c8a2cee8f5c4bb47a155054d850f8..c289664c317c9059d131f9e8f703d2304999a3cb 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -254,6 +254,7 @@ public class ServerPlayer extends Player { @@ -37,7 +37,7 @@ index de50d3de98490b5620a085c1af7fb100b8b8ad99..2be97d1024b15691fb2aaa8516d6447f public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) { super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 1fffa32bd193fa122c7f7b5381f57975c2e895fe..c495525da3dda12977d70ea85c87701988aa5929 100644 +index 70f82d410dd12d4f162ff38f7222f9d099e11e1f..642c525d09fcb580d14dab2e544816e62dc59a7a 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -444,6 +444,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0540-Seed-based-feature-search.patch b/patches/server/0541-Seed-based-feature-search.patch similarity index 100% rename from patches/server/0540-Seed-based-feature-search.patch rename to patches/server/0541-Seed-based-feature-search.patch diff --git a/patches/server/0541-Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server/0542-Add-Wandering-Trader-spawn-rate-config-options.patch similarity index 100% rename from patches/server/0541-Add-Wandering-Trader-spawn-rate-config-options.patch rename to patches/server/0542-Add-Wandering-Trader-spawn-rate-config-options.patch diff --git a/patches/server/0542-Significantly-improve-performance-of-the-end-generat.patch b/patches/server/0543-Significantly-improve-performance-of-the-end-generat.patch similarity index 100% rename from patches/server/0542-Significantly-improve-performance-of-the-end-generat.patch rename to patches/server/0543-Significantly-improve-performance-of-the-end-generat.patch diff --git a/patches/server/0543-Expose-world-spawn-angle.patch b/patches/server/0544-Expose-world-spawn-angle.patch similarity index 100% rename from patches/server/0543-Expose-world-spawn-angle.patch rename to patches/server/0544-Expose-world-spawn-angle.patch diff --git a/patches/server/0544-Add-Destroy-Speed-API.patch b/patches/server/0545-Add-Destroy-Speed-API.patch similarity index 100% rename from patches/server/0544-Add-Destroy-Speed-API.patch rename to patches/server/0545-Add-Destroy-Speed-API.patch diff --git a/patches/server/0545-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/patches/server/0546-Fix-Player-spawnParticle-x-y-z-precision-loss.patch similarity index 100% rename from patches/server/0545-Fix-Player-spawnParticle-x-y-z-precision-loss.patch rename to patches/server/0546-Fix-Player-spawnParticle-x-y-z-precision-loss.patch diff --git a/patches/server/0546-Add-LivingEntity-clearActiveItem.patch b/patches/server/0547-Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from patches/server/0546-Add-LivingEntity-clearActiveItem.patch rename to patches/server/0547-Add-LivingEntity-clearActiveItem.patch diff --git a/patches/server/0547-Add-PlayerItemCooldownEvent.patch b/patches/server/0548-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from patches/server/0547-Add-PlayerItemCooldownEvent.patch rename to patches/server/0548-Add-PlayerItemCooldownEvent.patch diff --git a/patches/server/0548-More-lightning-API.patch b/patches/server/0549-More-lightning-API.patch similarity index 100% rename from patches/server/0548-More-lightning-API.patch rename to patches/server/0549-More-lightning-API.patch diff --git a/patches/server/0549-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/0550-Climbing-should-not-bypass-cramming-gamerule.patch similarity index 98% rename from patches/server/0549-Climbing-should-not-bypass-cramming-gamerule.patch rename to patches/server/0550-Climbing-should-not-bypass-cramming-gamerule.patch index cb9304652a..5364432181 100644 --- a/patches/server/0549-Climbing-should-not-bypass-cramming-gamerule.patch +++ b/patches/server/0550-Climbing-should-not-bypass-cramming-gamerule.patch @@ -21,7 +21,7 @@ index afc637476380da272e61c10663dc77b30901c03a..247b30b2b2edbb1043b6385039ba830d private void keepLoadedRange() { keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d64caca72a5302392df944d4c60ed2ba79a19ee7..785970057ceb7a58049f9d36ac0eaa122637430f 100644 +index c3b05e73f9f42bdc2ab5d43fa905dd4cf5e39440..3ca07887bc67587cd820556d160037ca62c32c10 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1704,6 +1704,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0550-Added-missing-default-perms-for-commands.patch b/patches/server/0551-Added-missing-default-perms-for-commands.patch similarity index 100% rename from patches/server/0550-Added-missing-default-perms-for-commands.patch rename to patches/server/0551-Added-missing-default-perms-for-commands.patch diff --git a/patches/server/0551-Add-PlayerShearBlockEvent.patch b/patches/server/0552-Add-PlayerShearBlockEvent.patch similarity index 100% rename from patches/server/0551-Add-PlayerShearBlockEvent.patch rename to patches/server/0552-Add-PlayerShearBlockEvent.patch diff --git a/patches/server/0552-Set-spigots-verbose-world-setting-to-false-by-def.patch b/patches/server/0553-Set-spigots-verbose-world-setting-to-false-by-def.patch similarity index 100% rename from patches/server/0552-Set-spigots-verbose-world-setting-to-false-by-def.patch rename to patches/server/0553-Set-spigots-verbose-world-setting-to-false-by-def.patch diff --git a/patches/server/0553-Fix-curing-zombie-villager-discount-exploit.patch b/patches/server/0554-Fix-curing-zombie-villager-discount-exploit.patch similarity index 96% rename from patches/server/0553-Fix-curing-zombie-villager-discount-exploit.patch rename to patches/server/0554-Fix-curing-zombie-villager-discount-exploit.patch index d4d9695b5c..015e81c616 100644 --- a/patches/server/0553-Fix-curing-zombie-villager-discount-exploit.patch +++ b/patches/server/0554-Fix-curing-zombie-villager-discount-exploit.patch @@ -24,7 +24,7 @@ index 247b30b2b2edbb1043b6385039ba830dea877c55..618f47567ca9d4704f4686d7ca789286 private void keepLoadedRange() { keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index f534d3afaa20abacfd9e6e15d31d592855667c57..ee23149411a49f08d2eb4808ef78cb5a50785977 100644 +index fe9ee43bf0c49c0541bc4fb114e63b8a0fcf1967..18b35c8d2160d24c31483edef13cc5e8d93ed09b 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -1056,6 +1056,15 @@ public class Villager extends AbstractVillager implements ReputationEventHandler diff --git a/patches/server/0554-Limit-recipe-packets.patch b/patches/server/0555-Limit-recipe-packets.patch similarity index 97% rename from patches/server/0554-Limit-recipe-packets.patch rename to patches/server/0555-Limit-recipe-packets.patch index 261cfcff49..383406629b 100644 --- a/patches/server/0554-Limit-recipe-packets.patch +++ b/patches/server/0555-Limit-recipe-packets.patch @@ -23,7 +23,7 @@ index 7d50aded88f5b7dfebaea1aebc86231f7b5c4e25..652d87fc5d566dba8018c81676329f0e public static boolean velocityOnlineMode; public static byte[] velocitySecretKey; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index c495525da3dda12977d70ea85c87701988aa5929..2a1c524941e50d6a16076f57460d0cb05ed57f7c 100644 +index 642c525d09fcb580d14dab2e544816e62dc59a7a..2e8c7703f450e8f6fc872d78fa909f9f3d947b0c 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -232,6 +232,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0555-Fix-CraftSound-backwards-compatibility.patch b/patches/server/0556-Fix-CraftSound-backwards-compatibility.patch similarity index 100% rename from patches/server/0555-Fix-CraftSound-backwards-compatibility.patch rename to patches/server/0556-Fix-CraftSound-backwards-compatibility.patch diff --git a/patches/server/0556-MC-4-Fix-item-position-desync.patch b/patches/server/0557-MC-4-Fix-item-position-desync.patch similarity index 97% rename from patches/server/0556-MC-4-Fix-item-position-desync.patch rename to patches/server/0557-MC-4-Fix-item-position-desync.patch index aaad2cd0d1..d2b8ffa80d 100644 --- a/patches/server/0556-MC-4-Fix-item-position-desync.patch +++ b/patches/server/0557-MC-4-Fix-item-position-desync.patch @@ -41,7 +41,7 @@ index b30c08bfb8c55161543a4ef09f2e462e0a1fe4ae..ec93f5300cc7d423ec0d292f0f8443f9 public Vec3 updateEntityPosition(Vec3 orig) { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 785970057ceb7a58049f9d36ac0eaa122637430f..fec2a44c4a110407d33002a955fe5dacbccc840c 100644 +index 3ca07887bc67587cd820556d160037ca62c32c10..487923bcd5abe933f739e55f17a3c94d80af63b3 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -3731,6 +3731,16 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0557-Player-Chunk-Load-Unload-Events.patch b/patches/server/0558-Player-Chunk-Load-Unload-Events.patch similarity index 94% rename from patches/server/0557-Player-Chunk-Load-Unload-Events.patch rename to patches/server/0558-Player-Chunk-Load-Unload-Events.patch index 54e121ece4..19773457e0 100644 --- a/patches/server/0557-Player-Chunk-Load-Unload-Events.patch +++ b/patches/server/0558-Player-Chunk-Load-Unload-Events.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Player Chunk Load/Unload Events diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 2be97d1024b15691fb2aaa8516d6447f47da4937..f412f3b9f3af498b9ced4a808849442efad01b69 100644 +index c289664c317c9059d131f9e8f703d2304999a3cb..4d29671e38876bc6b8a2b80fa6e6f5d4200f0e9e 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -2087,11 +2087,21 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0558-Optimize-Dynamic-get-Missing-Keys.patch b/patches/server/0559-Optimize-Dynamic-get-Missing-Keys.patch similarity index 100% rename from patches/server/0558-Optimize-Dynamic-get-Missing-Keys.patch rename to patches/server/0559-Optimize-Dynamic-get-Missing-Keys.patch diff --git a/patches/server/0559-Expose-LivingEntity-hurt-direction.patch b/patches/server/0560-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from patches/server/0559-Expose-LivingEntity-hurt-direction.patch rename to patches/server/0560-Expose-LivingEntity-hurt-direction.patch diff --git a/patches/server/0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server/0561-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 91% rename from patches/server/0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/server/0561-Add-OBSTRUCTED-reason-to-BedEnterResult.patch index 56f636a0c1..b698f457cd 100644 --- a/patches/server/0560-Add-OBSTRUCTED-reason-to-BedEnterResult.patch +++ b/patches/server/0561-Add-OBSTRUCTED-reason-to-BedEnterResult.patch @@ -5,7 +5,7 @@ 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 fc9c63b73211d05321776648d6ba9c54f14ba83d..0f120d72816667ef8d50502b1e7e7dc3848f0ab4 100644 +index ff5d9baa5f961a6be7d5d73bfb78cb5de1b8cfe9..d6d6bc1ff3b9c1d303434bfc373a784b41557ed9 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -257,6 +257,10 @@ public class CraftEventFactory { diff --git a/patches/server/0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server/0562-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch similarity index 100% rename from patches/server/0561-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch rename to patches/server/0562-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch diff --git a/patches/server/0562-added-PlayerTradeEvent.patch b/patches/server/0563-added-PlayerTradeEvent.patch similarity index 100% rename from patches/server/0562-added-PlayerTradeEvent.patch rename to patches/server/0563-added-PlayerTradeEvent.patch diff --git a/patches/server/0563-Implement-TargetHitEvent.patch b/patches/server/0564-Implement-TargetHitEvent.patch similarity index 100% rename from patches/server/0563-Implement-TargetHitEvent.patch rename to patches/server/0564-Implement-TargetHitEvent.patch diff --git a/patches/server/0564-Additional-Block-Material-API-s.patch b/patches/server/0565-Additional-Block-Material-API-s.patch similarity index 100% rename from patches/server/0564-Additional-Block-Material-API-s.patch rename to patches/server/0565-Additional-Block-Material-API-s.patch diff --git a/patches/server/0565-Fix-harming-potion-dupe.patch b/patches/server/0566-Fix-harming-potion-dupe.patch similarity index 100% rename from patches/server/0565-Fix-harming-potion-dupe.patch rename to patches/server/0566-Fix-harming-potion-dupe.patch diff --git a/patches/server/0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/patches/server/0567-Implement-API-to-get-Material-from-Boats-and-Minecar.patch similarity index 100% rename from patches/server/0566-Implement-API-to-get-Material-from-Boats-and-Minecar.patch rename to patches/server/0567-Implement-API-to-get-Material-from-Boats-and-Minecar.patch diff --git a/patches/server/0567-Cache-burn-durations.patch b/patches/server/0568-Cache-burn-durations.patch similarity index 100% rename from patches/server/0567-Cache-burn-durations.patch rename to patches/server/0568-Cache-burn-durations.patch diff --git a/patches/server/0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server/0569-Allow-disabling-mob-spawner-spawn-egg-transformation.patch similarity index 100% rename from patches/server/0568-Allow-disabling-mob-spawner-spawn-egg-transformation.patch rename to patches/server/0569-Allow-disabling-mob-spawner-spawn-egg-transformation.patch diff --git a/patches/server/0569-Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server/0570-Implement-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from patches/server/0569-Implement-PlayerFlowerPotManipulateEvent.patch rename to patches/server/0570-Implement-PlayerFlowerPotManipulateEvent.patch diff --git a/patches/server/0570-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server/0571-Fix-interact-event-not-being-called-in-adventure.patch similarity index 95% rename from patches/server/0570-Fix-interact-event-not-being-called-in-adventure.patch rename to patches/server/0571-Fix-interact-event-not-being-called-in-adventure.patch index df7ae51e70..557725c214 100644 --- a/patches/server/0570-Fix-interact-event-not-being-called-in-adventure.patch +++ b/patches/server/0571-Fix-interact-event-not-being-called-in-adventure.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Fix interact event not being called in adventure Call PlayerInteractEvent when left-clicking on a block in adventure mode diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 2a1c524941e50d6a16076f57460d0cb05ed57f7c..8051cc5950b71f284e7ad8be685977fd098fe022 100644 +index 2e8c7703f450e8f6fc872d78fa909f9f3d947b0c..2eeca5c4cdeaf694700046fd6326608143605efe 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1734,7 +1734,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0571-Zombie-API-breaking-doors.patch b/patches/server/0572-Zombie-API-breaking-doors.patch similarity index 100% rename from patches/server/0571-Zombie-API-breaking-doors.patch rename to patches/server/0572-Zombie-API-breaking-doors.patch diff --git a/patches/server/0572-Fix-nerfed-slime-when-splitting.patch b/patches/server/0573-Fix-nerfed-slime-when-splitting.patch similarity index 100% rename from patches/server/0572-Fix-nerfed-slime-when-splitting.patch rename to patches/server/0573-Fix-nerfed-slime-when-splitting.patch diff --git a/patches/server/0573-Add-EntityLoadCrossbowEvent.patch b/patches/server/0574-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from patches/server/0573-Add-EntityLoadCrossbowEvent.patch rename to patches/server/0574-Add-EntityLoadCrossbowEvent.patch diff --git a/patches/server/0574-Guardian-beam-workaround.patch b/patches/server/0575-Guardian-beam-workaround.patch similarity index 100% rename from patches/server/0574-Guardian-beam-workaround.patch rename to patches/server/0575-Guardian-beam-workaround.patch diff --git a/patches/server/0575-Added-WorldGameRuleChangeEvent.patch b/patches/server/0576-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from patches/server/0575-Added-WorldGameRuleChangeEvent.patch rename to patches/server/0576-Added-WorldGameRuleChangeEvent.patch diff --git a/patches/server/0576-Added-ServerResourcesReloadedEvent.patch b/patches/server/0577-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from patches/server/0576-Added-ServerResourcesReloadedEvent.patch rename to patches/server/0577-Added-ServerResourcesReloadedEvent.patch diff --git a/patches/server/0577-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server/0578-Added-world-settings-for-mobs-picking-up-loot.patch similarity index 100% rename from patches/server/0577-Added-world-settings-for-mobs-picking-up-loot.patch rename to patches/server/0578-Added-world-settings-for-mobs-picking-up-loot.patch diff --git a/patches/server/0578-Implemented-BlockFailedDispenseEvent.patch b/patches/server/0579-Implemented-BlockFailedDispenseEvent.patch similarity index 96% rename from patches/server/0578-Implemented-BlockFailedDispenseEvent.patch rename to patches/server/0579-Implemented-BlockFailedDispenseEvent.patch index 3199535c18..739be08f2a 100644 --- a/patches/server/0578-Implemented-BlockFailedDispenseEvent.patch +++ b/patches/server/0579-Implemented-BlockFailedDispenseEvent.patch @@ -32,7 +32,7 @@ index 51723c8f740c7b0bbd15acc0f1c848790c2ff299..5a95b550c767284563c124df1ff45322 } 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 0f120d72816667ef8d50502b1e7e7dc3848f0ab4..263aaf312efcc8c8bda57448710ef6eb36a3a5bd 100644 +index d6d6bc1ff3b9c1d303434bfc373a784b41557ed9..55e64b4bbb60e793516a684ad877f356d6100db9 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -1791,4 +1791,12 @@ public class CraftEventFactory { diff --git a/patches/server/0579-Added-PlayerLecternPageChangeEvent.patch b/patches/server/0580-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from patches/server/0579-Added-PlayerLecternPageChangeEvent.patch rename to patches/server/0580-Added-PlayerLecternPageChangeEvent.patch diff --git a/patches/server/0580-Added-PlayerLoomPatternSelectEvent.patch b/patches/server/0581-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from patches/server/0580-Added-PlayerLoomPatternSelectEvent.patch rename to patches/server/0581-Added-PlayerLoomPatternSelectEvent.patch diff --git a/patches/server/0581-Configurable-door-breaking-difficulty.patch b/patches/server/0582-Configurable-door-breaking-difficulty.patch similarity index 100% rename from patches/server/0581-Configurable-door-breaking-difficulty.patch rename to patches/server/0582-Configurable-door-breaking-difficulty.patch diff --git a/patches/server/0582-Empty-commands-shall-not-be-dispatched.patch b/patches/server/0583-Empty-commands-shall-not-be-dispatched.patch similarity index 100% rename from patches/server/0582-Empty-commands-shall-not-be-dispatched.patch rename to patches/server/0583-Empty-commands-shall-not-be-dispatched.patch diff --git a/patches/server/0583-Implement-API-to-expose-exact-interaction-point.patch b/patches/server/0584-Implement-API-to-expose-exact-interaction-point.patch similarity index 97% rename from patches/server/0583-Implement-API-to-expose-exact-interaction-point.patch rename to patches/server/0584-Implement-API-to-expose-exact-interaction-point.patch index fcb5a17e21..410f64669f 100644 --- a/patches/server/0583-Implement-API-to-expose-exact-interaction-point.patch +++ b/patches/server/0584-Implement-API-to-expose-exact-interaction-point.patch @@ -18,7 +18,7 @@ index de4fdd46f23b2b17da752a8afc0faecc1ad8344f..2a0f313365a25c1780027f1536dbb88c 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 263aaf312efcc8c8bda57448710ef6eb36a3a5bd..f6f2856c407abe195f1dfee7f4a7e30baea585f7 100644 +index 55e64b4bbb60e793516a684ad877f356d6100db9..223029264288c6470f624d2cdc19282dddd13240 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -55,7 +55,9 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams; diff --git a/patches/server/0584-Remove-stale-POIs.patch b/patches/server/0585-Remove-stale-POIs.patch similarity index 100% rename from patches/server/0584-Remove-stale-POIs.patch rename to patches/server/0585-Remove-stale-POIs.patch diff --git a/patches/server/0585-Fix-villager-boat-exploit.patch b/patches/server/0586-Fix-villager-boat-exploit.patch similarity index 100% rename from patches/server/0585-Fix-villager-boat-exploit.patch rename to patches/server/0586-Fix-villager-boat-exploit.patch diff --git a/patches/server/0586-Add-sendOpLevel-API.patch b/patches/server/0587-Add-sendOpLevel-API.patch similarity index 100% rename from patches/server/0586-Add-sendOpLevel-API.patch rename to patches/server/0587-Add-sendOpLevel-API.patch diff --git a/patches/server/0587-Add-StructureLocateEvent.patch b/patches/server/0588-Add-StructureLocateEvent.patch similarity index 100% rename from patches/server/0587-Add-StructureLocateEvent.patch rename to patches/server/0588-Add-StructureLocateEvent.patch diff --git a/patches/server/0588-Collision-option-for-requiring-a-player-participant.patch b/patches/server/0589-Collision-option-for-requiring-a-player-participant.patch similarity index 98% rename from patches/server/0588-Collision-option-for-requiring-a-player-participant.patch rename to patches/server/0589-Collision-option-for-requiring-a-player-participant.patch index f3649e1149..a27b7eae79 100644 --- a/patches/server/0588-Collision-option-for-requiring-a-player-participant.patch +++ b/patches/server/0589-Collision-option-for-requiring-a-player-participant.patch @@ -28,7 +28,7 @@ index dd5c092a035a30c477fe828b58bc918fc48daa03..16b80fe4c55c51d3afaefba7eef97d1e public int wanderingTraderSpawnDayTicks = 24000; public int wanderingTraderSpawnChanceFailureIncrement = 25; diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index fec2a44c4a110407d33002a955fe5dacbccc840c..9023cee63d77886683840f8d5650a8e07426b4c6 100644 +index 487923bcd5abe933f739e55f17a3c94d80af63b3..5d4bee5470795bd9f362fff5ae653794223fa182 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1587,6 +1587,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0589-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/patches/server/0590-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch similarity index 100% rename from patches/server/0589-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch rename to patches/server/0590-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch diff --git a/patches/server/0590-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/server/0591-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from patches/server/0590-Return-chat-component-with-empty-text-instead-of-thr.patch rename to patches/server/0591-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/patches/server/0591-Make-schedule-command-per-world.patch b/patches/server/0592-Make-schedule-command-per-world.patch similarity index 100% rename from patches/server/0591-Make-schedule-command-per-world.patch rename to patches/server/0592-Make-schedule-command-per-world.patch diff --git a/patches/server/0592-Configurable-max-leash-distance.patch b/patches/server/0593-Configurable-max-leash-distance.patch similarity index 100% rename from patches/server/0592-Configurable-max-leash-distance.patch rename to patches/server/0593-Configurable-max-leash-distance.patch diff --git a/patches/server/0593-Implement-BlockPreDispenseEvent.patch b/patches/server/0594-Implement-BlockPreDispenseEvent.patch similarity index 95% rename from patches/server/0593-Implement-BlockPreDispenseEvent.patch rename to patches/server/0594-Implement-BlockPreDispenseEvent.patch index 7dd8f1e5f5..2e97f6d99a 100644 --- a/patches/server/0593-Implement-BlockPreDispenseEvent.patch +++ b/patches/server/0594-Implement-BlockPreDispenseEvent.patch @@ -17,7 +17,7 @@ index 501a5483160dba050261bb3448317a097cdb7ef2..2dcac4b638073aa1748f26f61219dbf9 tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index f6f2856c407abe195f1dfee7f4a7e30baea585f7..ea7082ab595f7bce572eec66ce7790a0afa8dae1 100644 +index 223029264288c6470f624d2cdc19282dddd13240..d66622db96abb553abe05eb917e233f1be7c873b 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -1809,5 +1809,11 @@ public class CraftEventFactory { diff --git a/patches/server/0594-Added-Vanilla-Entity-Tags.patch b/patches/server/0595-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from patches/server/0594-Added-Vanilla-Entity-Tags.patch rename to patches/server/0595-Added-Vanilla-Entity-Tags.patch diff --git a/patches/server/0595-added-Wither-API.patch b/patches/server/0596-added-Wither-API.patch similarity index 100% rename from patches/server/0595-added-Wither-API.patch rename to patches/server/0596-added-Wither-API.patch diff --git a/patches/server/0596-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/patches/server/0597-Added-firing-of-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from patches/server/0596-Added-firing-of-PlayerChangeBeaconEffectEvent.patch rename to patches/server/0597-Added-firing-of-PlayerChangeBeaconEffectEvent.patch diff --git a/patches/server/0597-Fix-console-spam-when-removing-chests-in-water.patch b/patches/server/0598-Fix-console-spam-when-removing-chests-in-water.patch similarity index 100% rename from patches/server/0597-Fix-console-spam-when-removing-chests-in-water.patch rename to patches/server/0598-Fix-console-spam-when-removing-chests-in-water.patch diff --git a/patches/server/0598-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server/0599-Add-toggle-for-always-placing-the-dragon-egg.patch similarity index 100% rename from patches/server/0598-Add-toggle-for-always-placing-the-dragon-egg.patch rename to patches/server/0599-Add-toggle-for-always-placing-the-dragon-egg.patch diff --git a/patches/server/0599-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server/0600-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from patches/server/0599-Added-PlayerStonecutterRecipeSelectEvent.patch rename to patches/server/0600-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/patches/server/0600-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/server/0601-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 98% rename from patches/server/0600-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/server/0601-Add-dropLeash-variable-to-EntityUnleashEvent.patch index fbf737e2d8..c0cf8f7c12 100644 --- a/patches/server/0600-Add-dropLeash-variable-to-EntityUnleashEvent.patch +++ b/patches/server/0601-Add-dropLeash-variable-to-EntityUnleashEvent.patch @@ -122,7 +122,7 @@ index b9b67134f02fd7484ed19905c9ae1f9b8a26ce26..c05f173b7642380900fdd77ce5d2c020 } } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index ea7082ab595f7bce572eec66ce7790a0afa8dae1..2b5f63c3f0ff3039fbef9afdfa46e0e715d347bc 100644 +index d66622db96abb553abe05eb917e233f1be7c873b..badba94d2a797952507d422b4ea92fc23bc5550f 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -1466,8 +1466,10 @@ public class CraftEventFactory { diff --git a/patches/server/0601-Skip-distance-map-update-when-spawning-disabled.patch b/patches/server/0602-Skip-distance-map-update-when-spawning-disabled.patch similarity index 100% rename from patches/server/0601-Skip-distance-map-update-when-spawning-disabled.patch rename to patches/server/0602-Skip-distance-map-update-when-spawning-disabled.patch diff --git a/patches/server/0602-Reset-shield-blocking-on-dimension-change.patch b/patches/server/0603-Reset-shield-blocking-on-dimension-change.patch similarity index 89% rename from patches/server/0602-Reset-shield-blocking-on-dimension-change.patch rename to patches/server/0603-Reset-shield-blocking-on-dimension-change.patch index aa3eb4e6c1..f718d3b81f 100644 --- a/patches/server/0602-Reset-shield-blocking-on-dimension-change.patch +++ b/patches/server/0603-Reset-shield-blocking-on-dimension-change.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Reset shield blocking on dimension change diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index f412f3b9f3af498b9ced4a808849442efad01b69..d0e9bbecb4b0cf980116c72b96ae8edd74f9bfd6 100644 +index 4d29671e38876bc6b8a2b80fa6e6f5d4200f0e9e..76e179089a419d4dae6bc64ef0122d03bcdd26e5 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1139,6 +1139,11 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0603-add-DragonEggFormEvent.patch b/patches/server/0604-add-DragonEggFormEvent.patch similarity index 100% rename from patches/server/0603-add-DragonEggFormEvent.patch rename to patches/server/0604-add-DragonEggFormEvent.patch diff --git a/patches/server/0604-EntityMoveEvent.patch b/patches/server/0605-EntityMoveEvent.patch similarity index 100% rename from patches/server/0604-EntityMoveEvent.patch rename to patches/server/0605-EntityMoveEvent.patch diff --git a/patches/server/0605-added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server/0606-added-option-to-disable-pathfinding-updates-on-block.patch similarity index 100% rename from patches/server/0605-added-option-to-disable-pathfinding-updates-on-block.patch rename to patches/server/0606-added-option-to-disable-pathfinding-updates-on-block.patch diff --git a/patches/server/0606-Inline-shift-direction-fields.patch b/patches/server/0607-Inline-shift-direction-fields.patch similarity index 100% rename from patches/server/0606-Inline-shift-direction-fields.patch rename to patches/server/0607-Inline-shift-direction-fields.patch diff --git a/patches/server/0607-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server/0608-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 95% rename from patches/server/0607-Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/server/0608-Allow-adding-items-to-BlockDropItemEvent.patch index 169393cd20..d15def0575 100644 --- a/patches/server/0607-Allow-adding-items-to-BlockDropItemEvent.patch +++ b/patches/server/0608-Allow-adding-items-to-BlockDropItemEvent.patch @@ -5,7 +5,7 @@ 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 2b5f63c3f0ff3039fbef9afdfa46e0e715d347bc..dcd59630c9e8870128859b9022827aeefebec963 100644 +index badba94d2a797952507d422b4ea92fc23bc5550f..f2bb96b13b3621af0079bd075798ed7f9bcb0b54 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -390,13 +390,30 @@ public class CraftEventFactory { diff --git a/patches/server/0608-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/server/0609-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from patches/server/0608-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/server/0609-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/patches/server/0609-living-entity-allow-attribute-registration.patch b/patches/server/0610-living-entity-allow-attribute-registration.patch similarity index 100% rename from patches/server/0609-living-entity-allow-attribute-registration.patch rename to patches/server/0610-living-entity-allow-attribute-registration.patch diff --git a/patches/server/0610-fix-dead-slime-setSize-invincibility.patch b/patches/server/0611-fix-dead-slime-setSize-invincibility.patch similarity index 100% rename from patches/server/0610-fix-dead-slime-setSize-invincibility.patch rename to patches/server/0611-fix-dead-slime-setSize-invincibility.patch diff --git a/patches/server/0611-Merchant-getRecipes-should-return-an-immutable-list.patch b/patches/server/0612-Merchant-getRecipes-should-return-an-immutable-list.patch similarity index 100% rename from patches/server/0611-Merchant-getRecipes-should-return-an-immutable-list.patch rename to patches/server/0612-Merchant-getRecipes-should-return-an-immutable-list.patch diff --git a/patches/server/0612-misc-debugging-dumps.patch b/patches/server/0613-misc-debugging-dumps.patch similarity index 100% rename from patches/server/0612-misc-debugging-dumps.patch rename to patches/server/0613-misc-debugging-dumps.patch diff --git a/patches/server/0613-Add-support-for-hex-color-codes-in-console.patch b/patches/server/0614-Add-support-for-hex-color-codes-in-console.patch similarity index 100% rename from patches/server/0613-Add-support-for-hex-color-codes-in-console.patch rename to patches/server/0614-Add-support-for-hex-color-codes-in-console.patch diff --git a/patches/server/0614-Expose-Tracked-Players.patch b/patches/server/0615-Expose-Tracked-Players.patch similarity index 100% rename from patches/server/0614-Expose-Tracked-Players.patch rename to patches/server/0615-Expose-Tracked-Players.patch diff --git a/patches/server/0615-Remove-streams-from-SensorNearest.patch b/patches/server/0616-Remove-streams-from-SensorNearest.patch similarity index 100% rename from patches/server/0615-Remove-streams-from-SensorNearest.patch rename to patches/server/0616-Remove-streams-from-SensorNearest.patch diff --git a/patches/server/0616-MC-29274-Fix-Wither-hostility-towards-players.patch b/patches/server/0617-MC-29274-Fix-Wither-hostility-towards-players.patch similarity index 100% rename from patches/server/0616-MC-29274-Fix-Wither-hostility-towards-players.patch rename to patches/server/0617-MC-29274-Fix-Wither-hostility-towards-players.patch diff --git a/patches/server/0617-Throw-proper-exception-on-empty-JsonList-file.patch b/patches/server/0618-Throw-proper-exception-on-empty-JsonList-file.patch similarity index 100% rename from patches/server/0617-Throw-proper-exception-on-empty-JsonList-file.patch rename to patches/server/0618-Throw-proper-exception-on-empty-JsonList-file.patch diff --git a/patches/server/0618-Improve-ServerGUI.patch b/patches/server/0619-Improve-ServerGUI.patch similarity index 100% rename from patches/server/0618-Improve-ServerGUI.patch rename to patches/server/0619-Improve-ServerGUI.patch diff --git a/patches/server/0619-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/patches/server/0620-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch similarity index 100% rename from patches/server/0619-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch rename to patches/server/0620-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch diff --git a/patches/server/0620-fix-converting-txt-to-json-file.patch b/patches/server/0621-fix-converting-txt-to-json-file.patch similarity index 100% rename from patches/server/0620-fix-converting-txt-to-json-file.patch rename to patches/server/0621-fix-converting-txt-to-json-file.patch diff --git a/patches/server/0621-Add-worldborder-events.patch b/patches/server/0622-Add-worldborder-events.patch similarity index 100% rename from patches/server/0621-Add-worldborder-events.patch rename to patches/server/0622-Add-worldborder-events.patch diff --git a/patches/server/0622-added-PlayerNameEntityEvent.patch b/patches/server/0623-added-PlayerNameEntityEvent.patch similarity index 100% rename from patches/server/0622-added-PlayerNameEntityEvent.patch rename to patches/server/0623-added-PlayerNameEntityEvent.patch diff --git a/patches/server/0623-Prevent-grindstones-from-overstacking-items.patch b/patches/server/0624-Prevent-grindstones-from-overstacking-items.patch similarity index 100% rename from patches/server/0623-Prevent-grindstones-from-overstacking-items.patch rename to patches/server/0624-Prevent-grindstones-from-overstacking-items.patch diff --git a/patches/server/0624-Add-recipe-to-cook-events.patch b/patches/server/0625-Add-recipe-to-cook-events.patch similarity index 100% rename from patches/server/0624-Add-recipe-to-cook-events.patch rename to patches/server/0625-Add-recipe-to-cook-events.patch diff --git a/patches/server/0625-Add-Block-isValidTool.patch b/patches/server/0626-Add-Block-isValidTool.patch similarity index 100% rename from patches/server/0625-Add-Block-isValidTool.patch rename to patches/server/0626-Add-Block-isValidTool.patch diff --git a/patches/server/0626-Allow-using-signs-inside-spawn-protection.patch b/patches/server/0627-Allow-using-signs-inside-spawn-protection.patch similarity index 96% rename from patches/server/0626-Allow-using-signs-inside-spawn-protection.patch rename to patches/server/0627-Allow-using-signs-inside-spawn-protection.patch index 1c8a0a68b4..300b353455 100644 --- a/patches/server/0626-Allow-using-signs-inside-spawn-protection.patch +++ b/patches/server/0627-Allow-using-signs-inside-spawn-protection.patch @@ -20,7 +20,7 @@ index caa15973d78e21725b5dd9e5fc91cede4cc0dac4..46601a98d9f06c6cfadc8120bcffab08 } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 8051cc5950b71f284e7ad8be685977fd098fe022..f5de1e31b62a4e04b865ab041e122d33c7efd54e 100644 +index 2eeca5c4cdeaf694700046fd6326608143605efe..7f7b34cc8a2c5fbf7dff8e785b067cb777808c52 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1723,7 +1723,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0627-Implement-Keyed-on-World.patch b/patches/server/0628-Implement-Keyed-on-World.patch similarity index 100% rename from patches/server/0627-Implement-Keyed-on-World.patch rename to patches/server/0628-Implement-Keyed-on-World.patch diff --git a/patches/server/0628-Add-fast-alternative-constructor-for-Rotations.patch b/patches/server/0629-Add-fast-alternative-constructor-for-Rotations.patch similarity index 100% rename from patches/server/0628-Add-fast-alternative-constructor-for-Rotations.patch rename to patches/server/0629-Add-fast-alternative-constructor-for-Rotations.patch diff --git a/patches/server/0629-Item-Rarity-API.patch b/patches/server/0630-Item-Rarity-API.patch similarity index 100% rename from patches/server/0629-Item-Rarity-API.patch rename to patches/server/0630-Item-Rarity-API.patch diff --git a/patches/server/0630-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/patches/server/0631-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch similarity index 100% rename from patches/server/0630-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch rename to patches/server/0631-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch diff --git a/patches/server/0631-copy-TESign-isEditable-from-snapshots.patch b/patches/server/0632-copy-TESign-isEditable-from-snapshots.patch similarity index 100% rename from patches/server/0631-copy-TESign-isEditable-from-snapshots.patch rename to patches/server/0632-copy-TESign-isEditable-from-snapshots.patch diff --git a/patches/server/0632-Drop-carried-item-when-player-has-disconnected.patch b/patches/server/0633-Drop-carried-item-when-player-has-disconnected.patch similarity index 100% rename from patches/server/0632-Drop-carried-item-when-player-has-disconnected.patch rename to patches/server/0633-Drop-carried-item-when-player-has-disconnected.patch diff --git a/patches/server/0633-forced-whitelist-use-configurable-kick-message.patch b/patches/server/0634-forced-whitelist-use-configurable-kick-message.patch similarity index 100% rename from patches/server/0633-forced-whitelist-use-configurable-kick-message.patch rename to patches/server/0634-forced-whitelist-use-configurable-kick-message.patch diff --git a/patches/server/0634-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/patches/server/0635-Don-t-ignore-result-of-PlayerEditBookEvent.patch similarity index 100% rename from patches/server/0634-Don-t-ignore-result-of-PlayerEditBookEvent.patch rename to patches/server/0635-Don-t-ignore-result-of-PlayerEditBookEvent.patch diff --git a/patches/server/0635-fix-cancelling-block-falling-causing-client-desync.patch b/patches/server/0636-fix-cancelling-block-falling-causing-client-desync.patch similarity index 100% rename from patches/server/0635-fix-cancelling-block-falling-causing-client-desync.patch rename to patches/server/0636-fix-cancelling-block-falling-causing-client-desync.patch diff --git a/patches/server/0636-Expose-protocol-version.patch b/patches/server/0637-Expose-protocol-version.patch similarity index 100% rename from patches/server/0636-Expose-protocol-version.patch rename to patches/server/0637-Expose-protocol-version.patch diff --git a/patches/server/0637-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/server/0638-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 98% rename from patches/server/0637-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to patches/server/0638-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch index 90d013302e..c3c5703755 100644 --- a/patches/server/0637-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch +++ b/patches/server/0638-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Allow for Component suggestion tooltips in diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 95b229081a4d51d63f477ef7894a938584d87fd0..f5c79ec1293c72b738bb6bc1d0aa9d495eefe194 100644 +index 11c2dac045e78b778a82246123ced159bfd2c1de..65219df9409c6c5165288a4e255b548c06e5f307 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -758,12 +758,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0638-Enhance-console-tab-completions-for-brigadier-comman.patch b/patches/server/0639-Enhance-console-tab-completions-for-brigadier-comman.patch similarity index 100% rename from patches/server/0638-Enhance-console-tab-completions-for-brigadier-comman.patch rename to patches/server/0639-Enhance-console-tab-completions-for-brigadier-comman.patch diff --git a/patches/server/0639-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/patches/server/0640-Fix-PlayerItemConsumeEvent-cancelling-properly.patch similarity index 100% rename from patches/server/0639-Fix-PlayerItemConsumeEvent-cancelling-properly.patch rename to patches/server/0640-Fix-PlayerItemConsumeEvent-cancelling-properly.patch diff --git a/patches/server/0640-Add-bypass-host-check.patch b/patches/server/0641-Add-bypass-host-check.patch similarity index 100% rename from patches/server/0640-Add-bypass-host-check.patch rename to patches/server/0641-Add-bypass-host-check.patch diff --git a/patches/server/0641-Set-area-affect-cloud-rotation.patch b/patches/server/0642-Set-area-affect-cloud-rotation.patch similarity index 100% rename from patches/server/0641-Set-area-affect-cloud-rotation.patch rename to patches/server/0642-Set-area-affect-cloud-rotation.patch diff --git a/patches/server/0642-add-isDeeplySleeping-to-HumanEntity.patch b/patches/server/0643-add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from patches/server/0642-add-isDeeplySleeping-to-HumanEntity.patch rename to patches/server/0643-add-isDeeplySleeping-to-HumanEntity.patch diff --git a/patches/server/0643-Fix-duplicating-give-items-on-item-drop-cancel.patch b/patches/server/0644-Fix-duplicating-give-items-on-item-drop-cancel.patch similarity index 100% rename from patches/server/0643-Fix-duplicating-give-items-on-item-drop-cancel.patch rename to patches/server/0644-Fix-duplicating-give-items-on-item-drop-cancel.patch diff --git a/patches/server/0644-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/server/0645-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from patches/server/0644-add-consumeFuel-to-FurnaceBurnEvent.patch rename to patches/server/0645-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/patches/server/0645-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/server/0646-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from patches/server/0645-add-get-set-drop-chance-to-EntityEquipment.patch rename to patches/server/0646-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/patches/server/0646-fix-PigZombieAngerEvent-cancellation.patch b/patches/server/0647-fix-PigZombieAngerEvent-cancellation.patch similarity index 100% rename from patches/server/0646-fix-PigZombieAngerEvent-cancellation.patch rename to patches/server/0647-fix-PigZombieAngerEvent-cancellation.patch diff --git a/patches/server/0647-Fix-checkReach-check-for-Shulker-boxes.patch b/patches/server/0648-Fix-checkReach-check-for-Shulker-boxes.patch similarity index 100% rename from patches/server/0647-Fix-checkReach-check-for-Shulker-boxes.patch rename to patches/server/0648-Fix-checkReach-check-for-Shulker-boxes.patch diff --git a/patches/server/0648-fix-PlayerItemHeldEvent-firing-twice.patch b/patches/server/0649-fix-PlayerItemHeldEvent-firing-twice.patch similarity index 93% rename from patches/server/0648-fix-PlayerItemHeldEvent-firing-twice.patch rename to patches/server/0649-fix-PlayerItemHeldEvent-firing-twice.patch index 21430d3a83..82e9419366 100644 --- a/patches/server/0648-fix-PlayerItemHeldEvent-firing-twice.patch +++ b/patches/server/0649-fix-PlayerItemHeldEvent-firing-twice.patch @@ -5,7 +5,7 @@ Subject: [PATCH] fix PlayerItemHeldEvent firing twice diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index f5c79ec1293c72b738bb6bc1d0aa9d495eefe194..b154aa2d151babbe4341c6dbaec1753d1472215c 100644 +index 65219df9409c6c5165288a4e255b548c06e5f307..efec476df92cd6563d7eafe120ff90bf3f959685 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1927,6 +1927,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0649-Added-PlayerDeepSleepEvent.patch b/patches/server/0650-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from patches/server/0649-Added-PlayerDeepSleepEvent.patch rename to patches/server/0650-Added-PlayerDeepSleepEvent.patch diff --git a/patches/server/0650-More-World-API.patch b/patches/server/0651-More-World-API.patch similarity index 100% rename from patches/server/0650-More-World-API.patch rename to patches/server/0651-More-World-API.patch diff --git a/patches/server/0651-Added-PlayerBedFailEnterEvent.patch b/patches/server/0652-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from patches/server/0651-Added-PlayerBedFailEnterEvent.patch rename to patches/server/0652-Added-PlayerBedFailEnterEvent.patch diff --git a/patches/server/0652-Implement-methods-to-convert-between-Component-and-B.patch b/patches/server/0653-Implement-methods-to-convert-between-Component-and-B.patch similarity index 100% rename from patches/server/0652-Implement-methods-to-convert-between-Component-and-B.patch rename to patches/server/0653-Implement-methods-to-convert-between-Component-and-B.patch diff --git a/patches/server/0653-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/patches/server/0654-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch similarity index 100% rename from patches/server/0653-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch rename to patches/server/0654-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch diff --git a/patches/server/0654-Introduce-beacon-activation-deactivation-events.patch b/patches/server/0655-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from patches/server/0654-Introduce-beacon-activation-deactivation-events.patch rename to patches/server/0655-Introduce-beacon-activation-deactivation-events.patch diff --git a/patches/server/0655-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/server/0656-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 97% rename from patches/server/0655-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/server/0656-add-RespawnFlags-to-PlayerRespawnEvent.patch index 6d960c9670..1cf0db1c8e 100644 --- a/patches/server/0655-add-RespawnFlags-to-PlayerRespawnEvent.patch +++ b/patches/server/0656-add-RespawnFlags-to-PlayerRespawnEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index b154aa2d151babbe4341c6dbaec1753d1472215c..e896057274434eea97d78777dcf303fd83e9cd79 100644 +index efec476df92cd6563d7eafe120ff90bf3f959685..3bee52c6a9d449599b8547437db50daee5014017 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -2461,7 +2461,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0656-Add-Channel-initialization-listeners.patch b/patches/server/0657-Add-Channel-initialization-listeners.patch similarity index 100% rename from patches/server/0656-Add-Channel-initialization-listeners.patch rename to patches/server/0657-Add-Channel-initialization-listeners.patch diff --git a/patches/server/0657-Send-empty-commands-if-tab-completion-is-disabled.patch b/patches/server/0658-Send-empty-commands-if-tab-completion-is-disabled.patch similarity index 100% rename from patches/server/0657-Send-empty-commands-if-tab-completion-is-disabled.patch rename to patches/server/0658-Send-empty-commands-if-tab-completion-is-disabled.patch diff --git a/patches/server/0658-Add-more-WanderingTrader-API.patch b/patches/server/0659-Add-more-WanderingTrader-API.patch similarity index 100% rename from patches/server/0658-Add-more-WanderingTrader-API.patch rename to patches/server/0659-Add-more-WanderingTrader-API.patch diff --git a/patches/server/0659-Add-EntityBlockStorage-clearEntities.patch b/patches/server/0660-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from patches/server/0659-Add-EntityBlockStorage-clearEntities.patch rename to patches/server/0660-Add-EntityBlockStorage-clearEntities.patch diff --git a/patches/server/0660-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/server/0661-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from patches/server/0660-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to patches/server/0661-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/patches/server/0661-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/server/0662-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from patches/server/0661-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/server/0662-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/patches/server/0662-Inventory-close.patch b/patches/server/0663-Inventory-close.patch similarity index 100% rename from patches/server/0662-Inventory-close.patch rename to patches/server/0663-Inventory-close.patch diff --git a/patches/server/0663-call-PortalCreateEvent-players-and-end-platform.patch b/patches/server/0664-call-PortalCreateEvent-players-and-end-platform.patch similarity index 96% rename from patches/server/0663-call-PortalCreateEvent-players-and-end-platform.patch rename to patches/server/0664-call-PortalCreateEvent-players-and-end-platform.patch index 2488018cba..068b62193d 100644 --- a/patches/server/0663-call-PortalCreateEvent-players-and-end-platform.patch +++ b/patches/server/0664-call-PortalCreateEvent-players-and-end-platform.patch @@ -17,7 +17,7 @@ index fd5c22a3d281d8d913c353c8a668ec51b885066a..8c3b34b3d55af4aa8e3619a5bdf0eadb return this.set(this.getX() + dx, this.getY() + dy, this.getZ() + dz); } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index d0e9bbecb4b0cf980116c72b96ae8edd74f9bfd6..3b5feea941eba2ee2c6d93fd5141f2f8f1dbae42 100644 +index 76e179089a419d4dae6bc64ef0122d03bcdd26e5..753ad5a12bc523eddfffa336a20ab3e3284e6f7c 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1166,15 +1166,21 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0664-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/server/0665-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 100% rename from patches/server/0664-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/server/0665-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch diff --git a/patches/server/0665-Fix-CraftPotionBrewer-cache.patch b/patches/server/0666-Fix-CraftPotionBrewer-cache.patch similarity index 100% rename from patches/server/0665-Fix-CraftPotionBrewer-cache.patch rename to patches/server/0666-Fix-CraftPotionBrewer-cache.patch diff --git a/patches/server/0666-Add-basic-Datapack-API.patch b/patches/server/0667-Add-basic-Datapack-API.patch similarity index 100% rename from patches/server/0666-Add-basic-Datapack-API.patch rename to patches/server/0667-Add-basic-Datapack-API.patch diff --git a/patches/server/0667-Add-environment-variable-to-disable-server-gui.patch b/patches/server/0668-Add-environment-variable-to-disable-server-gui.patch similarity index 100% rename from patches/server/0667-Add-environment-variable-to-disable-server-gui.patch rename to patches/server/0668-Add-environment-variable-to-disable-server-gui.patch diff --git a/patches/server/0668-additions-to-PlayerGameModeChangeEvent.patch b/patches/server/0669-additions-to-PlayerGameModeChangeEvent.patch similarity index 97% rename from patches/server/0668-additions-to-PlayerGameModeChangeEvent.patch rename to patches/server/0669-additions-to-PlayerGameModeChangeEvent.patch index 3fa2f12096..dda1537e31 100644 --- a/patches/server/0668-additions-to-PlayerGameModeChangeEvent.patch +++ b/patches/server/0669-additions-to-PlayerGameModeChangeEvent.patch @@ -45,7 +45,7 @@ index d75f78d2e3fb1376e8f6a8668c98a04a693c99e1..79f6089b934124c3309c6bee2e48b36b } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 3b5feea941eba2ee2c6d93fd5141f2f8f1dbae42..8d39c5314c2566d0193e10ad7c91c314fa16385a 100644 +index 753ad5a12bc523eddfffa336a20ab3e3284e6f7c..9f218a4b253fe2ab0e70e871eeee05bb4f0b3fcf 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1783,8 +1783,15 @@ public class ServerPlayer extends Player { @@ -123,7 +123,7 @@ index 2a0f313365a25c1780027f1536dbb88ccdab61e2..013ed10b8eca812309a2c9a10acd668a } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index e896057274434eea97d78777dcf303fd83e9cd79..b369d400e34fc8b6d161d79c57bcd26d57147ff8 100644 +index 3bee52c6a9d449599b8547437db50daee5014017..7ea9f362c19e5f3a67e4b5a46e708014953db480 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -2470,7 +2470,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0669-ItemStack-repair-check-API.patch b/patches/server/0670-ItemStack-repair-check-API.patch similarity index 100% rename from patches/server/0669-ItemStack-repair-check-API.patch rename to patches/server/0670-ItemStack-repair-check-API.patch diff --git a/patches/server/0670-More-Enchantment-API.patch b/patches/server/0671-More-Enchantment-API.patch similarity index 100% rename from patches/server/0670-More-Enchantment-API.patch rename to patches/server/0671-More-Enchantment-API.patch diff --git a/patches/server/0671-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/server/0672-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 100% rename from patches/server/0671-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to patches/server/0672-Add-command-line-option-to-load-extra-plugin-jars-no.patch diff --git a/patches/server/0672-Fix-and-optimise-world-force-upgrading.patch b/patches/server/0673-Fix-and-optimise-world-force-upgrading.patch similarity index 100% rename from patches/server/0672-Fix-and-optimise-world-force-upgrading.patch rename to patches/server/0673-Fix-and-optimise-world-force-upgrading.patch diff --git a/patches/server/0673-Add-Mob-lookAt-API.patch b/patches/server/0674-Add-Mob-lookAt-API.patch similarity index 100% rename from patches/server/0673-Add-Mob-lookAt-API.patch rename to patches/server/0674-Add-Mob-lookAt-API.patch diff --git a/patches/server/0674-Add-Unix-domain-socket-support.patch b/patches/server/0675-Add-Unix-domain-socket-support.patch similarity index 100% rename from patches/server/0674-Add-Unix-domain-socket-support.patch rename to patches/server/0675-Add-Unix-domain-socket-support.patch diff --git a/patches/server/0675-Add-EntityInsideBlockEvent.patch b/patches/server/0676-Add-EntityInsideBlockEvent.patch similarity index 99% rename from patches/server/0675-Add-EntityInsideBlockEvent.patch rename to patches/server/0676-Add-EntityInsideBlockEvent.patch index 31db266834..da1baff239 100644 --- a/patches/server/0675-Add-EntityInsideBlockEvent.patch +++ b/patches/server/0676-Add-EntityInsideBlockEvent.patch @@ -101,7 +101,7 @@ index 63c7f2cf530ac9562960ae5a3cbc6e511a009377..3705452f1b57d3bc1307411c7367529d if (!(Boolean) state.getValue(DetectorRailBlock.POWERED)) { this.checkPressed(world, pos, state); diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -index cc76a17492a67c1d2b97a8b6cd991db893de4414..834be24478b801d75be96ada91a4f18ccc3ee7b4 100644 +index 2cd9584aae80e5bf40d0a53417692758a17d05d6..739c9c3a49fd3893ac39962a02a5e3620dc4fe06 100644 --- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java @@ -44,6 +44,7 @@ public class EndPortalBlock extends BaseEntityBlock { diff --git a/patches/server/0676-Attributes-API-for-item-defaults.patch b/patches/server/0677-Attributes-API-for-item-defaults.patch similarity index 100% rename from patches/server/0676-Attributes-API-for-item-defaults.patch rename to patches/server/0677-Attributes-API-for-item-defaults.patch diff --git a/patches/server/0677-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/patches/server/0678-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch similarity index 100% rename from patches/server/0677-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch rename to patches/server/0678-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch diff --git a/patches/server/0678-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/server/0679-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from patches/server/0678-Add-cause-to-Weather-ThunderChangeEvents.patch rename to patches/server/0679-Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/patches/server/0679-More-Lidded-Block-API.patch b/patches/server/0680-More-Lidded-Block-API.patch similarity index 100% rename from patches/server/0679-More-Lidded-Block-API.patch rename to patches/server/0680-More-Lidded-Block-API.patch diff --git a/patches/server/0680-Limit-item-frame-cursors-on-maps.patch b/patches/server/0681-Limit-item-frame-cursors-on-maps.patch similarity index 100% rename from patches/server/0680-Limit-item-frame-cursors-on-maps.patch rename to patches/server/0681-Limit-item-frame-cursors-on-maps.patch diff --git a/patches/server/0681-Add-PufferFishStateChangeEvent.patch b/patches/server/0682-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from patches/server/0681-Add-PufferFishStateChangeEvent.patch rename to patches/server/0682-Add-PufferFishStateChangeEvent.patch diff --git a/patches/server/0682-Add-PlayerKickEvent-causes.patch b/patches/server/0683-Add-PlayerKickEvent-causes.patch similarity index 99% rename from patches/server/0682-Add-PlayerKickEvent-causes.patch rename to patches/server/0683-Add-PlayerKickEvent-causes.patch index 7959f099e4..010bdf05bd 100644 --- a/patches/server/0682-Add-PlayerKickEvent-causes.patch +++ b/patches/server/0683-Add-PlayerKickEvent-causes.patch @@ -57,7 +57,7 @@ index 708ac03d5a849bf09c49547306e4a8c5a5ef8d91..5a8df368a4a25839cd4ac9be6972da2e } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index b369d400e34fc8b6d161d79c57bcd26d57147ff8..8e7a8e7b6d44255044a34ed374f106435cf1ba07 100644 +index 7ea9f362c19e5f3a67e4b5a46e708014953db480..f1ffabb1226e568b64e3aadd695197d0c9742de8 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -321,7 +321,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0683-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/patches/server/0684-Fix-PlayerBucketEmptyEvent-result-itemstack.patch similarity index 100% rename from patches/server/0683-Fix-PlayerBucketEmptyEvent-result-itemstack.patch rename to patches/server/0684-Fix-PlayerBucketEmptyEvent-result-itemstack.patch diff --git a/patches/server/0684-Add-option-to-fix-items-merging-through-walls.patch b/patches/server/0685-Add-option-to-fix-items-merging-through-walls.patch similarity index 100% rename from patches/server/0684-Add-option-to-fix-items-merging-through-walls.patch rename to patches/server/0685-Add-option-to-fix-items-merging-through-walls.patch diff --git a/patches/server/0685-Add-BellRevealRaiderEvent.patch b/patches/server/0686-Add-BellRevealRaiderEvent.patch similarity index 100% rename from patches/server/0685-Add-BellRevealRaiderEvent.patch rename to patches/server/0686-Add-BellRevealRaiderEvent.patch diff --git a/patches/server/0686-Fix-invulnerable-end-crystals.patch b/patches/server/0687-Fix-invulnerable-end-crystals.patch similarity index 100% rename from patches/server/0686-Fix-invulnerable-end-crystals.patch rename to patches/server/0687-Fix-invulnerable-end-crystals.patch diff --git a/patches/server/0687-Add-ElderGuardianAppearanceEvent.patch b/patches/server/0688-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from patches/server/0687-Add-ElderGuardianAppearanceEvent.patch rename to patches/server/0688-Add-ElderGuardianAppearanceEvent.patch diff --git a/patches/server/0688-Reset-villager-inventory-on-cancelled-pickup-event.patch b/patches/server/0689-Reset-villager-inventory-on-cancelled-pickup-event.patch similarity index 96% rename from patches/server/0688-Reset-villager-inventory-on-cancelled-pickup-event.patch rename to patches/server/0689-Reset-villager-inventory-on-cancelled-pickup-event.patch index 502eba8446..4a6a053383 100644 --- a/patches/server/0688-Reset-villager-inventory-on-cancelled-pickup-event.patch +++ b/patches/server/0689-Reset-villager-inventory-on-cancelled-pickup-event.patch @@ -26,7 +26,7 @@ index 502e29644504aabe3834351d3b479e21bd8f4be7..4e47ea7359ae56efeb2b74161dc9e738 this.transaction.add(who); } diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index ee23149411a49f08d2eb4808ef78cb5a50785977..4591054d5f106f2d630fc7bd3304a8ff7f426007 100644 +index 18b35c8d2160d24c31483edef13cc5e8d93ed09b..27530389690ec329bd92a722e4faf87e367bce91 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -888,15 +888,19 @@ public class Villager extends AbstractVillager implements ReputationEventHandler diff --git a/patches/server/0689-Fix-dangerous-end-portal-logic.patch b/patches/server/0690-Fix-dangerous-end-portal-logic.patch similarity index 100% rename from patches/server/0689-Fix-dangerous-end-portal-logic.patch rename to patches/server/0690-Fix-dangerous-end-portal-logic.patch diff --git a/patches/server/0690-Make-item-validations-configurable.patch b/patches/server/0691-Make-item-validations-configurable.patch similarity index 100% rename from patches/server/0690-Make-item-validations-configurable.patch rename to patches/server/0691-Make-item-validations-configurable.patch diff --git a/patches/server/0691-Add-more-line-of-sight-methods.patch b/patches/server/0692-Add-more-line-of-sight-methods.patch similarity index 100% rename from patches/server/0691-Add-more-line-of-sight-methods.patch rename to patches/server/0692-Add-more-line-of-sight-methods.patch diff --git a/patches/server/0692-add-per-world-spawn-limits.patch b/patches/server/0693-add-per-world-spawn-limits.patch similarity index 100% rename from patches/server/0692-add-per-world-spawn-limits.patch rename to patches/server/0693-add-per-world-spawn-limits.patch diff --git a/patches/server/0693-Fix-PotionSplashEvent-for-water-splash-potions.patch b/patches/server/0694-Fix-PotionSplashEvent-for-water-splash-potions.patch similarity index 100% rename from patches/server/0693-Fix-PotionSplashEvent-for-water-splash-potions.patch rename to patches/server/0694-Fix-PotionSplashEvent-for-water-splash-potions.patch From b26ba5bc8acd8357c16a3960de3e2f1ce338be78 Mon Sep 17 00:00:00 2001 From: Omer Uddin Date: Tue, 15 Jun 2021 01:44:37 -0400 Subject: [PATCH 141/226] port some patches (#5837) --- .../0154-PreSpawnerSpawnEvent.patch} | 0 ...0312-Add-PufferFishStateChangeEvent.patch} | 0 ...e-Biome-Mob-Lookups-for-Mob-Spawning.patch | 99 --------------- .../1.17/0290-PreSpawnerSpawnEvent.patch | 31 ----- ...PaletteBlock-instead-of-ReentrantLoc.patch | 117 ------------------ .../server/0290-PreSpawnerSpawnEvent.patch | 29 +++++ ...tedContainer-instead-of-ReentrantLoc.patch | 92 ++++++++++++++ ...e-Biome-Mob-Lookups-for-Mob-Spawning.patch | 57 +++++++++ 8 files changed, 178 insertions(+), 247 deletions(-) rename patches/{removed/1.17/0153-PreSpawnerSpawnEvent.patch => api/0154-PreSpawnerSpawnEvent.patch} (100%) rename patches/api/{0313-Add-PufferFishStateChangeEvent.patch => 0312-Add-PufferFishStateChangeEvent.patch} (100%) delete mode 100644 patches/removed/1.17/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch delete mode 100644 patches/removed/1.17/0290-PreSpawnerSpawnEvent.patch delete mode 100644 patches/removed/1.17/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch create mode 100644 patches/server/0290-PreSpawnerSpawnEvent.patch create mode 100644 patches/server/0684-Synchronize-PalettedContainer-instead-of-ReentrantLoc.patch create mode 100644 patches/server/0690-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch diff --git a/patches/removed/1.17/0153-PreSpawnerSpawnEvent.patch b/patches/api/0154-PreSpawnerSpawnEvent.patch similarity index 100% rename from patches/removed/1.17/0153-PreSpawnerSpawnEvent.patch rename to patches/api/0154-PreSpawnerSpawnEvent.patch diff --git a/patches/api/0313-Add-PufferFishStateChangeEvent.patch b/patches/api/0312-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from patches/api/0313-Add-PufferFishStateChangeEvent.patch rename to patches/api/0312-Add-PufferFishStateChangeEvent.patch diff --git a/patches/removed/1.17/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/removed/1.17/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch deleted file mode 100644 index 5fe08a22a2..0000000000 --- a/patches/removed/1.17/0288-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 12 Sep 2018 21:47:01 -0400 -Subject: [PATCH] Optimize Biome Mob Lookups for Mob Spawning - -Uses an EnumMap as well as a Set paired List for O(1) contains calls. - - -TODO 1.17: Does not look relevant now -diff --git a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java -index 58ee27a994b4cd845b8bb28e80cc2102c860f097..528f42c63a1186b8827bfe7cf6193e14da938cb3 100644 ---- a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java -+++ b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java -@@ -30,19 +30,28 @@ public class MobSpawnSettings { - }, (enumcreaturetype) -> { - return ImmutableList.of(); - })), ImmutableMap.of(), false); -+ // Paper start- decompile error workaround -+ private static class bProxy extends MobSpawnSettings.MobSpawnCost { -+ private bProxy(double gravityLimit, double mass) { -+ super(gravityLimit, mass); -+ } -+ } -+ private static class cProxy extends MobSpawnSettings.SpawnerData { -+ public cProxy(EntityType type, int weight, int minGroupSize, int maxGroupSize) { -+ super(type, weight, minGroupSize, maxGroupSize); -+ } -+ }; -+ // Paper end - public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { -- RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { -- return biomesettingsmobs.d; -+ RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { // Paper - add type to builder -+ return biomesettingsmobs.creatureGenerationProbability; - }); -- Codec codec = MobCategory.CODEC; -- Codec codec1 = BiomeSettingsMobs.c.b.listOf(); -- Logger logger = MobSpawnSettings.LOGGER; -- -- logger.getClass(); -- return instance.group(recordcodecbuilder, Codec.simpleMap(codec, codec1.promotePartial(Util.prefix("Spawn data: ", logger::error)), StringRepresentable.keys(MobCategory.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { -- return biomesettingsmobs.e; -- }), Codec.simpleMap(Registry.ENTITY_TYPE, BiomeSettingsMobs.b.a, Registry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { -- return biomesettingsmobs.f; -+ // Paper - remove unused vars -+ -+ return instance.group(recordcodecbuilder, Codec.simpleMap(MobCategory.CODEC, cProxy.CODEC.listOf().promotePartial(Util.prefix("Spawn data: ", MobSpawnSettings.LOGGER::error)), StringRepresentable.keys(MobCategory.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { // Paper - inline codec, cProxy, LOGGER -+ return biomesettingsmobs.spawners; -+ }), Codec.simpleMap(Registry.ENTITY_TYPE, bProxy.CODEC, Registry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { // Paper - decompile error - bProxy -+ return biomesettingsmobs.mobSpawnCosts; - }), Codec.BOOL.fieldOf("player_spawn_friendly").orElse(false).forGetter(MobSpawnSettings::playerSpawnFriendly)).apply(instance, MobSpawnSettings::new); - }); - private final float creatureGenerationProbability; -@@ -76,11 +85,43 @@ public class MobSpawnSettings { - - public static class Builder { - -- private final Map> spawners = (Map) Stream.of(MobCategory.values()).collect(ImmutableMap.toImmutableMap((enumcreaturetype) -> { -+ // Paper start - keep track of data in a pair set to give O(1) contains calls - we have to hook removals incase plugins mess with it -+ public static class MobList extends java.util.ArrayList { -+ java.util.Set biomes = new java.util.HashSet<>(); -+ -+ @Override -+ public boolean contains(Object o) { -+ return biomes.contains(o); -+ } -+ -+ @Override -+ public boolean add(MobSpawnSettings.SpawnerData BiomeSettingsMobs) { -+ biomes.add(BiomeSettingsMobs); -+ return super.add(BiomeSettingsMobs); -+ } -+ -+ @Override -+ public MobSpawnSettings.SpawnerData remove(int index) { -+ MobSpawnSettings.SpawnerData removed = super.remove(index); -+ if (removed != null) { -+ biomes.remove(removed); -+ } -+ return removed; -+ } -+ -+ @Override -+ public void clear() { -+ biomes.clear(); -+ super.clear(); -+ } -+ } -+ // use toImmutableEnumMap collector -+ private final Map> spawners = (Map) Stream.of(MobCategory.values()).collect(Maps.toImmutableEnumMap((enumcreaturetype) -> { - return enumcreaturetype; - }, (enumcreaturetype) -> { -- return Lists.newArrayList(); -+ return new MobList(); // Use MobList instead of ArrayList - })); -+ // Paper end - private final Map, MobSpawnSettings.MobSpawnCost> mobSpawnCosts = Maps.newLinkedHashMap(); - private float creatureGenerationProbability = 0.1F; - private boolean playerCanSpawn; diff --git a/patches/removed/1.17/0290-PreSpawnerSpawnEvent.patch b/patches/removed/1.17/0290-PreSpawnerSpawnEvent.patch deleted file mode 100644 index 592cfbd22d..0000000000 --- a/patches/removed/1.17/0290-PreSpawnerSpawnEvent.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 18 Sep 2018 23:53:23 +0100 -Subject: [PATCH] PreSpawnerSpawnEvent - -This adds a separate event before an entity is spawned by a spawner -which contains the location of the spawner too similarly to how the -SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for -spawners. - -Dropped as it does not apply due to the earlier PreCreatureSpawnEvent patch not being applied - -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index ac572eba10a7239d71dfae060f623b076d4252ce..1ce675d0d24ceb5724f5ac2d8f671e38f2735f74 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -132,11 +132,11 @@ public abstract class BaseSpawner { - - org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); - if (type != null) { -- com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -- event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent( - MCUtil.toLocation(world, d3, d4, d5), - type, -- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER -+ MCUtil.toLocation(world, blockposition) - ); - if (!event.callEvent()) { - flag = true; diff --git a/patches/removed/1.17/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch b/patches/removed/1.17/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch deleted file mode 100644 index f172c356ec..0000000000 --- a/patches/removed/1.17/0362-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 May 2020 20:29:02 -0400 -Subject: [PATCH] Synchronize DataPaletteBlock instead of ReentrantLock -1.17: Mini have fun I don't want to die -Mojang has flaws in their logic about chunks being concurrently -wrote to. So we constantly see crashes around multiple threads writing. - -Additionally, java has optimized synchronization so well that its -in many times faster than trying to manage read wrote locks for low -contention situations. - -And this is extremely a low contention situation. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index 6d3dcd19ce1abc9d502903b8008949b5174a13c3..917b0a64083ebbe24321089b784b91f3af4918b9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -8,7 +8,6 @@ import java.util.function.Function; - import java.util.function.Predicate; - import java.util.stream.Collectors; - import net.minecraft.CrashReport; --import net.minecraft.CrashReportCategory; - import net.minecraft.ReportedException; - import net.minecraft.core.IdMapper; - import net.minecraft.nbt.CompoundTag; -@@ -32,23 +31,23 @@ public class PalettedContainer implements PaletteResize { - private int bits; private int getBitsPerObject() { return this.bits; } // Paper - OBFHELPER - private final ReentrantLock lock = new ReentrantLock(); - -- public void acquire() { -- if (this.lock.isLocked() && !this.lock.isHeldByCurrentThread()) { -+ public void acquire() { /* // Paper start - disable this - use proper synchronization -+ if (this.j.isLocked() && !this.j.isHeldByCurrentThread()) { - String s = (String) Thread.getAllStackTraces().keySet().stream().filter(Objects::nonNull).map((thread) -> { - return thread.getName() + ": \n\tat " + (String) Arrays.stream(thread.getStackTrace()).map(Object::toString).collect(Collectors.joining("\n\tat ")); - }).collect(Collectors.joining("\n")); - CrashReport crashreport = new CrashReport("Writing into PalettedContainer from multiple threads", new IllegalStateException()); -- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Thread dumps"); -+ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Thread dumps"); - -- crashreportsystemdetails.setDetail("Thread dumps", (Object) s); -+ crashreportsystemdetails.a("Thread dumps", (Object) s); - throw new ReportedException(crashreport); - } else { -- this.lock.lock(); -- } -+ this.j.lock(); -+ } */ // Paper end - } - - public void release() { -- this.lock.unlock(); -+ //this.j.unlock(); // Paper - disable this - } - - public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { -@@ -84,7 +83,7 @@ public class PalettedContainer implements PaletteResize { - } - - @Override -- public int onResize(int newSize, T objectAdded) { -+ public synchronized int onResize(int newSize, T objectAdded) { // Paper - synchronize - this.acquire(); - BitStorage databits = this.storage; - Palette datapalette = this.palette; -@@ -107,18 +106,18 @@ public class PalettedContainer implements PaletteResize { - } - - public T getAndSet(int x, int y, int z, T value) { -- this.acquire(); -- T t1 = this.getAndSet(getIndex(x, y, z), value); -+ //this.a(); // Paper - remove to reduce ops - synchronize handled below -+ return this.getAndSet(getIndex(x, y, z), value); // Paper - -- this.release(); -- return t1; -+ //this.b(); // Paper -+ //return t1; // PAper - } - - public T getAndSetUnchecked(int x, int y, int z, T value) { - return this.getAndSet(getIndex(x, y, z), value); - } - -- protected T getAndSet(int index, T value) { -+ protected synchronized T getAndSet(int index, T value) { // Paper - synchronize - writes - int j = this.palette.idFor(value); - int k = this.storage.getAndSet(index, j); - T t1 = this.palette.valueFor(k); -@@ -143,7 +142,7 @@ public class PalettedContainer implements PaletteResize { - } - - public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER -- public void write(FriendlyByteBuf buf) { -+ public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize - this.acquire(); - buf.writeByte(this.bits); - this.palette.write(buf); -@@ -151,7 +150,7 @@ public class PalettedContainer implements PaletteResize { - this.release(); - } - -- public void read(ListTag paletteTag, long[] data) { -+ public synchronized void read(ListTag paletteTag, long[] data) { // Paper - synchronize - this.acquire(); - int i = Math.max(4, Mth.ceillog2(paletteTag.size())); - -@@ -184,7 +183,7 @@ public class PalettedContainer implements PaletteResize { - this.release(); - } - -- public void write(CompoundTag nbttagcompound, String s, String s1) { -+ public synchronized void write(CompoundTag nbttagcompound, String s, String s1) { // Paper - synchronize - this.acquire(); - HashMapPalette datapalettehash = new HashMapPalette<>(this.registry, this.bits, this.dummyPaletteResize, this.reader, this.writer); - T t0 = this.defaultValue; diff --git a/patches/server/0290-PreSpawnerSpawnEvent.patch b/patches/server/0290-PreSpawnerSpawnEvent.patch new file mode 100644 index 0000000000..fd48f263be --- /dev/null +++ b/patches/server/0290-PreSpawnerSpawnEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Tue, 18 Sep 2018 23:53:23 +0100 +Subject: [PATCH] PreSpawnerSpawnEvent + +This adds a separate event before an entity is spawned by a spawner +which contains the location of the spawner too similarly to how the +SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for +spawners. + +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index c741f8e4a4b67d1bfed2d1bac36856c5688bb161..9228c0bc797fb95c8ac949bdc568eadafee84a80 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -138,11 +138,11 @@ public abstract class BaseSpawner { + + org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); + if (type != null) { +- com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; +- event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent( + net.minecraft.server.MCUtil.toLocation(world, d0, d1, d2), + type, +- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER ++ net.minecraft.server.MCUtil.toLocation(world, pos) + ); + if (!event.callEvent()) { + flag = true; diff --git a/patches/server/0684-Synchronize-PalettedContainer-instead-of-ReentrantLoc.patch b/patches/server/0684-Synchronize-PalettedContainer-instead-of-ReentrantLoc.patch new file mode 100644 index 0000000000..598b0de366 --- /dev/null +++ b/patches/server/0684-Synchronize-PalettedContainer-instead-of-ReentrantLoc.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 May 2020 20:29:02 -0400 +Subject: [PATCH] Synchronize PalettedContainer instead of ReentrantLock + +Mojang has flaws in their logic about chunks being concurrently +wrote to. So we constantly see crashes around multiple threads writing. + +Additionally, java has optimized synchronization so well that its +in many times faster than trying to manage read wrote locks for low +contention situations. + +And this is extremely a low contention situation. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index 5ac948b5b82f3144cdf402af440251cb8c7369d7..d8b7a7d9aa3ef47aa4e222c6ca85e83ce21f2444 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -36,16 +36,18 @@ public class PalettedContainer implements PaletteResize { + private final DebugBuffer> traces = null; + + public void acquire() { ++ /* // Paper start - disable this - use proper synchronization + if (this.traces != null) { + Thread thread = Thread.currentThread(); + this.traces.push(Pair.of(thread, thread.getStackTrace())); + } + + ThreadingDetector.checkAndLock(this.lock, this.traces, "PalettedContainer"); ++ */ // Paper end + } + + public void release() { +- this.lock.release(); ++ //this.lock.release(); // Paper - disable this + } + + public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { +@@ -96,7 +98,7 @@ public class PalettedContainer implements PaletteResize { + return this.palette.idFor(objectAdded); + } + +- public T getAndSet(int x, int y, int z, T value) { ++ public synchronized T getAndSet(int x, int y, int z, T value) { // Paper - synchronize + Object var6; + try { + this.acquire(); +@@ -120,7 +122,7 @@ public class PalettedContainer implements PaletteResize { + return (T)(object == null ? this.defaultValue : object); + } + +- public void set(int i, int j, int k, T object) { ++ public synchronized void set(int i, int j, int k, T object) { // Paper - synchronize + try { + this.acquire(); + this.set(getIndex(i, j, k), object); +@@ -144,7 +146,7 @@ public class PalettedContainer implements PaletteResize { + return (T)(object == null ? this.defaultValue : object); + } + +- public void read(FriendlyByteBuf buf) { ++ public synchronized void read(FriendlyByteBuf buf) { // Paper - synchronize + try { + this.acquire(); + int i = buf.readByte(); +@@ -161,7 +163,7 @@ public class PalettedContainer implements PaletteResize { + } + + public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER +- public void write(FriendlyByteBuf buf) { ++ public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize + try { + this.acquire(); + buf.writeByte(this.bits); +@@ -173,7 +175,7 @@ public class PalettedContainer implements PaletteResize { + + } + +- public void read(ListTag paletteNbt, long[] data) { ++ public synchronized void read(ListTag paletteNbt, long[] data) { // Paper - synchronize + try { + this.acquire(); + int i = Math.max(4, Mth.ceillog2(paletteNbt.size())); +@@ -206,7 +208,7 @@ public class PalettedContainer implements PaletteResize { + + } + +- public void write(CompoundTag nbt, String paletteKey, String dataKey) { ++ public synchronized void write(CompoundTag nbt, String paletteKey, String dataKey) { // Paper - synchronize + try { + this.acquire(); + HashMapPalette hashMapPalette = new HashMapPalette<>(this.registry, this.bits, this.dummyPaletteResize, this.reader, this.writer); diff --git a/patches/server/0690-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/server/0690-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch new file mode 100644 index 0000000000..14e1c84060 --- /dev/null +++ b/patches/server/0690-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 12 Sep 2018 21:47:01 -0400 +Subject: [PATCH] Optimize Biome Mob Lookups for Mob Spawning + +Uses an EnumMap as well as a Set paired List for O(1) contains calls. + +diff --git a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java +index 4e06bb1fbda33e79044ac54758b559f7436882a7..86528ff031014e788d72a8bf7c1c9443512096bb 100644 +--- a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java ++++ b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java +@@ -70,11 +70,43 @@ public class MobSpawnSettings { + } + + public static class Builder { +- private final Map> spawners = Stream.of(MobCategory.values()).collect(ImmutableMap.toImmutableMap((mobCategory) -> { ++ // Paper start - keep track of data in a pair set to give O(1) contains calls - we have to hook removals incase plugins mess with it ++ public static class MobList extends java.util.ArrayList { ++ java.util.Set biomes = new java.util.HashSet<>(); ++ ++ @Override ++ public boolean contains(Object o) { ++ return biomes.contains(o); ++ } ++ ++ @Override ++ public boolean add(MobSpawnSettings.SpawnerData BiomeSettingsMobs) { ++ biomes.add(BiomeSettingsMobs); ++ return super.add(BiomeSettingsMobs); ++ } ++ ++ @Override ++ public MobSpawnSettings.SpawnerData remove(int index) { ++ MobSpawnSettings.SpawnerData removed = super.remove(index); ++ if (removed != null) { ++ biomes.remove(removed); ++ } ++ return removed; ++ } ++ ++ @Override ++ public void clear() { ++ biomes.clear(); ++ super.clear(); ++ } ++ } ++ // use toImmutableEnumMap collector ++ private final Map> spawners = (Map) Stream.of(MobCategory.values()).collect(Maps.toImmutableEnumMap((mobCategory) -> { + return mobCategory; + }, (mobCategory) -> { +- return Lists.newArrayList(); ++ return new MobList(); // Use MobList instead of ArrayList + })); ++ // Paper end + private final Map, MobSpawnSettings.MobSpawnCost> mobSpawnCosts = Maps.newLinkedHashMap(); + private float creatureGenerationProbability = 0.1F; + private boolean playerCanSpawn; From f267238e0eadb935fa0aceded8f58413291a19e5 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 22:49:09 -0700 Subject: [PATCH 142/226] reorder patches after merge --- ...wnerSpawnEvent.patch => 0155-PreSpawnerSpawnEvent.patch} | 0 ...Add-Material-Tags.patch => 0156-Add-Material-Tags.patch} | 0 ...ty.patch => 0157-Add-LivingEntity-getTargetEntity.patch} | 2 +- ...sun-related-API.patch => 0158-Add-sun-related-API.patch} | 0 .../{0158-Here-s-Johnny.patch => 0159-Here-s-Johnny.patch} | 0 .../api/{0159-Turtle-API.patch => 0160-Turtle-API.patch} | 0 ...-events.patch => 0161-Add-spectator-target-events.patch} | 0 ...d-more-Witch-API.patch => 0162-Add-more-Witch-API.patch} | 0 ...-Make-the-default-permission-message-configurable.patch} | 0 ...port-cancellation-supression-of-EntityDismount-Ve.patch} | 0 ...more-Zombie-API.patch => 0165-Add-more-Zombie-API.patch} | 0 ...-Change-the-reserved-channel-check-to-be-sensible.patch} | 0 ...vent.patch => 0167-Add-PlayerConnectionCloseEvent.patch} | 0 ...8-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch} | 0 ...BlockDestroyEvent.patch => 0169-BlockDestroyEvent.patch} | 0 ...h => 0170-Add-ItemStack-Recipe-API-helper-methods.patch} | 0 ...oggleEvent.patch => 0171-Add-WhitelistToggleEvent.patch} | 0 ...est-changes.patch => 0172-Annotation-Test-changes.patch} | 0 ...nReason.patch => 0173-Entity-getEntitySpawnReason.patch} | 0 ...GS4-Query-event.patch => 0174-Add-GS4-Query-event.patch} | 0 ...awnEvent.patch => 0175-Add-PlayerPostRespawnEvent.patch} | 0 ...ore-package-private-methods-for-nullability-annot.patch} | 0 ...tch => 0177-Flip-some-Spigot-API-null-annotations.patch} | 0 ...rver-Tick-Events.patch => 0178-Server-Tick-Events.patch} | 0 ...eep.patch => 0179-PlayerDeathEvent-getItemsToKeep.patch} | 0 ...Add-Heightmap-API.patch => 0180-Add-Heightmap-API.patch} | 0 ...ements.patch => 0181-Mob-Spawner-API-Enhancements.patch} | 0 ...rface.patch => 0182-Add-BlockSoundGroup-interface.patch} | 0 ...nd-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch} | 0 ...0184-Increase-custom-payload-channel-message-size.patch} | 0 ...ck.patch => 0185-Expose-the-internal-current-tick.patch} | 0 ...tch => 0186-PlayerDeathEvent-shouldDropExperience.patch} | 0 ...patch => 0187-Add-effect-to-block-break-naturally.patch} | 0 ...istance-api.patch => 0188-World-view-distance-api.patch} | 0 ...gHatchEvent.patch => 0189-Add-ThrownEggHatchEvent.patch} | 0 ...189-Entity-Jump-API.patch => 0190-Entity-Jump-API.patch} | 0 ...nt.patch => 0191-add-hand-to-BlockMultiPlaceEvent.patch} | 0 ...d-tick-times-API.patch => 0192-Add-tick-times-API.patch} | 0 ...ng.patch => 0193-Expose-MinecraftServer-isRunning.patch} | 0 ...atch => 0194-Add-Raw-Byte-ItemStack-Serialization.patch} | 0 ...able-Sync-Events-firing-Async-errors-during-shutd.patch} | 0 ...e.patch => 0196-Make-JavaPluginLoader-thread-safe.patch} | 0 ...s-API.patch => 0197-Add-Player-Client-Options-API.patch} | 0 ... => 0198-Add-PlayerAttackEntityCooldownResetEvent.patch} | 0 ...-Potion-toItemStack-swapping-the-extended-and-upg.patch} | 0 ...s.patch => 0200-Add-item-slot-convenience-methods.patch} | 0 ...-Restocks-API.patch => 0201-Villager-Restocks-API.patch} | 2 +- ...1-Add-Mob-Goal-API.patch => 0202-Add-Mob-Goal-API.patch} | 0 ...ion-API.patch => 0203-Add-villager-reputation-API.patch} | 0 ...se-game-version.patch => 0204-Expose-game-version.patch} | 0 ...4-Spawn-Reason-API.patch => 0205-Spawn-Reason-API.patch} | 0 ...Potential-bed-API.patch => 0206-Potential-bed-API.patch} | 0 ...tch => 0207-Prioritise-own-classes-where-possible.patch} | 0 ... 0208-Provide-a-useful-PluginClassLoader-toString.patch} | 0 ...Inventory-getHolder-method-without-block-snapshot.patch} | 0 ...ItemStack.patch => 0210-Expose-Arrow-getItemStack.patch} | 0 ...0211-Add-and-implement-PlayerRecipeBookClickEvent.patch} | 0 ...Meta.patch => 0212-Support-components-in-ItemMeta.patch} | 0 ...3-added-2-new-TargetReasons-for-1.16-mob-behavior.patch} | 0 ...ty-liquid-API.patch => 0214-Add-entity-liquid-API.patch} | 0 ...215-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch} | 0 ...tch => 0216-Allow-delegation-to-vanilla-chunk-gen.patch} | 0 ...patch => 0217-Support-hex-colors-in-getLastColors.patch} | 0 ...axPlayers-API.patch => 0218-Add-setMaxPlayers-API.patch} | 0 ...d-moon-phase-API.patch => 0219-Add-moon-phase-API.patch} | 0 ... 0220-Add-playPickupItemAnimation-to-LivingEntity.patch} | 0 ...Add-BellRingEvent.patch => 0221-Add-BellRingEvent.patch} | 0 .../{0221-Brand-support.patch => 0222-Brand-support.patch} | 0 ...more-Evoker-API.patch => 0223-Add-more-Evoker-API.patch} | 0 ...-a-way-to-get-translation-keys-for-blocks-entitie.patch} | 0 ...h => 0225-Create-HoverEvent-from-ItemStack-Entity.patch} | 0 ...-Add-additional-open-container-api-to-HumanEntity.patch} | 0 ...ose-the-Entity-Counter-to-allow-plugins-to-use-va.patch} | 0 ...7-Entity-isTicking.patch => 0228-Entity-isTicking.patch} | 0 ...rify-the-Javadocs-for-Entity.getEntitySpawnReason.patch} | 0 ...er-resetOffers.patch => 0230-Villager-resetOffers.patch} | 0 ...a-boost-API.patch => 0231-Player-elytra-boost-API.patch} | 0 ...patch => 0232-Add-getOfflinePlayerIfCached-String.patch} | 0 ...counts-API.patch => 0233-Add-ignore-discounts-API.patch} | 0 ...pickup.patch => 0234-Item-no-age-no-player-pickup.patch} | 0 ...ges.patch => 0235-Beacon-API-custom-effect-ranges.patch} | 0 ...quit-reason.patch => 0236-Add-API-for-quit-reason.patch} | 0 ...roy-Speed-API.patch => 0237-Add-Destroy-Speed-API.patch} | 0 ...em.patch => 0238-Add-LivingEntity-clearActiveItem.patch} | 0 ...wnEvent.patch => 0239-Add-PlayerItemCooldownEvent.patch} | 0 ...re-lightning-API.patch => 0240-More-lightning-API.patch} | 0 ...lockEvent.patch => 0241-Add-PlayerShearBlockEvent.patch} | 0 ...rs.patch => 0242-Enable-multi-release-plugin-jars.patch} | 0 ...nts.patch => 0243-Player-Chunk-Load-Unload-Events.patch} | 0 ....patch => 0244-Expose-LivingEntity-hurt-direction.patch} | 0 ...h => 0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} | 0 ...erTradeEvent.patch => 0246-Added-PlayerTradeEvent.patch} | 0 ...HitEvent-API.patch => 0247-Add-TargetHitEvent-API.patch} | 0 ...I-s.patch => 0248-Additional-Block-Material-API-s.patch} | 0 ...-Add-API-to-get-Material-from-Boats-and-Minecarts.patch} | 0 ....patch => 0250-Add-PlayerFlowerPotManipulateEvent.patch} | 0 ...ing-doors.patch => 0251-Zombie-API-breaking-doors.patch} | 0 ...owEvent.patch => 0252-Add-EntityLoadCrossbowEvent.patch} | 0 ...vent.patch => 0253-Added-WorldGameRuleChangeEvent.patch} | 0 ....patch => 0254-Added-ServerResourcesReloadedEvent.patch} | 0 ...eEvent.patch => 0255-Add-BlockFailedDispenseEvent.patch} | 0 ....patch => 0256-Added-PlayerLecternPageChangeEvent.patch} | 0 ....patch => 0257-Added-PlayerLoomPatternSelectEvent.patch} | 0 ...tout.patch => 0258-Better-AnnotationTest-printout.patch} | 0 ...-API-to-get-exact-interaction-point-in-PlayerInte.patch} | 0 ...sendOpLevel-API.patch => 0260-Add-sendOpLevel-API.patch} | 0 ...ocateEvent.patch => 0261-Add-StructureLocateEvent.patch} | 0 ...urn-chat-component-with-empty-text-instead-of-thr.patch} | 0 ...enseEvent.patch => 0263-Add-BlockPreDispenseEvent.patch} | 0 ...tity-Tags.patch => 0264-Added-Vanilla-Entity-Tags.patch} | 0 ...4-added-Wither-API.patch => 0265-added-Wither-API.patch} | 0 ...patch => 0266-Added-PlayerChangeBeaconEffectEvent.patch} | 0 ... => 0267-Added-PlayerStonecutterRecipeSelectEvent.patch} | 0 ...0268-Add-dropLeash-variable-to-EntityUnleashEvent.patch} | 0 ...268-EntityMoveEvent.patch => 0269-EntityMoveEvent.patch} | 0 ...EggFormEvent.patch => 0270-add-DragonEggFormEvent.patch} | 0 ... => 0271-Allow-adding-items-to-BlockDropItemEvent.patch} | 0 ...0272-Add-getMainThreadExecutor-to-BukkitScheduler.patch} | 0 ...> 0273-living-entity-allow-attribute-registration.patch} | 0 ...missing-effects.patch => 0274-Add-missing-effects.patch} | 0 ...cked-Players.patch => 0275-Expose-Tracked-Players.patch} | 0 ...atch => 0276-Cache-the-result-of-Material-isBlock.patch} | 0 ...order-events.patch => 0277-Add-worldborder-events.patch} | 0 ...tyEvent.patch => 0278-added-PlayerNameEntityEvent.patch} | 0 ...ok-events.patch => 0279-Add-recipe-to-cook-events.patch} | 0 ...k-isValidTool.patch => 0280-Add-Block-isValidTool.patch} | 0 ...d-on-World.patch => 0281-Implement-Keyed-on-World.patch} | 0 ...> 0282-fix-Inventory-getContents-null-annotations.patch} | 0 ...282-Item-Rarity-API.patch => 0283-Item-Rarity-API.patch} | 0 ...col-version.patch => 0284-Expose-protocol-version.patch} | 0 ...ow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} | 0 ...patch => 0286-add-isDeeplySleeping-to-HumanEntity.patch} | 0 ...patch => 0287-add-consumeFuel-to-FurnaceBurnEvent.patch} | 0 ...> 0288-add-get-set-drop-chance-to-EntityEquipment.patch} | 0 ...eepEvent.patch => 0289-Added-PlayerDeepSleepEvent.patch} | 0 ...{0289-More-World-API.patch => 0290-More-World-API.patch} | 0 ...Event.patch => 0291-Added-PlayerBedFailEnterEvent.patch} | 0 ...2-Introduce-beacon-activation-deactivation-events.patch} | 0 ...ements.patch => 0293-PlayerMoveEvent-Improvements.patch} | 0 ...ch => 0294-add-RespawnFlags-to-PlayerRespawnEvent.patch} | 0 ...er-API.patch => 0295-Add-more-WanderingTrader-API.patch} | 0 ...atch => 0296-Add-EntityBlockStorage-clearEntities.patch} | 0 ...d-Adventure-message-to-PlayerAdvancementDoneEvent.patch} | 0 ... 0298-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch} | 0 ...298-Inventory-close.patch => 0299-Inventory-close.patch} | 0 ...-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch} | 0 ...Datapack-API.patch => 0301-Add-basic-Datapack-API.patch} | 0 ...ch => 0302-additions-to-PlayerGameModeChangeEvent.patch} | 0 ...heck-API.patch => 0303-ItemStack-repair-check-API.patch} | 0 ...nchantment-API.patch => 0304-More-Enchantment-API.patch} | 0 ...-command-line-option-to-load-extra-plugin-jars-no.patch} | 0 ...0306-List-all-missing-hard-depends-not-just-first.patch} | 0 ...d-Mob-lookAt-API.patch => 0307-Add-Mob-lookAt-API.patch} | 0 ...emStack-editMeta.patch => 0308-ItemStack-editMeta.patch} | 0 ...ockEvent.patch => 0309-Add-EntityInsideBlockEvent.patch} | 0 ...ts.patch => 0310-Attributes-API-for-item-defaults.patch} | 0 ... => 0311-Add-cause-to-Weather-ThunderChangeEvents.patch} | 0 ...ded-Block-API.patch => 0312-More-Lidded-Block-API.patch} | 0 ...t-causes.patch => 0313-Add-PlayerKickEvent-causes.patch} | 0 ...vent.patch => 0314-Add-PufferFishStateChangeEvent.patch} | 0 ...iderEvent.patch => 0315-Add-BellRevealRaiderEvent.patch} | 0 ...nt.patch => 0316-Add-ElderGuardianAppearanceEvent.patch} | 0 ...hods.patch => 0317-Add-more-line-of-sight-methods.patch} | 0 ...wnerSpawnEvent.patch => 0291-PreSpawnerSpawnEvent.patch} | 2 +- ... => 0292-Don-t-allow-digging-into-unloaded-chunks.patch} | 2 +- ...-Make-the-default-permission-message-configurable.patch} | 0 ...atch => 0294-Prevent-rayTrace-from-loading-chunks.patch} | 0 ...=> 0295-Handle-Large-Packets-disconnecting-client.patch} | 0 ...> 0296-force-entity-dismount-during-teleportation.patch} | 4 ++-- ...more-Zombie-API.patch => 0297-Add-more-Zombie-API.patch} | 0 ...7-Book-Size-Limits.patch => 0298-Book-Size-Limits.patch} | 2 +- ...vent.patch => 0299-Add-PlayerConnectionCloseEvent.patch} | 0 ...atch => 0300-Prevent-Enderman-from-loading-chunks.patch} | 0 ...1-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch} | 2 +- ...rkaround-for-vehicle-tracking-issue-on-disconnect.patch} | 2 +- ...ire-BlockPistonRetractEvent-for-all-empty-pistons.patch} | 0 ...-Block-Entity-remove-from-being-called-on-Players.patch} | 0 ...BlockDestroyEvent.patch => 0305-BlockDestroyEvent.patch} | 0 ...0306-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch} | 0 ...-more.patch => 0307-Limit-Client-Sign-length-more.patch} | 2 +- ...-Don-t-check-ConvertSigns-boolean-every-sign-save.patch} | 0 ...imize-Network-Manager-and-add-advanced-packet-sup.patch} | 0 ... => 0310-Handle-Oversized-Tile-Entities-in-chunks.patch} | 0 ...0311-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch} | 0 ...Set-Zombie-last-tick-at-start-of-drowning-process.patch} | 0 ...ll-WhitelistToggleEvent-when-whitelist-is-toggled.patch} | 0 ...-proper-max-length-when-serialising-BungeeCord-te.patch} | 0 ...nReason.patch => 0315-Entity-getEntitySpawnReason.patch} | 4 ++-- ...16-Update-entity-Metadata-for-all-tracked-players.patch} | 2 +- ...n-GS4-query.patch => 0317-Fire-event-on-GS4-query.patch} | 0 ...nt.patch => 0318-Implement-PlayerPostRespawnEvent.patch} | 0 ...-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch} | 0 ...rver-Tick-Events.patch => 0320-Server-Tick-Events.patch} | 0 ...eep.patch => 0321-PlayerDeathEvent-getItemsToKeep.patch} | 2 +- ...patch => 0322-Optimize-Captured-TileEntity-Lookup.patch} | 0 ...Add-Heightmap-API.patch => 0323-Add-Heightmap-API.patch} | 0 ...ements.patch => 0324-Mob-Spawner-API-Enhancements.patch} | 2 +- ...25-Fix-CB-call-to-changed-postToMainThread-method.patch} | 2 +- ...ix-sounds-when-item-frames-are-modified-MC-123450.patch} | 0 ...-CraftServer-isPrimaryThread-and-MinecraftServer-.patch} | 0 ...ed.patch => 0328-improve-CraftWorld-isChunkLoaded.patch} | 0 ...29-Configurable-Keep-Spawn-Loaded-range-per-world.patch} | 0 ...apDistance-CME.patch => 0330-ChunkMapDistance-CME.patch} | 0 ...roup.patch => 0331-Implement-CraftBlockSoundGroup.patch} | 0 ...k-debug-command.patch => 0332-Chunk-debug-command.patch} | 0 ...ls.patch => 0333-Fix-World-isChunkGenerated-calls.patch} | 0 ...-Show-blockstate-location-if-we-failed-to-read-it.patch} | 0 ...y-count-Natural-Spawned-mobs-towards-natural-spaw.patch} | 0 ...=> 0336-Configurable-projectile-relative-velocity.patch} | 0 ...e-ticking.patch => 0337-offset-item-frame-ticking.patch} | 0 ...Do-less-work-if-we-have-a-custom-Bukkit-generator.patch} | 0 .../{0338-Fix-MC-158900.patch => 0339-Fix-MC-158900.patch} | 0 ...tch => 0340-Prevent-consuming-the-wrong-itemstack.patch} | 0 ...nerator-Settings.patch => 0341-Generator-Settings.patch} | 0 .../{0341-Fix-MC-161754.patch => 0342-Fix-MC-161754.patch} | 0 ...-spawning-of-hanging-entities-that-are-not-ItemFr.patch} | 0 ...ck.patch => 0344-Expose-the-internal-current-tick.patch} | 0 ...-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch} | 2 +- ...ch => 0346-Add-option-to-disable-pillager-patrols.patch} | 0 ...-AssertionError-when-player-hand-set-to-empty-typ.patch} | 2 +- ...vent-sync-chunk-loads-when-villagers-try-to-find-.patch} | 0 ...=> 0349-MC-145656-Fix-Follow-Range-Initial-Target.patch} | 0 ...9-Optimize-Hoppers.patch => 0350-Optimize-Hoppers.patch} | 0 ...tch => 0351-PlayerDeathEvent-shouldDropExperience.patch} | 2 +- ...revent-bees-loading-chunks-checking-hive-position.patch} | 0 ...3-Don-t-load-Chunks-from-Hoppers-and-other-things.patch} | 0 ...rd-against-serializing-mismatching-chunk-coordina.patch} | 0 ...ch => 0355-Optimise-IEntityAccess-getPlayerByUUID.patch} | 0 ...tly.patch => 0356-Fix-items-not-falling-correctly.patch} | 0 ...ensate-eating.patch => 0357-Lag-compensate-eating.patch} | 0 ... => 0358-Optimize-call-to-getFluid-for-explosions.patch} | 0 ...-last-firework-in-stack-not-having-effects-when-d.patch} | 0 ...patch => 0360-Add-effect-to-block-break-naturally.patch} | 0 ...nge-2.0.patch => 0361-Entity-Activation-Range-2.0.patch} | 6 +++--- ...ueue-Size.patch => 0362-Increase-Light-Queue-Size.patch} | 0 ...Fix-Light-Command.patch => 0363-Fix-Light-Command.patch} | 0 ...atch => 0364-No-Tick-view-distance-implementation.patch} | 2 +- ...h => 0365-Implement-alternative-item-despawn-rate.patch} | 0 ...vements.patch => 0366-Tracking-Range-Improvements.patch} | 0 ...ch => 0367-Fix-items-vanishing-through-end-portal.patch} | 2 +- ... => 0368-implement-optional-per-player-mob-spawns.patch} | 2 +- ...=> 0369-Bees-get-gravity-in-void.-Fixes-MC-167279.patch} | 0 ... 0370-Optimise-getChunkAt-calls-for-loaded-chunks.patch} | 0 ...h => 0371-Allow-overriding-the-java-version-check.patch} | 0 ...gHatchEvent.patch => 0372-Add-ThrownEggHatchEvent.patch} | 0 ...cking.patch => 0373-Optimise-random-block-ticking.patch} | 0 ...373-Entity-Jump-API.patch => 0374-Entity-Jump-API.patch} | 0 ...375-Add-option-to-nerf-pigmen-from-nether-portals.patch} | 2 +- ...-fancier.patch => 0376-Make-the-GUI-graph-fancier.patch} | 0 ...nt.patch => 0377-add-hand-to-BlockMultiPlaceEvent.patch} | 2 +- ...s.patch => 0378-Prevent-teleporting-dead-entities.patch} | 2 +- ...79-Validate-tripwire-hook-placement-before-update.patch} | 0 ...0-Add-option-to-allow-iron-golems-to-spawn-in-air.patch} | 0 ...-Configurable-chance-of-villager-zombie-infection.patch} | 0 ...nk-getFluid.patch => 0382-Optimise-Chunk-getFluid.patch} | 0 ...h => 0383-Optimise-TickListServer-by-rewriting-it.patch} | 0 ...lager-patrol-spawn-settings-and-per-player-option.patch} | 2 +- ...385-Remote-Connections-shouldn-t-hold-up-shutdown.patch} | 0 ...386-Do-not-allow-bees-to-load-chunks-for-beehives.patch} | 2 +- ...revent-Double-PlayerChunkMap-adds-crashing-server.patch} | 0 ...tch => 0388-Optimize-Collision-to-not-load-chunks.patch} | 2 +- ...ead-players.patch => 0389-Don-t-tick-dead-players.patch} | 2 +- ...h => 0390-Dead-Player-s-shouldn-t-be-able-to-move.patch} | 0 ...imize-PlayerChunkMap-memory-use-for-visibleChunks.patch} | 0 ...-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch} | 0 ...> 0393-Don-t-move-existing-players-to-world-spawn.patch} | 2 +- ...patch => 0394-Add-tick-times-API-and-mspt-command.patch} | 0 ...ng.patch => 0395-Expose-MinecraftServer-isRunning.patch} | 0 ...atch => 0396-Add-Raw-Byte-ItemStack-Serialization.patch} | 0 ...m.patch => 0397-Remove-streams-from-Mob-AI-System.patch} | 0 ...building.patch => 0398-Async-command-map-building.patch} | 0 ...g-Support.patch => 0399-Improved-Watchdog-Support.patch} | 0 ...ze-Pathfinding.patch => 0400-Optimize-Pathfinding.patch} | 0 ...n.patch => 0401-Reduce-Either-Optional-allocation.patch} | 0 ...eue.patch => 0402-Remove-streams-from-PairedQueue.patch} | 0 ...=> 0403-Reduce-memory-footprint-of-NBTTagCompound.patch} | 0 ...h => 0404-Prevent-opening-inventories-when-frozen.patch} | 2 +- ...If.patch => 0405-Optimise-ArraySetSorted-removeIf.patch} | 0 ...406-Don-t-run-entity-collision-code-if-not-needed.patch} | 0 ...trict-vanilla-teleport-command-to-valid-locations.patch} | 0 ...patch => 0408-Implement-Player-Client-Options-API.patch} | 2 +- ...h => 0409-Fix-Chunk-Post-Processing-deadlock-risk.patch} | 0 ...-t-crash-if-player-is-attempted-to-be-removed-fro.patch} | 0 ...e.patch => 0411-Broadcast-join-message-to-console.patch} | 0 ...x-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch} | 2 +- ...atch => 0413-Load-Chunks-for-Login-Asynchronously.patch} | 6 +++--- ...e-player-to-spawn-point-if-spawn-in-unloaded-worl.patch} | 2 +- ... => 0415-Add-PlayerAttackEntityCooldownResetEvent.patch} | 0 ...ow-multiple-callbacks-to-schedule-for-Callback-Ex.patch} | 0 ... => 0417-Don-t-fire-BlockFade-on-worldgen-threads.patch} | 0 ... 0418-Add-phantom-creative-and-insomniac-controls.patch} | 0 ...-numerous-item-duplication-issues-and-teleport-is.patch} | 4 ++-- ...-API.patch => 0420-Implement-Brigadier-Mojang-API.patch} | 4 ++-- ...-Restocks-API.patch => 0421-Villager-Restocks-API.patch} | 4 ++-- ...422-Validate-PickItem-Packet-and-kick-for-invalid.patch} | 2 +- ...se-game-version.patch => 0423-Expose-game-version.patch} | 0 ...erging.patch => 0424-Optimize-Voxel-Shape-Merging.patch} | 0 ...et-cap-on-JDK-per-thread-native-byte-buffer-cache.patch} | 0 ...Mob-Goal-API.patch => 0426-Implement-Mob-Goal-API.patch} | 2 +- ... 0427-Use-distance-map-to-optimise-entity-tracker.patch} | 2 +- ...0428-Optimize-isOutsideRange-to-use-distance-maps.patch} | 2 +- ...ion-API.patch => 0429-Add-villager-reputation-API.patch} | 0 ...30-Option-for-maximum-exp-value-when-merging-orbs.patch} | 2 +- ...bMergeEvent.patch => 0431-ExperienceOrbMergeEvent.patch} | 2 +- ....patch => 0432-Fix-PotionEffect-ignores-icon-flag.patch} | 2 +- ...0433-Optimize-brigadier-child-sorting-performance.patch} | 0 ...Potential-bed-API.patch => 0434-Potential-bed-API.patch} | 0 ...atch => 0435-Wait-for-Async-Tasks-during-shutdown.patch} | 0 ...ure-EntityRaider-respects-game-and-entity-rules-f.patch} | 0 ...tect-Bedrock-and-End-Portal-Frames-from-being-des.patch} | 0 ...8-Reduce-MutableInt-allocations-from-light-engine.patch} | 0 ...0439-Reduce-allocation-of-Vec3D-by-entity-tracker.patch} | 0 ...leport.patch => 0440-Ensure-safe-gateway-teleport.patch} | 0 ...441-Add-option-for-console-having-all-permissions.patch} | 0 ...=> 0442-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch} | 0 ...imize-sending-packets-to-nearby-locations-sounds-.patch} | 0 ...tch => 0444-Fix-villager-trading-demand-MC-163962.patch} | 0 ...d-chunks.patch => 0445-Maps-shouldn-t-load-chunks.patch} | 0 ...-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch} | 0 ...0447-Delay-Chunk-Unloads-based-on-Player-Movement.patch} | 0 ...patch => 0448-Optimize-Bit-Operations-by-inlining.patch} | 0 ...unk-saving.patch => 0449-incremental-chunk-saving.patch} | 0 ...h => 0450-Add-Plugin-Tickets-to-API-Chunk-Methods.patch} | 0 ...> 0451-Fix-missing-chunks-due-to-integer-overflow.patch} | 0 ...-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch} | 0 ...> 0453-Fix-piston-physics-inconsistency-MC-188840.patch} | 0 ...453-Fix-sand-duping.patch => 0454-Fix-sand-duping.patch} | 0 ...vent-position-desync-in-playerconnection-causing-.patch} | 2 +- ...Inventory-getHolder-method-without-block-snapshot.patch} | 0 ...ItemStack.patch => 0457-Expose-Arrow-getItemStack.patch} | 0 ...0458-Add-and-implement-PlayerRecipeBookClickEvent.patch} | 2 +- ....patch => 0459-Hide-sync-chunk-writes-behind-flag.patch} | 0 ...s.patch => 0460-Add-permission-for-command-blocks.patch} | 2 +- ...ch => 0461-Ensure-Entity-AABB-s-are-never-invalid.patch} | 2 +- ...462-Optimize-WorldBorder-collision-checks-and-air.patch} | 2 +- ...3-Fix-Per-World-Difficulty-Remembering-Difficulty.patch} | 2 +- ...item-command.patch => 0464-Paper-dumpitem-command.patch} | 0 ...at.patch => 0465-Don-t-allow-null-UUID-s-for-chat.patch} | 0 ... 0466-Improve-Legacy-Component-serialization-size.patch} | 0 ...NBT.patch => 0467-Support-old-UUID-format-for-NBT.patch} | 0 ...> 0468-Clean-up-duplicated-GameProfile-Properties.patch} | 2 +- ...ch => 0469-Convert-legacy-attributes-in-Item-Meta.patch} | 0 ...mplement-Chunk-Priority-Urgency-System-for-Chunks.patch} | 4 ++-- ...patch => 0471-Remove-some-streams-from-structures.patch} | 0 ...move-streams-from-classes-related-villager-gossip.patch} | 0 ...Meta.patch => 0473-Support-components-in-ItemMeta.patch} | 0 ...prove-EntityTargetLivingEntityEvent-for-1.16-mobs.patch} | 0 ...ty-liquid-API.patch => 0475-Add-entity-liquid-API.patch} | 0 ...tch => 0476-Update-itemstack-legacy-name-and-lore.patch} | 0 ...ch => 0477-Spawn-player-in-correct-world-on-login.patch} | 0 ...eResultEvent.patch => 0478-Add-PrepareResultEvent.patch} | 0 ...tch => 0479-Allow-delegation-to-vanilla-chunk-gen.patch} | 0 ...-t-check-chunk-for-portal-on-world-gen-entity-add.patch} | 0 ...> 0481-Optimize-NetworkManager-Exception-Handling.patch} | 0 ...imize-the-advancement-data-player-iteration-to-be.patch} | 0 ...tch => 0483-Fix-arrows-never-despawning-MC-125757.patch} | 0 ...4-Thread-Safe-Vanilla-Command-permission-checking.patch} | 0 ...tch => 0485-Move-range-check-for-block-placing-up.patch} | 0 ...485-Fix-SPIGOT-5989.patch => 0486-Fix-SPIGOT-5989.patch} | 0 ...ix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch} | 0 ...88-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch} | 0 ...-AdvancementDataPlayer-leak-due-from-quitting-ear.patch} | 0 ...-missing-strikeLighting-call-to-World-spigot-stri.patch} | 0 ...atch => 0491-Fix-some-rails-connecting-improperly.patch} | 0 ...er-saving.patch => 0492-Incremental-player-saving.patch} | 0 ...patch => 0493-Fix-MC-187716-Use-configured-height.patch} | 0 ...4-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch} | 0 ...not-let-the-server-load-chunks-from-newer-version.patch} | 0 .../{0495-Brand-support.patch => 0496-Brand-support.patch} | 0 ...axPlayers-API.patch => 0497-Add-setMaxPlayers-API.patch} | 0 ... 0498-Add-playPickupItemAnimation-to-LivingEntity.patch} | 0 ...CING-data.patch => 0499-Don-t-require-FACING-data.patch} | 0 ...Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch} | 0 ...d-moon-phase-API.patch => 0501-Add-moon-phase-API.patch} | 0 ... 0502-Prevent-headless-pistons-from-being-created.patch} | 0 ...Add-BellRingEvent.patch => 0503-Add-BellRingEvent.patch} | 0 ...atch => 0504-Add-zombie-targets-turtle-egg-config.patch} | 0 ...oins-to-world.patch => 0505-Buffer-joins-to-world.patch} | 0 ...gorithm.patch => 0506-Optimize-redstone-algorithm.patch} | 0 ...-Fix-hex-colors-not-working-in-some-kick-messages.patch} | 0 ...> 0508-PortalCreateEvent-needs-to-know-its-entity.patch} | 0 ...null-check.patch => 0509-Fix-CraftTeam-null-check.patch} | 0 ...more-Evoker-API.patch => 0510-Add-more-Evoker-API.patch} | 0 ...-a-way-to-get-translation-keys-for-blocks-entitie.patch} | 0 ...h => 0512-Create-HoverEvent-from-ItemStack-Entity.patch} | 0 ...ta-strings.patch => 0513-Cache-block-data-strings.patch} | 0 ...-Entity-Teleportation-and-cancel-velocity-if-tele.patch} | 2 +- ...-Add-additional-open-container-api-to-HumanEntity.patch} | 0 ...0516-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch} | 0 ...end-block-drop-capture-to-capture-all-items-added.patch} | 0 ...Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch} | 0 ...ose-the-Entity-Counter-to-allow-plugins-to-use-va.patch} | 0 ...> 0520-Lazily-track-plugin-scoreboards-by-default.patch} | 0 ...0-Entity-isTicking.patch => 0521-Entity-isTicking.patch} | 0 ...-deop-kicking-non-whitelisted-player-when-white-l.patch} | 0 ...x-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch} | 0 ...atch => 0524-Reset-Ender-Crystals-on-Dragon-Spawn.patch} | 0 ...> 0525-Fix-for-large-move-vectors-crashing-server.patch} | 0 ...etType-calls.patch => 0526-Optimise-getType-calls.patch} | 0 ...er-resetOffers.patch => 0527-Villager-resetOffers.patch} | 0 ...8-Improve-inlinig-for-some-hot-IBlockData-methods.patch} | 0 ...tain-block-place-order-when-capturing-blockstates.patch} | 0 ... 0530-Reduce-blockpos-allocation-from-pathfinding.patch} | 0 ...=> 0531-Fix-item-locations-dropped-from-campfires.patch} | 0 ...a-boost-API.patch => 0532-Player-elytra-boost-API.patch} | 0 ...ak.patch => 0533-Fixed-TileEntityBell-memory-leak.patch} | 0 ...id-error-bubbling-up-when-item-stack-is-empty-in-.patch} | 0 ...patch => 0535-Add-getOfflinePlayerIfCached-String.patch} | 0 ...counts-API.patch => 0536-Add-ignore-discounts-API.patch} | 0 ...patch => 0537-Toggle-for-removing-existing-dragon.patch} | 0 ...tch => 0538-Fix-client-lag-on-advancement-loading.patch} | 0 ...pickup.patch => 0539-Item-no-age-no-player-pickup.patch} | 0 ...ges.patch => 0540-Beacon-API-custom-effect-ranges.patch} | 0 ...quit-reason.patch => 0541-Add-API-for-quit-reason.patch} | 0 ...re-search.patch => 0542-Seed-based-feature-search.patch} | 0 ...43-Add-Wandering-Trader-spawn-rate-config-options.patch} | 0 ...nificantly-improve-performance-of-the-end-generat.patch} | 0 ...pawn-angle.patch => 0545-Expose-world-spawn-angle.patch} | 0 ...roy-Speed-API.patch => 0546-Add-Destroy-Speed-API.patch} | 0 ...547-Fix-Player-spawnParticle-x-y-z-precision-loss.patch} | 0 ...em.patch => 0548-Add-LivingEntity-clearActiveItem.patch} | 0 ...wnEvent.patch => 0549-Add-PlayerItemCooldownEvent.patch} | 0 ...re-lightning-API.patch => 0550-More-lightning-API.patch} | 0 ...0551-Climbing-should-not-bypass-cramming-gamerule.patch} | 0 ... => 0552-Added-missing-default-perms-for-commands.patch} | 0 ...lockEvent.patch => 0553-Add-PlayerShearBlockEvent.patch} | 0 ...Set-spigots-verbose-world-setting-to-false-by-def.patch} | 0 ... 0555-Fix-curing-zombie-villager-discount-exploit.patch} | 0 ...recipe-packets.patch => 0556-Limit-recipe-packets.patch} | 0 ...ch => 0557-Fix-CraftSound-backwards-compatibility.patch} | 0 ...esync.patch => 0558-MC-4-Fix-item-position-desync.patch} | 0 ...nts.patch => 0559-Player-Chunk-Load-Unload-Events.patch} | 0 ...s.patch => 0560-Optimize-Dynamic-get-Missing-Keys.patch} | 0 ....patch => 0561-Expose-LivingEntity-hurt-direction.patch} | 0 ...h => 0562-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} | 0 ...not-crash-from-invalid-ingredient-lists-in-Villag.patch} | 0 ...erTradeEvent.patch => 0564-added-PlayerTradeEvent.patch} | 0 ...etHitEvent.patch => 0565-Implement-TargetHitEvent.patch} | 0 ...I-s.patch => 0566-Additional-Block-Material-API-s.patch} | 0 ...potion-dupe.patch => 0567-Fix-harming-potion-dupe.patch} | 0 ...lement-API-to-get-Material-from-Boats-and-Minecar.patch} | 0 ...burn-durations.patch => 0569-Cache-burn-durations.patch} | 0 ...ow-disabling-mob-spawner-spawn-egg-transformation.patch} | 0 ... => 0571-Implement-PlayerFlowerPotManipulateEvent.patch} | 0 ...-Fix-interact-event-not-being-called-in-adventure.patch} | 0 ...ing-doors.patch => 0573-Zombie-API-breaking-doors.patch} | 0 ...ing.patch => 0574-Fix-nerfed-slime-when-splitting.patch} | 0 ...owEvent.patch => 0575-Add-EntityLoadCrossbowEvent.patch} | 0 ...workaround.patch => 0576-Guardian-beam-workaround.patch} | 0 ...vent.patch => 0577-Added-WorldGameRuleChangeEvent.patch} | 0 ....patch => 0578-Added-ServerResourcesReloadedEvent.patch} | 0 ...579-Added-world-settings-for-mobs-picking-up-loot.patch} | 0 ...atch => 0580-Implemented-BlockFailedDispenseEvent.patch} | 0 ....patch => 0581-Added-PlayerLecternPageChangeEvent.patch} | 0 ....patch => 0582-Added-PlayerLoomPatternSelectEvent.patch} | 0 ...tch => 0583-Configurable-door-breaking-difficulty.patch} | 0 ...ch => 0584-Empty-commands-shall-not-be-dispatched.patch} | 0 ...5-Implement-API-to-expose-exact-interaction-point.patch} | 0 ...Remove-stale-POIs.patch => 0586-Remove-stale-POIs.patch} | 0 ...t-exploit.patch => 0587-Fix-villager-boat-exploit.patch} | 0 ...sendOpLevel-API.patch => 0588-Add-sendOpLevel-API.patch} | 0 ...ocateEvent.patch => 0589-Add-StructureLocateEvent.patch} | 0 ...llision-option-for-requiring-a-player-participant.patch} | 0 ...emove-ProjectileHitEvent-call-when-fireballs-dead.patch} | 0 ...urn-chat-component-with-empty-text-instead-of-thr.patch} | 0 ...rld.patch => 0593-Make-schedule-command-per-world.patch} | 0 ...nce.patch => 0594-Configurable-max-leash-distance.patch} | 0 ...ent.patch => 0595-Implement-BlockPreDispenseEvent.patch} | 0 ...tity-Tags.patch => 0596-Added-Vanilla-Entity-Tags.patch} | 0 ...6-added-Wither-API.patch => 0597-added-Wither-API.patch} | 0 ...598-Added-firing-of-PlayerChangeBeaconEffectEvent.patch} | 0 ...99-Fix-console-spam-when-removing-chests-in-water.patch} | 0 ...0600-Add-toggle-for-always-placing-the-dragon-egg.patch} | 0 ... => 0601-Added-PlayerStonecutterRecipeSelectEvent.patch} | 0 ...0602-Add-dropLeash-variable-to-EntityUnleashEvent.patch} | 0 ...3-Skip-distance-map-update-when-spawning-disabled.patch} | 0 ...=> 0604-Reset-shield-blocking-on-dimension-change.patch} | 0 ...EggFormEvent.patch => 0605-add-DragonEggFormEvent.patch} | 0 ...605-EntityMoveEvent.patch => 0606-EntityMoveEvent.patch} | 0 ...ed-option-to-disable-pathfinding-updates-on-block.patch} | 0 ...ields.patch => 0608-Inline-shift-direction-fields.patch} | 0 ... => 0609-Allow-adding-items-to-BlockDropItemEvent.patch} | 0 ...0610-Add-getMainThreadExecutor-to-BukkitScheduler.patch} | 0 ...> 0611-living-entity-allow-attribute-registration.patch} | 0 ...atch => 0612-fix-dead-slime-setSize-invincibility.patch} | 0 ...rchant-getRecipes-should-return-an-immutable-list.patch} | 0 ...ebugging-dumps.patch => 0614-misc-debugging-dumps.patch} | 0 ...> 0615-Add-support-for-hex-color-codes-in-console.patch} | 0 ...cked-Players.patch => 0616-Expose-Tracked-Players.patch} | 0 ...t.patch => 0617-Remove-streams-from-SensorNearest.patch} | 0 ...618-MC-29274-Fix-Wither-hostility-towards-players.patch} | 0 ...619-Throw-proper-exception-on-empty-JsonList-file.patch} | 0 ...Improve-ServerGUI.patch => 0620-Improve-ServerGUI.patch} | 0 ...p-firing-pressure-plate-EntityInteractEvent-for-i.patch} | 0 ...ile.patch => 0622-fix-converting-txt-to-json-file.patch} | 0 ...order-events.patch => 0623-Add-worldborder-events.patch} | 0 ...tyEvent.patch => 0624-added-PlayerNameEntityEvent.patch} | 0 ... 0625-Prevent-grindstones-from-overstacking-items.patch} | 0 ...ok-events.patch => 0626-Add-recipe-to-cook-events.patch} | 0 ...k-isValidTool.patch => 0627-Add-Block-isValidTool.patch} | 0 ...=> 0628-Allow-using-signs-inside-spawn-protection.patch} | 0 ...d-on-World.patch => 0629-Implement-Keyed-on-World.patch} | 0 ...30-Add-fast-alternative-constructor-for-Rotations.patch} | 0 ...630-Item-Rarity-API.patch => 0631-Item-Rarity-API.patch} | 0 ...y-set-despawnTimer-for-Wandering-Traders-spawned-.patch} | 0 ...tch => 0633-copy-TESign-isEditable-from-snapshots.patch} | 0 ...34-Drop-carried-item-when-player-has-disconnected.patch} | 0 ...35-forced-whitelist-use-configurable-kick-message.patch} | 0 ...> 0636-Don-t-ignore-result-of-PlayerEditBookEvent.patch} | 0 ...ix-cancelling-block-falling-causing-client-desync.patch} | 0 ...col-version.patch => 0638-Expose-protocol-version.patch} | 0 ...ow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} | 0 ...ance-console-tab-completions-for-brigadier-comman.patch} | 0 ...41-Fix-PlayerItemConsumeEvent-cancelling-properly.patch} | 0 ...ss-host-check.patch => 0642-Add-bypass-host-check.patch} | 0 ...tion.patch => 0643-Set-area-affect-cloud-rotation.patch} | 0 ...patch => 0644-add-isDeeplySleeping-to-HumanEntity.patch} | 0 ...45-Fix-duplicating-give-items-on-item-drop-cancel.patch} | 0 ...patch => 0646-add-consumeFuel-to-FurnaceBurnEvent.patch} | 0 ...> 0647-add-get-set-drop-chance-to-EntityEquipment.patch} | 0 ...atch => 0648-fix-PigZombieAngerEvent-cancellation.patch} | 0 ...ch => 0649-Fix-checkReach-check-for-Shulker-boxes.patch} | 0 ...atch => 0650-fix-PlayerItemHeldEvent-firing-twice.patch} | 0 ...eepEvent.patch => 0651-Added-PlayerDeepSleepEvent.patch} | 0 ...{0651-More-World-API.patch => 0652-More-World-API.patch} | 0 ...Event.patch => 0653-Added-PlayerBedFailEnterEvent.patch} | 0 ...lement-methods-to-convert-between-Component-and-B.patch} | 0 ...-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch} | 0 ...6-Introduce-beacon-activation-deactivation-events.patch} | 0 ...ch => 0657-add-RespawnFlags-to-PlayerRespawnEvent.patch} | 0 ...atch => 0658-Add-Channel-initialization-listeners.patch} | 0 ...Send-empty-commands-if-tab-completion-is-disabled.patch} | 0 ...er-API.patch => 0660-Add-more-WanderingTrader-API.patch} | 0 ...atch => 0661-Add-EntityBlockStorage-clearEntities.patch} | 0 ...d-Adventure-message-to-PlayerAdvancementDoneEvent.patch} | 0 ... 0663-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch} | 0 ...663-Inventory-close.patch => 0664-Inventory-close.patch} | 0 ...5-call-PortalCreateEvent-players-and-end-platform.patch} | 0 ...-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch} | 0 ...r-cache.patch => 0667-Fix-CraftPotionBrewer-cache.patch} | 0 ...Datapack-API.patch => 0668-Add-basic-Datapack-API.patch} | 0 ...69-Add-environment-variable-to-disable-server-gui.patch} | 0 ...ch => 0670-additions-to-PlayerGameModeChangeEvent.patch} | 0 ...heck-API.patch => 0671-ItemStack-repair-check-API.patch} | 0 ...nchantment-API.patch => 0672-More-Enchantment-API.patch} | 0 ...-command-line-option-to-load-extra-plugin-jars-no.patch} | 0 ...ch => 0674-Fix-and-optimise-world-force-upgrading.patch} | 0 ...d-Mob-lookAt-API.patch => 0675-Add-Mob-lookAt-API.patch} | 0 ...port.patch => 0676-Add-Unix-domain-socket-support.patch} | 0 ...ockEvent.patch => 0677-Add-EntityInsideBlockEvent.patch} | 0 ...ts.patch => 0678-Attributes-API-for-item-defaults.patch} | 0 ...Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch} | 0 ... => 0680-Add-cause-to-Weather-ThunderChangeEvents.patch} | 0 ...ded-Block-API.patch => 0681-More-Lidded-Block-API.patch} | 0 ...ps.patch => 0682-Limit-item-frame-cursors-on-maps.patch} | 0 ...vent.patch => 0683-Add-PufferFishStateChangeEvent.patch} | 0 ...t-causes.patch => 0684-Add-PlayerKickEvent-causes.patch} | 0 ... 0685-Fix-PlayerBucketEmptyEvent-result-itemstack.patch} | 0 ...chronize-PalettedContainer-instead-of-ReentrantLo.patch} | 0 ...687-Add-option-to-fix-items-merging-through-walls.patch} | 0 ...iderEvent.patch => 0688-Add-BellRevealRaiderEvent.patch} | 0 ...stals.patch => 0689-Fix-invulnerable-end-crystals.patch} | 0 ...nt.patch => 0690-Add-ElderGuardianAppearanceEvent.patch} | 0 ...eset-villager-inventory-on-cancelled-pickup-event.patch} | 0 ...ogic.patch => 0692-Fix-dangerous-end-portal-logic.patch} | 0 ... 0693-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch} | 0 ....patch => 0694-Make-item-validations-configurable.patch} | 0 ...hods.patch => 0695-Add-more-line-of-sight-methods.patch} | 0 ...n-limits.patch => 0696-add-per-world-spawn-limits.patch} | 0 ...97-Fix-PotionSplashEvent-for-water-splash-potions.patch} | 0 ...-incorrect-status-dataconverter-for-pre-1.13-chun.patch} | 0 571 files changed, 63 insertions(+), 63 deletions(-) rename patches/api/{0154-PreSpawnerSpawnEvent.patch => 0155-PreSpawnerSpawnEvent.patch} (100%) rename patches/api/{0155-Add-Material-Tags.patch => 0156-Add-Material-Tags.patch} (100%) rename patches/api/{0156-Add-LivingEntity-getTargetEntity.patch => 0157-Add-LivingEntity-getTargetEntity.patch} (97%) rename patches/api/{0157-Add-sun-related-API.patch => 0158-Add-sun-related-API.patch} (100%) rename patches/api/{0158-Here-s-Johnny.patch => 0159-Here-s-Johnny.patch} (100%) rename patches/api/{0159-Turtle-API.patch => 0160-Turtle-API.patch} (100%) rename patches/api/{0160-Add-spectator-target-events.patch => 0161-Add-spectator-target-events.patch} (100%) rename patches/api/{0161-Add-more-Witch-API.patch => 0162-Add-more-Witch-API.patch} (100%) rename patches/api/{0162-Make-the-default-permission-message-configurable.patch => 0163-Make-the-default-permission-message-configurable.patch} (100%) rename patches/api/{0163-Support-cancellation-supression-of-EntityDismount-Ve.patch => 0164-Support-cancellation-supression-of-EntityDismount-Ve.patch} (100%) rename patches/api/{0164-Add-more-Zombie-API.patch => 0165-Add-more-Zombie-API.patch} (100%) rename patches/api/{0165-Change-the-reserved-channel-check-to-be-sensible.patch => 0166-Change-the-reserved-channel-check-to-be-sensible.patch} (100%) rename patches/api/{0166-Add-PlayerConnectionCloseEvent.patch => 0167-Add-PlayerConnectionCloseEvent.patch} (100%) rename patches/api/{0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch => 0168-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch} (100%) rename patches/api/{0168-BlockDestroyEvent.patch => 0169-BlockDestroyEvent.patch} (100%) rename patches/api/{0169-Add-ItemStack-Recipe-API-helper-methods.patch => 0170-Add-ItemStack-Recipe-API-helper-methods.patch} (100%) rename patches/api/{0170-Add-WhitelistToggleEvent.patch => 0171-Add-WhitelistToggleEvent.patch} (100%) rename patches/api/{0171-Annotation-Test-changes.patch => 0172-Annotation-Test-changes.patch} (100%) rename patches/api/{0172-Entity-getEntitySpawnReason.patch => 0173-Entity-getEntitySpawnReason.patch} (100%) rename patches/api/{0173-Add-GS4-Query-event.patch => 0174-Add-GS4-Query-event.patch} (100%) rename patches/api/{0174-Add-PlayerPostRespawnEvent.patch => 0175-Add-PlayerPostRespawnEvent.patch} (100%) rename patches/api/{0175-Ignore-package-private-methods-for-nullability-annot.patch => 0176-Ignore-package-private-methods-for-nullability-annot.patch} (100%) rename patches/api/{0176-Flip-some-Spigot-API-null-annotations.patch => 0177-Flip-some-Spigot-API-null-annotations.patch} (100%) rename patches/api/{0177-Server-Tick-Events.patch => 0178-Server-Tick-Events.patch} (100%) rename patches/api/{0178-PlayerDeathEvent-getItemsToKeep.patch => 0179-PlayerDeathEvent-getItemsToKeep.patch} (100%) rename patches/api/{0179-Add-Heightmap-API.patch => 0180-Add-Heightmap-API.patch} (100%) rename patches/api/{0180-Mob-Spawner-API-Enhancements.patch => 0181-Mob-Spawner-API-Enhancements.patch} (100%) rename patches/api/{0181-Add-BlockSoundGroup-interface.patch => 0182-Add-BlockSoundGroup-interface.patch} (100%) rename patches/api/{0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch => 0183-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch} (100%) rename patches/api/{0183-Increase-custom-payload-channel-message-size.patch => 0184-Increase-custom-payload-channel-message-size.patch} (100%) rename patches/api/{0184-Expose-the-internal-current-tick.patch => 0185-Expose-the-internal-current-tick.patch} (100%) rename patches/api/{0185-PlayerDeathEvent-shouldDropExperience.patch => 0186-PlayerDeathEvent-shouldDropExperience.patch} (100%) rename patches/api/{0186-Add-effect-to-block-break-naturally.patch => 0187-Add-effect-to-block-break-naturally.patch} (100%) rename patches/api/{0187-World-view-distance-api.patch => 0188-World-view-distance-api.patch} (100%) rename patches/api/{0188-Add-ThrownEggHatchEvent.patch => 0189-Add-ThrownEggHatchEvent.patch} (100%) rename patches/api/{0189-Entity-Jump-API.patch => 0190-Entity-Jump-API.patch} (100%) rename patches/api/{0190-add-hand-to-BlockMultiPlaceEvent.patch => 0191-add-hand-to-BlockMultiPlaceEvent.patch} (100%) rename patches/api/{0191-Add-tick-times-API.patch => 0192-Add-tick-times-API.patch} (100%) rename patches/api/{0192-Expose-MinecraftServer-isRunning.patch => 0193-Expose-MinecraftServer-isRunning.patch} (100%) rename patches/api/{0193-Add-Raw-Byte-ItemStack-Serialization.patch => 0194-Add-Raw-Byte-ItemStack-Serialization.patch} (100%) rename patches/api/{0194-Disable-Sync-Events-firing-Async-errors-during-shutd.patch => 0195-Disable-Sync-Events-firing-Async-errors-during-shutd.patch} (100%) rename patches/api/{0195-Make-JavaPluginLoader-thread-safe.patch => 0196-Make-JavaPluginLoader-thread-safe.patch} (100%) rename patches/api/{0196-Add-Player-Client-Options-API.patch => 0197-Add-Player-Client-Options-API.patch} (100%) rename patches/api/{0197-Add-PlayerAttackEntityCooldownResetEvent.patch => 0198-Add-PlayerAttackEntityCooldownResetEvent.patch} (100%) rename patches/api/{0198-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch => 0199-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch} (100%) rename patches/api/{0199-Add-item-slot-convenience-methods.patch => 0200-Add-item-slot-convenience-methods.patch} (100%) rename patches/api/{0200-Villager-Restocks-API.patch => 0201-Villager-Restocks-API.patch} (91%) rename patches/api/{0201-Add-Mob-Goal-API.patch => 0202-Add-Mob-Goal-API.patch} (100%) rename patches/api/{0202-Add-villager-reputation-API.patch => 0203-Add-villager-reputation-API.patch} (100%) rename patches/api/{0203-Expose-game-version.patch => 0204-Expose-game-version.patch} (100%) rename patches/api/{0204-Spawn-Reason-API.patch => 0205-Spawn-Reason-API.patch} (100%) rename patches/api/{0205-Potential-bed-API.patch => 0206-Potential-bed-API.patch} (100%) rename patches/api/{0206-Prioritise-own-classes-where-possible.patch => 0207-Prioritise-own-classes-where-possible.patch} (100%) rename patches/api/{0207-Provide-a-useful-PluginClassLoader-toString.patch => 0208-Provide-a-useful-PluginClassLoader-toString.patch} (100%) rename patches/api/{0208-Inventory-getHolder-method-without-block-snapshot.patch => 0209-Inventory-getHolder-method-without-block-snapshot.patch} (100%) rename patches/api/{0209-Expose-Arrow-getItemStack.patch => 0210-Expose-Arrow-getItemStack.patch} (100%) rename patches/api/{0210-Add-and-implement-PlayerRecipeBookClickEvent.patch => 0211-Add-and-implement-PlayerRecipeBookClickEvent.patch} (100%) rename patches/api/{0211-Support-components-in-ItemMeta.patch => 0212-Support-components-in-ItemMeta.patch} (100%) rename patches/api/{0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch => 0213-added-2-new-TargetReasons-for-1.16-mob-behavior.patch} (100%) rename patches/api/{0213-Add-entity-liquid-API.patch => 0214-Add-entity-liquid-API.patch} (100%) rename patches/api/{0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch => 0215-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch} (100%) rename patches/api/{0215-Allow-delegation-to-vanilla-chunk-gen.patch => 0216-Allow-delegation-to-vanilla-chunk-gen.patch} (100%) rename patches/api/{0216-Support-hex-colors-in-getLastColors.patch => 0217-Support-hex-colors-in-getLastColors.patch} (100%) rename patches/api/{0217-Add-setMaxPlayers-API.patch => 0218-Add-setMaxPlayers-API.patch} (100%) rename patches/api/{0218-Add-moon-phase-API.patch => 0219-Add-moon-phase-API.patch} (100%) rename patches/api/{0219-Add-playPickupItemAnimation-to-LivingEntity.patch => 0220-Add-playPickupItemAnimation-to-LivingEntity.patch} (100%) rename patches/api/{0220-Add-BellRingEvent.patch => 0221-Add-BellRingEvent.patch} (100%) rename patches/api/{0221-Brand-support.patch => 0222-Brand-support.patch} (100%) rename patches/api/{0222-Add-more-Evoker-API.patch => 0223-Add-more-Evoker-API.patch} (100%) rename patches/api/{0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch => 0224-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch} (100%) rename patches/api/{0224-Create-HoverEvent-from-ItemStack-Entity.patch => 0225-Create-HoverEvent-from-ItemStack-Entity.patch} (100%) rename patches/api/{0225-Add-additional-open-container-api-to-HumanEntity.patch => 0226-Add-additional-open-container-api-to-HumanEntity.patch} (100%) rename patches/api/{0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch => 0227-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch} (100%) rename patches/api/{0227-Entity-isTicking.patch => 0228-Entity-isTicking.patch} (100%) rename patches/api/{0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch => 0229-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch} (100%) rename patches/api/{0229-Villager-resetOffers.patch => 0230-Villager-resetOffers.patch} (100%) rename patches/api/{0230-Player-elytra-boost-API.patch => 0231-Player-elytra-boost-API.patch} (100%) rename patches/api/{0231-Add-getOfflinePlayerIfCached-String.patch => 0232-Add-getOfflinePlayerIfCached-String.patch} (100%) rename patches/api/{0232-Add-ignore-discounts-API.patch => 0233-Add-ignore-discounts-API.patch} (100%) rename patches/api/{0233-Item-no-age-no-player-pickup.patch => 0234-Item-no-age-no-player-pickup.patch} (100%) rename patches/api/{0234-Beacon-API-custom-effect-ranges.patch => 0235-Beacon-API-custom-effect-ranges.patch} (100%) rename patches/api/{0235-Add-API-for-quit-reason.patch => 0236-Add-API-for-quit-reason.patch} (100%) rename patches/api/{0236-Add-Destroy-Speed-API.patch => 0237-Add-Destroy-Speed-API.patch} (100%) rename patches/api/{0237-Add-LivingEntity-clearActiveItem.patch => 0238-Add-LivingEntity-clearActiveItem.patch} (100%) rename patches/api/{0238-Add-PlayerItemCooldownEvent.patch => 0239-Add-PlayerItemCooldownEvent.patch} (100%) rename patches/api/{0239-More-lightning-API.patch => 0240-More-lightning-API.patch} (100%) rename patches/api/{0240-Add-PlayerShearBlockEvent.patch => 0241-Add-PlayerShearBlockEvent.patch} (100%) rename patches/api/{0241-Enable-multi-release-plugin-jars.patch => 0242-Enable-multi-release-plugin-jars.patch} (100%) rename patches/api/{0242-Player-Chunk-Load-Unload-Events.patch => 0243-Player-Chunk-Load-Unload-Events.patch} (100%) rename patches/api/{0243-Expose-LivingEntity-hurt-direction.patch => 0244-Expose-LivingEntity-hurt-direction.patch} (100%) rename patches/api/{0244-Add-OBSTRUCTED-reason-to-BedEnterResult.patch => 0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} (100%) rename patches/api/{0245-Added-PlayerTradeEvent.patch => 0246-Added-PlayerTradeEvent.patch} (100%) rename patches/api/{0246-Add-TargetHitEvent-API.patch => 0247-Add-TargetHitEvent-API.patch} (100%) rename patches/api/{0247-Additional-Block-Material-API-s.patch => 0248-Additional-Block-Material-API-s.patch} (100%) rename patches/api/{0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch => 0249-Add-API-to-get-Material-from-Boats-and-Minecarts.patch} (100%) rename patches/api/{0249-Add-PlayerFlowerPotManipulateEvent.patch => 0250-Add-PlayerFlowerPotManipulateEvent.patch} (100%) rename patches/api/{0250-Zombie-API-breaking-doors.patch => 0251-Zombie-API-breaking-doors.patch} (100%) rename patches/api/{0251-Add-EntityLoadCrossbowEvent.patch => 0252-Add-EntityLoadCrossbowEvent.patch} (100%) rename patches/api/{0252-Added-WorldGameRuleChangeEvent.patch => 0253-Added-WorldGameRuleChangeEvent.patch} (100%) rename patches/api/{0253-Added-ServerResourcesReloadedEvent.patch => 0254-Added-ServerResourcesReloadedEvent.patch} (100%) rename patches/api/{0254-Add-BlockFailedDispenseEvent.patch => 0255-Add-BlockFailedDispenseEvent.patch} (100%) rename patches/api/{0255-Added-PlayerLecternPageChangeEvent.patch => 0256-Added-PlayerLecternPageChangeEvent.patch} (100%) rename patches/api/{0256-Added-PlayerLoomPatternSelectEvent.patch => 0257-Added-PlayerLoomPatternSelectEvent.patch} (100%) rename patches/api/{0257-Better-AnnotationTest-printout.patch => 0258-Better-AnnotationTest-printout.patch} (100%) rename patches/api/{0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch => 0259-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch} (100%) rename patches/api/{0259-Add-sendOpLevel-API.patch => 0260-Add-sendOpLevel-API.patch} (100%) rename patches/api/{0260-Add-StructureLocateEvent.patch => 0261-Add-StructureLocateEvent.patch} (100%) rename patches/api/{0261-Return-chat-component-with-empty-text-instead-of-thr.patch => 0262-Return-chat-component-with-empty-text-instead-of-thr.patch} (100%) rename patches/api/{0262-Add-BlockPreDispenseEvent.patch => 0263-Add-BlockPreDispenseEvent.patch} (100%) rename patches/api/{0263-Added-Vanilla-Entity-Tags.patch => 0264-Added-Vanilla-Entity-Tags.patch} (100%) rename patches/api/{0264-added-Wither-API.patch => 0265-added-Wither-API.patch} (100%) rename patches/api/{0265-Added-PlayerChangeBeaconEffectEvent.patch => 0266-Added-PlayerChangeBeaconEffectEvent.patch} (100%) rename patches/api/{0266-Added-PlayerStonecutterRecipeSelectEvent.patch => 0267-Added-PlayerStonecutterRecipeSelectEvent.patch} (100%) rename patches/api/{0267-Add-dropLeash-variable-to-EntityUnleashEvent.patch => 0268-Add-dropLeash-variable-to-EntityUnleashEvent.patch} (100%) rename patches/api/{0268-EntityMoveEvent.patch => 0269-EntityMoveEvent.patch} (100%) rename patches/api/{0269-add-DragonEggFormEvent.patch => 0270-add-DragonEggFormEvent.patch} (100%) rename patches/api/{0270-Allow-adding-items-to-BlockDropItemEvent.patch => 0271-Allow-adding-items-to-BlockDropItemEvent.patch} (100%) rename patches/api/{0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch => 0272-Add-getMainThreadExecutor-to-BukkitScheduler.patch} (100%) rename patches/api/{0272-living-entity-allow-attribute-registration.patch => 0273-living-entity-allow-attribute-registration.patch} (100%) rename patches/api/{0273-Add-missing-effects.patch => 0274-Add-missing-effects.patch} (100%) rename patches/api/{0274-Expose-Tracked-Players.patch => 0275-Expose-Tracked-Players.patch} (100%) rename patches/api/{0275-Cache-the-result-of-Material-isBlock.patch => 0276-Cache-the-result-of-Material-isBlock.patch} (100%) rename patches/api/{0276-Add-worldborder-events.patch => 0277-Add-worldborder-events.patch} (100%) rename patches/api/{0277-added-PlayerNameEntityEvent.patch => 0278-added-PlayerNameEntityEvent.patch} (100%) rename patches/api/{0278-Add-recipe-to-cook-events.patch => 0279-Add-recipe-to-cook-events.patch} (100%) rename patches/api/{0279-Add-Block-isValidTool.patch => 0280-Add-Block-isValidTool.patch} (100%) rename patches/api/{0280-Implement-Keyed-on-World.patch => 0281-Implement-Keyed-on-World.patch} (100%) rename patches/api/{0281-fix-Inventory-getContents-null-annotations.patch => 0282-fix-Inventory-getContents-null-annotations.patch} (100%) rename patches/api/{0282-Item-Rarity-API.patch => 0283-Item-Rarity-API.patch} (100%) rename patches/api/{0283-Expose-protocol-version.patch => 0284-Expose-protocol-version.patch} (100%) rename patches/api/{0284-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch => 0285-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} (100%) rename patches/api/{0285-add-isDeeplySleeping-to-HumanEntity.patch => 0286-add-isDeeplySleeping-to-HumanEntity.patch} (100%) rename patches/api/{0286-add-consumeFuel-to-FurnaceBurnEvent.patch => 0287-add-consumeFuel-to-FurnaceBurnEvent.patch} (100%) rename patches/api/{0287-add-get-set-drop-chance-to-EntityEquipment.patch => 0288-add-get-set-drop-chance-to-EntityEquipment.patch} (100%) rename patches/api/{0288-Added-PlayerDeepSleepEvent.patch => 0289-Added-PlayerDeepSleepEvent.patch} (100%) rename patches/api/{0289-More-World-API.patch => 0290-More-World-API.patch} (100%) rename patches/api/{0290-Added-PlayerBedFailEnterEvent.patch => 0291-Added-PlayerBedFailEnterEvent.patch} (100%) rename patches/api/{0291-Introduce-beacon-activation-deactivation-events.patch => 0292-Introduce-beacon-activation-deactivation-events.patch} (100%) rename patches/api/{0292-PlayerMoveEvent-Improvements.patch => 0293-PlayerMoveEvent-Improvements.patch} (100%) rename patches/api/{0293-add-RespawnFlags-to-PlayerRespawnEvent.patch => 0294-add-RespawnFlags-to-PlayerRespawnEvent.patch} (100%) rename patches/api/{0294-Add-more-WanderingTrader-API.patch => 0295-Add-more-WanderingTrader-API.patch} (100%) rename patches/api/{0295-Add-EntityBlockStorage-clearEntities.patch => 0296-Add-EntityBlockStorage-clearEntities.patch} (100%) rename patches/api/{0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch => 0297-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch} (100%) rename patches/api/{0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch => 0298-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch} (100%) rename patches/api/{0298-Inventory-close.patch => 0299-Inventory-close.patch} (100%) rename patches/api/{0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch => 0300-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch} (100%) rename patches/api/{0300-Add-basic-Datapack-API.patch => 0301-Add-basic-Datapack-API.patch} (100%) rename patches/api/{0301-additions-to-PlayerGameModeChangeEvent.patch => 0302-additions-to-PlayerGameModeChangeEvent.patch} (100%) rename patches/api/{0302-ItemStack-repair-check-API.patch => 0303-ItemStack-repair-check-API.patch} (100%) rename patches/api/{0303-More-Enchantment-API.patch => 0304-More-Enchantment-API.patch} (100%) rename patches/api/{0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch => 0305-Add-command-line-option-to-load-extra-plugin-jars-no.patch} (100%) rename patches/api/{0305-List-all-missing-hard-depends-not-just-first.patch => 0306-List-all-missing-hard-depends-not-just-first.patch} (100%) rename patches/api/{0306-Add-Mob-lookAt-API.patch => 0307-Add-Mob-lookAt-API.patch} (100%) rename patches/api/{0307-ItemStack-editMeta.patch => 0308-ItemStack-editMeta.patch} (100%) rename patches/api/{0308-Add-EntityInsideBlockEvent.patch => 0309-Add-EntityInsideBlockEvent.patch} (100%) rename patches/api/{0309-Attributes-API-for-item-defaults.patch => 0310-Attributes-API-for-item-defaults.patch} (100%) rename patches/api/{0310-Add-cause-to-Weather-ThunderChangeEvents.patch => 0311-Add-cause-to-Weather-ThunderChangeEvents.patch} (100%) rename patches/api/{0311-More-Lidded-Block-API.patch => 0312-More-Lidded-Block-API.patch} (100%) rename patches/api/{0312-Add-PlayerKickEvent-causes.patch => 0313-Add-PlayerKickEvent-causes.patch} (100%) rename patches/api/{0312-Add-PufferFishStateChangeEvent.patch => 0314-Add-PufferFishStateChangeEvent.patch} (100%) rename patches/api/{0314-Add-BellRevealRaiderEvent.patch => 0315-Add-BellRevealRaiderEvent.patch} (100%) rename patches/api/{0315-Add-ElderGuardianAppearanceEvent.patch => 0316-Add-ElderGuardianAppearanceEvent.patch} (100%) rename patches/api/{0316-Add-more-line-of-sight-methods.patch => 0317-Add-more-line-of-sight-methods.patch} (100%) rename patches/server/{0290-PreSpawnerSpawnEvent.patch => 0291-PreSpawnerSpawnEvent.patch} (94%) rename patches/server/{0291-Don-t-allow-digging-into-unloaded-chunks.patch => 0292-Don-t-allow-digging-into-unloaded-chunks.patch} (97%) rename patches/server/{0292-Make-the-default-permission-message-configurable.patch => 0293-Make-the-default-permission-message-configurable.patch} (100%) rename patches/server/{0293-Prevent-rayTrace-from-loading-chunks.patch => 0294-Prevent-rayTrace-from-loading-chunks.patch} (100%) rename patches/server/{0294-Handle-Large-Packets-disconnecting-client.patch => 0295-Handle-Large-Packets-disconnecting-client.patch} (100%) rename patches/server/{0295-force-entity-dismount-during-teleportation.patch => 0296-force-entity-dismount-during-teleportation.patch} (97%) rename patches/server/{0296-Add-more-Zombie-API.patch => 0297-Add-more-Zombie-API.patch} (100%) rename patches/server/{0297-Book-Size-Limits.patch => 0298-Book-Size-Limits.patch} (97%) rename patches/server/{0298-Add-PlayerConnectionCloseEvent.patch => 0299-Add-PlayerConnectionCloseEvent.patch} (100%) rename patches/server/{0299-Prevent-Enderman-from-loading-chunks.patch => 0300-Prevent-Enderman-from-loading-chunks.patch} (100%) rename patches/server/{0300-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch => 0301-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch} (98%) rename patches/server/{0301-Workaround-for-vehicle-tracking-issue-on-disconnect.patch => 0302-Workaround-for-vehicle-tracking-issue-on-disconnect.patch} (91%) rename patches/server/{0302-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch => 0303-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch} (100%) rename patches/server/{0303-Block-Entity-remove-from-being-called-on-Players.patch => 0304-Block-Entity-remove-from-being-called-on-Players.patch} (100%) rename patches/server/{0304-BlockDestroyEvent.patch => 0305-BlockDestroyEvent.patch} (100%) rename patches/server/{0305-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch => 0306-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch} (100%) rename patches/server/{0306-Limit-Client-Sign-length-more.patch => 0307-Limit-Client-Sign-length-more.patch} (97%) rename patches/server/{0307-Don-t-check-ConvertSigns-boolean-every-sign-save.patch => 0308-Don-t-check-ConvertSigns-boolean-every-sign-save.patch} (100%) rename patches/server/{0308-Optimize-Network-Manager-and-add-advanced-packet-sup.patch => 0309-Optimize-Network-Manager-and-add-advanced-packet-sup.patch} (100%) rename patches/server/{0309-Handle-Oversized-Tile-Entities-in-chunks.patch => 0310-Handle-Oversized-Tile-Entities-in-chunks.patch} (100%) rename patches/server/{0310-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch => 0311-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch} (100%) rename patches/server/{0311-Set-Zombie-last-tick-at-start-of-drowning-process.patch => 0312-Set-Zombie-last-tick-at-start-of-drowning-process.patch} (100%) rename patches/server/{0312-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch => 0313-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch} (100%) rename patches/server/{0313-Use-proper-max-length-when-serialising-BungeeCord-te.patch => 0314-Use-proper-max-length-when-serialising-BungeeCord-te.patch} (100%) rename patches/server/{0314-Entity-getEntitySpawnReason.patch => 0315-Entity-getEntitySpawnReason.patch} (97%) rename patches/server/{0315-Update-entity-Metadata-for-all-tracked-players.patch => 0316-Update-entity-Metadata-for-all-tracked-players.patch} (96%) rename patches/server/{0316-Fire-event-on-GS4-query.patch => 0317-Fire-event-on-GS4-query.patch} (100%) rename patches/server/{0317-Implement-PlayerPostRespawnEvent.patch => 0318-Implement-PlayerPostRespawnEvent.patch} (100%) rename patches/server/{0318-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch => 0319-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch} (100%) rename patches/server/{0319-Server-Tick-Events.patch => 0320-Server-Tick-Events.patch} (100%) rename patches/server/{0320-PlayerDeathEvent-getItemsToKeep.patch => 0321-PlayerDeathEvent-getItemsToKeep.patch} (96%) rename patches/server/{0321-Optimize-Captured-TileEntity-Lookup.patch => 0322-Optimize-Captured-TileEntity-Lookup.patch} (100%) rename patches/server/{0322-Add-Heightmap-API.patch => 0323-Add-Heightmap-API.patch} (100%) rename patches/server/{0323-Mob-Spawner-API-Enhancements.patch => 0324-Mob-Spawner-API-Enhancements.patch} (98%) rename patches/server/{0324-Fix-CB-call-to-changed-postToMainThread-method.patch => 0325-Fix-CB-call-to-changed-postToMainThread-method.patch} (91%) rename patches/server/{0325-Fix-sounds-when-item-frames-are-modified-MC-123450.patch => 0326-Fix-sounds-when-item-frames-are-modified-MC-123450.patch} (100%) rename patches/server/{0326-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch => 0327-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch} (100%) rename patches/server/{0327-improve-CraftWorld-isChunkLoaded.patch => 0328-improve-CraftWorld-isChunkLoaded.patch} (100%) rename patches/server/{0328-Configurable-Keep-Spawn-Loaded-range-per-world.patch => 0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch} (100%) rename patches/server/{0329-ChunkMapDistance-CME.patch => 0330-ChunkMapDistance-CME.patch} (100%) rename patches/server/{0330-Implement-CraftBlockSoundGroup.patch => 0331-Implement-CraftBlockSoundGroup.patch} (100%) rename patches/server/{0331-Chunk-debug-command.patch => 0332-Chunk-debug-command.patch} (100%) rename patches/server/{0332-Fix-World-isChunkGenerated-calls.patch => 0333-Fix-World-isChunkGenerated-calls.patch} (100%) rename patches/server/{0333-Show-blockstate-location-if-we-failed-to-read-it.patch => 0334-Show-blockstate-location-if-we-failed-to-read-it.patch} (100%) rename patches/server/{0334-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch => 0335-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch} (100%) rename patches/server/{0335-Configurable-projectile-relative-velocity.patch => 0336-Configurable-projectile-relative-velocity.patch} (100%) rename patches/server/{0336-offset-item-frame-ticking.patch => 0337-offset-item-frame-ticking.patch} (100%) rename patches/server/{0337-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch => 0338-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch} (100%) rename patches/server/{0338-Fix-MC-158900.patch => 0339-Fix-MC-158900.patch} (100%) rename patches/server/{0339-Prevent-consuming-the-wrong-itemstack.patch => 0340-Prevent-consuming-the-wrong-itemstack.patch} (100%) rename patches/server/{0340-Generator-Settings.patch => 0341-Generator-Settings.patch} (100%) rename patches/server/{0341-Fix-MC-161754.patch => 0342-Fix-MC-161754.patch} (100%) rename patches/server/{0342-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch => 0343-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch} (100%) rename patches/server/{0343-Expose-the-internal-current-tick.patch => 0344-Expose-the-internal-current-tick.patch} (100%) rename patches/server/{0344-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch => 0345-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch} (94%) rename patches/server/{0345-Add-option-to-disable-pillager-patrols.patch => 0346-Add-option-to-disable-pillager-patrols.patch} (100%) rename patches/server/{0346-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch => 0347-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch} (92%) rename patches/server/{0347-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch => 0348-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch} (100%) rename patches/server/{0348-MC-145656-Fix-Follow-Range-Initial-Target.patch => 0349-MC-145656-Fix-Follow-Range-Initial-Target.patch} (100%) rename patches/server/{0349-Optimize-Hoppers.patch => 0350-Optimize-Hoppers.patch} (100%) rename patches/server/{0350-PlayerDeathEvent-shouldDropExperience.patch => 0351-PlayerDeathEvent-shouldDropExperience.patch} (91%) rename patches/server/{0351-Prevent-bees-loading-chunks-checking-hive-position.patch => 0352-Prevent-bees-loading-chunks-checking-hive-position.patch} (100%) rename patches/server/{0352-Don-t-load-Chunks-from-Hoppers-and-other-things.patch => 0353-Don-t-load-Chunks-from-Hoppers-and-other-things.patch} (100%) rename patches/server/{0353-Guard-against-serializing-mismatching-chunk-coordina.patch => 0354-Guard-against-serializing-mismatching-chunk-coordina.patch} (100%) rename patches/server/{0354-Optimise-IEntityAccess-getPlayerByUUID.patch => 0355-Optimise-IEntityAccess-getPlayerByUUID.patch} (100%) rename patches/server/{0355-Fix-items-not-falling-correctly.patch => 0356-Fix-items-not-falling-correctly.patch} (100%) rename patches/server/{0356-Lag-compensate-eating.patch => 0357-Lag-compensate-eating.patch} (100%) rename patches/server/{0357-Optimize-call-to-getFluid-for-explosions.patch => 0358-Optimize-call-to-getFluid-for-explosions.patch} (100%) rename patches/server/{0358-Fix-last-firework-in-stack-not-having-effects-when-d.patch => 0359-Fix-last-firework-in-stack-not-having-effects-when-d.patch} (100%) rename patches/server/{0359-Add-effect-to-block-break-naturally.patch => 0360-Add-effect-to-block-break-naturally.patch} (100%) rename patches/server/{0360-Entity-Activation-Range-2.0.patch => 0361-Entity-Activation-Range-2.0.patch} (99%) rename patches/server/{0361-Increase-Light-Queue-Size.patch => 0362-Increase-Light-Queue-Size.patch} (100%) rename patches/server/{0362-Fix-Light-Command.patch => 0363-Fix-Light-Command.patch} (100%) rename patches/server/{0363-No-Tick-view-distance-implementation.patch => 0364-No-Tick-view-distance-implementation.patch} (99%) rename patches/server/{0364-Implement-alternative-item-despawn-rate.patch => 0365-Implement-alternative-item-despawn-rate.patch} (100%) rename patches/server/{0365-Tracking-Range-Improvements.patch => 0366-Tracking-Range-Improvements.patch} (100%) rename patches/server/{0366-Fix-items-vanishing-through-end-portal.patch => 0367-Fix-items-vanishing-through-end-portal.patch} (93%) rename patches/server/{0367-implement-optional-per-player-mob-spawns.patch => 0368-implement-optional-per-player-mob-spawns.patch} (99%) rename patches/server/{0368-Bees-get-gravity-in-void.-Fixes-MC-167279.patch => 0369-Bees-get-gravity-in-void.-Fixes-MC-167279.patch} (100%) rename patches/server/{0369-Optimise-getChunkAt-calls-for-loaded-chunks.patch => 0370-Optimise-getChunkAt-calls-for-loaded-chunks.patch} (100%) rename patches/server/{0370-Allow-overriding-the-java-version-check.patch => 0371-Allow-overriding-the-java-version-check.patch} (100%) rename patches/server/{0371-Add-ThrownEggHatchEvent.patch => 0372-Add-ThrownEggHatchEvent.patch} (100%) rename patches/server/{0372-Optimise-random-block-ticking.patch => 0373-Optimise-random-block-ticking.patch} (100%) rename patches/server/{0373-Entity-Jump-API.patch => 0374-Entity-Jump-API.patch} (100%) rename patches/server/{0374-Add-option-to-nerf-pigmen-from-nether-portals.patch => 0375-Add-option-to-nerf-pigmen-from-nether-portals.patch} (97%) rename patches/server/{0375-Make-the-GUI-graph-fancier.patch => 0376-Make-the-GUI-graph-fancier.patch} (100%) rename patches/server/{0376-add-hand-to-BlockMultiPlaceEvent.patch => 0377-add-hand-to-BlockMultiPlaceEvent.patch} (93%) rename patches/server/{0377-Prevent-teleporting-dead-entities.patch => 0378-Prevent-teleporting-dead-entities.patch} (91%) rename patches/server/{0378-Validate-tripwire-hook-placement-before-update.patch => 0379-Validate-tripwire-hook-placement-before-update.patch} (100%) rename patches/server/{0379-Add-option-to-allow-iron-golems-to-spawn-in-air.patch => 0380-Add-option-to-allow-iron-golems-to-spawn-in-air.patch} (100%) rename patches/server/{0380-Configurable-chance-of-villager-zombie-infection.patch => 0381-Configurable-chance-of-villager-zombie-infection.patch} (100%) rename patches/server/{0381-Optimise-Chunk-getFluid.patch => 0382-Optimise-Chunk-getFluid.patch} (100%) rename patches/server/{0382-Optimise-TickListServer-by-rewriting-it.patch => 0383-Optimise-TickListServer-by-rewriting-it.patch} (100%) rename patches/server/{0383-Pillager-patrol-spawn-settings-and-per-player-option.patch => 0384-Pillager-patrol-spawn-settings-and-per-player-option.patch} (98%) rename patches/server/{0384-Remote-Connections-shouldn-t-hold-up-shutdown.patch => 0385-Remote-Connections-shouldn-t-hold-up-shutdown.patch} (100%) rename patches/server/{0385-Do-not-allow-bees-to-load-chunks-for-beehives.patch => 0386-Do-not-allow-bees-to-load-chunks-for-beehives.patch} (95%) rename patches/server/{0386-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch => 0387-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch} (100%) rename patches/server/{0387-Optimize-Collision-to-not-load-chunks.patch => 0388-Optimize-Collision-to-not-load-chunks.patch} (98%) rename patches/server/{0388-Don-t-tick-dead-players.patch => 0389-Don-t-tick-dead-players.patch} (91%) rename patches/server/{0389-Dead-Player-s-shouldn-t-be-able-to-move.patch => 0390-Dead-Player-s-shouldn-t-be-able-to-move.patch} (100%) rename patches/server/{0390-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch => 0391-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch} (100%) rename patches/server/{0391-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch => 0392-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch} (100%) rename patches/server/{0392-Don-t-move-existing-players-to-world-spawn.patch => 0393-Don-t-move-existing-players-to-world-spawn.patch} (96%) rename patches/server/{0393-Add-tick-times-API-and-mspt-command.patch => 0394-Add-tick-times-API-and-mspt-command.patch} (100%) rename patches/server/{0394-Expose-MinecraftServer-isRunning.patch => 0395-Expose-MinecraftServer-isRunning.patch} (100%) rename patches/server/{0395-Add-Raw-Byte-ItemStack-Serialization.patch => 0396-Add-Raw-Byte-ItemStack-Serialization.patch} (100%) rename patches/server/{0396-Remove-streams-from-Mob-AI-System.patch => 0397-Remove-streams-from-Mob-AI-System.patch} (100%) rename patches/server/{0397-Async-command-map-building.patch => 0398-Async-command-map-building.patch} (100%) rename patches/server/{0398-Improved-Watchdog-Support.patch => 0399-Improved-Watchdog-Support.patch} (100%) rename patches/server/{0399-Optimize-Pathfinding.patch => 0400-Optimize-Pathfinding.patch} (100%) rename patches/server/{0400-Reduce-Either-Optional-allocation.patch => 0401-Reduce-Either-Optional-allocation.patch} (100%) rename patches/server/{0401-Remove-streams-from-PairedQueue.patch => 0402-Remove-streams-from-PairedQueue.patch} (100%) rename patches/server/{0402-Reduce-memory-footprint-of-NBTTagCompound.patch => 0403-Reduce-memory-footprint-of-NBTTagCompound.patch} (100%) rename patches/server/{0403-Prevent-opening-inventories-when-frozen.patch => 0404-Prevent-opening-inventories-when-frozen.patch} (97%) rename patches/server/{0404-Optimise-ArraySetSorted-removeIf.patch => 0405-Optimise-ArraySetSorted-removeIf.patch} (100%) rename patches/server/{0405-Don-t-run-entity-collision-code-if-not-needed.patch => 0406-Don-t-run-entity-collision-code-if-not-needed.patch} (100%) rename patches/server/{0406-Restrict-vanilla-teleport-command-to-valid-locations.patch => 0407-Restrict-vanilla-teleport-command-to-valid-locations.patch} (100%) rename patches/server/{0407-Implement-Player-Client-Options-API.patch => 0408-Implement-Player-Client-Options-API.patch} (98%) rename patches/server/{0408-Fix-Chunk-Post-Processing-deadlock-risk.patch => 0409-Fix-Chunk-Post-Processing-deadlock-risk.patch} (100%) rename patches/server/{0409-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch => 0410-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch} (100%) rename patches/server/{0410-Broadcast-join-message-to-console.patch => 0411-Broadcast-join-message-to-console.patch} (100%) rename patches/server/{0411-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch => 0412-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch} (98%) rename patches/server/{0412-Load-Chunks-for-Login-Asynchronously.patch => 0413-Load-Chunks-for-Login-Asynchronously.patch} (98%) rename patches/server/{0413-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch => 0414-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch} (93%) rename patches/server/{0414-Add-PlayerAttackEntityCooldownResetEvent.patch => 0415-Add-PlayerAttackEntityCooldownResetEvent.patch} (100%) rename patches/server/{0415-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch => 0416-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch} (100%) rename patches/server/{0416-Don-t-fire-BlockFade-on-worldgen-threads.patch => 0417-Don-t-fire-BlockFade-on-worldgen-threads.patch} (100%) rename patches/server/{0417-Add-phantom-creative-and-insomniac-controls.patch => 0418-Add-phantom-creative-and-insomniac-controls.patch} (100%) rename patches/server/{0418-Fix-numerous-item-duplication-issues-and-teleport-is.patch => 0419-Fix-numerous-item-duplication-issues-and-teleport-is.patch} (97%) rename patches/server/{0419-Implement-Brigadier-Mojang-API.patch => 0420-Implement-Brigadier-Mojang-API.patch} (98%) rename patches/server/{0420-Villager-Restocks-API.patch => 0421-Villager-Restocks-API.patch} (94%) rename patches/server/{0421-Validate-PickItem-Packet-and-kick-for-invalid.patch => 0422-Validate-PickItem-Packet-and-kick-for-invalid.patch} (95%) rename patches/server/{0422-Expose-game-version.patch => 0423-Expose-game-version.patch} (100%) rename patches/server/{0423-Optimize-Voxel-Shape-Merging.patch => 0424-Optimize-Voxel-Shape-Merging.patch} (100%) rename patches/server/{0424-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch => 0425-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch} (100%) rename patches/server/{0425-Implement-Mob-Goal-API.patch => 0426-Implement-Mob-Goal-API.patch} (99%) rename patches/server/{0426-Use-distance-map-to-optimise-entity-tracker.patch => 0427-Use-distance-map-to-optimise-entity-tracker.patch} (99%) rename patches/server/{0427-Optimize-isOutsideRange-to-use-distance-maps.patch => 0428-Optimize-isOutsideRange-to-use-distance-maps.patch} (99%) rename patches/server/{0428-Add-villager-reputation-API.patch => 0429-Add-villager-reputation-API.patch} (100%) rename patches/server/{0429-Option-for-maximum-exp-value-when-merging-orbs.patch => 0430-Option-for-maximum-exp-value-when-merging-orbs.patch} (97%) rename patches/server/{0430-ExperienceOrbMergeEvent.patch => 0431-ExperienceOrbMergeEvent.patch} (94%) rename patches/server/{0431-Fix-PotionEffect-ignores-icon-flag.patch => 0432-Fix-PotionEffect-ignores-icon-flag.patch} (92%) rename patches/server/{0432-Optimize-brigadier-child-sorting-performance.patch => 0433-Optimize-brigadier-child-sorting-performance.patch} (100%) rename patches/server/{0433-Potential-bed-API.patch => 0434-Potential-bed-API.patch} (100%) rename patches/server/{0434-Wait-for-Async-Tasks-during-shutdown.patch => 0435-Wait-for-Async-Tasks-during-shutdown.patch} (100%) rename patches/server/{0435-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch => 0436-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch} (100%) rename patches/server/{0436-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch => 0437-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch} (100%) rename patches/server/{0437-Reduce-MutableInt-allocations-from-light-engine.patch => 0438-Reduce-MutableInt-allocations-from-light-engine.patch} (100%) rename patches/server/{0438-Reduce-allocation-of-Vec3D-by-entity-tracker.patch => 0439-Reduce-allocation-of-Vec3D-by-entity-tracker.patch} (100%) rename patches/server/{0439-Ensure-safe-gateway-teleport.patch => 0440-Ensure-safe-gateway-teleport.patch} (100%) rename patches/server/{0440-Add-option-for-console-having-all-permissions.patch => 0441-Add-option-for-console-having-all-permissions.patch} (100%) rename patches/server/{0441-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch => 0442-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch} (100%) rename patches/server/{0442-Optimize-sending-packets-to-nearby-locations-sounds-.patch => 0443-Optimize-sending-packets-to-nearby-locations-sounds-.patch} (100%) rename patches/server/{0443-Fix-villager-trading-demand-MC-163962.patch => 0444-Fix-villager-trading-demand-MC-163962.patch} (100%) rename patches/server/{0444-Maps-shouldn-t-load-chunks.patch => 0445-Maps-shouldn-t-load-chunks.patch} (100%) rename patches/server/{0445-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch => 0446-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch} (100%) rename patches/server/{0446-Delay-Chunk-Unloads-based-on-Player-Movement.patch => 0447-Delay-Chunk-Unloads-based-on-Player-Movement.patch} (100%) rename patches/server/{0447-Optimize-Bit-Operations-by-inlining.patch => 0448-Optimize-Bit-Operations-by-inlining.patch} (100%) rename patches/server/{0448-incremental-chunk-saving.patch => 0449-incremental-chunk-saving.patch} (100%) rename patches/server/{0449-Add-Plugin-Tickets-to-API-Chunk-Methods.patch => 0450-Add-Plugin-Tickets-to-API-Chunk-Methods.patch} (100%) rename patches/server/{0450-Fix-missing-chunks-due-to-integer-overflow.patch => 0451-Fix-missing-chunks-due-to-integer-overflow.patch} (100%) rename patches/server/{0451-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch => 0452-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch} (100%) rename patches/server/{0452-Fix-piston-physics-inconsistency-MC-188840.patch => 0453-Fix-piston-physics-inconsistency-MC-188840.patch} (100%) rename patches/server/{0453-Fix-sand-duping.patch => 0454-Fix-sand-duping.patch} (100%) rename patches/server/{0454-Prevent-position-desync-in-playerconnection-causing-.patch => 0455-Prevent-position-desync-in-playerconnection-causing-.patch} (94%) rename patches/server/{0455-Inventory-getHolder-method-without-block-snapshot.patch => 0456-Inventory-getHolder-method-without-block-snapshot.patch} (100%) rename patches/server/{0456-Expose-Arrow-getItemStack.patch => 0457-Expose-Arrow-getItemStack.patch} (100%) rename patches/server/{0457-Add-and-implement-PlayerRecipeBookClickEvent.patch => 0458-Add-and-implement-PlayerRecipeBookClickEvent.patch} (95%) rename patches/server/{0458-Hide-sync-chunk-writes-behind-flag.patch => 0459-Hide-sync-chunk-writes-behind-flag.patch} (100%) rename patches/server/{0459-Add-permission-for-command-blocks.patch => 0460-Add-permission-for-command-blocks.patch} (98%) rename patches/server/{0460-Ensure-Entity-AABB-s-are-never-invalid.patch => 0461-Ensure-Entity-AABB-s-are-never-invalid.patch} (94%) rename patches/server/{0461-Optimize-WorldBorder-collision-checks-and-air.patch => 0462-Optimize-WorldBorder-collision-checks-and-air.patch} (97%) rename patches/server/{0462-Fix-Per-World-Difficulty-Remembering-Difficulty.patch => 0463-Fix-Per-World-Difficulty-Remembering-Difficulty.patch} (98%) rename patches/server/{0463-Paper-dumpitem-command.patch => 0464-Paper-dumpitem-command.patch} (100%) rename patches/server/{0464-Don-t-allow-null-UUID-s-for-chat.patch => 0465-Don-t-allow-null-UUID-s-for-chat.patch} (100%) rename patches/server/{0465-Improve-Legacy-Component-serialization-size.patch => 0466-Improve-Legacy-Component-serialization-size.patch} (100%) rename patches/server/{0466-Support-old-UUID-format-for-NBT.patch => 0467-Support-old-UUID-format-for-NBT.patch} (100%) rename patches/server/{0467-Clean-up-duplicated-GameProfile-Properties.patch => 0468-Clean-up-duplicated-GameProfile-Properties.patch} (96%) rename patches/server/{0468-Convert-legacy-attributes-in-Item-Meta.patch => 0469-Convert-legacy-attributes-in-Item-Meta.patch} (100%) rename patches/server/{0469-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch => 0470-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch} (99%) rename patches/server/{0470-Remove-some-streams-from-structures.patch => 0471-Remove-some-streams-from-structures.patch} (100%) rename patches/server/{0471-Remove-streams-from-classes-related-villager-gossip.patch => 0472-Remove-streams-from-classes-related-villager-gossip.patch} (100%) rename patches/server/{0472-Support-components-in-ItemMeta.patch => 0473-Support-components-in-ItemMeta.patch} (100%) rename patches/server/{0473-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch => 0474-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch} (100%) rename patches/server/{0474-Add-entity-liquid-API.patch => 0475-Add-entity-liquid-API.patch} (100%) rename patches/server/{0475-Update-itemstack-legacy-name-and-lore.patch => 0476-Update-itemstack-legacy-name-and-lore.patch} (100%) rename patches/server/{0476-Spawn-player-in-correct-world-on-login.patch => 0477-Spawn-player-in-correct-world-on-login.patch} (100%) rename patches/server/{0477-Add-PrepareResultEvent.patch => 0478-Add-PrepareResultEvent.patch} (100%) rename patches/server/{0478-Allow-delegation-to-vanilla-chunk-gen.patch => 0479-Allow-delegation-to-vanilla-chunk-gen.patch} (100%) rename patches/server/{0479-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch => 0480-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch} (100%) rename patches/server/{0480-Optimize-NetworkManager-Exception-Handling.patch => 0481-Optimize-NetworkManager-Exception-Handling.patch} (100%) rename patches/server/{0481-Optimize-the-advancement-data-player-iteration-to-be.patch => 0482-Optimize-the-advancement-data-player-iteration-to-be.patch} (100%) rename patches/server/{0482-Fix-arrows-never-despawning-MC-125757.patch => 0483-Fix-arrows-never-despawning-MC-125757.patch} (100%) rename patches/server/{0483-Thread-Safe-Vanilla-Command-permission-checking.patch => 0484-Thread-Safe-Vanilla-Command-permission-checking.patch} (100%) rename patches/server/{0484-Move-range-check-for-block-placing-up.patch => 0485-Move-range-check-for-block-placing-up.patch} (100%) rename patches/server/{0485-Fix-SPIGOT-5989.patch => 0486-Fix-SPIGOT-5989.patch} (100%) rename patches/server/{0486-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch => 0487-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch} (100%) rename patches/server/{0487-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch => 0488-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch} (100%) rename patches/server/{0488-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch => 0489-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch} (100%) rename patches/server/{0489-Add-missing-strikeLighting-call-to-World-spigot-stri.patch => 0490-Add-missing-strikeLighting-call-to-World-spigot-stri.patch} (100%) rename patches/server/{0490-Fix-some-rails-connecting-improperly.patch => 0491-Fix-some-rails-connecting-improperly.patch} (100%) rename patches/server/{0491-Incremental-player-saving.patch => 0492-Incremental-player-saving.patch} (100%) rename patches/server/{0492-Fix-MC-187716-Use-configured-height.patch => 0493-Fix-MC-187716-Use-configured-height.patch} (100%) rename patches/server/{0493-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch => 0494-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch} (100%) rename patches/server/{0494-Do-not-let-the-server-load-chunks-from-newer-version.patch => 0495-Do-not-let-the-server-load-chunks-from-newer-version.patch} (100%) rename patches/server/{0495-Brand-support.patch => 0496-Brand-support.patch} (100%) rename patches/server/{0496-Add-setMaxPlayers-API.patch => 0497-Add-setMaxPlayers-API.patch} (100%) rename patches/server/{0497-Add-playPickupItemAnimation-to-LivingEntity.patch => 0498-Add-playPickupItemAnimation-to-LivingEntity.patch} (100%) rename patches/server/{0498-Don-t-require-FACING-data.patch => 0499-Don-t-require-FACING-data.patch} (100%) rename patches/server/{0499-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch => 0500-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch} (100%) rename patches/server/{0500-Add-moon-phase-API.patch => 0501-Add-moon-phase-API.patch} (100%) rename patches/server/{0501-Prevent-headless-pistons-from-being-created.patch => 0502-Prevent-headless-pistons-from-being-created.patch} (100%) rename patches/server/{0502-Add-BellRingEvent.patch => 0503-Add-BellRingEvent.patch} (100%) rename patches/server/{0503-Add-zombie-targets-turtle-egg-config.patch => 0504-Add-zombie-targets-turtle-egg-config.patch} (100%) rename patches/server/{0504-Buffer-joins-to-world.patch => 0505-Buffer-joins-to-world.patch} (100%) rename patches/server/{0505-Optimize-redstone-algorithm.patch => 0506-Optimize-redstone-algorithm.patch} (100%) rename patches/server/{0506-Fix-hex-colors-not-working-in-some-kick-messages.patch => 0507-Fix-hex-colors-not-working-in-some-kick-messages.patch} (100%) rename patches/server/{0507-PortalCreateEvent-needs-to-know-its-entity.patch => 0508-PortalCreateEvent-needs-to-know-its-entity.patch} (100%) rename patches/server/{0508-Fix-CraftTeam-null-check.patch => 0509-Fix-CraftTeam-null-check.patch} (100%) rename patches/server/{0509-Add-more-Evoker-API.patch => 0510-Add-more-Evoker-API.patch} (100%) rename patches/server/{0510-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch => 0511-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch} (100%) rename patches/server/{0511-Create-HoverEvent-from-ItemStack-Entity.patch => 0512-Create-HoverEvent-from-ItemStack-Entity.patch} (100%) rename patches/server/{0512-Cache-block-data-strings.patch => 0513-Cache-block-data-strings.patch} (100%) rename patches/server/{0513-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch => 0514-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch} (98%) rename patches/server/{0514-Add-additional-open-container-api-to-HumanEntity.patch => 0515-Add-additional-open-container-api-to-HumanEntity.patch} (100%) rename patches/server/{0515-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch => 0516-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch} (100%) rename patches/server/{0516-Extend-block-drop-capture-to-capture-all-items-added.patch => 0517-Extend-block-drop-capture-to-capture-all-items-added.patch} (100%) rename patches/server/{0517-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch => 0518-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch} (100%) rename patches/server/{0518-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch => 0519-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch} (100%) rename patches/server/{0519-Lazily-track-plugin-scoreboards-by-default.patch => 0520-Lazily-track-plugin-scoreboards-by-default.patch} (100%) rename patches/server/{0520-Entity-isTicking.patch => 0521-Entity-isTicking.patch} (100%) rename patches/server/{0521-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch => 0522-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch} (100%) rename patches/server/{0522-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch => 0523-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch} (100%) rename patches/server/{0523-Reset-Ender-Crystals-on-Dragon-Spawn.patch => 0524-Reset-Ender-Crystals-on-Dragon-Spawn.patch} (100%) rename patches/server/{0524-Fix-for-large-move-vectors-crashing-server.patch => 0525-Fix-for-large-move-vectors-crashing-server.patch} (100%) rename patches/server/{0525-Optimise-getType-calls.patch => 0526-Optimise-getType-calls.patch} (100%) rename patches/server/{0526-Villager-resetOffers.patch => 0527-Villager-resetOffers.patch} (100%) rename patches/server/{0527-Improve-inlinig-for-some-hot-IBlockData-methods.patch => 0528-Improve-inlinig-for-some-hot-IBlockData-methods.patch} (100%) rename patches/server/{0528-Retain-block-place-order-when-capturing-blockstates.patch => 0529-Retain-block-place-order-when-capturing-blockstates.patch} (100%) rename patches/server/{0529-Reduce-blockpos-allocation-from-pathfinding.patch => 0530-Reduce-blockpos-allocation-from-pathfinding.patch} (100%) rename patches/server/{0530-Fix-item-locations-dropped-from-campfires.patch => 0531-Fix-item-locations-dropped-from-campfires.patch} (100%) rename patches/server/{0531-Player-elytra-boost-API.patch => 0532-Player-elytra-boost-API.patch} (100%) rename patches/server/{0532-Fixed-TileEntityBell-memory-leak.patch => 0533-Fixed-TileEntityBell-memory-leak.patch} (100%) rename patches/server/{0533-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch => 0534-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch} (100%) rename patches/server/{0534-Add-getOfflinePlayerIfCached-String.patch => 0535-Add-getOfflinePlayerIfCached-String.patch} (100%) rename patches/server/{0535-Add-ignore-discounts-API.patch => 0536-Add-ignore-discounts-API.patch} (100%) rename patches/server/{0536-Toggle-for-removing-existing-dragon.patch => 0537-Toggle-for-removing-existing-dragon.patch} (100%) rename patches/server/{0537-Fix-client-lag-on-advancement-loading.patch => 0538-Fix-client-lag-on-advancement-loading.patch} (100%) rename patches/server/{0538-Item-no-age-no-player-pickup.patch => 0539-Item-no-age-no-player-pickup.patch} (100%) rename patches/server/{0539-Beacon-API-custom-effect-ranges.patch => 0540-Beacon-API-custom-effect-ranges.patch} (100%) rename patches/server/{0540-Add-API-for-quit-reason.patch => 0541-Add-API-for-quit-reason.patch} (100%) rename patches/server/{0541-Seed-based-feature-search.patch => 0542-Seed-based-feature-search.patch} (100%) rename patches/server/{0542-Add-Wandering-Trader-spawn-rate-config-options.patch => 0543-Add-Wandering-Trader-spawn-rate-config-options.patch} (100%) rename patches/server/{0543-Significantly-improve-performance-of-the-end-generat.patch => 0544-Significantly-improve-performance-of-the-end-generat.patch} (100%) rename patches/server/{0544-Expose-world-spawn-angle.patch => 0545-Expose-world-spawn-angle.patch} (100%) rename patches/server/{0545-Add-Destroy-Speed-API.patch => 0546-Add-Destroy-Speed-API.patch} (100%) rename patches/server/{0546-Fix-Player-spawnParticle-x-y-z-precision-loss.patch => 0547-Fix-Player-spawnParticle-x-y-z-precision-loss.patch} (100%) rename patches/server/{0547-Add-LivingEntity-clearActiveItem.patch => 0548-Add-LivingEntity-clearActiveItem.patch} (100%) rename patches/server/{0548-Add-PlayerItemCooldownEvent.patch => 0549-Add-PlayerItemCooldownEvent.patch} (100%) rename patches/server/{0549-More-lightning-API.patch => 0550-More-lightning-API.patch} (100%) rename patches/server/{0550-Climbing-should-not-bypass-cramming-gamerule.patch => 0551-Climbing-should-not-bypass-cramming-gamerule.patch} (100%) rename patches/server/{0551-Added-missing-default-perms-for-commands.patch => 0552-Added-missing-default-perms-for-commands.patch} (100%) rename patches/server/{0552-Add-PlayerShearBlockEvent.patch => 0553-Add-PlayerShearBlockEvent.patch} (100%) rename patches/server/{0553-Set-spigots-verbose-world-setting-to-false-by-def.patch => 0554-Set-spigots-verbose-world-setting-to-false-by-def.patch} (100%) rename patches/server/{0554-Fix-curing-zombie-villager-discount-exploit.patch => 0555-Fix-curing-zombie-villager-discount-exploit.patch} (100%) rename patches/server/{0555-Limit-recipe-packets.patch => 0556-Limit-recipe-packets.patch} (100%) rename patches/server/{0556-Fix-CraftSound-backwards-compatibility.patch => 0557-Fix-CraftSound-backwards-compatibility.patch} (100%) rename patches/server/{0557-MC-4-Fix-item-position-desync.patch => 0558-MC-4-Fix-item-position-desync.patch} (100%) rename patches/server/{0558-Player-Chunk-Load-Unload-Events.patch => 0559-Player-Chunk-Load-Unload-Events.patch} (100%) rename patches/server/{0559-Optimize-Dynamic-get-Missing-Keys.patch => 0560-Optimize-Dynamic-get-Missing-Keys.patch} (100%) rename patches/server/{0560-Expose-LivingEntity-hurt-direction.patch => 0561-Expose-LivingEntity-hurt-direction.patch} (100%) rename patches/server/{0561-Add-OBSTRUCTED-reason-to-BedEnterResult.patch => 0562-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} (100%) rename patches/server/{0562-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch => 0563-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch} (100%) rename patches/server/{0563-added-PlayerTradeEvent.patch => 0564-added-PlayerTradeEvent.patch} (100%) rename patches/server/{0564-Implement-TargetHitEvent.patch => 0565-Implement-TargetHitEvent.patch} (100%) rename patches/server/{0565-Additional-Block-Material-API-s.patch => 0566-Additional-Block-Material-API-s.patch} (100%) rename patches/server/{0566-Fix-harming-potion-dupe.patch => 0567-Fix-harming-potion-dupe.patch} (100%) rename patches/server/{0567-Implement-API-to-get-Material-from-Boats-and-Minecar.patch => 0568-Implement-API-to-get-Material-from-Boats-and-Minecar.patch} (100%) rename patches/server/{0568-Cache-burn-durations.patch => 0569-Cache-burn-durations.patch} (100%) rename patches/server/{0569-Allow-disabling-mob-spawner-spawn-egg-transformation.patch => 0570-Allow-disabling-mob-spawner-spawn-egg-transformation.patch} (100%) rename patches/server/{0570-Implement-PlayerFlowerPotManipulateEvent.patch => 0571-Implement-PlayerFlowerPotManipulateEvent.patch} (100%) rename patches/server/{0571-Fix-interact-event-not-being-called-in-adventure.patch => 0572-Fix-interact-event-not-being-called-in-adventure.patch} (100%) rename patches/server/{0572-Zombie-API-breaking-doors.patch => 0573-Zombie-API-breaking-doors.patch} (100%) rename patches/server/{0573-Fix-nerfed-slime-when-splitting.patch => 0574-Fix-nerfed-slime-when-splitting.patch} (100%) rename patches/server/{0574-Add-EntityLoadCrossbowEvent.patch => 0575-Add-EntityLoadCrossbowEvent.patch} (100%) rename patches/server/{0575-Guardian-beam-workaround.patch => 0576-Guardian-beam-workaround.patch} (100%) rename patches/server/{0576-Added-WorldGameRuleChangeEvent.patch => 0577-Added-WorldGameRuleChangeEvent.patch} (100%) rename patches/server/{0577-Added-ServerResourcesReloadedEvent.patch => 0578-Added-ServerResourcesReloadedEvent.patch} (100%) rename patches/server/{0578-Added-world-settings-for-mobs-picking-up-loot.patch => 0579-Added-world-settings-for-mobs-picking-up-loot.patch} (100%) rename patches/server/{0579-Implemented-BlockFailedDispenseEvent.patch => 0580-Implemented-BlockFailedDispenseEvent.patch} (100%) rename patches/server/{0580-Added-PlayerLecternPageChangeEvent.patch => 0581-Added-PlayerLecternPageChangeEvent.patch} (100%) rename patches/server/{0581-Added-PlayerLoomPatternSelectEvent.patch => 0582-Added-PlayerLoomPatternSelectEvent.patch} (100%) rename patches/server/{0582-Configurable-door-breaking-difficulty.patch => 0583-Configurable-door-breaking-difficulty.patch} (100%) rename patches/server/{0583-Empty-commands-shall-not-be-dispatched.patch => 0584-Empty-commands-shall-not-be-dispatched.patch} (100%) rename patches/server/{0584-Implement-API-to-expose-exact-interaction-point.patch => 0585-Implement-API-to-expose-exact-interaction-point.patch} (100%) rename patches/server/{0585-Remove-stale-POIs.patch => 0586-Remove-stale-POIs.patch} (100%) rename patches/server/{0586-Fix-villager-boat-exploit.patch => 0587-Fix-villager-boat-exploit.patch} (100%) rename patches/server/{0587-Add-sendOpLevel-API.patch => 0588-Add-sendOpLevel-API.patch} (100%) rename patches/server/{0588-Add-StructureLocateEvent.patch => 0589-Add-StructureLocateEvent.patch} (100%) rename patches/server/{0589-Collision-option-for-requiring-a-player-participant.patch => 0590-Collision-option-for-requiring-a-player-participant.patch} (100%) rename patches/server/{0590-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch => 0591-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch} (100%) rename patches/server/{0591-Return-chat-component-with-empty-text-instead-of-thr.patch => 0592-Return-chat-component-with-empty-text-instead-of-thr.patch} (100%) rename patches/server/{0592-Make-schedule-command-per-world.patch => 0593-Make-schedule-command-per-world.patch} (100%) rename patches/server/{0593-Configurable-max-leash-distance.patch => 0594-Configurable-max-leash-distance.patch} (100%) rename patches/server/{0594-Implement-BlockPreDispenseEvent.patch => 0595-Implement-BlockPreDispenseEvent.patch} (100%) rename patches/server/{0595-Added-Vanilla-Entity-Tags.patch => 0596-Added-Vanilla-Entity-Tags.patch} (100%) rename patches/server/{0596-added-Wither-API.patch => 0597-added-Wither-API.patch} (100%) rename patches/server/{0597-Added-firing-of-PlayerChangeBeaconEffectEvent.patch => 0598-Added-firing-of-PlayerChangeBeaconEffectEvent.patch} (100%) rename patches/server/{0598-Fix-console-spam-when-removing-chests-in-water.patch => 0599-Fix-console-spam-when-removing-chests-in-water.patch} (100%) rename patches/server/{0599-Add-toggle-for-always-placing-the-dragon-egg.patch => 0600-Add-toggle-for-always-placing-the-dragon-egg.patch} (100%) rename patches/server/{0600-Added-PlayerStonecutterRecipeSelectEvent.patch => 0601-Added-PlayerStonecutterRecipeSelectEvent.patch} (100%) rename patches/server/{0601-Add-dropLeash-variable-to-EntityUnleashEvent.patch => 0602-Add-dropLeash-variable-to-EntityUnleashEvent.patch} (100%) rename patches/server/{0602-Skip-distance-map-update-when-spawning-disabled.patch => 0603-Skip-distance-map-update-when-spawning-disabled.patch} (100%) rename patches/server/{0603-Reset-shield-blocking-on-dimension-change.patch => 0604-Reset-shield-blocking-on-dimension-change.patch} (100%) rename patches/server/{0604-add-DragonEggFormEvent.patch => 0605-add-DragonEggFormEvent.patch} (100%) rename patches/server/{0605-EntityMoveEvent.patch => 0606-EntityMoveEvent.patch} (100%) rename patches/server/{0606-added-option-to-disable-pathfinding-updates-on-block.patch => 0607-added-option-to-disable-pathfinding-updates-on-block.patch} (100%) rename patches/server/{0607-Inline-shift-direction-fields.patch => 0608-Inline-shift-direction-fields.patch} (100%) rename patches/server/{0608-Allow-adding-items-to-BlockDropItemEvent.patch => 0609-Allow-adding-items-to-BlockDropItemEvent.patch} (100%) rename patches/server/{0609-Add-getMainThreadExecutor-to-BukkitScheduler.patch => 0610-Add-getMainThreadExecutor-to-BukkitScheduler.patch} (100%) rename patches/server/{0610-living-entity-allow-attribute-registration.patch => 0611-living-entity-allow-attribute-registration.patch} (100%) rename patches/server/{0611-fix-dead-slime-setSize-invincibility.patch => 0612-fix-dead-slime-setSize-invincibility.patch} (100%) rename patches/server/{0612-Merchant-getRecipes-should-return-an-immutable-list.patch => 0613-Merchant-getRecipes-should-return-an-immutable-list.patch} (100%) rename patches/server/{0613-misc-debugging-dumps.patch => 0614-misc-debugging-dumps.patch} (100%) rename patches/server/{0614-Add-support-for-hex-color-codes-in-console.patch => 0615-Add-support-for-hex-color-codes-in-console.patch} (100%) rename patches/server/{0615-Expose-Tracked-Players.patch => 0616-Expose-Tracked-Players.patch} (100%) rename patches/server/{0616-Remove-streams-from-SensorNearest.patch => 0617-Remove-streams-from-SensorNearest.patch} (100%) rename patches/server/{0617-MC-29274-Fix-Wither-hostility-towards-players.patch => 0618-MC-29274-Fix-Wither-hostility-towards-players.patch} (100%) rename patches/server/{0618-Throw-proper-exception-on-empty-JsonList-file.patch => 0619-Throw-proper-exception-on-empty-JsonList-file.patch} (100%) rename patches/server/{0619-Improve-ServerGUI.patch => 0620-Improve-ServerGUI.patch} (100%) rename patches/server/{0620-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch => 0621-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch} (100%) rename patches/server/{0621-fix-converting-txt-to-json-file.patch => 0622-fix-converting-txt-to-json-file.patch} (100%) rename patches/server/{0622-Add-worldborder-events.patch => 0623-Add-worldborder-events.patch} (100%) rename patches/server/{0623-added-PlayerNameEntityEvent.patch => 0624-added-PlayerNameEntityEvent.patch} (100%) rename patches/server/{0624-Prevent-grindstones-from-overstacking-items.patch => 0625-Prevent-grindstones-from-overstacking-items.patch} (100%) rename patches/server/{0625-Add-recipe-to-cook-events.patch => 0626-Add-recipe-to-cook-events.patch} (100%) rename patches/server/{0626-Add-Block-isValidTool.patch => 0627-Add-Block-isValidTool.patch} (100%) rename patches/server/{0627-Allow-using-signs-inside-spawn-protection.patch => 0628-Allow-using-signs-inside-spawn-protection.patch} (100%) rename patches/server/{0628-Implement-Keyed-on-World.patch => 0629-Implement-Keyed-on-World.patch} (100%) rename patches/server/{0629-Add-fast-alternative-constructor-for-Rotations.patch => 0630-Add-fast-alternative-constructor-for-Rotations.patch} (100%) rename patches/server/{0630-Item-Rarity-API.patch => 0631-Item-Rarity-API.patch} (100%) rename patches/server/{0631-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch => 0632-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch} (100%) rename patches/server/{0632-copy-TESign-isEditable-from-snapshots.patch => 0633-copy-TESign-isEditable-from-snapshots.patch} (100%) rename patches/server/{0633-Drop-carried-item-when-player-has-disconnected.patch => 0634-Drop-carried-item-when-player-has-disconnected.patch} (100%) rename patches/server/{0634-forced-whitelist-use-configurable-kick-message.patch => 0635-forced-whitelist-use-configurable-kick-message.patch} (100%) rename patches/server/{0635-Don-t-ignore-result-of-PlayerEditBookEvent.patch => 0636-Don-t-ignore-result-of-PlayerEditBookEvent.patch} (100%) rename patches/server/{0636-fix-cancelling-block-falling-causing-client-desync.patch => 0637-fix-cancelling-block-falling-causing-client-desync.patch} (100%) rename patches/server/{0637-Expose-protocol-version.patch => 0638-Expose-protocol-version.patch} (100%) rename patches/server/{0638-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch => 0639-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} (100%) rename patches/server/{0639-Enhance-console-tab-completions-for-brigadier-comman.patch => 0640-Enhance-console-tab-completions-for-brigadier-comman.patch} (100%) rename patches/server/{0640-Fix-PlayerItemConsumeEvent-cancelling-properly.patch => 0641-Fix-PlayerItemConsumeEvent-cancelling-properly.patch} (100%) rename patches/server/{0641-Add-bypass-host-check.patch => 0642-Add-bypass-host-check.patch} (100%) rename patches/server/{0642-Set-area-affect-cloud-rotation.patch => 0643-Set-area-affect-cloud-rotation.patch} (100%) rename patches/server/{0643-add-isDeeplySleeping-to-HumanEntity.patch => 0644-add-isDeeplySleeping-to-HumanEntity.patch} (100%) rename patches/server/{0644-Fix-duplicating-give-items-on-item-drop-cancel.patch => 0645-Fix-duplicating-give-items-on-item-drop-cancel.patch} (100%) rename patches/server/{0645-add-consumeFuel-to-FurnaceBurnEvent.patch => 0646-add-consumeFuel-to-FurnaceBurnEvent.patch} (100%) rename patches/server/{0646-add-get-set-drop-chance-to-EntityEquipment.patch => 0647-add-get-set-drop-chance-to-EntityEquipment.patch} (100%) rename patches/server/{0647-fix-PigZombieAngerEvent-cancellation.patch => 0648-fix-PigZombieAngerEvent-cancellation.patch} (100%) rename patches/server/{0648-Fix-checkReach-check-for-Shulker-boxes.patch => 0649-Fix-checkReach-check-for-Shulker-boxes.patch} (100%) rename patches/server/{0649-fix-PlayerItemHeldEvent-firing-twice.patch => 0650-fix-PlayerItemHeldEvent-firing-twice.patch} (100%) rename patches/server/{0650-Added-PlayerDeepSleepEvent.patch => 0651-Added-PlayerDeepSleepEvent.patch} (100%) rename patches/server/{0651-More-World-API.patch => 0652-More-World-API.patch} (100%) rename patches/server/{0652-Added-PlayerBedFailEnterEvent.patch => 0653-Added-PlayerBedFailEnterEvent.patch} (100%) rename patches/server/{0653-Implement-methods-to-convert-between-Component-and-B.patch => 0654-Implement-methods-to-convert-between-Component-and-B.patch} (100%) rename patches/server/{0654-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch => 0655-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch} (100%) rename patches/server/{0655-Introduce-beacon-activation-deactivation-events.patch => 0656-Introduce-beacon-activation-deactivation-events.patch} (100%) rename patches/server/{0656-add-RespawnFlags-to-PlayerRespawnEvent.patch => 0657-add-RespawnFlags-to-PlayerRespawnEvent.patch} (100%) rename patches/server/{0657-Add-Channel-initialization-listeners.patch => 0658-Add-Channel-initialization-listeners.patch} (100%) rename patches/server/{0658-Send-empty-commands-if-tab-completion-is-disabled.patch => 0659-Send-empty-commands-if-tab-completion-is-disabled.patch} (100%) rename patches/server/{0659-Add-more-WanderingTrader-API.patch => 0660-Add-more-WanderingTrader-API.patch} (100%) rename patches/server/{0660-Add-EntityBlockStorage-clearEntities.patch => 0661-Add-EntityBlockStorage-clearEntities.patch} (100%) rename patches/server/{0661-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch => 0662-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch} (100%) rename patches/server/{0662-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch => 0663-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch} (100%) rename patches/server/{0663-Inventory-close.patch => 0664-Inventory-close.patch} (100%) rename patches/server/{0664-call-PortalCreateEvent-players-and-end-platform.patch => 0665-call-PortalCreateEvent-players-and-end-platform.patch} (100%) rename patches/server/{0665-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch => 0666-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch} (100%) rename patches/server/{0666-Fix-CraftPotionBrewer-cache.patch => 0667-Fix-CraftPotionBrewer-cache.patch} (100%) rename patches/server/{0667-Add-basic-Datapack-API.patch => 0668-Add-basic-Datapack-API.patch} (100%) rename patches/server/{0668-Add-environment-variable-to-disable-server-gui.patch => 0669-Add-environment-variable-to-disable-server-gui.patch} (100%) rename patches/server/{0669-additions-to-PlayerGameModeChangeEvent.patch => 0670-additions-to-PlayerGameModeChangeEvent.patch} (100%) rename patches/server/{0670-ItemStack-repair-check-API.patch => 0671-ItemStack-repair-check-API.patch} (100%) rename patches/server/{0671-More-Enchantment-API.patch => 0672-More-Enchantment-API.patch} (100%) rename patches/server/{0672-Add-command-line-option-to-load-extra-plugin-jars-no.patch => 0673-Add-command-line-option-to-load-extra-plugin-jars-no.patch} (100%) rename patches/server/{0673-Fix-and-optimise-world-force-upgrading.patch => 0674-Fix-and-optimise-world-force-upgrading.patch} (100%) rename patches/server/{0674-Add-Mob-lookAt-API.patch => 0675-Add-Mob-lookAt-API.patch} (100%) rename patches/server/{0675-Add-Unix-domain-socket-support.patch => 0676-Add-Unix-domain-socket-support.patch} (100%) rename patches/server/{0676-Add-EntityInsideBlockEvent.patch => 0677-Add-EntityInsideBlockEvent.patch} (100%) rename patches/server/{0677-Attributes-API-for-item-defaults.patch => 0678-Attributes-API-for-item-defaults.patch} (100%) rename patches/server/{0678-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch => 0679-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch} (100%) rename patches/server/{0679-Add-cause-to-Weather-ThunderChangeEvents.patch => 0680-Add-cause-to-Weather-ThunderChangeEvents.patch} (100%) rename patches/server/{0680-More-Lidded-Block-API.patch => 0681-More-Lidded-Block-API.patch} (100%) rename patches/server/{0681-Limit-item-frame-cursors-on-maps.patch => 0682-Limit-item-frame-cursors-on-maps.patch} (100%) rename patches/server/{0682-Add-PufferFishStateChangeEvent.patch => 0683-Add-PufferFishStateChangeEvent.patch} (100%) rename patches/server/{0683-Add-PlayerKickEvent-causes.patch => 0684-Add-PlayerKickEvent-causes.patch} (100%) rename patches/server/{0684-Fix-PlayerBucketEmptyEvent-result-itemstack.patch => 0685-Fix-PlayerBucketEmptyEvent-result-itemstack.patch} (100%) rename patches/server/{0684-Synchronize-PalettedContainer-instead-of-ReentrantLoc.patch => 0686-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch} (100%) rename patches/server/{0685-Add-option-to-fix-items-merging-through-walls.patch => 0687-Add-option-to-fix-items-merging-through-walls.patch} (100%) rename patches/server/{0686-Add-BellRevealRaiderEvent.patch => 0688-Add-BellRevealRaiderEvent.patch} (100%) rename patches/server/{0687-Fix-invulnerable-end-crystals.patch => 0689-Fix-invulnerable-end-crystals.patch} (100%) rename patches/server/{0688-Add-ElderGuardianAppearanceEvent.patch => 0690-Add-ElderGuardianAppearanceEvent.patch} (100%) rename patches/server/{0689-Reset-villager-inventory-on-cancelled-pickup-event.patch => 0691-Reset-villager-inventory-on-cancelled-pickup-event.patch} (100%) rename patches/server/{0690-Fix-dangerous-end-portal-logic.patch => 0692-Fix-dangerous-end-portal-logic.patch} (100%) rename patches/server/{0690-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch => 0693-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch} (100%) rename patches/server/{0691-Make-item-validations-configurable.patch => 0694-Make-item-validations-configurable.patch} (100%) rename patches/server/{0692-Add-more-line-of-sight-methods.patch => 0695-Add-more-line-of-sight-methods.patch} (100%) rename patches/server/{0693-add-per-world-spawn-limits.patch => 0696-add-per-world-spawn-limits.patch} (100%) rename patches/server/{0694-Fix-PotionSplashEvent-for-water-splash-potions.patch => 0697-Fix-PotionSplashEvent-for-water-splash-potions.patch} (100%) rename patches/server/{0694-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch => 0698-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch} (100%) diff --git a/patches/api/0154-PreSpawnerSpawnEvent.patch b/patches/api/0155-PreSpawnerSpawnEvent.patch similarity index 100% rename from patches/api/0154-PreSpawnerSpawnEvent.patch rename to patches/api/0155-PreSpawnerSpawnEvent.patch diff --git a/patches/api/0155-Add-Material-Tags.patch b/patches/api/0156-Add-Material-Tags.patch similarity index 100% rename from patches/api/0155-Add-Material-Tags.patch rename to patches/api/0156-Add-Material-Tags.patch diff --git a/patches/api/0156-Add-LivingEntity-getTargetEntity.patch b/patches/api/0157-Add-LivingEntity-getTargetEntity.patch similarity index 97% rename from patches/api/0156-Add-LivingEntity-getTargetEntity.patch rename to patches/api/0157-Add-LivingEntity-getTargetEntity.patch index 43c223a636..5ec536beeb 100644 --- a/patches/api/0156-Add-LivingEntity-getTargetEntity.patch +++ b/patches/api/0157-Add-LivingEntity-getTargetEntity.patch @@ -49,7 +49,7 @@ index 0000000000000000000000000000000000000000..f52644fab1522bdf83ff4f489e9805b2 + } +} diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 05992ade1bca42a6233373b44513b89986d89c5a..ac6921093457cee6d01fd27690c8bb6034b4af53 100644 +index ad885a0775b387e3e8ca6bfae80c18465038056c..93d20f67bf856d80226470ae2442d199d3e2f45b 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -151,6 +151,50 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0157-Add-sun-related-API.patch b/patches/api/0158-Add-sun-related-API.patch similarity index 100% rename from patches/api/0157-Add-sun-related-API.patch rename to patches/api/0158-Add-sun-related-API.patch diff --git a/patches/api/0158-Here-s-Johnny.patch b/patches/api/0159-Here-s-Johnny.patch similarity index 100% rename from patches/api/0158-Here-s-Johnny.patch rename to patches/api/0159-Here-s-Johnny.patch diff --git a/patches/api/0159-Turtle-API.patch b/patches/api/0160-Turtle-API.patch similarity index 100% rename from patches/api/0159-Turtle-API.patch rename to patches/api/0160-Turtle-API.patch diff --git a/patches/api/0160-Add-spectator-target-events.patch b/patches/api/0161-Add-spectator-target-events.patch similarity index 100% rename from patches/api/0160-Add-spectator-target-events.patch rename to patches/api/0161-Add-spectator-target-events.patch diff --git a/patches/api/0161-Add-more-Witch-API.patch b/patches/api/0162-Add-more-Witch-API.patch similarity index 100% rename from patches/api/0161-Add-more-Witch-API.patch rename to patches/api/0162-Add-more-Witch-API.patch diff --git a/patches/api/0162-Make-the-default-permission-message-configurable.patch b/patches/api/0163-Make-the-default-permission-message-configurable.patch similarity index 100% rename from patches/api/0162-Make-the-default-permission-message-configurable.patch rename to patches/api/0163-Make-the-default-permission-message-configurable.patch diff --git a/patches/api/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch b/patches/api/0164-Support-cancellation-supression-of-EntityDismount-Ve.patch similarity index 100% rename from patches/api/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch rename to patches/api/0164-Support-cancellation-supression-of-EntityDismount-Ve.patch diff --git a/patches/api/0164-Add-more-Zombie-API.patch b/patches/api/0165-Add-more-Zombie-API.patch similarity index 100% rename from patches/api/0164-Add-more-Zombie-API.patch rename to patches/api/0165-Add-more-Zombie-API.patch diff --git a/patches/api/0165-Change-the-reserved-channel-check-to-be-sensible.patch b/patches/api/0166-Change-the-reserved-channel-check-to-be-sensible.patch similarity index 100% rename from patches/api/0165-Change-the-reserved-channel-check-to-be-sensible.patch rename to patches/api/0166-Change-the-reserved-channel-check-to-be-sensible.patch diff --git a/patches/api/0166-Add-PlayerConnectionCloseEvent.patch b/patches/api/0167-Add-PlayerConnectionCloseEvent.patch similarity index 100% rename from patches/api/0166-Add-PlayerConnectionCloseEvent.patch rename to patches/api/0167-Add-PlayerConnectionCloseEvent.patch diff --git a/patches/api/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/patches/api/0168-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 100% rename from patches/api/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to patches/api/0168-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch diff --git a/patches/api/0168-BlockDestroyEvent.patch b/patches/api/0169-BlockDestroyEvent.patch similarity index 100% rename from patches/api/0168-BlockDestroyEvent.patch rename to patches/api/0169-BlockDestroyEvent.patch diff --git a/patches/api/0169-Add-ItemStack-Recipe-API-helper-methods.patch b/patches/api/0170-Add-ItemStack-Recipe-API-helper-methods.patch similarity index 100% rename from patches/api/0169-Add-ItemStack-Recipe-API-helper-methods.patch rename to patches/api/0170-Add-ItemStack-Recipe-API-helper-methods.patch diff --git a/patches/api/0170-Add-WhitelistToggleEvent.patch b/patches/api/0171-Add-WhitelistToggleEvent.patch similarity index 100% rename from patches/api/0170-Add-WhitelistToggleEvent.patch rename to patches/api/0171-Add-WhitelistToggleEvent.patch diff --git a/patches/api/0171-Annotation-Test-changes.patch b/patches/api/0172-Annotation-Test-changes.patch similarity index 100% rename from patches/api/0171-Annotation-Test-changes.patch rename to patches/api/0172-Annotation-Test-changes.patch diff --git a/patches/api/0172-Entity-getEntitySpawnReason.patch b/patches/api/0173-Entity-getEntitySpawnReason.patch similarity index 100% rename from patches/api/0172-Entity-getEntitySpawnReason.patch rename to patches/api/0173-Entity-getEntitySpawnReason.patch diff --git a/patches/api/0173-Add-GS4-Query-event.patch b/patches/api/0174-Add-GS4-Query-event.patch similarity index 100% rename from patches/api/0173-Add-GS4-Query-event.patch rename to patches/api/0174-Add-GS4-Query-event.patch diff --git a/patches/api/0174-Add-PlayerPostRespawnEvent.patch b/patches/api/0175-Add-PlayerPostRespawnEvent.patch similarity index 100% rename from patches/api/0174-Add-PlayerPostRespawnEvent.patch rename to patches/api/0175-Add-PlayerPostRespawnEvent.patch diff --git a/patches/api/0175-Ignore-package-private-methods-for-nullability-annot.patch b/patches/api/0176-Ignore-package-private-methods-for-nullability-annot.patch similarity index 100% rename from patches/api/0175-Ignore-package-private-methods-for-nullability-annot.patch rename to patches/api/0176-Ignore-package-private-methods-for-nullability-annot.patch diff --git a/patches/api/0176-Flip-some-Spigot-API-null-annotations.patch b/patches/api/0177-Flip-some-Spigot-API-null-annotations.patch similarity index 100% rename from patches/api/0176-Flip-some-Spigot-API-null-annotations.patch rename to patches/api/0177-Flip-some-Spigot-API-null-annotations.patch diff --git a/patches/api/0177-Server-Tick-Events.patch b/patches/api/0178-Server-Tick-Events.patch similarity index 100% rename from patches/api/0177-Server-Tick-Events.patch rename to patches/api/0178-Server-Tick-Events.patch diff --git a/patches/api/0178-PlayerDeathEvent-getItemsToKeep.patch b/patches/api/0179-PlayerDeathEvent-getItemsToKeep.patch similarity index 100% rename from patches/api/0178-PlayerDeathEvent-getItemsToKeep.patch rename to patches/api/0179-PlayerDeathEvent-getItemsToKeep.patch diff --git a/patches/api/0179-Add-Heightmap-API.patch b/patches/api/0180-Add-Heightmap-API.patch similarity index 100% rename from patches/api/0179-Add-Heightmap-API.patch rename to patches/api/0180-Add-Heightmap-API.patch diff --git a/patches/api/0180-Mob-Spawner-API-Enhancements.patch b/patches/api/0181-Mob-Spawner-API-Enhancements.patch similarity index 100% rename from patches/api/0180-Mob-Spawner-API-Enhancements.patch rename to patches/api/0181-Mob-Spawner-API-Enhancements.patch diff --git a/patches/api/0181-Add-BlockSoundGroup-interface.patch b/patches/api/0182-Add-BlockSoundGroup-interface.patch similarity index 100% rename from patches/api/0181-Add-BlockSoundGroup-interface.patch rename to patches/api/0182-Add-BlockSoundGroup-interface.patch diff --git a/patches/api/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch b/patches/api/0183-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch similarity index 100% rename from patches/api/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch rename to patches/api/0183-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch diff --git a/patches/api/0183-Increase-custom-payload-channel-message-size.patch b/patches/api/0184-Increase-custom-payload-channel-message-size.patch similarity index 100% rename from patches/api/0183-Increase-custom-payload-channel-message-size.patch rename to patches/api/0184-Increase-custom-payload-channel-message-size.patch diff --git a/patches/api/0184-Expose-the-internal-current-tick.patch b/patches/api/0185-Expose-the-internal-current-tick.patch similarity index 100% rename from patches/api/0184-Expose-the-internal-current-tick.patch rename to patches/api/0185-Expose-the-internal-current-tick.patch diff --git a/patches/api/0185-PlayerDeathEvent-shouldDropExperience.patch b/patches/api/0186-PlayerDeathEvent-shouldDropExperience.patch similarity index 100% rename from patches/api/0185-PlayerDeathEvent-shouldDropExperience.patch rename to patches/api/0186-PlayerDeathEvent-shouldDropExperience.patch diff --git a/patches/api/0186-Add-effect-to-block-break-naturally.patch b/patches/api/0187-Add-effect-to-block-break-naturally.patch similarity index 100% rename from patches/api/0186-Add-effect-to-block-break-naturally.patch rename to patches/api/0187-Add-effect-to-block-break-naturally.patch diff --git a/patches/api/0187-World-view-distance-api.patch b/patches/api/0188-World-view-distance-api.patch similarity index 100% rename from patches/api/0187-World-view-distance-api.patch rename to patches/api/0188-World-view-distance-api.patch diff --git a/patches/api/0188-Add-ThrownEggHatchEvent.patch b/patches/api/0189-Add-ThrownEggHatchEvent.patch similarity index 100% rename from patches/api/0188-Add-ThrownEggHatchEvent.patch rename to patches/api/0189-Add-ThrownEggHatchEvent.patch diff --git a/patches/api/0189-Entity-Jump-API.patch b/patches/api/0190-Entity-Jump-API.patch similarity index 100% rename from patches/api/0189-Entity-Jump-API.patch rename to patches/api/0190-Entity-Jump-API.patch diff --git a/patches/api/0190-add-hand-to-BlockMultiPlaceEvent.patch b/patches/api/0191-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from patches/api/0190-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/api/0191-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/patches/api/0191-Add-tick-times-API.patch b/patches/api/0192-Add-tick-times-API.patch similarity index 100% rename from patches/api/0191-Add-tick-times-API.patch rename to patches/api/0192-Add-tick-times-API.patch diff --git a/patches/api/0192-Expose-MinecraftServer-isRunning.patch b/patches/api/0193-Expose-MinecraftServer-isRunning.patch similarity index 100% rename from patches/api/0192-Expose-MinecraftServer-isRunning.patch rename to patches/api/0193-Expose-MinecraftServer-isRunning.patch diff --git a/patches/api/0193-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/api/0194-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 100% rename from patches/api/0193-Add-Raw-Byte-ItemStack-Serialization.patch rename to patches/api/0194-Add-Raw-Byte-ItemStack-Serialization.patch diff --git a/patches/api/0194-Disable-Sync-Events-firing-Async-errors-during-shutd.patch b/patches/api/0195-Disable-Sync-Events-firing-Async-errors-during-shutd.patch similarity index 100% rename from patches/api/0194-Disable-Sync-Events-firing-Async-errors-during-shutd.patch rename to patches/api/0195-Disable-Sync-Events-firing-Async-errors-during-shutd.patch diff --git a/patches/api/0195-Make-JavaPluginLoader-thread-safe.patch b/patches/api/0196-Make-JavaPluginLoader-thread-safe.patch similarity index 100% rename from patches/api/0195-Make-JavaPluginLoader-thread-safe.patch rename to patches/api/0196-Make-JavaPluginLoader-thread-safe.patch diff --git a/patches/api/0196-Add-Player-Client-Options-API.patch b/patches/api/0197-Add-Player-Client-Options-API.patch similarity index 100% rename from patches/api/0196-Add-Player-Client-Options-API.patch rename to patches/api/0197-Add-Player-Client-Options-API.patch diff --git a/patches/api/0197-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/api/0198-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from patches/api/0197-Add-PlayerAttackEntityCooldownResetEvent.patch rename to patches/api/0198-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/patches/api/0198-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch b/patches/api/0199-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch similarity index 100% rename from patches/api/0198-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch rename to patches/api/0199-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch diff --git a/patches/api/0199-Add-item-slot-convenience-methods.patch b/patches/api/0200-Add-item-slot-convenience-methods.patch similarity index 100% rename from patches/api/0199-Add-item-slot-convenience-methods.patch rename to patches/api/0200-Add-item-slot-convenience-methods.patch diff --git a/patches/api/0200-Villager-Restocks-API.patch b/patches/api/0201-Villager-Restocks-API.patch similarity index 91% rename from patches/api/0200-Villager-Restocks-API.patch rename to patches/api/0201-Villager-Restocks-API.patch index e2dcfc3144..689bd35b3c 100644 --- a/patches/api/0200-Villager-Restocks-API.patch +++ b/patches/api/0201-Villager-Restocks-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Villager Restocks API diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java -index ef48ad9b28750ab7b33071f6b8e354e922731909..d1579153092c1b80350155110f1b9926b1a1ef57 100644 +index 6545e568b74bd096e184b85e8da6f0d40acd3b36..ef8a81c4857bd06be19264580bf3a7e087118f5c 100644 --- a/src/main/java/org/bukkit/entity/Villager.java +++ b/src/main/java/org/bukkit/entity/Villager.java @@ -77,6 +77,20 @@ public interface Villager extends AbstractVillager { diff --git a/patches/api/0201-Add-Mob-Goal-API.patch b/patches/api/0202-Add-Mob-Goal-API.patch similarity index 100% rename from patches/api/0201-Add-Mob-Goal-API.patch rename to patches/api/0202-Add-Mob-Goal-API.patch diff --git a/patches/api/0202-Add-villager-reputation-API.patch b/patches/api/0203-Add-villager-reputation-API.patch similarity index 100% rename from patches/api/0202-Add-villager-reputation-API.patch rename to patches/api/0203-Add-villager-reputation-API.patch diff --git a/patches/api/0203-Expose-game-version.patch b/patches/api/0204-Expose-game-version.patch similarity index 100% rename from patches/api/0203-Expose-game-version.patch rename to patches/api/0204-Expose-game-version.patch diff --git a/patches/api/0204-Spawn-Reason-API.patch b/patches/api/0205-Spawn-Reason-API.patch similarity index 100% rename from patches/api/0204-Spawn-Reason-API.patch rename to patches/api/0205-Spawn-Reason-API.patch diff --git a/patches/api/0205-Potential-bed-API.patch b/patches/api/0206-Potential-bed-API.patch similarity index 100% rename from patches/api/0205-Potential-bed-API.patch rename to patches/api/0206-Potential-bed-API.patch diff --git a/patches/api/0206-Prioritise-own-classes-where-possible.patch b/patches/api/0207-Prioritise-own-classes-where-possible.patch similarity index 100% rename from patches/api/0206-Prioritise-own-classes-where-possible.patch rename to patches/api/0207-Prioritise-own-classes-where-possible.patch diff --git a/patches/api/0207-Provide-a-useful-PluginClassLoader-toString.patch b/patches/api/0208-Provide-a-useful-PluginClassLoader-toString.patch similarity index 100% rename from patches/api/0207-Provide-a-useful-PluginClassLoader-toString.patch rename to patches/api/0208-Provide-a-useful-PluginClassLoader-toString.patch diff --git a/patches/api/0208-Inventory-getHolder-method-without-block-snapshot.patch b/patches/api/0209-Inventory-getHolder-method-without-block-snapshot.patch similarity index 100% rename from patches/api/0208-Inventory-getHolder-method-without-block-snapshot.patch rename to patches/api/0209-Inventory-getHolder-method-without-block-snapshot.patch diff --git a/patches/api/0209-Expose-Arrow-getItemStack.patch b/patches/api/0210-Expose-Arrow-getItemStack.patch similarity index 100% rename from patches/api/0209-Expose-Arrow-getItemStack.patch rename to patches/api/0210-Expose-Arrow-getItemStack.patch diff --git a/patches/api/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/api/0211-Add-and-implement-PlayerRecipeBookClickEvent.patch similarity index 100% rename from patches/api/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch rename to patches/api/0211-Add-and-implement-PlayerRecipeBookClickEvent.patch diff --git a/patches/api/0211-Support-components-in-ItemMeta.patch b/patches/api/0212-Support-components-in-ItemMeta.patch similarity index 100% rename from patches/api/0211-Support-components-in-ItemMeta.patch rename to patches/api/0212-Support-components-in-ItemMeta.patch diff --git a/patches/api/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch b/patches/api/0213-added-2-new-TargetReasons-for-1.16-mob-behavior.patch similarity index 100% rename from patches/api/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch rename to patches/api/0213-added-2-new-TargetReasons-for-1.16-mob-behavior.patch diff --git a/patches/api/0213-Add-entity-liquid-API.patch b/patches/api/0214-Add-entity-liquid-API.patch similarity index 100% rename from patches/api/0213-Add-entity-liquid-API.patch rename to patches/api/0214-Add-entity-liquid-API.patch diff --git a/patches/api/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch b/patches/api/0215-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch similarity index 100% rename from patches/api/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch rename to patches/api/0215-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch diff --git a/patches/api/0215-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/api/0216-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 100% rename from patches/api/0215-Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/api/0216-Allow-delegation-to-vanilla-chunk-gen.patch diff --git a/patches/api/0216-Support-hex-colors-in-getLastColors.patch b/patches/api/0217-Support-hex-colors-in-getLastColors.patch similarity index 100% rename from patches/api/0216-Support-hex-colors-in-getLastColors.patch rename to patches/api/0217-Support-hex-colors-in-getLastColors.patch diff --git a/patches/api/0217-Add-setMaxPlayers-API.patch b/patches/api/0218-Add-setMaxPlayers-API.patch similarity index 100% rename from patches/api/0217-Add-setMaxPlayers-API.patch rename to patches/api/0218-Add-setMaxPlayers-API.patch diff --git a/patches/api/0218-Add-moon-phase-API.patch b/patches/api/0219-Add-moon-phase-API.patch similarity index 100% rename from patches/api/0218-Add-moon-phase-API.patch rename to patches/api/0219-Add-moon-phase-API.patch diff --git a/patches/api/0219-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/api/0220-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from patches/api/0219-Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/api/0220-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/patches/api/0220-Add-BellRingEvent.patch b/patches/api/0221-Add-BellRingEvent.patch similarity index 100% rename from patches/api/0220-Add-BellRingEvent.patch rename to patches/api/0221-Add-BellRingEvent.patch diff --git a/patches/api/0221-Brand-support.patch b/patches/api/0222-Brand-support.patch similarity index 100% rename from patches/api/0221-Brand-support.patch rename to patches/api/0222-Brand-support.patch diff --git a/patches/api/0222-Add-more-Evoker-API.patch b/patches/api/0223-Add-more-Evoker-API.patch similarity index 100% rename from patches/api/0222-Add-more-Evoker-API.patch rename to patches/api/0223-Add-more-Evoker-API.patch diff --git a/patches/api/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/api/0224-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 100% rename from patches/api/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to patches/api/0224-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch diff --git a/patches/api/0224-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/api/0225-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 100% rename from patches/api/0224-Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/api/0225-Create-HoverEvent-from-ItemStack-Entity.patch diff --git a/patches/api/0225-Add-additional-open-container-api-to-HumanEntity.patch b/patches/api/0226-Add-additional-open-container-api-to-HumanEntity.patch similarity index 100% rename from patches/api/0225-Add-additional-open-container-api-to-HumanEntity.patch rename to patches/api/0226-Add-additional-open-container-api-to-HumanEntity.patch diff --git a/patches/api/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/api/0227-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 100% rename from patches/api/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to patches/api/0227-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch diff --git a/patches/api/0227-Entity-isTicking.patch b/patches/api/0228-Entity-isTicking.patch similarity index 100% rename from patches/api/0227-Entity-isTicking.patch rename to patches/api/0228-Entity-isTicking.patch diff --git a/patches/api/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch b/patches/api/0229-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch similarity index 100% rename from patches/api/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch rename to patches/api/0229-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch diff --git a/patches/api/0229-Villager-resetOffers.patch b/patches/api/0230-Villager-resetOffers.patch similarity index 100% rename from patches/api/0229-Villager-resetOffers.patch rename to patches/api/0230-Villager-resetOffers.patch diff --git a/patches/api/0230-Player-elytra-boost-API.patch b/patches/api/0231-Player-elytra-boost-API.patch similarity index 100% rename from patches/api/0230-Player-elytra-boost-API.patch rename to patches/api/0231-Player-elytra-boost-API.patch diff --git a/patches/api/0231-Add-getOfflinePlayerIfCached-String.patch b/patches/api/0232-Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from patches/api/0231-Add-getOfflinePlayerIfCached-String.patch rename to patches/api/0232-Add-getOfflinePlayerIfCached-String.patch diff --git a/patches/api/0232-Add-ignore-discounts-API.patch b/patches/api/0233-Add-ignore-discounts-API.patch similarity index 100% rename from patches/api/0232-Add-ignore-discounts-API.patch rename to patches/api/0233-Add-ignore-discounts-API.patch diff --git a/patches/api/0233-Item-no-age-no-player-pickup.patch b/patches/api/0234-Item-no-age-no-player-pickup.patch similarity index 100% rename from patches/api/0233-Item-no-age-no-player-pickup.patch rename to patches/api/0234-Item-no-age-no-player-pickup.patch diff --git a/patches/api/0234-Beacon-API-custom-effect-ranges.patch b/patches/api/0235-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from patches/api/0234-Beacon-API-custom-effect-ranges.patch rename to patches/api/0235-Beacon-API-custom-effect-ranges.patch diff --git a/patches/api/0235-Add-API-for-quit-reason.patch b/patches/api/0236-Add-API-for-quit-reason.patch similarity index 100% rename from patches/api/0235-Add-API-for-quit-reason.patch rename to patches/api/0236-Add-API-for-quit-reason.patch diff --git a/patches/api/0236-Add-Destroy-Speed-API.patch b/patches/api/0237-Add-Destroy-Speed-API.patch similarity index 100% rename from patches/api/0236-Add-Destroy-Speed-API.patch rename to patches/api/0237-Add-Destroy-Speed-API.patch diff --git a/patches/api/0237-Add-LivingEntity-clearActiveItem.patch b/patches/api/0238-Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from patches/api/0237-Add-LivingEntity-clearActiveItem.patch rename to patches/api/0238-Add-LivingEntity-clearActiveItem.patch diff --git a/patches/api/0238-Add-PlayerItemCooldownEvent.patch b/patches/api/0239-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from patches/api/0238-Add-PlayerItemCooldownEvent.patch rename to patches/api/0239-Add-PlayerItemCooldownEvent.patch diff --git a/patches/api/0239-More-lightning-API.patch b/patches/api/0240-More-lightning-API.patch similarity index 100% rename from patches/api/0239-More-lightning-API.patch rename to patches/api/0240-More-lightning-API.patch diff --git a/patches/api/0240-Add-PlayerShearBlockEvent.patch b/patches/api/0241-Add-PlayerShearBlockEvent.patch similarity index 100% rename from patches/api/0240-Add-PlayerShearBlockEvent.patch rename to patches/api/0241-Add-PlayerShearBlockEvent.patch diff --git a/patches/api/0241-Enable-multi-release-plugin-jars.patch b/patches/api/0242-Enable-multi-release-plugin-jars.patch similarity index 100% rename from patches/api/0241-Enable-multi-release-plugin-jars.patch rename to patches/api/0242-Enable-multi-release-plugin-jars.patch diff --git a/patches/api/0242-Player-Chunk-Load-Unload-Events.patch b/patches/api/0243-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from patches/api/0242-Player-Chunk-Load-Unload-Events.patch rename to patches/api/0243-Player-Chunk-Load-Unload-Events.patch diff --git a/patches/api/0243-Expose-LivingEntity-hurt-direction.patch b/patches/api/0244-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from patches/api/0243-Expose-LivingEntity-hurt-direction.patch rename to patches/api/0244-Expose-LivingEntity-hurt-direction.patch diff --git a/patches/api/0244-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/api/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from patches/api/0244-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/api/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/patches/api/0245-Added-PlayerTradeEvent.patch b/patches/api/0246-Added-PlayerTradeEvent.patch similarity index 100% rename from patches/api/0245-Added-PlayerTradeEvent.patch rename to patches/api/0246-Added-PlayerTradeEvent.patch diff --git a/patches/api/0246-Add-TargetHitEvent-API.patch b/patches/api/0247-Add-TargetHitEvent-API.patch similarity index 100% rename from patches/api/0246-Add-TargetHitEvent-API.patch rename to patches/api/0247-Add-TargetHitEvent-API.patch diff --git a/patches/api/0247-Additional-Block-Material-API-s.patch b/patches/api/0248-Additional-Block-Material-API-s.patch similarity index 100% rename from patches/api/0247-Additional-Block-Material-API-s.patch rename to patches/api/0248-Additional-Block-Material-API-s.patch diff --git a/patches/api/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch b/patches/api/0249-Add-API-to-get-Material-from-Boats-and-Minecarts.patch similarity index 100% rename from patches/api/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch rename to patches/api/0249-Add-API-to-get-Material-from-Boats-and-Minecarts.patch diff --git a/patches/api/0249-Add-PlayerFlowerPotManipulateEvent.patch b/patches/api/0250-Add-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from patches/api/0249-Add-PlayerFlowerPotManipulateEvent.patch rename to patches/api/0250-Add-PlayerFlowerPotManipulateEvent.patch diff --git a/patches/api/0250-Zombie-API-breaking-doors.patch b/patches/api/0251-Zombie-API-breaking-doors.patch similarity index 100% rename from patches/api/0250-Zombie-API-breaking-doors.patch rename to patches/api/0251-Zombie-API-breaking-doors.patch diff --git a/patches/api/0251-Add-EntityLoadCrossbowEvent.patch b/patches/api/0252-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from patches/api/0251-Add-EntityLoadCrossbowEvent.patch rename to patches/api/0252-Add-EntityLoadCrossbowEvent.patch diff --git a/patches/api/0252-Added-WorldGameRuleChangeEvent.patch b/patches/api/0253-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from patches/api/0252-Added-WorldGameRuleChangeEvent.patch rename to patches/api/0253-Added-WorldGameRuleChangeEvent.patch diff --git a/patches/api/0253-Added-ServerResourcesReloadedEvent.patch b/patches/api/0254-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from patches/api/0253-Added-ServerResourcesReloadedEvent.patch rename to patches/api/0254-Added-ServerResourcesReloadedEvent.patch diff --git a/patches/api/0254-Add-BlockFailedDispenseEvent.patch b/patches/api/0255-Add-BlockFailedDispenseEvent.patch similarity index 100% rename from patches/api/0254-Add-BlockFailedDispenseEvent.patch rename to patches/api/0255-Add-BlockFailedDispenseEvent.patch diff --git a/patches/api/0255-Added-PlayerLecternPageChangeEvent.patch b/patches/api/0256-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from patches/api/0255-Added-PlayerLecternPageChangeEvent.patch rename to patches/api/0256-Added-PlayerLecternPageChangeEvent.patch diff --git a/patches/api/0256-Added-PlayerLoomPatternSelectEvent.patch b/patches/api/0257-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from patches/api/0256-Added-PlayerLoomPatternSelectEvent.patch rename to patches/api/0257-Added-PlayerLoomPatternSelectEvent.patch diff --git a/patches/api/0257-Better-AnnotationTest-printout.patch b/patches/api/0258-Better-AnnotationTest-printout.patch similarity index 100% rename from patches/api/0257-Better-AnnotationTest-printout.patch rename to patches/api/0258-Better-AnnotationTest-printout.patch diff --git a/patches/api/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch b/patches/api/0259-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch similarity index 100% rename from patches/api/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch rename to patches/api/0259-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch diff --git a/patches/api/0259-Add-sendOpLevel-API.patch b/patches/api/0260-Add-sendOpLevel-API.patch similarity index 100% rename from patches/api/0259-Add-sendOpLevel-API.patch rename to patches/api/0260-Add-sendOpLevel-API.patch diff --git a/patches/api/0260-Add-StructureLocateEvent.patch b/patches/api/0261-Add-StructureLocateEvent.patch similarity index 100% rename from patches/api/0260-Add-StructureLocateEvent.patch rename to patches/api/0261-Add-StructureLocateEvent.patch diff --git a/patches/api/0261-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/api/0262-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from patches/api/0261-Return-chat-component-with-empty-text-instead-of-thr.patch rename to patches/api/0262-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/patches/api/0262-Add-BlockPreDispenseEvent.patch b/patches/api/0263-Add-BlockPreDispenseEvent.patch similarity index 100% rename from patches/api/0262-Add-BlockPreDispenseEvent.patch rename to patches/api/0263-Add-BlockPreDispenseEvent.patch diff --git a/patches/api/0263-Added-Vanilla-Entity-Tags.patch b/patches/api/0264-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from patches/api/0263-Added-Vanilla-Entity-Tags.patch rename to patches/api/0264-Added-Vanilla-Entity-Tags.patch diff --git a/patches/api/0264-added-Wither-API.patch b/patches/api/0265-added-Wither-API.patch similarity index 100% rename from patches/api/0264-added-Wither-API.patch rename to patches/api/0265-added-Wither-API.patch diff --git a/patches/api/0265-Added-PlayerChangeBeaconEffectEvent.patch b/patches/api/0266-Added-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from patches/api/0265-Added-PlayerChangeBeaconEffectEvent.patch rename to patches/api/0266-Added-PlayerChangeBeaconEffectEvent.patch diff --git a/patches/api/0266-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/api/0267-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from patches/api/0266-Added-PlayerStonecutterRecipeSelectEvent.patch rename to patches/api/0267-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/patches/api/0267-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/api/0268-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from patches/api/0267-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/api/0268-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/patches/api/0268-EntityMoveEvent.patch b/patches/api/0269-EntityMoveEvent.patch similarity index 100% rename from patches/api/0268-EntityMoveEvent.patch rename to patches/api/0269-EntityMoveEvent.patch diff --git a/patches/api/0269-add-DragonEggFormEvent.patch b/patches/api/0270-add-DragonEggFormEvent.patch similarity index 100% rename from patches/api/0269-add-DragonEggFormEvent.patch rename to patches/api/0270-add-DragonEggFormEvent.patch diff --git a/patches/api/0270-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/api/0271-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from patches/api/0270-Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/api/0271-Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/patches/api/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/api/0272-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from patches/api/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/api/0272-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/patches/api/0272-living-entity-allow-attribute-registration.patch b/patches/api/0273-living-entity-allow-attribute-registration.patch similarity index 100% rename from patches/api/0272-living-entity-allow-attribute-registration.patch rename to patches/api/0273-living-entity-allow-attribute-registration.patch diff --git a/patches/api/0273-Add-missing-effects.patch b/patches/api/0274-Add-missing-effects.patch similarity index 100% rename from patches/api/0273-Add-missing-effects.patch rename to patches/api/0274-Add-missing-effects.patch diff --git a/patches/api/0274-Expose-Tracked-Players.patch b/patches/api/0275-Expose-Tracked-Players.patch similarity index 100% rename from patches/api/0274-Expose-Tracked-Players.patch rename to patches/api/0275-Expose-Tracked-Players.patch diff --git a/patches/api/0275-Cache-the-result-of-Material-isBlock.patch b/patches/api/0276-Cache-the-result-of-Material-isBlock.patch similarity index 100% rename from patches/api/0275-Cache-the-result-of-Material-isBlock.patch rename to patches/api/0276-Cache-the-result-of-Material-isBlock.patch diff --git a/patches/api/0276-Add-worldborder-events.patch b/patches/api/0277-Add-worldborder-events.patch similarity index 100% rename from patches/api/0276-Add-worldborder-events.patch rename to patches/api/0277-Add-worldborder-events.patch diff --git a/patches/api/0277-added-PlayerNameEntityEvent.patch b/patches/api/0278-added-PlayerNameEntityEvent.patch similarity index 100% rename from patches/api/0277-added-PlayerNameEntityEvent.patch rename to patches/api/0278-added-PlayerNameEntityEvent.patch diff --git a/patches/api/0278-Add-recipe-to-cook-events.patch b/patches/api/0279-Add-recipe-to-cook-events.patch similarity index 100% rename from patches/api/0278-Add-recipe-to-cook-events.patch rename to patches/api/0279-Add-recipe-to-cook-events.patch diff --git a/patches/api/0279-Add-Block-isValidTool.patch b/patches/api/0280-Add-Block-isValidTool.patch similarity index 100% rename from patches/api/0279-Add-Block-isValidTool.patch rename to patches/api/0280-Add-Block-isValidTool.patch diff --git a/patches/api/0280-Implement-Keyed-on-World.patch b/patches/api/0281-Implement-Keyed-on-World.patch similarity index 100% rename from patches/api/0280-Implement-Keyed-on-World.patch rename to patches/api/0281-Implement-Keyed-on-World.patch diff --git a/patches/api/0281-fix-Inventory-getContents-null-annotations.patch b/patches/api/0282-fix-Inventory-getContents-null-annotations.patch similarity index 100% rename from patches/api/0281-fix-Inventory-getContents-null-annotations.patch rename to patches/api/0282-fix-Inventory-getContents-null-annotations.patch diff --git a/patches/api/0282-Item-Rarity-API.patch b/patches/api/0283-Item-Rarity-API.patch similarity index 100% rename from patches/api/0282-Item-Rarity-API.patch rename to patches/api/0283-Item-Rarity-API.patch diff --git a/patches/api/0283-Expose-protocol-version.patch b/patches/api/0284-Expose-protocol-version.patch similarity index 100% rename from patches/api/0283-Expose-protocol-version.patch rename to patches/api/0284-Expose-protocol-version.patch diff --git a/patches/api/0284-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/api/0285-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 100% rename from patches/api/0284-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to patches/api/0285-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch diff --git a/patches/api/0285-add-isDeeplySleeping-to-HumanEntity.patch b/patches/api/0286-add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from patches/api/0285-add-isDeeplySleeping-to-HumanEntity.patch rename to patches/api/0286-add-isDeeplySleeping-to-HumanEntity.patch diff --git a/patches/api/0286-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/api/0287-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from patches/api/0286-add-consumeFuel-to-FurnaceBurnEvent.patch rename to patches/api/0287-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/patches/api/0287-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/api/0288-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from patches/api/0287-add-get-set-drop-chance-to-EntityEquipment.patch rename to patches/api/0288-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/patches/api/0288-Added-PlayerDeepSleepEvent.patch b/patches/api/0289-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from patches/api/0288-Added-PlayerDeepSleepEvent.patch rename to patches/api/0289-Added-PlayerDeepSleepEvent.patch diff --git a/patches/api/0289-More-World-API.patch b/patches/api/0290-More-World-API.patch similarity index 100% rename from patches/api/0289-More-World-API.patch rename to patches/api/0290-More-World-API.patch diff --git a/patches/api/0290-Added-PlayerBedFailEnterEvent.patch b/patches/api/0291-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from patches/api/0290-Added-PlayerBedFailEnterEvent.patch rename to patches/api/0291-Added-PlayerBedFailEnterEvent.patch diff --git a/patches/api/0291-Introduce-beacon-activation-deactivation-events.patch b/patches/api/0292-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from patches/api/0291-Introduce-beacon-activation-deactivation-events.patch rename to patches/api/0292-Introduce-beacon-activation-deactivation-events.patch diff --git a/patches/api/0292-PlayerMoveEvent-Improvements.patch b/patches/api/0293-PlayerMoveEvent-Improvements.patch similarity index 100% rename from patches/api/0292-PlayerMoveEvent-Improvements.patch rename to patches/api/0293-PlayerMoveEvent-Improvements.patch diff --git a/patches/api/0293-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/api/0294-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from patches/api/0293-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/api/0294-add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/patches/api/0294-Add-more-WanderingTrader-API.patch b/patches/api/0295-Add-more-WanderingTrader-API.patch similarity index 100% rename from patches/api/0294-Add-more-WanderingTrader-API.patch rename to patches/api/0295-Add-more-WanderingTrader-API.patch diff --git a/patches/api/0295-Add-EntityBlockStorage-clearEntities.patch b/patches/api/0296-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from patches/api/0295-Add-EntityBlockStorage-clearEntities.patch rename to patches/api/0296-Add-EntityBlockStorage-clearEntities.patch diff --git a/patches/api/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/api/0297-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from patches/api/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to patches/api/0297-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/patches/api/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/api/0298-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from patches/api/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/api/0298-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/patches/api/0298-Inventory-close.patch b/patches/api/0299-Inventory-close.patch similarity index 100% rename from patches/api/0298-Inventory-close.patch rename to patches/api/0299-Inventory-close.patch diff --git a/patches/api/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/api/0300-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 100% rename from patches/api/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/api/0300-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch diff --git a/patches/api/0300-Add-basic-Datapack-API.patch b/patches/api/0301-Add-basic-Datapack-API.patch similarity index 100% rename from patches/api/0300-Add-basic-Datapack-API.patch rename to patches/api/0301-Add-basic-Datapack-API.patch diff --git a/patches/api/0301-additions-to-PlayerGameModeChangeEvent.patch b/patches/api/0302-additions-to-PlayerGameModeChangeEvent.patch similarity index 100% rename from patches/api/0301-additions-to-PlayerGameModeChangeEvent.patch rename to patches/api/0302-additions-to-PlayerGameModeChangeEvent.patch diff --git a/patches/api/0302-ItemStack-repair-check-API.patch b/patches/api/0303-ItemStack-repair-check-API.patch similarity index 100% rename from patches/api/0302-ItemStack-repair-check-API.patch rename to patches/api/0303-ItemStack-repair-check-API.patch diff --git a/patches/api/0303-More-Enchantment-API.patch b/patches/api/0304-More-Enchantment-API.patch similarity index 100% rename from patches/api/0303-More-Enchantment-API.patch rename to patches/api/0304-More-Enchantment-API.patch diff --git a/patches/api/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/api/0305-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 100% rename from patches/api/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to patches/api/0305-Add-command-line-option-to-load-extra-plugin-jars-no.patch diff --git a/patches/api/0305-List-all-missing-hard-depends-not-just-first.patch b/patches/api/0306-List-all-missing-hard-depends-not-just-first.patch similarity index 100% rename from patches/api/0305-List-all-missing-hard-depends-not-just-first.patch rename to patches/api/0306-List-all-missing-hard-depends-not-just-first.patch diff --git a/patches/api/0306-Add-Mob-lookAt-API.patch b/patches/api/0307-Add-Mob-lookAt-API.patch similarity index 100% rename from patches/api/0306-Add-Mob-lookAt-API.patch rename to patches/api/0307-Add-Mob-lookAt-API.patch diff --git a/patches/api/0307-ItemStack-editMeta.patch b/patches/api/0308-ItemStack-editMeta.patch similarity index 100% rename from patches/api/0307-ItemStack-editMeta.patch rename to patches/api/0308-ItemStack-editMeta.patch diff --git a/patches/api/0308-Add-EntityInsideBlockEvent.patch b/patches/api/0309-Add-EntityInsideBlockEvent.patch similarity index 100% rename from patches/api/0308-Add-EntityInsideBlockEvent.patch rename to patches/api/0309-Add-EntityInsideBlockEvent.patch diff --git a/patches/api/0309-Attributes-API-for-item-defaults.patch b/patches/api/0310-Attributes-API-for-item-defaults.patch similarity index 100% rename from patches/api/0309-Attributes-API-for-item-defaults.patch rename to patches/api/0310-Attributes-API-for-item-defaults.patch diff --git a/patches/api/0310-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/api/0311-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from patches/api/0310-Add-cause-to-Weather-ThunderChangeEvents.patch rename to patches/api/0311-Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/patches/api/0311-More-Lidded-Block-API.patch b/patches/api/0312-More-Lidded-Block-API.patch similarity index 100% rename from patches/api/0311-More-Lidded-Block-API.patch rename to patches/api/0312-More-Lidded-Block-API.patch diff --git a/patches/api/0312-Add-PlayerKickEvent-causes.patch b/patches/api/0313-Add-PlayerKickEvent-causes.patch similarity index 100% rename from patches/api/0312-Add-PlayerKickEvent-causes.patch rename to patches/api/0313-Add-PlayerKickEvent-causes.patch diff --git a/patches/api/0312-Add-PufferFishStateChangeEvent.patch b/patches/api/0314-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from patches/api/0312-Add-PufferFishStateChangeEvent.patch rename to patches/api/0314-Add-PufferFishStateChangeEvent.patch diff --git a/patches/api/0314-Add-BellRevealRaiderEvent.patch b/patches/api/0315-Add-BellRevealRaiderEvent.patch similarity index 100% rename from patches/api/0314-Add-BellRevealRaiderEvent.patch rename to patches/api/0315-Add-BellRevealRaiderEvent.patch diff --git a/patches/api/0315-Add-ElderGuardianAppearanceEvent.patch b/patches/api/0316-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from patches/api/0315-Add-ElderGuardianAppearanceEvent.patch rename to patches/api/0316-Add-ElderGuardianAppearanceEvent.patch diff --git a/patches/api/0316-Add-more-line-of-sight-methods.patch b/patches/api/0317-Add-more-line-of-sight-methods.patch similarity index 100% rename from patches/api/0316-Add-more-line-of-sight-methods.patch rename to patches/api/0317-Add-more-line-of-sight-methods.patch diff --git a/patches/server/0290-PreSpawnerSpawnEvent.patch b/patches/server/0291-PreSpawnerSpawnEvent.patch similarity index 94% rename from patches/server/0290-PreSpawnerSpawnEvent.patch rename to patches/server/0291-PreSpawnerSpawnEvent.patch index fd48f263be..7a1e9d1d4c 100644 --- a/patches/server/0290-PreSpawnerSpawnEvent.patch +++ b/patches/server/0291-PreSpawnerSpawnEvent.patch @@ -9,7 +9,7 @@ SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for spawners. diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index c741f8e4a4b67d1bfed2d1bac36856c5688bb161..9228c0bc797fb95c8ac949bdc568eadafee84a80 100644 +index cfb820636f819a7da56d0302d49f39cea1b5a93d..7bf688057d684aa1b60f29294c9a7e81ab6742d1 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java @@ -138,11 +138,11 @@ public abstract class BaseSpawner { diff --git a/patches/server/0291-Don-t-allow-digging-into-unloaded-chunks.patch b/patches/server/0292-Don-t-allow-digging-into-unloaded-chunks.patch similarity index 97% rename from patches/server/0291-Don-t-allow-digging-into-unloaded-chunks.patch rename to patches/server/0292-Don-t-allow-digging-into-unloaded-chunks.patch index c74abe7bd4..6a1a7e75bd 100644 --- a/patches/server/0291-Don-t-allow-digging-into-unloaded-chunks.patch +++ b/patches/server/0292-Don-t-allow-digging-into-unloaded-chunks.patch @@ -51,7 +51,7 @@ index 315dad4789f5f2582ee9b4fc176affd1f57537ef..f4a056185990181e486f452960159a52 this.level.destroyBlockProgress(this.player.getId(), pos, -1); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 5f4718fa42be0ade1a40c0472efbbd0c65f061a7..8b716c625c363d7143fe6fbc26d3d674d62a5833 100644 +index cdcfc4390eca3dbb3395c29f300acce661a5e494..674d83f05246f7c6c9c9e1674c9428cfe0322cda 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1558,6 +1558,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0292-Make-the-default-permission-message-configurable.patch b/patches/server/0293-Make-the-default-permission-message-configurable.patch similarity index 100% rename from patches/server/0292-Make-the-default-permission-message-configurable.patch rename to patches/server/0293-Make-the-default-permission-message-configurable.patch diff --git a/patches/server/0293-Prevent-rayTrace-from-loading-chunks.patch b/patches/server/0294-Prevent-rayTrace-from-loading-chunks.patch similarity index 100% rename from patches/server/0293-Prevent-rayTrace-from-loading-chunks.patch rename to patches/server/0294-Prevent-rayTrace-from-loading-chunks.patch diff --git a/patches/server/0294-Handle-Large-Packets-disconnecting-client.patch b/patches/server/0295-Handle-Large-Packets-disconnecting-client.patch similarity index 100% rename from patches/server/0294-Handle-Large-Packets-disconnecting-client.patch rename to patches/server/0295-Handle-Large-Packets-disconnecting-client.patch diff --git a/patches/server/0295-force-entity-dismount-during-teleportation.patch b/patches/server/0296-force-entity-dismount-during-teleportation.patch similarity index 97% rename from patches/server/0295-force-entity-dismount-during-teleportation.patch rename to patches/server/0296-force-entity-dismount-during-teleportation.patch index 73280109bd..a19c63855c 100644 --- a/patches/server/0295-force-entity-dismount-during-teleportation.patch +++ b/patches/server/0296-force-entity-dismount-during-teleportation.patch @@ -20,7 +20,7 @@ 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 5eb37fb1ae861940839fe6815b57111812d6b3ec..963a3c159e912a39b98dfcb3fdb8c384765990d7 100644 +index 13dace1a8fcde011d26d37049ae3ca14d86990fc..8e86ca5221236ab3ab61d7a6859b64be9e5d8f97 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1299,11 +1299,13 @@ public class ServerPlayer extends Player { @@ -41,7 +41,7 @@ index 5eb37fb1ae861940839fe6815b57111812d6b3ec..963a3c159e912a39b98dfcb3fdb8c384 if (entity1 != entity && this.connection != null) { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f9f51b84036f522cdfc4ca6d47c074d51c14bf08..fcfee0f2b2b073b0c642684fddfb8d3c4eacf4f9 100644 +index d92a54022478eac52abf035aee89d91acf29c874..7b7c554ab22cee655d19eed793f45706f0311234 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -2214,12 +2214,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0296-Add-more-Zombie-API.patch b/patches/server/0297-Add-more-Zombie-API.patch similarity index 100% rename from patches/server/0296-Add-more-Zombie-API.patch rename to patches/server/0297-Add-more-Zombie-API.patch diff --git a/patches/server/0297-Book-Size-Limits.patch b/patches/server/0298-Book-Size-Limits.patch similarity index 97% rename from patches/server/0297-Book-Size-Limits.patch rename to patches/server/0298-Book-Size-Limits.patch index 0ac81c635d..56321d1d60 100644 --- a/patches/server/0297-Book-Size-Limits.patch +++ b/patches/server/0298-Book-Size-Limits.patch @@ -24,7 +24,7 @@ index 11d628869a9a6eda8bf21a4f213ff23ad753b18e..8bf4d2b8c38c02d6a5b2fea37113689a private static void asyncChunks() { ConfigurationSection section; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 8b716c625c363d7143fe6fbc26d3d674d62a5833..f1a8470d0b314c8fa5eade198cffc1f8cd5e6832 100644 +index 674d83f05246f7c6c9c9e1674c9428cfe0322cda..6f657c8b3a147fbd4cf625e89cb6023ee2967c07 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1002,6 +1002,52 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0298-Add-PlayerConnectionCloseEvent.patch b/patches/server/0299-Add-PlayerConnectionCloseEvent.patch similarity index 100% rename from patches/server/0298-Add-PlayerConnectionCloseEvent.patch rename to patches/server/0299-Add-PlayerConnectionCloseEvent.patch diff --git a/patches/server/0299-Prevent-Enderman-from-loading-chunks.patch b/patches/server/0300-Prevent-Enderman-from-loading-chunks.patch similarity index 100% rename from patches/server/0299-Prevent-Enderman-from-loading-chunks.patch rename to patches/server/0300-Prevent-Enderman-from-loading-chunks.patch diff --git a/patches/server/0300-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/patches/server/0301-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 98% rename from patches/server/0300-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to patches/server/0301-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch index 0cd88c9770..1dfa1b892c 100644 --- a/patches/server/0300-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch +++ b/patches/server/0301-Add-APIs-to-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 963a3c159e912a39b98dfcb3fdb8c384765990d7..44da4efc23a3273449431845308ba889615ac425 100644 +index 8e86ca5221236ab3ab61d7a6859b64be9e5d8f97..091d4fa14d286ad4777750fff2b315335e46e379 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -218,6 +218,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0301-Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/patches/server/0302-Workaround-for-vehicle-tracking-issue-on-disconnect.patch similarity index 91% rename from patches/server/0301-Workaround-for-vehicle-tracking-issue-on-disconnect.patch rename to patches/server/0302-Workaround-for-vehicle-tracking-issue-on-disconnect.patch index f822adc555..45a56c914a 100644 --- a/patches/server/0301-Workaround-for-vehicle-tracking-issue-on-disconnect.patch +++ b/patches/server/0302-Workaround-for-vehicle-tracking-issue-on-disconnect.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Workaround for vehicle tracking issue on disconnect diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 44da4efc23a3273449431845308ba889615ac425..955a7fcd80a57f920e402a5533f5029b9683104c 100644 +index 091d4fa14d286ad4777750fff2b315335e46e379..8f558fac783783c27c89b3b64a8d1feaa1c82d46 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1538,6 +1538,13 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0302-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/patches/server/0303-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch similarity index 100% rename from patches/server/0302-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch rename to patches/server/0303-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch diff --git a/patches/server/0303-Block-Entity-remove-from-being-called-on-Players.patch b/patches/server/0304-Block-Entity-remove-from-being-called-on-Players.patch similarity index 100% rename from patches/server/0303-Block-Entity-remove-from-being-called-on-Players.patch rename to patches/server/0304-Block-Entity-remove-from-being-called-on-Players.patch diff --git a/patches/server/0304-BlockDestroyEvent.patch b/patches/server/0305-BlockDestroyEvent.patch similarity index 100% rename from patches/server/0304-BlockDestroyEvent.patch rename to patches/server/0305-BlockDestroyEvent.patch diff --git a/patches/server/0305-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/patches/server/0306-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch similarity index 100% rename from patches/server/0305-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch rename to patches/server/0306-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch diff --git a/patches/server/0306-Limit-Client-Sign-length-more.patch b/patches/server/0307-Limit-Client-Sign-length-more.patch similarity index 97% rename from patches/server/0306-Limit-Client-Sign-length-more.patch rename to patches/server/0307-Limit-Client-Sign-length-more.patch index 877afd37b9..eb442a11dd 100644 --- a/patches/server/0306-Limit-Client-Sign-length-more.patch +++ b/patches/server/0307-Limit-Client-Sign-length-more.patch @@ -22,7 +22,7 @@ it only impacts data sent from the client. Set -DPaper.maxSignLength=XX to change limit or -1 to disable diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index f1a8470d0b314c8fa5eade198cffc1f8cd5e6832..defebf7b45e4f006fa7e575b5dbd01ac1e231d5a 100644 +index 6f657c8b3a147fbd4cf625e89cb6023ee2967c07..d8312d29103dd10f2b0634de5a056774d06d3263 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -255,6 +255,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0307-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/patches/server/0308-Don-t-check-ConvertSigns-boolean-every-sign-save.patch similarity index 100% rename from patches/server/0307-Don-t-check-ConvertSigns-boolean-every-sign-save.patch rename to patches/server/0308-Don-t-check-ConvertSigns-boolean-every-sign-save.patch diff --git a/patches/server/0308-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server/0309-Optimize-Network-Manager-and-add-advanced-packet-sup.patch similarity index 100% rename from patches/server/0308-Optimize-Network-Manager-and-add-advanced-packet-sup.patch rename to patches/server/0309-Optimize-Network-Manager-and-add-advanced-packet-sup.patch diff --git a/patches/server/0309-Handle-Oversized-Tile-Entities-in-chunks.patch b/patches/server/0310-Handle-Oversized-Tile-Entities-in-chunks.patch similarity index 100% rename from patches/server/0309-Handle-Oversized-Tile-Entities-in-chunks.patch rename to patches/server/0310-Handle-Oversized-Tile-Entities-in-chunks.patch diff --git a/patches/server/0310-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/patches/server/0311-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch similarity index 100% rename from patches/server/0310-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch rename to patches/server/0311-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch diff --git a/patches/server/0311-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/patches/server/0312-Set-Zombie-last-tick-at-start-of-drowning-process.patch similarity index 100% rename from patches/server/0311-Set-Zombie-last-tick-at-start-of-drowning-process.patch rename to patches/server/0312-Set-Zombie-last-tick-at-start-of-drowning-process.patch diff --git a/patches/server/0312-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/patches/server/0313-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch similarity index 100% rename from patches/server/0312-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch rename to patches/server/0313-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch diff --git a/patches/server/0313-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/patches/server/0314-Use-proper-max-length-when-serialising-BungeeCord-te.patch similarity index 100% rename from patches/server/0313-Use-proper-max-length-when-serialising-BungeeCord-te.patch rename to patches/server/0314-Use-proper-max-length-when-serialising-BungeeCord-te.patch diff --git a/patches/server/0314-Entity-getEntitySpawnReason.patch b/patches/server/0315-Entity-getEntitySpawnReason.patch similarity index 97% rename from patches/server/0314-Entity-getEntitySpawnReason.patch rename to patches/server/0315-Entity-getEntitySpawnReason.patch index 33f056c7fe..a034031ada 100644 --- a/patches/server/0314-Entity-getEntitySpawnReason.patch +++ b/patches/server/0315-Entity-getEntitySpawnReason.patch @@ -35,7 +35,7 @@ index ea336bdf2f15aabe74de82ef6c29b93573254e31..da3100d6577166e222164c174b280205 }); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index fcfee0f2b2b073b0c642684fddfb8d3c4eacf4f9..47503fa2feabf6615f250d13f25f080d19c2f560 100644 +index 7b7c554ab22cee655d19eed793f45706f0311234..434618dcb3d4261eb1db20b8f0807c9aba6b8332 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -67,6 +67,8 @@ import net.minecraft.world.InteractionHand; @@ -93,7 +93,7 @@ index fcfee0f2b2b073b0c642684fddfb8d3c4eacf4f9..47503fa2feabf6615f250d13f25f080d } catch (Throwable throwable) { diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index cfb820636f819a7da56d0302d49f39cea1b5a93d..9a8af1867315840518533381e594fc50542cd72d 100644 +index 7bf688057d684aa1b60f29294c9a7e81ab6742d1..66ae43c40d4bad373b3a5269e8c78d7a3b3ac498 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java @@ -188,6 +188,7 @@ public abstract class BaseSpawner { diff --git a/patches/server/0315-Update-entity-Metadata-for-all-tracked-players.patch b/patches/server/0316-Update-entity-Metadata-for-all-tracked-players.patch similarity index 96% rename from patches/server/0315-Update-entity-Metadata-for-all-tracked-players.patch rename to patches/server/0316-Update-entity-Metadata-for-all-tracked-players.patch index 8804fcd546..4b63ab1667 100644 --- a/patches/server/0315-Update-entity-Metadata-for-all-tracked-players.patch +++ b/patches/server/0316-Update-entity-Metadata-for-all-tracked-players.patch @@ -22,7 +22,7 @@ index ad9bbda31a4cdb306ca40f2b99e4b815c4f136bd..28afe2f238ded241acf77c3272a44068 this.broadcast.accept(packet); if (this.entity instanceof ServerPlayer) { diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index defebf7b45e4f006fa7e575b5dbd01ac1e231d5a..6c4266d847b1181a055fa425d5734032dadabf93 100644 +index d8312d29103dd10f2b0634de5a056774d06d3263..8b76ac2e7462cf56c2d5019d12f7e839bfbc8b1e 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -2289,7 +2289,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0316-Fire-event-on-GS4-query.patch b/patches/server/0317-Fire-event-on-GS4-query.patch similarity index 100% rename from patches/server/0316-Fire-event-on-GS4-query.patch rename to patches/server/0317-Fire-event-on-GS4-query.patch diff --git a/patches/server/0317-Implement-PlayerPostRespawnEvent.patch b/patches/server/0318-Implement-PlayerPostRespawnEvent.patch similarity index 100% rename from patches/server/0317-Implement-PlayerPostRespawnEvent.patch rename to patches/server/0318-Implement-PlayerPostRespawnEvent.patch diff --git a/patches/server/0318-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/patches/server/0319-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch similarity index 100% rename from patches/server/0318-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch rename to patches/server/0319-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch diff --git a/patches/server/0319-Server-Tick-Events.patch b/patches/server/0320-Server-Tick-Events.patch similarity index 100% rename from patches/server/0319-Server-Tick-Events.patch rename to patches/server/0320-Server-Tick-Events.patch diff --git a/patches/server/0320-PlayerDeathEvent-getItemsToKeep.patch b/patches/server/0321-PlayerDeathEvent-getItemsToKeep.patch similarity index 96% rename from patches/server/0320-PlayerDeathEvent-getItemsToKeep.patch rename to patches/server/0321-PlayerDeathEvent-getItemsToKeep.patch index 86899d6318..6c015bede7 100644 --- a/patches/server/0320-PlayerDeathEvent-getItemsToKeep.patch +++ b/patches/server/0321-PlayerDeathEvent-getItemsToKeep.patch @@ -8,7 +8,7 @@ Exposes a mutable array on items a player should keep on death Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4 diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 955a7fcd80a57f920e402a5533f5029b9683104c..679f1e3ef4c19ab466cf2d06c47b1018aabaa7bf 100644 +index 8f558fac783783c27c89b3b64a8d1feaa1c82d46..62a43f3e6f27245a0baec7ff703ec023dd4e5e05 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -729,6 +729,46 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0321-Optimize-Captured-TileEntity-Lookup.patch b/patches/server/0322-Optimize-Captured-TileEntity-Lookup.patch similarity index 100% rename from patches/server/0321-Optimize-Captured-TileEntity-Lookup.patch rename to patches/server/0322-Optimize-Captured-TileEntity-Lookup.patch diff --git a/patches/server/0322-Add-Heightmap-API.patch b/patches/server/0323-Add-Heightmap-API.patch similarity index 100% rename from patches/server/0322-Add-Heightmap-API.patch rename to patches/server/0323-Add-Heightmap-API.patch diff --git a/patches/server/0323-Mob-Spawner-API-Enhancements.patch b/patches/server/0324-Mob-Spawner-API-Enhancements.patch similarity index 98% rename from patches/server/0323-Mob-Spawner-API-Enhancements.patch rename to patches/server/0324-Mob-Spawner-API-Enhancements.patch index c19c118528..60d952f8ba 100644 --- a/patches/server/0323-Mob-Spawner-API-Enhancements.patch +++ b/patches/server/0324-Mob-Spawner-API-Enhancements.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Mob Spawner API Enhancements diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 9a8af1867315840518533381e594fc50542cd72d..68ce2732dfdc25ddadc15c43c30a609f9b1eba86 100644 +index 66ae43c40d4bad373b3a5269e8c78d7a3b3ac498..a87531f4669c7947e02764b5ceb098385ad99159 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java @@ -31,7 +31,7 @@ public abstract class BaseSpawner { diff --git a/patches/server/0324-Fix-CB-call-to-changed-postToMainThread-method.patch b/patches/server/0325-Fix-CB-call-to-changed-postToMainThread-method.patch similarity index 91% rename from patches/server/0324-Fix-CB-call-to-changed-postToMainThread-method.patch rename to patches/server/0325-Fix-CB-call-to-changed-postToMainThread-method.patch index 90c34e0572..260247a1e4 100644 --- a/patches/server/0324-Fix-CB-call-to-changed-postToMainThread-method.patch +++ b/patches/server/0325-Fix-CB-call-to-changed-postToMainThread-method.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix CB call to changed postToMainThread method diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 6c4266d847b1181a055fa425d5734032dadabf93..377e224acb06bfd5f769b5f75b7f52129394b494 100644 +index 8b76ac2e7462cf56c2d5019d12f7e839bfbc8b1e..fc7776e081a76d52e5890ba05f750944e5a1d402 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -440,7 +440,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0325-Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/patches/server/0326-Fix-sounds-when-item-frames-are-modified-MC-123450.patch similarity index 100% rename from patches/server/0325-Fix-sounds-when-item-frames-are-modified-MC-123450.patch rename to patches/server/0326-Fix-sounds-when-item-frames-are-modified-MC-123450.patch diff --git a/patches/server/0326-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/patches/server/0327-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch similarity index 100% rename from patches/server/0326-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch rename to patches/server/0327-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch diff --git a/patches/server/0327-improve-CraftWorld-isChunkLoaded.patch b/patches/server/0328-improve-CraftWorld-isChunkLoaded.patch similarity index 100% rename from patches/server/0327-improve-CraftWorld-isChunkLoaded.patch rename to patches/server/0328-improve-CraftWorld-isChunkLoaded.patch diff --git a/patches/server/0328-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch similarity index 100% rename from patches/server/0328-Configurable-Keep-Spawn-Loaded-range-per-world.patch rename to patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch diff --git a/patches/server/0329-ChunkMapDistance-CME.patch b/patches/server/0330-ChunkMapDistance-CME.patch similarity index 100% rename from patches/server/0329-ChunkMapDistance-CME.patch rename to patches/server/0330-ChunkMapDistance-CME.patch diff --git a/patches/server/0330-Implement-CraftBlockSoundGroup.patch b/patches/server/0331-Implement-CraftBlockSoundGroup.patch similarity index 100% rename from patches/server/0330-Implement-CraftBlockSoundGroup.patch rename to patches/server/0331-Implement-CraftBlockSoundGroup.patch diff --git a/patches/server/0331-Chunk-debug-command.patch b/patches/server/0332-Chunk-debug-command.patch similarity index 100% rename from patches/server/0331-Chunk-debug-command.patch rename to patches/server/0332-Chunk-debug-command.patch diff --git a/patches/server/0332-Fix-World-isChunkGenerated-calls.patch b/patches/server/0333-Fix-World-isChunkGenerated-calls.patch similarity index 100% rename from patches/server/0332-Fix-World-isChunkGenerated-calls.patch rename to patches/server/0333-Fix-World-isChunkGenerated-calls.patch diff --git a/patches/server/0333-Show-blockstate-location-if-we-failed-to-read-it.patch b/patches/server/0334-Show-blockstate-location-if-we-failed-to-read-it.patch similarity index 100% rename from patches/server/0333-Show-blockstate-location-if-we-failed-to-read-it.patch rename to patches/server/0334-Show-blockstate-location-if-we-failed-to-read-it.patch diff --git a/patches/server/0334-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/patches/server/0335-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch similarity index 100% rename from patches/server/0334-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch rename to patches/server/0335-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch diff --git a/patches/server/0335-Configurable-projectile-relative-velocity.patch b/patches/server/0336-Configurable-projectile-relative-velocity.patch similarity index 100% rename from patches/server/0335-Configurable-projectile-relative-velocity.patch rename to patches/server/0336-Configurable-projectile-relative-velocity.patch diff --git a/patches/server/0336-offset-item-frame-ticking.patch b/patches/server/0337-offset-item-frame-ticking.patch similarity index 100% rename from patches/server/0336-offset-item-frame-ticking.patch rename to patches/server/0337-offset-item-frame-ticking.patch diff --git a/patches/server/0337-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/patches/server/0338-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch similarity index 100% rename from patches/server/0337-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch rename to patches/server/0338-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch diff --git a/patches/server/0338-Fix-MC-158900.patch b/patches/server/0339-Fix-MC-158900.patch similarity index 100% rename from patches/server/0338-Fix-MC-158900.patch rename to patches/server/0339-Fix-MC-158900.patch diff --git a/patches/server/0339-Prevent-consuming-the-wrong-itemstack.patch b/patches/server/0340-Prevent-consuming-the-wrong-itemstack.patch similarity index 100% rename from patches/server/0339-Prevent-consuming-the-wrong-itemstack.patch rename to patches/server/0340-Prevent-consuming-the-wrong-itemstack.patch diff --git a/patches/server/0340-Generator-Settings.patch b/patches/server/0341-Generator-Settings.patch similarity index 100% rename from patches/server/0340-Generator-Settings.patch rename to patches/server/0341-Generator-Settings.patch diff --git a/patches/server/0341-Fix-MC-161754.patch b/patches/server/0342-Fix-MC-161754.patch similarity index 100% rename from patches/server/0341-Fix-MC-161754.patch rename to patches/server/0342-Fix-MC-161754.patch diff --git a/patches/server/0342-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/patches/server/0343-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch similarity index 100% rename from patches/server/0342-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch rename to patches/server/0343-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch diff --git a/patches/server/0343-Expose-the-internal-current-tick.patch b/patches/server/0344-Expose-the-internal-current-tick.patch similarity index 100% rename from patches/server/0343-Expose-the-internal-current-tick.patch rename to patches/server/0344-Expose-the-internal-current-tick.patch diff --git a/patches/server/0344-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/patches/server/0345-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch similarity index 94% rename from patches/server/0344-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch rename to patches/server/0345-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch index 559cc6317a..a87c2ad2b5 100644 --- a/patches/server/0344-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch +++ b/patches/server/0345-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix stuck in sneak when changing worlds (MC-10657) diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 679f1e3ef4c19ab466cf2d06c47b1018aabaa7bf..8da35a7dde494b059e542d049d7ee039deb5833d 100644 +index 62a43f3e6f27245a0baec7ff703ec023dd4e5e05..6086f86e6fd0395553aef42df4aef6a117231896 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1101,6 +1101,8 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0345-Add-option-to-disable-pillager-patrols.patch b/patches/server/0346-Add-option-to-disable-pillager-patrols.patch similarity index 100% rename from patches/server/0345-Add-option-to-disable-pillager-patrols.patch rename to patches/server/0346-Add-option-to-disable-pillager-patrols.patch diff --git a/patches/server/0346-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/patches/server/0347-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch similarity index 92% rename from patches/server/0346-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch rename to patches/server/0347-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch index fcb6434230..55d9df04d9 100644 --- a/patches/server/0346-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch +++ b/patches/server/0347-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch @@ -7,7 +7,7 @@ Fixes an AssertionError when setting the player's item in hand to null or a new Fixes GH-2718 diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 377e224acb06bfd5f769b5f75b7f52129394b494..9240064a17e7ac2492fe157b759d1f724105cd0e 100644 +index fc7776e081a76d52e5890ba05f750944e5a1d402..9c5eba2cbd7399c8e3f8c5c3dad228ded6d57832 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1741,6 +1741,10 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0347-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/patches/server/0348-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch similarity index 100% rename from patches/server/0347-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch rename to patches/server/0348-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch diff --git a/patches/server/0348-MC-145656-Fix-Follow-Range-Initial-Target.patch b/patches/server/0349-MC-145656-Fix-Follow-Range-Initial-Target.patch similarity index 100% rename from patches/server/0348-MC-145656-Fix-Follow-Range-Initial-Target.patch rename to patches/server/0349-MC-145656-Fix-Follow-Range-Initial-Target.patch diff --git a/patches/server/0349-Optimize-Hoppers.patch b/patches/server/0350-Optimize-Hoppers.patch similarity index 100% rename from patches/server/0349-Optimize-Hoppers.patch rename to patches/server/0350-Optimize-Hoppers.patch diff --git a/patches/server/0350-PlayerDeathEvent-shouldDropExperience.patch b/patches/server/0351-PlayerDeathEvent-shouldDropExperience.patch similarity index 91% rename from patches/server/0350-PlayerDeathEvent-shouldDropExperience.patch rename to patches/server/0351-PlayerDeathEvent-shouldDropExperience.patch index 40e04c2c40..bf75aa1911 100644 --- a/patches/server/0350-PlayerDeathEvent-shouldDropExperience.patch +++ b/patches/server/0351-PlayerDeathEvent-shouldDropExperience.patch @@ -5,7 +5,7 @@ Subject: [PATCH] PlayerDeathEvent#shouldDropExperience diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 8da35a7dde494b059e542d049d7ee039deb5833d..4fef4c0240be90ddcb9640f5719e292d2d5dbdf8 100644 +index 6086f86e6fd0395553aef42df4aef6a117231896..018632aa8b122f8c013579075615d88d712f4250 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -849,7 +849,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0351-Prevent-bees-loading-chunks-checking-hive-position.patch b/patches/server/0352-Prevent-bees-loading-chunks-checking-hive-position.patch similarity index 100% rename from patches/server/0351-Prevent-bees-loading-chunks-checking-hive-position.patch rename to patches/server/0352-Prevent-bees-loading-chunks-checking-hive-position.patch diff --git a/patches/server/0352-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/patches/server/0353-Don-t-load-Chunks-from-Hoppers-and-other-things.patch similarity index 100% rename from patches/server/0352-Don-t-load-Chunks-from-Hoppers-and-other-things.patch rename to patches/server/0353-Don-t-load-Chunks-from-Hoppers-and-other-things.patch diff --git a/patches/server/0353-Guard-against-serializing-mismatching-chunk-coordina.patch b/patches/server/0354-Guard-against-serializing-mismatching-chunk-coordina.patch similarity index 100% rename from patches/server/0353-Guard-against-serializing-mismatching-chunk-coordina.patch rename to patches/server/0354-Guard-against-serializing-mismatching-chunk-coordina.patch diff --git a/patches/server/0354-Optimise-IEntityAccess-getPlayerByUUID.patch b/patches/server/0355-Optimise-IEntityAccess-getPlayerByUUID.patch similarity index 100% rename from patches/server/0354-Optimise-IEntityAccess-getPlayerByUUID.patch rename to patches/server/0355-Optimise-IEntityAccess-getPlayerByUUID.patch diff --git a/patches/server/0355-Fix-items-not-falling-correctly.patch b/patches/server/0356-Fix-items-not-falling-correctly.patch similarity index 100% rename from patches/server/0355-Fix-items-not-falling-correctly.patch rename to patches/server/0356-Fix-items-not-falling-correctly.patch diff --git a/patches/server/0356-Lag-compensate-eating.patch b/patches/server/0357-Lag-compensate-eating.patch similarity index 100% rename from patches/server/0356-Lag-compensate-eating.patch rename to patches/server/0357-Lag-compensate-eating.patch diff --git a/patches/server/0357-Optimize-call-to-getFluid-for-explosions.patch b/patches/server/0358-Optimize-call-to-getFluid-for-explosions.patch similarity index 100% rename from patches/server/0357-Optimize-call-to-getFluid-for-explosions.patch rename to patches/server/0358-Optimize-call-to-getFluid-for-explosions.patch diff --git a/patches/server/0358-Fix-last-firework-in-stack-not-having-effects-when-d.patch b/patches/server/0359-Fix-last-firework-in-stack-not-having-effects-when-d.patch similarity index 100% rename from patches/server/0358-Fix-last-firework-in-stack-not-having-effects-when-d.patch rename to patches/server/0359-Fix-last-firework-in-stack-not-having-effects-when-d.patch diff --git a/patches/server/0359-Add-effect-to-block-break-naturally.patch b/patches/server/0360-Add-effect-to-block-break-naturally.patch similarity index 100% rename from patches/server/0359-Add-effect-to-block-break-naturally.patch rename to patches/server/0360-Add-effect-to-block-break-naturally.patch diff --git a/patches/server/0360-Entity-Activation-Range-2.0.patch b/patches/server/0361-Entity-Activation-Range-2.0.patch similarity index 99% rename from patches/server/0360-Entity-Activation-Range-2.0.patch rename to patches/server/0361-Entity-Activation-Range-2.0.patch index 8496b9c17e..b3fddc85d8 100644 --- a/patches/server/0360-Entity-Activation-Range-2.0.patch +++ b/patches/server/0361-Entity-Activation-Range-2.0.patch @@ -124,7 +124,7 @@ index fe98fa03548922903e4fb352fbdfeeaac87450df..8d72e68fe8f7d0a770264f54c539ea11 } else { passenger.stopRiding(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 47503fa2feabf6615f250d13f25f080d19c2f560..6b93b4e7717efbe68de3f1afe4843023e22c06bb 100644 +index 434618dcb3d4261eb1db20b8f0807c9aba6b8332..9ebbcd15dee0141eca83187a85e0d9b0b5a0fa86 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -277,7 +277,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @@ -180,7 +180,7 @@ index f48435dc344fb48feb48e2a141b394829058c5c4..bd1cc5e6fea4b9a171718c1249f65278 public float yya; public float zza; diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 32e8ae0d2a0f78af671a632c4d1be58a0b38a392..79e10f41b2993a02c4218551b06673f1848325a3 100644 +index 1dcfab8776c9da4c461ebd98187b65bc6ed7dc4d..c9324245d18f8268191c0a89b465ef3054dd014d 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java @@ -117,7 +117,7 @@ public abstract class Mob extends LivingEntity { @@ -293,7 +293,7 @@ index 065d0752db0e3ae2a89d707aaa2145807f50ecad..c93805ae832d049ea13ca495b778ed52 } } diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index aec77679584a2acab5818e26e2586b5316118e84..9c7cb4f11c429ca5006cf5e178326ead1658581d 100644 +index 555cf6d39108d40998adbbaf6b09dd9973f5f2e3..426fa33c9e5ddf2de5435859ee4a5f352313869c 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -227,17 +227,29 @@ public class Villager extends AbstractVillager implements ReputationEventHandler diff --git a/patches/server/0361-Increase-Light-Queue-Size.patch b/patches/server/0362-Increase-Light-Queue-Size.patch similarity index 100% rename from patches/server/0361-Increase-Light-Queue-Size.patch rename to patches/server/0362-Increase-Light-Queue-Size.patch diff --git a/patches/server/0362-Fix-Light-Command.patch b/patches/server/0363-Fix-Light-Command.patch similarity index 100% rename from patches/server/0362-Fix-Light-Command.patch rename to patches/server/0363-Fix-Light-Command.patch diff --git a/patches/server/0363-No-Tick-view-distance-implementation.patch b/patches/server/0364-No-Tick-view-distance-implementation.patch similarity index 99% rename from patches/server/0363-No-Tick-view-distance-implementation.patch rename to patches/server/0364-No-Tick-view-distance-implementation.patch index 50391a3d4f..96b59e1789 100644 --- a/patches/server/0363-No-Tick-view-distance-implementation.patch +++ b/patches/server/0364-No-Tick-view-distance-implementation.patch @@ -513,7 +513,7 @@ index 45c7ebe67019cdbe88b6617a95d5c40d3a68286c..38eebda226e007c8910e04f502ce218c if (withinViewDistance) { DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 4fef4c0240be90ddcb9640f5719e292d2d5dbdf8..bffc897cb88a54c36432c98264f3416051aeab17 100644 +index 018632aa8b122f8c013579075615d88d712f4250..92a77fa90828cc4bc3d9217d2df37ffeec6ee58e 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -241,6 +241,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0364-Implement-alternative-item-despawn-rate.patch b/patches/server/0365-Implement-alternative-item-despawn-rate.patch similarity index 100% rename from patches/server/0364-Implement-alternative-item-despawn-rate.patch rename to patches/server/0365-Implement-alternative-item-despawn-rate.patch diff --git a/patches/server/0365-Tracking-Range-Improvements.patch b/patches/server/0366-Tracking-Range-Improvements.patch similarity index 100% rename from patches/server/0365-Tracking-Range-Improvements.patch rename to patches/server/0366-Tracking-Range-Improvements.patch diff --git a/patches/server/0366-Fix-items-vanishing-through-end-portal.patch b/patches/server/0367-Fix-items-vanishing-through-end-portal.patch similarity index 93% rename from patches/server/0366-Fix-items-vanishing-through-end-portal.patch rename to patches/server/0367-Fix-items-vanishing-through-end-portal.patch index d64b934744..7ba3ecfef5 100644 --- a/patches/server/0366-Fix-items-vanishing-through-end-portal.patch +++ b/patches/server/0367-Fix-items-vanishing-through-end-portal.patch @@ -13,7 +13,7 @@ Quickly loading the exact world spawn chunk before searching the heightmap resolves the issue without having to load all spawn chunks. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 6b93b4e7717efbe68de3f1afe4843023e22c06bb..999cf6f54133fb70bff56f93347e9916b58e1e3a 100644 +index 9ebbcd15dee0141eca83187a85e0d9b0b5a0fa86..b4694693814ca37ca33fef10bd87e05c228c9fa1 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -2984,6 +2984,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0367-implement-optional-per-player-mob-spawns.patch b/patches/server/0368-implement-optional-per-player-mob-spawns.patch similarity index 99% rename from patches/server/0367-implement-optional-per-player-mob-spawns.patch rename to patches/server/0368-implement-optional-per-player-mob-spawns.patch index c999eb08be..27117d65e3 100644 --- a/patches/server/0367-implement-optional-per-player-mob-spawns.patch +++ b/patches/server/0368-implement-optional-per-player-mob-spawns.patch @@ -627,7 +627,7 @@ index c47d1772044913475a60292162ef4be594bed4c6..78143fe566fef13604c46029d4184ba3 this.lastSpawnState = spawnercreature_d; diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index bffc897cb88a54c36432c98264f3416051aeab17..14a0190ea5e9a387582736bb130c16a3bc94151e 100644 +index 92a77fa90828cc4bc3d9217d2df37ffeec6ee58e..ec7804e80f9c6b0fc53eb67823c6325a685c850b 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -90,12 +90,7 @@ import net.minecraft.world.damagesource.DamageSource; diff --git a/patches/server/0368-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/0369-Bees-get-gravity-in-void.-Fixes-MC-167279.patch similarity index 100% rename from patches/server/0368-Bees-get-gravity-in-void.-Fixes-MC-167279.patch rename to patches/server/0369-Bees-get-gravity-in-void.-Fixes-MC-167279.patch diff --git a/patches/server/0369-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server/0370-Optimise-getChunkAt-calls-for-loaded-chunks.patch similarity index 100% rename from patches/server/0369-Optimise-getChunkAt-calls-for-loaded-chunks.patch rename to patches/server/0370-Optimise-getChunkAt-calls-for-loaded-chunks.patch diff --git a/patches/server/0370-Allow-overriding-the-java-version-check.patch b/patches/server/0371-Allow-overriding-the-java-version-check.patch similarity index 100% rename from patches/server/0370-Allow-overriding-the-java-version-check.patch rename to patches/server/0371-Allow-overriding-the-java-version-check.patch diff --git a/patches/server/0371-Add-ThrownEggHatchEvent.patch b/patches/server/0372-Add-ThrownEggHatchEvent.patch similarity index 100% rename from patches/server/0371-Add-ThrownEggHatchEvent.patch rename to patches/server/0372-Add-ThrownEggHatchEvent.patch diff --git a/patches/server/0372-Optimise-random-block-ticking.patch b/patches/server/0373-Optimise-random-block-ticking.patch similarity index 100% rename from patches/server/0372-Optimise-random-block-ticking.patch rename to patches/server/0373-Optimise-random-block-ticking.patch diff --git a/patches/server/0373-Entity-Jump-API.patch b/patches/server/0374-Entity-Jump-API.patch similarity index 100% rename from patches/server/0373-Entity-Jump-API.patch rename to patches/server/0374-Entity-Jump-API.patch diff --git a/patches/server/0374-Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/0375-Add-option-to-nerf-pigmen-from-nether-portals.patch similarity index 97% rename from patches/server/0374-Add-option-to-nerf-pigmen-from-nether-portals.patch rename to patches/server/0375-Add-option-to-nerf-pigmen-from-nether-portals.patch index f33d6ed44f..683ab55aea 100644 --- a/patches/server/0374-Add-option-to-nerf-pigmen-from-nether-portals.patch +++ b/patches/server/0375-Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -21,7 +21,7 @@ index 16f013ffe992a934e9d0b32e764a14a8fd204449..6c7e90f9939d42fdf8d40dd7ec0a6a86 private void lightQueueSize() { lightQueueSize = getInt("light-queue-size", lightQueueSize); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 999cf6f54133fb70bff56f93347e9916b58e1e3a..d97319136d6cded2a12cb9ae4f9aa921ff59882c 100644 +index b4694693814ca37ca33fef10bd87e05c228c9fa1..eb35b18f4875367723ed2e57f19fabca4360ed54 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -308,6 +308,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0375-Make-the-GUI-graph-fancier.patch b/patches/server/0376-Make-the-GUI-graph-fancier.patch similarity index 100% rename from patches/server/0375-Make-the-GUI-graph-fancier.patch rename to patches/server/0376-Make-the-GUI-graph-fancier.patch diff --git a/patches/server/0376-add-hand-to-BlockMultiPlaceEvent.patch b/patches/server/0377-add-hand-to-BlockMultiPlaceEvent.patch similarity index 93% rename from patches/server/0376-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/server/0377-add-hand-to-BlockMultiPlaceEvent.patch index 02e47511bf..633352946b 100644 --- a/patches/server/0376-add-hand-to-BlockMultiPlaceEvent.patch +++ b/patches/server/0377-add-hand-to-BlockMultiPlaceEvent.patch @@ -5,7 +5,7 @@ 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 c3341d1c4e9cda85b0b236461b0a00cbebc9a856..98bec353d6dbd85c7b329f75e09f4d0bfcfdaa6c 100644 +index 4524d1af433750d763599dc990b8eda511ec0bad..60226f5c408ebd83c958d6644204bfc03365638a 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -339,13 +339,18 @@ public class CraftEventFactory { diff --git a/patches/server/0377-Prevent-teleporting-dead-entities.patch b/patches/server/0378-Prevent-teleporting-dead-entities.patch similarity index 91% rename from patches/server/0377-Prevent-teleporting-dead-entities.patch rename to patches/server/0378-Prevent-teleporting-dead-entities.patch index 59a60c41af..3def460b53 100644 --- a/patches/server/0377-Prevent-teleporting-dead-entities.patch +++ b/patches/server/0378-Prevent-teleporting-dead-entities.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Prevent teleporting dead entities diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 9240064a17e7ac2492fe157b759d1f724105cd0e..fcfd57fd7af655aafb330986e8f6f9cc55819165 100644 +index 9c5eba2cbd7399c8e3f8c5c3dad228ded6d57832..85a82c8bb98edec526260680ddfbcb36926b97ee 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1501,6 +1501,10 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0378-Validate-tripwire-hook-placement-before-update.patch b/patches/server/0379-Validate-tripwire-hook-placement-before-update.patch similarity index 100% rename from patches/server/0378-Validate-tripwire-hook-placement-before-update.patch rename to patches/server/0379-Validate-tripwire-hook-placement-before-update.patch diff --git a/patches/server/0379-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server/0380-Add-option-to-allow-iron-golems-to-spawn-in-air.patch similarity index 100% rename from patches/server/0379-Add-option-to-allow-iron-golems-to-spawn-in-air.patch rename to patches/server/0380-Add-option-to-allow-iron-golems-to-spawn-in-air.patch diff --git a/patches/server/0380-Configurable-chance-of-villager-zombie-infection.patch b/patches/server/0381-Configurable-chance-of-villager-zombie-infection.patch similarity index 100% rename from patches/server/0380-Configurable-chance-of-villager-zombie-infection.patch rename to patches/server/0381-Configurable-chance-of-villager-zombie-infection.patch diff --git a/patches/server/0381-Optimise-Chunk-getFluid.patch b/patches/server/0382-Optimise-Chunk-getFluid.patch similarity index 100% rename from patches/server/0381-Optimise-Chunk-getFluid.patch rename to patches/server/0382-Optimise-Chunk-getFluid.patch diff --git a/patches/server/0382-Optimise-TickListServer-by-rewriting-it.patch b/patches/server/0383-Optimise-TickListServer-by-rewriting-it.patch similarity index 100% rename from patches/server/0382-Optimise-TickListServer-by-rewriting-it.patch rename to patches/server/0383-Optimise-TickListServer-by-rewriting-it.patch diff --git a/patches/server/0383-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/0384-Pillager-patrol-spawn-settings-and-per-player-option.patch similarity index 98% rename from patches/server/0383-Pillager-patrol-spawn-settings-and-per-player-option.patch rename to patches/server/0384-Pillager-patrol-spawn-settings-and-per-player-option.patch index 150228e975..b2bc5ab21f 100644 --- a/patches/server/0383-Pillager-patrol-spawn-settings-and-per-player-option.patch +++ b/patches/server/0384-Pillager-patrol-spawn-settings-and-per-player-option.patch @@ -36,7 +36,7 @@ index 0863bdab8322b80a3df52c238b55c14401bafe6d..4a2b52b5f5c0453c204765ec77e35524 private void entitiesTargetWithFollowRange() { entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 14a0190ea5e9a387582736bb130c16a3bc94151e..c3ed4358b0cb6f252f9e3f71abe4ec9624cb7694 100644 +index ec7804e80f9c6b0fc53eb67823c6325a685c850b..9e6d6db0782751895afe345b4d6f586389ec2392 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -214,6 +214,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0384-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server/0385-Remote-Connections-shouldn-t-hold-up-shutdown.patch similarity index 100% rename from patches/server/0384-Remote-Connections-shouldn-t-hold-up-shutdown.patch rename to patches/server/0385-Remote-Connections-shouldn-t-hold-up-shutdown.patch diff --git a/patches/server/0385-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/0386-Do-not-allow-bees-to-load-chunks-for-beehives.patch similarity index 95% rename from patches/server/0385-Do-not-allow-bees-to-load-chunks-for-beehives.patch rename to patches/server/0386-Do-not-allow-bees-to-load-chunks-for-beehives.patch index 5e703d1985..2ce1c37a10 100644 --- a/patches/server/0385-Do-not-allow-bees-to-load-chunks-for-beehives.patch +++ b/patches/server/0386-Do-not-allow-bees-to-load-chunks-for-beehives.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Do not allow bees to load chunks for beehives diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index 3d049e43c8ea85597e98e9dad61c8d4c49b01b1c..207e6f411491d01f9ca5b49aa65a66e16255ff3e 100644 +index 50724baf5eb207ce44be62509f9a024d9a0e10f3..9b6dd82e5e6e4ba6290e1931c2e9756d93f323d8 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java @@ -409,6 +409,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { diff --git a/patches/server/0386-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server/0387-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch similarity index 100% rename from patches/server/0386-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch rename to patches/server/0387-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch diff --git a/patches/server/0387-Optimize-Collision-to-not-load-chunks.patch b/patches/server/0388-Optimize-Collision-to-not-load-chunks.patch similarity index 98% rename from patches/server/0387-Optimize-Collision-to-not-load-chunks.patch rename to patches/server/0388-Optimize-Collision-to-not-load-chunks.patch index 2387b545f1..a57bb431de 100644 --- a/patches/server/0387-Optimize-Collision-to-not-load-chunks.patch +++ b/patches/server/0388-Optimize-Collision-to-not-load-chunks.patch @@ -26,7 +26,7 @@ index 2730923bd0bf3b0f928765b9e09e2299fa9a393d..f98a1c32e0c209473cf7268cbd8245ab entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d97319136d6cded2a12cb9ae4f9aa921ff59882c..21bcb811eb002714db7a9be70133bda7a722ba65 100644 +index eb35b18f4875367723ed2e57f19fabca4360ed54..07630fabdc3e824572d7f551f3a876133fc253fe 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -172,6 +172,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0388-Don-t-tick-dead-players.patch b/patches/server/0389-Don-t-tick-dead-players.patch similarity index 91% rename from patches/server/0388-Don-t-tick-dead-players.patch rename to patches/server/0389-Don-t-tick-dead-players.patch index 95d2e787e5..157807e58b 100644 --- a/patches/server/0388-Don-t-tick-dead-players.patch +++ b/patches/server/0389-Don-t-tick-dead-players.patch @@ -7,7 +7,7 @@ Causes sync chunk loads and who knows what all else. This is safe because Spectators are skipped in unloaded chunks too in vanilla. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index c3ed4358b0cb6f252f9e3f71abe4ec9624cb7694..791aa76cd09b3597f6f1e0d7e302fe9a446ea8e5 100644 +index 9e6d6db0782751895afe345b4d6f586389ec2392..8fc75890eb7342ff9339789434b031ef9a6a5000 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -638,7 +638,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0389-Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server/0390-Dead-Player-s-shouldn-t-be-able-to-move.patch similarity index 100% rename from patches/server/0389-Dead-Player-s-shouldn-t-be-able-to-move.patch rename to patches/server/0390-Dead-Player-s-shouldn-t-be-able-to-move.patch diff --git a/patches/server/0390-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/0391-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch similarity index 100% rename from patches/server/0390-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch rename to patches/server/0391-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch diff --git a/patches/server/0391-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/patches/server/0392-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch similarity index 100% rename from patches/server/0391-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch rename to patches/server/0392-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch diff --git a/patches/server/0392-Don-t-move-existing-players-to-world-spawn.patch b/patches/server/0393-Don-t-move-existing-players-to-world-spawn.patch similarity index 96% rename from patches/server/0392-Don-t-move-existing-players-to-world-spawn.patch rename to patches/server/0393-Don-t-move-existing-players-to-world-spawn.patch index 2ca582d971..629ecd4cd2 100644 --- a/patches/server/0392-Don-t-move-existing-players-to-world-spawn.patch +++ b/patches/server/0393-Don-t-move-existing-players-to-world-spawn.patch @@ -10,7 +10,7 @@ larger than the keep loaded range. By skipping this, we avoid potential for a large spike on server start. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 791aa76cd09b3597f6f1e0d7e302fe9a446ea8e5..a2103ba85e012bbeaf5ecf91db8d5203f576e285 100644 +index 8fc75890eb7342ff9339789434b031ef9a6a5000..58da115a0c2f34c63ae3614acb0d6f8711069e7b 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -309,7 +309,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0393-Add-tick-times-API-and-mspt-command.patch b/patches/server/0394-Add-tick-times-API-and-mspt-command.patch similarity index 100% rename from patches/server/0393-Add-tick-times-API-and-mspt-command.patch rename to patches/server/0394-Add-tick-times-API-and-mspt-command.patch diff --git a/patches/server/0394-Expose-MinecraftServer-isRunning.patch b/patches/server/0395-Expose-MinecraftServer-isRunning.patch similarity index 100% rename from patches/server/0394-Expose-MinecraftServer-isRunning.patch rename to patches/server/0395-Expose-MinecraftServer-isRunning.patch diff --git a/patches/server/0395-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/0396-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 100% rename from patches/server/0395-Add-Raw-Byte-ItemStack-Serialization.patch rename to patches/server/0396-Add-Raw-Byte-ItemStack-Serialization.patch diff --git a/patches/server/0396-Remove-streams-from-Mob-AI-System.patch b/patches/server/0397-Remove-streams-from-Mob-AI-System.patch similarity index 100% rename from patches/server/0396-Remove-streams-from-Mob-AI-System.patch rename to patches/server/0397-Remove-streams-from-Mob-AI-System.patch diff --git a/patches/server/0397-Async-command-map-building.patch b/patches/server/0398-Async-command-map-building.patch similarity index 100% rename from patches/server/0397-Async-command-map-building.patch rename to patches/server/0398-Async-command-map-building.patch diff --git a/patches/server/0398-Improved-Watchdog-Support.patch b/patches/server/0399-Improved-Watchdog-Support.patch similarity index 100% rename from patches/server/0398-Improved-Watchdog-Support.patch rename to patches/server/0399-Improved-Watchdog-Support.patch diff --git a/patches/server/0399-Optimize-Pathfinding.patch b/patches/server/0400-Optimize-Pathfinding.patch similarity index 100% rename from patches/server/0399-Optimize-Pathfinding.patch rename to patches/server/0400-Optimize-Pathfinding.patch diff --git a/patches/server/0400-Reduce-Either-Optional-allocation.patch b/patches/server/0401-Reduce-Either-Optional-allocation.patch similarity index 100% rename from patches/server/0400-Reduce-Either-Optional-allocation.patch rename to patches/server/0401-Reduce-Either-Optional-allocation.patch diff --git a/patches/server/0401-Remove-streams-from-PairedQueue.patch b/patches/server/0402-Remove-streams-from-PairedQueue.patch similarity index 100% rename from patches/server/0401-Remove-streams-from-PairedQueue.patch rename to patches/server/0402-Remove-streams-from-PairedQueue.patch diff --git a/patches/server/0402-Reduce-memory-footprint-of-NBTTagCompound.patch b/patches/server/0403-Reduce-memory-footprint-of-NBTTagCompound.patch similarity index 100% rename from patches/server/0402-Reduce-memory-footprint-of-NBTTagCompound.patch rename to patches/server/0403-Reduce-memory-footprint-of-NBTTagCompound.patch diff --git a/patches/server/0403-Prevent-opening-inventories-when-frozen.patch b/patches/server/0404-Prevent-opening-inventories-when-frozen.patch similarity index 97% rename from patches/server/0403-Prevent-opening-inventories-when-frozen.patch rename to patches/server/0404-Prevent-opening-inventories-when-frozen.patch index 2c7b34bab9..83b4bcfc78 100644 --- a/patches/server/0403-Prevent-opening-inventories-when-frozen.patch +++ b/patches/server/0404-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 a2103ba85e012bbeaf5ecf91db8d5203f576e285..d9db660db873bade362ef40aa776293a001564a9 100644 +index 58da115a0c2f34c63ae3614acb0d6f8711069e7b..37fcc83cbaf8e80809c994b18f5a7f3f6d807202 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -609,7 +609,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0404-Optimise-ArraySetSorted-removeIf.patch b/patches/server/0405-Optimise-ArraySetSorted-removeIf.patch similarity index 100% rename from patches/server/0404-Optimise-ArraySetSorted-removeIf.patch rename to patches/server/0405-Optimise-ArraySetSorted-removeIf.patch diff --git a/patches/server/0405-Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server/0406-Don-t-run-entity-collision-code-if-not-needed.patch similarity index 100% rename from patches/server/0405-Don-t-run-entity-collision-code-if-not-needed.patch rename to patches/server/0406-Don-t-run-entity-collision-code-if-not-needed.patch diff --git a/patches/server/0406-Restrict-vanilla-teleport-command-to-valid-locations.patch b/patches/server/0407-Restrict-vanilla-teleport-command-to-valid-locations.patch similarity index 100% rename from patches/server/0406-Restrict-vanilla-teleport-command-to-valid-locations.patch rename to patches/server/0407-Restrict-vanilla-teleport-command-to-valid-locations.patch diff --git a/patches/server/0407-Implement-Player-Client-Options-API.patch b/patches/server/0408-Implement-Player-Client-Options-API.patch similarity index 98% rename from patches/server/0407-Implement-Player-Client-Options-API.patch rename to patches/server/0408-Implement-Player-Client-Options-API.patch index ef5eadd098..8496cca27d 100644 --- a/patches/server/0407-Implement-Player-Client-Options-API.patch +++ b/patches/server/0408-Implement-Player-Client-Options-API.patch @@ -85,7 +85,7 @@ index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabb + } +} diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index d9db660db873bade362ef40aa776293a001564a9..c3aae7bc629b08b8bc1b40973adebfd6aa1edbfd 100644 +index 37fcc83cbaf8e80809c994b18f5a7f3f6d807202..efc6e03e86867665fc655e5a3e0f154af066ef24 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1802,6 +1802,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0408-Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server/0409-Fix-Chunk-Post-Processing-deadlock-risk.patch similarity index 100% rename from patches/server/0408-Fix-Chunk-Post-Processing-deadlock-risk.patch rename to patches/server/0409-Fix-Chunk-Post-Processing-deadlock-risk.patch diff --git a/patches/server/0409-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/patches/server/0410-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch similarity index 100% rename from patches/server/0409-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch rename to patches/server/0410-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch diff --git a/patches/server/0410-Broadcast-join-message-to-console.patch b/patches/server/0411-Broadcast-join-message-to-console.patch similarity index 100% rename from patches/server/0410-Broadcast-join-message-to-console.patch rename to patches/server/0411-Broadcast-join-message-to-console.patch diff --git a/patches/server/0411-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/patches/server/0412-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch similarity index 98% rename from patches/server/0411-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch rename to patches/server/0412-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch index 3f471ab0a6..fe9800e326 100644 --- a/patches/server/0411-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch +++ b/patches/server/0412-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch @@ -49,7 +49,7 @@ index f651b7d2bbc2fc883bc73ef892de62624d1285e7..6c763b5407425b764839b921f4dc9e18 if (!(entity instanceof EnderDragonPart)) { EntityType entitytypes = entity.getType(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index c3aae7bc629b08b8bc1b40973adebfd6aa1edbfd..48f089040dd21342d001b91135ec9128ad5e1027 100644 +index efc6e03e86867665fc655e5a3e0f154af066ef24..488b45d8b8d3c10b72cd0529a494ea408be58c4c 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -237,6 +237,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0412-Load-Chunks-for-Login-Asynchronously.patch b/patches/server/0413-Load-Chunks-for-Login-Asynchronously.patch similarity index 98% rename from patches/server/0412-Load-Chunks-for-Login-Asynchronously.patch rename to patches/server/0413-Load-Chunks-for-Login-Asynchronously.patch index e5ea651270..66df2681d9 100644 --- a/patches/server/0412-Load-Chunks-for-Login-Asynchronously.patch +++ b/patches/server/0413-Load-Chunks-for-Login-Asynchronously.patch @@ -18,7 +18,7 @@ index 60cdb1f5c3f329b417f340f1d2651d89c244e439..3d1c4f8e0db37c6dabece657a17595e7 boolean flag1 = this.chunkMap.promoteChunkMap(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 48f089040dd21342d001b91135ec9128ad5e1027..c083ee1322f86809300fce1552eacd663aaa650d 100644 +index 488b45d8b8d3c10b72cd0529a494ea408be58c4c..61f9eda59684c08884c4a621effb1705db592a53 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -172,6 +172,7 @@ public class ServerPlayer extends Player { @@ -50,7 +50,7 @@ index be677d437d17b74c6188ce1bd5fc6fdc228fd92f..78fbb4c3e52e900956ae0811aaf934c8 public static final TicketType UNKNOWN = TicketType.create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); public static final TicketType PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index fcfd57fd7af655aafb330986e8f6f9cc55819165..1263e845a56e96920c71a7ef636ad3437a70c06f 100644 +index 85a82c8bb98edec526260680ddfbcb36926b97ee..10e4be89803bcdcc8bf7ce64350464c826368ae7 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -221,6 +221,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @@ -263,7 +263,7 @@ index 3a13c151066c8784fdc844e1d6310f77ff32e7f1..c4242a1602bbb02541c330bc02016f15 Iterator iterator = list.iterator(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 21bcb811eb002714db7a9be70133bda7a722ba65..326241a4669aa771db9d91ddd205576599110c2d 100644 +index 07630fabdc3e824572d7f551f3a876133fc253fe..e9f7191fefa7c0cf33d56abb7b2a30df261a392c 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1491,7 +1491,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0413-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/patches/server/0414-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch similarity index 93% rename from patches/server/0413-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch rename to patches/server/0414-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch index dd8d0f9858..ed7c7447a6 100644 --- a/patches/server/0413-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch +++ b/patches/server/0414-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch @@ -7,7 +7,7 @@ The code following this has better support for null worlds to move them back to the world spawn. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 326241a4669aa771db9d91ddd205576599110c2d..62b16f0cedc90af6842c981cf0d8390675fc7201 100644 +index e9f7191fefa7c0cf33d56abb7b2a30df261a392c..250a9b5cd47114aa4743f9695dadec2ad485f99d 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1980,9 +1980,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0414-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server/0415-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from patches/server/0414-Add-PlayerAttackEntityCooldownResetEvent.patch rename to patches/server/0415-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/patches/server/0415-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/patches/server/0416-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch similarity index 100% rename from patches/server/0415-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch rename to patches/server/0416-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch diff --git a/patches/server/0416-Don-t-fire-BlockFade-on-worldgen-threads.patch b/patches/server/0417-Don-t-fire-BlockFade-on-worldgen-threads.patch similarity index 100% rename from patches/server/0416-Don-t-fire-BlockFade-on-worldgen-threads.patch rename to patches/server/0417-Don-t-fire-BlockFade-on-worldgen-threads.patch diff --git a/patches/server/0417-Add-phantom-creative-and-insomniac-controls.patch b/patches/server/0418-Add-phantom-creative-and-insomniac-controls.patch similarity index 100% rename from patches/server/0417-Add-phantom-creative-and-insomniac-controls.patch rename to patches/server/0418-Add-phantom-creative-and-insomniac-controls.patch diff --git a/patches/server/0418-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/patches/server/0419-Fix-numerous-item-duplication-issues-and-teleport-is.patch similarity index 97% rename from patches/server/0418-Fix-numerous-item-duplication-issues-and-teleport-is.patch rename to patches/server/0419-Fix-numerous-item-duplication-issues-and-teleport-is.patch index 98d85e37e6..fe2cca76b8 100644 --- a/patches/server/0418-Fix-numerous-item-duplication-issues-and-teleport-is.patch +++ b/patches/server/0419-Fix-numerous-item-duplication-issues-and-teleport-is.patch @@ -16,7 +16,7 @@ So even if something NEW comes up, it would be impossible to drop the same item twice because the source was destroyed. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 62b16f0cedc90af6842c981cf0d8390675fc7201..a80a1a54a66de45aaf4974be56aecbafeb477825 100644 +index 250a9b5cd47114aa4743f9695dadec2ad485f99d..c6e659cd766facba6411e930d3ae1d2143c2f269 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -2126,11 +2126,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @@ -102,7 +102,7 @@ index cb9969d768b13863722aad3dc5daad3c10bb264a..5bfec185e15a54ee5fe6eab1aa59d196 } } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 98bec353d6dbd85c7b329f75e09f4d0bfcfdaa6c..7d43439a13bd109399691ddec60ee99c818db198 100644 +index 60226f5c408ebd83c958d6644204bfc03365638a..19724497e407c93f738c3bfaec72997dd5fe7ba1 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -807,7 +807,8 @@ public class CraftEventFactory { diff --git a/patches/server/0419-Implement-Brigadier-Mojang-API.patch b/patches/server/0420-Implement-Brigadier-Mojang-API.patch similarity index 98% rename from patches/server/0419-Implement-Brigadier-Mojang-API.patch rename to patches/server/0420-Implement-Brigadier-Mojang-API.patch index c73a8699ba..4916e3c246 100644 --- a/patches/server/0419-Implement-Brigadier-Mojang-API.patch +++ b/patches/server/0420-Implement-Brigadier-Mojang-API.patch @@ -10,7 +10,7 @@ Adds CommandRegisteredEvent - Allows manipulating the CommandNode to add more children/metadata for the client diff --git a/build.gradle.kts b/build.gradle.kts -index f0256fe4aea16c9e0d6f5eee360eeec36cfdeebd..2543a4cf2bb58c2265cfc427c427b683d2ff70ca 100644 +index 39ae4cc76438c40e007bfe5e8ace7cbaee66d3b8..23e8666e2b5691eb814af7e06b75c8507f0ed253 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -21,6 +21,7 @@ repositories { @@ -81,7 +81,7 @@ index 13e358e0eac3bfd426d924b6f745e001df76c64a..7156dea53be828acd01734fa1f9f7b9a event.getPlayer().getServer().getPluginManager().callEvent(event); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 1263e845a56e96920c71a7ef636ad3437a70c06f..fbb33cfa62723ac1fd6f426969e747e49abc8ea6 100644 +index 10e4be89803bcdcc8bf7ce64350464c826368ae7..33dfa5a72974f952a08ef9022b8158629a40a153 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -760,8 +760,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0420-Villager-Restocks-API.patch b/patches/server/0421-Villager-Restocks-API.patch similarity index 94% rename from patches/server/0420-Villager-Restocks-API.patch rename to patches/server/0421-Villager-Restocks-API.patch index 1445794bf4..4212655fc2 100644 --- a/patches/server/0420-Villager-Restocks-API.patch +++ b/patches/server/0421-Villager-Restocks-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Villager Restocks API diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 9c7cb4f11c429ca5006cf5e178326ead1658581d..fd2a2493fd7c935ab0b2fcd0f5d2b87ef3413af2 100644 +index 426fa33c9e5ddf2de5435859ee4a5f352313869c..124a8eb24bc9428011075925092e99f8159ee1c2 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -127,7 +127,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @@ -18,7 +18,7 @@ index 9c7cb4f11c429ca5006cf5e178326ead1658581d..fd2a2493fd7c935ab0b2fcd0f5d2b87e private boolean assignProfessionWhenSpawned; private static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.WALK_TARGET, new MemoryModuleType[]{MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index 40815c2500a1b4946c502b8ae7f80c4e93e556ae..115f107ac100524ef0fcf8de0fc528d164c845f7 100644 +index e22453a79371266c3dad450e6c82cb24babcece8..6b16bb1226515b8cbb477e62b617ee1a7f5ef8ed 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java @@ -83,6 +83,18 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { diff --git a/patches/server/0421-Validate-PickItem-Packet-and-kick-for-invalid.patch b/patches/server/0422-Validate-PickItem-Packet-and-kick-for-invalid.patch similarity index 95% rename from patches/server/0421-Validate-PickItem-Packet-and-kick-for-invalid.patch rename to patches/server/0422-Validate-PickItem-Packet-and-kick-for-invalid.patch index 348bbe236c..197d9443ce 100644 --- a/patches/server/0421-Validate-PickItem-Packet-and-kick-for-invalid.patch +++ b/patches/server/0422-Validate-PickItem-Packet-and-kick-for-invalid.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Validate PickItem Packet and kick for invalid diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index fbb33cfa62723ac1fd6f426969e747e49abc8ea6..b5325f19458467b307db629a00359af41004124a 100644 +index 33dfa5a72974f952a08ef9022b8158629a40a153..1aa260504c9ff022a32ffbb770c8d133bbd68cfc 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -877,7 +877,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0422-Expose-game-version.patch b/patches/server/0423-Expose-game-version.patch similarity index 100% rename from patches/server/0422-Expose-game-version.patch rename to patches/server/0423-Expose-game-version.patch diff --git a/patches/server/0423-Optimize-Voxel-Shape-Merging.patch b/patches/server/0424-Optimize-Voxel-Shape-Merging.patch similarity index 100% rename from patches/server/0423-Optimize-Voxel-Shape-Merging.patch rename to patches/server/0424-Optimize-Voxel-Shape-Merging.patch diff --git a/patches/server/0424-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/patches/server/0425-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch similarity index 100% rename from patches/server/0424-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch rename to patches/server/0425-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch diff --git a/patches/server/0425-Implement-Mob-Goal-API.patch b/patches/server/0426-Implement-Mob-Goal-API.patch similarity index 99% rename from patches/server/0425-Implement-Mob-Goal-API.patch rename to patches/server/0426-Implement-Mob-Goal-API.patch index dd073b39fe..49390dd06e 100644 --- a/patches/server/0425-Implement-Mob-Goal-API.patch +++ b/patches/server/0426-Implement-Mob-Goal-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Implement Mob Goal API diff --git a/build.gradle.kts b/build.gradle.kts -index 2543a4cf2bb58c2265cfc427c427b683d2ff70ca..5c885454c729467e29fd3784058fff6a7379c9dc 100644 +index 23e8666e2b5691eb814af7e06b75c8507f0ed253..01989dc93f768165f9de341d9df51355fd5f2727 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -52,6 +52,7 @@ dependencies { diff --git a/patches/server/0426-Use-distance-map-to-optimise-entity-tracker.patch b/patches/server/0427-Use-distance-map-to-optimise-entity-tracker.patch similarity index 99% rename from patches/server/0426-Use-distance-map-to-optimise-entity-tracker.patch rename to patches/server/0427-Use-distance-map-to-optimise-entity-tracker.patch index 0312a52281..1fac56559b 100644 --- a/patches/server/0426-Use-distance-map-to-optimise-entity-tracker.patch +++ b/patches/server/0427-Use-distance-map-to-optimise-entity-tracker.patch @@ -312,7 +312,7 @@ index 28afe2f238ded241acf77c3272a44068646b9133..6b492b72b177e3c58580561585609b17 List list = this.entity.getPassengers(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a80a1a54a66de45aaf4974be56aecbafeb477825..11ae525a5d2bd29bfe658d683c53a0ab2626616a 100644 +index c6e659cd766facba6411e930d3ae1d2143c2f269..57d8b712cbdcc1ff082e9313d50dedafa239f50e 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -50,6 +50,7 @@ import net.minecraft.network.syncher.EntityDataSerializers; diff --git a/patches/server/0427-Optimize-isOutsideRange-to-use-distance-maps.patch b/patches/server/0428-Optimize-isOutsideRange-to-use-distance-maps.patch similarity index 99% rename from patches/server/0427-Optimize-isOutsideRange-to-use-distance-maps.patch rename to patches/server/0428-Optimize-isOutsideRange-to-use-distance-maps.patch index 2971066550..3db66834ee 100644 --- a/patches/server/0427-Optimize-isOutsideRange-to-use-distance-maps.patch +++ b/patches/server/0428-Optimize-isOutsideRange-to-use-distance-maps.patch @@ -362,7 +362,7 @@ index 3d1c4f8e0db37c6dabece657a17595e7bf1e3dc2..3faa808f41f057a9956c697ec1323330 if (chunksTicked[0]++ % 10 == 0) this.level.getServer().midTickLoadChunks(); // Paper } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index c083ee1322f86809300fce1552eacd663aaa650d..cd34b5aa61c78d8138500a93f0a9714bedd7ed86 100644 +index 61f9eda59684c08884c4a621effb1705db592a53..a01227f1b6d3589a6f56c9289824a1503a32c878 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -244,6 +244,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0428-Add-villager-reputation-API.patch b/patches/server/0429-Add-villager-reputation-API.patch similarity index 100% rename from patches/server/0428-Add-villager-reputation-API.patch rename to patches/server/0429-Add-villager-reputation-API.patch diff --git a/patches/server/0429-Option-for-maximum-exp-value-when-merging-orbs.patch b/patches/server/0430-Option-for-maximum-exp-value-when-merging-orbs.patch similarity index 97% rename from patches/server/0429-Option-for-maximum-exp-value-when-merging-orbs.patch rename to patches/server/0430-Option-for-maximum-exp-value-when-merging-orbs.patch index 329975a609..c08ccc6865 100644 --- a/patches/server/0429-Option-for-maximum-exp-value-when-merging-orbs.patch +++ b/patches/server/0430-Option-for-maximum-exp-value-when-merging-orbs.patch @@ -22,7 +22,7 @@ index 16cf7d116e3ffd44ffc4f060b4014b52389cff77..3bc6329d3ea48966cb99e792f9b35e2d private void squidMaxSpawnHeight() { squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 7d43439a13bd109399691ddec60ee99c818db198..36b2faebca20ef152e4fc88ecfa660ecbbb11384 100644 +index 19724497e407c93f738c3bfaec72997dd5fe7ba1..4ad9dae575ea55b422e7b03b7eaf341ac0796d2c 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -610,16 +610,30 @@ public class CraftEventFactory { diff --git a/patches/server/0430-ExperienceOrbMergeEvent.patch b/patches/server/0431-ExperienceOrbMergeEvent.patch similarity index 94% rename from patches/server/0430-ExperienceOrbMergeEvent.patch rename to patches/server/0431-ExperienceOrbMergeEvent.patch index 5a91c0f475..1099425eb3 100644 --- a/patches/server/0430-ExperienceOrbMergeEvent.patch +++ b/patches/server/0431-ExperienceOrbMergeEvent.patch @@ -9,7 +9,7 @@ Plugins can cancel this if they want to ensure experience orbs do not lose impor metadata such as spawn reason, or conditionally move data from source to target. diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 36b2faebca20ef152e4fc88ecfa660ecbbb11384..d4b8035160332d98c37918f62ee9e0d630e23ee8 100644 +index 4ad9dae575ea55b422e7b03b7eaf341ac0796d2c..e508f75158423e8c4a59af18a094dfa36b9c180c 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -620,7 +620,7 @@ public class CraftEventFactory { diff --git a/patches/server/0431-Fix-PotionEffect-ignores-icon-flag.patch b/patches/server/0432-Fix-PotionEffect-ignores-icon-flag.patch similarity index 92% rename from patches/server/0431-Fix-PotionEffect-ignores-icon-flag.patch rename to patches/server/0432-Fix-PotionEffect-ignores-icon-flag.patch index 5ed01958b2..da67d64eeb 100644 --- a/patches/server/0431-Fix-PotionEffect-ignores-icon-flag.patch +++ b/patches/server/0432-Fix-PotionEffect-ignores-icon-flag.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix PotionEffect ignores icon flag diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 76e9977f7b2f7fb50631fc56f3318d59d04b1398..a7a6757b83c94a0c0926097021015815f8f18b8e 100644 +index d2e1dbc33d25cd1132b74d50dd9dd746098a4ecc..46fe4779bb894f3beb1f7814dbcc95a7f03b9e5a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -400,7 +400,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { diff --git a/patches/server/0432-Optimize-brigadier-child-sorting-performance.patch b/patches/server/0433-Optimize-brigadier-child-sorting-performance.patch similarity index 100% rename from patches/server/0432-Optimize-brigadier-child-sorting-performance.patch rename to patches/server/0433-Optimize-brigadier-child-sorting-performance.patch diff --git a/patches/server/0433-Potential-bed-API.patch b/patches/server/0434-Potential-bed-API.patch similarity index 100% rename from patches/server/0433-Potential-bed-API.patch rename to patches/server/0434-Potential-bed-API.patch diff --git a/patches/server/0434-Wait-for-Async-Tasks-during-shutdown.patch b/patches/server/0435-Wait-for-Async-Tasks-during-shutdown.patch similarity index 100% rename from patches/server/0434-Wait-for-Async-Tasks-during-shutdown.patch rename to patches/server/0435-Wait-for-Async-Tasks-during-shutdown.patch diff --git a/patches/server/0435-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/patches/server/0436-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch similarity index 100% rename from patches/server/0435-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch rename to patches/server/0436-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch diff --git a/patches/server/0436-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server/0437-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch similarity index 100% rename from patches/server/0436-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch rename to patches/server/0437-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch diff --git a/patches/server/0437-Reduce-MutableInt-allocations-from-light-engine.patch b/patches/server/0438-Reduce-MutableInt-allocations-from-light-engine.patch similarity index 100% rename from patches/server/0437-Reduce-MutableInt-allocations-from-light-engine.patch rename to patches/server/0438-Reduce-MutableInt-allocations-from-light-engine.patch diff --git a/patches/server/0438-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/patches/server/0439-Reduce-allocation-of-Vec3D-by-entity-tracker.patch similarity index 100% rename from patches/server/0438-Reduce-allocation-of-Vec3D-by-entity-tracker.patch rename to patches/server/0439-Reduce-allocation-of-Vec3D-by-entity-tracker.patch diff --git a/patches/server/0439-Ensure-safe-gateway-teleport.patch b/patches/server/0440-Ensure-safe-gateway-teleport.patch similarity index 100% rename from patches/server/0439-Ensure-safe-gateway-teleport.patch rename to patches/server/0440-Ensure-safe-gateway-teleport.patch diff --git a/patches/server/0440-Add-option-for-console-having-all-permissions.patch b/patches/server/0441-Add-option-for-console-having-all-permissions.patch similarity index 100% rename from patches/server/0440-Add-option-for-console-having-all-permissions.patch rename to patches/server/0441-Add-option-for-console-having-all-permissions.patch diff --git a/patches/server/0441-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/patches/server/0442-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch similarity index 100% rename from patches/server/0441-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch rename to patches/server/0442-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch diff --git a/patches/server/0442-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/patches/server/0443-Optimize-sending-packets-to-nearby-locations-sounds-.patch similarity index 100% rename from patches/server/0442-Optimize-sending-packets-to-nearby-locations-sounds-.patch rename to patches/server/0443-Optimize-sending-packets-to-nearby-locations-sounds-.patch diff --git a/patches/server/0443-Fix-villager-trading-demand-MC-163962.patch b/patches/server/0444-Fix-villager-trading-demand-MC-163962.patch similarity index 100% rename from patches/server/0443-Fix-villager-trading-demand-MC-163962.patch rename to patches/server/0444-Fix-villager-trading-demand-MC-163962.patch diff --git a/patches/server/0444-Maps-shouldn-t-load-chunks.patch b/patches/server/0445-Maps-shouldn-t-load-chunks.patch similarity index 100% rename from patches/server/0444-Maps-shouldn-t-load-chunks.patch rename to patches/server/0445-Maps-shouldn-t-load-chunks.patch diff --git a/patches/server/0445-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/patches/server/0446-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch similarity index 100% rename from patches/server/0445-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch rename to patches/server/0446-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch diff --git a/patches/server/0446-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/patches/server/0447-Delay-Chunk-Unloads-based-on-Player-Movement.patch similarity index 100% rename from patches/server/0446-Delay-Chunk-Unloads-based-on-Player-Movement.patch rename to patches/server/0447-Delay-Chunk-Unloads-based-on-Player-Movement.patch diff --git a/patches/server/0447-Optimize-Bit-Operations-by-inlining.patch b/patches/server/0448-Optimize-Bit-Operations-by-inlining.patch similarity index 100% rename from patches/server/0447-Optimize-Bit-Operations-by-inlining.patch rename to patches/server/0448-Optimize-Bit-Operations-by-inlining.patch diff --git a/patches/server/0448-incremental-chunk-saving.patch b/patches/server/0449-incremental-chunk-saving.patch similarity index 100% rename from patches/server/0448-incremental-chunk-saving.patch rename to patches/server/0449-incremental-chunk-saving.patch diff --git a/patches/server/0449-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/patches/server/0450-Add-Plugin-Tickets-to-API-Chunk-Methods.patch similarity index 100% rename from patches/server/0449-Add-Plugin-Tickets-to-API-Chunk-Methods.patch rename to patches/server/0450-Add-Plugin-Tickets-to-API-Chunk-Methods.patch diff --git a/patches/server/0450-Fix-missing-chunks-due-to-integer-overflow.patch b/patches/server/0451-Fix-missing-chunks-due-to-integer-overflow.patch similarity index 100% rename from patches/server/0450-Fix-missing-chunks-due-to-integer-overflow.patch rename to patches/server/0451-Fix-missing-chunks-due-to-integer-overflow.patch diff --git a/patches/server/0451-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/patches/server/0452-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch similarity index 100% rename from patches/server/0451-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch rename to patches/server/0452-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch diff --git a/patches/server/0452-Fix-piston-physics-inconsistency-MC-188840.patch b/patches/server/0453-Fix-piston-physics-inconsistency-MC-188840.patch similarity index 100% rename from patches/server/0452-Fix-piston-physics-inconsistency-MC-188840.patch rename to patches/server/0453-Fix-piston-physics-inconsistency-MC-188840.patch diff --git a/patches/server/0453-Fix-sand-duping.patch b/patches/server/0454-Fix-sand-duping.patch similarity index 100% rename from patches/server/0453-Fix-sand-duping.patch rename to patches/server/0454-Fix-sand-duping.patch diff --git a/patches/server/0454-Prevent-position-desync-in-playerconnection-causing-.patch b/patches/server/0455-Prevent-position-desync-in-playerconnection-causing-.patch similarity index 94% rename from patches/server/0454-Prevent-position-desync-in-playerconnection-causing-.patch rename to patches/server/0455-Prevent-position-desync-in-playerconnection-causing-.patch index 032768e519..e3a18ba403 100644 --- a/patches/server/0454-Prevent-position-desync-in-playerconnection-causing-.patch +++ b/patches/server/0455-Prevent-position-desync-in-playerconnection-causing-.patch @@ -14,7 +14,7 @@ behaviour, we need to move all of this dangerous logic outside of the move call and into an appropriate place in the tick method. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index b5325f19458467b307db629a00359af41004124a..7c9ac85431f8c5a325c94c0e7d1db0315b2d62c1 100644 +index 1aa260504c9ff022a32ffbb770c8d133bbd68cfc..72d8936660f2f6c43e4f6c220b60eef20ac2d055 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1345,6 +1345,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0455-Inventory-getHolder-method-without-block-snapshot.patch b/patches/server/0456-Inventory-getHolder-method-without-block-snapshot.patch similarity index 100% rename from patches/server/0455-Inventory-getHolder-method-without-block-snapshot.patch rename to patches/server/0456-Inventory-getHolder-method-without-block-snapshot.patch diff --git a/patches/server/0456-Expose-Arrow-getItemStack.patch b/patches/server/0457-Expose-Arrow-getItemStack.patch similarity index 100% rename from patches/server/0456-Expose-Arrow-getItemStack.patch rename to patches/server/0457-Expose-Arrow-getItemStack.patch diff --git a/patches/server/0457-Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/server/0458-Add-and-implement-PlayerRecipeBookClickEvent.patch similarity index 95% rename from patches/server/0457-Add-and-implement-PlayerRecipeBookClickEvent.patch rename to patches/server/0458-Add-and-implement-PlayerRecipeBookClickEvent.patch index dd62e3c0fe..4d47bb7fc2 100644 --- a/patches/server/0457-Add-and-implement-PlayerRecipeBookClickEvent.patch +++ b/patches/server/0458-Add-and-implement-PlayerRecipeBookClickEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 7c9ac85431f8c5a325c94c0e7d1db0315b2d62c1..c65f6eda0cff66ae9007e92002075e1f6fd631cd 100644 +index 72d8936660f2f6c43e4f6c220b60eef20ac2d055..8c182e3e4f81a6fc6554e8014e30c0cecf91cf5c 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -2778,9 +2778,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0458-Hide-sync-chunk-writes-behind-flag.patch b/patches/server/0459-Hide-sync-chunk-writes-behind-flag.patch similarity index 100% rename from patches/server/0458-Hide-sync-chunk-writes-behind-flag.patch rename to patches/server/0459-Hide-sync-chunk-writes-behind-flag.patch diff --git a/patches/server/0459-Add-permission-for-command-blocks.patch b/patches/server/0460-Add-permission-for-command-blocks.patch similarity index 98% rename from patches/server/0459-Add-permission-for-command-blocks.patch rename to patches/server/0460-Add-permission-for-command-blocks.patch index 65b46313ce..da4472b2e1 100644 --- a/patches/server/0459-Add-permission-for-command-blocks.patch +++ b/patches/server/0460-Add-permission-for-command-blocks.patch @@ -18,7 +18,7 @@ index f4a056185990181e486f452960159a5287947382..6c55bd8b876d1d694e05ad6de6a9fd29 return false; } else if (this.player.blockActionRestricted((Level) this.level, pos, this.gameModeForPlayer)) { diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index c65f6eda0cff66ae9007e92002075e1f6fd631cd..8193f783cbe7c678632b55f4bc59bc9d7b5756be 100644 +index 8c182e3e4f81a6fc6554e8014e30c0cecf91cf5c..2011ef91d026117be267cc3ea84d49a3288dd9ca 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -788,7 +788,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0460-Ensure-Entity-AABB-s-are-never-invalid.patch b/patches/server/0461-Ensure-Entity-AABB-s-are-never-invalid.patch similarity index 94% rename from patches/server/0460-Ensure-Entity-AABB-s-are-never-invalid.patch rename to patches/server/0461-Ensure-Entity-AABB-s-are-never-invalid.patch index 095b8c0582..2878f8259a 100644 --- a/patches/server/0460-Ensure-Entity-AABB-s-are-never-invalid.patch +++ b/patches/server/0461-Ensure-Entity-AABB-s-are-never-invalid.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Ensure Entity AABB's are never invalid diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 11ae525a5d2bd29bfe658d683c53a0ab2626616a..fd0cef886761e71fe331aa60806c186c23ed19bc 100644 +index 57d8b712cbdcc1ff082e9313d50dedafa239f50e..13b6cf4b3d5af77263051a5b17fa2b9da9803596 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -540,7 +540,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0461-Optimize-WorldBorder-collision-checks-and-air.patch b/patches/server/0462-Optimize-WorldBorder-collision-checks-and-air.patch similarity index 97% rename from patches/server/0461-Optimize-WorldBorder-collision-checks-and-air.patch rename to patches/server/0462-Optimize-WorldBorder-collision-checks-and-air.patch index 01936bbbf9..6c43f0ba85 100644 --- a/patches/server/0461-Optimize-WorldBorder-collision-checks-and-air.patch +++ b/patches/server/0462-Optimize-WorldBorder-collision-checks-and-air.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Optimize WorldBorder collision checks and air diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index fd0cef886761e71fe331aa60806c186c23ed19bc..96da70f1077f70c4bd5ba1196292a856deb25286 100644 +index 13b6cf4b3d5af77263051a5b17fa2b9da9803596..28f9b58c379306138f1528d91f2112c21ae9cb0a 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1024,7 +1024,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0462-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/patches/server/0463-Fix-Per-World-Difficulty-Remembering-Difficulty.patch similarity index 98% rename from patches/server/0462-Fix-Per-World-Difficulty-Remembering-Difficulty.patch rename to patches/server/0463-Fix-Per-World-Difficulty-Remembering-Difficulty.patch index eec5efcc02..6a136884e3 100644 --- a/patches/server/0462-Fix-Per-World-Difficulty-Remembering-Difficulty.patch +++ b/patches/server/0463-Fix-Per-World-Difficulty-Remembering-Difficulty.patch @@ -63,7 +63,7 @@ index e5f7f043cbdb28d85b8aa0eea7cbaeb584e5fb85..a5c1114f9b323e8a49c84d0e68461e47 @Override diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 8193f783cbe7c678632b55f4bc59bc9d7b5756be..39777c2b1bbb12ce3e5be3724235ea0a8072cef8 100644 +index 2011ef91d026117be267cc3ea84d49a3288dd9ca..c4a25ac9aad94c5ef610505db6d7539fa12cd31d 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -3041,7 +3041,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0463-Paper-dumpitem-command.patch b/patches/server/0464-Paper-dumpitem-command.patch similarity index 100% rename from patches/server/0463-Paper-dumpitem-command.patch rename to patches/server/0464-Paper-dumpitem-command.patch diff --git a/patches/server/0464-Don-t-allow-null-UUID-s-for-chat.patch b/patches/server/0465-Don-t-allow-null-UUID-s-for-chat.patch similarity index 100% rename from patches/server/0464-Don-t-allow-null-UUID-s-for-chat.patch rename to patches/server/0465-Don-t-allow-null-UUID-s-for-chat.patch diff --git a/patches/server/0465-Improve-Legacy-Component-serialization-size.patch b/patches/server/0466-Improve-Legacy-Component-serialization-size.patch similarity index 100% rename from patches/server/0465-Improve-Legacy-Component-serialization-size.patch rename to patches/server/0466-Improve-Legacy-Component-serialization-size.patch diff --git a/patches/server/0466-Support-old-UUID-format-for-NBT.patch b/patches/server/0467-Support-old-UUID-format-for-NBT.patch similarity index 100% rename from patches/server/0466-Support-old-UUID-format-for-NBT.patch rename to patches/server/0467-Support-old-UUID-format-for-NBT.patch diff --git a/patches/server/0467-Clean-up-duplicated-GameProfile-Properties.patch b/patches/server/0468-Clean-up-duplicated-GameProfile-Properties.patch similarity index 96% rename from patches/server/0467-Clean-up-duplicated-GameProfile-Properties.patch rename to patches/server/0468-Clean-up-duplicated-GameProfile-Properties.patch index 495144b4fb..811c919be7 100644 --- a/patches/server/0467-Clean-up-duplicated-GameProfile-Properties.patch +++ b/patches/server/0468-Clean-up-duplicated-GameProfile-Properties.patch @@ -9,7 +9,7 @@ growing to large sizes and preventing login. This now automatically cleans up the extra properties. diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java -index dc136cd4d5d4ba1e0e53a7187b3a2e836e185c19..1a9435a55e20170244497be70d86d989a4e0f78f 100644 +index 06fe97e05608fc21f90c9884d745d910beb6883d..dca8853944832e8fc5a291aa6b46d84b24181ea7 100644 --- a/src/main/java/net/minecraft/nbt/NbtUtils.java +++ b/src/main/java/net/minecraft/nbt/NbtUtils.java @@ -93,7 +93,8 @@ public final class NbtUtils { diff --git a/patches/server/0468-Convert-legacy-attributes-in-Item-Meta.patch b/patches/server/0469-Convert-legacy-attributes-in-Item-Meta.patch similarity index 100% rename from patches/server/0468-Convert-legacy-attributes-in-Item-Meta.patch rename to patches/server/0469-Convert-legacy-attributes-in-Item-Meta.patch diff --git a/patches/server/0469-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server/0470-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch similarity index 99% rename from patches/server/0469-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch rename to patches/server/0470-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch index 619abec3da..ed51f630f3 100644 --- a/patches/server/0469-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch +++ b/patches/server/0470-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch @@ -1035,7 +1035,7 @@ index 7ab28e9bd3f785838b7fa4ac5811c0e71cddcb61..d13abec908dbb756272888e9ccdedbef boolean flag1 = this.chunkMap.promoteChunkMap(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index cd34b5aa61c78d8138500a93f0a9714bedd7ed86..b106a972a76e856d6cdab78dec5daef77b135f98 100644 +index a01227f1b6d3589a6f56c9289824a1503a32c878..2bf25f90f760c1a5ee025a0ebaaccd9285a4db7f 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -183,6 +183,12 @@ public class ServerPlayer extends Player { @@ -1115,7 +1115,7 @@ index 8770fe0db46b01e8b608637df4f1a669a3f4cdde..3c1698ba0d3bc412ab957777d9b5211d private final String name; private final Comparator comparator; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 39777c2b1bbb12ce3e5be3724235ea0a8072cef8..2b8a9d16add3ac81ede029a909a40feaa07c51d3 100644 +index c4a25ac9aad94c5ef610505db6d7539fa12cd31d..91a06e1ac325fe80aaadaf213d40495f4ce15e53 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1566,6 +1566,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0470-Remove-some-streams-from-structures.patch b/patches/server/0471-Remove-some-streams-from-structures.patch similarity index 100% rename from patches/server/0470-Remove-some-streams-from-structures.patch rename to patches/server/0471-Remove-some-streams-from-structures.patch diff --git a/patches/server/0471-Remove-streams-from-classes-related-villager-gossip.patch b/patches/server/0472-Remove-streams-from-classes-related-villager-gossip.patch similarity index 100% rename from patches/server/0471-Remove-streams-from-classes-related-villager-gossip.patch rename to patches/server/0472-Remove-streams-from-classes-related-villager-gossip.patch diff --git a/patches/server/0472-Support-components-in-ItemMeta.patch b/patches/server/0473-Support-components-in-ItemMeta.patch similarity index 100% rename from patches/server/0472-Support-components-in-ItemMeta.patch rename to patches/server/0473-Support-components-in-ItemMeta.patch diff --git a/patches/server/0473-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/patches/server/0474-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch similarity index 100% rename from patches/server/0473-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch rename to patches/server/0474-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch diff --git a/patches/server/0474-Add-entity-liquid-API.patch b/patches/server/0475-Add-entity-liquid-API.patch similarity index 100% rename from patches/server/0474-Add-entity-liquid-API.patch rename to patches/server/0475-Add-entity-liquid-API.patch diff --git a/patches/server/0475-Update-itemstack-legacy-name-and-lore.patch b/patches/server/0476-Update-itemstack-legacy-name-and-lore.patch similarity index 100% rename from patches/server/0475-Update-itemstack-legacy-name-and-lore.patch rename to patches/server/0476-Update-itemstack-legacy-name-and-lore.patch diff --git a/patches/server/0476-Spawn-player-in-correct-world-on-login.patch b/patches/server/0477-Spawn-player-in-correct-world-on-login.patch similarity index 100% rename from patches/server/0476-Spawn-player-in-correct-world-on-login.patch rename to patches/server/0477-Spawn-player-in-correct-world-on-login.patch diff --git a/patches/server/0477-Add-PrepareResultEvent.patch b/patches/server/0478-Add-PrepareResultEvent.patch similarity index 100% rename from patches/server/0477-Add-PrepareResultEvent.patch rename to patches/server/0478-Add-PrepareResultEvent.patch diff --git a/patches/server/0478-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/0479-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 100% rename from patches/server/0478-Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/server/0479-Allow-delegation-to-vanilla-chunk-gen.patch diff --git a/patches/server/0479-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server/0480-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch similarity index 100% rename from patches/server/0479-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch rename to patches/server/0480-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch diff --git a/patches/server/0480-Optimize-NetworkManager-Exception-Handling.patch b/patches/server/0481-Optimize-NetworkManager-Exception-Handling.patch similarity index 100% rename from patches/server/0480-Optimize-NetworkManager-Exception-Handling.patch rename to patches/server/0481-Optimize-NetworkManager-Exception-Handling.patch diff --git a/patches/server/0481-Optimize-the-advancement-data-player-iteration-to-be.patch b/patches/server/0482-Optimize-the-advancement-data-player-iteration-to-be.patch similarity index 100% rename from patches/server/0481-Optimize-the-advancement-data-player-iteration-to-be.patch rename to patches/server/0482-Optimize-the-advancement-data-player-iteration-to-be.patch diff --git a/patches/server/0482-Fix-arrows-never-despawning-MC-125757.patch b/patches/server/0483-Fix-arrows-never-despawning-MC-125757.patch similarity index 100% rename from patches/server/0482-Fix-arrows-never-despawning-MC-125757.patch rename to patches/server/0483-Fix-arrows-never-despawning-MC-125757.patch diff --git a/patches/server/0483-Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server/0484-Thread-Safe-Vanilla-Command-permission-checking.patch similarity index 100% rename from patches/server/0483-Thread-Safe-Vanilla-Command-permission-checking.patch rename to patches/server/0484-Thread-Safe-Vanilla-Command-permission-checking.patch diff --git a/patches/server/0484-Move-range-check-for-block-placing-up.patch b/patches/server/0485-Move-range-check-for-block-placing-up.patch similarity index 100% rename from patches/server/0484-Move-range-check-for-block-placing-up.patch rename to patches/server/0485-Move-range-check-for-block-placing-up.patch diff --git a/patches/server/0485-Fix-SPIGOT-5989.patch b/patches/server/0486-Fix-SPIGOT-5989.patch similarity index 100% rename from patches/server/0485-Fix-SPIGOT-5989.patch rename to patches/server/0486-Fix-SPIGOT-5989.patch diff --git a/patches/server/0486-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/patches/server/0487-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch similarity index 100% rename from patches/server/0486-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch rename to patches/server/0487-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch diff --git a/patches/server/0487-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/patches/server/0488-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch similarity index 100% rename from patches/server/0487-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch rename to patches/server/0488-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch diff --git a/patches/server/0488-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/patches/server/0489-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch similarity index 100% rename from patches/server/0488-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch rename to patches/server/0489-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch diff --git a/patches/server/0489-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/patches/server/0490-Add-missing-strikeLighting-call-to-World-spigot-stri.patch similarity index 100% rename from patches/server/0489-Add-missing-strikeLighting-call-to-World-spigot-stri.patch rename to patches/server/0490-Add-missing-strikeLighting-call-to-World-spigot-stri.patch diff --git a/patches/server/0490-Fix-some-rails-connecting-improperly.patch b/patches/server/0491-Fix-some-rails-connecting-improperly.patch similarity index 100% rename from patches/server/0490-Fix-some-rails-connecting-improperly.patch rename to patches/server/0491-Fix-some-rails-connecting-improperly.patch diff --git a/patches/server/0491-Incremental-player-saving.patch b/patches/server/0492-Incremental-player-saving.patch similarity index 100% rename from patches/server/0491-Incremental-player-saving.patch rename to patches/server/0492-Incremental-player-saving.patch diff --git a/patches/server/0492-Fix-MC-187716-Use-configured-height.patch b/patches/server/0493-Fix-MC-187716-Use-configured-height.patch similarity index 100% rename from patches/server/0492-Fix-MC-187716-Use-configured-height.patch rename to patches/server/0493-Fix-MC-187716-Use-configured-height.patch diff --git a/patches/server/0493-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/patches/server/0494-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch similarity index 100% rename from patches/server/0493-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch rename to patches/server/0494-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch diff --git a/patches/server/0494-Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server/0495-Do-not-let-the-server-load-chunks-from-newer-version.patch similarity index 100% rename from patches/server/0494-Do-not-let-the-server-load-chunks-from-newer-version.patch rename to patches/server/0495-Do-not-let-the-server-load-chunks-from-newer-version.patch diff --git a/patches/server/0495-Brand-support.patch b/patches/server/0496-Brand-support.patch similarity index 100% rename from patches/server/0495-Brand-support.patch rename to patches/server/0496-Brand-support.patch diff --git a/patches/server/0496-Add-setMaxPlayers-API.patch b/patches/server/0497-Add-setMaxPlayers-API.patch similarity index 100% rename from patches/server/0496-Add-setMaxPlayers-API.patch rename to patches/server/0497-Add-setMaxPlayers-API.patch diff --git a/patches/server/0497-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server/0498-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from patches/server/0497-Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/server/0498-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/patches/server/0498-Don-t-require-FACING-data.patch b/patches/server/0499-Don-t-require-FACING-data.patch similarity index 100% rename from patches/server/0498-Don-t-require-FACING-data.patch rename to patches/server/0499-Don-t-require-FACING-data.patch diff --git a/patches/server/0499-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server/0500-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch similarity index 100% rename from patches/server/0499-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch rename to patches/server/0500-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch diff --git a/patches/server/0500-Add-moon-phase-API.patch b/patches/server/0501-Add-moon-phase-API.patch similarity index 100% rename from patches/server/0500-Add-moon-phase-API.patch rename to patches/server/0501-Add-moon-phase-API.patch diff --git a/patches/server/0501-Prevent-headless-pistons-from-being-created.patch b/patches/server/0502-Prevent-headless-pistons-from-being-created.patch similarity index 100% rename from patches/server/0501-Prevent-headless-pistons-from-being-created.patch rename to patches/server/0502-Prevent-headless-pistons-from-being-created.patch diff --git a/patches/server/0502-Add-BellRingEvent.patch b/patches/server/0503-Add-BellRingEvent.patch similarity index 100% rename from patches/server/0502-Add-BellRingEvent.patch rename to patches/server/0503-Add-BellRingEvent.patch diff --git a/patches/server/0503-Add-zombie-targets-turtle-egg-config.patch b/patches/server/0504-Add-zombie-targets-turtle-egg-config.patch similarity index 100% rename from patches/server/0503-Add-zombie-targets-turtle-egg-config.patch rename to patches/server/0504-Add-zombie-targets-turtle-egg-config.patch diff --git a/patches/server/0504-Buffer-joins-to-world.patch b/patches/server/0505-Buffer-joins-to-world.patch similarity index 100% rename from patches/server/0504-Buffer-joins-to-world.patch rename to patches/server/0505-Buffer-joins-to-world.patch diff --git a/patches/server/0505-Optimize-redstone-algorithm.patch b/patches/server/0506-Optimize-redstone-algorithm.patch similarity index 100% rename from patches/server/0505-Optimize-redstone-algorithm.patch rename to patches/server/0506-Optimize-redstone-algorithm.patch diff --git a/patches/server/0506-Fix-hex-colors-not-working-in-some-kick-messages.patch b/patches/server/0507-Fix-hex-colors-not-working-in-some-kick-messages.patch similarity index 100% rename from patches/server/0506-Fix-hex-colors-not-working-in-some-kick-messages.patch rename to patches/server/0507-Fix-hex-colors-not-working-in-some-kick-messages.patch diff --git a/patches/server/0507-PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server/0508-PortalCreateEvent-needs-to-know-its-entity.patch similarity index 100% rename from patches/server/0507-PortalCreateEvent-needs-to-know-its-entity.patch rename to patches/server/0508-PortalCreateEvent-needs-to-know-its-entity.patch diff --git a/patches/server/0508-Fix-CraftTeam-null-check.patch b/patches/server/0509-Fix-CraftTeam-null-check.patch similarity index 100% rename from patches/server/0508-Fix-CraftTeam-null-check.patch rename to patches/server/0509-Fix-CraftTeam-null-check.patch diff --git a/patches/server/0509-Add-more-Evoker-API.patch b/patches/server/0510-Add-more-Evoker-API.patch similarity index 100% rename from patches/server/0509-Add-more-Evoker-API.patch rename to patches/server/0510-Add-more-Evoker-API.patch diff --git a/patches/server/0510-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/server/0511-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 100% rename from patches/server/0510-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to patches/server/0511-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch diff --git a/patches/server/0511-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server/0512-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 100% rename from patches/server/0511-Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/server/0512-Create-HoverEvent-from-ItemStack-Entity.patch diff --git a/patches/server/0512-Cache-block-data-strings.patch b/patches/server/0513-Cache-block-data-strings.patch similarity index 100% rename from patches/server/0512-Cache-block-data-strings.patch rename to patches/server/0513-Cache-block-data-strings.patch diff --git a/patches/server/0513-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/patches/server/0514-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch similarity index 98% rename from patches/server/0513-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch rename to patches/server/0514-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch index 8599c641f4..3689035e0e 100644 --- a/patches/server/0513-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch +++ b/patches/server/0514-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch @@ -57,7 +57,7 @@ index 0f37c205fe401126a19191fb5382cc1b4d3f43b4..b964efb6afb090ffec505493e9bbbb88 this.setYRot(yaw); this.setXRot(pitch); diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 68ce2732dfdc25ddadc15c43c30a609f9b1eba86..c741f8e4a4b67d1bfed2d1bac36856c5688bb161 100644 +index a87531f4669c7947e02764b5ceb098385ad99159..9228c0bc797fb95c8ac949bdc568eadafee84a80 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java @@ -170,6 +170,7 @@ public abstract class BaseSpawner { diff --git a/patches/server/0514-Add-additional-open-container-api-to-HumanEntity.patch b/patches/server/0515-Add-additional-open-container-api-to-HumanEntity.patch similarity index 100% rename from patches/server/0514-Add-additional-open-container-api-to-HumanEntity.patch rename to patches/server/0515-Add-additional-open-container-api-to-HumanEntity.patch diff --git a/patches/server/0515-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/patches/server/0516-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch similarity index 100% rename from patches/server/0515-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch rename to patches/server/0516-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch diff --git a/patches/server/0516-Extend-block-drop-capture-to-capture-all-items-added.patch b/patches/server/0517-Extend-block-drop-capture-to-capture-all-items-added.patch similarity index 100% rename from patches/server/0516-Extend-block-drop-capture-to-capture-all-items-added.patch rename to patches/server/0517-Extend-block-drop-capture-to-capture-all-items-added.patch diff --git a/patches/server/0517-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server/0518-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch similarity index 100% rename from patches/server/0517-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch rename to patches/server/0518-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch diff --git a/patches/server/0518-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server/0519-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 100% rename from patches/server/0518-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to patches/server/0519-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch diff --git a/patches/server/0519-Lazily-track-plugin-scoreboards-by-default.patch b/patches/server/0520-Lazily-track-plugin-scoreboards-by-default.patch similarity index 100% rename from patches/server/0519-Lazily-track-plugin-scoreboards-by-default.patch rename to patches/server/0520-Lazily-track-plugin-scoreboards-by-default.patch diff --git a/patches/server/0520-Entity-isTicking.patch b/patches/server/0521-Entity-isTicking.patch similarity index 100% rename from patches/server/0520-Entity-isTicking.patch rename to patches/server/0521-Entity-isTicking.patch diff --git a/patches/server/0521-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/patches/server/0522-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch similarity index 100% rename from patches/server/0521-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch rename to patches/server/0522-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch diff --git a/patches/server/0522-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/patches/server/0523-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch similarity index 100% rename from patches/server/0522-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch rename to patches/server/0523-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch diff --git a/patches/server/0523-Reset-Ender-Crystals-on-Dragon-Spawn.patch b/patches/server/0524-Reset-Ender-Crystals-on-Dragon-Spawn.patch similarity index 100% rename from patches/server/0523-Reset-Ender-Crystals-on-Dragon-Spawn.patch rename to patches/server/0524-Reset-Ender-Crystals-on-Dragon-Spawn.patch diff --git a/patches/server/0524-Fix-for-large-move-vectors-crashing-server.patch b/patches/server/0525-Fix-for-large-move-vectors-crashing-server.patch similarity index 100% rename from patches/server/0524-Fix-for-large-move-vectors-crashing-server.patch rename to patches/server/0525-Fix-for-large-move-vectors-crashing-server.patch diff --git a/patches/server/0525-Optimise-getType-calls.patch b/patches/server/0526-Optimise-getType-calls.patch similarity index 100% rename from patches/server/0525-Optimise-getType-calls.patch rename to patches/server/0526-Optimise-getType-calls.patch diff --git a/patches/server/0526-Villager-resetOffers.patch b/patches/server/0527-Villager-resetOffers.patch similarity index 100% rename from patches/server/0526-Villager-resetOffers.patch rename to patches/server/0527-Villager-resetOffers.patch diff --git a/patches/server/0527-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/patches/server/0528-Improve-inlinig-for-some-hot-IBlockData-methods.patch similarity index 100% rename from patches/server/0527-Improve-inlinig-for-some-hot-IBlockData-methods.patch rename to patches/server/0528-Improve-inlinig-for-some-hot-IBlockData-methods.patch diff --git a/patches/server/0528-Retain-block-place-order-when-capturing-blockstates.patch b/patches/server/0529-Retain-block-place-order-when-capturing-blockstates.patch similarity index 100% rename from patches/server/0528-Retain-block-place-order-when-capturing-blockstates.patch rename to patches/server/0529-Retain-block-place-order-when-capturing-blockstates.patch diff --git a/patches/server/0529-Reduce-blockpos-allocation-from-pathfinding.patch b/patches/server/0530-Reduce-blockpos-allocation-from-pathfinding.patch similarity index 100% rename from patches/server/0529-Reduce-blockpos-allocation-from-pathfinding.patch rename to patches/server/0530-Reduce-blockpos-allocation-from-pathfinding.patch diff --git a/patches/server/0530-Fix-item-locations-dropped-from-campfires.patch b/patches/server/0531-Fix-item-locations-dropped-from-campfires.patch similarity index 100% rename from patches/server/0530-Fix-item-locations-dropped-from-campfires.patch rename to patches/server/0531-Fix-item-locations-dropped-from-campfires.patch diff --git a/patches/server/0531-Player-elytra-boost-API.patch b/patches/server/0532-Player-elytra-boost-API.patch similarity index 100% rename from patches/server/0531-Player-elytra-boost-API.patch rename to patches/server/0532-Player-elytra-boost-API.patch diff --git a/patches/server/0532-Fixed-TileEntityBell-memory-leak.patch b/patches/server/0533-Fixed-TileEntityBell-memory-leak.patch similarity index 100% rename from patches/server/0532-Fixed-TileEntityBell-memory-leak.patch rename to patches/server/0533-Fixed-TileEntityBell-memory-leak.patch diff --git a/patches/server/0533-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/patches/server/0534-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch similarity index 100% rename from patches/server/0533-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch rename to patches/server/0534-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch diff --git a/patches/server/0534-Add-getOfflinePlayerIfCached-String.patch b/patches/server/0535-Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from patches/server/0534-Add-getOfflinePlayerIfCached-String.patch rename to patches/server/0535-Add-getOfflinePlayerIfCached-String.patch diff --git a/patches/server/0535-Add-ignore-discounts-API.patch b/patches/server/0536-Add-ignore-discounts-API.patch similarity index 100% rename from patches/server/0535-Add-ignore-discounts-API.patch rename to patches/server/0536-Add-ignore-discounts-API.patch diff --git a/patches/server/0536-Toggle-for-removing-existing-dragon.patch b/patches/server/0537-Toggle-for-removing-existing-dragon.patch similarity index 100% rename from patches/server/0536-Toggle-for-removing-existing-dragon.patch rename to patches/server/0537-Toggle-for-removing-existing-dragon.patch diff --git a/patches/server/0537-Fix-client-lag-on-advancement-loading.patch b/patches/server/0538-Fix-client-lag-on-advancement-loading.patch similarity index 100% rename from patches/server/0537-Fix-client-lag-on-advancement-loading.patch rename to patches/server/0538-Fix-client-lag-on-advancement-loading.patch diff --git a/patches/server/0538-Item-no-age-no-player-pickup.patch b/patches/server/0539-Item-no-age-no-player-pickup.patch similarity index 100% rename from patches/server/0538-Item-no-age-no-player-pickup.patch rename to patches/server/0539-Item-no-age-no-player-pickup.patch diff --git a/patches/server/0539-Beacon-API-custom-effect-ranges.patch b/patches/server/0540-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from patches/server/0539-Beacon-API-custom-effect-ranges.patch rename to patches/server/0540-Beacon-API-custom-effect-ranges.patch diff --git a/patches/server/0540-Add-API-for-quit-reason.patch b/patches/server/0541-Add-API-for-quit-reason.patch similarity index 100% rename from patches/server/0540-Add-API-for-quit-reason.patch rename to patches/server/0541-Add-API-for-quit-reason.patch diff --git a/patches/server/0541-Seed-based-feature-search.patch b/patches/server/0542-Seed-based-feature-search.patch similarity index 100% rename from patches/server/0541-Seed-based-feature-search.patch rename to patches/server/0542-Seed-based-feature-search.patch diff --git a/patches/server/0542-Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server/0543-Add-Wandering-Trader-spawn-rate-config-options.patch similarity index 100% rename from patches/server/0542-Add-Wandering-Trader-spawn-rate-config-options.patch rename to patches/server/0543-Add-Wandering-Trader-spawn-rate-config-options.patch diff --git a/patches/server/0543-Significantly-improve-performance-of-the-end-generat.patch b/patches/server/0544-Significantly-improve-performance-of-the-end-generat.patch similarity index 100% rename from patches/server/0543-Significantly-improve-performance-of-the-end-generat.patch rename to patches/server/0544-Significantly-improve-performance-of-the-end-generat.patch diff --git a/patches/server/0544-Expose-world-spawn-angle.patch b/patches/server/0545-Expose-world-spawn-angle.patch similarity index 100% rename from patches/server/0544-Expose-world-spawn-angle.patch rename to patches/server/0545-Expose-world-spawn-angle.patch diff --git a/patches/server/0545-Add-Destroy-Speed-API.patch b/patches/server/0546-Add-Destroy-Speed-API.patch similarity index 100% rename from patches/server/0545-Add-Destroy-Speed-API.patch rename to patches/server/0546-Add-Destroy-Speed-API.patch diff --git a/patches/server/0546-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/patches/server/0547-Fix-Player-spawnParticle-x-y-z-precision-loss.patch similarity index 100% rename from patches/server/0546-Fix-Player-spawnParticle-x-y-z-precision-loss.patch rename to patches/server/0547-Fix-Player-spawnParticle-x-y-z-precision-loss.patch diff --git a/patches/server/0547-Add-LivingEntity-clearActiveItem.patch b/patches/server/0548-Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from patches/server/0547-Add-LivingEntity-clearActiveItem.patch rename to patches/server/0548-Add-LivingEntity-clearActiveItem.patch diff --git a/patches/server/0548-Add-PlayerItemCooldownEvent.patch b/patches/server/0549-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from patches/server/0548-Add-PlayerItemCooldownEvent.patch rename to patches/server/0549-Add-PlayerItemCooldownEvent.patch diff --git a/patches/server/0549-More-lightning-API.patch b/patches/server/0550-More-lightning-API.patch similarity index 100% rename from patches/server/0549-More-lightning-API.patch rename to patches/server/0550-More-lightning-API.patch diff --git a/patches/server/0550-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/0551-Climbing-should-not-bypass-cramming-gamerule.patch similarity index 100% rename from patches/server/0550-Climbing-should-not-bypass-cramming-gamerule.patch rename to patches/server/0551-Climbing-should-not-bypass-cramming-gamerule.patch diff --git a/patches/server/0551-Added-missing-default-perms-for-commands.patch b/patches/server/0552-Added-missing-default-perms-for-commands.patch similarity index 100% rename from patches/server/0551-Added-missing-default-perms-for-commands.patch rename to patches/server/0552-Added-missing-default-perms-for-commands.patch diff --git a/patches/server/0552-Add-PlayerShearBlockEvent.patch b/patches/server/0553-Add-PlayerShearBlockEvent.patch similarity index 100% rename from patches/server/0552-Add-PlayerShearBlockEvent.patch rename to patches/server/0553-Add-PlayerShearBlockEvent.patch diff --git a/patches/server/0553-Set-spigots-verbose-world-setting-to-false-by-def.patch b/patches/server/0554-Set-spigots-verbose-world-setting-to-false-by-def.patch similarity index 100% rename from patches/server/0553-Set-spigots-verbose-world-setting-to-false-by-def.patch rename to patches/server/0554-Set-spigots-verbose-world-setting-to-false-by-def.patch diff --git a/patches/server/0554-Fix-curing-zombie-villager-discount-exploit.patch b/patches/server/0555-Fix-curing-zombie-villager-discount-exploit.patch similarity index 100% rename from patches/server/0554-Fix-curing-zombie-villager-discount-exploit.patch rename to patches/server/0555-Fix-curing-zombie-villager-discount-exploit.patch diff --git a/patches/server/0555-Limit-recipe-packets.patch b/patches/server/0556-Limit-recipe-packets.patch similarity index 100% rename from patches/server/0555-Limit-recipe-packets.patch rename to patches/server/0556-Limit-recipe-packets.patch diff --git a/patches/server/0556-Fix-CraftSound-backwards-compatibility.patch b/patches/server/0557-Fix-CraftSound-backwards-compatibility.patch similarity index 100% rename from patches/server/0556-Fix-CraftSound-backwards-compatibility.patch rename to patches/server/0557-Fix-CraftSound-backwards-compatibility.patch diff --git a/patches/server/0557-MC-4-Fix-item-position-desync.patch b/patches/server/0558-MC-4-Fix-item-position-desync.patch similarity index 100% rename from patches/server/0557-MC-4-Fix-item-position-desync.patch rename to patches/server/0558-MC-4-Fix-item-position-desync.patch diff --git a/patches/server/0558-Player-Chunk-Load-Unload-Events.patch b/patches/server/0559-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from patches/server/0558-Player-Chunk-Load-Unload-Events.patch rename to patches/server/0559-Player-Chunk-Load-Unload-Events.patch diff --git a/patches/server/0559-Optimize-Dynamic-get-Missing-Keys.patch b/patches/server/0560-Optimize-Dynamic-get-Missing-Keys.patch similarity index 100% rename from patches/server/0559-Optimize-Dynamic-get-Missing-Keys.patch rename to patches/server/0560-Optimize-Dynamic-get-Missing-Keys.patch diff --git a/patches/server/0560-Expose-LivingEntity-hurt-direction.patch b/patches/server/0561-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from patches/server/0560-Expose-LivingEntity-hurt-direction.patch rename to patches/server/0561-Expose-LivingEntity-hurt-direction.patch diff --git a/patches/server/0561-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server/0562-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from patches/server/0561-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/server/0562-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/patches/server/0562-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server/0563-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch similarity index 100% rename from patches/server/0562-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch rename to patches/server/0563-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch diff --git a/patches/server/0563-added-PlayerTradeEvent.patch b/patches/server/0564-added-PlayerTradeEvent.patch similarity index 100% rename from patches/server/0563-added-PlayerTradeEvent.patch rename to patches/server/0564-added-PlayerTradeEvent.patch diff --git a/patches/server/0564-Implement-TargetHitEvent.patch b/patches/server/0565-Implement-TargetHitEvent.patch similarity index 100% rename from patches/server/0564-Implement-TargetHitEvent.patch rename to patches/server/0565-Implement-TargetHitEvent.patch diff --git a/patches/server/0565-Additional-Block-Material-API-s.patch b/patches/server/0566-Additional-Block-Material-API-s.patch similarity index 100% rename from patches/server/0565-Additional-Block-Material-API-s.patch rename to patches/server/0566-Additional-Block-Material-API-s.patch diff --git a/patches/server/0566-Fix-harming-potion-dupe.patch b/patches/server/0567-Fix-harming-potion-dupe.patch similarity index 100% rename from patches/server/0566-Fix-harming-potion-dupe.patch rename to patches/server/0567-Fix-harming-potion-dupe.patch diff --git a/patches/server/0567-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/patches/server/0568-Implement-API-to-get-Material-from-Boats-and-Minecar.patch similarity index 100% rename from patches/server/0567-Implement-API-to-get-Material-from-Boats-and-Minecar.patch rename to patches/server/0568-Implement-API-to-get-Material-from-Boats-and-Minecar.patch diff --git a/patches/server/0568-Cache-burn-durations.patch b/patches/server/0569-Cache-burn-durations.patch similarity index 100% rename from patches/server/0568-Cache-burn-durations.patch rename to patches/server/0569-Cache-burn-durations.patch diff --git a/patches/server/0569-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server/0570-Allow-disabling-mob-spawner-spawn-egg-transformation.patch similarity index 100% rename from patches/server/0569-Allow-disabling-mob-spawner-spawn-egg-transformation.patch rename to patches/server/0570-Allow-disabling-mob-spawner-spawn-egg-transformation.patch diff --git a/patches/server/0570-Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server/0571-Implement-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from patches/server/0570-Implement-PlayerFlowerPotManipulateEvent.patch rename to patches/server/0571-Implement-PlayerFlowerPotManipulateEvent.patch diff --git a/patches/server/0571-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server/0572-Fix-interact-event-not-being-called-in-adventure.patch similarity index 100% rename from patches/server/0571-Fix-interact-event-not-being-called-in-adventure.patch rename to patches/server/0572-Fix-interact-event-not-being-called-in-adventure.patch diff --git a/patches/server/0572-Zombie-API-breaking-doors.patch b/patches/server/0573-Zombie-API-breaking-doors.patch similarity index 100% rename from patches/server/0572-Zombie-API-breaking-doors.patch rename to patches/server/0573-Zombie-API-breaking-doors.patch diff --git a/patches/server/0573-Fix-nerfed-slime-when-splitting.patch b/patches/server/0574-Fix-nerfed-slime-when-splitting.patch similarity index 100% rename from patches/server/0573-Fix-nerfed-slime-when-splitting.patch rename to patches/server/0574-Fix-nerfed-slime-when-splitting.patch diff --git a/patches/server/0574-Add-EntityLoadCrossbowEvent.patch b/patches/server/0575-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from patches/server/0574-Add-EntityLoadCrossbowEvent.patch rename to patches/server/0575-Add-EntityLoadCrossbowEvent.patch diff --git a/patches/server/0575-Guardian-beam-workaround.patch b/patches/server/0576-Guardian-beam-workaround.patch similarity index 100% rename from patches/server/0575-Guardian-beam-workaround.patch rename to patches/server/0576-Guardian-beam-workaround.patch diff --git a/patches/server/0576-Added-WorldGameRuleChangeEvent.patch b/patches/server/0577-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from patches/server/0576-Added-WorldGameRuleChangeEvent.patch rename to patches/server/0577-Added-WorldGameRuleChangeEvent.patch diff --git a/patches/server/0577-Added-ServerResourcesReloadedEvent.patch b/patches/server/0578-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from patches/server/0577-Added-ServerResourcesReloadedEvent.patch rename to patches/server/0578-Added-ServerResourcesReloadedEvent.patch diff --git a/patches/server/0578-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server/0579-Added-world-settings-for-mobs-picking-up-loot.patch similarity index 100% rename from patches/server/0578-Added-world-settings-for-mobs-picking-up-loot.patch rename to patches/server/0579-Added-world-settings-for-mobs-picking-up-loot.patch diff --git a/patches/server/0579-Implemented-BlockFailedDispenseEvent.patch b/patches/server/0580-Implemented-BlockFailedDispenseEvent.patch similarity index 100% rename from patches/server/0579-Implemented-BlockFailedDispenseEvent.patch rename to patches/server/0580-Implemented-BlockFailedDispenseEvent.patch diff --git a/patches/server/0580-Added-PlayerLecternPageChangeEvent.patch b/patches/server/0581-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from patches/server/0580-Added-PlayerLecternPageChangeEvent.patch rename to patches/server/0581-Added-PlayerLecternPageChangeEvent.patch diff --git a/patches/server/0581-Added-PlayerLoomPatternSelectEvent.patch b/patches/server/0582-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from patches/server/0581-Added-PlayerLoomPatternSelectEvent.patch rename to patches/server/0582-Added-PlayerLoomPatternSelectEvent.patch diff --git a/patches/server/0582-Configurable-door-breaking-difficulty.patch b/patches/server/0583-Configurable-door-breaking-difficulty.patch similarity index 100% rename from patches/server/0582-Configurable-door-breaking-difficulty.patch rename to patches/server/0583-Configurable-door-breaking-difficulty.patch diff --git a/patches/server/0583-Empty-commands-shall-not-be-dispatched.patch b/patches/server/0584-Empty-commands-shall-not-be-dispatched.patch similarity index 100% rename from patches/server/0583-Empty-commands-shall-not-be-dispatched.patch rename to patches/server/0584-Empty-commands-shall-not-be-dispatched.patch diff --git a/patches/server/0584-Implement-API-to-expose-exact-interaction-point.patch b/patches/server/0585-Implement-API-to-expose-exact-interaction-point.patch similarity index 100% rename from patches/server/0584-Implement-API-to-expose-exact-interaction-point.patch rename to patches/server/0585-Implement-API-to-expose-exact-interaction-point.patch diff --git a/patches/server/0585-Remove-stale-POIs.patch b/patches/server/0586-Remove-stale-POIs.patch similarity index 100% rename from patches/server/0585-Remove-stale-POIs.patch rename to patches/server/0586-Remove-stale-POIs.patch diff --git a/patches/server/0586-Fix-villager-boat-exploit.patch b/patches/server/0587-Fix-villager-boat-exploit.patch similarity index 100% rename from patches/server/0586-Fix-villager-boat-exploit.patch rename to patches/server/0587-Fix-villager-boat-exploit.patch diff --git a/patches/server/0587-Add-sendOpLevel-API.patch b/patches/server/0588-Add-sendOpLevel-API.patch similarity index 100% rename from patches/server/0587-Add-sendOpLevel-API.patch rename to patches/server/0588-Add-sendOpLevel-API.patch diff --git a/patches/server/0588-Add-StructureLocateEvent.patch b/patches/server/0589-Add-StructureLocateEvent.patch similarity index 100% rename from patches/server/0588-Add-StructureLocateEvent.patch rename to patches/server/0589-Add-StructureLocateEvent.patch diff --git a/patches/server/0589-Collision-option-for-requiring-a-player-participant.patch b/patches/server/0590-Collision-option-for-requiring-a-player-participant.patch similarity index 100% rename from patches/server/0589-Collision-option-for-requiring-a-player-participant.patch rename to patches/server/0590-Collision-option-for-requiring-a-player-participant.patch diff --git a/patches/server/0590-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/patches/server/0591-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch similarity index 100% rename from patches/server/0590-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch rename to patches/server/0591-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch diff --git a/patches/server/0591-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/server/0592-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from patches/server/0591-Return-chat-component-with-empty-text-instead-of-thr.patch rename to patches/server/0592-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/patches/server/0592-Make-schedule-command-per-world.patch b/patches/server/0593-Make-schedule-command-per-world.patch similarity index 100% rename from patches/server/0592-Make-schedule-command-per-world.patch rename to patches/server/0593-Make-schedule-command-per-world.patch diff --git a/patches/server/0593-Configurable-max-leash-distance.patch b/patches/server/0594-Configurable-max-leash-distance.patch similarity index 100% rename from patches/server/0593-Configurable-max-leash-distance.patch rename to patches/server/0594-Configurable-max-leash-distance.patch diff --git a/patches/server/0594-Implement-BlockPreDispenseEvent.patch b/patches/server/0595-Implement-BlockPreDispenseEvent.patch similarity index 100% rename from patches/server/0594-Implement-BlockPreDispenseEvent.patch rename to patches/server/0595-Implement-BlockPreDispenseEvent.patch diff --git a/patches/server/0595-Added-Vanilla-Entity-Tags.patch b/patches/server/0596-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from patches/server/0595-Added-Vanilla-Entity-Tags.patch rename to patches/server/0596-Added-Vanilla-Entity-Tags.patch diff --git a/patches/server/0596-added-Wither-API.patch b/patches/server/0597-added-Wither-API.patch similarity index 100% rename from patches/server/0596-added-Wither-API.patch rename to patches/server/0597-added-Wither-API.patch diff --git a/patches/server/0597-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/patches/server/0598-Added-firing-of-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from patches/server/0597-Added-firing-of-PlayerChangeBeaconEffectEvent.patch rename to patches/server/0598-Added-firing-of-PlayerChangeBeaconEffectEvent.patch diff --git a/patches/server/0598-Fix-console-spam-when-removing-chests-in-water.patch b/patches/server/0599-Fix-console-spam-when-removing-chests-in-water.patch similarity index 100% rename from patches/server/0598-Fix-console-spam-when-removing-chests-in-water.patch rename to patches/server/0599-Fix-console-spam-when-removing-chests-in-water.patch diff --git a/patches/server/0599-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server/0600-Add-toggle-for-always-placing-the-dragon-egg.patch similarity index 100% rename from patches/server/0599-Add-toggle-for-always-placing-the-dragon-egg.patch rename to patches/server/0600-Add-toggle-for-always-placing-the-dragon-egg.patch diff --git a/patches/server/0600-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server/0601-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from patches/server/0600-Added-PlayerStonecutterRecipeSelectEvent.patch rename to patches/server/0601-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/patches/server/0601-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/server/0602-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from patches/server/0601-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/server/0602-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/patches/server/0602-Skip-distance-map-update-when-spawning-disabled.patch b/patches/server/0603-Skip-distance-map-update-when-spawning-disabled.patch similarity index 100% rename from patches/server/0602-Skip-distance-map-update-when-spawning-disabled.patch rename to patches/server/0603-Skip-distance-map-update-when-spawning-disabled.patch diff --git a/patches/server/0603-Reset-shield-blocking-on-dimension-change.patch b/patches/server/0604-Reset-shield-blocking-on-dimension-change.patch similarity index 100% rename from patches/server/0603-Reset-shield-blocking-on-dimension-change.patch rename to patches/server/0604-Reset-shield-blocking-on-dimension-change.patch diff --git a/patches/server/0604-add-DragonEggFormEvent.patch b/patches/server/0605-add-DragonEggFormEvent.patch similarity index 100% rename from patches/server/0604-add-DragonEggFormEvent.patch rename to patches/server/0605-add-DragonEggFormEvent.patch diff --git a/patches/server/0605-EntityMoveEvent.patch b/patches/server/0606-EntityMoveEvent.patch similarity index 100% rename from patches/server/0605-EntityMoveEvent.patch rename to patches/server/0606-EntityMoveEvent.patch diff --git a/patches/server/0606-added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server/0607-added-option-to-disable-pathfinding-updates-on-block.patch similarity index 100% rename from patches/server/0606-added-option-to-disable-pathfinding-updates-on-block.patch rename to patches/server/0607-added-option-to-disable-pathfinding-updates-on-block.patch diff --git a/patches/server/0607-Inline-shift-direction-fields.patch b/patches/server/0608-Inline-shift-direction-fields.patch similarity index 100% rename from patches/server/0607-Inline-shift-direction-fields.patch rename to patches/server/0608-Inline-shift-direction-fields.patch diff --git a/patches/server/0608-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server/0609-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from patches/server/0608-Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/server/0609-Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/patches/server/0609-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/server/0610-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from patches/server/0609-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/server/0610-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/patches/server/0610-living-entity-allow-attribute-registration.patch b/patches/server/0611-living-entity-allow-attribute-registration.patch similarity index 100% rename from patches/server/0610-living-entity-allow-attribute-registration.patch rename to patches/server/0611-living-entity-allow-attribute-registration.patch diff --git a/patches/server/0611-fix-dead-slime-setSize-invincibility.patch b/patches/server/0612-fix-dead-slime-setSize-invincibility.patch similarity index 100% rename from patches/server/0611-fix-dead-slime-setSize-invincibility.patch rename to patches/server/0612-fix-dead-slime-setSize-invincibility.patch diff --git a/patches/server/0612-Merchant-getRecipes-should-return-an-immutable-list.patch b/patches/server/0613-Merchant-getRecipes-should-return-an-immutable-list.patch similarity index 100% rename from patches/server/0612-Merchant-getRecipes-should-return-an-immutable-list.patch rename to patches/server/0613-Merchant-getRecipes-should-return-an-immutable-list.patch diff --git a/patches/server/0613-misc-debugging-dumps.patch b/patches/server/0614-misc-debugging-dumps.patch similarity index 100% rename from patches/server/0613-misc-debugging-dumps.patch rename to patches/server/0614-misc-debugging-dumps.patch diff --git a/patches/server/0614-Add-support-for-hex-color-codes-in-console.patch b/patches/server/0615-Add-support-for-hex-color-codes-in-console.patch similarity index 100% rename from patches/server/0614-Add-support-for-hex-color-codes-in-console.patch rename to patches/server/0615-Add-support-for-hex-color-codes-in-console.patch diff --git a/patches/server/0615-Expose-Tracked-Players.patch b/patches/server/0616-Expose-Tracked-Players.patch similarity index 100% rename from patches/server/0615-Expose-Tracked-Players.patch rename to patches/server/0616-Expose-Tracked-Players.patch diff --git a/patches/server/0616-Remove-streams-from-SensorNearest.patch b/patches/server/0617-Remove-streams-from-SensorNearest.patch similarity index 100% rename from patches/server/0616-Remove-streams-from-SensorNearest.patch rename to patches/server/0617-Remove-streams-from-SensorNearest.patch diff --git a/patches/server/0617-MC-29274-Fix-Wither-hostility-towards-players.patch b/patches/server/0618-MC-29274-Fix-Wither-hostility-towards-players.patch similarity index 100% rename from patches/server/0617-MC-29274-Fix-Wither-hostility-towards-players.patch rename to patches/server/0618-MC-29274-Fix-Wither-hostility-towards-players.patch diff --git a/patches/server/0618-Throw-proper-exception-on-empty-JsonList-file.patch b/patches/server/0619-Throw-proper-exception-on-empty-JsonList-file.patch similarity index 100% rename from patches/server/0618-Throw-proper-exception-on-empty-JsonList-file.patch rename to patches/server/0619-Throw-proper-exception-on-empty-JsonList-file.patch diff --git a/patches/server/0619-Improve-ServerGUI.patch b/patches/server/0620-Improve-ServerGUI.patch similarity index 100% rename from patches/server/0619-Improve-ServerGUI.patch rename to patches/server/0620-Improve-ServerGUI.patch diff --git a/patches/server/0620-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/patches/server/0621-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch similarity index 100% rename from patches/server/0620-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch rename to patches/server/0621-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch diff --git a/patches/server/0621-fix-converting-txt-to-json-file.patch b/patches/server/0622-fix-converting-txt-to-json-file.patch similarity index 100% rename from patches/server/0621-fix-converting-txt-to-json-file.patch rename to patches/server/0622-fix-converting-txt-to-json-file.patch diff --git a/patches/server/0622-Add-worldborder-events.patch b/patches/server/0623-Add-worldborder-events.patch similarity index 100% rename from patches/server/0622-Add-worldborder-events.patch rename to patches/server/0623-Add-worldborder-events.patch diff --git a/patches/server/0623-added-PlayerNameEntityEvent.patch b/patches/server/0624-added-PlayerNameEntityEvent.patch similarity index 100% rename from patches/server/0623-added-PlayerNameEntityEvent.patch rename to patches/server/0624-added-PlayerNameEntityEvent.patch diff --git a/patches/server/0624-Prevent-grindstones-from-overstacking-items.patch b/patches/server/0625-Prevent-grindstones-from-overstacking-items.patch similarity index 100% rename from patches/server/0624-Prevent-grindstones-from-overstacking-items.patch rename to patches/server/0625-Prevent-grindstones-from-overstacking-items.patch diff --git a/patches/server/0625-Add-recipe-to-cook-events.patch b/patches/server/0626-Add-recipe-to-cook-events.patch similarity index 100% rename from patches/server/0625-Add-recipe-to-cook-events.patch rename to patches/server/0626-Add-recipe-to-cook-events.patch diff --git a/patches/server/0626-Add-Block-isValidTool.patch b/patches/server/0627-Add-Block-isValidTool.patch similarity index 100% rename from patches/server/0626-Add-Block-isValidTool.patch rename to patches/server/0627-Add-Block-isValidTool.patch diff --git a/patches/server/0627-Allow-using-signs-inside-spawn-protection.patch b/patches/server/0628-Allow-using-signs-inside-spawn-protection.patch similarity index 100% rename from patches/server/0627-Allow-using-signs-inside-spawn-protection.patch rename to patches/server/0628-Allow-using-signs-inside-spawn-protection.patch diff --git a/patches/server/0628-Implement-Keyed-on-World.patch b/patches/server/0629-Implement-Keyed-on-World.patch similarity index 100% rename from patches/server/0628-Implement-Keyed-on-World.patch rename to patches/server/0629-Implement-Keyed-on-World.patch diff --git a/patches/server/0629-Add-fast-alternative-constructor-for-Rotations.patch b/patches/server/0630-Add-fast-alternative-constructor-for-Rotations.patch similarity index 100% rename from patches/server/0629-Add-fast-alternative-constructor-for-Rotations.patch rename to patches/server/0630-Add-fast-alternative-constructor-for-Rotations.patch diff --git a/patches/server/0630-Item-Rarity-API.patch b/patches/server/0631-Item-Rarity-API.patch similarity index 100% rename from patches/server/0630-Item-Rarity-API.patch rename to patches/server/0631-Item-Rarity-API.patch diff --git a/patches/server/0631-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/patches/server/0632-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch similarity index 100% rename from patches/server/0631-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch rename to patches/server/0632-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch diff --git a/patches/server/0632-copy-TESign-isEditable-from-snapshots.patch b/patches/server/0633-copy-TESign-isEditable-from-snapshots.patch similarity index 100% rename from patches/server/0632-copy-TESign-isEditable-from-snapshots.patch rename to patches/server/0633-copy-TESign-isEditable-from-snapshots.patch diff --git a/patches/server/0633-Drop-carried-item-when-player-has-disconnected.patch b/patches/server/0634-Drop-carried-item-when-player-has-disconnected.patch similarity index 100% rename from patches/server/0633-Drop-carried-item-when-player-has-disconnected.patch rename to patches/server/0634-Drop-carried-item-when-player-has-disconnected.patch diff --git a/patches/server/0634-forced-whitelist-use-configurable-kick-message.patch b/patches/server/0635-forced-whitelist-use-configurable-kick-message.patch similarity index 100% rename from patches/server/0634-forced-whitelist-use-configurable-kick-message.patch rename to patches/server/0635-forced-whitelist-use-configurable-kick-message.patch diff --git a/patches/server/0635-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/patches/server/0636-Don-t-ignore-result-of-PlayerEditBookEvent.patch similarity index 100% rename from patches/server/0635-Don-t-ignore-result-of-PlayerEditBookEvent.patch rename to patches/server/0636-Don-t-ignore-result-of-PlayerEditBookEvent.patch diff --git a/patches/server/0636-fix-cancelling-block-falling-causing-client-desync.patch b/patches/server/0637-fix-cancelling-block-falling-causing-client-desync.patch similarity index 100% rename from patches/server/0636-fix-cancelling-block-falling-causing-client-desync.patch rename to patches/server/0637-fix-cancelling-block-falling-causing-client-desync.patch diff --git a/patches/server/0637-Expose-protocol-version.patch b/patches/server/0638-Expose-protocol-version.patch similarity index 100% rename from patches/server/0637-Expose-protocol-version.patch rename to patches/server/0638-Expose-protocol-version.patch diff --git a/patches/server/0638-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/server/0639-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 100% rename from patches/server/0638-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to patches/server/0639-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch diff --git a/patches/server/0639-Enhance-console-tab-completions-for-brigadier-comman.patch b/patches/server/0640-Enhance-console-tab-completions-for-brigadier-comman.patch similarity index 100% rename from patches/server/0639-Enhance-console-tab-completions-for-brigadier-comman.patch rename to patches/server/0640-Enhance-console-tab-completions-for-brigadier-comman.patch diff --git a/patches/server/0640-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/patches/server/0641-Fix-PlayerItemConsumeEvent-cancelling-properly.patch similarity index 100% rename from patches/server/0640-Fix-PlayerItemConsumeEvent-cancelling-properly.patch rename to patches/server/0641-Fix-PlayerItemConsumeEvent-cancelling-properly.patch diff --git a/patches/server/0641-Add-bypass-host-check.patch b/patches/server/0642-Add-bypass-host-check.patch similarity index 100% rename from patches/server/0641-Add-bypass-host-check.patch rename to patches/server/0642-Add-bypass-host-check.patch diff --git a/patches/server/0642-Set-area-affect-cloud-rotation.patch b/patches/server/0643-Set-area-affect-cloud-rotation.patch similarity index 100% rename from patches/server/0642-Set-area-affect-cloud-rotation.patch rename to patches/server/0643-Set-area-affect-cloud-rotation.patch diff --git a/patches/server/0643-add-isDeeplySleeping-to-HumanEntity.patch b/patches/server/0644-add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from patches/server/0643-add-isDeeplySleeping-to-HumanEntity.patch rename to patches/server/0644-add-isDeeplySleeping-to-HumanEntity.patch diff --git a/patches/server/0644-Fix-duplicating-give-items-on-item-drop-cancel.patch b/patches/server/0645-Fix-duplicating-give-items-on-item-drop-cancel.patch similarity index 100% rename from patches/server/0644-Fix-duplicating-give-items-on-item-drop-cancel.patch rename to patches/server/0645-Fix-duplicating-give-items-on-item-drop-cancel.patch diff --git a/patches/server/0645-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/server/0646-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from patches/server/0645-add-consumeFuel-to-FurnaceBurnEvent.patch rename to patches/server/0646-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/patches/server/0646-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/server/0647-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from patches/server/0646-add-get-set-drop-chance-to-EntityEquipment.patch rename to patches/server/0647-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/patches/server/0647-fix-PigZombieAngerEvent-cancellation.patch b/patches/server/0648-fix-PigZombieAngerEvent-cancellation.patch similarity index 100% rename from patches/server/0647-fix-PigZombieAngerEvent-cancellation.patch rename to patches/server/0648-fix-PigZombieAngerEvent-cancellation.patch diff --git a/patches/server/0648-Fix-checkReach-check-for-Shulker-boxes.patch b/patches/server/0649-Fix-checkReach-check-for-Shulker-boxes.patch similarity index 100% rename from patches/server/0648-Fix-checkReach-check-for-Shulker-boxes.patch rename to patches/server/0649-Fix-checkReach-check-for-Shulker-boxes.patch diff --git a/patches/server/0649-fix-PlayerItemHeldEvent-firing-twice.patch b/patches/server/0650-fix-PlayerItemHeldEvent-firing-twice.patch similarity index 100% rename from patches/server/0649-fix-PlayerItemHeldEvent-firing-twice.patch rename to patches/server/0650-fix-PlayerItemHeldEvent-firing-twice.patch diff --git a/patches/server/0650-Added-PlayerDeepSleepEvent.patch b/patches/server/0651-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from patches/server/0650-Added-PlayerDeepSleepEvent.patch rename to patches/server/0651-Added-PlayerDeepSleepEvent.patch diff --git a/patches/server/0651-More-World-API.patch b/patches/server/0652-More-World-API.patch similarity index 100% rename from patches/server/0651-More-World-API.patch rename to patches/server/0652-More-World-API.patch diff --git a/patches/server/0652-Added-PlayerBedFailEnterEvent.patch b/patches/server/0653-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from patches/server/0652-Added-PlayerBedFailEnterEvent.patch rename to patches/server/0653-Added-PlayerBedFailEnterEvent.patch diff --git a/patches/server/0653-Implement-methods-to-convert-between-Component-and-B.patch b/patches/server/0654-Implement-methods-to-convert-between-Component-and-B.patch similarity index 100% rename from patches/server/0653-Implement-methods-to-convert-between-Component-and-B.patch rename to patches/server/0654-Implement-methods-to-convert-between-Component-and-B.patch diff --git a/patches/server/0654-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/patches/server/0655-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch similarity index 100% rename from patches/server/0654-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch rename to patches/server/0655-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch diff --git a/patches/server/0655-Introduce-beacon-activation-deactivation-events.patch b/patches/server/0656-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from patches/server/0655-Introduce-beacon-activation-deactivation-events.patch rename to patches/server/0656-Introduce-beacon-activation-deactivation-events.patch diff --git a/patches/server/0656-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/server/0657-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from patches/server/0656-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/server/0657-add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/patches/server/0657-Add-Channel-initialization-listeners.patch b/patches/server/0658-Add-Channel-initialization-listeners.patch similarity index 100% rename from patches/server/0657-Add-Channel-initialization-listeners.patch rename to patches/server/0658-Add-Channel-initialization-listeners.patch diff --git a/patches/server/0658-Send-empty-commands-if-tab-completion-is-disabled.patch b/patches/server/0659-Send-empty-commands-if-tab-completion-is-disabled.patch similarity index 100% rename from patches/server/0658-Send-empty-commands-if-tab-completion-is-disabled.patch rename to patches/server/0659-Send-empty-commands-if-tab-completion-is-disabled.patch diff --git a/patches/server/0659-Add-more-WanderingTrader-API.patch b/patches/server/0660-Add-more-WanderingTrader-API.patch similarity index 100% rename from patches/server/0659-Add-more-WanderingTrader-API.patch rename to patches/server/0660-Add-more-WanderingTrader-API.patch diff --git a/patches/server/0660-Add-EntityBlockStorage-clearEntities.patch b/patches/server/0661-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from patches/server/0660-Add-EntityBlockStorage-clearEntities.patch rename to patches/server/0661-Add-EntityBlockStorage-clearEntities.patch diff --git a/patches/server/0661-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/server/0662-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from patches/server/0661-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to patches/server/0662-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/patches/server/0662-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/server/0663-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from patches/server/0662-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/server/0663-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/patches/server/0663-Inventory-close.patch b/patches/server/0664-Inventory-close.patch similarity index 100% rename from patches/server/0663-Inventory-close.patch rename to patches/server/0664-Inventory-close.patch diff --git a/patches/server/0664-call-PortalCreateEvent-players-and-end-platform.patch b/patches/server/0665-call-PortalCreateEvent-players-and-end-platform.patch similarity index 100% rename from patches/server/0664-call-PortalCreateEvent-players-and-end-platform.patch rename to patches/server/0665-call-PortalCreateEvent-players-and-end-platform.patch diff --git a/patches/server/0665-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/server/0666-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 100% rename from patches/server/0665-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/server/0666-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch diff --git a/patches/server/0666-Fix-CraftPotionBrewer-cache.patch b/patches/server/0667-Fix-CraftPotionBrewer-cache.patch similarity index 100% rename from patches/server/0666-Fix-CraftPotionBrewer-cache.patch rename to patches/server/0667-Fix-CraftPotionBrewer-cache.patch diff --git a/patches/server/0667-Add-basic-Datapack-API.patch b/patches/server/0668-Add-basic-Datapack-API.patch similarity index 100% rename from patches/server/0667-Add-basic-Datapack-API.patch rename to patches/server/0668-Add-basic-Datapack-API.patch diff --git a/patches/server/0668-Add-environment-variable-to-disable-server-gui.patch b/patches/server/0669-Add-environment-variable-to-disable-server-gui.patch similarity index 100% rename from patches/server/0668-Add-environment-variable-to-disable-server-gui.patch rename to patches/server/0669-Add-environment-variable-to-disable-server-gui.patch diff --git a/patches/server/0669-additions-to-PlayerGameModeChangeEvent.patch b/patches/server/0670-additions-to-PlayerGameModeChangeEvent.patch similarity index 100% rename from patches/server/0669-additions-to-PlayerGameModeChangeEvent.patch rename to patches/server/0670-additions-to-PlayerGameModeChangeEvent.patch diff --git a/patches/server/0670-ItemStack-repair-check-API.patch b/patches/server/0671-ItemStack-repair-check-API.patch similarity index 100% rename from patches/server/0670-ItemStack-repair-check-API.patch rename to patches/server/0671-ItemStack-repair-check-API.patch diff --git a/patches/server/0671-More-Enchantment-API.patch b/patches/server/0672-More-Enchantment-API.patch similarity index 100% rename from patches/server/0671-More-Enchantment-API.patch rename to patches/server/0672-More-Enchantment-API.patch diff --git a/patches/server/0672-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/server/0673-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 100% rename from patches/server/0672-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to patches/server/0673-Add-command-line-option-to-load-extra-plugin-jars-no.patch diff --git a/patches/server/0673-Fix-and-optimise-world-force-upgrading.patch b/patches/server/0674-Fix-and-optimise-world-force-upgrading.patch similarity index 100% rename from patches/server/0673-Fix-and-optimise-world-force-upgrading.patch rename to patches/server/0674-Fix-and-optimise-world-force-upgrading.patch diff --git a/patches/server/0674-Add-Mob-lookAt-API.patch b/patches/server/0675-Add-Mob-lookAt-API.patch similarity index 100% rename from patches/server/0674-Add-Mob-lookAt-API.patch rename to patches/server/0675-Add-Mob-lookAt-API.patch diff --git a/patches/server/0675-Add-Unix-domain-socket-support.patch b/patches/server/0676-Add-Unix-domain-socket-support.patch similarity index 100% rename from patches/server/0675-Add-Unix-domain-socket-support.patch rename to patches/server/0676-Add-Unix-domain-socket-support.patch diff --git a/patches/server/0676-Add-EntityInsideBlockEvent.patch b/patches/server/0677-Add-EntityInsideBlockEvent.patch similarity index 100% rename from patches/server/0676-Add-EntityInsideBlockEvent.patch rename to patches/server/0677-Add-EntityInsideBlockEvent.patch diff --git a/patches/server/0677-Attributes-API-for-item-defaults.patch b/patches/server/0678-Attributes-API-for-item-defaults.patch similarity index 100% rename from patches/server/0677-Attributes-API-for-item-defaults.patch rename to patches/server/0678-Attributes-API-for-item-defaults.patch diff --git a/patches/server/0678-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/patches/server/0679-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch similarity index 100% rename from patches/server/0678-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch rename to patches/server/0679-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch diff --git a/patches/server/0679-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/server/0680-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from patches/server/0679-Add-cause-to-Weather-ThunderChangeEvents.patch rename to patches/server/0680-Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/patches/server/0680-More-Lidded-Block-API.patch b/patches/server/0681-More-Lidded-Block-API.patch similarity index 100% rename from patches/server/0680-More-Lidded-Block-API.patch rename to patches/server/0681-More-Lidded-Block-API.patch diff --git a/patches/server/0681-Limit-item-frame-cursors-on-maps.patch b/patches/server/0682-Limit-item-frame-cursors-on-maps.patch similarity index 100% rename from patches/server/0681-Limit-item-frame-cursors-on-maps.patch rename to patches/server/0682-Limit-item-frame-cursors-on-maps.patch diff --git a/patches/server/0682-Add-PufferFishStateChangeEvent.patch b/patches/server/0683-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from patches/server/0682-Add-PufferFishStateChangeEvent.patch rename to patches/server/0683-Add-PufferFishStateChangeEvent.patch diff --git a/patches/server/0683-Add-PlayerKickEvent-causes.patch b/patches/server/0684-Add-PlayerKickEvent-causes.patch similarity index 100% rename from patches/server/0683-Add-PlayerKickEvent-causes.patch rename to patches/server/0684-Add-PlayerKickEvent-causes.patch diff --git a/patches/server/0684-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/patches/server/0685-Fix-PlayerBucketEmptyEvent-result-itemstack.patch similarity index 100% rename from patches/server/0684-Fix-PlayerBucketEmptyEvent-result-itemstack.patch rename to patches/server/0685-Fix-PlayerBucketEmptyEvent-result-itemstack.patch diff --git a/patches/server/0684-Synchronize-PalettedContainer-instead-of-ReentrantLoc.patch b/patches/server/0686-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch similarity index 100% rename from patches/server/0684-Synchronize-PalettedContainer-instead-of-ReentrantLoc.patch rename to patches/server/0686-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch diff --git a/patches/server/0685-Add-option-to-fix-items-merging-through-walls.patch b/patches/server/0687-Add-option-to-fix-items-merging-through-walls.patch similarity index 100% rename from patches/server/0685-Add-option-to-fix-items-merging-through-walls.patch rename to patches/server/0687-Add-option-to-fix-items-merging-through-walls.patch diff --git a/patches/server/0686-Add-BellRevealRaiderEvent.patch b/patches/server/0688-Add-BellRevealRaiderEvent.patch similarity index 100% rename from patches/server/0686-Add-BellRevealRaiderEvent.patch rename to patches/server/0688-Add-BellRevealRaiderEvent.patch diff --git a/patches/server/0687-Fix-invulnerable-end-crystals.patch b/patches/server/0689-Fix-invulnerable-end-crystals.patch similarity index 100% rename from patches/server/0687-Fix-invulnerable-end-crystals.patch rename to patches/server/0689-Fix-invulnerable-end-crystals.patch diff --git a/patches/server/0688-Add-ElderGuardianAppearanceEvent.patch b/patches/server/0690-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from patches/server/0688-Add-ElderGuardianAppearanceEvent.patch rename to patches/server/0690-Add-ElderGuardianAppearanceEvent.patch diff --git a/patches/server/0689-Reset-villager-inventory-on-cancelled-pickup-event.patch b/patches/server/0691-Reset-villager-inventory-on-cancelled-pickup-event.patch similarity index 100% rename from patches/server/0689-Reset-villager-inventory-on-cancelled-pickup-event.patch rename to patches/server/0691-Reset-villager-inventory-on-cancelled-pickup-event.patch diff --git a/patches/server/0690-Fix-dangerous-end-portal-logic.patch b/patches/server/0692-Fix-dangerous-end-portal-logic.patch similarity index 100% rename from patches/server/0690-Fix-dangerous-end-portal-logic.patch rename to patches/server/0692-Fix-dangerous-end-portal-logic.patch diff --git a/patches/server/0690-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/server/0693-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch similarity index 100% rename from patches/server/0690-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch rename to patches/server/0693-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch diff --git a/patches/server/0691-Make-item-validations-configurable.patch b/patches/server/0694-Make-item-validations-configurable.patch similarity index 100% rename from patches/server/0691-Make-item-validations-configurable.patch rename to patches/server/0694-Make-item-validations-configurable.patch diff --git a/patches/server/0692-Add-more-line-of-sight-methods.patch b/patches/server/0695-Add-more-line-of-sight-methods.patch similarity index 100% rename from patches/server/0692-Add-more-line-of-sight-methods.patch rename to patches/server/0695-Add-more-line-of-sight-methods.patch diff --git a/patches/server/0693-add-per-world-spawn-limits.patch b/patches/server/0696-add-per-world-spawn-limits.patch similarity index 100% rename from patches/server/0693-add-per-world-spawn-limits.patch rename to patches/server/0696-add-per-world-spawn-limits.patch diff --git a/patches/server/0694-Fix-PotionSplashEvent-for-water-splash-potions.patch b/patches/server/0697-Fix-PotionSplashEvent-for-water-splash-potions.patch similarity index 100% rename from patches/server/0694-Fix-PotionSplashEvent-for-water-splash-potions.patch rename to patches/server/0697-Fix-PotionSplashEvent-for-water-splash-potions.patch diff --git a/patches/server/0694-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/patches/server/0698-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch similarity index 100% rename from patches/server/0694-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch rename to patches/server/0698-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch From bbb8816211a36da2acf4d19dcf0fe0aca863e678 Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Tue, 15 Jun 2021 00:56:07 -0500 Subject: [PATCH 143/226] Update to paperweight 1.0.0, with automatic library imports --- build-data/library-imports.txt | 12 +++++++----- build.gradle.kts | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/build-data/library-imports.txt b/build-data/library-imports.txt index aa3c46be31..e6e68fdb6f 100644 --- a/build-data/library-imports.txt +++ b/build-data/library-imports.txt @@ -1,5 +1,7 @@ -authlib com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -datafixerupper com/mojang/datafixers/DataFixerBuilder.java -datafixerupper com/mojang/datafixers/util/Either.java -datafixerupper com/mojang/serialization/codecs/KeyDispatchCodec.java -datafixerupper com/mojang/serialization/Dynamic.java +# You can use this file to import files from minecraft libraries into the project +# format: +# +# both fully qualified and a file based syntax are accepted for : +# authlib com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java +# datafixerupper com.mojang.datafixers.DataFixerBuilder +# datafixerupper com/mojang/datafixers/util/Either.java diff --git a/build.gradle.kts b/build.gradle.kts index ada32f29a8..264f4a7b7c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight.core") version "1.0.0-SNAPSHOT" + id("io.papermc.paperweight.core") version "1.0.0" } subprojects { From 15741a08f32ebce7f107dcf741852ee02295e7bd Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Tue, 15 Jun 2021 01:19:26 -0500 Subject: [PATCH 144/226] Update paperweight to 1.0.1 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 264f4a7b7c..8da4bfb38b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight.core") version "1.0.0" + id("io.papermc.paperweight.core") version "1.0.1" } subprojects { From 34269f8a39ee2a054f49a0246d82ad498433ff3f Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Tue, 15 Jun 2021 01:29:55 -0500 Subject: [PATCH 145/226] Run Gradle tasks in parallel by default --- gradle.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gradle.properties b/gradle.properties index 071cb6fb13..947f7fcfef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,3 +3,5 @@ version = 1.17-R0.1-SNAPSHOT mcVersion = 1.17 packageVersion = 1_17_R1 + +org.gradle.parallel=true From c8ecb664c640639bf6b57a4e82bb5ba43518b02c Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Tue, 15 Jun 2021 01:42:57 -0500 Subject: [PATCH 146/226] Remove now unnecessary scripts and update upstreamMerge.sh --- scripts/applyPatches.sh | 109 -------------------- scripts/build.sh | 15 --- scripts/decompile.sh | 146 -------------------------- scripts/functions.sh | 24 ----- scripts/importmcdev.sh | 126 ----------------------- scripts/init.sh | 77 -------------- scripts/makemcdevsrc.sh | 29 ------ scripts/paperclip.sh | 22 ---- scripts/pre-source-patches/README.md | 16 --- scripts/rebuildPatches.sh | 70 ------------- scripts/remap.sh | 81 --------------- scripts/requireDeps.sh | 26 ----- scripts/testServer.sh | 148 --------------------------- scripts/upstreamMerge.sh | 4 +- 14 files changed, 2 insertions(+), 891 deletions(-) delete mode 100755 scripts/applyPatches.sh delete mode 100755 scripts/build.sh delete mode 100755 scripts/decompile.sh delete mode 100755 scripts/functions.sh delete mode 100755 scripts/importmcdev.sh delete mode 100755 scripts/init.sh delete mode 100755 scripts/makemcdevsrc.sh delete mode 100755 scripts/paperclip.sh delete mode 100644 scripts/pre-source-patches/README.md delete mode 100755 scripts/rebuildPatches.sh delete mode 100755 scripts/remap.sh delete mode 100755 scripts/requireDeps.sh delete mode 100755 scripts/testServer.sh diff --git a/scripts/applyPatches.sh b/scripts/applyPatches.sh deleted file mode 100755 index e700fde80b..0000000000 --- a/scripts/applyPatches.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env bash - -( -PS1="$" -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -minecraftversion=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -gitcmd="git -c commit.gpgsign=false" -applycmd="$gitcmd am --3way --ignore-whitespace" -# Windows detection to workaround ARG_MAX limitation -windows="$([[ "$OSTYPE" == "cygwin" || "$OSTYPE" == "msys" ]] && echo "true" || echo "false")" - -echo "Rebuilding Forked projects.... " - -function applyPatch { - what=$1 - what_name=$(basename "$what") - target=$2 - branch=$3 - - cd "$basedir/$what" - $gitcmd fetch - $gitcmd branch -f upstream "$branch" >/dev/null - - cd "$basedir" - if [ ! -d "$basedir/$target" ]; then - $gitcmd clone "$what" "$target" - fi - cd "$basedir/$target" - - echo "Resetting $target to $what_name..." - $gitcmd remote rm upstream > /dev/null 2>&1 - $gitcmd remote add upstream "$basedir/$what" >/dev/null 2>&1 - $gitcmd checkout master 2>/dev/null || $gitcmd checkout -b master - $gitcmd fetch upstream >/dev/null 2>&1 - $gitcmd reset --hard upstream/upstream - - echo " Applying patches to $target..." - - statusfile=".git/patch-apply-failed" - rm -f "$statusfile" - git config commit.gpgsign false - $gitcmd am --abort >/dev/null 2>&1 - - # Special case Windows handling because of ARG_MAX constraint - if [[ $windows == "true" ]]; then - echo " Using workaround for Windows ARG_MAX constraint" - find "$basedir/${what_name}-Patches/"*.patch -print0 | xargs -0 $applycmd - else - $applycmd "$basedir/${what_name}-Patches/"*.patch - fi - - if [ "$?" != "0" ]; then - echo 1 > "$statusfile" - echo " Something did not apply cleanly to $target." - echo " Please review above details and finish the apply then" - echo " save the changes with rebuildPatches.sh" - - # On Windows, finishing the patch apply will only fix the latest patch - # users will need to rebuild from that point and then re-run the patch - # process to continue - if [[ $windows == "true" ]]; then - echo "" - echo " Because you're on Windows you'll need to finish the AM," - echo " rebuild all patches, and then re-run the patch apply again." - echo " Consider using the scripts with Windows Subsystem for Linux." - fi - - exit 1 - else - rm -f "$statusfile" - echo " Patches applied cleanly to $target" - fi -} - -# Move into spigot dir -cd "$workdir/Spigot" -basedir=$(pwd) -# Apply Spigot -( - applyPatch ../Bukkit Spigot-API HEAD && - applyPatch ../CraftBukkit Spigot-Server patched -) || ( - echo "Failed to apply Spigot Patches" - exit 1 -) || exit 1 -# Move out of Spigot -basedir="$1" -cd "$basedir" - -echo "Importing MC Dev" - -./scripts/importmcdev.sh "$basedir" || exit 1 - -# Apply paper -( - applyPatch "work/Spigot/Spigot-API" Paper-API HEAD && - applyPatch "work/Spigot/Spigot-Server" Paper-Server HEAD - cd "$basedir" - - # if we have previously ran ./paper mcdev, update it - if [ -d "$workdir/Minecraft/$minecraftversion/src" ]; then - ./scripts/makemcdevsrc.sh "$basedir" - fi -) || ( - echo "Failed to apply Paper Patches" - exit 1 -) || exit 1 -) || exit 1 diff --git a/scripts/build.sh b/scripts/build.sh deleted file mode 100755 index 9b8fa286a7..0000000000 --- a/scripts/build.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -basedir="$(cd "$1" && pwd -P)" -gitcmd="git -c commit.gpgsign=false" - -($gitcmd submodule update --init && ./scripts/remap.sh "$basedir" && ./scripts/decompile.sh "$basedir" && ./scripts/init.sh "$basedir" && ./scripts/applyPatches.sh "$basedir") || ( - echo "Failed to build Paper" - exit 1 -) || exit 1 -if [ "$2" == "--jar" ]; then - mvn clean install && ./scripts/paperclip.sh "$basedir" -fi -) || exit 1 diff --git a/scripts/decompile.sh b/scripts/decompile.sh deleted file mode 100755 index 0d0467d99a..0000000000 --- a/scripts/decompile.sh +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -PS1="$" -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -minecraftversion=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -windows="$([[ "$OSTYPE" == "cygwin" || "$OSTYPE" == "msys" ]] && echo "true" || echo "false")" -decompiledir="$workdir/Minecraft/$minecraftversion" -spigotdecompiledir="$decompiledir/spigot" -forgedecompiledir="$decompiledir/forge" -forgeflowerversion="1.5.380.19" -forgeflowerurl="http://files.minecraftforge.net/maven/net/minecraftforge/forgeflower/$forgeflowerversion/forgeflower-$forgeflowerversion.jar" -# temp use patched version -forgeflowerurl="https://zachbr.keybase.pub/paper/forgeflower-patched/forgeflower-1.5.380.19.jar?dl=1" -forgeflowerbin="$workdir/ForgeFlower/$forgeflowerversion.jar" -# TODO: Make this better? We don't need spigot compat for this stage -forgefloweroptions="-dgs=1 -hdc=0 -asc=1 -udv=1 -jvn=1" -forgeflowercachefile="$decompiledir/forgeflowercache" -forgeflowercachevalue="$forgeflowerurl - $forgeflowerversion - $forgefloweroptions"; -classdir="$decompiledir/classes" -versionjson="$workdir/Minecraft/$minecraftversion/$minecraftversion.json" - -if [[ ! -f "$versionjson" ]]; then - echo "Downloading $minecraftversion JSON Data" - verescaped=$(echo ${minecraftversion} | sed 's/\-pre/ Pre-Release /g' | sed 's/\./\\./g') - urlescaped=$(echo ${verescaped} | sed 's/ /_/g') - verentry=$(curl -s "https://launchermeta.mojang.com/mc/game/version_manifest.json" | grep -oE "\{\"id\": \"${verescaped}\".*${urlescaped}\.json") - jsonurl=$(echo $verentry | grep -oE https:\/\/.*\.json) - curl -o "$versionjson" "$jsonurl" - echo "$versionjson - $jsonurl" -fi - -function downloadLibraries { - group=$1 - groupesc=$(echo ${group} | sed 's/\./\\./g') - grouppath=$(echo ${group} | sed 's/\./\//g') - libdir="$decompiledir/libraries/${group}/" - mkdir -p "$libdir" - shift - for lib in "$@" - do - jar="$libdir/${lib}-sources.jar" - destlib="$libdir/${lib}" - if [ ! -f "$jar" ]; then - libesc=$(echo ${lib} | sed 's/\./\\]./g') - ver=$(grep -oE "${groupesc}:${libesc}:[0-9\.]+" "$versionjson" | sed "s/${groupesc}:${libesc}://g") - echo "Downloading ${group}:${lib}:${ver} Sources" - curl -s -o "$jar" "https://libraries.minecraft.net/${grouppath}/${lib}/${ver}/${lib}-${ver}-sources.jar" - set +e - grep "" "$jar" && grep -oE ".*?" "$jar" && rm "$jar" && echo "Failed to download $jar" && exit 1 - set -e - fi - - if [ ! -d "$destlib/$grouppath" ]; then - echo "Extracting $group:$lib Sources" - mkdir -p "$destlib" - (cd "$destlib" && jar xf "$jar") - fi - done -} - -downloadLibraries "com.mojang" datafixerupper authlib brigadier - -# prep folders -mkdir -p "$workdir/ForgeFlower" -mkdir -p "$spigotdecompiledir" -mkdir -p "$forgedecompiledir" - -echo "Extracting NMS classes..." -if [ ! -d "$classdir" ]; then - mkdir -p "$classdir" - cd "$classdir" - set +e - jar xf "$decompiledir/$minecraftversion-mapped.jar" net/minecraft com/mojang/math - if [ "$?" != "0" ]; then - cd "$basedir" - echo "Failed to extract NMS classes." - exit 1 - fi - set -e -fi - -#needsDecomp=0 -#if [ ! -f "$forgeflowercachefile" ]; then -# needsDecomp=1 -#elif [ "$(cat ${forgeflowercachefile})" != "$forgeflowercachevalue" ]; then -# needsDecomp=1 -#fi -#if [ "$needsDecomp" == "1" ]; then -# # our local cache is now invalidated, we can update forgeflower to get better deobfuscation -# rm -rf "$forgedecompiledir/net" -#fi - -## Forge (for Paper mc-dev imports, and dev src folders for unimported files) -#if [ ! -d "$forgedecompiledir/net" ] ; then -# echo "Decompiling classes (stage 1)..." -# cd "$basedir" -# -# if [ ! -f "$forgeflowerbin" ]; then -# echo "Downloading ForgeFlower ($forgeflowerversion)..." -# curl -s -o "$forgeflowerbin" "$forgeflowerurl" -# fi -# -# set +e -# java -Ddecomp.renameparams=true -jar "$forgeflowerbin" ${forgefloweroptions} -ind=' ' "$classdir" "$forgedecompiledir" -# if [ "$?" != "0" ]; then -# rm -rf "$forgedecompiledir/net" -# echo "Failed to decompile classes." -# exit 1 -# fi -# echo "$forgeflowercachevalue" > "$forgeflowercachefile" -# set -e -#fi - -# Spigot (for CraftBukkit patches) - -# if we see the old net folder, copy it to spigot to avoid redecompiling -if [ -d "$decompiledir/net" ]; then - cp -r "$decompiledir/net" "$spigotdecompiledir/" -fi - -if [ ! -d "$spigotdecompiledir/net" ]; then - echo "Decompiling classes (stage 2)..." - cd "$basedir" - set +e - java -jar "$workdir/BuildData/bin/fernflower.jar" -dgs=1 -hdc=0 -asc=1 -udv=0 -rsy=1 -aoa=1 "$classdir" "$spigotdecompiledir" - if [ "$?" != "0" ]; then - rm -rf "$spigotdecompiledir/net" - echo "Failed to decompile classes." - exit 1 - fi - set -e -fi - -# set a symlink to current -currentlink="$workdir/Minecraft/current" -if ([ ! -e "$currentlink" ] || [ -L "$currentlink" ]) && [ "$windows" == "false" ]; then - set +e - echo "Pointing $currentlink to $minecraftversion" - rm -rf "$currentlink" || true - ln -sfn "$minecraftversion" "$currentlink" || echo "Failed to set current symlink" -fi - -) diff --git a/scripts/functions.sh b/scripts/functions.sh deleted file mode 100755 index fecad9922d..0000000000 --- a/scripts/functions.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -gitcmd="git -c commit.gpgsign=false" - -color() { - if [ $2 ]; then - printf "\e[$1;$2m" - else - printf "\e[$1m" - fi -} -colorend() { - printf "\e[m" -} - -paperstash() { - STASHED=$($gitcmd stash 2>/dev/null|| return 0) # errors are ok -} - -paperunstash() { - if [[ "$STASHED" != "No local changes to save" ]] ; then - $gitcmd stash pop 2>/dev/null|| return 0 # errors are ok - fi -} diff --git a/scripts/importmcdev.sh b/scripts/importmcdev.sh deleted file mode 100755 index 3e8c8e2169..0000000000 --- a/scripts/importmcdev.sh +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -nms="net/minecraft" -export MODLOG="" -PS1="$" -basedir="$(cd "$1" && pwd -P)" -source "$basedir/scripts/functions.sh" -gitcmd="git -c commit.gpgsign=false" - -workdir="$basedir/work" -minecraftversion=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -decompiledir="$workdir/Minecraft/$minecraftversion/forge" -# replace for now -decompiledir="$workdir/Minecraft/$minecraftversion/spigot" -export importedmcdev="" -function import { - export importedmcdev="$importedmcdev $1" - file="${1}.java" - target="$workdir/Spigot/Spigot-Server/src/main/java/$nms/$file" - base="$decompiledir/$nms/$file" - - if [[ ! -f "$target" ]]; then - export MODLOG="$MODLOG Imported $file from mc-dev\n"; - #echo "Copying $base to $target" - mkdir -p "$(dirname "$target")" - cp "$base" "$target" || exit 1 - else - echo "UN-NEEDED IMPORT: $file" - fi -} - -function importLibrary { - group=$1 - lib=$2 - prefix=$3 - shift 3 - for file in "$@"; do - file="$prefix/$file" - target="$workdir/Spigot/Spigot-Server/src/main/java/${file}" - targetdir=$(dirname "$target") - mkdir -p "${targetdir}" - base="$workdir/Minecraft/$minecraftversion/libraries/${group}/${lib}/$file" - if [ ! -f "$base" ]; then - echo "Missing $base" - exit 1 - fi - export MODLOG="$MODLOG Imported $file from $lib\n"; - sed 's/\r$//' "$base" > "$target" || exit 1 - done -} - -( - cd "$workdir/Spigot/Spigot-Server/" - lastlog=$($gitcmd log -1 --oneline) - if [[ "$lastlog" = *"mc-dev Imports"* ]]; then - $gitcmd reset --hard HEAD^ - fi -) - - -files=$(cat "$basedir/Spigot-Server-Patches/"* | grep "+++ b/src/main/java/net/minecraft/" | sort | uniq | sed 's/\+\+\+ b\/src\/main\/java\/net\/minecraft\///g') - -nonnms=$(grep -R "new file mode" -B 1 "$basedir/Spigot-Server-Patches/" | grep -v "new file mode" | grep -oE --color=none "net\/minecraft\/.*.java" | sed 's/.*\/net\/minecraft\///g') -function containsElement { - local e - for e in "${@:2}"; do - [[ "$e" == "$1" ]] && return 0; - done - return 1 -} -set +e -for f in $files; do - containsElement "$f" ${nonnms[@]} - if [ "$?" == "1" ]; then - if [ ! -f "$workdir/Spigot/Spigot-Server/src/main/java/net/minecraft/$f" ]; then - f="$(echo "$f" | sed 's/.java//g')" - if [ ! -f "$decompiledir/$nms/$f.java" ]; then - echo "$(color 1 31) ERROR!!! Missing NMS$(color 1 34) $f $(colorend)"; - error=true - else - import $f - fi - fi - fi -done -if [ -n "$error" ]; then - exit 1 -fi - -######################################################## -######################################################## -######################################################## -# NMS IMPORTS -# Temporarily add new NMS dev imports here before you run paper patch -# but after you have paper rb'd your changes, remove the line from this file before committing. -# we do not need any lines added to this file for NMS - -# import FileName - - -######################################################## -######################################################## -######################################################## -# LIBRARY IMPORTS -# These must always be mapped manually, no automatic stuff -# -# # group # lib # prefix # many files - -# dont forget \ at end of each line but last -importLibrary com.mojang authlib com/mojang/authlib yggdrasil/YggdrasilGameProfileRepository.java -importLibrary com.mojang datafixerupper com/mojang/datafixers DataFixerBuilder.java -importLibrary com.mojang datafixerupper com/mojang/datafixers/util Either.java -importLibrary com.mojang datafixerupper com/mojang/serialization/codecs KeyDispatchCodec.java -importLibrary com.mojang datafixerupper com/mojang/serialization Dynamic.java - -######################################################## -######################################################## -######################################################## -set -e -cd "$workdir/Spigot/Spigot-Server/" -rm -rf nms-patches applyPatches.sh makePatches.sh >/dev/null 2>&1 -$gitcmd add --force . -A >/dev/null 2>&1 -echo -e "mc-dev Imports\n\n$MODLOG" | $gitcmd commit . -F - -) diff --git a/scripts/init.sh b/scripts/init.sh deleted file mode 100755 index 8b1929c836..0000000000 --- a/scripts/init.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -PS1="$" -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -minecraftversion=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -spigotdecompiledir="$workdir/Minecraft/$minecraftversion/spigot" -nms="$spigotdecompiledir" -cb="src/main/java" -gitcmd="git -c commit.gpgsign=false" - -# https://stackoverflow.com/a/38595160 -# https://stackoverflow.com/a/800644 -if sed --version >/dev/null 2>&1; then - strip_cr() { - sed -i -- "s/\r//" "$@" - } -else - strip_cr () { - sed -i "" "s/$(printf '\r')//" "$@" - } -fi - -patch=$(which patch 2>/dev/null) -if [ "x$patch" == "x" ]; then - patch="$basedir/hctap.exe" -fi - -# apply patches directly to the file tree -# used to fix issues from upstream source repos -cd "$basedir" -prepatchesdir="$basedir/scripts/pre-source-patches" -for file in $(ls "$prepatchesdir") -do - if [ $file == "README.md" ]; then - continue - fi - - echo "--==-- Applying PRE-SOURCE patch: $file --==--" - $patch -p0 < "$prepatchesdir/$file" -done - -echo "Applying CraftBukkit patches to NMS..." -cd "$workdir/CraftBukkit" -$gitcmd checkout -B patched HEAD >/dev/null 2>&1 -rm -rf "$cb/net" -# create baseline NMS import so we can see diff of what CB changed -while IFS= read -r -d '' file -do - patchFile="$file" - file="$(echo "$file" | cut -d "/" -f2- | cut -d. -f1).java" - mkdir -p "$(dirname $cb/"$file")" - cp "$nms/$file" "$cb/$file" -done < <(find nms-patches -type f -print0) -$gitcmd add --force src -$gitcmd commit -m "Minecraft $ $(date)" --author="Vanilla " - -# apply patches -while IFS= read -r -d '' file -do - patchFile="$file" - file="$(echo "$file" | cut -d "/" -f2- | cut -d. -f1).java" - - echo "Patching $file < $patchFile" - set +e - strip_cr "$nms/$file" > /dev/null - set -e - - "$patch" -d src/main/java -p 1 < "$patchFile" -done < <(find nms-patches -type f -print0) - -$gitcmd add --force src -$gitcmd commit -m "CraftBukkit $ $(date)" --author="CraftBukkit " -$gitcmd checkout -f HEAD~2 -) diff --git a/scripts/makemcdevsrc.sh b/scripts/makemcdevsrc.sh deleted file mode 100755 index bd86947f8d..0000000000 --- a/scripts/makemcdevsrc.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -PS1="$" - -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -minecraftversion=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -decompiledir="$workdir/Minecraft/$minecraftversion" -nms="$decompiledir/spigot/net/minecraft" -papernms="$basedir/Paper-Server/src/main/java/net/minecraft" -mcdevsrc="${decompiledir}/src/net/minecraft" -rm -rf "${mcdevsrc}" -mkdir -p "${mcdevsrc}" -cd "${nms}" - -for file in $(find . -name '*.java') -do - if [ ! -f "${papernms}/${file}" ]; then - destdir="${mcdevsrc}"/$(dirname "${file}") - mkdir -p "${destdir}" - cp "${file}" "${destdir}" - fi -done - -cd "$basedir" -echo "Built $decompiledir/src to be included in your project for src access"; -) diff --git a/scripts/paperclip.sh b/scripts/paperclip.sh deleted file mode 100755 index 2722ca3dda..0000000000 --- a/scripts/paperclip.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -mcver=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -paperjar="$basedir/Paper-Server/target/paper-$mcver.jar" -vanillajar="$workdir/Minecraft/$mcver/$mcver.jar" - -( - cd "$workdir/Paperclip" - mvn clean package "-Dmcver=$mcver" "-Dpaperjar=$paperjar" "-Dvanillajar=$vanillajar" -) -cp "$workdir/Paperclip/assembly/target/paperclip-${mcver}.jar" "$basedir/paperclip.jar" - -echo "" -echo "" -echo "" -echo "Build success!" -echo "Copied final jar to $(cd "$basedir" && pwd -P)/paperclip.jar" -) || exit 1 diff --git a/scripts/pre-source-patches/README.md b/scripts/pre-source-patches/README.md deleted file mode 100644 index f91d42efd0..0000000000 --- a/scripts/pre-source-patches/README.md +++ /dev/null @@ -1,16 +0,0 @@ -Files in this directory are applied directly to the tree before any other -patches. - -These patches are always applied directly from the root of the repository. -"$basedir" - -This allows us to fix malformed patch files and other changes from upstream. -This is not intended to replace any other system and should not be used in -place of the existing specific patch directories. - -Documentation is intentionally sparse to avoid being misused. - -`diff -ruN originalfile changedfile` - -See the man pages on diff and patch. - diff --git a/scripts/rebuildPatches.sh b/scripts/rebuildPatches.sh deleted file mode 100755 index a910d6f23d..0000000000 --- a/scripts/rebuildPatches.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env bash - -( -PS1="$" -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -source "$basedir/scripts/functions.sh" -gitcmd="git -c commit.gpgsign=false -c core.safecrlf=false" - -echo "Rebuilding patch files from current fork state..." -nofilter="0" -if [ "$2" == "nofilter" ] || [ "$2" == "noclean" ]; then - nofilter="1" -fi -function cleanupPatches { - cd "$1" - for patch in *.patch; do - echo "$patch" - diffs=$($gitcmd diff --staged "$patch" | grep --color=none -E "^(\+|\-)" | grep --color=none -Ev "(\-\-\- a|\+\+\+ b|^.index)") - - if [ "x$diffs" == "x" ] ; then - $gitcmd reset HEAD "$patch" >/dev/null - $gitcmd checkout -- "$patch" >/dev/null - fi - done -} - -function savePatches { - what=$1 - what_name=$(basename "$what") - target=$2 - echo "Formatting patches for $what..." - - cd "$basedir/${what_name}-Patches/" - if [ -d "$basedir/$target/.git/rebase-apply" ]; then - # in middle of a rebase, be smarter - echo "REBASE DETECTED - PARTIAL SAVE" - last=$(cat "$basedir/$target/.git/rebase-apply/last") - next=$(cat "$basedir/$target/.git/rebase-apply/next") - orderedfiles=$(find . -name "*.patch" | sort) - for i in $(seq -f "%04g" 1 1 $last) - do - if [ $i -lt $next ]; then - rm $(echo "$orderedfiles{@}" | sed -n "${i}p") - fi - done - else - rm -rf *.patch - fi - - cd "$basedir/$target" - - $gitcmd format-patch --zero-commit --full-index --no-signature --no-stat -N -o "$basedir/${what_name}-Patches/" upstream/upstream >/dev/null - cd "$basedir" - $gitcmd add --force -A "$basedir/${what_name}-Patches" - if [ "$nofilter" == "0" ]; then - cleanupPatches "$basedir/${what_name}-Patches" - fi - echo " Patches saved for $what to $what_name-Patches/" -} - -savePatches "$workdir/Spigot/Spigot-API" "Paper-API" -if [ -f "$basedir/Paper-API/.git/patch-apply-failed" ]; then - echo "$(color 1 31)[[[ WARNING ]]] $(color 1 33)- Not saving Paper-Server as it appears Paper-API did not apply clean.$(colorend)" - echo "$(color 1 33)If this is a mistake, delete $(color 1 34)Paper-API/.git/patch-apply-failed$(color 1 33) and run rebuild again.$(colorend)" - echo "$(color 1 33)Otherwise, rerun ./paper patch to have a clean Paper-API apply so the latest Paper-Server can build.$(colorend)" -else - savePatches "$workdir/Spigot/Spigot-Server" "Paper-Server" -fi -) || exit 1 diff --git a/scripts/remap.sh b/scripts/remap.sh deleted file mode 100755 index e47992e17b..0000000000 --- a/scripts/remap.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -PS1="$" -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -minecraftversion="$(cat "${workdir}/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4)" -minecraftserverurl=$(cat "${workdir}/BuildData/info.json" | grep serverUrl | cut -d '"' -f 4) -minecrafthash=$(cat "${workdir}/BuildData/info.json" | grep minecraftHash | cut -d '"' -f 4) -accesstransforms="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep accessTransforms | cut -d '"' -f 4) -classmappings="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep classMappings | cut -d '"' -f 4) -membermappings="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep memberMappings | cut -d '"' -f 4) -#packagemappings="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep packageMappings | cut -d '"' -f 4) -decompiledir="$workdir/Minecraft/$minecraftversion" -jarpath="$decompiledir/$minecraftversion" -mkdir -p "$decompiledir" - -echo "Downloading unmapped vanilla jar..." -if [ ! -f "$jarpath.jar" ]; then - curl -s -o "$jarpath.jar" "$minecraftserverurl" - if [ "$?" != "0" ]; then - echo "Failed to download the vanilla server jar. Check connectivity or try again later." - exit 1 - fi -fi - -# OS X & FreeBSD don't have md5sum, just md5 -r -#command -v md5sum >/dev/null 2>&1 || { -# command -v md5 >/dev/null 2>&1 && { -# shopt -s expand_aliases -# alias md5sum='md5 -r' -# echo "md5sum command not found, using an alias instead" -# } || { -# echo >&2 "No md5sum or md5 command found" -# exit 1 -# } -#} -# -#checksum=$(md5sum "$jarpath.jar" | cut -d ' ' -f 1) -#if [ "$checksum" != "$minecrafthash" ]; then -# echo "The MD5 checksum of the downloaded server jar does not match the BuildData hash." -# exit 1 -#fi - -# These specialsource commands are from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/builddata/browse/info.json -echo "Applying class mappings..." -if [ ! -f "$jarpath-cl.jar" ]; then - java -jar "$workdir/BuildData/bin/SpecialSource-2.jar" map --only . --only net/minecraft --only com/mojang/math --auto-lvt BASIC --auto-member SYNTHETIC -i "$jarpath.jar" -m "$classmappings" -o "$jarpath-cl.jar" 1>/dev/null - if [ "$?" != "0" ]; then - echo "Failed to apply class mappings." - exit 1 - fi -fi - -echo "Applying member mappings..." -if [ ! -f "$jarpath-m.jar" ]; then - java -jar "$workdir/BuildData/bin/SpecialSource-2.jar" map --only . --only com/mojang/math --only net/minecraft --auto-member TOKENS -i "$jarpath-cl.jar" -m "$membermappings" -o "$jarpath-m.jar" 1>/dev/null - if [ "$?" != "0" ]; then - echo "Failed to apply member mappings." - exit 1 - fi -fi - -echo "Creating remapped jar..." -if [ ! -f "$jarpath-mapped.jar" ]; then - java -jar "$workdir/BuildData/bin/SpecialSource.jar" --only . --only com/mojang/math --only net/minecraft -i "$jarpath-m.jar" --access-transformer "$accesstransforms" -m "/home/martin/Projects/Paper/bukkit-e3c5450d-fields.csrg" -o "$jarpath-mapped.jar" 1>/dev/null - if [ "$?" != "0" ]; then - echo "Failed to create remapped jar." - exit 1 - fi -fi - -echo "Installing remapped jar..." -cd "$workdir/CraftBukkit" # Need to be in a directory with a valid POM at the time of install. -mvn install:install-file -q -Dfile="$jarpath-mapped.jar" -Dpackaging=jar -DgroupId=io.papermc -DartifactId=minecraft-server -Dversion="$minecraftversion-SNAPSHOT" -if [ "$?" != "0" ]; then - echo "Failed to install remapped jar." - exit 1 -fi -) diff --git a/scripts/requireDeps.sh b/scripts/requireDeps.sh deleted file mode 100755 index 8437accfaa..0000000000 --- a/scripts/requireDeps.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -set -ue - -# Check if an application is on the PATH. -# If it is not, return with non-zero. -_is_dep_available() { - command -v "$1" >/dev/null || (echo "\`$1\` ${2:-command was not found in the path and is a required dependency}"; return 1) -} - -if [ -z "${1:-}" ]; then - # No specific dependency was found; let's just check for all required ones. - _is_dep_available git - _is_dep_available patch - _is_dep_available mvn - _is_dep_available curl - - _is_dep_available javac "was not found; you can download the JDK from https://adoptopenjdk.net/ or via your package manager" - _is_dep_available jar "was not found; you can download the JDK from https://adoptopenjdk.net/ or via your package manager" -else - # Require all dependencies provided. - for dep in $@; do - _is_dep_available "$dep" - done -fi - -# vim: set ff=unix autoindent ts=4 sw=4 tw=0 et : diff --git a/scripts/testServer.sh b/scripts/testServer.sh deleted file mode 100755 index 3fabfcd0bf..0000000000 --- a/scripts/testServer.sh +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env bash - -set -e -PS1="$" -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -minecraftversion=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -gitcmd="git -c commit.gpgsign=false" - -# -# FUNCTIONS -# -source "$basedir"/scripts/functions.sh - -updateTest() { - paperstash - $gitcmd reset --hard origin/master - paperunstash -} - -papertestdir="${PAPER_TEST_DIR:-$workdir/test-server}" - -mkdir -p "$papertestdir" -cd "$papertestdir" - -# -# SKELETON CHECK -# - -if [ ! -d .git ]; then - $gitcmd init - $gitcmd remote add origin ${PAPER_TEST_SKELETON:-https://github.com/PaperMC/PaperTestServer} - $gitcmd fetch origin - updateTest -elif [ "$2" == "update" ] || [ "$3" == "update" ]; then - updateTest -fi - -if [ ! -f server.properties ] || [ ! -d plugins ]; then - echo " " - echo " Checking out Test Server Skeleton" - updateTest -fi - - -# -# EULA CHECK -# - -if [ -z "$(grep true eula.txt 2>/dev/null)" ]; then - echo - echo "$(color 32) It appears you have not agreed to Mojangs EULA yet! Press $(color 1 33)y$(colorend) $(color 32)to confirm agreement to" - read -p " Mojangs EULA found at:$(color 1 32) https://account.mojang.com/documents/minecraft_eula $(colorend) " -n 1 -r - echo "" - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "$(color 1 31)Aborted$(colorend)" - exit; - fi - echo "eula=true" > eula.txt -fi - -# -# JAR CHECK -# - -folder="$basedir/Paper-Server" -jar="$folder/target/paper-${minecraftversion}.jar" -if [ ! -z "$PAPER_JAR" ]; then - jar="$PAPER_JAR" -fi -if [ ! -d "$folder" ]; then -( - echo "Building Patched Repo" - cd "$basedir" - ./paper patch -) -fi - -if [ "$2" == "build" ] || [ "$3" == "build" ]; then -( - echo "Building Paper" - cd "$basedir" - mvn package -) -fi -# -# JVM FLAGS -# - -if [ -f "$jar" ]; then - cp "$jar" paper.jar -fi -baseargs="-server -Xms${PAPER_MIN_TEST_MEMORY:-512M} -Xmx${PAPER_TEST_MEMORY:-2G} -Dfile.encoding=UTF-8 -XX:MaxGCPauseMillis=150 -XX:+UseG1GC " -baseargs="$baseargs -DIReallyKnowWhatIAmDoingISwear=1 " -baseargs="$baseargs -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=40 -XX:G1MaxNewSizePercent=60 " -baseargs="$baseargs -XX:InitiatingHeapOccupancyPercent=10 -XX:G1MixedGCLiveThresholdPercent=80 " -baseargs="$baseargs -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5100" - - -cmd="java ${PAPER_TEST_BASE_JVM_ARGS:-$baseargs} ${PAPER_TEST_EXTRA_JVM_ARGS} -jar paper.jar ${PAPER_TEST_APP_ARGS:-} nogui" -screen_command="screen -DURS papertest $cmd" -tmux_command="tmux new-session -A -s Paper -n 'Paper Test' -c '$(pwd)' '$cmd'" - -# -# MULTIPLEXER CHOICE -# - -multiplex=${PAPER_TEST_MULTIPLEXER} - -if [ ! -z "$PAPER_NO_MULTIPLEX" ]; then - cmd="$cmd" -elif [ "$multiplex" == "screen" ]; then - if command -v "screen" >/dev/null 2>&1 ; then - cmd="$screen_command" - else - echo "screen not found" - exit 1 - fi -elif [ "$multiplex" == "tmux" ] ; then - if command -v "tmux" >/dev/null 2>&1 ; then - cmd="$tmux_command" - else - echo "tmux not found" - exit 1 - fi -else - if command -v "screen" >/dev/null 2>&1 ; then - cmd="$screen_command" - elif command -v "tmux" >/dev/null 2>&1 ; then - cmd="$tmux_command" - else - echo "screen or tmux not found - it is strongly recommended to install either" - echo "No terminal multiplexer will be used" - fi -fi - -# -# START / LOG -# - -if [ ! -z "$PAPER_TEST_COMMAND_WRAPPER" ]; then - $PAPER_TEST_COMMAND_WRAPPER $cmd -else - echo "Running command: $cmd" - echo "In directory: $(pwd)" - #sleep 1 - /usr/bin/env bash -c "$cmd" -fi diff --git a/scripts/upstreamMerge.sh b/scripts/upstreamMerge.sh index f011f708fc..02376dc7a2 100755 --- a/scripts/upstreamMerge.sh +++ b/scripts/upstreamMerge.sh @@ -30,11 +30,11 @@ update Spigot if [[ "$2" = "all" || "$2" = "a" ]] ; then update BuildData - update Paperclip fi if [ "$updated" == "1" ]; then echo "Rebuilding patches without filtering to improve apply ability" cd "$basedir" - scripts/rebuildPatches.sh "$basedir" nofilter 1>/dev/null|| exit 1 + ./gradlew applyPatches -Dpaperweight.debug=true || exit 1 + ./gradlew rebuildPatches || exit 1 fi ) From a3de494f1152cb038e2fafa07dd6bd1ad7481ba1 Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Tue, 15 Jun 2021 01:44:13 -0500 Subject: [PATCH 147/226] Remove Paperclip submodule --- .gitmodules | 3 --- work/Paperclip | 1 - 2 files changed, 4 deletions(-) delete mode 160000 work/Paperclip diff --git a/.gitmodules b/.gitmodules index 758536e061..7280fb743d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,6 +10,3 @@ [submodule "work/Spigot"] path = work/Spigot url = https://hub.spigotmc.org/stash/scm/spigot/spigot.git -[submodule "work/Paperclip"] - path = work/Paperclip - url = https://github.com/PaperMC/Paperclip.git diff --git a/work/Paperclip b/work/Paperclip deleted file mode 160000 index 6776c66987..0000000000 --- a/work/Paperclip +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6776c66987a021a1c0db55b2e21c883660acc19f From c9f654db919574ef221a75373d0a5643d5051e40 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 14 Jun 2021 23:51:30 -0700 Subject: [PATCH 148/226] Updated Upstream (CraftBukkit) 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 CraftBukkit Changes: f992ce60 Fix duplicate datapack reload on /reload --- build.gradle.kts | 2 +- settings.gradle.kts | 2 ++ work/CraftBukkit | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8da4bfb38b..0704b95179 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight.core") version "1.0.1" + id("io.papermc.paperweight.core") version "1.0.1-LOCAL-SNAPSHOT" } subprojects { diff --git a/settings.gradle.kts b/settings.gradle.kts index 4127fc6b8c..27f9364149 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,9 +1,11 @@ pluginManagement { repositories { + mavenLocal() gradlePluginPortal() maven("https://papermc.io/repo/repository/maven-public/") } } +includeBuild("../paperweight") rootProject.name = "Paper" diff --git a/work/CraftBukkit b/work/CraftBukkit index 622cf61119..f992ce6097 160000 --- a/work/CraftBukkit +++ b/work/CraftBukkit @@ -1 +1 @@ -Subproject commit 622cf6111905e787add191b9a88d62656439ef31 +Subproject commit f992ce6097f846ed5967fc797d98ae3e84ef1b10 From 57fce3dca572ae19d1d11df9970ae991c09c1308 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Tue, 15 Jun 2021 00:28:40 -0700 Subject: [PATCH 149/226] revert accidental changes --- build.gradle.kts | 2 +- settings.gradle.kts | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0704b95179..8da4bfb38b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight.core") version "1.0.1-LOCAL-SNAPSHOT" + id("io.papermc.paperweight.core") version "1.0.1" } subprojects { diff --git a/settings.gradle.kts b/settings.gradle.kts index 27f9364149..4127fc6b8c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,11 +1,9 @@ pluginManagement { repositories { - mavenLocal() gradlePluginPortal() maven("https://papermc.io/repo/repository/maven-public/") } } -includeBuild("../paperweight") rootProject.name = "Paper" From ebbfe2749b22ac9d012bd53f6b7772730eb1273d Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Tue, 15 Jun 2021 00:43:03 -0700 Subject: [PATCH 150/226] update Optimize Pathfinder - Remove Streams / Optimized collections --- ...der-Remove-Streams-Optimized-collect.patch | 159 ------------------ ...der-Remove-Streams-Optimized-collect.patch | 130 ++++++++++++++ ...541-Beacon-API-custom-effect-ranges.patch} | 0 ...tch => 0542-Add-API-for-quit-reason.patch} | 0 ...h => 0543-Seed-based-feature-search.patch} | 0 ...ng-Trader-spawn-rate-config-options.patch} | 0 ...rove-performance-of-the-end-generat.patch} | 0 ...ch => 0546-Expose-world-spawn-angle.patch} | 0 ...patch => 0547-Add-Destroy-Speed-API.patch} | 0 ...-spawnParticle-x-y-z-precision-loss.patch} | 0 ...49-Add-LivingEntity-clearActiveItem.patch} | 0 ...=> 0550-Add-PlayerItemCooldownEvent.patch} | 0 ...PI.patch => 0551-More-lightning-API.patch} | 0 ...should-not-bypass-cramming-gamerule.patch} | 0 ...-missing-default-perms-for-commands.patch} | 0 ...h => 0554-Add-PlayerShearBlockEvent.patch} | 0 ...rbose-world-setting-to-false-by-def.patch} | 0 ...ng-zombie-villager-discount-exploit.patch} | 0 ....patch => 0557-Limit-recipe-packets.patch} | 0 ...-CraftSound-backwards-compatibility.patch} | 0 ... 0559-MC-4-Fix-item-position-desync.patch} | 0 ...560-Player-Chunk-Load-Unload-Events.patch} | 0 ...1-Optimize-Dynamic-get-Missing-Keys.patch} | 0 ...-Expose-LivingEntity-hurt-direction.patch} | 0 ...OBSTRUCTED-reason-to-BedEnterResult.patch} | 0 ...-invalid-ingredient-lists-in-Villag.patch} | 0 ...atch => 0565-added-PlayerTradeEvent.patch} | 0 ...ch => 0566-Implement-TargetHitEvent.patch} | 0 ...567-Additional-Block-Material-API-s.patch} | 0 ...tch => 0568-Fix-harming-potion-dupe.patch} | 0 ...get-Material-from-Boats-and-Minecar.patch} | 0 ....patch => 0570-Cache-burn-durations.patch} | 0 ...ob-spawner-spawn-egg-transformation.patch} | 0 ...ment-PlayerFlowerPotManipulateEvent.patch} | 0 ...event-not-being-called-in-adventure.patch} | 0 ...h => 0574-Zombie-API-breaking-doors.patch} | 0 ...575-Fix-nerfed-slime-when-splitting.patch} | 0 ...=> 0576-Add-EntityLoadCrossbowEvent.patch} | 0 ...ch => 0577-Guardian-beam-workaround.patch} | 0 ...0578-Added-WorldGameRuleChangeEvent.patch} | 0 ...-Added-ServerResourcesReloadedEvent.patch} | 0 ...d-settings-for-mobs-picking-up-loot.patch} | 0 ...mplemented-BlockFailedDispenseEvent.patch} | 0 ...-Added-PlayerLecternPageChangeEvent.patch} | 0 ...-Added-PlayerLoomPatternSelectEvent.patch} | 0 ...nfigurable-door-breaking-difficulty.patch} | 0 ...ty-commands-shall-not-be-dispatched.patch} | 0 ...I-to-expose-exact-interaction-point.patch} | 0 ...OIs.patch => 0587-Remove-stale-POIs.patch} | 0 ...h => 0588-Fix-villager-boat-exploit.patch} | 0 ...I.patch => 0589-Add-sendOpLevel-API.patch} | 0 ...ch => 0590-Add-StructureLocateEvent.patch} | 0 ...-for-requiring-a-player-participant.patch} | 0 ...leHitEvent-call-when-fireballs-dead.patch} | 0 ...nent-with-empty-text-instead-of-thr.patch} | 0 ...594-Make-schedule-command-per-world.patch} | 0 ...595-Configurable-max-leash-distance.patch} | 0 ...596-Implement-BlockPreDispenseEvent.patch} | 0 ...h => 0597-Added-Vanilla-Entity-Tags.patch} | 0 ...-API.patch => 0598-added-Wither-API.patch} | 0 ...ng-of-PlayerChangeBeaconEffectEvent.patch} | 0 ...-spam-when-removing-chests-in-water.patch} | 0 ...e-for-always-placing-the-dragon-egg.patch} | 0 ...-PlayerStonecutterRecipeSelectEvent.patch} | 0 ...eash-variable-to-EntityUnleashEvent.patch} | 0 ...e-map-update-when-spawning-disabled.patch} | 0 ...shield-blocking-on-dimension-change.patch} | 0 ...atch => 0606-add-DragonEggFormEvent.patch} | 0 ...Event.patch => 0607-EntityMoveEvent.patch} | 0 ...isable-pathfinding-updates-on-block.patch} | 0 ... 0609-Inline-shift-direction-fields.patch} | 0 ...-adding-items-to-BlockDropItemEvent.patch} | 0 ...inThreadExecutor-to-BukkitScheduler.patch} | 0 ...entity-allow-attribute-registration.patch} | 0 ...ix-dead-slime-setSize-invincibility.patch} | 0 ...pes-should-return-an-immutable-list.patch} | 0 ....patch => 0615-misc-debugging-dumps.patch} | 0 ...port-for-hex-color-codes-in-console.patch} | 0 ...atch => 0617-Expose-Tracked-Players.patch} | 0 ...8-Remove-streams-from-SensorNearest.patch} | 0 ...ix-Wither-hostility-towards-players.patch} | 0 ...er-exception-on-empty-JsonList-file.patch} | 0 ...GUI.patch => 0621-Improve-ServerGUI.patch} | 0 ...ure-plate-EntityInteractEvent-for-i.patch} | 0 ...623-fix-converting-txt-to-json-file.patch} | 0 ...atch => 0624-Add-worldborder-events.patch} | 0 ...=> 0625-added-PlayerNameEntityEvent.patch} | 0 ...grindstones-from-overstacking-items.patch} | 0 ...h => 0627-Add-recipe-to-cook-events.patch} | 0 ...patch => 0628-Add-Block-isValidTool.patch} | 0 ...using-signs-inside-spawn-protection.patch} | 0 ...ch => 0630-Implement-Keyed-on-World.patch} | 0 ...ternative-constructor-for-Rotations.patch} | 0 ...y-API.patch => 0632-Item-Rarity-API.patch} | 0 ...imer-for-Wandering-Traders-spawned-.patch} | 0 ...py-TESign-isEditable-from-snapshots.patch} | 0 ...d-item-when-player-has-disconnected.patch} | 0 ...elist-use-configurable-kick-message.patch} | 0 ...gnore-result-of-PlayerEditBookEvent.patch} | 0 ...block-falling-causing-client-desync.patch} | 0 ...tch => 0639-Expose-protocol-version.patch} | 0 ...nt-suggestion-tooltips-in-AsyncTabC.patch} | 0 ...ab-completions-for-brigadier-comman.patch} | 0 ...temConsumeEvent-cancelling-properly.patch} | 0 ...patch => 0643-Add-bypass-host-check.patch} | 0 ...0644-Set-area-affect-cloud-rotation.patch} | 0 ...add-isDeeplySleeping-to-HumanEntity.patch} | 0 ...ting-give-items-on-item-drop-cancel.patch} | 0 ...add-consumeFuel-to-FurnaceBurnEvent.patch} | 0 ...-set-drop-chance-to-EntityEquipment.patch} | 0 ...ix-PigZombieAngerEvent-cancellation.patch} | 0 ...-checkReach-check-for-Shulker-boxes.patch} | 0 ...ix-PlayerItemHeldEvent-firing-twice.patch} | 0 ... => 0652-Added-PlayerDeepSleepEvent.patch} | 0 ...ld-API.patch => 0653-More-World-API.patch} | 0 ... 0654-Added-PlayerBedFailEnterEvent.patch} | 0 ...-to-convert-between-Component-and-B.patch} | 0 ...n-acting-as-a-bed-respawn-from-the-.patch} | 0 ...acon-activation-deactivation-events.patch} | 0 ...-RespawnFlags-to-PlayerRespawnEvent.patch} | 0 ...dd-Channel-initialization-listeners.patch} | 0 ...mands-if-tab-completion-is-disabled.patch} | 0 ...> 0661-Add-more-WanderingTrader-API.patch} | 0 ...dd-EntityBlockStorage-clearEntities.patch} | 0 ...ssage-to-PlayerAdvancementDoneEvent.patch} | 0 ...address-to-AsyncPlayerPreLoginEvent.patch} | 0 ...close.patch => 0665-Inventory-close.patch} | 0 ...reateEvent-players-and-end-platform.patch} | 0 ...-in-sunlight-API-for-Phantoms-and-S.patch} | 0 ...=> 0668-Fix-CraftPotionBrewer-cache.patch} | 0 ...atch => 0669-Add-basic-Datapack-API.patch} | 0 ...ment-variable-to-disable-server-gui.patch} | 0 ...itions-to-PlayerGameModeChangeEvent.patch} | 0 ... => 0672-ItemStack-repair-check-API.patch} | 0 ....patch => 0673-More-Enchantment-API.patch} | 0 ...option-to-load-extra-plugin-jars-no.patch} | 0 ...-and-optimise-world-force-upgrading.patch} | 0 ...PI.patch => 0676-Add-Mob-lookAt-API.patch} | 0 ...0677-Add-Unix-domain-socket-support.patch} | 0 ... => 0678-Add-EntityInsideBlockEvent.patch} | 0 ...79-Attributes-API-for-item-defaults.patch} | 0 ...hantCustom-emit-PlayerPurchaseEvent.patch} | 0 ...ause-to-Weather-ThunderChangeEvents.patch} | 0 ...patch => 0682-More-Lidded-Block-API.patch} | 0 ...83-Limit-item-frame-cursors-on-maps.patch} | 0 ...0684-Add-PufferFishStateChangeEvent.patch} | 0 ... => 0685-Add-PlayerKickEvent-causes.patch} | 0 ...erBucketEmptyEvent-result-itemstack.patch} | 0 ...tedContainer-instead-of-ReentrantLo.patch} | 0 ...-to-fix-items-merging-through-walls.patch} | 0 ...h => 0689-Add-BellRevealRaiderEvent.patch} | 0 ... 0690-Fix-invulnerable-end-crystals.patch} | 0 ...91-Add-ElderGuardianAppearanceEvent.patch} | 0 ...inventory-on-cancelled-pickup-event.patch} | 0 ...0693-Fix-dangerous-end-portal-logic.patch} | 0 ...-Biome-Mob-Lookups-for-Mob-Spawning.patch} | 0 ...-Make-item-validations-configurable.patch} | 0 ...0696-Add-more-line-of-sight-methods.patch} | 0 ... => 0697-add-per-world-spawn-limits.patch} | 0 ...plashEvent-for-water-splash-potions.patch} | 0 ...tus-dataconverter-for-pre-1.13-chun.patch} | 0 161 files changed, 130 insertions(+), 159 deletions(-) delete mode 100644 patches/removed/1.17/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch create mode 100644 patches/server/0540-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch rename patches/server/{0540-Beacon-API-custom-effect-ranges.patch => 0541-Beacon-API-custom-effect-ranges.patch} (100%) rename patches/server/{0541-Add-API-for-quit-reason.patch => 0542-Add-API-for-quit-reason.patch} (100%) rename patches/server/{0542-Seed-based-feature-search.patch => 0543-Seed-based-feature-search.patch} (100%) rename patches/server/{0543-Add-Wandering-Trader-spawn-rate-config-options.patch => 0544-Add-Wandering-Trader-spawn-rate-config-options.patch} (100%) rename patches/server/{0544-Significantly-improve-performance-of-the-end-generat.patch => 0545-Significantly-improve-performance-of-the-end-generat.patch} (100%) rename patches/server/{0545-Expose-world-spawn-angle.patch => 0546-Expose-world-spawn-angle.patch} (100%) rename patches/server/{0546-Add-Destroy-Speed-API.patch => 0547-Add-Destroy-Speed-API.patch} (100%) rename patches/server/{0547-Fix-Player-spawnParticle-x-y-z-precision-loss.patch => 0548-Fix-Player-spawnParticle-x-y-z-precision-loss.patch} (100%) rename patches/server/{0548-Add-LivingEntity-clearActiveItem.patch => 0549-Add-LivingEntity-clearActiveItem.patch} (100%) rename patches/server/{0549-Add-PlayerItemCooldownEvent.patch => 0550-Add-PlayerItemCooldownEvent.patch} (100%) rename patches/server/{0550-More-lightning-API.patch => 0551-More-lightning-API.patch} (100%) rename patches/server/{0551-Climbing-should-not-bypass-cramming-gamerule.patch => 0552-Climbing-should-not-bypass-cramming-gamerule.patch} (100%) rename patches/server/{0552-Added-missing-default-perms-for-commands.patch => 0553-Added-missing-default-perms-for-commands.patch} (100%) rename patches/server/{0553-Add-PlayerShearBlockEvent.patch => 0554-Add-PlayerShearBlockEvent.patch} (100%) rename patches/server/{0554-Set-spigots-verbose-world-setting-to-false-by-def.patch => 0555-Set-spigots-verbose-world-setting-to-false-by-def.patch} (100%) rename patches/server/{0555-Fix-curing-zombie-villager-discount-exploit.patch => 0556-Fix-curing-zombie-villager-discount-exploit.patch} (100%) rename patches/server/{0556-Limit-recipe-packets.patch => 0557-Limit-recipe-packets.patch} (100%) rename patches/server/{0557-Fix-CraftSound-backwards-compatibility.patch => 0558-Fix-CraftSound-backwards-compatibility.patch} (100%) rename patches/server/{0558-MC-4-Fix-item-position-desync.patch => 0559-MC-4-Fix-item-position-desync.patch} (100%) rename patches/server/{0559-Player-Chunk-Load-Unload-Events.patch => 0560-Player-Chunk-Load-Unload-Events.patch} (100%) rename patches/server/{0560-Optimize-Dynamic-get-Missing-Keys.patch => 0561-Optimize-Dynamic-get-Missing-Keys.patch} (100%) rename patches/server/{0561-Expose-LivingEntity-hurt-direction.patch => 0562-Expose-LivingEntity-hurt-direction.patch} (100%) rename patches/server/{0562-Add-OBSTRUCTED-reason-to-BedEnterResult.patch => 0563-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} (100%) rename patches/server/{0563-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch => 0564-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch} (100%) rename patches/server/{0564-added-PlayerTradeEvent.patch => 0565-added-PlayerTradeEvent.patch} (100%) rename patches/server/{0565-Implement-TargetHitEvent.patch => 0566-Implement-TargetHitEvent.patch} (100%) rename patches/server/{0566-Additional-Block-Material-API-s.patch => 0567-Additional-Block-Material-API-s.patch} (100%) rename patches/server/{0567-Fix-harming-potion-dupe.patch => 0568-Fix-harming-potion-dupe.patch} (100%) rename patches/server/{0568-Implement-API-to-get-Material-from-Boats-and-Minecar.patch => 0569-Implement-API-to-get-Material-from-Boats-and-Minecar.patch} (100%) rename patches/server/{0569-Cache-burn-durations.patch => 0570-Cache-burn-durations.patch} (100%) rename patches/server/{0570-Allow-disabling-mob-spawner-spawn-egg-transformation.patch => 0571-Allow-disabling-mob-spawner-spawn-egg-transformation.patch} (100%) rename patches/server/{0571-Implement-PlayerFlowerPotManipulateEvent.patch => 0572-Implement-PlayerFlowerPotManipulateEvent.patch} (100%) rename patches/server/{0572-Fix-interact-event-not-being-called-in-adventure.patch => 0573-Fix-interact-event-not-being-called-in-adventure.patch} (100%) rename patches/server/{0573-Zombie-API-breaking-doors.patch => 0574-Zombie-API-breaking-doors.patch} (100%) rename patches/server/{0574-Fix-nerfed-slime-when-splitting.patch => 0575-Fix-nerfed-slime-when-splitting.patch} (100%) rename patches/server/{0575-Add-EntityLoadCrossbowEvent.patch => 0576-Add-EntityLoadCrossbowEvent.patch} (100%) rename patches/server/{0576-Guardian-beam-workaround.patch => 0577-Guardian-beam-workaround.patch} (100%) rename patches/server/{0577-Added-WorldGameRuleChangeEvent.patch => 0578-Added-WorldGameRuleChangeEvent.patch} (100%) rename patches/server/{0578-Added-ServerResourcesReloadedEvent.patch => 0579-Added-ServerResourcesReloadedEvent.patch} (100%) rename patches/server/{0579-Added-world-settings-for-mobs-picking-up-loot.patch => 0580-Added-world-settings-for-mobs-picking-up-loot.patch} (100%) rename patches/server/{0580-Implemented-BlockFailedDispenseEvent.patch => 0581-Implemented-BlockFailedDispenseEvent.patch} (100%) rename patches/server/{0581-Added-PlayerLecternPageChangeEvent.patch => 0582-Added-PlayerLecternPageChangeEvent.patch} (100%) rename patches/server/{0582-Added-PlayerLoomPatternSelectEvent.patch => 0583-Added-PlayerLoomPatternSelectEvent.patch} (100%) rename patches/server/{0583-Configurable-door-breaking-difficulty.patch => 0584-Configurable-door-breaking-difficulty.patch} (100%) rename patches/server/{0584-Empty-commands-shall-not-be-dispatched.patch => 0585-Empty-commands-shall-not-be-dispatched.patch} (100%) rename patches/server/{0585-Implement-API-to-expose-exact-interaction-point.patch => 0586-Implement-API-to-expose-exact-interaction-point.patch} (100%) rename patches/server/{0586-Remove-stale-POIs.patch => 0587-Remove-stale-POIs.patch} (100%) rename patches/server/{0587-Fix-villager-boat-exploit.patch => 0588-Fix-villager-boat-exploit.patch} (100%) rename patches/server/{0588-Add-sendOpLevel-API.patch => 0589-Add-sendOpLevel-API.patch} (100%) rename patches/server/{0589-Add-StructureLocateEvent.patch => 0590-Add-StructureLocateEvent.patch} (100%) rename patches/server/{0590-Collision-option-for-requiring-a-player-participant.patch => 0591-Collision-option-for-requiring-a-player-participant.patch} (100%) rename patches/server/{0591-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch => 0592-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch} (100%) rename patches/server/{0592-Return-chat-component-with-empty-text-instead-of-thr.patch => 0593-Return-chat-component-with-empty-text-instead-of-thr.patch} (100%) rename patches/server/{0593-Make-schedule-command-per-world.patch => 0594-Make-schedule-command-per-world.patch} (100%) rename patches/server/{0594-Configurable-max-leash-distance.patch => 0595-Configurable-max-leash-distance.patch} (100%) rename patches/server/{0595-Implement-BlockPreDispenseEvent.patch => 0596-Implement-BlockPreDispenseEvent.patch} (100%) rename patches/server/{0596-Added-Vanilla-Entity-Tags.patch => 0597-Added-Vanilla-Entity-Tags.patch} (100%) rename patches/server/{0597-added-Wither-API.patch => 0598-added-Wither-API.patch} (100%) rename patches/server/{0598-Added-firing-of-PlayerChangeBeaconEffectEvent.patch => 0599-Added-firing-of-PlayerChangeBeaconEffectEvent.patch} (100%) rename patches/server/{0599-Fix-console-spam-when-removing-chests-in-water.patch => 0600-Fix-console-spam-when-removing-chests-in-water.patch} (100%) rename patches/server/{0600-Add-toggle-for-always-placing-the-dragon-egg.patch => 0601-Add-toggle-for-always-placing-the-dragon-egg.patch} (100%) rename patches/server/{0601-Added-PlayerStonecutterRecipeSelectEvent.patch => 0602-Added-PlayerStonecutterRecipeSelectEvent.patch} (100%) rename patches/server/{0602-Add-dropLeash-variable-to-EntityUnleashEvent.patch => 0603-Add-dropLeash-variable-to-EntityUnleashEvent.patch} (100%) rename patches/server/{0603-Skip-distance-map-update-when-spawning-disabled.patch => 0604-Skip-distance-map-update-when-spawning-disabled.patch} (100%) rename patches/server/{0604-Reset-shield-blocking-on-dimension-change.patch => 0605-Reset-shield-blocking-on-dimension-change.patch} (100%) rename patches/server/{0605-add-DragonEggFormEvent.patch => 0606-add-DragonEggFormEvent.patch} (100%) rename patches/server/{0606-EntityMoveEvent.patch => 0607-EntityMoveEvent.patch} (100%) rename patches/server/{0607-added-option-to-disable-pathfinding-updates-on-block.patch => 0608-added-option-to-disable-pathfinding-updates-on-block.patch} (100%) rename patches/server/{0608-Inline-shift-direction-fields.patch => 0609-Inline-shift-direction-fields.patch} (100%) rename patches/server/{0609-Allow-adding-items-to-BlockDropItemEvent.patch => 0610-Allow-adding-items-to-BlockDropItemEvent.patch} (100%) rename patches/server/{0610-Add-getMainThreadExecutor-to-BukkitScheduler.patch => 0611-Add-getMainThreadExecutor-to-BukkitScheduler.patch} (100%) rename patches/server/{0611-living-entity-allow-attribute-registration.patch => 0612-living-entity-allow-attribute-registration.patch} (100%) rename patches/server/{0612-fix-dead-slime-setSize-invincibility.patch => 0613-fix-dead-slime-setSize-invincibility.patch} (100%) rename patches/server/{0613-Merchant-getRecipes-should-return-an-immutable-list.patch => 0614-Merchant-getRecipes-should-return-an-immutable-list.patch} (100%) rename patches/server/{0614-misc-debugging-dumps.patch => 0615-misc-debugging-dumps.patch} (100%) rename patches/server/{0615-Add-support-for-hex-color-codes-in-console.patch => 0616-Add-support-for-hex-color-codes-in-console.patch} (100%) rename patches/server/{0616-Expose-Tracked-Players.patch => 0617-Expose-Tracked-Players.patch} (100%) rename patches/server/{0617-Remove-streams-from-SensorNearest.patch => 0618-Remove-streams-from-SensorNearest.patch} (100%) rename patches/server/{0618-MC-29274-Fix-Wither-hostility-towards-players.patch => 0619-MC-29274-Fix-Wither-hostility-towards-players.patch} (100%) rename patches/server/{0619-Throw-proper-exception-on-empty-JsonList-file.patch => 0620-Throw-proper-exception-on-empty-JsonList-file.patch} (100%) rename patches/server/{0620-Improve-ServerGUI.patch => 0621-Improve-ServerGUI.patch} (100%) rename patches/server/{0621-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch => 0622-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch} (100%) rename patches/server/{0622-fix-converting-txt-to-json-file.patch => 0623-fix-converting-txt-to-json-file.patch} (100%) rename patches/server/{0623-Add-worldborder-events.patch => 0624-Add-worldborder-events.patch} (100%) rename patches/server/{0624-added-PlayerNameEntityEvent.patch => 0625-added-PlayerNameEntityEvent.patch} (100%) rename patches/server/{0625-Prevent-grindstones-from-overstacking-items.patch => 0626-Prevent-grindstones-from-overstacking-items.patch} (100%) rename patches/server/{0626-Add-recipe-to-cook-events.patch => 0627-Add-recipe-to-cook-events.patch} (100%) rename patches/server/{0627-Add-Block-isValidTool.patch => 0628-Add-Block-isValidTool.patch} (100%) rename patches/server/{0628-Allow-using-signs-inside-spawn-protection.patch => 0629-Allow-using-signs-inside-spawn-protection.patch} (100%) rename patches/server/{0629-Implement-Keyed-on-World.patch => 0630-Implement-Keyed-on-World.patch} (100%) rename patches/server/{0630-Add-fast-alternative-constructor-for-Rotations.patch => 0631-Add-fast-alternative-constructor-for-Rotations.patch} (100%) rename patches/server/{0631-Item-Rarity-API.patch => 0632-Item-Rarity-API.patch} (100%) rename patches/server/{0632-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch => 0633-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch} (100%) rename patches/server/{0633-copy-TESign-isEditable-from-snapshots.patch => 0634-copy-TESign-isEditable-from-snapshots.patch} (100%) rename patches/server/{0634-Drop-carried-item-when-player-has-disconnected.patch => 0635-Drop-carried-item-when-player-has-disconnected.patch} (100%) rename patches/server/{0635-forced-whitelist-use-configurable-kick-message.patch => 0636-forced-whitelist-use-configurable-kick-message.patch} (100%) rename patches/server/{0636-Don-t-ignore-result-of-PlayerEditBookEvent.patch => 0637-Don-t-ignore-result-of-PlayerEditBookEvent.patch} (100%) rename patches/server/{0637-fix-cancelling-block-falling-causing-client-desync.patch => 0638-fix-cancelling-block-falling-causing-client-desync.patch} (100%) rename patches/server/{0638-Expose-protocol-version.patch => 0639-Expose-protocol-version.patch} (100%) rename patches/server/{0639-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch => 0640-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} (100%) rename patches/server/{0640-Enhance-console-tab-completions-for-brigadier-comman.patch => 0641-Enhance-console-tab-completions-for-brigadier-comman.patch} (100%) rename patches/server/{0641-Fix-PlayerItemConsumeEvent-cancelling-properly.patch => 0642-Fix-PlayerItemConsumeEvent-cancelling-properly.patch} (100%) rename patches/server/{0642-Add-bypass-host-check.patch => 0643-Add-bypass-host-check.patch} (100%) rename patches/server/{0643-Set-area-affect-cloud-rotation.patch => 0644-Set-area-affect-cloud-rotation.patch} (100%) rename patches/server/{0644-add-isDeeplySleeping-to-HumanEntity.patch => 0645-add-isDeeplySleeping-to-HumanEntity.patch} (100%) rename patches/server/{0645-Fix-duplicating-give-items-on-item-drop-cancel.patch => 0646-Fix-duplicating-give-items-on-item-drop-cancel.patch} (100%) rename patches/server/{0646-add-consumeFuel-to-FurnaceBurnEvent.patch => 0647-add-consumeFuel-to-FurnaceBurnEvent.patch} (100%) rename patches/server/{0647-add-get-set-drop-chance-to-EntityEquipment.patch => 0648-add-get-set-drop-chance-to-EntityEquipment.patch} (100%) rename patches/server/{0648-fix-PigZombieAngerEvent-cancellation.patch => 0649-fix-PigZombieAngerEvent-cancellation.patch} (100%) rename patches/server/{0649-Fix-checkReach-check-for-Shulker-boxes.patch => 0650-Fix-checkReach-check-for-Shulker-boxes.patch} (100%) rename patches/server/{0650-fix-PlayerItemHeldEvent-firing-twice.patch => 0651-fix-PlayerItemHeldEvent-firing-twice.patch} (100%) rename patches/server/{0651-Added-PlayerDeepSleepEvent.patch => 0652-Added-PlayerDeepSleepEvent.patch} (100%) rename patches/server/{0652-More-World-API.patch => 0653-More-World-API.patch} (100%) rename patches/server/{0653-Added-PlayerBedFailEnterEvent.patch => 0654-Added-PlayerBedFailEnterEvent.patch} (100%) rename patches/server/{0654-Implement-methods-to-convert-between-Component-and-B.patch => 0655-Implement-methods-to-convert-between-Component-and-B.patch} (100%) rename patches/server/{0655-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch => 0656-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch} (100%) rename patches/server/{0656-Introduce-beacon-activation-deactivation-events.patch => 0657-Introduce-beacon-activation-deactivation-events.patch} (100%) rename patches/server/{0657-add-RespawnFlags-to-PlayerRespawnEvent.patch => 0658-add-RespawnFlags-to-PlayerRespawnEvent.patch} (100%) rename patches/server/{0658-Add-Channel-initialization-listeners.patch => 0659-Add-Channel-initialization-listeners.patch} (100%) rename patches/server/{0659-Send-empty-commands-if-tab-completion-is-disabled.patch => 0660-Send-empty-commands-if-tab-completion-is-disabled.patch} (100%) rename patches/server/{0660-Add-more-WanderingTrader-API.patch => 0661-Add-more-WanderingTrader-API.patch} (100%) rename patches/server/{0661-Add-EntityBlockStorage-clearEntities.patch => 0662-Add-EntityBlockStorage-clearEntities.patch} (100%) rename patches/server/{0662-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch => 0663-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch} (100%) rename patches/server/{0663-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch => 0664-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch} (100%) rename patches/server/{0664-Inventory-close.patch => 0665-Inventory-close.patch} (100%) rename patches/server/{0665-call-PortalCreateEvent-players-and-end-platform.patch => 0666-call-PortalCreateEvent-players-and-end-platform.patch} (100%) rename patches/server/{0666-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch => 0667-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch} (100%) rename patches/server/{0667-Fix-CraftPotionBrewer-cache.patch => 0668-Fix-CraftPotionBrewer-cache.patch} (100%) rename patches/server/{0668-Add-basic-Datapack-API.patch => 0669-Add-basic-Datapack-API.patch} (100%) rename patches/server/{0669-Add-environment-variable-to-disable-server-gui.patch => 0670-Add-environment-variable-to-disable-server-gui.patch} (100%) rename patches/server/{0670-additions-to-PlayerGameModeChangeEvent.patch => 0671-additions-to-PlayerGameModeChangeEvent.patch} (100%) rename patches/server/{0671-ItemStack-repair-check-API.patch => 0672-ItemStack-repair-check-API.patch} (100%) rename patches/server/{0672-More-Enchantment-API.patch => 0673-More-Enchantment-API.patch} (100%) rename patches/server/{0673-Add-command-line-option-to-load-extra-plugin-jars-no.patch => 0674-Add-command-line-option-to-load-extra-plugin-jars-no.patch} (100%) rename patches/server/{0674-Fix-and-optimise-world-force-upgrading.patch => 0675-Fix-and-optimise-world-force-upgrading.patch} (100%) rename patches/server/{0675-Add-Mob-lookAt-API.patch => 0676-Add-Mob-lookAt-API.patch} (100%) rename patches/server/{0676-Add-Unix-domain-socket-support.patch => 0677-Add-Unix-domain-socket-support.patch} (100%) rename patches/server/{0677-Add-EntityInsideBlockEvent.patch => 0678-Add-EntityInsideBlockEvent.patch} (100%) rename patches/server/{0678-Attributes-API-for-item-defaults.patch => 0679-Attributes-API-for-item-defaults.patch} (100%) rename patches/server/{0679-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch => 0680-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch} (100%) rename patches/server/{0680-Add-cause-to-Weather-ThunderChangeEvents.patch => 0681-Add-cause-to-Weather-ThunderChangeEvents.patch} (100%) rename patches/server/{0681-More-Lidded-Block-API.patch => 0682-More-Lidded-Block-API.patch} (100%) rename patches/server/{0682-Limit-item-frame-cursors-on-maps.patch => 0683-Limit-item-frame-cursors-on-maps.patch} (100%) rename patches/server/{0683-Add-PufferFishStateChangeEvent.patch => 0684-Add-PufferFishStateChangeEvent.patch} (100%) rename patches/server/{0684-Add-PlayerKickEvent-causes.patch => 0685-Add-PlayerKickEvent-causes.patch} (100%) rename patches/server/{0685-Fix-PlayerBucketEmptyEvent-result-itemstack.patch => 0686-Fix-PlayerBucketEmptyEvent-result-itemstack.patch} (100%) rename patches/server/{0686-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch => 0687-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch} (100%) rename patches/server/{0687-Add-option-to-fix-items-merging-through-walls.patch => 0688-Add-option-to-fix-items-merging-through-walls.patch} (100%) rename patches/server/{0688-Add-BellRevealRaiderEvent.patch => 0689-Add-BellRevealRaiderEvent.patch} (100%) rename patches/server/{0689-Fix-invulnerable-end-crystals.patch => 0690-Fix-invulnerable-end-crystals.patch} (100%) rename patches/server/{0690-Add-ElderGuardianAppearanceEvent.patch => 0691-Add-ElderGuardianAppearanceEvent.patch} (100%) rename patches/server/{0691-Reset-villager-inventory-on-cancelled-pickup-event.patch => 0692-Reset-villager-inventory-on-cancelled-pickup-event.patch} (100%) rename patches/server/{0692-Fix-dangerous-end-portal-logic.patch => 0693-Fix-dangerous-end-portal-logic.patch} (100%) rename patches/server/{0693-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch => 0694-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch} (100%) rename patches/server/{0694-Make-item-validations-configurable.patch => 0695-Make-item-validations-configurable.patch} (100%) rename patches/server/{0695-Add-more-line-of-sight-methods.patch => 0696-Add-more-line-of-sight-methods.patch} (100%) rename patches/server/{0696-add-per-world-spawn-limits.patch => 0697-add-per-world-spawn-limits.patch} (100%) rename patches/server/{0697-Fix-PotionSplashEvent-for-water-splash-potions.patch => 0698-Fix-PotionSplashEvent-for-water-splash-potions.patch} (100%) rename patches/server/{0698-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch => 0699-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch} (100%) diff --git a/patches/removed/1.17/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/patches/removed/1.17/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch deleted file mode 100644 index 4d8b1d0357..0000000000 --- a/patches/removed/1.17/0539-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 4 Aug 2020 22:24:15 +0200 -Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections -1.17 Update: Please do this k thx bb -I utilized the IDE to convert streams to non streams code, so shouldn't -be any risk of behavior change. Only did minor optimization of the -generated code set to remove unnecessary things. - -I expect us to just drop this patch on next major update and re-apply -it with the IDE again and re-apply the collections optimization. - -Optimize collection by creating a list instead of a set of the key and value. - -This lets us get faster foreach iteration, as well as avoids map lookups on -the values when needed. - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -index ba8ee93032aabe7ec4ecf52d452e1a580d6ebc20..2ef0e04af771e14f8d71aef4ccb81d3b81db7df5 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -@@ -33,28 +33,31 @@ public class PathFinder { - this.openSet.a(); - this.nodeEvaluator.prepare(world, mob); - Node pathpoint = this.nodeEvaluator.getStart(); -- Map map = (Map) positions.stream().collect(Collectors.toMap((blockposition) -> { -- return this.nodeEvaluator.getGoal((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); -- }, Function.identity())); -- Path pathentity = this.findPath(pathpoint, map, followRange, distance, rangeMultiplier); -+ // Paper start - remove streams - and optimize collection -+ List> map = Lists.newArrayList(); -+ for (BlockPos blockposition : positions) { -+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal((double) blockposition.getX(), blockposition.getY(), blockposition.getZ()), blockposition)); -+ } -+ // Paper end -+ Path pathentity = this.a(pathpoint, map, followRange, distance, rangeMultiplier); - - this.nodeEvaluator.done(); - return pathentity; - } - - @Nullable -- private Path findPath(Node startNode, Map positions, float followRange, int distance, float rangeMultiplier) { -- Set set = positions.keySet(); -+ private Path a(Node pathpoint, List> list, float f, int i, float f1) { // Paper - optimize collection -+ //Set set = map.keySet(); // Paper - -- startNode.g = 0.0F; -- startNode.h = this.getBestH(startNode, set); -- startNode.f = startNode.h; -+ pathpoint.g = 0.0F; -+ pathpoint.h = this.a(pathpoint, list); // Paper - optimize collection -+ pathpoint.f = pathpoint.h; - this.openSet.a(); -- this.openSet.a(startNode); -+ this.openSet.a(pathpoint); - Set set1 = ImmutableSet.of(); - int j = 0; -- Set set2 = Sets.newHashSetWithExpectedSize(set.size()); -- int k = (int) ((float) this.maxVisitedNodes * rangeMultiplier); -+ List> set2 = Lists.newArrayListWithExpectedSize(list.size()); // Paper - optimize collection -+ int k = (int) ((float) this.maxVisitedNodes * f1); - - while (!this.openSet.e()) { - ++j; -@@ -65,14 +68,15 @@ public class PathFinder { - Node pathpoint1 = this.openSet.c(); - - pathpoint1.closed = true; -- Iterator iterator = set.iterator(); -- -- while (iterator.hasNext()) { -- Target pathdestination = (Target) iterator.next(); -+ // Paper start - optimize collection -+ for (int i1 = 0; i1 < list.size(); i1++) { -+ Map.Entry entry = list.get(i1); -+ Target pathdestination = entry.getKey(); - -- if (pathpoint1.distanceManhattan((Node) pathdestination) <= (float) distance) { -+ if (pathpoint1.distanceManhattan((Node) pathdestination) <= (float) i) { - pathdestination.setReached(); -- set2.add(pathdestination); -+ set2.add(entry); -+ // Paper end - } - } - -@@ -80,7 +84,7 @@ public class PathFinder { - break; - } - -- if (pathpoint1.distanceTo(startNode) < followRange) { -+ if (pathpoint1.distanceTo(pathpoint) < f) { - int l = this.nodeEvaluator.getNeighbors(this.neighbors, pathpoint1); - - for (int i1 = 0; i1 < l; ++i1) { -@@ -90,10 +94,10 @@ public class PathFinder { - pathpoint2.walkedDistance = pathpoint1.walkedDistance + f2; - float f3 = pathpoint1.g + f2 + pathpoint2.costMalus; - -- if (pathpoint2.walkedDistance < followRange && (!pathpoint2.inOpenSet() || f3 < pathpoint2.g)) { -+ if (pathpoint2.walkedDistance < f && (!pathpoint2.inOpenSet() || f3 < pathpoint2.g)) { - pathpoint2.cameFrom = pathpoint1; - pathpoint2.g = f3; -- pathpoint2.h = this.getBestH(pathpoint2, set) * 1.5F; -+ pathpoint2.h = this.a(pathpoint2, list) * 1.5F; // Paper - list instead of set - if (pathpoint2.inOpenSet()) { - this.openSet.a(pathpoint2, pathpoint2.g + pathpoint2.h); - } else { -@@ -105,31 +109,32 @@ public class PathFinder { - } - } - -- Optional optional = !set2.isEmpty() ? set2.stream().map((pathdestination1) -> { -- return this.reconstructPath(pathdestination1.getBestNode(), (BlockPos) positions.get(pathdestination1), true); -- }).min(Comparator.comparingInt(Path::getNodeCount)) : set.stream().map((pathdestination1) -> { -- return this.reconstructPath(pathdestination1.getBestNode(), (BlockPos) positions.get(pathdestination1), false); -- }).min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount)); -- -- if (!optional.isPresent()) { -- return null; -- } else { -- Path pathentity = (Path) optional.get(); -- -- return pathentity; -+ // Paper start - remove streams - and optimize collection -+ Path best = null; -+ boolean useSet1 = set2.isEmpty(); -+ Comparator comparator = useSet1 ? Comparator.comparingInt(Path::getNodeCount) -+ : Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount); -+ for (Map.Entry entry : useSet1 ? list : set2) { -+ Path pathEntity = this.reconstructPath(entry.getKey().getBestNode(), entry.getValue(), !useSet1); -+ if (best == null || comparator.compare(pathEntity, best) < 0) -+ best = pathEntity; - } -+ return best; -+ // Paper end - } - -- private float getBestH(Node node, Set targets) { -+ private float a(Node pathpoint, List> list) { // Paper - optimize collection - float f = Float.MAX_VALUE; - - float f1; - -- for (Iterator iterator = targets.iterator(); iterator.hasNext(); f = Math.min(f1, f)) { -- Target pathdestination = (Target) iterator.next(); -+ // Paper start - optimize collection -+ for (int i = 0, listSize = list.size(); i < listSize; f = Math.min(f1, f), i++) { // Paper -+ Target pathdestination = list.get(i).getKey(); // Paper -+ // Paper end - -- f1 = node.distanceTo(pathdestination); -- pathdestination.updateBest(f1, node); -+ f1 = pathpoint.distanceTo(pathdestination); -+ pathdestination.updateBest(f1, pathpoint); - } - - return f; diff --git a/patches/server/0540-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/patches/server/0540-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch new file mode 100644 index 0000000000..bb6aaed2d5 --- /dev/null +++ b/patches/server/0540-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 4 Aug 2020 22:24:15 +0200 +Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections + +1.17 Update: Please do this k thx bb +I utilized the IDE to convert streams to non streams code, so shouldn't +be any risk of behavior change. Only did minor optimization of the +generated code set to remove unnecessary things. + +I expect us to just drop this patch on next major update and re-apply +it with the IDE again and re-apply the collections optimization. + +Optimize collection by creating a list instead of a set of the key and value. + +This lets us get faster foreach iteration, as well as avoids map lookups on +the values when needed. + +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +index 800d464207026d145056b39b298045121342b899..6062f5154c55179e1cf3b280e6dc56d2f561987d 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +@@ -35,27 +35,31 @@ public class PathFinder { + this.openSet.clear(); + this.nodeEvaluator.prepare(world, mob); + Node node = this.nodeEvaluator.getStart(); +- Map map = positions.stream().collect(Collectors.toMap((blockPos) -> { +- return this.nodeEvaluator.getGoal((double)blockPos.getX(), (double)blockPos.getY(), (double)blockPos.getZ()); +- }, Function.identity())); ++ // Paper start - remove streams - and optimize collection ++ List> map = Lists.newArrayList(); ++ for (BlockPos blockPos : positions) { ++ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal(blockPos.getX(), blockPos.getY(), blockPos.getZ()), blockPos)); ++ } ++ // Paper end + Path path = this.findPath(world.getProfiler(), node, map, followRange, distance, rangeMultiplier); + this.nodeEvaluator.done(); + return path; + } + + @Nullable +- private Path findPath(ProfilerFiller profiler, Node startNode, Map positions, float followRange, int distance, float rangeMultiplier) { ++ // Paper start - optimize collection ++ private Path findPath(ProfilerFiller profiler, Node startNode, List> positions, float followRange, int distance, float rangeMultiplier) { + profiler.push("find_path"); + profiler.markForCharting(MetricCategory.PATH_FINDING); +- Set set = positions.keySet(); ++ //Set set = positions.keySet(); + startNode.g = 0.0F; +- startNode.h = this.getBestH(startNode, set); ++ startNode.h = this.getBestH(startNode, positions); // Paper - optimize collection + startNode.f = startNode.h; + this.openSet.clear(); + this.openSet.insert(startNode); +- Set set2 = ImmutableSet.of(); ++ //Set set2 = ImmutableSet.of(); // Paper - unused - diff on change + int i = 0; +- Set set3 = Sets.newHashSetWithExpectedSize(set.size()); ++ List> entryList = Lists.newArrayListWithExpectedSize(positions.size()); // Paper - optimize collection + int j = (int)((float)this.maxVisitedNodes * rangeMultiplier); + + while(!this.openSet.isEmpty()) { +@@ -67,14 +71,18 @@ public class PathFinder { + Node node = this.openSet.pop(); + node.closed = true; + +- for(Target target : set) { ++ // Paper start - optimize collection ++ for(int i1 = 0; i1 < positions.size(); i1++) { ++ final Map.Entry entry = positions.get(i1); ++ Target target = entry.getKey(); + if (node.distanceManhattan(target) <= (float)distance) { + target.setReached(); +- set3.add(target); ++ entryList.add(entry); ++ // Paper end + } + } + +- if (!set3.isEmpty()) { ++ if (!entryList.isEmpty()) { // Paper - rename variable + break; + } + +@@ -89,7 +97,7 @@ public class PathFinder { + if (node2.walkedDistance < followRange && (!node2.inOpenSet() || g < node2.g)) { + node2.cameFrom = node; + node2.g = g; +- node2.h = this.getBestH(node2, set) * 1.5F; ++ node2.h = this.getBestH(node2, positions) * 1.5F; // Paper - list instead of set + if (node2.inOpenSet()) { + this.openSet.changeCost(node2, node2.g + node2.h); + } else { +@@ -101,19 +109,27 @@ public class PathFinder { + } + } + +- Optional optional = !set3.isEmpty() ? set3.stream().map((target) -> { +- return this.reconstructPath(target.getBestNode(), positions.get(target), true); +- }).min(Comparator.comparingInt(Path::getNodeCount)) : set.stream().map((target) -> { +- return this.reconstructPath(target.getBestNode(), positions.get(target), false); +- }).min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount)); +- profiler.pop(); +- return !optional.isPresent() ? null : optional.get(); ++ // Paper start - remove streams - and optimize collection ++ Path best = null; ++ boolean entryListIsEmpty = entryList.isEmpty(); ++ Comparator comparator = entryListIsEmpty ? Comparator.comparingInt(Path::getNodeCount) ++ : Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount); ++ for (Map.Entry entry : entryListIsEmpty ? positions : entryList) { ++ Path path = this.reconstructPath(entry.getKey().getBestNode(), entry.getValue(), !entryListIsEmpty); ++ if (best == null || comparator.compare(path, best) < 0) ++ best = path; ++ } ++ return best; ++ // Paper end + } + +- private float getBestH(Node node, Set targets) { ++ private float getBestH(Node node, List> targets) { // Paper - optimize collection - Set -> List> + float f = Float.MAX_VALUE; + +- for(Target target : targets) { ++ // Paper start - optimize collection ++ for (int i = 0, targetsSize = targets.size(); i < targetsSize; i++) { ++ final Target target = targets.get(i).getKey(); ++ // Paper end + float g = node.distanceTo(target); + target.updateBest(g, node); + f = Math.min(g, f); diff --git a/patches/server/0540-Beacon-API-custom-effect-ranges.patch b/patches/server/0541-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from patches/server/0540-Beacon-API-custom-effect-ranges.patch rename to patches/server/0541-Beacon-API-custom-effect-ranges.patch diff --git a/patches/server/0541-Add-API-for-quit-reason.patch b/patches/server/0542-Add-API-for-quit-reason.patch similarity index 100% rename from patches/server/0541-Add-API-for-quit-reason.patch rename to patches/server/0542-Add-API-for-quit-reason.patch diff --git a/patches/server/0542-Seed-based-feature-search.patch b/patches/server/0543-Seed-based-feature-search.patch similarity index 100% rename from patches/server/0542-Seed-based-feature-search.patch rename to patches/server/0543-Seed-based-feature-search.patch diff --git a/patches/server/0543-Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server/0544-Add-Wandering-Trader-spawn-rate-config-options.patch similarity index 100% rename from patches/server/0543-Add-Wandering-Trader-spawn-rate-config-options.patch rename to patches/server/0544-Add-Wandering-Trader-spawn-rate-config-options.patch diff --git a/patches/server/0544-Significantly-improve-performance-of-the-end-generat.patch b/patches/server/0545-Significantly-improve-performance-of-the-end-generat.patch similarity index 100% rename from patches/server/0544-Significantly-improve-performance-of-the-end-generat.patch rename to patches/server/0545-Significantly-improve-performance-of-the-end-generat.patch diff --git a/patches/server/0545-Expose-world-spawn-angle.patch b/patches/server/0546-Expose-world-spawn-angle.patch similarity index 100% rename from patches/server/0545-Expose-world-spawn-angle.patch rename to patches/server/0546-Expose-world-spawn-angle.patch diff --git a/patches/server/0546-Add-Destroy-Speed-API.patch b/patches/server/0547-Add-Destroy-Speed-API.patch similarity index 100% rename from patches/server/0546-Add-Destroy-Speed-API.patch rename to patches/server/0547-Add-Destroy-Speed-API.patch diff --git a/patches/server/0547-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/patches/server/0548-Fix-Player-spawnParticle-x-y-z-precision-loss.patch similarity index 100% rename from patches/server/0547-Fix-Player-spawnParticle-x-y-z-precision-loss.patch rename to patches/server/0548-Fix-Player-spawnParticle-x-y-z-precision-loss.patch diff --git a/patches/server/0548-Add-LivingEntity-clearActiveItem.patch b/patches/server/0549-Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from patches/server/0548-Add-LivingEntity-clearActiveItem.patch rename to patches/server/0549-Add-LivingEntity-clearActiveItem.patch diff --git a/patches/server/0549-Add-PlayerItemCooldownEvent.patch b/patches/server/0550-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from patches/server/0549-Add-PlayerItemCooldownEvent.patch rename to patches/server/0550-Add-PlayerItemCooldownEvent.patch diff --git a/patches/server/0550-More-lightning-API.patch b/patches/server/0551-More-lightning-API.patch similarity index 100% rename from patches/server/0550-More-lightning-API.patch rename to patches/server/0551-More-lightning-API.patch diff --git a/patches/server/0551-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/0552-Climbing-should-not-bypass-cramming-gamerule.patch similarity index 100% rename from patches/server/0551-Climbing-should-not-bypass-cramming-gamerule.patch rename to patches/server/0552-Climbing-should-not-bypass-cramming-gamerule.patch diff --git a/patches/server/0552-Added-missing-default-perms-for-commands.patch b/patches/server/0553-Added-missing-default-perms-for-commands.patch similarity index 100% rename from patches/server/0552-Added-missing-default-perms-for-commands.patch rename to patches/server/0553-Added-missing-default-perms-for-commands.patch diff --git a/patches/server/0553-Add-PlayerShearBlockEvent.patch b/patches/server/0554-Add-PlayerShearBlockEvent.patch similarity index 100% rename from patches/server/0553-Add-PlayerShearBlockEvent.patch rename to patches/server/0554-Add-PlayerShearBlockEvent.patch diff --git a/patches/server/0554-Set-spigots-verbose-world-setting-to-false-by-def.patch b/patches/server/0555-Set-spigots-verbose-world-setting-to-false-by-def.patch similarity index 100% rename from patches/server/0554-Set-spigots-verbose-world-setting-to-false-by-def.patch rename to patches/server/0555-Set-spigots-verbose-world-setting-to-false-by-def.patch diff --git a/patches/server/0555-Fix-curing-zombie-villager-discount-exploit.patch b/patches/server/0556-Fix-curing-zombie-villager-discount-exploit.patch similarity index 100% rename from patches/server/0555-Fix-curing-zombie-villager-discount-exploit.patch rename to patches/server/0556-Fix-curing-zombie-villager-discount-exploit.patch diff --git a/patches/server/0556-Limit-recipe-packets.patch b/patches/server/0557-Limit-recipe-packets.patch similarity index 100% rename from patches/server/0556-Limit-recipe-packets.patch rename to patches/server/0557-Limit-recipe-packets.patch diff --git a/patches/server/0557-Fix-CraftSound-backwards-compatibility.patch b/patches/server/0558-Fix-CraftSound-backwards-compatibility.patch similarity index 100% rename from patches/server/0557-Fix-CraftSound-backwards-compatibility.patch rename to patches/server/0558-Fix-CraftSound-backwards-compatibility.patch diff --git a/patches/server/0558-MC-4-Fix-item-position-desync.patch b/patches/server/0559-MC-4-Fix-item-position-desync.patch similarity index 100% rename from patches/server/0558-MC-4-Fix-item-position-desync.patch rename to patches/server/0559-MC-4-Fix-item-position-desync.patch diff --git a/patches/server/0559-Player-Chunk-Load-Unload-Events.patch b/patches/server/0560-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from patches/server/0559-Player-Chunk-Load-Unload-Events.patch rename to patches/server/0560-Player-Chunk-Load-Unload-Events.patch diff --git a/patches/server/0560-Optimize-Dynamic-get-Missing-Keys.patch b/patches/server/0561-Optimize-Dynamic-get-Missing-Keys.patch similarity index 100% rename from patches/server/0560-Optimize-Dynamic-get-Missing-Keys.patch rename to patches/server/0561-Optimize-Dynamic-get-Missing-Keys.patch diff --git a/patches/server/0561-Expose-LivingEntity-hurt-direction.patch b/patches/server/0562-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from patches/server/0561-Expose-LivingEntity-hurt-direction.patch rename to patches/server/0562-Expose-LivingEntity-hurt-direction.patch diff --git a/patches/server/0562-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server/0563-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from patches/server/0562-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/server/0563-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/patches/server/0563-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server/0564-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch similarity index 100% rename from patches/server/0563-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch rename to patches/server/0564-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch diff --git a/patches/server/0564-added-PlayerTradeEvent.patch b/patches/server/0565-added-PlayerTradeEvent.patch similarity index 100% rename from patches/server/0564-added-PlayerTradeEvent.patch rename to patches/server/0565-added-PlayerTradeEvent.patch diff --git a/patches/server/0565-Implement-TargetHitEvent.patch b/patches/server/0566-Implement-TargetHitEvent.patch similarity index 100% rename from patches/server/0565-Implement-TargetHitEvent.patch rename to patches/server/0566-Implement-TargetHitEvent.patch diff --git a/patches/server/0566-Additional-Block-Material-API-s.patch b/patches/server/0567-Additional-Block-Material-API-s.patch similarity index 100% rename from patches/server/0566-Additional-Block-Material-API-s.patch rename to patches/server/0567-Additional-Block-Material-API-s.patch diff --git a/patches/server/0567-Fix-harming-potion-dupe.patch b/patches/server/0568-Fix-harming-potion-dupe.patch similarity index 100% rename from patches/server/0567-Fix-harming-potion-dupe.patch rename to patches/server/0568-Fix-harming-potion-dupe.patch diff --git a/patches/server/0568-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/patches/server/0569-Implement-API-to-get-Material-from-Boats-and-Minecar.patch similarity index 100% rename from patches/server/0568-Implement-API-to-get-Material-from-Boats-and-Minecar.patch rename to patches/server/0569-Implement-API-to-get-Material-from-Boats-and-Minecar.patch diff --git a/patches/server/0569-Cache-burn-durations.patch b/patches/server/0570-Cache-burn-durations.patch similarity index 100% rename from patches/server/0569-Cache-burn-durations.patch rename to patches/server/0570-Cache-burn-durations.patch diff --git a/patches/server/0570-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server/0571-Allow-disabling-mob-spawner-spawn-egg-transformation.patch similarity index 100% rename from patches/server/0570-Allow-disabling-mob-spawner-spawn-egg-transformation.patch rename to patches/server/0571-Allow-disabling-mob-spawner-spawn-egg-transformation.patch diff --git a/patches/server/0571-Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server/0572-Implement-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from patches/server/0571-Implement-PlayerFlowerPotManipulateEvent.patch rename to patches/server/0572-Implement-PlayerFlowerPotManipulateEvent.patch diff --git a/patches/server/0572-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server/0573-Fix-interact-event-not-being-called-in-adventure.patch similarity index 100% rename from patches/server/0572-Fix-interact-event-not-being-called-in-adventure.patch rename to patches/server/0573-Fix-interact-event-not-being-called-in-adventure.patch diff --git a/patches/server/0573-Zombie-API-breaking-doors.patch b/patches/server/0574-Zombie-API-breaking-doors.patch similarity index 100% rename from patches/server/0573-Zombie-API-breaking-doors.patch rename to patches/server/0574-Zombie-API-breaking-doors.patch diff --git a/patches/server/0574-Fix-nerfed-slime-when-splitting.patch b/patches/server/0575-Fix-nerfed-slime-when-splitting.patch similarity index 100% rename from patches/server/0574-Fix-nerfed-slime-when-splitting.patch rename to patches/server/0575-Fix-nerfed-slime-when-splitting.patch diff --git a/patches/server/0575-Add-EntityLoadCrossbowEvent.patch b/patches/server/0576-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from patches/server/0575-Add-EntityLoadCrossbowEvent.patch rename to patches/server/0576-Add-EntityLoadCrossbowEvent.patch diff --git a/patches/server/0576-Guardian-beam-workaround.patch b/patches/server/0577-Guardian-beam-workaround.patch similarity index 100% rename from patches/server/0576-Guardian-beam-workaround.patch rename to patches/server/0577-Guardian-beam-workaround.patch diff --git a/patches/server/0577-Added-WorldGameRuleChangeEvent.patch b/patches/server/0578-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from patches/server/0577-Added-WorldGameRuleChangeEvent.patch rename to patches/server/0578-Added-WorldGameRuleChangeEvent.patch diff --git a/patches/server/0578-Added-ServerResourcesReloadedEvent.patch b/patches/server/0579-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from patches/server/0578-Added-ServerResourcesReloadedEvent.patch rename to patches/server/0579-Added-ServerResourcesReloadedEvent.patch diff --git a/patches/server/0579-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server/0580-Added-world-settings-for-mobs-picking-up-loot.patch similarity index 100% rename from patches/server/0579-Added-world-settings-for-mobs-picking-up-loot.patch rename to patches/server/0580-Added-world-settings-for-mobs-picking-up-loot.patch diff --git a/patches/server/0580-Implemented-BlockFailedDispenseEvent.patch b/patches/server/0581-Implemented-BlockFailedDispenseEvent.patch similarity index 100% rename from patches/server/0580-Implemented-BlockFailedDispenseEvent.patch rename to patches/server/0581-Implemented-BlockFailedDispenseEvent.patch diff --git a/patches/server/0581-Added-PlayerLecternPageChangeEvent.patch b/patches/server/0582-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from patches/server/0581-Added-PlayerLecternPageChangeEvent.patch rename to patches/server/0582-Added-PlayerLecternPageChangeEvent.patch diff --git a/patches/server/0582-Added-PlayerLoomPatternSelectEvent.patch b/patches/server/0583-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from patches/server/0582-Added-PlayerLoomPatternSelectEvent.patch rename to patches/server/0583-Added-PlayerLoomPatternSelectEvent.patch diff --git a/patches/server/0583-Configurable-door-breaking-difficulty.patch b/patches/server/0584-Configurable-door-breaking-difficulty.patch similarity index 100% rename from patches/server/0583-Configurable-door-breaking-difficulty.patch rename to patches/server/0584-Configurable-door-breaking-difficulty.patch diff --git a/patches/server/0584-Empty-commands-shall-not-be-dispatched.patch b/patches/server/0585-Empty-commands-shall-not-be-dispatched.patch similarity index 100% rename from patches/server/0584-Empty-commands-shall-not-be-dispatched.patch rename to patches/server/0585-Empty-commands-shall-not-be-dispatched.patch diff --git a/patches/server/0585-Implement-API-to-expose-exact-interaction-point.patch b/patches/server/0586-Implement-API-to-expose-exact-interaction-point.patch similarity index 100% rename from patches/server/0585-Implement-API-to-expose-exact-interaction-point.patch rename to patches/server/0586-Implement-API-to-expose-exact-interaction-point.patch diff --git a/patches/server/0586-Remove-stale-POIs.patch b/patches/server/0587-Remove-stale-POIs.patch similarity index 100% rename from patches/server/0586-Remove-stale-POIs.patch rename to patches/server/0587-Remove-stale-POIs.patch diff --git a/patches/server/0587-Fix-villager-boat-exploit.patch b/patches/server/0588-Fix-villager-boat-exploit.patch similarity index 100% rename from patches/server/0587-Fix-villager-boat-exploit.patch rename to patches/server/0588-Fix-villager-boat-exploit.patch diff --git a/patches/server/0588-Add-sendOpLevel-API.patch b/patches/server/0589-Add-sendOpLevel-API.patch similarity index 100% rename from patches/server/0588-Add-sendOpLevel-API.patch rename to patches/server/0589-Add-sendOpLevel-API.patch diff --git a/patches/server/0589-Add-StructureLocateEvent.patch b/patches/server/0590-Add-StructureLocateEvent.patch similarity index 100% rename from patches/server/0589-Add-StructureLocateEvent.patch rename to patches/server/0590-Add-StructureLocateEvent.patch diff --git a/patches/server/0590-Collision-option-for-requiring-a-player-participant.patch b/patches/server/0591-Collision-option-for-requiring-a-player-participant.patch similarity index 100% rename from patches/server/0590-Collision-option-for-requiring-a-player-participant.patch rename to patches/server/0591-Collision-option-for-requiring-a-player-participant.patch diff --git a/patches/server/0591-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/patches/server/0592-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch similarity index 100% rename from patches/server/0591-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch rename to patches/server/0592-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch diff --git a/patches/server/0592-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/server/0593-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from patches/server/0592-Return-chat-component-with-empty-text-instead-of-thr.patch rename to patches/server/0593-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/patches/server/0593-Make-schedule-command-per-world.patch b/patches/server/0594-Make-schedule-command-per-world.patch similarity index 100% rename from patches/server/0593-Make-schedule-command-per-world.patch rename to patches/server/0594-Make-schedule-command-per-world.patch diff --git a/patches/server/0594-Configurable-max-leash-distance.patch b/patches/server/0595-Configurable-max-leash-distance.patch similarity index 100% rename from patches/server/0594-Configurable-max-leash-distance.patch rename to patches/server/0595-Configurable-max-leash-distance.patch diff --git a/patches/server/0595-Implement-BlockPreDispenseEvent.patch b/patches/server/0596-Implement-BlockPreDispenseEvent.patch similarity index 100% rename from patches/server/0595-Implement-BlockPreDispenseEvent.patch rename to patches/server/0596-Implement-BlockPreDispenseEvent.patch diff --git a/patches/server/0596-Added-Vanilla-Entity-Tags.patch b/patches/server/0597-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from patches/server/0596-Added-Vanilla-Entity-Tags.patch rename to patches/server/0597-Added-Vanilla-Entity-Tags.patch diff --git a/patches/server/0597-added-Wither-API.patch b/patches/server/0598-added-Wither-API.patch similarity index 100% rename from patches/server/0597-added-Wither-API.patch rename to patches/server/0598-added-Wither-API.patch diff --git a/patches/server/0598-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/patches/server/0599-Added-firing-of-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from patches/server/0598-Added-firing-of-PlayerChangeBeaconEffectEvent.patch rename to patches/server/0599-Added-firing-of-PlayerChangeBeaconEffectEvent.patch diff --git a/patches/server/0599-Fix-console-spam-when-removing-chests-in-water.patch b/patches/server/0600-Fix-console-spam-when-removing-chests-in-water.patch similarity index 100% rename from patches/server/0599-Fix-console-spam-when-removing-chests-in-water.patch rename to patches/server/0600-Fix-console-spam-when-removing-chests-in-water.patch diff --git a/patches/server/0600-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server/0601-Add-toggle-for-always-placing-the-dragon-egg.patch similarity index 100% rename from patches/server/0600-Add-toggle-for-always-placing-the-dragon-egg.patch rename to patches/server/0601-Add-toggle-for-always-placing-the-dragon-egg.patch diff --git a/patches/server/0601-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server/0602-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from patches/server/0601-Added-PlayerStonecutterRecipeSelectEvent.patch rename to patches/server/0602-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/patches/server/0602-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/server/0603-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from patches/server/0602-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/server/0603-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/patches/server/0603-Skip-distance-map-update-when-spawning-disabled.patch b/patches/server/0604-Skip-distance-map-update-when-spawning-disabled.patch similarity index 100% rename from patches/server/0603-Skip-distance-map-update-when-spawning-disabled.patch rename to patches/server/0604-Skip-distance-map-update-when-spawning-disabled.patch diff --git a/patches/server/0604-Reset-shield-blocking-on-dimension-change.patch b/patches/server/0605-Reset-shield-blocking-on-dimension-change.patch similarity index 100% rename from patches/server/0604-Reset-shield-blocking-on-dimension-change.patch rename to patches/server/0605-Reset-shield-blocking-on-dimension-change.patch diff --git a/patches/server/0605-add-DragonEggFormEvent.patch b/patches/server/0606-add-DragonEggFormEvent.patch similarity index 100% rename from patches/server/0605-add-DragonEggFormEvent.patch rename to patches/server/0606-add-DragonEggFormEvent.patch diff --git a/patches/server/0606-EntityMoveEvent.patch b/patches/server/0607-EntityMoveEvent.patch similarity index 100% rename from patches/server/0606-EntityMoveEvent.patch rename to patches/server/0607-EntityMoveEvent.patch diff --git a/patches/server/0607-added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server/0608-added-option-to-disable-pathfinding-updates-on-block.patch similarity index 100% rename from patches/server/0607-added-option-to-disable-pathfinding-updates-on-block.patch rename to patches/server/0608-added-option-to-disable-pathfinding-updates-on-block.patch diff --git a/patches/server/0608-Inline-shift-direction-fields.patch b/patches/server/0609-Inline-shift-direction-fields.patch similarity index 100% rename from patches/server/0608-Inline-shift-direction-fields.patch rename to patches/server/0609-Inline-shift-direction-fields.patch diff --git a/patches/server/0609-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server/0610-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from patches/server/0609-Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/server/0610-Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/patches/server/0610-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/server/0611-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from patches/server/0610-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/server/0611-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/patches/server/0611-living-entity-allow-attribute-registration.patch b/patches/server/0612-living-entity-allow-attribute-registration.patch similarity index 100% rename from patches/server/0611-living-entity-allow-attribute-registration.patch rename to patches/server/0612-living-entity-allow-attribute-registration.patch diff --git a/patches/server/0612-fix-dead-slime-setSize-invincibility.patch b/patches/server/0613-fix-dead-slime-setSize-invincibility.patch similarity index 100% rename from patches/server/0612-fix-dead-slime-setSize-invincibility.patch rename to patches/server/0613-fix-dead-slime-setSize-invincibility.patch diff --git a/patches/server/0613-Merchant-getRecipes-should-return-an-immutable-list.patch b/patches/server/0614-Merchant-getRecipes-should-return-an-immutable-list.patch similarity index 100% rename from patches/server/0613-Merchant-getRecipes-should-return-an-immutable-list.patch rename to patches/server/0614-Merchant-getRecipes-should-return-an-immutable-list.patch diff --git a/patches/server/0614-misc-debugging-dumps.patch b/patches/server/0615-misc-debugging-dumps.patch similarity index 100% rename from patches/server/0614-misc-debugging-dumps.patch rename to patches/server/0615-misc-debugging-dumps.patch diff --git a/patches/server/0615-Add-support-for-hex-color-codes-in-console.patch b/patches/server/0616-Add-support-for-hex-color-codes-in-console.patch similarity index 100% rename from patches/server/0615-Add-support-for-hex-color-codes-in-console.patch rename to patches/server/0616-Add-support-for-hex-color-codes-in-console.patch diff --git a/patches/server/0616-Expose-Tracked-Players.patch b/patches/server/0617-Expose-Tracked-Players.patch similarity index 100% rename from patches/server/0616-Expose-Tracked-Players.patch rename to patches/server/0617-Expose-Tracked-Players.patch diff --git a/patches/server/0617-Remove-streams-from-SensorNearest.patch b/patches/server/0618-Remove-streams-from-SensorNearest.patch similarity index 100% rename from patches/server/0617-Remove-streams-from-SensorNearest.patch rename to patches/server/0618-Remove-streams-from-SensorNearest.patch diff --git a/patches/server/0618-MC-29274-Fix-Wither-hostility-towards-players.patch b/patches/server/0619-MC-29274-Fix-Wither-hostility-towards-players.patch similarity index 100% rename from patches/server/0618-MC-29274-Fix-Wither-hostility-towards-players.patch rename to patches/server/0619-MC-29274-Fix-Wither-hostility-towards-players.patch diff --git a/patches/server/0619-Throw-proper-exception-on-empty-JsonList-file.patch b/patches/server/0620-Throw-proper-exception-on-empty-JsonList-file.patch similarity index 100% rename from patches/server/0619-Throw-proper-exception-on-empty-JsonList-file.patch rename to patches/server/0620-Throw-proper-exception-on-empty-JsonList-file.patch diff --git a/patches/server/0620-Improve-ServerGUI.patch b/patches/server/0621-Improve-ServerGUI.patch similarity index 100% rename from patches/server/0620-Improve-ServerGUI.patch rename to patches/server/0621-Improve-ServerGUI.patch diff --git a/patches/server/0621-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/patches/server/0622-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch similarity index 100% rename from patches/server/0621-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch rename to patches/server/0622-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch diff --git a/patches/server/0622-fix-converting-txt-to-json-file.patch b/patches/server/0623-fix-converting-txt-to-json-file.patch similarity index 100% rename from patches/server/0622-fix-converting-txt-to-json-file.patch rename to patches/server/0623-fix-converting-txt-to-json-file.patch diff --git a/patches/server/0623-Add-worldborder-events.patch b/patches/server/0624-Add-worldborder-events.patch similarity index 100% rename from patches/server/0623-Add-worldborder-events.patch rename to patches/server/0624-Add-worldborder-events.patch diff --git a/patches/server/0624-added-PlayerNameEntityEvent.patch b/patches/server/0625-added-PlayerNameEntityEvent.patch similarity index 100% rename from patches/server/0624-added-PlayerNameEntityEvent.patch rename to patches/server/0625-added-PlayerNameEntityEvent.patch diff --git a/patches/server/0625-Prevent-grindstones-from-overstacking-items.patch b/patches/server/0626-Prevent-grindstones-from-overstacking-items.patch similarity index 100% rename from patches/server/0625-Prevent-grindstones-from-overstacking-items.patch rename to patches/server/0626-Prevent-grindstones-from-overstacking-items.patch diff --git a/patches/server/0626-Add-recipe-to-cook-events.patch b/patches/server/0627-Add-recipe-to-cook-events.patch similarity index 100% rename from patches/server/0626-Add-recipe-to-cook-events.patch rename to patches/server/0627-Add-recipe-to-cook-events.patch diff --git a/patches/server/0627-Add-Block-isValidTool.patch b/patches/server/0628-Add-Block-isValidTool.patch similarity index 100% rename from patches/server/0627-Add-Block-isValidTool.patch rename to patches/server/0628-Add-Block-isValidTool.patch diff --git a/patches/server/0628-Allow-using-signs-inside-spawn-protection.patch b/patches/server/0629-Allow-using-signs-inside-spawn-protection.patch similarity index 100% rename from patches/server/0628-Allow-using-signs-inside-spawn-protection.patch rename to patches/server/0629-Allow-using-signs-inside-spawn-protection.patch diff --git a/patches/server/0629-Implement-Keyed-on-World.patch b/patches/server/0630-Implement-Keyed-on-World.patch similarity index 100% rename from patches/server/0629-Implement-Keyed-on-World.patch rename to patches/server/0630-Implement-Keyed-on-World.patch diff --git a/patches/server/0630-Add-fast-alternative-constructor-for-Rotations.patch b/patches/server/0631-Add-fast-alternative-constructor-for-Rotations.patch similarity index 100% rename from patches/server/0630-Add-fast-alternative-constructor-for-Rotations.patch rename to patches/server/0631-Add-fast-alternative-constructor-for-Rotations.patch diff --git a/patches/server/0631-Item-Rarity-API.patch b/patches/server/0632-Item-Rarity-API.patch similarity index 100% rename from patches/server/0631-Item-Rarity-API.patch rename to patches/server/0632-Item-Rarity-API.patch diff --git a/patches/server/0632-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/patches/server/0633-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch similarity index 100% rename from patches/server/0632-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch rename to patches/server/0633-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch diff --git a/patches/server/0633-copy-TESign-isEditable-from-snapshots.patch b/patches/server/0634-copy-TESign-isEditable-from-snapshots.patch similarity index 100% rename from patches/server/0633-copy-TESign-isEditable-from-snapshots.patch rename to patches/server/0634-copy-TESign-isEditable-from-snapshots.patch diff --git a/patches/server/0634-Drop-carried-item-when-player-has-disconnected.patch b/patches/server/0635-Drop-carried-item-when-player-has-disconnected.patch similarity index 100% rename from patches/server/0634-Drop-carried-item-when-player-has-disconnected.patch rename to patches/server/0635-Drop-carried-item-when-player-has-disconnected.patch diff --git a/patches/server/0635-forced-whitelist-use-configurable-kick-message.patch b/patches/server/0636-forced-whitelist-use-configurable-kick-message.patch similarity index 100% rename from patches/server/0635-forced-whitelist-use-configurable-kick-message.patch rename to patches/server/0636-forced-whitelist-use-configurable-kick-message.patch diff --git a/patches/server/0636-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/patches/server/0637-Don-t-ignore-result-of-PlayerEditBookEvent.patch similarity index 100% rename from patches/server/0636-Don-t-ignore-result-of-PlayerEditBookEvent.patch rename to patches/server/0637-Don-t-ignore-result-of-PlayerEditBookEvent.patch diff --git a/patches/server/0637-fix-cancelling-block-falling-causing-client-desync.patch b/patches/server/0638-fix-cancelling-block-falling-causing-client-desync.patch similarity index 100% rename from patches/server/0637-fix-cancelling-block-falling-causing-client-desync.patch rename to patches/server/0638-fix-cancelling-block-falling-causing-client-desync.patch diff --git a/patches/server/0638-Expose-protocol-version.patch b/patches/server/0639-Expose-protocol-version.patch similarity index 100% rename from patches/server/0638-Expose-protocol-version.patch rename to patches/server/0639-Expose-protocol-version.patch diff --git a/patches/server/0639-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/server/0640-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 100% rename from patches/server/0639-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to patches/server/0640-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch diff --git a/patches/server/0640-Enhance-console-tab-completions-for-brigadier-comman.patch b/patches/server/0641-Enhance-console-tab-completions-for-brigadier-comman.patch similarity index 100% rename from patches/server/0640-Enhance-console-tab-completions-for-brigadier-comman.patch rename to patches/server/0641-Enhance-console-tab-completions-for-brigadier-comman.patch diff --git a/patches/server/0641-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/patches/server/0642-Fix-PlayerItemConsumeEvent-cancelling-properly.patch similarity index 100% rename from patches/server/0641-Fix-PlayerItemConsumeEvent-cancelling-properly.patch rename to patches/server/0642-Fix-PlayerItemConsumeEvent-cancelling-properly.patch diff --git a/patches/server/0642-Add-bypass-host-check.patch b/patches/server/0643-Add-bypass-host-check.patch similarity index 100% rename from patches/server/0642-Add-bypass-host-check.patch rename to patches/server/0643-Add-bypass-host-check.patch diff --git a/patches/server/0643-Set-area-affect-cloud-rotation.patch b/patches/server/0644-Set-area-affect-cloud-rotation.patch similarity index 100% rename from patches/server/0643-Set-area-affect-cloud-rotation.patch rename to patches/server/0644-Set-area-affect-cloud-rotation.patch diff --git a/patches/server/0644-add-isDeeplySleeping-to-HumanEntity.patch b/patches/server/0645-add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from patches/server/0644-add-isDeeplySleeping-to-HumanEntity.patch rename to patches/server/0645-add-isDeeplySleeping-to-HumanEntity.patch diff --git a/patches/server/0645-Fix-duplicating-give-items-on-item-drop-cancel.patch b/patches/server/0646-Fix-duplicating-give-items-on-item-drop-cancel.patch similarity index 100% rename from patches/server/0645-Fix-duplicating-give-items-on-item-drop-cancel.patch rename to patches/server/0646-Fix-duplicating-give-items-on-item-drop-cancel.patch diff --git a/patches/server/0646-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/server/0647-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from patches/server/0646-add-consumeFuel-to-FurnaceBurnEvent.patch rename to patches/server/0647-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/patches/server/0647-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/server/0648-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from patches/server/0647-add-get-set-drop-chance-to-EntityEquipment.patch rename to patches/server/0648-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/patches/server/0648-fix-PigZombieAngerEvent-cancellation.patch b/patches/server/0649-fix-PigZombieAngerEvent-cancellation.patch similarity index 100% rename from patches/server/0648-fix-PigZombieAngerEvent-cancellation.patch rename to patches/server/0649-fix-PigZombieAngerEvent-cancellation.patch diff --git a/patches/server/0649-Fix-checkReach-check-for-Shulker-boxes.patch b/patches/server/0650-Fix-checkReach-check-for-Shulker-boxes.patch similarity index 100% rename from patches/server/0649-Fix-checkReach-check-for-Shulker-boxes.patch rename to patches/server/0650-Fix-checkReach-check-for-Shulker-boxes.patch diff --git a/patches/server/0650-fix-PlayerItemHeldEvent-firing-twice.patch b/patches/server/0651-fix-PlayerItemHeldEvent-firing-twice.patch similarity index 100% rename from patches/server/0650-fix-PlayerItemHeldEvent-firing-twice.patch rename to patches/server/0651-fix-PlayerItemHeldEvent-firing-twice.patch diff --git a/patches/server/0651-Added-PlayerDeepSleepEvent.patch b/patches/server/0652-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from patches/server/0651-Added-PlayerDeepSleepEvent.patch rename to patches/server/0652-Added-PlayerDeepSleepEvent.patch diff --git a/patches/server/0652-More-World-API.patch b/patches/server/0653-More-World-API.patch similarity index 100% rename from patches/server/0652-More-World-API.patch rename to patches/server/0653-More-World-API.patch diff --git a/patches/server/0653-Added-PlayerBedFailEnterEvent.patch b/patches/server/0654-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from patches/server/0653-Added-PlayerBedFailEnterEvent.patch rename to patches/server/0654-Added-PlayerBedFailEnterEvent.patch diff --git a/patches/server/0654-Implement-methods-to-convert-between-Component-and-B.patch b/patches/server/0655-Implement-methods-to-convert-between-Component-and-B.patch similarity index 100% rename from patches/server/0654-Implement-methods-to-convert-between-Component-and-B.patch rename to patches/server/0655-Implement-methods-to-convert-between-Component-and-B.patch diff --git a/patches/server/0655-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/patches/server/0656-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch similarity index 100% rename from patches/server/0655-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch rename to patches/server/0656-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch diff --git a/patches/server/0656-Introduce-beacon-activation-deactivation-events.patch b/patches/server/0657-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from patches/server/0656-Introduce-beacon-activation-deactivation-events.patch rename to patches/server/0657-Introduce-beacon-activation-deactivation-events.patch diff --git a/patches/server/0657-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/server/0658-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from patches/server/0657-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/server/0658-add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/patches/server/0658-Add-Channel-initialization-listeners.patch b/patches/server/0659-Add-Channel-initialization-listeners.patch similarity index 100% rename from patches/server/0658-Add-Channel-initialization-listeners.patch rename to patches/server/0659-Add-Channel-initialization-listeners.patch diff --git a/patches/server/0659-Send-empty-commands-if-tab-completion-is-disabled.patch b/patches/server/0660-Send-empty-commands-if-tab-completion-is-disabled.patch similarity index 100% rename from patches/server/0659-Send-empty-commands-if-tab-completion-is-disabled.patch rename to patches/server/0660-Send-empty-commands-if-tab-completion-is-disabled.patch diff --git a/patches/server/0660-Add-more-WanderingTrader-API.patch b/patches/server/0661-Add-more-WanderingTrader-API.patch similarity index 100% rename from patches/server/0660-Add-more-WanderingTrader-API.patch rename to patches/server/0661-Add-more-WanderingTrader-API.patch diff --git a/patches/server/0661-Add-EntityBlockStorage-clearEntities.patch b/patches/server/0662-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from patches/server/0661-Add-EntityBlockStorage-clearEntities.patch rename to patches/server/0662-Add-EntityBlockStorage-clearEntities.patch diff --git a/patches/server/0662-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/server/0663-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from patches/server/0662-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to patches/server/0663-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/patches/server/0663-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/server/0664-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from patches/server/0663-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/server/0664-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/patches/server/0664-Inventory-close.patch b/patches/server/0665-Inventory-close.patch similarity index 100% rename from patches/server/0664-Inventory-close.patch rename to patches/server/0665-Inventory-close.patch diff --git a/patches/server/0665-call-PortalCreateEvent-players-and-end-platform.patch b/patches/server/0666-call-PortalCreateEvent-players-and-end-platform.patch similarity index 100% rename from patches/server/0665-call-PortalCreateEvent-players-and-end-platform.patch rename to patches/server/0666-call-PortalCreateEvent-players-and-end-platform.patch diff --git a/patches/server/0666-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/server/0667-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 100% rename from patches/server/0666-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/server/0667-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch diff --git a/patches/server/0667-Fix-CraftPotionBrewer-cache.patch b/patches/server/0668-Fix-CraftPotionBrewer-cache.patch similarity index 100% rename from patches/server/0667-Fix-CraftPotionBrewer-cache.patch rename to patches/server/0668-Fix-CraftPotionBrewer-cache.patch diff --git a/patches/server/0668-Add-basic-Datapack-API.patch b/patches/server/0669-Add-basic-Datapack-API.patch similarity index 100% rename from patches/server/0668-Add-basic-Datapack-API.patch rename to patches/server/0669-Add-basic-Datapack-API.patch diff --git a/patches/server/0669-Add-environment-variable-to-disable-server-gui.patch b/patches/server/0670-Add-environment-variable-to-disable-server-gui.patch similarity index 100% rename from patches/server/0669-Add-environment-variable-to-disable-server-gui.patch rename to patches/server/0670-Add-environment-variable-to-disable-server-gui.patch diff --git a/patches/server/0670-additions-to-PlayerGameModeChangeEvent.patch b/patches/server/0671-additions-to-PlayerGameModeChangeEvent.patch similarity index 100% rename from patches/server/0670-additions-to-PlayerGameModeChangeEvent.patch rename to patches/server/0671-additions-to-PlayerGameModeChangeEvent.patch diff --git a/patches/server/0671-ItemStack-repair-check-API.patch b/patches/server/0672-ItemStack-repair-check-API.patch similarity index 100% rename from patches/server/0671-ItemStack-repair-check-API.patch rename to patches/server/0672-ItemStack-repair-check-API.patch diff --git a/patches/server/0672-More-Enchantment-API.patch b/patches/server/0673-More-Enchantment-API.patch similarity index 100% rename from patches/server/0672-More-Enchantment-API.patch rename to patches/server/0673-More-Enchantment-API.patch diff --git a/patches/server/0673-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/server/0674-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 100% rename from patches/server/0673-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to patches/server/0674-Add-command-line-option-to-load-extra-plugin-jars-no.patch diff --git a/patches/server/0674-Fix-and-optimise-world-force-upgrading.patch b/patches/server/0675-Fix-and-optimise-world-force-upgrading.patch similarity index 100% rename from patches/server/0674-Fix-and-optimise-world-force-upgrading.patch rename to patches/server/0675-Fix-and-optimise-world-force-upgrading.patch diff --git a/patches/server/0675-Add-Mob-lookAt-API.patch b/patches/server/0676-Add-Mob-lookAt-API.patch similarity index 100% rename from patches/server/0675-Add-Mob-lookAt-API.patch rename to patches/server/0676-Add-Mob-lookAt-API.patch diff --git a/patches/server/0676-Add-Unix-domain-socket-support.patch b/patches/server/0677-Add-Unix-domain-socket-support.patch similarity index 100% rename from patches/server/0676-Add-Unix-domain-socket-support.patch rename to patches/server/0677-Add-Unix-domain-socket-support.patch diff --git a/patches/server/0677-Add-EntityInsideBlockEvent.patch b/patches/server/0678-Add-EntityInsideBlockEvent.patch similarity index 100% rename from patches/server/0677-Add-EntityInsideBlockEvent.patch rename to patches/server/0678-Add-EntityInsideBlockEvent.patch diff --git a/patches/server/0678-Attributes-API-for-item-defaults.patch b/patches/server/0679-Attributes-API-for-item-defaults.patch similarity index 100% rename from patches/server/0678-Attributes-API-for-item-defaults.patch rename to patches/server/0679-Attributes-API-for-item-defaults.patch diff --git a/patches/server/0679-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/patches/server/0680-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch similarity index 100% rename from patches/server/0679-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch rename to patches/server/0680-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch diff --git a/patches/server/0680-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/server/0681-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from patches/server/0680-Add-cause-to-Weather-ThunderChangeEvents.patch rename to patches/server/0681-Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/patches/server/0681-More-Lidded-Block-API.patch b/patches/server/0682-More-Lidded-Block-API.patch similarity index 100% rename from patches/server/0681-More-Lidded-Block-API.patch rename to patches/server/0682-More-Lidded-Block-API.patch diff --git a/patches/server/0682-Limit-item-frame-cursors-on-maps.patch b/patches/server/0683-Limit-item-frame-cursors-on-maps.patch similarity index 100% rename from patches/server/0682-Limit-item-frame-cursors-on-maps.patch rename to patches/server/0683-Limit-item-frame-cursors-on-maps.patch diff --git a/patches/server/0683-Add-PufferFishStateChangeEvent.patch b/patches/server/0684-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from patches/server/0683-Add-PufferFishStateChangeEvent.patch rename to patches/server/0684-Add-PufferFishStateChangeEvent.patch diff --git a/patches/server/0684-Add-PlayerKickEvent-causes.patch b/patches/server/0685-Add-PlayerKickEvent-causes.patch similarity index 100% rename from patches/server/0684-Add-PlayerKickEvent-causes.patch rename to patches/server/0685-Add-PlayerKickEvent-causes.patch diff --git a/patches/server/0685-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/patches/server/0686-Fix-PlayerBucketEmptyEvent-result-itemstack.patch similarity index 100% rename from patches/server/0685-Fix-PlayerBucketEmptyEvent-result-itemstack.patch rename to patches/server/0686-Fix-PlayerBucketEmptyEvent-result-itemstack.patch diff --git a/patches/server/0686-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch b/patches/server/0687-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch similarity index 100% rename from patches/server/0686-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch rename to patches/server/0687-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch diff --git a/patches/server/0687-Add-option-to-fix-items-merging-through-walls.patch b/patches/server/0688-Add-option-to-fix-items-merging-through-walls.patch similarity index 100% rename from patches/server/0687-Add-option-to-fix-items-merging-through-walls.patch rename to patches/server/0688-Add-option-to-fix-items-merging-through-walls.patch diff --git a/patches/server/0688-Add-BellRevealRaiderEvent.patch b/patches/server/0689-Add-BellRevealRaiderEvent.patch similarity index 100% rename from patches/server/0688-Add-BellRevealRaiderEvent.patch rename to patches/server/0689-Add-BellRevealRaiderEvent.patch diff --git a/patches/server/0689-Fix-invulnerable-end-crystals.patch b/patches/server/0690-Fix-invulnerable-end-crystals.patch similarity index 100% rename from patches/server/0689-Fix-invulnerable-end-crystals.patch rename to patches/server/0690-Fix-invulnerable-end-crystals.patch diff --git a/patches/server/0690-Add-ElderGuardianAppearanceEvent.patch b/patches/server/0691-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from patches/server/0690-Add-ElderGuardianAppearanceEvent.patch rename to patches/server/0691-Add-ElderGuardianAppearanceEvent.patch diff --git a/patches/server/0691-Reset-villager-inventory-on-cancelled-pickup-event.patch b/patches/server/0692-Reset-villager-inventory-on-cancelled-pickup-event.patch similarity index 100% rename from patches/server/0691-Reset-villager-inventory-on-cancelled-pickup-event.patch rename to patches/server/0692-Reset-villager-inventory-on-cancelled-pickup-event.patch diff --git a/patches/server/0692-Fix-dangerous-end-portal-logic.patch b/patches/server/0693-Fix-dangerous-end-portal-logic.patch similarity index 100% rename from patches/server/0692-Fix-dangerous-end-portal-logic.patch rename to patches/server/0693-Fix-dangerous-end-portal-logic.patch diff --git a/patches/server/0693-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/server/0694-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch similarity index 100% rename from patches/server/0693-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch rename to patches/server/0694-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch diff --git a/patches/server/0694-Make-item-validations-configurable.patch b/patches/server/0695-Make-item-validations-configurable.patch similarity index 100% rename from patches/server/0694-Make-item-validations-configurable.patch rename to patches/server/0695-Make-item-validations-configurable.patch diff --git a/patches/server/0695-Add-more-line-of-sight-methods.patch b/patches/server/0696-Add-more-line-of-sight-methods.patch similarity index 100% rename from patches/server/0695-Add-more-line-of-sight-methods.patch rename to patches/server/0696-Add-more-line-of-sight-methods.patch diff --git a/patches/server/0696-add-per-world-spawn-limits.patch b/patches/server/0697-add-per-world-spawn-limits.patch similarity index 100% rename from patches/server/0696-add-per-world-spawn-limits.patch rename to patches/server/0697-add-per-world-spawn-limits.patch diff --git a/patches/server/0697-Fix-PotionSplashEvent-for-water-splash-potions.patch b/patches/server/0698-Fix-PotionSplashEvent-for-water-splash-potions.patch similarity index 100% rename from patches/server/0697-Fix-PotionSplashEvent-for-water-splash-potions.patch rename to patches/server/0698-Fix-PotionSplashEvent-for-water-splash-potions.patch diff --git a/patches/server/0698-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/patches/server/0699-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch similarity index 100% rename from patches/server/0698-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch rename to patches/server/0699-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch From a0056c36f17d8beaedd7ebeb9d8185bf202ab965 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Tue, 15 Jun 2021 01:12:10 -0700 Subject: [PATCH 151/226] Revert "Updated Upstream (CraftBukkit)" This reverts commit c9f654db919574ef221a75373d0a5643d5051e40. --- work/CraftBukkit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/work/CraftBukkit b/work/CraftBukkit index f992ce6097..622cf61119 160000 --- a/work/CraftBukkit +++ b/work/CraftBukkit @@ -1 +1 @@ -Subproject commit f992ce6097f846ed5967fc797d98ae3e84ef1b10 +Subproject commit 622cf6111905e787add191b9a88d62656439ef31 From 3846367c2de23db6bae256c930b4fba6256e9d87 Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Tue, 15 Jun 2021 01:29:12 -0700 Subject: [PATCH 152/226] add back optimizing hopper searches (#5839) --- ...opper-searches-if-there-are-no-items.patch | 127 ---------------- ...opper-searches-if-there-are-no-items.patch | 142 ++++++++++++++++++ ...et-gravity-in-void.-Fixes-MC-167279.patch} | 0 ...-getChunkAt-calls-for-loaded-chunks.patch} | 0 ...w-overriding-the-java-version-check.patch} | 0 ...tch => 0373-Add-ThrownEggHatchEvent.patch} | 0 ... 0374-Optimise-random-block-ticking.patch} | 2 +- ...p-API.patch => 0375-Entity-Jump-API.patch} | 0 ...-to-nerf-pigmen-from-nether-portals.patch} | 0 ... => 0377-Make-the-GUI-graph-fancier.patch} | 0 ...78-add-hand-to-BlockMultiPlaceEvent.patch} | 0 ...9-Prevent-teleporting-dead-entities.patch} | 0 ...ipwire-hook-placement-before-update.patch} | 0 ...o-allow-iron-golems-to-spawn-in-air.patch} | 0 ...chance-of-villager-zombie-infection.patch} | 0 ...tch => 0383-Optimise-Chunk-getFluid.patch} | 0 ...mise-TickListServer-by-rewriting-it.patch} | 0 ...pawn-settings-and-per-player-option.patch} | 0 ...nections-shouldn-t-hold-up-shutdown.patch} | 0 ...ow-bees-to-load-chunks-for-beehives.patch} | 0 ...PlayerChunkMap-adds-crashing-server.patch} | 0 ...timize-Collision-to-not-load-chunks.patch} | 0 ...tch => 0390-Don-t-tick-dead-players.patch} | 0 ...-Player-s-shouldn-t-be-able-to-move.patch} | 0 ...unkMap-memory-use-for-visibleChunks.patch} | 0 ...sks-Speed-up-processing-of-chunk-lo.patch} | 0 ...ove-existing-players-to-world-spawn.patch} | 0 ...Add-tick-times-API-and-mspt-command.patch} | 0 ...96-Expose-MinecraftServer-isRunning.patch} | 0 ...dd-Raw-Byte-ItemStack-Serialization.patch} | 0 ...8-Remove-streams-from-Mob-AI-System.patch} | 0 ... => 0399-Async-command-map-building.patch} | 0 ...h => 0400-Improved-Watchdog-Support.patch} | 2 +- ....patch => 0401-Optimize-Pathfinding.patch} | 0 ...2-Reduce-Either-Optional-allocation.patch} | 0 ...403-Remove-streams-from-PairedQueue.patch} | 0 ...-memory-footprint-of-NBTTagCompound.patch} | 0 ...ent-opening-inventories-when-frozen.patch} | 0 ...06-Optimise-ArraySetSorted-removeIf.patch} | 0 ...entity-collision-code-if-not-needed.patch} | 0 ...teleport-command-to-valid-locations.patch} | 0 ...Implement-Player-Client-Options-API.patch} | 0 ...Chunk-Post-Processing-deadlock-risk.patch} | 0 ...ayer-is-attempted-to-be-removed-fro.patch} | 0 ...2-Broadcast-join-message-to-console.patch} | 0 ...-Broken-behavior-of-PlayerJoinEvent.patch} | 0 ...oad-Chunks-for-Login-Asynchronously.patch} | 0 ...awn-point-if-spawn-in-unloaded-worl.patch} | 0 ...layerAttackEntityCooldownResetEvent.patch} | 0 ...llbacks-to-schedule-for-Callback-Ex.patch} | 0 ...-fire-BlockFade-on-worldgen-threads.patch} | 0 ...tom-creative-and-insomniac-controls.patch} | 0 ...-duplication-issues-and-teleport-is.patch} | 0 ...0421-Implement-Brigadier-Mojang-API.patch} | 0 ...patch => 0422-Villager-Restocks-API.patch} | 0 ...ickItem-Packet-and-kick-for-invalid.patch} | 0 ...n.patch => 0424-Expose-game-version.patch} | 0 ...> 0425-Optimize-Voxel-Shape-Merging.patch} | 0 ...per-thread-native-byte-buffer-cache.patch} | 0 ...atch => 0427-Implement-Mob-Goal-API.patch} | 0 ...ance-map-to-optimise-entity-tracker.patch} | 0 ...isOutsideRange-to-use-distance-maps.patch} | 0 ...=> 0430-Add-villager-reputation-API.patch} | 0 ...maximum-exp-value-when-merging-orbs.patch} | 0 ...tch => 0432-ExperienceOrbMergeEvent.patch} | 0 ...-Fix-PotionEffect-ignores-icon-flag.patch} | 0 ...brigadier-child-sorting-performance.patch} | 0 ...API.patch => 0435-Potential-bed-API.patch} | 0 ...ait-for-Async-Tasks-during-shutdown.patch} | 0 ...er-respects-game-and-entity-rules-f.patch} | 0 ...nd-End-Portal-Frames-from-being-des.patch} | 2 +- ...leInt-allocations-from-light-engine.patch} | 0 ...location-of-Vec3D-by-entity-tracker.patch} | 0 ...> 0441-Ensure-safe-gateway-teleport.patch} | 0 ...-for-console-having-all-permissions.patch} | 0 ...n-Full-Status-Chunk-NBT-Memory-Leak.patch} | 0 ...packets-to-nearby-locations-sounds-.patch} | 0 ...x-villager-trading-demand-MC-163962.patch} | 0 ... => 0446-Maps-shouldn-t-load-chunks.patch} | 0 ...okup-for-Treasure-Maps-Fixes-lag-fr.patch} | 0 ...nk-Unloads-based-on-Player-Movement.patch} | 0 ...Optimize-Bit-Operations-by-inlining.patch} | 0 ...ch => 0450-incremental-chunk-saving.patch} | 0 ...Plugin-Tickets-to-API-Chunk-Methods.patch} | 0 ...sing-chunks-due-to-integer-overflow.patch} | 0 ...r-runTaskTimerAsynchronously-Plugin.patch} | 0 ...ton-physics-inconsistency-MC-188840.patch} | 0 ...uping.patch => 0455-Fix-sand-duping.patch} | 0 ...desync-in-playerconnection-causing-.patch} | 0 ...older-method-without-block-snapshot.patch} | 0 ...h => 0458-Expose-Arrow-getItemStack.patch} | 0 ...mplement-PlayerRecipeBookClickEvent.patch} | 0 ...-Hide-sync-chunk-writes-behind-flag.patch} | 0 ...1-Add-permission-for-command-blocks.patch} | 0 ...ure-Entity-AABB-s-are-never-invalid.patch} | 0 ...orldBorder-collision-checks-and-air.patch} | 0 ...d-Difficulty-Remembering-Difficulty.patch} | 0 ...atch => 0465-Paper-dumpitem-command.patch} | 0 ...66-Don-t-allow-null-UUID-s-for-chat.patch} | 0 ...Legacy-Component-serialization-size.patch} | 0 ...468-Support-old-UUID-format-for-NBT.patch} | 0 ...p-duplicated-GameProfile-Properties.patch} | 0 ...vert-legacy-attributes-in-Item-Meta.patch} | 0 ...-Priority-Urgency-System-for-Chunks.patch} | 0 ...Remove-some-streams-from-structures.patch} | 0 ...rom-classes-related-villager-gossip.patch} | 0 ...0474-Support-components-in-ItemMeta.patch} | 0 ...rgetLivingEntityEvent-for-1.16-mobs.patch} | 0 ...patch => 0476-Add-entity-liquid-API.patch} | 0 ...date-itemstack-legacy-name-and-lore.patch} | 0 ...wn-player-in-correct-world-on-login.patch} | 0 ...atch => 0479-Add-PrepareResultEvent.patch} | 0 ...low-delegation-to-vanilla-chunk-gen.patch} | 0 ...-for-portal-on-world-gen-entity-add.patch} | 0 ...e-NetworkManager-Exception-Handling.patch} | 0 ...ncement-data-player-iteration-to-be.patch} | 0 ...x-arrows-never-despawning-MC-125757.patch} | 0 ...Vanilla-Command-permission-checking.patch} | 0 ...ve-range-check-for-block-placing-up.patch} | 0 ...-5989.patch => 0487-Fix-SPIGOT-5989.patch} | 0 ...-Bukkit-world-container-is-not-used.patch} | 0 ...5885-Unable-to-disable-advancements.patch} | 0 ...taPlayer-leak-due-from-quitting-ear.patch} | 0 ...eLighting-call-to-World-spigot-stri.patch} | 0 ...ix-some-rails-connecting-improperly.patch} | 0 ...h => 0493-Incremental-player-saving.patch} | 0 ...Fix-MC-187716-Use-configured-height.patch} | 0 ...stake-in-CB-NBT-int-deserialization.patch} | 0 ...rver-load-chunks-from-newer-version.patch} | 0 ...support.patch => 0497-Brand-support.patch} | 0 ...patch => 0498-Add-setMaxPlayers-API.patch} | 0 ...PickupItemAnimation-to-LivingEntity.patch} | 0 ...h => 0500-Don-t-require-FACING-data.patch} | 0 ...eEvent-not-firing-for-all-use-cases.patch} | 0 ...PI.patch => 0502-Add-moon-phase-API.patch} | 0 ...headless-pistons-from-being-created.patch} | 0 ...ent.patch => 0504-Add-BellRingEvent.patch} | 0 ...dd-zombie-targets-turtle-egg-config.patch} | 0 ...patch => 0506-Buffer-joins-to-world.patch} | 0 ...=> 0507-Optimize-redstone-algorithm.patch} | 0 ...s-not-working-in-some-kick-messages.patch} | 0 ...reateEvent-needs-to-know-its-entity.patch} | 0 ...ch => 0510-Fix-CraftTeam-null-check.patch} | 0 ...I.patch => 0511-Add-more-Evoker-API.patch} | 0 ...translation-keys-for-blocks-entitie.patch} | 0 ...te-HoverEvent-from-ItemStack-Entity.patch} | 0 ...ch => 0514-Cache-block-data-strings.patch} | 0 ...rtation-and-cancel-velocity-if-tele.patch} | 0 ...l-open-container-api-to-HumanEntity.patch} | 0 ...aFixerUpper-Rewrite-Rules-on-demand.patch} | 0 ...-capture-to-capture-all-items-added.patch} | 0 ...ty-in-invalid-locations-SPIGOT-6086.patch} | 0 ...-Counter-to-allow-plugins-to-use-va.patch} | 0 ...track-plugin-scoreboards-by-default.patch} | 0 ...king.patch => 0522-Entity-isTicking.patch} | 0 ...non-whitelisted-player-when-white-l.patch} | 0 ...g-a-passenger-in-CreatureSpawnEvent.patch} | 0 ...eset-Ender-Crystals-on-Dragon-Spawn.patch} | 0 ...-large-move-vectors-crashing-server.patch} | 0 ...atch => 0527-Optimise-getType-calls.patch} | 0 ....patch => 0528-Villager-resetOffers.patch} | 0 ...nig-for-some-hot-IBlockData-methods.patch} | 0 ...ce-order-when-capturing-blockstates.patch} | 2 +- ...lockpos-allocation-from-pathfinding.patch} | 0 ...em-locations-dropped-from-campfires.patch} | 0 ...tch => 0533-Player-elytra-boost-API.patch} | 0 ...34-Fixed-TileEntityBell-memory-leak.patch} | 0 ...ing-up-when-item-stack-is-empty-in-.patch} | 0 ...Add-getOfflinePlayerIfCached-String.patch} | 0 ...ch => 0537-Add-ignore-discounts-API.patch} | 0 ...Toggle-for-removing-existing-dragon.patch} | 0 ...x-client-lag-on-advancement-loading.patch} | 0 ...> 0540-Item-no-age-no-player-pickup.patch} | 0 ...er-Remove-Streams-Optimized-collect.patch} | 0 ...542-Beacon-API-custom-effect-ranges.patch} | 0 ...tch => 0543-Add-API-for-quit-reason.patch} | 0 ...h => 0544-Seed-based-feature-search.patch} | 0 ...ng-Trader-spawn-rate-config-options.patch} | 0 ...rove-performance-of-the-end-generat.patch} | 0 ...ch => 0547-Expose-world-spawn-angle.patch} | 0 ...patch => 0548-Add-Destroy-Speed-API.patch} | 0 ...-spawnParticle-x-y-z-precision-loss.patch} | 0 ...50-Add-LivingEntity-clearActiveItem.patch} | 0 ...=> 0551-Add-PlayerItemCooldownEvent.patch} | 0 ...PI.patch => 0552-More-lightning-API.patch} | 0 ...should-not-bypass-cramming-gamerule.patch} | 0 ...-missing-default-perms-for-commands.patch} | 0 ...h => 0555-Add-PlayerShearBlockEvent.patch} | 0 ...rbose-world-setting-to-false-by-def.patch} | 0 ...ng-zombie-villager-discount-exploit.patch} | 0 ....patch => 0558-Limit-recipe-packets.patch} | 0 ...-CraftSound-backwards-compatibility.patch} | 0 ... 0560-MC-4-Fix-item-position-desync.patch} | 0 ...561-Player-Chunk-Load-Unload-Events.patch} | 0 ...2-Optimize-Dynamic-get-Missing-Keys.patch} | 0 ...-Expose-LivingEntity-hurt-direction.patch} | 0 ...OBSTRUCTED-reason-to-BedEnterResult.patch} | 0 ...-invalid-ingredient-lists-in-Villag.patch} | 0 ...atch => 0566-added-PlayerTradeEvent.patch} | 0 ...ch => 0567-Implement-TargetHitEvent.patch} | 0 ...568-Additional-Block-Material-API-s.patch} | 0 ...tch => 0569-Fix-harming-potion-dupe.patch} | 0 ...get-Material-from-Boats-and-Minecar.patch} | 0 ....patch => 0571-Cache-burn-durations.patch} | 0 ...ob-spawner-spawn-egg-transformation.patch} | 0 ...ment-PlayerFlowerPotManipulateEvent.patch} | 0 ...event-not-being-called-in-adventure.patch} | 0 ...h => 0575-Zombie-API-breaking-doors.patch} | 0 ...576-Fix-nerfed-slime-when-splitting.patch} | 0 ...=> 0577-Add-EntityLoadCrossbowEvent.patch} | 0 ...ch => 0578-Guardian-beam-workaround.patch} | 0 ...0579-Added-WorldGameRuleChangeEvent.patch} | 0 ...-Added-ServerResourcesReloadedEvent.patch} | 0 ...d-settings-for-mobs-picking-up-loot.patch} | 0 ...mplemented-BlockFailedDispenseEvent.patch} | 0 ...-Added-PlayerLecternPageChangeEvent.patch} | 0 ...-Added-PlayerLoomPatternSelectEvent.patch} | 0 ...nfigurable-door-breaking-difficulty.patch} | 0 ...ty-commands-shall-not-be-dispatched.patch} | 0 ...I-to-expose-exact-interaction-point.patch} | 0 ...OIs.patch => 0588-Remove-stale-POIs.patch} | 0 ...h => 0589-Fix-villager-boat-exploit.patch} | 0 ...I.patch => 0590-Add-sendOpLevel-API.patch} | 0 ...ch => 0591-Add-StructureLocateEvent.patch} | 0 ...-for-requiring-a-player-participant.patch} | 0 ...leHitEvent-call-when-fireballs-dead.patch} | 0 ...nent-with-empty-text-instead-of-thr.patch} | 0 ...595-Make-schedule-command-per-world.patch} | 0 ...596-Configurable-max-leash-distance.patch} | 0 ...597-Implement-BlockPreDispenseEvent.patch} | 0 ...h => 0598-Added-Vanilla-Entity-Tags.patch} | 0 ...-API.patch => 0599-added-Wither-API.patch} | 0 ...ng-of-PlayerChangeBeaconEffectEvent.patch} | 0 ...-spam-when-removing-chests-in-water.patch} | 0 ...e-for-always-placing-the-dragon-egg.patch} | 0 ...-PlayerStonecutterRecipeSelectEvent.patch} | 0 ...eash-variable-to-EntityUnleashEvent.patch} | 0 ...e-map-update-when-spawning-disabled.patch} | 0 ...shield-blocking-on-dimension-change.patch} | 0 ...atch => 0607-add-DragonEggFormEvent.patch} | 0 ...Event.patch => 0608-EntityMoveEvent.patch} | 0 ...isable-pathfinding-updates-on-block.patch} | 0 ... 0610-Inline-shift-direction-fields.patch} | 0 ...-adding-items-to-BlockDropItemEvent.patch} | 0 ...inThreadExecutor-to-BukkitScheduler.patch} | 0 ...entity-allow-attribute-registration.patch} | 0 ...ix-dead-slime-setSize-invincibility.patch} | 0 ...pes-should-return-an-immutable-list.patch} | 0 ....patch => 0616-misc-debugging-dumps.patch} | 0 ...port-for-hex-color-codes-in-console.patch} | 0 ...atch => 0618-Expose-Tracked-Players.patch} | 0 ...9-Remove-streams-from-SensorNearest.patch} | 0 ...ix-Wither-hostility-towards-players.patch} | 0 ...er-exception-on-empty-JsonList-file.patch} | 0 ...GUI.patch => 0622-Improve-ServerGUI.patch} | 0 ...ure-plate-EntityInteractEvent-for-i.patch} | 0 ...624-fix-converting-txt-to-json-file.patch} | 0 ...atch => 0625-Add-worldborder-events.patch} | 0 ...=> 0626-added-PlayerNameEntityEvent.patch} | 0 ...grindstones-from-overstacking-items.patch} | 0 ...h => 0628-Add-recipe-to-cook-events.patch} | 0 ...patch => 0629-Add-Block-isValidTool.patch} | 0 ...using-signs-inside-spawn-protection.patch} | 0 ...ch => 0631-Implement-Keyed-on-World.patch} | 0 ...ternative-constructor-for-Rotations.patch} | 0 ...y-API.patch => 0633-Item-Rarity-API.patch} | 0 ...imer-for-Wandering-Traders-spawned-.patch} | 0 ...py-TESign-isEditable-from-snapshots.patch} | 0 ...d-item-when-player-has-disconnected.patch} | 0 ...elist-use-configurable-kick-message.patch} | 0 ...gnore-result-of-PlayerEditBookEvent.patch} | 0 ...block-falling-causing-client-desync.patch} | 0 ...tch => 0640-Expose-protocol-version.patch} | 0 ...nt-suggestion-tooltips-in-AsyncTabC.patch} | 0 ...ab-completions-for-brigadier-comman.patch} | 0 ...temConsumeEvent-cancelling-properly.patch} | 0 ...patch => 0644-Add-bypass-host-check.patch} | 0 ...0645-Set-area-affect-cloud-rotation.patch} | 0 ...add-isDeeplySleeping-to-HumanEntity.patch} | 0 ...ting-give-items-on-item-drop-cancel.patch} | 0 ...add-consumeFuel-to-FurnaceBurnEvent.patch} | 0 ...-set-drop-chance-to-EntityEquipment.patch} | 0 ...ix-PigZombieAngerEvent-cancellation.patch} | 0 ...-checkReach-check-for-Shulker-boxes.patch} | 0 ...ix-PlayerItemHeldEvent-firing-twice.patch} | 0 ... => 0653-Added-PlayerDeepSleepEvent.patch} | 0 ...ld-API.patch => 0654-More-World-API.patch} | 0 ... 0655-Added-PlayerBedFailEnterEvent.patch} | 0 ...-to-convert-between-Component-and-B.patch} | 0 ...n-acting-as-a-bed-respawn-from-the-.patch} | 0 ...acon-activation-deactivation-events.patch} | 0 ...-RespawnFlags-to-PlayerRespawnEvent.patch} | 0 ...dd-Channel-initialization-listeners.patch} | 0 ...mands-if-tab-completion-is-disabled.patch} | 0 ...> 0662-Add-more-WanderingTrader-API.patch} | 0 ...dd-EntityBlockStorage-clearEntities.patch} | 0 ...ssage-to-PlayerAdvancementDoneEvent.patch} | 0 ...address-to-AsyncPlayerPreLoginEvent.patch} | 0 ...close.patch => 0666-Inventory-close.patch} | 0 ...reateEvent-players-and-end-platform.patch} | 0 ...-in-sunlight-API-for-Phantoms-and-S.patch} | 0 ...=> 0669-Fix-CraftPotionBrewer-cache.patch} | 0 ...atch => 0670-Add-basic-Datapack-API.patch} | 0 ...ment-variable-to-disable-server-gui.patch} | 0 ...itions-to-PlayerGameModeChangeEvent.patch} | 0 ... => 0673-ItemStack-repair-check-API.patch} | 0 ....patch => 0674-More-Enchantment-API.patch} | 0 ...option-to-load-extra-plugin-jars-no.patch} | 0 ...-and-optimise-world-force-upgrading.patch} | 2 +- ...PI.patch => 0677-Add-Mob-lookAt-API.patch} | 0 ...0678-Add-Unix-domain-socket-support.patch} | 0 ... => 0679-Add-EntityInsideBlockEvent.patch} | 0 ...80-Attributes-API-for-item-defaults.patch} | 0 ...hantCustom-emit-PlayerPurchaseEvent.patch} | 0 ...ause-to-Weather-ThunderChangeEvents.patch} | 0 ...patch => 0683-More-Lidded-Block-API.patch} | 0 ...84-Limit-item-frame-cursors-on-maps.patch} | 0 ...0685-Add-PufferFishStateChangeEvent.patch} | 0 ... => 0686-Add-PlayerKickEvent-causes.patch} | 0 ...erBucketEmptyEvent-result-itemstack.patch} | 0 ...tedContainer-instead-of-ReentrantLo.patch} | 0 ...-to-fix-items-merging-through-walls.patch} | 0 ...h => 0690-Add-BellRevealRaiderEvent.patch} | 0 ... 0691-Fix-invulnerable-end-crystals.patch} | 0 ...92-Add-ElderGuardianAppearanceEvent.patch} | 0 ...inventory-on-cancelled-pickup-event.patch} | 0 ...0694-Fix-dangerous-end-portal-logic.patch} | 0 ...-Biome-Mob-Lookups-for-Mob-Spawning.patch} | 0 ...-Make-item-validations-configurable.patch} | 0 ...0697-Add-more-line-of-sight-methods.patch} | 0 ... => 0698-add-per-world-spawn-limits.patch} | 0 ...plashEvent-for-water-splash-potions.patch} | 0 ...tus-dataconverter-for-pre-1.13-chun.patch} | 0 333 files changed, 147 insertions(+), 132 deletions(-) delete mode 100644 patches/removed/1.17/0369-Avoid-hopper-searches-if-there-are-no-items.patch create mode 100644 patches/server/0369-Avoid-hopper-searches-if-there-are-no-items.patch rename patches/server/{0369-Bees-get-gravity-in-void.-Fixes-MC-167279.patch => 0370-Bees-get-gravity-in-void.-Fixes-MC-167279.patch} (100%) rename patches/server/{0370-Optimise-getChunkAt-calls-for-loaded-chunks.patch => 0371-Optimise-getChunkAt-calls-for-loaded-chunks.patch} (100%) rename patches/server/{0371-Allow-overriding-the-java-version-check.patch => 0372-Allow-overriding-the-java-version-check.patch} (100%) rename patches/server/{0372-Add-ThrownEggHatchEvent.patch => 0373-Add-ThrownEggHatchEvent.patch} (100%) rename patches/server/{0373-Optimise-random-block-ticking.patch => 0374-Optimise-random-block-ticking.patch} (99%) rename patches/server/{0374-Entity-Jump-API.patch => 0375-Entity-Jump-API.patch} (100%) rename patches/server/{0375-Add-option-to-nerf-pigmen-from-nether-portals.patch => 0376-Add-option-to-nerf-pigmen-from-nether-portals.patch} (100%) rename patches/server/{0376-Make-the-GUI-graph-fancier.patch => 0377-Make-the-GUI-graph-fancier.patch} (100%) rename patches/server/{0377-add-hand-to-BlockMultiPlaceEvent.patch => 0378-add-hand-to-BlockMultiPlaceEvent.patch} (100%) rename patches/server/{0378-Prevent-teleporting-dead-entities.patch => 0379-Prevent-teleporting-dead-entities.patch} (100%) rename patches/server/{0379-Validate-tripwire-hook-placement-before-update.patch => 0380-Validate-tripwire-hook-placement-before-update.patch} (100%) rename patches/server/{0380-Add-option-to-allow-iron-golems-to-spawn-in-air.patch => 0381-Add-option-to-allow-iron-golems-to-spawn-in-air.patch} (100%) rename patches/server/{0381-Configurable-chance-of-villager-zombie-infection.patch => 0382-Configurable-chance-of-villager-zombie-infection.patch} (100%) rename patches/server/{0382-Optimise-Chunk-getFluid.patch => 0383-Optimise-Chunk-getFluid.patch} (100%) rename patches/server/{0383-Optimise-TickListServer-by-rewriting-it.patch => 0384-Optimise-TickListServer-by-rewriting-it.patch} (100%) rename patches/server/{0384-Pillager-patrol-spawn-settings-and-per-player-option.patch => 0385-Pillager-patrol-spawn-settings-and-per-player-option.patch} (100%) rename patches/server/{0385-Remote-Connections-shouldn-t-hold-up-shutdown.patch => 0386-Remote-Connections-shouldn-t-hold-up-shutdown.patch} (100%) rename patches/server/{0386-Do-not-allow-bees-to-load-chunks-for-beehives.patch => 0387-Do-not-allow-bees-to-load-chunks-for-beehives.patch} (100%) rename patches/server/{0387-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch => 0388-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch} (100%) rename patches/server/{0388-Optimize-Collision-to-not-load-chunks.patch => 0389-Optimize-Collision-to-not-load-chunks.patch} (100%) rename patches/server/{0389-Don-t-tick-dead-players.patch => 0390-Don-t-tick-dead-players.patch} (100%) rename patches/server/{0390-Dead-Player-s-shouldn-t-be-able-to-move.patch => 0391-Dead-Player-s-shouldn-t-be-able-to-move.patch} (100%) rename patches/server/{0391-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch => 0392-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch} (100%) rename patches/server/{0392-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch => 0393-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch} (100%) rename patches/server/{0393-Don-t-move-existing-players-to-world-spawn.patch => 0394-Don-t-move-existing-players-to-world-spawn.patch} (100%) rename patches/server/{0394-Add-tick-times-API-and-mspt-command.patch => 0395-Add-tick-times-API-and-mspt-command.patch} (100%) rename patches/server/{0395-Expose-MinecraftServer-isRunning.patch => 0396-Expose-MinecraftServer-isRunning.patch} (100%) rename patches/server/{0396-Add-Raw-Byte-ItemStack-Serialization.patch => 0397-Add-Raw-Byte-ItemStack-Serialization.patch} (100%) rename patches/server/{0397-Remove-streams-from-Mob-AI-System.patch => 0398-Remove-streams-from-Mob-AI-System.patch} (100%) rename patches/server/{0398-Async-command-map-building.patch => 0399-Async-command-map-building.patch} (100%) rename patches/server/{0399-Improved-Watchdog-Support.patch => 0400-Improved-Watchdog-Support.patch} (99%) rename patches/server/{0400-Optimize-Pathfinding.patch => 0401-Optimize-Pathfinding.patch} (100%) rename patches/server/{0401-Reduce-Either-Optional-allocation.patch => 0402-Reduce-Either-Optional-allocation.patch} (100%) rename patches/server/{0402-Remove-streams-from-PairedQueue.patch => 0403-Remove-streams-from-PairedQueue.patch} (100%) rename patches/server/{0403-Reduce-memory-footprint-of-NBTTagCompound.patch => 0404-Reduce-memory-footprint-of-NBTTagCompound.patch} (100%) rename patches/server/{0404-Prevent-opening-inventories-when-frozen.patch => 0405-Prevent-opening-inventories-when-frozen.patch} (100%) rename patches/server/{0405-Optimise-ArraySetSorted-removeIf.patch => 0406-Optimise-ArraySetSorted-removeIf.patch} (100%) rename patches/server/{0406-Don-t-run-entity-collision-code-if-not-needed.patch => 0407-Don-t-run-entity-collision-code-if-not-needed.patch} (100%) rename patches/server/{0407-Restrict-vanilla-teleport-command-to-valid-locations.patch => 0408-Restrict-vanilla-teleport-command-to-valid-locations.patch} (100%) rename patches/server/{0408-Implement-Player-Client-Options-API.patch => 0409-Implement-Player-Client-Options-API.patch} (100%) rename patches/server/{0409-Fix-Chunk-Post-Processing-deadlock-risk.patch => 0410-Fix-Chunk-Post-Processing-deadlock-risk.patch} (100%) rename patches/server/{0410-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch => 0411-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch} (100%) rename patches/server/{0411-Broadcast-join-message-to-console.patch => 0412-Broadcast-join-message-to-console.patch} (100%) rename patches/server/{0412-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch => 0413-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch} (100%) rename patches/server/{0413-Load-Chunks-for-Login-Asynchronously.patch => 0414-Load-Chunks-for-Login-Asynchronously.patch} (100%) rename patches/server/{0414-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch => 0415-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch} (100%) rename patches/server/{0415-Add-PlayerAttackEntityCooldownResetEvent.patch => 0416-Add-PlayerAttackEntityCooldownResetEvent.patch} (100%) rename patches/server/{0416-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch => 0417-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch} (100%) rename patches/server/{0417-Don-t-fire-BlockFade-on-worldgen-threads.patch => 0418-Don-t-fire-BlockFade-on-worldgen-threads.patch} (100%) rename patches/server/{0418-Add-phantom-creative-and-insomniac-controls.patch => 0419-Add-phantom-creative-and-insomniac-controls.patch} (100%) rename patches/server/{0419-Fix-numerous-item-duplication-issues-and-teleport-is.patch => 0420-Fix-numerous-item-duplication-issues-and-teleport-is.patch} (100%) rename patches/server/{0420-Implement-Brigadier-Mojang-API.patch => 0421-Implement-Brigadier-Mojang-API.patch} (100%) rename patches/server/{0421-Villager-Restocks-API.patch => 0422-Villager-Restocks-API.patch} (100%) rename patches/server/{0422-Validate-PickItem-Packet-and-kick-for-invalid.patch => 0423-Validate-PickItem-Packet-and-kick-for-invalid.patch} (100%) rename patches/server/{0423-Expose-game-version.patch => 0424-Expose-game-version.patch} (100%) rename patches/server/{0424-Optimize-Voxel-Shape-Merging.patch => 0425-Optimize-Voxel-Shape-Merging.patch} (100%) rename patches/server/{0425-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch => 0426-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch} (100%) rename patches/server/{0426-Implement-Mob-Goal-API.patch => 0427-Implement-Mob-Goal-API.patch} (100%) rename patches/server/{0427-Use-distance-map-to-optimise-entity-tracker.patch => 0428-Use-distance-map-to-optimise-entity-tracker.patch} (100%) rename patches/server/{0428-Optimize-isOutsideRange-to-use-distance-maps.patch => 0429-Optimize-isOutsideRange-to-use-distance-maps.patch} (100%) rename patches/server/{0429-Add-villager-reputation-API.patch => 0430-Add-villager-reputation-API.patch} (100%) rename patches/server/{0430-Option-for-maximum-exp-value-when-merging-orbs.patch => 0431-Option-for-maximum-exp-value-when-merging-orbs.patch} (100%) rename patches/server/{0431-ExperienceOrbMergeEvent.patch => 0432-ExperienceOrbMergeEvent.patch} (100%) rename patches/server/{0432-Fix-PotionEffect-ignores-icon-flag.patch => 0433-Fix-PotionEffect-ignores-icon-flag.patch} (100%) rename patches/server/{0433-Optimize-brigadier-child-sorting-performance.patch => 0434-Optimize-brigadier-child-sorting-performance.patch} (100%) rename patches/server/{0434-Potential-bed-API.patch => 0435-Potential-bed-API.patch} (100%) rename patches/server/{0435-Wait-for-Async-Tasks-during-shutdown.patch => 0436-Wait-for-Async-Tasks-during-shutdown.patch} (100%) rename patches/server/{0436-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch => 0437-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch} (100%) rename patches/server/{0437-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch => 0438-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch} (99%) rename patches/server/{0438-Reduce-MutableInt-allocations-from-light-engine.patch => 0439-Reduce-MutableInt-allocations-from-light-engine.patch} (100%) rename patches/server/{0439-Reduce-allocation-of-Vec3D-by-entity-tracker.patch => 0440-Reduce-allocation-of-Vec3D-by-entity-tracker.patch} (100%) rename patches/server/{0440-Ensure-safe-gateway-teleport.patch => 0441-Ensure-safe-gateway-teleport.patch} (100%) rename patches/server/{0441-Add-option-for-console-having-all-permissions.patch => 0442-Add-option-for-console-having-all-permissions.patch} (100%) rename patches/server/{0442-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch => 0443-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch} (100%) rename patches/server/{0443-Optimize-sending-packets-to-nearby-locations-sounds-.patch => 0444-Optimize-sending-packets-to-nearby-locations-sounds-.patch} (100%) rename patches/server/{0444-Fix-villager-trading-demand-MC-163962.patch => 0445-Fix-villager-trading-demand-MC-163962.patch} (100%) rename patches/server/{0445-Maps-shouldn-t-load-chunks.patch => 0446-Maps-shouldn-t-load-chunks.patch} (100%) rename patches/server/{0446-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch => 0447-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch} (100%) rename patches/server/{0447-Delay-Chunk-Unloads-based-on-Player-Movement.patch => 0448-Delay-Chunk-Unloads-based-on-Player-Movement.patch} (100%) rename patches/server/{0448-Optimize-Bit-Operations-by-inlining.patch => 0449-Optimize-Bit-Operations-by-inlining.patch} (100%) rename patches/server/{0449-incremental-chunk-saving.patch => 0450-incremental-chunk-saving.patch} (100%) rename patches/server/{0450-Add-Plugin-Tickets-to-API-Chunk-Methods.patch => 0451-Add-Plugin-Tickets-to-API-Chunk-Methods.patch} (100%) rename patches/server/{0451-Fix-missing-chunks-due-to-integer-overflow.patch => 0452-Fix-missing-chunks-due-to-integer-overflow.patch} (100%) rename patches/server/{0452-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch => 0453-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch} (100%) rename patches/server/{0453-Fix-piston-physics-inconsistency-MC-188840.patch => 0454-Fix-piston-physics-inconsistency-MC-188840.patch} (100%) rename patches/server/{0454-Fix-sand-duping.patch => 0455-Fix-sand-duping.patch} (100%) rename patches/server/{0455-Prevent-position-desync-in-playerconnection-causing-.patch => 0456-Prevent-position-desync-in-playerconnection-causing-.patch} (100%) rename patches/server/{0456-Inventory-getHolder-method-without-block-snapshot.patch => 0457-Inventory-getHolder-method-without-block-snapshot.patch} (100%) rename patches/server/{0457-Expose-Arrow-getItemStack.patch => 0458-Expose-Arrow-getItemStack.patch} (100%) rename patches/server/{0458-Add-and-implement-PlayerRecipeBookClickEvent.patch => 0459-Add-and-implement-PlayerRecipeBookClickEvent.patch} (100%) rename patches/server/{0459-Hide-sync-chunk-writes-behind-flag.patch => 0460-Hide-sync-chunk-writes-behind-flag.patch} (100%) rename patches/server/{0460-Add-permission-for-command-blocks.patch => 0461-Add-permission-for-command-blocks.patch} (100%) rename patches/server/{0461-Ensure-Entity-AABB-s-are-never-invalid.patch => 0462-Ensure-Entity-AABB-s-are-never-invalid.patch} (100%) rename patches/server/{0462-Optimize-WorldBorder-collision-checks-and-air.patch => 0463-Optimize-WorldBorder-collision-checks-and-air.patch} (100%) rename patches/server/{0463-Fix-Per-World-Difficulty-Remembering-Difficulty.patch => 0464-Fix-Per-World-Difficulty-Remembering-Difficulty.patch} (100%) rename patches/server/{0464-Paper-dumpitem-command.patch => 0465-Paper-dumpitem-command.patch} (100%) rename patches/server/{0465-Don-t-allow-null-UUID-s-for-chat.patch => 0466-Don-t-allow-null-UUID-s-for-chat.patch} (100%) rename patches/server/{0466-Improve-Legacy-Component-serialization-size.patch => 0467-Improve-Legacy-Component-serialization-size.patch} (100%) rename patches/server/{0467-Support-old-UUID-format-for-NBT.patch => 0468-Support-old-UUID-format-for-NBT.patch} (100%) rename patches/server/{0468-Clean-up-duplicated-GameProfile-Properties.patch => 0469-Clean-up-duplicated-GameProfile-Properties.patch} (100%) rename patches/server/{0469-Convert-legacy-attributes-in-Item-Meta.patch => 0470-Convert-legacy-attributes-in-Item-Meta.patch} (100%) rename patches/server/{0470-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch => 0471-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch} (100%) rename patches/server/{0471-Remove-some-streams-from-structures.patch => 0472-Remove-some-streams-from-structures.patch} (100%) rename patches/server/{0472-Remove-streams-from-classes-related-villager-gossip.patch => 0473-Remove-streams-from-classes-related-villager-gossip.patch} (100%) rename patches/server/{0473-Support-components-in-ItemMeta.patch => 0474-Support-components-in-ItemMeta.patch} (100%) rename patches/server/{0474-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch => 0475-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch} (100%) rename patches/server/{0475-Add-entity-liquid-API.patch => 0476-Add-entity-liquid-API.patch} (100%) rename patches/server/{0476-Update-itemstack-legacy-name-and-lore.patch => 0477-Update-itemstack-legacy-name-and-lore.patch} (100%) rename patches/server/{0477-Spawn-player-in-correct-world-on-login.patch => 0478-Spawn-player-in-correct-world-on-login.patch} (100%) rename patches/server/{0478-Add-PrepareResultEvent.patch => 0479-Add-PrepareResultEvent.patch} (100%) rename patches/server/{0479-Allow-delegation-to-vanilla-chunk-gen.patch => 0480-Allow-delegation-to-vanilla-chunk-gen.patch} (100%) rename patches/server/{0480-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch => 0481-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch} (100%) rename patches/server/{0481-Optimize-NetworkManager-Exception-Handling.patch => 0482-Optimize-NetworkManager-Exception-Handling.patch} (100%) rename patches/server/{0482-Optimize-the-advancement-data-player-iteration-to-be.patch => 0483-Optimize-the-advancement-data-player-iteration-to-be.patch} (100%) rename patches/server/{0483-Fix-arrows-never-despawning-MC-125757.patch => 0484-Fix-arrows-never-despawning-MC-125757.patch} (100%) rename patches/server/{0484-Thread-Safe-Vanilla-Command-permission-checking.patch => 0485-Thread-Safe-Vanilla-Command-permission-checking.patch} (100%) rename patches/server/{0485-Move-range-check-for-block-placing-up.patch => 0486-Move-range-check-for-block-placing-up.patch} (100%) rename patches/server/{0486-Fix-SPIGOT-5989.patch => 0487-Fix-SPIGOT-5989.patch} (100%) rename patches/server/{0487-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch => 0488-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch} (100%) rename patches/server/{0488-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch => 0489-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch} (100%) rename patches/server/{0489-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch => 0490-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch} (100%) rename patches/server/{0490-Add-missing-strikeLighting-call-to-World-spigot-stri.patch => 0491-Add-missing-strikeLighting-call-to-World-spigot-stri.patch} (100%) rename patches/server/{0491-Fix-some-rails-connecting-improperly.patch => 0492-Fix-some-rails-connecting-improperly.patch} (100%) rename patches/server/{0492-Incremental-player-saving.patch => 0493-Incremental-player-saving.patch} (100%) rename patches/server/{0493-Fix-MC-187716-Use-configured-height.patch => 0494-Fix-MC-187716-Use-configured-height.patch} (100%) rename patches/server/{0494-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch => 0495-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch} (100%) rename patches/server/{0495-Do-not-let-the-server-load-chunks-from-newer-version.patch => 0496-Do-not-let-the-server-load-chunks-from-newer-version.patch} (100%) rename patches/server/{0496-Brand-support.patch => 0497-Brand-support.patch} (100%) rename patches/server/{0497-Add-setMaxPlayers-API.patch => 0498-Add-setMaxPlayers-API.patch} (100%) rename patches/server/{0498-Add-playPickupItemAnimation-to-LivingEntity.patch => 0499-Add-playPickupItemAnimation-to-LivingEntity.patch} (100%) rename patches/server/{0499-Don-t-require-FACING-data.patch => 0500-Don-t-require-FACING-data.patch} (100%) rename patches/server/{0500-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch => 0501-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch} (100%) rename patches/server/{0501-Add-moon-phase-API.patch => 0502-Add-moon-phase-API.patch} (100%) rename patches/server/{0502-Prevent-headless-pistons-from-being-created.patch => 0503-Prevent-headless-pistons-from-being-created.patch} (100%) rename patches/server/{0503-Add-BellRingEvent.patch => 0504-Add-BellRingEvent.patch} (100%) rename patches/server/{0504-Add-zombie-targets-turtle-egg-config.patch => 0505-Add-zombie-targets-turtle-egg-config.patch} (100%) rename patches/server/{0505-Buffer-joins-to-world.patch => 0506-Buffer-joins-to-world.patch} (100%) rename patches/server/{0506-Optimize-redstone-algorithm.patch => 0507-Optimize-redstone-algorithm.patch} (100%) rename patches/server/{0507-Fix-hex-colors-not-working-in-some-kick-messages.patch => 0508-Fix-hex-colors-not-working-in-some-kick-messages.patch} (100%) rename patches/server/{0508-PortalCreateEvent-needs-to-know-its-entity.patch => 0509-PortalCreateEvent-needs-to-know-its-entity.patch} (100%) rename patches/server/{0509-Fix-CraftTeam-null-check.patch => 0510-Fix-CraftTeam-null-check.patch} (100%) rename patches/server/{0510-Add-more-Evoker-API.patch => 0511-Add-more-Evoker-API.patch} (100%) rename patches/server/{0511-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch => 0512-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch} (100%) rename patches/server/{0512-Create-HoverEvent-from-ItemStack-Entity.patch => 0513-Create-HoverEvent-from-ItemStack-Entity.patch} (100%) rename patches/server/{0513-Cache-block-data-strings.patch => 0514-Cache-block-data-strings.patch} (100%) rename patches/server/{0514-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch => 0515-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch} (100%) rename patches/server/{0515-Add-additional-open-container-api-to-HumanEntity.patch => 0516-Add-additional-open-container-api-to-HumanEntity.patch} (100%) rename patches/server/{0516-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch => 0517-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch} (100%) rename patches/server/{0517-Extend-block-drop-capture-to-capture-all-items-added.patch => 0518-Extend-block-drop-capture-to-capture-all-items-added.patch} (100%) rename patches/server/{0518-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch => 0519-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch} (100%) rename patches/server/{0519-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch => 0520-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch} (100%) rename patches/server/{0520-Lazily-track-plugin-scoreboards-by-default.patch => 0521-Lazily-track-plugin-scoreboards-by-default.patch} (100%) rename patches/server/{0521-Entity-isTicking.patch => 0522-Entity-isTicking.patch} (100%) rename patches/server/{0522-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch => 0523-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch} (100%) rename patches/server/{0523-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch => 0524-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch} (100%) rename patches/server/{0524-Reset-Ender-Crystals-on-Dragon-Spawn.patch => 0525-Reset-Ender-Crystals-on-Dragon-Spawn.patch} (100%) rename patches/server/{0525-Fix-for-large-move-vectors-crashing-server.patch => 0526-Fix-for-large-move-vectors-crashing-server.patch} (100%) rename patches/server/{0526-Optimise-getType-calls.patch => 0527-Optimise-getType-calls.patch} (100%) rename patches/server/{0527-Villager-resetOffers.patch => 0528-Villager-resetOffers.patch} (100%) rename patches/server/{0528-Improve-inlinig-for-some-hot-IBlockData-methods.patch => 0529-Improve-inlinig-for-some-hot-IBlockData-methods.patch} (100%) rename patches/server/{0529-Retain-block-place-order-when-capturing-blockstates.patch => 0530-Retain-block-place-order-when-capturing-blockstates.patch} (93%) rename patches/server/{0530-Reduce-blockpos-allocation-from-pathfinding.patch => 0531-Reduce-blockpos-allocation-from-pathfinding.patch} (100%) rename patches/server/{0531-Fix-item-locations-dropped-from-campfires.patch => 0532-Fix-item-locations-dropped-from-campfires.patch} (100%) rename patches/server/{0532-Player-elytra-boost-API.patch => 0533-Player-elytra-boost-API.patch} (100%) rename patches/server/{0533-Fixed-TileEntityBell-memory-leak.patch => 0534-Fixed-TileEntityBell-memory-leak.patch} (100%) rename patches/server/{0534-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch => 0535-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch} (100%) rename patches/server/{0535-Add-getOfflinePlayerIfCached-String.patch => 0536-Add-getOfflinePlayerIfCached-String.patch} (100%) rename patches/server/{0536-Add-ignore-discounts-API.patch => 0537-Add-ignore-discounts-API.patch} (100%) rename patches/server/{0537-Toggle-for-removing-existing-dragon.patch => 0538-Toggle-for-removing-existing-dragon.patch} (100%) rename patches/server/{0538-Fix-client-lag-on-advancement-loading.patch => 0539-Fix-client-lag-on-advancement-loading.patch} (100%) rename patches/server/{0539-Item-no-age-no-player-pickup.patch => 0540-Item-no-age-no-player-pickup.patch} (100%) rename patches/server/{0540-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch => 0541-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch} (100%) rename patches/server/{0541-Beacon-API-custom-effect-ranges.patch => 0542-Beacon-API-custom-effect-ranges.patch} (100%) rename patches/server/{0542-Add-API-for-quit-reason.patch => 0543-Add-API-for-quit-reason.patch} (100%) rename patches/server/{0543-Seed-based-feature-search.patch => 0544-Seed-based-feature-search.patch} (100%) rename patches/server/{0544-Add-Wandering-Trader-spawn-rate-config-options.patch => 0545-Add-Wandering-Trader-spawn-rate-config-options.patch} (100%) rename patches/server/{0545-Significantly-improve-performance-of-the-end-generat.patch => 0546-Significantly-improve-performance-of-the-end-generat.patch} (100%) rename patches/server/{0546-Expose-world-spawn-angle.patch => 0547-Expose-world-spawn-angle.patch} (100%) rename patches/server/{0547-Add-Destroy-Speed-API.patch => 0548-Add-Destroy-Speed-API.patch} (100%) rename patches/server/{0548-Fix-Player-spawnParticle-x-y-z-precision-loss.patch => 0549-Fix-Player-spawnParticle-x-y-z-precision-loss.patch} (100%) rename patches/server/{0549-Add-LivingEntity-clearActiveItem.patch => 0550-Add-LivingEntity-clearActiveItem.patch} (100%) rename patches/server/{0550-Add-PlayerItemCooldownEvent.patch => 0551-Add-PlayerItemCooldownEvent.patch} (100%) rename patches/server/{0551-More-lightning-API.patch => 0552-More-lightning-API.patch} (100%) rename patches/server/{0552-Climbing-should-not-bypass-cramming-gamerule.patch => 0553-Climbing-should-not-bypass-cramming-gamerule.patch} (100%) rename patches/server/{0553-Added-missing-default-perms-for-commands.patch => 0554-Added-missing-default-perms-for-commands.patch} (100%) rename patches/server/{0554-Add-PlayerShearBlockEvent.patch => 0555-Add-PlayerShearBlockEvent.patch} (100%) rename patches/server/{0555-Set-spigots-verbose-world-setting-to-false-by-def.patch => 0556-Set-spigots-verbose-world-setting-to-false-by-def.patch} (100%) rename patches/server/{0556-Fix-curing-zombie-villager-discount-exploit.patch => 0557-Fix-curing-zombie-villager-discount-exploit.patch} (100%) rename patches/server/{0557-Limit-recipe-packets.patch => 0558-Limit-recipe-packets.patch} (100%) rename patches/server/{0558-Fix-CraftSound-backwards-compatibility.patch => 0559-Fix-CraftSound-backwards-compatibility.patch} (100%) rename patches/server/{0559-MC-4-Fix-item-position-desync.patch => 0560-MC-4-Fix-item-position-desync.patch} (100%) rename patches/server/{0560-Player-Chunk-Load-Unload-Events.patch => 0561-Player-Chunk-Load-Unload-Events.patch} (100%) rename patches/server/{0561-Optimize-Dynamic-get-Missing-Keys.patch => 0562-Optimize-Dynamic-get-Missing-Keys.patch} (100%) rename patches/server/{0562-Expose-LivingEntity-hurt-direction.patch => 0563-Expose-LivingEntity-hurt-direction.patch} (100%) rename patches/server/{0563-Add-OBSTRUCTED-reason-to-BedEnterResult.patch => 0564-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} (100%) rename patches/server/{0564-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch => 0565-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch} (100%) rename patches/server/{0565-added-PlayerTradeEvent.patch => 0566-added-PlayerTradeEvent.patch} (100%) rename patches/server/{0566-Implement-TargetHitEvent.patch => 0567-Implement-TargetHitEvent.patch} (100%) rename patches/server/{0567-Additional-Block-Material-API-s.patch => 0568-Additional-Block-Material-API-s.patch} (100%) rename patches/server/{0568-Fix-harming-potion-dupe.patch => 0569-Fix-harming-potion-dupe.patch} (100%) rename patches/server/{0569-Implement-API-to-get-Material-from-Boats-and-Minecar.patch => 0570-Implement-API-to-get-Material-from-Boats-and-Minecar.patch} (100%) rename patches/server/{0570-Cache-burn-durations.patch => 0571-Cache-burn-durations.patch} (100%) rename patches/server/{0571-Allow-disabling-mob-spawner-spawn-egg-transformation.patch => 0572-Allow-disabling-mob-spawner-spawn-egg-transformation.patch} (100%) rename patches/server/{0572-Implement-PlayerFlowerPotManipulateEvent.patch => 0573-Implement-PlayerFlowerPotManipulateEvent.patch} (100%) rename patches/server/{0573-Fix-interact-event-not-being-called-in-adventure.patch => 0574-Fix-interact-event-not-being-called-in-adventure.patch} (100%) rename patches/server/{0574-Zombie-API-breaking-doors.patch => 0575-Zombie-API-breaking-doors.patch} (100%) rename patches/server/{0575-Fix-nerfed-slime-when-splitting.patch => 0576-Fix-nerfed-slime-when-splitting.patch} (100%) rename patches/server/{0576-Add-EntityLoadCrossbowEvent.patch => 0577-Add-EntityLoadCrossbowEvent.patch} (100%) rename patches/server/{0577-Guardian-beam-workaround.patch => 0578-Guardian-beam-workaround.patch} (100%) rename patches/server/{0578-Added-WorldGameRuleChangeEvent.patch => 0579-Added-WorldGameRuleChangeEvent.patch} (100%) rename patches/server/{0579-Added-ServerResourcesReloadedEvent.patch => 0580-Added-ServerResourcesReloadedEvent.patch} (100%) rename patches/server/{0580-Added-world-settings-for-mobs-picking-up-loot.patch => 0581-Added-world-settings-for-mobs-picking-up-loot.patch} (100%) rename patches/server/{0581-Implemented-BlockFailedDispenseEvent.patch => 0582-Implemented-BlockFailedDispenseEvent.patch} (100%) rename patches/server/{0582-Added-PlayerLecternPageChangeEvent.patch => 0583-Added-PlayerLecternPageChangeEvent.patch} (100%) rename patches/server/{0583-Added-PlayerLoomPatternSelectEvent.patch => 0584-Added-PlayerLoomPatternSelectEvent.patch} (100%) rename patches/server/{0584-Configurable-door-breaking-difficulty.patch => 0585-Configurable-door-breaking-difficulty.patch} (100%) rename patches/server/{0585-Empty-commands-shall-not-be-dispatched.patch => 0586-Empty-commands-shall-not-be-dispatched.patch} (100%) rename patches/server/{0586-Implement-API-to-expose-exact-interaction-point.patch => 0587-Implement-API-to-expose-exact-interaction-point.patch} (100%) rename patches/server/{0587-Remove-stale-POIs.patch => 0588-Remove-stale-POIs.patch} (100%) rename patches/server/{0588-Fix-villager-boat-exploit.patch => 0589-Fix-villager-boat-exploit.patch} (100%) rename patches/server/{0589-Add-sendOpLevel-API.patch => 0590-Add-sendOpLevel-API.patch} (100%) rename patches/server/{0590-Add-StructureLocateEvent.patch => 0591-Add-StructureLocateEvent.patch} (100%) rename patches/server/{0591-Collision-option-for-requiring-a-player-participant.patch => 0592-Collision-option-for-requiring-a-player-participant.patch} (100%) rename patches/server/{0592-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch => 0593-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch} (100%) rename patches/server/{0593-Return-chat-component-with-empty-text-instead-of-thr.patch => 0594-Return-chat-component-with-empty-text-instead-of-thr.patch} (100%) rename patches/server/{0594-Make-schedule-command-per-world.patch => 0595-Make-schedule-command-per-world.patch} (100%) rename patches/server/{0595-Configurable-max-leash-distance.patch => 0596-Configurable-max-leash-distance.patch} (100%) rename patches/server/{0596-Implement-BlockPreDispenseEvent.patch => 0597-Implement-BlockPreDispenseEvent.patch} (100%) rename patches/server/{0597-Added-Vanilla-Entity-Tags.patch => 0598-Added-Vanilla-Entity-Tags.patch} (100%) rename patches/server/{0598-added-Wither-API.patch => 0599-added-Wither-API.patch} (100%) rename patches/server/{0599-Added-firing-of-PlayerChangeBeaconEffectEvent.patch => 0600-Added-firing-of-PlayerChangeBeaconEffectEvent.patch} (100%) rename patches/server/{0600-Fix-console-spam-when-removing-chests-in-water.patch => 0601-Fix-console-spam-when-removing-chests-in-water.patch} (100%) rename patches/server/{0601-Add-toggle-for-always-placing-the-dragon-egg.patch => 0602-Add-toggle-for-always-placing-the-dragon-egg.patch} (100%) rename patches/server/{0602-Added-PlayerStonecutterRecipeSelectEvent.patch => 0603-Added-PlayerStonecutterRecipeSelectEvent.patch} (100%) rename patches/server/{0603-Add-dropLeash-variable-to-EntityUnleashEvent.patch => 0604-Add-dropLeash-variable-to-EntityUnleashEvent.patch} (100%) rename patches/server/{0604-Skip-distance-map-update-when-spawning-disabled.patch => 0605-Skip-distance-map-update-when-spawning-disabled.patch} (100%) rename patches/server/{0605-Reset-shield-blocking-on-dimension-change.patch => 0606-Reset-shield-blocking-on-dimension-change.patch} (100%) rename patches/server/{0606-add-DragonEggFormEvent.patch => 0607-add-DragonEggFormEvent.patch} (100%) rename patches/server/{0607-EntityMoveEvent.patch => 0608-EntityMoveEvent.patch} (100%) rename patches/server/{0608-added-option-to-disable-pathfinding-updates-on-block.patch => 0609-added-option-to-disable-pathfinding-updates-on-block.patch} (100%) rename patches/server/{0609-Inline-shift-direction-fields.patch => 0610-Inline-shift-direction-fields.patch} (100%) rename patches/server/{0610-Allow-adding-items-to-BlockDropItemEvent.patch => 0611-Allow-adding-items-to-BlockDropItemEvent.patch} (100%) rename patches/server/{0611-Add-getMainThreadExecutor-to-BukkitScheduler.patch => 0612-Add-getMainThreadExecutor-to-BukkitScheduler.patch} (100%) rename patches/server/{0612-living-entity-allow-attribute-registration.patch => 0613-living-entity-allow-attribute-registration.patch} (100%) rename patches/server/{0613-fix-dead-slime-setSize-invincibility.patch => 0614-fix-dead-slime-setSize-invincibility.patch} (100%) rename patches/server/{0614-Merchant-getRecipes-should-return-an-immutable-list.patch => 0615-Merchant-getRecipes-should-return-an-immutable-list.patch} (100%) rename patches/server/{0615-misc-debugging-dumps.patch => 0616-misc-debugging-dumps.patch} (100%) rename patches/server/{0616-Add-support-for-hex-color-codes-in-console.patch => 0617-Add-support-for-hex-color-codes-in-console.patch} (100%) rename patches/server/{0617-Expose-Tracked-Players.patch => 0618-Expose-Tracked-Players.patch} (100%) rename patches/server/{0618-Remove-streams-from-SensorNearest.patch => 0619-Remove-streams-from-SensorNearest.patch} (100%) rename patches/server/{0619-MC-29274-Fix-Wither-hostility-towards-players.patch => 0620-MC-29274-Fix-Wither-hostility-towards-players.patch} (100%) rename patches/server/{0620-Throw-proper-exception-on-empty-JsonList-file.patch => 0621-Throw-proper-exception-on-empty-JsonList-file.patch} (100%) rename patches/server/{0621-Improve-ServerGUI.patch => 0622-Improve-ServerGUI.patch} (100%) rename patches/server/{0622-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch => 0623-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch} (100%) rename patches/server/{0623-fix-converting-txt-to-json-file.patch => 0624-fix-converting-txt-to-json-file.patch} (100%) rename patches/server/{0624-Add-worldborder-events.patch => 0625-Add-worldborder-events.patch} (100%) rename patches/server/{0625-added-PlayerNameEntityEvent.patch => 0626-added-PlayerNameEntityEvent.patch} (100%) rename patches/server/{0626-Prevent-grindstones-from-overstacking-items.patch => 0627-Prevent-grindstones-from-overstacking-items.patch} (100%) rename patches/server/{0627-Add-recipe-to-cook-events.patch => 0628-Add-recipe-to-cook-events.patch} (100%) rename patches/server/{0628-Add-Block-isValidTool.patch => 0629-Add-Block-isValidTool.patch} (100%) rename patches/server/{0629-Allow-using-signs-inside-spawn-protection.patch => 0630-Allow-using-signs-inside-spawn-protection.patch} (100%) rename patches/server/{0630-Implement-Keyed-on-World.patch => 0631-Implement-Keyed-on-World.patch} (100%) rename patches/server/{0631-Add-fast-alternative-constructor-for-Rotations.patch => 0632-Add-fast-alternative-constructor-for-Rotations.patch} (100%) rename patches/server/{0632-Item-Rarity-API.patch => 0633-Item-Rarity-API.patch} (100%) rename patches/server/{0633-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch => 0634-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch} (100%) rename patches/server/{0634-copy-TESign-isEditable-from-snapshots.patch => 0635-copy-TESign-isEditable-from-snapshots.patch} (100%) rename patches/server/{0635-Drop-carried-item-when-player-has-disconnected.patch => 0636-Drop-carried-item-when-player-has-disconnected.patch} (100%) rename patches/server/{0636-forced-whitelist-use-configurable-kick-message.patch => 0637-forced-whitelist-use-configurable-kick-message.patch} (100%) rename patches/server/{0637-Don-t-ignore-result-of-PlayerEditBookEvent.patch => 0638-Don-t-ignore-result-of-PlayerEditBookEvent.patch} (100%) rename patches/server/{0638-fix-cancelling-block-falling-causing-client-desync.patch => 0639-fix-cancelling-block-falling-causing-client-desync.patch} (100%) rename patches/server/{0639-Expose-protocol-version.patch => 0640-Expose-protocol-version.patch} (100%) rename patches/server/{0640-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch => 0641-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} (100%) rename patches/server/{0641-Enhance-console-tab-completions-for-brigadier-comman.patch => 0642-Enhance-console-tab-completions-for-brigadier-comman.patch} (100%) rename patches/server/{0642-Fix-PlayerItemConsumeEvent-cancelling-properly.patch => 0643-Fix-PlayerItemConsumeEvent-cancelling-properly.patch} (100%) rename patches/server/{0643-Add-bypass-host-check.patch => 0644-Add-bypass-host-check.patch} (100%) rename patches/server/{0644-Set-area-affect-cloud-rotation.patch => 0645-Set-area-affect-cloud-rotation.patch} (100%) rename patches/server/{0645-add-isDeeplySleeping-to-HumanEntity.patch => 0646-add-isDeeplySleeping-to-HumanEntity.patch} (100%) rename patches/server/{0646-Fix-duplicating-give-items-on-item-drop-cancel.patch => 0647-Fix-duplicating-give-items-on-item-drop-cancel.patch} (100%) rename patches/server/{0647-add-consumeFuel-to-FurnaceBurnEvent.patch => 0648-add-consumeFuel-to-FurnaceBurnEvent.patch} (100%) rename patches/server/{0648-add-get-set-drop-chance-to-EntityEquipment.patch => 0649-add-get-set-drop-chance-to-EntityEquipment.patch} (100%) rename patches/server/{0649-fix-PigZombieAngerEvent-cancellation.patch => 0650-fix-PigZombieAngerEvent-cancellation.patch} (100%) rename patches/server/{0650-Fix-checkReach-check-for-Shulker-boxes.patch => 0651-Fix-checkReach-check-for-Shulker-boxes.patch} (100%) rename patches/server/{0651-fix-PlayerItemHeldEvent-firing-twice.patch => 0652-fix-PlayerItemHeldEvent-firing-twice.patch} (100%) rename patches/server/{0652-Added-PlayerDeepSleepEvent.patch => 0653-Added-PlayerDeepSleepEvent.patch} (100%) rename patches/server/{0653-More-World-API.patch => 0654-More-World-API.patch} (100%) rename patches/server/{0654-Added-PlayerBedFailEnterEvent.patch => 0655-Added-PlayerBedFailEnterEvent.patch} (100%) rename patches/server/{0655-Implement-methods-to-convert-between-Component-and-B.patch => 0656-Implement-methods-to-convert-between-Component-and-B.patch} (100%) rename patches/server/{0656-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch => 0657-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch} (100%) rename patches/server/{0657-Introduce-beacon-activation-deactivation-events.patch => 0658-Introduce-beacon-activation-deactivation-events.patch} (100%) rename patches/server/{0658-add-RespawnFlags-to-PlayerRespawnEvent.patch => 0659-add-RespawnFlags-to-PlayerRespawnEvent.patch} (100%) rename patches/server/{0659-Add-Channel-initialization-listeners.patch => 0660-Add-Channel-initialization-listeners.patch} (100%) rename patches/server/{0660-Send-empty-commands-if-tab-completion-is-disabled.patch => 0661-Send-empty-commands-if-tab-completion-is-disabled.patch} (100%) rename patches/server/{0661-Add-more-WanderingTrader-API.patch => 0662-Add-more-WanderingTrader-API.patch} (100%) rename patches/server/{0662-Add-EntityBlockStorage-clearEntities.patch => 0663-Add-EntityBlockStorage-clearEntities.patch} (100%) rename patches/server/{0663-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch => 0664-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch} (100%) rename patches/server/{0664-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch => 0665-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch} (100%) rename patches/server/{0665-Inventory-close.patch => 0666-Inventory-close.patch} (100%) rename patches/server/{0666-call-PortalCreateEvent-players-and-end-platform.patch => 0667-call-PortalCreateEvent-players-and-end-platform.patch} (100%) rename patches/server/{0667-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch => 0668-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch} (100%) rename patches/server/{0668-Fix-CraftPotionBrewer-cache.patch => 0669-Fix-CraftPotionBrewer-cache.patch} (100%) rename patches/server/{0669-Add-basic-Datapack-API.patch => 0670-Add-basic-Datapack-API.patch} (100%) rename patches/server/{0670-Add-environment-variable-to-disable-server-gui.patch => 0671-Add-environment-variable-to-disable-server-gui.patch} (100%) rename patches/server/{0671-additions-to-PlayerGameModeChangeEvent.patch => 0672-additions-to-PlayerGameModeChangeEvent.patch} (100%) rename patches/server/{0672-ItemStack-repair-check-API.patch => 0673-ItemStack-repair-check-API.patch} (100%) rename patches/server/{0673-More-Enchantment-API.patch => 0674-More-Enchantment-API.patch} (100%) rename patches/server/{0674-Add-command-line-option-to-load-extra-plugin-jars-no.patch => 0675-Add-command-line-option-to-load-extra-plugin-jars-no.patch} (100%) rename patches/server/{0675-Fix-and-optimise-world-force-upgrading.patch => 0676-Fix-and-optimise-world-force-upgrading.patch} (99%) rename patches/server/{0676-Add-Mob-lookAt-API.patch => 0677-Add-Mob-lookAt-API.patch} (100%) rename patches/server/{0677-Add-Unix-domain-socket-support.patch => 0678-Add-Unix-domain-socket-support.patch} (100%) rename patches/server/{0678-Add-EntityInsideBlockEvent.patch => 0679-Add-EntityInsideBlockEvent.patch} (100%) rename patches/server/{0679-Attributes-API-for-item-defaults.patch => 0680-Attributes-API-for-item-defaults.patch} (100%) rename patches/server/{0680-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch => 0681-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch} (100%) rename patches/server/{0681-Add-cause-to-Weather-ThunderChangeEvents.patch => 0682-Add-cause-to-Weather-ThunderChangeEvents.patch} (100%) rename patches/server/{0682-More-Lidded-Block-API.patch => 0683-More-Lidded-Block-API.patch} (100%) rename patches/server/{0683-Limit-item-frame-cursors-on-maps.patch => 0684-Limit-item-frame-cursors-on-maps.patch} (100%) rename patches/server/{0684-Add-PufferFishStateChangeEvent.patch => 0685-Add-PufferFishStateChangeEvent.patch} (100%) rename patches/server/{0685-Add-PlayerKickEvent-causes.patch => 0686-Add-PlayerKickEvent-causes.patch} (100%) rename patches/server/{0686-Fix-PlayerBucketEmptyEvent-result-itemstack.patch => 0687-Fix-PlayerBucketEmptyEvent-result-itemstack.patch} (100%) rename patches/server/{0687-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch => 0688-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch} (100%) rename patches/server/{0688-Add-option-to-fix-items-merging-through-walls.patch => 0689-Add-option-to-fix-items-merging-through-walls.patch} (100%) rename patches/server/{0689-Add-BellRevealRaiderEvent.patch => 0690-Add-BellRevealRaiderEvent.patch} (100%) rename patches/server/{0690-Fix-invulnerable-end-crystals.patch => 0691-Fix-invulnerable-end-crystals.patch} (100%) rename patches/server/{0691-Add-ElderGuardianAppearanceEvent.patch => 0692-Add-ElderGuardianAppearanceEvent.patch} (100%) rename patches/server/{0692-Reset-villager-inventory-on-cancelled-pickup-event.patch => 0693-Reset-villager-inventory-on-cancelled-pickup-event.patch} (100%) rename patches/server/{0693-Fix-dangerous-end-portal-logic.patch => 0694-Fix-dangerous-end-portal-logic.patch} (100%) rename patches/server/{0694-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch => 0695-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch} (100%) rename patches/server/{0695-Make-item-validations-configurable.patch => 0696-Make-item-validations-configurable.patch} (100%) rename patches/server/{0696-Add-more-line-of-sight-methods.patch => 0697-Add-more-line-of-sight-methods.patch} (100%) rename patches/server/{0697-add-per-world-spawn-limits.patch => 0698-add-per-world-spawn-limits.patch} (100%) rename patches/server/{0698-Fix-PotionSplashEvent-for-water-splash-potions.patch => 0699-Fix-PotionSplashEvent-for-water-splash-potions.patch} (100%) rename patches/server/{0699-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch => 0700-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch} (100%) diff --git a/patches/removed/1.17/0369-Avoid-hopper-searches-if-there-are-no-items.patch b/patches/removed/1.17/0369-Avoid-hopper-searches-if-there-are-no-items.patch deleted file mode 100644 index f4d9a785b8..0000000000 --- a/patches/removed/1.17/0369-Avoid-hopper-searches-if-there-are-no-items.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CullanP -Date: Thu, 3 Mar 2016 02:13:38 -0600 -Subject: [PATCH] Avoid hopper searches if there are no items -1.17: figure this out after methods got moved -Hoppers searching for items and minecarts is the most expensive part of hopper ticking. -We keep track of the number of minecarts and items in a chunk. -If there are no items in the chunk, we skip searching for items. -If there are no minecarts in the chunk, we skip searching for them. - -Usually hoppers aren't near items, so we can skip most item searches. -And since minecart hoppers are used _very_ rarely near we can avoid alot of searching there. - -Combined, this adds up a lot. - -diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index d3640975c5a33b4911428760691215905b987385..e7facd849e3511c64b4ae44b34382f4a4985f2a4 100644 ---- a/src/main/java/net/minecraft/world/entity/EntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -16,6 +16,7 @@ public final class EntitySelector { - public static final Predicate ENTITY_NOT_BEING_RIDDEN = (entity) -> { - return entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); - }; -+ public static final Predicate isInventory() { return CONTAINER_ENTITY_SELECTOR; } // Paper - OBFHELPER - public static final Predicate CONTAINER_ENTITY_SELECTOR = (entity) -> { - return entity instanceof Container && entity.isAlive(); - }; -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 85861545ec4620a6cfd06876dad091637bd29b0b..4fef3abe4b416cbebe1b456468b5c3e162de18f1 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -31,10 +31,13 @@ import net.minecraft.server.level.ChunkHolder; - import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.Mth; -+import net.minecraft.world.Container; - import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntitySelector; - import net.minecraft.world.entity.EntityType; - import net.minecraft.world.entity.boss.EnderDragonPart; - import net.minecraft.world.entity.boss.enderdragon.EnderDragon; -+import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.ChunkTickList; - import net.minecraft.world.level.EmptyTickList; -@@ -122,6 +125,10 @@ public class LevelChunk implements ChunkAccess { - return removed; - } - } -+ // Track the number of minecarts and items -+ // Keep this synced with entitySlices.add() and entitySlices.remove() -+ private final int[] itemCounts = new int[16]; -+ private final int[] inventoryEntityCounts = new int[16]; - // Paper end - - public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes, UpgradeData upgradeData, TickList blockTickScheduler, TickList fluidTickScheduler, long inhabitedTime, @Nullable LevelChunkSection[] sections, @Nullable Consumer loadToWorldConsumer) { -@@ -581,6 +588,13 @@ public class LevelChunk implements ChunkAccess { - entity.zChunk = this.chunkPos.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ // Paper start -+ if (entity instanceof ItemEntity) { -+ itemCounts[k]++; -+ } else if (entity instanceof Container) { -+ inventoryEntityCounts[k]++; -+ } -+ // Paper end - entity.entitySlice = this.entitySlices[k]; // Paper - this.markUnsaved(); // Paper - } -@@ -614,6 +628,11 @@ public class LevelChunk implements ChunkAccess { - if (!this.entitySlices[section].remove(entity)) { - return; - } -+ if (entity instanceof ItemEntity) { -+ itemCounts[section]--; -+ } else if (entity instanceof Container) { -+ inventoryEntityCounts[section]--; -+ } - entityCounts.decrement(entity.getMinecraftKeyString()); - this.markUnsaved(); // Paper - // Paper end -@@ -899,6 +918,14 @@ public class LevelChunk implements ChunkAccess { - for (int k = i; k <= j; ++k) { - Iterator iterator = this.entitySlices[k].iterator(); // Spigot - -+ // Paper start - Don't search for inventories if we have none, and that is all we want -+ /* -+ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` -+ * -+ * Make sure the inventory selector stays in sync. -+ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -+ */ -+ if (predicate == EntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; - while (iterator.hasNext()) { - T entity = (T) iterator.next(); // CraftBukkit - decompile error - if (entity.shouldBeRemoved) continue; // Paper -@@ -919,9 +946,29 @@ public class LevelChunk implements ChunkAccess { - i = Mth.clamp(i, 0, this.entitySlices.length - 1); - j = Mth.clamp(j, 0, this.entitySlices.length - 1); - -+ // Paper start -+ int[] counts; -+ if (ItemEntity.class.isAssignableFrom(entityClass)) { -+ counts = itemCounts; -+ } else if (Container.class.isAssignableFrom(entityClass)) { -+ counts = inventoryEntityCounts; -+ } else { -+ counts = null; -+ } -+ // Paper end - for (int k = i; k <= j; ++k) { -+ if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for - Iterator iterator = this.entitySlices[k].iterator(); // Spigot - -+ // Paper start - Don't search for inventories if we have none, and that is all we want -+ /* -+ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` -+ * -+ * Make sure the inventory selector stays in sync. -+ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -+ */ -+ if (predicate == EntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; -+ // Paper end - while (iterator.hasNext()) { - T t0 = (T) iterator.next(); // CraftBukkit - decompile error - if (t0.shouldBeRemoved) continue; // Paper diff --git a/patches/server/0369-Avoid-hopper-searches-if-there-are-no-items.patch b/patches/server/0369-Avoid-hopper-searches-if-there-are-no-items.patch new file mode 100644 index 0000000000..f2b4f51f8e --- /dev/null +++ b/patches/server/0369-Avoid-hopper-searches-if-there-are-no-items.patch @@ -0,0 +1,142 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: CullanP +Date: Thu, 3 Mar 2016 02:13:38 -0600 +Subject: [PATCH] Avoid hopper searches if there are no items + +Hoppers searching for items and minecarts is the most expensive part of hopper ticking. +We keep track of the number of minecarts and items in a chunk. +If there are no items in the chunk, we skip searching for items. +If there are no minecarts in the chunk, we skip searching for them. + +Usually hoppers aren't near items, so we can skip most item searches. +And since minecart hoppers are used _very_ rarely near we can avoid alot of searching there. + +Combined, this adds up a lot. + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 507a70521a97c463d6fd22b788c39e9f458971c3..1dc1f7a5319e067b5f56c2fdadf04547ae1bc9ea 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -984,7 +984,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + } + +- }); ++ }, predicate == net.minecraft.world.entity.EntitySelector.CONTAINER_ENTITY_SELECTOR); // Paper + return list; + } + +diff --git a/src/main/java/net/minecraft/world/level/entity/EntitySection.java b/src/main/java/net/minecraft/world/level/entity/EntitySection.java +index 9a7b2602c2549dd03ad097c4a922a10a5e869645..5342eafe25614d262eeb39fa517a242e27d998f6 100644 +--- a/src/main/java/net/minecraft/world/level/entity/EntitySection.java ++++ b/src/main/java/net/minecraft/world/level/entity/EntitySection.java +@@ -12,6 +12,10 @@ public class EntitySection { + protected static final Logger LOGGER = LogManager.getLogger(); + private final ClassInstanceMultiMap storage; + private Visibility chunkStatus; ++ // Paper start - track number of items and minecarts ++ public int itemCount; ++ public int inventoryEntityCount; ++ // Paper end + + public EntitySection(Class entityClass, Visibility status) { + this.chunkStatus = status; +@@ -19,10 +23,24 @@ public class EntitySection { + } + + public void add(T obj) { ++ // Paper start ++ if (obj instanceof net.minecraft.world.entity.item.ItemEntity) { ++ this.itemCount++; ++ } else if (obj instanceof net.minecraft.world.Container) { ++ this.inventoryEntityCount++; ++ } ++ // Paper end + this.storage.add(obj); + } + + public boolean remove(T obj) { ++ // Paper start ++ if (obj instanceof net.minecraft.world.entity.item.ItemEntity) { ++ this.itemCount--; ++ } else if (obj instanceof net.minecraft.world.Container) { ++ this.inventoryEntityCount--; ++ } ++ // Paper end + return this.storage.remove(obj); + } + +@@ -39,7 +57,7 @@ public class EntitySection { + for(T object : this.storage.find(type.getBaseClass())) { + U object2 = (U)type.tryCast(object); + if (object2 != null && filter.test(object2)) { +- action.accept((T)object2); ++ action.accept(object2); // Paper - decompile fix + } + } + +diff --git a/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java b/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java +index 067138e3983959347d19754e668bb7a1f702bad0..24552500307c42f9f3dc5c4d9ba73a84a787423a 100644 +--- a/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java +@@ -105,7 +105,7 @@ public class EntitySectionStorage { + + public LongSet getAllChunksWithExistingSections() { + LongSet longSet = new LongOpenHashSet(); +- this.sections.keySet().forEach((sectionPos) -> { ++ this.sections.keySet().forEach((java.util.function.LongConsumer) (sectionPos) -> { // Paper - decompile fix + longSet.add(getChunkKeyFromSectionKey(sectionPos)); + }); + return longSet; +@@ -118,13 +118,20 @@ public class EntitySectionStorage { + } + + public void getEntities(AABB box, Consumer action) { ++ // Paper start ++ this.getEntities(box, action, false); ++ } ++ public void getEntities(AABB box, Consumer action, boolean isContainerSearch) { ++ // Paper end + this.forEachAccessibleSection(box, (entitySection) -> { ++ if (isContainerSearch && entitySection.inventoryEntityCount <= 0) return; // Paper + entitySection.getEntities(createBoundingBoxCheck(box), action); + }); + } + + public void getEntities(EntityTypeTest filter, AABB box, Consumer action) { + this.forEachAccessibleSection(box, (entitySection) -> { ++ if (filter.getBaseClass() == net.minecraft.world.entity.item.ItemEntity.class && entitySection.itemCount <= 0) return; // Paper + entitySection.getEntities(filter, createBoundingBoxCheck(box), action); + }); + } +diff --git a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java +index 9723a0ad61548c8c6c4c5ef20a150d5b17d80afd..da1ad0b2679e392ed81b50c15f012c63cb5c939e 100644 +--- a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java +@@ -17,6 +17,7 @@ public interface LevelEntityGetter { + void get(EntityTypeTest filter, Consumer action); + + void get(AABB box, Consumer action); ++ void get(AABB box, Consumer action, boolean isContainerSearch); // Paper + + void get(EntityTypeTest filter, AABB box, Consumer action); + } +diff --git a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java +index d5129c12c79eb6fe6b7e5f8eed4d24226423f5fd..3b13f6ea36a3bfecabe09221eb5c48dddab119db 100644 +--- a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java ++++ b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java +@@ -38,7 +38,13 @@ public class LevelEntityGetterAdapter implements LevelEn + + @Override + public void get(AABB box, Consumer action) { +- this.sectionStorage.getEntities(box, action); ++ // Paper start ++ this.get(box, action, false); ++ } ++ @Override ++ public void get(AABB box, Consumer action, boolean isContainerSearch) { ++ this.sectionStorage.getEntities(box, action, isContainerSearch); ++ // Paper end + } + + @Override diff --git a/patches/server/0369-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/0370-Bees-get-gravity-in-void.-Fixes-MC-167279.patch similarity index 100% rename from patches/server/0369-Bees-get-gravity-in-void.-Fixes-MC-167279.patch rename to patches/server/0370-Bees-get-gravity-in-void.-Fixes-MC-167279.patch diff --git a/patches/server/0370-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server/0371-Optimise-getChunkAt-calls-for-loaded-chunks.patch similarity index 100% rename from patches/server/0370-Optimise-getChunkAt-calls-for-loaded-chunks.patch rename to patches/server/0371-Optimise-getChunkAt-calls-for-loaded-chunks.patch diff --git a/patches/server/0371-Allow-overriding-the-java-version-check.patch b/patches/server/0372-Allow-overriding-the-java-version-check.patch similarity index 100% rename from patches/server/0371-Allow-overriding-the-java-version-check.patch rename to patches/server/0372-Allow-overriding-the-java-version-check.patch diff --git a/patches/server/0372-Add-ThrownEggHatchEvent.patch b/patches/server/0373-Add-ThrownEggHatchEvent.patch similarity index 100% rename from patches/server/0372-Add-ThrownEggHatchEvent.patch rename to patches/server/0373-Add-ThrownEggHatchEvent.patch diff --git a/patches/server/0373-Optimise-random-block-ticking.patch b/patches/server/0374-Optimise-random-block-ticking.patch similarity index 99% rename from patches/server/0373-Optimise-random-block-ticking.patch rename to patches/server/0374-Optimise-random-block-ticking.patch index d8b3340523..f5938a4275 100644 --- a/patches/server/0373-Optimise-random-block-ticking.patch +++ b/patches/server/0374-Optimise-random-block-ticking.patch @@ -266,7 +266,7 @@ index e638d982b4bd1d261a7282cad6dab98ad0b55213..e305173fd1652a8b88ae8a9b94d0fae0 public BlockPos getHomePos() { // Paper - public diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 507a70521a97c463d6fd22b788c39e9f458971c3..ea455e8aa7db5e9c397875e1fc8716cd52044c05 100644 +index 1dc1f7a5319e067b5f56c2fdadf04547ae1bc9ea..9d5dcaabe43ee36259b24063b4c74daddc7df773 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -1300,10 +1300,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { diff --git a/patches/server/0374-Entity-Jump-API.patch b/patches/server/0375-Entity-Jump-API.patch similarity index 100% rename from patches/server/0374-Entity-Jump-API.patch rename to patches/server/0375-Entity-Jump-API.patch diff --git a/patches/server/0375-Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/0376-Add-option-to-nerf-pigmen-from-nether-portals.patch similarity index 100% rename from patches/server/0375-Add-option-to-nerf-pigmen-from-nether-portals.patch rename to patches/server/0376-Add-option-to-nerf-pigmen-from-nether-portals.patch diff --git a/patches/server/0376-Make-the-GUI-graph-fancier.patch b/patches/server/0377-Make-the-GUI-graph-fancier.patch similarity index 100% rename from patches/server/0376-Make-the-GUI-graph-fancier.patch rename to patches/server/0377-Make-the-GUI-graph-fancier.patch diff --git a/patches/server/0377-add-hand-to-BlockMultiPlaceEvent.patch b/patches/server/0378-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from patches/server/0377-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/server/0378-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/patches/server/0378-Prevent-teleporting-dead-entities.patch b/patches/server/0379-Prevent-teleporting-dead-entities.patch similarity index 100% rename from patches/server/0378-Prevent-teleporting-dead-entities.patch rename to patches/server/0379-Prevent-teleporting-dead-entities.patch diff --git a/patches/server/0379-Validate-tripwire-hook-placement-before-update.patch b/patches/server/0380-Validate-tripwire-hook-placement-before-update.patch similarity index 100% rename from patches/server/0379-Validate-tripwire-hook-placement-before-update.patch rename to patches/server/0380-Validate-tripwire-hook-placement-before-update.patch diff --git a/patches/server/0380-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server/0381-Add-option-to-allow-iron-golems-to-spawn-in-air.patch similarity index 100% rename from patches/server/0380-Add-option-to-allow-iron-golems-to-spawn-in-air.patch rename to patches/server/0381-Add-option-to-allow-iron-golems-to-spawn-in-air.patch diff --git a/patches/server/0381-Configurable-chance-of-villager-zombie-infection.patch b/patches/server/0382-Configurable-chance-of-villager-zombie-infection.patch similarity index 100% rename from patches/server/0381-Configurable-chance-of-villager-zombie-infection.patch rename to patches/server/0382-Configurable-chance-of-villager-zombie-infection.patch diff --git a/patches/server/0382-Optimise-Chunk-getFluid.patch b/patches/server/0383-Optimise-Chunk-getFluid.patch similarity index 100% rename from patches/server/0382-Optimise-Chunk-getFluid.patch rename to patches/server/0383-Optimise-Chunk-getFluid.patch diff --git a/patches/server/0383-Optimise-TickListServer-by-rewriting-it.patch b/patches/server/0384-Optimise-TickListServer-by-rewriting-it.patch similarity index 100% rename from patches/server/0383-Optimise-TickListServer-by-rewriting-it.patch rename to patches/server/0384-Optimise-TickListServer-by-rewriting-it.patch diff --git a/patches/server/0384-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/0385-Pillager-patrol-spawn-settings-and-per-player-option.patch similarity index 100% rename from patches/server/0384-Pillager-patrol-spawn-settings-and-per-player-option.patch rename to patches/server/0385-Pillager-patrol-spawn-settings-and-per-player-option.patch diff --git a/patches/server/0385-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server/0386-Remote-Connections-shouldn-t-hold-up-shutdown.patch similarity index 100% rename from patches/server/0385-Remote-Connections-shouldn-t-hold-up-shutdown.patch rename to patches/server/0386-Remote-Connections-shouldn-t-hold-up-shutdown.patch diff --git a/patches/server/0386-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/0387-Do-not-allow-bees-to-load-chunks-for-beehives.patch similarity index 100% rename from patches/server/0386-Do-not-allow-bees-to-load-chunks-for-beehives.patch rename to patches/server/0387-Do-not-allow-bees-to-load-chunks-for-beehives.patch diff --git a/patches/server/0387-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server/0388-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch similarity index 100% rename from patches/server/0387-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch rename to patches/server/0388-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch diff --git a/patches/server/0388-Optimize-Collision-to-not-load-chunks.patch b/patches/server/0389-Optimize-Collision-to-not-load-chunks.patch similarity index 100% rename from patches/server/0388-Optimize-Collision-to-not-load-chunks.patch rename to patches/server/0389-Optimize-Collision-to-not-load-chunks.patch diff --git a/patches/server/0389-Don-t-tick-dead-players.patch b/patches/server/0390-Don-t-tick-dead-players.patch similarity index 100% rename from patches/server/0389-Don-t-tick-dead-players.patch rename to patches/server/0390-Don-t-tick-dead-players.patch diff --git a/patches/server/0390-Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server/0391-Dead-Player-s-shouldn-t-be-able-to-move.patch similarity index 100% rename from patches/server/0390-Dead-Player-s-shouldn-t-be-able-to-move.patch rename to patches/server/0391-Dead-Player-s-shouldn-t-be-able-to-move.patch diff --git a/patches/server/0391-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/0392-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch similarity index 100% rename from patches/server/0391-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch rename to patches/server/0392-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch diff --git a/patches/server/0392-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/patches/server/0393-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch similarity index 100% rename from patches/server/0392-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch rename to patches/server/0393-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch diff --git a/patches/server/0393-Don-t-move-existing-players-to-world-spawn.patch b/patches/server/0394-Don-t-move-existing-players-to-world-spawn.patch similarity index 100% rename from patches/server/0393-Don-t-move-existing-players-to-world-spawn.patch rename to patches/server/0394-Don-t-move-existing-players-to-world-spawn.patch diff --git a/patches/server/0394-Add-tick-times-API-and-mspt-command.patch b/patches/server/0395-Add-tick-times-API-and-mspt-command.patch similarity index 100% rename from patches/server/0394-Add-tick-times-API-and-mspt-command.patch rename to patches/server/0395-Add-tick-times-API-and-mspt-command.patch diff --git a/patches/server/0395-Expose-MinecraftServer-isRunning.patch b/patches/server/0396-Expose-MinecraftServer-isRunning.patch similarity index 100% rename from patches/server/0395-Expose-MinecraftServer-isRunning.patch rename to patches/server/0396-Expose-MinecraftServer-isRunning.patch diff --git a/patches/server/0396-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/0397-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 100% rename from patches/server/0396-Add-Raw-Byte-ItemStack-Serialization.patch rename to patches/server/0397-Add-Raw-Byte-ItemStack-Serialization.patch diff --git a/patches/server/0397-Remove-streams-from-Mob-AI-System.patch b/patches/server/0398-Remove-streams-from-Mob-AI-System.patch similarity index 100% rename from patches/server/0397-Remove-streams-from-Mob-AI-System.patch rename to patches/server/0398-Remove-streams-from-Mob-AI-System.patch diff --git a/patches/server/0398-Async-command-map-building.patch b/patches/server/0399-Async-command-map-building.patch similarity index 100% rename from patches/server/0398-Async-command-map-building.patch rename to patches/server/0399-Async-command-map-building.patch diff --git a/patches/server/0399-Improved-Watchdog-Support.patch b/patches/server/0400-Improved-Watchdog-Support.patch similarity index 99% rename from patches/server/0399-Improved-Watchdog-Support.patch rename to patches/server/0400-Improved-Watchdog-Support.patch index 77f803c039..4f5188cdf9 100644 --- a/patches/server/0399-Improved-Watchdog-Support.patch +++ b/patches/server/0400-Improved-Watchdog-Support.patch @@ -299,7 +299,7 @@ index 0ef3c4982df88a7991a56d983ac733daa8adc507..cdd797c6fc7507a0e6376f7d9c521be8 } diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index ea455e8aa7db5e9c397875e1fc8716cd52044c05..6aeb3ff79f08ade7ddd0d328d1a01514a91f671a 100644 +index 9d5dcaabe43ee36259b24063b4c74daddc7df773..06f2f76636804cd5f997bbe1558a104bc24aa84a 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -837,6 +837,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { diff --git a/patches/server/0400-Optimize-Pathfinding.patch b/patches/server/0401-Optimize-Pathfinding.patch similarity index 100% rename from patches/server/0400-Optimize-Pathfinding.patch rename to patches/server/0401-Optimize-Pathfinding.patch diff --git a/patches/server/0401-Reduce-Either-Optional-allocation.patch b/patches/server/0402-Reduce-Either-Optional-allocation.patch similarity index 100% rename from patches/server/0401-Reduce-Either-Optional-allocation.patch rename to patches/server/0402-Reduce-Either-Optional-allocation.patch diff --git a/patches/server/0402-Remove-streams-from-PairedQueue.patch b/patches/server/0403-Remove-streams-from-PairedQueue.patch similarity index 100% rename from patches/server/0402-Remove-streams-from-PairedQueue.patch rename to patches/server/0403-Remove-streams-from-PairedQueue.patch diff --git a/patches/server/0403-Reduce-memory-footprint-of-NBTTagCompound.patch b/patches/server/0404-Reduce-memory-footprint-of-NBTTagCompound.patch similarity index 100% rename from patches/server/0403-Reduce-memory-footprint-of-NBTTagCompound.patch rename to patches/server/0404-Reduce-memory-footprint-of-NBTTagCompound.patch diff --git a/patches/server/0404-Prevent-opening-inventories-when-frozen.patch b/patches/server/0405-Prevent-opening-inventories-when-frozen.patch similarity index 100% rename from patches/server/0404-Prevent-opening-inventories-when-frozen.patch rename to patches/server/0405-Prevent-opening-inventories-when-frozen.patch diff --git a/patches/server/0405-Optimise-ArraySetSorted-removeIf.patch b/patches/server/0406-Optimise-ArraySetSorted-removeIf.patch similarity index 100% rename from patches/server/0405-Optimise-ArraySetSorted-removeIf.patch rename to patches/server/0406-Optimise-ArraySetSorted-removeIf.patch diff --git a/patches/server/0406-Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server/0407-Don-t-run-entity-collision-code-if-not-needed.patch similarity index 100% rename from patches/server/0406-Don-t-run-entity-collision-code-if-not-needed.patch rename to patches/server/0407-Don-t-run-entity-collision-code-if-not-needed.patch diff --git a/patches/server/0407-Restrict-vanilla-teleport-command-to-valid-locations.patch b/patches/server/0408-Restrict-vanilla-teleport-command-to-valid-locations.patch similarity index 100% rename from patches/server/0407-Restrict-vanilla-teleport-command-to-valid-locations.patch rename to patches/server/0408-Restrict-vanilla-teleport-command-to-valid-locations.patch diff --git a/patches/server/0408-Implement-Player-Client-Options-API.patch b/patches/server/0409-Implement-Player-Client-Options-API.patch similarity index 100% rename from patches/server/0408-Implement-Player-Client-Options-API.patch rename to patches/server/0409-Implement-Player-Client-Options-API.patch diff --git a/patches/server/0409-Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server/0410-Fix-Chunk-Post-Processing-deadlock-risk.patch similarity index 100% rename from patches/server/0409-Fix-Chunk-Post-Processing-deadlock-risk.patch rename to patches/server/0410-Fix-Chunk-Post-Processing-deadlock-risk.patch diff --git a/patches/server/0410-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/patches/server/0411-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch similarity index 100% rename from patches/server/0410-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch rename to patches/server/0411-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch diff --git a/patches/server/0411-Broadcast-join-message-to-console.patch b/patches/server/0412-Broadcast-join-message-to-console.patch similarity index 100% rename from patches/server/0411-Broadcast-join-message-to-console.patch rename to patches/server/0412-Broadcast-join-message-to-console.patch diff --git a/patches/server/0412-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/patches/server/0413-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch similarity index 100% rename from patches/server/0412-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch rename to patches/server/0413-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch diff --git a/patches/server/0413-Load-Chunks-for-Login-Asynchronously.patch b/patches/server/0414-Load-Chunks-for-Login-Asynchronously.patch similarity index 100% rename from patches/server/0413-Load-Chunks-for-Login-Asynchronously.patch rename to patches/server/0414-Load-Chunks-for-Login-Asynchronously.patch diff --git a/patches/server/0414-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/patches/server/0415-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch similarity index 100% rename from patches/server/0414-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch rename to patches/server/0415-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch diff --git a/patches/server/0415-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server/0416-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from patches/server/0415-Add-PlayerAttackEntityCooldownResetEvent.patch rename to patches/server/0416-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/patches/server/0416-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/patches/server/0417-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch similarity index 100% rename from patches/server/0416-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch rename to patches/server/0417-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch diff --git a/patches/server/0417-Don-t-fire-BlockFade-on-worldgen-threads.patch b/patches/server/0418-Don-t-fire-BlockFade-on-worldgen-threads.patch similarity index 100% rename from patches/server/0417-Don-t-fire-BlockFade-on-worldgen-threads.patch rename to patches/server/0418-Don-t-fire-BlockFade-on-worldgen-threads.patch diff --git a/patches/server/0418-Add-phantom-creative-and-insomniac-controls.patch b/patches/server/0419-Add-phantom-creative-and-insomniac-controls.patch similarity index 100% rename from patches/server/0418-Add-phantom-creative-and-insomniac-controls.patch rename to patches/server/0419-Add-phantom-creative-and-insomniac-controls.patch diff --git a/patches/server/0419-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/patches/server/0420-Fix-numerous-item-duplication-issues-and-teleport-is.patch similarity index 100% rename from patches/server/0419-Fix-numerous-item-duplication-issues-and-teleport-is.patch rename to patches/server/0420-Fix-numerous-item-duplication-issues-and-teleport-is.patch diff --git a/patches/server/0420-Implement-Brigadier-Mojang-API.patch b/patches/server/0421-Implement-Brigadier-Mojang-API.patch similarity index 100% rename from patches/server/0420-Implement-Brigadier-Mojang-API.patch rename to patches/server/0421-Implement-Brigadier-Mojang-API.patch diff --git a/patches/server/0421-Villager-Restocks-API.patch b/patches/server/0422-Villager-Restocks-API.patch similarity index 100% rename from patches/server/0421-Villager-Restocks-API.patch rename to patches/server/0422-Villager-Restocks-API.patch diff --git a/patches/server/0422-Validate-PickItem-Packet-and-kick-for-invalid.patch b/patches/server/0423-Validate-PickItem-Packet-and-kick-for-invalid.patch similarity index 100% rename from patches/server/0422-Validate-PickItem-Packet-and-kick-for-invalid.patch rename to patches/server/0423-Validate-PickItem-Packet-and-kick-for-invalid.patch diff --git a/patches/server/0423-Expose-game-version.patch b/patches/server/0424-Expose-game-version.patch similarity index 100% rename from patches/server/0423-Expose-game-version.patch rename to patches/server/0424-Expose-game-version.patch diff --git a/patches/server/0424-Optimize-Voxel-Shape-Merging.patch b/patches/server/0425-Optimize-Voxel-Shape-Merging.patch similarity index 100% rename from patches/server/0424-Optimize-Voxel-Shape-Merging.patch rename to patches/server/0425-Optimize-Voxel-Shape-Merging.patch diff --git a/patches/server/0425-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/patches/server/0426-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch similarity index 100% rename from patches/server/0425-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch rename to patches/server/0426-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch diff --git a/patches/server/0426-Implement-Mob-Goal-API.patch b/patches/server/0427-Implement-Mob-Goal-API.patch similarity index 100% rename from patches/server/0426-Implement-Mob-Goal-API.patch rename to patches/server/0427-Implement-Mob-Goal-API.patch diff --git a/patches/server/0427-Use-distance-map-to-optimise-entity-tracker.patch b/patches/server/0428-Use-distance-map-to-optimise-entity-tracker.patch similarity index 100% rename from patches/server/0427-Use-distance-map-to-optimise-entity-tracker.patch rename to patches/server/0428-Use-distance-map-to-optimise-entity-tracker.patch diff --git a/patches/server/0428-Optimize-isOutsideRange-to-use-distance-maps.patch b/patches/server/0429-Optimize-isOutsideRange-to-use-distance-maps.patch similarity index 100% rename from patches/server/0428-Optimize-isOutsideRange-to-use-distance-maps.patch rename to patches/server/0429-Optimize-isOutsideRange-to-use-distance-maps.patch diff --git a/patches/server/0429-Add-villager-reputation-API.patch b/patches/server/0430-Add-villager-reputation-API.patch similarity index 100% rename from patches/server/0429-Add-villager-reputation-API.patch rename to patches/server/0430-Add-villager-reputation-API.patch diff --git a/patches/server/0430-Option-for-maximum-exp-value-when-merging-orbs.patch b/patches/server/0431-Option-for-maximum-exp-value-when-merging-orbs.patch similarity index 100% rename from patches/server/0430-Option-for-maximum-exp-value-when-merging-orbs.patch rename to patches/server/0431-Option-for-maximum-exp-value-when-merging-orbs.patch diff --git a/patches/server/0431-ExperienceOrbMergeEvent.patch b/patches/server/0432-ExperienceOrbMergeEvent.patch similarity index 100% rename from patches/server/0431-ExperienceOrbMergeEvent.patch rename to patches/server/0432-ExperienceOrbMergeEvent.patch diff --git a/patches/server/0432-Fix-PotionEffect-ignores-icon-flag.patch b/patches/server/0433-Fix-PotionEffect-ignores-icon-flag.patch similarity index 100% rename from patches/server/0432-Fix-PotionEffect-ignores-icon-flag.patch rename to patches/server/0433-Fix-PotionEffect-ignores-icon-flag.patch diff --git a/patches/server/0433-Optimize-brigadier-child-sorting-performance.patch b/patches/server/0434-Optimize-brigadier-child-sorting-performance.patch similarity index 100% rename from patches/server/0433-Optimize-brigadier-child-sorting-performance.patch rename to patches/server/0434-Optimize-brigadier-child-sorting-performance.patch diff --git a/patches/server/0434-Potential-bed-API.patch b/patches/server/0435-Potential-bed-API.patch similarity index 100% rename from patches/server/0434-Potential-bed-API.patch rename to patches/server/0435-Potential-bed-API.patch diff --git a/patches/server/0435-Wait-for-Async-Tasks-during-shutdown.patch b/patches/server/0436-Wait-for-Async-Tasks-during-shutdown.patch similarity index 100% rename from patches/server/0435-Wait-for-Async-Tasks-during-shutdown.patch rename to patches/server/0436-Wait-for-Async-Tasks-during-shutdown.patch diff --git a/patches/server/0436-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/patches/server/0437-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch similarity index 100% rename from patches/server/0436-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch rename to patches/server/0437-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch diff --git a/patches/server/0437-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server/0438-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch similarity index 99% rename from patches/server/0437-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch rename to patches/server/0438-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch index 2c13e4ac2d..6fa1cd4c6d 100644 --- a/patches/server/0437-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch +++ b/patches/server/0438-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch @@ -56,7 +56,7 @@ index cdf214fca3b0055efa56702470d9d2f890a8aead..a12af10e28f2d023ba6f916b5e7a5353 this.level.getProfiler().push("explosion_blocks"); diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 6aeb3ff79f08ade7ddd0d328d1a01514a91f671a..b969e7f2087aed5b1f97ce8593a25ada737daec9 100644 +index 06f2f76636804cd5f997bbe1558a104bc24aa84a..b92d930448757968cd6a178f4bcafae72c93044c 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -420,6 +420,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { diff --git a/patches/server/0438-Reduce-MutableInt-allocations-from-light-engine.patch b/patches/server/0439-Reduce-MutableInt-allocations-from-light-engine.patch similarity index 100% rename from patches/server/0438-Reduce-MutableInt-allocations-from-light-engine.patch rename to patches/server/0439-Reduce-MutableInt-allocations-from-light-engine.patch diff --git a/patches/server/0439-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/patches/server/0440-Reduce-allocation-of-Vec3D-by-entity-tracker.patch similarity index 100% rename from patches/server/0439-Reduce-allocation-of-Vec3D-by-entity-tracker.patch rename to patches/server/0440-Reduce-allocation-of-Vec3D-by-entity-tracker.patch diff --git a/patches/server/0440-Ensure-safe-gateway-teleport.patch b/patches/server/0441-Ensure-safe-gateway-teleport.patch similarity index 100% rename from patches/server/0440-Ensure-safe-gateway-teleport.patch rename to patches/server/0441-Ensure-safe-gateway-teleport.patch diff --git a/patches/server/0441-Add-option-for-console-having-all-permissions.patch b/patches/server/0442-Add-option-for-console-having-all-permissions.patch similarity index 100% rename from patches/server/0441-Add-option-for-console-having-all-permissions.patch rename to patches/server/0442-Add-option-for-console-having-all-permissions.patch diff --git a/patches/server/0442-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/patches/server/0443-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch similarity index 100% rename from patches/server/0442-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch rename to patches/server/0443-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch diff --git a/patches/server/0443-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/patches/server/0444-Optimize-sending-packets-to-nearby-locations-sounds-.patch similarity index 100% rename from patches/server/0443-Optimize-sending-packets-to-nearby-locations-sounds-.patch rename to patches/server/0444-Optimize-sending-packets-to-nearby-locations-sounds-.patch diff --git a/patches/server/0444-Fix-villager-trading-demand-MC-163962.patch b/patches/server/0445-Fix-villager-trading-demand-MC-163962.patch similarity index 100% rename from patches/server/0444-Fix-villager-trading-demand-MC-163962.patch rename to patches/server/0445-Fix-villager-trading-demand-MC-163962.patch diff --git a/patches/server/0445-Maps-shouldn-t-load-chunks.patch b/patches/server/0446-Maps-shouldn-t-load-chunks.patch similarity index 100% rename from patches/server/0445-Maps-shouldn-t-load-chunks.patch rename to patches/server/0446-Maps-shouldn-t-load-chunks.patch diff --git a/patches/server/0446-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/patches/server/0447-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch similarity index 100% rename from patches/server/0446-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch rename to patches/server/0447-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch diff --git a/patches/server/0447-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/patches/server/0448-Delay-Chunk-Unloads-based-on-Player-Movement.patch similarity index 100% rename from patches/server/0447-Delay-Chunk-Unloads-based-on-Player-Movement.patch rename to patches/server/0448-Delay-Chunk-Unloads-based-on-Player-Movement.patch diff --git a/patches/server/0448-Optimize-Bit-Operations-by-inlining.patch b/patches/server/0449-Optimize-Bit-Operations-by-inlining.patch similarity index 100% rename from patches/server/0448-Optimize-Bit-Operations-by-inlining.patch rename to patches/server/0449-Optimize-Bit-Operations-by-inlining.patch diff --git a/patches/server/0449-incremental-chunk-saving.patch b/patches/server/0450-incremental-chunk-saving.patch similarity index 100% rename from patches/server/0449-incremental-chunk-saving.patch rename to patches/server/0450-incremental-chunk-saving.patch diff --git a/patches/server/0450-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/patches/server/0451-Add-Plugin-Tickets-to-API-Chunk-Methods.patch similarity index 100% rename from patches/server/0450-Add-Plugin-Tickets-to-API-Chunk-Methods.patch rename to patches/server/0451-Add-Plugin-Tickets-to-API-Chunk-Methods.patch diff --git a/patches/server/0451-Fix-missing-chunks-due-to-integer-overflow.patch b/patches/server/0452-Fix-missing-chunks-due-to-integer-overflow.patch similarity index 100% rename from patches/server/0451-Fix-missing-chunks-due-to-integer-overflow.patch rename to patches/server/0452-Fix-missing-chunks-due-to-integer-overflow.patch diff --git a/patches/server/0452-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/patches/server/0453-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch similarity index 100% rename from patches/server/0452-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch rename to patches/server/0453-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch diff --git a/patches/server/0453-Fix-piston-physics-inconsistency-MC-188840.patch b/patches/server/0454-Fix-piston-physics-inconsistency-MC-188840.patch similarity index 100% rename from patches/server/0453-Fix-piston-physics-inconsistency-MC-188840.patch rename to patches/server/0454-Fix-piston-physics-inconsistency-MC-188840.patch diff --git a/patches/server/0454-Fix-sand-duping.patch b/patches/server/0455-Fix-sand-duping.patch similarity index 100% rename from patches/server/0454-Fix-sand-duping.patch rename to patches/server/0455-Fix-sand-duping.patch diff --git a/patches/server/0455-Prevent-position-desync-in-playerconnection-causing-.patch b/patches/server/0456-Prevent-position-desync-in-playerconnection-causing-.patch similarity index 100% rename from patches/server/0455-Prevent-position-desync-in-playerconnection-causing-.patch rename to patches/server/0456-Prevent-position-desync-in-playerconnection-causing-.patch diff --git a/patches/server/0456-Inventory-getHolder-method-without-block-snapshot.patch b/patches/server/0457-Inventory-getHolder-method-without-block-snapshot.patch similarity index 100% rename from patches/server/0456-Inventory-getHolder-method-without-block-snapshot.patch rename to patches/server/0457-Inventory-getHolder-method-without-block-snapshot.patch diff --git a/patches/server/0457-Expose-Arrow-getItemStack.patch b/patches/server/0458-Expose-Arrow-getItemStack.patch similarity index 100% rename from patches/server/0457-Expose-Arrow-getItemStack.patch rename to patches/server/0458-Expose-Arrow-getItemStack.patch diff --git a/patches/server/0458-Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/server/0459-Add-and-implement-PlayerRecipeBookClickEvent.patch similarity index 100% rename from patches/server/0458-Add-and-implement-PlayerRecipeBookClickEvent.patch rename to patches/server/0459-Add-and-implement-PlayerRecipeBookClickEvent.patch diff --git a/patches/server/0459-Hide-sync-chunk-writes-behind-flag.patch b/patches/server/0460-Hide-sync-chunk-writes-behind-flag.patch similarity index 100% rename from patches/server/0459-Hide-sync-chunk-writes-behind-flag.patch rename to patches/server/0460-Hide-sync-chunk-writes-behind-flag.patch diff --git a/patches/server/0460-Add-permission-for-command-blocks.patch b/patches/server/0461-Add-permission-for-command-blocks.patch similarity index 100% rename from patches/server/0460-Add-permission-for-command-blocks.patch rename to patches/server/0461-Add-permission-for-command-blocks.patch diff --git a/patches/server/0461-Ensure-Entity-AABB-s-are-never-invalid.patch b/patches/server/0462-Ensure-Entity-AABB-s-are-never-invalid.patch similarity index 100% rename from patches/server/0461-Ensure-Entity-AABB-s-are-never-invalid.patch rename to patches/server/0462-Ensure-Entity-AABB-s-are-never-invalid.patch diff --git a/patches/server/0462-Optimize-WorldBorder-collision-checks-and-air.patch b/patches/server/0463-Optimize-WorldBorder-collision-checks-and-air.patch similarity index 100% rename from patches/server/0462-Optimize-WorldBorder-collision-checks-and-air.patch rename to patches/server/0463-Optimize-WorldBorder-collision-checks-and-air.patch diff --git a/patches/server/0463-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/patches/server/0464-Fix-Per-World-Difficulty-Remembering-Difficulty.patch similarity index 100% rename from patches/server/0463-Fix-Per-World-Difficulty-Remembering-Difficulty.patch rename to patches/server/0464-Fix-Per-World-Difficulty-Remembering-Difficulty.patch diff --git a/patches/server/0464-Paper-dumpitem-command.patch b/patches/server/0465-Paper-dumpitem-command.patch similarity index 100% rename from patches/server/0464-Paper-dumpitem-command.patch rename to patches/server/0465-Paper-dumpitem-command.patch diff --git a/patches/server/0465-Don-t-allow-null-UUID-s-for-chat.patch b/patches/server/0466-Don-t-allow-null-UUID-s-for-chat.patch similarity index 100% rename from patches/server/0465-Don-t-allow-null-UUID-s-for-chat.patch rename to patches/server/0466-Don-t-allow-null-UUID-s-for-chat.patch diff --git a/patches/server/0466-Improve-Legacy-Component-serialization-size.patch b/patches/server/0467-Improve-Legacy-Component-serialization-size.patch similarity index 100% rename from patches/server/0466-Improve-Legacy-Component-serialization-size.patch rename to patches/server/0467-Improve-Legacy-Component-serialization-size.patch diff --git a/patches/server/0467-Support-old-UUID-format-for-NBT.patch b/patches/server/0468-Support-old-UUID-format-for-NBT.patch similarity index 100% rename from patches/server/0467-Support-old-UUID-format-for-NBT.patch rename to patches/server/0468-Support-old-UUID-format-for-NBT.patch diff --git a/patches/server/0468-Clean-up-duplicated-GameProfile-Properties.patch b/patches/server/0469-Clean-up-duplicated-GameProfile-Properties.patch similarity index 100% rename from patches/server/0468-Clean-up-duplicated-GameProfile-Properties.patch rename to patches/server/0469-Clean-up-duplicated-GameProfile-Properties.patch diff --git a/patches/server/0469-Convert-legacy-attributes-in-Item-Meta.patch b/patches/server/0470-Convert-legacy-attributes-in-Item-Meta.patch similarity index 100% rename from patches/server/0469-Convert-legacy-attributes-in-Item-Meta.patch rename to patches/server/0470-Convert-legacy-attributes-in-Item-Meta.patch diff --git a/patches/server/0470-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server/0471-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch similarity index 100% rename from patches/server/0470-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch rename to patches/server/0471-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch diff --git a/patches/server/0471-Remove-some-streams-from-structures.patch b/patches/server/0472-Remove-some-streams-from-structures.patch similarity index 100% rename from patches/server/0471-Remove-some-streams-from-structures.patch rename to patches/server/0472-Remove-some-streams-from-structures.patch diff --git a/patches/server/0472-Remove-streams-from-classes-related-villager-gossip.patch b/patches/server/0473-Remove-streams-from-classes-related-villager-gossip.patch similarity index 100% rename from patches/server/0472-Remove-streams-from-classes-related-villager-gossip.patch rename to patches/server/0473-Remove-streams-from-classes-related-villager-gossip.patch diff --git a/patches/server/0473-Support-components-in-ItemMeta.patch b/patches/server/0474-Support-components-in-ItemMeta.patch similarity index 100% rename from patches/server/0473-Support-components-in-ItemMeta.patch rename to patches/server/0474-Support-components-in-ItemMeta.patch diff --git a/patches/server/0474-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/patches/server/0475-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch similarity index 100% rename from patches/server/0474-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch rename to patches/server/0475-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch diff --git a/patches/server/0475-Add-entity-liquid-API.patch b/patches/server/0476-Add-entity-liquid-API.patch similarity index 100% rename from patches/server/0475-Add-entity-liquid-API.patch rename to patches/server/0476-Add-entity-liquid-API.patch diff --git a/patches/server/0476-Update-itemstack-legacy-name-and-lore.patch b/patches/server/0477-Update-itemstack-legacy-name-and-lore.patch similarity index 100% rename from patches/server/0476-Update-itemstack-legacy-name-and-lore.patch rename to patches/server/0477-Update-itemstack-legacy-name-and-lore.patch diff --git a/patches/server/0477-Spawn-player-in-correct-world-on-login.patch b/patches/server/0478-Spawn-player-in-correct-world-on-login.patch similarity index 100% rename from patches/server/0477-Spawn-player-in-correct-world-on-login.patch rename to patches/server/0478-Spawn-player-in-correct-world-on-login.patch diff --git a/patches/server/0478-Add-PrepareResultEvent.patch b/patches/server/0479-Add-PrepareResultEvent.patch similarity index 100% rename from patches/server/0478-Add-PrepareResultEvent.patch rename to patches/server/0479-Add-PrepareResultEvent.patch diff --git a/patches/server/0479-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/0480-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 100% rename from patches/server/0479-Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/server/0480-Allow-delegation-to-vanilla-chunk-gen.patch diff --git a/patches/server/0480-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server/0481-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch similarity index 100% rename from patches/server/0480-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch rename to patches/server/0481-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch diff --git a/patches/server/0481-Optimize-NetworkManager-Exception-Handling.patch b/patches/server/0482-Optimize-NetworkManager-Exception-Handling.patch similarity index 100% rename from patches/server/0481-Optimize-NetworkManager-Exception-Handling.patch rename to patches/server/0482-Optimize-NetworkManager-Exception-Handling.patch diff --git a/patches/server/0482-Optimize-the-advancement-data-player-iteration-to-be.patch b/patches/server/0483-Optimize-the-advancement-data-player-iteration-to-be.patch similarity index 100% rename from patches/server/0482-Optimize-the-advancement-data-player-iteration-to-be.patch rename to patches/server/0483-Optimize-the-advancement-data-player-iteration-to-be.patch diff --git a/patches/server/0483-Fix-arrows-never-despawning-MC-125757.patch b/patches/server/0484-Fix-arrows-never-despawning-MC-125757.patch similarity index 100% rename from patches/server/0483-Fix-arrows-never-despawning-MC-125757.patch rename to patches/server/0484-Fix-arrows-never-despawning-MC-125757.patch diff --git a/patches/server/0484-Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server/0485-Thread-Safe-Vanilla-Command-permission-checking.patch similarity index 100% rename from patches/server/0484-Thread-Safe-Vanilla-Command-permission-checking.patch rename to patches/server/0485-Thread-Safe-Vanilla-Command-permission-checking.patch diff --git a/patches/server/0485-Move-range-check-for-block-placing-up.patch b/patches/server/0486-Move-range-check-for-block-placing-up.patch similarity index 100% rename from patches/server/0485-Move-range-check-for-block-placing-up.patch rename to patches/server/0486-Move-range-check-for-block-placing-up.patch diff --git a/patches/server/0486-Fix-SPIGOT-5989.patch b/patches/server/0487-Fix-SPIGOT-5989.patch similarity index 100% rename from patches/server/0486-Fix-SPIGOT-5989.patch rename to patches/server/0487-Fix-SPIGOT-5989.patch diff --git a/patches/server/0487-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/patches/server/0488-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch similarity index 100% rename from patches/server/0487-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch rename to patches/server/0488-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch diff --git a/patches/server/0488-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/patches/server/0489-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch similarity index 100% rename from patches/server/0488-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch rename to patches/server/0489-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch diff --git a/patches/server/0489-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/patches/server/0490-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch similarity index 100% rename from patches/server/0489-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch rename to patches/server/0490-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch diff --git a/patches/server/0490-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/patches/server/0491-Add-missing-strikeLighting-call-to-World-spigot-stri.patch similarity index 100% rename from patches/server/0490-Add-missing-strikeLighting-call-to-World-spigot-stri.patch rename to patches/server/0491-Add-missing-strikeLighting-call-to-World-spigot-stri.patch diff --git a/patches/server/0491-Fix-some-rails-connecting-improperly.patch b/patches/server/0492-Fix-some-rails-connecting-improperly.patch similarity index 100% rename from patches/server/0491-Fix-some-rails-connecting-improperly.patch rename to patches/server/0492-Fix-some-rails-connecting-improperly.patch diff --git a/patches/server/0492-Incremental-player-saving.patch b/patches/server/0493-Incremental-player-saving.patch similarity index 100% rename from patches/server/0492-Incremental-player-saving.patch rename to patches/server/0493-Incremental-player-saving.patch diff --git a/patches/server/0493-Fix-MC-187716-Use-configured-height.patch b/patches/server/0494-Fix-MC-187716-Use-configured-height.patch similarity index 100% rename from patches/server/0493-Fix-MC-187716-Use-configured-height.patch rename to patches/server/0494-Fix-MC-187716-Use-configured-height.patch diff --git a/patches/server/0494-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/patches/server/0495-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch similarity index 100% rename from patches/server/0494-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch rename to patches/server/0495-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch diff --git a/patches/server/0495-Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server/0496-Do-not-let-the-server-load-chunks-from-newer-version.patch similarity index 100% rename from patches/server/0495-Do-not-let-the-server-load-chunks-from-newer-version.patch rename to patches/server/0496-Do-not-let-the-server-load-chunks-from-newer-version.patch diff --git a/patches/server/0496-Brand-support.patch b/patches/server/0497-Brand-support.patch similarity index 100% rename from patches/server/0496-Brand-support.patch rename to patches/server/0497-Brand-support.patch diff --git a/patches/server/0497-Add-setMaxPlayers-API.patch b/patches/server/0498-Add-setMaxPlayers-API.patch similarity index 100% rename from patches/server/0497-Add-setMaxPlayers-API.patch rename to patches/server/0498-Add-setMaxPlayers-API.patch diff --git a/patches/server/0498-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server/0499-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from patches/server/0498-Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/server/0499-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/patches/server/0499-Don-t-require-FACING-data.patch b/patches/server/0500-Don-t-require-FACING-data.patch similarity index 100% rename from patches/server/0499-Don-t-require-FACING-data.patch rename to patches/server/0500-Don-t-require-FACING-data.patch diff --git a/patches/server/0500-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server/0501-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch similarity index 100% rename from patches/server/0500-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch rename to patches/server/0501-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch diff --git a/patches/server/0501-Add-moon-phase-API.patch b/patches/server/0502-Add-moon-phase-API.patch similarity index 100% rename from patches/server/0501-Add-moon-phase-API.patch rename to patches/server/0502-Add-moon-phase-API.patch diff --git a/patches/server/0502-Prevent-headless-pistons-from-being-created.patch b/patches/server/0503-Prevent-headless-pistons-from-being-created.patch similarity index 100% rename from patches/server/0502-Prevent-headless-pistons-from-being-created.patch rename to patches/server/0503-Prevent-headless-pistons-from-being-created.patch diff --git a/patches/server/0503-Add-BellRingEvent.patch b/patches/server/0504-Add-BellRingEvent.patch similarity index 100% rename from patches/server/0503-Add-BellRingEvent.patch rename to patches/server/0504-Add-BellRingEvent.patch diff --git a/patches/server/0504-Add-zombie-targets-turtle-egg-config.patch b/patches/server/0505-Add-zombie-targets-turtle-egg-config.patch similarity index 100% rename from patches/server/0504-Add-zombie-targets-turtle-egg-config.patch rename to patches/server/0505-Add-zombie-targets-turtle-egg-config.patch diff --git a/patches/server/0505-Buffer-joins-to-world.patch b/patches/server/0506-Buffer-joins-to-world.patch similarity index 100% rename from patches/server/0505-Buffer-joins-to-world.patch rename to patches/server/0506-Buffer-joins-to-world.patch diff --git a/patches/server/0506-Optimize-redstone-algorithm.patch b/patches/server/0507-Optimize-redstone-algorithm.patch similarity index 100% rename from patches/server/0506-Optimize-redstone-algorithm.patch rename to patches/server/0507-Optimize-redstone-algorithm.patch diff --git a/patches/server/0507-Fix-hex-colors-not-working-in-some-kick-messages.patch b/patches/server/0508-Fix-hex-colors-not-working-in-some-kick-messages.patch similarity index 100% rename from patches/server/0507-Fix-hex-colors-not-working-in-some-kick-messages.patch rename to patches/server/0508-Fix-hex-colors-not-working-in-some-kick-messages.patch diff --git a/patches/server/0508-PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server/0509-PortalCreateEvent-needs-to-know-its-entity.patch similarity index 100% rename from patches/server/0508-PortalCreateEvent-needs-to-know-its-entity.patch rename to patches/server/0509-PortalCreateEvent-needs-to-know-its-entity.patch diff --git a/patches/server/0509-Fix-CraftTeam-null-check.patch b/patches/server/0510-Fix-CraftTeam-null-check.patch similarity index 100% rename from patches/server/0509-Fix-CraftTeam-null-check.patch rename to patches/server/0510-Fix-CraftTeam-null-check.patch diff --git a/patches/server/0510-Add-more-Evoker-API.patch b/patches/server/0511-Add-more-Evoker-API.patch similarity index 100% rename from patches/server/0510-Add-more-Evoker-API.patch rename to patches/server/0511-Add-more-Evoker-API.patch diff --git a/patches/server/0511-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/server/0512-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 100% rename from patches/server/0511-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to patches/server/0512-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch diff --git a/patches/server/0512-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server/0513-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 100% rename from patches/server/0512-Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/server/0513-Create-HoverEvent-from-ItemStack-Entity.patch diff --git a/patches/server/0513-Cache-block-data-strings.patch b/patches/server/0514-Cache-block-data-strings.patch similarity index 100% rename from patches/server/0513-Cache-block-data-strings.patch rename to patches/server/0514-Cache-block-data-strings.patch diff --git a/patches/server/0514-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/patches/server/0515-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch similarity index 100% rename from patches/server/0514-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch rename to patches/server/0515-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch diff --git a/patches/server/0515-Add-additional-open-container-api-to-HumanEntity.patch b/patches/server/0516-Add-additional-open-container-api-to-HumanEntity.patch similarity index 100% rename from patches/server/0515-Add-additional-open-container-api-to-HumanEntity.patch rename to patches/server/0516-Add-additional-open-container-api-to-HumanEntity.patch diff --git a/patches/server/0516-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/patches/server/0517-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch similarity index 100% rename from patches/server/0516-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch rename to patches/server/0517-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch diff --git a/patches/server/0517-Extend-block-drop-capture-to-capture-all-items-added.patch b/patches/server/0518-Extend-block-drop-capture-to-capture-all-items-added.patch similarity index 100% rename from patches/server/0517-Extend-block-drop-capture-to-capture-all-items-added.patch rename to patches/server/0518-Extend-block-drop-capture-to-capture-all-items-added.patch diff --git a/patches/server/0518-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server/0519-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch similarity index 100% rename from patches/server/0518-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch rename to patches/server/0519-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch diff --git a/patches/server/0519-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server/0520-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 100% rename from patches/server/0519-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to patches/server/0520-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch diff --git a/patches/server/0520-Lazily-track-plugin-scoreboards-by-default.patch b/patches/server/0521-Lazily-track-plugin-scoreboards-by-default.patch similarity index 100% rename from patches/server/0520-Lazily-track-plugin-scoreboards-by-default.patch rename to patches/server/0521-Lazily-track-plugin-scoreboards-by-default.patch diff --git a/patches/server/0521-Entity-isTicking.patch b/patches/server/0522-Entity-isTicking.patch similarity index 100% rename from patches/server/0521-Entity-isTicking.patch rename to patches/server/0522-Entity-isTicking.patch diff --git a/patches/server/0522-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/patches/server/0523-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch similarity index 100% rename from patches/server/0522-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch rename to patches/server/0523-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch diff --git a/patches/server/0523-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/patches/server/0524-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch similarity index 100% rename from patches/server/0523-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch rename to patches/server/0524-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch diff --git a/patches/server/0524-Reset-Ender-Crystals-on-Dragon-Spawn.patch b/patches/server/0525-Reset-Ender-Crystals-on-Dragon-Spawn.patch similarity index 100% rename from patches/server/0524-Reset-Ender-Crystals-on-Dragon-Spawn.patch rename to patches/server/0525-Reset-Ender-Crystals-on-Dragon-Spawn.patch diff --git a/patches/server/0525-Fix-for-large-move-vectors-crashing-server.patch b/patches/server/0526-Fix-for-large-move-vectors-crashing-server.patch similarity index 100% rename from patches/server/0525-Fix-for-large-move-vectors-crashing-server.patch rename to patches/server/0526-Fix-for-large-move-vectors-crashing-server.patch diff --git a/patches/server/0526-Optimise-getType-calls.patch b/patches/server/0527-Optimise-getType-calls.patch similarity index 100% rename from patches/server/0526-Optimise-getType-calls.patch rename to patches/server/0527-Optimise-getType-calls.patch diff --git a/patches/server/0527-Villager-resetOffers.patch b/patches/server/0528-Villager-resetOffers.patch similarity index 100% rename from patches/server/0527-Villager-resetOffers.patch rename to patches/server/0528-Villager-resetOffers.patch diff --git a/patches/server/0528-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/patches/server/0529-Improve-inlinig-for-some-hot-IBlockData-methods.patch similarity index 100% rename from patches/server/0528-Improve-inlinig-for-some-hot-IBlockData-methods.patch rename to patches/server/0529-Improve-inlinig-for-some-hot-IBlockData-methods.patch diff --git a/patches/server/0529-Retain-block-place-order-when-capturing-blockstates.patch b/patches/server/0530-Retain-block-place-order-when-capturing-blockstates.patch similarity index 93% rename from patches/server/0529-Retain-block-place-order-when-capturing-blockstates.patch rename to patches/server/0530-Retain-block-place-order-when-capturing-blockstates.patch index 60332ff843..86eaf1f7dc 100644 --- a/patches/server/0529-Retain-block-place-order-when-capturing-blockstates.patch +++ b/patches/server/0530-Retain-block-place-order-when-capturing-blockstates.patch @@ -10,7 +10,7 @@ In general, look at making this logic more robust (i.e properly handling cases where a captured entry is overriden) - but for now this will do. diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index b969e7f2087aed5b1f97ce8593a25ada737daec9..31aa0c682fddb0555c2ac47f563484cfa51f2669 100644 +index b92d930448757968cd6a178f4bcafae72c93044c..0c1774ecf236d7616738a170930abe58c5d12ece 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -147,7 +147,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { diff --git a/patches/server/0530-Reduce-blockpos-allocation-from-pathfinding.patch b/patches/server/0531-Reduce-blockpos-allocation-from-pathfinding.patch similarity index 100% rename from patches/server/0530-Reduce-blockpos-allocation-from-pathfinding.patch rename to patches/server/0531-Reduce-blockpos-allocation-from-pathfinding.patch diff --git a/patches/server/0531-Fix-item-locations-dropped-from-campfires.patch b/patches/server/0532-Fix-item-locations-dropped-from-campfires.patch similarity index 100% rename from patches/server/0531-Fix-item-locations-dropped-from-campfires.patch rename to patches/server/0532-Fix-item-locations-dropped-from-campfires.patch diff --git a/patches/server/0532-Player-elytra-boost-API.patch b/patches/server/0533-Player-elytra-boost-API.patch similarity index 100% rename from patches/server/0532-Player-elytra-boost-API.patch rename to patches/server/0533-Player-elytra-boost-API.patch diff --git a/patches/server/0533-Fixed-TileEntityBell-memory-leak.patch b/patches/server/0534-Fixed-TileEntityBell-memory-leak.patch similarity index 100% rename from patches/server/0533-Fixed-TileEntityBell-memory-leak.patch rename to patches/server/0534-Fixed-TileEntityBell-memory-leak.patch diff --git a/patches/server/0534-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/patches/server/0535-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch similarity index 100% rename from patches/server/0534-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch rename to patches/server/0535-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch diff --git a/patches/server/0535-Add-getOfflinePlayerIfCached-String.patch b/patches/server/0536-Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from patches/server/0535-Add-getOfflinePlayerIfCached-String.patch rename to patches/server/0536-Add-getOfflinePlayerIfCached-String.patch diff --git a/patches/server/0536-Add-ignore-discounts-API.patch b/patches/server/0537-Add-ignore-discounts-API.patch similarity index 100% rename from patches/server/0536-Add-ignore-discounts-API.patch rename to patches/server/0537-Add-ignore-discounts-API.patch diff --git a/patches/server/0537-Toggle-for-removing-existing-dragon.patch b/patches/server/0538-Toggle-for-removing-existing-dragon.patch similarity index 100% rename from patches/server/0537-Toggle-for-removing-existing-dragon.patch rename to patches/server/0538-Toggle-for-removing-existing-dragon.patch diff --git a/patches/server/0538-Fix-client-lag-on-advancement-loading.patch b/patches/server/0539-Fix-client-lag-on-advancement-loading.patch similarity index 100% rename from patches/server/0538-Fix-client-lag-on-advancement-loading.patch rename to patches/server/0539-Fix-client-lag-on-advancement-loading.patch diff --git a/patches/server/0539-Item-no-age-no-player-pickup.patch b/patches/server/0540-Item-no-age-no-player-pickup.patch similarity index 100% rename from patches/server/0539-Item-no-age-no-player-pickup.patch rename to patches/server/0540-Item-no-age-no-player-pickup.patch diff --git a/patches/server/0540-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/patches/server/0541-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch similarity index 100% rename from patches/server/0540-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch rename to patches/server/0541-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch diff --git a/patches/server/0541-Beacon-API-custom-effect-ranges.patch b/patches/server/0542-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from patches/server/0541-Beacon-API-custom-effect-ranges.patch rename to patches/server/0542-Beacon-API-custom-effect-ranges.patch diff --git a/patches/server/0542-Add-API-for-quit-reason.patch b/patches/server/0543-Add-API-for-quit-reason.patch similarity index 100% rename from patches/server/0542-Add-API-for-quit-reason.patch rename to patches/server/0543-Add-API-for-quit-reason.patch diff --git a/patches/server/0543-Seed-based-feature-search.patch b/patches/server/0544-Seed-based-feature-search.patch similarity index 100% rename from patches/server/0543-Seed-based-feature-search.patch rename to patches/server/0544-Seed-based-feature-search.patch diff --git a/patches/server/0544-Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server/0545-Add-Wandering-Trader-spawn-rate-config-options.patch similarity index 100% rename from patches/server/0544-Add-Wandering-Trader-spawn-rate-config-options.patch rename to patches/server/0545-Add-Wandering-Trader-spawn-rate-config-options.patch diff --git a/patches/server/0545-Significantly-improve-performance-of-the-end-generat.patch b/patches/server/0546-Significantly-improve-performance-of-the-end-generat.patch similarity index 100% rename from patches/server/0545-Significantly-improve-performance-of-the-end-generat.patch rename to patches/server/0546-Significantly-improve-performance-of-the-end-generat.patch diff --git a/patches/server/0546-Expose-world-spawn-angle.patch b/patches/server/0547-Expose-world-spawn-angle.patch similarity index 100% rename from patches/server/0546-Expose-world-spawn-angle.patch rename to patches/server/0547-Expose-world-spawn-angle.patch diff --git a/patches/server/0547-Add-Destroy-Speed-API.patch b/patches/server/0548-Add-Destroy-Speed-API.patch similarity index 100% rename from patches/server/0547-Add-Destroy-Speed-API.patch rename to patches/server/0548-Add-Destroy-Speed-API.patch diff --git a/patches/server/0548-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/patches/server/0549-Fix-Player-spawnParticle-x-y-z-precision-loss.patch similarity index 100% rename from patches/server/0548-Fix-Player-spawnParticle-x-y-z-precision-loss.patch rename to patches/server/0549-Fix-Player-spawnParticle-x-y-z-precision-loss.patch diff --git a/patches/server/0549-Add-LivingEntity-clearActiveItem.patch b/patches/server/0550-Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from patches/server/0549-Add-LivingEntity-clearActiveItem.patch rename to patches/server/0550-Add-LivingEntity-clearActiveItem.patch diff --git a/patches/server/0550-Add-PlayerItemCooldownEvent.patch b/patches/server/0551-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from patches/server/0550-Add-PlayerItemCooldownEvent.patch rename to patches/server/0551-Add-PlayerItemCooldownEvent.patch diff --git a/patches/server/0551-More-lightning-API.patch b/patches/server/0552-More-lightning-API.patch similarity index 100% rename from patches/server/0551-More-lightning-API.patch rename to patches/server/0552-More-lightning-API.patch diff --git a/patches/server/0552-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/0553-Climbing-should-not-bypass-cramming-gamerule.patch similarity index 100% rename from patches/server/0552-Climbing-should-not-bypass-cramming-gamerule.patch rename to patches/server/0553-Climbing-should-not-bypass-cramming-gamerule.patch diff --git a/patches/server/0553-Added-missing-default-perms-for-commands.patch b/patches/server/0554-Added-missing-default-perms-for-commands.patch similarity index 100% rename from patches/server/0553-Added-missing-default-perms-for-commands.patch rename to patches/server/0554-Added-missing-default-perms-for-commands.patch diff --git a/patches/server/0554-Add-PlayerShearBlockEvent.patch b/patches/server/0555-Add-PlayerShearBlockEvent.patch similarity index 100% rename from patches/server/0554-Add-PlayerShearBlockEvent.patch rename to patches/server/0555-Add-PlayerShearBlockEvent.patch diff --git a/patches/server/0555-Set-spigots-verbose-world-setting-to-false-by-def.patch b/patches/server/0556-Set-spigots-verbose-world-setting-to-false-by-def.patch similarity index 100% rename from patches/server/0555-Set-spigots-verbose-world-setting-to-false-by-def.patch rename to patches/server/0556-Set-spigots-verbose-world-setting-to-false-by-def.patch diff --git a/patches/server/0556-Fix-curing-zombie-villager-discount-exploit.patch b/patches/server/0557-Fix-curing-zombie-villager-discount-exploit.patch similarity index 100% rename from patches/server/0556-Fix-curing-zombie-villager-discount-exploit.patch rename to patches/server/0557-Fix-curing-zombie-villager-discount-exploit.patch diff --git a/patches/server/0557-Limit-recipe-packets.patch b/patches/server/0558-Limit-recipe-packets.patch similarity index 100% rename from patches/server/0557-Limit-recipe-packets.patch rename to patches/server/0558-Limit-recipe-packets.patch diff --git a/patches/server/0558-Fix-CraftSound-backwards-compatibility.patch b/patches/server/0559-Fix-CraftSound-backwards-compatibility.patch similarity index 100% rename from patches/server/0558-Fix-CraftSound-backwards-compatibility.patch rename to patches/server/0559-Fix-CraftSound-backwards-compatibility.patch diff --git a/patches/server/0559-MC-4-Fix-item-position-desync.patch b/patches/server/0560-MC-4-Fix-item-position-desync.patch similarity index 100% rename from patches/server/0559-MC-4-Fix-item-position-desync.patch rename to patches/server/0560-MC-4-Fix-item-position-desync.patch diff --git a/patches/server/0560-Player-Chunk-Load-Unload-Events.patch b/patches/server/0561-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from patches/server/0560-Player-Chunk-Load-Unload-Events.patch rename to patches/server/0561-Player-Chunk-Load-Unload-Events.patch diff --git a/patches/server/0561-Optimize-Dynamic-get-Missing-Keys.patch b/patches/server/0562-Optimize-Dynamic-get-Missing-Keys.patch similarity index 100% rename from patches/server/0561-Optimize-Dynamic-get-Missing-Keys.patch rename to patches/server/0562-Optimize-Dynamic-get-Missing-Keys.patch diff --git a/patches/server/0562-Expose-LivingEntity-hurt-direction.patch b/patches/server/0563-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from patches/server/0562-Expose-LivingEntity-hurt-direction.patch rename to patches/server/0563-Expose-LivingEntity-hurt-direction.patch diff --git a/patches/server/0563-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server/0564-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from patches/server/0563-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/server/0564-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/patches/server/0564-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server/0565-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch similarity index 100% rename from patches/server/0564-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch rename to patches/server/0565-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch diff --git a/patches/server/0565-added-PlayerTradeEvent.patch b/patches/server/0566-added-PlayerTradeEvent.patch similarity index 100% rename from patches/server/0565-added-PlayerTradeEvent.patch rename to patches/server/0566-added-PlayerTradeEvent.patch diff --git a/patches/server/0566-Implement-TargetHitEvent.patch b/patches/server/0567-Implement-TargetHitEvent.patch similarity index 100% rename from patches/server/0566-Implement-TargetHitEvent.patch rename to patches/server/0567-Implement-TargetHitEvent.patch diff --git a/patches/server/0567-Additional-Block-Material-API-s.patch b/patches/server/0568-Additional-Block-Material-API-s.patch similarity index 100% rename from patches/server/0567-Additional-Block-Material-API-s.patch rename to patches/server/0568-Additional-Block-Material-API-s.patch diff --git a/patches/server/0568-Fix-harming-potion-dupe.patch b/patches/server/0569-Fix-harming-potion-dupe.patch similarity index 100% rename from patches/server/0568-Fix-harming-potion-dupe.patch rename to patches/server/0569-Fix-harming-potion-dupe.patch diff --git a/patches/server/0569-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/patches/server/0570-Implement-API-to-get-Material-from-Boats-and-Minecar.patch similarity index 100% rename from patches/server/0569-Implement-API-to-get-Material-from-Boats-and-Minecar.patch rename to patches/server/0570-Implement-API-to-get-Material-from-Boats-and-Minecar.patch diff --git a/patches/server/0570-Cache-burn-durations.patch b/patches/server/0571-Cache-burn-durations.patch similarity index 100% rename from patches/server/0570-Cache-burn-durations.patch rename to patches/server/0571-Cache-burn-durations.patch diff --git a/patches/server/0571-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server/0572-Allow-disabling-mob-spawner-spawn-egg-transformation.patch similarity index 100% rename from patches/server/0571-Allow-disabling-mob-spawner-spawn-egg-transformation.patch rename to patches/server/0572-Allow-disabling-mob-spawner-spawn-egg-transformation.patch diff --git a/patches/server/0572-Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server/0573-Implement-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from patches/server/0572-Implement-PlayerFlowerPotManipulateEvent.patch rename to patches/server/0573-Implement-PlayerFlowerPotManipulateEvent.patch diff --git a/patches/server/0573-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server/0574-Fix-interact-event-not-being-called-in-adventure.patch similarity index 100% rename from patches/server/0573-Fix-interact-event-not-being-called-in-adventure.patch rename to patches/server/0574-Fix-interact-event-not-being-called-in-adventure.patch diff --git a/patches/server/0574-Zombie-API-breaking-doors.patch b/patches/server/0575-Zombie-API-breaking-doors.patch similarity index 100% rename from patches/server/0574-Zombie-API-breaking-doors.patch rename to patches/server/0575-Zombie-API-breaking-doors.patch diff --git a/patches/server/0575-Fix-nerfed-slime-when-splitting.patch b/patches/server/0576-Fix-nerfed-slime-when-splitting.patch similarity index 100% rename from patches/server/0575-Fix-nerfed-slime-when-splitting.patch rename to patches/server/0576-Fix-nerfed-slime-when-splitting.patch diff --git a/patches/server/0576-Add-EntityLoadCrossbowEvent.patch b/patches/server/0577-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from patches/server/0576-Add-EntityLoadCrossbowEvent.patch rename to patches/server/0577-Add-EntityLoadCrossbowEvent.patch diff --git a/patches/server/0577-Guardian-beam-workaround.patch b/patches/server/0578-Guardian-beam-workaround.patch similarity index 100% rename from patches/server/0577-Guardian-beam-workaround.patch rename to patches/server/0578-Guardian-beam-workaround.patch diff --git a/patches/server/0578-Added-WorldGameRuleChangeEvent.patch b/patches/server/0579-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from patches/server/0578-Added-WorldGameRuleChangeEvent.patch rename to patches/server/0579-Added-WorldGameRuleChangeEvent.patch diff --git a/patches/server/0579-Added-ServerResourcesReloadedEvent.patch b/patches/server/0580-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from patches/server/0579-Added-ServerResourcesReloadedEvent.patch rename to patches/server/0580-Added-ServerResourcesReloadedEvent.patch diff --git a/patches/server/0580-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server/0581-Added-world-settings-for-mobs-picking-up-loot.patch similarity index 100% rename from patches/server/0580-Added-world-settings-for-mobs-picking-up-loot.patch rename to patches/server/0581-Added-world-settings-for-mobs-picking-up-loot.patch diff --git a/patches/server/0581-Implemented-BlockFailedDispenseEvent.patch b/patches/server/0582-Implemented-BlockFailedDispenseEvent.patch similarity index 100% rename from patches/server/0581-Implemented-BlockFailedDispenseEvent.patch rename to patches/server/0582-Implemented-BlockFailedDispenseEvent.patch diff --git a/patches/server/0582-Added-PlayerLecternPageChangeEvent.patch b/patches/server/0583-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from patches/server/0582-Added-PlayerLecternPageChangeEvent.patch rename to patches/server/0583-Added-PlayerLecternPageChangeEvent.patch diff --git a/patches/server/0583-Added-PlayerLoomPatternSelectEvent.patch b/patches/server/0584-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from patches/server/0583-Added-PlayerLoomPatternSelectEvent.patch rename to patches/server/0584-Added-PlayerLoomPatternSelectEvent.patch diff --git a/patches/server/0584-Configurable-door-breaking-difficulty.patch b/patches/server/0585-Configurable-door-breaking-difficulty.patch similarity index 100% rename from patches/server/0584-Configurable-door-breaking-difficulty.patch rename to patches/server/0585-Configurable-door-breaking-difficulty.patch diff --git a/patches/server/0585-Empty-commands-shall-not-be-dispatched.patch b/patches/server/0586-Empty-commands-shall-not-be-dispatched.patch similarity index 100% rename from patches/server/0585-Empty-commands-shall-not-be-dispatched.patch rename to patches/server/0586-Empty-commands-shall-not-be-dispatched.patch diff --git a/patches/server/0586-Implement-API-to-expose-exact-interaction-point.patch b/patches/server/0587-Implement-API-to-expose-exact-interaction-point.patch similarity index 100% rename from patches/server/0586-Implement-API-to-expose-exact-interaction-point.patch rename to patches/server/0587-Implement-API-to-expose-exact-interaction-point.patch diff --git a/patches/server/0587-Remove-stale-POIs.patch b/patches/server/0588-Remove-stale-POIs.patch similarity index 100% rename from patches/server/0587-Remove-stale-POIs.patch rename to patches/server/0588-Remove-stale-POIs.patch diff --git a/patches/server/0588-Fix-villager-boat-exploit.patch b/patches/server/0589-Fix-villager-boat-exploit.patch similarity index 100% rename from patches/server/0588-Fix-villager-boat-exploit.patch rename to patches/server/0589-Fix-villager-boat-exploit.patch diff --git a/patches/server/0589-Add-sendOpLevel-API.patch b/patches/server/0590-Add-sendOpLevel-API.patch similarity index 100% rename from patches/server/0589-Add-sendOpLevel-API.patch rename to patches/server/0590-Add-sendOpLevel-API.patch diff --git a/patches/server/0590-Add-StructureLocateEvent.patch b/patches/server/0591-Add-StructureLocateEvent.patch similarity index 100% rename from patches/server/0590-Add-StructureLocateEvent.patch rename to patches/server/0591-Add-StructureLocateEvent.patch diff --git a/patches/server/0591-Collision-option-for-requiring-a-player-participant.patch b/patches/server/0592-Collision-option-for-requiring-a-player-participant.patch similarity index 100% rename from patches/server/0591-Collision-option-for-requiring-a-player-participant.patch rename to patches/server/0592-Collision-option-for-requiring-a-player-participant.patch diff --git a/patches/server/0592-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/patches/server/0593-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch similarity index 100% rename from patches/server/0592-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch rename to patches/server/0593-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch diff --git a/patches/server/0593-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/server/0594-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from patches/server/0593-Return-chat-component-with-empty-text-instead-of-thr.patch rename to patches/server/0594-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/patches/server/0594-Make-schedule-command-per-world.patch b/patches/server/0595-Make-schedule-command-per-world.patch similarity index 100% rename from patches/server/0594-Make-schedule-command-per-world.patch rename to patches/server/0595-Make-schedule-command-per-world.patch diff --git a/patches/server/0595-Configurable-max-leash-distance.patch b/patches/server/0596-Configurable-max-leash-distance.patch similarity index 100% rename from patches/server/0595-Configurable-max-leash-distance.patch rename to patches/server/0596-Configurable-max-leash-distance.patch diff --git a/patches/server/0596-Implement-BlockPreDispenseEvent.patch b/patches/server/0597-Implement-BlockPreDispenseEvent.patch similarity index 100% rename from patches/server/0596-Implement-BlockPreDispenseEvent.patch rename to patches/server/0597-Implement-BlockPreDispenseEvent.patch diff --git a/patches/server/0597-Added-Vanilla-Entity-Tags.patch b/patches/server/0598-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from patches/server/0597-Added-Vanilla-Entity-Tags.patch rename to patches/server/0598-Added-Vanilla-Entity-Tags.patch diff --git a/patches/server/0598-added-Wither-API.patch b/patches/server/0599-added-Wither-API.patch similarity index 100% rename from patches/server/0598-added-Wither-API.patch rename to patches/server/0599-added-Wither-API.patch diff --git a/patches/server/0599-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/patches/server/0600-Added-firing-of-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from patches/server/0599-Added-firing-of-PlayerChangeBeaconEffectEvent.patch rename to patches/server/0600-Added-firing-of-PlayerChangeBeaconEffectEvent.patch diff --git a/patches/server/0600-Fix-console-spam-when-removing-chests-in-water.patch b/patches/server/0601-Fix-console-spam-when-removing-chests-in-water.patch similarity index 100% rename from patches/server/0600-Fix-console-spam-when-removing-chests-in-water.patch rename to patches/server/0601-Fix-console-spam-when-removing-chests-in-water.patch diff --git a/patches/server/0601-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server/0602-Add-toggle-for-always-placing-the-dragon-egg.patch similarity index 100% rename from patches/server/0601-Add-toggle-for-always-placing-the-dragon-egg.patch rename to patches/server/0602-Add-toggle-for-always-placing-the-dragon-egg.patch diff --git a/patches/server/0602-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server/0603-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from patches/server/0602-Added-PlayerStonecutterRecipeSelectEvent.patch rename to patches/server/0603-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/patches/server/0603-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/server/0604-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from patches/server/0603-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/server/0604-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/patches/server/0604-Skip-distance-map-update-when-spawning-disabled.patch b/patches/server/0605-Skip-distance-map-update-when-spawning-disabled.patch similarity index 100% rename from patches/server/0604-Skip-distance-map-update-when-spawning-disabled.patch rename to patches/server/0605-Skip-distance-map-update-when-spawning-disabled.patch diff --git a/patches/server/0605-Reset-shield-blocking-on-dimension-change.patch b/patches/server/0606-Reset-shield-blocking-on-dimension-change.patch similarity index 100% rename from patches/server/0605-Reset-shield-blocking-on-dimension-change.patch rename to patches/server/0606-Reset-shield-blocking-on-dimension-change.patch diff --git a/patches/server/0606-add-DragonEggFormEvent.patch b/patches/server/0607-add-DragonEggFormEvent.patch similarity index 100% rename from patches/server/0606-add-DragonEggFormEvent.patch rename to patches/server/0607-add-DragonEggFormEvent.patch diff --git a/patches/server/0607-EntityMoveEvent.patch b/patches/server/0608-EntityMoveEvent.patch similarity index 100% rename from patches/server/0607-EntityMoveEvent.patch rename to patches/server/0608-EntityMoveEvent.patch diff --git a/patches/server/0608-added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server/0609-added-option-to-disable-pathfinding-updates-on-block.patch similarity index 100% rename from patches/server/0608-added-option-to-disable-pathfinding-updates-on-block.patch rename to patches/server/0609-added-option-to-disable-pathfinding-updates-on-block.patch diff --git a/patches/server/0609-Inline-shift-direction-fields.patch b/patches/server/0610-Inline-shift-direction-fields.patch similarity index 100% rename from patches/server/0609-Inline-shift-direction-fields.patch rename to patches/server/0610-Inline-shift-direction-fields.patch diff --git a/patches/server/0610-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server/0611-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from patches/server/0610-Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/server/0611-Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/patches/server/0611-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/server/0612-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from patches/server/0611-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/server/0612-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/patches/server/0612-living-entity-allow-attribute-registration.patch b/patches/server/0613-living-entity-allow-attribute-registration.patch similarity index 100% rename from patches/server/0612-living-entity-allow-attribute-registration.patch rename to patches/server/0613-living-entity-allow-attribute-registration.patch diff --git a/patches/server/0613-fix-dead-slime-setSize-invincibility.patch b/patches/server/0614-fix-dead-slime-setSize-invincibility.patch similarity index 100% rename from patches/server/0613-fix-dead-slime-setSize-invincibility.patch rename to patches/server/0614-fix-dead-slime-setSize-invincibility.patch diff --git a/patches/server/0614-Merchant-getRecipes-should-return-an-immutable-list.patch b/patches/server/0615-Merchant-getRecipes-should-return-an-immutable-list.patch similarity index 100% rename from patches/server/0614-Merchant-getRecipes-should-return-an-immutable-list.patch rename to patches/server/0615-Merchant-getRecipes-should-return-an-immutable-list.patch diff --git a/patches/server/0615-misc-debugging-dumps.patch b/patches/server/0616-misc-debugging-dumps.patch similarity index 100% rename from patches/server/0615-misc-debugging-dumps.patch rename to patches/server/0616-misc-debugging-dumps.patch diff --git a/patches/server/0616-Add-support-for-hex-color-codes-in-console.patch b/patches/server/0617-Add-support-for-hex-color-codes-in-console.patch similarity index 100% rename from patches/server/0616-Add-support-for-hex-color-codes-in-console.patch rename to patches/server/0617-Add-support-for-hex-color-codes-in-console.patch diff --git a/patches/server/0617-Expose-Tracked-Players.patch b/patches/server/0618-Expose-Tracked-Players.patch similarity index 100% rename from patches/server/0617-Expose-Tracked-Players.patch rename to patches/server/0618-Expose-Tracked-Players.patch diff --git a/patches/server/0618-Remove-streams-from-SensorNearest.patch b/patches/server/0619-Remove-streams-from-SensorNearest.patch similarity index 100% rename from patches/server/0618-Remove-streams-from-SensorNearest.patch rename to patches/server/0619-Remove-streams-from-SensorNearest.patch diff --git a/patches/server/0619-MC-29274-Fix-Wither-hostility-towards-players.patch b/patches/server/0620-MC-29274-Fix-Wither-hostility-towards-players.patch similarity index 100% rename from patches/server/0619-MC-29274-Fix-Wither-hostility-towards-players.patch rename to patches/server/0620-MC-29274-Fix-Wither-hostility-towards-players.patch diff --git a/patches/server/0620-Throw-proper-exception-on-empty-JsonList-file.patch b/patches/server/0621-Throw-proper-exception-on-empty-JsonList-file.patch similarity index 100% rename from patches/server/0620-Throw-proper-exception-on-empty-JsonList-file.patch rename to patches/server/0621-Throw-proper-exception-on-empty-JsonList-file.patch diff --git a/patches/server/0621-Improve-ServerGUI.patch b/patches/server/0622-Improve-ServerGUI.patch similarity index 100% rename from patches/server/0621-Improve-ServerGUI.patch rename to patches/server/0622-Improve-ServerGUI.patch diff --git a/patches/server/0622-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/patches/server/0623-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch similarity index 100% rename from patches/server/0622-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch rename to patches/server/0623-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch diff --git a/patches/server/0623-fix-converting-txt-to-json-file.patch b/patches/server/0624-fix-converting-txt-to-json-file.patch similarity index 100% rename from patches/server/0623-fix-converting-txt-to-json-file.patch rename to patches/server/0624-fix-converting-txt-to-json-file.patch diff --git a/patches/server/0624-Add-worldborder-events.patch b/patches/server/0625-Add-worldborder-events.patch similarity index 100% rename from patches/server/0624-Add-worldborder-events.patch rename to patches/server/0625-Add-worldborder-events.patch diff --git a/patches/server/0625-added-PlayerNameEntityEvent.patch b/patches/server/0626-added-PlayerNameEntityEvent.patch similarity index 100% rename from patches/server/0625-added-PlayerNameEntityEvent.patch rename to patches/server/0626-added-PlayerNameEntityEvent.patch diff --git a/patches/server/0626-Prevent-grindstones-from-overstacking-items.patch b/patches/server/0627-Prevent-grindstones-from-overstacking-items.patch similarity index 100% rename from patches/server/0626-Prevent-grindstones-from-overstacking-items.patch rename to patches/server/0627-Prevent-grindstones-from-overstacking-items.patch diff --git a/patches/server/0627-Add-recipe-to-cook-events.patch b/patches/server/0628-Add-recipe-to-cook-events.patch similarity index 100% rename from patches/server/0627-Add-recipe-to-cook-events.patch rename to patches/server/0628-Add-recipe-to-cook-events.patch diff --git a/patches/server/0628-Add-Block-isValidTool.patch b/patches/server/0629-Add-Block-isValidTool.patch similarity index 100% rename from patches/server/0628-Add-Block-isValidTool.patch rename to patches/server/0629-Add-Block-isValidTool.patch diff --git a/patches/server/0629-Allow-using-signs-inside-spawn-protection.patch b/patches/server/0630-Allow-using-signs-inside-spawn-protection.patch similarity index 100% rename from patches/server/0629-Allow-using-signs-inside-spawn-protection.patch rename to patches/server/0630-Allow-using-signs-inside-spawn-protection.patch diff --git a/patches/server/0630-Implement-Keyed-on-World.patch b/patches/server/0631-Implement-Keyed-on-World.patch similarity index 100% rename from patches/server/0630-Implement-Keyed-on-World.patch rename to patches/server/0631-Implement-Keyed-on-World.patch diff --git a/patches/server/0631-Add-fast-alternative-constructor-for-Rotations.patch b/patches/server/0632-Add-fast-alternative-constructor-for-Rotations.patch similarity index 100% rename from patches/server/0631-Add-fast-alternative-constructor-for-Rotations.patch rename to patches/server/0632-Add-fast-alternative-constructor-for-Rotations.patch diff --git a/patches/server/0632-Item-Rarity-API.patch b/patches/server/0633-Item-Rarity-API.patch similarity index 100% rename from patches/server/0632-Item-Rarity-API.patch rename to patches/server/0633-Item-Rarity-API.patch diff --git a/patches/server/0633-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/patches/server/0634-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch similarity index 100% rename from patches/server/0633-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch rename to patches/server/0634-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch diff --git a/patches/server/0634-copy-TESign-isEditable-from-snapshots.patch b/patches/server/0635-copy-TESign-isEditable-from-snapshots.patch similarity index 100% rename from patches/server/0634-copy-TESign-isEditable-from-snapshots.patch rename to patches/server/0635-copy-TESign-isEditable-from-snapshots.patch diff --git a/patches/server/0635-Drop-carried-item-when-player-has-disconnected.patch b/patches/server/0636-Drop-carried-item-when-player-has-disconnected.patch similarity index 100% rename from patches/server/0635-Drop-carried-item-when-player-has-disconnected.patch rename to patches/server/0636-Drop-carried-item-when-player-has-disconnected.patch diff --git a/patches/server/0636-forced-whitelist-use-configurable-kick-message.patch b/patches/server/0637-forced-whitelist-use-configurable-kick-message.patch similarity index 100% rename from patches/server/0636-forced-whitelist-use-configurable-kick-message.patch rename to patches/server/0637-forced-whitelist-use-configurable-kick-message.patch diff --git a/patches/server/0637-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/patches/server/0638-Don-t-ignore-result-of-PlayerEditBookEvent.patch similarity index 100% rename from patches/server/0637-Don-t-ignore-result-of-PlayerEditBookEvent.patch rename to patches/server/0638-Don-t-ignore-result-of-PlayerEditBookEvent.patch diff --git a/patches/server/0638-fix-cancelling-block-falling-causing-client-desync.patch b/patches/server/0639-fix-cancelling-block-falling-causing-client-desync.patch similarity index 100% rename from patches/server/0638-fix-cancelling-block-falling-causing-client-desync.patch rename to patches/server/0639-fix-cancelling-block-falling-causing-client-desync.patch diff --git a/patches/server/0639-Expose-protocol-version.patch b/patches/server/0640-Expose-protocol-version.patch similarity index 100% rename from patches/server/0639-Expose-protocol-version.patch rename to patches/server/0640-Expose-protocol-version.patch diff --git a/patches/server/0640-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/server/0641-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 100% rename from patches/server/0640-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to patches/server/0641-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch diff --git a/patches/server/0641-Enhance-console-tab-completions-for-brigadier-comman.patch b/patches/server/0642-Enhance-console-tab-completions-for-brigadier-comman.patch similarity index 100% rename from patches/server/0641-Enhance-console-tab-completions-for-brigadier-comman.patch rename to patches/server/0642-Enhance-console-tab-completions-for-brigadier-comman.patch diff --git a/patches/server/0642-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/patches/server/0643-Fix-PlayerItemConsumeEvent-cancelling-properly.patch similarity index 100% rename from patches/server/0642-Fix-PlayerItemConsumeEvent-cancelling-properly.patch rename to patches/server/0643-Fix-PlayerItemConsumeEvent-cancelling-properly.patch diff --git a/patches/server/0643-Add-bypass-host-check.patch b/patches/server/0644-Add-bypass-host-check.patch similarity index 100% rename from patches/server/0643-Add-bypass-host-check.patch rename to patches/server/0644-Add-bypass-host-check.patch diff --git a/patches/server/0644-Set-area-affect-cloud-rotation.patch b/patches/server/0645-Set-area-affect-cloud-rotation.patch similarity index 100% rename from patches/server/0644-Set-area-affect-cloud-rotation.patch rename to patches/server/0645-Set-area-affect-cloud-rotation.patch diff --git a/patches/server/0645-add-isDeeplySleeping-to-HumanEntity.patch b/patches/server/0646-add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from patches/server/0645-add-isDeeplySleeping-to-HumanEntity.patch rename to patches/server/0646-add-isDeeplySleeping-to-HumanEntity.patch diff --git a/patches/server/0646-Fix-duplicating-give-items-on-item-drop-cancel.patch b/patches/server/0647-Fix-duplicating-give-items-on-item-drop-cancel.patch similarity index 100% rename from patches/server/0646-Fix-duplicating-give-items-on-item-drop-cancel.patch rename to patches/server/0647-Fix-duplicating-give-items-on-item-drop-cancel.patch diff --git a/patches/server/0647-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/server/0648-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from patches/server/0647-add-consumeFuel-to-FurnaceBurnEvent.patch rename to patches/server/0648-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/patches/server/0648-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/server/0649-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from patches/server/0648-add-get-set-drop-chance-to-EntityEquipment.patch rename to patches/server/0649-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/patches/server/0649-fix-PigZombieAngerEvent-cancellation.patch b/patches/server/0650-fix-PigZombieAngerEvent-cancellation.patch similarity index 100% rename from patches/server/0649-fix-PigZombieAngerEvent-cancellation.patch rename to patches/server/0650-fix-PigZombieAngerEvent-cancellation.patch diff --git a/patches/server/0650-Fix-checkReach-check-for-Shulker-boxes.patch b/patches/server/0651-Fix-checkReach-check-for-Shulker-boxes.patch similarity index 100% rename from patches/server/0650-Fix-checkReach-check-for-Shulker-boxes.patch rename to patches/server/0651-Fix-checkReach-check-for-Shulker-boxes.patch diff --git a/patches/server/0651-fix-PlayerItemHeldEvent-firing-twice.patch b/patches/server/0652-fix-PlayerItemHeldEvent-firing-twice.patch similarity index 100% rename from patches/server/0651-fix-PlayerItemHeldEvent-firing-twice.patch rename to patches/server/0652-fix-PlayerItemHeldEvent-firing-twice.patch diff --git a/patches/server/0652-Added-PlayerDeepSleepEvent.patch b/patches/server/0653-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from patches/server/0652-Added-PlayerDeepSleepEvent.patch rename to patches/server/0653-Added-PlayerDeepSleepEvent.patch diff --git a/patches/server/0653-More-World-API.patch b/patches/server/0654-More-World-API.patch similarity index 100% rename from patches/server/0653-More-World-API.patch rename to patches/server/0654-More-World-API.patch diff --git a/patches/server/0654-Added-PlayerBedFailEnterEvent.patch b/patches/server/0655-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from patches/server/0654-Added-PlayerBedFailEnterEvent.patch rename to patches/server/0655-Added-PlayerBedFailEnterEvent.patch diff --git a/patches/server/0655-Implement-methods-to-convert-between-Component-and-B.patch b/patches/server/0656-Implement-methods-to-convert-between-Component-and-B.patch similarity index 100% rename from patches/server/0655-Implement-methods-to-convert-between-Component-and-B.patch rename to patches/server/0656-Implement-methods-to-convert-between-Component-and-B.patch diff --git a/patches/server/0656-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/patches/server/0657-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch similarity index 100% rename from patches/server/0656-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch rename to patches/server/0657-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch diff --git a/patches/server/0657-Introduce-beacon-activation-deactivation-events.patch b/patches/server/0658-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from patches/server/0657-Introduce-beacon-activation-deactivation-events.patch rename to patches/server/0658-Introduce-beacon-activation-deactivation-events.patch diff --git a/patches/server/0658-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/server/0659-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from patches/server/0658-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/server/0659-add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/patches/server/0659-Add-Channel-initialization-listeners.patch b/patches/server/0660-Add-Channel-initialization-listeners.patch similarity index 100% rename from patches/server/0659-Add-Channel-initialization-listeners.patch rename to patches/server/0660-Add-Channel-initialization-listeners.patch diff --git a/patches/server/0660-Send-empty-commands-if-tab-completion-is-disabled.patch b/patches/server/0661-Send-empty-commands-if-tab-completion-is-disabled.patch similarity index 100% rename from patches/server/0660-Send-empty-commands-if-tab-completion-is-disabled.patch rename to patches/server/0661-Send-empty-commands-if-tab-completion-is-disabled.patch diff --git a/patches/server/0661-Add-more-WanderingTrader-API.patch b/patches/server/0662-Add-more-WanderingTrader-API.patch similarity index 100% rename from patches/server/0661-Add-more-WanderingTrader-API.patch rename to patches/server/0662-Add-more-WanderingTrader-API.patch diff --git a/patches/server/0662-Add-EntityBlockStorage-clearEntities.patch b/patches/server/0663-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from patches/server/0662-Add-EntityBlockStorage-clearEntities.patch rename to patches/server/0663-Add-EntityBlockStorage-clearEntities.patch diff --git a/patches/server/0663-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/server/0664-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from patches/server/0663-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to patches/server/0664-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/patches/server/0664-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/server/0665-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from patches/server/0664-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/server/0665-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/patches/server/0665-Inventory-close.patch b/patches/server/0666-Inventory-close.patch similarity index 100% rename from patches/server/0665-Inventory-close.patch rename to patches/server/0666-Inventory-close.patch diff --git a/patches/server/0666-call-PortalCreateEvent-players-and-end-platform.patch b/patches/server/0667-call-PortalCreateEvent-players-and-end-platform.patch similarity index 100% rename from patches/server/0666-call-PortalCreateEvent-players-and-end-platform.patch rename to patches/server/0667-call-PortalCreateEvent-players-and-end-platform.patch diff --git a/patches/server/0667-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/server/0668-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 100% rename from patches/server/0667-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/server/0668-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch diff --git a/patches/server/0668-Fix-CraftPotionBrewer-cache.patch b/patches/server/0669-Fix-CraftPotionBrewer-cache.patch similarity index 100% rename from patches/server/0668-Fix-CraftPotionBrewer-cache.patch rename to patches/server/0669-Fix-CraftPotionBrewer-cache.patch diff --git a/patches/server/0669-Add-basic-Datapack-API.patch b/patches/server/0670-Add-basic-Datapack-API.patch similarity index 100% rename from patches/server/0669-Add-basic-Datapack-API.patch rename to patches/server/0670-Add-basic-Datapack-API.patch diff --git a/patches/server/0670-Add-environment-variable-to-disable-server-gui.patch b/patches/server/0671-Add-environment-variable-to-disable-server-gui.patch similarity index 100% rename from patches/server/0670-Add-environment-variable-to-disable-server-gui.patch rename to patches/server/0671-Add-environment-variable-to-disable-server-gui.patch diff --git a/patches/server/0671-additions-to-PlayerGameModeChangeEvent.patch b/patches/server/0672-additions-to-PlayerGameModeChangeEvent.patch similarity index 100% rename from patches/server/0671-additions-to-PlayerGameModeChangeEvent.patch rename to patches/server/0672-additions-to-PlayerGameModeChangeEvent.patch diff --git a/patches/server/0672-ItemStack-repair-check-API.patch b/patches/server/0673-ItemStack-repair-check-API.patch similarity index 100% rename from patches/server/0672-ItemStack-repair-check-API.patch rename to patches/server/0673-ItemStack-repair-check-API.patch diff --git a/patches/server/0673-More-Enchantment-API.patch b/patches/server/0674-More-Enchantment-API.patch similarity index 100% rename from patches/server/0673-More-Enchantment-API.patch rename to patches/server/0674-More-Enchantment-API.patch diff --git a/patches/server/0674-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/server/0675-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 100% rename from patches/server/0674-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to patches/server/0675-Add-command-line-option-to-load-extra-plugin-jars-no.patch diff --git a/patches/server/0675-Fix-and-optimise-world-force-upgrading.patch b/patches/server/0676-Fix-and-optimise-world-force-upgrading.patch similarity index 99% rename from patches/server/0675-Fix-and-optimise-world-force-upgrading.patch rename to patches/server/0676-Fix-and-optimise-world-force-upgrading.patch index ac29e5ed6b..8c5f11e07b 100644 --- a/patches/server/0675-Fix-and-optimise-world-force-upgrading.patch +++ b/patches/server/0676-Fix-and-optimise-world-force-upgrading.patch @@ -297,7 +297,7 @@ index 73ac55de9059a1d0f1da5bec0688dcd4bf5c8973..db2d6e7b2dc82c60d524dd2a018d28c2 if (dimensionKey == LevelStem.OVERWORLD) { diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 31aa0c682fddb0555c2ac47f563484cfa51f2669..ad2d5b19ef23677dd6192b049fca42b9cec392a1 100644 +index 0c1774ecf236d7616738a170930abe58c5d12ece..667aecc27e0c886f15a0418020d046e0a9791a0e 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -185,6 +185,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { diff --git a/patches/server/0676-Add-Mob-lookAt-API.patch b/patches/server/0677-Add-Mob-lookAt-API.patch similarity index 100% rename from patches/server/0676-Add-Mob-lookAt-API.patch rename to patches/server/0677-Add-Mob-lookAt-API.patch diff --git a/patches/server/0677-Add-Unix-domain-socket-support.patch b/patches/server/0678-Add-Unix-domain-socket-support.patch similarity index 100% rename from patches/server/0677-Add-Unix-domain-socket-support.patch rename to patches/server/0678-Add-Unix-domain-socket-support.patch diff --git a/patches/server/0678-Add-EntityInsideBlockEvent.patch b/patches/server/0679-Add-EntityInsideBlockEvent.patch similarity index 100% rename from patches/server/0678-Add-EntityInsideBlockEvent.patch rename to patches/server/0679-Add-EntityInsideBlockEvent.patch diff --git a/patches/server/0679-Attributes-API-for-item-defaults.patch b/patches/server/0680-Attributes-API-for-item-defaults.patch similarity index 100% rename from patches/server/0679-Attributes-API-for-item-defaults.patch rename to patches/server/0680-Attributes-API-for-item-defaults.patch diff --git a/patches/server/0680-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/patches/server/0681-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch similarity index 100% rename from patches/server/0680-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch rename to patches/server/0681-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch diff --git a/patches/server/0681-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/server/0682-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from patches/server/0681-Add-cause-to-Weather-ThunderChangeEvents.patch rename to patches/server/0682-Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/patches/server/0682-More-Lidded-Block-API.patch b/patches/server/0683-More-Lidded-Block-API.patch similarity index 100% rename from patches/server/0682-More-Lidded-Block-API.patch rename to patches/server/0683-More-Lidded-Block-API.patch diff --git a/patches/server/0683-Limit-item-frame-cursors-on-maps.patch b/patches/server/0684-Limit-item-frame-cursors-on-maps.patch similarity index 100% rename from patches/server/0683-Limit-item-frame-cursors-on-maps.patch rename to patches/server/0684-Limit-item-frame-cursors-on-maps.patch diff --git a/patches/server/0684-Add-PufferFishStateChangeEvent.patch b/patches/server/0685-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from patches/server/0684-Add-PufferFishStateChangeEvent.patch rename to patches/server/0685-Add-PufferFishStateChangeEvent.patch diff --git a/patches/server/0685-Add-PlayerKickEvent-causes.patch b/patches/server/0686-Add-PlayerKickEvent-causes.patch similarity index 100% rename from patches/server/0685-Add-PlayerKickEvent-causes.patch rename to patches/server/0686-Add-PlayerKickEvent-causes.patch diff --git a/patches/server/0686-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/patches/server/0687-Fix-PlayerBucketEmptyEvent-result-itemstack.patch similarity index 100% rename from patches/server/0686-Fix-PlayerBucketEmptyEvent-result-itemstack.patch rename to patches/server/0687-Fix-PlayerBucketEmptyEvent-result-itemstack.patch diff --git a/patches/server/0687-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch b/patches/server/0688-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch similarity index 100% rename from patches/server/0687-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch rename to patches/server/0688-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch diff --git a/patches/server/0688-Add-option-to-fix-items-merging-through-walls.patch b/patches/server/0689-Add-option-to-fix-items-merging-through-walls.patch similarity index 100% rename from patches/server/0688-Add-option-to-fix-items-merging-through-walls.patch rename to patches/server/0689-Add-option-to-fix-items-merging-through-walls.patch diff --git a/patches/server/0689-Add-BellRevealRaiderEvent.patch b/patches/server/0690-Add-BellRevealRaiderEvent.patch similarity index 100% rename from patches/server/0689-Add-BellRevealRaiderEvent.patch rename to patches/server/0690-Add-BellRevealRaiderEvent.patch diff --git a/patches/server/0690-Fix-invulnerable-end-crystals.patch b/patches/server/0691-Fix-invulnerable-end-crystals.patch similarity index 100% rename from patches/server/0690-Fix-invulnerable-end-crystals.patch rename to patches/server/0691-Fix-invulnerable-end-crystals.patch diff --git a/patches/server/0691-Add-ElderGuardianAppearanceEvent.patch b/patches/server/0692-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from patches/server/0691-Add-ElderGuardianAppearanceEvent.patch rename to patches/server/0692-Add-ElderGuardianAppearanceEvent.patch diff --git a/patches/server/0692-Reset-villager-inventory-on-cancelled-pickup-event.patch b/patches/server/0693-Reset-villager-inventory-on-cancelled-pickup-event.patch similarity index 100% rename from patches/server/0692-Reset-villager-inventory-on-cancelled-pickup-event.patch rename to patches/server/0693-Reset-villager-inventory-on-cancelled-pickup-event.patch diff --git a/patches/server/0693-Fix-dangerous-end-portal-logic.patch b/patches/server/0694-Fix-dangerous-end-portal-logic.patch similarity index 100% rename from patches/server/0693-Fix-dangerous-end-portal-logic.patch rename to patches/server/0694-Fix-dangerous-end-portal-logic.patch diff --git a/patches/server/0694-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/server/0695-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch similarity index 100% rename from patches/server/0694-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch rename to patches/server/0695-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch diff --git a/patches/server/0695-Make-item-validations-configurable.patch b/patches/server/0696-Make-item-validations-configurable.patch similarity index 100% rename from patches/server/0695-Make-item-validations-configurable.patch rename to patches/server/0696-Make-item-validations-configurable.patch diff --git a/patches/server/0696-Add-more-line-of-sight-methods.patch b/patches/server/0697-Add-more-line-of-sight-methods.patch similarity index 100% rename from patches/server/0696-Add-more-line-of-sight-methods.patch rename to patches/server/0697-Add-more-line-of-sight-methods.patch diff --git a/patches/server/0697-add-per-world-spawn-limits.patch b/patches/server/0698-add-per-world-spawn-limits.patch similarity index 100% rename from patches/server/0697-add-per-world-spawn-limits.patch rename to patches/server/0698-add-per-world-spawn-limits.patch diff --git a/patches/server/0698-Fix-PotionSplashEvent-for-water-splash-potions.patch b/patches/server/0699-Fix-PotionSplashEvent-for-water-splash-potions.patch similarity index 100% rename from patches/server/0698-Fix-PotionSplashEvent-for-water-splash-potions.patch rename to patches/server/0699-Fix-PotionSplashEvent-for-water-splash-potions.patch diff --git a/patches/server/0699-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/patches/server/0700-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch similarity index 100% rename from patches/server/0699-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch rename to patches/server/0700-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch From 89860077fa09d8c20979e6abb0fe75146c442e81 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Tue, 15 Jun 2021 01:38:41 -0700 Subject: [PATCH 153/226] Clean cache on upstream update --- scripts/upstreamMerge.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/upstreamMerge.sh b/scripts/upstreamMerge.sh index 02376dc7a2..319a71695d 100755 --- a/scripts/upstreamMerge.sh +++ b/scripts/upstreamMerge.sh @@ -34,6 +34,7 @@ fi if [ "$updated" == "1" ]; then echo "Rebuilding patches without filtering to improve apply ability" cd "$basedir" + ./gradlew cleanCache || exit 1 # todo: Figure out why this is necessary ./gradlew applyPatches -Dpaperweight.debug=true || exit 1 ./gradlew rebuildPatches || exit 1 fi From 8291fff4aced677df1b6fd2ef0bb23f313d8fde5 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Tue, 15 Jun 2021 01:38:57 -0700 Subject: [PATCH 154/226] Updated Upstream (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 CraftBukkit Changes: f992ce60 Fix duplicate datapack reload on /reload Spigot Changes: 9472b09d Rebuild patches --- patches/server/0004-Paper-config-files.patch | 9 ++++--- patches/server/0009-Timings-v2.patch | 8 +++---- patches/server/0010-Adventure.patch | 24 +++++++++---------- ...023-Further-improve-server-tick-loop.patch | 4 ++-- .../0046-Expose-server-CommandMap.patch | 4 ++-- ...llow-Reloading-of-Custom-Permissions.patch | 4 ++-- .../0061-Remove-Metadata-on-reload.patch | 4 ++-- ...setting-for-proxy-online-mode-status.patch | 4 ++-- ...1-Allow-Reloading-of-Command-Aliases.patch | 4 ++-- ...n-option-to-prevent-player-names-fro.patch | 4 ++-- ...oleAppender-for-console-improvements.patch | 6 ++--- .../server/0143-Basic-PlayerProfile-API.patch | 4 ++-- .../server/0168-AsyncTabCompleteEvent.patch | 6 ++--- .../server/0186-getPlayerUniqueId-API.patch | 4 ++-- ...dd-Early-Warning-Feature-to-WatchDog.patch | 4 ++-- ...ault-permission-message-configurable.patch | 4 ++-- ...isPrimaryThread-and-MinecraftServer-.patch | 4 ++-- ...344-Expose-the-internal-current-tick.patch | 4 ++-- ...-Add-tick-times-API-and-mspt-command.patch | 4 ++-- ...396-Expose-MinecraftServer-isRunning.patch | 4 ++-- .../0400-Improved-Watchdog-Support.patch | 4 ++-- .../server/0427-Implement-Mob-Goal-API.patch | 4 ++-- ...Wait-for-Async-Tasks-during-shutdown.patch | 4 ++-- ...llow-delegation-to-vanilla-chunk-gen.patch | 4 ++-- ...-Add-getOfflinePlayerIfCached-String.patch | 4 ++-- .../0598-Added-Vanilla-Entity-Tags.patch | 4 ++-- .../server/0616-misc-debugging-dumps.patch | 4 ++-- .../0631-Implement-Keyed-on-World.patch | 6 ++--- .../server/0670-Add-basic-Datapack-API.patch | 4 ++-- ...x-and-optimise-world-force-upgrading.patch | 6 ++--- work/CraftBukkit | 2 +- work/Spigot | 2 +- 32 files changed, 80 insertions(+), 81 deletions(-) diff --git a/patches/server/0004-Paper-config-files.patch b/patches/server/0004-Paper-config-files.patch index 1745107d79..ce5199bb6b 100644 --- a/patches/server/0004-Paper-config-files.patch +++ b/patches/server/0004-Paper-config-files.patch @@ -689,7 +689,7 @@ index b2083d26e3b239d0f26da77955db6a34b622a1bb..90854842fda0f91ac68c70efbcf8ad9e this.world = new CraftWorld((ServerLevel) this, gen, env); this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns(); // CraftBukkit diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 22391e541c0289b60372dc2531416947955fc067..6345774687d4158d58be067e968c055f0c4a01bb 100644 +index 7230982ee15d0584824e25aaad7b1adfe128e59a..933d5bd4b5871af83d2db5b52edac217fdf87188 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -809,6 +809,7 @@ public final class CraftServer implements Server { @@ -700,7 +700,7 @@ index 22391e541c0289b60372dc2531416947955fc067..6345774687d4158d58be067e968c055f for (ServerLevel world : this.console.getAllLevels()) { world.serverLevelData.setDifficulty(config.difficulty); world.setSpawnSettings(config.spawnMonsters, config.spawnAnimals); -@@ -842,6 +843,7 @@ public final class CraftServer implements Server { +@@ -842,12 +843,14 @@ public final class CraftServer implements Server { world.ticksPerAmbientSpawns = this.getTicksPerAmbientSpawns(); } world.spigotConfig.init(); // Spigot @@ -708,15 +708,14 @@ index 22391e541c0289b60372dc2531416947955fc067..6345774687d4158d58be067e968c055f } this.pluginManager.clearPlugins(); -@@ -849,6 +851,7 @@ public final class CraftServer implements Server { - this.resetRecipes(); + this.commandMap.clearCommands(); this.reloadData(); org.spigotmc.SpigotConfig.registerCommands(); // Spigot + com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); -@@ -2106,4 +2109,35 @@ public final class CraftServer implements Server { +@@ -2105,4 +2108,35 @@ public final class CraftServer implements Server { return this.spigot; } // Spigot end diff --git a/patches/server/0009-Timings-v2.patch b/patches/server/0009-Timings-v2.patch index a4e68352d9..b7a646b9e9 100644 --- a/patches/server/0009-Timings-v2.patch +++ b/patches/server/0009-Timings-v2.patch @@ -1378,7 +1378,7 @@ index b6eb04733611b63916453f36abf2ae615786845c..2db7c62d25791bc7856d007e9197f8c8 this.entityManager.saveAll(); } else { diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 73f6e956afd2a679ffda2e7e21485e0b1791ecdf..47195235a0aafeb7c5af090777b323a2685bcd5f 100644 +index 83e71d07f86c115a0df1eb56ae9f2b127821fe80..78ef2e0d9a32d38c7193859f8ee726c70c9b289e 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -209,6 +209,7 @@ import org.bukkit.inventory.EquipmentSlot; @@ -1457,7 +1457,7 @@ index 01f3267c086837cbbc311d62974ecb034e429c23..34e386efda7ea52fb6f53333eda0f015 public UserWhiteList getWhiteList() { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 2ad8e9ada3ba68c107931793846b4e8284b1ab06..2bfafeec6f8a605a7826091314992e61a49e4c51 100644 +index 2e90d3e79fdc5707aa5467c6270374e05b280ab3..ac1c81c964c51256c82397668b39447a36a10914 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -126,7 +126,6 @@ import org.bukkit.craftbukkit.event.CraftPortalEvent; @@ -1838,10 +1838,10 @@ index 468b67babc628f7ff7c6fa138ed7944a8d77f0a6..22d5c4cc3aea19cbf53ea320765ecceb private static CompoundTag packStructureData(ServerLevel world, ChunkPos chunkcoordintpair, Map, StructureStart> map, Map, LongSet> map1) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6345774687d4158d58be067e968c055f0c4a01bb..b1b44efbe0ad16619a32991f594b928a82d53278 100644 +index 933d5bd4b5871af83d2db5b52edac217fdf87188..bcd056ac91775c72809284bbc20c366e1ca31350 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2078,12 +2078,31 @@ public final class CraftServer implements Server { +@@ -2077,12 +2077,31 @@ public final class CraftServer implements Server { private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() { diff --git a/patches/server/0010-Adventure.patch b/patches/server/0010-Adventure.patch index 1da3dba942..9e9cff360c 100644 --- a/patches/server/0010-Adventure.patch +++ b/patches/server/0010-Adventure.patch @@ -1140,7 +1140,7 @@ index 762a9392ffac3042356709dddd15bb3516048bed..3544e2dc2522e9d6305d727d56e73490 buf.writeComponent(this.footer); } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 59e58647e0650997b523a683aa52cb922a1d9c51..ab62111ebafad77c3dc739185f907a19e9f911db 100644 +index 99292d239dfdd2c0aaeece2b526db011b17aa121..a8fae13b18c1619f898e818b749c02c647f164c5 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -145,6 +145,7 @@ import net.minecraft.world.scores.Score; @@ -1215,7 +1215,7 @@ index 59e58647e0650997b523a683aa52cb922a1d9c51..ab62111ebafad77c3dc739185f907a19 // CraftBukkit end this.chatVisibility = packet.getChatVisibility(); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 47195235a0aafeb7c5af090777b323a2685bcd5f..c58f8cf20822439098648265917801509dda1a72 100644 +index 78ef2e0d9a32d38c7193859f8ee726c70c9b289e..3e89612f4bf74179b3461166b17b42af2e59b8e5 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -162,6 +162,8 @@ import org.apache.logging.log4j.LogManager; @@ -1542,7 +1542,7 @@ index d5b8931243e2f9cac9b0f92ab8df043a831bbe70..ac05b201167d8e17f39d3df732adf676 MutableComponent ichatmutablecomponent = (new TextComponent("")).append(this.getHoverName()); diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -index 75d52cc90a015588ffbbae77b4c272f938a7c0a9..6d3df3d1bcaa016611320e7ba1f005e71bf0bfdf 100644 +index 5a662dd8a05be01cbb232c3dee65d660c9b19a98..07a83fc6f9a83889a0a3b8c714be68302e700a0f 100644 --- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java @@ -95,6 +95,7 @@ public abstract class Enchantment { @@ -1575,7 +1575,7 @@ index 7a0e7961df1e62b311ea2ecc76d7343a8646723b..6859fafa42527d45366018f737c19e6c } collection = icons; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index b1b44efbe0ad16619a32991f594b928a82d53278..d2e2e0cab3035a6a458fde75e9fcf72b2d1e77dd 100644 +index bcd056ac91775c72809284bbc20c366e1ca31350..e2564dee0603735d135d1de2af6801a0f2a93e7d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -564,8 +564,10 @@ public final class CraftServer implements Server { @@ -1589,7 +1589,7 @@ index b1b44efbe0ad16619a32991f594b928a82d53278..d2e2e0cab3035a6a458fde75e9fcf72b } public Player getPlayer(final ServerPlayer entity) { -@@ -1310,7 +1312,15 @@ public final class CraftServer implements Server { +@@ -1309,7 +1311,15 @@ public final class CraftServer implements Server { return this.configuration.getInt("settings.spawn-radius", -1); } @@ -1605,7 +1605,7 @@ index b1b44efbe0ad16619a32991f594b928a82d53278..d2e2e0cab3035a6a458fde75e9fcf72b public String getShutdownMessage() { return this.configuration.getString("settings.shutdown-message"); } -@@ -1427,7 +1437,20 @@ public final class CraftServer implements Server { +@@ -1426,7 +1436,20 @@ public final class CraftServer implements Server { } @Override @@ -1626,7 +1626,7 @@ index b1b44efbe0ad16619a32991f594b928a82d53278..d2e2e0cab3035a6a458fde75e9fcf72b Set recipients = new HashSet<>(); for (Permissible permissible : this.getPluginManager().getPermissionSubscriptions(permission)) { if (permissible instanceof CommandSender && permissible.hasPermission(permission)) { -@@ -1435,14 +1458,14 @@ public final class CraftServer implements Server { +@@ -1434,14 +1457,14 @@ public final class CraftServer implements Server { } } @@ -1643,7 +1643,7 @@ index b1b44efbe0ad16619a32991f594b928a82d53278..d2e2e0cab3035a6a458fde75e9fcf72b for (CommandSender recipient : recipients) { recipient.sendMessage(message); -@@ -1668,6 +1691,14 @@ public final class CraftServer implements Server { +@@ -1667,6 +1690,14 @@ public final class CraftServer implements Server { return CraftInventoryCreator.INSTANCE.createInventory(owner, type); } @@ -1658,7 +1658,7 @@ index b1b44efbe0ad16619a32991f594b928a82d53278..d2e2e0cab3035a6a458fde75e9fcf72b @Override public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); -@@ -1680,13 +1711,28 @@ public final class CraftServer implements Server { +@@ -1679,13 +1710,28 @@ public final class CraftServer implements Server { return CraftInventoryCreator.INSTANCE.createInventory(owner, size); } @@ -1687,7 +1687,7 @@ index b1b44efbe0ad16619a32991f594b928a82d53278..d2e2e0cab3035a6a458fde75e9fcf72b public Merchant createMerchant(String title) { return new CraftMerchantCustom(title == null ? InventoryType.MERCHANT.getDefaultTitle() : title); } -@@ -1730,6 +1776,12 @@ public final class CraftServer implements Server { +@@ -1729,6 +1775,12 @@ public final class CraftServer implements Server { return Thread.currentThread().equals(console.serverThread) || this.console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog) } @@ -1700,7 +1700,7 @@ index b1b44efbe0ad16619a32991f594b928a82d53278..d2e2e0cab3035a6a458fde75e9fcf72b @Override public String getMotd() { return this.console.getMotd(); -@@ -2158,5 +2210,15 @@ public final class CraftServer implements Server { +@@ -2157,5 +2209,15 @@ public final class CraftServer implements Server { return null; } } @@ -2336,7 +2336,7 @@ index 969d5071dbf3356b80da38526351d488ab936c08..f1f35eeff46f6573b79f1190265a908e private final Player.Spigot spigot = new Player.Spigot() { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index ad68b85f5aec00b5fc266a97880fc38c93073af3..e96ce62978e2cca454f797c4ce1ab1d306f9d7e4 100644 +index e260366ca4f0ba7f37b7e78e3b46a05d91079d8d..ae12d4a7b56ec70ac5f529e0f336019e97f667ce 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -787,9 +787,9 @@ public class CraftEventFactory { diff --git a/patches/server/0023-Further-improve-server-tick-loop.patch b/patches/server/0023-Further-improve-server-tick-loop.patch index 2baf296734..08d8d108b2 100644 --- a/patches/server/0023-Further-improve-server-tick-loop.patch +++ b/patches/server/0023-Further-improve-server-tick-loop.patch @@ -143,10 +143,10 @@ index 3a9d77a190ef96c06717ee00bcfba52b8f984c14..ca439ac2a09a2ce4e019282c0b75f2f5 this.startMetricsRecordingTick(); this.profiler.push("tick"); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index cbf84099f473115559c5344782618c2ab9c86582..4612557dfe8c81e6a9b6f11dc1c8d40eaa1337ec 100644 +index f00844d2953e6ead58bfd383a214695b3dbe5086..477097955ad36b2639f6304f762a529a1989ba5e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2126,6 +2126,17 @@ public final class CraftServer implements Server { +@@ -2125,6 +2125,17 @@ public final class CraftServer implements Server { return CraftMagicNumbers.INSTANCE; } diff --git a/patches/server/0046-Expose-server-CommandMap.patch b/patches/server/0046-Expose-server-CommandMap.patch index 52cd616fd2..a90544071d 100644 --- a/patches/server/0046-Expose-server-CommandMap.patch +++ b/patches/server/0046-Expose-server-CommandMap.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose server CommandMap diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 452904333ce232855d61ff7d12cb8a5595ebb3f8..4b6e6f120edc0e2c3dd3f81c5b9fb96980e41a33 100644 +index 7154b5151375574a10e079b70dbd210d698f1d27..ae810acb2d54fc589ff59bbf97e3fbf86f76955c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1764,6 +1764,7 @@ public final class CraftServer implements Server { +@@ -1763,6 +1763,7 @@ public final class CraftServer implements Server { return this.helpMap; } diff --git a/patches/server/0060-Allow-Reloading-of-Custom-Permissions.patch b/patches/server/0060-Allow-Reloading-of-Custom-Permissions.patch index ef582a4eaa..ab14a1c735 100644 --- a/patches/server/0060-Allow-Reloading-of-Custom-Permissions.patch +++ b/patches/server/0060-Allow-Reloading-of-Custom-Permissions.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Allow Reloading of Custom Permissions https://github.com/PaperMC/Paper/issues/49 diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 7e990ec783440ae7ca706bdd315305fe088a7cbe..0147b2b903e59e4689fa1a88f13c06942233379f 100644 +index a9ca1e44eca6691e41c6b443f8953e77dbde62b2..610af41f33a41bd0465eace2c3e2b6ed8eeceac7 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2256,5 +2256,23 @@ public final class CraftServer implements Server { +@@ -2255,5 +2255,23 @@ public final class CraftServer implements Server { } return this.adventure$audiences; } diff --git a/patches/server/0061-Remove-Metadata-on-reload.patch b/patches/server/0061-Remove-Metadata-on-reload.patch index b19a0304d8..89fd73426a 100644 --- a/patches/server/0061-Remove-Metadata-on-reload.patch +++ b/patches/server/0061-Remove-Metadata-on-reload.patch @@ -7,7 +7,7 @@ Metadata is not meant to persist reload as things break badly with non primitive This will remove metadata on reload so it does not crash everything if a plugin uses it. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 448e750974f9e15e5222ffa1c2d342c1f0a84a1e..95689d11668e37a894b70517270849c2c4e162aa 100644 +index 610af41f33a41bd0465eace2c3e2b6ed8eeceac7..568777b6cad6f87f1ad7be361ebe47a6bc55cb2d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -872,8 +872,16 @@ public final class CraftServer implements Server { @@ -24,6 +24,6 @@ index 448e750974f9e15e5222ffa1c2d342c1f0a84a1e..95689d11668e37a894b70517270849c2 + playerMetadata.removeAll(plugin); + } + // Paper end - this.resetRecipes(); this.reloadData(); org.spigotmc.SpigotConfig.registerCommands(); // Spigot + com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper diff --git a/patches/server/0101-Add-setting-for-proxy-online-mode-status.patch b/patches/server/0101-Add-setting-for-proxy-online-mode-status.patch index 8942648247..a64f11a6f0 100644 --- a/patches/server/0101-Add-setting-for-proxy-online-mode-status.patch +++ b/patches/server/0101-Add-setting-for-proxy-online-mode-status.patch @@ -67,10 +67,10 @@ index 8e27b43e2f6ce4d7f5007fe02db1722e73c30a58..6aacc724c8c8d6fbe3067226989039ca } else { String[] astring1 = astring; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6deff28585dfc2f541a34f00ba2efad0f907dc71..28b64d39828ef484b6085f1cc793746d4438976d 100644 +index 568777b6cad6f87f1ad7be361ebe47a6bc55cb2d..6387f01a9aeb72817988d1609188ca20b5ca4f6e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1517,7 +1517,7 @@ public final class CraftServer implements Server { +@@ -1516,7 +1516,7 @@ public final class CraftServer implements Server { // Spigot Start GameProfile profile = null; // Only fetch an online UUID in online mode diff --git a/patches/server/0111-Allow-Reloading-of-Command-Aliases.patch b/patches/server/0111-Allow-Reloading-of-Command-Aliases.patch index ad8f7479e4..4fd8e9f05f 100644 --- a/patches/server/0111-Allow-Reloading-of-Command-Aliases.patch +++ b/patches/server/0111-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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 28b64d39828ef484b6085f1cc793746d4438976d..eec2b587cc9cfb9e5d66d89c2763115e9d260cc2 100644 +index 6387f01a9aeb72817988d1609188ca20b5ca4f6e..25cdff21377fdd9d3daf6af8da1f3db4ed65dab6 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2282,5 +2282,24 @@ public final class CraftServer implements Server { +@@ -2281,5 +2281,24 @@ public final class CraftServer implements Server { DefaultPermissions.registerCorePermissions(); CraftDefaultPermissions.registerCorePermissions(); } diff --git a/patches/server/0136-Add-configuration-option-to-prevent-player-names-fro.patch b/patches/server/0136-Add-configuration-option-to-prevent-player-names-fro.patch index 179d0f9168..aa73138ef9 100644 --- a/patches/server/0136-Add-configuration-option-to-prevent-player-names-fro.patch +++ b/patches/server/0136-Add-configuration-option-to-prevent-player-names-fro.patch @@ -20,10 +20,10 @@ index 4e2f243faa209925dcb7c3ef89df3ed875c5ff78..48319aaf1c525c6fb7bdee5c2f570a0d + } } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index eec2b587cc9cfb9e5d66d89c2763115e9d260cc2..ec81cbf3362202aca7c57af2ca013a7c433677f9 100644 +index 25cdff21377fdd9d3daf6af8da1f3db4ed65dab6..8bd458b8995c9019b5ae85eab062df44e9424703 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2301,5 +2301,10 @@ public final class CraftServer implements Server { +@@ -2300,5 +2300,10 @@ public final class CraftServer implements Server { commandMap.registerServerAliases(); return true; } diff --git a/patches/server/0137-Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server/0137-Use-TerminalConsoleAppender-for-console-improvements.patch index 0e174e6fc9..a4ec9e1c30 100644 --- a/patches/server/0137-Use-TerminalConsoleAppender-for-console-improvements.patch +++ b/patches/server/0137-Use-TerminalConsoleAppender-for-console-improvements.patch @@ -19,7 +19,7 @@ Other changes: configuration diff --git a/build.gradle.kts b/build.gradle.kts -index e7fdc8ee6024608605fe04b9df851c17cd615e10..ce7c6a3604e11642c27cbb645ee648dc2f8d6701 100644 +index 07be9eb1dd7f0f85e8a36cc4e8df807bae989372..2d016978c4e2ee2d222b177ccdb1f356ffd60db1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -21,7 +21,17 @@ repositories { @@ -244,7 +244,7 @@ index 79ebb15bed6eec80c12c1020b2b6b07c758332aa..bf6c3ac7ae37067f345568fb6656cf6b this.bans = new UserBanList(PlayerList.USERBANLIST_FILE); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index ec81cbf3362202aca7c57af2ca013a7c433677f9..ebc3cba0b221a98bd4a5f831dafa856594d0c0bd 100644 +index 8bd458b8995c9019b5ae85eab062df44e9424703..79fe58b09c9e0870a5ab55bc21b8ab933450a1d7 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -46,7 +46,6 @@ import java.util.function.Consumer; @@ -263,7 +263,7 @@ index ec81cbf3362202aca7c57af2ca013a7c433677f9..ebc3cba0b221a98bd4a5f831dafa8565 import net.minecraft.server.MinecraftServer; import net.minecraft.server.bossevents.CustomBossEvent; import net.minecraft.server.commands.ReloadCommand; -@@ -1205,9 +1205,13 @@ public final class CraftServer implements Server { +@@ -1204,9 +1204,13 @@ public final class CraftServer implements Server { return this.logger; } diff --git a/patches/server/0143-Basic-PlayerProfile-API.patch b/patches/server/0143-Basic-PlayerProfile-API.patch index a8b4917409..2cc20ab20a 100644 --- a/patches/server/0143-Basic-PlayerProfile-API.patch +++ b/patches/server/0143-Basic-PlayerProfile-API.patch @@ -500,7 +500,7 @@ index 3eb4bee81a8543cc06b9d5898f5f6c0e9dbbf554..8ea7d9a2070074a45d3276b8d2abac62 public GameProfile get(UUID uuid) { GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 76856f3648e8cb881653a94bf6e8e4310c97be2d..754e10be4f62ee3efac34bea3c72e23b1b06053c 100644 +index 2f25e4c26f2f418de738ba2fcf7f2485bb2dda3c..46972308cf399ed02c450bc2d45b4dc88b234ab0 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -226,6 +226,9 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; @@ -513,7 +513,7 @@ index 76856f3648e8cb881653a94bf6e8e4310c97be2d..754e10be4f62ee3efac34bea3c72e23b public final class CraftServer implements Server { private final String serverName = "Paper"; // Paper private final String serverVersion; -@@ -2316,5 +2319,24 @@ public final class CraftServer implements Server { +@@ -2315,5 +2318,24 @@ public final class CraftServer implements Server { public boolean suggestPlayerNamesWhenNullTabCompletions() { return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; } diff --git a/patches/server/0168-AsyncTabCompleteEvent.patch b/patches/server/0168-AsyncTabCompleteEvent.patch index c0a87f996b..d51ba56fd0 100644 --- a/patches/server/0168-AsyncTabCompleteEvent.patch +++ b/patches/server/0168-AsyncTabCompleteEvent.patch @@ -14,7 +14,7 @@ completion, such as offline players. Also adds isCommand and getLocation to the sync TabCompleteEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 985736fc4e3d702a1fd787336db8ab18ee2a4783..5b426265d62063544f0104c8c9f8061d002bc56c 100644 +index c2f614b64482be75b28d47e79b0531a9143a157d..413bf8504821d4605e940f865332e8dd77acb436 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -703,10 +703,10 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @@ -72,10 +72,10 @@ index 985736fc4e3d702a1fd787336db8ab18ee2a4783..5b426265d62063544f0104c8c9f8061d @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 754e10be4f62ee3efac34bea3c72e23b1b06053c..8e93f6398a5974676a479e17f31a8e77c461fb41 100644 +index 46972308cf399ed02c450bc2d45b4dc88b234ab0..c7dbe127e30cc6830794c3a81686908f076160ac 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1851,7 +1851,7 @@ public final class CraftServer implements Server { +@@ -1850,7 +1850,7 @@ public final class CraftServer implements Server { offers = this.tabCompleteChat(player, message); } diff --git a/patches/server/0186-getPlayerUniqueId-API.patch b/patches/server/0186-getPlayerUniqueId-API.patch index 0db33e015e..2e83e5c893 100644 --- a/patches/server/0186-getPlayerUniqueId-API.patch +++ b/patches/server/0186-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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 8e93f6398a5974676a479e17f31a8e77c461fb41..b12fb31d9a601c1781b0cb0a24bdd9cbcc4f382b 100644 +index c7dbe127e30cc6830794c3a81686908f076160ac..8f2c7ca033a7c162395b6e5114895836e10534ab 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1519,6 +1519,25 @@ public final class CraftServer implements Server { +@@ -1518,6 +1518,25 @@ public final class CraftServer implements Server { return recipients.size(); } diff --git a/patches/server/0244-Add-Early-Warning-Feature-to-WatchDog.patch b/patches/server/0244-Add-Early-Warning-Feature-to-WatchDog.patch index 2656d34b76..4b271ce3d9 100644 --- a/patches/server/0244-Add-Early-Warning-Feature-to-WatchDog.patch +++ b/patches/server/0244-Add-Early-Warning-Feature-to-WatchDog.patch @@ -48,7 +48,7 @@ index 050b27be1c25764d65e5340149718e858b3aeb2e..880fc4e346549a5d7ed627244bdfd284 long start = System.nanoTime(), curTime, tickSection = start; // Paper - Further improve server tick loop lastTick = start - TICK_TIME; // Paper diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index b12fb31d9a601c1781b0cb0a24bdd9cbcc4f382b..16645b4c096936c4d5c00f335e5cdb7dd4a4e2bd 100644 +index 8f2c7ca033a7c162395b6e5114895836e10534ab..e22b073a7a5f35a8edf58946144d1f1e9d94b6e3 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -810,6 +810,7 @@ public final class CraftServer implements Server { @@ -59,7 +59,7 @@ index b12fb31d9a601c1781b0cb0a24bdd9cbcc4f382b..16645b4c096936c4d5c00f335e5cdb7d this.reloadCount++; this.configuration = YamlConfiguration.loadConfiguration(this.getConfigFile()); this.commandsConfiguration = YamlConfiguration.loadConfiguration(this.getCommandsConfigFile()); -@@ -926,6 +927,7 @@ public final class CraftServer implements Server { +@@ -925,6 +926,7 @@ public final class CraftServer implements Server { this.enablePlugins(PluginLoadOrder.STARTUP); this.enablePlugins(PluginLoadOrder.POSTWORLD); this.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.RELOAD)); diff --git a/patches/server/0293-Make-the-default-permission-message-configurable.patch b/patches/server/0293-Make-the-default-permission-message-configurable.patch index 16f546dd5d..bec69b632a 100644 --- a/patches/server/0293-Make-the-default-permission-message-configurable.patch +++ b/patches/server/0293-Make-the-default-permission-message-configurable.patch @@ -30,10 +30,10 @@ index 9768c591e72ce2ef5fdb43e2fc63378c57773216..11d628869a9a6eda8bf21a4f213ff23a Object val = config.get("settings.save-player-data"); if (val instanceof Boolean) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 717ad1c24bbc882db8f76cfef7bf847c58914e5a..0448e6b4c512f512bda13f41f1feb58de02fc9d4 100644 +index 7f1d5725e156b9cf3273aa0f66c1e0d486df6a51..d9bfaff4880de1254a72869562b4c42aa29146f1 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2341,6 +2341,11 @@ public final class CraftServer implements Server { +@@ -2340,6 +2340,11 @@ public final class CraftServer implements Server { return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; } diff --git a/patches/server/0327-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/patches/server/0327-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch index 92eb435a4a..427be5b0c0 100644 --- a/patches/server/0327-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch +++ b/patches/server/0327-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch @@ -29,10 +29,10 @@ index eb103c15218c334b9f85a57e30582e9efb188704..c8a59de4673d430fc8ec2e53315f1072 public boolean isDebugging() { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0448e6b4c512f512bda13f41f1feb58de02fc9d4..58d7fec472dd8c8d7775eb6d931be29871102054 100644 +index d9bfaff4880de1254a72869562b4c42aa29146f1..334ea92dd16bf325961afd92e835e63163cbcecb 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1840,7 +1840,7 @@ public final class CraftServer implements Server { +@@ -1839,7 +1839,7 @@ public final class CraftServer implements Server { @Override public boolean isPrimaryThread() { diff --git a/patches/server/0344-Expose-the-internal-current-tick.patch b/patches/server/0344-Expose-the-internal-current-tick.patch index 0382311058..fadde9f694 100644 --- a/patches/server/0344-Expose-the-internal-current-tick.patch +++ b/patches/server/0344-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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 58d7fec472dd8c8d7775eb6d931be29871102054..9730c701b734eb3491bc1fa5d9bb81ddfefc910a 100644 +index 334ea92dd16bf325961afd92e835e63163cbcecb..39e6db52421528f16ac4595faa8cfcf191771c77 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2364,5 +2364,10 @@ public final class CraftServer implements Server { +@@ -2363,5 +2363,10 @@ public final class CraftServer implements Server { } return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); } diff --git a/patches/server/0395-Add-tick-times-API-and-mspt-command.patch b/patches/server/0395-Add-tick-times-API-and-mspt-command.patch index 81685ed79c..13c6d25f13 100644 --- a/patches/server/0395-Add-tick-times-API-and-mspt-command.patch +++ b/patches/server/0395-Add-tick-times-API-and-mspt-command.patch @@ -146,10 +146,10 @@ index fa3a9d763f7072c68b126ce95fee191aab576e43..91ae80ee1020dc017faef7c8be848713 + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 9730c701b734eb3491bc1fa5d9bb81ddfefc910a..6eebbe2d7948a164f9562801b727768d199fa228 100644 +index 39e6db52421528f16ac4595faa8cfcf191771c77..bc5034eff1e9d41c97a210b3b53c188395cb2574 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2202,6 +2202,16 @@ public final class CraftServer implements Server { +@@ -2201,6 +2201,16 @@ public final class CraftServer implements Server { net.minecraft.server.MinecraftServer.getServer().tps15.getAverage() }; } diff --git a/patches/server/0396-Expose-MinecraftServer-isRunning.patch b/patches/server/0396-Expose-MinecraftServer-isRunning.patch index eee93a6749..6474701813 100644 --- a/patches/server/0396-Expose-MinecraftServer-isRunning.patch +++ b/patches/server/0396-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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6eebbe2d7948a164f9562801b727768d199fa228..3423de396e0fadfa29714f5fcac4b579a8ff0967 100644 +index bc5034eff1e9d41c97a210b3b53c188395cb2574..2c8c800f04793493515782722d706db6e5f861af 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2379,5 +2379,10 @@ public final class CraftServer implements Server { +@@ -2378,5 +2378,10 @@ public final class CraftServer implements Server { public int getCurrentTick() { return net.minecraft.server.MinecraftServer.currentTick; } diff --git a/patches/server/0400-Improved-Watchdog-Support.patch b/patches/server/0400-Improved-Watchdog-Support.patch index 4f5188cdf9..17dd04331c 100644 --- a/patches/server/0400-Improved-Watchdog-Support.patch +++ b/patches/server/0400-Improved-Watchdog-Support.patch @@ -323,10 +323,10 @@ index 59a77541bbda880ae8f84e3535a2b6112caa78fb..a63dc77db41dab79f03ef7384da55c1c String msg = "TileEntity threw exception at " + LevelChunk.this.getLevel().getWorld().getName() + ":" + this.getPos().getX() + "," + this.getPos().getY() + "," + this.getPos().getZ(); System.err.println(msg); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 3423de396e0fadfa29714f5fcac4b579a8ff0967..4c0b94a56fab161fca92b594f55e1c846524d5e8 100644 +index 2c8c800f04793493515782722d706db6e5f861af..e31a05dfe7e934692ac89c7cedcab736bcd9ca4f 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1840,7 +1840,7 @@ public final class CraftServer implements Server { +@@ -1839,7 +1839,7 @@ public final class CraftServer implements Server { @Override public boolean isPrimaryThread() { diff --git a/patches/server/0427-Implement-Mob-Goal-API.patch b/patches/server/0427-Implement-Mob-Goal-API.patch index 49390dd06e..c9e7137219 100644 --- a/patches/server/0427-Implement-Mob-Goal-API.patch +++ b/patches/server/0427-Implement-Mob-Goal-API.patch @@ -933,10 +933,10 @@ index bcb2c5480872eef6f21746003380f71b8d44f5c8..bcd0da029edd9b1d6f3617ee20dac00c private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. private final com.destroystokyo.paper.util.set.OptimizedSmallEnumSet goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 479b4eb8efeeca432bcb21925db18d5c0750f001..4d6a6583af73a25b5f2783ba56a63b8c9987c0a4 100644 +index 130ab05393a7136020e06ec199256a031ba66091..8dd93620a770855450ed222dad6572e20760b08c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2391,5 +2391,11 @@ public final class CraftServer implements Server { +@@ -2390,5 +2390,11 @@ public final class CraftServer implements Server { public boolean isStopping() { return net.minecraft.server.MinecraftServer.getServer().hasStopped(); } diff --git a/patches/server/0436-Wait-for-Async-Tasks-during-shutdown.patch b/patches/server/0436-Wait-for-Async-Tasks-during-shutdown.patch index cc6436b194..9f0cd39123 100644 --- a/patches/server/0436-Wait-for-Async-Tasks-during-shutdown.patch +++ b/patches/server/0436-Wait-for-Async-Tasks-during-shutdown.patch @@ -22,10 +22,10 @@ index d7023cb0974f6c28a0fb8a0a6e5a6600fe30d3e3..11dbe48c8a8c29cd28d725c43505e326 // CraftBukkit end if (this.getConnection() != null) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 4d6a6583af73a25b5f2783ba56a63b8c9987c0a4..94670ec4de01341822f6affe0fa1c9774dd6131b 100644 +index 8dd93620a770855450ed222dad6572e20760b08c..e3338717bffe5f5e4a00fe1ebe3ba7cf74555b36 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -937,6 +937,35 @@ public final class CraftServer implements Server { +@@ -936,6 +936,35 @@ public final class CraftServer implements Server { org.spigotmc.WatchdogThread.hasStarted = true; // Paper - Disable watchdog early timeout on reload } diff --git a/patches/server/0480-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/0480-Allow-delegation-to-vanilla-chunk-gen.patch index 840cdeb9ac..ef0cf459b5 100644 --- a/patches/server/0480-Allow-delegation-to-vanilla-chunk-gen.patch +++ b/patches/server/0480-Allow-delegation-to-vanilla-chunk-gen.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow delegation to vanilla chunk gen diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6bc5ba51c90723c7138b1b5d2381cb215f1e5271..beb8b7d06ef47c80ede95c884598fedcc7126d67 100644 +index f7d542b828904fb51a30dfb7a50e01e4e2df0f3e..407a91f64e040745dea17544d6b7c6d125866c62 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2033,6 +2033,32 @@ public final class CraftServer implements Server { +@@ -2032,6 +2032,32 @@ public final class CraftServer implements Server { return new CraftChunkData(world); } diff --git a/patches/server/0536-Add-getOfflinePlayerIfCached-String.patch b/patches/server/0536-Add-getOfflinePlayerIfCached-String.patch index 9c08b509fc..0952d7bbac 100644 --- a/patches/server/0536-Add-getOfflinePlayerIfCached-String.patch +++ b/patches/server/0536-Add-getOfflinePlayerIfCached-String.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add getOfflinePlayerIfCached(String) diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 7795735e5acc3b7b6b71b4e61bdc4bdcb722a7b3..ecae20bb39848cc0223df3c4804a68f4e0731e3b 100644 +index c4d7ac8abd7d86e8a4e2d8a3340d04f8710e925c..0d29e3163a637c742d100129cb650f53635ef765 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1613,6 +1613,28 @@ public final class CraftServer implements Server { +@@ -1612,6 +1612,28 @@ public final class CraftServer implements Server { return result; } diff --git a/patches/server/0598-Added-Vanilla-Entity-Tags.patch b/patches/server/0598-Added-Vanilla-Entity-Tags.patch index 25885466ab..09623d60c9 100644 --- a/patches/server/0598-Added-Vanilla-Entity-Tags.patch +++ b/patches/server/0598-Added-Vanilla-Entity-Tags.patch @@ -39,10 +39,10 @@ index 0000000000000000000000000000000000000000..6271586368c65250c887739d04c5fccf + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index ecae20bb39848cc0223df3c4804a68f4e0731e3b..726db110f27ce46b8ed9c78dad14542bba1622a8 100644 +index 0d29e3163a637c742d100129cb650f53635ef765..4739b4c3035064de328595329ee0b65ea59e559b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2222,6 +2222,11 @@ public final class CraftServer implements Server { +@@ -2221,6 +2221,11 @@ public final class CraftServer implements Server { Preconditions.checkArgument(clazz == org.bukkit.Fluid.class, "Fluid namespace must have fluid type"); return (org.bukkit.Tag) new CraftFluidTag(FluidTags.getAllTags(), key); diff --git a/patches/server/0616-misc-debugging-dumps.patch b/patches/server/0616-misc-debugging-dumps.patch index 3b8113783b..5e9c0b75bf 100644 --- a/patches/server/0616-misc-debugging-dumps.patch +++ b/patches/server/0616-misc-debugging-dumps.patch @@ -58,10 +58,10 @@ index c8213692e658f6eb82d3bd843b9525ff6565cc81..f1c1d715d509aeb13e465cd57a82896d this.running = false; if (flag) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 726db110f27ce46b8ed9c78dad14542bba1622a8..40496bc7b1ce71c898078f7713600ac05922dcf1 100644 +index 4739b4c3035064de328595329ee0b65ea59e559b..989b6b91dc046e20332f0cef35105b290fdb2e43 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -936,6 +936,7 @@ public final class CraftServer implements Server { +@@ -935,6 +935,7 @@ public final class CraftServer implements Server { plugin.getDescription().getName(), "This plugin is not properly shutting down its async tasks when it is being reloaded. This may cause conflicts with the newly loaded version of the plugin" )); diff --git a/patches/server/0631-Implement-Keyed-on-World.patch b/patches/server/0631-Implement-Keyed-on-World.patch index 8b4d4dd266..7df0d16a39 100644 --- a/patches/server/0631-Implement-Keyed-on-World.patch +++ b/patches/server/0631-Implement-Keyed-on-World.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Implement Keyed on World diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 40496bc7b1ce71c898078f7713600ac05922dcf1..bd7db12503c3175c3bd71f8a0fe3a826eb043000 100644 +index 989b6b91dc046e20332f0cef35105b290fdb2e43..fb18b1f0bbc5b87f6895086f6d6a749543caf11f 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1155,7 +1155,7 @@ public final class CraftServer implements Server { +@@ -1154,7 +1154,7 @@ public final class CraftServer implements Server { } else if (name.equals(levelName + "_the_end")) { worldKey = net.minecraft.world.level.Level.END; } else { @@ -17,7 +17,7 @@ index 40496bc7b1ce71c898078f7713600ac05922dcf1..bd7db12503c3175c3bd71f8a0fe3a826 } ServerLevel internal = (ServerLevel) new ServerLevel(this.console, console.executor, worldSession, worlddata, worldKey, dimensionmanager, this.getServer().progressListenerFactory.create(11), -@@ -1246,6 +1246,15 @@ public final class CraftServer implements Server { +@@ -1245,6 +1245,15 @@ public final class CraftServer implements Server { return null; } diff --git a/patches/server/0670-Add-basic-Datapack-API.patch b/patches/server/0670-Add-basic-Datapack-API.patch index 5ec36d4c3b..6142f156a3 100644 --- a/patches/server/0670-Add-basic-Datapack-API.patch +++ b/patches/server/0670-Add-basic-Datapack-API.patch @@ -92,7 +92,7 @@ index 0000000000000000000000000000000000000000..cf4374493c11057451a62a655514415c + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index bd7db12503c3175c3bd71f8a0fe3a826eb043000..2f914ebd18764fbfd3834c0a94cedb2184f8dbb0 100644 +index fb18b1f0bbc5b87f6895086f6d6a749543caf11f..b7db2d68deeee0a213ee26e31475f05ba16d073e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -266,6 +266,7 @@ public final class CraftServer implements Server { @@ -111,7 +111,7 @@ index bd7db12503c3175c3bd71f8a0fe3a826eb043000..2f914ebd18764fbfd3834c0a94cedb21 } public boolean getCommandBlockOverride(String command) { -@@ -2496,5 +2498,11 @@ public final class CraftServer implements Server { +@@ -2495,5 +2497,11 @@ public final class CraftServer implements Server { public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { return mobGoals; } diff --git a/patches/server/0676-Fix-and-optimise-world-force-upgrading.patch b/patches/server/0676-Fix-and-optimise-world-force-upgrading.patch index 8c5f11e07b..83bea4ae22 100644 --- a/patches/server/0676-Fix-and-optimise-world-force-upgrading.patch +++ b/patches/server/0676-Fix-and-optimise-world-force-upgrading.patch @@ -349,10 +349,10 @@ index 1bee455235ece8aa299a2baeede027d251e6ff57..60ae9395591c81aebaa4be1541380a8f return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 59c352f9666ff9b828450a62f590ab637b4329b5..e5135b5cffc39fa63cb9a78274c026a0b5fddaf8 100644 +index ca28dda0f9819e8d75fbaa48cf5ff5643910999a..8a98bd1018afd934696fedbed24e271ab6b75f51 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1143,14 +1143,7 @@ public final class CraftServer implements Server { +@@ -1142,14 +1142,7 @@ public final class CraftServer implements Server { } worlddata.checkName(name); worlddata.setModdedInfo(this.console.getServerModName(), this.console.getModdedStatus().isPresent()); @@ -368,7 +368,7 @@ index 59c352f9666ff9b828450a62f590ab637b4329b5..e5135b5cffc39fa63cb9a78274c026a0 long j = BiomeManager.obfuscateSeed(creator.seed()); List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata)); -@@ -1167,6 +1160,14 @@ public final class CraftServer implements Server { +@@ -1166,6 +1159,14 @@ public final class CraftServer implements Server { chunkgenerator = worlddimension.generator(); } diff --git a/work/CraftBukkit b/work/CraftBukkit index 622cf61119..f992ce6097 160000 --- a/work/CraftBukkit +++ b/work/CraftBukkit @@ -1 +1 @@ -Subproject commit 622cf6111905e787add191b9a88d62656439ef31 +Subproject commit f992ce6097f846ed5967fc797d98ae3e84ef1b10 diff --git a/work/Spigot b/work/Spigot index 66f9d3c17b..9472b09d5f 160000 --- a/work/Spigot +++ b/work/Spigot @@ -1 +1 @@ -Subproject commit 66f9d3c17bd578dacbb87702cc0347148696e105 +Subproject commit 9472b09d5fa46afc41871d063689b5ddd89764b3 From df2247b2ed5022561a0465da9b3c7a28a861ab87 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Tue, 15 Jun 2021 03:13:30 -0700 Subject: [PATCH 155/226] Remove sync loading of spawn chunks Adding the tickets is sufficient --- ...9-Configurable-Keep-Spawn-Loaded-range-per-world.patch | 8 ++------ ...event-Double-PlayerChunkMap-adds-crashing-server.patch | 6 +++--- ...ix-SpawnChangeEvent-not-firing-for-all-use-cases.patch | 4 ++-- patches/server/0588-Remove-stale-POIs.patch | 4 ++-- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch index bbd5eacb22..ce2f3b24c8 100644 --- a/patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ b/patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -85,7 +85,7 @@ index c8a59de4673d430fc8ec2e53315f107293122e7e..40e48c3f1199b127066732e3c8a6d40c // CraftBukkit start // this.updateSpawnFlags(); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index c64557c70122bff6ea0c8d0b34f62daf680e4334..c778ce951c1ca648faa5d6c02b331d34ffc71156 100644 +index c64557c70122bff6ea0c8d0b34f62daf680e4334..6631a2b8cf99993d727d65a67af2bc7febb685b4 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -61,6 +61,7 @@ import net.minecraft.network.protocol.game.ClientboundSoundEntityPacket; @@ -96,7 +96,7 @@ index c64557c70122bff6ea0c8d0b34f62daf680e4334..c778ce951c1ca648faa5d6c02b331d34 import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerScoreboard; import net.minecraft.server.level.progress.ChunkProgressListener; -@@ -1510,12 +1511,88 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1510,12 +1511,84 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl return ((MapIndex) this.getServer().overworld().getDataStorage().computeIfAbsent(MapIndex::load, MapIndex::new, "idcounts")).getFreeAuxValueForMap(); } @@ -132,10 +132,6 @@ index c64557c70122bff6ea0c8d0b34f62daf680e4334..c778ce951c1ca648faa5d6c02b331d34 + // left + chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(spawn.add(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 + } -+ -+ MCUtil.getSpiralOutChunks(spawn, radiusInBlocks >> 4).forEach(pair -> { -+ getChunkSource().getChunkAtMainThread(pair.x, pair.z); -+ }); + } + public void removeTicketsForSpawn(int radiusInBlocks, BlockPos spawn) { + // In order to respect vanilla behavior, which is ensuring everything but the spawn border can tick, we added tickets diff --git a/patches/server/0388-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server/0388-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch index 6a201d9358..09f26df53f 100644 --- a/patches/server/0388-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ b/patches/server/0388-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -26,10 +26,10 @@ index e1498a5a8e664b922c77a8524ed2ea38c91834ce..71d5c298e14869d9d44226aeb6ffe3f0 EntityType entitytypes = entity.getType(); int i = entitytypes.clientTrackingRange() * 16; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index a43839ddd468d7b61d5609f22fb1e9fcd873590a..da85bfe5de9dcd6d51605ce9b023265b5a5f2936 100644 +index 03939f43ade3859a53ccf90e7fc221555ce6e97f..7340a25e49af30ecbb4b212365b9941e24e221d2 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -2124,7 +2124,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -2120,7 +2120,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl public void onTrackingStart(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot @@ -38,7 +38,7 @@ index a43839ddd468d7b61d5609f22fb1e9fcd873590a..da85bfe5de9dcd6d51605ce9b023265b if (entity instanceof ServerPlayer) { ServerLevel.this.players.add((ServerPlayer) entity); ServerLevel.this.updateSleepingPlayerList(); -@@ -2146,6 +2146,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -2142,6 +2142,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } entity.valid = true; // CraftBukkit diff --git a/patches/server/0501-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server/0501-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch index 744c5321fa..69caf29aee 100644 --- a/patches/server/0501-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch +++ b/patches/server/0501-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix SpawnChangeEvent not firing for all use-cases diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index bdabcdb60dbfb803ead13c42c8dd5e100b37dc00..4ae56444d258cdf44a02256315d6aae84e2f53be 100644 +index 23f9bb0f3202b418bf4fb59a46c624477f4dfae3..8d3d76ff942baf129f9845b945bd1537a058833a 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1679,12 +1679,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1675,12 +1675,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } // Paper end diff --git a/patches/server/0588-Remove-stale-POIs.patch b/patches/server/0588-Remove-stale-POIs.patch index 0683532986..712638228b 100644 --- a/patches/server/0588-Remove-stale-POIs.patch +++ b/patches/server/0588-Remove-stale-POIs.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Remove stale POIs diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index f1c02ae301da2a3b582d2ec1215c1a981e26ac47..0e14946284738b751790b2763bfe197c0148a54a 100644 +index 908708900a9160d95dea3a392d96a40a17489280..a883677719b408edf0b81cdc885e65759a03936e 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1768,6 +1768,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1764,6 +1764,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl }); optional1.ifPresent((villageplacetype) -> { this.getServer().execute(() -> { From e3fea251a689673467ba704fbf22086c9e9782aa Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Tue, 15 Jun 2021 06:55:25 -0700 Subject: [PATCH 156/226] BlockPos.withinManhattan decomp fix --- patches/server/0002-Decompile-fixes.patch | 39 ++++++++++++++++++- patches/server/0005-MC-Dev-fixes.patch | 6 +-- patches/server/0006-MC-Utils.patch | 14 +++---- ...CreateEvent-players-and-end-platform.patch | 4 +- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/patches/server/0002-Decompile-fixes.patch b/patches/server/0002-Decompile-fixes.patch index fea43707a9..bfd4cefec2 100644 --- a/patches/server/0002-Decompile-fixes.patch +++ b/patches/server/0002-Decompile-fixes.patch @@ -4,6 +4,43 @@ Date: Fri, 11 Jun 2021 05:25:03 -0500 Subject: [PATCH] Decompile fixes +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 1bd6ef643b17b059eb525035496b816a098279c4..891fc7f4cbea8eccd580f371715478265339c0cc 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -270,9 +270,11 @@ public class BlockPos extends Vec3i { + + public static Iterable withinManhattan(BlockPos center, int rangeX, int rangeY, int rangeZ) { + int i = rangeX + rangeY + rangeZ; +- int j = center.getX(); +- int k = center.getY(); +- int l = center.getZ(); ++ // Paper start - rename variables to fix conflict with anonymous class (decompile fix) ++ int centerX = center.getX(); ++ int centerY = center.getY(); ++ int centerZ = center.getZ(); ++ // Paper end + return () -> { + return new AbstractIterator() { + private final BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos(); +@@ -287,7 +289,7 @@ public class BlockPos extends Vec3i { + protected BlockPos computeNext() { + if (this.zMirror) { + this.zMirror = false; +- this.cursor.setZ(l - (this.cursor.getZ() - l)); ++ this.cursor.setZ(centerZ - (this.cursor.getZ() - centerZ)); // Paper - decompile fix + return this.cursor; + } else { + BlockPos blockPos; +@@ -313,7 +315,7 @@ public class BlockPos extends Vec3i { + int k = this.currentDepth - Math.abs(i) - Math.abs(j); + if (k <= rangeZ) { + this.zMirror = k != 0; +- blockPos = this.cursor.set(j + i, k + j, l + k); ++ blockPos = this.cursor.set(centerX + i, centerY + j, centerZ + k); // Paper - decompile fix + } + } + diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index 0000a0057ec4ee2db72e4ea1bf421f95d9d9fdc6..729e55535d833f8f6ff65bf226aac5ecdec44990 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java @@ -63,7 +100,7 @@ index c88dc823ca0c2f83bc10886208d498ea77523d68..dcfd0b107ac7bd1633f3b681cd5f5e26 while (iterator.hasNext()) { diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java -index b4a5709b03e400d00504f33a9b34019d2b7bf115..2d79d4014770081fcd58a929e5fe0a26ac1b8023 100644 +index efb37470d4927def456c382420775a815594aa58..9bc0ccf6acccd5505bac7b8a6bfb7597a43570cf 100644 --- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java @@ -172,7 +172,7 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { diff --git a/patches/server/0005-MC-Dev-fixes.patch b/patches/server/0005-MC-Dev-fixes.patch index ab305f9e0f..011c068e82 100644 --- a/patches/server/0005-MC-Dev-fixes.patch +++ b/patches/server/0005-MC-Dev-fixes.patch @@ -18,10 +18,10 @@ index 8fd67e0be207561d329b417959f6c537cc8b7c49..23c0914685e51de9dcdbb305c203efd4 public static CompletableFuture> sequence(List> futures) { diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 1bd6ef643b17b059eb525035496b816a098279c4..3cf71f85da94bcda5d4527b5f3e18d959c6c4634 100644 +index 891fc7f4cbea8eccd580f371715478265339c0cc..a153ca538d237fab567550b0bfcdf5b2985c56f8 100644 --- a/src/main/java/net/minecraft/core/BlockPos.java +++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -367,12 +367,12 @@ public class BlockPos extends Vec3i { +@@ -369,12 +369,12 @@ public class BlockPos extends Vec3i { if (this.index == l) { return this.endOfData(); } else { @@ -222,7 +222,7 @@ index d4488ebc4d4f50e1c3ccfeeb8bb82d06a7a90c30..37110c535b9fe25b53b5ebe9aa448ade }); } finally { diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java -index 2d79d4014770081fcd58a929e5fe0a26ac1b8023..f39a82bb231f5623fc69b044e6c17e742f56171a 100644 +index 9bc0ccf6acccd5505bac7b8a6bfb7597a43570cf..396cf81c2a501a09ab742f53d524463741c4d1ed 100644 --- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java @@ -75,7 +75,7 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { diff --git a/patches/server/0006-MC-Utils.patch b/patches/server/0006-MC-Utils.patch index 2b9b3e768c..de5c9c64f6 100644 --- a/patches/server/0006-MC-Utils.patch +++ b/patches/server/0006-MC-Utils.patch @@ -2271,7 +2271,7 @@ index 23c0914685e51de9dcdbb305c203efd4f2a73128..6f29d1fc437764a75d592ccb0c0ddc05 public static long getEpochMillis() { diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 3cf71f85da94bcda5d4527b5f3e18d959c6c4634..c2309751e3798874eee6b469129121c2e317fbc3 100644 +index a153ca538d237fab567550b0bfcdf5b2985c56f8..022cccbc52a7dda2f6bf0999905db82dd650b5ef 100644 --- a/src/main/java/net/minecraft/core/BlockPos.java +++ b/src/main/java/net/minecraft/core/BlockPos.java @@ -104,6 +104,7 @@ public class BlockPos extends Vec3i { @@ -2282,7 +2282,7 @@ index 3cf71f85da94bcda5d4527b5f3e18d959c6c4634..c2309751e3798874eee6b469129121c2 @Override public BlockPos offset(int i, int j, int k) { return i == 0 && j == 0 && k == 0 ? this : new BlockPos(this.getX() + i, this.getY() + j, this.getZ() + k); -@@ -459,6 +460,7 @@ public class BlockPos extends Vec3i { +@@ -461,6 +462,7 @@ public class BlockPos extends Vec3i { return super.rotate(rotation).immutable(); } @@ -2290,7 +2290,7 @@ index 3cf71f85da94bcda5d4527b5f3e18d959c6c4634..c2309751e3798874eee6b469129121c2 public BlockPos.MutableBlockPos set(int x, int y, int z) { this.setX(x); this.setY(y); -@@ -466,6 +468,7 @@ public class BlockPos extends Vec3i { +@@ -468,6 +470,7 @@ public class BlockPos extends Vec3i { return this; } @@ -2298,7 +2298,7 @@ index 3cf71f85da94bcda5d4527b5f3e18d959c6c4634..c2309751e3798874eee6b469129121c2 public BlockPos.MutableBlockPos set(double x, double y, double z) { return this.set(Mth.floor(x), Mth.floor(y), Mth.floor(z)); } -@@ -523,6 +526,7 @@ public class BlockPos extends Vec3i { +@@ -525,6 +528,7 @@ public class BlockPos extends Vec3i { } } @@ -2306,7 +2306,7 @@ index 3cf71f85da94bcda5d4527b5f3e18d959c6c4634..c2309751e3798874eee6b469129121c2 @Override public BlockPos.MutableBlockPos setX(int i) { super.setX(i); -@@ -540,6 +544,7 @@ public class BlockPos extends Vec3i { +@@ -542,6 +546,7 @@ public class BlockPos extends Vec3i { super.setZ(i); return this; } @@ -3425,7 +3425,7 @@ index ea44904fdf709ae097f5ede128193a78c1f49d35..b6eb04733611b63916453f36abf2ae61 public final PrimaryLevelData serverLevelData; // CraftBukkit - type final EntityTickList entityTickList; diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 7d55cece82e51ebadee07add83324351ed35ac49..59e58647e0650997b523a683aa52cb922a1d9c51 100644 +index d25086e37b7ea34fd586be7818c6b585760ce18e..99292d239dfdd2c0aaeece2b526db011b17aa121 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -228,6 +228,8 @@ public class ServerPlayer extends Player { @@ -3490,7 +3490,7 @@ index 391bae98e542333a431fb48bf0675c0e8a1873ac..0f6b534a4c789a2f09f6c4624e5d58b9 public BlockState getBlockState(BlockPos pos) { return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())).getBlockState(pos); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 65093c26247ff8fc6e487cd5a6b88cd246a79841..73f6e956afd2a679ffda2e7e21485e0b1791ecdf 100644 +index e06254a78334b009bf03635927361a369f8ee51a..83e71d07f86c115a0df1eb56ae9f2b127821fe80 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -219,9 +219,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0667-call-PortalCreateEvent-players-and-end-platform.patch b/patches/server/0667-call-PortalCreateEvent-players-and-end-platform.patch index 068b62193d..821306464c 100644 --- a/patches/server/0667-call-PortalCreateEvent-players-and-end-platform.patch +++ b/patches/server/0667-call-PortalCreateEvent-players-and-end-platform.patch @@ -5,10 +5,10 @@ Subject: [PATCH] call PortalCreateEvent players and end platform diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index fd5c22a3d281d8d913c353c8a668ec51b885066a..8c3b34b3d55af4aa8e3619a5bdf0eadb7baad029 100644 +index 8f0cf4297015f3cbe709e2eb82280cac72489925..22ea0da3836b61bb018ae974d2b8c7546b9528d6 100644 --- a/src/main/java/net/minecraft/core/BlockPos.java +++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -521,6 +521,7 @@ public class BlockPos extends Vec3i { +@@ -523,6 +523,7 @@ public class BlockPos extends Vec3i { return this.set(this.getX() + direction.getStepX() * distance, this.getY() + direction.getStepY() * distance, this.getZ() + direction.getStepZ() * distance); } From 68caddbb73ff2b0b643da4d8cc45a8aa635c3fb7 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Tue, 15 Jun 2021 15:20:52 +0200 Subject: [PATCH 157/226] Port anti x-ray patch --- .../1.17 => server}/0364-Anti-Xray.patch | 670 +++++++----------- ...o-Tick-view-distance-implementation.patch} | 23 +- ...ement-alternative-item-despawn-rate.patch} | 45 +- ...=> 0367-Tracking-Range-Improvements.patch} | 2 +- ...-items-vanishing-through-end-portal.patch} | 0 ...ment-optional-per-player-mob-spawns.patch} | 24 +- ...pper-searches-if-there-are-no-items.patch} | 4 +- ...et-gravity-in-void.-Fixes-MC-167279.patch} | 0 ...-getChunkAt-calls-for-loaded-chunks.patch} | 0 ...w-overriding-the-java-version-check.patch} | 0 ...tch => 0374-Add-ThrownEggHatchEvent.patch} | 0 ... 0375-Optimise-random-block-ticking.patch} | 24 +- ...p-API.patch => 0376-Entity-Jump-API.patch} | 0 ...-to-nerf-pigmen-from-nether-portals.patch} | 4 +- ... => 0378-Make-the-GUI-graph-fancier.patch} | 0 ...79-add-hand-to-BlockMultiPlaceEvent.patch} | 0 ...0-Prevent-teleporting-dead-entities.patch} | 0 ...ipwire-hook-placement-before-update.patch} | 0 ...o-allow-iron-golems-to-spawn-in-air.patch} | 4 +- ...chance-of-villager-zombie-infection.patch} | 4 +- ...tch => 0384-Optimise-Chunk-getFluid.patch} | 6 +- ...mise-TickListServer-by-rewriting-it.patch} | 2 +- ...pawn-settings-and-per-player-option.patch} | 4 +- ...nections-shouldn-t-hold-up-shutdown.patch} | 0 ...ow-bees-to-load-chunks-for-beehives.patch} | 0 ...PlayerChunkMap-adds-crashing-server.patch} | 6 +- ...timize-Collision-to-not-load-chunks.patch} | 0 ...tch => 0391-Don-t-tick-dead-players.patch} | 0 ...-Player-s-shouldn-t-be-able-to-move.patch} | 0 ...unkMap-memory-use-for-visibleChunks.patch} | 16 +- ...sks-Speed-up-processing-of-chunk-lo.patch} | 2 +- ...ove-existing-players-to-world-spawn.patch} | 0 ...Add-tick-times-API-and-mspt-command.patch} | 0 ...97-Expose-MinecraftServer-isRunning.patch} | 0 ...dd-Raw-Byte-ItemStack-Serialization.patch} | 0 ...9-Remove-streams-from-Mob-AI-System.patch} | 0 ... => 0400-Async-command-map-building.patch} | 0 ...h => 0401-Improved-Watchdog-Support.patch} | 10 +- ....patch => 0402-Optimize-Pathfinding.patch} | 0 ...3-Reduce-Either-Optional-allocation.patch} | 0 ...404-Remove-streams-from-PairedQueue.patch} | 0 ...-memory-footprint-of-NBTTagCompound.patch} | 0 ...ent-opening-inventories-when-frozen.patch} | 0 ...07-Optimise-ArraySetSorted-removeIf.patch} | 0 ...entity-collision-code-if-not-needed.patch} | 0 ...teleport-command-to-valid-locations.patch} | 0 ...Implement-Player-Client-Options-API.patch} | 0 ...Chunk-Post-Processing-deadlock-risk.patch} | 6 +- ...ayer-is-attempted-to-be-removed-fro.patch} | 0 ...3-Broadcast-join-message-to-console.patch} | 0 ...-Broken-behavior-of-PlayerJoinEvent.patch} | 6 +- ...oad-Chunks-for-Login-Asynchronously.patch} | 0 ...awn-point-if-spawn-in-unloaded-worl.patch} | 0 ...layerAttackEntityCooldownResetEvent.patch} | 0 ...llbacks-to-schedule-for-Callback-Ex.patch} | 4 +- ...-fire-BlockFade-on-worldgen-threads.patch} | 0 ...tom-creative-and-insomniac-controls.patch} | 4 +- ...-duplication-issues-and-teleport-is.patch} | 0 ...0422-Implement-Brigadier-Mojang-API.patch} | 0 ...patch => 0423-Villager-Restocks-API.patch} | 0 ...ickItem-Packet-and-kick-for-invalid.patch} | 0 ...n.patch => 0425-Expose-game-version.patch} | 2 +- ...> 0426-Optimize-Voxel-Shape-Merging.patch} | 0 ...per-thread-native-byte-buffer-cache.patch} | 0 ...atch => 0428-Implement-Mob-Goal-API.patch} | 0 ...ance-map-to-optimise-entity-tracker.patch} | 22 +- ...isOutsideRange-to-use-distance-maps.patch} | 18 +- ...=> 0431-Add-villager-reputation-API.patch} | 0 ...maximum-exp-value-when-merging-orbs.patch} | 4 +- ...tch => 0433-ExperienceOrbMergeEvent.patch} | 0 ...-Fix-PotionEffect-ignores-icon-flag.patch} | 0 ...brigadier-child-sorting-performance.patch} | 0 ...API.patch => 0436-Potential-bed-API.patch} | 0 ...ait-for-Async-Tasks-during-shutdown.patch} | 0 ...er-respects-game-and-entity-rules-f.patch} | 0 ...nd-End-Portal-Frames-from-being-des.patch} | 4 +- ...leInt-allocations-from-light-engine.patch} | 0 ...location-of-Vec3D-by-entity-tracker.patch} | 4 +- ...> 0442-Ensure-safe-gateway-teleport.patch} | 0 ...-for-console-having-all-permissions.patch} | 0 ...n-Full-Status-Chunk-NBT-Memory-Leak.patch} | 2 +- ...packets-to-nearby-locations-sounds-.patch} | 0 ...x-villager-trading-demand-MC-163962.patch} | 0 ... => 0447-Maps-shouldn-t-load-chunks.patch} | 0 ...okup-for-Treasure-Maps-Fixes-lag-fr.patch} | 0 ...nk-Unloads-based-on-Player-Movement.patch} | 6 +- ...Optimize-Bit-Operations-by-inlining.patch} | 0 ...ch => 0451-incremental-chunk-saving.patch} | 22 +- ...Plugin-Tickets-to-API-Chunk-Methods.patch} | 2 +- ...sing-chunks-due-to-integer-overflow.patch} | 0 ...r-runTaskTimerAsynchronously-Plugin.patch} | 0 ...ton-physics-inconsistency-MC-188840.patch} | 0 ...uping.patch => 0456-Fix-sand-duping.patch} | 0 ...desync-in-playerconnection-causing-.patch} | 0 ...older-method-without-block-snapshot.patch} | 0 ...h => 0459-Expose-Arrow-getItemStack.patch} | 0 ...mplement-PlayerRecipeBookClickEvent.patch} | 0 ...-Hide-sync-chunk-writes-behind-flag.patch} | 0 ...2-Add-permission-for-command-blocks.patch} | 4 +- ...ure-Entity-AABB-s-are-never-invalid.patch} | 0 ...orldBorder-collision-checks-and-air.patch} | 0 ...d-Difficulty-Remembering-Difficulty.patch} | 0 ...atch => 0466-Paper-dumpitem-command.patch} | 0 ...67-Don-t-allow-null-UUID-s-for-chat.patch} | 0 ...Legacy-Component-serialization-size.patch} | 0 ...469-Support-old-UUID-format-for-NBT.patch} | 0 ...p-duplicated-GameProfile-Properties.patch} | 0 ...vert-legacy-attributes-in-Item-Meta.patch} | 0 ...-Priority-Urgency-System-for-Chunks.patch} | 24 +- ...Remove-some-streams-from-structures.patch} | 0 ...rom-classes-related-villager-gossip.patch} | 0 ...0475-Support-components-in-ItemMeta.patch} | 0 ...rgetLivingEntityEvent-for-1.16-mobs.patch} | 0 ...patch => 0477-Add-entity-liquid-API.patch} | 0 ...date-itemstack-legacy-name-and-lore.patch} | 0 ...wn-player-in-correct-world-on-login.patch} | 0 ...atch => 0480-Add-PrepareResultEvent.patch} | 0 ...low-delegation-to-vanilla-chunk-gen.patch} | 6 +- ...-for-portal-on-world-gen-entity-add.patch} | 0 ...e-NetworkManager-Exception-Handling.patch} | 0 ...ncement-data-player-iteration-to-be.patch} | 0 ...x-arrows-never-despawning-MC-125757.patch} | 0 ...Vanilla-Command-permission-checking.patch} | 0 ...ve-range-check-for-block-placing-up.patch} | 0 ...-5989.patch => 0488-Fix-SPIGOT-5989.patch} | 0 ...-Bukkit-world-container-is-not-used.patch} | 0 ...5885-Unable-to-disable-advancements.patch} | 0 ...taPlayer-leak-due-from-quitting-ear.patch} | 0 ...eLighting-call-to-World-spigot-stri.patch} | 0 ...ix-some-rails-connecting-improperly.patch} | 0 ...h => 0494-Incremental-player-saving.patch} | 0 ...Fix-MC-187716-Use-configured-height.patch} | 0 ...stake-in-CB-NBT-int-deserialization.patch} | 0 ...rver-load-chunks-from-newer-version.patch} | 2 +- ...support.patch => 0498-Brand-support.patch} | 0 ...patch => 0499-Add-setMaxPlayers-API.patch} | 2 +- ...PickupItemAnimation-to-LivingEntity.patch} | 0 ...h => 0501-Don-t-require-FACING-data.patch} | 0 ...eEvent-not-firing-for-all-use-cases.patch} | 2 +- ...PI.patch => 0503-Add-moon-phase-API.patch} | 0 ...headless-pistons-from-being-created.patch} | 0 ...ent.patch => 0505-Add-BellRingEvent.patch} | 0 ...dd-zombie-targets-turtle-egg-config.patch} | 4 +- ...patch => 0507-Buffer-joins-to-world.patch} | 0 ...=> 0508-Optimize-redstone-algorithm.patch} | 4 +- ...s-not-working-in-some-kick-messages.patch} | 0 ...reateEvent-needs-to-know-its-entity.patch} | 0 ...ch => 0511-Fix-CraftTeam-null-check.patch} | 0 ...I.patch => 0512-Add-more-Evoker-API.patch} | 0 ...translation-keys-for-blocks-entitie.patch} | 0 ...te-HoverEvent-from-ItemStack-Entity.patch} | 0 ...ch => 0515-Cache-block-data-strings.patch} | 0 ...rtation-and-cancel-velocity-if-tele.patch} | 0 ...l-open-container-api-to-HumanEntity.patch} | 0 ...aFixerUpper-Rewrite-Rules-on-demand.patch} | 0 ...-capture-to-capture-all-items-added.patch} | 6 +- ...ty-in-invalid-locations-SPIGOT-6086.patch} | 0 ...-Counter-to-allow-plugins-to-use-va.patch} | 0 ...track-plugin-scoreboards-by-default.patch} | 0 ...king.patch => 0523-Entity-isTicking.patch} | 0 ...non-whitelisted-player-when-white-l.patch} | 0 ...g-a-passenger-in-CreatureSpawnEvent.patch} | 0 ...eset-Ender-Crystals-on-Dragon-Spawn.patch} | 0 ...-large-move-vectors-crashing-server.patch} | 0 ...atch => 0528-Optimise-getType-calls.patch} | 4 +- ....patch => 0529-Villager-resetOffers.patch} | 0 ...nig-for-some-hot-IBlockData-methods.patch} | 0 ...ce-order-when-capturing-blockstates.patch} | 2 +- ...lockpos-allocation-from-pathfinding.patch} | 0 ...em-locations-dropped-from-campfires.patch} | 0 ...tch => 0534-Player-elytra-boost-API.patch} | 0 ...35-Fixed-TileEntityBell-memory-leak.patch} | 0 ...ing-up-when-item-stack-is-empty-in-.patch} | 0 ...Add-getOfflinePlayerIfCached-String.patch} | 0 ...ch => 0538-Add-ignore-discounts-API.patch} | 0 ...Toggle-for-removing-existing-dragon.patch} | 4 +- ...x-client-lag-on-advancement-loading.patch} | 0 ...> 0541-Item-no-age-no-player-pickup.patch} | 0 ...er-Remove-Streams-Optimized-collect.patch} | 0 ...543-Beacon-API-custom-effect-ranges.patch} | 0 ...tch => 0544-Add-API-for-quit-reason.patch} | 0 ...h => 0545-Seed-based-feature-search.patch} | 4 +- ...ng-Trader-spawn-rate-config-options.patch} | 4 +- ...rove-performance-of-the-end-generat.patch} | 0 ...ch => 0548-Expose-world-spawn-angle.patch} | 0 ...patch => 0549-Add-Destroy-Speed-API.patch} | 0 ...-spawnParticle-x-y-z-precision-loss.patch} | 0 ...51-Add-LivingEntity-clearActiveItem.patch} | 0 ...=> 0552-Add-PlayerItemCooldownEvent.patch} | 0 ...PI.patch => 0553-More-lightning-API.patch} | 0 ...should-not-bypass-cramming-gamerule.patch} | 4 +- ...-missing-default-perms-for-commands.patch} | 0 ...h => 0556-Add-PlayerShearBlockEvent.patch} | 0 ...rbose-world-setting-to-false-by-def.patch} | 0 ...ng-zombie-villager-discount-exploit.patch} | 4 +- ....patch => 0559-Limit-recipe-packets.patch} | 0 ...-CraftSound-backwards-compatibility.patch} | 0 ... 0561-MC-4-Fix-item-position-desync.patch} | 0 ...562-Player-Chunk-Load-Unload-Events.patch} | 0 ...3-Optimize-Dynamic-get-Missing-Keys.patch} | 0 ...-Expose-LivingEntity-hurt-direction.patch} | 0 ...OBSTRUCTED-reason-to-BedEnterResult.patch} | 0 ...-invalid-ingredient-lists-in-Villag.patch} | 0 ...atch => 0567-added-PlayerTradeEvent.patch} | 0 ...ch => 0568-Implement-TargetHitEvent.patch} | 0 ...569-Additional-Block-Material-API-s.patch} | 0 ...tch => 0570-Fix-harming-potion-dupe.patch} | 0 ...get-Material-from-Boats-and-Minecar.patch} | 0 ....patch => 0572-Cache-burn-durations.patch} | 0 ...ob-spawner-spawn-egg-transformation.patch} | 4 +- ...ment-PlayerFlowerPotManipulateEvent.patch} | 0 ...event-not-being-called-in-adventure.patch} | 0 ...h => 0576-Zombie-API-breaking-doors.patch} | 0 ...577-Fix-nerfed-slime-when-splitting.patch} | 0 ...=> 0578-Add-EntityLoadCrossbowEvent.patch} | 0 ...ch => 0579-Guardian-beam-workaround.patch} | 0 ...0580-Added-WorldGameRuleChangeEvent.patch} | 0 ...-Added-ServerResourcesReloadedEvent.patch} | 0 ...d-settings-for-mobs-picking-up-loot.patch} | 4 +- ...mplemented-BlockFailedDispenseEvent.patch} | 0 ...-Added-PlayerLecternPageChangeEvent.patch} | 0 ...-Added-PlayerLoomPatternSelectEvent.patch} | 0 ...nfigurable-door-breaking-difficulty.patch} | 16 +- ...ty-commands-shall-not-be-dispatched.patch} | 0 ...I-to-expose-exact-interaction-point.patch} | 4 +- ...OIs.patch => 0589-Remove-stale-POIs.patch} | 2 +- ...h => 0590-Fix-villager-boat-exploit.patch} | 0 ...I.patch => 0591-Add-sendOpLevel-API.patch} | 0 ...ch => 0592-Add-StructureLocateEvent.patch} | 0 ...-for-requiring-a-player-participant.patch} | 4 +- ...leHitEvent-call-when-fireballs-dead.patch} | 0 ...nent-with-empty-text-instead-of-thr.patch} | 0 ...596-Make-schedule-command-per-world.patch} | 0 ...597-Configurable-max-leash-distance.patch} | 4 +- ...598-Implement-BlockPreDispenseEvent.patch} | 0 ...h => 0599-Added-Vanilla-Entity-Tags.patch} | 0 ...-API.patch => 0600-added-Wither-API.patch} | 0 ...ng-of-PlayerChangeBeaconEffectEvent.patch} | 0 ...-spam-when-removing-chests-in-water.patch} | 0 ...e-for-always-placing-the-dragon-egg.patch} | 4 +- ...-PlayerStonecutterRecipeSelectEvent.patch} | 0 ...eash-variable-to-EntityUnleashEvent.patch} | 0 ...e-map-update-when-spawning-disabled.patch} | 0 ...shield-blocking-on-dimension-change.patch} | 0 ...atch => 0608-add-DragonEggFormEvent.patch} | 0 ...Event.patch => 0609-EntityMoveEvent.patch} | 2 +- ...isable-pathfinding-updates-on-block.patch} | 6 +- ... 0611-Inline-shift-direction-fields.patch} | 0 ...-adding-items-to-BlockDropItemEvent.patch} | 0 ...inThreadExecutor-to-BukkitScheduler.patch} | 0 ...entity-allow-attribute-registration.patch} | 0 ...ix-dead-slime-setSize-invincibility.patch} | 0 ...pes-should-return-an-immutable-list.patch} | 0 ....patch => 0617-misc-debugging-dumps.patch} | 0 ...port-for-hex-color-codes-in-console.patch} | 0 ...atch => 0619-Expose-Tracked-Players.patch} | 0 ...0-Remove-streams-from-SensorNearest.patch} | 0 ...ix-Wither-hostility-towards-players.patch} | 4 +- ...er-exception-on-empty-JsonList-file.patch} | 0 ...GUI.patch => 0623-Improve-ServerGUI.patch} | 0 ...ure-plate-EntityInteractEvent-for-i.patch} | 0 ...625-fix-converting-txt-to-json-file.patch} | 0 ...atch => 0626-Add-worldborder-events.patch} | 0 ...=> 0627-added-PlayerNameEntityEvent.patch} | 0 ...grindstones-from-overstacking-items.patch} | 0 ...h => 0629-Add-recipe-to-cook-events.patch} | 0 ...patch => 0630-Add-Block-isValidTool.patch} | 0 ...using-signs-inside-spawn-protection.patch} | 4 +- ...ch => 0632-Implement-Keyed-on-World.patch} | 0 ...ternative-constructor-for-Rotations.patch} | 0 ...y-API.patch => 0634-Item-Rarity-API.patch} | 0 ...imer-for-Wandering-Traders-spawned-.patch} | 0 ...py-TESign-isEditable-from-snapshots.patch} | 0 ...d-item-when-player-has-disconnected.patch} | 0 ...elist-use-configurable-kick-message.patch} | 0 ...gnore-result-of-PlayerEditBookEvent.patch} | 0 ...block-falling-causing-client-desync.patch} | 0 ...tch => 0641-Expose-protocol-version.patch} | 0 ...nt-suggestion-tooltips-in-AsyncTabC.patch} | 0 ...ab-completions-for-brigadier-comman.patch} | 0 ...temConsumeEvent-cancelling-properly.patch} | 0 ...patch => 0645-Add-bypass-host-check.patch} | 0 ...0646-Set-area-affect-cloud-rotation.patch} | 0 ...add-isDeeplySleeping-to-HumanEntity.patch} | 0 ...ting-give-items-on-item-drop-cancel.patch} | 0 ...add-consumeFuel-to-FurnaceBurnEvent.patch} | 0 ...-set-drop-chance-to-EntityEquipment.patch} | 0 ...ix-PigZombieAngerEvent-cancellation.patch} | 0 ...-checkReach-check-for-Shulker-boxes.patch} | 0 ...ix-PlayerItemHeldEvent-firing-twice.patch} | 0 ... => 0654-Added-PlayerDeepSleepEvent.patch} | 0 ...ld-API.patch => 0655-More-World-API.patch} | 0 ... 0656-Added-PlayerBedFailEnterEvent.patch} | 0 ...-to-convert-between-Component-and-B.patch} | 0 ...n-acting-as-a-bed-respawn-from-the-.patch} | 0 ...acon-activation-deactivation-events.patch} | 0 ...-RespawnFlags-to-PlayerRespawnEvent.patch} | 0 ...dd-Channel-initialization-listeners.patch} | 0 ...mands-if-tab-completion-is-disabled.patch} | 0 ...> 0663-Add-more-WanderingTrader-API.patch} | 0 ...dd-EntityBlockStorage-clearEntities.patch} | 0 ...ssage-to-PlayerAdvancementDoneEvent.patch} | 0 ...address-to-AsyncPlayerPreLoginEvent.patch} | 0 ...close.patch => 0667-Inventory-close.patch} | 0 ...reateEvent-players-and-end-platform.patch} | 0 ...-in-sunlight-API-for-Phantoms-and-S.patch} | 0 ...=> 0670-Fix-CraftPotionBrewer-cache.patch} | 0 ...atch => 0671-Add-basic-Datapack-API.patch} | 0 ...ment-variable-to-disable-server-gui.patch} | 0 ...itions-to-PlayerGameModeChangeEvent.patch} | 2 +- ... => 0674-ItemStack-repair-check-API.patch} | 0 ....patch => 0675-More-Enchantment-API.patch} | 0 ...option-to-load-extra-plugin-jars-no.patch} | 2 +- ...-and-optimise-world-force-upgrading.patch} | 15 +- ...PI.patch => 0678-Add-Mob-lookAt-API.patch} | 0 ...0679-Add-Unix-domain-socket-support.patch} | 0 ... => 0680-Add-EntityInsideBlockEvent.patch} | 0 ...81-Attributes-API-for-item-defaults.patch} | 0 ...hantCustom-emit-PlayerPurchaseEvent.patch} | 0 ...ause-to-Weather-ThunderChangeEvents.patch} | 2 +- ...patch => 0684-More-Lidded-Block-API.patch} | 0 ...85-Limit-item-frame-cursors-on-maps.patch} | 4 +- ...0686-Add-PufferFishStateChangeEvent.patch} | 0 ... => 0687-Add-PlayerKickEvent-causes.patch} | 0 ...erBucketEmptyEvent-result-itemstack.patch} | 0 ...tedContainer-instead-of-ReentrantLo.patch} | 30 +- ...-to-fix-items-merging-through-walls.patch} | 4 +- ...h => 0691-Add-BellRevealRaiderEvent.patch} | 0 ... 0692-Fix-invulnerable-end-crystals.patch} | 4 +- ...93-Add-ElderGuardianAppearanceEvent.patch} | 0 ...inventory-on-cancelled-pickup-event.patch} | 0 ...0695-Fix-dangerous-end-portal-logic.patch} | 0 ...-Biome-Mob-Lookups-for-Mob-Spawning.patch} | 0 ...-Make-item-validations-configurable.patch} | 0 ...0698-Add-more-line-of-sight-methods.patch} | 0 ... => 0699-add-per-world-spawn-limits.patch} | 4 +- ...plashEvent-for-water-splash-potions.patch} | 0 ...tus-dataconverter-for-pre-1.13-chun.patch} | 0 338 files changed, 500 insertions(+), 661 deletions(-) rename patches/{removed/1.17 => server}/0364-Anti-Xray.patch (70%) rename patches/server/{0364-No-Tick-view-distance-implementation.patch => 0365-No-Tick-view-distance-implementation.patch} (98%) rename patches/server/{0365-Implement-alternative-item-despawn-rate.patch => 0366-Implement-alternative-item-despawn-rate.patch} (76%) rename patches/server/{0366-Tracking-Range-Improvements.patch => 0367-Tracking-Range-Improvements.patch} (97%) rename patches/server/{0367-Fix-items-vanishing-through-end-portal.patch => 0368-Fix-items-vanishing-through-end-portal.patch} (100%) rename patches/server/{0368-implement-optional-per-player-mob-spawns.patch => 0369-implement-optional-per-player-mob-spawns.patch} (97%) rename patches/server/{0369-Avoid-hopper-searches-if-there-are-no-items.patch => 0370-Avoid-hopper-searches-if-there-are-no-items.patch} (97%) rename patches/server/{0370-Bees-get-gravity-in-void.-Fixes-MC-167279.patch => 0371-Bees-get-gravity-in-void.-Fixes-MC-167279.patch} (100%) rename patches/server/{0371-Optimise-getChunkAt-calls-for-loaded-chunks.patch => 0372-Optimise-getChunkAt-calls-for-loaded-chunks.patch} (100%) rename patches/server/{0372-Allow-overriding-the-java-version-check.patch => 0373-Allow-overriding-the-java-version-check.patch} (100%) rename patches/server/{0373-Add-ThrownEggHatchEvent.patch => 0374-Add-ThrownEggHatchEvent.patch} (100%) rename patches/server/{0374-Optimise-random-block-ticking.patch => 0375-Optimise-random-block-ticking.patch} (95%) rename patches/server/{0375-Entity-Jump-API.patch => 0376-Entity-Jump-API.patch} (100%) rename patches/server/{0376-Add-option-to-nerf-pigmen-from-nether-portals.patch => 0377-Add-option-to-nerf-pigmen-from-nether-portals.patch} (95%) rename patches/server/{0377-Make-the-GUI-graph-fancier.patch => 0378-Make-the-GUI-graph-fancier.patch} (100%) rename patches/server/{0378-add-hand-to-BlockMultiPlaceEvent.patch => 0379-add-hand-to-BlockMultiPlaceEvent.patch} (100%) rename patches/server/{0379-Prevent-teleporting-dead-entities.patch => 0380-Prevent-teleporting-dead-entities.patch} (100%) rename patches/server/{0380-Validate-tripwire-hook-placement-before-update.patch => 0381-Validate-tripwire-hook-placement-before-update.patch} (100%) rename patches/server/{0381-Add-option-to-allow-iron-golems-to-spawn-in-air.patch => 0382-Add-option-to-allow-iron-golems-to-spawn-in-air.patch} (92%) rename patches/server/{0382-Configurable-chance-of-villager-zombie-infection.patch => 0383-Configurable-chance-of-villager-zombie-infection.patch} (94%) rename patches/server/{0383-Optimise-Chunk-getFluid.patch => 0384-Optimise-Chunk-getFluid.patch} (92%) rename patches/server/{0384-Optimise-TickListServer-by-rewriting-it.patch => 0385-Optimise-TickListServer-by-rewriting-it.patch} (99%) rename patches/server/{0385-Pillager-patrol-spawn-settings-and-per-player-option.patch => 0386-Pillager-patrol-spawn-settings-and-per-player-option.patch} (97%) rename patches/server/{0386-Remote-Connections-shouldn-t-hold-up-shutdown.patch => 0387-Remote-Connections-shouldn-t-hold-up-shutdown.patch} (100%) rename patches/server/{0387-Do-not-allow-bees-to-load-chunks-for-beehives.patch => 0388-Do-not-allow-bees-to-load-chunks-for-beehives.patch} (100%) rename patches/server/{0388-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch => 0389-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch} (91%) rename patches/server/{0389-Optimize-Collision-to-not-load-chunks.patch => 0390-Optimize-Collision-to-not-load-chunks.patch} (100%) rename patches/server/{0390-Don-t-tick-dead-players.patch => 0391-Don-t-tick-dead-players.patch} (100%) rename patches/server/{0391-Dead-Player-s-shouldn-t-be-able-to-move.patch => 0392-Dead-Player-s-shouldn-t-be-able-to-move.patch} (100%) rename patches/server/{0392-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch => 0393-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch} (96%) rename patches/server/{0393-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch => 0394-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch} (99%) rename patches/server/{0394-Don-t-move-existing-players-to-world-spawn.patch => 0395-Don-t-move-existing-players-to-world-spawn.patch} (100%) rename patches/server/{0395-Add-tick-times-API-and-mspt-command.patch => 0396-Add-tick-times-API-and-mspt-command.patch} (100%) rename patches/server/{0396-Expose-MinecraftServer-isRunning.patch => 0397-Expose-MinecraftServer-isRunning.patch} (100%) rename patches/server/{0397-Add-Raw-Byte-ItemStack-Serialization.patch => 0398-Add-Raw-Byte-ItemStack-Serialization.patch} (100%) rename patches/server/{0398-Remove-streams-from-Mob-AI-System.patch => 0399-Remove-streams-from-Mob-AI-System.patch} (100%) rename patches/server/{0399-Async-command-map-building.patch => 0400-Async-command-map-building.patch} (100%) rename patches/server/{0400-Improved-Watchdog-Support.patch => 0401-Improved-Watchdog-Support.patch} (98%) rename patches/server/{0401-Optimize-Pathfinding.patch => 0402-Optimize-Pathfinding.patch} (100%) rename patches/server/{0402-Reduce-Either-Optional-allocation.patch => 0403-Reduce-Either-Optional-allocation.patch} (100%) rename patches/server/{0403-Remove-streams-from-PairedQueue.patch => 0404-Remove-streams-from-PairedQueue.patch} (100%) rename patches/server/{0404-Reduce-memory-footprint-of-NBTTagCompound.patch => 0405-Reduce-memory-footprint-of-NBTTagCompound.patch} (100%) rename patches/server/{0405-Prevent-opening-inventories-when-frozen.patch => 0406-Prevent-opening-inventories-when-frozen.patch} (100%) rename patches/server/{0406-Optimise-ArraySetSorted-removeIf.patch => 0407-Optimise-ArraySetSorted-removeIf.patch} (100%) rename patches/server/{0407-Don-t-run-entity-collision-code-if-not-needed.patch => 0408-Don-t-run-entity-collision-code-if-not-needed.patch} (100%) rename patches/server/{0408-Restrict-vanilla-teleport-command-to-valid-locations.patch => 0409-Restrict-vanilla-teleport-command-to-valid-locations.patch} (100%) rename patches/server/{0409-Implement-Player-Client-Options-API.patch => 0410-Implement-Player-Client-Options-API.patch} (100%) rename patches/server/{0410-Fix-Chunk-Post-Processing-deadlock-risk.patch => 0411-Fix-Chunk-Post-Processing-deadlock-risk.patch} (93%) rename patches/server/{0411-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch => 0412-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch} (100%) rename patches/server/{0412-Broadcast-join-message-to-console.patch => 0413-Broadcast-join-message-to-console.patch} (100%) rename patches/server/{0413-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch => 0414-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch} (96%) rename patches/server/{0414-Load-Chunks-for-Login-Asynchronously.patch => 0415-Load-Chunks-for-Login-Asynchronously.patch} (100%) rename patches/server/{0415-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch => 0416-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch} (100%) rename patches/server/{0416-Add-PlayerAttackEntityCooldownResetEvent.patch => 0417-Add-PlayerAttackEntityCooldownResetEvent.patch} (100%) rename patches/server/{0417-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch => 0418-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch} (93%) rename patches/server/{0418-Don-t-fire-BlockFade-on-worldgen-threads.patch => 0419-Don-t-fire-BlockFade-on-worldgen-threads.patch} (100%) rename patches/server/{0419-Add-phantom-creative-and-insomniac-controls.patch => 0420-Add-phantom-creative-and-insomniac-controls.patch} (96%) rename patches/server/{0420-Fix-numerous-item-duplication-issues-and-teleport-is.patch => 0421-Fix-numerous-item-duplication-issues-and-teleport-is.patch} (100%) rename patches/server/{0421-Implement-Brigadier-Mojang-API.patch => 0422-Implement-Brigadier-Mojang-API.patch} (100%) rename patches/server/{0422-Villager-Restocks-API.patch => 0423-Villager-Restocks-API.patch} (100%) rename patches/server/{0423-Validate-PickItem-Packet-and-kick-for-invalid.patch => 0424-Validate-PickItem-Packet-and-kick-for-invalid.patch} (100%) rename patches/server/{0424-Expose-game-version.patch => 0425-Expose-game-version.patch} (89%) rename patches/server/{0425-Optimize-Voxel-Shape-Merging.patch => 0426-Optimize-Voxel-Shape-Merging.patch} (100%) rename patches/server/{0426-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch => 0427-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch} (100%) rename patches/server/{0427-Implement-Mob-Goal-API.patch => 0428-Implement-Mob-Goal-API.patch} (100%) rename patches/server/{0428-Use-distance-map-to-optimise-entity-tracker.patch => 0429-Use-distance-map-to-optimise-entity-tracker.patch} (96%) rename patches/server/{0429-Optimize-isOutsideRange-to-use-distance-maps.patch => 0430-Optimize-isOutsideRange-to-use-distance-maps.patch} (97%) rename patches/server/{0430-Add-villager-reputation-API.patch => 0431-Add-villager-reputation-API.patch} (100%) rename patches/server/{0431-Option-for-maximum-exp-value-when-merging-orbs.patch => 0432-Option-for-maximum-exp-value-when-merging-orbs.patch} (95%) rename patches/server/{0432-ExperienceOrbMergeEvent.patch => 0433-ExperienceOrbMergeEvent.patch} (100%) rename patches/server/{0433-Fix-PotionEffect-ignores-icon-flag.patch => 0434-Fix-PotionEffect-ignores-icon-flag.patch} (100%) rename patches/server/{0434-Optimize-brigadier-child-sorting-performance.patch => 0435-Optimize-brigadier-child-sorting-performance.patch} (100%) rename patches/server/{0435-Potential-bed-API.patch => 0436-Potential-bed-API.patch} (100%) rename patches/server/{0436-Wait-for-Async-Tasks-during-shutdown.patch => 0437-Wait-for-Async-Tasks-during-shutdown.patch} (100%) rename patches/server/{0437-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch => 0438-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch} (100%) rename patches/server/{0438-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch => 0439-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch} (98%) rename patches/server/{0439-Reduce-MutableInt-allocations-from-light-engine.patch => 0440-Reduce-MutableInt-allocations-from-light-engine.patch} (100%) rename patches/server/{0440-Reduce-allocation-of-Vec3D-by-entity-tracker.patch => 0441-Reduce-allocation-of-Vec3D-by-entity-tracker.patch} (96%) rename patches/server/{0441-Ensure-safe-gateway-teleport.patch => 0442-Ensure-safe-gateway-teleport.patch} (100%) rename patches/server/{0442-Add-option-for-console-having-all-permissions.patch => 0443-Add-option-for-console-having-all-permissions.patch} (100%) rename patches/server/{0443-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch => 0444-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch} (98%) rename patches/server/{0444-Optimize-sending-packets-to-nearby-locations-sounds-.patch => 0445-Optimize-sending-packets-to-nearby-locations-sounds-.patch} (100%) rename patches/server/{0445-Fix-villager-trading-demand-MC-163962.patch => 0446-Fix-villager-trading-demand-MC-163962.patch} (100%) rename patches/server/{0446-Maps-shouldn-t-load-chunks.patch => 0447-Maps-shouldn-t-load-chunks.patch} (100%) rename patches/server/{0447-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch => 0448-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch} (100%) rename patches/server/{0448-Delay-Chunk-Unloads-based-on-Player-Movement.patch => 0449-Delay-Chunk-Unloads-based-on-Player-Movement.patch} (96%) rename patches/server/{0449-Optimize-Bit-Operations-by-inlining.patch => 0450-Optimize-Bit-Operations-by-inlining.patch} (100%) rename patches/server/{0450-incremental-chunk-saving.patch => 0451-incremental-chunk-saving.patch} (94%) rename patches/server/{0451-Add-Plugin-Tickets-to-API-Chunk-Methods.patch => 0452-Add-Plugin-Tickets-to-API-Chunk-Methods.patch} (98%) rename patches/server/{0452-Fix-missing-chunks-due-to-integer-overflow.patch => 0453-Fix-missing-chunks-due-to-integer-overflow.patch} (100%) rename patches/server/{0453-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch => 0454-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch} (100%) rename patches/server/{0454-Fix-piston-physics-inconsistency-MC-188840.patch => 0455-Fix-piston-physics-inconsistency-MC-188840.patch} (100%) rename patches/server/{0455-Fix-sand-duping.patch => 0456-Fix-sand-duping.patch} (100%) rename patches/server/{0456-Prevent-position-desync-in-playerconnection-causing-.patch => 0457-Prevent-position-desync-in-playerconnection-causing-.patch} (100%) rename patches/server/{0457-Inventory-getHolder-method-without-block-snapshot.patch => 0458-Inventory-getHolder-method-without-block-snapshot.patch} (100%) rename patches/server/{0458-Expose-Arrow-getItemStack.patch => 0459-Expose-Arrow-getItemStack.patch} (100%) rename patches/server/{0459-Add-and-implement-PlayerRecipeBookClickEvent.patch => 0460-Add-and-implement-PlayerRecipeBookClickEvent.patch} (100%) rename patches/server/{0460-Hide-sync-chunk-writes-behind-flag.patch => 0461-Hide-sync-chunk-writes-behind-flag.patch} (100%) rename patches/server/{0461-Add-permission-for-command-blocks.patch => 0462-Add-permission-for-command-blocks.patch} (97%) rename patches/server/{0462-Ensure-Entity-AABB-s-are-never-invalid.patch => 0463-Ensure-Entity-AABB-s-are-never-invalid.patch} (100%) rename patches/server/{0463-Optimize-WorldBorder-collision-checks-and-air.patch => 0464-Optimize-WorldBorder-collision-checks-and-air.patch} (100%) rename patches/server/{0464-Fix-Per-World-Difficulty-Remembering-Difficulty.patch => 0465-Fix-Per-World-Difficulty-Remembering-Difficulty.patch} (100%) rename patches/server/{0465-Paper-dumpitem-command.patch => 0466-Paper-dumpitem-command.patch} (100%) rename patches/server/{0466-Don-t-allow-null-UUID-s-for-chat.patch => 0467-Don-t-allow-null-UUID-s-for-chat.patch} (100%) rename patches/server/{0467-Improve-Legacy-Component-serialization-size.patch => 0468-Improve-Legacy-Component-serialization-size.patch} (100%) rename patches/server/{0468-Support-old-UUID-format-for-NBT.patch => 0469-Support-old-UUID-format-for-NBT.patch} (100%) rename patches/server/{0469-Clean-up-duplicated-GameProfile-Properties.patch => 0470-Clean-up-duplicated-GameProfile-Properties.patch} (100%) rename patches/server/{0470-Convert-legacy-attributes-in-Item-Meta.patch => 0471-Convert-legacy-attributes-in-Item-Meta.patch} (100%) rename patches/server/{0471-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch => 0472-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch} (98%) rename patches/server/{0472-Remove-some-streams-from-structures.patch => 0473-Remove-some-streams-from-structures.patch} (100%) rename patches/server/{0473-Remove-streams-from-classes-related-villager-gossip.patch => 0474-Remove-streams-from-classes-related-villager-gossip.patch} (100%) rename patches/server/{0474-Support-components-in-ItemMeta.patch => 0475-Support-components-in-ItemMeta.patch} (100%) rename patches/server/{0475-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch => 0476-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch} (100%) rename patches/server/{0476-Add-entity-liquid-API.patch => 0477-Add-entity-liquid-API.patch} (100%) rename patches/server/{0477-Update-itemstack-legacy-name-and-lore.patch => 0478-Update-itemstack-legacy-name-and-lore.patch} (100%) rename patches/server/{0478-Spawn-player-in-correct-world-on-login.patch => 0479-Spawn-player-in-correct-world-on-login.patch} (100%) rename patches/server/{0479-Add-PrepareResultEvent.patch => 0480-Add-PrepareResultEvent.patch} (100%) rename patches/server/{0480-Allow-delegation-to-vanilla-chunk-gen.patch => 0481-Allow-delegation-to-vanilla-chunk-gen.patch} (95%) rename patches/server/{0481-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch => 0482-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch} (100%) rename patches/server/{0482-Optimize-NetworkManager-Exception-Handling.patch => 0483-Optimize-NetworkManager-Exception-Handling.patch} (100%) rename patches/server/{0483-Optimize-the-advancement-data-player-iteration-to-be.patch => 0484-Optimize-the-advancement-data-player-iteration-to-be.patch} (100%) rename patches/server/{0484-Fix-arrows-never-despawning-MC-125757.patch => 0485-Fix-arrows-never-despawning-MC-125757.patch} (100%) rename patches/server/{0485-Thread-Safe-Vanilla-Command-permission-checking.patch => 0486-Thread-Safe-Vanilla-Command-permission-checking.patch} (100%) rename patches/server/{0486-Move-range-check-for-block-placing-up.patch => 0487-Move-range-check-for-block-placing-up.patch} (100%) rename patches/server/{0487-Fix-SPIGOT-5989.patch => 0488-Fix-SPIGOT-5989.patch} (100%) rename patches/server/{0488-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch => 0489-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch} (100%) rename patches/server/{0489-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch => 0490-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch} (100%) rename patches/server/{0490-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch => 0491-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch} (100%) rename patches/server/{0491-Add-missing-strikeLighting-call-to-World-spigot-stri.patch => 0492-Add-missing-strikeLighting-call-to-World-spigot-stri.patch} (100%) rename patches/server/{0492-Fix-some-rails-connecting-improperly.patch => 0493-Fix-some-rails-connecting-improperly.patch} (100%) rename patches/server/{0493-Incremental-player-saving.patch => 0494-Incremental-player-saving.patch} (100%) rename patches/server/{0494-Fix-MC-187716-Use-configured-height.patch => 0495-Fix-MC-187716-Use-configured-height.patch} (100%) rename patches/server/{0495-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch => 0496-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch} (100%) rename patches/server/{0496-Do-not-let-the-server-load-chunks-from-newer-version.patch => 0497-Do-not-let-the-server-load-chunks-from-newer-version.patch} (96%) rename patches/server/{0497-Brand-support.patch => 0498-Brand-support.patch} (100%) rename patches/server/{0498-Add-setMaxPlayers-API.patch => 0499-Add-setMaxPlayers-API.patch} (94%) rename patches/server/{0499-Add-playPickupItemAnimation-to-LivingEntity.patch => 0500-Add-playPickupItemAnimation-to-LivingEntity.patch} (100%) rename patches/server/{0500-Don-t-require-FACING-data.patch => 0501-Don-t-require-FACING-data.patch} (100%) rename patches/server/{0501-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch => 0502-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch} (96%) rename patches/server/{0502-Add-moon-phase-API.patch => 0503-Add-moon-phase-API.patch} (100%) rename patches/server/{0503-Prevent-headless-pistons-from-being-created.patch => 0504-Prevent-headless-pistons-from-being-created.patch} (100%) rename patches/server/{0504-Add-BellRingEvent.patch => 0505-Add-BellRingEvent.patch} (100%) rename patches/server/{0505-Add-zombie-targets-turtle-egg-config.patch => 0506-Add-zombie-targets-turtle-egg-config.patch} (92%) rename patches/server/{0506-Buffer-joins-to-world.patch => 0507-Buffer-joins-to-world.patch} (100%) rename patches/server/{0507-Optimize-redstone-algorithm.patch => 0508-Optimize-redstone-algorithm.patch} (99%) rename patches/server/{0508-Fix-hex-colors-not-working-in-some-kick-messages.patch => 0509-Fix-hex-colors-not-working-in-some-kick-messages.patch} (100%) rename patches/server/{0509-PortalCreateEvent-needs-to-know-its-entity.patch => 0510-PortalCreateEvent-needs-to-know-its-entity.patch} (100%) rename patches/server/{0510-Fix-CraftTeam-null-check.patch => 0511-Fix-CraftTeam-null-check.patch} (100%) rename patches/server/{0511-Add-more-Evoker-API.patch => 0512-Add-more-Evoker-API.patch} (100%) rename patches/server/{0512-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch => 0513-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch} (100%) rename patches/server/{0513-Create-HoverEvent-from-ItemStack-Entity.patch => 0514-Create-HoverEvent-from-ItemStack-Entity.patch} (100%) rename patches/server/{0514-Cache-block-data-strings.patch => 0515-Cache-block-data-strings.patch} (100%) rename patches/server/{0515-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch => 0516-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch} (100%) rename patches/server/{0516-Add-additional-open-container-api-to-HumanEntity.patch => 0517-Add-additional-open-container-api-to-HumanEntity.patch} (100%) rename patches/server/{0517-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch => 0518-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch} (100%) rename patches/server/{0518-Extend-block-drop-capture-to-capture-all-items-added.patch => 0519-Extend-block-drop-capture-to-capture-all-items-added.patch} (92%) rename patches/server/{0519-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch => 0520-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch} (100%) rename patches/server/{0520-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch => 0521-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch} (100%) rename patches/server/{0521-Lazily-track-plugin-scoreboards-by-default.patch => 0522-Lazily-track-plugin-scoreboards-by-default.patch} (100%) rename patches/server/{0522-Entity-isTicking.patch => 0523-Entity-isTicking.patch} (100%) rename patches/server/{0523-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch => 0524-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch} (100%) rename patches/server/{0524-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch => 0525-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch} (100%) rename patches/server/{0525-Reset-Ender-Crystals-on-Dragon-Spawn.patch => 0526-Reset-Ender-Crystals-on-Dragon-Spawn.patch} (100%) rename patches/server/{0526-Fix-for-large-move-vectors-crashing-server.patch => 0527-Fix-for-large-move-vectors-crashing-server.patch} (100%) rename patches/server/{0527-Optimise-getType-calls.patch => 0528-Optimise-getType-calls.patch} (96%) rename patches/server/{0528-Villager-resetOffers.patch => 0529-Villager-resetOffers.patch} (100%) rename patches/server/{0529-Improve-inlinig-for-some-hot-IBlockData-methods.patch => 0530-Improve-inlinig-for-some-hot-IBlockData-methods.patch} (100%) rename patches/server/{0530-Retain-block-place-order-when-capturing-blockstates.patch => 0531-Retain-block-place-order-when-capturing-blockstates.patch} (93%) rename patches/server/{0531-Reduce-blockpos-allocation-from-pathfinding.patch => 0532-Reduce-blockpos-allocation-from-pathfinding.patch} (100%) rename patches/server/{0532-Fix-item-locations-dropped-from-campfires.patch => 0533-Fix-item-locations-dropped-from-campfires.patch} (100%) rename patches/server/{0533-Player-elytra-boost-API.patch => 0534-Player-elytra-boost-API.patch} (100%) rename patches/server/{0534-Fixed-TileEntityBell-memory-leak.patch => 0535-Fixed-TileEntityBell-memory-leak.patch} (100%) rename patches/server/{0535-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch => 0536-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch} (100%) rename patches/server/{0536-Add-getOfflinePlayerIfCached-String.patch => 0537-Add-getOfflinePlayerIfCached-String.patch} (100%) rename patches/server/{0537-Add-ignore-discounts-API.patch => 0538-Add-ignore-discounts-API.patch} (100%) rename patches/server/{0538-Toggle-for-removing-existing-dragon.patch => 0539-Toggle-for-removing-existing-dragon.patch} (92%) rename patches/server/{0539-Fix-client-lag-on-advancement-loading.patch => 0540-Fix-client-lag-on-advancement-loading.patch} (100%) rename patches/server/{0540-Item-no-age-no-player-pickup.patch => 0541-Item-no-age-no-player-pickup.patch} (100%) rename patches/server/{0541-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch => 0542-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch} (100%) rename patches/server/{0542-Beacon-API-custom-effect-ranges.patch => 0543-Beacon-API-custom-effect-ranges.patch} (100%) rename patches/server/{0543-Add-API-for-quit-reason.patch => 0544-Add-API-for-quit-reason.patch} (100%) rename patches/server/{0544-Seed-based-feature-search.patch => 0545-Seed-based-feature-search.patch} (96%) rename patches/server/{0545-Add-Wandering-Trader-spawn-rate-config-options.patch => 0546-Add-Wandering-Trader-spawn-rate-config-options.patch} (97%) rename patches/server/{0546-Significantly-improve-performance-of-the-end-generat.patch => 0547-Significantly-improve-performance-of-the-end-generat.patch} (100%) rename patches/server/{0547-Expose-world-spawn-angle.patch => 0548-Expose-world-spawn-angle.patch} (100%) rename patches/server/{0548-Add-Destroy-Speed-API.patch => 0549-Add-Destroy-Speed-API.patch} (100%) rename patches/server/{0549-Fix-Player-spawnParticle-x-y-z-precision-loss.patch => 0550-Fix-Player-spawnParticle-x-y-z-precision-loss.patch} (100%) rename patches/server/{0550-Add-LivingEntity-clearActiveItem.patch => 0551-Add-LivingEntity-clearActiveItem.patch} (100%) rename patches/server/{0551-Add-PlayerItemCooldownEvent.patch => 0552-Add-PlayerItemCooldownEvent.patch} (100%) rename patches/server/{0552-More-lightning-API.patch => 0553-More-lightning-API.patch} (100%) rename patches/server/{0553-Climbing-should-not-bypass-cramming-gamerule.patch => 0554-Climbing-should-not-bypass-cramming-gamerule.patch} (98%) rename patches/server/{0554-Added-missing-default-perms-for-commands.patch => 0555-Added-missing-default-perms-for-commands.patch} (100%) rename patches/server/{0555-Add-PlayerShearBlockEvent.patch => 0556-Add-PlayerShearBlockEvent.patch} (100%) rename patches/server/{0556-Set-spigots-verbose-world-setting-to-false-by-def.patch => 0557-Set-spigots-verbose-world-setting-to-false-by-def.patch} (100%) rename patches/server/{0557-Fix-curing-zombie-villager-discount-exploit.patch => 0558-Fix-curing-zombie-villager-discount-exploit.patch} (94%) rename patches/server/{0558-Limit-recipe-packets.patch => 0559-Limit-recipe-packets.patch} (100%) rename patches/server/{0559-Fix-CraftSound-backwards-compatibility.patch => 0560-Fix-CraftSound-backwards-compatibility.patch} (100%) rename patches/server/{0560-MC-4-Fix-item-position-desync.patch => 0561-MC-4-Fix-item-position-desync.patch} (100%) rename patches/server/{0561-Player-Chunk-Load-Unload-Events.patch => 0562-Player-Chunk-Load-Unload-Events.patch} (100%) rename patches/server/{0562-Optimize-Dynamic-get-Missing-Keys.patch => 0563-Optimize-Dynamic-get-Missing-Keys.patch} (100%) rename patches/server/{0563-Expose-LivingEntity-hurt-direction.patch => 0564-Expose-LivingEntity-hurt-direction.patch} (100%) rename patches/server/{0564-Add-OBSTRUCTED-reason-to-BedEnterResult.patch => 0565-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} (100%) rename patches/server/{0565-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch => 0566-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch} (100%) rename patches/server/{0566-added-PlayerTradeEvent.patch => 0567-added-PlayerTradeEvent.patch} (100%) rename patches/server/{0567-Implement-TargetHitEvent.patch => 0568-Implement-TargetHitEvent.patch} (100%) rename patches/server/{0568-Additional-Block-Material-API-s.patch => 0569-Additional-Block-Material-API-s.patch} (100%) rename patches/server/{0569-Fix-harming-potion-dupe.patch => 0570-Fix-harming-potion-dupe.patch} (100%) rename patches/server/{0570-Implement-API-to-get-Material-from-Boats-and-Minecar.patch => 0571-Implement-API-to-get-Material-from-Boats-and-Minecar.patch} (100%) rename patches/server/{0571-Cache-burn-durations.patch => 0572-Cache-burn-durations.patch} (100%) rename patches/server/{0572-Allow-disabling-mob-spawner-spawn-egg-transformation.patch => 0573-Allow-disabling-mob-spawner-spawn-egg-transformation.patch} (93%) rename patches/server/{0573-Implement-PlayerFlowerPotManipulateEvent.patch => 0574-Implement-PlayerFlowerPotManipulateEvent.patch} (100%) rename patches/server/{0574-Fix-interact-event-not-being-called-in-adventure.patch => 0575-Fix-interact-event-not-being-called-in-adventure.patch} (100%) rename patches/server/{0575-Zombie-API-breaking-doors.patch => 0576-Zombie-API-breaking-doors.patch} (100%) rename patches/server/{0576-Fix-nerfed-slime-when-splitting.patch => 0577-Fix-nerfed-slime-when-splitting.patch} (100%) rename patches/server/{0577-Add-EntityLoadCrossbowEvent.patch => 0578-Add-EntityLoadCrossbowEvent.patch} (100%) rename patches/server/{0578-Guardian-beam-workaround.patch => 0579-Guardian-beam-workaround.patch} (100%) rename patches/server/{0579-Added-WorldGameRuleChangeEvent.patch => 0580-Added-WorldGameRuleChangeEvent.patch} (100%) rename patches/server/{0580-Added-ServerResourcesReloadedEvent.patch => 0581-Added-ServerResourcesReloadedEvent.patch} (100%) rename patches/server/{0581-Added-world-settings-for-mobs-picking-up-loot.patch => 0582-Added-world-settings-for-mobs-picking-up-loot.patch} (95%) rename patches/server/{0582-Implemented-BlockFailedDispenseEvent.patch => 0583-Implemented-BlockFailedDispenseEvent.patch} (100%) rename patches/server/{0583-Added-PlayerLecternPageChangeEvent.patch => 0584-Added-PlayerLecternPageChangeEvent.patch} (100%) rename patches/server/{0584-Added-PlayerLoomPatternSelectEvent.patch => 0585-Added-PlayerLoomPatternSelectEvent.patch} (100%) rename patches/server/{0585-Configurable-door-breaking-difficulty.patch => 0586-Configurable-door-breaking-difficulty.patch} (92%) rename patches/server/{0586-Empty-commands-shall-not-be-dispatched.patch => 0587-Empty-commands-shall-not-be-dispatched.patch} (100%) rename patches/server/{0587-Implement-API-to-expose-exact-interaction-point.patch => 0588-Implement-API-to-expose-exact-interaction-point.patch} (96%) rename patches/server/{0588-Remove-stale-POIs.patch => 0589-Remove-stale-POIs.patch} (92%) rename patches/server/{0589-Fix-villager-boat-exploit.patch => 0590-Fix-villager-boat-exploit.patch} (100%) rename patches/server/{0590-Add-sendOpLevel-API.patch => 0591-Add-sendOpLevel-API.patch} (100%) rename patches/server/{0591-Add-StructureLocateEvent.patch => 0592-Add-StructureLocateEvent.patch} (100%) rename patches/server/{0592-Collision-option-for-requiring-a-player-participant.patch => 0593-Collision-option-for-requiring-a-player-participant.patch} (97%) rename patches/server/{0593-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch => 0594-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch} (100%) rename patches/server/{0594-Return-chat-component-with-empty-text-instead-of-thr.patch => 0595-Return-chat-component-with-empty-text-instead-of-thr.patch} (100%) rename patches/server/{0595-Make-schedule-command-per-world.patch => 0596-Make-schedule-command-per-world.patch} (100%) rename patches/server/{0596-Configurable-max-leash-distance.patch => 0597-Configurable-max-leash-distance.patch} (94%) rename patches/server/{0597-Implement-BlockPreDispenseEvent.patch => 0598-Implement-BlockPreDispenseEvent.patch} (100%) rename patches/server/{0598-Added-Vanilla-Entity-Tags.patch => 0599-Added-Vanilla-Entity-Tags.patch} (100%) rename patches/server/{0599-added-Wither-API.patch => 0600-added-Wither-API.patch} (100%) rename patches/server/{0600-Added-firing-of-PlayerChangeBeaconEffectEvent.patch => 0601-Added-firing-of-PlayerChangeBeaconEffectEvent.patch} (100%) rename patches/server/{0601-Fix-console-spam-when-removing-chests-in-water.patch => 0602-Fix-console-spam-when-removing-chests-in-water.patch} (100%) rename patches/server/{0602-Add-toggle-for-always-placing-the-dragon-egg.patch => 0603-Add-toggle-for-always-placing-the-dragon-egg.patch} (92%) rename patches/server/{0603-Added-PlayerStonecutterRecipeSelectEvent.patch => 0604-Added-PlayerStonecutterRecipeSelectEvent.patch} (100%) rename patches/server/{0604-Add-dropLeash-variable-to-EntityUnleashEvent.patch => 0605-Add-dropLeash-variable-to-EntityUnleashEvent.patch} (100%) rename patches/server/{0605-Skip-distance-map-update-when-spawning-disabled.patch => 0606-Skip-distance-map-update-when-spawning-disabled.patch} (100%) rename patches/server/{0606-Reset-shield-blocking-on-dimension-change.patch => 0607-Reset-shield-blocking-on-dimension-change.patch} (100%) rename patches/server/{0607-add-DragonEggFormEvent.patch => 0608-add-DragonEggFormEvent.patch} (100%) rename patches/server/{0608-EntityMoveEvent.patch => 0609-EntityMoveEvent.patch} (97%) rename patches/server/{0609-added-option-to-disable-pathfinding-updates-on-block.patch => 0610-added-option-to-disable-pathfinding-updates-on-block.patch} (88%) rename patches/server/{0610-Inline-shift-direction-fields.patch => 0611-Inline-shift-direction-fields.patch} (100%) rename patches/server/{0611-Allow-adding-items-to-BlockDropItemEvent.patch => 0612-Allow-adding-items-to-BlockDropItemEvent.patch} (100%) rename patches/server/{0612-Add-getMainThreadExecutor-to-BukkitScheduler.patch => 0613-Add-getMainThreadExecutor-to-BukkitScheduler.patch} (100%) rename patches/server/{0613-living-entity-allow-attribute-registration.patch => 0614-living-entity-allow-attribute-registration.patch} (100%) rename patches/server/{0614-fix-dead-slime-setSize-invincibility.patch => 0615-fix-dead-slime-setSize-invincibility.patch} (100%) rename patches/server/{0615-Merchant-getRecipes-should-return-an-immutable-list.patch => 0616-Merchant-getRecipes-should-return-an-immutable-list.patch} (100%) rename patches/server/{0616-misc-debugging-dumps.patch => 0617-misc-debugging-dumps.patch} (100%) rename patches/server/{0617-Add-support-for-hex-color-codes-in-console.patch => 0618-Add-support-for-hex-color-codes-in-console.patch} (100%) rename patches/server/{0618-Expose-Tracked-Players.patch => 0619-Expose-Tracked-Players.patch} (100%) rename patches/server/{0619-Remove-streams-from-SensorNearest.patch => 0620-Remove-streams-from-SensorNearest.patch} (100%) rename patches/server/{0620-MC-29274-Fix-Wither-hostility-towards-players.patch => 0621-MC-29274-Fix-Wither-hostility-towards-players.patch} (93%) rename patches/server/{0621-Throw-proper-exception-on-empty-JsonList-file.patch => 0622-Throw-proper-exception-on-empty-JsonList-file.patch} (100%) rename patches/server/{0622-Improve-ServerGUI.patch => 0623-Improve-ServerGUI.patch} (100%) rename patches/server/{0623-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch => 0624-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch} (100%) rename patches/server/{0624-fix-converting-txt-to-json-file.patch => 0625-fix-converting-txt-to-json-file.patch} (100%) rename patches/server/{0625-Add-worldborder-events.patch => 0626-Add-worldborder-events.patch} (100%) rename patches/server/{0626-added-PlayerNameEntityEvent.patch => 0627-added-PlayerNameEntityEvent.patch} (100%) rename patches/server/{0627-Prevent-grindstones-from-overstacking-items.patch => 0628-Prevent-grindstones-from-overstacking-items.patch} (100%) rename patches/server/{0628-Add-recipe-to-cook-events.patch => 0629-Add-recipe-to-cook-events.patch} (100%) rename patches/server/{0629-Add-Block-isValidTool.patch => 0630-Add-Block-isValidTool.patch} (100%) rename patches/server/{0630-Allow-using-signs-inside-spawn-protection.patch => 0631-Allow-using-signs-inside-spawn-protection.patch} (94%) rename patches/server/{0631-Implement-Keyed-on-World.patch => 0632-Implement-Keyed-on-World.patch} (100%) rename patches/server/{0632-Add-fast-alternative-constructor-for-Rotations.patch => 0633-Add-fast-alternative-constructor-for-Rotations.patch} (100%) rename patches/server/{0633-Item-Rarity-API.patch => 0634-Item-Rarity-API.patch} (100%) rename patches/server/{0634-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch => 0635-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch} (100%) rename patches/server/{0635-copy-TESign-isEditable-from-snapshots.patch => 0636-copy-TESign-isEditable-from-snapshots.patch} (100%) rename patches/server/{0636-Drop-carried-item-when-player-has-disconnected.patch => 0637-Drop-carried-item-when-player-has-disconnected.patch} (100%) rename patches/server/{0637-forced-whitelist-use-configurable-kick-message.patch => 0638-forced-whitelist-use-configurable-kick-message.patch} (100%) rename patches/server/{0638-Don-t-ignore-result-of-PlayerEditBookEvent.patch => 0639-Don-t-ignore-result-of-PlayerEditBookEvent.patch} (100%) rename patches/server/{0639-fix-cancelling-block-falling-causing-client-desync.patch => 0640-fix-cancelling-block-falling-causing-client-desync.patch} (100%) rename patches/server/{0640-Expose-protocol-version.patch => 0641-Expose-protocol-version.patch} (100%) rename patches/server/{0641-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch => 0642-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} (100%) rename patches/server/{0642-Enhance-console-tab-completions-for-brigadier-comman.patch => 0643-Enhance-console-tab-completions-for-brigadier-comman.patch} (100%) rename patches/server/{0643-Fix-PlayerItemConsumeEvent-cancelling-properly.patch => 0644-Fix-PlayerItemConsumeEvent-cancelling-properly.patch} (100%) rename patches/server/{0644-Add-bypass-host-check.patch => 0645-Add-bypass-host-check.patch} (100%) rename patches/server/{0645-Set-area-affect-cloud-rotation.patch => 0646-Set-area-affect-cloud-rotation.patch} (100%) rename patches/server/{0646-add-isDeeplySleeping-to-HumanEntity.patch => 0647-add-isDeeplySleeping-to-HumanEntity.patch} (100%) rename patches/server/{0647-Fix-duplicating-give-items-on-item-drop-cancel.patch => 0648-Fix-duplicating-give-items-on-item-drop-cancel.patch} (100%) rename patches/server/{0648-add-consumeFuel-to-FurnaceBurnEvent.patch => 0649-add-consumeFuel-to-FurnaceBurnEvent.patch} (100%) rename patches/server/{0649-add-get-set-drop-chance-to-EntityEquipment.patch => 0650-add-get-set-drop-chance-to-EntityEquipment.patch} (100%) rename patches/server/{0650-fix-PigZombieAngerEvent-cancellation.patch => 0651-fix-PigZombieAngerEvent-cancellation.patch} (100%) rename patches/server/{0651-Fix-checkReach-check-for-Shulker-boxes.patch => 0652-Fix-checkReach-check-for-Shulker-boxes.patch} (100%) rename patches/server/{0652-fix-PlayerItemHeldEvent-firing-twice.patch => 0653-fix-PlayerItemHeldEvent-firing-twice.patch} (100%) rename patches/server/{0653-Added-PlayerDeepSleepEvent.patch => 0654-Added-PlayerDeepSleepEvent.patch} (100%) rename patches/server/{0654-More-World-API.patch => 0655-More-World-API.patch} (100%) rename patches/server/{0655-Added-PlayerBedFailEnterEvent.patch => 0656-Added-PlayerBedFailEnterEvent.patch} (100%) rename patches/server/{0656-Implement-methods-to-convert-between-Component-and-B.patch => 0657-Implement-methods-to-convert-between-Component-and-B.patch} (100%) rename patches/server/{0657-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch => 0658-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch} (100%) rename patches/server/{0658-Introduce-beacon-activation-deactivation-events.patch => 0659-Introduce-beacon-activation-deactivation-events.patch} (100%) rename patches/server/{0659-add-RespawnFlags-to-PlayerRespawnEvent.patch => 0660-add-RespawnFlags-to-PlayerRespawnEvent.patch} (100%) rename patches/server/{0660-Add-Channel-initialization-listeners.patch => 0661-Add-Channel-initialization-listeners.patch} (100%) rename patches/server/{0661-Send-empty-commands-if-tab-completion-is-disabled.patch => 0662-Send-empty-commands-if-tab-completion-is-disabled.patch} (100%) rename patches/server/{0662-Add-more-WanderingTrader-API.patch => 0663-Add-more-WanderingTrader-API.patch} (100%) rename patches/server/{0663-Add-EntityBlockStorage-clearEntities.patch => 0664-Add-EntityBlockStorage-clearEntities.patch} (100%) rename patches/server/{0664-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch => 0665-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch} (100%) rename patches/server/{0665-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch => 0666-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch} (100%) rename patches/server/{0666-Inventory-close.patch => 0667-Inventory-close.patch} (100%) rename patches/server/{0667-call-PortalCreateEvent-players-and-end-platform.patch => 0668-call-PortalCreateEvent-players-and-end-platform.patch} (100%) rename patches/server/{0668-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch => 0669-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch} (100%) rename patches/server/{0669-Fix-CraftPotionBrewer-cache.patch => 0670-Fix-CraftPotionBrewer-cache.patch} (100%) rename patches/server/{0670-Add-basic-Datapack-API.patch => 0671-Add-basic-Datapack-API.patch} (100%) rename patches/server/{0671-Add-environment-variable-to-disable-server-gui.patch => 0672-Add-environment-variable-to-disable-server-gui.patch} (100%) rename patches/server/{0672-additions-to-PlayerGameModeChangeEvent.patch => 0673-additions-to-PlayerGameModeChangeEvent.patch} (98%) rename patches/server/{0673-ItemStack-repair-check-API.patch => 0674-ItemStack-repair-check-API.patch} (100%) rename patches/server/{0674-More-Enchantment-API.patch => 0675-More-Enchantment-API.patch} (100%) rename patches/server/{0675-Add-command-line-option-to-load-extra-plugin-jars-no.patch => 0676-Add-command-line-option-to-load-extra-plugin-jars-no.patch} (96%) rename patches/server/{0676-Fix-and-optimise-world-force-upgrading.patch => 0677-Fix-and-optimise-world-force-upgrading.patch} (95%) rename patches/server/{0677-Add-Mob-lookAt-API.patch => 0678-Add-Mob-lookAt-API.patch} (100%) rename patches/server/{0678-Add-Unix-domain-socket-support.patch => 0679-Add-Unix-domain-socket-support.patch} (100%) rename patches/server/{0679-Add-EntityInsideBlockEvent.patch => 0680-Add-EntityInsideBlockEvent.patch} (100%) rename patches/server/{0680-Attributes-API-for-item-defaults.patch => 0681-Attributes-API-for-item-defaults.patch} (100%) rename patches/server/{0681-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch => 0682-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch} (100%) rename patches/server/{0682-Add-cause-to-Weather-ThunderChangeEvents.patch => 0683-Add-cause-to-Weather-ThunderChangeEvents.patch} (98%) rename patches/server/{0683-More-Lidded-Block-API.patch => 0684-More-Lidded-Block-API.patch} (100%) rename patches/server/{0684-Limit-item-frame-cursors-on-maps.patch => 0685-Limit-item-frame-cursors-on-maps.patch} (93%) rename patches/server/{0685-Add-PufferFishStateChangeEvent.patch => 0686-Add-PufferFishStateChangeEvent.patch} (100%) rename patches/server/{0686-Add-PlayerKickEvent-causes.patch => 0687-Add-PlayerKickEvent-causes.patch} (100%) rename patches/server/{0687-Fix-PlayerBucketEmptyEvent-result-itemstack.patch => 0688-Fix-PlayerBucketEmptyEvent-result-itemstack.patch} (100%) rename patches/server/{0688-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch => 0689-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch} (71%) rename patches/server/{0689-Add-option-to-fix-items-merging-through-walls.patch => 0690-Add-option-to-fix-items-merging-through-walls.patch} (93%) rename patches/server/{0690-Add-BellRevealRaiderEvent.patch => 0691-Add-BellRevealRaiderEvent.patch} (100%) rename patches/server/{0691-Fix-invulnerable-end-crystals.patch => 0692-Fix-invulnerable-end-crystals.patch} (96%) rename patches/server/{0692-Add-ElderGuardianAppearanceEvent.patch => 0693-Add-ElderGuardianAppearanceEvent.patch} (100%) rename patches/server/{0693-Reset-villager-inventory-on-cancelled-pickup-event.patch => 0694-Reset-villager-inventory-on-cancelled-pickup-event.patch} (100%) rename patches/server/{0694-Fix-dangerous-end-portal-logic.patch => 0695-Fix-dangerous-end-portal-logic.patch} (100%) rename patches/server/{0695-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch => 0696-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch} (100%) rename patches/server/{0696-Make-item-validations-configurable.patch => 0697-Make-item-validations-configurable.patch} (100%) rename patches/server/{0697-Add-more-line-of-sight-methods.patch => 0698-Add-more-line-of-sight-methods.patch} (100%) rename patches/server/{0698-add-per-world-spawn-limits.patch => 0699-add-per-world-spawn-limits.patch} (94%) rename patches/server/{0699-Fix-PotionSplashEvent-for-water-splash-potions.patch => 0700-Fix-PotionSplashEvent-for-water-splash-potions.patch} (100%) rename patches/server/{0700-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch => 0701-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch} (100%) diff --git a/patches/removed/1.17/0364-Anti-Xray.patch b/patches/server/0364-Anti-Xray.patch similarity index 70% rename from patches/removed/1.17/0364-Anti-Xray.patch rename to patches/server/0364-Anti-Xray.patch index 250195a551..982e71aa3f 100644 --- a/patches/removed/1.17/0364-Anti-Xray.patch +++ b/patches/server/0364-Anti-Xray.patch @@ -2,12 +2,16 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: stonar96 Date: Mon, 20 Aug 2018 03:03:58 +0200 Subject: [PATCH] Anti-Xray +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + stonar96 — Today at 15:49 I'm just here to watch you suffer :smile: You can skip it if you want and I can do it later. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1278d09f70c1e97607ef20d87a178dc252c7f723..c45493e88bf7e8811be2759ff9ac19e3fe9d938a 100644 +index e29566cad2647da4d9288e912188b57f00e8dd0c..51691d3dedf113d58f340b74d448c5e5375b5bed 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -1,7 +1,9 @@ @@ -20,9 +24,9 @@ index 1278d09f70c1e97607ef20d87a178dc252c7f723..c45493e88bf7e8811be2759ff9ac19e3 import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.spigotmc.SpigotWorldConfig; -@@ -461,4 +463,38 @@ public class PaperWorldConfig { - private void maxAutoSaveChunksPerTick() { - maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); +@@ -445,5 +447,39 @@ public class PaperWorldConfig { + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); } + + public boolean antiXray; @@ -59,9 +63,10 @@ index 1278d09f70c1e97607ef20d87a178dc252c7f723..c45493e88bf7e8811be2759ff9ac19e3 + } + } } + diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java new file mode 100644 -index 0000000000000000000000000000000000000000..8fb63441fbf9afb6f11e1185a9f29528e1950546 +index 0000000000000000000000000000000000000000..fe1a91a3a281dd91e5989bf2282240b03684b500 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java @@ -0,0 +1,45 @@ @@ -90,11 +95,11 @@ index 0000000000000000000000000000000000000000..8fb63441fbf9afb6f11e1185a9f29528 + return null; + } + -+ public boolean shouldModify(ServerPlayer entityPlayer, LevelChunk chunk, int chunkSectionSelector) { ++ public boolean shouldModify(ServerPlayer entityPlayer, LevelChunk chunk) { + return false; + } + -+ public ChunkPacketInfo getChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector) { ++ public ChunkPacketInfo getChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk) { + return null; + } + @@ -112,7 +117,7 @@ index 0000000000000000000000000000000000000000..8fb63441fbf9afb6f11e1185a9f29528 +} diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java new file mode 100644 -index 0000000000000000000000000000000000000000..6d41628444e880dea5c96ad5caf557f4c56dea46 +index 0000000000000000000000000000000000000000..e1bc1093a03b931ff2c3870ea1601cd420f71192 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java @@ -0,0 +1,649 @@ @@ -200,7 +205,7 @@ index 0000000000000000000000000000000000000000..6d41628444e880dea5c96ad5caf557f4 + for (String id : paperWorldConfig.hiddenBlocks) { + Block block = Registry.BLOCK.getOptional(new ResourceLocation(id)).orElse(null); + -+ if (block != null && !block.isEntityBlock()) { ++ if (block != null && !(block instanceof net.minecraft.world.level.block.EntityBlock)) { + toObfuscate.add(id); + predefinedBlockDataList.add(block.defaultBlockState()); + } @@ -284,15 +289,15 @@ index 0000000000000000000000000000000000000000..6d41628444e880dea5c96ad5caf557f4 + } + + @Override -+ public boolean shouldModify(ServerPlayer entityPlayer, LevelChunk chunk, int chunkSectionSelector) { ++ public boolean shouldModify(ServerPlayer entityPlayer, LevelChunk chunk) { + return !usePermission || !entityPlayer.getBukkitEntity().hasPermission("paper.antixray.bypass"); + } + + @Override -+ public ChunkPacketInfoAntiXray getChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector) { ++ public ChunkPacketInfoAntiXray getChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk) { + // Return a new instance to collect data and objects in the right state while creating the chunk packet for thread safe access later + // Note: As of 1.14 this has to be moved later due to the chunk system. -+ ChunkPacketInfoAntiXray chunkPacketInfoAntiXray = new ChunkPacketInfoAntiXray(packetPlayOutMapChunk, chunk, chunkSectionSelector, this); ++ ChunkPacketInfoAntiXray chunkPacketInfoAntiXray = new ChunkPacketInfoAntiXray(packetPlayOutMapChunk, chunk, this); + return chunkPacketInfoAntiXray; + } + @@ -314,7 +319,7 @@ index 0000000000000000000000000000000000000000..6d41628444e880dea5c96ad5caf557f4 + LevelChunk chunk = chunkPacketInfo.getChunk(); + int x = chunk.getPos().x; + int z = chunk.getPos().z; -+ ServerLevel world = (ServerLevel)chunk.world; ++ ServerLevel world = (ServerLevel)chunk.level; + ((ChunkPacketInfoAntiXray) chunkPacketInfo).setNearbyChunks( + (LevelChunk) world.getChunkIfLoadedImmediately(x - 1, z), + (LevelChunk) world.getChunkIfLoadedImmediately(x + 1, z), @@ -374,7 +379,7 @@ index 0000000000000000000000000000000000000000..6d41628444e880dea5c96ad5caf557f4 + int[] predefinedBlockDataBitsTemp; + + if (chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex) == LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE) { -+ predefinedBlockDataBitsTemp = engineMode == EngineMode.HIDE ? chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.NETHER ? predefinedBlockDataBitsNetherrackGlobal : chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.THE_END ? predefinedBlockDataBitsEndStoneGlobal : predefinedBlockDataBitsStoneGlobal : predefinedBlockDataBitsGlobal; ++ predefinedBlockDataBitsTemp = engineMode == EngineMode.HIDE ? chunkPacketInfoAntiXray.getChunk().level.getWorld().getEnvironment() == Environment.NETHER ? predefinedBlockDataBitsNetherrackGlobal : chunkPacketInfoAntiXray.getChunk().level.getWorld().getEnvironment() == Environment.THE_END ? predefinedBlockDataBitsEndStoneGlobal : predefinedBlockDataBitsStoneGlobal : predefinedBlockDataBitsGlobal; + } else { + // If it's this.predefinedBlockData, use this.predefinedBlockDataFull instead + BlockState[] predefinedBlockDataFull = chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) == predefinedBlockData ? this.predefinedBlockDataFull : chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex); @@ -767,10 +772,10 @@ index 0000000000000000000000000000000000000000..6d41628444e880dea5c96ad5caf557f4 +} diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java new file mode 100644 -index 0000000000000000000000000000000000000000..dc04ffc76e11ab63cd98a84cf95c58dc5cd1efdb +index 0000000000000000000000000000000000000000..4d06356d4c183605fdaa9157da02c66990f0fb70 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java -@@ -0,0 +1,81 @@ +@@ -0,0 +1,75 @@ +package com.destroystokyo.paper.antixray; + +import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; @@ -781,17 +786,15 @@ index 0000000000000000000000000000000000000000..dc04ffc76e11ab63cd98a84cf95c58dc + + private final ClientboundLevelChunkPacket packetPlayOutMapChunk; + private final LevelChunk chunk; -+ private final int chunkSectionSelector; + private byte[] data; + private final int[] bitsPerObject = new int[16]; + private final Object[] dataPalettes = new Object[16]; + private final int[] dataBitsIndexes = new int[16]; + private final Object[][] predefinedObjects = new Object[16][]; + -+ public ChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector) { ++ public ChunkPacketInfo(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk) { + this.packetPlayOutMapChunk = packetPlayOutMapChunk; + this.chunk = chunk; -+ this.chunkSectionSelector = chunkSectionSelector; + } + + public ClientboundLevelChunkPacket getPacketPlayOutMapChunk() { @@ -802,10 +805,6 @@ index 0000000000000000000000000000000000000000..dc04ffc76e11ab63cd98a84cf95c58dc + return chunk; + } + -+ public int getChunkSectionSelector() { -+ return chunkSectionSelector; -+ } -+ + public byte[] getData() { + return data; + } @@ -854,7 +853,7 @@ index 0000000000000000000000000000000000000000..dc04ffc76e11ab63cd98a84cf95c58dc +} diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java new file mode 100644 -index 0000000000000000000000000000000000000000..7345f1dc7c5c05f2e1ee09b94f4ebf56dd59bc55 +index 0000000000000000000000000000000000000000..2339aa92ecaf3af9c7481ec6c21981c39319c76f --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java @@ -0,0 +1,30 @@ @@ -869,9 +868,9 @@ index 0000000000000000000000000000000000000000..7345f1dc7c5c05f2e1ee09b94f4ebf56 + private LevelChunk[] nearbyChunks; + private final ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray; + -+ public ChunkPacketInfoAntiXray(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, int chunkSectionSelector, ++ public ChunkPacketInfoAntiXray(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, + ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray) { -+ super(packetPlayOutMapChunk, chunk, chunkSectionSelector); ++ super(packetPlayOutMapChunk, chunk); + this.chunkPacketBlockControllerAntiXray = chunkPacketBlockControllerAntiXray; + } + @@ -1031,90 +1030,73 @@ index 0000000000000000000000000000000000000000..333763936897befda5bb6c077944d266 + } +} diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -index b587f774c8f88f2a1c3ea489f7e4fe0bbdeb5a41..10dd582b0fff4df27f1113e41c8ee3e274c6fb65 100644 +index c28879f32b004f36ff746ea2274f91ddd9501e71..7762d8ff94f856d613a6f50311006b698f2aa2b0 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -@@ -1,5 +1,6 @@ - package net.minecraft.network.protocol.game; - -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import com.google.common.collect.Lists; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.Unpooled; -@@ -16,6 +17,7 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.block.entity.BlockEntity; - import net.minecraft.world.level.block.entity.SkullBlockEntity; -+import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.level.chunk.ChunkBiomeContainer; - import net.minecraft.world.level.chunk.LevelChunk; - import net.minecraft.world.level.chunk.LevelChunkSection; -@@ -33,7 +35,13 @@ public class ClientboundLevelChunkPacket implements Packet blockEntitiesTags; - private boolean fullChunk; - -- public ClientboundLevelChunkPacket() {} -+ // Paper start - Async-Anti-Xray - Set the ready flag to true -+ private volatile boolean ready; // Paper - Async-Anti-Xray - Ready flag for the network manager -+ public ClientboundLevelChunkPacket() { -+ this.ready = true; -+ } -+ // Paper end -+ - // Paper start - private final java.util.List extraPackets = new java.util.ArrayList<>(); - private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); -@@ -43,12 +51,16 @@ public class ClientboundLevelChunkPacket implements Packet chunkPacketInfo = modifyBlocks ? chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i) : null; + +- public ClientboundLevelChunkPacket(LevelChunk chunk) { ++ private volatile boolean ready; // Paper - Async-Anti-Xray - Ready flag for the network manager ++ ++ // Paper start ++ @Deprecated public ClientboundLevelChunkPacket(LevelChunk chunk) { this(chunk, true); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public ClientboundLevelChunkPacket(LevelChunk chunk, boolean modifyBlocks) { ++ com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo = modifyBlocks ? chunk.level.chunkPacketBlockController.getChunkPacketInfo(this, chunk) : null; + // Paper end - ChunkPos chunkcoordintpair = chunk.getPos(); + ChunkPos chunkPos = chunk.getPos(); + this.x = chunkPos.x; + this.z = chunkPos.z; +@@ -51,7 +57,12 @@ public class ClientboundLevelChunkPacket implements Packet> 4; -- if (this.isFullChunk() || (includedSectionsMask & 1 << j) != 0) { -+ if (this.isFullChunk() || (i & 1 << j) != 0) { - // Paper start - improve oversized chunk data packet handling - if (++totalTileEntities > TE_LIMIT) { - ClientboundBlockEntityDataPacket updatePacket = tileentity.getUpdatePacket(); -@@ -93,8 +110,19 @@ public class ClientboundLevelChunkPacket implements Packet chunkPacketInfo) { ++ // Paper end + BitSet bitSet = new BitSet(); + LevelChunkSection[] levelChunkSections = chunk.getSections(); + int i = 0; +@@ -129,7 +143,7 @@ public class ClientboundLevelChunkPacket implements Packet chunkPacketInfo) { return this.a(packetDataSerializer, chunk, chunkSectionSelector, chunkPacketInfo); } // OBFHELPER -+ public int a(FriendlyByteBuf packetdataserializer, LevelChunk chunk, int i, ChunkPacketInfo chunkPacketInfo) { -+ // Paper end - int j = 0; - LevelChunkSection[] achunksection = chunk.getSections(); - int k = 0; -@@ -169,9 +201,9 @@ public class ClientboundLevelChunkPacket implements Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { if (packets[0] == null) { -- packets[0] = new ClientboundLevelChunkPacket(chunk, 65535); -+ packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass - packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, true); +- packets[0] = new ClientboundLevelChunkPacket(chunk); ++ packets[0] = new ClientboundLevelChunkPacket(chunk, chunk.level.chunkPacketBlockController.shouldModify(player, chunk)); // Paper - Ani-Xray - Bypass + packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, (BitSet) null, (BitSet) null, true); } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index fd7ee4badb383ffb4347d62c00ea2dfa3d76fd12..7a09bc921827958f58290bd3d6f19984bb34a8f6 100644 +index e6ef6d9b6e9a674db1180cae6263537e57b843d3..c5070975be1ceeab20ad0b3bab790426adb5e5fa 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -204,7 +204,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - +@@ -292,7 +292,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl // Add env and gen to constructor, WorldData -> WorldDataServer public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env); -+ super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor ++ super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper - pass executor this.pvpMode = minecraftserver.isPvpAllowed(); - convertable = convertable_conversionsession; - uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile()); + this.convertable = convertable_conversionsession; + this.uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile()); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index d97607f2ded4977b253d3afa3bafcbe6d7f98837..af048ab682612233c01f7087d7b8afbf7e58945b 100644 +index f4a056185990181e486f452960159a5287947382..a695e5a0c2e8846333ccb9aea499b5656af35163 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -308,6 +308,8 @@ public class ServerPlayerGameMode { +@@ -49,7 +49,7 @@ import org.bukkit.event.player.PlayerInteractEvent; + public class ServerPlayerGameMode { + + private static final Logger LOGGER = LogManager.getLogger(); +- protected ServerLevel level; ++ public ServerLevel level; // Paper - protected->public + protected final ServerPlayer player; + private GameType gameModeForPlayer; + @Nullable +@@ -314,6 +314,8 @@ public class ServerPlayerGameMode { } } @@ -1207,39 +1157,32 @@ index d97607f2ded4977b253d3afa3bafcbe6d7f98837..af048ab682612233c01f7087d7b8afbf public void destroyAndAck(BlockPos pos, ServerboundPlayerActionPacket.Action action, String reason) { diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index eb88d830fb45a6b8c990e8bdc1943d80f63c8b93..1377465e3dc062f34be25cac10aa018776fb22e7 100644 +index aa198e9f2755734eac591bd3f94679518e9d7270..687e3652d0f36a358a2348df845801ad82d8460c 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -2,6 +2,8 @@ package net.minecraft.world.level; - - import co.aikar.timings.Timing; - import co.aikar.timings.Timings; -+import com.destroystokyo.paper.antixray.ChunkPacketBlockController; // Paper - Anti-Xray -+import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray; // Paper - Anti-Xray - import com.destroystokyo.paper.event.server.ServerExceptionEvent; - import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.base.MoreObjects; -@@ -144,6 +146,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -164,6 +164,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper -+ public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray ++ public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray public final co.aikar.timings.WorldTimingsHandler timings; // Paper public static BlockPos lastPhysicsProblem; // Spigot -@@ -165,9 +168,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return typeKey; +@@ -185,9 +186,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return this.typeKey; } - protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper -+ this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray ++ this.chunkPacketBlockController = this.paperConfig.antiXray ? ++ new com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray(this, executor) ++ : com.destroystokyo.paper.antixray.ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray this.generator = gen; this.world = new CraftWorld((ServerLevel) this, gen, env); this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns(); // CraftBukkit -@@ -433,6 +437,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -448,6 +452,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { // CraftBukkit end BlockState iblockdata1 = chunk.setType(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag @@ -1247,131 +1190,98 @@ index eb88d830fb45a6b8c990e8bdc1943d80f63c8b93..1377465e3dc062f34be25cac10aa0187 if (iblockdata1 == null) { // CraftBukkit start - remove blockstate if failed (or the same) +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index c0075d226331f32e470dae5bf1ce8d79e8b263dc..91f5106cfe7914389b52a1ed001117b13e4f9768 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -75,6 +75,7 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { + default LevelChunkSection getOrCreateSection(int yIndex) { + LevelChunkSection[] levelChunkSections = this.getSections(); + if (levelChunkSections[yIndex] == LevelChunk.EMPTY_SECTION) { ++ // Paper - diff on change in ProtoChunk + levelChunkSections[yIndex] = new LevelChunkSection(this.getSectionYFromSectionIndex(yIndex)); + } + diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java -index e369730ac6909ff5343468bd685c9ea2b6b3cfed..2c19d147710a3bbe2e980114161f1cdf81760947 100644 +index 69c2454533e6f21c70792b555ec02c6bc6d169b3..2607c7ba5cf1aca5f3e5c22be2e4e8b3007427d4 100644 --- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java -@@ -8,6 +8,7 @@ import net.minecraft.Util; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Registry; - import net.minecraft.data.worldgen.biome.Biomes; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkHolder; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkPos; -@@ -28,7 +29,7 @@ public class EmptyLevelChunk extends LevelChunk { - }); +@@ -86,7 +86,7 @@ public class EmptyLevelChunk extends LevelChunk { + private static final Biome[] EMPTY_BIOMES = new Biome[0]; - public EmptyLevelChunk(Level world, ChunkPos pos) { -- super(world, pos, new ChunkBiomeContainer(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), EmptyLevelChunk.BIOMES)); -+ super(world, pos, new ChunkBiomeContainer(MinecraftServer.getServer().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), EmptyLevelChunk.BIOMES)); // Paper - world isnt ready yet for anti xray use here, use server singleton for registry - } - - // Paper start -diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -index 17fa8b23d1000ae53f2b4f1a6e8817c1005c1c81..56ab660e29a0dc7d22eeaa41cc8f50e8a96717ef 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -@@ -27,7 +27,7 @@ public class ImposterProtoChunk extends ProtoChunk { - private final LevelChunk wrapped; - - public ImposterProtoChunk(LevelChunk wrapped) { -- super(wrapped.getPos(), UpgradeData.EMPTY); -+ super(wrapped.getPos(), UpgradeData.EMPTY, wrapped.world); // Paper - Anti-Xray - Add parameter - this.wrapped = wrapped; - } + public EmptyChunkBiomeContainer(Level world) { +- super(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), world, EMPTY_BIOMES); ++ super(net.minecraft.server.MinecraftServer.getServer().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), world, EMPTY_BIOMES); // Paper - world isnt ready yet for anti xray use here, use server singleton for registry + } + @Override diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 419b4bf0549d798d52d73fbbd9de59313fc05eb1..85861545ec4620a6cfd06876dad091637bd29b0b 100644 +index 521f199e495f3bec232cc9ca36e51e0392afe737..d4e11b552988f0ef28059f9aa2ca1f1897653171 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -464,7 +464,7 @@ public class LevelChunk implements ChunkAccess { +@@ -456,7 +456,7 @@ public class LevelChunk implements ChunkAccess { return null; } -- chunksection = new LevelChunkSection(j >> 4 << 4); -+ chunksection = new LevelChunkSection(j >> 4 << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters - this.sections[j >> 4] = chunksection; +- chunksection = new LevelChunkSection(SectionPos.blockToSectionCoord(i)); ++ chunksection = new LevelChunkSection(SectionPos.blockToSectionCoord(i), this, this.level, true); // Paper - Anti-Xray - Add parameters + this.sections[j] = chunksection; } diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index f5db97fb0dac78e1d9aa68d0417aa13f39914f52..38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341 100644 +index 5fd66020a937b641e2a060cf38df731a43f3bf55..b10beabccf5a29098a796e5615eb4632fae95f99 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -1,9 +1,11 @@ - package net.minecraft.world.level.chunk; - - import java.util.function.Predicate; -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import javax.annotation.Nullable; - import net.minecraft.nbt.NbtUtils; - import net.minecraft.network.FriendlyByteBuf; -+import net.minecraft.world.level.Level; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.BlockState; -@@ -18,16 +20,22 @@ public class LevelChunkSection { +@@ -20,16 +20,25 @@ public class LevelChunkSection { private short tickingFluidCount; final PalettedContainer states; // Paper - package-private - public LevelChunkSection(int yOffset) { -- this(yOffset, (short) 0, (short) 0, (short) 0); +- this(yOffset, (short)0, (short)0, (short)0); + // Paper start - Anti-Xray - Add parameters + @Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public LevelChunkSection(int i, ChunkAccess chunk, Level world, boolean initializeBlocks) { -+ this(i, (short) 0, (short) 0, (short) 0, chunk, world, initializeBlocks); ++ public LevelChunkSection(int yOffset, ChunkAccess chunk, net.minecraft.server.level.ServerLevel world, boolean initializeBlocks) { + // Paper end ++ this(yOffset, (short) 0, (short) 0, (short) 0, chunk, world, initializeBlocks); } - public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount) { -- this.bottomBlockY = yOffset; -- this.nonEmptyBlockCount = nonEmptyBlockCount; -- this.tickingBlockCount = randomTickableBlockCount; -- this.tickingFluidCount = nonEmptyFluidCount; -- this.states = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); + // Paper start - Anti-Xray - Add parameters -+ @Deprecated public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount) { this(yOffset, nonEmptyBlockCount, randomTickableBlockCount, nonEmptyFluidCount, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public LevelChunkSection(int i, short short0, short short1, short short2, ChunkAccess chunk, Level world, boolean initializeBlocks) { ++ @Deprecated public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount) { // Notice for updates: Please make sure this constructor isn't used anywhere ++ this(yOffset, nonEmptyBlockCount, randomTickableBlockCount, nonEmptyFluidCount, null, null, true); ++ } ++ public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount, ChunkAccess chunk, net.minecraft.server.level.ServerLevel world, boolean initializeBlocks) { + // Paper end -+ this.bottomBlockY = i; -+ this.nonEmptyBlockCount = short0; -+ this.tickingBlockCount = short1; -+ this.tickingFluidCount = short2; -+ this.states = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState(), world == null ? null : world.chunkPacketBlockController.getPredefinedBlockData(world, chunk, this, initializeBlocks), initializeBlocks); // Paper - Anti-Xray - Add predefined block data + this.bottomBlockY = getBottomBlockY(yOffset); + this.nonEmptyBlockCount = nonEmptyBlockCount; + this.tickingBlockCount = randomTickableBlockCount; + this.tickingFluidCount = nonEmptyFluidCount; +- this.states = new PalettedContainer<>(GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); ++ this.states = new PalettedContainer<>(GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState(), ++ world == null ? null : world.chunkPacketBlockController.getPredefinedBlockData(world, chunk, this, initializeBlocks), initializeBlocks); // Paper - Anti-Xray - Add predefined block data } - public final BlockState getBlockState(int x, int y, int z) { // Paper -@@ -139,10 +147,14 @@ public class LevelChunkSection { - return this.states; + public static int getBottomBlockY(int chunkPos) { +@@ -147,9 +156,12 @@ public class LevelChunkSection { + this.states.read(buf); } -- public void writeChunkSection(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER -- public void write(FriendlyByteBuf packetdataserializer) { -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public final void writeChunkSection(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public final void write(FriendlyByteBuf packetdataserializer) { this.writeChunkSection(packetdataserializer, null); } // Notice for updates: Please make sure this method isn't used anywhere -+ public final void writeChunkSection(FriendlyByteBuf packetDataSerializer, ChunkPacketInfo chunkPacketInfo) { this.b(packetDataSerializer, chunkPacketInfo); } // OBFHELPER -+ public void b(FriendlyByteBuf packetdataserializer, ChunkPacketInfo chunkPacketInfo) { +- public void write(FriendlyByteBuf buf) { ++ // Paper start ++ @Deprecated public void write(FriendlyByteBuf buf) { write(buf, null); } // Notice for updates: Please make sure this method isn't used anywhere ++ public void write(FriendlyByteBuf buf, com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo) { + // Paper end - packetdataserializer.writeShort(this.nonEmptyBlockCount); -- this.states.write(packetdataserializer); -+ this.states.writeDataPaletteBlock(packetdataserializer, chunkPacketInfo, this.bottomBlockY >> 4); // Paper - Anti-Xray - Add chunk packet info + buf.writeShort(this.nonEmptyBlockCount); +- this.states.write(buf); ++ this.states.write(buf, chunkPacketInfo, this.bottomBlockY >> 4); // Paper - Anti-Xray - Add chunk packet info } public int getSerializedSize() { diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index 917b0a64083ebbe24321089b784b91f3af4918b9..dd252372e1e380674b1191e9ea265cbb10de437b 100644 +index 5ea60bbb56450502f1ceb41959239ab579458ac2..efe4d45b431890e4821f977b8f9fafdab7de3be2 100644 --- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -1,6 +1,7 @@ - package net.minecraft.world.level.chunk; - - import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import java.util.Arrays; - import java.util.Objects; - import java.util.concurrent.locks.ReentrantLock; -@@ -26,6 +27,7 @@ public class PalettedContainer implements PaletteResize { +@@ -28,6 +28,7 @@ public class PalettedContainer implements PaletteResize { private final Function reader; private final Function writer; private final T defaultValue; @@ -1379,26 +1289,23 @@ index 917b0a64083ebbe24321089b784b91f3af4918b9..dd252372e1e380674b1191e9ea265cbb protected BitStorage storage; public final BitStorage getDataBits() { return this.storage; } // Paper - OBFHELPER private Palette palette; private Palette getDataPalette() { return this.palette; } // Paper - OBFHELPER private int bits; private int getBitsPerObject() { return this.bits; } // Paper - OBFHELPER -@@ -50,14 +52,47 @@ public class PalettedContainer implements PaletteResize { - //this.j.unlock(); // Paper - disable this +@@ -48,15 +49,51 @@ public class PalettedContainer implements PaletteResize { + this.lock.release(); } - public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { -- this.globalPalette = fallbackPalette; -- this.registry = idList; -- this.reader = elementDeserializer; -- this.writer = elementSerializer; -- this.defaultValue = defaultElement; -- this.setBits(4); + // Paper start - Anti-Xray - Add predefined objects -+ @Deprecated public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { this(fallbackPalette, idList, elementDeserializer, elementSerializer, defaultElement, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public PalettedContainer(Palette datapalette, IdMapper registryblockid, Function function, Function function1, T t0, T[] predefinedObjects, boolean initialize) { ++ @Deprecated public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { // Notice for updates: Please make sure this constructor isn't used anywhere ++ this(fallbackPalette, idList, elementDeserializer, elementSerializer, defaultElement, null, true); ++ } ++ public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement, T[] predefinedObjects, boolean initialize) { + // Paper end -+ this.globalPalette = datapalette; -+ this.registry = registryblockid; -+ this.reader = function; -+ this.writer = function1; -+ this.defaultValue = t0; + this.globalPalette = fallbackPalette; + this.registry = idList; + this.reader = elementDeserializer; + this.writer = elementSerializer; + this.defaultValue = defaultElement; + this.setBits(4); + // Paper start - Anti-Xray - Add predefined objects + this.predefinedObjects = predefinedObjects; + @@ -1420,168 +1327,119 @@ index 917b0a64083ebbe24321089b784b91f3af4918b9..dd252372e1e380674b1191e9ea265cbb + } + } + // Paper end -+ } -+ + } + + // Paper start - Anti-Xray - Add predefined objects + private void addPredefinedObjects() { -+ if (this.predefinedObjects != null && this.getDataPalette() != this.getDataPaletteGlobal()) { -+ for (int i = 0; i < this.predefinedObjects.length; i++) { -+ this.getDataPalette().getOrCreateIdFor(this.predefinedObjects[i]); ++ if (this.predefinedObjects != null && this.palette != this.globalPalette) { ++ for (T predefinedObject : this.predefinedObjects) { ++ this.palette.getOrCreateIdFor(predefinedObject); + } + } - } ++ } + // Paper end - ++ private static int getIndex(int x, int y, int z) { return y << 8 | z << 4 | x; -@@ -92,6 +127,7 @@ public class PalettedContainer implements PaletteResize { - - int j; + } +@@ -86,6 +123,7 @@ public class PalettedContainer implements PaletteResize { + Palette palette = this.palette; + this.setBits(newSize); + this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects - for (j = 0; j < databits.getSize(); ++j) { - T t1 = datapalette.valueFor(databits.get(j)); - -@@ -141,24 +177,38 @@ public class PalettedContainer implements PaletteResize { - return t0 == null ? this.defaultValue : t0; + for(int i = 0; i < bitStorage.getSize(); ++i) { + T object = palette.valueFor(bitStorage.get(i)); + if (object != null) { +@@ -161,11 +199,24 @@ public class PalettedContainer implements PaletteResize { } -- public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER -- public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize + public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER +- public void write(FriendlyByteBuf buf) { + // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public void write(FriendlyByteBuf buf) { this.writeDataPaletteBlock(buf, null, 0); } // Notice for updates: Please make sure this method isn't used anywhere -+ public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { this.b(packetDataSerializer, chunkPacketInfo, chunkSectionIndex); } // OBFHELPER -+ public synchronized void b(FriendlyByteBuf packetdataserializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { // Paper - synchronize ++ @Deprecated public void write(FriendlyByteBuf buf) { ++ write(buf, null, 0); ++ } ++ public void write(FriendlyByteBuf buf, com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { + // Paper end - this.acquire(); -- buf.writeByte(this.bits); -- this.palette.write(buf); -- buf.writeLongArray(this.storage.getRaw()); -+ packetdataserializer.writeByte(this.bits); -+ this.palette.write(packetdataserializer); -+ // Paper start - Anti-Xray - Add chunk packet info -+ if (chunkPacketInfo != null) { -+ chunkPacketInfo.setBitsPerObject(chunkSectionIndex, this.getBitsPerObject()); -+ chunkPacketInfo.setDataPalette(chunkSectionIndex, this.getDataPalette()); -+ chunkPacketInfo.setDataBitsIndex(chunkSectionIndex, packetdataserializer.writerIndex() + FriendlyByteBuf.countBytes(this.getDataBits().getDataBits().length)); -+ chunkPacketInfo.setPredefinedObjects(chunkSectionIndex, this.predefinedObjects); -+ } -+ // Paper end -+ packetdataserializer.writeLongArray(this.storage.getRaw()); - this.release(); - } + try { + this.acquire(); + buf.writeByte(this.bits); + this.palette.write(buf); ++ // Paper start - Anti-Xray - Add chunk packet info ++ if (chunkPacketInfo != null) { ++ chunkPacketInfo.setBitsPerObject(chunkSectionIndex, this.bits); ++ chunkPacketInfo.setDataPalette(chunkSectionIndex, this.palette); ++ chunkPacketInfo.setDataBitsIndex(chunkSectionIndex, buf.writerIndex() + FriendlyByteBuf.getVarIntSize(this.storage.getDataBits().length)); ++ chunkPacketInfo.setPredefinedObjects(chunkSectionIndex, this.predefinedObjects); ++ } ++ // Paper end + buf.writeLongArray(this.storage.getRaw()); + } finally { + this.release(); +@@ -176,12 +227,14 @@ public class PalettedContainer implements PaletteResize { + public void read(ListTag paletteNbt, long[] data) { + try { + this.acquire(); +- int i = Math.max(4, Mth.ceillog2(paletteNbt.size())); +- if (i != this.bits) { ++ // Paper - Anti-Xray - TODO: Should this.predefinedObjects.length just be added here (faster) or should the contents be compared to calculate the size (less RAM)? ++ int i = Math.max(4, Mth.ceillog2(paletteNbt.size() + (this.predefinedObjects == null ? 0 : this.predefinedObjects.length))); // Paper - Anti-Xray - Calculate the size with predefined objects ++ if (true || i != this.bits) { // Paper - Anti-Xray - Not initialized yet + this.setBits(i); + } - public synchronized void read(ListTag paletteTag, long[] data) { // Paper - synchronize - this.acquire(); -- int i = Math.max(4, Mth.ceillog2(paletteTag.size())); -+ // Paper - Anti-Xray - TODO: Should this.predefinedObjects.length just be added here (faster) or should the contents be compared to calculate the size (less RAM)? -+ int i = Math.max(4, Mth.ceillog2(paletteTag.size() + (this.predefinedObjects == null ? 0 : this.predefinedObjects.length))); // Paper - Anti-Xray - Calculate the size with predefined objects - -- if (i != this.bits) { -+ if (true || i != this.bits) { // Paper - Anti-Xray - Not initialized yet - this.setBits(i); - } - - this.palette.read(paletteTag); -+ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects - int j = data.length * 64 / 4096; - - if (this.palette == this.globalPalette) { + this.palette.read(paletteNbt); ++ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects + int j = data.length * 64 / 4096; + if (this.palette == this.globalPalette) { + Palette palette = new HashMapPalette<>(this.registry, i, this.dummyPaletteResize, this.reader, this.writer); diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index d8b7b210484079c9ca2c34831c84102cba6692f5..87fd585141ad9818fca0b697cb4c87248fe7ce11 100644 +index 245998e2cea32cf15ee2659639c647f449704ec0..cd41b9ee682248a9abde1bf046e54c7e6e485470 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -64,16 +64,24 @@ public class ProtoChunk implements ChunkAccess { +@@ -63,7 +63,7 @@ public class ProtoChunk implements ChunkAccess { private long inhabitedTime; - private final Map carvingMasks; + private final Map carvingMasks = new Object2ObjectArrayMap<>(); private volatile boolean isLightCorrect; -+ private final Level world; // Paper - Anti-Xray - Add world +- final net.minecraft.world.level.Level level; // Paper - Add level ++ final net.minecraft.server.level.ServerLevel level; // Paper - Add level -- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { -- this(pos, upgradeData, (LevelChunkSection[]) null, new ProtoTickList<>((block) -> { -+ // Paper start - Anti-Xray - Add world -+ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { this(pos, upgradeData, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ProtoChunk(ChunkPos chunkcoordintpair, UpgradeData chunkconverter, Level world) { -+ // Paper end -+ this(chunkcoordintpair, chunkconverter, (LevelChunkSection[]) null, new ProtoTickList<>((block) -> { - return block == null || block.defaultBlockState().isAir(); -- }, pos), new ProtoTickList<>((fluidtype) -> { -+ }, chunkcoordintpair), new ProtoTickList<>((fluidtype) -> { - return fluidtype == null || fluidtype == Fluids.EMPTY; -- }, pos)); -+ }, chunkcoordintpair), world); // Paper - Anti-Xray - Add world + // Paper start - add level + @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) { this(pos, upgradeData, world, null); } +@@ -506,4 +506,15 @@ public class ProtoChunk implements ChunkAccess { + public int getHeight() { + return this.levelHeightAccessor.getHeight(); } - -- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] sections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler) { -+ // Paper start - Anti-Xray - Add world -+ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] sections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler) { this(pos, upgradeData, sections, blockTickScheduler, fluidTickScheduler, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ProtoChunk(ChunkPos chunkcoordintpair, UpgradeData chunkconverter, @Nullable LevelChunkSection[] achunksection, ProtoTickList protochunkticklist, ProtoTickList protochunkticklist1, Level world) { -+ this.world = world; -+ // Paper end - this.heightmaps = Maps.newEnumMap(Heightmap.Types.class); - this.status = ChunkStatus.EMPTY; - this.blockEntities = Maps.newHashMap(); -@@ -85,15 +93,15 @@ public class ProtoChunk implements ChunkAccess { - this.structureStarts = Maps.newHashMap(); - this.structuresRefences = Maps.newHashMap(); - this.carvingMasks = new Object2ObjectArrayMap(); -- this.chunkPos = pos; -- this.upgradeData = upgradeData; -- this.blockTicks = blockTickScheduler; -- this.liquidTicks = fluidTickScheduler; -- if (sections != null) { -- if (this.sections.length == sections.length) { -- System.arraycopy(sections, 0, this.sections, 0, this.sections.length); -+ this.chunkPos = chunkcoordintpair; -+ this.upgradeData = chunkconverter; -+ this.blockTicks = protochunkticklist; -+ this.liquidTicks = protochunkticklist1; -+ if (achunksection != null) { -+ if (this.sections.length == achunksection.length) { -+ System.arraycopy(achunksection, 0, this.sections, 0, this.sections.length); - } else { -- ProtoChunk.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", sections.length, this.sections.length); -+ ProtoChunk.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", achunksection.length, this.sections.length); - } - } - -@@ -228,7 +236,7 @@ public class ProtoChunk implements ChunkAccess { - - public LevelChunkSection getOrCreateSection(int y) { - if (this.sections[y] == LevelChunk.EMPTY_SECTION) { -- this.sections[y] = new LevelChunkSection(y << 4); -+ this.sections[y] = new LevelChunkSection(y << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters - } - - return this.sections[y]; ++ ++ @Override ++ public net.minecraft.world.level.chunk.LevelChunkSection getOrCreateSection(final int yIndex) { ++ LevelChunkSection[] levelChunkSections = this.getSections(); ++ if (levelChunkSections[yIndex] == LevelChunk.EMPTY_SECTION) { ++ // Paper - diff on change in ProtoChunk ++ levelChunkSections[yIndex] = new LevelChunkSection(this.getSectionYFromSectionIndex(yIndex), this, this.level, true); // Paper - Anti-Xray - Add parameters ++ } ++ ++ return levelChunkSections[yIndex]; ++ } + } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 969130442b529eaac6f708107ff129f89cc0af90..8dbd1dc2de400ad0c6c2be49ba09dfc03216ffd2 100644 +index 7c04aef3eac54981ca1e34cb87d97104c3c9685b..097d38f12ef324dbb529a833383e2da949377f9c 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -101,7 +101,7 @@ public class ChunkSerializer { +@@ -136,7 +136,7 @@ public class ChunkSerializer { byte b0 = nbttagcompound2.getByte("Y"); if (nbttagcompound2.contains("Palette", 9) && nbttagcompound2.contains("BlockStates", 12)) { -- LevelChunkSection chunksection = new LevelChunkSection(b0 << 4); -+ LevelChunkSection chunksection = new LevelChunkSection(b0 << 4, null, world, false); // Paper - Anti-Xray - Add parameters +- LevelChunkSection chunksection = new LevelChunkSection(b0); ++ LevelChunkSection chunksection = new LevelChunkSection(b0, null, world, false); // Paper - Anti-Xray - Add parameters chunksection.getStates().read(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); chunksection.recalcBlockCounts(); -@@ -165,7 +165,7 @@ public class ChunkSerializer { - // CraftBukkit end - }); - } else { -- ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1); -+ ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world); // Paper - Anti-Xray - Add parameter - - protochunk.setBiomes(biomestorage); - object = protochunk; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index 423594177fe78600755d913f169f28dd1bfa2b37..74bad15034d9d55fb70931f38868f812160c6305 100644 +index 245d764d3dcc549fa8acbd7c9024a3c88d2d2a74..4dd7cea1eec5ec55a3700ce9786da8a513e72a28 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -43,7 +43,7 @@ public class CraftChunk implements Chunk { +@@ -46,7 +46,7 @@ public class CraftChunk implements Chunk { private final ServerLevel worldServer; private final int x; private final int z; @@ -1590,7 +1448,7 @@ index 423594177fe78600755d913f169f28dd1bfa2b37..74bad15034d9d55fb70931f38868f812 private static final byte[] emptyLight = new byte[2048]; public CraftChunk(net.minecraft.world.level.chunk.LevelChunk chunk) { -@@ -287,7 +287,7 @@ public class CraftChunk implements Chunk { +@@ -275,7 +275,7 @@ public class CraftChunk implements Chunk { CompoundTag data = new CompoundTag(); cs[i].getStates().write(data, "Palette", "BlockStates"); @@ -1600,27 +1458,27 @@ index 423594177fe78600755d913f169f28dd1bfa2b37..74bad15034d9d55fb70931f38868f812 sectionBlockIDs[i] = blockids; diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index a94c65f4d63a06be099fd67b0b7756c5b45b84a0..8d72cd6a44cf462cfe3adac9bf99a16883a587df 100644 +index 3d905c98704da64cefd009b2c796b24e729396a5..fe7851476636dfed02339d4d9f93824b96086769 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -21,9 +21,11 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { +@@ -22,9 +22,11 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { private final int maxHeight; private final LevelChunkSection[] sections; private Set tiles; + private World world; // Paper - Anti-Xray - Add world public CraftChunkData(World world) { - this(world.getMaxHeight()); + this(world.getMinHeight(), world.getMaxHeight()); + this.world = world; // Paper - Anti-Xray - Add world } - /* pp for tests */ CraftChunkData(int maxHeight) { -@@ -157,7 +159,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - private LevelChunkSection getChunkSection(int y, boolean create) { - LevelChunkSection section = sections[y >> 4]; + /* pp for tests */ CraftChunkData(int minHeight, int maxHeight) { +@@ -162,7 +164,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + int offset = (y - this.minHeight) >> 4; + LevelChunkSection section = this.sections[offset]; if (create && section == null) { -- sections[y >> 4] = section = new LevelChunkSection(y >> 4 << 4); -+ sections[y >> 4] = section = new LevelChunkSection(y >> 4 << 4, null, world instanceof org.bukkit.craftbukkit.CraftWorld ? ((org.bukkit.craftbukkit.CraftWorld) world).getHandle() : null, true); // Paper - Anti-Xray - Add parameters +- this.sections[offset] = section = new LevelChunkSection(offset + (this.minHeight >> 4)); ++ this.sections[offset] = section = new LevelChunkSection(offset + (this.minHeight >> 4), null, world instanceof org.bukkit.craftbukkit.CraftWorld ? ((org.bukkit.craftbukkit.CraftWorld) world).getHandle() : null, true); // Paper - Anti-Xray - Add parameters } return section; } diff --git a/patches/server/0364-No-Tick-view-distance-implementation.patch b/patches/server/0365-No-Tick-view-distance-implementation.patch similarity index 98% rename from patches/server/0364-No-Tick-view-distance-implementation.patch rename to patches/server/0365-No-Tick-view-distance-implementation.patch index 96b59e1789..ef60b4aa37 100644 --- a/patches/server/0364-No-Tick-view-distance-implementation.patch +++ b/patches/server/0365-No-Tick-view-distance-implementation.patch @@ -23,20 +23,21 @@ index f27fadc15cb7f5c782e45885ec6a5a69963beade..2ff4d4921e2076abf415bd3c8f5173ec })); diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e29566cad2647da4d9288e912188b57f00e8dd0c..3cd8895adecd345c3bdfb8b5e3e9fdf0ef9097db 100644 +index 51691d3dedf113d58f340b74d448c5e5375b5bed..b2f0102c2a15eb4324367f52e03e534bff883f9b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -445,5 +445,10 @@ public class PaperWorldConfig { - private void lightQueueSize() { +@@ -448,6 +448,11 @@ public class PaperWorldConfig { lightQueueSize = getInt("light-queue-size", lightQueueSize); } -+ + + public int noTickViewDistance; + private void viewDistance() { + this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); + } - } - ++ + public boolean antiXray; + public EngineMode engineMode; + public int maxChunkSectionIndex; diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java index bb0a07a280c7d4885165e9d6488e7741aaa7b47c..9c88426ab1275ee5fb6e28be8b213533dc4ab859 100644 --- a/src/main/java/net/minecraft/server/MCUtil.java @@ -144,7 +145,7 @@ index 3653ec6f93d627092e63cede51f4db2e12b10613..995d7977233f0d7683c00a75c3833f9a public CompletableFuture> getOrScheduleFuture(ChunkStatus targetStatus, ChunkMap chunkStorage) { diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 480c361c919bbfbebacf9ac94418eac5ed38e233..fdf5d8ede4b01e399272ddebfbd49258b166f00b 100644 +index 56dece64f19009583c94569c5713c2ad0c91ae17..b0cf6e186d7030b1aa9296671683bd33e2d15579 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -122,7 +122,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -486,7 +487,7 @@ index 480c361c919bbfbebacf9ac94418eac5ed38e233..fdf5d8ede4b01e399272ddebfbd49258 + + public void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { // Paper - private -> public if (packets[0] == null) { - packets[0] = new ClientboundLevelChunkPacket(chunk); + packets[0] = new ClientboundLevelChunkPacket(chunk, chunk.level.chunkPacketBlockController.shouldModify(player, chunk)); // Paper - Ani-Xray - Bypass packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, (BitSet) null, (BitSet) null, true); diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java index 45c7ebe67019cdbe88b6617a95d5c40d3a68286c..38eebda226e007c8910e04f502ce218cdfe1d456 100644 @@ -556,10 +557,10 @@ index bcc946d2747443c34ee8ac2485a5ab41773c93af..2730923bd0bf3b0f928765b9e09e2299 while (iterator.hasNext()) { diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index aa198e9f2755734eac591bd3f94679518e9d7270..507a70521a97c463d6fd22b788c39e9f458971c3 100644 +index 687e3652d0f36a358a2348df845801ad82d8460c..4eee8156d193f59b7e28499f492f81247c4b1591 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -522,8 +522,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -527,8 +527,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); } @@ -575,7 +576,7 @@ index aa198e9f2755734eac591bd3f94679518e9d7270..507a70521a97c463d6fd22b788c39e9f if ((i & 1) != 0) { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 521f199e495f3bec232cc9ca36e51e0392afe737..922026da8c234427e0322443004d3c32993adfce 100644 +index d4e11b552988f0ef28059f9aa2ca1f1897653171..f6b591f045ae992180806fd6aba309c0d04e722b 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -33,7 +33,10 @@ import net.minecraft.core.Registry; diff --git a/patches/server/0365-Implement-alternative-item-despawn-rate.patch b/patches/server/0366-Implement-alternative-item-despawn-rate.patch similarity index 76% rename from patches/server/0365-Implement-alternative-item-despawn-rate.patch rename to patches/server/0366-Implement-alternative-item-despawn-rate.patch index 5db80421d3..889c22011c 100644 --- a/patches/server/0365-Implement-alternative-item-despawn-rate.patch +++ b/patches/server/0366-Implement-alternative-item-despawn-rate.patch @@ -5,44 +5,29 @@ Subject: [PATCH] Implement alternative item-despawn-rate diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3cd8895adecd345c3bdfb8b5e3e9fdf0ef9097db..be4a36df28d4f16727daad1270d5c3a84ae94613 100644 +index b2f0102c2a15eb4324367f52e03e534bff883f9b..3f4a9ce31981f77b1c451a5d9ba91d6c9ab67587 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -1,8 +1,13 @@ - package com.destroystokyo.paper; - -+import java.util.EnumMap; -+import java.util.HashMap; - import java.util.List; -+import java.util.Map; - - import org.bukkit.Bukkit; -+import org.bukkit.Material; -+import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -450,5 +455,53 @@ public class PaperWorldConfig { - private void viewDistance() { +@@ -453,6 +453,54 @@ public class PaperWorldConfig { this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); } -+ + + public boolean altItemDespawnRateEnabled; -+ public Map altItemDespawnRateMap; ++ public java.util.Map altItemDespawnRateMap; + private void altItemDespawnRate() { + String path = "alt-item-despawn-rate"; + + altItemDespawnRateEnabled = getBoolean(path + ".enabled", false); + -+ Map altItemDespawnRateMapDefault = new EnumMap<>(Material.class); -+ altItemDespawnRateMapDefault.put(Material.COBBLESTONE, 300); -+ for (Material key : altItemDespawnRateMapDefault.keySet()) { ++ java.util.Map altItemDespawnRateMapDefault = new java.util.EnumMap<>(org.bukkit.Material.class); ++ altItemDespawnRateMapDefault.put(org.bukkit.Material.COBBLESTONE, 300); ++ for (org.bukkit.Material key : altItemDespawnRateMapDefault.keySet()) { + config.addDefault("world-settings.default." + path + ".items." + key, altItemDespawnRateMapDefault.get(key)); + } + -+ Map rawMap = new HashMap<>(); ++ java.util.Map rawMap = new java.util.HashMap<>(); + try { -+ ConfigurationSection mapSection = config.getConfigurationSection("world-settings." + worldName + "." + path + ".items"); ++ org.bukkit.configuration.ConfigurationSection mapSection = config.getConfigurationSection("world-settings." + worldName + "." + path + ".items"); + if (mapSection == null) { + mapSection = config.getConfigurationSection("world-settings.default." + path + ".items"); + } @@ -56,26 +41,28 @@ index 3cd8895adecd345c3bdfb8b5e3e9fdf0ef9097db..be4a36df28d4f16727daad1270d5c3a8 + altItemDespawnRateEnabled = false; + } + -+ altItemDespawnRateMap = new EnumMap<>(Material.class); ++ altItemDespawnRateMap = new java.util.EnumMap<>(org.bukkit.Material.class); + if (!altItemDespawnRateEnabled) { + return; + } + + for(String key : rawMap.keySet()) { + try { -+ altItemDespawnRateMap.put(Material.valueOf(key), rawMap.get(key)); ++ altItemDespawnRateMap.put(org.bukkit.Material.valueOf(key), rawMap.get(key)); + } catch (Exception e) { + logError("Could not add item " + key + " to altItemDespawnRateMap: " + e.getMessage()); + } + } + if(altItemDespawnRateEnabled) { -+ for(Material key : altItemDespawnRateMap.keySet()) { ++ for(org.bukkit.Material key : altItemDespawnRateMap.keySet()) { + log("Alternative item despawn rate of " + key + ": " + altItemDespawnRateMap.get(key)); + } + } + } - } - ++ + public boolean antiXray; + public EngineMode engineMode; + public int maxChunkSectionIndex; diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java index 9ee1dc89dd4c6b9453e1f6f92208d454877d23c9..e0c13a112c95eed9867d4608e18dc797b0c9c9cf 100644 --- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java diff --git a/patches/server/0366-Tracking-Range-Improvements.patch b/patches/server/0367-Tracking-Range-Improvements.patch similarity index 97% rename from patches/server/0366-Tracking-Range-Improvements.patch rename to patches/server/0367-Tracking-Range-Improvements.patch index b4d6875ed4..a8cc0ab069 100644 --- a/patches/server/0366-Tracking-Range-Improvements.patch +++ b/patches/server/0367-Tracking-Range-Improvements.patch @@ -8,7 +8,7 @@ Sets tracking range of watermobs to animals instead of misc and simplifies code Also ignores Enderdragon, defaulting it to Mojang's setting diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index fdf5d8ede4b01e399272ddebfbd49258b166f00b..273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c 100644 +index b0cf6e186d7030b1aa9296671683bd33e2d15579..280bd301b7005d16fec293311f11485b94ded550 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -1791,6 +1791,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially diff --git a/patches/server/0367-Fix-items-vanishing-through-end-portal.patch b/patches/server/0368-Fix-items-vanishing-through-end-portal.patch similarity index 100% rename from patches/server/0367-Fix-items-vanishing-through-end-portal.patch rename to patches/server/0368-Fix-items-vanishing-through-end-portal.patch diff --git a/patches/server/0368-implement-optional-per-player-mob-spawns.patch b/patches/server/0369-implement-optional-per-player-mob-spawns.patch similarity index 97% rename from patches/server/0368-implement-optional-per-player-mob-spawns.patch rename to patches/server/0369-implement-optional-per-player-mob-spawns.patch index 27117d65e3..0ddeaece3a 100644 --- a/patches/server/0368-implement-optional-per-player-mob-spawns.patch +++ b/patches/server/0369-implement-optional-per-player-mob-spawns.patch @@ -25,11 +25,11 @@ index fe79c0add4f7cb18d487c5bb9415c40c5b551ea2..8d9ddad1879e7616d980ca70de8aecac poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index be4a36df28d4f16727daad1270d5c3a84ae94613..16f013ffe992a934e9d0b32e764a14a8fd204449 100644 +index 3f4a9ce31981f77b1c451a5d9ba91d6c9ab67587..a69efd1a21a667c5eee539f6c761755479375527 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -503,5 +503,10 @@ public class PaperWorldConfig { - } +@@ -534,5 +534,10 @@ public class PaperWorldConfig { + Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); } } + @@ -545,18 +545,10 @@ index 0000000000000000000000000000000000000000..11de56afaf059b00fa5bec293516bcdc + } +} diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c..e1498a5a8e664b922c77a8524ed2ea38c91834ce 100644 +index 280bd301b7005d16fec293311f11485b94ded550..d3f835a0c76ce559fb5f3c39714a3312c7e865d1 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -69,6 +69,7 @@ import net.minecraft.util.thread.ProcessorMailbox; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; - import net.minecraft.world.entity.Mob; -+import net.minecraft.world.entity.MobCategory; - import net.minecraft.world.entity.ai.village.poi.PoiManager; - import net.minecraft.world.entity.boss.EnderDragonPart; - import net.minecraft.world.level.ChunkPos; -@@ -140,6 +141,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -140,6 +140,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider private final Long2ByteMap chunkTypeCache; private final Queue unloadQueue; int viewDistance; @@ -564,7 +556,7 @@ index 273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c..e1498a5a8e664b922c77a8524ed2ea38 // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() public final CallbackExecutor callbackExecutor = new CallbackExecutor(); -@@ -263,6 +265,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -263,6 +264,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.overworldDataStorage = persistentStateManagerFactory; this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world); this.setViewDistance(viewDistance); @@ -572,7 +564,7 @@ index 273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c..e1498a5a8e664b922c77a8524ed2ea38 // Paper start - no-tick view distance this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -@@ -304,6 +307,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -304,6 +306,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // Paper end - no-tick view distance } @@ -590,7 +582,7 @@ index 273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c..e1498a5a8e664b922c77a8524ed2ea38 + } + } + -+ public int getMobCountNear(ServerPlayer entityPlayer, MobCategory enumCreatureType) { ++ public int getMobCountNear(ServerPlayer entityPlayer, net.minecraft.world.entity.MobCategory enumCreatureType) { + return entityPlayer.mobCounts[enumCreatureType.ordinal()]; + } + // Paper end diff --git a/patches/server/0369-Avoid-hopper-searches-if-there-are-no-items.patch b/patches/server/0370-Avoid-hopper-searches-if-there-are-no-items.patch similarity index 97% rename from patches/server/0369-Avoid-hopper-searches-if-there-are-no-items.patch rename to patches/server/0370-Avoid-hopper-searches-if-there-are-no-items.patch index f2b4f51f8e..d0bab4c136 100644 --- a/patches/server/0369-Avoid-hopper-searches-if-there-are-no-items.patch +++ b/patches/server/0370-Avoid-hopper-searches-if-there-are-no-items.patch @@ -14,10 +14,10 @@ And since minecart hoppers are used _very_ rarely near we can avoid alot of sear Combined, this adds up a lot. diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 507a70521a97c463d6fd22b788c39e9f458971c3..1dc1f7a5319e067b5f56c2fdadf04547ae1bc9ea 100644 +index 4eee8156d193f59b7e28499f492f81247c4b1591..641f022c4c716e0441a098f4540fd008059a4b51 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -984,7 +984,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -989,7 +989,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } } diff --git a/patches/server/0370-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/0371-Bees-get-gravity-in-void.-Fixes-MC-167279.patch similarity index 100% rename from patches/server/0370-Bees-get-gravity-in-void.-Fixes-MC-167279.patch rename to patches/server/0371-Bees-get-gravity-in-void.-Fixes-MC-167279.patch diff --git a/patches/server/0371-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server/0372-Optimise-getChunkAt-calls-for-loaded-chunks.patch similarity index 100% rename from patches/server/0371-Optimise-getChunkAt-calls-for-loaded-chunks.patch rename to patches/server/0372-Optimise-getChunkAt-calls-for-loaded-chunks.patch diff --git a/patches/server/0372-Allow-overriding-the-java-version-check.patch b/patches/server/0373-Allow-overriding-the-java-version-check.patch similarity index 100% rename from patches/server/0372-Allow-overriding-the-java-version-check.patch rename to patches/server/0373-Allow-overriding-the-java-version-check.patch diff --git a/patches/server/0373-Add-ThrownEggHatchEvent.patch b/patches/server/0374-Add-ThrownEggHatchEvent.patch similarity index 100% rename from patches/server/0373-Add-ThrownEggHatchEvent.patch rename to patches/server/0374-Add-ThrownEggHatchEvent.patch diff --git a/patches/server/0374-Optimise-random-block-ticking.patch b/patches/server/0375-Optimise-random-block-ticking.patch similarity index 95% rename from patches/server/0374-Optimise-random-block-ticking.patch rename to patches/server/0375-Optimise-random-block-ticking.patch index f5938a4275..99d7609598 100644 --- a/patches/server/0374-Optimise-random-block-ticking.patch +++ b/patches/server/0375-Optimise-random-block-ticking.patch @@ -71,7 +71,7 @@ index 0000000000000000000000000000000000000000..3edc8e52e06a62ce9f8cc734fd7458b3 + } +} diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 8d72e68fe8f7d0a770264f54c539ea11f5e1d8da..50efe1bd6a62b71007bf3274f323704be1477ce7 100644 +index c5070975be1ceeab20ad0b3bab790426adb5e5fa..86ee1b535a6e586fd4e9e3c37f439d81b4508939 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -667,7 +667,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl @@ -266,10 +266,10 @@ index e638d982b4bd1d261a7282cad6dab98ad0b55213..e305173fd1652a8b88ae8a9b94d0fae0 public BlockPos getHomePos() { // Paper - public diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 1dc1f7a5319e067b5f56c2fdadf04547ae1bc9ea..9d5dcaabe43ee36259b24063b4c74daddc7df773 100644 +index 641f022c4c716e0441a098f4540fd008059a4b51..944b28b55a38352dfb49aeecca3f196502cb04e8 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1300,10 +1300,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1305,10 +1305,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public abstract TagContainer getTagManager(); public BlockPos getBlockRandomPos(int x, int y, int z, int l) { @@ -290,7 +290,7 @@ index 1dc1f7a5319e067b5f56c2fdadf04547ae1bc9ea..9d5dcaabe43ee36259b24063b4c74dad public boolean noSave() { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 922026da8c234427e0322443004d3c32993adfce..88b053d8181d2a5abdb2c5527529a81855e1de7c 100644 +index f6b591f045ae992180806fd6aba309c0d04e722b..338e93a1855cf0e535e8a9897cffaff1d2e87279 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -568,6 +568,7 @@ public class LevelChunk implements ChunkAccess { @@ -302,7 +302,7 @@ index 922026da8c234427e0322443004d3c32993adfce..88b053d8181d2a5abdb2c5527529a818 public int getHeight(Heightmap.Types type, int x, int z) { return ((Heightmap) this.heightmaps.get(type)).getFirstAvailable(x & 15, z & 15) - 1; diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index 5fd66020a937b641e2a060cf38df731a43f3bf55..b5497272bc03a290298b5a829bdf653ac986866b 100644 +index b10beabccf5a29098a796e5615eb4632fae95f99..79fda9a003ca4088404d3f0490c0c6a12afa1711 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java @@ -14,11 +14,12 @@ public class LevelChunkSection { @@ -318,9 +318,9 @@ index 5fd66020a937b641e2a060cf38df731a43f3bf55..b5497272bc03a290298b5a829bdf653a final PalettedContainer states; // Paper - package-private + public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper - public LevelChunkSection(int yOffset) { - this(yOffset, (short)0, (short)0, (short)0); -@@ -70,6 +71,9 @@ public class LevelChunkSection { + // Paper start - Anti-Xray - Add parameters + @Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere +@@ -79,6 +80,9 @@ public class LevelChunkSection { --this.nonEmptyBlockCount; if (blockState.isRandomlyTicking()) { --this.tickingBlockCount; @@ -330,7 +330,7 @@ index 5fd66020a937b641e2a060cf38df731a43f3bf55..b5497272bc03a290298b5a829bdf653a } } -@@ -81,6 +85,9 @@ public class LevelChunkSection { +@@ -90,6 +94,9 @@ public class LevelChunkSection { ++this.nonEmptyBlockCount; if (state.isRandomlyTicking()) { ++this.tickingBlockCount; @@ -340,7 +340,7 @@ index 5fd66020a937b641e2a060cf38df731a43f3bf55..b5497272bc03a290298b5a829bdf653a } } -@@ -116,22 +123,28 @@ public class LevelChunkSection { +@@ -125,22 +132,28 @@ public class LevelChunkSection { } public void recalcBlockCounts() { @@ -375,10 +375,10 @@ index 5fd66020a937b641e2a060cf38df731a43f3bf55..b5497272bc03a290298b5a829bdf653a } diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index 5ea60bbb56450502f1ceb41959239ab579458ac2..5ac948b5b82f3144cdf402af440251cb8c7369d7 100644 +index efe4d45b431890e4821f977b8f9fafdab7de3be2..82a4b7969e36940cb694bd999b8c03f9c66a71dc 100644 --- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -259,6 +259,14 @@ public class PalettedContainer implements PaletteResize { +@@ -312,6 +312,14 @@ public class PalettedContainer implements PaletteResize { }); } diff --git a/patches/server/0375-Entity-Jump-API.patch b/patches/server/0376-Entity-Jump-API.patch similarity index 100% rename from patches/server/0375-Entity-Jump-API.patch rename to patches/server/0376-Entity-Jump-API.patch diff --git a/patches/server/0376-Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/0377-Add-option-to-nerf-pigmen-from-nether-portals.patch similarity index 95% rename from patches/server/0376-Add-option-to-nerf-pigmen-from-nether-portals.patch rename to patches/server/0377-Add-option-to-nerf-pigmen-from-nether-portals.patch index 683ab55aea..276ef35f7c 100644 --- a/patches/server/0376-Add-option-to-nerf-pigmen-from-nether-portals.patch +++ b/patches/server/0377-Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to nerf pigmen from nether portals diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 16f013ffe992a934e9d0b32e764a14a8fd204449..6c7e90f9939d42fdf8d40dd7ec0a6a86d5437451 100644 +index a69efd1a21a667c5eee539f6c761755479375527..8b460378d8c2dd1942404f332d4012acb5687773 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -446,6 +446,11 @@ public class PaperWorldConfig { +@@ -443,6 +443,11 @@ public class PaperWorldConfig { log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); } diff --git a/patches/server/0377-Make-the-GUI-graph-fancier.patch b/patches/server/0378-Make-the-GUI-graph-fancier.patch similarity index 100% rename from patches/server/0377-Make-the-GUI-graph-fancier.patch rename to patches/server/0378-Make-the-GUI-graph-fancier.patch diff --git a/patches/server/0378-add-hand-to-BlockMultiPlaceEvent.patch b/patches/server/0379-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from patches/server/0378-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/server/0379-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/patches/server/0379-Prevent-teleporting-dead-entities.patch b/patches/server/0380-Prevent-teleporting-dead-entities.patch similarity index 100% rename from patches/server/0379-Prevent-teleporting-dead-entities.patch rename to patches/server/0380-Prevent-teleporting-dead-entities.patch diff --git a/patches/server/0380-Validate-tripwire-hook-placement-before-update.patch b/patches/server/0381-Validate-tripwire-hook-placement-before-update.patch similarity index 100% rename from patches/server/0380-Validate-tripwire-hook-placement-before-update.patch rename to patches/server/0381-Validate-tripwire-hook-placement-before-update.patch diff --git a/patches/server/0381-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server/0382-Add-option-to-allow-iron-golems-to-spawn-in-air.patch similarity index 92% rename from patches/server/0381-Add-option-to-allow-iron-golems-to-spawn-in-air.patch rename to patches/server/0382-Add-option-to-allow-iron-golems-to-spawn-in-air.patch index 3f7ba7afc5..89293c2bda 100644 --- a/patches/server/0381-Add-option-to-allow-iron-golems-to-spawn-in-air.patch +++ b/patches/server/0382-Add-option-to-allow-iron-golems-to-spawn-in-air.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to allow iron golems to spawn in air diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6c7e90f9939d42fdf8d40dd7ec0a6a86d5437451..3ac4fe247dd12e039396da5276b83709957823c7 100644 +index 8b460378d8c2dd1942404f332d4012acb5687773..a2b1e2c3c4bd958b6ec7b7de5561747d3a2075d2 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -385,6 +385,11 @@ public class PaperWorldConfig { +@@ -382,6 +382,11 @@ public class PaperWorldConfig { scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); } diff --git a/patches/server/0382-Configurable-chance-of-villager-zombie-infection.patch b/patches/server/0383-Configurable-chance-of-villager-zombie-infection.patch similarity index 94% rename from patches/server/0382-Configurable-chance-of-villager-zombie-infection.patch rename to patches/server/0383-Configurable-chance-of-villager-zombie-infection.patch index 2e4e196e34..bf91ca7a1e 100644 --- a/patches/server/0382-Configurable-chance-of-villager-zombie-infection.patch +++ b/patches/server/0383-Configurable-chance-of-villager-zombie-infection.patch @@ -8,10 +8,10 @@ This allows you to solve an issue in vanilla behavior where: * On normal difficulty they will have a 50% of getting infected or dying. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3ac4fe247dd12e039396da5276b83709957823c7..0863bdab8322b80a3df52c238b55c14401bafe6d 100644 +index a2b1e2c3c4bd958b6ec7b7de5561747d3a2075d2..c3f2cdedf7b9c2ff9e33b823cb20890cba0ded8a 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -456,6 +456,11 @@ public class PaperWorldConfig { +@@ -453,6 +453,11 @@ public class PaperWorldConfig { nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); } diff --git a/patches/server/0383-Optimise-Chunk-getFluid.patch b/patches/server/0384-Optimise-Chunk-getFluid.patch similarity index 92% rename from patches/server/0383-Optimise-Chunk-getFluid.patch rename to patches/server/0384-Optimise-Chunk-getFluid.patch index 13d8263759..07dd478b16 100644 --- a/patches/server/0383-Optimise-Chunk-getFluid.patch +++ b/patches/server/0384-Optimise-Chunk-getFluid.patch @@ -8,7 +8,7 @@ faster on its own, however removing the try catch makes it easier to inline due to code size diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 88b053d8181d2a5abdb2c5527529a81855e1de7c..59a77541bbda880ae8f84e3535a2b6112caa78fb 100644 +index 338e93a1855cf0e535e8a9897cffaff1d2e87279..a4398502dd0cbbceb00cffc68702d34bf8ed7e8f 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -461,18 +461,20 @@ public class LevelChunk implements ChunkAccess { @@ -49,10 +49,10 @@ index 88b053d8181d2a5abdb2c5527529a81855e1de7c..59a77541bbda880ae8f84e3535a2b611 // CraftBukkit start diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index b5497272bc03a290298b5a829bdf653ac986866b..fa350db3f4ada07a385d9f57b46aa799effb6039 100644 +index 79fda9a003ca4088404d3f0490c0c6a12afa1711..9ca27907c6e1d4d5cc79e954136c63a59d3be2b8 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -42,7 +42,7 @@ public class LevelChunkSection { +@@ -51,7 +51,7 @@ public class LevelChunkSection { } public FluidState getFluidState(int x, int y, int z) { diff --git a/patches/server/0384-Optimise-TickListServer-by-rewriting-it.patch b/patches/server/0385-Optimise-TickListServer-by-rewriting-it.patch similarity index 99% rename from patches/server/0384-Optimise-TickListServer-by-rewriting-it.patch rename to patches/server/0385-Optimise-TickListServer-by-rewriting-it.patch index 40dbc4fec4..16152bd344 100644 --- a/patches/server/0384-Optimise-TickListServer-by-rewriting-it.patch +++ b/patches/server/0385-Optimise-TickListServer-by-rewriting-it.patch @@ -941,7 +941,7 @@ index 56aa640eb0096e5c5f1a34d6f11a4dd9ac8770df..a81c773cc281ba390d3ce44c52c43710 public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier supplier) { this.level = world; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 50efe1bd6a62b71007bf3274f323704be1477ce7..a43839ddd468d7b61d5609f22fb1e9fcd873590a 100644 +index 86ee1b535a6e586fd4e9e3c37f439d81b4508939..d037b14b34658e2f13d7e77f06576c406abc8a60 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -289,6 +289,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0385-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/0386-Pillager-patrol-spawn-settings-and-per-player-option.patch similarity index 97% rename from patches/server/0385-Pillager-patrol-spawn-settings-and-per-player-option.patch rename to patches/server/0386-Pillager-patrol-spawn-settings-and-per-player-option.patch index b2bc5ab21f..2a6264e464 100644 --- a/patches/server/0385-Pillager-patrol-spawn-settings-and-per-player-option.patch +++ b/patches/server/0386-Pillager-patrol-spawn-settings-and-per-player-option.patch @@ -10,10 +10,10 @@ When not per player it will use the Vanilla mechanic of one delay per world and the world age for the start day. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0863bdab8322b80a3df52c238b55c14401bafe6d..4a2b52b5f5c0453c204765ec77e35524ee7e77c1 100644 +index c3f2cdedf7b9c2ff9e33b823cb20890cba0ded8a..8f1dcdb3b1beddb5698f596c048869d99e1f4437 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -433,10 +433,21 @@ public class PaperWorldConfig { +@@ -430,10 +430,21 @@ public class PaperWorldConfig { } public boolean disablePillagerPatrols = false; diff --git a/patches/server/0386-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server/0387-Remote-Connections-shouldn-t-hold-up-shutdown.patch similarity index 100% rename from patches/server/0386-Remote-Connections-shouldn-t-hold-up-shutdown.patch rename to patches/server/0387-Remote-Connections-shouldn-t-hold-up-shutdown.patch diff --git a/patches/server/0387-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/0388-Do-not-allow-bees-to-load-chunks-for-beehives.patch similarity index 100% rename from patches/server/0387-Do-not-allow-bees-to-load-chunks-for-beehives.patch rename to patches/server/0388-Do-not-allow-bees-to-load-chunks-for-beehives.patch diff --git a/patches/server/0388-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server/0389-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch similarity index 91% rename from patches/server/0388-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch rename to patches/server/0389-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch index 09f26df53f..1a65d627cd 100644 --- a/patches/server/0388-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ b/patches/server/0389-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -7,10 +7,10 @@ Suspected case would be around the technique used in .stopRiding Stack will identify any causer of this and warn instead of crashing. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index e1498a5a8e664b922c77a8524ed2ea38c91834ce..71d5c298e14869d9d44226aeb6ffe3f051827d1a 100644 +index d3f835a0c76ce559fb5f3c39714a3312c7e865d1..002561c87ddd03e8bc31864ddd9dee7bc2ff0931 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1467,6 +1467,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1466,6 +1466,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider protected void addEntity(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot @@ -26,7 +26,7 @@ index e1498a5a8e664b922c77a8524ed2ea38c91834ce..71d5c298e14869d9d44226aeb6ffe3f0 EntityType entitytypes = entity.getType(); int i = entitytypes.clientTrackingRange() * 16; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 03939f43ade3859a53ccf90e7fc221555ce6e97f..7340a25e49af30ecbb4b212365b9941e24e221d2 100644 +index d037b14b34658e2f13d7e77f06576c406abc8a60..9cdfd1c8bce3adb5d3ad6d970c6f46ca75f3a952 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -2120,7 +2120,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0389-Optimize-Collision-to-not-load-chunks.patch b/patches/server/0390-Optimize-Collision-to-not-load-chunks.patch similarity index 100% rename from patches/server/0389-Optimize-Collision-to-not-load-chunks.patch rename to patches/server/0390-Optimize-Collision-to-not-load-chunks.patch diff --git a/patches/server/0390-Don-t-tick-dead-players.patch b/patches/server/0391-Don-t-tick-dead-players.patch similarity index 100% rename from patches/server/0390-Don-t-tick-dead-players.patch rename to patches/server/0391-Don-t-tick-dead-players.patch diff --git a/patches/server/0391-Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server/0392-Dead-Player-s-shouldn-t-be-able-to-move.patch similarity index 100% rename from patches/server/0391-Dead-Player-s-shouldn-t-be-able-to-move.patch rename to patches/server/0392-Dead-Player-s-shouldn-t-be-able-to-move.patch diff --git a/patches/server/0392-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/0393-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch similarity index 96% rename from patches/server/0392-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch rename to patches/server/0393-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch index 66741a4086..2eaf2e2ef7 100644 --- a/patches/server/0392-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch +++ b/patches/server/0393-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch @@ -70,10 +70,10 @@ index 9c88426ab1275ee5fb6e28be8b213533dc4ab859..87c9a5c1b43f6010898d72136b5eb997 List allChunks = new ArrayList<>(visibleChunks.values()); List players = world.players; diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 71d5c298e14869d9d44226aeb6ffe3f051827d1a..a75de538835522f92e889452fddd5a3d8fc25f07 100644 +index 002561c87ddd03e8bc31864ddd9dee7bc2ff0931..a80c4517cd0d2c5e7b71b4f86b6a8d441a9eb64e 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -108,9 +108,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -107,9 +107,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider private static final int MIN_VIEW_DISTANCE = 3; public static final int MAX_VIEW_DISTANCE = 33; public static final int MAX_CHUNK_DISTANCE = 33 + ChunkStatus.maxDistance(); @@ -112,7 +112,7 @@ index 71d5c298e14869d9d44226aeb6ffe3f051827d1a..a75de538835522f92e889452fddd5a3d private final Long2ObjectLinkedOpenHashMap pendingUnloads; public final LongSet entitiesInLevel; // Paper - private -> public public final ServerLevel level; -@@ -233,7 +260,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -232,7 +259,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { super(new File(session.getDimensionPath(world.dimension()), "region"), dataFixer, dsync); @@ -121,7 +121,7 @@ index 71d5c298e14869d9d44226aeb6ffe3f051827d1a..a75de538835522f92e889452fddd5a3d this.pendingUnloads = new Long2ObjectLinkedOpenHashMap(); this.entitiesInLevel = new LongOpenHashSet(); this.toDrop = new LongOpenHashSet(); -@@ -372,9 +399,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -371,9 +398,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return (ChunkHolder) this.updatingChunkMap.get(pos); } @@ -175,7 +175,7 @@ index 71d5c298e14869d9d44226aeb6ffe3f051827d1a..a75de538835522f92e889452fddd5a3d } protected IntSupplier getChunkQueueLevel(long pos) { -@@ -531,8 +601,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -530,8 +600,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } protected void saveAllChunks(boolean flush) { @@ -186,7 +186,7 @@ index 71d5c298e14869d9d44226aeb6ffe3f051827d1a..a75de538835522f92e889452fddd5a3d MutableBoolean mutableboolean = new MutableBoolean(); do { -@@ -563,7 +634,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -562,7 +633,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // this.i(); // Paper - nuke IOWorker ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); } else { @@ -195,7 +195,7 @@ index 71d5c298e14869d9d44226aeb6ffe3f051827d1a..a75de538835522f92e889452fddd5a3d ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error if (ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk) { -@@ -723,7 +794,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -722,7 +793,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (!this.modified) { return false; } else { @@ -217,7 +217,7 @@ index 71d5c298e14869d9d44226aeb6ffe3f051827d1a..a75de538835522f92e889452fddd5a3d this.modified = false; return true; } -@@ -1132,12 +1216,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1131,12 +1215,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } protected Iterable getChunks() { diff --git a/patches/server/0393-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/patches/server/0394-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch similarity index 99% rename from patches/server/0393-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch rename to patches/server/0394-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch index 7f241bc382..f70626a470 100644 --- a/patches/server/0393-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch +++ b/patches/server/0394-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch @@ -226,7 +226,7 @@ index 34183527a23650706a9249ffac0182cb77b18086..90decfade57b2f17cdcc9188962c2d21 // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task public boolean pollTask() { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index da85bfe5de9dcd6d51605ce9b023265b5a5f2936..f10fad84e4f36f9158383b327170593f273cecd9 100644 +index 9cdfd1c8bce3adb5d3ad6d970c6f46ca75f3a952..70106dda486d685dffafc0d4b3ae95b4861c6342 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -581,6 +581,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0394-Don-t-move-existing-players-to-world-spawn.patch b/patches/server/0395-Don-t-move-existing-players-to-world-spawn.patch similarity index 100% rename from patches/server/0394-Don-t-move-existing-players-to-world-spawn.patch rename to patches/server/0395-Don-t-move-existing-players-to-world-spawn.patch diff --git a/patches/server/0395-Add-tick-times-API-and-mspt-command.patch b/patches/server/0396-Add-tick-times-API-and-mspt-command.patch similarity index 100% rename from patches/server/0395-Add-tick-times-API-and-mspt-command.patch rename to patches/server/0396-Add-tick-times-API-and-mspt-command.patch diff --git a/patches/server/0396-Expose-MinecraftServer-isRunning.patch b/patches/server/0397-Expose-MinecraftServer-isRunning.patch similarity index 100% rename from patches/server/0396-Expose-MinecraftServer-isRunning.patch rename to patches/server/0397-Expose-MinecraftServer-isRunning.patch diff --git a/patches/server/0397-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/0398-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 100% rename from patches/server/0397-Add-Raw-Byte-ItemStack-Serialization.patch rename to patches/server/0398-Add-Raw-Byte-ItemStack-Serialization.patch diff --git a/patches/server/0398-Remove-streams-from-Mob-AI-System.patch b/patches/server/0399-Remove-streams-from-Mob-AI-System.patch similarity index 100% rename from patches/server/0398-Remove-streams-from-Mob-AI-System.patch rename to patches/server/0399-Remove-streams-from-Mob-AI-System.patch diff --git a/patches/server/0399-Async-command-map-building.patch b/patches/server/0400-Async-command-map-building.patch similarity index 100% rename from patches/server/0399-Async-command-map-building.patch rename to patches/server/0400-Async-command-map-building.patch diff --git a/patches/server/0400-Improved-Watchdog-Support.patch b/patches/server/0401-Improved-Watchdog-Support.patch similarity index 98% rename from patches/server/0400-Improved-Watchdog-Support.patch rename to patches/server/0401-Improved-Watchdog-Support.patch index 17dd04331c..b979bd4e07 100644 --- a/patches/server/0400-Improved-Watchdog-Support.patch +++ b/patches/server/0401-Improved-Watchdog-Support.patch @@ -262,10 +262,10 @@ index 0511f1921193b78cbf4d8426136bf1f79746f955..e5f7f043cbdb28d85b8aa0eea7cbaeb5 @Override diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index a75de538835522f92e889452fddd5a3d8fc25f07..ccf50500b53f7336db1d3d287ec6f2a0da3d4183 100644 +index a80c4517cd0d2c5e7b71b4f86b6a8d441a9eb64e..3994cefe74481efd5d779f22c752aadc22b4749b 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -607,6 +607,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -606,6 +606,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider MutableBoolean mutableboolean = new MutableBoolean(); do { @@ -299,10 +299,10 @@ index 0ef3c4982df88a7991a56d983ac733daa8adc507..cdd797c6fc7507a0e6376f7d9c521be8 } diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 9d5dcaabe43ee36259b24063b4c74daddc7df773..06f2f76636804cd5f997bbe1558a104bc24aa84a 100644 +index 944b28b55a38352dfb49aeecca3f196502cb04e8..54fcdcef2a6b68e4b4f4c6a090e84919fe76b073 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -837,6 +837,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -842,6 +842,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { try { tickConsumer.accept(entity); } catch (Throwable throwable) { @@ -311,7 +311,7 @@ index 9d5dcaabe43ee36259b24063b4c74daddc7df773..06f2f76636804cd5f997bbe1558a104b String msg = "Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ(); System.err.println(msg); diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 59a77541bbda880ae8f84e3535a2b6112caa78fb..a63dc77db41dab79f03ef7384da55c1cdeca5d98 100644 +index a4398502dd0cbbceb00cffc68702d34bf8ed7e8f..bde00ca058f32eb55e940614f0fbc361fe3a501d 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -1320,6 +1320,7 @@ public class LevelChunk implements ChunkAccess { diff --git a/patches/server/0401-Optimize-Pathfinding.patch b/patches/server/0402-Optimize-Pathfinding.patch similarity index 100% rename from patches/server/0401-Optimize-Pathfinding.patch rename to patches/server/0402-Optimize-Pathfinding.patch diff --git a/patches/server/0402-Reduce-Either-Optional-allocation.patch b/patches/server/0403-Reduce-Either-Optional-allocation.patch similarity index 100% rename from patches/server/0402-Reduce-Either-Optional-allocation.patch rename to patches/server/0403-Reduce-Either-Optional-allocation.patch diff --git a/patches/server/0403-Remove-streams-from-PairedQueue.patch b/patches/server/0404-Remove-streams-from-PairedQueue.patch similarity index 100% rename from patches/server/0403-Remove-streams-from-PairedQueue.patch rename to patches/server/0404-Remove-streams-from-PairedQueue.patch diff --git a/patches/server/0404-Reduce-memory-footprint-of-NBTTagCompound.patch b/patches/server/0405-Reduce-memory-footprint-of-NBTTagCompound.patch similarity index 100% rename from patches/server/0404-Reduce-memory-footprint-of-NBTTagCompound.patch rename to patches/server/0405-Reduce-memory-footprint-of-NBTTagCompound.patch diff --git a/patches/server/0405-Prevent-opening-inventories-when-frozen.patch b/patches/server/0406-Prevent-opening-inventories-when-frozen.patch similarity index 100% rename from patches/server/0405-Prevent-opening-inventories-when-frozen.patch rename to patches/server/0406-Prevent-opening-inventories-when-frozen.patch diff --git a/patches/server/0406-Optimise-ArraySetSorted-removeIf.patch b/patches/server/0407-Optimise-ArraySetSorted-removeIf.patch similarity index 100% rename from patches/server/0406-Optimise-ArraySetSorted-removeIf.patch rename to patches/server/0407-Optimise-ArraySetSorted-removeIf.patch diff --git a/patches/server/0407-Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server/0408-Don-t-run-entity-collision-code-if-not-needed.patch similarity index 100% rename from patches/server/0407-Don-t-run-entity-collision-code-if-not-needed.patch rename to patches/server/0408-Don-t-run-entity-collision-code-if-not-needed.patch diff --git a/patches/server/0408-Restrict-vanilla-teleport-command-to-valid-locations.patch b/patches/server/0409-Restrict-vanilla-teleport-command-to-valid-locations.patch similarity index 100% rename from patches/server/0408-Restrict-vanilla-teleport-command-to-valid-locations.patch rename to patches/server/0409-Restrict-vanilla-teleport-command-to-valid-locations.patch diff --git a/patches/server/0409-Implement-Player-Client-Options-API.patch b/patches/server/0410-Implement-Player-Client-Options-API.patch similarity index 100% rename from patches/server/0409-Implement-Player-Client-Options-API.patch rename to patches/server/0410-Implement-Player-Client-Options-API.patch diff --git a/patches/server/0410-Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server/0411-Fix-Chunk-Post-Processing-deadlock-risk.patch similarity index 93% rename from patches/server/0410-Fix-Chunk-Post-Processing-deadlock-risk.patch rename to patches/server/0411-Fix-Chunk-Post-Processing-deadlock-risk.patch index 0818f079c0..e7af5f978e 100644 --- a/patches/server/0410-Fix-Chunk-Post-Processing-deadlock-risk.patch +++ b/patches/server/0411-Fix-Chunk-Post-Processing-deadlock-risk.patch @@ -25,10 +25,10 @@ This successfully fixed a reoccurring and highly reproduceable crash for heightmaps. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index ccf50500b53f7336db1d3d287ec6f2a0da3d4183..f651b7d2bbc2fc883bc73ef892de62624d1285e7 100644 +index 3994cefe74481efd5d779f22c752aadc22b4749b..dede8863193423858f6d60cc942919e52f28b607 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -191,6 +191,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -190,6 +190,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider }; // CraftBukkit end @@ -36,7 +36,7 @@ index ccf50500b53f7336db1d3d287ec6f2a0da3d4183..f651b7d2bbc2fc883bc73ef892de6262 // Paper start - distance maps private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); // Paper start - no-tick view distance -@@ -1050,7 +1051,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1049,7 +1050,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return Either.left(chunk); }); }, (runnable) -> { diff --git a/patches/server/0411-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/patches/server/0412-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch similarity index 100% rename from patches/server/0411-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch rename to patches/server/0412-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch diff --git a/patches/server/0412-Broadcast-join-message-to-console.patch b/patches/server/0413-Broadcast-join-message-to-console.patch similarity index 100% rename from patches/server/0412-Broadcast-join-message-to-console.patch rename to patches/server/0413-Broadcast-join-message-to-console.patch diff --git a/patches/server/0413-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/patches/server/0414-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch similarity index 96% rename from patches/server/0413-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch rename to patches/server/0414-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch index fe9800e326..d9ef680f7d 100644 --- a/patches/server/0413-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch +++ b/patches/server/0414-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch @@ -28,10 +28,10 @@ receives a deterministic result, and should no longer require 1 tick delays anymore. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index f651b7d2bbc2fc883bc73ef892de62624d1285e7..6c763b5407425b764839b921f4dc9e18d76442cd 100644 +index dede8863193423858f6d60cc942919e52f28b607..4fe5b75661de64474698495776ebb8232fd252aa 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1551,7 +1551,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1550,7 +1550,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // Paper end - per player view distance } @@ -40,7 +40,7 @@ index f651b7d2bbc2fc883bc73ef892de62624d1285e7..6c763b5407425b764839b921f4dc9e18 org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot // Paper start - ignore and warn about illegal addEntity calls instead of crashing server if (!entity.valid || entity.level != this.level || this.entityMap.containsKey(entity.getId())) { -@@ -1560,6 +1560,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1559,6 +1559,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider .printStackTrace(); return; } diff --git a/patches/server/0414-Load-Chunks-for-Login-Asynchronously.patch b/patches/server/0415-Load-Chunks-for-Login-Asynchronously.patch similarity index 100% rename from patches/server/0414-Load-Chunks-for-Login-Asynchronously.patch rename to patches/server/0415-Load-Chunks-for-Login-Asynchronously.patch diff --git a/patches/server/0415-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/patches/server/0416-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch similarity index 100% rename from patches/server/0415-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch rename to patches/server/0416-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch diff --git a/patches/server/0416-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server/0417-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from patches/server/0416-Add-PlayerAttackEntityCooldownResetEvent.patch rename to patches/server/0417-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/patches/server/0417-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/patches/server/0418-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch similarity index 93% rename from patches/server/0417-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch rename to patches/server/0418-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch index 9ced634f50..e74eba1280 100644 --- a/patches/server/0417-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch +++ b/patches/server/0418-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch @@ -14,10 +14,10 @@ Use an ArrayDeque to store this Queue We make sure to also implement a pattern that is recursion safe too. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 6c763b5407425b764839b921f4dc9e18d76442cd..f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c 100644 +index 4fe5b75661de64474698495776ebb8232fd252aa..3e45ddc39d1283661cbfc1057aa0548d940a444a 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -174,17 +174,29 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -173,17 +173,29 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public final CallbackExecutor callbackExecutor = new CallbackExecutor(); public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { diff --git a/patches/server/0418-Don-t-fire-BlockFade-on-worldgen-threads.patch b/patches/server/0419-Don-t-fire-BlockFade-on-worldgen-threads.patch similarity index 100% rename from patches/server/0418-Don-t-fire-BlockFade-on-worldgen-threads.patch rename to patches/server/0419-Don-t-fire-BlockFade-on-worldgen-threads.patch diff --git a/patches/server/0419-Add-phantom-creative-and-insomniac-controls.patch b/patches/server/0420-Add-phantom-creative-and-insomniac-controls.patch similarity index 96% rename from patches/server/0419-Add-phantom-creative-and-insomniac-controls.patch rename to patches/server/0420-Add-phantom-creative-and-insomniac-controls.patch index ae7582ec64..91912af6f4 100644 --- a/patches/server/0419-Add-phantom-creative-and-insomniac-controls.patch +++ b/patches/server/0420-Add-phantom-creative-and-insomniac-controls.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add phantom creative and insomniac controls diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4a2b52b5f5c0453c204765ec77e35524ee7e77c1..16cf7d116e3ffd44ffc4f060b4014b52389cff77 100644 +index 8f1dcdb3b1beddb5698f596c048869d99e1f4437..98416de3dfc9d16d17124902e19cbd9b916077d2 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -477,6 +477,13 @@ public class PaperWorldConfig { +@@ -474,6 +474,13 @@ public class PaperWorldConfig { lightQueueSize = getInt("light-queue-size", lightQueueSize); } diff --git a/patches/server/0420-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/patches/server/0421-Fix-numerous-item-duplication-issues-and-teleport-is.patch similarity index 100% rename from patches/server/0420-Fix-numerous-item-duplication-issues-and-teleport-is.patch rename to patches/server/0421-Fix-numerous-item-duplication-issues-and-teleport-is.patch diff --git a/patches/server/0421-Implement-Brigadier-Mojang-API.patch b/patches/server/0422-Implement-Brigadier-Mojang-API.patch similarity index 100% rename from patches/server/0421-Implement-Brigadier-Mojang-API.patch rename to patches/server/0422-Implement-Brigadier-Mojang-API.patch diff --git a/patches/server/0422-Villager-Restocks-API.patch b/patches/server/0423-Villager-Restocks-API.patch similarity index 100% rename from patches/server/0422-Villager-Restocks-API.patch rename to patches/server/0423-Villager-Restocks-API.patch diff --git a/patches/server/0423-Validate-PickItem-Packet-and-kick-for-invalid.patch b/patches/server/0424-Validate-PickItem-Packet-and-kick-for-invalid.patch similarity index 100% rename from patches/server/0423-Validate-PickItem-Packet-and-kick-for-invalid.patch rename to patches/server/0424-Validate-PickItem-Packet-and-kick-for-invalid.patch diff --git a/patches/server/0424-Expose-game-version.patch b/patches/server/0425-Expose-game-version.patch similarity index 89% rename from patches/server/0424-Expose-game-version.patch rename to patches/server/0425-Expose-game-version.patch index 9c79c20af1..3fc2583240 100644 --- a/patches/server/0424-Expose-game-version.patch +++ b/patches/server/0425-Expose-game-version.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Expose game version diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 4c0b94a56fab161fca92b594f55e1c846524d5e8..479b4eb8efeeca432bcb21925db18d5c0750f001 100644 +index e31a05dfe7e934692ac89c7cedcab736bcd9ca4f..130ab05393a7136020e06ec199256a031ba66091 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -517,6 +517,13 @@ public final class CraftServer implements Server { diff --git a/patches/server/0425-Optimize-Voxel-Shape-Merging.patch b/patches/server/0426-Optimize-Voxel-Shape-Merging.patch similarity index 100% rename from patches/server/0425-Optimize-Voxel-Shape-Merging.patch rename to patches/server/0426-Optimize-Voxel-Shape-Merging.patch diff --git a/patches/server/0426-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/patches/server/0427-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch similarity index 100% rename from patches/server/0426-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch rename to patches/server/0427-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch diff --git a/patches/server/0427-Implement-Mob-Goal-API.patch b/patches/server/0428-Implement-Mob-Goal-API.patch similarity index 100% rename from patches/server/0427-Implement-Mob-Goal-API.patch rename to patches/server/0428-Implement-Mob-Goal-API.patch diff --git a/patches/server/0428-Use-distance-map-to-optimise-entity-tracker.patch b/patches/server/0429-Use-distance-map-to-optimise-entity-tracker.patch similarity index 96% rename from patches/server/0428-Use-distance-map-to-optimise-entity-tracker.patch rename to patches/server/0429-Use-distance-map-to-optimise-entity-tracker.patch index 1fac56559b..3df5bd58bb 100644 --- a/patches/server/0428-Use-distance-map-to-optimise-entity-tracker.patch +++ b/patches/server/0429-Use-distance-map-to-optimise-entity-tracker.patch @@ -18,7 +18,7 @@ index 11fd6d24ed0612e4df1a0493907178fb9c455d1c..d7023cb0974f6c28a0fb8a0a6e5a6600 return initialDistance; } diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c..f7032e1d64afa6707756bb5a2af9d43a808c9736 100644 +index 3e45ddc39d1283661cbfc1057aa0548d940a444a..f4a31d340ea9629dea70eec4e339cfd869a73ed9 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -58,6 +58,7 @@ import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; @@ -29,7 +29,7 @@ index f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c..f7032e1d64afa6707756bb5a2af9d43a import net.minecraft.server.level.progress.ChunkProgressListener; import net.minecraft.server.network.ServerPlayerConnection; import net.minecraft.util.CsvOutput; -@@ -222,11 +223,33 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -221,11 +222,33 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap; public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap; // Paper end - no-tick view distance @@ -63,7 +63,7 @@ index f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c..f7032e1d64afa6707756bb5a2af9d43a // Paper start - no-tick view distance int effectiveTickViewDistance = this.getEffectiveViewDistance(); int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); -@@ -243,7 +266,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -242,7 +265,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } void removePlayerFromDistanceMaps(ServerPlayer player) { @@ -76,7 +76,7 @@ index f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c..f7032e1d64afa6707756bb5a2af9d43a // Paper start - no-tick view distance this.playerViewDistanceBroadcastMap.remove(player); this.playerViewDistanceTickMap.remove(player); -@@ -255,6 +282,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -254,6 +281,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider int chunkX = MCUtil.getChunkCoordinate(player.getX()); int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); // Note: players need to be explicitly added to distance maps before they can be updated @@ -91,7 +91,7 @@ index f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c..f7032e1d64afa6707756bb5a2af9d43a // Paper start - no-tick view distance int effectiveTickViewDistance = this.getEffectiveViewDistance(); int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); -@@ -306,6 +341,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -305,6 +340,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world); this.setViewDistance(viewDistance); this.playerMobDistanceMap = this.level.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper @@ -137,7 +137,7 @@ index f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c..f7032e1d64afa6707756bb5a2af9d43a // Paper start - no-tick view distance this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -@@ -1424,17 +1498,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1423,17 +1497,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } public void move(ServerPlayer player) { @@ -156,7 +156,7 @@ index f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c..f7032e1d64afa6707756bb5a2af9d43a int i = SectionPos.blockToSectionCoord(player.getBlockX()); int j = SectionPos.blockToSectionCoord(player.getBlockZ()); -@@ -1589,7 +1653,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1588,7 +1652,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); @@ -165,7 +165,7 @@ index f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c..f7032e1d64afa6707756bb5a2af9d43a if (entity instanceof ServerPlayer) { ServerPlayer entityplayer = (ServerPlayer) entity; -@@ -1633,7 +1697,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1632,7 +1696,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider entity.tracker = null; // Paper - We're no longer tracked } @@ -203,7 +203,7 @@ index f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c..f7032e1d64afa6707756bb5a2af9d43a List list = Lists.newArrayList(); List list1 = this.level.players(); -@@ -1742,23 +1836,31 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially +@@ -1741,23 +1835,31 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos()); List list = Lists.newArrayList(); List list1 = Lists.newArrayList(); @@ -247,7 +247,7 @@ index f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c..f7032e1d64afa6707756bb5a2af9d43a Iterator iterator; Entity entity1; -@@ -1837,6 +1939,42 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially +@@ -1836,6 +1938,42 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially this.lastSectionPos = SectionPos.of(entity); } @@ -290,7 +290,7 @@ index f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c..f7032e1d64afa6707756bb5a2af9d43a public boolean equals(Object object) { return object instanceof ChunkMap.TrackedEntity ? ((ChunkMap.TrackedEntity) object).entity.getId() == this.entity.getId() : false; } -@@ -1922,7 +2060,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially +@@ -1921,7 +2059,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially int j = entity.getType().clientTrackingRange() * 16; j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper diff --git a/patches/server/0429-Optimize-isOutsideRange-to-use-distance-maps.patch b/patches/server/0430-Optimize-isOutsideRange-to-use-distance-maps.patch similarity index 97% rename from patches/server/0429-Optimize-isOutsideRange-to-use-distance-maps.patch rename to patches/server/0430-Optimize-isOutsideRange-to-use-distance-maps.patch index 3db66834ee..71825c2d60 100644 --- a/patches/server/0429-Optimize-isOutsideRange-to-use-distance-maps.patch +++ b/patches/server/0430-Optimize-isOutsideRange-to-use-distance-maps.patch @@ -37,10 +37,10 @@ index 58369d70bcd8b2c25609b6f101d9cbe2031df352..969b0c9cf6d7eb2055d3b804f25a3cbc // CraftBukkit start diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index f7032e1d64afa6707756bb5a2af9d43a808c9736..18335e2c5c9e50a8ed31a3d2b585835bcc28bbe6 100644 +index f4a31d340ea9629dea70eec4e339cfd869a73ed9..450ab55859304ecda6f752b0e4a04279f4104af1 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -237,6 +237,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -236,6 +236,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); } // Paper end - use distance map to optimise tracker @@ -58,7 +58,7 @@ index f7032e1d64afa6707756bb5a2af9d43a808c9736..18335e2c5c9e50a8ed31a3d2b585835b void addPlayerToDistanceMaps(ServerPlayer player) { int chunkX = MCUtil.getChunkCoordinate(player.getX()); -@@ -250,6 +261,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -249,6 +260,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); } // Paper end - use distance map to optimise entity tracker @@ -71,7 +71,7 @@ index f7032e1d64afa6707756bb5a2af9d43a808c9736..18335e2c5c9e50a8ed31a3d2b585835b // Paper start - no-tick view distance int effectiveTickViewDistance = this.getEffectiveViewDistance(); int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); -@@ -271,6 +288,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -270,6 +287,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.playerEntityTrackerTrackMaps[i].remove(player); } // Paper end - use distance map to optimise tracker @@ -82,7 +82,7 @@ index f7032e1d64afa6707756bb5a2af9d43a808c9736..18335e2c5c9e50a8ed31a3d2b585835b // Paper start - no-tick view distance this.playerViewDistanceBroadcastMap.remove(player); this.playerViewDistanceTickMap.remove(player); -@@ -290,6 +311,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -289,6 +310,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); } // Paper end - use distance map to optimise entity tracker @@ -92,7 +92,7 @@ index f7032e1d64afa6707756bb5a2af9d43a808c9736..18335e2c5c9e50a8ed31a3d2b585835b // Paper start - no-tick view distance int effectiveTickViewDistance = this.getEffectiveViewDistance(); int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); -@@ -336,7 +360,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -335,7 +359,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); this.mailboxLight = this.queueSorter.getProcessor(lightthreaded, false);// Paper this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); @@ -101,7 +101,7 @@ index f7032e1d64afa6707756bb5a2af9d43a808c9736..18335e2c5c9e50a8ed31a3d2b585835b this.overworldDataStorage = persistentStateManagerFactory; this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world); this.setViewDistance(viewDistance); -@@ -380,6 +404,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -379,6 +403,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); } // Paper end - use distance map to optimise entity tracker @@ -140,7 +140,7 @@ index f7032e1d64afa6707756bb5a2af9d43a808c9736..18335e2c5c9e50a8ed31a3d2b585835b // Paper start - no-tick view distance this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -@@ -649,6 +705,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -648,6 +704,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } else { if (holder != null) { holder.setTicketLevel(level); @@ -148,7 +148,7 @@ index f7032e1d64afa6707756bb5a2af9d43a808c9736..18335e2c5c9e50a8ed31a3d2b585835b } if (holder != null) { -@@ -1434,29 +1491,50 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1433,29 +1490,50 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return this.isOutsideOfRange(chunkPos, false); } diff --git a/patches/server/0430-Add-villager-reputation-API.patch b/patches/server/0431-Add-villager-reputation-API.patch similarity index 100% rename from patches/server/0430-Add-villager-reputation-API.patch rename to patches/server/0431-Add-villager-reputation-API.patch diff --git a/patches/server/0431-Option-for-maximum-exp-value-when-merging-orbs.patch b/patches/server/0432-Option-for-maximum-exp-value-when-merging-orbs.patch similarity index 95% rename from patches/server/0431-Option-for-maximum-exp-value-when-merging-orbs.patch rename to patches/server/0432-Option-for-maximum-exp-value-when-merging-orbs.patch index c08ccc6865..6b5ce39eda 100644 --- a/patches/server/0431-Option-for-maximum-exp-value-when-merging-orbs.patch +++ b/patches/server/0432-Option-for-maximum-exp-value-when-merging-orbs.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Option for maximum exp value when merging orbs diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 16cf7d116e3ffd44ffc4f060b4014b52389cff77..3bc6329d3ea48966cb99e792f9b35e2d2d71a34b 100644 +index 98416de3dfc9d16d17124902e19cbd9b916077d2..b10de4e99913030bae7451b3242067312e94df7e 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -359,6 +359,12 @@ public class PaperWorldConfig { +@@ -356,6 +356,12 @@ public class PaperWorldConfig { log("Creeper lingering effect: " + disableCreeperLingeringEffect); } diff --git a/patches/server/0432-ExperienceOrbMergeEvent.patch b/patches/server/0433-ExperienceOrbMergeEvent.patch similarity index 100% rename from patches/server/0432-ExperienceOrbMergeEvent.patch rename to patches/server/0433-ExperienceOrbMergeEvent.patch diff --git a/patches/server/0433-Fix-PotionEffect-ignores-icon-flag.patch b/patches/server/0434-Fix-PotionEffect-ignores-icon-flag.patch similarity index 100% rename from patches/server/0433-Fix-PotionEffect-ignores-icon-flag.patch rename to patches/server/0434-Fix-PotionEffect-ignores-icon-flag.patch diff --git a/patches/server/0434-Optimize-brigadier-child-sorting-performance.patch b/patches/server/0435-Optimize-brigadier-child-sorting-performance.patch similarity index 100% rename from patches/server/0434-Optimize-brigadier-child-sorting-performance.patch rename to patches/server/0435-Optimize-brigadier-child-sorting-performance.patch diff --git a/patches/server/0435-Potential-bed-API.patch b/patches/server/0436-Potential-bed-API.patch similarity index 100% rename from patches/server/0435-Potential-bed-API.patch rename to patches/server/0436-Potential-bed-API.patch diff --git a/patches/server/0436-Wait-for-Async-Tasks-during-shutdown.patch b/patches/server/0437-Wait-for-Async-Tasks-during-shutdown.patch similarity index 100% rename from patches/server/0436-Wait-for-Async-Tasks-during-shutdown.patch rename to patches/server/0437-Wait-for-Async-Tasks-during-shutdown.patch diff --git a/patches/server/0437-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/patches/server/0438-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch similarity index 100% rename from patches/server/0437-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch rename to patches/server/0438-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch diff --git a/patches/server/0438-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server/0439-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch similarity index 98% rename from patches/server/0438-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch rename to patches/server/0439-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch index 6fa1cd4c6d..18f52c03fd 100644 --- a/patches/server/0438-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch +++ b/patches/server/0439-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch @@ -56,10 +56,10 @@ index cdf214fca3b0055efa56702470d9d2f890a8aead..a12af10e28f2d023ba6f916b5e7a5353 this.level.getProfiler().push("explosion_blocks"); diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 06f2f76636804cd5f997bbe1558a104bc24aa84a..b92d930448757968cd6a178f4bcafae72c93044c 100644 +index 54fcdcef2a6b68e4b4f4c6a090e84919fe76b073..f004f5012ce157f9b0fb9c5890b5f3de957418f8 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -420,6 +420,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -424,6 +424,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { // CraftBukkit start - tree generation if (this.captureTreeGeneration) { diff --git a/patches/server/0439-Reduce-MutableInt-allocations-from-light-engine.patch b/patches/server/0440-Reduce-MutableInt-allocations-from-light-engine.patch similarity index 100% rename from patches/server/0439-Reduce-MutableInt-allocations-from-light-engine.patch rename to patches/server/0440-Reduce-MutableInt-allocations-from-light-engine.patch diff --git a/patches/server/0440-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/patches/server/0441-Reduce-allocation-of-Vec3D-by-entity-tracker.patch similarity index 96% rename from patches/server/0440-Reduce-allocation-of-Vec3D-by-entity-tracker.patch rename to patches/server/0441-Reduce-allocation-of-Vec3D-by-entity-tracker.patch index b91add5e6e..b595c247f0 100644 --- a/patches/server/0440-Reduce-allocation-of-Vec3D-by-entity-tracker.patch +++ b/patches/server/0441-Reduce-allocation-of-Vec3D-by-entity-tracker.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Reduce allocation of Vec3D by entity tracker diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 18335e2c5c9e50a8ed31a3d2b585835bcc28bbe6..d8f99f7f5ca0e1dbbb9b760af3a4b4f9c52ef6c7 100644 +index 450ab55859304ecda6f752b0e4a04279f4104af1..f722d9e77fa074847a2bdc6a117816d176eb6dca 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -2102,9 +2102,14 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially +@@ -2101,9 +2101,14 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially public void updatePlayer(ServerPlayer player) { org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot if (player != this.entity) { diff --git a/patches/server/0441-Ensure-safe-gateway-teleport.patch b/patches/server/0442-Ensure-safe-gateway-teleport.patch similarity index 100% rename from patches/server/0441-Ensure-safe-gateway-teleport.patch rename to patches/server/0442-Ensure-safe-gateway-teleport.patch diff --git a/patches/server/0442-Add-option-for-console-having-all-permissions.patch b/patches/server/0443-Add-option-for-console-having-all-permissions.patch similarity index 100% rename from patches/server/0442-Add-option-for-console-having-all-permissions.patch rename to patches/server/0443-Add-option-for-console-having-all-permissions.patch diff --git a/patches/server/0443-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/patches/server/0444-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch similarity index 98% rename from patches/server/0443-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch rename to patches/server/0444-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch index 9a51437a68..7b2d1c7f8f 100644 --- a/patches/server/0443-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch +++ b/patches/server/0444-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch @@ -16,7 +16,7 @@ We further improve it by making a copy of the nbt tag with only the memory it needs, so that we dont have to hold a copy to the entire compound. diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 7c04aef3eac54981ca1e34cb87d97104c3c9685b..b4246524dd11ad1e1dc94c56eee966c5a54d9ecc 100644 +index 097d38f12ef324dbb529a833383e2da949377f9c..1f95ac18990822a64f0bb2af947693c4b88cdf73 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java @@ -27,6 +27,7 @@ import net.minecraft.nbt.CompoundTag; diff --git a/patches/server/0444-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/patches/server/0445-Optimize-sending-packets-to-nearby-locations-sounds-.patch similarity index 100% rename from patches/server/0444-Optimize-sending-packets-to-nearby-locations-sounds-.patch rename to patches/server/0445-Optimize-sending-packets-to-nearby-locations-sounds-.patch diff --git a/patches/server/0445-Fix-villager-trading-demand-MC-163962.patch b/patches/server/0446-Fix-villager-trading-demand-MC-163962.patch similarity index 100% rename from patches/server/0445-Fix-villager-trading-demand-MC-163962.patch rename to patches/server/0446-Fix-villager-trading-demand-MC-163962.patch diff --git a/patches/server/0446-Maps-shouldn-t-load-chunks.patch b/patches/server/0447-Maps-shouldn-t-load-chunks.patch similarity index 100% rename from patches/server/0446-Maps-shouldn-t-load-chunks.patch rename to patches/server/0447-Maps-shouldn-t-load-chunks.patch diff --git a/patches/server/0447-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/patches/server/0448-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch similarity index 100% rename from patches/server/0447-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch rename to patches/server/0448-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch diff --git a/patches/server/0448-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/patches/server/0449-Delay-Chunk-Unloads-based-on-Player-Movement.patch similarity index 96% rename from patches/server/0448-Delay-Chunk-Unloads-based-on-Player-Movement.patch rename to patches/server/0449-Delay-Chunk-Unloads-based-on-Player-Movement.patch index a7a809be4c..38b1b71ec6 100644 --- a/patches/server/0448-Delay-Chunk-Unloads-based-on-Player-Movement.patch +++ b/patches/server/0449-Delay-Chunk-Unloads-based-on-Player-Movement.patch @@ -17,10 +17,10 @@ This allows servers with smaller worlds who do less long distance exploring to s wasting cpu cycles on saving/unloading/reloading chunks repeatedly. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3bc6329d3ea48966cb99e792f9b35e2d2d71a34b..1f4d0d3493e748f52eb3b679c0a8a1306c0cc8b4 100644 +index b10de4e99913030bae7451b3242067312e94df7e..d2b1ef727004906d184995a840657e22ea127f71 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -495,6 +495,15 @@ public class PaperWorldConfig { +@@ -492,6 +492,15 @@ public class PaperWorldConfig { this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); } @@ -34,7 +34,7 @@ index 3bc6329d3ea48966cb99e792f9b35e2d2d71a34b..1f4d0d3493e748f52eb3b679c0a8a130 + } + public boolean altItemDespawnRateEnabled; - public Map altItemDespawnRateMap; + public java.util.Map altItemDespawnRateMap; private void altItemDespawnRate() { diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java index 577b391dcba1db712c1e2c83296e1c87b3e34ab2..d94241bcca4f2fd5e464a860bd356af504dc68b7 100644 diff --git a/patches/server/0449-Optimize-Bit-Operations-by-inlining.patch b/patches/server/0450-Optimize-Bit-Operations-by-inlining.patch similarity index 100% rename from patches/server/0449-Optimize-Bit-Operations-by-inlining.patch rename to patches/server/0450-Optimize-Bit-Operations-by-inlining.patch diff --git a/patches/server/0450-incremental-chunk-saving.patch b/patches/server/0451-incremental-chunk-saving.patch similarity index 94% rename from patches/server/0450-incremental-chunk-saving.patch rename to patches/server/0451-incremental-chunk-saving.patch index ece4224cd0..ad4e15eae2 100644 --- a/patches/server/0450-incremental-chunk-saving.patch +++ b/patches/server/0451-incremental-chunk-saving.patch @@ -5,10 +5,10 @@ Subject: [PATCH] incremental chunk saving diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1f4d0d3493e748f52eb3b679c0a8a1306c0cc8b4..91917b11163c0740d5e5effc5e93d494e2b2d73e 100644 +index d2b1ef727004906d184995a840657e22ea127f71..040956f5d714ac014f9a153981d444db299fd826 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -47,6 +47,21 @@ public class PaperWorldConfig { +@@ -44,6 +44,21 @@ public class PaperWorldConfig { log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); } @@ -139,10 +139,10 @@ index 969b0c9cf6d7eb2055d3b804f25a3cbc161ceaea..1f67c9c5f7161ea687983e7ae0ec7d25 for (int i = 0; i < this.futures.length(); ++i) { CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index d8f99f7f5ca0e1dbbb9b760af3a4b4f9c52ef6c7..5a5e9188f55405c8a2646891c348d544d33eb940 100644 +index f722d9e77fa074847a2bdc6a117816d176eb6dca..8982823efd8fd21d403c6c6fb158d57a9da67707 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -93,6 +93,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana +@@ -92,6 +92,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana import net.minecraft.world.level.storage.DimensionDataStorage; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.phys.Vec3; @@ -150,7 +150,7 @@ index d8f99f7f5ca0e1dbbb9b760af3a4b4f9c52ef6c7..5a5e9188f55405c8a2646891c348d544 import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -@@ -744,6 +745,64 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -743,6 +744,64 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } @@ -215,7 +215,7 @@ index d8f99f7f5ca0e1dbbb9b760af3a4b4f9c52ef6c7..5a5e9188f55405c8a2646891c348d544 protected void saveAllChunks(boolean flush) { Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) if (flush) { -@@ -883,6 +942,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -882,6 +941,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider asyncSaveData, chunk); chunk.setUnsaved(false); @@ -223,7 +223,7 @@ index d8f99f7f5ca0e1dbbb9b760af3a4b4f9c52ef6c7..5a5e9188f55405c8a2646891c348d544 } // Paper end -@@ -905,6 +965,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -904,6 +964,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.level.unload(chunk); } @@ -231,7 +231,7 @@ index d8f99f7f5ca0e1dbbb9b760af3a4b4f9c52ef6c7..5a5e9188f55405c8a2646891c348d544 // Paper start - async chunk saving try { -@@ -1231,6 +1292,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1230,6 +1291,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (!chunk.isUnsaved()) { return false; } else { @@ -260,7 +260,7 @@ index 3faa808f41f057a9956c697ec1323330f5920b86..7ab28e9bd3f785838b7fa4ac5811c0e7 public void close() throws IOException { // CraftBukkit start diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index f10fad84e4f36f9158383b327170593f273cecd9..bdabcdb60dbfb803ead13c42c8dd5e100b37dc00 100644 +index 70106dda486d685dffafc0d4b3ae95b4861c6342..74753639ed095eab305c2facd0f00264a6253cef 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1017,6 +1017,38 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl @@ -303,7 +303,7 @@ index f10fad84e4f36f9158383b327170593f273cecd9..bdabcdb60dbfb803ead13c42c8dd5e10 ServerChunkCache chunkproviderserver = this.getChunkSource(); diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -index c0075d226331f32e470dae5bf1ce8d79e8b263dc..8ba782511b0a6c7859cbcf910ad742cbb9f599e5 100644 +index 91f5106cfe7914389b52a1ed001117b13e4f9768..31ea618547e0e452f9a495796a4197e718abbfa6 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java @@ -29,6 +29,7 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { @@ -315,7 +315,7 @@ index c0075d226331f32e470dae5bf1ce8d79e8b263dc..8ba782511b0a6c7859cbcf910ad742cb default boolean generateFlatBedrock() { if (this instanceof ProtoChunk) { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index a63dc77db41dab79f03ef7384da55c1cdeca5d98..efb9c6fef915b43c9dd4468ead52aa36ea9e7ef3 100644 +index bde00ca058f32eb55e940614f0fbc361fe3a501d..fe46fdb828d630f9dc9b212128608203f6c6f4bb 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -108,6 +108,13 @@ public class LevelChunk implements ChunkAccess { diff --git a/patches/server/0451-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/patches/server/0452-Add-Plugin-Tickets-to-API-Chunk-Methods.patch similarity index 98% rename from patches/server/0451-Add-Plugin-Tickets-to-API-Chunk-Methods.patch rename to patches/server/0452-Add-Plugin-Tickets-to-API-Chunk-Methods.patch index ab4ec662b0..10203095da 100644 --- a/patches/server/0451-Add-Plugin-Tickets-to-API-Chunk-Methods.patch +++ b/patches/server/0452-Add-Plugin-Tickets-to-API-Chunk-Methods.patch @@ -22,7 +22,7 @@ wants it to collect even faster, they can restore that setting back to 1 instead Not adding it to .getType() though to keep behavior consistent with vanilla for performance reasons. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 94670ec4de01341822f6affe0fa1c9774dd6131b..6bc5ba51c90723c7138b1b5d2381cb215f1e5271 100644 +index e3338717bffe5f5e4a00fe1ebe3ba7cf74555b36..f7d542b828904fb51a30dfb7a50e01e4e2df0f3e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -346,7 +346,7 @@ public final class CraftServer implements Server { diff --git a/patches/server/0452-Fix-missing-chunks-due-to-integer-overflow.patch b/patches/server/0453-Fix-missing-chunks-due-to-integer-overflow.patch similarity index 100% rename from patches/server/0452-Fix-missing-chunks-due-to-integer-overflow.patch rename to patches/server/0453-Fix-missing-chunks-due-to-integer-overflow.patch diff --git a/patches/server/0453-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/patches/server/0454-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch similarity index 100% rename from patches/server/0453-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch rename to patches/server/0454-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch diff --git a/patches/server/0454-Fix-piston-physics-inconsistency-MC-188840.patch b/patches/server/0455-Fix-piston-physics-inconsistency-MC-188840.patch similarity index 100% rename from patches/server/0454-Fix-piston-physics-inconsistency-MC-188840.patch rename to patches/server/0455-Fix-piston-physics-inconsistency-MC-188840.patch diff --git a/patches/server/0455-Fix-sand-duping.patch b/patches/server/0456-Fix-sand-duping.patch similarity index 100% rename from patches/server/0455-Fix-sand-duping.patch rename to patches/server/0456-Fix-sand-duping.patch diff --git a/patches/server/0456-Prevent-position-desync-in-playerconnection-causing-.patch b/patches/server/0457-Prevent-position-desync-in-playerconnection-causing-.patch similarity index 100% rename from patches/server/0456-Prevent-position-desync-in-playerconnection-causing-.patch rename to patches/server/0457-Prevent-position-desync-in-playerconnection-causing-.patch diff --git a/patches/server/0457-Inventory-getHolder-method-without-block-snapshot.patch b/patches/server/0458-Inventory-getHolder-method-without-block-snapshot.patch similarity index 100% rename from patches/server/0457-Inventory-getHolder-method-without-block-snapshot.patch rename to patches/server/0458-Inventory-getHolder-method-without-block-snapshot.patch diff --git a/patches/server/0458-Expose-Arrow-getItemStack.patch b/patches/server/0459-Expose-Arrow-getItemStack.patch similarity index 100% rename from patches/server/0458-Expose-Arrow-getItemStack.patch rename to patches/server/0459-Expose-Arrow-getItemStack.patch diff --git a/patches/server/0459-Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/server/0460-Add-and-implement-PlayerRecipeBookClickEvent.patch similarity index 100% rename from patches/server/0459-Add-and-implement-PlayerRecipeBookClickEvent.patch rename to patches/server/0460-Add-and-implement-PlayerRecipeBookClickEvent.patch diff --git a/patches/server/0460-Hide-sync-chunk-writes-behind-flag.patch b/patches/server/0461-Hide-sync-chunk-writes-behind-flag.patch similarity index 100% rename from patches/server/0460-Hide-sync-chunk-writes-behind-flag.patch rename to patches/server/0461-Hide-sync-chunk-writes-behind-flag.patch diff --git a/patches/server/0461-Add-permission-for-command-blocks.patch b/patches/server/0462-Add-permission-for-command-blocks.patch similarity index 97% rename from patches/server/0461-Add-permission-for-command-blocks.patch rename to patches/server/0462-Add-permission-for-command-blocks.patch index da4472b2e1..e1dcbcf07f 100644 --- a/patches/server/0461-Add-permission-for-command-blocks.patch +++ b/patches/server/0462-Add-permission-for-command-blocks.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add permission for command blocks diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index f4a056185990181e486f452960159a5287947382..6c55bd8b876d1d694e05ad6de6a9fd29a4d4d053 100644 +index a695e5a0c2e8846333ccb9aea499b5656af35163..c21c5134308a2a83fb50bfe37f05d19c8e96ca7c 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -389,7 +389,7 @@ public class ServerPlayerGameMode { +@@ -391,7 +391,7 @@ public class ServerPlayerGameMode { BlockEntity tileentity = this.level.getBlockEntity(pos); Block block = iblockdata.getBlock(); diff --git a/patches/server/0462-Ensure-Entity-AABB-s-are-never-invalid.patch b/patches/server/0463-Ensure-Entity-AABB-s-are-never-invalid.patch similarity index 100% rename from patches/server/0462-Ensure-Entity-AABB-s-are-never-invalid.patch rename to patches/server/0463-Ensure-Entity-AABB-s-are-never-invalid.patch diff --git a/patches/server/0463-Optimize-WorldBorder-collision-checks-and-air.patch b/patches/server/0464-Optimize-WorldBorder-collision-checks-and-air.patch similarity index 100% rename from patches/server/0463-Optimize-WorldBorder-collision-checks-and-air.patch rename to patches/server/0464-Optimize-WorldBorder-collision-checks-and-air.patch diff --git a/patches/server/0464-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/patches/server/0465-Fix-Per-World-Difficulty-Remembering-Difficulty.patch similarity index 100% rename from patches/server/0464-Fix-Per-World-Difficulty-Remembering-Difficulty.patch rename to patches/server/0465-Fix-Per-World-Difficulty-Remembering-Difficulty.patch diff --git a/patches/server/0465-Paper-dumpitem-command.patch b/patches/server/0466-Paper-dumpitem-command.patch similarity index 100% rename from patches/server/0465-Paper-dumpitem-command.patch rename to patches/server/0466-Paper-dumpitem-command.patch diff --git a/patches/server/0466-Don-t-allow-null-UUID-s-for-chat.patch b/patches/server/0467-Don-t-allow-null-UUID-s-for-chat.patch similarity index 100% rename from patches/server/0466-Don-t-allow-null-UUID-s-for-chat.patch rename to patches/server/0467-Don-t-allow-null-UUID-s-for-chat.patch diff --git a/patches/server/0467-Improve-Legacy-Component-serialization-size.patch b/patches/server/0468-Improve-Legacy-Component-serialization-size.patch similarity index 100% rename from patches/server/0467-Improve-Legacy-Component-serialization-size.patch rename to patches/server/0468-Improve-Legacy-Component-serialization-size.patch diff --git a/patches/server/0468-Support-old-UUID-format-for-NBT.patch b/patches/server/0469-Support-old-UUID-format-for-NBT.patch similarity index 100% rename from patches/server/0468-Support-old-UUID-format-for-NBT.patch rename to patches/server/0469-Support-old-UUID-format-for-NBT.patch diff --git a/patches/server/0469-Clean-up-duplicated-GameProfile-Properties.patch b/patches/server/0470-Clean-up-duplicated-GameProfile-Properties.patch similarity index 100% rename from patches/server/0469-Clean-up-duplicated-GameProfile-Properties.patch rename to patches/server/0470-Clean-up-duplicated-GameProfile-Properties.patch diff --git a/patches/server/0470-Convert-legacy-attributes-in-Item-Meta.patch b/patches/server/0471-Convert-legacy-attributes-in-Item-Meta.patch similarity index 100% rename from patches/server/0470-Convert-legacy-attributes-in-Item-Meta.patch rename to patches/server/0471-Convert-legacy-attributes-in-Item-Meta.patch diff --git a/patches/server/0471-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server/0472-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch similarity index 98% rename from patches/server/0471-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch rename to patches/server/0472-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch index ed51f630f3..f96921a0f0 100644 --- a/patches/server/0471-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch +++ b/patches/server/0472-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch @@ -327,10 +327,10 @@ index 1f67c9c5f7161ea687983e7ae0ec7d259da9acd3..6a1c000d693031f0c537112963cfa52e } diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 5a5e9188f55405c8a2646891c348d544d33eb940..b86ff17cdfa613a03bd75eeaab194de03a597b29 100644 +index 8982823efd8fd21d403c6c6fb158d57a9da67707..943c187efab8fdbcc38c313a498f876983a98412 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -145,6 +145,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -144,6 +144,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public final ServerLevel level; private final ThreadedLevelLightEngine lightEngine; private final BlockableEventLoop mainThreadExecutor; @@ -338,7 +338,7 @@ index 5a5e9188f55405c8a2646891c348d544d33eb940..b86ff17cdfa613a03bd75eeaab194de0 public final ChunkGenerator generator; private final Supplier overworldDataStorage; public final Supplier getWorldPersistentDataSupplier() { return this.overworldDataStorage; } // Paper - OBFHELPER private final PoiManager poiManager; -@@ -183,6 +184,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -182,6 +183,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @Override public void execute(Runnable runnable) { @@ -346,7 +346,7 @@ index 5a5e9188f55405c8a2646891c348d544d33eb940..b86ff17cdfa613a03bd75eeaab194de0 if (this.queue == null) { this.queue = new java.util.ArrayDeque<>(); } -@@ -191,6 +193,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -190,6 +192,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @Override public void run() { @@ -354,7 +354,7 @@ index 5a5e9188f55405c8a2646891c348d544d33eb940..b86ff17cdfa613a03bd75eeaab194de0 if (this.queue == null) { return; } -@@ -347,6 +350,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -346,6 +349,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.level = world; this.generator = chunkGenerator; this.mainThreadExecutor = mainThreadExecutor; @@ -370,7 +370,7 @@ index 5a5e9188f55405c8a2646891c348d544d33eb940..b86ff17cdfa613a03bd75eeaab194de0 ProcessorMailbox threadedmailbox = ProcessorMailbox.create(executor, "worldgen"); Objects.requireNonNull(mainThreadExecutor); -@@ -442,6 +454,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -441,6 +453,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { @@ -378,7 +378,7 @@ index 5a5e9188f55405c8a2646891c348d544d33eb940..b86ff17cdfa613a03bd75eeaab194de0 if (newState.size() != 1) { return; } -@@ -460,7 +473,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -459,7 +472,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); ChunkMap.this.level.getChunkSource().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update @@ -391,7 +391,7 @@ index 5a5e9188f55405c8a2646891c348d544d33eb940..b86ff17cdfa613a03bd75eeaab194de0 this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -@@ -477,8 +494,116 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -476,8 +493,116 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider }); // Paper end - no-tick view distance } @@ -508,7 +508,7 @@ index 5a5e9188f55405c8a2646891c348d544d33eb940..b86ff17cdfa613a03bd75eeaab194de0 public void updatePlayerMobTypeMap(Entity entity) { if (!this.level.paperConfig.perPlayerMobSpawns) { return; -@@ -636,6 +761,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -635,6 +760,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider List>> list = Lists.newArrayList(); int j = centerChunk.x; int k = centerChunk.z; @@ -516,7 +516,7 @@ index 5a5e9188f55405c8a2646891c348d544d33eb940..b86ff17cdfa613a03bd75eeaab194de0 for (int l = -margin; l <= margin; ++l) { for (int i1 = -margin; i1 <= margin; ++i1) { -@@ -654,6 +780,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -653,6 +779,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider ChunkStatus chunkstatus = (ChunkStatus) distanceToStatus.apply(j1); CompletableFuture> completablefuture = playerchunk.getOrScheduleFuture(chunkstatus, this); @@ -531,7 +531,7 @@ index 5a5e9188f55405c8a2646891c348d544d33eb940..b86ff17cdfa613a03bd75eeaab194de0 list.add(completablefuture); } -@@ -1100,14 +1234,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1099,14 +1233,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider }; CompletableFuture chunkSaveFuture = this.level.asyncChunkTaskManager.getChunkSaveFuture(pos.x, pos.z); @@ -559,7 +559,7 @@ index 5a5e9188f55405c8a2646891c348d544d33eb940..b86ff17cdfa613a03bd75eeaab194de0 return ret; // Paper end } -@@ -1238,7 +1380,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1237,7 +1379,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider long i = playerchunk.getPos().toLong(); Objects.requireNonNull(playerchunk); diff --git a/patches/server/0472-Remove-some-streams-from-structures.patch b/patches/server/0473-Remove-some-streams-from-structures.patch similarity index 100% rename from patches/server/0472-Remove-some-streams-from-structures.patch rename to patches/server/0473-Remove-some-streams-from-structures.patch diff --git a/patches/server/0473-Remove-streams-from-classes-related-villager-gossip.patch b/patches/server/0474-Remove-streams-from-classes-related-villager-gossip.patch similarity index 100% rename from patches/server/0473-Remove-streams-from-classes-related-villager-gossip.patch rename to patches/server/0474-Remove-streams-from-classes-related-villager-gossip.patch diff --git a/patches/server/0474-Support-components-in-ItemMeta.patch b/patches/server/0475-Support-components-in-ItemMeta.patch similarity index 100% rename from patches/server/0474-Support-components-in-ItemMeta.patch rename to patches/server/0475-Support-components-in-ItemMeta.patch diff --git a/patches/server/0475-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/patches/server/0476-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch similarity index 100% rename from patches/server/0475-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch rename to patches/server/0476-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch diff --git a/patches/server/0476-Add-entity-liquid-API.patch b/patches/server/0477-Add-entity-liquid-API.patch similarity index 100% rename from patches/server/0476-Add-entity-liquid-API.patch rename to patches/server/0477-Add-entity-liquid-API.patch diff --git a/patches/server/0477-Update-itemstack-legacy-name-and-lore.patch b/patches/server/0478-Update-itemstack-legacy-name-and-lore.patch similarity index 100% rename from patches/server/0477-Update-itemstack-legacy-name-and-lore.patch rename to patches/server/0478-Update-itemstack-legacy-name-and-lore.patch diff --git a/patches/server/0478-Spawn-player-in-correct-world-on-login.patch b/patches/server/0479-Spawn-player-in-correct-world-on-login.patch similarity index 100% rename from patches/server/0478-Spawn-player-in-correct-world-on-login.patch rename to patches/server/0479-Spawn-player-in-correct-world-on-login.patch diff --git a/patches/server/0479-Add-PrepareResultEvent.patch b/patches/server/0480-Add-PrepareResultEvent.patch similarity index 100% rename from patches/server/0479-Add-PrepareResultEvent.patch rename to patches/server/0480-Add-PrepareResultEvent.patch diff --git a/patches/server/0480-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/0481-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 95% rename from patches/server/0480-Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/server/0481-Allow-delegation-to-vanilla-chunk-gen.patch index ef0cf459b5..eb2bc9a627 100644 --- a/patches/server/0480-Allow-delegation-to-vanilla-chunk-gen.patch +++ b/patches/server/0481-Allow-delegation-to-vanilla-chunk-gen.patch @@ -42,7 +42,7 @@ index f7d542b828904fb51a30dfb7a50e01e4e2df0f3e..407a91f64e040745dea17544d6b7c6d1 public BossBar createBossBar(String title, BarColor color, BarStyle style, BarFlag... flags) { return new CraftBossBar(title, color, style, flags); diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index 3d905c98704da64cefd009b2c796b24e729396a5..6e8018241664d2cc2a6a8d52d87946740ac8bb97 100644 +index fe7851476636dfed02339d4d9f93824b96086769..24a2e88d083f90375c46cf948c7c89dccc6e4aa0 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java @@ -20,7 +20,7 @@ import org.bukkit.material.MaterialData; @@ -52,9 +52,9 @@ index 3d905c98704da64cefd009b2c796b24e729396a5..6e8018241664d2cc2a6a8d52d8794674 - private final LevelChunkSection[] sections; + private LevelChunkSection[] sections; // Paper - remove final private Set tiles; + private World world; // Paper - Anti-Xray - Add world - public CraftChunkData(World world) { -@@ -171,6 +171,12 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { +@@ -173,6 +173,12 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { return this.sections; } diff --git a/patches/server/0481-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server/0482-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch similarity index 100% rename from patches/server/0481-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch rename to patches/server/0482-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch diff --git a/patches/server/0482-Optimize-NetworkManager-Exception-Handling.patch b/patches/server/0483-Optimize-NetworkManager-Exception-Handling.patch similarity index 100% rename from patches/server/0482-Optimize-NetworkManager-Exception-Handling.patch rename to patches/server/0483-Optimize-NetworkManager-Exception-Handling.patch diff --git a/patches/server/0483-Optimize-the-advancement-data-player-iteration-to-be.patch b/patches/server/0484-Optimize-the-advancement-data-player-iteration-to-be.patch similarity index 100% rename from patches/server/0483-Optimize-the-advancement-data-player-iteration-to-be.patch rename to patches/server/0484-Optimize-the-advancement-data-player-iteration-to-be.patch diff --git a/patches/server/0484-Fix-arrows-never-despawning-MC-125757.patch b/patches/server/0485-Fix-arrows-never-despawning-MC-125757.patch similarity index 100% rename from patches/server/0484-Fix-arrows-never-despawning-MC-125757.patch rename to patches/server/0485-Fix-arrows-never-despawning-MC-125757.patch diff --git a/patches/server/0485-Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server/0486-Thread-Safe-Vanilla-Command-permission-checking.patch similarity index 100% rename from patches/server/0485-Thread-Safe-Vanilla-Command-permission-checking.patch rename to patches/server/0486-Thread-Safe-Vanilla-Command-permission-checking.patch diff --git a/patches/server/0486-Move-range-check-for-block-placing-up.patch b/patches/server/0487-Move-range-check-for-block-placing-up.patch similarity index 100% rename from patches/server/0486-Move-range-check-for-block-placing-up.patch rename to patches/server/0487-Move-range-check-for-block-placing-up.patch diff --git a/patches/server/0487-Fix-SPIGOT-5989.patch b/patches/server/0488-Fix-SPIGOT-5989.patch similarity index 100% rename from patches/server/0487-Fix-SPIGOT-5989.patch rename to patches/server/0488-Fix-SPIGOT-5989.patch diff --git a/patches/server/0488-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/patches/server/0489-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch similarity index 100% rename from patches/server/0488-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch rename to patches/server/0489-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch diff --git a/patches/server/0489-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/patches/server/0490-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch similarity index 100% rename from patches/server/0489-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch rename to patches/server/0490-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch diff --git a/patches/server/0490-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/patches/server/0491-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch similarity index 100% rename from patches/server/0490-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch rename to patches/server/0491-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch diff --git a/patches/server/0491-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/patches/server/0492-Add-missing-strikeLighting-call-to-World-spigot-stri.patch similarity index 100% rename from patches/server/0491-Add-missing-strikeLighting-call-to-World-spigot-stri.patch rename to patches/server/0492-Add-missing-strikeLighting-call-to-World-spigot-stri.patch diff --git a/patches/server/0492-Fix-some-rails-connecting-improperly.patch b/patches/server/0493-Fix-some-rails-connecting-improperly.patch similarity index 100% rename from patches/server/0492-Fix-some-rails-connecting-improperly.patch rename to patches/server/0493-Fix-some-rails-connecting-improperly.patch diff --git a/patches/server/0493-Incremental-player-saving.patch b/patches/server/0494-Incremental-player-saving.patch similarity index 100% rename from patches/server/0493-Incremental-player-saving.patch rename to patches/server/0494-Incremental-player-saving.patch diff --git a/patches/server/0494-Fix-MC-187716-Use-configured-height.patch b/patches/server/0495-Fix-MC-187716-Use-configured-height.patch similarity index 100% rename from patches/server/0494-Fix-MC-187716-Use-configured-height.patch rename to patches/server/0495-Fix-MC-187716-Use-configured-height.patch diff --git a/patches/server/0495-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/patches/server/0496-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch similarity index 100% rename from patches/server/0495-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch rename to patches/server/0496-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch diff --git a/patches/server/0496-Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server/0497-Do-not-let-the-server-load-chunks-from-newer-version.patch similarity index 96% rename from patches/server/0496-Do-not-let-the-server-load-chunks-from-newer-version.patch rename to patches/server/0497-Do-not-let-the-server-load-chunks-from-newer-version.patch index f0ecafa556..5ddcf459d1 100644 --- a/patches/server/0496-Do-not-let-the-server-load-chunks-from-newer-version.patch +++ b/patches/server/0497-Do-not-let-the-server-load-chunks-from-newer-version.patch @@ -9,7 +9,7 @@ the game, immediately stop the server to prevent data corruption. You can override this functionality at your own peril. diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index b4246524dd11ad1e1dc94c56eee966c5a54d9ecc..fad795c67829f89b21d78e822c7b15f2ea560184 100644 +index 1f95ac18990822a64f0bb2af947693c4b88cdf73..6b7d3433c6e26888b3c718cfe13237342ad9b2b4 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java @@ -98,10 +98,25 @@ public class ChunkSerializer { diff --git a/patches/server/0497-Brand-support.patch b/patches/server/0498-Brand-support.patch similarity index 100% rename from patches/server/0497-Brand-support.patch rename to patches/server/0498-Brand-support.patch diff --git a/patches/server/0498-Add-setMaxPlayers-API.patch b/patches/server/0499-Add-setMaxPlayers-API.patch similarity index 94% rename from patches/server/0498-Add-setMaxPlayers-API.patch rename to patches/server/0499-Add-setMaxPlayers-API.patch index 1249b8a981..f7d28abb3b 100644 --- a/patches/server/0498-Add-setMaxPlayers-API.patch +++ b/patches/server/0499-Add-setMaxPlayers-API.patch @@ -18,7 +18,7 @@ index 554da65376a1513af64fee6a958ceaa63c88b552..c61a4e8e03996487ed3f7f39187d96a8 private boolean allowCheatsForAllPlayers; private static final boolean ALLOW_LOGOUTIVATOR = false; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index beb8b7d06ef47c80ede95c884598fedcc7126d67..7795735e5acc3b7b6b71b4e61bdc4bdcb722a7b3 100644 +index 407a91f64e040745dea17544d6b7c6d125866c62..c4d7ac8abd7d86e8a4e2d8a3340d04f8710e925c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -616,6 +616,13 @@ public final class CraftServer implements Server { diff --git a/patches/server/0499-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server/0500-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from patches/server/0499-Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/server/0500-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/patches/server/0500-Don-t-require-FACING-data.patch b/patches/server/0501-Don-t-require-FACING-data.patch similarity index 100% rename from patches/server/0500-Don-t-require-FACING-data.patch rename to patches/server/0501-Don-t-require-FACING-data.patch diff --git a/patches/server/0501-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server/0502-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch similarity index 96% rename from patches/server/0501-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch rename to patches/server/0502-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch index 69caf29aee..8750c499d9 100644 --- a/patches/server/0501-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch +++ b/patches/server/0502-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix SpawnChangeEvent not firing for all use-cases diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 23f9bb0f3202b418bf4fb59a46c624477f4dfae3..8d3d76ff942baf129f9845b945bd1537a058833a 100644 +index 74753639ed095eab305c2facd0f00264a6253cef..93d31c6f4d05625c2fab1bd7166922323dac4b47 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1675,12 +1675,14 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0502-Add-moon-phase-API.patch b/patches/server/0503-Add-moon-phase-API.patch similarity index 100% rename from patches/server/0502-Add-moon-phase-API.patch rename to patches/server/0503-Add-moon-phase-API.patch diff --git a/patches/server/0503-Prevent-headless-pistons-from-being-created.patch b/patches/server/0504-Prevent-headless-pistons-from-being-created.patch similarity index 100% rename from patches/server/0503-Prevent-headless-pistons-from-being-created.patch rename to patches/server/0504-Prevent-headless-pistons-from-being-created.patch diff --git a/patches/server/0504-Add-BellRingEvent.patch b/patches/server/0505-Add-BellRingEvent.patch similarity index 100% rename from patches/server/0504-Add-BellRingEvent.patch rename to patches/server/0505-Add-BellRingEvent.patch diff --git a/patches/server/0505-Add-zombie-targets-turtle-egg-config.patch b/patches/server/0506-Add-zombie-targets-turtle-egg-config.patch similarity index 92% rename from patches/server/0505-Add-zombie-targets-turtle-egg-config.patch rename to patches/server/0506-Add-zombie-targets-turtle-egg-config.patch index 7704727c56..2f5c2120c0 100644 --- a/patches/server/0505-Add-zombie-targets-turtle-egg-config.patch +++ b/patches/server/0506-Add-zombie-targets-turtle-egg-config.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add zombie targets turtle egg config diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 91917b11163c0740d5e5effc5e93d494e2b2d73e..caac3c9936c764e411799cb6a702b590f49d9955 100644 +index 040956f5d714ac014f9a153981d444db299fd826..83a4a3bbea1c076788cb7746adcee61e128b90fe 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -41,6 +41,11 @@ public class PaperWorldConfig { +@@ -38,6 +38,11 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0506-Buffer-joins-to-world.patch b/patches/server/0507-Buffer-joins-to-world.patch similarity index 100% rename from patches/server/0506-Buffer-joins-to-world.patch rename to patches/server/0507-Buffer-joins-to-world.patch diff --git a/patches/server/0507-Optimize-redstone-algorithm.patch b/patches/server/0508-Optimize-redstone-algorithm.patch similarity index 99% rename from patches/server/0507-Optimize-redstone-algorithm.patch rename to patches/server/0508-Optimize-redstone-algorithm.patch index 1c103119e7..4ed4d3c38a 100644 --- a/patches/server/0507-Optimize-redstone-algorithm.patch +++ b/patches/server/0508-Optimize-redstone-algorithm.patch @@ -19,10 +19,10 @@ Aside from making the obvious class/function renames and obfhelpers I didn't nee Just added Bukkit's event system and took a few liberties with dead code and comment misspellings. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index caac3c9936c764e411799cb6a702b590f49d9955..a88ef43adcf4ba36964f02e3fd363d3e018147cd 100644 +index 83a4a3bbea1c076788cb7746adcee61e128b90fe..acbaa00167d60ca6c6019b2dcd0947ef1d0557ee 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -46,6 +46,16 @@ public class PaperWorldConfig { +@@ -43,6 +43,16 @@ public class PaperWorldConfig { zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); } diff --git a/patches/server/0508-Fix-hex-colors-not-working-in-some-kick-messages.patch b/patches/server/0509-Fix-hex-colors-not-working-in-some-kick-messages.patch similarity index 100% rename from patches/server/0508-Fix-hex-colors-not-working-in-some-kick-messages.patch rename to patches/server/0509-Fix-hex-colors-not-working-in-some-kick-messages.patch diff --git a/patches/server/0509-PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server/0510-PortalCreateEvent-needs-to-know-its-entity.patch similarity index 100% rename from patches/server/0509-PortalCreateEvent-needs-to-know-its-entity.patch rename to patches/server/0510-PortalCreateEvent-needs-to-know-its-entity.patch diff --git a/patches/server/0510-Fix-CraftTeam-null-check.patch b/patches/server/0511-Fix-CraftTeam-null-check.patch similarity index 100% rename from patches/server/0510-Fix-CraftTeam-null-check.patch rename to patches/server/0511-Fix-CraftTeam-null-check.patch diff --git a/patches/server/0511-Add-more-Evoker-API.patch b/patches/server/0512-Add-more-Evoker-API.patch similarity index 100% rename from patches/server/0511-Add-more-Evoker-API.patch rename to patches/server/0512-Add-more-Evoker-API.patch diff --git a/patches/server/0512-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/server/0513-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 100% rename from patches/server/0512-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to patches/server/0513-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch diff --git a/patches/server/0513-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server/0514-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 100% rename from patches/server/0513-Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/server/0514-Create-HoverEvent-from-ItemStack-Entity.patch diff --git a/patches/server/0514-Cache-block-data-strings.patch b/patches/server/0515-Cache-block-data-strings.patch similarity index 100% rename from patches/server/0514-Cache-block-data-strings.patch rename to patches/server/0515-Cache-block-data-strings.patch diff --git a/patches/server/0515-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/patches/server/0516-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch similarity index 100% rename from patches/server/0515-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch rename to patches/server/0516-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch diff --git a/patches/server/0516-Add-additional-open-container-api-to-HumanEntity.patch b/patches/server/0517-Add-additional-open-container-api-to-HumanEntity.patch similarity index 100% rename from patches/server/0516-Add-additional-open-container-api-to-HumanEntity.patch rename to patches/server/0517-Add-additional-open-container-api-to-HumanEntity.patch diff --git a/patches/server/0517-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/patches/server/0518-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch similarity index 100% rename from patches/server/0517-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch rename to patches/server/0518-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch diff --git a/patches/server/0518-Extend-block-drop-capture-to-capture-all-items-added.patch b/patches/server/0519-Extend-block-drop-capture-to-capture-all-items-added.patch similarity index 92% rename from patches/server/0518-Extend-block-drop-capture-to-capture-all-items-added.patch rename to patches/server/0519-Extend-block-drop-capture-to-capture-all-items-added.patch index e32d13d264..07fde0b288 100644 --- a/patches/server/0518-Extend-block-drop-capture-to-capture-all-items-added.patch +++ b/patches/server/0519-Extend-block-drop-capture-to-capture-all-items-added.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Extend block drop capture to capture all items added to the diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 4ae56444d258cdf44a02256315d6aae84e2f53be..f1c02ae301da2a3b582d2ec1215c1a981e26ac47 100644 +index 93d31c6f4d05625c2fab1bd7166922323dac4b47..fd797376447e121c56a557ea6af277654e3a1831 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1220,6 +1220,13 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl @@ -24,7 +24,7 @@ index 4ae56444d258cdf44a02256315d6aae84e2f53be..f1c02ae301da2a3b582d2ec1215c1a98 return false; } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index 6c55bd8b876d1d694e05ad6de6a9fd29a4d4d053..de4fdd46f23b2b17da752a8afc0faecc1ad8344f 100644 +index c21c5134308a2a83fb50bfe37f05d19c8e96ca7c..c3cdc5a7ae90b7d2dd5676d66086e1f0c5b23d0d 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java @@ -7,6 +7,7 @@ import net.minecraft.world.InteractionResult; @@ -35,7 +35,7 @@ index 6c55bd8b876d1d694e05ad6de6a9fd29a4d4d053..de4fdd46f23b2b17da752a8afc0faecc import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.DoubleHighBlockItem; import net.minecraft.world.item.ItemStack; -@@ -421,10 +422,12 @@ public class ServerPlayerGameMode { +@@ -423,10 +424,12 @@ public class ServerPlayerGameMode { // return true; // CraftBukkit } // CraftBukkit start diff --git a/patches/server/0519-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server/0520-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch similarity index 100% rename from patches/server/0519-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch rename to patches/server/0520-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch diff --git a/patches/server/0520-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server/0521-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 100% rename from patches/server/0520-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to patches/server/0521-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch diff --git a/patches/server/0521-Lazily-track-plugin-scoreboards-by-default.patch b/patches/server/0522-Lazily-track-plugin-scoreboards-by-default.patch similarity index 100% rename from patches/server/0521-Lazily-track-plugin-scoreboards-by-default.patch rename to patches/server/0522-Lazily-track-plugin-scoreboards-by-default.patch diff --git a/patches/server/0522-Entity-isTicking.patch b/patches/server/0523-Entity-isTicking.patch similarity index 100% rename from patches/server/0522-Entity-isTicking.patch rename to patches/server/0523-Entity-isTicking.patch diff --git a/patches/server/0523-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/patches/server/0524-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch similarity index 100% rename from patches/server/0523-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch rename to patches/server/0524-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch diff --git a/patches/server/0524-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/patches/server/0525-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch similarity index 100% rename from patches/server/0524-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch rename to patches/server/0525-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch diff --git a/patches/server/0525-Reset-Ender-Crystals-on-Dragon-Spawn.patch b/patches/server/0526-Reset-Ender-Crystals-on-Dragon-Spawn.patch similarity index 100% rename from patches/server/0525-Reset-Ender-Crystals-on-Dragon-Spawn.patch rename to patches/server/0526-Reset-Ender-Crystals-on-Dragon-Spawn.patch diff --git a/patches/server/0526-Fix-for-large-move-vectors-crashing-server.patch b/patches/server/0527-Fix-for-large-move-vectors-crashing-server.patch similarity index 100% rename from patches/server/0526-Fix-for-large-move-vectors-crashing-server.patch rename to patches/server/0527-Fix-for-large-move-vectors-crashing-server.patch diff --git a/patches/server/0527-Optimise-getType-calls.patch b/patches/server/0528-Optimise-getType-calls.patch similarity index 96% rename from patches/server/0527-Optimise-getType-calls.patch rename to patches/server/0528-Optimise-getType-calls.patch index e67e76e8d0..29bd54a4d7 100644 --- a/patches/server/0527-Optimise-getType-calls.patch +++ b/patches/server/0528-Optimise-getType-calls.patch @@ -80,10 +80,10 @@ index 6dc8f9f269db6971b8b46819e017357899ccd118..7f49c7c7048b5778f20ddce1d844d4b3 public BlockState getState() { diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index 6e8018241664d2cc2a6a8d52d87946740ac8bb97..8038fe792533617023e9667fa2763ce98975318c 100644 +index 24a2e88d083f90375c46cf948c7c89dccc6e4aa0..53a0edfff9b8a5417461aa253ee6df4f592fd5d8 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java +++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -75,7 +75,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { +@@ -77,7 +77,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { @Override public Material getType(int x, int y, int z) { diff --git a/patches/server/0528-Villager-resetOffers.patch b/patches/server/0529-Villager-resetOffers.patch similarity index 100% rename from patches/server/0528-Villager-resetOffers.patch rename to patches/server/0529-Villager-resetOffers.patch diff --git a/patches/server/0529-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/patches/server/0530-Improve-inlinig-for-some-hot-IBlockData-methods.patch similarity index 100% rename from patches/server/0529-Improve-inlinig-for-some-hot-IBlockData-methods.patch rename to patches/server/0530-Improve-inlinig-for-some-hot-IBlockData-methods.patch diff --git a/patches/server/0530-Retain-block-place-order-when-capturing-blockstates.patch b/patches/server/0531-Retain-block-place-order-when-capturing-blockstates.patch similarity index 93% rename from patches/server/0530-Retain-block-place-order-when-capturing-blockstates.patch rename to patches/server/0531-Retain-block-place-order-when-capturing-blockstates.patch index 86eaf1f7dc..c81368ec8e 100644 --- a/patches/server/0530-Retain-block-place-order-when-capturing-blockstates.patch +++ b/patches/server/0531-Retain-block-place-order-when-capturing-blockstates.patch @@ -10,7 +10,7 @@ In general, look at making this logic more robust (i.e properly handling cases where a captured entry is overriden) - but for now this will do. diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index b92d930448757968cd6a178f4bcafae72c93044c..0c1774ecf236d7616738a170930abe58c5d12ece 100644 +index f004f5012ce157f9b0fb9c5890b5f3de957418f8..febc4fececb4bf527a69e47a06d782ec81616c1e 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -147,7 +147,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { diff --git a/patches/server/0531-Reduce-blockpos-allocation-from-pathfinding.patch b/patches/server/0532-Reduce-blockpos-allocation-from-pathfinding.patch similarity index 100% rename from patches/server/0531-Reduce-blockpos-allocation-from-pathfinding.patch rename to patches/server/0532-Reduce-blockpos-allocation-from-pathfinding.patch diff --git a/patches/server/0532-Fix-item-locations-dropped-from-campfires.patch b/patches/server/0533-Fix-item-locations-dropped-from-campfires.patch similarity index 100% rename from patches/server/0532-Fix-item-locations-dropped-from-campfires.patch rename to patches/server/0533-Fix-item-locations-dropped-from-campfires.patch diff --git a/patches/server/0533-Player-elytra-boost-API.patch b/patches/server/0534-Player-elytra-boost-API.patch similarity index 100% rename from patches/server/0533-Player-elytra-boost-API.patch rename to patches/server/0534-Player-elytra-boost-API.patch diff --git a/patches/server/0534-Fixed-TileEntityBell-memory-leak.patch b/patches/server/0535-Fixed-TileEntityBell-memory-leak.patch similarity index 100% rename from patches/server/0534-Fixed-TileEntityBell-memory-leak.patch rename to patches/server/0535-Fixed-TileEntityBell-memory-leak.patch diff --git a/patches/server/0535-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/patches/server/0536-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch similarity index 100% rename from patches/server/0535-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch rename to patches/server/0536-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch diff --git a/patches/server/0536-Add-getOfflinePlayerIfCached-String.patch b/patches/server/0537-Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from patches/server/0536-Add-getOfflinePlayerIfCached-String.patch rename to patches/server/0537-Add-getOfflinePlayerIfCached-String.patch diff --git a/patches/server/0537-Add-ignore-discounts-API.patch b/patches/server/0538-Add-ignore-discounts-API.patch similarity index 100% rename from patches/server/0537-Add-ignore-discounts-API.patch rename to patches/server/0538-Add-ignore-discounts-API.patch diff --git a/patches/server/0538-Toggle-for-removing-existing-dragon.patch b/patches/server/0539-Toggle-for-removing-existing-dragon.patch similarity index 92% rename from patches/server/0538-Toggle-for-removing-existing-dragon.patch rename to patches/server/0539-Toggle-for-removing-existing-dragon.patch index 3bb55320e8..c7654f7d44 100644 --- a/patches/server/0538-Toggle-for-removing-existing-dragon.patch +++ b/patches/server/0539-Toggle-for-removing-existing-dragon.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Toggle for removing existing dragon diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a88ef43adcf4ba36964f02e3fd363d3e018147cd..1a2f62fae9ccf31764d8e10642ef38bdb955dc41 100644 +index acbaa00167d60ca6c6019b2dcd0947ef1d0557ee..b3e9149dbbc1cd6a6d01bb9f7109136b995afb0a 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -56,6 +56,14 @@ public class PaperWorldConfig { +@@ -53,6 +53,14 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0539-Fix-client-lag-on-advancement-loading.patch b/patches/server/0540-Fix-client-lag-on-advancement-loading.patch similarity index 100% rename from patches/server/0539-Fix-client-lag-on-advancement-loading.patch rename to patches/server/0540-Fix-client-lag-on-advancement-loading.patch diff --git a/patches/server/0540-Item-no-age-no-player-pickup.patch b/patches/server/0541-Item-no-age-no-player-pickup.patch similarity index 100% rename from patches/server/0540-Item-no-age-no-player-pickup.patch rename to patches/server/0541-Item-no-age-no-player-pickup.patch diff --git a/patches/server/0541-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/patches/server/0542-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch similarity index 100% rename from patches/server/0541-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch rename to patches/server/0542-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch diff --git a/patches/server/0542-Beacon-API-custom-effect-ranges.patch b/patches/server/0543-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from patches/server/0542-Beacon-API-custom-effect-ranges.patch rename to patches/server/0543-Beacon-API-custom-effect-ranges.patch diff --git a/patches/server/0543-Add-API-for-quit-reason.patch b/patches/server/0544-Add-API-for-quit-reason.patch similarity index 100% rename from patches/server/0543-Add-API-for-quit-reason.patch rename to patches/server/0544-Add-API-for-quit-reason.patch diff --git a/patches/server/0544-Seed-based-feature-search.patch b/patches/server/0545-Seed-based-feature-search.patch similarity index 96% rename from patches/server/0544-Seed-based-feature-search.patch rename to patches/server/0545-Seed-based-feature-search.patch index 05c05fa386..46be6bfd43 100644 --- a/patches/server/0544-Seed-based-feature-search.patch +++ b/patches/server/0545-Seed-based-feature-search.patch @@ -21,10 +21,10 @@ changes but this should usually not happen. A config option to disable this completely is added though in case that should ever be necessary. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1a2f62fae9ccf31764d8e10642ef38bdb955dc41..2097c579bda12c2d1d19d67a023ca94051509b51 100644 +index b3e9149dbbc1cd6a6d01bb9f7109136b995afb0a..2523aabf499ef3807af02f7e61a3b13dbca08ee3 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -379,6 +379,14 @@ public class PaperWorldConfig { +@@ -376,6 +376,14 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0545-Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server/0546-Add-Wandering-Trader-spawn-rate-config-options.patch similarity index 97% rename from patches/server/0545-Add-Wandering-Trader-spawn-rate-config-options.patch rename to patches/server/0546-Add-Wandering-Trader-spawn-rate-config-options.patch index d5e31e5fbb..22e1ab6f8c 100644 --- a/patches/server/0545-Add-Wandering-Trader-spawn-rate-config-options.patch +++ b/patches/server/0546-Add-Wandering-Trader-spawn-rate-config-options.patch @@ -11,10 +11,10 @@ in IWorldServerData are removed as they were only used in certain places, with h values used in other places. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2097c579bda12c2d1d19d67a023ca94051509b51..afc637476380da272e61c10663dc77b30901c03a 100644 +index 2523aabf499ef3807af02f7e61a3b13dbca08ee3..d76b292cdfa2ae4d84a449da7f66faba494f6b03 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -64,6 +64,19 @@ public class PaperWorldConfig { +@@ -61,6 +61,19 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0546-Significantly-improve-performance-of-the-end-generat.patch b/patches/server/0547-Significantly-improve-performance-of-the-end-generat.patch similarity index 100% rename from patches/server/0546-Significantly-improve-performance-of-the-end-generat.patch rename to patches/server/0547-Significantly-improve-performance-of-the-end-generat.patch diff --git a/patches/server/0547-Expose-world-spawn-angle.patch b/patches/server/0548-Expose-world-spawn-angle.patch similarity index 100% rename from patches/server/0547-Expose-world-spawn-angle.patch rename to patches/server/0548-Expose-world-spawn-angle.patch diff --git a/patches/server/0548-Add-Destroy-Speed-API.patch b/patches/server/0549-Add-Destroy-Speed-API.patch similarity index 100% rename from patches/server/0548-Add-Destroy-Speed-API.patch rename to patches/server/0549-Add-Destroy-Speed-API.patch diff --git a/patches/server/0549-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/patches/server/0550-Fix-Player-spawnParticle-x-y-z-precision-loss.patch similarity index 100% rename from patches/server/0549-Fix-Player-spawnParticle-x-y-z-precision-loss.patch rename to patches/server/0550-Fix-Player-spawnParticle-x-y-z-precision-loss.patch diff --git a/patches/server/0550-Add-LivingEntity-clearActiveItem.patch b/patches/server/0551-Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from patches/server/0550-Add-LivingEntity-clearActiveItem.patch rename to patches/server/0551-Add-LivingEntity-clearActiveItem.patch diff --git a/patches/server/0551-Add-PlayerItemCooldownEvent.patch b/patches/server/0552-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from patches/server/0551-Add-PlayerItemCooldownEvent.patch rename to patches/server/0552-Add-PlayerItemCooldownEvent.patch diff --git a/patches/server/0552-More-lightning-API.patch b/patches/server/0553-More-lightning-API.patch similarity index 100% rename from patches/server/0552-More-lightning-API.patch rename to patches/server/0553-More-lightning-API.patch diff --git a/patches/server/0553-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/0554-Climbing-should-not-bypass-cramming-gamerule.patch similarity index 98% rename from patches/server/0553-Climbing-should-not-bypass-cramming-gamerule.patch rename to patches/server/0554-Climbing-should-not-bypass-cramming-gamerule.patch index 5364432181..af8c479a90 100644 --- a/patches/server/0553-Climbing-should-not-bypass-cramming-gamerule.patch +++ b/patches/server/0554-Climbing-should-not-bypass-cramming-gamerule.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Climbing should not bypass cramming gamerule diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index afc637476380da272e61c10663dc77b30901c03a..247b30b2b2edbb1043b6385039ba830dea877c55 100644 +index d76b292cdfa2ae4d84a449da7f66faba494f6b03..0ec093e5d8865e909d0d105e27b81b31bdb5c192 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -77,6 +77,11 @@ public class PaperWorldConfig { +@@ -74,6 +74,11 @@ public class PaperWorldConfig { wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); } diff --git a/patches/server/0554-Added-missing-default-perms-for-commands.patch b/patches/server/0555-Added-missing-default-perms-for-commands.patch similarity index 100% rename from patches/server/0554-Added-missing-default-perms-for-commands.patch rename to patches/server/0555-Added-missing-default-perms-for-commands.patch diff --git a/patches/server/0555-Add-PlayerShearBlockEvent.patch b/patches/server/0556-Add-PlayerShearBlockEvent.patch similarity index 100% rename from patches/server/0555-Add-PlayerShearBlockEvent.patch rename to patches/server/0556-Add-PlayerShearBlockEvent.patch diff --git a/patches/server/0556-Set-spigots-verbose-world-setting-to-false-by-def.patch b/patches/server/0557-Set-spigots-verbose-world-setting-to-false-by-def.patch similarity index 100% rename from patches/server/0556-Set-spigots-verbose-world-setting-to-false-by-def.patch rename to patches/server/0557-Set-spigots-verbose-world-setting-to-false-by-def.patch diff --git a/patches/server/0557-Fix-curing-zombie-villager-discount-exploit.patch b/patches/server/0558-Fix-curing-zombie-villager-discount-exploit.patch similarity index 94% rename from patches/server/0557-Fix-curing-zombie-villager-discount-exploit.patch rename to patches/server/0558-Fix-curing-zombie-villager-discount-exploit.patch index 015e81c616..b6a6b16e0f 100644 --- a/patches/server/0557-Fix-curing-zombie-villager-discount-exploit.patch +++ b/patches/server/0558-Fix-curing-zombie-villager-discount-exploit.patch @@ -8,10 +8,10 @@ and curing a villager on repeat by simply resetting the relevant part of the reputation when it is cured. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 247b30b2b2edbb1043b6385039ba830dea877c55..618f47567ca9d4704f4686d7ca789286866f080a 100644 +index 0ec093e5d8865e909d0d105e27b81b31bdb5c192..1a8e7a495c38f617932825185378b2e494158175 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -82,6 +82,11 @@ public class PaperWorldConfig { +@@ -79,6 +79,11 @@ public class PaperWorldConfig { fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); } diff --git a/patches/server/0558-Limit-recipe-packets.patch b/patches/server/0559-Limit-recipe-packets.patch similarity index 100% rename from patches/server/0558-Limit-recipe-packets.patch rename to patches/server/0559-Limit-recipe-packets.patch diff --git a/patches/server/0559-Fix-CraftSound-backwards-compatibility.patch b/patches/server/0560-Fix-CraftSound-backwards-compatibility.patch similarity index 100% rename from patches/server/0559-Fix-CraftSound-backwards-compatibility.patch rename to patches/server/0560-Fix-CraftSound-backwards-compatibility.patch diff --git a/patches/server/0560-MC-4-Fix-item-position-desync.patch b/patches/server/0561-MC-4-Fix-item-position-desync.patch similarity index 100% rename from patches/server/0560-MC-4-Fix-item-position-desync.patch rename to patches/server/0561-MC-4-Fix-item-position-desync.patch diff --git a/patches/server/0561-Player-Chunk-Load-Unload-Events.patch b/patches/server/0562-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from patches/server/0561-Player-Chunk-Load-Unload-Events.patch rename to patches/server/0562-Player-Chunk-Load-Unload-Events.patch diff --git a/patches/server/0562-Optimize-Dynamic-get-Missing-Keys.patch b/patches/server/0563-Optimize-Dynamic-get-Missing-Keys.patch similarity index 100% rename from patches/server/0562-Optimize-Dynamic-get-Missing-Keys.patch rename to patches/server/0563-Optimize-Dynamic-get-Missing-Keys.patch diff --git a/patches/server/0563-Expose-LivingEntity-hurt-direction.patch b/patches/server/0564-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from patches/server/0563-Expose-LivingEntity-hurt-direction.patch rename to patches/server/0564-Expose-LivingEntity-hurt-direction.patch diff --git a/patches/server/0564-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server/0565-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from patches/server/0564-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/server/0565-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/patches/server/0565-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server/0566-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch similarity index 100% rename from patches/server/0565-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch rename to patches/server/0566-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch diff --git a/patches/server/0566-added-PlayerTradeEvent.patch b/patches/server/0567-added-PlayerTradeEvent.patch similarity index 100% rename from patches/server/0566-added-PlayerTradeEvent.patch rename to patches/server/0567-added-PlayerTradeEvent.patch diff --git a/patches/server/0567-Implement-TargetHitEvent.patch b/patches/server/0568-Implement-TargetHitEvent.patch similarity index 100% rename from patches/server/0567-Implement-TargetHitEvent.patch rename to patches/server/0568-Implement-TargetHitEvent.patch diff --git a/patches/server/0568-Additional-Block-Material-API-s.patch b/patches/server/0569-Additional-Block-Material-API-s.patch similarity index 100% rename from patches/server/0568-Additional-Block-Material-API-s.patch rename to patches/server/0569-Additional-Block-Material-API-s.patch diff --git a/patches/server/0569-Fix-harming-potion-dupe.patch b/patches/server/0570-Fix-harming-potion-dupe.patch similarity index 100% rename from patches/server/0569-Fix-harming-potion-dupe.patch rename to patches/server/0570-Fix-harming-potion-dupe.patch diff --git a/patches/server/0570-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/patches/server/0571-Implement-API-to-get-Material-from-Boats-and-Minecar.patch similarity index 100% rename from patches/server/0570-Implement-API-to-get-Material-from-Boats-and-Minecar.patch rename to patches/server/0571-Implement-API-to-get-Material-from-Boats-and-Minecar.patch diff --git a/patches/server/0571-Cache-burn-durations.patch b/patches/server/0572-Cache-burn-durations.patch similarity index 100% rename from patches/server/0571-Cache-burn-durations.patch rename to patches/server/0572-Cache-burn-durations.patch diff --git a/patches/server/0572-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server/0573-Allow-disabling-mob-spawner-spawn-egg-transformation.patch similarity index 93% rename from patches/server/0572-Allow-disabling-mob-spawner-spawn-egg-transformation.patch rename to patches/server/0573-Allow-disabling-mob-spawner-spawn-egg-transformation.patch index 25231c3e9e..df86b299c0 100644 --- a/patches/server/0572-Allow-disabling-mob-spawner-spawn-egg-transformation.patch +++ b/patches/server/0573-Allow-disabling-mob-spawner-spawn-egg-transformation.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow disabling mob spawner spawn egg transformation diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 618f47567ca9d4704f4686d7ca789286866f080a..bedadfc8835fa0c834494eb10cef13fa1cdc5cf5 100644 +index 1a8e7a495c38f617932825185378b2e494158175..3c9bc0684f25d511b05b724d4d52aaa82e965397 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -87,6 +87,11 @@ public class PaperWorldConfig { +@@ -84,6 +84,11 @@ public class PaperWorldConfig { fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); } diff --git a/patches/server/0573-Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server/0574-Implement-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from patches/server/0573-Implement-PlayerFlowerPotManipulateEvent.patch rename to patches/server/0574-Implement-PlayerFlowerPotManipulateEvent.patch diff --git a/patches/server/0574-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server/0575-Fix-interact-event-not-being-called-in-adventure.patch similarity index 100% rename from patches/server/0574-Fix-interact-event-not-being-called-in-adventure.patch rename to patches/server/0575-Fix-interact-event-not-being-called-in-adventure.patch diff --git a/patches/server/0575-Zombie-API-breaking-doors.patch b/patches/server/0576-Zombie-API-breaking-doors.patch similarity index 100% rename from patches/server/0575-Zombie-API-breaking-doors.patch rename to patches/server/0576-Zombie-API-breaking-doors.patch diff --git a/patches/server/0576-Fix-nerfed-slime-when-splitting.patch b/patches/server/0577-Fix-nerfed-slime-when-splitting.patch similarity index 100% rename from patches/server/0576-Fix-nerfed-slime-when-splitting.patch rename to patches/server/0577-Fix-nerfed-slime-when-splitting.patch diff --git a/patches/server/0577-Add-EntityLoadCrossbowEvent.patch b/patches/server/0578-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from patches/server/0577-Add-EntityLoadCrossbowEvent.patch rename to patches/server/0578-Add-EntityLoadCrossbowEvent.patch diff --git a/patches/server/0578-Guardian-beam-workaround.patch b/patches/server/0579-Guardian-beam-workaround.patch similarity index 100% rename from patches/server/0578-Guardian-beam-workaround.patch rename to patches/server/0579-Guardian-beam-workaround.patch diff --git a/patches/server/0579-Added-WorldGameRuleChangeEvent.patch b/patches/server/0580-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from patches/server/0579-Added-WorldGameRuleChangeEvent.patch rename to patches/server/0580-Added-WorldGameRuleChangeEvent.patch diff --git a/patches/server/0580-Added-ServerResourcesReloadedEvent.patch b/patches/server/0581-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from patches/server/0580-Added-ServerResourcesReloadedEvent.patch rename to patches/server/0581-Added-ServerResourcesReloadedEvent.patch diff --git a/patches/server/0581-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server/0582-Added-world-settings-for-mobs-picking-up-loot.patch similarity index 95% rename from patches/server/0581-Added-world-settings-for-mobs-picking-up-loot.patch rename to patches/server/0582-Added-world-settings-for-mobs-picking-up-loot.patch index 78f99e2245..84060c5b85 100644 --- a/patches/server/0581-Added-world-settings-for-mobs-picking-up-loot.patch +++ b/patches/server/0582-Added-world-settings-for-mobs-picking-up-loot.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Added world settings for mobs picking up loot diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index bedadfc8835fa0c834494eb10cef13fa1cdc5cf5..b0b414a31192a2b0e5c69d00b982f883b66e77fd 100644 +index 3c9bc0684f25d511b05b724d4d52aaa82e965397..4a9fedb40acc72bec29fe71634406b06ce6b53cd 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -433,6 +433,14 @@ public class PaperWorldConfig { +@@ -430,6 +430,14 @@ public class PaperWorldConfig { log("Creeper lingering effect: " + disableCreeperLingeringEffect); } diff --git a/patches/server/0582-Implemented-BlockFailedDispenseEvent.patch b/patches/server/0583-Implemented-BlockFailedDispenseEvent.patch similarity index 100% rename from patches/server/0582-Implemented-BlockFailedDispenseEvent.patch rename to patches/server/0583-Implemented-BlockFailedDispenseEvent.patch diff --git a/patches/server/0583-Added-PlayerLecternPageChangeEvent.patch b/patches/server/0584-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from patches/server/0583-Added-PlayerLecternPageChangeEvent.patch rename to patches/server/0584-Added-PlayerLecternPageChangeEvent.patch diff --git a/patches/server/0584-Added-PlayerLoomPatternSelectEvent.patch b/patches/server/0585-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from patches/server/0584-Added-PlayerLoomPatternSelectEvent.patch rename to patches/server/0585-Added-PlayerLoomPatternSelectEvent.patch diff --git a/patches/server/0585-Configurable-door-breaking-difficulty.patch b/patches/server/0586-Configurable-door-breaking-difficulty.patch similarity index 92% rename from patches/server/0585-Configurable-door-breaking-difficulty.patch rename to patches/server/0586-Configurable-door-breaking-difficulty.patch index 8b84a411c3..a2bac6f78b 100644 --- a/patches/server/0585-Configurable-door-breaking-difficulty.patch +++ b/patches/server/0586-Configurable-door-breaking-difficulty.patch @@ -5,22 +5,22 @@ Subject: [PATCH] Configurable door breaking difficulty diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b0b414a31192a2b0e5c69d00b982f883b66e77fd..dd5c092a035a30c477fe828b58bc918fc48daa03 100644 +index 4a9fedb40acc72bec29fe71634406b06ce6b53cd..48e0f9b8dbb94d56200b0b46c2a50d9bfa44b398 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -4,7 +4,10 @@ import java.util.EnumMap; - import java.util.HashMap; +@@ -2,7 +2,10 @@ package com.destroystokyo.paper; + + import java.util.Arrays; import java.util.List; - import java.util.Map; - +import java.util.stream.Collectors; +import net.minecraft.world.Difficulty; +import net.minecraft.world.entity.monster.Vindicator; +import net.minecraft.world.entity.monster.Zombie; + import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; import org.bukkit.Bukkit; - import org.bukkit.Material; - import org.bukkit.configuration.ConfigurationSection; -@@ -92,6 +95,25 @@ public class PaperWorldConfig { + import org.bukkit.configuration.file.YamlConfiguration; +@@ -89,6 +92,25 @@ public class PaperWorldConfig { disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); } @@ -46,7 +46,7 @@ index b0b414a31192a2b0e5c69d00b982f883b66e77fd..dd5c092a035a30c477fe828b58bc918f public short keepLoadedRange; private void keepLoadedRange() { keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); -@@ -143,6 +165,11 @@ public class PaperWorldConfig { +@@ -140,6 +162,11 @@ public class PaperWorldConfig { return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); } diff --git a/patches/server/0586-Empty-commands-shall-not-be-dispatched.patch b/patches/server/0587-Empty-commands-shall-not-be-dispatched.patch similarity index 100% rename from patches/server/0586-Empty-commands-shall-not-be-dispatched.patch rename to patches/server/0587-Empty-commands-shall-not-be-dispatched.patch diff --git a/patches/server/0587-Implement-API-to-expose-exact-interaction-point.patch b/patches/server/0588-Implement-API-to-expose-exact-interaction-point.patch similarity index 96% rename from patches/server/0587-Implement-API-to-expose-exact-interaction-point.patch rename to patches/server/0588-Implement-API-to-expose-exact-interaction-point.patch index 410f64669f..7d021dd589 100644 --- a/patches/server/0587-Implement-API-to-expose-exact-interaction-point.patch +++ b/patches/server/0588-Implement-API-to-expose-exact-interaction-point.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Implement API to expose exact interaction point diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index de4fdd46f23b2b17da752a8afc0faecc1ad8344f..2a0f313365a25c1780027f1536dbb88ccdab61e2 100644 +index c3cdc5a7ae90b7d2dd5676d66086e1f0c5b23d0d..b096384cdc7596166e010e06272534b8001693c9 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -498,7 +498,7 @@ public class ServerPlayerGameMode { +@@ -500,7 +500,7 @@ public class ServerPlayerGameMode { cancelledBlock = true; } diff --git a/patches/server/0588-Remove-stale-POIs.patch b/patches/server/0589-Remove-stale-POIs.patch similarity index 92% rename from patches/server/0588-Remove-stale-POIs.patch rename to patches/server/0589-Remove-stale-POIs.patch index 712638228b..89164a2d29 100644 --- a/patches/server/0588-Remove-stale-POIs.patch +++ b/patches/server/0589-Remove-stale-POIs.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Remove stale POIs diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 908708900a9160d95dea3a392d96a40a17489280..a883677719b408edf0b81cdc885e65759a03936e 100644 +index fd797376447e121c56a557ea6af277654e3a1831..d5cfcba5e9a496deafa32f162b6ef634eae06214 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1764,6 +1764,11 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0589-Fix-villager-boat-exploit.patch b/patches/server/0590-Fix-villager-boat-exploit.patch similarity index 100% rename from patches/server/0589-Fix-villager-boat-exploit.patch rename to patches/server/0590-Fix-villager-boat-exploit.patch diff --git a/patches/server/0590-Add-sendOpLevel-API.patch b/patches/server/0591-Add-sendOpLevel-API.patch similarity index 100% rename from patches/server/0590-Add-sendOpLevel-API.patch rename to patches/server/0591-Add-sendOpLevel-API.patch diff --git a/patches/server/0591-Add-StructureLocateEvent.patch b/patches/server/0592-Add-StructureLocateEvent.patch similarity index 100% rename from patches/server/0591-Add-StructureLocateEvent.patch rename to patches/server/0592-Add-StructureLocateEvent.patch diff --git a/patches/server/0592-Collision-option-for-requiring-a-player-participant.patch b/patches/server/0593-Collision-option-for-requiring-a-player-participant.patch similarity index 97% rename from patches/server/0592-Collision-option-for-requiring-a-player-participant.patch rename to patches/server/0593-Collision-option-for-requiring-a-player-participant.patch index a27b7eae79..ab0cf7aa4c 100644 --- a/patches/server/0592-Collision-option-for-requiring-a-player-participant.patch +++ b/patches/server/0593-Collision-option-for-requiring-a-player-participant.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Collision option for requiring a player participant diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index dd5c092a035a30c477fe828b58bc918fc48daa03..16b80fe4c55c51d3afaefba7eef97d1e3e4a3248 100644 +index 48e0f9b8dbb94d56200b0b46c2a50d9bfa44b398..bc39e5fe8c9f5d1e5b5c4ea7bd80193af8574211 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -67,6 +67,18 @@ public class PaperWorldConfig { +@@ -64,6 +64,18 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0593-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/patches/server/0594-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch similarity index 100% rename from patches/server/0593-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch rename to patches/server/0594-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch diff --git a/patches/server/0594-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/server/0595-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from patches/server/0594-Return-chat-component-with-empty-text-instead-of-thr.patch rename to patches/server/0595-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/patches/server/0595-Make-schedule-command-per-world.patch b/patches/server/0596-Make-schedule-command-per-world.patch similarity index 100% rename from patches/server/0595-Make-schedule-command-per-world.patch rename to patches/server/0596-Make-schedule-command-per-world.patch diff --git a/patches/server/0596-Configurable-max-leash-distance.patch b/patches/server/0597-Configurable-max-leash-distance.patch similarity index 94% rename from patches/server/0596-Configurable-max-leash-distance.patch rename to patches/server/0597-Configurable-max-leash-distance.patch index de244acf73..39b2c1b3a2 100644 --- a/patches/server/0596-Configurable-max-leash-distance.patch +++ b/patches/server/0597-Configurable-max-leash-distance.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable max leash distance diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 16b80fe4c55c51d3afaefba7eef97d1e3e4a3248..4ceb6b048889c62edb69c88422abddd1aee0bcf7 100644 +index bc39e5fe8c9f5d1e5b5c4ea7bd80193af8574211..214b7ab71c4717faa3c949e18f268bef3e066305 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -266,6 +266,12 @@ public class PaperWorldConfig { +@@ -263,6 +263,12 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0597-Implement-BlockPreDispenseEvent.patch b/patches/server/0598-Implement-BlockPreDispenseEvent.patch similarity index 100% rename from patches/server/0597-Implement-BlockPreDispenseEvent.patch rename to patches/server/0598-Implement-BlockPreDispenseEvent.patch diff --git a/patches/server/0598-Added-Vanilla-Entity-Tags.patch b/patches/server/0599-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from patches/server/0598-Added-Vanilla-Entity-Tags.patch rename to patches/server/0599-Added-Vanilla-Entity-Tags.patch diff --git a/patches/server/0599-added-Wither-API.patch b/patches/server/0600-added-Wither-API.patch similarity index 100% rename from patches/server/0599-added-Wither-API.patch rename to patches/server/0600-added-Wither-API.patch diff --git a/patches/server/0600-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/patches/server/0601-Added-firing-of-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from patches/server/0600-Added-firing-of-PlayerChangeBeaconEffectEvent.patch rename to patches/server/0601-Added-firing-of-PlayerChangeBeaconEffectEvent.patch diff --git a/patches/server/0601-Fix-console-spam-when-removing-chests-in-water.patch b/patches/server/0602-Fix-console-spam-when-removing-chests-in-water.patch similarity index 100% rename from patches/server/0601-Fix-console-spam-when-removing-chests-in-water.patch rename to patches/server/0602-Fix-console-spam-when-removing-chests-in-water.patch diff --git a/patches/server/0602-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server/0603-Add-toggle-for-always-placing-the-dragon-egg.patch similarity index 92% rename from patches/server/0602-Add-toggle-for-always-placing-the-dragon-egg.patch rename to patches/server/0603-Add-toggle-for-always-placing-the-dragon-egg.patch index 1ca09dd0b5..421a188e0f 100644 --- a/patches/server/0602-Add-toggle-for-always-placing-the-dragon-egg.patch +++ b/patches/server/0603-Add-toggle-for-always-placing-the-dragon-egg.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add toggle for always placing the dragon egg diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4ceb6b048889c62edb69c88422abddd1aee0bcf7..7738b5959f347cb369646852e7174aa580546400 100644 +index 214b7ab71c4717faa3c949e18f268bef3e066305..70fdd29f0dd6dfac94b2c20090348678a956c333 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -683,5 +683,10 @@ public class PaperWorldConfig { +@@ -714,5 +714,10 @@ public class PaperWorldConfig { private void perPlayerMobSpawns() { perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); } diff --git a/patches/server/0603-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server/0604-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from patches/server/0603-Added-PlayerStonecutterRecipeSelectEvent.patch rename to patches/server/0604-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/patches/server/0604-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/server/0605-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from patches/server/0604-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/server/0605-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/patches/server/0605-Skip-distance-map-update-when-spawning-disabled.patch b/patches/server/0606-Skip-distance-map-update-when-spawning-disabled.patch similarity index 100% rename from patches/server/0605-Skip-distance-map-update-when-spawning-disabled.patch rename to patches/server/0606-Skip-distance-map-update-when-spawning-disabled.patch diff --git a/patches/server/0606-Reset-shield-blocking-on-dimension-change.patch b/patches/server/0607-Reset-shield-blocking-on-dimension-change.patch similarity index 100% rename from patches/server/0606-Reset-shield-blocking-on-dimension-change.patch rename to patches/server/0607-Reset-shield-blocking-on-dimension-change.patch diff --git a/patches/server/0607-add-DragonEggFormEvent.patch b/patches/server/0608-add-DragonEggFormEvent.patch similarity index 100% rename from patches/server/0607-add-DragonEggFormEvent.patch rename to patches/server/0608-add-DragonEggFormEvent.patch diff --git a/patches/server/0608-EntityMoveEvent.patch b/patches/server/0609-EntityMoveEvent.patch similarity index 97% rename from patches/server/0608-EntityMoveEvent.patch rename to patches/server/0609-EntityMoveEvent.patch index b6b9cba0ed..95012893ed 100644 --- a/patches/server/0608-EntityMoveEvent.patch +++ b/patches/server/0609-EntityMoveEvent.patch @@ -17,7 +17,7 @@ index 51bbb11ff8d3da95fa6d9890be3135a34b3eafac..c8213692e658f6eb82d3bd843b9525ff this.profiler.push(() -> { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 0e14946284738b751790b2763bfe197c0148a54a..5cd1fe3506b1009de9fce64c3f4f44a29f13c359 100644 +index d5cfcba5e9a496deafa32f162b6ef634eae06214..103d32b360095c179e681bd354d0b9316b050339 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -200,6 +200,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0609-added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server/0610-added-option-to-disable-pathfinding-updates-on-block.patch similarity index 88% rename from patches/server/0609-added-option-to-disable-pathfinding-updates-on-block.patch rename to patches/server/0610-added-option-to-disable-pathfinding-updates-on-block.patch index 176d82a83b..ca55ee348e 100644 --- a/patches/server/0609-added-option-to-disable-pathfinding-updates-on-block.patch +++ b/patches/server/0610-added-option-to-disable-pathfinding-updates-on-block.patch @@ -5,10 +5,10 @@ Subject: [PATCH] added option to disable pathfinding updates on block changes diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7738b5959f347cb369646852e7174aa580546400..c6cbc656f2cf6b253c3dfc87b8367f11102c7e41 100644 +index 70fdd29f0dd6dfac94b2c20090348678a956c333..bc33cf47e6f67179656f9ac0c378408985d9a88e 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -688,5 +688,10 @@ public class PaperWorldConfig { +@@ -719,5 +719,10 @@ public class PaperWorldConfig { private void enderDragonsDeathAlwaysPlacesDragonEgg() { enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); } @@ -20,7 +20,7 @@ index 7738b5959f347cb369646852e7174aa580546400..c6cbc656f2cf6b253c3dfc87b8367f11 } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 5cd1fe3506b1009de9fce64c3f4f44a29f13c359..a2d9e093bf7b5ee947f1d7c3b94397cd93eedef7 100644 +index 103d32b360095c179e681bd354d0b9316b050339..1f1b1a62ea9b37bc671e4df60a00c16c1027d3f6 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1360,6 +1360,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0610-Inline-shift-direction-fields.patch b/patches/server/0611-Inline-shift-direction-fields.patch similarity index 100% rename from patches/server/0610-Inline-shift-direction-fields.patch rename to patches/server/0611-Inline-shift-direction-fields.patch diff --git a/patches/server/0611-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server/0612-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from patches/server/0611-Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/server/0612-Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/patches/server/0612-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/server/0613-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from patches/server/0612-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/server/0613-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/patches/server/0613-living-entity-allow-attribute-registration.patch b/patches/server/0614-living-entity-allow-attribute-registration.patch similarity index 100% rename from patches/server/0613-living-entity-allow-attribute-registration.patch rename to patches/server/0614-living-entity-allow-attribute-registration.patch diff --git a/patches/server/0614-fix-dead-slime-setSize-invincibility.patch b/patches/server/0615-fix-dead-slime-setSize-invincibility.patch similarity index 100% rename from patches/server/0614-fix-dead-slime-setSize-invincibility.patch rename to patches/server/0615-fix-dead-slime-setSize-invincibility.patch diff --git a/patches/server/0615-Merchant-getRecipes-should-return-an-immutable-list.patch b/patches/server/0616-Merchant-getRecipes-should-return-an-immutable-list.patch similarity index 100% rename from patches/server/0615-Merchant-getRecipes-should-return-an-immutable-list.patch rename to patches/server/0616-Merchant-getRecipes-should-return-an-immutable-list.patch diff --git a/patches/server/0616-misc-debugging-dumps.patch b/patches/server/0617-misc-debugging-dumps.patch similarity index 100% rename from patches/server/0616-misc-debugging-dumps.patch rename to patches/server/0617-misc-debugging-dumps.patch diff --git a/patches/server/0617-Add-support-for-hex-color-codes-in-console.patch b/patches/server/0618-Add-support-for-hex-color-codes-in-console.patch similarity index 100% rename from patches/server/0617-Add-support-for-hex-color-codes-in-console.patch rename to patches/server/0618-Add-support-for-hex-color-codes-in-console.patch diff --git a/patches/server/0618-Expose-Tracked-Players.patch b/patches/server/0619-Expose-Tracked-Players.patch similarity index 100% rename from patches/server/0618-Expose-Tracked-Players.patch rename to patches/server/0619-Expose-Tracked-Players.patch diff --git a/patches/server/0619-Remove-streams-from-SensorNearest.patch b/patches/server/0620-Remove-streams-from-SensorNearest.patch similarity index 100% rename from patches/server/0619-Remove-streams-from-SensorNearest.patch rename to patches/server/0620-Remove-streams-from-SensorNearest.patch diff --git a/patches/server/0620-MC-29274-Fix-Wither-hostility-towards-players.patch b/patches/server/0621-MC-29274-Fix-Wither-hostility-towards-players.patch similarity index 93% rename from patches/server/0620-MC-29274-Fix-Wither-hostility-towards-players.patch rename to patches/server/0621-MC-29274-Fix-Wither-hostility-towards-players.patch index 019deb51e8..519adeaa4d 100644 --- a/patches/server/0620-MC-29274-Fix-Wither-hostility-towards-players.patch +++ b/patches/server/0621-MC-29274-Fix-Wither-hostility-towards-players.patch @@ -5,10 +5,10 @@ Subject: [PATCH] MC-29274: Fix Wither hostility towards players diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c6cbc656f2cf6b253c3dfc87b8367f11102c7e41..caa15973d78e21725b5dd9e5fc91cede4cc0dac4 100644 +index bc33cf47e6f67179656f9ac0c378408985d9a88e..f97795330cff2df87c91a0946b80d156d1df9389 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -693,5 +693,11 @@ public class PaperWorldConfig { +@@ -724,5 +724,11 @@ public class PaperWorldConfig { private void setUpdatePathfindingOnBlockUpdate() { updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); } diff --git a/patches/server/0621-Throw-proper-exception-on-empty-JsonList-file.patch b/patches/server/0622-Throw-proper-exception-on-empty-JsonList-file.patch similarity index 100% rename from patches/server/0621-Throw-proper-exception-on-empty-JsonList-file.patch rename to patches/server/0622-Throw-proper-exception-on-empty-JsonList-file.patch diff --git a/patches/server/0622-Improve-ServerGUI.patch b/patches/server/0623-Improve-ServerGUI.patch similarity index 100% rename from patches/server/0622-Improve-ServerGUI.patch rename to patches/server/0623-Improve-ServerGUI.patch diff --git a/patches/server/0623-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/patches/server/0624-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch similarity index 100% rename from patches/server/0623-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch rename to patches/server/0624-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch diff --git a/patches/server/0624-fix-converting-txt-to-json-file.patch b/patches/server/0625-fix-converting-txt-to-json-file.patch similarity index 100% rename from patches/server/0624-fix-converting-txt-to-json-file.patch rename to patches/server/0625-fix-converting-txt-to-json-file.patch diff --git a/patches/server/0625-Add-worldborder-events.patch b/patches/server/0626-Add-worldborder-events.patch similarity index 100% rename from patches/server/0625-Add-worldborder-events.patch rename to patches/server/0626-Add-worldborder-events.patch diff --git a/patches/server/0626-added-PlayerNameEntityEvent.patch b/patches/server/0627-added-PlayerNameEntityEvent.patch similarity index 100% rename from patches/server/0626-added-PlayerNameEntityEvent.patch rename to patches/server/0627-added-PlayerNameEntityEvent.patch diff --git a/patches/server/0627-Prevent-grindstones-from-overstacking-items.patch b/patches/server/0628-Prevent-grindstones-from-overstacking-items.patch similarity index 100% rename from patches/server/0627-Prevent-grindstones-from-overstacking-items.patch rename to patches/server/0628-Prevent-grindstones-from-overstacking-items.patch diff --git a/patches/server/0628-Add-recipe-to-cook-events.patch b/patches/server/0629-Add-recipe-to-cook-events.patch similarity index 100% rename from patches/server/0628-Add-recipe-to-cook-events.patch rename to patches/server/0629-Add-recipe-to-cook-events.patch diff --git a/patches/server/0629-Add-Block-isValidTool.patch b/patches/server/0630-Add-Block-isValidTool.patch similarity index 100% rename from patches/server/0629-Add-Block-isValidTool.patch rename to patches/server/0630-Add-Block-isValidTool.patch diff --git a/patches/server/0630-Allow-using-signs-inside-spawn-protection.patch b/patches/server/0631-Allow-using-signs-inside-spawn-protection.patch similarity index 94% rename from patches/server/0630-Allow-using-signs-inside-spawn-protection.patch rename to patches/server/0631-Allow-using-signs-inside-spawn-protection.patch index 300b353455..b353cb3548 100644 --- a/patches/server/0630-Allow-using-signs-inside-spawn-protection.patch +++ b/patches/server/0631-Allow-using-signs-inside-spawn-protection.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow using signs inside spawn protection diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index caa15973d78e21725b5dd9e5fc91cede4cc0dac4..46601a98d9f06c6cfadc8120bcffab081ca7f557 100644 +index f97795330cff2df87c91a0946b80d156d1df9389..19a0b2a73ab1d066501148108d6cd9998d281853 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -699,5 +699,10 @@ public class PaperWorldConfig { +@@ -730,5 +730,10 @@ public class PaperWorldConfig { fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); log("Withers properly target players: " + fixWitherTargetingBug); } diff --git a/patches/server/0631-Implement-Keyed-on-World.patch b/patches/server/0632-Implement-Keyed-on-World.patch similarity index 100% rename from patches/server/0631-Implement-Keyed-on-World.patch rename to patches/server/0632-Implement-Keyed-on-World.patch diff --git a/patches/server/0632-Add-fast-alternative-constructor-for-Rotations.patch b/patches/server/0633-Add-fast-alternative-constructor-for-Rotations.patch similarity index 100% rename from patches/server/0632-Add-fast-alternative-constructor-for-Rotations.patch rename to patches/server/0633-Add-fast-alternative-constructor-for-Rotations.patch diff --git a/patches/server/0633-Item-Rarity-API.patch b/patches/server/0634-Item-Rarity-API.patch similarity index 100% rename from patches/server/0633-Item-Rarity-API.patch rename to patches/server/0634-Item-Rarity-API.patch diff --git a/patches/server/0634-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/patches/server/0635-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch similarity index 100% rename from patches/server/0634-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch rename to patches/server/0635-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch diff --git a/patches/server/0635-copy-TESign-isEditable-from-snapshots.patch b/patches/server/0636-copy-TESign-isEditable-from-snapshots.patch similarity index 100% rename from patches/server/0635-copy-TESign-isEditable-from-snapshots.patch rename to patches/server/0636-copy-TESign-isEditable-from-snapshots.patch diff --git a/patches/server/0636-Drop-carried-item-when-player-has-disconnected.patch b/patches/server/0637-Drop-carried-item-when-player-has-disconnected.patch similarity index 100% rename from patches/server/0636-Drop-carried-item-when-player-has-disconnected.patch rename to patches/server/0637-Drop-carried-item-when-player-has-disconnected.patch diff --git a/patches/server/0637-forced-whitelist-use-configurable-kick-message.patch b/patches/server/0638-forced-whitelist-use-configurable-kick-message.patch similarity index 100% rename from patches/server/0637-forced-whitelist-use-configurable-kick-message.patch rename to patches/server/0638-forced-whitelist-use-configurable-kick-message.patch diff --git a/patches/server/0638-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/patches/server/0639-Don-t-ignore-result-of-PlayerEditBookEvent.patch similarity index 100% rename from patches/server/0638-Don-t-ignore-result-of-PlayerEditBookEvent.patch rename to patches/server/0639-Don-t-ignore-result-of-PlayerEditBookEvent.patch diff --git a/patches/server/0639-fix-cancelling-block-falling-causing-client-desync.patch b/patches/server/0640-fix-cancelling-block-falling-causing-client-desync.patch similarity index 100% rename from patches/server/0639-fix-cancelling-block-falling-causing-client-desync.patch rename to patches/server/0640-fix-cancelling-block-falling-causing-client-desync.patch diff --git a/patches/server/0640-Expose-protocol-version.patch b/patches/server/0641-Expose-protocol-version.patch similarity index 100% rename from patches/server/0640-Expose-protocol-version.patch rename to patches/server/0641-Expose-protocol-version.patch diff --git a/patches/server/0641-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/server/0642-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 100% rename from patches/server/0641-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to patches/server/0642-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch diff --git a/patches/server/0642-Enhance-console-tab-completions-for-brigadier-comman.patch b/patches/server/0643-Enhance-console-tab-completions-for-brigadier-comman.patch similarity index 100% rename from patches/server/0642-Enhance-console-tab-completions-for-brigadier-comman.patch rename to patches/server/0643-Enhance-console-tab-completions-for-brigadier-comman.patch diff --git a/patches/server/0643-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/patches/server/0644-Fix-PlayerItemConsumeEvent-cancelling-properly.patch similarity index 100% rename from patches/server/0643-Fix-PlayerItemConsumeEvent-cancelling-properly.patch rename to patches/server/0644-Fix-PlayerItemConsumeEvent-cancelling-properly.patch diff --git a/patches/server/0644-Add-bypass-host-check.patch b/patches/server/0645-Add-bypass-host-check.patch similarity index 100% rename from patches/server/0644-Add-bypass-host-check.patch rename to patches/server/0645-Add-bypass-host-check.patch diff --git a/patches/server/0645-Set-area-affect-cloud-rotation.patch b/patches/server/0646-Set-area-affect-cloud-rotation.patch similarity index 100% rename from patches/server/0645-Set-area-affect-cloud-rotation.patch rename to patches/server/0646-Set-area-affect-cloud-rotation.patch diff --git a/patches/server/0646-add-isDeeplySleeping-to-HumanEntity.patch b/patches/server/0647-add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from patches/server/0646-add-isDeeplySleeping-to-HumanEntity.patch rename to patches/server/0647-add-isDeeplySleeping-to-HumanEntity.patch diff --git a/patches/server/0647-Fix-duplicating-give-items-on-item-drop-cancel.patch b/patches/server/0648-Fix-duplicating-give-items-on-item-drop-cancel.patch similarity index 100% rename from patches/server/0647-Fix-duplicating-give-items-on-item-drop-cancel.patch rename to patches/server/0648-Fix-duplicating-give-items-on-item-drop-cancel.patch diff --git a/patches/server/0648-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/server/0649-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from patches/server/0648-add-consumeFuel-to-FurnaceBurnEvent.patch rename to patches/server/0649-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/patches/server/0649-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/server/0650-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from patches/server/0649-add-get-set-drop-chance-to-EntityEquipment.patch rename to patches/server/0650-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/patches/server/0650-fix-PigZombieAngerEvent-cancellation.patch b/patches/server/0651-fix-PigZombieAngerEvent-cancellation.patch similarity index 100% rename from patches/server/0650-fix-PigZombieAngerEvent-cancellation.patch rename to patches/server/0651-fix-PigZombieAngerEvent-cancellation.patch diff --git a/patches/server/0651-Fix-checkReach-check-for-Shulker-boxes.patch b/patches/server/0652-Fix-checkReach-check-for-Shulker-boxes.patch similarity index 100% rename from patches/server/0651-Fix-checkReach-check-for-Shulker-boxes.patch rename to patches/server/0652-Fix-checkReach-check-for-Shulker-boxes.patch diff --git a/patches/server/0652-fix-PlayerItemHeldEvent-firing-twice.patch b/patches/server/0653-fix-PlayerItemHeldEvent-firing-twice.patch similarity index 100% rename from patches/server/0652-fix-PlayerItemHeldEvent-firing-twice.patch rename to patches/server/0653-fix-PlayerItemHeldEvent-firing-twice.patch diff --git a/patches/server/0653-Added-PlayerDeepSleepEvent.patch b/patches/server/0654-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from patches/server/0653-Added-PlayerDeepSleepEvent.patch rename to patches/server/0654-Added-PlayerDeepSleepEvent.patch diff --git a/patches/server/0654-More-World-API.patch b/patches/server/0655-More-World-API.patch similarity index 100% rename from patches/server/0654-More-World-API.patch rename to patches/server/0655-More-World-API.patch diff --git a/patches/server/0655-Added-PlayerBedFailEnterEvent.patch b/patches/server/0656-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from patches/server/0655-Added-PlayerBedFailEnterEvent.patch rename to patches/server/0656-Added-PlayerBedFailEnterEvent.patch diff --git a/patches/server/0656-Implement-methods-to-convert-between-Component-and-B.patch b/patches/server/0657-Implement-methods-to-convert-between-Component-and-B.patch similarity index 100% rename from patches/server/0656-Implement-methods-to-convert-between-Component-and-B.patch rename to patches/server/0657-Implement-methods-to-convert-between-Component-and-B.patch diff --git a/patches/server/0657-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/patches/server/0658-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch similarity index 100% rename from patches/server/0657-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch rename to patches/server/0658-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch diff --git a/patches/server/0658-Introduce-beacon-activation-deactivation-events.patch b/patches/server/0659-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from patches/server/0658-Introduce-beacon-activation-deactivation-events.patch rename to patches/server/0659-Introduce-beacon-activation-deactivation-events.patch diff --git a/patches/server/0659-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/server/0660-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from patches/server/0659-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/server/0660-add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/patches/server/0660-Add-Channel-initialization-listeners.patch b/patches/server/0661-Add-Channel-initialization-listeners.patch similarity index 100% rename from patches/server/0660-Add-Channel-initialization-listeners.patch rename to patches/server/0661-Add-Channel-initialization-listeners.patch diff --git a/patches/server/0661-Send-empty-commands-if-tab-completion-is-disabled.patch b/patches/server/0662-Send-empty-commands-if-tab-completion-is-disabled.patch similarity index 100% rename from patches/server/0661-Send-empty-commands-if-tab-completion-is-disabled.patch rename to patches/server/0662-Send-empty-commands-if-tab-completion-is-disabled.patch diff --git a/patches/server/0662-Add-more-WanderingTrader-API.patch b/patches/server/0663-Add-more-WanderingTrader-API.patch similarity index 100% rename from patches/server/0662-Add-more-WanderingTrader-API.patch rename to patches/server/0663-Add-more-WanderingTrader-API.patch diff --git a/patches/server/0663-Add-EntityBlockStorage-clearEntities.patch b/patches/server/0664-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from patches/server/0663-Add-EntityBlockStorage-clearEntities.patch rename to patches/server/0664-Add-EntityBlockStorage-clearEntities.patch diff --git a/patches/server/0664-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/server/0665-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from patches/server/0664-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to patches/server/0665-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/patches/server/0665-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/server/0666-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from patches/server/0665-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/server/0666-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/patches/server/0666-Inventory-close.patch b/patches/server/0667-Inventory-close.patch similarity index 100% rename from patches/server/0666-Inventory-close.patch rename to patches/server/0667-Inventory-close.patch diff --git a/patches/server/0667-call-PortalCreateEvent-players-and-end-platform.patch b/patches/server/0668-call-PortalCreateEvent-players-and-end-platform.patch similarity index 100% rename from patches/server/0667-call-PortalCreateEvent-players-and-end-platform.patch rename to patches/server/0668-call-PortalCreateEvent-players-and-end-platform.patch diff --git a/patches/server/0668-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/server/0669-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 100% rename from patches/server/0668-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/server/0669-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch diff --git a/patches/server/0669-Fix-CraftPotionBrewer-cache.patch b/patches/server/0670-Fix-CraftPotionBrewer-cache.patch similarity index 100% rename from patches/server/0669-Fix-CraftPotionBrewer-cache.patch rename to patches/server/0670-Fix-CraftPotionBrewer-cache.patch diff --git a/patches/server/0670-Add-basic-Datapack-API.patch b/patches/server/0671-Add-basic-Datapack-API.patch similarity index 100% rename from patches/server/0670-Add-basic-Datapack-API.patch rename to patches/server/0671-Add-basic-Datapack-API.patch diff --git a/patches/server/0671-Add-environment-variable-to-disable-server-gui.patch b/patches/server/0672-Add-environment-variable-to-disable-server-gui.patch similarity index 100% rename from patches/server/0671-Add-environment-variable-to-disable-server-gui.patch rename to patches/server/0672-Add-environment-variable-to-disable-server-gui.patch diff --git a/patches/server/0672-additions-to-PlayerGameModeChangeEvent.patch b/patches/server/0673-additions-to-PlayerGameModeChangeEvent.patch similarity index 98% rename from patches/server/0672-additions-to-PlayerGameModeChangeEvent.patch rename to patches/server/0673-additions-to-PlayerGameModeChangeEvent.patch index dda1537e31..673eefae1e 100644 --- a/patches/server/0672-additions-to-PlayerGameModeChangeEvent.patch +++ b/patches/server/0673-additions-to-PlayerGameModeChangeEvent.patch @@ -91,7 +91,7 @@ index 753ad5a12bc523eddfffa336a20ab3e3284e6f7c..9f218a4b253fe2ab0e70e871eeee05bb } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index 2a0f313365a25c1780027f1536dbb88ccdab61e2..013ed10b8eca812309a2c9a10acd668ad51aac8e 100644 +index b096384cdc7596166e010e06272534b8001693c9..4b756c0a4b607faa03b00ab81761335be63c39eb 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java @@ -74,18 +74,24 @@ public class ServerPlayerGameMode { diff --git a/patches/server/0673-ItemStack-repair-check-API.patch b/patches/server/0674-ItemStack-repair-check-API.patch similarity index 100% rename from patches/server/0673-ItemStack-repair-check-API.patch rename to patches/server/0674-ItemStack-repair-check-API.patch diff --git a/patches/server/0674-More-Enchantment-API.patch b/patches/server/0675-More-Enchantment-API.patch similarity index 100% rename from patches/server/0674-More-Enchantment-API.patch rename to patches/server/0675-More-Enchantment-API.patch diff --git a/patches/server/0675-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/server/0676-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 96% rename from patches/server/0675-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to patches/server/0676-Add-command-line-option-to-load-extra-plugin-jars-no.patch index 2299c257c0..ff5753ab51 100644 --- a/patches/server/0675-Add-command-line-option-to-load-extra-plugin-jars-no.patch +++ b/patches/server/0676-Add-command-line-option-to-load-extra-plugin-jars-no.patch @@ -7,7 +7,7 @@ Subject: [PATCH] Add command line option to load extra plugin jars not in the ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 2f914ebd18764fbfd3834c0a94cedb2184f8dbb0..59c352f9666ff9b828450a62f590ab637b4329b5 100644 +index b7db2d68deeee0a213ee26e31475f05ba16d073e..ca28dda0f9819e8d75fbaa48cf5ff5643910999a 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -386,8 +386,13 @@ public final class CraftServer implements Server { diff --git a/patches/server/0676-Fix-and-optimise-world-force-upgrading.patch b/patches/server/0677-Fix-and-optimise-world-force-upgrading.patch similarity index 95% rename from patches/server/0676-Fix-and-optimise-world-force-upgrading.patch rename to patches/server/0677-Fix-and-optimise-world-force-upgrading.patch index 83bea4ae22..8b74933f38 100644 --- a/patches/server/0676-Fix-and-optimise-world-force-upgrading.patch +++ b/patches/server/0677-Fix-and-optimise-world-force-upgrading.patch @@ -297,12 +297,12 @@ index 73ac55de9059a1d0f1da5bec0688dcd4bf5c8973..db2d6e7b2dc82c60d524dd2a018d28c2 if (dimensionKey == LevelStem.OVERWORLD) { diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 0c1774ecf236d7616738a170930abe58c5d12ece..667aecc27e0c886f15a0418020d046e0a9791a0e 100644 +index febc4fececb4bf527a69e47a06d782ec81616c1e..ccf6c79293ca046174b94a61a28aea3fa9c2a37f 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -185,6 +185,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return this.typeKey; - } +@@ -174,6 +174,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions + public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here + // Paper start - fix and optimise world upgrading + // copied from below @@ -312,9 +312,10 @@ index 0c1774ecf236d7616738a170930abe58c5d12ece..667aecc27e0c886f15a0418020d046e0 + }); + } + // Paper end - fix and optimise world upgrading - protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot - this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper ++ + public CraftWorld getWorld() { + return this.world; + } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java index 1bee455235ece8aa299a2baeede027d251e6ff57..60ae9395591c81aebaa4be1541380a8fe921ce68 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java diff --git a/patches/server/0677-Add-Mob-lookAt-API.patch b/patches/server/0678-Add-Mob-lookAt-API.patch similarity index 100% rename from patches/server/0677-Add-Mob-lookAt-API.patch rename to patches/server/0678-Add-Mob-lookAt-API.patch diff --git a/patches/server/0678-Add-Unix-domain-socket-support.patch b/patches/server/0679-Add-Unix-domain-socket-support.patch similarity index 100% rename from patches/server/0678-Add-Unix-domain-socket-support.patch rename to patches/server/0679-Add-Unix-domain-socket-support.patch diff --git a/patches/server/0679-Add-EntityInsideBlockEvent.patch b/patches/server/0680-Add-EntityInsideBlockEvent.patch similarity index 100% rename from patches/server/0679-Add-EntityInsideBlockEvent.patch rename to patches/server/0680-Add-EntityInsideBlockEvent.patch diff --git a/patches/server/0680-Attributes-API-for-item-defaults.patch b/patches/server/0681-Attributes-API-for-item-defaults.patch similarity index 100% rename from patches/server/0680-Attributes-API-for-item-defaults.patch rename to patches/server/0681-Attributes-API-for-item-defaults.patch diff --git a/patches/server/0681-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/patches/server/0682-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch similarity index 100% rename from patches/server/0681-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch rename to patches/server/0682-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch diff --git a/patches/server/0682-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/server/0683-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 98% rename from patches/server/0682-Add-cause-to-Weather-ThunderChangeEvents.patch rename to patches/server/0683-Add-cause-to-Weather-ThunderChangeEvents.patch index b94ca80e31..501e76c033 100644 --- a/patches/server/0682-Add-cause-to-Weather-ThunderChangeEvents.patch +++ b/patches/server/0683-Add-cause-to-Weather-ThunderChangeEvents.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add cause to Weather/ThunderChangeEvents diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index a2d9e093bf7b5ee947f1d7c3b94397cd93eedef7..985b8b9da26aba43b84e9fe363507627c625e6d3 100644 +index 1f1b1a62ea9b37bc671e4df60a00c16c1027d3f6..6c8d18c4ea8a332a6973c3bb257cb443fe844d17 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -419,8 +419,8 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0683-More-Lidded-Block-API.patch b/patches/server/0684-More-Lidded-Block-API.patch similarity index 100% rename from patches/server/0683-More-Lidded-Block-API.patch rename to patches/server/0684-More-Lidded-Block-API.patch diff --git a/patches/server/0684-Limit-item-frame-cursors-on-maps.patch b/patches/server/0685-Limit-item-frame-cursors-on-maps.patch similarity index 93% rename from patches/server/0684-Limit-item-frame-cursors-on-maps.patch rename to patches/server/0685-Limit-item-frame-cursors-on-maps.patch index 5717cf12a3..0f1eee2ed7 100644 --- a/patches/server/0684-Limit-item-frame-cursors-on-maps.patch +++ b/patches/server/0685-Limit-item-frame-cursors-on-maps.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Limit item frame cursors on maps diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 46601a98d9f06c6cfadc8120bcffab081ca7f557..b7b160ef6feded6b84faf9958599c761828fcf59 100644 +index 19a0b2a73ab1d066501148108d6cd9998d281853..0fef75148df251d76a029e86a345adad039fcdd0 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -704,5 +704,10 @@ public class PaperWorldConfig { +@@ -735,5 +735,10 @@ public class PaperWorldConfig { private void allowUsingSignsInsideSpawnProtection() { allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); } diff --git a/patches/server/0685-Add-PufferFishStateChangeEvent.patch b/patches/server/0686-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from patches/server/0685-Add-PufferFishStateChangeEvent.patch rename to patches/server/0686-Add-PufferFishStateChangeEvent.patch diff --git a/patches/server/0686-Add-PlayerKickEvent-causes.patch b/patches/server/0687-Add-PlayerKickEvent-causes.patch similarity index 100% rename from patches/server/0686-Add-PlayerKickEvent-causes.patch rename to patches/server/0687-Add-PlayerKickEvent-causes.patch diff --git a/patches/server/0687-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/patches/server/0688-Fix-PlayerBucketEmptyEvent-result-itemstack.patch similarity index 100% rename from patches/server/0687-Fix-PlayerBucketEmptyEvent-result-itemstack.patch rename to patches/server/0688-Fix-PlayerBucketEmptyEvent-result-itemstack.patch diff --git a/patches/server/0688-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch b/patches/server/0689-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch similarity index 71% rename from patches/server/0688-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch rename to patches/server/0689-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch index 598b0de366..fd18c13168 100644 --- a/patches/server/0688-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch +++ b/patches/server/0689-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch @@ -13,10 +13,10 @@ contention situations. And this is extremely a low contention situation. diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index 5ac948b5b82f3144cdf402af440251cb8c7369d7..d8b7a7d9aa3ef47aa4e222c6ca85e83ce21f2444 100644 +index 82a4b7969e36940cb694bd999b8c03f9c66a71dc..05d5a77c439b177dc12b8b1ebd4181a5446c0f31 100644 --- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -36,16 +36,18 @@ public class PalettedContainer implements PaletteResize { +@@ -37,16 +37,18 @@ public class PalettedContainer implements PaletteResize { private final DebugBuffer> traces = null; public void acquire() { @@ -35,8 +35,8 @@ index 5ac948b5b82f3144cdf402af440251cb8c7369d7..d8b7a7d9aa3ef47aa4e222c6ca85e83c + //this.lock.release(); // Paper - disable this } - public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { -@@ -96,7 +98,7 @@ public class PalettedContainer implements PaletteResize { + // Paper start - Anti-Xray - Add predefined objects +@@ -134,7 +136,7 @@ public class PalettedContainer implements PaletteResize { return this.palette.idFor(objectAdded); } @@ -45,7 +45,7 @@ index 5ac948b5b82f3144cdf402af440251cb8c7369d7..d8b7a7d9aa3ef47aa4e222c6ca85e83c Object var6; try { this.acquire(); -@@ -120,7 +122,7 @@ public class PalettedContainer implements PaletteResize { +@@ -158,7 +160,7 @@ public class PalettedContainer implements PaletteResize { return (T)(object == null ? this.defaultValue : object); } @@ -54,7 +54,7 @@ index 5ac948b5b82f3144cdf402af440251cb8c7369d7..d8b7a7d9aa3ef47aa4e222c6ca85e83c try { this.acquire(); this.set(getIndex(i, j, k), object); -@@ -144,7 +146,7 @@ public class PalettedContainer implements PaletteResize { +@@ -182,7 +184,7 @@ public class PalettedContainer implements PaletteResize { return (T)(object == null ? this.defaultValue : object); } @@ -63,16 +63,16 @@ index 5ac948b5b82f3144cdf402af440251cb8c7369d7..d8b7a7d9aa3ef47aa4e222c6ca85e83c try { this.acquire(); int i = buf.readByte(); -@@ -161,7 +163,7 @@ public class PalettedContainer implements PaletteResize { +@@ -203,7 +205,7 @@ public class PalettedContainer implements PaletteResize { + @Deprecated public void write(FriendlyByteBuf buf) { + write(buf, null, 0); } - - public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER -- public void write(FriendlyByteBuf buf) { -+ public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize +- public void write(FriendlyByteBuf buf, com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { ++ public synchronized void write(FriendlyByteBuf buf, com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { // Paper - synchronize + // Paper end try { this.acquire(); - buf.writeByte(this.bits); -@@ -173,7 +175,7 @@ public class PalettedContainer implements PaletteResize { +@@ -224,7 +226,7 @@ public class PalettedContainer implements PaletteResize { } @@ -80,8 +80,8 @@ index 5ac948b5b82f3144cdf402af440251cb8c7369d7..d8b7a7d9aa3ef47aa4e222c6ca85e83c + public synchronized void read(ListTag paletteNbt, long[] data) { // Paper - synchronize try { this.acquire(); - int i = Math.max(4, Mth.ceillog2(paletteNbt.size())); -@@ -206,7 +208,7 @@ public class PalettedContainer implements PaletteResize { + // Paper - Anti-Xray - TODO: Should this.predefinedObjects.length just be added here (faster) or should the contents be compared to calculate the size (less RAM)? +@@ -259,7 +261,7 @@ public class PalettedContainer implements PaletteResize { } diff --git a/patches/server/0689-Add-option-to-fix-items-merging-through-walls.patch b/patches/server/0690-Add-option-to-fix-items-merging-through-walls.patch similarity index 93% rename from patches/server/0689-Add-option-to-fix-items-merging-through-walls.patch rename to patches/server/0690-Add-option-to-fix-items-merging-through-walls.patch index 3e34d24f12..b0a39319bf 100644 --- a/patches/server/0689-Add-option-to-fix-items-merging-through-walls.patch +++ b/patches/server/0690-Add-option-to-fix-items-merging-through-walls.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to fix items merging through walls diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b7b160ef6feded6b84faf9958599c761828fcf59..75a02252f398b3d16f8588693e71f779d7fa062a 100644 +index 0fef75148df251d76a029e86a345adad039fcdd0..57929ffa8e992874089ee30d8a96eeb03d754816 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -709,5 +709,10 @@ public class PaperWorldConfig { +@@ -740,5 +740,10 @@ public class PaperWorldConfig { private void mapItemFrameCursorLimit() { mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); } diff --git a/patches/server/0690-Add-BellRevealRaiderEvent.patch b/patches/server/0691-Add-BellRevealRaiderEvent.patch similarity index 100% rename from patches/server/0690-Add-BellRevealRaiderEvent.patch rename to patches/server/0691-Add-BellRevealRaiderEvent.patch diff --git a/patches/server/0691-Fix-invulnerable-end-crystals.patch b/patches/server/0692-Fix-invulnerable-end-crystals.patch similarity index 96% rename from patches/server/0691-Fix-invulnerable-end-crystals.patch rename to patches/server/0692-Fix-invulnerable-end-crystals.patch index 6da3abadd1..7c436c60d4 100644 --- a/patches/server/0691-Fix-invulnerable-end-crystals.patch +++ b/patches/server/0692-Fix-invulnerable-end-crystals.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix invulnerable end crystals MC-108513 diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 75a02252f398b3d16f8588693e71f779d7fa062a..f2981aa82c26d7bdac08f45818813025b240b77e 100644 +index 57929ffa8e992874089ee30d8a96eeb03d754816..31be320d7d4cf8659d2d4281186b3f0d424a99e1 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -714,5 +714,10 @@ public class PaperWorldConfig { +@@ -745,5 +745,10 @@ public class PaperWorldConfig { private void fixItemsMergingThroughWalls() { fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); } diff --git a/patches/server/0692-Add-ElderGuardianAppearanceEvent.patch b/patches/server/0693-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from patches/server/0692-Add-ElderGuardianAppearanceEvent.patch rename to patches/server/0693-Add-ElderGuardianAppearanceEvent.patch diff --git a/patches/server/0693-Reset-villager-inventory-on-cancelled-pickup-event.patch b/patches/server/0694-Reset-villager-inventory-on-cancelled-pickup-event.patch similarity index 100% rename from patches/server/0693-Reset-villager-inventory-on-cancelled-pickup-event.patch rename to patches/server/0694-Reset-villager-inventory-on-cancelled-pickup-event.patch diff --git a/patches/server/0694-Fix-dangerous-end-portal-logic.patch b/patches/server/0695-Fix-dangerous-end-portal-logic.patch similarity index 100% rename from patches/server/0694-Fix-dangerous-end-portal-logic.patch rename to patches/server/0695-Fix-dangerous-end-portal-logic.patch diff --git a/patches/server/0695-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/server/0696-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch similarity index 100% rename from patches/server/0695-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch rename to patches/server/0696-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch diff --git a/patches/server/0696-Make-item-validations-configurable.patch b/patches/server/0697-Make-item-validations-configurable.patch similarity index 100% rename from patches/server/0696-Make-item-validations-configurable.patch rename to patches/server/0697-Make-item-validations-configurable.patch diff --git a/patches/server/0697-Add-more-line-of-sight-methods.patch b/patches/server/0698-Add-more-line-of-sight-methods.patch similarity index 100% rename from patches/server/0697-Add-more-line-of-sight-methods.patch rename to patches/server/0698-Add-more-line-of-sight-methods.patch diff --git a/patches/server/0698-add-per-world-spawn-limits.patch b/patches/server/0699-add-per-world-spawn-limits.patch similarity index 94% rename from patches/server/0698-add-per-world-spawn-limits.patch rename to patches/server/0699-add-per-world-spawn-limits.patch index a828305722..4bfb3570ac 100644 --- a/patches/server/0698-add-per-world-spawn-limits.patch +++ b/patches/server/0699-add-per-world-spawn-limits.patch @@ -6,10 +6,10 @@ Subject: [PATCH] add per world spawn limits Taken from #2982. Credit to Chasewhip8 diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index f2981aa82c26d7bdac08f45818813025b240b77e..974fba89648399919802dc4c11846601d2923712 100644 +index 31be320d7d4cf8659d2d4281186b3f0d424a99e1..cc2d40ba72a904baf2c39cd011cf7e1c746b2ca9 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -605,6 +605,19 @@ public class PaperWorldConfig { +@@ -602,6 +602,19 @@ public class PaperWorldConfig { zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); } diff --git a/patches/server/0699-Fix-PotionSplashEvent-for-water-splash-potions.patch b/patches/server/0700-Fix-PotionSplashEvent-for-water-splash-potions.patch similarity index 100% rename from patches/server/0699-Fix-PotionSplashEvent-for-water-splash-potions.patch rename to patches/server/0700-Fix-PotionSplashEvent-for-water-splash-potions.patch diff --git a/patches/server/0700-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/patches/server/0701-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch similarity index 100% rename from patches/server/0700-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch rename to patches/server/0701-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch From 7267c01db0cf3629f34f4b360db561ea9369428a Mon Sep 17 00:00:00 2001 From: KennyTV Date: Tue, 15 Jun 2021 16:07:27 +0200 Subject: [PATCH 158/226] Fix ChunkPacketBlockControllerAntiXray initialize --- patches/server/0364-Anti-Xray.patch | 27 ++++++++++++------- ...ement-optional-per-player-mob-spawns.patch | 4 +-- ...le-for-always-placing-the-dragon-egg.patch | 4 +-- ...disable-pathfinding-updates-on-block.patch | 4 +-- ...Fix-Wither-hostility-towards-players.patch | 4 +-- ...-using-signs-inside-spawn-protection.patch | 4 +-- ...685-Limit-item-frame-cursors-on-maps.patch | 4 +-- ...n-to-fix-items-merging-through-walls.patch | 4 +-- .../0692-Fix-invulnerable-end-crystals.patch | 4 +-- 9 files changed, 33 insertions(+), 26 deletions(-) diff --git a/patches/server/0364-Anti-Xray.patch b/patches/server/0364-Anti-Xray.patch index 982e71aa3f..4fd21d7351 100644 --- a/patches/server/0364-Anti-Xray.patch +++ b/patches/server/0364-Anti-Xray.patch @@ -11,7 +11,7 @@ I'm just here to watch you suffer :smile: You can skip it if you want and I can do it later. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e29566cad2647da4d9288e912188b57f00e8dd0c..51691d3dedf113d58f340b74d448c5e5375b5bed 100644 +index e29566cad2647da4d9288e912188b57f00e8dd0c..edb9952ddd014c92b9604a9a187fdcd46de8a04f 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -1,7 +1,9 @@ @@ -24,7 +24,7 @@ index e29566cad2647da4d9288e912188b57f00e8dd0c..51691d3dedf113d58f340b74d448c5e5 import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.spigotmc.SpigotWorldConfig; -@@ -445,5 +447,39 @@ public class PaperWorldConfig { +@@ -445,5 +447,41 @@ public class PaperWorldConfig { private void lightQueueSize() { lightQueueSize = getInt("light-queue-size", lightQueueSize); } @@ -46,7 +46,9 @@ index e29566cad2647da4d9288e912188b57f00e8dd0c..51691d3dedf113d58f340b74d448c5e5 + updateRadius = getInt("anti-xray.update-radius", 2); + lavaObscures = getBoolean("anti-xray.lava-obscures", false); + usePermission = getBoolean("anti-xray.use-permission", false); -+ hiddenBlocks = getList("anti-xray.hidden-blocks", Arrays.asList("gold_ore", "iron_ore", "coal_ore", "lapis_ore", "mossy_cobblestone", "obsidian", "chest", "diamond_ore", "redstone_ore", "clay", "emerald_ore", "ender_chest")); ++ hiddenBlocks = getList("anti-xray.hidden-blocks", Arrays.asList("copper_ore", "deepslate_copper_ore", "gold_ore", "deepslate_gold_ore", "iron_ore", "deepslate_iron_ore", ++ "coal_ore", "deepslate_coal_ore", "lapis_ore", "deepslate_lapis_ore", "mossy_cobblestone", "obsidian", "chest", "diamond_ore", "deepslate_diamond_ore", ++ "redstone_ore", "deepslate_redstone_ore", "clay", "emerald_ore", "deepslate_emerald_ore", "ender_chest")); + replacementBlocks = getList("anti-xray.replacement-blocks", Arrays.asList("stone", "oak_planks")); + if (PaperConfig.version < 19) { + hiddenBlocks.remove("lit_redstone_ore"); @@ -66,7 +68,7 @@ index e29566cad2647da4d9288e912188b57f00e8dd0c..51691d3dedf113d58f340b74d448c5e5 diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java new file mode 100644 -index 0000000000000000000000000000000000000000..fe1a91a3a281dd91e5989bf2282240b03684b500 +index 0000000000000000000000000000000000000000..95d16cd708817534e5f2748f5da9c98c835392be --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java @@ -0,0 +1,45 @@ @@ -117,7 +119,7 @@ index 0000000000000000000000000000000000000000..fe1a91a3a281dd91e5989bf2282240b0 +} diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java new file mode 100644 -index 0000000000000000000000000000000000000000..e1bc1093a03b931ff2c3870ea1601cd420f71192 +index 0000000000000000000000000000000000000000..db95bde2a0bb17d13d0588dd0bbb81b7c5506345 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java @@ -0,0 +1,649 @@ @@ -1157,7 +1159,7 @@ index f4a056185990181e486f452960159a5287947382..a695e5a0c2e8846333ccb9aea499b565 public void destroyAndAck(BlockPos pos, ServerboundPlayerActionPacket.Action action, String reason) { diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index aa198e9f2755734eac591bd3f94679518e9d7270..687e3652d0f36a358a2348df845801ad82d8460c 100644 +index aa198e9f2755734eac591bd3f94679518e9d7270..5c30d06ac80bb9e82d5eecf58b692040c3a55a99 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -164,6 +164,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @@ -1168,7 +1170,7 @@ index aa198e9f2755734eac591bd3f94679518e9d7270..687e3652d0f36a358a2348df845801ad public final co.aikar.timings.WorldTimingsHandler timings; // Paper public static BlockPos lastPhysicsProblem; // Spigot -@@ -185,9 +186,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -185,7 +186,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { return this.typeKey; } @@ -1176,12 +1178,17 @@ index aa198e9f2755734eac591bd3f94679518e9d7270..687e3652d0f36a358a2348df845801ad + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper + this.generator = gen; +@@ -258,6 +259,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.keepSpawnInMemory = this.paperConfig.keepSpawnInMemory; // Paper + this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + this.chunkPacketBlockController = this.paperConfig.antiXray ? + new com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray(this, executor) + : com.destroystokyo.paper.antixray.ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray - this.generator = gen; - this.world = new CraftWorld((ServerLevel) this, gen, env); - this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns(); // CraftBukkit + } + + // Paper start @@ -448,6 +452,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { // CraftBukkit end diff --git a/patches/server/0369-implement-optional-per-player-mob-spawns.patch b/patches/server/0369-implement-optional-per-player-mob-spawns.patch index 0ddeaece3a..08d0b300e2 100644 --- a/patches/server/0369-implement-optional-per-player-mob-spawns.patch +++ b/patches/server/0369-implement-optional-per-player-mob-spawns.patch @@ -25,10 +25,10 @@ index fe79c0add4f7cb18d487c5bb9415c40c5b551ea2..8d9ddad1879e7616d980ca70de8aecac poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3f4a9ce31981f77b1c451a5d9ba91d6c9ab67587..a69efd1a21a667c5eee539f6c761755479375527 100644 +index 1a21a177e3062130d7bbcde53e49732c634db73d..154866506a33cf2185891cd5051d51de9e2e4584 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -534,5 +534,10 @@ public class PaperWorldConfig { +@@ -536,5 +536,10 @@ public class PaperWorldConfig { Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); } } diff --git a/patches/server/0603-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server/0603-Add-toggle-for-always-placing-the-dragon-egg.patch index 421a188e0f..b579a1db1f 100644 --- a/patches/server/0603-Add-toggle-for-always-placing-the-dragon-egg.patch +++ b/patches/server/0603-Add-toggle-for-always-placing-the-dragon-egg.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add toggle for always placing the dragon egg diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 214b7ab71c4717faa3c949e18f268bef3e066305..70fdd29f0dd6dfac94b2c20090348678a956c333 100644 +index a001f5cd737cf5c76dc14b2b3442238adaa5f79e..2e5321e41ece132f61718816d8f16015cee9aadd 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -714,5 +714,10 @@ public class PaperWorldConfig { +@@ -716,5 +716,10 @@ public class PaperWorldConfig { private void perPlayerMobSpawns() { perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); } diff --git a/patches/server/0610-added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server/0610-added-option-to-disable-pathfinding-updates-on-block.patch index ca55ee348e..89d9ba621a 100644 --- a/patches/server/0610-added-option-to-disable-pathfinding-updates-on-block.patch +++ b/patches/server/0610-added-option-to-disable-pathfinding-updates-on-block.patch @@ -5,10 +5,10 @@ Subject: [PATCH] added option to disable pathfinding updates on block changes diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 70fdd29f0dd6dfac94b2c20090348678a956c333..bc33cf47e6f67179656f9ac0c378408985d9a88e 100644 +index 2e5321e41ece132f61718816d8f16015cee9aadd..9b507c67d12b9117671d31b9b1581764b93233ba 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -719,5 +719,10 @@ public class PaperWorldConfig { +@@ -721,5 +721,10 @@ public class PaperWorldConfig { private void enderDragonsDeathAlwaysPlacesDragonEgg() { enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); } diff --git a/patches/server/0621-MC-29274-Fix-Wither-hostility-towards-players.patch b/patches/server/0621-MC-29274-Fix-Wither-hostility-towards-players.patch index 519adeaa4d..4c7ecd606e 100644 --- a/patches/server/0621-MC-29274-Fix-Wither-hostility-towards-players.patch +++ b/patches/server/0621-MC-29274-Fix-Wither-hostility-towards-players.patch @@ -5,10 +5,10 @@ Subject: [PATCH] MC-29274: Fix Wither hostility towards players diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index bc33cf47e6f67179656f9ac0c378408985d9a88e..f97795330cff2df87c91a0946b80d156d1df9389 100644 +index 9b507c67d12b9117671d31b9b1581764b93233ba..7ef033def7bf5bfc7b9f054e3c4dd9914a0d2146 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -724,5 +724,11 @@ public class PaperWorldConfig { +@@ -726,5 +726,11 @@ public class PaperWorldConfig { private void setUpdatePathfindingOnBlockUpdate() { updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); } diff --git a/patches/server/0631-Allow-using-signs-inside-spawn-protection.patch b/patches/server/0631-Allow-using-signs-inside-spawn-protection.patch index b353cb3548..4473da3be8 100644 --- a/patches/server/0631-Allow-using-signs-inside-spawn-protection.patch +++ b/patches/server/0631-Allow-using-signs-inside-spawn-protection.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow using signs inside spawn protection diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index f97795330cff2df87c91a0946b80d156d1df9389..19a0b2a73ab1d066501148108d6cd9998d281853 100644 +index 7ef033def7bf5bfc7b9f054e3c4dd9914a0d2146..c0e4f56dc0d17322ab1ea8923f9f215e2eaa210f 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -730,5 +730,10 @@ public class PaperWorldConfig { +@@ -732,5 +732,10 @@ public class PaperWorldConfig { fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); log("Withers properly target players: " + fixWitherTargetingBug); } diff --git a/patches/server/0685-Limit-item-frame-cursors-on-maps.patch b/patches/server/0685-Limit-item-frame-cursors-on-maps.patch index 0f1eee2ed7..6c7628bd61 100644 --- a/patches/server/0685-Limit-item-frame-cursors-on-maps.patch +++ b/patches/server/0685-Limit-item-frame-cursors-on-maps.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Limit item frame cursors on maps diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 19a0b2a73ab1d066501148108d6cd9998d281853..0fef75148df251d76a029e86a345adad039fcdd0 100644 +index c0e4f56dc0d17322ab1ea8923f9f215e2eaa210f..1e55e6338a7e41c238170837fa03eeb3d909fa08 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -735,5 +735,10 @@ public class PaperWorldConfig { +@@ -737,5 +737,10 @@ public class PaperWorldConfig { private void allowUsingSignsInsideSpawnProtection() { allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); } diff --git a/patches/server/0690-Add-option-to-fix-items-merging-through-walls.patch b/patches/server/0690-Add-option-to-fix-items-merging-through-walls.patch index b0a39319bf..4570265819 100644 --- a/patches/server/0690-Add-option-to-fix-items-merging-through-walls.patch +++ b/patches/server/0690-Add-option-to-fix-items-merging-through-walls.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to fix items merging through walls diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0fef75148df251d76a029e86a345adad039fcdd0..57929ffa8e992874089ee30d8a96eeb03d754816 100644 +index 1e55e6338a7e41c238170837fa03eeb3d909fa08..7777ff1677a207adfb48f2f227b854cfcade0373 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -740,5 +740,10 @@ public class PaperWorldConfig { +@@ -742,5 +742,10 @@ public class PaperWorldConfig { private void mapItemFrameCursorLimit() { mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); } diff --git a/patches/server/0692-Fix-invulnerable-end-crystals.patch b/patches/server/0692-Fix-invulnerable-end-crystals.patch index 7c436c60d4..09d09ced6e 100644 --- a/patches/server/0692-Fix-invulnerable-end-crystals.patch +++ b/patches/server/0692-Fix-invulnerable-end-crystals.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix invulnerable end crystals MC-108513 diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 57929ffa8e992874089ee30d8a96eeb03d754816..31be320d7d4cf8659d2d4281186b3f0d424a99e1 100644 +index 7777ff1677a207adfb48f2f227b854cfcade0373..43ab68f1822e92973e57a40f63376b467df3bdc7 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -745,5 +745,10 @@ public class PaperWorldConfig { +@@ -747,5 +747,10 @@ public class PaperWorldConfig { private void fixItemsMergingThroughWalls() { fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); } From eab6d9f53323bad608c7597ce9152a18f2e6ff15 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Tue, 15 Jun 2021 16:33:39 +0200 Subject: [PATCH 159/226] Changes to xray patch --- patches/server/0364-Anti-Xray.patch | 66 ++++++++++++++++++----------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/patches/server/0364-Anti-Xray.patch b/patches/server/0364-Anti-Xray.patch index 4fd21d7351..ce0e69fc01 100644 --- a/patches/server/0364-Anti-Xray.patch +++ b/patches/server/0364-Anti-Xray.patch @@ -2,13 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: stonar96 Date: Mon, 20 Aug 2018 03:03:58 +0200 Subject: [PATCH] Anti-Xray -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit -stonar96 — Today at 15:49 -I'm just here to watch you suffer :smile: -You can skip it if you want and I can do it later. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java index e29566cad2647da4d9288e912188b57f00e8dd0c..edb9952ddd014c92b9604a9a187fdcd46de8a04f 100644 @@ -1198,17 +1192,29 @@ index aa198e9f2755734eac591bd3f94679518e9d7270..5c30d06ac80bb9e82d5eecf58b692040 if (iblockdata1 == null) { // CraftBukkit start - remove blockstate if failed (or the same) diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -index c0075d226331f32e470dae5bf1ce8d79e8b263dc..91f5106cfe7914389b52a1ed001117b13e4f9768 100644 +index c0075d226331f32e470dae5bf1ce8d79e8b263dc..a857953f3488e79fd601ac63881bc4d87708afa7 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -@@ -75,6 +75,7 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { +@@ -75,12 +75,18 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { default LevelChunkSection getOrCreateSection(int yIndex) { LevelChunkSection[] levelChunkSections = this.getSections(); if (levelChunkSections[yIndex] == LevelChunk.EMPTY_SECTION) { -+ // Paper - diff on change in ProtoChunk - levelChunkSections[yIndex] = new LevelChunkSection(this.getSectionYFromSectionIndex(yIndex)); +- levelChunkSections[yIndex] = new LevelChunkSection(this.getSectionYFromSectionIndex(yIndex)); ++ levelChunkSections[yIndex] = new LevelChunkSection(this.getSectionYFromSectionIndex(yIndex), this, getServerLevel(), true); } + return levelChunkSections[yIndex]; + } + ++ // Paper start ++ default net.minecraft.server.level.ServerLevel getServerLevel() { ++ return null; ++ } ++ // Paper end ++ + Collection> getHeightmaps(); + + default void setHeightmap(Heightmap.Types type, long[] heightmap) { diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java index 69c2454533e6f21c70792b555ec02c6bc6d169b3..2607c7ba5cf1aca5f3e5c22be2e4e8b3007427d4 100644 --- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java @@ -1223,7 +1229,7 @@ index 69c2454533e6f21c70792b555ec02c6bc6d169b3..2607c7ba5cf1aca5f3e5c22be2e4e8b3 @Override diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 521f199e495f3bec232cc9ca36e51e0392afe737..d4e11b552988f0ef28059f9aa2ca1f1897653171 100644 +index 521f199e495f3bec232cc9ca36e51e0392afe737..164df6e9a91d9fbdbf6e4b835ea1946d81f3be55 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -456,7 +456,7 @@ public class LevelChunk implements ChunkAccess { @@ -1235,6 +1241,18 @@ index 521f199e495f3bec232cc9ca36e51e0392afe737..d4e11b552988f0ef28059f9aa2ca1f18 this.sections[j] = chunksection; } +@@ -1307,4 +1307,11 @@ public class LevelChunk implements ChunkAccess { + return "Level ticker for " + s + "@" + this.getPos(); + } + } ++ ++ // Paper start ++ @Override ++ public net.minecraft.server.level.ServerLevel getServerLevel() { ++ return level; ++ } ++ // Paper end + } diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java index 5fd66020a937b641e2a060cf38df731a43f3bf55..b10beabccf5a29098a796e5615eb4632fae95f99 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java @@ -1401,7 +1419,7 @@ index 5ea60bbb56450502f1ceb41959239ab579458ac2..efe4d45b431890e4821f977b8f9fafda if (this.palette == this.globalPalette) { Palette palette = new HashMapPalette<>(this.registry, i, this.dummyPaletteResize, this.reader, this.writer); diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 245998e2cea32cf15ee2659639c647f449704ec0..cd41b9ee682248a9abde1bf046e54c7e6e485470 100644 +index 245998e2cea32cf15ee2659639c647f449704ec0..d455eafe3810b6d8f3c6cbbfc0df85d3e6c90567 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java @@ -63,7 +63,7 @@ public class ProtoChunk implements ChunkAccess { @@ -1413,22 +1431,20 @@ index 245998e2cea32cf15ee2659639c647f449704ec0..cd41b9ee682248a9abde1bf046e54c7e // Paper start - add level @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) { this(pos, upgradeData, world, null); } -@@ -506,4 +506,15 @@ public class ProtoChunk implements ChunkAccess { - public int getHeight() { - return this.levelHeightAccessor.getHeight(); +@@ -98,6 +98,13 @@ public class ProtoChunk implements ChunkAccess { + this.postProcessing = new ShortList[world.getSectionsCount()]; } -+ + ++ // Paper start + @Override -+ public net.minecraft.world.level.chunk.LevelChunkSection getOrCreateSection(final int yIndex) { -+ LevelChunkSection[] levelChunkSections = this.getSections(); -+ if (levelChunkSections[yIndex] == LevelChunk.EMPTY_SECTION) { -+ // Paper - diff on change in ProtoChunk -+ levelChunkSections[yIndex] = new LevelChunkSection(this.getSectionYFromSectionIndex(yIndex), this, this.level, true); // Paper - Anti-Xray - Add parameters -+ } -+ -+ return levelChunkSections[yIndex]; ++ public net.minecraft.server.level.ServerLevel getServerLevel() { ++ return level; + } - } ++ // Paper end ++ + // Paper start - If loaded util + @Override + public FluidState getFluidIfLoaded(BlockPos blockposition) { diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java index 7c04aef3eac54981ca1e34cb87d97104c3c9685b..097d38f12ef324dbb529a833383e2da949377f9c 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java From 7480cf008a8e36141e5ea26c1b3e864fb3f50219 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Tue, 15 Jun 2021 17:43:00 +0200 Subject: [PATCH 160/226] Port Stop-copy-on-write-operations-for-updating-light-dat --- ...te-operations-for-updating-light-dat.patch | 239 ++++++++---------- ...470-Support-old-UUID-format-for-NBT.patch} | 0 ...p-duplicated-GameProfile-Properties.patch} | 0 ...vert-legacy-attributes-in-Item-Meta.patch} | 0 ...-Priority-Urgency-System-for-Chunks.patch} | 0 ...Remove-some-streams-from-structures.patch} | 0 ...rom-classes-related-villager-gossip.patch} | 0 ...0476-Support-components-in-ItemMeta.patch} | 0 ...rgetLivingEntityEvent-for-1.16-mobs.patch} | 0 ...patch => 0478-Add-entity-liquid-API.patch} | 0 ...date-itemstack-legacy-name-and-lore.patch} | 0 ...wn-player-in-correct-world-on-login.patch} | 0 ...atch => 0481-Add-PrepareResultEvent.patch} | 0 ...low-delegation-to-vanilla-chunk-gen.patch} | 0 ...-for-portal-on-world-gen-entity-add.patch} | 0 ...e-NetworkManager-Exception-Handling.patch} | 0 ...ncement-data-player-iteration-to-be.patch} | 0 ...x-arrows-never-despawning-MC-125757.patch} | 0 ...Vanilla-Command-permission-checking.patch} | 0 ...ve-range-check-for-block-placing-up.patch} | 0 ...-5989.patch => 0489-Fix-SPIGOT-5989.patch} | 0 ...-Bukkit-world-container-is-not-used.patch} | 0 ...5885-Unable-to-disable-advancements.patch} | 0 ...taPlayer-leak-due-from-quitting-ear.patch} | 0 ...eLighting-call-to-World-spigot-stri.patch} | 0 ...ix-some-rails-connecting-improperly.patch} | 0 ...h => 0495-Incremental-player-saving.patch} | 0 ...Fix-MC-187716-Use-configured-height.patch} | 0 ...stake-in-CB-NBT-int-deserialization.patch} | 0 ...rver-load-chunks-from-newer-version.patch} | 0 ...support.patch => 0499-Brand-support.patch} | 0 ...patch => 0500-Add-setMaxPlayers-API.patch} | 0 ...PickupItemAnimation-to-LivingEntity.patch} | 0 ...h => 0502-Don-t-require-FACING-data.patch} | 0 ...eEvent-not-firing-for-all-use-cases.patch} | 0 ...PI.patch => 0504-Add-moon-phase-API.patch} | 0 ...headless-pistons-from-being-created.patch} | 0 ...ent.patch => 0506-Add-BellRingEvent.patch} | 0 ...dd-zombie-targets-turtle-egg-config.patch} | 2 +- ...patch => 0508-Buffer-joins-to-world.patch} | 0 ...=> 0509-Optimize-redstone-algorithm.patch} | 2 +- ...s-not-working-in-some-kick-messages.patch} | 0 ...reateEvent-needs-to-know-its-entity.patch} | 0 ...ch => 0512-Fix-CraftTeam-null-check.patch} | 0 ...I.patch => 0513-Add-more-Evoker-API.patch} | 0 ...translation-keys-for-blocks-entitie.patch} | 0 ...te-HoverEvent-from-ItemStack-Entity.patch} | 0 ...ch => 0516-Cache-block-data-strings.patch} | 0 ...rtation-and-cancel-velocity-if-tele.patch} | 0 ...l-open-container-api-to-HumanEntity.patch} | 0 ...aFixerUpper-Rewrite-Rules-on-demand.patch} | 0 ...-capture-to-capture-all-items-added.patch} | 0 ...ty-in-invalid-locations-SPIGOT-6086.patch} | 0 ...-Counter-to-allow-plugins-to-use-va.patch} | 0 ...track-plugin-scoreboards-by-default.patch} | 0 ...king.patch => 0524-Entity-isTicking.patch} | 0 ...non-whitelisted-player-when-white-l.patch} | 0 ...g-a-passenger-in-CreatureSpawnEvent.patch} | 0 ...eset-Ender-Crystals-on-Dragon-Spawn.patch} | 0 ...-large-move-vectors-crashing-server.patch} | 0 ...atch => 0529-Optimise-getType-calls.patch} | 0 ....patch => 0530-Villager-resetOffers.patch} | 0 ...nig-for-some-hot-IBlockData-methods.patch} | 0 ...ce-order-when-capturing-blockstates.patch} | 2 +- ...lockpos-allocation-from-pathfinding.patch} | 0 ...em-locations-dropped-from-campfires.patch} | 0 ...tch => 0535-Player-elytra-boost-API.patch} | 0 ...36-Fixed-TileEntityBell-memory-leak.patch} | 0 ...ing-up-when-item-stack-is-empty-in-.patch} | 0 ...Add-getOfflinePlayerIfCached-String.patch} | 0 ...ch => 0539-Add-ignore-discounts-API.patch} | 0 ...Toggle-for-removing-existing-dragon.patch} | 2 +- ...x-client-lag-on-advancement-loading.patch} | 0 ...> 0542-Item-no-age-no-player-pickup.patch} | 0 ...er-Remove-Streams-Optimized-collect.patch} | 0 ...544-Beacon-API-custom-effect-ranges.patch} | 0 ...tch => 0545-Add-API-for-quit-reason.patch} | 0 ...h => 0546-Seed-based-feature-search.patch} | 2 +- ...ng-Trader-spawn-rate-config-options.patch} | 2 +- ...rove-performance-of-the-end-generat.patch} | 0 ...ch => 0549-Expose-world-spawn-angle.patch} | 0 ...patch => 0550-Add-Destroy-Speed-API.patch} | 0 ...-spawnParticle-x-y-z-precision-loss.patch} | 0 ...52-Add-LivingEntity-clearActiveItem.patch} | 0 ...=> 0553-Add-PlayerItemCooldownEvent.patch} | 0 ...PI.patch => 0554-More-lightning-API.patch} | 0 ...should-not-bypass-cramming-gamerule.patch} | 2 +- ...-missing-default-perms-for-commands.patch} | 0 ...h => 0557-Add-PlayerShearBlockEvent.patch} | 0 ...rbose-world-setting-to-false-by-def.patch} | 0 ...ng-zombie-villager-discount-exploit.patch} | 2 +- ....patch => 0560-Limit-recipe-packets.patch} | 0 ...-CraftSound-backwards-compatibility.patch} | 0 ... 0562-MC-4-Fix-item-position-desync.patch} | 0 ...563-Player-Chunk-Load-Unload-Events.patch} | 0 ...4-Optimize-Dynamic-get-Missing-Keys.patch} | 0 ...-Expose-LivingEntity-hurt-direction.patch} | 0 ...OBSTRUCTED-reason-to-BedEnterResult.patch} | 0 ...-invalid-ingredient-lists-in-Villag.patch} | 0 ...atch => 0568-added-PlayerTradeEvent.patch} | 0 ...ch => 0569-Implement-TargetHitEvent.patch} | 0 ...570-Additional-Block-Material-API-s.patch} | 0 ...tch => 0571-Fix-harming-potion-dupe.patch} | 0 ...get-Material-from-Boats-and-Minecar.patch} | 0 ....patch => 0573-Cache-burn-durations.patch} | 0 ...ob-spawner-spawn-egg-transformation.patch} | 2 +- ...ment-PlayerFlowerPotManipulateEvent.patch} | 0 ...event-not-being-called-in-adventure.patch} | 0 ...h => 0577-Zombie-API-breaking-doors.patch} | 0 ...578-Fix-nerfed-slime-when-splitting.patch} | 0 ...=> 0579-Add-EntityLoadCrossbowEvent.patch} | 0 ...ch => 0580-Guardian-beam-workaround.patch} | 0 ...0581-Added-WorldGameRuleChangeEvent.patch} | 0 ...-Added-ServerResourcesReloadedEvent.patch} | 0 ...d-settings-for-mobs-picking-up-loot.patch} | 2 +- ...mplemented-BlockFailedDispenseEvent.patch} | 0 ...-Added-PlayerLecternPageChangeEvent.patch} | 0 ...-Added-PlayerLoomPatternSelectEvent.patch} | 0 ...nfigurable-door-breaking-difficulty.patch} | 2 +- ...ty-commands-shall-not-be-dispatched.patch} | 0 ...I-to-expose-exact-interaction-point.patch} | 0 ...OIs.patch => 0590-Remove-stale-POIs.patch} | 0 ...h => 0591-Fix-villager-boat-exploit.patch} | 0 ...I.patch => 0592-Add-sendOpLevel-API.patch} | 0 ...ch => 0593-Add-StructureLocateEvent.patch} | 0 ...-for-requiring-a-player-participant.patch} | 2 +- ...leHitEvent-call-when-fireballs-dead.patch} | 0 ...nent-with-empty-text-instead-of-thr.patch} | 0 ...597-Make-schedule-command-per-world.patch} | 0 ...598-Configurable-max-leash-distance.patch} | 2 +- ...599-Implement-BlockPreDispenseEvent.patch} | 0 ...h => 0600-Added-Vanilla-Entity-Tags.patch} | 0 ...-API.patch => 0601-added-Wither-API.patch} | 0 ...ng-of-PlayerChangeBeaconEffectEvent.patch} | 0 ...-spam-when-removing-chests-in-water.patch} | 0 ...e-for-always-placing-the-dragon-egg.patch} | 0 ...-PlayerStonecutterRecipeSelectEvent.patch} | 0 ...eash-variable-to-EntityUnleashEvent.patch} | 0 ...e-map-update-when-spawning-disabled.patch} | 0 ...shield-blocking-on-dimension-change.patch} | 0 ...atch => 0609-add-DragonEggFormEvent.patch} | 0 ...Event.patch => 0610-EntityMoveEvent.patch} | 0 ...isable-pathfinding-updates-on-block.patch} | 0 ... 0612-Inline-shift-direction-fields.patch} | 0 ...-adding-items-to-BlockDropItemEvent.patch} | 0 ...inThreadExecutor-to-BukkitScheduler.patch} | 0 ...entity-allow-attribute-registration.patch} | 0 ...ix-dead-slime-setSize-invincibility.patch} | 0 ...pes-should-return-an-immutable-list.patch} | 0 ....patch => 0618-misc-debugging-dumps.patch} | 0 ...port-for-hex-color-codes-in-console.patch} | 0 ...atch => 0620-Expose-Tracked-Players.patch} | 0 ...1-Remove-streams-from-SensorNearest.patch} | 0 ...ix-Wither-hostility-towards-players.patch} | 0 ...er-exception-on-empty-JsonList-file.patch} | 0 ...GUI.patch => 0624-Improve-ServerGUI.patch} | 0 ...ure-plate-EntityInteractEvent-for-i.patch} | 0 ...626-fix-converting-txt-to-json-file.patch} | 0 ...atch => 0627-Add-worldborder-events.patch} | 0 ...=> 0628-added-PlayerNameEntityEvent.patch} | 0 ...grindstones-from-overstacking-items.patch} | 0 ...h => 0630-Add-recipe-to-cook-events.patch} | 0 ...patch => 0631-Add-Block-isValidTool.patch} | 0 ...using-signs-inside-spawn-protection.patch} | 0 ...ch => 0633-Implement-Keyed-on-World.patch} | 0 ...ternative-constructor-for-Rotations.patch} | 0 ...y-API.patch => 0635-Item-Rarity-API.patch} | 0 ...imer-for-Wandering-Traders-spawned-.patch} | 0 ...py-TESign-isEditable-from-snapshots.patch} | 0 ...d-item-when-player-has-disconnected.patch} | 0 ...elist-use-configurable-kick-message.patch} | 0 ...gnore-result-of-PlayerEditBookEvent.patch} | 0 ...block-falling-causing-client-desync.patch} | 0 ...tch => 0642-Expose-protocol-version.patch} | 0 ...nt-suggestion-tooltips-in-AsyncTabC.patch} | 0 ...ab-completions-for-brigadier-comman.patch} | 0 ...temConsumeEvent-cancelling-properly.patch} | 0 ...patch => 0646-Add-bypass-host-check.patch} | 0 ...0647-Set-area-affect-cloud-rotation.patch} | 0 ...add-isDeeplySleeping-to-HumanEntity.patch} | 0 ...ting-give-items-on-item-drop-cancel.patch} | 0 ...add-consumeFuel-to-FurnaceBurnEvent.patch} | 0 ...-set-drop-chance-to-EntityEquipment.patch} | 0 ...ix-PigZombieAngerEvent-cancellation.patch} | 0 ...-checkReach-check-for-Shulker-boxes.patch} | 0 ...ix-PlayerItemHeldEvent-firing-twice.patch} | 0 ... => 0655-Added-PlayerDeepSleepEvent.patch} | 0 ...ld-API.patch => 0656-More-World-API.patch} | 0 ... 0657-Added-PlayerBedFailEnterEvent.patch} | 0 ...-to-convert-between-Component-and-B.patch} | 0 ...n-acting-as-a-bed-respawn-from-the-.patch} | 0 ...acon-activation-deactivation-events.patch} | 0 ...-RespawnFlags-to-PlayerRespawnEvent.patch} | 0 ...dd-Channel-initialization-listeners.patch} | 0 ...mands-if-tab-completion-is-disabled.patch} | 0 ...> 0664-Add-more-WanderingTrader-API.patch} | 0 ...dd-EntityBlockStorage-clearEntities.patch} | 0 ...ssage-to-PlayerAdvancementDoneEvent.patch} | 0 ...address-to-AsyncPlayerPreLoginEvent.patch} | 0 ...close.patch => 0668-Inventory-close.patch} | 0 ...reateEvent-players-and-end-platform.patch} | 0 ...-in-sunlight-API-for-Phantoms-and-S.patch} | 0 ...=> 0671-Fix-CraftPotionBrewer-cache.patch} | 0 ...atch => 0672-Add-basic-Datapack-API.patch} | 0 ...ment-variable-to-disable-server-gui.patch} | 0 ...itions-to-PlayerGameModeChangeEvent.patch} | 0 ... => 0675-ItemStack-repair-check-API.patch} | 0 ....patch => 0676-More-Enchantment-API.patch} | 0 ...option-to-load-extra-plugin-jars-no.patch} | 0 ...-and-optimise-world-force-upgrading.patch} | 2 +- ...PI.patch => 0679-Add-Mob-lookAt-API.patch} | 0 ...0680-Add-Unix-domain-socket-support.patch} | 0 ... => 0681-Add-EntityInsideBlockEvent.patch} | 0 ...82-Attributes-API-for-item-defaults.patch} | 0 ...hantCustom-emit-PlayerPurchaseEvent.patch} | 0 ...ause-to-Weather-ThunderChangeEvents.patch} | 0 ...patch => 0685-More-Lidded-Block-API.patch} | 0 ...86-Limit-item-frame-cursors-on-maps.patch} | 0 ...0687-Add-PufferFishStateChangeEvent.patch} | 0 ... => 0688-Add-PlayerKickEvent-causes.patch} | 0 ...erBucketEmptyEvent-result-itemstack.patch} | 0 ...tedContainer-instead-of-ReentrantLo.patch} | 0 ...-to-fix-items-merging-through-walls.patch} | 0 ...h => 0692-Add-BellRevealRaiderEvent.patch} | 0 ... 0693-Fix-invulnerable-end-crystals.patch} | 0 ...94-Add-ElderGuardianAppearanceEvent.patch} | 0 ...inventory-on-cancelled-pickup-event.patch} | 0 ...0696-Fix-dangerous-end-portal-logic.patch} | 0 ...-Biome-Mob-Lookups-for-Mob-Spawning.patch} | 0 ...-Make-item-validations-configurable.patch} | 0 ...0699-Add-more-line-of-sight-methods.patch} | 0 ... => 0700-add-per-world-spawn-limits.patch} | 2 +- ...plashEvent-for-water-splash-potions.patch} | 0 ...tus-dataconverter-for-pre-1.13-chun.patch} | 0 234 files changed, 122 insertions(+), 147 deletions(-) rename patches/{removed/1.17 => server}/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch (52%) rename patches/server/{0469-Support-old-UUID-format-for-NBT.patch => 0470-Support-old-UUID-format-for-NBT.patch} (100%) rename patches/server/{0470-Clean-up-duplicated-GameProfile-Properties.patch => 0471-Clean-up-duplicated-GameProfile-Properties.patch} (100%) rename patches/server/{0471-Convert-legacy-attributes-in-Item-Meta.patch => 0472-Convert-legacy-attributes-in-Item-Meta.patch} (100%) rename patches/server/{0472-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch => 0473-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch} (100%) rename patches/server/{0473-Remove-some-streams-from-structures.patch => 0474-Remove-some-streams-from-structures.patch} (100%) rename patches/server/{0474-Remove-streams-from-classes-related-villager-gossip.patch => 0475-Remove-streams-from-classes-related-villager-gossip.patch} (100%) rename patches/server/{0475-Support-components-in-ItemMeta.patch => 0476-Support-components-in-ItemMeta.patch} (100%) rename patches/server/{0476-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch => 0477-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch} (100%) rename patches/server/{0477-Add-entity-liquid-API.patch => 0478-Add-entity-liquid-API.patch} (100%) rename patches/server/{0478-Update-itemstack-legacy-name-and-lore.patch => 0479-Update-itemstack-legacy-name-and-lore.patch} (100%) rename patches/server/{0479-Spawn-player-in-correct-world-on-login.patch => 0480-Spawn-player-in-correct-world-on-login.patch} (100%) rename patches/server/{0480-Add-PrepareResultEvent.patch => 0481-Add-PrepareResultEvent.patch} (100%) rename patches/server/{0481-Allow-delegation-to-vanilla-chunk-gen.patch => 0482-Allow-delegation-to-vanilla-chunk-gen.patch} (100%) rename patches/server/{0482-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch => 0483-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch} (100%) rename patches/server/{0483-Optimize-NetworkManager-Exception-Handling.patch => 0484-Optimize-NetworkManager-Exception-Handling.patch} (100%) rename patches/server/{0484-Optimize-the-advancement-data-player-iteration-to-be.patch => 0485-Optimize-the-advancement-data-player-iteration-to-be.patch} (100%) rename patches/server/{0485-Fix-arrows-never-despawning-MC-125757.patch => 0486-Fix-arrows-never-despawning-MC-125757.patch} (100%) rename patches/server/{0486-Thread-Safe-Vanilla-Command-permission-checking.patch => 0487-Thread-Safe-Vanilla-Command-permission-checking.patch} (100%) rename patches/server/{0487-Move-range-check-for-block-placing-up.patch => 0488-Move-range-check-for-block-placing-up.patch} (100%) rename patches/server/{0488-Fix-SPIGOT-5989.patch => 0489-Fix-SPIGOT-5989.patch} (100%) rename patches/server/{0489-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch => 0490-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch} (100%) rename patches/server/{0490-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch => 0491-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch} (100%) rename patches/server/{0491-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch => 0492-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch} (100%) rename patches/server/{0492-Add-missing-strikeLighting-call-to-World-spigot-stri.patch => 0493-Add-missing-strikeLighting-call-to-World-spigot-stri.patch} (100%) rename patches/server/{0493-Fix-some-rails-connecting-improperly.patch => 0494-Fix-some-rails-connecting-improperly.patch} (100%) rename patches/server/{0494-Incremental-player-saving.patch => 0495-Incremental-player-saving.patch} (100%) rename patches/server/{0495-Fix-MC-187716-Use-configured-height.patch => 0496-Fix-MC-187716-Use-configured-height.patch} (100%) rename patches/server/{0496-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch => 0497-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch} (100%) rename patches/server/{0497-Do-not-let-the-server-load-chunks-from-newer-version.patch => 0498-Do-not-let-the-server-load-chunks-from-newer-version.patch} (100%) rename patches/server/{0498-Brand-support.patch => 0499-Brand-support.patch} (100%) rename patches/server/{0499-Add-setMaxPlayers-API.patch => 0500-Add-setMaxPlayers-API.patch} (100%) rename patches/server/{0500-Add-playPickupItemAnimation-to-LivingEntity.patch => 0501-Add-playPickupItemAnimation-to-LivingEntity.patch} (100%) rename patches/server/{0501-Don-t-require-FACING-data.patch => 0502-Don-t-require-FACING-data.patch} (100%) rename patches/server/{0502-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch => 0503-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch} (100%) rename patches/server/{0503-Add-moon-phase-API.patch => 0504-Add-moon-phase-API.patch} (100%) rename patches/server/{0504-Prevent-headless-pistons-from-being-created.patch => 0505-Prevent-headless-pistons-from-being-created.patch} (100%) rename patches/server/{0505-Add-BellRingEvent.patch => 0506-Add-BellRingEvent.patch} (100%) rename patches/server/{0506-Add-zombie-targets-turtle-egg-config.patch => 0507-Add-zombie-targets-turtle-egg-config.patch} (95%) rename patches/server/{0507-Buffer-joins-to-world.patch => 0508-Buffer-joins-to-world.patch} (100%) rename patches/server/{0508-Optimize-redstone-algorithm.patch => 0509-Optimize-redstone-algorithm.patch} (99%) rename patches/server/{0509-Fix-hex-colors-not-working-in-some-kick-messages.patch => 0510-Fix-hex-colors-not-working-in-some-kick-messages.patch} (100%) rename patches/server/{0510-PortalCreateEvent-needs-to-know-its-entity.patch => 0511-PortalCreateEvent-needs-to-know-its-entity.patch} (100%) rename patches/server/{0511-Fix-CraftTeam-null-check.patch => 0512-Fix-CraftTeam-null-check.patch} (100%) rename patches/server/{0512-Add-more-Evoker-API.patch => 0513-Add-more-Evoker-API.patch} (100%) rename patches/server/{0513-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch => 0514-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch} (100%) rename patches/server/{0514-Create-HoverEvent-from-ItemStack-Entity.patch => 0515-Create-HoverEvent-from-ItemStack-Entity.patch} (100%) rename patches/server/{0515-Cache-block-data-strings.patch => 0516-Cache-block-data-strings.patch} (100%) rename patches/server/{0516-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch => 0517-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch} (100%) rename patches/server/{0517-Add-additional-open-container-api-to-HumanEntity.patch => 0518-Add-additional-open-container-api-to-HumanEntity.patch} (100%) rename patches/server/{0518-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch => 0519-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch} (100%) rename patches/server/{0519-Extend-block-drop-capture-to-capture-all-items-added.patch => 0520-Extend-block-drop-capture-to-capture-all-items-added.patch} (100%) rename patches/server/{0520-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch => 0521-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch} (100%) rename patches/server/{0521-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch => 0522-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch} (100%) rename patches/server/{0522-Lazily-track-plugin-scoreboards-by-default.patch => 0523-Lazily-track-plugin-scoreboards-by-default.patch} (100%) rename patches/server/{0523-Entity-isTicking.patch => 0524-Entity-isTicking.patch} (100%) rename patches/server/{0524-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch => 0525-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch} (100%) rename patches/server/{0525-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch => 0526-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch} (100%) rename patches/server/{0526-Reset-Ender-Crystals-on-Dragon-Spawn.patch => 0527-Reset-Ender-Crystals-on-Dragon-Spawn.patch} (100%) rename patches/server/{0527-Fix-for-large-move-vectors-crashing-server.patch => 0528-Fix-for-large-move-vectors-crashing-server.patch} (100%) rename patches/server/{0528-Optimise-getType-calls.patch => 0529-Optimise-getType-calls.patch} (100%) rename patches/server/{0529-Villager-resetOffers.patch => 0530-Villager-resetOffers.patch} (100%) rename patches/server/{0530-Improve-inlinig-for-some-hot-IBlockData-methods.patch => 0531-Improve-inlinig-for-some-hot-IBlockData-methods.patch} (100%) rename patches/server/{0531-Retain-block-place-order-when-capturing-blockstates.patch => 0532-Retain-block-place-order-when-capturing-blockstates.patch} (93%) rename patches/server/{0532-Reduce-blockpos-allocation-from-pathfinding.patch => 0533-Reduce-blockpos-allocation-from-pathfinding.patch} (100%) rename patches/server/{0533-Fix-item-locations-dropped-from-campfires.patch => 0534-Fix-item-locations-dropped-from-campfires.patch} (100%) rename patches/server/{0534-Player-elytra-boost-API.patch => 0535-Player-elytra-boost-API.patch} (100%) rename patches/server/{0535-Fixed-TileEntityBell-memory-leak.patch => 0536-Fixed-TileEntityBell-memory-leak.patch} (100%) rename patches/server/{0536-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch => 0537-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch} (100%) rename patches/server/{0537-Add-getOfflinePlayerIfCached-String.patch => 0538-Add-getOfflinePlayerIfCached-String.patch} (100%) rename patches/server/{0538-Add-ignore-discounts-API.patch => 0539-Add-ignore-discounts-API.patch} (100%) rename patches/server/{0539-Toggle-for-removing-existing-dragon.patch => 0540-Toggle-for-removing-existing-dragon.patch} (95%) rename patches/server/{0540-Fix-client-lag-on-advancement-loading.patch => 0541-Fix-client-lag-on-advancement-loading.patch} (100%) rename patches/server/{0541-Item-no-age-no-player-pickup.patch => 0542-Item-no-age-no-player-pickup.patch} (100%) rename patches/server/{0542-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch => 0543-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch} (100%) rename patches/server/{0543-Beacon-API-custom-effect-ranges.patch => 0544-Beacon-API-custom-effect-ranges.patch} (100%) rename patches/server/{0544-Add-API-for-quit-reason.patch => 0545-Add-API-for-quit-reason.patch} (100%) rename patches/server/{0545-Seed-based-feature-search.patch => 0546-Seed-based-feature-search.patch} (98%) rename patches/server/{0546-Add-Wandering-Trader-spawn-rate-config-options.patch => 0547-Add-Wandering-Trader-spawn-rate-config-options.patch} (98%) rename patches/server/{0547-Significantly-improve-performance-of-the-end-generat.patch => 0548-Significantly-improve-performance-of-the-end-generat.patch} (100%) rename patches/server/{0548-Expose-world-spawn-angle.patch => 0549-Expose-world-spawn-angle.patch} (100%) rename patches/server/{0549-Add-Destroy-Speed-API.patch => 0550-Add-Destroy-Speed-API.patch} (100%) rename patches/server/{0550-Fix-Player-spawnParticle-x-y-z-precision-loss.patch => 0551-Fix-Player-spawnParticle-x-y-z-precision-loss.patch} (100%) rename patches/server/{0551-Add-LivingEntity-clearActiveItem.patch => 0552-Add-LivingEntity-clearActiveItem.patch} (100%) rename patches/server/{0552-Add-PlayerItemCooldownEvent.patch => 0553-Add-PlayerItemCooldownEvent.patch} (100%) rename patches/server/{0553-More-lightning-API.patch => 0554-More-lightning-API.patch} (100%) rename patches/server/{0554-Climbing-should-not-bypass-cramming-gamerule.patch => 0555-Climbing-should-not-bypass-cramming-gamerule.patch} (98%) rename patches/server/{0555-Added-missing-default-perms-for-commands.patch => 0556-Added-missing-default-perms-for-commands.patch} (100%) rename patches/server/{0556-Add-PlayerShearBlockEvent.patch => 0557-Add-PlayerShearBlockEvent.patch} (100%) rename patches/server/{0557-Set-spigots-verbose-world-setting-to-false-by-def.patch => 0558-Set-spigots-verbose-world-setting-to-false-by-def.patch} (100%) rename patches/server/{0558-Fix-curing-zombie-villager-discount-exploit.patch => 0559-Fix-curing-zombie-villager-discount-exploit.patch} (96%) rename patches/server/{0559-Limit-recipe-packets.patch => 0560-Limit-recipe-packets.patch} (100%) rename patches/server/{0560-Fix-CraftSound-backwards-compatibility.patch => 0561-Fix-CraftSound-backwards-compatibility.patch} (100%) rename patches/server/{0561-MC-4-Fix-item-position-desync.patch => 0562-MC-4-Fix-item-position-desync.patch} (100%) rename patches/server/{0562-Player-Chunk-Load-Unload-Events.patch => 0563-Player-Chunk-Load-Unload-Events.patch} (100%) rename patches/server/{0563-Optimize-Dynamic-get-Missing-Keys.patch => 0564-Optimize-Dynamic-get-Missing-Keys.patch} (100%) rename patches/server/{0564-Expose-LivingEntity-hurt-direction.patch => 0565-Expose-LivingEntity-hurt-direction.patch} (100%) rename patches/server/{0565-Add-OBSTRUCTED-reason-to-BedEnterResult.patch => 0566-Add-OBSTRUCTED-reason-to-BedEnterResult.patch} (100%) rename patches/server/{0566-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch => 0567-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch} (100%) rename patches/server/{0567-added-PlayerTradeEvent.patch => 0568-added-PlayerTradeEvent.patch} (100%) rename patches/server/{0568-Implement-TargetHitEvent.patch => 0569-Implement-TargetHitEvent.patch} (100%) rename patches/server/{0569-Additional-Block-Material-API-s.patch => 0570-Additional-Block-Material-API-s.patch} (100%) rename patches/server/{0570-Fix-harming-potion-dupe.patch => 0571-Fix-harming-potion-dupe.patch} (100%) rename patches/server/{0571-Implement-API-to-get-Material-from-Boats-and-Minecar.patch => 0572-Implement-API-to-get-Material-from-Boats-and-Minecar.patch} (100%) rename patches/server/{0572-Cache-burn-durations.patch => 0573-Cache-burn-durations.patch} (100%) rename patches/server/{0573-Allow-disabling-mob-spawner-spawn-egg-transformation.patch => 0574-Allow-disabling-mob-spawner-spawn-egg-transformation.patch} (95%) rename patches/server/{0574-Implement-PlayerFlowerPotManipulateEvent.patch => 0575-Implement-PlayerFlowerPotManipulateEvent.patch} (100%) rename patches/server/{0575-Fix-interact-event-not-being-called-in-adventure.patch => 0576-Fix-interact-event-not-being-called-in-adventure.patch} (100%) rename patches/server/{0576-Zombie-API-breaking-doors.patch => 0577-Zombie-API-breaking-doors.patch} (100%) rename patches/server/{0577-Fix-nerfed-slime-when-splitting.patch => 0578-Fix-nerfed-slime-when-splitting.patch} (100%) rename patches/server/{0578-Add-EntityLoadCrossbowEvent.patch => 0579-Add-EntityLoadCrossbowEvent.patch} (100%) rename patches/server/{0579-Guardian-beam-workaround.patch => 0580-Guardian-beam-workaround.patch} (100%) rename patches/server/{0580-Added-WorldGameRuleChangeEvent.patch => 0581-Added-WorldGameRuleChangeEvent.patch} (100%) rename patches/server/{0581-Added-ServerResourcesReloadedEvent.patch => 0582-Added-ServerResourcesReloadedEvent.patch} (100%) rename patches/server/{0582-Added-world-settings-for-mobs-picking-up-loot.patch => 0583-Added-world-settings-for-mobs-picking-up-loot.patch} (97%) rename patches/server/{0583-Implemented-BlockFailedDispenseEvent.patch => 0584-Implemented-BlockFailedDispenseEvent.patch} (100%) rename patches/server/{0584-Added-PlayerLecternPageChangeEvent.patch => 0585-Added-PlayerLecternPageChangeEvent.patch} (100%) rename patches/server/{0585-Added-PlayerLoomPatternSelectEvent.patch => 0586-Added-PlayerLoomPatternSelectEvent.patch} (100%) rename patches/server/{0586-Configurable-door-breaking-difficulty.patch => 0587-Configurable-door-breaking-difficulty.patch} (98%) rename patches/server/{0587-Empty-commands-shall-not-be-dispatched.patch => 0588-Empty-commands-shall-not-be-dispatched.patch} (100%) rename patches/server/{0588-Implement-API-to-expose-exact-interaction-point.patch => 0589-Implement-API-to-expose-exact-interaction-point.patch} (100%) rename patches/server/{0589-Remove-stale-POIs.patch => 0590-Remove-stale-POIs.patch} (100%) rename patches/server/{0590-Fix-villager-boat-exploit.patch => 0591-Fix-villager-boat-exploit.patch} (100%) rename patches/server/{0591-Add-sendOpLevel-API.patch => 0592-Add-sendOpLevel-API.patch} (100%) rename patches/server/{0592-Add-StructureLocateEvent.patch => 0593-Add-StructureLocateEvent.patch} (100%) rename patches/server/{0593-Collision-option-for-requiring-a-player-participant.patch => 0594-Collision-option-for-requiring-a-player-participant.patch} (98%) rename patches/server/{0594-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch => 0595-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch} (100%) rename patches/server/{0595-Return-chat-component-with-empty-text-instead-of-thr.patch => 0596-Return-chat-component-with-empty-text-instead-of-thr.patch} (100%) rename patches/server/{0596-Make-schedule-command-per-world.patch => 0597-Make-schedule-command-per-world.patch} (100%) rename patches/server/{0597-Configurable-max-leash-distance.patch => 0598-Configurable-max-leash-distance.patch} (96%) rename patches/server/{0598-Implement-BlockPreDispenseEvent.patch => 0599-Implement-BlockPreDispenseEvent.patch} (100%) rename patches/server/{0599-Added-Vanilla-Entity-Tags.patch => 0600-Added-Vanilla-Entity-Tags.patch} (100%) rename patches/server/{0600-added-Wither-API.patch => 0601-added-Wither-API.patch} (100%) rename patches/server/{0601-Added-firing-of-PlayerChangeBeaconEffectEvent.patch => 0602-Added-firing-of-PlayerChangeBeaconEffectEvent.patch} (100%) rename patches/server/{0602-Fix-console-spam-when-removing-chests-in-water.patch => 0603-Fix-console-spam-when-removing-chests-in-water.patch} (100%) rename patches/server/{0603-Add-toggle-for-always-placing-the-dragon-egg.patch => 0604-Add-toggle-for-always-placing-the-dragon-egg.patch} (100%) rename patches/server/{0604-Added-PlayerStonecutterRecipeSelectEvent.patch => 0605-Added-PlayerStonecutterRecipeSelectEvent.patch} (100%) rename patches/server/{0605-Add-dropLeash-variable-to-EntityUnleashEvent.patch => 0606-Add-dropLeash-variable-to-EntityUnleashEvent.patch} (100%) rename patches/server/{0606-Skip-distance-map-update-when-spawning-disabled.patch => 0607-Skip-distance-map-update-when-spawning-disabled.patch} (100%) rename patches/server/{0607-Reset-shield-blocking-on-dimension-change.patch => 0608-Reset-shield-blocking-on-dimension-change.patch} (100%) rename patches/server/{0608-add-DragonEggFormEvent.patch => 0609-add-DragonEggFormEvent.patch} (100%) rename patches/server/{0609-EntityMoveEvent.patch => 0610-EntityMoveEvent.patch} (100%) rename patches/server/{0610-added-option-to-disable-pathfinding-updates-on-block.patch => 0611-added-option-to-disable-pathfinding-updates-on-block.patch} (100%) rename patches/server/{0611-Inline-shift-direction-fields.patch => 0612-Inline-shift-direction-fields.patch} (100%) rename patches/server/{0612-Allow-adding-items-to-BlockDropItemEvent.patch => 0613-Allow-adding-items-to-BlockDropItemEvent.patch} (100%) rename patches/server/{0613-Add-getMainThreadExecutor-to-BukkitScheduler.patch => 0614-Add-getMainThreadExecutor-to-BukkitScheduler.patch} (100%) rename patches/server/{0614-living-entity-allow-attribute-registration.patch => 0615-living-entity-allow-attribute-registration.patch} (100%) rename patches/server/{0615-fix-dead-slime-setSize-invincibility.patch => 0616-fix-dead-slime-setSize-invincibility.patch} (100%) rename patches/server/{0616-Merchant-getRecipes-should-return-an-immutable-list.patch => 0617-Merchant-getRecipes-should-return-an-immutable-list.patch} (100%) rename patches/server/{0617-misc-debugging-dumps.patch => 0618-misc-debugging-dumps.patch} (100%) rename patches/server/{0618-Add-support-for-hex-color-codes-in-console.patch => 0619-Add-support-for-hex-color-codes-in-console.patch} (100%) rename patches/server/{0619-Expose-Tracked-Players.patch => 0620-Expose-Tracked-Players.patch} (100%) rename patches/server/{0620-Remove-streams-from-SensorNearest.patch => 0621-Remove-streams-from-SensorNearest.patch} (100%) rename patches/server/{0621-MC-29274-Fix-Wither-hostility-towards-players.patch => 0622-MC-29274-Fix-Wither-hostility-towards-players.patch} (100%) rename patches/server/{0622-Throw-proper-exception-on-empty-JsonList-file.patch => 0623-Throw-proper-exception-on-empty-JsonList-file.patch} (100%) rename patches/server/{0623-Improve-ServerGUI.patch => 0624-Improve-ServerGUI.patch} (100%) rename patches/server/{0624-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch => 0625-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch} (100%) rename patches/server/{0625-fix-converting-txt-to-json-file.patch => 0626-fix-converting-txt-to-json-file.patch} (100%) rename patches/server/{0626-Add-worldborder-events.patch => 0627-Add-worldborder-events.patch} (100%) rename patches/server/{0627-added-PlayerNameEntityEvent.patch => 0628-added-PlayerNameEntityEvent.patch} (100%) rename patches/server/{0628-Prevent-grindstones-from-overstacking-items.patch => 0629-Prevent-grindstones-from-overstacking-items.patch} (100%) rename patches/server/{0629-Add-recipe-to-cook-events.patch => 0630-Add-recipe-to-cook-events.patch} (100%) rename patches/server/{0630-Add-Block-isValidTool.patch => 0631-Add-Block-isValidTool.patch} (100%) rename patches/server/{0631-Allow-using-signs-inside-spawn-protection.patch => 0632-Allow-using-signs-inside-spawn-protection.patch} (100%) rename patches/server/{0632-Implement-Keyed-on-World.patch => 0633-Implement-Keyed-on-World.patch} (100%) rename patches/server/{0633-Add-fast-alternative-constructor-for-Rotations.patch => 0634-Add-fast-alternative-constructor-for-Rotations.patch} (100%) rename patches/server/{0634-Item-Rarity-API.patch => 0635-Item-Rarity-API.patch} (100%) rename patches/server/{0635-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch => 0636-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch} (100%) rename patches/server/{0636-copy-TESign-isEditable-from-snapshots.patch => 0637-copy-TESign-isEditable-from-snapshots.patch} (100%) rename patches/server/{0637-Drop-carried-item-when-player-has-disconnected.patch => 0638-Drop-carried-item-when-player-has-disconnected.patch} (100%) rename patches/server/{0638-forced-whitelist-use-configurable-kick-message.patch => 0639-forced-whitelist-use-configurable-kick-message.patch} (100%) rename patches/server/{0639-Don-t-ignore-result-of-PlayerEditBookEvent.patch => 0640-Don-t-ignore-result-of-PlayerEditBookEvent.patch} (100%) rename patches/server/{0640-fix-cancelling-block-falling-causing-client-desync.patch => 0641-fix-cancelling-block-falling-causing-client-desync.patch} (100%) rename patches/server/{0641-Expose-protocol-version.patch => 0642-Expose-protocol-version.patch} (100%) rename patches/server/{0642-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch => 0643-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch} (100%) rename patches/server/{0643-Enhance-console-tab-completions-for-brigadier-comman.patch => 0644-Enhance-console-tab-completions-for-brigadier-comman.patch} (100%) rename patches/server/{0644-Fix-PlayerItemConsumeEvent-cancelling-properly.patch => 0645-Fix-PlayerItemConsumeEvent-cancelling-properly.patch} (100%) rename patches/server/{0645-Add-bypass-host-check.patch => 0646-Add-bypass-host-check.patch} (100%) rename patches/server/{0646-Set-area-affect-cloud-rotation.patch => 0647-Set-area-affect-cloud-rotation.patch} (100%) rename patches/server/{0647-add-isDeeplySleeping-to-HumanEntity.patch => 0648-add-isDeeplySleeping-to-HumanEntity.patch} (100%) rename patches/server/{0648-Fix-duplicating-give-items-on-item-drop-cancel.patch => 0649-Fix-duplicating-give-items-on-item-drop-cancel.patch} (100%) rename patches/server/{0649-add-consumeFuel-to-FurnaceBurnEvent.patch => 0650-add-consumeFuel-to-FurnaceBurnEvent.patch} (100%) rename patches/server/{0650-add-get-set-drop-chance-to-EntityEquipment.patch => 0651-add-get-set-drop-chance-to-EntityEquipment.patch} (100%) rename patches/server/{0651-fix-PigZombieAngerEvent-cancellation.patch => 0652-fix-PigZombieAngerEvent-cancellation.patch} (100%) rename patches/server/{0652-Fix-checkReach-check-for-Shulker-boxes.patch => 0653-Fix-checkReach-check-for-Shulker-boxes.patch} (100%) rename patches/server/{0653-fix-PlayerItemHeldEvent-firing-twice.patch => 0654-fix-PlayerItemHeldEvent-firing-twice.patch} (100%) rename patches/server/{0654-Added-PlayerDeepSleepEvent.patch => 0655-Added-PlayerDeepSleepEvent.patch} (100%) rename patches/server/{0655-More-World-API.patch => 0656-More-World-API.patch} (100%) rename patches/server/{0656-Added-PlayerBedFailEnterEvent.patch => 0657-Added-PlayerBedFailEnterEvent.patch} (100%) rename patches/server/{0657-Implement-methods-to-convert-between-Component-and-B.patch => 0658-Implement-methods-to-convert-between-Component-and-B.patch} (100%) rename patches/server/{0658-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch => 0659-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch} (100%) rename patches/server/{0659-Introduce-beacon-activation-deactivation-events.patch => 0660-Introduce-beacon-activation-deactivation-events.patch} (100%) rename patches/server/{0660-add-RespawnFlags-to-PlayerRespawnEvent.patch => 0661-add-RespawnFlags-to-PlayerRespawnEvent.patch} (100%) rename patches/server/{0661-Add-Channel-initialization-listeners.patch => 0662-Add-Channel-initialization-listeners.patch} (100%) rename patches/server/{0662-Send-empty-commands-if-tab-completion-is-disabled.patch => 0663-Send-empty-commands-if-tab-completion-is-disabled.patch} (100%) rename patches/server/{0663-Add-more-WanderingTrader-API.patch => 0664-Add-more-WanderingTrader-API.patch} (100%) rename patches/server/{0664-Add-EntityBlockStorage-clearEntities.patch => 0665-Add-EntityBlockStorage-clearEntities.patch} (100%) rename patches/server/{0665-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch => 0666-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch} (100%) rename patches/server/{0666-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch => 0667-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch} (100%) rename patches/server/{0667-Inventory-close.patch => 0668-Inventory-close.patch} (100%) rename patches/server/{0668-call-PortalCreateEvent-players-and-end-platform.patch => 0669-call-PortalCreateEvent-players-and-end-platform.patch} (100%) rename patches/server/{0669-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch => 0670-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch} (100%) rename patches/server/{0670-Fix-CraftPotionBrewer-cache.patch => 0671-Fix-CraftPotionBrewer-cache.patch} (100%) rename patches/server/{0671-Add-basic-Datapack-API.patch => 0672-Add-basic-Datapack-API.patch} (100%) rename patches/server/{0672-Add-environment-variable-to-disable-server-gui.patch => 0673-Add-environment-variable-to-disable-server-gui.patch} (100%) rename patches/server/{0673-additions-to-PlayerGameModeChangeEvent.patch => 0674-additions-to-PlayerGameModeChangeEvent.patch} (100%) rename patches/server/{0674-ItemStack-repair-check-API.patch => 0675-ItemStack-repair-check-API.patch} (100%) rename patches/server/{0675-More-Enchantment-API.patch => 0676-More-Enchantment-API.patch} (100%) rename patches/server/{0676-Add-command-line-option-to-load-extra-plugin-jars-no.patch => 0677-Add-command-line-option-to-load-extra-plugin-jars-no.patch} (100%) rename patches/server/{0677-Fix-and-optimise-world-force-upgrading.patch => 0678-Fix-and-optimise-world-force-upgrading.patch} (99%) rename patches/server/{0678-Add-Mob-lookAt-API.patch => 0679-Add-Mob-lookAt-API.patch} (100%) rename patches/server/{0679-Add-Unix-domain-socket-support.patch => 0680-Add-Unix-domain-socket-support.patch} (100%) rename patches/server/{0680-Add-EntityInsideBlockEvent.patch => 0681-Add-EntityInsideBlockEvent.patch} (100%) rename patches/server/{0681-Attributes-API-for-item-defaults.patch => 0682-Attributes-API-for-item-defaults.patch} (100%) rename patches/server/{0682-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch => 0683-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch} (100%) rename patches/server/{0683-Add-cause-to-Weather-ThunderChangeEvents.patch => 0684-Add-cause-to-Weather-ThunderChangeEvents.patch} (100%) rename patches/server/{0684-More-Lidded-Block-API.patch => 0685-More-Lidded-Block-API.patch} (100%) rename patches/server/{0685-Limit-item-frame-cursors-on-maps.patch => 0686-Limit-item-frame-cursors-on-maps.patch} (100%) rename patches/server/{0686-Add-PufferFishStateChangeEvent.patch => 0687-Add-PufferFishStateChangeEvent.patch} (100%) rename patches/server/{0687-Add-PlayerKickEvent-causes.patch => 0688-Add-PlayerKickEvent-causes.patch} (100%) rename patches/server/{0688-Fix-PlayerBucketEmptyEvent-result-itemstack.patch => 0689-Fix-PlayerBucketEmptyEvent-result-itemstack.patch} (100%) rename patches/server/{0689-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch => 0690-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch} (100%) rename patches/server/{0690-Add-option-to-fix-items-merging-through-walls.patch => 0691-Add-option-to-fix-items-merging-through-walls.patch} (100%) rename patches/server/{0691-Add-BellRevealRaiderEvent.patch => 0692-Add-BellRevealRaiderEvent.patch} (100%) rename patches/server/{0692-Fix-invulnerable-end-crystals.patch => 0693-Fix-invulnerable-end-crystals.patch} (100%) rename patches/server/{0693-Add-ElderGuardianAppearanceEvent.patch => 0694-Add-ElderGuardianAppearanceEvent.patch} (100%) rename patches/server/{0694-Reset-villager-inventory-on-cancelled-pickup-event.patch => 0695-Reset-villager-inventory-on-cancelled-pickup-event.patch} (100%) rename patches/server/{0695-Fix-dangerous-end-portal-logic.patch => 0696-Fix-dangerous-end-portal-logic.patch} (100%) rename patches/server/{0696-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch => 0697-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch} (100%) rename patches/server/{0697-Make-item-validations-configurable.patch => 0698-Make-item-validations-configurable.patch} (100%) rename patches/server/{0698-Add-more-line-of-sight-methods.patch => 0699-Add-more-line-of-sight-methods.patch} (100%) rename patches/server/{0699-add-per-world-spawn-limits.patch => 0700-add-per-world-spawn-limits.patch} (96%) rename patches/server/{0700-Fix-PotionSplashEvent-for-water-splash-potions.patch => 0701-Fix-PotionSplashEvent-for-water-splash-potions.patch} (100%) rename patches/server/{0701-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch => 0702-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch} (100%) diff --git a/patches/removed/1.17/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch b/patches/server/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch similarity index 52% rename from patches/removed/1.17/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch rename to patches/server/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch index d2b1599c09..86a2778202 100644 --- a/patches/removed/1.17/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch +++ b/patches/server/0469-Stop-copy-on-write-operations-for-updating-light-dat.patch @@ -5,25 +5,23 @@ Subject: [PATCH] Stop copy-on-write operations for updating light data Causes huge memory allocations + gc issues -1.17 update note: Needs updating, temp skipped - diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java -index 9f33fa8f84d10f8f4089030074ad6c0d81269ce8..a1ad4d73ddaf6afe97a1f1ff7e0622b52fac8761 100644 +index 573cdb0897978eef8f5fc906ed4928293f4b2ab9..314b46f0becd088d26956b45981217b128d539cb 100644 --- a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java +++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java -@@ -10,7 +10,7 @@ import net.minecraft.world.level.chunk.LightChunkGetter; - public class BlockLightSectionStorage extends LayerLightSectionStorage { +@@ -9,7 +9,7 @@ import net.minecraft.world.level.chunk.LightChunkGetter; + public class BlockLightSectionStorage extends LayerLightSectionStorage { protected BlockLightSectionStorage(LightChunkGetter chunkProvider) { -- super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new Long2ObjectOpenHashMap())); +- super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new Long2ObjectOpenHashMap<>())); + super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data } @Override -@@ -23,13 +23,13 @@ public class BlockLightSectionStorage extends LayerLightSectionStorage { +@@ -20,13 +20,13 @@ public class BlockLightSectionStorage extends LayerLightSectionStorage { - public BlockDataLayerStorageMap(Long2ObjectOpenHashMap arrays) { - super(arrays); + public BlockDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data @@ -38,7 +36,7 @@ index 9f33fa8f84d10f8f4089030074ad6c0d81269ce8..a1ad4d73ddaf6afe97a1f1ff7e0622b5 } } diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -index 01ae1c811862f56317a90e3811fe2ef4b593695f..4c9041f1c1cb4b3ec114fbd0c5d4db50a6f2526d 100644 +index 67ff66e232592203cf8dad605ad01eabc4dded89..f357a3473682c2d37a20fb862522c67b9979402a 100644 --- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java @@ -9,10 +9,23 @@ public abstract class DataLayerStorageMap> { @@ -46,13 +44,12 @@ index 01ae1c811862f56317a90e3811fe2ef4b593695f..4c9041f1c1cb4b3ec114fbd0c5d4db50 private final DataLayer[] lastSections = new DataLayer[2]; private boolean cacheEnabled; - protected final Long2ObjectOpenHashMap map; -- -- protected DataLayerStorageMap(Long2ObjectOpenHashMap arrays) { -- this.map = arrays; + protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data + protected final boolean isVisible; // Paper - avoid copying light data + java.util.function.Function lookup; // Paper - faster branchless lookup -+ + +- protected DataLayerStorageMap(Long2ObjectOpenHashMap arrays) { +- this.map = arrays; + // Paper start - avoid copying light data + protected DataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { + if (isVisible) { @@ -73,7 +70,7 @@ index 01ae1c811862f56317a90e3811fe2ef4b593695f..4c9041f1c1cb4b3ec114fbd0c5d4db50 public abstract M copy(); public void copyDataLayer(long pos) { -- this.map.put(pos, ((DataLayer) this.map.get(pos)).copy()); +- this.map.put(pos, this.map.get(pos).copy()); + if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data + this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data this.clearCache(); @@ -88,22 +85,22 @@ index 01ae1c811862f56317a90e3811fe2ef4b593695f..4c9041f1c1cb4b3ec114fbd0c5d4db50 - public DataLayer getLayer(long chunkPos) { + public final DataLayer getLayer(long chunkPos) { // Paper - final if (this.cacheEnabled) { - for (int j = 0; j < 2; ++j) { - if (chunkPos == this.lastSectionKeys[j]) { + for(int i = 0; i < 2; ++i) { + if (chunkPos == this.lastSectionKeys[i]) { @@ -38,7 +52,7 @@ public abstract class DataLayerStorageMap> { } } -- DataLayer nibblearray = (DataLayer) this.map.get(chunkPos); -+ DataLayer nibblearray = lookup.apply(chunkPos); // Paper - avoid copying light data - - if (nibblearray == null) { +- DataLayer dataLayer = this.map.get(chunkPos); ++ DataLayer dataLayer = lookup.apply(chunkPos); // Paper - avoid copying light data + if (dataLayer == null) { return null; -@@ -59,11 +73,13 @@ public abstract class DataLayerStorageMap> { + } else { +@@ -58,11 +72,13 @@ public abstract class DataLayerStorageMap> { @Nullable public DataLayer removeLayer(long chunkPos) { -- return (DataLayer) this.map.remove(chunkPos); +- return this.map.remove(chunkPos); + if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data + return (DataLayer) this.data.queueRemove(chunkPos); // Paper - avoid copying light data } @@ -115,45 +112,35 @@ index 01ae1c811862f56317a90e3811fe2ef4b593695f..4c9041f1c1cb4b3ec114fbd0c5d4db50 } public void clearCache() { -@@ -71,7 +87,6 @@ public abstract class DataLayerStorageMap> { - this.lastSectionKeys[i] = Long.MAX_VALUE; - this.lastSections[i] = null; - } -- - } - - public void disableCache() { diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -index 45be10a0d7c26e4b6e5738ba994ce343265210f5..177dae992d13674bb285a60b8427df9ea843dc99 100644 +index ee32aba07aad4a3f101a6a57f7aa6c07f74dd0c3..cc9eb8273d5157fb649d84a3ec589b0b923b5bc9 100644 --- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -@@ -26,8 +26,8 @@ public abstract class LayerLightSectionStorage> +@@ -28,7 +28,7 @@ public abstract class LayerLightSectionStorage> protected final LongSet dataSectionSet = new LongOpenHashSet(); protected final LongSet toMarkNoData = new LongOpenHashSet(); protected final LongSet toMarkData = new LongOpenHashSet(); - protected volatile M visibleSectionData; -- protected final M updatingSectionData; + protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change -+ protected final M updatingSectionData; // Paper - diff on change, should be "updating" + protected final M updatingSectionData; protected final LongSet changedSections = new LongOpenHashSet(); protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet(); - protected final Long2ObjectMap queuedSections = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); -@@ -41,8 +41,8 @@ public abstract class LayerLightSectionStorage> +@@ -43,8 +43,8 @@ public abstract class LayerLightSectionStorage> this.layer = lightType; this.chunkSource = chunkProvider; this.updatingSectionData = lightData; - this.visibleSectionData = lightData.copy(); - this.visibleSectionData.disableCache(); -+ this.e_visible = lightData.copy(); // Paper - avoid copying light data -+ this.e_visible.disableCache(); // Paper - avoid copying light data ++ this.e_visible = lightData.copy(); // Paper - avoid copying light dat ++ this.e_visible.disableCache(); // Paper - avoid copying light dat } protected boolean storingLightForSection(long sectionPos) { -@@ -51,7 +51,15 @@ public abstract class LayerLightSectionStorage> +@@ -53,7 +53,15 @@ public abstract class LayerLightSectionStorage> @Nullable protected DataLayer getDataLayer(long sectionPos, boolean cached) { -- return this.getDataLayer(cached ? this.updatingSectionData : this.visibleSectionData, sectionPos); +- return this.getDataLayer((M)(cached ? this.updatingSectionData : this.visibleSectionData), sectionPos); + // Paper start - avoid copying light data + if (cached) { + return this.getDataLayer(this.updatingSectionData, sectionPos); @@ -166,150 +153,138 @@ index 45be10a0d7c26e4b6e5738ba994ce343265210f5..177dae992d13674bb285a60b8427df9e } @Nullable -@@ -364,10 +372,12 @@ public abstract class LayerLightSectionStorage> +@@ -346,9 +354,11 @@ public abstract class LayerLightSectionStorage> protected void swapSectionMap() { if (!this.changedSections.isEmpty()) { + synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data - M m0 = this.updatingSectionData.copy(); - - m0.disableCache(); -- this.visibleSectionData = m0; -+ this.e_visible = m0; // Paper - avoid copying light data + M dataLayerStorageMap = this.updatingSectionData.copy(); + dataLayerStorageMap.disableCache(); +- this.visibleSectionData = dataLayerStorageMap; ++ this.e_visible = dataLayerStorageMap; // Paper - avoid copying light data + } // Paper - avoid copying light data this.changedSections.clear(); } diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -index c304637ae8f80c65b58e8ba8a27609b532bb1184..410fcfa8c01b7e3d3e3829ebdb92a11badff16ea 100644 +index fb41fddaee27097b8b503ae13d6a775b207f883a..f6df52403a1068a0779e4ff8c2ce5dc06176e061 100644 --- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -@@ -23,15 +23,16 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage(), new Long2IntOpenHashMap(), Integer.MAX_VALUE)); + super(LightLayer.SKY, chunkProvider, new SkyLightSectionStorage.SkyDataLayerStorageMap(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data } @Override - protected int getLightValue(long blockPos) { - long j = SectionPos.blockToSection(blockPos); - int k = SectionPos.y(j); -- SkyLightSectionStorage.SkyDataLayerStorageMap lightenginestoragesky_a = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.visibleSectionData; -- int l = lightenginestoragesky_a.topSections.get(SectionPos.getZeroNode(j)); +@@ -32,8 +32,9 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage j) { - ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY = j; -- ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.defaultReturnValue(((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY); -+ ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.queueDefaultReturnValue(((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY); // Paper - avoid copying light data +@@ -59,13 +61,13 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage i) { + (this.updatingSectionData).currentLowestY = i; +- (this.updatingSectionData).topSections.defaultReturnValue((this.updatingSectionData).currentLowestY); ++ (this.updatingSectionData).otherData.queueDefaultReturnValue((this.updatingSectionData).currentLowestY); // Paper - avoid copying light data } - long k = SectionPos.getZeroNode(sectionPos); -- int l = ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.get(k); -+ int l = ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.getUpdating(k); // Paper - avoid copying light data - - if (l < j + 1) { -- ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.put(k, j + 1); -+ ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.queueUpdate(k, j + 1); // Paper - avoid copying light data - if (this.columnsWithSkySources.contains(k)) { + long l = SectionPos.getZeroNode(sectionPos); +- int j = (this.updatingSectionData).topSections.get(l); ++ int j = (this.updatingSectionData).otherData.getUpdating(l); // Paper - avoid copying light data + if (j < i + 1) { +- (this.updatingSectionData).topSections.put(l, i + 1); ++ (this.updatingSectionData).otherData.queueUpdate(l, i + 1); // Paper - avoid copying light data + if (this.columnsWithSkySources.contains(l)) { this.queueAddSource(sectionPos); - if (l > ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY) { -@@ -107,7 +109,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage (this.updatingSectionData).currentLowestY) { +@@ -102,19 +104,19 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage= k; + long l = SectionPos.getZeroNode(sectionPos); +- int i = (this.updatingSectionData).topSections.get(l); ++ int i = (this.updatingSectionData).otherData.getUpdating(l); // Paper - avoid copying light data + return i == (this.updatingSectionData).currentLowestY || SectionPos.y(sectionPos) >= i; } -@@ -327,18 +329,21 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage { - private int currentLowestY; -- private final Long2IntOpenHashMap topSections; +@@ -271,18 +273,21 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage { + int currentLowestY; +- final Long2IntOpenHashMap topSections; - - public SkyDataLayerStorageMap(Long2ObjectOpenHashMap arrays, Long2IntOpenHashMap columnToTopSection, int minSectionY) { - super(arrays); - this.topSections = columnToTopSection; - columnToTopSection.defaultReturnValue(minSectionY); -- this.currentLowestY = minSectionY; + private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data + + // Paper start - avoid copying light data -+ public SkyDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData, int i, boolean isVisible) { -+ super(data, isVisible); -+ this.otherData = otherData; -+ otherData.queueDefaultReturnValue(i); -+ // Paper end - avoid copying light data -+ this.currentLowestY = i; ++ public SkyDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object arrays, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int columnToTopSection, int minSectionY, boolean isVisible) { ++ super(arrays, isVisible); ++ this.otherData = columnToTopSection; ++ otherData.queueDefaultReturnValue(minSectionY); ++ // Paper end + this.currentLowestY = minSectionY; } @Override diff --git a/patches/server/0469-Support-old-UUID-format-for-NBT.patch b/patches/server/0470-Support-old-UUID-format-for-NBT.patch similarity index 100% rename from patches/server/0469-Support-old-UUID-format-for-NBT.patch rename to patches/server/0470-Support-old-UUID-format-for-NBT.patch diff --git a/patches/server/0470-Clean-up-duplicated-GameProfile-Properties.patch b/patches/server/0471-Clean-up-duplicated-GameProfile-Properties.patch similarity index 100% rename from patches/server/0470-Clean-up-duplicated-GameProfile-Properties.patch rename to patches/server/0471-Clean-up-duplicated-GameProfile-Properties.patch diff --git a/patches/server/0471-Convert-legacy-attributes-in-Item-Meta.patch b/patches/server/0472-Convert-legacy-attributes-in-Item-Meta.patch similarity index 100% rename from patches/server/0471-Convert-legacy-attributes-in-Item-Meta.patch rename to patches/server/0472-Convert-legacy-attributes-in-Item-Meta.patch diff --git a/patches/server/0472-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server/0473-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch similarity index 100% rename from patches/server/0472-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch rename to patches/server/0473-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch diff --git a/patches/server/0473-Remove-some-streams-from-structures.patch b/patches/server/0474-Remove-some-streams-from-structures.patch similarity index 100% rename from patches/server/0473-Remove-some-streams-from-structures.patch rename to patches/server/0474-Remove-some-streams-from-structures.patch diff --git a/patches/server/0474-Remove-streams-from-classes-related-villager-gossip.patch b/patches/server/0475-Remove-streams-from-classes-related-villager-gossip.patch similarity index 100% rename from patches/server/0474-Remove-streams-from-classes-related-villager-gossip.patch rename to patches/server/0475-Remove-streams-from-classes-related-villager-gossip.patch diff --git a/patches/server/0475-Support-components-in-ItemMeta.patch b/patches/server/0476-Support-components-in-ItemMeta.patch similarity index 100% rename from patches/server/0475-Support-components-in-ItemMeta.patch rename to patches/server/0476-Support-components-in-ItemMeta.patch diff --git a/patches/server/0476-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/patches/server/0477-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch similarity index 100% rename from patches/server/0476-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch rename to patches/server/0477-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch diff --git a/patches/server/0477-Add-entity-liquid-API.patch b/patches/server/0478-Add-entity-liquid-API.patch similarity index 100% rename from patches/server/0477-Add-entity-liquid-API.patch rename to patches/server/0478-Add-entity-liquid-API.patch diff --git a/patches/server/0478-Update-itemstack-legacy-name-and-lore.patch b/patches/server/0479-Update-itemstack-legacy-name-and-lore.patch similarity index 100% rename from patches/server/0478-Update-itemstack-legacy-name-and-lore.patch rename to patches/server/0479-Update-itemstack-legacy-name-and-lore.patch diff --git a/patches/server/0479-Spawn-player-in-correct-world-on-login.patch b/patches/server/0480-Spawn-player-in-correct-world-on-login.patch similarity index 100% rename from patches/server/0479-Spawn-player-in-correct-world-on-login.patch rename to patches/server/0480-Spawn-player-in-correct-world-on-login.patch diff --git a/patches/server/0480-Add-PrepareResultEvent.patch b/patches/server/0481-Add-PrepareResultEvent.patch similarity index 100% rename from patches/server/0480-Add-PrepareResultEvent.patch rename to patches/server/0481-Add-PrepareResultEvent.patch diff --git a/patches/server/0481-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/0482-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 100% rename from patches/server/0481-Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/server/0482-Allow-delegation-to-vanilla-chunk-gen.patch diff --git a/patches/server/0482-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server/0483-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch similarity index 100% rename from patches/server/0482-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch rename to patches/server/0483-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch diff --git a/patches/server/0483-Optimize-NetworkManager-Exception-Handling.patch b/patches/server/0484-Optimize-NetworkManager-Exception-Handling.patch similarity index 100% rename from patches/server/0483-Optimize-NetworkManager-Exception-Handling.patch rename to patches/server/0484-Optimize-NetworkManager-Exception-Handling.patch diff --git a/patches/server/0484-Optimize-the-advancement-data-player-iteration-to-be.patch b/patches/server/0485-Optimize-the-advancement-data-player-iteration-to-be.patch similarity index 100% rename from patches/server/0484-Optimize-the-advancement-data-player-iteration-to-be.patch rename to patches/server/0485-Optimize-the-advancement-data-player-iteration-to-be.patch diff --git a/patches/server/0485-Fix-arrows-never-despawning-MC-125757.patch b/patches/server/0486-Fix-arrows-never-despawning-MC-125757.patch similarity index 100% rename from patches/server/0485-Fix-arrows-never-despawning-MC-125757.patch rename to patches/server/0486-Fix-arrows-never-despawning-MC-125757.patch diff --git a/patches/server/0486-Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server/0487-Thread-Safe-Vanilla-Command-permission-checking.patch similarity index 100% rename from patches/server/0486-Thread-Safe-Vanilla-Command-permission-checking.patch rename to patches/server/0487-Thread-Safe-Vanilla-Command-permission-checking.patch diff --git a/patches/server/0487-Move-range-check-for-block-placing-up.patch b/patches/server/0488-Move-range-check-for-block-placing-up.patch similarity index 100% rename from patches/server/0487-Move-range-check-for-block-placing-up.patch rename to patches/server/0488-Move-range-check-for-block-placing-up.patch diff --git a/patches/server/0488-Fix-SPIGOT-5989.patch b/patches/server/0489-Fix-SPIGOT-5989.patch similarity index 100% rename from patches/server/0488-Fix-SPIGOT-5989.patch rename to patches/server/0489-Fix-SPIGOT-5989.patch diff --git a/patches/server/0489-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/patches/server/0490-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch similarity index 100% rename from patches/server/0489-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch rename to patches/server/0490-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch diff --git a/patches/server/0490-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/patches/server/0491-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch similarity index 100% rename from patches/server/0490-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch rename to patches/server/0491-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch diff --git a/patches/server/0491-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/patches/server/0492-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch similarity index 100% rename from patches/server/0491-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch rename to patches/server/0492-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch diff --git a/patches/server/0492-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/patches/server/0493-Add-missing-strikeLighting-call-to-World-spigot-stri.patch similarity index 100% rename from patches/server/0492-Add-missing-strikeLighting-call-to-World-spigot-stri.patch rename to patches/server/0493-Add-missing-strikeLighting-call-to-World-spigot-stri.patch diff --git a/patches/server/0493-Fix-some-rails-connecting-improperly.patch b/patches/server/0494-Fix-some-rails-connecting-improperly.patch similarity index 100% rename from patches/server/0493-Fix-some-rails-connecting-improperly.patch rename to patches/server/0494-Fix-some-rails-connecting-improperly.patch diff --git a/patches/server/0494-Incremental-player-saving.patch b/patches/server/0495-Incremental-player-saving.patch similarity index 100% rename from patches/server/0494-Incremental-player-saving.patch rename to patches/server/0495-Incremental-player-saving.patch diff --git a/patches/server/0495-Fix-MC-187716-Use-configured-height.patch b/patches/server/0496-Fix-MC-187716-Use-configured-height.patch similarity index 100% rename from patches/server/0495-Fix-MC-187716-Use-configured-height.patch rename to patches/server/0496-Fix-MC-187716-Use-configured-height.patch diff --git a/patches/server/0496-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/patches/server/0497-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch similarity index 100% rename from patches/server/0496-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch rename to patches/server/0497-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch diff --git a/patches/server/0497-Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server/0498-Do-not-let-the-server-load-chunks-from-newer-version.patch similarity index 100% rename from patches/server/0497-Do-not-let-the-server-load-chunks-from-newer-version.patch rename to patches/server/0498-Do-not-let-the-server-load-chunks-from-newer-version.patch diff --git a/patches/server/0498-Brand-support.patch b/patches/server/0499-Brand-support.patch similarity index 100% rename from patches/server/0498-Brand-support.patch rename to patches/server/0499-Brand-support.patch diff --git a/patches/server/0499-Add-setMaxPlayers-API.patch b/patches/server/0500-Add-setMaxPlayers-API.patch similarity index 100% rename from patches/server/0499-Add-setMaxPlayers-API.patch rename to patches/server/0500-Add-setMaxPlayers-API.patch diff --git a/patches/server/0500-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server/0501-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from patches/server/0500-Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/server/0501-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/patches/server/0501-Don-t-require-FACING-data.patch b/patches/server/0502-Don-t-require-FACING-data.patch similarity index 100% rename from patches/server/0501-Don-t-require-FACING-data.patch rename to patches/server/0502-Don-t-require-FACING-data.patch diff --git a/patches/server/0502-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server/0503-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch similarity index 100% rename from patches/server/0502-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch rename to patches/server/0503-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch diff --git a/patches/server/0503-Add-moon-phase-API.patch b/patches/server/0504-Add-moon-phase-API.patch similarity index 100% rename from patches/server/0503-Add-moon-phase-API.patch rename to patches/server/0504-Add-moon-phase-API.patch diff --git a/patches/server/0504-Prevent-headless-pistons-from-being-created.patch b/patches/server/0505-Prevent-headless-pistons-from-being-created.patch similarity index 100% rename from patches/server/0504-Prevent-headless-pistons-from-being-created.patch rename to patches/server/0505-Prevent-headless-pistons-from-being-created.patch diff --git a/patches/server/0505-Add-BellRingEvent.patch b/patches/server/0506-Add-BellRingEvent.patch similarity index 100% rename from patches/server/0505-Add-BellRingEvent.patch rename to patches/server/0506-Add-BellRingEvent.patch diff --git a/patches/server/0506-Add-zombie-targets-turtle-egg-config.patch b/patches/server/0507-Add-zombie-targets-turtle-egg-config.patch similarity index 95% rename from patches/server/0506-Add-zombie-targets-turtle-egg-config.patch rename to patches/server/0507-Add-zombie-targets-turtle-egg-config.patch index 2f5c2120c0..b65976440a 100644 --- a/patches/server/0506-Add-zombie-targets-turtle-egg-config.patch +++ b/patches/server/0507-Add-zombie-targets-turtle-egg-config.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add zombie targets turtle egg config diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 040956f5d714ac014f9a153981d444db299fd826..83a4a3bbea1c076788cb7746adcee61e128b90fe 100644 +index a22abda177b0ffc9699fb23aaac8680261f385fe..a14989c20275c49b0e6eaba52f3e06b28b043445 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -38,6 +38,11 @@ public class PaperWorldConfig { diff --git a/patches/server/0507-Buffer-joins-to-world.patch b/patches/server/0508-Buffer-joins-to-world.patch similarity index 100% rename from patches/server/0507-Buffer-joins-to-world.patch rename to patches/server/0508-Buffer-joins-to-world.patch diff --git a/patches/server/0508-Optimize-redstone-algorithm.patch b/patches/server/0509-Optimize-redstone-algorithm.patch similarity index 99% rename from patches/server/0508-Optimize-redstone-algorithm.patch rename to patches/server/0509-Optimize-redstone-algorithm.patch index 4ed4d3c38a..fc9c369c29 100644 --- a/patches/server/0508-Optimize-redstone-algorithm.patch +++ b/patches/server/0509-Optimize-redstone-algorithm.patch @@ -19,7 +19,7 @@ Aside from making the obvious class/function renames and obfhelpers I didn't nee Just added Bukkit's event system and took a few liberties with dead code and comment misspellings. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 83a4a3bbea1c076788cb7746adcee61e128b90fe..acbaa00167d60ca6c6019b2dcd0947ef1d0557ee 100644 +index a14989c20275c49b0e6eaba52f3e06b28b043445..631b68a4a661ceadac02c032e9199c54580f4079 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -43,6 +43,16 @@ public class PaperWorldConfig { diff --git a/patches/server/0509-Fix-hex-colors-not-working-in-some-kick-messages.patch b/patches/server/0510-Fix-hex-colors-not-working-in-some-kick-messages.patch similarity index 100% rename from patches/server/0509-Fix-hex-colors-not-working-in-some-kick-messages.patch rename to patches/server/0510-Fix-hex-colors-not-working-in-some-kick-messages.patch diff --git a/patches/server/0510-PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server/0511-PortalCreateEvent-needs-to-know-its-entity.patch similarity index 100% rename from patches/server/0510-PortalCreateEvent-needs-to-know-its-entity.patch rename to patches/server/0511-PortalCreateEvent-needs-to-know-its-entity.patch diff --git a/patches/server/0511-Fix-CraftTeam-null-check.patch b/patches/server/0512-Fix-CraftTeam-null-check.patch similarity index 100% rename from patches/server/0511-Fix-CraftTeam-null-check.patch rename to patches/server/0512-Fix-CraftTeam-null-check.patch diff --git a/patches/server/0512-Add-more-Evoker-API.patch b/patches/server/0513-Add-more-Evoker-API.patch similarity index 100% rename from patches/server/0512-Add-more-Evoker-API.patch rename to patches/server/0513-Add-more-Evoker-API.patch diff --git a/patches/server/0513-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/server/0514-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 100% rename from patches/server/0513-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to patches/server/0514-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch diff --git a/patches/server/0514-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server/0515-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 100% rename from patches/server/0514-Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/server/0515-Create-HoverEvent-from-ItemStack-Entity.patch diff --git a/patches/server/0515-Cache-block-data-strings.patch b/patches/server/0516-Cache-block-data-strings.patch similarity index 100% rename from patches/server/0515-Cache-block-data-strings.patch rename to patches/server/0516-Cache-block-data-strings.patch diff --git a/patches/server/0516-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/patches/server/0517-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch similarity index 100% rename from patches/server/0516-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch rename to patches/server/0517-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch diff --git a/patches/server/0517-Add-additional-open-container-api-to-HumanEntity.patch b/patches/server/0518-Add-additional-open-container-api-to-HumanEntity.patch similarity index 100% rename from patches/server/0517-Add-additional-open-container-api-to-HumanEntity.patch rename to patches/server/0518-Add-additional-open-container-api-to-HumanEntity.patch diff --git a/patches/server/0518-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/patches/server/0519-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch similarity index 100% rename from patches/server/0518-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch rename to patches/server/0519-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch diff --git a/patches/server/0519-Extend-block-drop-capture-to-capture-all-items-added.patch b/patches/server/0520-Extend-block-drop-capture-to-capture-all-items-added.patch similarity index 100% rename from patches/server/0519-Extend-block-drop-capture-to-capture-all-items-added.patch rename to patches/server/0520-Extend-block-drop-capture-to-capture-all-items-added.patch diff --git a/patches/server/0520-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server/0521-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch similarity index 100% rename from patches/server/0520-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch rename to patches/server/0521-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch diff --git a/patches/server/0521-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server/0522-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 100% rename from patches/server/0521-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to patches/server/0522-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch diff --git a/patches/server/0522-Lazily-track-plugin-scoreboards-by-default.patch b/patches/server/0523-Lazily-track-plugin-scoreboards-by-default.patch similarity index 100% rename from patches/server/0522-Lazily-track-plugin-scoreboards-by-default.patch rename to patches/server/0523-Lazily-track-plugin-scoreboards-by-default.patch diff --git a/patches/server/0523-Entity-isTicking.patch b/patches/server/0524-Entity-isTicking.patch similarity index 100% rename from patches/server/0523-Entity-isTicking.patch rename to patches/server/0524-Entity-isTicking.patch diff --git a/patches/server/0524-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/patches/server/0525-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch similarity index 100% rename from patches/server/0524-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch rename to patches/server/0525-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch diff --git a/patches/server/0525-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/patches/server/0526-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch similarity index 100% rename from patches/server/0525-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch rename to patches/server/0526-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch diff --git a/patches/server/0526-Reset-Ender-Crystals-on-Dragon-Spawn.patch b/patches/server/0527-Reset-Ender-Crystals-on-Dragon-Spawn.patch similarity index 100% rename from patches/server/0526-Reset-Ender-Crystals-on-Dragon-Spawn.patch rename to patches/server/0527-Reset-Ender-Crystals-on-Dragon-Spawn.patch diff --git a/patches/server/0527-Fix-for-large-move-vectors-crashing-server.patch b/patches/server/0528-Fix-for-large-move-vectors-crashing-server.patch similarity index 100% rename from patches/server/0527-Fix-for-large-move-vectors-crashing-server.patch rename to patches/server/0528-Fix-for-large-move-vectors-crashing-server.patch diff --git a/patches/server/0528-Optimise-getType-calls.patch b/patches/server/0529-Optimise-getType-calls.patch similarity index 100% rename from patches/server/0528-Optimise-getType-calls.patch rename to patches/server/0529-Optimise-getType-calls.patch diff --git a/patches/server/0529-Villager-resetOffers.patch b/patches/server/0530-Villager-resetOffers.patch similarity index 100% rename from patches/server/0529-Villager-resetOffers.patch rename to patches/server/0530-Villager-resetOffers.patch diff --git a/patches/server/0530-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/patches/server/0531-Improve-inlinig-for-some-hot-IBlockData-methods.patch similarity index 100% rename from patches/server/0530-Improve-inlinig-for-some-hot-IBlockData-methods.patch rename to patches/server/0531-Improve-inlinig-for-some-hot-IBlockData-methods.patch diff --git a/patches/server/0531-Retain-block-place-order-when-capturing-blockstates.patch b/patches/server/0532-Retain-block-place-order-when-capturing-blockstates.patch similarity index 93% rename from patches/server/0531-Retain-block-place-order-when-capturing-blockstates.patch rename to patches/server/0532-Retain-block-place-order-when-capturing-blockstates.patch index c81368ec8e..9825acb711 100644 --- a/patches/server/0531-Retain-block-place-order-when-capturing-blockstates.patch +++ b/patches/server/0532-Retain-block-place-order-when-capturing-blockstates.patch @@ -10,7 +10,7 @@ In general, look at making this logic more robust (i.e properly handling cases where a captured entry is overriden) - but for now this will do. diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index f004f5012ce157f9b0fb9c5890b5f3de957418f8..febc4fececb4bf527a69e47a06d782ec81616c1e 100644 +index d9697003d05ddc344207793b4f266743fcaef16c..c820cc7f3be693f445937a157ac2477e36f906b4 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -147,7 +147,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { diff --git a/patches/server/0532-Reduce-blockpos-allocation-from-pathfinding.patch b/patches/server/0533-Reduce-blockpos-allocation-from-pathfinding.patch similarity index 100% rename from patches/server/0532-Reduce-blockpos-allocation-from-pathfinding.patch rename to patches/server/0533-Reduce-blockpos-allocation-from-pathfinding.patch diff --git a/patches/server/0533-Fix-item-locations-dropped-from-campfires.patch b/patches/server/0534-Fix-item-locations-dropped-from-campfires.patch similarity index 100% rename from patches/server/0533-Fix-item-locations-dropped-from-campfires.patch rename to patches/server/0534-Fix-item-locations-dropped-from-campfires.patch diff --git a/patches/server/0534-Player-elytra-boost-API.patch b/patches/server/0535-Player-elytra-boost-API.patch similarity index 100% rename from patches/server/0534-Player-elytra-boost-API.patch rename to patches/server/0535-Player-elytra-boost-API.patch diff --git a/patches/server/0535-Fixed-TileEntityBell-memory-leak.patch b/patches/server/0536-Fixed-TileEntityBell-memory-leak.patch similarity index 100% rename from patches/server/0535-Fixed-TileEntityBell-memory-leak.patch rename to patches/server/0536-Fixed-TileEntityBell-memory-leak.patch diff --git a/patches/server/0536-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/patches/server/0537-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch similarity index 100% rename from patches/server/0536-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch rename to patches/server/0537-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch diff --git a/patches/server/0537-Add-getOfflinePlayerIfCached-String.patch b/patches/server/0538-Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from patches/server/0537-Add-getOfflinePlayerIfCached-String.patch rename to patches/server/0538-Add-getOfflinePlayerIfCached-String.patch diff --git a/patches/server/0538-Add-ignore-discounts-API.patch b/patches/server/0539-Add-ignore-discounts-API.patch similarity index 100% rename from patches/server/0538-Add-ignore-discounts-API.patch rename to patches/server/0539-Add-ignore-discounts-API.patch diff --git a/patches/server/0539-Toggle-for-removing-existing-dragon.patch b/patches/server/0540-Toggle-for-removing-existing-dragon.patch similarity index 95% rename from patches/server/0539-Toggle-for-removing-existing-dragon.patch rename to patches/server/0540-Toggle-for-removing-existing-dragon.patch index c7654f7d44..64a9a031ad 100644 --- a/patches/server/0539-Toggle-for-removing-existing-dragon.patch +++ b/patches/server/0540-Toggle-for-removing-existing-dragon.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Toggle for removing existing dragon diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index acbaa00167d60ca6c6019b2dcd0947ef1d0557ee..b3e9149dbbc1cd6a6d01bb9f7109136b995afb0a 100644 +index 631b68a4a661ceadac02c032e9199c54580f4079..f46890906f324d8c3f4d1917d38b0f8f8604e2f2 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -53,6 +53,14 @@ public class PaperWorldConfig { diff --git a/patches/server/0540-Fix-client-lag-on-advancement-loading.patch b/patches/server/0541-Fix-client-lag-on-advancement-loading.patch similarity index 100% rename from patches/server/0540-Fix-client-lag-on-advancement-loading.patch rename to patches/server/0541-Fix-client-lag-on-advancement-loading.patch diff --git a/patches/server/0541-Item-no-age-no-player-pickup.patch b/patches/server/0542-Item-no-age-no-player-pickup.patch similarity index 100% rename from patches/server/0541-Item-no-age-no-player-pickup.patch rename to patches/server/0542-Item-no-age-no-player-pickup.patch diff --git a/patches/server/0542-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/patches/server/0543-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch similarity index 100% rename from patches/server/0542-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch rename to patches/server/0543-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch diff --git a/patches/server/0543-Beacon-API-custom-effect-ranges.patch b/patches/server/0544-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from patches/server/0543-Beacon-API-custom-effect-ranges.patch rename to patches/server/0544-Beacon-API-custom-effect-ranges.patch diff --git a/patches/server/0544-Add-API-for-quit-reason.patch b/patches/server/0545-Add-API-for-quit-reason.patch similarity index 100% rename from patches/server/0544-Add-API-for-quit-reason.patch rename to patches/server/0545-Add-API-for-quit-reason.patch diff --git a/patches/server/0545-Seed-based-feature-search.patch b/patches/server/0546-Seed-based-feature-search.patch similarity index 98% rename from patches/server/0545-Seed-based-feature-search.patch rename to patches/server/0546-Seed-based-feature-search.patch index 46be6bfd43..359f0d7a61 100644 --- a/patches/server/0545-Seed-based-feature-search.patch +++ b/patches/server/0546-Seed-based-feature-search.patch @@ -21,7 +21,7 @@ changes but this should usually not happen. A config option to disable this completely is added though in case that should ever be necessary. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b3e9149dbbc1cd6a6d01bb9f7109136b995afb0a..2523aabf499ef3807af02f7e61a3b13dbca08ee3 100644 +index f46890906f324d8c3f4d1917d38b0f8f8604e2f2..72bfeb3d465585ea6de4e896eee65b5bed75188d 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -376,6 +376,14 @@ public class PaperWorldConfig { diff --git a/patches/server/0546-Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server/0547-Add-Wandering-Trader-spawn-rate-config-options.patch similarity index 98% rename from patches/server/0546-Add-Wandering-Trader-spawn-rate-config-options.patch rename to patches/server/0547-Add-Wandering-Trader-spawn-rate-config-options.patch index 22e1ab6f8c..fccbad4b4d 100644 --- a/patches/server/0546-Add-Wandering-Trader-spawn-rate-config-options.patch +++ b/patches/server/0547-Add-Wandering-Trader-spawn-rate-config-options.patch @@ -11,7 +11,7 @@ in IWorldServerData are removed as they were only used in certain places, with h values used in other places. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2523aabf499ef3807af02f7e61a3b13dbca08ee3..d76b292cdfa2ae4d84a449da7f66faba494f6b03 100644 +index 72bfeb3d465585ea6de4e896eee65b5bed75188d..19c42a9863341f1d06ad57e95049b3cd5b88aeb2 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -61,6 +61,19 @@ public class PaperWorldConfig { diff --git a/patches/server/0547-Significantly-improve-performance-of-the-end-generat.patch b/patches/server/0548-Significantly-improve-performance-of-the-end-generat.patch similarity index 100% rename from patches/server/0547-Significantly-improve-performance-of-the-end-generat.patch rename to patches/server/0548-Significantly-improve-performance-of-the-end-generat.patch diff --git a/patches/server/0548-Expose-world-spawn-angle.patch b/patches/server/0549-Expose-world-spawn-angle.patch similarity index 100% rename from patches/server/0548-Expose-world-spawn-angle.patch rename to patches/server/0549-Expose-world-spawn-angle.patch diff --git a/patches/server/0549-Add-Destroy-Speed-API.patch b/patches/server/0550-Add-Destroy-Speed-API.patch similarity index 100% rename from patches/server/0549-Add-Destroy-Speed-API.patch rename to patches/server/0550-Add-Destroy-Speed-API.patch diff --git a/patches/server/0550-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/patches/server/0551-Fix-Player-spawnParticle-x-y-z-precision-loss.patch similarity index 100% rename from patches/server/0550-Fix-Player-spawnParticle-x-y-z-precision-loss.patch rename to patches/server/0551-Fix-Player-spawnParticle-x-y-z-precision-loss.patch diff --git a/patches/server/0551-Add-LivingEntity-clearActiveItem.patch b/patches/server/0552-Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from patches/server/0551-Add-LivingEntity-clearActiveItem.patch rename to patches/server/0552-Add-LivingEntity-clearActiveItem.patch diff --git a/patches/server/0552-Add-PlayerItemCooldownEvent.patch b/patches/server/0553-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from patches/server/0552-Add-PlayerItemCooldownEvent.patch rename to patches/server/0553-Add-PlayerItemCooldownEvent.patch diff --git a/patches/server/0553-More-lightning-API.patch b/patches/server/0554-More-lightning-API.patch similarity index 100% rename from patches/server/0553-More-lightning-API.patch rename to patches/server/0554-More-lightning-API.patch diff --git a/patches/server/0554-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/0555-Climbing-should-not-bypass-cramming-gamerule.patch similarity index 98% rename from patches/server/0554-Climbing-should-not-bypass-cramming-gamerule.patch rename to patches/server/0555-Climbing-should-not-bypass-cramming-gamerule.patch index af8c479a90..71d40d33a8 100644 --- a/patches/server/0554-Climbing-should-not-bypass-cramming-gamerule.patch +++ b/patches/server/0555-Climbing-should-not-bypass-cramming-gamerule.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Climbing should not bypass cramming gamerule diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index d76b292cdfa2ae4d84a449da7f66faba494f6b03..0ec093e5d8865e909d0d105e27b81b31bdb5c192 100644 +index 19c42a9863341f1d06ad57e95049b3cd5b88aeb2..aef38974128c7986864571a3552a566ad672dccd 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -74,6 +74,11 @@ public class PaperWorldConfig { diff --git a/patches/server/0555-Added-missing-default-perms-for-commands.patch b/patches/server/0556-Added-missing-default-perms-for-commands.patch similarity index 100% rename from patches/server/0555-Added-missing-default-perms-for-commands.patch rename to patches/server/0556-Added-missing-default-perms-for-commands.patch diff --git a/patches/server/0556-Add-PlayerShearBlockEvent.patch b/patches/server/0557-Add-PlayerShearBlockEvent.patch similarity index 100% rename from patches/server/0556-Add-PlayerShearBlockEvent.patch rename to patches/server/0557-Add-PlayerShearBlockEvent.patch diff --git a/patches/server/0557-Set-spigots-verbose-world-setting-to-false-by-def.patch b/patches/server/0558-Set-spigots-verbose-world-setting-to-false-by-def.patch similarity index 100% rename from patches/server/0557-Set-spigots-verbose-world-setting-to-false-by-def.patch rename to patches/server/0558-Set-spigots-verbose-world-setting-to-false-by-def.patch diff --git a/patches/server/0558-Fix-curing-zombie-villager-discount-exploit.patch b/patches/server/0559-Fix-curing-zombie-villager-discount-exploit.patch similarity index 96% rename from patches/server/0558-Fix-curing-zombie-villager-discount-exploit.patch rename to patches/server/0559-Fix-curing-zombie-villager-discount-exploit.patch index b6a6b16e0f..9e23cbc2fd 100644 --- a/patches/server/0558-Fix-curing-zombie-villager-discount-exploit.patch +++ b/patches/server/0559-Fix-curing-zombie-villager-discount-exploit.patch @@ -8,7 +8,7 @@ and curing a villager on repeat by simply resetting the relevant part of the reputation when it is cured. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0ec093e5d8865e909d0d105e27b81b31bdb5c192..1a8e7a495c38f617932825185378b2e494158175 100644 +index aef38974128c7986864571a3552a566ad672dccd..dd23c6dc5e680006c10329433c059fc9b85dd1cc 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -79,6 +79,11 @@ public class PaperWorldConfig { diff --git a/patches/server/0559-Limit-recipe-packets.patch b/patches/server/0560-Limit-recipe-packets.patch similarity index 100% rename from patches/server/0559-Limit-recipe-packets.patch rename to patches/server/0560-Limit-recipe-packets.patch diff --git a/patches/server/0560-Fix-CraftSound-backwards-compatibility.patch b/patches/server/0561-Fix-CraftSound-backwards-compatibility.patch similarity index 100% rename from patches/server/0560-Fix-CraftSound-backwards-compatibility.patch rename to patches/server/0561-Fix-CraftSound-backwards-compatibility.patch diff --git a/patches/server/0561-MC-4-Fix-item-position-desync.patch b/patches/server/0562-MC-4-Fix-item-position-desync.patch similarity index 100% rename from patches/server/0561-MC-4-Fix-item-position-desync.patch rename to patches/server/0562-MC-4-Fix-item-position-desync.patch diff --git a/patches/server/0562-Player-Chunk-Load-Unload-Events.patch b/patches/server/0563-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from patches/server/0562-Player-Chunk-Load-Unload-Events.patch rename to patches/server/0563-Player-Chunk-Load-Unload-Events.patch diff --git a/patches/server/0563-Optimize-Dynamic-get-Missing-Keys.patch b/patches/server/0564-Optimize-Dynamic-get-Missing-Keys.patch similarity index 100% rename from patches/server/0563-Optimize-Dynamic-get-Missing-Keys.patch rename to patches/server/0564-Optimize-Dynamic-get-Missing-Keys.patch diff --git a/patches/server/0564-Expose-LivingEntity-hurt-direction.patch b/patches/server/0565-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from patches/server/0564-Expose-LivingEntity-hurt-direction.patch rename to patches/server/0565-Expose-LivingEntity-hurt-direction.patch diff --git a/patches/server/0565-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server/0566-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from patches/server/0565-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/server/0566-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/patches/server/0566-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server/0567-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch similarity index 100% rename from patches/server/0566-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch rename to patches/server/0567-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch diff --git a/patches/server/0567-added-PlayerTradeEvent.patch b/patches/server/0568-added-PlayerTradeEvent.patch similarity index 100% rename from patches/server/0567-added-PlayerTradeEvent.patch rename to patches/server/0568-added-PlayerTradeEvent.patch diff --git a/patches/server/0568-Implement-TargetHitEvent.patch b/patches/server/0569-Implement-TargetHitEvent.patch similarity index 100% rename from patches/server/0568-Implement-TargetHitEvent.patch rename to patches/server/0569-Implement-TargetHitEvent.patch diff --git a/patches/server/0569-Additional-Block-Material-API-s.patch b/patches/server/0570-Additional-Block-Material-API-s.patch similarity index 100% rename from patches/server/0569-Additional-Block-Material-API-s.patch rename to patches/server/0570-Additional-Block-Material-API-s.patch diff --git a/patches/server/0570-Fix-harming-potion-dupe.patch b/patches/server/0571-Fix-harming-potion-dupe.patch similarity index 100% rename from patches/server/0570-Fix-harming-potion-dupe.patch rename to patches/server/0571-Fix-harming-potion-dupe.patch diff --git a/patches/server/0571-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/patches/server/0572-Implement-API-to-get-Material-from-Boats-and-Minecar.patch similarity index 100% rename from patches/server/0571-Implement-API-to-get-Material-from-Boats-and-Minecar.patch rename to patches/server/0572-Implement-API-to-get-Material-from-Boats-and-Minecar.patch diff --git a/patches/server/0572-Cache-burn-durations.patch b/patches/server/0573-Cache-burn-durations.patch similarity index 100% rename from patches/server/0572-Cache-burn-durations.patch rename to patches/server/0573-Cache-burn-durations.patch diff --git a/patches/server/0573-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server/0574-Allow-disabling-mob-spawner-spawn-egg-transformation.patch similarity index 95% rename from patches/server/0573-Allow-disabling-mob-spawner-spawn-egg-transformation.patch rename to patches/server/0574-Allow-disabling-mob-spawner-spawn-egg-transformation.patch index df86b299c0..3bd5f9edeb 100644 --- a/patches/server/0573-Allow-disabling-mob-spawner-spawn-egg-transformation.patch +++ b/patches/server/0574-Allow-disabling-mob-spawner-spawn-egg-transformation.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Allow disabling mob spawner spawn egg transformation diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1a8e7a495c38f617932825185378b2e494158175..3c9bc0684f25d511b05b724d4d52aaa82e965397 100644 +index dd23c6dc5e680006c10329433c059fc9b85dd1cc..adf3ddd9ea295aafc8f8a5c0196d7c6ef54d0c4b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -84,6 +84,11 @@ public class PaperWorldConfig { diff --git a/patches/server/0574-Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server/0575-Implement-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from patches/server/0574-Implement-PlayerFlowerPotManipulateEvent.patch rename to patches/server/0575-Implement-PlayerFlowerPotManipulateEvent.patch diff --git a/patches/server/0575-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server/0576-Fix-interact-event-not-being-called-in-adventure.patch similarity index 100% rename from patches/server/0575-Fix-interact-event-not-being-called-in-adventure.patch rename to patches/server/0576-Fix-interact-event-not-being-called-in-adventure.patch diff --git a/patches/server/0576-Zombie-API-breaking-doors.patch b/patches/server/0577-Zombie-API-breaking-doors.patch similarity index 100% rename from patches/server/0576-Zombie-API-breaking-doors.patch rename to patches/server/0577-Zombie-API-breaking-doors.patch diff --git a/patches/server/0577-Fix-nerfed-slime-when-splitting.patch b/patches/server/0578-Fix-nerfed-slime-when-splitting.patch similarity index 100% rename from patches/server/0577-Fix-nerfed-slime-when-splitting.patch rename to patches/server/0578-Fix-nerfed-slime-when-splitting.patch diff --git a/patches/server/0578-Add-EntityLoadCrossbowEvent.patch b/patches/server/0579-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from patches/server/0578-Add-EntityLoadCrossbowEvent.patch rename to patches/server/0579-Add-EntityLoadCrossbowEvent.patch diff --git a/patches/server/0579-Guardian-beam-workaround.patch b/patches/server/0580-Guardian-beam-workaround.patch similarity index 100% rename from patches/server/0579-Guardian-beam-workaround.patch rename to patches/server/0580-Guardian-beam-workaround.patch diff --git a/patches/server/0580-Added-WorldGameRuleChangeEvent.patch b/patches/server/0581-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from patches/server/0580-Added-WorldGameRuleChangeEvent.patch rename to patches/server/0581-Added-WorldGameRuleChangeEvent.patch diff --git a/patches/server/0581-Added-ServerResourcesReloadedEvent.patch b/patches/server/0582-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from patches/server/0581-Added-ServerResourcesReloadedEvent.patch rename to patches/server/0582-Added-ServerResourcesReloadedEvent.patch diff --git a/patches/server/0582-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server/0583-Added-world-settings-for-mobs-picking-up-loot.patch similarity index 97% rename from patches/server/0582-Added-world-settings-for-mobs-picking-up-loot.patch rename to patches/server/0583-Added-world-settings-for-mobs-picking-up-loot.patch index 84060c5b85..ef1e217c08 100644 --- a/patches/server/0582-Added-world-settings-for-mobs-picking-up-loot.patch +++ b/patches/server/0583-Added-world-settings-for-mobs-picking-up-loot.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Added world settings for mobs picking up loot diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3c9bc0684f25d511b05b724d4d52aaa82e965397..4a9fedb40acc72bec29fe71634406b06ce6b53cd 100644 +index adf3ddd9ea295aafc8f8a5c0196d7c6ef54d0c4b..db9d8d1f30c671207617fc75c24b771cd7a23391 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -430,6 +430,14 @@ public class PaperWorldConfig { diff --git a/patches/server/0583-Implemented-BlockFailedDispenseEvent.patch b/patches/server/0584-Implemented-BlockFailedDispenseEvent.patch similarity index 100% rename from patches/server/0583-Implemented-BlockFailedDispenseEvent.patch rename to patches/server/0584-Implemented-BlockFailedDispenseEvent.patch diff --git a/patches/server/0584-Added-PlayerLecternPageChangeEvent.patch b/patches/server/0585-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from patches/server/0584-Added-PlayerLecternPageChangeEvent.patch rename to patches/server/0585-Added-PlayerLecternPageChangeEvent.patch diff --git a/patches/server/0585-Added-PlayerLoomPatternSelectEvent.patch b/patches/server/0586-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from patches/server/0585-Added-PlayerLoomPatternSelectEvent.patch rename to patches/server/0586-Added-PlayerLoomPatternSelectEvent.patch diff --git a/patches/server/0586-Configurable-door-breaking-difficulty.patch b/patches/server/0587-Configurable-door-breaking-difficulty.patch similarity index 98% rename from patches/server/0586-Configurable-door-breaking-difficulty.patch rename to patches/server/0587-Configurable-door-breaking-difficulty.patch index a2bac6f78b..de65c8bc54 100644 --- a/patches/server/0586-Configurable-door-breaking-difficulty.patch +++ b/patches/server/0587-Configurable-door-breaking-difficulty.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Configurable door breaking difficulty diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4a9fedb40acc72bec29fe71634406b06ce6b53cd..48e0f9b8dbb94d56200b0b46c2a50d9bfa44b398 100644 +index db9d8d1f30c671207617fc75c24b771cd7a23391..75b4da3d38912e52e7ca4d99d51bd97e06808303 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -2,7 +2,10 @@ package com.destroystokyo.paper; diff --git a/patches/server/0587-Empty-commands-shall-not-be-dispatched.patch b/patches/server/0588-Empty-commands-shall-not-be-dispatched.patch similarity index 100% rename from patches/server/0587-Empty-commands-shall-not-be-dispatched.patch rename to patches/server/0588-Empty-commands-shall-not-be-dispatched.patch diff --git a/patches/server/0588-Implement-API-to-expose-exact-interaction-point.patch b/patches/server/0589-Implement-API-to-expose-exact-interaction-point.patch similarity index 100% rename from patches/server/0588-Implement-API-to-expose-exact-interaction-point.patch rename to patches/server/0589-Implement-API-to-expose-exact-interaction-point.patch diff --git a/patches/server/0589-Remove-stale-POIs.patch b/patches/server/0590-Remove-stale-POIs.patch similarity index 100% rename from patches/server/0589-Remove-stale-POIs.patch rename to patches/server/0590-Remove-stale-POIs.patch diff --git a/patches/server/0590-Fix-villager-boat-exploit.patch b/patches/server/0591-Fix-villager-boat-exploit.patch similarity index 100% rename from patches/server/0590-Fix-villager-boat-exploit.patch rename to patches/server/0591-Fix-villager-boat-exploit.patch diff --git a/patches/server/0591-Add-sendOpLevel-API.patch b/patches/server/0592-Add-sendOpLevel-API.patch similarity index 100% rename from patches/server/0591-Add-sendOpLevel-API.patch rename to patches/server/0592-Add-sendOpLevel-API.patch diff --git a/patches/server/0592-Add-StructureLocateEvent.patch b/patches/server/0593-Add-StructureLocateEvent.patch similarity index 100% rename from patches/server/0592-Add-StructureLocateEvent.patch rename to patches/server/0593-Add-StructureLocateEvent.patch diff --git a/patches/server/0593-Collision-option-for-requiring-a-player-participant.patch b/patches/server/0594-Collision-option-for-requiring-a-player-participant.patch similarity index 98% rename from patches/server/0593-Collision-option-for-requiring-a-player-participant.patch rename to patches/server/0594-Collision-option-for-requiring-a-player-participant.patch index ab0cf7aa4c..c8a256ef02 100644 --- a/patches/server/0593-Collision-option-for-requiring-a-player-participant.patch +++ b/patches/server/0594-Collision-option-for-requiring-a-player-participant.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Collision option for requiring a player participant diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 48e0f9b8dbb94d56200b0b46c2a50d9bfa44b398..bc39e5fe8c9f5d1e5b5c4ea7bd80193af8574211 100644 +index 75b4da3d38912e52e7ca4d99d51bd97e06808303..013c6f898faca8c22b805c8a476666a0b73828f3 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -64,6 +64,18 @@ public class PaperWorldConfig { diff --git a/patches/server/0594-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/patches/server/0595-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch similarity index 100% rename from patches/server/0594-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch rename to patches/server/0595-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch diff --git a/patches/server/0595-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/server/0596-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from patches/server/0595-Return-chat-component-with-empty-text-instead-of-thr.patch rename to patches/server/0596-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/patches/server/0596-Make-schedule-command-per-world.patch b/patches/server/0597-Make-schedule-command-per-world.patch similarity index 100% rename from patches/server/0596-Make-schedule-command-per-world.patch rename to patches/server/0597-Make-schedule-command-per-world.patch diff --git a/patches/server/0597-Configurable-max-leash-distance.patch b/patches/server/0598-Configurable-max-leash-distance.patch similarity index 96% rename from patches/server/0597-Configurable-max-leash-distance.patch rename to patches/server/0598-Configurable-max-leash-distance.patch index 39b2c1b3a2..fd6ea75e17 100644 --- a/patches/server/0597-Configurable-max-leash-distance.patch +++ b/patches/server/0598-Configurable-max-leash-distance.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Configurable max leash distance diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index bc39e5fe8c9f5d1e5b5c4ea7bd80193af8574211..214b7ab71c4717faa3c949e18f268bef3e066305 100644 +index 013c6f898faca8c22b805c8a476666a0b73828f3..a001f5cd737cf5c76dc14b2b3442238adaa5f79e 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -263,6 +263,12 @@ public class PaperWorldConfig { diff --git a/patches/server/0598-Implement-BlockPreDispenseEvent.patch b/patches/server/0599-Implement-BlockPreDispenseEvent.patch similarity index 100% rename from patches/server/0598-Implement-BlockPreDispenseEvent.patch rename to patches/server/0599-Implement-BlockPreDispenseEvent.patch diff --git a/patches/server/0599-Added-Vanilla-Entity-Tags.patch b/patches/server/0600-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from patches/server/0599-Added-Vanilla-Entity-Tags.patch rename to patches/server/0600-Added-Vanilla-Entity-Tags.patch diff --git a/patches/server/0600-added-Wither-API.patch b/patches/server/0601-added-Wither-API.patch similarity index 100% rename from patches/server/0600-added-Wither-API.patch rename to patches/server/0601-added-Wither-API.patch diff --git a/patches/server/0601-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/patches/server/0602-Added-firing-of-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from patches/server/0601-Added-firing-of-PlayerChangeBeaconEffectEvent.patch rename to patches/server/0602-Added-firing-of-PlayerChangeBeaconEffectEvent.patch diff --git a/patches/server/0602-Fix-console-spam-when-removing-chests-in-water.patch b/patches/server/0603-Fix-console-spam-when-removing-chests-in-water.patch similarity index 100% rename from patches/server/0602-Fix-console-spam-when-removing-chests-in-water.patch rename to patches/server/0603-Fix-console-spam-when-removing-chests-in-water.patch diff --git a/patches/server/0603-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server/0604-Add-toggle-for-always-placing-the-dragon-egg.patch similarity index 100% rename from patches/server/0603-Add-toggle-for-always-placing-the-dragon-egg.patch rename to patches/server/0604-Add-toggle-for-always-placing-the-dragon-egg.patch diff --git a/patches/server/0604-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server/0605-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from patches/server/0604-Added-PlayerStonecutterRecipeSelectEvent.patch rename to patches/server/0605-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/patches/server/0605-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/server/0606-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from patches/server/0605-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/server/0606-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/patches/server/0606-Skip-distance-map-update-when-spawning-disabled.patch b/patches/server/0607-Skip-distance-map-update-when-spawning-disabled.patch similarity index 100% rename from patches/server/0606-Skip-distance-map-update-when-spawning-disabled.patch rename to patches/server/0607-Skip-distance-map-update-when-spawning-disabled.patch diff --git a/patches/server/0607-Reset-shield-blocking-on-dimension-change.patch b/patches/server/0608-Reset-shield-blocking-on-dimension-change.patch similarity index 100% rename from patches/server/0607-Reset-shield-blocking-on-dimension-change.patch rename to patches/server/0608-Reset-shield-blocking-on-dimension-change.patch diff --git a/patches/server/0608-add-DragonEggFormEvent.patch b/patches/server/0609-add-DragonEggFormEvent.patch similarity index 100% rename from patches/server/0608-add-DragonEggFormEvent.patch rename to patches/server/0609-add-DragonEggFormEvent.patch diff --git a/patches/server/0609-EntityMoveEvent.patch b/patches/server/0610-EntityMoveEvent.patch similarity index 100% rename from patches/server/0609-EntityMoveEvent.patch rename to patches/server/0610-EntityMoveEvent.patch diff --git a/patches/server/0610-added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server/0611-added-option-to-disable-pathfinding-updates-on-block.patch similarity index 100% rename from patches/server/0610-added-option-to-disable-pathfinding-updates-on-block.patch rename to patches/server/0611-added-option-to-disable-pathfinding-updates-on-block.patch diff --git a/patches/server/0611-Inline-shift-direction-fields.patch b/patches/server/0612-Inline-shift-direction-fields.patch similarity index 100% rename from patches/server/0611-Inline-shift-direction-fields.patch rename to patches/server/0612-Inline-shift-direction-fields.patch diff --git a/patches/server/0612-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server/0613-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from patches/server/0612-Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/server/0613-Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/patches/server/0613-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/server/0614-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from patches/server/0613-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/server/0614-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/patches/server/0614-living-entity-allow-attribute-registration.patch b/patches/server/0615-living-entity-allow-attribute-registration.patch similarity index 100% rename from patches/server/0614-living-entity-allow-attribute-registration.patch rename to patches/server/0615-living-entity-allow-attribute-registration.patch diff --git a/patches/server/0615-fix-dead-slime-setSize-invincibility.patch b/patches/server/0616-fix-dead-slime-setSize-invincibility.patch similarity index 100% rename from patches/server/0615-fix-dead-slime-setSize-invincibility.patch rename to patches/server/0616-fix-dead-slime-setSize-invincibility.patch diff --git a/patches/server/0616-Merchant-getRecipes-should-return-an-immutable-list.patch b/patches/server/0617-Merchant-getRecipes-should-return-an-immutable-list.patch similarity index 100% rename from patches/server/0616-Merchant-getRecipes-should-return-an-immutable-list.patch rename to patches/server/0617-Merchant-getRecipes-should-return-an-immutable-list.patch diff --git a/patches/server/0617-misc-debugging-dumps.patch b/patches/server/0618-misc-debugging-dumps.patch similarity index 100% rename from patches/server/0617-misc-debugging-dumps.patch rename to patches/server/0618-misc-debugging-dumps.patch diff --git a/patches/server/0618-Add-support-for-hex-color-codes-in-console.patch b/patches/server/0619-Add-support-for-hex-color-codes-in-console.patch similarity index 100% rename from patches/server/0618-Add-support-for-hex-color-codes-in-console.patch rename to patches/server/0619-Add-support-for-hex-color-codes-in-console.patch diff --git a/patches/server/0619-Expose-Tracked-Players.patch b/patches/server/0620-Expose-Tracked-Players.patch similarity index 100% rename from patches/server/0619-Expose-Tracked-Players.patch rename to patches/server/0620-Expose-Tracked-Players.patch diff --git a/patches/server/0620-Remove-streams-from-SensorNearest.patch b/patches/server/0621-Remove-streams-from-SensorNearest.patch similarity index 100% rename from patches/server/0620-Remove-streams-from-SensorNearest.patch rename to patches/server/0621-Remove-streams-from-SensorNearest.patch diff --git a/patches/server/0621-MC-29274-Fix-Wither-hostility-towards-players.patch b/patches/server/0622-MC-29274-Fix-Wither-hostility-towards-players.patch similarity index 100% rename from patches/server/0621-MC-29274-Fix-Wither-hostility-towards-players.patch rename to patches/server/0622-MC-29274-Fix-Wither-hostility-towards-players.patch diff --git a/patches/server/0622-Throw-proper-exception-on-empty-JsonList-file.patch b/patches/server/0623-Throw-proper-exception-on-empty-JsonList-file.patch similarity index 100% rename from patches/server/0622-Throw-proper-exception-on-empty-JsonList-file.patch rename to patches/server/0623-Throw-proper-exception-on-empty-JsonList-file.patch diff --git a/patches/server/0623-Improve-ServerGUI.patch b/patches/server/0624-Improve-ServerGUI.patch similarity index 100% rename from patches/server/0623-Improve-ServerGUI.patch rename to patches/server/0624-Improve-ServerGUI.patch diff --git a/patches/server/0624-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/patches/server/0625-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch similarity index 100% rename from patches/server/0624-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch rename to patches/server/0625-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch diff --git a/patches/server/0625-fix-converting-txt-to-json-file.patch b/patches/server/0626-fix-converting-txt-to-json-file.patch similarity index 100% rename from patches/server/0625-fix-converting-txt-to-json-file.patch rename to patches/server/0626-fix-converting-txt-to-json-file.patch diff --git a/patches/server/0626-Add-worldborder-events.patch b/patches/server/0627-Add-worldborder-events.patch similarity index 100% rename from patches/server/0626-Add-worldborder-events.patch rename to patches/server/0627-Add-worldborder-events.patch diff --git a/patches/server/0627-added-PlayerNameEntityEvent.patch b/patches/server/0628-added-PlayerNameEntityEvent.patch similarity index 100% rename from patches/server/0627-added-PlayerNameEntityEvent.patch rename to patches/server/0628-added-PlayerNameEntityEvent.patch diff --git a/patches/server/0628-Prevent-grindstones-from-overstacking-items.patch b/patches/server/0629-Prevent-grindstones-from-overstacking-items.patch similarity index 100% rename from patches/server/0628-Prevent-grindstones-from-overstacking-items.patch rename to patches/server/0629-Prevent-grindstones-from-overstacking-items.patch diff --git a/patches/server/0629-Add-recipe-to-cook-events.patch b/patches/server/0630-Add-recipe-to-cook-events.patch similarity index 100% rename from patches/server/0629-Add-recipe-to-cook-events.patch rename to patches/server/0630-Add-recipe-to-cook-events.patch diff --git a/patches/server/0630-Add-Block-isValidTool.patch b/patches/server/0631-Add-Block-isValidTool.patch similarity index 100% rename from patches/server/0630-Add-Block-isValidTool.patch rename to patches/server/0631-Add-Block-isValidTool.patch diff --git a/patches/server/0631-Allow-using-signs-inside-spawn-protection.patch b/patches/server/0632-Allow-using-signs-inside-spawn-protection.patch similarity index 100% rename from patches/server/0631-Allow-using-signs-inside-spawn-protection.patch rename to patches/server/0632-Allow-using-signs-inside-spawn-protection.patch diff --git a/patches/server/0632-Implement-Keyed-on-World.patch b/patches/server/0633-Implement-Keyed-on-World.patch similarity index 100% rename from patches/server/0632-Implement-Keyed-on-World.patch rename to patches/server/0633-Implement-Keyed-on-World.patch diff --git a/patches/server/0633-Add-fast-alternative-constructor-for-Rotations.patch b/patches/server/0634-Add-fast-alternative-constructor-for-Rotations.patch similarity index 100% rename from patches/server/0633-Add-fast-alternative-constructor-for-Rotations.patch rename to patches/server/0634-Add-fast-alternative-constructor-for-Rotations.patch diff --git a/patches/server/0634-Item-Rarity-API.patch b/patches/server/0635-Item-Rarity-API.patch similarity index 100% rename from patches/server/0634-Item-Rarity-API.patch rename to patches/server/0635-Item-Rarity-API.patch diff --git a/patches/server/0635-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/patches/server/0636-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch similarity index 100% rename from patches/server/0635-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch rename to patches/server/0636-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch diff --git a/patches/server/0636-copy-TESign-isEditable-from-snapshots.patch b/patches/server/0637-copy-TESign-isEditable-from-snapshots.patch similarity index 100% rename from patches/server/0636-copy-TESign-isEditable-from-snapshots.patch rename to patches/server/0637-copy-TESign-isEditable-from-snapshots.patch diff --git a/patches/server/0637-Drop-carried-item-when-player-has-disconnected.patch b/patches/server/0638-Drop-carried-item-when-player-has-disconnected.patch similarity index 100% rename from patches/server/0637-Drop-carried-item-when-player-has-disconnected.patch rename to patches/server/0638-Drop-carried-item-when-player-has-disconnected.patch diff --git a/patches/server/0638-forced-whitelist-use-configurable-kick-message.patch b/patches/server/0639-forced-whitelist-use-configurable-kick-message.patch similarity index 100% rename from patches/server/0638-forced-whitelist-use-configurable-kick-message.patch rename to patches/server/0639-forced-whitelist-use-configurable-kick-message.patch diff --git a/patches/server/0639-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/patches/server/0640-Don-t-ignore-result-of-PlayerEditBookEvent.patch similarity index 100% rename from patches/server/0639-Don-t-ignore-result-of-PlayerEditBookEvent.patch rename to patches/server/0640-Don-t-ignore-result-of-PlayerEditBookEvent.patch diff --git a/patches/server/0640-fix-cancelling-block-falling-causing-client-desync.patch b/patches/server/0641-fix-cancelling-block-falling-causing-client-desync.patch similarity index 100% rename from patches/server/0640-fix-cancelling-block-falling-causing-client-desync.patch rename to patches/server/0641-fix-cancelling-block-falling-causing-client-desync.patch diff --git a/patches/server/0641-Expose-protocol-version.patch b/patches/server/0642-Expose-protocol-version.patch similarity index 100% rename from patches/server/0641-Expose-protocol-version.patch rename to patches/server/0642-Expose-protocol-version.patch diff --git a/patches/server/0642-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/server/0643-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 100% rename from patches/server/0642-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to patches/server/0643-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch diff --git a/patches/server/0643-Enhance-console-tab-completions-for-brigadier-comman.patch b/patches/server/0644-Enhance-console-tab-completions-for-brigadier-comman.patch similarity index 100% rename from patches/server/0643-Enhance-console-tab-completions-for-brigadier-comman.patch rename to patches/server/0644-Enhance-console-tab-completions-for-brigadier-comman.patch diff --git a/patches/server/0644-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/patches/server/0645-Fix-PlayerItemConsumeEvent-cancelling-properly.patch similarity index 100% rename from patches/server/0644-Fix-PlayerItemConsumeEvent-cancelling-properly.patch rename to patches/server/0645-Fix-PlayerItemConsumeEvent-cancelling-properly.patch diff --git a/patches/server/0645-Add-bypass-host-check.patch b/patches/server/0646-Add-bypass-host-check.patch similarity index 100% rename from patches/server/0645-Add-bypass-host-check.patch rename to patches/server/0646-Add-bypass-host-check.patch diff --git a/patches/server/0646-Set-area-affect-cloud-rotation.patch b/patches/server/0647-Set-area-affect-cloud-rotation.patch similarity index 100% rename from patches/server/0646-Set-area-affect-cloud-rotation.patch rename to patches/server/0647-Set-area-affect-cloud-rotation.patch diff --git a/patches/server/0647-add-isDeeplySleeping-to-HumanEntity.patch b/patches/server/0648-add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from patches/server/0647-add-isDeeplySleeping-to-HumanEntity.patch rename to patches/server/0648-add-isDeeplySleeping-to-HumanEntity.patch diff --git a/patches/server/0648-Fix-duplicating-give-items-on-item-drop-cancel.patch b/patches/server/0649-Fix-duplicating-give-items-on-item-drop-cancel.patch similarity index 100% rename from patches/server/0648-Fix-duplicating-give-items-on-item-drop-cancel.patch rename to patches/server/0649-Fix-duplicating-give-items-on-item-drop-cancel.patch diff --git a/patches/server/0649-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/server/0650-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from patches/server/0649-add-consumeFuel-to-FurnaceBurnEvent.patch rename to patches/server/0650-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/patches/server/0650-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/server/0651-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from patches/server/0650-add-get-set-drop-chance-to-EntityEquipment.patch rename to patches/server/0651-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/patches/server/0651-fix-PigZombieAngerEvent-cancellation.patch b/patches/server/0652-fix-PigZombieAngerEvent-cancellation.patch similarity index 100% rename from patches/server/0651-fix-PigZombieAngerEvent-cancellation.patch rename to patches/server/0652-fix-PigZombieAngerEvent-cancellation.patch diff --git a/patches/server/0652-Fix-checkReach-check-for-Shulker-boxes.patch b/patches/server/0653-Fix-checkReach-check-for-Shulker-boxes.patch similarity index 100% rename from patches/server/0652-Fix-checkReach-check-for-Shulker-boxes.patch rename to patches/server/0653-Fix-checkReach-check-for-Shulker-boxes.patch diff --git a/patches/server/0653-fix-PlayerItemHeldEvent-firing-twice.patch b/patches/server/0654-fix-PlayerItemHeldEvent-firing-twice.patch similarity index 100% rename from patches/server/0653-fix-PlayerItemHeldEvent-firing-twice.patch rename to patches/server/0654-fix-PlayerItemHeldEvent-firing-twice.patch diff --git a/patches/server/0654-Added-PlayerDeepSleepEvent.patch b/patches/server/0655-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from patches/server/0654-Added-PlayerDeepSleepEvent.patch rename to patches/server/0655-Added-PlayerDeepSleepEvent.patch diff --git a/patches/server/0655-More-World-API.patch b/patches/server/0656-More-World-API.patch similarity index 100% rename from patches/server/0655-More-World-API.patch rename to patches/server/0656-More-World-API.patch diff --git a/patches/server/0656-Added-PlayerBedFailEnterEvent.patch b/patches/server/0657-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from patches/server/0656-Added-PlayerBedFailEnterEvent.patch rename to patches/server/0657-Added-PlayerBedFailEnterEvent.patch diff --git a/patches/server/0657-Implement-methods-to-convert-between-Component-and-B.patch b/patches/server/0658-Implement-methods-to-convert-between-Component-and-B.patch similarity index 100% rename from patches/server/0657-Implement-methods-to-convert-between-Component-and-B.patch rename to patches/server/0658-Implement-methods-to-convert-between-Component-and-B.patch diff --git a/patches/server/0658-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/patches/server/0659-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch similarity index 100% rename from patches/server/0658-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch rename to patches/server/0659-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch diff --git a/patches/server/0659-Introduce-beacon-activation-deactivation-events.patch b/patches/server/0660-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from patches/server/0659-Introduce-beacon-activation-deactivation-events.patch rename to patches/server/0660-Introduce-beacon-activation-deactivation-events.patch diff --git a/patches/server/0660-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/server/0661-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from patches/server/0660-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/server/0661-add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/patches/server/0661-Add-Channel-initialization-listeners.patch b/patches/server/0662-Add-Channel-initialization-listeners.patch similarity index 100% rename from patches/server/0661-Add-Channel-initialization-listeners.patch rename to patches/server/0662-Add-Channel-initialization-listeners.patch diff --git a/patches/server/0662-Send-empty-commands-if-tab-completion-is-disabled.patch b/patches/server/0663-Send-empty-commands-if-tab-completion-is-disabled.patch similarity index 100% rename from patches/server/0662-Send-empty-commands-if-tab-completion-is-disabled.patch rename to patches/server/0663-Send-empty-commands-if-tab-completion-is-disabled.patch diff --git a/patches/server/0663-Add-more-WanderingTrader-API.patch b/patches/server/0664-Add-more-WanderingTrader-API.patch similarity index 100% rename from patches/server/0663-Add-more-WanderingTrader-API.patch rename to patches/server/0664-Add-more-WanderingTrader-API.patch diff --git a/patches/server/0664-Add-EntityBlockStorage-clearEntities.patch b/patches/server/0665-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from patches/server/0664-Add-EntityBlockStorage-clearEntities.patch rename to patches/server/0665-Add-EntityBlockStorage-clearEntities.patch diff --git a/patches/server/0665-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/server/0666-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from patches/server/0665-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to patches/server/0666-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/patches/server/0666-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/server/0667-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from patches/server/0666-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/server/0667-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/patches/server/0667-Inventory-close.patch b/patches/server/0668-Inventory-close.patch similarity index 100% rename from patches/server/0667-Inventory-close.patch rename to patches/server/0668-Inventory-close.patch diff --git a/patches/server/0668-call-PortalCreateEvent-players-and-end-platform.patch b/patches/server/0669-call-PortalCreateEvent-players-and-end-platform.patch similarity index 100% rename from patches/server/0668-call-PortalCreateEvent-players-and-end-platform.patch rename to patches/server/0669-call-PortalCreateEvent-players-and-end-platform.patch diff --git a/patches/server/0669-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/server/0670-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 100% rename from patches/server/0669-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/server/0670-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch diff --git a/patches/server/0670-Fix-CraftPotionBrewer-cache.patch b/patches/server/0671-Fix-CraftPotionBrewer-cache.patch similarity index 100% rename from patches/server/0670-Fix-CraftPotionBrewer-cache.patch rename to patches/server/0671-Fix-CraftPotionBrewer-cache.patch diff --git a/patches/server/0671-Add-basic-Datapack-API.patch b/patches/server/0672-Add-basic-Datapack-API.patch similarity index 100% rename from patches/server/0671-Add-basic-Datapack-API.patch rename to patches/server/0672-Add-basic-Datapack-API.patch diff --git a/patches/server/0672-Add-environment-variable-to-disable-server-gui.patch b/patches/server/0673-Add-environment-variable-to-disable-server-gui.patch similarity index 100% rename from patches/server/0672-Add-environment-variable-to-disable-server-gui.patch rename to patches/server/0673-Add-environment-variable-to-disable-server-gui.patch diff --git a/patches/server/0673-additions-to-PlayerGameModeChangeEvent.patch b/patches/server/0674-additions-to-PlayerGameModeChangeEvent.patch similarity index 100% rename from patches/server/0673-additions-to-PlayerGameModeChangeEvent.patch rename to patches/server/0674-additions-to-PlayerGameModeChangeEvent.patch diff --git a/patches/server/0674-ItemStack-repair-check-API.patch b/patches/server/0675-ItemStack-repair-check-API.patch similarity index 100% rename from patches/server/0674-ItemStack-repair-check-API.patch rename to patches/server/0675-ItemStack-repair-check-API.patch diff --git a/patches/server/0675-More-Enchantment-API.patch b/patches/server/0676-More-Enchantment-API.patch similarity index 100% rename from patches/server/0675-More-Enchantment-API.patch rename to patches/server/0676-More-Enchantment-API.patch diff --git a/patches/server/0676-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/server/0677-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 100% rename from patches/server/0676-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to patches/server/0677-Add-command-line-option-to-load-extra-plugin-jars-no.patch diff --git a/patches/server/0677-Fix-and-optimise-world-force-upgrading.patch b/patches/server/0678-Fix-and-optimise-world-force-upgrading.patch similarity index 99% rename from patches/server/0677-Fix-and-optimise-world-force-upgrading.patch rename to patches/server/0678-Fix-and-optimise-world-force-upgrading.patch index 8b74933f38..ac027dc065 100644 --- a/patches/server/0677-Fix-and-optimise-world-force-upgrading.patch +++ b/patches/server/0678-Fix-and-optimise-world-force-upgrading.patch @@ -297,7 +297,7 @@ index 73ac55de9059a1d0f1da5bec0688dcd4bf5c8973..db2d6e7b2dc82c60d524dd2a018d28c2 if (dimensionKey == LevelStem.OVERWORLD) { diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index febc4fececb4bf527a69e47a06d782ec81616c1e..ccf6c79293ca046174b94a61a28aea3fa9c2a37f 100644 +index c820cc7f3be693f445937a157ac2477e36f906b4..ac7d3da1ca3b41e37daacb13865667614fde321b 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -174,6 +174,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable { diff --git a/patches/server/0678-Add-Mob-lookAt-API.patch b/patches/server/0679-Add-Mob-lookAt-API.patch similarity index 100% rename from patches/server/0678-Add-Mob-lookAt-API.patch rename to patches/server/0679-Add-Mob-lookAt-API.patch diff --git a/patches/server/0679-Add-Unix-domain-socket-support.patch b/patches/server/0680-Add-Unix-domain-socket-support.patch similarity index 100% rename from patches/server/0679-Add-Unix-domain-socket-support.patch rename to patches/server/0680-Add-Unix-domain-socket-support.patch diff --git a/patches/server/0680-Add-EntityInsideBlockEvent.patch b/patches/server/0681-Add-EntityInsideBlockEvent.patch similarity index 100% rename from patches/server/0680-Add-EntityInsideBlockEvent.patch rename to patches/server/0681-Add-EntityInsideBlockEvent.patch diff --git a/patches/server/0681-Attributes-API-for-item-defaults.patch b/patches/server/0682-Attributes-API-for-item-defaults.patch similarity index 100% rename from patches/server/0681-Attributes-API-for-item-defaults.patch rename to patches/server/0682-Attributes-API-for-item-defaults.patch diff --git a/patches/server/0682-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/patches/server/0683-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch similarity index 100% rename from patches/server/0682-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch rename to patches/server/0683-Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch diff --git a/patches/server/0683-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/server/0684-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from patches/server/0683-Add-cause-to-Weather-ThunderChangeEvents.patch rename to patches/server/0684-Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/patches/server/0684-More-Lidded-Block-API.patch b/patches/server/0685-More-Lidded-Block-API.patch similarity index 100% rename from patches/server/0684-More-Lidded-Block-API.patch rename to patches/server/0685-More-Lidded-Block-API.patch diff --git a/patches/server/0685-Limit-item-frame-cursors-on-maps.patch b/patches/server/0686-Limit-item-frame-cursors-on-maps.patch similarity index 100% rename from patches/server/0685-Limit-item-frame-cursors-on-maps.patch rename to patches/server/0686-Limit-item-frame-cursors-on-maps.patch diff --git a/patches/server/0686-Add-PufferFishStateChangeEvent.patch b/patches/server/0687-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from patches/server/0686-Add-PufferFishStateChangeEvent.patch rename to patches/server/0687-Add-PufferFishStateChangeEvent.patch diff --git a/patches/server/0687-Add-PlayerKickEvent-causes.patch b/patches/server/0688-Add-PlayerKickEvent-causes.patch similarity index 100% rename from patches/server/0687-Add-PlayerKickEvent-causes.patch rename to patches/server/0688-Add-PlayerKickEvent-causes.patch diff --git a/patches/server/0688-Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/patches/server/0689-Fix-PlayerBucketEmptyEvent-result-itemstack.patch similarity index 100% rename from patches/server/0688-Fix-PlayerBucketEmptyEvent-result-itemstack.patch rename to patches/server/0689-Fix-PlayerBucketEmptyEvent-result-itemstack.patch diff --git a/patches/server/0689-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch b/patches/server/0690-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch similarity index 100% rename from patches/server/0689-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch rename to patches/server/0690-Synchronize-PalettedContainer-instead-of-ReentrantLo.patch diff --git a/patches/server/0690-Add-option-to-fix-items-merging-through-walls.patch b/patches/server/0691-Add-option-to-fix-items-merging-through-walls.patch similarity index 100% rename from patches/server/0690-Add-option-to-fix-items-merging-through-walls.patch rename to patches/server/0691-Add-option-to-fix-items-merging-through-walls.patch diff --git a/patches/server/0691-Add-BellRevealRaiderEvent.patch b/patches/server/0692-Add-BellRevealRaiderEvent.patch similarity index 100% rename from patches/server/0691-Add-BellRevealRaiderEvent.patch rename to patches/server/0692-Add-BellRevealRaiderEvent.patch diff --git a/patches/server/0692-Fix-invulnerable-end-crystals.patch b/patches/server/0693-Fix-invulnerable-end-crystals.patch similarity index 100% rename from patches/server/0692-Fix-invulnerable-end-crystals.patch rename to patches/server/0693-Fix-invulnerable-end-crystals.patch diff --git a/patches/server/0693-Add-ElderGuardianAppearanceEvent.patch b/patches/server/0694-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from patches/server/0693-Add-ElderGuardianAppearanceEvent.patch rename to patches/server/0694-Add-ElderGuardianAppearanceEvent.patch diff --git a/patches/server/0694-Reset-villager-inventory-on-cancelled-pickup-event.patch b/patches/server/0695-Reset-villager-inventory-on-cancelled-pickup-event.patch similarity index 100% rename from patches/server/0694-Reset-villager-inventory-on-cancelled-pickup-event.patch rename to patches/server/0695-Reset-villager-inventory-on-cancelled-pickup-event.patch diff --git a/patches/server/0695-Fix-dangerous-end-portal-logic.patch b/patches/server/0696-Fix-dangerous-end-portal-logic.patch similarity index 100% rename from patches/server/0695-Fix-dangerous-end-portal-logic.patch rename to patches/server/0696-Fix-dangerous-end-portal-logic.patch diff --git a/patches/server/0696-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/server/0697-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch similarity index 100% rename from patches/server/0696-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch rename to patches/server/0697-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch diff --git a/patches/server/0697-Make-item-validations-configurable.patch b/patches/server/0698-Make-item-validations-configurable.patch similarity index 100% rename from patches/server/0697-Make-item-validations-configurable.patch rename to patches/server/0698-Make-item-validations-configurable.patch diff --git a/patches/server/0698-Add-more-line-of-sight-methods.patch b/patches/server/0699-Add-more-line-of-sight-methods.patch similarity index 100% rename from patches/server/0698-Add-more-line-of-sight-methods.patch rename to patches/server/0699-Add-more-line-of-sight-methods.patch diff --git a/patches/server/0699-add-per-world-spawn-limits.patch b/patches/server/0700-add-per-world-spawn-limits.patch similarity index 96% rename from patches/server/0699-add-per-world-spawn-limits.patch rename to patches/server/0700-add-per-world-spawn-limits.patch index 4bfb3570ac..b5bb36f0e0 100644 --- a/patches/server/0699-add-per-world-spawn-limits.patch +++ b/patches/server/0700-add-per-world-spawn-limits.patch @@ -6,7 +6,7 @@ Subject: [PATCH] add per world spawn limits Taken from #2982. Credit to Chasewhip8 diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 31be320d7d4cf8659d2d4281186b3f0d424a99e1..cc2d40ba72a904baf2c39cd011cf7e1c746b2ca9 100644 +index 43ab68f1822e92973e57a40f63376b467df3bdc7..c7bf1926bf2e02aae02585681c974f8e2f66d7c5 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -602,6 +602,19 @@ public class PaperWorldConfig { diff --git a/patches/server/0700-Fix-PotionSplashEvent-for-water-splash-potions.patch b/patches/server/0701-Fix-PotionSplashEvent-for-water-splash-potions.patch similarity index 100% rename from patches/server/0700-Fix-PotionSplashEvent-for-water-splash-potions.patch rename to patches/server/0701-Fix-PotionSplashEvent-for-water-splash-potions.patch diff --git a/patches/server/0701-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/patches/server/0702-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch similarity index 100% rename from patches/server/0701-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch rename to patches/server/0702-Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch From 9abef9c8054eea50f8fcaa5a291bba4b5d0b1e31 Mon Sep 17 00:00:00 2001 From: Kyle Wood Date: Tue, 15 Jun 2021 11:46:55 -0500 Subject: [PATCH 161/226] Disable Gradle file system watching by default It's unclear if this will help anything but we are getting a lot of issues with the daemon holdong on to files between builds and causing issues. --- gradle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/gradle.properties b/gradle.properties index 947f7fcfef..623b006fac 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,3 +5,4 @@ mcVersion = 1.17 packageVersion = 1_17_R1 org.gradle.parallel=true +org.gradle.vfs.watch=false From 4cbb187af5a1feded173ce7ca8baf40a425b0cdf Mon Sep 17 00:00:00 2001 From: KennyTV Date: Tue, 15 Jun 2021 19:34:04 +0200 Subject: [PATCH 162/226] Add note on removed patch --- .../1.17/0438-Workaround-for-Client-Lag-Spikes-MC-162253.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/removed/1.17/0438-Workaround-for-Client-Lag-Spikes-MC-162253.patch b/patches/removed/1.17/0438-Workaround-for-Client-Lag-Spikes-MC-162253.patch index bacdd2ea36..f5780c7a9a 100644 --- a/patches/removed/1.17/0438-Workaround-for-Client-Lag-Spikes-MC-162253.patch +++ b/patches/removed/1.17/0438-Workaround-for-Client-Lag-Spikes-MC-162253.patch @@ -11,7 +11,7 @@ This patch basically serves as a workaround by sending light maps to the client, so that it doesn't attempt to calculate them. This mitigates the frametime impact to a minimum (but it's still there). -1.17 update note: Line sending the light update packet needs updating, rest seems to be mostly fine +1.17 UPDATE NOTE: More or less untested, mapped version of the patch: https://paste.gg/p/anonymous/594123c7ce7d4d398d8834af6ba386d1 diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java index d8f99f7f5ca0e1dbbb9b760af3a4b4f9c52ef6c7..f700ac973ebc3037a5a44eac3c9d505b98adce41 100644 From 90546c7c50f684117ab0c9f5caa6888e2e26a19d Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Tue, 15 Jun 2021 21:44:22 +0200 Subject: [PATCH 163/226] start adding in ATs --- build-data/paper.at | 13 +++++ .../0211-Improve-EntityShootBowEvent.patch | 52 ------------------- ...36-Implement-Expanded-ArmorStand-API.patch | 13 ----- ...59-Asynchronous-chunk-IO-and-loading.patch | 17 +----- patches/server/0332-Chunk-debug-command.patch | 15 +----- ...hunkMap-memory-use-for-visibleChunks.patch | 4 +- 6 files changed, 18 insertions(+), 96 deletions(-) diff --git a/build-data/paper.at b/build-data/paper.at index e1f52762aa..84637b2535 100644 --- a/build-data/paper.at +++ b/build-data/paper.at @@ -4,6 +4,7 @@ # This line would make the field public and remove the final modifier #public-f net.minecraft.network.protocol.game.ClientboundChatPacket sender # Leave out the member and it will apply to the class itself +# More info, see here https://mcforge.readthedocs.io/en/latest/advanced/accesstransformers/#access-modifiers # Item Rarity API public net.minecraft.world.item.Item rarity @@ -16,3 +17,15 @@ public net.minecraft.util.worldupdate.WorldUpgrader REGEX # More Lidded Block API public net.minecraft.world.level.block.entity.EnderChestBlockEntity openersCounter + +# Improve EntityShootBowEvent +public net.minecraft.world.entity.projectile.AbstractArrow getPickupItem()Lnet.minecraft.world.item.ItemStack; + +# Implement Expanded ArmorStand API +public net.minecraft.world.entity.decoration.ArmorStand isDisabled(Lnet/minecraft/world/entity/EquipmentSlot;)Z + +# Asynchronous chunk IO and loading +public net.minecraft.util.thread.BlockableEventLoop runAllTasks()V + +# Chunk debug command +public net.minecraft.server.level.ChunkMap entitiesInLevel diff --git a/patches/server/0211-Improve-EntityShootBowEvent.patch b/patches/server/0211-Improve-EntityShootBowEvent.patch index fa63c641cd..96f7dc144f 100644 --- a/patches/server/0211-Improve-EntityShootBowEvent.patch +++ b/patches/server/0211-Improve-EntityShootBowEvent.patch @@ -42,55 +42,3 @@ index ff38ad2ac16ff49a290976e392175e96fa986925..c9fa01b910de7ecb494d3000afebea9a } @Override -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 71f0de893fe0243cc226fd36685f2a3fba02575f..988986d549dae93cfcb8147126c84f263efe3452 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -586,7 +586,7 @@ public abstract class AbstractArrow extends Projectile { - } - } - -- protected abstract ItemStack getPickupItem(); -+ public abstract ItemStack getPickupItem(); // Paper - protected -> public - - @Override - protected Entity.MovementEmission getMovementEmission() { -diff --git a/src/main/java/net/minecraft/world/entity/projectile/Arrow.java b/src/main/java/net/minecraft/world/entity/projectile/Arrow.java -index 1b71df52df1e1d408d2cdf5bef5fbea95fdced80..c0a3bfde24ef5e4b9c1bb1c0b8fbffdde3604513 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/Arrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/Arrow.java -@@ -244,7 +244,7 @@ public class Arrow extends AbstractArrow { - } - - @Override -- protected ItemStack getPickupItem() { -+ public ItemStack getPickupItem() { // Paper - protected -> public - if (this.effects.isEmpty() && this.potion == Potions.EMPTY) { - return new ItemStack(Items.ARROW); - } else { -diff --git a/src/main/java/net/minecraft/world/entity/projectile/SpectralArrow.java b/src/main/java/net/minecraft/world/entity/projectile/SpectralArrow.java -index 4f62f72d125504602d4b0278119247d36d58b3c9..f6081e0fdf71d6b2b80c94f2ffd3395c08fb84a7 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/SpectralArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/SpectralArrow.java -@@ -36,7 +36,7 @@ public class SpectralArrow extends AbstractArrow { - } - - @Override -- protected ItemStack getPickupItem() { -+ public ItemStack getPickupItem() { // Paper - protected -> public - return new ItemStack(Items.SPECTRAL_ARROW); - } - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java -index 04c6c3bf372186182b91a03e11dba0495357393d..227cb0834a075cbe2db136bf6dc9820d2a04c458 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java -@@ -98,7 +98,7 @@ public class ThrownTrident extends AbstractArrow { - } - - @Override -- protected ItemStack getPickupItem() { -+ public ItemStack getPickupItem() { // Paper - protected -> public - return this.tridentItem.copy(); - } - diff --git a/patches/server/0236-Implement-Expanded-ArmorStand-API.patch b/patches/server/0236-Implement-Expanded-ArmorStand-API.patch index 9db2b90a04..ace889510d 100644 --- a/patches/server/0236-Implement-Expanded-ArmorStand-API.patch +++ b/patches/server/0236-Implement-Expanded-ArmorStand-API.patch @@ -7,19 +7,6 @@ Add the following: - Add proper methods for getting and setting items in both hands. Deprecates old methods - Enable/Disable slot interactions -diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 33f1e486f3732c156289b16d973297e771da82b9..4adde11daa5ca97a2bf9c164c43c5c011a89b33d 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -428,7 +428,7 @@ public class ArmorStand extends LivingEntity { - return enumitemslot; - } - -- private boolean isDisabled(net.minecraft.world.entity.EquipmentSlot slot) { -+ public boolean isDisabled(net.minecraft.world.entity.EquipmentSlot slot) { // Paper - private -> public - return (this.disabledSlots & 1 << slot.getFilterFlag()) != 0 || slot.getType() == net.minecraft.world.entity.EquipmentSlot.Type.HAND && !this.isShowArms(); - } - diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java index 82b9ee993b0d2e7e0685231f7bad2b85756ec959..f4065938bbfd04519d1363ee8781c316aca468ab 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java diff --git a/patches/server/0259-Asynchronous-chunk-IO-and-loading.patch b/patches/server/0259-Asynchronous-chunk-IO-and-loading.patch index f362446c4e..8498e4d2a8 100644 --- a/patches/server/0259-Asynchronous-chunk-IO-and-loading.patch +++ b/patches/server/0259-Asynchronous-chunk-IO-and-loading.patch @@ -2357,7 +2357,7 @@ index ce4296ab7e6f1ccc735d619eacabdf2ef2f4e361..00f5cd29170e3594fe2ac194e04e403c completablefuture = (CompletableFuture) this.futures.get(i); if (completablefuture == null) { diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index a0f8f341e0cd6a2ac28e12d0824b694ac4fbc7ae..95ac30f56a9268f14d2518974c5a52e08f40ea18 100644 +index 64304bf9fc60332d9a17194660d3a34c853a36c6..c096c2fecc6ab74255b305a7eee045bedaab44ae 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -115,7 +115,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -2970,7 +2970,7 @@ index 0d536d72ac918fbd403397ff369d10143ee9c204..be677d437d17b74c6188ce1bd5fc6fdc private final String name; private final Comparator comparator; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index b65fcc7519589c3bc5c5f5b5ec1db53a520ec39f..a29b8c83be940e4b3db06d881b59b03120e931ab 100644 +index 1c76d6a616d6967402fb55feffafffa0aa2fd468..2917632c5e974dbfb7d78c497ebd49e742b8ef3c 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -712,6 +712,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @@ -2987,19 +2987,6 @@ index b65fcc7519589c3bc5c5f5b5ec1db53a520ec39f..a29b8c83be940e4b3db06d881b59b031 // CraftBukkit end StringReader stringreader = new StringReader(packet.getCommand()); -diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -index 5b38966093fe60b298844961d015d5a9f03412a2..0ef3c4982df88a7991a56d983ac733daa8adc507 100644 ---- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -+++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -@@ -106,7 +106,7 @@ public abstract class BlockableEventLoop implements Profiler - this.pendingRunnables.clear(); - } - -- protected void runAllTasks() { -+ public void runAllTasks() { // Paper - protected -> public - while(this.pollTask()) { - } - diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java index 3ca8b13744b406c3e563747f0cb69647c94103df..6c3455823f996e0421975b7f4a00f4e333e9f514 100644 --- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java diff --git a/patches/server/0332-Chunk-debug-command.patch b/patches/server/0332-Chunk-debug-command.patch index fc2006bbbd..e5149d9026 100644 --- a/patches/server/0332-Chunk-debug-command.patch +++ b/patches/server/0332-Chunk-debug-command.patch @@ -441,19 +441,6 @@ index 84831fc611589c19320b5e3af107080596b1fbdc..fa6d91886d433c0b7d77c1d059a23ee1 private boolean hasChangedSections; private final ShortSet[] changedBlocksPerSection; private final BitSet blockChangedLightSectionFilter; -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 95ac30f56a9268f14d2518974c5a52e08f40ea18..25826b41812f2d9ac29806ad7a9242e5674376fc 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -110,7 +110,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); - public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; - private final Long2ObjectLinkedOpenHashMap pendingUnloads; -- private final LongSet entitiesInLevel; -+ public final LongSet entitiesInLevel; // Paper - private -> public - public final ServerLevel level; - private final ThreadedLevelLightEngine lightEngine; - private final BlockableEventLoop mainThreadExecutor; diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java index 71ac5cf0fdedcfe422bf6f5e6ffb15ce4138aa04..77bb2fb280293da4a38f9acc6503e84997ecb399 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -468,7 +455,7 @@ index 71ac5cf0fdedcfe422bf6f5e6ffb15ce4138aa04..77bb2fb280293da4a38f9acc6503e849 public final ChunkGenerator generator; final ServerLevel level; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index c778ce951c1ca648faa5d6c02b331d34ffc71156..1e09fdfbc1a8f1014ad0f7c5db7c709fc454270e 100644 +index 6631a2b8cf99993d727d65a67af2bc7febb685b4..08b4e46109eb97746d0204e3797ebafce959b212 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -174,7 +174,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0393-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/0393-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch index 2eaf2e2ef7..c1310193c4 100644 --- a/patches/server/0393-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch +++ b/patches/server/0393-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch @@ -70,7 +70,7 @@ index 9c88426ab1275ee5fb6e28be8b213533dc4ab859..87c9a5c1b43f6010898d72136b5eb997 List allChunks = new ArrayList<>(visibleChunks.values()); List players = world.players; diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 002561c87ddd03e8bc31864ddd9dee7bc2ff0931..a80c4517cd0d2c5e7b71b4f86b6a8d441a9eb64e 100644 +index acc30f1ff6a3a9c067e312dc7b6b6fc6bc6904fe..0882552526d4de189f3af8b72653d776cb596859 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -107,9 +107,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -110,7 +110,7 @@ index 002561c87ddd03e8bc31864ddd9dee7bc2ff0931..a80c4517cd0d2c5e7b71b4f86b6a8d44 + // public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); // Paper - moved up + // public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; // Paper - moved up private final Long2ObjectLinkedOpenHashMap pendingUnloads; - public final LongSet entitiesInLevel; // Paper - private -> public + public final LongSet entitiesInLevel; public final ServerLevel level; @@ -232,7 +259,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider From 3fb6b93f96ff582f07547cb7bfbfca1b72778986 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Wed, 16 Jun 2021 00:24:12 +0200 Subject: [PATCH 164/226] AT bullshit --- build-data/paper.at | 147 ++++++++++++++++++ patches/server/0004-Paper-config-files.patch | 49 +----- patches/server/0006-MC-Utils.patch | 98 ++---------- .../0042-Add-PlayerInitialSpawnEvent.patch | 13 -- .../server/0058-Chunk-Save-Reattempt.patch | 6 +- ...062-Handle-Item-Meta-Inconsistencies.patch | 8 +- ...egionFileCache-and-make-configurable.patch | 4 +- ...0076-Add-PlayerUseUnknownEntityEvent.patch | 13 +- .../0085-Configurable-RCON-IP-address.patch | 13 -- ...-API-Replenishable-Lootables-Feature.patch | 39 +---- patches/server/0123-Firework-API-s.patch | 8 +- ...ke-parrots-stay-on-shoulders-despite.patch | 13 +- .../server/0153-LivingEntity-setKiller.patch | 15 +- ...0204-ItemStack-getMaxItemUseDuration.patch | 4 +- .../server/0234-SkeletonHorse-Additions.patch | 13 -- ...on-t-call-getItemMeta-on-hasItemMeta.patch | 4 +- ...ient-rendering-skulls-from-same-user.patch | 13 -- ...59-Asynchronous-chunk-IO-and-loading.patch | 75 ++------- .../server/0262-Improve-death-events.patch | 25 +-- patches/server/0274-Add-sun-related-API.patch | 13 -- ...275-Add-LivingEntity-getTargetEntity.patch | 8 +- patches/server/0276-Turtle-API.patch | 35 +---- ...tator-target-events-and-improve-impl.patch | 13 +- patches/server/0282-Here-s-Johnny.patch | 4 +- ...er-Thread-Pool-and-Thread-Priorities.patch | 11 +- ...entity-dismount-during-teleportation.patch | 10 +- patches/server/0297-Add-more-Zombie-API.patch | 16 +- .../0299-Add-PlayerConnectionCloseEvent.patch | 11 +- patches/server/0332-Chunk-debug-command.patch | 17 +- ...333-Fix-World-isChunkGenerated-calls.patch | 36 +---- ...revent-consuming-the-wrong-itemstack.patch | 8 +- .../server/0357-Lag-compensate-eating.patch | 12 +- .../0361-Entity-Activation-Range-2.0.patch | 30 +--- patches/server/0363-Fix-Light-Command.patch | 15 +- patches/server/0364-Anti-Xray.patch | 6 +- ...No-Tick-view-distance-implementation.patch | 37 +++-- patches/server/0376-Entity-Jump-API.patch | 4 +- ...-chance-of-villager-zombie-infection.patch | 6 +- ...-PlayerChunkMap-adds-crashing-server.patch | 6 +- ...hunkMap-memory-use-for-visibleChunks.patch | 6 +- ...move-existing-players-to-world-spawn.patch | 11 +- ...Add-Raw-Byte-ItemStack-Serialization.patch | 4 +- ...99-Remove-streams-from-Mob-AI-System.patch | 4 +- ...-entity-collision-code-if-not-needed.patch | 4 +- ...-Implement-Player-Client-Options-API.patch | 15 +- ...g-Broken-behavior-of-PlayerJoinEvent.patch | 13 +- ...Load-Chunks-for-Login-Asynchronously.patch | 21 +-- ...PlayerAttackEntityCooldownResetEvent.patch | 4 +- .../server/0428-Implement-Mob-Goal-API.patch | 21 +-- .../0431-Add-villager-reputation-API.patch | 11 +- ...k-Priority-Urgency-System-for-Chunks.patch | 12 +- .../server/0478-Add-entity-liquid-API.patch | 18 +-- ...llow-delegation-to-vanilla-chunk-gen.patch | 13 -- ...k-for-portal-on-world-gen-entity-add.patch | 4 +- .../0509-Optimize-redstone-algorithm.patch | 11 +- patches/server/0513-Add-more-Evoker-API.patch | 19 --- .../server/0550-Add-Destroy-Speed-API.patch | 4 +- patches/server/0554-More-lightning-API.patch | 16 -- ...-should-not-bypass-cramming-gamerule.patch | 14 +- ...ld-settings-for-mobs-picking-up-loot.patch | 4 +- ...onfigurable-door-breaking-difficulty.patch | 22 +-- patches/server/0610-EntityMoveEvent.patch | 6 +- ...ItemConsumeEvent-cancelling-properly.patch | 4 +- ...x-and-optimise-world-force-upgrading.patch | 4 +- .../0699-Add-more-line-of-sight-methods.patch | 4 +- 65 files changed, 340 insertions(+), 787 deletions(-) diff --git a/build-data/paper.at b/build-data/paper.at index 84637b2535..98e0759000 100644 --- a/build-data/paper.at +++ b/build-data/paper.at @@ -6,6 +6,152 @@ # Leave out the member and it will apply to the class itself # More info, see here https://mcforge.readthedocs.io/en/latest/advanced/accesstransformers/#access-modifiers +# Paper config files +public org.spigotmc.SpigotWorldConfig getBoolean(Ljava/lang/String;Z)Z +public org.spigotmc.SpigotWorldConfig getDouble(Ljava/lang/String;)D +public org.spigotmc.SpigotWorldConfig getDouble(Ljava/lang/String;D)D +public org.spigotmc.SpigotWorldConfig getInt(Ljava/lang/String;)I +public org.spigotmc.SpigotWorldConfig getInt(Ljava/lang/String;I)I +public org.spigotmc.SpigotWorldConfig getList(Ljava/lang/String;Ljava/lang/Object;)Ljava/util/List; +public org.spigotmc.SpigotWorldConfig getString(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + +# MC Utils +public net.minecraft.core.Vec3i setX(I)Lnet/minecraft/core/Vec3i; +public net.minecraft.core.Vec3i setY(I)Lnet/minecraft/core/Vec3i; +public net.minecraft.core.Vec3i setZ(I)Lnet/minecraft/core/Vec3i; +public net.minecraft.server.level.ServerChunkCache mainThread +public net.minecraft.server.level.ServerLevel chunkSource +public org.bukkit.craftbukkit.inventory.CraftItemStack handle + +# Add PlayerInitialSpawnEvent +public net.minecraft.world.entity.Entity setRot(FF)V + +# Add PlayerUseUnknownEntityEvent +public net.minecraft.network.protocol.game.ServerboundInteractPacket$ActionType + +# Configurable RCON IP address +public net.minecraft.server.dedicated.Settings getStringRaw(Ljava/lang/String;)Ljava/lang/String; + +# LootTable API +public org.bukkit.craftbukkit.block.CraftBlockEntityState getTileEntity()Lnet/minecraft/world/level/block/entity/BlockEntity; +public org.bukkit.craftbukkit.block.CraftLootable setLootTable(Lorg/bukkit/loot/LootTable;J)V +public org.bukkit.craftbukkit.entity.CraftMinecartContainer setLootTable(Lorg/bukkit/loot/LootTable;J)V + +# Firework API +public net.minecraft.world.entity.projectile.FireworkRocketEntity attachedToEntity + +# Add option to make parrots stay +public net.minecraft.world.entity.player.Player removeEntitiesOnShoulder()V + +# LivingEntity setkiller +public net.minecraft.world.entity.LivingEntity lastHurtByPlayerTime + +# SkeletonHore Addittions +public net.minecraft.world.entity.animal.horse.SkeletonHorse trapTime + +# Fix client rendering skulls +public net.minecraft.world.item.ItemStack tag + +# Async chunk io +public net.minecraft.server.level.ChunkMap structureManager +public net.minecraft.server.level.ChunkMap getUpdatingChunkIfPresent(J)Lnet/minecraft/server/level/ChunkHolder; +public net.minecraft.server.level.ChunkMap getVisibleChunkIfPresent(J)Lnet/minecraft/server/level/ChunkHolder; +public net.minecraft.server.level.ServerChunkCache mainThreadProcessor +public-f net.minecraft.world.level.chunk.storage.RegionFileStorage +public net.minecraft.world.level.chunk.storage.RegionFileStorage getFile(Lnet/minecraft/world/level/ChunkPos;Z)Lnet/minecraft/world/level/chunk/storage/RegionFile; +public net.minecraft.world.level.chunk.storage.SectionStorage dirty + +# Improve death events +public net.minecraft.world.entity.LivingEntity getDeathSound()Lnet/minecraft/sounds/SoundEvent; +public net.minecraft.world.entity.LivingEntity getSoundVolume()F +public net.minecraft.world.entity.ambient.Bat getSoundVolume()F +public net.minecraft.world.entity.monster.Ghast getSoundVolume()F +public net.minecraft.world.entity.monster.Phantom getSoundVolume()F +public net.minecraft.world.entity.animal.Squid getSoundVolume()F +public net.minecraft.world.entity.animal.Wolf getSoundVolume()F + +# Add sun related api +public net.minecraft.world.entity.Mob isSunBurnTick()Z + +# Turtle API +public net.minecraft.world.entity.animal.Turtle getHomePos()Lnet/minecraft/core/BlockPos; +public net.minecraft.world.entity.animal.Turtle setHasEgg(Z)V +public net.minecraft.world.entity.animal.Turtle isGoingHome()Z +public net.minecraft.world.entity.animal.Turtle setGoingHome(Z)V +public net.minecraft.world.entity.animal.Turtle isTravelling()Z +public net.minecraft.world.entity.animal.Turtle setTravelling(Z)V + +# Call player spectator target event +public net.minecraft.server.network.ServerGamePacketListenerImpl a(Ljava/util/List;Ljava/util/function/UnaryOperator;Lnet/minecraft/world/item/ItemStack;ILnet/minecraft/world/item/ItemStack;)V # todo fix this mapping + +# Improve Server THread Pool +public net.minecraft.Util onThreadException(Ljava/lang/Thread;Ljava/lang/Throwable;)V + +# Add more zombie API +public net.minecraft.world.entity.monster.Zombie isSunSensitive()Z + +# Add PlayerConnectionCloseEvent +public net.minecraft.server.network.ServerLoginPacketListenerImpl$State + +# Entity Activation Range 2.0 +public net.minecraft.world.entity.Entity isInsidePortal +public net.minecraft.world.entity.Mob leashHolder + +# No-Tick view distance +public net.minecraft.server.level.ChunkHolder broadcast(Lnet/minecraft/network/protocol/Packet;Z)V +public net.minecraft.server.level.ChunkMap setViewDistance(I)V +public net.minecraft.server.level.ChunkMap readChunk(Lnet/minecraft/world/level/ChunkPos;)Lnet/minecraft/nbt/CompoundTag; +public net.minecraft.server.level.ChunkMap playerLoadedChunk(Lnet/minecraft/server/level/ServerPlayer;[Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/world/level/chunk/LevelChunk;)V +public net.minecraft.server.level.ChunkMap mainThreadMailbox # todo one of these doesn't belong here + +# Optimise TickListServer +public net.minecraft.world.level.ServerTickList saveTickList(Ljava/util/function/Function;Ljava/lang/Iterable;J)Lnet/minecraft/nbt/ListTag; + +# Don't move existing players to world spawn +public net.minecraft.server.level.ServerPlayer fudgeSpawnLocation(Lnet/minecraft/server/level/ServerLevel;)V + +# Implement Player Client Options API +public net.minecraft.world.entity.player.Player DATA_PLAYER_MODE_CUSTOMISATION + +# Fix Longstanding Broken behavior +public net.minecraft.server.level.ChunkMap addEntity(Lnet/minecraft/world/entity/Entity;)V + +# Load Chunks for Login Async +public net.minecraft.server.level.ServerChunkCache runDistanceManagerUpdates()Z +public net.minecraft.server.level.ServerChunkCache$MainThreadExecutor # todo doesn't belong here but oh well + +# Implement MobGoalApi +public net.minecraft.world.entity.ai.goal.GoalSelector availableGoals + +# Add villager reputation API +public net.minecraft.world.entity.ai.gossip.GossipContainer$EntityGossips +public net.minecraft.world.entity.ai.gossip.GossipContainer$EntityGossips ()V + +# Add entity liquid API +public net.minecraft.world.entity.Entity isInRain()Z +public net.minecraft.world.entity.Entity isInBubbleColumn()Z + +# Allow delegation to vanilla chunk gen +public org.bukkit.craftbukkit.generator.CustomChunkGenerator delegate + +# Optimize redstone algorithm +public net.minecraft.world.level.block.RedStoneWireBlock shouldSignal + +# Add more Evoker API +public net.minecraft.world.entity.monster.Evoker setWololoTarget(Lnet/minecraft/world/entity/animal/Sheep;)V +public net.minecraft.world.entity.monster.Evoker getWololoTarget()Lnet/minecraft/world/entity/animal/Sheep; + +# More lightning API +public net.minecraft.world.entity.LightningBolt life +public net.minecraft.world.entity.LightningBolt flashes + +# Configurable door breaking difficulty +public net.minecraft.world.entity.monster.Vindicator DOOR_BREAKING_PREDICATE +public net.minecraft.world.entity.monster.Zombie DOOR_BREAKING_PREDICATE + +# Optimize sending packets to nearby locations (sounds/effects) +public net.minecraft.server.level.ServerLevel players + # Item Rarity API public net.minecraft.world.item.Item rarity @@ -29,3 +175,4 @@ public net.minecraft.util.thread.BlockableEventLoop runAllTasks()V # Chunk debug command public net.minecraft.server.level.ChunkMap entitiesInLevel +public net.minecraft.server.level.ServerLevel players diff --git a/patches/server/0004-Paper-config-files.patch b/patches/server/0004-Paper-config-files.patch index ce5199bb6b..a5cbd775b7 100644 --- a/patches/server/0004-Paper-config-files.patch +++ b/patches/server/0004-Paper-config-files.patch @@ -620,7 +620,7 @@ index 7bad75bd86fcb484e253fca8077d017d3161158b..fe83f13d71f84591f5506e1c6b9dfbf9 this.setPvpAllowed(dedicatedserverproperties.pvp); this.setFlightAllowed(dedicatedserverproperties.allowFlight); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 108432435aac34fadfd899941e6d2b951f509971..623b938177cc7287bccc55f34e644bda984a7b65 100644 +index 5bb6df24576948b1f5b66d14769d9137bad5a7e2..b4bc656a1c5fffd8c88bc61df3ac7f84dac52d29 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -23,6 +23,7 @@ import net.minecraft.core.BlockPos; @@ -770,50 +770,3 @@ index 24e08ca0fca3e87f8a6b7670b266f3c2900b798c..3c4281ad770598ecf3b9fae0d6ed6e91 } }; -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index c7bfa5fe5f7945883bd41461247e0efb04f5e9e8..9a31d8b709b28bba658603106c623560c5362947 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -39,36 +39,36 @@ public class SpigotWorldConfig - this.config.set( "world-settings.default." + path, val ); - } - -- private boolean getBoolean(String path, boolean def) -+ public boolean getBoolean(String path, boolean def) // Paper - private -> public - { - this.config.addDefault( "world-settings.default." + path, def ); - return this.config.getBoolean( "world-settings." + this.worldName + "." + path, this.config.getBoolean( "world-settings.default." + path ) ); - } - -- private double getDouble(String path, double def) -+ public double getDouble(String path, double def) // Paper - private -> public - { - this.config.addDefault( "world-settings.default." + path, def ); - return this.config.getDouble( "world-settings." + this.worldName + "." + path, this.config.getDouble( "world-settings.default." + path ) ); - } - -- private int getInt(String path) -+ public int getInt(String path) // Paper - private -> public - { - return this.config.getInt( "world-settings." + this.worldName + "." + path ); - } - -- private int getInt(String path, int def) -+ public int getInt(String path, int def) // Paper - private -> public - { - this.config.addDefault( "world-settings.default." + path, def ); - return this.config.getInt( "world-settings." + this.worldName + "." + path, this.config.getInt( "world-settings.default." + path ) ); - } - -- private List getList(String path, T def) -+ public List getList(String path, T def) // Paper - private -> public - { - this.config.addDefault( "world-settings.default." + path, def ); - return (List) this.config.getList( "world-settings." + this.worldName + "." + path, this.config.getList( "world-settings.default." + path ) ); - } - -- private String getString(String path, String def) -+ public String getString(String path, String def) // Paper - private -> public - { - this.config.addDefault( "world-settings.default." + path, def ); - return this.config.getString( "world-settings." + this.worldName + "." + path, this.config.getString( "world-settings.default." + path ) ); diff --git a/patches/server/0006-MC-Utils.patch b/patches/server/0006-MC-Utils.patch index de5c9c64f6..d94c640b6c 100644 --- a/patches/server/0006-MC-Utils.patch +++ b/patches/server/0006-MC-Utils.patch @@ -2258,7 +2258,7 @@ index 0000000000000000000000000000000000000000..9df0006c1a283f77c4d01d9fce9062fc + } +} diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index 23c0914685e51de9dcdbb305c203efd4f2a73128..6f29d1fc437764a75d592ccb0c0ddc0593a89967 100644 +index 771e4b72589d7117a154ab6917bd4a56d55f19db..65e0ca442980f273d2fe5f131e174cd92f80da20 100644 --- a/src/main/java/net/minecraft/Util.java +++ b/src/main/java/net/minecraft/Util.java @@ -94,7 +94,7 @@ public class Util { @@ -2314,39 +2314,6 @@ index a153ca538d237fab567550b0bfcdf5b2985c56f8..022cccbc52a7dda2f6bf0999905db82d @Override public BlockPos immutable() { -diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java -index f484cf19e1ed6f4e14a6c324c59511e822335ba7..f4b5792e080d5181184eb661d005ce6cab649bf3 100644 ---- a/src/main/java/net/minecraft/core/Vec3i.java -+++ b/src/main/java/net/minecraft/core/Vec3i.java -@@ -75,17 +75,17 @@ public class Vec3i implements Comparable { - return this.z; - } - -- protected Vec3i setX(int x) { -+ public Vec3i setX(int x) { // Paper - protected -> public - this.x = x; - return this; - } - -- protected Vec3i setY(int y) { -+ public Vec3i setY(int y) { // Paper - protected -> public - this.y = y; - return this; - } - -- protected Vec3i setZ(int z) { -+ public Vec3i setZ(int z) { // Paper - protected -> public - this.z = z; - return this; - } -@@ -193,6 +193,7 @@ public class Vec3i implements Comparable { - return this.distSqr(pos.x(), pos.y(), pos.z(), true) < distance * distance; - } - -+ @Deprecated public final double distanceSquared(Vec3i baseblockposition) { return distSqr(baseblockposition); } // Paper - OBFHELPER - public double distSqr(Vec3i vec) { - return this.distSqr((double)vec.getX(), (double)vec.getY(), (double)vec.getZ(), true); - } diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java index 3d374000cd61d4a29dae21035c5ee9a93a1ff0f9..750df4ab2fbfdcf759f4d3451340e66b6764391d 100644 --- a/src/main/java/net/minecraft/nbt/CompoundTag.java @@ -2918,7 +2885,7 @@ index f0aea7c801b3ef3b1a213ecd473ce9e718f1be46..224128235f712c3dc8588b3a5cdd3e77 MinecraftServer.LOGGER.info("Saving usercache.json"); this.getProfileCache().save(); diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index cc9b1f922d7f6953468de56a2c004233228769ee..ce4296ab7e6f1ccc735d619eacabdf2ef2f4e361 100644 +index ed9e1b4a9179a002b965a2d979b7ad0656dd1494..df32a8b1df60064c49702dca26d7310b7d27e94b 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java @@ -52,9 +52,9 @@ public class ChunkHolder { @@ -3081,7 +3048,7 @@ index cc9b1f922d7f6953468de56a2c004233228769ee..ce4296ab7e6f1ccc735d619eacabdf2e } diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 474d71813740f8ad61339a67bfa5bceae4331a77..cbaafa2024a36fbdaf9f753c58ca974831af9fdf 100644 +index c0a769a626165e5d5d1eef6f919966976afdae48..356a79900f5ca24b2d9f9af5a1223a4309f17df9 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -55,6 +55,7 @@ import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; @@ -3160,7 +3127,7 @@ index 474d71813740f8ad61339a67bfa5bceae4331a77..cbaafa2024a36fbdaf9f753c58ca9748 @Override diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 623b938177cc7287bccc55f34e644bda984a7b65..2cc633e6d03ae37a6d0785e0a3dcc4fe9350b10a 100644 +index b4bc656a1c5fffd8c88bc61df3ac7f84dac52d29..2427b2cfb52c0e6aee1397c9951c1aa1c0f14503 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -45,6 +45,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana @@ -3171,15 +3138,6 @@ index 623b938177cc7287bccc55f34e644bda984a7b65..2cc633e6d03ae37a6d0785e0a3dcc4fe public class ServerChunkCache extends ChunkSource { -@@ -52,7 +53,7 @@ public class ServerChunkCache extends ChunkSource { - private final DistanceManager distanceManager; - public final ChunkGenerator generator; - final ServerLevel level; -- final Thread mainThread; -+ public final Thread mainThread; // Paper - package-private -> public - final ThreadedLevelLightEngine lightEngine; - private final ServerChunkCache.MainThreadExecutor mainThreadProcessor; - public final ChunkMap chunkMap; @@ -67,6 +68,158 @@ public class ServerChunkCache extends ChunkSource { @Nullable @VisibleForDebug @@ -3404,7 +3362,7 @@ index 623b938177cc7287bccc55f34e644bda984a7b65..2cc633e6d03ae37a6d0785e0a3dcc4fe if (optional.isPresent()) { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index ea44904fdf709ae097f5ede128193a78c1f49d35..b6eb04733611b63916453f36abf2ae615786845c 100644 +index d13a2497396cf83e125c72041c4cf4dee164b6a4..0127e3ab8d4e65c802c9b44d081cc0d51946e473 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.longs.LongSet; @@ -3415,17 +3373,8 @@ index ea44904fdf709ae097f5ede128193a78c1f49d35..b6eb04733611b63916453f36abf2ae61 import it.unimi.dsi.fastutil.objects.ObjectIterator; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -@@ -172,7 +173,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - private static final Logger LOGGER = LogManager.getLogger(); - private static final int EMPTY_TIME_NO_TICK = 300; - final List players; -- private final ServerChunkCache chunkSource; -+ public final ServerChunkCache chunkSource; // Paper - public - private final MinecraftServer server; - public final PrimaryLevelData serverLevelData; // CraftBukkit - type - final EntityTickList entityTickList; diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index d25086e37b7ea34fd586be7818c6b585760ce18e..99292d239dfdd2c0aaeece2b526db011b17aa121 100644 +index 2889d43857f418eb26600e78940dedc2b7c2b0f4..2b0d989119c9f69a68a6c1c69fb09dbbedd16716 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -228,6 +228,8 @@ public class ServerPlayer extends Player { @@ -3519,7 +3468,7 @@ index 65bd706ca96f5c0ec4573da9fb144fb51d2de919..3a2e8bdc215a6af604bfaad01b670a36 return this.data; } diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -index 08fb847add9f5a2c1ca6dfef31de7e711c8b9840..5b38966093fe60b298844961d015d5a9f03412a2 100644 +index a4c5edee297af6d68d518b77f706732b5ccbe4de..7bf4bf5cb2c1b54a7e2733091f48f3a824336d36 100644 --- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java +++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java @@ -78,6 +78,13 @@ public abstract class BlockableEventLoop implements Profiler @@ -3560,7 +3509,7 @@ index 7f3d83d3d071f6b441ad119b1c93be035e911e70..89e7d02b88404ac5dce06595432ae95c } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index d067e2477231e145af88aa21d9173512c3a053cf..3b2b57f5049d26a14e45eb4ec88a5b498005d372 100644 +index 1bb24476ad61c18215cde369913376d21c6e8ab6..6c4d0d584e9042e2cafac1dd29710469ac3b133e 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -259,6 +259,7 @@ public abstract class LivingEntity extends Entity { @@ -3572,7 +3521,7 @@ index d067e2477231e145af88aa21d9173512c3a053cf..3b2b57f5049d26a14e45eb4ec88a5b49 @Override public float getBukkitYaw() { diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index bbc126bdea2e8b0b6781f257ebc34791e7405094..e4f3dbff2605243039f9f59f025c931b3fb309c5 100644 +index 7ed0498e86fa5cea8edb002146126dcedd5b23f6..e91932d25e7b5d4a95e485bfa8b70632e0641b0a 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java @@ -230,6 +230,7 @@ public abstract class Mob extends LivingEntity { @@ -3622,7 +3571,7 @@ index 6d0b9f8834e86a465cae3fa2af830b797c65a4fb..a193358bf274bf13bfa090dd7f796d8d public final Player player; private int timesChanged; diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index e5eab8bd104b84a9583cf28b1a89f3fe357a4004..d5b8931243e2f9cac9b0f92ab8df043a831bbe70 100644 +index 48902f822ccb6e231201f888a2a92923a946e8cf..680c4eb99b650c8ec7fe50022ba36070feb0a0e5 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java @@ -725,6 +725,24 @@ public final class ItemStack { @@ -3641,7 +3590,7 @@ index e5eab8bd104b84a9583cf28b1a89f3fe357a4004..d5b8931243e2f9cac9b0f92ab8df043a + } + private org.bukkit.craftbukkit.inventory.CraftItemStack bukkitStack; + public org.bukkit.inventory.ItemStack getBukkitStack() { -+ if (bukkitStack == null || bukkitStack.getHandle() != this) { ++ if (bukkitStack == null || bukkitStack.handle != this) { + bukkitStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this); + } + return bukkitStack; @@ -4349,18 +4298,6 @@ index 5af90e0f7222356cb0e905a9b6e0c4eac5617a41..5d4d953f197afc402248ab73daeb6ef5 public static VoxelShape block() { return BLOCK; } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 5a247fcd7398d83f37df4aa3103b55611dc87e66..1818be091ce06c1f347396a8a5b9e05f9ceca2c9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -85,6 +85,7 @@ public final class CraftItemStack extends ItemStack { - } - - net.minecraft.world.item.ItemStack handle; -+ public net.minecraft.world.item.ItemStack getHandle() { return handle; } // Paper - - /** - * Mirror diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java index 836ee63b7ea73165257acbcdf5c7336a2a2e36f3..2b4a922b84eeb2b1b64e43a2ca8bf16dcf58218e 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java @@ -4603,19 +4540,6 @@ index 9d14625528c14c9a4b48060dedabad2ac1adf541..a430506c31d9ce7a5c90d726a68f0974 @Override public WorldBorder getWorldBorder() { throw new UnsupportedOperationException("Not supported yet."); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -index d40c0d8be1b0153d62021b8bcb6e8b37fd0acb4e..b0897aba0ac2aa62c2f3d1268f38fef1440b230c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -@@ -17,7 +17,7 @@ import java.util.RandomAccess; - public class UnsafeList extends AbstractList implements List, RandomAccess, Cloneable, Serializable { - private static final long serialVersionUID = 8683452581112892191L; - -- private transient Object[] data; -+ private transient Object[] data; public final Object[] getRawDataArray() { return this.data; } // Paper - expose for raw get - private int size; - private int initialCapacity; - diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java index 87f4d952843654927779a16047da9d601d994fc2..e38b5957b015be3c835ca28a9fe6ee75d7954393 100644 --- a/src/main/java/org/spigotmc/SpigotConfig.java diff --git a/patches/server/0042-Add-PlayerInitialSpawnEvent.patch b/patches/server/0042-Add-PlayerInitialSpawnEvent.patch index f45f72f84e..76761aec77 100644 --- a/patches/server/0042-Add-PlayerInitialSpawnEvent.patch +++ b/patches/server/0042-Add-PlayerInitialSpawnEvent.patch @@ -33,16 +33,3 @@ index 446dd8c15d4ccdced316deeaba379cb6937496ca..8e9d0ca8aa2b1403fc65ed8d79252504 // Spigot end // CraftBukkit - Moved message to after join -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 7e7291cc41735a6c251738492a4cdd1c7798066f..cb65a20d34196866eead7844b93c65bfb853f74c 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -460,7 +460,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n - return d1 * d1 + d2 * d2 + d3 * d3 < radius * radius; - } - -- protected void setRot(float yaw, float pitch) { -+ public void setRot(float yaw, float pitch) { // Paper - protected -> public - // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 - if (Float.isNaN(yaw)) { - yaw = 0; diff --git a/patches/server/0058-Chunk-Save-Reattempt.patch b/patches/server/0058-Chunk-Save-Reattempt.patch index fc84b1d660..6b1b711846 100644 --- a/patches/server/0058-Chunk-Save-Reattempt.patch +++ b/patches/server/0058-Chunk-Save-Reattempt.patch @@ -19,7 +19,7 @@ index 659305865e9c6d9996fcf2596d086050508059cd..1a35ef48c487c92f55fcbbfc19a708ed } } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 7aa1f693c5f44a265ccb442c2c9e995cc3e7418d..1ed8232493c94bc0cf28ef8d4b647cb84bd3fe32 100644 +index ef1d64ebdc3150596cbc5efc36d6acc52dddafee..e506fa1153cabfb93c7bece73e6fe0fafbb958c9 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java @@ -11,6 +11,7 @@ import java.io.IOException; @@ -30,7 +30,7 @@ index 7aa1f693c5f44a265ccb442c2c9e995cc3e7418d..1ed8232493c94bc0cf28ef8d4b647cb8 import net.minecraft.util.ExceptionCollector; import net.minecraft.world.level.ChunkPos; -@@ -101,6 +102,7 @@ public final class RegionFileStorage implements AutoCloseable { +@@ -101,6 +102,7 @@ public class RegionFileStorage implements AutoCloseable { protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException { RegionFile regionfile = this.getFile(pos, false); // CraftBukkit @@ -38,7 +38,7 @@ index 7aa1f693c5f44a265ccb442c2c9e995cc3e7418d..1ed8232493c94bc0cf28ef8d4b647cb8 if (nbt == null) { regionfile.clear(pos); -@@ -126,6 +128,18 @@ public final class RegionFileStorage implements AutoCloseable { +@@ -126,6 +128,18 @@ public class RegionFileStorage implements AutoCloseable { } } diff --git a/patches/server/0062-Handle-Item-Meta-Inconsistencies.patch b/patches/server/0062-Handle-Item-Meta-Inconsistencies.patch index d7baa47ee7..051b530b76 100644 --- a/patches/server/0062-Handle-Item-Meta-Inconsistencies.patch +++ b/patches/server/0062-Handle-Item-Meta-Inconsistencies.patch @@ -18,7 +18,7 @@ For consistency, the old API methods now forward to use the ItemMeta API equivalents, and should deprecate the old API's. diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index ac05b201167d8e17f39d3df732adf676dc24b409..d3267cdef523b62f9985e49b768e6ad22fbe874d 100644 +index 1b3cf8e6310c83f9303705339bfa131c90b0ac3d..bbaf615a150bc9c1ad61d509209350eec922a9f2 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java @@ -13,6 +13,8 @@ import java.text.DecimalFormatSymbols; @@ -79,7 +79,7 @@ index ac05b201167d8e17f39d3df732adf676dc24b409..d3267cdef523b62f9985e49b768e6ad2 public boolean isEnchanted() { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 1818be091ce06c1f347396a8a5b9e05f9ceca2c9..51c1f62af5c25fe620f1d8a9cb03473e849db68d 100644 +index d11f50cab14cf1483c88914912ae018ce016ac50..799af645a0a39877dc36417110a73fe33d743ba4 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java @@ -6,7 +6,6 @@ import java.util.Map; @@ -90,7 +90,7 @@ index 1818be091ce06c1f347396a8a5b9e05f9ceca2c9..51c1f62af5c25fe620f1d8a9cb03473e import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.configuration.serialization.DelegateDeserialization; -@@ -178,28 +177,11 @@ public final class CraftItemStack extends ItemStack { +@@ -177,28 +176,11 @@ public final class CraftItemStack extends ItemStack { public void addUnsafeEnchantment(Enchantment ench, int level) { Validate.notNull(ench, "Cannot add null enchantment"); @@ -124,7 +124,7 @@ index 1818be091ce06c1f347396a8a5b9e05f9ceca2c9..51c1f62af5c25fe620f1d8a9cb03473e } static boolean makeTag(net.minecraft.world.item.ItemStack item) { -@@ -216,66 +198,33 @@ public final class CraftItemStack extends ItemStack { +@@ -215,66 +197,33 @@ public final class CraftItemStack extends ItemStack { @Override public boolean containsEnchantment(Enchantment ench) { diff --git a/patches/server/0074-Sanitise-RegionFileCache-and-make-configurable.patch b/patches/server/0074-Sanitise-RegionFileCache-and-make-configurable.patch index b31cdf5814..1abda080b9 100644 --- a/patches/server/0074-Sanitise-RegionFileCache-and-make-configurable.patch +++ b/patches/server/0074-Sanitise-RegionFileCache-and-make-configurable.patch @@ -25,10 +25,10 @@ index 716f285e67019b8a62922d09c15883c99f9421aa..439dcc6effdc91830d2b7ede90639829 + } } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 1ed8232493c94bc0cf28ef8d4b647cb84bd3fe32..3c82f98a34a5911fdb9e3ba66c54d25f6944fd07 100644 +index e506fa1153cabfb93c7bece73e6fe0fafbb958c9..f973792c8ee4523eb4efdf31d0a97cb3358e1b3b 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -35,7 +35,7 @@ public final class RegionFileStorage implements AutoCloseable { +@@ -35,7 +35,7 @@ public class RegionFileStorage implements AutoCloseable { if (regionfile != null) { return regionfile; } else { diff --git a/patches/server/0076-Add-PlayerUseUnknownEntityEvent.patch b/patches/server/0076-Add-PlayerUseUnknownEntityEvent.patch index 88703e3fdd..80017aa7d4 100644 --- a/patches/server/0076-Add-PlayerUseUnknownEntityEvent.patch +++ b/patches/server/0076-Add-PlayerUseUnknownEntityEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add PlayerUseUnknownEntityEvent diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java -index 1b316ecf2d8725b9c91a4869e6c2362c1443160d..70d309ddb215c62805b6ee13be50d8f93cdc38ba 100644 +index 8834ed411a7db86b4d2b88183a1315317107d719..c45b5ab6776f3ac79f856c3a6467c510e20db25a 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java @@ -10,8 +10,8 @@ import net.minecraft.world.entity.Entity; @@ -19,17 +19,8 @@ index 1b316ecf2d8725b9c91a4869e6c2362c1443160d..70d309ddb215c62805b6ee13be50d8f9 private final boolean usingSecondaryAction; static final ServerboundInteractPacket.Action ATTACK_ACTION = new ServerboundInteractPacket.Action() { @Override -@@ -88,7 +88,7 @@ public class ServerboundInteractPacket implements Packet public - INTERACT(ServerboundInteractPacket.InteractionAction::new), - ATTACK((friendlyByteBuf) -> { - return ServerboundInteractPacket.ATTACK_ACTION; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index dfab012166354af6233ee1fdab1b0fba6fcbe940..fa6d414387950d522243370714d5425f09e351e8 100644 +index cbd7e9b6b3d0cd5cb87ed8b2657daee9368424a0..8e751e9821dc76f33e9e844990c701f69c817c4b 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -2203,8 +2203,37 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0085-Configurable-RCON-IP-address.patch b/patches/server/0085-Configurable-RCON-IP-address.patch index 2e6902174f..c630888dc6 100644 --- a/patches/server/0085-Configurable-RCON-IP-address.patch +++ b/patches/server/0085-Configurable-RCON-IP-address.patch @@ -29,19 +29,6 @@ index 3dc2187035fff8c0c338b35c07ca2164ed753b04..e3409d5f4ddcaa4edecfa4b3c638a126 } // CraftBukkit start -diff --git a/src/main/java/net/minecraft/server/dedicated/Settings.java b/src/main/java/net/minecraft/server/dedicated/Settings.java -index f914b12473a607622eb9c816c980ef1adbc9e863..2f30f6332f7c81a28f2930a8b7a7379fd31f8c02 100644 ---- a/src/main/java/net/minecraft/server/dedicated/Settings.java -+++ b/src/main/java/net/minecraft/server/dedicated/Settings.java -@@ -124,7 +124,7 @@ public abstract class Settings> { - } - - @Nullable -- private String getStringRaw(String key) { -+ public String getStringRaw(String key) { // Paper - private -> public - return (String) this.getOverride(key, this.properties.getProperty(key)); // CraftBukkit - } - diff --git a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java b/src/main/java/net/minecraft/server/rcon/thread/RconThread.java index 5e642ab9947f054c1741e13170a36f8fe300cdbe..a93e0eb67a78abb2eabd549cd5240095a24e5545 100644 --- a/src/main/java/net/minecraft/server/rcon/thread/RconThread.java diff --git a/patches/server/0091-LootTable-API-Replenishable-Lootables-Feature.patch b/patches/server/0091-LootTable-API-Replenishable-Lootables-Feature.patch index d1eee7245f..36d72f4cd7 100644 --- a/patches/server/0091-LootTable-API-Replenishable-Lootables-Feature.patch +++ b/patches/server/0091-LootTable-API-Replenishable-Lootables-Feature.patch @@ -515,7 +515,7 @@ index 0000000000000000000000000000000000000000..3377b86c337d0234bbb9b0349e4034a7 + } +} diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index eceaeed527f34860e1c55b9f96863f140055faa7..416dd12638540312aa48b530e24ba3ad7ab6079c 100644 +index a5fa826f895fc8660521496ad1e9de5c55ffbdaa..c0ea34cacbc1b042f79b441f57a11fa646a5c872 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -168,6 +168,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @@ -641,19 +641,6 @@ index b79d9d26a8e60f9c0ecd69e9c2f9cfd087e21d23..f23fff80d07ac7d06715efe67cb49ebb LootContext.Builder builder = (new LootContext.Builder((ServerLevel)this.level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(this.worldPosition)).withOptionalRandomSeed(this.lootTableSeed); if (player != null) { builder.withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 90f44b49d2728c8a1110270fa8c52104355e45c4..d57b32090cebfc952ac0a71b8aada85f49275241 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -61,7 +61,7 @@ public class CraftBlockEntityState extends CraftBlockStat - } - - // gets the wrapped TileEntity -- protected T getTileEntity() { -+ public T getTileEntity() { // Paper - protected -> public - return this.tileEntity; - } - diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java index 5cb17e8289db0ab38fd36318e2957701d6dfb341..f48b830a9ae8160388cb0d0220a44b1ec9f0d214 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java @@ -670,7 +657,7 @@ index 5cb17e8289db0ab38fd36318e2957701d6dfb341..f48b830a9ae8160388cb0d0220a44b1e public CraftChest(final Block block) { super(block, ChestBlockEntity.class); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -index 28b9a42d43522cde9d0be4d98a8a5f8fdf6c3abd..055ffe404c37e1daab61b821b590f8c7038076eb 100644 +index a688845f6b8fc3de2864dd896cd132b5c7b3be59..322a8292876b3b4eb73cff2ef768f4b9325b2bdb 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java @@ -10,7 +10,7 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; @@ -682,15 +669,6 @@ index 28b9a42d43522cde9d0be4d98a8a5f8fdf6c3abd..055ffe404c37e1daab61b821b590f8c7 public CraftLootable(Block block, Class tileEntityClass) { super(block, tileEntityClass); -@@ -54,7 +54,7 @@ public abstract class CraftLootable - this.setLootTable(this.getLootTable(), seed); - } - -- private void setLootTable(LootTable table, long seed) { -+ public void setLootTable(LootTable table, long seed) { // Paper - public - ResourceLocation key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); - getSnapshot().setLootTable(key, seed); - } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java index eb21b8457774d5ac765fa9008157cb29d9b72509..abf58bef2042a9efba5a78fd7f97339deceaa780 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java @@ -704,19 +682,6 @@ index eb21b8457774d5ac765fa9008157cb29d9b72509..abf58bef2042a9efba5a78fd7f97339d private final CraftInventory inventory; public CraftMinecartChest(CraftServer server, MinecartChest entity) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -index 097d8bd479a0800114964725da8bfd19415a2956..4893d8e67025d919a455b44bb41d914a39ab5aa9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -@@ -47,7 +47,7 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo - return this.getHandle().lootTableSeed; - } - -- private void setLootTable(LootTable table, long seed) { -+ @Override public void setLootTable(LootTable table, long seed) { // Paper - ResourceLocation newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); - this.getHandle().setLootTable(newKey, seed); - } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java index 34b8f103625f087bb725bed595dd9c30f4a6f70c..ee9648739fb39c5842063d7442df6eb5c9336d7f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java diff --git a/patches/server/0123-Firework-API-s.patch b/patches/server/0123-Firework-API-s.patch index 1b1127a6c4..0206ec70a0 100644 --- a/patches/server/0123-Firework-API-s.patch +++ b/patches/server/0123-Firework-API-s.patch @@ -5,15 +5,13 @@ Subject: [PATCH] Firework API's diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -index 15ba8033dc7b5d533f29ab061b1db6dabfba560f..4cd6e5d62dcd319329d617e075aa3a61cdf01e0d 100644 +index 28e32cdac5b8c51dfcef14b585860f3181e814f3..5bfebe072ec722e7d6f3161d5d6cc709a9b80032 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -@@ -38,7 +38,8 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { - private int life; +@@ -39,6 +39,7 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { public int lifetime; @Nullable -- private LivingEntity attachedToEntity; -+ public LivingEntity attachedToEntity; // Paper - private -> public + public LivingEntity attachedToEntity; + public java.util.UUID spawningEntity; // Paper public FireworkRocketEntity(EntityType type, Level world) { diff --git a/patches/server/0135-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/patches/server/0135-Add-option-to-make-parrots-stay-on-shoulders-despite.patch index 75f04749cd..5a0818fc23 100644 --- a/patches/server/0135-Add-option-to-make-parrots-stay-on-shoulders-despite.patch +++ b/patches/server/0135-Add-option-to-make-parrots-stay-on-shoulders-despite.patch @@ -26,7 +26,7 @@ index c611b5a63498f5ad1f50a75ccd5d7299e27df7e3..9d1cddc6038f0fd0286e4a32013ae98f + } } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 55cd070c2dbf4cf4d8d0fc62067e9bde69ac7e84..03dcaffb57436875baf1b1f85133f422f5b7bbe0 100644 +index a6891c43b674919eecaac5e826b4d979478b300c..bb58cf52e69258a8c59b595f5fa28ced562965f3 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -2057,6 +2057,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @@ -44,7 +44,7 @@ index 55cd070c2dbf4cf4d8d0fc62067e9bde69ac7e84..03dcaffb57436875baf1b1f85133f422 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 e8768625e55f849cd31784cb46e67293bcd93abf..73277b04a45444edce02cce3e033741ebaf2ad0c 100644 +index 33a61c0ab7e6ed03030bdd8d8635d989b28bd169..56ce24ab7213776285d09cc0ab91f012d3e58caf 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java @@ -579,7 +579,7 @@ public abstract class Player extends LivingEntity { @@ -56,12 +56,3 @@ index e8768625e55f849cd31784cb46e67293bcd93abf..73277b04a45444edce02cce3e033741e } } -@@ -1939,7 +1939,7 @@ public abstract class Player extends LivingEntity { - } - } - -- protected void removeEntitiesOnShoulder() { -+ public void removeEntitiesOnShoulder() { // Paper - protected -> public - if (this.timeEntitySatOnShoulder + 20L < this.level.getGameTime()) { - // CraftBukkit start - if (this.spawnEntityFromShoulder(this.getShoulderEntityLeft())) { diff --git a/patches/server/0153-LivingEntity-setKiller.patch b/patches/server/0153-LivingEntity-setKiller.patch index e6db1422e6..099d4ce29a 100644 --- a/patches/server/0153-LivingEntity-setKiller.patch +++ b/patches/server/0153-LivingEntity-setKiller.patch @@ -4,21 +4,8 @@ Date: Mon, 31 Jul 2017 01:49:48 -0500 Subject: [PATCH] LivingEntity#setKiller -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index f0357f9d7b6a39bbdf6486a9d35d890942cc5e4c..89913edf98d65f08f379d0d201f9963c23573478 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -207,7 +207,7 @@ public abstract class LivingEntity extends Entity { - public float flyingSpeed; - @Nullable - public net.minecraft.world.entity.player.Player lastHurtByPlayer; -- protected int lastHurtByPlayerTime; -+ public int lastHurtByPlayerTime; // Paper - protected -> public - protected boolean dead; - protected int noActionTime; - protected float oRun; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index ea94dc9a3b8bd3da5f8ccbeb216384723db668aa..4e9565def5a28a7391f8f541d066c2981d0bbc92 100644 +index 9e98e854b6b3f8dac3990abaa1c9f60fd1ff3836..7beb84da34e58b18cd83a53eab2bcf703e8bf35e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -8,6 +8,7 @@ import java.util.Iterator; diff --git a/patches/server/0204-ItemStack-getMaxItemUseDuration.patch b/patches/server/0204-ItemStack-getMaxItemUseDuration.patch index 3a1ceb4922..be3cf1afd2 100644 --- a/patches/server/0204-ItemStack-getMaxItemUseDuration.patch +++ b/patches/server/0204-ItemStack-getMaxItemUseDuration.patch @@ -6,10 +6,10 @@ Subject: [PATCH] ItemStack#getMaxItemUseDuration Allows you to determine how long it takes to use a usable/consumable item diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 51c1f62af5c25fe620f1d8a9cb03473e849db68d..3fbfe4f77c4b82d96ed022498b2d9175d548e247 100644 +index 799af645a0a39877dc36417110a73fe33d743ba4..982da5f98601c6b3095d78e69e02554640708c64 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -173,6 +173,13 @@ public final class CraftItemStack extends ItemStack { +@@ -172,6 +172,13 @@ public final class CraftItemStack extends ItemStack { return (this.handle == null) ? Material.AIR.getMaxStackSize() : this.handle.getItem().getMaxStackSize(); } diff --git a/patches/server/0234-SkeletonHorse-Additions.patch b/patches/server/0234-SkeletonHorse-Additions.patch index b4a112f8f9..115ed4ddd6 100644 --- a/patches/server/0234-SkeletonHorse-Additions.patch +++ b/patches/server/0234-SkeletonHorse-Additions.patch @@ -4,19 +4,6 @@ Date: Fri, 27 Jul 2018 22:36:31 -0500 Subject: [PATCH] SkeletonHorse Additions -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java -index b5446b417963850f25c715abe52403c731b6ef01..9c5c7ef3b915afe5fe54144f51e383a83c1eb752 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java -@@ -23,7 +23,7 @@ public class SkeletonHorse extends AbstractHorse { - private final SkeletonTrapGoal skeletonTrapGoal = new SkeletonTrapGoal(this); - private static final int TRAP_MAX_LIFE = 18000; - private boolean isTrap; -- private int trapTime; -+ public int trapTime; // Paper private -> public - - public SkeletonHorse(EntityType type, Level world) { - super(type, world); diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java index 67afaab789041f49407233ca8a856a3b0131fcf6..1b874f8a72f5b1ac64dd66621b039295f5dc1f18 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java diff --git a/patches/server/0235-Don-t-call-getItemMeta-on-hasItemMeta.patch b/patches/server/0235-Don-t-call-getItemMeta-on-hasItemMeta.patch index de9d451a6f..d86eef41ce 100644 --- a/patches/server/0235-Don-t-call-getItemMeta-on-hasItemMeta.patch +++ b/patches/server/0235-Don-t-call-getItemMeta-on-hasItemMeta.patch @@ -11,10 +11,10 @@ Returns true if getDamage() == 0 or has damage tag or other tag is set. Check the `ItemMetaTest#testTaggedButNotMeta` method to see how this method behaves. diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 3fbfe4f77c4b82d96ed022498b2d9175d548e247..383c34a611f8371dd6ebcb858c1c0ba148d0660b 100644 +index 982da5f98601c6b3095d78e69e02554640708c64..fa6819fe0eaf52a1f7182ffb775e0a210530aa9b 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -572,7 +572,7 @@ public final class CraftItemStack extends ItemStack { +@@ -571,7 +571,7 @@ public final class CraftItemStack extends ItemStack { @Override public boolean hasItemMeta() { diff --git a/patches/server/0242-Fix-client-rendering-skulls-from-same-user.patch b/patches/server/0242-Fix-client-rendering-skulls-from-same-user.patch index 5864436e44..f0e8883c79 100644 --- a/patches/server/0242-Fix-client-rendering-skulls-from-same-user.patch +++ b/patches/server/0242-Fix-client-rendering-skulls-from-same-user.patch @@ -65,19 +65,6 @@ index 3bdb09ab00ec05ed532a0c26b9fd321e1f05c1a0..1451a98d69b185dd15a2d1d7681bcecb this.blockEntitiesTags.add(compoundTag); } -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 4d4b471bbfb2d9174391c8adc6075ec11295408b..8b3cf3b882ea6c0d48df8b551f4b85b87b889c58 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -143,7 +143,7 @@ public final class ItemStack { - private int popTime; - @Deprecated - private Item item; -- private CompoundTag tag; -+ public CompoundTag tag; // Paper private -> public - private boolean emptyCacheFlag; - private Entity entityRepresentation; - private BlockInWorld cachedBreakBlock; diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java index eaf586eb386e13e954bc593f6ddbc45929cec204..f0192a009f6a21d1781ce709624a9187048d9a08 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java diff --git a/patches/server/0259-Asynchronous-chunk-IO-and-loading.patch b/patches/server/0259-Asynchronous-chunk-IO-and-loading.patch index 8498e4d2a8..75843af998 100644 --- a/patches/server/0259-Asynchronous-chunk-IO-and-loading.patch +++ b/patches/server/0259-Asynchronous-chunk-IO-and-loading.patch @@ -2312,7 +2312,7 @@ index 880fc4e346549a5d7ed627244bdfd284705ad2fc..24fc2eb3ee067a4164db166aa3e07ecb public String getLocalIp() { diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index ce4296ab7e6f1ccc735d619eacabdf2ef2f4e361..00f5cd29170e3594fe2ac194e04e403cef685912 100644 +index df32a8b1df60064c49702dca26d7310b7d27e94b..92faf96e12b443351ea146d4d1deccb0f7e020e5 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java @@ -154,6 +154,18 @@ public class ChunkHolder { @@ -2357,7 +2357,7 @@ index ce4296ab7e6f1ccc735d619eacabdf2ef2f4e361..00f5cd29170e3594fe2ac194e04e403c completablefuture = (CompletableFuture) this.futures.get(i); if (completablefuture == null) { diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 64304bf9fc60332d9a17194660d3a34c853a36c6..c096c2fecc6ab74255b305a7eee045bedaab44ae 100644 +index a8c172c3742b8eb52c9cdd5adb65224f2e7bc736..5585c72b3c79a8c5bcc9d84c6cf4c7d61b6a42e9 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -115,7 +115,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -2369,30 +2369,6 @@ index 64304bf9fc60332d9a17194660d3a34c853a36c6..c096c2fecc6ab74255b305a7eee045be private final PoiManager poiManager; public final LongSet toDrop; private boolean modified; -@@ -126,7 +126,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private final ChunkStatusUpdateListener chunkStatusListener; - public final ChunkMap.ChunkDistanceManager distanceManager; - private final AtomicInteger tickingGenerated; -- private final StructureManager structureManager; -+ public final StructureManager structureManager; // Paper - private -> public - private final File storageFolder; - private final PlayerMap playerMap; - public final Int2ObjectMap entityMap; -@@ -252,12 +252,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - @Nullable -- protected ChunkHolder getUpdatingChunkIfPresent(long pos) { -+ public final ChunkHolder getUpdatingChunkIfPresent(long pos) { // Paper - protected -> public - return (ChunkHolder) this.updatingChunkMap.get(pos); - } - - @Nullable -- protected ChunkHolder getVisibleChunkIfPresent(long pos) { -+ public final ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public - return (ChunkHolder) this.visibleChunkMap.get(pos); - } - @@ -406,6 +406,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public void close() throws IOException { try { @@ -2677,18 +2653,9 @@ index 64304bf9fc60332d9a17194660d3a34c853a36c6..c096c2fecc6ab74255b305a7eee045be return this.poiManager; } diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 4a343fa19566f468aca17228379f4d75f3f56f28..71ac5cf0fdedcfe422bf6f5e6ffb15ce4138aa04 100644 +index bd937505244cc9305611815a9274f91395d3a8f8..b15d5c2a8d4d2184a55a16ff2071fd82cb2e0457 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -55,7 +55,7 @@ public class ServerChunkCache extends ChunkSource { - final ServerLevel level; - public final Thread mainThread; // Paper - package-private -> public - final ThreadedLevelLightEngine lightEngine; -- private final ServerChunkCache.MainThreadExecutor mainThreadProcessor; -+ public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; // Paper - private -> public - public final ChunkMap chunkMap; - private final DimensionDataStorage dataStorage; - private long lastInhabitedUpdate; @@ -323,10 +323,128 @@ public class ServerChunkCache extends ChunkSource { return ret; } @@ -2865,7 +2832,7 @@ index 4a343fa19566f468aca17228379f4d75f3f56f28..71ac5cf0fdedcfe422bf6f5e6ffb15ce } finally { chunkMap.callbackExecutor.run(); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 73da340ab8782efc7d97c3a3e29ea9cd9a830799..043869948201c728bf168855d260b0dca42a0b3a 100644 +index a86757a96fea11de150fb48ac123c3493e5420b7..f1d08ad4f29eb2b94dc24962bac177397df1110c 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -210,6 +210,79 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl @@ -3443,19 +3410,10 @@ index 1a35ef48c487c92f55fcbbfc19a708ededc6a32d..357da4846344d1182ab7149c4d352d50 } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 3c82f98a34a5911fdb9e3ba66c54d25f6944fd07..211ab6cffe78c61fcff12ef7ffba904c4cae57b2 100644 +index f973792c8ee4523eb4efdf31d0a97cb3358e1b3b..ebb1a050beab9530942c4498335f084c89faef06 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -15,7 +15,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionCollector; - import net.minecraft.world.level.ChunkPos; - --public final class RegionFileStorage implements AutoCloseable { -+public class RegionFileStorage implements AutoCloseable { // Paper - no final - - public static final String ANVIL_EXTENSION = ".mca"; - private static final int MAX_CACHE_SIZE = 256; -@@ -28,11 +28,32 @@ public final class RegionFileStorage implements AutoCloseable { +@@ -28,11 +28,32 @@ public class RegionFileStorage implements AutoCloseable { this.sync = dsync; } @@ -3471,7 +3429,7 @@ index 3c82f98a34a5911fdb9e3ba66c54d25f6944fd07..211ab6cffe78c61fcff12ef7ffba904c + return regionfile != null ? regionfile.hasChunk(pos) : false; + } + -+ public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - public ++ public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit + return this.getFile(chunkcoordintpair, existingOnly, false); + } + public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly, boolean lock) throws IOException { @@ -3489,7 +3447,7 @@ index 3c82f98a34a5911fdb9e3ba66c54d25f6944fd07..211ab6cffe78c61fcff12ef7ffba904c return regionfile; } else { if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable -@@ -50,6 +71,12 @@ public final class RegionFileStorage implements AutoCloseable { +@@ -50,6 +71,12 @@ public class RegionFileStorage implements AutoCloseable { RegionFile regionfile1 = new RegionFile(file1, this.folder, this.sync); this.regionCache.putAndMoveToFirst(i, regionfile1); @@ -3502,7 +3460,7 @@ index 3c82f98a34a5911fdb9e3ba66c54d25f6944fd07..211ab6cffe78c61fcff12ef7ffba904c return regionfile1; } } -@@ -57,11 +84,12 @@ public final class RegionFileStorage implements AutoCloseable { +@@ -57,11 +84,12 @@ public class RegionFileStorage implements AutoCloseable { @Nullable public CompoundTag read(ChunkPos pos) throws IOException { // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing @@ -3516,7 +3474,7 @@ index 3c82f98a34a5911fdb9e3ba66c54d25f6944fd07..211ab6cffe78c61fcff12ef7ffba904c DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); CompoundTag nbttagcompound; -@@ -98,10 +126,14 @@ public final class RegionFileStorage implements AutoCloseable { +@@ -98,10 +126,14 @@ public class RegionFileStorage implements AutoCloseable { } return nbttagcompound; @@ -3532,7 +3490,7 @@ index 3c82f98a34a5911fdb9e3ba66c54d25f6944fd07..211ab6cffe78c61fcff12ef7ffba904c int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper if (nbt == null) { -@@ -140,9 +172,12 @@ public final class RegionFileStorage implements AutoCloseable { +@@ -140,9 +172,12 @@ public class RegionFileStorage implements AutoCloseable { MinecraftServer.LOGGER.error("Failed to save chunk", laste); } // Paper end @@ -3546,7 +3504,7 @@ index 3c82f98a34a5911fdb9e3ba66c54d25f6944fd07..211ab6cffe78c61fcff12ef7ffba904c ExceptionCollector exceptionsuppressor = new ExceptionCollector<>(); ObjectIterator objectiterator = this.regionCache.values().iterator(); -@@ -159,7 +194,7 @@ public final class RegionFileStorage implements AutoCloseable { +@@ -159,7 +194,7 @@ public class RegionFileStorage implements AutoCloseable { exceptionsuppressor.throwIfPresent(); } @@ -3556,10 +3514,10 @@ index 3c82f98a34a5911fdb9e3ba66c54d25f6944fd07..211ab6cffe78c61fcff12ef7ffba904c while (objectiterator.hasNext()) { diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java -index 844d65612d9c4c19d02a2b0a5b90cd44de9f17c9..cfd4c38ca99b183f23716f82c972c14be33ca13d 100644 +index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e1fb5cc22 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java -@@ -30,12 +30,12 @@ import net.minecraft.world.level.LevelHeightAccessor; +@@ -30,10 +30,10 @@ import net.minecraft.world.level.LevelHeightAccessor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -3570,11 +3528,8 @@ index 844d65612d9c4c19d02a2b0a5b90cd44de9f17c9..cfd4c38ca99b183f23716f82c972c14b - private final IOWorker worker; + // Paper - remove mojang I/O thread private final Long2ObjectMap> storage = new Long2ObjectOpenHashMap<>(); -- private final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet(); -+ public final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet(); // Paper - private -> public + public final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet(); private final Function> codec; - private final Function factory; - private final DataFixer fixerUpper; @@ -43,12 +43,13 @@ public class SectionStorage implements AutoCloseable { protected final LevelHeightAccessor levelHeightAccessor; diff --git a/patches/server/0262-Improve-death-events.patch b/patches/server/0262-Improve-death-events.patch index 095ae72b8a..79d88fa35d 100644 --- a/patches/server/0262-Improve-death-events.patch +++ b/patches/server/0262-Improve-death-events.patch @@ -19,7 +19,7 @@ maybe more (please check patch overrides for drops for more): - players, armor stands, foxes, chested donkeys/llamas diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index c8652e3bf325d3c557257ad88fe195f7a31683d6..bea1461ee3bd65f02bf6add6ed967555092fd675 100644 +index b9fdccfc9815b0aec7bb5f5ad633c69b8eba6af2..df02d712e7daf1603885547995d69cb7fa3962ca 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -218,6 +218,10 @@ public class ServerPlayer extends Player { @@ -70,7 +70,7 @@ index c8652e3bf325d3c557257ad88fe195f7a31683d6..bea1461ee3bd65f02bf6add6ed967555 } } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 773c1e0ed3e10157c968d84b19947d99bb01371a..fd0c307a4b340661ba9aff9ae4e0055c139a1ebd 100644 +index 9382bc7569a39a0d5729fb7441f07b84f0d0c566..a629b6e3cd085f79ad231747cce996bb1fbdc3b2 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -261,6 +261,7 @@ public abstract class LivingEntity extends Entity { @@ -193,26 +193,15 @@ index 773c1e0ed3e10157c968d84b19947d99bb01371a..fd0c307a4b340661ba9aff9ae4e0055c // CraftBukkit start public int getExpReward() { -@@ -1762,8 +1788,9 @@ public abstract class LivingEntity extends Entity { - return SoundEvents.GENERIC_HURT; +@@ -1763,7 +1789,7 @@ public abstract class LivingEntity extends Entity { } -+ @Nullable - protected SoundEvent getDeathSound() { -+ public final SoundEvent getDeathSoundPublic() { return this.getDeathSound(); } protected SoundEvent getDeathSound() { // Paper - provide PUBLIC accessor, overrides are hell to deal with ++ protected SoundEvent getDeathSound() { return getDeathSoundPublic(); } public SoundEvent getDeathSoundPublic() { // Paper - public OBFHELPER return SoundEvents.GENERIC_DEATH; } -@@ -2477,7 +2504,7 @@ public abstract class LivingEntity extends Entity { - - } - -- protected float getSoundVolume() { -+ public final float getSoundVolumePublic() { return this.getSoundVolume(); } protected float getSoundVolume() { // Paper - provide PUBLIC accessor, overrides are hell - return 1.0F; - } - diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java index c1cdb1905536bda76f34ad3fc796996443839767..31f4e4a93ea5fd3ffe7e60dff2e2a9642b51daa2 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Fox.java @@ -272,7 +261,7 @@ index 224eca7d20cf4b890a6bc1b314d566e02e716762..7281eb294ddd178ba742088d3c61bf3d public void addAdditionalSaveData(CompoundTag nbt) { super.addAdditionalSaveData(nbt); diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 4adde11daa5ca97a2bf9c164c43c5c011a89b33d..cb9969d768b13863722aad3dc5daad3c10bb264a 100644 +index d545349f659b2a164a28d06e9ff0f9fff8fa8ecf..bbde9b758643c087733064a126d90689d71830cf 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java @@ -755,7 +755,8 @@ public class ArmorStand extends LivingEntity { @@ -306,7 +295,7 @@ index 9683b5e7045050ee0a6f279749dd159ff4366a7d..686dc5859c081d3b86d8e58a63abee49 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 bb006e6c703e5c4cfa16ca4ee4cf8463215c38b0..c3341d1c4e9cda85b0b236461b0a00cbebc9a856 100644 +index 8f44cabc1a92dc3e9afe988b23ac982e85d49fc8..9a84ac5aa03c645037daec23cc4422106a6ace1d 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -787,9 +787,16 @@ public class CraftEventFactory { @@ -354,7 +343,7 @@ index bb006e6c703e5c4cfa16ca4ee4cf8463215c38b0..c3341d1c4e9cda85b0b236461b0a00cb + net.minecraft.sounds.SoundEvent soundEffect = victim.getDeathSoundPublic(); + event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null); + event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundSource().name())); -+ event.setDeathSoundVolume(victim.getSoundVolumePublic()); ++ event.setDeathSoundVolume(victim.getSoundVolume()); + event.setDeathSoundPitch(victim.getVoicePitch()); + } + diff --git a/patches/server/0274-Add-sun-related-API.patch b/patches/server/0274-Add-sun-related-API.patch index 52e76a976f..bae65ee082 100644 --- a/patches/server/0274-Add-sun-related-API.patch +++ b/patches/server/0274-Add-sun-related-API.patch @@ -4,19 +4,6 @@ Date: Sun, 7 Oct 2018 00:54:21 -0500 Subject: [PATCH] Add sun related API -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 8451baff82cb7ec7615ab50a409724897ccf4d95..32e8ae0d2a0f78af671a632c4d1be58a0b38a392 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -1561,7 +1561,7 @@ public abstract class Mob extends LivingEntity { - - } - -- protected boolean isSunBurnTick() { -+ public boolean isSunBurnTick() { // Paper - protected -> public - if (this.level.isDay() && !this.level.isClientSide) { - float f = this.getBrightness(); - BlockPos blockposition = new BlockPos(this.getX(), this.getEyeY(), this.getZ()); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index a19de8405de8ee29afc112556e4684b042c6f4ab..be4c05259f176e9ef5c25db2b1745df5ea4d5789 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java diff --git a/patches/server/0275-Add-LivingEntity-getTargetEntity.patch b/patches/server/0275-Add-LivingEntity-getTargetEntity.patch index e2cacd1761..4395e3cbf3 100644 --- a/patches/server/0275-Add-LivingEntity-getTargetEntity.patch +++ b/patches/server/0275-Add-LivingEntity-getTargetEntity.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add LivingEntity#getTargetEntity diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0d4ab7a469b2ce643b80e7912e20d126a251960a..b75a7f702ca6166c1f869a138ac4b93ba3870c62 100644 +index 0be7bd3c5deef99f9ffe6d3d6390c9297d5b5815..0680ed44a47cfafdff400dd3033c9600afd3514b 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -2341,6 +2341,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @@ -17,7 +17,7 @@ index 0d4ab7a469b2ce643b80e7912e20d126a251960a..b75a7f702ca6166c1f869a138ac4b93b return 0.0F; } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index fd0c307a4b340661ba9aff9ae4e0055c139a1ebd..8333d604fce05349455bf1779f3e5b0a980c4c16 100644 +index a629b6e3cd085f79ad231747cce996bb1fbdc3b2..f795e7e689e205e9ba5ef57482850679ad7b19f9 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -116,6 +116,7 @@ import net.minecraft.world.level.storage.loot.LootTable; @@ -28,7 +28,7 @@ index fd0c307a4b340661ba9aff9ae4e0055c139a1ebd..8333d604fce05349455bf1779f3e5b0a import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; -@@ -3730,6 +3731,38 @@ public abstract class LivingEntity extends Entity { +@@ -3729,6 +3730,38 @@ public abstract class LivingEntity extends Entity { return level.clip(raytrace); } @@ -68,7 +68,7 @@ index fd0c307a4b340661ba9aff9ae4e0055c139a1ebd..8333d604fce05349455bf1779f3e5b0a public int getShieldBlockingDelay() { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index cb4c15d17ea3f22e6baa73ba6ce2a18e34ac4b00..5477f288db57d63051f4579b8cd3c19e3af430ee 100644 +index 05e962ed9269db4cfa170960507b10d7b7d13741..e2e76c5de41666ef3a7132e376a3e4257bb13109 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -1,5 +1,6 @@ diff --git a/patches/server/0276-Turtle-API.patch b/patches/server/0276-Turtle-API.patch index 4a809a1352..94bca6236d 100644 --- a/patches/server/0276-Turtle-API.patch +++ b/patches/server/0276-Turtle-API.patch @@ -18,7 +18,7 @@ index 70a51ba19fb34f652858b18f24554261787d97e2..065d0752db0e3ae2a89d707aaa214580 private final int searchRange; private final int verticalSearchRange; diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index b782d278463a72b8514719e9b14986f268828772..e638d982b4bd1d261a7282cad6dab98ad0b55213 100644 +index fa551b1338a21b7b0864bdb9f31cb365c918facf..925f16d5eb092518ef774f69a8d99689feb0f5d7 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java +++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java @@ -11,6 +11,7 @@ import net.minecraft.nbt.CompoundTag; @@ -38,39 +38,6 @@ index b782d278463a72b8514719e9b14986f268828772..e638d982b4bd1d261a7282cad6dab98a return (BlockPos) this.entityData.get(Turtle.HOME_POS); } -@@ -109,7 +110,7 @@ public class Turtle extends Animal { - return (Boolean) this.entityData.get(Turtle.HAS_EGG); - } - -- void setHasEgg(boolean hasEgg) { -+ public void setHasEgg(boolean hasEgg) { // Paper - this.entityData.set(Turtle.HAS_EGG, hasEgg); - } - -@@ -122,19 +123,19 @@ public class Turtle extends Animal { - this.entityData.set(Turtle.LAYING_EGG, diggingSand); - } - -- boolean isGoingHome() { -+ public boolean isGoingHome() { // Paper - public - return (Boolean) this.entityData.get(Turtle.GOING_HOME); - } - -- void setGoingHome(boolean landBound) { -+ public void setGoingHome(boolean landBound) { // Paper - public - this.entityData.set(Turtle.GOING_HOME, landBound); - } - -- boolean isTravelling() { -+ public boolean isTravelling() { // Paper - public - return (Boolean) this.entityData.get(Turtle.TRAVELLING); - } - -- void setTravelling(boolean travelling) { -+ public void setTravelling(boolean travelling) { // Paper - public - this.entityData.set(Turtle.TRAVELLING, travelling); - } - @@ -487,14 +488,17 @@ public class Turtle extends Animal { if (!this.turtle.isInWater() && this.isReachedTarget()) { diff --git a/patches/server/0278-Call-player-spectator-target-events-and-improve-impl.patch b/patches/server/0278-Call-player-spectator-target-events-and-improve-impl.patch index 537e2dbe3c..7137c95fee 100644 --- a/patches/server/0278-Call-player-spectator-target-events-and-improve-impl.patch +++ b/patches/server/0278-Call-player-spectator-target-events-and-improve-impl.patch @@ -19,7 +19,7 @@ spectate the target entity. Co-authored-by: Spottedleaf diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 76be554b8266f1cb2b2eebb4db9777bda727f421..e6b64def52915114edb7a5e53fdc8816afd809a9 100644 +index df02d712e7daf1603885547995d69cb7fa3962ca..3ca3a1c16ea0900bfb868a6e2fc88e3522bf7752 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1822,14 +1822,58 @@ public class ServerPlayer extends Player { @@ -86,18 +86,9 @@ index 76be554b8266f1cb2b2eebb4db9777bda727f421..e6b64def52915114edb7a5e53fdc8816 @Override diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 2917632c5e974dbfb7d78c497ebd49e742b8ef3c..deb6352604b7cbda7de9df0d654410399f4ce159 100644 +index 2917632c5e974dbfb7d78c497ebd49e742b8ef3c..4f263837f4111f77e14e4663afeff4e170b2b3da 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1068,7 +1068,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser - } - } - -- private void a(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack handItem) { // CraftBukkit -+ public void a(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack handItem) { // CraftBukkit // Paper - make public - ListTag nbttaglist = new ListTag(); - - if (this.player.isTextFilteringEnabled()) { @@ -1381,6 +1381,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.a(x, y, z, yaw, pitch, PlayerTeleportEvent.TeleportCause.UNKNOWN); } diff --git a/patches/server/0282-Here-s-Johnny.patch b/patches/server/0282-Here-s-Johnny.patch index 9bd412b6e3..4f0deb6247 100644 --- a/patches/server/0282-Here-s-Johnny.patch +++ b/patches/server/0282-Here-s-Johnny.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Here's Johnny! diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -index aaeb82575ce0a3dac7c4e413fb782925573894d7..dcaec42b0756cf36da813815b4a54e4d6c4e293a 100644 +index 6203069a09c578200b8de5e18e351f700472b62c..e3f900153c10a01fd8b1ba346fe87880c958b76a 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java @@ -51,7 +51,7 @@ public class Vindicator extends AbstractIllager { - static final Predicate DOOR_BREAKING_PREDICATE = (difficulty) -> { + public static final Predicate DOOR_BREAKING_PREDICATE = (difficulty) -> { return difficulty == Difficulty.NORMAL || difficulty == Difficulty.HARD; }; - boolean isJohnny; diff --git a/patches/server/0286-Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/patches/server/0286-Improve-Server-Thread-Pool-and-Thread-Priorities.patch index 33c9c97915..088dd9b37f 100644 --- a/patches/server/0286-Improve-Server-Thread-Pool-and-Thread-Priorities.patch +++ b/patches/server/0286-Improve-Server-Thread-Pool-and-Thread-Priorities.patch @@ -12,7 +12,7 @@ server threads Allow usage of a single thread executor by not using ForkJoin so single core CPU's. diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index 6f29d1fc437764a75d592ccb0c0ddc0593a89967..99d52a9643efe38b449b59b6aac81c5b20ed9477 100644 +index 65e0ca442980f273d2fe5f131e174cd92f80da20..81f4f26a6b83079d36acd1fd86dede0eb1116c01 100644 --- a/src/main/java/net/minecraft/Util.java +++ b/src/main/java/net/minecraft/Util.java @@ -56,7 +56,7 @@ import java.util.stream.Stream; @@ -66,15 +66,6 @@ index 6f29d1fc437764a75d592ccb0c0ddc0593a89967..99d52a9643efe38b449b59b6aac81c5b return executorService; } -@@ -180,7 +185,7 @@ public class Util { - throw t instanceof RuntimeException ? (RuntimeException)t : new RuntimeException(t); - } - -- private static void onThreadException(Thread thread, Throwable t) { -+ public static void onThreadException(Thread thread, Throwable t) { // Paper - make public - pauseInIde(t); - if (t instanceof CompletionException) { - t = t.getCause(); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index 24fc2eb3ee067a4164db166aa3e07ecbb426bbba..a302d232da3fbaa2cb3e1903cfd096d404847c54 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java diff --git a/patches/server/0296-force-entity-dismount-during-teleportation.patch b/patches/server/0296-force-entity-dismount-during-teleportation.patch index a19c63855c..4d12d3502d 100644 --- a/patches/server/0296-force-entity-dismount-during-teleportation.patch +++ b/patches/server/0296-force-entity-dismount-during-teleportation.patch @@ -20,7 +20,7 @@ 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 13dace1a8fcde011d26d37049ae3ca14d86990fc..8e86ca5221236ab3ab61d7a6859b64be9e5d8f97 100644 +index 8beca0412c65ad03376fb76e2d993bc841bf9e0b..77d9a4ce7be345b6a999a0269b26c0e60acab864 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1299,11 +1299,13 @@ public class ServerPlayer extends Player { @@ -41,7 +41,7 @@ index 13dace1a8fcde011d26d37049ae3ca14d86990fc..8e86ca5221236ab3ab61d7a6859b64be if (entity1 != entity && this.connection != null) { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d92a54022478eac52abf035aee89d91acf29c874..7b7c554ab22cee655d19eed793f45706f0311234 100644 +index 62bb61b6f8e099eddf3ad12b7ff47f62cab2eaa9..f95b6e77318f18c62b7c7dda2be23161ddd914d7 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -2214,12 +2214,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @@ -93,10 +93,10 @@ index d92a54022478eac52abf035aee89d91acf29c874..7b7c554ab22cee655d19eed793f45706 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 8333d604fce05349455bf1779f3e5b0a980c4c16..1dabdba428c10e65b634b6e2036f993c4be186a7 100644 +index f795e7e689e205e9ba5ef57482850679ad7b19f9..1460a3185d557acfe695d46b4254a2a573cb7323 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3329,11 +3329,13 @@ public abstract class LivingEntity extends Entity { +@@ -3328,11 +3328,13 @@ public abstract class LivingEntity extends Entity { return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 4) != 0; } @@ -114,7 +114,7 @@ index 8333d604fce05349455bf1779f3e5b0a980c4c16..1dabdba428c10e65b634b6e2036f993c this.dismountVehicle(entity); } 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 e0e33dd92b686939f622f0a7da0d5a971f43d0d6..4c9261c68518ab7429325f0366dfb2930663288c 100644 +index 1a7bd2462bab95fa6986cef705e5e5b82da30063..857346b755454956268cc594bb03dc060f2a4aac 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java @@ -1096,9 +1096,11 @@ public abstract class Player extends LivingEntity { diff --git a/patches/server/0297-Add-more-Zombie-API.patch b/patches/server/0297-Add-more-Zombie-API.patch index 9f2c58776e..d6951c979f 100644 --- a/patches/server/0297-Add-more-Zombie-API.patch +++ b/patches/server/0297-Add-more-Zombie-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add more Zombie API diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 017d8de4d09f524aed2ee03af7ef79468503edf0..c60d9775230b2ff554eeb38136f8e7c32c47d8cf 100644 +index eabdf345ddf208aaac681f249cb11356ade08673..0878e69aa5805f635971b5ce46783ce043c19bbe 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java @@ -96,6 +96,7 @@ public class Zombie extends Monster { @@ -29,12 +29,10 @@ index 017d8de4d09f524aed2ee03af7ef79468503edf0..c60d9775230b2ff554eeb38136f8e7c3 public void startUnderWaterConversion(int ticksUntilWaterConversion) { this.lastTick = MinecraftServer.currentTick; // CraftBukkit this.conversionTime = ticksUntilWaterConversion; -@@ -292,10 +299,17 @@ public class Zombie extends Monster { - +@@ -293,9 +300,15 @@ public class Zombie extends Monster { } -+ public boolean isSunSensitivePublic() { return this.isSunSensitive(); } // Paper - public getter - protected boolean isSunSensitive() { + public boolean isSunSensitive() { - return true; + return this.shouldBurnInDay; // Paper - use api value instead } @@ -48,7 +46,7 @@ index 017d8de4d09f524aed2ee03af7ef79468503edf0..c60d9775230b2ff554eeb38136f8e7c3 @Override public boolean hurt(DamageSource source, float amount) { if (!super.hurt(source, amount)) { -@@ -415,6 +429,7 @@ public class Zombie extends Monster { +@@ -415,6 +428,7 @@ public class Zombie extends Monster { nbt.putBoolean("CanBreakDoors", this.canBreakDoors()); nbt.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1); nbt.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1); @@ -56,7 +54,7 @@ index 017d8de4d09f524aed2ee03af7ef79468503edf0..c60d9775230b2ff554eeb38136f8e7c3 } @Override -@@ -426,6 +441,11 @@ public class Zombie extends Monster { +@@ -426,6 +440,11 @@ public class Zombie extends Monster { if (nbt.contains("DrownedConversionTime", 99) && nbt.getInt("DrownedConversionTime") > -1) { this.startUnderWaterConversion(nbt.getInt("DrownedConversionTime")); } @@ -69,7 +67,7 @@ index 017d8de4d09f524aed2ee03af7ef79468503edf0..c60d9775230b2ff554eeb38136f8e7c3 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 2e643e92569512ac4e75c0ef2ee7aa4b688e7356..41b5059f6fde8a1afa8c70b983750854ac0207a6 100644 +index 2e643e92569512ac4e75c0ef2ee7aa4b688e7356..77e4875484bdaedfba576a6b008245c488b2a112 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java @@ -93,6 +93,42 @@ public class CraftZombie extends CraftMonster implements Zombie { @@ -94,7 +92,7 @@ index 2e643e92569512ac4e75c0ef2ee7aa4b688e7356..41b5059f6fde8a1afa8c70b983750854 + + @Override + public boolean shouldBurnInDay() { -+ return getHandle().isSunSensitivePublic(); ++ return getHandle().isSunSensitive(); + } + + @Override diff --git a/patches/server/0299-Add-PlayerConnectionCloseEvent.patch b/patches/server/0299-Add-PlayerConnectionCloseEvent.patch index ef06807c6c..67df705ec6 100644 --- a/patches/server/0299-Add-PlayerConnectionCloseEvent.patch +++ b/patches/server/0299-Add-PlayerConnectionCloseEvent.patch @@ -65,7 +65,7 @@ index 8bbf13a7aea1142b3154a1c76837a98aa5ed431d..9f0537799a3cae43fb120056b8fe805a } diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index a196ab2510a1c302ef1c946400c1a7c07619994a..46432534fddbbf78e3bf46385b9638d2f92c951f 100644 +index 3d97f76f14b8c22c78c46a34c2da2e6406ba28b6..477117affabfe07d52d3b40404613492b0bcdc56 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -56,10 +56,10 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener @@ -81,12 +81,3 @@ index a196ab2510a1c302ef1c946400c1a7c07619994a..46432534fddbbf78e3bf46385b9638d2 private final String serverId; @Nullable private ServerPlayer delayedAcceptPlayer; -@@ -441,7 +441,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener - return new GameProfile(uuid, profile.getName()); - } - -- private static enum State { -+ public static enum State { // Paper - make public - - HELLO, KEY, AUTHENTICATING, NEGOTIATING, READY_TO_ACCEPT, DELAY_ACCEPT, ACCEPTED; - diff --git a/patches/server/0332-Chunk-debug-command.patch b/patches/server/0332-Chunk-debug-command.patch index e5149d9026..b3eca55d69 100644 --- a/patches/server/0332-Chunk-debug-command.patch +++ b/patches/server/0332-Chunk-debug-command.patch @@ -429,7 +429,7 @@ index 0df3961919f04f27eb265ab316aa5a0f15a70854..bb0a07a280c7d4885165e9d6488e7741 return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status); } diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 84831fc611589c19320b5e3af107080596b1fbdc..fa6d91886d433c0b7d77c1d059a23ee194ae14a4 100644 +index 1ff399ae84eb5281cd058556f67374688ab59e54..1e52b8e97dcee512e7d2fbe157152df9e0779bf1 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java @@ -61,7 +61,7 @@ public class ChunkHolder { @@ -442,7 +442,7 @@ index 84831fc611589c19320b5e3af107080596b1fbdc..fa6d91886d433c0b7d77c1d059a23ee1 private final ShortSet[] changedBlocksPerSection; private final BitSet blockChangedLightSectionFilter; diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 71ac5cf0fdedcfe422bf6f5e6ffb15ce4138aa04..77bb2fb280293da4a38f9acc6503e84997ecb399 100644 +index b15d5c2a8d4d2184a55a16ff2071fd82cb2e0457..d76568b06ff5035e59b664e371fe4a216517327a 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -49,7 +49,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper @@ -454,19 +454,6 @@ index 71ac5cf0fdedcfe422bf6f5e6ffb15ce4138aa04..77bb2fb280293da4a38f9acc6503e849 private final DistanceManager distanceManager; public final ChunkGenerator generator; final ServerLevel level; -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 6631a2b8cf99993d727d65a67af2bc7febb685b4..08b4e46109eb97746d0204e3797ebafce959b212 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -174,7 +174,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - public static final BlockPos END_SPAWN_POINT = new BlockPos(100, 50, 0); - private static final Logger LOGGER = LogManager.getLogger(); - private static final int EMPTY_TIME_NO_TICK = 300; -- final List players; -+ public final List players; // Paper - package->public - public final ServerChunkCache chunkSource; // Paper - public - private final MinecraftServer server; - public final PrimaryLevelData serverLevelData; // CraftBukkit - type diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java index b346fa94b23d81da7da073f71dd12e672e0f079c..8b0c6e1a649400908dbb674dfb4cdd1aa0ce1d38 100644 --- a/src/main/java/net/minecraft/server/level/Ticket.java diff --git a/patches/server/0333-Fix-World-isChunkGenerated-calls.patch b/patches/server/0333-Fix-World-isChunkGenerated-calls.patch index 8cfc74e92c..ce3b666529 100644 --- a/patches/server/0333-Fix-World-isChunkGenerated-calls.patch +++ b/patches/server/0333-Fix-World-isChunkGenerated-calls.patch @@ -8,7 +8,7 @@ This patch also adds a chunk status cache on region files (note that its only purpose is to cache the status on DISK) diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index fa6d91886d433c0b7d77c1d059a23ee194ae14a4..56e292e6550b19d0cae9ebad369da730ca1cabd8 100644 +index 1e52b8e97dcee512e7d2fbe157152df9e0779bf1..2aa86f35b8960273ad91b21e260bcf91cf861e08 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java @@ -111,6 +111,19 @@ public class ChunkHolder { @@ -32,7 +32,7 @@ index fa6d91886d433c0b7d77c1d059a23ee194ae14a4..56e292e6550b19d0cae9ebad369da730 public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 25826b41812f2d9ac29806ad7a9242e5674376fc..dd7de2c3db10d9d606d47c52eba40e71034fc11a 100644 +index 5585c72b3c79a8c5bcc9d84c6cf4c7d61b6a42e9..da58b2ee334a347eea375dafd37347635a4ab62f 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -84,6 +84,7 @@ import net.minecraft.world.level.chunk.ProtoChunk; @@ -108,24 +108,9 @@ index 25826b41812f2d9ac29806ad7a9242e5674376fc..dd7de2c3db10d9d606d47c52eba40e71 // Spigot start return this.isOutsideOfRange(chunkPos, false); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 77bb2fb280293da4a38f9acc6503e84997ecb399..c47d1772044913475a60292162ef4be594bed4c6 100644 +index d76568b06ff5035e59b664e371fe4a216517327a..6f8b4d9974c8fb549d69e9b46ab05958c9ce0ba7 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -52,10 +52,10 @@ public class ServerChunkCache extends ChunkSource { - private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); public static final List getPossibleChunkStatuses() { return ServerChunkCache.CHUNK_STATUSES; } // Paper - OBFHELPER - private final DistanceManager distanceManager; - public final ChunkGenerator generator; -- final ServerLevel level; -- public final Thread mainThread; // Paper - package-private -> public -- final ThreadedLevelLightEngine lightEngine; -- public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; // Paper - private -> public -+ private final ServerLevel level; -+ public final Thread mainThread; // Paper - private -> public -+ private final ThreadedLevelLightEngine lightEngine; -+ public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; // Paper private -> public - public final ChunkMap chunkMap; - private final DimensionDataStorage dataStorage; - private long lastInhabitedUpdate; @@ -324,6 +324,7 @@ public class ServerChunkCache extends ChunkSource { } // Paper end @@ -134,15 +119,6 @@ index 77bb2fb280293da4a38f9acc6503e84997ecb399..c47d1772044913475a60292162ef4be5 public ChunkAccess getChunkAtImmediately(int x, int z) { ChunkHolder holder = this.chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); if (holder == null) { -@@ -922,7 +923,7 @@ public class ServerChunkCache extends ChunkSource { - return this.lastSpawnState; - } - -- private final class MainThreadExecutor extends BlockableEventLoop { -+ public final class MainThreadExecutor extends BlockableEventLoop { // Paper - package -> public - - MainThreadExecutor(Level world) { - super("Chunk source main thread executor for " + world.dimension().location()); diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java index 6e0cf8ee76143301c939fc4af5eeb091abdcbc5c..066f03ee7b4feda9ec2b0984ee7cf63fa0b9e4fc 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java @@ -255,10 +231,10 @@ index 357da4846344d1182ab7149c4d352d5019384715..832392cc2adc94e1fcb1055d91eb4655 this.padToFullSector(); } finally { diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 211ab6cffe78c61fcff12ef7ffba904c4cae57b2..1bee455235ece8aa299a2baeede027d251e6ff57 100644 +index ebb1a050beab9530942c4498335f084c89faef06..4ab881f0488af3577deda2f90a31a3f9243306dc 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -143,6 +143,7 @@ public class RegionFileStorage implements AutoCloseable { // Paper - no final +@@ -143,6 +143,7 @@ public class RegionFileStorage implements AutoCloseable { try { NbtIo.write(nbt, (DataOutput) dataoutputstream); @@ -266,7 +242,7 @@ index 211ab6cffe78c61fcff12ef7ffba904c4cae57b2..1bee455235ece8aa299a2baeede027d2 } catch (Throwable throwable) { if (dataoutputstream != null) { try { -@@ -205,3 +206,4 @@ public class RegionFileStorage implements AutoCloseable { // Paper - no final +@@ -205,3 +206,4 @@ public class RegionFileStorage implements AutoCloseable { } } diff --git a/patches/server/0340-Prevent-consuming-the-wrong-itemstack.patch b/patches/server/0340-Prevent-consuming-the-wrong-itemstack.patch index ed08b471be..d9f9c995dd 100644 --- a/patches/server/0340-Prevent-consuming-the-wrong-itemstack.patch +++ b/patches/server/0340-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 1dabdba428c10e65b634b6e2036f993c4be186a7..5def2e0379373b126a1b2281b0859b39443fc4ac 100644 +index 1460a3185d557acfe695d46b4254a2a573cb7323..084156e1014647d8f4bfce271e114c47b1a09a81 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3548,15 +3548,18 @@ public abstract class LivingEntity extends Entity { +@@ -3547,15 +3547,18 @@ public abstract class LivingEntity extends Entity { this.entityData.set(LivingEntity.DATA_LIVING_ENTITY_FLAGS, (byte) j); } @@ -31,7 +31,7 @@ index 1dabdba428c10e65b634b6e2036f993c4be186a7..5def2e0379373b126a1b2281b0859b39 } } -@@ -3629,6 +3632,7 @@ public abstract class LivingEntity extends Entity { +@@ -3628,6 +3631,7 @@ public abstract class LivingEntity extends Entity { this.releaseUsingItem(); } else { if (!this.useItem.isEmpty() && this.isUsingItem()) { @@ -39,7 +39,7 @@ index 1dabdba428c10e65b634b6e2036f993c4be186a7..5def2e0379373b126a1b2281b0859b39 this.triggerItemUseEffects(this.useItem, 16); // CraftBukkit start - fire PlayerItemConsumeEvent ItemStack itemstack; -@@ -3663,8 +3667,8 @@ public abstract class LivingEntity extends Entity { +@@ -3662,8 +3666,8 @@ public abstract class LivingEntity extends Entity { } this.stopUsingItem(); diff --git a/patches/server/0357-Lag-compensate-eating.patch b/patches/server/0357-Lag-compensate-eating.patch index 9941db915c..c6b1004b93 100644 --- a/patches/server/0357-Lag-compensate-eating.patch +++ b/patches/server/0357-Lag-compensate-eating.patch @@ -7,10 +7,10 @@ When the server is lagging, players will wait longer when eating. Change to also use a time check instead if it passes. diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 5def2e0379373b126a1b2281b0859b39443fc4ac..f48435dc344fb48feb48e2a141b394829058c5c4 100644 +index 084156e1014647d8f4bfce271e114c47b1a09a81..5f73418035ac1226c6b655b654367ff9cf9f0841 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3492,6 +3492,11 @@ public abstract class LivingEntity extends Entity { +@@ -3491,6 +3491,11 @@ public abstract class LivingEntity extends Entity { return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; } @@ -22,7 +22,7 @@ index 5def2e0379373b126a1b2281b0859b39443fc4ac..f48435dc344fb48feb48e2a141b39482 private void updatingUsingItem() { if (this.isUsingItem()) { if (ItemStack.isSameIgnoreDurability(this.getItemInHand(this.getUsedItemHand()), this.useItem)) { -@@ -3509,8 +3514,12 @@ public abstract class LivingEntity extends Entity { +@@ -3508,8 +3513,12 @@ public abstract class LivingEntity extends Entity { if (this.shouldTriggerItemUseEffects()) { this.triggerItemUseEffects(stack, 5); } @@ -37,7 +37,7 @@ index 5def2e0379373b126a1b2281b0859b39443fc4ac..f48435dc344fb48feb48e2a141b39482 this.completeUsingItem(); } -@@ -3556,7 +3565,10 @@ public abstract class LivingEntity extends Entity { +@@ -3555,7 +3564,10 @@ public abstract class LivingEntity extends Entity { if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag this.useItem = itemstack; @@ -49,7 +49,7 @@ index 5def2e0379373b126a1b2281b0859b39443fc4ac..f48435dc344fb48feb48e2a141b39482 if (!this.level.isClientSide) { this.setLivingEntityFlag(1, true); this.setLivingEntityFlag(2, enumhand == InteractionHand.OFF_HAND); -@@ -3580,7 +3592,10 @@ public abstract class LivingEntity extends Entity { +@@ -3579,7 +3591,10 @@ public abstract class LivingEntity extends Entity { } } else if (!this.isUsingItem() && !this.useItem.isEmpty()) { this.useItem = ItemStack.EMPTY; @@ -61,7 +61,7 @@ index 5def2e0379373b126a1b2281b0859b39443fc4ac..f48435dc344fb48feb48e2a141b39482 } } -@@ -3706,7 +3721,10 @@ public abstract class LivingEntity extends Entity { +@@ -3705,7 +3720,10 @@ public abstract class LivingEntity extends Entity { } this.useItem = ItemStack.EMPTY; diff --git a/patches/server/0361-Entity-Activation-Range-2.0.patch b/patches/server/0361-Entity-Activation-Range-2.0.patch index b3fddc85d8..5663d95c45 100644 --- a/patches/server/0361-Entity-Activation-Range-2.0.patch +++ b/patches/server/0361-Entity-Activation-Range-2.0.patch @@ -14,7 +14,7 @@ Adds flying monsters to control ghast and phantoms Adds villagers as separate config diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index fe98fa03548922903e4fb352fbdfeeaac87450df..8d72e68fe8f7d0a770264f54c539ea11f5e1d8da 100644 +index 30ccb9c0ffabfe5536c89d1dafb97afb467371a7..9514eace33ef9de9a1d92f602549552456dc4ceb 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -2,7 +2,6 @@ package net.minecraft.server.level; @@ -124,18 +124,9 @@ index fe98fa03548922903e4fb352fbdfeeaac87450df..8d72e68fe8f7d0a770264f54c539ea11 } else { passenger.stopRiding(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 434618dcb3d4261eb1db20b8f0807c9aba6b8332..9ebbcd15dee0141eca83187a85e0d9b0b5a0fa86 100644 +index b2275c1171f52cbdf283d210c6488e974fa07d98..4ea2bea8641e08bb0350582efc8b43293703c453 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -277,7 +277,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n - public boolean noCulling; - public boolean hasImpulse; - public int portalCooldown; -- protected boolean isInsidePortal; -+ public boolean isInsidePortal; // Paper - public - protected int portalTime; - protected BlockPos portalEntrancePos; - private boolean invulnerable; @@ -306,6 +306,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); public final boolean defaultActivationState; @@ -167,7 +158,7 @@ index 434618dcb3d4261eb1db20b8f0807c9aba6b8332..9ebbcd15dee0141eca83187a85e0d9b0 movement = this.maybeBackOffFromEdge(movement, movementType); Vec3 vec3d1 = this.collide(movement); diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index f48435dc344fb48feb48e2a141b394829058c5c4..bd1cc5e6fea4b9a171718c1249f652782b7ce13e 100644 +index 5f73418035ac1226c6b655b654367ff9cf9f0841..02609533a9c8ae70d50fa81bd0e42af6aca2ee62 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -219,7 +219,7 @@ public abstract class LivingEntity extends Entity { @@ -180,18 +171,9 @@ index f48435dc344fb48feb48e2a141b394829058c5c4..bd1cc5e6fea4b9a171718c1249f65278 public float yya; public float zza; diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 1dcfab8776c9da4c461ebd98187b65bc6ed7dc4d..c9324245d18f8268191c0a89b465ef3054dd014d 100644 +index 9c208d24d6f84e8818c0a7b88cdcb7c2fd703f91..623fd2220007eec7a8e799a647e7c657aae5ee6d 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -117,7 +117,7 @@ public abstract class Mob extends LivingEntity { - public ResourceLocation lootTable; - public long lootTableSeed; - @Nullable -- private Entity leashHolder; -+ public Entity leashHolder; // Paper - private -> public - private int delayedLeashHolderId; - @Nullable - private CompoundTag leashInfoTag; @@ -198,6 +198,19 @@ public abstract class Mob extends LivingEntity { return this.lookControl; } @@ -225,7 +207,7 @@ index 920ae9af8985705a0ada7da5b7085a1ed8ca7f27..7c82d453388a27b69207d051dec316fc protected PathfinderMob(EntityType type, Level world) { super(type, world); diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -index 70e5b4446a8485b5995a0ba26af3a86d9b79bcc7..f29ace7b6a27a602102d37d43a6dd0571f218dfe 100644 +index dc7da3b806d1c759958d7c51b05efbc4b6c42653..69bf112655615337e0df3ea56b9e42fa5ff70430 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java @@ -31,6 +31,7 @@ public class GoalSelector { @@ -709,7 +691,7 @@ index 84ce3d38d5decb4a2f9fae78e0ef5d715860dc7d..2ab585a018290996e7fa9ca6f3ad7d73 isActive = false; } diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 8e6eae7cc27f66faede9a3dc74571e1814df3652..308de0757c219c1e5fa8bde182343c4095301cde 100644 +index 45be7d1821497f13ab0da3c4bbff7585238e902e..769a492305a3ce83e0da0b3de4ebd73859d1e1d9 100644 --- a/src/main/java/org/spigotmc/SpigotWorldConfig.java +++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java @@ -180,13 +180,59 @@ public class SpigotWorldConfig diff --git a/patches/server/0363-Fix-Light-Command.patch b/patches/server/0363-Fix-Light-Command.patch index 366d9738b2..80d2a105f2 100644 --- a/patches/server/0363-Fix-Light-Command.patch +++ b/patches/server/0363-Fix-Light-Command.patch @@ -133,21 +133,8 @@ index 71ffa66973d8994e2a480435ac1ada3fe61600a4..7b5afc5d34b78e6404c1a5c6bb823d95 + }, MinecraftServer.getServer()); + } } -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 56e292e6550b19d0cae9ebad369da730ca1cabd8..3653ec6f93d627092e63cede51f4db2e12b10613 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -312,7 +312,7 @@ public class ChunkHolder { - - } - -- private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { -+ public void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { // Paper - private -> public - this.playerProvider.getPlayers(this.pos, onlyOnWatchDistanceEdge).forEach((entityplayer) -> { - entityplayer.connection.send(packet); - }); diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 5473b22d21ea981f245f4826c4d47295890f88ef..480c361c919bbfbebacf9ac94418eac5ed38e233 100644 +index 6d69f15d90e9096f0ee6cb7259effa87622c787b..fe0fd4e590f7ceb47467c692c81e2b3579596f4e 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -123,6 +123,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider diff --git a/patches/server/0364-Anti-Xray.patch b/patches/server/0364-Anti-Xray.patch index ce0e69fc01..6a02526714 100644 --- a/patches/server/0364-Anti-Xray.patch +++ b/patches/server/0364-Anti-Xray.patch @@ -1105,12 +1105,12 @@ index c28879f32b004f36ff746ea2274f91ddd9501e71..7762d8ff94f856d613a6f50311006b69 + // Paper end } diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 480c361c919bbfbebacf9ac94418eac5ed38e233..56dece64f19009583c94569c5713c2ad0c91ae17 100644 +index fe0fd4e590f7ceb47467c692c81e2b3579596f4e..3a16316a8ecd658b2fbd473fa6ff14abe18e00de 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -1444,7 +1444,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { + public void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { if (packets[0] == null) { - packets[0] = new ClientboundLevelChunkPacket(chunk); + packets[0] = new ClientboundLevelChunkPacket(chunk, chunk.level.chunkPacketBlockController.shouldModify(player, chunk)); // Paper - Ani-Xray - Bypass @@ -1118,7 +1118,7 @@ index 480c361c919bbfbebacf9ac94418eac5ed38e233..56dece64f19009583c94569c5713c2ad } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index e6ef6d9b6e9a674db1180cae6263537e57b843d3..c5070975be1ceeab20ad0b3bab790426adb5e5fa 100644 +index 9514eace33ef9de9a1d92f602549552456dc4ceb..5a397c3f0f21ec8dc9b7ceecbc873cdf6843e203 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -292,7 +292,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0365-No-Tick-view-distance-implementation.patch b/patches/server/0365-No-Tick-view-distance-implementation.patch index ef60b4aa37..3c459b3737 100644 --- a/patches/server/0365-No-Tick-view-distance-implementation.patch +++ b/patches/server/0365-No-Tick-view-distance-implementation.patch @@ -23,7 +23,7 @@ index f27fadc15cb7f5c782e45885ec6a5a69963beade..2ff4d4921e2076abf415bd3c8f5173ec })); diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 51691d3dedf113d58f340b74d448c5e5375b5bed..b2f0102c2a15eb4324367f52e03e534bff883f9b 100644 +index edb9952ddd014c92b9604a9a187fdcd46de8a04f..3e3097f23f775eec4107f5c2f3f2266f4250ba15 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -448,6 +448,11 @@ public class PaperWorldConfig { @@ -53,7 +53,7 @@ index bb0a07a280c7d4885165e9d6488e7741aaa7b47c..9c88426ab1275ee5fb6e28be8b213533 worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); worldData.addProperty("visible-chunk-count", visibleChunks.size()); diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 3653ec6f93d627092e63cede51f4db2e12b10613..995d7977233f0d7683c00a75c3833f9a1eba7f92 100644 +index 2aa86f35b8960273ad91b21e260bcf91cf861e08..8fff5580a88fd1643845967eb7bdab2630777e91 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java @@ -75,6 +75,17 @@ public class ChunkHolder { @@ -95,7 +95,7 @@ index 3653ec6f93d627092e63cede51f4db2e12b10613..995d7977233f0d7683c00a75c3833f9a @@ -313,9 +324,48 @@ public class ChunkHolder { } - public void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { // Paper - private -> public + public void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { - this.playerProvider.getPlayers(this.pos, onlyOnWatchDistanceEdge).forEach((entityplayer) -> { - entityplayer.connection.send(packet); - }); @@ -145,7 +145,7 @@ index 3653ec6f93d627092e63cede51f4db2e12b10613..995d7977233f0d7683c00a75c3833f9a public CompletableFuture> getOrScheduleFuture(ChunkStatus targetStatus, ChunkMap chunkStorage) { diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 56dece64f19009583c94569c5713c2ad0c91ae17..b0cf6e186d7030b1aa9296671683bd33e2d15579 100644 +index 3a16316a8ecd658b2fbd473fa6ff14abe18e00de..91930daa3c965dcc1cb50ae260c159be55f351ed 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -122,7 +122,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -289,13 +289,11 @@ index 56dece64f19009583c94569c5713c2ad0c91ae17..b0cf6e186d7030b1aa9296671683bd33 }); return completablefuture1; } -@@ -962,28 +1044,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } +@@ -963,27 +1045,34 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } -- protected void setViewDistance(int watchDistance) { + public void setViewDistance(int watchDistance) { - int j = Mth.clamp(watchDistance + 1, 3, 33); -+ public void setViewDistance(int watchDistance) { // Paper - public + int j = Mth.clamp(watchDistance + 1, 3, 33); // Paper - diff on change, these make the lower view distance limit 2 and the upper 32 if (j != this.viewDistance) { @@ -348,6 +346,15 @@ index 56dece64f19009583c94569c5713c2ad0c91ae17..b0cf6e186d7030b1aa9296671683bd33 if (chunk != null) { this.playerLoadedChunk(player, packets, chunk); +@@ -1091,7 +1180,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end + + @Nullable +- public CompoundTag readChunk(ChunkPos pos) throws IOException { // Paper - private -> public ++ public CompoundTag readChunk(ChunkPos pos) throws IOException { + CompoundTag nbttagcompound = this.read(pos); + // Paper start - Cache chunk status on disk + if (nbttagcompound == null) { @@ -1202,13 +1291,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.removePlayerFromDistanceMaps(player); // Paper - distance maps } @@ -438,12 +445,11 @@ index 56dece64f19009583c94569c5713c2ad0c91ae17..b0cf6e186d7030b1aa9296671683bd33 + // Paper end - per player view distance } - protected void addEntity(Entity entity) { -@@ -1442,7 +1562,48 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public void addEntity(Entity entity) { +@@ -1442,6 +1562,47 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } -- private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { + // Paper start + private static int getLightMask(final LevelChunk chunk) { + final net.minecraft.world.level.chunk.LevelChunkSection[] chunkSections = chunk.getSections(); @@ -485,10 +491,9 @@ index 56dece64f19009583c94569c5713c2ad0c91ae17..b0cf6e186d7030b1aa9296671683bd33 + } + // Paper end + -+ public void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { // Paper - private -> public + public void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { if (packets[0] == null) { packets[0] = new ClientboundLevelChunkPacket(chunk, chunk.level.chunkPacketBlockController.shouldModify(player, chunk)); // Paper - Ani-Xray - Bypass - packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, (BitSet) null, (BitSet) null, true); diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java index 45c7ebe67019cdbe88b6617a95d5c40d3a68286c..38eebda226e007c8910e04f502ce218cdfe1d456 100644 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java @@ -514,7 +519,7 @@ index 45c7ebe67019cdbe88b6617a95d5c40d3a68286c..38eebda226e007c8910e04f502ce218c if (withinViewDistance) { DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 018632aa8b122f8c013579075615d88d712f4250..92a77fa90828cc4bc3d9217d2df37ffeec6ee58e 100644 +index 54cc0391f77d90a206e9fb2422ea31d5b9ee22af..648e7b258eef32213c512781faffa840eedebec6 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -241,6 +241,7 @@ public class ServerPlayer extends Player { @@ -557,7 +562,7 @@ index bcc946d2747443c34ee8ac2485a5ab41773c93af..2730923bd0bf3b0f928765b9e09e2299 while (iterator.hasNext()) { diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 687e3652d0f36a358a2348df845801ad82d8460c..4eee8156d193f59b7e28499f492f81247c4b1591 100644 +index 5c30d06ac80bb9e82d5eecf58b692040c3a55a99..c71ca549c15d4f88053b8046feecab4ea6a724a4 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -527,8 +527,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @@ -576,7 +581,7 @@ index 687e3652d0f36a358a2348df845801ad82d8460c..4eee8156d193f59b7e28499f492f8124 if ((i & 1) != 0) { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index d4e11b552988f0ef28059f9aa2ca1f1897653171..f6b591f045ae992180806fd6aba309c0d04e722b 100644 +index 164df6e9a91d9fbdbf6e4b835ea1946d81f3be55..a088cb005525fda2c9d5521ab3bac43cfa38a393 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -33,7 +33,10 @@ import net.minecraft.core.Registry; diff --git a/patches/server/0376-Entity-Jump-API.patch b/patches/server/0376-Entity-Jump-API.patch index 7bce87d91f..9511d73f67 100644 --- a/patches/server/0376-Entity-Jump-API.patch +++ b/patches/server/0376-Entity-Jump-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Entity Jump API diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index bd1cc5e6fea4b9a171718c1249f652782b7ce13e..6cc2d26403aa5074218b4b76e2d8ed9e8409a0ae 100644 +index 02609533a9c8ae70d50fa81bd0e42af6aca2ee62..40e5324e19e91640ce39245d8d9f69850903f166 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3159,8 +3159,10 @@ public abstract class LivingEntity extends Entity { +@@ -3158,8 +3158,10 @@ public abstract class LivingEntity extends Entity { } else if (this.isInLava() && (!this.onGround || d7 > d8)) { this.jumpInLiquid((Tag) FluidTags.LAVA); } else if ((this.onGround || flag && d7 <= d8) && this.noJumpDelay == 0) { diff --git a/patches/server/0383-Configurable-chance-of-villager-zombie-infection.patch b/patches/server/0383-Configurable-chance-of-villager-zombie-infection.patch index bf91ca7a1e..6d58c9377f 100644 --- a/patches/server/0383-Configurable-chance-of-villager-zombie-infection.patch +++ b/patches/server/0383-Configurable-chance-of-villager-zombie-infection.patch @@ -8,7 +8,7 @@ This allows you to solve an issue in vanilla behavior where: * On normal difficulty they will have a 50% of getting infected or dying. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a2b1e2c3c4bd958b6ec7b7de5561747d3a2075d2..c3f2cdedf7b9c2ff9e33b823cb20890cba0ded8a 100644 +index fc1c65a4b3c3d5e52d967a3174d8373ddde95e4d..0c9aa7fb4d42c63c920a002050941299e3847d95 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -453,6 +453,11 @@ public class PaperWorldConfig { @@ -24,10 +24,10 @@ index a2b1e2c3c4bd958b6ec7b7de5561747d3a2075d2..c3f2cdedf7b9c2ff9e33b823cb20890c private void lightQueueSize() { lightQueueSize = getInt("light-queue-size", lightQueueSize); diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index ee17cba501e0cc4822bd1278d18b561c77fe9674..b036cbb9a1b6bcac91ffc8ee659fc95d6e04d5d4 100644 +index 4c5213fe89ec131addcc3d705f2e3268f51f1868..299dc59535d2cd73de346618731c65bc01063b66 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -453,10 +453,13 @@ public class Zombie extends Monster { +@@ -452,10 +452,13 @@ public class Zombie extends Monster { @Override public void killed(ServerLevel world, LivingEntity other) { super.killed(world, other); diff --git a/patches/server/0389-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server/0389-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch index 1a65d627cd..3d4273a710 100644 --- a/patches/server/0389-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ b/patches/server/0389-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -7,12 +7,12 @@ Suspected case would be around the technique used in .stopRiding Stack will identify any causer of this and warn instead of crashing. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index d3f835a0c76ce559fb5f3c39714a3312c7e865d1..002561c87ddd03e8bc31864ddd9dee7bc2ff0931 100644 +index ebcfe31c8395aa2bbcc9a9ac74d4c6e1f2e5d0f7..46976a0ef5098e6d794653078111a9dcc1a151d2 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -1466,6 +1466,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - protected void addEntity(Entity entity) { + public void addEntity(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot + // Paper start - ignore and warn about illegal addEntity calls instead of crashing server + if (!entity.valid || entity.level != this.level || this.entityMap.containsKey(entity.getId())) { @@ -26,7 +26,7 @@ index d3f835a0c76ce559fb5f3c39714a3312c7e865d1..002561c87ddd03e8bc31864ddd9dee7b EntityType entitytypes = entity.getType(); int i = entitytypes.clientTrackingRange() * 16; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index d037b14b34658e2f13d7e77f06576c406abc8a60..9cdfd1c8bce3adb5d3ad6d970c6f46ca75f3a952 100644 +index 70de3413da219cc79a86e39893abc3f6f658f729..ba58d33810916bb8c3ac649f1e6e41354d17cde0 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -2120,7 +2120,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl diff --git a/patches/server/0393-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/0393-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch index c1310193c4..3765943fe1 100644 --- a/patches/server/0393-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch +++ b/patches/server/0393-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch @@ -70,7 +70,7 @@ index 9c88426ab1275ee5fb6e28be8b213533dc4ab859..87c9a5c1b43f6010898d72136b5eb997 List allChunks = new ArrayList<>(visibleChunks.values()); List players = world.players; diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index acc30f1ff6a3a9c067e312dc7b6b6fc6bc6904fe..0882552526d4de189f3af8b72653d776cb596859 100644 +index 46976a0ef5098e6d794653078111a9dcc1a151d2..1e366262306aedcd4b3236a6895d30fb35e3cc51 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -107,9 +107,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -162,7 +162,7 @@ index acc30f1ff6a3a9c067e312dc7b6b6fc6bc6904fe..0882552526d4de189f3af8b72653d776 + // Paper end + @Nullable - public final ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public + public ChunkHolder getVisibleChunkIfPresent(long pos) { - return (ChunkHolder) this.visibleChunkMap.get(pos); + // Paper start - mt safe get + if (Thread.currentThread() != this.level.thread) { @@ -233,7 +233,7 @@ index acc30f1ff6a3a9c067e312dc7b6b6fc6bc6904fe..0882552526d4de189f3af8b72653d776 while (objectbidirectionaliterator.hasNext()) { Entry entry = (Entry) objectbidirectionaliterator.next(); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index a81c773cc281ba390d3ce44c52c43710b43829a5..34183527a23650706a9249ffac0182cb77b18086 100644 +index 20a99b62b3466e4853e8d23576133dc728f7927f..302313f72b27fc4c58399c8c2d0bb3bf0cb1f8ab 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -766,7 +766,7 @@ public class ServerChunkCache extends ChunkSource { diff --git a/patches/server/0395-Don-t-move-existing-players-to-world-spawn.patch b/patches/server/0395-Don-t-move-existing-players-to-world-spawn.patch index 629ecd4cd2..c73ad9baa1 100644 --- a/patches/server/0395-Don-t-move-existing-players-to-world-spawn.patch +++ b/patches/server/0395-Don-t-move-existing-players-to-world-spawn.patch @@ -10,7 +10,7 @@ larger than the keep loaded range. By skipping this, we avoid potential for a large spike on server start. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 8fc75890eb7342ff9339789434b031ef9a6a5000..58da115a0c2f34c63ae3614acb0d6f8711069e7b 100644 +index e4a5b89a12c52ccca4f72823e8d7a5d5a689ff16..10489f6f76c1ac64365b677acda43efe640093c6 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -309,7 +309,7 @@ public class ServerPlayer extends Player { @@ -22,15 +22,6 @@ index 8fc75890eb7342ff9339789434b031ef9a6a5000..58da115a0c2f34c63ae3614acb0d6f87 this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -@@ -360,7 +360,7 @@ public class ServerPlayer extends Player { - } - // CraftBukkit end - -- private void fudgeSpawnLocation(ServerLevel world) { -+ public void fudgeSpawnLocation(ServerLevel world) { // Paper - private -> public - BlockPos blockposition = world.getSharedSpawnPos(); - - if (world.dimensionType().hasSkyLight() && world.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit @@ -528,7 +528,7 @@ public class ServerPlayer extends Player { position = Vec3.atCenterOf(((ServerLevel) world).getSharedSpawnPos()); } diff --git a/patches/server/0398-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/0398-Add-Raw-Byte-ItemStack-Serialization.patch index 761655bfd4..6e8c97799d 100644 --- a/patches/server/0398-Add-Raw-Byte-ItemStack-Serialization.patch +++ b/patches/server/0398-Add-Raw-Byte-ItemStack-Serialization.patch @@ -6,7 +6,7 @@ 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 ad8d6a84e1a66e03ae15269e36bc787148f12396..88d5c7a0d7de2e896433d85fbd5425351f51b64d 100644 +index ad8d6a84e1a66e03ae15269e36bc787148f12396..d18f8d7c699893740fa709ef1f0caa4390e7eb20 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -378,6 +378,46 @@ public final class CraftMagicNumbers implements UnsafeValues { @@ -20,7 +20,7 @@ index ad8d6a84e1a66e03ae15269e36bc787148f12396..88d5c7a0d7de2e896433d85fbd542535 + Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized"); + + java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); -+ CompoundTag compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).getHandle() : CraftItemStack.asNMSCopy(item)).save(new CompoundTag()); ++ CompoundTag compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).handle : CraftItemStack.asNMSCopy(item)).save(new CompoundTag()); + compound.putInt("DataVersion", getDataVersion()); + try { + net.minecraft.nbt.NbtIo.writeCompressed( diff --git a/patches/server/0399-Remove-streams-from-Mob-AI-System.patch b/patches/server/0399-Remove-streams-from-Mob-AI-System.patch index 12d3a671c6..7ddded373b 100644 --- a/patches/server/0399-Remove-streams-from-Mob-AI-System.patch +++ b/patches/server/0399-Remove-streams-from-Mob-AI-System.patch @@ -50,12 +50,12 @@ index d92ddc8a4c0f5249b7ff4f97af1ea3db413b2983..8c2ec30a35e86f2b30863045b586a67e public static enum Flag { diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -index f29ace7b6a27a602102d37d43a6dd0571f218dfe..bcb2c5480872eef6f21746003380f71b8d44f5c8 100644 +index 69bf112655615337e0df3ea56b9e42fa5ff70430..faa53d08a12cc7441c670cae6d301de3f498ffe7 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java @@ -28,10 +28,12 @@ public class GoalSelector { private final Map lockedFlags = new EnumMap<>(Goal.Flag.class); - private final Set availableGoals = Sets.newLinkedHashSet(); + public final Set availableGoals = Sets.newLinkedHashSet(); private final Supplier profiler; - private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); + private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. diff --git a/patches/server/0408-Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server/0408-Don-t-run-entity-collision-code-if-not-needed.patch index ce4b9003ba..d3c2a05ff2 100644 --- a/patches/server/0408-Don-t-run-entity-collision-code-if-not-needed.patch +++ b/patches/server/0408-Don-t-run-entity-collision-code-if-not-needed.patch @@ -7,10 +7,10 @@ Will not run if max entity craming is disabled and the max collisions per entity is less than or equal to 0 diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 6cc2d26403aa5074218b4b76e2d8ed9e8409a0ae..0fd79c399e723b5a9db04c8f2fe7b6ec66c0cf44 100644 +index 40e5324e19e91640ce39245d8d9f69850903f166..6d5323acfe22bb6fa8c84ef7ff32fdfc2e4d5f9c 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3256,10 +3256,16 @@ public abstract class LivingEntity extends Entity { +@@ -3255,10 +3255,16 @@ public abstract class LivingEntity extends Entity { protected void serverAiStep() {} protected void pushEntities() { diff --git a/patches/server/0410-Implement-Player-Client-Options-API.patch b/patches/server/0410-Implement-Player-Client-Options-API.patch index 8496cca27d..7fc1328279 100644 --- a/patches/server/0410-Implement-Player-Client-Options-API.patch +++ b/patches/server/0410-Implement-Player-Client-Options-API.patch @@ -85,7 +85,7 @@ index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabb + } +} diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 37fcc83cbaf8e80809c994b18f5a7f3f6d807202..efc6e03e86867665fc655e5a3e0f154af066ef24 100644 +index c8adcdbb8075ab8a1645c4dd809f7de31ad13d34..9500fb90db765095afb1ecd91bbef6099cdc7a4b 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1802,6 +1802,7 @@ public class ServerPlayer extends Player { @@ -96,19 +96,6 @@ index 37fcc83cbaf8e80809c994b18f5a7f3f6d807202..efc6e03e86867665fc655e5a3e0f154a // CraftBukkit start if (getMainArm() != packet.getMainHand()) { PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(this.getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); -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 a3d31cec6d1b8de700b6cd2f7f51398debef5b6d..b916f629c2a0fb018cba19aaa612cbbcbb597dc1 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -144,7 +144,7 @@ public abstract class Player extends LivingEntity { - private static final int FLY_ACHIEVEMENT_SPEED = 25; - private static final EntityDataAccessor DATA_PLAYER_ABSORPTION_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.FLOAT); - private static final EntityDataAccessor DATA_SCORE_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.INT); -- protected static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); -+ public static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); // Paper - protected -> public - protected static final EntityDataAccessor DATA_PLAYER_MAIN_HAND = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); - protected static final EntityDataAccessor DATA_SHOULDER_LEFT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); - protected static final EntityDataAccessor DATA_SHOULDER_RIGHT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 2ed7920b0e046bc9d581878a10b04ad784bb8655..0a6d6ea67eaf8b2a59ec45fb3ffb85096f509997 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java diff --git a/patches/server/0414-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/patches/server/0414-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch index d9ef680f7d..80fc145d53 100644 --- a/patches/server/0414-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch +++ b/patches/server/0414-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch @@ -28,18 +28,9 @@ receives a deterministic result, and should no longer require 1 tick delays anymore. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index dede8863193423858f6d60cc942919e52f28b607..4fe5b75661de64474698495776ebb8232fd252aa 100644 +index 874b7d4947d452c64b7a2f37c3091ba7aed18c4d..b64a3dd03a22542b070eae34f0eaa9b321dca4ec 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1550,7 +1550,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper end - per player view distance - } - -- protected void addEntity(Entity entity) { -+ public void addEntity(Entity entity) { // Paper - protected -> public - org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot - // Paper start - ignore and warn about illegal addEntity calls instead of crashing server - if (!entity.valid || entity.level != this.level || this.entityMap.containsKey(entity.getId())) { @@ -1559,6 +1559,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider .printStackTrace(); return; @@ -49,7 +40,7 @@ index dede8863193423858f6d60cc942919e52f28b607..4fe5b75661de64474698495776ebb823 if (!(entity instanceof EnderDragonPart)) { EntityType entitytypes = entity.getType(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index efc6e03e86867665fc655e5a3e0f154af066ef24..488b45d8b8d3c10b72cd0529a494ea408be58c4c 100644 +index 9500fb90db765095afb1ecd91bbef6099cdc7a4b..63f20e7adf80a1b81438262087e33c3a1e63ca7f 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -237,6 +237,7 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0415-Load-Chunks-for-Login-Asynchronously.patch b/patches/server/0415-Load-Chunks-for-Login-Asynchronously.patch index 66df2681d9..a5f29a3a90 100644 --- a/patches/server/0415-Load-Chunks-for-Login-Asynchronously.patch +++ b/patches/server/0415-Load-Chunks-for-Login-Asynchronously.patch @@ -4,21 +4,8 @@ Date: Sun, 19 Apr 2020 04:28:29 -0400 Subject: [PATCH] Load Chunks for Login Asynchronously -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 60cdb1f5c3f329b417f340f1d2651d89c244e439..3d1c4f8e0db37c6dabece657a17595e7bf1e3dc2 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -630,7 +630,7 @@ public class ServerChunkCache extends ChunkSource { - return this.mainThreadProcessor.pollTask(); - } - -- boolean runDistanceManagerUpdates() { -+ public boolean runDistanceManagerUpdates() { // Paper - packate-private -> public - boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); - boolean flag1 = this.chunkMap.promoteChunkMap(); - diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 488b45d8b8d3c10b72cd0529a494ea408be58c4c..61f9eda59684c08884c4a621effb1705db592a53 100644 +index 63f20e7adf80a1b81438262087e33c3a1e63ca7f..f0d574307b24d19d3006e5c53b650c75436bde38 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -172,6 +172,7 @@ public class ServerPlayer extends Player { @@ -50,7 +37,7 @@ index be677d437d17b74c6188ce1bd5fc6fdc228fd92f..78fbb4c3e52e900956ae0811aaf934c8 public static final TicketType UNKNOWN = TicketType.create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); public static final TicketType PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 85a82c8bb98edec526260680ddfbcb36926b97ee..10e4be89803bcdcc8bf7ce64350464c826368ae7 100644 +index 2e7b909750ee512dce40b8574dfb62ed68fbbfb6..0d8a8b3d7a13e2384f8614bdc190768c03bb98c2 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -221,6 +221,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @@ -87,7 +74,7 @@ index 85a82c8bb98edec526260680ddfbcb36926b97ee..10e4be89803bcdcc8bf7ce64350464c8 this.server.getProfiler().push("keepAlive"); // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 46432534fddbbf78e3bf46385b9638d2f92c951f..49308829885a473906d58fb17797127faabfcf31 100644 +index 477117affabfe07d52d3b40404613492b0bcdc56..3a7cc4f8ee62c8ff726ecf3e669c9f9ba5651487 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -88,7 +88,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener @@ -263,7 +250,7 @@ index 3a13c151066c8784fdc844e1d6310f77ff32e7f1..c4242a1602bbb02541c330bc02016f15 Iterator iterator = list.iterator(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 07630fabdc3e824572d7f551f3a876133fc253fe..e9f7191fefa7c0cf33d56abb7b2a30df261a392c 100644 +index 581f80c490932f66f57e7a91d8738e09521f5a1c..20f861c99b11844849d75ce4606abee80da147de 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1491,7 +1491,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n diff --git a/patches/server/0417-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server/0417-Add-PlayerAttackEntityCooldownResetEvent.patch index 8ef5ac518f..7edc89d1d8 100644 --- a/patches/server/0417-Add-PlayerAttackEntityCooldownResetEvent.patch +++ b/patches/server/0417-Add-PlayerAttackEntityCooldownResetEvent.patch @@ -5,10 +5,10 @@ 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 0fd79c399e723b5a9db04c8f2fe7b6ec66c0cf44..3a83cbe8fb1a5bfc7e7b699686b92561bf0cdba0 100644 +index 6d5323acfe22bb6fa8c84ef7ff32fdfc2e4d5f9c..be3fd03803bef6de0a4667b1794e73287288feb7 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2033,7 +2033,16 @@ public abstract class LivingEntity extends Entity { +@@ -2032,7 +2032,16 @@ public abstract class LivingEntity extends Entity { 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) { diff --git a/patches/server/0428-Implement-Mob-Goal-API.patch b/patches/server/0428-Implement-Mob-Goal-API.patch index c9e7137219..62f0839749 100644 --- a/patches/server/0428-Implement-Mob-Goal-API.patch +++ b/patches/server/0428-Implement-Mob-Goal-API.patch @@ -565,7 +565,7 @@ index 0000000000000000000000000000000000000000..ee500489fca34c339175b5209ebcf341 +} diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java new file mode 100644 -index 0000000000000000000000000000000000000000..a17a8d8ced942e6e3f9072f199c75391dd57dc6a +index 0000000000000000000000000000000000000000..2f9e87d37a8ca794b12098232836295aadd80aff --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java @@ -0,0 +1,221 @@ @@ -603,7 +603,7 @@ index 0000000000000000000000000000000000000000..a17a8d8ced942e6e3f9072f199c75391 + getHandle(craftMob, goal.getTypes()).removeGoal(((PaperVanillaGoal) goal).getHandle()); + } else { + List toRemove = new LinkedList<>(); -+ for (WrappedGoal item : getHandle(craftMob, goal.getTypes()).availableGoals()) { ++ for (WrappedGoal item : getHandle(craftMob, goal.getTypes()).availableGoals) { + if (item.getGoal() instanceof PaperCustomGoal) { + //noinspection unchecked + if (((PaperCustomGoal) item.getGoal()).getHandle() == goal) { @@ -683,7 +683,7 @@ index 0000000000000000000000000000000000000000..a17a8d8ced942e6e3f9072f199c75391 + public Collection> getAllGoals(T mob, GoalType type) { + CraftMob craftMob = (CraftMob) mob; + Set> goals = new HashSet<>(); -+ for (WrappedGoal item : getHandle(craftMob, type).availableGoals()) { ++ for (WrappedGoal item : getHandle(craftMob, type).availableGoals) { + if (!item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { + continue; + } @@ -707,7 +707,7 @@ index 0000000000000000000000000000000000000000..a17a8d8ced942e6e3f9072f199c75391 + if (internalType == type) { + continue; + } -+ for (WrappedGoal item : getHandle(craftMob, internalType).availableGoals()) { ++ for (WrappedGoal item : getHandle(craftMob, internalType).availableGoals) { + if (item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { + continue; + } @@ -919,19 +919,6 @@ index 8c2ec30a35e86f2b30863045b586a67e485c624b..a20faf55488baa31d7f8bf8231e3e825 MOVE, LOOK, JUMP, -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -index bcb2c5480872eef6f21746003380f71b8d44f5c8..bcd0da029edd9b1d6f3617ee20dac00c9890ae82 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -@@ -26,7 +26,7 @@ public class GoalSelector { - } - }; - private final Map lockedFlags = new EnumMap<>(Goal.Flag.class); -- private final Set availableGoals = Sets.newLinkedHashSet(); -+ private final Set availableGoals = Sets.newLinkedHashSet(); public final Set availableGoals() { return this.availableGoals; } // Paper - public getter - private final Supplier profiler; - private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. - private final com.destroystokyo.paper.util.set.OptimizedSmallEnumSet goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 130ab05393a7136020e06ec199256a031ba66091..8dd93620a770855450ed222dad6572e20760b08c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java diff --git a/patches/server/0431-Add-villager-reputation-API.patch b/patches/server/0431-Add-villager-reputation-API.patch index 4182694fcb..18e7254c2a 100644 --- a/patches/server/0431-Add-villager-reputation-API.patch +++ b/patches/server/0431-Add-villager-reputation-API.patch @@ -20,7 +20,7 @@ index 0000000000000000000000000000000000000000..0f10c333d88f2e1c56a6c7f22d421084 + } +} diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -index 07ecb01d02f64e85d478995062a33b58c211ed7e..e316f83a7adc7bba06a6a3fdab55cc9c004cb835 100644 +index 2e342e1c258180dc02080f76385351c0a65eade2..39c0fbae8b94dabd27ee8687015557c6a9279813 100644 --- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java @@ -29,7 +29,7 @@ import net.minecraft.util.VisibleForDebug; @@ -32,15 +32,6 @@ index 07ecb01d02f64e85d478995062a33b58c211ed7e..e316f83a7adc7bba06a6a3fdab55cc9c @VisibleForDebug public Map> getGossipEntries() { -@@ -177,7 +177,7 @@ public class GossipContainer { - return i > type.max ? Math.max(type.max, left) : i; - } - -- static class EntityGossips { -+ public static class EntityGossips { // Paper - make public - final Object2IntMap entries = new Object2IntOpenHashMap<>(); - - public int weightedValue(Predicate gossipTypeFilter) { @@ -228,6 +228,28 @@ public class GossipContainer { public void remove(GossipType gossipType) { this.entries.removeInt(gossipType); diff --git a/patches/server/0473-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server/0473-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch index f96921a0f0..a5608611f2 100644 --- a/patches/server/0473-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch +++ b/patches/server/0473-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch @@ -69,7 +69,7 @@ index 18ae2e2b339d357fbe0f6f2b18bc14c0dfe4c222..782301661f739192798ca6ef501b184b } diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 1f67c9c5f7161ea687983e7ae0ec7d259da9acd3..6a1c000d693031f0c537112963cfa52e22463f1d 100644 +index c1db5cc45dbc7dd24a1ef4dbf88a8efb6c7f2d57..7a87258d1725348fe0c343540f6423885a97a560 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java @@ -1,5 +1,6 @@ @@ -327,7 +327,7 @@ index 1f67c9c5f7161ea687983e7ae0ec7d259da9acd3..6a1c000d693031f0c537112963cfa52e } diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 8982823efd8fd21d403c6c6fb158d57a9da67707..943c187efab8fdbcc38c313a498f876983a98412 100644 +index 89f73e8a7f5b429c89d051b44ea6c9cbecb97730..08857bd5defc48eb2e91c1dc7c013a90443e9b7d 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -144,6 +144,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -949,7 +949,7 @@ index d94241bcca4f2fd5e464a860bd356af504dc68b7..864c78ae0f0b3b50b8ea22b709c1f16b public void runAllUpdates() { super.runAllUpdates(); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 7ab28e9bd3f785838b7fa4ac5811c0e71cddcb61..d13abec908dbb756272888e9ccdedbefff719012 100644 +index 08c3707e67b79de9347db9a66d3d68fedb09ab1d..76a3aafcc191cd4fd6ea43fc08e044a0a87a6ae5 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -446,6 +446,26 @@ public class ServerChunkCache extends ChunkSource { @@ -1029,13 +1029,13 @@ index 7ab28e9bd3f785838b7fa4ac5811c0e71cddcb61..d13abec908dbb756272888e9ccdedbef @@ -631,6 +662,7 @@ public class ServerChunkCache extends ChunkSource { } - public boolean runDistanceManagerUpdates() { // Paper - packate-private -> public + public boolean runDistanceManagerUpdates() { + if (distanceManager.delayDistanceManagerTick) return false; // Paper boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); boolean flag1 = this.chunkMap.promoteChunkMap(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index a01227f1b6d3589a6f56c9289824a1503a32c878..2bf25f90f760c1a5ee025a0ebaaccd9285a4db7f 100644 +index d59e707f28a5f04545208ad33d122fc433b85933..8cbfcbc795c920420bd1906576dfc766910e9e62 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -183,6 +183,12 @@ public class ServerPlayer extends Player { @@ -1115,7 +1115,7 @@ index 8770fe0db46b01e8b608637df4f1a669a3f4cdde..3c1698ba0d3bc412ab957777d9b5211d private final String name; private final Comparator comparator; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index c4a25ac9aad94c5ef610505db6d7539fa12cd31d..91a06e1ac325fe80aaadaf213d40495f4ce15e53 100644 +index fecb2a6b8674ca110d6af539396873e9dcdc0edb..6476d2a478b85116061a13f7ef2a5fec2ade4a04 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1566,6 +1566,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser diff --git a/patches/server/0478-Add-entity-liquid-API.patch b/patches/server/0478-Add-entity-liquid-API.patch index 3600a0f8a8..b86468c5f3 100644 --- a/patches/server/0478-Add-entity-liquid-API.patch +++ b/patches/server/0478-Add-entity-liquid-API.patch @@ -5,25 +5,9 @@ Subject: [PATCH] Add entity liquid API diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 28f9b58c379306138f1528d91f2112c21ae9cb0a..0f37c205fe401126a19191fb5382cc1b4d3f43b4 100644 +index d961faf2609ef820d27837b8f0bf6382f9ce97b6..6ae4da8ccff3627b37c4b0c0b65d23a37513fecc 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1305,13 +1305,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n - return this.wasTouchingWater; - } - -- private boolean isInRain() { -+ public boolean isInRain() { // Paper - private -> public - BlockPos blockposition = this.blockPosition(); - - return this.level.isRainingAt(blockposition) || this.level.isRainingAt(new BlockPos((double) blockposition.getX(), this.getBoundingBox().maxY, (double) blockposition.getZ())); - } - -- private boolean isInBubbleColumn() { -+ public boolean isInBubbleColumn() { // Paper - make public - return this.level.getBlockState(this.blockPosition()).is(Blocks.BUBBLE_COLUMN); - } - @@ -1319,7 +1319,6 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n return this.isInWater() || this.isInRain(); } diff --git a/patches/server/0482-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/0482-Allow-delegation-to-vanilla-chunk-gen.patch index eb2bc9a627..06da5adcf5 100644 --- a/patches/server/0482-Allow-delegation-to-vanilla-chunk-gen.patch +++ b/patches/server/0482-Allow-delegation-to-vanilla-chunk-gen.patch @@ -67,16 +67,3 @@ index fe7851476636dfed02339d4d9f93824b96086769..24a2e88d083f90375c46cf948c7c89dc Set getTiles() { return this.tiles; } -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -index e9502acf47b94e529f3ce273add9b7e0f4fe6d72..a4c3e307e861e6c220425d35fe228dcb9dc7ef31 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -@@ -34,7 +34,7 @@ import org.bukkit.generator.ChunkGenerator.ChunkData; - - public class CustomChunkGenerator extends InternalChunkGenerator { - -- private final net.minecraft.world.level.chunk.ChunkGenerator delegate; -+ public final net.minecraft.world.level.chunk.ChunkGenerator delegate; // Paper - public - private final ChunkGenerator generator; - private final ServerLevel world; - private final Random random = new Random(); diff --git a/patches/server/0483-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server/0483-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch index f3eb70e20f..5d004d5a0f 100644 --- a/patches/server/0483-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch +++ b/patches/server/0483-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 3a83cbe8fb1a5bfc7e7b699686b92561bf0cdba0..8781b3ac40f214974ebb3e06c789f1717735d3a6 100644 +index be3fd03803bef6de0a4667b1794e73287288feb7..42256b8c55c94f5c80834bf3a62b680b70c7cd10 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3353,7 +3353,7 @@ public abstract class LivingEntity extends Entity { +@@ -3352,7 +3352,7 @@ public abstract class LivingEntity extends Entity { Entity entity = this.getVehicle(); super.stopRiding(suppressCancellation); // Paper - suppress diff --git a/patches/server/0509-Optimize-redstone-algorithm.patch b/patches/server/0509-Optimize-redstone-algorithm.patch index fc9c369c29..76744c6f46 100644 --- a/patches/server/0509-Optimize-redstone-algorithm.patch +++ b/patches/server/0509-Optimize-redstone-algorithm.patch @@ -959,7 +959,7 @@ index 0000000000000000000000000000000000000000..3728979e290ab031c9fe9eeb19a0f98d + } +} diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java -index 2f7a34853fb52c840264ae9f01b3c598f1f92e96..881417b16c377572718fb3ed7c3db832ca7bf865 100644 +index 4698b567ced720946b14bd3e03a5b6e0dcf401fb..cdc040c657bfc70bd5b2a2d8251d2b2a2e94ab55 100644 --- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java @@ -1,5 +1,7 @@ @@ -970,15 +970,6 @@ index 2f7a34853fb52c840264ae9f01b3c598f1f92e96..881417b16c377572718fb3ed7c3db832 import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -@@ -69,7 +71,7 @@ public class RedStoneWireBlock extends Block { - }); - private static final float PARTICLE_DENSITY = 0.2F; - private final BlockState crossState; -- private boolean shouldSignal = true; -+ public boolean shouldSignal = true; // Paper private -> public - - public RedStoneWireBlock(BlockBehaviour.Properties settings) { - super(settings); @@ -256,6 +258,121 @@ public class RedStoneWireBlock extends Block { return floor.isFaceSturdy(world, pos, Direction.UP) || floor.is(Blocks.HOPPER); } diff --git a/patches/server/0513-Add-more-Evoker-API.patch b/patches/server/0513-Add-more-Evoker-API.patch index b61c781328..367e900e25 100644 --- a/patches/server/0513-Add-more-Evoker-API.patch +++ b/patches/server/0513-Add-more-Evoker-API.patch @@ -4,25 +4,6 @@ Date: Sun, 23 Aug 2020 15:28:35 +0200 Subject: [PATCH] Add more Evoker API -diff --git a/src/main/java/net/minecraft/world/entity/monster/Evoker.java b/src/main/java/net/minecraft/world/entity/monster/Evoker.java -index 2b09a864425160fadd05323006ddab0bab1d47c8..0400ced70839947532b90f546360701729244a73 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/Evoker.java -+++ b/src/main/java/net/minecraft/world/entity/monster/Evoker.java -@@ -125,12 +125,12 @@ public class Evoker extends SpellcasterIllager { - return SoundEvents.EVOKER_HURT; - } - -- void setWololoTarget(@Nullable Sheep sheep) { -+ public void setWololoTarget(@Nullable Sheep sheep) { // Paper - make public - this.wololoTarget = sheep; - } - - @Nullable -- Sheep getWololoTarget() { -+ public Sheep getWololoTarget() { // Paper - make public - return this.wololoTarget; - } - diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java index 91d07e6996e315734689ea25336992b0ed21cf25..7e861636710aa44ed36e7f20c6320dabb809c35d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java diff --git a/patches/server/0550-Add-Destroy-Speed-API.patch b/patches/server/0550-Add-Destroy-Speed-API.patch index bb9faa5da2..dae65f667d 100644 --- a/patches/server/0550-Add-Destroy-Speed-API.patch +++ b/patches/server/0550-Add-Destroy-Speed-API.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Add Destroy Speed API Co-authored-by: Jake Potrebic diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index aa81c0a4c02fd6f2ab900983fd8c9668fada802e..597ac36c6f6748ecfbf64920da172758814b8061 100644 +index aa81c0a4c02fd6f2ab900983fd8c9668fada802e..2209587fbc4240561aeea6e525fbf22f5041e145 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -782,5 +782,23 @@ public class CraftBlock implements Block { @@ -18,7 +18,7 @@ index aa81c0a4c02fd6f2ab900983fd8c9668fada802e..597ac36c6f6748ecfbf64920da172758 + public float getDestroySpeed(ItemStack itemStack, boolean considerEnchants) { + net.minecraft.world.item.ItemStack nmsItemStack; + if (itemStack instanceof CraftItemStack) { -+ nmsItemStack = ((CraftItemStack) itemStack).getHandle(); ++ nmsItemStack = ((CraftItemStack) itemStack).handle; + } else { + nmsItemStack = CraftItemStack.asNMSCopy(itemStack); + } diff --git a/patches/server/0554-More-lightning-API.patch b/patches/server/0554-More-lightning-API.patch index dae67c3aff..70e70f3aa7 100644 --- a/patches/server/0554-More-lightning-API.patch +++ b/patches/server/0554-More-lightning-API.patch @@ -4,22 +4,6 @@ Date: Sun, 26 Jul 2020 14:44:09 +0200 Subject: [PATCH] More lightning API -diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java -index e476bc8013ac199713e3aaae787bb61fab736aeb..fff23f1cd9da385781547664f26b59255487e2b1 100644 ---- a/src/main/java/net/minecraft/world/entity/LightningBolt.java -+++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java -@@ -39,9 +39,9 @@ public class LightningBolt extends Entity { - private static final int START_LIFE = 2; - private static final double DAMAGE_RADIUS = 3.0D; - private static final double DETECTION_RADIUS = 15.0D; -- private int life; -+ public int life; // Paper - private -> public - public long seed; -- private int flashes; -+ public int flashes; // Paper - private -> public - public boolean visualOnly; - @Nullable - private ServerPlayer cause; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java index f7991ff14ef9cda0327b8621bf615b49cffd7ac5..db6b158f18ad7b9171a8c041802e3495d733bc16 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java diff --git a/patches/server/0555-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/0555-Climbing-should-not-bypass-cramming-gamerule.patch index 71d40d33a8..3048c90fb9 100644 --- a/patches/server/0555-Climbing-should-not-bypass-cramming-gamerule.patch +++ b/patches/server/0555-Climbing-should-not-bypass-cramming-gamerule.patch @@ -21,7 +21,7 @@ index 19c42a9863341f1d06ad57e95049b3cd5b88aeb2..aef38974128c7986864571a3552a566a private void keepLoadedRange() { keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c3b05e73f9f42bdc2ab5d43fa905dd4cf5e39440..3ca07887bc67587cd820556d160037ca62c32c10 100644 +index 2e2effe72235bda3c9ef985840d4322551625ed8..75860a8c0373d3675e3b7e20d7b427f787ebd16b 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1704,6 +1704,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @@ -61,10 +61,10 @@ index 8fb89326395a7e70982c0d757b506565e98b12a4..a060cca08631fb42041e3a79a9abc422 } 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 8781b3ac40f214974ebb3e06c789f1717735d3a6..19ef1b2814270b9385ea15a89dac8c2613a672ee 100644 +index 42256b8c55c94f5c80834bf3a62b680b70c7cd10..a64b2043a27261cbf6b12e8185e8a91fe6ffb468 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3271,7 +3271,7 @@ public abstract class LivingEntity extends Entity { +@@ -3270,7 +3270,7 @@ public abstract class LivingEntity extends Entity { return; } // Paper end - don't run getEntities if we're not going to use its result @@ -73,7 +73,7 @@ index 8781b3ac40f214974ebb3e06c789f1717735d3a6..19ef1b2814270b9385ea15a89dac8c26 if (!list.isEmpty()) { // Paper - move up -@@ -3438,9 +3438,16 @@ public abstract class LivingEntity extends Entity { +@@ -3437,9 +3437,16 @@ public abstract class LivingEntity extends Entity { return !this.isRemoved() && this.collides; // CraftBukkit } @@ -92,7 +92,7 @@ index 8781b3ac40f214974ebb3e06c789f1717735d3a6..19ef1b2814270b9385ea15a89dac8c26 // CraftBukkit start - collidable API diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java -index 7a7b566d781560a85e184a0e67977ba75e6262c5..4716ece9bd1db50c87ccadc44d9ea3c43e741338 100644 +index 9cd91a73ae1a6ad550b9482db1fb7d72d7247c6e..153194d937d210e2e4fd8864e4a3c000f85d7e2e 100644 --- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java +++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java @@ -83,7 +83,7 @@ public class Bat extends AmbientCreature { @@ -120,7 +120,7 @@ index 23f87848b42d180c94b5659b184a768a756deed8..345fe87d5d6c3883c28d2c1b34d1020e @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index c9e0d66443387f3f3e3999ee84d523550f48f573..d9699a422164c30a8386a8042202e1a8bc0ab2b0 100644 +index 6ce4c3938fb5331b4d439c6a42a7bb5fffb1d0a0..ba58e066cca533dfed7610a730c4dd7423fe124d 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java @@ -240,7 +240,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, @@ -133,7 +133,7 @@ index c9e0d66443387f3f3e3999ee84d523550f48f573..d9699a422164c30a8386a8042202e1a8 } diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 5bfec185e15a54ee5fe6eab1aa59d1963d046262..d098d9f9280d2e08596491264a46a8978aaeaca7 100644 +index 069cdfce085909991a69ebec3004d407526d469d..5fc66d7096afcfe63eba774e1dc330ac3263e4b0 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java @@ -345,7 +345,7 @@ public class ArmorStand extends LivingEntity { diff --git a/patches/server/0583-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server/0583-Added-world-settings-for-mobs-picking-up-loot.patch index ef1e217c08..a9623716a8 100644 --- a/patches/server/0583-Added-world-settings-for-mobs-picking-up-loot.patch +++ b/patches/server/0583-Added-world-settings-for-mobs-picking-up-loot.patch @@ -37,10 +37,10 @@ index 3d8f3e22223e4effeaf52cb18c14c60276d4689c..6b4163f5601a0961055c8451ec7ef220 LocalDate localdate = LocalDate.now(); int i = localdate.get(ChronoField.DAY_OF_MONTH); diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 3125aad3b14a185bbd563827f07c15bbb1ef0895..03acacd30b84452733aa2bdeed515455a1f271f8 100644 +index 15f445e7d7250f274351cc5e46cc952d3630de5a..6c4c5756def8eb368cbc6e9319ae6f7ddccf0499 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -497,7 +497,7 @@ public class Zombie extends Monster { +@@ -496,7 +496,7 @@ public class Zombie extends Monster { Object object = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityNbt); float f = difficulty.getSpecialMultiplier(); diff --git a/patches/server/0587-Configurable-door-breaking-difficulty.patch b/patches/server/0587-Configurable-door-breaking-difficulty.patch index de65c8bc54..d08465d7c3 100644 --- a/patches/server/0587-Configurable-door-breaking-difficulty.patch +++ b/patches/server/0587-Configurable-door-breaking-difficulty.patch @@ -59,18 +59,9 @@ index db9d8d1f30c671207617fc75c24b771cd7a23391..75b4da3d38912e52e7ca4d99d51bd97e public int reedMaxHeight; public int bambooMaxHeight; diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -index dcaec42b0756cf36da813815b4a54e4d6c4e293a..53a9e4b0fda9f5a3b23a874c53d93fbe931b0cfb 100644 +index e3f900153c10a01fd8b1ba346fe87880c958b76a..beb6943bcab48d914c32c5de07851eb1731005e2 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -@@ -48,7 +48,7 @@ import net.minecraft.world.level.ServerLevelAccessor; - - public class Vindicator extends AbstractIllager { - private static final String TAG_JOHNNY = "Johnny"; -- static final Predicate DOOR_BREAKING_PREDICATE = (difficulty) -> { -+ public static final Predicate DOOR_BREAKING_PREDICATE = (difficulty) -> { // Paper - package private -> public - return difficulty == Difficulty.NORMAL || difficulty == Difficulty.HARD; - }; - private boolean isJohnny; public boolean isJohnny() { return this.isJohnny; } public void setJohnny(boolean johnny) { this.isJohnny = johnny; } // Paper - OBFHELPER @@ -195,7 +195,7 @@ public class Vindicator extends AbstractIllager { static class VindicatorBreakDoorGoal extends BreakDoorGoal { @@ -81,18 +72,9 @@ index dcaec42b0756cf36da813815b4a54e4d6c4e293a..53a9e4b0fda9f5a3b23a874c53d93fbe } diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 03acacd30b84452733aa2bdeed515455a1f271f8..9e535cf3293cf624b1e2e1b7fb40a446b888b099 100644 +index 6c4c5756def8eb368cbc6e9319ae6f7ddccf0499..bb3b932c57fd1e5b1517940c7602c7f4aeeaf17e 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -88,7 +88,7 @@ public class Zombie extends Monster { - public static final int REINFORCEMENT_RANGE_MAX = 40; - public static final int REINFORCEMENT_RANGE_MIN = 7; - private static final float BREAK_DOOR_CHANCE = 0.1F; -- private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { -+ public static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { // Paper - private -> public - return enumdifficulty == Difficulty.HARD; - }; - private final BreakDoorGoal breakDoorGoal; @@ -100,7 +100,7 @@ public class Zombie extends Monster { public Zombie(EntityType type, Level world) { diff --git a/patches/server/0610-EntityMoveEvent.patch b/patches/server/0610-EntityMoveEvent.patch index 95012893ed..9884943805 100644 --- a/patches/server/0610-EntityMoveEvent.patch +++ b/patches/server/0610-EntityMoveEvent.patch @@ -17,7 +17,7 @@ index 51bbb11ff8d3da95fa6d9890be3135a34b3eafac..c8213692e658f6eb82d3bd843b9525ff this.profiler.push(() -> { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index d5cfcba5e9a496deafa32f162b6ef634eae06214..103d32b360095c179e681bd354d0b9316b050339 100644 +index a988dcc693ab7f42fac39c4e4b5734ee1a1d72d4..a8576bbf964a9eab61c5b2ab7a8fba4be516b9ad 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -200,6 +200,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl @@ -29,10 +29,10 @@ index d5cfcba5e9a496deafa32f162b6ef634eae06214..103d32b360095c179e681bd354d0b931 return new Throwable(entity + " Added to world at " + new java.util.Date()); } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 19ef1b2814270b9385ea15a89dac8c2613a672ee..8c3fb37c511ada39dafdd19fa85e21a1b458386b 100644 +index a64b2043a27261cbf6b12e8185e8a91fe6ffb468..caf1607e5ed4d76469a5c8db7356e5911853c5d9 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3217,6 +3217,20 @@ public abstract class LivingEntity extends Entity { +@@ -3216,6 +3216,20 @@ public abstract class LivingEntity extends Entity { this.pushEntities(); this.level.getProfiler().pop(); diff --git a/patches/server/0645-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/patches/server/0645-Fix-PlayerItemConsumeEvent-cancelling-properly.patch index a990ea2e7b..be87e45583 100644 --- a/patches/server/0645-Fix-PlayerItemConsumeEvent-cancelling-properly.patch +++ b/patches/server/0645-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 8c3fb37c511ada39dafdd19fa85e21a1b458386b..b954fcfcf3bd3c55ca856126670fa6967d525fe3 100644 +index caf1607e5ed4d76469a5c8db7356e5911853c5d9..60a7f238c721551e00f2eb60990a5d9743a8a3a7 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3696,6 +3696,7 @@ public abstract class LivingEntity extends Entity { +@@ -3695,6 +3695,7 @@ public abstract class LivingEntity extends Entity { level.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { diff --git a/patches/server/0678-Fix-and-optimise-world-force-upgrading.patch b/patches/server/0678-Fix-and-optimise-world-force-upgrading.patch index ac027dc065..71dfea3457 100644 --- a/patches/server/0678-Fix-and-optimise-world-force-upgrading.patch +++ b/patches/server/0678-Fix-and-optimise-world-force-upgrading.patch @@ -317,10 +317,10 @@ index c820cc7f3be693f445937a157ac2477e36f906b4..ac7d3da1ca3b41e37daacb1386566761 return this.world; } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 1bee455235ece8aa299a2baeede027d251e6ff57..60ae9395591c81aebaa4be1541380a8fe921ce68 100644 +index 4ab881f0488af3577deda2f90a31a3f9243306dc..638ccec03c11f9ed9f502271b830f100899a97d7 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -29,6 +29,28 @@ public class RegionFileStorage implements AutoCloseable { // Paper - no final +@@ -29,6 +29,28 @@ public class RegionFileStorage implements AutoCloseable { } // Paper start diff --git a/patches/server/0699-Add-more-line-of-sight-methods.patch b/patches/server/0699-Add-more-line-of-sight-methods.patch index 9cf789500d..c29cb2b15d 100644 --- a/patches/server/0699-Add-more-line-of-sight-methods.patch +++ b/patches/server/0699-Add-more-line-of-sight-methods.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add more line of sight methods diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index b954fcfcf3bd3c55ca856126670fa6967d525fe3..cf7588aa282709a7b8ce6caff4aa713d54280660 100644 +index 60a7f238c721551e00f2eb60990a5d9743a8a3a7..e946981ccb07c94072f9470d1b8a00d0f9b6778b 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3424,6 +3424,7 @@ public abstract class LivingEntity extends Entity { +@@ -3423,6 +3423,7 @@ public abstract class LivingEntity extends Entity { Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); From 08fe6d3c86f5798e4929d3853b6e626fc4fc6e1b Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Wed, 16 Jun 2021 00:47:05 +0200 Subject: [PATCH 165/226] Fix a few cases of the vanilla mob goals --- patches/server/0428-Implement-Mob-Goal-API.patch | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/patches/server/0428-Implement-Mob-Goal-API.patch b/patches/server/0428-Implement-Mob-Goal-API.patch index 62f0839749..7d851a72c6 100644 --- a/patches/server/0428-Implement-Mob-Goal-API.patch +++ b/patches/server/0428-Implement-Mob-Goal-API.patch @@ -36,10 +36,10 @@ index 86cce7143abd317326cc755118bf61435e82e479..4233698d499b520dfc07c4184cefca63 diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java new file mode 100644 -index 0000000000000000000000000000000000000000..9efe7e29faf09901e8cde8713db80ceb31453412 +index 0000000000000000000000000000000000000000..dfc026d183adab1dde5942f36e7a281b3a2fc699 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -@@ -0,0 +1,463 @@ +@@ -0,0 +1,467 @@ +package com.destroystokyo.paper.entity.ai; + +import com.destroystokyo.paper.entity.RangedEntity; @@ -279,6 +279,8 @@ index 0000000000000000000000000000000000000000..9efe7e29faf09901e8cde8713db80ceb + + ignored.add("goal_selector_1"); + ignored.add("goal_selector_2"); ++ ignored.add("selector_1"); ++ ignored.add("selector_2"); + ignored.add("wrapped"); + + bukkitMap.put(net.minecraft.world.entity.Mob.class, Mob.class); @@ -396,6 +398,8 @@ index 0000000000000000000000000000000000000000..9efe7e29faf09901e8cde8713db80ceb + } + } + name = name.replace("PathfinderGoal", ""); ++ name = name.replace("TargetGoal", ""); ++ name = name.replace("Goal", ""); + StringBuilder sb = new StringBuilder(); + for (char c : name.toCharArray()) { + if (c >= 'A' && c <= 'Z') { @@ -937,7 +941,7 @@ index 130ab05393a7136020e06ec199256a031ba66091..8dd93620a770855450ed222dad6572e2 } diff --git a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java new file mode 100644 -index 0000000000000000000000000000000000000000..33597ba747c10bc9e2a89e6920f64ce5a737967e +index 0000000000000000000000000000000000000000..b2d510459bcf90a3611f3d91dae4ccc3d29b4079 --- /dev/null +++ b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java @@ -0,0 +1,105 @@ From f79ab295a53649df6a85348bfa4226e663d2067b Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Wed, 16 Jun 2021 00:59:41 +0200 Subject: [PATCH 166/226] one missed AT --- build-data/paper.at | 1 + .../server/0361-Entity-Activation-Range-2.0.patch | 13 ------------- patches/server/0428-Implement-Mob-Goal-API.patch | 2 +- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/build-data/paper.at b/build-data/paper.at index 98e0759000..76c0fda459 100644 --- a/build-data/paper.at +++ b/build-data/paper.at @@ -96,6 +96,7 @@ public net.minecraft.server.network.ServerLoginPacketListenerImpl$State # Entity Activation Range 2.0 public net.minecraft.world.entity.Entity isInsidePortal public net.minecraft.world.entity.Mob leashHolder +public net.minecraft.world.entity.LivingEntity jumping # No-Tick view distance public net.minecraft.server.level.ChunkHolder broadcast(Lnet/minecraft/network/protocol/Packet;Z)V diff --git a/patches/server/0361-Entity-Activation-Range-2.0.patch b/patches/server/0361-Entity-Activation-Range-2.0.patch index 5663d95c45..8b80bb91ae 100644 --- a/patches/server/0361-Entity-Activation-Range-2.0.patch +++ b/patches/server/0361-Entity-Activation-Range-2.0.patch @@ -157,19 +157,6 @@ index b2275c1171f52cbdf283d210c6488e974fa07d98..4ea2bea8641e08bb0350582efc8b4329 movement = this.maybeBackOffFromEdge(movement, movementType); Vec3 vec3d1 = this.collide(movement); -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 5f73418035ac1226c6b655b654367ff9cf9f0841..02609533a9c8ae70d50fa81bd0e42af6aca2ee62 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -219,7 +219,7 @@ public abstract class LivingEntity extends Entity { - protected float rotOffs; - protected int deathScore; - public float lastHurt; -- protected boolean jumping; -+ public boolean jumping; // Paper protected -> public - public float xxa; - public float yya; - public float zza; diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java index 9c208d24d6f84e8818c0a7b88cdcb7c2fd703f91..623fd2220007eec7a8e799a647e7c657aae5ee6d 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java diff --git a/patches/server/0428-Implement-Mob-Goal-API.patch b/patches/server/0428-Implement-Mob-Goal-API.patch index 7d851a72c6..93d56e3d79 100644 --- a/patches/server/0428-Implement-Mob-Goal-API.patch +++ b/patches/server/0428-Implement-Mob-Goal-API.patch @@ -941,7 +941,7 @@ index 130ab05393a7136020e06ec199256a031ba66091..8dd93620a770855450ed222dad6572e2 } diff --git a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java new file mode 100644 -index 0000000000000000000000000000000000000000..b2d510459bcf90a3611f3d91dae4ccc3d29b4079 +index 0000000000000000000000000000000000000000..35d6affcedcf324a7d2a8f8f7c0a966cef47631e --- /dev/null +++ b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java @@ -0,0 +1,105 @@ From ba2b40c60306d7c73ca1d85237cfb70c5c904d52 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Wed, 16 Jun 2021 01:24:22 +0200 Subject: [PATCH 167/226] mojang mapped vanilla goals --- patches/api/0202-Add-Mob-Goal-API.patch | 373 +++++++++++------- .../server/0428-Implement-Mob-Goal-API.patch | 6 +- 2 files changed, 228 insertions(+), 151 deletions(-) diff --git a/patches/api/0202-Add-Mob-Goal-API.patch b/patches/api/0202-Add-Mob-Goal-API.patch index 5c3c26fbaf..48c5f1eb9a 100644 --- a/patches/api/0202-Add-Mob-Goal-API.patch +++ b/patches/api/0202-Add-Mob-Goal-API.patch @@ -227,10 +227,10 @@ index 0000000000000000000000000000000000000000..e21f7574763dd4f13794f91bbef192ef +} diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java new file mode 100644 -index 0000000000000000000000000000000000000000..b42091752981a1f309ab350e9a394092cb334824 +index 0000000000000000000000000000000000000000..659193fc0596084031c09aa47fbb428a93d052e8 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java -@@ -0,0 +1,209 @@ +@@ -0,0 +1,288 @@ +package com.destroystokyo.paper.entity.ai; + +import com.destroystokyo.paper.entity.RangedEntity; @@ -244,6 +244,68 @@ index 0000000000000000000000000000000000000000..b42091752981a1f309ab350e9a394092 + */ +public interface VanillaGoal extends Goal { + ++ GoalKey AVOID_ENTITY = GoalKey.of(Creature.class, NamespacedKey.minecraft("avoid_entity")); ++ GoalKey BEG = GoalKey.of(Wolf.class, NamespacedKey.minecraft("beg")); ++ GoalKey BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("break_door")); ++ GoalKey BREATH_AIR = GoalKey.of(Creature.class, NamespacedKey.minecraft("breath_air")); ++ GoalKey BREED = GoalKey.of(Animals.class, NamespacedKey.minecraft("breed")); ++ GoalKey CAT_LIE_ON_BED = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_lie_on_bed")); ++ GoalKey CAT_SIT_ON_BLOCK = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_sit_on_block")); ++ GoalKey DOLPHIN_JUMP = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_jump")); ++ GoalKey EAT_BLOCK = GoalKey.of(Mob.class, NamespacedKey.minecraft("eat_block")); ++ GoalKey FLEE_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("flee_sun")); ++ GoalKey FLOAT = GoalKey.of(Mob.class, NamespacedKey.minecraft("float")); ++ GoalKey FOLLOW_BOAT = GoalKey.of(Creature.class, NamespacedKey.minecraft("follow_boat")); ++ GoalKey FOLLOW_FLOCK_LEADER = GoalKey.of(Fish.class, NamespacedKey.minecraft("follow_flock_leader")); ++ GoalKey FOLLOW_MOB = GoalKey.of(Mob.class, NamespacedKey.minecraft("follow_mob")); ++ GoalKey FOLLOW_OWNER = GoalKey.of(Tameable.class, NamespacedKey.minecraft("follow_owner")); ++ GoalKey FOLLOW_PARENT = GoalKey.of(Animals.class, NamespacedKey.minecraft("follow_parent")); ++ GoalKey GOLEM_RANDOM_STROLL_IN_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("golem_random_stroll_in_village")); ++ GoalKey INTERACT = GoalKey.of(Mob.class, NamespacedKey.minecraft("interact")); ++ GoalKey LAND_ON_OWNERS_SHOULDER = GoalKey.of(Parrot.class, NamespacedKey.minecraft("land_on_owners_shoulder")); ++ GoalKey LEAP_AT = GoalKey.of(Mob.class, NamespacedKey.minecraft("leap_at")); ++ GoalKey LLAMA_FOLLOW_CARAVAN = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_follow_caravan")); ++ GoalKey LOOK_AT_PLAYER = GoalKey.of(Mob.class, NamespacedKey.minecraft("look_at_player")); ++ GoalKey LOOK_AT_TRADING_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("look_at_trading_player")); ++ GoalKey MELEE_ATTACK = GoalKey.of(Creature.class, NamespacedKey.minecraft("melee_attack")); ++ GoalKey MOVE_BACK_TO_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_back_to_village")); ++ GoalKey MOVE_THROUGH_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_through_village")); ++ GoalKey MOVE_TOWARDS_RESTRICTION = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_restriction")); ++ GoalKey MOVE_TOWARDS = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards")); ++ GoalKey OCELOT_ATTACK = GoalKey.of(Mob.class, NamespacedKey.minecraft("ocelot_attack")); ++ GoalKey OFFER_FLOWER = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("offer_flower")); ++ GoalKey OPEN_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("open_door")); ++ GoalKey PANIC = GoalKey.of(Creature.class, NamespacedKey.minecraft("panic")); ++ GoalKey PATHFIND_TO_RAID = GoalKey.of(Raider.class, NamespacedKey.minecraft("pathfind_to_raid")); ++ GoalKey RANDOM_LOOK_AROUND = GoalKey.of(Mob.class, NamespacedKey.minecraft("random_look_around")); ++ GoalKey RANDOM_STROLL = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll")); ++ GoalKey RANDOM_SWIMMING = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_swimming")); ++ GoalKey RANGED_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("ranged_attack")); ++ GoalKey RANGED_BOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("ranged_bow_attack")); ++ GoalKey RANGED_CROSSBOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("ranged_crossbow_attack")); ++ GoalKey REMOVE_BLOCK = GoalKey.of(Creature.class, NamespacedKey.minecraft("remove_block")); ++ GoalKey RESTRICT_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("restrict_sun")); ++ GoalKey RUN_AROUND_LIKE_CRAZY = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("run_around_like_crazy")); ++ GoalKey SIT_WHEN_ORDERED_TO = GoalKey.of(Tameable.class, NamespacedKey.minecraft("sit_when_ordered_to")); ++ GoalKey STROLL_THROUGH_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_through_village")); ++ GoalKey SWELL = GoalKey.of(Creeper.class, NamespacedKey.minecraft("swell")); ++ GoalKey TEMPT = GoalKey.of(Creature.class, NamespacedKey.minecraft("tempt")); ++ GoalKey TRADE_WITH_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("trade_with_player")); ++ GoalKey TRY_FIND_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("try_find_water")); ++ GoalKey USE_ITEM = GoalKey.of(Mob.class, NamespacedKey.minecraft("use_item")); ++ GoalKey WATER_AVOIDING_RANDOM_FLYING = GoalKey.of(Creature.class, NamespacedKey.minecraft("water_avoiding_random_flying")); ++ GoalKey WATER_AVOIDING_RANDOM_STROLL = GoalKey.of(Creature.class, NamespacedKey.minecraft("water_avoiding_random_stroll")); ++ GoalKey ZOMBIE_ATTACK = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack")); ++ GoalKey DEFEND_VILLAGE = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("defend_village")); ++ GoalKey HURT_BY = GoalKey.of(Creature.class, NamespacedKey.minecraft("hurt_by")); ++ GoalKey NEAREST_ATTACKABLE = GoalKey.of(Mob.class, NamespacedKey.minecraft("nearest_attackable")); ++ GoalKey NEAREST_ATTACKABLE_WITCH = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_attackable_witch")); ++ GoalKey NEAREST_HEALABLE_RAIDER = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_healable_raider")); ++ GoalKey NON_TAME_RANDOM = GoalKey.of(Tameable.class, NamespacedKey.minecraft("non_tame_random")); ++ GoalKey OWNER_HURT_BY = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_by")); ++ GoalKey OWNER_HURT = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt")); ++ GoalKey RESET_UNIVERSAL_ANGER = GoalKey.of(Mob.class, NamespacedKey.minecraft("reset_universal_anger")); ++ GoalKey FISH_SWIM = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_swim")); + GoalKey BEE_ATTACK = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_attack")); + GoalKey BEE_BECOME_ANGRY = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_become_angry")); + GoalKey BEE_ENTER_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_enter_hive")); @@ -254,29 +316,14 @@ index 0000000000000000000000000000000000000000..b42091752981a1f309ab350e9a394092 + GoalKey BEE_LOCATE_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_locate_hive")); + GoalKey BEE_POLLINATE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_pollinate")); + GoalKey BEE_WANDER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_wander")); -+ GoalKey BLAZE_FIREBALL = GoalKey.of(Blaze.class, NamespacedKey.minecraft("blaze_fireball")); -+ GoalKey TEMPT_CHANCE = GoalKey.of(Cat.class, NamespacedKey.minecraft("tempt_chance")); + GoalKey CAT_AVOID_ENTITY = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_avoid_entity")); + GoalKey CAT_RELAX_ON_OWNER = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_relax_on_owner")); ++ GoalKey CAT_TEMPT = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_tempt")); + GoalKey DOLPHIN_SWIM_TO_TREASURE = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_swim_to_treasure")); + GoalKey DOLPHIN_SWIM_WITH_PLAYER = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_swim_with_player")); -+ GoalKey DOLPHIN_PLAY_WITH_ITEMS = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_play_with_items")); -+ GoalKey DROWNED_ATTACK = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack")); -+ GoalKey DROWNED_GOTO_BEACH = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_goto_beach")); -+ GoalKey DROWNED_GOTO_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("drowned_goto_water")); -+ GoalKey DROWNED_SWIM_UP = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_swim_up")); -+ GoalKey DROWNED_TRIDENT_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("drowned_trident_attack")); -+ GoalKey ENDERMAN_PICKUP_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_pickup_block")); -+ GoalKey ENDERMAN_PLACE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_place_block")); -+ GoalKey PLAYER_WHO_LOOKED_AT_TARGET = GoalKey.of(Enderman.class, NamespacedKey.minecraft("player_who_looked_at_target")); -+ GoalKey ENDERMAN_FREEZE_WHEN_LOOKED_AT = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_freeze_when_looked_at")); -+ GoalKey EVOKER_ATTACK_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_attack_spell")); -+ GoalKey EVOKER_CAST_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_cast_spell")); -+ GoalKey EVOKER_SUMMON_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_summon_spell")); -+ GoalKey EVOKER_WOLOLO_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_wololo_spell")); -+ GoalKey FISH_SWIM = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_swim")); -+ GoalKey FOX_DEFEND_TRUSTED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_defend_trusted")); -+ GoalKey FOX_FACEPLANT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_faceplant")); ++ GoalKey PLAY_WITH_ITEMS = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("play_with_items")); ++ GoalKey DEFEND_TRUSTED = GoalKey.of(Fox.class, NamespacedKey.minecraft("defend_trusted")); ++ GoalKey FACEPLANT = GoalKey.of(Fox.class, NamespacedKey.minecraft("faceplant")); + GoalKey FOX_BREED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_breed")); + GoalKey FOX_EAT_BERRIES = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_eat_berries")); + GoalKey FOX_FLOAT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_float")); @@ -284,161 +331,193 @@ index 0000000000000000000000000000000000000000..b42091752981a1f309ab350e9a394092 + GoalKey FOX_LOOK_AT_PLAYER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_look_at_player")); + GoalKey FOX_MELEE_ATTACK = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_melee_attack")); + GoalKey FOX_PANIC = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_panic")); -+ GoalKey FOX_PERCH_AND_SEARCH = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_perch_and_search")); + GoalKey FOX_POUNCE = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_pounce")); + GoalKey FOX_SEARCH_FOR_ITEMS = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_search_for_items")); -+ GoalKey FOX_SLEEP = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_sleep")); + GoalKey FOX_STROLL_THROUGH_VILLAGE = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stroll_through_village")); -+ GoalKey FOX_SEEK_SHELTER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_seek_shelter")); -+ GoalKey FOX_STALK_PREY = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stalk_prey")); -+ GoalKey GHAST_ATTACK_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_attack_target")); -+ GoalKey GHAST_IDLE_MOVE = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_idle_move")); -+ GoalKey GHAST_MOVE_TOWARDS_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_move_towards_target")); -+ GoalKey GUARDIAN_ATTACK = GoalKey.of(Guardian.class, NamespacedKey.minecraft("guardian_attack")); -+ GoalKey RAIDER_OPEN_DOOR = GoalKey.of(Illager.class, NamespacedKey.minecraft("raider_open_door")); -+ GoalKey ILLUSIONER_BLINDNESS_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_blindness_spell")); -+ GoalKey ILLUSIONER_MIRROR_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_mirror_spell")); -+ GoalKey SPELLCASTER_CAST_SPELL = GoalKey.of(Spellcaster.class, NamespacedKey.minecraft("spellcaster_cast_spell")); -+ GoalKey LLAMA_ATTACK_WOLF = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_attack_wolf")); -+ GoalKey LLAMA_HURT_BY = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_hurt_by")); -+ GoalKey LLAMATRADER_DEFENDED_WANDERING_TRADER = GoalKey.of(TraderLlama.class, NamespacedKey.minecraft("llamatrader_defended_wandering_trader")); -+ GoalKey LONG_DISTANCE_PATROL = GoalKey.of(Monster.class, NamespacedKey.minecraft("long_distance_patrol")); ++ GoalKey PERCH_AND_SEARCH = GoalKey.of(Fox.class, NamespacedKey.minecraft("perch_and_search")); ++ GoalKey SEEK_SHELTER = GoalKey.of(Fox.class, NamespacedKey.minecraft("seek_shelter")); ++ GoalKey SLEEP = GoalKey.of(Fox.class, NamespacedKey.minecraft("sleep")); ++ GoalKey STALK_PREY = GoalKey.of(Fox.class, NamespacedKey.minecraft("stalk_prey")); + GoalKey OCELOT_AVOID_ENTITY = GoalKey.of(Ocelot.class, NamespacedKey.minecraft("ocelot_avoid_entity")); + GoalKey OCELOT_TEMPT = GoalKey.of(Ocelot.class, NamespacedKey.minecraft("ocelot_tempt")); + GoalKey PANDA_ATTACK = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_attack")); + GoalKey PANDA_AVOID = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_avoid")); + GoalKey PANDA_BREED = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_breed")); -+ GoalKey PANDA_HURT_BY_TARGET = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_hurt_by_target")); ++ GoalKey PANDA_HURT_BY = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_hurt_by")); + GoalKey PANDA_LIE_ON_BACK = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_lie_on_back")); + GoalKey PANDA_LOOK_AT_PLAYER = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_look_at_player")); + GoalKey PANDA_PANIC = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_panic")); + GoalKey PANDA_ROLL = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_roll")); + GoalKey PANDA_SIT = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_sit")); + GoalKey PANDA_SNEEZE = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_sneeze")); ++ GoalKey POLAR_BEAR_ATTACK_PLAYERS = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polar_bear_attack_players")); ++ GoalKey POLAR_BEAR_HURT_BY = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polar_bear_hurt_by")); ++ GoalKey POLAR_BEAR_MELEE_ATTACK = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polar_bear_melee_attack")); ++ GoalKey POLAR_BEAR_PANIC = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polar_bear_panic")); ++ GoalKey PUFFERFISH_PUFF = GoalKey.of(PufferFish.class, NamespacedKey.minecraft("pufferfish_puff")); ++ GoalKey EVIL_RABBIT_ATTACK = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("evil_rabbit_attack")); ++ GoalKey RABBIT_AVOID_ENTITY = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_avoid_entity")); ++ GoalKey RABBIT_PANIC = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_panic")); ++ GoalKey RAID_GARDEN = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("raid_garden")); ++ GoalKey SQUID_FLEE = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid_flee")); ++ GoalKey SQUID_RANDOM_MOVEMENT = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid_random_movement")); ++ GoalKey TURTLE_BREED = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_breed")); ++ GoalKey TURTLE_GO_HOME = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_go_home")); ++ GoalKey TURTLE_GO_TO_WATER = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_go_to_water")); ++ GoalKey TURTLE_LAY_EGG = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_lay_egg")); ++ GoalKey TURTLE_PANIC = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_panic")); ++ GoalKey TURTLE_RANDOM_STROLL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_random_stroll")); ++ GoalKey TURTLE_TRAVEL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_travel")); ++ GoalKey WOLF_AVOID_ENTITY = GoalKey.of(Wolf.class, NamespacedKey.minecraft("wolf_avoid_entity")); ++ GoalKey LLAMA_ATTACK_WOLF = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_attack_wolf")); ++ GoalKey LLAMA_HURT_BY = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_hurt_by")); ++ GoalKey SKELETON_TRAP = GoalKey.of(SkeletonHorse.class, NamespacedKey.minecraft("skeleton_trap")); ++ GoalKey TRADER_LLAMA_DEFEND_WANDERING_TRADER = GoalKey.of(Llama.class, NamespacedKey.minecraft("trader_llama_defend_wandering_trader")); ++ GoalKey WITHER_DO_NOTHING = GoalKey.of(Wither.class, NamespacedKey.minecraft("wither_do_nothing")); ++ GoalKey RAIDER_OPEN_DOOR = GoalKey.of(Illager.class, NamespacedKey.minecraft("raider_open_door")); ++ GoalKey SKELETON_MELEE = GoalKey.of(Skeleton.class, NamespacedKey.minecraft("skeleton_melee")); ++ GoalKey BLAZE_ATTACK = GoalKey.of(Blaze.class, NamespacedKey.minecraft("blaze_attack")); ++ GoalKey DROWNED_ATTACK = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack")); ++ GoalKey DROWNED_GO_TO_BEACH = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_go_to_beach")); ++ GoalKey DROWNED_GO_TO_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("drowned_go_to_water")); ++ GoalKey DROWNED_SWIM_UP = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_swim_up")); ++ GoalKey DROWNED_TRIDENT_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("drowned_trident_attack")); ++ GoalKey ENDERMAN_FREEZE_WHEN_LOOKED_AT = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_freeze_when_looked_at")); ++ GoalKey ENDERMAN_LEAVE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_leave_block")); ++ GoalKey ENDERMAN_LOOK_FOR_PLAYER = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_look_for_player")); ++ GoalKey ENDERMAN_TAKE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_take_block")); ++ GoalKey EVOKER_ATTACK_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_attack_spell")); ++ GoalKey EVOKER_CASTING_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_casting_spell")); ++ GoalKey EVOKER_SUMMON_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_summon_spell")); ++ GoalKey EVOKER_WOLOLO_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_wololo_spell")); ++ GoalKey GHAST_LOOK = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_look")); ++ GoalKey GHAST_SHOOT_FIREBALL = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_shoot_fireball")); ++ GoalKey RANDOM_FLOAT_AROUND = GoalKey.of(Ghast.class, NamespacedKey.minecraft("random_float_around")); ++ GoalKey GUARDIAN_ATTACK = GoalKey.of(Guardian.class, NamespacedKey.minecraft("guardian_attack")); ++ GoalKey ILLUSIONER_BLINDNESS_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_blindness_spell")); ++ GoalKey ILLUSIONER_MIRROR_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_mirror_spell")); ++ GoalKey LONG_DISTANCE_PATROL = GoalKey.of(Monster.class, NamespacedKey.minecraft("long_distance_patrol")); + GoalKey PHANTOM_ATTACK_PLAYER = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_player")); + GoalKey PHANTOM_ATTACK_STRATEGY = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_strategy")); + GoalKey PHANTOM_CIRCLE_AROUND_ANCHOR = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_circle_around_anchor")); + GoalKey PHANTOM_SWEEP_ATTACK = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_sweep_attack")); -+ /** -+ * @deprecated removed in 1.16 -+ */ -+ @Deprecated -+ GoalKey ANGER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger")); -+ /** -+ * @deprecated removed in 1.16 -+ */ -+ @Deprecated -+ GoalKey ANGER_OTHER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger_other")); -+ GoalKey POLARBEAR_ATTACK_PLAYERS = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_attack_players")); -+ GoalKey POLARBEAR_HURT_BY = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_hurt_by")); -+ GoalKey POLARBEAR_MELEE = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_melee")); -+ GoalKey POLARBEAR_PANIC = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_panic")); -+ GoalKey PUFFERFISH_PUFF = GoalKey.of(PufferFish.class, NamespacedKey.minecraft("pufferfish_puff")); -+ GoalKey EAT_CARROTS = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("eat_carrots")); -+ GoalKey KILLER_RABBIT_MELEE_ATTACK = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("killer_rabbit_melee_attack")); -+ GoalKey RABBIT_AVOID_TARGET = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_avoid_target")); -+ GoalKey RABBIT_PANIC = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_panic")); -+ GoalKey RAIDER_HOLD_GROUND = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_hold_ground")); -+ GoalKey RAIDER_OBTAIN_BANNER = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_obtain_banner")); -+ GoalKey RAIDER_CELEBRATION = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_celebration")); -+ GoalKey RAIDER_MOVE_THROUGH_VILLAGE = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_move_through_village")); + GoalKey RAVAGER_MELEE_ATTACK = GoalKey.of(Ravager.class, NamespacedKey.minecraft("ravager_melee_attack")); + GoalKey SHULKER_ATTACK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_attack")); -+ GoalKey SHULKER_DEFENSE = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_defense")); -+ GoalKey SHULKER_NEAREST = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_nearest")); ++ GoalKey SHULKER_DEFENSE_ATTACK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_defense_attack")); ++ GoalKey SHULKER_NEAREST_ATTACK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_nearest_attack")); + GoalKey SHULKER_PEEK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_peek")); -+ GoalKey SILVERFISH_HIDE_IN_BLOCK = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_hide_in_block")); -+ GoalKey SILVERFISH_WAKE_OTHERS = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_wake_others")); -+ GoalKey SKELETON_MELEE = GoalKey.of(Skeleton.class, NamespacedKey.minecraft("skeleton_melee")); -+ GoalKey SLIME_IDLE = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_idle")); -+ GoalKey SLIME_NEAREST_PLAYER = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_nearest_player")); ++ GoalKey SILVERFISH_MERGE_WITH_STONE = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_merge_with_stone")); ++ GoalKey SILVERFISH_WAKE_UP_FRIENDS = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_wake_up_friends")); ++ GoalKey SLIME_ATTACK = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_attack")); ++ GoalKey SLIME_FLOAT = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_float")); ++ GoalKey SLIME_KEEP_ON_JUMPING = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_keep_on_jumping")); + GoalKey SLIME_RANDOM_DIRECTION = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_direction")); -+ GoalKey SLIME_RANDOM_JUMP = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_jump")); -+ GoalKey SPIDER_MELEE_ATTACK = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_melee_attack")); -+ GoalKey SPIDER_NEAREST_ATTACKABLE_TARGET = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_nearest_attackable_target")); ++ GoalKey SPELLCASTER_CASTING_SPELL = GoalKey.of(Spellcaster.class, NamespacedKey.minecraft("spellcaster_casting_spell")); ++ GoalKey SPIDER_ATTACK = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_attack")); ++ GoalKey SPIDER = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider")); + GoalKey STRIDER_GO_TO_LAVA = GoalKey.of(Strider.class, NamespacedKey.minecraft("strider_go_to_lava")); -+ GoalKey SQUID = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid")); -+ GoalKey SQUID_FLEE = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid_flee")); -+ GoalKey TURTLE_BREED = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_breed")); -+ GoalKey TURTLE_GO_HOME = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_go_home")); -+ GoalKey TURTLE_GOTO_WATER = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_goto_water")); -+ GoalKey TURTLE_LAY_EGG = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_lay_egg")); -+ GoalKey TURTLE_PANIC = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_panic")); -+ GoalKey TURTLE_RANDOM_STROLL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_random_stroll")); -+ GoalKey TURTLE_TEMPT = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_tempt")); -+ GoalKey TURTLE_TRAVEL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_travel")); + GoalKey VEX_CHARGE_ATTACK = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_charge_attack")); -+ GoalKey VEX_COPY_TARGET_OF_OWNER = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_copy_target_of_owner")); ++ GoalKey VEX_COPY_OWNER = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_copy_owner")); + GoalKey VEX_RANDOM_MOVE = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_random_move")); -+ GoalKey VILLAGERTRADER_WANDER_TO_POSITION = GoalKey.of(WanderingTrader.class, NamespacedKey.minecraft("villagertrader_wander_to_position")); + GoalKey VINDICATOR_BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("vindicator_break_door")); + GoalKey VINDICATOR_JOHNNY_ATTACK = GoalKey.of(Vindicator.class, NamespacedKey.minecraft("vindicator_johnny_attack")); + GoalKey VINDICATOR_MELEE_ATTACK = GoalKey.of(Vindicator.class, NamespacedKey.minecraft("vindicator_melee_attack")); -+ GoalKey WITHER_DO_NOTHING = GoalKey.of(Wither.class, NamespacedKey.minecraft("wither_do_nothing")); -+ GoalKey WOLF_AVOID_ENTITY = GoalKey.of(Wolf.class, NamespacedKey.minecraft("wolf_avoid_entity")); + GoalKey ZOMBIE_ATTACK_TURTLE_EGG = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack_turtle_egg")); -+ GoalKey ARROW_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("arrow_attack")); -+ GoalKey AVOID_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("avoid_target")); -+ GoalKey BEG = GoalKey.of(Wolf.class, NamespacedKey.minecraft("beg")); -+ GoalKey BOW_SHOOT = GoalKey.of(Monster.class, NamespacedKey.minecraft("bow_shoot")); -+ GoalKey BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("break_door")); -+ GoalKey BREATH = GoalKey.of(Creature.class, NamespacedKey.minecraft("breath")); -+ GoalKey BREED = GoalKey.of(Animals.class, NamespacedKey.minecraft("breed")); -+ GoalKey CAT_SIT_ON_BED = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_sit_on_bed")); -+ GoalKey CROSSBOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("crossbow_attack")); -+ GoalKey DEFEND_VILLAGE = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("defend_village")); -+ GoalKey DOOR_OPEN = GoalKey.of(Mob.class, NamespacedKey.minecraft("door_open")); -+ GoalKey EAT_TILE = GoalKey.of(Mob.class, NamespacedKey.minecraft("eat_tile")); -+ GoalKey FISH_SCHOOL = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_school")); -+ GoalKey FLEE_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("flee_sun")); -+ GoalKey FLOAT = GoalKey.of(Mob.class, NamespacedKey.minecraft("float")); -+ GoalKey FOLLOW_BOAT = GoalKey.of(Creature.class, NamespacedKey.minecraft("follow_boat")); -+ GoalKey FOLLOW_ENTITY = GoalKey.of(Mob.class, NamespacedKey.minecraft("follow_entity")); -+ GoalKey FOLLOW_OWNER = GoalKey.of(Tameable.class, NamespacedKey.minecraft("follow_owner")); -+ GoalKey FOLLOW_PARENT = GoalKey.of(Animals.class, NamespacedKey.minecraft("follow_parent")); -+ GoalKey HORSE_TRAP = GoalKey.of(SkeletonHorse.class, NamespacedKey.minecraft("horse_trap")); -+ GoalKey HURT_BY_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("hurt_by_target")); -+ GoalKey INTERACT = GoalKey.of(Mob.class, NamespacedKey.minecraft("interact")); -+ GoalKey JUMP_ON_BLOCK = GoalKey.of(Cat.class, NamespacedKey.minecraft("jump_on_block")); -+ GoalKey LEAP_AT_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("leap_at_target")); -+ GoalKey LLAMA_FOLLOW = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_follow")); -+ GoalKey LOOK_AT_PLAYER = GoalKey.of(Mob.class, NamespacedKey.minecraft("look_at_player")); -+ GoalKey LOOK_AT_TRADING_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("look_at_trading_player")); -+ GoalKey MELEE_ATTACK = GoalKey.of(Creature.class, NamespacedKey.minecraft("melee_attack")); -+ GoalKey MOVE_THROUGH_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_through_village")); -+ GoalKey MOVE_TOWARDS_RESTRICTION = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_restriction")); -+ GoalKey MOVE_TOWARDS_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_target")); -+ GoalKey NEAREST_ATTACKABLE_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("nearest_attackable_target")); -+ GoalKey NEAREST_ATTACKABLE_TARGET_WITCH = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_attackable_target_witch")); -+ GoalKey NEAREST_HEALABLE_RAIDER = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_healable_raider")); -+ GoalKey NEAREST_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("nearest_village")); -+ GoalKey OCELOT_ATTACK = GoalKey.of(Mob.class, NamespacedKey.minecraft("ocelot_attack")); -+ GoalKey OFFER_FLOWER = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("offer_flower")); -+ GoalKey OWNER_HURT_BY_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_by_target")); -+ GoalKey OWNER_HURT_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_target")); -+ GoalKey PANIC = GoalKey.of(Creature.class, NamespacedKey.minecraft("panic")); -+ GoalKey PERCH = GoalKey.of(Parrot.class, NamespacedKey.minecraft("perch")); -+ GoalKey RAID = GoalKey.of(Raider.class, NamespacedKey.minecraft("raid")); -+ GoalKey RANDOM_FLY = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_fly")); -+ GoalKey RANDOM_LOOKAROUND = GoalKey.of(Mob.class, NamespacedKey.minecraft("random_lookaround")); -+ GoalKey RANDOM_STROLL = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll")); -+ GoalKey RANDOM_STROLL_LAND = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll_land")); -+ GoalKey RANDOM_SWIM = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_swim")); -+ GoalKey RANDOM_TARGET_NON_TAMED = GoalKey.of(Tameable.class, NamespacedKey.minecraft("random_target_non_tamed")); -+ GoalKey REMOVE_BLOCK = GoalKey.of(Creature.class, NamespacedKey.minecraft("remove_block")); -+ GoalKey RESTRICT_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("restrict_sun")); -+ GoalKey SIT = GoalKey.of(Tameable.class, NamespacedKey.minecraft("sit")); -+ GoalKey STROLL_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village")); -+ GoalKey SWELL = GoalKey.of(Creeper.class, NamespacedKey.minecraft("swell")); -+ GoalKey TAME = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("tame")); -+ GoalKey TEMPT = GoalKey.of(Creature.class, NamespacedKey.minecraft("tempt")); -+ GoalKey TRADE_WITH_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("trade_with_player")); -+ GoalKey USE_ITEM = GoalKey.of(Mob.class, NamespacedKey.minecraft("use_item")); -+ GoalKey WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("water")); -+ GoalKey WATER_JUMP = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("water_jump")); -+ GoalKey ZOMBIE_ATTACK = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack")); -+ GoalKey STROLL_VILLAGE_GOLEM = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village_golem")); -+ GoalKey UNIVERSAL_ANGER_RESET = GoalKey.of(Mob.class, NamespacedKey.minecraft("universal_anger_reset")); ++ GoalKey WANDER_TO_POSITION = GoalKey.of(WanderingTrader.class, NamespacedKey.minecraft("wander_to_position")); ++ GoalKey HOLD_GROUND_ATTACK = GoalKey.of(Raider.class, NamespacedKey.minecraft("hold_ground_attack")); ++ GoalKey OBTAIN_RAID_LEADER_BANNER = GoalKey.of(Raider.class, NamespacedKey.minecraft("obtain_raid_leader_banner")); ++ GoalKey RAIDER_CELEBRATION = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_celebration")); ++ GoalKey RAIDER_MOVE_THROUGH_VILLAGE = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_move_through_village")); ++ ++ /** ++ * @deprecated removed in 1.16 ++ */ ++ @Deprecated GoalKey ANGER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger")); ++ /** ++ * @deprecated removed in 1.16 ++ */ ++ @Deprecated GoalKey ANGER_OTHER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger_other")); ++ ++ // the constants below use spigot names, they no longer work ++ @Deprecated GoalKey BLAZE_FIREBALL = GoalKey.of(Blaze.class, NamespacedKey.minecraft("blaze_fireball")); ++ @Deprecated GoalKey TEMPT_CHANCE = GoalKey.of(Cat.class, NamespacedKey.minecraft("tempt_chance")); ++ @Deprecated GoalKey DOLPHIN_PLAY_WITH_ITEMS = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_play_with_items")); ++ @Deprecated GoalKey DROWNED_GOTO_BEACH = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_goto_beach")); ++ @Deprecated GoalKey DROWNED_GOTO_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("drowned_goto_water")); ++ @Deprecated GoalKey ENDERMAN_PICKUP_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_pickup_block")); ++ @Deprecated GoalKey ENDERMAN_PLACE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_place_block")); ++ @Deprecated GoalKey PLAYER_WHO_LOOKED_AT_TARGET = GoalKey.of(Enderman.class, NamespacedKey.minecraft("player_who_looked_at_target")); ++ @Deprecated GoalKey EVOKER_CAST_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_cast_spell")); ++ @Deprecated GoalKey FOX_DEFEND_TRUSTED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_defend_trusted")); ++ @Deprecated GoalKey FOX_FACEPLANT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_faceplant")); ++ @Deprecated GoalKey FOX_PERCH_AND_SEARCH = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_perch_and_search")); ++ @Deprecated GoalKey FOX_SLEEP = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_sleep")); ++ @Deprecated GoalKey FOX_SEEK_SHELTER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_seek_shelter")); ++ @Deprecated GoalKey FOX_STALK_PREY = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stalk_prey")); ++ @Deprecated GoalKey GHAST_ATTACK_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_attack_target")); ++ @Deprecated GoalKey GHAST_IDLE_MOVE = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_idle_move")); ++ @Deprecated GoalKey GHAST_MOVE_TOWARDS_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_move_towards_target")); ++ @Deprecated GoalKey SPELLCASTER_CAST_SPELL = GoalKey.of(Spellcaster.class, NamespacedKey.minecraft("spellcaster_cast_spell")); ++ @Deprecated GoalKey LLAMATRADER_DEFENDED_WANDERING_TRADER = GoalKey.of(TraderLlama.class, NamespacedKey.minecraft("llamatrader_defended_wandering_trader")); ++ @Deprecated GoalKey PANDA_HURT_BY_TARGET = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_hurt_by_target")); ++ @Deprecated GoalKey POLARBEAR_ATTACK_PLAYERS = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_attack_players")); ++ @Deprecated GoalKey POLARBEAR_HURT_BY = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_hurt_by")); ++ @Deprecated GoalKey POLARBEAR_MELEE = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_melee")); ++ @Deprecated GoalKey POLARBEAR_PANIC = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_panic")); ++ @Deprecated GoalKey EAT_CARROTS = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("eat_carrots")); ++ @Deprecated GoalKey KILLER_RABBIT_MELEE_ATTACK = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("killer_rabbit_melee_attack")); ++ @Deprecated GoalKey RABBIT_AVOID_TARGET = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_avoid_target")); ++ @Deprecated GoalKey RAIDER_HOLD_GROUND = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_hold_ground")); ++ @Deprecated GoalKey RAIDER_OBTAIN_BANNER = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_obtain_banner")); ++ @Deprecated GoalKey SHULKER_DEFENSE = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_defense")); ++ @Deprecated GoalKey SHULKER_NEAREST = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_nearest")); ++ @Deprecated GoalKey SILVERFISH_HIDE_IN_BLOCK = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_hide_in_block")); ++ @Deprecated GoalKey SILVERFISH_WAKE_OTHERS = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_wake_others")); ++ @Deprecated GoalKey SLIME_IDLE = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_idle")); ++ @Deprecated GoalKey SLIME_NEAREST_PLAYER = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_nearest_player")); ++ @Deprecated GoalKey SLIME_RANDOM_JUMP = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_jump")); ++ @Deprecated GoalKey SPIDER_MELEE_ATTACK = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_melee_attack")); ++ @Deprecated GoalKey SPIDER_NEAREST_ATTACKABLE_TARGET = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_nearest_attackable_target")); ++ @Deprecated GoalKey SQUID = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid")); ++ @Deprecated GoalKey TURTLE_GOTO_WATER = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_goto_water")); ++ @Deprecated GoalKey TURTLE_TEMPT = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_tempt")); ++ @Deprecated GoalKey VEX_COPY_TARGET_OF_OWNER = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_copy_target_of_owner")); ++ @Deprecated GoalKey VILLAGERTRADER_WANDER_TO_POSITION = GoalKey.of(WanderingTrader.class, NamespacedKey.minecraft("villagertrader_wander_to_position")); ++ @Deprecated GoalKey ARROW_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("arrow_attack")); ++ @Deprecated GoalKey AVOID_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("avoid_target")); ++ @Deprecated GoalKey BOW_SHOOT = GoalKey.of(Monster.class, NamespacedKey.minecraft("bow_shoot")); ++ @Deprecated GoalKey BREATH = GoalKey.of(Creature.class, NamespacedKey.minecraft("breath")); ++ @Deprecated GoalKey CAT_SIT_ON_BED = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_sit_on_bed")); ++ @Deprecated GoalKey CROSSBOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("crossbow_attack")); ++ @Deprecated GoalKey DOOR_OPEN = GoalKey.of(Mob.class, NamespacedKey.minecraft("door_open")); ++ @Deprecated GoalKey EAT_TILE = GoalKey.of(Mob.class, NamespacedKey.minecraft("eat_tile")); ++ @Deprecated GoalKey FISH_SCHOOL = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_school")); ++ @Deprecated GoalKey FOLLOW_ENTITY = GoalKey.of(Mob.class, NamespacedKey.minecraft("follow_entity")); ++ @Deprecated GoalKey HORSE_TRAP = GoalKey.of(SkeletonHorse.class, NamespacedKey.minecraft("horse_trap")); ++ @Deprecated GoalKey HURT_BY_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("hurt_by_target")); ++ @Deprecated GoalKey JUMP_ON_BLOCK = GoalKey.of(Cat.class, NamespacedKey.minecraft("jump_on_block")); ++ @Deprecated GoalKey LEAP_AT_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("leap_at_target")); ++ @Deprecated GoalKey LLAMA_FOLLOW = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_follow")); ++ @Deprecated GoalKey MOVE_TOWARDS_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_target")); ++ @Deprecated GoalKey NEAREST_ATTACKABLE_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("nearest_attackable_target")); ++ @Deprecated GoalKey NEAREST_ATTACKABLE_TARGET_WITCH = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_attackable_target_witch")); ++ @Deprecated GoalKey NEAREST_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("nearest_village")); ++ @Deprecated GoalKey OWNER_HURT_BY_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_by_target")); ++ @Deprecated GoalKey OWNER_HURT_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_target")); ++ @Deprecated GoalKey PERCH = GoalKey.of(Parrot.class, NamespacedKey.minecraft("perch")); ++ @Deprecated GoalKey RAID = GoalKey.of(Raider.class, NamespacedKey.minecraft("raid")); ++ @Deprecated GoalKey RANDOM_FLY = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_fly")); ++ @Deprecated GoalKey RANDOM_LOOKAROUND = GoalKey.of(Mob.class, NamespacedKey.minecraft("random_lookaround")); ++ @Deprecated GoalKey RANDOM_STROLL_LAND = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll_land")); ++ @Deprecated GoalKey RANDOM_SWIM = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_swim")); ++ @Deprecated GoalKey RANDOM_TARGET_NON_TAMED = GoalKey.of(Tameable.class, NamespacedKey.minecraft("random_target_non_tamed")); ++ @Deprecated GoalKey SIT = GoalKey.of(Tameable.class, NamespacedKey.minecraft("sit")); ++ @Deprecated GoalKey STROLL_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village")); ++ @Deprecated GoalKey TAME = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("tame")); ++ @Deprecated GoalKey WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("water")); ++ @Deprecated GoalKey WATER_JUMP = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("water_jump")); ++ @Deprecated GoalKey STROLL_VILLAGE_GOLEM = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village_golem")); ++ @Deprecated GoalKey UNIVERSAL_ANGER_RESET = GoalKey.of(Mob.class, NamespacedKey.minecraft("universal_anger_reset")); +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java index 847ba5143660d5c56ff8f2cae2169a51b8927757..17553703d6dcb0c7852cc35b08da05075af435f2 100644 diff --git a/patches/server/0428-Implement-Mob-Goal-API.patch b/patches/server/0428-Implement-Mob-Goal-API.patch index 93d56e3d79..44b1aa853b 100644 --- a/patches/server/0428-Implement-Mob-Goal-API.patch +++ b/patches/server/0428-Implement-Mob-Goal-API.patch @@ -941,10 +941,10 @@ index 130ab05393a7136020e06ec199256a031ba66091..8dd93620a770855450ed222dad6572e2 } diff --git a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java new file mode 100644 -index 0000000000000000000000000000000000000000..35d6affcedcf324a7d2a8f8f7c0a966cef47631e +index 0000000000000000000000000000000000000000..b2d510459bcf90a3611f3d91dae4ccc3d29b4079 --- /dev/null +++ b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java -@@ -0,0 +1,105 @@ +@@ -0,0 +1,103 @@ +package com.destroystokyo.paper.entity.ai; + +import org.junit.Assert; @@ -964,7 +964,6 @@ index 0000000000000000000000000000000000000000..35d6affcedcf324a7d2a8f8f7c0a966c + +public class VanillaMobGoalTest { + -+ /* TODO: FIX THIS + @Test + public void testKeys() { + List> deprecated = new ArrayList<>(); @@ -1024,7 +1023,6 @@ index 0000000000000000000000000000000000000000..35d6affcedcf324a7d2a8f8f7c0a966c + + if (shouldFail) Assert.fail("See above"); + } -+ */ + + private static boolean hasNoEnclosingClass(Class clazz) { + return clazz.getEnclosingClass() == null || hasNoEnclosingClass(clazz.getSuperclass()); From 9501e7619fb9094ffad84e4050a747314c175f4f Mon Sep 17 00:00:00 2001 From: Jake Potrebic <15055071+Machine-Maker@users.noreply.github.com> Date: Tue, 15 Jun 2021 16:41:38 -0700 Subject: [PATCH 168/226] added remaining hunks from chat/title packets (#5844) --- patches/removed/1.17/0012-Adventure.patch | 23 ----- .../0049-Player-Tab-List-and-Title-APIs.patch | 31 ------- .../0051-Player-Tab-List-and-Title-APIs.patch | 31 ------- patches/server/0010-Adventure.patch | 92 +++++++++++++++++-- .../0048-Player-Tab-List-and-Title-APIs.patch | 56 +++++++++-- ...ble-inter-world-teleportation-safety.patch | 4 +- .../0057-Complete-resource-pack-API.patch | 6 +- ...th-absorb-values-and-repair-bad-data.patch | 4 +- ...nd-for-setting-passengers-on-players.patch | 4 +- ...86-Implement-PlayerLocaleChangeEvent.patch | 6 +- .../0121-String-based-Action-Bar-API.patch | 29 +++++- ...0-Ability-to-apply-mending-to-XP-API.patch | 4 +- .../0185-Player.setPlayerProfile-API.patch | 8 +- ...90-Flag-to-disable-the-channel-limit.patch | 4 +- .../0219-InventoryCloseEvent-Reason-API.patch | 10 +- ...e-attack-cooldown-methods-for-Player.patch | 4 +- .../server/0262-Improve-death-events.patch | 6 +- ...-replace-OfflinePlayer-getLastPlayed.patch | 8 +- ...-remove-from-being-called-on-Players.patch | 4 +- ...-Implement-Player-Client-Options-API.patch | 4 +- ...k-Priority-Urgency-System-for-Chunks.patch | 4 +- patches/server/0499-Brand-support.patch | 4 +- .../server/0535-Player-elytra-boost-API.patch | 4 +- ...r-spawnParticle-x-y-z-precision-loss.patch | 4 +- patches/server/0592-Add-sendOpLevel-API.patch | 4 +- .../server/0620-Expose-Tracked-Players.patch | 4 +- ...ditions-to-PlayerGameModeChangeEvent.patch | 4 +- .../0688-Add-PlayerKickEvent-causes.patch | 4 +- 28 files changed, 212 insertions(+), 158 deletions(-) delete mode 100644 patches/removed/1.17/0012-Adventure.patch delete mode 100644 patches/removed/1.17/0049-Player-Tab-List-and-Title-APIs.patch delete mode 100644 patches/removed/1.17/0051-Player-Tab-List-and-Title-APIs.patch diff --git a/patches/removed/1.17/0012-Adventure.patch b/patches/removed/1.17/0012-Adventure.patch deleted file mode 100644 index d0d6c9d6b6..0000000000 --- a/patches/removed/1.17/0012-Adventure.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -index 915120cc505c70153f7b70f07d8d42c13eb77ea7..69ff8df7340e60c476803256750a48f0b43414d3 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -@@ -10,6 +10,7 @@ public class ClientboundSetTitlesPacket implements Packet { - } - - } -+ // Paper start -+ public net.md_5.bungee.api.chat.BaseComponent[] components; -+ -+ public PacketPlayOutTitle(EnumTitleAction action, net.md_5.bungee.api.chat.BaseComponent[] components, int fadeIn, int stay, int fadeOut) { -+ this.a = action; -+ this.components = components; -+ this.c = fadeIn; -+ this.d = stay; -+ this.e = fadeOut; -+ } -+ // Paper end - - @Override - public void b(PacketDataSerializer packetdataserializer) throws IOException { -@@ -55,6 +66,8 @@ public class PacketPlayOutTitle implements Packet { - // Paper start - if (this.adventure$text != null) { - packetdataserializer.writeComponent(this.adventure$text); -+ } else if (this.components != null) { -+ packetdataserializer.writeComponent(this.components); - } else - // Paper end - packetdataserializer.a(this.b); diff --git a/patches/removed/1.17/0051-Player-Tab-List-and-Title-APIs.patch b/patches/removed/1.17/0051-Player-Tab-List-and-Title-APIs.patch deleted file mode 100644 index 3ad1a77c63..0000000000 --- a/patches/removed/1.17/0051-Player-Tab-List-and-Title-APIs.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -index 69ff8df7340e60c476803256750a48f0b43414d3..df444daeb181ff78170f7b92bd02f1f1862dfa2e 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitlesPacket.java -@@ -47,6 +47,17 @@ public class ClientboundSetTitlesPacket implements Packet { + private final Component text; ++ public net.kyori.adventure.text.Component adventure$text; // Paper + + public ClientboundSetActionBarTextPacket(Component message) { + this.text = message; +@@ -17,6 +18,11 @@ public class ClientboundSetActionBarTextPacket implements Packet { + private final Component text; ++ public net.kyori.adventure.text.Component adventure$text; // Paper + + public ClientboundSetSubtitleTextPacket(Component subtitle) { + this.text = subtitle; +@@ -17,6 +18,11 @@ public class ClientboundSetSubtitleTextPacket implements Packet { + private final Component text; ++ public net.kyori.adventure.text.Component adventure$text; // Paper + + public ClientboundSetTitleTextPacket(Component title) { + this.text = title; +@@ -17,6 +18,11 @@ public class ClientboundSetTitleTextPacket implements Packet { + private final Component text; + public net.kyori.adventure.text.Component adventure$text; // Paper ++ public net.md_5.bungee.api.chat.BaseComponent[] components; // Paper + + public ClientboundSetSubtitleTextPacket(Component subtitle) { + this.text = subtitle; +@@ -21,6 +22,8 @@ public class ClientboundSetSubtitleTextPacket implements Packet { + private final Component text; + public net.kyori.adventure.text.Component adventure$text; // Paper ++ public net.md_5.bungee.api.chat.BaseComponent[] components; // Paper + + public ClientboundSetTitleTextPacket(Component title) { + this.text = title; +@@ -21,6 +22,8 @@ public class ClientboundSetTitleTextPacket implements Packet { + private final Component text; + public net.kyori.adventure.text.Component adventure$text; // Paper ++ public net.md_5.bungee.api.chat.BaseComponent[] components; // Paper + + public ClientboundSetActionBarTextPacket(Component message) { + this.text = message; +@@ -21,6 +22,8 @@ public class ClientboundSetActionBarTextPacket implements Packet